[
  {
    "path": ".editorconfig",
    "content": "﻿## \n## PROJECT:    Mouri Internal Library Essentials\n## FILE:       .editorconfig\n## PURPOSE:    The root .editorconfig file\n## \n## LICENSE:    The MIT License\n## \n## MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n## \n\nroot = true\n\n[*]\ncharset = utf-8-bom\nend_of_line = crlf\n\n[*.md]\ninsert_final_newline = true\n\n[*.{c,c++,cc,cpp,cxx,h,h++,hh,hpp,hxx,ixx,cppm,ipp,odl,idl,inl,ipp,tlh,tli}]\nindent_style = space\nindent_size = 4\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nvc_generate_documentation_comments = doxygen_slash_star\ncpp_new_line_before_open_brace_function = new_line\ncpp_new_line_before_open_brace_block = new_line\ncpp_new_line_before_open_brace_lambda = new_line\ncpp_new_line_before_open_brace_type = new_line\ncpp_new_line_before_open_brace_namespace = new_line\ncpp_new_line_close_brace_same_line_empty_type = false\ncpp_new_line_close_brace_same_line_empty_function = false\ncpp_new_line_before_else = true\ncpp_new_line_before_catch = true\ncpp_new_line_before_while_in_do_while = true\ncpp_naming_rule.general_names.symbols = all_symbols\ncpp_naming_rule.general_names.style = mile_project_cpp\ncpp_naming_symbols.all_symbols.applicable_kinds = *\ncpp_naming_style.mile_project_cpp.capitalization = pascal_case\n\n[*.{cs,csx,vb,vbx,asmx}]\nindent_style = space\nindent_size = 4\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.{js,json,xml,toml,xaml}]\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.rc]\ncharset = utf-16le\n\n[*.inf]\ncharset = utf-16le\n\n[*.bat]\ncharset = utf-8\ninsert_final_newline = true\n\n[*.sh]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\n\n[*.{asm,inc,s,nasm}]\ncharset = utf-8\nindent_style = space\nindent_size = 4\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "custom: [\n  \"https://github.com/M2Team/NanaZip/blob/main/Documents/SponsorEdition.md\"\n]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug report\ndescription: Something isn't working as expected.\nlabels: [\"bug\"]\nbody:\n  - type: checkboxes\n    attributes:\n      label: Prerequisite checks\n      description: These items are required before submitting the bug report.\n      options:\n      - label: My system fulfills [the minimum software requirements](https://github.com/M2Team/NanaZip?tab=readme-ov-file#system-requirements).\n        required: true\n      - label: I have downloaded NanaZip from an official source (GitHub, Microsoft Store, My Digital Life Forums, SourceForge, and Windows App Community)\n        required: true\n  - type: textarea\n    attributes:\n      label: Describe the issue\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Reproduction steps\n      description: What steps did you take for this bug to happen?\n      placeholder: |\n        1.\n        2.\n        3.\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Expected behavior\n      description: What did you expect this feature to do?\n    validations:\n      required: true\n  - type: input\n    attributes:\n      label: NanaZip veresion\n      description: What version of NanaZip are you using?\n    validations:\n      required: true\n  - type: input\n    attributes:\n      label: Windows version\n      description: What version of Windows are you using?\n      placeholder: Windows 11, version 25H2; Windows 11 Insider build xxxxx\n    validations:\n      required: true\n  - type: textarea\n    attributes:\n      label: Additional context\n      description: Any other information related to this bug that you want to tell us.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: Report a security vulnerability\n    url: https://github.com/M2Team/NanaZip/security/advisories/new\n    about: Don't open a GitHub issue to report a vulnerability. Please create a new security advisory instead.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "﻿name: Feature request\ndescription: Request a new feature into NanaZip.\nlabels: [\"enhancement\"]\nbody:\n  - type: textarea\n    attributes:\n      label: Describe the feature\n    validations:\n      required: true\n  - type: checkboxes\n    attributes:\n      label: Prerequisite checks\n      options:\n        - label: I have confirmed that this feature isn't yet implemented in the latest Preview release.\n          required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "﻿<!---\n  Read https://github.com/M2Team/NanaZip/blob/main/CONTRIBUTING.md word by word\n  first. For security fix PRs, also need to read\n  https://github.com/M2Team/NanaZip/blob/main/Security.md.\n-->\n"
  },
  {
    "path": ".github/dco.yml",
    "content": "﻿allowRemediationCommits:\n  individual: true\n  thirdParty: true\nrequire:\n  members: true\n"
  },
  {
    "path": ".github/workflows/BuildBinaries.yml",
    "content": "﻿name: Build Binaries\n\non:\n  push:\n    paths-ignore:\n      - 'Documents/**'\n      - '**/*.md'\n  pull_request:\n    paths-ignore:\n      - 'Documents/**'\n      - '**/*.md'\n\njobs:\n  build:\n    runs-on: windows-latest\n    env:\n      POWERSHELL_TELEMETRY_OPTOUT: 1\n    steps:\n    - uses: actions/checkout@v4\n      with:\n        submodules: 'recursive'\n    - uses: microsoft/setup-msbuild@v2\n    - name: Clear local NuGet cache (workaround for failed restores on windows-latest)\n      run: dotnet nuget locals all --clear\n    - name: Build\n      run: MSBuild -binaryLogger:Output\\BuildAllTargets.binlog -m BuildAllTargets.proj\n    - name: Upload MSIX Bundle\n      uses: actions/upload-artifact@v4\n      with:\n        name: NanaZip_Mainline_ApplicationPackages\n        path: Output/Binaries/AppPackages\n    - name: Upload Extension Package Installer\n      uses: actions/upload-artifact@v4\n      with:\n        name: NanaZip_Mainline_ExtensionPackageInstaller\n        path: Output/NanaZip.ExtensionPackage_*.exe\n    - name: Upload MSBuild Build Process Binary Log\n      uses: actions/upload-artifact@v4\n      if: '!cancelled()'\n      with:\n        name: NanaZip_Mainline_BuildBinaryLog\n        path: Output/BuildAllTargets.binlog\n    - name: Upload Portable Binaries\n      uses: actions/upload-artifact@v4\n      with:\n        name: NanaZip_Mainline_PortableBinaries\n        path: Output/Binaries/Root/Binaries\n    - name: Upload Debug Symbols\n      uses: actions/upload-artifact@v4\n      with:\n        name: NanaZip_Mainline_DebugSymbols\n        path: Output/Binaries/Root/Symbols\n"
  },
  {
    "path": ".github/workflows/UpdatePrecompiledBuildTools.yml",
    "content": "﻿name: Update Precompiled Build Tools\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - 'NanaZip.Build.Tasks/**'\n      - '.github/workflows/UpdatePrecompiledBuildTools.yml'\n\njobs:\n  build:\n    runs-on: windows-latest\n    env:\n      POWERSHELL_TELEMETRY_OPTOUT: 1\n    steps:\n    - uses: actions/checkout@v4\n      with:\n        submodules: 'recursive'\n    - uses: microsoft/setup-msbuild@v2\n    - name: Clear local NuGet cache (workaround for failed restores on windows-latest)\n      run: dotnet nuget locals all --clear\n    - name: Configure the git commit information\n      run: |\n        git config --local user.email \"41898282+github-actions[bot]@users.noreply.github.com\"\n        git config --local user.name \"github-actions[bot]\"\n    - name: Refresh the build number\n      run: |\n        MSBuild -target:RefreshVersion BuildAllTargets.proj\n        git commit -a -m \"Refresh the build number for the precompiled build tools.\"\n    - name: Prepare the compiled build tools binaries\n      run: |\n        dotnet build --configuration Release NanaZip.Build.Tasks\\NanaZip.Build.Tasks.csproj\n        git commit -a -m \"Update the precompiled build tools.\"\n    - name: Push changes to the repository\n      run: |\n        git checkout -b unstaged/update-precompiled-build-tools\n        git push origin unstaged/update-precompiled-build-tools --force\n        "
  },
  {
    "path": ".github/workflows/UpdateWebsite.yml",
    "content": "﻿name: Update Website\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - 'Documents/Website/**'\n      - '.github/workflows/UpdateWebsite.yml'\n\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\nconcurrency:\n  group: \"pages\"\n  cancel-in-progress: false\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v6\n      - name: Build and upload website\n        uses: withastro/action@v5\n        with:\n          path: ./Documents/Website\n  \n  deploy:\n    needs: build\n    runs-on: ubuntu-latest\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4"
  },
  {
    "path": ".gitignore",
    "content": "## \n## PROJECT:    Mouri Internal Library Essentials\n## FILE:       .gitignore\n## PURPOSE:    The root .gitignore file for Visual Studio C++ Project\n## \n## LICENSE:    The MIT License\n## \n## MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n## \n\n##\n## Ignore Mile.Project specific temporary files, build results,\n## and files generated by popular Visual Studio add-ons.\n## \nOutput/\n\n##\n## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.tlog\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio 6 auto-generated project file (contains which files were open etc.)\n*.vbp\n\n# Visual Studio 6 workspace and project file (working project files containing files to include in project)\n*.dsw\n*.dsp\n\n# Visual Studio 6 technical files\n*.ncb\n*.aps\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\nMSBuild_Logs/\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# Visual Studio History (VSHistory) files\n.vshistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n# VS Code files for those working on multiple tools\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n*.code-workspace\n\n# Local History for Visual Studio Code\n.history/\n\n# Windows Installer files from build outputs\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# JetBrains Rider\n*.sln.iml\n"
  },
  {
    "path": "BuildAllTargets.cmd",
    "content": "@setlocal\n@echo off\n\nrem Change to the current folder.\ncd \"%~dp0\"\n\nrem Remove the output folder for a fresh compile.\nrd /s /q Output\n\nrem Initialize Visual Studio environment\nset VisualStudioInstallerFolder=\"%ProgramFiles(x86)%\\Microsoft Visual Studio\\Installer\"\nif %PROCESSOR_ARCHITECTURE%==x86 set VisualStudioInstallerFolder=\"%ProgramFiles%\\Microsoft Visual Studio\\Installer\"\npushd %VisualStudioInstallerFolder%\nfor /f \"usebackq tokens=*\" %%i in (`vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do (\n  set VisualStudioInstallDir=%%i\n)\npopd\ncall \"%VisualStudioInstallDir%\\VC\\Auxiliary\\Build\\vcvarsall.bat\" x86\n\nrem Build all targets\nMSBuild -binaryLogger:Output\\BuildAllTargets.binlog -m BuildAllTargets.proj\n\n@endlocal"
  },
  {
    "path": "BuildAllTargets.proj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project \n  DefaultTargets=\"RefreshVersion;Restore;Build;Packaging\"\n  xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"NanaZip.Project\\NanaZip.Project.props\" />\n  <UsingTask\n    TaskName=\"NanaZip.Build.Tasks.RefreshAppxManifestVersion\"\n    AssemblyFile=\"$(MSBuildThisFileDirectory)NanaZip.Project\\NanaZip.Build.Tasks.dll\"/>\n  <UsingTask\n    TaskName=\"NanaZip.Build.Tasks.RefreshProjectBuildNumberDate\"\n    AssemblyFile=\"$(MSBuildThisFileDirectory)NanaZip.Project\\NanaZip.Build.Tasks.dll\"/>\n  <Target Name=\"RefreshVersion\">\n    <Exec Command=\"git show -s --format=%25%25cs\" ConsoleToMSBuild=\"true\" IgnoreExitCode=\"true\">\n      <Output TaskParameter=\"ExitCode\" PropertyName=\"GitExitCode\" />\n      <Output TaskParameter=\"ConsoleOutput\" PropertyName=\"GitBuildNumberDate\" />\n    </Exec>\n    <PropertyGroup>\n      <NanaZipBuildNumberDate Condition=\"'$(GitExitCode)' == '0' and '$(GitBuildNumberDate)' != ''\">$(GitBuildNumberDate)</NanaZipBuildNumberDate>\n    </PropertyGroup>\n    <RefreshProjectBuildNumberDate\n      FilePath=\"$(MSBuildThisFileDirectory)NanaZip.Project\\NanaZip.Project.Version.props\"\n      BuildNumberDate=\"$(NanaZipBuildNumberDate)\" />\n    <PropertyGroup>\n      <MileProjectVersion>$(NanaZipMajorVersion).$(NanaZipMinorVersion).$([System.DateTime]::Parse('$(NanaZipBuildNumberDate)').Subtract($([System.DateTime]::Parse('$(NanaZipProjectCreationDate)'))).TotalDays).0</MileProjectVersion>\n    </PropertyGroup>\n    <RefreshAppxManifestVersion\n      FilePath=\"$(MSBuildThisFileDirectory)NanaZipPackage\\Package.appxmanifest\"\n      Version=\"$(MileProjectVersion)\" />\n  </Target>\n  <Target Name=\"Restore\">\n    <ItemGroup>\n      <RestoreProjectReference Include=\"$(MSBuildThisFileDirectory)NanaZip.slnx\">\n        <AdditionalProperties>Configuration=Debug;Platform=x64</AdditionalProperties>   \n      </RestoreProjectReference>\n      <RestoreProjectReference Include=\"$(MSBuildThisFileDirectory)NanaZip.slnx\">\n        <AdditionalProperties>Configuration=Release;Platform=x64</AdditionalProperties>   \n      </RestoreProjectReference>\n      <RestoreProjectReference Include=\"$(MSBuildThisFileDirectory)NanaZip.ExtensionPackage\\NanaZip.ExtensionPackage.Installer.proj\">\n        <AdditionalProperties>Configuration=Release</AdditionalProperties>\n      </RestoreProjectReference>\n    </ItemGroup>\n    <MSBuild\n      Projects=\"@(RestoreProjectReference)\"\n      Targets=\"Restore\"\n      StopOnFirstFailure=\"True\"\n      Properties=\"PreferredToolArchitecture=x64\" />\n  </Target>\n  <Target Name=\"Build\">\n    <MSBuild\n      Projects=\"$(MSBuildThisFileDirectory)NanaZipPackage\\NanaZipPackage.wapproj\"\n      Targets=\"Build\"\n      BuildInParallel=\"True\"\n      StopOnFirstFailure=\"True\"\n      Properties=\"PreferredToolArchitecture=x64;Configuration=Debug;Platform=x64\" />\n    <MSBuild\n      Projects=\"$(MSBuildThisFileDirectory)NanaZipPackage\\NanaZipPackage.wapproj\"\n      Targets=\"Build\"\n      BuildInParallel=\"True\"\n      StopOnFirstFailure=\"True\"\n      Properties=\"PreferredToolArchitecture=x64;Configuration=Release;Platform=x64\" />\n    <MSBuild\n      Projects=\"$(MSBuildThisFileDirectory)NanaZip.ExtensionPackage\\NanaZip.ExtensionPackage.Installer.proj\"\n      Targets=\"Build\"\n      BuildInParallel=\"True\"\n      StopOnFirstFailure=\"True\"\n      Properties=\"Configuration=Release\" />\n  </Target>\n  <Target Name=\"Packaging\">\n    <PropertyGroup>\n      <InputBinariesPath>$(MSBuildThisFileDirectory)Output\\Binaries\\Release\\</InputBinariesPath>\n      <OutputBinariesPath>$(MSBuildThisFileDirectory)Output\\Binaries\\Root\\Binaries\\</OutputBinariesPath>\n      <OutputSymbolsPath>$(MSBuildThisFileDirectory)Output\\Binaries\\Root\\Symbols\\</OutputSymbolsPath>\n      <OutputFileNamePrefix>NanaZip_$(MileProjectVersion)</OutputFileNamePrefix>\n    </PropertyGroup>\n\n    <MakeDir Directories=\"$(OutputSymbolsPath)arm64\" />\n    <MakeDir Directories=\"$(OutputSymbolsPath)x64\" />\n\n    <Copy SourceFiles=\"$(MSBuildThisFileDirectory)License.md\" DestinationFiles=\"$(OutputBinariesPath)License.txt\" />\n    <Copy SourceFiles=\"$(MSBuildThisFileDirectory)ReadMe.md\" DestinationFiles=\"$(OutputBinariesPath)ReadMe.txt\" />\n    <Copy SourceFiles=\"$(MSBuildThisFileDirectory)Documents\\People.md\" DestinationFiles=\"$(OutputBinariesPath)People.txt\" />\n    <Copy SourceFiles=\"$(MSBuildThisFileDirectory)Documents\\Policies.md\" DestinationFiles=\"$(OutputBinariesPath)Policies.txt\" />\n    <Copy SourceFiles=\"$(MSBuildThisFileDirectory)Documents\\ReleaseNotes.md\" DestinationFiles=\"$(OutputBinariesPath)ReleaseNotes.txt\" />\n    <Copy SourceFiles=\"$(MSBuildThisFileDirectory)Documents\\ReleaseNotesPreview.md\" DestinationFiles=\"$(OutputBinariesPath)ReleaseNotesPreview.txt\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\K7Base.dll\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\K7User.dll\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Codecs.dll\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Core.dll\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Core.Console.sfx\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Core.Windows.sfx\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Modern.dll\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Universal.Console.exe\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Universal.Windows.exe\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\Mile.Xaml.Styles.SunValley.xbf\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\resources.pri\" DestinationFolder=\"$(OutputBinariesPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\K7Base.dll\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\K7User.dll\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Codecs.dll\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Core.dll\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Core.Console.sfx\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Core.Windows.sfx\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Modern.dll\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Universal.Console.exe\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Universal.Windows.exe\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\Mile.Xaml.Styles.SunValley.xbf\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\resources.pri\" DestinationFolder=\"$(OutputBinariesPath)x64\" />\n\n    <Copy SourceFiles=\"$(MSBuildThisFileDirectory)License.md\" DestinationFiles=\"$(OutputSymbolsPath)License.txt\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\K7Base.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\K7User.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Codecs.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Core.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Core.Console.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Core.Windows.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Modern.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Universal.Console.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Universal.Windows.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.Modern.FileManager.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\arm64\\NanaZip.ShellExtension.pdb\" DestinationFolder=\"$(OutputSymbolsPath)arm64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\K7Base.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\K7User.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Codecs.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Core.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Core.Console.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Core.Windows.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Modern.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Universal.Console.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Universal.Windows.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Modern.FileManager.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n    <Copy SourceFiles=\"$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.ShellExtension.pdb\" DestinationFolder=\"$(OutputSymbolsPath)x64\" />\n\n    <Exec Command=\"&quot;$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Universal.Console.exe&quot; a -r .\\Output\\$(OutputFileNamePrefix)_Binaries.zip .\\Output\\Binaries\\Root\\Binaries\\*.*\" WorkingDirectory=\"$(MSBuildThisFileDirectory)\"/>\n    <Exec Command=\"&quot;$(InputBinariesPath)NanaZipPackage\\x64\\NanaZip.Universal.Console.exe&quot; a -r .\\Output\\$(OutputFileNamePrefix)_DebugSymbols.zip .\\Output\\Binaries\\Root\\Symbols\\*.*\" WorkingDirectory=\"$(MSBuildThisFileDirectory)\"/>\n  </Target>\n</Project>"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "﻿# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, \nbody size, disability, ethnicity, sex characteristics, gender identity and \nexpression, level of experience, education, socio-economic status, nationality,\npersonal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an \nappointed representative at an online or offline event. Representation of \nproject may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at Kenji.Mouri@outlook.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an \nincident. Further details of specific enforcement policies may be posted \nseparately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 1.4, available at\nhttps://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "﻿# Contributing to NanaZip\n\n## How to become a contributor\n\n- Direct contributions\n  - We use a code style similar but not identical to that of Windows NT kernel\n    drivers. You must read the code style guidelines carefully, word by word,\n    before submitting your pull request. To maintain NanaZip's source code\n    quality, and to respect our reviewers' time, we will not accept PRs that\n    don't follow these guidelines.\n  - We expect all contributions to match our existing style WITHOUT EXCEPTION.\n    If you have any questions about our coding standards, please open an issue\n    for discussion before submitting your pull request.\n  - By submitting a pull request, you agree to license your contribution under\n    the MIT license. We reserve the right to reuse and rewrite contributors' PRs\n    as needed.\n  - You are forbidden to modify any content in any files and folders starting\n    with the \"Mile.\" prefix because those implementations are shared across many\n    projects, or your pull request will not be merged and will be closed\n    immediately, unless you get the permission from Kenji Mouri.\n  - It's OK to use AI/LLM tools to help you write code, but you must ensure that\n    the final commit is written and reviewed by yourself, following our coding\n    style and conventions. If we find that your pull request has no contribution\n    from you, or the contribution is not reviewed by you, your pull request will\n    not be merged and will be closed immediately.\n- Feedback suggestions and bugs.\n  - We use GitHub issues to track bugs and features.\n  - For bugs and general issues please \n    [file a new issue](https://github.com/M2Team/NanaZip/issues/new).\n\n## Code contribution guidelines\n\n### Prerequisites\n\n- Visual Studio 2022 or later.\n  - You also need install ARM64 components (MSVC Toolchain and ATL/MFC) if you\n    want to compile the ARM64 version of NanaZip.\n- Windows 11 SDK or later.\n  - You also need to install ARM64 components if you want to compile the ARM64\n    version of NanaZip.\n\n### How to build all targets of NanaZip\n\nRun `BuildAllTargets.bat` in the root of the repository.\n\n### How to modify or debugging NanaZip\n\nRecommend to run `RestoreNuGetPackages.cmd` in the root of the repository to\nrestore NuGet packages if you have not run this script or `BuildAllTargets.bat`\nbefore. (Recent versions of Visual Studio 2026 has some issues to restore NuGet\npackages automatically.)\n\nOpen `NanaZip.slnx` in the root of the repository.\n\n### Code style and conventions\n\nRead Kenji Mouri's [MD24: The coding style for all my open-source projects] for\nmore information.\n\n[MD24: The coding style for all my open-source projects]: https://github.com/MouriNaruto/MouriDocs/tree/main/docs/24\n\nFor all languages respect the [.editorconfig](https://editorconfig.org/) file \nspecified in the source tree. Many IDEs natively support this or can with a \nplugin.\n\n#### Modifications for inherited 7-Zip mainline source code\n\n> [!NOTE]\n> Read https://github.com/M2Team/NanaZip/blob/main/License.md first for knowing\n> which files whether belong to inherited 7-Zip mainline source code.**\n\n> [!NOTE]\n> For adding something to inherited 7-Zip code, don't add extra empty line if\n> there is no empty line in the existed inherited 7-Zip methods and functions.\n\nFor simplifying the synchronization from 7-Zip mainline, the modification mark\nis necessary, which the original 7-Zip mainline code should be commented as\noriginal, Here is the format:\n\n```\n// **************** NanaZip Modification Start **************** \n// xzProps.numTotalThreads = (int)(prop.ulVal); \nxzProps.numTotalThreads = ((int)prop.ulVal) > 1 ? (int)prop.ulVal : 1; \n// **************** NanaZip Modification End **************** \n```\n\nFor multiple lines, you can also use the following format:\n\n```\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\nkBZip2 = 12,\n\nkLZMA = 14,\n\nkTerse = 18,\nkLz77 = 19,\nkZstdPk = 20,\n\nkZstdWz = 93,\nkMP3 = 94,\nkXz = 95,\nkJpeg = 96,\nkWavPack = 97,\nkPPMd = 98,\nkWzAES = 99\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\nkBZip2 = 12,   // File is compressed using BZIP2 algorithm\n\nkLZMA = 14,    // LZMA\n\nkTerse = 18,   // File is compressed using IBM TERSE (new)\nkLz77 = 19,    // IBM LZ77 z Architecture\nkZstdPk = 20,  // deprecated (use method 93 for zstd)\n\nkZstd = 93,    // Zstandard (zstd) Compression\nkMP3 = 94,     // MP3 Compression\nkXz = 95,      // XZ Compression\nkJpeg = 96,    // JPEG variant\nkWavPack = 97, // WavPack compressed data\nkPPMd = 98,    // PPMd version I, Rev 1\nkWzAES = 99    // AE-x encryption marker (see APPENDIX E)\n// **************** 7-Zip ZS Modification End ****************\n```\n\n#### Translation contribution notice\n\nAll `comment` in `resw` files should be kept English to make it better for \nmaintenance in the future.\n"
  },
  {
    "path": "Directory.Build.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project>\n  <PropertyGroup>\n    <MileProjectOutputPath>$(MSBuildThisFileDirectory)Output\\</MileProjectOutputPath>\n  </PropertyGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Build.props\" />\n</Project>"
  },
  {
    "path": "Documents/ChannelSwitchNote.md",
    "content": "﻿# Channel Switch Note for NanaZip development\n\nP.S. Only for Kenji Mouri\n\n## Preview\n\n- DisplayName=\"NanaZip Preview\"\n- Name=\"40174MouriNaruto.NanaZipPreview\"\n- <DisplayName>NanaZip Preview</DisplayName>\n- 469D94E9-6AF4-4395-B396-99B1308F8CE5\n- return ::SHStrDupW(L\"NanaZip Preview\", ppszName);\n\n## Stable\n\n- DisplayName=\"NanaZip\"\n- Name=\"40174MouriNaruto.NanaZip\"\n- <DisplayName>NanaZip</DisplayName>\n- CAE3F1D4-7765-4D98-A060-52CD14D56EAB\n- return ::SHStrDupW(L\"NanaZip\", ppszName);\n"
  },
  {
    "path": "Documents/DevelopmentRoadmapArchived.md",
    "content": "﻿# Development Roadmap (Archived)\n\nThese will be migrated to the new roadmap issue in the future.\n\n- Blue Moon (3.x) Series (Before 2024 Q3)\n  - [ ] Continue to modernize the UI with XAML Islands with the Windows 11 \n        control style, dark and light mode support.\n  - [ ] Full Accessibility support in all UI components.\n  - [ ] Migrate configurations from registry to json. (Suggested by \n        AndromedaMelody.)\n  - [ ] Continue to modernize the core implementation.\n  - [ ] Try to Windows Runtime component for interoperability.\n  - [ ] Provide NanaZip Installer for simplify the deployment.\n  - [ ] Try to add option for save file names with UTF-8 in 7z archives.\n  - [ ] Add batch task support. (Suggested by 刘泪.)\n  - [ ] Try to design the new UI layout. (Suggested by wangwenx190.)\n  - [ ] Try to add option for using Windows Imaging API (WIMGAPI) backend to \n        make better creation and extraction support for wim archives, also add \n        creation and extraction support for esd archives.\n  - [ ] Try to add pri archive extracting support.\n  - [ ] Try to add smart extraction.\n  - [ ] Try to add language encoding switching support for file names in File\n        Manager. (Suggested by 刘泪 and zjkmxy.)\n  - [ ] Try to add deleting source after archiving support. (Suggested by \n        OrionGrant.)\n  - [ ] Try to add an option when extracting an archive to open the folder \n        where you extracted the files, like WinRAR. (Suggested by maicol07.)\n  - [ ] Try to add ISO creation support.\n- Sherlock Holmes (5.x) Series (Before 2025 Q3)\n  - Currently no new feature plans for this series.\n- Unpredictable Future Series (T.B.D.)\n  - [ ] Try to create a new archive file format optimized for software \n        distribution and image backup and restore.\n    - [ ] Keeping metadata provided by file system.\n    - [ ] File referencing support.\n    - [ ] Integrity verification support.\n    - [ ] Differential support.\n    - [ ] Recovery record support.\n    - [ ] Provide lightweight SDK for authoring and consuming.\n  - [ ] Try to contribute recovery record support for 7z archives to 7-Zip \n        mainline. (Suggested by SakuraNeko.)\n  - [ ] Try to port NanaZip to Linux.\n    - [ ] Try to port MegaUI (an developing lightweight UI framework created by\n          mingkuang, under internal developing at the current stage, will be \n          open source if the work has done) framework to Linux.\n    - [ ] Try to create MinLin (a.k.a. Minimum Linux, a distro intended for \n          helping publish distroless binaries and provide some Windows API \n          functions as static libraries for having a lightweight platform \n          abstraction layer) project because I think NanaZip should support\n          distroless environment for reducing time wasting for compiling for\n          different distros.\n  - [ ] After porting NanaZip to Linux, accept contributions from community \n        folks for other POSIX platforms (e.g. FreeBSD) and macOS support.\n  - [ ] Try to add extension for Windows File Explorer for give user immersive \n        experience like builtin zip file support in Windows. (Suggested by \n        SakuraNeko and shuax.)\n  - [ ] Try to create isolated and portable plugin infrastructure based on\n        64-bit RISC-V Unprivileged ISA Specification.\n        Runtime Project: https://github.com/ChaosAIOfficial/RaySoul\n"
  },
  {
    "path": "Documents/People.md",
    "content": "﻿# Relevant People \n\n## Notice\n\n- This list is sorted in alphabetical order.\n\n## Development Team\n\n### Benevolent Dictators For Life\n\nThe project is governed by multiple Benevolent Dictators For Life who make final\ndecisions by reaching an agreement offline. This structure is chosen to avoid\nthe risks of a single point of control while maintaining efficiency over a large\ncommittee. Here are current active Benevolent Dictators For Life:\n\n- dinhngtu (Tu Dinh), https://github.com/dinhngtu\n- Kenji Mouri, https://github.com/MouriNaruto\n\n### Consultants and Benevolent Dictator For Life Candidates\n\nThe following contributors are recognized as candidates for the Benevolent\nDictator For Life role. In their current capacity, they serve as valued\nconsultants to the active Benevolent Dictators For Life due to their significant\nand valuable contributions to the project.\n\n- AndromedaMelody, https://github.com/AndromedaMelody\n- Dongle, https://github.com/dongle-the-gadget\n- Sakura Neko, https://github.com/SakuraNeko\n\n## Microsoft Store preinstall permission OEM Sponsor\n\n- Moespirit Tech, https://github.com/Moespirit\n\n## Logo Designers\n\n### 2.x Series\n\n- Shomnipotence, https://github.com/Shomnipotence\n\n### 1.x Series\n\n- Alice (四月天), https://twitter.com/alice_alice49\n- Chi Lei, https://github.com/lychichem\n- Kenji Mouri, https://github.com/MouriNaruto\n- Rúben Garrido, https://github.com/RGarrido03\n- Sakura Neko, https://github.com/SakuraNeko\n\n## Contributors\n\nRead https://github.com/M2Team/NanaZip/graphs/contributors for getting the\ncontributors list.\n\n## Special thanks\n\n- Belleve, https://github.com/be5invis\n- Igor Pavlov, https://sourceforge.net/u/ipavlov\n- mingkuang, https://github.com/mingkuang-Chuyu\n- myfreeer, https://github.com/myfreeer\n- Tino Reichardt, https://github.com/mcmilk\n"
  },
  {
    "path": "Documents/Policies.md",
    "content": "﻿# NanaZip Policies\n\nStarting with NanaZip 6.0, users can configure system‑wide policies under the\nWindows registry key `HKLM\\Software\\Policies\\M2Team\\NanaZip`.\n\nThese system-wide policies override user settings and are intended for use by\nsystem administrators to enforce specific configurations across multiple users\nor systems.\n\nYou can enforce these policies on an entire domain using our\n[Group Policy Administrative Templates](PolicyDefinitions).\n\nHere are the currently provided policies and their descriptions.\n\n## Available policies since NanaZip 6.0\n\n### Allow dynamic code generation for all NanaZip components\n\nNanaZip disables dynamic code generation for its components by default in\nRelease builds to reduce the risk of running potentially malicious code at\nruntime. However, some third‑party software that relies on dynamic code\ngeneration and injects code into NanaZip processes may require this feature\nto be enabled for compatibility.\n\n- Name: `AllowDynamicCodeGeneration`\n- Type: `REG_DWORD`\n- Value:\n  - `0`: Disabled (Default)\n  - `1`: Enabled\n\n### Allow child processes creation for all NanaZip components\n\nNanaZip blocks child process creation by default in its command line components\nand self‑extracting executables to reduce the risk of process abuse by malicious\narchives. However, some third‑party input method editors (IMEs) and assistive\ntechnologies (ATs) may require child process creation to function correctly. In\nsuch cases, this policy can be used to allow child process creation.\n\n- Name: `AllowChildProcessCreation`\n- Type: `REG_DWORD`\n- Value:\n  - `0`: Disabled (Default)\n  - `1`: Enabled\n\n### Archive handler restrictions\n\nThese values control which archive handlers can be loaded by NanaZip.\n\nWith this policy, you can significantly limit the attack surface of NanaZip by\nblocking the parsing of unusual archive formats.\n\nIf AllowedHandlers is present, only the handlers specified in said list will be\nallowed.\n\nIf BlockedHandlers is present, the handlers specified in said list will be\nblocked. BlockedHandlers takes precedence over AllowedHandlers; i.e. handlers\nspecified in BlockedHandlers will still be blocked even if they're specified in\nAllowedHandlers.\n\nNote that when editing a `REG_MULTI_SZ` value in Registry Editor, each entry\nmust be on its own line.\n\n- Name: `AllowedHandlers`\n- Type: `REG_MULTI_SZ`\n- Value: List of allowed archive handlers (case-sensitive).\n\n<!-- -->\n\n- Name: `BlockedHandlers`\n- Type: `REG_MULTI_SZ`\n- Value: List of blocked archive handlers (case-sensitive).\n\nKnown archive handlers (as of NanaZip 6.0 Preview 2):\n\n```\n.Electron Archive (asar), .NET Single File Application, 7z, APFS, APM, Ar, Arj,\nAVB, Base64, brotli, bzip2, Cab, Chm, COFF, Compound, Cpio, CramFS, Dmg, ELF,\nExt, FAT, FLV, GPT, gzip, HFS, Hxs, IHex, Iso, littlefs, lizard, LP, LVM, lz4,\nlz5, Lzh, lzip, lzma, lzma86, MachO, MBR, MsLZ, Mub, Nsis, NTFS, PE, Ppmd, QCOW,\nRar, Rar5, ROMFS, Rpm, Sparse, Split, SquashFS, SWF, SWFc, tar, TE, Udf, UEFIc,\nUEFIf, UFS, VDI, VHD, VHDX, VMDK, WebAssembly (WASM), wim, Xar, xz, Z, ZealFS,\nzip, zstd\n```\n\nRun `NanaZipC --version` to see the full list of currently-enabled handlers.\n\n### Codec restrictions\n\nSimilarly to archive handler restrictions, these values control which codecs can\nbe loaded by NanaZip.\n\n**Note:** Some single-codec archive formats (e.g. Brotli) may call their\nassociated codecs without respecting codec restrictions. If you want to fully\nblock a codec from being used, make sure that its associated formats are also\nblocked.\n\n- Name: `AllowedCodecs`\n- Type: `REG_MULTI_SZ`\n- Value: List of allowed codecs (case-sensitive).\n\n<!-- -->\n\n- Name: `BlockedCodecs`\n- Type: `REG_MULTI_SZ`\n- Value: List of blocked codecs (case-sensitive).\n\nKnown codecs (as of NanaZip 6.0 Preview 2):\n\n```\n7zAES, AES256CBC, ARM, ARM64, ARMT, BCJ, BCJ2, BROTLI, BZip2, Copy, Deflate,\nDeflate64, Delta, FLZMA2, IA64, LIZARD, LZ4, LZ5, LZMA, LZMA2, PPC, PPMD, Rar1,\nRar2, Rar3, Rar5, RISCV, SPARC, Swap2, Swap4, ZSTD\n```\n\nRun `NanaZipC --version` to see the full list of currently-enabled codecs.\n\n### Propagate Zone.Id stream\n\nThis value controls Mark-of-the-Web (MOTW) propagation of archive files.\n\n- Name: `WriteZoneIdExtract`\n- Type: `REG_DWORD`\n- Value:\n    - `0`: No\n    - `1`: Yes (all files)\n    - `2`: Only for unsafe extensions (does not support all nested archives)\n\n## Legacy Policies in NanaZip 6.0 Preview 1\n\nIn NanaZip 6.0 Preview 1, system-wide policies should be set via creating\nRegistry values in the key `HKLM\\Software\\NanaZip\\Policies` instead.\n\nHere are the policies can be applied in NanaZip 6.0 Preview 1.\n\n- WriteZoneIdExtract\n\nHere are some policies only available in NanaZip 6.0 Preview 1.\n\n### Disable mitigations\n\nThis value controls which security mitigations should not be applied by NanaZip.\n\n- Name: `DisableMitigations`\n- Type: `REG_DWORD`\n- Value:\n    - `0`: Don't disable mitigations\n    - `1`: Disable all mitigations\n    - Other values are reserved.\n"
  },
  {
    "path": "Documents/PolicyDefinitions/NanaZip.admx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<policyDefinitions\n    xmlns=\"http://www.microsoft.com/GroupPolicy/PolicyDefinitions\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:schemaLocation=\"http://www.microsoft.com/GroupPolicy/PolicyDefinitions PolicyDefinitionFiles.xsd\"\n    revision=\"1.0\"\n    schemaVersion=\"1.0\">\n    <policyNamespaces>\n        <target prefix=\"NanaZip\" namespace=\"NanaZip.Policies\" />\n    </policyNamespaces>\n    <resources minRequiredRevision=\"1.0\" />\n\n    <supportedOn>\n        <products>\n            <product name=\"NanaZip\" displayName=\"$(string.NanaZip)\">\n                <!-- major (2 digits) + minor (2 digits) + build (5 digits) -->\n                <majorVersion\n                    name=\"NanaZip60P1\"\n                    displayName=\"$(string.NanaZip60P1)\"\n                    versionIndex=\"60001461\" />\n                <majorVersion\n                    name=\"NanaZip60P2\"\n                    displayName=\"$(string.NanaZip60P2)\"\n                    versionIndex=\"60001621\" />\n            </product>\n        </products>\n        <definitions>\n            <definition\n                name=\"SUPPORTED_NanaZip60P1Only\"\n                displayName=\"$(string.SUPPORTED_NanaZip60P1Only)\">\n                <and>\n                    <range ref=\"NanaZip60P1\" />\n                </and>\n            </definition>\n            <definition\n                name=\"SUPPORTED_NanaZip60P2\"\n                displayName=\"$(string.SUPPORTED_NanaZip60P2)\">\n                <and>\n                    <range ref=\"NanaZip\" minVersionIndex=\"60001621\" />\n                </and>\n            </definition>\n        </definitions>\n    </supportedOn>\n\n    <categories>\n        <category name=\"NanaZipPolicies\" displayName=\"$(string.NanaZipPolicies)\" />\n        <category name=\"HandlerCodecRestrictions\" displayName=\"$(string.HandlerCodecRestrictions)\">\n            <parentCategory ref=\"NanaZipPolicies\" />\n        </category>\n        <category name=\"NanaZipPoliciesLegacy\" displayName=\"$(string.NanaZipPoliciesLegacy)\">\n            <parentCategory ref=\"NanaZipPolicies\" />\n        </category>\n    </categories>\n\n    <policies>\n        <policy\n            name=\"AllowDynamicCodeGeneration\"\n            class=\"Machine\"\n            displayName=\"$(string.AllowDynamicCodeGeneration)\"\n            explainText=\"$(string.AllowDynamicCodeGenerationExplain)\"\n            key=\"SOFTWARE\\Policies\\M2Team\\NanaZip\"\n            valueName=\"AllowDynamicCodeGeneration\">\n            <parentCategory ref=\"NanaZipPolicies\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P2\" />\n            <enabledValue>\n                <decimal value=\"1\" />\n            </enabledValue>\n            <disabledValue>\n                <decimal value=\"0\" />\n            </disabledValue>\n        </policy>\n        <policy\n            name=\"AllowChildProcessCreation\"\n            class=\"Machine\"\n            displayName=\"$(string.AllowChildProcessCreation)\"\n            explainText=\"$(string.AllowChildProcessCreationExplain)\"\n            key=\"SOFTWARE\\Policies\\M2Team\\NanaZip\"\n            valueName=\"AllowChildProcessCreation\">\n            <parentCategory ref=\"NanaZipPolicies\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P2\" />\n            <enabledValue>\n                <decimal value=\"1\" />\n            </enabledValue>\n            <disabledValue>\n                <decimal value=\"0\" />\n            </disabledValue>\n        </policy>\n        <policy\n            name=\"WriteZoneIdExtract\"\n            class=\"Machine\"\n            displayName=\"$(string.WriteZoneIdExtract)\"\n            explainText=\"$(string.WriteZoneIdExtractExplain)\"\n            presentation=\"$(presentation.WriteZoneIdExtract)\"\n            key=\"SOFTWARE\\Policies\\M2Team\\NanaZip\">\n            <parentCategory ref=\"NanaZipPolicies\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P2\" />\n            <elements>\n                <enum id=\"WriteZoneIdExtract\" valueName=\"WriteZoneIdExtract\">\n                    <item displayName=\"$(string.WriteZoneIdExtract0)\">\n                        <value>\n                            <decimal value=\"0\" />\n                        </value>\n                    </item>\n                    <item displayName=\"$(string.WriteZoneIdExtract1)\">\n                        <value>\n                            <decimal value=\"1\" />\n                        </value>\n                    </item>\n                    <item displayName=\"$(string.WriteZoneIdExtract2)\">\n                        <value>\n                            <decimal value=\"2\" />\n                        </value>\n                    </item>\n                </enum>\n            </elements>\n        </policy>\n\n        <!-- Handler and codec restrictions -->\n        <policy\n            name=\"AllowedHandlers\"\n            class=\"Machine\"\n            displayName=\"$(string.AllowedHandlers)\"\n            explainText=\"$(string.AllowedHandlersExplain)\"\n            presentation=\"$(presentation.AllowedHandlers)\"\n            key=\"SOFTWARE\\Policies\\M2Team\\NanaZip\">\n            <parentCategory ref=\"HandlerCodecRestrictions\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P2\" />\n            <elements>\n                <multiText id=\"AllowedHandlers\" valueName=\"AllowedHandlers\" />\n            </elements>\n        </policy>\n        <policy\n            name=\"BlockedHandlers\"\n            class=\"Machine\"\n            displayName=\"$(string.BlockedHandlers)\"\n            explainText=\"$(string.BlockedHandlersExplain)\"\n            presentation=\"$(presentation.BlockedHandlers)\"\n            key=\"SOFTWARE\\Policies\\M2Team\\NanaZip\">\n            <parentCategory ref=\"HandlerCodecRestrictions\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P2\" />\n            <elements>\n                <multiText id=\"BlockedHandlers\" valueName=\"BlockedHandlers\" />\n            </elements>\n        </policy>\n        <policy\n            name=\"AllowedCodecs\"\n            class=\"Machine\"\n            displayName=\"$(string.AllowedCodecs)\"\n            explainText=\"$(string.AllowedCodecsExplain)\"\n            presentation=\"$(presentation.AllowedCodecs)\"\n            key=\"SOFTWARE\\Policies\\M2Team\\NanaZip\">\n            <parentCategory ref=\"HandlerCodecRestrictions\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P2\" />\n            <elements>\n                <multiText id=\"AllowedCodecs\" valueName=\"AllowedCodecs\" />\n            </elements>\n        </policy>\n        <policy\n            name=\"BlockedCodecs\"\n            class=\"Machine\"\n            displayName=\"$(string.BlockedCodecs)\"\n            explainText=\"$(string.BlockedCodecsExplain)\"\n            presentation=\"$(presentation.BlockedCodecs)\"\n            key=\"SOFTWARE\\Policies\\M2Team\\NanaZip\">\n            <parentCategory ref=\"HandlerCodecRestrictions\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P2\" />\n            <elements>\n                <multiText id=\"BlockedCodecs\" valueName=\"BlockedCodecs\" />\n            </elements>\n        </policy>\n\n        <!-- Legacy policies -->\n        <policy\n            name=\"WriteZoneIdExtractLegacy\"\n            class=\"Machine\"\n            displayName=\"$(string.WriteZoneIdExtract)\"\n            explainText=\"$(string.WriteZoneIdExtractExplain)\"\n            presentation=\"$(presentation.WriteZoneIdExtract)\"\n            key=\"SOFTWARE\\NanaZip\\Policies\">\n            <parentCategory ref=\"NanaZipPoliciesLegacy\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P1Only\" />\n            <elements>\n                <enum id=\"WriteZoneIdExtract\" valueName=\"WriteZoneIdExtract\">\n                    <item displayName=\"$(string.WriteZoneIdExtract0)\">\n                        <value>\n                            <decimal value=\"0\" />\n                        </value>\n                    </item>\n                    <item displayName=\"$(string.WriteZoneIdExtract1)\">\n                        <value>\n                            <decimal value=\"1\" />\n                        </value>\n                    </item>\n                    <item displayName=\"$(string.WriteZoneIdExtract2)\">\n                        <value>\n                            <decimal value=\"2\" />\n                        </value>\n                    </item>\n                </enum>\n            </elements>\n        </policy>\n        <policy\n            name=\"DisableMitigations\"\n            class=\"Machine\"\n            displayName=\"$(string.DisableMitigations)\"\n            explainText=\"$(string.DisableMitigationsExplain)\"\n            key=\"SOFTWARE\\NanaZip\\Policies\"\n            valueName=\"DisableMitigations\">\n            <parentCategory ref=\"NanaZipPoliciesLegacy\" />\n            <supportedOn ref=\"SUPPORTED_NanaZip60P1Only\" />\n            <enabledValue>\n                <decimal value=\"1\" />\n            </enabledValue>\n            <disabledValue>\n                <decimal value=\"0\" />\n            </disabledValue>\n        </policy>\n    </policies>\n</policyDefinitions>\n"
  },
  {
    "path": "Documents/PolicyDefinitions/en-US/NanaZip.adml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<policyDefinitionResources\n    xmlns=\"http://www.microsoft.com/GroupPolicy/PolicyDefinitions\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:schemaLocation=\"http://www.microsoft.com/GroupPolicy/PolicyDefinitions ../PolicyDefinitionFiles.xsd\"\n    revision=\"1.0\"\n    schemaVersion=\"1.0\">\n    <displayName>NanaZip</displayName>\n    <description>NanaZip</description>\n\n    <resources>\n        <stringTable>\n            <!-- Products -->\n            <string id=\"NanaZip\">NanaZip</string>\n            <string id=\"NanaZip60P1\">NanaZip 6.0 Preview 1</string>\n            <string id=\"NanaZip60P2\">NanaZip 6.0 Preview 2</string>\n\n            <!-- Definitions -->\n            <string id=\"SUPPORTED_NanaZip60P1Only\">NanaZip 6.0 Preview 1 only</string>\n            <string id=\"SUPPORTED_NanaZip60P2\">At least NanaZip 6.0 Preview 2</string>\n\n            <!-- Categories -->\n            <string id=\"NanaZipPolicies\">NanaZip</string>\n            <string id=\"HandlerCodecRestrictions\">Handler and Codec Restrictions</string>\n            <string id=\"NanaZipPoliciesLegacy\">Legacy Policies</string>\n\n            <!-- Policies -->\n            <string id=\"AllowDynamicCodeGeneration\">Allow dynamic code generation for all NanaZip components</string>\n            <string id=\"AllowDynamicCodeGenerationExplain\">NanaZip disables dynamic code generation for its components by default in Release builds to reduce the risk of running potentially malicious code at runtime. However, some third-party software that relies on dynamic code generation and injects code into NanaZip processes may require this feature to be enabled for compatibility.\n\nIf you enable this policy setting, NanaZip allows third-party components to generate dynamic code at runtime.\n\nIf you disable or do not configure this policy setting, NanaZip blocks the ability to create dynamic code in its own processes.</string>\n\n            <string id=\"AllowChildProcessCreation\">Allow child processes creation for all NanaZip components</string>\n            <string id=\"AllowChildProcessCreationExplain\">NanaZip blocks child process creation by default in its command line components and self-extracting executables to reduce the risk of process abuse by malicious archives. However, some third-party input method editors (IMEs) and assistive technologies (ATs) may require child process creation to function correctly. In such cases, this policy can be used to allow child process creation.\n\nIf you enable this policy setting, NanaZip processes can create child processes at runtime.\n\nIf you disable or do not configure this policy setting, NanaZip blocks the ability to create child processes from many of its own processes.</string>\n\n            <string id=\"AllowedHandlers\">Allowed archive handlers</string>\n            <string id=\"AllowedHandlersExplain\">This policy setting controls which archive handlers can be loaded by NanaZip.\n\nWith this policy setting, you can significantly limit the attack surface of NanaZip by blocking the parsing of uncommon archive formats.\n\nIf you enable this policy setting, only the handlers specified in this list (one in each line, case sensitive) will be allowed to load.\n\nIf you disable or do not configure this policy setting, all otherwise-unspecified archive handlers can load.\n\nRun NanaZipC --version to see the full list of currently-enabled handlers.</string>\n\n            <string id=\"BlockedHandlers\">Blocked archive handlers</string>\n            <string id=\"BlockedHandlersExplain\">This policy setting controls which archive handlers cannot be loaded by NanaZip.\n\nWith this policy setting, you can significantly limit the attack surface of NanaZip by blocking the parsing of uncommon archive formats.\n\nIf you enable this policy setting, the handlers specified in this list (one in each line, case sensitive) will be blocked from loading.\n\nIf you disable or do not configure this policy setting, all otherwise-unspecified archive handlers can load.\n\nRun NanaZipC --version to see the full list of currently-enabled handlers.</string>\n\n            <string id=\"AllowedCodecs\">Allowed compression codecs</string>\n            <string id=\"AllowedCodecsExplain\">This policy setting controls which compression codecs can be loaded by NanaZip.\n\nWith this policy setting, you can significantly limit the attack surface of NanaZip by blocking the execution of uncommon compression codecs.\n\nIf you enable this policy setting, only the codecs specified in this list (one in each line, case sensitive) will be allowed to load.\n\nIf you disable or do not configure this policy setting, all otherwise-unspecified compression codecs can load.\n\nRun NanaZipC --version to see the full list of currently-enabled codecs.</string>\n\n            <string id=\"BlockedCodecs\">Blocked compression codecs</string>\n            <string id=\"BlockedCodecsExplain\">This policy setting controls which compression codecs cannot be loaded by NanaZip.\n\nWith this policy setting, you can significantly limit the attack surface of NanaZip by blocking the execution of uncommon compression codecs.\n\nIf you enable this policy setting, the codecs specified in this list (one in each line, case sensitive) will be blocked from loading.\n\nIf you disable or do not configure this policy setting, all otherwise-unspecified compression codecs can load.\n\nRun NanaZipC --version to see the full list of currently-enabled codecs.</string>\n\n            <!-- Shared between new and legacy policies -->\n            <string id=\"WriteZoneIdExtract\">Propagate Zone.Id stream</string>\n            <string id=\"WriteZoneIdExtractExplain\">This policy setting controls Mark-of-the-Web (MOTW) propagation of archive files.\n\nIf you enable this policy setting, NanaZip follows the given MOTW setting when extracting files.\n\nIf you disable or do not configure this policy setting, NanaZip follows the user's MOTW propagation setting.</string>\n            <string id=\"WriteZoneIdExtract0\">Don't propagate MOTW</string>\n            <string id=\"WriteZoneIdExtract1\">Propagate MOTW to all files</string>\n            <string id=\"WriteZoneIdExtract2\">Propagate MOTW to unsafe files</string>\n\n            <!-- Legacy policies -->\n            <string id=\"DisableMitigations\">Disable mitigations</string>\n            <string id=\"DisableMitigationsExplain\">This policy setting controls the application of security mitigations on NanaZip processes.\n\nIf you enable this policy setting, NanaZip disables all security mitigations in its processes.\n\nIf you disable or do not configure this policy setting, NanaZip enables all mitigations by default.</string>\n        </stringTable>\n\n        <presentationTable>\n            <presentation id=\"AllowedHandlers\">\n                <text>List of allowed archive handlers:</text>\n                <multiTextBox refId=\"AllowedHandlers\" />\n            </presentation>\n            <presentation id=\"BlockedHandlers\">\n                <text>List of blocked archive handlers:</text>\n                <multiTextBox refId=\"BlockedHandlers\" />\n            </presentation>\n            <presentation id=\"AllowedCodecs\">\n                <text>List of allowed compression codecs:</text>\n                <multiTextBox refId=\"AllowedCodecs\" />\n            </presentation>\n            <presentation id=\"BlockedCodecs\">\n                <text>List of blocked compression codecs:</text>\n                <multiTextBox refId=\"BlockedCodecs\" />\n            </presentation>\n            <presentation id=\"WriteZoneIdExtract\">\n                <dropdownList refId=\"WriteZoneIdExtract\" defaultItem=\"1\">Propagate Zone.Id stream:</dropdownList>\n            </presentation>\n        </presentationTable>\n    </resources>\n</policyDefinitionResources>\n"
  },
  {
    "path": "Documents/Privacy.md",
    "content": "﻿# NanaZip - Privacy Policy\n\n## Information collected\n\nNanaZip does not collect any information. However it does provide you access to \nfiles and folders on your file system. Additionally, the Windows Store and \nWindows App Host collect data on usage, for example, who bought/used the app \nand crash reports. If you open any files or links in the app that go to other\nwebsites you will need to look at their privacy policy.\n\n## Sponsored edition\n\nDue to the Microsoft Store Licensing API implementation, you will find NanaZip\nwill try to access the Internet beginning with NanaZip 3.0 because NanaZip\nneeds to use that to check the Sponsor Edition addon licensing status.\n\nFor optimizing the user experience, NanaZip will only check the Sponsor \nEdition addon licensing status at the first time your launch NanaZip File\nManager. You can click the sponsor button if you want to refresh the status\nafter you have purchased or redeemed the Sponsor Edition addon.\n \n## Use of information\n\nNo other data is collected or shared online. We reserve the right to \nmake changes to this policy. Any changes to this policy will be updated. \n \n## Last updated: May 28, 2024\n"
  },
  {
    "path": "Documents/ReleaseNotes.md",
    "content": "﻿# NanaZip Release Notes\n\nFor preview versions, please read \n[NanaZip Preview Release Notes](ReleaseNotesPreview.md).\n\n**NanaZip 6.0 Update 2 (6.0.1650.0)**\n\n- Add NanaZip official website link to the XAML About Dialog.\n- Fix some crash issues caused by dark mode support.\n- Fix some crash issues caused by the XAML information dialog.\n- Fix the issue that we cannot use NanaZip.Universal.Windows.exe without\n  NanaZip.Modern.dll.\n- Fix the issue that we cannot set the initial folder for the copy location\n  dialog browse button.\n- Fix the buffer overflow issue introduced since 7-Zip mainline 26.00 when using\n  NanaZip.Core.Setup.sfx which you need to compiled manually to get. (Backported\n  from https://github.com/M2Team/NanaZip/pull/850 and\n  https://github.com/mcmilk/7-Zip-zstd/pull/468/changes/f4efd0f2d960b18fd51a894d04b5eadebf8c270b.)\n\n**NanaZip 6.0 Update 1 (6.0.1638.0)**\n\n- Fix several issues for the UFS/UFS2 file system image readonly support.\n  (Cooperated with HO-9.)\n- Fix several issues for the .NET Single File Application bundle readonly\n  support. (Cooperated with HO-9.)\n- Fix the white flashes when initializing the file panels in the NanaZip File \n  Manager main window. (Thanks to anhelloooo.)\n- Disable text wrapping for textbox control in XAML information dialog to show\n  information better.\n- Make the hash calculation result output text format more compact to improve\n  the copy and paste experience.\n- Fix the Win32 TaskDialog-based Folders History dialog not functioning when\n  users navigate to the desktop virtual folder.\n- Update Japanese translation. (Contributed by noangel.)\n- Update Brazilian Portuguese translation. (Contributed by maisondasilva.)\n\n**NanaZip 6.0 (6.0.1632.0)**\n\n- Notes\n  - Start to transition to community driven development model.\n  - Update system requirement to Windows 10, version 2004 (Build 19041) or\n    later, and remove the x86 (32-bit) for all components.\n  - Start to provide the official portable binaries package of NanaZip with both\n    Modern and Classic flavors, except the NanaZip File Manager.\n  - Introduce formal version of contributing guide and security policies.\n    (Cooperated with dinhngtu and dongle-the-gadget.)\n  - Add Release Tags to NanaZip Versioning.\n- Features\n  - Introduce extract-on-open feature. (Contributed by dinhngtu.)\n    - To disable this temporarily, hold Shift while opening the file.\n    - To disable this permanently, go to Settings, Integration tab, and disable\n      \"Extract on open\" at the bottom.\n  - Introduce registry settings for Mark of the Web (MoTW) enforcement policies.\n    (Contributed by dinhngtu.)\n  - Improve the dynamic library block list for resolving compatibility issues.\n    (Contributed by dinhngtu.)\n  - Introduce registry settings for disabling security mitigation policies,\n    which should be helpful for debugging and resolving compatibility issues.\n    (Contributed by dinhngtu.)\n  - Introduce registry settings for the archive handler and codec handler\n    restriction. (Contributed by dinhngtu.)\n  - Introduce Group Policy Administrative Template (ADMX/ADML) for NanaZip.\n    (Contributed by dinhngtu.)\n  - Set the LOAD_LIBRARY_SEARCH_SYSTEM32 dependent load flag on Release builds\n    of Self Extracting Executables stubs to mitigate static imports level DLL\n    planting attack on Windows 10 build 14393 and later. (Contributed by\n    dinhngtu.)\n  - Introduce the XAML-based address bar. (Contributed by dongle-the-gadget.)\n  - Introduce the XAML-based status bar. (Contributed by dongle-the-gadget.)\n  - Introduce the XAML-based properties and information dialog. (Contributed by\n    dongle-the-gadget.)\n  - Introduce the XAML-based progress dialog. (Contributed by \n    dongle-the-gadget.)\n  - Introduce extract all automatically policy when opening executable files in\n    archives. (Contributed by MajThomas.)\n  - Introduce the environment variable parsing support for address bar. (Thanks\n    to dongle-the-gadget's huge help.)\n  - Add support for CBR and CBZ file associations. (Contributed by dinhngtu.)\n  - Add support for ASAR file association. (Contributed by dongle-the-gadget.)\n  - Display file system version in archive property window for the UFS/UFS2 file\n    system image readonly support.\n  - Display bundle version in archive property for the .NET Single File\n    Application bundle readonly support.\n  - Display file system version in archive property for the littlefs file system\n    image readonly support.\n  - Allow to associate more file types to NanaZip. (Contributed by manfromarce.)\n  - Enable Ctrl+Backspace on edit fields using SHAutoComplete. (Contributed by\n    dinhngtu.)\n  - Introduce NanaZip.Universal.Windows project for making NanaZip Command Line\n    Interface (Windows) for both NanaZip (Modern) and NanaZip Classic a.k.a.\n    NanaZipG or K7G to synchronize to the latest 7-Zip mainline and 7-Zip ZS\n    implementations.\n  - Introduce NanaZip Platform Base Library (K7Base) and NanaZip Platform User\n    Library (K7User) to replace NanaZip Platform Abstraction Layer (K7Pal) and\n    NanaZip.Frieren for better code sharing and maintainability.\n  - Create NanaZip.Modern project for the modern user experience development.\n  - Introduce Mile.Mobility dependence to NanaZip.Codecs project for making\n    better portability between NanaZip and AptxZip (a.k.a. NanaZip for POSIX).\n  - Introduce NanaZip.ExtensionPackage project for future development of\n    features which need to be distributed as legacy installer. (Contributed by\n    dinhngtu.)\n  - Introduce Mile.Helpers.Portable.Base.Unstaged as the temporary\n    infrastructure to standardize some portable things in NanaZip.Codecs.\n  - Introduce NanaZip.Codecs.Specification.Fat for adding definitions of FAT12,\n    FAT16 and FAT32.\n  - Introduce NanaZip.Codecs.Specification.Zealfs for adding definitions of\n    ZealFS series file system. (Cooperated with Zeal 8-bit.)\n  - Add littlefs v1 on-disk definitions to the littlefs file system image\n    readonly support.\n  - Move NanaZip.Core's NanaZip.Core.Console project to NanaZip.Universal's\n    NanaZip.Universal.Console project.\n- Improvements\n  - Start to use Zstandard decoder instead of 7-Zip mainline's implementation\n    for better reliability, especially it can reduce more potential\n    vulnerabilities.\n  - Use x-generate to define language resources in AppX manifest to solve the\n    Windows AppX language fallback issue. (Suggested by dongle-the-gadget.)\n  - Make texts have better contrast in dark mode.\n  - Improve the Smart Extraction feature. (Contributed by R-YaTian.)\n  - Improve the NanaZip startup performance by initializing the StoreContext\n    later. (Contributed by dongle-the-gadget.)\n  - Move open folder checkbox to extract dialog. (Contributed by dinhngtu.)\n  - Update Albanian translation. (Contributed by F1219R.)\n  - Update Hungarian translation. (Contributed by John Fowler.)\n  - Update Greek translation. (Contributed by Lefteris T.)\n  - Update German translation. (Contributed by HackZy01.)\n  - Update Bengali translation. (Contributed by Sumon Kayal.)\n  - Update Dutch translation. (Contributed by Stephan-P.)\n  - Localize Open Inside menu text. (Contributed by dinhngtu.)\n  - Remove Help button from compress option dialogs. (Contributed by\n    peashooter2.)\n  - Update the icon assets with optimized assets to reduce the binary size.\n  - Use Win32 TaskDialog to implement the Folders History dialog to simplify the\n    implementation.\n  - Synchronize 7-Zip mainline implementations to 26.00. (Except the NanaZip\n    File Manager.) (Thanks to Igor Pavlov. Noticed by FadeMind and Pinguin2001.)\n  - Synchronize the 7-Zip ZS implementations to\n    https://github.com/mcmilk/7-Zip-zstd/tree/5766dd7745f6517f7ea42f6de9a190dfd92aa25f.\n    (Except the NanaZip File Manager.) (Thanks to Sergey G. Brester and Tino\n    Reichardt.)\n  - Make FastLZMA2 and Lizard reuse partial Zstandard implementations.\n  - Update Zstandard to v1.5.7. (Noticed by dcog989.)\n  - Update Lizard to v2.1.\n  - Synchronize Brotli implementations to v1.2.0.\n    (https://github.com/google/brotli/releases/tag/v1.2.0)\n  - Synchronize the FastLZMA2 implementations to\n    https://github.com/conor42/fast-lzma2/tree/a793db99fade2957d2453035390f97e573acecb2,\n    which can fix some issues. (Contributed by dinhngtu.)\n  - Synchronize the BLAKE3 implementation to 1.8.3. (Noticed by peashooter2.)\n    (https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.8.3)\n  - Use assembly hardware acceleration for BLAKE3 implementation.\n  - Synchronize RHash to the latest master\n    (https://github.com/rhash/RHash/tree/b76c6a3312422c09817c2cef40442b2f2d9d4689)\n    which is after v1.4.6.\n  - Update Mile.Project.Configurations to 1.0.1917, which solve some issues for\n    using NuGet Package References Support in Visual Studio 2026 version 18.3 or\n    later. (Cooperated by AndromedaMelody.)\n  - Update Mile.Project.Helpers to 1.0.975.\n  - Update Mile.Windows.Helpers to 1.0.1171.\n  - Update Mile.Windows.Internal to 1.0.3515.\n  - Update Mile.Xaml to 2.5.1616.\n  - Update Mile.Detours to 1.0.2180.\n  - Update Mile.Json to 1.0.1057.\n  - Update .NET projects to .NET 10 and update NuGet package dependencies.\n  - Add littlefs v2.10.2 to NanaZip.Codecs for future development of work in\n    progress littlefs archive format readonly support.\n  - Update build binary logs when failed to build in GitHub Actions.\n    (Contributed by dongle-the-gadget.)\n  - Introduce legacy string migrator. (Contributed by dongle-the-gadget.)\n  - Add more targeted editorconfig rules. (Contributed by dongle-the-gadget.)\n  - Move NanaZip.Core's NanaZip.Core.Console project to NanaZip.Universal's\n    NanaZip.Universal.Console project.\n  - Disable WinRT metadata generation for all WinRT component consumers.\n  - Move NanaZip.Modern as the first item to workaround the AppX toolchain\n    manifest generation issues.\n  - Improve the GitHub Actions artifacts generation.\n  - Update to Windows 11 SDK Build 26100 for NanaZipPackage.\n  - Introduce reproducible build support for the whole project.\n  - Migrate solution from sln to slnx, and start to build with MSVC 14.50 \n    toolset.\n  - Support opening NanaZip Visual Studio solution without installing WinUI\n    application and/or Universal Windows Platform development workload.\n    (Contributed by AndromedaMelody.)\n  - Add RestoreNuGetPackages.cmd script to workaround some issues for people who\n    want to use Visual Studio to build NanaZip without running\n    BuildAllTargets.bat script.\n  - Make the precompiled build tools generated by GitHub Actions workflow\n    automatically.\n  - Improve several implementations.\n- Fixes\n  - Fix dead loop issue when compressing files with Brotli, Lizard, LZ4 and LZ5\n    mentioned in https://github.com/M2Team/NanaZip/issues/639. (Thanks to\n    gigano01, InfiniteLoopGameDev and iOrange.)\n  - Backport CVE-2025-0411 and CVE-2025-11001 for the NanaZip File Manager which\n    still use the old 7-Zip mainline codebase. (Contributed by dinhngtu.)\n  - Fix several crash issues for the .NET Single File Application bundle\n    readonly support. (Thanks to haaeein.)\n  - Fix several hang issues for the ROMFS file system image readonly support\n    support. (Contributed by dinhngtu. Thanks to haaeein.)\n  - Fix the flickering issues when selecting list view in dark mode.\n  - Fix the unable to return the processed bytes count issue for\n    NanaZipCodecsReadInputStream.\n  - Fix the parsing padding issue for Electron Archive (asar) readonly support.\n    (Contributed by Vlad-Andrei Popescu).\n  - Improve the ZealFS file system image readonly support implementation to fix\n    several issues. (Cooperated with Zeal 8-bit.)\n  - Try to bring dialog window to the foreground to resolve user experience\n    issues when opened from context menu. (Contributed by dinhngtu.)\n  - Fix flickering XAML dialogs. (Contributed by dongle-the-gadget.)\n  - Fix crash issue from XAML address bar. (Contributed by dongle-the-gadget.)\n  - Use a low name as the shell extension name prefix to work around our context\n    menu not appearing in the classic context menu. (Contributed by dinhngtu.)\n  - Don't reset compression method after changing level. (Contributed by\n    dongle-the-gadget.)\n  - Fix text overflow in German translation. (Contributed by Pinguin2001.)\n  - Fix UI assignment of WriteZone setting. (Contributed by dinhngtu.)\n  - Handle Add button when inside archives. (Contributed by dinhngtu.)\n  - Fix issues for NanaZip Preview SVG icon assets for Contrast Black mode.\n  - Fix several issues for context menu support. (Contributed by dinhngtu.)\n  - Fix some potential issues for the dark mode support.\n  - Try to partially improve the NanaZip File Manager main window keyboard\n    navigation experience.\n  - Fix some string resources issues. (Contributed by dinhngtu.)\n  - Fix issues in compression levels combobox. (Contributed by dongle-the-gadget.)\n  - Fix the source code file header comment format.\n  - Use C++ zero initialization to reduce potential issues.\n  - Fix several issues.\n\n**NanaZip 5.0 Update 2 (5.0.1263.0)**\n\n- Features\n  - Provide K7 style execution aliases (K7.exe, K7C.exe, and K7G.exe) for\n    simplifying the command line user experience and providing the same command\n    name style in work-in-progress NanaZip for POSIX a.k.a. AptxZip.\n- Improvements\n  - Update Mile.Windows.UniCrt to 1.2.328.\n  - Update Mile.Xaml to 2.5.1250.\n  - Migrate from Mile.Project.Windows to Mile.Project.Configurations.\n- Fixes\n  - Fix crash issue when using Open Inside # mode for the WebAssembly (WASM)\n    binary file readonly support for NanaZip.Codecs.\n  - Fix crash issue when using Open Inside # mode for the .NET Single File\n    Application bundle readonly support for NanaZip.Codecs.\n  - Fix crash issue when using Open Inside # mode for the Electron Archive\n    (asar) readonly support for NanaZip.Codecs.\n  - Fix the crash issue when extracting *.br archives. (Thanks to HikariCalyx.)\n  - Fix the XXH3_128bits printable results with wrong byte order. (Thanks to\n    fuchanghao.)\n\n**NanaZip 5.0 Update 1 (5.0.1252.0)**\n\n- Features\n  - Introduce the .NET Single File Application bundle readonly support which\n    currently extracting compressed files in the bundle are not supported.\n  - Introduce the Electron Archive (asar) readonly support.\n  - Introduce the ROMFS file system image readonly support.\n  - Introduce the ZealFS file system image readonly support.\n  - Introduce the WebAssembly (WASM) binary file readonly support.\n  - Introduce the **Work In Progress** littlefs file system image readonly\n    support which currently only block information can acquired.\n- Improvements\n  - Update Ukrainian and Russian translation. (Contributed by SlowDancer011.)\n  - Update Hungarian translation. (Contributed by JohnFowler58.)\n  - Update packages for maintainer tools.\n- Fixes\n  - Fix the empty folders are excluded issue for the UFS/UFS2 file system image\n    readonly support.\n  - Fix the unavailable issue when cancelling the extraction for the UFS/UFS2\n    file system image readonly support.\n\n**NanaZip 5.0 (5.0.1250.0)**\n\n- Features\n  - Introduce the UFS/UFS2 file system image readonly support. (Thanks to\n    NishiOwO.)\n  - Introduce work-in-progress NanaZip Platform Abstraction Layer (K7Pal) for\n    wrapping the platform specific infrastructures. (Thanks to RuesanG's \n    feedback.) (https://github.com/M2Team/NanaZip/tree/main/K7Pal)\n    - Provide hash functions interfaces implemented with Windows CNG API.\n      NanaZip uses these hash functions from K7Pal:\n      - MD2\n      - MD4\n      - MD5\n      - SHA-1\n      - SHA-256\n      - SHA-384\n      - SHA-512\n      - ED2K (Implemented as the K7Pal MD4 wrapper in NanaZip.Codecs.)\n  - Update NanaZip.Specification.SevenZip header file.\n  - Introduce the Smart Extraction. (Contributed by R-YaTian.)\n  - Adds a setting for opening the folder after extracting from archive.\n    (Contributing by DaxDupont.)\n- Improvements\n  - Synchronize the 7-Zip mainline implementations to 24.09.\n    (https://github.com/ip7z/7zip/releases/tag/24.09) (Thanks to Igor Pavlov.\n    Noticed by FadeMind and peashooter2.)\n  - Synchronize the BLAKE3 implementation to 1.5.5.\n    (https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.5.5)\n  - Synchronize the RHash implementation to the latest master branch which is\n    after v1.4.5.\n    (https://github.com/rhash/RHash/commit/cf2adf22ae7c39d9b8e5e7b87222046a8f42b3dc)\n  - Synchronize the xxHash implementation to v0.8.3.\n    (https://github.com/Cyan4973/xxHash/releases/tag/v0.8.3)\n  - Update Mile.Windows.Helpers to 1.0.671.\n    (https://github.com/ProjectMile/Mile.Windows.Helpers/tree/1.0.671.0)\n  - Update Brazilian Portuguese translation. (Contributed by maisondasilva.)\n  - Update Polish translation. (Contributed by ChuckMichael.)\n  - Update zh-Hans and zh-Hant translations for 'Want * History' strings. \n    (Contributed by R-YaTian.) (Forget to mentioned in NanaZip 5.0 Preview 1.)\n  - Make sure NanaZip Core (except the Self Extracting Executables) and NanaZip\n    Classic using ucrtbase.dll with 10.0.19041.0 version or later.\n  - Move NanaZip console version to NanaZip.Core project.\n  - Remove C++/WinRT dependency for NanaZip.Codecs and NanaZip.Frieren.\n  - Remove VC-LTL dependency for all components, and also use \n    Mile.Windows.UniCrt (https://github.com/ProjectMile/Mile.Windows.UniCrt)\n    instead of VC-LTL for non Self Extracting Executables stub components.\n  - Adjust the compilation configurations to optimize the binary size for the\n    Self Extracting Executables.\n  - Start to simplify the NanaZip specific decoders and encoders implementation.\n  - Enable disabling child process creation for NanaZip Self Extracting\n    Executables. (Except installer mode of Self Extracting Executables, which\n    compiled binaries is not provided in the NanaZip MSIX package.)\n- Fixes\n  - Add GetDpiForWindowWrapper for NanaZip.Frieren.DarkMode to fix the legacy\n    Windows compatibility issues.\n  - Don't fail ModernSHBrowseForFolderW when DefaultFolder cannot be set.\n    (Contributed by dinhngtu.)\n  - Fix the issue that which NanaZip windows and dialogs will be opened in the\n    background when using NanaZip from context menu. (Contributed by R-YaTian.)\n\n**NanaZip 3.1 (3.1.1080.0)**\n\n- Try to discover the new Sponsor button design but finally reverted to the old\n  design for more natural looking. (Contributed by dongle-the-gadget and\n  Gaoyifei1011.)\n- Improve Simplified Chinese translation. (Contributed by DeepChirp.)\n- Improve the Sponsor Edition documentation. (Contributed by sirredbeard.)\n- Improve Albanian translation. (Contributed by RDN000.)\n- Improve German translation. (Contributed by CennoxX.)\n- Fix several dark mode UI style issues. (Contributed by rounk-ctrl.)\n- Ignore the text scale factor for solving the UI layout issues.\n- Synchronize the 7-Zip mainline implementations to 24.08.\n  (https://github.com/ip7z/7zip/releases/tag/24.08) (Thanks to Igor Pavlov.\n  Noticed by atplsx and wallrik.)\n- Synchronize the LZ4 implementations to 1.10.0.\n  (https://github.com/lz4/lz4/releases/tag/v1.10.0)\n- Update Mile.Project.Windows submodule to the August 12, 2024 latest.\n- Update VC-LTL to 5.1.1.\n- Update YY-Thunks to 1.1.2.\n- Update Mile.Windows.Helpers to 1.0.645.\n- Update Mile.Xaml to 2.3.1064.\n- Update Mile.Windows.Internal to 1.0.2971.\n- Defer package updates while the app is running in Windows 11 23H2 or later.\n  (Suggested by AndromedaMelody.)\n- Improve maintainer tools for introducing automatic packaging support when\n  building all targets for NanaZip.\n\n**NanaZip 3.0 Update 1 (3.0.1000.0)**\n\n- Update Mile.Windows.Internal to 1.0.2889.\n- Make the 7-Zip Zstandard branch's specific options translatable. (Contributed\n  by ChuckMichael.)\n- Polish translation for Sponsor dialog. (Contributed by ChuckMichael.)\n- Fix compatibility issues with iFlyIME, Sogou Pinyin, and Transparent Flyout.\n  (Contributed by dinhngtu.)\n- Update the UI layout for the sponsor button. (Suggested by namazso.)\n- NanaZip will only check the Sponsor Edition addon licensing status the first\n  time you launch NanaZip File Manager or click the sponsor button to optimize\n  the user experience.\n- Update NanaZip installation documentation. (Contributed by dongle-the-gadget.)\n- Use Extract dialog when extracting without selection. (Contributed by \n  dinhngtu.)\n- Fix tooltips from XAML controls cannot be transparent.\n- Fix dark mode UI font rendering issues in some Windows 10 environments.\n- Adjust the dark mode text color for improving the user experience. (Suggested\n  by userzzzq.)\n- Synchronize the 7-Zip mainline implementations to 24.06.\n  (https://github.com/ip7z/7zip/releases/tag/24.06) (Thanks to Igor Pavlov.\n  Noticed by KsZAO.)\n\n**NanaZip 3.0 (3.0.996.0)**\n\n- Notes\n  - NanaZip 3.0 and onwards will have two distribution flavors called NanaZip\n    and NanaZip Classic. But NanaZip 3.0 does not have the Classic flavor yet\n    because it's not ready. Read\n    https://github.com/M2Team/NanaZip#differences-between-nanazip-and-nanazip-classic\n    for more information.\n  - The 32-bit x86 support for NanaZip packaged version is removed because\n    supported 32-bit x86 Windows versions don't support running on 32-bit\n    only x86 processors.\n  - NanaZip 3.0 and onwards will have NanaZip Sponsor Edition. Read\n    https://github.com/M2Team/NanaZip/blob/main/Documents/SponsorEdition.md\n    for more information.\n  - NanaZip has introduced the Preinstall Support. Read\n    https://github.com/M2Team/NanaZip/issues/398 for more information.\n- Features\n  - Introducing dark mode support for all GUI components.\n  - Introducing the Mica support. You will enjoy the full window immersive Mica\n    support for all GUI components if you are using dark mode with HDR disabled.\n    (Thanks to Andarwinux.)\n  - Synchronize the 7-Zip mainline implementations to 24.05.\n    (https://github.com/ip7z/7zip/releases/tag/24.05) (Thanks to Igor Pavlov.\n    Noticed by AVMLOVER-4885955 and PopuriAO29.)\n    - Make NanaZip Self Extracting Executable stubs use 7-Zip mainline\n      Zstandard decoder instead of Zstandard official's for reducing the\n      size for binaries.\n    - Use 7-Zip mainline Zstandard decoder instead of Zstandard official\n      decoder for NanaZip.Core project.\n    - Remove 7-Zip mainline XXH64 Hash handler for NanaZip.Core because we\n      have the xxHash-based implementation in NanaZip.Codecs. It will have\n      much better performance, especially for non-x86 targets.\n  - Implement the new toolbar and use it to replace the old menubar and old\n    toolbar.\n  - Refresh the UI layout for About Dialog via following other Nana series\n    project design.\n  - Add the SM3 HASH algorithm from GmSSL. (https://github.com/guanzhi/GmSSL)\n- Improvements\n  - Rewrite and split the implementation of the Core Library and the Self\n    Extracting Executable to the separate NanaZip.Codecs and NanaZip.Core\n    projects. Read https://github.com/M2Team/NanaZip/issues/336 for more\n    information.\n  - Ensure the implementation of Core Library and the Self Extracting Executable\n    supports Windows Vista RTM (Build 6000.16386).\n  - Reduce the binary size for the Self Extracting Executables.\n  - Synchronize the 7-Zip ZS implementations to the latest master branch.\n    (https://github.com/mcmilk/7-Zip-zstd/commit/79b2c78e9e7735ddf90147129b75cf2797ff6522)\n  - Synchronize Zstandard and builtin xxHash implementations to v1.5.6.\n    (https://github.com/facebook/zstd/releases/tag/v1.5.6)\n  - Synchronize Brotli implementations to v1.1.0.\n    (https://github.com/google/brotli/releases/tag/v1.1.0)\n  - Synchronize the RHash implementation to the latest master branch which is\n    after v1.4.4.\n    (https://github.com/rhash/RHash/commit/d916787590b9dc57eb9d420fd13e469160e0b04c)\n  - Synchronize the BLAKE3 implementation to latest master which is after 1.5.1.\n    (https://github.com/BLAKE3-team/BLAKE3/commit/0816badf3ada3ec48e712dd4f4cbc2cd60828278)\n  - Update to Git submodule version of Mile.Project.Windows.\n    (https://github.com/ProjectMile/Mile.Project.Windows)\n  - Update Mile.Windows.Helpers to 1.0.558.\n    (https://github.com/ProjectMile/Mile.Windows.Helpers/tree/1.0.558.0)\n  - Update Mile.Xaml to 2.2.944.\n    (https://github.com/ProjectMile/Mile.Xaml/releases/tag/2.2.944.0)\n  - Use Mile.Windows.Internal package.\n    (https://github.com/ProjectMile/Mile.Windows.Internal)\n  - Use Mile.Detours package.\n    (https://github.com/ProjectMile/Mile.Detours)\n  - Use modern IFileDialog for folder picker dialog. (Contributed by \n    reflectronic.)\n  - Launch directly to the settings page of association for NanaZip.\n    (Contributed by AndromedaMelody.)\n  - Show NanaZip in Drives' ContextMenu. (Contributed by AndromedaMelody.)\n  - Sync file extension support from https://github.com/mcmilk/7-Zip-zstd.\n  - Add other methods to compression dialog.\n    (https://github.com/mcmilk/7-Zip-zstd/commit/cf29d0c1babcd5ddf2c67eda8bb36e11f9c643b9)\n  - Reorder initialization in constructor matching to member declaration order.\n    (https://github.com/mcmilk/7-Zip-zstd/commit/8b011d230f1ccd8990943bd2eaad38d70e6e3fdf)\n  - Fix selectable uppercase / lowercase hash formatting.\n    (https://github.com/mcmilk/7-Zip-zstd/commit/4fae369d2d6aa60e2bb45eea1fb05659a2599caa)\n  - Update russian translation. (Contributed by Blueberryy.)\n  - Update Polish translation. (Contributed by ChuckMichael.)\n  - Add mitigation policy of disabling child process creation for command line\n    version of NanaZip. (Contributed by dinhngtu.)\n  - Add Explorer Patcher DLL blocking for NanaZip File Manager for reenabling\n    mitigation policy of blocking loading unexpected libraries from remote\n    sources at runtime for the main thread of NanaZip File Manager without the\n    stability issues. (Contributed by dinhngtu.)\n- Fixes\n  - Fix issue in IEnumExplorerCommand::Next for shell extension. (Thanks to\n    cnbluefire.)\n- Other adjustments for project development.\n\n**NanaZip 2.0 Update 1 (2.0.450.0)**\n\n- Optimize NanaZip binaries via adjusting the WindowsTargetPlatformMinVersion\n  to 10.0.19041.0 in all packaged NanaZip binaries projects except the Self\n  Extracting Executable stubs projects.\n- Opt out of dynamic code mitigation on main NanaZip thread for resolving the\n  compatibility issues with Explorer Patcher. (Contributed by dinhngtu.)\n- Update Mile.Xaml to 1.1.434.\n  (https://github.com/ProjectMile/Mile.Xaml/releases/tag/1.1.434.0)\n- Update Mile.Windows.Helpers to 1.0.8.\n  (https://github.com/ProjectMile/Mile.Windows.Helpers/commits/main)\n- Add dark mode support for context menus.\n- Refresh the about dialog with Windows 11 XAML control styles and the \n  immersive Mica effects.\n- Fix model dialog style behavior for About dialog.\n- Continue to refresh application and file type icons. (Designed by \n  Shomnipotence.)\n\n**NanaZip 2.0 (2.0.396.0)**\n\n- Notes\n  - Update the minimum system requirement to Windows 10 Version 2004 (Build \n    1)     or later for solving issues in the XAML Islands.\n  - Add instructions for installing NanaZip for all users. (Contributed by\n    AndromedaMelody. Suggested by Wolverine1977.)\n- Features\n  - Integrate the following HASH algorithms to NanaZip from RHash (AICH, \n    BLAKE2b, BTIH, ED2K, EDON-R 224, EDON-R 256, EDON-R 384, EDON-R 512, \n    GOST R 34.11-94, GOST R 34.11-94 CryptoPro, GOST R 34.11-2012 256, \n    GOST R 34.11-2012 512, HAS-160, RIPEMD-160, SHA-224, SHA3-224, SHA3-256, \n    SHA3-384, SHA3-512, Snefru-128, Snefru-256, Tiger, Tiger2, TTH, Whirlpool) \n    and xxHash (XXH3_64bits, XXH3_128bits).\n  - Allow NanaZip to be associated with any file type. (Contributed by \n    manfromarce.)\n  - Add hfsx to file type association. (Suggested by AndromedaMelody.)\n- Improvements\n  - Refresh application and file type icons. (Designed by Shomnipotence.)\n  - Refresh the about dialog with XAML Islands.\n  - Update 7-Zip to 22.01. (https://www.7-zip.org/history.txt) (Thanks to Igor \n    Pavlov. Noticed by HylianSteel, Random-name-hi and DJxSpeedy.)\n  - Update Zstandard to 1.5.2. \n    (https://github.com/facebook/zstd/releases/tag/v1.5.2).\n  - Update BLAKE3 to 1.3.1.\n    (https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.3.1)\n  - Update LZ4 to 1.9.4. (https://github.com/lz4/lz4/releases/tag/v1.9.4)\n  - Enable Control Flow Guard (CFG) to all target binaries for mitigating ROP \n    attacks. (Contributed by dinhngtu.)\n  - Mark all x86 and x64 target binaries as compatible with Control-flow \n    Enforcement Technology (CET) Shadow Stack. (Contributed by dinhngtu.)\n  - Strict handle checks at runtime to block the use of invalid handles. \n    (Contributed by dinhngtu.)\n  - Disable dynamic code generation in Release builds prevents generating \n    malicious code at runtime. (Contributed by dinhngtu. Thanks to \n    AndromedaMelody.)\n  - Block loading unexpected libraries from remote sources at runtime.\n    (Contributed by dinhngtu.)\n  - Enable Package Integrity Check. (Contributed by AndromedaMelody.)\n  - Enable EH Continuation Metadata. (Suggested by dinhngtu. Thanks to \n    mingkuang.)\n  - Enable Signed Returns.\n  - Add Mile.Xaml to NanaZip project.\n  - Start adding prerequisite support for unpackaged mode.\n- Fixes\n  - Fix the shell extension issue which cause Everything crashed. (Thanks to \n    No5972, startkkkkkk, SakuraNeko, bfgxp and riverar.)\n  - Improve the Per-Monitor DPI Awareness support in Windows 10 Version 1607 \n    for Self Extracting Executable stubs.\n  - Fix line break issue for i18n resource files. (Thanks to ygjsz.)\n  - Generate resource identities for package manifest manually. (Suggested by \n    AndromedaMelody.)\n  - Add workaround for NanaZip not appearing in classic context menu. \n    (Contributed by dinhngtu.)\n  - Check 7z compression parameter validity upon start of compression.\n    (Contributed by dinhngtu.)\n\n**NanaZip 1.2 (1.2.252.0)**\n\n- Fix no ordinal 345 was found in the dynamically attached library issue in \n  Self Extracting Executables. (Thanks to FadeMind.)\n- Add Per-Monitor DPI-Aware support for all GUI components.\n- Adjust and simplify the compiler options for modernizing.\n- Fix i18n issue for the About dialog. (Thanks to AndromedaMelody.)\n- Update installation tutorial. (Suggested by AndromedaMelody.)\n- Fix cannot start editor issue when only store edition of notepad existed. \n  (Thanks to AndromedaMelody.)\n- Modernize the i18n implementation via migrating language files from .txt to \n  .resw. (Contributed by AndromedaMelody. Suggested by Maicol Battistini.)\n- Update ModernWin32MessageBox for solving the infinite loop issue in some \n  cases. (Thanks to AndromedaMelody.)\n- Tweak icons and provide icons for preview versions. (Designed by Alice \n  (四月天). Thanks to StarlightMelody.)\n- Fix crash issue when opening archive files. (Thanks to 1human and Maicol \n  Battistini.)\n- Remove Language page in Options dialog because NanaZip will follow the \n  language settings from Windows itself.\n- Fix the issue of the i18n implementation of File Type Association. \n  (Contributed by AndromedaMelody.)\n- Add i18n support for GUI edition of Self Extracting Executable. \n  (Contributed by AndromedaMelody.)\n\n**NanaZip 1.1 (1.1.194.0)**\n\n- Add assembly implementations from 7-Zip back for improving performance.\n- Reimplement the about dialog with Task Dialog.\n- Modernize the message boxes with Task Dialog. (Thanks to DJxSpeedy.)\n- Update 7-Zip to 21.07. (Thanks to Igor Pavlov. Noticed by HylianSteel.)\n- Update translations inherited from 7-Zip.\n- Update Deutsch translations. (Contributed by Hen Ry.)\n- Update Polish translation. (Contributed by ChuckMichael.)\n- Improve the multi volume rar file detection for solving \n  https://github.com/M2Team/NanaZip/issues/82. (Thanks to 1human.)\n- Simplify the file type association definitions and add the open verb for \n  them. (Thanks to Fabio286.)\n- Fix CI issue.\n- Update VC-LTL to 5.0.4.\n- Update C++/WinRT to 2.0.211028.7.\n\n**NanaZip 1.0 (1.0.95.0)**\n\n- Modernize the build toolchain with MSBuild for using MSIX packaging and \n  parallel compilation support. (Thanks to AndromedaMelody, be5invis, \n  青春永不落幕 and oxygen-dioxide.)\n- Use [VC-LTL 5.x](https://github.com/Chuyu-Team/VC-LTL5) toolchain to make the\n  binary size even smaller than the official 7-Zip because we can use \n  ucrtbase.dll directly and the optimizations from modern compile toolchain.\n  (Thanks to mingkuang.)\n- Add the context menu support in Windows 10/11 File Explorer. (Thanks to \n  shiroshan.)\n- New icons. (Designed by Alice (四月天), Chi Lei, Kenji Mouri, Rúben Garrido \n  and Sakura Neko. Thanks to AndromedaMelody and 奕然.)\n- Minor tweaks. (Thanks to adrianghc, Blueberryy, ChuckMichael, Legna, Maicol \n  Battistini, SakuraNeko and Zbynius.)\n- Update 7-Zip from 21.03 to 21.06. (Noticed by Dan, lychichem and sanderdewit.\n  Thanks to Igor Pavlov.)\n- Enable parsing the NSIS script support in the NSIS archives. (Suggested by \n  alanfox2000. Thanks to myfreeer.)\n- Merge features from 7-Zip ZStandard branch. (Suggested by fcharlie. Thanks to\n  Tino Reichardt.)\n"
  },
  {
    "path": "Documents/ReleaseNotesPreview.md",
    "content": "﻿# NanaZip Preview Release Notes\n\nFor stable versions, please read [NanaZip Release Notes](ReleaseNotes.md).\n\n**NanaZip 6.5 Preview (6.5.16xx.0)**\n\n- Includes all the improvements from NanaZip 6.0 Update 2 (6.0.1650.0).\n- Introduce XAML XAML copy location dialog. (Contributed by dongle-the-gadget.)\n\n**NanaZip 6.5 Preview (6.5.1638.0)**\n\nThis release includes all the improvements from NanaZip 6.0 Update 1\n(6.0.1638.0).\n\n**NanaZip 6.0 Final (6.0.1630.0)**\n\n- Start to provide the official portable binaries package of NanaZip with both\n  Modern and Classic flavors, except the NanaZip File Manager.\n- Fix several crash issues for the .NET Single File Application bundle readonly\n  support. (Thanks to haaeein.)\n- Fix several hang issues for the ROMFS file system image readonly support\n  support. (Contributed by dinhngtu. Thanks to haaeein.)\n- Fix several issues for context menu support. (Contributed by dinhngtu.)\n- Synchronize 7-Zip mainline implementations to 26.00. (Except the NanaZip File\n  Manager.) (Thanks to Igor Pavlov. Noticed by FadeMind.)\n- Improve the address bar UI layout. (Cooperated with dinhngtu. Suggested by\n  VinaC2.)\n- Make the splitter bar fully white to workaround the light mode UI visual\n  issues in the 2 Panels mode.\n- Fix the splitter bar cannot have Mica in the dark mode.\n- Add the dark mode support for Win32 task dialog.\n- Use Win32 TaskDialog to implement the Folders History dialog to simplify the\n  implementation.\n- Introduce Group Policy Administrative Template (ADMX/ADML) for NanaZip.\n  (Contributed by dinhngtu.)\n- Update Dutch translation. (Contributed by Stephan-P.)\n- Synchronize the NanaZip File Manager implementations between NanaZip (Modern)\n  and NanaZip Classic.\n- Fix some potential issues for the dark mode support.\n- Try to partially improve the NanaZip File Manager main window keyboard\n  navigation experience.\n- Update Mile.Project.Configurations to 1.0.1917, which solve some issues for\n  using NuGet Package References Support in Visual Studio 2026 version 18.3 or\n  later. (Cooperated by AndromedaMelody.)\n- Update Mile.Windows.Internal to 1.0.3515.\n- Update Mile.Xaml to 2.5.1616.\n- Add RestoreNuGetPackages.cmd script to workaround some issues for people who\n  want to use Visual Studio to build NanaZip without running BuildAllTargets.bat\n  script.\n \n**NanaZip 6.0 Preview 2 (6.0.1621.0)**\n\n- Introduce NanaZip.Universal.Windows project for making NanaZip Command Line\n  Interface (Windows) for both NanaZip (Modern) and NanaZip Classic a.k.a.\n  NanaZipG or K7G to synchronize to the latest 7-Zip mainline and 7-Zip ZS\n  implementations.\n- Introduce NanaZip Platform Base Library (K7Base) and NanaZip Platform User\n  Library (K7User) to replace NanaZip Platform Abstraction Layer (K7Pal) and\n  NanaZip.Frieren for better code sharing and maintainability.\n- Redesign the security mitigation policies settings support (followed some\n  suggestions from dongle-the-gadget), also introduces several new security\n  mitigation policies like the archive handler and codec handler restriction\n  (which is contributed by dinhngtu). Read\n  https://github.com/M2Team/NanaZip/blob/main/Documents/Policies.md for more\n  information.\n- Backport CVE-2025-0411 and CVE-2025-11001 for the NanaZip File Manager which\n  still use the old 7-Zip mainline codebase. (Contributed by dinhngtu.)\n- Set the LOAD_LIBRARY_SEARCH_SYSTEM32 dependent load flag on Release builds of\n  Self Extracting Executables stubs to mitigate static imports level DLL\n  planting attack on Windows 10 build 14393 and later. (Contributed by\n  dinhngtu.)\n- Allow to associate more file types to NanaZip. (Contributed by manfromarce.)\n- Enable Ctrl+Backspace on edit fields using SHAutoComplete. (Contributed by\n  dinhngtu.)\n- Fix the flickering issues when selecting list view in dark mode.\n- Make texts have better contrast in dark mode.\n- Make FastLZMA2 and Lizard reuse partial Zstandard implementations.\n- Fix crash issue when using NanaZip.Core.Setup.sfx.\n  (https://github.com/M2Team/NanaZip/issues/795) (Thanks to kbarnes3.)\n- Fix flickering XAML dialogs. (Contributed by dongle-the-gadget.)\n- Fix crash issue from XAML address bar. (Contributed by dongle-the-gadget.)\n- Use a low name as the shell extension name prefix to work around our context\n  menu not appearing in the classic context menu. (Contributed by dinhngtu.)\n- Don't reset compression method after changing level. (Contributed by\n  dongle-the-gadget.)\n- Fix text overflow in German translation. (Contributed by Pinguin2001.)\n- Localize Open Inside menu text. (Contributed by dinhngtu.)\n- Remove Help button from compress option dialogs. (Contributed by peashooter2.)\n- Fix UI assignment of WriteZone setting. (Contributed by dinhngtu.)\n- Handle Add button when inside archives. (Contributed by dinhngtu.)\n- Use assembly hardware acceleration for BLAKE3 implementation.\n- Fix issues for NanaZip Preview SVG icon assets for Contrast Black mode.\n- Update the icon assets with optimized assets to reduce the binary size.\n- Don't contain Mile.Project.Wap.Unstaged.targets in the MSIX package.\n- Synchronize 7-Zip mainline implementations to 25.01 for NanaZip components\n  which still use the old 7-Zip mainline codebase (command line version).\n  (Thanks to Igor Pavlov.)\n- Synchronize the 7-Zip ZS implementations to\n  https://github.com/mcmilk/7-Zip-zstd/tree/5766dd7745f6517f7ea42f6de9a190dfd92aa25f.\n  (Except the NanaZip File Manager.) (Thanks to Sergey G. Brester and Tino\n  Reichardt.)\n- Synchronize Brotli implementations to v1.2.0.\n  (https://github.com/google/brotli/releases/tag/v1.2.0)\n- Synchronize the FastLZMA2 implementations to\n  https://github.com/conor42/fast-lzma2/tree/a793db99fade2957d2453035390f97e573acecb2,\n  which can fix some issues. (Contributed by dinhngtu.)\n- Synchronize the BLAKE3 implementation to 1.8.3.\n  (https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.8.3)\n- Synchronize RHash to the latest master\n  (https://github.com/rhash/RHash/tree/b76c6a3312422c09817c2cef40442b2f2d9d4689)\n  which is after v1.4.6.\n- Update Mile.Project.Configurations to 1.0.1827.\n- Update Mile.Mobility to 1.0.372.\n- Update Mile.Project.Helpers to 1.0.975.\n- Update Mile.Windows.Helpers to 1.0.1171.\n- Update Mile.Detours to 1.0.2180.\n- Update .NET projects to .NET 10 and update NuGet package dependencies.\n- Add Release Tags to NanaZip Versioning.\n- Migrate solution from sln to slnx, and start to build with MSVC 14.50 toolset.\n- Support opening NanaZip Visual Studio solution without installing WinUI\n  application and/or Universal Windows Platform development workload.\n  (Contributed by AndromedaMelody.)\n- Make the precompiled build tools generated by GitHub Actions workflow\n  automatically.\n- Improve several implementations and fix several issues.\n\n**NanaZip 6.0 Preview 1 (6.0.1461.0)**\n\n- Start to transition to community driven development model.\n- Introduce extract-on-open feature. (Contributed by dinhngtu.)\n  - To disable this temporarily, hold Shift while opening the file.\n  - To disable this permanently, go to Settings, Integration tab, and disable\n    \"Extract on open\" at the bottom.\n- Introduce formal version of contributing guide and security policies.\n  (Cooperated with dinhngtu and dongle-the-gadget.)\n- Update system requirement to Windows 10, version 2004 (Build 19041) or later,\n  and remove the x86 (32-bit) for all components.\n- Start to use Zstandard decoder instead of 7-Zip mainline's implementation for\n  better reliability, especially it can reduce more potential vulnerabilities.\n- Introduce the XAML-based address bar. (Contributed by dongle-the-gadget.)\n- Introduce the XAML-based status bar. (Contributed by dongle-the-gadget.)\n- Introduce the XAML-based properties and information dialog. (Contributed by\n  dongle-the-gadget.)\n- Introduce the XAML-based progress dialog. (Contributed by dongle-the-gadget.)\n- Improve the Smart Extraction feature. (Contributed by R-YaTian.)\n- Introduce extract all automatically policy when opening executable files in\n  archives. (Contributed by MajThomas.)\n- Introduce the environment variable parsing support for address bar. (Thanks to\n  dongle-the-gadget's huge help.)\n- Improve the NanaZip startup performance by initializing the StoreContext\n  later. (Contributed by dongle-the-gadget.)\n- Add support for CBR and CBZ file associations. (Contributed by dinhngtu.)\n- Add support for ASAR file association. (Contributed by dongle-the-gadget.)\n- Display file system version in archive property window for the UFS/UFS2 file\n  system image readonly support.\n- Display bundle version in archive property for the .NET Single File\n  Application bundle readonly support.\n- Display file system version in archive property for the littlefs file system\n  image readonly support.\n- Fix the parsing padding issue for Electron Archive (asar) readonly support.\n  (Contributed by Vlad-Andrei Popescu).\n- Improve the ZealFS file system image readonly support implementation to fix\n  several issues. (Cooperated with Zeal 8-bit.)\n- Try to bring dialog window to the foreground to resolve user experience issues\n  when opened from context menu. (Contributed by dinhngtu.)\n- Move open folder checkbox to extract dialog. (Contributed by dinhngtu.)\n- Introduce registry settings for Mark of the Web (MoTW) enforcement policies.\n  (Contributed by dinhngtu.)\n- Improve the dynamic library block list for resolving compatibility issues.\n  (Contributed by dinhngtu.)\n- Introduce registry settings for disabling security mitigation policies, which\n  should be helpful for debugging and resolving compatibility issues.\n  (Contributed by dinhngtu.)\n- Fix dead loop issue when compressing files with Brotli, Lizard, LZ4 and LZ5\n  mentioned in https://github.com/M2Team/NanaZip/issues/639. (Thanks to\n  gigano01, InfiniteLoopGameDev and iOrange.)\n- Fix the unable to return the processed bytes count issue for\n  NanaZipCodecsReadInputStream.\n- Fix some string resources issues. (Contributed by dinhngtu.)\n- Fix issues in compression levels combobox. (Contributed by dongle-the-gadget.)\n- Update Albanian translation. (Contributed by F1219R.)\n- Update Hungarian translation. (Contributed by John Fowler.)\n- Update Greek translation. (Contributed by Lefteris T.)\n- Update German translation. (Contributed by HackZy01.)\n- Update Bengali translation. (Contributed by Sumon Kayal.)\n- Synchronize 7-Zip mainline implementations to 25.01. (Thanks to Igor Pavlov.\n  Noticed by FadeMind and Pinguin2001.)\n- Synchronize the 7-Zip ZS implementations to\n  https://github.com/mcmilk/7-Zip-zstd/tree/2a2dcb293b80180dc305544bf6a9e081750bccfe.\n  (Thanks to Sergey G. Brester and Tino Reichardt.)\n- Update Zstandard to v1.5.7. (Noticed by dcog989.)\n- Update Lizard to v2.1.\n- Synchronize the BLAKE3 implementation to 1.8.2. (Noticed by peashooter2.)\n- Synchronize the RHash implementation to latest master a.k.a.\n  https://github.com/rhash/RHash/commit/cce6c628f93d9ed332921656aa5e1750d12b8d3e\n  which is after v1.4.6.\n- Update Mile.Windows.Helpers to 1.0.952.\n- Update Mile.Windows.Internal to 1.0.3259.\n- Update Mile.Json to 1.0.1057.\n- Add littlefs v2.10.2 to NanaZip.Codecs for future development of work in\n  progress littlefs archive format readonly support.\n- Create NanaZip.Modern project for the modern user experience development.\n- Introduce Mile.Mobility dependence to NanaZip.Codecs project for making better\n  portability between NanaZip and AptxZip (a.k.a. NanaZip for POSIX).\n- Introduce NanaZip.ExtensionPackage project for future development of features\n  which need to be distributed as legacy installer. (Contributed by dinhngtu.)\n- Introduce Mile.Helpers.Portable.Base.Unstaged as the temporary infrastructure\n  to standardize some portable things in NanaZip.Codecs.\n- Introduce NanaZip.Codecs.Specification.Fat for adding definitions of FAT12,\n  FAT16 and FAT32.\n- Introduce NanaZip.Codecs.Specification.Zealfs for adding definitions of\n  ZealFS series file system. (Cooperated with Zeal 8-bit.)\n- Add littlefs v1 on-disk definitions to the littlefs file system image readonly\n  support.\n- Introduce Mile.Project.Wap.Unstaged.targets for solving the issue that\n  unnecessary XAML files contained in the final MSIX package.\n- Add XAML Styler indentation configuration. (Contributed by dongle-the-gadget.)\n- Use x-generate to define language resources in AppX manifest to solve the\n  Windows AppX language fallback issue. (Suggested by dongle-the-gadget.)\n- Update build binary logs when failed to build in GitHub Actions. (Contributed\n  by dongle-the-gadget.)\n- Introduce legacy string migrator. (Contributed by dongle-the-gadget.)\n- Add more targeted editorconfig rules. (Contributed by dongle-the-gadget.)\n- Move NanaZip.Core's NanaZip.Core.Console project to NanaZip.Universal's\n  NanaZip.Universal.Console project.\n- Disable WinRT metadata generation for all WinRT component consumers.\n- Move NanaZip.Modern as the first item to workaround the AppX toolchain\n  manifest generation issues.\n- Improve the GitHub Actions artifacts generation.\n- Update to Windows 11 SDK Build 26100 for NanaZipPackage.\n- Fix the source code file header comment format.\n- Use C++ zero initialization to reduce potential issues.\n- Introduce reproducible build support for the whole project.\n\n**NanaZip 5.1 Preview 0 (5.1.1263.0)**\n\nThis release includes all the improvements from NanaZip 5.0 Update 2\n(5.0.1263.0).\n\n**NanaZip 5.1 Preview 0 (5.1.1252.0)**\n\nThis release includes all the improvements from NanaZip 5.0 Update 1\n(5.0.1252.0).\n\n**NanaZip 5.0 Preview 2 (5.0.1243.0)**\n\n- Continue to improve the work-in-progress NanaZip Platform Abstraction Layer\n  (K7Pal). (https://github.com/M2Team/NanaZip/tree/main/K7Pal)\n  - Fix the crash and encrypted RAR5 format extraction wrong password issue for\n    7-Zip's hash algorithms wrappers which mentioned in\n    https://github.com/M2Team/NanaZip/issues/542. (Thanks to RuesanG.)\n  - Introduce K7PalHashDuplicate API.\n  - Remove K7PalHashReset API for improving the security.\n  - Reduce the saved information in hash contexts to improve the security.\n  - Use NanaZip Platform Abstraction Layer (K7Pal) to implement 7-Zip's SHA-1\n    hash algorithms.\n- Update zh-Hans and zh-Hant translations for 'Want * History' strings. \n  (Contributed by R-YaTian.) (Forget to mentioned in NanaZip 5.0 Preview 1.)\n- Adds a setting for opening the folder after extracting from archive.\n  (Contributing by DaxDupont.)\n- Introduce the Smart Extraction. (Contributed by R-YaTian.)\n- Fix the issue that which NanaZip windows and dialogs will be opened in the\n  background when using NanaZip from context menu. (Contributed by R-YaTian.)\n- Update xxHash to v0.8.3.\n  (https://github.com/Cyan4973/xxHash/releases/tag/v0.8.3)\n\n**NanaZip 5.0 Preview 1 (5.0.1215.0)**\n\n- Introduce NanaZip Platform Abstraction Layer (K7Pal) for wrapping the platform\n  specific infrastructures. (https://github.com/M2Team/NanaZip/tree/main/K7Pal)\n  (Work In Progress)\n  - Provide hash functions interfaces implemented with Windows CNG API. NanaZip\n    uses these hash functions from K7Pal:\n    - MD2\n    - MD4\n    - MD5\n    - SHA-1\n    - SHA-256\n    - SHA-384\n    - SHA-512\n    - ED2K (Implemented as the K7Pal MD4 wrapper in NanaZip.Codecs.)\n- Synchronize the 7-Zip mainline implementations to 24.09.\n  (https://github.com/ip7z/7zip/releases/tag/24.09) (Thanks to Igor Pavlov.\n  Noticed by FadeMind and peashooter2.)\n- Finally move NanaZip console version to NanaZip.Core project.\n- Don't fail ModernSHBrowseForFolderW when DefaultFolder cannot be set.\n  (Contributed by dinhngtu.)\n- Update Mile.Windows.UniCrt to 1.1.278.\n\n**NanaZip 5.0 Preview 0 (5.0.1188.0)**\n\n- This release includes all the improvements from NanaZip 3.1 (3.1.1080.0)\n  (https://github.com/M2Team/NanaZip/releases/tag/3.1.1080.0).\n- Update Brazilian Portuguese translation. (Contributed by maisondasilva.)\n- Make sure NanaZip Core (except the Self Extracting Executables) and NanaZip\n  Classic using ucrtbase.dll with 10.0.19041.0 version or later.\n- Update Mile.Windows.Helpers to 1.0.671.\n    (https://github.com/ProjectMile/Mile.Windows.Helpers/tree/1.0.671.0)\n- Move NanaZip console version to NanaZip.Core project. (Not used in NanaZip\n  MSIX package because we need to release the next preview to contain the\n  CVE-2024-11477 fix in NanaZip 3.1.)\n- Remove C++/WinRT dependency for NanaZip.Codecs and NanaZip.Frieren.\n- Add GetDpiForWindowWrapper for NanaZip.Frieren.DarkMode to fix the legacy\n  Windows compatibility issues.\n- Remove VC-LTL dependency for the Self Extracting Executables related projects.\n- Adjust the compilation configurations to optimize the binary size for the Self\n  Extracting Executables.\n- Use Mile.Windows.UniCrt (https://github.com/ProjectMile/Mile.Windows.UniCrt)\n  instead of VC-LTL.\n- Update NanaZip.Specification.SevenZip header file.\n- Start to simplify the NanaZip specific decoders and encoders implementation.\n- Synchronize the BLAKE3 implementation to 1.5.5.\n  (https://github.com/BLAKE3-team/BLAKE3/releases/tag/1.5.5)\n- Synchronize the RHash implementation to the latest master branch which is\n  after v1.4.5.\n  (https://github.com/rhash/RHash/commit/cf2adf22ae7c39d9b8e5e7b87222046a8f42b3dc)\n- Enable disabling child process creation for NanaZip Self Extracting\n  Executables. (Except installer mode of Self Extracting Executables, which\n  compiled binaries is not provided in the NanaZip MSIX package.)\n\n**NanaZip 3.5 Preview 0 (3.5.1000.0)**\n\nThis release includes all the improvements from NanaZip 3.0 Update 1\n(3.0.1000.0).\n\n**NanaZip 3.5 Preview 0 (3.5.996.0)**\n\nThis release includes all the improvements from NanaZip 3.0 (3.0.996.0).\n\n**NanaZip 3.0 Preview 0 (3.0.756.0)**\n\n- Rewrite and split the implementation of the Core Library and the Self\n  Extracting Executable to the separate NanaZip.Core project.\n- Ensure the implementation of Core Library and the Self Extracting Executable\n  supports Windows Vista RTM (Build 6000.16386).\n- Reduce the binary size for the Self Extracting Executables.\n- Synchronize the 7-Zip mainline implementations to 23.01.\n  (https://www.7-zip.org/history.txt)\n- Synchronize the 7-Zip ZS implementations to the latest master branch.\n  (https://github.com/mcmilk/7-Zip-zstd/commit/ce27b4a0d3a94313d256c3d077f1784baffb9eee)\n- Add the SM3 HASH algorithm from GmSSL.\n  (https://github.com/guanzhi/GmSSL)\n- Synchronize Zstandard and builtin xxHash implementations to v1.5.5.\n  (https://github.com/facebook/zstd/releases/tag/v1.5.5)\n- Synchronize Brotli implementations to v1.1.0.\n  (https://github.com/google/brotli/releases/tag/v1.1.0)\n- Synchronize the RHash implementation to the latest master branch.\n  (https://github.com/rhash/RHash/commit/b8c91ea6551e99e10352386cd46ea26973bb4a4d)\n- Update to Git submodule version of Mile.Project.Windows.\n  (https://github.com/ProjectMile/Mile.Project.Windows)\n- Update Mile.Windows.Helpers to 1.0.15.\n  (https://github.com/ProjectMile/Mile.Windows.Helpers/commit/b522a956f7dd42dc205869d362f96a777bcb2aa0)\n- Update Mile.Xaml to 2.1.661.\n  (https://github.com/ProjectMile/Mile.Xaml/releases/tag/2.1.661.0)\n- Update russian translation. (Contributed by Blueberryy.)\n- Fix the text wrapping issue in the About dialog. (Thanks to MenschenToaster.)\n- Use modern IFileDialog for folder picker dialog. (Contributed by \n  reflectronic.)\n- Launch directly to the settings page of association for NanaZip. (Contributed\n  by AndromedaMelody.)\n- Show NanaZip in Drives' ContextMenu. (Contributed by AndromedaMelody.)\n- Sync file extension support from https://github.com/mcmilk/7-Zip-zstd.\n- Add other methods to compression dialog.\n  (https://github.com/mcmilk/7-Zip-zstd/commit/cf29d0c1babcd5ddf2c67eda8bb36e11f9c643b9)\n- Reorder initialization in constructor matching to member declaration order.\n  (https://github.com/mcmilk/7-Zip-zstd/commit/8b011d230f1ccd8990943bd2eaad38d70e6e3fdf)\n- Fix selectable uppercase / lowercase hash formatting.\n  (https://github.com/mcmilk/7-Zip-zstd/commit/4fae369d2d6aa60e2bb45eea1fb05659a2599caa)\n- Other adjustments for project development.\n\n**NanaZip 2.1 Preview 0 (2.1.451.0)**\n\n- Update icons. (Designed by Shomnipotence. Updated in NanaZip 2.0 Stable.)\n- Add instructions for installing NanaZip for all users. (Updated in NanaZip\n  2.0 Stable.)\n- Add Mile.Xaml to NanaZip project. (Updated in NanaZip 2.0 Stable.)\n- Refresh the about dialog with XAML Islands. (Updated in NanaZip 2.0 Stable.)\n- Start adding prerequisite support for unpackaged mode. (Updated in NanaZip \n  2.0 Stable.)\n- Optimize NanaZip binaries via adjusting the WindowsTargetPlatformMinVersion\n  to 10.0.19041.0 in all packaged NanaZip binaries projects except the Self\n  Extracting Executable stubs projects. (Updated in NanaZip 2.0 Update 1.)\n- Opt out of dynamic code mitigation on main NanaZip thread for resolving the\n  compatibility issues with Explorer Patcher. (Contributed by dinhngtu. Updated\n  in NanaZip 2.0 Update 1.)\n- Update Mile.Xaml to 1.1.434. (Updated in NanaZip 2.0 Update 1.)\n  (https://github.com/ProjectMile/Mile.Xaml/releases/tag/1.1.434.0)\n- Update Mile.Windows.Helpers to 1.0.8. (Updated in NanaZip 2.0 Update 1.)\n  (https://github.com/ProjectMile/Mile.Windows.Helpers/commits/main)\n- Add dark mode support for context menus. (Updated in NanaZip 2.0 Update 1.)\n- Refresh the about dialog with Windows 11 XAML control styles and the \n  immersive Mica effects. (Updated in NanaZip 2.0 Update 1.)\n- Fix model dialog style behavior for About dialog. (Updated in NanaZip 2.0\n  Update 1.)\n- Continue to refresh application and file type icons. (Designed by \n  Shomnipotence. Updated in NanaZip 2.0 Update 1.)\n\n**NanaZip 2.0 Preview 2 (2.0.376.0)**\n\n- Update 7-Zip to 22.01. (Thanks to Igor Pavlov. Noticed by HylianSteel, \n  Random-name-hi and DJxSpeedy.)\n- Add hfsx to file type association. (Suggested by AndromedaMelody.)\n- Update the minimum system requirement to Windows 10 Version 2004 (Build 19041)\n  or later for solving issues in the XAML Islands.\n- Update LZ4 to v1.9.4.\n- Enable Package Integrity. (Contributed by AndromedaMelody.)\n- Don't enable \"Disable dynamic code generation\" mitigation in Debug builds for\n  solving codec load error issue. (Thanks to AndromedaMelody.)\n- Continue to enable several security mitigations.\n  - Enable EH Continuation Metadata.\n  - Enable Signed Returns.\n- Generate resource identities for package manifest manually. (Suggested by \n  AndromedaMelody.)\n- Add workaround for NanaZip not appearing in classic context menu. \n  (Contributed by dinhngtu.)\n- Check 7z compression parameter validity upon start of compression.\n  (Contributed by dinhngtu.)\n- Update icons. (Designed by Shomnipotence.)\n\n**NanaZip 2.0 Preview 1 (2.0.313.0)**\n\n- Fix the shell extension issue which cause Everything crashed. (Thanks to \n  No5972, startkkkkkk, SakuraNeko, bfgxp and riverar.)\n- Allow NanaZip to be associated with any file type. (Contributed by \n  manfromarce.)\n- Update 7-Zip to 22.00. (Thanks to Igor Pavlov. Noticed by HylianSteel.)\n- Integrate the following HASH algorithms to NanaZip from RHash and xxHash.\n  - AICH\n  - BLAKE2b\n  - BTIH\n  - ED2K\n  - EDON-R 224, EDON-R 256, EDON-R 384, EDON-R 512\n  - GOST R 34.11-94, GOST R 34.11-94 CryptoPro\n  - GOST R 34.11-2012 256, GOST R 34.11-2012 512\n  - HAS-160, RIPEMD-160\n  - SHA-224\n  - SHA3-224, SHA3-256, SHA3-384, SHA3-512\n  - Snefru-128, Snefru-256\n  - Tiger, Tiger2\n  - TTH\n  - Whirlpool\n  - XXH3_64bits, XXH3_128bits\n- Update Zstandard to 1.5.2.\n- Update BLAKE3 to 1.3.1.\n- Improve the Per-Monitor DPI Awareness support in Windows 10 Version 1607 for\n  Self Extracting Executable stubs.\n- Fix line break issue for i18n resource files. (Thanks to ygjsz.)\n- Enable several security mitigations. (Contributed by dinhngtu.)\n  - Enable Control Flow Guard (CFG) to all target binaries for mitigating ROP \n    attacks.\n  - Mark all x86 and x64 target binaries as compatible with Control-flow \n    Enforcement Technology (CET) Shadow Stack.\n  - Strict handle checks at runtime to block the use of invalid handles.\n  - Disable dynamic code generation prevents generating malicious code at\n    runtime.\n  - Block loading unexpected libraries from remote sources at runtime.\n\n**NanaZip 1.2 Update 1 Preview 1 (1.2.253.0)**\n\n- Fix the issue of the i18n implementation of File Type Association. \n  (Contributed by AndromedaMelody. Updated in NanaZip 1.2 Stable.)\n- Add i18n support for GUI edition of Self Extracting Executable. \n  (Contributed by AndromedaMelody. Updated in NanaZip 1.2 Stable.)\n\n**NanaZip 1.2 Preview 4 (1.2.225.0)**\n\n- Continue to update ModernWin32MessageBox for solving the infinite loop issue\n  in some cases. (Thanks to AndromedaMelody.)\n- Fix crash issue when opening archive files. (Thanks to 1human and Maicol \n  Battistini.)\n- Remove Language page in Options dialog because NanaZip will follow the \n  language settings from Windows itself.\n\n**NanaZip 1.1 Servicing Update 1 Preview 3 (1.1.220.0)**\n\n- Modernize the i18n implementation via migrating language files from .txt to \n  .resw. (Contributed by AndromedaMelody. Suggested by Maicol Battistini.)\n- Update ModernWin32MessageBox for solving the infinite loop issue in some \n  cases. (Thanks to AndromedaMelody.)\n- Tweak icons and provide icons for preview versions. (Designed by Alice \n  (四月天). Thanks to StarlightMelody.)\n\n**NanaZip 1.1 Servicing Update 1 Preview 2 (1.1.201.0)**\n\n- Fix no ordinal 345 was found in the dynamically attached library issue in \n  Self Extracting Executables. (Thanks to FadeMind.)\n- Add Per-Monitor DPI-Aware support for all GUI components.\n- Adjust and simplify the compiler options for modernizing.\n- Fix i18n issue for the About dialog. (Thanks to AndromedaMelody.)\n- Update installation tutorial. (Suggested by AndromedaMelody.)\n- Fix cannot start editor issue when only store edition of notepad existed. \n  (Thanks to AndromedaMelody.)\n\n**NanaZip 1.1 Servicing Update 1 Preview 1 (1.1.196.0)**\n\n- Simplify the file type association definitions and add the open verb for \n  them. (Thanks to Fabio286. Fixed in NanaZip 1.1 Stable.)\n- Update VC-LTL to 5.0.4. (Updated in NanaZip 1.1 Stable.)\n\n**NanaZip 1.1 Preview 2 (1.1.153.0)**\n\n- Fix the issue which can't load context menu properly. (Thanks to DJxSpeedy.)\n\n**NanaZip 1.1 Preview 2 (1.1.152.0)**\n\n- Reimplement the about dialog with Task Dialog.\n- Update Deutsch translations. (Contributed by Hen Ry.)\n- Add assembly implementations from 7-Zip back for improving performance.\n- Update translations inherited from 7-Zip.\n- Update 7-Zip to 21.07. (Thanks to Igor Pavlov. Noticed by HylianSteel.)\n- Improve the multi volume rar file detection for solving \n  https://github.com/M2Team/NanaZip/issues/82. (Thanks to 1human.)\n- Modernize the message boxes with Task Dialog.\n\n**NanaZip 1.1 Preview 1 (1.1.101.0)**\n\n- Exclude .webp in the archive file type list for solving \n  https://github.com/M2Team/NanaZip/issues/57. (Thanks to Zbynius. Fixed in \n  NanaZip 1.0 Stable.)\n- Update Polish translation. (Contributed by ChuckMichael.)\n- Fix CI issue.\n- Update VC-LTL to 5.0.3.\n- Update C++/WinRT to 2.0.211028.7.\n\n**NanaZip 1.0 Preview 4 (1.0.88.0)**\n\n- Update Italian, Russian and Polish Translations. (Contributed by Blueberryy, \n  Maicol Battistini and ChuckMichael.)\n- Provide 7-Zip execution alias for helping users to migrate to NanaZip. \n  (Suggested by AndromedaMelody.)\n- Adjust file association icon. (Suggested by 奕然.)\n- Merge features from 7-Zip ZStandard branch. (Suggested by fcharlie. Thanks to\n  Tino Reichardt.)\n- Update 7-Zip to 21.06. (Noticed by Dan, lychichem and sanderdewit. Thanks to \n  Igor Pavlov.)\n- Fix compression level display issue in the compress dialog. (Thanks to \n  SakuraNeko.)\n- Make every file extension have own file type in file type association\n  definitions for solving https://github.com/M2Team/NanaZip/issues/53. (Thanks \n  to oxygen-dioxide.)\n- Disable virtualization:ExcludedDirectories for resolve \n  https://github.com/M2Team/NanaZip/issues/34. (Thanks to AndromedaMelody.)\n- Reduce the compilation warnings.\n- Change the configuration for NanaZipPackage project for solve the issue when\n  referencing the Windows Runtime Components.\n- Update Mile.Cpp.\n\n**NanaZip 1.0 Preview 3 (1.0.46.0)**\n\n- Enable parsing the NSIS script support in the NSIS archives. (Suggested by \n  alanfox2000. Thanks to myfreeer.)\n- Simplify the separator layout in the context menu implementation.\n- Fix app still displays in folder context menu, resulting in empty entry \n  that doesn't do anything when no options that could interact. (Thanks to \n  shiroshan.)\n- Fix the application crash in some cases caused by some issues in the \n  exception handler implementation from VC-LTL 5.x. (Thanks to mingkuang.)\n- Update new icons. (Designed by Alice (四月天), Chi Lei, Kenji Mouri, Rúben\n  Garrido and Sakura Neko.)\n- Make main NanaZip package contains all resources.\n- Fix the command line help string. (Thanks to adrianghc.)\n\n**NanaZip 1.0 Preview 2 (1.0.31.0)**\n\n- Remove IObjectWithSite in shell extension implementation to reduce the \n  complexity and crashes.\n- Add altform-lightunplated assets for display the contrast standard mode icon\n  in the taskbar instead of contrast white icon. (Thanks to AndromedaMelody.)\n- Remove Windows.Universal TargetDeviceFamily for solving the minimum OS \n  requirements display issue. (Thanks to 青春永不落幕.)\n- Enable NanaZipC and NanaZipG in AppX manifest. (Thanks to be5invis.)\n- Change \"The operation can require big amount of RAM (memory)\" error dialog to\n  warning dialog. (Thanks to Legna.)\n\n**NanaZip 1.0 Preview 1 (1.0.25.0)**\n\n- Modernize the build toolchain with MSBuild for using MSIX packaging and \n  parallel compilation support.\n- Use [VC-LTL 5.x](https://github.com/Chuyu-Team/VC-LTL5) toolchain to make the\n  binary size even smaller than the official 7-Zip because we can use \n  ucrtbase.dll directly and the optimizations from modern compile toolchain.\n- Add the context menu support in Windows 10/11 File Explorer.\n- New icons and minor UI tweaks.\n"
  },
  {
    "path": "Documents/Section508/NanaZip.html",
    "content": "<!doctype HTML><html lang=\"en\"><head><title>NanaZip Accessibility Conformance Report</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta charset=\"utf-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"></head><body id=\"openACR\"><style>body#openACR {\n      padding-left: 35px;\n    }\n    h2,\n    h3 {\n      position: relative;\n    }\n    h2 a.header-anchor,\n    h3 a.header-anchor {\n      position: absolute;\n      left: -2rem;\n    }\n    h2 a.header-anchor:hover svg,\n    h2 a.header-anchor:focus svg,\n    h2 a.header-anchor:focus-within svg,\n    h3 a.header-anchor:hover svg,\n    h3 a.header-anchor:focus svg,\n    h3 a.header-anchor:focus-within svg {\n      fill: #0000EE;\n      opacity: 1;\n    }\n    h2 a.header-anchor svg,\n    h3 a.header-anchor svg {\n      width: 28px;\n      height: 28px;\n      opacity: .3;\n    }\n    @media all and (max-width: 63.99em) {\n      h2 a.header-anchor,\n      h3 a.header-anchor {\n        position:relative;\n        opacity: 1;\n        left: 0;\n        vertical-align: top\n      }\n    }\n    a.header-anchor {\n      opacity: 0.4;\n      font-size: small;\n      text-decoration: none;\n      position: relative;\n      /* left: 20px; */\n      -webkit-transition: opacity 1s, font-size 1s;\n      -moz-transition: opacity 1s, font-size 1s;\n      -o-transition: opacity 1s, font-size 1s;\n      transition: opacity 1s, font-size 1s;\n    }\n    a.header-anchor:focus,a.header-anchor:hover {\n      text-decoration: underline;\n      font-size: large;\n      opacity: 1\n    }\n    .visuallyhidden {\n      border: 0;\n      clip: rect(0 0 0 0);\n      clip-path: inset(50%);\n      height: 1px;\n      margin: -1px;\n      overflow: hidden;\n      padding: 0;\n      position: absolute;\n      width: 1px;\n      white-space: nowrap;\n      &.focusable {\n          &:active,\n          &:focus {\n              clip: auto;\n              clip-path: none;\n              height: auto;\n              margin: 0;\n              overflow: visible;\n              position: static;\n              width: auto;\n              white-space: inherit;\n          }\n      }\n    }</style> <main><div class=\"grid-container\"><h1 class=\"svelte-1nee40z\">NanaZip Accessibility Conformance Report</h1>\n\nBased on VPAT® 2.4 WCAG 2.1 and Revised Section 508 Edition <h2 id=\"name-of-product-version-download\" class=\"svelte-1y7sq6j\">Name of Product/Version <a href=\"#name-of-product-version-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  NanaZip  <h2 id=\"report-date-download\" class=\"svelte-1y7sq6j\">Report Dates and Version <a href=\"#report-date-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <ul><li>Report Date: 2026/2/25</li> <li>Last Modified Date: 2026/2/25</li> <li>Version: nanazip-1</li></ul> <h2 id=\"product-description-download\" class=\"svelte-1y7sq6j\">Product Description <a href=\"#product-description-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <p>NanaZip is an open source file archiver intended for the modern Windows experience, forked from the source code of well-known open source file archiver 7-Zip.</p>\n <h2 id=\"contact-information-download\" class=\"svelte-1y7sq6j\">Contact Information <a href=\"#contact-information-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>   <h3 id=\"author-download\" class=\"svelte-1y7sq6j\">Author Information <a href=\"#author-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3> <ul><li>Name: Kenji Mouri</li> <li>Company: M2-Team</li>  <li>Email: <a href=\"mailto:Kenji.Mouri@outlook.com\" target=\"_blank\">Kenji.Mouri@outlook.com <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li>  <li>Website: <a href=\"http://nanazip.org/\" target=\"_blank\">http://nanazip.org/ <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li></ul>  <h3 id=\"vendor-download\" class=\"svelte-1y7sq6j\">Vendor Information <a href=\"#vendor-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3> <ul><li>Name: Kenji Mouri</li> <li>Company: M2-Team</li>  <li>Email: <a href=\"mailto:Kenji.Mouri@outlook.com\" target=\"_blank\">Kenji.Mouri@outlook.com <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li>  <li>Website: <a href=\"http://nanazip.org/\" target=\"_blank\">http://nanazip.org/ <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li></ul>   <h2 id=\"applicable-standards-guidelines-download\" class=\"svelte-1y7sq6j\">Applicable Standards/Guidelines <a href=\"#applicable-standards-guidelines-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2> \nThis report covers the degree of conformance for the following accessibility standard/guidelines:\n\n<table border=\"1\" style=\"border-collapse: collapse\"><thead><tr><th>Standard/Guideline</th> \n      <th>Included In Report</th></tr></thead> <tbody><tr><td><a href=\"https://www.w3.org/TR/WCAG21/\" target=\"_blank\">Web Content Accessibility Guidelines 2.1 <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td><ul><li>Table 1: Success Criteria, Level A</li><li>Table 2: Success Criteria, Level AA</li><li>Table 3: Success Criteria, Level AAA</li></ul></td> </tr><tr><td><a href=\"https://www.access-board.gov/ict/\" target=\"_blank\">Revised Section 508 standards published January 18, 2017 and corrected January 22, 2018 <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td><ul><li>Chapter 3: Functional Performance Criteria (FPC)</li><li>Chapter 4: Hardware</li><li>Chapter 5: Software</li><li>Chapter 6: Support Documentation and Services</li></ul></td> </tr></tbody></table> <h2 id=\"terms-download\" class=\"svelte-1y7sq6j\">Terms <a href=\"#terms-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2> \nThe terms used in the Conformance Level information are defined as follows:\n<ul><li><strong>Supports</strong>: The functionality of the product has at least one method that meets the criterion without known defects or meets with equivalent facilitation.</li><li><strong>Partially Supports</strong>: Some functionality of the product does not meet the criterion.</li><li><strong>Does Not Support</strong>: The majority of product functionality does not meet the criterion.</li><li><strong>Not Applicable</strong>: The criterion is not relevant to the product.</li><li><strong>Not Evaluated</strong>: The product has not been evaluated against the criterion. This can be used only in WCAG 2.x Level AAA.</li></ul> <h2 id=\"wcag-2.1-download\" class=\"svelte-1y7sq6j\">WCAG 2.1 Report <a href=\"#wcag-2.1-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>   <h3 id=\"success_criteria_level_a-download\" class=\"svelte-1y7sq6j\">Table 1: Success Criteria, Level A <a href=\"#success_criteria_level_a-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>   <h3 id=\"success_criteria_level_aa-download\" class=\"svelte-1y7sq6j\">Table 2: Success Criteria, Level AA <a href=\"#success_criteria_level_aa-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>   <h3 id=\"success_criteria_level_aaa-download\" class=\"svelte-1y7sq6j\">Table 3: Success Criteria, Level AAA <a href=\"#success_criteria_level_aaa-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>  <h2 id=\"508-download\" class=\"svelte-1y7sq6j\">Revised Section 508 Report <a href=\"#508-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>   <h3 id=\"functional_performance_criteria-download\" class=\"svelte-1y7sq6j\">Chapter 3: Functional Performance Criteria (FPC) <a href=\"#functional_performance_criteria-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>  <table class=\"svelte-4eon1l\" border=\"1\" style=\"border-collapse: collapse\"><thead class=\"svelte-4eon1l\"><tr class=\"svelte-4eon1l\"><th class=\"svelte-4eon1l\">Criteria</th> \n      <th class=\"svelte-4eon1l\">Conformance Level</th> \n      <th class=\"svelte-4eon1l\">Remarks and Explanations</th></tr></thead> <tbody><tr class=\"result-row svelte-cn2gpq\" id=\"302.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.1\" target=\"_blank\">302.1 Without Vision <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.2\" target=\"_blank\">302.2 With Limited Vision <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.3\" target=\"_blank\">302.3 Without Perception of Color <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.4\" target=\"_blank\">302.4 Without Hearing <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.5-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.5\" target=\"_blank\">302.5 With Limited Hearing <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.6-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.6\" target=\"_blank\">302.6 Without Speech <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.7-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.7\" target=\"_blank\">302.7 With Limited Manipulation <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.8-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.8\" target=\"_blank\">302.8 With Limited Reach and Strength <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.9-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.9\" target=\"_blank\">302.9 With Limited Language, Cognitive, and Learning Abilities <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr></tbody></table> <h3 id=\"hardware-download\" class=\"svelte-1y7sq6j\">Chapter 4: Hardware <a href=\"#hardware-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>   <h3 id=\"software-download\" class=\"svelte-1y7sq6j\">Chapter 5: Software <a href=\"#software-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>  <table class=\"svelte-4eon1l\" border=\"1\" style=\"border-collapse: collapse\"><thead class=\"svelte-4eon1l\"><tr class=\"svelte-4eon1l\"><th class=\"svelte-4eon1l\">Criteria</th> \n      <th class=\"svelte-4eon1l\">Conformance Level</th> \n      <th class=\"svelte-4eon1l\">Remarks and Explanations</th></tr></thead> <tbody><tr class=\"result-row svelte-cn2gpq\" id=\"502.2.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.2.1\" target=\"_blank\">502.2.1 User Control of Accessibility Features <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.2.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.2.2\" target=\"_blank\">502.2.2 No Disruption of Accessibility Features <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.1\" target=\"_blank\">502.3.1 Object Information <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.2\" target=\"_blank\">502.3.2 Modification of Object Information <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.3\" target=\"_blank\">502.3.3 Row, Column, and Headers <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.4\" target=\"_blank\">502.3.4 Values <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.5-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.5\" target=\"_blank\">502.3.5 Modification of Values <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.6-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.6\" target=\"_blank\">502.3.6 Label Relationships <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.7-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.7\" target=\"_blank\">502.3.7 Hierarchical Relationships <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.8-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.8\" target=\"_blank\">502.3.8 Text <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.9-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.9\" target=\"_blank\">502.3.9 Modification of Text <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.10-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.10\" target=\"_blank\">502.3.10 List of Actions <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.11-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.11\" target=\"_blank\">502.3.11 Actions on Objects <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.12-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.12\" target=\"_blank\">502.3.12 Focus Cursor <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.13-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.13\" target=\"_blank\">502.3.13 Modification of Focus Cursor <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.14-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.14\" target=\"_blank\">502.3.14 Event Notification <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.4\" target=\"_blank\">502.4 Platform Accessibility Features <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.2\" target=\"_blank\">503.2 User Preferences <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.3\" target=\"_blank\">503.3 Alternative User Interfaces <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.4.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.4.1\" target=\"_blank\">503.4.1 Caption Controls <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.4.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.4.2\" target=\"_blank\">503.4.2 Audio Description Controls <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.2\" target=\"_blank\">504.2 Content Creation or Editing <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.2.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.2.1\" target=\"_blank\">504.2.1 Preservation of Information Provided for Accessibility in Format Conversion <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.2.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.2.2\" target=\"_blank\">504.2.2 PDF Export <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.3\" target=\"_blank\">504.3 Prompts <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.4\" target=\"_blank\">504.4 Templates <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr></tbody></table> <h3 id=\"support_documentation_and_services-download\" class=\"svelte-1y7sq6j\">Chapter 6: Support Documentation and Services <a href=\"#support_documentation_and_services-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>    <h2 id=\"repository-download\" class=\"svelte-1y7sq6j\">Repository <a href=\"#repository-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <a href=\"https://github.com/M2Team/NanaZip\" target=\"_blank\">https://github.com/M2Team/NanaZip <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a> <h2 id=\"feedback-download\" class=\"svelte-1y7sq6j\">Feedback <a href=\"#feedback-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <a href=\"https://github.com/M2Team/NanaZip\" target=\"_blank\">https://github.com/M2Team/NanaZip <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a> </div></main> <footer class=\"usa-footer usa-footer usa-footer--slim\"><div class=\"usa-footer__return-to-top\"><div class=\"grid-container\"><a href=\"#\">Return to top</a></div></div> <div class=\"usa-footer__secondary-section\"><div class=\"grid-container\"><div class=\"grid-row grid-gap\"><div class=\"grid-col\"><a href=\"https://github.com/GSA/openacr\" target=\"_blank\">OpenACR <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a> is a format maintained by the <a href=\"https://gsa.gov/\" target=\"_blank\">GSA <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a>. The content is the responsibility of the author.\n          </div> <div class=\"grid-col\">This content is licensed under a <a href=\"https://opensource.org/licenses/MIT\" target=\"_blank\">MIT License <span>(opens in a new window or tab)</span></a>.</div></div></div></div></footer></body></html>"
  },
  {
    "path": "Documents/Section508/NanaZip.yaml",
    "content": "title: NanaZip Accessibility Conformance Report\nproduct:\n  name: NanaZip\n  version: ''\n  description: >-\n    NanaZip is an open source file archiver intended for the modern Windows\n    experience, forked from the source code of well-known open source file\n    archiver 7-Zip.\nauthor:\n  name: Kenji Mouri\n  company_name: M2-Team\n  address: ''\n  email: Kenji.Mouri@outlook.com\n  phone: ''\n  website: 'http://nanazip.org/'\nvendor:\n  name: Kenji Mouri\n  company_name: M2-Team\n  address: ''\n  email: Kenji.Mouri@outlook.com\n  phone: ''\n  website: 'http://nanazip.org/'\nreport_date: 2026/2/25\nlast_modified_date: 2026/2/25\nversion: 1\nnotes: ''\nevaluation_methods_used: ''\nlegal_disclaimer: ''\nrepository: 'https://github.com/M2Team/NanaZip'\nfeedback: 'https://github.com/M2Team/NanaZip'\nlicense: MIT\nrelated_openacrs: []\ncatalog: 2.4-edition-wcag-2.1-508-en\nchapters:\n  success_criteria_level_a:\n    notes: ''\n    disabled: true\n    criteria:\n      - num: 1.1.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.2.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.2.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.2.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.3.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.3.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.3.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.1.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.1.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.1.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.2.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.2.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.3.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.5.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.5.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.5.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.5.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.1.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.2.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.2.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.3.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.3.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 4.1.1\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 4.1.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n  success_criteria_level_aa:\n    notes: ''\n    disabled: true\n    criteria:\n      - num: 1.2.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.2.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.3.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.3.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.10\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.11\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.12\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.13\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.7\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.1.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.2.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.2.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.3.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.3.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 4.1.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n  success_criteria_level_aaa:\n    notes: ''\n    disabled: true\n    criteria:\n      - num: 1.2.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.2.7\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.2.8\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.2.9\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.3.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.7\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.8\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 1.4.9\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.1.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.2.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.2.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.2.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.2.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.3.2\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.3.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.8\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.9\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.4.10\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.5.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 2.5.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.1.3\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.1.4\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.1.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.1.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.2.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.3.5\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n      - num: 3.3.6\n        components:\n          - name: web\n            adherence:\n              level: ''\n              notes: ''\n          - name: electronic-docs\n            adherence:\n              level: ''\n              notes: ''\n          - name: software\n            adherence:\n              level: ''\n              notes: ''\n          - name: authoring-tool\n            adherence:\n              level: ''\n              notes: ''\n  functional_performance_criteria:\n    notes: ''\n    disabled: false\n    criteria:\n      - num: '302.1'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.2'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.3'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.4'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.5'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.6'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.7'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.8'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '302.9'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n  hardware:\n    notes: ''\n    disabled: true\n    criteria:\n      - num: 402.2.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 402.2.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 402.2.3\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 402.2.4\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 402.2.5\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 402.3.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 402.3.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '402.4'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '402.5'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '403.1'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '404.1'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '405.1'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '406.1'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '407.2'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.3.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.3.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.3.3\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '407.4'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '407.5'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '407.6'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '407.7'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.1.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.1.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.2.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.2.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.3\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.3.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.3.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.3.2.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 407.8.3.2.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '408.2'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '408.3'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '409.1'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '410.1'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '411.1'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.2.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.2.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.3.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.3.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '412.4'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '412.5'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '412.6'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '412.7'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.8.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.8.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.8.3\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 412.8.4\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 413.1.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 413.1.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 414.1.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 414.1.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 415.1.1\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: 415.1.2\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n  software:\n    notes: ''\n    disabled: false\n    criteria:\n      - num: 502.2.1\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.2.2\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.1\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.2\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.3\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.4\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.5\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.6\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.7\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.8\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.9\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.10\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.11\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.12\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.13\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: 502.3.14\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '502.4'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '503.2'\n        components:\n          - name: none\n            adherence:\n              level: supports\n              notes: ''\n      - num: '503.3'\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n      - num: 503.4.1\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n      - num: 503.4.2\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n      - num: '504.2'\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n      - num: 504.2.1\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n      - num: 504.2.2\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n      - num: '504.3'\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n      - num: '504.4'\n        components:\n          - name: none\n            adherence:\n              level: not-applicable\n              notes: ''\n  support_documentation_and_services:\n    notes: ''\n    disabled: true\n    criteria:\n      - num: '602.2'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '602.3'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '602.4'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '603.2'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n      - num: '603.3'\n        components:\n          - name: none\n            adherence:\n              level: ''\n              notes: ''\n"
  },
  {
    "path": "Documents/SponsorEdition.md",
    "content": "﻿# NanaZip Sponsor Edition\n\nNanaZip provides a $99.99 USD Sponsor Edition addon to the Microsoft Store to \nattract more sponsors and contributors.\n\nIt's free for NanaZip source code repository contributors and NanaZip sponsors\nwho sponsored before March 30, 2024.\n\n## Feature\n\nThe only difference for NanaZip Sponsor Edition is showing \"Appreciate your\nsponsorship\" button instead of \"Sponsor NanaZip\" button in the next\nstable version of NanaZip's toolbar like the Visual Studio administrator mode.\n\n![VisualStudioAdministratorMode](VisualStudioAdministratorMode.png)\n\n## Purpose\n\nWe hope every NanaZip user is happier than before. Here is why we offer a\nsponsored version:\n\n- Most users: We are happy with using a $99.99 product freely without feature \n  differences.\n- Contributors: We want to show \"Appreciate your sponsorship\" button to \n  others. It's free because we are the contributors. Contribute it if you want\n  to get that free.\n- Sponsors: You can show \"Appreciate your sponsorship\" button to others\n  because sponsors deserve that.\n- The author of NanaZip, Kenji Mouri: Finally, NanaZip has a price. Nobody \n  will think this is a worthless product. Efforts from contributors and I should\n  have value even NanaZip is a fully free and open source project.\n\n## Notes for NanaZip source code repository contributors\n\nIf you are the contributor of NanaZip source code repository, please contact\nwith Kenji.Mouri@outlook.com for more information.\n\nNote: If you are the contributor of Project Mile projects which is used in\nNanaZip, you are eligibled too. I think I have sent e-mails or QQ message \nto all eligible Project Mile contributors.\n\n## Notes for NanaZip sponsors who sponsored before March 30, 2024\n\nI think I have sent e-mails or QQ message to all eligible NanaZip sponsors.\n\nContact with Kenji.Mouri@outlook.com for more information.\n"
  },
  {
    "path": "Documents/UpstreamSynchronization.md",
    "content": "﻿# NanaZip Upstream Synchronization Status\n\n## 7-Zip Mainline\n\n- NanaZip.Core: 26.00\n- NanaZip.UI.Classic: 22.01\n    - Fix for CVE-2025-0411 backported from 7-Zip 24.09.\n    - Fix for CVE-2025-11001 and CVE-2025-11002 backported from 7-Zip 25.00.\n    - Security enhancements for symbolic link handling backported from 7-Zip 25.01.\n- NanaZip.UI.Modern: 22.01\n    - Fix for CVE-2025-0411 backported from 7-Zip 24.09.\n    - Fix for CVE-2025-11001 and CVE-2025-11002 backported from 7-Zip 25.00.\n    - Security enhancements for symbolic link handling backported from 7-Zip 25.01.\n- NanaZip.Universal: 26.00\n\n## 7-Zip ZS\n\n- NanaZip.Core: Commit 5766dd7745f6517f7ea42f6de9a190dfd92aa25f.\n- NanaZip.UI.Classic: Unknown because it modifies the old codebase a lot.\n- NanaZip.UI.Modern: Unknown because it modifies the old codebase a lot.\n- NanaZip.Universal: Commit 5766dd7745f6517f7ea42f6de9a190dfd92aa25f.\n\n## BLAKE3\n\n- NanaZip.Codecs: 1.8.2\n\n## Brotli\n\n- NanaZip.Codecs: 1.2.0\n\n## FastLZMA2\n\n- NanaZip.Codecs: Commit a793db99fade2957d2453035390f97e573acecb2.\n\n## FreeBSD\n\n- NanaZip.Codecs: 14.2.0 with Windows-specific adaptations.\n\n## GmSSL\n\n- NanaZip.Codecs: 3.1.1\n\n## LittleFS\n\n- NanaZip.Codecs: 2.10.2 with actually has not been integrated yet.\n\n## Lizard\n\n- NanaZip.Codecs: 2.1\n\n## LZ4\n\n- NanaZip.Codecs: 1.10.0\n\n## LZ5\n\n- NanaZip.Codecs: 1.5\n\n## RHash\n\n- NanaZip.Codecs: Commit b76c6a3312422c09817c2cef40442b2f2d9d4689 after v1.4.6.\n\n## xxHash\n\n- NanaZip.Codecs: 0.8.3\n\n## Zstandard\n\n- NanaZip.Codecs: 1.5.7\n\n## ZSTDMT\n\n- NanaZip.Codecs: Follow 7-Zip ZS's integration.\n"
  },
  {
    "path": "Documents/Versioning.md",
    "content": "﻿# NanaZip Versioning\n\nThis document applies to all versions of NanaZip.\n\n## Version Format\n\n- Simple Version: `<Major>.<Minor> <Tag>`\n  - Example: `9.0 Preview 1`\n- Binary Version: `<Major>.<Minor>.<Build>.<Revision>`\n  - Example: `9.0.2654.0`\n\n## The rule for build and revision number\n\nThe build number is the number of days since August 31, 2021 because the first \nversion of NanaZip is created and published on that day.\n\nThe revision number is the number of releases releases in the day corresponding\nto the build number, and it counts from zero. So the first revision is 0 and \nthe second revision is 1.\n\n## Release Tags\n\nThe tag timeline for each release is:\n\n```\n\"Preview {N}\" (one or more) -> \"Final\" (one or more) -> \"No Tag\"\n-> {\"Update N Final\" (one or more) -> \"Update N\"} (zero or more)\n-> Repeat again for vNext\n```\n\nHere is the explanation for each tag:\n\n- \"Preview {N}\"\n  - This tag only appears in NanaZip Preview.\n  - N is the preview release number, starting from 1.\n  - N is also optional if there is only one preview release.\n- \"Final\" and \"Update N Final\"\n  - This tag only appears in NanaZip Preview.\n  - The last corresponding \"Final\" release in NanaZip Preview has the same\n    implementation as the corresponding stable release in NanaZip.\n  - There will be more than one \"Final\" release if there are some big issues\n    found before the corresponding stable release.\n  - \"Update N Final\" is used for validating updates after the corresponding\n    \"No Tag\" stable release.\n  - \"Update N Final\" corresponds to the stable release \"Update N\".\n- \"No Tag\" or \"Update N\"\n  - This tag only appears in NanaZip a.k.a. the stable release.\n  - This indicates the stable release of NanaZip.\n  - There is only one stable release for each minor version.\n  - N is the update release number, starting from 1.\n\nHere is the example timeline:\n\n```\n6.0 Preview 1 -> 6.0 Final -> 6.0 -> 6.0 Update 1 Final -> 6.0 Update 1\n-> 6.0 Update 2 Final -> 6.0 Update 2 -> 6.5 Preview -> ...\n```\n"
  },
  {
    "path": "Documents/Website/.gitignore",
    "content": "# build output\ndist/\n\n# generated types\n.astro/\n\n# dependencies\nnode_modules/\n\n# logs\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n# environment variables\n.env\n.env.production\n\n# macOS-specific files\n.DS_Store\n\n# jetbrains setting folder\n.idea/\n"
  },
  {
    "path": "Documents/Website/.vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"astro-build.astro-vscode\"],\n  \"unwantedRecommendations\": []\n}\n"
  },
  {
    "path": "Documents/Website/.vscode/launch.json",
    "content": "{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"command\": \"./node_modules/.bin/astro dev\",\n      \"name\": \"Development server\",\n      \"request\": \"launch\",\n      \"type\": \"node-terminal\"\n    }\n  ]\n}\n"
  },
  {
    "path": "Documents/Website/.vscode/mcp.json",
    "content": "{\n\t\"servers\": {\n\t\t\"Astro docs\": {\n\t\t\t\"url\": \"https://mcp.docs.astro.build/mcp\",\n\t\t\t\"type\": \"http\"\n\t\t}\n\t},\n\t\"inputs\": []\n}"
  },
  {
    "path": "Documents/Website/ReadMe.md",
    "content": "# NanaZip Website\n\nThis folder contains the source code of the NanaZip website,\nbuilt using [Astro](https://astro.build).\n\n## Images\n\nWhen taking screenshots for the website, please note the following guidelines:\n- Use the default Bloom wallpapers for Windows 11.\n- Do not use Snipping Tool (or the built-in `Windows` + `Shift` + `S` shortcut),\n  as it adds ugly borders around the screenshot. Use\n  [ShareX](https://getsharex.com/) (with transparency on and shadows off), or\n  an equivalent tool.\n  - To turn on transparency mode in ShareX:\n    1. Open ShareX and go to \"Task settings\".\n    2. On the left sidebar, click on \"Capture\".\n    3. Turn on \"Capture window with transparency\" and\n       turn off \"Capture window with shadow\".\n- Compress the PNG files using [pngquant](https://pngquant.org/),\n  with the following command:\n  ```\n  pngquant --force --ext .png --quality 85-85 <input-file.png>\n  ```\n\nWhen adding images to the website, place them in `src/assets/images`,\nand reference them like this:\n```html\n---\nimport exampleImage from '[path to picture]';\n---\n\n<Picture\n  src={exampleImage}\n  formats={[\"avif\", \"webp\"]}\n  alt=\"[alt text]\"\n  loading=\"[loading mode]\" />\n```\nWhere `[loading mode]` can be either `eager` or `lazy`.\nUse `eager` for images that are above the fold (i.e. visible without scrolling),\nand `lazy` for images that are below the fold.\n\nIf the image has both a light and a dark version, \nyou can use the `ThemedLocalPicture` component instead, \nlike this:\n```html\n---\nimport exampleImageLight from '[path to light version of picture]';\nimport exampleImageDark from '[path to dark version of picture]';\n---\n\n<ThemedLocalPicture\n  lightSrc={exampleImageLight}\n  darkSrc={exampleImageDark}\n  alt=\"[alt text]\"\n  loading=\"[loading mode]\" />\n```"
  },
  {
    "path": "Documents/Website/astro.config.mjs",
    "content": "// @ts-check\nimport { defineConfig } from 'astro/config';\n\n// https://astro.build/config\nexport default defineConfig({\n    site: 'https://nanazip.org',\n});\n"
  },
  {
    "path": "Documents/Website/package.json",
    "content": "{\n  \"name\": \"k7site\",\n  \"type\": \"module\",\n  \"version\": \"0.0.1\",\n  \"scripts\": {\n    \"dev\": \"astro dev\",\n    \"build\": \"astro build\",\n    \"preview\": \"astro preview\",\n    \"astro\": \"astro\"\n  },\n  \"dependencies\": {\n    \"@fluentui/svg-icons\": \"^1.1.320\",\n    \"astro\": \"^5.17.1\"\n  },\n  \"devDependencies\": {\n    \"sass-embedded\": \"^1.97.3\"\n  }\n}\n"
  },
  {
    "path": "Documents/Website/src/assets/styles/button.css",
    "content": "button, .btn {\n    border-radius: var(--fds-control-corner-radius);\n    font-size: var(--fds-body-font-size);\n    border: 1px solid var(--fds-control-border-default);\n    background-color: var(--fds-control-fill-default);\n    color: var(--fds-text-primary);\n    font-family: var(--fds-font-family-text);\n    padding: 4px 11px 6px 11px;\n    transition: var(--fds-control-faster-duration) ease background;\n    font-size: var(--fds-body-font-size);\n    cursor: pointer;\n    user-select: none;\n    text-decoration: none;\n    display: inline-block;\n}\n\nbutton:hover, .btn:hover {\n    background-color: var(--fds-control-fill-secondary);\n}\n\nbutton:active, .btn:active {\n    background-color: var(--fds-control-fill-tertiary);\n    border-color: var(--fds-control-stroke-default);\n    color: var(--fds-text-secondary);\n}\n\n.btn-hyper {\n    background-color: transparent;\n    color: var(--fds-accent-text-primary);\n}\n\n.btn-hyper:hover {\n    background-color: var(--fds-subtle-fill-secondary);\n}\n\n.btn-hyper:active {\n    background-color: var(--fds-subtle-fill-tertiary);\n    color: var(--fds-accent-text-tertiary);\n}\n\n.btn-accent {\n    background-color: var(--fds-accent-default);\n    border: 1px solid var(--fds-control-stroke-on-accent-default);\n    border-bottom-color: var(--fds-control-stroke-on-accent-secondary);\n    color: var(--fds-text-on-accent-primary);\n    transition: var(--fds-control-faster-duration) ease border-color;\n}\n\n.btn-accent:hover {\n    background-color: var(--fds-accent-secondary);\n}\n\n.btn-accent:active {\n    background-color: var(--fds-accent-tertiary);\n    border-color: transparent;\n    color: var(--fds-text-on-accent-secondary);\n}"
  },
  {
    "path": "Documents/Website/src/assets/styles/global.css",
    "content": "body {\n\tbackground-color: var(--fds-solid-background-base);\n\tcolor: var(--fds-text-primary);\n    font-family: var(--fds-font-family-text);\n    font-size: var(--fds-body-font-size);\n    line-height: 20px;\n\n    margin: 0;\n    padding: 0;\n\n    min-height: 100vh;\n    display: flex;\n    flex-direction: column;\n}\n\nmain {\n    display: flex;\n    flex-direction: column;\n    flex: 1 0 auto;\n}\n\nmain article {\n    max-width: 800px;\n    margin: 40px 16px 16px 16px;\n    align-self: center;\n}\n\nhtml {\n    color-scheme: light;\n}\n\n@media (prefers-color-scheme: dark) {\n    html {\n        color-scheme: dark;\n    }\n}\n\n@view-transition {\n    navigation: auto;\n}"
  },
  {
    "path": "Documents/Website/src/assets/styles/icons.css",
    "content": "@font-face {\n    font-family: \"FluentSystemIcons-Regular\";\n    src: url(\"/FluentSystemIcons-Regular.woff2\") format(\"woff2\"),\n        url(\"/FluentSystemIcons-Regular.woff\") format(\"woff\"),\n        url(\"/FluentSystemIcons-Regular.ttf\") format(\"truetype\");\n    font-display: swap;\n}\n\n.icon:before {\n    font-family: FluentSystemIcons-Regular !important;\n    font-style: normal;\n    font-weight: normal !important;\n    font-variant: normal;\n    text-transform: none;\n    line-height: 1;\n    -webkit-font-smoothing: antialiased;\n    -moz-osx-font-smoothing: grayscale;\n}\n\n.icon {\n    line-height: 0;\n}"
  },
  {
    "path": "Documents/Website/src/assets/styles/image.css",
    "content": "img {\n\tmax-width: 100%;\n\theight: auto;\n}\n\n.image-card {\n\tborder: 1px solid var(--fds-surface-stroke-default);\n\tborder-radius: 8px;\n}"
  },
  {
    "path": "Documents/Website/src/assets/styles/pages/index.css",
    "content": ".se-demo-scenario {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    gap: 16px;\n}\n\n.card {\n    border: 1px solid var(--fds-card-stroke-default);\n    background-color: var(--fds-card-background-default);\n    border-radius: 8px;\n    padding: 16px;\n}\n\n.se-demo-scenario .card {\n    flex: 1;\n}\n\n@media (max-width: 768px) {\n    .se-demo {\n        gap: 32px;\n    }\n\n    #right-arrow {\n        transform: rotate(90deg);\n    }\n\n    .se-demo-scenario .card {\n        flex: unset;\n    }\n\n    .se-demo-scenario {\n        flex-direction: column;\n    }\n}\n\n.format-list {\n    display: flex;\n    flex-direction: row;\n    gap: 16px;\n    flex-wrap: wrap;\n    align-items: center;\n    justify-content: center;\n    text-align: center;\n}\n\n.format-list .card {\n    font-size: 18px;\n}"
  },
  {
    "path": "Documents/Website/src/assets/styles/text.css",
    "content": "h1, h2, h3, h4, h5, h6 {\n    font-family: var(--fds-font-family-display);\n\n    margin: 0;\n    padding: 0;\n}\n\nh1 {\n    font-size: var(--fds-title-large-font-size);\n    font-weight: 600;\n    line-height: 52px;\n}\n\nh2 {\n    font-size: var(--fds-title-font-size);\n    font-weight: 600;\n    line-height: 36px;\n}\n\nh3 {\n    font-size: var(--fds-subtitle-font-size);\n    font-weight: 600;\n    line-height: 28px;\n}\n\nsmall {\n    font-size: var(--fds-caption-font-size);\n    font-family: var(--fds-font-family-small);\n    line-height: 16px;\n}\n\narticle h1, article h2 {\n    margin-top: 16px;\n    margin-bottom: 16px;\n}\n\na {\n    color: var(--fds-accent-text-primary);\n}\n\na:active {\n    color: var(--fds-accent-text-tertiary);\n}"
  },
  {
    "path": "Documents/Website/src/assets/styles/theme.css",
    "content": "/* Global Variables */\n:root {\n\t/* Accent Colors */\n\t--fds-accent-light-3: 191, 98%, 80%;\n\t--fds-accent-light-2: 199, 99%, 69%;\n\t--fds-accent-light-1: 205, 100%, 49%;\n\t--fds-accent-base: 206, 100%, 42%;\n\t--fds-accent-dark-1: 209, 100%, 36%;\n\t--fds-accent-dark-2: 215, 100%, 29%;\n\t--fds-accent-dark-3: 226, 100%, 20%;\n\n\t/* Font Families */\n\t--fds-font-family-fallback: \"Segoe UI\", -apple-system, ui-sans-serif, system-ui,\n\t\tBlinkMacSystemFont, Helvetica, Arial, sans-serif;\n\t--fds-font-family-text: \"Segoe UI Variable Text\", \"Seoge UI Variable Static Text\",\n\t\tvar(--fds-font-family-fallback);\n\t--fds-font-family-small: \"Segoe UI Variable Small\", \"Seoge UI Variable Static Small\",\n\t\tvar(--fds-font-family-fallback);\n\t--fds-font-family-display: \"Segoe UI Variable Display\", \"Seoge UI Variable Static Display\",\n\t\tvar(--fds-font-family-fallback);\n\n\t/* Font Size */\n\t--fds-caption-font-size: 12px;\n\t--fds-body-font-size: 14px;\n\t--fds-body-large-font-size: 18px;\n\t--fds-subtitle-font-size: 20px;\n\t--fds-title-font-size: 28px;\n\t--fds-title-large-font-size: 40px;\n\t--fds-display-font-size: 68px;\n\n\t/* Roundness */\n\t--fds-control-corner-radius: 4px;\n\t--fds-overlay-corner-radius: 8px;\n\n\t/* Duration */\n\t--fds-control-slow-duration: 333ms;\n\t--fds-control-normal-duration: 250ms;\n\t--fds-control-fast-duration: 167ms;\n\t/* --fds-control-fast-after-duration: 168ms; */\n\t--fds-control-faster-duration: 83ms;\n\n\t/* Easing */\n\t--fds-control-fast-out-slow-in-easing: cubic-bezier(0, 0, 0, 1);\n\n\t/* Focus Stroke */\n\t--fds-focus-stroke: 0 0 0 1px var(--fds-focus-stroke-inner),\n\t\t0 0 0 3px var(--fds-focus-stroke-outer);\n}\n\n/* Reduced Motion Support */\n@media (prefers-reduced-motion: reduce) {\n\t:root {\n\t\t--fds-control-slow-duration: 0ms;\n\t\t--fds-control-normal-duration: 0ms;\n\t\t--fds-control-fast-duration: 0ms;\n\t\t/* --fds-control-fast-after-duration: 0ms; */\n\t\t--fds-control-faster-duration: 0ms;\n\t}\n}\n\n/* Light Theme Colors */\n@media (prefers-color-scheme: light) {\n\t:root {\n\t\t/* Text */\n\t\t--fds-text-primary: hsla(0, 0%, 0%, 89.56%);\n\t\t--fds-text-secondary: hsla(0, 0%, 0%, 60.63%);\n\t\t--fds-text-tertiary: hsla(0, 0%, 0%, 44.58%);\n\t\t--fds-text-disabled: hsla(0, 0%, 0%, 36.14%);\n\n\t\t/* Accent */\n\t\t--fds-accent-default: hsl(var(--fds-accent-dark-1));\n\t\t--fds-accent-secondary: hsla(var(--fds-accent-dark-1), 90%);\n\t\t--fds-accent-tertiary: hsla(var(--fds-accent-dark-1), 80%);\n\t\t--fds-accent-disabled: hsla(0, 0%, 0%, 21.69%);\n\n\t\t/* Accent Text */\n\t\t--fds-accent-text-primary: hsl(var(--fds-accent-dark-2));\n\t\t--fds-accent-text-secondary: hsl(var(--fds-accent-dark-3));\n\t\t--fds-accent-text-tertiary: hsl(var(--fds-accent-dark-1));\n\t\t--fds-accent-text-disabled: hsla(0, 0%, 0%, 36.14%);\n\n\t\t/* Text on Accent */\n\t\t--fds-text-on-accent-primary: hsl(0, 0%, 100%);\n\t\t--fds-text-on-accent-secondary: hsla(0, 0%, 100%, 70%);\n\t\t--fds-text-on-accent-disabled: var(--fds-text-on-accent-secondary);\n\t\t--fds-text-on-accent-selected: var(--fds-text-on-accent-primary);\n\n\t\t/* Control Fill */\n\t\t--fds-control-fill-transparent: transparent;\n\t\t--fds-control-fill-default: hsla(0, 0%, 100%, 70%);\n\t\t--fds-control-fill-secondary: hsla(0, 0%, 98%, 50%);\n\t\t--fds-control-fill-tertiary: hsla(0, 0%, 98%, 30%);\n\t\t--fds-control-fill-disabled: var(--fds-control-fill-tertiary);\n\t\t--fds-control-fill-input-active: hsl(0, 0%, 100%);\n\n\t\t/* Control Strong Fill */\n\t\t--fds-control-strong-fill-default: hsla(0, 0%, 0%, 44.58%);\n\t\t--fds-control-strong-fill-disabled: hsla(0, 0%, 0%, 31.73%);\n\n\t\t/* Control Solid Fill */\n\t\t--fds-control-solid-fill-default: hsl(0, 0%, 100%);\n\n\t\t/* Control Alt Fill */\n\t\t--fds-control-alt-fill-transparent: transparent;\n\t\t--fds-control-alt-fill-secondary: hsla(0, 0%, 0%, 2.41%);\n\t\t--fds-control-alt-fill-tertiary: hsla(0, 0%, 0%, 5.78%);\n\t\t--fds-control-alt-fill-quarternary: hsla(0, 0%, 0%, 9.24%);\n\t\t--fds-control-alt-fill-disabled: var(--fds-control-alt-fill-transparent);\n\n\t\t/* Control on Image Fill */\n\t\t--fds-control-on-image-fill-default: hsla(0, 0%, 100%, 79%);\n\t\t--fds-control-on-image-fill-secondary: hsl(0, 0%, 95%);\n\t\t--fds-control-on-image-fill-tertiary: hsl(0, 0%, 92%);\n\t\t--fds-control-on-image-fill-disabled: transparent;\n\n\t\t/* Subtle Fill */\n\t\t--fds-subtle-fill-transparent: transparent;\n\t\t--fds-subtle-fill-secondary: hsla(0, 0%, 0%, 3.73%);\n\t\t--fds-subtle-fill-tertiary: hsla(0, 0%, 0%, 2.41%);\n\t\t--fds-subtle-fill-disabled: var(--fds-subtle-fill-transparent);\n\n\t\t/* Control Stroke */\n\t\t--fds-control-stroke-default: hsla(0, 0%, 0%, 5.78%);\n\t\t--fds-control-stroke-secondary: hsla(0, 0%, 0%, 16.22%);\n\n\t\t/* Control Strong Stroke */\n\t\t--fds-control-strong-stroke-default: hsla(0, 0%, 0%, 44.58%);\n\t\t--fds-control-strong-stroke-disabled: hsla(0, 0%, 0%, 21.69%);\n\n\t\t/* Control Stroke on Accent */\n\t\t--fds-control-stroke-on-accent-default: hsla(0, 0%, 100%, 8%);\n\t\t--fds-control-stroke-on-accent-secondary: hsla(0, 0%, 0%, 40%);\n\t\t--fds-control-stroke-on-accent-tertiary: hsla(0, 0%, 0%, 21.69%);\n\t\t--fds-control-stroke-on-accent-disabled: var(--fds-control-stroke-on-accent-default);\n\n\t\t/* Control Strong Stroke on Image */\n\t\t--fds-control-strong-stroke-on-image-default: hsla(0, 0%, 100%, 35%);\n\n\t\t/* Card Stroke */\n\t\t--fds-card-stroke-default: hsla(0, 0%, 0%, 5.78%);\n\t\t--fds-card-stroke-default-solid: hsl(0, 0%, 92%);\n\n\t\t/* Surface Stroke */\n\t\t--fds-surface-stroke-default: hsla(0, 0%, 46%, 40%);\n\t\t--fds-surface-stroke-flyout: hsla(0, 0%, 0%, 5.78%);\n\n\t\t/* Divider Stroke */\n\t\t--fds-divider-stroke-default: hsla(0, 0%, 0%, 8.03%);\n\n\t\t/* Focus Stroke */\n\t\t--fds-focus-stroke-outer: hsla(0, 0%, 0%, 89.56%);\n\t\t--fds-focus-stroke-inner: hsl(0, 0%, 100%);\n\n\t\t/* Card Background */\n\t\t--fds-card-background-default: hsla(0, 0%, 100%, 70%);\n\t\t--fds-card-background-secondary: hsla(0, 0%, 96%, 50%);\n\t\t/* --fds-card-background-tertiary: hsl(0, 0%, 100%); */\n\n\t\t/* Smoke Background */\n\t\t--fds-smoke-background-default: hsla(0, 0%, 0%, 30%);\n\n\t\t/* Layer */\n\t\t--fds-layer-background-default: hsla(0, 0%, 100%, 50%);\n\t\t--fds-layer-background-alt: hsl(0, 0%, 100%);\n\n\t\t/* Solid Background */\n\t\t--fds-solid-background-base: hsl(0, 0%, 95%);\n\t\t--fds-solid-background-secondary: hsl(0, 0%, 93%);\n\t\t--fds-solid-background-tertiary: hsl(0, 0%, 98%);\n\t\t--fds-solid-background-quarternary: hsl(0, 0%, 100%);\n\n\t\t/* System */\n\t\t--fds-system-attention: hsl(209, 100%, 36%);\n\t\t--fds-system-success: hsl(120, 78%, 27%);\n\t\t--fds-system-caution: hsl(36, 100%, 31%);\n\t\t--fds-system-critical: hsl(5, 75%, 44%);\n\t\t--fds-system-neutral: hsla(0, 0%, 0%, 44.58%);\n\n\t\t/* System Solid */\n\t\t--fds-system-solid-neutral: hsl(0, 0%, 54%);\n\n\t\t/* System Background */\n\t\t--fds-system-background-attention: hsla(0, 0%, 96%, 50%);\n\t\t--fds-system-background-success: hsl(115, 58%, 92%);\n\t\t--fds-system-background-caution: hsl(47, 100%, 90%);\n\t\t--fds-system-background-critical: hsl(355, 85%, 95%);\n\n\t\t/* System Background Solid */\n\t\t--fds-system-background-solid-attention: hsl(0, 0%, 97%);\n\t\t--fds-system-background-solid-neutral: hsl(0, 0%, 95%);\n\n\t\t/* Borders */\n\t\t--fds-control-border-default: var(--fds-control-stroke-default)\n\t\t\tvar(--fds-control-stroke-default) var(--fds-control-stroke-secondary)\n\t\t\tvar(--fds-control-stroke-default);\n\n\t\t/* Shadows */\n\t\t--fds-card-shadow: 0px 2px 4px hsla(0, 0%, 0%, 4%);\n\t\t--fds-tooltip-shadow: 0px 4px 8px hsla(0, 0%, 0%, 14%);\n\t\t--fds-flyout-shadow: 0px 8px 16px hsla(0, 0%, 0%, 14%);\n\t\t--fds-dialog-shadow: 0px 32px 64px hsla(0, 0%, 0%, 18.76%),\n\t\t\t0px 2px 21px hsl(0, 0%, 0%, 14.74%);\n\n\t\t/* Shell Shadows */\n\t\t--fds-inactive-window-shadow: 0px 16px 32px hsla(0, 0%, 0%, 18%),\n\t\t\t0px 2px 10.67px hsla(0, 0%, 0%, 0.1474);\n\t\t--fds-active-window-shadow: 0px 32px 64px hsla(0, 0%, 0%, 28%),\n\t\t\t0px 2px 21px hsla(0, 0%, 0%, 22%);\n\t}\n}\n\n/* Dark Theme Colors */\n@media (prefers-color-scheme: dark) {\n\t:root {\n\t\t/* Text */\n\t\t--fds-text-primary: hsla(0, 0%, 100%, 100%);\n\t\t--fds-text-secondary: hsla(0, 0%, 100%, 78.6%);\n\t\t--fds-text-tertiary: hsla(0, 0%, 100%, 54.42%);\n\t\t--fds-text-disabled: hsla(0, 0%, 100%, 36.28%);\n\n\t\t/* Accent */\n\t\t--fds-accent-default: hsla(var(--fds-accent-light-2));\n\t\t--fds-accent-secondary: hsla(var(--fds-accent-light-2), 90%);\n\t\t--fds-accent-tertiary: hsla(var(--fds-accent-light-2), 80%);\n\t\t--fds-accent-disabled: hsla(0, 0%, 100%, 15.81%);\n\n\t\t/* Accent Text */\n\t\t--fds-accent-text-primary: hsl(var(--fds-accent-light-3));\n\t\t--fds-accent-text-secondary: hsl(var(--fds-accent-light-3));\n\t\t--fds-accent-text-tertiary: hsl(var(--fds-accent-light-2));\n\t\t--fds-accent-text-disabled: hsla(0, 0%, 100%, 36.28%);\n\n\t\t/* Text on Accent */\n\t\t--fds-text-on-accent-primary: hsl(0, 0%, 0%);\n\t\t--fds-text-on-accent-secondary: hsla(0, 0%, 0%, 0.5);\n\t\t--fds-text-on-accent-disabled: hsla(0, 0%, 100%, 0.53);\n\t\t--fds-text-on-accent-selected: hsl(0, 0%, 100%);\n\n\t\t/* Control Fill */\n\t\t--fds-control-fill-transparent: transparent;\n\t\t--fds-control-fill-default: hsla(0, 0%, 100%, 0.061);\n\t\t--fds-control-fill-secondary: hsla(0, 0%, 100%, 0.084);\n\t\t--fds-control-fill-tertiary: hsla(0, 0%, 100%, 0.033);\n\t\t--fds-control-fill-disabled: hsla(0, 0%, 100%, 0.042);\n\t\t--fds-control-fill-input-active: hsla(0, 0%, 12%, 70%);\n\n\t\t/* Control Strong Fill */\n\t\t--fds-control-strong-fill-default: hsla(0, 0%, 100%, 54.42%);\n\t\t--fds-control-strong-fill-disabled: hsla(0, 0%, 100%, 24.65%);\n\n\t\t/* Control Solid Fill */\n\t\t--fds-control-solid-fill-default: hsl(0, 0%, 27%);\n\n\t\t/* Control Alt Fill */\n\t\t--fds-control-alt-fill-transparent: transparent;\n\t\t--fds-control-alt-fill-secondary: hsla(0, 0%, 0%, 0.1);\n\t\t--fds-control-alt-fill-tertiary: hsla(0, 0%, 100%, 0.042);\n\t\t--fds-control-alt-fill-quarternary: hsla(0, 0%, 100%, 0.07);\n\t\t--fds-control-alt-fill-disabled: var(--fds-control-fill-transparent);\n\n\t\t/* Control on Image Fill */\n\t\t--fds-control-on-image-fill-default: hsla(0, 0%, 11%, 70%);\n\t\t--fds-control-on-image-fill-secondary: hsl(0, 0%, 10%);\n\t\t--fds-control-on-image-fill-tertiary: hsl(0, 0%, 7%);\n\t\t--fds-control-on-image-fill-disabled: transparent;\n\n\t\t/* Subtle Fill */\n\t\t--fds-subtle-fill-transparent: transparent;\n\t\t--fds-subtle-fill-secondary: hsla(0, 0%, 100%, 6.05%);\n\t\t--fds-subtle-fill-tertiary: hsla(0, 0%, 100%, 4.19%);\n\t\t--fds-subtle-fill-disabled: transparent;\n\n\t\t/* Control Stroke */\n\t\t--fds-control-stroke-default: hsla(0, 0%, 100%, 6.98%);\n\t\t--fds-control-stroke-secondary: hsla(0, 0%, 100%, 9.3%);\n\n\t\t/* Control Strong Stroke */\n\t\t--fds-control-strong-stroke-default: hsla(0, 0%, 100%, 54.42%);\n\t\t--fds-control-strong-stroke-disabled: hsla(0, 0%, 100%, 15.81%);\n\n\t\t/* Control Stroke on Accent */\n\t\t--fds-control-stroke-on-accent-default: hsla(0, 0%, 100%, 8%);\n\t\t--fds-control-stroke-on-accent-secondary: hsla(0, 0%, 0%, 14%);\n\t\t--fds-control-stroke-on-accent-tertiary: hsla(0, 0%, 0%, 21.69%);\n\t\t--fds-control-stroke-on-accent-disabled: hsla(0, 0%, 0%, 20%);\n\n\t\t/* Control Strong Stroke on Image */\n\t\t--fds-control-strong-stroke-on-image-default: hsla(0, 0%, 0%, 42%);\n\n\t\t/* Card Stroke */\n\t\t--fds-card-stroke-default: hsla(0, 0%, 0%, 10%);\n\t\t--fds-card-stroke-default-solid: hsl(0, 0%, 11%);\n\n\t\t/* Surface Stroke */\n\t\t--fds-surface-stroke-default: hsla(0, 0%, 46%, 40%);\n\t\t--fds-surface-stroke-flyout: hsla(0, 0%, 0%, 20%);\n\n\t\t/* Divider Stroke */\n\t\t--fds-divider-stroke-default: hsla(0, 0%, 100%, 8.37%);\n\n\t\t/* Focus Stroke */\n\t\t--fds-focus-stroke-outer: hsl(0, 0%, 100%);\n\t\t--fds-focus-stroke-inner: hsla(0, 0%, 0%, 70%);\n\n\t\t/* Card Background */\n\t\t--fds-card-background-default: hsla(0, 0%, 100%, 5.12%);\n\t\t--fds-card-background-secondary: hsla(0, 0%, 100%, 3.26%);\n\t\t/* --fds-card-background-tertiary: unset; */\n\n\t\t/* Smoke Background */\n\t\t--fds-smoke-background-default: hsla(0, 0%, 0%, 30%);\n\n\t\t/* Layer */\n\t\t--fds-layer-background-default: hsla(0, 0%, 23%, 30%);\n\t\t--fds-layer-background-alt: hsla(0, 0%, 100%, 5.38%);\n\n\t\t/* Solid Background */\n\t\t--fds-solid-background-base: hsl(0, 0%, 13%);\n\t\t--fds-solid-background-secondary: hsl(0, 0%, 11%);\n\t\t--fds-solid-background-tertiary: hsl(0, 0%, 16%);\n\t\t--fds-solid-background-quarternary: hsl(0, 0%, 17%);\n\n\t\t/* System */\n\t\t--fds-system-attention: hsl(199, 100%, 69%);\n\t\t--fds-system-success: hsl(113, 51%, 58%);\n\t\t--fds-system-caution: hsl(54, 100%, 49%);\n\t\t--fds-system-critical: hsl(354, 100%, 80%);\n\t\t--fds-system-neutral: hsla(0, 0%, 100%, 54.42%);\n\n\t\t/* System Solid */\n\t\t--fds-system-solid-neutral: hsl(0, 0%, 62%);\n\n\t\t/* System Background */\n\t\t--fds-system-background-attention: hsla(0, 0%, 100%, 3.26%);\n\t\t--fds-system-background-success: hsl(67, 39%, 17%);\n\t\t--fds-system-background-caution: hsl(40, 46%, 18%);\n\t\t--fds-system-background-critical: hsl(2, 28%, 21%);\n\n\t\t/* System Background Solid */\n\t\t--fds-system-background-solid-attention: hsl(0, 0%, 18%);\n\t\t--fds-system-background-solid-neutral: hsl(0, 0%, 62%);\n\n\t\t/* Borders */\n\t\t--fds-control-border-default: var(--fds-control-stroke-secondary)\n\t\t\tvar(--fds-control-stroke-default) var(--fds-control-stroke-default)\n\t\t\tvar(--fds-control-stroke-default);\n\n\t\t/* Shadows */\n\t\t--fds-card-shadow: 0px 2px 4px hsla(0, 0%, 0%, 0.13);\n\t\t--fds-tooltip-shadow: 0px 4px 8px hsla(0, 0%, 0%, 0.26);\n\t\t--fds-flyout-shadow: 0px 8px 16px hsla(0, 0%, 0%, 0.14);\n\t\t--fds-dialog-shadow: 0px 32px 64px hsla(0, 0%, 0%, 0.37), 0px 2px 21px hsla(0, 0%, 0%, 0.37);\n\n\t\t/* Shell Shadows */\n\t\t--fds-inactive-window-shadow: 0px 16px 32px hsla(0, 0%, 0%, 0.37),\n\t\t\t0px 2px 10.67px hsla(0, 0%, 0%, 0.37);\n\t\t--fds-active-window-shadow: 0px 32px 64px hsla(0, 0%, 0%, 0.56),\n\t\t\t0px 2px 21px hsla(0, 0%, 0%, 0.55);\n\t}\n}"
  },
  {
    "path": "Documents/Website/src/components/Footer/Footer.astro",
    "content": "---\nimport './Footer.css';\n---\n\n<footer>\n    <p>NanaZip, with ❤️ by <a href=\"https://m2team.org\">M2-Team</a> and contributors.</p>\n    <p>\n        Note: NanaZip.org is the only official website for NanaZip.\n        Any other websites claiming to be NanaZip are fake.\n        We are not responsible for content on those websites.\n    </p>\n</footer>"
  },
  {
    "path": "Documents/Website/src/components/Footer/Footer.css",
    "content": "footer {\n    background-color: var(--fds-card-stroke-default-solid);\n    border-top: 1px solid var(--fds-surface-stroke-flyout);\n    padding: 8px 32px;\n    margin-top: 16px;\n}"
  },
  {
    "path": "Documents/Website/src/components/InfoBar/InfoBar.astro",
    "content": "---\nimport \"./InfoBar.scss\";\n\ninterface Props {\n    title?: string;\n    severity: \"information\" | \"success\" | \"caution\" | \"critical\" | \"attention\";\n    wrap?: boolean;\n}\n\nconst { title, severity, wrap = false } = Astro.props;\n\nlet path = \"\";\nif (severity === \"attention\") {\n    path =\n        \"M862.5,680C862.5,687.333 861.083,694.25 858.25,700.75C855.417,707.25 851.583,712.917 846.75,717.75C841.917,722.583 836.25,726.417 829.75,729.25C823.25,732.083 816.333,733.5 809,733.5C800,733.5 791.333,731.167 783,726.5L565.5,603.5L565.5,853.5C565.5,860.833 564.083,867.75 561.25,874.25C558.417,880.75 554.583,886.333 549.75,891C544.917,895.667 539.25,899.417 532.75,902.25C526.25,905.083 519.333,906.5 512,906.5C504.667,906.5 497.75,905.083 491.25,902.25C484.75,899.417 479.083,895.667 474.25,891C469.417,886.333 465.583,880.75 462.75,874.25C459.917,867.75 458.5,860.833 458.5,853.5L458.5,603.5L241,726.5C232.667,731.167 224,733.5 215,733.5C207.667,733.5 200.75,732.083 194.25,729.25C187.75,726.417 182.083,722.583 177.25,717.75C172.417,712.917 168.583,707.25 165.75,700.75C162.917,694.25 161.5,687.333 161.5,680C161.5,670.667 164,661.75 169,653.25C174,644.75 180.5,638.167 188.5,633.5L403.5,512L188.5,390.5C180.5,385.833 174,379.25 169,370.75C164,362.25 161.5,353.333 161.5,344C161.5,336.667 162.917,329.75 165.75,323.25C168.583,316.75 172.417,311.083 177.25,306.25C182.083,301.417 187.75,297.583 194.25,294.75C200.75,291.917 207.667,290.5 215,290.5C224.667,290.5 233.333,292.833 241,297.5L458.5,420.5L458.5,170.5C458.5,163.167 459.917,156.25 462.75,149.75C465.583,143.25 469.417,137.667 474.25,133C479.083,128.333 484.75,124.583 491.25,121.75C497.75,118.917 504.667,117.5 512,117.5C519.333,117.5 526.25,118.917 532.75,121.75C539.25,124.583 544.917,128.333 549.75,133C554.583,137.667 558.417,143.25 561.25,149.75C564.083,156.25 565.5,163.167 565.5,170.5L565.5,420.5L783,297.5C791.333,292.833 800,290.5 809,290.5C816.333,290.5 823.25,291.917 829.75,294.75C836.25,297.583 841.917,301.417 846.75,306.25C851.583,311.083 855.417,316.75 858.25,323.25C861.083,329.75 862.5,336.667 862.5,344C862.5,353.333 860,362.25 855,370.75C850,379.25 843.5,385.833 835.5,390.5L620.5,512L835.5,633.5C843.5,638.167 850,644.75 855,653.25C860,661.75 862.5,670.667 862.5,680Z\";\n} else if (severity === \"success\") {\n    path =\n        \"M117.5,554.5C117.5,547.167 118.917,540.25 121.75,533.75C124.583,527.25 128.417,521.583 133.25,516.75C138.083,511.917 143.75,508.083 150.25,505.25C156.75,502.417 163.667,501 171,501C185.333,501 197.833,506.333 208.5,517L384,692.5L815.5,261C826.167,250.333 838.833,245 853.5,245C860.833,245 867.75,246.417 874.25,249.25C880.75,252.083 886.417,256 891.25,261C896.083,266 899.917,271.75 902.75,278.25C905.583,284.75 907,291.5 907,298.5C907,313.167 901.667,325.833 891,336.5L421.5,805.5C416.5,810.5 410.75,814.417 404.25,817.25C397.75,820.083 391,821.5 384,821.5C369.667,821.5 357.167,816.167 346.5,805.5L133,592.5C122.667,582.167 117.5,569.5 117.5,554.5Z\";\n} else if (severity == \"caution\") {\n    path =\n        \"M426.5,512L426.5,170.5C426.5,158.833 428.75,147.833 433.25,137.5C437.75,127.167 443.917,118.167 451.75,110.5C459.583,102.833 468.667,96.75 479,92.25C489.333,87.75 500.333,85.5 512,85.5C523.667,85.5 534.667,87.75 545,92.25C555.333,96.75 564.417,102.833 572.25,110.5C580.083,118.167 586.25,127.167 590.75,137.5C595.25,147.833 597.5,158.833 597.5,170.5L597.5,512C597.5,523.667 595.25,534.667 590.75,545C586.25,555.333 580.083,564.417 572.25,572.25C564.417,580.083 555.333,586.25 545,590.75C534.667,595.25 523.667,597.5 512,597.5C500.333,597.5 489.333,595.25 479,590.75C468.667,586.25 459.583,580.083 451.75,572.25C443.917,564.417 437.75,555.333 433.25,545C428.75,534.667 426.5,523.667 426.5,512ZM405.5,853.5C405.5,838.833 408.333,825 414,812C419.667,799 427.333,787.667 437,778C446.667,768.333 457.917,760.667 470.75,755C483.583,749.333 497.333,746.5 512,746.5C526.667,746.5 540.417,749.333 553.25,755C566.083,760.667 577.333,768.333 587,778C596.667,787.667 604.333,799 610,812C615.667,825 618.5,838.833 618.5,853.5C618.5,868.167 615.667,881.917 610,894.75C604.333,907.583 596.667,918.833 587,928.5C577.333,938.167 566,945.833 553,951.5C540,957.167 526.333,960 512,960C497.333,960 483.583,957.167 470.75,951.5C457.917,945.833 446.667,938.167 437,928.5C427.333,918.833 419.667,907.583 414,894.75C408.333,881.917 405.5,868.167 405.5,853.5Z\";\n} else if (severity === \"critical\") {\n    path =\n        \"M512.5,587.5L262.5,838C252.167,848.333 239.5,853.5 224.5,853.5C209.5,853.5 196.917,848.417 186.75,838.25C176.583,828.083 171.5,815.5 171.5,800.5C171.5,785.5 176.667,772.833 187,762.5L437,512L187,262C176.667,251.667 171.5,239.167 171.5,224.5C171.5,217.167 172.833,210.167 175.5,203.5C178.167,196.833 181.917,191.167 186.75,186.5C191.583,181.833 197.167,178.083 203.5,175.25C209.833,172.417 216.833,171 224.5,171C239.167,171 251.667,176.167 262,186.5L512.5,437L762.5,186.5C773.167,175.833 785.833,170.5 800.5,170.5C807.833,170.5 814.75,171.917 821.25,174.75C827.75,177.583 833.417,181.417 838.25,186.25C843.083,191.083 846.833,196.75 849.5,203.25C852.167,209.75 853.5,216.667 853.5,224C853.5,238.667 848.333,251.167 838,261.5L587.5,512L838,762.5C848.667,773.167 854,785.833 854,800.5C854,807.833 852.583,814.667 849.75,821C846.917,827.333 843.083,832.917 838.25,837.75C833.417,842.583 827.75,846.417 821.25,849.25C814.75,852.083 807.833,853.5 800.5,853.5C785.5,853.5 772.833,848.333 762.5,838Z\";\n} else if (severity === \"information\") {\n    path =\n        \"M405.5,170.5C405.5,156.167 408.333,142.5 414,129.5C419.667,116.5 427.333,105.167 437,95.5C446.667,85.8334 457.917,78.1667 470.75,72.5C483.583,66.8334 497.333,64.0001 512,64C526.333,64.0001 540,66.8334 553,72.5C566,78.1667 577.333,85.8334 587,95.5C596.667,105.167 604.333,116.5 610,129.5C615.667,142.5 618.5,156.167 618.5,170.5C618.5,185.167 615.667,199 610,212C604.333,225 596.667,236.333 587,246C577.333,255.667 566.083,263.333 553.25,269C540.417,274.667 526.667,277.5 512,277.5C497.333,277.5 483.583,274.667 470.75,269C457.917,263.333 446.667,255.667 437,246C427.333,236.333 419.667,225 414,212C408.333,199 405.5,185.167 405.5,170.5ZM426.5,853.5L426.5,512C426.5,500.333 428.75,489.333 433.25,479C437.75,468.667 443.917,459.583 451.75,451.75C459.583,443.917 468.667,437.75 479,433.25C489.333,428.75 500.333,426.5 512,426.5C523.667,426.5 534.667,428.75 545,433.25C555.333,437.75 564.417,443.917 572.25,451.75C580.083,459.583 586.25,468.667 590.75,479C595.25,489.333 597.5,500.333 597.5,512L597.5,853.5C597.5,865.167 595.25,876.167 590.75,886.5C586.25,896.833 580.083,905.833 572.25,913.5C564.417,921.167 555.333,927.25 545,931.75C534.667,936.25 523.667,938.5 512,938.5C500.333,938.5 489.333,936.25 479,931.75C468.667,927.25 459.583,921.167 451.75,913.5C443.917,905.833 437.75,896.833 433.25,886.5C428.75,876.167 426.5,865.167 426.5,853.5Z\";\n}\n\nlet viewBox = \"\";\nif (severity === \"attention\") {\n    viewBox = \"162 118 701 789\";\n} else if (severity === \"success\") {\n    viewBox = \"118 245 790 577\";\n} else if (severity === \"caution\") {\n    viewBox = \"406 86 213 875\";\n} else if (severity === \"critical\") {\n    viewBox = \"172 171 683 683\";\n} else if (severity === \"information\") {\n    viewBox = \"406 64 213 875\";\n}\n---\n\n<div class={`info-bar severity-${severity}`} role=\"alert\">\n    <div class=\"info-bar-icon\">\n        <span class={`info-badge severity-${severity}`}>\n            <svg viewBox={viewBox} fill=\"currentColor\">\n                <path d={path}></path>\n            </svg>\n        </span>\n    </div>\n    <div class={`info-bar-content ${wrap ? \"message-wrapped\" : \"\"}`}>\n        {title && <h5>{title}</h5>}\n        <p>\n            <slot />\n        </p>\n    </div>\n</div>\n"
  },
  {
    "path": "Documents/Website/src/components/InfoBar/InfoBar.scss",
    "content": ".info-badge {\n    display: flex;\n    align-items: center;\n    box-sizing: border-box;\n\tuser-select: none;\n\tmin-inline-size: 16px;\n\tmin-block-size: 16px;\n\tborder-radius: 16px;\n\tpadding: 2px 4px;\n\tcolor: var(--fds-text-on-accent-primary);\n\tline-height: var(--fds-caption-font-size);\n\tfont: {\n\t\tfamily: var(--fds-font-family-small);\n\t\tsize: var(--fds-caption-font-size);\n\t}\n\n    &.severity- {\n\t\t&attention {\n\t\t\tbackground-color: var(--fds-system-attention);\n\t\t}\n\t\t&success {\n\t\t\tbackground-color: var(--fds-system-success);\n\t\t}\n\t\t&caution {\n\t\t\tbackground-color: var(--fds-system-caution);\n\t\t}\n\t\t&critical {\n\t\t\tbackground-color: var(--fds-system-critical);\n\t\t}\n\t\t&information {\n\t\t\tbackground-color: var(--fds-system-solid-neutral);\n\t\t}\n\t}\n\tsvg {\n\t\tinline-size: 8px;\n\t\tblock-size: 8px;\n\t\tfill: currentColor;\n\t}\n}\n\n.info-bar {\n    display: flex;\n    align-items: center;\n    position: relative;\n\tmin-block-size: 48px;\n\tpadding-inline-start: 15px;\n\tbox-sizing: border-box;\n\tuser-select: none;\n\tbackground-clip: padding-box;\n\tfont-family: var(--fds-font-family-text);\n\tborder: 1px solid var(--fds-card-stroke-default);\n\tborder-radius: var(--fds-control-corner-radius);\n    margin-bottom: 16px;\n\t&.severity- {\n\t\t&information {\n\t\t\tbackground-color: var(--fds-card-background-secondary);\n\t\t}\n\t\t&success {\n\t\t\tbackground-color: var(--fds-system-background-success);\n\t\t}\n\t\t&caution {\n\t\t\tbackground-color: var(--fds-system-background-caution);\n\t\t}\n\t\t&critical {\n\t\t\tbackground-color: var(--fds-system-background-critical);\n\t\t}\n\t\t&attention {\n\t\t\tbackground-color: var(--fds-system-background-attention);\n\t\t}\n\t}\n\t&-icon {\n\t\talign-self: flex-start;\n\t\tdisplay: flex;\n\t\tflex: 0 0 auto;\n\t\tmargin: {\n\t\t\tblock-start: 16px;\n\t\t}\n\t}\n\t&-content {\n        display: flex;\n        align-items: center;\n        flex-wrap: wrap;\n\t\tposition: relative;\n\t\tbox-sizing: border-box;\n\t\tflex: 1 1 auto;\n\t\tmargin: {\n\t\t\tinline-start: 13px;\n\t\t\tblock-start: 7px;\n\t\t\tblock-end: 7px;\n\t\t}\n\t\t&.message-wrapped,\n\t\t&.action-wrapped {\n\t\t\tmargin: {\n\t\t\t\tblock-start: 13px;\n\t\t\t\tblock-end: 15px;\n\t\t\t}\n\t\t}\n\t\t&.message-wrapped {\n\t\t\th5,\n\t\t\tp {\n\t\t\t\talign-self: flex-start;\n\t\t\t}\n\t\t\t.info-bar-action {\n\t\t\t\tmargin-inline-end: 50%;\n\t\t\t}\n\t\t}\n\t\t&.action-wrapped .info-bar-action {\n\t\t\tpadding-block-start: 16px;\n\t\t}\n\t}\n\th5,\n\tp {\n\t\tcolor: var(--text-primary);\n\t\tmargin: 0;\n\t\tline-height: 20px;\n\t\tfont: {\n\t\t\tsize: var(--body-font-size);\n\t\t\tweight: 400;\n\t\t}\n\t}\n\th5 {\n\t\tfont-weight: 600;\n\t\tmargin-inline-end: 12px;\n\t}\n\tp {\n\t\tflex: 1 1 auto;\n\t\tmargin-inline-end: 15px;\n\t}\n}"
  },
  {
    "path": "Documents/Website/src/components/Navbar/Navbar.astro",
    "content": "---\nimport \"./Navbar.scss\";\nimport Logo from \"../../assets/images/NanaZip.svg\";\nimport NavIcon from '@fluentui/svg-icons/icons/navigation_24_regular.svg';\nimport HomeIcon from '@fluentui/svg-icons/icons/home_20_regular.svg';\nimport DownloadIcon from '@fluentui/svg-icons/icons/arrow_download_20_regular.svg';\n---\n\n<header class=\"navbar\">\n    <a class=\"btn btn-accent skip-to-content\" href=\"#main\">Skip to main content</a>\n    <a class=\"logo\" href=\"/\">\n        <Logo height=\"40\" width=\"40\" />\n        <span>NanaZip</span>\n    </a>\n    <button title=\"Menu\" aria-label=\"Menu\" class=\"menu-button\">\n        <NavIcon fill=\"currentColor\" />\n    </button>\n    <nav>\n        <div class=\"nav-items\">\n            <a class=\"btn\" href=\"/\">\n                <HomeIcon fill=\"currentColor\" />\n                <span>Home</span>\n            </a>\n            <a class=\"btn\" href=\"/downloads\">\n                <DownloadIcon fill=\"currentColor\" />\n                <span>Downloads</span>\n            </a>\n        </div>\n        <a\n            class=\"btn icon-button\"\n            title=\"GitHub repository\"\n            aria-label=\"GitHub repository\"\n            href=\"https://github.com/M2Team/NanaZip\"\n        >\n            <svg\n                xmlns=\"http://www.w3.org/2000/svg\"\n                width=\"20\"\n                height=\"20\"\n                viewBox=\"0 0 98 96\"\n                fill=\"currentColor\"\n            >\n                <g clip-path=\"url(#clip0_730_27126)\">\n                    <path\n                        d=\"M41.4395 69.3848C28.8066 67.8535 19.9062 58.7617 19.9062 46.9902C19.9062 42.2051 21.6289 37.0371 24.5 33.5918C23.2559 30.4336 23.4473 23.7344 24.8828 20.959C28.7109 20.4805 33.8789 22.4902 36.9414 25.2656C40.5781 24.1172 44.4062 23.543 49.0957 23.543C53.7852 23.543 57.6133 24.1172 61.0586 25.1699C64.0254 22.4902 69.2891 20.4805 73.1172 20.959C74.457 23.543 74.6484 30.2422 73.4043 33.4961C76.4668 37.1328 78.0937 42.0137 78.0937 46.9902C78.0937 58.7617 69.1934 67.6621 56.3691 69.2891C59.623 71.3945 61.8242 75.9883 61.8242 81.252L61.8242 91.2051C61.8242 94.0762 64.2168 95.7031 67.0879 94.5547C84.4102 87.9512 98 70.6289 98 49.1914C98 22.1074 75.9883 6.69539e-07 48.9043 4.309e-07C21.8203 1.92261e-07 -1.9479e-07 22.1074 -4.3343e-07 49.1914C-6.20631e-07 70.4375 13.4941 88.0469 31.6777 94.6504C34.2617 95.6074 36.75 93.8848 36.75 91.3008L36.75 83.6445C35.4102 84.2188 33.6875 84.6016 32.1562 84.6016C25.8398 84.6016 22.1074 81.1563 19.4277 74.7441C18.375 72.1602 17.2266 70.6289 15.0254 70.3418C13.877 70.2461 13.4941 69.7676 13.4941 69.1934C13.4941 68.0449 15.4082 67.1836 17.3223 67.1836C20.0977 67.1836 22.4902 68.9063 24.9785 72.4473C26.8926 75.2227 28.9023 76.4668 31.2949 76.4668C33.6875 76.4668 35.2187 75.6055 37.4199 73.4043C39.0469 71.7773 40.291 70.3418 41.4395 69.3848Z\"\n                    ></path>\n                </g>\n                <defs>\n                    <clipPath id=\"clip0_730_27126\">\n                        <rect width=\"98\" height=\"96\" fill=\"white\"></rect>\n                    </clipPath>\n                </defs>\n            </svg>\n\n            <span>GitHub repository</span>\n        </a>\n    </nav>\n</header>\n\n<script src=\"./Navbar.ts\" />"
  },
  {
    "path": "Documents/Website/src/components/Navbar/Navbar.scss",
    "content": ".navbar {\n    position: sticky;\n    top: 0;\n    z-index: 1000;\n    background-color: var(--fds-layer-background-default);\n    border-bottom: 1px solid var(--fds-surface-stroke-flyout);\n    backdrop-filter: blur(60px);\n    padding: 8px;\n    gap: 8px;\n\n    display: flex;\n    justify-content: space-between;\n    flex-direction: row;\n    align-items: center;\n\n    & .btn:not(.skip-to-content), button {\n        padding: 8px;\n        background-color: transparent;\n        align-items: center;\n        gap: 8px;\n\n        & svg {\n            display: block;\n        }\n\n        &:hover {\n            background-color: var(--fds-subtle-fill-secondary);\n        }\n\n        &:active {\n            background-color: var(--fds-subtle-fill-tertiary);\n            color: var(--fds-text-secondary);\n        }\n    }\n\n    & .btn {\n        display: flex;\n    }\n}\n\nnav, .nav-items {\n    display: flex;\n    align-items: center;\n    flex-direction: row;\n    gap: 8px;\n}\n\nnav {\n    flex: 1;\n    justify-content: space-between;\n}\n\n.logo {\n    display: flex;\n    align-items: center;\n    color: var(--fds-text-primary);\n    text-decoration: none;\n    font-size: var(--fds-body-large-font-size);\n    gap: 8px;\n    margin-right: 8px;\n}\n\n.logo:active {\n    color: var(--fds-text-secondary);\n}\n\n.skip-to-content {\n    position: absolute;\n    left: -9999px;\n    top: 0;\n    overflow: hidden;\n\n    &:focus {\n        left: 0;\n        z-index: 1001;\n    }\n}\n\n.menu-button {\n    display: none;\n}\n\n.icon-button>span:not(.icon) {\n    display: none;\n}\n\n@media screen and (max-width: 768px) {\n    .navbar {\n        flex-wrap: wrap;\n    }\n\n    nav, .nav-items {\n        flex-direction: column;\n        align-items: stretch;\n    }\n\n    nav {\n        flex-basis: 100%;\n        display: none;\n        justify-content: unset;\n\n        &.active {\n            display: flex;\n        }\n    }\n\n    .menu-button {\n        display: unset;\n    }\n\n    .icon-button > span:not(.icon) {\n        display: unset;\n    }\n}\n\n.icon {\n    font-size: 20px;\n}\n\n.icon-home::before {\n    content: '\\F480';\n}\n\n.icon-download::before {\n    content: '\\F150';\n}\n\n:global(body.active) {\n    overflow-y: hidden;\n}"
  },
  {
    "path": "Documents/Website/src/components/Navbar/Navbar.ts",
    "content": "document.querySelector('.menu-button')?.addEventListener('click', () => {\n    const nav = document.querySelector('nav');\n    if (nav) {\n        nav.classList.toggle('active');\n    }\n});"
  },
  {
    "path": "Documents/Website/src/components/PageSection/PageSection.astro",
    "content": "---\nimport './PageSection.scss';\n\ninterface Props {\n    header: string;\n}\n\nconst { header } = Astro.props;\n---\n\n<div class=\"page-section\">\n    <div class=\"page-section-left\">\n        <h1>{header}</h1>\n        <slot name=\"description\" />\n    </div>\n    <div class=\"page-section-right\">\n        <slot />\n    </div>\n</div>"
  },
  {
    "path": "Documents/Website/src/components/PageSection/PageSection.scss",
    "content": ".page-section {\n    padding: 72px;\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    gap: 72px;\n    min-height: 50vh;\n\n    & .subtitle {\n        font-size: var(--fds-subtitle-font-size);\n        line-height: 1.65;\n        margin: 12px 0;\n    }\n\n    &-left {\n        display: flex;\n        flex-direction: column;\n        justify-items: center;\n        flex: 1 1 0;\n        min-width: 0;\n    }\n\n    &-right {\n        flex: 1 1 0;\n        min-width: 480px;\n    }\n\n    @media screen and (width < 960px) {\n        padding: 36px;\n        gap: 36px;\n        flex-direction: column;\n        align-items: center;\n        min-height: unset;\n\n        &-left {\n            align-items: center;\n            text-align: center;\n            flex: auto;\n        }\n\n        &-right {\n            min-width: 0;\n            flex: auto;\n        }\n    }\n}"
  },
  {
    "path": "Documents/Website/src/components/StoreBadge/StoreBadge.astro",
    "content": "---\ninterface Props {\n    productId: string;\n    windowMode?: \"direct\" | \"full\";\n    size?: \"large\" | \"small\";\n    campaignId?: string;\n}\n\nconst { productId, windowMode = \"direct\", size = \"large\", campaignId } = Astro.props;\n\nimport \"./StoreBadge.css\";\n---\n\n<script\n    type=\"module\"\n    src=\"https://get.microsoft.com/badge/ms-store-badge.bundled.js\"></script>\n\n<noscript>\n    <a\n        class=\"store-badge-link\"\n        href={`https://apps.microsoft.com/detail/${productId}?referrer=appbadge&mode=${windowMode}&cid=${campaignId}`}\n        target=\"_blank\"\n    >\n        <picture>\n            <source\n                srcset=\"https://get.microsoft.com/images/en-us%20dark.svg\"\n                media=\"(prefers-color-scheme: light)\"\n            />\n            <source\n                srcset=\"https://get.microsoft.com/images/en-us%20light.svg\"\n                media=\"(prefers-color-scheme: dark)\"\n            />\n            <img\n                src=\"https://get.microsoft.com/images/en-us%20dark.svg\"\n                class={size}\n                alt=\"Microsoft Store app badge\"\n            />\n        </picture>\n    </a>\n</noscript>\n\n<ms-store-badge\n    productid={productId}\n    window-mode={windowMode}\n    theme=\"auto\"\n    size={size}\n    language=\"en-us\"\n    animation=\"on\"\n    cid={campaignId}\n>\n</ms-store-badge>"
  },
  {
    "path": "Documents/Website/src/components/StoreBadge/StoreBadge.css",
    "content": ".store-badge-link img.large {\n    height: 104px;\n}\n\n.store-badge-link img {\n    display: block;\n    transition: 0.35s ease;\n}\n\n.store-badge-link img:hover {\n    transform: translate(0, -4px);\n    cursor: pointer;\n    box-shadow: 0 12px 40px 20px rgba(0, 0, 0, 0.05);\n}\n\niframe {\n    border: none;\n    width: 0;\n    height: 0;\n}\n\nms-store-badge::part(img), .store-badge-link img {\n    max-width: 100%;\n    min-width: 200px;\n}\n\nms-store-badge, .store-badge-link {\n    display: block;\n    width: fit-content;\n    line-height: 0;\n}"
  },
  {
    "path": "Documents/Website/src/components/StoreBadge/StoreBadge.ts",
    "content": "function changeStoreBadge(darkMode: boolean) {\n    document.querySelectorAll(\"ms-store-badge\").forEach((badge) => {\n        badge.setAttribute(\"theme\", darkMode ? \"light\" : \"dark\");\n    });\n}\n\nwindow.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {\n    changeStoreBadge(e.matches);\n});"
  },
  {
    "path": "Documents/Website/src/components/ThemedLocalPicture/ThemedLocalPicture.astro",
    "content": "---\nimport type { ImageMetadata } from \"astro\";\nimport { getImage } from 'astro:assets';\n\ninterface Props {\n    lightSrc: string | ImageMetadata;\n    darkSrc: string | ImageMetadata;\n    alt: string;\n    loading?: \"eager\" | \"lazy\";\n    class?: string;\n    fetchPriority?: \"high\" | \"low\" | \"auto\";\n}\n\nconst { lightSrc, darkSrc, alt, loading = \"lazy\", class: className, fetchPriority = \"auto\" } = Astro.props as Props;\n\nconst lightImgAvif = await getImage({\n    src: lightSrc,\n    format: 'avif',\n    layout: 'full-width'\n});\n\nconst lightImgWebp = await getImage({\n    src: lightSrc,\n    format: 'webp',\n    layout: 'full-width'\n});\n\nconst lightImgPng = await getImage({\n    src: lightSrc,\n    format: 'png',\n    layout: 'full-width'\n});\n\nconst darkImgAvif = await getImage({\n    src: darkSrc,\n    format: 'avif',\n    layout: 'full-width'\n});\n\nconst darkImgWebp = await getImage({\n    src: darkSrc,\n    format: 'webp',\n    layout: 'full-width'\n});\n\nconst darkImgPng = await getImage({\n    src: darkSrc,\n    format: 'png',\n    layout: 'full-width'\n});\n---\n\n<picture>\n    <source media=\"(prefers-color-scheme: light)\" srcset={lightImgAvif.srcSet.attribute} type=\"image/avif\" />\n    <source media=\"(prefers-color-scheme: light)\" srcset={lightImgWebp.srcSet.attribute} type=\"image/webp\" />\n    <source media=\"(prefers-color-scheme: light)\" srcset={lightImgPng.srcSet.attribute} type=\"image/png\" />\n\n    <source media=\"(prefers-color-scheme: dark)\" srcset={darkImgAvif.srcSet.attribute} type=\"image/avif\" />\n    <source media=\"(prefers-color-scheme: dark)\" srcset={darkImgWebp.srcSet.attribute} type=\"image/webp\" />\n    <source media=\"(prefers-color-scheme: dark)\" srcset={darkImgPng.srcSet.attribute} type=\"image/png\" />\n\n    <img class={className} srcset={lightImgPng.srcSet.attribute} alt={alt} loading={loading} fetchpriority={fetchPriority} {...lightImgPng.attributes} />\n</picture>"
  },
  {
    "path": "Documents/Website/src/components/Tree/Tree.astro",
    "content": "---\ninterface Props {\n    text: string;\n}\n\nconst { text } = Astro.props;\n\nimport './Tree.css';\n---\n\n<div class=\"tree\">\n    <p>\n        <slot name=\"icon\" />\n        {text}\n    </p>\n\n    <slot />\n</div>"
  },
  {
    "path": "Documents/Website/src/components/Tree/Tree.css",
    "content": ".tree > .tree {\n    margin-left: 16px;\n}\n\n.tree p {\n    margin-top: 8px;\n    margin-bottom: 8px;\n\n    display: flex;\n    align-items: center;\n    gap: 4px;\n}"
  },
  {
    "path": "Documents/Website/src/layouts/Layout.astro",
    "content": "---\nimport '../assets/styles/theme.css';\nimport '../assets/styles/global.css';\nimport '../assets/styles/text.css';\nimport '../assets/styles/image.css';\nimport '../assets/styles/button.css';\nimport Navbar from '../components/Navbar/Navbar.astro';\nimport Footer from '../components/Footer/Footer.astro';\n\ninterface Props {\n\ttitle?: string;\n\tdescription: string;\n}\n\nconst { title, description } = Astro.props;\n---\n\n<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"UTF-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width\" />\n\t\t<meta name=\"generator\" content={Astro.generator} />\n\t\t<meta name=\"description\" content={description} />\n\t\t<meta name=\"author\" content=\"M2-Team\" />\n\t\t<title>{title ? `${title} - NanaZip` : \"NanaZip\"}</title>\n\n\t\t<link rel=\"icon\" href=\"/NanaZip.ico\" />\n\t</head>\n\t<body>\n\t\t<Navbar />\n\t\t<slot />\n\t\t<Footer />\n\t</body>\n</html>"
  },
  {
    "path": "Documents/Website/src/pages/downloads.astro",
    "content": "---\nimport Layout from \"../layouts/Layout.astro\";\nimport StoreBadge from \"../components/StoreBadge/StoreBadge.astro\";\nimport InfoBar from \"../components/InfoBar/InfoBar.astro\";\n---\n\n<Layout title=\"Downloads\" description=\"NanaZip download links\">\n    <main id=\"main\">\n        <article>\n            <h1>Downloads</h1>\n\n            <InfoBar title=\"Warning\" severity=\"caution\" wrap={true}>\n                Only GitHub, Microsoft Store, My Digital Life Forums,\n                SourceForge, and Windows App Community hosts official downloads.\n            </InfoBar>\n\n            <!-- Microsoft Store -->\n            <h2>Microsoft Store (recommended)</h2>\n\n            <p><b>NanaZip</b></p>\n            <StoreBadge\n                productId=\"9n8g7tscl18r\"\n                windowMode=\"full\"\n                size=\"small\"\n\t\t\t\tcampaignId=\"nanaziporg\"\n            />\n            <p><b>NanaZip Preview</b></p>\n            <StoreBadge\n                productId=\"9NZL0LRP1BNL\"\n                windowMode=\"full\"\n\t\t\t\tcampaignId=\"nanaziporg\"\n                size=\"small\"\n            />\n\n            <!-- SourceForge -->\n            <h2>SourceForge</h2>\n            <a class=\"btn btn-accent\" href=\"https://sourceforge.net/projects/nanazip/\">Go to SourceForge</a>\n\n            <!-- GitHub Releases -->\n            <h2>GitHub Releases</h2>\n            <InfoBar title=\"Attention\" severity=\"attention\" wrap={true}>\n                GitHub Releases include experimental portable versions. These\n                versions are intended for users without access to MSIX (such as\n                Windows PE and Wine).\n                <br />\n                Some features are not available (such as File Manager), and no support\n                is provided for these versions.\n            </InfoBar>\n            <a class=\"btn btn-accent\" href=\"https://github.com/M2Team/NanaZip/releases/latest\" >Latest stable release</a>\n            <br />\n            <a href=\"https://github.com/M2Team/NanaZip/releases\">All releases</a>\n        </article>\n    </main>\n</Layout>\n\n<style>\n    a {\n        margin-top: 8px;\n        margin-bottom: 8px;\n    }\n</style>"
  },
  {
    "path": "Documents/Website/src/pages/index.astro",
    "content": "---\nimport Layout from \"../layouts/Layout.astro\";\nimport PageSection from \"../components/PageSection/PageSection.astro\";\nimport StoreBadge from \"../components/StoreBadge/StoreBadge.astro\";\nimport ThemedLocalPicture from \"../components/ThemedLocalPicture/ThemedLocalPicture.astro\";\nimport Tree from \"../components/Tree/Tree.astro\";\n\nimport '../assets/styles/pages/index.css';\n\nimport heroImageDark from \"../assets/images/MainWindowDarkMode.png\";\nimport heroImageLight from \"../assets/images/MainWindowLightMode.png\";\n\nimport contextMenuDark from \"../assets/images/ContextMenuDark.png\";\nimport contextMenuLight from \"../assets/images/ContextMenuLight.png\";\n\nimport ArchiveFile from \"../assets/images/ArchiveFile.svg\";\n\nimport RightArrow from '@fluentui/svg-icons/icons/arrow_right_32_regular.svg';\nimport FileIcon from '@fluentui/svg-icons/icons/document_20_regular.svg';\nimport FolderIcon from '@fluentui/svg-icons/icons/folder_20_regular.svg';\n---\n\n<Layout description=\"NanaZip home page\">\n\t<main id=\"main\">\n\t\t<PageSection header=\"NanaZip\">\n\t\t\t<Fragment slot=\"description\">\n\t\t\t\t<p class=\"subtitle\">\n\t\t\t\t\tThe 7-Zip derivative intended for the modern Windows\n\t\t\t\t\texperience\n\t\t\t\t</p>\n\t\t\t\t<StoreBadge\n\t\t\t\t\tproductId=\"9n8g7tscl18r\"\n\t\t\t\t\twindowMode=\"full\"\n\t\t\t\t\tsize=\"small\"\n\t\t\t\t\tcampaignId=\"nanaziporg\"\n\t\t\t\t/>\n\t\t\t\t<span>Or check out <a href=\"/downloads\">alternative download options</a></span>\n\t\t\t</Fragment>\n\t\t\t<ThemedLocalPicture\n\t\t\t\tlightSrc={heroImageLight}\n\t\t\t\tdarkSrc={heroImageDark}\n\t\t\t\talt=\"\"\n\t\t\t\tloading=\"eager\"\n\t\t\t\tfetchPriority=\"high\"\n\t\t\t/>\n\t\t</PageSection>\n\n\t\t<PageSection header=\"Modern UI\">\n\t\t\t<Fragment slot=\"description\">\n\t\t\t\t<p class=\"subtitle\">\n\t\t\t\t\tNanaZip supports the new Windows 11 context menu and adopts the\n\t\t\t\t\tFluent Design System, using the Mica material and adding dark\n\t\t\t\t\tmode support.\n\t\t\t\t</p>\n\n\t\t\t\t<p class=\"subtitle\">\n\t\t\t\t\tNanaZip supports Windows accessibility features and\n\t\t\t\t\tmeets <a href=\"/section508\">Section 508 compliance standards</a>.\n\t\t\t\t</p>\n\t\t\t</Fragment>\n\n\t\t\t<ThemedLocalPicture\n\t\t\t\tclass=\"image-card\"\n\t\t\t\tlightSrc={contextMenuLight}\n\t\t\t\tdarkSrc={contextMenuDark}\n\t\t\t\talt=\"\"\n\t\t\t\tloading=\"lazy\"\n\t\t\t/>\n\t\t</PageSection>\n\n\t\t<PageSection header=\"Smart Extraction\">\n\t\t\t<Fragment slot=\"description\">\n\t\t\t\t<p class=\"subtitle\">\n\t\t\t\t\tSmart Extraction saves you clicks for archives with a single root item,\n\t\t\t\t\tand keeps your files organized for those with multiple root items.\n\t\t\t\t</p>\n\t\t\t\t<p class=\"subtitle\">\n\t\t\t\t\tIn addition, you can configure NanaZip to start Smart Extraction\n\t\t\t\t\tupon opening an archive, instead of opening NanaZip File Manager.\n\t\t\t\t</p>\n\t\t\t</Fragment>\n\t\t\t\n\t\t\t<div class=\"se-demo-scenario\" role=\"img\" aria-label=\"A demonstration of Smart Extraction. Archives with a single file or a single folder in the root will be extracted directly. Archives with multiple root elements will have their contents placed in a newly created folder.\">\n\t\t\t\t<div class=\"card\" aria-hidden=\"true\">\n\t\t\t\t\t<Tree text=\"Archive1.zip\">\n\t\t\t\t\t\t<ArchiveFile width=\"20\" height=\"20\" slot=\"icon\" />\n\t\t\t\t\n\t\t\t\t\t\t<Tree text=\"Music.mp3\">\n\t\t\t\t\t\t\t<FileIcon fill=\"currentColor\" slot=\"icon\" />\n\t\t\t\t\t\t</Tree>\n\t\t\t\t\t</Tree>\n\n\t\t\t\t\t<Tree text=\"Archive2.zip\">\n\t\t\t\t\t\t<ArchiveFile width=\"20\" height=\"20\" slot=\"icon\" />\n\t\t\t\t\n\t\t\t\t\t\t<Tree text=\"Image.jpg\">\n\t\t\t\t\t\t\t<FileIcon fill=\"currentColor\" slot=\"icon\" />\n\t\t\t\t\t\t</Tree>\n\n\t\t\t\t\t\t<Tree text=\"Document.docx\">\n\t\t\t\t\t\t\t<FileIcon fill=\"currentColor\" slot=\"icon\" />\n\t\t\t\t\t\t</Tree>\n\t\t\t\t\t</Tree>\n\t\t\t\t</div>\n\n\t\t\t\t<RightArrow fill=\"currentColor\" id=\"right-arrow\" />\n\n\t\t\t\t<div class=\"card\" aria-hidden=\"true\">\n\t\t\t\t\t<Tree text=\"Music.mp3\">\n\t\t\t\t\t\t<FileIcon fill=\"currentColor\" slot=\"icon\" />\n\t\t\t\t\t</Tree>\n\n\t\t\t\t\t<Tree text=\"Archive2\">\n\t\t\t\t\t\t<FolderIcon fill=\"currentColor\" slot=\"icon\" />\n\n\t\t\t\t\t\t<Tree text=\"Image.jpg\">\n\t\t\t\t\t\t\t<FileIcon fill=\"currentColor\" slot=\"icon\" />\n\t\t\t\t\t\t</Tree>\n\n\t\t\t\t\t\t<Tree text=\"Document.docx\">\n\t\t\t\t\t\t\t<FileIcon fill=\"currentColor\" slot=\"icon\" />\n\t\t\t\t\t\t</Tree>\n\t\t\t\t\t</Tree>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</PageSection>\n\n\t\t<PageSection header=\"File formats\">\n\t\t\t<p slot=\"description\" class=\"subtitle\">\n\t\t\t\tNanaZip supports additional file formats on top of 7-zip, such as Zstandard, WASM, Electron ASAR, and .NET Single File Bundle.\n\t\t\t</p>\n\n\t\t\t<div class=\"format-list\" role=\"list\" aria-label=\"List of formats NanaZip supports on top of 7-zip's\">\n\t\t\t\t<div class=\"card\" role=\"listitem\">Brotli</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">Lizard</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">LZ4</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">LZ5</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">Zstandard</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">Fast-LZMA2</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">NSIS</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">UFS</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">UFS2</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">.NET Single File</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">Electron ASAR</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">ROMFS</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">ZealFS</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">WASM</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">CB7</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">CBZ</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">CBR</div>\n\t\t\t</div>\n\t\t</PageSection>\n\n\t\t<PageSection header=\"Security\">\n\t\t\t<Fragment slot=\"description\">\n\t\t\t\t<p class=\"subtitle\">NanaZip integrates multiple security mitigations to reduce the impact of vulnerabilities.</p>\n\t\t\t\t<p class=\"subtitle\">These mitigations are enabled by default and configurable using <a href=\"https://github.com/M2Team/NanaZip/blob/main/Documents/Policies.md\">Group Policy</a>.</p>\n\t\t\t</Fragment>\n\n\t\t\t<div class=\"format-list\" role=\"list\" aria-label=\"Security mitigations NanaZip includes\">\n\t\t\t\t<div class=\"card\" role=\"listitem\">Control Flow Guard</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">Shadow Stack</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\" style=\"width: max-content\">Dynamic code generation prohibition</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">Package Integrity</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\">Mark-Of-The-Web</div>\n\t\t\t\t<div class=\"card\" role=\"listitem\" style=\"width: max-content\">Archive format restrictions</div>\n\t\t\t</div>\n\t\t</PageSection>\n\t</main>\n</Layout>\n"
  },
  {
    "path": "Documents/Website/src/pages/section508.astro",
    "content": "<!doctype HTML><html lang=\"en\"><head><title>NanaZip Accessibility Conformance Report</title><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta charset=\"utf-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"></head><body id=\"openACR\"><style>body#openACR {\n      padding-left: 35px;\n    }\n    h2,\n    h3 {\n      position: relative;\n    }\n    h2 a.header-anchor,\n    h3 a.header-anchor {\n      position: absolute;\n      left: -2rem;\n    }\n    h2 a.header-anchor:hover svg,\n    h2 a.header-anchor:focus svg,\n    h2 a.header-anchor:focus-within svg,\n    h3 a.header-anchor:hover svg,\n    h3 a.header-anchor:focus svg,\n    h3 a.header-anchor:focus-within svg {\n      fill: #0000EE;\n      opacity: 1;\n    }\n    h2 a.header-anchor svg,\n    h3 a.header-anchor svg {\n      width: 28px;\n      height: 28px;\n      opacity: .3;\n    }\n    @media all and (max-width: 63.99em) {\n      h2 a.header-anchor,\n      h3 a.header-anchor {\n        position:relative;\n        opacity: 1;\n        left: 0;\n        vertical-align: top\n      }\n    }\n    a.header-anchor {\n      opacity: 0.4;\n      font-size: small;\n      text-decoration: none;\n      position: relative;\n      /* left: 20px; */\n      -webkit-transition: opacity 1s, font-size 1s;\n      -moz-transition: opacity 1s, font-size 1s;\n      -o-transition: opacity 1s, font-size 1s;\n      transition: opacity 1s, font-size 1s;\n    }\n    a.header-anchor:focus,a.header-anchor:hover {\n      text-decoration: underline;\n      font-size: large;\n      opacity: 1\n    }\n    .visuallyhidden {\n      border: 0;\n      clip: rect(0 0 0 0);\n      clip-path: inset(50%);\n      height: 1px;\n      margin: -1px;\n      overflow: hidden;\n      padding: 0;\n      position: absolute;\n      width: 1px;\n      white-space: nowrap;\n      &.focusable {\n          &:active,\n          &:focus {\n              clip: auto;\n              clip-path: none;\n              height: auto;\n              margin: 0;\n              overflow: visible;\n              position: static;\n              width: auto;\n              white-space: inherit;\n          }\n      }\n    }</style> <main><div class=\"grid-container\"><h1 class=\"svelte-1nee40z\">NanaZip Accessibility Conformance Report</h1>\n\nBased on VPAT® 2.4 WCAG 2.1 and Revised Section 508 Edition <h2 id=\"name-of-product-version-download\" class=\"svelte-1y7sq6j\">Name of Product/Version <a href=\"#name-of-product-version-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  NanaZip  <h2 id=\"report-date-download\" class=\"svelte-1y7sq6j\">Report Dates and Version <a href=\"#report-date-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <ul><li>Report Date: 2026/2/25</li> <li>Last Modified Date: 2026/2/25</li> <li>Version: nanazip-1</li></ul> <h2 id=\"product-description-download\" class=\"svelte-1y7sq6j\">Product Description <a href=\"#product-description-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <p>NanaZip is an open source file archiver intended for the modern Windows experience, forked from the source code of well-known open source file archiver 7-Zip.</p>\n <h2 id=\"contact-information-download\" class=\"svelte-1y7sq6j\">Contact Information <a href=\"#contact-information-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>   <h3 id=\"author-download\" class=\"svelte-1y7sq6j\">Author Information <a href=\"#author-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3> <ul><li>Name: Kenji Mouri</li> <li>Company: M2-Team</li>  <li>Email: <a href=\"mailto:Kenji.Mouri@outlook.com\" target=\"_blank\">Kenji.Mouri@outlook.com <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li>  <li>Website: <a href=\"http://nanazip.org/\" target=\"_blank\">http://nanazip.org/ <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li></ul>  <h3 id=\"vendor-download\" class=\"svelte-1y7sq6j\">Vendor Information <a href=\"#vendor-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3> <ul><li>Name: Kenji Mouri</li> <li>Company: M2-Team</li>  <li>Email: <a href=\"mailto:Kenji.Mouri@outlook.com\" target=\"_blank\">Kenji.Mouri@outlook.com <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li>  <li>Website: <a href=\"http://nanazip.org/\" target=\"_blank\">http://nanazip.org/ <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></li></ul>   <h2 id=\"applicable-standards-guidelines-download\" class=\"svelte-1y7sq6j\">Applicable Standards/Guidelines <a href=\"#applicable-standards-guidelines-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2> \nThis report covers the degree of conformance for the following accessibility standard/guidelines:\n\n<table border=\"1\" style=\"border-collapse: collapse\"><thead><tr><th>Standard/Guideline</th> \n      <th>Included In Report</th></tr></thead> <tbody><tr><td><a href=\"https://www.w3.org/TR/WCAG21/\" target=\"_blank\">Web Content Accessibility Guidelines 2.1 <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td><ul><li>Table 1: Success Criteria, Level A</li><li>Table 2: Success Criteria, Level AA</li><li>Table 3: Success Criteria, Level AAA</li></ul></td> </tr><tr><td><a href=\"https://www.access-board.gov/ict/\" target=\"_blank\">Revised Section 508 standards published January 18, 2017 and corrected January 22, 2018 <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td><ul><li>Chapter 3: Functional Performance Criteria (FPC)</li><li>Chapter 4: Hardware</li><li>Chapter 5: Software</li><li>Chapter 6: Support Documentation and Services</li></ul></td> </tr></tbody></table> <h2 id=\"terms-download\" class=\"svelte-1y7sq6j\">Terms <a href=\"#terms-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2> \nThe terms used in the Conformance Level information are defined as follows:\n<ul><li><strong>Supports</strong>: The functionality of the product has at least one method that meets the criterion without known defects or meets with equivalent facilitation.</li><li><strong>Partially Supports</strong>: Some functionality of the product does not meet the criterion.</li><li><strong>Does Not Support</strong>: The majority of product functionality does not meet the criterion.</li><li><strong>Not Applicable</strong>: The criterion is not relevant to the product.</li><li><strong>Not Evaluated</strong>: The product has not been evaluated against the criterion. This can be used only in WCAG 2.x Level AAA.</li></ul> <h2 id=\"wcag-2.1-download\" class=\"svelte-1y7sq6j\">WCAG 2.1 Report <a href=\"#wcag-2.1-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>   <h3 id=\"success_criteria_level_a-download\" class=\"svelte-1y7sq6j\">Table 1: Success Criteria, Level A <a href=\"#success_criteria_level_a-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>   <h3 id=\"success_criteria_level_aa-download\" class=\"svelte-1y7sq6j\">Table 2: Success Criteria, Level AA <a href=\"#success_criteria_level_aa-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>   <h3 id=\"success_criteria_level_aaa-download\" class=\"svelte-1y7sq6j\">Table 3: Success Criteria, Level AAA <a href=\"#success_criteria_level_aaa-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>  <h2 id=\"508-download\" class=\"svelte-1y7sq6j\">Revised Section 508 Report <a href=\"#508-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>   <h3 id=\"functional_performance_criteria-download\" class=\"svelte-1y7sq6j\">Chapter 3: Functional Performance Criteria (FPC) <a href=\"#functional_performance_criteria-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>  <table class=\"svelte-4eon1l\" border=\"1\" style=\"border-collapse: collapse\"><thead class=\"svelte-4eon1l\"><tr class=\"svelte-4eon1l\"><th class=\"svelte-4eon1l\">Criteria</th> \n      <th class=\"svelte-4eon1l\">Conformance Level</th> \n      <th class=\"svelte-4eon1l\">Remarks and Explanations</th></tr></thead> <tbody><tr class=\"result-row svelte-cn2gpq\" id=\"302.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.1\" target=\"_blank\">302.1 Without Vision <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.2\" target=\"_blank\">302.2 With Limited Vision <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.3\" target=\"_blank\">302.3 Without Perception of Color <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.4\" target=\"_blank\">302.4 Without Hearing <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.5-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.5\" target=\"_blank\">302.5 With Limited Hearing <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.6-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.6\" target=\"_blank\">302.6 Without Speech <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.7-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.7\" target=\"_blank\">302.7 With Limited Manipulation <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.8-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.8\" target=\"_blank\">302.8 With Limited Reach and Strength <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"302.9-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#302.9\" target=\"_blank\">302.9 With Limited Language, Cognitive, and Learning Abilities <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr></tbody></table> <h3 id=\"hardware-download\" class=\"svelte-1y7sq6j\">Chapter 4: Hardware <a href=\"#hardware-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>   <h3 id=\"software-download\" class=\"svelte-1y7sq6j\">Chapter 5: Software <a href=\"#software-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>  <table class=\"svelte-4eon1l\" border=\"1\" style=\"border-collapse: collapse\"><thead class=\"svelte-4eon1l\"><tr class=\"svelte-4eon1l\"><th class=\"svelte-4eon1l\">Criteria</th> \n      <th class=\"svelte-4eon1l\">Conformance Level</th> \n      <th class=\"svelte-4eon1l\">Remarks and Explanations</th></tr></thead> <tbody><tr class=\"result-row svelte-cn2gpq\" id=\"502.2.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.2.1\" target=\"_blank\">502.2.1 User Control of Accessibility Features <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.2.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.2.2\" target=\"_blank\">502.2.2 No Disruption of Accessibility Features <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.1\" target=\"_blank\">502.3.1 Object Information <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.2\" target=\"_blank\">502.3.2 Modification of Object Information <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.3\" target=\"_blank\">502.3.3 Row, Column, and Headers <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.4\" target=\"_blank\">502.3.4 Values <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.5-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.5\" target=\"_blank\">502.3.5 Modification of Values <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.6-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.6\" target=\"_blank\">502.3.6 Label Relationships <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.7-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.7\" target=\"_blank\">502.3.7 Hierarchical Relationships <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.8-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.8\" target=\"_blank\">502.3.8 Text <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.9-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.9\" target=\"_blank\">502.3.9 Modification of Text <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.10-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.10\" target=\"_blank\">502.3.10 List of Actions <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.11-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.11\" target=\"_blank\">502.3.11 Actions on Objects <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.12-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.12\" target=\"_blank\">502.3.12 Focus Cursor <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.13-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.13\" target=\"_blank\">502.3.13 Modification of Focus Cursor <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.3.14-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.3.14\" target=\"_blank\">502.3.14 Event Notification <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"502.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#502.4\" target=\"_blank\">502.4 Platform Accessibility Features <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.2\" target=\"_blank\">503.2 User Preferences <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Supports</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.3\" target=\"_blank\">503.3 Alternative User Interfaces <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.4.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.4.1\" target=\"_blank\">503.4.1 Caption Controls <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"503.4.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#503.4.2\" target=\"_blank\">503.4.2 Audio Description Controls <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.2\" target=\"_blank\">504.2 Content Creation or Editing <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.2.1-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.2.1\" target=\"_blank\">504.2.1 Preservation of Information Provided for Accessibility in Format Conversion <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.2.2-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.2.2\" target=\"_blank\">504.2.2 PDF Export <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.3-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.3\" target=\"_blank\">504.3 Prompts <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr><tr class=\"result-row svelte-cn2gpq\" id=\"504.4-download\"><td class=\"svelte-cn2gpq\"><a href=\"https://www.access-board.gov/ict/#504.4\" target=\"_blank\">504.4 Templates <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a></td> <td class=\"svelte-cn2gpq\"><ul><li><p>Not Applicable</p></li></ul></td> <td class=\"svelte-cn2gpq\"><ul></ul></td></tr></tbody></table> <h3 id=\"support_documentation_and_services-download\" class=\"svelte-1y7sq6j\">Chapter 6: Support Documentation and Services <a href=\"#support_documentation_and_services-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h3>    <h2 id=\"repository-download\" class=\"svelte-1y7sq6j\">Repository <a href=\"#repository-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <a href=\"https://github.com/M2Team/NanaZip\" target=\"_blank\">https://github.com/M2Team/NanaZip <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a> <h2 id=\"feedback-download\" class=\"svelte-1y7sq6j\">Feedback <a href=\"#feedback-download\" class=\"header-anchor svelte-1y7sq6j\"><span class=\"anchor-icon\" aria-hidden=\"true\"><svg focusable=\"false\" aria-hidden=\"true\" class=\"icon-link svelte-1y7sq6j\"><path d=\"M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z\"></path></svg></span> <span class=\"visuallyhidden\">Anchor link</span></a></h2>  <a href=\"https://github.com/M2Team/NanaZip\" target=\"_blank\">https://github.com/M2Team/NanaZip <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a> </div></main> <footer class=\"usa-footer usa-footer usa-footer--slim\"><div class=\"usa-footer__return-to-top\"><div class=\"grid-container\"><a href=\"#\">Return to top</a></div></div> <div class=\"usa-footer__secondary-section\"><div class=\"grid-container\"><div class=\"grid-row grid-gap\"><div class=\"grid-col\"><a href=\"https://github.com/GSA/openacr\" target=\"_blank\">OpenACR <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a> is a format maintained by the <a href=\"https://gsa.gov/\" target=\"_blank\">GSA <span class=\"visuallyhidden\">(opens in a new window or tab)</span></a>. The content is the responsibility of the author.\n          </div> <div class=\"grid-col\">This content is licensed under a <a href=\"https://opensource.org/licenses/MIT\" target=\"_blank\">MIT License <span>(opens in a new window or tab)</span></a>.</div></div></div></div></footer></body></html>"
  },
  {
    "path": "Documents/Website/tsconfig.json",
    "content": "{\n  \"extends\": \"astro/tsconfigs/strictest\",\n  \"include\": [\".astro/types.d.ts\", \"**/*\"],\n  \"exclude\": [\"dist\"]\n}\n"
  },
  {
    "path": "K7Base/K7Base.def",
    "content": "﻿LIBRARY\n\nEXPORTS\n\nK7BaseDetourTransactionBegin\nK7BaseDetourTransactionAbort\nK7BaseDetourTransactionCommit\nK7BaseDetourUpdateThread\nK7BaseDetourAttach\nK7BaseDetourDetach\n\nK7BaseHashCreate\nK7BaseHashDestroy\nK7BaseHashUpdate\nK7BaseHashFinal\nK7BaseHashGetSize\nK7BaseHashDuplicate\n\nK7BaseGetAllowedHandlerPolicy\nK7BaseGetAllowedCodecPolicy\nK7BaseGetWriteZoneIdExtractPolicy\n\nK7BaseDisableDynamicCodeGeneration\nK7BaseDisableChildProcessCreation\n\nK7BaseInitialize\n\nK7BaseModernFileTimeToLocalFileTime\nK7BaseModernLocalFileTimeToFileTime\n"
  },
  {
    "path": "K7Base/K7Base.h",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7Base.h\n * PURPOSE:    Definition for NanaZip Platform Base Public Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef K7_BASE\n#define K7_BASE\n\n#include <Mile.Mobility.Portable.Types.h>\n#ifndef MILE_MOBILITY_ENABLE_MINIMUM_SAL\n#include <sal.h>\n#endif // !MILE_MOBILITY_ENABLE_MINIMUM_SAL\n\n// Workaround for Windows SDK, which defines these types in #ifndef VOID block.\n// That design is terrible, but needs to have a workaround.\n#ifdef VOID\ntypedef char CHAR;\ntypedef short SHORT;\ntypedef long LONG;\n#endif // VOID\n\n#include <Windows.h>\n\n#ifndef K7_BASE_DETOURS\n#define K7_BASE_DETOURS\n\n/**\n * @brief Begin a new transaction for attaching or detaching detours.\n * @return Returns NO_ERROR if successful; otherwise, returns an error code.\n * @remark For more information, see DetourTransactionBegin.\n */\nEXTERN_C LONG MOAPI K7BaseDetourTransactionBegin();\n\n/**\n * @brief Abort the current transaction for attaching or detaching detours.\n * @return Returns NO_ERROR if the pending transaction was completely aborted;\n *         otherwise, returns an error code.\n * @remark For more information, see DetourTransactionAbort.\n */\nEXTERN_C LONG MOAPI K7BaseDetourTransactionAbort();\n\n/**\n * @brief Commit the current transaction for attaching or detaching detours.\n * @return Returns NO_ERROR if successful; otherwise, returns an error code.\n * @remark For more information, see DetourTransactionCommit.\n */\nEXTERN_C LONG MOAPI K7BaseDetourTransactionCommit();\n\n/**\n * @brief Enlist a thread for update in the current transaction.\n * @param ThreadHandle The handle of the thread to be updated with the pending\n *                     transaction. If hThread is equal to the current threads\n *                     pseudo handle (as returned by GetCurrentThread()) no\n *                     action is performed and NO_ERROR is returned.\n * @return Returns NO_ERROR if successful; otherwise, returns an error code.\n * @remark For more information, see DetourUpdateThread.\n */\nEXTERN_C LONG MOAPI K7BaseDetourUpdateThread(\n    _In_ HANDLE ThreadHandle);\n\n/**\n * @brief Attach a detour to a target function.\n * @param OriginalFunction Pointer to the target pointer to which the detour\n *                         will be attached.\n * @param DetouredFunction Pointer to the detour function.\n * @return Returns NO_ERROR if successful; otherwise, returns an error code.\n * @remark For more information, see DetourAttach.\n */\nEXTERN_C LONG MOAPI K7BaseDetourAttach(\n    _Inout_ PMO_POINTER OriginalFunction,\n    _In_ MO_POINTER DetouredFunction);\n\n/**\n * @brief Detach a detour from a target function.\n * @param OriginalFunction Pointer to the target pointer from which the detour\n *                         will be detached.\n * @param DetouredFunction Pointer to the detour function.\n * @return Returns NO_ERROR if successful; otherwise, returns an error code.\n * @remark For more information, see DetourDetach.\n */\nEXTERN_C LONG MOAPI K7BaseDetourDetach(\n    _Inout_ PMO_POINTER OriginalFunction,\n    _In_ MO_POINTER DetouredFunction);\n\n#endif // !K7_BASE_DETOURS\n\n#ifndef K7_BASE_HASH\n#define K7_BASE_HASH\n\n/**\n * @brief Enumeration for supported hash algorithm types.\n * @remarks The sequence and values of this enumeration must keep the same for\n *          binary-level backward compatibility.\n */\ntypedef enum _K7_BASE_HASH_ALGORITHM_TYPE\n{\n    /**\n     * @brief The MD2 hash algorithm.\n     */\n    K7_BASE_HASH_ALGORITHM_MD2 = 0,\n\n    /**\n     * @brief The MD4 hash algorithm.\n     */\n    K7_BASE_HASH_ALGORITHM_MD4 = 1,\n\n    /**\n     * @brief The MD5 hash algorithm.\n     */\n    K7_BASE_HASH_ALGORITHM_MD5 = 2,\n\n    /**\n     * @brief The SHA-1 hash algorithm.\n     */\n    K7_BASE_HASH_ALGORITHM_SHA1 = 3,\n\n    /**\n     * @brief The SHA-256 hash algorithm.\n     */\n    K7_BASE_HASH_ALGORITHM_SHA256 = 4,\n\n    /**\n     * @brief The SHA-384 hash algorithm.\n     */\n    K7_BASE_HASH_ALGORITHM_SHA384 = 5,\n\n    /**\n     * @brief The SHA-512 hash algorithm.\n     */\n    K7_BASE_HASH_ALGORITHM_SHA512 = 6,\n\n    /**\n     * @brief Indicates the maximum value for the K7_BASE_HASH_ALGORITHM_TYPE\n     *        enumeration, which is useful for validation purposes.\n     */\n    K7_BASE_HASH_ALGORITHM_MAXIMUM\n} K7_BASE_HASH_ALGORITHM_TYPE, *PK7_BASE_HASH_ALGORITHM_TYPE;\n\nMO_DECLARE_HANDLE(K7_BASE_HASH_HANDLE);\ntypedef K7_BASE_HASH_HANDLE *PK7_BASE_HASH_HANDLE;\n\n/**\n * @brief Creates a hash handle for the specified algorithm.\n * @param HashHandle A pointer to receive the created hash handle.\n * @param Algorithm The hash algorithm type.\n * @param SecretBuffer An optional buffer containing the secret key for HMAC.\n * @param SecretSize The size of the secret key in bytes.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseHashCreate(\n    _Inout_ PK7_BASE_HASH_HANDLE HashHandle,\n    _In_ K7_BASE_HASH_ALGORITHM_TYPE Algorithm,\n    _In_opt_ MO_POINTER SecretBuffer,\n    _In_ MO_UINT32 SecretSize);\n\n/**\n * @brief Destroys the specified hash handle and releases associated resources.\n * @param HashHandle The handle of the hash to be destroyed.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseHashDestroy(\n    _Inout_opt_ K7_BASE_HASH_HANDLE HashHandle);\n\n/**\n * @brief Updates the hash with the specified input data.\n * @param HashHandle The handle of the hash to be updated.\n * @param InputBuffer The input data to be hashed.\n * @param InputSize The size of the input data in bytes.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseHashUpdate(\n    _Inout_ K7_BASE_HASH_HANDLE HashHandle,\n    _In_ MO_POINTER InputBuffer,\n    _In_ MO_UINT32 InputSize);\n\n/**\n * @brief Finalizes the hash computation and retrieves the hash value.\n * @param HashHandle The handle of the hash to be finalized.\n * @param OutputBuffer The buffer to receive the computed hash value.\n * @param OutputSize The size of the output buffer in bytes.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseHashFinal(\n    _Inout_ K7_BASE_HASH_HANDLE HashHandle,\n    _Out_ MO_POINTER OutputBuffer,\n    _In_ MO_UINT32 OutputSize);\n\n/**\n * @brief Retrieves the size of the hash value for the specified hash handle.\n * @param HashHandle The handle of the hash.\n * @param HashSize A pointer to receive the size of the hash value in bytes.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseHashGetSize(\n    _In_ K7_BASE_HASH_HANDLE HashHandle,\n    _Out_ PMO_UINT32 HashSize);\n\n/**\n * @brief Duplicates the specified hash handle.\n * @param SourceHashHandle The handle of the hash to be duplicated.\n * @param DestinationHashHandle A pointer to receive the duplicated hash handle.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseHashDuplicate(\n    _In_ K7_BASE_HASH_HANDLE SourceHashHandle,\n    _Out_ PK7_BASE_HASH_HANDLE DestinationHashHandle);\n\n#endif // !K7_BASE_HASH\n\n#ifndef K7_BASE_POLICIES\n#define K7_BASE_POLICIES\n\n/**\n * @brief Retrieves the policy setting for allowing a specific handler.\n * @param Name The name of the handler to check.\n * @return Returns MO_TRUE if the handler is allowed, or MO_FALSE if not.\n */\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowedHandlerPolicy(\n    _In_ MO_CONSTANT_STRING Name);\n\n/**\n * @brief Retrieves the policy setting for allowing a specific codec.\n * @param Name The name of the codec to check.\n * @return Returns MO_TRUE if the codec is allowed, or MO_FALSE if not.\n */\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowedCodecPolicy(\n    _In_ MO_CONSTANT_STRING Name);\n\n/**\n * @brief Retrieves the policy setting for Zone.Id stream propagation.\n * @return Returns a Zone.Id stream propagation policy value set by the user, or\n *         MO_UINT32_MAX if user has not defined the policy.\n */\nEXTERN_C MO_UINT32 MOAPI K7BaseGetWriteZoneIdExtractPolicy();\n\n#endif // !K7_BASE_POLICIES\n\n#ifndef K7_BASE_MITIGATIONS\n#define K7_BASE_MITIGATIONS\n\n/**\n * @brief Disables dynamic code generation for the current process if the policy\n *        is set to disallow it.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseDisableDynamicCodeGeneration();\n\n/**\n * @brief Disables child process creation for the current process if the policy\n *        is set to disallow it.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseDisableChildProcessCreation();\n\n#endif // !K7_BASE_MITIGATIONS\n\n#ifndef K7_BASE_INITIALIZE\n#define K7_BASE_INITIALIZE\n\n/**\n * @brief Initializes the K7Base library.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n * @remarks The function should be called only once during the initialization\n *          phase as early as possible.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseInitialize();\n\n#endif // !K7_BASE_INITIALIZE\n\n#ifndef K7_BASE_MODERN\n#define K7_BASE_MODERN\n\n/**\n * @brief Converts a file time to a local file time.\n * @param lpFileTime A pointer to a FILETIME structure containing the UTC-based\n *                   file time to be converted into a local file time.\n * @param lpLocalFileTime A pointer to a FILETIME structure to receive the\n *                        converted local file time. This parameter cannot be\n *                        the same as the lpFileTime parameter.\n * @return If the function succeeds, the return value is nonzero. If the\n *         function fails, the return value is zero. To get extended error\n *         information, call GetLastError.\n * @remark For more information, see FileTimeToLocalFileTime.\n */\nEXTERN_C BOOL WINAPI K7BaseModernFileTimeToLocalFileTime(\n    _In_ CONST FILETIME* lpFileTime,\n    _Out_ LPFILETIME lpLocalFileTime);\n\n/**\n * @brief Converts a local file time to a file time based on the Coordinated\n *        Universal Time (UTC).\n * @param lpLocalFileTime A pointer to a FILETIME structure that specifies the\n *                        local file time to be converted into a UTC-based file\n *                        time.\n * @param lpFileTime A pointer to a FILETIME structure to receive the converted\n *                   UTC-based file time. This parameter cannot be the same as\n *                   the lpLocalFileTime parameter.\n * @return If the function succeeds, the return value is nonzero. If the\n *         function fails, the return value is zero. To get extended error\n *         information, use the GetLastError function.\n * @remark For more information, see LocalFileTimeToFileTime.\n */\nEXTERN_C BOOL WINAPI K7BaseModernLocalFileTimeToFileTime(\n    _In_ CONST FILETIME* lpLocalFileTime,\n    _Out_ LPFILETIME lpFileTime);\n\n#endif // !K7_BASE_MODERN\n\n#endif // !K7_BASE\n"
  },
  {
    "path": "K7Base/K7Base.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaZip Platform Base Library (K7Base)\n  FILE:       K7Base.props\n  PURPOSE:    MSBuild Properties for referencing the K7Base dynamic library\n\n  LICENSE:    The MIT License\n\n  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n-->\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <Link>\n      <AdditionalDependencies>$(OutDir)K7Base.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <Target Name=\"K7BaseBuildSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(K7BaseDisableRedirector)' != 'true'\">\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)K7BaseRedirector.cpp\" />\n    </ItemGroup>\n  </Target>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Mobility\">\n      <Version>1.0.372</Version>\n    </PackageReference>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)K7Base.vcxproj\">\n      <Project>{5998305E-D017-47C2-8025-A19111F73539}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "K7Base/K7Base.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{5998305E-D017-47C2-8025-A19111F73539}</ProjectGuid>\n    <RootNamespace>K7Base</RootNamespace>\n    <MileProjectType>DynamicLibrary</MileProjectType>\n    <WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Platform Base Library</MileProjectFileDescription>\n    <MileProjectInternalName>K7Base</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>K7Base.dll</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n    <K7BaseDisableRedirector>true</K7BaseDisableRedirector>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.ARM64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Project=\"$(MSBuildThisFileDirectory)K7BaseStatic.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <ModuleDefinitionFile>K7Base.def</ModuleDefinitionFile>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <None Include=\"K7Base.def\" />\n    <None Include=\"K7Base.props\" />\n    <None Include=\"K7BaseRedirector.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "K7Base/K7BaseDetours.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BaseDetours.cpp\n * PURPOSE:    Implementation for NanaZip Platform Detours Library Wrappers\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7BasePrivate.h\"\n\n#include <Detours.h>\n\nEXTERN_C LONG MOAPI K7BaseDetourTransactionBegin()\n{\n    return ::DetourTransactionBegin();\n}\n\nEXTERN_C LONG MOAPI K7BaseDetourTransactionAbort()\n{\n    return ::DetourTransactionAbort();\n}\n\nEXTERN_C LONG MOAPI K7BaseDetourTransactionCommit()\n{\n    return ::DetourTransactionCommit();\n}\n\nEXTERN_C LONG MOAPI K7BaseDetourUpdateThread(\n    _In_ HANDLE ThreadHandle)\n{\n    return ::DetourUpdateThread(ThreadHandle);\n}\n\nEXTERN_C LONG MOAPI K7BaseDetourAttach(\n    _Inout_ PMO_POINTER OriginalFunction,\n    _In_ MO_POINTER DetouredFunction)\n{\n    return ::DetourAttach(OriginalFunction, DetouredFunction);\n}\n\nEXTERN_C LONG MOAPI K7BaseDetourDetach(\n    _Inout_ PMO_POINTER OriginalFunction,\n    _In_ MO_POINTER DetouredFunction)\n{\n    return ::DetourDetach(OriginalFunction, DetouredFunction);\n}\n"
  },
  {
    "path": "K7Base/K7BaseHash.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BaseHash.cpp\n * PURPOSE:    Implementation for NanaZip Platform Hash Algorithms Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7BasePrivate.h\"\n\n#include <Mile.Helpers.Base.h>\n\n#include <bcrypt.h>\n#pragma comment(lib, \"bcrypt.lib\")\n\n#include <cstring>\n#include <cwchar>\n\nnamespace\n{\n    typedef struct _K7_BASE_HASH_ALGORITHM\n    {\n        MO_CONSTANT_WIDE_STRING Identifier;\n        BCRYPT_ALG_HANDLE Handle;\n        BCRYPT_ALG_HANDLE HmacHandle;\n    } K7_BASE_HASH_ALGORITHM, *PK7_BASE_HASH_ALGORITHM;\n\n    K7_BASE_HASH_ALGORITHM g_HashAlgorithms[K7_BASE_HASH_ALGORITHM_MAXIMUM] =\n    {\n        { BCRYPT_MD2_ALGORITHM, nullptr, nullptr },\n        { BCRYPT_MD4_ALGORITHM, nullptr, nullptr },\n        { BCRYPT_MD5_ALGORITHM, nullptr, nullptr },\n        { BCRYPT_SHA1_ALGORITHM, nullptr, nullptr },\n        { BCRYPT_SHA256_ALGORITHM, nullptr, nullptr },\n        { BCRYPT_SHA384_ALGORITHM, nullptr, nullptr },\n        { BCRYPT_SHA512_ALGORITHM, nullptr, nullptr },\n    };\n\n    typedef struct _K7_BASE_HASH_CONTEXT\n    {\n        MO_UINT32 ContextSize;\n        MO_UINT32 HashSize;\n        MO_UINT32 HashObjectSize;\n        MO_POINTER HashObject;\n        BCRYPT_HASH_HANDLE HashHandle;\n    } K7_BASE_HASH_CONTEXT, *PK7_BASE_HASH_CONTEXT;\n\n    static PK7_BASE_HASH_CONTEXT K7BaseHashInternalGetContextFromHandle(\n        _In_opt_ K7_BASE_HASH_HANDLE HashHandle)\n    {\n        if (HashHandle)\n        {\n            __try\n            {\n                PK7_BASE_HASH_CONTEXT Context =\n                    reinterpret_cast<PK7_BASE_HASH_CONTEXT>(HashHandle);\n                if (sizeof(K7_BASE_HASH_CONTEXT) == Context->ContextSize)\n                {\n                    return Context;\n                }\n            }\n            __except (EXCEPTION_EXECUTE_HANDLER)\n            {\n                // Fall through.\n            }\n        }\n\n        return nullptr;\n    }\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseHashCreate(\n    _Inout_ PK7_BASE_HASH_HANDLE HashHandle,\n    _In_ K7_BASE_HASH_ALGORITHM_TYPE Algorithm,\n    _In_opt_ MO_POINTER SecretBuffer,\n    _In_ MO_UINT32 SecretSize)\n{\n    if (Algorithm < 0 ||\n        Algorithm >= K7_BASE_HASH_ALGORITHM_MAXIMUM)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n\n    if (!HashHandle)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n    *HashHandle = nullptr;\n\n    bool Result = false;\n\n    do\n    {\n        PK7_BASE_HASH_CONTEXT Context = reinterpret_cast<PK7_BASE_HASH_CONTEXT>(\n            ::MileAllocateMemory(sizeof(K7_BASE_HASH_CONTEXT)));\n        if (!Context)\n        {\n            break;\n        }\n        *HashHandle = reinterpret_cast<K7_BASE_HASH_HANDLE>(Context);\n        Context->ContextSize = sizeof(K7_BASE_HASH_CONTEXT);\n\n        BCRYPT_ALG_HANDLE AlgorithmHandle = nullptr;\n        if (SecretBuffer)\n        {\n            if (!g_HashAlgorithms[Algorithm].HmacHandle)\n            {\n                if (!BCRYPT_SUCCESS(::BCryptOpenAlgorithmProvider(\n                    &g_HashAlgorithms[Algorithm].HmacHandle,\n                    g_HashAlgorithms[Algorithm].Identifier,\n                    nullptr,\n                    BCRYPT_ALG_HANDLE_HMAC_FLAG)))\n                {\n                    break;\n                }\n            }\n            AlgorithmHandle = g_HashAlgorithms[Algorithm].HmacHandle;\n        }\n        else\n        {\n            if (!g_HashAlgorithms[Algorithm].Handle)\n            {\n                if (!BCRYPT_SUCCESS(::BCryptOpenAlgorithmProvider(\n                    &g_HashAlgorithms[Algorithm].Handle,\n                    g_HashAlgorithms[Algorithm].Identifier,\n                    nullptr,\n                    0)))\n                {\n                    break;\n                }\n            }\n            AlgorithmHandle = g_HashAlgorithms[Algorithm].Handle;\n        }\n\n        {\n            DWORD ReturnLength = 0;\n            if (!BCRYPT_SUCCESS(::BCryptGetProperty(\n                AlgorithmHandle,\n                BCRYPT_HASH_LENGTH,\n                reinterpret_cast<PUCHAR>(&Context->HashSize),\n                sizeof(Context->HashSize),\n                &ReturnLength,\n                0)))\n            {\n                break;\n            }\n        }\n\n        {\n            DWORD ReturnLength = 0;\n            if (!BCRYPT_SUCCESS(::BCryptGetProperty(\n                AlgorithmHandle,\n                BCRYPT_OBJECT_LENGTH,\n                reinterpret_cast<PUCHAR>(&Context->HashObjectSize),\n                sizeof(Context->HashObjectSize),\n                &ReturnLength,\n                0)))\n            {\n                break;\n            }\n        }\n\n        Context->HashObject = ::MileAllocateMemory(Context->HashObjectSize);\n        if (!Context->HashObject)\n        {\n            break;\n        }\n\n        Result = BCRYPT_SUCCESS(::BCryptCreateHash(\n            AlgorithmHandle,\n            &Context->HashHandle,\n            reinterpret_cast<PUCHAR>(Context->HashObject),\n            Context->HashObjectSize,\n            SecretBuffer ? reinterpret_cast<PUCHAR>(SecretBuffer) : nullptr,\n            SecretBuffer ? SecretSize : 0,\n            0));\n\n    } while (false);\n\n    if (!Result)\n    {\n        ::K7BaseHashDestroy(*HashHandle);\n        *HashHandle = nullptr;\n    }\n\n    return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseHashDestroy(\n    _Inout_opt_ K7_BASE_HASH_HANDLE HashHandle)\n{\n    PK7_BASE_HASH_CONTEXT Context =\n        ::K7BaseHashInternalGetContextFromHandle(HashHandle);\n    if (!Context)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n\n    Context->ContextSize = 0;\n\n    Context->HashSize = 0;\n\n    Context->HashObjectSize = 0;\n\n    if (Context->HashHandle)\n    {\n        ::BCryptDestroyHash(Context->HashHandle);\n        Context->HashHandle = nullptr;\n    }\n\n    if (Context->HashObject)\n    {\n        ::MileFreeMemory(Context->HashObject);\n        Context->HashObject = nullptr;\n    }\n\n    ::MileFreeMemory(Context);\n\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseHashUpdate(\n    _Inout_ K7_BASE_HASH_HANDLE HashHandle,\n    _In_ MO_POINTER InputBuffer,\n    _In_ MO_UINT32 InputSize)\n{\n    PK7_BASE_HASH_CONTEXT Context =\n        ::K7BaseHashInternalGetContextFromHandle(HashHandle);\n    if (!Context)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n\n    bool Result = BCRYPT_SUCCESS(::BCryptHashData(\n        Context->HashHandle,\n        reinterpret_cast<PUCHAR>(InputBuffer),\n        InputSize,\n        0));\n\n    return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseHashFinal(\n    _Inout_ K7_BASE_HASH_HANDLE HashHandle,\n    _Out_ MO_POINTER OutputBuffer,\n    _In_ MO_UINT32 OutputSize)\n{\n    PK7_BASE_HASH_CONTEXT Context =\n        ::K7BaseHashInternalGetContextFromHandle(HashHandle);\n    if (!Context)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n\n    bool Result = false;\n\n    PVOID FinishHashObject = ::MileAllocateMemory(\n        Context->HashObjectSize);\n    if (FinishHashObject)\n    {\n        BCRYPT_HASH_HANDLE FinishHashHandle = nullptr;\n        if (BCRYPT_SUCCESS(::BCryptDuplicateHash(\n            Context->HashHandle,\n            &FinishHashHandle,\n            reinterpret_cast<PUCHAR>(FinishHashObject),\n            Context->HashObjectSize,\n            0)))\n        {\n            Result = BCRYPT_SUCCESS(::BCryptFinishHash(\n                FinishHashHandle,\n                reinterpret_cast<PUCHAR>(OutputBuffer),\n                OutputSize,\n                0));\n\n            ::BCryptDestroyHash(FinishHashHandle);\n        }\n\n        ::MileFreeMemory(FinishHashObject);\n    }\n\n    if (!Result)\n    {\n        if (OutputBuffer)\n        {\n            std::memset(OutputBuffer, 0, OutputSize);\n        }\n    }\n\n    return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseHashGetSize(\n    _In_ K7_BASE_HASH_HANDLE HashHandle,\n    _Out_ PMO_UINT32 HashSize)\n{\n    if (!HashSize)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n\n    PK7_BASE_HASH_CONTEXT Context =\n        ::K7BaseHashInternalGetContextFromHandle(HashHandle);\n    if (!Context)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n\n    *HashSize = Context->HashSize;\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseHashDuplicate(\n    _In_ K7_BASE_HASH_HANDLE SourceHashHandle,\n    _Out_ PK7_BASE_HASH_HANDLE DestinationHashHandle)\n{\n    if (!DestinationHashHandle)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n    *DestinationHashHandle = nullptr;\n\n    PK7_BASE_HASH_CONTEXT SourceContext =\n        ::K7BaseHashInternalGetContextFromHandle(SourceHashHandle);\n    if (!SourceContext)\n    {\n        return MO_RESULT_ERROR_INVALID_PARAMETER;\n    }\n\n    bool Result = false;\n\n    do\n    {\n        PK7_BASE_HASH_CONTEXT Context = reinterpret_cast<PK7_BASE_HASH_CONTEXT>(\n            ::MileAllocateMemory(sizeof(K7_BASE_HASH_CONTEXT)));\n        if (!Context)\n        {\n            break;\n        }\n        *DestinationHashHandle = reinterpret_cast<K7_BASE_HASH_HANDLE>(Context);\n        Context->ContextSize = sizeof(K7_BASE_HASH_CONTEXT);\n\n        Context->HashSize = SourceContext->HashSize;\n\n        Context->HashObjectSize = SourceContext->HashObjectSize;\n\n        Context->HashObject = ::MileAllocateMemory(Context->HashObjectSize);\n        if (!Context->HashObject)\n        {\n            break;\n        }\n\n        Result = BCRYPT_SUCCESS(::BCryptDuplicateHash(\n            SourceContext->HashHandle,\n            &Context->HashHandle,\n            reinterpret_cast<PUCHAR>(Context->HashObject),\n            Context->HashObjectSize,\n            0));\n\n    } while (false);\n\n    if (!Result)\n    {\n        ::K7BaseHashDestroy(*DestinationHashHandle);\n        *DestinationHashHandle = nullptr;\n    }\n\n    return Result ? MO_RESULT_SUCCESS_OK : MO_RESULT_ERROR_FAIL;\n}\n"
  },
  {
    "path": "K7Base/K7BaseInitialize.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BaseInitialize.cpp\n * PURPOSE:    Implementation for NanaZip Platform Base Initialize Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7BasePrivate.h\"\n\nEXTERN_C MO_RESULT MOAPI K7BaseInitialize()\n{\n    static MO_BOOL g_Initialized = MO_FALSE;\n    if (g_Initialized)\n    {\n        return MO_RESULT_SUCCESS_OK;\n    }\n\n    MO_RESULT Result = MO_RESULT_SUCCESS_OK;\n\n    Result = ::K7BaseInitializePolicies();\n    if (MO_RESULT_SUCCESS_OK != Result)\n    {\n        return Result;\n    }\n\n    Result = ::K7BaseEnableMandatoryMitigations();\n    if (MO_RESULT_SUCCESS_OK != Result)\n    {\n        return Result;\n    }\n\n    Result = ::K7BaseInitializeDynamicLinkLibraryBlocker();\n    if (MO_RESULT_SUCCESS_OK != Result)\n    {\n        return Result;\n    }\n\n    g_Initialized = MO_TRUE;\n\n    // Do nothing if already initialized.\n    return MO_RESULT_SUCCESS_OK;\n}\n"
  },
  {
    "path": "K7Base/K7BaseMitigations.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BaseMitigations.cpp\n * PURPOSE:    Implementation for NanaZip Platform Base Mitigations Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: dinhngtu (contact@tudinh.xyz)\n *             MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include <Mile.Internal.h>\n\n#include \"K7BasePrivate.h\"\n\n#include <intrin.h>\n\n#include <mutex>\n#include <vector>\n\nnamespace\n{\n    static BOOL GetCurrentProcessMitigationPolicy(\n        _In_ PROCESS_MITIGATION_POLICY MitigationPolicy,\n        _Out_ PVOID lpBuffer,\n        _In_ SIZE_T dwLength)\n    {\n        return ::GetProcessMitigationPolicy(\n            ::GetCurrentProcess(),\n            MitigationPolicy,\n            lpBuffer,\n            dwLength);\n    }\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseEnableMandatoryMitigations()\n{\n    {\n        PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY Policy = {};\n\n        // Get the current policy state to avoid failing to set the mitigation\n        // policy when the callers already have set the policy to a more strict\n        // state.\n        if (!::GetCurrentProcessMitigationPolicy(\n            ProcessStrictHandleCheckPolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY)))\n        {\n            // We should not trust the policy state if the get call fails, but\n            // we can still try to set the policy.\n            Policy = {};\n        }\n\n        Policy.RaiseExceptionOnInvalidHandleReference = 1;\n        Policy.HandleExceptionsPermanentlyEnabled = 1;\n\n        if (!::SetProcessMitigationPolicy(\n            ProcessStrictHandleCheckPolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_STRICT_HANDLE_CHECK_POLICY)))\n        {\n            return MO_RESULT_ERROR_FAIL;\n        }\n    }\n\n    {\n        PROCESS_MITIGATION_IMAGE_LOAD_POLICY Policy = {};\n\n        // Get the current policy state to avoid failing to set the mitigation\n        // policy when the callers already have set the policy to a more strict\n        // state.\n        if (!::GetCurrentProcessMitigationPolicy(\n            ProcessImageLoadPolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_IMAGE_LOAD_POLICY)))\n        {\n            // We should not trust the policy state if the get call fails, but\n            // we can still try to set the policy.\n            Policy = {};\n        }\n\n        Policy.NoRemoteImages = 1;\n        Policy.NoLowMandatoryLabelImages = 1;\n\n        if (!::SetProcessMitigationPolicy(\n            ProcessImageLoadPolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_IMAGE_LOAD_POLICY)))\n        {\n            return MO_RESULT_ERROR_FAIL;\n        }\n    }\n\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseDisableDynamicCodeGeneration()\n{\n#ifndef _DEBUG\n    if (!::K7BaseGetAllowDynamicCodeGenerationPolicy())\n    {\n        PROCESS_MITIGATION_DYNAMIC_CODE_POLICY Policy = {};\n\n        // Get the current policy state to avoid failing to set the mitigation\n        // policy when the callers already have set the policy to a more strict\n        // state.\n        if (!::GetCurrentProcessMitigationPolicy(\n            ProcessDynamicCodePolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_DYNAMIC_CODE_POLICY)))\n        {\n            // We should not trust the policy state if the get call fails, but\n            // we can still try to set the policy.\n            Policy = {};\n        }\n\n        Policy.ProhibitDynamicCode = 1;\n        Policy.AllowThreadOptOut = 1;\n\n        if (!::SetProcessMitigationPolicy(\n            ProcessDynamicCodePolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_DYNAMIC_CODE_POLICY)))\n        {\n            return MO_RESULT_ERROR_FAIL;\n        }\n    }\n#endif // _DEBUG\n\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseDisableChildProcessCreation()\n{\n    if (!::K7BaseGetAllowChildProcessCreationPolicy())\n    {\n        PROCESS_MITIGATION_CHILD_PROCESS_POLICY Policy = {};\n\n        // Get the current policy state to avoid failing to set the mitigation\n        // policy when the callers already have set the policy to a more strict\n        // state.\n        if (!::GetCurrentProcessMitigationPolicy(\n            ProcessChildProcessPolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_CHILD_PROCESS_POLICY)))\n        {\n            // We should not trust the policy state if the get call fails, but\n            // we can still try to set the policy.\n            Policy = {};\n        }\n\n        Policy.NoChildProcessCreation = 1;\n\n        if (!::SetProcessMitigationPolicy(\n            ProcessChildProcessPolicy,\n            &Policy,\n            sizeof(PROCESS_MITIGATION_CHILD_PROCESS_POLICY)))\n        {\n            return MO_RESULT_ERROR_FAIL;\n        }\n    }\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseSetCurrentThreadDynamicCodePolicyOptOut(\n    _In_ MO_BOOL AllowDynamicCodeGeneration)\n{\n#ifndef _DEBUG\n    if (::K7BaseGetAllowDynamicCodeGenerationPolicy())\n    {\n        return TRUE;\n    }\n    DWORD PolicyValue = AllowDynamicCodeGeneration\n        ? THREAD_DYNAMIC_CODE_ALLOW\n        : 0;\n    if (!::SetThreadInformation(\n        ::GetCurrentThread(),\n        ThreadDynamicCodePolicy,\n        &PolicyValue,\n        sizeof(DWORD)))\n    {\n        return MO_RESULT_ERROR_FAIL;\n    }\n#else\n    UNREFERENCED_PARAMETER(AllowDynamicCodeGeneration);\n#endif\n    return MO_RESULT_SUCCESS_OK;\n}\n\n#ifndef _DEBUG\nnamespace\n{\n    namespace ModuleTypes\n    {\n        enum\n        {\n            Unknown,\n            NeedsBlocking,\n            NeedsDynamicCodeOptout,\n        };\n    }\n\n    struct ModuleItem\n    {\n        MO_UINT8 ModuleType;\n        MO_CONSTANT_STRING ModuleName;\n    };\n\n    /**\n     * @remarks Make sure that this list is sorted for _stricmp.\n     */\n    const ModuleItem g_ModuleRules[] =\n    {\n        { ModuleTypes::NeedsDynamicCodeOptout, \"BaseGUI.dll\" },\n        { ModuleTypes::NeedsBlocking, \"ExplorerPatcher.amd64.dll\" },\n        { ModuleTypes::NeedsBlocking, \"ExplorerPatcher.IA-32.dll\" },\n        { ModuleTypes::NeedsBlocking, \"PrxDrvPE.dll\" },\n        { ModuleTypes::NeedsBlocking, \"PrxDrvPE64.dll\" },\n        { ModuleTypes::NeedsBlocking, \"TFMain32.dll\" },\n        { ModuleTypes::NeedsBlocking, \"TFMain64.dll\" },\n    };\n\n    static MO_UINT8 QueryModuleType(\n        _In_ MO_CONSTANT_STRING ModuleName)\n    {\n        for (MO_UINT32 i = 0; i < MO_ARRAY_SIZE(g_ModuleRules); ++i)\n        {\n            if (!::_stricmp(ModuleName, g_ModuleRules[i].ModuleName))\n            {\n                return g_ModuleRules[i].ModuleType;\n            }\n        }\n        return ModuleTypes::Unknown;\n    }\n\n    static std::mutex g_DynamicCodeRangesMutex;\n    static std::vector<std::pair<MO_UINTN, MO_UINTN>> g_DynamicCodeRanges;\n\n    static bool IsDynamicCodeAllowed(\n        _In_ MO_POINTER CallerPointer)\n    {\n        MO_UINTN CallerAddress = reinterpret_cast<MO_UINTN>(CallerPointer);\n        std::lock_guard<std::mutex> Lock(g_DynamicCodeRangesMutex);\n        for (auto const& Range : g_DynamicCodeRanges)\n        {\n            if (CallerAddress >= Range.first &&\n                CallerAddress < Range.first + Range.second)\n            {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    static bool IsCurrentProcessHandle(\n        _In_ HANDLE ProcessHandle)\n    {\n        if (ProcessHandle == ::GetCurrentProcess() ||\n            ::GetCurrentProcessId() == ::GetProcessId(ProcessHandle))\n        {\n            return true;\n        }\n        return false;\n    }\n\n    static bool IsPageExecute(\n        _In_ DWORD Protect)\n    {\n        if (PAGE_EXECUTE == Protect ||\n            PAGE_EXECUTE_READ == Protect ||\n            PAGE_EXECUTE_READWRITE == Protect ||\n            PAGE_EXECUTE_WRITECOPY == Protect)\n        {\n            return true;\n        }\n        return false;\n    }\n\n    static inline bool CheckExtents(\n        _In_ MO_UINTN ViewSize,\n        _In_ MO_UINTN Offset,\n        _In_ MO_UINTN Size)\n    {\n        return (\n            Offset < ViewSize &&\n            Size <= ViewSize &&\n            Offset + Size <= ViewSize);\n    }\n\n    static bool GetModuleExportName(\n        _In_ MO_CHAR(&ModuleName)[256],\n        _In_ MO_STRING Base,\n        _In_ MO_UINTN ViewSize)\n    {\n        if (sizeof(IMAGE_DOS_HEADER) > ViewSize)\n        {\n            return false;\n        }\n\n        PIMAGE_DOS_HEADER DosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(Base);\n        if (IMAGE_DOS_SIGNATURE != DosHeader->e_magic)\n        {\n            return false;\n        }\n        if (0 > DosHeader->e_lfanew ||\n            !::CheckExtents(\n                ViewSize,\n                DosHeader->e_lfanew,\n                sizeof(IMAGE_NT_HEADERS)))\n        {\n            return false;\n        }\n\n        PIMAGE_NT_HEADERS NtHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(\n            Base + DosHeader->e_lfanew);\n        if (IMAGE_NT_SIGNATURE != NtHeader->Signature ||\n            IMAGE_DIRECTORY_ENTRY_EXPORT >\n            NtHeader->OptionalHeader.NumberOfRvaAndSizes)\n        {\n            return false;\n        }\n\n        PIMAGE_DATA_DIRECTORY ExportDirectory =\n            &(NtHeader->OptionalHeader.DataDirectory[\n                IMAGE_DIRECTORY_ENTRY_EXPORT]);\n        if (sizeof(IMAGE_EXPORT_DIRECTORY) > ExportDirectory->Size ||\n            !ExportDirectory->VirtualAddress ||\n            !::CheckExtents(\n                ViewSize,\n                ExportDirectory->VirtualAddress,\n                sizeof(IMAGE_EXPORT_DIRECTORY)))\n        {\n            return false;\n        }\n\n        PIMAGE_EXPORT_DIRECTORY Exports =\n            reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(\n                Base + ExportDirectory->VirtualAddress);\n        // We don't know the export directory name size so assume that at least\n        // 256 bytes after the name are safe.\n        if (!Exports->Name ||\n            !::CheckExtents(\n                ViewSize,\n                Exports->Name,\n                MO_ARRAY_SIZE(ModuleName)))\n        {\n            return false;\n        }\n\n        const char* Name = Base + Exports->Name;\n        if (::strncpy_s(ModuleName, Name, _TRUNCATE))\n        {\n            return false;\n        }\n\n        return true;\n    }\n\n    namespace FunctionTypes\n    {\n        enum\n        {\n            NtMapViewOfSection,\n            NtQuerySection,\n            NtUnmapViewOfSection,\n            VirtualAlloc,\n            VirtualAllocEx,\n            VirtualProtect,\n            VirtualProtectEx,\n\n            MaximumFunction\n        };\n    }\n\n    struct FunctionItem\n    {\n        PVOID Original;\n        PVOID Detoured;\n    };\n\n    static FunctionItem g_FunctionTable[FunctionTypes::MaximumFunction];\n\n    static NTSTATUS NTAPI OriginalNtMapViewOfSection(\n        _In_ HANDLE SectionHandle,\n        _In_ HANDLE ProcessHandle,\n        _Inout_ PVOID* BaseAddress,\n        _In_ ULONG_PTR ZeroBits,\n        _In_ SIZE_T CommitSize,\n        _Inout_opt_ PLARGE_INTEGER SectionOffset,\n        _Inout_ PSIZE_T ViewSize,\n        _In_ SECTION_INHERIT InheritDisposition,\n        _In_ ULONG AllocationType,\n        _In_ ULONG PageProtection)\n    {\n        using FunctionType = decltype(::NtMapViewOfSection)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::NtMapViewOfSection].Original);\n        if (!FunctionAddress)\n        {\n            return STATUS_NOINTERFACE;\n        }\n        return FunctionAddress(\n            SectionHandle,\n            ProcessHandle,\n            BaseAddress,\n            ZeroBits,\n            CommitSize,\n            SectionOffset,\n            ViewSize,\n            InheritDisposition,\n            AllocationType,\n            PageProtection);\n    }\n\n    static NTSTATUS NTAPI OriginalNtQuerySection(\n        _In_ HANDLE SectionHandle,\n        _In_ SECTION_INFORMATION_CLASS SectionInformationClass,\n        _Out_ PVOID SectionInformation,\n        _In_ SIZE_T SectionInformationLength,\n        _Out_opt_ PSIZE_T ReturnLength)\n    {\n        using FunctionType = decltype(::NtQuerySection)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::NtQuerySection].Original);\n        if (!FunctionAddress)\n        {\n            return STATUS_NOINTERFACE;\n        }\n        return FunctionAddress(\n            SectionHandle,\n            SectionInformationClass,\n            SectionInformation,\n            SectionInformationLength,\n            ReturnLength);\n    }\n\n    static NTSTATUS NTAPI OriginalNtUnmapViewOfSection(\n        _In_ HANDLE ProcessHandle,\n        _In_opt_ PVOID BaseAddress)\n    {\n        using FunctionType = decltype(::NtUnmapViewOfSection)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::NtUnmapViewOfSection].Original);\n        if (!FunctionAddress)\n        {\n            return STATUS_NOINTERFACE;\n        }\n        return FunctionAddress(\n            ProcessHandle,\n            BaseAddress);\n    }\n\n    static LPVOID WINAPI OriginalVirtualAlloc(\n        _In_opt_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flAllocationType,\n        _In_ DWORD flProtect)\n    {\n        using FunctionType = decltype(::VirtualAlloc)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::VirtualAlloc].Original);\n        if (!FunctionAddress)\n        {\n            ::SetLastError(ERROR_NOINTERFACE);\n            return nullptr;\n        }\n        return FunctionAddress(\n            lpAddress,\n            dwSize,\n            flAllocationType,\n            flProtect);\n    }\n\n    static LPVOID WINAPI OriginalVirtualAllocEx(\n        _In_ HANDLE hProcess,\n        _In_opt_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flAllocationType,\n        _In_ DWORD flProtect)\n    {\n        using FunctionType = decltype(::VirtualAllocEx)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::VirtualAllocEx].Original);\n        if (!FunctionAddress)\n        {\n            ::SetLastError(ERROR_NOINTERFACE);\n            return nullptr;\n        }\n        return FunctionAddress(\n            hProcess,\n            lpAddress,\n            dwSize,\n            flAllocationType,\n            flProtect);\n    }\n\n    static BOOL WINAPI OriginalVirtualProtect(\n        _In_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flNewProtect,\n        _Out_ PDWORD lpflOldProtect)\n    {\n        using FunctionType = decltype(::VirtualProtect)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::VirtualProtect].Original);\n        if (!FunctionAddress)\n        {\n            ::SetLastError(ERROR_NOINTERFACE);\n            return FALSE;\n        }\n        return FunctionAddress(\n            lpAddress,\n            dwSize,\n            flNewProtect,\n            lpflOldProtect);\n    }\n\n    static BOOL WINAPI OriginalVirtualProtectEx(\n        _In_ HANDLE hProcess,\n        _In_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flNewProtect,\n        _Out_ PDWORD lpflOldProtect)\n    {\n        using FunctionType = decltype(::VirtualProtectEx)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::VirtualProtectEx].Original);\n        if (!FunctionAddress)\n        {\n            ::SetLastError(ERROR_NOINTERFACE);\n            return FALSE;\n        }\n        return FunctionAddress(\n            hProcess,\n            lpAddress,\n            dwSize,\n            flNewProtect,\n            lpflOldProtect);\n    }\n\n    static NTSTATUS NTAPI DetouredNtMapViewOfSection(\n        _In_ HANDLE SectionHandle,\n        _In_ HANDLE ProcessHandle,\n        _Inout_ PVOID* BaseAddress,\n        _In_ ULONG_PTR ZeroBits,\n        _In_ SIZE_T CommitSize,\n        _Inout_opt_ PLARGE_INTEGER SectionOffset,\n        _Inout_ PSIZE_T ViewSize,\n        _In_ SECTION_INHERIT InheritDisposition,\n        _In_ ULONG AllocationType,\n        _In_ ULONG PageProtection)\n    {\n        NTSTATUS Status = ::OriginalNtMapViewOfSection(\n            SectionHandle,\n            ProcessHandle,\n            BaseAddress,\n            ZeroBits,\n            CommitSize,\n            SectionOffset,\n            ViewSize,\n            InheritDisposition,\n            AllocationType,\n            PageProtection);\n        if (!NT_SUCCESS(Status) ||\n            !::IsCurrentProcessHandle(ProcessHandle) ||\n            !::IsPageExecute(PageProtection))\n        {\n            return Status;\n        }\n        {\n            SECTION_BASIC_INFORMATION Information = {};\n            if (!NT_SUCCESS(::OriginalNtQuerySection(\n                SectionHandle,\n                SectionBasicInformation,\n                &Information,\n                sizeof(SECTION_BASIC_INFORMATION),\n                nullptr)) ||\n                !(SEC_IMAGE & Information.AllocationAttributes))\n            {\n                return Status;\n            }\n        }\n        MO_CHAR ModuleName[256] = {};\n        if (!::GetModuleExportName(\n            ModuleName,\n            reinterpret_cast<MO_STRING>(*BaseAddress),\n            *ViewSize))\n        {\n            return Status;\n        }\n        MO_UINT8 ModuleType = ::QueryModuleType(ModuleName);\n        if (ModuleTypes::NeedsBlocking & ModuleType)\n        {\n            ::OriginalNtUnmapViewOfSection(ProcessHandle, *BaseAddress);\n            return STATUS_ACCESS_DENIED;\n        }\n        else if (ModuleTypes::NeedsDynamicCodeOptout & ModuleType)\n        {\n            std::lock_guard<std::mutex> Lock(g_DynamicCodeRangesMutex);\n            g_DynamicCodeRanges.emplace_back(\n                reinterpret_cast<MO_UINTN>(*BaseAddress),\n                *ViewSize);\n        }\n        return Status;\n    }\n\n    static NTSTATUS NTAPI DetouredNtUnmapViewOfSection(\n        _In_ HANDLE ProcessHandle,\n        _In_opt_ PVOID BaseAddress)\n    {\n        NTSTATUS Status = ::OriginalNtUnmapViewOfSection(\n            ProcessHandle,\n            BaseAddress);\n        if (NT_SUCCESS(Status) &&\n            ::IsCurrentProcessHandle(ProcessHandle))\n        {\n            MO_UINTN BaseStart = reinterpret_cast<MO_UINTN>(BaseAddress);\n            std::lock_guard<std::mutex> Lock(g_DynamicCodeRangesMutex);\n            for (auto Iterator = g_DynamicCodeRanges.begin();\n                Iterator != g_DynamicCodeRanges.end();\n                ++Iterator)\n            {\n                if (BaseStart >= Iterator->first &&\n                    BaseStart < Iterator->first + Iterator->second)\n                {\n                    g_DynamicCodeRanges.erase(Iterator);\n                    break;\n                }\n            }\n        }\n        return Status;\n    }\n\n    static LPVOID WINAPI DetouredVirtualAlloc(\n        _In_opt_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flAllocationType,\n        _In_ DWORD flProtect)\n    {\n        if (!::IsPageExecute(flProtect) ||\n            !::IsDynamicCodeAllowed(::_ReturnAddress()))\n        {\n            return ::OriginalVirtualAlloc(\n                lpAddress,\n                dwSize,\n                flAllocationType,\n                flProtect);\n        }\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);\n        LPVOID Result = ::OriginalVirtualAlloc(\n            lpAddress,\n            dwSize,\n            flAllocationType,\n            flProtect);\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);\n        return Result;\n    }\n\n    static LPVOID WINAPI DetouredVirtualAllocEx(\n        _In_ HANDLE hProcess,\n        _In_opt_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flAllocationType,\n        _In_ DWORD flProtect)\n    {\n        if (!::IsCurrentProcessHandle(hProcess) ||\n            !::IsPageExecute(flProtect) ||\n            !::IsDynamicCodeAllowed(::_ReturnAddress()))\n        {\n            return ::OriginalVirtualAllocEx(\n                hProcess,\n                lpAddress,\n                dwSize,\n                flAllocationType,\n                flProtect);\n        }\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);\n        LPVOID Result = ::OriginalVirtualAllocEx(\n            hProcess,\n            lpAddress,\n            dwSize,\n            flAllocationType,\n            flProtect);\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);\n        return Result;\n    }\n\n    static BOOL WINAPI DetouredVirtualProtect(\n        _In_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flNewProtect,\n        _Out_ PDWORD lpflOldProtect)\n    {\n        if (!::IsPageExecute(flNewProtect) ||\n            !::IsDynamicCodeAllowed(::_ReturnAddress()))\n        {\n            return ::OriginalVirtualProtect(\n                lpAddress,\n                dwSize,\n                flNewProtect,\n                lpflOldProtect);\n        }\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);\n        BOOL Result = ::OriginalVirtualProtect(\n            lpAddress,\n            dwSize,\n            flNewProtect,\n            lpflOldProtect);\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);\n        return Result;\n    }\n\n    static BOOL WINAPI DetouredVirtualProtectEx(\n        _In_ HANDLE hProcess,\n        _In_ LPVOID lpAddress,\n        _In_ SIZE_T dwSize,\n        _In_ DWORD flNewProtect,\n        _Out_ PDWORD lpflOldProtect)\n    {\n        if (!::IsCurrentProcessHandle(hProcess) ||\n            !::IsPageExecute(flNewProtect) ||\n            !::IsDynamicCodeAllowed(::_ReturnAddress()))\n        {\n            return ::OriginalVirtualProtectEx(\n                hProcess,\n                lpAddress,\n                dwSize,\n                flNewProtect,\n                lpflOldProtect);\n        }\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_TRUE);\n        BOOL Result = ::OriginalVirtualProtectEx(\n            hProcess,\n            lpAddress,\n            dwSize,\n            flNewProtect,\n            lpflOldProtect);\n        ::K7BaseSetCurrentThreadDynamicCodePolicyOptOut(MO_FALSE);\n        return Result;\n    }\n\n    static bool InitializeFunctionTable()\n    {\n        HMODULE NtDllModuleHandle = ::GetModuleHandleW(L\"ntdll.dll\");\n        if (!NtDllModuleHandle)\n        {\n            return false;\n        }\n\n        g_FunctionTable[FunctionTypes::NtMapViewOfSection].Original =\n            ::GetProcAddress(NtDllModuleHandle, \"NtMapViewOfSection\");\n        g_FunctionTable[FunctionTypes::NtMapViewOfSection].Detoured =\n            ::DetouredNtMapViewOfSection;\n\n        g_FunctionTable[FunctionTypes::NtQuerySection].Original =\n            ::GetProcAddress(NtDllModuleHandle, \"NtQuerySection\");\n        g_FunctionTable[FunctionTypes::NtQuerySection].Detoured =\n            nullptr;\n\n        g_FunctionTable[FunctionTypes::NtUnmapViewOfSection].Original =\n            ::GetProcAddress(NtDllModuleHandle, \"NtUnmapViewOfSection\");\n        g_FunctionTable[FunctionTypes::NtUnmapViewOfSection].Detoured =\n            ::DetouredNtUnmapViewOfSection;\n\n        g_FunctionTable[FunctionTypes::VirtualAlloc].Original =\n            ::VirtualAlloc;\n        g_FunctionTable[FunctionTypes::VirtualAlloc].Detoured =\n            ::DetouredVirtualAlloc;\n\n        g_FunctionTable[FunctionTypes::VirtualAllocEx].Original =\n            ::VirtualAllocEx;\n        g_FunctionTable[FunctionTypes::VirtualAllocEx].Detoured =\n            ::DetouredVirtualAllocEx;\n\n        g_FunctionTable[FunctionTypes::VirtualProtect].Original =\n            ::VirtualProtect;\n        g_FunctionTable[FunctionTypes::VirtualProtect].Detoured =\n            ::DetouredVirtualProtect;\n\n        g_FunctionTable[FunctionTypes::VirtualProtectEx].Original =\n            ::VirtualProtectEx;\n        g_FunctionTable[FunctionTypes::VirtualProtectEx].Detoured =\n            ::DetouredVirtualProtectEx;\n\n        return true;\n    }\n\n    static void UninitializeFunctionTable()\n    {\n        for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)\n        {\n            g_FunctionTable[i].Original = nullptr;\n            g_FunctionTable[i].Detoured = nullptr;\n        }\n    }\n}\n#endif // _DEBUG\n\nEXTERN_C MO_RESULT MOAPI K7BaseInitializeDynamicLinkLibraryBlocker()\n{\n#ifndef _DEBUG\n    if (::K7BaseGetAllowDynamicCodeGenerationPolicy())\n    {\n        return MO_RESULT_SUCCESS_OK;\n    }\n\n    if (!::InitializeFunctionTable())\n    {\n        return MO_RESULT_ERROR_FAIL;\n    }\n\n    ::K7BaseDetourTransactionBegin();\n    ::K7BaseDetourUpdateThread(::GetCurrentThread());\n    for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)\n    {\n        if (g_FunctionTable[i].Original &&\n            g_FunctionTable[i].Detoured)\n        {\n            if (NO_ERROR != ::K7BaseDetourAttach(\n                &g_FunctionTable[i].Original,\n                g_FunctionTable[i].Detoured))\n            {\n                ::K7BaseDetourTransactionAbort();\n                ::UninitializeFunctionTable();\n                return MO_RESULT_ERROR_FAIL;\n            }\n        }\n    }\n    ::K7BaseDetourTransactionCommit();\n#endif // _DEBUG\n\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseUninitializeDynamicLinkLibraryBlocker()\n{\n#ifndef _DEBUG\n    if (::K7BaseGetAllowDynamicCodeGenerationPolicy())\n    {\n        return MO_RESULT_SUCCESS_OK;\n    }\n\n    ::K7BaseDetourTransactionBegin();\n    ::K7BaseDetourUpdateThread(::GetCurrentThread());\n    for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)\n    {\n        if (g_FunctionTable[i].Original &&\n            g_FunctionTable[i].Detoured)\n        {\n            if (NO_ERROR != ::K7BaseDetourDetach(\n                &g_FunctionTable[i].Original,\n                g_FunctionTable[i].Detoured))\n            {\n                ::K7BaseDetourTransactionAbort();\n                return MO_RESULT_ERROR_FAIL;\n            }\n        }\n    }\n    ::K7BaseDetourTransactionCommit();\n\n    ::UninitializeFunctionTable();\n\n    {\n        std::lock_guard<std::mutex> Lock(g_DynamicCodeRangesMutex);\n        g_DynamicCodeRanges.clear();\n    }\n#endif // _DEBUG\n    return MO_RESULT_SUCCESS_OK;\n}\n"
  },
  {
    "path": "K7Base/K7BaseModern.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BaseModern.cpp\n * PURPOSE:    Implementation for NanaZip Platform Base Modern Experiences\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7BasePrivate.h\"\n\nEXTERN_C BOOL WINAPI K7BaseModernFileTimeToLocalFileTime(\n    _In_ CONST FILETIME* lpFileTime,\n    _Out_ LPFILETIME lpLocalFileTime)\n{\n    if (!lpFileTime || !lpLocalFileTime)\n    {\n        ::SetLastError(ERROR_INVALID_PARAMETER);\n        return FALSE;\n    }\n\n    SYSTEMTIME UtcSystemTime = {};\n    if (!::FileTimeToSystemTime(lpFileTime, &UtcSystemTime))\n    {\n        return FALSE;\n    }\n\n    SYSTEMTIME LocalSystemTime = {};\n    if (!::SystemTimeToTzSpecificLocalTimeEx(\n        nullptr,\n        &UtcSystemTime,\n        &LocalSystemTime))\n    {\n        return FALSE;\n    }\n\n    return ::SystemTimeToFileTime(&LocalSystemTime, lpLocalFileTime);\n}\n\nEXTERN_C BOOL WINAPI K7BaseModernLocalFileTimeToFileTime(\n    _In_ CONST FILETIME* lpLocalFileTime,\n    _Out_ LPFILETIME lpFileTime)\n{\n    if (!lpLocalFileTime || !lpFileTime)\n    {\n        ::SetLastError(ERROR_INVALID_PARAMETER);\n        return FALSE;\n    }\n\n    SYSTEMTIME LocalSystemTime = {};\n    if (!::FileTimeToSystemTime(lpLocalFileTime, &LocalSystemTime))\n    {\n        return FALSE;\n    }\n\n    SYSTEMTIME UtcSystemTime = {};\n    if (!::TzSpecificLocalTimeToSystemTimeEx(\n        nullptr,\n        &LocalSystemTime,\n        &UtcSystemTime))\n    {\n        return FALSE;\n    }\n\n    return ::SystemTimeToFileTime(&UtcSystemTime, lpFileTime);\n}\n"
  },
  {
    "path": "K7Base/K7BasePolicies.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BasePolicies.cpp\n * PURPOSE:    Implementation for NanaZip Platform Base Policies Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: dinhngtu (contact@tudinh.xyz)\n *             MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7BasePrivate.h\"\n\n#include <Mile.Helpers.CppBase.h>\n\n#include <set>\n#include <string>\n\nnamespace\n{\n    // Note: These static variables are initialized with default policy\n    // settings. Also, no thread-safety mechanism is needed here because the\n    // only modification of these variables happens in the\n    // K7BaseInitializePolicies function should be called only once during the\n    // K7Base library initialization phase as early as possible.\n\n    static MO_BOOL g_AllowDynamicCodeGeneration = MO_FALSE;\n    static MO_BOOL g_AllowChildProcessCreation = MO_FALSE;\n    static std::set<std::string> g_AllowedHandlers;\n    static std::set<std::string> g_BlockedHandlers;\n    static std::set<std::string> g_AllowedCodecs;\n    static std::set<std::string> g_BlockedCodecs;\n    // MO_UINT32_MAX is undefined\n    static MO_UINT32 g_WriteZoneIdExtract = MO_UINT32_MAX;\n\n    static bool QueryDwordValue(\n        _Out_ PDWORD Value,\n        _In_ HKEY KeyHandle,\n        _In_ LPCWSTR ValueName)\n    {\n        DWORD Type = REG_NONE;\n        DWORD Length = sizeof(DWORD);\n        if (ERROR_SUCCESS != ::RegQueryValueExW(\n            KeyHandle,\n            ValueName,\n            nullptr,\n            &Type,\n            reinterpret_cast<LPBYTE>(Value),\n            &Length))\n        {\n            return false;\n        }\n        if (REG_DWORD != Type || sizeof(DWORD) != Length)\n        {\n            return false;\n        }\n        return true;\n    }\n\n    static std::set<std::string> QueryMultiStringValue(\n        _In_ HKEY KeyHandle,\n        _In_ LPCWSTR ValueName)\n    {\n        std::set<std::string> Result;\n\n        PMO_WIDE_CHAR Buffer = nullptr;\n\n        do\n        {\n            DWORD Type = REG_NONE;\n            DWORD Length = sizeof(DWORD);\n            if (ERROR_SUCCESS != ::RegQueryValueExW(\n                KeyHandle,\n                ValueName,\n                nullptr,\n                &Type,\n                nullptr,\n                &Length))\n            {\n                break;\n            }\n            if (REG_MULTI_SZ != Type)\n            {\n                break;\n            }\n\n            Buffer = static_cast<PMO_WIDE_CHAR>(::MileAllocateMemory(Length));\n            if (!Buffer)\n            {\n                break;\n            }\n\n            if (ERROR_SUCCESS != ::RegQueryValueExW(\n                KeyHandle,\n                ValueName,\n                nullptr,\n                nullptr,\n                reinterpret_cast<LPBYTE>(Buffer),\n                &Length))\n            {\n                break;\n            }\n\n            for (PMO_WIDE_CHAR Current = Buffer;\n                *Current;\n                Current += std::wcslen(Current) + 1)\n            {\n                Result.insert(Mile::ToString(CP_UTF8, std::wstring(Current)));\n            }\n        }\n        while (false);\n\n        if (Buffer)\n        {\n            ::MileFreeMemory(Buffer);\n        }\n\n        return Result;\n    }\n}\n\nEXTERN_C MO_RESULT MOAPI K7BaseInitializePolicies()\n{\n    HKEY PoliciesKeyHandle = nullptr;\n    if (ERROR_SUCCESS != ::RegOpenKeyExW(\n        HKEY_LOCAL_MACHINE,\n        L\"Software\\\\Policies\\\\M2Team\\\\NanaZip\",\n        0,\n        KEY_READ | KEY_WOW64_64KEY,\n        &PoliciesKeyHandle))\n    {\n        // NanaZip should use the default policy settings if the relevant\n        // policies registry key cannot be opened successfully.\n        return MO_RESULT_SUCCESS_OK;\n    }\n\n    {\n        DWORD Value = 0;\n        if (::QueryDwordValue(\n            &Value,\n            PoliciesKeyHandle,\n            L\"AllowDynamicCodeGeneration\"))\n        {\n            if (1 == Value)\n            {\n                // Only when the registry value is 1, NanaZip will allow dynamic\n                // code generation.\n                g_AllowDynamicCodeGeneration = MO_TRUE;\n            }\n        }\n    }\n\n    {\n        DWORD Value = 0;\n        if (::QueryDwordValue(\n            &Value,\n            PoliciesKeyHandle,\n            L\"AllowChildProcessCreation\"))\n        {\n            if (1 == Value)\n            {\n                // Only when the registry value is 1, NanaZip will allow child\n                // process creation.\n                g_AllowChildProcessCreation = MO_TRUE;\n            }\n        }\n    }\n\n    g_AllowedHandlers = ::QueryMultiStringValue(\n        PoliciesKeyHandle,\n        L\"AllowedHandlers\");\n\n    g_BlockedHandlers = ::QueryMultiStringValue(\n        PoliciesKeyHandle,\n        L\"BlockedHandlers\");\n\n    g_AllowedCodecs = ::QueryMultiStringValue(\n        PoliciesKeyHandle,\n        L\"AllowedCodecs\");\n\n    g_BlockedCodecs = ::QueryMultiStringValue(\n        PoliciesKeyHandle,\n        L\"BlockedCodecs\");\n\n    {\n        DWORD Value = 0;\n        if (::QueryDwordValue(\n            &Value,\n            PoliciesKeyHandle,\n            L\"WriteZoneIdExtract\"))\n        {\n            // Valid values are 0, 1, and 2.\n            if (Value <= 2)\n            {\n                g_WriteZoneIdExtract = Value;\n            }\n        }\n    }\n\n    ::RegCloseKey(PoliciesKeyHandle);\n\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowDynamicCodeGenerationPolicy()\n{\n    return g_AllowDynamicCodeGeneration;\n}\n\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowChildProcessCreationPolicy()\n{\n    return g_AllowChildProcessCreation;\n}\n\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowedHandlerPolicy(\n    _In_ MO_CONSTANT_STRING Name)\n{\n    std::string HandlerName = std::string(Name);\n    if (!g_AllowedHandlers.empty())\n    {\n        return g_AllowedHandlers.contains(HandlerName) ? MO_TRUE : MO_FALSE;\n    }\n    if (!g_BlockedHandlers.empty())\n    {\n        return g_BlockedHandlers.contains(HandlerName) ? MO_FALSE : MO_TRUE;\n    }\n    return MO_TRUE;\n}\n\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowedCodecPolicy(\n    _In_ MO_CONSTANT_STRING Name)\n{\n    std::string CodecName = std::string(Name);\n    if (!g_AllowedCodecs.empty())\n    {\n        return g_AllowedCodecs.contains(CodecName) ? MO_TRUE : MO_FALSE;\n    }\n    if (!g_BlockedCodecs.empty())\n    {\n        return g_BlockedCodecs.contains(CodecName) ? MO_FALSE : MO_TRUE;\n    }\n    return MO_TRUE;\n}\n\nEXTERN_C MO_UINT32 MOAPI K7BaseGetWriteZoneIdExtractPolicy()\n{\n    return g_WriteZoneIdExtract;\n}\n"
  },
  {
    "path": "K7Base/K7BasePrivate.h",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BasePrivate.h\n * PURPOSE:    Definition for NanaZip Platform Base Private Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef K7_BASE_PRIVATE\n#define K7_BASE_PRIVATE\n\n#include \"K7Base.h\"\n\n#ifndef K7_BASE_POLICIES_PRIVATE\n#define K7_BASE_POLICIES_PRIVATE\n\n/**\n * @brief Initializes the NanaZip policy settings.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n * @remarks The function should be called only once during the K7Base library\n *          initialization phase as early as possible.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseInitializePolicies();\n\n/**\n * @brief Retrieves the policy setting for allowing dynamic code generation.\n * @return Returns MO_TRUE if dynamic code generation is allowed, or MO_FALSE if\n *         not.\n */\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowDynamicCodeGenerationPolicy();\n\n/**\n * @brief Retrieves the policy setting for allowing child process creation.\n * @return Returns MO_TRUE if child process creation is allowed, or MO_FALSE if\n *         not.\n */\nEXTERN_C MO_BOOL MOAPI K7BaseGetAllowChildProcessCreationPolicy();\n\n#endif // !K7_BASE_POLICIES_PRIVATE\n\n#ifndef K7_BASE_MITIGATIONS_PRIVATE\n#define K7_BASE_MITIGATIONS_PRIVATE\n\n/**\n * @brief Enables the mandatory mitigations for the current process.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseEnableMandatoryMitigations();\n\n/**\n * @brief Sets the dynamic code generation policy for the current thread.\n * @param AllowDynamicCodeGeneration Indicates whether to allow dynamic code\n *                                   generation for the current thread.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseSetCurrentThreadDynamicCodePolicyOptOut(\n    _In_ MO_BOOL AllowDynamicCodeGeneration);\n\n/**\n * @brief Initializes the dynamic link library blocker to workaround various\n *        issues caused by incompatible dynamic link libraries.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseInitializeDynamicLinkLibraryBlocker();\n\n/**\n * @brief Uninitializes the dynamic link library blocker.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7BaseUninitializeDynamicLinkLibraryBlocker();\n\n#endif // !K7_BASE_MITIGATIONS_PRIVATE\n\n#endif // !K7_BASE_PRIVATE\n"
  },
  {
    "path": "K7Base/K7BaseRedirector.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform Base Library (K7Base)\n * FILE:       K7BaseRedirector.cpp\n * PURPOSE:    Implementation for NanaZip Platform Base API Redirector\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7BasePrivate.h\"\n\n// Here are the linker-time redirections to replace the original APIs.\n// Implementations only for x64 and ARM64, if you want to learn how to achieve\n// that in x86, please refer to NanaZip.Shared.ModernExperienceShims project in\n// the historical NanaZip versions source code.\n\n#ifndef K7_REDIRECT\n#define K7_REDIRECT(Source, Target) \\\n    extern \"C\" __declspec(selectany) void const* const __imp_##Source = \\\n        reinterpret_cast<void const*>(::Target); \\\n    __pragma(comment(linker, \"/include:__imp_\" #Source))\n#endif // !K7_REDIRECT\n\nK7_REDIRECT(FileTimeToLocalFileTime, K7BaseModernFileTimeToLocalFileTime);\nK7_REDIRECT(LocalFileTimeToFileTime, K7BaseModernLocalFileTimeToFileTime);\n"
  },
  {
    "path": "K7Base/K7BaseStatic.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaZip Platform Base Library (K7Base)\n  FILE:       K7BaseStatic.props\n  PURPOSE:    MSBuild Properties for referencing the K7Base static library\n\n  LICENSE:    The MIT License\n\n  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n-->\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <Link>\n      <AdditionalDependencies>$(OutDir)K7BaseStatic.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <Target Name=\"K7BaseBuildSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(K7BaseDisableRedirector)' != 'true'\">\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)K7BaseRedirector.cpp\" />\n    </ItemGroup>\n  </Target>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Mobility\">\n      <Version>1.0.372</Version>\n    </PackageReference>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)K7BaseStatic.vcxproj\">\n      <Project>{38BB5165-3DB0-45B7-85CE-0A72DEF5CCD6}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "K7Base/K7BaseStatic.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{38BB5165-3DB0-45B7-85CE-0A72DEF5CCD6}</ProjectGuid>\n    <RootNamespace>K7Base</RootNamespace>\n    <MileProjectType>StaticLibrary</MileProjectType>\n    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>\n  </PropertyGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.ARM64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Mobility\">\n      <Version>1.0.372</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.Internal\">\n      <Version>1.0.3550</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Detours\">\n      <Version>1.0.2180</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.Helpers\">\n      <Version>1.0.1171</Version>\n    </PackageReference>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"K7BaseStatic.props\" />\n    <None Include=\"K7BaseRedirector.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"K7BaseDetours.cpp\" />\n    <ClCompile Include=\"K7BaseInitialize.cpp\" />\n    <ClCompile Include=\"K7BaseMitigations.cpp\" />\n    <ClCompile Include=\"K7BaseModern.cpp\" />\n    <ClCompile Include=\"K7BasePolicies.cpp\" />\n    <ClCompile Include=\"K7BaseHash.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"K7Base.h\" />\n    <ClInclude Include=\"K7BasePrivate.h\" />\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "K7Base/ReadMe.md",
    "content": "﻿# NanaZip Platform Base Library (K7Base)\n\n***Work In Progress***\n\nThe static and dynamic library that encapsulates the non-GUI portion of the base\nplatform infrastructure for the NanaZip. It's one of the foundational libraries\nof the NanaZip Platform Abstraction Layer.\n\nK7 is the alias of NanaZip. Here is the relationship between K7 and NanaZip: I\nhad mentioned one of the reasons that I call this project NanaZip because Nana\nis the romaji of なな which means seven in Japanese. But I had not mentioned the\nway I confirm that: I had recalled one of the Japanese VTubers called Kagura\nNana when I waiting my elder sister for dinner at Taiyanggong subway station,\nBeijing. For playing more puns, NanaZip uses the K7 (K -> Kagura, 7 -> Nana) as\nthe alias.\n\nK7Base is designed for Windows only, although the most of the K7Base interfaces\nare designed to be platform-independent. Maybe in the future, the K7Base will\nhave the implementations for Linux and FreeBSD, although the implementation may\nnot in this repository.\n\n## Features\n\n- Cryptography Support\n  - Hash Functions\n    - MD2\n    - MD4\n    - MD5\n    - SHA-1\n    - SHA-256\n    - SHA-384\n    - SHA-512\n- Detours Library Wrappers\n- Modern Experiences Support (non-GUI)\n- Policies Support\n- Security Mitigations Support\n"
  },
  {
    "path": "K7User/K7User.def",
    "content": "﻿LIBRARY\n\nEXPORTS\n\nK7UserInitializeDarkModeSupport\n\nK7UserModernMessageBoxW\nK7UserModernSHBrowseForFolderW\nK7UserModernLaunchDefaultAppsSettings\nK7UserModernSetForegroundWindow\nK7UserModernSetForegroundProcessMainWindow\n"
  },
  {
    "path": "K7User/K7User.h",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform User Library (K7User)\n * FILE:       K7User.h\n * PURPOSE:    Definition for NanaZip Platform User Public Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef K7_USER\n#define K7_USER\n\n#include <Mile.Mobility.Portable.Types.h>\n#ifndef MILE_MOBILITY_ENABLE_MINIMUM_SAL\n#include <sal.h>\n#endif // !MILE_MOBILITY_ENABLE_MINIMUM_SAL\n\n // Workaround for Windows SDK, which defines these types in #ifndef VOID block.\n // That design is terrible, but needs to have a workaround.\n#ifdef VOID\ntypedef char CHAR;\ntypedef short SHORT;\ntypedef long LONG;\n#endif // VOID\n\n#include <Windows.h>\n#include <ShlObj_core.h>\n\n#ifndef K7_USER_DARK_MODE\n#define K7_USER_DARK_MODE\n\n/**\n * @brief Initializes the dark mode support.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7UserInitializeDarkModeSupport();\n\n#endif // !K7_USER_DARK_MODE\n\n#ifndef K7_USER_MODERN\n#define K7_USER_MODERN\n\n/**\n * @brief Displays a modal dialog box that contains a system icon, a set of\n *        buttons, and a brief application-specific message, such as status or\n *        error information. The message box returns an integer value that\n *        indicates which button the user clicked.\n * @param hWnd A handle to the owner window of the message box to be created. If\n *             this parameter is nullptr, the message box has no owner window.\n * @param lpText The message to be displayed. If the string consists of more\n *               than one line, you can separate the lines using a carriage\n *               return and/or linefeed character between each line.\n * @param lpCaption The dialog box title. If this parameter is nullptr, the\n *                  default title is Error.\n * @param uType The contents and behavior of the dialog box.\n * @return If the function fails, the return value is zero. To get extended\n *         error information, call GetLastError. If the function succeeds, the\n *         return value is one of the button ID values.\n * @remark For more information, see MessageBoxW.\n */\nEXTERN_C int WINAPI K7UserModernMessageBoxW(\n    _In_opt_ HWND hWnd,\n    _In_opt_ LPCWSTR lpText,\n    _In_opt_ LPCWSTR lpCaption,\n    _In_ UINT uType);\n\n/**\n * @brief Displays a dialog box that enables the user to select a Shell folder.\n * @param lpbi A pointer to a BROWSEINFO structure that contains information\n *             used to display the dialog box.\n * @return Returns a PIDL that specifies the location of the selected folder\n *         relative to the root of the namespace. If the user chooses the Cancel\n *         button in the dialog box, the return value is nullptr. It is possible\n *         that the PIDL returned is that of a folder shortcut rather than a\n *         folder.\n * @remark For more information, see SHBrowseForFolderW.\n */\nEXTERN_C PIDLIST_ABSOLUTE WINAPI K7UserModernSHBrowseForFolderW(\n    _In_ LPBROWSEINFOW lpbi);\n\n/**\n * @brief Launches the Windows Settings Default Apps settings page for the\n *        current application.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7UserModernLaunchDefaultAppsSettings();\n\n/**\n * @brief Tries to bring the specified window to the foreground and activates\n *        the window. Keyboard input is directed to the window, and various\n *        visual cues are changed for the user.\n * @param WindowHandle A handle to the window that should be activated and\n *                     brought to the foreground.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundWindow(\n    _In_ HWND WindowHandle);\n\n/**\n * @brief Tries to bring the main window of the specified process to the\n *        foreground and activates the window. Keyboard input is directed to the\n *        window, and various visual cues are changed for the user.\n * @param ProcessHandle A handle to the process whose main window should be\n *                      activated and brought to the foreground.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundProcessMainWindow(\n    _In_ HANDLE ProcessHandle);\n\n#endif // !K7_USER_MODERN\n\n#endif // !K7_USER\n"
  },
  {
    "path": "K7User/K7User.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaZip Platform User Library (K7User)\n  FILE:       K7User.props\n  PURPOSE:    MSBuild Properties for referencing the K7User dynamic library\n\n  LICENSE:    The MIT License\n\n  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n-->\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <Link>\n      <AdditionalDependencies>$(OutDir)K7User.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <Target Name=\"K7UserBuildSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(K7UserDisableRedirector)' != 'true'\">\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)K7UserRedirector.cpp\" />\n    </ItemGroup>\n  </Target>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Mobility\">\n      <Version>1.0.372</Version>\n    </PackageReference>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)K7User.vcxproj\">\n      <Project>{F9BF062B-998F-45A4-8285-96E4A0D5EC00}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "K7User/K7User.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{F9BF062B-998F-45A4-8285-96E4A0D5EC00}</ProjectGuid>\n    <RootNamespace>K7User</RootNamespace>\n    <MileProjectType>DynamicLibrary</MileProjectType>\n    <WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Platform User Library</MileProjectFileDescription>\n    <MileProjectInternalName>K7User</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>K7User.dll</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n    <K7BaseDisableRedirector>true</K7BaseDisableRedirector>\n    <K7UserDisableRedirector>true</K7UserDisableRedirector>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.ARM64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Project=\"$(MSBuildThisFileDirectory)K7UserStatic.props\" />\n  <Import Project=\"..\\K7Base\\K7Base.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n    <Link>\n      <ModuleDefinitionFile>K7User.def</ModuleDefinitionFile>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <None Include=\"K7User.def\" />\n    <None Include=\"K7User.props\" />\n    <None Include=\"K7UserRedirector.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "K7User/K7UserDarkMode.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform User Library (K7User)\n * FILE:       K7UserDarkMode.cpp\n * PURPOSE:    Implementation for NanaZip Platform User Dark Mode Support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7UserPrivate.h\"\n\n#include <Mile.Helpers.h>\n#include <Mile.Helpers.CppBase.h>\n\n#include <K7Base.h>\n\n#include <Uxtheme.h>\n#pragma comment(lib, \"Uxtheme.lib\")\n\nEXTERN_C HTHEME WINAPI OpenNcThemeData(\n    _In_opt_ HWND hwnd,\n    _In_ LPCWSTR pszClassList);\n\nEXTERN_C HRESULT WINAPI GetThemeClass(\n    _In_ HTHEME hTheme,\n    _Out_ LPWSTR pszClassName,\n    _In_ int cchClassName);\n\n#include <vssym32.h>\n#include <Richedit.h>\n\n#include <dwmapi.h>\n#pragma comment(lib, \"dwmapi.lib\")\n\n#include <ShellScalingApi.h>\n\n#include <CommCtrl.h>\n#pragma comment(lib,\"comctl32.lib\")\n\n// TODO: Move some workaround for NanaZip.UI.* to this.\n\nnamespace\n{\n    const COLORREF g_LightModeBackgroundColor = RGB(255, 255, 255);\n    const COLORREF g_LightModeForegroundColor = RGB(0, 0, 0);\n\n    const COLORREF g_DarkModeBackgroundColor = RGB(0, 0, 0);\n    const COLORREF g_DarkModeForegroundColor = RGB(255, 255, 255);\n    const COLORREF g_DarkModeBorderColor = RGB(127, 127, 127);\n    const COLORREF g_DarkModeMenuSelectedBackgroundColor = RGB(65, 65, 65);\n\n    static HBRUSH GetDarkModeBackgroundBrush()\n    {\n        static HBRUSH CachedResult =\n            ::CreateSolidBrush(g_DarkModeBackgroundColor);\n        return CachedResult;\n    }\n\n    static HBRUSH GetDarkModeForegroundBrush()\n    {\n        static HBRUSH CachedResult =\n            ::CreateSolidBrush(g_DarkModeForegroundColor);\n        return CachedResult;\n    }\n\n    static HBRUSH GetDarkModeBorderBrush()\n    {\n        static HBRUSH CachedResult =\n            ::CreateSolidBrush(g_DarkModeBorderColor);\n        return CachedResult;\n    }\n\n    static HBRUSH GetDarkModeMenuSelectedBackgroundBrush()\n    {\n        static HBRUSH CachedResult =\n            ::CreateSolidBrush(g_DarkModeMenuSelectedBackgroundColor);\n        return CachedResult;\n    }\n\n    static bool IsStandardDynamicRangeMode()\n    {\n        static bool CachedResult = ([]() -> bool\n        {\n            bool Result = true;\n\n            UINT32 NumPathArrayElements = 0;\n            UINT32 NumModeInfoArrayElements = 0;\n            if (ERROR_SUCCESS == ::GetDisplayConfigBufferSizes(\n                QDC_ONLY_ACTIVE_PATHS,\n                &NumPathArrayElements,\n                &NumModeInfoArrayElements))\n            {\n                std::vector<DISPLAYCONFIG_PATH_INFO> PathArray(\n                    NumPathArrayElements);\n                std::vector<DISPLAYCONFIG_MODE_INFO> ModeInfoArray(\n                    NumModeInfoArrayElements);\n                if (ERROR_SUCCESS == ::QueryDisplayConfig(\n                    QDC_ONLY_ACTIVE_PATHS,\n                    &NumPathArrayElements,\n                    &PathArray[0],\n                    &NumModeInfoArrayElements,\n                    &ModeInfoArray[0],\n                    nullptr))\n                {\n                    for (DISPLAYCONFIG_PATH_INFO const& Path : PathArray)\n                    {\n                        DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO AdvancedColorInfo;\n                        std::memset(\n                            &AdvancedColorInfo,\n                            0,\n                            sizeof(DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO));\n                        AdvancedColorInfo.header.type =\n                            DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;\n                        AdvancedColorInfo.header.size =\n                            sizeof(DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO);\n                        AdvancedColorInfo.header.adapterId =\n                            Path.targetInfo.adapterId;\n                        AdvancedColorInfo.header.id =\n                            Path.targetInfo.id;\n                        if (ERROR_SUCCESS == ::DisplayConfigGetDeviceInfo(\n                            &AdvancedColorInfo.header))\n                        {\n                            if (AdvancedColorInfo.advancedColorEnabled)\n                            {\n                                Result = false;\n                                break;\n                            }\n                        }\n                    }\n                }\n            }\n\n            return Result;\n        }());\n\n        return CachedResult;\n    }\n\n    static volatile bool g_GlobalInitialized = false;\n\n    static LRESULT CALLBACK CallWndProcCallback(\n        _In_ int nCode,\n        _In_ WPARAM wParam,\n        _In_ LPARAM lParam);\n\n    struct ThreadContext\n    {\n    public:\n\n        // Fields for all scenarios.\n        // Should always be available if ShouldAppsUseDarkMode is true.\n\n        bool volatile ShouldAppsUseDarkMode = false;\n        HHOOK volatile WindowsHookHandle = nullptr;\n\n        // Fields for specific scenarios.\n        // May not be available, which need to be checked before use.\n\n        bool volatile MicaBackdropAvailable = false;\n        HTHEME TabControlThemeHandle = nullptr;\n        HTHEME StatusBarThemeHandle = nullptr;\n\n    public:\n\n        ThreadContext()\n        {\n            this->WindowsHookHandle = ::SetWindowsHookExW(\n                WH_CALLWNDPROC,\n                ::CallWndProcCallback,\n                nullptr,\n                ::GetCurrentThreadId());\n            if (!this->WindowsHookHandle)\n            {\n                return;\n            }\n\n            // Put this at the end of constructor to ensure that the dark mode\n            // support won't be enabled before the thread context is fully\n            // initialized to reduce the possibility of unintended behaviors.\n            this->ShouldAppsUseDarkMode =\n                ::MileShouldAppsUseDarkMode() &&\n                !::MileShouldAppsUseHighContrastMode();\n        }\n\n        ~ThreadContext()\n        {\n            // Put this at the beginning of destructor to ensure that the dark\n            // mode support won't be enabled after the thread context starts to\n            // uninitialize to reduce the possibility of unintended behaviors.\n            this->ShouldAppsUseDarkMode = false;\n\n            if (this->WindowsHookHandle)\n            {\n                ::UnhookWindowsHookEx(this->WindowsHookHandle);\n                this->WindowsHookHandle = nullptr;\n            }\n        }\n    };\n    thread_local ThreadContext g_ThreadContext;\n\n    static void RefreshWindowTheme(\n        _In_ HWND WindowHandle)\n    {\n        wchar_t ClassName[256] = {};\n        if (0 != ::GetClassNameW(\n            WindowHandle,\n            ClassName,\n            MO_ARRAY_SIZE(ClassName)))\n        {\n            if (0 == std::wcscmp(ClassName, WC_BUTTONW))\n            {\n                ::SetWindowTheme(WindowHandle, L\"Explorer\", nullptr);\n            }\n            else if (\n                (0 == std::wcscmp(ClassName, WC_COMBOBOXW)) ||\n                (0 == std::wcscmp(ClassName, WC_EDITW)))\n            {\n                ::SetWindowTheme(WindowHandle, L\"CFD\", nullptr);\n                ::MileAllowDarkModeForWindow(WindowHandle, TRUE);\n            }\n            else if (0 == std::wcscmp(ClassName, WC_HEADERW))\n            {\n                ::SetWindowTheme(WindowHandle, L\"ItemsView\", nullptr);\n            }\n            else if (0 == std::wcscmp(ClassName, WC_LISTVIEWW))\n            {\n                ::SetWindowTheme(WindowHandle, L\"ItemsView\", nullptr);\n\n                if (g_ThreadContext.ShouldAppsUseDarkMode)\n                {\n                    ListView_SetTextBkColor(\n                        WindowHandle,\n                        g_DarkModeBackgroundColor);\n                    ListView_SetBkColor(\n                        WindowHandle,\n                        g_DarkModeBackgroundColor);\n                    ListView_SetTextColor(\n                        WindowHandle,\n                        g_DarkModeForegroundColor);\n                }\n                else\n                {\n                    ListView_SetTextBkColor(\n                        WindowHandle,\n                        g_LightModeBackgroundColor);\n                    ListView_SetBkColor(\n                        WindowHandle,\n                        g_LightModeBackgroundColor);\n                    ListView_SetTextColor(\n                        WindowHandle,\n                        g_LightModeForegroundColor);\n                }\n            }\n            else if (0 == std::wcscmp(ClassName, STATUSCLASSNAMEW))\n            {\n                ::SetWindowLongW(\n                    WindowHandle,\n                    GWL_EXSTYLE,\n                    ::GetWindowLongW(\n                        WindowHandle,\n                        GWL_EXSTYLE) | WS_EX_COMPOSITED);\n            }\n            else if (0 == std::wcscmp(ClassName, WC_TABCONTROLW))\n            {\n                ::SetWindowLongW(\n                    WindowHandle,\n                    GWL_EXSTYLE,\n                    ::GetWindowLongW(\n                        WindowHandle,\n                        GWL_EXSTYLE) | WS_EX_COMPOSITED);\n            }\n            else\n            {\n                // DO NOT USE ELSE IF INSTEAD\n                // FOR HANDLING DYNAMIC DARK AND LIGHT MODE SWITCH PROPERLY\n\n                if (0 == std::wcscmp(ClassName, TOOLBARCLASSNAMEW))\n                {\n                    // make it double bufferred\n                    ::SetWindowLongW(\n                        WindowHandle,\n                        GWL_EXSTYLE,\n                        ::GetWindowLongW(\n                            WindowHandle,\n                            GWL_EXSTYLE) | WS_EX_COMPOSITED);\n\n                    COLORSCHEME ColorScheme;\n                    ColorScheme.dwSize = sizeof(COLORSCHEME);\n                    ColorScheme.clrBtnHighlight = CLR_DEFAULT;\n                    ColorScheme.clrBtnShadow = CLR_DEFAULT;\n                    if (g_ThreadContext.ShouldAppsUseDarkMode)\n                    {\n                        ColorScheme.clrBtnHighlight = g_DarkModeBackgroundColor;\n                        ColorScheme.clrBtnShadow = g_DarkModeBackgroundColor;\n                    }\n                    ::SendMessageW(\n                        WindowHandle,\n                        TB_SETCOLORSCHEME,\n                        0,\n                        reinterpret_cast<LPARAM>(&ColorScheme));\n                }\n\n                ::SendMessageW(WindowHandle, WM_THEMECHANGED, 0, 0);\n            }\n        }\n    }\n\n    static bool IsFileManagerWindowClassName(\n        _In_ LPCWSTR ClassName)\n    {\n        return (0 == std::wcscmp(ClassName, L\"NanaZip.Modern.FileManager\"));\n    }\n\n    static bool IsFileManagerPanelWindowClassName(\n        _In_ LPCWSTR ClassName)\n    {\n        return (0 == std::wcscmp(ClassName, L\"NanaZip::Panel\"));\n    }\n\n    static bool IsFileManagerWindow(\n        _In_ HWND WindowHandle)\n    {\n        wchar_t ClassName[256] = {};\n        if (0 != ::GetClassNameW(\n            WindowHandle,\n            ClassName,\n            MO_ARRAY_SIZE(ClassName)))\n        {\n            return ::IsFileManagerWindowClassName(ClassName);\n        }\n\n        return false;\n    }\n\n    LRESULT CALLBACK WindowSubclassCallback(\n        _In_ HWND hWnd,\n        _In_ UINT uMsg,\n        _In_ WPARAM wParam,\n        _In_ LPARAM lParam,\n        _In_ UINT_PTR uIdSubclass,\n        _In_ DWORD_PTR dwRefData)\n    {\n        UNREFERENCED_PARAMETER(uIdSubclass);\n        UNREFERENCED_PARAMETER(dwRefData);\n\n        switch (uMsg)\n        {\n        case WM_CTLCOLOREDIT:\n        case WM_CTLCOLORLISTBOX:\n        case WM_CTLCOLORDLG:\n        case WM_CTLCOLORSTATIC:\n        case WM_CTLCOLORBTN:\n        {\n            if (g_ThreadContext.ShouldAppsUseDarkMode)\n            {\n                HDC DeviceContextHandle = reinterpret_cast<HDC>(wParam);\n                if (DeviceContextHandle)\n                {\n                    ::SetTextColor(\n                        DeviceContextHandle,\n                        g_DarkModeForegroundColor);\n                    ::SetBkColor(\n                        DeviceContextHandle,\n                        g_DarkModeBackgroundColor);\n                }\n\n                return reinterpret_cast<INT_PTR>(\n                    ::GetDarkModeBackgroundBrush());\n            }\n\n            break;\n        }\n        default:\n            break;\n        }\n\n        LRESULT Result = ::DefSubclassProc(\n            hWnd,\n            uMsg,\n            wParam,\n            lParam);\n\n        switch (uMsg)\n        {\n        case WM_SETTINGCHANGE:\n        {\n            LPCTSTR Section = reinterpret_cast<LPCTSTR>(lParam);\n\n            if (Section && 0 == std::wcscmp(Section, L\"ImmersiveColorSet\"))\n            {\n                ::MileRefreshImmersiveColorPolicyState();\n\n                g_ThreadContext.ShouldAppsUseDarkMode =\n                    ::MileShouldAppsUseDarkMode() &&\n                    !::MileShouldAppsUseHighContrastMode();\n\n                ::MileEnableImmersiveDarkModeForWindow(\n                    hWnd,\n                    g_ThreadContext.ShouldAppsUseDarkMode);\n\n                bool ShouldExtendFrame = (\n                    g_ThreadContext.ShouldAppsUseDarkMode &&\n                    ::IsStandardDynamicRangeMode() &&\n                    g_ThreadContext.MicaBackdropAvailable);\n                MARGINS Margins = {};\n                if (ShouldExtendFrame)\n                {\n                    Margins = { -1 };\n                }\n                else if (::IsFileManagerWindow(hWnd))\n                {\n                    UINT DpiValue = ::GetDpiForWindow(hWnd);\n                    Margins.cyTopHeight =\n                        ::MulDiv(84, DpiValue, USER_DEFAULT_SCREEN_DPI);\n                    Margins.cyBottomHeight =\n                        ::MulDiv(32, DpiValue, USER_DEFAULT_SCREEN_DPI);\n                }\n                ::DwmExtendFrameIntoClientArea(hWnd, &Margins);\n\n                ::EnumChildWindows(\n                    hWnd,\n                    [](\n                        _In_ HWND hWnd,\n                        _In_ LPARAM lParam) -> BOOL\n                {\n                    UNREFERENCED_PARAMETER(lParam);\n                    ::RefreshWindowTheme(hWnd);\n                    return TRUE;\n                },\n                    0);\n\n                ::InvalidateRect(hWnd, nullptr, TRUE);\n            }\n\n            break;\n        }\n        case WM_INITDIALOG:\n        case WM_CREATE:\n        {\n            ::MileAllowDarkModeForWindow(\n                hWnd,\n                TRUE);\n\n            ::MileSetWindowSystemBackdropTypeAttribute(\n                hWnd,\n                MILE_WINDOW_SYSTEM_BACKDROP_TYPE_MICA);\n\n            g_ThreadContext.MicaBackdropAvailable =\n                (S_OK == ::MileEnableImmersiveDarkModeForWindow(\n                    hWnd,\n                    g_ThreadContext.ShouldAppsUseDarkMode));\n\n            bool ShouldExtendFrame = (\n                g_ThreadContext.ShouldAppsUseDarkMode &&\n                ::IsStandardDynamicRangeMode() &&\n                g_ThreadContext.MicaBackdropAvailable);\n            if (ShouldExtendFrame)\n            {\n                MARGINS Margins = { -1 };\n                ::DwmExtendFrameIntoClientArea(hWnd, &Margins);\n            }\n            else if (::IsFileManagerWindow(hWnd))\n            {\n                UINT DpiValue = ::GetDpiForWindow(hWnd);\n\n                MARGINS Margins = {};\n                Margins.cyTopHeight =\n                    ::MulDiv(84, DpiValue, USER_DEFAULT_SCREEN_DPI);\n                Margins.cyBottomHeight =\n                    ::MulDiv(32, DpiValue, USER_DEFAULT_SCREEN_DPI);\n                ::DwmExtendFrameIntoClientArea(hWnd, &Margins);\n            }\n\n            ::RefreshWindowTheme(hWnd);\n\n            wchar_t ClassName[256] = {};\n            if (0 != ::GetClassNameW(\n                hWnd,\n                ClassName,\n                MO_ARRAY_SIZE(ClassName)))\n            {\n                if (0 == std::wcscmp(ClassName, WC_TABCONTROLW))\n                {\n                    ::SetWindowLongPtrW(\n                        hWnd,\n                        GWL_STYLE,\n                        (::GetWindowLongPtrW(hWnd, GWL_STYLE) & ~TCS_BUTTONS)\n                        | TCS_TABS);\n                    ::SetWindowTheme(hWnd, nullptr, nullptr);\n                    g_ThreadContext.TabControlThemeHandle =\n                        ::GetWindowTheme(hWnd);\n                }\n                else if (0 == std::wcscmp(ClassName, STATUSCLASSNAMEW))\n                {\n                    g_ThreadContext.StatusBarThemeHandle =\n                        ::GetWindowTheme(hWnd);\n                }\n            }\n\n            break;\n        }\n        case WM_ERASEBKGND:\n        {\n            wchar_t ClassName[256] = {};\n            if (0 != ::GetClassNameW(\n                hWnd,\n                ClassName,\n                MO_ARRAY_SIZE(ClassName)))\n            {\n                if (g_ThreadContext.ShouldAppsUseDarkMode &&\n                    0 == std::wcscmp(ClassName, STATUSCLASSNAMEW))\n                {\n                    RECT ClientArea = {};\n                    if (::GetClientRect(hWnd, &ClientArea))\n                    {\n                        ::FillRect(\n                            reinterpret_cast<HDC>(wParam),\n                            &ClientArea,\n                            reinterpret_cast<HBRUSH>(\n                                ::GetStockObject(BLACK_BRUSH)));\n                        return TRUE;\n                    }\n                }\n\n                if (::IsFileManagerWindowClassName(ClassName) ||\n                    ::IsFileManagerPanelWindowClassName(ClassName))\n                {\n                    RECT ClientArea = {};\n                    if (::GetClientRect(hWnd, &ClientArea))\n                    {\n                        ::FillRect(\n                            reinterpret_cast<HDC>(wParam),\n                            &ClientArea,\n                            reinterpret_cast<HBRUSH>(\n                                ::GetStockObject(\n                                    g_ThreadContext.ShouldAppsUseDarkMode\n                                    ? BLACK_BRUSH\n                                    : WHITE_BRUSH)));\n                        return TRUE;\n                    }\n                }\n            }\n\n            break;\n        }\n        case WM_DPICHANGED:\n        {\n            bool ShouldExtendFrame = (\n                g_ThreadContext.ShouldAppsUseDarkMode &&\n                ::IsStandardDynamicRangeMode() &&\n                g_ThreadContext.MicaBackdropAvailable);\n            if (!ShouldExtendFrame && ::IsFileManagerWindow(hWnd))\n            {\n                UINT DpiValue = ::GetDpiForWindow(hWnd);\n\n                MARGINS Margins = {};\n                Margins.cyTopHeight =\n                    ::MulDiv(84, DpiValue, USER_DEFAULT_SCREEN_DPI);\n                Margins.cyBottomHeight =\n                    ::MulDiv(32, DpiValue, USER_DEFAULT_SCREEN_DPI);\n                ::DwmExtendFrameIntoClientArea(hWnd, &Margins);\n            }\n\n            break;\n        }\n        default:\n            break;\n        }\n\n        if (g_ThreadContext.ShouldAppsUseDarkMode && ::GetMenu(hWnd))\n        {\n            if (WM_UAHDRAWMENU == uMsg)\n            {\n                PUAHMENU UahMenu = reinterpret_cast<PUAHMENU>(lParam);\n                if (UahMenu)\n                {\n                    MENUBARINFO MenuBarInfo;\n                    MenuBarInfo.cbSize = sizeof(MENUBARINFO);\n                    if (::GetMenuBarInfo(hWnd, OBJID_MENU, 0, &MenuBarInfo))\n                    {\n                        RECT WindowRect = {};\n                        ::GetWindowRect(hWnd, &WindowRect);\n\n                        RECT MenuRect = MenuBarInfo.rcBar;\n                        ::OffsetRect(\n                            &MenuRect,\n                            -WindowRect.left,\n                            -WindowRect.top);\n\n                        ::FillRect(\n                            UahMenu->hdc,\n                            &MenuRect,\n                            ::GetDarkModeBackgroundBrush());\n                    }\n                }\n\n                return TRUE;\n            }\n            else if (WM_UAHDRAWMENUITEM == uMsg)\n            {\n                PUAHDRAWMENUITEM UahDrawMenuItem =\n                    reinterpret_cast<PUAHDRAWMENUITEM>(lParam);\n                if (UahDrawMenuItem)\n                {\n                    PDRAWITEMSTRUCT DrawItemStruct = &UahDrawMenuItem->dis;\n                    if (ODT_MENU == DrawItemStruct->CtlType)\n                    {\n                        wchar_t Buffer[256] = {};\n                        MENUITEMINFOW MenuItemInfo;\n                        MenuItemInfo.cbSize = sizeof(MENUITEMINFOW);\n                        MenuItemInfo.fMask = MIIM_STRING;\n                        MenuItemInfo.dwTypeData = Buffer;\n                        MenuItemInfo.cch = MO_ARRAY_SIZE(Buffer) - 1;\n                        if (::GetMenuItemInfoW(\n                            UahDrawMenuItem->um.hmenu,\n                            UahDrawMenuItem->umi.iPosition,\n                            TRUE,\n                            &MenuItemInfo))\n                        {\n                            int StateId = 0;\n                            COLORREF TextColor = g_DarkModeForegroundColor;\n                            HBRUSH BackgroundBrush =\n                                ::GetDarkModeBackgroundBrush();\n                            if (DrawItemStruct->itemState & ODS_INACTIVE)\n                            {\n                                StateId = MBI_DISABLED;\n                                TextColor = RGB(109, 109, 109);\n                            }\n                            else if ((DrawItemStruct->itemState & ODS_GRAYED) &&\n                                (DrawItemStruct->itemState & ODS_HOTLIGHT))\n                            {\n                                StateId = MBI_DISABLEDHOT;\n                            }\n                            else if (DrawItemStruct->itemState & ODS_GRAYED)\n                            {\n                                StateId = MBI_DISABLED;\n                                TextColor = RGB(109, 109, 109);\n                            }\n                            else if (DrawItemStruct->itemState\n                                & (ODS_HOTLIGHT | ODS_SELECTED))\n                            {\n                                StateId = MBI_HOT;\n                                BackgroundBrush =\n                                    ::GetDarkModeMenuSelectedBackgroundBrush();\n                            }\n                            else\n                            {\n                                StateId = MBI_NORMAL;\n                            }\n\n                            ::FillRect(\n                                DrawItemStruct->hDC,\n                                &DrawItemStruct->rcItem,\n                                BackgroundBrush);\n\n                            // We have to specify the text colour explicitly as\n                            // by default black would be used, making the menu\n                            // label unreadable on the (almost) black\n                            // background.\n                            DTTOPTS TextOptions = {};\n                            TextOptions.dwSize = sizeof(DTTOPTS);\n                            TextOptions.dwFlags = DTT_TEXTCOLOR;\n                            TextOptions.crText = TextColor;\n\n                            DWORD TextFlags =\n                                DT_CENTER | DT_VCENTER | DT_SINGLELINE;\n                            if (DrawItemStruct->itemState & ODS_NOACCEL)\n                            {\n                                TextFlags |= DT_HIDEPREFIX;\n                            }\n\n                            HTHEME ThemeHandle = ::OpenThemeData(hWnd, L\"Menu\");\n                            if (ThemeHandle)\n                            {\n                                ::DrawThemeTextEx(\n                                    ThemeHandle,\n                                    UahDrawMenuItem->um.hdc,\n                                    MENU_BARITEM,\n                                    StateId,\n                                    Buffer,\n                                    static_cast<int>(std::wcslen(Buffer)),\n                                    TextFlags,\n                                    &DrawItemStruct->rcItem,\n                                    &TextOptions);\n\n                                ::CloseThemeData(ThemeHandle);\n                            }\n                        }\n                    }\n                }\n\n                return TRUE;\n            }\n            else if (WM_NCPAINT == uMsg || WM_NCACTIVATE == uMsg)\n            {\n                MENUBARINFO MenuBarInfo;\n                MenuBarInfo.cbSize = sizeof(MENUBARINFO);\n                if (::GetMenuBarInfo(hWnd, OBJID_MENU, 0, &MenuBarInfo))\n                {\n                    RECT ClientRect = {};\n                    ::GetClientRect(hWnd, &ClientRect);\n\n                    ::MapWindowPoints(\n                        hWnd,\n                        nullptr,\n                        reinterpret_cast<PPOINT>(&ClientRect),\n                        2);\n\n                    RECT WindowRect = {};\n                    ::GetWindowRect(hWnd, &WindowRect);\n\n                    ::OffsetRect(\n                        &ClientRect,\n                        -WindowRect.left,\n                        -WindowRect.top);\n\n                    RECT AnnoyingLineRect = ClientRect;\n                    AnnoyingLineRect.bottom = AnnoyingLineRect.top;\n                    --AnnoyingLineRect.top;\n\n                    HDC DeviceContextHandle = ::GetWindowDC(hWnd);\n                    if (DeviceContextHandle)\n                    {\n                        ::FillRect(\n                            DeviceContextHandle,\n                            &AnnoyingLineRect,\n                            ::GetDarkModeBackgroundBrush());\n\n                        ::ReleaseDC(hWnd, DeviceContextHandle);\n                    }\n                }\n            }\n        }\n\n        return Result;\n    }\n\n    static std::wstring GetAssociatedModuleNameFromWindowHandle(\n        _In_ HWND WindowHandle)\n    {\n        // 32767 is the maximum path length without the terminating null\n        // character.\n        std::wstring Path(32767, L'\\0');\n        Path.resize(::GetWindowModuleFileNameW(\n            WindowHandle, &Path[0], static_cast<UINT>(Path.size())));\n        wchar_t* LastBackslash = std::wcsrchr(Path.data(), L'\\\\');\n        return LastBackslash ? std::wstring(LastBackslash + 1) : Path;\n    }\n\n    static bool IsModernizedWindow(\n        _In_ HWND WindowHandle)\n    {\n        std::wstring ModuleName =\n            ::GetAssociatedModuleNameFromWindowHandle(WindowHandle);\n        if (!::_wcsicmp(ModuleName.c_str(), L\"combase.dll\") ||\n            !::_wcsicmp(ModuleName.c_str(), L\"CoreMessaging.dll\") ||\n            !::_wcsicmp(ModuleName.c_str(), L\"InputHost.dll\") ||\n            !::_wcsicmp(ModuleName.c_str(), L\"Windows.UI.dll\") ||\n            !::_wcsicmp(ModuleName.c_str(), L\"Windows.UI.Xaml.dll\"))\n        {\n            return true;\n        }\n\n        wchar_t ClassName[256] = {};\n        if (0 != ::GetClassNameW(\n            WindowHandle,\n            ClassName,\n            MO_ARRAY_SIZE(ClassName)))\n        {\n            if (std::wcsstr(ClassName, L\"Windows.UI.\") ||\n                std::wcsstr(ClassName, L\"Mile.Xaml.\") ||\n                std::wcsstr(ClassName, L\"Xaml_WindowedPopupClass\"))\n            {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    static LRESULT CALLBACK CallWndProcCallback(\n        _In_ int nCode,\n        _In_ WPARAM wParam,\n        _In_ LPARAM lParam)\n    {\n        if (g_GlobalInitialized && nCode == HC_ACTION)\n        {\n            PCWPSTRUCT WndProcStruct =\n                reinterpret_cast<PCWPSTRUCT>(lParam);\n\n            switch (WndProcStruct->message)\n            {\n            case WM_CREATE:\n            case WM_INITDIALOG:\n            {\n                if (!::IsModernizedWindow(WndProcStruct->hwnd))\n                {\n                    ::SetWindowSubclass(\n                        WndProcStruct->hwnd,\n                        ::WindowSubclassCallback,\n                        0,\n                        0);\n                }\n                break;\n            }\n            default:\n                break;\n            }\n        }\n\n        return ::CallNextHookEx(\n            nullptr,\n            nCode,\n            wParam,\n            lParam);\n    }\n\n    namespace FunctionTypes\n    {\n        enum\n        {\n            GetSysColor,\n            GetSysColorBrush,\n            GetThemeColor,\n            DrawThemeText,\n            DrawThemeBackground,\n            DrawThemeBackgroundEx,\n            OpenNcThemeData,\n            GetThemeClass,\n\n            MaximumFunction\n        };\n    }\n\n    struct FunctionItem\n    {\n        PVOID Original;\n        PVOID Detoured;\n    };\n\n    FunctionItem g_FunctionTable[FunctionTypes::MaximumFunction];\n\n    static DWORD WINAPI OriginalGetSysColor(\n        _In_ int nIndex)\n    {\n        using FunctionType = decltype(::GetSysColor)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::GetSysColor].Original);\n        if (!FunctionAddress)\n        {\n            return 0;\n        }\n        return FunctionAddress(nIndex);\n    }\n\n    static HBRUSH WINAPI OriginalGetSysColorBrush(\n        _In_ int nIndex)\n    {\n        using FunctionType = decltype(::GetSysColorBrush)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::GetSysColorBrush].Original);\n        if (!FunctionAddress)\n        {\n            return nullptr;\n        }\n        return FunctionAddress(nIndex);\n    }\n\n    static HRESULT WINAPI OriginalGetThemeColor(\n        _In_ HTHEME hTheme,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ int iPropId,\n        _Out_ COLORREF* pColor)\n    {\n        using FunctionType = decltype(::GetThemeColor)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::GetThemeColor].Original);\n        if (!FunctionAddress)\n        {\n            return E_NOINTERFACE;\n        }\n        return FunctionAddress(\n            hTheme,\n            iPartId,\n            iStateId,\n            iPropId,\n            pColor);\n    }\n\n    static HRESULT WINAPI OriginalDrawThemeText(\n        _In_ HTHEME hTheme,\n        _In_ HDC hdc,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ LPCWSTR pszText,\n        _In_ int cchText,\n        _In_ DWORD dwTextFlags,\n        _In_ DWORD dwTextFlags2,\n        _In_ LPCRECT pRect)\n    {\n        using FunctionType = decltype(::DrawThemeText)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::DrawThemeText].Original);\n        if (!FunctionAddress)\n        {\n            return E_NOINTERFACE;\n        }\n        return FunctionAddress(\n            hTheme,\n            hdc,\n            iPartId,\n            iStateId,\n            pszText,\n            cchText,\n            dwTextFlags,\n            dwTextFlags2,\n            pRect);\n    }\n\n    static HRESULT WINAPI OriginalDrawThemeBackground(\n        _In_ HTHEME hTheme,\n        _In_ HDC hdc,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ LPCRECT pRect,\n        _In_opt_ LPCRECT pClipRect)\n    {\n        using FunctionType = decltype(::DrawThemeBackground)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::DrawThemeBackground].Original);\n        if (!FunctionAddress)\n        {\n            return E_NOINTERFACE;\n        }\n        return FunctionAddress(\n            hTheme,\n            hdc,\n            iPartId,\n            iStateId,\n            pRect,\n            pClipRect);\n    }\n\n    static HRESULT WINAPI OriginalDrawThemeBackgroundEx(\n        _In_ HTHEME hTheme,\n        _In_ HDC hdc,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ LPCRECT pRect,\n        _In_opt_ const DTBGOPTS* pOptions)\n    {\n        using FunctionType = decltype(::DrawThemeBackgroundEx)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::DrawThemeBackgroundEx].Original);\n        if (!FunctionAddress)\n        {\n            return E_NOINTERFACE;\n        }\n        return FunctionAddress(\n            hTheme,\n            hdc,\n            iPartId,\n            iStateId,\n            pRect,\n            pOptions);\n    }\n\n    static HTHEME WINAPI OriginalOpenNcThemeData(\n        _In_opt_ HWND hwnd,\n        _In_ LPCWSTR pszClassList)\n    {\n        using FunctionType = decltype(::OpenNcThemeData)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::OpenNcThemeData].Original);\n        if (!FunctionAddress)\n        {\n            return nullptr;\n        }\n        return FunctionAddress(hwnd, pszClassList);\n    }\n\n    static HRESULT WINAPI OriginalGetThemeClass(\n        _In_ HTHEME hTheme,\n        _Out_ LPWSTR pszClassName,\n        _In_ int cchClassName)\n    {\n        using FunctionType = decltype(::GetThemeClass)*;\n        FunctionType FunctionAddress = reinterpret_cast<FunctionType>(\n            g_FunctionTable[FunctionTypes::GetThemeClass].Original);\n        if (!FunctionAddress)\n        {\n            return E_NOINTERFACE;\n        }\n        return FunctionAddress(\n            hTheme,\n            pszClassName,\n            cchClassName);\n    }\n\n    static DWORD WINAPI DetouredGetSysColor(\n        _In_ int nIndex)\n    {\n        if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)\n        {\n            return ::OriginalGetSysColor(nIndex);\n        }\n\n        switch (nIndex)\n        {\n        case COLOR_WINDOW:\n        case COLOR_BTNFACE:\n            return g_DarkModeBackgroundColor;\n        case COLOR_WINDOWTEXT:\n        case COLOR_BTNTEXT:\n            return g_DarkModeForegroundColor;\n        default:\n            return ::OriginalGetSysColor(nIndex);\n        }\n    }\n\n    static HBRUSH WINAPI DetouredGetSysColorBrush(\n        _In_ int nIndex)\n    {\n        if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)\n        {\n            return ::OriginalGetSysColorBrush(nIndex);\n        }\n\n        switch (nIndex)\n        {\n        case COLOR_BTNFACE:\n            return ::GetDarkModeBackgroundBrush();\n        case COLOR_BTNTEXT:\n            return ::GetDarkModeForegroundBrush();\n        default:\n            return ::OriginalGetSysColorBrush(nIndex);\n        }\n    }\n\n    static HRESULT WINAPI DetouredGetThemeColor(\n        _In_ HTHEME hTheme,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ int iPropId,\n        _Out_ COLORREF* pColor)\n    {\n        if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)\n        {\n            return ::OriginalGetThemeColor(\n                hTheme,\n                iPartId,\n                iStateId,\n                iPropId,\n                pColor);\n        }\n\n        HRESULT hr = ::OriginalGetThemeColor(\n            hTheme,\n            iPartId,\n            iStateId,\n            iPropId,\n            pColor);\n        if (S_OK != hr)\n        {\n            return hr;\n        }\n\n        wchar_t ClassName[256] = {};\n        if (S_OK == ::OriginalGetThemeClass(\n            hTheme,\n            ClassName,\n            MO_ARRAY_SIZE(ClassName)))\n        {\n            if (0 == ::_wcsicmp(ClassName, VSCLASS_TASKDIALOGSTYLE))\n            {\n                if (TMT_TEXTCOLOR == iPropId)\n                {\n                    *pColor = g_DarkModeForegroundColor;\n                }\n            }\n        }\n\n        return S_OK;\n    }\n\n    static HRESULT WINAPI DetouredDrawThemeText(\n        _In_ HTHEME hTheme,\n        _In_ HDC hdc,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ LPCWSTR pszText,\n        _In_ int cchText,\n        _In_ DWORD dwTextFlags,\n        _In_ DWORD dwTextFlags2,\n        _In_ LPCRECT pRect)\n    {\n        if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)\n        {\n            return ::OriginalDrawThemeText(\n                hTheme,\n                hdc,\n                iPartId,\n                iStateId,\n                pszText,\n                cchText,\n                dwTextFlags,\n                dwTextFlags2,\n                pRect);\n        }\n\n        DTTOPTS TextOptions = {};\n        TextOptions.dwSize = sizeof(DTTOPTS);\n        TextOptions.dwFlags = DTT_TEXTCOLOR;\n        TextOptions.crText = g_DarkModeForegroundColor;\n\n        return ::DrawThemeTextEx(\n            hTheme,\n            hdc,\n            iPartId,\n            iStateId,\n            pszText,\n            cchText,\n            dwTextFlags,\n            const_cast<LPRECT>(pRect),\n            &TextOptions);\n    }\n\n    static HRESULT WINAPI DetouredDrawThemeBackground(\n        _In_ HTHEME hTheme,\n        _In_ HDC hdc,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ LPCRECT pRect,\n        _In_opt_ LPCRECT pClipRect)\n    {\n        if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)\n        {\n            return ::OriginalDrawThemeBackground(\n                hTheme,\n                hdc,\n                iPartId,\n                iStateId,\n                pRect,\n                pClipRect);\n        }\n\n        if (hTheme == g_ThreadContext.TabControlThemeHandle)\n        {\n            const int HoveredCheckStateId[] =\n            {\n                -1,\n                TIS_HOT,\n                TILES_HOT,\n                TIRES_HOT,\n                TIBES_HOT,\n                TTIS_HOT,\n                TTILES_HOT,\n                TTIRES_HOT,\n                TTIBES_HOT,\n                -1,\n                -1,\n                -1\n            };\n\n            const int SelectedCheckStateId[] =\n            {\n                -1,\n                TIS_SELECTED,\n                TILES_SELECTED,\n                TIRES_SELECTED,\n                TIBES_SELECTED,\n                TTIS_SELECTED,\n                TTILES_SELECTED,\n                TTIRES_SELECTED,\n                TTIBES_SELECTED,\n                -1,\n                -1,\n                -1\n            };\n\n            switch (iPartId)\n            {\n            case TABP_TABITEM:\n            case TABP_TABITEMLEFTEDGE:\n            case TABP_TABITEMRIGHTEDGE:\n            case TABP_TABITEMBOTHEDGE:\n            case TABP_TOPTABITEM:\n            case TABP_TOPTABITEMLEFTEDGE:\n            case TABP_TOPTABITEMRIGHTEDGE:\n            case TABP_TOPTABITEMBOTHEDGE:\n            {\n                RECT paddedRect = *pRect;\n                RECT insideRect =\n                {\n                    pRect->left + 1,\n                    pRect->top + 1,\n                    pRect->right - 1,\n                    pRect->bottom - 1\n                };\n\n                if (iStateId == SelectedCheckStateId[iPartId])\n                {\n                    paddedRect.top += 1;\n                    paddedRect.bottom -= 2;\n\n                    // Allow the rect to overlap so the bottom border outline is removed\n                    insideRect.top += 1;\n                    insideRect.bottom += 1;\n                }\n\n                ::FrameRect(\n                    hdc,\n                    &paddedRect,\n                    ::GetDarkModeBorderBrush());\n                ::FillRect(\n                    hdc,\n                    &insideRect,\n                    iStateId == HoveredCheckStateId[iPartId]\n                    ? ::GetDarkModeBorderBrush()\n                    : ::GetDarkModeBackgroundBrush());\n\n                return S_OK;\n            }\n            case TABP_PANE:\n                return S_OK;\n            default:\n                break;\n            }\n        }\n        else if (hTheme == g_ThreadContext.StatusBarThemeHandle)\n        {\n            switch (iPartId)\n            {\n            case 0:\n            {\n                // Outside border (top, right)\n                ::FillRect(hdc, pRect, ::GetDarkModeBorderBrush());\n                return S_OK;\n            }\n            case SP_PANE:\n            case SP_GRIPPERPANE:\n            case SP_GRIPPER:\n            {\n                // Everything else\n                ::FillRect(hdc, pRect, ::GetDarkModeBackgroundBrush());\n                return S_OK;\n            }\n            default:\n                break;\n            }\n        }\n\n        return ::OriginalDrawThemeBackground(\n            hTheme,\n            hdc,\n            iPartId,\n            iStateId,\n            pRect,\n            pClipRect);\n    }\n\n    static HRESULT WINAPI DetouredDrawThemeBackgroundEx(\n        _In_ HTHEME hTheme,\n        _In_ HDC hdc,\n        _In_ int iPartId,\n        _In_ int iStateId,\n        _In_ LPCRECT pRect,\n        _In_opt_ const DTBGOPTS* pOptions)\n    {\n        if (!g_GlobalInitialized || !g_ThreadContext.ShouldAppsUseDarkMode)\n        {\n            return ::OriginalDrawThemeBackgroundEx(\n                hTheme,\n                hdc,\n                iPartId,\n                iStateId,\n                pRect,\n                pOptions);\n        }\n\n        bool NeedTaskDialogWorkaround = (\n            TDLG_PRIMARYPANEL == iPartId ||\n            TDLG_SECONDARYPANEL == iPartId ||\n            TDLG_EXPANDOBUTTON == iPartId ||\n            TDLG_FOOTNOTEPANE == iPartId ||\n            TDLG_FOOTNOTESEPARATOR == iPartId);\n        if (NeedTaskDialogWorkaround)\n        {\n            NeedTaskDialogWorkaround = false;\n            wchar_t ClassName[256] = {};\n            if (S_OK == ::OriginalGetThemeClass(\n                hTheme,\n                ClassName,\n                MO_ARRAY_SIZE(ClassName)))\n            {\n                NeedTaskDialogWorkaround =\n                    (0 == ::_wcsicmp(ClassName, VSCLASS_TASKDIALOG));\n            }\n        }\n\n        if (NeedTaskDialogWorkaround)\n        {\n            if (TDLG_PRIMARYPANEL == iPartId)\n            {\n                ::FillRect(hdc, pRect, ::GetDarkModeBackgroundBrush());\n                return S_OK;\n            }\n            else if (\n                TDLG_SECONDARYPANEL == iPartId ||\n                TDLG_FOOTNOTEPANE == iPartId ||\n                TDLG_FOOTNOTESEPARATOR == iPartId)\n            {\n                ::FillRect(hdc, pRect, ::GetDarkModeBorderBrush());\n                RECT ContentRect = *pRect;\n                ContentRect.top += 1;\n                ::FillRect(hdc, &ContentRect, ::GetDarkModeBackgroundBrush());\n                return S_OK;\n            }\n            else if (iPartId == TDLG_EXPANDOBUTTON)\n            {\n                // It seems our current implementation doesn't have the issue\n                // that the button becomes invisible on dark mode in Windows 11,\n                // so we don't need to do anything here for now.\n            }\n        }\n\n        return ::OriginalDrawThemeBackgroundEx(\n            hTheme,\n            hdc,\n            iPartId,\n            iStateId,\n            pRect,\n            pOptions);\n    }\n\n    static HTHEME WINAPI DetouredOpenNcThemeData(\n        _In_opt_ HWND hwnd,\n        _In_ LPCWSTR pszClassList)\n    {\n        // Workaround for dark mode scrollbar\n        if (0 == std::wcscmp(pszClassList, L\"ScrollBar\"))\n        {\n            return ::OriginalOpenNcThemeData(nullptr, L\"Explorer::ScrollBar\");\n        }\n\n        return ::OriginalOpenNcThemeData(hwnd, pszClassList);\n    }\n\n    static bool InitializeFunctionTable()\n    {\n        g_FunctionTable[FunctionTypes::GetSysColor].Original =\n            ::GetSysColor;\n        g_FunctionTable[FunctionTypes::GetSysColor].Detoured =\n            ::DetouredGetSysColor;\n\n        g_FunctionTable[FunctionTypes::GetSysColorBrush].Original =\n            ::GetSysColorBrush;\n        g_FunctionTable[FunctionTypes::GetSysColorBrush].Detoured =\n            ::DetouredGetSysColorBrush;\n\n        g_FunctionTable[FunctionTypes::GetThemeColor].Original =\n            ::GetThemeColor;\n        g_FunctionTable[FunctionTypes::GetThemeColor].Detoured =\n            ::DetouredGetThemeColor;\n\n        g_FunctionTable[FunctionTypes::DrawThemeText].Original =\n            ::DrawThemeText;\n        g_FunctionTable[FunctionTypes::DrawThemeText].Detoured =\n            ::DetouredDrawThemeText;\n\n        g_FunctionTable[FunctionTypes::DrawThemeBackground].Original =\n            ::DrawThemeBackground;\n        g_FunctionTable[FunctionTypes::DrawThemeBackground].Detoured =\n            ::DetouredDrawThemeBackground;\n\n        g_FunctionTable[FunctionTypes::DrawThemeBackgroundEx].Original =\n            ::DrawThemeBackgroundEx;\n        g_FunctionTable[FunctionTypes::DrawThemeBackgroundEx].Detoured =\n            ::DetouredDrawThemeBackgroundEx;\n\n        {\n            HMODULE ModuleHandle = ::GetModuleHandleW(\n                L\"uxtheme.dll\");\n            if (ModuleHandle)\n            {\n                PVOID ProcAddress = ::GetProcAddress(\n                    ModuleHandle,\n                    MAKEINTRESOURCEA(49));\n                if (ProcAddress)\n                {\n                    g_FunctionTable[FunctionTypes::OpenNcThemeData].Original =\n                        ProcAddress;\n                    g_FunctionTable[FunctionTypes::OpenNcThemeData].Detoured =\n                        ::DetouredOpenNcThemeData;\n                }\n            }\n            if (ModuleHandle)\n            {\n                PVOID ProcAddress = ::GetProcAddress(\n                    ModuleHandle,\n                    MAKEINTRESOURCEA(74));\n                if (ProcAddress)\n                {\n                    g_FunctionTable[FunctionTypes::GetThemeClass].Original =\n                        ProcAddress;\n                    g_FunctionTable[FunctionTypes::GetThemeClass].Detoured =\n                        nullptr;\n                }\n            }\n        }\n\n        return true;\n    }\n\n    static void UninitializeFunctionTable()\n    {\n        for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)\n        {\n            g_FunctionTable[i].Original = nullptr;\n            g_FunctionTable[i].Detoured = nullptr;\n        }\n    }\n}\n\nEXTERN_C MO_RESULT MOAPI K7UserInitializeDarkModeSupport()\n{\n    if (g_GlobalInitialized)\n    {\n        return MO_RESULT_SUCCESS_OK;\n    }\n\n    if (!::MileIsWindowsVersionAtLeast(10, 0, 0))\n    {\n        // Dark mode is only supported on Windows 10 and above, so we can just\n        // return success without doing anything on older versions of Windows.\n        return MO_RESULT_SUCCESS_OK;\n    }\n\n    if (!::InitializeFunctionTable())\n    {\n        return MO_RESULT_ERROR_FAIL;\n    }\n\n    ::MileAllowDarkModeForApp(TRUE);\n    ::MileRefreshImmersiveColorPolicyState();\n\n    ::K7BaseDetourTransactionBegin();\n    ::K7BaseDetourUpdateThread(::GetCurrentThread());\n    for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)\n    {\n        if (g_FunctionTable[i].Original &&\n            g_FunctionTable[i].Detoured)\n        {\n            if (NO_ERROR != ::K7BaseDetourAttach(\n                &g_FunctionTable[i].Original,\n                g_FunctionTable[i].Detoured))\n            {\n                ::K7BaseDetourTransactionAbort();\n                ::UninitializeFunctionTable();\n                return MO_RESULT_ERROR_FAIL;\n            }\n        }\n    }\n    ::K7BaseDetourTransactionCommit();\n\n    g_GlobalInitialized = true;\n\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7UserUninitializeDarkModeSupport()\n{\n    if (!g_GlobalInitialized)\n    {\n        return MO_RESULT_SUCCESS_OK;\n    }\n    g_GlobalInitialized = false;\n\n    ::MileAllowDarkModeForApp(FALSE);\n    ::MileRefreshImmersiveColorPolicyState();\n\n    ::K7BaseDetourTransactionBegin();\n    ::K7BaseDetourUpdateThread(::GetCurrentThread());\n    for (size_t i = 0; i < FunctionTypes::MaximumFunction; ++i)\n    {\n        if (g_FunctionTable[i].Original &&\n            g_FunctionTable[i].Detoured)\n        {\n            if (NO_ERROR != ::K7BaseDetourDetach(\n                &g_FunctionTable[i].Original,\n                g_FunctionTable[i].Detoured))\n            {\n                ::K7BaseDetourTransactionAbort();\n                return MO_RESULT_ERROR_FAIL;\n            }\n        }\n    }\n    ::K7BaseDetourTransactionCommit();\n\n    ::UninitializeFunctionTable();\n\n    return MO_RESULT_SUCCESS_OK;\n}\n"
  },
  {
    "path": "K7User/K7UserModern.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform User Library (K7User)\n * FILE:       K7UserModern.cpp\n * PURPOSE:    Implementation for NanaZip Platform User Modern Experiences\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n *             reflectronic (john-tur@outlook.com)\n */\n\n#include \"K7UserPrivate.h\"\n\n#include <Mile.Helpers.CppBase.h>\n\n#include <CommCtrl.h>\n#pragma comment(lib,\"comctl32.lib\")\n\n#include <appmodel.h>\n\n#include <string>\n\nnamespace\n{\n    int WINAPI OriginalMessageBoxW(\n        _In_opt_ HWND hWnd,\n        _In_opt_ LPCWSTR lpText,\n        _In_opt_ LPCWSTR lpCaption,\n        _In_ UINT uType)\n    {\n        static decltype(::MessageBoxW)* ProcAddress =\n            reinterpret_cast<decltype(::MessageBoxW)*>(::GetProcAddress(\n                ::GetModuleHandleW(L\"user32.dll\"),\n                \"MessageBoxW\"));\n        if (ProcAddress)\n        {\n            return ProcAddress(hWnd, lpText, lpCaption, uType);\n        }\n        else\n        {\n            ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\n            return 0;\n        }\n    }\n}\n\nEXTERN_C int WINAPI K7UserModernMessageBoxW(\n    _In_opt_ HWND hWnd,\n    _In_opt_ LPCWSTR lpText,\n    _In_opt_ LPCWSTR lpCaption,\n    _In_ UINT uType)\n{\n    if (uType != (uType & (MB_ICONMASK | MB_TYPEMASK)))\n    {\n        return ::OriginalMessageBoxW(hWnd, lpText, lpCaption, uType);\n    }\n\n    TASKDIALOGCONFIG TaskDialogConfig = {};\n\n    TaskDialogConfig.cbSize = sizeof(TASKDIALOGCONFIG);\n    TaskDialogConfig.hwndParent = hWnd;\n    TaskDialogConfig.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION;\n    TaskDialogConfig.pszWindowTitle = lpCaption;\n    TaskDialogConfig.pszMainInstruction = lpText;\n\n    switch (uType & MB_TYPEMASK)\n    {\n    case MB_OK:\n        TaskDialogConfig.dwCommonButtons =\n            TDCBF_OK_BUTTON;\n        break;\n    case MB_OKCANCEL:\n        TaskDialogConfig.dwCommonButtons =\n            TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON;\n        break;\n    case MB_YESNOCANCEL:\n        TaskDialogConfig.dwCommonButtons =\n            TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON;\n        break;\n    case MB_YESNO:\n        TaskDialogConfig.dwCommonButtons =\n            TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;\n        break;\n    case MB_RETRYCANCEL:\n        TaskDialogConfig.dwCommonButtons =\n            TDCBF_RETRY_BUTTON | TDCBF_CANCEL_BUTTON;\n        break;\n    default:\n        return ::OriginalMessageBoxW(hWnd, lpText, lpCaption, uType);\n    }\n\n    switch (uType & MB_ICONMASK)\n    {\n    case MB_ICONHAND:\n        TaskDialogConfig.pszMainIcon = TD_ERROR_ICON;\n        break;\n    case MB_ICONQUESTION:\n        TaskDialogConfig.dwFlags |= TDF_USE_HICON_MAIN;\n        TaskDialogConfig.hMainIcon = ::LoadIconW(nullptr, IDI_QUESTION);\n        break;\n    case MB_ICONEXCLAMATION:\n        TaskDialogConfig.pszMainIcon = TD_WARNING_ICON;\n        break;\n    case MB_ICONASTERISK:\n        TaskDialogConfig.pszMainIcon = TD_INFORMATION_ICON;\n        break;\n    default:\n        break;\n    }\n\n    int ButtonID = 0;\n\n    HRESULT hr = ::TaskDialogIndirect(\n        &TaskDialogConfig,\n        &ButtonID,\n        nullptr,\n        nullptr);\n\n    if (0 == ButtonID)\n    {\n        // According to the documentation of TaskDialogIndirect, if the function\n        // fails, the value pointed to by pnButton will be set to zero. To\n        // follow the ABI of MessageBoxW, we will return zero in this case and\n        // set TaskDialogIndirect's HRESULT code to the last error code.\n        ::SetLastError(hr);\n    }\n\n    return ButtonID;\n}\n\nEXTERN_C PIDLIST_ABSOLUTE WINAPI K7UserModernSHBrowseForFolderW(\n    _In_ LPBROWSEINFOW lpbi)\n{\n    LPITEMIDLIST IDList = nullptr;\n\n    IFileDialog* FileDialog = nullptr;\n    if (SUCCEEDED(::CoCreateInstance(\n        CLSID_FileOpenDialog,\n        nullptr,\n        CLSCTX_INPROC_SERVER,\n        IID_PPV_ARGS(&FileDialog))))\n    {\n        DWORD Flags = 0;\n        if (SUCCEEDED(FileDialog->GetOptions(\n            &Flags)))\n        {\n            if (SUCCEEDED(FileDialog->SetOptions(\n                Flags | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM)))\n            {\n                if (SUCCEEDED(FileDialog->SetTitle(\n                    lpbi->lpszTitle)))\n                {\n                    // 7-Zip does not use the pidlRoot parameter to configure\n                    // the default folder. Instead, it sets it by configuring\n                    // the message loop for the shell dialog, passing the path\n                    // of the default folder through the lParam, and navigating\n                    // to that folder inside the message loop.\n                    //\n                    // Since we cannot augment the IFileDialog's message loop,\n                    // we will reach into the lParam given to us to find the\n                    // initial path and hope that 7-Zip does not change this\n                    // behavior.\n\n                    IShellItem* DefaultFolder = nullptr;\n                    if (SUCCEEDED(::SHCreateItemFromParsingName(\n                        reinterpret_cast<PCWSTR>(lpbi->lParam),\n                        nullptr,\n                        IID_PPV_ARGS(&DefaultFolder))))\n                    {\n                        FileDialog->SetFolder(DefaultFolder);\n                        DefaultFolder->Release();\n                    }\n\n                    if (SUCCEEDED(FileDialog->Show(\n                        lpbi->hwndOwner)))\n                    {\n                        IShellItem* Result = nullptr;\n                        if (SUCCEEDED(FileDialog->GetResult(\n                            &Result)))\n                        {\n                            ::SHGetIDListFromObject(Result, &IDList);\n\n                            Result->Release();\n                        }\n                    }\n                }\n            }\n        }\n\n        FileDialog->Release();\n    }\n\n    return IDList;\n}\n\nnamespace\n{\n    static LONG GetCurrentApplicationUserModelIdWrapper(\n        _Inout_ PUINT32 applicationUserModelIdLength,\n        _Out_opt_ PWSTR applicationUserModelId)\n    {\n        using ProcType = decltype(::GetCurrentApplicationUserModelId)*;\n\n        static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n        {\n            HMODULE ModuleHandle = ::GetModuleHandleW(L\"kernel32.dll\");\n            if (ModuleHandle)\n            {\n                return ::GetProcAddress(\n                    ModuleHandle,\n                    \"GetCurrentApplicationUserModelId\");\n            }\n            return nullptr;\n        }());\n\n        if (ProcAddress)\n        {\n            return ProcAddress(\n                applicationUserModelIdLength,\n                applicationUserModelId);\n        }\n\n        return ERROR_NOINTERFACE;\n    }\n\n    static std::wstring GetCurrentApplicationUserModelIdSimple()\n    {\n        static std::wstring CachedResult = ([]() -> std::wstring\n        {\n            std::wstring ApplicationUserModelId;\n            {\n                UINT32 ApplicationUserModelIdLength = 0;\n                LONG Result = ::GetCurrentApplicationUserModelIdWrapper(\n                    &ApplicationUserModelIdLength,\n                    nullptr);\n                if (ERROR_INSUFFICIENT_BUFFER == Result)\n                {\n                    ApplicationUserModelId.resize(ApplicationUserModelIdLength);\n                    Result = ::GetCurrentApplicationUserModelIdWrapper(\n                        &ApplicationUserModelIdLength,\n                        reinterpret_cast<PWSTR>(ApplicationUserModelId.data()));\n                    if (ERROR_SUCCESS == Result)\n                    {\n                        // Remove the trailing null character added by the API.\n                        if (!ApplicationUserModelId.empty() &&\n                            L'\\0' == ApplicationUserModelId.back())\n                        {\n                            ApplicationUserModelId.pop_back();\n                        }\n                    }\n                }\n            }\n            return ApplicationUserModelId;\n        }());\n\n        return CachedResult;\n    }\n}\n\nEXTERN_C MO_RESULT MOAPI K7UserModernLaunchDefaultAppsSettings()\n{\n    std::wstring NavigateUri = L\"ms-settings:defaultapps\";\n    std::wstring CurrentApplicationUserModelId =\n        ::GetCurrentApplicationUserModelIdSimple();\n    if (!CurrentApplicationUserModelId.empty())\n    {\n        NavigateUri.append(L\"?registeredAUMID=\");\n        NavigateUri.append(CurrentApplicationUserModelId);\n    }\n    SHELLEXECUTEINFOW Information = {};\n    Information.cbSize = sizeof(SHELLEXECUTEINFOW);\n    Information.lpVerb = L\"open\";\n    Information.lpFile = NavigateUri.c_str();\n    Information.nShow = SW_SHOWNORMAL;\n    return ::ShellExecuteExW(&Information)\n        ? MO_RESULT_SUCCESS_OK\n        : MO_RESULT_ERROR_FAIL;\n}\n\nEXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundWindow(\n    _In_ HWND WindowHandle)\n{\n    DWORD ForegroundThreadId = ::GetWindowThreadProcessId(\n        ::GetForegroundWindow(),\n        nullptr);\n    DWORD CurrentThreadId = ::GetCurrentThreadId();\n    ::AttachThreadInput(ForegroundThreadId, CurrentThreadId, TRUE);\n    ::SetWindowPos(\n        WindowHandle,\n        HWND_TOPMOST,\n        0,\n        0,\n        0,\n        0,\n        SWP_NOSIZE | SWP_NOMOVE);\n    ::SetWindowPos(\n        WindowHandle,\n        HWND_NOTOPMOST,\n        0,\n        0,\n        0,\n        0,\n        SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE);\n    ::SetForegroundWindow(WindowHandle);\n    ::SetFocus(WindowHandle);\n    ::SetActiveWindow(WindowHandle);\n    ::AttachThreadInput(ForegroundThreadId, CurrentThreadId, FALSE);\n    return MO_RESULT_SUCCESS_OK;\n}\n\nEXTERN_C MO_RESULT MOAPI K7UserModernSetForegroundProcessMainWindow(\n    _In_ HANDLE ProcessHandle)\n{\n    DWORD ProcessId = ::GetProcessId(ProcessHandle);\n    ::AllowSetForegroundWindow(ProcessId);\n    ::WaitForInputIdle(ProcessHandle, 500);\n    ::EnumWindows(\n        [](\n            _In_ HWND hWnd,\n            _In_ LPARAM lParam) -> BOOL\n    {\n        DWORD ProcessId = 0;\n        ::GetWindowThreadProcessId(hWnd, &ProcessId);\n\n        if (!lParam || ProcessId == (DWORD)lParam)\n        {\n            ::K7UserModernSetForegroundWindow(hWnd);\n            return FALSE;\n        }\n\n        return TRUE;\n    },\n        static_cast<LPARAM>(ProcessId));\n\n    return MO_RESULT_SUCCESS_OK;\n}\n"
  },
  {
    "path": "K7User/K7UserPrivate.h",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform User Library (K7User)\n * FILE:       K7UserPrivate.h\n * PURPOSE:    Definition for NanaZip Platform User Private Interfaces\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef K7_USER_PRIVATE\n#define K7_USER_PRIVATE\n\n#include \"K7User.h\"\n\n#ifndef K7_USER_WIN_USER_PRIVATE\n#define K7_USER_WIN_USER_PRIVATE\n\n// Reference: https://github.com/adzm/win32-custom-menubar-aero-theme\n\n// window messages related to menu bar drawing\n#define WM_UAHDESTROYWINDOW 0x0090 // handled by DefWindowProc\n#define WM_UAHDRAWMENU 0x0091 // lParam is UAHMENU\n#define WM_UAHDRAWMENUITEM 0x0092 // lParam is UAHDRAWMENUITEM\n#define WM_UAHINITMENU 0x0093 // handled by DefWindowProc\n#define WM_UAHMEASUREMENUITEM 0x0094 // lParam is UAHMEASUREMENUITEM\n#define WM_UAHNCPAINTMENUPOPUP 0x0095 // handled by DefWindowProc\n\n// describes the sizes of the menu bar or menu item\ntypedef union tagUAHMENUITEMMETRICS\n{\n    // cx appears to be 14 / 0xE less than rcItem's width!\n    // cy 0x14 seems stable, i wonder if it is 4 less than rcItem's height which\n    //    is always 24 atm\n    struct {\n        DWORD cx;\n        DWORD cy;\n    } rgsizeBar[2];\n    struct {\n        DWORD cx;\n        DWORD cy;\n    } rgsizePopup[4];\n} UAHMENUITEMMETRICS, *PUAHMENUITEMMETRICS;\n\n// not really used in our case but part of the other structures\ntypedef struct tagUAHMENUPOPUPMETRICS\n{\n    DWORD rgcx[4];\n\n    // from kernel symbols, padded to full dword\n    DWORD fUpdateMaxWidths : 2;\n} UAHMENUPOPUPMETRICS, *PUAHMENUPOPUPMETRICS;\n\n// hmenu is the main window menu; hdc is the context to draw in\ntypedef struct tagUAHMENU\n{\n    HMENU hmenu;\n    HDC hdc;\n    // no idea what these mean, in my testing it's either 0x00000a00 or\n    // sometimes 0x00000a10\n    DWORD dwFlags;\n} UAHMENU, *PUAHMENU;\n\n// menu items are always referred to by iPosition here\ntypedef struct tagUAHMENUITEM\n{\n    int iPosition; // 0-based position of menu item in menubar\n    UAHMENUITEMMETRICS umim;\n    UAHMENUPOPUPMETRICS umpm;\n} UAHMENUITEM, *PUAHMENUITEM;\n\n// the DRAWITEMSTRUCT contains the states of the menu items, as well as\n// the position index of the item in the menu, which is duplicated in\n// the UAHMENUITEM's iPosition as well\ntypedef struct UAHDRAWMENUITEM\n{\n    DRAWITEMSTRUCT dis; // itemID looks uninitialized\n    UAHMENU um;\n    UAHMENUITEM umi;\n} UAHDRAWMENUITEM, *PUAHDRAWMENUITEM;\n\n// the MEASUREITEMSTRUCT is intended to be filled with the size of the item\n// height appears to be ignored, but width can be modified\ntypedef struct tagUAHMEASUREMENUITEM\n{\n    MEASUREITEMSTRUCT mis;\n    UAHMENU um;\n    UAHMENUITEM umi;\n} UAHMEASUREMENUITEM, *PUAHMEASUREMENUITEM;\n\n#endif // !K7_USER_WIN_USER_PRIVATE\n\n#ifndef K7_USER_DARK_MODE_PRIVATE\n#define K7_USER_DARK_MODE_PRIVATE\n\n/**\n * @brief Uninitializes the dark mode support.\n * @return If the function succeeds, it returns MO_RESULT_SUCCESS_OK. Otherwise,\n *         it returns an MO_RESULT error code.\n */\nEXTERN_C MO_RESULT MOAPI K7UserUninitializeDarkModeSupport();\n\n#endif // !K7_USER_DARK_MODE_PRIVATE\n\n\n#endif // !K7_USER_PRIVATE\n"
  },
  {
    "path": "K7User/K7UserRedirector.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip Platform User Library (K7User)\n * FILE:       K7UserRedirector.cpp\n * PURPOSE:    Implementation for NanaZip Platform User API Redirector\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"K7UserPrivate.h\"\n\n// Here are the linker-time redirections to replace the original APIs.\n// Implementations only for x64 and ARM64, if you want to learn how to achieve\n// that in x86, please refer to NanaZip.Shared.ModernExperienceShims project in\n// the historical NanaZip versions source code.\n\n#ifndef K7_REDIRECT\n#define K7_REDIRECT(Source, Target) \\\n    extern \"C\" __declspec(selectany) void const* const __imp_##Source = \\\n        reinterpret_cast<void const*>(::Target); \\\n    __pragma(comment(linker, \"/include:__imp_\" #Source))\n#endif // !K7_REDIRECT\n\nK7_REDIRECT(MessageBoxW, K7UserModernMessageBoxW);\nK7_REDIRECT(SHBrowseForFolderW, K7UserModernSHBrowseForFolderW);\n"
  },
  {
    "path": "K7User/K7UserStatic.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaZip Platform User Library (K7User)\n  FILE:       K7UserStatic.props\n  PURPOSE:    MSBuild Properties for referencing the K7User static library\n\n  LICENSE:    The MIT License\n\n  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n-->\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <Link>\n      <AdditionalDependencies>$(OutDir)K7UserStatic.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <Target Name=\"K7UserBuildSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(K7UserDisableRedirector)' != 'true'\">\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)K7UserRedirector.cpp\" />\n    </ItemGroup>\n  </Target>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Mobility\">\n      <Version>1.0.372</Version>\n    </PackageReference>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)K7UserStatic.vcxproj\">\n      <Project>{0B7D00BE-6890-453E-86A4-DEF68B5C22A4}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "K7User/K7UserStatic.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{0B7D00BE-6890-453E-86A4-DEF68B5C22A4}</ProjectGuid>\n    <RootNamespace>K7UserStatic</RootNamespace>\n    <MileProjectType>StaticLibrary</MileProjectType>\n    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>\n  </PropertyGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.ARM64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory)..\\K7Base\\;$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Mobility\">\n      <Version>1.0.372</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.Internal\">\n      <Version>1.0.3550</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.Helpers\">\n      <Version>1.0.1171</Version>\n    </PackageReference>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"K7UserStatic.props\" />\n    <None Include=\"K7UserRedirector.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"K7User.h\" />\n    <ClInclude Include=\"K7UserPrivate.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"K7UserDarkMode.cpp\" />\n    <ClCompile Include=\"K7UserModern.cpp\" />\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "K7User/ReadMe.md",
    "content": "﻿# NanaZip Platform User Library (K7User)\n\n***Work In Progress***\n\nThe static and dynamic library that encapsulates the GUI portion of the base\nplatform infrastructure for the NanaZip. It's one of the foundational libraries\nof the NanaZip Platform Abstraction Layer.\n\nK7 is the alias of NanaZip. Here is the relationship between K7 and NanaZip: I\nhad mentioned one of the reasons that I call this project NanaZip because Nana\nis the romaji of なな which means seven in Japanese. But I had not mentioned the\nway I confirm that: I had recalled one of the Japanese VTubers called Kagura\nNana when I waiting my elder sister for dinner at Taiyanggong subway station,\nBeijing. For playing more puns, NanaZip uses the K7 (K -> Kagura, 7 -> Nana) as\nthe alias.\n\nK7User is designed for Windows only, although the most of the K7User interfaces\nare designed to be platform-independent. Maybe in the future, the K7User will\nhave the implementations for Linux and FreeBSD, although the implementation may\nnot in this repository.\n\n## Features\n\n- Dark Mode Support\n- Modern Experiences Support (GUI)\n"
  },
  {
    "path": "License.md",
    "content": "﻿# NanaZip License\n\nFor giving the maximum respect for the upstream projects and following the \nphilosophy about open-source software from Kenji Mouri (MouriNaruto), the one\nof the M2-Team founders. \n\nThe source code of NanaZip (not including the source code from third-party \nlibraries, 7-Zip or other 7-Zip derivatives) is distributed under the MIT \nLicense.\n\nThe application file association icons of NanaZip (these contents are only in \nthe `Assets` folder) are designed by Shomnipotence and authorized to the \nNanaZip project, and it is distributed under the CC BY-ND 4.0 License.\n\nThe source code from 7-Zip or other 7-Zip derivatives (these contents are only \nin the `NanaZip.Core\\SevenZip`, `NanaZip.Core\\Extensions\\ZSCodecs`,\n`NanaZip.Universal\\SevenZip`, `NanaZip.UI.Classic\\SevenZip` and\n`NanaZip.UI.Modern\\SevenZip` folders) is distributed under the 7-Zip License.\n\nThe source code from the third-party libraries is distributed under the original\nlicense used in the third-party libraries.\n\nThis permission notice shall be included in all copies or substantial portions\nof the Software.\n\n### The philosophy about open-source software from Kenji Mouri (MouriNaruto)\n\n- The source code from the third-party projects should be distributed under \n  their original licenses to give the maximum respect for the upstream \n  projects.\n\n- Don't make your software open source if you don't want your source code or\n  ideas used in proprietary software. Because they always have the way to cross\n  restrictions if they really want to do, even you distributed your source code\n  under the strictest copyleft license, they can use clean room to resolve it.\n\n- I prefer permissive licenses because using copyleft licenses will make you\n  feel anxious in most cases because you always need to worry about someone\n  using your source code in proprietary software. So, I choose to give the\n  maximum respect to users, and I also hope people can try their best to treat\n  others kindly.\n\n### The MIT License\n\n```\nThe MIT License (MIT)\n\nCopyright (c) M2-Team and Contributors. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n\n### The 7-Zip License\n\n```\n  7-Zip\n  ~~~~~\n  License for use and distribution\n  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n  7-Zip Copyright (C) 1999-2021 Igor Pavlov.\n\n  The licenses for files are:\n\n    1) 7z.dll:\n         - The \"GNU LGPL\" as main license for most of the code\n         - The \"GNU LGPL\" with \"unRAR license restriction\" for some code\n         - The \"BSD 3-clause License\" for some code\n    2) All other files: the \"GNU LGPL\".\n\n  Redistributions in binary form must reproduce related license information \n  from this file.\n\n  Note:\n    You can use 7-Zip on any computer, including a computer in a commercial\n    organization. You don't need to register or pay for 7-Zip.\n\n\n  GNU LGPL information\n  --------------------\n\n    This library is free software; you can redistribute it and/or\n    modify it under the terms of the GNU Lesser General Public\n    License as published by the Free Software Foundation; either\n    version 2.1 of the License, or (at your option) any later version.\n\n    This library is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n    Lesser General Public License for more details.\n\n    You can receive a copy of the GNU Lesser General Public License from\n    http://www.gnu.org/\n\n\n  BSD 3-clause License\n  --------------------\n\n    The \"BSD 3-clause License\" is used for the code in 7z.dll that implements\n    LZFSE data decompression. That code was derived from the code in the \"LZFSE\n    compression library\" developed by Apple Inc, that also uses the \"BSD \n    3-clause License\":\n\n    ----\n    Copyright (c) 2015-2016, Apple Inc. All rights reserved.\n\n    Redistribution and use in source and binary forms, with or without \n    modification, are permitted provided that the following conditions are met:\n\n    1.  Redistributions of source code must retain the above copyright notice, \n        this list of conditions and the following disclaimer.\n\n    2.  Redistributions in binary form must reproduce the above copyright \n        notice, this list of conditions and the following disclaimer in the\n        documentation and/or other materials provided with the distribution.\n\n    3.  Neither the name of the copyright holder(s) nor the names of any \n        contributors may be used to endorse or promote products derived from \n        this software without specific prior written permission.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE \n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR \n    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF \n    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN \n    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF \n    THE POSSIBILITY OF SUCH DAMAGE.\n    ----\n\n\n  unRAR license restriction\n  -------------------------\n\n    The decompression engine for RAR archives was developed using source\n    code of unRAR program.\n    All copyrights to original unRAR code are owned by Alexander Roshal.\n\n    The license for original unRAR code has the following restriction:\n\n      The unRAR sources cannot be used to re-create the RAR compression \n      algorithm, which is proprietary. Distribution of modified unRAR sources\n      in separate form or as a part of other software is permitted, provided\n      that it is clearly stated in the documentation and source comments that\n      the code may not be used to develop a RAR (WinRAR) compatible archiver.\n\n\n  --\n  Igor Pavlov\n```\n\n### The CC BY-ND 4.0 License\n\n```\nCopyright (c) Shomnipotence and M2-Team. All rights reserved.\n\nThis work is licensed under a Creative Commons Attribution-NoDerivatives 4.0\nInternational License.\n\nAttribution-NoDerivatives 4.0 International\n\n=======================================================================\n\nCreative Commons Corporation (\"Creative Commons\") is not a law firm and\ndoes not provide legal services or legal advice. Distribution of\nCreative Commons public licenses does not create a lawyer-client or\nother relationship. Creative Commons makes its licenses and related\ninformation available on an \"as-is\" basis. Creative Commons gives no\nwarranties regarding its licenses, any material licensed under their\nterms and conditions, or any related information. Creative Commons\ndisclaims all liability for damages resulting from their use to the\nfullest extent possible.\n\nUsing Creative Commons Public Licenses\n\nCreative Commons public licenses provide a standard set of terms and\nconditions that creators and other rights holders may use to share\noriginal works of authorship and other material subject to copyright\nand certain other rights specified in the public license below. The\nfollowing considerations are for informational purposes only, are not\nexhaustive, and do not form part of our licenses.\n\n     Considerations for licensors: Our public licenses are\n     intended for use by those authorized to give the public\n     permission to use material in ways otherwise restricted by\n     copyright and certain other rights. Our licenses are\n     irrevocable. Licensors should read and understand the terms\n     and conditions of the license they choose before applying it.\n     Licensors should also secure all rights necessary before\n     applying our licenses so that the public can reuse the\n     material as expected. Licensors should clearly mark any\n     material not subject to the license. This includes other CC-\n     licensed material, or material used under an exception or\n     limitation to copyright. More considerations for licensors:\n    wiki.creativecommons.org/Considerations_for_licensors\n\n     Considerations for the public: By using one of our public\n     licenses, a licensor grants the public permission to use the\n     licensed material under specified terms and conditions. If\n     the licensor's permission is not necessary for any reason--for\n     example, because of any applicable exception or limitation to\n     copyright--then that use is not regulated by the license. Our\n     licenses grant only permissions under copyright and certain\n     other rights that a licensor has authority to grant. Use of\n     the licensed material may still be restricted for other\n     reasons, including because others have copyright or other\n     rights in the material. A licensor may make special requests,\n     such as asking that all changes be marked or described.\n     Although not required by our licenses, you are encouraged to\n     respect those requests where reasonable. More considerations\n     for the public:\n    wiki.creativecommons.org/Considerations_for_licensees\n\n\n=======================================================================\n\nCreative Commons Attribution-NoDerivatives 4.0 International Public\nLicense\n\nBy exercising the Licensed Rights (defined below), You accept and agree\nto be bound by the terms and conditions of this Creative Commons\nAttribution-NoDerivatives 4.0 International Public License (\"Public\nLicense\"). To the extent this Public License may be interpreted as a\ncontract, You are granted the Licensed Rights in consideration of Your\nacceptance of these terms and conditions, and the Licensor grants You\nsuch rights in consideration of benefits the Licensor receives from\nmaking the Licensed Material available under these terms and\nconditions.\n\n\nSection 1 -- Definitions.\n\n  a. Adapted Material means material subject to Copyright and Similar\n     Rights that is derived from or based upon the Licensed Material\n     and in which the Licensed Material is translated, altered,\n     arranged, transformed, or otherwise modified in a manner requiring\n     permission under the Copyright and Similar Rights held by the\n     Licensor. For purposes of this Public License, where the Licensed\n     Material is a musical work, performance, or sound recording,\n     Adapted Material is always produced where the Licensed Material is\n     synched in timed relation with a moving image.\n\n  b. Copyright and Similar Rights means copyright and/or similar rights\n     closely related to copyright including, without limitation,\n     performance, broadcast, sound recording, and Sui Generis Database\n     Rights, without regard to how the rights are labeled or\n     categorized. For purposes of this Public License, the rights\n     specified in Section 2(b)(1)-(2) are not Copyright and Similar\n     Rights.\n\n  c. Effective Technological Measures means those measures that, in the\n     absence of proper authority, may not be circumvented under laws\n     fulfilling obligations under Article 11 of the WIPO Copyright\n     Treaty adopted on December 20, 1996, and/or similar international\n     agreements.\n\n  d. Exceptions and Limitations means fair use, fair dealing, and/or\n     any other exception or limitation to Copyright and Similar Rights\n     that applies to Your use of the Licensed Material.\n\n  e. Licensed Material means the artistic or literary work, database,\n     or other material to which the Licensor applied this Public\n     License.\n\n  f. Licensed Rights means the rights granted to You subject to the\n     terms and conditions of this Public License, which are limited to\n     all Copyright and Similar Rights that apply to Your use of the\n     Licensed Material and that the Licensor has authority to license.\n\n  g. Licensor means the individual(s) or entity(ies) granting rights\n     under this Public License.\n\n  h. Share means to provide material to the public by any means or\n     process that requires permission under the Licensed Rights, such\n     as reproduction, public display, public performance, distribution,\n     dissemination, communication, or importation, and to make material\n     available to the public including in ways that members of the\n     public may access the material from a place and at a time\n     individually chosen by them.\n\n  i. Sui Generis Database Rights means rights other than copyright\n     resulting from Directive 96/9/EC of the European Parliament and of\n     the Council of 11 March 1996 on the legal protection of databases,\n     as amended and/or succeeded, as well as other essentially\n     equivalent rights anywhere in the world.\n\n  j. You means the individual or entity exercising the Licensed Rights\n     under this Public License. Your has a corresponding meaning.\n\n\nSection 2 -- Scope.\n\n  a. License grant.\n\n       1. Subject to the terms and conditions of this Public License,\n          the Licensor hereby grants You a worldwide, royalty-free,\n          non-sublicensable, non-exclusive, irrevocable license to\n          exercise the Licensed Rights in the Licensed Material to:\n\n            a. reproduce and Share the Licensed Material, in whole or\n               in part; and\n\n            b. produce and reproduce, but not Share, Adapted Material.\n\n       2. Exceptions and Limitations. For the avoidance of doubt, where\n          Exceptions and Limitations apply to Your use, this Public\n          License does not apply, and You do not need to comply with\n          its terms and conditions.\n\n       3. Term. The term of this Public License is specified in Section\n          6(a).\n\n       4. Media and formats; technical modifications allowed. The\n          Licensor authorizes You to exercise the Licensed Rights in\n          all media and formats whether now known or hereafter created,\n          and to make technical modifications necessary to do so. The\n          Licensor waives and/or agrees not to assert any right or\n          authority to forbid You from making technical modifications\n          necessary to exercise the Licensed Rights, including\n          technical modifications necessary to circumvent Effective\n          Technological Measures. For purposes of this Public License,\n          simply making modifications authorized by this Section 2(a)\n          (4) never produces Adapted Material.\n\n       5. Downstream recipients.\n\n            a. Offer from the Licensor -- Licensed Material. Every\n               recipient of the Licensed Material automatically\n               receives an offer from the Licensor to exercise the\n               Licensed Rights under the terms and conditions of this\n               Public License.\n\n            b. No downstream restrictions. You may not offer or impose\n               any additional or different terms or conditions on, or\n               apply any Effective Technological Measures to, the\n               Licensed Material if doing so restricts exercise of the\n               Licensed Rights by any recipient of the Licensed\n               Material.\n\n       6. No endorsement. Nothing in this Public License constitutes or\n          may be construed as permission to assert or imply that You\n          are, or that Your use of the Licensed Material is, connected\n          with, or sponsored, endorsed, or granted official status by,\n          the Licensor or others designated to receive attribution as\n          provided in Section 3(a)(1)(A)(i).\n\n  b. Other rights.\n\n       1. Moral rights, such as the right of integrity, are not\n          licensed under this Public License, nor are publicity,\n          privacy, and/or other similar personality rights; however, to\n          the extent possible, the Licensor waives and/or agrees not to\n          assert any such rights held by the Licensor to the limited\n          extent necessary to allow You to exercise the Licensed\n          Rights, but not otherwise.\n\n       2. Patent and trademark rights are not licensed under this\n          Public License.\n\n       3. To the extent possible, the Licensor waives any right to\n          collect royalties from You for the exercise of the Licensed\n          Rights, whether directly or through a collecting society\n          under any voluntary or waivable statutory or compulsory\n          licensing scheme. In all other cases the Licensor expressly\n          reserves any right to collect such royalties.\n\n\nSection 3 -- License Conditions.\n\nYour exercise of the Licensed Rights is expressly made subject to the\nfollowing conditions.\n\n  a. Attribution.\n\n       1. If You Share the Licensed Material, You must:\n\n            a. retain the following if it is supplied by the Licensor\n               with the Licensed Material:\n\n                 i. identification of the creator(s) of the Licensed\n                    Material and any others designated to receive\n                    attribution, in any reasonable manner requested by\n                    the Licensor (including by pseudonym if\n                    designated);\n\n                ii. a copyright notice;\n\n               iii. a notice that refers to this Public License;\n\n                iv. a notice that refers to the disclaimer of\n                    warranties;\n\n                 v. a URI or hyperlink to the Licensed Material to the\n                    extent reasonably practicable;\n\n            b. indicate if You modified the Licensed Material and\n               retain an indication of any previous modifications; and\n\n            c. indicate the Licensed Material is licensed under this\n               Public License, and include the text of, or the URI or\n               hyperlink to, this Public License.\n\n          For the avoidance of doubt, You do not have permission under\n          this Public License to Share Adapted Material.\n\n       2. You may satisfy the conditions in Section 3(a)(1) in any\n          reasonable manner based on the medium, means, and context in\n          which You Share the Licensed Material. For example, it may be\n          reasonable to satisfy the conditions by providing a URI or\n          hyperlink to a resource that includes the required\n          information.\n\n       3. If requested by the Licensor, You must remove any of the\n          information required by Section 3(a)(1)(A) to the extent\n          reasonably practicable.\n\n\nSection 4 -- Sui Generis Database Rights.\n\nWhere the Licensed Rights include Sui Generis Database Rights that\napply to Your use of the Licensed Material:\n\n  a. for the avoidance of doubt, Section 2(a)(1) grants You the right\n     to extract, reuse, reproduce, and Share all or a substantial\n     portion of the contents of the database, provided You do not Share\n     Adapted Material;\n  b. if You include all or a substantial portion of the database\n     contents in a database in which You have Sui Generis Database\n     Rights, then the database in which You have Sui Generis Database\n     Rights (but not its individual contents) is Adapted Material; and\n  c. You must comply with the conditions in Section 3(a) if You Share\n     all or a substantial portion of the contents of the database.\n\nFor the avoidance of doubt, this Section 4 supplements and does not\nreplace Your obligations under this Public License where the Licensed\nRights include other Copyright and Similar Rights.\n\n\nSection 5 -- Disclaimer of Warranties and Limitation of Liability.\n\n  a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE\n     EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS\n     AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF\n     ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,\n     IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,\n     WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR\n     PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,\n     ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT\n     KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT\n     ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.\n\n  b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE\n     TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,\n     NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,\n     INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,\n     COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR\n     USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN\n     ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR\n     DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR\n     IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.\n\n  c. The disclaimer of warranties and limitation of liability provided\n     above shall be interpreted in a manner that, to the extent\n     possible, most closely approximates an absolute disclaimer and\n     waiver of all liability.\n\n\nSection 6 -- Term and Termination.\n\n  a. This Public License applies for the term of the Copyright and\n     Similar Rights licensed here. However, if You fail to comply with\n     this Public License, then Your rights under this Public License\n     terminate automatically.\n\n  b. Where Your right to use the Licensed Material has terminated under\n     Section 6(a), it reinstates:\n\n       1. automatically as of the date the violation is cured, provided\n          it is cured within 30 days of Your discovery of the\n          violation; or\n\n       2. upon express reinstatement by the Licensor.\n\n     For the avoidance of doubt, this Section 6(b) does not affect any\n     right the Licensor may have to seek remedies for Your violations\n     of this Public License.\n\n  c. For the avoidance of doubt, the Licensor may also offer the\n     Licensed Material under separate terms or conditions or stop\n     distributing the Licensed Material at any time; however, doing so\n     will not terminate this Public License.\n\n  d. Sections 1, 5, 6, 7, and 8 survive termination of this Public\n     License.\n\n\nSection 7 -- Other Terms and Conditions.\n\n  a. The Licensor shall not be bound by any additional or different\n     terms or conditions communicated by You unless expressly agreed.\n\n  b. Any arrangements, understandings, or agreements regarding the\n     Licensed Material not stated herein are separate from and\n     independent of the terms and conditions of this Public License.\n\n\nSection 8 -- Interpretation.\n\n  a. For the avoidance of doubt, this Public License does not, and\n     shall not be interpreted to, reduce, limit, restrict, or impose\n     conditions on any use of the Licensed Material that could lawfully\n     be made without permission under this Public License.\n\n  b. To the extent possible, if any provision of this Public License is\n     deemed unenforceable, it shall be automatically reformed to the\n     minimum extent necessary to make it enforceable. If the provision\n     cannot be reformed, it shall be severed from this Public License\n     without affecting the enforceability of the remaining terms and\n     conditions.\n\n  c. No term or condition of this Public License will be waived and no\n     failure to comply consented to unless expressly agreed to by the\n     Licensor.\n\n  d. Nothing in this Public License constitutes or may be interpreted\n     as a limitation upon, or waiver of, any privileges and immunities\n     that apply to the Licensor or You, including from the legal\n     processes of any jurisdiction or authority.\n\n=======================================================================\n\nCreative Commons is not a party to its public\nlicenses. Notwithstanding, Creative Commons may elect to apply one of\nits public licenses to material it publishes and in those instances\nwill be considered the “Licensor.” The text of the Creative Commons\npublic licenses is dedicated to the public domain under the CC0 Public\nDomain Dedication. Except for the limited purpose of indicating that\nmaterial is shared under a Creative Commons public license or as\notherwise permitted by the Creative Commons policies published at\ncreativecommons.org/policies, Creative Commons does not authorize the\nuse of the trademark \"Creative Commons\" or any other trademark or logo\nof Creative Commons without its prior written consent including,\nwithout limitation, in connection with any unauthorized modifications\nto any of its public licenses or any other arrangements,\nunderstandings, or agreements concerning use of licensed material. For\nthe avoidance of doubt, this paragraph does not form part of the\npublic licenses.\n\nCreative Commons may be contacted at creativecommons.org.\n```\n\n### The 7-Zip branches used in NanaZip\n\n- https://www.7-zip.org/\n- https://github.com/myfreeer/7z-build-nsis\n- https://github.com/mcmilk/7-Zip-zstd\n\n### The third-party libraries used in NanaZip\n\n- BLAKE3, https://github.com/BLAKE3-team/BLAKE3\n- Brotli, https://github.com/google/brotli\n- C++/WinRT, https://github.com/microsoft/cppwinrt\n- Fast LZMA2, https://github.com/conor42/fast-lzma2\n- FreeBSD, https://github.com/freebsd/freebsd-src\n- GmSSL, https://github.com/guanzhi/GmSSL\n- littlefs, https://github.com/littlefs-project/littlefs\n- Lizard, https://github.com/inikep/lizard\n- LZ4, https://github.com/lz4/lz4\n- LZ5, https://github.com/inikep/lizard\n- LZMA SDK, https://www.7-zip.org/sdk.html\n- Mile.Detours, https://github.com/ProjectMile/Mile.Detours\n- Mile.Json, https://github.com/ProjectMile/Mile.Json\n- Mile.Mobility, https://github.com/ProjectMile/Mile.Mobility\n- Mile.Project.Configurations, https://github.com/ProjectMile/Mile.Project.Configurations\n- Mile.Windows.Helpers, https://github.com/ProjectMile/Mile.Windows.Helpers\n- Mile.Windows.Internal, https://github.com/ProjectMile/Mile.Windows.Internal\n- Mile.Windows.UniCrt, https://github.com/ProjectMile/Mile.Windows.UniCrt\n- Mile.Xaml, https://github.com/ProjectMile/Mile.Xaml\n- RHash, https://github.com/rhash/RHash\n- Windows-driver-samples, https://github.com/microsoft/Windows-driver-samples\n- xxHash, https://github.com/Cyan4973/xxHash\n- Zstandard, https://github.com/facebook/zstd\n- ZSTDMT, https://github.com/mcmilk/zstdmt\n"
  },
  {
    "path": "NanaZip.Build.Tasks/NanaZip.Build.Tasks.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <LangVersion>default</LangVersion>\n    <Nullable>enable</Nullable>\n    <Authors>M2-Team</Authors>\n    <Copyright>© M2-Team and Contributors. All rights reserved.</Copyright>\n    <Version>$(MileProjectVersion)</Version>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Build.Framework\" Version=\"18.0.2\" />\n    <PackageReference Include=\"Microsoft.Build.Utilities.Core\" Version=\"18.0.2\" />\n    <PackageReference Include=\"Mile.Project.Helpers\" Version=\"1.0.975\" />\n  </ItemGroup>\n\n  <Target Name=\"NanaZipBuildTasksAfterBuild\" AfterTargets=\"Build\">\n    <MSBuild Projects=\"$(MSBuildProjectFullPath)\" Targets=\"Publish\" />\n    <Copy OverwriteReadOnlyFiles=\"true\" SourceFiles=\"$(PublishDir)Mile.Project.Helpers.dll\" DestinationFolder=\"$(MSBuildThisFileDirectory)..\\NanaZip.Project\\\" />\n    <Copy OverwriteReadOnlyFiles=\"true\" SourceFiles=\"$(PublishDir)NanaZip.Build.Tasks.dll\" DestinationFolder=\"$(MSBuildThisFileDirectory)..\\NanaZip.Project\\\" />\n  </Target>\n\n</Project>\n"
  },
  {
    "path": "NanaZip.Build.Tasks/RefreshAppxManifestVersion.cs",
    "content": "﻿using Microsoft.Build.Framework;\nusing Microsoft.Build.Utilities;\nusing Mile.Project.Helpers;\nusing System.IO;\nusing System.Xml;\n\nnamespace NanaZip.Build.Tasks\n{\n    public class RefreshAppxManifestVersion : Task\n    {\n        [Required]\n        public string? FilePath { get; set; }\n\n        [Required]\n        public string? Version { get; set; }\n\n        public override bool Execute()\n        {\n            XmlDocument Document = new XmlDocument();\n            Document.PreserveWhitespace = true;\n            Document.Load(FilePath);\n\n            XmlNode? PackageNode = Document[\"Package\"];\n            if (PackageNode == null)\n            {\n                Log.LogError(\"Cannot find Package node in the manifest.\");\n                return false;\n            }\n\n            XmlNode? IdentityNode = PackageNode[\"Identity\"];\n            if (IdentityNode == null)\n            {\n                Log.LogError(\"Cannot find Identity node in the manifest.\");\n                return false;\n            }\n\n            XmlAttribute? VersionAttribute = IdentityNode.Attributes[\"Version\"];\n            if (VersionAttribute == null)\n            {\n                Log.LogError(\"Cannot find Version attribute in the manifest.\");\n                return false;\n            }\n\n            FileUtilities.SaveTextToFileAsUtf8Bom(\n               FilePath,\n               File.ReadAllText(FilePath).Replace(\n                   string.Format(\n                       \" {0}=\\\"{1}\\\"\",\n                       VersionAttribute.Name,\n                       VersionAttribute.Value),\n                   string.Format(\n                       \" {0}=\\\"{1}\\\"\",\n                       VersionAttribute.Name,\n                       Version)));\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "NanaZip.Build.Tasks/RefreshProjectBuildNumberDate.cs",
    "content": "﻿using Microsoft.Build.Framework;\nusing Microsoft.Build.Utilities;\nusing Mile.Project.Helpers;\nusing System.IO;\nusing System.Xml;\n\nnamespace NanaZip.Build.Tasks\n{\n    public class RefreshProjectBuildNumberDate : Task\n    {\n        [Required]\n        public string? FilePath { get; set; }\n\n        [Required]\n        public string? BuildNumberDate { get; set; }\n\n        public override bool Execute()\n        {\n            XmlDocument Document = new XmlDocument();\n            Document.PreserveWhitespace = true;\n            Document.Load(FilePath);\n\n            XmlNode? ProjectNode = Document[\"Project\"];\n            if (ProjectNode == null)\n            {\n                Log.LogError(\n                    \"Cannot find Project node in the manifest.\");\n                return false;\n            }\n\n            XmlNode? PropertyGroupNode = ProjectNode[\"PropertyGroup\"];\n            if (PropertyGroupNode == null)\n            {\n                Log.LogError(\n                    \"Cannot find PropertyGroup node in the manifest.\");\n                return false;\n            }\n\n            XmlNode? NanaZipBuildNumberDateNode =\n                PropertyGroupNode[\"NanaZipBuildNumberDate\"];\n            if (NanaZipBuildNumberDateNode == null)\n            {\n                Log.LogError(\n                    \"Cannot find NanaZipBuildNumberDate node in the manifest.\");\n                return false;\n            }\n\n            FileUtilities.SaveTextToFileAsUtf8Bom(\n                FilePath,\n                File.ReadAllText(FilePath).Replace(\n                    string.Format(\n                        \"<{0}>{1}</{0}>\",\n                        NanaZipBuildNumberDateNode.Name,\n                        NanaZipBuildNumberDateNode.InnerText),\n                    string.Format(\n                        \"<{0}>{1}</{0}>\",\n                        NanaZipBuildNumberDateNode.Name,\n                        BuildNumberDate)));\n\n            return true;\n        }\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3.c",
    "content": "﻿#include <assert.h>\n#include <stdbool.h>\n#include <string.h>\n\n#include \"blake3.h\"\n#include \"blake3_impl.h\"\n\nconst char *blake3_version(void) { return BLAKE3_VERSION_STRING; }\n\nINLINE void chunk_state_init(blake3_chunk_state *self, const uint32_t key[8],\n                             uint8_t flags) {\n  memcpy(self->cv, key, BLAKE3_KEY_LEN);\n  self->chunk_counter = 0;\n  memset(self->buf, 0, BLAKE3_BLOCK_LEN);\n  self->buf_len = 0;\n  self->blocks_compressed = 0;\n  self->flags = flags;\n}\n\nINLINE void chunk_state_reset(blake3_chunk_state *self, const uint32_t key[8],\n                              uint64_t chunk_counter) {\n  memcpy(self->cv, key, BLAKE3_KEY_LEN);\n  self->chunk_counter = chunk_counter;\n  self->blocks_compressed = 0;\n  memset(self->buf, 0, BLAKE3_BLOCK_LEN);\n  self->buf_len = 0;\n}\n\nINLINE size_t chunk_state_len(const blake3_chunk_state *self) {\n  return (BLAKE3_BLOCK_LEN * (size_t)self->blocks_compressed) +\n         ((size_t)self->buf_len);\n}\n\nINLINE size_t chunk_state_fill_buf(blake3_chunk_state *self,\n                                   const uint8_t *input, size_t input_len) {\n  size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len);\n  if (take > input_len) {\n    take = input_len;\n  }\n  uint8_t *dest = self->buf + ((size_t)self->buf_len);\n  memcpy(dest, input, take);\n  self->buf_len += (uint8_t)take;\n  return take;\n}\n\nINLINE uint8_t chunk_state_maybe_start_flag(const blake3_chunk_state *self) {\n  if (self->blocks_compressed == 0) {\n    return CHUNK_START;\n  } else {\n    return 0;\n  }\n}\n\ntypedef struct {\n  uint32_t input_cv[8];\n  uint64_t counter;\n  uint8_t block[BLAKE3_BLOCK_LEN];\n  uint8_t block_len;\n  uint8_t flags;\n} output_t;\n\nINLINE output_t make_output(const uint32_t input_cv[8],\n                            const uint8_t block[BLAKE3_BLOCK_LEN],\n                            uint8_t block_len, uint64_t counter,\n                            uint8_t flags) {\n  output_t ret;\n  memcpy(ret.input_cv, input_cv, 32);\n  memcpy(ret.block, block, BLAKE3_BLOCK_LEN);\n  ret.block_len = block_len;\n  ret.counter = counter;\n  ret.flags = flags;\n  return ret;\n}\n\n// Chaining values within a given chunk (specifically the compress_in_place\n// interface) are represented as words. This avoids unnecessary bytes<->words\n// conversion overhead in the portable implementation. However, the hash_many\n// interface handles both user input and parent node blocks, so it accepts\n// bytes. For that reason, chaining values in the CV stack are represented as\n// bytes.\nINLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) {\n  uint32_t cv_words[8];\n  memcpy(cv_words, self->input_cv, 32);\n  blake3_compress_in_place(cv_words, self->block, self->block_len,\n                           self->counter, self->flags);\n  store_cv_words(cv, cv_words);\n}\n\nINLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out,\n                              size_t out_len) {\n  if (out_len == 0) {\n      return;\n  }\n  uint64_t output_block_counter = seek / 64;\n  size_t offset_within_block = seek % 64;\n  uint8_t wide_buf[64];\n  if(offset_within_block) {\n    blake3_compress_xof(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, wide_buf);\n    const size_t available_bytes = 64 - offset_within_block;\n    const size_t bytes = out_len > available_bytes ? available_bytes : out_len;\n    memcpy(out, wide_buf + offset_within_block, bytes);\n    out += bytes;\n    out_len -= bytes;\n    output_block_counter += 1;\n  }\n  if(out_len / 64) {\n    blake3_xof_many(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, out, out_len / 64);\n  }\n  output_block_counter += out_len / 64;\n  out += out_len & -64;\n  out_len -= out_len & -64;\n  if(out_len) {\n    blake3_compress_xof(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, wide_buf);\n    memcpy(out, wide_buf, out_len);\n  }\n}\n\nINLINE void chunk_state_update(blake3_chunk_state *self, const uint8_t *input,\n                               size_t input_len) {\n  if (self->buf_len > 0) {\n    size_t take = chunk_state_fill_buf(self, input, input_len);\n    input += take;\n    input_len -= take;\n    if (input_len > 0) {\n      blake3_compress_in_place(\n          self->cv, self->buf, BLAKE3_BLOCK_LEN, self->chunk_counter,\n          self->flags | chunk_state_maybe_start_flag(self));\n      self->blocks_compressed += 1;\n      self->buf_len = 0;\n      memset(self->buf, 0, BLAKE3_BLOCK_LEN);\n    }\n  }\n\n  while (input_len > BLAKE3_BLOCK_LEN) {\n    blake3_compress_in_place(self->cv, input, BLAKE3_BLOCK_LEN,\n                             self->chunk_counter,\n                             self->flags | chunk_state_maybe_start_flag(self));\n    self->blocks_compressed += 1;\n    input += BLAKE3_BLOCK_LEN;\n    input_len -= BLAKE3_BLOCK_LEN;\n  }\n\n  chunk_state_fill_buf(self, input, input_len);\n}\n\nINLINE output_t chunk_state_output(const blake3_chunk_state *self) {\n  uint8_t block_flags =\n      self->flags | chunk_state_maybe_start_flag(self) | CHUNK_END;\n  return make_output(self->cv, self->buf, self->buf_len, self->chunk_counter,\n                     block_flags);\n}\n\nINLINE output_t parent_output(const uint8_t block[BLAKE3_BLOCK_LEN],\n                              const uint32_t key[8], uint8_t flags) {\n  return make_output(key, block, BLAKE3_BLOCK_LEN, 0, flags | PARENT);\n}\n\n// Given some input larger than one chunk, return the number of bytes that\n// should go in the left subtree. This is the largest power-of-2 number of\n// chunks that leaves at least 1 byte for the right subtree.\nINLINE size_t left_subtree_len(size_t input_len) {\n  // Subtract 1 to reserve at least one byte for the right side. input_len\n  // should always be greater than BLAKE3_CHUNK_LEN.\n  size_t full_chunks = (input_len - 1) / BLAKE3_CHUNK_LEN;\n  return round_down_to_power_of_2(full_chunks) * BLAKE3_CHUNK_LEN;\n}\n\n// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE chunks at the same time\n// on a single thread. Write out the chunk chaining values and return the\n// number of chunks hashed. These chunks are never the root and never empty;\n// those cases use a different codepath.\nINLINE size_t compress_chunks_parallel(const uint8_t *input, size_t input_len,\n                                       const uint32_t key[8],\n                                       uint64_t chunk_counter, uint8_t flags,\n                                       uint8_t *out) {\n#if defined(BLAKE3_TESTING)\n  assert(0 < input_len);\n  assert(input_len <= MAX_SIMD_DEGREE * BLAKE3_CHUNK_LEN);\n#endif\n\n  const uint8_t *chunks_array[MAX_SIMD_DEGREE];\n  size_t input_position = 0;\n  size_t chunks_array_len = 0;\n  while (input_len - input_position >= BLAKE3_CHUNK_LEN) {\n    chunks_array[chunks_array_len] = &input[input_position];\n    input_position += BLAKE3_CHUNK_LEN;\n    chunks_array_len += 1;\n  }\n\n  blake3_hash_many(chunks_array, chunks_array_len,\n                   BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter,\n                   true, flags, CHUNK_START, CHUNK_END, out);\n\n  // Hash the remaining partial chunk, if there is one. Note that the empty\n  // chunk (meaning the empty message) is a different codepath.\n  if (input_len > input_position) {\n    uint64_t counter = chunk_counter + (uint64_t)chunks_array_len;\n    blake3_chunk_state chunk_state;\n    chunk_state_init(&chunk_state, key, flags);\n    chunk_state.chunk_counter = counter;\n    chunk_state_update(&chunk_state, &input[input_position],\n                       input_len - input_position);\n    output_t output = chunk_state_output(&chunk_state);\n    output_chaining_value(&output, &out[chunks_array_len * BLAKE3_OUT_LEN]);\n    return chunks_array_len + 1;\n  } else {\n    return chunks_array_len;\n  }\n}\n\n// Use SIMD parallelism to hash up to MAX_SIMD_DEGREE parents at the same time\n// on a single thread. Write out the parent chaining values and return the\n// number of parents hashed. (If there's an odd input chaining value left over,\n// return it as an additional output.) These parents are never the root and\n// never empty; those cases use a different codepath.\nINLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values,\n                                        size_t num_chaining_values,\n                                        const uint32_t key[8], uint8_t flags,\n                                        uint8_t *out) {\n#if defined(BLAKE3_TESTING)\n  assert(2 <= num_chaining_values);\n  assert(num_chaining_values <= 2 * MAX_SIMD_DEGREE_OR_2);\n#endif\n\n  const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2];\n  size_t parents_array_len = 0;\n  while (num_chaining_values - (2 * parents_array_len) >= 2) {\n    parents_array[parents_array_len] =\n        &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN];\n    parents_array_len += 1;\n  }\n\n  blake3_hash_many(parents_array, parents_array_len, 1, key,\n                   0, // Parents always use counter 0.\n                   false, flags | PARENT,\n                   0, // Parents have no start flags.\n                   0, // Parents have no end flags.\n                   out);\n\n  // If there's an odd child left over, it becomes an output.\n  if (num_chaining_values > 2 * parents_array_len) {\n    memcpy(&out[parents_array_len * BLAKE3_OUT_LEN],\n           &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN],\n           BLAKE3_OUT_LEN);\n    return parents_array_len + 1;\n  } else {\n    return parents_array_len;\n  }\n}\n\n// The wide helper function returns (writes out) an array of chaining values\n// and returns the length of that array. The number of chaining values returned\n// is the dynamically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer,\n// if the input is shorter than that many chunks. The reason for maintaining a\n// wide array of chaining values going back up the tree, is to allow the\n// implementation to hash as many parents in parallel as possible.\n//\n// As a special case when the SIMD degree is 1, this function will still return\n// at least 2 outputs. This guarantees that this function doesn't perform the\n// root compression. (If it did, it would use the wrong flags, and also we\n// wouldn't be able to implement extendable output.) Note that this function is\n// not used when the whole input is only 1 chunk long; that's a different\n// codepath.\n//\n// Why not just have the caller split the input on the first update(), instead\n// of implementing this special rule? Because we don't want to limit SIMD or\n// multi-threading parallelism for that update().\nsize_t blake3_compress_subtree_wide(const uint8_t *input, size_t input_len,\n                                    const uint32_t key[8],\n                                    uint64_t chunk_counter, uint8_t flags,\n                                    uint8_t *out, bool use_tbb) {\n  // Note that the single chunk case does *not* bump the SIMD degree up to 2\n  // when it is 1. If this implementation adds multi-threading in the future,\n  // this gives us the option of multi-threading even the 2-chunk case, which\n  // can help performance on smaller platforms.\n  if (input_len <= blake3_simd_degree() * BLAKE3_CHUNK_LEN) {\n    return compress_chunks_parallel(input, input_len, key, chunk_counter, flags,\n                                    out);\n  }\n\n  // With more than simd_degree chunks, we need to recurse. Start by dividing\n  // the input into left and right subtrees. (Note that this is only optimal\n  // as long as the SIMD degree is a power of 2. If we ever get a SIMD degree\n  // of 3 or something, we'll need a more complicated strategy.)\n  size_t left_input_len = left_subtree_len(input_len);\n  size_t right_input_len = input_len - left_input_len;\n  const uint8_t *right_input = &input[left_input_len];\n  uint64_t right_chunk_counter =\n      chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN);\n\n  // Make space for the child outputs. Here we use MAX_SIMD_DEGREE_OR_2 to\n  // account for the special case of returning 2 outputs when the SIMD degree\n  // is 1.\n  uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN];\n  size_t degree = blake3_simd_degree();\n  if (left_input_len > BLAKE3_CHUNK_LEN && degree == 1) {\n    // The special case: We always use a degree of at least two, to make\n    // sure there are two outputs. Except, as noted above, at the chunk\n    // level, where we allow degree=1. (Note that the 1-chunk-input case is\n    // a different codepath.)\n    degree = 2;\n  }\n  uint8_t *right_cvs = &cv_array[degree * BLAKE3_OUT_LEN];\n\n  // Recurse!\n  size_t left_n = -1;\n  size_t right_n = -1;\n\n#if defined(BLAKE3_USE_TBB)\n  blake3_compress_subtree_wide_join_tbb(\n      key, flags, use_tbb,\n      // left-hand side\n      input, left_input_len, chunk_counter, cv_array, &left_n,\n      // right-hand side\n      right_input, right_input_len, right_chunk_counter, right_cvs, &right_n);\n#else\n  left_n = blake3_compress_subtree_wide(\n      input, left_input_len, key, chunk_counter, flags, cv_array, use_tbb);\n  right_n = blake3_compress_subtree_wide(right_input, right_input_len, key,\n                                         right_chunk_counter, flags, right_cvs,\n                                         use_tbb);\n#endif // BLAKE3_USE_TBB\n\n  // The special case again. If simd_degree=1, then we'll have left_n=1 and\n  // right_n=1. Rather than compressing them into a single output, return\n  // them directly, to make sure we always have at least two outputs.\n  if (left_n == 1) {\n    memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN);\n    return 2;\n  }\n\n  // Otherwise, do one layer of parent node compression.\n  size_t num_chaining_values = left_n + right_n;\n  return compress_parents_parallel(cv_array, num_chaining_values, key, flags,\n                                   out);\n}\n\n// Hash a subtree with compress_subtree_wide(), and then condense the resulting\n// list of chaining values down to a single parent node. Don't compress that\n// last parent node, however. Instead, return its message bytes (the\n// concatenated chaining values of its children). This is necessary when the\n// first call to update() supplies a complete subtree, because the topmost\n// parent node of that subtree could end up being the root. It's also necessary\n// for extended output in the general case.\n//\n// As with compress_subtree_wide(), this function is not used on inputs of 1\n// chunk or less. That's a different codepath.\nINLINE void\ncompress_subtree_to_parent_node(const uint8_t *input, size_t input_len,\n                                const uint32_t key[8], uint64_t chunk_counter,\n                                uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN],\n                                bool use_tbb) {\n#if defined(BLAKE3_TESTING)\n  assert(input_len > BLAKE3_CHUNK_LEN);\n#endif\n\n  uint8_t cv_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN];\n  size_t num_cvs = blake3_compress_subtree_wide(input, input_len, key,\n                                                chunk_counter, flags, cv_array, use_tbb);\n  assert(num_cvs <= MAX_SIMD_DEGREE_OR_2);\n  // The following loop never executes when MAX_SIMD_DEGREE_OR_2 is 2, because\n  // as we just asserted, num_cvs will always be <=2 in that case. But GCC\n  // (particularly GCC 8.5) can't tell that it never executes, and if NDEBUG is\n  // set then it emits incorrect warnings here. We tried a few different\n  // hacks to silence these, but in the end our hacks just produced different\n  // warnings (see https://github.com/BLAKE3-team/BLAKE3/pull/380). Out of\n  // desperation, we ifdef out this entire loop when we know it's not needed.\n#if MAX_SIMD_DEGREE_OR_2 > 2\n  // If MAX_SIMD_DEGREE_OR_2 is greater than 2 and there's enough input,\n  // compress_subtree_wide() returns more than 2 chaining values. Condense\n  // them into 2 by forming parent nodes repeatedly.\n  uint8_t out_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN / 2];\n  while (num_cvs > 2) {\n    num_cvs =\n        compress_parents_parallel(cv_array, num_cvs, key, flags, out_array);\n    memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN);\n  }\n#endif\n  memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN);\n}\n\nINLINE void hasher_init_base(blake3_hasher *self, const uint32_t key[8],\n                             uint8_t flags) {\n  memcpy(self->key, key, BLAKE3_KEY_LEN);\n  chunk_state_init(&self->chunk, key, flags);\n  self->cv_stack_len = 0;\n}\n\nvoid blake3_hasher_init(blake3_hasher *self) { hasher_init_base(self, IV, 0); }\n\nvoid blake3_hasher_init_keyed(blake3_hasher *self,\n                              const uint8_t key[BLAKE3_KEY_LEN]) {\n  uint32_t key_words[8];\n  load_key_words(key, key_words);\n  hasher_init_base(self, key_words, KEYED_HASH);\n}\n\nvoid blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context,\n                                       size_t context_len) {\n  blake3_hasher context_hasher;\n  hasher_init_base(&context_hasher, IV, DERIVE_KEY_CONTEXT);\n  blake3_hasher_update(&context_hasher, context, context_len);\n  uint8_t context_key[BLAKE3_KEY_LEN];\n  blake3_hasher_finalize(&context_hasher, context_key, BLAKE3_KEY_LEN);\n  uint32_t context_key_words[8];\n  load_key_words(context_key, context_key_words);\n  hasher_init_base(self, context_key_words, DERIVE_KEY_MATERIAL);\n}\n\nvoid blake3_hasher_init_derive_key(blake3_hasher *self, const char *context) {\n  blake3_hasher_init_derive_key_raw(self, context, strlen(context));\n}\n\n// As described in hasher_push_cv() below, we do \"lazy merging\", delaying\n// merges until right before the next CV is about to be added. This is\n// different from the reference implementation. Another difference is that we\n// aren't always merging 1 chunk at a time. Instead, each CV might represent\n// any power-of-two number of chunks, as long as the smaller-above-larger stack\n// order is maintained. Instead of the \"count the trailing 0-bits\" algorithm\n// described in the spec, we use a \"count the total number of 1-bits\" variant\n// that doesn't require us to retain the subtree size of the CV on top of the\n// stack. The principle is the same: each CV that should remain in the stack is\n// represented by a 1-bit in the total number of chunks (or bytes) so far.\nINLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) {\n  size_t post_merge_stack_len = (size_t)popcnt(total_len);\n  while (self->cv_stack_len > post_merge_stack_len) {\n    uint8_t *parent_node =\n        &self->cv_stack[(self->cv_stack_len - 2) * BLAKE3_OUT_LEN];\n    output_t output = parent_output(parent_node, self->key, self->chunk.flags);\n    output_chaining_value(&output, parent_node);\n    self->cv_stack_len -= 1;\n  }\n}\n\n// In reference_impl.rs, we merge the new CV with existing CVs from the stack\n// before pushing it. We can do that because we know more input is coming, so\n// we know none of the merges are root.\n//\n// This setting is different. We want to feed as much input as possible to\n// compress_subtree_wide(), without setting aside anything for the chunk_state.\n// If the user gives us 64 KiB, we want to parallelize over all 64 KiB at once\n// as a single subtree, if at all possible.\n//\n// This leads to two problems:\n// 1) This 64 KiB input might be the only call that ever gets made to update.\n//    In this case, the root node of the 64 KiB subtree would be the root node\n//    of the whole tree, and it would need to be ROOT finalized. We can't\n//    compress it until we know.\n// 2) This 64 KiB input might complete a larger tree, whose root node is\n//    similarly going to be the root of the whole tree. For example, maybe\n//    we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the\n//    node at the root of the 256 KiB subtree until we know how to finalize it.\n//\n// The second problem is solved with \"lazy merging\". That is, when we're about\n// to add a CV to the stack, we don't merge it with anything first, as the\n// reference impl does. Instead we do merges using the *previous* CV that was\n// added, which is sitting on top of the stack, and we put the new CV\n// (unmerged) on top of the stack afterwards. This guarantees that we never\n// merge the root node until finalize().\n//\n// Solving the first problem requires an additional tool,\n// compress_subtree_to_parent_node(). That function always returns the top\n// *two* chaining values of the subtree it's compressing. We then do lazy\n// merging with each of them separately, so that the second CV will always\n// remain unmerged. (That also helps us support extendable output when we're\n// hashing an input all-at-once.)\nINLINE void hasher_push_cv(blake3_hasher *self, uint8_t new_cv[BLAKE3_OUT_LEN],\n                           uint64_t chunk_counter) {\n  hasher_merge_cv_stack(self, chunk_counter);\n  memcpy(&self->cv_stack[self->cv_stack_len * BLAKE3_OUT_LEN], new_cv,\n         BLAKE3_OUT_LEN);\n  self->cv_stack_len += 1;\n}\n\nINLINE void blake3_hasher_update_base(blake3_hasher *self, const void *input,\n                                      size_t input_len, bool use_tbb) {\n  // Explicitly checking for zero avoids causing UB by passing a null pointer\n  // to memcpy. This comes up in practice with things like:\n  //   std::vector<uint8_t> v;\n  //   blake3_hasher_update(&hasher, v.data(), v.size());\n  if (input_len == 0) {\n    return;\n  }\n\n  const uint8_t *input_bytes = (const uint8_t *)input;\n\n  // If we have some partial chunk bytes in the internal chunk_state, we need\n  // to finish that chunk first.\n  if (chunk_state_len(&self->chunk) > 0) {\n    size_t take = BLAKE3_CHUNK_LEN - chunk_state_len(&self->chunk);\n    if (take > input_len) {\n      take = input_len;\n    }\n    chunk_state_update(&self->chunk, input_bytes, take);\n    input_bytes += take;\n    input_len -= take;\n    // If we've filled the current chunk and there's more coming, finalize this\n    // chunk and proceed. In this case we know it's not the root.\n    if (input_len > 0) {\n      output_t output = chunk_state_output(&self->chunk);\n      uint8_t chunk_cv[32];\n      output_chaining_value(&output, chunk_cv);\n      hasher_push_cv(self, chunk_cv, self->chunk.chunk_counter);\n      chunk_state_reset(&self->chunk, self->key, self->chunk.chunk_counter + 1);\n    } else {\n      return;\n    }\n  }\n\n  // Now the chunk_state is clear, and we have more input. If there's more than\n  // a single chunk (so, definitely not the root chunk), hash the largest whole\n  // subtree we can, with the full benefits of SIMD (and maybe in the future,\n  // multi-threading) parallelism. Two restrictions:\n  // - The subtree has to be a power-of-2 number of chunks. Only subtrees along\n  //   the right edge can be incomplete, and we don't know where the right edge\n  //   is going to be until we get to finalize().\n  // - The subtree must evenly divide the total number of chunks up until this\n  //   point (if total is not 0). If the current incomplete subtree is only\n  //   waiting for 1 more chunk, we can't hash a subtree of 4 chunks. We have\n  //   to complete the current subtree first.\n  // Because we might need to break up the input to form powers of 2, or to\n  // evenly divide what we already have, this part runs in a loop.\n  while (input_len > BLAKE3_CHUNK_LEN) {\n    size_t subtree_len = round_down_to_power_of_2(input_len);\n    uint64_t count_so_far = self->chunk.chunk_counter * BLAKE3_CHUNK_LEN;\n    // Shrink the subtree_len until it evenly divides the count so far. We know\n    // that subtree_len itself is a power of 2, so we can use a bitmasking\n    // trick instead of an actual remainder operation. (Note that if the caller\n    // consistently passes power-of-2 inputs of the same size, as is hopefully\n    // typical, this loop condition will always fail, and subtree_len will\n    // always be the full length of the input.)\n    //\n    // An aside: We don't have to shrink subtree_len quite this much. For\n    // example, if count_so_far is 1, we could pass 2 chunks to\n    // compress_subtree_to_parent_node. Since we'll get 2 CVs back, we'll still\n    // get the right answer in the end, and we might get to use 2-way SIMD\n    // parallelism. The problem with this optimization, is that it gets us\n    // stuck always hashing 2 chunks. The total number of chunks will remain\n    // odd, and we'll never graduate to higher degrees of parallelism. See\n    // https://github.com/BLAKE3-team/BLAKE3/issues/69.\n    while ((((uint64_t)(subtree_len - 1)) & count_so_far) != 0) {\n      subtree_len /= 2;\n    }\n    // The shrunken subtree_len might now be 1 chunk long. If so, hash that one\n    // chunk by itself. Otherwise, compress the subtree into a pair of CVs.\n    uint64_t subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN;\n    if (subtree_len <= BLAKE3_CHUNK_LEN) {\n      blake3_chunk_state chunk_state;\n      chunk_state_init(&chunk_state, self->key, self->chunk.flags);\n      chunk_state.chunk_counter = self->chunk.chunk_counter;\n      chunk_state_update(&chunk_state, input_bytes, subtree_len);\n      output_t output = chunk_state_output(&chunk_state);\n      uint8_t cv[BLAKE3_OUT_LEN];\n      output_chaining_value(&output, cv);\n      hasher_push_cv(self, cv, chunk_state.chunk_counter);\n    } else {\n      // This is the high-performance happy path, though getting here depends\n      // on the caller giving us a long enough input.\n      uint8_t cv_pair[2 * BLAKE3_OUT_LEN];\n      compress_subtree_to_parent_node(input_bytes, subtree_len, self->key,\n                                      self->chunk.chunk_counter,\n                                      self->chunk.flags, cv_pair, use_tbb);\n      hasher_push_cv(self, cv_pair, self->chunk.chunk_counter);\n      hasher_push_cv(self, &cv_pair[BLAKE3_OUT_LEN],\n                     self->chunk.chunk_counter + (subtree_chunks / 2));\n    }\n    self->chunk.chunk_counter += subtree_chunks;\n    input_bytes += subtree_len;\n    input_len -= subtree_len;\n  }\n\n  // If there's any remaining input less than a full chunk, add it to the chunk\n  // state. In that case, also do a final merge loop to make sure the subtree\n  // stack doesn't contain any unmerged pairs. The remaining input means we\n  // know these merges are non-root. This merge loop isn't strictly necessary\n  // here, because hasher_push_chunk_cv already does its own merge loop, but it\n  // simplifies blake3_hasher_finalize below.\n  if (input_len > 0) {\n    chunk_state_update(&self->chunk, input_bytes, input_len);\n    hasher_merge_cv_stack(self, self->chunk.chunk_counter);\n  }\n}\n\nvoid blake3_hasher_update(blake3_hasher *self, const void *input,\n                          size_t input_len) {\n  bool use_tbb = false;\n  blake3_hasher_update_base(self, input, input_len, use_tbb);\n}\n\n#if defined(BLAKE3_USE_TBB)\nvoid blake3_hasher_update_tbb(blake3_hasher *self, const void *input,\n                              size_t input_len) {\n  bool use_tbb = true;\n  blake3_hasher_update_base(self, input, input_len, use_tbb);\n}\n#endif // BLAKE3_USE_TBB\n\nvoid blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,\n                            size_t out_len) {\n  blake3_hasher_finalize_seek(self, 0, out, out_len);\n}\n\nvoid blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,\n                                 uint8_t *out, size_t out_len) {\n  // Explicitly checking for zero avoids causing UB by passing a null pointer\n  // to memcpy. This comes up in practice with things like:\n  //   std::vector<uint8_t> v;\n  //   blake3_hasher_finalize(&hasher, v.data(), v.size());\n  if (out_len == 0) {\n    return;\n  }\n\n  // If the subtree stack is empty, then the current chunk is the root.\n  if (self->cv_stack_len == 0) {\n    output_t output = chunk_state_output(&self->chunk);\n    output_root_bytes(&output, seek, out, out_len);\n    return;\n  }\n  // If there are any bytes in the chunk state, finalize that chunk and do a\n  // roll-up merge between that chunk hash and every subtree in the stack. In\n  // this case, the extra merge loop at the end of blake3_hasher_update\n  // guarantees that none of the subtrees in the stack need to be merged with\n  // each other first. Otherwise, if there are no bytes in the chunk state,\n  // then the top of the stack is a chunk hash, and we start the merge from\n  // that.\n  output_t output;\n  size_t cvs_remaining;\n  if (chunk_state_len(&self->chunk) > 0) {\n    cvs_remaining = self->cv_stack_len;\n    output = chunk_state_output(&self->chunk);\n  } else {\n    // There are always at least 2 CVs in the stack in this case.\n    cvs_remaining = self->cv_stack_len - 2;\n    output = parent_output(&self->cv_stack[cvs_remaining * 32], self->key,\n                           self->chunk.flags);\n  }\n  while (cvs_remaining > 0) {\n    cvs_remaining -= 1;\n    uint8_t parent_block[BLAKE3_BLOCK_LEN];\n    memcpy(parent_block, &self->cv_stack[cvs_remaining * 32], 32);\n    output_chaining_value(&output, &parent_block[32]);\n    output = parent_output(parent_block, self->key, self->chunk.flags);\n  }\n  output_root_bytes(&output, seek, out, out_len);\n}\n\nvoid blake3_hasher_reset(blake3_hasher *self) {\n  chunk_state_reset(&self->chunk, self->key, 0);\n  self->cv_stack_len = 0;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3.h",
    "content": "﻿#ifndef BLAKE3_H\n#define BLAKE3_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#if !defined(BLAKE3_API)\n# if defined(_WIN32) || defined(__CYGWIN__)\n#   if defined(BLAKE3_DLL)\n#     if defined(BLAKE3_DLL_EXPORTS)\n#       define BLAKE3_API __declspec(dllexport)\n#     else\n#       define BLAKE3_API __declspec(dllimport)\n#     endif\n#     define BLAKE3_PRIVATE\n#   else\n#     define BLAKE3_API\n#     define BLAKE3_PRIVATE\n#   endif\n# elif __GNUC__ >= 4\n#   define BLAKE3_API __attribute__((visibility(\"default\")))\n#   define BLAKE3_PRIVATE __attribute__((visibility(\"hidden\")))\n# else\n#   define BLAKE3_API\n#   define BLAKE3_PRIVATE\n# endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define BLAKE3_VERSION_STRING \"1.8.3\"\n#define BLAKE3_KEY_LEN 32\n#define BLAKE3_OUT_LEN 32\n#define BLAKE3_BLOCK_LEN 64\n#define BLAKE3_CHUNK_LEN 1024\n#define BLAKE3_MAX_DEPTH 54\n\n// This struct is a private implementation detail. It has to be here because\n// it's part of the blake3_hasher structure defined below.\ntypedef struct {\n  uint32_t cv[8];\n  uint64_t chunk_counter;\n  uint8_t buf[BLAKE3_BLOCK_LEN];\n  uint8_t buf_len;\n  uint8_t blocks_compressed;\n  uint8_t flags;\n} blake3_chunk_state;\n\ntypedef struct {\n  uint32_t key[8];\n  blake3_chunk_state chunk;\n  uint8_t cv_stack_len;\n  // The stack size is MAX_DEPTH + 1 because we do lazy merging. For example,\n  // with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk\n  // requires a 4th entry, rather than merging everything down to 1, because we\n  // don't know whether more input is coming. This is different from how the\n  // reference implementation does things.\n  uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN];\n} blake3_hasher;\n\nBLAKE3_API const char *blake3_version(void);\nBLAKE3_API void blake3_hasher_init(blake3_hasher *self);\nBLAKE3_API void blake3_hasher_init_keyed(blake3_hasher *self,\n                                         const uint8_t key[BLAKE3_KEY_LEN]);\nBLAKE3_API void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context);\nBLAKE3_API void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context,\n                                                  size_t context_len);\nBLAKE3_API void blake3_hasher_update(blake3_hasher *self, const void *input,\n                                     size_t input_len);\n#if defined(BLAKE3_USE_TBB)\nBLAKE3_API void blake3_hasher_update_tbb(blake3_hasher *self, const void *input,\n                                         size_t input_len);\n#endif // BLAKE3_USE_TBB\nBLAKE3_API void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,\n                                       size_t out_len);\nBLAKE3_API void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,\n                                            uint8_t *out, size_t out_len);\nBLAKE3_API void blake3_hasher_reset(blake3_hasher *self);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* BLAKE3_H */\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_avx2_x86-64_windows_msvc.asm",
    "content": "public _blake3_hash_many_avx2\npublic blake3_hash_many_avx2\n\n_TEXT   SEGMENT ALIGN(16) 'CODE'\n\nALIGN   16\nblake3_hash_many_avx2 PROC\n_blake3_hash_many_avx2 PROC\n        push    r15\n        push    r14\n        push    r13\n        push    r12\n        push    rsi\n        push    rdi\n        push    rbx\n        push    rbp\n        mov     rbp, rsp\n        sub     rsp, 880\n        and     rsp, 0FFFFFFFFFFFFFFC0H\n        vmovdqa xmmword ptr [rsp+2D0H], xmm6\n        vmovdqa xmmword ptr [rsp+2E0H], xmm7\n        vmovdqa xmmword ptr [rsp+2F0H], xmm8\n        vmovdqa xmmword ptr [rsp+300H], xmm9\n        vmovdqa xmmword ptr [rsp+310H], xmm10\n        vmovdqa xmmword ptr [rsp+320H], xmm11\n        vmovdqa xmmword ptr [rsp+330H], xmm12\n        vmovdqa xmmword ptr [rsp+340H], xmm13\n        vmovdqa xmmword ptr [rsp+350H], xmm14\n        vmovdqa xmmword ptr [rsp+360H], xmm15\n        mov     rdi, rcx\n        mov     rsi, rdx\n        mov     rdx, r8\n        mov     rcx, r9\n        mov     r8, qword ptr [rbp+68H]\n        movzx   r9, byte ptr [rbp+70H]\n        neg     r9d\n        vmovd   xmm0, r9d\n        vpbroadcastd ymm0, xmm0\n        vmovdqa ymmword ptr [rsp+260H], ymm0\n        vpand   ymm1, ymm0, ymmword ptr [ADD0]\n        vpand   ymm2, ymm0, ymmword ptr [ADD1]\n        vmovdqa ymmword ptr [rsp+2A0H], ymm2\n        vmovd   xmm2, r8d\n        vpbroadcastd ymm2, xmm2\n        vpaddd  ymm2, ymm2, ymm1\n        vmovdqa ymmword ptr [rsp+220H], ymm2\n        vpxor   ymm1, ymm1, ymmword ptr [CMP_MSB_MASK]\n        vpxor   ymm2, ymm2, ymmword ptr [CMP_MSB_MASK]\n        vpcmpgtd ymm2, ymm1, ymm2\n        shr     r8, 32\n        vmovd   xmm3, r8d\n        vpbroadcastd ymm3, xmm3\n        vpsubd  ymm3, ymm3, ymm2\n        vmovdqa ymmword ptr [rsp+240H], ymm3\n        shl     rdx, 6\n        mov     qword ptr [rsp+2C0H], rdx\n        cmp     rsi, 8\n        jc      final7blocks\nouterloop8:\n        vpbroadcastd ymm0, dword ptr [rcx]\n        vpbroadcastd ymm1, dword ptr [rcx+4H]\n        vpbroadcastd ymm2, dword ptr [rcx+8H]\n        vpbroadcastd ymm3, dword ptr [rcx+0CH]\n        vpbroadcastd ymm4, dword ptr [rcx+10H]\n        vpbroadcastd ymm5, dword ptr [rcx+14H]\n        vpbroadcastd ymm6, dword ptr [rcx+18H]\n        vpbroadcastd ymm7, dword ptr [rcx+1CH]\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        mov     r12, qword ptr [rdi+20H]\n        mov     r13, qword ptr [rdi+28H]\n        mov     r14, qword ptr [rdi+30H]\n        mov     r15, qword ptr [rdi+38H]\n        movzx   eax, byte ptr [rbp+78H]\n        movzx   ebx, byte ptr [rbp+80H]\n        or      eax, ebx\n        xor     edx, edx\nALIGN   16\ninnerloop8:\n        movzx   ebx, byte ptr [rbp+88H]\n        or      ebx, eax\n        add     rdx, 64\n        cmp     rdx, qword ptr [rsp+2C0H]\n        cmove   eax, ebx\n        mov     dword ptr [rsp+200H], eax\n        vmovups xmm8, xmmword ptr [r8+rdx-40H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-40H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-40H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-40H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-40H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-40H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-40H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-40H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm8, ymm12, ymm14, 136\n        vmovaps ymmword ptr [rsp], ymm8\n        vshufps ymm9, ymm12, ymm14, 221\n        vmovaps ymmword ptr [rsp+20H], ymm9\n        vshufps ymm10, ymm13, ymm15, 136\n        vmovaps ymmword ptr [rsp+40H], ymm10\n        vshufps ymm11, ymm13, ymm15, 221\n        vmovaps ymmword ptr [rsp+60H], ymm11\n        vmovups xmm8, xmmword ptr [r8+rdx-30H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-30H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-30H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-30H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-30H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-30H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-30H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-30H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm8, ymm12, ymm14, 136\n        vmovaps ymmword ptr [rsp+80H], ymm8\n        vshufps ymm9, ymm12, ymm14, 221\n        vmovaps ymmword ptr [rsp+0A0H], ymm9\n        vshufps ymm10, ymm13, ymm15, 136\n        vmovaps ymmword ptr [rsp+0C0H], ymm10\n        vshufps ymm11, ymm13, ymm15, 221\n        vmovaps ymmword ptr [rsp+0E0H], ymm11\n        vmovups xmm8, xmmword ptr [r8+rdx-20H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-20H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-20H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-20H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-20H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-20H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-20H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-20H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm8, ymm12, ymm14, 136\n        vmovaps ymmword ptr [rsp+100H], ymm8\n        vshufps ymm9, ymm12, ymm14, 221\n        vmovaps ymmword ptr [rsp+120H], ymm9\n        vshufps ymm10, ymm13, ymm15, 136\n        vmovaps ymmword ptr [rsp+140H], ymm10\n        vshufps ymm11, ymm13, ymm15, 221\n        vmovaps ymmword ptr [rsp+160H], ymm11\n        vmovups xmm8, xmmword ptr [r8+rdx-10H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-10H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-10H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-10H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-10H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-10H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-10H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-10H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm8, ymm12, ymm14, 136\n        vmovaps ymmword ptr [rsp+180H], ymm8\n        vshufps ymm9, ymm12, ymm14, 221\n        vmovaps ymmword ptr [rsp+1A0H], ymm9\n        vshufps ymm10, ymm13, ymm15, 136\n        vmovaps ymmword ptr [rsp+1C0H], ymm10\n        vshufps ymm11, ymm13, ymm15, 221\n        vmovaps ymmword ptr [rsp+1E0H], ymm11\n        vpbroadcastd ymm15, dword ptr [rsp+200H]\n        prefetcht0 byte ptr [r8+rdx+80H]\n        prefetcht0 byte ptr [r12+rdx+80H]\n        prefetcht0 byte ptr [r9+rdx+80H]\n        prefetcht0 byte ptr [r13+rdx+80H]\n        prefetcht0 byte ptr [r10+rdx+80H]\n        prefetcht0 byte ptr [r14+rdx+80H]\n        prefetcht0 byte ptr [r11+rdx+80H]\n        prefetcht0 byte ptr [r15+rdx+80H]\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+40H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+80H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0C0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm0, ymmword ptr [rsp+220H]\n        vpxor   ymm13, ymm1, ymmword ptr [rsp+240H]\n        vpxor   ymm14, ymm2, ymmword ptr [BLAKE3_BLOCK_LEN]\n        vpxor   ymm15, ymm3, ymm15\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [BLAKE3_IV_0]\n        vpaddd  ymm9, ymm13, ymmword ptr [BLAKE3_IV_1]\n        vpaddd  ymm10, ymm14, ymmword ptr [BLAKE3_IV_2]\n        vpaddd  ymm11, ymm15, ymmword ptr [BLAKE3_IV_3]\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+20H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+60H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+0A0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0E0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+100H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+140H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+180H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1C0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+120H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+160H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+1A0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1E0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+40H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+60H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+0E0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+80H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+0C0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+140H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1A0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+20H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+180H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+120H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1E0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+160H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+0A0H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+1C0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+100H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+60H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+140H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+1A0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0E0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+80H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+180H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+40H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1C0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+0C0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+120H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+160H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+100H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+0A0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+1E0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+20H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+140H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+180H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+1C0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1A0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+0E0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+120H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+60H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1E0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+80H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+160H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+0A0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+20H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+40H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+100H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0C0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+180H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+120H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+1E0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1C0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+1A0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+160H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+140H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+100H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+0E0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+0A0H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0C0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+40H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+60H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+20H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+80H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+120H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+160H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+100H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1E0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+1C0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+0A0H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+180H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+20H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+1A0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+40H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+80H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+60H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+140H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+0C0H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0E0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+160H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+0A0H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+20H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+100H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+1E0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+120H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0C0H]\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxor   ymm12, ymm12, ymm0\n        vpxor   ymm13, ymm13, ymm1\n        vpxor   ymm14, ymm14, ymm2\n        vpxor   ymm15, ymm15, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpshufb ymm15, ymm15, ymm8\n        vpaddd  ymm8, ymm12, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxor   ymm4, ymm4, ymm8\n        vpxor   ymm5, ymm5, ymm9\n        vpxor   ymm6, ymm6, ymm10\n        vpxor   ymm7, ymm7, ymm11\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+1C0H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+40H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+60H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+0E0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT16]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vmovdqa ymmword ptr [rsp+200H], ymm8\n        vpsrld  ymm8, ymm5, 12\n        vpslld  ymm5, ymm5, 20\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 12\n        vpslld  ymm6, ymm6, 20\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 12\n        vpslld  ymm7, ymm7, 20\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 12\n        vpslld  ymm4, ymm4, 20\n        vpor    ymm4, ymm4, ymm8\n        vpaddd  ymm0, ymm0, ymmword ptr [rsp+140H]\n        vpaddd  ymm1, ymm1, ymmword ptr [rsp+180H]\n        vpaddd  ymm2, ymm2, ymmword ptr [rsp+80H]\n        vpaddd  ymm3, ymm3, ymmword ptr [rsp+1A0H]\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxor   ymm15, ymm15, ymm0\n        vpxor   ymm12, ymm12, ymm1\n        vpxor   ymm13, ymm13, ymm2\n        vpxor   ymm14, ymm14, ymm3\n        vbroadcasti128 ymm8, xmmword ptr [ROT8]\n        vpshufb ymm15, ymm15, ymm8\n        vpshufb ymm12, ymm12, ymm8\n        vpshufb ymm13, ymm13, ymm8\n        vpshufb ymm14, ymm14, ymm8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm13, ymmword ptr [rsp+200H]\n        vpaddd  ymm9, ymm9, ymm14\n        vpxor   ymm5, ymm5, ymm10\n        vpxor   ymm6, ymm6, ymm11\n        vpxor   ymm7, ymm7, ymm8\n        vpxor   ymm4, ymm4, ymm9\n        vpxor   ymm0, ymm0, ymm8\n        vpxor   ymm1, ymm1, ymm9\n        vpxor   ymm2, ymm2, ymm10\n        vpxor   ymm3, ymm3, ymm11\n        vpsrld  ymm8, ymm5, 7\n        vpslld  ymm5, ymm5, 25\n        vpor    ymm5, ymm5, ymm8\n        vpsrld  ymm8, ymm6, 7\n        vpslld  ymm6, ymm6, 25\n        vpor    ymm6, ymm6, ymm8\n        vpsrld  ymm8, ymm7, 7\n        vpslld  ymm7, ymm7, 25\n        vpor    ymm7, ymm7, ymm8\n        vpsrld  ymm8, ymm4, 7\n        vpslld  ymm4, ymm4, 25\n        vpor    ymm4, ymm4, ymm8\n        vpxor   ymm4, ymm4, ymm12\n        vpxor   ymm5, ymm5, ymm13\n        vpxor   ymm6, ymm6, ymm14\n        vpxor   ymm7, ymm7, ymm15\n        movzx   eax, byte ptr [rbp+78H]\n        jne     innerloop8\n        mov     rbx, qword ptr [rbp+90H]\n        vunpcklps ymm8, ymm0, ymm1\n        vunpcklps ymm9, ymm2, ymm3\n        vunpckhps ymm10, ymm0, ymm1\n        vunpcklps ymm11, ymm4, ymm5\n        vunpcklps ymm0, ymm6, ymm7\n        vshufps ymm12, ymm8, ymm9, 78\n        vblendps ymm1, ymm8, ymm12, 0CCH\n        vshufps ymm8, ymm11, ymm0, 78\n        vunpckhps ymm13, ymm2, ymm3\n        vblendps ymm2, ymm11, ymm8, 0CCH\n        vblendps ymm3, ymm12, ymm9, 0CCH\n        vperm2f128 ymm12, ymm1, ymm2, 20H\n        vmovups ymmword ptr [rbx], ymm12\n        vunpckhps ymm14, ymm4, ymm5\n        vblendps ymm4, ymm8, ymm0, 0CCH\n        vunpckhps ymm15, ymm6, ymm7\n        vperm2f128 ymm7, ymm3, ymm4, 20H\n        vmovups ymmword ptr [rbx+20H], ymm7\n        vshufps ymm5, ymm10, ymm13, 78\n        vblendps ymm6, ymm5, ymm13, 0CCH\n        vshufps ymm13, ymm14, ymm15, 78\n        vblendps ymm10, ymm10, ymm5, 0CCH\n        vblendps ymm14, ymm14, ymm13, 0CCH\n        vperm2f128 ymm8, ymm10, ymm14, 20H\n        vmovups ymmword ptr [rbx+40H], ymm8\n        vblendps ymm15, ymm13, ymm15, 0CCH\n        vperm2f128 ymm13, ymm6, ymm15, 20H\n        vmovups ymmword ptr [rbx+60H], ymm13\n        vperm2f128 ymm9, ymm1, ymm2, 31H\n        vperm2f128 ymm11, ymm3, ymm4, 31H\n        vmovups ymmword ptr [rbx+80H], ymm9\n        vperm2f128 ymm14, ymm10, ymm14, 31H\n        vperm2f128 ymm15, ymm6, ymm15, 31H\n        vmovups ymmword ptr [rbx+0A0H], ymm11\n        vmovups ymmword ptr [rbx+0C0H], ymm14\n        vmovups ymmword ptr [rbx+0E0H], ymm15\n        vmovdqa ymm0, ymmword ptr [rsp+2A0H]\n        vpaddd  ymm1, ymm0, ymmword ptr [rsp+220H]\n        vmovdqa ymmword ptr [rsp+220H], ymm1\n        vpxor   ymm0, ymm0, ymmword ptr [CMP_MSB_MASK]\n        vpxor   ymm2, ymm1, ymmword ptr [CMP_MSB_MASK]\n        vpcmpgtd ymm2, ymm0, ymm2\n        vmovdqa ymm0, ymmword ptr [rsp+240H]\n        vpsubd  ymm2, ymm0, ymm2\n        vmovdqa ymmword ptr [rsp+240H], ymm2\n        add     rdi, 64\n        add     rbx, 256\n        mov     qword ptr [rbp+90H], rbx\n        sub     rsi, 8\n        cmp     rsi, 8\n        jnc     outerloop8\n        test    rsi, rsi\n        jnz     final7blocks\nunwind:\n        vzeroupper\n        vmovdqa xmm6, xmmword ptr [rsp+2D0H]\n        vmovdqa xmm7, xmmword ptr [rsp+2E0H]\n        vmovdqa xmm8, xmmword ptr [rsp+2F0H]\n        vmovdqa xmm9, xmmword ptr [rsp+300H]\n        vmovdqa xmm10, xmmword ptr [rsp+310H]\n        vmovdqa xmm11, xmmword ptr [rsp+320H]\n        vmovdqa xmm12, xmmword ptr [rsp+330H]\n        vmovdqa xmm13, xmmword ptr [rsp+340H]\n        vmovdqa xmm14, xmmword ptr [rsp+350H]\n        vmovdqa xmm15, xmmword ptr [rsp+360H]\n        mov     rsp, rbp\n        pop     rbp\n        pop     rbx\n        pop     rdi\n        pop     rsi\n        pop     r12\n        pop     r13\n        pop     r14\n        pop     r15\n        ret\nALIGN   16\nfinal7blocks:\n        mov     rbx, qword ptr [rbp+90H]\n        mov     r15, qword ptr [rsp+2C0H]\n        movzx   r13d, byte ptr [rbp+78H]\n        movzx   r12d, byte ptr [rbp+88H]\n        test    rsi, 4H\n        je      final3blocks\n        vbroadcasti128 ymm0, xmmword ptr [rcx]\n        vbroadcasti128 ymm1, xmmword ptr [rcx+10H]\n        vmovdqa ymm8, ymm0\n        vmovdqa ymm9, ymm1\n        vbroadcasti128 ymm12, xmmword ptr [rsp+220H]\n        vbroadcasti128 ymm13, xmmword ptr [rsp+240H]\n        vpunpckldq ymm14, ymm12, ymm13\n        vpunpckhdq ymm15, ymm12, ymm13\n        vpermq  ymm14, ymm14, 50H\n        vpermq  ymm15, ymm15, 50H\n        vbroadcasti128 ymm12, xmmword ptr [BLAKE3_BLOCK_LEN]\n        vpblendd ymm14, ymm14, ymm12, 44H\n        vpblendd ymm15, ymm15, ymm12, 44H\n        vmovdqa ymmword ptr [rsp], ymm14\n        vmovdqa ymmword ptr [rsp+20H], ymm15\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\nALIGN   16\ninnerloop4:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        mov     dword ptr [rsp+200H], eax\n        vmovups ymm2, ymmword ptr [r8+rdx-40H]\n        vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-40H], 01H\n        vmovups ymm3, ymmword ptr [r8+rdx-30H]\n        vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-30H], 01H\n        vshufps ymm4, ymm2, ymm3, 136\n        vshufps ymm5, ymm2, ymm3, 221\n        vmovups ymm2, ymmword ptr [r8+rdx-20H]\n        vinsertf128 ymm2, ymm2, xmmword ptr [r9+rdx-20H], 01H\n        vmovups ymm3, ymmword ptr [r8+rdx-10H]\n        vinsertf128 ymm3, ymm3, xmmword ptr [r9+rdx-10H], 01H\n        vshufps ymm6, ymm2, ymm3, 136\n        vshufps ymm7, ymm2, ymm3, 221\n        vpshufd ymm6, ymm6, 93H\n        vpshufd ymm7, ymm7, 93H\n        vmovups ymm10, ymmword ptr [r10+rdx-40H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-40H], 01H\n        vmovups ymm11, ymmword ptr [r10+rdx-30H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-30H], 01H\n        vshufps ymm12, ymm10, ymm11, 136\n        vshufps ymm13, ymm10, ymm11, 221\n        vmovups ymm10, ymmword ptr [r10+rdx-20H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r11+rdx-20H], 01H\n        vmovups ymm11, ymmword ptr [r10+rdx-10H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r11+rdx-10H], 01H\n        vshufps ymm14, ymm10, ymm11, 136\n        vshufps ymm15, ymm10, ymm11, 221\n        vpshufd ymm14, ymm14, 93H\n        vpshufd ymm15, ymm15, 93H\n        vpbroadcastd ymm2, dword ptr [rsp+200H]\n        vmovdqa ymm3, ymmword ptr [rsp]\n        vmovdqa ymm11, ymmword ptr [rsp+20H]\n        vpblendd ymm3, ymm3, ymm2, 88H\n        vpblendd ymm11, ymm11, ymm2, 88H\n        vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV]\n        vmovdqa ymm10, ymm2\n        mov     al, 7\nroundloop4:\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm8, ymm8, ymm12\n        vmovdqa ymmword ptr [rsp+40H], ymm4\n        nop\n        vmovdqa ymmword ptr [rsp+60H], ymm12\n        nop\n        vpaddd  ymm0, ymm0, ymm1\n        vpaddd  ymm8, ymm8, ymm9\n        vpxor   ymm3, ymm3, ymm0\n        vpxor   ymm11, ymm11, ymm8\n        vbroadcasti128 ymm4, xmmword ptr [ROT16]\n        vpshufb ymm3, ymm3, ymm4\n        vpshufb ymm11, ymm11, ymm4\n        vpaddd  ymm2, ymm2, ymm3\n        vpaddd  ymm10, ymm10, ymm11\n        vpxor   ymm1, ymm1, ymm2\n        vpxor   ymm9, ymm9, ymm10\n        vpsrld  ymm4, ymm1, 12\n        vpslld  ymm1, ymm1, 20\n        vpor    ymm1, ymm1, ymm4\n        vpsrld  ymm4, ymm9, 12\n        vpslld  ymm9, ymm9, 20\n        vpor    ymm9, ymm9, ymm4\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm0, ymm0, ymm1\n        vpaddd  ymm8, ymm8, ymm9\n        vmovdqa ymmword ptr [rsp+80H], ymm5\n        vmovdqa ymmword ptr [rsp+0A0H], ymm13\n        vpxor   ymm3, ymm3, ymm0\n        vpxor   ymm11, ymm11, ymm8\n        vbroadcasti128 ymm4, xmmword ptr [ROT8]\n        vpshufb ymm3, ymm3, ymm4\n        vpshufb ymm11, ymm11, ymm4\n        vpaddd  ymm2, ymm2, ymm3\n        vpaddd  ymm10, ymm10, ymm11\n        vpxor   ymm1, ymm1, ymm2\n        vpxor   ymm9, ymm9, ymm10\n        vpsrld  ymm4, ymm1, 7\n        vpslld  ymm1, ymm1, 25\n        vpor    ymm1, ymm1, ymm4\n        vpsrld  ymm4, ymm9, 7\n        vpslld  ymm9, ymm9, 25\n        vpor    ymm9, ymm9, ymm4\n        vpshufd ymm0, ymm0, 93H\n        vpshufd ymm8, ymm8, 93H\n        vpshufd ymm3, ymm3, 4EH\n        vpshufd ymm11, ymm11, 4EH\n        vpshufd ymm2, ymm2, 39H\n        vpshufd ymm10, ymm10, 39H\n        vpaddd  ymm0, ymm0, ymm6\n        vpaddd  ymm8, ymm8, ymm14\n        vpaddd  ymm0, ymm0, ymm1\n        vpaddd  ymm8, ymm8, ymm9\n        vpxor   ymm3, ymm3, ymm0\n        vpxor   ymm11, ymm11, ymm8\n        vbroadcasti128 ymm4, xmmword ptr [ROT16]\n        vpshufb ymm3, ymm3, ymm4\n        vpshufb ymm11, ymm11, ymm4\n        vpaddd  ymm2, ymm2, ymm3\n        vpaddd  ymm10, ymm10, ymm11\n        vpxor   ymm1, ymm1, ymm2\n        vpxor   ymm9, ymm9, ymm10\n        vpsrld  ymm4, ymm1, 12\n        vpslld  ymm1, ymm1, 20\n        vpor    ymm1, ymm1, ymm4\n        vpsrld  ymm4, ymm9, 12\n        vpslld  ymm9, ymm9, 20\n        vpor    ymm9, ymm9, ymm4\n        vpaddd  ymm0, ymm0, ymm7\n        vpaddd  ymm8, ymm8, ymm15\n        vpaddd  ymm0, ymm0, ymm1\n        vpaddd  ymm8, ymm8, ymm9\n        vpxor   ymm3, ymm3, ymm0\n        vpxor   ymm11, ymm11, ymm8\n        vbroadcasti128 ymm4, xmmword ptr [ROT8]\n        vpshufb ymm3, ymm3, ymm4\n        vpshufb ymm11, ymm11, ymm4\n        vpaddd  ymm2, ymm2, ymm3\n        vpaddd  ymm10, ymm10, ymm11\n        vpxor   ymm1, ymm1, ymm2\n        vpxor   ymm9, ymm9, ymm10\n        vpsrld  ymm4, ymm1, 7\n        vpslld  ymm1, ymm1, 25\n        vpor    ymm1, ymm1, ymm4\n        vpsrld  ymm4, ymm9, 7\n        vpslld  ymm9, ymm9, 25\n        vpor    ymm9, ymm9, ymm4\n        vpshufd ymm0, ymm0, 39H\n        vpshufd ymm8, ymm8, 39H\n        vpshufd ymm3, ymm3, 4EH\n        vpshufd ymm11, ymm11, 4EH\n        vpshufd ymm2, ymm2, 93H\n        vpshufd ymm10, ymm10, 93H\n        dec     al\n        je      endroundloop4\n        vmovdqa ymm4, ymmword ptr [rsp+40H]\n        vmovdqa ymm5, ymmword ptr [rsp+80H]\n        vshufps ymm12, ymm4, ymm5, 214\n        vpshufd ymm13, ymm4, 0FH\n        vpshufd ymm4, ymm12, 39H\n        vshufps ymm12, ymm6, ymm7, 250\n        vpblendd ymm13, ymm13, ymm12, 0AAH\n        vpunpcklqdq ymm12, ymm7, ymm5\n        vpblendd ymm12, ymm12, ymm6, 88H\n        vpshufd ymm12, ymm12, 78H\n        vpunpckhdq ymm5, ymm5, ymm7\n        vpunpckldq ymm6, ymm6, ymm5\n        vpshufd ymm7, ymm6, 1EH\n        vmovdqa ymmword ptr [rsp+40H], ymm13\n        vmovdqa ymmword ptr [rsp+80H], ymm12\n        vmovdqa ymm12, ymmword ptr [rsp+60H]\n        vmovdqa ymm13, ymmword ptr [rsp+0A0H]\n        vshufps ymm5, ymm12, ymm13, 214\n        vpshufd ymm6, ymm12, 0FH\n        vpshufd ymm12, ymm5, 39H\n        vshufps ymm5, ymm14, ymm15, 250\n        vpblendd ymm6, ymm6, ymm5, 0AAH\n        vpunpcklqdq ymm5, ymm15, ymm13\n        vpblendd ymm5, ymm5, ymm14, 88H\n        vpshufd ymm5, ymm5, 78H\n        vpunpckhdq ymm13, ymm13, ymm15\n        vpunpckldq ymm14, ymm14, ymm13\n        vpshufd ymm15, ymm14, 1EH\n        vmovdqa ymm13, ymm6\n        vmovdqa ymm14, ymm5\n        vmovdqa ymm5, ymmword ptr [rsp+40H]\n        vmovdqa ymm6, ymmword ptr [rsp+80H]\n        jmp     roundloop4\nendroundloop4:\n        vpxor   ymm0, ymm0, ymm2\n        vpxor   ymm1, ymm1, ymm3\n        vpxor   ymm8, ymm8, ymm10\n        vpxor   ymm9, ymm9, ymm11\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop4\n        vmovdqu xmmword ptr [rbx], xmm0\n        vmovdqu xmmword ptr [rbx+10H], xmm1\n        vextracti128 xmmword ptr [rbx+20H], ymm0, 01H\n        vextracti128 xmmword ptr [rbx+30H], ymm1, 01H\n        vmovdqu xmmword ptr [rbx+40H], xmm8\n        vmovdqu xmmword ptr [rbx+50H], xmm9\n        vextracti128 xmmword ptr [rbx+60H], ymm8, 01H\n        vextracti128 xmmword ptr [rbx+70H], ymm9, 01H\n        vmovaps xmm8, xmmword ptr [rsp+260H]\n        vmovaps xmm0, xmmword ptr [rsp+220H]\n        vmovaps xmm1, xmmword ptr [rsp+230H]\n        vmovaps xmm2, xmmword ptr [rsp+240H]\n        vmovaps xmm3, xmmword ptr [rsp+250H]\n        vblendvps xmm0, xmm0, xmm1, xmm8\n        vblendvps xmm2, xmm2, xmm3, xmm8\n        vmovaps xmmword ptr [rsp+220H], xmm0\n        vmovaps xmmword ptr [rsp+240H], xmm2\n        add     rbx, 128\n        add     rdi, 32\n        sub     rsi, 4\nfinal3blocks:\n        test    rsi, 2H\n        je      final1blocks\n        vbroadcasti128 ymm0, xmmword ptr [rcx]\n        vbroadcasti128 ymm1, xmmword ptr [rcx+10H]\n        vmovd   xmm13, dword ptr [rsp+220H]\n        vpinsrd xmm13, xmm13, dword ptr [rsp+240H], 1\n        vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2\n        vmovd   xmm14, dword ptr [rsp+224H]\n        vpinsrd xmm14, xmm14, dword ptr [rsp+244H], 1\n        vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2\n        vinserti128 ymm13, ymm13, xmm14, 01H\n        vbroadcasti128 ymm14, xmmword ptr [ROT16]\n        vbroadcasti128 ymm15, xmmword ptr [ROT8]\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\nALIGN   16\ninnerloop2:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        mov     dword ptr [rsp+200H], eax\n        vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV]\n        vpbroadcastd ymm8, dword ptr [rsp+200H]\n        vpblendd ymm3, ymm13, ymm8, 88H\n        vmovups ymm8, ymmword ptr [r8+rdx-40H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-40H], 01H\n        vmovups ymm9, ymmword ptr [r8+rdx-30H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-30H], 01H\n        vshufps ymm4, ymm8, ymm9, 136\n        vshufps ymm5, ymm8, ymm9, 221\n        vmovups ymm8, ymmword ptr [r8+rdx-20H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-20H], 01H\n        vmovups ymm9, ymmword ptr [r8+rdx-10H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-10H], 01H\n        vshufps ymm6, ymm8, ymm9, 136\n        vshufps ymm7, ymm8, ymm9, 221\n        vpshufd ymm6, ymm6, 93H\n        vpshufd ymm7, ymm7, 93H\n        mov     al, 7\nroundloop2:\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm0, ymm0, ymm1\n        vpxor   ymm3, ymm3, ymm0\n        vpshufb ymm3, ymm3, ymm14\n        vpaddd  ymm2, ymm2, ymm3\n        vpxor   ymm1, ymm1, ymm2\n        vpsrld  ymm8, ymm1, 12\n        vpslld  ymm1, ymm1, 20\n        vpor    ymm1, ymm1, ymm8\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm0, ymm0, ymm1\n        vpxor   ymm3, ymm3, ymm0\n        vpshufb ymm3, ymm3, ymm15\n        vpaddd  ymm2, ymm2, ymm3\n        vpxor   ymm1, ymm1, ymm2\n        vpsrld  ymm8, ymm1, 7\n        vpslld  ymm1, ymm1, 25\n        vpor    ymm1, ymm1, ymm8\n        vpshufd ymm0, ymm0, 93H\n        vpshufd ymm3, ymm3, 4EH\n        vpshufd ymm2, ymm2, 39H\n        vpaddd  ymm0, ymm0, ymm6\n        vpaddd  ymm0, ymm0, ymm1\n        vpxor   ymm3, ymm3, ymm0\n        vpshufb ymm3, ymm3, ymm14\n        vpaddd  ymm2, ymm2, ymm3\n        vpxor   ymm1, ymm1, ymm2\n        vpsrld  ymm8, ymm1, 12\n        vpslld  ymm1, ymm1, 20\n        vpor    ymm1, ymm1, ymm8\n        vpaddd  ymm0, ymm0, ymm7\n        vpaddd  ymm0, ymm0, ymm1\n        vpxor   ymm3, ymm3, ymm0\n        vpshufb ymm3, ymm3, ymm15\n        vpaddd  ymm2, ymm2, ymm3\n        vpxor   ymm1, ymm1, ymm2\n        vpsrld  ymm8, ymm1, 7\n        vpslld  ymm1, ymm1, 25\n        vpor    ymm1, ymm1, ymm8\n        vpshufd ymm0, ymm0, 39H\n        vpshufd ymm3, ymm3, 4EH\n        vpshufd ymm2, ymm2, 93H\n        dec     al\n        jz      endroundloop2\n        vshufps ymm8, ymm4, ymm5, 214\n        vpshufd ymm9, ymm4, 0FH\n        vpshufd ymm4, ymm8, 39H\n        vshufps ymm8, ymm6, ymm7, 250\n        vpblendd ymm9, ymm9, ymm8, 0AAH\n        vpunpcklqdq ymm8, ymm7, ymm5\n        vpblendd ymm8, ymm8, ymm6, 88H\n        vpshufd ymm8, ymm8, 78H\n        vpunpckhdq ymm5, ymm5, ymm7\n        vpunpckldq ymm6, ymm6, ymm5\n        vpshufd ymm7, ymm6, 1EH\n        vmovdqa ymm5, ymm9\n        vmovdqa ymm6, ymm8\n        jmp     roundloop2\nendroundloop2:\n        vpxor   ymm0, ymm0, ymm2\n        vpxor   ymm1, ymm1, ymm3\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop2\n        vmovdqu xmmword ptr [rbx], xmm0\n        vmovdqu xmmword ptr [rbx+10H], xmm1\n        vextracti128 xmmword ptr [rbx+20H], ymm0, 01H\n        vextracti128 xmmword ptr [rbx+30H], ymm1, 01H\n        vmovaps ymm8, ymmword ptr [rsp+260H]\n        vmovaps ymm0, ymmword ptr [rsp+220H]\n        vmovups ymm1, ymmword ptr [rsp+228H]\n        vmovaps ymm2, ymmword ptr [rsp+240H]\n        vmovups ymm3, ymmword ptr [rsp+248H]\n        vblendvps ymm0, ymm0, ymm1, ymm8\n        vblendvps ymm2, ymm2, ymm3, ymm8\n        vmovaps ymmword ptr [rsp+220H], ymm0\n        vmovaps ymmword ptr [rsp+240H], ymm2\n        add     rbx, 64\n        add     rdi, 16\n        sub     rsi, 2\nfinal1blocks:\n        test    rsi, 1H\n        je      unwind\n        vmovdqu xmm0, xmmword ptr [rcx]\n        vmovdqu xmm1, xmmword ptr [rcx+10H]\n        vmovd   xmm3, dword ptr [rsp+220H]\n        vpinsrd xmm3, xmm3, dword ptr [rsp+240H], 1\n        vpinsrd xmm13, xmm3, dword ptr [BLAKE3_BLOCK_LEN], 2\n        vmovdqa xmm14, xmmword ptr [ROT16]\n        vmovdqa xmm15, xmmword ptr [ROT8]\n        mov     r8, qword ptr [rdi]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\nALIGN   16\ninnerloop1:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        vmovdqa xmm2, xmmword ptr [BLAKE3_IV]\n        vmovdqa xmm3, xmm13\n        vpinsrd xmm3, xmm3, eax, 3\n        vmovups xmm8, xmmword ptr [r8+rdx-40H]\n        vmovups xmm9, xmmword ptr [r8+rdx-30H]\n        vshufps xmm4, xmm8, xmm9, 136\n        vshufps xmm5, xmm8, xmm9, 221\n        vmovups xmm8, xmmword ptr [r8+rdx-20H]\n        vmovups xmm9, xmmword ptr [r8+rdx-10H]\n        vshufps xmm6, xmm8, xmm9, 136\n        vshufps xmm7, xmm8, xmm9, 221\n        vpshufd xmm6, xmm6, 93H\n        vpshufd xmm7, xmm7, 93H\n        mov     al, 7\nroundloop1:\n        vpaddd  xmm0, xmm0, xmm4\n        vpaddd  xmm0, xmm0, xmm1\n        vpxor   xmm3, xmm3, xmm0\n        vpshufb xmm3, xmm3, xmm14\n        vpaddd  xmm2, xmm2, xmm3\n        vpxor   xmm1, xmm1, xmm2\n        vpsrld  xmm8, xmm1, 12\n        vpslld  xmm1, xmm1, 20\n        vpor    xmm1, xmm1, xmm8\n        vpaddd  xmm0, xmm0, xmm5\n        vpaddd  xmm0, xmm0, xmm1\n        vpxor   xmm3, xmm3, xmm0\n        vpshufb xmm3, xmm3, xmm15\n        vpaddd  xmm2, xmm2, xmm3\n        vpxor   xmm1, xmm1, xmm2\n        vpsrld  xmm8, xmm1, 7\n        vpslld  xmm1, xmm1, 25\n        vpor    xmm1, xmm1, xmm8\n        vpshufd xmm0, xmm0, 93H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 39H\n        vpaddd  xmm0, xmm0, xmm6\n        vpaddd  xmm0, xmm0, xmm1\n        vpxor   xmm3, xmm3, xmm0\n        vpshufb xmm3, xmm3, xmm14\n        vpaddd  xmm2, xmm2, xmm3\n        vpxor   xmm1, xmm1, xmm2\n        vpsrld  xmm8, xmm1, 12\n        vpslld  xmm1, xmm1, 20\n        vpor    xmm1, xmm1, xmm8\n        vpaddd  xmm0, xmm0, xmm7\n        vpaddd  xmm0, xmm0, xmm1\n        vpxor   xmm3, xmm3, xmm0\n        vpshufb xmm3, xmm3, xmm15\n        vpaddd  xmm2, xmm2, xmm3\n        vpxor   xmm1, xmm1, xmm2\n        vpsrld  xmm8, xmm1, 7\n        vpslld  xmm1, xmm1, 25\n        vpor    xmm1, xmm1, xmm8\n        vpshufd xmm0, xmm0, 39H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 93H\n        dec     al\n        jz      endroundloop1\n        vshufps xmm8, xmm4, xmm5, 214\n        vpshufd xmm9, xmm4, 0FH\n        vpshufd xmm4, xmm8, 39H\n        vshufps xmm8, xmm6, xmm7, 250\n        vpblendd xmm9, xmm9, xmm8, 0AAH\n        vpunpcklqdq xmm8, xmm7, xmm5\n        vpblendd xmm8, xmm8, xmm6, 88H\n        vpshufd xmm8, xmm8, 78H\n        vpunpckhdq xmm5, xmm5, xmm7\n        vpunpckldq xmm6, xmm6, xmm5\n        vpshufd xmm7, xmm6, 1EH\n        vmovdqa xmm5, xmm9\n        vmovdqa xmm6, xmm8\n        jmp     roundloop1\nendroundloop1:\n        vpxor   xmm0, xmm0, xmm2\n        vpxor   xmm1, xmm1, xmm3\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop1\n        vmovdqu xmmword ptr [rbx], xmm0\n        vmovdqu xmmword ptr [rbx+10H], xmm1\n        jmp     unwind\n\n_blake3_hash_many_avx2 ENDP\nblake3_hash_many_avx2 ENDP\n_TEXT ENDS\n\n_RDATA SEGMENT READONLY PAGE ALIAS(\".rdata\") 'CONST'\nALIGN   64\nADD0:\n        dd 0, 1, 2, 3, 4, 5, 6, 7\n\nADD1:\n        dd 8 dup (8)\n\nBLAKE3_IV_0:\n        dd 8 dup (6A09E667H)\n\nBLAKE3_IV_1:\n        dd 8 dup (0BB67AE85H)\n\nBLAKE3_IV_2:\n        dd 8 dup (3C6EF372H)\n\nBLAKE3_IV_3:\n        dd 8 dup (0A54FF53AH)\n\nBLAKE3_BLOCK_LEN:\n        dd 8 dup (64)\n\nROT16:\n        db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13\n\nROT8:\n        db 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12\n\nCMP_MSB_MASK:\n        dd 8 dup(80000000H)\n\nBLAKE3_IV:\n        dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH\n\n_RDATA ENDS\nEND\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_avx512_x86-64_windows_msvc.asm",
    "content": "public _blake3_hash_many_avx512\npublic blake3_hash_many_avx512\npublic blake3_compress_in_place_avx512\npublic _blake3_compress_in_place_avx512\npublic blake3_compress_xof_avx512\npublic _blake3_compress_xof_avx512\n\n_TEXT   SEGMENT ALIGN(16) 'CODE'\n\nALIGN   16\nblake3_hash_many_avx512 PROC\n_blake3_hash_many_avx512 PROC\n        push    r15\n        push    r14\n        push    r13\n        push    r12\n        push    rdi\n        push    rsi\n        push    rbx\n        push    rbp\n        mov     rbp, rsp\n        sub     rsp, 304\n        and     rsp, 0FFFFFFFFFFFFFFC0H\n        vmovdqa xmmword ptr [rsp+90H], xmm6\n        vmovdqa xmmword ptr [rsp+0A0H], xmm7\n        vmovdqa xmmword ptr [rsp+0B0H], xmm8\n        vmovdqa xmmword ptr [rsp+0C0H], xmm9\n        vmovdqa xmmword ptr [rsp+0D0H], xmm10\n        vmovdqa xmmword ptr [rsp+0E0H], xmm11\n        vmovdqa xmmword ptr [rsp+0F0H], xmm12\n        vmovdqa xmmword ptr [rsp+100H], xmm13\n        vmovdqa xmmword ptr [rsp+110H], xmm14\n        vmovdqa xmmword ptr [rsp+120H], xmm15\n        mov     rdi, rcx\n        mov     rsi, rdx\n        mov     rdx, r8\n        mov     rcx, r9\n        mov     r8, qword ptr [rbp+68H]\n        movzx   r9, byte ptr [rbp+70H]\n        neg     r9\n        kmovw   k1, r9d\n        vmovd   xmm0, r8d\n        vpbroadcastd ymm0, xmm0\n        shr     r8, 32\n        vmovd   xmm1, r8d\n        vpbroadcastd ymm1, xmm1\n        vmovdqa ymm4, ymm1\n        vmovdqa ymm5, ymm1\n        vpaddd  ymm2, ymm0, ymmword ptr [ADD0]\n        vpaddd  ymm3, ymm0, ymmword ptr [ADD0+32]\n        vpcmpud k2, ymm2, ymm0, 1\n        vpcmpud k3, ymm3, ymm0, 1\n        ; XXX: ml64.exe does not currently understand the syntax. We use a workaround.\n        vpbroadcastd ymm6, dword ptr [ADD1]\n        vpaddd  ymm4 {k2}, ymm4, ymm6\n        vpaddd  ymm5 {k3}, ymm5, ymm6\n        ; vpaddd  ymm4 {k2}, ymm4, dword ptr [ADD1] {1to8}\n        ; vpaddd  ymm5 {k3}, ymm5, dword ptr [ADD1] {1to8}\n        knotw   k2, k1\n        vmovdqa32 ymm2 {k2}, ymm0\n        vmovdqa32 ymm3 {k2}, ymm0\n        vmovdqa32 ymm4 {k2}, ymm1\n        vmovdqa32 ymm5 {k2}, ymm1\n        vmovdqa ymmword ptr [rsp], ymm2\n        vmovdqa ymmword ptr [rsp+20H], ymm3\n        vmovdqa ymmword ptr [rsp+40H], ymm4\n        vmovdqa ymmword ptr [rsp+60H], ymm5\n        shl     rdx, 6\n        mov     qword ptr [rsp+80H], rdx\n        cmp     rsi, 16\n        jc      final15blocks\nouterloop16:\n        vpbroadcastd zmm0, dword ptr [rcx]\n        vpbroadcastd zmm1, dword ptr [rcx+1H*4H]\n        vpbroadcastd zmm2, dword ptr [rcx+2H*4H]\n        vpbroadcastd zmm3, dword ptr [rcx+3H*4H]\n        vpbroadcastd zmm4, dword ptr [rcx+4H*4H]\n        vpbroadcastd zmm5, dword ptr [rcx+5H*4H]\n        vpbroadcastd zmm6, dword ptr [rcx+6H*4H]\n        vpbroadcastd zmm7, dword ptr [rcx+7H*4H]\n        movzx   eax, byte ptr [rbp+78H]\n        movzx   ebx, byte ptr [rbp+80H]\n        or      eax, ebx\n        xor     edx, edx\nALIGN   16\ninnerloop16:\n        movzx   ebx, byte ptr [rbp+88H]\n        or      ebx, eax\n        add     rdx, 64\n        cmp     rdx, qword ptr [rsp+80H]\n        cmove   eax, ebx\n        mov     dword ptr [rsp+88H], eax\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        mov     r12, qword ptr [rdi+40H]\n        mov     r13, qword ptr [rdi+48H]\n        mov     r14, qword ptr [rdi+50H]\n        mov     r15, qword ptr [rdi+58H]\n        vmovdqu32 ymm16, ymmword ptr [rdx+r8-2H*20H]\n        vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-2H*20H], 01H\n        vmovdqu32 ymm17, ymmword ptr [rdx+r9-2H*20H]\n        vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-2H*20H], 01H\n        vpunpcklqdq zmm8, zmm16, zmm17\n        vpunpckhqdq zmm9, zmm16, zmm17\n        vmovdqu32 ymm18, ymmword ptr [rdx+r10-2H*20H]\n        vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-2H*20H], 01H\n        vmovdqu32 ymm19, ymmword ptr [rdx+r11-2H*20H]\n        vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-2H*20H], 01H\n        vpunpcklqdq zmm10, zmm18, zmm19\n        vpunpckhqdq zmm11, zmm18, zmm19\n        mov     r8, qword ptr [rdi+20H]\n        mov     r9, qword ptr [rdi+28H]\n        mov     r10, qword ptr [rdi+30H]\n        mov     r11, qword ptr [rdi+38H]\n        mov     r12, qword ptr [rdi+60H]\n        mov     r13, qword ptr [rdi+68H]\n        mov     r14, qword ptr [rdi+70H]\n        mov     r15, qword ptr [rdi+78H]\n        vmovdqu32 ymm16, ymmword ptr [rdx+r8-2H*20H]\n        vinserti64x4 zmm16, zmm16, ymmword ptr [rdx+r12-2H*20H], 01H\n        vmovdqu32 ymm17, ymmword ptr [rdx+r9-2H*20H]\n        vinserti64x4 zmm17, zmm17, ymmword ptr [rdx+r13-2H*20H], 01H\n        vpunpcklqdq zmm12, zmm16, zmm17\n        vpunpckhqdq zmm13, zmm16, zmm17\n        vmovdqu32 ymm18, ymmword ptr [rdx+r10-2H*20H]\n        vinserti64x4 zmm18, zmm18, ymmword ptr [rdx+r14-2H*20H], 01H\n        vmovdqu32 ymm19, ymmword ptr [rdx+r11-2H*20H]\n        vinserti64x4 zmm19, zmm19, ymmword ptr [rdx+r15-2H*20H], 01H\n        vpunpcklqdq zmm14, zmm18, zmm19\n        vpunpckhqdq zmm15, zmm18, zmm19\n        vmovdqa32 zmm27, zmmword ptr [INDEX0]\n        vmovdqa32 zmm31, zmmword ptr [INDEX1]\n        vshufps zmm16, zmm8, zmm10, 136\n        vshufps zmm17, zmm12, zmm14, 136\n        vmovdqa32 zmm20, zmm16\n        vpermt2d zmm16, zmm27, zmm17\n        vpermt2d zmm20, zmm31, zmm17\n        vshufps zmm17, zmm8, zmm10, 221\n        vshufps zmm30, zmm12, zmm14, 221\n        vmovdqa32 zmm21, zmm17\n        vpermt2d zmm17, zmm27, zmm30\n        vpermt2d zmm21, zmm31, zmm30\n        vshufps zmm18, zmm9, zmm11, 136\n        vshufps zmm8, zmm13, zmm15, 136\n        vmovdqa32 zmm22, zmm18\n        vpermt2d zmm18, zmm27, zmm8\n        vpermt2d zmm22, zmm31, zmm8\n        vshufps zmm19, zmm9, zmm11, 221\n        vshufps zmm8, zmm13, zmm15, 221\n        vmovdqa32 zmm23, zmm19\n        vpermt2d zmm19, zmm27, zmm8\n        vpermt2d zmm23, zmm31, zmm8\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        mov     r12, qword ptr [rdi+40H]\n        mov     r13, qword ptr [rdi+48H]\n        mov     r14, qword ptr [rdi+50H]\n        mov     r15, qword ptr [rdi+58H]\n        vmovdqu32 ymm24, ymmword ptr [r8+rdx-1H*20H]\n        vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-1H*20H], 01H\n        vmovdqu32 ymm25, ymmword ptr [r9+rdx-1H*20H]\n        vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-1H*20H], 01H\n        vpunpcklqdq zmm8, zmm24, zmm25\n        vpunpckhqdq zmm9, zmm24, zmm25\n        vmovdqu32 ymm24, ymmword ptr [r10+rdx-1H*20H]\n        vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-1H*20H], 01H\n        vmovdqu32 ymm25, ymmword ptr [r11+rdx-1H*20H]\n        vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-1H*20H], 01H\n        vpunpcklqdq zmm10, zmm24, zmm25\n        vpunpckhqdq zmm11, zmm24, zmm25\n        prefetcht0 byte ptr [r8+rdx+80H]\n        prefetcht0 byte ptr [r12+rdx+80H]\n        prefetcht0 byte ptr [r9+rdx+80H]\n        prefetcht0 byte ptr [r13+rdx+80H]\n        prefetcht0 byte ptr [r10+rdx+80H]\n        prefetcht0 byte ptr [r14+rdx+80H]\n        prefetcht0 byte ptr [r11+rdx+80H]\n        prefetcht0 byte ptr [r15+rdx+80H]\n        mov     r8, qword ptr [rdi+20H]\n        mov     r9, qword ptr [rdi+28H]\n        mov     r10, qword ptr [rdi+30H]\n        mov     r11, qword ptr [rdi+38H]\n        mov     r12, qword ptr [rdi+60H]\n        mov     r13, qword ptr [rdi+68H]\n        mov     r14, qword ptr [rdi+70H]\n        mov     r15, qword ptr [rdi+78H]\n        vmovdqu32 ymm24, ymmword ptr [r8+rdx-1H*20H]\n        vinserti64x4 zmm24, zmm24, ymmword ptr [r12+rdx-1H*20H], 01H\n        vmovdqu32 ymm25, ymmword ptr [r9+rdx-1H*20H]\n        vinserti64x4 zmm25, zmm25, ymmword ptr [r13+rdx-1H*20H], 01H\n        vpunpcklqdq zmm12, zmm24, zmm25\n        vpunpckhqdq zmm13, zmm24, zmm25\n        vmovdqu32 ymm24, ymmword ptr [r10+rdx-1H*20H]\n        vinserti64x4 zmm24, zmm24, ymmword ptr [r14+rdx-1H*20H], 01H\n        vmovdqu32 ymm25, ymmword ptr [r11+rdx-1H*20H]\n        vinserti64x4 zmm25, zmm25, ymmword ptr [r15+rdx-1H*20H], 01H\n        vpunpcklqdq zmm14, zmm24, zmm25\n        vpunpckhqdq zmm15, zmm24, zmm25\n        prefetcht0 byte  ptr [r8+rdx+80H]\n        prefetcht0 byte ptr [r12+rdx+80H]\n        prefetcht0 byte ptr [r9+rdx+80H]\n        prefetcht0 byte ptr [r13+rdx+80H]\n        prefetcht0 byte ptr [r10+rdx+80H]\n        prefetcht0 byte ptr [r14+rdx+80H]\n        prefetcht0 byte ptr [r11+rdx+80H]\n        prefetcht0 byte ptr [r15+rdx+80H]\n        vshufps zmm24, zmm8, zmm10, 136\n        vshufps zmm30, zmm12, zmm14, 136\n        vmovdqa32 zmm28, zmm24\n        vpermt2d zmm24, zmm27, zmm30\n        vpermt2d zmm28, zmm31, zmm30\n        vshufps zmm25, zmm8, zmm10, 221\n        vshufps zmm30, zmm12, zmm14, 221\n        vmovdqa32 zmm29, zmm25\n        vpermt2d zmm25, zmm27, zmm30\n        vpermt2d zmm29, zmm31, zmm30\n        vshufps zmm26, zmm9, zmm11, 136\n        vshufps zmm8, zmm13, zmm15, 136\n        vmovdqa32 zmm30, zmm26\n        vpermt2d zmm26, zmm27, zmm8\n        vpermt2d zmm30, zmm31, zmm8\n        vshufps zmm8, zmm9, zmm11, 221\n        vshufps zmm10, zmm13, zmm15, 221\n        vpermi2d zmm27, zmm8, zmm10\n        vpermi2d zmm31, zmm8, zmm10\n        vpbroadcastd zmm8, dword ptr [BLAKE3_IV_0]\n        vpbroadcastd zmm9, dword ptr [BLAKE3_IV_1]\n        vpbroadcastd zmm10, dword ptr [BLAKE3_IV_2]\n        vpbroadcastd zmm11, dword ptr [BLAKE3_IV_3]\n        vmovdqa32 zmm12, zmmword ptr [rsp]\n        vmovdqa32 zmm13, zmmword ptr [rsp+1H*40H]\n        vpbroadcastd zmm14, dword ptr [BLAKE3_BLOCK_LEN]\n        vpbroadcastd zmm15, dword ptr [rsp+22H*4H]\n        vpaddd  zmm0, zmm0, zmm16\n        vpaddd  zmm1, zmm1, zmm18\n        vpaddd  zmm2, zmm2, zmm20\n        vpaddd  zmm3, zmm3, zmm22\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vprord  zmm15, zmm15, 16\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 12\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vpaddd  zmm0, zmm0, zmm17\n        vpaddd  zmm1, zmm1, zmm19\n        vpaddd  zmm2, zmm2, zmm21\n        vpaddd  zmm3, zmm3, zmm23\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vprord  zmm15, zmm15, 8\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 7\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vpaddd  zmm0, zmm0, zmm24\n        vpaddd  zmm1, zmm1, zmm26\n        vpaddd  zmm2, zmm2, zmm28\n        vpaddd  zmm3, zmm3, zmm30\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 16\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vprord  zmm4, zmm4, 12\n        vpaddd  zmm0, zmm0, zmm25\n        vpaddd  zmm1, zmm1, zmm27\n        vpaddd  zmm2, zmm2, zmm29\n        vpaddd  zmm3, zmm3, zmm31\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 8\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vprord  zmm4, zmm4, 7\n        vpaddd  zmm0, zmm0, zmm18\n        vpaddd  zmm1, zmm1, zmm19\n        vpaddd  zmm2, zmm2, zmm23\n        vpaddd  zmm3, zmm3, zmm20\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vprord  zmm15, zmm15, 16\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 12\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vpaddd  zmm0, zmm0, zmm22\n        vpaddd  zmm1, zmm1, zmm26\n        vpaddd  zmm2, zmm2, zmm16\n        vpaddd  zmm3, zmm3, zmm29\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vprord  zmm15, zmm15, 8\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 7\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vpaddd  zmm0, zmm0, zmm17\n        vpaddd  zmm1, zmm1, zmm28\n        vpaddd  zmm2, zmm2, zmm25\n        vpaddd  zmm3, zmm3, zmm31\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 16\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vprord  zmm4, zmm4, 12\n        vpaddd  zmm0, zmm0, zmm27\n        vpaddd  zmm1, zmm1, zmm21\n        vpaddd  zmm2, zmm2, zmm30\n        vpaddd  zmm3, zmm3, zmm24\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 8\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vprord  zmm4, zmm4, 7\n        vpaddd  zmm0, zmm0, zmm19\n        vpaddd  zmm1, zmm1, zmm26\n        vpaddd  zmm2, zmm2, zmm29\n        vpaddd  zmm3, zmm3, zmm23\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vprord  zmm15, zmm15, 16\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 12\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vpaddd  zmm0, zmm0, zmm20\n        vpaddd  zmm1, zmm1, zmm28\n        vpaddd  zmm2, zmm2, zmm18\n        vpaddd  zmm3, zmm3, zmm30\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vprord  zmm15, zmm15, 8\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 7\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vpaddd  zmm0, zmm0, zmm22\n        vpaddd  zmm1, zmm1, zmm25\n        vpaddd  zmm2, zmm2, zmm27\n        vpaddd  zmm3, zmm3, zmm24\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 16\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vprord  zmm4, zmm4, 12\n        vpaddd  zmm0, zmm0, zmm21\n        vpaddd  zmm1, zmm1, zmm16\n        vpaddd  zmm2, zmm2, zmm31\n        vpaddd  zmm3, zmm3, zmm17\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 8\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vprord  zmm4, zmm4, 7\n        vpaddd  zmm0, zmm0, zmm26\n        vpaddd  zmm1, zmm1, zmm28\n        vpaddd  zmm2, zmm2, zmm30\n        vpaddd  zmm3, zmm3, zmm29\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vprord  zmm15, zmm15, 16\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 12\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vpaddd  zmm0, zmm0, zmm23\n        vpaddd  zmm1, zmm1, zmm25\n        vpaddd  zmm2, zmm2, zmm19\n        vpaddd  zmm3, zmm3, zmm31\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vprord  zmm15, zmm15, 8\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 7\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vpaddd  zmm0, zmm0, zmm20\n        vpaddd  zmm1, zmm1, zmm27\n        vpaddd  zmm2, zmm2, zmm21\n        vpaddd  zmm3, zmm3, zmm17\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 16\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vprord  zmm4, zmm4, 12\n        vpaddd  zmm0, zmm0, zmm16\n        vpaddd  zmm1, zmm1, zmm18\n        vpaddd  zmm2, zmm2, zmm24\n        vpaddd  zmm3, zmm3, zmm22\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 8\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vprord  zmm4, zmm4, 7\n        vpaddd  zmm0, zmm0, zmm28\n        vpaddd  zmm1, zmm1, zmm25\n        vpaddd  zmm2, zmm2, zmm31\n        vpaddd  zmm3, zmm3, zmm30\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vprord  zmm15, zmm15, 16\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 12\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vpaddd  zmm0, zmm0, zmm29\n        vpaddd  zmm1, zmm1, zmm27\n        vpaddd  zmm2, zmm2, zmm26\n        vpaddd  zmm3, zmm3, zmm24\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vprord  zmm15, zmm15, 8\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 7\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vpaddd  zmm0, zmm0, zmm23\n        vpaddd  zmm1, zmm1, zmm21\n        vpaddd  zmm2, zmm2, zmm16\n        vpaddd  zmm3, zmm3, zmm22\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 16\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vprord  zmm4, zmm4, 12\n        vpaddd  zmm0, zmm0, zmm18\n        vpaddd  zmm1, zmm1, zmm19\n        vpaddd  zmm2, zmm2, zmm17\n        vpaddd  zmm3, zmm3, zmm20\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 8\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vprord  zmm4, zmm4, 7\n        vpaddd  zmm0, zmm0, zmm25\n        vpaddd  zmm1, zmm1, zmm27\n        vpaddd  zmm2, zmm2, zmm24\n        vpaddd  zmm3, zmm3, zmm31\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vprord  zmm15, zmm15, 16\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 12\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vpaddd  zmm0, zmm0, zmm30\n        vpaddd  zmm1, zmm1, zmm21\n        vpaddd  zmm2, zmm2, zmm28\n        vpaddd  zmm3, zmm3, zmm17\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vprord  zmm15, zmm15, 8\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 7\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vpaddd  zmm0, zmm0, zmm29\n        vpaddd  zmm1, zmm1, zmm16\n        vpaddd  zmm2, zmm2, zmm18\n        vpaddd  zmm3, zmm3, zmm20\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 16\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vprord  zmm4, zmm4, 12\n        vpaddd  zmm0, zmm0, zmm19\n        vpaddd  zmm1, zmm1, zmm26\n        vpaddd  zmm2, zmm2, zmm22\n        vpaddd  zmm3, zmm3, zmm23\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 8\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vprord  zmm4, zmm4, 7\n        vpaddd  zmm0, zmm0, zmm27\n        vpaddd  zmm1, zmm1, zmm21\n        vpaddd  zmm2, zmm2, zmm17\n        vpaddd  zmm3, zmm3, zmm24\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vprord  zmm15, zmm15, 16\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 12\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vpaddd  zmm0, zmm0, zmm31\n        vpaddd  zmm1, zmm1, zmm16\n        vpaddd  zmm2, zmm2, zmm25\n        vpaddd  zmm3, zmm3, zmm22\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm1, zmm1, zmm5\n        vpaddd  zmm2, zmm2, zmm6\n        vpaddd  zmm3, zmm3, zmm7\n        vpxord  zmm12, zmm12, zmm0\n        vpxord  zmm13, zmm13, zmm1\n        vpxord  zmm14, zmm14, zmm2\n        vpxord  zmm15, zmm15, zmm3\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vprord  zmm15, zmm15, 8\n        vpaddd  zmm8, zmm8, zmm12\n        vpaddd  zmm9, zmm9, zmm13\n        vpaddd  zmm10, zmm10, zmm14\n        vpaddd  zmm11, zmm11, zmm15\n        vpxord  zmm4, zmm4, zmm8\n        vpxord  zmm5, zmm5, zmm9\n        vpxord  zmm6, zmm6, zmm10\n        vpxord  zmm7, zmm7, zmm11\n        vprord  zmm4, zmm4, 7\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vpaddd  zmm0, zmm0, zmm30\n        vpaddd  zmm1, zmm1, zmm18\n        vpaddd  zmm2, zmm2, zmm19\n        vpaddd  zmm3, zmm3, zmm23\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 16\n        vprord  zmm12, zmm12, 16\n        vprord  zmm13, zmm13, 16\n        vprord  zmm14, zmm14, 16\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 12\n        vprord  zmm6, zmm6, 12\n        vprord  zmm7, zmm7, 12\n        vprord  zmm4, zmm4, 12\n        vpaddd  zmm0, zmm0, zmm26\n        vpaddd  zmm1, zmm1, zmm28\n        vpaddd  zmm2, zmm2, zmm20\n        vpaddd  zmm3, zmm3, zmm29\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm1, zmm1, zmm6\n        vpaddd  zmm2, zmm2, zmm7\n        vpaddd  zmm3, zmm3, zmm4\n        vpxord  zmm15, zmm15, zmm0\n        vpxord  zmm12, zmm12, zmm1\n        vpxord  zmm13, zmm13, zmm2\n        vpxord  zmm14, zmm14, zmm3\n        vprord  zmm15, zmm15, 8\n        vprord  zmm12, zmm12, 8\n        vprord  zmm13, zmm13, 8\n        vprord  zmm14, zmm14, 8\n        vpaddd  zmm10, zmm10, zmm15\n        vpaddd  zmm11, zmm11, zmm12\n        vpaddd  zmm8, zmm8, zmm13\n        vpaddd  zmm9, zmm9, zmm14\n        vpxord  zmm5, zmm5, zmm10\n        vpxord  zmm6, zmm6, zmm11\n        vpxord  zmm7, zmm7, zmm8\n        vpxord  zmm4, zmm4, zmm9\n        vprord  zmm5, zmm5, 7\n        vprord  zmm6, zmm6, 7\n        vprord  zmm7, zmm7, 7\n        vprord  zmm4, zmm4, 7\n        vpxord  zmm0, zmm0, zmm8\n        vpxord  zmm1, zmm1, zmm9\n        vpxord  zmm2, zmm2, zmm10\n        vpxord  zmm3, zmm3, zmm11\n        vpxord  zmm4, zmm4, zmm12\n        vpxord  zmm5, zmm5, zmm13\n        vpxord  zmm6, zmm6, zmm14\n        vpxord  zmm7, zmm7, zmm15\n        movzx   eax, byte ptr [rbp+78H]\n        jne     innerloop16\n        mov     rbx, qword ptr [rbp+90H]\n        vpunpckldq zmm16, zmm0, zmm1\n        vpunpckhdq zmm17, zmm0, zmm1\n        vpunpckldq zmm18, zmm2, zmm3\n        vpunpckhdq zmm19, zmm2, zmm3\n        vpunpckldq zmm20, zmm4, zmm5\n        vpunpckhdq zmm21, zmm4, zmm5\n        vpunpckldq zmm22, zmm6, zmm7\n        vpunpckhdq zmm23, zmm6, zmm7\n        vpunpcklqdq zmm0, zmm16, zmm18\n        vpunpckhqdq zmm1, zmm16, zmm18\n        vpunpcklqdq zmm2, zmm17, zmm19\n        vpunpckhqdq zmm3, zmm17, zmm19\n        vpunpcklqdq zmm4, zmm20, zmm22\n        vpunpckhqdq zmm5, zmm20, zmm22\n        vpunpcklqdq zmm6, zmm21, zmm23\n        vpunpckhqdq zmm7, zmm21, zmm23\n        vshufi32x4 zmm16, zmm0, zmm4, 88H\n        vshufi32x4 zmm17, zmm1, zmm5, 88H\n        vshufi32x4 zmm18, zmm2, zmm6, 88H\n        vshufi32x4 zmm19, zmm3, zmm7, 88H\n        vshufi32x4 zmm20, zmm0, zmm4, 0DDH\n        vshufi32x4 zmm21, zmm1, zmm5, 0DDH\n        vshufi32x4 zmm22, zmm2, zmm6, 0DDH\n        vshufi32x4 zmm23, zmm3, zmm7, 0DDH\n        vshufi32x4 zmm0, zmm16, zmm17, 88H\n        vshufi32x4 zmm1, zmm18, zmm19, 88H\n        vshufi32x4 zmm2, zmm20, zmm21, 88H\n        vshufi32x4 zmm3, zmm22, zmm23, 88H\n        vshufi32x4 zmm4, zmm16, zmm17, 0DDH\n        vshufi32x4 zmm5, zmm18, zmm19, 0DDH\n        vshufi32x4 zmm6, zmm20, zmm21, 0DDH\n        vshufi32x4 zmm7, zmm22, zmm23, 0DDH\n        vmovdqu32 zmmword ptr [rbx], zmm0\n        vmovdqu32 zmmword ptr [rbx+1H*40H], zmm1\n        vmovdqu32 zmmword ptr [rbx+2H*40H], zmm2\n        vmovdqu32 zmmword ptr [rbx+3H*40H], zmm3\n        vmovdqu32 zmmword ptr [rbx+4H*40H], zmm4\n        vmovdqu32 zmmword ptr [rbx+5H*40H], zmm5\n        vmovdqu32 zmmword ptr [rbx+6H*40H], zmm6\n        vmovdqu32 zmmword ptr [rbx+7H*40H], zmm7\n        vmovdqa32 zmm0, zmmword ptr [rsp]\n        vmovdqa32 zmm1, zmmword ptr [rsp+1H*40H]\n        vmovdqa32 zmm2, zmm0\n        ; XXX: ml64.exe does not currently understand the syntax. We use a workaround.\n        vpbroadcastd zmm4, dword ptr [ADD16]\n        vpbroadcastd zmm5, dword ptr [ADD1]\n        vpaddd  zmm2{k1}, zmm0, zmm4\n        ; vpaddd  zmm2{k1}, zmm0, dword ptr [ADD16] ; {1to16}\n        vpcmpud k2, zmm2, zmm0, 1\n        vpaddd  zmm1 {k2}, zmm1, zmm5\n        ; vpaddd  zmm1 {k2}, zmm1, dword ptr [ADD1] ; {1to16}\n        vmovdqa32 zmmword ptr [rsp], zmm2\n        vmovdqa32 zmmword ptr [rsp+1H*40H], zmm1\n        add     rdi, 128\n        add     rbx, 512\n        mov     qword ptr [rbp+90H], rbx\n        sub     rsi, 16\n        cmp     rsi, 16\n        jnc     outerloop16\n        test    rsi, rsi\n        jne     final15blocks\nunwind:\n        vzeroupper\n        vmovdqa xmm6, xmmword ptr [rsp+90H]\n        vmovdqa xmm7, xmmword ptr [rsp+0A0H]\n        vmovdqa xmm8, xmmword ptr [rsp+0B0H]\n        vmovdqa xmm9, xmmword ptr [rsp+0C0H]\n        vmovdqa xmm10, xmmword ptr [rsp+0D0H]\n        vmovdqa xmm11, xmmword ptr [rsp+0E0H]\n        vmovdqa xmm12, xmmword ptr [rsp+0F0H]\n        vmovdqa xmm13, xmmword ptr [rsp+100H]\n        vmovdqa xmm14, xmmword ptr [rsp+110H]\n        vmovdqa xmm15, xmmword ptr [rsp+120H]\n        mov     rsp, rbp\n        pop     rbp\n        pop     rbx\n        pop     rsi\n        pop     rdi\n        pop     r12\n        pop     r13\n        pop     r14\n        pop     r15\n        ret\nALIGN   16\nfinal15blocks:\n        test    esi, 8H\n        je      final7blocks\n        vpbroadcastd ymm0, dword ptr [rcx]\n        vpbroadcastd ymm1, dword ptr [rcx+4H]\n        vpbroadcastd ymm2, dword ptr [rcx+8H]\n        vpbroadcastd ymm3, dword ptr [rcx+0CH]\n        vpbroadcastd ymm4, dword ptr [rcx+10H]\n        vpbroadcastd ymm5, dword ptr [rcx+14H]\n        vpbroadcastd ymm6, dword ptr [rcx+18H]\n        vpbroadcastd ymm7, dword ptr [rcx+1CH]\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        mov     r12, qword ptr [rdi+20H]\n        mov     r13, qword ptr [rdi+28H]\n        mov     r14, qword ptr [rdi+30H]\n        mov     r15, qword ptr [rdi+38H]\n        movzx   eax, byte ptr [rbp+78H]\n        movzx   ebx, byte ptr [rbp+80H]\n        or      eax, ebx\n        xor     edx, edx\ninnerloop8:\n        movzx   ebx, byte ptr [rbp+88H]\n        or      ebx, eax\n        add     rdx, 64\n        cmp     rdx, qword ptr [rsp+80H]\n        cmove   eax, ebx\n        mov     dword ptr [rsp+88H], eax\n        vmovups xmm8, xmmword ptr [r8+rdx-40H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-40H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-40H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-40H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-40H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-40H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-40H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-40H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm16, ymm12, ymm14, 136\n        vshufps ymm17, ymm12, ymm14, 221\n        vshufps ymm18, ymm13, ymm15, 136\n        vshufps ymm19, ymm13, ymm15, 221\n        vmovups xmm8, xmmword ptr [r8+rdx-30H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-30H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-30H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-30H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-30H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-30H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-30H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-30H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm20, ymm12, ymm14, 136\n        vshufps ymm21, ymm12, ymm14, 221\n        vshufps ymm22, ymm13, ymm15, 136\n        vshufps ymm23, ymm13, ymm15, 221\n        vmovups xmm8, xmmword ptr [r8+rdx-20H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-20H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-20H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-20H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-20H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-20H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-20H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-20H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm24, ymm12, ymm14, 136\n        vshufps ymm25, ymm12, ymm14, 221\n        vshufps ymm26, ymm13, ymm15, 136\n        vshufps ymm27, ymm13, ymm15, 221\n        vmovups xmm8, xmmword ptr [r8+rdx-10H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r12+rdx-10H], 01H\n        vmovups xmm9, xmmword ptr [r9+rdx-10H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r13+rdx-10H], 01H\n        vunpcklpd ymm12, ymm8, ymm9\n        vunpckhpd ymm13, ymm8, ymm9\n        vmovups xmm10, xmmword ptr [r10+rdx-10H]\n        vinsertf128 ymm10, ymm10, xmmword ptr [r14+rdx-10H], 01H\n        vmovups xmm11, xmmword ptr [r11+rdx-10H]\n        vinsertf128 ymm11, ymm11, xmmword ptr [r15+rdx-10H], 01H\n        vunpcklpd ymm14, ymm10, ymm11\n        vunpckhpd ymm15, ymm10, ymm11\n        vshufps ymm28, ymm12, ymm14, 136\n        vshufps ymm29, ymm12, ymm14, 221\n        vshufps ymm30, ymm13, ymm15, 136\n        vshufps ymm31, ymm13, ymm15, 221\n        vpbroadcastd ymm8, dword ptr [BLAKE3_IV_0]\n        vpbroadcastd ymm9, dword ptr [BLAKE3_IV_1]\n        vpbroadcastd ymm10, dword ptr [BLAKE3_IV_2]\n        vpbroadcastd ymm11, dword ptr [BLAKE3_IV_3]\n        vmovdqa ymm12, ymmword ptr [rsp]\n        vmovdqa ymm13, ymmword ptr [rsp+40H]\n        vpbroadcastd ymm14, dword ptr [BLAKE3_BLOCK_LEN]\n        vpbroadcastd ymm15, dword ptr [rsp+88H]\n        vpaddd  ymm0, ymm0, ymm16\n        vpaddd  ymm1, ymm1, ymm18\n        vpaddd  ymm2, ymm2, ymm20\n        vpaddd  ymm3, ymm3, ymm22\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vprord  ymm15, ymm15, 16\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 12\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vpaddd  ymm0, ymm0, ymm17\n        vpaddd  ymm1, ymm1, ymm19\n        vpaddd  ymm2, ymm2, ymm21\n        vpaddd  ymm3, ymm3, ymm23\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vprord  ymm15, ymm15, 8\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 7\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vpaddd  ymm0, ymm0, ymm24\n        vpaddd  ymm1, ymm1, ymm26\n        vpaddd  ymm2, ymm2, ymm28\n        vpaddd  ymm3, ymm3, ymm30\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 16\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vprord  ymm4, ymm4, 12\n        vpaddd  ymm0, ymm0, ymm25\n        vpaddd  ymm1, ymm1, ymm27\n        vpaddd  ymm2, ymm2, ymm29\n        vpaddd  ymm3, ymm3, ymm31\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 8\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vprord  ymm4, ymm4, 7\n        vpaddd  ymm0, ymm0, ymm18\n        vpaddd  ymm1, ymm1, ymm19\n        vpaddd  ymm2, ymm2, ymm23\n        vpaddd  ymm3, ymm3, ymm20\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vprord  ymm15, ymm15, 16\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 12\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vpaddd  ymm0, ymm0, ymm22\n        vpaddd  ymm1, ymm1, ymm26\n        vpaddd  ymm2, ymm2, ymm16\n        vpaddd  ymm3, ymm3, ymm29\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vprord  ymm15, ymm15, 8\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 7\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vpaddd  ymm0, ymm0, ymm17\n        vpaddd  ymm1, ymm1, ymm28\n        vpaddd  ymm2, ymm2, ymm25\n        vpaddd  ymm3, ymm3, ymm31\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 16\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vprord  ymm4, ymm4, 12\n        vpaddd  ymm0, ymm0, ymm27\n        vpaddd  ymm1, ymm1, ymm21\n        vpaddd  ymm2, ymm2, ymm30\n        vpaddd  ymm3, ymm3, ymm24\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 8\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vprord  ymm4, ymm4, 7\n        vpaddd  ymm0, ymm0, ymm19\n        vpaddd  ymm1, ymm1, ymm26\n        vpaddd  ymm2, ymm2, ymm29\n        vpaddd  ymm3, ymm3, ymm23\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vprord  ymm15, ymm15, 16\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 12\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vpaddd  ymm0, ymm0, ymm20\n        vpaddd  ymm1, ymm1, ymm28\n        vpaddd  ymm2, ymm2, ymm18\n        vpaddd  ymm3, ymm3, ymm30\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vprord  ymm15, ymm15, 8\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 7\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vpaddd  ymm0, ymm0, ymm22\n        vpaddd  ymm1, ymm1, ymm25\n        vpaddd  ymm2, ymm2, ymm27\n        vpaddd  ymm3, ymm3, ymm24\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 16\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vprord  ymm4, ymm4, 12\n        vpaddd  ymm0, ymm0, ymm21\n        vpaddd  ymm1, ymm1, ymm16\n        vpaddd  ymm2, ymm2, ymm31\n        vpaddd  ymm3, ymm3, ymm17\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 8\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vprord  ymm4, ymm4, 7\n        vpaddd  ymm0, ymm0, ymm26\n        vpaddd  ymm1, ymm1, ymm28\n        vpaddd  ymm2, ymm2, ymm30\n        vpaddd  ymm3, ymm3, ymm29\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vprord  ymm15, ymm15, 16\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 12\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vpaddd  ymm0, ymm0, ymm23\n        vpaddd  ymm1, ymm1, ymm25\n        vpaddd  ymm2, ymm2, ymm19\n        vpaddd  ymm3, ymm3, ymm31\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vprord  ymm15, ymm15, 8\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 7\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vpaddd  ymm0, ymm0, ymm20\n        vpaddd  ymm1, ymm1, ymm27\n        vpaddd  ymm2, ymm2, ymm21\n        vpaddd  ymm3, ymm3, ymm17\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 16\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vprord  ymm4, ymm4, 12\n        vpaddd  ymm0, ymm0, ymm16\n        vpaddd  ymm1, ymm1, ymm18\n        vpaddd  ymm2, ymm2, ymm24\n        vpaddd  ymm3, ymm3, ymm22\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 8\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vprord  ymm4, ymm4, 7\n        vpaddd  ymm0, ymm0, ymm28\n        vpaddd  ymm1, ymm1, ymm25\n        vpaddd  ymm2, ymm2, ymm31\n        vpaddd  ymm3, ymm3, ymm30\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vprord  ymm15, ymm15, 16\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 12\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vpaddd  ymm0, ymm0, ymm29\n        vpaddd  ymm1, ymm1, ymm27\n        vpaddd  ymm2, ymm2, ymm26\n        vpaddd  ymm3, ymm3, ymm24\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vprord  ymm15, ymm15, 8\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 7\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vpaddd  ymm0, ymm0, ymm23\n        vpaddd  ymm1, ymm1, ymm21\n        vpaddd  ymm2, ymm2, ymm16\n        vpaddd  ymm3, ymm3, ymm22\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 16\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vprord  ymm4, ymm4, 12\n        vpaddd  ymm0, ymm0, ymm18\n        vpaddd  ymm1, ymm1, ymm19\n        vpaddd  ymm2, ymm2, ymm17\n        vpaddd  ymm3, ymm3, ymm20\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 8\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vprord  ymm4, ymm4, 7\n        vpaddd  ymm0, ymm0, ymm25\n        vpaddd  ymm1, ymm1, ymm27\n        vpaddd  ymm2, ymm2, ymm24\n        vpaddd  ymm3, ymm3, ymm31\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vprord  ymm15, ymm15, 16\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 12\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vpaddd  ymm0, ymm0, ymm30\n        vpaddd  ymm1, ymm1, ymm21\n        vpaddd  ymm2, ymm2, ymm28\n        vpaddd  ymm3, ymm3, ymm17\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vprord  ymm15, ymm15, 8\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 7\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vpaddd  ymm0, ymm0, ymm29\n        vpaddd  ymm1, ymm1, ymm16\n        vpaddd  ymm2, ymm2, ymm18\n        vpaddd  ymm3, ymm3, ymm20\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 16\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vprord  ymm4, ymm4, 12\n        vpaddd  ymm0, ymm0, ymm19\n        vpaddd  ymm1, ymm1, ymm26\n        vpaddd  ymm2, ymm2, ymm22\n        vpaddd  ymm3, ymm3, ymm23\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 8\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vprord  ymm4, ymm4, 7\n        vpaddd  ymm0, ymm0, ymm27\n        vpaddd  ymm1, ymm1, ymm21\n        vpaddd  ymm2, ymm2, ymm17\n        vpaddd  ymm3, ymm3, ymm24\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vprord  ymm15, ymm15, 16\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 12\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vpaddd  ymm0, ymm0, ymm31\n        vpaddd  ymm1, ymm1, ymm16\n        vpaddd  ymm2, ymm2, ymm25\n        vpaddd  ymm3, ymm3, ymm22\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm1, ymm1, ymm5\n        vpaddd  ymm2, ymm2, ymm6\n        vpaddd  ymm3, ymm3, ymm7\n        vpxord  ymm12, ymm12, ymm0\n        vpxord  ymm13, ymm13, ymm1\n        vpxord  ymm14, ymm14, ymm2\n        vpxord  ymm15, ymm15, ymm3\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vprord  ymm15, ymm15, 8\n        vpaddd  ymm8, ymm8, ymm12\n        vpaddd  ymm9, ymm9, ymm13\n        vpaddd  ymm10, ymm10, ymm14\n        vpaddd  ymm11, ymm11, ymm15\n        vpxord  ymm4, ymm4, ymm8\n        vpxord  ymm5, ymm5, ymm9\n        vpxord  ymm6, ymm6, ymm10\n        vpxord  ymm7, ymm7, ymm11\n        vprord  ymm4, ymm4, 7\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vpaddd  ymm0, ymm0, ymm30\n        vpaddd  ymm1, ymm1, ymm18\n        vpaddd  ymm2, ymm2, ymm19\n        vpaddd  ymm3, ymm3, ymm23\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 16\n        vprord  ymm12, ymm12, 16\n        vprord  ymm13, ymm13, 16\n        vprord  ymm14, ymm14, 16\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 12\n        vprord  ymm6, ymm6, 12\n        vprord  ymm7, ymm7, 12\n        vprord  ymm4, ymm4, 12\n        vpaddd  ymm0, ymm0, ymm26\n        vpaddd  ymm1, ymm1, ymm28\n        vpaddd  ymm2, ymm2, ymm20\n        vpaddd  ymm3, ymm3, ymm29\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm1, ymm1, ymm6\n        vpaddd  ymm2, ymm2, ymm7\n        vpaddd  ymm3, ymm3, ymm4\n        vpxord  ymm15, ymm15, ymm0\n        vpxord  ymm12, ymm12, ymm1\n        vpxord  ymm13, ymm13, ymm2\n        vpxord  ymm14, ymm14, ymm3\n        vprord  ymm15, ymm15, 8\n        vprord  ymm12, ymm12, 8\n        vprord  ymm13, ymm13, 8\n        vprord  ymm14, ymm14, 8\n        vpaddd  ymm10, ymm10, ymm15\n        vpaddd  ymm11, ymm11, ymm12\n        vpaddd  ymm8, ymm8, ymm13\n        vpaddd  ymm9, ymm9, ymm14\n        vpxord  ymm5, ymm5, ymm10\n        vpxord  ymm6, ymm6, ymm11\n        vpxord  ymm7, ymm7, ymm8\n        vpxord  ymm4, ymm4, ymm9\n        vprord  ymm5, ymm5, 7\n        vprord  ymm6, ymm6, 7\n        vprord  ymm7, ymm7, 7\n        vprord  ymm4, ymm4, 7\n        vpxor   ymm0, ymm0, ymm8\n        vpxor   ymm1, ymm1, ymm9\n        vpxor   ymm2, ymm2, ymm10\n        vpxor   ymm3, ymm3, ymm11\n        vpxor   ymm4, ymm4, ymm12\n        vpxor   ymm5, ymm5, ymm13\n        vpxor   ymm6, ymm6, ymm14\n        vpxor   ymm7, ymm7, ymm15\n        movzx   eax, byte ptr [rbp+78H]\n        jne     innerloop8\n        mov     rbx, qword ptr [rbp+90H]\n        vunpcklps ymm8, ymm0, ymm1\n        vunpcklps ymm9, ymm2, ymm3\n        vunpckhps ymm10, ymm0, ymm1\n        vunpcklps ymm11, ymm4, ymm5\n        vunpcklps ymm0, ymm6, ymm7\n        vshufps ymm12, ymm8, ymm9, 78\n        vblendps ymm1, ymm8, ymm12, 0CCH\n        vshufps ymm8, ymm11, ymm0, 78\n        vunpckhps ymm13, ymm2, ymm3\n        vblendps ymm2, ymm11, ymm8, 0CCH\n        vblendps ymm3, ymm12, ymm9, 0CCH\n        vperm2f128 ymm12, ymm1, ymm2, 20H\n        vmovups ymmword ptr [rbx], ymm12\n        vunpckhps ymm14, ymm4, ymm5\n        vblendps ymm4, ymm8, ymm0, 0CCH\n        vunpckhps ymm15, ymm6, ymm7\n        vperm2f128 ymm7, ymm3, ymm4, 20H\n        vmovups ymmword ptr [rbx+20H], ymm7\n        vshufps ymm5, ymm10, ymm13, 78\n        vblendps ymm6, ymm5, ymm13, 0CCH\n        vshufps ymm13, ymm14, ymm15, 78\n        vblendps ymm10, ymm10, ymm5, 0CCH\n        vblendps ymm14, ymm14, ymm13, 0CCH\n        vperm2f128 ymm8, ymm10, ymm14, 20H\n        vmovups ymmword ptr [rbx+40H], ymm8\n        vblendps ymm15, ymm13, ymm15, 0CCH\n        vperm2f128 ymm13, ymm6, ymm15, 20H\n        vmovups ymmword ptr [rbx+60H], ymm13\n        vperm2f128 ymm9, ymm1, ymm2, 31H\n        vperm2f128 ymm11, ymm3, ymm4, 31H\n        vmovups ymmword ptr [rbx+80H], ymm9\n        vperm2f128 ymm14, ymm10, ymm14, 31H\n        vperm2f128 ymm15, ymm6, ymm15, 31H\n        vmovups ymmword ptr [rbx+0A0H], ymm11\n        vmovups ymmword ptr [rbx+0C0H], ymm14\n        vmovups ymmword ptr [rbx+0E0H], ymm15\n        vmovdqa ymm0, ymmword ptr [rsp]\n        vmovdqa ymm2, ymmword ptr [rsp+40H]\n        vmovdqa32 ymm0 {k1}, ymmword ptr [rsp+1H*20H]\n        vmovdqa32 ymm2 {k1}, ymmword ptr [rsp+3H*20H]\n        vmovdqa ymmword ptr [rsp], ymm0\n        vmovdqa ymmword ptr [rsp+40H], ymm2\n        add     rbx, 256\n        mov     qword ptr [rbp+90H], rbx\n        add     rdi, 64\n        sub     rsi, 8\nfinal7blocks:\n        mov     rbx, qword ptr [rbp+90H]\n        mov     r15, qword ptr [rsp+80H]\n        movzx   r13, byte ptr [rbp+78H]\n        movzx   r12, byte ptr [rbp+88H]\n        test    esi, 4H\n        je      final3blocks\n        vbroadcasti32x4 zmm0, xmmword ptr [rcx]\n        vbroadcasti32x4 zmm1, xmmword ptr [rcx+1H*10H]\n        vmovdqa xmm12, xmmword ptr [rsp]\n        vmovdqa xmm13, xmmword ptr [rsp+40H]\n        vpunpckldq xmm14, xmm12, xmm13\n        vpunpckhdq xmm15, xmm12, xmm13\n        vpermq  ymm14, ymm14, 0DCH\n        vpermq  ymm15, ymm15, 0DCH\n        vpbroadcastd zmm12, dword ptr [BLAKE3_BLOCK_LEN]\n        vinserti64x4 zmm13, zmm14, ymm15, 01H\n        mov     eax, 17476\n        kmovw   k2, eax\n        vpblendmd zmm13 {k2}, zmm13, zmm12\n        vbroadcasti32x4 zmm15, xmmword ptr [BLAKE3_IV]\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        mov     eax, 43690\n        kmovw   k3, eax\n        mov     eax, 34952\n        kmovw   k4, eax\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\nALIGN   16\ninnerloop4:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        mov     dword ptr [rsp+88H], eax\n        vmovdqa32 zmm2, zmm15\n        vpbroadcastd zmm8, dword ptr [rsp+22H*4H]\n        vpblendmd zmm3 {k4}, zmm13, zmm8\n        vmovups zmm8, zmmword ptr [r8+rdx-1H*40H]\n        vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-4H*10H], 01H\n        vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-4H*10H], 02H\n        vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-4H*10H], 03H\n        vmovups zmm9, zmmword ptr [r8+rdx-30H]\n        vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-3H*10H], 01H\n        vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-3H*10H], 02H\n        vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-3H*10H], 03H\n        vshufps zmm4, zmm8, zmm9, 136\n        vshufps zmm5, zmm8, zmm9, 221\n        vmovups zmm8, zmmword ptr [r8+rdx-20H]\n        vinserti32x4 zmm8, zmm8, xmmword ptr [r9+rdx-2H*10H], 01H\n        vinserti32x4 zmm8, zmm8, xmmword ptr [r10+rdx-2H*10H], 02H\n        vinserti32x4 zmm8, zmm8, xmmword ptr [r11+rdx-2H*10H], 03H\n        vmovups zmm9, zmmword ptr [r8+rdx-10H]\n        vinserti32x4 zmm9, zmm9, xmmword ptr [r9+rdx-1H*10H], 01H\n        vinserti32x4 zmm9, zmm9, xmmword ptr [r10+rdx-1H*10H], 02H\n        vinserti32x4 zmm9, zmm9, xmmword ptr [r11+rdx-1H*10H], 03H\n        vshufps zmm6, zmm8, zmm9, 136\n        vshufps zmm7, zmm8, zmm9, 221\n        vpshufd zmm6, zmm6, 93H\n        vpshufd zmm7, zmm7, 93H\n        mov     al, 7\nroundloop4:\n        vpaddd  zmm0, zmm0, zmm4\n        vpaddd  zmm0, zmm0, zmm1\n        vpxord  zmm3, zmm3, zmm0\n        vprord  zmm3, zmm3, 16\n        vpaddd  zmm2, zmm2, zmm3\n        vpxord  zmm1, zmm1, zmm2\n        vprord  zmm1, zmm1, 12\n        vpaddd  zmm0, zmm0, zmm5\n        vpaddd  zmm0, zmm0, zmm1\n        vpxord  zmm3, zmm3, zmm0\n        vprord  zmm3, zmm3, 8\n        vpaddd  zmm2, zmm2, zmm3\n        vpxord  zmm1, zmm1, zmm2\n        vprord  zmm1, zmm1, 7\n        vpshufd zmm0, zmm0, 93H\n        vpshufd zmm3, zmm3, 4EH\n        vpshufd zmm2, zmm2, 39H\n        vpaddd  zmm0, zmm0, zmm6\n        vpaddd  zmm0, zmm0, zmm1\n        vpxord  zmm3, zmm3, zmm0\n        vprord  zmm3, zmm3, 16\n        vpaddd  zmm2, zmm2, zmm3\n        vpxord  zmm1, zmm1, zmm2\n        vprord  zmm1, zmm1, 12\n        vpaddd  zmm0, zmm0, zmm7\n        vpaddd  zmm0, zmm0, zmm1\n        vpxord  zmm3, zmm3, zmm0\n        vprord  zmm3, zmm3, 8\n        vpaddd  zmm2, zmm2, zmm3\n        vpxord  zmm1, zmm1, zmm2\n        vprord  zmm1, zmm1, 7\n        vpshufd zmm0, zmm0, 39H\n        vpshufd zmm3, zmm3, 4EH\n        vpshufd zmm2, zmm2, 93H\n        dec     al\n        jz      endroundloop4\n        vshufps zmm8, zmm4, zmm5, 214\n        vpshufd zmm9, zmm4, 0FH\n        vpshufd zmm4, zmm8, 39H\n        vshufps zmm8, zmm6, zmm7, 250\n        vpblendmd zmm9 {k3}, zmm9, zmm8\n        vpunpcklqdq zmm8, zmm7, zmm5\n        vpblendmd zmm8 {k4}, zmm8, zmm6\n        vpshufd zmm8, zmm8, 78H\n        vpunpckhdq zmm5, zmm5, zmm7\n        vpunpckldq zmm6, zmm6, zmm5\n        vpshufd zmm7, zmm6, 1EH\n        vmovdqa32 zmm5, zmm9\n        vmovdqa32 zmm6, zmm8\n        jmp     roundloop4\nendroundloop4:\n        vpxord  zmm0, zmm0, zmm2\n        vpxord  zmm1, zmm1, zmm3\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop4\n        vmovdqu xmmword ptr [rbx], xmm0\n        vmovdqu xmmword ptr [rbx+10H], xmm1\n        vextracti128 xmmword ptr [rbx+20H], ymm0, 01H\n        vextracti128 xmmword ptr [rbx+30H], ymm1, 01H\n        vextracti32x4 xmmword ptr [rbx+4H*10H], zmm0, 02H\n        vextracti32x4 xmmword ptr [rbx+5H*10H], zmm1, 02H\n        vextracti32x4 xmmword ptr [rbx+6H*10H], zmm0, 03H\n        vextracti32x4 xmmword ptr [rbx+7H*10H], zmm1, 03H\n        vmovdqa xmm0, xmmword ptr [rsp]\n        vmovdqa xmm2, xmmword ptr [rsp+40H]\n        vmovdqa32 xmm0 {k1}, xmmword ptr [rsp+1H*10H]\n        vmovdqa32 xmm2 {k1}, xmmword ptr [rsp+5H*10H]\n        vmovdqa xmmword ptr [rsp], xmm0\n        vmovdqa xmmword ptr [rsp+40H], xmm2\n        add     rbx, 128\n        add     rdi, 32\n        sub     rsi, 4\nfinal3blocks:\n        test    esi, 2H\n        je      final1block\n        vbroadcasti128 ymm0, xmmword ptr [rcx]\n        vbroadcasti128 ymm1, xmmword ptr [rcx+10H]\n        vmovd   xmm13, dword ptr [rsp]\n        vpinsrd xmm13, xmm13, dword ptr [rsp+40H], 1\n        vpinsrd xmm13, xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2\n        vmovd   xmm14, dword ptr [rsp+4H]\n        vpinsrd xmm14, xmm14, dword ptr [rsp+44H], 1\n        vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2\n        vinserti128 ymm13, ymm13, xmm14, 01H\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\nALIGN   16\ninnerloop2:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        mov     dword ptr [rsp+88H], eax\n        vbroadcasti128 ymm2, xmmword ptr [BLAKE3_IV]\n        vpbroadcastd ymm8, dword ptr [rsp+88H]\n        vpblendd ymm3, ymm13, ymm8, 88H\n        vmovups ymm8, ymmword ptr [r8+rdx-40H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-40H], 01H\n        vmovups ymm9, ymmword ptr [r8+rdx-30H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-30H], 01H\n        vshufps ymm4, ymm8, ymm9, 136\n        vshufps ymm5, ymm8, ymm9, 221\n        vmovups ymm8, ymmword ptr [r8+rdx-20H]\n        vinsertf128 ymm8, ymm8, xmmword ptr [r9+rdx-20H], 01H\n        vmovups ymm9, ymmword ptr [r8+rdx-10H]\n        vinsertf128 ymm9, ymm9, xmmword ptr [r9+rdx-10H], 01H\n        vshufps ymm6, ymm8, ymm9, 136\n        vshufps ymm7, ymm8, ymm9, 221\n        vpshufd ymm6, ymm6, 93H\n        vpshufd ymm7, ymm7, 93H\n        mov     al, 7\nroundloop2:\n        vpaddd  ymm0, ymm0, ymm4\n        vpaddd  ymm0, ymm0, ymm1\n        vpxord  ymm3, ymm3, ymm0\n        vprord  ymm3, ymm3, 16\n        vpaddd  ymm2, ymm2, ymm3\n        vpxord  ymm1, ymm1, ymm2\n        vprord  ymm1, ymm1, 12\n        vpaddd  ymm0, ymm0, ymm5\n        vpaddd  ymm0, ymm0, ymm1\n        vpxord  ymm3, ymm3, ymm0\n        vprord  ymm3, ymm3, 8\n        vpaddd  ymm2, ymm2, ymm3\n        vpxord  ymm1, ymm1, ymm2\n        vprord  ymm1, ymm1, 7\n        vpshufd ymm0, ymm0, 93H\n        vpshufd ymm3, ymm3, 4EH\n        vpshufd ymm2, ymm2, 39H\n        vpaddd  ymm0, ymm0, ymm6\n        vpaddd  ymm0, ymm0, ymm1\n        vpxord  ymm3, ymm3, ymm0\n        vprord  ymm3, ymm3, 16\n        vpaddd  ymm2, ymm2, ymm3\n        vpxord  ymm1, ymm1, ymm2\n        vprord  ymm1, ymm1, 12\n        vpaddd  ymm0, ymm0, ymm7\n        vpaddd  ymm0, ymm0, ymm1\n        vpxord  ymm3, ymm3, ymm0\n        vprord  ymm3, ymm3, 8\n        vpaddd  ymm2, ymm2, ymm3\n        vpxord  ymm1, ymm1, ymm2\n        vprord  ymm1, ymm1, 7\n        vpshufd ymm0, ymm0, 39H\n        vpshufd ymm3, ymm3, 4EH\n        vpshufd ymm2, ymm2, 93H\n        dec     al\n        jz      endroundloop2\n        vshufps ymm8, ymm4, ymm5, 214\n        vpshufd ymm9, ymm4, 0FH\n        vpshufd ymm4, ymm8, 39H\n        vshufps ymm8, ymm6, ymm7, 250\n        vpblendd ymm9, ymm9, ymm8, 0AAH\n        vpunpcklqdq ymm8, ymm7, ymm5\n        vpblendd ymm8, ymm8, ymm6, 88H\n        vpshufd ymm8, ymm8, 78H\n        vpunpckhdq ymm5, ymm5, ymm7\n        vpunpckldq ymm6, ymm6, ymm5\n        vpshufd ymm7, ymm6, 1EH\n        vmovdqa ymm5, ymm9\n        vmovdqa ymm6, ymm8\n        jmp     roundloop2\nendroundloop2:\n        vpxor   ymm0, ymm0, ymm2\n        vpxor   ymm1, ymm1, ymm3\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop2\n        vmovdqu xmmword ptr [rbx], xmm0\n        vmovdqu xmmword ptr [rbx+10H], xmm1\n        vextracti128 xmmword ptr [rbx+20H], ymm0, 01H\n        vextracti128 xmmword ptr [rbx+30H], ymm1, 01H\n        vmovdqa xmm0, xmmword ptr [rsp]\n        vmovdqa xmm2, xmmword ptr [rsp+40H]\n        vmovdqu32 xmm0 {k1}, xmmword ptr [rsp+8H]\n        vmovdqu32 xmm2 {k1}, xmmword ptr [rsp+48H]\n        vmovdqa xmmword ptr [rsp], xmm0\n        vmovdqa xmmword ptr [rsp+40H], xmm2\n        add     rbx, 64\n        add     rdi, 16\n        sub     rsi, 2\nfinal1block:\n        test    esi, 1H\n        je      unwind\n        vmovdqu xmm0, xmmword ptr [rcx]\n        vmovdqu xmm1, xmmword ptr [rcx+10H]\n        vmovd   xmm14, dword ptr [rsp]\n        vpinsrd xmm14, xmm14, dword ptr [rsp+40H], 1\n        vpinsrd xmm14, xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2\n        vmovdqa xmm15, xmmword ptr [BLAKE3_IV]\n        mov     r8, qword ptr [rdi]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\nALIGN   16\ninnerloop1:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        vpinsrd xmm3, xmm14, eax, 3\n        vmovdqa xmm2, xmm15\n        vmovups xmm8, xmmword ptr [r8+rdx-40H]\n        vmovups xmm9, xmmword ptr [r8+rdx-30H]\n        vshufps xmm4, xmm8, xmm9, 136\n        vshufps xmm5, xmm8, xmm9, 221\n        vmovups xmm8, xmmword ptr [r8+rdx-20H]\n        vmovups xmm9, xmmword ptr [r8+rdx-10H]\n        vshufps xmm6, xmm8, xmm9, 136\n        vshufps xmm7, xmm8, xmm9, 221\n        vpshufd xmm6, xmm6, 93H\n        vpshufd xmm7, xmm7, 93H\n        mov     al, 7\nroundloop1:\n        vpaddd  xmm0, xmm0, xmm4\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 16\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 12\n        vpaddd  xmm0, xmm0, xmm5\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 8\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 7\n        vpshufd xmm0, xmm0, 93H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 39H\n        vpaddd  xmm0, xmm0, xmm6\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 16\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 12\n        vpaddd  xmm0, xmm0, xmm7\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 8\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 7\n        vpshufd xmm0, xmm0, 39H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 93H\n        dec     al\n        jz      endroundloop1\n        vshufps xmm8, xmm4, xmm5, 214\n        vpshufd xmm9, xmm4, 0FH\n        vpshufd xmm4, xmm8, 39H\n        vshufps xmm8, xmm6, xmm7, 250\n        vpblendd xmm9, xmm9, xmm8, 0AAH\n        vpunpcklqdq xmm8, xmm7, xmm5\n        vpblendd xmm8, xmm8, xmm6, 88H\n        vpshufd xmm8, xmm8, 78H\n        vpunpckhdq xmm5, xmm5, xmm7\n        vpunpckldq xmm6, xmm6, xmm5\n        vpshufd xmm7, xmm6, 1EH\n        vmovdqa xmm5, xmm9\n        vmovdqa xmm6, xmm8\n        jmp     roundloop1\nendroundloop1:\n        vpxor   xmm0, xmm0, xmm2\n        vpxor   xmm1, xmm1, xmm3\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop1\n        vmovdqu xmmword ptr [rbx], xmm0\n        vmovdqu xmmword ptr [rbx+10H], xmm1\n        jmp     unwind\n\n_blake3_hash_many_avx512 ENDP\nblake3_hash_many_avx512 ENDP\n\nALIGN 16\nblake3_compress_in_place_avx512 PROC\n_blake3_compress_in_place_avx512 PROC\n        sub     rsp, 72\n        vmovdqa xmmword ptr [rsp], xmm6\n        vmovdqa xmmword ptr [rsp+10H], xmm7\n        vmovdqa xmmword ptr [rsp+20H], xmm8\n        vmovdqa xmmword ptr [rsp+30H], xmm9\n        vmovdqu xmm0, xmmword ptr [rcx]\n        vmovdqu xmm1, xmmword ptr [rcx+10H]\n        movzx   eax, byte ptr [rsp+70H]\n        movzx   r8d, r8b\n        shl     rax, 32\n        add     r8, rax\n        vmovq   xmm3, r9\n        vmovq   xmm4, r8\n        vpunpcklqdq xmm3, xmm3, xmm4\n        vmovaps xmm2, xmmword ptr [BLAKE3_IV]\n        vmovups xmm8, xmmword ptr [rdx]\n        vmovups xmm9, xmmword ptr [rdx+10H]\n        vshufps xmm4, xmm8, xmm9, 136\n        vshufps xmm5, xmm8, xmm9, 221\n        vmovups xmm8, xmmword ptr [rdx+20H]\n        vmovups xmm9, xmmword ptr [rdx+30H]\n        vshufps xmm6, xmm8, xmm9, 136\n        vshufps xmm7, xmm8, xmm9, 221\n        vpshufd xmm6, xmm6, 93H\n        vpshufd xmm7, xmm7, 93H\n        mov     al, 7\n@@:\n        vpaddd  xmm0, xmm0, xmm4\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 16\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 12\n        vpaddd  xmm0, xmm0, xmm5\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 8\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 7\n        vpshufd xmm0, xmm0, 93H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 39H\n        vpaddd  xmm0, xmm0, xmm6\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 16\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 12\n        vpaddd  xmm0, xmm0, xmm7\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 8\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 7\n        vpshufd xmm0, xmm0, 39H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 93H\n        dec     al\n        jz      @F\n        vshufps xmm8, xmm4, xmm5, 214\n        vpshufd xmm9, xmm4, 0FH\n        vpshufd xmm4, xmm8, 39H\n        vshufps xmm8, xmm6, xmm7, 250\n        vpblendd xmm9, xmm9, xmm8, 0AAH\n        vpunpcklqdq xmm8, xmm7, xmm5\n        vpblendd xmm8, xmm8, xmm6, 88H\n        vpshufd xmm8, xmm8, 78H\n        vpunpckhdq xmm5, xmm5, xmm7\n        vpunpckldq xmm6, xmm6, xmm5\n        vpshufd xmm7, xmm6, 1EH\n        vmovdqa xmm5, xmm9\n        vmovdqa xmm6, xmm8\n        jmp     @B\n@@:\n        vpxor   xmm0, xmm0, xmm2\n        vpxor   xmm1, xmm1, xmm3\n        vmovdqu xmmword ptr [rcx], xmm0\n        vmovdqu xmmword ptr [rcx+10H], xmm1\n        vmovdqa xmm6, xmmword ptr [rsp]\n        vmovdqa xmm7, xmmword ptr [rsp+10H]\n        vmovdqa xmm8, xmmword ptr [rsp+20H]\n        vmovdqa xmm9, xmmword ptr [rsp+30H]\n        add     rsp, 72\n        ret\n_blake3_compress_in_place_avx512 ENDP\nblake3_compress_in_place_avx512 ENDP\n\nALIGN 16\nblake3_compress_xof_avx512 PROC\n_blake3_compress_xof_avx512 PROC\n        sub     rsp, 72\n        vmovdqa xmmword ptr [rsp], xmm6\n        vmovdqa xmmword ptr [rsp+10H], xmm7\n        vmovdqa xmmword ptr [rsp+20H], xmm8\n        vmovdqa xmmword ptr [rsp+30H], xmm9\n        vmovdqu xmm0, xmmword ptr [rcx]\n        vmovdqu xmm1, xmmword ptr [rcx+10H]\n        movzx   eax, byte ptr [rsp+70H]\n        movzx   r8d, r8b\n        mov     r10, qword ptr [rsp+78H]\n        shl     rax, 32\n        add     r8, rax\n        vmovq   xmm3, r9\n        vmovq   xmm4, r8\n        vpunpcklqdq xmm3, xmm3, xmm4\n        vmovaps xmm2, xmmword ptr [BLAKE3_IV]\n        vmovups xmm8, xmmword ptr [rdx]\n        vmovups xmm9, xmmword ptr [rdx+10H]\n        vshufps xmm4, xmm8, xmm9, 136\n        vshufps xmm5, xmm8, xmm9, 221\n        vmovups xmm8, xmmword ptr [rdx+20H]\n        vmovups xmm9, xmmword ptr [rdx+30H]\n        vshufps xmm6, xmm8, xmm9, 136\n        vshufps xmm7, xmm8, xmm9, 221\n        vpshufd xmm6, xmm6, 93H\n        vpshufd xmm7, xmm7, 93H\n        mov     al, 7\n@@:\n        vpaddd  xmm0, xmm0, xmm4\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 16\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 12\n        vpaddd  xmm0, xmm0, xmm5\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 8\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 7\n        vpshufd xmm0, xmm0, 93H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 39H\n        vpaddd  xmm0, xmm0, xmm6\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 16\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 12\n        vpaddd  xmm0, xmm0, xmm7\n        vpaddd  xmm0, xmm0, xmm1\n        vpxord  xmm3, xmm3, xmm0\n        vprord  xmm3, xmm3, 8\n        vpaddd  xmm2, xmm2, xmm3\n        vpxord  xmm1, xmm1, xmm2\n        vprord  xmm1, xmm1, 7\n        vpshufd xmm0, xmm0, 39H\n        vpshufd xmm3, xmm3, 4EH\n        vpshufd xmm2, xmm2, 93H\n        dec     al\n        jz      @F\n        vshufps xmm8, xmm4, xmm5, 214\n        vpshufd xmm9, xmm4, 0FH\n        vpshufd xmm4, xmm8, 39H\n        vshufps xmm8, xmm6, xmm7, 250\n        vpblendd xmm9, xmm9, xmm8, 0AAH\n        vpunpcklqdq xmm8, xmm7, xmm5\n        vpblendd xmm8, xmm8, xmm6, 88H\n        vpshufd xmm8, xmm8, 78H\n        vpunpckhdq xmm5, xmm5, xmm7\n        vpunpckldq xmm6, xmm6, xmm5\n        vpshufd xmm7, xmm6, 1EH\n        vmovdqa xmm5, xmm9\n        vmovdqa xmm6, xmm8\n        jmp     @B\n@@:\n        vpxor   xmm0, xmm0, xmm2\n        vpxor   xmm1, xmm1, xmm3\n        vpxor   xmm2, xmm2, xmmword ptr [rcx]\n        vpxor   xmm3, xmm3, xmmword ptr [rcx+10H]\n        vmovdqu xmmword ptr [r10], xmm0\n        vmovdqu xmmword ptr [r10+10H], xmm1\n        vmovdqu xmmword ptr [r10+20H], xmm2\n        vmovdqu xmmword ptr [r10+30H], xmm3\n        vmovdqa xmm6, xmmword ptr [rsp]\n        vmovdqa xmm7, xmmword ptr [rsp+10H]\n        vmovdqa xmm8, xmmword ptr [rsp+20H]\n        vmovdqa xmm9, xmmword ptr [rsp+30H]\n        add     rsp, 72\n        ret\n_blake3_compress_xof_avx512 ENDP\nblake3_compress_xof_avx512 ENDP\n\n_TEXT ENDS\n\n_RDATA SEGMENT READONLY PAGE ALIAS(\".rdata\") 'CONST'\nALIGN   64\nINDEX0:\n        dd    0,  1,  2,  3, 16, 17, 18, 19\n        dd    8,  9, 10, 11, 24, 25, 26, 27\nINDEX1:\n        dd    4,  5,  6,  7, 20, 21, 22, 23\n        dd   12, 13, 14, 15, 28, 29, 30, 31\nADD0:\n        dd    0,  1,  2,  3,  4,  5,  6,  7\n        dd    8,  9, 10, 11, 12, 13, 14, 15\nADD1:   \n        dd    1\nADD16:  \n        dd   16\nBLAKE3_BLOCK_LEN:\n        dd   64\nALIGN   64\nBLAKE3_IV:\nBLAKE3_IV_0:\n        dd   06A09E667H\nBLAKE3_IV_1:\n        dd   0BB67AE85H\nBLAKE3_IV_2:\n        dd   03C6EF372H\nBLAKE3_IV_3:\n        dd   0A54FF53AH\n\n_RDATA ENDS\nEND\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_dispatch.c",
    "content": "﻿#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"blake3_impl.h\"\n\n#if defined(_MSC_VER)\n#include <Windows.h>\n#endif\n\n#if defined(IS_X86)\n#if defined(_MSC_VER)\n#include <intrin.h>\n#elif defined(__GNUC__)\n#include <immintrin.h>\n#else\n#undef IS_X86 /* Unimplemented! */\n#endif\n#endif\n\n#if !defined(BLAKE3_ATOMICS)\n#if defined(__has_include)\n#if __has_include(<stdatomic.h>) && !defined(_MSC_VER)\n#define BLAKE3_ATOMICS 1\n#else\n#define BLAKE3_ATOMICS 0\n#endif /* __has_include(<stdatomic.h>) && !defined(_MSC_VER) */\n#else\n#define BLAKE3_ATOMICS 0\n#endif /* defined(__has_include) */\n#endif /* BLAKE3_ATOMICS */\n\n#if BLAKE3_ATOMICS\n#define ATOMIC_INT _Atomic int\n#define ATOMIC_LOAD(x) x\n#define ATOMIC_STORE(x, y) x = y\n#elif defined(_MSC_VER)\n#define ATOMIC_INT LONG\n#define ATOMIC_LOAD(x) InterlockedOr(&x, 0)\n#define ATOMIC_STORE(x, y) InterlockedExchange(&x, y)\n#else\n#define ATOMIC_INT int\n#define ATOMIC_LOAD(x) x\n#define ATOMIC_STORE(x, y) x = y\n#endif\n\n#define MAYBE_UNUSED(x) (void)((x))\n\n#if defined(IS_X86)\nstatic uint64_t xgetbv(void) {\n#if defined(_MSC_VER)\n  return _xgetbv(0);\n#else\n  uint32_t eax = 0, edx = 0;\n  __asm__ __volatile__(\"xgetbv\\n\" : \"=a\"(eax), \"=d\"(edx) : \"c\"(0));\n  return ((uint64_t)edx << 32) | eax;\n#endif\n}\n\nstatic void cpuid(uint32_t out[4], uint32_t id) {\n#if defined(_MSC_VER)\n  __cpuid((int *)out, id);\n#elif defined(__i386__) || defined(_M_IX86)\n  __asm__ __volatile__(\"movl %%ebx, %1\\n\"\n                       \"cpuid\\n\"\n                       \"xchgl %1, %%ebx\\n\"\n                       : \"=a\"(out[0]), \"=r\"(out[1]), \"=c\"(out[2]), \"=d\"(out[3])\n                       : \"a\"(id));\n#else\n  __asm__ __volatile__(\"cpuid\\n\"\n                       : \"=a\"(out[0]), \"=b\"(out[1]), \"=c\"(out[2]), \"=d\"(out[3])\n                       : \"a\"(id));\n#endif\n}\n\nstatic void cpuidex(uint32_t out[4], uint32_t id, uint32_t sid) {\n#if defined(_MSC_VER)\n  __cpuidex((int *)out, id, sid);\n#elif defined(__i386__) || defined(_M_IX86)\n  __asm__ __volatile__(\"movl %%ebx, %1\\n\"\n                       \"cpuid\\n\"\n                       \"xchgl %1, %%ebx\\n\"\n                       : \"=a\"(out[0]), \"=r\"(out[1]), \"=c\"(out[2]), \"=d\"(out[3])\n                       : \"a\"(id), \"c\"(sid));\n#else\n  __asm__ __volatile__(\"cpuid\\n\"\n                       : \"=a\"(out[0]), \"=b\"(out[1]), \"=c\"(out[2]), \"=d\"(out[3])\n                       : \"a\"(id), \"c\"(sid));\n#endif\n}\n\n\nenum cpu_feature {\n  SSE2 = 1 << 0,\n  SSSE3 = 1 << 1,\n  SSE41 = 1 << 2,\n  AVX = 1 << 3,\n  AVX2 = 1 << 4,\n  AVX512F = 1 << 5,\n  AVX512VL = 1 << 6,\n  /* ... */\n  UNDEFINED = 1 << 30\n};\n\n#if !defined(BLAKE3_TESTING)\nstatic /* Allow the variable to be controlled manually for testing */\n#endif\n    ATOMIC_INT g_cpu_features = UNDEFINED;\n\n#if !defined(BLAKE3_TESTING)\nstatic\n#endif\n    enum cpu_feature\n    get_cpu_features(void) {\n\n  /* If TSAN detects a data race here, try compiling with -DBLAKE3_ATOMICS=1 */\n  enum cpu_feature features = ATOMIC_LOAD(g_cpu_features);\n  if (features != UNDEFINED) {\n    return features;\n  } else {\n#if defined(IS_X86)\n    uint32_t regs[4] = {0};\n    uint32_t *eax = &regs[0], *ebx = &regs[1], *ecx = &regs[2], *edx = &regs[3];\n    (void)edx;\n    features = 0;\n    cpuid(regs, 0);\n    const int max_id = *eax;\n    cpuid(regs, 1);\n#if defined(__amd64__) || defined(_M_X64)\n    features |= SSE2;\n#else\n    if (*edx & (1UL << 26))\n      features |= SSE2;\n#endif\n    if (*ecx & (1UL << 9))\n      features |= SSSE3;\n    if (*ecx & (1UL << 19))\n      features |= SSE41;\n\n    if (*ecx & (1UL << 27)) { // OSXSAVE\n      const uint64_t mask = xgetbv();\n      if ((mask & 6) == 6) { // SSE and AVX states\n        if (*ecx & (1UL << 28))\n          features |= AVX;\n        if (max_id >= 7) {\n          cpuidex(regs, 7, 0);\n          if (*ebx & (1UL << 5))\n            features |= AVX2;\n          if ((mask & 224) == 224) { // Opmask, ZMM_Hi256, Hi16_Zmm\n            if (*ebx & (1UL << 31))\n              features |= AVX512VL;\n            if (*ebx & (1UL << 16))\n              features |= AVX512F;\n          }\n        }\n      }\n    }\n    ATOMIC_STORE(g_cpu_features, features);\n    return features;\n#else\n    /* How to detect NEON? */\n    return 0;\n#endif\n  }\n}\n#endif\n\nvoid blake3_compress_in_place(uint32_t cv[8],\n                              const uint8_t block[BLAKE3_BLOCK_LEN],\n                              uint8_t block_len, uint64_t counter,\n                              uint8_t flags) {\n#if defined(IS_X86)\n  const enum cpu_feature features = get_cpu_features();\n  MAYBE_UNUSED(features);\n#if !defined(BLAKE3_NO_AVX512)\n  if (features & AVX512VL) {\n    blake3_compress_in_place_avx512(cv, block, block_len, counter, flags);\n    return;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE41)\n  if (features & SSE41) {\n    blake3_compress_in_place_sse41(cv, block, block_len, counter, flags);\n    return;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE2)\n  if (features & SSE2) {\n    blake3_compress_in_place_sse2(cv, block, block_len, counter, flags);\n    return;\n  }\n#endif\n#endif\n  blake3_compress_in_place_portable(cv, block, block_len, counter, flags);\n}\n\nvoid blake3_compress_xof(const uint32_t cv[8],\n                         const uint8_t block[BLAKE3_BLOCK_LEN],\n                         uint8_t block_len, uint64_t counter, uint8_t flags,\n                         uint8_t out[64]) {\n#if defined(IS_X86)\n  const enum cpu_feature features = get_cpu_features();\n  MAYBE_UNUSED(features);\n#if !defined(BLAKE3_NO_AVX512)\n  if (features & AVX512VL) {\n    blake3_compress_xof_avx512(cv, block, block_len, counter, flags, out);\n    return;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE41)\n  if (features & SSE41) {\n    blake3_compress_xof_sse41(cv, block, block_len, counter, flags, out);\n    return;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE2)\n  if (features & SSE2) {\n    blake3_compress_xof_sse2(cv, block, block_len, counter, flags, out);\n    return;\n  }\n#endif\n#endif\n  blake3_compress_xof_portable(cv, block, block_len, counter, flags, out);\n}\n\n\nvoid blake3_xof_many(const uint32_t cv[8],\n                     const uint8_t block[BLAKE3_BLOCK_LEN],\n                     uint8_t block_len, uint64_t counter, uint8_t flags,\n                     uint8_t out[64], size_t outblocks) {\n  if (outblocks == 0) {\n    // The current assembly implementation always outputs at least 1 block.\n    return;\n  }\n#if defined(IS_X86)\n  const enum cpu_feature features = get_cpu_features();\n  MAYBE_UNUSED(features);\n#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(BLAKE3_NO_AVX512)\n  if (features & AVX512VL) {\n    blake3_xof_many_avx512(cv, block, block_len, counter, flags, out, outblocks);\n    return;\n  }\n#endif\n#endif\n  for(size_t i = 0; i < outblocks; ++i) {\n    blake3_compress_xof(cv, block, block_len, counter + i, flags, out + 64*i);\n  }\n}\n\nvoid blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs,\n                      size_t blocks, const uint32_t key[8], uint64_t counter,\n                      bool increment_counter, uint8_t flags,\n                      uint8_t flags_start, uint8_t flags_end, uint8_t *out) {\n#if defined(IS_X86)\n  const enum cpu_feature features = get_cpu_features();\n  MAYBE_UNUSED(features);\n#if !defined(BLAKE3_NO_AVX512)\n  if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) {\n    blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter,\n                            increment_counter, flags, flags_start, flags_end,\n                            out);\n    return;\n  }\n#endif\n#if !defined(BLAKE3_NO_AVX2)\n  if (features & AVX2) {\n    blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter,\n                          increment_counter, flags, flags_start, flags_end,\n                          out);\n    return;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE41)\n  if (features & SSE41) {\n    blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter,\n                           increment_counter, flags, flags_start, flags_end,\n                           out);\n    return;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE2)\n  if (features & SSE2) {\n    blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter,\n                          increment_counter, flags, flags_start, flags_end,\n                          out);\n    return;\n  }\n#endif\n#endif\n\n#if BLAKE3_USE_NEON == 1\n  blake3_hash_many_neon(inputs, num_inputs, blocks, key, counter,\n                        increment_counter, flags, flags_start, flags_end, out);\n  return;\n#endif\n\n  blake3_hash_many_portable(inputs, num_inputs, blocks, key, counter,\n                            increment_counter, flags, flags_start, flags_end,\n                            out);\n}\n\n// The dynamically detected SIMD degree of the current platform.\nsize_t blake3_simd_degree(void) {\n#if defined(IS_X86)\n  const enum cpu_feature features = get_cpu_features();\n  MAYBE_UNUSED(features);\n#if !defined(BLAKE3_NO_AVX512)\n  if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) {\n    return 16;\n  }\n#endif\n#if !defined(BLAKE3_NO_AVX2)\n  if (features & AVX2) {\n    return 8;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE41)\n  if (features & SSE41) {\n    return 4;\n  }\n#endif\n#if !defined(BLAKE3_NO_SSE2)\n  if (features & SSE2) {\n    return 4;\n  }\n#endif\n#endif\n#if BLAKE3_USE_NEON == 1\n  return 4;\n#endif\n  return 1;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_impl.h",
    "content": "﻿#ifndef BLAKE3_IMPL_H\n#define BLAKE3_IMPL_H\n\n#include <assert.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"blake3.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n// internal flags\nenum blake3_flags {\n  CHUNK_START         = 1 << 0,\n  CHUNK_END           = 1 << 1,\n  PARENT              = 1 << 2,\n  ROOT                = 1 << 3,\n  KEYED_HASH          = 1 << 4,\n  DERIVE_KEY_CONTEXT  = 1 << 5,\n  DERIVE_KEY_MATERIAL = 1 << 6,\n};\n\n// This C implementation tries to support recent versions of GCC, Clang, and\n// MSVC.\n#if defined(_MSC_VER)\n#define INLINE static __forceinline\n#else\n#define INLINE static inline __attribute__((always_inline))\n#endif\n\n#ifdef __cplusplus\n#define NOEXCEPT noexcept\n#else\n#define NOEXCEPT\n#endif\n\n#if (defined(__x86_64__) || defined(_M_X64)) && !defined(_M_ARM64EC)\n#define IS_X86\n#define IS_X86_64\n#endif\n\n#if defined(__i386__) || defined(_M_IX86)\n#define IS_X86\n#define IS_X86_32\n#endif\n\n#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)\n#define IS_AARCH64\n#endif\n\n#if defined(IS_X86)\n#if defined(_MSC_VER)\n#include <intrin.h>\n#endif\n#endif\n\n#if !defined(BLAKE3_USE_NEON) \n  // If BLAKE3_USE_NEON not manually set, autodetect based on AArch64ness\n  #if defined(IS_AARCH64)\n    #if defined(__ARM_BIG_ENDIAN)\n      #define BLAKE3_USE_NEON 0\n    #else\n      #define BLAKE3_USE_NEON 1\n    #endif\n  #else\n    #define BLAKE3_USE_NEON 0\n  #endif\n#endif\n\n#if defined(IS_X86)\n#define MAX_SIMD_DEGREE 16\n#elif BLAKE3_USE_NEON == 1\n#define MAX_SIMD_DEGREE 4\n#else\n#define MAX_SIMD_DEGREE 1\n#endif\n\n// There are some places where we want a static size that's equal to the\n// MAX_SIMD_DEGREE, but also at least 2.\n#define MAX_SIMD_DEGREE_OR_2 (MAX_SIMD_DEGREE > 2 ? MAX_SIMD_DEGREE : 2)\n\nstatic const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL,\n                               0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL,\n                               0x1F83D9ABUL, 0x5BE0CD19UL};\n\nstatic const uint8_t MSG_SCHEDULE[7][16] = {\n    {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},\n    {2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8},\n    {3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1},\n    {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6},\n    {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4},\n    {9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7},\n    {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13},\n};\n\n/* Find index of the highest set bit */\n/* x is assumed to be nonzero.       */\nstatic unsigned int highest_one(uint64_t x) {\n#if defined(__GNUC__) || defined(__clang__)\n  return 63 ^ (unsigned int)__builtin_clzll(x);\n#elif defined(_MSC_VER) && defined(IS_X86_64)\n  unsigned long index;\n  _BitScanReverse64(&index, x);\n  return index;\n#elif defined(_MSC_VER) && defined(IS_X86_32)\n  if(x >> 32) {\n    unsigned long index;\n    _BitScanReverse(&index, (unsigned long)(x >> 32));\n    return 32 + index;\n  } else {\n    unsigned long index;\n    _BitScanReverse(&index, (unsigned long)x);\n    return index;\n  }\n#else\n  unsigned int c = 0;\n  if(x & 0xffffffff00000000ULL) { x >>= 32; c += 32; }\n  if(x & 0x00000000ffff0000ULL) { x >>= 16; c += 16; }\n  if(x & 0x000000000000ff00ULL) { x >>=  8; c +=  8; }\n  if(x & 0x00000000000000f0ULL) { x >>=  4; c +=  4; }\n  if(x & 0x000000000000000cULL) { x >>=  2; c +=  2; }\n  if(x & 0x0000000000000002ULL) {           c +=  1; }\n  return c;\n#endif\n}\n\n// Count the number of 1 bits.\nINLINE unsigned int popcnt(uint64_t x) {\n#if defined(__GNUC__) || defined(__clang__)\n  return (unsigned int)__builtin_popcountll(x);\n#else\n  unsigned int count = 0;\n  while (x != 0) {\n    count += 1;\n    x &= x - 1;\n  }\n  return count;\n#endif\n}\n\n// Largest power of two less than or equal to x. As a special case, returns 1\n// when x is 0. \nINLINE uint64_t round_down_to_power_of_2(uint64_t x) {\n  return 1ULL << highest_one(x | 1);\n}\n\nINLINE uint32_t counter_low(uint64_t counter) { return (uint32_t)counter; }\n\nINLINE uint32_t counter_high(uint64_t counter) {\n  return (uint32_t)(counter >> 32);\n}\n\nINLINE uint32_t load32(const void *src) {\n  const uint8_t *p = (const uint8_t *)src;\n  return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |\n         ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);\n}\n\nINLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN],\n                           uint32_t key_words[8]) {\n  key_words[0] = load32(&key[0 * 4]);\n  key_words[1] = load32(&key[1 * 4]);\n  key_words[2] = load32(&key[2 * 4]);\n  key_words[3] = load32(&key[3 * 4]);\n  key_words[4] = load32(&key[4 * 4]);\n  key_words[5] = load32(&key[5 * 4]);\n  key_words[6] = load32(&key[6 * 4]);\n  key_words[7] = load32(&key[7 * 4]);\n}\n\nINLINE void load_block_words(const uint8_t block[BLAKE3_BLOCK_LEN],\n                             uint32_t block_words[16]) {\n  for (size_t i = 0; i < 16; i++) {\n      block_words[i] = load32(&block[i * 4]);\n  }\n}\n\nINLINE void store32(void *dst, uint32_t w) {\n  uint8_t *p = (uint8_t *)dst;\n  p[0] = (uint8_t)(w >> 0);\n  p[1] = (uint8_t)(w >> 8);\n  p[2] = (uint8_t)(w >> 16);\n  p[3] = (uint8_t)(w >> 24);\n}\n\nINLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) {\n  store32(&bytes_out[0 * 4], cv_words[0]);\n  store32(&bytes_out[1 * 4], cv_words[1]);\n  store32(&bytes_out[2 * 4], cv_words[2]);\n  store32(&bytes_out[3 * 4], cv_words[3]);\n  store32(&bytes_out[4 * 4], cv_words[4]);\n  store32(&bytes_out[5 * 4], cv_words[5]);\n  store32(&bytes_out[6 * 4], cv_words[6]);\n  store32(&bytes_out[7 * 4], cv_words[7]);\n}\n\nvoid blake3_compress_in_place(uint32_t cv[8],\n                              const uint8_t block[BLAKE3_BLOCK_LEN],\n                              uint8_t block_len, uint64_t counter,\n                              uint8_t flags);\n\nvoid blake3_compress_xof(const uint32_t cv[8],\n                         const uint8_t block[BLAKE3_BLOCK_LEN],\n                         uint8_t block_len, uint64_t counter, uint8_t flags,\n                         uint8_t out[64]);\n\nvoid blake3_xof_many(const uint32_t cv[8],\n                     const uint8_t block[BLAKE3_BLOCK_LEN],\n                     uint8_t block_len, uint64_t counter, uint8_t flags,\n                     uint8_t out[64], size_t outblocks);\n\nvoid blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs,\n                      size_t blocks, const uint32_t key[8], uint64_t counter,\n                      bool increment_counter, uint8_t flags,\n                      uint8_t flags_start, uint8_t flags_end, uint8_t *out);\n\nsize_t blake3_simd_degree(void);\n\nBLAKE3_PRIVATE size_t blake3_compress_subtree_wide(const uint8_t *input, size_t input_len,\n                                                   const uint32_t key[8],\n                                                   uint64_t chunk_counter, uint8_t flags,\n                                                   uint8_t *out, bool use_tbb);\n\n#if defined(BLAKE3_USE_TBB)\nBLAKE3_PRIVATE void blake3_compress_subtree_wide_join_tbb(\n    // shared params\n    const uint32_t key[8], uint8_t flags, bool use_tbb,\n    // left-hand side params\n    const uint8_t *l_input, size_t l_input_len, uint64_t l_chunk_counter,\n    uint8_t *l_cvs, size_t *l_n,\n    // right-hand side params\n    const uint8_t *r_input, size_t r_input_len, uint64_t r_chunk_counter,\n    uint8_t *r_cvs, size_t *r_n) NOEXCEPT;\n#endif\n\n// Declarations for implementation-specific functions.\nvoid blake3_compress_in_place_portable(uint32_t cv[8],\n                                       const uint8_t block[BLAKE3_BLOCK_LEN],\n                                       uint8_t block_len, uint64_t counter,\n                                       uint8_t flags);\n\nvoid blake3_compress_xof_portable(const uint32_t cv[8],\n                                  const uint8_t block[BLAKE3_BLOCK_LEN],\n                                  uint8_t block_len, uint64_t counter,\n                                  uint8_t flags, uint8_t out[64]);\n\nvoid blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs,\n                               size_t blocks, const uint32_t key[8],\n                               uint64_t counter, bool increment_counter,\n                               uint8_t flags, uint8_t flags_start,\n                               uint8_t flags_end, uint8_t *out);\n\n#if defined(IS_X86)\n#if !defined(BLAKE3_NO_SSE2)\nvoid blake3_compress_in_place_sse2(uint32_t cv[8],\n                                   const uint8_t block[BLAKE3_BLOCK_LEN],\n                                   uint8_t block_len, uint64_t counter,\n                                   uint8_t flags);\nvoid blake3_compress_xof_sse2(const uint32_t cv[8],\n                              const uint8_t block[BLAKE3_BLOCK_LEN],\n                              uint8_t block_len, uint64_t counter,\n                              uint8_t flags, uint8_t out[64]);\nvoid blake3_hash_many_sse2(const uint8_t *const *inputs, size_t num_inputs,\n                           size_t blocks, const uint32_t key[8],\n                           uint64_t counter, bool increment_counter,\n                           uint8_t flags, uint8_t flags_start,\n                           uint8_t flags_end, uint8_t *out);\n#endif\n#if !defined(BLAKE3_NO_SSE41)\nvoid blake3_compress_in_place_sse41(uint32_t cv[8],\n                                    const uint8_t block[BLAKE3_BLOCK_LEN],\n                                    uint8_t block_len, uint64_t counter,\n                                    uint8_t flags);\nvoid blake3_compress_xof_sse41(const uint32_t cv[8],\n                               const uint8_t block[BLAKE3_BLOCK_LEN],\n                               uint8_t block_len, uint64_t counter,\n                               uint8_t flags, uint8_t out[64]);\nvoid blake3_hash_many_sse41(const uint8_t *const *inputs, size_t num_inputs,\n                            size_t blocks, const uint32_t key[8],\n                            uint64_t counter, bool increment_counter,\n                            uint8_t flags, uint8_t flags_start,\n                            uint8_t flags_end, uint8_t *out);\n#endif\n#if !defined(BLAKE3_NO_AVX2)\nvoid blake3_hash_many_avx2(const uint8_t *const *inputs, size_t num_inputs,\n                           size_t blocks, const uint32_t key[8],\n                           uint64_t counter, bool increment_counter,\n                           uint8_t flags, uint8_t flags_start,\n                           uint8_t flags_end, uint8_t *out);\n#endif\n#if !defined(BLAKE3_NO_AVX512)\nvoid blake3_compress_in_place_avx512(uint32_t cv[8],\n                                     const uint8_t block[BLAKE3_BLOCK_LEN],\n                                     uint8_t block_len, uint64_t counter,\n                                     uint8_t flags);\n\nvoid blake3_compress_xof_avx512(const uint32_t cv[8],\n                                const uint8_t block[BLAKE3_BLOCK_LEN],\n                                uint8_t block_len, uint64_t counter,\n                                uint8_t flags, uint8_t out[64]);\n\nvoid blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs,\n                             size_t blocks, const uint32_t key[8],\n                             uint64_t counter, bool increment_counter,\n                             uint8_t flags, uint8_t flags_start,\n                             uint8_t flags_end, uint8_t *out);\n\n#if !defined(_WIN32) && !defined(__CYGWIN__)\nvoid blake3_xof_many_avx512(const uint32_t cv[8],\n                            const uint8_t block[BLAKE3_BLOCK_LEN],\n                            uint8_t block_len, uint64_t counter, uint8_t flags,\n                            uint8_t* out, size_t outblocks);\n#endif\n#endif\n#endif\n\n#if BLAKE3_USE_NEON == 1\nvoid blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs,\n                           size_t blocks, const uint32_t key[8],\n                           uint64_t counter, bool increment_counter,\n                           uint8_t flags, uint8_t flags_start,\n                           uint8_t flags_end, uint8_t *out);\n#endif\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* BLAKE3_IMPL_H */\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_neon.c",
    "content": "﻿#include \"blake3_impl.h\"\n\n#include <arm_neon.h>\n\n#ifdef __ARM_BIG_ENDIAN\n#error \"This implementation only supports little-endian ARM.\"\n// It might be that all we need for big-endian support here is to get the loads\n// and stores right, but step zero would be finding a way to test it in CI.\n#endif\n\nINLINE uint32x4_t loadu_128(const uint8_t src[16]) {\n  // vld1q_u32 has alignment requirements. Don't use it.\n  return vreinterpretq_u32_u8(vld1q_u8(src));\n}\n\nINLINE void storeu_128(uint32x4_t src, uint8_t dest[16]) {\n  // vst1q_u32 has alignment requirements. Don't use it.\n  vst1q_u8(dest, vreinterpretq_u8_u32(src));\n}\n\nINLINE uint32x4_t add_128(uint32x4_t a, uint32x4_t b) {\n  return vaddq_u32(a, b);\n}\n\nINLINE uint32x4_t xor_128(uint32x4_t a, uint32x4_t b) {\n  return veorq_u32(a, b);\n}\n\nINLINE uint32x4_t set1_128(uint32_t x) { return vld1q_dup_u32(&x); }\n\nINLINE uint32x4_t set4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {\n  uint32_t array[4] = {a, b, c, d};\n  return vld1q_u32(array);\n}\n\nINLINE uint32x4_t rot16_128(uint32x4_t x) {\n  // The straightforward implementation would be two shifts and an or, but that's\n  // slower on microarchitectures we've tested. See\n  // https://github.com/BLAKE3-team/BLAKE3/pull/319.\n  // return vorrq_u32(vshrq_n_u32(x, 16), vshlq_n_u32(x, 32 - 16));\n  return vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(x)));\n}\n\nINLINE uint32x4_t rot12_128(uint32x4_t x) {\n  // See comment in rot16_128.\n  // return vorrq_u32(vshrq_n_u32(x, 12), vshlq_n_u32(x, 32 - 12));\n  return vsriq_n_u32(vshlq_n_u32(x, 32-12), x, 12);\n}\n\nINLINE uint32x4_t rot8_128(uint32x4_t x) {\n  // See comment in rot16_128.\n  // return vorrq_u32(vshrq_n_u32(x, 8), vshlq_n_u32(x, 32 - 8));\n#if defined(__clang__)\n  return vreinterpretq_u32_u8(__builtin_shufflevector(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12));\n#elif __GNUC__ * 10000 + __GNUC_MINOR__ * 100 >=40700\n  static const uint8x16_t r8 = {1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12};\n  return vreinterpretq_u32_u8(__builtin_shuffle(vreinterpretq_u8_u32(x), vreinterpretq_u8_u32(x), r8));\n#else \n  return vsriq_n_u32(vshlq_n_u32(x, 32-8), x, 8);\n#endif\n}\n\nINLINE uint32x4_t rot7_128(uint32x4_t x) {\n  // See comment in rot16_128.\n  // return vorrq_u32(vshrq_n_u32(x, 7), vshlq_n_u32(x, 32 - 7));\n  return vsriq_n_u32(vshlq_n_u32(x, 32-7), x, 7);\n}\n\n// TODO: compress_neon\n\n// TODO: hash2_neon\n\n/*\n * ----------------------------------------------------------------------------\n * hash4_neon\n * ----------------------------------------------------------------------------\n */\n\nINLINE void round_fn4(uint32x4_t v[16], uint32x4_t m[16], size_t r) {\n  v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][0]]);\n  v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][2]]);\n  v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][4]]);\n  v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][6]]);\n  v[0] = add_128(v[0], v[4]);\n  v[1] = add_128(v[1], v[5]);\n  v[2] = add_128(v[2], v[6]);\n  v[3] = add_128(v[3], v[7]);\n  v[12] = xor_128(v[12], v[0]);\n  v[13] = xor_128(v[13], v[1]);\n  v[14] = xor_128(v[14], v[2]);\n  v[15] = xor_128(v[15], v[3]);\n  v[12] = rot16_128(v[12]);\n  v[13] = rot16_128(v[13]);\n  v[14] = rot16_128(v[14]);\n  v[15] = rot16_128(v[15]);\n  v[8] = add_128(v[8], v[12]);\n  v[9] = add_128(v[9], v[13]);\n  v[10] = add_128(v[10], v[14]);\n  v[11] = add_128(v[11], v[15]);\n  v[4] = xor_128(v[4], v[8]);\n  v[5] = xor_128(v[5], v[9]);\n  v[6] = xor_128(v[6], v[10]);\n  v[7] = xor_128(v[7], v[11]);\n  v[4] = rot12_128(v[4]);\n  v[5] = rot12_128(v[5]);\n  v[6] = rot12_128(v[6]);\n  v[7] = rot12_128(v[7]);\n  v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][1]]);\n  v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][3]]);\n  v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][5]]);\n  v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][7]]);\n  v[0] = add_128(v[0], v[4]);\n  v[1] = add_128(v[1], v[5]);\n  v[2] = add_128(v[2], v[6]);\n  v[3] = add_128(v[3], v[7]);\n  v[12] = xor_128(v[12], v[0]);\n  v[13] = xor_128(v[13], v[1]);\n  v[14] = xor_128(v[14], v[2]);\n  v[15] = xor_128(v[15], v[3]);\n  v[12] = rot8_128(v[12]);\n  v[13] = rot8_128(v[13]);\n  v[14] = rot8_128(v[14]);\n  v[15] = rot8_128(v[15]);\n  v[8] = add_128(v[8], v[12]);\n  v[9] = add_128(v[9], v[13]);\n  v[10] = add_128(v[10], v[14]);\n  v[11] = add_128(v[11], v[15]);\n  v[4] = xor_128(v[4], v[8]);\n  v[5] = xor_128(v[5], v[9]);\n  v[6] = xor_128(v[6], v[10]);\n  v[7] = xor_128(v[7], v[11]);\n  v[4] = rot7_128(v[4]);\n  v[5] = rot7_128(v[5]);\n  v[6] = rot7_128(v[6]);\n  v[7] = rot7_128(v[7]);\n\n  v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][8]]);\n  v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][10]]);\n  v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][12]]);\n  v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][14]]);\n  v[0] = add_128(v[0], v[5]);\n  v[1] = add_128(v[1], v[6]);\n  v[2] = add_128(v[2], v[7]);\n  v[3] = add_128(v[3], v[4]);\n  v[15] = xor_128(v[15], v[0]);\n  v[12] = xor_128(v[12], v[1]);\n  v[13] = xor_128(v[13], v[2]);\n  v[14] = xor_128(v[14], v[3]);\n  v[15] = rot16_128(v[15]);\n  v[12] = rot16_128(v[12]);\n  v[13] = rot16_128(v[13]);\n  v[14] = rot16_128(v[14]);\n  v[10] = add_128(v[10], v[15]);\n  v[11] = add_128(v[11], v[12]);\n  v[8] = add_128(v[8], v[13]);\n  v[9] = add_128(v[9], v[14]);\n  v[5] = xor_128(v[5], v[10]);\n  v[6] = xor_128(v[6], v[11]);\n  v[7] = xor_128(v[7], v[8]);\n  v[4] = xor_128(v[4], v[9]);\n  v[5] = rot12_128(v[5]);\n  v[6] = rot12_128(v[6]);\n  v[7] = rot12_128(v[7]);\n  v[4] = rot12_128(v[4]);\n  v[0] = add_128(v[0], m[(size_t)MSG_SCHEDULE[r][9]]);\n  v[1] = add_128(v[1], m[(size_t)MSG_SCHEDULE[r][11]]);\n  v[2] = add_128(v[2], m[(size_t)MSG_SCHEDULE[r][13]]);\n  v[3] = add_128(v[3], m[(size_t)MSG_SCHEDULE[r][15]]);\n  v[0] = add_128(v[0], v[5]);\n  v[1] = add_128(v[1], v[6]);\n  v[2] = add_128(v[2], v[7]);\n  v[3] = add_128(v[3], v[4]);\n  v[15] = xor_128(v[15], v[0]);\n  v[12] = xor_128(v[12], v[1]);\n  v[13] = xor_128(v[13], v[2]);\n  v[14] = xor_128(v[14], v[3]);\n  v[15] = rot8_128(v[15]);\n  v[12] = rot8_128(v[12]);\n  v[13] = rot8_128(v[13]);\n  v[14] = rot8_128(v[14]);\n  v[10] = add_128(v[10], v[15]);\n  v[11] = add_128(v[11], v[12]);\n  v[8] = add_128(v[8], v[13]);\n  v[9] = add_128(v[9], v[14]);\n  v[5] = xor_128(v[5], v[10]);\n  v[6] = xor_128(v[6], v[11]);\n  v[7] = xor_128(v[7], v[8]);\n  v[4] = xor_128(v[4], v[9]);\n  v[5] = rot7_128(v[5]);\n  v[6] = rot7_128(v[6]);\n  v[7] = rot7_128(v[7]);\n  v[4] = rot7_128(v[4]);\n}\n\nINLINE void transpose_vecs_128(uint32x4_t vecs[4]) {\n  // Individually transpose the four 2x2 sub-matrices in each corner.\n  uint32x4x2_t rows01 = vtrnq_u32(vecs[0], vecs[1]);\n  uint32x4x2_t rows23 = vtrnq_u32(vecs[2], vecs[3]);\n\n  // Swap the top-right and bottom-left 2x2s (which just got transposed).\n  vecs[0] =\n      vcombine_u32(vget_low_u32(rows01.val[0]), vget_low_u32(rows23.val[0]));\n  vecs[1] =\n      vcombine_u32(vget_low_u32(rows01.val[1]), vget_low_u32(rows23.val[1]));\n  vecs[2] =\n      vcombine_u32(vget_high_u32(rows01.val[0]), vget_high_u32(rows23.val[0]));\n  vecs[3] =\n      vcombine_u32(vget_high_u32(rows01.val[1]), vget_high_u32(rows23.val[1]));\n}\n\nINLINE void transpose_msg_vecs4(const uint8_t *const *inputs,\n                                size_t block_offset, uint32x4_t out[16]) {\n  out[0] = loadu_128(&inputs[0][block_offset + 0 * sizeof(uint32x4_t)]);\n  out[1] = loadu_128(&inputs[1][block_offset + 0 * sizeof(uint32x4_t)]);\n  out[2] = loadu_128(&inputs[2][block_offset + 0 * sizeof(uint32x4_t)]);\n  out[3] = loadu_128(&inputs[3][block_offset + 0 * sizeof(uint32x4_t)]);\n  out[4] = loadu_128(&inputs[0][block_offset + 1 * sizeof(uint32x4_t)]);\n  out[5] = loadu_128(&inputs[1][block_offset + 1 * sizeof(uint32x4_t)]);\n  out[6] = loadu_128(&inputs[2][block_offset + 1 * sizeof(uint32x4_t)]);\n  out[7] = loadu_128(&inputs[3][block_offset + 1 * sizeof(uint32x4_t)]);\n  out[8] = loadu_128(&inputs[0][block_offset + 2 * sizeof(uint32x4_t)]);\n  out[9] = loadu_128(&inputs[1][block_offset + 2 * sizeof(uint32x4_t)]);\n  out[10] = loadu_128(&inputs[2][block_offset + 2 * sizeof(uint32x4_t)]);\n  out[11] = loadu_128(&inputs[3][block_offset + 2 * sizeof(uint32x4_t)]);\n  out[12] = loadu_128(&inputs[0][block_offset + 3 * sizeof(uint32x4_t)]);\n  out[13] = loadu_128(&inputs[1][block_offset + 3 * sizeof(uint32x4_t)]);\n  out[14] = loadu_128(&inputs[2][block_offset + 3 * sizeof(uint32x4_t)]);\n  out[15] = loadu_128(&inputs[3][block_offset + 3 * sizeof(uint32x4_t)]);\n  transpose_vecs_128(&out[0]);\n  transpose_vecs_128(&out[4]);\n  transpose_vecs_128(&out[8]);\n  transpose_vecs_128(&out[12]);\n}\n\nINLINE void load_counters4(uint64_t counter, bool increment_counter,\n                           uint32x4_t *out_low, uint32x4_t *out_high) {\n  uint64_t mask = (increment_counter ? ~0 : 0);\n  *out_low = set4(\n      counter_low(counter + (mask & 0)), counter_low(counter + (mask & 1)),\n      counter_low(counter + (mask & 2)), counter_low(counter + (mask & 3)));\n  *out_high = set4(\n      counter_high(counter + (mask & 0)), counter_high(counter + (mask & 1)),\n      counter_high(counter + (mask & 2)), counter_high(counter + (mask & 3)));\n}\n\nstatic void blake3_hash4_neon(const uint8_t *const *inputs, size_t blocks,\n                              const uint32_t key[8], uint64_t counter,\n                              bool increment_counter, uint8_t flags,\n                              uint8_t flags_start, uint8_t flags_end, \n                              uint8_t *out) {\n  uint32x4_t h_vecs[8] = {\n      set1_128(key[0]), set1_128(key[1]), set1_128(key[2]), set1_128(key[3]),\n      set1_128(key[4]), set1_128(key[5]), set1_128(key[6]), set1_128(key[7]),\n  };\n  uint32x4_t counter_low_vec, counter_high_vec;\n  load_counters4(counter, increment_counter, &counter_low_vec,\n                 &counter_high_vec);\n  uint8_t block_flags = flags | flags_start;\n\n  for (size_t block = 0; block < blocks; block++) {\n    if (block + 1 == blocks) {\n      block_flags |= flags_end;\n    }\n    uint32x4_t block_len_vec = set1_128(BLAKE3_BLOCK_LEN);\n    uint32x4_t block_flags_vec = set1_128(block_flags);\n    uint32x4_t msg_vecs[16];\n    transpose_msg_vecs4(inputs, block * BLAKE3_BLOCK_LEN, msg_vecs);\n\n    uint32x4_t v[16] = {\n        h_vecs[0],       h_vecs[1],        h_vecs[2],       h_vecs[3],\n        h_vecs[4],       h_vecs[5],        h_vecs[6],       h_vecs[7],\n        set1_128(IV[0]), set1_128(IV[1]),  set1_128(IV[2]), set1_128(IV[3]),\n        counter_low_vec, counter_high_vec, block_len_vec,   block_flags_vec,\n    };\n    round_fn4(v, msg_vecs, 0);\n    round_fn4(v, msg_vecs, 1);\n    round_fn4(v, msg_vecs, 2);\n    round_fn4(v, msg_vecs, 3);\n    round_fn4(v, msg_vecs, 4);\n    round_fn4(v, msg_vecs, 5);\n    round_fn4(v, msg_vecs, 6);\n    h_vecs[0] = xor_128(v[0], v[8]);\n    h_vecs[1] = xor_128(v[1], v[9]);\n    h_vecs[2] = xor_128(v[2], v[10]);\n    h_vecs[3] = xor_128(v[3], v[11]);\n    h_vecs[4] = xor_128(v[4], v[12]);\n    h_vecs[5] = xor_128(v[5], v[13]);\n    h_vecs[6] = xor_128(v[6], v[14]);\n    h_vecs[7] = xor_128(v[7], v[15]);\n\n    block_flags = flags;\n  }\n\n  transpose_vecs_128(&h_vecs[0]);\n  transpose_vecs_128(&h_vecs[4]);\n  // The first four vecs now contain the first half of each output, and the\n  // second four vecs contain the second half of each output.\n  storeu_128(h_vecs[0], &out[0 * sizeof(uint32x4_t)]);\n  storeu_128(h_vecs[4], &out[1 * sizeof(uint32x4_t)]);\n  storeu_128(h_vecs[1], &out[2 * sizeof(uint32x4_t)]);\n  storeu_128(h_vecs[5], &out[3 * sizeof(uint32x4_t)]);\n  storeu_128(h_vecs[2], &out[4 * sizeof(uint32x4_t)]);\n  storeu_128(h_vecs[6], &out[5 * sizeof(uint32x4_t)]);\n  storeu_128(h_vecs[3], &out[6 * sizeof(uint32x4_t)]);\n  storeu_128(h_vecs[7], &out[7 * sizeof(uint32x4_t)]);\n}\n\n/*\n * ----------------------------------------------------------------------------\n * hash_many_neon\n * ----------------------------------------------------------------------------\n */\n\nvoid blake3_compress_in_place_portable(uint32_t cv[8],\n                                       const uint8_t block[BLAKE3_BLOCK_LEN],\n                                       uint8_t block_len, uint64_t counter,\n                                       uint8_t flags);\n\nINLINE void hash_one_neon(const uint8_t *input, size_t blocks,\n                          const uint32_t key[8], uint64_t counter,\n                          uint8_t flags, uint8_t flags_start, uint8_t flags_end,\n                          uint8_t out[BLAKE3_OUT_LEN]) {\n  uint32_t cv[8];\n  memcpy(cv, key, BLAKE3_KEY_LEN);\n  uint8_t block_flags = flags | flags_start;\n  while (blocks > 0) {\n    if (blocks == 1) {\n      block_flags |= flags_end;\n    }\n    // TODO: Implement compress_neon. However note that according to\n    // https://github.com/BLAKE2/BLAKE2/commit/7965d3e6e1b4193438b8d3a656787587d2579227,\n    // compress_neon might not be any faster than compress_portable.\n    blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter,\n                                      block_flags);\n    input = &input[BLAKE3_BLOCK_LEN];\n    blocks -= 1;\n    block_flags = flags;\n  }\n  memcpy(out, cv, BLAKE3_OUT_LEN);\n}\n\nvoid blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs,\n                           size_t blocks, const uint32_t key[8],\n                           uint64_t counter, bool increment_counter,\n                           uint8_t flags, uint8_t flags_start,\n                           uint8_t flags_end, uint8_t *out) {\n  while (num_inputs >= 4) {\n    blake3_hash4_neon(inputs, blocks, key, counter, increment_counter, flags,\n                      flags_start, flags_end, out);\n    if (increment_counter) {\n      counter += 4;\n    }\n    inputs += 4;\n    num_inputs -= 4;\n    out = &out[4 * BLAKE3_OUT_LEN];\n  }\n  while (num_inputs > 0) {\n    hash_one_neon(inputs[0], blocks, key, counter, flags, flags_start,\n                  flags_end, out);\n    if (increment_counter) {\n      counter += 1;\n    }\n    inputs += 1;\n    num_inputs -= 1;\n    out = &out[BLAKE3_OUT_LEN];\n  }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_portable.c",
    "content": "﻿#include \"blake3_impl.h\"\n#include <string.h>\n\nINLINE uint32_t rotr32(uint32_t w, uint32_t c) {\n  return (w >> c) | (w << (32 - c));\n}\n\nINLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d,\n              uint32_t x, uint32_t y) {\n  state[a] = state[a] + state[b] + x;\n  state[d] = rotr32(state[d] ^ state[a], 16);\n  state[c] = state[c] + state[d];\n  state[b] = rotr32(state[b] ^ state[c], 12);\n  state[a] = state[a] + state[b] + y;\n  state[d] = rotr32(state[d] ^ state[a], 8);\n  state[c] = state[c] + state[d];\n  state[b] = rotr32(state[b] ^ state[c], 7);\n}\n\nINLINE void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) {\n  // Select the message schedule based on the round.\n  const uint8_t *schedule = MSG_SCHEDULE[round];\n\n  // Mix the columns.\n  g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]);\n  g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]);\n  g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]);\n  g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]);\n\n  // Mix the rows.\n  g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]);\n  g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]);\n  g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]);\n  g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]);\n}\n\nINLINE void compress_pre(uint32_t state[16], const uint32_t cv[8],\n                         const uint8_t block[BLAKE3_BLOCK_LEN],\n                         uint8_t block_len, uint64_t counter, uint8_t flags) {\n  uint32_t block_words[16];\n  block_words[0] = load32(block + 4 * 0);\n  block_words[1] = load32(block + 4 * 1);\n  block_words[2] = load32(block + 4 * 2);\n  block_words[3] = load32(block + 4 * 3);\n  block_words[4] = load32(block + 4 * 4);\n  block_words[5] = load32(block + 4 * 5);\n  block_words[6] = load32(block + 4 * 6);\n  block_words[7] = load32(block + 4 * 7);\n  block_words[8] = load32(block + 4 * 8);\n  block_words[9] = load32(block + 4 * 9);\n  block_words[10] = load32(block + 4 * 10);\n  block_words[11] = load32(block + 4 * 11);\n  block_words[12] = load32(block + 4 * 12);\n  block_words[13] = load32(block + 4 * 13);\n  block_words[14] = load32(block + 4 * 14);\n  block_words[15] = load32(block + 4 * 15);\n\n  state[0] = cv[0];\n  state[1] = cv[1];\n  state[2] = cv[2];\n  state[3] = cv[3];\n  state[4] = cv[4];\n  state[5] = cv[5];\n  state[6] = cv[6];\n  state[7] = cv[7];\n  state[8] = IV[0];\n  state[9] = IV[1];\n  state[10] = IV[2];\n  state[11] = IV[3];\n  state[12] = counter_low(counter);\n  state[13] = counter_high(counter);\n  state[14] = (uint32_t)block_len;\n  state[15] = (uint32_t)flags;\n\n  round_fn(state, &block_words[0], 0);\n  round_fn(state, &block_words[0], 1);\n  round_fn(state, &block_words[0], 2);\n  round_fn(state, &block_words[0], 3);\n  round_fn(state, &block_words[0], 4);\n  round_fn(state, &block_words[0], 5);\n  round_fn(state, &block_words[0], 6);\n}\n\nvoid blake3_compress_in_place_portable(uint32_t cv[8],\n                                       const uint8_t block[BLAKE3_BLOCK_LEN],\n                                       uint8_t block_len, uint64_t counter,\n                                       uint8_t flags) {\n  uint32_t state[16];\n  compress_pre(state, cv, block, block_len, counter, flags);\n  cv[0] = state[0] ^ state[8];\n  cv[1] = state[1] ^ state[9];\n  cv[2] = state[2] ^ state[10];\n  cv[3] = state[3] ^ state[11];\n  cv[4] = state[4] ^ state[12];\n  cv[5] = state[5] ^ state[13];\n  cv[6] = state[6] ^ state[14];\n  cv[7] = state[7] ^ state[15];\n}\n\nvoid blake3_compress_xof_portable(const uint32_t cv[8],\n                                  const uint8_t block[BLAKE3_BLOCK_LEN],\n                                  uint8_t block_len, uint64_t counter,\n                                  uint8_t flags, uint8_t out[64]) {\n  uint32_t state[16];\n  compress_pre(state, cv, block, block_len, counter, flags);\n\n  store32(&out[0 * 4], state[0] ^ state[8]);\n  store32(&out[1 * 4], state[1] ^ state[9]);\n  store32(&out[2 * 4], state[2] ^ state[10]);\n  store32(&out[3 * 4], state[3] ^ state[11]);\n  store32(&out[4 * 4], state[4] ^ state[12]);\n  store32(&out[5 * 4], state[5] ^ state[13]);\n  store32(&out[6 * 4], state[6] ^ state[14]);\n  store32(&out[7 * 4], state[7] ^ state[15]);\n  store32(&out[8 * 4], state[8] ^ cv[0]);\n  store32(&out[9 * 4], state[9] ^ cv[1]);\n  store32(&out[10 * 4], state[10] ^ cv[2]);\n  store32(&out[11 * 4], state[11] ^ cv[3]);\n  store32(&out[12 * 4], state[12] ^ cv[4]);\n  store32(&out[13 * 4], state[13] ^ cv[5]);\n  store32(&out[14 * 4], state[14] ^ cv[6]);\n  store32(&out[15 * 4], state[15] ^ cv[7]);\n}\n\nINLINE void hash_one_portable(const uint8_t *input, size_t blocks,\n                              const uint32_t key[8], uint64_t counter,\n                              uint8_t flags, uint8_t flags_start,\n                              uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) {\n  uint32_t cv[8];\n  memcpy(cv, key, BLAKE3_KEY_LEN);\n  uint8_t block_flags = flags | flags_start;\n  while (blocks > 0) {\n    if (blocks == 1) {\n      block_flags |= flags_end;\n    }\n    blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter,\n                                      block_flags);\n    input = &input[BLAKE3_BLOCK_LEN];\n    blocks -= 1;\n    block_flags = flags;\n  }\n  store_cv_words(out, cv);\n}\n\nvoid blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs,\n                               size_t blocks, const uint32_t key[8],\n                               uint64_t counter, bool increment_counter,\n                               uint8_t flags, uint8_t flags_start,\n                               uint8_t flags_end, uint8_t *out) {\n  while (num_inputs > 0) {\n    hash_one_portable(inputs[0], blocks, key, counter, flags, flags_start,\n                      flags_end, out);\n    if (increment_counter) {\n      counter += 1;\n    }\n    inputs += 1;\n    num_inputs -= 1;\n    out = &out[BLAKE3_OUT_LEN];\n  }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_sse2_x86-64_windows_msvc.asm",
    "content": "public _blake3_hash_many_sse2\npublic blake3_hash_many_sse2\npublic blake3_compress_in_place_sse2\npublic _blake3_compress_in_place_sse2\npublic blake3_compress_xof_sse2\npublic _blake3_compress_xof_sse2\n\n_TEXT   SEGMENT ALIGN(16) 'CODE'\n\nALIGN   16\nblake3_hash_many_sse2 PROC\n_blake3_hash_many_sse2 PROC\n        push    r15\n        push    r14\n        push    r13\n        push    r12\n        push    rsi\n        push    rdi\n        push    rbx\n        push    rbp\n        mov     rbp, rsp\n        sub     rsp, 528\n        and     rsp, 0FFFFFFFFFFFFFFC0H\n        movdqa  xmmword ptr [rsp+170H], xmm6\n        movdqa  xmmword ptr [rsp+180H], xmm7\n        movdqa  xmmword ptr [rsp+190H], xmm8\n        movdqa  xmmword ptr [rsp+1A0H], xmm9\n        movdqa  xmmword ptr [rsp+1B0H], xmm10\n        movdqa  xmmword ptr [rsp+1C0H], xmm11\n        movdqa  xmmword ptr [rsp+1D0H], xmm12\n        movdqa  xmmword ptr [rsp+1E0H], xmm13\n        movdqa  xmmword ptr [rsp+1F0H], xmm14\n        movdqa  xmmword ptr [rsp+200H], xmm15\n        mov     rdi, rcx\n        mov     rsi, rdx\n        mov     rdx, r8\n        mov     rcx, r9\n        mov     r8, qword ptr [rbp+68H]\n        movzx   r9, byte ptr [rbp+70H]\n        neg     r9d\n        movd    xmm0, r9d\n        pshufd  xmm0, xmm0, 00H\n        movdqa  xmmword ptr [rsp+130H], xmm0\n        movdqa  xmm1, xmm0\n        pand    xmm1, xmmword ptr [ADD0]\n        pand    xmm0, xmmword ptr [ADD1]\n        movdqa  xmmword ptr [rsp+150H], xmm0\n        movd    xmm0, r8d\n        pshufd  xmm0, xmm0, 00H\n        paddd   xmm0, xmm1\n        movdqa  xmmword ptr [rsp+110H], xmm0\n        pxor    xmm0, xmmword ptr [CMP_MSB_MASK]\n        pxor    xmm1, xmmword ptr [CMP_MSB_MASK]\n        pcmpgtd xmm1, xmm0\n        shr     r8, 32\n        movd    xmm2, r8d\n        pshufd  xmm2, xmm2, 00H\n        psubd   xmm2, xmm1\n        movdqa  xmmword ptr [rsp+120H], xmm2\n        mov     rbx, qword ptr [rbp+90H]\n        mov     r15, rdx\n        shl     r15, 6\n        movzx   r13d, byte ptr [rbp+78H]\n        movzx   r12d, byte ptr [rbp+88H]\n        cmp     rsi, 4\n        jc      final3blocks\nouterloop4:\n        movdqu  xmm3, xmmword ptr [rcx]\n        pshufd  xmm0, xmm3, 00H\n        pshufd  xmm1, xmm3, 55H\n        pshufd  xmm2, xmm3, 0AAH\n        pshufd  xmm3, xmm3, 0FFH\n        movdqu  xmm7, xmmword ptr [rcx+10H]\n        pshufd  xmm4, xmm7, 00H\n        pshufd  xmm5, xmm7, 55H\n        pshufd  xmm6, xmm7, 0AAH\n        pshufd  xmm7, xmm7, 0FFH\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\ninnerloop4:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        movdqu  xmm8, xmmword ptr [r8+rdx-40H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-40H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-40H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-40H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp], xmm8\n        movdqa  xmmword ptr [rsp+10H], xmm9\n        movdqa  xmmword ptr [rsp+20H], xmm12\n        movdqa  xmmword ptr [rsp+30H], xmm13\n        movdqu  xmm8, xmmword ptr [r8+rdx-30H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-30H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-30H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-30H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp+40H], xmm8\n        movdqa  xmmword ptr [rsp+50H], xmm9\n        movdqa  xmmword ptr [rsp+60H], xmm12\n        movdqa  xmmword ptr [rsp+70H], xmm13\n        movdqu  xmm8, xmmword ptr [r8+rdx-20H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-20H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-20H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-20H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp+80H], xmm8\n        movdqa  xmmword ptr [rsp+90H], xmm9\n        movdqa  xmmword ptr [rsp+0A0H], xmm12\n        movdqa  xmmword ptr [rsp+0B0H], xmm13\n        movdqu  xmm8, xmmword ptr [r8+rdx-10H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-10H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-10H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-10H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp+0C0H], xmm8\n        movdqa  xmmword ptr [rsp+0D0H], xmm9\n        movdqa  xmmword ptr [rsp+0E0H], xmm12\n        movdqa  xmmword ptr [rsp+0F0H], xmm13\n        movdqa  xmm9, xmmword ptr [BLAKE3_IV_1]\n        movdqa  xmm10, xmmword ptr [BLAKE3_IV_2]\n        movdqa  xmm11, xmmword ptr [BLAKE3_IV_3]\n        movdqa  xmm12, xmmword ptr [rsp+110H]\n        movdqa  xmm13, xmmword ptr [rsp+120H]\n        movdqa  xmm14, xmmword ptr [BLAKE3_BLOCK_LEN]\n        movd    xmm15, eax\n        pshufd  xmm15, xmm15, 00H\n        prefetcht0 byte ptr [r8+rdx+80H]\n        prefetcht0 byte ptr [r9+rdx+80H]\n        prefetcht0 byte ptr [r10+rdx+80H]\n        prefetcht0 byte ptr [r11+rdx+80H]\n        paddd   xmm0, xmmword ptr [rsp]\n        paddd   xmm1, xmmword ptr [rsp+20H]\n        paddd   xmm2, xmmword ptr [rsp+40H]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        movdqa  xmm8, xmmword ptr [BLAKE3_IV_0]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+10H]\n        paddd   xmm1, xmmword ptr [rsp+30H]\n        paddd   xmm2, xmmword ptr [rsp+50H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+80H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp+0C0H]\n        paddd   xmm3, xmmword ptr [rsp+0E0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+90H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+0D0H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+20H]\n        paddd   xmm1, xmmword ptr [rsp+30H]\n        paddd   xmm2, xmmword ptr [rsp+70H]\n        paddd   xmm3, xmmword ptr [rsp+40H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+60H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp]\n        paddd   xmm3, xmmword ptr [rsp+0D0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+10H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+90H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0B0H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp+0E0H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+30H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp+0D0H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+40H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+20H]\n        paddd   xmm3, xmmword ptr [rsp+0E0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+60H]\n        paddd   xmm1, xmmword ptr [rsp+90H]\n        paddd   xmm2, xmmword ptr [rsp+0B0H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+50H]\n        paddd   xmm1, xmmword ptr [rsp]\n        paddd   xmm2, xmmword ptr [rsp+0F0H]\n        paddd   xmm3, xmmword ptr [rsp+10H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0A0H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+0E0H]\n        paddd   xmm3, xmmword ptr [rsp+0D0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+70H]\n        paddd   xmm1, xmmword ptr [rsp+90H]\n        paddd   xmm2, xmmword ptr [rsp+30H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+40H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+50H]\n        paddd   xmm3, xmmword ptr [rsp+10H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp]\n        paddd   xmm1, xmmword ptr [rsp+20H]\n        paddd   xmm2, xmmword ptr [rsp+80H]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0C0H]\n        paddd   xmm1, xmmword ptr [rsp+90H]\n        paddd   xmm2, xmmword ptr [rsp+0F0H]\n        paddd   xmm3, xmmword ptr [rsp+0E0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0D0H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+0A0H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+70H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+20H]\n        paddd   xmm1, xmmword ptr [rsp+30H]\n        paddd   xmm2, xmmword ptr [rsp+10H]\n        paddd   xmm3, xmmword ptr [rsp+40H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+90H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+80H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0E0H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp+0C0H]\n        paddd   xmm3, xmmword ptr [rsp+10H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0D0H]\n        paddd   xmm1, xmmword ptr [rsp]\n        paddd   xmm2, xmmword ptr [rsp+20H]\n        paddd   xmm3, xmmword ptr [rsp+40H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+30H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp+60H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0B0H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp+10H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0F0H]\n        paddd   xmm1, xmmword ptr [rsp]\n        paddd   xmm2, xmmword ptr [rsp+90H]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0E0H]\n        paddd   xmm1, xmmword ptr [rsp+20H]\n        paddd   xmm2, xmmword ptr [rsp+30H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        pshuflw xmm15, xmm15, 0B1H\n        pshufhw xmm15, xmm15, 0B1H\n        pshuflw xmm12, xmm12, 0B1H\n        pshufhw xmm12, xmm12, 0B1H\n        pshuflw xmm13, xmm13, 0B1H\n        pshufhw xmm13, xmm13, 0B1H\n        pshuflw xmm14, xmm14, 0B1H\n        pshufhw xmm14, xmm14, 0B1H\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0A0H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+40H]\n        paddd   xmm3, xmmword ptr [rsp+0D0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmm15\n        psrld   xmm15, 8\n        pslld   xmm8, 24\n        pxor    xmm15, xmm8\n        movdqa  xmm8, xmm12\n        psrld   xmm12, 8\n        pslld   xmm8, 24\n        pxor    xmm12, xmm8\n        movdqa  xmm8, xmm13\n        psrld   xmm13, 8\n        pslld   xmm8, 24\n        pxor    xmm13, xmm8\n        movdqa  xmm8, xmm14\n        psrld   xmm14, 8\n        pslld   xmm8, 24\n        pxor    xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        pxor    xmm0, xmm8\n        pxor    xmm1, xmm9\n        pxor    xmm2, xmm10\n        pxor    xmm3, xmm11\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        pxor    xmm4, xmm12\n        pxor    xmm5, xmm13\n        pxor    xmm6, xmm14\n        pxor    xmm7, xmm15\n        mov     eax, r13d\n        jne     innerloop4\n        movdqa  xmm9, xmm0\n        punpckldq xmm0, xmm1\n        punpckhdq xmm9, xmm1\n        movdqa  xmm11, xmm2\n        punpckldq xmm2, xmm3\n        punpckhdq xmm11, xmm3\n        movdqa  xmm1, xmm0\n        punpcklqdq xmm0, xmm2\n        punpckhqdq xmm1, xmm2\n        movdqa  xmm3, xmm9\n        punpcklqdq xmm9, xmm11\n        punpckhqdq xmm3, xmm11\n        movdqu  xmmword ptr [rbx], xmm0\n        movdqu  xmmword ptr [rbx+20H], xmm1\n        movdqu  xmmword ptr [rbx+40H], xmm9\n        movdqu  xmmword ptr [rbx+60H], xmm3\n        movdqa  xmm9, xmm4\n        punpckldq xmm4, xmm5\n        punpckhdq xmm9, xmm5\n        movdqa  xmm11, xmm6\n        punpckldq xmm6, xmm7\n        punpckhdq xmm11, xmm7\n        movdqa  xmm5, xmm4\n        punpcklqdq xmm4, xmm6\n        punpckhqdq xmm5, xmm6\n        movdqa  xmm7, xmm9\n        punpcklqdq xmm9, xmm11\n        punpckhqdq xmm7, xmm11\n        movdqu  xmmword ptr [rbx+10H], xmm4\n        movdqu  xmmword ptr [rbx+30H], xmm5\n        movdqu  xmmword ptr [rbx+50H], xmm9\n        movdqu  xmmword ptr [rbx+70H], xmm7\n        movdqa  xmm1, xmmword ptr [rsp+110H]\n        movdqa  xmm0, xmm1\n        paddd   xmm1, xmmword ptr [rsp+150H]\n        movdqa  xmmword ptr [rsp+110H], xmm1\n        pxor    xmm0, xmmword ptr [CMP_MSB_MASK]\n        pxor    xmm1, xmmword ptr [CMP_MSB_MASK]\n        pcmpgtd xmm0, xmm1\n        movdqa  xmm1, xmmword ptr [rsp+120H]\n        psubd   xmm1, xmm0\n        movdqa  xmmword ptr [rsp+120H], xmm1\n        add     rbx, 128\n        add     rdi, 32\n        sub     rsi, 4\n        cmp     rsi, 4\n        jnc     outerloop4\n        test    rsi, rsi\n        jne     final3blocks\nunwind:\n        movdqa  xmm6, xmmword ptr [rsp+170H]\n        movdqa  xmm7, xmmword ptr [rsp+180H]\n        movdqa  xmm8, xmmword ptr [rsp+190H]\n        movdqa  xmm9, xmmword ptr [rsp+1A0H]\n        movdqa  xmm10, xmmword ptr [rsp+1B0H]\n        movdqa  xmm11, xmmword ptr [rsp+1C0H]\n        movdqa  xmm12, xmmword ptr [rsp+1D0H]\n        movdqa  xmm13, xmmword ptr [rsp+1E0H]\n        movdqa  xmm14, xmmword ptr [rsp+1F0H]\n        movdqa  xmm15, xmmword ptr [rsp+200H]\n        mov     rsp, rbp\n        pop     rbp\n        pop     rbx\n        pop     rdi\n        pop     rsi\n        pop     r12\n        pop     r13\n        pop     r14\n        pop     r15\n        ret\nALIGN   16\nfinal3blocks:\n        test    esi, 2H\n        je      final1block\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movaps  xmm8, xmm0\n        movaps  xmm9, xmm1\n        movd    xmm13, dword ptr [rsp+110H]\n        movd    xmm14, dword ptr [rsp+120H]\n        punpckldq xmm13, xmm14\n        movaps  xmmword ptr [rsp], xmm13\n        movd    xmm14, dword ptr [rsp+114H]\n        movd    xmm13, dword ptr [rsp+124H]\n        punpckldq xmm14, xmm13\n        movaps  xmmword ptr [rsp+10H], xmm14\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\ninnerloop2:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        movaps  xmm10, xmm2\n        movups  xmm4, xmmword ptr [r8+rdx-40H]\n        movups  xmm5, xmmword ptr [r8+rdx-30H]\n        movaps  xmm3, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm3, xmm5, 221\n        movaps  xmm5, xmm3\n        movups  xmm6, xmmword ptr [r8+rdx-20H]\n        movups  xmm7, xmmword ptr [r8+rdx-10H]\n        movaps  xmm3, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm3, xmm7, 221\n        pshufd  xmm7, xmm3, 93H\n        movups  xmm12, xmmword ptr [r9+rdx-40H]\n        movups  xmm13, xmmword ptr [r9+rdx-30H]\n        movaps  xmm11, xmm12\n        shufps  xmm12, xmm13, 136\n        shufps  xmm11, xmm13, 221\n        movaps  xmm13, xmm11\n        movups  xmm14, xmmword ptr [r9+rdx-20H]\n        movups  xmm15, xmmword ptr [r9+rdx-10H]\n        movaps  xmm11, xmm14\n        shufps  xmm14, xmm15, 136\n        pshufd  xmm14, xmm14, 93H\n        shufps  xmm11, xmm15, 221\n        pshufd  xmm15, xmm11, 93H\n        shl     rax, 20H\n        or      rax, 40H\n        movd    xmm3, rax\n        movdqa  xmmword ptr [rsp+20H], xmm3\n        movaps  xmm3, xmmword ptr [rsp]\n        movaps  xmm11, xmmword ptr [rsp+10H]\n        punpcklqdq xmm3, xmmword ptr [rsp+20H]\n        punpcklqdq xmm11, xmmword ptr [rsp+20H]\n        mov     al, 7\nroundloop2:\n        paddd   xmm0, xmm4\n        paddd   xmm8, xmm12\n        movaps  xmmword ptr [rsp+20H], xmm4\n        movaps  xmmword ptr [rsp+30H], xmm12\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        pshuflw xmm11, xmm11, 0B1H\n        pshufhw xmm11, xmm11, 0B1H\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 20\n        psrld   xmm4, 12\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 20\n        psrld   xmm4, 12\n        por     xmm9, xmm4\n        paddd   xmm0, xmm5\n        paddd   xmm8, xmm13\n        movaps  xmmword ptr [rsp+40H], xmm5\n        movaps  xmmword ptr [rsp+50H], xmm13\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        movdqa  xmm13, xmm3\n        psrld   xmm3, 8\n        pslld   xmm13, 24\n        pxor    xmm3, xmm13\n        movdqa  xmm13, xmm11\n        psrld   xmm11, 8\n        pslld   xmm13, 24\n        pxor    xmm11, xmm13\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 25\n        psrld   xmm4, 7\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 25\n        psrld   xmm4, 7\n        por     xmm9, xmm4\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm8, xmm8, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm11, xmm11, 4EH\n        pshufd  xmm2, xmm2, 39H\n        pshufd  xmm10, xmm10, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm8, xmm14\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        pshuflw xmm11, xmm11, 0B1H\n        pshufhw xmm11, xmm11, 0B1H\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 20\n        psrld   xmm4, 12\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 20\n        psrld   xmm4, 12\n        por     xmm9, xmm4\n        paddd   xmm0, xmm7\n        paddd   xmm8, xmm15\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        movdqa  xmm13, xmm3\n        psrld   xmm3, 8\n        pslld   xmm13, 24\n        pxor    xmm3, xmm13\n        movdqa  xmm13, xmm11\n        psrld   xmm11, 8\n        pslld   xmm13, 24\n        pxor    xmm11, xmm13\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 25\n        psrld   xmm4, 7\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 25\n        psrld   xmm4, 7\n        por     xmm9, xmm4\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm8, xmm8, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm11, xmm11, 4EH\n        pshufd  xmm2, xmm2, 93H\n        pshufd  xmm10, xmm10, 93H\n        dec     al\n        je      endroundloop2\n        movdqa  xmm12, xmmword ptr [rsp+20H]\n        movdqa  xmm5, xmmword ptr [rsp+40H]\n        pshufd  xmm13, xmm12, 0FH\n        shufps  xmm12, xmm5, 214\n        pshufd  xmm4, xmm12, 39H\n        movdqa  xmm12, xmm6\n        shufps  xmm12, xmm7, 250\n        pand    xmm13, xmmword ptr [PBLENDW_0x33_MASK]\n        pand    xmm12, xmmword ptr [PBLENDW_0xCC_MASK]\n        por     xmm13, xmm12\n        movdqa  xmmword ptr [rsp+20H], xmm13\n        movdqa  xmm12, xmm7\n        punpcklqdq xmm12, xmm5\n        movdqa  xmm13, xmm6\n        pand    xmm12, xmmword ptr [PBLENDW_0x3F_MASK]\n        pand    xmm13, xmmword ptr [PBLENDW_0xC0_MASK]\n        por     xmm12, xmm13\n        pshufd  xmm12, xmm12, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmmword ptr [rsp+40H], xmm12\n        movdqa  xmm5, xmmword ptr [rsp+30H]\n        movdqa  xmm13, xmmword ptr [rsp+50H]\n        pshufd  xmm6, xmm5, 0FH\n        shufps  xmm5, xmm13, 214\n        pshufd  xmm12, xmm5, 39H\n        movdqa  xmm5, xmm14\n        shufps  xmm5, xmm15, 250\n        pand    xmm6, xmmword ptr [PBLENDW_0x33_MASK]\n        pand    xmm5, xmmword ptr [PBLENDW_0xCC_MASK]\n        por     xmm6, xmm5\n        movdqa  xmm5, xmm15\n        punpcklqdq xmm5, xmm13\n        movdqa  xmmword ptr [rsp+30H], xmm2\n        movdqa  xmm2, xmm14\n        pand    xmm5, xmmword ptr [PBLENDW_0x3F_MASK]\n        pand    xmm2, xmmword ptr [PBLENDW_0xC0_MASK]\n        por     xmm5, xmm2\n        movdqa  xmm2, xmmword ptr [rsp+30H]\n        pshufd  xmm5, xmm5, 78H\n        punpckhdq xmm13, xmm15\n        punpckldq xmm14, xmm13\n        pshufd  xmm15, xmm14, 1EH\n        movdqa  xmm13, xmm6\n        movdqa  xmm14, xmm5\n        movdqa  xmm5, xmmword ptr [rsp+20H]\n        movdqa  xmm6, xmmword ptr [rsp+40H]\n        jmp     roundloop2\nendroundloop2:\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        pxor    xmm8, xmm10\n        pxor    xmm9, xmm11\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop2\n        movups  xmmword ptr [rbx], xmm0\n        movups  xmmword ptr [rbx+10H], xmm1\n        movups  xmmword ptr [rbx+20H], xmm8\n        movups  xmmword ptr [rbx+30H], xmm9\n        mov     eax, dword ptr [rsp+130H]\n        neg     eax\n        mov    r10d, dword ptr [rsp+110H+8*rax]\n        mov    r11d, dword ptr [rsp+120H+8*rax]\n        mov dword ptr [rsp+110H], r10d\n        mov dword ptr [rsp+120H], r11d\n        add     rdi, 16\n        add     rbx, 64\n        sub     rsi, 2\nfinal1block:\n        test    esi, 1H\n        je      unwind\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movd    xmm13, dword ptr [rsp+110H]\n        movd    xmm14, dword ptr [rsp+120H]\n        punpckldq xmm13, xmm14\n        mov     r8, qword ptr [rdi]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\ninnerloop1:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        shl     rax, 32\n        or      rax, 64\n        movd    xmm12, rax\n        movdqa  xmm3, xmm13\n        punpcklqdq xmm3, xmm12\n        movups  xmm4, xmmword ptr [r8+rdx-40H]\n        movups  xmm5, xmmword ptr [r8+rdx-30H]\n        movaps  xmm8, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm8, xmm5, 221\n        movaps  xmm5, xmm8\n        movups  xmm6, xmmword ptr [r8+rdx-20H]\n        movups  xmm7, xmmword ptr [r8+rdx-10H]\n        movaps  xmm8, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm8, xmm7, 221\n        pshufd  xmm7, xmm8, 93H\n        mov     al, 7\nroundloop1:\n        paddd   xmm0, xmm4\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm5\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        movdqa  xmm14, xmm3\n        psrld   xmm3, 8\n        pslld   xmm14, 24\n        pxor    xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm7\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        movdqa  xmm14, xmm3\n        psrld   xmm3, 8\n        pslld   xmm14, 24\n        pxor    xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 93H\n        dec     al\n        jz      endroundloop1\n        movdqa  xmm8, xmm4\n        shufps  xmm8, xmm5, 214\n        pshufd  xmm9, xmm4, 0FH\n        pshufd  xmm4, xmm8, 39H\n        movdqa  xmm8, xmm6\n        shufps  xmm8, xmm7, 250\n        pand    xmm9, xmmword ptr [PBLENDW_0x33_MASK]\n        pand    xmm8, xmmword ptr [PBLENDW_0xCC_MASK]\n        por     xmm9, xmm8\n        movdqa  xmm8, xmm7\n        punpcklqdq xmm8, xmm5\n        movdqa  xmm10, xmm6\n        pand    xmm8, xmmword ptr [PBLENDW_0x3F_MASK]\n        pand    xmm10, xmmword ptr [PBLENDW_0xC0_MASK]\n        por     xmm8, xmm10\n        pshufd  xmm8, xmm8, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmm5, xmm9\n        movdqa  xmm6, xmm8\n        jmp     roundloop1\nendroundloop1:\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop1\n        movups  xmmword ptr [rbx], xmm0\n        movups  xmmword ptr [rbx+10H], xmm1\n        jmp     unwind\n_blake3_hash_many_sse2 ENDP\nblake3_hash_many_sse2 ENDP\n\nblake3_compress_in_place_sse2 PROC\n_blake3_compress_in_place_sse2 PROC\n        sub     rsp, 120\n        movdqa  xmmword ptr [rsp], xmm6\n        movdqa  xmmword ptr [rsp+10H], xmm7\n        movdqa  xmmword ptr [rsp+20H], xmm8\n        movdqa  xmmword ptr [rsp+30H], xmm9\n        movdqa  xmmword ptr [rsp+40H], xmm11\n        movdqa  xmmword ptr [rsp+50H], xmm14\n        movdqa  xmmword ptr [rsp+60H], xmm15\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        movzx   eax, byte ptr [rsp+0A0H]\n        movzx   r8d, r8b\n        shl     rax, 32\n        add     r8, rax\n        movd    xmm3, r9\n        movd    xmm4, r8\n        punpcklqdq xmm3, xmm4\n        movups  xmm4, xmmword ptr [rdx]\n        movups  xmm5, xmmword ptr [rdx+10H]\n        movaps  xmm8, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm8, xmm5, 221\n        movaps  xmm5, xmm8\n        movups  xmm6, xmmword ptr [rdx+20H]\n        movups  xmm7, xmmword ptr [rdx+30H]\n        movaps  xmm8, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm8, xmm7, 221\n        pshufd  xmm7, xmm8, 93H\n        mov     al, 7\n@@:\n        paddd   xmm0, xmm4\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm5\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        movdqa  xmm14, xmm3\n        psrld   xmm3, 8\n        pslld   xmm14, 24\n        pxor    xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm7\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        movdqa  xmm14, xmm3\n        psrld   xmm3, 8\n        pslld   xmm14, 24\n        pxor    xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 93H\n        dec     al\n        jz      @F\n        movdqa  xmm8, xmm4\n        shufps  xmm8, xmm5, 214\n        pshufd  xmm9, xmm4, 0FH\n        pshufd  xmm4, xmm8, 39H\n        movdqa  xmm8, xmm6\n        shufps  xmm8, xmm7, 250\n        pand    xmm9, xmmword ptr [PBLENDW_0x33_MASK]\n        pand    xmm8, xmmword ptr [PBLENDW_0xCC_MASK]\n        por     xmm9, xmm8\n        movdqa  xmm8, xmm7\n        punpcklqdq xmm8, xmm5\n        movdqa  xmm14, xmm6\n        pand    xmm8, xmmword ptr [PBLENDW_0x3F_MASK]\n        pand    xmm14, xmmword ptr [PBLENDW_0xC0_MASK]\n        por     xmm8, xmm14\n        pshufd  xmm8, xmm8, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmm5, xmm9\n        movdqa  xmm6, xmm8\n        jmp     @B\n@@:\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        movups  xmmword ptr [rcx], xmm0\n        movups  xmmword ptr [rcx+10H], xmm1\n        movdqa  xmm6, xmmword ptr [rsp]\n        movdqa  xmm7, xmmword ptr [rsp+10H]\n        movdqa  xmm8, xmmword ptr [rsp+20H]\n        movdqa  xmm9, xmmword ptr [rsp+30H]\n        movdqa  xmm11, xmmword ptr [rsp+40H]\n        movdqa  xmm14, xmmword ptr [rsp+50H]\n        movdqa  xmm15, xmmword ptr [rsp+60H]\n        add     rsp, 120\n        ret\n_blake3_compress_in_place_sse2 ENDP\nblake3_compress_in_place_sse2 ENDP\n\nALIGN 16\nblake3_compress_xof_sse2 PROC\n_blake3_compress_xof_sse2 PROC\n        sub     rsp, 120\n        movdqa  xmmword ptr [rsp], xmm6\n        movdqa  xmmword ptr [rsp+10H], xmm7\n        movdqa  xmmword ptr [rsp+20H], xmm8\n        movdqa  xmmword ptr [rsp+30H], xmm9\n        movdqa  xmmword ptr [rsp+40H], xmm11\n        movdqa  xmmword ptr [rsp+50H], xmm14\n        movdqa  xmmword ptr [rsp+60H], xmm15\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        movzx   eax, byte ptr [rsp+0A0H]\n        movzx   r8d, r8b\n        mov     r10, qword ptr [rsp+0A8H]\n        shl     rax, 32\n        add     r8, rax\n        movd    xmm3, r9\n        movd    xmm4, r8\n        punpcklqdq xmm3, xmm4\n        movups  xmm4, xmmword ptr [rdx]\n        movups  xmm5, xmmword ptr [rdx+10H]\n        movaps  xmm8, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm8, xmm5, 221\n        movaps  xmm5, xmm8\n        movups  xmm6, xmmword ptr [rdx+20H]\n        movups  xmm7, xmmword ptr [rdx+30H]\n        movaps  xmm8, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm8, xmm7, 221\n        pshufd  xmm7, xmm8, 93H\n        mov     al, 7\n@@:\n        paddd   xmm0, xmm4\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm5\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        movdqa  xmm14, xmm3\n        psrld   xmm3, 8\n        pslld   xmm14, 24\n        pxor    xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshuflw xmm3, xmm3, 0B1H\n        pshufhw xmm3, xmm3, 0B1H\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm7\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        movdqa  xmm14, xmm3\n        psrld   xmm3, 8\n        pslld   xmm14, 24\n        pxor    xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 93H\n        dec     al\n        jz      @F\n        movdqa  xmm8, xmm4\n        shufps  xmm8, xmm5, 214\n        pshufd  xmm9, xmm4, 0FH\n        pshufd  xmm4, xmm8, 39H\n        movdqa  xmm8, xmm6\n        shufps  xmm8, xmm7, 250\n        pand    xmm9, xmmword ptr [PBLENDW_0x33_MASK]\n        pand    xmm8, xmmword ptr [PBLENDW_0xCC_MASK]\n        por     xmm9, xmm8\n        movdqa  xmm8, xmm7\n        punpcklqdq xmm8, xmm5\n        movdqa  xmm14, xmm6\n        pand    xmm8, xmmword ptr [PBLENDW_0x3F_MASK]\n        pand    xmm14, xmmword ptr [PBLENDW_0xC0_MASK]\n        por     xmm8, xmm14\n        pshufd  xmm8, xmm8, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmm5, xmm9\n        movdqa  xmm6, xmm8\n        jmp     @B\n@@:\n        movdqu  xmm4, xmmword ptr [rcx]\n        movdqu  xmm5, xmmword ptr [rcx+10H]\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        pxor    xmm2, xmm4\n        pxor    xmm3, xmm5\n        movups  xmmword ptr [r10], xmm0\n        movups  xmmword ptr [r10+10H], xmm1\n        movups  xmmword ptr [r10+20H], xmm2\n        movups  xmmword ptr [r10+30H], xmm3\n        movdqa  xmm6, xmmword ptr [rsp]\n        movdqa  xmm7, xmmword ptr [rsp+10H]\n        movdqa  xmm8, xmmword ptr [rsp+20H]\n        movdqa  xmm9, xmmword ptr [rsp+30H]\n        movdqa  xmm11, xmmword ptr [rsp+40H]\n        movdqa  xmm14, xmmword ptr [rsp+50H]\n        movdqa  xmm15, xmmword ptr [rsp+60H]\n        add     rsp, 120\n        ret\n_blake3_compress_xof_sse2 ENDP\nblake3_compress_xof_sse2 ENDP\n\n_TEXT ENDS\n\n\n_RDATA SEGMENT READONLY PAGE ALIAS(\".rdata\") 'CONST'\nALIGN   64\nBLAKE3_IV:\n        dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH\n\nADD0:\n        dd 0, 1, 2, 3\n\nADD1:\n        dd 4 dup (4)\n\nBLAKE3_IV_0:\n        dd 4 dup (6A09E667H)\n\nBLAKE3_IV_1:\n        dd 4 dup (0BB67AE85H)\n\nBLAKE3_IV_2:\n        dd 4 dup (3C6EF372H)\n\nBLAKE3_IV_3:\n        dd 4 dup (0A54FF53AH)\n\nBLAKE3_BLOCK_LEN:\n        dd 4 dup (64)\n\nCMP_MSB_MASK:\n        dd 8 dup(80000000H)\n\nPBLENDW_0x33_MASK:\n       dd 0FFFFFFFFH, 000000000H, 0FFFFFFFFH, 000000000H\nPBLENDW_0xCC_MASK:\n       dd 000000000H, 0FFFFFFFFH, 000000000H, 0FFFFFFFFH\nPBLENDW_0x3F_MASK:\n\tdd 0FFFFFFFFH, 0FFFFFFFFH, 0FFFFFFFFH, 000000000H\nPBLENDW_0xC0_MASK:\n       dd 000000000H, 000000000H, 000000000H, 0FFFFFFFFH\n\n_RDATA ENDS\nEND\n"
  },
  {
    "path": "NanaZip.Codecs/BLAKE3/blake3_sse41_x86-64_windows_msvc.asm",
    "content": "public _blake3_hash_many_sse41\npublic blake3_hash_many_sse41\npublic blake3_compress_in_place_sse41\npublic _blake3_compress_in_place_sse41\npublic blake3_compress_xof_sse41\npublic _blake3_compress_xof_sse41\n\n_TEXT   SEGMENT ALIGN(16) 'CODE'\n\nALIGN   16\nblake3_hash_many_sse41 PROC\n_blake3_hash_many_sse41 PROC\n        push    r15\n        push    r14\n        push    r13\n        push    r12\n        push    rsi\n        push    rdi\n        push    rbx\n        push    rbp\n        mov     rbp, rsp\n        sub     rsp, 528\n        and     rsp, 0FFFFFFFFFFFFFFC0H\n        movdqa  xmmword ptr [rsp+170H], xmm6\n        movdqa  xmmword ptr [rsp+180H], xmm7\n        movdqa  xmmword ptr [rsp+190H], xmm8\n        movdqa  xmmword ptr [rsp+1A0H], xmm9\n        movdqa  xmmword ptr [rsp+1B0H], xmm10\n        movdqa  xmmword ptr [rsp+1C0H], xmm11\n        movdqa  xmmword ptr [rsp+1D0H], xmm12\n        movdqa  xmmword ptr [rsp+1E0H], xmm13\n        movdqa  xmmword ptr [rsp+1F0H], xmm14\n        movdqa  xmmword ptr [rsp+200H], xmm15\n        mov     rdi, rcx\n        mov     rsi, rdx\n        mov     rdx, r8\n        mov     rcx, r9\n        mov     r8, qword ptr [rbp+68H]\n        movzx   r9, byte ptr [rbp+70H]\n        neg     r9d\n        movd    xmm0, r9d\n        pshufd  xmm0, xmm0, 00H\n        movdqa  xmmword ptr [rsp+130H], xmm0\n        movdqa  xmm1, xmm0\n        pand    xmm1, xmmword ptr [ADD0]\n        pand    xmm0, xmmword ptr [ADD1]\n        movdqa  xmmword ptr [rsp+150H], xmm0\n        movd    xmm0, r8d\n        pshufd  xmm0, xmm0, 00H\n        paddd   xmm0, xmm1\n        movdqa  xmmword ptr [rsp+110H], xmm0\n        pxor    xmm0, xmmword ptr [CMP_MSB_MASK]\n        pxor    xmm1, xmmword ptr [CMP_MSB_MASK]\n        pcmpgtd xmm1, xmm0\n        shr     r8, 32\n        movd    xmm2, r8d\n        pshufd  xmm2, xmm2, 00H\n        psubd   xmm2, xmm1\n        movdqa  xmmword ptr [rsp+120H], xmm2\n        mov     rbx, qword ptr [rbp+90H]\n        mov     r15, rdx\n        shl     r15, 6\n        movzx   r13d, byte ptr [rbp+78H]\n        movzx   r12d, byte ptr [rbp+88H]\n        cmp     rsi, 4\n        jc      final3blocks\nouterloop4:\n        movdqu  xmm3, xmmword ptr [rcx]\n        pshufd  xmm0, xmm3, 00H\n        pshufd  xmm1, xmm3, 55H\n        pshufd  xmm2, xmm3, 0AAH\n        pshufd  xmm3, xmm3, 0FFH\n        movdqu  xmm7, xmmword ptr [rcx+10H]\n        pshufd  xmm4, xmm7, 00H\n        pshufd  xmm5, xmm7, 55H\n        pshufd  xmm6, xmm7, 0AAH\n        pshufd  xmm7, xmm7, 0FFH\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        mov     r10, qword ptr [rdi+10H]\n        mov     r11, qword ptr [rdi+18H]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\ninnerloop4:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        movdqu  xmm8, xmmword ptr [r8+rdx-40H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-40H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-40H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-40H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp], xmm8\n        movdqa  xmmword ptr [rsp+10H], xmm9\n        movdqa  xmmword ptr [rsp+20H], xmm12\n        movdqa  xmmword ptr [rsp+30H], xmm13\n        movdqu  xmm8, xmmword ptr [r8+rdx-30H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-30H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-30H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-30H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp+40H], xmm8\n        movdqa  xmmword ptr [rsp+50H], xmm9\n        movdqa  xmmword ptr [rsp+60H], xmm12\n        movdqa  xmmword ptr [rsp+70H], xmm13\n        movdqu  xmm8, xmmword ptr [r8+rdx-20H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-20H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-20H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-20H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp+80H], xmm8\n        movdqa  xmmword ptr [rsp+90H], xmm9\n        movdqa  xmmword ptr [rsp+0A0H], xmm12\n        movdqa  xmmword ptr [rsp+0B0H], xmm13\n        movdqu  xmm8, xmmword ptr [r8+rdx-10H]\n        movdqu  xmm9, xmmword ptr [r9+rdx-10H]\n        movdqu  xmm10, xmmword ptr [r10+rdx-10H]\n        movdqu  xmm11, xmmword ptr [r11+rdx-10H]\n        movdqa  xmm12, xmm8\n        punpckldq xmm8, xmm9\n        punpckhdq xmm12, xmm9\n        movdqa  xmm14, xmm10\n        punpckldq xmm10, xmm11\n        punpckhdq xmm14, xmm11\n        movdqa  xmm9, xmm8\n        punpcklqdq xmm8, xmm10\n        punpckhqdq xmm9, xmm10\n        movdqa  xmm13, xmm12\n        punpcklqdq xmm12, xmm14\n        punpckhqdq xmm13, xmm14\n        movdqa  xmmword ptr [rsp+0C0H], xmm8\n        movdqa  xmmword ptr [rsp+0D0H], xmm9\n        movdqa  xmmword ptr [rsp+0E0H], xmm12\n        movdqa  xmmword ptr [rsp+0F0H], xmm13\n        movdqa  xmm9, xmmword ptr [BLAKE3_IV_1]\n        movdqa  xmm10, xmmword ptr [BLAKE3_IV_2]\n        movdqa  xmm11, xmmword ptr [BLAKE3_IV_3]\n        movdqa  xmm12, xmmword ptr [rsp+110H]\n        movdqa  xmm13, xmmword ptr [rsp+120H]\n        movdqa  xmm14, xmmword ptr [BLAKE3_BLOCK_LEN]\n        movd    xmm15, eax\n        pshufd  xmm15, xmm15, 00H\n        prefetcht0 byte ptr [r8+rdx+80H]\n        prefetcht0 byte ptr [r9+rdx+80H]\n        prefetcht0 byte ptr [r10+rdx+80H]\n        prefetcht0 byte ptr [r11+rdx+80H]\n        paddd   xmm0, xmmword ptr [rsp]\n        paddd   xmm1, xmmword ptr [rsp+20H]\n        paddd   xmm2, xmmword ptr [rsp+40H]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [BLAKE3_IV_0]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+10H]\n        paddd   xmm1, xmmword ptr [rsp+30H]\n        paddd   xmm2, xmmword ptr [rsp+50H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+80H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp+0C0H]\n        paddd   xmm3, xmmword ptr [rsp+0E0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+90H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+0D0H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+20H]\n        paddd   xmm1, xmmword ptr [rsp+30H]\n        paddd   xmm2, xmmword ptr [rsp+70H]\n        paddd   xmm3, xmmword ptr [rsp+40H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+60H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp]\n        paddd   xmm3, xmmword ptr [rsp+0D0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+10H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+90H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0B0H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp+0E0H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+30H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp+0D0H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+40H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+20H]\n        paddd   xmm3, xmmword ptr [rsp+0E0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+60H]\n        paddd   xmm1, xmmword ptr [rsp+90H]\n        paddd   xmm2, xmmword ptr [rsp+0B0H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+50H]\n        paddd   xmm1, xmmword ptr [rsp]\n        paddd   xmm2, xmmword ptr [rsp+0F0H]\n        paddd   xmm3, xmmword ptr [rsp+10H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0A0H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+0E0H]\n        paddd   xmm3, xmmword ptr [rsp+0D0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+70H]\n        paddd   xmm1, xmmword ptr [rsp+90H]\n        paddd   xmm2, xmmword ptr [rsp+30H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+40H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+50H]\n        paddd   xmm3, xmmword ptr [rsp+10H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp]\n        paddd   xmm1, xmmword ptr [rsp+20H]\n        paddd   xmm2, xmmword ptr [rsp+80H]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0C0H]\n        paddd   xmm1, xmmword ptr [rsp+90H]\n        paddd   xmm2, xmmword ptr [rsp+0F0H]\n        paddd   xmm3, xmmword ptr [rsp+0E0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0D0H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+0A0H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+70H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+20H]\n        paddd   xmm1, xmmword ptr [rsp+30H]\n        paddd   xmm2, xmmword ptr [rsp+10H]\n        paddd   xmm3, xmmword ptr [rsp+40H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+90H]\n        paddd   xmm1, xmmword ptr [rsp+0B0H]\n        paddd   xmm2, xmmword ptr [rsp+80H]\n        paddd   xmm3, xmmword ptr [rsp+0F0H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0E0H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp+0C0H]\n        paddd   xmm3, xmmword ptr [rsp+10H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0D0H]\n        paddd   xmm1, xmmword ptr [rsp]\n        paddd   xmm2, xmmword ptr [rsp+20H]\n        paddd   xmm3, xmmword ptr [rsp+40H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+30H]\n        paddd   xmm1, xmmword ptr [rsp+0A0H]\n        paddd   xmm2, xmmword ptr [rsp+60H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0B0H]\n        paddd   xmm1, xmmword ptr [rsp+50H]\n        paddd   xmm2, xmmword ptr [rsp+10H]\n        paddd   xmm3, xmmword ptr [rsp+80H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0F0H]\n        paddd   xmm1, xmmword ptr [rsp]\n        paddd   xmm2, xmmword ptr [rsp+90H]\n        paddd   xmm3, xmmword ptr [rsp+60H]\n        paddd   xmm0, xmm4\n        paddd   xmm1, xmm5\n        paddd   xmm2, xmm6\n        paddd   xmm3, xmm7\n        pxor    xmm12, xmm0\n        pxor    xmm13, xmm1\n        pxor    xmm14, xmm2\n        pxor    xmm15, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        pshufb  xmm15, xmm8\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm12\n        paddd   xmm9, xmm13\n        paddd   xmm10, xmm14\n        paddd   xmm11, xmm15\n        pxor    xmm4, xmm8\n        pxor    xmm5, xmm9\n        pxor    xmm6, xmm10\n        pxor    xmm7, xmm11\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0E0H]\n        paddd   xmm1, xmmword ptr [rsp+20H]\n        paddd   xmm2, xmmword ptr [rsp+30H]\n        paddd   xmm3, xmmword ptr [rsp+70H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT16]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        movdqa  xmmword ptr [rsp+100H], xmm8\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 12\n        pslld   xmm5, 20\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 12\n        pslld   xmm6, 20\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 12\n        pslld   xmm7, 20\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 12\n        pslld   xmm4, 20\n        por     xmm4, xmm8\n        paddd   xmm0, xmmword ptr [rsp+0A0H]\n        paddd   xmm1, xmmword ptr [rsp+0C0H]\n        paddd   xmm2, xmmword ptr [rsp+40H]\n        paddd   xmm3, xmmword ptr [rsp+0D0H]\n        paddd   xmm0, xmm5\n        paddd   xmm1, xmm6\n        paddd   xmm2, xmm7\n        paddd   xmm3, xmm4\n        pxor    xmm15, xmm0\n        pxor    xmm12, xmm1\n        pxor    xmm13, xmm2\n        pxor    xmm14, xmm3\n        movdqa  xmm8, xmmword ptr [ROT8]\n        pshufb  xmm15, xmm8\n        pshufb  xmm12, xmm8\n        pshufb  xmm13, xmm8\n        pshufb  xmm14, xmm8\n        paddd   xmm10, xmm15\n        paddd   xmm11, xmm12\n        movdqa  xmm8, xmmword ptr [rsp+100H]\n        paddd   xmm8, xmm13\n        paddd   xmm9, xmm14\n        pxor    xmm5, xmm10\n        pxor    xmm6, xmm11\n        pxor    xmm7, xmm8\n        pxor    xmm4, xmm9\n        pxor    xmm0, xmm8\n        pxor    xmm1, xmm9\n        pxor    xmm2, xmm10\n        pxor    xmm3, xmm11\n        movdqa  xmm8, xmm5\n        psrld   xmm8, 7\n        pslld   xmm5, 25\n        por     xmm5, xmm8\n        movdqa  xmm8, xmm6\n        psrld   xmm8, 7\n        pslld   xmm6, 25\n        por     xmm6, xmm8\n        movdqa  xmm8, xmm7\n        psrld   xmm8, 7\n        pslld   xmm7, 25\n        por     xmm7, xmm8\n        movdqa  xmm8, xmm4\n        psrld   xmm8, 7\n        pslld   xmm4, 25\n        por     xmm4, xmm8\n        pxor    xmm4, xmm12\n        pxor    xmm5, xmm13\n        pxor    xmm6, xmm14\n        pxor    xmm7, xmm15\n        mov     eax, r13d\n        jne     innerloop4\n        movdqa  xmm9, xmm0\n        punpckldq xmm0, xmm1\n        punpckhdq xmm9, xmm1\n        movdqa  xmm11, xmm2\n        punpckldq xmm2, xmm3\n        punpckhdq xmm11, xmm3\n        movdqa  xmm1, xmm0\n        punpcklqdq xmm0, xmm2\n        punpckhqdq xmm1, xmm2\n        movdqa  xmm3, xmm9\n        punpcklqdq xmm9, xmm11\n        punpckhqdq xmm3, xmm11\n        movdqu  xmmword ptr [rbx], xmm0\n        movdqu  xmmword ptr [rbx+20H], xmm1\n        movdqu  xmmword ptr [rbx+40H], xmm9\n        movdqu  xmmword ptr [rbx+60H], xmm3\n        movdqa  xmm9, xmm4\n        punpckldq xmm4, xmm5\n        punpckhdq xmm9, xmm5\n        movdqa  xmm11, xmm6\n        punpckldq xmm6, xmm7\n        punpckhdq xmm11, xmm7\n        movdqa  xmm5, xmm4\n        punpcklqdq xmm4, xmm6\n        punpckhqdq xmm5, xmm6\n        movdqa  xmm7, xmm9\n        punpcklqdq xmm9, xmm11\n        punpckhqdq xmm7, xmm11\n        movdqu  xmmword ptr [rbx+10H], xmm4\n        movdqu  xmmword ptr [rbx+30H], xmm5\n        movdqu  xmmword ptr [rbx+50H], xmm9\n        movdqu  xmmword ptr [rbx+70H], xmm7\n        movdqa  xmm1, xmmword ptr [rsp+110H]\n        movdqa  xmm0, xmm1\n        paddd   xmm1, xmmword ptr [rsp+150H]\n        movdqa  xmmword ptr [rsp+110H], xmm1\n        pxor    xmm0, xmmword ptr [CMP_MSB_MASK]\n        pxor    xmm1, xmmword ptr [CMP_MSB_MASK]\n        pcmpgtd xmm0, xmm1\n        movdqa  xmm1, xmmword ptr [rsp+120H]\n        psubd   xmm1, xmm0\n        movdqa  xmmword ptr [rsp+120H], xmm1\n        add     rbx, 128\n        add     rdi, 32\n        sub     rsi, 4\n        cmp     rsi, 4\n        jnc     outerloop4\n        test    rsi, rsi\n        jne     final3blocks\nunwind:\n        movdqa  xmm6, xmmword ptr [rsp+170H]\n        movdqa  xmm7, xmmword ptr [rsp+180H]\n        movdqa  xmm8, xmmword ptr [rsp+190H]\n        movdqa  xmm9, xmmword ptr [rsp+1A0H]\n        movdqa  xmm10, xmmword ptr [rsp+1B0H]\n        movdqa  xmm11, xmmword ptr [rsp+1C0H]\n        movdqa  xmm12, xmmword ptr [rsp+1D0H]\n        movdqa  xmm13, xmmword ptr [rsp+1E0H]\n        movdqa  xmm14, xmmword ptr [rsp+1F0H]\n        movdqa  xmm15, xmmword ptr [rsp+200H]\n        mov     rsp, rbp\n        pop     rbp\n        pop     rbx\n        pop     rdi\n        pop     rsi\n        pop     r12\n        pop     r13\n        pop     r14\n        pop     r15\n        ret\nALIGN   16\nfinal3blocks:\n        test    esi, 2H\n        je      final1block\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movaps  xmm8, xmm0\n        movaps  xmm9, xmm1\n        movd    xmm13, dword ptr [rsp+110H]\n        pinsrd  xmm13, dword ptr [rsp+120H], 1\n        pinsrd  xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2\n        movaps  xmmword ptr [rsp], xmm13\n        movd    xmm14, dword ptr [rsp+114H]\n        pinsrd  xmm14, dword ptr [rsp+124H], 1\n        pinsrd  xmm14, dword ptr [BLAKE3_BLOCK_LEN], 2\n        movaps  xmmword ptr [rsp+10H], xmm14\n        mov     r8, qword ptr [rdi]\n        mov     r9, qword ptr [rdi+8H]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\ninnerloop2:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        movaps  xmm10, xmm2\n        movups  xmm4, xmmword ptr [r8+rdx-40H]\n        movups  xmm5, xmmword ptr [r8+rdx-30H]\n        movaps  xmm3, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm3, xmm5, 221\n        movaps  xmm5, xmm3\n        movups  xmm6, xmmword ptr [r8+rdx-20H]\n        movups  xmm7, xmmword ptr [r8+rdx-10H]\n        movaps  xmm3, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm3, xmm7, 221\n        pshufd  xmm7, xmm3, 93H\n        movups  xmm12, xmmword ptr [r9+rdx-40H]\n        movups  xmm13, xmmword ptr [r9+rdx-30H]\n        movaps  xmm11, xmm12\n        shufps  xmm12, xmm13, 136\n        shufps  xmm11, xmm13, 221\n        movaps  xmm13, xmm11\n        movups  xmm14, xmmword ptr [r9+rdx-20H]\n        movups  xmm15, xmmword ptr [r9+rdx-10H]\n        movaps  xmm11, xmm14\n        shufps  xmm14, xmm15, 136\n        pshufd  xmm14, xmm14, 93H\n        shufps  xmm11, xmm15, 221\n        pshufd  xmm15, xmm11, 93H\n        movaps  xmm3, xmmword ptr [rsp]\n        movaps  xmm11, xmmword ptr [rsp+10H]\n        pinsrd  xmm3, eax, 3\n        pinsrd  xmm11, eax, 3\n        mov     al, 7\nroundloop2:\n        paddd   xmm0, xmm4\n        paddd   xmm8, xmm12\n        movaps  xmmword ptr [rsp+20H], xmm4\n        movaps  xmmword ptr [rsp+30H], xmm12\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        movaps  xmm12, xmmword ptr [ROT16]\n        pshufb  xmm3, xmm12\n        pshufb  xmm11, xmm12\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 20\n        psrld   xmm4, 12\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 20\n        psrld   xmm4, 12\n        por     xmm9, xmm4\n        paddd   xmm0, xmm5\n        paddd   xmm8, xmm13\n        movaps  xmmword ptr [rsp+40H], xmm5\n        movaps  xmmword ptr [rsp+50H], xmm13\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        movaps  xmm13, xmmword ptr [ROT8]\n        pshufb  xmm3, xmm13\n        pshufb  xmm11, xmm13\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 25\n        psrld   xmm4, 7\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 25\n        psrld   xmm4, 7\n        por     xmm9, xmm4\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm8, xmm8, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm11, xmm11, 4EH\n        pshufd  xmm2, xmm2, 39H\n        pshufd  xmm10, xmm10, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm8, xmm14\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        pshufb  xmm3, xmm12\n        pshufb  xmm11, xmm12\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 20\n        psrld   xmm4, 12\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 20\n        psrld   xmm4, 12\n        por     xmm9, xmm4\n        paddd   xmm0, xmm7\n        paddd   xmm8, xmm15\n        paddd   xmm0, xmm1\n        paddd   xmm8, xmm9\n        pxor    xmm3, xmm0\n        pxor    xmm11, xmm8\n        pshufb  xmm3, xmm13\n        pshufb  xmm11, xmm13\n        paddd   xmm2, xmm3\n        paddd   xmm10, xmm11\n        pxor    xmm1, xmm2\n        pxor    xmm9, xmm10\n        movdqa  xmm4, xmm1\n        pslld   xmm1, 25\n        psrld   xmm4, 7\n        por     xmm1, xmm4\n        movdqa  xmm4, xmm9\n        pslld   xmm9, 25\n        psrld   xmm4, 7\n        por     xmm9, xmm4\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm8, xmm8, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm11, xmm11, 4EH\n        pshufd  xmm2, xmm2, 93H\n        pshufd  xmm10, xmm10, 93H\n        dec     al\n        je      endroundloop2\n        movdqa  xmm12, xmmword ptr [rsp+20H]\n        movdqa  xmm5, xmmword ptr [rsp+40H]\n        pshufd  xmm13, xmm12, 0FH\n        shufps  xmm12, xmm5, 214\n        pshufd  xmm4, xmm12, 39H\n        movdqa  xmm12, xmm6\n        shufps  xmm12, xmm7, 250\n        pblendw xmm13, xmm12, 0CCH\n        movdqa  xmm12, xmm7\n        punpcklqdq xmm12, xmm5\n        pblendw xmm12, xmm6, 0C0H\n        pshufd  xmm12, xmm12, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmmword ptr [rsp+20H], xmm13\n        movdqa  xmmword ptr [rsp+40H], xmm12\n        movdqa  xmm5, xmmword ptr [rsp+30H]\n        movdqa  xmm13, xmmword ptr [rsp+50H]\n        pshufd  xmm6, xmm5, 0FH\n        shufps  xmm5, xmm13, 214\n        pshufd  xmm12, xmm5, 39H\n        movdqa  xmm5, xmm14\n        shufps  xmm5, xmm15, 250\n        pblendw xmm6, xmm5, 0CCH\n        movdqa  xmm5, xmm15\n        punpcklqdq xmm5, xmm13\n        pblendw xmm5, xmm14, 0C0H\n        pshufd  xmm5, xmm5, 78H\n        punpckhdq xmm13, xmm15\n        punpckldq xmm14, xmm13\n        pshufd  xmm15, xmm14, 1EH\n        movdqa  xmm13, xmm6\n        movdqa  xmm14, xmm5\n        movdqa  xmm5, xmmword ptr [rsp+20H]\n        movdqa  xmm6, xmmword ptr [rsp+40H]\n        jmp     roundloop2\nendroundloop2:\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        pxor    xmm8, xmm10\n        pxor    xmm9, xmm11\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop2\n        movups  xmmword ptr [rbx], xmm0\n        movups  xmmword ptr [rbx+10H], xmm1\n        movups  xmmword ptr [rbx+20H], xmm8\n        movups  xmmword ptr [rbx+30H], xmm9\n        movdqa  xmm0, xmmword ptr [rsp+130H]\n        movdqa  xmm1, xmmword ptr [rsp+110H]\n        movdqa  xmm2, xmmword ptr [rsp+120H]\n        movdqu  xmm3, xmmword ptr [rsp+118H]\n        movdqu  xmm4, xmmword ptr [rsp+128H]\n        blendvps xmm1, xmm3, xmm0\n        blendvps xmm2, xmm4, xmm0\n        movdqa  xmmword ptr [rsp+110H], xmm1\n        movdqa  xmmword ptr [rsp+120H], xmm2\n        add     rdi, 16\n        add     rbx, 64\n        sub     rsi, 2\nfinal1block:\n        test    esi, 1H\n        je      unwind\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movd    xmm13, dword ptr [rsp+110H]\n        pinsrd  xmm13, dword ptr [rsp+120H], 1\n        pinsrd  xmm13, dword ptr [BLAKE3_BLOCK_LEN], 2\n        movaps  xmm14, xmmword ptr [ROT8]\n        movaps  xmm15, xmmword ptr [ROT16]\n        mov     r8, qword ptr [rdi]\n        movzx   eax, byte ptr [rbp+80H]\n        or      eax, r13d\n        xor     edx, edx\ninnerloop1:\n        mov     r14d, eax\n        or      eax, r12d\n        add     rdx, 64\n        cmp     rdx, r15\n        cmovne  eax, r14d\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        movaps  xmm3, xmm13\n        pinsrd  xmm3, eax, 3\n        movups  xmm4, xmmword ptr [r8+rdx-40H]\n        movups  xmm5, xmmword ptr [r8+rdx-30H]\n        movaps  xmm8, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm8, xmm5, 221\n        movaps  xmm5, xmm8\n        movups  xmm6, xmmword ptr [r8+rdx-20H]\n        movups  xmm7, xmmword ptr [r8+rdx-10H]\n        movaps  xmm8, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm8, xmm7, 221\n        pshufd  xmm7, xmm8, 93H\n        mov     al, 7\nroundloop1:\n        paddd   xmm0, xmm4\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm15\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm5\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm15\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm7\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 93H\n        dec     al\n        jz      endroundloop1\n        movdqa  xmm8, xmm4\n        shufps  xmm8, xmm5, 214\n        pshufd  xmm9, xmm4, 0FH\n        pshufd  xmm4, xmm8, 39H\n        movdqa  xmm8, xmm6\n        shufps  xmm8, xmm7, 250\n        pblendw xmm9, xmm8, 0CCH\n        movdqa  xmm8, xmm7\n        punpcklqdq xmm8, xmm5\n        pblendw xmm8, xmm6, 0C0H\n        pshufd  xmm8, xmm8, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmm5, xmm9\n        movdqa  xmm6, xmm8\n        jmp     roundloop1\nendroundloop1:\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        mov     eax, r13d\n        cmp     rdx, r15\n        jne     innerloop1\n        movups  xmmword ptr [rbx], xmm0\n        movups  xmmword ptr [rbx+10H], xmm1\n        jmp     unwind\n_blake3_hash_many_sse41 ENDP\nblake3_hash_many_sse41 ENDP\n\nblake3_compress_in_place_sse41 PROC\n_blake3_compress_in_place_sse41 PROC\n        sub     rsp, 120\n        movdqa  xmmword ptr [rsp], xmm6\n        movdqa  xmmword ptr [rsp+10H], xmm7\n        movdqa  xmmword ptr [rsp+20H], xmm8\n        movdqa  xmmword ptr [rsp+30H], xmm9\n        movdqa  xmmword ptr [rsp+40H], xmm11\n        movdqa  xmmword ptr [rsp+50H], xmm14\n        movdqa  xmmword ptr [rsp+60H], xmm15\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        movzx   eax, byte ptr [rsp+0A0H]\n        movzx   r8d, r8b\n        shl     rax, 32\n        add     r8, rax\n        movd    xmm3, r9\n        movd    xmm4, r8\n        punpcklqdq xmm3, xmm4\n        movups  xmm4, xmmword ptr [rdx]\n        movups  xmm5, xmmword ptr [rdx+10H]\n        movaps  xmm8, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm8, xmm5, 221\n        movaps  xmm5, xmm8\n        movups  xmm6, xmmword ptr [rdx+20H]\n        movups  xmm7, xmmword ptr [rdx+30H]\n        movaps  xmm8, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm8, xmm7, 221\n        pshufd  xmm7, xmm8, 93H\n        movaps  xmm14, xmmword ptr [ROT8]\n        movaps  xmm15, xmmword ptr [ROT16]\n        mov     al, 7\n@@:\n        paddd   xmm0, xmm4\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm15\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm5\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm15\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm7\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 93H\n        dec     al\n        jz      @F\n        movdqa  xmm8, xmm4\n        shufps  xmm8, xmm5, 214\n        pshufd  xmm9, xmm4, 0FH\n        pshufd  xmm4, xmm8, 39H\n        movdqa  xmm8, xmm6\n        shufps  xmm8, xmm7, 250\n        pblendw xmm9, xmm8, 0CCH\n        movdqa  xmm8, xmm7\n        punpcklqdq xmm8, xmm5\n        pblendw xmm8, xmm6, 0C0H\n        pshufd  xmm8, xmm8, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmm5, xmm9\n        movdqa  xmm6, xmm8\n        jmp     @B\n@@:\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        movups  xmmword ptr [rcx], xmm0\n        movups  xmmword ptr [rcx+10H], xmm1\n        movdqa  xmm6, xmmword ptr [rsp]\n        movdqa  xmm7, xmmword ptr [rsp+10H]\n        movdqa  xmm8, xmmword ptr [rsp+20H]\n        movdqa  xmm9, xmmword ptr [rsp+30H]\n        movdqa  xmm11, xmmword ptr [rsp+40H]\n        movdqa  xmm14, xmmword ptr [rsp+50H]\n        movdqa  xmm15, xmmword ptr [rsp+60H]\n        add     rsp, 120\n        ret\n_blake3_compress_in_place_sse41 ENDP\nblake3_compress_in_place_sse41 ENDP\n\nALIGN 16\nblake3_compress_xof_sse41 PROC\n_blake3_compress_xof_sse41 PROC\n        sub     rsp, 120\n        movdqa  xmmword ptr [rsp], xmm6\n        movdqa  xmmword ptr [rsp+10H], xmm7\n        movdqa  xmmword ptr [rsp+20H], xmm8\n        movdqa  xmmword ptr [rsp+30H], xmm9\n        movdqa  xmmword ptr [rsp+40H], xmm11\n        movdqa  xmmword ptr [rsp+50H], xmm14\n        movdqa  xmmword ptr [rsp+60H], xmm15\n        movups  xmm0, xmmword ptr [rcx]\n        movups  xmm1, xmmword ptr [rcx+10H]\n        movaps  xmm2, xmmword ptr [BLAKE3_IV]\n        movzx   eax, byte ptr [rsp+0A0H]\n        movzx   r8d, r8b\n        mov     r10, qword ptr [rsp+0A8H]\n        shl     rax, 32\n        add     r8, rax\n        movd    xmm3, r9\n        movd    xmm4, r8\n        punpcklqdq xmm3, xmm4\n        movups  xmm4, xmmword ptr [rdx]\n        movups  xmm5, xmmword ptr [rdx+10H]\n        movaps  xmm8, xmm4\n        shufps  xmm4, xmm5, 136\n        shufps  xmm8, xmm5, 221\n        movaps  xmm5, xmm8\n        movups  xmm6, xmmword ptr [rdx+20H]\n        movups  xmm7, xmmword ptr [rdx+30H]\n        movaps  xmm8, xmm6\n        shufps  xmm6, xmm7, 136\n        pshufd  xmm6, xmm6, 93H\n        shufps  xmm8, xmm7, 221\n        pshufd  xmm7, xmm8, 93H\n        movaps  xmm14, xmmword ptr [ROT8]\n        movaps  xmm15, xmmword ptr [ROT16]\n        mov     al, 7\n@@:\n        paddd   xmm0, xmm4\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm15\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm5\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 93H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 39H\n        paddd   xmm0, xmm6\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm15\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 20\n        psrld   xmm11, 12\n        por     xmm1, xmm11\n        paddd   xmm0, xmm7\n        paddd   xmm0, xmm1\n        pxor    xmm3, xmm0\n        pshufb  xmm3, xmm14\n        paddd   xmm2, xmm3\n        pxor    xmm1, xmm2\n        movdqa  xmm11, xmm1\n        pslld   xmm1, 25\n        psrld   xmm11, 7\n        por     xmm1, xmm11\n        pshufd  xmm0, xmm0, 39H\n        pshufd  xmm3, xmm3, 4EH\n        pshufd  xmm2, xmm2, 93H\n        dec     al\n        jz      @F\n        movdqa  xmm8, xmm4\n        shufps  xmm8, xmm5, 214\n        pshufd  xmm9, xmm4, 0FH\n        pshufd  xmm4, xmm8, 39H\n        movdqa  xmm8, xmm6\n        shufps  xmm8, xmm7, 250\n        pblendw xmm9, xmm8, 0CCH\n        movdqa  xmm8, xmm7\n        punpcklqdq xmm8, xmm5\n        pblendw xmm8, xmm6, 0C0H\n        pshufd  xmm8, xmm8, 78H\n        punpckhdq xmm5, xmm7\n        punpckldq xmm6, xmm5\n        pshufd  xmm7, xmm6, 1EH\n        movdqa  xmm5, xmm9\n        movdqa  xmm6, xmm8\n        jmp     @B\n@@:\n        movdqu  xmm4, xmmword ptr [rcx]\n        movdqu  xmm5, xmmword ptr [rcx+10H]\n        pxor    xmm0, xmm2\n        pxor    xmm1, xmm3\n        pxor    xmm2, xmm4\n        pxor    xmm3, xmm5\n        movups  xmmword ptr [r10], xmm0\n        movups  xmmword ptr [r10+10H], xmm1\n        movups  xmmword ptr [r10+20H], xmm2\n        movups  xmmword ptr [r10+30H], xmm3\n        movdqa  xmm6, xmmword ptr [rsp]\n        movdqa  xmm7, xmmword ptr [rsp+10H]\n        movdqa  xmm8, xmmword ptr [rsp+20H]\n        movdqa  xmm9, xmmword ptr [rsp+30H]\n        movdqa  xmm11, xmmword ptr [rsp+40H]\n        movdqa  xmm14, xmmword ptr [rsp+50H]\n        movdqa  xmm15, xmmword ptr [rsp+60H]\n        add     rsp, 120\n        ret\n_blake3_compress_xof_sse41 ENDP\nblake3_compress_xof_sse41 ENDP\n\n_TEXT ENDS\n\n\n_RDATA SEGMENT READONLY PAGE ALIAS(\".rdata\") 'CONST'\nALIGN   64\nBLAKE3_IV:\n        dd 6A09E667H, 0BB67AE85H, 3C6EF372H, 0A54FF53AH\n\nADD0:\n        dd 0, 1, 2, 3\n\nADD1:\n        dd 4 dup (4)\n\nBLAKE3_IV_0:\n        dd 4 dup (6A09E667H)\n\nBLAKE3_IV_1:\n        dd 4 dup (0BB67AE85H)\n\nBLAKE3_IV_2:\n        dd 4 dup (3C6EF372H)\n\nBLAKE3_IV_3:\n        dd 4 dup (0A54FF53AH)\n\nBLAKE3_BLOCK_LEN:\n        dd 4 dup (64)\n\nROT16:\n        db 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13\n\nROT8:\n        db 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12\n\nCMP_MSB_MASK:\n        dd 8 dup(80000000H)\n\n_RDATA ENDS\nEND\n\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/constants.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"constants.h\"\n\nconst BROTLI_MODEL(\"small\")\nBrotliPrefixCodeRange _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {\n    {1, 2},     {5, 2},     {9, 2},   {13, 2},    {17, 3},    {25, 3},\n    {33, 3},    {41, 3},    {49, 4},  {65, 4},    {81, 4},    {97, 4},\n    {113, 5},   {145, 5},   {177, 5}, {209, 5},   {241, 6},   {305, 6},\n    {369, 7},   {497, 8},   {753, 9}, {1265, 10}, {2289, 11}, {4337, 12},\n    {8433, 13}, {16625, 24}};\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/constants.h",
    "content": "﻿/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * Common constants used in decoder and encoder API.\n */\n\n#ifndef BROTLI_COMMON_CONSTANTS_H_\n#define BROTLI_COMMON_CONSTANTS_H_\n\n#include \"platform.h\"\n\n/* Specification: 7.3. Encoding of the context map */\n#define BROTLI_CONTEXT_MAP_MAX_RLE 16\n\n/* Specification: 2. Compressed representation overview */\n#define BROTLI_MAX_NUMBER_OF_BLOCK_TYPES 256\n\n/* Specification: 3.3. Alphabet sizes: insert-and-copy length */\n#define BROTLI_NUM_LITERAL_SYMBOLS 256\n#define BROTLI_NUM_COMMAND_SYMBOLS 704\n#define BROTLI_NUM_BLOCK_LEN_SYMBOLS 26\n#define BROTLI_MAX_CONTEXT_MAP_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + \\\n                                        BROTLI_CONTEXT_MAP_MAX_RLE)\n#define BROTLI_MAX_BLOCK_TYPE_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 2)\n\n/* Specification: 3.5. Complex prefix codes */\n#define BROTLI_REPEAT_PREVIOUS_CODE_LENGTH 16\n#define BROTLI_REPEAT_ZERO_CODE_LENGTH 17\n#define BROTLI_CODE_LENGTH_CODES (BROTLI_REPEAT_ZERO_CODE_LENGTH + 1)\n/* \"code length of 8 is repeated\" */\n#define BROTLI_INITIAL_REPEATED_CODE_LENGTH 8\n\n/* \"Large Window Brotli\" */\n\n/**\n * The theoretical maximum number of distance bits specified for large window\n * brotli, for 64-bit encoders and decoders. Even when in practice 32-bit\n * encoders and decoders only support up to 30 max distance bits, the value is\n * set to 62 because it affects the large window brotli file format.\n * Specifically, it affects the encoding of simple huffman tree for distances,\n * see Specification RFC 7932 chapter 3.4.\n */\n#define BROTLI_LARGE_MAX_DISTANCE_BITS 62U\n#define BROTLI_LARGE_MIN_WBITS 10\n/**\n * The maximum supported large brotli window bits by the encoder and decoder.\n * Large window brotli allows up to 62 bits, however the current encoder and\n * decoder, designed for 32-bit integers, only support up to 30 bits maximum.\n */\n#define BROTLI_LARGE_MAX_WBITS 30\n\n/* Specification: 4. Encoding of distances */\n#define BROTLI_NUM_DISTANCE_SHORT_CODES 16\n/**\n * Maximal number of \"postfix\" bits.\n *\n * Number of \"postfix\" bits is stored as 2 bits in meta-block header.\n */\n#define BROTLI_MAX_NPOSTFIX 3\n#define BROTLI_MAX_NDIRECT 120\n#define BROTLI_MAX_DISTANCE_BITS 24U\n#define BROTLI_DISTANCE_ALPHABET_SIZE(NPOSTFIX, NDIRECT, MAXNBITS) ( \\\n    BROTLI_NUM_DISTANCE_SHORT_CODES + (NDIRECT) +                    \\\n    ((MAXNBITS) << ((NPOSTFIX) + 1)))\n/* BROTLI_NUM_DISTANCE_SYMBOLS == 1128 */\n#define BROTLI_NUM_DISTANCE_SYMBOLS \\\n    BROTLI_DISTANCE_ALPHABET_SIZE(  \\\n        BROTLI_MAX_NDIRECT, BROTLI_MAX_NPOSTFIX, BROTLI_LARGE_MAX_DISTANCE_BITS)\n\n/* ((1 << 26) - 4) is the maximal distance that can be expressed in RFC 7932\n   brotli stream using NPOSTFIX = 0 and NDIRECT = 0. With other NPOSTFIX and\n   NDIRECT values distances up to ((1 << 29) + 88) could be expressed. */\n#define BROTLI_MAX_DISTANCE 0x3FFFFFC\n\n/* ((1 << 31) - 4) is the safe distance limit. Using this number as a limit\n   allows safe distance calculation without overflows, given the distance\n   alphabet size is limited to corresponding size\n   (see kLargeWindowDistanceCodeLimits). */\n#define BROTLI_MAX_ALLOWED_DISTANCE 0x7FFFFFFC\n\n\n/* Specification: 4. Encoding of Literal Insertion Lengths and Copy Lengths */\n#define BROTLI_NUM_INS_COPY_CODES 24\n\n/* 7.1. Context modes and context ID lookup for literals */\n/* \"context IDs for literals are in the range of 0..63\" */\n#define BROTLI_LITERAL_CONTEXT_BITS 6\n\n/* 7.2. Context ID for distances */\n#define BROTLI_DISTANCE_CONTEXT_BITS 2\n\n/* 9.1. Format of the Stream Header */\n/* Number of slack bytes for window size. Don't confuse\n   with BROTLI_NUM_DISTANCE_SHORT_CODES. */\n#define BROTLI_WINDOW_GAP 16\n#define BROTLI_MAX_BACKWARD_LIMIT(W) (((size_t)1 << (W)) - BROTLI_WINDOW_GAP)\n\ntypedef struct BrotliDistanceCodeLimit {\n  uint32_t max_alphabet_size;\n  uint32_t max_distance;\n} BrotliDistanceCodeLimit;\n\n/* This function calculates maximal size of distance alphabet, such that the\n   distances greater than the given values can not be represented.\n\n   This limits are designed to support fast and safe 32-bit decoders.\n   \"32-bit\" means that signed integer values up to ((1 << 31) - 1) could be\n   safely expressed.\n\n   Brotli distance alphabet symbols do not represent consecutive distance\n   ranges. Each distance alphabet symbol (excluding direct distances and short\n   codes), represent interleaved (for NPOSTFIX > 0) range of distances.\n   A \"group\" of consecutive (1 << NPOSTFIX) symbols represent non-interleaved\n   range. Two consecutive groups require the same amount of \"extra bits\".\n\n   It is important that distance alphabet represents complete \"groups\".\n   To avoid complex logic on encoder side about interleaved ranges\n   it was decided to restrict both sides to complete distance code \"groups\".\n */\nBROTLI_UNUSED_FUNCTION BrotliDistanceCodeLimit BrotliCalculateDistanceCodeLimit(\n    uint32_t max_distance, uint32_t npostfix, uint32_t ndirect) {\n  BrotliDistanceCodeLimit result;\n  /* Marking this function as unused, because not all files\n     including \"constants.h\" use it -> compiler warns about that. */\n  BROTLI_UNUSED(&BrotliCalculateDistanceCodeLimit);\n  if (max_distance <= ndirect) {\n    /* This case never happens / exists only for the sake of completeness. */\n    result.max_alphabet_size = max_distance + BROTLI_NUM_DISTANCE_SHORT_CODES;\n    result.max_distance = max_distance;\n    return result;\n  } else {\n    /* The first prohibited value. */\n    uint32_t forbidden_distance = max_distance + 1;\n    /* Subtract \"directly\" encoded region. */\n    uint32_t offset = forbidden_distance - ndirect - 1;\n    uint32_t ndistbits = 0;\n    uint32_t tmp;\n    uint32_t half;\n    uint32_t group;\n    /* Postfix for the last dcode in the group. */\n    uint32_t postfix = (1u << npostfix) - 1;\n    uint32_t extra;\n    uint32_t start;\n    /* Remove postfix and \"head-start\". */\n    offset = (offset >> npostfix) + 4;\n    /* Calculate the number of distance bits. */\n    tmp = offset / 2;\n    /* Poor-man's log2floor, to avoid extra dependencies. */\n    while (tmp != 0) {ndistbits++; tmp = tmp >> 1;}\n    /* One bit is covered with subrange addressing (\"half\"). */\n    ndistbits--;\n    /* Find subrange. */\n    half = (offset >> ndistbits) & 1;\n    /* Calculate the \"group\" part of dcode. */\n    group = ((ndistbits - 1) << 1) | half;\n    /* Calculated \"group\" covers the prohibited distance value. */\n    if (group == 0) {\n      /* This case is added for correctness; does not occur for limit > 128. */\n      result.max_alphabet_size = ndirect + BROTLI_NUM_DISTANCE_SHORT_CODES;\n      result.max_distance = ndirect;\n      return result;\n    }\n    /* Decrement \"group\", so it is the last permitted \"group\". */\n    group--;\n    /* After group was decremented, ndistbits and half must be recalculated. */\n    ndistbits = (group >> 1) + 1;\n    /* The last available distance in the subrange has all extra bits set. */\n    extra = (1u << ndistbits) - 1;\n    /* Calculate region start. NB: ndistbits >= 1. */\n    start = (1u << (ndistbits + 1)) - 4;\n    /* Move to subregion. */\n    start += (group & 1) << ndistbits;\n    /* Calculate the alphabet size. */\n    result.max_alphabet_size = ((group << npostfix) | postfix) + ndirect +\n        BROTLI_NUM_DISTANCE_SHORT_CODES + 1;\n    /* Calculate the maximal distance representable by alphabet. */\n    result.max_distance = ((start + extra) << npostfix) + postfix + ndirect + 1;\n    return result;\n  }\n}\n\n/* Represents the range of values belonging to a prefix code:\n   [offset, offset + 2^nbits) */\ntypedef struct {\n  uint16_t offset;\n  uint8_t nbits;\n} BrotliPrefixCodeRange;\n\n/* \"Soft-private\", it is exported, but not \"advertised\" as API. */\nBROTLI_COMMON_API extern const BROTLI_MODEL(\"small\")\nBrotliPrefixCodeRange _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n\n#endif  /* BROTLI_COMMON_CONSTANTS_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/context.c",
    "content": "﻿#include \"context.h\"\n\n#include \"platform.h\"\n\n/* Common context lookup table for all context modes. */\nconst BROTLI_MODEL(\"small\") uint8_t _kBrotliContextLookupTable[2048] = {\n  /* CONTEXT_LSB6, last byte. */\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n\n  /* CONTEXT_LSB6, second last byte, */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\n  /* CONTEXT_MSB6, last byte. */\n   0,  0,  0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,\n   4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,\n   8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11, 11,\n  12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,\n  16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,\n  20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,\n  24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27,\n  28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,\n  32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35,\n  36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,\n  40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,\n  44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47,\n  48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51,\n  52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55,\n  56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59,\n  60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63,\n\n  /* CONTEXT_MSB6, second last byte, */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\n  /* CONTEXT_UTF8, last byte. */\n  /* ASCII range. */\n   0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  4,  0,  0,  4,  0,  0,\n   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n   8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12,\n  44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 32, 32, 24, 40, 28, 12,\n  12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48,\n  52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12,\n  12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56,\n  60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12,  0,\n  /* UTF8 continuation byte range. */\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  /* UTF8 lead byte range. */\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n\n  /* CONTEXT_UTF8 second last byte. */\n  /* ASCII range. */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,\n  1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,\n  1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0,\n  /* UTF8 continuation byte range. */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  /* UTF8 lead byte range. */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n\n  /* CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits. */\n   0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,\n  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56,\n\n  /* CONTEXT_SIGNED, second last byte. */\n  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,\n};\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/context.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Lookup table to map the previous two bytes to a context id.\n\n  There are four different context modeling modes defined here:\n    CONTEXT_LSB6: context id is the least significant 6 bits of the last byte,\n    CONTEXT_MSB6: context id is the most significant 6 bits of the last byte,\n    CONTEXT_UTF8: second-order context model tuned for UTF8-encoded text,\n    CONTEXT_SIGNED: second-order context model tuned for signed integers.\n\n  If |p1| and |p2| are the previous two bytes, and |mode| is current context\n  mode, we calculate the context as:\n\n    context = ContextLut(mode)[p1] | ContextLut(mode)[p2 + 256].\n\n  For CONTEXT_UTF8 mode, if the previous two bytes are ASCII characters\n  (i.e. < 128), this will be equivalent to\n\n    context = 4 * context1(p1) + context2(p2),\n\n  where context1 is based on the previous byte in the following way:\n\n    0  : non-ASCII control\n    1  : \\t, \\n, \\r\n    2  : space\n    3  : other punctuation\n    4  : \" '\n    5  : %\n    6  : ( < [ {\n    7  : ) > ] }\n    8  : , ; :\n    9  : .\n    10 : =\n    11 : number\n    12 : upper-case vowel\n    13 : upper-case consonant\n    14 : lower-case vowel\n    15 : lower-case consonant\n\n  and context2 is based on the second last byte:\n\n    0 : control, space\n    1 : punctuation\n    2 : upper-case letter, number\n    3 : lower-case letter\n\n  If the last byte is ASCII, and the second last byte is not (in a valid UTF8\n  stream it will be a continuation byte, value between 128 and 191), the\n  context is the same as if the second last byte was an ASCII control or space.\n\n  If the last byte is a UTF8 lead byte (value >= 192), then the next byte will\n  be a continuation byte and the context id is 2 or 3 depending on the LSB of\n  the last byte and to a lesser extent on the second last byte if it is ASCII.\n\n  If the last byte is a UTF8 continuation byte, the second last byte can be:\n    - continuation byte: the next byte is probably ASCII or lead byte (assuming\n      4-byte UTF8 characters are rare) and the context id is 0 or 1.\n    - lead byte (192 - 207): next byte is ASCII or lead byte, context is 0 or 1\n    - lead byte (208 - 255): next byte is continuation byte, context is 2 or 3\n\n  The possible value combinations of the previous two bytes, the range of\n  context ids and the type of the next byte is summarized in the table below:\n\n  |--------\\-----------------------------------------------------------------|\n  |         \\                         Last byte                              |\n  | Second   \\---------------------------------------------------------------|\n  | last byte \\    ASCII            |   cont. byte        |   lead byte      |\n  |            \\   (0-127)          |   (128-191)         |   (192-)         |\n  |=============|===================|=====================|==================|\n  |  ASCII      | next: ASCII/lead  |  not valid          |  next: cont.     |\n  |  (0-127)    | context: 4 - 63   |                     |  context: 2 - 3  |\n  |-------------|-------------------|---------------------|------------------|\n  |  cont. byte | next: ASCII/lead  |  next: ASCII/lead   |  next: cont.     |\n  |  (128-191)  | context: 4 - 63   |  context: 0 - 1     |  context: 2 - 3  |\n  |-------------|-------------------|---------------------|------------------|\n  |  lead byte  | not valid         |  next: ASCII/lead   |  not valid       |\n  |  (192-207)  |                   |  context: 0 - 1     |                  |\n  |-------------|-------------------|---------------------|------------------|\n  |  lead byte  | not valid         |  next: cont.        |  not valid       |\n  |  (208-)     |                   |  context: 2 - 3     |                  |\n  |-------------|-------------------|---------------------|------------------|\n*/\n\n#ifndef BROTLI_COMMON_CONTEXT_H_\n#define BROTLI_COMMON_CONTEXT_H_\n\n#include \"platform.h\"\n\ntypedef enum ContextType {\n  CONTEXT_LSB6 = 0,\n  CONTEXT_MSB6 = 1,\n  CONTEXT_UTF8 = 2,\n  CONTEXT_SIGNED = 3\n} ContextType;\n\n/* \"Soft-private\", it is exported, but not \"advertised\" as API. */\n/* Common context lookup table for all context modes. */\nBROTLI_COMMON_API extern const uint8_t _kBrotliContextLookupTable[2048];\n\ntypedef const uint8_t* ContextLut;\n\n/* typeof(MODE) == ContextType; returns ContextLut */\n#define BROTLI_CONTEXT_LUT(MODE) (&_kBrotliContextLookupTable[(MODE) << 9])\n\n/* typeof(LUT) == ContextLut */\n#define BROTLI_CONTEXT(P1, P2, LUT) ((LUT)[P1] | ((LUT) + 256)[P2])\n\n#endif  /* BROTLI_COMMON_CONTEXT_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/dictionary.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"dictionary.h\"\n#include \"platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\n/* Embed kBrotliDictionaryData */\n#include \"dictionary_inc.h\"\nstatic const BROTLI_MODEL(\"small\") BrotliDictionary kBrotliDictionary = {\n#else\nstatic BROTLI_MODEL(\"small\") BrotliDictionary kBrotliDictionary = {\n#endif\n  /* size_bits_by_length */\n  {\n    0, 0, 0, 0, 10, 10, 11, 11,\n    10, 10, 10, 10, 10, 9, 9, 8,\n    7, 7, 8, 7, 7, 6, 6, 5,\n    5, 0, 0, 0, 0, 0, 0, 0\n  },\n\n  /* offsets_by_length */\n  {\n    0, 0, 0, 0, 0, 4096, 9216, 21504,\n    35840, 44032, 53248, 63488, 74752, 87040, 93696, 100864,\n    104704, 106752, 108928, 113536, 115968, 118528, 119872, 121280,\n    122016, 122784, 122784, 122784, 122784, 122784, 122784, 122784\n  },\n\n  /* data_size ==  sizeof(kBrotliDictionaryData) */\n  122784,\n\n  /* data */\n#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\n  NULL\n#else\n  kBrotliDictionaryData\n#endif\n};\n\nconst BrotliDictionary* BrotliGetDictionary(void) {\n  return &kBrotliDictionary;\n}\n\nvoid BrotliSetDictionaryData(const uint8_t* data) {\n#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\n  if (!!data && !kBrotliDictionary.data) {\n    kBrotliDictionary.data = data;\n  }\n#else\n  BROTLI_UNUSED(data);  // Appease -Werror=unused-parameter\n#endif\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/dictionary.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Collection of static dictionary words. */\n\n#ifndef BROTLI_COMMON_DICTIONARY_H_\n#define BROTLI_COMMON_DICTIONARY_H_\n\n#include \"platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BrotliDictionary {\n  /**\n   * Number of bits to encode index of dictionary word in a bucket.\n   *\n   * Specification: Appendix A. Static Dictionary Data\n   *\n   * Words in a dictionary are bucketed by length.\n   * @c 0 means that there are no words of a given length.\n   * Dictionary consists of words with length of [4..24] bytes.\n   * Values at [0..3] and [25..31] indices should not be addressed.\n   */\n  uint8_t size_bits_by_length[32];\n\n  /* assert(offset[i + 1] == offset[i] + (bits[i] ? (i << bits[i]) : 0)) */\n  uint32_t offsets_by_length[32];\n\n  /* assert(data_size == offsets_by_length[31]) */\n  size_t data_size;\n\n  /* Data array is not bound, and should obey to size_bits_by_length values.\n     Specified size matches default (RFC 7932) dictionary. Its size is\n     defined by data_size */\n  const uint8_t* data;\n} BrotliDictionary;\n\nBROTLI_COMMON_API const BrotliDictionary* BrotliGetDictionary(void);\n\n/**\n * Sets dictionary data.\n *\n * When dictionary data is already set / present, this method is no-op.\n *\n * Dictionary data MUST be provided before BrotliGetDictionary is invoked.\n * This method is used ONLY in multi-client environment (e.g. C + Java),\n * to reduce storage by sharing single dictionary between implementations.\n */\nBROTLI_COMMON_API void BrotliSetDictionaryData(const uint8_t* data);\n\n#define BROTLI_MIN_DICTIONARY_WORD_LENGTH 4\n#define BROTLI_MAX_DICTIONARY_WORD_LENGTH 24\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_DICTIONARY_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/dictionary_inc.h",
    "content": "﻿static const BROTLI_MODEL(\"small\") uint8_t kBrotliDictionaryData[] = {\n116,105,109,101,100,111,119,110,108,105,102,101,108,101,102,116,98,97,99,107,99,\n111,100,101,100,97,116,97,115,104,111,119,111,110,108,121,115,105,116,101,99,105\n,116,121,111,112,101,110,106,117,115,116,108,105,107,101,102,114,101,101,119,111\n,114,107,116,101,120,116,121,101,97,114,111,118,101,114,98,111,100,121,108,111,\n118,101,102,111,114,109,98,111,111,107,112,108,97,121,108,105,118,101,108,105,\n110,101,104,101,108,112,104,111,109,101,115,105,100,101,109,111,114,101,119,111,\n114,100,108,111,110,103,116,104,101,109,118,105,101,119,102,105,110,100,112,97,\n103,101,100,97,121,115,102,117,108,108,104,101,97,100,116,101,114,109,101,97,99,\n104,97,114,101,97,102,114,111,109,116,114,117,101,109,97,114,107,97,98,108,101,\n117,112,111,110,104,105,103,104,100,97,116,101,108,97,110,100,110,101,119,115,\n101,118,101,110,110,101,120,116,99,97,115,101,98,111,116,104,112,111,115,116,117\n,115,101,100,109,97,100,101,104,97,110,100,104,101,114,101,119,104,97,116,110,97\n,109,101,76,105,110,107,98,108,111,103,115,105,122,101,98,97,115,101,104,101,108\n,100,109,97,107,101,109,97,105,110,117,115,101,114,39,41,32,43,104,111,108,100,\n101,110,100,115,119,105,116,104,78,101,119,115,114,101,97,100,119,101,114,101,\n115,105,103,110,116,97,107,101,104,97,118,101,103,97,109,101,115,101,101,110,99,\n97,108,108,112,97,116,104,119,101,108,108,112,108,117,115,109,101,110,117,102,\n105,108,109,112,97,114,116,106,111,105,110,116,104,105,115,108,105,115,116,103,\n111,111,100,110,101,101,100,119,97,121,115,119,101,115,116,106,111,98,115,109,\n105,110,100,97,108,115,111,108,111,103,111,114,105,99,104,117,115,101,115,108,97\n,115,116,116,101,97,109,97,114,109,121,102,111,111,100,107,105,110,103,119,105,\n108,108,101,97,115,116,119,97,114,100,98,101,115,116,102,105,114,101,80,97,103,\n101,107,110,111,119,97,119,97,121,46,112,110,103,109,111,118,101,116,104,97,110,\n108,111,97,100,103,105,118,101,115,101,108,102,110,111,116,101,109,117,99,104,\n102,101,101,100,109,97,110,121,114,111,99,107,105,99,111,110,111,110,99,101,108,\n111,111,107,104,105,100,101,100,105,101,100,72,111,109,101,114,117,108,101,104,\n111,115,116,97,106,97,120,105,110,102,111,99,108,117,98,108,97,119,115,108,101,\n115,115,104,97,108,102,115,111,109,101,115,117,99,104,122,111,110,101,49,48,48,\n37,111,110,101,115,99,97,114,101,84,105,109,101,114,97,99,101,98,108,117,101,102\n,111,117,114,119,101,101,107,102,97,99,101,104,111,112,101,103,97,118,101,104,97\n,114,100,108,111,115,116,119,104,101,110,112,97,114,107,107,101,112,116,112,97,\n115,115,115,104,105,112,114,111,111,109,72,84,77,76,112,108,97,110,84,121,112,\n101,100,111,110,101,115,97,118,101,107,101,101,112,102,108,97,103,108,105,110,\n107,115,111,108,100,102,105,118,101,116,111,111,107,114,97,116,101,116,111,119,\n110,106,117,109,112,116,104,117,115,100,97,114,107,99,97,114,100,102,105,108,101\n,102,101,97,114,115,116,97,121,107,105,108,108,116,104,97,116,102,97,108,108,97,\n117,116,111,101,118,101,114,46,99,111,109,116,97,108,107,115,104,111,112,118,111\n,116,101,100,101,101,112,109,111,100,101,114,101,115,116,116,117,114,110,98,111,\n114,110,98,97,110,100,102,101,108,108,114,111,115,101,117,114,108,40,115,107,105\n,110,114,111,108,101,99,111,109,101,97,99,116,115,97,103,101,115,109,101,101,116\n,103,111,108,100,46,106,112,103,105,116,101,109,118,97,114,121,102,101,108,116,\n116,104,101,110,115,101,110,100,100,114,111,112,86,105,101,119,99,111,112,121,49\n,46,48,34,60,47,97,62,115,116,111,112,101,108,115,101,108,105,101,115,116,111,\n117,114,112,97,99,107,46,103,105,102,112,97,115,116,99,115,115,63,103,114,97,121\n,109,101,97,110,38,103,116,59,114,105,100,101,115,104,111,116,108,97,116,101,115\n,97,105,100,114,111,97,100,118,97,114,32,102,101,101,108,106,111,104,110,114,105\n,99,107,112,111,114,116,102,97,115,116,39,85,65,45,100,101,97,100,60,47,98,62,\n112,111,111,114,98,105,108,108,116,121,112,101,85,46,83,46,119,111,111,100,109,\n117,115,116,50,112,120,59,73,110,102,111,114,97,110,107,119,105,100,101,119,97,\n110,116,119,97,108,108,108,101,97,100,91,48,93,59,112,97,117,108,119,97,118,101,\n115,117,114,101,36,40,39,35,119,97,105,116,109,97,115,115,97,114,109,115,103,111\n,101,115,103,97,105,110,108,97,110,103,112,97,105,100,33,45,45,32,108,111,99,107\n,117,110,105,116,114,111,111,116,119,97,108,107,102,105,114,109,119,105,102,101,\n120,109,108,34,115,111,110,103,116,101,115,116,50,48,112,120,107,105,110,100,114\n,111,119,115,116,111,111,108,102,111,110,116,109,97,105,108,115,97,102,101,115,\n116,97,114,109,97,112,115,99,111,114,101,114,97,105,110,102,108,111,119,98,97,98\n,121,115,112,97,110,115,97,121,115,52,112,120,59,54,112,120,59,97,114,116,115,\n102,111,111,116,114,101,97,108,119,105,107,105,104,101,97,116,115,116,101,112,\n116,114,105,112,111,114,103,47,108,97,107,101,119,101,97,107,116,111,108,100,70,\n111,114,109,99,97,115,116,102,97,110,115,98,97,110,107,118,101,114,121,114,117,\n110,115,106,117,108,121,116,97,115,107,49,112,120,59,103,111,97,108,103,114,101,\n119,115,108,111,119,101,100,103,101,105,100,61,34,115,101,116,115,53,112,120,59,\n46,106,115,63,52,48,112,120,105,102,32,40,115,111,111,110,115,101,97,116,110,111\n,110,101,116,117,98,101,122,101,114,111,115,101,110,116,114,101,101,100,102,97,\n99,116,105,110,116,111,103,105,102,116,104,97,114,109,49,56,112,120,99,97,109,\n101,104,105,108,108,98,111,108,100,122,111,111,109,118,111,105,100,101,97,115,\n121,114,105,110,103,102,105,108,108,112,101,97,107,105,110,105,116,99,111,115,\n116,51,112,120,59,106,97,99,107,116,97,103,115,98,105,116,115,114,111,108,108,\n101,100,105,116,107,110,101,119,110,101,97,114,60,33,45,45,103,114,111,119,74,83\n,79,78,100,117,116,121,78,97,109,101,115,97,108,101,121,111,117,32,108,111,116,\n115,112,97,105,110,106,97,122,122,99,111,108,100,101,121,101,115,102,105,115,104\n,119,119,119,46,114,105,115,107,116,97,98,115,112,114,101,118,49,48,112,120,114,\n105,115,101,50,53,112,120,66,108,117,101,100,105,110,103,51,48,48,44,98,97,108,\n108,102,111,114,100,101,97,114,110,119,105,108,100,98,111,120,46,102,97,105,114,\n108,97,99,107,118,101,114,115,112,97,105,114,106,117,110,101,116,101,99,104,105,\n102,40,33,112,105,99,107,101,118,105,108,36,40,34,35,119,97,114,109,108,111,114,\n100,100,111,101,115,112,117,108,108,44,48,48,48,105,100,101,97,100,114,97,119,\n104,117,103,101,115,112,111,116,102,117,110,100,98,117,114,110,104,114,101,102,\n99,101,108,108,107,101,121,115,116,105,99,107,104,111,117,114,108,111,115,115,\n102,117,101,108,49,50,112,120,115,117,105,116,100,101,97,108,82,83,83,34,97,103,\n101,100,103,114,101,121,71,69,84,34,101,97,115,101,97,105,109,115,103,105,114,\n108,97,105,100,115,56,112,120,59,110,97,118,121,103,114,105,100,116,105,112,115,\n35,57,57,57,119,97,114,115,108,97,100,121,99,97,114,115,41,59,32,125,112,104,112\n,63,104,101,108,108,116,97,108,108,119,104,111,109,122,104,58,229,42,47,13,10,32\n,49,48,48,104,97,108,108,46,10,10,65,55,112,120,59,112,117,115,104,99,104,97,116\n,48,112,120,59,99,114,101,119,42,47,60,47,104,97,115,104,55,53,112,120,102,108,\n97,116,114,97,114,101,32,38,38,32,116,101,108,108,99,97,109,112,111,110,116,111,\n108,97,105,100,109,105,115,115,115,107,105,112,116,101,110,116,102,105,110,101,\n109,97,108,101,103,101,116,115,112,108,111,116,52,48,48,44,13,10,13,10,99,111,\n111,108,102,101,101,116,46,112,104,112,60,98,114,62,101,114,105,99,109,111,115,\n116,103,117,105,100,98,101,108,108,100,101,115,99,104,97,105,114,109,97,116,104,\n97,116,111,109,47,105,109,103,38,35,56,50,108,117,99,107,99,101,110,116,48,48,48\n,59,116,105,110,121,103,111,110,101,104,116,109,108,115,101,108,108,100,114,117,\n103,70,82,69,69,110,111,100,101,110,105,99,107,63,105,100,61,108,111,115,101,110\n,117,108,108,118,97,115,116,119,105,110,100,82,83,83,32,119,101,97,114,114,101,\n108,121,98,101,101,110,115,97,109,101,100,117,107,101,110,97,115,97,99,97,112,\n101,119,105,115,104,103,117,108,102,84,50,51,58,104,105,116,115,115,108,111,116,\n103,97,116,101,107,105,99,107,98,108,117,114,116,104,101,121,49,53,112,120,39,39\n,41,59,41,59,34,62,109,115,105,101,119,105,110,115,98,105,114,100,115,111,114,\n116,98,101,116,97,115,101,101,107,84,49,56,58,111,114,100,115,116,114,101,101,\n109,97,108,108,54,48,112,120,102,97,114,109,226,128,153,115,98,111,121,115,91,48\n,93,46,39,41,59,34,80,79,83,84,98,101,97,114,107,105,100,115,41,59,125,125,109,\n97,114,121,116,101,110,100,40,85,75,41,113,117,97,100,122,104,58,230,45,115,105,\n122,45,45,45,45,112,114,111,112,39,41,59,13,108,105,102,116,84,49,57,58,118,105,\n99,101,97,110,100,121,100,101,98,116,62,82,83,83,112,111,111,108,110,101,99,107,\n98,108,111,119,84,49,54,58,100,111,111,114,101,118,97,108,84,49,55,58,108,101,\n116,115,102,97,105,108,111,114,97,108,112,111,108,108,110,111,118,97,99,111,108,\n115,103,101,110,101,32,226,128,148,115,111,102,116,114,111,109,101,116,105,108,\n108,114,111,115,115,60,104,51,62,112,111,117,114,102,97,100,101,112,105,110,107,\n60,116,114,62,109,105,110,105,41,124,33,40,109,105,110,101,122,104,58,232,98,97,\n114,115,104,101,97,114,48,48,41,59,109,105,108,107,32,45,45,62,105,114,111,110,\n102,114,101,100,100,105,115,107,119,101,110,116,115,111,105,108,112,117,116,115,\n47,106,115,47,104,111,108,121,84,50,50,58,73,83,66,78,84,50,48,58,97,100,97,109,\n115,101,101,115,60,104,50,62,106,115,111,110,39,44,32,39,99,111,110,116,84,50,49\n,58,32,82,83,83,108,111,111,112,97,115,105,97,109,111,111,110,60,47,112,62,115,\n111,117,108,76,73,78,69,102,111,114,116,99,97,114,116,84,49,52,58,60,104,49,62,\n56,48,112,120,33,45,45,60,57,112,120,59,84,48,52,58,109,105,107,101,58,52,54,90,\n110,105,99,101,105,110,99,104,89,111,114,107,114,105,99,101,122,104,58,228,39,41\n,41,59,112,117,114,101,109,97,103,101,112,97,114,97,116,111,110,101,98,111,110,\n100,58,51,55,90,95,111,102,95,39,93,41,59,48,48,48,44,122,104,58,231,116,97,110,\n107,121,97,114,100,98,111,119,108,98,117,115,104,58,53,54,90,74,97,118,97,51,48,\n112,120,10,124,125,10,37,67,51,37,58,51,52,90,106,101,102,102,69,88,80,73,99,97,\n115,104,118,105,115,97,103,111,108,102,115,110,111,119,122,104,58,233,113,117,\n101,114,46,99,115,115,115,105,99,107,109,101,97,116,109,105,110,46,98,105,110,\n100,100,101,108,108,104,105,114,101,112,105,99,115,114,101,110,116,58,51,54,90,\n72,84,84,80,45,50,48,49,102,111,116,111,119,111,108,102,69,78,68,32,120,98,111,\n120,58,53,52,90,66,79,68,89,100,105,99,107,59,10,125,10,101,120,105,116,58,51,53\n,90,118,97,114,115,98,101,97,116,39,125,41,59,100,105,101,116,57,57,57,59,97,110\n,110,101,125,125,60,47,91,105,93,46,76,97,110,103,107,109,194,178,119,105,114,\n101,116,111,121,115,97,100,100,115,115,101,97,108,97,108,101,120,59,10,9,125,101\n,99,104,111,110,105,110,101,46,111,114,103,48,48,53,41,116,111,110,121,106,101,\n119,115,115,97,110,100,108,101,103,115,114,111,111,102,48,48,48,41,32,50,48,48,\n119,105,110,101,103,101,97,114,100,111,103,115,98,111,111,116,103,97,114,121,99,\n117,116,115,116,121,108,101,116,101,109,112,116,105,111,110,46,120,109,108,99,\n111,99,107,103,97,110,103,36,40,39,46,53,48,112,120,80,104,46,68,109,105,115,99,\n97,108,97,110,108,111,97,110,100,101,115,107,109,105,108,101,114,121,97,110,117,\n110,105,120,100,105,115,99,41,59,125,10,100,117,115,116,99,108,105,112,41,46,10,\n10,55,48,112,120,45,50,48,48,68,86,68,115,55,93,62,60,116,97,112,101,100,101,109\n,111,105,43,43,41,119,97,103,101,101,117,114,111,112,104,105,108,111,112,116,115\n,104,111,108,101,70,65,81,115,97,115,105,110,45,50,54,84,108,97,98,115,112,101,\n116,115,85,82,76,32,98,117,108,107,99,111,111,107,59,125,13,10,72,69,65,68,91,48\n,93,41,97,98,98,114,106,117,97,110,40,49,57,56,108,101,115,104,116,119,105,110,\n60,47,105,62,115,111,110,121,103,117,121,115,102,117,99,107,112,105,112,101,124,\n45,10,33,48,48,50,41,110,100,111,119,91,49,93,59,91,93,59,10,76,111,103,32,115,\n97,108,116,13,10,9,9,98,97,110,103,116,114,105,109,98,97,116,104,41,123,13,10,48\n,48,112,120,10,125,41,59,107,111,58,236,102,101,101,115,97,100,62,13,115,58,47,\n47,32,91,93,59,116,111,108,108,112,108,117,103,40,41,123,10,123,13,10,32,46,106,\n115,39,50,48,48,112,100,117,97,108,98,111,97,116,46,74,80,71,41,59,10,125,113,\n117,111,116,41,59,10,10,39,41,59,10,13,10,125,13,50,48,49,52,50,48,49,53,50,48,\n49,54,50,48,49,55,50,48,49,56,50,48,49,57,50,48,50,48,50,48,50,49,50,48,50,50,50\n,48,50,51,50,48,50,52,50,48,50,53,50,48,50,54,50,48,50,55,50,48,50,56,50,48,50,\n57,50,48,51,48,50,48,51,49,50,48,51,50,50,48,51,51,50,48,51,52,50,48,51,53,50,48\n,51,54,50,48,51,55,50,48,49,51,50,48,49,50,50,48,49,49,50,48,49,48,50,48,48,57,\n50,48,48,56,50,48,48,55,50,48,48,54,50,48,48,53,50,48,48,52,50,48,48,51,50,48,48\n,50,50,48,48,49,50,48,48,48,49,57,57,57,49,57,57,56,49,57,57,55,49,57,57,54,49,\n57,57,53,49,57,57,52,49,57,57,51,49,57,57,50,49,57,57,49,49,57,57,48,49,57,56,57\n,49,57,56,56,49,57,56,55,49,57,56,54,49,57,56,53,49,57,56,52,49,57,56,51,49,57,\n56,50,49,57,56,49,49,57,56,48,49,57,55,57,49,57,55,56,49,57,55,55,49,57,55,54,49\n,57,55,53,49,57,55,52,49,57,55,51,49,57,55,50,49,57,55,49,49,57,55,48,49,57,54,\n57,49,57,54,56,49,57,54,55,49,57,54,54,49,57,54,53,49,57,54,52,49,57,54,51,49,57\n,54,50,49,57,54,49,49,57,54,48,49,57,53,57,49,57,53,56,49,57,53,55,49,57,53,54,\n49,57,53,53,49,57,53,52,49,57,53,51,49,57,53,50,49,57,53,49,49,57,53,48,49,48,48\n,48,49,48,50,52,49,51,57,52,48,48,48,48,57,57,57,57,99,111,109,111,109,195,161,\n115,101,115,116,101,101,115,116,97,112,101,114,111,116,111,100,111,104,97,99,101\n,99,97,100,97,97,195,177,111,98,105,101,110,100,195,173,97,97,115,195,173,118,\n105,100,97,99,97,115,111,111,116,114,111,102,111,114,111,115,111,108,111,111,116\n,114,97,99,117,97,108,100,105,106,111,115,105,100,111,103,114,97,110,116,105,112\n,111,116,101,109,97,100,101,98,101,97,108,103,111,113,117,195,169,101,115,116,\n111,110,97,100,97,116,114,101,115,112,111,99,111,99,97,115,97,98,97,106,111,116,\n111,100,97,115,105,110,111,97,103,117,97,112,117,101,115,117,110,111,115,97,110,\n116,101,100,105,99,101,108,117,105,115,101,108,108,97,109,97,121,111,122,111,110\n,97,97,109,111,114,112,105,115,111,111,98,114,97,99,108,105,99,101,108,108,111,\n100,105,111,115,104,111,114,97,99,97,115,105,208,183,208,176,208,189,208,176,208\n,190,208,188,209,128,208,176,209,128,209,131,209,130,208,176,208,189,208,181,208\n,191,208,190,208,190,209,130,208,184,208,183,208,189,208,190,208,180,208,190,209\n,130,208,190,208,182,208,181,208,190,208,189,208,184,209,133,208,157,208,176,208\n,181,208,181,208,177,209,139,208,188,209,139,208,146,209,139,209,129,208,190,208\n,178,209,139,208,178,208,190,208,157,208,190,208,190,208,177,208,159,208,190,208\n,187,208,184,208,189,208,184,208,160,208,164,208,157,208,181,208,156,209,139,209\n,130,209,139,208,158,208,189,208,184,208,188,208,180,208,176,208,151,208,176,208\n,148,208,176,208,157,209,131,208,158,208,177,209,130,208,181,208,152,208,183,208\n,181,208,185,208,189,209,131,208,188,208,188,208,162,209,139,209,131,208,182,217\n,129,217,138,216,163,217,134,217,133,216,167,217,133,216,185,217,131,217,132,216\n,163,217,136,216,177,216,175,217,138,216,167,217,129,217,137,217,135,217,136,217\n,132,217,133,217,132,217,131,216,167,217,136,217,132,217,135,216,168,216,179,216\n,167,217,132,216,165,217,134,217,135,217,138,216,163,217,138,217,130,216,175,217\n,135,217,132,216,171,217,133,216,168,217,135,217,132,217,136,217,132,217,138,216\n,168,217,132,216,167,217,138,216,168,217,131,216,180,217,138,216,167,217,133,216\n,163,217,133,217,134,216,170,216,168,217,138,217,132,217,134,216,173,216,168,217\n,135,217,133,217,133,216,180,217,136,216,180,102,105,114,115,116,118,105,100,101\n,111,108,105,103,104,116,119,111,114,108,100,109,101,100,105,97,119,104,105,116,\n101,99,108,111,115,101,98,108,97,99,107,114,105,103,104,116,115,109,97,108,108,\n98,111,111,107,115,112,108,97,99,101,109,117,115,105,99,102,105,101,108,100,111,\n114,100,101,114,112,111,105,110,116,118,97,108,117,101,108,101,118,101,108,116,\n97,98,108,101,98,111,97,114,100,104,111,117,115,101,103,114,111,117,112,119,111,\n114,107,115,121,101,97,114,115,115,116,97,116,101,116,111,100,97,121,119,97,116,\n101,114,115,116,97,114,116,115,116,121,108,101,100,101,97,116,104,112,111,119,\n101,114,112,104,111,110,101,110,105,103,104,116,101,114,114,111,114,105,110,112,\n117,116,97,98,111,117,116,116,101,114,109,115,116,105,116,108,101,116,111,111,\n108,115,101,118,101,110,116,108,111,99,97,108,116,105,109,101,115,108,97,114,103\n,101,119,111,114,100,115,103,97,109,101,115,115,104,111,114,116,115,112,97,99,\n101,102,111,99,117,115,99,108,101,97,114,109,111,100,101,108,98,108,111,99,107,\n103,117,105,100,101,114,97,100,105,111,115,104,97,114,101,119,111,109,101,110,97\n,103,97,105,110,109,111,110,101,121,105,109,97,103,101,110,97,109,101,115,121,\n111,117,110,103,108,105,110,101,115,108,97,116,101,114,99,111,108,111,114,103,\n114,101,101,110,102,114,111,110,116,38,97,109,112,59,119,97,116,99,104,102,111,\n114,99,101,112,114,105,99,101,114,117,108,101,115,98,101,103,105,110,97,102,116,\n101,114,118,105,115,105,116,105,115,115,117,101,97,114,101,97,115,98,101,108,111\n,119,105,110,100,101,120,116,111,116,97,108,104,111,117,114,115,108,97,98,101,\n108,112,114,105,110,116,112,114,101,115,115,98,117,105,108,116,108,105,110,107,\n115,115,112,101,101,100,115,116,117,100,121,116,114,97,100,101,102,111,117,110,\n100,115,101,110,115,101,117,110,100,101,114,115,104,111,119,110,102,111,114,109,\n115,114,97,110,103,101,97,100,100,101,100,115,116,105,108,108,109,111,118,101,\n100,116,97,107,101,110,97,98,111,118,101,102,108,97,115,104,102,105,120,101,100,\n111,102,116,101,110,111,116,104,101,114,118,105,101,119,115,99,104,101,99,107,\n108,101,103,97,108,114,105,118,101,114,105,116,101,109,115,113,117,105,99,107,\n115,104,97,112,101,104,117,109,97,110,101,120,105,115,116,103,111,105,110,103,\n109,111,118,105,101,116,104,105,114,100,98,97,115,105,99,112,101,97,99,101,115,\n116,97,103,101,119,105,100,116,104,108,111,103,105,110,105,100,101,97,115,119,\n114,111,116,101,112,97,103,101,115,117,115,101,114,115,100,114,105,118,101,115,\n116,111,114,101,98,114,101,97,107,115,111,117,116,104,118,111,105,99,101,115,105\n,116,101,115,109,111,110,116,104,119,104,101,114,101,98,117,105,108,100,119,104,\n105,99,104,101,97,114,116,104,102,111,114,117,109,116,104,114,101,101,115,112,\n111,114,116,112,97,114,116,121,67,108,105,99,107,108,111,119,101,114,108,105,118\n,101,115,99,108,97,115,115,108,97,121,101,114,101,110,116,114,121,115,116,111,\n114,121,117,115,97,103,101,115,111,117,110,100,99,111,117,114,116,121,111,117,\n114,32,98,105,114,116,104,112,111,112,117,112,116,121,112,101,115,97,112,112,108\n,121,73,109,97,103,101,98,101,105,110,103,117,112,112,101,114,110,111,116,101,\n115,101,118,101,114,121,115,104,111,119,115,109,101,97,110,115,101,120,116,114,\n97,109,97,116,99,104,116,114,97,99,107,107,110,111,119,110,101,97,114,108,121,98\n,101,103,97,110,115,117,112,101,114,112,97,112,101,114,110,111,114,116,104,108,\n101,97,114,110,103,105,118,101,110,110,97,109,101,100,101,110,100,101,100,84,101\n,114,109,115,112,97,114,116,115,71,114,111,117,112,98,114,97,110,100,117,115,105\n,110,103,119,111,109,97,110,102,97,108,115,101,114,101,97,100,121,97,117,100,105\n,111,116,97,107,101,115,119,104,105,108,101,46,99,111,109,47,108,105,118,101,100\n,99,97,115,101,115,100,97,105,108,121,99,104,105,108,100,103,114,101,97,116,106,\n117,100,103,101,116,104,111,115,101,117,110,105,116,115,110,101,118,101,114,98,\n114,111,97,100,99,111,97,115,116,99,111,118,101,114,97,112,112,108,101,102,105,\n108,101,115,99,121,99,108,101,115,99,101,110,101,112,108,97,110,115,99,108,105,\n99,107,119,114,105,116,101,113,117,101,101,110,112,105,101,99,101,101,109,97,105\n,108,102,114,97,109,101,111,108,100,101,114,112,104,111,116,111,108,105,109,105,\n116,99,97,99,104,101,99,105,118,105,108,115,99,97,108,101,101,110,116,101,114,\n116,104,101,109,101,116,104,101,114,101,116,111,117,99,104,98,111,117,110,100,\n114,111,121,97,108,97,115,107,101,100,119,104,111,108,101,115,105,110,99,101,115\n,116,111,99,107,32,110,97,109,101,102,97,105,116,104,104,101,97,114,116,101,109,\n112,116,121,111,102,102,101,114,115,99,111,112,101,111,119,110,101,100,109,105,\n103,104,116,97,108,98,117,109,116,104,105,110,107,98,108,111,111,100,97,114,114,\n97,121,109,97,106,111,114,116,114,117,115,116,99,97,110,111,110,117,110,105,111,\n110,99,111,117,110,116,118,97,108,105,100,115,116,111,110,101,83,116,121,108,101\n,76,111,103,105,110,104,97,112,112,121,111,99,99,117,114,108,101,102,116,58,102,\n114,101,115,104,113,117,105,116,101,102,105,108,109,115,103,114,97,100,101,110,\n101,101,100,115,117,114,98,97,110,102,105,103,104,116,98,97,115,105,115,104,111,\n118,101,114,97,117,116,111,59,114,111,117,116,101,46,104,116,109,108,109,105,120\n,101,100,102,105,110,97,108,89,111,117,114,32,115,108,105,100,101,116,111,112,\n105,99,98,114,111,119,110,97,108,111,110,101,100,114,97,119,110,115,112,108,105,\n116,114,101,97,99,104,82,105,103,104,116,100,97,116,101,115,109,97,114,99,104,\n113,117,111,116,101,103,111,111,100,115,76,105,110,107,115,100,111,117,98,116,97\n,115,121,110,99,116,104,117,109,98,97,108,108,111,119,99,104,105,101,102,121,111\n,117,116,104,110,111,118,101,108,49,48,112,120,59,115,101,114,118,101,117,110,\n116,105,108,104,97,110,100,115,67,104,101,99,107,83,112,97,99,101,113,117,101,\n114,121,106,97,109,101,115,101,113,117,97,108,116,119,105,99,101,48,44,48,48,48,\n83,116,97,114,116,112,97,110,101,108,115,111,110,103,115,114,111,117,110,100,101\n,105,103,104,116,115,104,105,102,116,119,111,114,116,104,112,111,115,116,115,108\n,101,97,100,115,119,101,101,107,115,97,118,111,105,100,116,104,101,115,101,109,\n105,108,101,115,112,108,97,110,101,115,109,97,114,116,97,108,112,104,97,112,108,\n97,110,116,109,97,114,107,115,114,97,116,101,115,112,108,97,121,115,99,108,97,\n105,109,115,97,108,101,115,116,101,120,116,115,115,116,97,114,115,119,114,111,\n110,103,60,47,104,51,62,116,104,105,110,103,46,111,114,103,47,109,117,108,116,\n105,104,101,97,114,100,80,111,119,101,114,115,116,97,110,100,116,111,107,101,110\n,115,111,108,105,100,40,116,104,105,115,98,114,105,110,103,115,104,105,112,115,\n115,116,97,102,102,116,114,105,101,100,99,97,108,108,115,102,117,108,108,121,102\n,97,99,116,115,97,103,101,110,116,84,104,105,115,32,47,47,45,45,62,97,100,109,\n105,110,101,103,121,112,116,69,118,101,110,116,49,53,112,120,59,69,109,97,105,\n108,116,114,117,101,34,99,114,111,115,115,115,112,101,110,116,98,108,111,103,115\n,98,111,120,34,62,110,111,116,101,100,108,101,97,118,101,99,104,105,110,97,115,\n105,122,101,115,103,117,101,115,116,60,47,104,52,62,114,111,98,111,116,104,101,\n97,118,121,116,114,117,101,44,115,101,118,101,110,103,114,97,110,100,99,114,105,\n109,101,115,105,103,110,115,97,119,97,114,101,100,97,110,99,101,112,104,97,115,\n101,62,60,33,45,45,101,110,95,85,83,38,35,51,57,59,50,48,48,112,120,95,110,97,\n109,101,108,97,116,105,110,101,110,106,111,121,97,106,97,120,46,97,116,105,111,\n110,115,109,105,116,104,85,46,83,46,32,104,111,108,100,115,112,101,116,101,114,\n105,110,100,105,97,110,97,118,34,62,99,104,97,105,110,115,99,111,114,101,99,111,\n109,101,115,100,111,105,110,103,112,114,105,111,114,83,104,97,114,101,49,57,57,\n48,115,114,111,109,97,110,108,105,115,116,115,106,97,112,97,110,102,97,108,108,\n115,116,114,105,97,108,111,119,110,101,114,97,103,114,101,101,60,47,104,50,62,97\n,98,117,115,101,97,108,101,114,116,111,112,101,114,97,34,45,47,47,87,99,97,114,\n100,115,104,105,108,108,115,116,101,97,109,115,80,104,111,116,111,116,114,117,\n116,104,99,108,101,97,110,46,112,104,112,63,115,97,105,110,116,109,101,116,97,\n108,108,111,117,105,115,109,101,97,110,116,112,114,111,111,102,98,114,105,101,\n102,114,111,119,34,62,103,101,110,114,101,116,114,117,99,107,108,111,111,107,115\n,86,97,108,117,101,70,114,97,109,101,46,110,101,116,47,45,45,62,10,60,116,114,\n121,32,123,10,118,97,114,32,109,97,107,101,115,99,111,115,116,115,112,108,97,105\n,110,97,100,117,108,116,113,117,101,115,116,116,114,97,105,110,108,97,98,111,114\n,104,101,108,112,115,99,97,117,115,101,109,97,103,105,99,109,111,116,111,114,116\n,104,101,105,114,50,53,48,112,120,108,101,97,115,116,115,116,101,112,115,67,111,\n117,110,116,99,111,117,108,100,103,108,97,115,115,115,105,100,101,115,102,117,\n110,100,115,104,111,116,101,108,97,119,97,114,100,109,111,117,116,104,109,111,\n118,101,115,112,97,114,105,115,103,105,118,101,115,100,117,116,99,104,116,101,\n120,97,115,102,114,117,105,116,110,117,108,108,44,124,124,91,93,59,116,111,112,\n34,62,10,60,33,45,45,80,79,83,84,34,111,99,101,97,110,60,98,114,47,62,102,108,\n111,111,114,115,112,101,97,107,100,101,112,116,104,32,115,105,122,101,98,97,110,\n107,115,99,97,116,99,104,99,104,97,114,116,50,48,112,120,59,97,108,105,103,110,\n100,101,97,108,115,119,111,117,108,100,53,48,112,120,59,117,114,108,61,34,112,97\n,114,107,115,109,111,117,115,101,77,111,115,116,32,46,46,46,60,47,97,109,111,110\n,103,98,114,97,105,110,98,111,100,121,32,110,111,110,101,59,98,97,115,101,100,99\n,97,114,114,121,100,114,97,102,116,114,101,102,101,114,112,97,103,101,95,104,111\n,109,101,46,109,101,116,101,114,100,101,108,97,121,100,114,101,97,109,112,114,\n111,118,101,106,111,105,110,116,60,47,116,114,62,100,114,117,103,115,60,33,45,45\n,32,97,112,114,105,108,105,100,101,97,108,97,108,108,101,110,101,120,97,99,116,\n102,111,114,116,104,99,111,100,101,115,108,111,103,105,99,86,105,101,119,32,115,\n101,101,109,115,98,108,97,110,107,112,111,114,116,115,32,40,50,48,48,115,97,118,\n101,100,95,108,105,110,107,103,111,97,108,115,103,114,97,110,116,103,114,101,101\n,107,104,111,109,101,115,114,105,110,103,115,114,97,116,101,100,51,48,112,120,59\n,119,104,111,115,101,112,97,114,115,101,40,41,59,34,32,66,108,111,99,107,108,105\n,110,117,120,106,111,110,101,115,112,105,120,101,108,39,41,59,34,62,41,59,105,\n102,40,45,108,101,102,116,100,97,118,105,100,104,111,114,115,101,70,111,99,117,\n115,114,97,105,115,101,98,111,120,101,115,84,114,97,99,107,101,109,101,110,116,\n60,47,101,109,62,98,97,114,34,62,46,115,114,99,61,116,111,119,101,114,97,108,116\n,61,34,99,97,98,108,101,104,101,110,114,121,50,52,112,120,59,115,101,116,117,112\n,105,116,97,108,121,115,104,97,114,112,109,105,110,111,114,116,97,115,116,101,\n119,97,110,116,115,116,104,105,115,46,114,101,115,101,116,119,104,101,101,108,\n103,105,114,108,115,47,99,115,115,47,49,48,48,37,59,99,108,117,98,115,115,116,\n117,102,102,98,105,98,108,101,118,111,116,101,115,32,49,48,48,48,107,111,114,101\n,97,125,41,59,13,10,98,97,110,100,115,113,117,101,117,101,61,32,123,125,59,56,48\n,112,120,59,99,107,105,110,103,123,13,10,9,9,97,104,101,97,100,99,108,111,99,107\n,105,114,105,115,104,108,105,107,101,32,114,97,116,105,111,115,116,97,116,115,70\n,111,114,109,34,121,97,104,111,111,41,91,48,93,59,65,98,111,117,116,102,105,110,\n100,115,60,47,104,49,62,100,101,98,117,103,116,97,115,107,115,85,82,76,32,61,99,\n101,108,108,115,125,41,40,41,59,49,50,112,120,59,112,114,105,109,101,116,101,108\n,108,115,116,117,114,110,115,48,120,54,48,48,46,106,112,103,34,115,112,97,105,\n110,98,101,97,99,104,116,97,120,101,115,109,105,99,114,111,97,110,103,101,108,45\n,45,62,60,47,103,105,102,116,115,115,116,101,118,101,45,108,105,110,107,98,111,\n100,121,46,125,41,59,10,9,109,111,117,110,116,32,40,49,57,57,70,65,81,60,47,114,\n111,103,101,114,102,114,97,110,107,67,108,97,115,115,50,56,112,120,59,102,101,\n101,100,115,60,104,49,62,60,115,99,111,116,116,116,101,115,116,115,50,50,112,120\n,59,100,114,105,110,107,41,32,124,124,32,108,101,119,105,115,115,104,97,108,108,\n35,48,51,57,59,32,102,111,114,32,108,111,118,101,100,119,97,115,116,101,48,48,\n112,120,59,106,97,58,227,130,115,105,109,111,110,60,102,111,110,116,114,101,112,\n108,121,109,101,101,116,115,117,110,116,101,114,99,104,101,97,112,116,105,103,\n104,116,66,114,97,110,100,41,32,33,61,32,100,114,101,115,115,99,108,105,112,115,\n114,111,111,109,115,111,110,107,101,121,109,111,98,105,108,109,97,105,110,46,78,\n97,109,101,32,112,108,97,116,101,102,117,110,110,121,116,114,101,101,115,99,111,\n109,47,34,49,46,106,112,103,119,109,111,100,101,112,97,114,97,109,83,84,65,82,84\n,108,101,102,116,32,105,100,100,101,110,44,32,50,48,49,41,59,10,125,10,102,111,\n114,109,46,118,105,114,117,115,99,104,97,105,114,116,114,97,110,115,119,111,114,\n115,116,80,97,103,101,115,105,116,105,111,110,112,97,116,99,104,60,33,45,45,10,\n111,45,99,97,99,102,105,114,109,115,116,111,117,114,115,44,48,48,48,32,97,115,\n105,97,110,105,43,43,41,123,97,100,111,98,101,39,41,91,48,93,105,100,61,49,48,98\n,111,116,104,59,109,101,110,117,32,46,50,46,109,105,46,112,110,103,34,107,101,\n118,105,110,99,111,97,99,104,67,104,105,108,100,98,114,117,99,101,50,46,106,112,\n103,85,82,76,41,43,46,106,112,103,124,115,117,105,116,101,115,108,105,99,101,104\n,97,114,114,121,49,50,48,34,32,115,119,101,101,116,116,114,62,13,10,110,97,109,\n101,61,100,105,101,103,111,112,97,103,101,32,115,119,105,115,115,45,45,62,10,10,\n35,102,102,102,59,34,62,76,111,103,46,99,111,109,34,116,114,101,97,116,115,104,\n101,101,116,41,32,38,38,32,49,52,112,120,59,115,108,101,101,112,110,116,101,110,\n116,102,105,108,101,100,106,97,58,227,131,105,100,61,34,99,78,97,109,101,34,119,\n111,114,115,101,115,104,111,116,115,45,98,111,120,45,100,101,108,116,97,10,38,\n108,116,59,98,101,97,114,115,58,52,56,90,60,100,97,116,97,45,114,117,114,97,108,\n60,47,97,62,32,115,112,101,110,100,98,97,107,101,114,115,104,111,112,115,61,32,\n34,34,59,112,104,112,34,62,99,116,105,111,110,49,51,112,120,59,98,114,105,97,110\n,104,101,108,108,111,115,105,122,101,61,111,61,37,50,70,32,106,111,105,110,109,\n97,121,98,101,60,105,109,103,32,105,109,103,34,62,44,32,102,106,115,105,109,103,\n34,32,34,41,91,48,93,77,84,111,112,66,84,121,112,101,34,110,101,119,108,121,68,\n97,110,115,107,99,122,101,99,104,116,114,97,105,108,107,110,111,119,115,60,47,\n104,53,62,102,97,113,34,62,122,104,45,99,110,49,48,41,59,10,45,49,34,41,59,116,\n121,112,101,61,98,108,117,101,115,116,114,117,108,121,100,97,118,105,115,46,106,\n115,39,59,62,13,10,60,33,115,116,101,101,108,32,121,111,117,32,104,50,62,13,10,\n102,111,114,109,32,106,101,115,117,115,49,48,48,37,32,109,101,110,117,46,13,10,9\n,13,10,119,97,108,101,115,114,105,115,107,115,117,109,101,110,116,100,100,105,\n110,103,98,45,108,105,107,116,101,97,99,104,103,105,102,34,32,118,101,103,97,115\n,100,97,110,115,107,101,101,115,116,105,115,104,113,105,112,115,117,111,109,105,\n115,111,98,114,101,100,101,115,100,101,101,110,116,114,101,116,111,100,111,115,\n112,117,101,100,101,97,195,177,111,115,101,115,116,195,161,116,105,101,110,101,\n104,97,115,116,97,111,116,114,111,115,112,97,114,116,101,100,111,110,100,101,110\n,117,101,118,111,104,97,99,101,114,102,111,114,109,97,109,105,115,109,111,109,\n101,106,111,114,109,117,110,100,111,97,113,117,195,173,100,195,173,97,115,115,\n195,179,108,111,97,121,117,100,97,102,101,99,104,97,116,111,100,97,115,116,97,\n110,116,111,109,101,110,111,115,100,97,116,111,115,111,116,114,97,115,115,105,\n116,105,111,109,117,99,104,111,97,104,111,114,97,108,117,103,97,114,109,97,121,\n111,114,101,115,116,111,115,104,111,114,97,115,116,101,110,101,114,97,110,116,\n101,115,102,111,116,111,115,101,115,116,97,115,112,97,195,173,115,110,117,101,\n118,97,115,97,108,117,100,102,111,114,111,115,109,101,100,105,111,113,117,105,\n101,110,109,101,115,101,115,112,111,100,101,114,99,104,105,108,101,115,101,114,\n195,161,118,101,99,101,115,100,101,99,105,114,106,111,115,195,169,101,115,116,97\n,114,118,101,110,116,97,103,114,117,112,111,104,101,99,104,111,101,108,108,111,\n115,116,101,110,103,111,97,109,105,103,111,99,111,115,97,115,110,105,118,101,108\n,103,101,110,116,101,109,105,115,109,97,97,105,114,101,115,106,117,108,105,111,\n116,101,109,97,115,104,97,99,105,97,102,97,118,111,114,106,117,110,105,111,108,\n105,98,114,101,112,117,110,116,111,98,117,101,110,111,97,117,116,111,114,97,98,\n114,105,108,98,117,101,110,97,116,101,120,116,111,109,97,114,122,111,115,97,98,\n101,114,108,105,115,116,97,108,117,101,103,111,99,195,179,109,111,101,110,101,\n114,111,106,117,101,103,111,112,101,114,195,186,104,97,98,101,114,101,115,116,\n111,121,110,117,110,99,97,109,117,106,101,114,118,97,108,111,114,102,117,101,114\n,97,108,105,98,114,111,103,117,115,116,97,105,103,117,97,108,118,111,116,111,115\n,99,97,115,111,115,103,117,195,173,97,112,117,101,100,111,115,111,109,111,115,97\n,118,105,115,111,117,115,116,101,100,100,101,98,101,110,110,111,99,104,101,98,\n117,115,99,97,102,97,108,116,97,101,117,114,111,115,115,101,114,105,101,100,105,\n99,104,111,99,117,114,115,111,99,108,97,118,101,99,97,115,97,115,108,101,195,179\n,110,112,108,97,122,111,108,97,114,103,111,111,98,114,97,115,118,105,115,116,97,\n97,112,111,121,111,106,117,110,116,111,116,114,97,116,97,118,105,115,116,111,99,\n114,101,97,114,99,97,109,112,111,104,101,109,111,115,99,105,110,99,111,99,97,114\n,103,111,112,105,115,111,115,111,114,100,101,110,104,97,99,101,110,195,161,114,\n101,97,100,105,115,99,111,112,101,100,114,111,99,101,114,99,97,112,117,101,100,\n97,112,97,112,101,108,109,101,110,111,114,195,186,116,105,108,99,108,97,114,111,\n106,111,114,103,101,99,97,108,108,101,112,111,110,101,114,116,97,114,100,101,110\n,97,100,105,101,109,97,114,99,97,115,105,103,117,101,101,108,108,97,115,115,105,\n103,108,111,99,111,99,104,101,109,111,116,111,115,109,97,100,114,101,99,108,97,\n115,101,114,101,115,116,111,110,105,195,177,111,113,117,101,100,97,112,97,115,97\n,114,98,97,110,99,111,104,105,106,111,115,118,105,97,106,101,112,97,98,108,111,\n195,169,115,116,101,118,105,101,110,101,114,101,105,110,111,100,101,106,97,114,\n102,111,110,100,111,99,97,110,97,108,110,111,114,116,101,108,101,116,114,97,99,\n97,117,115,97,116,111,109,97,114,109,97,110,111,115,108,117,110,101,115,97,117,\n116,111,115,118,105,108,108,97,118,101,110,100,111,112,101,115,97,114,116,105,\n112,111,115,116,101,110,103,97,109,97,114,99,111,108,108,101,118,97,112,97,100,\n114,101,117,110,105,100,111,118,97,109,111,115,122,111,110,97,115,97,109,98,111,\n115,98,97,110,100,97,109,97,114,105,97,97,98,117,115,111,109,117,99,104,97,115,\n117,98,105,114,114,105,111,106,97,118,105,118,105,114,103,114,97,100,111,99,104,\n105,99,97,97,108,108,195,173,106,111,118,101,110,100,105,99,104,97,101,115,116,\n97,110,116,97,108,101,115,115,97,108,105,114,115,117,101,108,111,112,101,115,111\n,115,102,105,110,101,115,108,108,97,109,97,98,117,115,99,111,195,169,115,116,97,\n108,108,101,103,97,110,101,103,114,111,112,108,97,122,97,104,117,109,111,114,112\n,97,103,97,114,106,117,110,116,97,100,111,98,108,101,105,115,108,97,115,98,111,\n108,115,97,98,97,195,177,111,104,97,98,108,97,108,117,99,104,97,195,129,114,101,\n97,100,105,99,101,110,106,117,103,97,114,110,111,116,97,115,118,97,108,108,101,\n97,108,108,195,161,99,97,114,103,97,100,111,108,111,114,97,98,97,106,111,101,115\n,116,195,169,103,117,115,116,111,109,101,110,116,101,109,97,114,105,111,102,105,\n114,109,97,99,111,115,116,111,102,105,99,104,97,112,108,97,116,97,104,111,103,97\n,114,97,114,116,101,115,108,101,121,101,115,97,113,117,101,108,109,117,115,101,\n111,98,97,115,101,115,112,111,99,111,115,109,105,116,97,100,99,105,101,108,111,\n99,104,105,99,111,109,105,101,100,111,103,97,110,97,114,115,97,110,116,111,101,\n116,97,112,97,100,101,98,101,115,112,108,97,121,97,114,101,100,101,115,115,105,\n101,116,101,99,111,114,116,101,99,111,114,101,97,100,117,100,97,115,100,101,115,\n101,111,118,105,101,106,111,100,101,115,101,97,97,103,117,97,115,38,113,117,111,\n116,59,100,111,109,97,105,110,99,111,109,109,111,110,115,116,97,116,117,115,101,\n118,101,110,116,115,109,97,115,116,101,114,115,121,115,116,101,109,97,99,116,105\n,111,110,98,97,110,110,101,114,114,101,109,111,118,101,115,99,114,111,108,108,\n117,112,100,97,116,101,103,108,111,98,97,108,109,101,100,105,117,109,102,105,108\n,116,101,114,110,117,109,98,101,114,99,104,97,110,103,101,114,101,115,117,108,\n116,112,117,98,108,105,99,115,99,114,101,101,110,99,104,111,111,115,101,110,111,\n114,109,97,108,116,114,97,118,101,108,105,115,115,117,101,115,115,111,117,114,99\n,101,116,97,114,103,101,116,115,112,114,105,110,103,109,111,100,117,108,101,109,\n111,98,105,108,101,115,119,105,116,99,104,112,104,111,116,111,115,98,111,114,100\n,101,114,114,101,103,105,111,110,105,116,115,101,108,102,115,111,99,105,97,108,\n97,99,116,105,118,101,99,111,108,117,109,110,114,101,99,111,114,100,102,111,108,\n108,111,119,116,105,116,108,101,62,101,105,116,104,101,114,108,101,110,103,116,\n104,102,97,109,105,108,121,102,114,105,101,110,100,108,97,121,111,117,116,97,117\n,116,104,111,114,99,114,101,97,116,101,114,101,118,105,101,119,115,117,109,109,\n101,114,115,101,114,118,101,114,112,108,97,121,101,100,112,108,97,121,101,114,\n101,120,112,97,110,100,112,111,108,105,99,121,102,111,114,109,97,116,100,111,117\n,98,108,101,112,111,105,110,116,115,115,101,114,105,101,115,112,101,114,115,111,\n110,108,105,118,105,110,103,100,101,115,105,103,110,109,111,110,116,104,115,102,\n111,114,99,101,115,117,110,105,113,117,101,119,101,105,103,104,116,112,101,111,\n112,108,101,101,110,101,114,103,121,110,97,116,117,114,101,115,101,97,114,99,104\n,102,105,103,117,114,101,104,97,118,105,110,103,99,117,115,116,111,109,111,102,\n102,115,101,116,108,101,116,116,101,114,119,105,110,100,111,119,115,117,98,109,\n105,116,114,101,110,100,101,114,103,114,111,117,112,115,117,112,108,111,97,100,\n104,101,97,108,116,104,109,101,116,104,111,100,118,105,100,101,111,115,115,99,\n104,111,111,108,102,117,116,117,114,101,115,104,97,100,111,119,100,101,98,97,116\n,101,118,97,108,117,101,115,79,98,106,101,99,116,111,116,104,101,114,115,114,105\n,103,104,116,115,108,101,97,103,117,101,99,104,114,111,109,101,115,105,109,112,\n108,101,110,111,116,105,99,101,115,104,97,114,101,100,101,110,100,105,110,103,\n115,101,97,115,111,110,114,101,112,111,114,116,111,110,108,105,110,101,115,113,\n117,97,114,101,98,117,116,116,111,110,105,109,97,103,101,115,101,110,97,98,108,\n101,109,111,118,105,110,103,108,97,116,101,115,116,119,105,110,116,101,114,70,\n114,97,110,99,101,112,101,114,105,111,100,115,116,114,111,110,103,114,101,112,\n101,97,116,76,111,110,100,111,110,100,101,116,97,105,108,102,111,114,109,101,100\n,100,101,109,97,110,100,115,101,99,117,114,101,112,97,115,115,101,100,116,111,\n103,103,108,101,112,108,97,99,101,115,100,101,118,105,99,101,115,116,97,116,105,\n99,99,105,116,105,101,115,115,116,114,101,97,109,121,101,108,108,111,119,97,116,\n116,97,99,107,115,116,114,101,101,116,102,108,105,103,104,116,104,105,100,100,\n101,110,105,110,102,111,34,62,111,112,101,110,101,100,117,115,101,102,117,108,\n118,97,108,108,101,121,99,97,117,115,101,115,108,101,97,100,101,114,115,101,99,\n114,101,116,115,101,99,111,110,100,100,97,109,97,103,101,115,112,111,114,116,115\n,101,120,99,101,112,116,114,97,116,105,110,103,115,105,103,110,101,100,116,104,\n105,110,103,115,101,102,102,101,99,116,102,105,101,108,100,115,115,116,97,116,\n101,115,111,102,102,105,99,101,118,105,115,117,97,108,101,100,105,116,111,114,\n118,111,108,117,109,101,82,101,112,111,114,116,109,117,115,101,117,109,109,111,\n118,105,101,115,112,97,114,101,110,116,97,99,99,101,115,115,109,111,115,116,108,\n121,109,111,116,104,101,114,34,32,105,100,61,34,109,97,114,107,101,116,103,114,\n111,117,110,100,99,104,97,110,99,101,115,117,114,118,101,121,98,101,102,111,114,\n101,115,121,109,98,111,108,109,111,109,101,110,116,115,112,101,101,99,104,109,\n111,116,105,111,110,105,110,115,105,100,101,109,97,116,116,101,114,67,101,110,\n116,101,114,111,98,106,101,99,116,101,120,105,115,116,115,109,105,100,100,108,\n101,69,117,114,111,112,101,103,114,111,119,116,104,108,101,103,97,99,121,109,97,\n110,110,101,114,101,110,111,117,103,104,99,97,114,101,101,114,97,110,115,119,101\n,114,111,114,105,103,105,110,112,111,114,116,97,108,99,108,105,101,110,116,115,\n101,108,101,99,116,114,97,110,100,111,109,99,108,111,115,101,100,116,111,112,105\n,99,115,99,111,109,105,110,103,102,97,116,104,101,114,111,112,116,105,111,110,\n115,105,109,112,108,121,114,97,105,115,101,100,101,115,99,97,112,101,99,104,111,\n115,101,110,99,104,117,114,99,104,100,101,102,105,110,101,114,101,97,115,111,110\n,99,111,114,110,101,114,111,117,116,112,117,116,109,101,109,111,114,121,105,102,\n114,97,109,101,112,111,108,105,99,101,109,111,100,101,108,115,78,117,109,98,101,\n114,100,117,114,105,110,103,111,102,102,101,114,115,115,116,121,108,101,115,107,\n105,108,108,101,100,108,105,115,116,101,100,99,97,108,108,101,100,115,105,108,\n118,101,114,109,97,114,103,105,110,100,101,108,101,116,101,98,101,116,116,101,\n114,98,114,111,119,115,101,108,105,109,105,116,115,71,108,111,98,97,108,115,105,\n110,103,108,101,119,105,100,103,101,116,99,101,110,116,101,114,98,117,100,103,\n101,116,110,111,119,114,97,112,99,114,101,100,105,116,99,108,97,105,109,115,101,\n110,103,105,110,101,115,97,102,101,116,121,99,104,111,105,99,101,115,112,105,114\n,105,116,45,115,116,121,108,101,115,112,114,101,97,100,109,97,107,105,110,103,\n110,101,101,100,101,100,114,117,115,115,105,97,112,108,101,97,115,101,101,120,\n116,101,110,116,83,99,114,105,112,116,98,114,111,107,101,110,97,108,108,111,119,\n115,99,104,97,114,103,101,100,105,118,105,100,101,102,97,99,116,111,114,109,101,\n109,98,101,114,45,98,97,115,101,100,116,104,101,111,114,121,99,111,110,102,105,\n103,97,114,111,117,110,100,119,111,114,107,101,100,104,101,108,112,101,100,67,\n104,117,114,99,104,105,109,112,97,99,116,115,104,111,117,108,100,97,108,119,97,\n121,115,108,111,103,111,34,32,98,111,116,116,111,109,108,105,115,116,34,62,41,\n123,118,97,114,32,112,114,101,102,105,120,111,114,97,110,103,101,72,101,97,100,\n101,114,46,112,117,115,104,40,99,111,117,112,108,101,103,97,114,100,101,110,98,\n114,105,100,103,101,108,97,117,110,99,104,82,101,118,105,101,119,116,97,107,105,\n110,103,118,105,115,105,111,110,108,105,116,116,108,101,100,97,116,105,110,103,\n66,117,116,116,111,110,98,101,97,117,116,121,116,104,101,109,101,115,102,111,114\n,103,111,116,83,101,97,114,99,104,97,110,99,104,111,114,97,108,109,111,115,116,\n108,111,97,100,101,100,67,104,97,110,103,101,114,101,116,117,114,110,115,116,114\n,105,110,103,114,101,108,111,97,100,77,111,98,105,108,101,105,110,99,111,109,101\n,115,117,112,112,108,121,83,111,117,114,99,101,111,114,100,101,114,115,118,105,\n101,119,101,100,38,110,98,115,112,59,99,111,117,114,115,101,65,98,111,117,116,32\n,105,115,108,97,110,100,60,104,116,109,108,32,99,111,111,107,105,101,110,97,109,\n101,61,34,97,109,97,122,111,110,109,111,100,101,114,110,97,100,118,105,99,101,\n105,110,60,47,97,62,58,32,84,104,101,32,100,105,97,108,111,103,104,111,117,115,\n101,115,66,69,71,73,78,32,77,101,120,105,99,111,115,116,97,114,116,115,99,101,\n110,116,114,101,104,101,105,103,104,116,97,100,100,105,110,103,73,115,108,97,110\n,100,97,115,115,101,116,115,69,109,112,105,114,101,83,99,104,111,111,108,101,102\n,102,111,114,116,100,105,114,101,99,116,110,101,97,114,108,121,109,97,110,117,97\n,108,83,101,108,101,99,116,46,10,10,79,110,101,106,111,105,110,101,100,109,101,\n110,117,34,62,80,104,105,108,105,112,97,119,97,114,100,115,104,97,110,100,108,\n101,105,109,112,111,114,116,79,102,102,105,99,101,114,101,103,97,114,100,115,107\n,105,108,108,115,110,97,116,105,111,110,83,112,111,114,116,115,100,101,103,114,\n101,101,119,101,101,107,108,121,32,40,101,46,103,46,98,101,104,105,110,100,100,\n111,99,116,111,114,108,111,103,103,101,100,117,110,105,116,101,100,60,47,98,62,\n60,47,98,101,103,105,110,115,112,108,97,110,116,115,97,115,115,105,115,116,97,\n114,116,105,115,116,105,115,115,117,101,100,51,48,48,112,120,124,99,97,110,97,\n100,97,97,103,101,110,99,121,115,99,104,101,109,101,114,101,109,97,105,110,66,\n114,97,122,105,108,115,97,109,112,108,101,108,111,103,111,34,62,98,101,121,111,\n110,100,45,115,99,97,108,101,97,99,99,101,112,116,115,101,114,118,101,100,109,97\n,114,105,110,101,70,111,111,116,101,114,99,97,109,101,114,97,60,47,104,49,62,10,\n95,102,111,114,109,34,108,101,97,118,101,115,115,116,114,101,115,115,34,32,47,62\n,13,10,46,103,105,102,34,32,111,110,108,111,97,100,108,111,97,100,101,114,79,120\n,102,111,114,100,115,105,115,116,101,114,115,117,114,118,105,118,108,105,115,116\n,101,110,102,101,109,97,108,101,68,101,115,105,103,110,115,105,122,101,61,34,97,\n112,112,101,97,108,116,101,120,116,34,62,108,101,118,101,108,115,116,104,97,110,\n107,115,104,105,103,104,101,114,102,111,114,99,101,100,97,110,105,109,97,108,97,\n110,121,111,110,101,65,102,114,105,99,97,97,103,114,101,101,100,114,101,99,101,\n110,116,80,101,111,112,108,101,60,98,114,32,47,62,119,111,110,100,101,114,112,\n114,105,99,101,115,116,117,114,110,101,100,124,124,32,123,125,59,109,97,105,110,\n34,62,105,110,108,105,110,101,115,117,110,100,97,121,119,114,97,112,34,62,102,97\n,105,108,101,100,99,101,110,115,117,115,109,105,110,117,116,101,98,101,97,99,111\n,110,113,117,111,116,101,115,49,53,48,112,120,124,101,115,116,97,116,101,114,101\n,109,111,116,101,101,109,97,105,108,34,108,105,110,107,101,100,114,105,103,104,\n116,59,115,105,103,110,97,108,102,111,114,109,97,108,49,46,104,116,109,108,115,\n105,103,110,117,112,112,114,105,110,99,101,102,108,111,97,116,58,46,112,110,103,\n34,32,102,111,114,117,109,46,65,99,99,101,115,115,112,97,112,101,114,115,115,111\n,117,110,100,115,101,120,116,101,110,100,72,101,105,103,104,116,115,108,105,100,\n101,114,85,84,70,45,56,34,38,97,109,112,59,32,66,101,102,111,114,101,46,32,87,\n105,116,104,115,116,117,100,105,111,111,119,110,101,114,115,109,97,110,97,103,\n101,112,114,111,102,105,116,106,81,117,101,114,121,97,110,110,117,97,108,112,97,\n114,97,109,115,98,111,117,103,104,116,102,97,109,111,117,115,103,111,111,103,108\n,101,108,111,110,103,101,114,105,43,43,41,32,123,105,115,114,97,101,108,115,97,\n121,105,110,103,100,101,99,105,100,101,104,111,109,101,34,62,104,101,97,100,101,\n114,101,110,115,117,114,101,98,114,97,110,99,104,112,105,101,99,101,115,98,108,\n111,99,107,59,115,116,97,116,101,100,116,111,112,34,62,60,114,97,99,105,110,103,\n114,101,115,105,122,101,45,45,38,103,116,59,112,97,99,105,116,121,115,101,120,\n117,97,108,98,117,114,101,97,117,46,106,112,103,34,32,49,48,44,48,48,48,111,98,\n116,97,105,110,116,105,116,108,101,115,97,109,111,117,110,116,44,32,73,110,99,46\n,99,111,109,101,100,121,109,101,110,117,34,32,108,121,114,105,99,115,116,111,100\n,97,121,46,105,110,100,101,101,100,99,111,117,110,116,121,95,108,111,103,111,46,\n70,97,109,105,108,121,108,111,111,107,101,100,77,97,114,107,101,116,108,115,101,\n32,105,102,80,108,97,121,101,114,116,117,114,107,101,121,41,59,118,97,114,32,102\n,111,114,101,115,116,103,105,118,105,110,103,101,114,114,111,114,115,68,111,109,\n97,105,110,125,101,108,115,101,123,105,110,115,101,114,116,66,108,111,103,60,47,\n102,111,111,116,101,114,108,111,103,105,110,46,102,97,115,116,101,114,97,103,101\n,110,116,115,60,98,111,100,121,32,49,48,112,120,32,48,112,114,97,103,109,97,102,\n114,105,100,97,121,106,117,110,105,111,114,100,111,108,108,97,114,112,108,97,99,\n101,100,99,111,118,101,114,115,112,108,117,103,105,110,53,44,48,48,48,32,112,97,\n103,101,34,62,98,111,115,116,111,110,46,116,101,115,116,40,97,118,97,116,97,114,\n116,101,115,116,101,100,95,99,111,117,110,116,102,111,114,117,109,115,115,99,104\n,101,109,97,105,110,100,101,120,44,102,105,108,108,101,100,115,104,97,114,101,\n115,114,101,97,100,101,114,97,108,101,114,116,40,97,112,112,101,97,114,83,117,98\n,109,105,116,108,105,110,101,34,62,98,111,100,121,34,62,10,42,32,84,104,101,84,\n104,111,117,103,104,115,101,101,105,110,103,106,101,114,115,101,121,78,101,119,\n115,60,47,118,101,114,105,102,121,101,120,112,101,114,116,105,110,106,117,114,\n121,119,105,100,116,104,61,67,111,111,107,105,101,83,84,65,82,84,32,97,99,114,\n111,115,115,95,105,109,97,103,101,116,104,114,101,97,100,110,97,116,105,118,101,\n112,111,99,107,101,116,98,111,120,34,62,10,83,121,115,116,101,109,32,68,97,118,\n105,100,99,97,110,99,101,114,116,97,98,108,101,115,112,114,111,118,101,100,65,\n112,114,105,108,32,114,101,97,108,108,121,100,114,105,118,101,114,105,116,101,\n109,34,62,109,111,114,101,34,62,98,111,97,114,100,115,99,111,108,111,114,115,99,\n97,109,112,117,115,102,105,114,115,116,32,124,124,32,91,93,59,109,101,100,105,97\n,46,103,117,105,116,97,114,102,105,110,105,115,104,119,105,100,116,104,58,115,\n104,111,119,101,100,79,116,104,101,114,32,46,112,104,112,34,32,97,115,115,117,\n109,101,108,97,121,101,114,115,119,105,108,115,111,110,115,116,111,114,101,115,\n114,101,108,105,101,102,115,119,101,100,101,110,67,117,115,116,111,109,101,97,\n115,105,108,121,32,121,111,117,114,32,83,116,114,105,110,103,10,10,87,104,105,\n108,116,97,121,108,111,114,99,108,101,97,114,58,114,101,115,111,114,116,102,114,\n101,110,99,104,116,104,111,117,103,104,34,41,32,43,32,34,60,98,111,100,121,62,98\n,117,121,105,110,103,98,114,97,110,100,115,77,101,109,98,101,114,110,97,109,101,\n34,62,111,112,112,105,110,103,115,101,99,116,111,114,53,112,120,59,34,62,118,115\n,112,97,99,101,112,111,115,116,101,114,109,97,106,111,114,32,99,111,102,102,101,\n101,109,97,114,116,105,110,109,97,116,117,114,101,104,97,112,112,101,110,60,47,\n110,97,118,62,107,97,110,115,97,115,108,105,110,107,34,62,73,109,97,103,101,115,\n61,102,97,108,115,101,119,104,105,108,101,32,104,115,112,97,99,101,48,38,97,109,\n112,59,32,10,10,73,110,32,32,112,111,119,101,114,80,111,108,115,107,105,45,99,\n111,108,111,114,106,111,114,100,97,110,66,111,116,116,111,109,83,116,97,114,116,\n32,45,99,111,117,110,116,50,46,104,116,109,108,110,101,119,115,34,62,48,49,46,\n106,112,103,79,110,108,105,110,101,45,114,105,103,104,116,109,105,108,108,101,\n114,115,101,110,105,111,114,73,83,66,78,32,48,48,44,48,48,48,32,103,117,105,100,\n101,115,118,97,108,117,101,41,101,99,116,105,111,110,114,101,112,97,105,114,46,\n120,109,108,34,32,32,114,105,103,104,116,115,46,104,116,109,108,45,98,108,111,99\n,107,114,101,103,69,120,112,58,104,111,118,101,114,119,105,116,104,105,110,118,\n105,114,103,105,110,112,104,111,110,101,115,60,47,116,114,62,13,117,115,105,110,\n103,32,10,9,118,97,114,32,62,39,41,59,10,9,60,47,116,100,62,10,60,47,116,114,62,\n10,98,97,104,97,115,97,98,114,97,115,105,108,103,97,108,101,103,111,109,97,103,\n121,97,114,112,111,108,115,107,105,115,114,112,115,107,105,216,177,216,175,217,\n136,228,184,173,230,150,135,231,174,128,228,189,147,231,185,129,233,171,148,228,\n191,161,230,129,175,228,184,173,229,155,189,230,136,145,228,187,172,228,184,128,\n228,184,170,229,133,172,229,143,184,231,174,161,231,144,134,232,174,186,229,157,\n155,229,143,175,228,187,165,230,156,141,229,138,161,230,151,182,233,151,180,228,\n184,170,228,186,186,228,186,167,229,147,129,232,135,170,229,183,177,228,188,129,\n228,184,154,230,159,165,231,156,139,229,183,165,228,189,156,232,129,148,231,179,\n187,230,178,161,230,156,137,231,189,145,231,171,153,230,137,128,230,156,137,232,\n175,132,232,174,186,228,184,173,229,191,131,230,150,135,231,171,160,231,148,168,\n230,136,183,233,166,150,233,161,181,228,189,156,232,128,133,230,138,128,230,156,\n175,233,151,174,233,162,152,231,155,184,229,133,179,228,184,139,232,189,189,230,\n144,156,231,180,162,228,189,191,231,148,168,232,189,175,228,187,182,229,156,168,\n231,186,191,228,184,187,233,162,152,232,181,132,230,150,153,232,167,134,233,162,\n145,229,155,158,229,164,141,230,179,168,229,134,140,231,189,145,231,187,156,230,\n148,182,232,151,143,229,134,133,229,174,185,230,142,168,232,141,144,229,184,130,\n229,156,186,230,182,136,230,129,175,231,169,186,233,151,180,229,143,145,229,184,\n131,228,187,128,228,185,136,229,165,189,229,143,139,231,148,159,230,180,187,229,\n155,190,231,137,135,229,143,145,229,177,149,229,166,130,230,158,156,230,137,139,\n230,156,186,230,150,176,233,151,187,230,156,128,230,150,176,230,150,185,229,188,\n143,229,140,151,228,186,172,230,143,144,228,190,155,229,133,179,228,186,142,230,\n155,180,229,164,154,232,191,153,228,184,170,231,179,187,231,187,159,231,159,165,\n233,129,147,230,184,184,230,136,143,229,185,191,229,145,138,229,133,182,228,187,\n150,229,143,145,232,161,168,229,174,137,229,133,168,231,172,172,228,184,128,228,\n188,154,229,145,152,232,191,155,232,161,140,231,130,185,229,135,187,231,137,136,\n230,157,131,231,148,181,229,173,144,228,184,150,231,149,140,232,174,190,232,174,\n161,229,133,141,232,180,185,230,149,153,232,130,178,229,138,160,229,133,165,230,\n180,187,229,138,168,228,187,150,228,187,172,229,149,134,229,147,129,229,141,154,\n229,174,162,231,142,176,229,156,168,228,184,138,230,181,183,229,166,130,228,189,\n149,229,183,178,231,187,143,231,149,153,232,168,128,232,175,166,231,187,134,231,\n164,190,229,140,186,231,153,187,229,189,149,230,156,172,231,171,153,233,156,128,\n232,166,129,228,187,183,230,160,188,230,148,175,230,140,129,229,155,189,233,153,\n133,233,147,190,230,142,165,229,155,189,229,174,182,229,187,186,232,174,190,230,\n156,139,229,143,139,233,152,133,232,175,187,230,179,149,229,190,139,228,189,141,\n231,189,174,231,187,143,230,181,142,233,128,137,230,139,169,232,191,153,230,160,\n183,229,189,147,229,137,141,229,136,134,231,177,187,230,142,146,232,161,140,229,\n155,160,228,184,186,228,186,164,230,152,147,230,156,128,229,144,142,233,159,179,\n228,185,144,228,184,141,232,131,189,233,128,154,232,191,135,232,161,140,228,184,\n154,231,167,145,230,138,128,229,143,175,232,131,189,232,174,190,229,164,135,229,\n144,136,228,189,156,229,164,167,229,174,182,231,164,190,228,188,154,231,160,148,\n231,169,182,228,184,147,228,184,154,229,133,168,233,131,168,233,161,185,231,155,\n174,232,191,153,233,135,140,232,191,152,230,152,175,229,188,128,229,167,139,230,\n131,133,229,134,181,231,148,181,232,132,145,230,150,135,228,187,182,229,147,129,\n231,137,140,229,184,174,229,138,169,230,150,135,229,140,150,232,181,132,230,186,\n144,229,164,167,229,173,166,229,173,166,228,185,160,229,156,176,229,157,128,230,\n181,143,232,167,136,230,138,149,232,181,132,229,183,165,231,168,139,232,166,129,\n230,177,130,230,128,142,228,185,136,230,151,182,229,128,153,229,138,159,232,131,\n189,228,184,187,232,166,129,231,155,174,229,137,141,232,181,132,232,174,175,229,\n159,142,229,184,130,230,150,185,230,179,149,231,148,181,229,189,177,230,139,155,\n232,129,152,229,163,176,230,152,142,228,187,187,228,189,149,229,129,165,229,186,\n183,230,149,176,230,141,174,231,190,142,229,155,189,230,177,189,232,189,166,228,\n187,139,231,187,141,228,189,134,230,152,175,228,186,164,230,181,129,231,148,159,\n228,186,167,230,137,128,228,187,165,231,148,181,232,175,157,230,152,190,231,164,\n186,228,184,128,228,186,155,229,141,149,228,189,141,228,186,186,229,145,152,229,\n136,134,230,158,144,229,156,176,229,155,190,230,151,133,230,184,184,229,183,165,\n229,133,183,229,173,166,231,148,159,231,179,187,229,136,151,231,189,145,229,143,\n139,229,184,150,229,173,144,229,175,134,231,160,129,233,162,145,233,129,147,230,\n142,167,229,136,182,229,156,176,229,140,186,229,159,186,230,156,172,229,133,168,\n229,155,189,231,189,145,228,184,138,233,135,141,232,166,129,231,172,172,228,186,\n140,229,150,156,230,172,162,232,191,155,229,133,165,229,143,139,230,131,133,232,\n191,153,228,186,155,232,128,131,232,175,149,229,143,145,231,142,176,229,159,185,\n232,174,173,228,187,165,228,184,138,230,148,191,229,186,156,230,136,144,228,184,\n186,231,142,175,229,162,131,233,166,153,230,184,175,229,144,140,230,151,182,229,\n168,177,228,185,144,229,143,145,233,128,129,228,184,128,229,174,154,229,188,128,\n229,143,145,228,189,156,229,147,129,230,160,135,229,135,134,230,172,162,232,191,\n142,232,167,163,229,134,179,229,156,176,230,150,185,228,184,128,228,184,139,228,\n187,165,229,143,138,232,180,163,228,187,187,230,136,150,232,128,133,229,174,162,\n230,136,183,228,187,163,232,161,168,231,167,175,229,136,134,229,165,179,228,186,\n186,230,149,176,231,160,129,233,148,128,229,148,174,229,135,186,231,142,176,231,\n166,187,231,186,191,229,186,148,231,148,168,229,136,151,232,161,168,228,184,141,\n229,144,140,231,188,150,232,190,145,231,187,159,232,174,161,230,159,165,232,175,\n162,228,184,141,232,166,129,230,156,137,229,133,179,230,156,186,230,158,132,229,\n190,136,229,164,154,230,146,173,230,148,190,231,187,132,231,187,135,230,148,191,\n231,173,150,231,155,180,230,142,165,232,131,189,229,138,155,230,157,165,230,186,\n144,230,153,130,233,150,147,231,156,139,229,136,176,231,131,173,233,151,168,229,\n133,179,233,148,174,228,184,147,229,140,186,233,157,158,229,184,184,232,139,177,\n232,175,173,231,153,190,229,186,166,229,184,140,230,156,155,231,190,142,229,165,\n179,230,175,148,232,190,131,231,159,165,232,175,134,232,167,132,229,174,154,229,\n187,186,232,174,174,233,131,168,233,151,168,230,132,143,232,167,129,231,178,190,\n229,189,169,230,151,165,230,156,172,230,143,144,233,171,152,229,143,145,232,168,\n128,230,150,185,233,157,162,229,159,186,233,135,145,229,164,132,231,144,134,230,\n157,131,233,153,144,229,189,177,231,137,135,233,147,182,232,161,140,232,191,152,\n230,156,137,229,136,134,228,186,171,231,137,169,229,147,129,231,187,143,232,144,\n165,230,183,187,229,138,160,228,184,147,229,174,182,232,191,153,231,167,141,232,\n175,157,233,162,152,232,181,183,230,157,165,228,184,154,229,138,161,229,133,172,\n229,145,138,232,174,176,229,189,149,231,174,128,228,187,139,232,180,168,233,135,\n143,231,148,183,228,186,186,229,189,177,229,147,141,229,188,149,231,148,168,230,\n138,165,229,145,138,233,131,168,229,136,134,229,191,171,233,128,159,229,146,168,\n232,175,162,230,151,182,229,176,154,230,179,168,230,132,143,231,148,179,232,175,\n183,229,173,166,230,160,161,229,186,148,232,175,165,229,142,134,229,143,178,229,\n143,170,230,152,175,232,191,148,229,155,158,232,180,173,228,185,176,229,144,141,\n231,167,176,228,184,186,228,186,134,230,136,144,229,138,159,232,175,180,230,152,\n142,228,190,155,229,186,148,229,173,169,229,173,144,228,184,147,233,162,152,231,\n168,139,229,186,143,228,184,128,232,136,172,230,156,131,229,147,161,229,143,170,\n230,156,137,229,133,182,229,174,131,228,191,157,230,138,164,232,128,140,228,184,\n148,228,187,138,229,164,169,231,170,151,229,143,163,229,138,168,230,128,129,231,\n138,182,230,128,129,231,137,185,229,136,171,232,174,164,228,184,186,229,191,133,\n233,161,187,230,155,180,230,150,176,229,176,143,232,175,180,230,136,145,229,128,\n145,228,189,156,228,184,186,229,170,146,228,189,147,229,140,133,230,139,172,233,\n130,163,228,185,136,228,184,128,230,160,183,229,155,189,229,134,133,230,152,175,\n229,144,166,230,160,185,230,141,174,231,148,181,232,167,134,229,173,166,233,153,\n162,229,133,183,230,156,137,232,191,135,231,168,139,231,148,177,228,186,142,228,\n186,186,230,137,141,229,135,186,230,157,165,228,184,141,232,191,135,230,173,163,\n229,156,168,230,152,142,230,152,159,230,149,133,228,186,139,229,133,179,231,179,\n187,230,160,135,233,162,152,229,149,134,229,138,161,232,190,147,229,133,165,228,\n184,128,231,155,180,229,159,186,231,161,128,230,149,153,229,173,166,228,186,134,\n232,167,163,229,187,186,231,173,145,231,187,147,230,158,156,229,133,168,231,144,\n131,233,128,154,231,159,165,232,174,161,229,136,146,229,175,185,228,186,142,232,\n137,186,230,156,175,231,155,184,229,134,140,229,143,145,231,148,159,231,156,159,\n231,154,132,229,187,186,231,171,139,231,173,137,231,186,167,231,177,187,229,158,\n139,231,187,143,233,170,140,229,174,158,231,142,176,229,136,182,228,189,156,230,\n157,165,232,135,170,230,160,135,231,173,190,228,187,165,228,184,139,229,142,159,\n229,136,155,230,151,160,230,179,149,229,133,182,228,184,173,229,128,139,228,186,\n186,228,184,128,229,136,135,230,140,135,229,141,151,229,133,179,233,151,173,233,\n155,134,229,155,162,231,172,172,228,184,137,229,133,179,230,179,168,229,155,160,\n230,173,164,231,133,167,231,137,135,230,183,177,229,156,179,229,149,134,228,184,\n154,229,185,191,229,183,158,230,151,165,230,156,159,233,171,152,231,186,167,230,\n156,128,232,191,145,231,187,188,229,144,136,232,161,168,231,164,186,228,184,147,\n232,190,145,232,161,140,228,184,186,228,186,164,233,128,154,232,175,132,228,187,\n183,232,167,137,229,190,151,231,178,190,229,141,142,229,174,182,229,186,173,229,\n174,140,230,136,144,230,132,159,232,167,137,229,174,137,232,163,133,229,190,151,\n229,136,176,233,130,174,228,187,182,229,136,182,229,186,166,233,163,159,229,147,\n129,232,153,189,231,132,182,232,189,172,232,189,189,230,138,165,228,187,183,232,\n174,176,232,128,133,230,150,185,230,161,136,232,161,140,230,148,191,228,186,186,\n230,176,145,231,148,168,229,147,129,228,184,156,232,165,191,230,143,144,229,135,\n186,233,133,146,229,186,151,231,132,182,229,144,142,228,187,152,230,172,190,231,\n131,173,231,130,185,228,187,165,229,137,141,229,174,140,229,133,168,229,143,145,\n229,184,150,232,174,190,231,189,174,233,162,134,229,175,188,229,183,165,228,184,\n154,229,140,187,233,153,162,231,156,139,231,156,139,231,187,143,229,133,184,229,\n142,159,229,155,160,229,185,179,229,143,176,229,144,132,231,167,141,229,162,158,\n229,138,160,230,157,144,230,150,153,230,150,176,229,162,158,228,185,139,229,144,\n142,232,129,140,228,184,154,230,149,136,230,158,156,228,187,138,229,185,180,232,\n174,186,230,150,135,230,136,145,229,155,189,229,145,138,232,175,137,231,137,136,\n228,184,187,228,191,174,230,148,185,229,143,130,228,184,142,230,137,147,229,141,\n176,229,191,171,228,185,144,230,156,186,230,162,176,232,167,130,231,130,185,229,\n173,152,229,156,168,231,178,190,231,165,158,232,142,183,229,190,151,229,136,169,\n231,148,168,231,187,167,231,187,173,228,189,160,228,187,172,232,191,153,228,185,\n136,230,168,161,229,188,143,232,175,173,232,168,128,232,131,189,229,164,159,233,\n155,133,232,153,142,230,147,141,228,189,156,233,163,142,230,160,188,228,184,128,\n232,181,183,231,167,145,229,173,166,228,189,147,232,130,178,231,159,173,228,191,\n161,230,157,161,228,187,182,230,178,187,231,150,151,232,191,144,229,138,168,228,\n186,167,228,184,154,228,188,154,232,174,174,229,175,188,232,136,170,229,133,136,\n231,148,159,232,129,148,231,155,159,229,143,175,230,152,175,229,149,143,233,161,\n140,231,187,147,230,158,132,228,189,156,231,148,168,232,176,131,230,159,165,232,\n179,135,230,150,153,232,135,170,229,138,168,232,180,159,232,180,163,229,134,156,\n228,184,154,232,174,191,233,151,174,229,174,158,230,150,189,230,142,165,229,143,\n151,232,174,168,232,174,186,233,130,163,228,184,170,229,143,141,233,166,136,229,\n138,160,229,188,186,229,165,179,230,128,167,232,140,131,229,155,180,230,156,141,\n229,139,153,228,188,145,233,151,178,228,187,138,230,151,165,229,174,162,230,156,\n141,232,167,128,231,156,139,229,143,130,229,138,160,231,154,132,232,175,157,228,\n184,128,231,130,185,228,191,157,232,175,129,229,155,190,228,185,166,230,156,137,\n230,149,136,230,181,139,232,175,149,231,167,187,229,138,168,230,137,141,232,131,\n189,229,134,179,229,174,154,232,130,161,231,165,168,228,184,141,230,150,173,233,\n156,128,230,177,130,228,184,141,229,190,151,229,138,158,230,179,149,228,185,139,\n233,151,180,233,135,135,231,148,168,232,144,165,233,148,128,230,138,149,232,175,\n137,231,155,174,230,160,135,231,136,177,230,131,133,230,145,132,229,189,177,230,\n156,137,228,186,155,232,164,135,232,163,189,230,150,135,229,173,166,230,156,186,\n228,188,154,230,149,176,229,173,151,232,163,133,228,191,174,232,180,173,231,137,\n169,229,134,156,230,157,145,229,133,168,233,157,162,231,178,190,229,147,129,229,\n133,182,229,174,158,228,186,139,230,131,133,230,176,180,229,185,179,230,143,144,\n231,164,186,228,184,138,229,184,130,232,176,162,232,176,162,230,153,174,233,128,\n154,230,149,153,229,184,136,228,184,138,228,188,160,231,177,187,229,136,171,230,\n173,140,230,155,178,230,139,165,230,156,137,229,136,155,230,150,176,233,133,141,\n228,187,182,229,143,170,232,166,129,230,151,182,228,187,163,232,179,135,232,168,\n138,232,190,190,229,136,176,228,186,186,231,148,159,232,174,162,233,152,133,232,\n128,129,229,184,136,229,177,149,231,164,186,229,191,131,231,144,134,232,180,180,\n229,173,144,231,182,178,231,171,153,228,184,187,233,161,140,232,135,170,231,132,\n182,231,186,167,229,136,171,231,174,128,229,141,149,230,148,185,233,157,169,233,\n130,163,228,186,155,230,157,165,232,175,180,230,137,147,229,188,128,228,187,163,\n231,160,129,229,136,160,233,153,164,232,175,129,229,136,184,232,138,130,231,155,\n174,233,135,141,231,130,185,230,172,161,230,149,184,229,164,154,229,176,145,232,\n167,132,229,136,146,232,181,132,233,135,145,230,137,190,229,136,176,228,187,165,\n229,144,142,229,164,167,229,133,168,228,184,187,233,161,181,230,156,128,228,189,\n179,229,155,158,231,173,148,229,164,169,228,184,139,228,191,157,233,154,156,231,\n142,176,228,187,163,230,163,128,230,159,165,230,138,149,231,165,168,229,176,143,\n230,151,182,230,178,146,230,156,137,230,173,163,229,184,184,231,148,154,232,135,\n179,228,187,163,231,144,134,231,155,174,229,189,149,229,133,172,229,188,128,229,\n164,141,229,136,182,233,135,145,232,158,141,229,185,184,231,166,143,231,137,136,\n230,156,172,229,189,162,230,136,144,229,135,134,229,164,135,232,161,140,230,131,\n133,229,155,158,229,136,176,230,128,157,230,131,179,230,128,142,230,160,183,229,\n141,143,232,174,174,232,174,164,232,175,129,230,156,128,229,165,189,228,186,167,\n231,148,159,230,140,137,231,133,167,230,156,141,232,163,133,229,185,191,228,184,\n156,229,138,168,230,188,171,233,135,135,232,180,173,230,150,176,230,137,139,231,\n187,132,229,155,190,233,157,162,230,157,191,229,143,130,232,128,131,230,148,191,\n230,178,187,229,174,185,230,152,147,229,164,169,229,156,176,229,138,170,229,138,\n155,228,186,186,228,187,172,229,141,135,231,186,167,233,128,159,229,186,166,228,\n186,186,231,137,169,232,176,131,230,149,180,230,181,129,232,161,140,233,128,160,\n230,136,144,230,150,135,229,173,151,233,159,169,229,155,189,232,180,184,230,152,\n147,229,188,128,229,177,149,231,155,184,233,151,156,232,161,168,231,142,176,229,\n189,177,232,167,134,229,166,130,230,173,164,231,190,142,229,174,185,229,164,167,\n229,176,143,230,138,165,233,129,147,230,157,161,230,172,190,229,191,131,230,131,\n133,232,174,184,229,164,154,230,179,149,232,167,132,229,174,182,229,177,133,228,\n185,166,229,186,151,232,191,158,230,142,165,231,171,139,229,141,179,228,184,190,\n230,138,165,230,138,128,229,183,167,229,165,165,232,191,144,231,153,187,229,133,\n165,228,187,165,230,157,165,231,144,134,232,174,186,228,186,139,228,187,182,232,\n135,170,231,148,177,228,184,173,229,141,142,229,138,158,229,133,172,229,166,136,\n229,166,136,231,156,159,230,173,163,228,184,141,233,148,153,229,133,168,230,150,\n135,229,144,136,229,144,140,228,187,183,229,128,188,229,136,171,228,186,186,231,\n155,145,231,157,163,229,133,183,228,189,147,228,184,150,231,186,170,229,155,162,\n233,152,159,229,136,155,228,184,154,230,137,191,230,139,133,229,162,158,233,149,\n191,230,156,137,228,186,186,228,191,157,230,140,129,229,149,134,229,174,182,231,\n187,180,228,191,174,229,143,176,230,185,190,229,183,166,229,143,179,232,130,161,\n228,187,189,231,173,148,230,161,136,229,174,158,233,153,133,231,148,181,228,191,\n161,231,187,143,231,144,134,231,148,159,229,145,189,229,174,163,228,188,160,228,\n187,187,229,138,161,230,173,163,229,188,143,231,137,185,232,137,178,228,184,139,\n230,157,165,229,141,143,228,188,154,229,143,170,232,131,189,229,189,147,231,132,\n182,233,135,141,230,150,176,229,133,167,229,174,185,230,140,135,229,175,188,232,\n191,144,232,161,140,230,151,165,229,191,151,232,179,163,229,174,182,232,182,133,\n232,191,135,229,156,159,229,156,176,230,181,153,230,177,159,230,148,175,228,187,\n152,230,142,168,229,135,186,231,171,153,233,149,191,230,157,173,229,183,158,230,\n137,167,232,161,140,229,136,182,233,128,160,228,185,139,228,184,128,230,142,168,\n229,185,191,231,142,176,229,156,186,230,143,143,232,191,176,229,143,152,229,140,\n150,228,188,160,231,187,159,230,173,140,230,137,139,228,191,157,233,153,169,232,\n175,190,231,168,139,229,140,187,231,150,151,231,187,143,232,191,135,232,191,135,\n229,142,187,228,185,139,229,137,141,230,148,182,229,133,165,229,185,180,229,186,\n166,230,157,130,229,191,151,231,190,142,228,184,189,230,156,128,233,171,152,231,\n153,187,233,153,134,230,156,170,230,157,165,229,138,160,229,183,165,229,133,141,\n232,180,163,230,149,153,231,168,139,231,137,136,229,157,151,232,186,171,228,189,\n147,233,135,141,229,186,134,229,135,186,229,148,174,230,136,144,230,156,172,229,\n189,162,229,188,143,229,156,159,232,177,134,229,135,186,229,131,185,228,184,156,\n230,150,185,233,130,174,231,174,177,229,141,151,228,186,172,230,177,130,232,129,\n140,229,143,150,229,190,151,232,129,140,228,189,141,231,155,184,228,191,161,233,\n161,181,233,157,162,229,136,134,233,146,159,231,189,145,233,161,181,231,161,174,\n229,174,154,229,155,190,228,190,139,231,189,145,229,157,128,231,167,175,230,158,\n129,233,148,153,232,175,175,231,155,174,231,154,132,229,174,157,232,180,157,230,\n156,186,229,133,179,233,163,142,233,153,169,230,142,136,230,157,131,231,151,133,\n230,175,146,229,174,160,231,137,169,233,153,164,228,186,134,232,169,149,232,171,\n150,231,150,190,231,151,133,229,143,138,230,151,182,230,177,130,232,180,173,231,\n171,153,231,130,185,229,132,191,231,171,165,230,175,143,229,164,169,228,184,173,\n229,164,174,232,174,164,232,175,134,230,175,143,228,184,170,229,164,169,230,180,\n165,229,173,151,228,189,147,229,143,176,231,129,163,231,187,180,230,138,164,230,\n156,172,233,161,181,228,184,170,230,128,167,229,174,152,230,150,185,229,184,184,\n232,167,129,231,155,184,230,156,186,230,136,152,231,149,165,229,186,148,229,189,\n147,229,190,139,229,184,136,230,150,185,228,190,191,230,160,161,229,155,173,232,\n130,161,229,184,130,230,136,191,229,177,139,230,160,143,231,155,174,229,145,152,\n229,183,165,229,175,188,232,135,180,231,170,129,231,132,182,233,129,147,229,133,\n183,230,156,172,231,189,145,231,187,147,229,144,136,230,161,163,230,161,136,229,\n138,179,229,138,168,229,143,166,229,164,150,231,190,142,229,133,131,229,188,149,\n232,181,183,230,148,185,229,143,152,231,172,172,229,155,155,228,188,154,232,174,\n161,232,170,170,230,152,142,233,154,144,231,167,129,229,174,157,229,174,157,232,\n167,132,232,140,131,230,182,136,232,180,185,229,133,177,229,144,140,229,191,152,\n232,174,176,228,189,147,231,179,187,229,184,166,230,157,165,229,144,141,229,173,\n151,231,153,188,232,161,168,229,188,128,230,148,190,229,138,160,231,155,159,229,\n143,151,229,136,176,228,186,140,230,137,139,229,164,167,233,135,143,230,136,144,\n228,186,186,230,149,176,233,135,143,229,133,177,228,186,171,229,140,186,229,159,\n159,229,165,179,229,173,169,229,142,159,229,136,153,230,137,128,229,156,168,231,\n187,147,230,157,159,233,128,154,228,191,161,232,182,133,231,186,167,233,133,141,\n231,189,174,229,189,147,230,151,182,228,188,152,231,167,128,230,128,167,230,132,\n159,230,136,191,228,186,167,233,129,138,230,136,178,229,135,186,229,143,163,230,\n143,144,228,186,164,229,176,177,228,184,154,228,191,157,229,129,165,231,168,139,\n229,186,166,229,143,130,230,149,176,228,186,139,228,184,154,230,149,180,228,184,\n170,229,177,177,228,184,156,230,131,133,230,132,159,231,137,185,230,174,138,229,\n136,134,233,161,158,230,144,156,229,176,139,229,177,158,228,186,142,233,151,168,\n230,136,183,232,180,162,229,138,161,229,163,176,233,159,179,229,143,138,229,133,\n182,232,180,162,231,187,143,229,157,154,230,140,129,229,185,178,233,131,168,230,\n136,144,231,171,139,229,136,169,231,155,138,232,128,131,232,153,145,230,136,144,\n233,131,189,229,140,133,232,163,133,231,148,168,230,136,182,230,175,148,232,181,\n155,230,150,135,230,152,142,230,139,155,229,149,134,229,174,140,230,149,180,231,\n156,159,230,152,175,231,156,188,231,157,155,228,188,153,228,188,180,229,168,129,\n230,156,155,233,162,134,229,159,159,229,141,171,231,148,159,228,188,152,230,131,\n160,232,171,150,229,163,135,229,133,172,229,133,177,232,137,175,229,165,189,229,\n133,133,229,136,134,231,172,166,229,144,136,233,153,132,228,187,182,231,137,185,\n231,130,185,228,184,141,229,143,175,232,139,177,230,150,135,232,181,132,228,186,\n167,230,160,185,230,156,172,230,152,142,230,152,190,229,175,134,231,162,188,229,\n133,172,228,188,151,230,176,145,230,151,143,230,155,180,229,138,160,228,186,171,\n229,143,151,229,144,140,229,173,166,229,144,175,229,138,168,233,128,130,229,144,\n136,229,142,159,230,157,165,233,151,174,231,173,148,230,156,172,230,150,135,231,\n190,142,233,163,159,231,187,191,232,137,178,231,168,179,229,174,154,231,187,136,\n228,186,142,231,148,159,231,137,169,228,190,155,230,177,130,230,144,156,231,139,\n144,229,138,155,233,135,143,228,184,165,233,135,141,230,176,184,232,191,156,229,\n134,153,231,156,159,230,156,137,233,153,144,231,171,158,228,186,137,229,175,185,\n232,177,161,232,180,185,231,148,168,228,184,141,229,165,189,231,187,157,229,175,\n185,229,141,129,229,136,134,228,191,131,232,191,155,231,130,185,232,175,132,229,\n189,177,233,159,179,228,188,152,229,138,191,228,184,141,229,176,145,230,172,163,\n232,181,143,229,185,182,228,184,148,230,156,137,231,130,185,230,150,185,229,144,\n145,229,133,168,230,150,176,228,191,161,231,148,168,232,174,190,230,150,189,229,\n189,162,232,177,161,232,181,132,230,160,188,231,170,129,231,160,180,233,154,143,\n231,157,128,233,135,141,229,164,167,228,186,142,230,152,175,230,175,149,228,184,\n154,230,153,186,232,131,189,229,140,150,229,183,165,229,174,140,231,190,142,229,\n149,134,229,159,142,231,187,159,228,184,128,229,135,186,231,137,136,230,137,147,\n233,128,160,231,148,162,229,147,129,230,166,130,229,134,181,231,148,168,228,186,\n142,228,191,157,231,149,153,229,155,160,231,180,160,228,184,173,229,156,139,229,\n173,152,229,130,168,232,180,180,229,155,190,230,156,128,230,132,155,233,149,191,\n230,156,159,229,143,163,228,187,183,231,144,134,232,180,162,229,159,186,229,156,\n176,229,174,137,230,142,146,230,173,166,230,177,137,233,135,140,233,157,162,229,\n136,155,229,187,186,229,164,169,231,169,186,233,166,150,229,133,136,229,174,140,\n229,150,132,233,169,177,229,138,168,228,184,139,233,157,162,228,184,141,229,134,\n141,232,175,154,228,191,161,230,132,143,228,185,137,233,152,179,229,133,137,232,\n139,177,229,155,189,230,188,130,228,186,174,229,134,155,228,186,139,231,142,169,\n229,174,182,231,190,164,228,188,151,229,134,156,230,176,145,229,141,179,229,143,\n175,229,144,141,231,168,177,229,174,182,229,133,183,229,138,168,231,148,187,230,\n131,179,229,136,176,230,179,168,230,152,142,229,176,143,229,173,166,230,128,167,\n232,131,189,232,128,131,231,160,148,231,161,172,228,187,182,232,167,130,231,156,\n139,230,184,133,230,165,154,230,144,158,231,172,145,233,166,150,233,160,129,233,\n187,132,233,135,145,233,128,130,231,148,168,230,177,159,232,139,143,231,156,159,\n229,174,158,228,184,187,231,174,161,233,152,182,230,174,181,232,168,187,229,134,\n138,231,191,187,232,175,145,230,157,131,229,136,169,229,129,154,229,165,189,228,\n188,188,228,185,142,233,128,154,232,174,175,230,150,189,229,183,165,231,139,128,\n230,133,139,228,185,159,232,174,184,231,142,175,228,191,157,229,159,185,229,133,\n187,230,166,130,229,191,181,229,164,167,229,158,139,230,156,186,231,165,168,231,\n144,134,232,167,163,229,140,191,229,144,141,99,117,97,110,100,111,101,110,118,\n105,97,114,109,97,100,114,105,100,98,117,115,99,97,114,105,110,105,99,105,111,\n116,105,101,109,112,111,112,111,114,113,117,101,99,117,101,110,116,97,101,115,\n116,97,100,111,112,117,101,100,101,110,106,117,101,103,111,115,99,111,110,116,\n114,97,101,115,116,195,161,110,110,111,109,98,114,101,116,105,101,110,101,110,\n112,101,114,102,105,108,109,97,110,101,114,97,97,109,105,103,111,115,99,105,117,\n100,97,100,99,101,110,116,114,111,97,117,110,113,117,101,112,117,101,100,101,115\n,100,101,110,116,114,111,112,114,105,109,101,114,112,114,101,99,105,111,115,101,\n103,195,186,110,98,117,101,110,111,115,118,111,108,118,101,114,112,117,110,116,\n111,115,115,101,109,97,110,97,104,97,98,195,173,97,97,103,111,115,116,111,110,\n117,101,118,111,115,117,110,105,100,111,115,99,97,114,108,111,115,101,113,117,\n105,112,111,110,105,195,177,111,115,109,117,99,104,111,115,97,108,103,117,110,97\n,99,111,114,114,101,111,105,109,97,103,101,110,112,97,114,116,105,114,97,114,114\n,105,98,97,109,97,114,195,173,97,104,111,109,98,114,101,101,109,112,108,101,111,\n118,101,114,100,97,100,99,97,109,98,105,111,109,117,99,104,97,115,102,117,101,\n114,111,110,112,97,115,97,100,111,108,195,173,110,101,97,112,97,114,101,99,101,\n110,117,101,118,97,115,99,117,114,115,111,115,101,115,116,97,98,97,113,117,105,\n101,114,111,108,105,98,114,111,115,99,117,97,110,116,111,97,99,99,101,115,111,\n109,105,103,117,101,108,118,97,114,105,111,115,99,117,97,116,114,111,116,105,101\n,110,101,115,103,114,117,112,111,115,115,101,114,195,161,110,101,117,114,111,112\n,97,109,101,100,105,111,115,102,114,101,110,116,101,97,99,101,114,99,97,100,101,\n109,195,161,115,111,102,101,114,116,97,99,111,99,104,101,115,109,111,100,101,108\n,111,105,116,97,108,105,97,108,101,116,114,97,115,97,108,103,195,186,110,99,111,\n109,112,114,97,99,117,97,108,101,115,101,120,105,115,116,101,99,117,101,114,112,\n111,115,105,101,110,100,111,112,114,101,110,115,97,108,108,101,103,97,114,118,\n105,97,106,101,115,100,105,110,101,114,111,109,117,114,99,105,97,112,111,100,114\n,195,161,112,117,101,115,116,111,100,105,97,114,105,111,112,117,101,98,108,111,\n113,117,105,101,114,101,109,97,110,117,101,108,112,114,111,112,105,111,99,114,\n105,115,105,115,99,105,101,114,116,111,115,101,103,117,114,111,109,117,101,114,\n116,101,102,117,101,110,116,101,99,101,114,114,97,114,103,114,97,110,100,101,101\n,102,101,99,116,111,112,97,114,116,101,115,109,101,100,105,100,97,112,114,111,\n112,105,97,111,102,114,101,99,101,116,105,101,114,114,97,101,45,109,97,105,108,\n118,97,114,105,97,115,102,111,114,109,97,115,102,117,116,117,114,111,111,98,106,\n101,116,111,115,101,103,117,105,114,114,105,101,115,103,111,110,111,114,109,97,\n115,109,105,115,109,111,115,195,186,110,105,99,111,99,97,109,105,110,111,115,105\n,116,105,111,115,114,97,122,195,179,110,100,101,98,105,100,111,112,114,117,101,\n98,97,116,111,108,101,100,111,116,101,110,195,173,97,106,101,115,195,186,115,101\n,115,112,101,114,111,99,111,99,105,110,97,111,114,105,103,101,110,116,105,101,\n110,100,97,99,105,101,110,116,111,99,195,161,100,105,122,104,97,98,108,97,114,\n115,101,114,195,173,97,108,97,116,105,110,97,102,117,101,114,122,97,101,115,116,\n105,108,111,103,117,101,114,114,97,101,110,116,114,97,114,195,169,120,105,116,\n111,108,195,179,112,101,122,97,103,101,110,100,97,118,195,173,100,101,111,101,\n118,105,116,97,114,112,97,103,105,110,97,109,101,116,114,111,115,106,97,118,105,\n101,114,112,97,100,114,101,115,102,195,161,99,105,108,99,97,98,101,122,97,195,\n161,114,101,97,115,115,97,108,105,100,97,101,110,118,195,173,111,106,97,112,195,\n179,110,97,98,117,115,111,115,98,105,101,110,101,115,116,101,120,116,111,115,108\n,108,101,118,97,114,112,117,101,100,97,110,102,117,101,114,116,101,99,111,109,\n195,186,110,99,108,97,115,101,115,104,117,109,97,110,111,116,101,110,105,100,111\n,98,105,108,98,97,111,117,110,105,100,97,100,101,115,116,195,161,115,101,100,105\n,116,97,114,99,114,101,97,100,111,208,180,208,187,209,143,209,135,209,130,208,\n190,208,186,208,176,208,186,208,184,208,187,208,184,209,141,209,130,208,190,208,\n178,209,129,208,181,208,181,208,179,208,190,208,191,209,128,208,184,209,130,208,\n176,208,186,208,181,209,137,208,181,209,131,208,182,208,181,208,154,208,176,208,\n186,208,177,208,181,208,183,208,177,209,139,208,187,208,190,208,189,208,184,208,\n146,209,129,208,181,208,191,208,190,208,180,208,173,209,130,208,190,209,130,208,\n190,208,188,209,135,208,181,208,188,208,189,208,181,209,130,208,187,208,181,209,\n130,209,128,208,176,208,183,208,190,208,189,208,176,208,179,208,180,208,181,208,\n188,208,189,208,181,208,148,208,187,209,143,208,159,209,128,208,184,208,189,208,\n176,209,129,208,189,208,184,209,133,209,130,208,181,208,188,208,186,209,130,208,\n190,208,179,208,190,208,180,208,178,208,190,209,130,209,130,208,176,208,188,208,\n161,208,168,208,144,208,188,208,176,209,143,208,167,209,130,208,190,208,178,208,\n176,209,129,208,178,208,176,208,188,208,181,208,188,209,131,208,162,208,176,208,\n186,208,180,208,178,208,176,208,189,208,176,208,188,209,141,209,130,208,184,209,\n141,209,130,209,131,208,146,208,176,208,188,209,130,208,181,209,133,208,191,209,\n128,208,190,209,130,209,131,209,130,208,189,208,176,208,180,208,180,208,189,209,\n143,208,146,208,190,209,130,209,130,209,128,208,184,208,189,208,181,208,185,208,\n146,208,176,209,129,208,189,208,184,208,188,209,129,208,176,208,188,209,130,208,\n190,209,130,209,128,209,131,208,177,208,158,208,189,208,184,208,188,208,184,209,\n128,208,189,208,181,208,181,208,158,208,158,208,158,208,187,208,184,209,134,209,\n141,209,130,208,176,208,158,208,189,208,176,208,189,208,181,208,188,208,180,208,\n190,208,188,208,188,208,190,208,185,208,180,208,178,208,181,208,190,208,189,208,\n190,209,129,209,131,208,180,224,164,149,224,165,135,224,164,185,224,165,136,224,\n164,149,224,165,128,224,164,184,224,165,135,224,164,149,224,164,190,224,164,149,\n224,165,139,224,164,148,224,164,176,224,164,170,224,164,176,224,164,168,224,165,\n135,224,164,143,224,164,149,224,164,149,224,164,191,224,164,173,224,165,128,224,\n164,135,224,164,184,224,164,149,224,164,176,224,164,164,224,165,139,224,164,185,\n224,165,139,224,164,134,224,164,170,224,164,185,224,165,128,224,164,175,224,164,\n185,224,164,175,224,164,190,224,164,164,224,164,149,224,164,165,224,164,190,106,\n97,103,114,97,110,224,164,134,224,164,156,224,164,156,224,165,139,224,164,133,\n224,164,172,224,164,166,224,165,139,224,164,151,224,164,136,224,164,156,224,164,\n190,224,164,151,224,164,143,224,164,185,224,164,174,224,164,135,224,164,168,224,\n164,181,224,164,185,224,164,175,224,165,135,224,164,165,224,165,135,224,164,165,\n224,165,128,224,164,152,224,164,176,224,164,156,224,164,172,224,164,166,224,165,\n128,224,164,149,224,164,136,224,164,156,224,165,128,224,164,181,224,165,135,224,\n164,168,224,164,136,224,164,168,224,164,143,224,164,185,224,164,176,224,164,137,\n224,164,184,224,164,174,224,165,135,224,164,149,224,164,174,224,164,181,224,165,\n139,224,164,178,224,165,135,224,164,184,224,164,172,224,164,174,224,164,136,224,\n164,166,224,165,135,224,164,147,224,164,176,224,164,134,224,164,174,224,164,172,\n224,164,184,224,164,173,224,164,176,224,164,172,224,164,168,224,164,154,224,164,\n178,224,164,174,224,164,168,224,164,134,224,164,151,224,164,184,224,165,128,224,\n164,178,224,165,128,216,185,217,132,217,137,216,165,217,132,217,137,217,135,216,\n176,216,167,216,162,216,174,216,177,216,185,216,175,216,175,216,167,217,132,217,\n137,217,135,216,176,217,135,216,181,217,136,216,177,216,186,217,138,216,177,217,\n131,216,167,217,134,217,136,217,132,216,167,216,168,217,138,217,134,216,185,216,\n177,216,182,216,176,217,132,217,131,217,135,217,134,216,167,217,138,217,136,217,\n133,217,130,216,167,217,132,216,185,217,132,217,138,216,167,217,134,216,167,217,\n132,217,131,217,134,216,173,216,170,217,137,217,130,216,168,217,132,217,136,216,\n173,216,169,216,167,216,174,216,177,217,129,217,130,216,183,216,185,216,168,216,\n175,216,177,217,131,217,134,216,165,216,176,216,167,217,131,217,133,216,167,216,\n167,216,173,216,175,216,165,217,132,216,167,217,129,217,138,217,135,216,168,216,\n185,216,182,217,131,217,138,217,129,216,168,216,173,216,171,217,136,217,133,217,\n134,217,136,217,135,217,136,216,163,217,134,216,167,216,172,216,175,216,167,217,\n132,217,135,216,167,216,179,217,132,217,133,216,185,217,134,216,175,217,132,217,\n138,216,179,216,185,216,168,216,177,216,181,217,132,217,137,217,133,217,134,216,\n176,216,168,217,135,216,167,216,163,217,134,217,135,217,133,216,171,217,132,217,\n131,217,134,216,170,216,167,217,132,216,167,216,173,217,138,216,171,217,133,216,\n181,216,177,216,180,216,177,216,173,216,173,217,136,217,132,217,136,217,129,217,\n138,216,167,216,176,216,167,217,132,217,131,217,132,217,133,216,177,216,169,216,\n167,217,134,216,170,216,167,217,132,217,129,216,163,216,168,217,136,216,174,216,\n167,216,181,216,163,217,134,216,170,216,167,217,134,217,135,216,167,217,132,217,\n138,216,185,216,182,217,136,217,136,217,130,216,175,216,167,216,168,217,134,216,\n174,217,138,216,177,216,168,217,134,216,170,217,132,217,131,217,133,216,180,216,\n167,216,161,217,136,217,135,217,138,216,167,216,168,217,136,217,130,216,181,216,\n181,217,136,217,133,216,167,216,177,217,130,217,133,216,163,216,173,216,175,217,\n134,216,173,217,134,216,185,216,175,217,133,216,177,216,163,217,138,216,167,216,\n173,216,169,217,131,216,170,216,168,216,175,217,136,217,134,217,138,216,172,216,\n168,217,133,217,134,217,135,216,170,216,173,216,170,216,172,217,135,216,169,216,\n179,217,134,216,169,217,138,216,170,217,133,217,131,216,177,216,169,216,186,216,\n178,216,169,217,134,217,129,216,179,216,168,217,138,216,170,217,132,217,132,217,\n135,217,132,217,134,216,167,216,170,217,132,217,131,217,130,217,132,216,168,217,\n132,217,133,216,167,216,185,217,134,217,135,216,163,217,136,217,132,216,180,217,\n138,216,161,217,134,217,136,216,177,216,163,217,133,216,167,217,129,217,138,217,\n131,216,168,217,131,217,132,216,176,216,167,216,170,216,177,216,170,216,168,216,\n168,216,163,217,134,217,135,217,133,216,179,216,167,217,134,217,131,216,168,217,\n138,216,185,217,129,217,130,216,175,216,173,216,179,217,134,217,132,217,135,217,\n133,216,180,216,185,216,177,216,163,217,135,217,132,216,180,217,135,216,177,217,\n130,216,183,216,177,216,183,217,132,216,168,112,114,111,102,105,108,101,115,101,\n114,118,105,99,101,100,101,102,97,117,108,116,104,105,109,115,101,108,102,100,\n101,116,97,105,108,115,99,111,110,116,101,110,116,115,117,112,112,111,114,116,\n115,116,97,114,116,101,100,109,101,115,115,97,103,101,115,117,99,99,101,115,115,\n102,97,115,104,105,111,110,60,116,105,116,108,101,62,99,111,117,110,116,114,121,\n97,99,99,111,117,110,116,99,114,101,97,116,101,100,115,116,111,114,105,101,115,\n114,101,115,117,108,116,115,114,117,110,110,105,110,103,112,114,111,99,101,115,\n115,119,114,105,116,105,110,103,111,98,106,101,99,116,115,118,105,115,105,98,108\n,101,119,101,108,99,111,109,101,97,114,116,105,99,108,101,117,110,107,110,111,\n119,110,110,101,116,119,111,114,107,99,111,109,112,97,110,121,100,121,110,97,109\n,105,99,98,114,111,119,115,101,114,112,114,105,118,97,99,121,112,114,111,98,108,\n101,109,83,101,114,118,105,99,101,114,101,115,112,101,99,116,100,105,115,112,108\n,97,121,114,101,113,117,101,115,116,114,101,115,101,114,118,101,119,101,98,115,\n105,116,101,104,105,115,116,111,114,121,102,114,105,101,110,100,115,111,112,116,\n105,111,110,115,119,111,114,107,105,110,103,118,101,114,115,105,111,110,109,105,\n108,108,105,111,110,99,104,97,110,110,101,108,119,105,110,100,111,119,46,97,100,\n100,114,101,115,115,118,105,115,105,116,101,100,119,101,97,116,104,101,114,99,\n111,114,114,101,99,116,112,114,111,100,117,99,116,101,100,105,114,101,99,116,102\n,111,114,119,97,114,100,121,111,117,32,99,97,110,114,101,109,111,118,101,100,115\n,117,98,106,101,99,116,99,111,110,116,114,111,108,97,114,99,104,105,118,101,99,\n117,114,114,101,110,116,114,101,97,100,105,110,103,108,105,98,114,97,114,121,108\n,105,109,105,116,101,100,109,97,110,97,103,101,114,102,117,114,116,104,101,114,\n115,117,109,109,97,114,121,109,97,99,104,105,110,101,109,105,110,117,116,101,115\n,112,114,105,118,97,116,101,99,111,110,116,101,120,116,112,114,111,103,114,97,\n109,115,111,99,105,101,116,121,110,117,109,98,101,114,115,119,114,105,116,116,\n101,110,101,110,97,98,108,101,100,116,114,105,103,103,101,114,115,111,117,114,99\n,101,115,108,111,97,100,105,110,103,101,108,101,109,101,110,116,112,97,114,116,\n110,101,114,102,105,110,97,108,108,121,112,101,114,102,101,99,116,109,101,97,110\n,105,110,103,115,121,115,116,101,109,115,107,101,101,112,105,110,103,99,117,108,\n116,117,114,101,38,113,117,111,116,59,44,106,111,117,114,110,97,108,112,114,111,\n106,101,99,116,115,117,114,102,97,99,101,115,38,113,117,111,116,59,101,120,112,\n105,114,101,115,114,101,118,105,101,119,115,98,97,108,97,110,99,101,69,110,103,\n108,105,115,104,67,111,110,116,101,110,116,116,104,114,111,117,103,104,80,108,\n101,97,115,101,32,111,112,105,110,105,111,110,99,111,110,116,97,99,116,97,118,\n101,114,97,103,101,112,114,105,109,97,114,121,118,105,108,108,97,103,101,83,112,\n97,110,105,115,104,103,97,108,108,101,114,121,100,101,99,108,105,110,101,109,101\n,101,116,105,110,103,109,105,115,115,105,111,110,112,111,112,117,108,97,114,113,\n117,97,108,105,116,121,109,101,97,115,117,114,101,103,101,110,101,114,97,108,115\n,112,101,99,105,101,115,115,101,115,115,105,111,110,115,101,99,116,105,111,110,\n119,114,105,116,101,114,115,99,111,117,110,116,101,114,105,110,105,116,105,97,\n108,114,101,112,111,114,116,115,102,105,103,117,114,101,115,109,101,109,98,101,\n114,115,104,111,108,100,105,110,103,100,105,115,112,117,116,101,101,97,114,108,\n105,101,114,101,120,112,114,101,115,115,100,105,103,105,116,97,108,112,105,99,\n116,117,114,101,65,110,111,116,104,101,114,109,97,114,114,105,101,100,116,114,97\n,102,102,105,99,108,101,97,100,105,110,103,99,104,97,110,103,101,100,99,101,110,\n116,114,97,108,118,105,99,116,111,114,121,105,109,97,103,101,115,47,114,101,97,\n115,111,110,115,115,116,117,100,105,101,115,102,101,97,116,117,114,101,108,105,\n115,116,105,110,103,109,117,115,116,32,98,101,115,99,104,111,111,108,115,86,101,\n114,115,105,111,110,117,115,117,97,108,108,121,101,112,105,115,111,100,101,112,\n108,97,121,105,110,103,103,114,111,119,105,110,103,111,98,118,105,111,117,115,\n111,118,101,114,108,97,121,112,114,101,115,101,110,116,97,99,116,105,111,110,115\n,60,47,117,108,62,13,10,119,114,97,112,112,101,114,97,108,114,101,97,100,121,99,\n101,114,116,97,105,110,114,101,97,108,105,116,121,115,116,111,114,97,103,101,97,\n110,111,116,104,101,114,100,101,115,107,116,111,112,111,102,102,101,114,101,100,\n112,97,116,116,101,114,110,117,110,117,115,117,97,108,68,105,103,105,116,97,108,\n99,97,112,105,116,97,108,87,101,98,115,105,116,101,102,97,105,108,117,114,101,99\n,111,110,110,101,99,116,114,101,100,117,99,101,100,65,110,100,114,111,105,100,\n100,101,99,97,100,101,115,114,101,103,117,108,97,114,32,38,97,109,112,59,32,97,\n110,105,109,97,108,115,114,101,108,101,97,115,101,65,117,116,111,109,97,116,103,\n101,116,116,105,110,103,109,101,116,104,111,100,115,110,111,116,104,105,110,103,\n80,111,112,117,108,97,114,99,97,112,116,105,111,110,108,101,116,116,101,114,115,\n99,97,112,116,117,114,101,115,99,105,101,110,99,101,108,105,99,101,110,115,101,\n99,104,97,110,103,101,115,69,110,103,108,97,110,100,61,49,38,97,109,112,59,72,\n105,115,116,111,114,121,32,61,32,110,101,119,32,67,101,110,116,114,97,108,117,\n112,100,97,116,101,100,83,112,101,99,105,97,108,78,101,116,119,111,114,107,114,\n101,113,117,105,114,101,99,111,109,109,101,110,116,119,97,114,110,105,110,103,67\n,111,108,108,101,103,101,116,111,111,108,98,97,114,114,101,109,97,105,110,115,98\n,101,99,97,117,115,101,101,108,101,99,116,101,100,68,101,117,116,115,99,104,102,\n105,110,97,110,99,101,119,111,114,107,101,114,115,113,117,105,99,107,108,121,98,\n101,116,119,101,101,110,101,120,97,99,116,108,121,115,101,116,116,105,110,103,\n100,105,115,101,97,115,101,83,111,99,105,101,116,121,119,101,97,112,111,110,115,\n101,120,104,105,98,105,116,38,108,116,59,33,45,45,67,111,110,116,114,111,108,99,\n108,97,115,115,101,115,99,111,118,101,114,101,100,111,117,116,108,105,110,101,97\n,116,116,97,99,107,115,100,101,118,105,99,101,115,40,119,105,110,100,111,119,112\n,117,114,112,111,115,101,116,105,116,108,101,61,34,77,111,98,105,108,101,32,107,\n105,108,108,105,110,103,115,104,111,119,105,110,103,73,116,97,108,105,97,110,100\n,114,111,112,112,101,100,104,101,97,118,105,108,121,101,102,102,101,99,116,115,\n45,49,39,93,41,59,10,99,111,110,102,105,114,109,67,117,114,114,101,110,116,97,\n100,118,97,110,99,101,115,104,97,114,105,110,103,111,112,101,110,105,110,103,100\n,114,97,119,105,110,103,98,105,108,108,105,111,110,111,114,100,101,114,101,100,\n71,101,114,109,97,110,121,114,101,108,97,116,101,100,60,47,102,111,114,109,62,\n105,110,99,108,117,100,101,119,104,101,116,104,101,114,100,101,102,105,110,101,\n100,83,99,105,101,110,99,101,99,97,116,97,108,111,103,65,114,116,105,99,108,101,\n98,117,116,116,111,110,115,108,97,114,103,101,115,116,117,110,105,102,111,114,\n109,106,111,117,114,110,101,121,115,105,100,101,98,97,114,67,104,105,99,97,103,\n111,104,111,108,105,100,97,121,71,101,110,101,114,97,108,112,97,115,115,97,103,\n101,44,38,113,117,111,116,59,97,110,105,109,97,116,101,102,101,101,108,105,110,\n103,97,114,114,105,118,101,100,112,97,115,115,105,110,103,110,97,116,117,114,97,\n108,114,111,117,103,104,108,121,46,10,10,84,104,101,32,98,117,116,32,110,111,116\n,100,101,110,115,105,116,121,66,114,105,116,97,105,110,67,104,105,110,101,115,\n101,108,97,99,107,32,111,102,116,114,105,98,117,116,101,73,114,101,108,97,110,\n100,34,32,100,97,116,97,45,102,97,99,116,111,114,115,114,101,99,101,105,118,101,\n116,104,97,116,32,105,115,76,105,98,114,97,114,121,104,117,115,98,97,110,100,105\n,110,32,102,97,99,116,97,102,102,97,105,114,115,67,104,97,114,108,101,115,114,97\n,100,105,99,97,108,98,114,111,117,103,104,116,102,105,110,100,105,110,103,108,97\n,110,100,105,110,103,58,108,97,110,103,61,34,114,101,116,117,114,110,32,108,101,\n97,100,101,114,115,112,108,97,110,110,101,100,112,114,101,109,105,117,109,112,97\n,99,107,97,103,101,65,109,101,114,105,99,97,69,100,105,116,105,111,110,93,38,113\n,117,111,116,59,77,101,115,115,97,103,101,110,101,101,100,32,116,111,118,97,108,\n117,101,61,34,99,111,109,112,108,101,120,108,111,111,107,105,110,103,115,116,97,\n116,105,111,110,98,101,108,105,101,118,101,115,109,97,108,108,101,114,45,109,111\n,98,105,108,101,114,101,99,111,114,100,115,119,97,110,116,32,116,111,107,105,110\n,100,32,111,102,70,105,114,101,102,111,120,121,111,117,32,97,114,101,115,105,109\n,105,108,97,114,115,116,117,100,105,101,100,109,97,120,105,109,117,109,104,101,\n97,100,105,110,103,114,97,112,105,100,108,121,99,108,105,109,97,116,101,107,105,\n110,103,100,111,109,101,109,101,114,103,101,100,97,109,111,117,110,116,115,102,\n111,117,110,100,101,100,112,105,111,110,101,101,114,102,111,114,109,117,108,97,\n100,121,110,97,115,116,121,104,111,119,32,116,111,32,83,117,112,112,111,114,116,\n114,101,118,101,110,117,101,101,99,111,110,111,109,121,82,101,115,117,108,116,\n115,98,114,111,116,104,101,114,115,111,108,100,105,101,114,108,97,114,103,101,\n108,121,99,97,108,108,105,110,103,46,38,113,117,111,116,59,65,99,99,111,117,110,\n116,69,100,119,97,114,100,32,115,101,103,109,101,110,116,82,111,98,101,114,116,\n32,101,102,102,111,114,116,115,80,97,99,105,102,105,99,108,101,97,114,110,101,\n100,117,112,32,119,105,116,104,104,101,105,103,104,116,58,119,101,32,104,97,118,\n101,65,110,103,101,108,101,115,110,97,116,105,111,110,115,95,115,101,97,114,99,\n104,97,112,112,108,105,101,100,97,99,113,117,105,114,101,109,97,115,115,105,118,\n101,103,114,97,110,116,101,100,58,32,102,97,108,115,101,116,114,101,97,116,101,\n100,98,105,103,103,101,115,116,98,101,110,101,102,105,116,100,114,105,118,105,\n110,103,83,116,117,100,105,101,115,109,105,110,105,109,117,109,112,101,114,104,\n97,112,115,109,111,114,110,105,110,103,115,101,108,108,105,110,103,105,115,32,\n117,115,101,100,114,101,118,101,114,115,101,118,97,114,105,97,110,116,32,114,111\n,108,101,61,34,109,105,115,115,105,110,103,97,99,104,105,101,118,101,112,114,111\n,109,111,116,101,115,116,117,100,101,110,116,115,111,109,101,111,110,101,101,120\n,116,114,101,109,101,114,101,115,116,111,114,101,98,111,116,116,111,109,58,101,\n118,111,108,118,101,100,97,108,108,32,116,104,101,115,105,116,101,109,97,112,101\n,110,103,108,105,115,104,119,97,121,32,116,111,32,32,65,117,103,117,115,116,115,\n121,109,98,111,108,115,67,111,109,112,97,110,121,109,97,116,116,101,114,115,109,\n117,115,105,99,97,108,97,103,97,105,110,115,116,115,101,114,118,105,110,103,125,\n41,40,41,59,13,10,112,97,121,109,101,110,116,116,114,111,117,98,108,101,99,111,\n110,99,101,112,116,99,111,109,112,97,114,101,112,97,114,101,110,116,115,112,108,\n97,121,101,114,115,114,101,103,105,111,110,115,109,111,110,105,116,111,114,32,39\n,39,84,104,101,32,119,105,110,110,105,110,103,101,120,112,108,111,114,101,97,100\n,97,112,116,101,100,71,97,108,108,101,114,121,112,114,111,100,117,99,101,97,98,\n105,108,105,116,121,101,110,104,97,110,99,101,99,97,114,101,101,114,115,41,46,32\n,84,104,101,32,99,111,108,108,101,99,116,83,101,97,114,99,104,32,97,110,99,105,\n101,110,116,101,120,105,115,116,101,100,102,111,111,116,101,114,32,104,97,110,\n100,108,101,114,112,114,105,110,116,101,100,99,111,110,115,111,108,101,69,97,115\n,116,101,114,110,101,120,112,111,114,116,115,119,105,110,100,111,119,115,67,104,\n97,110,110,101,108,105,108,108,101,103,97,108,110,101,117,116,114,97,108,115,117\n,103,103,101,115,116,95,104,101,97,100,101,114,115,105,103,110,105,110,103,46,\n104,116,109,108,34,62,115,101,116,116,108,101,100,119,101,115,116,101,114,110,99\n,97,117,115,105,110,103,45,119,101,98,107,105,116,99,108,97,105,109,101,100,74,\n117,115,116,105,99,101,99,104,97,112,116,101,114,118,105,99,116,105,109,115,84,\n104,111,109,97,115,32,109,111,122,105,108,108,97,112,114,111,109,105,115,101,112\n,97,114,116,105,101,115,101,100,105,116,105,111,110,111,117,116,115,105,100,101,\n58,102,97,108,115,101,44,104,117,110,100,114,101,100,79,108,121,109,112,105,99,\n95,98,117,116,116,111,110,97,117,116,104,111,114,115,114,101,97,99,104,101,100,\n99,104,114,111,110,105,99,100,101,109,97,110,100,115,115,101,99,111,110,100,115,\n112,114,111,116,101,99,116,97,100,111,112,116,101,100,112,114,101,112,97,114,101\n,110,101,105,116,104,101,114,103,114,101,97,116,108,121,103,114,101,97,116,101,\n114,111,118,101,114,97,108,108,105,109,112,114,111,118,101,99,111,109,109,97,110\n,100,115,112,101,99,105,97,108,115,101,97,114,99,104,46,119,111,114,115,104,105,\n112,102,117,110,100,105,110,103,116,104,111,117,103,104,116,104,105,103,104,101,\n115,116,105,110,115,116,101,97,100,117,116,105,108,105,116,121,113,117,97,114,\n116,101,114,67,117,108,116,117,114,101,116,101,115,116,105,110,103,99,108,101,97\n,114,108,121,101,120,112,111,115,101,100,66,114,111,119,115,101,114,108,105,98,\n101,114,97,108,125,32,99,97,116,99,104,80,114,111,106,101,99,116,101,120,97,109,\n112,108,101,104,105,100,101,40,41,59,70,108,111,114,105,100,97,97,110,115,119,\n101,114,115,97,108,108,111,119,101,100,69,109,112,101,114,111,114,100,101,102,\n101,110,115,101,115,101,114,105,111,117,115,102,114,101,101,100,111,109,83,101,\n118,101,114,97,108,45,98,117,116,116,111,110,70,117,114,116,104,101,114,111,117,\n116,32,111,102,32,33,61,32,110,117,108,108,116,114,97,105,110,101,100,68,101,110\n,109,97,114,107,118,111,105,100,40,48,41,47,97,108,108,46,106,115,112,114,101,\n118,101,110,116,82,101,113,117,101,115,116,83,116,101,112,104,101,110,10,10,87,\n104,101,110,32,111,98,115,101,114,118,101,60,47,104,50,62,13,10,77,111,100,101,\n114,110,32,112,114,111,118,105,100,101,34,32,97,108,116,61,34,98,111,114,100,101\n,114,115,46,10,10,70,111,114,32,10,10,77,97,110,121,32,97,114,116,105,115,116,\n115,112,111,119,101,114,101,100,112,101,114,102,111,114,109,102,105,99,116,105,\n111,110,116,121,112,101,32,111,102,109,101,100,105,99,97,108,116,105,99,107,101,\n116,115,111,112,112,111,115,101,100,67,111,117,110,99,105,108,119,105,116,110,\n101,115,115,106,117,115,116,105,99,101,71,101,111,114,103,101,32,66,101,108,103,\n105,117,109,46,46,46,60,47,97,62,116,119,105,116,116,101,114,110,111,116,97,98,\n108,121,119,97,105,116,105,110,103,119,97,114,102,97,114,101,32,79,116,104,101,\n114,32,114,97,110,107,105,110,103,112,104,114,97,115,101,115,109,101,110,116,105\n,111,110,115,117,114,118,105,118,101,115,99,104,111,108,97,114,60,47,112,62,13,\n10,32,67,111,117,110,116,114,121,105,103,110,111,114,101,100,108,111,115,115,32,\n111,102,106,117,115,116,32,97,115,71,101,111,114,103,105,97,115,116,114,97,110,\n103,101,60,104,101,97,100,62,60,115,116,111,112,112,101,100,49,39,93,41,59,13,10\n,105,115,108,97,110,100,115,110,111,116,97,98,108,101,98,111,114,100,101,114,58,\n108,105,115,116,32,111,102,99,97,114,114,105,101,100,49,48,48,44,48,48,48,60,47,\n104,51,62,10,32,115,101,118,101,114,97,108,98,101,99,111,109,101,115,115,101,108\n,101,99,116,32,119,101,100,100,105,110,103,48,48,46,104,116,109,108,109,111,110,\n97,114,99,104,111,102,102,32,116,104,101,116,101,97,99,104,101,114,104,105,103,\n104,108,121,32,98,105,111,108,111,103,121,108,105,102,101,32,111,102,111,114,32,\n101,118,101,110,114,105,115,101,32,111,102,38,114,97,113,117,111,59,112,108,117,\n115,111,110,101,104,117,110,116,105,110,103,40,116,104,111,117,103,104,68,111,\n117,103,108,97,115,106,111,105,110,105,110,103,99,105,114,99,108,101,115,70,111,\n114,32,116,104,101,65,110,99,105,101,110,116,86,105,101,116,110,97,109,118,101,\n104,105,99,108,101,115,117,99,104,32,97,115,99,114,121,115,116,97,108,118,97,108\n,117,101,32,61,87,105,110,100,111,119,115,101,110,106,111,121,101,100,97,32,115,\n109,97,108,108,97,115,115,117,109,101,100,60,97,32,105,100,61,34,102,111,114,101\n,105,103,110,32,65,108,108,32,114,105,104,111,119,32,116,104,101,68,105,115,112,\n108,97,121,114,101,116,105,114,101,100,104,111,119,101,118,101,114,104,105,100,\n100,101,110,59,98,97,116,116,108,101,115,115,101,101,107,105,110,103,99,97,98,\n105,110,101,116,119,97,115,32,110,111,116,108,111,111,107,32,97,116,99,111,110,\n100,117,99,116,103,101,116,32,116,104,101,74,97,110,117,97,114,121,104,97,112,\n112,101,110,115,116,117,114,110,105,110,103,97,58,104,111,118,101,114,79,110,108\n,105,110,101,32,70,114,101,110,99,104,32,108,97,99,107,105,110,103,116,121,112,\n105,99,97,108,101,120,116,114,97,99,116,101,110,101,109,105,101,115,101,118,101,\n110,32,105,102,103,101,110,101,114,97,116,100,101,99,105,100,101,100,97,114,101,\n32,110,111,116,47,115,101,97,114,99,104,98,101,108,105,101,102,115,45,105,109,97\n,103,101,58,108,111,99,97,116,101,100,115,116,97,116,105,99,46,108,111,103,105,\n110,34,62,99,111,110,118,101,114,116,118,105,111,108,101,110,116,101,110,116,101\n,114,101,100,102,105,114,115,116,34,62,99,105,114,99,117,105,116,70,105,110,108,\n97,110,100,99,104,101,109,105,115,116,115,104,101,32,119,97,115,49,48,112,120,59\n,34,62,97,115,32,115,117,99,104,100,105,118,105,100,101,100,60,47,115,112,97,110\n,62,119,105,108,108,32,98,101,108,105,110,101,32,111,102,97,32,103,114,101,97,\n116,109,121,115,116,101,114,121,47,105,110,100,101,120,46,102,97,108,108,105,110\n,103,100,117,101,32,116,111,32,114,97,105,108,119,97,121,99,111,108,108,101,103,\n101,109,111,110,115,116,101,114,100,101,115,99,101,110,116,105,116,32,119,105,\n116,104,110,117,99,108,101,97,114,74,101,119,105,115,104,32,112,114,111,116,101,\n115,116,66,114,105,116,105,115,104,102,108,111,119,101,114,115,112,114,101,100,\n105,99,116,114,101,102,111,114,109,115,98,117,116,116,111,110,32,119,104,111,32,\n119,97,115,108,101,99,116,117,114,101,105,110,115,116,97,110,116,115,117,105,99,\n105,100,101,103,101,110,101,114,105,99,112,101,114,105,111,100,115,109,97,114,\n107,101,116,115,83,111,99,105,97,108,32,102,105,115,104,105,110,103,99,111,109,\n98,105,110,101,103,114,97,112,104,105,99,119,105,110,110,101,114,115,60,98,114,\n32,47,62,60,98,121,32,116,104,101,32,78,97,116,117,114,97,108,80,114,105,118,97,\n99,121,99,111,111,107,105,101,115,111,117,116,99,111,109,101,114,101,115,111,108\n,118,101,83,119,101,100,105,115,104,98,114,105,101,102,108,121,80,101,114,115,\n105,97,110,115,111,32,109,117,99,104,67,101,110,116,117,114,121,100,101,112,105,\n99,116,115,99,111,108,117,109,110,115,104,111,117,115,105,110,103,115,99,114,105\n,112,116,115,110,101,120,116,32,116,111,98,101,97,114,105,110,103,109,97,112,112\n,105,110,103,114,101,118,105,115,101,100,106,81,117,101,114,121,40,45,119,105,\n100,116,104,58,116,105,116,108,101,34,62,116,111,111,108,116,105,112,83,101,99,\n116,105,111,110,100,101,115,105,103,110,115,84,117,114,107,105,115,104,121,111,\n117,110,103,101,114,46,109,97,116,99,104,40,125,41,40,41,59,10,10,98,117,114,110\n,105,110,103,111,112,101,114,97,116,101,100,101,103,114,101,101,115,115,111,117,\n114,99,101,61,82,105,99,104,97,114,100,99,108,111,115,101,108,121,112,108,97,115\n,116,105,99,101,110,116,114,105,101,115,60,47,116,114,62,13,10,99,111,108,111,\n114,58,35,117,108,32,105,100,61,34,112,111,115,115,101,115,115,114,111,108,108,\n105,110,103,112,104,121,115,105,99,115,102,97,105,108,105,110,103,101,120,101,99\n,117,116,101,99,111,110,116,101,115,116,108,105,110,107,32,116,111,68,101,102,97\n,117,108,116,60,98,114,32,47,62,10,58,32,116,114,117,101,44,99,104,97,114,116,\n101,114,116,111,117,114,105,115,109,99,108,97,115,115,105,99,112,114,111,99,101,\n101,100,101,120,112,108,97,105,110,60,47,104,49,62,13,10,111,110,108,105,110,101\n,46,63,120,109,108,32,118,101,104,101,108,112,105,110,103,100,105,97,109,111,110\n,100,117,115,101,32,116,104,101,97,105,114,108,105,110,101,101,110,100,32,45,45,\n62,41,46,97,116,116,114,40,114,101,97,100,101,114,115,104,111,115,116,105,110,\n103,35,102,102,102,102,102,102,114,101,97,108,105,122,101,86,105,110,99,101,110,\n116,115,105,103,110,97,108,115,32,115,114,99,61,34,47,80,114,111,100,117,99,116,\n100,101,115,112,105,116,101,100,105,118,101,114,115,101,116,101,108,108,105,110,\n103,80,117,98,108,105,99,32,104,101,108,100,32,105,110,74,111,115,101,112,104,32\n,116,104,101,97,116,114,101,97,102,102,101,99,116,115,60,115,116,121,108,101,62,\n97,32,108,97,114,103,101,100,111,101,115,110,39,116,108,97,116,101,114,44,32,69,\n108,101,109,101,110,116,102,97,118,105,99,111,110,99,114,101,97,116,111,114,72,\n117,110,103,97,114,121,65,105,114,112,111,114,116,115,101,101,32,116,104,101,115\n,111,32,116,104,97,116,77,105,99,104,97,101,108,83,121,115,116,101,109,115,80,\n114,111,103,114,97,109,115,44,32,97,110,100,32,32,119,105,100,116,104,61,101,38,\n113,117,111,116,59,116,114,97,100,105,110,103,108,101,102,116,34,62,10,112,101,\n114,115,111,110,115,71,111,108,100,101,110,32,65,102,102,97,105,114,115,103,114,\n97,109,109,97,114,102,111,114,109,105,110,103,100,101,115,116,114,111,121,105,\n100,101,97,32,111,102,99,97,115,101,32,111,102,111,108,100,101,115,116,32,116,\n104,105,115,32,105,115,46,115,114,99,32,61,32,99,97,114,116,111,111,110,114,101,\n103,105,115,116,114,67,111,109,109,111,110,115,77,117,115,108,105,109,115,87,104\n,97,116,32,105,115,105,110,32,109,97,110,121,109,97,114,107,105,110,103,114,101,\n118,101,97,108,115,73,110,100,101,101,100,44,101,113,117,97,108,108,121,47,115,\n104,111,119,95,97,111,117,116,100,111,111,114,101,115,99,97,112,101,40,65,117,\n115,116,114,105,97,103,101,110,101,116,105,99,115,121,115,116,101,109,44,73,110,\n32,116,104,101,32,115,105,116,116,105,110,103,72,101,32,97,108,115,111,73,115,\n108,97,110,100,115,65,99,97,100,101,109,121,10,9,9,60,33,45,45,68,97,110,105,101\n,108,32,98,105,110,100,105,110,103,98,108,111,99,107,34,62,105,109,112,111,115,\n101,100,117,116,105,108,105,122,101,65,98,114,97,104,97,109,40,101,120,99,101,\n112,116,123,119,105,100,116,104,58,112,117,116,116,105,110,103,41,46,104,116,109\n,108,40,124,124,32,91,93,59,10,68,65,84,65,91,32,42,107,105,116,99,104,101,110,\n109,111,117,110,116,101,100,97,99,116,117,97,108,32,100,105,97,108,101,99,116,\n109,97,105,110,108,121,32,95,98,108,97,110,107,39,105,110,115,116,97,108,108,101\n,120,112,101,114,116,115,105,102,40,116,121,112,101,73,116,32,97,108,115,111,38,\n99,111,112,121,59,32,34,62,84,101,114,109,115,98,111,114,110,32,105,110,79,112,\n116,105,111,110,115,101,97,115,116,101,114,110,116,97,108,107,105,110,103,99,111\n,110,99,101,114,110,103,97,105,110,101,100,32,111,110,103,111,105,110,103,106,\n117,115,116,105,102,121,99,114,105,116,105,99,115,102,97,99,116,111,114,121,105,\n116,115,32,111,119,110,97,115,115,97,117,108,116,105,110,118,105,116,101,100,108\n,97,115,116,105,110,103,104,105,115,32,111,119,110,104,114,101,102,61,34,47,34,\n32,114,101,108,61,34,100,101,118,101,108,111,112,99,111,110,99,101,114,116,100,\n105,97,103,114,97,109,100,111,108,108,97,114,115,99,108,117,115,116,101,114,112,\n104,112,63,105,100,61,97,108,99,111,104,111,108,41,59,125,41,40,41,59,117,115,\n105,110,103,32,97,62,60,115,112,97,110,62,118,101,115,115,101,108,115,114,101,\n118,105,118,97,108,65,100,100,114,101,115,115,97,109,97,116,101,117,114,97,110,\n100,114,111,105,100,97,108,108,101,103,101,100,105,108,108,110,101,115,115,119,\n97,108,107,105,110,103,99,101,110,116,101,114,115,113,117,97,108,105,102,121,109\n,97,116,99,104,101,115,117,110,105,102,105,101,100,101,120,116,105,110,99,116,68\n,101,102,101,110,115,101,100,105,101,100,32,105,110,10,9,60,33,45,45,32,99,117,\n115,116,111,109,115,108,105,110,107,105,110,103,76,105,116,116,108,101,32,66,111\n,111,107,32,111,102,101,118,101,110,105,110,103,109,105,110,46,106,115,63,97,114\n,101,32,116,104,101,107,111,110,116,97,107,116,116,111,100,97,121,39,115,46,104,\n116,109,108,34,32,116,97,114,103,101,116,61,119,101,97,114,105,110,103,65,108,\n108,32,82,105,103,59,10,125,41,40,41,59,114,97,105,115,105,110,103,32,65,108,115\n,111,44,32,99,114,117,99,105,97,108,97,98,111,117,116,34,62,100,101,99,108,97,\n114,101,45,45,62,10,60,115,99,102,105,114,101,102,111,120,97,115,32,109,117,99,\n104,97,112,112,108,105,101,115,105,110,100,101,120,44,32,115,44,32,98,117,116,32\n,116,121,112,101,32,61,32,10,13,10,60,33,45,45,116,111,119,97,114,100,115,82,101\n,99,111,114,100,115,80,114,105,118,97,116,101,70,111,114,101,105,103,110,80,114,\n101,109,105,101,114,99,104,111,105,99,101,115,86,105,114,116,117,97,108,114,101,\n116,117,114,110,115,67,111,109,109,101,110,116,80,111,119,101,114,101,100,105,\n110,108,105,110,101,59,112,111,118,101,114,116,121,99,104,97,109,98,101,114,76,\n105,118,105,110,103,32,118,111,108,117,109,101,115,65,110,116,104,111,110,121,\n108,111,103,105,110,34,32,82,101,108,97,116,101,100,69,99,111,110,111,109,121,\n114,101,97,99,104,101,115,99,117,116,116,105,110,103,103,114,97,118,105,116,121,\n108,105,102,101,32,105,110,67,104,97,112,116,101,114,45,115,104,97,100,111,119,\n78,111,116,97,98,108,101,60,47,116,100,62,13,10,32,114,101,116,117,114,110,115,\n116,97,100,105,117,109,119,105,100,103,101,116,115,118,97,114,121,105,110,103,\n116,114,97,118,101,108,115,104,101,108,100,32,98,121,119,104,111,32,97,114,101,\n119,111,114,107,32,105,110,102,97,99,117,108,116,121,97,110,103,117,108,97,114,\n119,104,111,32,104,97,100,97,105,114,112,111,114,116,116,111,119,110,32,111,102,\n10,10,83,111,109,101,32,39,99,108,105,99,107,39,99,104,97,114,103,101,115,107,\n101,121,119,111,114,100,105,116,32,119,105,108,108,99,105,116,121,32,111,102,40,\n116,104,105,115,41,59,65,110,100,114,101,119,32,117,110,105,113,117,101,32,99,\n104,101,99,107,101,100,111,114,32,109,111,114,101,51,48,48,112,120,59,32,114,101\n,116,117,114,110,59,114,115,105,111,110,61,34,112,108,117,103,105,110,115,119,\n105,116,104,105,110,32,104,101,114,115,101,108,102,83,116,97,116,105,111,110,70,\n101,100,101,114,97,108,118,101,110,116,117,114,101,112,117,98,108,105,115,104,\n115,101,110,116,32,116,111,116,101,110,115,105,111,110,97,99,116,114,101,115,115\n,99,111,109,101,32,116,111,102,105,110,103,101,114,115,68,117,107,101,32,111,102\n,112,101,111,112,108,101,44,101,120,112,108,111,105,116,119,104,97,116,32,105,\n115,104,97,114,109,111,110,121,97,32,109,97,106,111,114,34,58,34,104,116,116,112\n,105,110,32,104,105,115,32,109,101,110,117,34,62,10,109,111,110,116,104,108,121,\n111,102,102,105,99,101,114,99,111,117,110,99,105,108,103,97,105,110,105,110,103,\n101,118,101,110,32,105,110,83,117,109,109,97,114,121,100,97,116,101,32,111,102,\n108,111,121,97,108,116,121,102,105,116,110,101,115,115,97,110,100,32,119,97,115,\n101,109,112,101,114,111,114,115,117,112,114,101,109,101,83,101,99,111,110,100,32\n,104,101,97,114,105,110,103,82,117,115,115,105,97,110,108,111,110,103,101,115,\n116,65,108,98,101,114,116,97,108,97,116,101,114,97,108,115,101,116,32,111,102,32\n,115,109,97,108,108,34,62,46,97,112,112,101,110,100,100,111,32,119,105,116,104,\n102,101,100,101,114,97,108,98,97,110,107,32,111,102,98,101,110,101,97,116,104,68\n,101,115,112,105,116,101,67,97,112,105,116,97,108,103,114,111,117,110,100,115,41\n,44,32,97,110,100,32,112,101,114,99,101,110,116,105,116,32,102,114,111,109,99,\n108,111,115,105,110,103,99,111,110,116,97,105,110,73,110,115,116,101,97,100,102,\n105,102,116,101,101,110,97,115,32,119,101,108,108,46,121,97,104,111,111,46,114,\n101,115,112,111,110,100,102,105,103,104,116,101,114,111,98,115,99,117,114,101,\n114,101,102,108,101,99,116,111,114,103,97,110,105,99,61,32,77,97,116,104,46,101,\n100,105,116,105,110,103,111,110,108,105,110,101,32,112,97,100,100,105,110,103,97\n,32,119,104,111,108,101,111,110,101,114,114,111,114,121,101,97,114,32,111,102,\n101,110,100,32,111,102,32,98,97,114,114,105,101,114,119,104,101,110,32,105,116,\n104,101,97,100,101,114,32,104,111,109,101,32,111,102,114,101,115,117,109,101,100\n,114,101,110,97,109,101,100,115,116,114,111,110,103,62,104,101,97,116,105,110,\n103,114,101,116,97,105,110,115,99,108,111,117,100,102,114,119,97,121,32,111,102,\n32,77,97,114,99,104,32,49,107,110,111,119,105,110,103,105,110,32,112,97,114,116,\n66,101,116,119,101,101,110,108,101,115,115,111,110,115,99,108,111,115,101,115,\n116,118,105,114,116,117,97,108,108,105,110,107,115,34,62,99,114,111,115,115,101,\n100,69,78,68,32,45,45,62,102,97,109,111,117,115,32,97,119,97,114,100,101,100,76,\n105,99,101,110,115,101,72,101,97,108,116,104,32,102,97,105,114,108,121,32,119,\n101,97,108,116,104,121,109,105,110,105,109,97,108,65,102,114,105,99,97,110,99,\n111,109,112,101,116,101,108,97,98,101,108,34,62,115,105,110,103,105,110,103,102,\n97,114,109,101,114,115,66,114,97,115,105,108,41,100,105,115,99,117,115,115,114,\n101,112,108,97,99,101,71,114,101,103,111,114,121,102,111,110,116,32,99,111,112,\n117,114,115,117,101,100,97,112,112,101,97,114,115,109,97,107,101,32,117,112,114,\n111,117,110,100,101,100,98,111,116,104,32,111,102,98,108,111,99,107,101,100,115,\n97,119,32,116,104,101,111,102,102,105,99,101,115,99,111,108,111,117,114,115,105,\n102,40,100,111,99,117,119,104,101,110,32,104,101,101,110,102,111,114,99,101,112,\n117,115,104,40,102,117,65,117,103,117,115,116,32,85,84,70,45,56,34,62,70,97,110,\n116,97,115,121,105,110,32,109,111,115,116,105,110,106,117,114,101,100,85,115,117\n,97,108,108,121,102,97,114,109,105,110,103,99,108,111,115,117,114,101,111,98,106\n,101,99,116,32,100,101,102,101,110,99,101,117,115,101,32,111,102,32,77,101,100,\n105,99,97,108,60,98,111,100,121,62,10,101,118,105,100,101,110,116,98,101,32,117,\n115,101,100,107,101,121,67,111,100,101,115,105,120,116,101,101,110,73,115,108,97\n,109,105,99,35,48,48,48,48,48,48,101,110,116,105,114,101,32,119,105,100,101,108,\n121,32,97,99,116,105,118,101,32,40,116,121,112,101,111,102,111,110,101,32,99,97,\n110,99,111,108,111,114,32,61,115,112,101,97,107,101,114,101,120,116,101,110,100,\n115,80,104,121,115,105,99,115,116,101,114,114,97,105,110,60,116,98,111,100,121,\n62,102,117,110,101,114,97,108,118,105,101,119,105,110,103,109,105,100,100,108,\n101,32,99,114,105,99,107,101,116,112,114,111,112,104,101,116,115,104,105,102,116\n,101,100,100,111,99,116,111,114,115,82,117,115,115,101,108,108,32,116,97,114,103\n,101,116,99,111,109,112,97,99,116,97,108,103,101,98,114,97,115,111,99,105,97,108\n,45,98,117,108,107,32,111,102,109,97,110,32,97,110,100,60,47,116,100,62,10,32,\n104,101,32,108,101,102,116,41,46,118,97,108,40,41,102,97,108,115,101,41,59,108,\n111,103,105,99,97,108,98,97,110,107,105,110,103,104,111,109,101,32,116,111,110,\n97,109,105,110,103,32,65,114,105,122,111,110,97,99,114,101,100,105,116,115,41,59\n,10,125,41,59,10,102,111,117,110,100,101,114,105,110,32,116,117,114,110,67,111,\n108,108,105,110,115,98,101,102,111,114,101,32,66,117,116,32,116,104,101,99,104,\n97,114,103,101,100,84,105,116,108,101,34,62,67,97,112,116,97,105,110,115,112,101\n,108,108,101,100,103,111,100,100,101,115,115,84,97,103,32,45,45,62,65,100,100,\n105,110,103,58,98,117,116,32,119,97,115,82,101,99,101,110,116,32,112,97,116,105,\n101,110,116,98,97,99,107,32,105,110,61,102,97,108,115,101,38,76,105,110,99,111,\n108,110,119,101,32,107,110,111,119,67,111,117,110,116,101,114,74,117,100,97,105,\n115,109,115,99,114,105,112,116,32,97,108,116,101,114,101,100,39,93,41,59,10,32,\n32,104,97,115,32,116,104,101,117,110,99,108,101,97,114,69,118,101,110,116,39,44,\n98,111,116,104,32,105,110,110,111,116,32,97,108,108,10,10,60,33,45,45,32,112,108\n,97,99,105,110,103,104,97,114,100,32,116,111,32,99,101,110,116,101,114,115,111,\n114,116,32,111,102,99,108,105,101,110,116,115,115,116,114,101,101,116,115,66,101\n,114,110,97,114,100,97,115,115,101,114,116,115,116,101,110,100,32,116,111,102,97\n,110,116,97,115,121,100,111,119,110,32,105,110,104,97,114,98,111,117,114,70,114,\n101,101,100,111,109,106,101,119,101,108,114,121,47,97,98,111,117,116,46,46,115,\n101,97,114,99,104,108,101,103,101,110,100,115,105,115,32,109,97,100,101,109,111,\n100,101,114,110,32,111,110,108,121,32,111,110,111,110,108,121,32,116,111,105,109\n,97,103,101,34,32,108,105,110,101,97,114,32,112,97,105,110,116,101,114,97,110,\n100,32,110,111,116,114,97,114,101,108,121,32,97,99,114,111,110,121,109,100,101,\n108,105,118,101,114,115,104,111,114,116,101,114,48,48,38,97,109,112,59,97,115,32\n,109,97,110,121,119,105,100,116,104,61,34,47,42,32,60,33,91,67,116,105,116,108,\n101,32,61,111,102,32,116,104,101,32,108,111,119,101,115,116,32,112,105,99,107,\n101,100,32,101,115,99,97,112,101,100,117,115,101,115,32,111,102,112,101,111,112,\n108,101,115,32,80,117,98,108,105,99,77,97,116,116,104,101,119,116,97,99,116,105,\n99,115,100,97,109,97,103,101,100,119,97,121,32,102,111,114,108,97,119,115,32,111\n,102,101,97,115,121,32,116,111,32,119,105,110,100,111,119,115,116,114,111,110,\n103,32,32,115,105,109,112,108,101,125,99,97,116,99,104,40,115,101,118,101,110,\n116,104,105,110,102,111,98,111,120,119,101,110,116,32,116,111,112,97,105,110,116\n,101,100,99,105,116,105,122,101,110,73,32,100,111,110,39,116,114,101,116,114,101\n,97,116,46,32,83,111,109,101,32,119,119,46,34,41,59,10,98,111,109,98,105,110,103\n,109,97,105,108,116,111,58,109,97,100,101,32,105,110,46,32,77,97,110,121,32,99,\n97,114,114,105,101,115,124,124,123,125,59,119,105,119,111,114,107,32,111,102,115\n,121,110,111,110,121,109,100,101,102,101,97,116,115,102,97,118,111,114,101,100,\n111,112,116,105,99,97,108,112,97,103,101,84,114,97,117,110,108,101,115,115,32,\n115,101,110,100,105,110,103,108,101,102,116,34,62,60,99,111,109,83,99,111,114,65\n,108,108,32,116,104,101,106,81,117,101,114,121,46,116,111,117,114,105,115,116,67\n,108,97,115,115,105,99,102,97,108,115,101,34,32,87,105,108,104,101,108,109,115,\n117,98,117,114,98,115,103,101,110,117,105,110,101,98,105,115,104,111,112,115,46,\n115,112,108,105,116,40,103,108,111,98,97,108,32,102,111,108,108,111,119,115,98,\n111,100,121,32,111,102,110,111,109,105,110,97,108,67,111,110,116,97,99,116,115,\n101,99,117,108,97,114,108,101,102,116,32,116,111,99,104,105,101,102,108,121,45,\n104,105,100,100,101,110,45,98,97,110,110,101,114,60,47,108,105,62,10,10,46,32,87\n,104,101,110,32,105,110,32,98,111,116,104,100,105,115,109,105,115,115,69,120,112\n,108,111,114,101,97,108,119,97,121,115,32,118,105,97,32,116,104,101,115,112,97,\n195,177,111,108,119,101,108,102,97,114,101,114,117,108,105,110,103,32,97,114,114\n,97,110,103,101,99,97,112,116,97,105,110,104,105,115,32,115,111,110,114,117,108,\n101,32,111,102,104,101,32,116,111,111,107,105,116,115,101,108,102,44,61,48,38,97\n,109,112,59,40,99,97,108,108,101,100,115,97,109,112,108,101,115,116,111,32,109,\n97,107,101,99,111,109,47,112,97,103,77,97,114,116,105,110,32,75,101,110,110,101,\n100,121,97,99,99,101,112,116,115,102,117,108,108,32,111,102,104,97,110,100,108,\n101,100,66,101,115,105,100,101,115,47,47,45,45,62,60,47,97,98,108,101,32,116,111\n,116,97,114,103,101,116,115,101,115,115,101,110,99,101,104,105,109,32,116,111,32\n,105,116,115,32,98,121,32,99,111,109,109,111,110,46,109,105,110,101,114,97,108,\n116,111,32,116,97,107,101,119,97,121,115,32,116,111,115,46,111,114,103,47,108,97\n,100,118,105,115,101,100,112,101,110,97,108,116,121,115,105,109,112,108,101,58,\n105,102,32,116,104,101,121,76,101,116,116,101,114,115,97,32,115,104,111,114,116,\n72,101,114,98,101,114,116,115,116,114,105,107,101,115,32,103,114,111,117,112,115\n,46,108,101,110,103,116,104,102,108,105,103,104,116,115,111,118,101,114,108,97,\n112,115,108,111,119,108,121,32,108,101,115,115,101,114,32,115,111,99,105,97,108,\n32,60,47,112,62,10,9,9,105,116,32,105,110,116,111,114,97,110,107,101,100,32,114,\n97,116,101,32,111,102,117,108,62,13,10,32,32,97,116,116,101,109,112,116,112,97,\n105,114,32,111,102,109,97,107,101,32,105,116,75,111,110,116,97,107,116,65,110,\n116,111,110,105,111,104,97,118,105,110,103,32,114,97,116,105,110,103,115,32,97,\n99,116,105,118,101,115,116,114,101,97,109,115,116,114,97,112,112,101,100,34,41,\n46,99,115,115,40,104,111,115,116,105,108,101,108,101,97,100,32,116,111,108,105,\n116,116,108,101,32,103,114,111,117,112,115,44,80,105,99,116,117,114,101,45,45,62\n,13,10,13,10,32,114,111,119,115,61,34,32,111,98,106,101,99,116,105,110,118,101,\n114,115,101,60,102,111,111,116,101,114,67,117,115,116,111,109,86,62,60,92,47,115\n,99,114,115,111,108,118,105,110,103,67,104,97,109,98,101,114,115,108,97,118,101,\n114,121,119,111,117,110,100,101,100,119,104,101,114,101,97,115,33,61,32,39,117,\n110,100,102,111,114,32,97,108,108,112,97,114,116,108,121,32,45,114,105,103,104,\n116,58,65,114,97,98,105,97,110,98,97,99,107,101,100,32,99,101,110,116,117,114,\n121,117,110,105,116,32,111,102,109,111,98,105,108,101,45,69,117,114,111,112,101,\n44,105,115,32,104,111,109,101,114,105,115,107,32,111,102,100,101,115,105,114,101\n,100,67,108,105,110,116,111,110,99,111,115,116,32,111,102,97,103,101,32,111,102,\n32,98,101,99,111,109,101,32,110,111,110,101,32,111,102,112,38,113,117,111,116,59\n,77,105,100,100,108,101,32,101,97,100,39,41,91,48,67,114,105,116,105,99,115,115,\n116,117,100,105,111,115,62,38,99,111,112,121,59,103,114,111,117,112,34,62,97,115\n,115,101,109,98,108,109,97,107,105,110,103,32,112,114,101,115,115,101,100,119,\n105,100,103,101,116,46,112,115,58,34,32,63,32,114,101,98,117,105,108,116,98,121,\n32,115,111,109,101,70,111,114,109,101,114,32,101,100,105,116,111,114,115,100,101\n,108,97,121,101,100,67,97,110,111,110,105,99,104,97,100,32,116,104,101,112,117,\n115,104,105,110,103,99,108,97,115,115,61,34,98,117,116,32,97,114,101,112,97,114,\n116,105,97,108,66,97,98,121,108,111,110,98,111,116,116,111,109,32,99,97,114,114,\n105,101,114,67,111,109,109,97,110,100,105,116,115,32,117,115,101,65,115,32,119,\n105,116,104,99,111,117,114,115,101,115,97,32,116,104,105,114,100,100,101,110,111\n,116,101,115,97,108,115,111,32,105,110,72,111,117,115,116,111,110,50,48,112,120,\n59,34,62,97,99,99,117,115,101,100,100,111,117,98,108,101,32,103,111,97,108,32,\n111,102,70,97,109,111,117,115,32,41,46,98,105,110,100,40,112,114,105,101,115,116\n,115,32,79,110,108,105,110,101,105,110,32,74,117,108,121,115,116,32,43,32,34,103\n,99,111,110,115,117,108,116,100,101,99,105,109,97,108,104,101,108,112,102,117,\n108,114,101,118,105,118,101,100,105,115,32,118,101,114,121,114,39,43,39,105,112,\n116,108,111,115,105,110,103,32,102,101,109,97,108,101,115,105,115,32,97,108,115,\n111,115,116,114,105,110,103,115,100,97,121,115,32,111,102,97,114,114,105,118,97,\n108,102,117,116,117,114,101,32,60,111,98,106,101,99,116,102,111,114,99,105,110,\n103,83,116,114,105,110,103,40,34,32,47,62,10,9,9,104,101,114,101,32,105,115,101,\n110,99,111,100,101,100,46,32,32,84,104,101,32,98,97,108,108,111,111,110,100,111,\n110,101,32,98,121,47,99,111,109,109,111,110,98,103,99,111,108,111,114,108,97,119\n,32,111,102,32,73,110,100,105,97,110,97,97,118,111,105,100,101,100,98,117,116,32\n,116,104,101,50,112,120,32,51,112,120,106,113,117,101,114,121,46,97,102,116,101,\n114,32,97,112,111,108,105,99,121,46,109,101,110,32,97,110,100,102,111,111,116,\n101,114,45,61,32,116,114,117,101,59,102,111,114,32,117,115,101,115,99,114,101,\n101,110,46,73,110,100,105,97,110,32,105,109,97,103,101,32,61,102,97,109,105,108,\n121,44,104,116,116,112,58,47,47,32,38,110,98,115,112,59,100,114,105,118,101,114,\n115,101,116,101,114,110,97,108,115,97,109,101,32,97,115,110,111,116,105,99,101,\n100,118,105,101,119,101,114,115,125,41,40,41,59,10,32,105,115,32,109,111,114,101\n,115,101,97,115,111,110,115,102,111,114,109,101,114,32,116,104,101,32,110,101,\n119,105,115,32,106,117,115,116,99,111,110,115,101,110,116,32,83,101,97,114,99,\n104,119,97,115,32,116,104,101,119,104,121,32,116,104,101,115,104,105,112,112,101\n,100,98,114,62,60,98,114,62,119,105,100,116,104,58,32,104,101,105,103,104,116,61\n,109,97,100,101,32,111,102,99,117,105,115,105,110,101,105,115,32,116,104,97,116,\n97,32,118,101,114,121,32,65,100,109,105,114,97,108,32,102,105,120,101,100,59,110\n,111,114,109,97,108,32,77,105,115,115,105,111,110,80,114,101,115,115,44,32,111,\n110,116,97,114,105,111,99,104,97,114,115,101,116,116,114,121,32,116,111,32,105,\n110,118,97,100,101,100,61,34,116,114,117,101,34,115,112,97,99,105,110,103,105,\n115,32,109,111,115,116,97,32,109,111,114,101,32,116,111,116,97,108,108,121,102,\n97,108,108,32,111,102,125,41,59,13,10,32,32,105,109,109,101,110,115,101,116,105,\n109,101,32,105,110,115,101,116,32,111,117,116,115,97,116,105,115,102,121,116,111\n,32,102,105,110,100,100,111,119,110,32,116,111,108,111,116,32,111,102,32,80,108,\n97,121,101,114,115,105,110,32,74,117,110,101,113,117,97,110,116,117,109,110,111,\n116,32,116,104,101,116,105,109,101,32,116,111,100,105,115,116,97,110,116,70,105,\n110,110,105,115,104,115,114,99,32,61,32,40,115,105,110,103,108,101,32,104,101,\n108,112,32,111,102,71,101,114,109,97,110,32,108,97,119,32,97,110,100,108,97,98,\n101,108,101,100,102,111,114,101,115,116,115,99,111,111,107,105,110,103,115,112,\n97,99,101,34,62,104,101,97,100,101,114,45,119,101,108,108,32,97,115,83,116,97,\n110,108,101,121,98,114,105,100,103,101,115,47,103,108,111,98,97,108,67,114,111,\n97,116,105,97,32,65,98,111,117,116,32,91,48,93,59,10,32,32,105,116,44,32,97,110,\n100,103,114,111,117,112,101,100,98,101,105,110,103,32,97,41,123,116,104,114,111,\n119,104,101,32,109,97,100,101,108,105,103,104,116,101,114,101,116,104,105,99,97,\n108,70,70,70,70,70,70,34,98,111,116,116,111,109,34,108,105,107,101,32,97,32,101,\n109,112,108,111,121,115,108,105,118,101,32,105,110,97,115,32,115,101,101,110,112\n,114,105,110,116,101,114,109,111,115,116,32,111,102,117,98,45,108,105,110,107,\n114,101,106,101,99,116,115,97,110,100,32,117,115,101,105,109,97,103,101,34,62,\n115,117,99,99,101,101,100,102,101,101,100,105,110,103,78,117,99,108,101,97,114,\n105,110,102,111,114,109,97,116,111,32,104,101,108,112,87,111,109,101,110,39,115,\n78,101,105,116,104,101,114,77,101,120,105,99,97,110,112,114,111,116,101,105,110,\n60,116,97,98,108,101,32,98,121,32,109,97,110,121,104,101,97,108,116,104,121,108,\n97,119,115,117,105,116,100,101,118,105,115,101,100,46,112,117,115,104,40,123,115\n,101,108,108,101,114,115,115,105,109,112,108,121,32,84,104,114,111,117,103,104,\n46,99,111,111,107,105,101,32,73,109,97,103,101,40,111,108,100,101,114,34,62,117,\n115,46,106,115,34,62,32,83,105,110,99,101,32,117,110,105,118,101,114,115,108,97,\n114,103,101,114,32,111,112,101,110,32,116,111,33,45,45,32,101,110,100,108,105,\n101,115,32,105,110,39,93,41,59,13,10,32,32,109,97,114,107,101,116,119,104,111,32\n,105,115,32,40,34,68,79,77,67,111,109,97,110,97,103,101,100,111,110,101,32,102,\n111,114,116,121,112,101,111,102,32,75,105,110,103,100,111,109,112,114,111,102,\n105,116,115,112,114,111,112,111,115,101,116,111,32,115,104,111,119,99,101,110,\n116,101,114,59,109,97,100,101,32,105,116,100,114,101,115,115,101,100,119,101,114\n,101,32,105,110,109,105,120,116,117,114,101,112,114,101,99,105,115,101,97,114,\n105,115,105,110,103,115,114,99,32,61,32,39,109,97,107,101,32,97,32,115,101,99,\n117,114,101,100,66,97,112,116,105,115,116,118,111,116,105,110,103,32,10,9,9,118,\n97,114,32,77,97,114,99,104,32,50,103,114,101,119,32,117,112,67,108,105,109,97,\n116,101,46,114,101,109,111,118,101,115,107,105,108,108,101,100,119,97,121,32,116\n,104,101,60,47,104,101,97,100,62,102,97,99,101,32,111,102,97,99,116,105,110,103,\n32,114,105,103,104,116,34,62,116,111,32,119,111,114,107,114,101,100,117,99,101,\n115,104,97,115,32,104,97,100,101,114,101,99,116,101,100,115,104,111,119,40,41,59\n,97,99,116,105,111,110,61,98,111,111,107,32,111,102,97,110,32,97,114,101,97,61,\n61,32,34,104,116,116,60,104,101,97,100,101,114,10,60,104,116,109,108,62,99,111,\n110,102,111,114,109,102,97,99,105,110,103,32,99,111,111,107,105,101,46,114,101,\n108,121,32,111,110,104,111,115,116,101,100,32,46,99,117,115,116,111,109,104,101,\n32,119,101,110,116,98,117,116,32,102,111,114,115,112,114,101,97,100,32,70,97,109\n,105,108,121,32,97,32,109,101,97,110,115,111,117,116,32,116,104,101,102,111,114,\n117,109,115,46,102,111,111,116,97,103,101,34,62,77,111,98,105,108,67,108,101,109\n,101,110,116,115,34,32,105,100,61,34,97,115,32,104,105,103,104,105,110,116,101,\n110,115,101,45,45,62,60,33,45,45,102,101,109,97,108,101,32,105,115,32,115,101,\n101,110,105,109,112,108,105,101,100,115,101,116,32,116,104,101,97,32,115,116,97,\n116,101,97,110,100,32,104,105,115,102,97,115,116,101,115,116,98,101,115,105,100,\n101,115,98,117,116,116,111,110,95,98,111,117,110,100,101,100,34,62,60,105,109,\n103,32,73,110,102,111,98,111,120,101,118,101,110,116,115,44,97,32,121,111,117,\n110,103,97,110,100,32,97,114,101,78,97,116,105,118,101,32,99,104,101,97,112,101,\n114,84,105,109,101,111,117,116,97,110,100,32,104,97,115,101,110,103,105,110,101,\n115,119,111,110,32,116,104,101,40,109,111,115,116,108,121,114,105,103,104,116,58\n,32,102,105,110,100,32,97,32,45,98,111,116,116,111,109,80,114,105,110,99,101,32,\n97,114,101,97,32,111,102,109,111,114,101,32,111,102,115,101,97,114,99,104,95,110\n,97,116,117,114,101,44,108,101,103,97,108,108,121,112,101,114,105,111,100,44,108\n,97,110,100,32,111,102,111,114,32,119,105,116,104,105,110,100,117,99,101,100,112\n,114,111,118,105,110,103,109,105,115,115,105,108,101,108,111,99,97,108,108,121,\n65,103,97,105,110,115,116,116,104,101,32,119,97,121,107,38,113,117,111,116,59,\n112,120,59,34,62,13,10,112,117,115,104,101,100,32,97,98,97,110,100,111,110,110,\n117,109,101,114,97,108,67,101,114,116,97,105,110,73,110,32,116,104,105,115,109,\n111,114,101,32,105,110,111,114,32,115,111,109,101,110,97,109,101,32,105,115,97,\n110,100,44,32,105,110,99,114,111,119,110,101,100,73,83,66,78,32,48,45,99,114,101\n,97,116,101,115,79,99,116,111,98,101,114,109,97,121,32,110,111,116,99,101,110,\n116,101,114,32,108,97,116,101,32,105,110,68,101,102,101,110,99,101,101,110,97,99\n,116,101,100,119,105,115,104,32,116,111,98,114,111,97,100,108,121,99,111,111,108\n,105,110,103,111,110,108,111,97,100,61,105,116,46,32,84,104,101,114,101,99,111,\n118,101,114,77,101,109,98,101,114,115,104,101,105,103,104,116,32,97,115,115,117,\n109,101,115,60,104,116,109,108,62,10,112,101,111,112,108,101,46,105,110,32,111,\n110,101,32,61,119,105,110,100,111,119,102,111,111,116,101,114,95,97,32,103,111,\n111,100,32,114,101,107,108,97,109,97,111,116,104,101,114,115,44,116,111,32,116,\n104,105,115,95,99,111,111,107,105,101,112,97,110,101,108,34,62,76,111,110,100,\n111,110,44,100,101,102,105,110,101,115,99,114,117,115,104,101,100,98,97,112,116,\n105,115,109,99,111,97,115,116,97,108,115,116,97,116,117,115,32,116,105,116,108,\n101,34,32,109,111,118,101,32,116,111,108,111,115,116,32,105,110,98,101,116,116,\n101,114,32,105,109,112,108,105,101,115,114,105,118,97,108,114,121,115,101,114,\n118,101,114,115,32,83,121,115,116,101,109,80,101,114,104,97,112,115,101,115,32,\n97,110,100,32,99,111,110,116,101,110,100,102,108,111,119,105,110,103,108,97,115,\n116,101,100,32,114,105,115,101,32,105,110,71,101,110,101,115,105,115,118,105,101\n,119,32,111,102,114,105,115,105,110,103,32,115,101,101,109,32,116,111,98,117,116\n,32,105,110,32,98,97,99,107,105,110,103,104,101,32,119,105,108,108,103,105,118,\n101,110,32,97,103,105,118,105,110,103,32,99,105,116,105,101,115,46,102,108,111,\n119,32,111,102,32,76,97,116,101,114,32,97,108,108,32,98,117,116,72,105,103,104,\n119,97,121,111,110,108,121,32,98,121,115,105,103,110,32,111,102,104,101,32,100,\n111,101,115,100,105,102,102,101,114,115,98,97,116,116,101,114,121,38,97,109,112,\n59,108,97,115,105,110,103,108,101,115,116,104,114,101,97,116,115,105,110,116,101\n,103,101,114,116,97,107,101,32,111,110,114,101,102,117,115,101,100,99,97,108,108\n,101,100,32,61,85,83,38,97,109,112,83,101,101,32,116,104,101,110,97,116,105,118,\n101,115,98,121,32,116,104,105,115,115,121,115,116,101,109,46,104,101,97,100,32,\n111,102,58,104,111,118,101,114,44,108,101,115,98,105,97,110,115,117,114,110,97,\n109,101,97,110,100,32,97,108,108,99,111,109,109,111,110,47,104,101,97,100,101,\n114,95,95,112,97,114,97,109,115,72,97,114,118,97,114,100,47,112,105,120,101,108,\n46,114,101,109,111,118,97,108,115,111,32,108,111,110,103,114,111,108,101,32,111,\n102,106,111,105,110,116,108,121,115,107,121,115,99,114,97,85,110,105,99,111,100,\n101,98,114,32,47,62,13,10,65,116,108,97,110,116,97,110,117,99,108,101,117,115,67\n,111,117,110,116,121,44,112,117,114,101,108,121,32,99,111,117,110,116,34,62,101,\n97,115,105,108,121,32,98,117,105,108,100,32,97,111,110,99,108,105,99,107,97,32,\n103,105,118,101,110,112,111,105,110,116,101,114,104,38,113,117,111,116,59,101,\n118,101,110,116,115,32,101,108,115,101,32,123,10,100,105,116,105,111,110,115,110\n,111,119,32,116,104,101,44,32,119,105,116,104,32,109,97,110,32,119,104,111,111,\n114,103,47,87,101,98,111,110,101,32,97,110,100,99,97,118,97,108,114,121,72,101,\n32,100,105,101,100,115,101,97,116,116,108,101,48,48,44,48,48,48,32,123,119,105,\n110,100,111,119,104,97,118,101,32,116,111,105,102,40,119,105,110,100,97,110,100,\n32,105,116,115,115,111,108,101,108,121,32,109,38,113,117,111,116,59,114,101,110,\n101,119,101,100,68,101,116,114,111,105,116,97,109,111,110,103,115,116,101,105,\n116,104,101,114,32,116,104,101,109,32,105,110,83,101,110,97,116,111,114,85,115,\n60,47,97,62,60,75,105,110,103,32,111,102,70,114,97,110,99,105,115,45,112,114,111\n,100,117,99,104,101,32,117,115,101,100,97,114,116,32,97,110,100,104,105,109,32,\n97,110,100,117,115,101,100,32,98,121,115,99,111,114,105,110,103,97,116,32,104,\n111,109,101,116,111,32,104,97,118,101,114,101,108,97,116,101,115,105,98,105,108,\n105,116,121,102,97,99,116,105,111,110,66,117,102,102,97,108,111,108,105,110,107,\n34,62,60,119,104,97,116,32,104,101,102,114,101,101,32,116,111,67,105,116,121,32,\n111,102,99,111,109,101,32,105,110,115,101,99,116,111,114,115,99,111,117,110,116,\n101,100,111,110,101,32,100,97,121,110,101,114,118,111,117,115,115,113,117,97,114\n,101,32,125,59,105,102,40,103,111,105,110,32,119,104,97,116,105,109,103,34,32,97\n,108,105,115,32,111,110,108,121,115,101,97,114,99,104,47,116,117,101,115,100,97,\n121,108,111,111,115,101,108,121,83,111,108,111,109,111,110,115,101,120,117,97,\n108,32,45,32,60,97,32,104,114,109,101,100,105,117,109,34,68,79,32,78,79,84,32,70\n,114,97,110,99,101,44,119,105,116,104,32,97,32,119,97,114,32,97,110,100,115,101,\n99,111,110,100,32,116,97,107,101,32,97,32,62,13,10,13,10,13,10,109,97,114,107,\n101,116,46,104,105,103,104,119,97,121,100,111,110,101,32,105,110,99,116,105,118,\n105,116,121,34,108,97,115,116,34,62,111,98,108,105,103,101,100,114,105,115,101,\n32,116,111,34,117,110,100,101,102,105,109,97,100,101,32,116,111,32,69,97,114,108\n,121,32,112,114,97,105,115,101,100,105,110,32,105,116,115,32,102,111,114,32,104,\n105,115,97,116,104,108,101,116,101,74,117,112,105,116,101,114,89,97,104,111,111,\n33,32,116,101,114,109,101,100,32,115,111,32,109,97,110,121,114,101,97,108,108,\n121,32,115,46,32,84,104,101,32,97,32,119,111,109,97,110,63,118,97,108,117,101,61\n,100,105,114,101,99,116,32,114,105,103,104,116,34,32,98,105,99,121,99,108,101,97\n,99,105,110,103,61,34,100,97,121,32,97,110,100,115,116,97,116,105,110,103,82,97,\n116,104,101,114,44,104,105,103,104,101,114,32,79,102,102,105,99,101,32,97,114,\n101,32,110,111,119,116,105,109,101,115,44,32,119,104,101,110,32,97,32,112,97,121\n,32,102,111,114,111,110,32,116,104,105,115,45,108,105,110,107,34,62,59,98,111,\n114,100,101,114,97,114,111,117,110,100,32,97,110,110,117,97,108,32,116,104,101,\n32,78,101,119,112,117,116,32,116,104,101,46,99,111,109,34,32,116,97,107,105,110,\n32,116,111,97,32,98,114,105,101,102,40,105,110,32,116,104,101,103,114,111,117,\n112,115,46,59,32,119,105,100,116,104,101,110,122,121,109,101,115,115,105,109,112\n,108,101,32,105,110,32,108,97,116,101,123,114,101,116,117,114,110,116,104,101,\n114,97,112,121,97,32,112,111,105,110,116,98,97,110,110,105,110,103,105,110,107,\n115,34,62,10,40,41,59,34,32,114,101,97,32,112,108,97,99,101,92,117,48,48,51,67,\n97,97,98,111,117,116,32,97,116,114,62,13,10,9,9,99,99,111,117,110,116,32,103,105\n,118,101,115,32,97,60,83,67,82,73,80,84,82,97,105,108,119,97,121,116,104,101,109\n,101,115,47,116,111,111,108,98,111,120,66,121,73,100,40,34,120,104,117,109,97,\n110,115,44,119,97,116,99,104,101,115,105,110,32,115,111,109,101,32,105,102,32,40\n,119,105,99,111,109,105,110,103,32,102,111,114,109,97,116,115,32,85,110,100,101,\n114,32,98,117,116,32,104,97,115,104,97,110,100,101,100,32,109,97,100,101,32,98,\n121,116,104,97,110,32,105,110,102,101,97,114,32,111,102,100,101,110,111,116,101,\n100,47,105,102,114,97,109,101,108,101,102,116,32,105,110,118,111,108,116,97,103,\n101,105,110,32,101,97,99,104,97,38,113,117,111,116,59,98,97,115,101,32,111,102,\n73,110,32,109,97,110,121,117,110,100,101,114,103,111,114,101,103,105,109,101,115\n,97,99,116,105,111,110,32,60,47,112,62,13,10,60,117,115,116,111,109,86,97,59,38,\n103,116,59,60,47,105,109,112,111,114,116,115,111,114,32,116,104,97,116,109,111,\n115,116,108,121,32,38,97,109,112,59,114,101,32,115,105,122,101,61,34,60,47,97,62\n,60,47,104,97,32,99,108,97,115,115,112,97,115,115,105,118,101,72,111,115,116,32,\n61,32,87,104,101,116,104,101,114,102,101,114,116,105,108,101,86,97,114,105,111,\n117,115,61,91,93,59,40,102,117,99,97,109,101,114,97,115,47,62,60,47,116,100,62,\n97,99,116,115,32,97,115,73,110,32,115,111,109,101,62,13,10,13,10,60,33,111,114,\n103,97,110,105,115,32,60,98,114,32,47,62,66,101,105,106,105,110,103,99,97,116,97\n,108,195,160,100,101,117,116,115,99,104,101,117,114,111,112,101,117,101,117,115,\n107,97,114,97,103,97,101,105,108,103,101,115,118,101,110,115,107,97,101,115,112,\n97,195,177,97,109,101,110,115,97,106,101,117,115,117,97,114,105,111,116,114,97,\n98,97,106,111,109,195,169,120,105,99,111,112,195,161,103,105,110,97,115,105,101,\n109,112,114,101,115,105,115,116,101,109,97,111,99,116,117,98,114,101,100,117,114\n,97,110,116,101,97,195,177,97,100,105,114,101,109,112,114,101,115,97,109,111,109\n,101,110,116,111,110,117,101,115,116,114,111,112,114,105,109,101,114,97,116,114,\n97,118,195,169,115,103,114,97,99,105,97,115,110,117,101,115,116,114,97,112,114,\n111,99,101,115,111,101,115,116,97,100,111,115,99,97,108,105,100,97,100,112,101,\n114,115,111,110,97,110,195,186,109,101,114,111,97,99,117,101,114,100,111,109,195\n,186,115,105,99,97,109,105,101,109,98,114,111,111,102,101,114,116,97,115,97,108,\n103,117,110,111,115,112,97,195,173,115,101,115,101,106,101,109,112,108,111,100,\n101,114,101,99,104,111,97,100,101,109,195,161,115,112,114,105,118,97,100,111,97,\n103,114,101,103,97,114,101,110,108,97,99,101,115,112,111,115,105,98,108,101,104,\n111,116,101,108,101,115,115,101,118,105,108,108,97,112,114,105,109,101,114,111,\n195,186,108,116,105,109,111,101,118,101,110,116,111,115,97,114,99,104,105,118,\n111,99,117,108,116,117,114,97,109,117,106,101,114,101,115,101,110,116,114,97,100\n,97,97,110,117,110,99,105,111,101,109,98,97,114,103,111,109,101,114,99,97,100,\n111,103,114,97,110,100,101,115,101,115,116,117,100,105,111,109,101,106,111,114,\n101,115,102,101,98,114,101,114,111,100,105,115,101,195,177,111,116,117,114,105,\n115,109,111,99,195,179,100,105,103,111,112,111,114,116,97,100,97,101,115,112,97,\n99,105,111,102,97,109,105,108,105,97,97,110,116,111,110,105,111,112,101,114,109,\n105,116,101,103,117,97,114,100,97,114,97,108,103,117,110,97,115,112,114,101,99,\n105,111,115,97,108,103,117,105,101,110,115,101,110,116,105,100,111,118,105,115,\n105,116,97,115,116,195,173,116,117,108,111,99,111,110,111,99,101,114,115,101,103\n,117,110,100,111,99,111,110,115,101,106,111,102,114,97,110,99,105,97,109,105,110\n,117,116,111,115,115,101,103,117,110,100,97,116,101,110,101,109,111,115,101,102,\n101,99,116,111,115,109,195,161,108,97,103,97,115,101,115,105,195,179,110,114,101\n,118,105,115,116,97,103,114,97,110,97,100,97,99,111,109,112,114,97,114,105,110,\n103,114,101,115,111,103,97,114,99,195,173,97,97,99,99,105,195,179,110,101,99,117\n,97,100,111,114,113,117,105,101,110,101,115,105,110,99,108,117,115,111,100,101,\n98,101,114,195,161,109,97,116,101,114,105,97,104,111,109,98,114,101,115,109,117,\n101,115,116,114,97,112,111,100,114,195,173,97,109,97,195,177,97,110,97,195,186,\n108,116,105,109,97,101,115,116,97,109,111,115,111,102,105,99,105,97,108,116,97,\n109,98,105,101,110,110,105,110,103,195,186,110,115,97,108,117,100,111,115,112,\n111,100,101,109,111,115,109,101,106,111,114,97,114,112,111,115,105,116,105,111,\n110,98,117,115,105,110,101,115,115,104,111,109,101,112,97,103,101,115,101,99,117\n,114,105,116,121,108,97,110,103,117,97,103,101,115,116,97,110,100,97,114,100,99,\n97,109,112,97,105,103,110,102,101,97,116,117,114,101,115,99,97,116,101,103,111,\n114,121,101,120,116,101,114,110,97,108,99,104,105,108,100,114,101,110,114,101,\n115,101,114,118,101,100,114,101,115,101,97,114,99,104,101,120,99,104,97,110,103,\n101,102,97,118,111,114,105,116,101,116,101,109,112,108,97,116,101,109,105,108,\n105,116,97,114,121,105,110,100,117,115,116,114,121,115,101,114,118,105,99,101,\n115,109,97,116,101,114,105,97,108,112,114,111,100,117,99,116,115,122,45,105,110,\n100,101,120,58,99,111,109,109,101,110,116,115,115,111,102,116,119,97,114,101,99,\n111,109,112,108,101,116,101,99,97,108,101,110,100,97,114,112,108,97,116,102,111,\n114,109,97,114,116,105,99,108,101,115,114,101,113,117,105,114,101,100,109,111,\n118,101,109,101,110,116,113,117,101,115,116,105,111,110,98,117,105,108,100,105,\n110,103,112,111,108,105,116,105,99,115,112,111,115,115,105,98,108,101,114,101,\n108,105,103,105,111,110,112,104,121,115,105,99,97,108,102,101,101,100,98,97,99,\n107,114,101,103,105,115,116,101,114,112,105,99,116,117,114,101,115,100,105,115,\n97,98,108,101,100,112,114,111,116,111,99,111,108,97,117,100,105,101,110,99,101,\n115,101,116,116,105,110,103,115,97,99,116,105,118,105,116,121,101,108,101,109,\n101,110,116,115,108,101,97,114,110,105,110,103,97,110,121,116,104,105,110,103,97\n,98,115,116,114,97,99,116,112,114,111,103,114,101,115,115,111,118,101,114,118,\n105,101,119,109,97,103,97,122,105,110,101,101,99,111,110,111,109,105,99,116,114,\n97,105,110,105,110,103,112,114,101,115,115,117,114,101,118,97,114,105,111,117,\n115,32,60,115,116,114,111,110,103,62,112,114,111,112,101,114,116,121,115,104,111\n,112,112,105,110,103,116,111,103,101,116,104,101,114,97,100,118,97,110,99,101,\n100,98,101,104,97,118,105,111,114,100,111,119,110,108,111,97,100,102,101,97,116,\n117,114,101,100,102,111,111,116,98,97,108,108,115,101,108,101,99,116,101,100,76,\n97,110,103,117,97,103,101,100,105,115,116,97,110,99,101,114,101,109,101,109,98,\n101,114,116,114,97,99,107,105,110,103,112,97,115,115,119,111,114,100,109,111,100\n,105,102,105,101,100,115,116,117,100,101,110,116,115,100,105,114,101,99,116,108,\n121,102,105,103,104,116,105,110,103,110,111,114,116,104,101,114,110,100,97,116,\n97,98,97,115,101,102,101,115,116,105,118,97,108,98,114,101,97,107,105,110,103,\n108,111,99,97,116,105,111,110,105,110,116,101,114,110,101,116,100,114,111,112,\n100,111,119,110,112,114,97,99,116,105,99,101,101,118,105,100,101,110,99,101,102,\n117,110,99,116,105,111,110,109,97,114,114,105,97,103,101,114,101,115,112,111,110\n,115,101,112,114,111,98,108,101,109,115,110,101,103,97,116,105,118,101,112,114,\n111,103,114,97,109,115,97,110,97,108,121,115,105,115,114,101,108,101,97,115,101,\n100,98,97,110,110,101,114,34,62,112,117,114,99,104,97,115,101,112,111,108,105,99\n,105,101,115,114,101,103,105,111,110,97,108,99,114,101,97,116,105,118,101,97,114\n,103,117,109,101,110,116,98,111,111,107,109,97,114,107,114,101,102,101,114,114,\n101,114,99,104,101,109,105,99,97,108,100,105,118,105,115,105,111,110,99,97,108,\n108,98,97,99,107,115,101,112,97,114,97,116,101,112,114,111,106,101,99,116,115,99\n,111,110,102,108,105,99,116,104,97,114,100,119,97,114,101,105,110,116,101,114,\n101,115,116,100,101,108,105,118,101,114,121,109,111,117,110,116,97,105,110,111,\n98,116,97,105,110,101,100,61,32,102,97,108,115,101,59,102,111,114,40,118,97,114,\n32,97,99,99,101,112,116,101,100,99,97,112,97,99,105,116,121,99,111,109,112,117,\n116,101,114,105,100,101,110,116,105,116,121,97,105,114,99,114,97,102,116,101,109\n,112,108,111,121,101,100,112,114,111,112,111,115,101,100,100,111,109,101,115,116\n,105,99,105,110,99,108,117,100,101,115,112,114,111,118,105,100,101,100,104,111,\n115,112,105,116,97,108,118,101,114,116,105,99,97,108,99,111,108,108,97,112,115,\n101,97,112,112,114,111,97,99,104,112,97,114,116,110,101,114,115,108,111,103,111,\n34,62,60,97,100,97,117,103,104,116,101,114,97,117,116,104,111,114,34,32,99,117,\n108,116,117,114,97,108,102,97,109,105,108,105,101,115,47,105,109,97,103,101,115,\n47,97,115,115,101,109,98,108,121,112,111,119,101,114,102,117,108,116,101,97,99,\n104,105,110,103,102,105,110,105,115,104,101,100,100,105,115,116,114,105,99,116,\n99,114,105,116,105,99,97,108,99,103,105,45,98,105,110,47,112,117,114,112,111,115\n,101,115,114,101,113,117,105,114,101,115,101,108,101,99,116,105,111,110,98,101,\n99,111,109,105,110,103,112,114,111,118,105,100,101,115,97,99,97,100,101,109,105,\n99,101,120,101,114,99,105,115,101,97,99,116,117,97,108,108,121,109,101,100,105,\n99,105,110,101,99,111,110,115,116,97,110,116,97,99,99,105,100,101,110,116,77,97,\n103,97,122,105,110,101,100,111,99,117,109,101,110,116,115,116,97,114,116,105,110\n,103,98,111,116,116,111,109,34,62,111,98,115,101,114,118,101,100,58,32,38,113,\n117,111,116,59,101,120,116,101,110,100,101,100,112,114,101,118,105,111,117,115,\n83,111,102,116,119,97,114,101,99,117,115,116,111,109,101,114,100,101,99,105,115,\n105,111,110,115,116,114,101,110,103,116,104,100,101,116,97,105,108,101,100,115,\n108,105,103,104,116,108,121,112,108,97,110,110,105,110,103,116,101,120,116,97,\n114,101,97,99,117,114,114,101,110,99,121,101,118,101,114,121,111,110,101,115,116\n,114,97,105,103,104,116,116,114,97,110,115,102,101,114,112,111,115,105,116,105,\n118,101,112,114,111,100,117,99,101,100,104,101,114,105,116,97,103,101,115,104,\n105,112,112,105,110,103,97,98,115,111,108,117,116,101,114,101,99,101,105,118,101\n,100,114,101,108,101,118,97,110,116,98,117,116,116,111,110,34,32,118,105,111,108\n,101,110,99,101,97,110,121,119,104,101,114,101,98,101,110,101,102,105,116,115,\n108,97,117,110,99,104,101,100,114,101,99,101,110,116,108,121,97,108,108,105,97,\n110,99,101,102,111,108,108,111,119,101,100,109,117,108,116,105,112,108,101,98,\n117,108,108,101,116,105,110,105,110,99,108,117,100,101,100,111,99,99,117,114,114\n,101,100,105,110,116,101,114,110,97,108,36,40,116,104,105,115,41,46,114,101,112,\n117,98,108,105,99,62,60,116,114,62,60,116,100,99,111,110,103,114,101,115,115,114\n,101,99,111,114,100,101,100,117,108,116,105,109,97,116,101,115,111,108,117,116,\n105,111,110,60,117,108,32,105,100,61,34,100,105,115,99,111,118,101,114,72,111,\n109,101,60,47,97,62,119,101,98,115,105,116,101,115,110,101,116,119,111,114,107,\n115,97,108,116,104,111,117,103,104,101,110,116,105,114,101,108,121,109,101,109,\n111,114,105,97,108,109,101,115,115,97,103,101,115,99,111,110,116,105,110,117,101\n,97,99,116,105,118,101,34,62,115,111,109,101,119,104,97,116,118,105,99,116,111,\n114,105,97,87,101,115,116,101,114,110,32,32,116,105,116,108,101,61,34,76,111,99,\n97,116,105,111,110,99,111,110,116,114,97,99,116,118,105,115,105,116,111,114,115,\n68,111,119,110,108,111,97,100,119,105,116,104,111,117,116,32,114,105,103,104,116\n,34,62,10,109,101,97,115,117,114,101,115,119,105,100,116,104,32,61,32,118,97,114\n,105,97,98,108,101,105,110,118,111,108,118,101,100,118,105,114,103,105,110,105,\n97,110,111,114,109,97,108,108,121,104,97,112,112,101,110,101,100,97,99,99,111,\n117,110,116,115,115,116,97,110,100,105,110,103,110,97,116,105,111,110,97,108,82,\n101,103,105,115,116,101,114,112,114,101,112,97,114,101,100,99,111,110,116,114,\n111,108,115,97,99,99,117,114,97,116,101,98,105,114,116,104,100,97,121,115,116,\n114,97,116,101,103,121,111,102,102,105,99,105,97,108,103,114,97,112,104,105,99,\n115,99,114,105,109,105,110,97,108,112,111,115,115,105,98,108,121,99,111,110,115,\n117,109,101,114,80,101,114,115,111,110,97,108,115,112,101,97,107,105,110,103,118\n,97,108,105,100,97,116,101,97,99,104,105,101,118,101,100,46,106,112,103,34,32,47\n,62,109,97,99,104,105,110,101,115,60,47,104,50,62,10,32,32,107,101,121,119,111,\n114,100,115,102,114,105,101,110,100,108,121,98,114,111,116,104,101,114,115,99,\n111,109,98,105,110,101,100,111,114,105,103,105,110,97,108,99,111,109,112,111,115\n,101,100,101,120,112,101,99,116,101,100,97,100,101,113,117,97,116,101,112,97,107\n,105,115,116,97,110,102,111,108,108,111,119,34,32,118,97,108,117,97,98,108,101,\n60,47,108,97,98,101,108,62,114,101,108,97,116,105,118,101,98,114,105,110,103,105\n,110,103,105,110,99,114,101,97,115,101,103,111,118,101,114,110,111,114,112,108,\n117,103,105,110,115,47,76,105,115,116,32,111,102,32,72,101,97,100,101,114,34,62,\n34,32,110,97,109,101,61,34,32,40,38,113,117,111,116,59,103,114,97,100,117,97,116\n,101,60,47,104,101,97,100,62,10,99,111,109,109,101,114,99,101,109,97,108,97,121,\n115,105,97,100,105,114,101,99,116,111,114,109,97,105,110,116,97,105,110,59,104,\n101,105,103,104,116,58,115,99,104,101,100,117,108,101,99,104,97,110,103,105,110,\n103,98,97,99,107,32,116,111,32,99,97,116,104,111,108,105,99,112,97,116,116,101,\n114,110,115,99,111,108,111,114,58,32,35,103,114,101,97,116,101,115,116,115,117,\n112,112,108,105,101,115,114,101,108,105,97,98,108,101,60,47,117,108,62,10,9,9,60\n,115,101,108,101,99,116,32,99,105,116,105,122,101,110,115,99,108,111,116,104,105\n,110,103,119,97,116,99,104,105,110,103,60,108,105,32,105,100,61,34,115,112,101,\n99,105,102,105,99,99,97,114,114,121,105,110,103,115,101,110,116,101,110,99,101,\n60,99,101,110,116,101,114,62,99,111,110,116,114,97,115,116,116,104,105,110,107,\n105,110,103,99,97,116,99,104,40,101,41,115,111,117,116,104,101,114,110,77,105,99\n,104,97,101,108,32,109,101,114,99,104,97,110,116,99,97,114,111,117,115,101,108,\n112,97,100,100,105,110,103,58,105,110,116,101,114,105,111,114,46,115,112,108,105\n,116,40,34,108,105,122,97,116,105,111,110,79,99,116,111,98,101,114,32,41,123,114\n,101,116,117,114,110,105,109,112,114,111,118,101,100,45,45,38,103,116,59,10,10,\n99,111,118,101,114,97,103,101,99,104,97,105,114,109,97,110,46,112,110,103,34,32,\n47,62,115,117,98,106,101,99,116,115,82,105,99,104,97,114,100,32,119,104,97,116,\n101,118,101,114,112,114,111,98,97,98,108,121,114,101,99,111,118,101,114,121,98,\n97,115,101,98,97,108,108,106,117,100,103,109,101,110,116,99,111,110,110,101,99,\n116,46,46,99,115,115,34,32,47,62,32,119,101,98,115,105,116,101,114,101,112,111,\n114,116,101,100,100,101,102,97,117,108,116,34,47,62,60,47,97,62,13,10,101,108,\n101,99,116,114,105,99,115,99,111,116,108,97,110,100,99,114,101,97,116,105,111,\n110,113,117,97,110,116,105,116,121,46,32,73,83,66,78,32,48,100,105,100,32,110,\n111,116,32,105,110,115,116,97,110,99,101,45,115,101,97,114,99,104,45,34,32,108,\n97,110,103,61,34,115,112,101,97,107,101,114,115,67,111,109,112,117,116,101,114,\n99,111,110,116,97,105,110,115,97,114,99,104,105,118,101,115,109,105,110,105,115,\n116,101,114,114,101,97,99,116,105,111,110,100,105,115,99,111,117,110,116,73,116,\n97,108,105,97,110,111,99,114,105,116,101,114,105,97,115,116,114,111,110,103,108,\n121,58,32,39,104,116,116,112,58,39,115,99,114,105,112,116,39,99,111,118,101,114,\n105,110,103,111,102,102,101,114,105,110,103,97,112,112,101,97,114,101,100,66,114\n,105,116,105,115,104,32,105,100,101,110,116,105,102,121,70,97,99,101,98,111,111,\n107,110,117,109,101,114,111,117,115,118,101,104,105,99,108,101,115,99,111,110,99\n,101,114,110,115,65,109,101,114,105,99,97,110,104,97,110,100,108,105,110,103,100\n,105,118,32,105,100,61,34,87,105,108,108,105,97,109,32,112,114,111,118,105,100,\n101,114,95,99,111,110,116,101,110,116,97,99,99,117,114,97,99,121,115,101,99,116,\n105,111,110,32,97,110,100,101,114,115,111,110,102,108,101,120,105,98,108,101,67,\n97,116,101,103,111,114,121,108,97,119,114,101,110,99,101,60,115,99,114,105,112,\n116,62,108,97,121,111,117,116,61,34,97,112,112,114,111,118,101,100,32,109,97,120\n,105,109,117,109,104,101,97,100,101,114,34,62,60,47,116,97,98,108,101,62,83,101,\n114,118,105,99,101,115,104,97,109,105,108,116,111,110,99,117,114,114,101,110,116\n,32,99,97,110,97,100,105,97,110,99,104,97,110,110,101,108,115,47,116,104,101,109\n,101,115,47,47,97,114,116,105,99,108,101,111,112,116,105,111,110,97,108,112,111,\n114,116,117,103,97,108,118,97,108,117,101,61,34,34,105,110,116,101,114,118,97,\n108,119,105,114,101,108,101,115,115,101,110,116,105,116,108,101,100,97,103,101,\n110,99,105,101,115,83,101,97,114,99,104,34,32,109,101,97,115,117,114,101,100,116\n,104,111,117,115,97,110,100,115,112,101,110,100,105,110,103,38,104,101,108,108,\n105,112,59,110,101,119,32,68,97,116,101,34,32,115,105,122,101,61,34,112,97,103,\n101,78,97,109,101,109,105,100,100,108,101,34,32,34,32,47,62,60,47,97,62,104,105,\n100,100,101,110,34,62,115,101,113,117,101,110,99,101,112,101,114,115,111,110,97,\n108,111,118,101,114,102,108,111,119,111,112,105,110,105,111,110,115,105,108,108,\n105,110,111,105,115,108,105,110,107,115,34,62,10,9,60,116,105,116,108,101,62,118\n,101,114,115,105,111,110,115,115,97,116,117,114,100,97,121,116,101,114,109,105,\n110,97,108,105,116,101,109,112,114,111,112,101,110,103,105,110,101,101,114,115,\n101,99,116,105,111,110,115,100,101,115,105,103,110,101,114,112,114,111,112,111,\n115,97,108,61,34,102,97,108,115,101,34,69,115,112,97,195,177,111,108,114,101,108\n,101,97,115,101,115,115,117,98,109,105,116,34,32,101,114,38,113,117,111,116,59,\n97,100,100,105,116,105,111,110,115,121,109,112,116,111,109,115,111,114,105,101,\n110,116,101,100,114,101,115,111,117,114,99,101,114,105,103,104,116,34,62,60,112,\n108,101,97,115,117,114,101,115,116,97,116,105,111,110,115,104,105,115,116,111,\n114,121,46,108,101,97,118,105,110,103,32,32,98,111,114,100,101,114,61,99,111,110\n,116,101,110,116,115,99,101,110,116,101,114,34,62,46,10,10,83,111,109,101,32,100\n,105,114,101,99,116,101,100,115,117,105,116,97,98,108,101,98,117,108,103,97,114,\n105,97,46,115,104,111,119,40,41,59,100,101,115,105,103,110,101,100,71,101,110,\n101,114,97,108,32,99,111,110,99,101,112,116,115,69,120,97,109,112,108,101,115,\n119,105,108,108,105,97,109,115,79,114,105,103,105,110,97,108,34,62,60,115,112,97\n,110,62,115,101,97,114,99,104,34,62,111,112,101,114,97,116,111,114,114,101,113,\n117,101,115,116,115,97,32,38,113,117,111,116,59,97,108,108,111,119,105,110,103,\n68,111,99,117,109,101,110,116,114,101,118,105,115,105,111,110,46,32,10,10,84,104\n,101,32,121,111,117,114,115,101,108,102,67,111,110,116,97,99,116,32,109,105,99,\n104,105,103,97,110,69,110,103,108,105,115,104,32,99,111,108,117,109,98,105,97,\n112,114,105,111,114,105,116,121,112,114,105,110,116,105,110,103,100,114,105,110,\n107,105,110,103,102,97,99,105,108,105,116,121,114,101,116,117,114,110,101,100,67\n,111,110,116,101,110,116,32,111,102,102,105,99,101,114,115,82,117,115,115,105,97\n,110,32,103,101,110,101,114,97,116,101,45,56,56,53,57,45,49,34,105,110,100,105,\n99,97,116,101,102,97,109,105,108,105,97,114,32,113,117,97,108,105,116,121,109,97\n,114,103,105,110,58,48,32,99,111,110,116,101,110,116,118,105,101,119,112,111,114\n,116,99,111,110,116,97,99,116,115,45,116,105,116,108,101,34,62,112,111,114,116,\n97,98,108,101,46,108,101,110,103,116,104,32,101,108,105,103,105,98,108,101,105,\n110,118,111,108,118,101,115,97,116,108,97,110,116,105,99,111,110,108,111,97,100,\n61,34,100,101,102,97,117,108,116,46,115,117,112,112,108,105,101,100,112,97,121,\n109,101,110,116,115,103,108,111,115,115,97,114,121,10,10,65,102,116,101,114,32,\n103,117,105,100,97,110,99,101,60,47,116,100,62,60,116,100,101,110,99,111,100,105\n,110,103,109,105,100,100,108,101,34,62,99,97,109,101,32,116,111,32,100,105,115,\n112,108,97,121,115,115,99,111,116,116,105,115,104,106,111,110,97,116,104,97,110,\n109,97,106,111,114,105,116,121,119,105,100,103,101,116,115,46,99,108,105,110,105\n,99,97,108,116,104,97,105,108,97,110,100,116,101,97,99,104,101,114,115,60,104,\n101,97,100,62,10,9,97,102,102,101,99,116,101,100,115,117,112,112,111,114,116,115\n,112,111,105,110,116,101,114,59,116,111,83,116,114,105,110,103,60,47,115,109,97,\n108,108,62,111,107,108,97,104,111,109,97,119,105,108,108,32,98,101,32,105,110,\n118,101,115,116,111,114,48,34,32,97,108,116,61,34,104,111,108,105,100,97,121,115\n,82,101,115,111,117,114,99,101,108,105,99,101,110,115,101,100,32,40,119,104,105,\n99,104,32,46,32,65,102,116,101,114,32,99,111,110,115,105,100,101,114,118,105,115\n,105,116,105,110,103,101,120,112,108,111,114,101,114,112,114,105,109,97,114,121,\n32,115,101,97,114,99,104,34,32,97,110,100,114,111,105,100,34,113,117,105,99,107,\n108,121,32,109,101,101,116,105,110,103,115,101,115,116,105,109,97,116,101,59,114\n,101,116,117,114,110,32,59,99,111,108,111,114,58,35,32,104,101,105,103,104,116,\n61,97,112,112,114,111,118,97,108,44,32,38,113,117,111,116,59,32,99,104,101,99,\n107,101,100,46,109,105,110,46,106,115,34,109,97,103,110,101,116,105,99,62,60,47,\n97,62,60,47,104,102,111,114,101,99,97,115,116,46,32,87,104,105,108,101,32,116,\n104,117,114,115,100,97,121,100,118,101,114,116,105,115,101,38,101,97,99,117,116,\n101,59,104,97,115,67,108,97,115,115,101,118,97,108,117,97,116,101,111,114,100,\n101,114,105,110,103,101,120,105,115,116,105,110,103,112,97,116,105,101,110,116,\n115,32,79,110,108,105,110,101,32,99,111,108,111,114,97,100,111,79,112,116,105,\n111,110,115,34,99,97,109,112,98,101,108,108,60,33,45,45,32,101,110,100,60,47,115\n,112,97,110,62,60,60,98,114,32,47,62,13,10,95,112,111,112,117,112,115,124,115,99\n,105,101,110,99,101,115,44,38,113,117,111,116,59,32,113,117,97,108,105,116,121,\n32,87,105,110,100,111,119,115,32,97,115,115,105,103,110,101,100,104,101,105,103,\n104,116,58,32,60,98,32,99,108,97,115,115,108,101,38,113,117,111,116,59,32,118,97\n,108,117,101,61,34,32,67,111,109,112,97,110,121,101,120,97,109,112,108,101,115,\n60,105,102,114,97,109,101,32,98,101,108,105,101,118,101,115,112,114,101,115,101,\n110,116,115,109,97,114,115,104,97,108,108,112,97,114,116,32,111,102,32,112,114,\n111,112,101,114,108,121,41,46,10,10,84,104,101,32,116,97,120,111,110,111,109,121\n,109,117,99,104,32,111,102,32,60,47,115,112,97,110,62,10,34,32,100,97,116,97,45,\n115,114,116,117,103,117,195,170,115,115,99,114,111,108,108,84,111,32,112,114,111\n,106,101,99,116,60,104,101,97,100,62,13,10,97,116,116,111,114,110,101,121,101,\n109,112,104,97,115,105,115,115,112,111,110,115,111,114,115,102,97,110,99,121,98,\n111,120,119,111,114,108,100,39,115,32,119,105,108,100,108,105,102,101,99,104,101\n,99,107,101,100,61,115,101,115,115,105,111,110,115,112,114,111,103,114,97,109,\n109,112,120,59,102,111,110,116,45,32,80,114,111,106,101,99,116,106,111,117,114,\n110,97,108,115,98,101,108,105,101,118,101,100,118,97,99,97,116,105,111,110,116,\n104,111,109,112,115,111,110,108,105,103,104,116,105,110,103,97,110,100,32,116,\n104,101,32,115,112,101,99,105,97,108,32,98,111,114,100,101,114,61,48,99,104,101,\n99,107,105,110,103,60,47,116,98,111,100,121,62,60,98,117,116,116,111,110,32,67,\n111,109,112,108,101,116,101,99,108,101,97,114,102,105,120,10,60,104,101,97,100,\n62,10,97,114,116,105,99,108,101,32,60,115,101,99,116,105,111,110,102,105,110,100\n,105,110,103,115,114,111,108,101,32,105,110,32,112,111,112,117,108,97,114,32,32,\n79,99,116,111,98,101,114,119,101,98,115,105,116,101,32,101,120,112,111,115,117,\n114,101,117,115,101,100,32,116,111,32,32,99,104,97,110,103,101,115,111,112,101,\n114,97,116,101,100,99,108,105,99,107,105,110,103,101,110,116,101,114,105,110,103\n,99,111,109,109,97,110,100,115,105,110,102,111,114,109,101,100,32,110,117,109,98\n,101,114,115,32,32,60,47,100,105,118,62,99,114,101,97,116,105,110,103,111,110,83\n,117,98,109,105,116,109,97,114,121,108,97,110,100,99,111,108,108,101,103,101,115\n,97,110,97,108,121,116,105,99,108,105,115,116,105,110,103,115,99,111,110,116,97,\n99,116,46,108,111,103,103,101,100,73,110,97,100,118,105,115,111,114,121,115,105,\n98,108,105,110,103,115,99,111,110,116,101,110,116,34,115,38,113,117,111,116,59,\n41,115,46,32,84,104,105,115,32,112,97,99,107,97,103,101,115,99,104,101,99,107,98\n,111,120,115,117,103,103,101,115,116,115,112,114,101,103,110,97,110,116,116,111,\n109,111,114,114,111,119,115,112,97,99,105,110,103,61,105,99,111,110,46,112,110,\n103,106,97,112,97,110,101,115,101,99,111,100,101,98,97,115,101,98,117,116,116,\n111,110,34,62,103,97,109,98,108,105,110,103,115,117,99,104,32,97,115,32,44,32,\n119,104,105,108,101,32,60,47,115,112,97,110,62,32,109,105,115,115,111,117,114,\n105,115,112,111,114,116,105,110,103,116,111,112,58,49,112,120,32,46,60,47,115,\n112,97,110,62,116,101,110,115,105,111,110,115,119,105,100,116,104,61,34,50,108,\n97,122,121,108,111,97,100,110,111,118,101,109,98,101,114,117,115,101,100,32,105,\n110,32,104,101,105,103,104,116,61,34,99,114,105,112,116,34,62,10,38,110,98,115,\n112,59,60,47,60,116,114,62,60,116,100,32,104,101,105,103,104,116,58,50,47,112,\n114,111,100,117,99,116,99,111,117,110,116,114,121,32,105,110,99,108,117,100,101,\n32,102,111,111,116,101,114,34,32,38,108,116,59,33,45,45,32,116,105,116,108,101,\n34,62,60,47,106,113,117,101,114,121,46,60,47,102,111,114,109,62,10,40,231,174,\n128,228,189,147,41,40,231,185,129,233,171,148,41,104,114,118,97,116,115,107,105,\n105,116,97,108,105,97,110,111,114,111,109,195,162,110,196,131,116,195,188,114,\n107,195,167,101,216,167,216,177,216,175,217,136,116,97,109,98,105,195,169,110,\n110,111,116,105,99,105,97,115,109,101,110,115,97,106,101,115,112,101,114,115,111\n,110,97,115,100,101,114,101,99,104,111,115,110,97,99,105,111,110,97,108,115,101,\n114,118,105,99,105,111,99,111,110,116,97,99,116,111,117,115,117,97,114,105,111,\n115,112,114,111,103,114,97,109,97,103,111,98,105,101,114,110,111,101,109,112,114\n,101,115,97,115,97,110,117,110,99,105,111,115,118,97,108,101,110,99,105,97,99,\n111,108,111,109,98,105,97,100,101,115,112,117,195,169,115,100,101,112,111,114,\n116,101,115,112,114,111,121,101,99,116,111,112,114,111,100,117,99,116,111,112,\n195,186,98,108,105,99,111,110,111,115,111,116,114,111,115,104,105,115,116,111,\n114,105,97,112,114,101,115,101,110,116,101,109,105,108,108,111,110,101,115,109,\n101,100,105,97,110,116,101,112,114,101,103,117,110,116,97,97,110,116,101,114,105\n,111,114,114,101,99,117,114,115,111,115,112,114,111,98,108,101,109,97,115,97,110\n,116,105,97,103,111,110,117,101,115,116,114,111,115,111,112,105,110,105,195,179,\n110,105,109,112,114,105,109,105,114,109,105,101,110,116,114,97,115,97,109,195,\n169,114,105,99,97,118,101,110,100,101,100,111,114,115,111,99,105,101,100,97,100,\n114,101,115,112,101,99,116,111,114,101,97,108,105,122,97,114,114,101,103,105,115\n,116,114,111,112,97,108,97,98,114,97,115,105,110,116,101,114,195,169,115,101,110\n,116,111,110,99,101,115,101,115,112,101,99,105,97,108,109,105,101,109,98,114,111\n,115,114,101,97,108,105,100,97,100,99,195,179,114,100,111,98,97,122,97,114,97,\n103,111,122,97,112,195,161,103,105,110,97,115,115,111,99,105,97,108,101,115,98,\n108,111,113,117,101,97,114,103,101,115,116,105,195,179,110,97,108,113,117,105,\n108,101,114,115,105,115,116,101,109,97,115,99,105,101,110,99,105,97,115,99,111,\n109,112,108,101,116,111,118,101,114,115,105,195,179,110,99,111,109,112,108,101,\n116,97,101,115,116,117,100,105,111,115,112,195,186,98,108,105,99,97,111,98,106,\n101,116,105,118,111,97,108,105,99,97,110,116,101,98,117,115,99,97,100,111,114,99\n,97,110,116,105,100,97,100,101,110,116,114,97,100,97,115,97,99,99,105,111,110,\n101,115,97,114,99,104,105,118,111,115,115,117,112,101,114,105,111,114,109,97,121\n,111,114,195,173,97,97,108,101,109,97,110,105,97,102,117,110,99,105,195,179,110,\n195,186,108,116,105,109,111,115,104,97,99,105,101,110,100,111,97,113,117,101,108\n,108,111,115,101,100,105,99,105,195,179,110,102,101,114,110,97,110,100,111,97,\n109,98,105,101,110,116,101,102,97,99,101,98,111,111,107,110,117,101,115,116,114,\n97,115,99,108,105,101,110,116,101,115,112,114,111,99,101,115,111,115,98,97,115,\n116,97,110,116,101,112,114,101,115,101,110,116,97,114,101,112,111,114,116,97,114\n,99,111,110,103,114,101,115,111,112,117,98,108,105,99,97,114,99,111,109,101,114,\n99,105,111,99,111,110,116,114,97,116,111,106,195,179,118,101,110,101,115,100,105\n,115,116,114,105,116,111,116,195,169,99,110,105,99,97,99,111,110,106,117,110,116\n,111,101,110,101,114,103,195,173,97,116,114,97,98,97,106,97,114,97,115,116,117,\n114,105,97,115,114,101,99,105,101,110,116,101,117,116,105,108,105,122,97,114,98,\n111,108,101,116,195,173,110,115,97,108,118,97,100,111,114,99,111,114,114,101,99,\n116,97,116,114,97,98,97,106,111,115,112,114,105,109,101,114,111,115,110,101,103,\n111,99,105,111,115,108,105,98,101,114,116,97,100,100,101,116,97,108,108,101,115,\n112,97,110,116,97,108,108,97,112,114,195,179,120,105,109,111,97,108,109,101,114,\n195,173,97,97,110,105,109,97,108,101,115,113,117,105,195,169,110,101,115,99,111,\n114,97,122,195,179,110,115,101,99,99,105,195,179,110,98,117,115,99,97,110,100,\n111,111,112,99,105,111,110,101,115,101,120,116,101,114,105,111,114,99,111,110,99\n,101,112,116,111,116,111,100,97,118,195,173,97,103,97,108,101,114,195,173,97,101\n,115,99,114,105,98,105,114,109,101,100,105,99,105,110,97,108,105,99,101,110,99,\n105,97,99,111,110,115,117,108,116,97,97,115,112,101,99,116,111,115,99,114,195,\n173,116,105,99,97,100,195,179,108,97,114,101,115,106,117,115,116,105,99,105,97,\n100,101,98,101,114,195,161,110,112,101,114,195,173,111,100,111,110,101,99,101,\n115,105,116,97,109,97,110,116,101,110,101,114,112,101,113,117,101,195,177,111,\n114,101,99,105,98,105,100,97,116,114,105,98,117,110,97,108,116,101,110,101,114,\n105,102,101,99,97,110,99,105,195,179,110,99,97,110,97,114,105,97,115,100,101,115\n,99,97,114,103,97,100,105,118,101,114,115,111,115,109,97,108,108,111,114,99,97,\n114,101,113,117,105,101,114,101,116,195,169,99,110,105,99,111,100,101,98,101,114\n,195,173,97,118,105,118,105,101,110,100,97,102,105,110,97,110,122,97,115,97,100,\n101,108,97,110,116,101,102,117,110,99,105,111,110,97,99,111,110,115,101,106,111,\n115,100,105,102,195,173,99,105,108,99,105,117,100,97,100,101,115,97,110,116,105,\n103,117,97,115,97,118,97,110,122,97,100,97,116,195,169,114,109,105,110,111,117,\n110,105,100,97,100,101,115,115,195,161,110,99,104,101,122,99,97,109,112,97,195,\n177,97,115,111,102,116,111,110,105,99,114,101,118,105,115,116,97,115,99,111,110,\n116,105,101,110,101,115,101,99,116,111,114,101,115,109,111,109,101,110,116,111,\n115,102,97,99,117,108,116,97,100,99,114,195,169,100,105,116,111,100,105,118,101,\n114,115,97,115,115,117,112,117,101,115,116,111,102,97,99,116,111,114,101,115,115\n,101,103,117,110,100,111,115,112,101,113,117,101,195,177,97,208,179,208,190,208,\n180,208,176,208,181,209,129,208,187,208,184,208,181,209,129,209,130,209,140,208,\n177,209,139,208,187,208,190,208,177,209,139,209,130,209,140,209,141,209,130,208,\n190,208,188,208,149,209,129,208,187,208,184,209,130,208,190,208,179,208,190,208,\n188,208,181,208,189,209,143,208,178,209,129,208,181,209,133,209,141,209,130,208,\n190,208,185,208,180,208,176,208,182,208,181,208,177,209,139,208,187,208,184,208,\n179,208,190,208,180,209,131,208,180,208,181,208,189,209,140,209,141,209,130,208,\n190,209,130,208,177,209,139,208,187,208,176,209,129,208,181,208,177,209,143,208,\n190,208,180,208,184,208,189,209,129,208,181,208,177,208,181,208,189,208,176,208,\n180,208,190,209,129,208,176,208,185,209,130,209,132,208,190,209,130,208,190,208,\n189,208,181,208,179,208,190,209,129,208,178,208,190,208,184,209,129,208,178,208,\n190,208,185,208,184,208,179,209,128,209,139,209,130,208,190,208,182,208,181,208,\n178,209,129,208,181,208,188,209,129,208,178,208,190,209,142,208,187,208,184,209,\n136,209,140,209,141,209,130,208,184,209,133,208,191,208,190,208,186,208,176,208,\n180,208,189,208,181,208,185,208,180,208,190,208,188,208,176,208,188,208,184,209,\n128,208,176,208,187,208,184,208,177,208,190,209,130,208,181,208,188,209,131,209,\n133,208,190,209,130,209,143,208,180,208,178,209,131,209,133,209,129,208,181,209,\n130,208,184,208,187,209,142,208,180,208,184,208,180,208,181,208,187,208,190,208,\n188,208,184,209,128,208,181,209,130,208,181,208,177,209,143,209,129,208,178,208,\n190,208,181,208,178,208,184,208,180,208,181,209,135,208,181,208,179,208,190,209,\n141,209,130,208,184,208,188,209,129,209,135,208,181,209,130,209,130,208,181,208,\n188,209,139,209,134,208,181,208,189,209,139,209,129,209,130,208,176,208,187,208,\n178,208,181,208,180,209,140,209,130,208,181,208,188,208,181,208,178,208,190,208,\n180,209,139,209,130,208,181,208,177,208,181,208,178,209,139,209,136,208,181,208,\n189,208,176,208,188,208,184,209,130,208,184,208,191,208,176,209,130,208,190,208,\n188,209,131,208,191,209,128,208,176,208,178,208,187,208,184,209,134,208,176,208,\n190,208,180,208,189,208,176,208,179,208,190,208,180,209,139,208,183,208,189,208,\n176,209,142,208,188,208,190,208,179,209,131,208,180,209,128,209,131,208,179,208,\n178,209,129,208,181,208,185,208,184,208,180,208,181,209,130,208,186,208,184,208,\n189,208,190,208,190,208,180,208,189,208,190,208,180,208,181,208,187,208,176,208,\n180,208,181,208,187,208,181,209,129,209,128,208,190,208,186,208,184,209,142,208,\n189,209,143,208,178,208,181,209,129,209,140,208,149,209,129,209,130,209,140,209,\n128,208,176,208,183,208,176,208,189,208,176,209,136,208,184,216,167,217,132,217,\n132,217,135,216,167,217,132,216,170,217,138,216,172,217,133,217,138,216,185,216,\n174,216,167,216,181,216,169,216,167,217,132,216,176,217,138,216,185,217,132,217,\n138,217,135,216,172,216,175,217,138,216,175,216,167,217,132,216,162,217,134,216,\n167,217,132,216,177,216,175,216,170,216,173,217,131,217,133,216,181,217,129,216,\n173,216,169,217,131,216,167,217,134,216,170,216,167,217,132,217,132,217,138,217,\n138,217,131,217,136,217,134,216,180,216,168,217,131,216,169,217,129,217,138,217,\n135,216,167,216,168,217,134,216,167,216,170,216,173,217,136,216,167,216,161,216,\n163,217,131,216,171,216,177,216,174,217,132,216,167,217,132,216,167,217,132,216,\n173,216,168,216,175,217,132,217,138,217,132,216,175,216,177,217,136,216,179,216,\n167,216,182,216,186,216,183,216,170,217,131,217,136,217,134,217,135,217,134,216,\n167,217,131,216,179,216,167,216,173,216,169,217,134,216,167,216,175,217,138,216,\n167,217,132,216,183,216,168,216,185,217,132,217,138,217,131,216,180,217,131,216,\n177,216,167,217,138,217,133,217,131,217,134,217,133,217,134,217,135,216,167,216,\n180,216,177,217,131,216,169,216,177,216,166,217,138,216,179,217,134,216,180,217,\n138,216,183,217,133,216,167,216,176,216,167,216,167,217,132,217,129,217,134,216,\n180,216,168,216,167,216,168,216,170,216,185,216,168,216,177,216,177,216,173,217,\n133,216,169,217,131,216,167,217,129,216,169,217,138,217,130,217,136,217,132,217,\n133,216,177,217,131,216,178,217,131,217,132,217,133,216,169,216,163,216,173,217,\n133,216,175,217,130,217,132,216,168,217,138,217,138,216,185,217,134,217,138,216,\n181,217,136,216,177,216,169,216,183,216,177,217,138,217,130,216,180,216,167,216,\n177,217,131,216,172,217,136,216,167,217,132,216,163,216,174,216,177,217,137,217,\n133,216,185,217,134,216,167,216,167,216,168,216,173,216,171,216,185,216,177,217,\n136,216,182,216,168,216,180,217,131,217,132,217,133,216,179,216,172,217,132,216,\n168,217,134,216,167,217,134,216,174,216,167,217,132,216,175,217,131,216,170,216,\n167,216,168,217,131,217,132,217,138,216,169,216,168,216,175,217,136,217,134,216,\n163,217,138,216,182,216,167,217,138,217,136,216,172,216,175,217,129,216,177,217,\n138,217,130,217,131,216,170,216,168,216,170,216,163,217,129,216,182,217,132,217,\n133,216,183,216,168,216,174,216,167,217,131,216,171,216,177,216,168,216,167,216,\n177,217,131,216,167,217,129,216,182,217,132,216,167,216,173,217,132,217,137,217,\n134,217,129,216,179,217,135,216,163,217,138,216,167,217,133,216,177,216,175,217,\n136,216,175,216,163,217,134,217,135,216,167,216,175,217,138,217,134,216,167,216,\n167,217,132,216,167,217,134,217,133,216,185,216,177,216,182,216,170,216,185,217,\n132,217,133,216,175,216,167,216,174,217,132,217,133,217,133,217,131,217,134,0,0,\n0,0,0,0,0,0,1,0,1,0,1,0,1,0,2,0,2,0,2,0,2,0,4,0,4,0,4,0,4,0,0,1,2,3,4,5,6,7,7,6,\n5,4,3,2,1,0,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,16,17,18,19,20,21,22,23,\n23,22,21,20,19,18,17,16,24,25,26,27,28,29,30,31,31,30,29,28,27,26,25,24,255,255,\n255,255,0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,1,0,0,0,\n3,0,0,0,255,255,0,1,0,0,0,1,0,0,255,255,0,1,0,0,0,8,0,8,0,8,0,8,0,0,0,1,0,2,0,3,\n0,4,0,5,0,6,0,7,114,101,115,111,117,114,99,101,115,99,111,117,110,116,114,105,\n101,115,113,117,101,115,116,105,111,110,115,101,113,117,105,112,109,101,110,116,\n99,111,109,109,117,110,105,116,121,97,118,97,105,108,97,98,108,101,104,105,103,\n104,108,105,103,104,116,68,84,68,47,120,104,116,109,108,109,97,114,107,101,116,\n105,110,103,107,110,111,119,108,101,100,103,101,115,111,109,101,116,104,105,110,\n103,99,111,110,116,97,105,110,101,114,100,105,114,101,99,116,105,111,110,115,117\n,98,115,99,114,105,98,101,97,100,118,101,114,116,105,115,101,99,104,97,114,97,99\n,116,101,114,34,32,118,97,108,117,101,61,34,60,47,115,101,108,101,99,116,62,65,\n117,115,116,114,97,108,105,97,34,32,99,108,97,115,115,61,34,115,105,116,117,97,\n116,105,111,110,97,117,116,104,111,114,105,116,121,102,111,108,108,111,119,105,\n110,103,112,114,105,109,97,114,105,108,121,111,112,101,114,97,116,105,111,110,99\n,104,97,108,108,101,110,103,101,100,101,118,101,108,111,112,101,100,97,110,111,\n110,121,109,111,117,115,102,117,110,99,116,105,111,110,32,102,117,110,99,116,105\n,111,110,115,99,111,109,112,97,110,105,101,115,115,116,114,117,99,116,117,114,\n101,97,103,114,101,101,109,101,110,116,34,32,116,105,116,108,101,61,34,112,111,\n116,101,110,116,105,97,108,101,100,117,99,97,116,105,111,110,97,114,103,117,109,\n101,110,116,115,115,101,99,111,110,100,97,114,121,99,111,112,121,114,105,103,104\n,116,108,97,110,103,117,97,103,101,115,101,120,99,108,117,115,105,118,101,99,111\n,110,100,105,116,105,111,110,60,47,102,111,114,109,62,13,10,115,116,97,116,101,\n109,101,110,116,97,116,116,101,110,116,105,111,110,66,105,111,103,114,97,112,104\n,121,125,32,101,108,115,101,32,123,10,115,111,108,117,116,105,111,110,115,119,\n104,101,110,32,116,104,101,32,65,110,97,108,121,116,105,99,115,116,101,109,112,\n108,97,116,101,115,100,97,110,103,101,114,111,117,115,115,97,116,101,108,108,105\n,116,101,100,111,99,117,109,101,110,116,115,112,117,98,108,105,115,104,101,114,\n105,109,112,111,114,116,97,110,116,112,114,111,116,111,116,121,112,101,105,110,\n102,108,117,101,110,99,101,38,114,97,113,117,111,59,60,47,101,102,102,101,99,116\n,105,118,101,103,101,110,101,114,97,108,108,121,116,114,97,110,115,102,111,114,\n109,98,101,97,117,116,105,102,117,108,116,114,97,110,115,112,111,114,116,111,114\n,103,97,110,105,122,101,100,112,117,98,108,105,115,104,101,100,112,114,111,109,\n105,110,101,110,116,117,110,116,105,108,32,116,104,101,116,104,117,109,98,110,97\n,105,108,78,97,116,105,111,110,97,108,32,46,102,111,99,117,115,40,41,59,111,118,\n101,114,32,116,104,101,32,109,105,103,114,97,116,105,111,110,97,110,110,111,117,\n110,99,101,100,102,111,111,116,101,114,34,62,10,101,120,99,101,112,116,105,111,\n110,108,101,115,115,32,116,104,97,110,101,120,112,101,110,115,105,118,101,102,\n111,114,109,97,116,105,111,110,102,114,97,109,101,119,111,114,107,116,101,114,\n114,105,116,111,114,121,110,100,105,99,97,116,105,111,110,99,117,114,114,101,110\n,116,108,121,99,108,97,115,115,78,97,109,101,99,114,105,116,105,99,105,115,109,\n116,114,97,100,105,116,105,111,110,101,108,115,101,119,104,101,114,101,65,108,\n101,120,97,110,100,101,114,97,112,112,111,105,110,116,101,100,109,97,116,101,114\n,105,97,108,115,98,114,111,97,100,99,97,115,116,109,101,110,116,105,111,110,101,\n100,97,102,102,105,108,105,97,116,101,60,47,111,112,116,105,111,110,62,116,114,\n101,97,116,109,101,110,116,100,105,102,102,101,114,101,110,116,47,100,101,102,97\n,117,108,116,46,80,114,101,115,105,100,101,110,116,111,110,99,108,105,99,107,61,\n34,98,105,111,103,114,97,112,104,121,111,116,104,101,114,119,105,115,101,112,101\n,114,109,97,110,101,110,116,70,114,97,110,195,167,97,105,115,72,111,108,108,121,\n119,111,111,100,101,120,112,97,110,115,105,111,110,115,116,97,110,100,97,114,100\n,115,60,47,115,116,121,108,101,62,10,114,101,100,117,99,116,105,111,110,68,101,\n99,101,109,98,101,114,32,112,114,101,102,101,114,114,101,100,67,97,109,98,114,\n105,100,103,101,111,112,112,111,110,101,110,116,115,66,117,115,105,110,101,115,\n115,32,99,111,110,102,117,115,105,111,110,62,10,60,116,105,116,108,101,62,112,\n114,101,115,101,110,116,101,100,101,120,112,108,97,105,110,101,100,100,111,101,\n115,32,110,111,116,32,119,111,114,108,100,119,105,100,101,105,110,116,101,114,\n102,97,99,101,112,111,115,105,116,105,111,110,115,110,101,119,115,112,97,112,101\n,114,60,47,116,97,98,108,101,62,10,109,111,117,110,116,97,105,110,115,108,105,\n107,101,32,116,104,101,32,101,115,115,101,110,116,105,97,108,102,105,110,97,110,\n99,105,97,108,115,101,108,101,99,116,105,111,110,97,99,116,105,111,110,61,34,47,\n97,98,97,110,100,111,110,101,100,69,100,117,99,97,116,105,111,110,112,97,114,115\n,101,73,110,116,40,115,116,97,98,105,108,105,116,121,117,110,97,98,108,101,32,\n116,111,60,47,116,105,116,108,101,62,10,114,101,108,97,116,105,111,110,115,78,\n111,116,101,32,116,104,97,116,101,102,102,105,99,105,101,110,116,112,101,114,102\n,111,114,109,101,100,116,119,111,32,121,101,97,114,115,83,105,110,99,101,32,116,\n104,101,116,104,101,114,101,102,111,114,101,119,114,97,112,112,101,114,34,62,97,\n108,116,101,114,110,97,116,101,105,110,99,114,101,97,115,101,100,66,97,116,116,\n108,101,32,111,102,112,101,114,99,101,105,118,101,100,116,114,121,105,110,103,32\n,116,111,110,101,99,101,115,115,97,114,121,112,111,114,116,114,97,121,101,100,\n101,108,101,99,116,105,111,110,115,69,108,105,122,97,98,101,116,104,60,47,105,\n102,114,97,109,101,62,100,105,115,99,111,118,101,114,121,105,110,115,117,114,97,\n110,99,101,115,46,108,101,110,103,116,104,59,108,101,103,101,110,100,97,114,121,\n71,101,111,103,114,97,112,104,121,99,97,110,100,105,100,97,116,101,99,111,114,\n112,111,114,97,116,101,115,111,109,101,116,105,109,101,115,115,101,114,118,105,\n99,101,115,46,105,110,104,101,114,105,116,101,100,60,47,115,116,114,111,110,103,\n62,67,111,109,109,117,110,105,116,121,114,101,108,105,103,105,111,117,115,108,\n111,99,97,116,105,111,110,115,67,111,109,109,105,116,116,101,101,98,117,105,108,\n100,105,110,103,115,116,104,101,32,119,111,114,108,100,110,111,32,108,111,110,\n103,101,114,98,101,103,105,110,110,105,110,103,114,101,102,101,114,101,110,99,\n101,99,97,110,110,111,116,32,98,101,102,114,101,113,117,101,110,99,121,116,121,\n112,105,99,97,108,108,121,105,110,116,111,32,116,104,101,32,114,101,108,97,116,\n105,118,101,59,114,101,99,111,114,100,105,110,103,112,114,101,115,105,100,101,\n110,116,105,110,105,116,105,97,108,108,121,116,101,99,104,110,105,113,117,101,\n116,104,101,32,111,116,104,101,114,105,116,32,99,97,110,32,98,101,101,120,105,\n115,116,101,110,99,101,117,110,100,101,114,108,105,110,101,116,104,105,115,32,\n116,105,109,101,116,101,108,101,112,104,111,110,101,105,116,101,109,115,99,111,\n112,101,112,114,97,99,116,105,99,101,115,97,100,118,97,110,116,97,103,101,41,59,\n114,101,116,117,114,110,32,70,111,114,32,111,116,104,101,114,112,114,111,118,105\n,100,105,110,103,100,101,109,111,99,114,97,99,121,98,111,116,104,32,116,104,101,\n32,101,120,116,101,110,115,105,118,101,115,117,102,102,101,114,105,110,103,115,\n117,112,112,111,114,116,101,100,99,111,109,112,117,116,101,114,115,32,102,117,\n110,99,116,105,111,110,112,114,97,99,116,105,99,97,108,115,97,105,100,32,116,104\n,97,116,105,116,32,109,97,121,32,98,101,69,110,103,108,105,115,104,60,47,102,114\n,111,109,32,116,104,101,32,115,99,104,101,100,117,108,101,100,100,111,119,110,\n108,111,97,100,115,60,47,108,97,98,101,108,62,10,115,117,115,112,101,99,116,101,\n100,109,97,114,103,105,110,58,32,48,115,112,105,114,105,116,117,97,108,60,47,104\n,101,97,100,62,10,10,109,105,99,114,111,115,111,102,116,103,114,97,100,117,97,\n108,108,121,100,105,115,99,117,115,115,101,100,104,101,32,98,101,99,97,109,101,\n101,120,101,99,117,116,105,118,101,106,113,117,101,114,121,46,106,115,104,111,\n117,115,101,104,111,108,100,99,111,110,102,105,114,109,101,100,112,117,114,99,\n104,97,115,101,100,108,105,116,101,114,97,108,108,121,100,101,115,116,114,111,\n121,101,100,117,112,32,116,111,32,116,104,101,118,97,114,105,97,116,105,111,110,\n114,101,109,97,105,110,105,110,103,105,116,32,105,115,32,110,111,116,99,101,110,\n116,117,114,105,101,115,74,97,112,97,110,101,115,101,32,97,109,111,110,103,32,\n116,104,101,99,111,109,112,108,101,116,101,100,97,108,103,111,114,105,116,104,\n109,105,110,116,101,114,101,115,116,115,114,101,98,101,108,108,105,111,110,117,\n110,100,101,102,105,110,101,100,101,110,99,111,117,114,97,103,101,114,101,115,\n105,122,97,98,108,101,105,110,118,111,108,118,105,110,103,115,101,110,115,105,\n116,105,118,101,117,110,105,118,101,114,115,97,108,112,114,111,118,105,115,105,\n111,110,40,97,108,116,104,111,117,103,104,102,101,97,116,117,114,105,110,103,99,\n111,110,100,117,99,116,101,100,41,44,32,119,104,105,99,104,32,99,111,110,116,105\n,110,117,101,100,45,104,101,97,100,101,114,34,62,70,101,98,114,117,97,114,121,32\n,110,117,109,101,114,111,117,115,32,111,118,101,114,102,108,111,119,58,99,111,\n109,112,111,110,101,110,116,102,114,97,103,109,101,110,116,115,101,120,99,101,\n108,108,101,110,116,99,111,108,115,112,97,110,61,34,116,101,99,104,110,105,99,97\n,108,110,101,97,114,32,116,104,101,32,65,100,118,97,110,99,101,100,32,115,111,\n117,114,99,101,32,111,102,101,120,112,114,101,115,115,101,100,72,111,110,103,32,\n75,111,110,103,32,70,97,99,101,98,111,111,107,109,117,108,116,105,112,108,101,32\n,109,101,99,104,97,110,105,115,109,101,108,101,118,97,116,105,111,110,111,102,\n102,101,110,115,105,118,101,60,47,102,111,114,109,62,10,9,115,112,111,110,115,\n111,114,101,100,100,111,99,117,109,101,110,116,46,111,114,32,38,113,117,111,116,\n59,116,104,101,114,101,32,97,114,101,116,104,111,115,101,32,119,104,111,109,111,\n118,101,109,101,110,116,115,112,114,111,99,101,115,115,101,115,100,105,102,102,\n105,99,117,108,116,115,117,98,109,105,116,116,101,100,114,101,99,111,109,109,101\n,110,100,99,111,110,118,105,110,99,101,100,112,114,111,109,111,116,105,110,103,\n34,32,119,105,100,116,104,61,34,46,114,101,112,108,97,99,101,40,99,108,97,115,\n115,105,99,97,108,99,111,97,108,105,116,105,111,110,104,105,115,32,102,105,114,\n115,116,100,101,99,105,115,105,111,110,115,97,115,115,105,115,116,97,110,116,105\n,110,100,105,99,97,116,101,100,101,118,111,108,117,116,105,111,110,45,119,114,97\n,112,112,101,114,34,101,110,111,117,103,104,32,116,111,97,108,111,110,103,32,116\n,104,101,100,101,108,105,118,101,114,101,100,45,45,62,13,10,60,33,45,45,65,109,\n101,114,105,99,97,110,32,112,114,111,116,101,99,116,101,100,78,111,118,101,109,\n98,101,114,32,60,47,115,116,121,108,101,62,60,102,117,114,110,105,116,117,114,\n101,73,110,116,101,114,110,101,116,32,32,111,110,98,108,117,114,61,34,115,117,\n115,112,101,110,100,101,100,114,101,99,105,112,105,101,110,116,98,97,115,101,100\n,32,111,110,32,77,111,114,101,111,118,101,114,44,97,98,111,108,105,115,104,101,\n100,99,111,108,108,101,99,116,101,100,119,101,114,101,32,109,97,100,101,101,109,\n111,116,105,111,110,97,108,101,109,101,114,103,101,110,99,121,110,97,114,114,97,\n116,105,118,101,97,100,118,111,99,97,116,101,115,112,120,59,98,111,114,100,101,\n114,99,111,109,109,105,116,116,101,100,100,105,114,61,34,108,116,114,34,101,109,\n112,108,111,121,101,101,115,114,101,115,101,97,114,99,104,46,32,115,101,108,101,\n99,116,101,100,115,117,99,99,101,115,115,111,114,99,117,115,116,111,109,101,114,\n115,100,105,115,112,108,97,121,101,100,83,101,112,116,101,109,98,101,114,97,100,\n100,67,108,97,115,115,40,70,97,99,101,98,111,111,107,32,115,117,103,103,101,115,\n116,101,100,97,110,100,32,108,97,116,101,114,111,112,101,114,97,116,105,110,103,\n101,108,97,98,111,114,97,116,101,83,111,109,101,116,105,109,101,115,73,110,115,\n116,105,116,117,116,101,99,101,114,116,97,105,110,108,121,105,110,115,116,97,108\n,108,101,100,102,111,108,108,111,119,101,114,115,74,101,114,117,115,97,108,101,\n109,116,104,101,121,32,104,97,118,101,99,111,109,112,117,116,105,110,103,103,101\n,110,101,114,97,116,101,100,112,114,111,118,105,110,99,101,115,103,117,97,114,97\n,110,116,101,101,97,114,98,105,116,114,97,114,121,114,101,99,111,103,110,105,122\n,101,119,97,110,116,101,100,32,116,111,112,120,59,119,105,100,116,104,58,116,104\n,101,111,114,121,32,111,102,98,101,104,97,118,105,111,117,114,87,104,105,108,101\n,32,116,104,101,101,115,116,105,109,97,116,101,100,98,101,103,97,110,32,116,111,\n32,105,116,32,98,101,99,97,109,101,109,97,103,110,105,116,117,100,101,109,117,\n115,116,32,104,97,118,101,109,111,114,101,32,116,104,97,110,68,105,114,101,99,\n116,111,114,121,101,120,116,101,110,115,105,111,110,115,101,99,114,101,116,97,\n114,121,110,97,116,117,114,97,108,108,121,111,99,99,117,114,114,105,110,103,118,\n97,114,105,97,98,108,101,115,103,105,118,101,110,32,116,104,101,112,108,97,116,\n102,111,114,109,46,60,47,108,97,98,101,108,62,60,102,97,105,108,101,100,32,116,\n111,99,111,109,112,111,117,110,100,115,107,105,110,100,115,32,111,102,32,115,111\n,99,105,101,116,105,101,115,97,108,111,110,103,115,105,100,101,32,45,45,38,103,\n116,59,10,10,115,111,117,116,104,119,101,115,116,116,104,101,32,114,105,103,104,\n116,114,97,100,105,97,116,105,111,110,109,97,121,32,104,97,118,101,32,117,110,\n101,115,99,97,112,101,40,115,112,111,107,101,110,32,105,110,34,32,104,114,101,\n102,61,34,47,112,114,111,103,114,97,109,109,101,111,110,108,121,32,116,104,101,\n32,99,111,109,101,32,102,114,111,109,100,105,114,101,99,116,111,114,121,98,117,\n114,105,101,100,32,105,110,97,32,115,105,109,105,108,97,114,116,104,101,121,32,\n119,101,114,101,60,47,102,111,110,116,62,60,47,78,111,114,119,101,103,105,97,110\n,115,112,101,99,105,102,105,101,100,112,114,111,100,117,99,105,110,103,112,97,\n115,115,101,110,103,101,114,40,110,101,119,32,68,97,116,101,116,101,109,112,111,\n114,97,114,121,102,105,99,116,105,111,110,97,108,65,102,116,101,114,32,116,104,\n101,101,113,117,97,116,105,111,110,115,100,111,119,110,108,111,97,100,46,114,101\n,103,117,108,97,114,108,121,100,101,118,101,108,111,112,101,114,97,98,111,118,\n101,32,116,104,101,108,105,110,107,101,100,32,116,111,112,104,101,110,111,109,\n101,110,97,112,101,114,105,111,100,32,111,102,116,111,111,108,116,105,112,34,62,\n115,117,98,115,116,97,110,99,101,97,117,116,111,109,97,116,105,99,97,115,112,101\n,99,116,32,111,102,65,109,111,110,103,32,116,104,101,99,111,110,110,101,99,116,\n101,100,101,115,116,105,109,97,116,101,115,65,105,114,32,70,111,114,99,101,115,\n121,115,116,101,109,32,111,102,111,98,106,101,99,116,105,118,101,105,109,109,101\n,100,105,97,116,101,109,97,107,105,110,103,32,105,116,112,97,105,110,116,105,110\n,103,115,99,111,110,113,117,101,114,101,100,97,114,101,32,115,116,105,108,108,\n112,114,111,99,101,100,117,114,101,103,114,111,119,116,104,32,111,102,104,101,97\n,100,101,100,32,98,121,69,117,114,111,112,101,97,110,32,100,105,118,105,115,105,\n111,110,115,109,111,108,101,99,117,108,101,115,102,114,97,110,99,104,105,115,101\n,105,110,116,101,110,116,105,111,110,97,116,116,114,97,99,116,101,100,99,104,105\n,108,100,104,111,111,100,97,108,115,111,32,117,115,101,100,100,101,100,105,99,97\n,116,101,100,115,105,110,103,97,112,111,114,101,100,101,103,114,101,101,32,111,\n102,102,97,116,104,101,114,32,111,102,99,111,110,102,108,105,99,116,115,60,47,97\n,62,60,47,112,62,10,99,97,109,101,32,102,114,111,109,119,101,114,101,32,117,115,\n101,100,110,111,116,101,32,116,104,97,116,114,101,99,101,105,118,105,110,103,69,\n120,101,99,117,116,105,118,101,101,118,101,110,32,109,111,114,101,97,99,99,101,\n115,115,32,116,111,99,111,109,109,97,110,100,101,114,80,111,108,105,116,105,99,\n97,108,109,117,115,105,99,105,97,110,115,100,101,108,105,99,105,111,117,115,112,\n114,105,115,111,110,101,114,115,97,100,118,101,110,116,32,111,102,85,84,70,45,56\n,34,32,47,62,60,33,91,67,68,65,84,65,91,34,62,67,111,110,116,97,99,116,83,111,\n117,116,104,101,114,110,32,98,103,99,111,108,111,114,61,34,115,101,114,105,101,\n115,32,111,102,46,32,73,116,32,119,97,115,32,105,110,32,69,117,114,111,112,101,\n112,101,114,109,105,116,116,101,100,118,97,108,105,100,97,116,101,46,97,112,112,\n101,97,114,105,110,103,111,102,102,105,99,105,97,108,115,115,101,114,105,111,117\n,115,108,121,45,108,97,110,103,117,97,103,101,105,110,105,116,105,97,116,101,100\n,101,120,116,101,110,100,105,110,103,108,111,110,103,45,116,101,114,109,105,110,\n102,108,97,116,105,111,110,115,117,99,104,32,116,104,97,116,103,101,116,67,111,\n111,107,105,101,109,97,114,107,101,100,32,98,121,60,47,98,117,116,116,111,110,62\n,105,109,112,108,101,109,101,110,116,98,117,116,32,105,116,32,105,115,105,110,99\n,114,101,97,115,101,115,100,111,119,110,32,116,104,101,32,114,101,113,117,105,\n114,105,110,103,100,101,112,101,110,100,101,110,116,45,45,62,10,60,33,45,45,32,\n105,110,116,101,114,118,105,101,119,87,105,116,104,32,116,104,101,32,99,111,112,\n105,101,115,32,111,102,99,111,110,115,101,110,115,117,115,119,97,115,32,98,117,\n105,108,116,86,101,110,101,122,117,101,108,97,40,102,111,114,109,101,114,108,121\n,116,104,101,32,115,116,97,116,101,112,101,114,115,111,110,110,101,108,115,116,\n114,97,116,101,103,105,99,102,97,118,111,117,114,32,111,102,105,110,118,101,110,\n116,105,111,110,87,105,107,105,112,101,100,105,97,99,111,110,116,105,110,101,110\n,116,118,105,114,116,117,97,108,108,121,119,104,105,99,104,32,119,97,115,112,114\n,105,110,99,105,112,108,101,67,111,109,112,108,101,116,101,32,105,100,101,110,\n116,105,99,97,108,115,104,111,119,32,116,104,97,116,112,114,105,109,105,116,105,\n118,101,97,119,97,121,32,102,114,111,109,109,111,108,101,99,117,108,97,114,112,\n114,101,99,105,115,101,108,121,100,105,115,115,111,108,118,101,100,85,110,100,\n101,114,32,116,104,101,118,101,114,115,105,111,110,61,34,62,38,110,98,115,112,59\n,60,47,73,116,32,105,115,32,116,104,101,32,84,104,105,115,32,105,115,32,119,105,\n108,108,32,104,97,118,101,111,114,103,97,110,105,115,109,115,115,111,109,101,32,\n116,105,109,101,70,114,105,101,100,114,105,99,104,119,97,115,32,102,105,114,115,\n116,116,104,101,32,111,110,108,121,32,102,97,99,116,32,116,104,97,116,102,111,\n114,109,32,105,100,61,34,112,114,101,99,101,100,105,110,103,84,101,99,104,110,\n105,99,97,108,112,104,121,115,105,99,105,115,116,111,99,99,117,114,115,32,105,\n110,110,97,118,105,103,97,116,111,114,115,101,99,116,105,111,110,34,62,115,112,\n97,110,32,105,100,61,34,115,111,117,103,104,116,32,116,111,98,101,108,111,119,32\n,116,104,101,115,117,114,118,105,118,105,110,103,125,60,47,115,116,121,108,101,\n62,104,105,115,32,100,101,97,116,104,97,115,32,105,110,32,116,104,101,99,97,117,\n115,101,100,32,98,121,112,97,114,116,105,97,108,108,121,101,120,105,115,116,105,\n110,103,32,117,115,105,110,103,32,116,104,101,119,97,115,32,103,105,118,101,110,\n97,32,108,105,115,116,32,111,102,108,101,118,101,108,115,32,111,102,110,111,116,\n105,111,110,32,111,102,79,102,102,105,99,105,97,108,32,100,105,115,109,105,115,\n115,101,100,115,99,105,101,110,116,105,115,116,114,101,115,101,109,98,108,101,\n115,100,117,112,108,105,99,97,116,101,101,120,112,108,111,115,105,118,101,114,\n101,99,111,118,101,114,101,100,97,108,108,32,111,116,104,101,114,103,97,108,108,\n101,114,105,101,115,123,112,97,100,100,105,110,103,58,112,101,111,112,108,101,32\n,111,102,114,101,103,105,111,110,32,111,102,97,100,100,114,101,115,115,101,115,\n97,115,115,111,99,105,97,116,101,105,109,103,32,97,108,116,61,34,105,110,32,109,\n111,100,101,114,110,115,104,111,117,108,100,32,98,101,109,101,116,104,111,100,32\n,111,102,114,101,112,111,114,116,105,110,103,116,105,109,101,115,116,97,109,112,\n110,101,101,100,101,100,32,116,111,116,104,101,32,71,114,101,97,116,114,101,103,\n97,114,100,105,110,103,115,101,101,109,101,100,32,116,111,118,105,101,119,101,\n100,32,97,115,105,109,112,97,99,116,32,111,110,105,100,101,97,32,116,104,97,116,\n116,104,101,32,87,111,114,108,100,104,101,105,103,104,116,32,111,102,101,120,112\n,97,110,100,105,110,103,84,104,101,115,101,32,97,114,101,99,117,114,114,101,110,\n116,34,62,99,97,114,101,102,117,108,108,121,109,97,105,110,116,97,105,110,115,99\n,104,97,114,103,101,32,111,102,67,108,97,115,115,105,99,97,108,97,100,100,114,\n101,115,115,101,100,112,114,101,100,105,99,116,101,100,111,119,110,101,114,115,\n104,105,112,60,100,105,118,32,105,100,61,34,114,105,103,104,116,34,62,13,10,114,\n101,115,105,100,101,110,99,101,108,101,97,118,101,32,116,104,101,99,111,110,116,\n101,110,116,34,62,97,114,101,32,111,102,116,101,110,32,32,125,41,40,41,59,13,10,\n112,114,111,98,97,98,108,121,32,80,114,111,102,101,115,115,111,114,45,98,117,116\n,116,111,110,34,32,114,101,115,112,111,110,100,101,100,115,97,121,115,32,116,104\n,97,116,104,97,100,32,116,111,32,98,101,112,108,97,99,101,100,32,105,110,72,117,\n110,103,97,114,105,97,110,115,116,97,116,117,115,32,111,102,115,101,114,118,101,\n115,32,97,115,85,110,105,118,101,114,115,97,108,101,120,101,99,117,116,105,111,\n110,97,103,103,114,101,103,97,116,101,102,111,114,32,119,104,105,99,104,105,110,\n102,101,99,116,105,111,110,97,103,114,101,101,100,32,116,111,104,111,119,101,118\n,101,114,44,32,112,111,112,117,108,97,114,34,62,112,108,97,99,101,100,32,111,110\n,99,111,110,115,116,114,117,99,116,101,108,101,99,116,111,114,97,108,115,121,109\n,98,111,108,32,111,102,105,110,99,108,117,100,105,110,103,114,101,116,117,114,\n110,32,116,111,97,114,99,104,105,116,101,99,116,67,104,114,105,115,116,105,97,\n110,112,114,101,118,105,111,117,115,32,108,105,118,105,110,103,32,105,110,101,97\n,115,105,101,114,32,116,111,112,114,111,102,101,115,115,111,114,10,38,108,116,59\n,33,45,45,32,101,102,102,101,99,116,32,111,102,97,110,97,108,121,116,105,99,115,\n119,97,115,32,116,97,107,101,110,119,104,101,114,101,32,116,104,101,116,111,111,\n107,32,111,118,101,114,98,101,108,105,101,102,32,105,110,65,102,114,105,107,97,\n97,110,115,97,115,32,102,97,114,32,97,115,112,114,101,118,101,110,116,101,100,\n119,111,114,107,32,119,105,116,104,97,32,115,112,101,99,105,97,108,60,102,105,\n101,108,100,115,101,116,67,104,114,105,115,116,109,97,115,82,101,116,114,105,101\n,118,101,100,10,10,73,110,32,116,104,101,32,98,97,99,107,32,105,110,116,111,110,\n111,114,116,104,101,97,115,116,109,97,103,97,122,105,110,101,115,62,60,115,116,\n114,111,110,103,62,99,111,109,109,105,116,116,101,101,103,111,118,101,114,110,\n105,110,103,103,114,111,117,112,115,32,111,102,115,116,111,114,101,100,32,105,\n110,101,115,116,97,98,108,105,115,104,97,32,103,101,110,101,114,97,108,105,116,\n115,32,102,105,114,115,116,116,104,101,105,114,32,111,119,110,112,111,112,117,\n108,97,116,101,100,97,110,32,111,98,106,101,99,116,67,97,114,105,98,98,101,97,\n110,97,108,108,111,119,32,116,104,101,100,105,115,116,114,105,99,116,115,119,105\n,115,99,111,110,115,105,110,108,111,99,97,116,105,111,110,46,59,32,119,105,100,\n116,104,58,32,105,110,104,97,98,105,116,101,100,83,111,99,105,97,108,105,115,116\n,74,97,110,117,97,114,121,32,49,60,47,102,111,111,116,101,114,62,115,105,109,105\n,108,97,114,108,121,99,104,111,105,99,101,32,111,102,116,104,101,32,115,97,109,\n101,32,115,112,101,99,105,102,105,99,32,98,117,115,105,110,101,115,115,32,84,104\n,101,32,102,105,114,115,116,46,108,101,110,103,116,104,59,32,100,101,115,105,114\n,101,32,116,111,100,101,97,108,32,119,105,116,104,115,105,110,99,101,32,116,104,\n101,117,115,101,114,65,103,101,110,116,99,111,110,99,101,105,118,101,100,105,110\n,100,101,120,46,112,104,112,97,115,32,38,113,117,111,116,59,101,110,103,97,103,\n101,32,105,110,114,101,99,101,110,116,108,121,44,102,101,119,32,121,101,97,114,\n115,119,101,114,101,32,97,108,115,111,10,60,104,101,97,100,62,10,60,101,100,105,\n116,101,100,32,98,121,97,114,101,32,107,110,111,119,110,99,105,116,105,101,115,\n32,105,110,97,99,99,101,115,115,107,101,121,99,111,110,100,101,109,110,101,100,\n97,108,115,111,32,104,97,118,101,115,101,114,118,105,99,101,115,44,102,97,109,\n105,108,121,32,111,102,83,99,104,111,111,108,32,111,102,99,111,110,118,101,114,\n116,101,100,110,97,116,117,114,101,32,111,102,32,108,97,110,103,117,97,103,101,\n109,105,110,105,115,116,101,114,115,60,47,111,98,106,101,99,116,62,116,104,101,\n114,101,32,105,115,32,97,32,112,111,112,117,108,97,114,115,101,113,117,101,110,\n99,101,115,97,100,118,111,99,97,116,101,100,84,104,101,121,32,119,101,114,101,97\n,110,121,32,111,116,104,101,114,108,111,99,97,116,105,111,110,61,101,110,116,101\n,114,32,116,104,101,109,117,99,104,32,109,111,114,101,114,101,102,108,101,99,116\n,101,100,119,97,115,32,110,97,109,101,100,111,114,105,103,105,110,97,108,32,97,\n32,116,121,112,105,99,97,108,119,104,101,110,32,116,104,101,121,101,110,103,105,\n110,101,101,114,115,99,111,117,108,100,32,110,111,116,114,101,115,105,100,101,\n110,116,115,119,101,100,110,101,115,100,97,121,116,104,101,32,116,104,105,114,\n100,32,112,114,111,100,117,99,116,115,74,97,110,117,97,114,121,32,50,119,104,97,\n116,32,116,104,101,121,97,32,99,101,114,116,97,105,110,114,101,97,99,116,105,111\n,110,115,112,114,111,99,101,115,115,111,114,97,102,116,101,114,32,104,105,115,\n116,104,101,32,108,97,115,116,32,99,111,110,116,97,105,110,101,100,34,62,60,47,\n100,105,118,62,10,60,47,97,62,60,47,116,100,62,100,101,112,101,110,100,32,111,\n110,115,101,97,114,99,104,34,62,10,112,105,101,99,101,115,32,111,102,99,111,109,\n112,101,116,105,110,103,82,101,102,101,114,101,110,99,101,116,101,110,110,101,\n115,115,101,101,119,104,105,99,104,32,104,97,115,32,118,101,114,115,105,111,110,\n61,60,47,115,112,97,110,62,32,60,60,47,104,101,97,100,101,114,62,103,105,118,101\n,115,32,116,104,101,104,105,115,116,111,114,105,97,110,118,97,108,117,101,61,34,\n34,62,112,97,100,100,105,110,103,58,48,118,105,101,119,32,116,104,97,116,116,111\n,103,101,116,104,101,114,44,116,104,101,32,109,111,115,116,32,119,97,115,32,102,\n111,117,110,100,115,117,98,115,101,116,32,111,102,97,116,116,97,99,107,32,111,\n110,99,104,105,108,100,114,101,110,44,112,111,105,110,116,115,32,111,102,112,101\n,114,115,111,110,97,108,32,112,111,115,105,116,105,111,110,58,97,108,108,101,103\n,101,100,108,121,67,108,101,118,101,108,97,110,100,119,97,115,32,108,97,116,101,\n114,97,110,100,32,97,102,116,101,114,97,114,101,32,103,105,118,101,110,119,97,\n115,32,115,116,105,108,108,115,99,114,111,108,108,105,110,103,100,101,115,105,\n103,110,32,111,102,109,97,107,101,115,32,116,104,101,109,117,99,104,32,108,101,\n115,115,65,109,101,114,105,99,97,110,115,46,10,10,65,102,116,101,114,32,44,32,98\n,117,116,32,116,104,101,77,117,115,101,117,109,32,111,102,108,111,117,105,115,\n105,97,110,97,40,102,114,111,109,32,116,104,101,109,105,110,110,101,115,111,116,\n97,112,97,114,116,105,99,108,101,115,97,32,112,114,111,99,101,115,115,68,111,109\n,105,110,105,99,97,110,118,111,108,117,109,101,32,111,102,114,101,116,117,114,\n110,105,110,103,100,101,102,101,110,115,105,118,101,48,48,112,120,124,114,105,\n103,104,109,97,100,101,32,102,114,111,109,109,111,117,115,101,111,118,101,114,34\n,32,115,116,121,108,101,61,34,115,116,97,116,101,115,32,111,102,40,119,104,105,\n99,104,32,105,115,99,111,110,116,105,110,117,101,115,70,114,97,110,99,105,115,99\n,111,98,117,105,108,100,105,110,103,32,119,105,116,104,111,117,116,32,97,119,105\n,116,104,32,115,111,109,101,119,104,111,32,119,111,117,108,100,97,32,102,111,114\n,109,32,111,102,97,32,112,97,114,116,32,111,102,98,101,102,111,114,101,32,105,\n116,107,110,111,119,110,32,97,115,32,32,83,101,114,118,105,99,101,115,108,111,99\n,97,116,105,111,110,32,97,110,100,32,111,102,116,101,110,109,101,97,115,117,114,\n105,110,103,97,110,100,32,105,116,32,105,115,112,97,112,101,114,98,97,99,107,118\n,97,108,117,101,115,32,111,102,13,10,60,116,105,116,108,101,62,61,32,119,105,110\n,100,111,119,46,100,101,116,101,114,109,105,110,101,101,114,38,113,117,111,116,\n59,32,112,108,97,121,101,100,32,98,121,97,110,100,32,101,97,114,108,121,60,47,99\n,101,110,116,101,114,62,102,114,111,109,32,116,104,105,115,116,104,101,32,116,\n104,114,101,101,112,111,119,101,114,32,97,110,100,111,102,32,38,113,117,111,116,\n59,105,110,110,101,114,72,84,77,76,60,97,32,104,114,101,102,61,34,121,58,105,110\n,108,105,110,101,59,67,104,117,114,99,104,32,111,102,116,104,101,32,101,118,101,\n110,116,118,101,114,121,32,104,105,103,104,111,102,102,105,99,105,97,108,32,45,\n104,101,105,103,104,116,58,32,99,111,110,116,101,110,116,61,34,47,99,103,105,45,\n98,105,110,47,116,111,32,99,114,101,97,116,101,97,102,114,105,107,97,97,110,115,\n101,115,112,101,114,97,110,116,111,102,114,97,110,195,167,97,105,115,108,97,116,\n118,105,101,197,161,117,108,105,101,116,117,118,105,197,179,196,140,101,197,161,\n116,105,110,97,196,141,101,197,161,116,105,110,97,224,185,132,224,184,151,224,\n184,162,230,151,165,230,156,172,232,170,158,231,174,128,228,189,147,229,173,151,\n231,185,129,233,171,148,229,173,151,237,149,156,234,181,173,236,150,180,228,184,\n186,228,187,128,228,185,136,232,174,161,231,174,151,230,156,186,231,172,148,232,\n174,176,230,156,172,232,168,142,232,171,150,229,141,128,230,156,141,229,138,161,\n229,153,168,228,186,146,232,129,148,231,189,145,230,136,191,229,156,176,228,186,\n167,228,191,177,228,185,144,233,131,168,229,135,186,231,137,136,231,164,190,230,\n142,146,232,161,140,230,166,156,233,131,168,232,144,189,230,160,188,232,191,155,\n228,184,128,230,173,165,230,148,175,228,187,152,229,174,157,233,170,140,232,175,\n129,231,160,129,229,167,148,229,145,152,228,188,154,230,149,176,230,141,174,229,\n186,147,230,182,136,232,180,185,232,128,133,229,138,158,229,133,172,229,174,164,\n232,174,168,232,174,186,229,140,186,230,183,177,229,156,179,229,184,130,230,146,\n173,230,148,190,229,153,168,229,140,151,228,186,172,229,184,130,229,164,167,229,\n173,166,231,148,159,232,182,138,230,157,165,232,182,138,231,174,161,231,144,134,\n229,145,152,228,191,161,230,129,175,231,189,145,115,101,114,118,105,99,105,111,\n115,97,114,116,195,173,99,117,108,111,97,114,103,101,110,116,105,110,97,98,97,\n114,99,101,108,111,110,97,99,117,97,108,113,117,105,101,114,112,117,98,108,105,\n99,97,100,111,112,114,111,100,117,99,116,111,115,112,111,108,195,173,116,105,99,\n97,114,101,115,112,117,101,115,116,97,119,105,107,105,112,101,100,105,97,115,105\n,103,117,105,101,110,116,101,98,195,186,115,113,117,101,100,97,99,111,109,117,\n110,105,100,97,100,115,101,103,117,114,105,100,97,100,112,114,105,110,99,105,112\n,97,108,112,114,101,103,117,110,116,97,115,99,111,110,116,101,110,105,100,111,\n114,101,115,112,111,110,100,101,114,118,101,110,101,122,117,101,108,97,112,114,\n111,98,108,101,109,97,115,100,105,99,105,101,109,98,114,101,114,101,108,97,99,\n105,195,179,110,110,111,118,105,101,109,98,114,101,115,105,109,105,108,97,114,\n101,115,112,114,111,121,101,99,116,111,115,112,114,111,103,114,97,109,97,115,105\n,110,115,116,105,116,117,116,111,97,99,116,105,118,105,100,97,100,101,110,99,117\n,101,110,116,114,97,101,99,111,110,111,109,195,173,97,105,109,195,161,103,101,\n110,101,115,99,111,110,116,97,99,116,97,114,100,101,115,99,97,114,103,97,114,110\n,101,99,101,115,97,114,105,111,97,116,101,110,99,105,195,179,110,116,101,108,195\n,169,102,111,110,111,99,111,109,105,115,105,195,179,110,99,97,110,99,105,111,110\n,101,115,99,97,112,97,99,105,100,97,100,101,110,99,111,110,116,114,97,114,97,110\n,195,161,108,105,115,105,115,102,97,118,111,114,105,116,111,115,116,195,169,114,\n109,105,110,111,115,112,114,111,118,105,110,99,105,97,101,116,105,113,117,101,\n116,97,115,101,108,101,109,101,110,116,111,115,102,117,110,99,105,111,110,101,\n115,114,101,115,117,108,116,97,100,111,99,97,114,195,161,99,116,101,114,112,114,\n111,112,105,101,100,97,100,112,114,105,110,99,105,112,105,111,110,101,99,101,115\n,105,100,97,100,109,117,110,105,99,105,112,97,108,99,114,101,97,99,105,195,179,\n110,100,101,115,99,97,114,103,97,115,112,114,101,115,101,110,99,105,97,99,111,\n109,101,114,99,105,97,108,111,112,105,110,105,111,110,101,115,101,106,101,114,99\n,105,99,105,111,101,100,105,116,111,114,105,97,108,115,97,108,97,109,97,110,99,\n97,103,111,110,122,195,161,108,101,122,100,111,99,117,109,101,110,116,111,112,\n101,108,195,173,99,117,108,97,114,101,99,105,101,110,116,101,115,103,101,110,101\n,114,97,108,101,115,116,97,114,114,97,103,111,110,97,112,114,195,161,99,116,105,\n99,97,110,111,118,101,100,97,100,101,115,112,114,111,112,117,101,115,116,97,112,\n97,99,105,101,110,116,101,115,116,195,169,99,110,105,99,97,115,111,98,106,101,\n116,105,118,111,115,99,111,110,116,97,99,116,111,115,224,164,174,224,165,135,224\n,164,130,224,164,178,224,164,191,224,164,143,224,164,185,224,165,136,224,164,130\n,224,164,151,224,164,175,224,164,190,224,164,184,224,164,190,224,164,165,224,164\n,143,224,164,181,224,164,130,224,164,176,224,164,185,224,165,135,224,164,149,224\n,165,139,224,164,136,224,164,149,224,165,129,224,164,155,224,164,176,224,164,185\n,224,164,190,224,164,172,224,164,190,224,164,166,224,164,149,224,164,185,224,164\n,190,224,164,184,224,164,173,224,165,128,224,164,185,224,165,129,224,164,143,224\n,164,176,224,164,185,224,165,128,224,164,174,224,165,136,224,164,130,224,164,166\n,224,164,191,224,164,168,224,164,172,224,164,190,224,164,164,100,105,112,108,111\n,100,111,99,115,224,164,184,224,164,174,224,164,175,224,164,176,224,165,130,224,\n164,170,224,164,168,224,164,190,224,164,174,224,164,170,224,164,164,224,164,190,\n224,164,171,224,164,191,224,164,176,224,164,148,224,164,184,224,164,164,224,164,\n164,224,164,176,224,164,185,224,164,178,224,165,139,224,164,151,224,164,185,224,\n165,129,224,164,134,224,164,172,224,164,190,224,164,176,224,164,166,224,165,135,\n224,164,182,224,164,185,224,165,129,224,164,136,224,164,150,224,165,135,224,164,\n178,224,164,175,224,164,166,224,164,191,224,164,149,224,164,190,224,164,174,224,\n164,181,224,165,135,224,164,172,224,164,164,224,165,128,224,164,168,224,164,172,\n224,165,128,224,164,154,224,164,174,224,165,140,224,164,164,224,164,184,224,164,\n190,224,164,178,224,164,178,224,165,135,224,164,150,224,164,156,224,165,137,224,\n164,172,224,164,174,224,164,166,224,164,166,224,164,164,224,164,165,224,164,190,\n224,164,168,224,164,185,224,165,128,224,164,182,224,164,185,224,164,176,224,164,\n133,224,164,178,224,164,151,224,164,149,224,164,173,224,165,128,224,164,168,224,\n164,151,224,164,176,224,164,170,224,164,190,224,164,184,224,164,176,224,164,190,\n224,164,164,224,164,149,224,164,191,224,164,143,224,164,137,224,164,184,224,165,\n135,224,164,151,224,164,175,224,165,128,224,164,185,224,165,130,224,164,129,224,\n164,134,224,164,151,224,165,135,224,164,159,224,165,128,224,164,174,224,164,150,\n224,165,139,224,164,156,224,164,149,224,164,190,224,164,176,224,164,133,224,164,\n173,224,165,128,224,164,151,224,164,175,224,165,135,224,164,164,224,165,129,224,\n164,174,224,164,181,224,165,139,224,164,159,224,164,166,224,165,135,224,164,130,\n224,164,133,224,164,151,224,164,176,224,164,144,224,164,184,224,165,135,224,164,\n174,224,165,135,224,164,178,224,164,178,224,164,151,224,164,190,224,164,185,224,\n164,190,224,164,178,224,164,138,224,164,170,224,164,176,224,164,154,224,164,190,\n224,164,176,224,164,144,224,164,184,224,164,190,224,164,166,224,165,135,224,164,\n176,224,164,156,224,164,191,224,164,184,224,164,166,224,164,191,224,164,178,224,\n164,172,224,164,130,224,164,166,224,164,172,224,164,168,224,164,190,224,164,185,\n224,165,130,224,164,130,224,164,178,224,164,190,224,164,150,224,164,156,224,165,\n128,224,164,164,224,164,172,224,164,159,224,164,168,224,164,174,224,164,191,224,\n164,178,224,164,135,224,164,184,224,165,135,224,164,134,224,164,168,224,165,135,\n224,164,168,224,164,175,224,164,190,224,164,149,224,165,129,224,164,178,224,164,\n178,224,165,137,224,164,151,224,164,173,224,164,190,224,164,151,224,164,176,224,\n165,135,224,164,178,224,164,156,224,164,151,224,164,185,224,164,176,224,164,190,\n224,164,174,224,164,178,224,164,151,224,165,135,224,164,170,224,165,135,224,164,\n156,224,164,185,224,164,190,224,164,165,224,164,135,224,164,184,224,165,128,224,\n164,184,224,164,185,224,165,128,224,164,149,224,164,178,224,164,190,224,164,160,\n224,165,128,224,164,149,224,164,185,224,164,190,224,164,129,224,164,166,224,165,\n130,224,164,176,224,164,164,224,164,185,224,164,164,224,164,184,224,164,190,224,\n164,164,224,164,175,224,164,190,224,164,166,224,164,134,224,164,175,224,164,190,\n224,164,170,224,164,190,224,164,149,224,164,149,224,165,140,224,164,168,224,164,\n182,224,164,190,224,164,174,224,164,166,224,165,135,224,164,150,224,164,175,224,\n164,185,224,165,128,224,164,176,224,164,190,224,164,175,224,164,150,224,165,129,\n224,164,166,224,164,178,224,164,151,224,165,128,99,97,116,101,103,111,114,105,\n101,115,101,120,112,101,114,105,101,110,99,101,60,47,116,105,116,108,101,62,13,\n10,67,111,112,121,114,105,103,104,116,32,106,97,118,97,115,99,114,105,112,116,99\n,111,110,100,105,116,105,111,110,115,101,118,101,114,121,116,104,105,110,103,60,\n112,32,99,108,97,115,115,61,34,116,101,99,104,110,111,108,111,103,121,98,97,99,\n107,103,114,111,117,110,100,60,97,32,99,108,97,115,115,61,34,109,97,110,97,103,\n101,109,101,110,116,38,99,111,112,121,59,32,50,48,49,106,97,118,97,83,99,114,105\n,112,116,99,104,97,114,97,99,116,101,114,115,98,114,101,97,100,99,114,117,109,98\n,116,104,101,109,115,101,108,118,101,115,104,111,114,105,122,111,110,116,97,108,\n103,111,118,101,114,110,109,101,110,116,67,97,108,105,102,111,114,110,105,97,97,\n99,116,105,118,105,116,105,101,115,100,105,115,99,111,118,101,114,101,100,78,97,\n118,105,103,97,116,105,111,110,116,114,97,110,115,105,116,105,111,110,99,111,110\n,110,101,99,116,105,111,110,110,97,118,105,103,97,116,105,111,110,97,112,112,101\n,97,114,97,110,99,101,60,47,116,105,116,108,101,62,60,109,99,104,101,99,107,98,\n111,120,34,32,116,101,99,104,110,105,113,117,101,115,112,114,111,116,101,99,116,\n105,111,110,97,112,112,97,114,101,110,116,108,121,97,115,32,119,101,108,108,32,\n97,115,117,110,116,39,44,32,39,85,65,45,114,101,115,111,108,117,116,105,111,110,\n111,112,101,114,97,116,105,111,110,115,116,101,108,101,118,105,115,105,111,110,\n116,114,97,110,115,108,97,116,101,100,87,97,115,104,105,110,103,116,111,110,110,\n97,118,105,103,97,116,111,114,46,32,61,32,119,105,110,100,111,119,46,105,109,112\n,114,101,115,115,105,111,110,38,108,116,59,98,114,38,103,116,59,108,105,116,101,\n114,97,116,117,114,101,112,111,112,117,108,97,116,105,111,110,98,103,99,111,108,\n111,114,61,34,35,101,115,112,101,99,105,97,108,108,121,32,99,111,110,116,101,110\n,116,61,34,112,114,111,100,117,99,116,105,111,110,110,101,119,115,108,101,116,\n116,101,114,112,114,111,112,101,114,116,105,101,115,100,101,102,105,110,105,116,\n105,111,110,108,101,97,100,101,114,115,104,105,112,84,101,99,104,110,111,108,111\n,103,121,80,97,114,108,105,97,109,101,110,116,99,111,109,112,97,114,105,115,111,\n110,117,108,32,99,108,97,115,115,61,34,46,105,110,100,101,120,79,102,40,34,99,\n111,110,99,108,117,115,105,111,110,100,105,115,99,117,115,115,105,111,110,99,111\n,109,112,111,110,101,110,116,115,98,105,111,108,111,103,105,99,97,108,82,101,118\n,111,108,117,116,105,111,110,95,99,111,110,116,97,105,110,101,114,117,110,100,\n101,114,115,116,111,111,100,110,111,115,99,114,105,112,116,62,60,112,101,114,109\n,105,115,115,105,111,110,101,97,99,104,32,111,116,104,101,114,97,116,109,111,115\n,112,104,101,114,101,32,111,110,102,111,99,117,115,61,34,60,102,111,114,109,32,\n105,100,61,34,112,114,111,99,101,115,115,105,110,103,116,104,105,115,46,118,97,\n108,117,101,103,101,110,101,114,97,116,105,111,110,67,111,110,102,101,114,101,\n110,99,101,115,117,98,115,101,113,117,101,110,116,119,101,108,108,45,107,110,111\n,119,110,118,97,114,105,97,116,105,111,110,115,114,101,112,117,116,97,116,105,\n111,110,112,104,101,110,111,109,101,110,111,110,100,105,115,99,105,112,108,105,\n110,101,108,111,103,111,46,112,110,103,34,32,40,100,111,99,117,109,101,110,116,\n44,98,111,117,110,100,97,114,105,101,115,101,120,112,114,101,115,115,105,111,110\n,115,101,116,116,108,101,109,101,110,116,66,97,99,107,103,114,111,117,110,100,\n111,117,116,32,111,102,32,116,104,101,101,110,116,101,114,112,114,105,115,101,40\n,34,104,116,116,112,115,58,34,32,117,110,101,115,99,97,112,101,40,34,112,97,115,\n115,119,111,114,100,34,32,100,101,109,111,99,114,97,116,105,99,60,97,32,104,114,\n101,102,61,34,47,119,114,97,112,112,101,114,34,62,10,109,101,109,98,101,114,115,\n104,105,112,108,105,110,103,117,105,115,116,105,99,112,120,59,112,97,100,100,105\n,110,103,112,104,105,108,111,115,111,112,104,121,97,115,115,105,115,116,97,110,\n99,101,117,110,105,118,101,114,115,105,116,121,102,97,99,105,108,105,116,105,101\n,115,114,101,99,111,103,110,105,122,101,100,112,114,101,102,101,114,101,110,99,\n101,105,102,32,40,116,121,112,101,111,102,109,97,105,110,116,97,105,110,101,100,\n118,111,99,97,98,117,108,97,114,121,104,121,112,111,116,104,101,115,105,115,46,\n115,117,98,109,105,116,40,41,59,38,97,109,112,59,110,98,115,112,59,97,110,110,\n111,116,97,116,105,111,110,98,101,104,105,110,100,32,116,104,101,70,111,117,110,\n100,97,116,105,111,110,112,117,98,108,105,115,104,101,114,34,97,115,115,117,109,\n112,116,105,111,110,105,110,116,114,111,100,117,99,101,100,99,111,114,114,117,\n112,116,105,111,110,115,99,105,101,110,116,105,115,116,115,101,120,112,108,105,\n99,105,116,108,121,105,110,115,116,101,97,100,32,111,102,100,105,109,101,110,115\n,105,111,110,115,32,111,110,67,108,105,99,107,61,34,99,111,110,115,105,100,101,\n114,101,100,100,101,112,97,114,116,109,101,110,116,111,99,99,117,112,97,116,105,\n111,110,115,111,111,110,32,97,102,116,101,114,105,110,118,101,115,116,109,101,\n110,116,112,114,111,110,111,117,110,99,101,100,105,100,101,110,116,105,102,105,\n101,100,101,120,112,101,114,105,109,101,110,116,77,97,110,97,103,101,109,101,110\n,116,103,101,111,103,114,97,112,104,105,99,34,32,104,101,105,103,104,116,61,34,\n108,105,110,107,32,114,101,108,61,34,46,114,101,112,108,97,99,101,40,47,100,101,\n112,114,101,115,115,105,111,110,99,111,110,102,101,114,101,110,99,101,112,117,\n110,105,115,104,109,101,110,116,101,108,105,109,105,110,97,116,101,100,114,101,\n115,105,115,116,97,110,99,101,97,100,97,112,116,97,116,105,111,110,111,112,112,\n111,115,105,116,105,111,110,119,101,108,108,32,107,110,111,119,110,115,117,112,\n112,108,101,109,101,110,116,100,101,116,101,114,109,105,110,101,100,104,49,32,99\n,108,97,115,115,61,34,48,112,120,59,109,97,114,103,105,110,109,101,99,104,97,110\n,105,99,97,108,115,116,97,116,105,115,116,105,99,115,99,101,108,101,98,114,97,\n116,101,100,71,111,118,101,114,110,109,101,110,116,10,10,68,117,114,105,110,103,\n32,116,100,101,118,101,108,111,112,101,114,115,97,114,116,105,102,105,99,105,97,\n108,101,113,117,105,118,97,108,101,110,116,111,114,105,103,105,110,97,116,101,\n100,67,111,109,109,105,115,115,105,111,110,97,116,116,97,99,104,109,101,110,116,\n60,115,112,97,110,32,105,100,61,34,116,104,101,114,101,32,119,101,114,101,78,101\n,100,101,114,108,97,110,100,115,98,101,121,111,110,100,32,116,104,101,114,101,\n103,105,115,116,101,114,101,100,106,111,117,114,110,97,108,105,115,116,102,114,\n101,113,117,101,110,116,108,121,97,108,108,32,111,102,32,116,104,101,108,97,110,\n103,61,34,101,110,34,32,60,47,115,116,121,108,101,62,13,10,97,98,115,111,108,117\n,116,101,59,32,115,117,112,112,111,114,116,105,110,103,101,120,116,114,101,109,\n101,108,121,32,109,97,105,110,115,116,114,101,97,109,60,47,115,116,114,111,110,\n103,62,32,112,111,112,117,108,97,114,105,116,121,101,109,112,108,111,121,109,101\n,110,116,60,47,116,97,98,108,101,62,13,10,32,99,111,108,115,112,97,110,61,34,60,\n47,102,111,114,109,62,10,32,32,99,111,110,118,101,114,115,105,111,110,97,98,111,\n117,116,32,116,104,101,32,60,47,112,62,60,47,100,105,118,62,105,110,116,101,103,\n114,97,116,101,100,34,32,108,97,110,103,61,34,101,110,80,111,114,116,117,103,117\n,101,115,101,115,117,98,115,116,105,116,117,116,101,105,110,100,105,118,105,100,\n117,97,108,105,109,112,111,115,115,105,98,108,101,109,117,108,116,105,109,101,\n100,105,97,97,108,109,111,115,116,32,97,108,108,112,120,32,115,111,108,105,100,\n32,35,97,112,97,114,116,32,102,114,111,109,115,117,98,106,101,99,116,32,116,111,\n105,110,32,69,110,103,108,105,115,104,99,114,105,116,105,99,105,122,101,100,101,\n120,99,101,112,116,32,102,111,114,103,117,105,100,101,108,105,110,101,115,111,\n114,105,103,105,110,97,108,108,121,114,101,109,97,114,107,97,98,108,101,116,104,\n101,32,115,101,99,111,110,100,104,50,32,99,108,97,115,115,61,34,60,97,32,116,105\n,116,108,101,61,34,40,105,110,99,108,117,100,105,110,103,112,97,114,97,109,101,\n116,101,114,115,112,114,111,104,105,98,105,116,101,100,61,32,34,104,116,116,112,\n58,47,47,100,105,99,116,105,111,110,97,114,121,112,101,114,99,101,112,116,105,\n111,110,114,101,118,111,108,117,116,105,111,110,102,111,117,110,100,97,116,105,\n111,110,112,120,59,104,101,105,103,104,116,58,115,117,99,99,101,115,115,102,117,\n108,115,117,112,112,111,114,116,101,114,115,109,105,108,108,101,110,110,105,117,\n109,104,105,115,32,102,97,116,104,101,114,116,104,101,32,38,113,117,111,116,59,\n110,111,45,114,101,112,101,97,116,59,99,111,109,109,101,114,99,105,97,108,105,\n110,100,117,115,116,114,105,97,108,101,110,99,111,117,114,97,103,101,100,97,109,\n111,117,110,116,32,111,102,32,117,110,111,102,102,105,99,105,97,108,101,102,102,\n105,99,105,101,110,99,121,82,101,102,101,114,101,110,99,101,115,99,111,111,114,\n100,105,110,97,116,101,100,105,115,99,108,97,105,109,101,114,101,120,112,101,100\n,105,116,105,111,110,100,101,118,101,108,111,112,105,110,103,99,97,108,99,117,\n108,97,116,101,100,115,105,109,112,108,105,102,105,101,100,108,101,103,105,116,\n105,109,97,116,101,115,117,98,115,116,114,105,110,103,40,48,34,32,99,108,97,115,\n115,61,34,99,111,109,112,108,101,116,101,108,121,105,108,108,117,115,116,114,97,\n116,101,102,105,118,101,32,121,101,97,114,115,105,110,115,116,114,117,109,101,\n110,116,80,117,98,108,105,115,104,105,110,103,49,34,32,99,108,97,115,115,61,34,\n112,115,121,99,104,111,108,111,103,121,99,111,110,102,105,100,101,110,99,101,110\n,117,109,98,101,114,32,111,102,32,97,98,115,101,110,99,101,32,111,102,102,111,99\n,117,115,101,100,32,111,110,106,111,105,110,101,100,32,116,104,101,115,116,114,\n117,99,116,117,114,101,115,112,114,101,118,105,111,117,115,108,121,62,60,47,105,\n102,114,97,109,101,62,111,110,99,101,32,97,103,97,105,110,98,117,116,32,114,97,\n116,104,101,114,105,109,109,105,103,114,97,110,116,115,111,102,32,99,111,117,114\n,115,101,44,97,32,103,114,111,117,112,32,111,102,76,105,116,101,114,97,116,117,\n114,101,85,110,108,105,107,101,32,116,104,101,60,47,97,62,38,110,98,115,112,59,\n10,102,117,110,99,116,105,111,110,32,105,116,32,119,97,115,32,116,104,101,67,111\n,110,118,101,110,116,105,111,110,97,117,116,111,109,111,98,105,108,101,80,114,\n111,116,101,115,116,97,110,116,97,103,103,114,101,115,115,105,118,101,97,102,116\n,101,114,32,116,104,101,32,83,105,109,105,108,97,114,108,121,44,34,32,47,62,60,\n47,100,105,118,62,99,111,108,108,101,99,116,105,111,110,13,10,102,117,110,99,116\n,105,111,110,118,105,115,105,98,105,108,105,116,121,116,104,101,32,117,115,101,\n32,111,102,118,111,108,117,110,116,101,101,114,115,97,116,116,114,97,99,116,105,\n111,110,117,110,100,101,114,32,116,104,101,32,116,104,114,101,97,116,101,110,101\n,100,42,60,33,91,67,68,65,84,65,91,105,109,112,111,114,116,97,110,99,101,105,110\n,32,103,101,110,101,114,97,108,116,104,101,32,108,97,116,116,101,114,60,47,102,\n111,114,109,62,10,60,47,46,105,110,100,101,120,79,102,40,39,105,32,61,32,48,59,\n32,105,32,60,100,105,102,102,101,114,101,110,99,101,100,101,118,111,116,101,100,\n32,116,111,116,114,97,100,105,116,105,111,110,115,115,101,97,114,99,104,32,102,\n111,114,117,108,116,105,109,97,116,101,108,121,116,111,117,114,110,97,109,101,\n110,116,97,116,116,114,105,98,117,116,101,115,115,111,45,99,97,108,108,101,100,\n32,125,10,60,47,115,116,121,108,101,62,101,118,97,108,117,97,116,105,111,110,101\n,109,112,104,97,115,105,122,101,100,97,99,99,101,115,115,105,98,108,101,60,47,\n115,101,99,116,105,111,110,62,115,117,99,99,101,115,115,105,111,110,97,108,111,\n110,103,32,119,105,116,104,77,101,97,110,119,104,105,108,101,44,105,110,100,117,\n115,116,114,105,101,115,60,47,97,62,60,98,114,32,47,62,104,97,115,32,98,101,99,\n111,109,101,97,115,112,101,99,116,115,32,111,102,84,101,108,101,118,105,115,105,\n111,110,115,117,102,102,105,99,105,101,110,116,98,97,115,107,101,116,98,97,108,\n108,98,111,116,104,32,115,105,100,101,115,99,111,110,116,105,110,117,105,110,103\n,97,110,32,97,114,116,105,99,108,101,60,105,109,103,32,97,108,116,61,34,97,100,\n118,101,110,116,117,114,101,115,104,105,115,32,109,111,116,104,101,114,109,97,\n110,99,104,101,115,116,101,114,112,114,105,110,99,105,112,108,101,115,112,97,114\n,116,105,99,117,108,97,114,99,111,109,109,101,110,116,97,114,121,101,102,102,101\n,99,116,115,32,111,102,100,101,99,105,100,101,100,32,116,111,34,62,60,115,116,\n114,111,110,103,62,112,117,98,108,105,115,104,101,114,115,74,111,117,114,110,97,\n108,32,111,102,100,105,102,102,105,99,117,108,116,121,102,97,99,105,108,105,116,\n97,116,101,97,99,99,101,112,116,97,98,108,101,115,116,121,108,101,46,99,115,115,\n34,9,102,117,110,99,116,105,111,110,32,105,110,110,111,118,97,116,105,111,110,62\n,67,111,112,121,114,105,103,104,116,115,105,116,117,97,116,105,111,110,115,119,\n111,117,108,100,32,104,97,118,101,98,117,115,105,110,101,115,115,101,115,68,105,\n99,116,105,111,110,97,114,121,115,116,97,116,101,109,101,110,116,115,111,102,116\n,101,110,32,117,115,101,100,112,101,114,115,105,115,116,101,110,116,105,110,32,\n74,97,110,117,97,114,121,99,111,109,112,114,105,115,105,110,103,60,47,116,105,\n116,108,101,62,10,9,100,105,112,108,111,109,97,116,105,99,99,111,110,116,97,105,\n110,105,110,103,112,101,114,102,111,114,109,105,110,103,101,120,116,101,110,115,\n105,111,110,115,109,97,121,32,110,111,116,32,98,101,99,111,110,99,101,112,116,32\n,111,102,32,111,110,99,108,105,99,107,61,34,73,116,32,105,115,32,97,108,115,111,\n102,105,110,97,110,99,105,97,108,32,109,97,107,105,110,103,32,116,104,101,76,117\n,120,101,109,98,111,117,114,103,97,100,100,105,116,105,111,110,97,108,97,114,101\n,32,99,97,108,108,101,100,101,110,103,97,103,101,100,32,105,110,34,115,99,114,\n105,112,116,34,41,59,98,117,116,32,105,116,32,119,97,115,101,108,101,99,116,114,\n111,110,105,99,111,110,115,117,98,109,105,116,61,34,10,60,33,45,45,32,69,110,100\n,32,101,108,101,99,116,114,105,99,97,108,111,102,102,105,99,105,97,108,108,121,\n115,117,103,103,101,115,116,105,111,110,116,111,112,32,111,102,32,116,104,101,\n117,110,108,105,107,101,32,116,104,101,65,117,115,116,114,97,108,105,97,110,79,\n114,105,103,105,110,97,108,108,121,114,101,102,101,114,101,110,99,101,115,10,60,\n47,104,101,97,100,62,13,10,114,101,99,111,103,110,105,115,101,100,105,110,105,\n116,105,97,108,105,122,101,108,105,109,105,116,101,100,32,116,111,65,108,101,120\n,97,110,100,114,105,97,114,101,116,105,114,101,109,101,110,116,65,100,118,101,\n110,116,117,114,101,115,102,111,117,114,32,121,101,97,114,115,10,10,38,108,116,\n59,33,45,45,32,105,110,99,114,101,97,115,105,110,103,100,101,99,111,114,97,116,\n105,111,110,104,51,32,99,108,97,115,115,61,34,111,114,105,103,105,110,115,32,111\n,102,111,98,108,105,103,97,116,105,111,110,114,101,103,117,108,97,116,105,111,\n110,99,108,97,115,115,105,102,105,101,100,40,102,117,110,99,116,105,111,110,40,\n97,100,118,97,110,116,97,103,101,115,98,101,105,110,103,32,116,104,101,32,104,\n105,115,116,111,114,105,97,110,115,60,98,97,115,101,32,104,114,101,102,114,101,\n112,101,97,116,101,100,108,121,119,105,108,108,105,110,103,32,116,111,99,111,109\n,112,97,114,97,98,108,101,100,101,115,105,103,110,97,116,101,100,110,111,109,105\n,110,97,116,105,111,110,102,117,110,99,116,105,111,110,97,108,105,110,115,105,\n100,101,32,116,104,101,114,101,118,101,108,97,116,105,111,110,101,110,100,32,111\n,102,32,116,104,101,115,32,102,111,114,32,116,104,101,32,97,117,116,104,111,114,\n105,122,101,100,114,101,102,117,115,101,100,32,116,111,116,97,107,101,32,112,108\n,97,99,101,97,117,116,111,110,111,109,111,117,115,99,111,109,112,114,111,109,105\n,115,101,112,111,108,105,116,105,99,97,108,32,114,101,115,116,97,117,114,97,110,\n116,116,119,111,32,111,102,32,116,104,101,70,101,98,114,117,97,114,121,32,50,113\n,117,97,108,105,116,121,32,111,102,115,119,102,111,98,106,101,99,116,46,117,110,\n100,101,114,115,116,97,110,100,110,101,97,114,108,121,32,97,108,108,119,114,105,\n116,116,101,110,32,98,121,105,110,116,101,114,118,105,101,119,115,34,32,119,105,\n100,116,104,61,34,49,119,105,116,104,100,114,97,119,97,108,102,108,111,97,116,58\n,108,101,102,116,105,115,32,117,115,117,97,108,108,121,99,97,110,100,105,100,97,\n116,101,115,110,101,119,115,112,97,112,101,114,115,109,121,115,116,101,114,105,\n111,117,115,68,101,112,97,114,116,109,101,110,116,98,101,115,116,32,107,110,111,\n119,110,112,97,114,108,105,97,109,101,110,116,115,117,112,112,114,101,115,115,\n101,100,99,111,110,118,101,110,105,101,110,116,114,101,109,101,109,98,101,114,\n101,100,100,105,102,102,101,114,101,110,116,32,115,121,115,116,101,109,97,116,\n105,99,104,97,115,32,108,101,100,32,116,111,112,114,111,112,97,103,97,110,100,97\n,99,111,110,116,114,111,108,108,101,100,105,110,102,108,117,101,110,99,101,115,\n99,101,114,101,109,111,110,105,97,108,112,114,111,99,108,97,105,109,101,100,80,\n114,111,116,101,99,116,105,111,110,108,105,32,99,108,97,115,115,61,34,83,99,105,\n101,110,116,105,102,105,99,99,108,97,115,115,61,34,110,111,45,116,114,97,100,101\n,109,97,114,107,115,109,111,114,101,32,116,104,97,110,32,119,105,100,101,115,112\n,114,101,97,100,76,105,98,101,114,97,116,105,111,110,116,111,111,107,32,112,108,\n97,99,101,100,97,121,32,111,102,32,116,104,101,97,115,32,108,111,110,103,32,97,\n115,105,109,112,114,105,115,111,110,101,100,65,100,100,105,116,105,111,110,97,\n108,10,60,104,101,97,100,62,10,60,109,76,97,98,111,114,97,116,111,114,121,78,111\n,118,101,109,98,101,114,32,50,101,120,99,101,112,116,105,111,110,115,73,110,100,\n117,115,116,114,105,97,108,118,97,114,105,101,116,121,32,111,102,102,108,111,97,\n116,58,32,108,101,102,68,117,114,105,110,103,32,116,104,101,97,115,115,101,115,\n115,109,101,110,116,104,97,118,101,32,98,101,101,110,32,100,101,97,108,115,32,\n119,105,116,104,83,116,97,116,105,115,116,105,99,115,111,99,99,117,114,114,101,\n110,99,101,47,117,108,62,60,47,100,105,118,62,99,108,101,97,114,102,105,120,34,\n62,116,104,101,32,112,117,98,108,105,99,109,97,110,121,32,121,101,97,114,115,119\n,104,105,99,104,32,119,101,114,101,111,118,101,114,32,116,105,109,101,44,115,121\n,110,111,110,121,109,111,117,115,99,111,110,116,101,110,116,34,62,10,112,114,101\n,115,117,109,97,98,108,121,104,105,115,32,102,97,109,105,108,121,117,115,101,114\n,65,103,101,110,116,46,117,110,101,120,112,101,99,116,101,100,105,110,99,108,117\n,100,105,110,103,32,99,104,97,108,108,101,110,103,101,100,97,32,109,105,110,111,\n114,105,116,121,117,110,100,101,102,105,110,101,100,34,98,101,108,111,110,103,\n115,32,116,111,116,97,107,101,110,32,102,114,111,109,105,110,32,79,99,116,111,98\n,101,114,112,111,115,105,116,105,111,110,58,32,115,97,105,100,32,116,111,32,98,\n101,114,101,108,105,103,105,111,117,115,32,70,101,100,101,114,97,116,105,111,110\n,32,114,111,119,115,112,97,110,61,34,111,110,108,121,32,97,32,102,101,119,109,\n101,97,110,116,32,116,104,97,116,108,101,100,32,116,111,32,116,104,101,45,45,62,\n13,10,60,100,105,118,32,60,102,105,101,108,100,115,101,116,62,65,114,99,104,98,\n105,115,104,111,112,32,99,108,97,115,115,61,34,110,111,98,101,105,110,103,32,117\n,115,101,100,97,112,112,114,111,97,99,104,101,115,112,114,105,118,105,108,101,\n103,101,115,110,111,115,99,114,105,112,116,62,10,114,101,115,117,108,116,115,32,\n105,110,109,97,121,32,98,101,32,116,104,101,69,97,115,116,101,114,32,101,103,103\n,109,101,99,104,97,110,105,115,109,115,114,101,97,115,111,110,97,98,108,101,80,\n111,112,117,108,97,116,105,111,110,67,111,108,108,101,99,116,105,111,110,115,101\n,108,101,99,116,101,100,34,62,110,111,115,99,114,105,112,116,62,13,47,105,110,\n100,101,120,46,112,104,112,97,114,114,105,118,97,108,32,111,102,45,106,115,115,\n100,107,39,41,41,59,109,97,110,97,103,101,100,32,116,111,105,110,99,111,109,112,\n108,101,116,101,99,97,115,117,97,108,116,105,101,115,99,111,109,112,108,101,116,\n105,111,110,67,104,114,105,115,116,105,97,110,115,83,101,112,116,101,109,98,101,\n114,32,97,114,105,116,104,109,101,116,105,99,112,114,111,99,101,100,117,114,101,\n115,109,105,103,104,116,32,104,97,118,101,80,114,111,100,117,99,116,105,111,110,\n105,116,32,97,112,112,101,97,114,115,80,104,105,108,111,115,111,112,104,121,102,\n114,105,101,110,100,115,104,105,112,108,101,97,100,105,110,103,32,116,111,103,\n105,118,105,110,103,32,116,104,101,116,111,119,97,114,100,32,116,104,101,103,117\n,97,114,97,110,116,101,101,100,100,111,99,117,109,101,110,116,101,100,99,111,108\n,111,114,58,35,48,48,48,118,105,100,101,111,32,103,97,109,101,99,111,109,109,105\n,115,115,105,111,110,114,101,102,108,101,99,116,105,110,103,99,104,97,110,103,\n101,32,116,104,101,97,115,115,111,99,105,97,116,101,100,115,97,110,115,45,115,\n101,114,105,102,111,110,107,101,121,112,114,101,115,115,59,32,112,97,100,100,105\n,110,103,58,72,101,32,119,97,115,32,116,104,101,117,110,100,101,114,108,121,105,\n110,103,116,121,112,105,99,97,108,108,121,32,44,32,97,110,100,32,116,104,101,32,\n115,114,99,69,108,101,109,101,110,116,115,117,99,99,101,115,115,105,118,101,115,\n105,110,99,101,32,116,104,101,32,115,104,111,117,108,100,32,98,101,32,110,101,\n116,119,111,114,107,105,110,103,97,99,99,111,117,110,116,105,110,103,117,115,101\n,32,111,102,32,116,104,101,108,111,119,101,114,32,116,104,97,110,115,104,111,119\n,115,32,116,104,97,116,60,47,115,112,97,110,62,10,9,9,99,111,109,112,108,97,105,\n110,116,115,99,111,110,116,105,110,117,111,117,115,113,117,97,110,116,105,116,\n105,101,115,97,115,116,114,111,110,111,109,101,114,104,101,32,100,105,100,32,110\n,111,116,100,117,101,32,116,111,32,105,116,115,97,112,112,108,105,101,100,32,116\n,111,97,110,32,97,118,101,114,97,103,101,101,102,102,111,114,116,115,32,116,111,\n116,104,101,32,102,117,116,117,114,101,97,116,116,101,109,112,116,32,116,111,84,\n104,101,114,101,102,111,114,101,44,99,97,112,97,98,105,108,105,116,121,82,101,\n112,117,98,108,105,99,97,110,119,97,115,32,102,111,114,109,101,100,69,108,101,99\n,116,114,111,110,105,99,107,105,108,111,109,101,116,101,114,115,99,104,97,108,\n108,101,110,103,101,115,112,117,98,108,105,115,104,105,110,103,116,104,101,32,\n102,111,114,109,101,114,105,110,100,105,103,101,110,111,117,115,100,105,114,101,\n99,116,105,111,110,115,115,117,98,115,105,100,105,97,114,121,99,111,110,115,112,\n105,114,97,99,121,100,101,116,97,105,108,115,32,111,102,97,110,100,32,105,110,32\n,116,104,101,97,102,102,111,114,100,97,98,108,101,115,117,98,115,116,97,110,99,\n101,115,114,101,97,115,111,110,32,102,111,114,99,111,110,118,101,110,116,105,111\n,110,105,116,101,109,116,121,112,101,61,34,97,98,115,111,108,117,116,101,108,121\n,115,117,112,112,111,115,101,100,108,121,114,101,109,97,105,110,101,100,32,97,97\n,116,116,114,97,99,116,105,118,101,116,114,97,118,101,108,108,105,110,103,115,\n101,112,97,114,97,116,101,108,121,102,111,99,117,115,101,115,32,111,110,101,108,\n101,109,101,110,116,97,114,121,97,112,112,108,105,99,97,98,108,101,102,111,117,\n110,100,32,116,104,97,116,115,116,121,108,101,115,104,101,101,116,109,97,110,117\n,115,99,114,105,112,116,115,116,97,110,100,115,32,102,111,114,32,110,111,45,114,\n101,112,101,97,116,40,115,111,109,101,116,105,109,101,115,67,111,109,109,101,114\n,99,105,97,108,105,110,32,65,109,101,114,105,99,97,117,110,100,101,114,116,97,\n107,101,110,113,117,97,114,116,101,114,32,111,102,97,110,32,101,120,97,109,112,\n108,101,112,101,114,115,111,110,97,108,108,121,105,110,100,101,120,46,112,104,\n112,63,60,47,98,117,116,116,111,110,62,10,112,101,114,99,101,110,116,97,103,101,\n98,101,115,116,45,107,110,111,119,110,99,114,101,97,116,105,110,103,32,97,34,32,\n100,105,114,61,34,108,116,114,76,105,101,117,116,101,110,97,110,116,10,60,100,\n105,118,32,105,100,61,34,116,104,101,121,32,119,111,117,108,100,97,98,105,108,\n105,116,121,32,111,102,109,97,100,101,32,117,112,32,111,102,110,111,116,101,100,\n32,116,104,97,116,99,108,101,97,114,32,116,104,97,116,97,114,103,117,101,32,116,\n104,97,116,116,111,32,97,110,111,116,104,101,114,99,104,105,108,100,114,101,110,\n39,115,112,117,114,112,111,115,101,32,111,102,102,111,114,109,117,108,97,116,101\n,100,98,97,115,101,100,32,117,112,111,110,116,104,101,32,114,101,103,105,111,110\n,115,117,98,106,101,99,116,32,111,102,112,97,115,115,101,110,103,101,114,115,112\n,111,115,115,101,115,115,105,111,110,46,10,10,73,110,32,116,104,101,32,66,101,\n102,111,114,101,32,116,104,101,97,102,116,101,114,119,97,114,100,115,99,117,114,\n114,101,110,116,108,121,32,97,99,114,111,115,115,32,116,104,101,115,99,105,101,\n110,116,105,102,105,99,99,111,109,109,117,110,105,116,121,46,99,97,112,105,116,\n97,108,105,115,109,105,110,32,71,101,114,109,97,110,121,114,105,103,104,116,45,\n119,105,110,103,116,104,101,32,115,121,115,116,101,109,83,111,99,105,101,116,121\n,32,111,102,112,111,108,105,116,105,99,105,97,110,100,105,114,101,99,116,105,111\n,110,58,119,101,110,116,32,111,110,32,116,111,114,101,109,111,118,97,108,32,111,\n102,32,78,101,119,32,89,111,114,107,32,97,112,97,114,116,109,101,110,116,115,105\n,110,100,105,99,97,116,105,111,110,100,117,114,105,110,103,32,116,104,101,117,\n110,108,101,115,115,32,116,104,101,104,105,115,116,111,114,105,99,97,108,104,97,\n100,32,98,101,101,110,32,97,100,101,102,105,110,105,116,105,118,101,105,110,103,\n114,101,100,105,101,110,116,97,116,116,101,110,100,97,110,99,101,67,101,110,116,\n101,114,32,102,111,114,112,114,111,109,105,110,101,110,99,101,114,101,97,100,121\n,83,116,97,116,101,115,116,114,97,116,101,103,105,101,115,98,117,116,32,105,110,\n32,116,104,101,97,115,32,112,97,114,116,32,111,102,99,111,110,115,116,105,116,\n117,116,101,99,108,97,105,109,32,116,104,97,116,108,97,98,111,114,97,116,111,114\n,121,99,111,109,112,97,116,105,98,108,101,102,97,105,108,117,114,101,32,111,102,\n44,32,115,117,99,104,32,97,115,32,98,101,103,97,110,32,119,105,116,104,117,115,\n105,110,103,32,116,104,101,32,116,111,32,112,114,111,118,105,100,101,102,101,97,\n116,117,114,101,32,111,102,102,114,111,109,32,119,104,105,99,104,47,34,32,99,108\n,97,115,115,61,34,103,101,111,108,111,103,105,99,97,108,115,101,118,101,114,97,\n108,32,111,102,100,101,108,105,98,101,114,97,116,101,105,109,112,111,114,116,97,\n110,116,32,104,111,108,100,115,32,116,104,97,116,105,110,103,38,113,117,111,116,\n59,32,118,97,108,105,103,110,61,116,111,112,116,104,101,32,71,101,114,109,97,110\n,111,117,116,115,105,100,101,32,111,102,110,101,103,111,116,105,97,116,101,100,\n104,105,115,32,99,97,114,101,101,114,115,101,112,97,114,97,116,105,111,110,105,\n100,61,34,115,101,97,114,99,104,119,97,115,32,99,97,108,108,101,100,116,104,101,\n32,102,111,117,114,116,104,114,101,99,114,101,97,116,105,111,110,111,116,104,101\n,114,32,116,104,97,110,112,114,101,118,101,110,116,105,111,110,119,104,105,108,\n101,32,116,104,101,32,101,100,117,99,97,116,105,111,110,44,99,111,110,110,101,99\n,116,105,110,103,97,99,99,117,114,97,116,101,108,121,119,101,114,101,32,98,117,\n105,108,116,119,97,115,32,107,105,108,108,101,100,97,103,114,101,101,109,101,110\n,116,115,109,117,99,104,32,109,111,114,101,32,68,117,101,32,116,111,32,116,104,\n101,119,105,100,116,104,58,32,49,48,48,115,111,109,101,32,111,116,104,101,114,75\n,105,110,103,100,111,109,32,111,102,116,104,101,32,101,110,116,105,114,101,102,\n97,109,111,117,115,32,102,111,114,116,111,32,99,111,110,110,101,99,116,111,98,\n106,101,99,116,105,118,101,115,116,104,101,32,70,114,101,110,99,104,112,101,111,\n112,108,101,32,97,110,100,102,101,97,116,117,114,101,100,34,62,105,115,32,115,97\n,105,100,32,116,111,115,116,114,117,99,116,117,114,97,108,114,101,102,101,114,\n101,110,100,117,109,109,111,115,116,32,111,102,116,101,110,97,32,115,101,112,97,\n114,97,116,101,45,62,10,60,100,105,118,32,105,100,32,79,102,102,105,99,105,97,\n108,32,119,111,114,108,100,119,105,100,101,46,97,114,105,97,45,108,97,98,101,108\n,116,104,101,32,112,108,97,110,101,116,97,110,100,32,105,116,32,119,97,115,100,\n34,32,118,97,108,117,101,61,34,108,111,111,107,105,110,103,32,97,116,98,101,110,\n101,102,105,99,105,97,108,97,114,101,32,105,110,32,116,104,101,109,111,110,105,\n116,111,114,105,110,103,114,101,112,111,114,116,101,100,108,121,116,104,101,32,\n109,111,100,101,114,110,119,111,114,107,105,110,103,32,111,110,97,108,108,111,\n119,101,100,32,116,111,119,104,101,114,101,32,116,104,101,32,105,110,110,111,118\n,97,116,105,118,101,60,47,97,62,60,47,100,105,118,62,115,111,117,110,100,116,114\n,97,99,107,115,101,97,114,99,104,70,111,114,109,116,101,110,100,32,116,111,32,98\n,101,105,110,112,117,116,32,105,100,61,34,111,112,101,110,105,110,103,32,111,102\n,114,101,115,116,114,105,99,116,101,100,97,100,111,112,116,101,100,32,98,121,97,\n100,100,114,101,115,115,105,110,103,116,104,101,111,108,111,103,105,97,110,109,\n101,116,104,111,100,115,32,111,102,118,97,114,105,97,110,116,32,111,102,67,104,\n114,105,115,116,105,97,110,32,118,101,114,121,32,108,97,114,103,101,97,117,116,\n111,109,111,116,105,118,101,98,121,32,102,97,114,32,116,104,101,114,97,110,103,\n101,32,102,114,111,109,112,117,114,115,117,105,116,32,111,102,102,111,108,108,\n111,119,32,116,104,101,98,114,111,117,103,104,116,32,116,111,105,110,32,69,110,\n103,108,97,110,100,97,103,114,101,101,32,116,104,97,116,97,99,99,117,115,101,100\n,32,111,102,99,111,109,101,115,32,102,114,111,109,112,114,101,118,101,110,116,\n105,110,103,100,105,118,32,115,116,121,108,101,61,104,105,115,32,111,114,32,104,\n101,114,116,114,101,109,101,110,100,111,117,115,102,114,101,101,100,111,109,32,\n111,102,99,111,110,99,101,114,110,105,110,103,48,32,49,101,109,32,49,101,109,59,\n66,97,115,107,101,116,98,97,108,108,47,115,116,121,108,101,46,99,115,115,97,110,\n32,101,97,114,108,105,101,114,101,118,101,110,32,97,102,116,101,114,47,34,32,116\n,105,116,108,101,61,34,46,99,111,109,47,105,110,100,101,120,116,97,107,105,110,\n103,32,116,104,101,112,105,116,116,115,98,117,114,103,104,99,111,110,116,101,110\n,116,34,62,13,60,115,99,114,105,112,116,62,40,102,116,117,114,110,101,100,32,111\n,117,116,104,97,118,105,110,103,32,116,104,101,60,47,115,112,97,110,62,13,10,32,\n111,99,99,97,115,105,111,110,97,108,98,101,99,97,117,115,101,32,105,116,115,116,\n97,114,116,101,100,32,116,111,112,104,121,115,105,99,97,108,108,121,62,60,47,100\n,105,118,62,10,32,32,99,114,101,97,116,101,100,32,98,121,67,117,114,114,101,110,\n116,108,121,44,32,98,103,99,111,108,111,114,61,34,116,97,98,105,110,100,101,120,\n61,34,100,105,115,97,115,116,114,111,117,115,65,110,97,108,121,116,105,99,115,32\n,97,108,115,111,32,104,97,115,32,97,62,60,100,105,118,32,105,100,61,34,60,47,115\n,116,121,108,101,62,10,60,99,97,108,108,101,100,32,102,111,114,115,105,110,103,\n101,114,32,97,110,100,46,115,114,99,32,61,32,34,47,47,118,105,111,108,97,116,105\n,111,110,115,116,104,105,115,32,112,111,105,110,116,99,111,110,115,116,97,110,\n116,108,121,105,115,32,108,111,99,97,116,101,100,114,101,99,111,114,100,105,110,\n103,115,100,32,102,114,111,109,32,116,104,101,110,101,100,101,114,108,97,110,100\n,115,112,111,114,116,117,103,117,195,170,115,215,162,215,145,215,168,215,153,215\n,170,217,129,216,167,216,177,216,179,219,140,100,101,115,97,114,114,111,108,108,\n111,99,111,109,101,110,116,97,114,105,111,101,100,117,99,97,99,105,195,179,110,\n115,101,112,116,105,101,109,98,114,101,114,101,103,105,115,116,114,97,100,111,\n100,105,114,101,99,99,105,195,179,110,117,98,105,99,97,99,105,195,179,110,112,\n117,98,108,105,99,105,100,97,100,114,101,115,112,117,101,115,116,97,115,114,101,\n115,117,108,116,97,100,111,115,105,109,112,111,114,116,97,110,116,101,114,101,\n115,101,114,118,97,100,111,115,97,114,116,195,173,99,117,108,111,115,100,105,102\n,101,114,101,110,116,101,115,115,105,103,117,105,101,110,116,101,115,114,101,112\n,195,186,98,108,105,99,97,115,105,116,117,97,99,105,195,179,110,109,105,110,105,\n115,116,101,114,105,111,112,114,105,118,97,99,105,100,97,100,100,105,114,101,99,\n116,111,114,105,111,102,111,114,109,97,99,105,195,179,110,112,111,98,108,97,99,\n105,195,179,110,112,114,101,115,105,100,101,110,116,101,99,111,110,116,101,110,\n105,100,111,115,97,99,99,101,115,111,114,105,111,115,116,101,99,104,110,111,114,\n97,116,105,112,101,114,115,111,110,97,108,101,115,99,97,116,101,103,111,114,195,\n173,97,101,115,112,101,99,105,97,108,101,115,100,105,115,112,111,110,105,98,108,\n101,97,99,116,117,97,108,105,100,97,100,114,101,102,101,114,101,110,99,105,97,\n118,97,108,108,97,100,111,108,105,100,98,105,98,108,105,111,116,101,99,97,114,\n101,108,97,99,105,111,110,101,115,99,97,108,101,110,100,97,114,105,111,112,111,\n108,195,173,116,105,99,97,115,97,110,116,101,114,105,111,114,101,115,100,111,99,\n117,109,101,110,116,111,115,110,97,116,117,114,97,108,101,122,97,109,97,116,101,\n114,105,97,108,101,115,100,105,102,101,114,101,110,99,105,97,101,99,111,110,195,\n179,109,105,99,97,116,114,97,110,115,112,111,114,116,101,114,111,100,114,195,173\n,103,117,101,122,112,97,114,116,105,99,105,112,97,114,101,110,99,117,101,110,116\n,114,97,110,100,105,115,99,117,115,105,195,179,110,101,115,116,114,117,99,116,\n117,114,97,102,117,110,100,97,99,105,195,179,110,102,114,101,99,117,101,110,116,\n101,115,112,101,114,109,97,110,101,110,116,101,116,111,116,97,108,109,101,110,\n116,101,208,188,208,190,208,182,208,189,208,190,208,177,209,131,208,180,208,181,\n209,130,208,188,208,190,208,182,208,181,209,130,208,178,209,128,208,181,208,188,\n209,143,209,130,208,176,208,186,208,182,208,181,209,135,209,130,208,190,208,177,\n209,139,208,177,208,190,208,187,208,181,208,181,208,190,209,135,208,181,208,189,\n209,140,209,141,209,130,208,190,208,179,208,190,208,186,208,190,208,179,208,180,\n208,176,208,191,208,190,209,129,208,187,208,181,208,178,209,129,208,181,208,179,\n208,190,209,129,208,176,208,185,209,130,208,181,209,135,208,181,209,128,208,181,\n208,183,208,188,208,190,208,179,209,131,209,130,209,129,208,176,208,185,209,130,\n208,176,208,182,208,184,208,183,208,189,208,184,208,188,208,181,208,182,208,180,\n209,131,208,177,209,131,208,180,209,131,209,130,208,159,208,190,208,184,209,129,\n208,186,208,183,208,180,208,181,209,129,209,140,208,178,208,184,208,180,208,181,\n208,190,209,129,208,178,209,143,208,183,208,184,208,189,209,131,208,182,208,189,\n208,190,209,129,208,178,208,190,208,181,208,185,208,187,209,142,208,180,208,181,\n208,185,208,191,208,190,209,128,208,189,208,190,208,188,208,189,208,190,208,179,\n208,190,208,180,208,181,209,130,208,181,208,185,209,129,208,178,208,190,208,184,\n209,133,208,191,209,128,208,176,208,178,208,176,209,130,208,176,208,186,208,190,\n208,185,208,188,208,181,209,129,209,130,208,190,208,184,208,188,208,181,208,181,\n209,130,208,182,208,184,208,183,208,189,209,140,208,190,208,180,208,189,208,190,\n208,185,208,187,209,131,209,135,209,136,208,181,208,191,208,181,209,128,208,181,\n208,180,209,135,208,176,209,129,209,130,208,184,209,135,208,176,209,129,209,130,\n209,140,209,128,208,176,208,177,208,190,209,130,208,189,208,190,208,178,209,139,\n209,133,208,191,209,128,208,176,208,178,208,190,209,129,208,190,208,177,208,190,\n208,185,208,191,208,190,209,130,208,190,208,188,208,188,208,181,208,189,208,181,\n208,181,209,135,208,184,209,129,208,187,208,181,208,189,208,190,208,178,209,139,\n208,181,209,131,209,129,208,187,209,131,208,179,208,190,208,186,208,190,208,187,\n208,190,208,189,208,176,208,183,208,176,208,180,209,130,208,176,208,186,208,190,\n208,181,209,130,208,190,208,179,208,180,208,176,208,191,208,190,209,135,209,130,\n208,184,208,159,208,190,209,129,208,187,208,181,209,130,208,176,208,186,208,184,\n208,181,208,189,208,190,208,178,209,139,208,185,209,129,209,130,208,190,208,184,\n209,130,209,130,208,176,208,186,208,184,209,133,209,129,209,128,208,176,208,183,\n209,131,208,161,208,176,208,189,208,186,209,130,209,132,208,190,209,128,209,131,\n208,188,208,154,208,190,208,179,208,180,208,176,208,186,208,189,208,184,208,179,\n208,184,209,129,208,187,208,190,208,178,208,176,208,189,208,176,209,136,208,181,\n208,185,208,189,208,176,208,185,209,130,208,184,209,129,208,178,208,190,208,184,\n208,188,209,129,208,178,209,143,208,183,209,140,208,187,209,142,208,177,208,190,\n208,185,209,135,208,176,209,129,209,130,208,190,209,129,209,128,208,181,208,180,\n208,184,208,154,209,128,208,190,208,188,208,181,208,164,208,190,209,128,209,131,\n208,188,209,128,209,139,208,189,208,186,208,181,209,129,209,130,208,176,208,187,\n208,184,208,191,208,190,208,184,209,129,208,186,209,130,209,139,209,129,209,143,\n209,135,208,188,208,181,209,129,209,143,209,134,209,134,208,181,208,189,209,130,\n209,128,209,130,209,128,209,131,208,180,208,176,209,129,208,176,208,188,209,139,\n209,133,209,128,209,139,208,189,208,186,208,176,208,157,208,190,208,178,209,139,\n208,185,209,135,208,176,209,129,208,190,208,178,208,188,208,181,209,129,209,130,\n208,176,209,132,208,184,208,187,209,140,208,188,208,188,208,176,209,128,209,130,\n208,176,209,129,209,130,209,128,208,176,208,189,208,188,208,181,209,129,209,130,\n208,181,209,130,208,181,208,186,209,129,209,130,208,189,208,176,209,136,208,184,\n209,133,208,188,208,184,208,189,209,131,209,130,208,184,208,188,208,181,208,189,\n208,184,208,184,208,188,208,181,209,142,209,130,208,189,208,190,208,188,208,181,\n209,128,208,179,208,190,209,128,208,190,208,180,209,129,208,176,208,188,208,190,\n208,188,209,141,209,130,208,190,208,188,209,131,208,186,208,190,208,189,209,134,\n208,181,209,129,208,178,208,190,208,181,208,188,208,186,208,176,208,186,208,190,\n208,185,208,144,209,128,209,133,208,184,208,178,217,133,217,134,216,170,216,175,\n217,137,216,165,216,177,216,179,216,167,217,132,216,177,216,179,216,167,217,132,\n216,169,216,167,217,132,216,185,216,167,217,133,217,131,216,170,216,168,217,135,\n216,167,216,168,216,177,216,167,217,133,216,172,216,167,217,132,217,138,217,136,\n217,133,216,167,217,132,216,181,217,136,216,177,216,172,216,175,217,138,216,175,\n216,169,216,167,217,132,216,185,216,182,217,136,216,165,216,182,216,167,217,129,\n216,169,216,167,217,132,217,130,216,179,217,133,216,167,217,132,216,185,216,167,\n216,168,216,170,216,173,217,133,217,138,217,132,217,133,217,132,217,129,216,167,\n216,170,217,133,217,132,216,170,217,130,217,137,216,170,216,185,216,175,217,138,\n217,132,216,167,217,132,216,180,216,185,216,177,216,163,216,174,216,168,216,167,\n216,177,216,170,216,183,217,136,217,138,216,177,216,185,217,132,217,138,217,131,\n217,133,216,165,216,177,217,129,216,167,217,130,216,183,217,132,216,168,216,167,\n216,170,216,167,217,132,217,132,216,186,216,169,216,170,216,177,216,170,217,138,\n216,168,216,167,217,132,217,134,216,167,216,179,216,167,217,132,216,180,217,138,\n216,174,217,133,217,134,216,170,216,175,217,138,216,167,217,132,216,185,216,177,\n216,168,216,167,217,132,217,130,216,181,216,181,216,167,217,129,217,132,216,167,\n217,133,216,185,217,132,217,138,217,135,216,167,216,170,216,173,216,175,217,138,\n216,171,216,167,217,132,217,132,217,135,217,133,216,167,217,132,216,185,217,133,\n217,132,217,133,217,131,216,170,216,168,216,169,217,138,217,133,217,131,217,134,\n217,131,216,167,217,132,216,183,217,129,217,132,217,129,217,138,216,175,217,138,\n217,136,216,165,216,175,216,167,216,177,216,169,216,170,216,167,216,177,217,138,\n216,174,216,167,217,132,216,181,216,173,216,169,216,170,216,179,216,172,217,138,\n217,132,216,167,217,132,217,136,217,130,216,170,216,185,217,134,216,175,217,133,\n216,167,217,133,216,175,217,138,217,134,216,169,216,170,216,181,217,133,217,138,\n217,133,216,163,216,177,216,180,217,138,217,129,216,167,217,132,216,176,217,138,\n217,134,216,185,216,177,216,168,217,138,216,169,216,168,217,136,216,167,216,168,\n216,169,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,179,217,129,\n216,177,217,133,216,180,216,167,217,131,217,132,216,170,216,185,216,167,217,132,\n217,137,216,167,217,132,216,163,217,136,217,132,216,167,217,132,216,179,217,134,\n216,169,216,172,216,167,217,133,216,185,216,169,216,167,217,132,216,181,216,173,\n217,129,216,167,217,132,216,175,217,138,217,134,217,131,217,132,217,133,216,167,\n216,170,216,167,217,132,216,174,216,167,216,181,216,167,217,132,217,133,217,132,\n217,129,216,163,216,185,216,182,216,167,216,161,217,131,216,170,216,167,216,168,\n216,169,216,167,217,132,216,174,217,138,216,177,216,177,216,179,216,167,216,166,\n217,132,216,167,217,132,217,130,217,132,216,168,216,167,217,132,216,163,216,175,\n216,168,217,133,217,130,216,167,216,183,216,185,217,133,216,177,216,167,216,179,\n217,132,217,133,217,134,216,183,217,130,216,169,216,167,217,132,217,131,216,170,\n216,168,216,167,217,132,216,177,216,172,217,132,216,167,216,180,216,170,216,177,\n217,131,216,167,217,132,217,130,216,175,217,133,217,138,216,185,216,183,217,138,\n217,131,115,66,121,84,97,103,78,97,109,101,40,46,106,112,103,34,32,97,108,116,61\n,34,49,112,120,32,115,111,108,105,100,32,35,46,103,105,102,34,32,97,108,116,61,\n34,116,114,97,110,115,112,97,114,101,110,116,105,110,102,111,114,109,97,116,105,\n111,110,97,112,112,108,105,99,97,116,105,111,110,34,32,111,110,99,108,105,99,107\n,61,34,101,115,116,97,98,108,105,115,104,101,100,97,100,118,101,114,116,105,115,\n105,110,103,46,112,110,103,34,32,97,108,116,61,34,101,110,118,105,114,111,110,\n109,101,110,116,112,101,114,102,111,114,109,97,110,99,101,97,112,112,114,111,112\n,114,105,97,116,101,38,97,109,112,59,109,100,97,115,104,59,105,109,109,101,100,\n105,97,116,101,108,121,60,47,115,116,114,111,110,103,62,60,47,114,97,116,104,101\n,114,32,116,104,97,110,116,101,109,112,101,114,97,116,117,114,101,100,101,118,\n101,108,111,112,109,101,110,116,99,111,109,112,101,116,105,116,105,111,110,112,\n108,97,99,101,104,111,108,100,101,114,118,105,115,105,98,105,108,105,116,121,58,\n99,111,112,121,114,105,103,104,116,34,62,48,34,32,104,101,105,103,104,116,61,34,\n101,118,101,110,32,116,104,111,117,103,104,114,101,112,108,97,99,101,109,101,110\n,116,100,101,115,116,105,110,97,116,105,111,110,67,111,114,112,111,114,97,116,\n105,111,110,60,117,108,32,99,108,97,115,115,61,34,65,115,115,111,99,105,97,116,\n105,111,110,105,110,100,105,118,105,100,117,97,108,115,112,101,114,115,112,101,\n99,116,105,118,101,115,101,116,84,105,109,101,111,117,116,40,117,114,108,40,104,\n116,116,112,58,47,47,109,97,116,104,101,109,97,116,105,99,115,109,97,114,103,105\n,110,45,116,111,112,58,101,118,101,110,116,117,97,108,108,121,32,100,101,115,99,\n114,105,112,116,105,111,110,41,32,110,111,45,114,101,112,101,97,116,99,111,108,\n108,101,99,116,105,111,110,115,46,74,80,71,124,116,104,117,109,98,124,112,97,114\n,116,105,99,105,112,97,116,101,47,104,101,97,100,62,60,98,111,100,121,102,108,\n111,97,116,58,108,101,102,116,59,60,108,105,32,99,108,97,115,115,61,34,104,117,\n110,100,114,101,100,115,32,111,102,10,10,72,111,119,101,118,101,114,44,32,99,111\n,109,112,111,115,105,116,105,111,110,99,108,101,97,114,58,98,111,116,104,59,99,\n111,111,112,101,114,97,116,105,111,110,119,105,116,104,105,110,32,116,104,101,32\n,108,97,98,101,108,32,102,111,114,61,34,98,111,114,100,101,114,45,116,111,112,58\n,78,101,119,32,90,101,97,108,97,110,100,114,101,99,111,109,109,101,110,100,101,\n100,112,104,111,116,111,103,114,97,112,104,121,105,110,116,101,114,101,115,116,\n105,110,103,38,108,116,59,115,117,112,38,103,116,59,99,111,110,116,114,111,118,\n101,114,115,121,78,101,116,104,101,114,108,97,110,100,115,97,108,116,101,114,110\n,97,116,105,118,101,109,97,120,108,101,110,103,116,104,61,34,115,119,105,116,122\n,101,114,108,97,110,100,68,101,118,101,108,111,112,109,101,110,116,101,115,115,\n101,110,116,105,97,108,108,121,10,10,65,108,116,104,111,117,103,104,32,60,47,116\n,101,120,116,97,114,101,97,62,116,104,117,110,100,101,114,98,105,114,100,114,101\n,112,114,101,115,101,110,116,101,100,38,97,109,112,59,110,100,97,115,104,59,115,\n112,101,99,117,108,97,116,105,111,110,99,111,109,109,117,110,105,116,105,101,115\n,108,101,103,105,115,108,97,116,105,111,110,101,108,101,99,116,114,111,110,105,\n99,115,10,9,60,100,105,118,32,105,100,61,34,105,108,108,117,115,116,114,97,116,\n101,100,101,110,103,105,110,101,101,114,105,110,103,116,101,114,114,105,116,111,\n114,105,101,115,97,117,116,104,111,114,105,116,105,101,115,100,105,115,116,114,\n105,98,117,116,101,100,54,34,32,104,101,105,103,104,116,61,34,115,97,110,115,45,\n115,101,114,105,102,59,99,97,112,97,98,108,101,32,111,102,32,100,105,115,97,112,\n112,101,97,114,101,100,105,110,116,101,114,97,99,116,105,118,101,108,111,111,107\n,105,110,103,32,102,111,114,105,116,32,119,111,117,108,100,32,98,101,65,102,103,\n104,97,110,105,115,116,97,110,119,97,115,32,99,114,101,97,116,101,100,77,97,116,\n104,46,102,108,111,111,114,40,115,117,114,114,111,117,110,100,105,110,103,99,97,\n110,32,97,108,115,111,32,98,101,111,98,115,101,114,118,97,116,105,111,110,109,97\n,105,110,116,101,110,97,110,99,101,101,110,99,111,117,110,116,101,114,101,100,60\n,104,50,32,99,108,97,115,115,61,34,109,111,114,101,32,114,101,99,101,110,116,105\n,116,32,104,97,115,32,98,101,101,110,105,110,118,97,115,105,111,110,32,111,102,\n41,46,103,101,116,84,105,109,101,40,41,102,117,110,100,97,109,101,110,116,97,108\n,68,101,115,112,105,116,101,32,116,104,101,34,62,60,100,105,118,32,105,100,61,34\n,105,110,115,112,105,114,97,116,105,111,110,101,120,97,109,105,110,97,116,105,\n111,110,112,114,101,112,97,114,97,116,105,111,110,101,120,112,108,97,110,97,116,\n105,111,110,60,105,110,112,117,116,32,105,100,61,34,60,47,97,62,60,47,115,112,97\n,110,62,118,101,114,115,105,111,110,115,32,111,102,105,110,115,116,114,117,109,\n101,110,116,115,98,101,102,111,114,101,32,116,104,101,32,32,61,32,39,104,116,116\n,112,58,47,47,68,101,115,99,114,105,112,116,105,111,110,114,101,108,97,116,105,\n118,101,108,121,32,46,115,117,98,115,116,114,105,110,103,40,101,97,99,104,32,111\n,102,32,116,104,101,101,120,112,101,114,105,109,101,110,116,115,105,110,102,108,\n117,101,110,116,105,97,108,105,110,116,101,103,114,97,116,105,111,110,109,97,110\n,121,32,112,101,111,112,108,101,100,117,101,32,116,111,32,116,104,101,32,99,111,\n109,98,105,110,97,116,105,111,110,100,111,32,110,111,116,32,104,97,118,101,77,\n105,100,100,108,101,32,69,97,115,116,60,110,111,115,99,114,105,112,116,62,60,99,\n111,112,121,114,105,103,104,116,34,32,112,101,114,104,97,112,115,32,116,104,101,\n105,110,115,116,105,116,117,116,105,111,110,105,110,32,68,101,99,101,109,98,101,\n114,97,114,114,97,110,103,101,109,101,110,116,109,111,115,116,32,102,97,109,111,\n117,115,112,101,114,115,111,110,97,108,105,116,121,99,114,101,97,116,105,111,110\n,32,111,102,108,105,109,105,116,97,116,105,111,110,115,101,120,99,108,117,115,\n105,118,101,108,121,115,111,118,101,114,101,105,103,110,116,121,45,99,111,110,\n116,101,110,116,34,62,10,60,116,100,32,99,108,97,115,115,61,34,117,110,100,101,\n114,103,114,111,117,110,100,112,97,114,97,108,108,101,108,32,116,111,100,111,99,\n116,114,105,110,101,32,111,102,111,99,99,117,112,105,101,100,32,98,121,116,101,\n114,109,105,110,111,108,111,103,121,82,101,110,97,105,115,115,97,110,99,101,97,\n32,110,117,109,98,101,114,32,111,102,115,117,112,112,111,114,116,32,102,111,114,\n101,120,112,108,111,114,97,116,105,111,110,114,101,99,111,103,110,105,116,105,\n111,110,112,114,101,100,101,99,101,115,115,111,114,60,105,109,103,32,115,114,99,\n61,34,47,60,104,49,32,99,108,97,115,115,61,34,112,117,98,108,105,99,97,116,105,\n111,110,109,97,121,32,97,108,115,111,32,98,101,115,112,101,99,105,97,108,105,122\n,101,100,60,47,102,105,101,108,100,115,101,116,62,112,114,111,103,114,101,115,\n115,105,118,101,109,105,108,108,105,111,110,115,32,111,102,115,116,97,116,101,\n115,32,116,104,97,116,101,110,102,111,114,99,101,109,101,110,116,97,114,111,117,\n110,100,32,116,104,101,32,111,110,101,32,97,110,111,116,104,101,114,46,112,97,\n114,101,110,116,78,111,100,101,97,103,114,105,99,117,108,116,117,114,101,65,108,\n116,101,114,110,97,116,105,118,101,114,101,115,101,97,114,99,104,101,114,115,116\n,111,119,97,114,100,115,32,116,104,101,77,111,115,116,32,111,102,32,116,104,101,\n109,97,110,121,32,111,116,104,101,114,32,40,101,115,112,101,99,105,97,108,108,\n121,60,116,100,32,119,105,100,116,104,61,34,59,119,105,100,116,104,58,49,48,48,\n37,105,110,100,101,112,101,110,100,101,110,116,60,104,51,32,99,108,97,115,115,61\n,34,32,111,110,99,104,97,110,103,101,61,34,41,46,97,100,100,67,108,97,115,115,40\n,105,110,116,101,114,97,99,116,105,111,110,79,110,101,32,111,102,32,116,104,101,\n32,100,97,117,103,104,116,101,114,32,111,102,97,99,99,101,115,115,111,114,105,\n101,115,98,114,97,110,99,104,101,115,32,111,102,13,10,60,100,105,118,32,105,100,\n61,34,116,104,101,32,108,97,114,103,101,115,116,100,101,99,108,97,114,97,116,105\n,111,110,114,101,103,117,108,97,116,105,111,110,115,73,110,102,111,114,109,97,\n116,105,111,110,116,114,97,110,115,108,97,116,105,111,110,100,111,99,117,109,101\n,110,116,97,114,121,105,110,32,111,114,100,101,114,32,116,111,34,62,10,60,104,\n101,97,100,62,10,60,34,32,104,101,105,103,104,116,61,34,49,97,99,114,111,115,115\n,32,116,104,101,32,111,114,105,101,110,116,97,116,105,111,110,41,59,60,47,115,99\n,114,105,112,116,62,105,109,112,108,101,109,101,110,116,101,100,99,97,110,32,98,\n101,32,115,101,101,110,116,104,101,114,101,32,119,97,115,32,97,100,101,109,111,\n110,115,116,114,97,116,101,99,111,110,116,97,105,110,101,114,34,62,99,111,110,\n110,101,99,116,105,111,110,115,116,104,101,32,66,114,105,116,105,115,104,119,97,\n115,32,119,114,105,116,116,101,110,33,105,109,112,111,114,116,97,110,116,59,112,\n120,59,32,109,97,114,103,105,110,45,102,111,108,108,111,119,101,100,32,98,121,97\n,98,105,108,105,116,121,32,116,111,32,99,111,109,112,108,105,99,97,116,101,100,\n100,117,114,105,110,103,32,116,104,101,32,105,109,109,105,103,114,97,116,105,111\n,110,97,108,115,111,32,99,97,108,108,101,100,60,104,52,32,99,108,97,115,115,61,\n34,100,105,115,116,105,110,99,116,105,111,110,114,101,112,108,97,99,101,100,32,\n98,121,103,111,118,101,114,110,109,101,110,116,115,108,111,99,97,116,105,111,110\n,32,111,102,105,110,32,78,111,118,101,109,98,101,114,119,104,101,116,104,101,114\n,32,116,104,101,60,47,112,62,10,60,47,100,105,118,62,97,99,113,117,105,115,105,\n116,105,111,110,99,97,108,108,101,100,32,116,104,101,32,112,101,114,115,101,99,\n117,116,105,111,110,100,101,115,105,103,110,97,116,105,111,110,123,102,111,110,\n116,45,115,105,122,101,58,97,112,112,101,97,114,101,100,32,105,110,105,110,118,\n101,115,116,105,103,97,116,101,101,120,112,101,114,105,101,110,99,101,100,109,\n111,115,116,32,108,105,107,101,108,121,119,105,100,101,108,121,32,117,115,101,\n100,100,105,115,99,117,115,115,105,111,110,115,112,114,101,115,101,110,99,101,32\n,111,102,32,40,100,111,99,117,109,101,110,116,46,101,120,116,101,110,115,105,118\n,101,108,121,73,116,32,104,97,115,32,98,101,101,110,105,116,32,100,111,101,115,\n32,110,111,116,99,111,110,116,114,97,114,121,32,116,111,105,110,104,97,98,105,\n116,97,110,116,115,105,109,112,114,111,118,101,109,101,110,116,115,99,104,111,\n108,97,114,115,104,105,112,99,111,110,115,117,109,112,116,105,111,110,105,110,\n115,116,114,117,99,116,105,111,110,102,111,114,32,101,120,97,109,112,108,101,111\n,110,101,32,111,114,32,109,111,114,101,112,120,59,32,112,97,100,100,105,110,103,\n116,104,101,32,99,117,114,114,101,110,116,97,32,115,101,114,105,101,115,32,111,\n102,97,114,101,32,117,115,117,97,108,108,121,114,111,108,101,32,105,110,32,116,\n104,101,112,114,101,118,105,111,117,115,108,121,32,100,101,114,105,118,97,116,\n105,118,101,115,101,118,105,100,101,110,99,101,32,111,102,101,120,112,101,114,\n105,101,110,99,101,115,99,111,108,111,114,115,99,104,101,109,101,115,116,97,116,\n101,100,32,116,104,97,116,99,101,114,116,105,102,105,99,97,116,101,60,47,97,62,\n60,47,100,105,118,62,10,32,115,101,108,101,99,116,101,100,61,34,104,105,103,104,\n32,115,99,104,111,111,108,114,101,115,112,111,110,115,101,32,116,111,99,111,109,\n102,111,114,116,97,98,108,101,97,100,111,112,116,105,111,110,32,111,102,116,104,\n114,101,101,32,121,101,97,114,115,116,104,101,32,99,111,117,110,116,114,121,105,\n110,32,70,101,98,114,117,97,114,121,115,111,32,116,104,97,116,32,116,104,101,112\n,101,111,112,108,101,32,119,104,111,32,112,114,111,118,105,100,101,100,32,98,121\n,60,112,97,114,97,109,32,110,97,109,101,97,102,102,101,99,116,101,100,32,98,121,\n105,110,32,116,101,114,109,115,32,111,102,97,112,112,111,105,110,116,109,101,110\n,116,73,83,79,45,56,56,53,57,45,49,34,119,97,115,32,98,111,114,110,32,105,110,\n104,105,115,116,111,114,105,99,97,108,32,114,101,103,97,114,100,101,100,32,97,\n115,109,101,97,115,117,114,101,109,101,110,116,105,115,32,98,97,115,101,100,32,\n111,110,32,97,110,100,32,111,116,104,101,114,32,58,32,102,117,110,99,116,105,111\n,110,40,115,105,103,110,105,102,105,99,97,110,116,99,101,108,101,98,114,97,116,\n105,111,110,116,114,97,110,115,109,105,116,116,101,100,47,106,115,47,106,113,117\n,101,114,121,46,105,115,32,107,110,111,119,110,32,97,115,116,104,101,111,114,101\n,116,105,99,97,108,32,116,97,98,105,110,100,101,120,61,34,105,116,32,99,111,117,\n108,100,32,98,101,60,110,111,115,99,114,105,112,116,62,10,104,97,118,105,110,103\n,32,98,101,101,110,13,10,60,104,101,97,100,62,13,10,60,32,38,113,117,111,116,59,\n84,104,101,32,99,111,109,112,105,108,97,116,105,111,110,104,101,32,104,97,100,32\n,98,101,101,110,112,114,111,100,117,99,101,100,32,98,121,112,104,105,108,111,115\n,111,112,104,101,114,99,111,110,115,116,114,117,99,116,101,100,105,110,116,101,\n110,100,101,100,32,116,111,97,109,111,110,103,32,111,116,104,101,114,99,111,109,\n112,97,114,101,100,32,116,111,116,111,32,115,97,121,32,116,104,97,116,69,110,103\n,105,110,101,101,114,105,110,103,97,32,100,105,102,102,101,114,101,110,116,114,\n101,102,101,114,114,101,100,32,116,111,100,105,102,102,101,114,101,110,99,101,\n115,98,101,108,105,101,102,32,116,104,97,116,112,104,111,116,111,103,114,97,112,\n104,115,105,100,101,110,116,105,102,121,105,110,103,72,105,115,116,111,114,121,\n32,111,102,32,82,101,112,117,98,108,105,99,32,111,102,110,101,99,101,115,115,97,\n114,105,108,121,112,114,111,98,97,98,105,108,105,116,121,116,101,99,104,110,105,\n99,97,108,108,121,108,101,97,118,105,110,103,32,116,104,101,115,112,101,99,116,\n97,99,117,108,97,114,102,114,97,99,116,105,111,110,32,111,102,101,108,101,99,116\n,114,105,99,105,116,121,104,101,97,100,32,111,102,32,116,104,101,114,101,115,116\n,97,117,114,97,110,116,115,112,97,114,116,110,101,114,115,104,105,112,101,109,\n112,104,97,115,105,115,32,111,110,109,111,115,116,32,114,101,99,101,110,116,115,\n104,97,114,101,32,119,105,116,104,32,115,97,121,105,110,103,32,116,104,97,116,\n102,105,108,108,101,100,32,119,105,116,104,100,101,115,105,103,110,101,100,32,\n116,111,105,116,32,105,115,32,111,102,116,101,110,34,62,60,47,105,102,114,97,109\n,101,62,97,115,32,102,111,108,108,111,119,115,58,109,101,114,103,101,100,32,119,\n105,116,104,116,104,114,111,117,103,104,32,116,104,101,99,111,109,109,101,114,99\n,105,97,108,32,112,111,105,110,116,101,100,32,111,117,116,111,112,112,111,114,\n116,117,110,105,116,121,118,105,101,119,32,111,102,32,116,104,101,114,101,113,\n117,105,114,101,109,101,110,116,100,105,118,105,115,105,111,110,32,111,102,112,\n114,111,103,114,97,109,109,105,110,103,104,101,32,114,101,99,101,105,118,101,100\n,115,101,116,73,110,116,101,114,118,97,108,34,62,60,47,115,112,97,110,62,60,47,\n105,110,32,78,101,119,32,89,111,114,107,97,100,100,105,116,105,111,110,97,108,32\n,99,111,109,112,114,101,115,115,105,111,110,10,10,60,100,105,118,32,105,100,61,\n34,105,110,99,111,114,112,111,114,97,116,101,59,60,47,115,99,114,105,112,116,62,\n60,97,116,116,97,99,104,69,118,101,110,116,98,101,99,97,109,101,32,116,104,101,\n32,34,32,116,97,114,103,101,116,61,34,95,99,97,114,114,105,101,100,32,111,117,\n116,83,111,109,101,32,111,102,32,116,104,101,115,99,105,101,110,99,101,32,97,110\n,100,116,104,101,32,116,105,109,101,32,111,102,67,111,110,116,97,105,110,101,114\n,34,62,109,97,105,110,116,97,105,110,105,110,103,67,104,114,105,115,116,111,112,\n104,101,114,77,117,99,104,32,111,102,32,116,104,101,119,114,105,116,105,110,103,\n115,32,111,102,34,32,104,101,105,103,104,116,61,34,50,115,105,122,101,32,111,102\n,32,116,104,101,118,101,114,115,105,111,110,32,111,102,32,109,105,120,116,117,\n114,101,32,111,102,32,98,101,116,119,101,101,110,32,116,104,101,69,120,97,109,\n112,108,101,115,32,111,102,101,100,117,99,97,116,105,111,110,97,108,99,111,109,\n112,101,116,105,116,105,118,101,32,111,110,115,117,98,109,105,116,61,34,100,105,\n114,101,99,116,111,114,32,111,102,100,105,115,116,105,110,99,116,105,118,101,47,\n68,84,68,32,88,72,84,77,76,32,114,101,108,97,116,105,110,103,32,116,111,116,101,\n110,100,101,110,99,121,32,116,111,112,114,111,118,105,110,99,101,32,111,102,119,\n104,105,99,104,32,119,111,117,108,100,100,101,115,112,105,116,101,32,116,104,101\n,115,99,105,101,110,116,105,102,105,99,32,108,101,103,105,115,108,97,116,117,114\n,101,46,105,110,110,101,114,72,84,77,76,32,97,108,108,101,103,97,116,105,111,110\n,115,65,103,114,105,99,117,108,116,117,114,101,119,97,115,32,117,115,101,100,32,\n105,110,97,112,112,114,111,97,99,104,32,116,111,105,110,116,101,108,108,105,103,\n101,110,116,121,101,97,114,115,32,108,97,116,101,114,44,115,97,110,115,45,115,\n101,114,105,102,100,101,116,101,114,109,105,110,105,110,103,80,101,114,102,111,\n114,109,97,110,99,101,97,112,112,101,97,114,97,110,99,101,115,44,32,119,104,105,\n99,104,32,105,115,32,102,111,117,110,100,97,116,105,111,110,115,97,98,98,114,101\n,118,105,97,116,101,100,104,105,103,104,101,114,32,116,104,97,110,115,32,102,114\n,111,109,32,116,104,101,32,105,110,100,105,118,105,100,117,97,108,32,99,111,109,\n112,111,115,101,100,32,111,102,115,117,112,112,111,115,101,100,32,116,111,99,108\n,97,105,109,115,32,116,104,97,116,97,116,116,114,105,98,117,116,105,111,110,102,\n111,110,116,45,115,105,122,101,58,49,101,108,101,109,101,110,116,115,32,111,102,\n72,105,115,116,111,114,105,99,97,108,32,104,105,115,32,98,114,111,116,104,101,\n114,97,116,32,116,104,101,32,116,105,109,101,97,110,110,105,118,101,114,115,97,\n114,121,103,111,118,101,114,110,101,100,32,98,121,114,101,108,97,116,101,100,32,\n116,111,32,117,108,116,105,109,97,116,101,108,121,32,105,110,110,111,118,97,116,\n105,111,110,115,105,116,32,105,115,32,115,116,105,108,108,99,97,110,32,111,110,\n108,121,32,98,101,100,101,102,105,110,105,116,105,111,110,115,116,111,71,77,84,\n83,116,114,105,110,103,65,32,110,117,109,98,101,114,32,111,102,105,109,103,32,99\n,108,97,115,115,61,34,69,118,101,110,116,117,97,108,108,121,44,119,97,115,32,99,\n104,97,110,103,101,100,111,99,99,117,114,114,101,100,32,105,110,110,101,105,103,\n104,98,111,114,105,110,103,100,105,115,116,105,110,103,117,105,115,104,119,104,\n101,110,32,104,101,32,119,97,115,105,110,116,114,111,100,117,99,105,110,103,116,\n101,114,114,101,115,116,114,105,97,108,77,97,110,121,32,111,102,32,116,104,101,\n97,114,103,117,101,115,32,116,104,97,116,97,110,32,65,109,101,114,105,99,97,110,\n99,111,110,113,117,101,115,116,32,111,102,119,105,100,101,115,112,114,101,97,100\n,32,119,101,114,101,32,107,105,108,108,101,100,115,99,114,101,101,110,32,97,110,\n100,32,73,110,32,111,114,100,101,114,32,116,111,101,120,112,101,99,116,101,100,\n32,116,111,100,101,115,99,101,110,100,97,110,116,115,97,114,101,32,108,111,99,97\n,116,101,100,108,101,103,105,115,108,97,116,105,118,101,103,101,110,101,114,97,\n116,105,111,110,115,32,98,97,99,107,103,114,111,117,110,100,109,111,115,116,32,\n112,101,111,112,108,101,121,101,97,114,115,32,97,102,116,101,114,116,104,101,114\n,101,32,105,115,32,110,111,116,104,101,32,104,105,103,104,101,115,116,102,114,\n101,113,117,101,110,116,108,121,32,116,104,101,121,32,100,111,32,110,111,116,97,\n114,103,117,101,100,32,116,104,97,116,115,104,111,119,101,100,32,116,104,97,116,\n112,114,101,100,111,109,105,110,97,110,116,116,104,101,111,108,111,103,105,99,97\n,108,98,121,32,116,104,101,32,116,105,109,101,99,111,110,115,105,100,101,114,105\n,110,103,115,104,111,114,116,45,108,105,118,101,100,60,47,115,112,97,110,62,60,\n47,97,62,99,97,110,32,98,101,32,117,115,101,100,118,101,114,121,32,108,105,116,\n116,108,101,111,110,101,32,111,102,32,116,104,101,32,104,97,100,32,97,108,114,\n101,97,100,121,105,110,116,101,114,112,114,101,116,101,100,99,111,109,109,117,\n110,105,99,97,116,101,102,101,97,116,117,114,101,115,32,111,102,103,111,118,101,\n114,110,109,101,110,116,44,60,47,110,111,115,99,114,105,112,116,62,101,110,116,\n101,114,101,100,32,116,104,101,34,32,104,101,105,103,104,116,61,34,51,73,110,100\n,101,112,101,110,100,101,110,116,112,111,112,117,108,97,116,105,111,110,115,108,\n97,114,103,101,45,115,99,97,108,101,46,32,65,108,116,104,111,117,103,104,32,117,\n115,101,100,32,105,110,32,116,104,101,100,101,115,116,114,117,99,116,105,111,110\n,112,111,115,115,105,98,105,108,105,116,121,115,116,97,114,116,105,110,103,32,\n105,110,116,119,111,32,111,114,32,109,111,114,101,101,120,112,114,101,115,115,\n105,111,110,115,115,117,98,111,114,100,105,110,97,116,101,108,97,114,103,101,114\n,32,116,104,97,110,104,105,115,116,111,114,121,32,97,110,100,60,47,111,112,116,\n105,111,110,62,13,10,67,111,110,116,105,110,101,110,116,97,108,101,108,105,109,\n105,110,97,116,105,110,103,119,105,108,108,32,110,111,116,32,98,101,112,114,97,\n99,116,105,99,101,32,111,102,105,110,32,102,114,111,110,116,32,111,102,115,105,\n116,101,32,111,102,32,116,104,101,101,110,115,117,114,101,32,116,104,97,116,116,\n111,32,99,114,101,97,116,101,32,97,109,105,115,115,105,115,115,105,112,112,105,\n112,111,116,101,110,116,105,97,108,108,121,111,117,116,115,116,97,110,100,105,\n110,103,98,101,116,116,101,114,32,116,104,97,110,119,104,97,116,32,105,115,32,\n110,111,119,115,105,116,117,97,116,101,100,32,105,110,109,101,116,97,32,110,97,\n109,101,61,34,84,114,97,100,105,116,105,111,110,97,108,115,117,103,103,101,115,\n116,105,111,110,115,84,114,97,110,115,108,97,116,105,111,110,116,104,101,32,102,\n111,114,109,32,111,102,97,116,109,111,115,112,104,101,114,105,99,105,100,101,111\n,108,111,103,105,99,97,108,101,110,116,101,114,112,114,105,115,101,115,99,97,108\n,99,117,108,97,116,105,110,103,101,97,115,116,32,111,102,32,116,104,101,114,101,\n109,110,97,110,116,115,32,111,102,112,108,117,103,105,110,115,112,97,103,101,47,\n105,110,100,101,120,46,112,104,112,63,114,101,109,97,105,110,101,100,32,105,110,\n116,114,97,110,115,102,111,114,109,101,100,72,101,32,119,97,115,32,97,108,115,\n111,119,97,115,32,97,108,114,101,97,100,121,115,116,97,116,105,115,116,105,99,97\n,108,105,110,32,102,97,118,111,114,32,111,102,77,105,110,105,115,116,114,121,32,\n111,102,109,111,118,101,109,101,110,116,32,111,102,102,111,114,109,117,108,97,\n116,105,111,110,105,115,32,114,101,113,117,105,114,101,100,60,108,105,110,107,32\n,114,101,108,61,34,84,104,105,115,32,105,115,32,116,104,101,32,60,97,32,104,114,\n101,102,61,34,47,112,111,112,117,108,97,114,105,122,101,100,105,110,118,111,108,\n118,101,100,32,105,110,97,114,101,32,117,115,101,100,32,116,111,97,110,100,32,\n115,101,118,101,114,97,108,109,97,100,101,32,98,121,32,116,104,101,115,101,101,\n109,115,32,116,111,32,98,101,108,105,107,101,108,121,32,116,104,97,116,80,97,108\n,101,115,116,105,110,105,97,110,110,97,109,101,100,32,97,102,116,101,114,105,116\n,32,104,97,100,32,98,101,101,110,109,111,115,116,32,99,111,109,109,111,110,116,\n111,32,114,101,102,101,114,32,116,111,98,117,116,32,116,104,105,115,32,105,115,\n99,111,110,115,101,99,117,116,105,118,101,116,101,109,112,111,114,97,114,105,108\n,121,73,110,32,103,101,110,101,114,97,108,44,99,111,110,118,101,110,116,105,111,\n110,115,116,97,107,101,115,32,112,108,97,99,101,115,117,98,100,105,118,105,115,\n105,111,110,116,101,114,114,105,116,111,114,105,97,108,111,112,101,114,97,116,\n105,111,110,97,108,112,101,114,109,97,110,101,110,116,108,121,119,97,115,32,108,\n97,114,103,101,108,121,111,117,116,98,114,101,97,107,32,111,102,105,110,32,116,\n104,101,32,112,97,115,116,102,111,108,108,111,119,105,110,103,32,97,32,120,109,\n108,110,115,58,111,103,61,34,62,60,97,32,99,108,97,115,115,61,34,99,108,97,115,\n115,61,34,116,101,120,116,67,111,110,118,101,114,115,105,111,110,32,109,97,121,\n32,98,101,32,117,115,101,100,109,97,110,117,102,97,99,116,117,114,101,97,102,116\n,101,114,32,98,101,105,110,103,99,108,101,97,114,102,105,120,34,62,10,113,117,\n101,115,116,105,111,110,32,111,102,119,97,115,32,101,108,101,99,116,101,100,116,\n111,32,98,101,99,111,109,101,32,97,98,101,99,97,117,115,101,32,111,102,32,115,\n111,109,101,32,112,101,111,112,108,101,105,110,115,112,105,114,101,100,32,98,121\n,115,117,99,99,101,115,115,102,117,108,32,97,32,116,105,109,101,32,119,104,101,\n110,109,111,114,101,32,99,111,109,109,111,110,97,109,111,110,103,115,116,32,116,\n104,101,97,110,32,111,102,102,105,99,105,97,108,119,105,100,116,104,58,49,48,48,\n37,59,116,101,99,104,110,111,108,111,103,121,44,119,97,115,32,97,100,111,112,116\n,101,100,116,111,32,107,101,101,112,32,116,104,101,115,101,116,116,108,101,109,\n101,110,116,115,108,105,118,101,32,98,105,114,116,104,115,105,110,100,101,120,46\n,104,116,109,108,34,67,111,110,110,101,99,116,105,99,117,116,97,115,115,105,103,\n110,101,100,32,116,111,38,97,109,112,59,116,105,109,101,115,59,97,99,99,111,117,\n110,116,32,102,111,114,97,108,105,103,110,61,114,105,103,104,116,116,104,101,32,\n99,111,109,112,97,110,121,97,108,119,97,121,115,32,98,101,101,110,114,101,116,\n117,114,110,101,100,32,116,111,105,110,118,111,108,118,101,109,101,110,116,66,\n101,99,97,117,115,101,32,116,104,101,116,104,105,115,32,112,101,114,105,111,100,\n34,32,110,97,109,101,61,34,113,34,32,99,111,110,102,105,110,101,100,32,116,111,\n97,32,114,101,115,117,108,116,32,111,102,118,97,108,117,101,61,34,34,32,47,62,\n105,115,32,97,99,116,117,97,108,108,121,69,110,118,105,114,111,110,109,101,110,\n116,13,10,60,47,104,101,97,100,62,13,10,67,111,110,118,101,114,115,101,108,121,\n44,62,10,60,100,105,118,32,105,100,61,34,48,34,32,119,105,100,116,104,61,34,49,\n105,115,32,112,114,111,98,97,98,108,121,104,97,118,101,32,98,101,99,111,109,101,\n99,111,110,116,114,111,108,108,105,110,103,116,104,101,32,112,114,111,98,108,101\n,109,99,105,116,105,122,101,110,115,32,111,102,112,111,108,105,116,105,99,105,97\n,110,115,114,101,97,99,104,101,100,32,116,104,101,97,115,32,101,97,114,108,121,\n32,97,115,58,110,111,110,101,59,32,111,118,101,114,60,116,97,98,108,101,32,99,\n101,108,108,118,97,108,105,100,105,116,121,32,111,102,100,105,114,101,99,116,108\n,121,32,116,111,111,110,109,111,117,115,101,100,111,119,110,119,104,101,114,101,\n32,105,116,32,105,115,119,104,101,110,32,105,116,32,119,97,115,109,101,109,98,\n101,114,115,32,111,102,32,114,101,108,97,116,105,111,110,32,116,111,97,99,99,111\n,109,109,111,100,97,116,101,97,108,111,110,103,32,119,105,116,104,32,73,110,32,\n116,104,101,32,108,97,116,101,116,104,101,32,69,110,103,108,105,115,104,100,101,\n108,105,99,105,111,117,115,34,62,116,104,105,115,32,105,115,32,110,111,116,116,\n104,101,32,112,114,101,115,101,110,116,105,102,32,116,104,101,121,32,97,114,101,\n97,110,100,32,102,105,110,97,108,108,121,97,32,109,97,116,116,101,114,32,111,102\n,13,10,9,60,47,100,105,118,62,13,10,13,10,60,47,115,99,114,105,112,116,62,102,97\n,115,116,101,114,32,116,104,97,110,109,97,106,111,114,105,116,121,32,111,102,97,\n102,116,101,114,32,119,104,105,99,104,99,111,109,112,97,114,97,116,105,118,101,\n116,111,32,109,97,105,110,116,97,105,110,105,109,112,114,111,118,101,32,116,104,\n101,97,119,97,114,100,101,100,32,116,104,101,101,114,34,32,99,108,97,115,115,61,\n34,102,114,97,109,101,98,111,114,100,101,114,114,101,115,116,111,114,97,116,105,\n111,110,105,110,32,116,104,101,32,115,97,109,101,97,110,97,108,121,115,105,115,\n32,111,102,116,104,101,105,114,32,102,105,114,115,116,68,117,114,105,110,103,32,\n116,104,101,32,99,111,110,116,105,110,101,110,116,97,108,115,101,113,117,101,110\n,99,101,32,111,102,102,117,110,99,116,105,111,110,40,41,123,102,111,110,116,45,\n115,105,122,101,58,32,119,111,114,107,32,111,110,32,116,104,101,60,47,115,99,114\n,105,112,116,62,10,60,98,101,103,105,110,115,32,119,105,116,104,106,97,118,97,\n115,99,114,105,112,116,58,99,111,110,115,116,105,116,117,101,110,116,119,97,115,\n32,102,111,117,110,100,101,100,101,113,117,105,108,105,98,114,105,117,109,97,115\n,115,117,109,101,32,116,104,97,116,105,115,32,103,105,118,101,110,32,98,121,110,\n101,101,100,115,32,116,111,32,98,101,99,111,111,114,100,105,110,97,116,101,115,\n116,104,101,32,118,97,114,105,111,117,115,97,114,101,32,112,97,114,116,32,111,\n102,111,110,108,121,32,105,110,32,116,104,101,115,101,99,116,105,111,110,115,32,\n111,102,105,115,32,97,32,99,111,109,109,111,110,116,104,101,111,114,105,101,115,\n32,111,102,100,105,115,99,111,118,101,114,105,101,115,97,115,115,111,99,105,97,\n116,105,111,110,101,100,103,101,32,111,102,32,116,104,101,115,116,114,101,110,\n103,116,104,32,111,102,112,111,115,105,116,105,111,110,32,105,110,112,114,101,\n115,101,110,116,45,100,97,121,117,110,105,118,101,114,115,97,108,108,121,116,111\n,32,102,111,114,109,32,116,104,101,98,117,116,32,105,110,115,116,101,97,100,99,\n111,114,112,111,114,97,116,105,111,110,97,116,116,97,99,104,101,100,32,116,111,\n105,115,32,99,111,109,109,111,110,108,121,114,101,97,115,111,110,115,32,102,111,\n114,32,38,113,117,111,116,59,116,104,101,32,99,97,110,32,98,101,32,109,97,100,\n101,119,97,115,32,97,98,108,101,32,116,111,119,104,105,99,104,32,109,101,97,110,\n115,98,117,116,32,100,105,100,32,110,111,116,111,110,77,111,117,115,101,79,118,\n101,114,97,115,32,112,111,115,115,105,98,108,101,111,112,101,114,97,116,101,100,\n32,98,121,99,111,109,105,110,103,32,102,114,111,109,116,104,101,32,112,114,105,\n109,97,114,121,97,100,100,105,116,105,111,110,32,111,102,102,111,114,32,115,101,\n118,101,114,97,108,116,114,97,110,115,102,101,114,114,101,100,97,32,112,101,114,\n105,111,100,32,111,102,97,114,101,32,97,98,108,101,32,116,111,104,111,119,101,\n118,101,114,44,32,105,116,115,104,111,117,108,100,32,104,97,118,101,109,117,99,\n104,32,108,97,114,103,101,114,10,9,60,47,115,99,114,105,112,116,62,97,100,111,\n112,116,101,100,32,116,104,101,112,114,111,112,101,114,116,121,32,111,102,100,\n105,114,101,99,116,101,100,32,98,121,101,102,102,101,99,116,105,118,101,108,121,\n119,97,115,32,98,114,111,117,103,104,116,99,104,105,108,100,114,101,110,32,111,\n102,80,114,111,103,114,97,109,109,105,110,103,108,111,110,103,101,114,32,116,104\n,97,110,109,97,110,117,115,99,114,105,112,116,115,119,97,114,32,97,103,97,105,\n110,115,116,98,121,32,109,101,97,110,115,32,111,102,97,110,100,32,109,111,115,\n116,32,111,102,115,105,109,105,108,97,114,32,116,111,32,112,114,111,112,114,105,\n101,116,97,114,121,111,114,105,103,105,110,97,116,105,110,103,112,114,101,115,\n116,105,103,105,111,117,115,103,114,97,109,109,97,116,105,99,97,108,101,120,112,\n101,114,105,101,110,99,101,46,116,111,32,109,97,107,101,32,116,104,101,73,116,32\n,119,97,115,32,97,108,115,111,105,115,32,102,111,117,110,100,32,105,110,99,111,\n109,112,101,116,105,116,111,114,115,105,110,32,116,104,101,32,85,46,83,46,114,\n101,112,108,97,99,101,32,116,104,101,98,114,111,117,103,104,116,32,116,104,101,\n99,97,108,99,117,108,97,116,105,111,110,102,97,108,108,32,111,102,32,116,104,101\n,116,104,101,32,103,101,110,101,114,97,108,112,114,97,99,116,105,99,97,108,108,\n121,105,110,32,104,111,110,111,114,32,111,102,114,101,108,101,97,115,101,100,32,\n105,110,114,101,115,105,100,101,110,116,105,97,108,97,110,100,32,115,111,109,101\n,32,111,102,107,105,110,103,32,111,102,32,116,104,101,114,101,97,99,116,105,111,\n110,32,116,111,49,115,116,32,69,97,114,108,32,111,102,99,117,108,116,117,114,101\n,32,97,110,100,112,114,105,110,99,105,112,97,108,108,121,60,47,116,105,116,108,\n101,62,10,32,32,116,104,101,121,32,99,97,110,32,98,101,98,97,99,107,32,116,111,\n32,116,104,101,115,111,109,101,32,111,102,32,104,105,115,101,120,112,111,115,117\n,114,101,32,116,111,97,114,101,32,115,105,109,105,108,97,114,102,111,114,109,32,\n111,102,32,116,104,101,97,100,100,70,97,118,111,114,105,116,101,99,105,116,105,\n122,101,110,115,104,105,112,112,97,114,116,32,105,110,32,116,104,101,112,101,111\n,112,108,101,32,119,105,116,104,105,110,32,112,114,97,99,116,105,99,101,116,111,\n32,99,111,110,116,105,110,117,101,38,97,109,112,59,109,105,110,117,115,59,97,112\n,112,114,111,118,101,100,32,98,121,32,116,104,101,32,102,105,114,115,116,32,97,\n108,108,111,119,101,100,32,116,104,101,97,110,100,32,102,111,114,32,116,104,101,\n102,117,110,99,116,105,111,110,105,110,103,112,108,97,121,105,110,103,32,116,104\n,101,115,111,108,117,116,105,111,110,32,116,111,104,101,105,103,104,116,61,34,48\n,34,32,105,110,32,104,105,115,32,98,111,111,107,109,111,114,101,32,116,104,97,\n110,32,97,102,111,108,108,111,119,115,32,116,104,101,99,114,101,97,116,101,100,\n32,116,104,101,112,114,101,115,101,110,99,101,32,105,110,38,110,98,115,112,59,60\n,47,116,100,62,110,97,116,105,111,110,97,108,105,115,116,116,104,101,32,105,100,\n101,97,32,111,102,97,32,99,104,97,114,97,99,116,101,114,119,101,114,101,32,102,\n111,114,99,101,100,32,99,108,97,115,115,61,34,98,116,110,100,97,121,115,32,111,\n102,32,116,104,101,102,101,97,116,117,114,101,100,32,105,110,115,104,111,119,105\n,110,103,32,116,104,101,105,110,116,101,114,101,115,116,32,105,110,105,110,32,\n112,108,97,99,101,32,111,102,116,117,114,110,32,111,102,32,116,104,101,116,104,\n101,32,104,101,97,100,32,111,102,76,111,114,100,32,111,102,32,116,104,101,112,\n111,108,105,116,105,99,97,108,108,121,104,97,115,32,105,116,115,32,111,119,110,\n69,100,117,99,97,116,105,111,110,97,108,97,112,112,114,111,118,97,108,32,111,102\n,115,111,109,101,32,111,102,32,116,104,101,101,97,99,104,32,111,116,104,101,114,\n44,98,101,104,97,118,105,111,114,32,111,102,97,110,100,32,98,101,99,97,117,115,\n101,97,110,100,32,97,110,111,116,104,101,114,97,112,112,101,97,114,101,100,32,\n111,110,114,101,99,111,114,100,101,100,32,105,110,98,108,97,99,107,38,113,117,\n111,116,59,109,97,121,32,105,110,99,108,117,100,101,116,104,101,32,119,111,114,\n108,100,39,115,99,97,110,32,108,101,97,100,32,116,111,114,101,102,101,114,115,32\n,116,111,32,97,98,111,114,100,101,114,61,34,48,34,32,103,111,118,101,114,110,109\n,101,110,116,32,119,105,110,110,105,110,103,32,116,104,101,114,101,115,117,108,\n116,101,100,32,105,110,32,119,104,105,108,101,32,116,104,101,32,87,97,115,104,\n105,110,103,116,111,110,44,116,104,101,32,115,117,98,106,101,99,116,99,105,116,\n121,32,105,110,32,116,104,101,62,60,47,100,105,118,62,13,10,9,9,114,101,102,108,\n101,99,116,32,116,104,101,116,111,32,99,111,109,112,108,101,116,101,98,101,99,97\n,109,101,32,109,111,114,101,114,97,100,105,111,97,99,116,105,118,101,114,101,106\n,101,99,116,101,100,32,98,121,119,105,116,104,111,117,116,32,97,110,121,104,105,\n115,32,102,97,116,104,101,114,44,119,104,105,99,104,32,99,111,117,108,100,99,111\n,112,121,32,111,102,32,116,104,101,116,111,32,105,110,100,105,99,97,116,101,97,\n32,112,111,108,105,116,105,99,97,108,97,99,99,111,117,110,116,115,32,111,102,99,\n111,110,115,116,105,116,117,116,101,115,119,111,114,107,101,100,32,119,105,116,\n104,101,114,60,47,97,62,60,47,108,105,62,111,102,32,104,105,115,32,108,105,102,\n101,97,99,99,111,109,112,97,110,105,101,100,99,108,105,101,110,116,87,105,100,\n116,104,112,114,101,118,101,110,116,32,116,104,101,76,101,103,105,115,108,97,116\n,105,118,101,100,105,102,102,101,114,101,110,116,108,121,116,111,103,101,116,104\n,101,114,32,105,110,104,97,115,32,115,101,118,101,114,97,108,102,111,114,32,97,\n110,111,116,104,101,114,116,101,120,116,32,111,102,32,116,104,101,102,111,117,\n110,100,101,100,32,116,104,101,101,32,119,105,116,104,32,116,104,101,32,105,115,\n32,117,115,101,100,32,102,111,114,99,104,97,110,103,101,100,32,116,104,101,117,\n115,117,97,108,108,121,32,116,104,101,112,108,97,99,101,32,119,104,101,114,101,\n119,104,101,114,101,97,115,32,116,104,101,62,32,60,97,32,104,114,101,102,61,34,\n34,62,60,97,32,104,114,101,102,61,34,116,104,101,109,115,101,108,118,101,115,44,\n97,108,116,104,111,117,103,104,32,104,101,116,104,97,116,32,99,97,110,32,98,101,\n116,114,97,100,105,116,105,111,110,97,108,114,111,108,101,32,111,102,32,116,104,\n101,97,115,32,97,32,114,101,115,117,108,116,114,101,109,111,118,101,67,104,105,\n108,100,100,101,115,105,103,110,101,100,32,98,121,119,101,115,116,32,111,102,32,\n116,104,101,83,111,109,101,32,112,101,111,112,108,101,112,114,111,100,117,99,116\n,105,111,110,44,115,105,100,101,32,111,102,32,116,104,101,110,101,119,115,108,\n101,116,116,101,114,115,117,115,101,100,32,98,121,32,116,104,101,100,111,119,110\n,32,116,111,32,116,104,101,97,99,99,101,112,116,101,100,32,98,121,108,105,118,\n101,32,105,110,32,116,104,101,97,116,116,101,109,112,116,115,32,116,111,111,117,\n116,115,105,100,101,32,116,104,101,102,114,101,113,117,101,110,99,105,101,115,72\n,111,119,101,118,101,114,44,32,105,110,112,114,111,103,114,97,109,109,101,114,\n115,97,116,32,108,101,97,115,116,32,105,110,97,112,112,114,111,120,105,109,97,\n116,101,97,108,116,104,111,117,103,104,32,105,116,119,97,115,32,112,97,114,116,\n32,111,102,97,110,100,32,118,97,114,105,111,117,115,71,111,118,101,114,110,111,\n114,32,111,102,116,104,101,32,97,114,116,105,99,108,101,116,117,114,110,101,100,\n32,105,110,116,111,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,101,99,\n111,110,111,109,121,105,115,32,116,104,101,32,109,111,115,116,109,111,115,116,32\n,119,105,100,101,108,121,119,111,117,108,100,32,108,97,116,101,114,97,110,100,32\n,112,101,114,104,97,112,115,114,105,115,101,32,116,111,32,116,104,101,111,99,99,\n117,114,115,32,119,104,101,110,117,110,100,101,114,32,119,104,105,99,104,99,111,\n110,100,105,116,105,111,110,115,46,116,104,101,32,119,101,115,116,101,114,110,\n116,104,101,111,114,121,32,116,104,97,116,105,115,32,112,114,111,100,117,99,101,\n100,116,104,101,32,99,105,116,121,32,111,102,105,110,32,119,104,105,99,104,32,\n104,101,115,101,101,110,32,105,110,32,116,104,101,116,104,101,32,99,101,110,116,\n114,97,108,98,117,105,108,100,105,110,103,32,111,102,109,97,110,121,32,111,102,\n32,104,105,115,97,114,101,97,32,111,102,32,116,104,101,105,115,32,116,104,101,32\n,111,110,108,121,109,111,115,116,32,111,102,32,116,104,101,109,97,110,121,32,111\n,102,32,116,104,101,116,104,101,32,87,101,115,116,101,114,110,84,104,101,114,101\n,32,105,115,32,110,111,101,120,116,101,110,100,101,100,32,116,111,83,116,97,116,\n105,115,116,105,99,97,108,99,111,108,115,112,97,110,61,50,32,124,115,104,111,114\n,116,32,115,116,111,114,121,112,111,115,115,105,98,108,101,32,116,111,116,111,\n112,111,108,111,103,105,99,97,108,99,114,105,116,105,99,97,108,32,111,102,114,\n101,112,111,114,116,101,100,32,116,111,97,32,67,104,114,105,115,116,105,97,110,\n100,101,99,105,115,105,111,110,32,116,111,105,115,32,101,113,117,97,108,32,116,\n111,112,114,111,98,108,101,109,115,32,111,102,84,104,105,115,32,99,97,110,32,98,\n101,109,101,114,99,104,97,110,100,105,115,101,102,111,114,32,109,111,115,116,32,\n111,102,110,111,32,101,118,105,100,101,110,99,101,101,100,105,116,105,111,110,\n115,32,111,102,101,108,101,109,101,110,116,115,32,105,110,38,113,117,111,116,59,\n46,32,84,104,101,99,111,109,47,105,109,97,103,101,115,47,119,104,105,99,104,32,\n109,97,107,101,115,116,104,101,32,112,114,111,99,101,115,115,114,101,109,97,105,\n110,115,32,116,104,101,108,105,116,101,114,97,116,117,114,101,44,105,115,32,97,\n32,109,101,109,98,101,114,116,104,101,32,112,111,112,117,108,97,114,116,104,101,\n32,97,110,99,105,101,110,116,112,114,111,98,108,101,109,115,32,105,110,116,105,\n109,101,32,111,102,32,116,104,101,100,101,102,101,97,116,101,100,32,98,121,98,\n111,100,121,32,111,102,32,116,104,101,97,32,102,101,119,32,121,101,97,114,115,\n109,117,99,104,32,111,102,32,116,104,101,116,104,101,32,119,111,114,107,32,111,\n102,67,97,108,105,102,111,114,110,105,97,44,115,101,114,118,101,100,32,97,115,32\n,97,103,111,118,101,114,110,109,101,110,116,46,99,111,110,99,101,112,116,115,32,\n111,102,109,111,118,101,109,101,110,116,32,105,110,9,9,60,100,105,118,32,105,100\n,61,34,105,116,34,32,118,97,108,117,101,61,34,108,97,110,103,117,97,103,101,32,\n111,102,97,115,32,116,104,101,121,32,97,114,101,112,114,111,100,117,99,101,100,\n32,105,110,105,115,32,116,104,97,116,32,116,104,101,101,120,112,108,97,105,110,\n32,116,104,101,100,105,118,62,60,47,100,105,118,62,10,72,111,119,101,118,101,114\n,32,116,104,101,108,101,97,100,32,116,111,32,116,104,101,9,60,97,32,104,114,101,\n102,61,34,47,119,97,115,32,103,114,97,110,116,101,100,112,101,111,112,108,101,32\n,104,97,118,101,99,111,110,116,105,110,117,97,108,108,121,119,97,115,32,115,101,\n101,110,32,97,115,97,110,100,32,114,101,108,97,116,101,100,116,104,101,32,114,\n111,108,101,32,111,102,112,114,111,112,111,115,101,100,32,98,121,111,102,32,116,\n104,101,32,98,101,115,116,101,97,99,104,32,111,116,104,101,114,46,67,111,110,115\n,116,97,110,116,105,110,101,112,101,111,112,108,101,32,102,114,111,109,100,105,\n97,108,101,99,116,115,32,111,102,116,111,32,114,101,118,105,115,105,111,110,119,\n97,115,32,114,101,110,97,109,101,100,97,32,115,111,117,114,99,101,32,111,102,116\n,104,101,32,105,110,105,116,105,97,108,108,97,117,110,99,104,101,100,32,105,110,\n112,114,111,118,105,100,101,32,116,104,101,116,111,32,116,104,101,32,119,101,115\n,116,119,104,101,114,101,32,116,104,101,114,101,97,110,100,32,115,105,109,105,\n108,97,114,98,101,116,119,101,101,110,32,116,119,111,105,115,32,97,108,115,111,\n32,116,104,101,69,110,103,108,105,115,104,32,97,110,100,99,111,110,100,105,116,\n105,111,110,115,44,116,104,97,116,32,105,116,32,119,97,115,101,110,116,105,116,\n108,101,100,32,116,111,116,104,101,109,115,101,108,118,101,115,46,113,117,97,110\n,116,105,116,121,32,111,102,114,97,110,115,112,97,114,101,110,99,121,116,104,101\n,32,115,97,109,101,32,97,115,116,111,32,106,111,105,110,32,116,104,101,99,111,\n117,110,116,114,121,32,97,110,100,116,104,105,115,32,105,115,32,116,104,101,84,\n104,105,115,32,108,101,100,32,116,111,97,32,115,116,97,116,101,109,101,110,116,\n99,111,110,116,114,97,115,116,32,116,111,108,97,115,116,73,110,100,101,120,79,\n102,116,104,114,111,117,103,104,32,104,105,115,105,115,32,100,101,115,105,103,\n110,101,100,116,104,101,32,116,101,114,109,32,105,115,105,115,32,112,114,111,118\n,105,100,101,100,112,114,111,116,101,99,116,32,116,104,101,110,103,60,47,97,62,\n60,47,108,105,62,84,104,101,32,99,117,114,114,101,110,116,116,104,101,32,115,105\n,116,101,32,111,102,115,117,98,115,116,97,110,116,105,97,108,101,120,112,101,114\n,105,101,110,99,101,44,105,110,32,116,104,101,32,87,101,115,116,116,104,101,121,\n32,115,104,111,117,108,100,115,108,111,118,101,110,196,141,105,110,97,99,111,109\n,101,110,116,97,114,105,111,115,117,110,105,118,101,114,115,105,100,97,100,99,\n111,110,100,105,99,105,111,110,101,115,97,99,116,105,118,105,100,97,100,101,115,\n101,120,112,101,114,105,101,110,99,105,97,116,101,99,110,111,108,111,103,195,173\n,97,112,114,111,100,117,99,99,105,195,179,110,112,117,110,116,117,97,99,105,195,\n179,110,97,112,108,105,99,97,99,105,195,179,110,99,111,110,116,114,97,115,101,\n195,177,97,99,97,116,101,103,111,114,195,173,97,115,114,101,103,105,115,116,114,\n97,114,115,101,112,114,111,102,101,115,105,111,110,97,108,116,114,97,116,97,109,\n105,101,110,116,111,114,101,103,195,173,115,116,114,97,116,101,115,101,99,114,\n101,116,97,114,195,173,97,112,114,105,110,99,105,112,97,108,101,115,112,114,111,\n116,101,99,99,105,195,179,110,105,109,112,111,114,116,97,110,116,101,115,105,109\n,112,111,114,116,97,110,99,105,97,112,111,115,105,98,105,108,105,100,97,100,105,\n110,116,101,114,101,115,97,110,116,101,99,114,101,99,105,109,105,101,110,116,111\n,110,101,99,101,115,105,100,97,100,101,115,115,117,115,99,114,105,98,105,114,115\n,101,97,115,111,99,105,97,99,105,195,179,110,100,105,115,112,111,110,105,98,108,\n101,115,101,118,97,108,117,97,99,105,195,179,110,101,115,116,117,100,105,97,110,\n116,101,115,114,101,115,112,111,110,115,97,98,108,101,114,101,115,111,108,117,99\n,105,195,179,110,103,117,97,100,97,108,97,106,97,114,97,114,101,103,105,115,116,\n114,97,100,111,115,111,112,111,114,116,117,110,105,100,97,100,99,111,109,101,114\n,99,105,97,108,101,115,102,111,116,111,103,114,97,102,195,173,97,97,117,116,111,\n114,105,100,97,100,101,115,105,110,103,101,110,105,101,114,195,173,97,116,101,\n108,101,118,105,115,105,195,179,110,99,111,109,112,101,116,101,110,99,105,97,111\n,112,101,114,97,99,105,111,110,101,115,101,115,116,97,98,108,101,99,105,100,111,\n115,105,109,112,108,101,109,101,110,116,101,97,99,116,117,97,108,109,101,110,116\n,101,110,97,118,101,103,97,99,105,195,179,110,99,111,110,102,111,114,109,105,100\n,97,100,108,105,110,101,45,104,101,105,103,104,116,58,102,111,110,116,45,102,97,\n109,105,108,121,58,34,32,58,32,34,104,116,116,112,58,47,47,97,112,112,108,105,99\n,97,116,105,111,110,115,108,105,110,107,34,32,104,114,101,102,61,34,115,112,101,\n99,105,102,105,99,97,108,108,121,47,47,60,33,91,67,68,65,84,65,91,10,79,114,103,\n97,110,105,122,97,116,105,111,110,100,105,115,116,114,105,98,117,116,105,111,110\n,48,112,120,59,32,104,101,105,103,104,116,58,114,101,108,97,116,105,111,110,115,\n104,105,112,100,101,118,105,99,101,45,119,105,100,116,104,60,100,105,118,32,99,\n108,97,115,115,61,34,60,108,97,98,101,108,32,102,111,114,61,34,114,101,103,105,\n115,116,114,97,116,105,111,110,60,47,110,111,115,99,114,105,112,116,62,10,47,105\n,110,100,101,120,46,104,116,109,108,34,119,105,110,100,111,119,46,111,112,101,\n110,40,32,33,105,109,112,111,114,116,97,110,116,59,97,112,112,108,105,99,97,116,\n105,111,110,47,105,110,100,101,112,101,110,100,101,110,99,101,47,47,119,119,119,\n46,103,111,111,103,108,101,111,114,103,97,110,105,122,97,116,105,111,110,97,117,\n116,111,99,111,109,112,108,101,116,101,114,101,113,117,105,114,101,109,101,110,\n116,115,99,111,110,115,101,114,118,97,116,105,118,101,60,102,111,114,109,32,110,\n97,109,101,61,34,105,110,116,101,108,108,101,99,116,117,97,108,109,97,114,103,\n105,110,45,108,101,102,116,58,49,56,116,104,32,99,101,110,116,117,114,121,97,110\n,32,105,109,112,111,114,116,97,110,116,105,110,115,116,105,116,117,116,105,111,\n110,115,97,98,98,114,101,118,105,97,116,105,111,110,60,105,109,103,32,99,108,97,\n115,115,61,34,111,114,103,97,110,105,115,97,116,105,111,110,99,105,118,105,108,\n105,122,97,116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,97,114,99\n,104,105,116,101,99,116,117,114,101,105,110,99,111,114,112,111,114,97,116,101,\n100,50,48,116,104,32,99,101,110,116,117,114,121,45,99,111,110,116,97,105,110,101\n,114,34,62,109,111,115,116,32,110,111,116,97,98,108,121,47,62,60,47,97,62,60,47,\n100,105,118,62,110,111,116,105,102,105,99,97,116,105,111,110,39,117,110,100,101,\n102,105,110,101,100,39,41,70,117,114,116,104,101,114,109,111,114,101,44,98,101,\n108,105,101,118,101,32,116,104,97,116,105,110,110,101,114,72,84,77,76,32,61,32,\n112,114,105,111,114,32,116,111,32,116,104,101,100,114,97,109,97,116,105,99,97,\n108,108,121,114,101,102,101,114,114,105,110,103,32,116,111,110,101,103,111,116,\n105,97,116,105,111,110,115,104,101,97,100,113,117,97,114,116,101,114,115,83,111,\n117,116,104,32,65,102,114,105,99,97,117,110,115,117,99,99,101,115,115,102,117,\n108,80,101,110,110,115,121,108,118,97,110,105,97,65,115,32,97,32,114,101,115,117\n,108,116,44,60,104,116,109,108,32,108,97,110,103,61,34,38,108,116,59,47,115,117,\n112,38,103,116,59,100,101,97,108,105,110,103,32,119,105,116,104,112,104,105,108,\n97,100,101,108,112,104,105,97,104,105,115,116,111,114,105,99,97,108,108,121,41,\n59,60,47,115,99,114,105,112,116,62,10,112,97,100,100,105,110,103,45,116,111,112,\n58,101,120,112,101,114,105,109,101,110,116,97,108,103,101,116,65,116,116,114,105\n,98,117,116,101,105,110,115,116,114,117,99,116,105,111,110,115,116,101,99,104,\n110,111,108,111,103,105,101,115,112,97,114,116,32,111,102,32,116,104,101,32,61,\n102,117,110,99,116,105,111,110,40,41,123,115,117,98,115,99,114,105,112,116,105,\n111,110,108,46,100,116,100,34,62,13,10,60,104,116,103,101,111,103,114,97,112,104\n,105,99,97,108,67,111,110,115,116,105,116,117,116,105,111,110,39,44,32,102,117,\n110,99,116,105,111,110,40,115,117,112,112,111,114,116,101,100,32,98,121,97,103,\n114,105,99,117,108,116,117,114,97,108,99,111,110,115,116,114,117,99,116,105,111,\n110,112,117,98,108,105,99,97,116,105,111,110,115,102,111,110,116,45,115,105,122,\n101,58,32,49,97,32,118,97,114,105,101,116,121,32,111,102,60,100,105,118,32,115,\n116,121,108,101,61,34,69,110,99,121,99,108,111,112,101,100,105,97,105,102,114,97\n,109,101,32,115,114,99,61,34,100,101,109,111,110,115,116,114,97,116,101,100,97,\n99,99,111,109,112,108,105,115,104,101,100,117,110,105,118,101,114,115,105,116,\n105,101,115,68,101,109,111,103,114,97,112,104,105,99,115,41,59,60,47,115,99,114,\n105,112,116,62,60,100,101,100,105,99,97,116,101,100,32,116,111,107,110,111,119,\n108,101,100,103,101,32,111,102,115,97,116,105,115,102,97,99,116,105,111,110,112,\n97,114,116,105,99,117,108,97,114,108,121,60,47,100,105,118,62,60,47,100,105,118,\n62,69,110,103,108,105,115,104,32,40,85,83,41,97,112,112,101,110,100,67,104,105,\n108,100,40,116,114,97,110,115,109,105,115,115,105,111,110,115,46,32,72,111,119,\n101,118,101,114,44,32,105,110,116,101,108,108,105,103,101,110,99,101,34,32,116,\n97,98,105,110,100,101,120,61,34,102,108,111,97,116,58,114,105,103,104,116,59,67,\n111,109,109,111,110,119,101,97,108,116,104,114,97,110,103,105,110,103,32,102,114\n,111,109,105,110,32,119,104,105,99,104,32,116,104,101,97,116,32,108,101,97,115,\n116,32,111,110,101,114,101,112,114,111,100,117,99,116,105,111,110,101,110,99,121\n,99,108,111,112,101,100,105,97,59,102,111,110,116,45,115,105,122,101,58,49,106,\n117,114,105,115,100,105,99,116,105,111,110,97,116,32,116,104,97,116,32,116,105,\n109,101,34,62,60,97,32,99,108,97,115,115,61,34,73,110,32,97,100,100,105,116,105,\n111,110,44,100,101,115,99,114,105,112,116,105,111,110,43,99,111,110,118,101,114,\n115,97,116,105,111,110,99,111,110,116,97,99,116,32,119,105,116,104,105,115,32,\n103,101,110,101,114,97,108,108,121,114,34,32,99,111,110,116,101,110,116,61,34,\n114,101,112,114,101,115,101,110,116,105,110,103,38,108,116,59,109,97,116,104,38,\n103,116,59,112,114,101,115,101,110,116,97,116,105,111,110,111,99,99,97,115,105,\n111,110,97,108,108,121,60,105,109,103,32,119,105,100,116,104,61,34,110,97,118,\n105,103,97,116,105,111,110,34,62,99,111,109,112,101,110,115,97,116,105,111,110,\n99,104,97,109,112,105,111,110,115,104,105,112,109,101,100,105,97,61,34,97,108,\n108,34,32,118,105,111,108,97,116,105,111,110,32,111,102,114,101,102,101,114,101,\n110,99,101,32,116,111,114,101,116,117,114,110,32,116,114,117,101,59,83,116,114,\n105,99,116,47,47,69,78,34,32,116,114,97,110,115,97,99,116,105,111,110,115,105,\n110,116,101,114,118,101,110,116,105,111,110,118,101,114,105,102,105,99,97,116,\n105,111,110,73,110,102,111,114,109,97,116,105,111,110,32,100,105,102,102,105,99,\n117,108,116,105,101,115,67,104,97,109,112,105,111,110,115,104,105,112,99,97,112,\n97,98,105,108,105,116,105,101,115,60,33,91,101,110,100,105,102,93,45,45,62,125,\n10,60,47,115,99,114,105,112,116,62,10,67,104,114,105,115,116,105,97,110,105,116,\n121,102,111,114,32,101,120,97,109,112,108,101,44,80,114,111,102,101,115,115,105,\n111,110,97,108,114,101,115,116,114,105,99,116,105,111,110,115,115,117,103,103,\n101,115,116,32,116,104,97,116,119,97,115,32,114,101,108,101,97,115,101,100,40,\n115,117,99,104,32,97,115,32,116,104,101,114,101,109,111,118,101,67,108,97,115,\n115,40,117,110,101,109,112,108,111,121,109,101,110,116,116,104,101,32,65,109,101\n,114,105,99,97,110,115,116,114,117,99,116,117,114,101,32,111,102,47,105,110,100,\n101,120,46,104,116,109,108,32,112,117,98,108,105,115,104,101,100,32,105,110,115,\n112,97,110,32,99,108,97,115,115,61,34,34,62,60,97,32,104,114,101,102,61,34,47,\n105,110,116,114,111,100,117,99,116,105,111,110,98,101,108,111,110,103,105,110,\n103,32,116,111,99,108,97,105,109,101,100,32,116,104,97,116,99,111,110,115,101,\n113,117,101,110,99,101,115,60,109,101,116,97,32,110,97,109,101,61,34,71,117,105,\n100,101,32,116,111,32,116,104,101,111,118,101,114,119,104,101,108,109,105,110,\n103,97,103,97,105,110,115,116,32,116,104,101,32,99,111,110,99,101,110,116,114,97\n,116,101,100,44,10,46,110,111,110,116,111,117,99,104,32,111,98,115,101,114,118,\n97,116,105,111,110,115,60,47,97,62,10,60,47,100,105,118,62,10,102,32,40,100,111,\n99,117,109,101,110,116,46,98,111,114,100,101,114,58,32,49,112,120,32,123,102,111\n,110,116,45,115,105,122,101,58,49,116,114,101,97,116,109,101,110,116,32,111,102,\n48,34,32,104,101,105,103,104,116,61,34,49,109,111,100,105,102,105,99,97,116,105,\n111,110,73,110,100,101,112,101,110,100,101,110,99,101,100,105,118,105,100,101,\n100,32,105,110,116,111,103,114,101,97,116,101,114,32,116,104,97,110,97,99,104,\n105,101,118,101,109,101,110,116,115,101,115,116,97,98,108,105,115,104,105,110,\n103,74,97,118,97,83,99,114,105,112,116,34,32,110,101,118,101,114,116,104,101,108\n,101,115,115,115,105,103,110,105,102,105,99,97,110,99,101,66,114,111,97,100,99,\n97,115,116,105,110,103,62,38,110,98,115,112,59,60,47,116,100,62,99,111,110,116,\n97,105,110,101,114,34,62,10,115,117,99,104,32,97,115,32,116,104,101,32,105,110,\n102,108,117,101,110,99,101,32,111,102,97,32,112,97,114,116,105,99,117,108,97,114\n,115,114,99,61,39,104,116,116,112,58,47,47,110,97,118,105,103,97,116,105,111,110\n,34,32,104,97,108,102,32,111,102,32,116,104,101,32,115,117,98,115,116,97,110,116\n,105,97,108,32,38,110,98,115,112,59,60,47,100,105,118,62,97,100,118,97,110,116,\n97,103,101,32,111,102,100,105,115,99,111,118,101,114,121,32,111,102,102,117,110,\n100,97,109,101,110,116,97,108,32,109,101,116,114,111,112,111,108,105,116,97,110,\n116,104,101,32,111,112,112,111,115,105,116,101,34,32,120,109,108,58,108,97,110,\n103,61,34,100,101,108,105,98,101,114,97,116,101,108,121,97,108,105,103,110,61,99\n,101,110,116,101,114,101,118,111,108,117,116,105,111,110,32,111,102,112,114,101,\n115,101,114,118,97,116,105,111,110,105,109,112,114,111,118,101,109,101,110,116,\n115,98,101,103,105,110,110,105,110,103,32,105,110,74,101,115,117,115,32,67,104,\n114,105,115,116,80,117,98,108,105,99,97,116,105,111,110,115,100,105,115,97,103,\n114,101,101,109,101,110,116,116,101,120,116,45,97,108,105,103,110,58,114,44,32,\n102,117,110,99,116,105,111,110,40,41,115,105,109,105,108,97,114,105,116,105,101,\n115,98,111,100,121,62,60,47,104,116,109,108,62,105,115,32,99,117,114,114,101,110\n,116,108,121,97,108,112,104,97,98,101,116,105,99,97,108,105,115,32,115,111,109,\n101,116,105,109,101,115,116,121,112,101,61,34,105,109,97,103,101,47,109,97,110,\n121,32,111,102,32,116,104,101,32,102,108,111,119,58,104,105,100,100,101,110,59,\n97,118,97,105,108,97,98,108,101,32,105,110,100,101,115,99,114,105,98,101,32,116,\n104,101,101,120,105,115,116,101,110,99,101,32,111,102,97,108,108,32,111,118,101,\n114,32,116,104,101,116,104,101,32,73,110,116,101,114,110,101,116,9,60,117,108,32\n,99,108,97,115,115,61,34,105,110,115,116,97,108,108,97,116,105,111,110,110,101,\n105,103,104,98,111,114,104,111,111,100,97,114,109,101,100,32,102,111,114,99,101,\n115,114,101,100,117,99,105,110,103,32,116,104,101,99,111,110,116,105,110,117,101\n,115,32,116,111,78,111,110,101,116,104,101,108,101,115,115,44,116,101,109,112,\n101,114,97,116,117,114,101,115,10,9,9,60,97,32,104,114,101,102,61,34,99,108,111,\n115,101,32,116,111,32,116,104,101,101,120,97,109,112,108,101,115,32,111,102,32,\n105,115,32,97,98,111,117,116,32,116,104,101,40,115,101,101,32,98,101,108,111,119\n,41,46,34,32,105,100,61,34,115,101,97,114,99,104,112,114,111,102,101,115,115,105\n,111,110,97,108,105,115,32,97,118,97,105,108,97,98,108,101,116,104,101,32,111,\n102,102,105,99,105,97,108,9,9,60,47,115,99,114,105,112,116,62,10,10,9,9,60,100,\n105,118,32,105,100,61,34,97,99,99,101,108,101,114,97,116,105,111,110,116,104,114\n,111,117,103,104,32,116,104,101,32,72,97,108,108,32,111,102,32,70,97,109,101,100\n,101,115,99,114,105,112,116,105,111,110,115,116,114,97,110,115,108,97,116,105,\n111,110,115,105,110,116,101,114,102,101,114,101,110,99,101,32,116,121,112,101,61\n,39,116,101,120,116,47,114,101,99,101,110,116,32,121,101,97,114,115,105,110,32,\n116,104,101,32,119,111,114,108,100,118,101,114,121,32,112,111,112,117,108,97,114\n,123,98,97,99,107,103,114,111,117,110,100,58,116,114,97,100,105,116,105,111,110,\n97,108,32,115,111,109,101,32,111,102,32,116,104,101,32,99,111,110,110,101,99,116\n,101,100,32,116,111,101,120,112,108,111,105,116,97,116,105,111,110,101,109,101,\n114,103,101,110,99,101,32,111,102,99,111,110,115,116,105,116,117,116,105,111,110\n,65,32,72,105,115,116,111,114,121,32,111,102,115,105,103,110,105,102,105,99,97,\n110,116,32,109,97,110,117,102,97,99,116,117,114,101,100,101,120,112,101,99,116,\n97,116,105,111,110,115,62,60,110,111,115,99,114,105,112,116,62,60,99,97,110,32,\n98,101,32,102,111,117,110,100,98,101,99,97,117,115,101,32,116,104,101,32,104,97,\n115,32,110,111,116,32,98,101,101,110,110,101,105,103,104,98,111,117,114,105,110,\n103,119,105,116,104,111,117,116,32,116,104,101,32,97,100,100,101,100,32,116,111,\n32,116,104,101,9,60,108,105,32,99,108,97,115,115,61,34,105,110,115,116,114,117,\n109,101,110,116,97,108,83,111,118,105,101,116,32,85,110,105,111,110,97,99,107,\n110,111,119,108,101,100,103,101,100,119,104,105,99,104,32,99,97,110,32,98,101,\n110,97,109,101,32,102,111,114,32,116,104,101,97,116,116,101,110,116,105,111,110,\n32,116,111,97,116,116,101,109,112,116,115,32,116,111,32,100,101,118,101,108,111,\n112,109,101,110,116,115,73,110,32,102,97,99,116,44,32,116,104,101,60,108,105,32,\n99,108,97,115,115,61,34,97,105,109,112,108,105,99,97,116,105,111,110,115,115,117\n,105,116,97,98,108,101,32,102,111,114,109,117,99,104,32,111,102,32,116,104,101,\n32,99,111,108,111,110,105,122,97,116,105,111,110,112,114,101,115,105,100,101,110\n,116,105,97,108,99,97,110,99,101,108,66,117,98,98,108,101,32,73,110,102,111,114,\n109,97,116,105,111,110,109,111,115,116,32,111,102,32,116,104,101,32,105,115,32,\n100,101,115,99,114,105,98,101,100,114,101,115,116,32,111,102,32,116,104,101,32,\n109,111,114,101,32,111,114,32,108,101,115,115,105,110,32,83,101,112,116,101,109,\n98,101,114,73,110,116,101,108,108,105,103,101,110,99,101,115,114,99,61,34,104,\n116,116,112,58,47,47,112,120,59,32,104,101,105,103,104,116,58,32,97,118,97,105,\n108,97,98,108,101,32,116,111,109,97,110,117,102,97,99,116,117,114,101,114,104,\n117,109,97,110,32,114,105,103,104,116,115,108,105,110,107,32,104,114,101,102,61,\n34,47,97,118,97,105,108,97,98,105,108,105,116,121,112,114,111,112,111,114,116,\n105,111,110,97,108,111,117,116,115,105,100,101,32,116,104,101,32,97,115,116,114,\n111,110,111,109,105,99,97,108,104,117,109,97,110,32,98,101,105,110,103,115,110,\n97,109,101,32,111,102,32,116,104,101,32,97,114,101,32,102,111,117,110,100,32,105\n,110,97,114,101,32,98,97,115,101,100,32,111,110,115,109,97,108,108,101,114,32,\n116,104,97,110,97,32,112,101,114,115,111,110,32,119,104,111,101,120,112,97,110,\n115,105,111,110,32,111,102,97,114,103,117,105,110,103,32,116,104,97,116,110,111,\n119,32,107,110,111,119,110,32,97,115,73,110,32,116,104,101,32,101,97,114,108,121\n,105,110,116,101,114,109,101,100,105,97,116,101,100,101,114,105,118,101,100,32,\n102,114,111,109,83,99,97,110,100,105,110,97,118,105,97,110,60,47,97,62,60,47,100\n,105,118,62,13,10,99,111,110,115,105,100,101,114,32,116,104,101,97,110,32,101,\n115,116,105,109,97,116,101,100,116,104,101,32,78,97,116,105,111,110,97,108,60,\n100,105,118,32,105,100,61,34,112,97,103,114,101,115,117,108,116,105,110,103,32,\n105,110,99,111,109,109,105,115,115,105,111,110,101,100,97,110,97,108,111,103,111\n,117,115,32,116,111,97,114,101,32,114,101,113,117,105,114,101,100,47,117,108,62,\n10,60,47,100,105,118,62,10,119,97,115,32,98,97,115,101,100,32,111,110,97,110,100\n,32,98,101,99,97,109,101,32,97,38,110,98,115,112,59,38,110,98,115,112,59,116,34,\n32,118,97,108,117,101,61,34,34,32,119,97,115,32,99,97,112,116,117,114,101,100,\n110,111,32,109,111,114,101,32,116,104,97,110,114,101,115,112,101,99,116,105,118,\n101,108,121,99,111,110,116,105,110,117,101,32,116,111,32,62,13,10,60,104,101,97,\n100,62,13,10,60,119,101,114,101,32,99,114,101,97,116,101,100,109,111,114,101,32,\n103,101,110,101,114,97,108,105,110,102,111,114,109,97,116,105,111,110,32,117,115\n,101,100,32,102,111,114,32,116,104,101,105,110,100,101,112,101,110,100,101,110,\n116,32,116,104,101,32,73,109,112,101,114,105,97,108,99,111,109,112,111,110,101,\n110,116,32,111,102,116,111,32,116,104,101,32,110,111,114,116,104,105,110,99,108,\n117,100,101,32,116,104,101,32,67,111,110,115,116,114,117,99,116,105,111,110,115,\n105,100,101,32,111,102,32,116,104,101,32,119,111,117,108,100,32,110,111,116,32,\n98,101,102,111,114,32,105,110,115,116,97,110,99,101,105,110,118,101,110,116,105,\n111,110,32,111,102,109,111,114,101,32,99,111,109,112,108,101,120,99,111,108,108,\n101,99,116,105,118,101,108,121,98,97,99,107,103,114,111,117,110,100,58,32,116,\n101,120,116,45,97,108,105,103,110,58,32,105,116,115,32,111,114,105,103,105,110,\n97,108,105,110,116,111,32,97,99,99,111,117,110,116,116,104,105,115,32,112,114,\n111,99,101,115,115,97,110,32,101,120,116,101,110,115,105,118,101,104,111,119,101\n,118,101,114,44,32,116,104,101,116,104,101,121,32,97,114,101,32,110,111,116,114,\n101,106,101,99,116,101,100,32,116,104,101,99,114,105,116,105,99,105,115,109,32,\n111,102,100,117,114,105,110,103,32,119,104,105,99,104,112,114,111,98,97,98,108,\n121,32,116,104,101,116,104,105,115,32,97,114,116,105,99,108,101,40,102,117,110,\n99,116,105,111,110,40,41,123,73,116,32,115,104,111,117,108,100,32,98,101,97,110,\n32,97,103,114,101,101,109,101,110,116,97,99,99,105,100,101,110,116,97,108,108,\n121,100,105,102,102,101,114,115,32,102,114,111,109,65,114,99,104,105,116,101,99,\n116,117,114,101,98,101,116,116,101,114,32,107,110,111,119,110,97,114,114,97,110,\n103,101,109,101,110,116,115,105,110,102,108,117,101,110,99,101,32,111,110,97,116\n,116,101,110,100,101,100,32,116,104,101,105,100,101,110,116,105,99,97,108,32,116\n,111,115,111,117,116,104,32,111,102,32,116,104,101,112,97,115,115,32,116,104,114\n,111,117,103,104,120,109,108,34,32,116,105,116,108,101,61,34,119,101,105,103,104\n,116,58,98,111,108,100,59,99,114,101,97,116,105,110,103,32,116,104,101,100,105,\n115,112,108,97,121,58,110,111,110,101,114,101,112,108,97,99,101,100,32,116,104,\n101,60,105,109,103,32,115,114,99,61,34,47,105,104,116,116,112,115,58,47,47,119,\n119,119,46,87,111,114,108,100,32,87,97,114,32,73,73,116,101,115,116,105,109,111,\n110,105,97,108,115,102,111,117,110,100,32,105,110,32,116,104,101,114,101,113,117\n,105,114,101,100,32,116,111,32,97,110,100,32,116,104,97,116,32,116,104,101,98,\n101,116,119,101,101,110,32,116,104,101,32,119,97,115,32,100,101,115,105,103,110,\n101,100,99,111,110,115,105,115,116,115,32,111,102,32,99,111,110,115,105,100,101,\n114,97,98,108,121,112,117,98,108,105,115,104,101,100,32,98,121,116,104,101,32,\n108,97,110,103,117,97,103,101,67,111,110,115,101,114,118,97,116,105,111,110,99,\n111,110,115,105,115,116,101,100,32,111,102,114,101,102,101,114,32,116,111,32,116\n,104,101,98,97,99,107,32,116,111,32,116,104,101,32,99,115,115,34,32,109,101,100,\n105,97,61,34,80,101,111,112,108,101,32,102,114,111,109,32,97,118,97,105,108,97,\n98,108,101,32,111,110,112,114,111,118,101,100,32,116,111,32,98,101,115,117,103,\n103,101,115,116,105,111,110,115,34,119,97,115,32,107,110,111,119,110,32,97,115,\n118,97,114,105,101,116,105,101,115,32,111,102,108,105,107,101,108,121,32,116,111\n,32,98,101,99,111,109,112,114,105,115,101,100,32,111,102,115,117,112,112,111,114\n,116,32,116,104,101,32,104,97,110,100,115,32,111,102,32,116,104,101,99,111,117,\n112,108,101,100,32,119,105,116,104,99,111,110,110,101,99,116,32,97,110,100,32,98\n,111,114,100,101,114,58,110,111,110,101,59,112,101,114,102,111,114,109,97,110,99\n,101,115,98,101,102,111,114,101,32,98,101,105,110,103,108,97,116,101,114,32,98,\n101,99,97,109,101,99,97,108,99,117,108,97,116,105,111,110,115,111,102,116,101,\n110,32,99,97,108,108,101,100,114,101,115,105,100,101,110,116,115,32,111,102,109,\n101,97,110,105,110,103,32,116,104,97,116,62,60,108,105,32,99,108,97,115,115,61,\n34,101,118,105,100,101,110,99,101,32,102,111,114,101,120,112,108,97,110,97,116,\n105,111,110,115,101,110,118,105,114,111,110,109,101,110,116,115,34,62,60,47,97,\n62,60,47,100,105,118,62,119,104,105,99,104,32,97,108,108,111,119,115,73,110,116,\n114,111,100,117,99,116,105,111,110,100,101,118,101,108,111,112,101,100,32,98,121\n,97,32,119,105,100,101,32,114,97,110,103,101,111,110,32,98,101,104,97,108,102,32\n,111,102,118,97,108,105,103,110,61,34,116,111,112,34,112,114,105,110,99,105,112,\n108,101,32,111,102,97,116,32,116,104,101,32,116,105,109,101,44,60,47,110,111,115\n,99,114,105,112,116,62,13,115,97,105,100,32,116,111,32,104,97,118,101,105,110,32\n,116,104,101,32,102,105,114,115,116,119,104,105,108,101,32,111,116,104,101,114,\n115,104,121,112,111,116,104,101,116,105,99,97,108,112,104,105,108,111,115,111,\n112,104,101,114,115,112,111,119,101,114,32,111,102,32,116,104,101,99,111,110,116\n,97,105,110,101,100,32,105,110,112,101,114,102,111,114,109,101,100,32,98,121,105\n,110,97,98,105,108,105,116,121,32,116,111,119,101,114,101,32,119,114,105,116,116\n,101,110,115,112,97,110,32,115,116,121,108,101,61,34,105,110,112,117,116,32,110,\n97,109,101,61,34,116,104,101,32,113,117,101,115,116,105,111,110,105,110,116,101,\n110,100,101,100,32,102,111,114,114,101,106,101,99,116,105,111,110,32,111,102,105\n,109,112,108,105,101,115,32,116,104,97,116,105,110,118,101,110,116,101,100,32,\n116,104,101,116,104,101,32,115,116,97,110,100,97,114,100,119,97,115,32,112,114,\n111,98,97,98,108,121,108,105,110,107,32,98,101,116,119,101,101,110,112,114,111,\n102,101,115,115,111,114,32,111,102,105,110,116,101,114,97,99,116,105,111,110,115\n,99,104,97,110,103,105,110,103,32,116,104,101,73,110,100,105,97,110,32,79,99,101\n,97,110,32,99,108,97,115,115,61,34,108,97,115,116,119,111,114,107,105,110,103,32\n,119,105,116,104,39,104,116,116,112,58,47,47,119,119,119,46,121,101,97,114,115,\n32,98,101,102,111,114,101,84,104,105,115,32,119,97,115,32,116,104,101,114,101,99\n,114,101,97,116,105,111,110,97,108,101,110,116,101,114,105,110,103,32,116,104,\n101,109,101,97,115,117,114,101,109,101,110,116,115,97,110,32,101,120,116,114,101\n,109,101,108,121,118,97,108,117,101,32,111,102,32,116,104,101,115,116,97,114,116\n,32,111,102,32,116,104,101,10,60,47,115,99,114,105,112,116,62,10,10,97,110,32,\n101,102,102,111,114,116,32,116,111,105,110,99,114,101,97,115,101,32,116,104,101,\n116,111,32,116,104,101,32,115,111,117,116,104,115,112,97,99,105,110,103,61,34,48\n,34,62,115,117,102,102,105,99,105,101,110,116,108,121,116,104,101,32,69,117,114,\n111,112,101,97,110,99,111,110,118,101,114,116,101,100,32,116,111,99,108,101,97,\n114,84,105,109,101,111,117,116,100,105,100,32,110,111,116,32,104,97,118,101,99,\n111,110,115,101,113,117,101,110,116,108,121,102,111,114,32,116,104,101,32,110,\n101,120,116,101,120,116,101,110,115,105,111,110,32,111,102,101,99,111,110,111,\n109,105,99,32,97,110,100,97,108,116,104,111,117,103,104,32,116,104,101,97,114,\n101,32,112,114,111,100,117,99,101,100,97,110,100,32,119,105,116,104,32,116,104,\n101,105,110,115,117,102,102,105,99,105,101,110,116,103,105,118,101,110,32,98,121\n,32,116,104,101,115,116,97,116,105,110,103,32,116,104,97,116,101,120,112,101,110\n,100,105,116,117,114,101,115,60,47,115,112,97,110,62,60,47,97,62,10,116,104,111,\n117,103,104,116,32,116,104,97,116,111,110,32,116,104,101,32,98,97,115,105,115,99\n,101,108,108,112,97,100,100,105,110,103,61,105,109,97,103,101,32,111,102,32,116,\n104,101,114,101,116,117,114,110,105,110,103,32,116,111,105,110,102,111,114,109,\n97,116,105,111,110,44,115,101,112,97,114,97,116,101,100,32,98,121,97,115,115,97,\n115,115,105,110,97,116,101,100,115,34,32,99,111,110,116,101,110,116,61,34,97,117\n,116,104,111,114,105,116,121,32,111,102,110,111,114,116,104,119,101,115,116,101,\n114,110,60,47,100,105,118,62,10,60,100,105,118,32,34,62,60,47,100,105,118,62,13,\n10,32,32,99,111,110,115,117,108,116,97,116,105,111,110,99,111,109,109,117,110,\n105,116,121,32,111,102,116,104,101,32,110,97,116,105,111,110,97,108,105,116,32,\n115,104,111,117,108,100,32,98,101,112,97,114,116,105,99,105,112,97,110,116,115,\n32,97,108,105,103,110,61,34,108,101,102,116,116,104,101,32,103,114,101,97,116,\n101,115,116,115,101,108,101,99,116,105,111,110,32,111,102,115,117,112,101,114,\n110,97,116,117,114,97,108,100,101,112,101,110,100,101,110,116,32,111,110,105,115\n,32,109,101,110,116,105,111,110,101,100,97,108,108,111,119,105,110,103,32,116,\n104,101,119,97,115,32,105,110,118,101,110,116,101,100,97,99,99,111,109,112,97,\n110,121,105,110,103,104,105,115,32,112,101,114,115,111,110,97,108,97,118,97,105,\n108,97,98,108,101,32,97,116,115,116,117,100,121,32,111,102,32,116,104,101,111,\n110,32,116,104,101,32,111,116,104,101,114,101,120,101,99,117,116,105,111,110,32,\n111,102,72,117,109,97,110,32,82,105,103,104,116,115,116,101,114,109,115,32,111,\n102,32,116,104,101,97,115,115,111,99,105,97,116,105,111,110,115,114,101,115,101,\n97,114,99,104,32,97,110,100,115,117,99,99,101,101,100,101,100,32,98,121,100,101,\n102,101,97,116,101,100,32,116,104,101,97,110,100,32,102,114,111,109,32,116,104,\n101,98,117,116,32,116,104,101,121,32,97,114,101,99,111,109,109,97,110,100,101,\n114,32,111,102,115,116,97,116,101,32,111,102,32,116,104,101,121,101,97,114,115,\n32,111,102,32,97,103,101,116,104,101,32,115,116,117,100,121,32,111,102,60,117,\n108,32,99,108,97,115,115,61,34,115,112,108,97,99,101,32,105,110,32,116,104,101,\n119,104,101,114,101,32,104,101,32,119,97,115,60,108,105,32,99,108,97,115,115,61,\n34,102,116,104,101,114,101,32,97,114,101,32,110,111,119,104,105,99,104,32,98,101\n,99,97,109,101,104,101,32,112,117,98,108,105,115,104,101,100,101,120,112,114,101\n,115,115,101,100,32,105,110,116,111,32,119,104,105,99,104,32,116,104,101,99,111,\n109,109,105,115,115,105,111,110,101,114,102,111,110,116,45,119,101,105,103,104,\n116,58,116,101,114,114,105,116,111,114,121,32,111,102,101,120,116,101,110,115,\n105,111,110,115,34,62,82,111,109,97,110,32,69,109,112,105,114,101,101,113,117,97\n,108,32,116,111,32,116,104,101,73,110,32,99,111,110,116,114,97,115,116,44,104,\n111,119,101,118,101,114,44,32,97,110,100,105,115,32,116,121,112,105,99,97,108,\n108,121,97,110,100,32,104,105,115,32,119,105,102,101,40,97,108,115,111,32,99,97,\n108,108,101,100,62,60,117,108,32,99,108,97,115,115,61,34,101,102,102,101,99,116,\n105,118,101,108,121,32,101,118,111,108,118,101,100,32,105,110,116,111,115,101,\n101,109,32,116,111,32,104,97,118,101,119,104,105,99,104,32,105,115,32,116,104,\n101,116,104,101,114,101,32,119,97,115,32,110,111,97,110,32,101,120,99,101,108,\n108,101,110,116,97,108,108,32,111,102,32,116,104,101,115,101,100,101,115,99,114,\n105,98,101,100,32,98,121,73,110,32,112,114,97,99,116,105,99,101,44,98,114,111,97\n,100,99,97,115,116,105,110,103,99,104,97,114,103,101,100,32,119,105,116,104,114,\n101,102,108,101,99,116,101,100,32,105,110,115,117,98,106,101,99,116,101,100,32,\n116,111,109,105,108,105,116,97,114,121,32,97,110,100,116,111,32,116,104,101,32,\n112,111,105,110,116,101,99,111,110,111,109,105,99,97,108,108,121,115,101,116,84,\n97,114,103,101,116,105,110,103,97,114,101,32,97,99,116,117,97,108,108,121,118,\n105,99,116,111,114,121,32,111,118,101,114,40,41,59,60,47,115,99,114,105,112,116,\n62,99,111,110,116,105,110,117,111,117,115,108,121,114,101,113,117,105,114,101,\n100,32,102,111,114,101,118,111,108,117,116,105,111,110,97,114,121,97,110,32,101,\n102,102,101,99,116,105,118,101,110,111,114,116,104,32,111,102,32,116,104,101,44,\n32,119,104,105,99,104,32,119,97,115,32,102,114,111,110,116,32,111,102,32,116,104\n,101,111,114,32,111,116,104,101,114,119,105,115,101,115,111,109,101,32,102,111,\n114,109,32,111,102,104,97,100,32,110,111,116,32,98,101,101,110,103,101,110,101,\n114,97,116,101,100,32,98,121,105,110,102,111,114,109,97,116,105,111,110,46,112,\n101,114,109,105,116,116,101,100,32,116,111,105,110,99,108,117,100,101,115,32,116\n,104,101,100,101,118,101,108,111,112,109,101,110,116,44,101,110,116,101,114,101,\n100,32,105,110,116,111,116,104,101,32,112,114,101,118,105,111,117,115,99,111,110\n,115,105,115,116,101,110,116,108,121,97,114,101,32,107,110,111,119,110,32,97,115\n,116,104,101,32,102,105,101,108,100,32,111,102,116,104,105,115,32,116,121,112,\n101,32,111,102,103,105,118,101,110,32,116,111,32,116,104,101,116,104,101,32,116,\n105,116,108,101,32,111,102,99,111,110,116,97,105,110,115,32,116,104,101,105,110,\n115,116,97,110,99,101,115,32,111,102,105,110,32,116,104,101,32,110,111,114,116,\n104,100,117,101,32,116,111,32,116,104,101,105,114,97,114,101,32,100,101,115,105,\n103,110,101,100,99,111,114,112,111,114,97,116,105,111,110,115,119,97,115,32,116,\n104,97,116,32,116,104,101,111,110,101,32,111,102,32,116,104,101,115,101,109,111,\n114,101,32,112,111,112,117,108,97,114,115,117,99,99,101,101,100,101,100,32,105,\n110,115,117,112,112,111,114,116,32,102,114,111,109,105,110,32,100,105,102,102,\n101,114,101,110,116,100,111,109,105,110,97,116,101,100,32,98,121,100,101,115,105\n,103,110,101,100,32,102,111,114,111,119,110,101,114,115,104,105,112,32,111,102,\n97,110,100,32,112,111,115,115,105,98,108,121,115,116,97,110,100,97,114,100,105,\n122,101,100,114,101,115,112,111,110,115,101,84,101,120,116,119,97,115,32,105,110\n,116,101,110,100,101,100,114,101,99,101,105,118,101,100,32,116,104,101,97,115,\n115,117,109,101,100,32,116,104,97,116,97,114,101,97,115,32,111,102,32,116,104,\n101,112,114,105,109,97,114,105,108,121,32,105,110,116,104,101,32,98,97,115,105,\n115,32,111,102,105,110,32,116,104,101,32,115,101,110,115,101,97,99,99,111,117,\n110,116,115,32,102,111,114,100,101,115,116,114,111,121,101,100,32,98,121,97,116,\n32,108,101,97,115,116,32,116,119,111,119,97,115,32,100,101,99,108,97,114,101,100\n,99,111,117,108,100,32,110,111,116,32,98,101,83,101,99,114,101,116,97,114,121,32\n,111,102,97,112,112,101,97,114,32,116,111,32,98,101,109,97,114,103,105,110,45,\n116,111,112,58,49,47,94,92,115,43,124,92,115,43,36,47,103,101,41,123,116,104,114\n,111,119,32,101,125,59,116,104,101,32,115,116,97,114,116,32,111,102,116,119,111,\n32,115,101,112,97,114,97,116,101,108,97,110,103,117,97,103,101,32,97,110,100,119\n,104,111,32,104,97,100,32,98,101,101,110,111,112,101,114,97,116,105,111,110,32,\n111,102,100,101,97,116,104,32,111,102,32,116,104,101,114,101,97,108,32,110,117,\n109,98,101,114,115,9,60,108,105,110,107,32,114,101,108,61,34,112,114,111,118,105\n,100,101,100,32,116,104,101,116,104,101,32,115,116,111,114,121,32,111,102,99,111\n,109,112,101,116,105,116,105,111,110,115,101,110,103,108,105,115,104,32,40,85,75\n,41,101,110,103,108,105,115,104,32,40,85,83,41,208,156,208,190,208,189,208,179,\n208,190,208,187,208,161,209,128,208,191,209,129,208,186,208,184,209,129,209,128,\n208,191,209,129,208,186,208,184,209,129,209,128,208,191,209,129,208,186,208,190,\n217,132,216,185,216,177,216,168,217,138,216,169,230,173,163,233,171,148,228,184,\n173,230,150,135,231,174,128,228,189,147,228,184,173,230,150,135,231,185,129,228,\n189,147,228,184,173,230,150,135,230,156,137,233,153,144,229,133,172,229,143,184,\n228,186,186,230,176,145,230,148,191,229,186,156,233,152,191,233,135,140,229,183,\n180,229,183,180,231,164,190,228,188,154,228,184,187,228,185,137,230,147,141,228,\n189,156,231,179,187,231,187,159,230,148,191,231,173,150,230,179,149,232,167,132,\n105,110,102,111,114,109,97,99,105,195,179,110,104,101,114,114,97,109,105,101,110\n,116,97,115,101,108,101,99,116,114,195,179,110,105,99,111,100,101,115,99,114,105\n,112,99,105,195,179,110,99,108,97,115,105,102,105,99,97,100,111,115,99,111,110,\n111,99,105,109,105,101,110,116,111,112,117,98,108,105,99,97,99,105,195,179,110,\n114,101,108,97,99,105,111,110,97,100,97,115,105,110,102,111,114,109,195,161,116,\n105,99,97,114,101,108,97,99,105,111,110,97,100,111,115,100,101,112,97,114,116,97\n,109,101,110,116,111,116,114,97,98,97,106,97,100,111,114,101,115,100,105,114,101\n,99,116,97,109,101,110,116,101,97,121,117,110,116,97,109,105,101,110,116,111,109\n,101,114,99,97,100,111,76,105,98,114,101,99,111,110,116,195,161,99,116,101,110,\n111,115,104,97,98,105,116,97,99,105,111,110,101,115,99,117,109,112,108,105,109,\n105,101,110,116,111,114,101,115,116,97,117,114,97,110,116,101,115,100,105,115,\n112,111,115,105,99,105,195,179,110,99,111,110,115,101,99,117,101,110,99,105,97,\n101,108,101,99,116,114,195,179,110,105,99,97,97,112,108,105,99,97,99,105,111,110\n,101,115,100,101,115,99,111,110,101,99,116,97,100,111,105,110,115,116,97,108,97,\n99,105,195,179,110,114,101,97,108,105,122,97,99,105,195,179,110,117,116,105,108,\n105,122,97,99,105,195,179,110,101,110,99,105,99,108,111,112,101,100,105,97,101,\n110,102,101,114,109,101,100,97,100,101,115,105,110,115,116,114,117,109,101,110,\n116,111,115,101,120,112,101,114,105,101,110,99,105,97,115,105,110,115,116,105,\n116,117,99,105,195,179,110,112,97,114,116,105,99,117,108,97,114,101,115,115,117,\n98,99,97,116,101,103,111,114,105,97,209,130,208,190,208,187,209,140,208,186,208,\n190,208,160,208,190,209,129,209,129,208,184,208,184,209,128,208,176,208,177,208,\n190,209,130,209,139,208,177,208,190,208,187,209,140,209,136,208,181,208,191,209,\n128,208,190,209,129,209,130,208,190,208,188,208,190,208,182,208,181,209,130,208,\n181,208,180,209,128,209,131,208,179,208,184,209,133,209,129,208,187,209,131,209,\n135,208,176,208,181,209,129,208,181,208,185,209,135,208,176,209,129,208,178,209,\n129,208,181,208,179,208,180,208,176,208,160,208,190,209,129,209,129,208,184,209,\n143,208,156,208,190,209,129,208,186,208,178,208,181,208,180,209,128,209,131,208,\n179,208,184,208,181,208,179,208,190,209,128,208,190,208,180,208,176,208,178,208,\n190,208,191,209,128,208,190,209,129,208,180,208,176,208,189,208,189,209,139,209,\n133,208,180,208,190,208,187,208,182,208,189,209,139,208,184,208,188,208,181,208,\n189,208,189,208,190,208,156,208,190,209,129,208,186,208,178,209,139,209,128,209,\n131,208,177,208,187,208,181,208,185,208,156,208,190,209,129,208,186,208,178,208,\n176,209,129,209,130,209,128,208,176,208,189,209,139,208,189,208,184,209,135,208,\n181,208,179,208,190,209,128,208,176,208,177,208,190,209,130,208,181,208,180,208,\n190,208,187,208,182,208,181,208,189,209,131,209,129,208,187,209,131,208,179,208,\n184,209,130,208,181,208,191,208,181,209,128,209,140,208,158,208,180,208,189,208,\n176,208,186,208,190,208,191,208,190,209,130,208,190,208,188,209,131,209,128,208,\n176,208,177,208,190,209,130,209,131,208,176,208,191,209,128,208,181,208,187,209,\n143,208,178,208,190,208,190,208,177,209,137,208,181,208,190,208,180,208,189,208,\n190,208,179,208,190,209,129,208,178,208,190,208,181,208,179,208,190,209,129,209,\n130,208,176,209,130,209,140,208,184,208,180,209,128,209,131,208,179,208,190,208,\n185,209,132,208,190,209,128,209,131,208,188,208,181,209,133,208,190,209,128,208,\n190,209,136,208,190,208,191,209,128,208,190,209,130,208,184,208,178,209,129,209,\n129,209,139,208,187,208,186,208,176,208,186,208,176,208,182,208,180,209,139,208,\n185,208,178,208,187,208,176,209,129,209,130,208,184,208,179,209,128,209,131,208,\n191,208,191,209,139,208,178,208,188,208,181,209,129,209,130,208,181,209,128,208,\n176,208,177,208,190,209,130,208,176,209,129,208,186,208,176,208,183,208,176,208,\n187,208,191,208,181,209,128,208,178,209,139,208,185,208,180,208,181,208,187,208,\n176,209,130,209,140,208,180,208,181,208,189,209,140,208,179,208,184,208,191,208,\n181,209,128,208,184,208,190,208,180,208,177,208,184,208,183,208,189,208,181,209,\n129,208,190,209,129,208,189,208,190,208,178,208,181,208,188,208,190,208,188,208,\n181,208,189,209,130,208,186,209,131,208,191,208,184,209,130,209,140,208,180,208,\n190,208,187,208,182,208,189,208,176,209,128,208,176,208,188,208,186,208,176,209,\n133,208,189,208,176,209,135,208,176,208,187,208,190,208,160,208,176,208,177,208,\n190,209,130,208,176,208,162,208,190,208,187,209,140,208,186,208,190,209,129,208,\n190,208,178,209,129,208,181,208,188,208,178,209,130,208,190,209,128,208,190,208,\n185,208,189,208,176,209,135,208,176,208,187,208,176,209,129,208,191,208,184,209,\n129,208,190,208,186,209,129,208,187,209,131,208,182,208,177,209,139,209,129,208,\n184,209,129,209,130,208,181,208,188,208,191,208,181,209,135,208,176,209,130,208,\n184,208,189,208,190,208,178,208,190,208,179,208,190,208,191,208,190,208,188,208,\n190,209,137,208,184,209,129,208,176,208,185,209,130,208,190,208,178,208,191,208,\n190,209,135,208,181,208,188,209,131,208,191,208,190,208,188,208,190,209,137,209,\n140,208,180,208,190,208,187,208,182,208,189,208,190,209,129,209,129,209,139,208,\n187,208,186,208,184,208,177,209,139,209,129,209,130,209,128,208,190,208,180,208,\n176,208,189,208,189,209,139,208,181,208,188,208,189,208,190,208,179,208,184,208,\n181,208,191,209,128,208,190,208,181,208,186,209,130,208,161,208,181,208,185,209,\n135,208,176,209,129,208,188,208,190,208,180,208,181,208,187,208,184,209,130,208,\n176,208,186,208,190,208,179,208,190,208,190,208,189,208,187,208,176,208,185,208,\n189,208,179,208,190,209,128,208,190,208,180,208,181,208,178,208,181,209,128,209,\n129,208,184,209,143,209,129,209,130,209,128,208,176,208,189,208,181,209,132,208,\n184,208,187,209,140,208,188,209,139,209,131,209,128,208,190,208,178,208,189,209,\n143,209,128,208,176,208,183,208,189,209,139,209,133,208,184,209,129,208,186,208,\n176,209,130,209,140,208,189,208,181,208,180,208,181,208,187,209,142,209,143,208,\n189,208,178,208,176,209,128,209,143,208,188,208,181,208,189,209,140,209,136,208,\n181,208,188,208,189,208,190,208,179,208,184,209,133,208,180,208,176,208,189,208,\n189,208,190,208,185,208,183,208,189,208,176,209,135,208,184,209,130,208,189,208,\n181,208,187,209,140,208,183,209,143,209,132,208,190,209,128,209,131,208,188,208,\n176,208,162,208,181,208,191,208,181,209,128,209,140,208,188,208,181,209,129,209,\n143,209,134,208,176,208,183,208,176,209,137,208,184,209,130,209,139,208,155,209,\n131,209,135,209,136,208,184,208,181,224,164,168,224,164,185,224,165,128,224,164,\n130,224,164,149,224,164,176,224,164,168,224,165,135,224,164,133,224,164,170,224,\n164,168,224,165,135,224,164,149,224,164,191,224,164,175,224,164,190,224,164,149,\n224,164,176,224,165,135,224,164,130,224,164,133,224,164,168,224,165,141,224,164,\n175,224,164,149,224,165,141,224,164,175,224,164,190,224,164,151,224,164,190,224,\n164,135,224,164,161,224,164,172,224,164,190,224,164,176,224,165,135,224,164,149,\n224,164,191,224,164,184,224,165,128,224,164,166,224,164,191,224,164,175,224,164,\n190,224,164,170,224,164,185,224,164,178,224,165,135,224,164,184,224,164,191,224,\n164,130,224,164,185,224,164,173,224,164,190,224,164,176,224,164,164,224,164,133,\n224,164,170,224,164,168,224,165,128,224,164,181,224,164,190,224,164,178,224,165,\n135,224,164,184,224,165,135,224,164,181,224,164,190,224,164,149,224,164,176,224,\n164,164,224,165,135,224,164,174,224,165,135,224,164,176,224,165,135,224,164,185,\n224,165,139,224,164,168,224,165,135,224,164,184,224,164,149,224,164,164,224,165,\n135,224,164,172,224,164,185,224,165,129,224,164,164,224,164,184,224,164,190,224,\n164,135,224,164,159,224,164,185,224,165,139,224,164,151,224,164,190,224,164,156,\n224,164,190,224,164,168,224,165,135,224,164,174,224,164,191,224,164,168,224,164,\n159,224,164,149,224,164,176,224,164,164,224,164,190,224,164,149,224,164,176,224,\n164,168,224,164,190,224,164,137,224,164,168,224,164,149,224,165,135,224,164,175,\n224,164,185,224,164,190,224,164,129,224,164,184,224,164,172,224,164,184,224,165,\n135,224,164,173,224,164,190,224,164,183,224,164,190,224,164,134,224,164,170,224,\n164,149,224,165,135,224,164,178,224,164,191,224,164,175,224,165,135,224,164,182,\n224,165,129,224,164,176,224,165,130,224,164,135,224,164,184,224,164,149,224,165,\n135,224,164,152,224,164,130,224,164,159,224,165,135,224,164,174,224,165,135,224,\n164,176,224,165,128,224,164,184,224,164,149,224,164,164,224,164,190,224,164,174,\n224,165,135,224,164,176,224,164,190,224,164,178,224,165,135,224,164,149,224,164,\n176,224,164,133,224,164,167,224,164,191,224,164,149,224,164,133,224,164,170,224,\n164,168,224,164,190,224,164,184,224,164,174,224,164,190,224,164,156,224,164,174,\n224,165,129,224,164,157,224,165,135,224,164,149,224,164,190,224,164,176,224,164,\n163,224,164,185,224,165,139,224,164,164,224,164,190,224,164,149,224,164,161,224,\n164,188,224,165,128,224,164,175,224,164,185,224,164,190,224,164,130,224,164,185,\n224,165,139,224,164,159,224,164,178,224,164,182,224,164,172,224,165,141,224,164,\n166,224,164,178,224,164,191,224,164,175,224,164,190,224,164,156,224,165,128,224,\n164,181,224,164,168,224,164,156,224,164,190,224,164,164,224,164,190,224,164,149,\n224,165,136,224,164,184,224,165,135,224,164,134,224,164,170,224,164,149,224,164,\n190,224,164,181,224,164,190,224,164,178,224,165,128,224,164,166,224,165,135,224,\n164,168,224,165,135,224,164,170,224,165,130,224,164,176,224,165,128,224,164,170,\n224,164,190,224,164,168,224,165,128,224,164,137,224,164,184,224,164,149,224,165,\n135,224,164,185,224,165,139,224,164,151,224,165,128,224,164,172,224,165,136,224,\n164,160,224,164,149,224,164,134,224,164,170,224,164,149,224,165,128,224,164,181,\n224,164,176,224,165,141,224,164,183,224,164,151,224,164,190,224,164,130,224,164,\n181,224,164,134,224,164,170,224,164,149,224,165,139,224,164,156,224,164,191,224,\n164,178,224,164,190,224,164,156,224,164,190,224,164,168,224,164,190,224,164,184,\n224,164,185,224,164,174,224,164,164,224,164,185,224,164,174,224,165,135,224,164,\n130,224,164,137,224,164,168,224,164,149,224,165,128,224,164,175,224,164,190,224,\n164,185,224,165,130,224,164,166,224,164,176,224,165,141,224,164,156,224,164,184,\n224,165,130,224,164,154,224,165,128,224,164,170,224,164,184,224,164,130,224,164,\n166,224,164,184,224,164,181,224,164,190,224,164,178,224,164,185,224,165,139,224,\n164,168,224,164,190,224,164,185,224,165,139,224,164,164,224,165,128,224,164,156,\n224,165,136,224,164,184,224,165,135,224,164,181,224,164,190,224,164,170,224,164,\n184,224,164,156,224,164,168,224,164,164,224,164,190,224,164,168,224,165,135,224,\n164,164,224,164,190,224,164,156,224,164,190,224,164,176,224,165,128,224,164,152,\n224,164,190,224,164,175,224,164,178,224,164,156,224,164,191,224,164,178,224,165,\n135,224,164,168,224,165,128,224,164,154,224,165,135,224,164,156,224,164,190,224,\n164,130,224,164,154,224,164,170,224,164,164,224,165,141,224,164,176,224,164,151,\n224,165,130,224,164,151,224,164,178,224,164,156,224,164,190,224,164,164,224,165,\n135,224,164,172,224,164,190,224,164,185,224,164,176,224,164,134,224,164,170,224,\n164,168,224,165,135,224,164,181,224,164,190,224,164,185,224,164,168,224,164,135,\n224,164,184,224,164,149,224,164,190,224,164,184,224,165,129,224,164,172,224,164,\n185,224,164,176,224,164,185,224,164,168,224,165,135,224,164,135,224,164,184,224,\n164,184,224,165,135,224,164,184,224,164,185,224,164,191,224,164,164,224,164,172,\n224,164,161,224,164,188,224,165,135,224,164,152,224,164,159,224,164,168,224,164,\n190,224,164,164,224,164,178,224,164,190,224,164,182,224,164,170,224,164,190,224,\n164,130,224,164,154,224,164,182,224,165,141,224,164,176,224,165,128,224,164,172,\n224,164,161,224,164,188,224,165,128,224,164,185,224,165,139,224,164,164,224,165,\n135,224,164,184,224,164,190,224,164,136,224,164,159,224,164,182,224,164,190,224,\n164,175,224,164,166,224,164,184,224,164,149,224,164,164,224,165,128,224,164,156,\n224,164,190,224,164,164,224,165,128,224,164,181,224,164,190,224,164,178,224,164,\n190,224,164,185,224,164,156,224,164,190,224,164,176,224,164,170,224,164,159,224,\n164,168,224,164,190,224,164,176,224,164,150,224,164,168,224,165,135,224,164,184,\n224,164,161,224,164,188,224,164,149,224,164,174,224,164,191,224,164,178,224,164,\n190,224,164,137,224,164,184,224,164,149,224,165,128,224,164,149,224,165,135,224,\n164,181,224,164,178,224,164,178,224,164,151,224,164,164,224,164,190,224,164,150,\n224,164,190,224,164,168,224,164,190,224,164,133,224,164,176,224,165,141,224,164,\n165,224,164,156,224,164,185,224,164,190,224,164,130,224,164,166,224,165,135,224,\n164,150,224,164,190,224,164,170,224,164,185,224,164,178,224,165,128,224,164,168,\n224,164,191,224,164,175,224,164,174,224,164,172,224,164,191,224,164,168,224,164,\n190,224,164,172,224,165,136,224,164,130,224,164,149,224,164,149,224,164,185,224,\n165,128,224,164,130,224,164,149,224,164,185,224,164,168,224,164,190,224,164,166,\n224,165,135,224,164,164,224,164,190,224,164,185,224,164,174,224,164,178,224,165,\n135,224,164,149,224,164,190,224,164,171,224,165,128,224,164,156,224,164,172,224,\n164,149,224,164,191,224,164,164,224,165,129,224,164,176,224,164,164,224,164,174,\n224,164,190,224,164,130,224,164,151,224,164,181,224,164,185,224,165,128,224,164,\n130,224,164,176,224,165,139,224,164,156,224,164,188,224,164,174,224,164,191,224,\n164,178,224,165,128,224,164,134,224,164,176,224,165,139,224,164,170,224,164,184,\n224,165,135,224,164,168,224,164,190,224,164,175,224,164,190,224,164,166,224,164,\n181,224,164,178,224,165,135,224,164,168,224,165,135,224,164,150,224,164,190,224,\n164,164,224,164,190,224,164,149,224,164,176,224,165,128,224,164,172,224,164,137,\n224,164,168,224,164,149,224,164,190,224,164,156,224,164,181,224,164,190,224,164,\n172,224,164,170,224,165,130,224,164,176,224,164,190,224,164,172,224,164,161,224,\n164,188,224,164,190,224,164,184,224,165,140,224,164,166,224,164,190,224,164,182,\n224,165,135,224,164,175,224,164,176,224,164,149,224,164,191,224,164,175,224,165,\n135,224,164,149,224,164,185,224,164,190,224,164,130,224,164,133,224,164,149,224,\n164,184,224,164,176,224,164,172,224,164,168,224,164,190,224,164,143,224,164,181,\n224,164,185,224,164,190,224,164,130,224,164,184,224,165,141,224,164,165,224,164,\n178,224,164,174,224,164,191,224,164,178,224,165,135,224,164,178,224,165,135,224,\n164,150,224,164,149,224,164,181,224,164,191,224,164,183,224,164,175,224,164,149,\n224,165,141,224,164,176,224,164,130,224,164,184,224,164,174,224,165,130,224,164,\n185,224,164,165,224,164,190,224,164,168,224,164,190,216,170,216,179,216,170,216,\n183,217,138,216,185,217,133,216,180,216,167,216,177,217,131,216,169,216,168,217,\n136,216,167,216,179,216,183,216,169,216,167,217,132,216,181,217,129,216,173,216,\n169,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,174,216,\n167,216,181,216,169,216,167,217,132,217,133,216,178,217,138,216,175,216,167,217,\n132,216,185,216,167,217,133,216,169,216,167,217,132,217,131,216,167,216,170,216,\n168,216,167,217,132,216,177,216,175,217,136,216,175,216,168,216,177,217,134,216,\n167,217,133,216,172,216,167,217,132,216,175,217,136,217,132,216,169,216,167,217,\n132,216,185,216,167,217,132,217,133,216,167,217,132,217,133,217,136,217,130,216,\n185,216,167,217,132,216,185,216,177,216,168,217,138,216,167,217,132,216,179,216,\n177,217,138,216,185,216,167,217,132,216,172,217,136,216,167,217,132,216,167,217,\n132,216,176,217,135,216,167,216,168,216,167,217,132,216,173,217,138,216,167,216,\n169,216,167,217,132,216,173,217,130,217,136,217,130,216,167,217,132,217,131,216,\n177,217,138,217,133,216,167,217,132,216,185,216,177,216,167,217,130,217,133,216,\n173,217,129,217,136,216,184,216,169,216,167,217,132,216,171,216,167,217,134,217,\n138,217,133,216,180,216,167,217,135,216,175,216,169,216,167,217,132,217,133,216,\n177,216,163,216,169,216,167,217,132,217,130,216,177,216,162,217,134,216,167,217,\n132,216,180,216,168,216,167,216,168,216,167,217,132,216,173,217,136,216,167,216,\n177,216,167,217,132,216,172,216,175,217,138,216,175,216,167,217,132,216,163,216,\n179,216,177,216,169,216,167,217,132,216,185,217,132,217,136,217,133,217,133,216,\n172,217,133,217,136,216,185,216,169,216,167,217,132,216,177,216,173,217,133,217,\n134,216,167,217,132,217,134,217,130,216,167,216,183,217,129,217,132,216,179,216,\n183,217,138,217,134,216,167,217,132,217,131,217,136,217,138,216,170,216,167,217,\n132,216,175,217,134,217,138,216,167,216,168,216,177,217,131,216,167,216,170,217,\n135,216,167,217,132,216,177,217,138,216,167,216,182,216,170,216,173,217,138,216,\n167,216,170,217,138,216,168,216,170,217,136,217,130,217,138,216,170,216,167,217,\n132,216,163,217,136,217,132,217,137,216,167,217,132,216,168,216,177,217,138,216,\n175,216,167,217,132,217,131,217,132,216,167,217,133,216,167,217,132,216,177,216,\n167,216,168,216,183,216,167,217,132,216,180,216,174,216,181,217,138,216,179,217,\n138,216,167,216,177,216,167,216,170,216,167,217,132,216,171,216,167,217,132,216,\n171,216,167,217,132,216,181,217,132,216,167,216,169,216,167,217,132,216,173,216,\n175,217,138,216,171,216,167,217,132,216,178,217,136,216,167,216,177,216,167,217,\n132,216,174,217,132,217,138,216,172,216,167,217,132,216,172,217,133,217,138,216,\n185,216,167,217,132,216,185,216,167,217,133,217,135,216,167,217,132,216,172,217,\n133,216,167,217,132,216,167,217,132,216,179,216,167,216,185,216,169,217,133,216,\n180,216,167,217,135,216,175,217,135,216,167,217,132,216,177,216,166,217,138,216,\n179,216,167,217,132,216,175,216,174,217,136,217,132,216,167,217,132,217,129,217,\n134,217,138,216,169,216,167,217,132,217,131,216,170,216,167,216,168,216,167,217,\n132,216,175,217,136,216,177,217,138,216,167,217,132,216,175,216,177,217,136,216,\n179,216,167,216,179,216,170,216,186,216,177,217,130,216,170,216,181,216,167,217,\n133,217,138,217,133,216,167,217,132,216,168,217,134,216,167,216,170,216,167,217,\n132,216,185,216,184,217,138,217,133,101,110,116,101,114,116,97,105,110,109,101,\n110,116,117,110,100,101,114,115,116,97,110,100,105,110,103,32,61,32,102,117,110,\n99,116,105,111,110,40,41,46,106,112,103,34,32,119,105,100,116,104,61,34,99,111,\n110,102,105,103,117,114,97,116,105,111,110,46,112,110,103,34,32,119,105,100,116,\n104,61,34,60,98,111,100,121,32,99,108,97,115,115,61,34,77,97,116,104,46,114,97,\n110,100,111,109,40,41,99,111,110,116,101,109,112,111,114,97,114,121,32,85,110,\n105,116,101,100,32,83,116,97,116,101,115,99,105,114,99,117,109,115,116,97,110,99\n,101,115,46,97,112,112,101,110,100,67,104,105,108,100,40,111,114,103,97,110,105,\n122,97,116,105,111,110,115,60,115,112,97,110,32,99,108,97,115,115,61,34,34,62,60\n,105,109,103,32,115,114,99,61,34,47,100,105,115,116,105,110,103,117,105,115,104,\n101,100,116,104,111,117,115,97,110,100,115,32,111,102,32,99,111,109,109,117,110,\n105,99,97,116,105,111,110,99,108,101,97,114,34,62,60,47,100,105,118,62,105,110,\n118,101,115,116,105,103,97,116,105,111,110,102,97,118,105,99,111,110,46,105,99,\n111,34,32,109,97,114,103,105,110,45,114,105,103,104,116,58,98,97,115,101,100,32,\n111,110,32,116,104,101,32,77,97,115,115,97,99,104,117,115,101,116,116,115,116,97\n,98,108,101,32,98,111,114,100,101,114,61,105,110,116,101,114,110,97,116,105,111,\n110,97,108,97,108,115,111,32,107,110,111,119,110,32,97,115,112,114,111,110,117,\n110,99,105,97,116,105,111,110,98,97,99,107,103,114,111,117,110,100,58,35,102,112\n,97,100,100,105,110,103,45,108,101,102,116,58,70,111,114,32,101,120,97,109,112,\n108,101,44,32,109,105,115,99,101,108,108,97,110,101,111,117,115,38,108,116,59,47\n,109,97,116,104,38,103,116,59,112,115,121,99,104,111,108,111,103,105,99,97,108,\n105,110,32,112,97,114,116,105,99,117,108,97,114,101,97,114,99,104,34,32,116,121,\n112,101,61,34,102,111,114,109,32,109,101,116,104,111,100,61,34,97,115,32,111,112\n,112,111,115,101,100,32,116,111,83,117,112,114,101,109,101,32,67,111,117,114,116\n,111,99,99,97,115,105,111,110,97,108,108,121,32,65,100,100,105,116,105,111,110,\n97,108,108,121,44,78,111,114,116,104,32,65,109,101,114,105,99,97,112,120,59,98,\n97,99,107,103,114,111,117,110,100,111,112,112,111,114,116,117,110,105,116,105,\n101,115,69,110,116,101,114,116,97,105,110,109,101,110,116,46,116,111,76,111,119,\n101,114,67,97,115,101,40,109,97,110,117,102,97,99,116,117,114,105,110,103,112,\n114,111,102,101,115,115,105,111,110,97,108,32,99,111,109,98,105,110,101,100,32,\n119,105,116,104,70,111,114,32,105,110,115,116,97,110,99,101,44,99,111,110,115,\n105,115,116,105,110,103,32,111,102,34,32,109,97,120,108,101,110,103,116,104,61,\n34,114,101,116,117,114,110,32,102,97,108,115,101,59,99,111,110,115,99,105,111,\n117,115,110,101,115,115,77,101,100,105,116,101,114,114,97,110,101,97,110,101,120\n,116,114,97,111,114,100,105,110,97,114,121,97,115,115,97,115,115,105,110,97,116,\n105,111,110,115,117,98,115,101,113,117,101,110,116,108,121,32,98,117,116,116,111\n,110,32,116,121,112,101,61,34,116,104,101,32,110,117,109,98,101,114,32,111,102,\n116,104,101,32,111,114,105,103,105,110,97,108,32,99,111,109,112,114,101,104,101,\n110,115,105,118,101,114,101,102,101,114,115,32,116,111,32,116,104,101,60,47,117,\n108,62,10,60,47,100,105,118,62,10,112,104,105,108,111,115,111,112,104,105,99,97,\n108,108,111,99,97,116,105,111,110,46,104,114,101,102,119,97,115,32,112,117,98,\n108,105,115,104,101,100,83,97,110,32,70,114,97,110,99,105,115,99,111,40,102,117,\n110,99,116,105,111,110,40,41,123,10,60,100,105,118,32,105,100,61,34,109,97,105,\n110,115,111,112,104,105,115,116,105,99,97,116,101,100,109,97,116,104,101,109,97,\n116,105,99,97,108,32,47,104,101,97,100,62,13,10,60,98,111,100,121,115,117,103,\n103,101,115,116,115,32,116,104,97,116,100,111,99,117,109,101,110,116,97,116,105,\n111,110,99,111,110,99,101,110,116,114,97,116,105,111,110,114,101,108,97,116,105,\n111,110,115,104,105,112,115,109,97,121,32,104,97,118,101,32,98,101,101,110,40,\n102,111,114,32,101,120,97,109,112,108,101,44,84,104,105,115,32,97,114,116,105,99\n,108,101,32,105,110,32,115,111,109,101,32,99,97,115,101,115,112,97,114,116,115,\n32,111,102,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,\n71,114,101,97,116,32,66,114,105,116,97,105,110,32,99,101,108,108,112,97,100,100,\n105,110,103,61,101,113,117,105,118,97,108,101,110,116,32,116,111,112,108,97,99,\n101,104,111,108,100,101,114,61,34,59,32,102,111,110,116,45,115,105,122,101,58,32\n,106,117,115,116,105,102,105,99,97,116,105,111,110,98,101,108,105,101,118,101,\n100,32,116,104,97,116,115,117,102,102,101,114,101,100,32,102,114,111,109,97,116,\n116,101,109,112,116,101,100,32,116,111,32,108,101,97,100,101,114,32,111,102,32,\n116,104,101,99,114,105,112,116,34,32,115,114,99,61,34,47,40,102,117,110,99,116,\n105,111,110,40,41,32,123,97,114,101,32,97,118,97,105,108,97,98,108,101,10,9,60,\n108,105,110,107,32,114,101,108,61,34,32,115,114,99,61,39,104,116,116,112,58,47,\n47,105,110,116,101,114,101,115,116,101,100,32,105,110,99,111,110,118,101,110,116\n,105,111,110,97,108,32,34,32,97,108,116,61,34,34,32,47,62,60,47,97,114,101,32,\n103,101,110,101,114,97,108,108,121,104,97,115,32,97,108,115,111,32,98,101,101,\n110,109,111,115,116,32,112,111,112,117,108,97,114,32,99,111,114,114,101,115,112,\n111,110,100,105,110,103,99,114,101,100,105,116,101,100,32,119,105,116,104,116,\n121,108,101,61,34,98,111,114,100,101,114,58,60,47,97,62,60,47,115,112,97,110,62,\n60,47,46,103,105,102,34,32,119,105,100,116,104,61,34,60,105,102,114,97,109,101,\n32,115,114,99,61,34,116,97,98,108,101,32,99,108,97,115,115,61,34,105,110,108,105\n,110,101,45,98,108,111,99,107,59,97,99,99,111,114,100,105,110,103,32,116,111,32,\n116,111,103,101,116,104,101,114,32,119,105,116,104,97,112,112,114,111,120,105,\n109,97,116,101,108,121,112,97,114,108,105,97,109,101,110,116,97,114,121,109,111,\n114,101,32,97,110,100,32,109,111,114,101,100,105,115,112,108,97,121,58,110,111,\n110,101,59,116,114,97,100,105,116,105,111,110,97,108,108,121,112,114,101,100,111\n,109,105,110,97,110,116,108,121,38,110,98,115,112,59,124,38,110,98,115,112,59,38\n,110,98,115,112,59,60,47,115,112,97,110,62,32,99,101,108,108,115,112,97,99,105,\n110,103,61,60,105,110,112,117,116,32,110,97,109,101,61,34,111,114,34,32,99,111,\n110,116,101,110,116,61,34,99,111,110,116,114,111,118,101,114,115,105,97,108,112,\n114,111,112,101,114,116,121,61,34,111,103,58,47,120,45,115,104,111,99,107,119,97\n,118,101,45,100,101,109,111,110,115,116,114,97,116,105,111,110,115,117,114,114,\n111,117,110,100,101,100,32,98,121,78,101,118,101,114,116,104,101,108,101,115,115\n,44,119,97,115,32,116,104,101,32,102,105,114,115,116,99,111,110,115,105,100,101,\n114,97,98,108,101,32,65,108,116,104,111,117,103,104,32,116,104,101,32,99,111,108\n,108,97,98,111,114,97,116,105,111,110,115,104,111,117,108,100,32,110,111,116,32,\n98,101,112,114,111,112,111,114,116,105,111,110,32,111,102,60,115,112,97,110,32,\n115,116,121,108,101,61,34,107,110,111,119,110,32,97,115,32,116,104,101,32,115,\n104,111,114,116,108,121,32,97,102,116,101,114,102,111,114,32,105,110,115,116,97,\n110,99,101,44,100,101,115,99,114,105,98,101,100,32,97,115,32,47,104,101,97,100,\n62,10,60,98,111,100,121,32,115,116,97,114,116,105,110,103,32,119,105,116,104,105\n,110,99,114,101,97,115,105,110,103,108,121,32,116,104,101,32,102,97,99,116,32,\n116,104,97,116,100,105,115,99,117,115,115,105,111,110,32,111,102,109,105,100,100\n,108,101,32,111,102,32,116,104,101,97,110,32,105,110,100,105,118,105,100,117,97,\n108,100,105,102,102,105,99,117,108,116,32,116,111,32,112,111,105,110,116,32,111,\n102,32,118,105,101,119,104,111,109,111,115,101,120,117,97,108,105,116,121,97,99,\n99,101,112,116,97,110,99,101,32,111,102,60,47,115,112,97,110,62,60,47,100,105,\n118,62,109,97,110,117,102,97,99,116,117,114,101,114,115,111,114,105,103,105,110,\n32,111,102,32,116,104,101,99,111,109,109,111,110,108,121,32,117,115,101,100,105,\n109,112,111,114,116,97,110,99,101,32,111,102,100,101,110,111,109,105,110,97,116,\n105,111,110,115,98,97,99,107,103,114,111,117,110,100,58,32,35,108,101,110,103,\n116,104,32,111,102,32,116,104,101,100,101,116,101,114,109,105,110,97,116,105,111\n,110,97,32,115,105,103,110,105,102,105,99,97,110,116,34,32,98,111,114,100,101,\n114,61,34,48,34,62,114,101,118,111,108,117,116,105,111,110,97,114,121,112,114,\n105,110,99,105,112,108,101,115,32,111,102,105,115,32,99,111,110,115,105,100,101,\n114,101,100,119,97,115,32,100,101,118,101,108,111,112,101,100,73,110,100,111,45,\n69,117,114,111,112,101,97,110,118,117,108,110,101,114,97,98,108,101,32,116,111,\n112,114,111,112,111,110,101,110,116,115,32,111,102,97,114,101,32,115,111,109,101\n,116,105,109,101,115,99,108,111,115,101,114,32,116,111,32,116,104,101,78,101,119\n,32,89,111,114,107,32,67,105,116,121,32,110,97,109,101,61,34,115,101,97,114,99,\n104,97,116,116,114,105,98,117,116,101,100,32,116,111,99,111,117,114,115,101,32,\n111,102,32,116,104,101,109,97,116,104,101,109,97,116,105,99,105,97,110,98,121,32\n,116,104,101,32,101,110,100,32,111,102,97,116,32,116,104,101,32,101,110,100,32,\n111,102,34,32,98,111,114,100,101,114,61,34,48,34,32,116,101,99,104,110,111,108,\n111,103,105,99,97,108,46,114,101,109,111,118,101,67,108,97,115,115,40,98,114,97,\n110,99,104,32,111,102,32,116,104,101,101,118,105,100,101,110,99,101,32,116,104,\n97,116,33,91,101,110,100,105,102,93,45,45,62,13,10,73,110,115,116,105,116,117,\n116,101,32,111,102,32,105,110,116,111,32,97,32,115,105,110,103,108,101,114,101,\n115,112,101,99,116,105,118,101,108,121,46,97,110,100,32,116,104,101,114,101,102,\n111,114,101,112,114,111,112,101,114,116,105,101,115,32,111,102,105,115,32,108,\n111,99,97,116,101,100,32,105,110,115,111,109,101,32,111,102,32,119,104,105,99,\n104,84,104,101,114,101,32,105,115,32,97,108,115,111,99,111,110,116,105,110,117,\n101,100,32,116,111,32,97,112,112,101,97,114,97,110,99,101,32,111,102,32,38,97,\n109,112,59,110,100,97,115,104,59,32,100,101,115,99,114,105,98,101,115,32,116,104\n,101,99,111,110,115,105,100,101,114,97,116,105,111,110,97,117,116,104,111,114,32\n,111,102,32,116,104,101,105,110,100,101,112,101,110,100,101,110,116,108,121,101,\n113,117,105,112,112,101,100,32,119,105,116,104,100,111,101,115,32,110,111,116,32\n,104,97,118,101,60,47,97,62,60,97,32,104,114,101,102,61,34,99,111,110,102,117,\n115,101,100,32,119,105,116,104,60,108,105,110,107,32,104,114,101,102,61,34,47,97\n,116,32,116,104,101,32,97,103,101,32,111,102,97,112,112,101,97,114,32,105,110,32\n,116,104,101,84,104,101,115,101,32,105,110,99,108,117,100,101,114,101,103,97,114\n,100,108,101,115,115,32,111,102,99,111,117,108,100,32,98,101,32,117,115,101,100,\n32,115,116,121,108,101,61,38,113,117,111,116,59,115,101,118,101,114,97,108,32,\n116,105,109,101,115,114,101,112,114,101,115,101,110,116,32,116,104,101,98,111,\n100,121,62,10,60,47,104,116,109,108,62,116,104,111,117,103,104,116,32,116,111,32\n,98,101,112,111,112,117,108,97,116,105,111,110,32,111,102,112,111,115,115,105,98\n,105,108,105,116,105,101,115,112,101,114,99,101,110,116,97,103,101,32,111,102,97\n,99,99,101,115,115,32,116,111,32,116,104,101,97,110,32,97,116,116,101,109,112,\n116,32,116,111,112,114,111,100,117,99,116,105,111,110,32,111,102,106,113,117,101\n,114,121,47,106,113,117,101,114,121,116,119,111,32,100,105,102,102,101,114,101,\n110,116,98,101,108,111,110,103,32,116,111,32,116,104,101,101,115,116,97,98,108,\n105,115,104,109,101,110,116,114,101,112,108,97,99,105,110,103,32,116,104,101,100\n,101,115,99,114,105,112,116,105,111,110,34,32,100,101,116,101,114,109,105,110,\n101,32,116,104,101,97,118,97,105,108,97,98,108,101,32,102,111,114,65,99,99,111,\n114,100,105,110,103,32,116,111,32,119,105,100,101,32,114,97,110,103,101,32,111,\n102,9,60,100,105,118,32,99,108,97,115,115,61,34,109,111,114,101,32,99,111,109,\n109,111,110,108,121,111,114,103,97,110,105,115,97,116,105,111,110,115,102,117,\n110,99,116,105,111,110,97,108,105,116,121,119,97,115,32,99,111,109,112,108,101,\n116,101,100,32,38,97,109,112,59,109,100,97,115,104,59,32,112,97,114,116,105,99,\n105,112,97,116,105,111,110,116,104,101,32,99,104,97,114,97,99,116,101,114,97,110\n,32,97,100,100,105,116,105,111,110,97,108,97,112,112,101,97,114,115,32,116,111,\n32,98,101,102,97,99,116,32,116,104,97,116,32,116,104,101,97,110,32,101,120,97,\n109,112,108,101,32,111,102,115,105,103,110,105,102,105,99,97,110,116,108,121,111\n,110,109,111,117,115,101,111,118,101,114,61,34,98,101,99,97,117,115,101,32,116,\n104,101,121,32,97,115,121,110,99,32,61,32,116,114,117,101,59,112,114,111,98,108,\n101,109,115,32,119,105,116,104,115,101,101,109,115,32,116,111,32,104,97,118,101,\n116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,114,99,61,34,104,116,\n116,112,58,47,47,102,97,109,105,108,105,97,114,32,119,105,116,104,112,111,115,\n115,101,115,115,105,111,110,32,111,102,102,117,110,99,116,105,111,110,32,40,41,\n32,123,116,111,111,107,32,112,108,97,99,101,32,105,110,97,110,100,32,115,111,109\n,101,116,105,109,101,115,115,117,98,115,116,97,110,116,105,97,108,108,121,60,115\n,112,97,110,62,60,47,115,112,97,110,62,105,115,32,111,102,116,101,110,32,117,115\n,101,100,105,110,32,97,110,32,97,116,116,101,109,112,116,103,114,101,97,116,32,\n100,101,97,108,32,111,102,69,110,118,105,114,111,110,109,101,110,116,97,108,115,\n117,99,99,101,115,115,102,117,108,108,121,32,118,105,114,116,117,97,108,108,121,\n32,97,108,108,50,48,116,104,32,99,101,110,116,117,114,121,44,112,114,111,102,101\n,115,115,105,111,110,97,108,115,110,101,99,101,115,115,97,114,121,32,116,111,32,\n100,101,116,101,114,109,105,110,101,100,32,98,121,99,111,109,112,97,116,105,98,\n105,108,105,116,121,98,101,99,97,117,115,101,32,105,116,32,105,115,68,105,99,116\n,105,111,110,97,114,121,32,111,102,109,111,100,105,102,105,99,97,116,105,111,110\n,115,84,104,101,32,102,111,108,108,111,119,105,110,103,109,97,121,32,114,101,102\n,101,114,32,116,111,58,67,111,110,115,101,113,117,101,110,116,108,121,44,73,110,\n116,101,114,110,97,116,105,111,110,97,108,97,108,116,104,111,117,103,104,32,115,\n111,109,101,116,104,97,116,32,119,111,117,108,100,32,98,101,119,111,114,108,100,\n39,115,32,102,105,114,115,116,99,108,97,115,115,105,102,105,101,100,32,97,115,98\n,111,116,116,111,109,32,111,102,32,116,104,101,40,112,97,114,116,105,99,117,108,\n97,114,108,121,97,108,105,103,110,61,34,108,101,102,116,34,32,109,111,115,116,32\n,99,111,109,109,111,110,108,121,98,97,115,105,115,32,102,111,114,32,116,104,101,\n102,111,117,110,100,97,116,105,111,110,32,111,102,99,111,110,116,114,105,98,117,\n116,105,111,110,115,112,111,112,117,108,97,114,105,116,121,32,111,102,99,101,110\n,116,101,114,32,111,102,32,116,104,101,116,111,32,114,101,100,117,99,101,32,116,\n104,101,106,117,114,105,115,100,105,99,116,105,111,110,115,97,112,112,114,111,\n120,105,109,97,116,105,111,110,32,111,110,109,111,117,115,101,111,117,116,61,34,\n78,101,119,32,84,101,115,116,97,109,101,110,116,99,111,108,108,101,99,116,105,\n111,110,32,111,102,60,47,115,112,97,110,62,60,47,97,62,60,47,105,110,32,116,104,\n101,32,85,110,105,116,101,100,102,105,108,109,32,100,105,114,101,99,116,111,114,\n45,115,116,114,105,99,116,46,100,116,100,34,62,104,97,115,32,98,101,101,110,32,\n117,115,101,100,114,101,116,117,114,110,32,116,111,32,116,104,101,97,108,116,104\n,111,117,103,104,32,116,104,105,115,99,104,97,110,103,101,32,105,110,32,116,104,\n101,115,101,118,101,114,97,108,32,111,116,104,101,114,98,117,116,32,116,104,101,\n114,101,32,97,114,101,117,110,112,114,101,99,101,100,101,110,116,101,100,105,115\n,32,115,105,109,105,108,97,114,32,116,111,101,115,112,101,99,105,97,108,108,121,\n32,105,110,119,101,105,103,104,116,58,32,98,111,108,100,59,105,115,32,99,97,108,\n108,101,100,32,116,104,101,99,111,109,112,117,116,97,116,105,111,110,97,108,105,\n110,100,105,99,97,116,101,32,116,104,97,116,114,101,115,116,114,105,99,116,101,\n100,32,116,111,9,60,109,101,116,97,32,110,97,109,101,61,34,97,114,101,32,116,121\n,112,105,99,97,108,108,121,99,111,110,102,108,105,99,116,32,119,105,116,104,72,\n111,119,101,118,101,114,44,32,116,104,101,32,65,110,32,101,120,97,109,112,108,\n101,32,111,102,99,111,109,112,97,114,101,100,32,119,105,116,104,113,117,97,110,\n116,105,116,105,101,115,32,111,102,114,97,116,104,101,114,32,116,104,97,110,32,\n97,99,111,110,115,116,101,108,108,97,116,105,111,110,110,101,99,101,115,115,97,\n114,121,32,102,111,114,114,101,112,111,114,116,101,100,32,116,104,97,116,115,112\n,101,99,105,102,105,99,97,116,105,111,110,112,111,108,105,116,105,99,97,108,32,\n97,110,100,38,110,98,115,112,59,38,110,98,115,112,59,60,114,101,102,101,114,101,\n110,99,101,115,32,116,111,116,104,101,32,115,97,109,101,32,121,101,97,114,71,111\n,118,101,114,110,109,101,110,116,32,111,102,103,101,110,101,114,97,116,105,111,\n110,32,111,102,104,97,118,101,32,110,111,116,32,98,101,101,110,115,101,118,101,\n114,97,108,32,121,101,97,114,115,99,111,109,109,105,116,109,101,110,116,32,116,\n111,9,9,60,117,108,32,99,108,97,115,115,61,34,118,105,115,117,97,108,105,122,97,\n116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,44,112,114,97,99,116\n,105,116,105,111,110,101,114,115,116,104,97,116,32,104,101,32,119,111,117,108,\n100,97,110,100,32,99,111,110,116,105,110,117,101,100,111,99,99,117,112,97,116,\n105,111,110,32,111,102,105,115,32,100,101,102,105,110,101,100,32,97,115,99,101,\n110,116,114,101,32,111,102,32,116,104,101,116,104,101,32,97,109,111,117,110,116,\n32,111,102,62,60,100,105,118,32,115,116,121,108,101,61,34,101,113,117,105,118,97\n,108,101,110,116,32,111,102,100,105,102,102,101,114,101,110,116,105,97,116,101,\n98,114,111,117,103,104,116,32,97,98,111,117,116,109,97,114,103,105,110,45,108,\n101,102,116,58,32,97,117,116,111,109,97,116,105,99,97,108,108,121,116,104,111,\n117,103,104,116,32,111,102,32,97,115,83,111,109,101,32,111,102,32,116,104,101,\n115,101,10,60,100,105,118,32,99,108,97,115,115,61,34,105,110,112,117,116,32,99,\n108,97,115,115,61,34,114,101,112,108,97,99,101,100,32,119,105,116,104,105,115,32\n,111,110,101,32,111,102,32,116,104,101,101,100,117,99,97,116,105,111,110,32,97,\n110,100,105,110,102,108,117,101,110,99,101,100,32,98,121,114,101,112,117,116,97,\n116,105,111,110,32,97,115,10,60,109,101,116,97,32,110,97,109,101,61,34,97,99,99,\n111,109,109,111,100,97,116,105,111,110,60,47,100,105,118,62,10,60,47,100,105,118\n,62,108,97,114,103,101,32,112,97,114,116,32,111,102,73,110,115,116,105,116,117,\n116,101,32,102,111,114,116,104,101,32,115,111,45,99,97,108,108,101,100,32,97,103\n,97,105,110,115,116,32,116,104,101,32,73,110,32,116,104,105,115,32,99,97,115,101\n,44,119,97,115,32,97,112,112,111,105,110,116,101,100,99,108,97,105,109,101,100,\n32,116,111,32,98,101,72,111,119,101,118,101,114,44,32,116,104,105,115,68,101,112\n,97,114,116,109,101,110,116,32,111,102,116,104,101,32,114,101,109,97,105,110,105\n,110,103,101,102,102,101,99,116,32,111,110,32,116,104,101,112,97,114,116,105,99,\n117,108,97,114,108,121,32,100,101,97,108,32,119,105,116,104,32,116,104,101,10,60\n,100,105,118,32,115,116,121,108,101,61,34,97,108,109,111,115,116,32,97,108,119,\n97,121,115,97,114,101,32,99,117,114,114,101,110,116,108,121,101,120,112,114,101,\n115,115,105,111,110,32,111,102,112,104,105,108,111,115,111,112,104,121,32,111,\n102,102,111,114,32,109,111,114,101,32,116,104,97,110,99,105,118,105,108,105,122,\n97,116,105,111,110,115,111,110,32,116,104,101,32,105,115,108,97,110,100,115,101,\n108,101,99,116,101,100,73,110,100,101,120,99,97,110,32,114,101,115,117,108,116,\n32,105,110,34,32,118,97,108,117,101,61,34,34,32,47,62,116,104,101,32,115,116,114\n,117,99,116,117,114,101,32,47,62,60,47,97,62,60,47,100,105,118,62,77,97,110,121,\n32,111,102,32,116,104,101,115,101,99,97,117,115,101,100,32,98,121,32,116,104,101\n,111,102,32,116,104,101,32,85,110,105,116,101,100,115,112,97,110,32,99,108,97,\n115,115,61,34,109,99,97,110,32,98,101,32,116,114,97,99,101,100,105,115,32,114,\n101,108,97,116,101,100,32,116,111,98,101,99,97,109,101,32,111,110,101,32,111,102\n,105,115,32,102,114,101,113,117,101,110,116,108,121,108,105,118,105,110,103,32,\n105,110,32,116,104,101,116,104,101,111,114,101,116,105,99,97,108,108,121,70,111,\n108,108,111,119,105,110,103,32,116,104,101,82,101,118,111,108,117,116,105,111,\n110,97,114,121,103,111,118,101,114,110,109,101,110,116,32,105,110,105,115,32,100\n,101,116,101,114,109,105,110,101,100,116,104,101,32,112,111,108,105,116,105,99,\n97,108,105,110,116,114,111,100,117,99,101,100,32,105,110,115,117,102,102,105,99,\n105,101,110,116,32,116,111,100,101,115,99,114,105,112,116,105,111,110,34,62,115,\n104,111,114,116,32,115,116,111,114,105,101,115,115,101,112,97,114,97,116,105,111\n,110,32,111,102,97,115,32,116,111,32,119,104,101,116,104,101,114,107,110,111,119\n,110,32,102,111,114,32,105,116,115,119,97,115,32,105,110,105,116,105,97,108,108,\n121,100,105,115,112,108,97,121,58,98,108,111,99,107,105,115,32,97,110,32,101,120\n,97,109,112,108,101,116,104,101,32,112,114,105,110,99,105,112,97,108,99,111,110,\n115,105,115,116,115,32,111,102,32,97,114,101,99,111,103,110,105,122,101,100,32,\n97,115,47,98,111,100,121,62,60,47,104,116,109,108,62,97,32,115,117,98,115,116,97\n,110,116,105,97,108,114,101,99,111,110,115,116,114,117,99,116,101,100,104,101,97\n,100,32,111,102,32,115,116,97,116,101,114,101,115,105,115,116,97,110,99,101,32,\n116,111,117,110,100,101,114,103,114,97,100,117,97,116,101,84,104,101,114,101,32,\n97,114,101,32,116,119,111,103,114,97,118,105,116,97,116,105,111,110,97,108,97,\n114,101,32,100,101,115,99,114,105,98,101,100,105,110,116,101,110,116,105,111,110\n,97,108,108,121,115,101,114,118,101,100,32,97,115,32,116,104,101,99,108,97,115,\n115,61,34,104,101,97,100,101,114,111,112,112,111,115,105,116,105,111,110,32,116,\n111,102,117,110,100,97,109,101,110,116,97,108,108,121,100,111,109,105,110,97,116\n,101,100,32,116,104,101,97,110,100,32,116,104,101,32,111,116,104,101,114,97,108,\n108,105,97,110,99,101,32,119,105,116,104,119,97,115,32,102,111,114,99,101,100,32\n,116,111,114,101,115,112,101,99,116,105,118,101,108,121,44,97,110,100,32,112,111\n,108,105,116,105,99,97,108,105,110,32,115,117,112,112,111,114,116,32,111,102,112\n,101,111,112,108,101,32,105,110,32,116,104,101,50,48,116,104,32,99,101,110,116,\n117,114,121,46,97,110,100,32,112,117,98,108,105,115,104,101,100,108,111,97,100,\n67,104,97,114,116,98,101,97,116,116,111,32,117,110,100,101,114,115,116,97,110,\n100,109,101,109,98,101,114,32,115,116,97,116,101,115,101,110,118,105,114,111,110\n,109,101,110,116,97,108,102,105,114,115,116,32,104,97,108,102,32,111,102,99,111,\n117,110,116,114,105,101,115,32,97,110,100,97,114,99,104,105,116,101,99,116,117,\n114,97,108,98,101,32,99,111,110,115,105,100,101,114,101,100,99,104,97,114,97,99,\n116,101,114,105,122,101,100,99,108,101,97,114,73,110,116,101,114,118,97,108,97,\n117,116,104,111,114,105,116,97,116,105,118,101,70,101,100,101,114,97,116,105,111\n,110,32,111,102,119,97,115,32,115,117,99,99,101,101,100,101,100,97,110,100,32,\n116,104,101,114,101,32,97,114,101,97,32,99,111,110,115,101,113,117,101,110,99,\n101,116,104,101,32,80,114,101,115,105,100,101,110,116,97,108,115,111,32,105,110,\n99,108,117,100,101,100,102,114,101,101,32,115,111,102,116,119,97,114,101,115,117\n,99,99,101,115,115,105,111,110,32,111,102,100,101,118,101,108,111,112,101,100,32\n,116,104,101,119,97,115,32,100,101,115,116,114,111,121,101,100,97,119,97,121,32,\n102,114,111,109,32,116,104,101,59,10,60,47,115,99,114,105,112,116,62,10,60,97,\n108,116,104,111,117,103,104,32,116,104,101,121,102,111,108,108,111,119,101,100,\n32,98,121,32,97,109,111,114,101,32,112,111,119,101,114,102,117,108,114,101,115,\n117,108,116,101,100,32,105,110,32,97,85,110,105,118,101,114,115,105,116,121,32,\n111,102,72,111,119,101,118,101,114,44,32,109,97,110,121,116,104,101,32,112,114,\n101,115,105,100,101,110,116,72,111,119,101,118,101,114,44,32,115,111,109,101,105\n,115,32,116,104,111,117,103,104,116,32,116,111,117,110,116,105,108,32,116,104,\n101,32,101,110,100,119,97,115,32,97,110,110,111,117,110,99,101,100,97,114,101,32\n,105,109,112,111,114,116,97,110,116,97,108,115,111,32,105,110,99,108,117,100,101\n,115,62,60,105,110,112,117,116,32,116,121,112,101,61,116,104,101,32,99,101,110,\n116,101,114,32,111,102,32,68,79,32,78,79,84,32,65,76,84,69,82,117,115,101,100,32\n,116,111,32,114,101,102,101,114,116,104,101,109,101,115,47,63,115,111,114,116,61\n,116,104,97,116,32,104,97,100,32,98,101,101,110,116,104,101,32,98,97,115,105,115\n,32,102,111,114,104,97,115,32,100,101,118,101,108,111,112,101,100,105,110,32,116\n,104,101,32,115,117,109,109,101,114,99,111,109,112,97,114,97,116,105,118,101,108\n,121,100,101,115,99,114,105,98,101,100,32,116,104,101,115,117,99,104,32,97,115,\n32,116,104,111,115,101,116,104,101,32,114,101,115,117,108,116,105,110,103,105,\n115,32,105,109,112,111,115,115,105,98,108,101,118,97,114,105,111,117,115,32,111,\n116,104,101,114,83,111,117,116,104,32,65,102,114,105,99,97,110,104,97,118,101,32\n,116,104,101,32,115,97,109,101,101,102,102,101,99,116,105,118,101,110,101,115,\n115,105,110,32,119,104,105,99,104,32,99,97,115,101,59,32,116,101,120,116,45,97,\n108,105,103,110,58,115,116,114,117,99,116,117,114,101,32,97,110,100,59,32,98,97,\n99,107,103,114,111,117,110,100,58,114,101,103,97,114,100,105,110,103,32,116,104,\n101,115,117,112,112,111,114,116,101,100,32,116,104,101,105,115,32,97,108,115,111\n,32,107,110,111,119,110,115,116,121,108,101,61,34,109,97,114,103,105,110,105,110\n,99,108,117,100,105,110,103,32,116,104,101,98,97,104,97,115,97,32,77,101,108,97,\n121,117,110,111,114,115,107,32,98,111,107,109,195,165,108,110,111,114,115,107,32\n,110,121,110,111,114,115,107,115,108,111,118,101,110,197,161,196,141,105,110,97,\n105,110,116,101,114,110,97,99,105,111,110,97,108,99,97,108,105,102,105,99,97,99,\n105,195,179,110,99,111,109,117,110,105,99,97,99,105,195,179,110,99,111,110,115,\n116,114,117,99,99,105,195,179,110,34,62,60,100,105,118,32,99,108,97,115,115,61,\n34,100,105,115,97,109,98,105,103,117,97,116,105,111,110,68,111,109,97,105,110,78\n,97,109,101,39,44,32,39,97,100,109,105,110,105,115,116,114,97,116,105,111,110,\n115,105,109,117,108,116,97,110,101,111,117,115,108,121,116,114,97,110,115,112,\n111,114,116,97,116,105,111,110,73,110,116,101,114,110,97,116,105,111,110,97,108,\n32,109,97,114,103,105,110,45,98,111,116,116,111,109,58,114,101,115,112,111,110,\n115,105,98,105,108,105,116,121,60,33,91,101,110,100,105,102,93,45,45,62,10,60,47\n,62,60,109,101,116,97,32,110,97,109,101,61,34,105,109,112,108,101,109,101,110,\n116,97,116,105,111,110,105,110,102,114,97,115,116,114,117,99,116,117,114,101,114\n,101,112,114,101,115,101,110,116,97,116,105,111,110,98,111,114,100,101,114,45,98\n,111,116,116,111,109,58,60,47,104,101,97,100,62,10,60,98,111,100,121,62,61,104,\n116,116,112,37,51,65,37,50,70,37,50,70,60,102,111,114,109,32,109,101,116,104,111\n,100,61,34,109,101,116,104,111,100,61,34,112,111,115,116,34,32,47,102,97,118,105\n,99,111,110,46,105,99,111,34,32,125,41,59,10,60,47,115,99,114,105,112,116,62,10,\n46,115,101,116,65,116,116,114,105,98,117,116,101,40,65,100,109,105,110,105,115,\n116,114,97,116,105,111,110,61,32,110,101,119,32,65,114,114,97,121,40,41,59,60,33\n,91,101,110,100,105,102,93,45,45,62,13,10,100,105,115,112,108,97,121,58,98,108,\n111,99,107,59,85,110,102,111,114,116,117,110,97,116,101,108,121,44,34,62,38,110,\n98,115,112,59,60,47,100,105,118,62,47,102,97,118,105,99,111,110,46,105,99,111,34\n,62,61,39,115,116,121,108,101,115,104,101,101,116,39,32,105,100,101,110,116,105,\n102,105,99,97,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,44\n,60,108,105,62,60,97,32,104,114,101,102,61,34,47,97,110,32,97,108,116,101,114,\n110,97,116,105,118,101,97,115,32,97,32,114,101,115,117,108,116,32,111,102,112,\n116,34,62,60,47,115,99,114,105,112,116,62,10,116,121,112,101,61,34,115,117,98,\n109,105,116,34,32,10,40,102,117,110,99,116,105,111,110,40,41,32,123,114,101,99,\n111,109,109,101,110,100,97,116,105,111,110,102,111,114,109,32,97,99,116,105,111,\n110,61,34,47,116,114,97,110,115,102,111,114,109,97,116,105,111,110,114,101,99,\n111,110,115,116,114,117,99,116,105,111,110,46,115,116,121,108,101,46,100,105,115\n,112,108,97,121,32,65,99,99,111,114,100,105,110,103,32,116,111,32,104,105,100,\n100,101,110,34,32,110,97,109,101,61,34,97,108,111,110,103,32,119,105,116,104,32,\n116,104,101,100,111,99,117,109,101,110,116,46,98,111,100,121,46,97,112,112,114,\n111,120,105,109,97,116,101,108,121,32,67,111,109,109,117,110,105,99,97,116,105,\n111,110,115,112,111,115,116,34,32,97,99,116,105,111,110,61,34,109,101,97,110,105\n,110,103,32,38,113,117,111,116,59,45,45,60,33,91,101,110,100,105,102,93,45,45,62\n,80,114,105,109,101,32,77,105,110,105,115,116,101,114,99,104,97,114,97,99,116,\n101,114,105,115,116,105,99,60,47,97,62,32,60,97,32,99,108,97,115,115,61,116,104,\n101,32,104,105,115,116,111,114,121,32,111,102,32,111,110,109,111,117,115,101,111\n,118,101,114,61,34,116,104,101,32,103,111,118,101,114,110,109,101,110,116,104,\n114,101,102,61,34,104,116,116,112,115,58,47,47,119,97,115,32,111,114,105,103,105\n,110,97,108,108,121,119,97,115,32,105,110,116,114,111,100,117,99,101,100,99,108,\n97,115,115,105,102,105,99,97,116,105,111,110,114,101,112,114,101,115,101,110,116\n,97,116,105,118,101,97,114,101,32,99,111,110,115,105,100,101,114,101,100,60,33,\n91,101,110,100,105,102,93,45,45,62,10,10,100,101,112,101,110,100,115,32,111,110,\n32,116,104,101,85,110,105,118,101,114,115,105,116,121,32,111,102,32,105,110,32,\n99,111,110,116,114,97,115,116,32,116,111,32,112,108,97,99,101,104,111,108,100,\n101,114,61,34,105,110,32,116,104,101,32,99,97,115,101,32,111,102,105,110,116,101\n,114,110,97,116,105,111,110,97,108,32,99,111,110,115,116,105,116,117,116,105,111\n,110,97,108,115,116,121,108,101,61,34,98,111,114,100,101,114,45,58,32,102,117,\n110,99,116,105,111,110,40,41,32,123,66,101,99,97,117,115,101,32,111,102,32,116,\n104,101,45,115,116,114,105,99,116,46,100,116,100,34,62,10,60,116,97,98,108,101,\n32,99,108,97,115,115,61,34,97,99,99,111,109,112,97,110,105,101,100,32,98,121,97,\n99,99,111,117,110,116,32,111,102,32,116,104,101,60,115,99,114,105,112,116,32,115\n,114,99,61,34,47,110,97,116,117,114,101,32,111,102,32,116,104,101,32,116,104,101\n,32,112,101,111,112,108,101,32,105,110,32,105,110,32,97,100,100,105,116,105,111,\n110,32,116,111,115,41,59,32,106,115,46,105,100,32,61,32,105,100,34,32,119,105,\n100,116,104,61,34,49,48,48,37,34,114,101,103,97,114,100,105,110,103,32,116,104,\n101,32,82,111,109,97,110,32,67,97,116,104,111,108,105,99,97,110,32,105,110,100,\n101,112,101,110,100,101,110,116,102,111,108,108,111,119,105,110,103,32,116,104,\n101,32,46,103,105,102,34,32,119,105,100,116,104,61,34,49,116,104,101,32,102,111,\n108,108,111,119,105,110,103,32,100,105,115,99,114,105,109,105,110,97,116,105,111\n,110,97,114,99,104,97,101,111,108,111,103,105,99,97,108,112,114,105,109,101,32,\n109,105,110,105,115,116,101,114,46,106,115,34,62,60,47,115,99,114,105,112,116,62\n,99,111,109,98,105,110,97,116,105,111,110,32,111,102,32,109,97,114,103,105,110,\n119,105,100,116,104,61,34,99,114,101,97,116,101,69,108,101,109,101,110,116,40,\n119,46,97,116,116,97,99,104,69,118,101,110,116,40,60,47,97,62,60,47,116,100,62,\n60,47,116,114,62,115,114,99,61,34,104,116,116,112,115,58,47,47,97,73,110,32,112,\n97,114,116,105,99,117,108,97,114,44,32,97,108,105,103,110,61,34,108,101,102,116,\n34,32,67,122,101,99,104,32,82,101,112,117,98,108,105,99,85,110,105,116,101,100,\n32,75,105,110,103,100,111,109,99,111,114,114,101,115,112,111,110,100,101,110,99,\n101,99,111,110,99,108,117,100,101,100,32,116,104,97,116,46,104,116,109,108,34,32\n,116,105,116,108,101,61,34,40,102,117,110,99,116,105,111,110,32,40,41,32,123,99,\n111,109,101,115,32,102,114,111,109,32,116,104,101,97,112,112,108,105,99,97,116,\n105,111,110,32,111,102,60,115,112,97,110,32,99,108,97,115,115,61,34,115,98,101,\n108,105,101,118,101,100,32,116,111,32,98,101,101,109,101,110,116,40,39,115,99,\n114,105,112,116,39,60,47,97,62,10,60,47,108,105,62,10,60,108,105,118,101,114,121\n,32,100,105,102,102,101,114,101,110,116,62,60,115,112,97,110,32,99,108,97,115,\n115,61,34,111,112,116,105,111,110,32,118,97,108,117,101,61,34,40,97,108,115,111,\n32,107,110,111,119,110,32,97,115,9,60,108,105,62,60,97,32,104,114,101,102,61,34,\n62,60,105,110,112,117,116,32,110,97,109,101,61,34,115,101,112,97,114,97,116,101,\n100,32,102,114,111,109,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,\n118,97,108,105,103,110,61,34,116,111,112,34,62,102,111,117,110,100,101,114,32,\n111,102,32,116,104,101,97,116,116,101,109,112,116,105,110,103,32,116,111,32,99,\n97,114,98,111,110,32,100,105,111,120,105,100,101,10,10,60,100,105,118,32,99,108,\n97,115,115,61,34,99,108,97,115,115,61,34,115,101,97,114,99,104,45,47,98,111,100,\n121,62,10,60,47,104,116,109,108,62,111,112,112,111,114,116,117,110,105,116,121,\n32,116,111,99,111,109,109,117,110,105,99,97,116,105,111,110,115,60,47,104,101,97\n,100,62,13,10,60,98,111,100,121,32,115,116,121,108,101,61,34,119,105,100,116,104\n,58,84,105,225,186,191,110,103,32,86,105,225,187,135,116,99,104,97,110,103,101,\n115,32,105,110,32,116,104,101,98,111,114,100,101,114,45,99,111,108,111,114,58,35\n,48,34,32,98,111,114,100,101,114,61,34,48,34,32,60,47,115,112,97,110,62,60,47,\n100,105,118,62,60,119,97,115,32,100,105,115,99,111,118,101,114,101,100,34,32,116\n,121,112,101,61,34,116,101,120,116,34,32,41,59,10,60,47,115,99,114,105,112,116,\n62,10,10,68,101,112,97,114,116,109,101,110,116,32,111,102,32,101,99,99,108,101,\n115,105,97,115,116,105,99,97,108,116,104,101,114,101,32,104,97,115,32,98,101,101\n,110,114,101,115,117,108,116,105,110,103,32,102,114,111,109,60,47,98,111,100,121\n,62,60,47,104,116,109,108,62,104,97,115,32,110,101,118,101,114,32,98,101,101,110\n,116,104,101,32,102,105,114,115,116,32,116,105,109,101,105,110,32,114,101,115,\n112,111,110,115,101,32,116,111,97,117,116,111,109,97,116,105,99,97,108,108,121,\n32,60,47,100,105,118,62,10,10,60,100,105,118,32,105,119,97,115,32,99,111,110,115\n,105,100,101,114,101,100,112,101,114,99,101,110,116,32,111,102,32,116,104,101,34\n,32,47,62,60,47,97,62,60,47,100,105,118,62,99,111,108,108,101,99,116,105,111,110\n,32,111,102,32,100,101,115,99,101,110,100,101,100,32,102,114,111,109,115,101,99,\n116,105,111,110,32,111,102,32,116,104,101,97,99,99,101,112,116,45,99,104,97,114,\n115,101,116,116,111,32,98,101,32,99,111,110,102,117,115,101,100,109,101,109,98,\n101,114,32,111,102,32,116,104,101,32,112,97,100,100,105,110,103,45,114,105,103,\n104,116,58,116,114,97,110,115,108,97,116,105,111,110,32,111,102,105,110,116,101,\n114,112,114,101,116,97,116,105,111,110,32,104,114,101,102,61,39,104,116,116,112,\n58,47,47,119,104,101,116,104,101,114,32,111,114,32,110,111,116,84,104,101,114,\n101,32,97,114,101,32,97,108,115,111,116,104,101,114,101,32,97,114,101,32,109,97,\n110,121,97,32,115,109,97,108,108,32,110,117,109,98,101,114,111,116,104,101,114,\n32,112,97,114,116,115,32,111,102,105,109,112,111,115,115,105,98,108,101,32,116,\n111,32,32,99,108,97,115,115,61,34,98,117,116,116,111,110,108,111,99,97,116,101,\n100,32,105,110,32,116,104,101,46,32,72,111,119,101,118,101,114,44,32,116,104,101\n,97,110,100,32,101,118,101,110,116,117,97,108,108,121,65,116,32,116,104,101,32,\n101,110,100,32,111,102,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,114\n,101,112,114,101,115,101,110,116,115,32,116,104,101,60,102,111,114,109,32,97,99,\n116,105,111,110,61,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,105,\n116,32,105,115,32,112,111,115,115,105,98,108,101,109,111,114,101,32,108,105,107,\n101,108,121,32,116,111,97,110,32,105,110,99,114,101,97,115,101,32,105,110,104,97\n,118,101,32,97,108,115,111,32,98,101,101,110,99,111,114,114,101,115,112,111,110,\n100,115,32,116,111,97,110,110,111,117,110,99,101,100,32,116,104,97,116,97,108,\n105,103,110,61,34,114,105,103,104,116,34,62,109,97,110,121,32,99,111,117,110,116\n,114,105,101,115,102,111,114,32,109,97,110,121,32,121,101,97,114,115,101,97,114,\n108,105,101,115,116,32,107,110,111,119,110,98,101,99,97,117,115,101,32,105,116,\n32,119,97,115,112,116,34,62,60,47,115,99,114,105,112,116,62,13,32,118,97,108,105\n,103,110,61,34,116,111,112,34,32,105,110,104,97,98,105,116,97,110,116,115,32,111\n,102,102,111,108,108,111,119,105,110,103,32,121,101,97,114,13,10,60,100,105,118,\n32,99,108,97,115,115,61,34,109,105,108,108,105,111,110,32,112,101,111,112,108,\n101,99,111,110,116,114,111,118,101,114,115,105,97,108,32,99,111,110,99,101,114,\n110,105,110,103,32,116,104,101,97,114,103,117,101,32,116,104,97,116,32,116,104,\n101,103,111,118,101,114,110,109,101,110,116,32,97,110,100,97,32,114,101,102,101,\n114,101,110,99,101,32,116,111,116,114,97,110,115,102,101,114,114,101,100,32,116,\n111,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,115,116,121,108,101,\n61,34,99,111,108,111,114,58,97,108,116,104,111,117,103,104,32,116,104,101,114,\n101,98,101,115,116,32,107,110,111,119,110,32,102,111,114,115,117,98,109,105,116,\n34,32,110,97,109,101,61,34,109,117,108,116,105,112,108,105,99,97,116,105,111,110\n,109,111,114,101,32,116,104,97,110,32,111,110,101,32,114,101,99,111,103,110,105,\n116,105,111,110,32,111,102,67,111,117,110,99,105,108,32,111,102,32,116,104,101,\n101,100,105,116,105,111,110,32,111,102,32,116,104,101,32,32,60,109,101,116,97,32\n,110,97,109,101,61,34,69,110,116,101,114,116,97,105,110,109,101,110,116,32,97,\n119,97,121,32,102,114,111,109,32,116,104,101,32,59,109,97,114,103,105,110,45,114\n,105,103,104,116,58,97,116,32,116,104,101,32,116,105,109,101,32,111,102,105,110,\n118,101,115,116,105,103,97,116,105,111,110,115,99,111,110,110,101,99,116,101,100\n,32,119,105,116,104,97,110,100,32,109,97,110,121,32,111,116,104,101,114,97,108,\n116,104,111,117,103,104,32,105,116,32,105,115,98,101,103,105,110,110,105,110,103\n,32,119,105,116,104,32,60,115,112,97,110,32,99,108,97,115,115,61,34,100,101,115,\n99,101,110,100,97,110,116,115,32,111,102,60,115,112,97,110,32,99,108,97,115,115,\n61,34,105,32,97,108,105,103,110,61,34,114,105,103,104,116,34,60,47,104,101,97,\n100,62,10,60,98,111,100,121,32,97,115,112,101,99,116,115,32,111,102,32,116,104,\n101,104,97,115,32,115,105,110,99,101,32,98,101,101,110,69,117,114,111,112,101,97\n,110,32,85,110,105,111,110,114,101,109,105,110,105,115,99,101,110,116,32,111,102\n,109,111,114,101,32,100,105,102,102,105,99,117,108,116,86,105,99,101,32,80,114,\n101,115,105,100,101,110,116,99,111,109,112,111,115,105,116,105,111,110,32,111,\n102,112,97,115,115,101,100,32,116,104,114,111,117,103,104,109,111,114,101,32,105\n,109,112,111,114,116,97,110,116,102,111,110,116,45,115,105,122,101,58,49,49,112,\n120,101,120,112,108,97,110,97,116,105,111,110,32,111,102,116,104,101,32,99,111,\n110,99,101,112,116,32,111,102,119,114,105,116,116,101,110,32,105,110,32,116,104,\n101,9,60,115,112,97,110,32,99,108,97,115,115,61,34,105,115,32,111,110,101,32,111\n,102,32,116,104,101,32,114,101,115,101,109,98,108,97,110,99,101,32,116,111,111,\n110,32,116,104,101,32,103,114,111,117,110,100,115,119,104,105,99,104,32,99,111,\n110,116,97,105,110,115,105,110,99,108,117,100,105,110,103,32,116,104,101,32,100,\n101,102,105,110,101,100,32,98,121,32,116,104,101,112,117,98,108,105,99,97,116,\n105,111,110,32,111,102,109,101,97,110,115,32,116,104,97,116,32,116,104,101,111,\n117,116,115,105,100,101,32,111,102,32,116,104,101,115,117,112,112,111,114,116,32\n,111,102,32,116,104,101,60,105,110,112,117,116,32,99,108,97,115,115,61,34,60,115\n,112,97,110,32,99,108,97,115,115,61,34,116,40,77,97,116,104,46,114,97,110,100,\n111,109,40,41,109,111,115,116,32,112,114,111,109,105,110,101,110,116,100,101,115\n,99,114,105,112,116,105,111,110,32,111,102,67,111,110,115,116,97,110,116,105,110\n,111,112,108,101,119,101,114,101,32,112,117,98,108,105,115,104,101,100,60,100,\n105,118,32,99,108,97,115,115,61,34,115,101,97,112,112,101,97,114,115,32,105,110,\n32,116,104,101,49,34,32,104,101,105,103,104,116,61,34,49,34,32,109,111,115,116,\n32,105,109,112,111,114,116,97,110,116,119,104,105,99,104,32,105,110,99,108,117,\n100,101,115,119,104,105,99,104,32,104,97,100,32,98,101,101,110,100,101,115,116,\n114,117,99,116,105,111,110,32,111,102,116,104,101,32,112,111,112,117,108,97,116,\n105,111,110,10,9,60,100,105,118,32,99,108,97,115,115,61,34,112,111,115,115,105,\n98,105,108,105,116,121,32,111,102,115,111,109,101,116,105,109,101,115,32,117,115\n,101,100,97,112,112,101,97,114,32,116,111,32,104,97,118,101,115,117,99,99,101,\n115,115,32,111,102,32,116,104,101,105,110,116,101,110,100,101,100,32,116,111,32,\n98,101,112,114,101,115,101,110,116,32,105,110,32,116,104,101,115,116,121,108,101\n,61,34,99,108,101,97,114,58,98,13,10,60,47,115,99,114,105,112,116,62,13,10,60,\n119,97,115,32,102,111,117,110,100,101,100,32,105,110,105,110,116,101,114,118,105\n,101,119,32,119,105,116,104,95,105,100,34,32,99,111,110,116,101,110,116,61,34,99\n,97,112,105,116,97,108,32,111,102,32,116,104,101,13,10,60,108,105,110,107,32,114\n,101,108,61,34,115,114,101,108,101,97,115,101,32,111,102,32,116,104,101,112,111,\n105,110,116,32,111,117,116,32,116,104,97,116,120,77,76,72,116,116,112,82,101,113\n,117,101,115,116,97,110,100,32,115,117,98,115,101,113,117,101,110,116,115,101,99\n,111,110,100,32,108,97,114,103,101,115,116,118,101,114,121,32,105,109,112,111,\n114,116,97,110,116,115,112,101,99,105,102,105,99,97,116,105,111,110,115,115,117,\n114,102,97,99,101,32,111,102,32,116,104,101,97,112,112,108,105,101,100,32,116,\n111,32,116,104,101,102,111,114,101,105,103,110,32,112,111,108,105,99,121,95,115,\n101,116,68,111,109,97,105,110,78,97,109,101,101,115,116,97,98,108,105,115,104,\n101,100,32,105,110,105,115,32,98,101,108,105,101,118,101,100,32,116,111,73,110,\n32,97,100,100,105,116,105,111,110,32,116,111,109,101,97,110,105,110,103,32,111,\n102,32,116,104,101,105,115,32,110,97,109,101,100,32,97,102,116,101,114,116,111,\n32,112,114,111,116,101,99,116,32,116,104,101,105,115,32,114,101,112,114,101,115,\n101,110,116,101,100,68,101,99,108,97,114,97,116,105,111,110,32,111,102,109,111,\n114,101,32,101,102,102,105,99,105,101,110,116,67,108,97,115,115,105,102,105,99,\n97,116,105,111,110,111,116,104,101,114,32,102,111,114,109,115,32,111,102,104,101\n,32,114,101,116,117,114,110,101,100,32,116,111,60,115,112,97,110,32,99,108,97,\n115,115,61,34,99,112,101,114,102,111,114,109,97,110,99,101,32,111,102,40,102,117\n,110,99,116,105,111,110,40,41,32,123,13,105,102,32,97,110,100,32,111,110,108,121\n,32,105,102,114,101,103,105,111,110,115,32,111,102,32,116,104,101,108,101,97,100\n,105,110,103,32,116,111,32,116,104,101,114,101,108,97,116,105,111,110,115,32,119\n,105,116,104,85,110,105,116,101,100,32,78,97,116,105,111,110,115,115,116,121,108\n,101,61,34,104,101,105,103,104,116,58,111,116,104,101,114,32,116,104,97,110,32,\n116,104,101,121,112,101,34,32,99,111,110,116,101,110,116,61,34,65,115,115,111,99\n,105,97,116,105,111,110,32,111,102,10,60,47,104,101,97,100,62,10,60,98,111,100,\n121,108,111,99,97,116,101,100,32,111,110,32,116,104,101,105,115,32,114,101,102,\n101,114,114,101,100,32,116,111,40,105,110,99,108,117,100,105,110,103,32,116,104,\n101,99,111,110,99,101,110,116,114,97,116,105,111,110,115,116,104,101,32,105,110,\n100,105,118,105,100,117,97,108,97,109,111,110,103,32,116,104,101,32,109,111,115,\n116,116,104,97,110,32,97,110,121,32,111,116,104,101,114,47,62,10,60,108,105,110,\n107,32,114,101,108,61,34,32,114,101,116,117,114,110,32,102,97,108,115,101,59,116\n,104,101,32,112,117,114,112,111,115,101,32,111,102,116,104,101,32,97,98,105,108,\n105,116,121,32,116,111,59,99,111,108,111,114,58,35,102,102,102,125,10,46,10,60,\n115,112,97,110,32,99,108,97,115,115,61,34,116,104,101,32,115,117,98,106,101,99,\n116,32,111,102,100,101,102,105,110,105,116,105,111,110,115,32,111,102,62,13,10,\n60,108,105,110,107,32,114,101,108,61,34,99,108,97,105,109,32,116,104,97,116,32,\n116,104,101,104,97,118,101,32,100,101,118,101,108,111,112,101,100,60,116,97,98,\n108,101,32,119,105,100,116,104,61,34,99,101,108,101,98,114,97,116,105,111,110,32\n,111,102,70,111,108,108,111,119,105,110,103,32,116,104,101,32,116,111,32,100,105\n,115,116,105,110,103,117,105,115,104,60,115,112,97,110,32,99,108,97,115,115,61,\n34,98,116,97,107,101,115,32,112,108,97,99,101,32,105,110,117,110,100,101,114,32,\n116,104,101,32,110,97,109,101,110,111,116,101,100,32,116,104,97,116,32,116,104,\n101,62,60,33,91,101,110,100,105,102,93,45,45,62,10,115,116,121,108,101,61,34,109\n,97,114,103,105,110,45,105,110,115,116,101,97,100,32,111,102,32,116,104,101,105,\n110,116,114,111,100,117,99,101,100,32,116,104,101,116,104,101,32,112,114,111,99,\n101,115,115,32,111,102,105,110,99,114,101,97,115,105,110,103,32,116,104,101,100,\n105,102,102,101,114,101,110,99,101,115,32,105,110,101,115,116,105,109,97,116,101\n,100,32,116,104,97,116,101,115,112,101,99,105,97,108,108,121,32,116,104,101,47,\n100,105,118,62,60,100,105,118,32,105,100,61,34,119,97,115,32,101,118,101,110,116\n,117,97,108,108,121,116,104,114,111,117,103,104,111,117,116,32,104,105,115,116,\n104,101,32,100,105,102,102,101,114,101,110,99,101,115,111,109,101,116,104,105,\n110,103,32,116,104,97,116,115,112,97,110,62,60,47,115,112,97,110,62,60,47,115,\n105,103,110,105,102,105,99,97,110,116,108,121,32,62,60,47,115,99,114,105,112,116\n,62,13,10,13,10,101,110,118,105,114,111,110,109,101,110,116,97,108,32,116,111,32\n,112,114,101,118,101,110,116,32,116,104,101,104,97,118,101,32,98,101,101,110,32,\n117,115,101,100,101,115,112,101,99,105,97,108,108,121,32,102,111,114,117,110,100\n,101,114,115,116,97,110,100,32,116,104,101,105,115,32,101,115,115,101,110,116,\n105,97,108,108,121,119,101,114,101,32,116,104,101,32,102,105,114,115,116,105,115\n,32,116,104,101,32,108,97,114,103,101,115,116,104,97,118,101,32,98,101,101,110,\n32,109,97,100,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,105,110,116,\n101,114,112,114,101,116,101,100,32,97,115,115,101,99,111,110,100,32,104,97,108,\n102,32,111,102,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,115,32,99,\n111,109,112,111,115,101,100,32,111,102,73,73,44,32,72,111,108,121,32,82,111,109,\n97,110,105,115,32,101,120,112,101,99,116,101,100,32,116,111,104,97,118,101,32,\n116,104,101,105,114,32,111,119,110,100,101,102,105,110,101,100,32,97,115,32,116,\n104,101,116,114,97,100,105,116,105,111,110,97,108,108,121,32,104,97,118,101,32,\n100,105,102,102,101,114,101,110,116,97,114,101,32,111,102,116,101,110,32,117,115\n,101,100,116,111,32,101,110,115,117,114,101,32,116,104,97,116,97,103,114,101,101\n,109,101,110,116,32,119,105,116,104,99,111,110,116,97,105,110,105,110,103,32,116\n,104,101,97,114,101,32,102,114,101,113,117,101,110,116,108,121,105,110,102,111,\n114,109,97,116,105,111,110,32,111,110,101,120,97,109,112,108,101,32,105,115,32,\n116,104,101,114,101,115,117,108,116,105,110,103,32,105,110,32,97,60,47,97,62,60,\n47,108,105,62,60,47,117,108,62,32,99,108,97,115,115,61,34,102,111,111,116,101,\n114,97,110,100,32,101,115,112,101,99,105,97,108,108,121,116,121,112,101,61,34,98\n,117,116,116,111,110,34,32,60,47,115,112,97,110,62,60,47,115,112,97,110,62,119,\n104,105,99,104,32,105,110,99,108,117,100,101,100,62,10,60,109,101,116,97,32,110,\n97,109,101,61,34,99,111,110,115,105,100,101,114,101,100,32,116,104,101,99,97,114\n,114,105,101,100,32,111,117,116,32,98,121,72,111,119,101,118,101,114,44,32,105,\n116,32,105,115,98,101,99,97,109,101,32,112,97,114,116,32,111,102,105,110,32,114,\n101,108,97,116,105,111,110,32,116,111,112,111,112,117,108,97,114,32,105,110,32,\n116,104,101,116,104,101,32,99,97,112,105,116,97,108,32,111,102,119,97,115,32,111\n,102,102,105,99,105,97,108,108,121,119,104,105,99,104,32,104,97,115,32,98,101,\n101,110,116,104,101,32,72,105,115,116,111,114,121,32,111,102,97,108,116,101,114,\n110,97,116,105,118,101,32,116,111,100,105,102,102,101,114,101,110,116,32,102,114\n,111,109,116,111,32,115,117,112,112,111,114,116,32,116,104,101,115,117,103,103,\n101,115,116,101,100,32,116,104,97,116,105,110,32,116,104,101,32,112,114,111,99,\n101,115,115,32,32,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,102,\n111,117,110,100,97,116,105,111,110,98,101,99,97,117,115,101,32,111,102,32,104,\n105,115,99,111,110,99,101,114,110,101,100,32,119,105,116,104,116,104,101,32,117,\n110,105,118,101,114,115,105,116,121,111,112,112,111,115,101,100,32,116,111,32,\n116,104,101,116,104,101,32,99,111,110,116,101,120,116,32,111,102,60,115,112,97,\n110,32,99,108,97,115,115,61,34,112,116,101,120,116,34,32,110,97,109,101,61,34,\n113,34,9,9,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,115,99,105,\n101,110,116,105,102,105,99,114,101,112,114,101,115,101,110,116,101,100,32,98,121\n,109,97,116,104,101,109,97,116,105,99,105,97,110,115,101,108,101,99,116,101,100,\n32,98,121,32,116,104,101,116,104,97,116,32,104,97,118,101,32,98,101,101,110,62,\n60,100,105,118,32,99,108,97,115,115,61,34,99,100,105,118,32,105,100,61,34,104,\n101,97,100,101,114,105,110,32,112,97,114,116,105,99,117,108,97,114,44,99,111,110\n,118,101,114,116,101,100,32,105,110,116,111,41,59,10,60,47,115,99,114,105,112,\n116,62,10,60,112,104,105,108,111,115,111,112,104,105,99,97,108,32,115,114,112,\n115,107,111,104,114,118,97,116,115,107,105,116,105,225,186,191,110,103,32,86,105\n,225,187,135,116,208,160,209,131,209,129,209,129,208,186,208,184,208,185,209,128\n,209,131,209,129,209,129,208,186,208,184,208,185,105,110,118,101,115,116,105,103\n,97,99,105,195,179,110,112,97,114,116,105,99,105,112,97,99,105,195,179,110,208,\n186,208,190,209,130,208,190,209,128,209,139,208,181,208,190,208,177,208,187,208,\n176,209,129,209,130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,208,\n185,209,135,208,181,208,187,208,190,208,178,208,181,208,186,209,129,208,184,209,\n129,209,130,208,181,208,188,209,139,208,157,208,190,208,178,208,190,209,129,209,\n130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,209,133,208,190,208,\n177,208,187,208,176,209,129,209,130,209,140,208,178,209,128,208,181,208,188,208,\n181,208,189,208,184,208,186,208,190,209,130,208,190,209,128,208,176,209,143,209,\n129,208,181,208,179,208,190,208,180,208,189,209,143,209,129,208,186,208,176,209,\n135,208,176,209,130,209,140,208,189,208,190,208,178,208,190,209,129,209,130,208,\n184,208,163,208,186,209,128,208,176,208,184,208,189,209,139,208,178,208,190,208,\n191,209,128,208,190,209,129,209,139,208,186,208,190,209,130,208,190,209,128,208,\n190,208,185,209,129,208,180,208,181,208,187,208,176,209,130,209,140,208,191,208,\n190,208,188,208,190,209,137,209,140,209,142,209,129,209,128,208,181,208,180,209,\n129,209,130,208,178,208,190,208,177,209,128,208,176,208,183,208,190,208,188,209,\n129,209,130,208,190,209,128,208,190,208,189,209,139,209,131,209,135,208,176,209,\n129,209,130,208,184,208,181,209,130,208,181,209,135,208,181,208,189,208,184,208,\n181,208,147,208,187,208,176,208,178,208,189,208,176,209,143,208,184,209,129,209,\n130,208,190,209,128,208,184,208,184,209,129,208,184,209,129,209,130,208,181,208,\n188,208,176,209,128,208,181,209,136,208,181,208,189,208,184,209,143,208,161,208,\n186,208,176,209,135,208,176,209,130,209,140,208,191,208,190,209,141,209,130,208,\n190,208,188,209,131,209,129,208,187,208,181,208,180,209,131,208,181,209,130,209,\n129,208,186,208,176,208,183,208,176,209,130,209,140,209,130,208,190,208,178,208,\n176,209,128,208,190,208,178,208,186,208,190,208,189,208,181,209,135,208,189,208,\n190,209,128,208,181,209,136,208,181,208,189,208,184,208,181,208,186,208,190,209,\n130,208,190,209,128,208,190,208,181,208,190,209,128,208,179,208,176,208,189,208,\n190,208,178,208,186,208,190,209,130,208,190,209,128,208,190,208,188,208,160,208,\n181,208,186,208,187,208,176,208,188,208,176,216,167,217,132,217,133,217,134,216,\n170,216,175,217,137,217,133,217,134,216,170,216,175,217,138,216,167,216,170,216,\n167,217,132,217,133,217,136,216,182,217,136,216,185,216,167,217,132,216,168,216,\n177,216,167,217,133,216,172,216,167,217,132,217,133,217,136,216,167,217,130,216,\n185,216,167,217,132,216,177,216,179,216,167,216,166,217,132,217,133,216,180,216,\n167,216,177,217,131,216,167,216,170,216,167,217,132,216,163,216,185,216,182,216,\n167,216,161,216,167,217,132,216,177,217,138,216,167,216,182,216,169,216,167,217,\n132,216,170,216,181,217,133,217,138,217,133,216,167,217,132,216,167,216,185,216,\n182,216,167,216,161,216,167,217,132,217,134,216,170,216,167,216,166,216,172,216,\n167,217,132,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,170,216,\n179,216,172,217,138,217,132,216,167,217,132,216,163,217,130,216,179,216,167,217,\n133,216,167,217,132,216,182,216,186,216,183,216,167,216,170,216,167,217,132,217,\n129,217,138,216,175,217,138,217,136,216,167,217,132,216,170,216,177,216,173,217,\n138,216,168,216,167,217,132,216,172,216,175,217,138,216,175,216,169,216,167,217,\n132,216,170,216,185,217,132,217,138,217,133,216,167,217,132,216,163,216,174,216,\n168,216,167,216,177,216,167,217,132,216,167,217,129,217,132,216,167,217,133,216,\n167,217,132,216,163,217,129,217,132,216,167,217,133,216,167,217,132,216,170,216,\n167,216,177,217,138,216,174,216,167,217,132,216,170,217,130,217,134,217,138,216,\n169,216,167,217,132,216,167,217,132,216,185,216,167,216,168,216,167,217,132,216,\n174,217,136,216,167,216,183,216,177,216,167,217,132,217,133,216,172,216,170,217,\n133,216,185,216,167,217,132,216,175,217,138,217,131,217,136,216,177,216,167,217,\n132,216,179,217,138,216,167,216,173,216,169,216,185,216,168,216,175,216,167,217,\n132,217,132,217,135,216,167,217,132,216,170,216,177,216,168,217,138,216,169,216,\n167,217,132,216,177,217,136,216,167,216,168,216,183,216,167,217,132,216,163,216,\n175,216,168,217,138,216,169,216,167,217,132,216,167,216,174,216,168,216,167,216,\n177,216,167,217,132,217,133,216,170,216,173,216,175,216,169,216,167,217,132,216,\n167,216,186,216,167,217,134,217,138,99,117,114,115,111,114,58,112,111,105,110,\n116,101,114,59,60,47,116,105,116,108,101,62,10,60,109,101,116,97,32,34,32,104,\n114,101,102,61,34,104,116,116,112,58,47,47,34,62,60,115,112,97,110,32,99,108,97,\n115,115,61,34,109,101,109,98,101,114,115,32,111,102,32,116,104,101,32,119,105,\n110,100,111,119,46,108,111,99,97,116,105,111,110,118,101,114,116,105,99,97,108,\n45,97,108,105,103,110,58,47,97,62,32,124,32,60,97,32,104,114,101,102,61,34,60,33\n,100,111,99,116,121,112,101,32,104,116,109,108,62,109,101,100,105,97,61,34,115,\n99,114,101,101,110,34,32,60,111,112,116,105,111,110,32,118,97,108,117,101,61,34,\n102,97,118,105,99,111,110,46,105,99,111,34,32,47,62,10,9,9,60,100,105,118,32,99,\n108,97,115,115,61,34,99,104,97,114,97,99,116,101,114,105,115,116,105,99,115,34,\n32,109,101,116,104,111,100,61,34,103,101,116,34,32,47,98,111,100,121,62,10,60,47\n,104,116,109,108,62,10,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,\n100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,112,97,100,100,105,110,\n103,45,98,111,116,116,111,109,58,114,101,112,114,101,115,101,110,116,97,116,105,\n118,101,115,115,117,98,109,105,116,34,32,118,97,108,117,101,61,34,97,108,105,103\n,110,61,34,99,101,110,116,101,114,34,32,116,104,114,111,117,103,104,111,117,116,\n32,116,104,101,32,115,99,105,101,110,99,101,32,102,105,99,116,105,111,110,10,32,\n32,60,100,105,118,32,99,108,97,115,115,61,34,115,117,98,109,105,116,34,32,99,108\n,97,115,115,61,34,111,110,101,32,111,102,32,116,104,101,32,109,111,115,116,32,\n118,97,108,105,103,110,61,34,116,111,112,34,62,60,119,97,115,32,101,115,116,97,\n98,108,105,115,104,101,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10,114\n,101,116,117,114,110,32,102,97,108,115,101,59,34,62,41,46,115,116,121,108,101,46\n,100,105,115,112,108,97,121,98,101,99,97,117,115,101,32,111,102,32,116,104,101,\n32,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,60,102,111,114,109,\n32,97,99,116,105,111,110,61,34,47,125,98,111,100,121,123,109,97,114,103,105,110,\n58,48,59,69,110,99,121,99,108,111,112,101,100,105,97,32,111,102,118,101,114,115,\n105,111,110,32,111,102,32,116,104,101,32,46,99,114,101,97,116,101,69,108,101,109\n,101,110,116,40,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,60,47,100,\n105,118,62,10,60,47,100,105,118,62,10,10,97,100,109,105,110,105,115,116,114,97,\n116,105,118,101,32,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,104,105,\n115,116,111,114,121,32,111,102,32,116,104,101,32,34,62,60,105,110,112,117,116,32\n,116,121,112,101,61,34,112,111,114,116,105,111,110,32,111,102,32,116,104,101,32,\n97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,38,110,98,115,112,59,60,97\n,32,104,114,101,102,61,34,111,116,104,101,114,32,99,111,117,110,116,114,105,101,\n115,34,62,10,60,100,105,118,32,99,108,97,115,115,61,34,60,47,115,112,97,110,62,\n60,47,115,112,97,110,62,60,73,110,32,111,116,104,101,114,32,119,111,114,100,115,\n44,100,105,115,112,108,97,121,58,32,98,108,111,99,107,59,99,111,110,116,114,111,\n108,32,111,102,32,116,104,101,32,105,110,116,114,111,100,117,99,116,105,111,110,\n32,111,102,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,97,115,32,119,101,\n108,108,32,97,115,32,116,104,101,32,105,110,32,114,101,99,101,110,116,32,121,101\n,97,114,115,13,10,9,60,100,105,118,32,99,108,97,115,115,61,34,60,47,100,105,118,\n62,10,9,60,47,100,105,118,62,10,105,110,115,112,105,114,101,100,32,98,121,32,116\n,104,101,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,99,111,109,112,\n97,116,105,98,108,101,32,119,105,116,104,98,101,99,97,109,101,32,107,110,111,119\n,110,32,97,115,32,115,116,121,108,101,61,34,109,97,114,103,105,110,58,46,106,115\n,34,62,60,47,115,99,114,105,112,116,62,60,32,73,110,116,101,114,110,97,116,105,\n111,110,97,108,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,71,101\n,114,109,97,110,32,108,97,110,103,117,97,103,101,32,115,116,121,108,101,61,34,99\n,111,108,111,114,58,35,67,111,109,109,117,110,105,115,116,32,80,97,114,116,121,\n99,111,110,115,105,115,116,101,110,116,32,119,105,116,104,98,111,114,100,101,114\n,61,34,48,34,32,99,101,108,108,32,109,97,114,103,105,110,104,101,105,103,104,116\n,61,34,116,104,101,32,109,97,106,111,114,105,116,121,32,111,102,34,32,97,108,105\n,103,110,61,34,99,101,110,116,101,114,114,101,108,97,116,101,100,32,116,111,32,\n116,104,101,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,79,114,\n116,104,111,100,111,120,32,67,104,117,114,99,104,115,105,109,105,108,97,114,32,\n116,111,32,116,104,101,32,47,62,10,60,108,105,110,107,32,114,101,108,61,34,115,\n119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,117,110,116,105,108,32,\n104,105,115,32,100,101,97,116,104,125,41,40,41,59,10,60,47,115,99,114,105,112,\n116,62,111,116,104,101,114,32,108,97,110,103,117,97,103,101,115,99,111,109,112,\n97,114,101,100,32,116,111,32,116,104,101,112,111,114,116,105,111,110,115,32,111,\n102,32,116,104,101,116,104,101,32,78,101,116,104,101,114,108,97,110,100,115,116,\n104,101,32,109,111,115,116,32,99,111,109,109,111,110,98,97,99,107,103,114,111,\n117,110,100,58,117,114,108,40,97,114,103,117,101,100,32,116,104,97,116,32,116,\n104,101,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,110,99,108,\n117,100,101,100,32,105,110,32,116,104,101,78,111,114,116,104,32,65,109,101,114,\n105,99,97,110,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,105,110\n,116,101,114,112,114,101,116,97,116,105,111,110,115,116,104,101,32,116,114,97,\n100,105,116,105,111,110,97,108,100,101,118,101,108,111,112,109,101,110,116,32,\n111,102,32,102,114,101,113,117,101,110,116,108,121,32,117,115,101,100,97,32,99,\n111,108,108,101,99,116,105,111,110,32,111,102,118,101,114,121,32,115,105,109,105\n,108,97,114,32,116,111,115,117,114,114,111,117,110,100,105,110,103,32,116,104,\n101,101,120,97,109,112,108,101,32,111,102,32,116,104,105,115,97,108,105,103,110,\n61,34,99,101,110,116,101,114,34,62,119,111,117,108,100,32,104,97,118,101,32,98,\n101,101,110,105,109,97,103,101,95,99,97,112,116,105,111,110,32,61,97,116,116,97,\n99,104,101,100,32,116,111,32,116,104,101,115,117,103,103,101,115,116,105,110,103\n,32,116,104,97,116,105,110,32,116,104,101,32,102,111,114,109,32,111,102,32,105,\n110,118,111,108,118,101,100,32,105,110,32,116,104,101,105,115,32,100,101,114,105\n,118,101,100,32,102,114,111,109,110,97,109,101,100,32,97,102,116,101,114,32,116,\n104,101,73,110,116,114,111,100,117,99,116,105,111,110,32,116,111,114,101,115,116\n,114,105,99,116,105,111,110,115,32,111,110,32,115,116,121,108,101,61,34,119,105,\n100,116,104,58,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,116,104,\n101,32,99,114,101,97,116,105,111,110,32,111,102,109,111,115,116,32,105,109,112,\n111,114,116,97,110,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,110,\n100,114,101,115,117,108,116,101,100,32,105,110,32,116,104,101,99,111,108,108,97,\n112,115,101,32,111,102,32,116,104,101,84,104,105,115,32,109,101,97,110,115,32,\n116,104,97,116,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,119,97,\n115,32,114,101,112,108,97,99,101,100,32,98,121,97,110,97,108,121,115,105,115,32,\n111,102,32,116,104,101,105,110,115,112,105,114,97,116,105,111,110,32,102,111,114\n,114,101,103,97,114,100,101,100,32,97,115,32,116,104,101,109,111,115,116,32,115,\n117,99,99,101,115,115,102,117,108,107,110,111,119,110,32,97,115,32,38,113,117,\n111,116,59,97,32,99,111,109,112,114,101,104,101,110,115,105,118,101,72,105,115,\n116,111,114,121,32,111,102,32,116,104,101,32,119,101,114,101,32,99,111,110,115,\n105,100,101,114,101,100,114,101,116,117,114,110,101,100,32,116,111,32,116,104,\n101,97,114,101,32,114,101,102,101,114,114,101,100,32,116,111,85,110,115,111,117,\n114,99,101,100,32,105,109,97,103,101,62,10,9,60,100,105,118,32,99,108,97,115,115\n,61,34,99,111,110,115,105,115,116,115,32,111,102,32,116,104,101,115,116,111,112,\n80,114,111,112,97,103,97,116,105,111,110,105,110,116,101,114,101,115,116,32,105,\n110,32,116,104,101,97,118,97,105,108,97,98,105,108,105,116,121,32,111,102,97,112\n,112,101,97,114,115,32,116,111,32,104,97,118,101,101,108,101,99,116,114,111,109,\n97,103,110,101,116,105,99,101,110,97,98,108,101,83,101,114,118,105,99,101,115,40\n,102,117,110,99,116,105,111,110,32,111,102,32,116,104,101,73,116,32,105,115,32,\n105,109,112,111,114,116,97,110,116,60,47,115,99,114,105,112,116,62,60,47,100,105\n,118,62,102,117,110,99,116,105,111,110,40,41,123,118,97,114,32,114,101,108,97,\n116,105,118,101,32,116,111,32,116,104,101,97,115,32,97,32,114,101,115,117,108,\n116,32,111,102,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,102,70,\n111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,109,101,116,104,111,100,\n61,34,112,111,115,116,34,32,119,97,115,32,102,111,108,108,111,119,101,100,32,98,\n121,38,97,109,112,59,109,100,97,115,104,59,32,116,104,101,116,104,101,32,97,112,\n112,108,105,99,97,116,105,111,110,106,115,34,62,60,47,115,99,114,105,112,116,62,\n13,10,117,108,62,60,47,100,105,118,62,60,47,100,105,118,62,97,102,116,101,114,32\n,116,104,101,32,100,101,97,116,104,119,105,116,104,32,114,101,115,112,101,99,116\n,32,116,111,115,116,121,108,101,61,34,112,97,100,100,105,110,103,58,105,115,32,\n112,97,114,116,105,99,117,108,97,114,108,121,100,105,115,112,108,97,121,58,105,\n110,108,105,110,101,59,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,105\n,115,32,100,105,118,105,100,101,100,32,105,110,116,111,228,184,173,230,150,135,\n32,40,231,174,128,228,189,147,41,114,101,115,112,111,110,115,97,98,105,108,105,\n100,97,100,97,100,109,105,110,105,115,116,114,97,99,105,195,179,110,105,110,116,\n101,114,110,97,99,105,111,110,97,108,101,115,99,111,114,114,101,115,112,111,110,\n100,105,101,110,116,101,224,164,137,224,164,170,224,164,175,224,165,139,224,164,\n151,224,164,170,224,165,130,224,164,176,224,165,141,224,164,181,224,164,185,224,\n164,174,224,164,190,224,164,176,224,165,135,224,164,178,224,165,139,224,164,151,\n224,165,139,224,164,130,224,164,154,224,165,129,224,164,168,224,164,190,224,164,\n181,224,164,178,224,165,135,224,164,149,224,164,191,224,164,168,224,164,184,224,\n164,176,224,164,149,224,164,190,224,164,176,224,164,170,224,165,129,224,164,178,\n224,164,191,224,164,184,224,164,150,224,165,139,224,164,156,224,165,135,224,164,\n130,224,164,154,224,164,190,224,164,185,224,164,191,224,164,143,224,164,173,224,\n165,135,224,164,156,224,165,135,224,164,130,224,164,182,224,164,190,224,164,174,\n224,164,191,224,164,178,224,164,185,224,164,174,224,164,190,224,164,176,224,165,\n128,224,164,156,224,164,190,224,164,151,224,164,176,224,164,163,224,164,172,224,\n164,168,224,164,190,224,164,168,224,165,135,224,164,149,224,165,129,224,164,174,\n224,164,190,224,164,176,224,164,172,224,165,141,224,164,178,224,165,137,224,164,\n151,224,164,174,224,164,190,224,164,178,224,164,191,224,164,149,224,164,174,224,\n164,185,224,164,191,224,164,178,224,164,190,224,164,170,224,165,131,224,164,183,\n224,165,141,224,164,160,224,164,172,224,164,162,224,164,188,224,164,164,224,165,\n135,224,164,173,224,164,190,224,164,156,224,164,170,224,164,190,224,164,149,224,\n165,141,224,164,178,224,164,191,224,164,149,224,164,159,224,165,141,224,164,176,\n224,165,135,224,164,168,224,164,150,224,164,191,224,164,178,224,164,190,224,164,\n171,224,164,166,224,165,140,224,164,176,224,164,190,224,164,168,224,164,174,224,\n164,190,224,164,174,224,164,178,224,165,135,224,164,174,224,164,164,224,164,166,\n224,164,190,224,164,168,224,164,172,224,164,190,224,164,156,224,164,190,224,164,\n176,224,164,181,224,164,191,224,164,149,224,164,190,224,164,184,224,164,149,224,\n165,141,224,164,175,224,165,139,224,164,130,224,164,154,224,164,190,224,164,185,\n224,164,164,224,165,135,224,164,170,224,164,185,224,165,129,224,164,129,224,164,\n154,224,164,172,224,164,164,224,164,190,224,164,175,224,164,190,224,164,184,224,\n164,130,224,164,181,224,164,190,224,164,166,224,164,166,224,165,135,224,164,150,\n224,164,168,224,165,135,224,164,170,224,164,191,224,164,155,224,164,178,224,165,\n135,224,164,181,224,164,191,224,164,182,224,165,135,224,164,183,224,164,176,224,\n164,190,224,164,156,224,165,141,224,164,175,224,164,137,224,164,164,224,165,141,\n224,164,164,224,164,176,224,164,174,224,165,129,224,164,130,224,164,172,224,164,\n136,224,164,166,224,165,139,224,164,168,224,165,139,224,164,130,224,164,137,224,\n164,170,224,164,149,224,164,176,224,164,163,224,164,170,224,164,162,224,164,188,\n224,165,135,224,164,130,224,164,184,224,165,141,224,164,165,224,164,191,224,164,\n164,224,164,171,224,164,191,224,164,178,224,165,141,224,164,174,224,164,174,224,\n165,129,224,164,150,224,165,141,224,164,175,224,164,133,224,164,154,224,165,141,\n224,164,155,224,164,190,224,164,155,224,165,130,224,164,159,224,164,164,224,165,\n128,224,164,184,224,164,130,224,164,151,224,165,128,224,164,164,224,164,156,224,\n164,190,224,164,143,224,164,151,224,164,190,224,164,181,224,164,191,224,164,173,\n224,164,190,224,164,151,224,164,152,224,164,163,224,165,141,224,164,159,224,165,\n135,224,164,166,224,165,130,224,164,184,224,164,176,224,165,135,224,164,166,224,\n164,191,224,164,168,224,165,139,224,164,130,224,164,185,224,164,164,224,165,141,\n224,164,175,224,164,190,224,164,184,224,165,135,224,164,149,224,165,141,224,164,\n184,224,164,151,224,164,190,224,164,130,224,164,167,224,165,128,224,164,181,224,\n164,191,224,164,182,224,165,141,224,164,181,224,164,176,224,164,190,224,164,164,\n224,165,135,224,164,130,224,164,166,224,165,136,224,164,159,224,165,141,224,164,\n184,224,164,168,224,164,149,224,165,141,224,164,182,224,164,190,224,164,184,224,\n164,190,224,164,174,224,164,168,224,165,135,224,164,133,224,164,166,224,164,190,\n224,164,178,224,164,164,224,164,172,224,164,191,224,164,156,224,164,178,224,165,\n128,224,164,170,224,165,129,224,164,176,224,165,130,224,164,183,224,164,185,224,\n164,191,224,164,130,224,164,166,224,165,128,224,164,174,224,164,191,224,164,164,\n224,165,141,224,164,176,224,164,149,224,164,181,224,164,191,224,164,164,224,164,\n190,224,164,176,224,165,129,224,164,170,224,164,175,224,165,135,224,164,184,224,\n165,141,224,164,165,224,164,190,224,164,168,224,164,149,224,164,176,224,165,139,\n224,164,161,224,164,188,224,164,174,224,165,129,224,164,149,224,165,141,224,164,\n164,224,164,175,224,165,139,224,164,156,224,164,168,224,164,190,224,164,149,224,\n165,131,224,164,170,224,164,175,224,164,190,224,164,170,224,165,139,224,164,184,\n224,165,141,224,164,159,224,164,152,224,164,176,224,165,135,224,164,178,224,165,\n130,224,164,149,224,164,190,224,164,176,224,165,141,224,164,175,224,164,181,224,\n164,191,224,164,154,224,164,190,224,164,176,224,164,184,224,165,130,224,164,154,\n224,164,168,224,164,190,224,164,174,224,165,130,224,164,178,224,165,141,224,164,\n175,224,164,166,224,165,135,224,164,150,224,165,135,224,164,130,224,164,185,224,\n164,174,224,165,135,224,164,182,224,164,190,224,164,184,224,165,141,224,164,149,\n224,165,130,224,164,178,224,164,174,224,165,136,224,164,130,224,164,168,224,165,\n135,224,164,164,224,165,136,224,164,175,224,164,190,224,164,176,224,164,156,224,\n164,191,224,164,184,224,164,149,224,165,135,114,115,115,43,120,109,108,34,32,116\n,105,116,108,101,61,34,45,116,121,112,101,34,32,99,111,110,116,101,110,116,61,34\n,116,105,116,108,101,34,32,99,111,110,116,101,110,116,61,34,97,116,32,116,104,\n101,32,115,97,109,101,32,116,105,109,101,46,106,115,34,62,60,47,115,99,114,105,\n112,116,62,10,60,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,32,60,47\n,115,112,97,110,62,60,47,97,62,60,47,108,105,62,118,101,114,116,105,99,97,108,45\n,97,108,105,103,110,58,116,47,106,113,117,101,114,121,46,109,105,110,46,106,115,\n34,62,46,99,108,105,99,107,40,102,117,110,99,116,105,111,110,40,32,115,116,121,\n108,101,61,34,112,97,100,100,105,110,103,45,125,41,40,41,59,10,60,47,115,99,114,\n105,112,116,62,10,60,47,115,112,97,110,62,60,97,32,104,114,101,102,61,34,60,97,\n32,104,114,101,102,61,34,104,116,116,112,58,47,47,41,59,32,114,101,116,117,114,\n110,32,102,97,108,115,101,59,116,101,120,116,45,100,101,99,111,114,97,116,105,\n111,110,58,32,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,98,111,114,\n100,101,114,45,99,111,108,108,97,112,115,101,58,97,115,115,111,99,105,97,116,101\n,100,32,119,105,116,104,32,66,97,104,97,115,97,32,73,110,100,111,110,101,115,105\n,97,69,110,103,108,105,115,104,32,108,97,110,103,117,97,103,101,60,116,101,120,\n116,32,120,109,108,58,115,112,97,99,101,61,46,103,105,102,34,32,98,111,114,100,\n101,114,61,34,48,34,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,10,111,\n118,101,114,102,108,111,119,58,104,105,100,100,101,110,59,105,109,103,32,115,114\n,99,61,34,104,116,116,112,58,47,47,97,100,100,69,118,101,110,116,76,105,115,116,\n101,110,101,114,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,115\n,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,47,102,97,118,105,99,111,\n110,46,105,99,111,34,32,47,62,111,112,101,114,97,116,105,110,103,32,115,121,115,\n116,101,109,34,32,115,116,121,108,101,61,34,119,105,100,116,104,58,49,116,97,114\n,103,101,116,61,34,95,98,108,97,110,107,34,62,83,116,97,116,101,32,85,110,105,\n118,101,114,115,105,116,121,116,101,120,116,45,97,108,105,103,110,58,108,101,102\n,116,59,10,100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,44,32,105,\n110,99,108,117,100,105,110,103,32,116,104,101,32,97,114,111,117,110,100,32,116,\n104,101,32,119,111,114,108,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10\n,60,34,32,115,116,121,108,101,61,34,104,101,105,103,104,116,58,59,111,118,101,\n114,102,108,111,119,58,104,105,100,100,101,110,109,111,114,101,32,105,110,102,\n111,114,109,97,116,105,111,110,97,110,32,105,110,116,101,114,110,97,116,105,111,\n110,97,108,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,111,110,101\n,32,111,102,32,116,104,101,32,102,105,114,115,116,99,97,110,32,98,101,32,102,111\n,117,110,100,32,105,110,32,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,\n100,105,115,112,108,97,121,58,32,110,111,110,101,59,34,62,34,32,47,62,10,60,108,\n105,110,107,32,114,101,108,61,34,10,32,32,40,102,117,110,99,116,105,111,110,40,\n41,32,123,116,104,101,32,49,53,116,104,32,99,101,110,116,117,114,121,46,112,114,\n101,118,101,110,116,68,101,102,97,117,108,116,40,108,97,114,103,101,32,110,117,\n109,98,101,114,32,111,102,32,66,121,122,97,110,116,105,110,101,32,69,109,112,105\n,114,101,46,106,112,103,124,116,104,117,109,98,124,108,101,102,116,124,118,97,\n115,116,32,109,97,106,111,114,105,116,121,32,111,102,109,97,106,111,114,105,116,\n121,32,111,102,32,116,104,101,32,32,97,108,105,103,110,61,34,99,101,110,116,101,\n114,34,62,85,110,105,118,101,114,115,105,116,121,32,80,114,101,115,115,100,111,\n109,105,110,97,116,101,100,32,98,121,32,116,104,101,83,101,99,111,110,100,32,87,\n111,114,108,100,32,87,97,114,100,105,115,116,114,105,98,117,116,105,111,110,32,\n111,102,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,116,104,\n101,32,114,101,115,116,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101,\n114,105,122,101,100,32,98,121,32,114,101,108,61,34,110,111,102,111,108,108,111,\n119,34,62,100,101,114,105,118,101,115,32,102,114,111,109,32,116,104,101,114,97,\n116,104,101,114,32,116,104,97,110,32,116,104,101,32,97,32,99,111,109,98,105,110,\n97,116,105,111,110,32,111,102,115,116,121,108,101,61,34,119,105,100,116,104,58,\n49,48,48,69,110,103,108,105,115,104,45,115,112,101,97,107,105,110,103,99,111,109\n,112,117,116,101,114,32,115,99,105,101,110,99,101,98,111,114,100,101,114,61,34,\n48,34,32,97,108,116,61,34,116,104,101,32,101,120,105,115,116,101,110,99,101,32,\n111,102,68,101,109,111,99,114,97,116,105,99,32,80,97,114,116,121,34,32,115,116,\n121,108,101,61,34,109,97,114,103,105,110,45,70,111,114,32,116,104,105,115,32,114\n,101,97,115,111,110,44,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,9,115\n,66,121,84,97,103,78,97,109,101,40,115,41,91,48,93,106,115,34,62,60,47,115,99,\n114,105,112,116,62,13,10,60,46,106,115,34,62,60,47,115,99,114,105,112,116,62,13,\n10,108,105,110,107,32,114,101,108,61,34,105,99,111,110,34,32,39,32,97,108,116,61\n,39,39,32,99,108,97,115,115,61,39,102,111,114,109,97,116,105,111,110,32,111,102,\n32,116,104,101,118,101,114,115,105,111,110,115,32,111,102,32,116,104,101,32,60,\n47,97,62,60,47,100,105,118,62,60,47,100,105,118,62,47,112,97,103,101,62,10,32,32\n,60,112,97,103,101,62,10,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,\n116,98,101,99,97,109,101,32,116,104,101,32,102,105,114,115,116,98,97,104,97,115,\n97,32,73,110,100,111,110,101,115,105,97,101,110,103,108,105,115,104,32,40,115,\n105,109,112,108,101,41,206,149,206,187,206,187,206,183,206,189,206,185,206,186,\n206,172,209,133,209,128,208,178,208,176,209,130,209,129,208,186,208,184,208,186,\n208,190,208,188,208,191,208,176,208,189,208,184,208,184,209,143,208,178,208,187,\n209,143,208,181,209,130,209,129,209,143,208,148,208,190,208,177,208,176,208,178,\n208,184,209,130,209,140,209,135,208,181,208,187,208,190,208,178,208,181,208,186,\n208,176,209,128,208,176,208,183,208,178,208,184,209,130,208,184,209,143,208,152,\n208,189,209,130,208,181,209,128,208,189,208,181,209,130,208,158,209,130,208,178,\n208,181,209,130,208,184,209,130,209,140,208,189,208,176,208,191,209,128,208,184,\n208,188,208,181,209,128,208,184,208,189,209,130,208,181,209,128,208,189,208,181,\n209,130,208,186,208,190,209,130,208,190,209,128,208,190,208,179,208,190,209,129,\n209,130,209,128,208,176,208,189,208,184,209,134,209,139,208,186,208,176,209,135,\n208,181,209,129,209,130,208,178,208,181,209,131,209,129,208,187,208,190,208,178,\n208,184,209,143,209,133,208,191,209,128,208,190,208,177,208,187,208,181,208,188,\n209,139,208,191,208,190,208,187,209,131,209,135,208,184,209,130,209,140,209,143,\n208,178,208,187,209,143,209,142,209,130,209,129,209,143,208,189,208,176,208,184,\n208,177,208,190,208,187,208,181,208,181,208,186,208,190,208,188,208,191,208,176,\n208,189,208,184,209,143,208,178,208,189,208,184,208,188,208,176,208,189,208,184,\n208,181,209,129,209,128,208,181,208,180,209,129,209,130,208,178,208,176,216,167,\n217,132,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,177,\n216,166,217,138,216,179,217,138,216,169,216,167,217,132,216,167,217,134,216,170,\n217,130,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216,167,216,170,\n217,131,216,167,217,132,216,179,217,138,216,167,216,177,216,167,216,170,216,167,\n217,132,217,133,217,131,216,170,217,136,216,168,216,169,216,167,217,132,216,179,\n216,185,217,136,216,175,217,138,216,169,216,167,216,173,216,181,216,167,216,166,\n217,138,216,167,216,170,216,167,217,132,216,185,216,167,217,132,217,133,217,138,\n216,169,216,167,217,132,216,181,217,136,216,170,217,138,216,167,216,170,216,167,\n217,132,216,167,217,134,216,170,216,177,217,134,216,170,216,167,217,132,216,170,\n216,181,216,167,217,133,217,138,217,133,216,167,217,132,216,165,216,179,217,132,\n216,167,217,133,217,138,216,167,217,132,217,133,216,180,216,167,216,177,217,131,\n216,169,216,167,217,132,217,133,216,177,216,166,217,138,216,167,216,170,114,111,\n98,111,116,115,34,32,99,111,110,116,101,110,116,61,34,60,100,105,118,32,105,100,\n61,34,102,111,111,116,101,114,34,62,116,104,101,32,85,110,105,116,101,100,32,83,\n116,97,116,101,115,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,\n46,106,112,103,124,114,105,103,104,116,124,116,104,117,109,98,124,46,106,115,34,\n62,60,47,115,99,114,105,112,116,62,13,10,60,108,111,99,97,116,105,111,110,46,112\n,114,111,116,111,99,111,108,102,114,97,109,101,98,111,114,100,101,114,61,34,48,\n34,32,115,34,32,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,60,47,97,62,\n60,47,100,105,118,62,60,47,100,105,118,62,60,102,111,110,116,45,119,101,105,103,\n104,116,58,98,111,108,100,59,38,113,117,111,116,59,32,97,110,100,32,38,113,117,\n111,116,59,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,109,\n97,114,103,105,110,58,48,59,112,97,100,100,105,110,103,58,34,32,114,101,108,61,\n34,110,111,102,111,108,108,111,119,34,32,80,114,101,115,105,100,101,110,116,32,\n111,102,32,116,104,101,32,116,119,101,110,116,105,101,116,104,32,99,101,110,116,\n117,114,121,101,118,105,115,105,111,110,62,10,32,32,60,47,112,97,103,101,73,110,\n116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,97,46,97,115,121,110,\n99,32,61,32,116,114,117,101,59,13,10,105,110,102,111,114,109,97,116,105,111,110,\n32,97,98,111,117,116,60,100,105,118,32,105,100,61,34,104,101,97,100,101,114,34,\n62,34,32,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,60,97,32,104,114,\n101,102,61,34,104,116,116,112,115,58,47,47,60,100,105,118,32,105,100,61,34,99,\n111,110,116,101,110,116,34,60,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10\n,60,100,101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32,60,105,109,\n103,32,115,114,99,61,39,104,116,116,112,58,47,47,97,99,99,111,114,100,105,110,\n103,32,116,111,32,116,104,101,32,10,60,47,98,111,100,121,62,10,60,47,104,116,109\n,108,62,10,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,115,\n99,114,105,112,116,32,108,97,110,103,117,97,103,101,61,34,65,114,105,97,108,44,\n32,72,101,108,118,101,116,105,99,97,44,60,47,97,62,60,115,112,97,110,32,99,108,\n97,115,115,61,34,60,47,115,99,114,105,112,116,62,60,115,99,114,105,112,116,32,\n112,111,108,105,116,105,99,97,108,32,112,97,114,116,105,101,115,116,100,62,60,47\n,116,114,62,60,47,116,97,98,108,101,62,60,104,114,101,102,61,34,104,116,116,112,\n58,47,47,119,119,119,46,105,110,116,101,114,112,114,101,116,97,116,105,111,110,\n32,111,102,114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,100,\n111,99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,99,104,97,114,115,101\n,116,61,34,117,116,102,45,56,34,62,10,98,101,103,105,110,110,105,110,103,32,111,\n102,32,116,104,101,32,114,101,118,101,97,108,101,100,32,116,104,97,116,32,116,\n104,101,116,101,108,101,118,105,115,105,111,110,32,115,101,114,105,101,115,34,32\n,114,101,108,61,34,110,111,102,111,108,108,111,119,34,62,32,116,97,114,103,101,\n116,61,34,95,98,108,97,110,107,34,62,99,108,97,105,109,105,110,103,32,116,104,97\n,116,32,116,104,101,104,116,116,112,37,51,65,37,50,70,37,50,70,119,119,119,46,\n109,97,110,105,102,101,115,116,97,116,105,111,110,115,32,111,102,80,114,105,109,\n101,32,77,105,110,105,115,116,101,114,32,111,102,105,110,102,108,117,101,110,99,\n101,100,32,98,121,32,116,104,101,99,108,97,115,115,61,34,99,108,101,97,114,102,\n105,120,34,62,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10,13,10,116,104,\n114,101,101,45,100,105,109,101,110,115,105,111,110,97,108,67,104,117,114,99,104,\n32,111,102,32,69,110,103,108,97,110,100,111,102,32,78,111,114,116,104,32,67,97,\n114,111,108,105,110,97,115,113,117,97,114,101,32,107,105,108,111,109,101,116,114\n,101,115,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,101,114,100,105\n,115,116,105,110,99,116,32,102,114,111,109,32,116,104,101,99,111,109,109,111,110\n,108,121,32,107,110,111,119,110,32,97,115,80,104,111,110,101,116,105,99,32,65,\n108,112,104,97,98,101,116,100,101,99,108,97,114,101,100,32,116,104,97,116,32,116\n,104,101,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,66,101,\n110,106,97,109,105,110,32,70,114,97,110,107,108,105,110,114,111,108,101,45,112,\n108,97,121,105,110,103,32,103,97,109,101,116,104,101,32,85,110,105,118,101,114,\n115,105,116,121,32,111,102,105,110,32,87,101,115,116,101,114,110,32,69,117,114,\n111,112,101,112,101,114,115,111,110,97,108,32,99,111,109,112,117,116,101,114,80,\n114,111,106,101,99,116,32,71,117,116,101,110,98,101,114,103,114,101,103,97,114,\n100,108,101,115,115,32,111,102,32,116,104,101,104,97,115,32,98,101,101,110,32,\n112,114,111,112,111,115,101,100,116,111,103,101,116,104,101,114,32,119,105,116,\n104,32,116,104,101,62,60,47,108,105,62,60,108,105,32,99,108,97,115,115,61,34,105\n,110,32,115,111,109,101,32,99,111,117,110,116,114,105,101,115,109,105,110,46,106\n,115,34,62,60,47,115,99,114,105,112,116,62,111,102,32,116,104,101,32,112,111,112\n,117,108,97,116,105,111,110,111,102,102,105,99,105,97,108,32,108,97,110,103,117,\n97,103,101,60,105,109,103,32,115,114,99,61,34,105,109,97,103,101,115,47,105,100,\n101,110,116,105,102,105,101,100,32,98,121,32,116,104,101,110,97,116,117,114,97,\n108,32,114,101,115,111,117,114,99,101,115,99,108,97,115,115,105,102,105,99,97,\n116,105,111,110,32,111,102,99,97,110,32,98,101,32,99,111,110,115,105,100,101,114\n,101,100,113,117,97,110,116,117,109,32,109,101,99,104,97,110,105,99,115,78,101,\n118,101,114,116,104,101,108,101,115,115,44,32,116,104,101,109,105,108,108,105,\n111,110,32,121,101,97,114,115,32,97,103,111,60,47,98,111,100,121,62,13,10,60,47,\n104,116,109,108,62,13,206,149,206,187,206,187,206,183,206,189,206,185,206,186,\n206,172,10,116,97,107,101,32,97,100,118,97,110,116,97,103,101,32,111,102,97,110,\n100,44,32,97,99,99,111,114,100,105,110,103,32,116,111,97,116,116,114,105,98,117,\n116,101,100,32,116,111,32,116,104,101,77,105,99,114,111,115,111,102,116,32,87,\n105,110,100,111,119,115,116,104,101,32,102,105,114,115,116,32,99,101,110,116,117\n,114,121,117,110,100,101,114,32,116,104,101,32,99,111,110,116,114,111,108,100,\n105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,115,104,111,114,116,\n108,121,32,97,102,116,101,114,32,116,104,101,110,111,116,97,98,108,101,32,101,\n120,99,101,112,116,105,111,110,116,101,110,115,32,111,102,32,116,104,111,117,115\n,97,110,100,115,115,101,118,101,114,97,108,32,100,105,102,102,101,114,101,110,\n116,97,114,111,117,110,100,32,116,104,101,32,119,111,114,108,100,46,114,101,97,\n99,104,105,110,103,32,109,105,108,105,116,97,114,121,105,115,111,108,97,116,101,\n100,32,102,114,111,109,32,116,104,101,111,112,112,111,115,105,116,105,111,110,32\n,116,111,32,116,104,101,116,104,101,32,79,108,100,32,84,101,115,116,97,109,101,\n110,116,65,102,114,105,99,97,110,32,65,109,101,114,105,99,97,110,115,105,110,115\n,101,114,116,101,100,32,105,110,116,111,32,116,104,101,115,101,112,97,114,97,116\n,101,32,102,114,111,109,32,116,104,101,109,101,116,114,111,112,111,108,105,116,\n97,110,32,97,114,101,97,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,\n108,101,97,99,107,110,111,119,108,101,100,103,101,100,32,116,104,97,116,97,114,\n103,117,97,98,108,121,32,116,104,101,32,109,111,115,116,116,121,112,101,61,34,\n116,101,120,116,47,99,115,115,34,62,10,116,104,101,32,73,110,116,101,114,110,97,\n116,105,111,110,97,108,65,99,99,111,114,100,105,110,103,32,116,111,32,116,104,\n101,32,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,99,111,105,110\n,99,105,100,101,32,119,105,116,104,32,116,104,101,116,119,111,45,116,104,105,114\n,100,115,32,111,102,32,116,104,101,68,117,114,105,110,103,32,116,104,105,115,32,\n116,105,109,101,44,100,117,114,105,110,103,32,116,104,101,32,112,101,114,105,111\n,100,97,110,110,111,117,110,99,101,100,32,116,104,97,116,32,104,101,116,104,101,\n32,105,110,116,101,114,110,97,116,105,111,110,97,108,97,110,100,32,109,111,114,\n101,32,114,101,99,101,110,116,108,121,98,101,108,105,101,118,101,100,32,116,104,\n97,116,32,116,104,101,99,111,110,115,99,105,111,117,115,110,101,115,115,32,97,\n110,100,102,111,114,109,101,114,108,121,32,107,110,111,119,110,32,97,115,115,117\n,114,114,111,117,110,100,101,100,32,98,121,32,116,104,101,102,105,114,115,116,32\n,97,112,112,101,97,114,101,100,32,105,110,111,99,99,97,115,105,111,110,97,108,\n108,121,32,117,115,101,100,112,111,115,105,116,105,111,110,58,97,98,115,111,108,\n117,116,101,59,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,112\n,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,116,101,120,\n116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,106,97,120,47,108,105,98,\n115,47,106,113,117,101,114,121,47,49,46,98,97,99,107,103,114,111,117,110,100,45,\n99,111,108,111,114,58,35,116,121,112,101,61,34,97,112,112,108,105,99,97,116,105,\n111,110,47,97,110,103,117,97,103,101,34,32,99,111,110,116,101,110,116,61,34,60,\n109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,80,114,105,118,97\n,99,121,32,80,111,108,105,99,121,60,47,97,62,101,40,34,37,51,67,115,99,114,105,\n112,116,32,115,114,99,61,39,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,\n107,34,62,79,110,32,116,104,101,32,111,116,104,101,114,32,104,97,110,100,44,46,\n106,112,103,124,116,104,117,109,98,124,114,105,103,104,116,124,50,60,47,100,105,\n118,62,60,100,105,118,32,99,108,97,115,115,61,34,60,100,105,118,32,115,116,121,\n108,101,61,34,102,108,111,97,116,58,110,105,110,101,116,101,101,110,116,104,32,\n99,101,110,116,117,114,121,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,\n62,13,10,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,115,59,116,\n101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,102,111,110,116,45,\n119,101,105,103,104,116,58,32,98,111,108,100,59,32,65,99,99,111,114,100,105,110,\n103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,\n101,116,119,101,101,110,34,32,102,114,97,109,101,98,111,114,100,101,114,61,34,48\n,34,32,34,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,108,\n105,110,107,32,104,114,101,102,61,34,104,116,116,112,58,47,47,104,116,109,108,52\n,47,108,111,111,115,101,46,100,116,100,34,62,10,100,117,114,105,110,103,32,116,\n104,105,115,32,112,101,114,105,111,100,60,47,116,100,62,60,47,116,114,62,60,47,\n116,97,98,108,101,62,99,108,111,115,101,108,121,32,114,101,108,97,116,101,100,32\n,116,111,102,111,114,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,59\n,102,111,110,116,45,119,101,105,103,104,116,58,98,111,108,100,59,105,110,112,117\n,116,32,116,121,112,101,61,34,116,101,120,116,34,32,60,115,112,97,110,32,115,116\n,121,108,101,61,34,102,111,110,116,45,111,110,114,101,97,100,121,115,116,97,116,\n101,99,104,97,110,103,101,9,60,100,105,118,32,99,108,97,115,115,61,34,99,108,101\n,97,114,100,111,99,117,109,101,110,116,46,108,111,99,97,116,105,111,110,46,32,70\n,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,97,32,119,105,100,\n101,32,118,97,114,105,101,116,121,32,111,102,32,60,33,68,79,67,84,89,80,69,32,\n104,116,109,108,62,13,10,60,38,110,98,115,112,59,38,110,98,115,112,59,38,110,98,\n115,112,59,34,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,115,116\n,121,108,101,61,34,102,108,111,97,116,58,108,101,102,116,59,99,111,110,99,101,\n114,110,101,100,32,119,105,116,104,32,116,104,101,61,104,116,116,112,37,51,65,37\n,50,70,37,50,70,119,119,119,46,105,110,32,112,111,112,117,108,97,114,32,99,117,\n108,116,117,114,101,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47\n,62,105,116,32,105,115,32,112,111,115,115,105,98,108,101,32,116,111,32,72,97,114\n,118,97,114,100,32,85,110,105,118,101,114,115,105,116,121,116,121,108,101,115,\n104,101,101,116,34,32,104,114,101,102,61,34,47,116,104,101,32,109,97,105,110,32,\n99,104,97,114,97,99,116,101,114,79,120,102,111,114,100,32,85,110,105,118,101,114\n,115,105,116,121,32,32,110,97,109,101,61,34,107,101,121,119,111,114,100,115,34,\n32,99,115,116,121,108,101,61,34,116,101,120,116,45,97,108,105,103,110,58,116,104\n,101,32,85,110,105,116,101,100,32,75,105,110,103,100,111,109,102,101,100,101,114\n,97,108,32,103,111,118,101,114,110,109,101,110,116,60,100,105,118,32,115,116,121\n,108,101,61,34,109,97,114,103,105,110,32,100,101,112,101,110,100,105,110,103,32,\n111,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,\n32,116,104,101,60,100,105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,\n46,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,100,101,115,116,\n114,117,99,116,105,111,110,32,111,102,32,116,104,101,115,108,105,103,104,116,108\n,121,32,100,105,102,102,101,114,101,110,116,105,110,32,97,99,99,111,114,100,97,\n110,99,101,32,119,105,116,104,116,101,108,101,99,111,109,109,117,110,105,99,97,\n116,105,111,110,115,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32,116,\n104,101,115,104,111,114,116,108,121,32,116,104,101,114,101,97,102,116,101,114,\n101,115,112,101,99,105,97,108,108,121,32,105,110,32,116,104,101,32,69,117,114,\n111,112,101,97,110,32,99,111,117,110,116,114,105,101,115,72,111,119,101,118,101,\n114,44,32,116,104,101,114,101,32,97,114,101,115,114,99,61,34,104,116,116,112,58,\n47,47,115,116,97,116,105,99,115,117,103,103,101,115,116,101,100,32,116,104,97,\n116,32,116,104,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,\n46,97,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,84,101,108,\n101,99,111,109,109,117,110,105,99,97,116,105,111,110,115,34,32,114,101,108,61,34\n,110,111,102,111,108,108,111,119,34,32,116,72,111,108,121,32,82,111,109,97,110,\n32,69,109,112,101,114,111,114,97,108,109,111,115,116,32,101,120,99,108,117,115,\n105,118,101,108,121,34,32,98,111,114,100,101,114,61,34,48,34,32,97,108,116,61,34\n,83,101,99,114,101,116,97,114,121,32,111,102,32,83,116,97,116,101,99,117,108,109\n,105,110,97,116,105,110,103,32,105,110,32,116,104,101,67,73,65,32,87,111,114,108\n,100,32,70,97,99,116,98,111,111,107,116,104,101,32,109,111,115,116,32,105,109,\n112,111,114,116,97,110,116,97,110,110,105,118,101,114,115,97,114,121,32,111,102,\n32,116,104,101,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45\n,60,108,105,62,60,101,109,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,65\n,116,108,97,110,116,105,99,32,79,99,101,97,110,115,116,114,105,99,116,108,121,32\n,115,112,101,97,107,105,110,103,44,115,104,111,114,116,108,121,32,98,101,102,111\n,114,101,32,116,104,101,100,105,102,102,101,114,101,110,116,32,116,121,112,101,\n115,32,111,102,116,104,101,32,79,116,116,111,109,97,110,32,69,109,112,105,114,\n101,62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,65,110,32,73,\n110,116,114,111,100,117,99,116,105,111,110,32,116,111,99,111,110,115,101,113,117\n,101,110,99,101,32,111,102,32,116,104,101,100,101,112,97,114,116,117,114,101,32,\n102,114,111,109,32,116,104,101,67,111,110,102,101,100,101,114,97,116,101,32,83,\n116,97,116,101,115,105,110,100,105,103,101,110,111,117,115,32,112,101,111,112,\n108,101,115,80,114,111,99,101,101,100,105,110,103,115,32,111,102,32,116,104,101,\n105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,104,101,116,104,101\n,111,114,105,101,115,32,104,97,118,101,32,98,101,101,110,105,110,118,111,108,118\n,101,109,101,110,116,32,105,110,32,116,104,101,100,105,118,105,100,101,100,32,\n105,110,116,111,32,116,104,114,101,101,97,100,106,97,99,101,110,116,32,99,111,\n117,110,116,114,105,101,115,105,115,32,114,101,115,112,111,110,115,105,98,108,\n101,32,102,111,114,100,105,115,115,111,108,117,116,105,111,110,32,111,102,32,116\n,104,101,99,111,108,108,97,98,111,114,97,116,105,111,110,32,119,105,116,104,119,\n105,100,101,108,121,32,114,101,103,97,114,100,101,100,32,97,115,104,105,115,32,\n99,111,110,116,101,109,112,111,114,97,114,105,101,115,102,111,117,110,100,105,\n110,103,32,109,101,109,98,101,114,32,111,102,68,111,109,105,110,105,99,97,110,32\n,82,101,112,117,98,108,105,99,103,101,110,101,114,97,108,108,121,32,97,99,99,101\n,112,116,101,100,116,104,101,32,112,111,115,115,105,98,105,108,105,116,121,32,\n111,102,97,114,101,32,97,108,115,111,32,97,118,97,105,108,97,98,108,101,117,110,\n100,101,114,32,99,111,110,115,116,114,117,99,116,105,111,110,114,101,115,116,111\n,114,97,116,105,111,110,32,111,102,32,116,104,101,116,104,101,32,103,101,110,101\n,114,97,108,32,112,117,98,108,105,99,105,115,32,97,108,109,111,115,116,32,101,\n110,116,105,114,101,108,121,112,97,115,115,101,115,32,116,104,114,111,117,103,\n104,32,116,104,101,104,97,115,32,98,101,101,110,32,115,117,103,103,101,115,116,\n101,100,99,111,109,112,117,116,101,114,32,97,110,100,32,118,105,100,101,111,71,\n101,114,109,97,110,105,99,32,108,97,110,103,117,97,103,101,115,32,97,99,99,111,\n114,100,105,110,103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110\n,116,32,102,114,111,109,32,116,104,101,115,104,111,114,116,108,121,32,97,102,116\n,101,114,119,97,114,100,115,104,114,101,102,61,34,104,116,116,112,115,58,47,47,\n119,119,119,46,114,101,99,101,110,116,32,100,101,118,101,108,111,112,109,101,110\n,116,66,111,97,114,100,32,111,102,32,68,105,114,101,99,116,111,114,115,60,100,\n105,118,32,99,108,97,115,115,61,34,115,101,97,114,99,104,124,32,60,97,32,104,114\n,101,102,61,34,104,116,116,112,58,47,47,73,110,32,112,97,114,116,105,99,117,108,\n97,114,44,32,116,104,101,77,117,108,116,105,112,108,101,32,102,111,111,116,110,\n111,116,101,115,111,114,32,111,116,104,101,114,32,115,117,98,115,116,97,110,99,\n101,116,104,111,117,115,97,110,100,115,32,111,102,32,121,101,97,114,115,116,114,\n97,110,115,108,97,116,105,111,110,32,111,102,32,116,104,101,60,47,100,105,118,62\n,13,10,60,47,100,105,118,62,13,10,13,10,60,97,32,104,114,101,102,61,34,105,110,\n100,101,120,46,112,104,112,119,97,115,32,101,115,116,97,98,108,105,115,104,101,\n100,32,105,110,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,\n112,97,114,116,105,99,105,112,97,116,101,32,105,110,32,116,104,101,97,32,115,116\n,114,111,110,103,32,105,110,102,108,117,101,110,99,101,115,116,121,108,101,61,34\n,109,97,114,103,105,110,45,116,111,112,58,114,101,112,114,101,115,101,110,116,\n101,100,32,98,121,32,116,104,101,103,114,97,100,117,97,116,101,100,32,102,114,\n111,109,32,116,104,101,84,114,97,100,105,116,105,111,110,97,108,108,121,44,32,\n116,104,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,72,\n111,119,101,118,101,114,44,32,115,105,110,99,101,32,116,104,101,47,100,105,118,\n62,10,60,47,100,105,118,62,10,60,100,105,118,32,108,101,102,116,59,32,109,97,114\n,103,105,110,45,108,101,102,116,58,112,114,111,116,101,99,116,105,111,110,32,97,\n103,97,105,110,115,116,48,59,32,118,101,114,116,105,99,97,108,45,97,108,105,103,\n110,58,85,110,102,111,114,116,117,110,97,116,101,108,121,44,32,116,104,101,116,\n121,112,101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,47,100,105,118,62,\n10,60,100,105,118,32,99,108,97,115,115,61,34,32,99,108,97,115,115,61,34,99,108,\n101,97,114,102,105,120,34,62,60,100,105,118,32,99,108,97,115,115,61,34,102,111,\n111,116,101,114,9,9,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,116,104,\n101,32,109,111,116,105,111,110,32,112,105,99,116,117,114,101,208,145,209,138,208\n,187,208,179,208,176,209,128,209,129,208,186,208,184,208,177,209,138,208,187,208\n,179,208,176,209,128,209,129,208,186,208,184,208,164,208,181,208,180,208,181,209\n,128,208,176,209,134,208,184,208,184,208,189,208,181,209,129,208,186,208,190,208\n,187,209,140,208,186,208,190,209,129,208,190,208,190,208,177,209,137,208,181,208\n,189,208,184,208,181,209,129,208,190,208,190,208,177,209,137,208,181,208,189,208\n,184,209,143,208,191,209,128,208,190,208,179,209,128,208,176,208,188,208,188,209\n,139,208,158,209,130,208,191,209,128,208,176,208,178,208,184,209,130,209,140,208\n,177,208,181,209,129,208,191,208,187,208,176,209,130,208,189,208,190,208,188,208\n,176,209,130,208,181,209,128,208,184,208,176,208,187,209,139,208,191,208,190,208\n,183,208,178,208,190,208,187,209,143,208,181,209,130,208,191,208,190,209,129,208\n,187,208,181,208,180,208,189,208,184,208,181,209,128,208,176,208,183,208,187,208\n,184,209,135,208,189,209,139,209,133,208,191,209,128,208,190,208,180,209,131,208\n,186,209,134,208,184,208,184,208,191,209,128,208,190,208,179,209,128,208,176,208\n,188,208,188,208,176,208,191,208,190,208,187,208,189,208,190,209,129,209,130,209\n,140,209,142,208,189,208,176,209,133,208,190,208,180,208,184,209,130,209,129,209\n,143,208,184,208,183,208,177,209,128,208,176,208,189,208,189,208,190,208,181,208\n,189,208,176,209,129,208,181,208,187,208,181,208,189,208,184,209,143,208,184,208\n,183,208,188,208,181,208,189,208,181,208,189,208,184,209,143,208,186,208,176,209\n,130,208,181,208,179,208,190,209,128,208,184,208,184,208,144,208,187,208,181,208\n,186,209,129,208,176,208,189,208,180,209,128,224,164,166,224,165,141,224,164,181\n,224,164,190,224,164,176,224,164,190,224,164,174,224,165,136,224,164,168,224,165\n,129,224,164,133,224,164,178,224,164,170,224,165,141,224,164,176,224,164,166,224\n,164,190,224,164,168,224,164,173,224,164,190,224,164,176,224,164,164,224,165,128\n,224,164,175,224,164,133,224,164,168,224,165,129,224,164,166,224,165,135,224,164\n,182,224,164,185,224,164,191,224,164,168,224,165,141,224,164,166,224,165,128,224\n,164,135,224,164,130,224,164,161,224,164,191,224,164,175,224,164,190,224,164,166\n,224,164,191,224,164,178,224,165,141,224,164,178,224,165,128,224,164,133,224,164\n,167,224,164,191,224,164,149,224,164,190,224,164,176,224,164,181,224,165,128,224\n,164,161,224,164,191,224,164,175,224,165,139,224,164,154,224,164,191,224,164,159\n,224,165,141,224,164,160,224,165,135,224,164,184,224,164,174,224,164,190,224,164\n,154,224,164,190,224,164,176,224,164,156,224,164,130,224,164,149,224,165,141,224\n,164,182,224,164,168,224,164,166,224,165,129,224,164,168,224,164,191,224,164,175\n,224,164,190,224,164,170,224,165,141,224,164,176,224,164,175,224,165,139,224,164\n,151,224,164,133,224,164,168,224,165,129,224,164,184,224,164,190,224,164,176,224\n,164,145,224,164,168,224,164,178,224,164,190,224,164,135,224,164,168,224,164,170\n,224,164,190,224,164,176,224,165,141,224,164,159,224,165,128,224,164,182,224,164\n,176,224,165,141,224,164,164,224,165,139,224,164,130,224,164,178,224,165,139,224\n,164,149,224,164,184,224,164,173,224,164,190,224,164,171,224,164,188,224,165,141\n,224,164,178,224,165,136,224,164,182,224,164,182,224,164,176,224,165,141,224,164\n,164,224,165,135,224,164,130,224,164,170,224,165,141,224,164,176,224,164,166,224\n,165,135,224,164,182,224,164,170,224,165,141,224,164,178,224,165,135,224,164,175\n,224,164,176,224,164,149,224,165,135,224,164,130,224,164,166,224,165,141,224,164\n,176,224,164,184,224,165,141,224,164,165,224,164,191,224,164,164,224,164,191,224\n,164,137,224,164,164,224,165,141,224,164,170,224,164,190,224,164,166,224,164,137\n,224,164,168,224,165,141,224,164,185,224,165,135,224,164,130,224,164,154,224,164\n,191,224,164,159,224,165,141,224,164,160,224,164,190,224,164,175,224,164,190,224\n,164,164,224,165,141,224,164,176,224,164,190,224,164,156,224,165,141,224,164,175\n,224,164,190,224,164,166,224,164,190,224,164,170,224,165,129,224,164,176,224,164\n,190,224,164,168,224,165,135,224,164,156,224,165,139,224,164,161,224,164,188,224\n,165,135,224,164,130,224,164,133,224,164,168,224,165,129,224,164,181,224,164,190\n,224,164,166,224,164,182,224,165,141,224,164,176,224,165,135,224,164,163,224,165\n,128,224,164,182,224,164,191,224,164,149,224,165,141,224,164,183,224,164,190,224\n,164,184,224,164,176,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184\n,224,164,130,224,164,151,224,165,141,224,164,176,224,164,185,224,164,170,224,164\n,176,224,164,191,224,164,163,224,164,190,224,164,174,224,164,172,224,165,141,224\n,164,176,224,164,190,224,164,130,224,164,161,224,164,172,224,164,154,224,165,141\n,224,164,154,224,165,139,224,164,130,224,164,137,224,164,170,224,164,178,224,164\n,172,224,165,141,224,164,167,224,164,174,224,164,130,224,164,164,224,165,141,224\n,164,176,224,165,128,224,164,184,224,164,130,224,164,170,224,164,176,224,165,141\n,224,164,149,224,164,137,224,164,174,224,165,141,224,164,174,224,165,128,224,164\n,166,224,164,174,224,164,190,224,164,167,224,165,141,224,164,175,224,164,174,224\n,164,184,224,164,185,224,164,190,224,164,175,224,164,164,224,164,190,224,164,182\n,224,164,172,224,165,141,224,164,166,224,165,139,224,164,130,224,164,174,224,165\n,128,224,164,161,224,164,191,224,164,175,224,164,190,224,164,134,224,164,136,224\n,164,170,224,165,128,224,164,143,224,164,178,224,164,174,224,165,139,224,164,172\n,224,164,190,224,164,135,224,164,178,224,164,184,224,164,130,224,164,150,224,165\n,141,224,164,175,224,164,190,224,164,134,224,164,170,224,164,176,224,165,135,224\n,164,182,224,164,168,224,164,133,224,164,168,224,165,129,224,164,172,224,164,130\n,224,164,167,224,164,172,224,164,190,224,164,156,224,164,188,224,164,190,224,164\n,176,224,164,168,224,164,181,224,165,128,224,164,168,224,164,164,224,164,174,224\n,164,170,224,165,141,224,164,176,224,164,174,224,165,129,224,164,150,224,164,170\n,224,165,141,224,164,176,224,164,182,224,165,141,224,164,168,224,164,170,224,164\n,176,224,164,191,224,164,181,224,164,190,224,164,176,224,164,168,224,165,129,224\n,164,149,224,164,184,224,164,190,224,164,168,224,164,184,224,164,174,224,164,176\n,224,165,141,224,164,165,224,164,168,224,164,134,224,164,175,224,165,139,224,164\n,156,224,164,191,224,164,164,224,164,184,224,165,139,224,164,174,224,164,181,224\n,164,190,224,164,176,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216\n,167,216,170,216,167,217,132,217,133,217,134,216,170,216,175,217,138,216,167,216\n,170,216,167,217,132,217,131,217,133,216,168,217,138,217,136,216,170,216,177,216\n,167,217,132,217,133,216,180,216,167,217,135,216,175,216,167,216,170,216,185,216\n,175,216,175,216,167,217,132,216,178,217,136,216,167,216,177,216,185,216,175,216\n,175,216,167,217,132,216,177,216,175,217,136,216,175,216,167,217,132,216,165,216\n,179,217,132,216,167,217,133,217,138,216,169,216,167,217,132,217,129,217,136,216\n,170,217,136,216,180,217,136,216,168,216,167,217,132,217,133,216,179,216,167,216\n,168,217,130,216,167,216,170,216,167,217,132,217,133,216,185,217,132,217,136,217\n,133,216,167,216,170,216,167,217,132,217,133,216,179,217,132,216,179,217,132,216\n,167,216,170,216,167,217,132,216,172,216,177,216,167,217,129,217,138,217,131,216\n,179,216,167,217,132,216,167,216,179,217,132,216,167,217,133,217,138,216,169,216\n,167,217,132,216,167,216,170,216,181,216,167,217,132,216,167,216,170,107,101,121\n,119,111,114,100,115,34,32,99,111,110,116,101,110,116,61,34,119,51,46,111,114,\n103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,97,32,116,97,114,103,101,116,\n61,34,95,98,108,97,110,107,34,32,116,101,120,116,47,104,116,109,108,59,32,99,104\n,97,114,115,101,116,61,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,\n34,62,60,116,97,98,108,101,32,99,101,108,108,112,97,100,100,105,110,103,61,34,97\n,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,116,101,120,\n116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,116,111,32,108,97,115,\n116,32,118,101,114,115,105,111,110,32,98,121,32,98,97,99,107,103,114,111,117,110\n,100,45,99,111,108,111,114,58,32,35,34,32,104,114,101,102,61,34,104,116,116,112,\n58,47,47,119,119,119,46,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,32\n,105,100,61,60,97,32,104,114,101,102,61,34,35,34,32,99,108,97,115,115,61,34,34,\n62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,99,114,105,112,\n116,34,32,115,114,99,61,34,104,116,116,112,58,47,47,10,60,115,99,114,105,112,116\n,32,108,97,110,103,117,97,103,101,61,34,47,47,69,78,34,32,34,104,116,116,112,58,\n47,47,119,119,119,46,119,101,110,99,111,100,101,85,82,73,67,111,109,112,111,110,\n101,110,116,40,34,32,104,114,101,102,61,34,106,97,118,97,115,99,114,105,112,116,\n58,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,116,101,110,116,100,111,\n99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,115,99,112,111,115,105,\n116,105,111,110,58,32,97,98,115,111,108,117,116,101,59,115,99,114,105,112,116,32\n,115,114,99,61,34,104,116,116,112,58,47,47,32,115,116,121,108,101,61,34,109,97,\n114,103,105,110,45,116,111,112,58,46,109,105,110,46,106,115,34,62,60,47,115,99,\n114,105,112,116,62,10,60,47,100,105,118,62,10,60,100,105,118,32,99,108,97,115,\n115,61,34,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,32,10,\n13,10,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,62,100,105,115,116,105\n,110,99,116,105,111,110,32,98,101,116,119,101,101,110,47,34,32,116,97,114,103,\n101,116,61,34,95,98,108,97,110,107,34,62,60,108,105,110,107,32,104,114,101,102,\n61,34,104,116,116,112,58,47,47,101,110,99,111,100,105,110,103,61,34,117,116,102,\n45,56,34,63,62,10,119,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,\n101,114,63,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,119,119,119,46,\n105,99,111,110,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,32,115,116,\n121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,58,116,121,112,101,61,34,\n116,101,120,116,47,99,115,115,34,32,47,62,10,109,101,116,97,32,112,114,111,112,\n101,114,116,121,61,34,111,103,58,116,60,105,110,112,117,116,32,116,121,112,101,\n61,34,116,101,120,116,34,32,32,115,116,121,108,101,61,34,116,101,120,116,45,97,\n108,105,103,110,58,116,104,101,32,100,101,118,101,108,111,112,109,101,110,116,32\n,111,102,32,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116,\n101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,105,115\n,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,116,97,98,108,\n101,32,119,105,100,116,104,61,34,49,48,48,37,34,32,73,110,32,97,100,100,105,116,\n105,111,110,32,116,111,32,116,104,101,32,99,111,110,116,114,105,98,117,116,101,\n100,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,115,32,\n98,101,116,119,101,101,110,100,101,118,101,108,111,112,109,101,110,116,32,111,\n102,32,116,104,101,32,73,116,32,105,115,32,105,109,112,111,114,116,97,110,116,32\n,116,111,32,60,47,115,99,114,105,112,116,62,10,10,60,115,99,114,105,112,116,32,\n32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,62,60,47,\n115,112,97,110,62,60,115,112,97,110,32,105,100,61,103,98,76,105,98,114,97,114,\n121,32,111,102,32,67,111,110,103,114,101,115,115,60,105,109,103,32,115,114,99,61\n,34,104,116,116,112,58,47,47,105,109,69,110,103,108,105,115,104,32,116,114,97,\n110,115,108,97,116,105,111,110,65,99,97,100,101,109,121,32,111,102,32,83,99,105,\n101,110,99,101,115,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,\n97,121,58,99,111,110,115,116,114,117,99,116,105,111,110,32,111,102,32,116,104,\n101,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,105,100,41,105,\n110,32,99,111,110,106,117,110,99,116,105,111,110,32,119,105,116,104,69,108,101,\n109,101,110,116,40,39,115,99,114,105,112,116,39,41,59,32,60,109,101,116,97,32,\n112,114,111,112,101,114,116,121,61,34,111,103,58,208,145,209,138,208,187,208,179\n,208,176,209,128,209,129,208,186,208,184,10,32,116,121,112,101,61,34,116,101,120\n,116,34,32,110,97,109,101,61,34,62,80,114,105,118,97,99,121,32,80,111,108,105,99\n,121,60,47,97,62,97,100,109,105,110,105,115,116,101,114,101,100,32,98,121,32,116\n,104,101,101,110,97,98,108,101,83,105,110,103,108,101,82,101,113,117,101,115,116\n,115,116,121,108,101,61,38,113,117,111,116,59,109,97,114,103,105,110,58,60,47,\n100,105,118,62,60,47,100,105,118,62,60,47,100,105,118,62,60,62,60,105,109,103,32\n,115,114,99,61,34,104,116,116,112,58,47,47,105,32,115,116,121,108,101,61,38,113,\n117,111,116,59,102,108,111,97,116,58,114,101,102,101,114,114,101,100,32,116,111,\n32,97,115,32,116,104,101,32,116,111,116,97,108,32,112,111,112,117,108,97,116,105\n,111,110,32,111,102,105,110,32,87,97,115,104,105,110,103,116,111,110,44,32,68,46\n,67,46,32,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45,97,\n109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,44,111,114,103\n,97,110,105,122,97,116,105,111,110,32,111,102,32,116,104,101,112,97,114,116,105,\n99,105,112,97,116,101,100,32,105,110,32,116,104,101,116,104,101,32,105,110,116,\n114,111,100,117,99,116,105,111,110,32,111,102,105,100,101,110,116,105,102,105,\n101,100,32,119,105,116,104,32,116,104,101,102,105,99,116,105,111,110,97,108,32,\n99,104,97,114,97,99,116,101,114,32,79,120,102,111,114,100,32,85,110,105,118,101,\n114,115,105,116,121,32,109,105,115,117,110,100,101,114,115,116,97,110,100,105,\n110,103,32,111,102,84,104,101,114,101,32,97,114,101,44,32,104,111,119,101,118,\n101,114,44,115,116,121,108,101,115,104,101,101,116,34,32,104,114,101,102,61,34,\n47,67,111,108,117,109,98,105,97,32,85,110,105,118,101,114,115,105,116,121,101,\n120,112,97,110,100,101,100,32,116,111,32,105,110,99,108,117,100,101,117,115,117,\n97,108,108,121,32,114,101,102,101,114,114,101,100,32,116,111,105,110,100,105,99,\n97,116,105,110,103,32,116,104,97,116,32,116,104,101,104,97,118,101,32,115,117,\n103,103,101,115,116,101,100,32,116,104,97,116,97,102,102,105,108,105,97,116,101,\n100,32,119,105,116,104,32,116,104,101,99,111,114,114,101,108,97,116,105,111,110,\n32,98,101,116,119,101,101,110,110,117,109,98,101,114,32,111,102,32,100,105,102,\n102,101,114,101,110,116,62,60,47,116,100,62,60,47,116,114,62,60,47,116,97,98,108\n,101,62,82,101,112,117,98,108,105,99,32,111,102,32,73,114,101,108,97,110,100,10,\n60,47,115,99,114,105,112,116,62,10,60,115,99,114,105,112,116,32,117,110,100,101,\n114,32,116,104,101,32,105,110,102,108,117,101,110,99,101,99,111,110,116,114,105,\n98,117,116,105,111,110,32,116,111,32,116,104,101,79,102,102,105,99,105,97,108,32\n,119,101,98,115,105,116,101,32,111,102,104,101,97,100,113,117,97,114,116,101,114\n,115,32,111,102,32,116,104,101,99,101,110,116,101,114,101,100,32,97,114,111,117,\n110,100,32,116,104,101,105,109,112,108,105,99,97,116,105,111,110,115,32,111,102,\n32,116,104,101,104,97,118,101,32,98,101,101,110,32,100,101,118,101,108,111,112,\n101,100,70,101,100,101,114,97,108,32,82,101,112,117,98,108,105,99,32,111,102,98,\n101,99,97,109,101,32,105,110,99,114,101,97,115,105,110,103,108,121,99,111,110,\n116,105,110,117,97,116,105,111,110,32,111,102,32,116,104,101,78,111,116,101,44,\n32,104,111,119,101,118,101,114,44,32,116,104,97,116,115,105,109,105,108,97,114,\n32,116,111,32,116,104,97,116,32,111,102,32,99,97,112,97,98,105,108,105,116,105,\n101,115,32,111,102,32,116,104,101,97,99,99,111,114,100,97,110,99,101,32,119,105,\n116,104,32,116,104,101,112,97,114,116,105,99,105,112,97,110,116,115,32,105,110,\n32,116,104,101,102,117,114,116,104,101,114,32,100,101,118,101,108,111,112,109,\n101,110,116,117,110,100,101,114,32,116,104,101,32,100,105,114,101,99,116,105,111\n,110,105,115,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,101,100,\n104,105,115,32,121,111,117,110,103,101,114,32,98,114,111,116,104,101,114,60,47,\n116,100,62,60,47,116,114,62,60,47,116,97,98,108,101,62,60,97,32,104,116,116,112,\n45,101,113,117,105,118,61,34,88,45,85,65,45,112,104,121,115,105,99,97,108,32,112\n,114,111,112,101,114,116,105,101,115,111,102,32,66,114,105,116,105,115,104,32,67\n,111,108,117,109,98,105,97,104,97,115,32,98,101,101,110,32,99,114,105,116,105,99\n,105,122,101,100,40,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105\n,111,110,113,117,101,115,116,105,111,110,115,32,97,98,111,117,116,32,116,104,101\n,112,97,115,115,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,48,34,\n32,99,101,108,108,112,97,100,100,105,110,103,61,34,48,34,32,116,104,111,117,115,\n97,110,100,115,32,111,102,32,112,101,111,112,108,101,114,101,100,105,114,101,99,\n116,115,32,104,101,114,101,46,32,70,111,114,104,97,118,101,32,99,104,105,108,100\n,114,101,110,32,117,110,100,101,114,37,51,69,37,51,67,47,115,99,114,105,112,116,\n37,51,69,34,41,41,59,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119\n,119,119,46,60,108,105,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,\n47,115,105,116,101,95,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,116,\n101,120,116,45,100,101,99,111,114,97,116,105,111,110,58,110,111,110,101,115,116,\n121,108,101,61,34,100,105,115,112,108,97,121,58,32,110,111,110,101,60,109,101,\n116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,88,45,110,101,119,32,68,\n97,116,101,40,41,46,103,101,116,84,105,109,101,40,41,32,116,121,112,101,61,34,\n105,109,97,103,101,47,120,45,105,99,111,110,34,60,47,115,112,97,110,62,60,115,\n112,97,110,32,99,108,97,115,115,61,34,108,97,110,103,117,97,103,101,61,34,106,97\n,118,97,115,99,114,105,112,116,119,105,110,100,111,119,46,108,111,99,97,116,105,\n111,110,46,104,114,101,102,60,97,32,104,114,101,102,61,34,106,97,118,97,115,99,\n114,105,112,116,58,45,45,62,13,10,60,115,99,114,105,112,116,32,116,121,112,101,\n61,34,116,60,97,32,104,114,101,102,61,39,104,116,116,112,58,47,47,119,119,119,46\n,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,114,101,102,61,34,60,47,\n100,105,118,62,13,10,60,100,105,118,32,99,108,97,115,115,61,34,60,115,99,114,105\n,112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,34,32,114,101,108,61,34,\n115,116,121,108,101,115,104,101,101,116,34,32,116,60,47,100,105,118,62,10,60,115\n,99,114,105,112,116,32,116,121,112,101,61,47,97,62,32,60,97,32,104,114,101,102,\n61,34,104,116,116,112,58,47,47,32,97,108,108,111,119,84,114,97,110,115,112,97,\n114,101,110,99,121,61,34,88,45,85,65,45,67,111,109,112,97,116,105,98,108,101,34,\n32,99,111,110,114,101,108,97,116,105,111,110,115,104,105,112,32,98,101,116,119,\n101,101,110,10,60,47,115,99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,\n32,60,47,97,62,60,47,108,105,62,60,47,117,108,62,60,47,100,105,118,62,97,115,115\n,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,112,114,111,103,\n114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,60,47,97,62,60,97,32\n,104,114,101,102,61,34,104,116,116,112,58,47,47,60,47,97,62,60,47,108,105,62,60,\n108,105,32,99,108,97,115,115,61,34,102,111,114,109,32,97,99,116,105,111,110,61,\n34,104,116,116,112,58,47,47,60,100,105,118,32,115,116,121,108,101,61,34,100,105,\n115,112,108,97,121,58,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101\n,61,34,113,34,60,116,97,98,108,101,32,119,105,100,116,104,61,34,49,48,48,37,34,\n32,98,97,99,107,103,114,111,117,110,100,45,112,111,115,105,116,105,111,110,58,34\n,32,98,111,114,100,101,114,61,34,48,34,32,119,105,100,116,104,61,34,114,101,108,\n61,34,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,54,62,60,117,\n108,62,60,108,105,62,60,97,32,104,114,101,102,61,34,32,32,60,109,101,116,97,32,\n104,116,116,112,45,101,113,117,105,118,61,34,99,115,115,34,32,109,101,100,105,97\n,61,34,115,99,114,101,101,110,34,32,114,101,115,112,111,110,115,105,98,108,101,\n32,102,111,114,32,116,104,101,32,34,32,116,121,112,101,61,34,97,112,112,108,105,\n99,97,116,105,111,110,47,34,32,115,116,121,108,101,61,34,98,97,99,107,103,114,\n111,117,110,100,45,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,\n102,45,56,34,32,97,108,108,111,119,116,114,97,110,115,112,97,114,101,110,99,121,\n61,34,115,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116,\n101,13,10,60,109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,62,\n60,47,115,112,97,110,62,60,115,112,97,110,32,99,108,97,115,115,61,34,48,34,32,99\n,101,108,108,115,112,97,99,105,110,103,61,34,48,34,62,59,10,60,47,115,99,114,105\n,112,116,62,10,60,115,99,114,105,112,116,32,115,111,109,101,116,105,109,101,115,\n32,99,97,108,108,101,100,32,116,104,101,100,111,101,115,32,110,111,116,32,110,\n101,99,101,115,115,97,114,105,108,121,70,111,114,32,109,111,114,101,32,105,110,\n102,111,114,109,97,116,105,111,110,97,116,32,116,104,101,32,98,101,103,105,110,\n110,105,110,103,32,111,102,32,60,33,68,79,67,84,89,80,69,32,104,116,109,108,62,\n60,104,116,109,108,112,97,114,116,105,99,117,108,97,114,108,121,32,105,110,32,\n116,104,101,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,97,109,\n101,61,34,106,97,118,97,115,99,114,105,112,116,58,118,111,105,100,40,48,41,59,34\n,101,102,102,101,99,116,105,118,101,110,101,115,115,32,111,102,32,116,104,101,32\n,97,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,103,101,\n110,101,114,97,108,108,121,32,99,111,110,115,105,100,101,114,101,100,62,60,105,\n110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,34,62,60,47,115,\n99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,116,104,114,111,117,103,\n104,111,117,116,32,116,104,101,32,119,111,114,108,100,99,111,109,109,111,110,32,\n109,105,115,99,111,110,99,101,112,116,105,111,110,97,115,115,111,99,105,97,116,\n105,111,110,32,119,105,116,104,32,116,104,101,60,47,100,105,118,62,10,60,47,100,\n105,118,62,10,60,100,105,118,32,99,100,117,114,105,110,103,32,104,105,115,32,108\n,105,102,101,116,105,109,101,44,99,111,114,114,101,115,112,111,110,100,105,110,\n103,32,116,111,32,116,104,101,116,121,112,101,61,34,105,109,97,103,101,47,120,45\n,105,99,111,110,34,32,97,110,32,105,110,99,114,101,97,115,105,110,103,32,110,117\n,109,98,101,114,100,105,112,108,111,109,97,116,105,99,32,114,101,108,97,116,105,\n111,110,115,97,114,101,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,\n101,100,109,101,116,97,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,\n32,60,105,110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,101,120\n,97,109,112,108,101,115,32,105,110,99,108,117,100,101,32,116,104,101,34,62,60,\n105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,105,112,97,114,116,105,\n99,105,112,97,116,105,111,110,32,105,110,32,116,104,101,116,104,101,32,101,115,\n116,97,98,108,105,115,104,109,101,110,116,32,111,102,10,60,47,100,105,118,62,10,\n60,100,105,118,32,99,108,97,115,115,61,34,38,97,109,112,59,110,98,115,112,59,38,\n97,109,112,59,110,98,115,112,59,116,111,32,100,101,116,101,114,109,105,110,101,\n32,119,104,101,116,104,101,114,113,117,105,116,101,32,100,105,102,102,101,114,\n101,110,116,32,102,114,111,109,109,97,114,107,101,100,32,116,104,101,32,98,101,\n103,105,110,110,105,110,103,100,105,115,116,97,110,99,101,32,98,101,116,119,101,\n101,110,32,116,104,101,99,111,110,116,114,105,98,117,116,105,111,110,115,32,116,\n111,32,116,104,101,99,111,110,102,108,105,99,116,32,98,101,116,119,101,101,110,\n32,116,104,101,119,105,100,101,108,121,32,99,111,110,115,105,100,101,114,101,100\n,32,116,111,119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,102,105,114,\n115,116,119,105,116,104,32,118,97,114,121,105,110,103,32,100,101,103,114,101,101\n,115,104,97,118,101,32,115,112,101,99,117,108,97,116,101,100,32,116,104,97,116,\n40,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,112,\n97,114,116,105,99,105,112,97,116,105,110,103,32,105,110,32,116,104,101,111,114,\n105,103,105,110,97,108,108,121,32,100,101,118,101,108,111,112,101,100,101,116,97\n,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,32,116,121,112,101,\n61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,105,110,116,101,114,99,104,97\n,110,103,101,97,98,108,121,32,119,105,116,104,109,111,114,101,32,99,108,111,115,\n101,108,121,32,114,101,108,97,116,101,100,115,111,99,105,97,108,32,97,110,100,32\n,112,111,108,105,116,105,99,97,108,116,104,97,116,32,119,111,117,108,100,32,111,\n116,104,101,114,119,105,115,101,112,101,114,112,101,110,100,105,99,117,108,97,\n114,32,116,111,32,116,104,101,115,116,121,108,101,32,116,121,112,101,61,34,116,\n101,120,116,47,99,115,115,116,121,112,101,61,34,115,117,98,109,105,116,34,32,110\n,97,109,101,61,34,102,97,109,105,108,105,101,115,32,114,101,115,105,100,105,110,\n103,32,105,110,100,101,118,101,108,111,112,105,110,103,32,99,111,117,110,116,114\n,105,101,115,99,111,109,112,117,116,101,114,32,112,114,111,103,114,97,109,109,\n105,110,103,101,99,111,110,111,109,105,99,32,100,101,118,101,108,111,112,109,101\n,110,116,100,101,116,101,114,109,105,110,97,116,105,111,110,32,111,102,32,116,\n104,101,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111\n,110,111,110,32,115,101,118,101,114,97,108,32,111,99,99,97,115,105,111,110,115,\n112,111,114,116,117,103,117,195,170,115,32,40,69,117,114,111,112,101,117,41,208,\n163,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,209,\n131,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,208,\n160,208,190,209,129,209,129,208,184,208,185,209,129,208,186,208,190,208,185,208,\n188,208,176,209,130,208,181,209,128,208,184,208,176,208,187,208,190,208,178,208,\n184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,208,184,209,\n131,208,191,209,128,208,176,208,178,208,187,208,181,208,189,208,184,209,143,208,\n189,208,181,208,190,208,177,209,133,208,190,208,180,208,184,208,188,208,190,208,\n184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208,\n152,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208,\n160,208,181,209,129,208,191,209,131,208,177,208,187,208,184,208,186,208,184,208,\n186,208,190,208,187,208,184,209,135,208,181,209,129,209,130,208,178,208,190,208,\n184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,142,209,\n130,208,181,209,128,209,128,208,184,209,130,208,190,209,128,208,184,208,184,208,\n180,208,190,209,129,209,130,208,176,209,130,208,190,209,135,208,189,208,190,216,\n167,217,132,217,133,216,170,217,136,216,167,216,172,216,175,217,136,217,134,216,\n167,217,132,216,167,216,180,216,170,216,177,216,167,217,131,216,167,216,170,216,\n167,217,132,216,167,217,130,216,170,216,177,216,167,216,173,216,167,216,170,104,\n116,109,108,59,32,99,104,97,114,115,101,116,61,85,84,70,45,56,34,32,115,101,116,\n84,105,109,101,111,117,116,40,102,117,110,99,116,105,111,110,40,41,100,105,115,\n112,108,97,121,58,105,110,108,105,110,101,45,98,108,111,99,107,59,60,105,110,112\n,117,116,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,116,121,112,101,\n32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,60,105,109,103,32,\n115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,46,34,32,34,104,116,116,\n112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,115,104,111,114,116,99,117,\n116,32,105,99,111,110,34,32,104,114,101,102,61,34,34,32,97,117,116,111,99,111,\n109,112,108,101,116,101,61,34,111,102,102,34,32,60,47,97,62,60,47,100,105,118,62\n,60,100,105,118,32,99,108,97,115,115,61,60,47,97,62,60,47,108,105,62,10,60,108,\n105,32,99,108,97,115,115,61,34,99,115,115,34,32,116,121,112,101,61,34,116,101,\n120,116,47,99,115,115,34,32,60,102,111,114,109,32,97,99,116,105,111,110,61,34,\n104,116,116,112,58,47,47,120,116,47,99,115,115,34,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,108,105,110,107,32,114,101,108,61,34,97,108,116,101,114,110\n,97,116,101,34,32,13,10,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,\n101,120,116,47,32,111,110,99,108,105,99,107,61,34,106,97,118,97,115,99,114,105,\n112,116,58,40,110,101,119,32,68,97,116,101,41,46,103,101,116,84,105,109,101,40,\n41,125,104,101,105,103,104,116,61,34,49,34,32,119,105,100,116,104,61,34,49,34,32\n,80,101,111,112,108,101,39,115,32,82,101,112,117,98,108,105,99,32,111,102,32,32,\n60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,116,101,\n120,116,45,100,101,99,111,114,97,116,105,111,110,58,117,110,100,101,114,116,104,\n101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,60,47,100\n,105,118,62,10,60,47,100,105,118,62,10,60,47,100,105,118,62,10,101,115,116,97,98\n,108,105,115,104,109,101,110,116,32,111,102,32,116,104,101,32,60,47,100,105,118,\n62,60,47,100,105,118,62,60,47,100,105,118,62,60,47,100,35,118,105,101,119,112,\n111,114,116,123,109,105,110,45,104,101,105,103,104,116,58,10,60,115,99,114,105,\n112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,111,112,116,105,111,110,62,\n60,111,112,116,105,111,110,32,118,97,108,117,101,61,111,102,116,101,110,32,114,\n101,102,101,114,114,101,100,32,116,111,32,97,115,32,47,111,112,116,105,111,110,\n62,10,60,111,112,116,105,111,110,32,118,97,108,117,60,33,68,79,67,84,89,80,69,32\n,104,116,109,108,62,10,60,33,45,45,91,73,110,116,101,114,110,97,116,105,111,110,\n97,108,32,65,105,114,112,111,114,116,62,10,60,97,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,119,119,119,60,47,97,62,60,97,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,119,224,184,160,224,184,178,224,184,169,224,184,178,224,185\n,132,224,184,151,224,184,162,225,131,165,225,131,144,225,131,160,225,131,151,225\n,131,163,225,131,154,225,131,152,230,173,163,233,171,148,228,184,173,230,150,135\n,32,40,231,185,129,233,171,148,41,224,164,168,224,164,191,224,164,176,224,165,\n141,224,164,166,224,165,135,224,164,182,224,164,161,224,164,190,224,164,137,224,\n164,168,224,164,178,224,165,139,224,164,161,224,164,149,224,165,141,224,164,183,\n224,165,135,224,164,164,224,165,141,224,164,176,224,164,156,224,164,190,224,164,\n168,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184,224,164,130,224,\n164,172,224,164,130,224,164,167,224,164,191,224,164,164,224,164,184,224,165,141,\n224,164,165,224,164,190,224,164,170,224,164,168,224,164,190,224,164,184,224,165,\n141,224,164,181,224,165,128,224,164,149,224,164,190,224,164,176,224,164,184,224,\n164,130,224,164,184,224,165,141,224,164,149,224,164,176,224,164,163,224,164,184,\n224,164,190,224,164,174,224,164,151,224,165,141,224,164,176,224,165,128,224,164,\n154,224,164,191,224,164,159,224,165,141,224,164,160,224,165,139,224,164,130,224,\n164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164,168,\n224,164,133,224,164,174,224,165,135,224,164,176,224,164,191,224,164,149,224,164,\n190,224,164,181,224,164,191,224,164,173,224,164,191,224,164,168,224,165,141,224,\n164,168,224,164,151,224,164,190,224,164,161,224,164,191,224,164,175,224,164,190,\n224,164,129,224,164,149,224,165,141,224,164,175,224,165,139,224,164,130,224,164,\n149,224,164,191,224,164,184,224,165,129,224,164,176,224,164,149,224,165,141,224,\n164,183,224,164,190,224,164,170,224,164,185,224,165,129,224,164,129,224,164,154,\n224,164,164,224,165,128,224,164,170,224,165,141,224,164,176,224,164,172,224,164,\n130,224,164,167,224,164,168,224,164,159,224,164,191,224,164,170,224,165,141,224,\n164,170,224,164,163,224,165,128,224,164,149,224,165,141,224,164,176,224,164,191,\n224,164,149,224,165,135,224,164,159,224,164,170,224,165,141,224,164,176,224,164,\n190,224,164,176,224,164,130,224,164,173,224,164,170,224,165,141,224,164,176,224,\n164,190,224,164,170,224,165,141,224,164,164,224,164,174,224,164,190,224,164,178,\n224,164,191,224,164,149,224,165,139,224,164,130,224,164,176,224,164,171,224,164,\n188,224,165,141,224,164,164,224,164,190,224,164,176,224,164,168,224,164,191,224,\n164,176,224,165,141,224,164,174,224,164,190,224,164,163,224,164,178,224,164,191,\n224,164,174,224,164,191,224,164,159,224,165,135,224,164,161,100,101,115,99,114,\n105,112,116,105,111,110,34,32,99,111,110,116,101,110,116,61,34,100,111,99,117,\n109,101,110,116,46,108,111,99,97,116,105,111,110,46,112,114,111,116,46,103,101,\n116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,60,33,68,79\n,67,84,89,80,69,32,104,116,109,108,62,10,60,104,116,109,108,32,60,109,101,116,97\n,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,58,117,114,108,34,32\n,99,111,110,116,101,110,116,61,34,104,116,116,112,58,47,47,46,99,115,115,34,32,\n114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,115,116,121,108,101\n,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,62,116,121,112,101,61\n,34,116,101,120,116,47,99,115,115,34,32,104,114,101,102,61,34,119,51,46,111,114,\n103,47,49,57,57,57,47,120,104,116,109,108,34,32,120,109,108,116,121,112,101,61,\n34,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,34,32,109,101,116,104\n,111,100,61,34,103,101,116,34,32,97,99,116,105,111,110,61,34,108,105,110,107,32,\n114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,32,61,32,100,111\n,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,116,121,112,\n101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,34,32,47,62,99,101,108,108\n,112,97,100,100,105,110,103,61,34,48,34,32,99,101,108,108,115,112,46,99,115,115,\n34,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,60,47,97,62,60,\n47,108,105,62,60,108,105,62,60,97,32,104,114,101,102,61,34,34,32,119,105,100,116\n,104,61,34,49,34,32,104,101,105,103,104,116,61,34,49,34,34,62,60,97,32,104,114,\n101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,115,116,121,108,101,61,34,\n100,105,115,112,108,97,121,58,110,111,110,101,59,34,62,97,108,116,101,114,110,97\n,116,101,34,32,116,121,112,101,61,34,97,112,112,108,105,45,47,47,87,51,67,47,47,\n68,84,68,32,88,72,84,77,76,32,49,46,48,32,101,108,108,115,112,97,99,105,110,103,\n61,34,48,34,32,99,101,108,108,112,97,100,32,116,121,112,101,61,34,104,105,100,\n100,101,110,34,32,118,97,108,117,101,61,34,47,97,62,38,110,98,115,112,59,60,115,\n112,97,110,32,114,111,108,101,61,34,115,10,60,105,110,112,117,116,32,116,121,112\n,101,61,34,104,105,100,100,101,110,34,32,108,97,110,103,117,97,103,101,61,34,74,\n97,118,97,83,99,114,105,112,116,34,32,32,100,111,99,117,109,101,110,116,46,103,\n101,116,69,108,101,109,101,110,116,115,66,103,61,34,48,34,32,99,101,108,108,115,\n112,97,99,105,110,103,61,34,48,34,32,121,112,101,61,34,116,101,120,116,47,99,115\n,115,34,32,109,101,100,105,97,61,34,116,121,112,101,61,39,116,101,120,116,47,106\n,97,118,97,115,99,114,105,112,116,39,119,105,116,104,32,116,104,101,32,101,120,\n99,101,112,116,105,111,110,32,111,102,32,121,112,101,61,34,116,101,120,116,47,99\n,115,115,34,32,114,101,108,61,34,115,116,32,104,101,105,103,104,116,61,34,49,34,\n32,119,105,100,116,104,61,34,49,34,32,61,39,43,101,110,99,111,100,101,85,82,73,\n67,111,109,112,111,110,101,110,116,40,60,108,105,110,107,32,114,101,108,61,34,97\n,108,116,101,114,110,97,116,101,34,32,10,98,111,100,121,44,32,116,114,44,32,105,\n110,112,117,116,44,32,116,101,120,116,109,101,116,97,32,110,97,109,101,61,34,114\n,111,98,111,116,115,34,32,99,111,110,109,101,116,104,111,100,61,34,112,111,115,\n116,34,32,97,99,116,105,111,110,61,34,62,10,60,97,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,119,119,119,46,99,115,115,34,32,114,101,108,61,34,115,116,\n121,108,101,115,104,101,101,116,34,32,60,47,100,105,118,62,60,47,100,105,118,62,\n60,100,105,118,32,99,108,97,115,115,108,97,110,103,117,97,103,101,61,34,106,97,\n118,97,115,99,114,105,112,116,34,62,97,114,105,97,45,104,105,100,100,101,110,61,\n34,116,114,117,101,34,62,194,183,60,114,105,112,116,34,32,116,121,112,101,61,34,\n116,101,120,116,47,106,97,118,97,115,108,61,48,59,125,41,40,41,59,10,40,102,117,\n110,99,116,105,111,110,40,41,123,98,97,99,107,103,114,111,117,110,100,45,105,109\n,97,103,101,58,32,117,114,108,40,47,97,62,60,47,108,105,62,60,108,105,62,60,97,\n32,104,114,101,102,61,34,104,9,9,60,108,105,62,60,97,32,104,114,101,102,61,34,\n104,116,116,112,58,47,47,97,116,111,114,34,32,97,114,105,97,45,104,105,100,100,\n101,110,61,34,116,114,117,62,32,60,97,32,104,114,101,102,61,34,104,116,116,112,\n58,47,47,119,119,119,46,108,97,110,103,117,97,103,101,61,34,106,97,118,97,115,99\n,114,105,112,116,34,32,47,111,112,116,105,111,110,62,10,60,111,112,116,105,111,\n110,32,118,97,108,117,101,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,\n32,99,108,97,115,115,61,114,97,116,111,114,34,32,97,114,105,97,45,104,105,100,\n100,101,110,61,34,116,114,101,61,40,110,101,119,32,68,97,116,101,41,46,103,101,\n116,84,105,109,101,40,41,112,111,114,116,117,103,117,195,170,115,32,40,100,111,\n32,66,114,97,115,105,108,41,208,190,209,128,208,179,208,176,208,189,208,184,208,\n183,208,176,209,134,208,184,208,184,208,178,208,190,208,183,208,188,208,190,208,\n182,208,189,208,190,209,129,209,130,209,140,208,190,208,177,209,128,208,176,208,\n183,208,190,208,178,208,176,208,189,208,184,209,143,209,128,208,181,208,179,208,\n184,209,129,209,130,209,128,208,176,209,134,208,184,208,184,208,178,208,190,208,\n183,208,188,208,190,208,182,208,189,208,190,209,129,209,130,208,184,208,190,208,\n177,209,143,208,183,208,176,209,130,208,181,208,187,209,140,208,189,208,176,60,\n33,68,79,67,84,89,80,69,32,104,116,109,108,32,80,85,66,76,73,67,32,34,110,116,45\n,84,121,112,101,34,32,99,111,110,116,101,110,116,61,34,116,101,120,116,47,60,109\n,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,116,101,\n114,97,110,115,105,116,105,111,110,97,108,47,47,69,78,34,32,34,104,116,116,112,\n58,60,104,116,109,108,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,\n119,119,45,47,47,87,51,67,47,47,68,84,68,32,88,72,84,77,76,32,49,46,48,32,84,68,\n84,68,47,120,104,116,109,108,49,45,116,114,97,110,115,105,116,105,111,110,97,108\n,47,47,119,119,119,46,119,51,46,111,114,103,47,84,82,47,120,104,116,109,108,49,\n47,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,\n39,59,60,109,101,116,97,32,110,97,109,101,61,34,100,101,115,99,114,105,112,116,\n105,111,110,112,97,114,101,110,116,78,111,100,101,46,105,110,115,101,114,116,66,\n101,102,111,114,101,60,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,\n100,101,110,34,32,110,97,106,115,34,32,116,121,112,101,61,34,116,101,120,116,47,\n106,97,118,97,115,99,114,105,40,100,111,99,117,109,101,110,116,41,46,114,101,97,\n100,121,40,102,117,110,99,116,105,115,99,114,105,112,116,32,116,121,112,101,61,\n34,116,101,120,116,47,106,97,118,97,115,105,109,97,103,101,34,32,99,111,110,116,\n101,110,116,61,34,104,116,116,112,58,47,47,85,65,45,67,111,109,112,97,116,105,98\n,108,101,34,32,99,111,110,116,101,110,116,61,116,109,108,59,32,99,104,97,114,115\n,101,116,61,117,116,102,45,56,34,32,47,62,10,108,105,110,107,32,114,101,108,61,\n34,115,104,111,114,116,99,117,116,32,105,99,111,110,60,108,105,110,107,32,114,\n101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,60,47,115,99,114,105\n,112,116,62,10,60,115,99,114,105,112,116,32,116,121,112,101,61,61,32,100,111,99,\n117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,60,97,32,116\n,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,104,114,101,102,61,32,100,\n111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,105,\n110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61\n,97,46,116,121,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,\n105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,\n97,109,101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,\n34,32,47,62,100,116,100,34,62,10,60,104,116,109,108,32,120,109,108,110,115,61,34\n,104,116,116,112,45,47,47,87,51,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,\n32,84,101,110,116,115,66,121,84,97,103,78,97,109,101,40,39,115,99,114,105,112,\n116,39,41,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,\n34,32,110,97,109,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,101,120,\n116,47,106,97,118,97,115,34,32,115,116,121,108,101,61,34,100,105,115,112,108,97,\n121,58,110,111,110,101,59,34,62,100,111,99,117,109,101,110,116,46,103,101,116,69\n,108,101,109,101,110,116,66,121,73,100,40,61,100,111,99,117,109,101,110,116,46,\n99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,32,116,121,112,101,61,39,\n116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,105,110,112,117,116,\n32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61,34,100,46,103,\n101,116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,115,110\n,105,99,97,108,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,\n46,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,32,84,114,97,110,115,105,116,\n60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34\n,62,10,10,60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,\n115,115,34,62,105,111,110,97,108,46,100,116,100,34,62,10,60,104,116,109,108,32,\n120,109,108,110,115,61,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,\n116,101,110,116,45,84,121,112,101,100,105,110,103,61,34,48,34,32,99,101,108,108,\n115,112,97,99,105,110,103,61,34,48,34,104,116,109,108,59,32,99,104,97,114,115,\n101,116,61,117,116,102,45,56,34,32,47,62,10,32,115,116,121,108,101,61,34,100,105\n,115,112,108,97,121,58,110,111,110,101,59,34,62,60,60,108,105,62,60,97,32,104,\n114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,32,116,121,112,101,61,\n39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,62,208,180,208,181\n,209,143,209,130,208,181,208,187,209,140,208,189,208,190,209,129,209,130,208,184\n,209,129,208,190,208,190,209,130,208,178,208,181,209,130,209,129,209,130,208,178\n,208,184,208,184,208,191,209,128,208,190,208,184,208,183,208,178,208,190,208,180\n,209,129,209,130,208,178,208,176,208,177,208,181,208,183,208,190,208,191,208,176\n,209,129,208,189,208,190,209,129,209,130,208,184,224,164,170,224,165,129,224,164\n,184,224,165,141,224,164,164,224,164,191,224,164,149,224,164,190,224,164,149,224\n,164,190,224,164,130,224,164,151,224,165,141,224,164,176,224,165,135,224,164,184\n,224,164,137,224,164,168,224,165,141,224,164,185,224,165,139,224,164,130,224,164\n,168,224,165,135,224,164,181,224,164,191,224,164,167,224,164,190,224,164,168,224\n,164,184,224,164,173,224,164,190,224,164,171,224,164,191,224,164,149,224,165,141\n,224,164,184,224,164,191,224,164,130,224,164,151,224,164,184,224,165,129,224,164\n,176,224,164,149,224,165,141,224,164,183,224,164,191,224,164,164,224,164,149,224\n,165,137,224,164,170,224,165,128,224,164,176,224,164,190,224,164,135,224,164,159\n,224,164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164\n,170,224,164,168,224,164,149,224,164,190,224,164,176,224,165,141,224,164,176,224\n,164,181,224,164,190,224,164,136,224,164,184,224,164,149,224,165,141,224,164,176\n,224,164,191,224,164,175,224,164,164,224,164,190\n};\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/platform.c",
    "content": "﻿/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"platform.h\"\n\n/* Default brotli_alloc_func */\nvoid* BrotliDefaultAllocFunc(void* opaque, size_t size) {\n  BROTLI_UNUSED(opaque);\n  return malloc(size);\n}\n\n/* Default brotli_free_func */\nvoid BrotliDefaultFreeFunc(void* opaque, void* address) {\n  BROTLI_UNUSED(opaque);\n  free(address);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/platform.h",
    "content": "﻿/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Macros for compiler / platform specific features and build options.\n\n   Build options are:\n    * BROTLI_BUILD_32_BIT disables 64-bit optimizations\n    * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations\n    * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations\n    * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations\n    * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations\n    * BROTLI_BUILD_NO_RBIT disables \"rbit\" optimization for ARM CPUs\n    * BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read\n      optimizations (mainly for testing purposes)\n    * BROTLI_DEBUG dumps file name and line number when decoder detects stream\n      or memory error\n    * BROTLI_ENABLE_LOG enables asserts and dumps various state information\n    * BROTLI_ENABLE_DUMP overrides default \"dump\" behaviour\n*/\n\n#ifndef BROTLI_COMMON_PLATFORM_H_\n#define BROTLI_COMMON_PLATFORM_H_\n\n#include <string.h>  /* IWYU pragma: export memcmp, memcpy, memset */\n#include <stdlib.h>  /* IWYU pragma: export exit, free, malloc */\n#include <sys/types.h>  /* should include endian.h for us */\n\n#include <brotli/port.h>  /* IWYU pragma: export */\n#include <brotli/types.h>  /* IWYU pragma: export */\n\n#if BROTLI_MSVC_VERSION_CHECK(18, 0, 0)\n#include <intrin.h>\n#endif\n\n#if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG)\n#include <assert.h>\n#include <stdio.h>\n#endif\n\n/* The following macros were borrowed from https://github.com/nemequ/hedley\n * with permission of original author - Evan Nemerson <evan@nemerson.com> */\n\n/* >>> >>> >>> hedley macros */\n\n/* Define \"BROTLI_PREDICT_TRUE\" and \"BROTLI_PREDICT_FALSE\" macros for capable\n   compilers.\n\nTo apply compiler hint, enclose the branching condition into macros, like this:\n\n  if (BROTLI_PREDICT_TRUE(zero == 0)) {\n    // main execution path\n  } else {\n    // compiler should place this code outside of main execution path\n  }\n\nOR:\n\n  if (BROTLI_PREDICT_FALSE(something_rare_or_unexpected_happens)) {\n    // compiler should place this code outside of main execution path\n  }\n\n*/\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_expect, 3, 0, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||               \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 15, 0) ||              \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                  \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                 \\\n    BROTLI_TI_VERSION_CHECK(7, 3, 0) ||                   \\\n    BROTLI_TINYC_VERSION_CHECK(0, 9, 27)\n#define BROTLI_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))\n#define BROTLI_PREDICT_FALSE(x) (__builtin_expect(x, 0))\n#else\n#define BROTLI_PREDICT_FALSE(x) (x)\n#define BROTLI_PREDICT_TRUE(x) (x)\n#endif\n\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \\\n    !defined(__cplusplus)\n#define BROTLI_RESTRICT restrict\n#elif BROTLI_GNUC_VERSION_CHECK(3, 1, 0) ||                         \\\n    BROTLI_MSVC_VERSION_CHECK(14, 0, 0) ||                          \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                         \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                            \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                           \\\n    BROTLI_PGI_VERSION_CHECK(17, 10, 0) ||                          \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                             \\\n    BROTLI_IAR_VERSION_CHECK(8, 0, 0) ||                            \\\n    (BROTLI_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus))\n#define BROTLI_RESTRICT __restrict\n#elif BROTLI_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus)\n#define BROTLI_RESTRICT _Restrict\n#else\n#define BROTLI_RESTRICT\n#endif\n\n#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \\\n    (defined(__cplusplus) && (__cplusplus >= 199711L))\n#define BROTLI_MAYBE_INLINE inline\n#elif defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__) || \\\n    BROTLI_ARM_VERSION_CHECK(6, 2, 0)\n#define BROTLI_MAYBE_INLINE __inline__\n#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) || \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) || BROTLI_TI_VERSION_CHECK(8, 0, 0)\n#define BROTLI_MAYBE_INLINE __inline\n#else\n#define BROTLI_MAYBE_INLINE\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(always_inline, 4, 0, 0) ||                       \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                                    \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                                   \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                                       \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                                      \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE __attribute__((__always_inline__))\n#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0)\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE __forceinline\n#elif BROTLI_TI_VERSION_CHECK(7, 0, 0) && defined(__cplusplus)\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma(\"FUNC_ALWAYS_INLINE;\")\n#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0)\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma(\"inline=forced\")\n#else\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(noinline, 4, 0, 0) ||                            \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                                    \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                                   \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                                       \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                                      \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))\n#define BROTLI_NOINLINE __attribute__((__noinline__))\n#elif BROTLI_MSVC_VERSION_CHECK(13, 10, 0)\n#define BROTLI_NOINLINE __declspec(noinline)\n#elif BROTLI_PGI_VERSION_CHECK(10, 2, 0)\n#define BROTLI_NOINLINE _Pragma(\"noinline\")\n#elif BROTLI_TI_VERSION_CHECK(6, 0, 0) && defined(__cplusplus)\n#define BROTLI_NOINLINE _Pragma(\"FUNC_CANNOT_INLINE;\")\n#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0)\n#define BROTLI_NOINLINE _Pragma(\"inline=never\")\n#else\n#define BROTLI_NOINLINE\n#endif\n\n/* <<< <<< <<< end of hedley macros. */\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE __attribute__ ((unused))\n#else\n#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)\n#define BROTLI_ALIGNED(N) __attribute__((aligned(N)))\n#else\n#define BROTLI_ALIGNED(N)\n#endif\n\n#if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \\\n    (defined(M_ARM) && (M_ARM == 7))\n#define BROTLI_TARGET_ARMV7\n#endif  /* ARMv7 */\n\n#if (defined(__ARM_ARCH) && (__ARM_ARCH == 8)) || \\\n    defined(__aarch64__) || defined(__ARM64_ARCH_8__)\n#define BROTLI_TARGET_ARMV8_ANY\n\n#if defined(__ARM_32BIT_STATE)\n#define BROTLI_TARGET_ARMV8_32\n#elif defined(__ARM_64BIT_STATE)\n#define BROTLI_TARGET_ARMV8_64\n#endif\n\n#endif  /* ARMv8 */\n\n#if defined(__ARM_NEON__) || defined(__ARM_NEON)\n#define BROTLI_TARGET_NEON\n#endif\n\n#if defined(__i386) || defined(_M_IX86)\n#define BROTLI_TARGET_X86\n#endif\n\n#if defined(__x86_64__) || defined(_M_X64)\n#define BROTLI_TARGET_X64\n#endif\n\n#if defined(__PPC64__)\n#define BROTLI_TARGET_POWERPC64\n#endif\n\n#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64\n#define BROTLI_TARGET_RISCV64\n#endif\n\n#if defined(__loongarch_lp64)\n#define BROTLI_TARGET_LOONGARCH64\n#endif\n\n/* This does not seem to be an indicator of z/Architecture (64-bit); neither\n   that allows to use unaligned loads. */\n#if defined(__s390x__)\n#define BROTLI_TARGET_S390X\n#endif\n\n#if defined(__mips64)\n#define BROTLI_TARGET_MIPS64\n#endif\n\n#if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \\\n    defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) || \\\n    defined(BROTLI_TARGET_LOONGARCH64) || defined(BROTLI_TARGET_MIPS64)\n#define BROTLI_TARGET_64_BITS 1\n#else\n#define BROTLI_TARGET_64_BITS 0\n#endif\n\n#if defined(BROTLI_BUILD_64_BIT)\n#define BROTLI_64_BITS 1\n#elif defined(BROTLI_BUILD_32_BIT)\n#define BROTLI_64_BITS 0\n#else\n#define BROTLI_64_BITS BROTLI_TARGET_64_BITS\n#endif\n\n#if (BROTLI_64_BITS)\n#define brotli_reg_t uint64_t\n#else\n#define brotli_reg_t uint32_t\n#endif\n\n#if defined(BROTLI_BUILD_BIG_ENDIAN)\n#define BROTLI_BIG_ENDIAN 1\n#elif defined(BROTLI_BUILD_LITTLE_ENDIAN)\n#define BROTLI_LITTLE_ENDIAN 1\n#elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL)\n/* Just break elif chain. */\n#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#define BROTLI_LITTLE_ENDIAN 1\n#elif defined(_WIN32) || defined(BROTLI_TARGET_X64)\n/* Win32 & x64 can currently always be assumed to be little endian */\n#define BROTLI_LITTLE_ENDIAN 1\n#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#define BROTLI_BIG_ENDIAN 1\n/* Likely target platform is iOS / OSX. */\n#elif defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)\n#define BROTLI_LITTLE_ENDIAN 1\n#elif defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)\n#define BROTLI_BIG_ENDIAN 1\n#endif\n\n#if !defined(BROTLI_LITTLE_ENDIAN)\n#define BROTLI_LITTLE_ENDIAN 0\n#endif\n\n#if !defined(BROTLI_BIG_ENDIAN)\n#define BROTLI_BIG_ENDIAN 0\n#endif\n\n#if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST)\n#define BROTLI_UNALIGNED_READ_FAST (!!0)\n#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) ||       \\\n    defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \\\n    defined(BROTLI_TARGET_RISCV64) || defined(BROTLI_TARGET_LOONGARCH64)\n/* These targets are known to generate efficient code for unaligned reads\n * (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd\n * together). */\n#define BROTLI_UNALIGNED_READ_FAST (!!1)\n#else\n#define BROTLI_UNALIGNED_READ_FAST (!!0)\n#endif\n\n/* Portable unaligned memory access: read / write values via memcpy. */\n#if !defined(BROTLI_USE_PACKED_FOR_UNALIGNED)\n#if defined(__mips__) && (!defined(__mips_isa_rev) || __mips_isa_rev < 6)\n#define BROTLI_USE_PACKED_FOR_UNALIGNED 1\n#else\n#define BROTLI_USE_PACKED_FOR_UNALIGNED 0\n#endif\n#endif /* defined(BROTLI_USE_PACKED_FOR_UNALIGNED) */\n\n#if BROTLI_USE_PACKED_FOR_UNALIGNED\n\ntypedef union BrotliPackedValue {\n  uint16_t u16;\n  uint32_t u32;\n  uint64_t u64;\n  size_t szt;\n} __attribute__ ((packed)) BrotliPackedValue;\n\nstatic BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {\n  const BrotliPackedValue* address = (const BrotliPackedValue*)p;\n  return address->u16;\n}\nstatic BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {\n  const BrotliPackedValue* address = (const BrotliPackedValue*)p;\n  return address->u32;\n}\nstatic BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {\n  const BrotliPackedValue* address = (const BrotliPackedValue*)p;\n  return address->u64;\n}\nstatic BROTLI_INLINE size_t BrotliUnalignedReadSizeT(const void* p) {\n  const BrotliPackedValue* address = (const BrotliPackedValue*)p;\n  return address->szt;\n}\nstatic BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {\n  BrotliPackedValue* address = (BrotliPackedValue*)p;\n  address->u64 = v;\n}\n\n#else  /* not BROTLI_USE_PACKED_FOR_UNALIGNED */\n\nstatic BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {\n  uint16_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\nstatic BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {\n  uint32_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\nstatic BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {\n  uint64_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\nstatic BROTLI_INLINE size_t BrotliUnalignedReadSizeT(const void* p) {\n  size_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\nstatic BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {\n  memcpy(p, &v, sizeof v);\n}\n\n#endif  /* BROTLI_USE_PACKED_FOR_UNALIGNED */\n\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_bswap16, 4, 3, 0)\n#define BROTLI_BSWAP16(V) ((uint16_t)__builtin_bswap16(V))\n#else\n#define BROTLI_BSWAP16(V) ((uint16_t)( \\\n  (((V) & 0xFFU) << 8) | \\\n  (((V) >> 8) & 0xFFU)))\n#endif\n\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_bswap32, 4, 3, 0)\n#define BROTLI_BSWAP32(V) ((uint32_t)__builtin_bswap32(V))\n#else\n#define BROTLI_BSWAP32(V) ((uint32_t)( \\\n  (((V) & 0xFFU) << 24) | (((V) & 0xFF00U) << 8) | \\\n  (((V) >> 8) & 0xFF00U) | (((V) >> 24) & 0xFFU)))\n#endif\n\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_bswap64, 4, 3, 0)\n#define BROTLI_BSWAP64(V) ((uint64_t)__builtin_bswap64(V))\n#else\n#define BROTLI_BSWAP64(V) ((uint64_t)( \\\n  (((V) & 0xFFU) << 56) | (((V) & 0xFF00U) << 40) | \\\n  (((V) & 0xFF0000U) << 24) | (((V) & 0xFF000000U) << 8) | \\\n  (((V) >> 8) & 0xFF000000U) | (((V) >> 24) & 0xFF0000U) | \\\n  (((V) >> 40) & 0xFF00U) | (((V) >> 56) & 0xFFU)))\n#endif\n\n#if BROTLI_LITTLE_ENDIAN\n/* Straight endianness. Just read / write values. */\n#define BROTLI_UNALIGNED_LOAD16LE BrotliUnalignedRead16\n#define BROTLI_UNALIGNED_LOAD32LE BrotliUnalignedRead32\n#define BROTLI_UNALIGNED_LOAD64LE BrotliUnalignedRead64\n#define BROTLI_UNALIGNED_STORE64LE BrotliUnalignedWrite64\n#elif BROTLI_BIG_ENDIAN  /* BROTLI_LITTLE_ENDIAN */\nstatic BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) {\n  uint16_t value = BrotliUnalignedRead16(p);\n  return BROTLI_BSWAP16(value);\n}\nstatic BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) {\n  uint32_t value = BrotliUnalignedRead32(p);\n  return BROTLI_BSWAP32(value);\n}\nstatic BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) {\n  uint64_t value = BrotliUnalignedRead64(p);\n  return BROTLI_BSWAP64(value);\n}\nstatic BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {\n  uint64_t value = BROTLI_BSWAP64(v);\n  BrotliUnalignedWrite64(p, value);\n}\n#else  /* BROTLI_LITTLE_ENDIAN */\n/* Read / store values byte-wise; hopefully compiler will understand. */\nstatic BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) {\n  const uint8_t* in = (const uint8_t*)p;\n  return (uint16_t)(in[0] | (in[1] << 8));\n}\nstatic BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) {\n  const uint8_t* in = (const uint8_t*)p;\n  uint32_t value = (uint32_t)(in[0]);\n  value |= (uint32_t)(in[1]) << 8;\n  value |= (uint32_t)(in[2]) << 16;\n  value |= (uint32_t)(in[3]) << 24;\n  return value;\n}\nstatic BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) {\n  const uint8_t* in = (const uint8_t*)p;\n  uint64_t value = (uint64_t)(in[0]);\n  value |= (uint64_t)(in[1]) << 8;\n  value |= (uint64_t)(in[2]) << 16;\n  value |= (uint64_t)(in[3]) << 24;\n  value |= (uint64_t)(in[4]) << 32;\n  value |= (uint64_t)(in[5]) << 40;\n  value |= (uint64_t)(in[6]) << 48;\n  value |= (uint64_t)(in[7]) << 56;\n  return value;\n}\nstatic BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {\n  uint8_t* out = (uint8_t*)p;\n  out[0] = (uint8_t)v;\n  out[1] = (uint8_t)(v >> 8);\n  out[2] = (uint8_t)(v >> 16);\n  out[3] = (uint8_t)(v >> 24);\n  out[4] = (uint8_t)(v >> 32);\n  out[5] = (uint8_t)(v >> 40);\n  out[6] = (uint8_t)(v >> 48);\n  out[7] = (uint8_t)(v >> 56);\n}\n#endif  /* BROTLI_LITTLE_ENDIAN */\n\nstatic BROTLI_INLINE void* BROTLI_UNALIGNED_LOAD_PTR(const void* p) {\n  void* v;\n  memcpy(&v, p, sizeof(void*));\n  return v;\n}\n\nstatic BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR(void* p, const void* v) {\n  memcpy(p, &v, sizeof(void*));\n}\n\n/* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_IS_CONSTANT(x) (!!__builtin_constant_p(x))\n#else\n#define BROTLI_IS_CONSTANT(x) (!!0)\n#endif\n\n#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)\n#define BROTLI_HAS_UBFX (!!1)\n#else\n#define BROTLI_HAS_UBFX (!!0)\n#endif\n\n#if defined(BROTLI_ENABLE_LOG)\n#define BROTLI_LOG(x) printf x\n#else\n#define BROTLI_LOG(x)\n#endif\n\n#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)\n#define BROTLI_ENABLE_DUMP_DEFAULT 1\n#define BROTLI_DCHECK(x) assert(x)\n#else\n#define BROTLI_ENABLE_DUMP_DEFAULT 0\n#define BROTLI_DCHECK(x)\n#endif\n\n#if !defined(BROTLI_ENABLE_DUMP)\n#define BROTLI_ENABLE_DUMP BROTLI_ENABLE_DUMP_DEFAULT\n#endif\n\n#if BROTLI_ENABLE_DUMP\nstatic BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {\n  fprintf(stderr, \"%s:%d (%s)\\n\", f, l, fn);\n  fflush(stderr);\n}\n#define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__)\n#else\n#define BROTLI_DUMP() (void)(0)\n#endif\n\n/* BrotliRBit assumes brotli_reg_t fits native CPU register type. */\n#if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS)\n/* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */\n#if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \\\n    !defined(BROTLI_BUILD_NO_RBIT)\n#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)\n/* TODO(eustas): detect ARMv6T2 and enable this code for it. */\nstatic BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {\n  brotli_reg_t output;\n  __asm__(\"rbit %0, %1\\n\" : \"=r\"(output) : \"r\"(input));\n  return output;\n}\n#define BROTLI_RBIT(x) BrotliRBit(x)\n#endif  /* armv7 / armv8 */\n#endif  /* gcc || clang */\n#endif  /* brotli_reg_t is native */\n#if !defined(BROTLI_RBIT)\nstatic BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ }\n#endif  /* BROTLI_RBIT */\n\n#define BROTLI_REPEAT_4(X) {X; X; X; X;}\n#define BROTLI_REPEAT_5(X) {X; X; X; X; X;}\n#define BROTLI_REPEAT_6(X) {X; X; X; X; X; X;}\n\n#define BROTLI_UNUSED(X) (void)(X)\n\n#define BROTLI_MIN_MAX(T)                                                      \\\n  static BROTLI_INLINE T brotli_min_ ## T (T a, T b) { return a < b ? a : b; } \\\n  static BROTLI_INLINE T brotli_max_ ## T (T a, T b) { return a > b ? a : b; }\nBROTLI_MIN_MAX(double) BROTLI_MIN_MAX(float) BROTLI_MIN_MAX(int)\nBROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t)\n#undef BROTLI_MIN_MAX\n#define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B)))\n#define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B)))\n\n#define BROTLI_SWAP(T, A, I, J) { \\\n  T __brotli_swap_tmp = (A)[(I)]; \\\n  (A)[(I)] = (A)[(J)];            \\\n  (A)[(J)] = __brotli_swap_tmp;   \\\n}\n\n#if BROTLI_64_BITS\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_TZCNT64 __builtin_ctzll\n#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)\n#if defined(BROTLI_TARGET_X64) && !defined(_M_ARM64EC)\n#define BROTLI_TZCNT64 _tzcnt_u64\n#else /* BROTLI_TARGET_X64 */\nstatic BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) {\n  uint32_t lsb;\n  _BitScanForward64(&lsb, x);\n  return lsb;\n}\n#define BROTLI_TZCNT64 BrotliBsf64Msvc\n#endif /* BROTLI_TARGET_X64 */\n#endif /* __builtin_ctzll */\n#endif /* BROTLI_64_BITS */\n\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_BSR32(x) (31u ^ (uint32_t)__builtin_clz(x))\n#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)\nstatic BROTLI_INLINE uint32_t BrotliBsr32Msvc(uint32_t x) {\n  unsigned long msb;\n  _BitScanReverse(&msb, x);\n  return (uint32_t)msb;\n}\n#define BROTLI_BSR32 BrotliBsr32Msvc\n#endif /* __builtin_clz */\n\n/* Default brotli_alloc_func */\nBROTLI_COMMON_API void* BrotliDefaultAllocFunc(void* opaque, size_t size);\n\n/* Default brotli_free_func */\nBROTLI_COMMON_API void BrotliDefaultFreeFunc(void* opaque, void* address);\n\n/* Circular logical rotates. */\nstatic BROTLI_INLINE uint16_t BrotliRotateRight16(uint16_t const value,\n                                             size_t count) {\n  count &= 0x0F; /* for fickle pattern recognition */\n  return (value >> count) | (uint16_t)(value << ((0U - count) & 0x0F));\n}\nstatic BROTLI_INLINE uint32_t BrotliRotateRight32(uint32_t const value,\n                                             size_t count) {\n  count &= 0x1F; /* for fickle pattern recognition */\n  return (value >> count) | (uint32_t)(value << ((0U - count) & 0x1F));\n}\nstatic BROTLI_INLINE uint64_t BrotliRotateRight64(uint64_t const value,\n                                             size_t count) {\n  count &= 0x3F; /* for fickle pattern recognition */\n  return (value >> count) | (uint64_t)(value << ((0U - count) & 0x3F));\n}\n\nBROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {\n  BROTLI_UNUSED(&BrotliSuppressUnusedFunctions);\n  BROTLI_UNUSED(&BrotliUnalignedRead16);\n  BROTLI_UNUSED(&BrotliUnalignedRead32);\n  BROTLI_UNUSED(&BrotliUnalignedRead64);\n  BROTLI_UNUSED(&BrotliUnalignedReadSizeT);\n  BROTLI_UNUSED(&BrotliUnalignedWrite64);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD16LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD_PTR);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE_PTR);\n  BROTLI_UNUSED(&BrotliRBit);\n  BROTLI_UNUSED(&brotli_min_double);\n  BROTLI_UNUSED(&brotli_max_double);\n  BROTLI_UNUSED(&brotli_min_float);\n  BROTLI_UNUSED(&brotli_max_float);\n  BROTLI_UNUSED(&brotli_min_int);\n  BROTLI_UNUSED(&brotli_max_int);\n  BROTLI_UNUSED(&brotli_min_size_t);\n  BROTLI_UNUSED(&brotli_max_size_t);\n  BROTLI_UNUSED(&brotli_min_uint32_t);\n  BROTLI_UNUSED(&brotli_max_uint32_t);\n  BROTLI_UNUSED(&brotli_min_uint8_t);\n  BROTLI_UNUSED(&brotli_max_uint8_t);\n  BROTLI_UNUSED(&BrotliDefaultAllocFunc);\n  BROTLI_UNUSED(&BrotliDefaultFreeFunc);\n  BROTLI_UNUSED(&BrotliRotateRight16);\n  BROTLI_UNUSED(&BrotliRotateRight32);\n  BROTLI_UNUSED(&BrotliRotateRight64);\n#if BROTLI_ENABLE_DUMP\n  BROTLI_UNUSED(&BrotliDump);\n#endif\n\n#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && \\\n    !defined(_M_ARM64EC)\n/* _mm_prefetch() is not defined outside of x86/x64 */\n/* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */\n#include <mmintrin.h>\n#define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)\n#define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1)\n#elif BROTLI_GNUC_HAS_BUILTIN(__builtin_prefetch, 3, 1, 0)\n#define PREFETCH_L1(ptr) \\\n  __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)\n#define PREFETCH_L2(ptr) \\\n  __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)\n#elif defined(__aarch64__)\n#define PREFETCH_L1(ptr)                                      \\\n  do {                                                        \\\n    __asm__ __volatile__(\"prfm pldl1keep, %0\" ::\"Q\"(*(ptr))); \\\n  } while (0)\n#define PREFETCH_L2(ptr)                                      \\\n  do {                                                        \\\n    __asm__ __volatile__(\"prfm pldl2keep, %0\" ::\"Q\"(*(ptr))); \\\n  } while (0)\n#else\n#define PREFETCH_L1(ptr) \\\n  do {                   \\\n    (void)(ptr);         \\\n  } while (0) /* disabled */\n#define PREFETCH_L2(ptr) \\\n  do {                   \\\n    (void)(ptr);         \\\n  } while (0) /* disabled */\n#endif\n\n/* The SIMD matchers are only faster at certain quality levels. */\n#if defined(_M_X64) && defined(BROTLI_TZCNT64)\n#define BROTLI_MAX_SIMD_QUALITY 7\n#elif defined(BROTLI_TZCNT64)\n#define BROTLI_MAX_SIMD_QUALITY 6\n#endif\n}\n\n#if defined(_MSC_VER)\n#define BROTLI_CRASH() __debugbreak(), (void)abort()\n#elif BROTLI_GNUC_HAS_BUILTIN(__builtin_trap, 3, 0, 0)\n#define BROTLI_CRASH() (void)__builtin_trap()\n#else\n#define BROTLI_CRASH() (void)abort()\n#endif\n\n/* Make BROTLI_TEST=0 act same as undefined. */\n#if defined(BROTLI_TEST) && ((1-BROTLI_TEST-1) == 0)\n#undef BROTLI_TEST\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(model, 3, 0, 3)\n#define BROTLI_MODEL(M) __attribute__((model(M)))\n#else\n#define BROTLI_MODEL(M) /* M */\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(cold, 4, 3, 0)\n#define BROTLI_COLD __attribute__((cold))\n#else\n#define BROTLI_COLD /* cold */\n#endif\n\n#endif  /* BROTLI_COMMON_PLATFORM_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/shared_dictionary.c",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Shared Dictionary definition and utilities. */\n\n#include <brotli/shared_dictionary.h>\n\n#include \"dictionary.h\"\n#include \"platform.h\"\n#include \"shared_dictionary_internal.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if defined(BROTLI_EXPERIMENTAL)\n\n#define BROTLI_NUM_ENCODED_LENGTHS (SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH \\\n    - SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH + 1)\n\n/* Max allowed by spec */\n#define BROTLI_MAX_SIZE_BITS 15u\n\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadBool(const uint8_t* encoded, size_t size, size_t* pos,\n    BROTLI_BOOL* result) {\n  uint8_t value;\n  size_t position = *pos;\n  if (position >= size) return BROTLI_FALSE;  /* past file end */\n  value = encoded[position++];\n  if (value > 1) return BROTLI_FALSE;  /* invalid bool */\n  *result = TO_BROTLI_BOOL(value);\n  *pos = position;\n  return BROTLI_TRUE;  /* success */\n}\n\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadUint8(const uint8_t* encoded, size_t size, size_t* pos,\n    uint8_t* result) {\n  size_t position = *pos;\n  if (position + sizeof(uint8_t) > size) return BROTLI_FALSE;\n  *result = encoded[position++];\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadUint16(const uint8_t* encoded, size_t size, size_t* pos,\n    uint16_t* result) {\n  size_t position = *pos;\n  if (position + sizeof(uint16_t) > size) return BROTLI_FALSE;\n  *result = BROTLI_UNALIGNED_LOAD16LE(&encoded[position]);\n  position += 2;\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\n/* Reads a varint into a uint32_t, and returns error if it's too large */\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadVarint32(const uint8_t* encoded, size_t size,\n    size_t* pos, uint32_t* result) {\n  int num = 0;\n  uint8_t byte;\n  *result = 0;\n  for (;;) {\n    if (*pos >= size) return BROTLI_FALSE;\n    byte = encoded[(*pos)++];\n    if (num == 4 && byte > 15) return BROTLI_FALSE;\n    *result |= (uint32_t)(byte & 127) << (num * 7);\n    if (byte < 128) return BROTLI_TRUE;\n    num++;\n  }\n}\n\n/* Returns the total length of word list. */\nstatic size_t BrotliSizeBitsToOffsets(const uint8_t* size_bits_by_length,\n    uint32_t* offsets_by_length) {\n  uint32_t pos = 0;\n  uint32_t i;\n  for (i = 0; i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {\n    offsets_by_length[i] = pos;\n    if (size_bits_by_length[i] != 0) {\n      pos += i << size_bits_by_length[i];\n    }\n  }\n  return pos;\n}\n\nstatic BROTLI_BOOL ParseWordList(size_t size, const uint8_t* encoded,\n    size_t* pos, BrotliDictionary* out) {\n  size_t offset;\n  size_t i;\n  size_t position = *pos;\n  if (position + BROTLI_NUM_ENCODED_LENGTHS > size) {\n    return BROTLI_FALSE;\n  }\n\n  memset(out->size_bits_by_length, 0, SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH);\n  memcpy(out->size_bits_by_length + SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH,\n      &encoded[position], BROTLI_NUM_ENCODED_LENGTHS);\n  for (i = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;\n      i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {\n    if (out->size_bits_by_length[i] > BROTLI_MAX_SIZE_BITS) {\n      return BROTLI_FALSE;\n    }\n  }\n  position += BROTLI_NUM_ENCODED_LENGTHS;\n  offset = BrotliSizeBitsToOffsets(\n      out->size_bits_by_length, out->offsets_by_length);\n\n  out->data = &encoded[position];\n  out->data_size = offset;\n  position += offset;\n  if (position > size) return BROTLI_FALSE;\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\n/* Computes the cutOffTransforms of a BrotliTransforms which already has the\n   transforms data correctly filled in. */\nstatic void ComputeCutoffTransforms(BrotliTransforms* transforms) {\n  uint32_t i;\n  for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {\n    transforms->cutOffTransforms[i] = -1;\n  }\n  for (i = 0; i < transforms->num_transforms; i++) {\n    const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, i);\n    uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, i);\n    const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, i);\n    if (type <= BROTLI_TRANSFORM_OMIT_LAST_9 && *prefix == 0 && *suffix == 0 &&\n        transforms->cutOffTransforms[type] == -1) {\n      transforms->cutOffTransforms[type] = (int16_t)i;\n    }\n  }\n}\n\nstatic BROTLI_BOOL ParsePrefixSuffixTable(size_t size, const uint8_t* encoded,\n    size_t* pos, BrotliTransforms* out, uint16_t* out_table,\n    size_t* out_table_size) {\n  size_t position = *pos;\n  size_t offset = 0;\n  size_t stringlet_count = 0;  /* NUM_PREFIX_SUFFIX */\n  size_t data_length = 0;\n\n  /* PREFIX_SUFFIX_LENGTH */\n  if (!ReadUint16(encoded, size, &position, &out->prefix_suffix_size)) {\n    return BROTLI_FALSE;\n  }\n  data_length = out->prefix_suffix_size;\n\n  /* Must at least have space for null terminator. */\n  if (data_length < 1) return BROTLI_FALSE;\n  out->prefix_suffix = &encoded[position];\n  if (position + data_length >= size) return BROTLI_FALSE;\n  while (BROTLI_TRUE) {\n    /* STRING_LENGTH */\n    size_t stringlet_len = encoded[position + offset];\n    out_table[stringlet_count] = (uint16_t)offset;\n    stringlet_count++;\n    offset++;\n    if (stringlet_len == 0) {\n      if (offset == data_length) {\n        break;\n      } else {\n        return BROTLI_FALSE;\n      }\n    }\n    if (stringlet_count > 255) return BROTLI_FALSE;\n    offset += stringlet_len;\n    if (offset >= data_length) return BROTLI_FALSE;\n  }\n\n  position += data_length;\n  *pos = position;\n  *out_table_size = (uint16_t)stringlet_count;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL ParseTransformsList(size_t size, const uint8_t* encoded,\n    size_t* pos, BrotliTransforms* out, uint16_t* prefix_suffix_table,\n    size_t* prefix_suffix_count) {\n  uint32_t i;\n  BROTLI_BOOL has_params = BROTLI_FALSE;\n  BROTLI_BOOL prefix_suffix_ok = BROTLI_FALSE;\n  size_t position = *pos;\n  size_t stringlet_cnt = 0;\n  if (position >= size) return BROTLI_FALSE;\n\n  prefix_suffix_ok = ParsePrefixSuffixTable(\n      size, encoded, &position, out, prefix_suffix_table, &stringlet_cnt);\n  if (!prefix_suffix_ok) return BROTLI_FALSE;\n  out->prefix_suffix_map = prefix_suffix_table;\n  *prefix_suffix_count = stringlet_cnt;\n\n  out->num_transforms = encoded[position++];\n  out->transforms = &encoded[position];\n  position += (size_t)out->num_transforms * 3;\n  if (position > size) return BROTLI_FALSE;\n  /* Check for errors and read extra parameters. */\n  for (i = 0; i < out->num_transforms; i++) {\n    uint8_t prefix_id = BROTLI_TRANSFORM_PREFIX_ID(out, i);\n    uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);\n    uint8_t suffix_id = BROTLI_TRANSFORM_SUFFIX_ID(out, i);\n    if (prefix_id >= stringlet_cnt) return BROTLI_FALSE;\n    if (type >= BROTLI_NUM_TRANSFORM_TYPES) return BROTLI_FALSE;\n    if (suffix_id >= stringlet_cnt) return BROTLI_FALSE;\n    if (type == BROTLI_TRANSFORM_SHIFT_FIRST ||\n        type == BROTLI_TRANSFORM_SHIFT_ALL) {\n      has_params = BROTLI_TRUE;\n    }\n  }\n  if (has_params) {\n    out->params = &encoded[position];\n    position += (size_t)out->num_transforms * 2;\n    if (position > size) return BROTLI_FALSE;\n    for (i = 0; i < out->num_transforms; i++) {\n      uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);\n      if (type != BROTLI_TRANSFORM_SHIFT_FIRST &&\n          type != BROTLI_TRANSFORM_SHIFT_ALL) {\n        if (out->params[i * 2] != 0 || out->params[i * 2 + 1] != 0) {\n          return BROTLI_FALSE;\n        }\n      }\n    }\n  } else {\n    out->params = NULL;\n  }\n  ComputeCutoffTransforms(out);\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL DryParseDictionary(const uint8_t* encoded,\n    size_t size, uint32_t* num_prefix, BROTLI_BOOL* is_custom_static_dict) {\n  size_t pos = 0;\n  uint32_t chunk_size = 0;\n  uint8_t num_word_lists;\n  uint8_t num_transform_lists;\n  *is_custom_static_dict = BROTLI_FALSE;\n  *num_prefix = 0;\n\n  /* Skip magic header bytes. */\n  pos += 2;\n\n  /* LZ77_DICTIONARY_LENGTH */\n  if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;\n  if (chunk_size != 0) {\n    /* This limitation is not specified but the 32-bit Brotli decoder for now */\n    if (chunk_size > 1073741823) return BROTLI_FALSE;\n    *num_prefix = 1;\n    if (pos + chunk_size > size) return BROTLI_FALSE;\n    pos += chunk_size;\n  }\n\n  if (!ReadUint8(encoded, size, &pos, &num_word_lists)) {\n    return BROTLI_FALSE;\n  }\n  if (!ReadUint8(encoded, size, &pos, &num_transform_lists)) {\n    return BROTLI_FALSE;\n  }\n\n  if (num_word_lists > 0 || num_transform_lists > 0) {\n    *is_custom_static_dict = BROTLI_TRUE;\n  }\n\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL ParseDictionary(const uint8_t* encoded, size_t size,\n    BrotliSharedDictionary* dict) {\n  uint32_t i;\n  size_t pos = 0;\n  uint32_t chunk_size = 0;\n  size_t total_prefix_suffix_count = 0;\n  size_t transform_list_start[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n  uint16_t temporary_prefix_suffix_table[256];\n\n  /* Skip magic header bytes. */\n  pos += 2;\n\n  /* LZ77_DICTIONARY_LENGTH */\n  if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;\n  if (chunk_size != 0) {\n    if (pos + chunk_size > size) return BROTLI_FALSE;\n    dict->prefix_size[dict->num_prefix] = chunk_size;\n    dict->prefix[dict->num_prefix] = &encoded[pos];\n    dict->num_prefix++;\n    /* LZ77_DICTIONARY_LENGTH bytes. */\n    pos += chunk_size;\n  }\n\n  /* NUM_WORD_LISTS */\n  if (!ReadUint8(encoded, size, &pos, &dict->num_word_lists)) {\n    return BROTLI_FALSE;\n  }\n  if (dict->num_word_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {\n    return BROTLI_FALSE;\n  }\n\n  if (dict->num_word_lists != 0) {\n    dict->words_instances = (BrotliDictionary*)dict->alloc_func(\n        dict->memory_manager_opaque,\n        dict->num_word_lists * sizeof(*dict->words_instances));\n    if (!dict->words_instances) return BROTLI_FALSE;  /* OOM */\n  }\n  for (i = 0; i < dict->num_word_lists; i++) {\n    if (!ParseWordList(size, encoded, &pos, &dict->words_instances[i])) {\n      return BROTLI_FALSE;\n    }\n  }\n\n  /* NUM_TRANSFORM_LISTS */\n  if (!ReadUint8(encoded, size, &pos, &dict->num_transform_lists)) {\n    return BROTLI_FALSE;\n  }\n  if (dict->num_transform_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {\n    return BROTLI_FALSE;\n  }\n\n  if (dict->num_transform_lists != 0) {\n    dict->transforms_instances = (BrotliTransforms*)dict->alloc_func(\n        dict->memory_manager_opaque,\n        dict->num_transform_lists * sizeof(*dict->transforms_instances));\n    if (!dict->transforms_instances) return BROTLI_FALSE;  /* OOM */\n  }\n  for (i = 0; i < dict->num_transform_lists; i++) {\n    BROTLI_BOOL ok = BROTLI_FALSE;\n    size_t prefix_suffix_count = 0;\n    transform_list_start[i] = pos;\n    dict->transforms_instances[i].prefix_suffix_map =\n        temporary_prefix_suffix_table;\n    ok = ParseTransformsList(\n        size, encoded, &pos, &dict->transforms_instances[i],\n        temporary_prefix_suffix_table, &prefix_suffix_count);\n    if (!ok) return BROTLI_FALSE;\n    total_prefix_suffix_count += prefix_suffix_count;\n  }\n  if (total_prefix_suffix_count != 0) {\n    dict->prefix_suffix_maps = (uint16_t*)dict->alloc_func(\n        dict->memory_manager_opaque,\n        total_prefix_suffix_count * sizeof(*dict->prefix_suffix_maps));\n    if (!dict->prefix_suffix_maps) return BROTLI_FALSE;  /* OOM */\n  }\n  total_prefix_suffix_count = 0;\n  for (i = 0; i < dict->num_transform_lists; i++) {\n    size_t prefix_suffix_count = 0;\n    size_t position = transform_list_start[i];\n    uint16_t* prefix_suffix_map =\n      &dict->prefix_suffix_maps[total_prefix_suffix_count];\n    BROTLI_BOOL ok = ParsePrefixSuffixTable(\n        size, encoded, &position, &dict->transforms_instances[i],\n        prefix_suffix_map, &prefix_suffix_count);\n    if (!ok) return BROTLI_FALSE;\n    dict->transforms_instances[i].prefix_suffix_map = prefix_suffix_map;\n    total_prefix_suffix_count += prefix_suffix_count;\n  }\n\n  if (dict->num_word_lists != 0 || dict->num_transform_lists != 0) {\n    if (!ReadUint8(encoded, size, &pos, &dict->num_dictionaries)) {\n      return BROTLI_FALSE;\n    }\n    if (dict->num_dictionaries == 0 ||\n        dict->num_dictionaries > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {\n      return BROTLI_FALSE;\n    }\n    for (i = 0; i < dict->num_dictionaries; i++) {\n      uint8_t words_index;\n      uint8_t transforms_index;\n      if (!ReadUint8(encoded, size, &pos, &words_index)) {\n        return BROTLI_FALSE;\n      }\n      if (words_index > dict->num_word_lists) return BROTLI_FALSE;\n      if (!ReadUint8(encoded, size, &pos, &transforms_index)) {\n        return BROTLI_FALSE;\n      }\n      if (transforms_index > dict->num_transform_lists) return BROTLI_FALSE;\n      dict->words[i] = words_index == dict->num_word_lists ?\n          BrotliGetDictionary() : &dict->words_instances[words_index];\n      dict->transforms[i] = transforms_index == dict->num_transform_lists ?\n          BrotliGetTransforms(): &dict->transforms_instances[transforms_index];\n    }\n    /* CONTEXT_ENABLED */\n    if (!ReadBool(encoded, size, &pos, &dict->context_based)) {\n      return BROTLI_FALSE;\n    }\n\n    /* CONTEXT_MAP */\n    if (dict->context_based) {\n      for (i = 0; i < SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS; i++) {\n        if (!ReadUint8(encoded, size, &pos, &dict->context_map[i])) {\n          return BROTLI_FALSE;\n        }\n        if (dict->context_map[i] >= dict->num_dictionaries) {\n          return BROTLI_FALSE;\n        }\n      }\n    }\n  } else {\n    dict->context_based = BROTLI_FALSE;\n    dict->num_dictionaries = 1;\n    dict->words[0] = BrotliGetDictionary();\n    dict->transforms[0] = BrotliGetTransforms();\n  }\n\n  return BROTLI_TRUE;\n}\n\n/* Decodes shared dictionary and verifies correctness.\n   Returns BROTLI_TRUE if dictionary is valid, BROTLI_FALSE otherwise.\n   The BrotliSharedDictionary must already have been initialized. If the\n   BrotliSharedDictionary already contains data, compound dictionaries\n   will be appended, but an error will be returned if it already has\n   custom words or transforms.\n   TODO(lode): link to RFC for shared brotli once published. */\nstatic BROTLI_BOOL DecodeSharedDictionary(\n    const uint8_t* encoded, size_t size, BrotliSharedDictionary* dict) {\n  uint32_t num_prefix = 0;\n  BROTLI_BOOL is_custom_static_dict = BROTLI_FALSE;\n  BROTLI_BOOL has_custom_static_dict =\n      dict->num_word_lists > 0 || dict->num_transform_lists > 0;\n\n  /* Check magic header bytes. */\n  if (size < 2) return BROTLI_FALSE;\n  if (encoded[0] != 0x91 || encoded[1] != 0) return BROTLI_FALSE;\n\n  if (!DryParseDictionary(encoded, size, &num_prefix, &is_custom_static_dict)) {\n    return BROTLI_FALSE;\n  }\n\n  if (num_prefix + dict->num_prefix > SHARED_BROTLI_MAX_COMPOUND_DICTS) {\n    return BROTLI_FALSE;\n  }\n\n  /* Cannot combine different static dictionaries, only prefix dictionaries */\n  if (has_custom_static_dict && is_custom_static_dict) return BROTLI_FALSE;\n\n  return ParseDictionary(encoded, size, dict);\n}\n\n#endif  /* BROTLI_EXPERIMENTAL */\n\nvoid BrotliSharedDictionaryDestroyInstance(\n    BrotliSharedDictionary* dict) {\n  if (!dict) {\n    return;\n  } else {\n    brotli_free_func free_func = dict->free_func;\n    void* opaque = dict->memory_manager_opaque;\n    /* Cleanup. */\n    free_func(opaque, dict->words_instances);\n    free_func(opaque, dict->transforms_instances);\n    free_func(opaque, dict->prefix_suffix_maps);\n    /* Self-destruction. */\n    free_func(opaque, dict);\n  }\n}\n\nBROTLI_BOOL BrotliSharedDictionaryAttach(\n    BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {\n  if (!dict) {\n    return BROTLI_FALSE;\n  }\n#if defined(BROTLI_EXPERIMENTAL)\n  if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) {\n    return DecodeSharedDictionary(data, data_size, dict);\n  }\n#endif  /* BROTLI_EXPERIMENTAL */\n  if (type == BROTLI_SHARED_DICTIONARY_RAW) {\n    if (dict->num_prefix >= SHARED_BROTLI_MAX_COMPOUND_DICTS) {\n      return BROTLI_FALSE;\n    }\n    dict->prefix_size[dict->num_prefix] = data_size;\n    dict->prefix[dict->num_prefix] = data;\n    dict->num_prefix++;\n    return BROTLI_TRUE;\n  }\n  return BROTLI_FALSE;\n}\n\nBrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  BrotliSharedDictionary* dict = 0;\n  if (!alloc_func && !free_func) {\n    dict = (BrotliSharedDictionary*)malloc(sizeof(BrotliSharedDictionary));\n  } else if (alloc_func && free_func) {\n    dict = (BrotliSharedDictionary*)alloc_func(\n        opaque, sizeof(BrotliSharedDictionary));\n  }\n  if (dict == 0) {\n    return 0;\n  }\n\n  /* TODO(eustas): explicitly initialize all the fields? */\n  memset(dict, 0, sizeof(BrotliSharedDictionary));\n\n  dict->context_based = BROTLI_FALSE;\n  dict->num_dictionaries = 1;\n  dict->num_word_lists = 0;\n  dict->num_transform_lists = 0;\n\n  dict->words[0] = BrotliGetDictionary();\n  dict->transforms[0] = BrotliGetTransforms();\n\n  dict->alloc_func = alloc_func ? alloc_func : BrotliDefaultAllocFunc;\n  dict->free_func = free_func ? free_func : BrotliDefaultFreeFunc;\n  dict->memory_manager_opaque = opaque;\n\n  return dict;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/shared_dictionary_internal.h",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* (Transparent) Shared Dictionary definition. */\n\n#ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_\n#define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_\n\n#include <brotli/shared_dictionary.h>\n\n#include \"dictionary.h\"\n#include \"platform.h\"\n#include \"transform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstruct BrotliSharedDictionaryStruct {\n  /* LZ77 prefixes (compound dictionary). */\n  uint32_t num_prefix;  /* max SHARED_BROTLI_MAX_COMPOUND_DICTS */\n  size_t prefix_size[SHARED_BROTLI_MAX_COMPOUND_DICTS];\n  const uint8_t* prefix[SHARED_BROTLI_MAX_COMPOUND_DICTS];\n\n  /* If set, the context map is used to select word and transform list from 64\n     contexts, if not set, the context map is not used and only words[0] and\n     transforms[0] are to be used. */\n  BROTLI_BOOL context_based;\n\n  uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* Amount of word_list+transform_list combinations. */\n  uint8_t num_dictionaries;\n\n  /* Must use num_dictionaries values. */\n  const BrotliDictionary* words[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* Must use num_dictionaries values. */\n  const BrotliTransforms* transforms[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* Amount of custom word lists. May be 0 if only Brotli's built-in is used */\n  uint8_t num_word_lists;\n\n  /* Contents of the custom words lists. Must be NULL if num_word_lists is 0. */\n  BrotliDictionary* words_instances;\n\n  /* Amount of custom transform lists. May be 0 if only Brotli's built-in is\n     used */\n  uint8_t num_transform_lists;\n\n  /* Contents of the custom transform lists. Must be NULL if num_transform_lists\n     is 0. */\n  BrotliTransforms* transforms_instances;\n\n  /* Concatenated prefix_suffix_maps of the custom transform lists. Must be NULL\n     if num_transform_lists is 0. */\n  uint16_t* prefix_suffix_maps;\n\n  /* Memory management */\n  brotli_alloc_func alloc_func;\n  brotli_free_func free_func;\n  void* memory_manager_opaque;\n};\n\ntypedef struct BrotliSharedDictionaryStruct BrotliSharedDictionaryInternal;\n#define BrotliSharedDictionary BrotliSharedDictionaryInternal\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/static_init.h",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/*\n   Central point for static initialization.\n\n   In case of \"lazy\" mode `BrotliXxxLazyStaticInit` is not provided by the\n   library. Embedder is responsible for providing it. This function should call\n   `BrotliXxxLazyStaticInitInner` on the first invocation. This function should\n   not return until execution of `BrotliXxxLazyStaticInitInner` is finished.\n   In C or before C++11 it is possible to call `BrotliXxxLazyStaticInitInner`\n   on start-up path and then `BrotliEncoderLazyStaticInit` is could be no-op;\n   another option is to use available thread execution controls to meet the\n   requirements. For possible C++11 implementation see static_init_lazy.cc.\n*/\n\n#ifndef THIRD_PARTY_BROTLI_COMMON_STATIC_INIT_H_\n#define THIRD_PARTY_BROTLI_COMMON_STATIC_INIT_H_\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Static data is \"initialized\" in compile time. */\n#define BROTLI_STATIC_INIT_NONE 0\n/* Static data is initialized before \"main\". */\n#define BROTLI_STATIC_INIT_EARLY 1\n/* Static data is initialized when first encoder is created. */\n#define BROTLI_STATIC_INIT_LAZY 2\n\n#define BROTLI_STATIC_INIT_DEFAULT BROTLI_STATIC_INIT_NONE\n\n#if !defined(BROTLI_STATIC_INIT)\n#define BROTLI_STATIC_INIT BROTLI_STATIC_INIT_DEFAULT\n#endif\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE) && \\\n    (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_EARLY) && \\\n    (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_LAZY)\n#error Invalid value for BROTLI_STATIC_INIT\n#endif\n\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)\n#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\n#error BROTLI_STATIC_INIT_EARLY will fail with BROTLI_EXTERNAL_DICTIONARY_DATA\n#endif\n#endif  /* BROTLI_STATIC_INIT */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  // THIRD_PARTY_BROTLI_COMMON_STATIC_INIT_H_\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/transform.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"platform.h\"\n#include \"transform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* RFC 7932 transforms string data */\nstatic const BROTLI_MODEL(\"small\") char kPrefixSuffix[217] =\n      \"\\1 \\2, \\10 of the \\4 of \\2s \\1.\\5 and \\4 \"\n/* 0x  _0 _2  __5        _E    _3  _6 _8     _E */\n      \"in \\1\\\"\\4 to \\2\\\">\\1\\n\\2. \\1]\\5 for \\3 a \\6 \"\n/* 2x     _3_ _5    _A_  _D_ _F  _2 _4     _A   _E */\n      \"that \\1\\'\\6 with \\6 from \\4 by \\1(\\6. T\"\n/* 4x       _5_ _7      _E      _5    _A _C */\n      \"he \\4 on \\4 as \\4 is \\4ing \\2\\n\\t\\1:\\3ed \"\n/* 6x     _3    _8    _D    _2    _7_ _ _A _C */\n      \"\\2=\\\"\\4 at \\3ly \\1,\\2=\\'\\5.com/\\7. This \\5\"\n/* 8x  _0 _ _3    _8   _C _E _ _1     _7       _F */\n      \" not \\3er \\3al \\4ful \\4ive \\5less \\4es\"\n/* Ax       _5   _9   _D    _2    _7     _D */\n      \"t \\4ize \\2\\xc2\\xa0\\4ous \\5 the \\2e \"; /* \\0 - implicit trailing zero. */\n/* Cx    _2    _7___ ___ _A    _F     _5        _8 */\n\nstatic const BROTLI_MODEL(\"small\") uint16_t kPrefixSuffixMap[50] = {\n  0x00, 0x02, 0x05, 0x0E, 0x13, 0x16, 0x18, 0x1E, 0x23, 0x25,\n  0x2A, 0x2D, 0x2F, 0x32, 0x34, 0x3A, 0x3E, 0x45, 0x47, 0x4E,\n  0x55, 0x5A, 0x5C, 0x63, 0x68, 0x6D, 0x72, 0x77, 0x7A, 0x7C,\n  0x80, 0x83, 0x88, 0x8C, 0x8E, 0x91, 0x97, 0x9F, 0xA5, 0xA9,\n  0xAD, 0xB2, 0xB7, 0xBD, 0xC2, 0xC7, 0xCA, 0xCF, 0xD5, 0xD8\n};\n\n/* RFC 7932 transforms */\nstatic const BROTLI_MODEL(\"small\") uint8_t kTransformsData[] = {\n  49, BROTLI_TRANSFORM_IDENTITY, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 0,\n   0, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_1, 49,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 47,\n   0, BROTLI_TRANSFORM_IDENTITY, 49,\n   4, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 3,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 6,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_2, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_1, 49,\n   1, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 1,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 7,\n  49, BROTLI_TRANSFORM_IDENTITY, 9,\n  48, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 8,\n  49, BROTLI_TRANSFORM_IDENTITY, 5,\n  49, BROTLI_TRANSFORM_IDENTITY, 10,\n  49, BROTLI_TRANSFORM_IDENTITY, 11,\n  49, BROTLI_TRANSFORM_OMIT_LAST_3, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 13,\n  49, BROTLI_TRANSFORM_IDENTITY, 14,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_3, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_2, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 15,\n  49, BROTLI_TRANSFORM_IDENTITY, 16,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 12,\n   5, BROTLI_TRANSFORM_IDENTITY, 49,\n   0, BROTLI_TRANSFORM_IDENTITY, 1,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_4, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 18,\n  49, BROTLI_TRANSFORM_IDENTITY, 17,\n  49, BROTLI_TRANSFORM_IDENTITY, 19,\n  49, BROTLI_TRANSFORM_IDENTITY, 20,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_5, 49,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_6, 49,\n  47, BROTLI_TRANSFORM_IDENTITY, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_4, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 22,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 23,\n  49, BROTLI_TRANSFORM_IDENTITY, 24,\n  49, BROTLI_TRANSFORM_IDENTITY, 25,\n  49, BROTLI_TRANSFORM_OMIT_LAST_7, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_1, 26,\n  49, BROTLI_TRANSFORM_IDENTITY, 27,\n  49, BROTLI_TRANSFORM_IDENTITY, 28,\n   0, BROTLI_TRANSFORM_IDENTITY, 12,\n  49, BROTLI_TRANSFORM_IDENTITY, 29,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_9, 49,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_7, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_6, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1,\n  49, BROTLI_TRANSFORM_OMIT_LAST_8, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 31,\n  49, BROTLI_TRANSFORM_IDENTITY, 32,\n  47, BROTLI_TRANSFORM_IDENTITY, 3,\n  49, BROTLI_TRANSFORM_OMIT_LAST_5, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_9, 49,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 8,\n   5, BROTLI_TRANSFORM_IDENTITY, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 0,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 10,\n  49, BROTLI_TRANSFORM_IDENTITY, 30,\n   0, BROTLI_TRANSFORM_IDENTITY, 5,\n  35, BROTLI_TRANSFORM_IDENTITY, 49,\n  47, BROTLI_TRANSFORM_IDENTITY, 2,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 17,\n  49, BROTLI_TRANSFORM_IDENTITY, 36,\n  49, BROTLI_TRANSFORM_IDENTITY, 33,\n   5, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5,\n  49, BROTLI_TRANSFORM_IDENTITY, 37,\n   0, BROTLI_TRANSFORM_IDENTITY, 30,\n  49, BROTLI_TRANSFORM_IDENTITY, 38,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 39,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 34,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 8,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12,\n   0, BROTLI_TRANSFORM_IDENTITY, 21,\n  49, BROTLI_TRANSFORM_IDENTITY, 40,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12,\n  49, BROTLI_TRANSFORM_IDENTITY, 41,\n  49, BROTLI_TRANSFORM_IDENTITY, 42,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 17,\n  49, BROTLI_TRANSFORM_IDENTITY, 43,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 10,\n   0, BROTLI_TRANSFORM_IDENTITY, 34,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33,\n  49, BROTLI_TRANSFORM_IDENTITY, 44,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 5,\n  45, BROTLI_TRANSFORM_IDENTITY, 49,\n   0, BROTLI_TRANSFORM_IDENTITY, 33,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 30,\n  49, BROTLI_TRANSFORM_IDENTITY, 46,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 1,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 30,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 1,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 33,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 12,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 5,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 34,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 12,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 34,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nBrotliTransforms kBrotliTransforms = {\n  sizeof(kPrefixSuffix),\n  (const uint8_t*)kPrefixSuffix,\n  kPrefixSuffixMap,\n  sizeof(kTransformsData) / (3 * sizeof(kTransformsData[0])),\n  kTransformsData,\n  NULL,  /* no extra parameters */\n  {0, 12, 27, 23, 42, 63, 56, 48, 59, 64}\n};\n\nconst BrotliTransforms* BrotliGetTransforms(void) {\n  return &kBrotliTransforms;\n}\n\nstatic int ToUpperCase(uint8_t* p) {\n  if (p[0] < 0xC0) {\n    if (p[0] >= 'a' && p[0] <= 'z') {\n      p[0] ^= 32;\n    }\n    return 1;\n  }\n  /* An overly simplified uppercasing model for UTF-8. */\n  if (p[0] < 0xE0) {\n    p[1] ^= 32;\n    return 2;\n  }\n  /* An arbitrary transform for three byte characters. */\n  p[2] ^= 5;\n  return 3;\n}\n\nstatic int Shift(uint8_t* word, int word_len, uint16_t parameter) {\n  /* Limited sign extension: scalar < (1 << 24). */\n  uint32_t scalar =\n      (parameter & 0x7FFFu) + (0x1000000u - (parameter & 0x8000u));\n  if (word[0] < 0x80) {\n    /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */\n    scalar += (uint32_t)word[0];\n    word[0] = (uint8_t)(scalar & 0x7Fu);\n    return 1;\n  } else if (word[0] < 0xC0) {\n    /* Continuation / 10AAAAAA. */\n    return 1;\n  } else if (word[0] < 0xE0) {\n    /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */\n    if (word_len < 2) return 1;\n    scalar += (uint32_t)((word[1] & 0x3Fu) | ((word[0] & 0x1Fu) << 6u));\n    word[0] = (uint8_t)(0xC0 | ((scalar >> 6u) & 0x1F));\n    word[1] = (uint8_t)((word[1] & 0xC0) | (scalar & 0x3F));\n    return 2;\n  } else if (word[0] < 0xF0) {\n    /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */\n    if (word_len < 3) return word_len;\n    scalar += (uint32_t)((word[2] & 0x3Fu) | ((word[1] & 0x3Fu) << 6u) |\n        ((word[0] & 0x0Fu) << 12u));\n    word[0] = (uint8_t)(0xE0 | ((scalar >> 12u) & 0x0F));\n    word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 6u) & 0x3F));\n    word[2] = (uint8_t)((word[2] & 0xC0) | (scalar & 0x3F));\n    return 3;\n  } else if (word[0] < 0xF8) {\n    /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */\n    if (word_len < 4) return word_len;\n    scalar += (uint32_t)((word[3] & 0x3Fu) | ((word[2] & 0x3Fu) << 6u) |\n        ((word[1] & 0x3Fu) << 12u) | ((word[0] & 0x07u) << 18u));\n    word[0] = (uint8_t)(0xF0 | ((scalar >> 18u) & 0x07));\n    word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 12u) & 0x3F));\n    word[2] = (uint8_t)((word[2] & 0xC0) | ((scalar >> 6u) & 0x3F));\n    word[3] = (uint8_t)((word[3] & 0xC0) | (scalar & 0x3F));\n    return 4;\n  }\n  return 1;\n}\n\nint BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len,\n    const BrotliTransforms* transforms, int transform_idx) {\n  int idx = 0;\n  const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transform_idx);\n  uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, transform_idx);\n  const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, transform_idx);\n  {\n    int prefix_len = *prefix++;\n    while (prefix_len--) { dst[idx++] = *prefix++; }\n  }\n  {\n    const int t = type;\n    int i = 0;\n    if (t <= BROTLI_TRANSFORM_OMIT_LAST_9) {\n      len -= t;\n    } else if (t >= BROTLI_TRANSFORM_OMIT_FIRST_1\n        && t <= BROTLI_TRANSFORM_OMIT_FIRST_9) {\n      int skip = t - (BROTLI_TRANSFORM_OMIT_FIRST_1 - 1);\n      word += skip;\n      len -= skip;\n    }\n    while (i < len) { dst[idx++] = word[i++]; }\n    if (t == BROTLI_TRANSFORM_UPPERCASE_FIRST) {\n      ToUpperCase(&dst[idx - len]);\n    } else if (t == BROTLI_TRANSFORM_UPPERCASE_ALL) {\n      uint8_t* uppercase = &dst[idx - len];\n      while (len > 0) {\n        int step = ToUpperCase(uppercase);\n        uppercase += step;\n        len -= step;\n      }\n    } else if (t == BROTLI_TRANSFORM_SHIFT_FIRST) {\n      uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]\n          + (transforms->params[transform_idx * 2 + 1] << 8u));\n      Shift(&dst[idx - len], len, param);\n    } else if (t == BROTLI_TRANSFORM_SHIFT_ALL) {\n      uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]\n          + (transforms->params[transform_idx * 2 + 1] << 8u));\n      uint8_t* shift = &dst[idx - len];\n      while (len > 0) {\n        int step = Shift(shift, len, param);\n        shift += step;\n        len -= step;\n      }\n    }\n  }\n  {\n    int suffix_len = *suffix++;\n    while (suffix_len--) { dst[idx++] = *suffix++; }\n    return idx;\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/transform.h",
    "content": "﻿/* transforms is a part of ABI, but not API.\n\n   It means that there are some functions that are supposed to be in \"common\"\n   library, but header itself is not placed into include/brotli. This way,\n   aforementioned functions will be available only to brotli internals.\n */\n\n#ifndef BROTLI_COMMON_TRANSFORM_H_\n#define BROTLI_COMMON_TRANSFORM_H_\n\n#include \"platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nenum BrotliWordTransformType {\n  BROTLI_TRANSFORM_IDENTITY = 0,\n  BROTLI_TRANSFORM_OMIT_LAST_1 = 1,\n  BROTLI_TRANSFORM_OMIT_LAST_2 = 2,\n  BROTLI_TRANSFORM_OMIT_LAST_3 = 3,\n  BROTLI_TRANSFORM_OMIT_LAST_4 = 4,\n  BROTLI_TRANSFORM_OMIT_LAST_5 = 5,\n  BROTLI_TRANSFORM_OMIT_LAST_6 = 6,\n  BROTLI_TRANSFORM_OMIT_LAST_7 = 7,\n  BROTLI_TRANSFORM_OMIT_LAST_8 = 8,\n  BROTLI_TRANSFORM_OMIT_LAST_9 = 9,\n  BROTLI_TRANSFORM_UPPERCASE_FIRST = 10,\n  BROTLI_TRANSFORM_UPPERCASE_ALL = 11,\n  BROTLI_TRANSFORM_OMIT_FIRST_1 = 12,\n  BROTLI_TRANSFORM_OMIT_FIRST_2 = 13,\n  BROTLI_TRANSFORM_OMIT_FIRST_3 = 14,\n  BROTLI_TRANSFORM_OMIT_FIRST_4 = 15,\n  BROTLI_TRANSFORM_OMIT_FIRST_5 = 16,\n  BROTLI_TRANSFORM_OMIT_FIRST_6 = 17,\n  BROTLI_TRANSFORM_OMIT_FIRST_7 = 18,\n  BROTLI_TRANSFORM_OMIT_FIRST_8 = 19,\n  BROTLI_TRANSFORM_OMIT_FIRST_9 = 20,\n  BROTLI_TRANSFORM_SHIFT_FIRST = 21,\n  BROTLI_TRANSFORM_SHIFT_ALL = 22,\n  BROTLI_NUM_TRANSFORM_TYPES  /* Counts transforms, not a transform itself. */\n};\n\n#define BROTLI_TRANSFORMS_MAX_CUT_OFF BROTLI_TRANSFORM_OMIT_LAST_9\n\ntypedef struct BrotliTransforms {\n  uint16_t prefix_suffix_size;\n  /* Last character must be null, so prefix_suffix_size must be at least 1. */\n  const uint8_t* prefix_suffix;\n  const uint16_t* prefix_suffix_map;\n  uint32_t num_transforms;\n  /* Each entry is a [prefix_id, transform, suffix_id] triplet. */\n  const uint8_t* transforms;\n  /* Shift for BROTLI_TRANSFORM_SHIFT_FIRST and BROTLI_TRANSFORM_SHIFT_ALL,\n     must be NULL if and only if no such transforms are present. */\n  const uint8_t* params;\n  /* Indices of transforms like [\"\", BROTLI_TRANSFORM_OMIT_LAST_#, \"\"].\n     0-th element corresponds to [\"\", BROTLI_TRANSFORM_IDENTITY, \"\"].\n     -1, if cut-off transform does not exist. */\n  int16_t cutOffTransforms[BROTLI_TRANSFORMS_MAX_CUT_OFF + 1];\n} BrotliTransforms;\n\n/* T is BrotliTransforms*; result is uint8_t. */\n#define BROTLI_TRANSFORM_PREFIX_ID(T, I) ((T)->transforms[((I) * 3) + 0])\n#define BROTLI_TRANSFORM_TYPE(T, I)      ((T)->transforms[((I) * 3) + 1])\n#define BROTLI_TRANSFORM_SUFFIX_ID(T, I) ((T)->transforms[((I) * 3) + 2])\n\n/* T is BrotliTransforms*; result is const uint8_t*. */\n#define BROTLI_TRANSFORM_PREFIX(T, I) (&(T)->prefix_suffix[ \\\n    (T)->prefix_suffix_map[BROTLI_TRANSFORM_PREFIX_ID(T, I)]])\n#define BROTLI_TRANSFORM_SUFFIX(T, I) (&(T)->prefix_suffix[ \\\n    (T)->prefix_suffix_map[BROTLI_TRANSFORM_SUFFIX_ID(T, I)]])\n\nBROTLI_COMMON_API const BrotliTransforms* BrotliGetTransforms(void);\n\nBROTLI_COMMON_API int BrotliTransformDictionaryWord(\n    uint8_t* dst, const uint8_t* word, int len,\n    const BrotliTransforms* transforms, int transform_idx);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_TRANSFORM_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/common/version.h",
    "content": "﻿/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Version definition. */\n\n#ifndef BROTLI_COMMON_VERSION_H_\n#define BROTLI_COMMON_VERSION_H_\n\n/* Compose 3 components into a single number. In a hexadecimal representation\n   B and C components occupy exactly 3 digits. */\n#define BROTLI_MAKE_HEX_VERSION(A, B, C) ((A << 24) | (B << 12) | C)\n\n/* Those macros should only be used when library is compiled together with\n   the client. If library is dynamically linked, use BrotliDecoderVersion and\n   BrotliEncoderVersion methods. */\n\n#define BROTLI_VERSION_MAJOR 1\n#define BROTLI_VERSION_MINOR 2\n#define BROTLI_VERSION_PATCH 0\n\n#define BROTLI_VERSION BROTLI_MAKE_HEX_VERSION(                     \\\n  BROTLI_VERSION_MAJOR, BROTLI_VERSION_MINOR, BROTLI_VERSION_PATCH)\n\n/* This macro is used by build system to produce Libtool-friendly soname. See\n   https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html\n   Version evolution rules:\n    - interfaces added (or change is compatible)      -> current+1:0:age+1\n    - interfaces removed (or changed is incompatible) -> current+1:0:0\n    - interfaces not changed                          -> current:revision+1:age\n */\n\n#define BROTLI_ABI_CURRENT  3\n#define BROTLI_ABI_REVISION 0\n#define BROTLI_ABI_AGE      2\n\n#if BROTLI_VERSION_MAJOR != (BROTLI_ABI_CURRENT - BROTLI_ABI_AGE)\n#error ABI/API version inconsistency\n#endif\n\n#if BROTLI_VERSION_MINOR != BROTLI_ABI_AGE\n#error ABI/API version inconsistency\n#endif\n\n#if BROTLI_VERSION_PATCH != BROTLI_ABI_REVISION\n#error ABI/API version inconsistency\n#endif\n\n#endif  /* BROTLI_COMMON_VERSION_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/bit_reader.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Bit reading helpers */\n\n#include \"bit_reader.h\"\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nconst BROTLI_MODEL(\"small\")\nbrotli_reg_t kBrotliBitMask[33] = {     0x00000000,\n    0x00000001, 0x00000003, 0x00000007, 0x0000000F,\n    0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,\n    0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,\n    0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,\n    0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,\n    0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,\n    0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,\n    0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF\n};\n\nvoid BrotliInitBitReader(BrotliBitReader* const br) {\n  br->val_ = 0;\n  br->bit_pos_ = 0;\n}\n\nBROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {\n  size_t aligned_read_mask = (sizeof(br->val_) >> 1) - 1;\n  /* Fixing alignment after unaligned BrotliFillWindow would result accumulator\n     overflow. If unalignment is caused by BrotliSafeReadBits, then there is\n     enough space in accumulator to fix alignment. */\n  if (BROTLI_UNALIGNED_READ_FAST) {\n    aligned_read_mask = 0;\n  }\n  if (BrotliGetAvailableBits(br) == 0) {\n    br->val_ = 0;\n    if (!BrotliPullByte(br)) {\n      return BROTLI_FALSE;\n    }\n  }\n\n  while ((((size_t)br->next_in) & aligned_read_mask) != 0) {\n    if (!BrotliPullByte(br)) {\n      /* If we consumed all the input, we don't care about the alignment. */\n      return BROTLI_TRUE;\n    }\n  }\n  return BROTLI_TRUE;\n}\n\nBROTLI_BOOL BrotliSafeReadBits32Slow(BrotliBitReader* const br,\n    brotli_reg_t n_bits, brotli_reg_t* val) {\n  brotli_reg_t low_val;\n  brotli_reg_t high_val;\n  BrotliBitReaderState memento;\n  BROTLI_DCHECK(n_bits <= 32);\n  BROTLI_DCHECK(n_bits > 24);\n  BrotliBitReaderSaveState(br, &memento);\n  if (!BrotliSafeReadBits(br, 16, &low_val) ||\n      !BrotliSafeReadBits(br, n_bits - 16, &high_val)) {\n    BrotliBitReaderRestoreState(br, &memento);\n    return BROTLI_FALSE;\n  }\n  *val = low_val | (high_val << 16);\n  return BROTLI_TRUE;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/bit_reader.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Bit reading helpers */\n\n#ifndef BROTLI_DEC_BIT_READER_H_\n#define BROTLI_DEC_BIT_READER_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1)\n\n/* 162 bits + 7 bytes */\n#define BROTLI_FAST_INPUT_SLACK 28\n\nBROTLI_INTERNAL extern const brotli_reg_t kBrotliBitMask[33];\n\nstatic BROTLI_INLINE brotli_reg_t BitMask(brotli_reg_t n) {\n  if (BROTLI_IS_CONSTANT(n) || BROTLI_HAS_UBFX) {\n    /* Masking with this expression turns to a single\n       \"Unsigned Bit Field Extract\" UBFX instruction on ARM. */\n    return ~(~((brotli_reg_t)0) << n);\n  } else {\n    return kBrotliBitMask[n];\n  }\n}\n\ntypedef struct {\n  brotli_reg_t val_;       /* pre-fetched bits */\n  brotli_reg_t bit_pos_;   /* current bit-reading position in val_ */\n  const uint8_t* next_in;  /* the byte we're reading from */\n  const uint8_t* guard_in; /* position from which \"fast-path\" is prohibited */\n  const uint8_t* last_in;  /* == next_in + avail_in */\n} BrotliBitReader;\n\ntypedef struct {\n  brotli_reg_t val_;\n  brotli_reg_t bit_pos_;\n  const uint8_t* next_in;\n  size_t avail_in;\n} BrotliBitReaderState;\n\n/* Initializes the BrotliBitReader fields. */\nBROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* br);\n\n/* Ensures that accumulator is not empty.\n   May consume up to sizeof(brotli_reg_t) - 1 bytes of input.\n   Returns BROTLI_FALSE if data is required but there is no input available.\n   For !BROTLI_UNALIGNED_READ_FAST this function also prepares bit reader for\n   aligned reading. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* br);\n\n/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden\n   the main code-path. Never called for RFC brotli streams, required only for\n   \"large-window\" mode and other extensions. */\nBROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow(\n    BrotliBitReader* br, brotli_reg_t n_bits, brotli_reg_t* val);\n\nstatic BROTLI_INLINE size_t\nBrotliBitReaderGetAvailIn(BrotliBitReader* const br) {\n  return (size_t)(br->last_in - br->next_in);\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderSaveState(\n    BrotliBitReader* const from, BrotliBitReaderState* to) {\n  to->val_ = from->val_;\n  to->bit_pos_ = from->bit_pos_;\n  to->next_in = from->next_in;\n  to->avail_in = BrotliBitReaderGetAvailIn(from);\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderSetInput(\n    BrotliBitReader* const br, const uint8_t* next_in, size_t avail_in) {\n  br->next_in = next_in;\n  br->last_in = (avail_in == 0) ? next_in : (next_in + avail_in);\n  if (avail_in + 1 > BROTLI_FAST_INPUT_SLACK) {\n    br->guard_in = next_in + (avail_in + 1 - BROTLI_FAST_INPUT_SLACK);\n  } else {\n    br->guard_in = next_in;\n  }\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderRestoreState(\n    BrotliBitReader* const to, BrotliBitReaderState* from) {\n  to->val_ = from->val_;\n  to->bit_pos_ = from->bit_pos_;\n  to->next_in = from->next_in;\n  BrotliBitReaderSetInput(to, from->next_in, from->avail_in);\n}\n\nstatic BROTLI_INLINE brotli_reg_t BrotliGetAvailableBits(\n    const BrotliBitReader* br) {\n  return br->bit_pos_;\n}\n\n/* Returns amount of unread bytes the bit reader still has buffered from the\n   BrotliInput, including whole bytes in br->val_. Result is capped with\n   maximal ring-buffer size (larger number won't be utilized anyway). */\nstatic BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {\n  static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS;\n  size_t avail_in = BrotliBitReaderGetAvailIn(br);\n  if (avail_in > kCap) return kCap;\n  return avail_in + (BrotliGetAvailableBits(br) >> 3);\n}\n\n/* Checks if there is at least |num| bytes left in the input ring-buffer\n   (excluding the bits remaining in br->val_). */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(\n    BrotliBitReader* const br) {\n  return TO_BROTLI_BOOL(br->next_in < br->guard_in);\n}\n\n/* Load more bits into accumulator. */\nstatic BROTLI_INLINE brotli_reg_t BrotliBitReaderLoadBits(brotli_reg_t val,\n                                                          brotli_reg_t new_bits,\n                                                          brotli_reg_t count,\n                                                          brotli_reg_t offset) {\n  BROTLI_DCHECK(\n      !((val >> offset) & ~new_bits & ~(~((brotli_reg_t)0) << count)));\n  (void)count;\n  return val | (new_bits << offset);\n}\n\n/* Guarantees that there are at least |n_bits| + 1 bits in accumulator.\n   Precondition: accumulator contains at least 1 bit.\n   |n_bits| should be in the range [1..24] for regular build. For portable\n   non-64-bit little-endian build only 16 bits are safe to request. */\nstatic BROTLI_INLINE void BrotliFillBitWindow(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n#if (BROTLI_64_BITS)\n  if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&\n      (n_bits <= 8)) {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 8) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          BROTLI_UNALIGNED_LOAD64LE(br->next_in), 56, bit_pos);\n      br->bit_pos_ = bit_pos + 56;\n      br->next_in += 7;\n    }\n  } else if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&\n             (n_bits <= 16)) {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 16) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          BROTLI_UNALIGNED_LOAD64LE(br->next_in), 48, bit_pos);\n      br->bit_pos_ = bit_pos + 48;\n      br->next_in += 6;\n    }\n  } else {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 32) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          (uint64_t)BROTLI_UNALIGNED_LOAD32LE(br->next_in), 32, bit_pos);\n      br->bit_pos_ = bit_pos + 32;\n      br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;\n    }\n  }\n#else\n  if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&\n      (n_bits <= 8)) {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 8) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          BROTLI_UNALIGNED_LOAD32LE(br->next_in), 24, bit_pos);\n      br->bit_pos_ = bit_pos + 24;\n      br->next_in += 3;\n    }\n  } else {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 16) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          (uint32_t)BROTLI_UNALIGNED_LOAD16LE(br->next_in), 16, bit_pos);\n      br->bit_pos_ = bit_pos + 16;\n      br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;\n    }\n  }\n#endif\n}\n\n/* Mostly like BrotliFillBitWindow, but guarantees only 16 bits and reads no\n   more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */\nstatic BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) {\n  BrotliFillBitWindow(br, 17);\n}\n\n/* Tries to pull one byte of input to accumulator.\n   Returns BROTLI_FALSE if there is no input available. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) {\n  if (br->next_in == br->last_in) {\n    return BROTLI_FALSE;\n  }\n  br->val_ = BrotliBitReaderLoadBits(br->val_,\n      (brotli_reg_t)*br->next_in, 8, br->bit_pos_);\n  br->bit_pos_ += 8;\n  ++br->next_in;\n  return BROTLI_TRUE;\n}\n\n/* Returns currently available bits.\n   The number of valid bits could be calculated by BrotliGetAvailableBits. */\nstatic BROTLI_INLINE brotli_reg_t BrotliGetBitsUnmasked(\n    BrotliBitReader* const br) {\n  return br->val_;\n}\n\n/* Like BrotliGetBits, but does not mask the result.\n   The result contains at least 16 valid bits. */\nstatic BROTLI_INLINE brotli_reg_t BrotliGet16BitsUnmasked(\n    BrotliBitReader* const br) {\n  BrotliFillBitWindow(br, 16);\n  return (brotli_reg_t)BrotliGetBitsUnmasked(br);\n}\n\n/* Returns the specified number of bits from |br| without advancing bit\n   position. */\nstatic BROTLI_INLINE brotli_reg_t BrotliGetBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  BrotliFillBitWindow(br, n_bits);\n  return BrotliGetBitsUnmasked(br) & BitMask(n_bits);\n}\n\n/* Tries to peek the specified amount of bits. Returns BROTLI_FALSE, if there\n   is not enough input. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliSafeGetBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  while (BrotliGetAvailableBits(br) < n_bits) {\n    if (!BrotliPullByte(br)) {\n      return BROTLI_FALSE;\n    }\n  }\n  *val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);\n  return BROTLI_TRUE;\n}\n\n/* Advances the bit pos by |n_bits|. */\nstatic BROTLI_INLINE void BrotliDropBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  br->bit_pos_ -= n_bits;\n  br->val_ >>= n_bits;\n}\n\n/* Make sure that there are no spectre bits in accumulator.\n   This is important for the cases when some bytes are skipped\n   (i.e. never placed into accumulator). */\nstatic BROTLI_INLINE void BrotliBitReaderNormalize(BrotliBitReader* br) {\n  /* Actually, it is enough to normalize when br->bit_pos_ == 0 */\n  if (br->bit_pos_ < (sizeof(brotli_reg_t) << 3u)) {\n    br->val_ &= (((brotli_reg_t)1) << br->bit_pos_) - 1;\n  }\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {\n  brotli_reg_t unused_bytes = BrotliGetAvailableBits(br) >> 3;\n  brotli_reg_t unused_bits = unused_bytes << 3;\n  br->next_in =\n      (unused_bytes == 0) ? br->next_in : (br->next_in - unused_bytes);\n  br->bit_pos_ -= unused_bits;\n  BrotliBitReaderNormalize(br);\n}\n\n/* Reads the specified number of bits from |br| and advances the bit pos.\n   Precondition: accumulator MUST contain at least |n_bits|. */\nstatic BROTLI_INLINE void BrotliTakeBits(BrotliBitReader* const br,\n                                         brotli_reg_t n_bits,\n                                         brotli_reg_t* val) {\n  *val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);\n  BROTLI_LOG((\"[BrotliTakeBits]  %d %d %d val: %6x\\n\",\n              (int)BrotliBitReaderGetAvailIn(br), (int)br->bit_pos_,\n              (int)n_bits, (int)*val));\n  BrotliDropBits(br, n_bits);\n}\n\n/* Reads the specified number of bits from |br| and advances the bit pos.\n   Assumes that there is enough input to perform BrotliFillBitWindow.\n   Up to 24 bits are allowed to be requested from this method. */\nstatic BROTLI_INLINE brotli_reg_t BrotliReadBits24(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  BROTLI_DCHECK(n_bits <= 24);\n  if (BROTLI_64_BITS || (n_bits <= 16)) {\n    brotli_reg_t val;\n    BrotliFillBitWindow(br, n_bits);\n    BrotliTakeBits(br, n_bits, &val);\n    return val;\n  } else {\n    brotli_reg_t low_val;\n    brotli_reg_t high_val;\n    BrotliFillBitWindow(br, 16);\n    BrotliTakeBits(br, 16, &low_val);\n    BrotliFillBitWindow(br, 8);\n    BrotliTakeBits(br, n_bits - 16, &high_val);\n    return low_val | (high_val << 16);\n  }\n}\n\n/* Same as BrotliReadBits24, but allows reading up to 32 bits. */\nstatic BROTLI_INLINE brotli_reg_t BrotliReadBits32(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  BROTLI_DCHECK(n_bits <= 32);\n  if (BROTLI_64_BITS || (n_bits <= 16)) {\n    brotli_reg_t val;\n    BrotliFillBitWindow(br, n_bits);\n    BrotliTakeBits(br, n_bits, &val);\n    return val;\n  } else {\n    brotli_reg_t low_val;\n    brotli_reg_t high_val;\n    BrotliFillBitWindow(br, 16);\n    BrotliTakeBits(br, 16, &low_val);\n    BrotliFillBitWindow(br, 16);\n    BrotliTakeBits(br, n_bits - 16, &high_val);\n    return low_val | (high_val << 16);\n  }\n}\n\n/* Tries to read the specified amount of bits. Returns BROTLI_FALSE, if there\n   is not enough input. |n_bits| MUST be positive.\n   Up to 24 bits are allowed to be requested from this method. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  BROTLI_DCHECK(n_bits <= 24);\n  while (BrotliGetAvailableBits(br) < n_bits) {\n    if (!BrotliPullByte(br)) {\n      return BROTLI_FALSE;\n    }\n  }\n  BrotliTakeBits(br, n_bits, val);\n  return BROTLI_TRUE;\n}\n\n/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  BROTLI_DCHECK(n_bits <= 32);\n  if (BROTLI_64_BITS || (n_bits <= 24)) {\n    while (BrotliGetAvailableBits(br) < n_bits) {\n      if (!BrotliPullByte(br)) {\n        return BROTLI_FALSE;\n      }\n    }\n    BrotliTakeBits(br, n_bits, val);\n    return BROTLI_TRUE;\n  } else {\n    return BrotliSafeReadBits32Slow(br, n_bits, val);\n  }\n}\n\n/* Advances the bit reader position to the next byte boundary and verifies\n   that any skipped bits are set to zero. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {\n  brotli_reg_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;\n  brotli_reg_t pad_bits = 0;\n  if (pad_bits_count != 0) {\n    BrotliTakeBits(br, pad_bits_count, &pad_bits);\n  }\n  BrotliBitReaderNormalize(br);\n  return TO_BROTLI_BOOL(pad_bits == 0);\n}\n\nstatic BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) {\n  /* Check detour is legal: accumulator must to be empty. */\n  BROTLI_DCHECK(br->bit_pos_ == 0);\n  BROTLI_DCHECK(br->val_ == 0);\n  br->next_in += num;\n}\n\n/* Copies remaining input bytes stored in the bit reader to the output. Value\n   |num| may not be larger than BrotliGetRemainingBytes. The bit reader must be\n   warmed up again after this. */\nstatic BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,\n                                          BrotliBitReader* br, size_t num) {\n  while (BrotliGetAvailableBits(br) >= 8 && num > 0) {\n    *dest = (uint8_t)BrotliGetBitsUnmasked(br);\n    BrotliDropBits(br, 8);\n    ++dest;\n    --num;\n  }\n  BrotliBitReaderNormalize(br);\n  if (num > 0) {\n    memcpy(dest, br->next_in, num);\n    BrotliDropBytes(br, num);\n  }\n}\n\nBROTLI_UNUSED_FUNCTION void BrotliBitReaderSuppressUnusedFunctions(void) {\n  BROTLI_UNUSED(&BrotliBitReaderSuppressUnusedFunctions);\n\n  BROTLI_UNUSED(&BrotliBitReaderGetAvailIn);\n  BROTLI_UNUSED(&BrotliBitReaderLoadBits);\n  BROTLI_UNUSED(&BrotliBitReaderRestoreState);\n  BROTLI_UNUSED(&BrotliBitReaderSaveState);\n  BROTLI_UNUSED(&BrotliBitReaderSetInput);\n  BROTLI_UNUSED(&BrotliBitReaderUnload);\n  BROTLI_UNUSED(&BrotliCheckInputAmount);\n  BROTLI_UNUSED(&BrotliCopyBytes);\n  BROTLI_UNUSED(&BrotliFillBitWindow16);\n  BROTLI_UNUSED(&BrotliGet16BitsUnmasked);\n  BROTLI_UNUSED(&BrotliGetBits);\n  BROTLI_UNUSED(&BrotliGetRemainingBytes);\n  BROTLI_UNUSED(&BrotliJumpToByteBoundary);\n  BROTLI_UNUSED(&BrotliReadBits24);\n  BROTLI_UNUSED(&BrotliReadBits32);\n  BROTLI_UNUSED(&BrotliSafeGetBits);\n  BROTLI_UNUSED(&BrotliSafeReadBits);\n  BROTLI_UNUSED(&BrotliSafeReadBits32);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_BIT_READER_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/dec_static_init.c",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"static_init.h\"\n\n#include \"../common/platform.h\"\n#include \"../common/static_init.h\"\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\n#include \"../common/dictionary.h\"\n#include \"prefix.h\"\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\nstatic BROTLI_BOOL DoBrotliDecoderStaticInit(void) {\n  BROTLI_BOOL ok = BrotliDecoderInitCmdLut(kCmdLut);\n  if (!ok) return BROTLI_FALSE;\n  return BROTLI_TRUE;\n}\n#endif  /* BROTLI_STATIC_INIT_NONE */\n\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)\nstatic BROTLI_BOOL kEarlyInitOk;\nstatic __attribute__((constructor)) void BrotliDecoderStaticInitEarly(void) {\n  kEarlyInitOk = DoBrotliDecoderStaticInit();\n}\n#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)\nstatic BROTLI_BOOL kLazyInitOk;\nvoid BrotliDecoderLazyStaticInitInner(void) {\n  kLazyInitOk = DoBrotliDecoderStaticInit();\n}\n#endif  /* BROTLI_STATIC_INIT_EARLY */\n\nBROTLI_BOOL BrotliDecoderEnsureStaticInit(void) {\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)\n  return BROTLI_TRUE;\n#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)\n  return kEarlyInitOk;\n#else\n  return kLazyInitOk;\n#endif\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/decode.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include <brotli/decode.h>\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"../common/shared_dictionary_internal.h\"\n#include \"../common/transform.h\"\n#include \"../common/version.h\"\n#include \"bit_reader.h\"\n#include \"huffman.h\"\n#include \"prefix.h\"\n#include \"state.h\"\n#include \"static_init.h\"\n\n#if defined(BROTLI_TARGET_NEON)\n#include <arm_neon.h>\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_FAILURE(CODE) (BROTLI_DUMP(), CODE)\n\n#define BROTLI_LOG_UINT(name)                                       \\\n  BROTLI_LOG((\"[%s] %s = %lu\\n\", __func__, #name, (unsigned long)(name)))\n#define BROTLI_LOG_ARRAY_INDEX(array_name, idx)                     \\\n  BROTLI_LOG((\"[%s] %s[%lu] = %lu\\n\", __func__, #array_name,        \\\n         (unsigned long)(idx), (unsigned long)array_name[idx]))\n\n#define HUFFMAN_TABLE_BITS 8U\n#define HUFFMAN_TABLE_MASK 0xFF\n\n/* We need the slack region for the following reasons:\n    - doing up to two 16-byte copies for fast backward copying\n    - inserting transformed dictionary word:\n        255 prefix + 32 base + 255 suffix */\nstatic const brotli_reg_t kRingBufferWriteAheadSlack = 542;\n\nstatic const BROTLI_MODEL(\"small\")\nuint8_t kCodeLengthCodeOrder[BROTLI_CODE_LENGTH_CODES] = {\n  1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n};\n\n/* Static prefix code for the complex code length code lengths. */\nstatic const BROTLI_MODEL(\"small\")\nuint8_t kCodeLengthPrefixLength[16] = {\n  2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nuint8_t kCodeLengthPrefixValue[16] = {\n  0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5,\n};\n\nBROTLI_BOOL BrotliDecoderSetParameter(\n    BrotliDecoderState* state, BrotliDecoderParameter p, uint32_t value) {\n  if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;\n  switch (p) {\n    case BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:\n      state->canny_ringbuffer_allocation = !!value ? 0 : 1;\n      return BROTLI_TRUE;\n\n    case BROTLI_DECODER_PARAM_LARGE_WINDOW:\n      state->large_window = TO_BROTLI_BOOL(!!value);\n      return BROTLI_TRUE;\n\n    default: return BROTLI_FALSE;\n  }\n}\n\nBrotliDecoderState* BrotliDecoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  BrotliDecoderState* state = 0;\n  if (!BrotliDecoderEnsureStaticInit()) {\n    BROTLI_DUMP();\n    return 0;\n  }\n  if (!alloc_func && !free_func) {\n    state = (BrotliDecoderState*)malloc(sizeof(BrotliDecoderState));\n  } else if (alloc_func && free_func) {\n    state = (BrotliDecoderState*)alloc_func(opaque, sizeof(BrotliDecoderState));\n  }\n  if (state == 0) {\n    BROTLI_DUMP();\n    return 0;\n  }\n  if (!BrotliDecoderStateInit(state, alloc_func, free_func, opaque)) {\n    BROTLI_DUMP();\n    if (!alloc_func && !free_func) {\n      free(state);\n    } else if (alloc_func && free_func) {\n      free_func(opaque, state);\n    }\n    return 0;\n  }\n  return state;\n}\n\n/* Deinitializes and frees BrotliDecoderState instance. */\nvoid BrotliDecoderDestroyInstance(BrotliDecoderState* state) {\n  if (!state) {\n    return;\n  } else {\n    brotli_free_func free_func = state->free_func;\n    void* opaque = state->memory_manager_opaque;\n    BrotliDecoderStateCleanup(state);\n    free_func(opaque, state);\n  }\n}\n\n/* Saves error code and converts it to BrotliDecoderResult. */\nstatic BROTLI_NOINLINE BrotliDecoderResult SaveErrorCode(\n    BrotliDecoderState* s, BrotliDecoderErrorCode e, size_t consumed_input) {\n  s->error_code = (int)e;\n  s->used_input += consumed_input;\n  if ((s->buffer_length != 0) && (s->br.next_in == s->br.last_in)) {\n    /* If internal buffer is depleted at last, reset it. */\n    s->buffer_length = 0;\n  }\n  switch (e) {\n    case BROTLI_DECODER_SUCCESS:\n      return BROTLI_DECODER_RESULT_SUCCESS;\n\n    case BROTLI_DECODER_NEEDS_MORE_INPUT:\n      return BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;\n\n    case BROTLI_DECODER_NEEDS_MORE_OUTPUT:\n      return BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;\n\n    default:\n      return BROTLI_DECODER_RESULT_ERROR;\n  }\n}\n\n/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for \"Large Window Brotli\".\n   Precondition: bit-reader accumulator has at least 8 bits. */\nstatic BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState* s,\n                                               BrotliBitReader* br) {\n  brotli_reg_t n;\n  BROTLI_BOOL large_window = s->large_window;\n  s->large_window = BROTLI_FALSE;\n  BrotliTakeBits(br, 1, &n);\n  if (n == 0) {\n    s->window_bits = 16;\n    return BROTLI_DECODER_SUCCESS;\n  }\n  BrotliTakeBits(br, 3, &n);\n  if (n != 0) {\n    s->window_bits = (17u + n) & 63u;\n    return BROTLI_DECODER_SUCCESS;\n  }\n  BrotliTakeBits(br, 3, &n);\n  if (n == 1) {\n    if (large_window) {\n      BrotliTakeBits(br, 1, &n);\n      if (n == 1) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);\n      }\n      s->large_window = BROTLI_TRUE;\n      return BROTLI_DECODER_SUCCESS;\n    } else {\n      return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);\n    }\n  }\n  if (n != 0) {\n    s->window_bits = (8u + n) & 63u;\n    return BROTLI_DECODER_SUCCESS;\n  }\n  s->window_bits = 17;\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {\n#if defined(BROTLI_TARGET_NEON)\n  vst1q_u8(dst, vld1q_u8(src));\n#else\n  uint32_t buffer[4];\n  memcpy(buffer, src, 16);\n  memcpy(dst, buffer, 16);\n#endif\n}\n\n/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */\nstatic BROTLI_NOINLINE BrotliDecoderErrorCode DecodeVarLenUint8(\n    BrotliDecoderState* s, BrotliBitReader* br, brotli_reg_t* value) {\n  brotli_reg_t bits;\n  switch (s->substate_decode_uint8) {\n    case BROTLI_STATE_DECODE_UINT8_NONE:\n      if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 1, &bits))) {\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if (bits == 0) {\n        *value = 0;\n        return BROTLI_DECODER_SUCCESS;\n      }\n    /* Fall through. */\n\n    case BROTLI_STATE_DECODE_UINT8_SHORT:\n      if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) {\n        s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_SHORT;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if (bits == 0) {\n        *value = 1;\n        s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;\n        return BROTLI_DECODER_SUCCESS;\n      }\n      /* Use output value as a temporary storage. It MUST be persisted. */\n      *value = bits;\n    /* Fall through. */\n\n    case BROTLI_STATE_DECODE_UINT8_LONG:\n      if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) {\n        s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_LONG;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      *value = ((brotli_reg_t)1U << *value) + bits;\n      s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;\n      return BROTLI_DECODER_SUCCESS;\n\n    default:\n      return\n          BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n  }\n}\n\n/* Decodes a metablock length and flags by reading 2 - 31 bits. */\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(\n    BrotliDecoderState* s, BrotliBitReader* br) {\n  brotli_reg_t bits;\n  int i;\n  for (;;) {\n    switch (s->substate_metablock_header) {\n      case BROTLI_STATE_METABLOCK_HEADER_NONE:\n        if (!BrotliSafeReadBits(br, 1, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        s->is_last_metablock = bits ? 1 : 0;\n        s->meta_block_remaining_len = 0;\n        s->is_uncompressed = 0;\n        s->is_metadata = 0;\n        if (!s->is_last_metablock) {\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;\n          break;\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_EMPTY;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_EMPTY:\n        if (!BrotliSafeReadBits(br, 1, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        if (bits) {\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n          return BROTLI_DECODER_SUCCESS;\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_NIBBLES:\n        if (!BrotliSafeReadBits(br, 2, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        s->size_nibbles = (uint8_t)(bits + 4);\n        s->loop_counter = 0;\n        if (bits == 3) {\n          s->is_metadata = 1;\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_RESERVED;\n          break;\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_SIZE;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_SIZE:\n        i = s->loop_counter;\n        for (; i < (int)s->size_nibbles; ++i) {\n          if (!BrotliSafeReadBits(br, 4, &bits)) {\n            s->loop_counter = i;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 4 &&\n              bits == 0) {\n            return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE);\n          }\n          s->meta_block_remaining_len |= (int)(bits << (i * 4));\n        }\n        s->substate_metablock_header =\n            BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED:\n        if (!s->is_last_metablock) {\n          if (!BrotliSafeReadBits(br, 1, &bits)) {\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          s->is_uncompressed = bits ? 1 : 0;\n        }\n        ++s->meta_block_remaining_len;\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n        return BROTLI_DECODER_SUCCESS;\n\n      case BROTLI_STATE_METABLOCK_HEADER_RESERVED:\n        if (!BrotliSafeReadBits(br, 1, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        if (bits != 0) {\n          return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_RESERVED);\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_BYTES:\n        if (!BrotliSafeReadBits(br, 2, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        if (bits == 0) {\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n          return BROTLI_DECODER_SUCCESS;\n        }\n        s->size_nibbles = (uint8_t)bits;\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_METADATA:\n        i = s->loop_counter;\n        for (; i < (int)s->size_nibbles; ++i) {\n          if (!BrotliSafeReadBits(br, 8, &bits)) {\n            s->loop_counter = i;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 1 &&\n              bits == 0) {\n            return BROTLI_FAILURE(\n                BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE);\n          }\n          s->meta_block_remaining_len |= (int)(bits << (i * 8));\n        }\n        ++s->meta_block_remaining_len;\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n        return BROTLI_DECODER_SUCCESS;\n\n      default:\n        return\n            BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n    }\n  }\n}\n\n/* Decodes the Huffman code.\n   This method doesn't read data from the bit reader, BUT drops the amount of\n   bits that correspond to the decoded symbol.\n   bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */\nstatic BROTLI_INLINE brotli_reg_t DecodeSymbol(brotli_reg_t bits,\n                                               const HuffmanCode* table,\n                                               BrotliBitReader* br) {\n  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, bits & HUFFMAN_TABLE_MASK);\n  if (BROTLI_HC_FAST_LOAD_BITS(table) > HUFFMAN_TABLE_BITS) {\n    brotli_reg_t nbits = BROTLI_HC_FAST_LOAD_BITS(table) - HUFFMAN_TABLE_BITS;\n    BrotliDropBits(br, HUFFMAN_TABLE_BITS);\n    BROTLI_HC_ADJUST_TABLE_INDEX(table,\n        BROTLI_HC_FAST_LOAD_VALUE(table) +\n        ((bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits)));\n  }\n  BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));\n  return BROTLI_HC_FAST_LOAD_VALUE(table);\n}\n\n/* Reads and decodes the next Huffman code from bit-stream.\n   This method peeks 16 bits of input and drops 0 - 15 of them. */\nstatic BROTLI_INLINE brotli_reg_t ReadSymbol(const HuffmanCode* table,\n                                             BrotliBitReader* br) {\n  return DecodeSymbol(BrotliGet16BitsUnmasked(br), table, br);\n}\n\n/* Same as DecodeSymbol, but it is known that there is less than 15 bits of\n   input are currently available. */\nstatic BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(\n    const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {\n  brotli_reg_t val;\n  brotli_reg_t available_bits = BrotliGetAvailableBits(br);\n  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n  if (available_bits == 0) {\n    if (BROTLI_HC_FAST_LOAD_BITS(table) == 0) {\n      *result = BROTLI_HC_FAST_LOAD_VALUE(table);\n      return BROTLI_TRUE;\n    }\n    return BROTLI_FALSE;  /* No valid bits at all. */\n  }\n  val = BrotliGetBitsUnmasked(br);\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, val & HUFFMAN_TABLE_MASK);\n  if (BROTLI_HC_FAST_LOAD_BITS(table) <= HUFFMAN_TABLE_BITS) {\n    if (BROTLI_HC_FAST_LOAD_BITS(table) <= available_bits) {\n      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));\n      *result = BROTLI_HC_FAST_LOAD_VALUE(table);\n      return BROTLI_TRUE;\n    } else {\n      return BROTLI_FALSE;  /* Not enough bits for the first level. */\n    }\n  }\n  if (available_bits <= HUFFMAN_TABLE_BITS) {\n    return BROTLI_FALSE;  /* Not enough bits to move to the second level. */\n  }\n\n  /* Speculatively drop HUFFMAN_TABLE_BITS. */\n  val = (val & BitMask(BROTLI_HC_FAST_LOAD_BITS(table))) >> HUFFMAN_TABLE_BITS;\n  available_bits -= HUFFMAN_TABLE_BITS;\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + val);\n  if (available_bits < BROTLI_HC_FAST_LOAD_BITS(table)) {\n    return BROTLI_FALSE;  /* Not enough bits for the second level. */\n  }\n\n  BrotliDropBits(br, HUFFMAN_TABLE_BITS + BROTLI_HC_FAST_LOAD_BITS(table));\n  *result = BROTLI_HC_FAST_LOAD_VALUE(table);\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadSymbol(\n    const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {\n  brotli_reg_t val;\n  if (BROTLI_PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) {\n    *result = DecodeSymbol(val, table, br);\n    return BROTLI_TRUE;\n  }\n  return SafeDecodeSymbol(table, br, result);\n}\n\n/* Makes a look-up in first level Huffman table. Peeks 8 bits. */\nstatic BROTLI_INLINE void PreloadSymbol(int safe,\n                                        const HuffmanCode* table,\n                                        BrotliBitReader* br,\n                                        brotli_reg_t* bits,\n                                        brotli_reg_t* value) {\n  if (safe) {\n    return;\n  }\n  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, BrotliGetBits(br, HUFFMAN_TABLE_BITS));\n  *bits = BROTLI_HC_FAST_LOAD_BITS(table);\n  *value = BROTLI_HC_FAST_LOAD_VALUE(table);\n}\n\n/* Decodes the next Huffman code using data prepared by PreloadSymbol.\n   Reads 0 - 15 bits. Also peeks 8 following bits. */\nstatic BROTLI_INLINE brotli_reg_t ReadPreloadedSymbol(const HuffmanCode* table,\n                                                  BrotliBitReader* br,\n                                                  brotli_reg_t* bits,\n                                                  brotli_reg_t* value) {\n  brotli_reg_t result = *value;\n  if (BROTLI_PREDICT_FALSE(*bits > HUFFMAN_TABLE_BITS)) {\n    brotli_reg_t val = BrotliGet16BitsUnmasked(br);\n    const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value;\n    brotli_reg_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS));\n    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(ext);\n    BrotliDropBits(br, HUFFMAN_TABLE_BITS);\n    BROTLI_HC_ADJUST_TABLE_INDEX(ext, (val >> HUFFMAN_TABLE_BITS) & mask);\n    BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(ext));\n    result = BROTLI_HC_FAST_LOAD_VALUE(ext);\n  } else {\n    BrotliDropBits(br, *bits);\n  }\n  PreloadSymbol(0, table, br, bits, value);\n  return result;\n}\n\n/* Reads up to limit symbols from br and copies them into ringbuffer,\n   starting from pos. Caller must ensure that there is enough space\n   for the write. Returns the amount of symbols actually copied. */\nstatic BROTLI_INLINE int BrotliCopyPreloadedSymbolsToU8(const HuffmanCode* table,\n                                                        BrotliBitReader* br,\n                                                        brotli_reg_t* bits,\n                                                        brotli_reg_t* value,\n                                                        uint8_t* ringbuffer,\n                                                        int pos,\n                                                        const int limit) {\n  /* Calculate range where CheckInputAmount is always true.\n     Start with the number of bytes we can read. */\n  int64_t new_lim = br->guard_in - br->next_in;\n  /* Convert to bits, since symbols use variable number of bits. */\n  new_lim *= 8;\n  /* At most 15 bits per symbol, so this is safe. */\n  new_lim /= 15;\n  const int kMaximalOverread = 4;\n  int pos_limit = limit;\n  int copies = 0;\n  if ((new_lim - kMaximalOverread) <= limit) {\n    // Safe cast, since new_lim is already < num_steps\n    pos_limit = (int)(new_lim - kMaximalOverread);\n  }\n  if (pos_limit < 0) {\n    pos_limit = 0;\n  }\n  copies = pos_limit;\n  pos_limit += pos;\n  /* Fast path, caller made sure it is safe to write,\n     we verified that is is safe to read. */\n  for (; pos < pos_limit; pos++) {\n    BROTLI_DCHECK(BrotliCheckInputAmount(br));\n    ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol(table, br, bits, value);\n    BROTLI_LOG_ARRAY_INDEX(ringbuffer, pos);\n  }\n  /* Do the remainder, caller made sure it is safe to write,\n     we need to bverify that it is safe to read. */\n  while (BrotliCheckInputAmount(br) && copies < limit) {\n    ringbuffer[pos] = (uint8_t)ReadPreloadedSymbol(table, br, bits, value);\n    BROTLI_LOG_ARRAY_INDEX(ringbuffer, pos);\n    pos++;\n    copies++;\n  }\n  return copies;\n}\n\nstatic BROTLI_INLINE brotli_reg_t Log2Floor(brotli_reg_t x) {\n  brotli_reg_t result = 0;\n  while (x) {\n    x >>= 1;\n    ++result;\n  }\n  return result;\n}\n\n/* Reads (s->symbol + 1) symbols.\n   Totally 1..4 symbols are read, 1..11 bits each.\n   The list of symbols MUST NOT contain duplicates. */\nstatic BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(\n    brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit,\n    BrotliDecoderState* s) {\n  /* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  brotli_reg_t max_bits = Log2Floor(alphabet_size_max - 1);\n  brotli_reg_t i = h->sub_loop_counter;\n  brotli_reg_t num_symbols = h->symbol;\n  while (i <= num_symbols) {\n    brotli_reg_t v;\n    if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {\n      h->sub_loop_counter = i;\n      h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;\n      return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    }\n    if (v >= alphabet_size_limit) {\n      return\n          BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);\n    }\n    h->symbols_lists_array[i] = (uint16_t)v;\n    BROTLI_LOG_UINT(h->symbols_lists_array[i]);\n    ++i;\n  }\n\n  for (i = 0; i < num_symbols; ++i) {\n    brotli_reg_t k = i + 1;\n    for (; k <= num_symbols; ++k) {\n      if (h->symbols_lists_array[i] == h->symbols_lists_array[k]) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);\n      }\n    }\n  }\n\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Process single decoded symbol code length:\n    A) reset the repeat variable\n    B) remember code length (if it is not 0)\n    C) extend corresponding index-chain\n    D) reduce the Huffman space\n    E) update the histogram */\nstatic BROTLI_INLINE void ProcessSingleCodeLength(brotli_reg_t code_len,\n    brotli_reg_t* symbol, brotli_reg_t* repeat, brotli_reg_t* space,\n    brotli_reg_t* prev_code_len, uint16_t* symbol_lists,\n    uint16_t* code_length_histo, int* next_symbol) {\n  *repeat = 0;\n  if (code_len != 0) {  /* code_len == 1..15 */\n    symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol);\n    next_symbol[code_len] = (int)(*symbol);\n    *prev_code_len = code_len;\n    *space -= 32768U >> code_len;\n    code_length_histo[code_len]++;\n    BROTLI_LOG((\"[ReadHuffmanCode] code_length[%d] = %d\\n\",\n        (int)*symbol, (int)code_len));\n  }\n  (*symbol)++;\n}\n\n/* Process repeated symbol code length.\n    A) Check if it is the extension of previous repeat sequence; if the decoded\n       value is not BROTLI_REPEAT_PREVIOUS_CODE_LENGTH, then it is a new\n       symbol-skip\n    B) Update repeat variable\n    C) Check if operation is feasible (fits alphabet)\n    D) For each symbol do the same operations as in ProcessSingleCodeLength\n\n   PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or\n                 code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */\nstatic BROTLI_INLINE void ProcessRepeatedCodeLength(brotli_reg_t code_len,\n    brotli_reg_t repeat_delta, brotli_reg_t alphabet_size, brotli_reg_t* symbol,\n    brotli_reg_t* repeat, brotli_reg_t* space, brotli_reg_t* prev_code_len,\n    brotli_reg_t* repeat_code_len, uint16_t* symbol_lists,\n    uint16_t* code_length_histo, int* next_symbol) {\n  brotli_reg_t old_repeat;\n  brotli_reg_t extra_bits = 3;  /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */\n  brotli_reg_t new_len = 0;  /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */\n  if (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {\n    new_len = *prev_code_len;\n    extra_bits = 2;\n  }\n  if (*repeat_code_len != new_len) {\n    *repeat = 0;\n    *repeat_code_len = new_len;\n  }\n  old_repeat = *repeat;\n  if (*repeat > 0) {\n    *repeat -= 2;\n    *repeat <<= extra_bits;\n  }\n  *repeat += repeat_delta + 3U;\n  repeat_delta = *repeat - old_repeat;\n  if (*symbol + repeat_delta > alphabet_size) {\n    BROTLI_DUMP();\n    *symbol = alphabet_size;\n    *space = 0xFFFFF;\n    return;\n  }\n  BROTLI_LOG((\"[ReadHuffmanCode] code_length[%d..%d] = %d\\n\",\n      (int)*symbol, (int)(*symbol + repeat_delta - 1), (int)*repeat_code_len));\n  if (*repeat_code_len != 0) {\n    brotli_reg_t last = *symbol + repeat_delta;\n    int next = next_symbol[*repeat_code_len];\n    do {\n      symbol_lists[next] = (uint16_t)*symbol;\n      next = (int)*symbol;\n    } while (++(*symbol) != last);\n    next_symbol[*repeat_code_len] = next;\n    *space -= repeat_delta << (15 - *repeat_code_len);\n    code_length_histo[*repeat_code_len] =\n        (uint16_t)(code_length_histo[*repeat_code_len] + repeat_delta);\n  } else {\n    *symbol += repeat_delta;\n  }\n}\n\n/* Reads and decodes symbol codelengths. */\nstatic BrotliDecoderErrorCode ReadSymbolCodeLengths(\n    brotli_reg_t alphabet_size, BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  brotli_reg_t symbol = h->symbol;\n  brotli_reg_t repeat = h->repeat;\n  brotli_reg_t space = h->space;\n  brotli_reg_t prev_code_len = h->prev_code_len;\n  brotli_reg_t repeat_code_len = h->repeat_code_len;\n  uint16_t* symbol_lists = h->symbol_lists;\n  uint16_t* code_length_histo = h->code_length_histo;\n  int* next_symbol = h->next_symbol;\n  if (!BrotliWarmupBitReader(br)) {\n    return BROTLI_DECODER_NEEDS_MORE_INPUT;\n  }\n  while (symbol < alphabet_size && space > 0) {\n    const HuffmanCode* p = h->table;\n    brotli_reg_t code_len;\n    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);\n    if (!BrotliCheckInputAmount(br)) {\n      h->symbol = symbol;\n      h->repeat = repeat;\n      h->prev_code_len = prev_code_len;\n      h->repeat_code_len = repeat_code_len;\n      h->space = space;\n      return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    }\n    BrotliFillBitWindow16(br);\n    BROTLI_HC_ADJUST_TABLE_INDEX(p, BrotliGetBitsUnmasked(br) &\n        BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));\n    BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));  /* Use 1..5 bits. */\n    code_len = BROTLI_HC_FAST_LOAD_VALUE(p);  /* code_len == 0..17 */\n    if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {\n      ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,\n          &prev_code_len, symbol_lists, code_length_histo, next_symbol);\n    } else {  /* code_len == 16..17, extra_bits == 2..3 */\n      brotli_reg_t extra_bits =\n          (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) ? 2 : 3;\n      brotli_reg_t repeat_delta =\n          BrotliGetBitsUnmasked(br) & BitMask(extra_bits);\n      BrotliDropBits(br, extra_bits);\n      ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,\n          &symbol, &repeat, &space, &prev_code_len, &repeat_code_len,\n          symbol_lists, code_length_histo, next_symbol);\n    }\n  }\n  h->space = space;\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic BrotliDecoderErrorCode SafeReadSymbolCodeLengths(\n    brotli_reg_t alphabet_size, BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  BROTLI_BOOL get_byte = BROTLI_FALSE;\n  while (h->symbol < alphabet_size && h->space > 0) {\n    const HuffmanCode* p = h->table;\n    brotli_reg_t code_len;\n    brotli_reg_t available_bits;\n    brotli_reg_t bits = 0;\n    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);\n    if (get_byte && !BrotliPullByte(br)) return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    get_byte = BROTLI_FALSE;\n    available_bits = BrotliGetAvailableBits(br);\n    if (available_bits != 0) {\n      bits = (uint32_t)BrotliGetBitsUnmasked(br);\n    }\n    BROTLI_HC_ADJUST_TABLE_INDEX(p,\n        bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));\n    if (BROTLI_HC_FAST_LOAD_BITS(p) > available_bits) {\n      get_byte = BROTLI_TRUE;\n      continue;\n    }\n    code_len = BROTLI_HC_FAST_LOAD_VALUE(p);  /* code_len == 0..17 */\n    if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {\n      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));\n      ProcessSingleCodeLength(code_len, &h->symbol, &h->repeat, &h->space,\n          &h->prev_code_len, h->symbol_lists, h->code_length_histo,\n          h->next_symbol);\n    } else {  /* code_len == 16..17, extra_bits == 2..3 */\n      brotli_reg_t extra_bits = code_len - 14U;\n      brotli_reg_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) &\n          BitMask(extra_bits);\n      if (available_bits < BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits) {\n        get_byte = BROTLI_TRUE;\n        continue;\n      }\n      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits);\n      ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,\n          &h->symbol, &h->repeat, &h->space, &h->prev_code_len,\n          &h->repeat_code_len, h->symbol_lists, h->code_length_histo,\n          h->next_symbol);\n    }\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Reads and decodes 15..18 codes using static prefix code.\n   Each code is 2..4 bits long. In total 30..72 bits are used. */\nstatic BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  brotli_reg_t num_codes = h->repeat;\n  brotli_reg_t space = h->space;\n  brotli_reg_t i = h->sub_loop_counter;\n  for (; i < BROTLI_CODE_LENGTH_CODES; ++i) {\n    const uint8_t code_len_idx = kCodeLengthCodeOrder[i];\n    brotli_reg_t ix;\n    brotli_reg_t v;\n    if (BROTLI_PREDICT_FALSE(!BrotliSafeGetBits(br, 4, &ix))) {\n      brotli_reg_t available_bits = BrotliGetAvailableBits(br);\n      if (available_bits != 0) {\n        ix = BrotliGetBitsUnmasked(br) & 0xF;\n      } else {\n        ix = 0;\n      }\n      if (kCodeLengthPrefixLength[ix] > available_bits) {\n        h->sub_loop_counter = i;\n        h->repeat = num_codes;\n        h->space = space;\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n    }\n    v = kCodeLengthPrefixValue[ix];\n    BrotliDropBits(br, kCodeLengthPrefixLength[ix]);\n    h->code_length_code_lengths[code_len_idx] = (uint8_t)v;\n    BROTLI_LOG_ARRAY_INDEX(h->code_length_code_lengths, code_len_idx);\n    if (v != 0) {\n      space = space - (32U >> v);\n      ++num_codes;\n      ++h->code_length_histo[v];\n      if (space - 1U >= 32U) {\n        /* space is 0 or wrapped around. */\n        break;\n      }\n    }\n  }\n  if (!(num_codes == 1 || space == 0)) {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CL_SPACE);\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Decodes the Huffman tables.\n   There are 2 scenarios:\n    A) Huffman code contains only few symbols (1..4). Those symbols are read\n       directly; their code lengths are defined by the number of symbols.\n       For this scenario 4 - 49 bits will be read.\n\n    B) 2-phase decoding:\n    B.1) Small Huffman table is decoded; it is specified with code lengths\n         encoded with predefined entropy code. 32 - 74 bits are used.\n    B.2) Decoded table is used to decode code lengths of symbols in resulting\n         Huffman table. In worst case 3520 bits are read. */\nstatic BrotliDecoderErrorCode ReadHuffmanCode(brotli_reg_t alphabet_size_max,\n                                              brotli_reg_t alphabet_size_limit,\n                                              HuffmanCode* table,\n                                              brotli_reg_t* opt_table_size,\n                                              BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  /* State machine. */\n  for (;;) {\n    switch (h->substate_huffman) {\n      case BROTLI_STATE_HUFFMAN_NONE:\n        if (!BrotliSafeReadBits(br, 2, &h->sub_loop_counter)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        BROTLI_LOG_UINT(h->sub_loop_counter);\n        /* The value is used as follows:\n           1 for simple code;\n           0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */\n        if (h->sub_loop_counter != 1) {\n          h->space = 32;\n          h->repeat = 0;  /* num_codes */\n          memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo[0]) *\n              (BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1));\n          memset(&h->code_length_code_lengths[0], 0,\n              sizeof(h->code_length_code_lengths));\n          h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;\n          continue;\n        }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:\n        /* Read symbols, codes & code lengths directly. */\n        if (!BrotliSafeReadBits(br, 2, &h->symbol)) {  /* num_symbols */\n          h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        h->sub_loop_counter = 0;\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {\n        BrotliDecoderErrorCode result =\n            ReadSimpleHuffmanSymbols(alphabet_size_max, alphabet_size_limit, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {\n        brotli_reg_t table_size;\n        if (h->symbol == 3) {\n          brotli_reg_t bits;\n          if (!BrotliSafeReadBits(br, 1, &bits)) {\n            h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          h->symbol += bits;\n        }\n        BROTLI_LOG_UINT(h->symbol);\n        table_size = BrotliBuildSimpleHuffmanTable(table, HUFFMAN_TABLE_BITS,\n                                                   h->symbols_lists_array,\n                                                   (uint32_t)h->symbol);\n        if (opt_table_size) {\n          *opt_table_size = table_size;\n        }\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;\n        return BROTLI_DECODER_SUCCESS;\n      }\n\n      /* Decode Huffman-coded code lengths. */\n      case BROTLI_STATE_HUFFMAN_COMPLEX: {\n        brotli_reg_t i;\n        BrotliDecoderErrorCode result = ReadCodeLengthCodeLengths(s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n        BrotliBuildCodeLengthsHuffmanTable(h->table,\n                                           h->code_length_code_lengths,\n                                           h->code_length_histo);\n        memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo));\n        for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) {\n          h->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);\n          h->symbol_lists[h->next_symbol[i]] = 0xFFFF;\n        }\n\n        h->symbol = 0;\n        h->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;\n        h->repeat = 0;\n        h->repeat_code_len = 0;\n        h->space = 32768;\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {\n        brotli_reg_t table_size;\n        BrotliDecoderErrorCode result = ReadSymbolCodeLengths(\n            alphabet_size_limit, s);\n        if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {\n          result = SafeReadSymbolCodeLengths(alphabet_size_limit, s);\n        }\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n\n        if (h->space != 0) {\n          BROTLI_LOG((\"[ReadHuffmanCode] space = %d\\n\", (int)h->space));\n          return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);\n        }\n        table_size = BrotliBuildHuffmanTable(\n            table, HUFFMAN_TABLE_BITS, h->symbol_lists, h->code_length_histo);\n        if (opt_table_size) {\n          *opt_table_size = table_size;\n        }\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;\n        return BROTLI_DECODER_SUCCESS;\n      }\n\n      default:\n        return\n            BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n    }\n  }\n}\n\n/* Decodes a block length by reading 3..39 bits. */\nstatic BROTLI_INLINE brotli_reg_t ReadBlockLength(const HuffmanCode* table,\n                                                  BrotliBitReader* br) {\n  brotli_reg_t code;\n  brotli_reg_t nbits;\n  code = ReadSymbol(table, br);\n  nbits = _kBrotliPrefixCodeRanges[code].nbits;  /* nbits == 2..24 */\n  return _kBrotliPrefixCodeRanges[code].offset + BrotliReadBits24(br, nbits);\n}\n\n/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then\n   reading can't be continued with ReadBlockLength. */\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(\n    BrotliDecoderState* s, brotli_reg_t* result, const HuffmanCode* table,\n    BrotliBitReader* br) {\n  brotli_reg_t index;\n  if (s->substate_read_block_length == BROTLI_STATE_READ_BLOCK_LENGTH_NONE) {\n    if (!SafeReadSymbol(table, br, &index)) {\n      return BROTLI_FALSE;\n    }\n  } else {\n    index = s->block_length_index;\n  }\n  {\n    brotli_reg_t bits;\n    brotli_reg_t nbits = _kBrotliPrefixCodeRanges[index].nbits;\n    brotli_reg_t offset = _kBrotliPrefixCodeRanges[index].offset;\n    if (!BrotliSafeReadBits(br, nbits, &bits)) {\n      s->block_length_index = index;\n      s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;\n      return BROTLI_FALSE;\n    }\n    *result = offset + bits;\n    s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;\n    return BROTLI_TRUE;\n  }\n}\n\n/* Transform:\n    1) initialize list L with values 0, 1,... 255\n    2) For each input element X:\n    2.1) let Y = L[X]\n    2.2) remove X-th element from L\n    2.3) prepend Y to L\n    2.4) append Y to output\n\n   In most cases max(Y) <= 7, so most of L remains intact.\n   To reduce the cost of initialization, we reuse L, remember the upper bound\n   of Y values, and reinitialize only first elements in L.\n\n   Most of input values are 0 and 1. To reduce number of branches, we replace\n   inner for loop with do-while. */\nstatic BROTLI_NOINLINE void InverseMoveToFrontTransform(\n    uint8_t* v, brotli_reg_t v_len, BrotliDecoderState* state) {\n  /* Reinitialize elements that could have been changed. */\n  brotli_reg_t i = 1;\n  brotli_reg_t upper_bound = state->mtf_upper_bound;\n  uint32_t* mtf = &state->mtf[1];  /* Make mtf[-1] addressable. */\n  uint8_t* mtf_u8 = (uint8_t*)mtf;\n  /* Load endian-aware constant. */\n  const uint8_t b0123[4] = {0, 1, 2, 3};\n  uint32_t pattern;\n  memcpy(&pattern, &b0123, 4);\n\n  /* Initialize list using 4 consequent values pattern. */\n  mtf[0] = pattern;\n  do {\n    pattern += 0x04040404;  /* Advance all 4 values by 4. */\n    mtf[i] = pattern;\n    i++;\n  } while (i <= upper_bound);\n\n  /* Transform the input. */\n  upper_bound = 0;\n  for (i = 0; i < v_len; ++i) {\n    int index = v[i];\n    uint8_t value = mtf_u8[index];\n    upper_bound |= v[i];\n    v[i] = value;\n    mtf_u8[-1] = value;\n    do {\n      index--;\n      mtf_u8[index + 1] = mtf_u8[index];\n    } while (index >= 0);\n  }\n  /* Remember amount of elements to be reinitialized. */\n  state->mtf_upper_bound = upper_bound >> 2;\n}\n\n/* Decodes a series of Huffman table using ReadHuffmanCode function. */\nstatic BrotliDecoderErrorCode HuffmanTreeGroupDecode(\n    HuffmanTreeGroup* group, BrotliDecoderState* s) {\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  if (h->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {\n    h->next = group->codes;\n    h->htree_index = 0;\n    h->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;\n  }\n  while (h->htree_index < group->num_htrees) {\n    brotli_reg_t table_size;\n    BrotliDecoderErrorCode result = ReadHuffmanCode(group->alphabet_size_max,\n        group->alphabet_size_limit, h->next, &table_size, s);\n    if (result != BROTLI_DECODER_SUCCESS) return result;\n    group->htrees[h->htree_index] = h->next;\n    h->next += table_size;\n    ++h->htree_index;\n  }\n  h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Decodes a context map.\n   Decoding is done in 4 phases:\n    1) Read auxiliary information (6..16 bits) and allocate memory.\n       In case of trivial context map, decoding is finished at this phase.\n    2) Decode Huffman table using ReadHuffmanCode function.\n       This table will be used for reading context map items.\n    3) Read context map items; \"0\" values could be run-length encoded.\n    4) Optionally, apply InverseMoveToFront transform to the resulting map. */\nstatic BrotliDecoderErrorCode DecodeContextMap(brotli_reg_t context_map_size,\n                                               brotli_reg_t* num_htrees,\n                                               uint8_t** context_map_arg,\n                                               BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n\n  switch ((int)h->substate_context_map) {\n    case BROTLI_STATE_CONTEXT_MAP_NONE:\n      result = DecodeVarLenUint8(s, br, num_htrees);\n      if (result != BROTLI_DECODER_SUCCESS) {\n        return result;\n      }\n      (*num_htrees)++;\n      h->context_index = 0;\n      BROTLI_LOG_UINT(context_map_size);\n      BROTLI_LOG_UINT(*num_htrees);\n      *context_map_arg =\n          (uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)context_map_size);\n      if (*context_map_arg == 0) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP);\n      }\n      if (*num_htrees <= 1) {\n        memset(*context_map_arg, 0, (size_t)context_map_size);\n        return BROTLI_DECODER_SUCCESS;\n      }\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {\n      brotli_reg_t bits;\n      /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe\n         to peek 4 bits ahead. */\n      if (!BrotliSafeGetBits(br, 5, &bits)) {\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if ((bits & 1) != 0) { /* Use RLE for zeros. */\n        h->max_run_length_prefix = (bits >> 1) + 1;\n        BrotliDropBits(br, 5);\n      } else {\n        h->max_run_length_prefix = 0;\n        BrotliDropBits(br, 1);\n      }\n      BROTLI_LOG_UINT(h->max_run_length_prefix);\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;\n    }\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: {\n      brotli_reg_t alphabet_size = *num_htrees + h->max_run_length_prefix;\n      result = ReadHuffmanCode(alphabet_size, alphabet_size,\n                               h->context_map_table, NULL, s);\n      if (result != BROTLI_DECODER_SUCCESS) return result;\n      h->code = 0xFFFF;\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;\n    }\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_DECODE: {\n      brotli_reg_t context_index = h->context_index;\n      brotli_reg_t max_run_length_prefix = h->max_run_length_prefix;\n      uint8_t* context_map = *context_map_arg;\n      brotli_reg_t code = h->code;\n      BROTLI_BOOL skip_preamble = (code != 0xFFFF);\n      while (context_index < context_map_size || skip_preamble) {\n        if (!skip_preamble) {\n          if (!SafeReadSymbol(h->context_map_table, br, &code)) {\n            h->code = 0xFFFF;\n            h->context_index = context_index;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          BROTLI_LOG_UINT(code);\n\n          if (code == 0) {\n            context_map[context_index++] = 0;\n            continue;\n          }\n          if (code > max_run_length_prefix) {\n            context_map[context_index++] =\n                (uint8_t)(code - max_run_length_prefix);\n            continue;\n          }\n        } else {\n          skip_preamble = BROTLI_FALSE;\n        }\n        /* RLE sub-stage. */\n        {\n          brotli_reg_t reps;\n          if (!BrotliSafeReadBits(br, code, &reps)) {\n            h->code = code;\n            h->context_index = context_index;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          reps += (brotli_reg_t)1U << code;\n          BROTLI_LOG_UINT(reps);\n          if (context_index + reps > context_map_size) {\n            return\n                BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT);\n          }\n          do {\n            context_map[context_index++] = 0;\n          } while (--reps);\n        }\n      }\n    }\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {\n      brotli_reg_t bits;\n      if (!BrotliSafeReadBits(br, 1, &bits)) {\n        h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if (bits != 0) {\n        InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);\n      }\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;\n      return BROTLI_DECODER_SUCCESS;\n    }\n\n    default:\n      return\n          BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n  }\n}\n\n/* Decodes a command or literal and updates block type ring-buffer.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(\n    int safe, BrotliDecoderState* s, int tree_type) {\n  brotli_reg_t max_block_type = s->num_block_types[tree_type];\n  const HuffmanCode* type_tree = &s->block_type_trees[\n      tree_type * BROTLI_HUFFMAN_MAX_SIZE_258];\n  const HuffmanCode* len_tree = &s->block_len_trees[\n      tree_type * BROTLI_HUFFMAN_MAX_SIZE_26];\n  BrotliBitReader* br = &s->br;\n  brotli_reg_t* ringbuffer = &s->block_type_rb[tree_type * 2];\n  brotli_reg_t block_type;\n  if (max_block_type <= 1) {\n    return BROTLI_FALSE;\n  }\n\n  /* Read 0..15 + 3..39 bits. */\n  if (!safe) {\n    block_type = ReadSymbol(type_tree, br);\n    s->block_length[tree_type] = ReadBlockLength(len_tree, br);\n  } else {\n    BrotliBitReaderState memento;\n    BrotliBitReaderSaveState(br, &memento);\n    if (!SafeReadSymbol(type_tree, br, &block_type)) return BROTLI_FALSE;\n    if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) {\n      s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;\n      BrotliBitReaderRestoreState(br, &memento);\n      return BROTLI_FALSE;\n    }\n  }\n\n  if (block_type == 1) {\n    block_type = ringbuffer[1] + 1;\n  } else if (block_type == 0) {\n    block_type = ringbuffer[0];\n  } else {\n    block_type -= 2;\n  }\n  if (block_type >= max_block_type) {\n    block_type -= max_block_type;\n  }\n  ringbuffer[0] = ringbuffer[1];\n  ringbuffer[1] = block_type;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void DetectTrivialLiteralBlockTypes(\n    BrotliDecoderState* s) {\n  size_t i;\n  for (i = 0; i < 8; ++i) s->trivial_literal_contexts[i] = 0;\n  for (i = 0; i < s->num_block_types[0]; i++) {\n    size_t offset = i << BROTLI_LITERAL_CONTEXT_BITS;\n    size_t error = 0;\n    size_t sample = s->context_map[offset];\n    size_t j;\n    for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS);) {\n      /* NOLINTNEXTLINE(bugprone-macro-repeated-side-effects) */\n      BROTLI_REPEAT_4({ error |= s->context_map[offset + j++] ^ sample; })\n    }\n    if (error == 0) {\n      s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31);\n    }\n  }\n}\n\nstatic BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState* s) {\n  uint8_t context_mode;\n  size_t trivial;\n  brotli_reg_t block_type = s->block_type_rb[1];\n  brotli_reg_t context_offset = block_type << BROTLI_LITERAL_CONTEXT_BITS;\n  s->context_map_slice = s->context_map + context_offset;\n  trivial = s->trivial_literal_contexts[block_type >> 5];\n  s->trivial_literal_context = (trivial >> (block_type & 31)) & 1;\n  s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]];\n  context_mode = s->context_modes[block_type] & 3;\n  s->context_lookup = BROTLI_CONTEXT_LUT(context_mode);\n}\n\n/* Decodes the block type and updates the state for literal context.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(\n    int safe, BrotliDecoderState* s) {\n  if (!DecodeBlockTypeAndLength(safe, s, 0)) {\n    return BROTLI_FALSE;\n  }\n  PrepareLiteralDecoding(s);\n  return BROTLI_TRUE;\n}\n\nstatic void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState* s) {\n  DecodeLiteralBlockSwitchInternal(0, s);\n}\n\nstatic BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(\n    BrotliDecoderState* s) {\n  return DecodeLiteralBlockSwitchInternal(1, s);\n}\n\n/* Block switch for insert/copy length.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(\n    int safe, BrotliDecoderState* s) {\n  if (!DecodeBlockTypeAndLength(safe, s, 1)) {\n    return BROTLI_FALSE;\n  }\n  s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]];\n  return BROTLI_TRUE;\n}\n\nstatic void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {\n  DecodeCommandBlockSwitchInternal(0, s);\n}\n\nstatic BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(\n    BrotliDecoderState* s) {\n  return DecodeCommandBlockSwitchInternal(1, s);\n}\n\n/* Block switch for distance codes.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(\n    int safe, BrotliDecoderState* s) {\n  if (!DecodeBlockTypeAndLength(safe, s, 2)) {\n    return BROTLI_FALSE;\n  }\n  s->dist_context_map_slice = s->dist_context_map +\n      (s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS);\n  s->dist_htree_index = s->dist_context_map_slice[s->distance_context];\n  return BROTLI_TRUE;\n}\n\nstatic void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState* s) {\n  DecodeDistanceBlockSwitchInternal(0, s);\n}\n\nstatic BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(\n    BrotliDecoderState* s) {\n  return DecodeDistanceBlockSwitchInternal(1, s);\n}\n\nstatic size_t UnwrittenBytes(const BrotliDecoderState* s, BROTLI_BOOL wrap) {\n  size_t pos = wrap && s->pos > s->ringbuffer_size ?\n      (size_t)s->ringbuffer_size : (size_t)(s->pos);\n  size_t partial_pos_rb = (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos;\n  return partial_pos_rb - s->partial_pos_out;\n}\n\n/* Dumps output.\n   Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push\n   and either ring-buffer is as big as window size, or |force| is true. */\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(\n    BrotliDecoderState* s, size_t* available_out, uint8_t** next_out,\n    size_t* total_out, BROTLI_BOOL force) {\n  uint8_t* start =\n      s->ringbuffer + (s->partial_pos_out & (size_t)s->ringbuffer_mask);\n  size_t to_write = UnwrittenBytes(s, BROTLI_TRUE);\n  size_t num_written = *available_out;\n  if (num_written > to_write) {\n    num_written = to_write;\n  }\n  if (s->meta_block_remaining_len < 0) {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1);\n  }\n  if (next_out && !*next_out) {\n    *next_out = start;\n  } else {\n    if (next_out) {\n      memcpy(*next_out, start, num_written);\n      *next_out += num_written;\n    }\n  }\n  *available_out -= num_written;\n  BROTLI_LOG_UINT(to_write);\n  BROTLI_LOG_UINT(num_written);\n  s->partial_pos_out += num_written;\n  if (total_out) {\n    *total_out = s->partial_pos_out;\n  }\n  if (num_written < to_write) {\n    if (s->ringbuffer_size == (1 << s->window_bits) || force) {\n      return BROTLI_DECODER_NEEDS_MORE_OUTPUT;\n    } else {\n      return BROTLI_DECODER_SUCCESS;\n    }\n  }\n  /* Wrap ring buffer only if it has reached its maximal size. */\n  if (s->ringbuffer_size == (1 << s->window_bits) &&\n      s->pos >= s->ringbuffer_size) {\n    s->pos -= s->ringbuffer_size;\n    s->rb_roundtrips++;\n    s->should_wrap_ringbuffer = (size_t)s->pos != 0 ? 1 : 0;\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic void BROTLI_NOINLINE WrapRingBuffer(BrotliDecoderState* s) {\n  if (s->should_wrap_ringbuffer) {\n    memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos);\n    s->should_wrap_ringbuffer = 0;\n  }\n}\n\n/* Allocates ring-buffer.\n\n   s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before\n   this function is called.\n\n   Last two bytes of ring-buffer are initialized to 0, so context calculation\n   could be done uniformly for the first two and all other positions. */\nstatic BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(\n    BrotliDecoderState* s) {\n  uint8_t* old_ringbuffer = s->ringbuffer;\n  if (s->ringbuffer_size == s->new_ringbuffer_size) {\n    return BROTLI_TRUE;\n  }\n\n  s->ringbuffer = (uint8_t*)BROTLI_DECODER_ALLOC(s,\n      (size_t)(s->new_ringbuffer_size) + kRingBufferWriteAheadSlack);\n  if (s->ringbuffer == 0) {\n    /* Restore previous value. */\n    s->ringbuffer = old_ringbuffer;\n    return BROTLI_FALSE;\n  }\n  s->ringbuffer[s->new_ringbuffer_size - 2] = 0;\n  s->ringbuffer[s->new_ringbuffer_size - 1] = 0;\n\n  if (!!old_ringbuffer) {\n    memcpy(s->ringbuffer, old_ringbuffer, (size_t)s->pos);\n    BROTLI_DECODER_FREE(s, old_ringbuffer);\n  }\n\n  s->ringbuffer_size = s->new_ringbuffer_size;\n  s->ringbuffer_mask = s->new_ringbuffer_size - 1;\n  s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;\n\n  return BROTLI_TRUE;\n}\n\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE\nSkipMetadataBlock(BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  int nbytes;\n\n  if (s->meta_block_remaining_len == 0) {\n    return BROTLI_DECODER_SUCCESS;\n  }\n\n  BROTLI_DCHECK((BrotliGetAvailableBits(br) & 7) == 0);\n\n  /* Drain accumulator. */\n  if (BrotliGetAvailableBits(br) >= 8) {\n    uint8_t buffer[8];\n    nbytes = (int)(BrotliGetAvailableBits(br)) >> 3;\n    BROTLI_DCHECK(nbytes <= 8);\n    if (nbytes > s->meta_block_remaining_len) {\n      nbytes = s->meta_block_remaining_len;\n    }\n    BrotliCopyBytes(buffer, br, (size_t)nbytes);\n    if (s->metadata_chunk_func) {\n      s->metadata_chunk_func(s->metadata_callback_opaque, buffer,\n                             (size_t)nbytes);\n    }\n    s->meta_block_remaining_len -= nbytes;\n    if (s->meta_block_remaining_len == 0) {\n      return BROTLI_DECODER_SUCCESS;\n    }\n  }\n\n  /* Direct access to metadata is possible. */\n  nbytes = (int)BrotliGetRemainingBytes(br);\n  if (nbytes > s->meta_block_remaining_len) {\n    nbytes = s->meta_block_remaining_len;\n  }\n  if (nbytes > 0) {\n    if (s->metadata_chunk_func) {\n      s->metadata_chunk_func(s->metadata_callback_opaque, br->next_in,\n                             (size_t)nbytes);\n    }\n    BrotliDropBytes(br, (size_t)nbytes);\n    s->meta_block_remaining_len -= nbytes;\n    if (s->meta_block_remaining_len == 0) {\n      return BROTLI_DECODER_SUCCESS;\n    }\n  }\n\n  BROTLI_DCHECK(BrotliGetRemainingBytes(br) == 0);\n\n  return BROTLI_DECODER_NEEDS_MORE_INPUT;\n}\n\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(\n    size_t* available_out, uint8_t** next_out, size_t* total_out,\n    BrotliDecoderState* s) {\n  /* TODO(eustas): avoid allocation for single uncompressed block. */\n  if (!BrotliEnsureRingBuffer(s)) {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1);\n  }\n\n  /* State machine */\n  for (;;) {\n    switch (s->substate_uncompressed) {\n      case BROTLI_STATE_UNCOMPRESSED_NONE: {\n        int nbytes = (int)BrotliGetRemainingBytes(&s->br);\n        if (nbytes > s->meta_block_remaining_len) {\n          nbytes = s->meta_block_remaining_len;\n        }\n        if (s->pos + nbytes > s->ringbuffer_size) {\n          nbytes = s->ringbuffer_size - s->pos;\n        }\n        /* Copy remaining bytes from s->br.buf_ to ring-buffer. */\n        BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes);\n        s->pos += nbytes;\n        s->meta_block_remaining_len -= nbytes;\n        if (s->pos < 1 << s->window_bits) {\n          if (s->meta_block_remaining_len == 0) {\n            return BROTLI_DECODER_SUCCESS;\n          }\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_UNCOMPRESSED_WRITE: {\n        BrotliDecoderErrorCode result;\n        result = WriteRingBuffer(\n            s, available_out, next_out, total_out, BROTLI_FALSE);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n        if (s->ringbuffer_size == 1 << s->window_bits) {\n          s->max_distance = s->max_backward_distance;\n        }\n        s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;\n        break;\n      }\n    }\n  }\n  BROTLI_DCHECK(0);  /* Unreachable */\n}\n\nstatic BROTLI_BOOL AttachCompoundDictionary(\n    BrotliDecoderState* state, const uint8_t* data, size_t size) {\n  BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;\n  if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;\n  if (!addon) {\n    addon = (BrotliDecoderCompoundDictionary*)BROTLI_DECODER_ALLOC(\n        state, sizeof(BrotliDecoderCompoundDictionary));\n    if (!addon) return BROTLI_FALSE;\n    addon->num_chunks = 0;\n    addon->total_size = 0;\n    addon->br_length = 0;\n    addon->br_copied = 0;\n    addon->block_bits = -1;\n    addon->chunk_offsets[0] = 0;\n    state->compound_dictionary = addon;\n  }\n  if (addon->num_chunks == 15) return BROTLI_FALSE;\n  addon->chunks[addon->num_chunks] = data;\n  addon->num_chunks++;\n  addon->total_size += (int)size;\n  addon->chunk_offsets[addon->num_chunks] = addon->total_size;\n  return BROTLI_TRUE;\n}\n\nstatic void EnsureCompoundDictionaryInitialized(BrotliDecoderState* state) {\n  BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;\n  /* 256 = (1 << 8) slots in block map. */\n  int block_bits = 8;\n  int cursor = 0;\n  int index = 0;\n  if (addon->block_bits != -1) return;\n  while (((addon->total_size - 1) >> block_bits) != 0) block_bits++;\n  block_bits -= 8;\n  addon->block_bits = block_bits;\n  while (cursor < addon->total_size) {\n    while (addon->chunk_offsets[index + 1] < cursor) index++;\n    addon->block_map[cursor >> block_bits] = (uint8_t)index;\n    cursor += 1 << block_bits;\n  }\n}\n\nstatic BROTLI_BOOL InitializeCompoundDictionaryCopy(BrotliDecoderState* s,\n    int address, int length) {\n  BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;\n  int index;\n  EnsureCompoundDictionaryInitialized(s);\n  index = addon->block_map[address >> addon->block_bits];\n  while (address >= addon->chunk_offsets[index + 1]) index++;\n  if (addon->total_size < address + length) return BROTLI_FALSE;\n  /* Update the recent distances cache. */\n  s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;\n  ++s->dist_rb_idx;\n  s->meta_block_remaining_len -= length;\n  addon->br_index = index;\n  addon->br_offset = address - addon->chunk_offsets[index];\n  addon->br_length = length;\n  addon->br_copied = 0;\n  return BROTLI_TRUE;\n}\n\nstatic int GetCompoundDictionarySize(BrotliDecoderState* s) {\n  return s->compound_dictionary ? s->compound_dictionary->total_size : 0;\n}\n\nstatic int CopyFromCompoundDictionary(BrotliDecoderState* s, int pos) {\n  BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;\n  int orig_pos = pos;\n  while (addon->br_length != addon->br_copied) {\n    uint8_t* copy_dst = &s->ringbuffer[pos];\n    const uint8_t* copy_src =\n        addon->chunks[addon->br_index] + addon->br_offset;\n    int space = s->ringbuffer_size - pos;\n    int rem_chunk_length = (addon->chunk_offsets[addon->br_index + 1] -\n        addon->chunk_offsets[addon->br_index]) - addon->br_offset;\n    int length = addon->br_length - addon->br_copied;\n    if (length > rem_chunk_length) length = rem_chunk_length;\n    if (length > space) length = space;\n    memcpy(copy_dst, copy_src, (size_t)length);\n    pos += length;\n    addon->br_offset += length;\n    addon->br_copied += length;\n    if (length == rem_chunk_length) {\n      addon->br_index++;\n      addon->br_offset = 0;\n    }\n    if (pos == s->ringbuffer_size) break;\n  }\n  return pos - orig_pos;\n}\n\nBROTLI_BOOL BrotliDecoderAttachDictionary(\n    BrotliDecoderState* state, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {\n  brotli_reg_t i;\n  brotli_reg_t num_prefix_before = state->dictionary->num_prefix;\n  if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;\n  if (!BrotliSharedDictionaryAttach(state->dictionary, type, data_size, data)) {\n    return BROTLI_FALSE;\n  }\n  for (i = num_prefix_before; i < state->dictionary->num_prefix; i++) {\n    if (!AttachCompoundDictionary(\n        state, state->dictionary->prefix[i],\n        state->dictionary->prefix_size[i])) {\n      return BROTLI_FALSE;\n    }\n  }\n  return BROTLI_TRUE;\n}\n\n/* Calculates the smallest feasible ring buffer.\n\n   If we know the data size is small, do not allocate more ring buffer\n   size than needed to reduce memory usage.\n\n   When this method is called, metablock size and flags MUST be decoded. */\nstatic void BROTLI_NOINLINE BrotliCalculateRingBufferSize(\n    BrotliDecoderState* s) {\n  int window_size = 1 << s->window_bits;\n  int new_ringbuffer_size = window_size;\n  /* We need at least 2 bytes of ring buffer size to get the last two\n     bytes for context from there */\n  int min_size = s->ringbuffer_size ? s->ringbuffer_size : 1024;\n  int output_size;\n\n  /* If maximum is already reached, no further extension is retired. */\n  if (s->ringbuffer_size == window_size) {\n    return;\n  }\n\n  /* Metadata blocks does not touch ring buffer. */\n  if (s->is_metadata) {\n    return;\n  }\n\n  if (!s->ringbuffer) {\n    output_size = 0;\n  } else {\n    output_size = s->pos;\n  }\n  output_size += s->meta_block_remaining_len;\n  min_size = min_size < output_size ? output_size : min_size;\n\n  if (!!s->canny_ringbuffer_allocation) {\n    /* Reduce ring buffer size to save memory when server is unscrupulous.\n       In worst case memory usage might be 1.5x bigger for a short period of\n       ring buffer reallocation. */\n    while ((new_ringbuffer_size >> 1) >= min_size) {\n      new_ringbuffer_size >>= 1;\n    }\n  }\n\n  s->new_ringbuffer_size = new_ringbuffer_size;\n}\n\n/* Reads 1..256 2-bit context modes. */\nstatic BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  int i = s->loop_counter;\n\n  while (i < (int)s->num_block_types[0]) {\n    brotli_reg_t bits;\n    if (!BrotliSafeReadBits(br, 2, &bits)) {\n      s->loop_counter = i;\n      return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    }\n    s->context_modes[i] = (uint8_t)bits;\n    BROTLI_LOG_ARRAY_INDEX(s->context_modes, i);\n    i++;\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {\n  int offset = s->distance_code - 3;\n  if (s->distance_code <= 3) {\n    /* Compensate double distance-ring-buffer roll for dictionary items. */\n    s->distance_context = 1 >> s->distance_code;\n    s->distance_code = s->dist_rb[(s->dist_rb_idx - offset) & 3];\n    s->dist_rb_idx -= s->distance_context;\n  } else {\n    int index_delta = 3;\n    int delta;\n    int base = s->distance_code - 10;\n    if (s->distance_code < 10) {\n      base = s->distance_code - 4;\n    } else {\n      index_delta = 2;\n    }\n    /* Unpack one of six 4-bit values. */\n    delta = ((0x605142 >> (4 * base)) & 0xF) - 3;\n    s->distance_code = s->dist_rb[(s->dist_rb_idx + index_delta) & 0x3] + delta;\n    if (s->distance_code <= 0) {\n      /* A huge distance will cause a BROTLI_FAILURE() soon.\n         This is a little faster than failing here. */\n      s->distance_code = 0x7FFFFFFF;\n    }\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  if (n_bits != 0) {\n    return BrotliSafeReadBits(br, n_bits, val);\n  } else {\n    *val = 0;\n    return BROTLI_TRUE;\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadBits32(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  if (n_bits != 0) {\n    return BrotliSafeReadBits32(br, n_bits, val);\n  } else {\n    *val = 0;\n    return BROTLI_TRUE;\n  }\n}\n\n/*\n   RFC 7932 Section 4 with \"...\" shortenings and \"[]\" emendations.\n\n   Each distance ... is represented with a pair <distance code, extra bits>...\n   The distance code is encoded using a prefix code... The number of extra bits\n   can be 0..24... Two additional parameters: NPOSTFIX (0..3), and ...\n   NDIRECT (0..120) ... are encoded in the meta-block header...\n\n   The first 16 distance symbols ... reference past distances... ring buffer ...\n   Next NDIRECT distance symbols ... represent distances from 1 to NDIRECT...\n   [For] distance symbols 16 + NDIRECT and greater ... the number of extra bits\n   ... is given by the following formula:\n\n   [ xcode = dcode - NDIRECT - 16 ]\n   ndistbits = 1 + [ xcode ] >> (NPOSTFIX + 1)\n\n   ...\n*/\n\n/*\n   RFC 7932 Section 9.2 with \"...\" shortenings and \"[]\" emendations.\n\n   ... to get the actual value of the parameter NDIRECT, left-shift this\n   four-bit number by NPOSTFIX bits ...\n*/\n\n/* Remaining formulas from RFC 7932 Section 4 could be rewritten as following:\n\n     alphabet_size = 16 + NDIRECT + (max_distbits << (NPOSTFIX + 1))\n\n     half = ((xcode >> NPOSTFIX) & 1) << ndistbits\n     postfix = xcode & ((1 << NPOSTFIX) - 1)\n     range_start = 2 * (1 << ndistbits - 1 - 1)\n\n     distance = (range_start + half + extra) << NPOSTFIX + postfix + NDIRECT + 1\n\n   NB: ndistbits >= 1 -> range_start >= 0\n   NB: range_start has factor 2, as the range is covered by 2 \"halves\"\n   NB: extra -1 offset in range_start formula covers the absence of\n       ndistbits = 0 case\n   NB: when NPOSTFIX = 0, NDIRECT is not greater than 15\n\n   In other words, xcode has the following binary structure - XXXHPPP:\n    - XXX represent the number of extra distance bits\n    - H selects upper / lower range of distances\n    - PPP represent \"postfix\"\n\n  \"Regular\" distance encoding has NPOSTFIX = 0; omitting the postfix part\n  simplifies distance calculation.\n\n  Using NPOSTFIX > 0 allows cheaper encoding of regular structures, e.g. where\n  most of distances have the same reminder of division by 2/4/8. For example,\n  the table of int32_t values that come from different sources; if it is likely\n  that 3 highest bytes of values from the same source are the same, then\n  copy distance often looks like 4x + y.\n\n  Distance calculation could be rewritten to:\n\n    ndistbits = NDISTBITS(NDIRECT, NPOSTFIX)[dcode]\n    distance = OFFSET(NDIRECT, NPOSTFIX)[dcode] + extra << NPOSTFIX\n\n  NDISTBITS and OFFSET could be pre-calculated, as NDIRECT and NPOSTFIX could\n  change only once per meta-block.\n*/\n\n/* Calculates distance lookup table.\n   NB: it is possible to have all 64 tables precalculated. */\nstatic void CalculateDistanceLut(BrotliDecoderState* s) {\n  BrotliMetablockBodyArena* b = &s->arena.body;\n  brotli_reg_t npostfix = s->distance_postfix_bits;\n  brotli_reg_t ndirect = s->num_direct_distance_codes;\n  brotli_reg_t alphabet_size_limit = s->distance_hgroup.alphabet_size_limit;\n  brotli_reg_t postfix = (brotli_reg_t)1u << npostfix;\n  brotli_reg_t j;\n  brotli_reg_t bits = 1;\n  brotli_reg_t half = 0;\n\n  /* Skip short codes. */\n  brotli_reg_t i = BROTLI_NUM_DISTANCE_SHORT_CODES;\n\n  /* Fill direct codes. */\n  for (j = 0; j < ndirect; ++j) {\n    b->dist_extra_bits[i] = 0;\n    b->dist_offset[i] = j + 1;\n    ++i;\n  }\n\n  /* Fill regular distance codes. */\n  while (i < alphabet_size_limit) {\n    brotli_reg_t base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;\n    /* Always fill the complete group. */\n    for (j = 0; j < postfix; ++j) {\n      b->dist_extra_bits[i] = (uint8_t)bits;\n      b->dist_offset[i] = base + j;\n      ++i;\n    }\n    bits = bits + half;\n    half = half ^ 1;\n  }\n}\n\n/* Precondition: s->distance_code < 0. */\nstatic BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(\n    int safe, BrotliDecoderState* s, BrotliBitReader* br) {\n  BrotliMetablockBodyArena* b = &s->arena.body;\n  brotli_reg_t code;\n  brotli_reg_t bits;\n  BrotliBitReaderState memento;\n  HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index];\n  if (!safe) {\n    code = ReadSymbol(distance_tree, br);\n  } else {\n    BrotliBitReaderSaveState(br, &memento);\n    if (!SafeReadSymbol(distance_tree, br, &code)) {\n      return BROTLI_FALSE;\n    }\n  }\n  --s->block_length[2];\n  /* Convert the distance code to the actual distance by possibly\n     looking up past distances from the s->dist_rb. */\n  s->distance_context = 0;\n  if ((code & ~0xFu) == 0) {\n    s->distance_code = (int)code;\n    TakeDistanceFromRingBuffer(s);\n    return BROTLI_TRUE;\n  }\n  if (!safe) {\n    bits = BrotliReadBits32(br, b->dist_extra_bits[code]);\n  } else {\n    if (!SafeReadBits32(br, b->dist_extra_bits[code], &bits)) {\n      ++s->block_length[2];\n      BrotliBitReaderRestoreState(br, &memento);\n      return BROTLI_FALSE;\n    }\n  }\n  s->distance_code =\n      (int)(b->dist_offset[code] + (bits << s->distance_postfix_bits));\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void ReadDistance(\n    BrotliDecoderState* s, BrotliBitReader* br) {\n  ReadDistanceInternal(0, s, br);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadDistance(\n    BrotliDecoderState* s, BrotliBitReader* br) {\n  return ReadDistanceInternal(1, s, br);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL ReadCommandInternal(\n    int safe, BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {\n  brotli_reg_t cmd_code;\n  brotli_reg_t insert_len_extra = 0;\n  brotli_reg_t copy_length;\n  CmdLutElement v;\n  BrotliBitReaderState memento;\n  if (!safe) {\n    cmd_code = ReadSymbol(s->htree_command, br);\n  } else {\n    BrotliBitReaderSaveState(br, &memento);\n    if (!SafeReadSymbol(s->htree_command, br, &cmd_code)) {\n      return BROTLI_FALSE;\n    }\n  }\n  v = kCmdLut[cmd_code];\n  s->distance_code = v.distance_code;\n  s->distance_context = v.context;\n  s->dist_htree_index = s->dist_context_map_slice[s->distance_context];\n  *insert_length = v.insert_len_offset;\n  if (!safe) {\n    if (BROTLI_PREDICT_FALSE(v.insert_len_extra_bits != 0)) {\n      insert_len_extra = BrotliReadBits24(br, v.insert_len_extra_bits);\n    }\n    copy_length = BrotliReadBits24(br, v.copy_len_extra_bits);\n  } else {\n    if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) ||\n        !SafeReadBits(br, v.copy_len_extra_bits, &copy_length)) {\n      BrotliBitReaderRestoreState(br, &memento);\n      return BROTLI_FALSE;\n    }\n  }\n  s->copy_length = (int)copy_length + v.copy_len_offset;\n  --s->block_length[1];\n  *insert_length += (int)insert_len_extra;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void ReadCommand(\n    BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {\n  ReadCommandInternal(0, s, br, insert_length);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadCommand(\n    BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {\n  return ReadCommandInternal(1, s, br, insert_length);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL CheckInputAmount(\n    int safe, BrotliBitReader* const br) {\n  if (safe) {\n    return BROTLI_TRUE;\n  }\n  return BrotliCheckInputAmount(br);\n}\n\n#define BROTLI_SAFE(METHOD)                       \\\n  {                                               \\\n    if (safe) {                                   \\\n      if (!Safe##METHOD) {                        \\\n        result = BROTLI_DECODER_NEEDS_MORE_INPUT; \\\n        goto saveStateAndReturn;                  \\\n      }                                           \\\n    } else {                                      \\\n      METHOD;                                     \\\n    }                                             \\\n  }\n\nstatic BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(\n    int safe, BrotliDecoderState* s) {\n  int pos = s->pos;\n  int i = s->loop_counter;\n  BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;\n  BrotliBitReader* br = &s->br;\n  int compound_dictionary_size = GetCompoundDictionarySize(s);\n\n  if (!CheckInputAmount(safe, br)) {\n    result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n    goto saveStateAndReturn;\n  }\n  if (!safe) {\n    BROTLI_UNUSED(BrotliWarmupBitReader(br));\n  }\n\n  /* Jump into state machine. */\n  if (s->state == BROTLI_STATE_COMMAND_BEGIN) {\n    goto CommandBegin;\n  } else if (s->state == BROTLI_STATE_COMMAND_INNER) {\n    goto CommandInner;\n  } else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) {\n    goto CommandPostDecodeLiterals;\n  } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) {\n    goto CommandPostWrapCopy;\n  } else {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n  }\n\nCommandBegin:\n  if (safe) {\n    s->state = BROTLI_STATE_COMMAND_BEGIN;\n  }\n  if (!CheckInputAmount(safe, br)) {\n    s->state = BROTLI_STATE_COMMAND_BEGIN;\n    result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n    goto saveStateAndReturn;\n  }\n  if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) {\n    BROTLI_SAFE(DecodeCommandBlockSwitch(s));\n    goto CommandBegin;\n  }\n  /* Read the insert/copy length in the command. */\n  BROTLI_SAFE(ReadCommand(s, br, &i));\n  BROTLI_LOG((\"[ProcessCommandsInternal] pos = %d insert = %d copy = %d\\n\",\n              pos, i, s->copy_length));\n  if (i == 0) {\n    goto CommandPostDecodeLiterals;\n  }\n  s->meta_block_remaining_len -= i;\n\nCommandInner:\n  if (safe) {\n    s->state = BROTLI_STATE_COMMAND_INNER;\n  }\n  /* Read the literals in the command. */\n  if (s->trivial_literal_context) {\n    brotli_reg_t bits;\n    brotli_reg_t value;\n    PreloadSymbol(safe, s->literal_htree, br, &bits, &value);\n    if (!safe) {\n      // This is a hottest part of the decode, so we copy the loop below\n      // and optimize it by calculating the number of steps where all checks\n      // evaluate to false (ringbuffer size/block size/input size).\n      // Since all checks are loop invariant, we just need to find\n      // minimal number of iterations for a simple loop, and run\n      // the full version for the remainder.\n      int num_steps = i - 1;\n      if (num_steps > 0 && ((brotli_reg_t)(num_steps) > s->block_length[0])) {\n        // Safe cast, since block_length < steps\n        num_steps = (int)s->block_length[0];\n      }\n      if (s->ringbuffer_size >= pos &&\n          (s->ringbuffer_size - pos) <= num_steps) {\n        num_steps = s->ringbuffer_size - pos - 1;\n      }\n      if (num_steps < 0) {\n        num_steps = 0;\n      }\n      num_steps = BrotliCopyPreloadedSymbolsToU8(s->literal_htree, br, &bits,\n                                                 &value, s->ringbuffer, pos,\n                                                 num_steps);\n      pos += num_steps;\n      s->block_length[0] -= (brotli_reg_t)num_steps;\n      i -= num_steps;\n      do {\n        if (!CheckInputAmount(safe, br)) {\n          s->state = BROTLI_STATE_COMMAND_INNER;\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          goto saveStateAndReturn;\n        }\n        if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {\n          goto NextLiteralBlock;\n        }\n        BrotliCopyPreloadedSymbolsToU8(s->literal_htree, br, &bits, &value,\n                                       s->ringbuffer, pos, 1);\n        --s->block_length[0];\n        BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);\n        ++pos;\n        if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {\n          s->state = BROTLI_STATE_COMMAND_INNER_WRITE;\n          --i;\n          goto saveStateAndReturn;\n        }\n      } while (--i != 0);\n    } else { /* safe */\n      do {\n        if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {\n          goto NextLiteralBlock;\n        }\n        brotli_reg_t literal;\n        if (!SafeReadSymbol(s->literal_htree, br, &literal)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          goto saveStateAndReturn;\n        }\n        s->ringbuffer[pos] = (uint8_t)literal;\n        --s->block_length[0];\n        BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);\n        ++pos;\n        if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {\n          s->state = BROTLI_STATE_COMMAND_INNER_WRITE;\n          --i;\n          goto saveStateAndReturn;\n        }\n      } while (--i != 0);\n    }\n  } else {\n    uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];\n    uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];\n    do {\n      const HuffmanCode* hc;\n      uint8_t context;\n      if (!CheckInputAmount(safe, br)) {\n        s->state = BROTLI_STATE_COMMAND_INNER;\n        result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n        goto saveStateAndReturn;\n      }\n      if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {\n        goto NextLiteralBlock;\n      }\n      context = BROTLI_CONTEXT(p1, p2, s->context_lookup);\n      BROTLI_LOG_UINT(context);\n      hc = s->literal_hgroup.htrees[s->context_map_slice[context]];\n      p2 = p1;\n      if (!safe) {\n        p1 = (uint8_t)ReadSymbol(hc, br);\n      } else {\n        brotli_reg_t literal;\n        if (!SafeReadSymbol(hc, br, &literal)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          goto saveStateAndReturn;\n        }\n        p1 = (uint8_t)literal;\n      }\n      s->ringbuffer[pos] = p1;\n      --s->block_length[0];\n      BROTLI_LOG_UINT(s->context_map_slice[context]);\n      BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask);\n      ++pos;\n      if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {\n        s->state = BROTLI_STATE_COMMAND_INNER_WRITE;\n        --i;\n        goto saveStateAndReturn;\n      }\n    } while (--i != 0);\n  }\n  BROTLI_LOG_UINT(s->meta_block_remaining_len);\n  if (BROTLI_PREDICT_FALSE(s->meta_block_remaining_len <= 0)) {\n    s->state = BROTLI_STATE_METABLOCK_DONE;\n    goto saveStateAndReturn;\n  }\n\nCommandPostDecodeLiterals:\n  if (safe) {\n    s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;\n  }\n  if (s->distance_code >= 0) {\n    /* Implicit distance case. */\n    s->distance_context = s->distance_code ? 0 : 1;\n    --s->dist_rb_idx;\n    s->distance_code = s->dist_rb[s->dist_rb_idx & 3];\n  } else {\n    /* Read distance code in the command, unless it was implicitly zero. */\n    if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) {\n      BROTLI_SAFE(DecodeDistanceBlockSwitch(s));\n    }\n    BROTLI_SAFE(ReadDistance(s, br));\n  }\n  BROTLI_LOG((\"[ProcessCommandsInternal] pos = %d distance = %d\\n\",\n              pos, s->distance_code));\n  if (s->max_distance != s->max_backward_distance) {\n    s->max_distance =\n        (pos < s->max_backward_distance) ? pos : s->max_backward_distance;\n  }\n  i = s->copy_length;\n  /* Apply copy of LZ77 back-reference, or static dictionary reference if\n     the distance is larger than the max LZ77 distance */\n  if (s->distance_code > s->max_distance) {\n    /* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC.\n       With this choice, no signed overflow can occur after decoding\n       a special distance code (e.g., after adding 3 to the last distance). */\n    if (s->distance_code > BROTLI_MAX_ALLOWED_DISTANCE) {\n      BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n          \"len: %d bytes left: %d\\n\",\n          pos, s->distance_code, i, s->meta_block_remaining_len));\n      return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DISTANCE);\n    }\n    if (s->distance_code - s->max_distance - 1 < compound_dictionary_size) {\n      int address = compound_dictionary_size -\n          (s->distance_code - s->max_distance);\n      if (!InitializeCompoundDictionaryCopy(s, address, i)) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY);\n      }\n      pos += CopyFromCompoundDictionary(s, pos);\n      if (pos >= s->ringbuffer_size) {\n        s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;\n        goto saveStateAndReturn;\n      }\n    } else if (i >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH &&\n               i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) {\n      uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];\n      uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];\n      uint8_t dict_id = s->dictionary->context_based ?\n          s->dictionary->context_map[BROTLI_CONTEXT(p1, p2, s->context_lookup)]\n          : 0;\n      const BrotliDictionary* words = s->dictionary->words[dict_id];\n      const BrotliTransforms* transforms = s->dictionary->transforms[dict_id];\n      int offset = (int)words->offsets_by_length[i];\n      brotli_reg_t shift = words->size_bits_by_length[i];\n      int address =\n          s->distance_code - s->max_distance - 1 - compound_dictionary_size;\n      int mask = (int)BitMask(shift);\n      int word_idx = address & mask;\n      int transform_idx = address >> shift;\n      /* Compensate double distance-ring-buffer roll. */\n      s->dist_rb_idx += s->distance_context;\n      offset += word_idx * i;\n      /* If the distance is out of bound, select a next static dictionary if\n         there exist multiple. */\n      if ((transform_idx >= (int)transforms->num_transforms ||\n          words->size_bits_by_length[i] == 0) &&\n          s->dictionary->num_dictionaries > 1) {\n        uint8_t dict_id2;\n        int dist_remaining = address -\n            (int)(((1u << shift) & ~1u)) * (int)transforms->num_transforms;\n        for (dict_id2 = 0; dict_id2 < s->dictionary->num_dictionaries;\n            dict_id2++) {\n          const BrotliDictionary* words2 = s->dictionary->words[dict_id2];\n          if (dict_id2 != dict_id && words2->size_bits_by_length[i] != 0) {\n            const BrotliTransforms* transforms2 =\n                s->dictionary->transforms[dict_id2];\n            brotli_reg_t shift2 = words2->size_bits_by_length[i];\n            int num = (int)((1u << shift2) & ~1u) *\n                (int)transforms2->num_transforms;\n            if (dist_remaining < num) {\n              dict_id = dict_id2;\n              words = words2;\n              transforms = transforms2;\n              address = dist_remaining;\n              shift = shift2;\n              mask = (int)BitMask(shift);\n              word_idx = address & mask;\n              transform_idx = address >> shift;\n              offset = (int)words->offsets_by_length[i] + word_idx * i;\n              break;\n            }\n            dist_remaining -= num;\n          }\n        }\n      }\n      if (BROTLI_PREDICT_FALSE(words->size_bits_by_length[i] == 0)) {\n        BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n            \"len: %d bytes left: %d\\n\",\n            pos, s->distance_code, i, s->meta_block_remaining_len));\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);\n      }\n      if (BROTLI_PREDICT_FALSE(!words->data)) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET);\n      }\n      if (transform_idx < (int)transforms->num_transforms) {\n        const uint8_t* word = &words->data[offset];\n        int len = i;\n        if (transform_idx == transforms->cutOffTransforms[0]) {\n          memcpy(&s->ringbuffer[pos], word, (size_t)len);\n          BROTLI_LOG((\"[ProcessCommandsInternal] dictionary word: [%.*s]\\n\",\n                      len, word));\n        } else {\n          len = BrotliTransformDictionaryWord(&s->ringbuffer[pos], word, len,\n              transforms, transform_idx);\n          BROTLI_LOG((\"[ProcessCommandsInternal] dictionary word: [%.*s],\"\n                      \" transform_idx = %d, transformed: [%.*s]\\n\",\n                      i, word, transform_idx, len, &s->ringbuffer[pos]));\n          if (len == 0 && s->distance_code <= 120) {\n            BROTLI_LOG((\"Invalid length-0 dictionary word after transform\\n\"));\n            return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);\n          }\n        }\n        pos += len;\n        s->meta_block_remaining_len -= len;\n        if (pos >= s->ringbuffer_size) {\n          s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;\n          goto saveStateAndReturn;\n        }\n      } else {\n        BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n            \"len: %d bytes left: %d\\n\",\n            pos, s->distance_code, i, s->meta_block_remaining_len));\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);\n      }\n    } else {\n      BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n          \"len: %d bytes left: %d\\n\",\n          pos, s->distance_code, i, s->meta_block_remaining_len));\n      return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);\n    }\n  } else {\n    int src_start = (pos - s->distance_code) & s->ringbuffer_mask;\n    uint8_t* copy_dst = &s->ringbuffer[pos];\n    uint8_t* copy_src = &s->ringbuffer[src_start];\n    int dst_end = pos + i;\n    int src_end = src_start + i;\n    /* Update the recent distances cache. */\n    s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;\n    ++s->dist_rb_idx;\n    s->meta_block_remaining_len -= i;\n    /* There are 32+ bytes of slack in the ring-buffer allocation.\n       Also, we have 16 short codes, that make these 16 bytes irrelevant\n       in the ring-buffer. Let's copy over them as a first guess. */\n    memmove16(copy_dst, copy_src);\n    if (src_end > pos && dst_end > src_start) {\n      /* Regions intersect. */\n      goto CommandPostWrapCopy;\n    }\n    if (dst_end >= s->ringbuffer_size || src_end >= s->ringbuffer_size) {\n      /* At least one region wraps. */\n      goto CommandPostWrapCopy;\n    }\n    pos += i;\n    if (i > 16) {\n      if (i > 32) {\n        memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16));\n      } else {\n        /* This branch covers about 45% cases.\n           Fixed size short copy allows more compiler optimizations. */\n        memmove16(copy_dst + 16, copy_src + 16);\n      }\n    }\n  }\n  BROTLI_LOG_UINT(s->meta_block_remaining_len);\n  if (s->meta_block_remaining_len <= 0) {\n    /* Next metablock, if any. */\n    s->state = BROTLI_STATE_METABLOCK_DONE;\n    goto saveStateAndReturn;\n  } else {\n    goto CommandBegin;\n  }\nCommandPostWrapCopy:\n  {\n    int wrap_guard = s->ringbuffer_size - pos;\n    while (--i >= 0) {\n      s->ringbuffer[pos] =\n          s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask];\n      ++pos;\n      if (BROTLI_PREDICT_FALSE(--wrap_guard == 0)) {\n        s->state = BROTLI_STATE_COMMAND_POST_WRITE_2;\n        goto saveStateAndReturn;\n      }\n    }\n  }\n  if (s->meta_block_remaining_len <= 0) {\n    /* Next metablock, if any. */\n    s->state = BROTLI_STATE_METABLOCK_DONE;\n    goto saveStateAndReturn;\n  } else {\n    goto CommandBegin;\n  }\n\nNextLiteralBlock:\n  BROTLI_SAFE(DecodeLiteralBlockSwitch(s));\n  goto CommandInner;\n\nsaveStateAndReturn:\n  s->pos = pos;\n  s->loop_counter = i;\n  return result;\n}\n\n#undef BROTLI_SAFE\n\nstatic BROTLI_NOINLINE BrotliDecoderErrorCode ProcessCommands(\n    BrotliDecoderState* s) {\n  return ProcessCommandsInternal(0, s);\n}\n\nstatic BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(\n    BrotliDecoderState* s) {\n  return ProcessCommandsInternal(1, s);\n}\n\nBrotliDecoderResult BrotliDecoderDecompress(\n    size_t encoded_size,\n    const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],\n    size_t* decoded_size,\n    uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]) {\n  BrotliDecoderState s;\n  BrotliDecoderResult result;\n  size_t total_out = 0;\n  size_t available_in = encoded_size;\n  const uint8_t* next_in = encoded_buffer;\n  size_t available_out = *decoded_size;\n  uint8_t* next_out = decoded_buffer;\n  if (!BrotliDecoderStateInit(&s, 0, 0, 0)) {\n    return BROTLI_DECODER_RESULT_ERROR;\n  }\n  result = BrotliDecoderDecompressStream(\n      &s, &available_in, &next_in, &available_out, &next_out, &total_out);\n  *decoded_size = total_out;\n  BrotliDecoderStateCleanup(&s);\n  if (result != BROTLI_DECODER_RESULT_SUCCESS) {\n    result = BROTLI_DECODER_RESULT_ERROR;\n  }\n  return result;\n}\n\n/* Invariant: input stream is never overconsumed:\n    - invalid input implies that the whole stream is invalid -> any amount of\n      input could be read and discarded\n    - when result is \"needs more input\", then at least one more byte is REQUIRED\n      to complete decoding; all input data MUST be consumed by decoder, so\n      client could swap the input buffer\n    - when result is \"needs more output\" decoder MUST ensure that it doesn't\n      hold more than 7 bits in bit reader; this saves client from swapping input\n      buffer ahead of time\n    - when result is \"success\" decoder MUST return all unused data back to input\n      buffer; this is possible because the invariant is held on enter */\nBrotliDecoderResult BrotliDecoderDecompressStream(\n    BrotliDecoderState* s, size_t* available_in, const uint8_t** next_in,\n    size_t* available_out, uint8_t** next_out, size_t* total_out) {\n  BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;\n  BrotliBitReader* br = &s->br;\n  size_t input_size = *available_in;\n#define BROTLI_SAVE_ERROR_CODE(code) \\\n    SaveErrorCode(s, (code), input_size - *available_in)\n  /* Ensure that |total_out| is set, even if no data will ever be pushed out. */\n  if (total_out) {\n    *total_out = s->partial_pos_out;\n  }\n  /* Do not try to process further in a case of unrecoverable error. */\n  if ((int)s->error_code < 0) {\n    return BROTLI_DECODER_RESULT_ERROR;\n  }\n  if (*available_out && (!next_out || !*next_out)) {\n    return BROTLI_SAVE_ERROR_CODE(\n        BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS));\n  }\n  if (!*available_out) next_out = 0;\n  if (s->buffer_length == 0) {  /* Just connect bit reader to input stream. */\n    BrotliBitReaderSetInput(br, *next_in, *available_in);\n  } else {\n    /* At least one byte of input is required. More than one byte of input may\n       be required to complete the transaction -> reading more data must be\n       done in a loop -> do it in a main loop. */\n    result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n    BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length);\n  }\n  /* State machine */\n  for (;;) {\n    if (result != BROTLI_DECODER_SUCCESS) {\n      /* Error, needs more input/output. */\n      if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {\n        if (s->ringbuffer != 0) {  /* Pro-actively push output. */\n          BrotliDecoderErrorCode intermediate_result = WriteRingBuffer(s,\n              available_out, next_out, total_out, BROTLI_TRUE);\n          /* WriteRingBuffer checks s->meta_block_remaining_len validity. */\n          if ((int)intermediate_result < 0) {\n            result = intermediate_result;\n            break;\n          }\n        }\n        if (s->buffer_length != 0) {  /* Used with internal buffer. */\n          if (br->next_in == br->last_in) {\n            /* Successfully finished read transaction.\n               Accumulator contains less than 8 bits, because internal buffer\n               is expanded byte-by-byte until it is enough to complete read. */\n            s->buffer_length = 0;\n            /* Switch to input stream and restart. */\n            result = BROTLI_DECODER_SUCCESS;\n            BrotliBitReaderSetInput(br, *next_in, *available_in);\n            continue;\n          } else if (*available_in != 0) {\n            /* Not enough data in buffer, but can take one more byte from\n               input stream. */\n            result = BROTLI_DECODER_SUCCESS;\n            BROTLI_DCHECK(s->buffer_length < 8);\n            s->buffer.u8[s->buffer_length] = **next_in;\n            s->buffer_length++;\n            BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length);\n            (*next_in)++;\n            (*available_in)--;\n            /* Retry with more data in buffer. */\n            continue;\n          }\n          /* Can't finish reading and no more input. */\n          break;\n        } else {  /* Input stream doesn't contain enough input. */\n          /* Copy tail to internal buffer and return. */\n          *next_in = br->next_in;\n          *available_in = BrotliBitReaderGetAvailIn(br);\n          while (*available_in) {\n            s->buffer.u8[s->buffer_length] = **next_in;\n            s->buffer_length++;\n            (*next_in)++;\n            (*available_in)--;\n          }\n          break;\n        }\n        /* Unreachable. */\n      }\n\n      /* Fail or needs more output. */\n\n      if (s->buffer_length != 0) {\n        /* Just consumed the buffered input and produced some output. Otherwise\n           it would result in \"needs more input\". Reset internal buffer. */\n        s->buffer_length = 0;\n      } else {\n        /* Using input stream in last iteration. When decoder switches to input\n           stream it has less than 8 bits in accumulator, so it is safe to\n           return unused accumulator bits there. */\n        BrotliBitReaderUnload(br);\n        *available_in = BrotliBitReaderGetAvailIn(br);\n        *next_in = br->next_in;\n      }\n      break;\n    }\n    switch (s->state) {\n      case BROTLI_STATE_UNINITED:\n        /* Prepare to the first read. */\n        if (!BrotliWarmupBitReader(br)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        /* Decode window size. */\n        result = DecodeWindowBits(s, br);  /* Reads 1..8 bits. */\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        if (s->large_window) {\n          s->state = BROTLI_STATE_LARGE_WINDOW_BITS;\n          break;\n        }\n        s->state = BROTLI_STATE_INITIALIZE;\n        break;\n\n      case BROTLI_STATE_LARGE_WINDOW_BITS: {\n        brotli_reg_t bits;\n        if (!BrotliSafeReadBits(br, 6, &bits)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        s->window_bits = bits & 63u;\n        if (s->window_bits < BROTLI_LARGE_MIN_WBITS ||\n            s->window_bits > BROTLI_LARGE_MAX_WBITS) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);\n          break;\n        }\n        s->state = BROTLI_STATE_INITIALIZE;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_INITIALIZE:\n        BROTLI_LOG_UINT(s->window_bits);\n        /* Maximum distance, see section 9.1. of the spec. */\n        s->max_backward_distance = (1 << s->window_bits) - BROTLI_WINDOW_GAP;\n\n        /* Allocate memory for both block_type_trees and block_len_trees. */\n        s->block_type_trees = (HuffmanCode*)BROTLI_DECODER_ALLOC(s,\n            sizeof(HuffmanCode) * 3 *\n                (BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26));\n        if (s->block_type_trees == 0) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES);\n          break;\n        }\n        s->block_len_trees =\n            s->block_type_trees + 3 * BROTLI_HUFFMAN_MAX_SIZE_258;\n\n        s->state = BROTLI_STATE_METABLOCK_BEGIN;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_BEGIN:\n        BrotliDecoderStateMetablockBegin(s);\n        BROTLI_LOG_UINT(s->pos);\n        s->state = BROTLI_STATE_METABLOCK_HEADER;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER:\n        result = DecodeMetaBlockLength(s, br);  /* Reads 2 - 31 bits. */\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        BROTLI_LOG_UINT(s->is_last_metablock);\n        BROTLI_LOG_UINT(s->meta_block_remaining_len);\n        BROTLI_LOG_UINT(s->is_metadata);\n        BROTLI_LOG_UINT(s->is_uncompressed);\n        if (s->is_metadata || s->is_uncompressed) {\n          if (!BrotliJumpToByteBoundary(br)) {\n            result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_1);\n            break;\n          }\n        }\n        if (s->is_metadata) {\n          s->state = BROTLI_STATE_METADATA;\n          if (s->metadata_start_func) {\n            s->metadata_start_func(s->metadata_callback_opaque,\n                                   (size_t)s->meta_block_remaining_len);\n          }\n          break;\n        }\n        if (s->meta_block_remaining_len == 0) {\n          s->state = BROTLI_STATE_METABLOCK_DONE;\n          break;\n        }\n        BrotliCalculateRingBufferSize(s);\n        if (s->is_uncompressed) {\n          s->state = BROTLI_STATE_UNCOMPRESSED;\n          break;\n        }\n        s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER;\n      /* Fall through. */\n\n      case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER: {\n        BrotliMetablockHeaderArena* h = &s->arena.header;\n        s->loop_counter = 0;\n        /* Initialize compressed metablock header arena. */\n        h->sub_loop_counter = 0;\n        /* Make small negative indexes addressable. */\n        h->symbol_lists =\n            &h->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;\n        h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;\n        h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_0;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_0:\n        if (s->loop_counter >= 3) {\n          s->state = BROTLI_STATE_METABLOCK_HEADER_2;\n          break;\n        }\n        /* Reads 1..11 bits. */\n        result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->num_block_types[s->loop_counter]++;\n        BROTLI_LOG_UINT(s->num_block_types[s->loop_counter]);\n        if (s->num_block_types[s->loop_counter] < 2) {\n          s->loop_counter++;\n          break;\n        }\n        s->state = BROTLI_STATE_HUFFMAN_CODE_1;\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_1: {\n        brotli_reg_t alphabet_size = s->num_block_types[s->loop_counter] + 2;\n        int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258;\n        result = ReadHuffmanCode(alphabet_size, alphabet_size,\n            &s->block_type_trees[tree_offset], NULL, s);\n        if (result != BROTLI_DECODER_SUCCESS) break;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_2;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_2: {\n        brotli_reg_t alphabet_size = BROTLI_NUM_BLOCK_LEN_SYMBOLS;\n        int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;\n        result = ReadHuffmanCode(alphabet_size, alphabet_size,\n            &s->block_len_trees[tree_offset], NULL, s);\n        if (result != BROTLI_DECODER_SUCCESS) break;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_3;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_3: {\n        int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;\n        if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter],\n            &s->block_len_trees[tree_offset], br)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        BROTLI_LOG_UINT(s->block_length[s->loop_counter]);\n        s->loop_counter++;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_0;\n        break;\n      }\n\n      case BROTLI_STATE_UNCOMPRESSED: {\n        result = CopyUncompressedBlockToOutput(\n            available_out, next_out, total_out, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->state = BROTLI_STATE_METABLOCK_DONE;\n        break;\n      }\n\n      case BROTLI_STATE_METADATA:\n        result = SkipMetadataBlock(s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->state = BROTLI_STATE_METABLOCK_DONE;\n        break;\n\n      case BROTLI_STATE_METABLOCK_HEADER_2: {\n        brotli_reg_t bits;\n        if (!BrotliSafeReadBits(br, 6, &bits)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        s->distance_postfix_bits = bits & BitMask(2);\n        bits >>= 2;\n        s->num_direct_distance_codes = bits << s->distance_postfix_bits;\n        BROTLI_LOG_UINT(s->num_direct_distance_codes);\n        BROTLI_LOG_UINT(s->distance_postfix_bits);\n        s->context_modes =\n            (uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]);\n        if (s->context_modes == 0) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES);\n          break;\n        }\n        s->loop_counter = 0;\n        s->state = BROTLI_STATE_CONTEXT_MODES;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_CONTEXT_MODES:\n        result = ReadContextModes(s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->state = BROTLI_STATE_CONTEXT_MAP_1;\n      /* Fall through. */\n\n      case BROTLI_STATE_CONTEXT_MAP_1:\n        result = DecodeContextMap(\n            s->num_block_types[0] << BROTLI_LITERAL_CONTEXT_BITS,\n            &s->num_literal_htrees, &s->context_map, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        DetectTrivialLiteralBlockTypes(s);\n        s->state = BROTLI_STATE_CONTEXT_MAP_2;\n      /* Fall through. */\n\n      case BROTLI_STATE_CONTEXT_MAP_2: {\n        brotli_reg_t npostfix = s->distance_postfix_bits;\n        brotli_reg_t ndirect = s->num_direct_distance_codes;\n        brotli_reg_t distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n            npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);\n        brotli_reg_t distance_alphabet_size_limit = distance_alphabet_size_max;\n        BROTLI_BOOL allocation_success = BROTLI_TRUE;\n        if (s->large_window) {\n          BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(\n              BROTLI_MAX_ALLOWED_DISTANCE, (uint32_t)npostfix,\n              (uint32_t)ndirect);\n          distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n              npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);\n          distance_alphabet_size_limit = limit.max_alphabet_size;\n        }\n        result = DecodeContextMap(\n            s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,\n            &s->num_dist_htrees, &s->dist_context_map, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        allocation_success &= BrotliDecoderHuffmanTreeGroupInit(\n            s, &s->literal_hgroup, BROTLI_NUM_LITERAL_SYMBOLS,\n            BROTLI_NUM_LITERAL_SYMBOLS, s->num_literal_htrees);\n        allocation_success &= BrotliDecoderHuffmanTreeGroupInit(\n            s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS,\n            BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]);\n        allocation_success &= BrotliDecoderHuffmanTreeGroupInit(\n            s, &s->distance_hgroup, distance_alphabet_size_max,\n            distance_alphabet_size_limit, s->num_dist_htrees);\n        if (!allocation_success) {\n          return BROTLI_SAVE_ERROR_CODE(\n              BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));\n        }\n        s->loop_counter = 0;\n        s->state = BROTLI_STATE_TREE_GROUP;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_TREE_GROUP: {\n        HuffmanTreeGroup* hgroup = NULL;\n        switch (s->loop_counter) {\n          case 0: hgroup = &s->literal_hgroup; break;\n          case 1: hgroup = &s->insert_copy_hgroup; break;\n          case 2: hgroup = &s->distance_hgroup; break;\n          default: return BROTLI_SAVE_ERROR_CODE(BROTLI_FAILURE(\n              BROTLI_DECODER_ERROR_UNREACHABLE));  /* COV_NF_LINE */\n        }\n        result = HuffmanTreeGroupDecode(hgroup, s);\n        if (result != BROTLI_DECODER_SUCCESS) break;\n        s->loop_counter++;\n        if (s->loop_counter < 3) {\n          break;\n        }\n        s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY:\n        PrepareLiteralDecoding(s);\n        s->dist_context_map_slice = s->dist_context_map;\n        s->htree_command = s->insert_copy_hgroup.htrees[0];\n        if (!BrotliEnsureRingBuffer(s)) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);\n          break;\n        }\n        CalculateDistanceLut(s);\n        s->state = BROTLI_STATE_COMMAND_BEGIN;\n      /* Fall through. */\n\n      case BROTLI_STATE_COMMAND_BEGIN:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_INNER:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_WRAP_COPY:\n        result = ProcessCommands(s);\n        if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {\n          result = SafeProcessCommands(s);\n        }\n        break;\n\n      case BROTLI_STATE_COMMAND_INNER_WRITE:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_WRITE_1:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_WRITE_2:\n        result = WriteRingBuffer(\n            s, available_out, next_out, total_out, BROTLI_FALSE);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        WrapRingBuffer(s);\n        if (s->ringbuffer_size == 1 << s->window_bits) {\n          s->max_distance = s->max_backward_distance;\n        }\n        if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) {\n          BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;\n          if (addon && (addon->br_length != addon->br_copied)) {\n            s->pos += CopyFromCompoundDictionary(s, s->pos);\n            if (s->pos >= s->ringbuffer_size) continue;\n          }\n          if (s->meta_block_remaining_len == 0) {\n            /* Next metablock, if any. */\n            s->state = BROTLI_STATE_METABLOCK_DONE;\n          } else {\n            s->state = BROTLI_STATE_COMMAND_BEGIN;\n          }\n          break;\n        } else if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_2) {\n          s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY;\n        } else {  /* BROTLI_STATE_COMMAND_INNER_WRITE */\n          if (s->loop_counter == 0) {\n            if (s->meta_block_remaining_len == 0) {\n              s->state = BROTLI_STATE_METABLOCK_DONE;\n            } else {\n              s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;\n            }\n            break;\n          }\n          s->state = BROTLI_STATE_COMMAND_INNER;\n        }\n        break;\n\n      case BROTLI_STATE_METABLOCK_DONE:\n        if (s->meta_block_remaining_len < 0) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2);\n          break;\n        }\n        BrotliDecoderStateCleanupAfterMetablock(s);\n        if (!s->is_last_metablock) {\n          s->state = BROTLI_STATE_METABLOCK_BEGIN;\n          break;\n        }\n        if (!BrotliJumpToByteBoundary(br)) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_2);\n          break;\n        }\n        if (s->buffer_length == 0) {\n          BrotliBitReaderUnload(br);\n          *available_in = BrotliBitReaderGetAvailIn(br);\n          *next_in = br->next_in;\n        }\n        s->state = BROTLI_STATE_DONE;\n      /* Fall through. */\n\n      case BROTLI_STATE_DONE:\n        if (s->ringbuffer != 0) {\n          result = WriteRingBuffer(\n              s, available_out, next_out, total_out, BROTLI_TRUE);\n          if (result != BROTLI_DECODER_SUCCESS) {\n            break;\n          }\n        }\n        return BROTLI_SAVE_ERROR_CODE(result);\n    }\n  }\n  return BROTLI_SAVE_ERROR_CODE(result);\n#undef BROTLI_SAVE_ERROR_CODE\n}\n\nBROTLI_BOOL BrotliDecoderHasMoreOutput(const BrotliDecoderState* s) {\n  /* After unrecoverable error remaining output is considered nonsensical. */\n  if ((int)s->error_code < 0) {\n    return BROTLI_FALSE;\n  }\n  return TO_BROTLI_BOOL(\n      s->ringbuffer != 0 && UnwrittenBytes(s, BROTLI_FALSE) != 0);\n}\n\nconst uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) {\n  uint8_t* result = 0;\n  size_t available_out = *size ? *size : 1u << 24;\n  size_t requested_out = available_out;\n  BrotliDecoderErrorCode status;\n  if ((s->ringbuffer == 0) || ((int)s->error_code < 0)) {\n    *size = 0;\n    return 0;\n  }\n  WrapRingBuffer(s);\n  status = WriteRingBuffer(s, &available_out, &result, 0, BROTLI_TRUE);\n  /* Either WriteRingBuffer returns those \"success\" codes... */\n  if (status == BROTLI_DECODER_SUCCESS ||\n      status == BROTLI_DECODER_NEEDS_MORE_OUTPUT) {\n    *size = requested_out - available_out;\n  } else {\n    /* ... or stream is broken. Normally this should be caught by\n       BrotliDecoderDecompressStream, this is just a safeguard. */\n    if ((int)status < 0) SaveErrorCode(s, status, 0);\n    *size = 0;\n    result = 0;\n  }\n  return result;\n}\n\nBROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s) {\n  return TO_BROTLI_BOOL(s->state != BROTLI_STATE_UNINITED ||\n      BrotliGetAvailableBits(&s->br) != 0);\n}\n\nBROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s) {\n  return TO_BROTLI_BOOL(s->state == BROTLI_STATE_DONE) &&\n      !BrotliDecoderHasMoreOutput(s);\n}\n\nBrotliDecoderErrorCode BrotliDecoderGetErrorCode(const BrotliDecoderState* s) {\n  return (BrotliDecoderErrorCode)s->error_code;\n}\n\nconst char* BrotliDecoderErrorString(BrotliDecoderErrorCode c) {\n  switch (c) {\n#define BROTLI_ERROR_CODE_CASE_(PREFIX, NAME, CODE) \\\n    case BROTLI_DECODER ## PREFIX ## NAME: return #PREFIX #NAME;\n#define BROTLI_NOTHING_\n    BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_CASE_, BROTLI_NOTHING_)\n#undef BROTLI_ERROR_CODE_CASE_\n#undef BROTLI_NOTHING_\n    default: return \"INVALID\";\n  }\n}\n\nuint32_t BrotliDecoderVersion(void) {\n  return BROTLI_VERSION;\n}\n\nvoid BrotliDecoderSetMetadataCallbacks(\n    BrotliDecoderState* state,\n    brotli_decoder_metadata_start_func start_func,\n    brotli_decoder_metadata_chunk_func chunk_func, void* opaque) {\n  state->metadata_start_func = start_func;\n  state->metadata_chunk_func = chunk_func;\n  state->metadata_callback_opaque = opaque;\n}\n\n/* Escalate internal functions visibility; for testing purposes only. */\n#if defined(BROTLI_TEST)\nBROTLI_BOOL BrotliSafeReadSymbolForTest(\n    const HuffmanCode*, BrotliBitReader*, brotli_reg_t*);\nBROTLI_BOOL BrotliSafeReadSymbolForTest(\n    const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {\n  return SafeReadSymbol(table, br, result);\n}\nvoid BrotliInverseMoveToFrontTransformForTest(\n    uint8_t*, brotli_reg_t, BrotliDecoderState*);\nvoid BrotliInverseMoveToFrontTransformForTest(\n    uint8_t* v, brotli_reg_t l, BrotliDecoderState* s) {\n  InverseMoveToFrontTransform(v, l, s);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/huffman.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Utilities for building Huffman decoding tables. */\n\n#include \"huffman.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_REVERSE_BITS_MAX 8\n\n#if defined(BROTLI_RBIT)\n#define BROTLI_REVERSE_BITS_BASE \\\n  ((sizeof(brotli_reg_t) << 3) - BROTLI_REVERSE_BITS_MAX)\n#else\n#define BROTLI_REVERSE_BITS_BASE 0\nstatic BROTLI_MODEL(\"small\")\nuint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = {\n  0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,\n  0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,\n  0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,\n  0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,\n  0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,\n  0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,\n  0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,\n  0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,\n  0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,\n  0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,\n  0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,\n  0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,\n  0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,\n  0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,\n  0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,\n  0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,\n  0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,\n  0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,\n  0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,\n  0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,\n  0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,\n  0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,\n  0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,\n  0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,\n  0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,\n  0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,\n  0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,\n  0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,\n  0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,\n  0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,\n  0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,\n  0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF\n};\n#endif  /* BROTLI_RBIT */\n\n#define BROTLI_REVERSE_BITS_LOWEST \\\n  ((brotli_reg_t)1 << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE))\n\n/* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX),\n   where reverse(value, len) is the bit-wise reversal of the len least\n   significant bits of value. */\nstatic BROTLI_INLINE brotli_reg_t BrotliReverseBits(brotli_reg_t num) {\n#if defined(BROTLI_RBIT)\n  return BROTLI_RBIT(num);\n#else\n  return kReverseBits[num];\n#endif\n}\n\n/* Stores code in table[0], table[step], table[2*step], ..., table[end] */\n/* Assumes that end is an integer multiple of step */\nstatic BROTLI_INLINE void ReplicateValue(HuffmanCode* table,\n                                         int step, int end,\n                                         HuffmanCode code) {\n  do {\n    end -= step;\n    table[end] = code;\n  } while (end > 0);\n}\n\n/* Returns the table width of the next 2nd level table. |count| is the histogram\n   of bit lengths for the remaining symbols, |len| is the code length of the\n   next processed symbol. */\nstatic BROTLI_INLINE int NextTableBitSize(const uint16_t* const count,\n                                          int len, int root_bits) {\n  int left = 1 << (len - root_bits);\n  while (len < BROTLI_HUFFMAN_MAX_CODE_LENGTH) {\n    left -= count[len];\n    if (left <= 0) break;\n    ++len;\n    left <<= 1;\n  }\n  return len - root_bits;\n}\n\nvoid BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,\n                                        const uint8_t* const code_lengths,\n                                        uint16_t* count) {\n  HuffmanCode code;       /* current table entry */\n  int symbol;             /* symbol index in original or sorted table */\n  brotli_reg_t key;       /* prefix code */\n  brotli_reg_t key_step;  /* prefix code addend */\n  int step;               /* step size to replicate values in current table */\n  int table_size;         /* size of current table */\n  int sorted[BROTLI_CODE_LENGTH_CODES];  /* symbols sorted by code length */\n  /* offsets in sorted table for each length */\n  int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1];\n  int bits;\n  int bits_count;\n  BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <=\n                BROTLI_REVERSE_BITS_MAX);\n  BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5);\n\n  /* Generate offsets into sorted symbol table by code length. */\n  symbol = -1;\n  bits = 1;\n  /* BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5 */\n  BROTLI_REPEAT_5({\n    symbol += count[bits];\n    offset[bits] = symbol;\n    bits++;\n  });\n  /* Symbols with code length 0 are placed after all other symbols. */\n  offset[0] = BROTLI_CODE_LENGTH_CODES - 1;\n\n  /* Sort symbols by length, by symbol order within each length. */\n  symbol = BROTLI_CODE_LENGTH_CODES;\n  do {\n    BROTLI_REPEAT_6({\n      symbol--;\n      sorted[offset[code_lengths[symbol]]--] = symbol;\n    });\n  } while (symbol != 0);\n\n  table_size = 1 << BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH;\n\n  /* Special case: all symbols but one have 0 code length. */\n  if (offset[0] == 0) {\n    code = ConstructHuffmanCode(0, (uint16_t)sorted[0]);\n    for (key = 0; key < (brotli_reg_t)table_size; ++key) {\n      table[key] = code;\n    }\n    return;\n  }\n\n  /* Fill in table. */\n  key = 0;\n  key_step = BROTLI_REVERSE_BITS_LOWEST;\n  symbol = 0;\n  bits = 1;\n  step = 2;\n  do {\n    for (bits_count = count[bits]; bits_count != 0; --bits_count) {\n      code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)sorted[symbol++]);\n      ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);\n      key += key_step;\n    }\n    step <<= 1;\n    key_step >>= 1;\n  } while (++bits <= BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);\n}\n\nuint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,\n                                 int root_bits,\n                                 const uint16_t* const symbol_lists,\n                                 uint16_t* count) {\n  HuffmanCode code;       /* current table entry */\n  HuffmanCode* table;     /* next available space in table */\n  int len;                /* current code length */\n  int symbol;             /* symbol index in original or sorted table */\n  brotli_reg_t key;       /* prefix code */\n  brotli_reg_t key_step;  /* prefix code addend */\n  brotli_reg_t sub_key;   /* 2nd level table prefix code */\n  brotli_reg_t sub_key_step;  /* 2nd level table prefix code addend */\n  int step;               /* step size to replicate values in current table */\n  int table_bits;         /* key length of current table */\n  int table_size;         /* size of current table */\n  int total_size;         /* sum of root table size and 2nd level table sizes */\n  int max_length = -1;\n  int bits;\n  int bits_count;\n\n  BROTLI_DCHECK(root_bits <= BROTLI_REVERSE_BITS_MAX);\n  BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <=\n                BROTLI_REVERSE_BITS_MAX);\n\n  while (symbol_lists[max_length] == 0xFFFF) max_length--;\n  max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1;\n\n  table = root_table;\n  table_bits = root_bits;\n  table_size = 1 << table_bits;\n  total_size = table_size;\n\n  /* Fill in the root table. Reduce the table size to if possible,\n     and create the repetitions by memcpy. */\n  if (table_bits > max_length) {\n    table_bits = max_length;\n    table_size = 1 << table_bits;\n  }\n  key = 0;\n  key_step = BROTLI_REVERSE_BITS_LOWEST;\n  bits = 1;\n  step = 2;\n  do {\n    symbol = bits - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);\n    for (bits_count = count[bits]; bits_count != 0; --bits_count) {\n      symbol = symbol_lists[symbol];\n      code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)symbol);\n      ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);\n      key += key_step;\n    }\n    step <<= 1;\n    key_step >>= 1;\n  } while (++bits <= table_bits);\n\n  /* If root_bits != table_bits then replicate to fill the remaining slots. */\n  while (total_size != table_size) {\n    memcpy(&table[table_size], &table[0],\n           (size_t)table_size * sizeof(table[0]));\n    table_size <<= 1;\n  }\n\n  /* Fill in 2nd level tables and add pointers to root table. */\n  key_step = BROTLI_REVERSE_BITS_LOWEST >> (root_bits - 1);\n  sub_key = (BROTLI_REVERSE_BITS_LOWEST << 1);\n  sub_key_step = BROTLI_REVERSE_BITS_LOWEST;\n  for (len = root_bits + 1, step = 2; len <= max_length; ++len) {\n    symbol = len - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);\n    for (; count[len] != 0; --count[len]) {\n      if (sub_key == (BROTLI_REVERSE_BITS_LOWEST << 1U)) {\n        table += table_size;\n        table_bits = NextTableBitSize(count, len, root_bits);\n        table_size = 1 << table_bits;\n        total_size += table_size;\n        sub_key = BrotliReverseBits(key);\n        key += key_step;\n        root_table[sub_key] = ConstructHuffmanCode(\n            (uint8_t)(table_bits + root_bits),\n            (uint16_t)(((size_t)(table - root_table)) - sub_key));\n        sub_key = 0;\n      }\n      symbol = symbol_lists[symbol];\n      code = ConstructHuffmanCode((uint8_t)(len - root_bits), (uint16_t)symbol);\n      ReplicateValue(\n          &table[BrotliReverseBits(sub_key)], step, table_size, code);\n      sub_key += sub_key_step;\n    }\n    step <<= 1;\n    sub_key_step >>= 1;\n  }\n  return (uint32_t)total_size;\n}\n\nuint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,\n                                       int root_bits,\n                                       uint16_t* val,\n                                       uint32_t num_symbols) {\n  uint32_t table_size = 1;\n  const uint32_t goal_size = 1U << root_bits;\n  switch (num_symbols) {\n    case 0:\n      table[0] = ConstructHuffmanCode(0, val[0]);\n      break;\n    case 1:\n      if (val[1] > val[0]) {\n        table[0] = ConstructHuffmanCode(1, val[0]);\n        table[1] = ConstructHuffmanCode(1, val[1]);\n      } else {\n        table[0] = ConstructHuffmanCode(1, val[1]);\n        table[1] = ConstructHuffmanCode(1, val[0]);\n      }\n      table_size = 2;\n      break;\n    case 2:\n      table[0] = ConstructHuffmanCode(1, val[0]);\n      table[2] = ConstructHuffmanCode(1, val[0]);\n      if (val[2] > val[1]) {\n        table[1] = ConstructHuffmanCode(2, val[1]);\n        table[3] = ConstructHuffmanCode(2, val[2]);\n      } else {\n        table[1] = ConstructHuffmanCode(2, val[2]);\n        table[3] = ConstructHuffmanCode(2, val[1]);\n      }\n      table_size = 4;\n      break;\n    case 3: {\n      int i, k;\n      for (i = 0; i < 3; ++i) {\n        for (k = i + 1; k < 4; ++k) {\n          if (val[k] < val[i]) {\n            uint16_t t = val[k];\n            val[k] = val[i];\n            val[i] = t;\n          }\n        }\n      }\n      table[0] = ConstructHuffmanCode(2, val[0]);\n      table[2] = ConstructHuffmanCode(2, val[1]);\n      table[1] = ConstructHuffmanCode(2, val[2]);\n      table[3] = ConstructHuffmanCode(2, val[3]);\n      table_size = 4;\n      break;\n    }\n    case 4: {\n      if (val[3] < val[2]) {\n        uint16_t t = val[3];\n        val[3] = val[2];\n        val[2] = t;\n      }\n      table[0] = ConstructHuffmanCode(1, val[0]);\n      table[1] = ConstructHuffmanCode(2, val[1]);\n      table[2] = ConstructHuffmanCode(1, val[0]);\n      table[3] = ConstructHuffmanCode(3, val[2]);\n      table[4] = ConstructHuffmanCode(1, val[0]);\n      table[5] = ConstructHuffmanCode(2, val[1]);\n      table[6] = ConstructHuffmanCode(1, val[0]);\n      table[7] = ConstructHuffmanCode(3, val[3]);\n      table_size = 8;\n      break;\n    }\n  }\n  while (table_size != goal_size) {\n    memcpy(&table[table_size], &table[0],\n           (size_t)table_size * sizeof(table[0]));\n    table_size <<= 1;\n  }\n  return goal_size;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/huffman.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Utilities for building Huffman decoding tables. */\n\n#ifndef BROTLI_DEC_HUFFMAN_H_\n#define BROTLI_DEC_HUFFMAN_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15\n\n/* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */\n#define BROTLI_HUFFMAN_MAX_SIZE_26 396\n/* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */\n#define BROTLI_HUFFMAN_MAX_SIZE_258 632\n/* BROTLI_MAX_CONTEXT_MAP_SYMBOLS == 272 */\n#define BROTLI_HUFFMAN_MAX_SIZE_272 646\n\n#define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5\n\n#if ((defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_32)) && \\\n  BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0))\n#define BROTLI_HUFFMAN_CODE_FAST_LOAD\n#endif\n\n#if !defined(BROTLI_HUFFMAN_CODE_FAST_LOAD)\n/* Do not create this struct directly - use the ConstructHuffmanCode\n * constructor below! */\ntypedef struct {\n  uint8_t bits;    /* number of bits used for this symbol */\n  uint16_t value;  /* symbol value or table offset */\n} HuffmanCode;\n\nstatic BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,\n    const uint16_t value) {\n  HuffmanCode h;\n  h.bits = bits;\n  h.value = value;\n  return h;\n}\n\n/* Please use the following macros to optimize HuffmanCode accesses in hot\n * paths.\n *\n * For example, assuming |table| contains a HuffmanCode pointer:\n *\n *   BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n *   BROTLI_HC_ADJUST_TABLE_INDEX(table, index_into_table);\n *   *bits = BROTLI_HC_GET_BITS(table);\n *   *value = BROTLI_HC_GET_VALUE(table);\n *   BROTLI_HC_ADJUST_TABLE_INDEX(table, offset);\n *   *bits2 = BROTLI_HC_GET_BITS(table);\n *   *value2 = BROTLI_HC_GET_VALUE(table);\n *\n */\n\n#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H)\n#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V)\n\n/* These must be given a HuffmanCode pointer! */\n#define BROTLI_HC_FAST_LOAD_BITS(H) (H->bits)\n#define BROTLI_HC_FAST_LOAD_VALUE(H) (H->value)\n\n#else /* BROTLI_HUFFMAN_CODE_FAST_LOAD */\n\ntypedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;\n\nstatic BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,\n    const uint16_t value) {\n  return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF);\n}\n\n#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)\n#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V); __fastload_##H = (*H)\n\n/* These must be given a HuffmanCode pointer! */\n#define BROTLI_HC_FAST_LOAD_BITS(H) ((__fastload_##H) & 0xFF)\n#define BROTLI_HC_FAST_LOAD_VALUE(H) ((__fastload_##H) >> 16)\n#endif /* BROTLI_HUFFMAN_CODE_FAST_LOAD */\n\n/* Builds Huffman lookup table assuming code lengths are in symbol order. */\nBROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,\n    const uint8_t* const code_lengths, uint16_t* count);\n\n/* Builds Huffman lookup table assuming code lengths are in symbol order.\n   Returns size of resulting table. */\nBROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,\n    int root_bits, const uint16_t* const symbol_lists, uint16_t* count);\n\n/* Builds a simple Huffman table. The |num_symbols| parameter is to be\n   interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,\n   2 means 3 symbols, 3 means 4 symbols with lengths [2, 2, 2, 2],\n   4 means 4 symbols with lengths [1, 2, 3, 3]. */\nBROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,\n    int root_bits, uint16_t* symbols, uint32_t num_symbols);\n\n/* Contains a collection of Huffman trees with the same alphabet size. */\n/* alphabet_size_limit is needed due to simple codes, since\n   log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */\ntypedef struct {\n  HuffmanCode** htrees;\n  HuffmanCode* codes;\n  uint16_t alphabet_size_max;\n  uint16_t alphabet_size_limit;\n  uint16_t num_htrees;\n} HuffmanTreeGroup;\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_HUFFMAN_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/prefix.c",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"prefix.h\"\n\n#include \"../common/platform.h\"  /* IWYU pragma: keep */\n#include \"../common/static_init.h\"\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\n#include \"../common/constants.h\"\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)\n/* Embed kCmdLut. */\n#include \"prefix_inc.h\"\n#else\nBROTLI_COLD BROTLI_BOOL BrotliDecoderInitCmdLut(CmdLutElement* items) {\n  static const uint8_t kInsertLengthExtraBits[24] = {\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,\n      0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0E, 0x18};\n  static const uint8_t kCopyLengthExtraBits[24] = {\n      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,\n      0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x18};\n  static const uint8_t kCellPos[11] = {0, 1, 0, 1, 8, 9, 2, 16, 10, 17, 18};\n\n  uint16_t insert_length_offsets[24];\n  uint16_t copy_length_offsets[24];\n  insert_length_offsets[0] = 0;\n  copy_length_offsets[0] = 2;\n  for (size_t i = 0; i < 23; ++i) {\n    insert_length_offsets[i + 1] =\n        insert_length_offsets[i] + (uint16_t)(1u << kInsertLengthExtraBits[i]);\n    copy_length_offsets[i + 1] =\n        copy_length_offsets[i] + (uint16_t)(1u << kCopyLengthExtraBits[i]);\n  }\n\n  for (size_t symbol = 0; symbol < BROTLI_NUM_COMMAND_SYMBOLS; ++symbol) {\n    CmdLutElement* item = items + symbol;\n    const size_t cell_idx = symbol >> 6;\n    const size_t cell_pos = kCellPos[cell_idx];\n    const size_t copy_code = ((cell_pos << 3) & 0x18) + (symbol & 0x7);\n    const uint16_t copy_len_offset = copy_length_offsets[copy_code];\n    const size_t insert_code = (cell_pos & 0x18) + ((symbol >> 3) & 0x7);\n    item->copy_len_extra_bits = kCopyLengthExtraBits[copy_code];\n    item->context = (copy_len_offset > 4) ? 3 : ((uint8_t)copy_len_offset - 2);\n    item->copy_len_offset = copy_len_offset;\n    item->distance_code = (cell_idx >= 2) ? -1 : 0;\n    item->insert_len_extra_bits = kInsertLengthExtraBits[insert_code];\n    item->insert_len_offset = insert_length_offsets[insert_code];\n  }\n  return BROTLI_TRUE;\n}\n\nBROTLI_MODEL(\"small\")\nCmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];\n#endif  /* BROTLI_STATIC_INIT */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/prefix.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Lookup tables to map prefix codes to value ranges. This is used during\n   decoding of the block lengths, literal insertion lengths and copy lengths. */\n\n#ifndef BROTLI_DEC_PREFIX_H_\n#define BROTLI_DEC_PREFIX_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"  /* IWYU pragma: keep */\n#include \"../common/static_init.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct CmdLutElement {\n  uint8_t insert_len_extra_bits;\n  uint8_t copy_len_extra_bits;\n  int8_t distance_code;\n  uint8_t context;\n  uint16_t insert_len_offset;\n  uint16_t copy_len_offset;\n} CmdLutElement;\n\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\")\n    CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];\n#else\nBROTLI_INTERNAL BROTLI_BOOL BrotliDecoderInitCmdLut(CmdLutElement* items);\nBROTLI_INTERNAL extern BROTLI_MODEL(\"small\")\n    CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS];\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_PREFIX_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/prefix_inc.h",
    "content": "﻿const BROTLI_MODEL(\"small\")\nCmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS] = {\n  { 0x00, 0x00, 0, 0x00, 0x0000, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0000, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0000, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0001, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0001, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0001, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0002, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0002, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0002, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0003, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0003, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0003, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0004, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0004, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0004, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0005, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0005, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0005, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0009 },\n  { 0x01, 0x00, 0, 0x00, 0x0006, 0x0002 },\n  { 0x01, 0x00, 0, 0x01, 0x0006, 0x0003 },\n  { 0x01, 0x00, 0, 0x02, 0x0006, 0x0004 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0005 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0006 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0007 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0008 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0009 },\n  { 0x01, 0x00, 0, 0x00, 0x0008, 0x0002 },\n  { 0x01, 0x00, 0, 0x01, 0x0008, 0x0003 },\n  { 0x01, 0x00, 0, 0x02, 0x0008, 0x0004 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0005 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0006 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0007 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0008 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0009 },\n  { 0x00, 0x01, 0, 0x03, 0x0000, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0000, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0000, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0000, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0000, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0000, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0000, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0000, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0001, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0001, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0001, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0001, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0001, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0001, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0001, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0001, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0002, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0002, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0002, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0002, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0002, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0002, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0002, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0002, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0003, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0003, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0003, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0003, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0003, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0003, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0003, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0003, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0004, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0004, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0004, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0004, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0004, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0004, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0004, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0004, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0005, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0005, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0005, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0005, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0005, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0005, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0005, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0005, 0x0036 },\n  { 0x01, 0x01, 0, 0x03, 0x0006, 0x000a },\n  { 0x01, 0x01, 0, 0x03, 0x0006, 0x000c },\n  { 0x01, 0x02, 0, 0x03, 0x0006, 0x000e },\n  { 0x01, 0x02, 0, 0x03, 0x0006, 0x0012 },\n  { 0x01, 0x03, 0, 0x03, 0x0006, 0x0016 },\n  { 0x01, 0x03, 0, 0x03, 0x0006, 0x001e },\n  { 0x01, 0x04, 0, 0x03, 0x0006, 0x0026 },\n  { 0x01, 0x04, 0, 0x03, 0x0006, 0x0036 },\n  { 0x01, 0x01, 0, 0x03, 0x0008, 0x000a },\n  { 0x01, 0x01, 0, 0x03, 0x0008, 0x000c },\n  { 0x01, 0x02, 0, 0x03, 0x0008, 0x000e },\n  { 0x01, 0x02, 0, 0x03, 0x0008, 0x0012 },\n  { 0x01, 0x03, 0, 0x03, 0x0008, 0x0016 },\n  { 0x01, 0x03, 0, 0x03, 0x0008, 0x001e },\n  { 0x01, 0x04, 0, 0x03, 0x0008, 0x0026 },\n  { 0x01, 0x04, 0, 0x03, 0x0008, 0x0036 },\n  { 0x00, 0x00, -1, 0x00, 0x0000, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0000, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0000, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0001, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0001, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0001, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0002, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0002, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0002, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0003, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0003, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0003, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0004, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0004, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0004, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0005, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0005, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0005, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0009 },\n  { 0x01, 0x00, -1, 0x00, 0x0006, 0x0002 },\n  { 0x01, 0x00, -1, 0x01, 0x0006, 0x0003 },\n  { 0x01, 0x00, -1, 0x02, 0x0006, 0x0004 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0005 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0006 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0007 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0008 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0009 },\n  { 0x01, 0x00, -1, 0x00, 0x0008, 0x0002 },\n  { 0x01, 0x00, -1, 0x01, 0x0008, 0x0003 },\n  { 0x01, 0x00, -1, 0x02, 0x0008, 0x0004 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0005 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0006 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0007 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0008 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0009 },\n  { 0x00, 0x01, -1, 0x03, 0x0000, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0000, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0000, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0000, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0000, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0000, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0000, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0000, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0001, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0001, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0001, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0001, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0001, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0001, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0001, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0001, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0002, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0002, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0002, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0002, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0002, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0002, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0002, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0002, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0003, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0003, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0003, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0003, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0003, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0003, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0003, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0003, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0004, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0004, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0004, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0004, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0004, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0004, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0004, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0004, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0005, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0005, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0005, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0005, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0005, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0005, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0005, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0005, 0x0036 },\n  { 0x01, 0x01, -1, 0x03, 0x0006, 0x000a },\n  { 0x01, 0x01, -1, 0x03, 0x0006, 0x000c },\n  { 0x01, 0x02, -1, 0x03, 0x0006, 0x000e },\n  { 0x01, 0x02, -1, 0x03, 0x0006, 0x0012 },\n  { 0x01, 0x03, -1, 0x03, 0x0006, 0x0016 },\n  { 0x01, 0x03, -1, 0x03, 0x0006, 0x001e },\n  { 0x01, 0x04, -1, 0x03, 0x0006, 0x0026 },\n  { 0x01, 0x04, -1, 0x03, 0x0006, 0x0036 },\n  { 0x01, 0x01, -1, 0x03, 0x0008, 0x000a },\n  { 0x01, 0x01, -1, 0x03, 0x0008, 0x000c },\n  { 0x01, 0x02, -1, 0x03, 0x0008, 0x000e },\n  { 0x01, 0x02, -1, 0x03, 0x0008, 0x0012 },\n  { 0x01, 0x03, -1, 0x03, 0x0008, 0x0016 },\n  { 0x01, 0x03, -1, 0x03, 0x0008, 0x001e },\n  { 0x01, 0x04, -1, 0x03, 0x0008, 0x0026 },\n  { 0x01, 0x04, -1, 0x03, 0x0008, 0x0036 },\n  { 0x02, 0x00, -1, 0x00, 0x000a, 0x0002 },\n  { 0x02, 0x00, -1, 0x01, 0x000a, 0x0003 },\n  { 0x02, 0x00, -1, 0x02, 0x000a, 0x0004 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0005 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0006 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0007 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0008 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0009 },\n  { 0x02, 0x00, -1, 0x00, 0x000e, 0x0002 },\n  { 0x02, 0x00, -1, 0x01, 0x000e, 0x0003 },\n  { 0x02, 0x00, -1, 0x02, 0x000e, 0x0004 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0005 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0006 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0007 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0008 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0009 },\n  { 0x03, 0x00, -1, 0x00, 0x0012, 0x0002 },\n  { 0x03, 0x00, -1, 0x01, 0x0012, 0x0003 },\n  { 0x03, 0x00, -1, 0x02, 0x0012, 0x0004 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0005 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0006 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0007 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0008 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0009 },\n  { 0x03, 0x00, -1, 0x00, 0x001a, 0x0002 },\n  { 0x03, 0x00, -1, 0x01, 0x001a, 0x0003 },\n  { 0x03, 0x00, -1, 0x02, 0x001a, 0x0004 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0005 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0006 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0007 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0008 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0009 },\n  { 0x04, 0x00, -1, 0x00, 0x0022, 0x0002 },\n  { 0x04, 0x00, -1, 0x01, 0x0022, 0x0003 },\n  { 0x04, 0x00, -1, 0x02, 0x0022, 0x0004 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0005 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0006 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0007 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0008 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0009 },\n  { 0x04, 0x00, -1, 0x00, 0x0032, 0x0002 },\n  { 0x04, 0x00, -1, 0x01, 0x0032, 0x0003 },\n  { 0x04, 0x00, -1, 0x02, 0x0032, 0x0004 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0005 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0006 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0007 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0008 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0009 },\n  { 0x05, 0x00, -1, 0x00, 0x0042, 0x0002 },\n  { 0x05, 0x00, -1, 0x01, 0x0042, 0x0003 },\n  { 0x05, 0x00, -1, 0x02, 0x0042, 0x0004 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0005 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0006 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0007 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0008 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0009 },\n  { 0x05, 0x00, -1, 0x00, 0x0062, 0x0002 },\n  { 0x05, 0x00, -1, 0x01, 0x0062, 0x0003 },\n  { 0x05, 0x00, -1, 0x02, 0x0062, 0x0004 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0005 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0006 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0007 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0008 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0009 },\n  { 0x02, 0x01, -1, 0x03, 0x000a, 0x000a },\n  { 0x02, 0x01, -1, 0x03, 0x000a, 0x000c },\n  { 0x02, 0x02, -1, 0x03, 0x000a, 0x000e },\n  { 0x02, 0x02, -1, 0x03, 0x000a, 0x0012 },\n  { 0x02, 0x03, -1, 0x03, 0x000a, 0x0016 },\n  { 0x02, 0x03, -1, 0x03, 0x000a, 0x001e },\n  { 0x02, 0x04, -1, 0x03, 0x000a, 0x0026 },\n  { 0x02, 0x04, -1, 0x03, 0x000a, 0x0036 },\n  { 0x02, 0x01, -1, 0x03, 0x000e, 0x000a },\n  { 0x02, 0x01, -1, 0x03, 0x000e, 0x000c },\n  { 0x02, 0x02, -1, 0x03, 0x000e, 0x000e },\n  { 0x02, 0x02, -1, 0x03, 0x000e, 0x0012 },\n  { 0x02, 0x03, -1, 0x03, 0x000e, 0x0016 },\n  { 0x02, 0x03, -1, 0x03, 0x000e, 0x001e },\n  { 0x02, 0x04, -1, 0x03, 0x000e, 0x0026 },\n  { 0x02, 0x04, -1, 0x03, 0x000e, 0x0036 },\n  { 0x03, 0x01, -1, 0x03, 0x0012, 0x000a },\n  { 0x03, 0x01, -1, 0x03, 0x0012, 0x000c },\n  { 0x03, 0x02, -1, 0x03, 0x0012, 0x000e },\n  { 0x03, 0x02, -1, 0x03, 0x0012, 0x0012 },\n  { 0x03, 0x03, -1, 0x03, 0x0012, 0x0016 },\n  { 0x03, 0x03, -1, 0x03, 0x0012, 0x001e },\n  { 0x03, 0x04, -1, 0x03, 0x0012, 0x0026 },\n  { 0x03, 0x04, -1, 0x03, 0x0012, 0x0036 },\n  { 0x03, 0x01, -1, 0x03, 0x001a, 0x000a },\n  { 0x03, 0x01, -1, 0x03, 0x001a, 0x000c },\n  { 0x03, 0x02, -1, 0x03, 0x001a, 0x000e },\n  { 0x03, 0x02, -1, 0x03, 0x001a, 0x0012 },\n  { 0x03, 0x03, -1, 0x03, 0x001a, 0x0016 },\n  { 0x03, 0x03, -1, 0x03, 0x001a, 0x001e },\n  { 0x03, 0x04, -1, 0x03, 0x001a, 0x0026 },\n  { 0x03, 0x04, -1, 0x03, 0x001a, 0x0036 },\n  { 0x04, 0x01, -1, 0x03, 0x0022, 0x000a },\n  { 0x04, 0x01, -1, 0x03, 0x0022, 0x000c },\n  { 0x04, 0x02, -1, 0x03, 0x0022, 0x000e },\n  { 0x04, 0x02, -1, 0x03, 0x0022, 0x0012 },\n  { 0x04, 0x03, -1, 0x03, 0x0022, 0x0016 },\n  { 0x04, 0x03, -1, 0x03, 0x0022, 0x001e },\n  { 0x04, 0x04, -1, 0x03, 0x0022, 0x0026 },\n  { 0x04, 0x04, -1, 0x03, 0x0022, 0x0036 },\n  { 0x04, 0x01, -1, 0x03, 0x0032, 0x000a },\n  { 0x04, 0x01, -1, 0x03, 0x0032, 0x000c },\n  { 0x04, 0x02, -1, 0x03, 0x0032, 0x000e },\n  { 0x04, 0x02, -1, 0x03, 0x0032, 0x0012 },\n  { 0x04, 0x03, -1, 0x03, 0x0032, 0x0016 },\n  { 0x04, 0x03, -1, 0x03, 0x0032, 0x001e },\n  { 0x04, 0x04, -1, 0x03, 0x0032, 0x0026 },\n  { 0x04, 0x04, -1, 0x03, 0x0032, 0x0036 },\n  { 0x05, 0x01, -1, 0x03, 0x0042, 0x000a },\n  { 0x05, 0x01, -1, 0x03, 0x0042, 0x000c },\n  { 0x05, 0x02, -1, 0x03, 0x0042, 0x000e },\n  { 0x05, 0x02, -1, 0x03, 0x0042, 0x0012 },\n  { 0x05, 0x03, -1, 0x03, 0x0042, 0x0016 },\n  { 0x05, 0x03, -1, 0x03, 0x0042, 0x001e },\n  { 0x05, 0x04, -1, 0x03, 0x0042, 0x0026 },\n  { 0x05, 0x04, -1, 0x03, 0x0042, 0x0036 },\n  { 0x05, 0x01, -1, 0x03, 0x0062, 0x000a },\n  { 0x05, 0x01, -1, 0x03, 0x0062, 0x000c },\n  { 0x05, 0x02, -1, 0x03, 0x0062, 0x000e },\n  { 0x05, 0x02, -1, 0x03, 0x0062, 0x0012 },\n  { 0x05, 0x03, -1, 0x03, 0x0062, 0x0016 },\n  { 0x05, 0x03, -1, 0x03, 0x0062, 0x001e },\n  { 0x05, 0x04, -1, 0x03, 0x0062, 0x0026 },\n  { 0x05, 0x04, -1, 0x03, 0x0062, 0x0036 },\n  { 0x00, 0x05, -1, 0x03, 0x0000, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0000, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0000, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0000, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0000, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0000, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0000, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0000, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0001, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0001, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0001, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0001, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0001, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0001, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0001, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0001, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0002, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0002, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0002, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0002, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0002, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0002, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0002, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0002, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0003, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0003, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0003, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0003, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0003, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0003, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0003, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0003, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0004, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0004, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0004, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0004, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0004, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0004, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0004, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0004, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0005, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0005, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0005, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0005, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0005, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0005, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0005, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0005, 0x0846 },\n  { 0x01, 0x05, -1, 0x03, 0x0006, 0x0046 },\n  { 0x01, 0x05, -1, 0x03, 0x0006, 0x0066 },\n  { 0x01, 0x06, -1, 0x03, 0x0006, 0x0086 },\n  { 0x01, 0x07, -1, 0x03, 0x0006, 0x00c6 },\n  { 0x01, 0x08, -1, 0x03, 0x0006, 0x0146 },\n  { 0x01, 0x09, -1, 0x03, 0x0006, 0x0246 },\n  { 0x01, 0x0a, -1, 0x03, 0x0006, 0x0446 },\n  { 0x01, 0x18, -1, 0x03, 0x0006, 0x0846 },\n  { 0x01, 0x05, -1, 0x03, 0x0008, 0x0046 },\n  { 0x01, 0x05, -1, 0x03, 0x0008, 0x0066 },\n  { 0x01, 0x06, -1, 0x03, 0x0008, 0x0086 },\n  { 0x01, 0x07, -1, 0x03, 0x0008, 0x00c6 },\n  { 0x01, 0x08, -1, 0x03, 0x0008, 0x0146 },\n  { 0x01, 0x09, -1, 0x03, 0x0008, 0x0246 },\n  { 0x01, 0x0a, -1, 0x03, 0x0008, 0x0446 },\n  { 0x01, 0x18, -1, 0x03, 0x0008, 0x0846 },\n  { 0x06, 0x00, -1, 0x00, 0x0082, 0x0002 },\n  { 0x06, 0x00, -1, 0x01, 0x0082, 0x0003 },\n  { 0x06, 0x00, -1, 0x02, 0x0082, 0x0004 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0005 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0006 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0007 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0008 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0009 },\n  { 0x07, 0x00, -1, 0x00, 0x00c2, 0x0002 },\n  { 0x07, 0x00, -1, 0x01, 0x00c2, 0x0003 },\n  { 0x07, 0x00, -1, 0x02, 0x00c2, 0x0004 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0005 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0006 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0007 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0008 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0009 },\n  { 0x08, 0x00, -1, 0x00, 0x0142, 0x0002 },\n  { 0x08, 0x00, -1, 0x01, 0x0142, 0x0003 },\n  { 0x08, 0x00, -1, 0x02, 0x0142, 0x0004 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0005 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0006 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0007 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0008 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0009 },\n  { 0x09, 0x00, -1, 0x00, 0x0242, 0x0002 },\n  { 0x09, 0x00, -1, 0x01, 0x0242, 0x0003 },\n  { 0x09, 0x00, -1, 0x02, 0x0242, 0x0004 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0005 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0006 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0007 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0008 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0009 },\n  { 0x0a, 0x00, -1, 0x00, 0x0442, 0x0002 },\n  { 0x0a, 0x00, -1, 0x01, 0x0442, 0x0003 },\n  { 0x0a, 0x00, -1, 0x02, 0x0442, 0x0004 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0005 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0006 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0007 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0008 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0009 },\n  { 0x0c, 0x00, -1, 0x00, 0x0842, 0x0002 },\n  { 0x0c, 0x00, -1, 0x01, 0x0842, 0x0003 },\n  { 0x0c, 0x00, -1, 0x02, 0x0842, 0x0004 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0005 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0006 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0007 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0008 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0009 },\n  { 0x0e, 0x00, -1, 0x00, 0x1842, 0x0002 },\n  { 0x0e, 0x00, -1, 0x01, 0x1842, 0x0003 },\n  { 0x0e, 0x00, -1, 0x02, 0x1842, 0x0004 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0005 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0006 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0007 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0008 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0009 },\n  { 0x18, 0x00, -1, 0x00, 0x5842, 0x0002 },\n  { 0x18, 0x00, -1, 0x01, 0x5842, 0x0003 },\n  { 0x18, 0x00, -1, 0x02, 0x5842, 0x0004 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0005 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0006 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0007 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0008 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0009 },\n  { 0x02, 0x05, -1, 0x03, 0x000a, 0x0046 },\n  { 0x02, 0x05, -1, 0x03, 0x000a, 0x0066 },\n  { 0x02, 0x06, -1, 0x03, 0x000a, 0x0086 },\n  { 0x02, 0x07, -1, 0x03, 0x000a, 0x00c6 },\n  { 0x02, 0x08, -1, 0x03, 0x000a, 0x0146 },\n  { 0x02, 0x09, -1, 0x03, 0x000a, 0x0246 },\n  { 0x02, 0x0a, -1, 0x03, 0x000a, 0x0446 },\n  { 0x02, 0x18, -1, 0x03, 0x000a, 0x0846 },\n  { 0x02, 0x05, -1, 0x03, 0x000e, 0x0046 },\n  { 0x02, 0x05, -1, 0x03, 0x000e, 0x0066 },\n  { 0x02, 0x06, -1, 0x03, 0x000e, 0x0086 },\n  { 0x02, 0x07, -1, 0x03, 0x000e, 0x00c6 },\n  { 0x02, 0x08, -1, 0x03, 0x000e, 0x0146 },\n  { 0x02, 0x09, -1, 0x03, 0x000e, 0x0246 },\n  { 0x02, 0x0a, -1, 0x03, 0x000e, 0x0446 },\n  { 0x02, 0x18, -1, 0x03, 0x000e, 0x0846 },\n  { 0x03, 0x05, -1, 0x03, 0x0012, 0x0046 },\n  { 0x03, 0x05, -1, 0x03, 0x0012, 0x0066 },\n  { 0x03, 0x06, -1, 0x03, 0x0012, 0x0086 },\n  { 0x03, 0x07, -1, 0x03, 0x0012, 0x00c6 },\n  { 0x03, 0x08, -1, 0x03, 0x0012, 0x0146 },\n  { 0x03, 0x09, -1, 0x03, 0x0012, 0x0246 },\n  { 0x03, 0x0a, -1, 0x03, 0x0012, 0x0446 },\n  { 0x03, 0x18, -1, 0x03, 0x0012, 0x0846 },\n  { 0x03, 0x05, -1, 0x03, 0x001a, 0x0046 },\n  { 0x03, 0x05, -1, 0x03, 0x001a, 0x0066 },\n  { 0x03, 0x06, -1, 0x03, 0x001a, 0x0086 },\n  { 0x03, 0x07, -1, 0x03, 0x001a, 0x00c6 },\n  { 0x03, 0x08, -1, 0x03, 0x001a, 0x0146 },\n  { 0x03, 0x09, -1, 0x03, 0x001a, 0x0246 },\n  { 0x03, 0x0a, -1, 0x03, 0x001a, 0x0446 },\n  { 0x03, 0x18, -1, 0x03, 0x001a, 0x0846 },\n  { 0x04, 0x05, -1, 0x03, 0x0022, 0x0046 },\n  { 0x04, 0x05, -1, 0x03, 0x0022, 0x0066 },\n  { 0x04, 0x06, -1, 0x03, 0x0022, 0x0086 },\n  { 0x04, 0x07, -1, 0x03, 0x0022, 0x00c6 },\n  { 0x04, 0x08, -1, 0x03, 0x0022, 0x0146 },\n  { 0x04, 0x09, -1, 0x03, 0x0022, 0x0246 },\n  { 0x04, 0x0a, -1, 0x03, 0x0022, 0x0446 },\n  { 0x04, 0x18, -1, 0x03, 0x0022, 0x0846 },\n  { 0x04, 0x05, -1, 0x03, 0x0032, 0x0046 },\n  { 0x04, 0x05, -1, 0x03, 0x0032, 0x0066 },\n  { 0x04, 0x06, -1, 0x03, 0x0032, 0x0086 },\n  { 0x04, 0x07, -1, 0x03, 0x0032, 0x00c6 },\n  { 0x04, 0x08, -1, 0x03, 0x0032, 0x0146 },\n  { 0x04, 0x09, -1, 0x03, 0x0032, 0x0246 },\n  { 0x04, 0x0a, -1, 0x03, 0x0032, 0x0446 },\n  { 0x04, 0x18, -1, 0x03, 0x0032, 0x0846 },\n  { 0x05, 0x05, -1, 0x03, 0x0042, 0x0046 },\n  { 0x05, 0x05, -1, 0x03, 0x0042, 0x0066 },\n  { 0x05, 0x06, -1, 0x03, 0x0042, 0x0086 },\n  { 0x05, 0x07, -1, 0x03, 0x0042, 0x00c6 },\n  { 0x05, 0x08, -1, 0x03, 0x0042, 0x0146 },\n  { 0x05, 0x09, -1, 0x03, 0x0042, 0x0246 },\n  { 0x05, 0x0a, -1, 0x03, 0x0042, 0x0446 },\n  { 0x05, 0x18, -1, 0x03, 0x0042, 0x0846 },\n  { 0x05, 0x05, -1, 0x03, 0x0062, 0x0046 },\n  { 0x05, 0x05, -1, 0x03, 0x0062, 0x0066 },\n  { 0x05, 0x06, -1, 0x03, 0x0062, 0x0086 },\n  { 0x05, 0x07, -1, 0x03, 0x0062, 0x00c6 },\n  { 0x05, 0x08, -1, 0x03, 0x0062, 0x0146 },\n  { 0x05, 0x09, -1, 0x03, 0x0062, 0x0246 },\n  { 0x05, 0x0a, -1, 0x03, 0x0062, 0x0446 },\n  { 0x05, 0x18, -1, 0x03, 0x0062, 0x0846 },\n  { 0x06, 0x01, -1, 0x03, 0x0082, 0x000a },\n  { 0x06, 0x01, -1, 0x03, 0x0082, 0x000c },\n  { 0x06, 0x02, -1, 0x03, 0x0082, 0x000e },\n  { 0x06, 0x02, -1, 0x03, 0x0082, 0x0012 },\n  { 0x06, 0x03, -1, 0x03, 0x0082, 0x0016 },\n  { 0x06, 0x03, -1, 0x03, 0x0082, 0x001e },\n  { 0x06, 0x04, -1, 0x03, 0x0082, 0x0026 },\n  { 0x06, 0x04, -1, 0x03, 0x0082, 0x0036 },\n  { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000a },\n  { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000c },\n  { 0x07, 0x02, -1, 0x03, 0x00c2, 0x000e },\n  { 0x07, 0x02, -1, 0x03, 0x00c2, 0x0012 },\n  { 0x07, 0x03, -1, 0x03, 0x00c2, 0x0016 },\n  { 0x07, 0x03, -1, 0x03, 0x00c2, 0x001e },\n  { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0026 },\n  { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0036 },\n  { 0x08, 0x01, -1, 0x03, 0x0142, 0x000a },\n  { 0x08, 0x01, -1, 0x03, 0x0142, 0x000c },\n  { 0x08, 0x02, -1, 0x03, 0x0142, 0x000e },\n  { 0x08, 0x02, -1, 0x03, 0x0142, 0x0012 },\n  { 0x08, 0x03, -1, 0x03, 0x0142, 0x0016 },\n  { 0x08, 0x03, -1, 0x03, 0x0142, 0x001e },\n  { 0x08, 0x04, -1, 0x03, 0x0142, 0x0026 },\n  { 0x08, 0x04, -1, 0x03, 0x0142, 0x0036 },\n  { 0x09, 0x01, -1, 0x03, 0x0242, 0x000a },\n  { 0x09, 0x01, -1, 0x03, 0x0242, 0x000c },\n  { 0x09, 0x02, -1, 0x03, 0x0242, 0x000e },\n  { 0x09, 0x02, -1, 0x03, 0x0242, 0x0012 },\n  { 0x09, 0x03, -1, 0x03, 0x0242, 0x0016 },\n  { 0x09, 0x03, -1, 0x03, 0x0242, 0x001e },\n  { 0x09, 0x04, -1, 0x03, 0x0242, 0x0026 },\n  { 0x09, 0x04, -1, 0x03, 0x0242, 0x0036 },\n  { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000a },\n  { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000c },\n  { 0x0a, 0x02, -1, 0x03, 0x0442, 0x000e },\n  { 0x0a, 0x02, -1, 0x03, 0x0442, 0x0012 },\n  { 0x0a, 0x03, -1, 0x03, 0x0442, 0x0016 },\n  { 0x0a, 0x03, -1, 0x03, 0x0442, 0x001e },\n  { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0026 },\n  { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0036 },\n  { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000a },\n  { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000c },\n  { 0x0c, 0x02, -1, 0x03, 0x0842, 0x000e },\n  { 0x0c, 0x02, -1, 0x03, 0x0842, 0x0012 },\n  { 0x0c, 0x03, -1, 0x03, 0x0842, 0x0016 },\n  { 0x0c, 0x03, -1, 0x03, 0x0842, 0x001e },\n  { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0026 },\n  { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0036 },\n  { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000a },\n  { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000c },\n  { 0x0e, 0x02, -1, 0x03, 0x1842, 0x000e },\n  { 0x0e, 0x02, -1, 0x03, 0x1842, 0x0012 },\n  { 0x0e, 0x03, -1, 0x03, 0x1842, 0x0016 },\n  { 0x0e, 0x03, -1, 0x03, 0x1842, 0x001e },\n  { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0026 },\n  { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0036 },\n  { 0x18, 0x01, -1, 0x03, 0x5842, 0x000a },\n  { 0x18, 0x01, -1, 0x03, 0x5842, 0x000c },\n  { 0x18, 0x02, -1, 0x03, 0x5842, 0x000e },\n  { 0x18, 0x02, -1, 0x03, 0x5842, 0x0012 },\n  { 0x18, 0x03, -1, 0x03, 0x5842, 0x0016 },\n  { 0x18, 0x03, -1, 0x03, 0x5842, 0x001e },\n  { 0x18, 0x04, -1, 0x03, 0x5842, 0x0026 },\n  { 0x18, 0x04, -1, 0x03, 0x5842, 0x0036 },\n  { 0x06, 0x05, -1, 0x03, 0x0082, 0x0046 },\n  { 0x06, 0x05, -1, 0x03, 0x0082, 0x0066 },\n  { 0x06, 0x06, -1, 0x03, 0x0082, 0x0086 },\n  { 0x06, 0x07, -1, 0x03, 0x0082, 0x00c6 },\n  { 0x06, 0x08, -1, 0x03, 0x0082, 0x0146 },\n  { 0x06, 0x09, -1, 0x03, 0x0082, 0x0246 },\n  { 0x06, 0x0a, -1, 0x03, 0x0082, 0x0446 },\n  { 0x06, 0x18, -1, 0x03, 0x0082, 0x0846 },\n  { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0046 },\n  { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0066 },\n  { 0x07, 0x06, -1, 0x03, 0x00c2, 0x0086 },\n  { 0x07, 0x07, -1, 0x03, 0x00c2, 0x00c6 },\n  { 0x07, 0x08, -1, 0x03, 0x00c2, 0x0146 },\n  { 0x07, 0x09, -1, 0x03, 0x00c2, 0x0246 },\n  { 0x07, 0x0a, -1, 0x03, 0x00c2, 0x0446 },\n  { 0x07, 0x18, -1, 0x03, 0x00c2, 0x0846 },\n  { 0x08, 0x05, -1, 0x03, 0x0142, 0x0046 },\n  { 0x08, 0x05, -1, 0x03, 0x0142, 0x0066 },\n  { 0x08, 0x06, -1, 0x03, 0x0142, 0x0086 },\n  { 0x08, 0x07, -1, 0x03, 0x0142, 0x00c6 },\n  { 0x08, 0x08, -1, 0x03, 0x0142, 0x0146 },\n  { 0x08, 0x09, -1, 0x03, 0x0142, 0x0246 },\n  { 0x08, 0x0a, -1, 0x03, 0x0142, 0x0446 },\n  { 0x08, 0x18, -1, 0x03, 0x0142, 0x0846 },\n  { 0x09, 0x05, -1, 0x03, 0x0242, 0x0046 },\n  { 0x09, 0x05, -1, 0x03, 0x0242, 0x0066 },\n  { 0x09, 0x06, -1, 0x03, 0x0242, 0x0086 },\n  { 0x09, 0x07, -1, 0x03, 0x0242, 0x00c6 },\n  { 0x09, 0x08, -1, 0x03, 0x0242, 0x0146 },\n  { 0x09, 0x09, -1, 0x03, 0x0242, 0x0246 },\n  { 0x09, 0x0a, -1, 0x03, 0x0242, 0x0446 },\n  { 0x09, 0x18, -1, 0x03, 0x0242, 0x0846 },\n  { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0046 },\n  { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0066 },\n  { 0x0a, 0x06, -1, 0x03, 0x0442, 0x0086 },\n  { 0x0a, 0x07, -1, 0x03, 0x0442, 0x00c6 },\n  { 0x0a, 0x08, -1, 0x03, 0x0442, 0x0146 },\n  { 0x0a, 0x09, -1, 0x03, 0x0442, 0x0246 },\n  { 0x0a, 0x0a, -1, 0x03, 0x0442, 0x0446 },\n  { 0x0a, 0x18, -1, 0x03, 0x0442, 0x0846 },\n  { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0046 },\n  { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0066 },\n  { 0x0c, 0x06, -1, 0x03, 0x0842, 0x0086 },\n  { 0x0c, 0x07, -1, 0x03, 0x0842, 0x00c6 },\n  { 0x0c, 0x08, -1, 0x03, 0x0842, 0x0146 },\n  { 0x0c, 0x09, -1, 0x03, 0x0842, 0x0246 },\n  { 0x0c, 0x0a, -1, 0x03, 0x0842, 0x0446 },\n  { 0x0c, 0x18, -1, 0x03, 0x0842, 0x0846 },\n  { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0046 },\n  { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0066 },\n  { 0x0e, 0x06, -1, 0x03, 0x1842, 0x0086 },\n  { 0x0e, 0x07, -1, 0x03, 0x1842, 0x00c6 },\n  { 0x0e, 0x08, -1, 0x03, 0x1842, 0x0146 },\n  { 0x0e, 0x09, -1, 0x03, 0x1842, 0x0246 },\n  { 0x0e, 0x0a, -1, 0x03, 0x1842, 0x0446 },\n  { 0x0e, 0x18, -1, 0x03, 0x1842, 0x0846 },\n  { 0x18, 0x05, -1, 0x03, 0x5842, 0x0046 },\n  { 0x18, 0x05, -1, 0x03, 0x5842, 0x0066 },\n  { 0x18, 0x06, -1, 0x03, 0x5842, 0x0086 },\n  { 0x18, 0x07, -1, 0x03, 0x5842, 0x00c6 },\n  { 0x18, 0x08, -1, 0x03, 0x5842, 0x0146 },\n  { 0x18, 0x09, -1, 0x03, 0x5842, 0x0246 },\n  { 0x18, 0x0a, -1, 0x03, 0x5842, 0x0446 },\n  { 0x18, 0x18, -1, 0x03, 0x5842, 0x0846 },\n};\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/state.c",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"state.h\"\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"huffman.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#ifdef BROTLI_REPORTING\n/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */\nvoid BrotliDecoderOnStart(const BrotliDecoderState* s);\nvoid BrotliDecoderOnFinish(const BrotliDecoderState* s);\n#define BROTLI_DECODER_ON_START(s) BrotliDecoderOnStart(s);\n#define BROTLI_DECODER_ON_FINISH(s) BrotliDecoderOnFinish(s);\n#else\n#if !defined(BROTLI_DECODER_ON_START)\n#define BROTLI_DECODER_ON_START(s) (void)(s);\n#endif\n#if !defined(BROTLI_DECODER_ON_FINISH)\n#define BROTLI_DECODER_ON_FINISH(s) (void)(s);\n#endif\n#endif\n\nBROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  BROTLI_DECODER_ON_START(s);\n  if (!alloc_func) {\n    s->alloc_func = BrotliDefaultAllocFunc;\n    s->free_func = BrotliDefaultFreeFunc;\n    s->memory_manager_opaque = 0;\n  } else {\n    s->alloc_func = alloc_func;\n    s->free_func = free_func;\n    s->memory_manager_opaque = opaque;\n  }\n\n  s->error_code = 0; /* BROTLI_DECODER_NO_ERROR */\n\n  BrotliInitBitReader(&s->br);\n  s->state = BROTLI_STATE_UNINITED;\n  s->large_window = 0;\n  s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n  s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;\n  s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;\n  s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;\n\n  s->buffer_length = 0;\n  s->loop_counter = 0;\n  s->pos = 0;\n  s->rb_roundtrips = 0;\n  s->partial_pos_out = 0;\n  s->used_input = 0;\n\n  s->block_type_trees = NULL;\n  s->block_len_trees = NULL;\n  s->ringbuffer = NULL;\n  s->ringbuffer_size = 0;\n  s->new_ringbuffer_size = 0;\n  s->ringbuffer_mask = 0;\n\n  s->context_map = NULL;\n  s->context_modes = NULL;\n  s->dist_context_map = NULL;\n  s->context_map_slice = NULL;\n  s->dist_context_map_slice = NULL;\n\n  s->literal_hgroup.codes = NULL;\n  s->literal_hgroup.htrees = NULL;\n  s->insert_copy_hgroup.codes = NULL;\n  s->insert_copy_hgroup.htrees = NULL;\n  s->distance_hgroup.codes = NULL;\n  s->distance_hgroup.htrees = NULL;\n\n  s->is_last_metablock = 0;\n  s->is_uncompressed = 0;\n  s->is_metadata = 0;\n  s->should_wrap_ringbuffer = 0;\n  s->canny_ringbuffer_allocation = 1;\n\n  s->window_bits = 0;\n  s->max_distance = 0;\n  s->dist_rb[0] = 16;\n  s->dist_rb[1] = 15;\n  s->dist_rb[2] = 11;\n  s->dist_rb[3] = 4;\n  s->dist_rb_idx = 0;\n  s->block_type_trees = NULL;\n  s->block_len_trees = NULL;\n\n  s->mtf_upper_bound = 63;\n\n  s->compound_dictionary = NULL;\n  s->dictionary =\n      BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque);\n  if (!s->dictionary) return BROTLI_FALSE;\n\n  s->metadata_start_func = NULL;\n  s->metadata_chunk_func = NULL;\n  s->metadata_callback_opaque = 0;\n\n  return BROTLI_TRUE;\n}\n\nvoid BrotliDecoderStateMetablockBegin(BrotliDecoderState* s) {\n  s->meta_block_remaining_len = 0;\n  s->block_length[0] = BROTLI_BLOCK_SIZE_CAP;\n  s->block_length[1] = BROTLI_BLOCK_SIZE_CAP;\n  s->block_length[2] = BROTLI_BLOCK_SIZE_CAP;\n  s->num_block_types[0] = 1;\n  s->num_block_types[1] = 1;\n  s->num_block_types[2] = 1;\n  s->block_type_rb[0] = 1;\n  s->block_type_rb[1] = 0;\n  s->block_type_rb[2] = 1;\n  s->block_type_rb[3] = 0;\n  s->block_type_rb[4] = 1;\n  s->block_type_rb[5] = 0;\n  s->context_map = NULL;\n  s->context_modes = NULL;\n  s->dist_context_map = NULL;\n  s->context_map_slice = NULL;\n  s->literal_htree = NULL;\n  s->dist_context_map_slice = NULL;\n  s->dist_htree_index = 0;\n  s->context_lookup = NULL;\n  s->literal_hgroup.codes = NULL;\n  s->literal_hgroup.htrees = NULL;\n  s->insert_copy_hgroup.codes = NULL;\n  s->insert_copy_hgroup.htrees = NULL;\n  s->distance_hgroup.codes = NULL;\n  s->distance_hgroup.htrees = NULL;\n}\n\nvoid BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState* s) {\n  BROTLI_DECODER_FREE(s, s->context_modes);\n  BROTLI_DECODER_FREE(s, s->context_map);\n  BROTLI_DECODER_FREE(s, s->dist_context_map);\n  BROTLI_DECODER_FREE(s, s->literal_hgroup.htrees);\n  BROTLI_DECODER_FREE(s, s->insert_copy_hgroup.htrees);\n  BROTLI_DECODER_FREE(s, s->distance_hgroup.htrees);\n}\n\nvoid BrotliDecoderStateCleanup(BrotliDecoderState* s) {\n  BrotliDecoderStateCleanupAfterMetablock(s);\n\n  BROTLI_DECODER_ON_FINISH(s);\n\n  BROTLI_DECODER_FREE(s, s->compound_dictionary);\n  BrotliSharedDictionaryDestroyInstance(s->dictionary);\n  s->dictionary = NULL;\n  BROTLI_DECODER_FREE(s, s->ringbuffer);\n  BROTLI_DECODER_FREE(s, s->block_type_trees);\n}\n\nBROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,\n    HuffmanTreeGroup* group, brotli_reg_t alphabet_size_max,\n    brotli_reg_t alphabet_size_limit, brotli_reg_t ntrees) {\n  /* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)\n     This number is discovered \"unlimited\" \"enough\" calculator; it is actually\n     a wee bigger than required in several cases (especially for alphabets with\n     less than 16 symbols). */\n  const size_t max_table_size = alphabet_size_limit + 376;\n  const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;\n  const size_t htree_size = sizeof(HuffmanCode*) * ntrees;\n  /* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */\n  HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s,\n      code_size + htree_size);\n  group->alphabet_size_max = (uint16_t)alphabet_size_max;\n  group->alphabet_size_limit = (uint16_t)alphabet_size_limit;\n  group->num_htrees = (uint16_t)ntrees;\n  group->htrees = p;\n  group->codes = p ? (HuffmanCode*)(&p[ntrees]) : NULL;\n  return !!p;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/state.h",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Brotli state for partial streaming decoding. */\n\n#ifndef BROTLI_DEC_STATE_H_\n#define BROTLI_DEC_STATE_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include <brotli/shared_dictionary.h>\n#include <brotli/decode.h>\n#include \"bit_reader.h\"\n#include \"huffman.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Graphviz diagram that describes state transitions:\n\ndigraph States {\n  graph [compound=true]\n  concentrate=true\n  node [shape=\"box\"]\n\n  UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE}\n  subgraph cluster_metablock_workflow {\n    style=\"rounded\"\n    label=< <B>METABLOCK CYCLE</B> >\n    METABLOCK_BEGIN -> METABLOCK_HEADER\n    METABLOCK_HEADER:sw -> METADATA\n    METABLOCK_HEADER:s -> UNCOMPRESSED\n    METABLOCK_HEADER:se -> METABLOCK_DONE:ne\n    METADATA:s -> METABLOCK_DONE:w\n    UNCOMPRESSED:s -> METABLOCK_DONE:n\n    METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint=\"false\"]\n  }\n  INITIALIZE -> METABLOCK_BEGIN\n  METABLOCK_DONE -> DONE\n\n  subgraph cluster_compressed_metablock {\n    style=\"rounded\"\n    label=< <B>COMPRESSED METABLOCK</B> >\n\n    subgraph cluster_command {\n      style=\"rounded\"\n      label=< <B>HOT LOOP</B> >\n\n      _METABLOCK_DONE_PORT_ [shape=point style=invis]\n\n      {\n        // Set different shape for nodes returning from \"compressed metablock\".\n        node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS;\n        CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1;\n      }\n\n      CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY\n\n      // IO (\"write\") nodes are not in the hot loop!\n      CMD_INNER_WRITE [style=dashed]\n      CMD_INNER -> CMD_INNER_WRITE\n      CMD_POST_WRITE_1 [style=dashed]\n      CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1\n      CMD_POST_WRITE_2 [style=dashed]\n      CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2\n\n      CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint=\"false\"]\n      CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS}\n          [constraint=\"false\"]\n      CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint=\"false\"]\n      CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint=\"false\"]\n      CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint=\"false\"]\n      CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint=\"false\"]\n      {rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS;\n          CMD_POST_WRAP_COPY}\n      {rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2}\n\n      {CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} ->\n          _METABLOCK_DONE_PORT_ [style=invis]\n      {CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_\n          [constraint=\"false\" style=invis]\n    }\n\n    BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n\n    HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3\n    HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1\n    CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP\n    TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e\n    BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n\n\n    HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint=\"false\"]\n    {rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3}\n    {rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2;\n        TREE_GROUP}\n  }\n  METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n\n\n  _METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se\n      [constraint=\"false\" ltail=cluster_command]\n\n  UNINITED [shape=Mdiamond];\n  DONE [shape=Msquare];\n}\n\n\n */\n\ntypedef enum {\n  BROTLI_STATE_UNINITED,\n  BROTLI_STATE_LARGE_WINDOW_BITS,\n  BROTLI_STATE_INITIALIZE,\n  BROTLI_STATE_METABLOCK_BEGIN,\n  BROTLI_STATE_METABLOCK_HEADER,\n  BROTLI_STATE_METABLOCK_HEADER_2,\n  BROTLI_STATE_CONTEXT_MODES,\n  BROTLI_STATE_COMMAND_BEGIN,\n  BROTLI_STATE_COMMAND_INNER,\n  BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,\n  BROTLI_STATE_COMMAND_POST_WRAP_COPY,\n  BROTLI_STATE_UNCOMPRESSED,\n  BROTLI_STATE_METADATA,\n  BROTLI_STATE_COMMAND_INNER_WRITE,\n  BROTLI_STATE_METABLOCK_DONE,\n  BROTLI_STATE_COMMAND_POST_WRITE_1,\n  BROTLI_STATE_COMMAND_POST_WRITE_2,\n  BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER,\n  BROTLI_STATE_HUFFMAN_CODE_0,\n  BROTLI_STATE_HUFFMAN_CODE_1,\n  BROTLI_STATE_HUFFMAN_CODE_2,\n  BROTLI_STATE_HUFFMAN_CODE_3,\n  BROTLI_STATE_CONTEXT_MAP_1,\n  BROTLI_STATE_CONTEXT_MAP_2,\n  BROTLI_STATE_TREE_GROUP,\n  BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY,\n  BROTLI_STATE_DONE\n} BrotliRunningState;\n\ntypedef enum {\n  BROTLI_STATE_METABLOCK_HEADER_NONE,\n  BROTLI_STATE_METABLOCK_HEADER_EMPTY,\n  BROTLI_STATE_METABLOCK_HEADER_NIBBLES,\n  BROTLI_STATE_METABLOCK_HEADER_SIZE,\n  BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED,\n  BROTLI_STATE_METABLOCK_HEADER_RESERVED,\n  BROTLI_STATE_METABLOCK_HEADER_BYTES,\n  BROTLI_STATE_METABLOCK_HEADER_METADATA\n} BrotliRunningMetablockHeaderState;\n\ntypedef enum {\n  BROTLI_STATE_UNCOMPRESSED_NONE,\n  BROTLI_STATE_UNCOMPRESSED_WRITE\n} BrotliRunningUncompressedState;\n\ntypedef enum {\n  BROTLI_STATE_TREE_GROUP_NONE,\n  BROTLI_STATE_TREE_GROUP_LOOP\n} BrotliRunningTreeGroupState;\n\ntypedef enum {\n  BROTLI_STATE_CONTEXT_MAP_NONE,\n  BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,\n  BROTLI_STATE_CONTEXT_MAP_HUFFMAN,\n  BROTLI_STATE_CONTEXT_MAP_DECODE,\n  BROTLI_STATE_CONTEXT_MAP_TRANSFORM\n} BrotliRunningContextMapState;\n\ntypedef enum {\n  BROTLI_STATE_HUFFMAN_NONE,\n  BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,\n  BROTLI_STATE_HUFFMAN_SIMPLE_READ,\n  BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,\n  BROTLI_STATE_HUFFMAN_COMPLEX,\n  BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS\n} BrotliRunningHuffmanState;\n\ntypedef enum {\n  BROTLI_STATE_DECODE_UINT8_NONE,\n  BROTLI_STATE_DECODE_UINT8_SHORT,\n  BROTLI_STATE_DECODE_UINT8_LONG\n} BrotliRunningDecodeUint8State;\n\ntypedef enum {\n  BROTLI_STATE_READ_BLOCK_LENGTH_NONE,\n  BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX\n} BrotliRunningReadBlockLengthState;\n\n/* BrotliDecoderState addon, used for Compound Dictionary functionality. */\ntypedef struct BrotliDecoderCompoundDictionary {\n  int num_chunks;\n  int total_size;\n  int br_index;\n  int br_offset;\n  int br_length;\n  int br_copied;\n  const uint8_t* chunks[16];\n  int chunk_offsets[16];\n  int block_bits;\n  uint8_t block_map[256];\n} BrotliDecoderCompoundDictionary;\n\ntypedef struct BrotliMetablockHeaderArena {\n  BrotliRunningTreeGroupState substate_tree_group;\n  BrotliRunningContextMapState substate_context_map;\n  BrotliRunningHuffmanState substate_huffman;\n\n  brotli_reg_t sub_loop_counter;\n\n  brotli_reg_t repeat_code_len;\n  brotli_reg_t prev_code_len;\n\n  /* For ReadHuffmanCode. */\n  brotli_reg_t symbol;\n  brotli_reg_t repeat;\n  brotli_reg_t space;\n\n  /* Huffman table for \"histograms\". */\n  HuffmanCode table[32];\n  /* List of heads of symbol chains. */\n  uint16_t* symbol_lists;\n  /* Storage from symbol_lists. */\n  uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +\n                               BROTLI_NUM_COMMAND_SYMBOLS];\n  /* Tails of symbol chains. */\n  int next_symbol[32];\n  uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];\n  /* Population counts for the code lengths. */\n  uint16_t code_length_histo[16];\n  /* TODO(eustas): +2 bytes padding */\n\n  /* For HuffmanTreeGroupDecode. */\n  int htree_index;\n  HuffmanCode* next;\n\n  /* For DecodeContextMap. */\n  brotli_reg_t context_index;\n  brotli_reg_t max_run_length_prefix;\n  brotli_reg_t code;\n  HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];\n} BrotliMetablockHeaderArena;\n\ntypedef struct BrotliMetablockBodyArena {\n  uint8_t dist_extra_bits[544];\n  brotli_reg_t dist_offset[544];\n} BrotliMetablockBodyArena;\n\nstruct BrotliDecoderStateStruct {\n  BrotliRunningState state;\n\n  /* This counter is reused for several disjoint loops. */\n  int loop_counter;\n\n  BrotliBitReader br;\n\n  brotli_alloc_func alloc_func;\n  brotli_free_func free_func;\n  void* memory_manager_opaque;\n\n  /* Temporary storage for remaining input. Brotli stream format is designed in\n     a way, that 64 bits are enough to make progress in decoding. */\n  union {\n    uint64_t u64;\n    uint8_t u8[8];\n  } buffer;\n  brotli_reg_t buffer_length;\n\n  int pos;\n  int max_backward_distance;\n  int max_distance;\n  int ringbuffer_size;\n  int ringbuffer_mask;\n  int dist_rb_idx;\n  int dist_rb[4];\n  int error_code;\n  int meta_block_remaining_len;\n\n  uint8_t* ringbuffer;\n  uint8_t* ringbuffer_end;\n  HuffmanCode* htree_command;\n  const uint8_t* context_lookup;\n  uint8_t* context_map_slice;\n  uint8_t* dist_context_map_slice;\n\n  /* This ring buffer holds a few past copy distances that will be used by\n     some special distance codes. */\n  HuffmanTreeGroup literal_hgroup;\n  HuffmanTreeGroup insert_copy_hgroup;\n  HuffmanTreeGroup distance_hgroup;\n  HuffmanCode* block_type_trees;\n  HuffmanCode* block_len_trees;\n  /* This is true if the literal context map histogram type always matches the\n     block type. It is then not needed to keep the context (faster decoding). */\n  int trivial_literal_context;\n  /* Distance context is actual after command is decoded and before distance is\n     computed. After distance computation it is used as a temporary variable. */\n  int distance_context;\n  brotli_reg_t block_length[3];\n  brotli_reg_t block_length_index;\n  brotli_reg_t num_block_types[3];\n  brotli_reg_t block_type_rb[6];\n  brotli_reg_t distance_postfix_bits;\n  brotli_reg_t num_direct_distance_codes;\n  brotli_reg_t num_dist_htrees;\n  uint8_t* dist_context_map;\n  HuffmanCode* literal_htree;\n\n  /* For partial write operations. */\n  size_t rb_roundtrips;  /* how many times we went around the ring-buffer */\n  size_t partial_pos_out;  /* how much output to the user in total */\n\n  /* For InverseMoveToFrontTransform. */\n  brotli_reg_t mtf_upper_bound;\n  uint32_t mtf[64 + 1];\n\n  int copy_length;\n  int distance_code;\n\n  uint8_t dist_htree_index;\n  /* TODO(eustas): +3 bytes padding */\n\n  /* Less used attributes are at the end of this struct. */\n\n  brotli_decoder_metadata_start_func metadata_start_func;\n  brotli_decoder_metadata_chunk_func metadata_chunk_func;\n  void* metadata_callback_opaque;\n\n  /* For reporting. */\n  uint64_t used_input;  /* how many bytes of input are consumed */\n\n  /* States inside function calls. */\n  BrotliRunningMetablockHeaderState substate_metablock_header;\n  BrotliRunningUncompressedState substate_uncompressed;\n  BrotliRunningDecodeUint8State substate_decode_uint8;\n  BrotliRunningReadBlockLengthState substate_read_block_length;\n\n  int new_ringbuffer_size;\n  /* TODO(eustas): +4 bytes padding */\n\n  unsigned int is_last_metablock : 1;\n  unsigned int is_uncompressed : 1;\n  unsigned int is_metadata : 1;\n  unsigned int should_wrap_ringbuffer : 1;\n  unsigned int canny_ringbuffer_allocation : 1;\n  unsigned int large_window : 1;\n  unsigned int window_bits : 6;\n  unsigned int size_nibbles : 8;\n  /* TODO(eustas): +12 bits padding */\n\n  brotli_reg_t num_literal_htrees;\n  uint8_t* context_map;\n  uint8_t* context_modes;\n\n  BrotliSharedDictionary* dictionary;\n  BrotliDecoderCompoundDictionary* compound_dictionary;\n\n  uint32_t trivial_literal_contexts[8];  /* 256 bits */\n\n  union {\n    BrotliMetablockHeaderArena header;\n    BrotliMetablockBodyArena body;\n  } arena;\n};\n\ntypedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal;\n#define BrotliDecoderState BrotliDecoderStateInternal\n\nBROTLI_INTERNAL BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\nBROTLI_INTERNAL void BrotliDecoderStateCleanup(BrotliDecoderState* s);\nBROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);\nBROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(\n    BrotliDecoderState* s);\nBROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(\n    BrotliDecoderState* s, HuffmanTreeGroup* group,\n    brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit,\n    brotli_reg_t ntrees);\n\n#define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)\n\n#define BROTLI_DECODER_FREE(S, X) {          \\\n  S->free_func(S->memory_manager_opaque, X); \\\n  X = NULL;                                  \\\n}\n\n/* Literal/Command/Distance block size maximum; same as maximum metablock size;\n   used as block size when there is no block switching. */\n#define BROTLI_BLOCK_SIZE_CAP (1U << 24)\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_STATE_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/dec/static_init.h",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Central point for static initialization. */\n\n#ifndef THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_\n#define THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_\n\n#include \"../common/platform.h\"\n#include \"../common/static_init.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)\nBROTLI_INTERNAL void BrotliDecoderLazyStaticInitInner(void);\nBROTLI_INTERNAL void BrotliDecoderLazyStaticInit(void);\n#endif  /* BROTLI_STATIC_INIT */\n\nBROTLI_INTERNAL BROTLI_BOOL BrotliDecoderEnsureStaticInit(void);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  // THIRD_PARTY_BROTLI_DEC_STATIC_INIT_H_\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/backward_references.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#include \"backward_references.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"compound_dictionary.h\"\n#include \"encoder_dict.h\"\n#include \"hash.h\"\n#include \"params.h\"\n#include \"quality.h\"  /* IWYU pragma: keep for inc */\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE size_t ComputeDistanceCode(size_t distance,\n                                                size_t max_distance,\n                                                const int* dist_cache) {\n  if (distance <= max_distance) {\n    size_t distance_plus_3 = distance + 3;\n    size_t offset0 = distance_plus_3 - (size_t)dist_cache[0];\n    size_t offset1 = distance_plus_3 - (size_t)dist_cache[1];\n    if (distance == (size_t)dist_cache[0]) {\n      return 0;\n    } else if (distance == (size_t)dist_cache[1]) {\n      return 1;\n    } else if (offset0 < 7) {\n      return (0x9750468 >> (4 * offset0)) & 0xF;\n    } else if (offset1 < 7) {\n      return (0xFDB1ACE >> (4 * offset1)) & 0xF;\n    } else if (distance == (size_t)dist_cache[2]) {\n      return 2;\n    } else if (distance == (size_t)dist_cache[3]) {\n      return 3;\n    }\n  }\n  return distance + BROTLI_NUM_DISTANCE_SHORT_CODES - 1;\n}\n\n#define EXPAND_CAT(a, b) CAT(a, b)\n#define CAT(a, b) a ## b\n#define FN(X) EXPAND_CAT(X, HASHER())\n#define EXPORT_FN(X) EXPAND_CAT(X, EXPAND_CAT(PREFIX(), HASHER()))\n\n#define PREFIX() N\n#define ENABLE_COMPOUND_DICTIONARY 0\n\n#define HASHER() H2\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H3\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H4\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H5\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H6\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H40\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H41\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H42\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H54\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H35\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H55\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H65\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#if defined(BROTLI_MAX_SIMD_QUALITY)\n#define HASHER() H58\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H68\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#endif\n\n#undef ENABLE_COMPOUND_DICTIONARY\n#undef PREFIX\n#define PREFIX() D\n#define ENABLE_COMPOUND_DICTIONARY 1\n\n#define HASHER() H5\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H6\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H40\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H41\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H42\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H55\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H65\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#if defined(BROTLI_MAX_SIMD_QUALITY)\n#define HASHER() H58\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H68\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#endif\n\n#undef ENABLE_COMPOUND_DICTIONARY\n#undef PREFIX\n\n#undef EXPORT_FN\n#undef FN\n#undef CAT\n#undef EXPAND_CAT\n\nvoid BrotliCreateBackwardReferences(size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  if (params->dictionary.compound.num_chunks != 0) {\n    switch (params->hasher.type) {\n#define CASE_(N)                                                    \\\n      case N:                                                       \\\n        CreateBackwardReferencesDH ## N(num_bytes,                  \\\n            position, ringbuffer, ringbuffer_mask,                  \\\n            literal_context_lut, params, hasher, dist_cache,        \\\n            last_insert_len, commands, num_commands, num_literals); \\\n        return;\n      CASE_(5)\n      CASE_(6)\n#if defined(BROTLI_MAX_SIMD_QUALITY)\n      CASE_(58)\n      CASE_(68)\n#endif\n      CASE_(40)\n      CASE_(41)\n      CASE_(42)\n      CASE_(55)\n      CASE_(65)\n#undef CASE_\n      default:\n        BROTLI_DCHECK(BROTLI_FALSE);\n        break;\n    }\n  }\n\n  switch (params->hasher.type) {\n#define CASE_(N)                                                  \\\n    case N:                                                       \\\n      CreateBackwardReferencesNH ## N(num_bytes,                  \\\n          position, ringbuffer, ringbuffer_mask,                  \\\n          literal_context_lut, params, hasher, dist_cache,        \\\n          last_insert_len, commands, num_commands, num_literals); \\\n      return;\n    FOR_GENERIC_HASHERS(CASE_)\n#undef CASE_\n    default:\n      BROTLI_DCHECK(BROTLI_FALSE);\n      break;\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/backward_references.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#ifndef BROTLI_ENC_BACKWARD_REFERENCES_H_\n#define BROTLI_ENC_BACKWARD_REFERENCES_H_\n\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"hash.h\"\n#include \"params.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* \"commands\" points to the next output command to write to, \"*num_commands\" is\n   initially the total amount of commands output by previous\n   CreateBackwardReferences calls, and must be incremented by the amount written\n   by this call. */\nBROTLI_INTERNAL void BrotliCreateBackwardReferences(size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BACKWARD_REFERENCES_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/backward_references_hq.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#include \"backward_references_hq.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"compound_dictionary.h\"\n#include \"encoder_dict.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"hash.h\"\n#include \"literal_cost.h\"\n#include \"memory.h\"\n#include \"params.h\"\n#include \"prefix.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* BrotliCalculateDistanceCodeLimit(BROTLI_MAX_ALLOWED_DISTANCE, 3, 120). */\n#define BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE 544\n\nstatic const float kInfinity = 1.7e38f;  /* ~= 2 ^ 127 */\n\nstatic const BROTLI_MODEL(\"small\") uint32_t kDistanceCacheIndex[] = {\n  0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,\n};\nstatic const BROTLI_MODEL(\"small\") int kDistanceCacheOffset[] = {\n  0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3\n};\n\nvoid BrotliInitZopfliNodes(ZopfliNode* array, size_t length) {\n  ZopfliNode stub;\n  size_t i;\n  stub.length = 1;\n  stub.distance = 0;\n  stub.dcode_insert_length = 0;\n  stub.u.cost = kInfinity;\n  for (i = 0; i < length; ++i) array[i] = stub;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeCopyLength(const ZopfliNode* self) {\n  return self->length & 0x1FFFFFF;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeLengthCode(const ZopfliNode* self) {\n  const uint32_t modifier = self->length >> 25;\n  return ZopfliNodeCopyLength(self) + 9u - modifier;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeCopyDistance(const ZopfliNode* self) {\n  return self->distance;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeDistanceCode(const ZopfliNode* self) {\n  const uint32_t short_code = self->dcode_insert_length >> 27;\n  return short_code == 0 ?\n      ZopfliNodeCopyDistance(self) + BROTLI_NUM_DISTANCE_SHORT_CODES - 1 :\n      short_code - 1;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeCommandLength(const ZopfliNode* self) {\n  return ZopfliNodeCopyLength(self) + (self->dcode_insert_length & 0x7FFFFFF);\n}\n\n/* Temporary data for ZopfliCostModelSetFromCommands. */\ntypedef struct ZopfliCostModelArena {\n  uint32_t histogram_literal[BROTLI_NUM_LITERAL_SYMBOLS];\n  uint32_t histogram_cmd[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint32_t histogram_dist[BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE];\n  float cost_literal[BROTLI_NUM_LITERAL_SYMBOLS];\n} ZopfliCostModelArena;\n\n/* Histogram based cost model for zopflification. */\ntypedef struct ZopfliCostModel {\n  /* The insert and copy length symbols. */\n  float cost_cmd_[BROTLI_NUM_COMMAND_SYMBOLS];\n  float* cost_dist_;\n  uint32_t distance_histogram_size;\n  /* Cumulative costs of literals per position in the stream. */\n  float* literal_costs_;\n  float min_cost_cmd_;\n  size_t num_bytes_;\n\n  /* Temporary data. */\n  union {\n    size_t literal_histograms[3 * 256];\n    ZopfliCostModelArena arena;\n  };\n} ZopfliCostModel;\n\nstatic void InitZopfliCostModel(\n    MemoryManager* m, ZopfliCostModel* self, const BrotliDistanceParams* dist,\n    size_t num_bytes) {\n  self->num_bytes_ = num_bytes;\n  self->literal_costs_ = BROTLI_ALLOC(m, float, num_bytes + 2);\n  self->cost_dist_ = BROTLI_ALLOC(m, float, dist->alphabet_size_limit);\n  self->distance_histogram_size = dist->alphabet_size_limit;\n  if (BROTLI_IS_OOM(m)) return;\n}\n\nstatic void CleanupZopfliCostModel(MemoryManager* m, ZopfliCostModel* self) {\n  BROTLI_FREE(m, self->literal_costs_);\n  BROTLI_FREE(m, self->cost_dist_);\n}\n\nstatic void SetCost(const uint32_t* histogram, size_t histogram_size,\n                    BROTLI_BOOL literal_histogram, float* cost) {\n  size_t sum = 0;\n  size_t missing_symbol_sum;\n  float log2sum;\n  float missing_symbol_cost;\n  size_t i;\n  for (i = 0; i < histogram_size; i++) {\n    sum += histogram[i];\n  }\n  log2sum = (float)FastLog2(sum);\n  missing_symbol_sum = sum;\n  if (!literal_histogram) {\n    for (i = 0; i < histogram_size; i++) {\n      if (histogram[i] == 0) missing_symbol_sum++;\n    }\n  }\n  missing_symbol_cost = (float)FastLog2(missing_symbol_sum) + 2;\n  for (i = 0; i < histogram_size; i++) {\n    if (histogram[i] == 0) {\n      cost[i] = missing_symbol_cost;\n      continue;\n    }\n\n    /* Shannon bits for this symbol. */\n    cost[i] = log2sum - (float)FastLog2(histogram[i]);\n\n    /* Cannot be coded with less than 1 bit */\n    if (cost[i] < 1) cost[i] = 1;\n  }\n}\n\nstatic void ZopfliCostModelSetFromCommands(ZopfliCostModel* self,\n                                           size_t position,\n                                           const uint8_t* ringbuffer,\n                                           size_t ringbuffer_mask,\n                                           const Command* commands,\n                                           size_t num_commands,\n                                           size_t last_insert_len) {\n  ZopfliCostModelArena* arena = &self->arena;\n  size_t pos = position - last_insert_len;\n  float min_cost_cmd = kInfinity;\n  size_t i;\n  float* cost_cmd = self->cost_cmd_;\n\n  memset(arena->histogram_literal, 0, sizeof(arena->histogram_literal));\n  memset(arena->histogram_cmd, 0, sizeof(arena->histogram_cmd));\n  memset(arena->histogram_dist, 0, sizeof(arena->histogram_dist));\n\n  for (i = 0; i < num_commands; i++) {\n    size_t inslength = commands[i].insert_len_;\n    size_t copylength = CommandCopyLen(&commands[i]);\n    size_t distcode = commands[i].dist_prefix_ & 0x3FF;\n    size_t cmdcode = commands[i].cmd_prefix_;\n    size_t j;\n\n    arena->histogram_cmd[cmdcode]++;\n    if (cmdcode >= 128) arena->histogram_dist[distcode]++;\n\n    for (j = 0; j < inslength; j++) {\n      arena->histogram_literal[ringbuffer[(pos + j) & ringbuffer_mask]]++;\n    }\n\n    pos += inslength + copylength;\n  }\n\n  SetCost(arena->histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, BROTLI_TRUE,\n          arena->cost_literal);\n  SetCost(arena->histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, BROTLI_FALSE,\n          cost_cmd);\n  SetCost(arena->histogram_dist, self->distance_histogram_size, BROTLI_FALSE,\n          self->cost_dist_);\n\n  for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) {\n    min_cost_cmd = BROTLI_MIN(float, min_cost_cmd, cost_cmd[i]);\n  }\n  self->min_cost_cmd_ = min_cost_cmd;\n\n  {\n    float* literal_costs = self->literal_costs_;\n    float literal_carry = 0.0;\n    size_t num_bytes = self->num_bytes_;\n    literal_costs[0] = 0.0;\n    for (i = 0; i < num_bytes; ++i) {\n      literal_carry +=\n          arena->cost_literal[ringbuffer[(position + i) & ringbuffer_mask]];\n      literal_costs[i + 1] = literal_costs[i] + literal_carry;\n      literal_carry -= literal_costs[i + 1] - literal_costs[i];\n    }\n  }\n}\n\nstatic void ZopfliCostModelSetFromLiteralCosts(ZopfliCostModel* self,\n                                               size_t position,\n                                               const uint8_t* ringbuffer,\n                                               size_t ringbuffer_mask) {\n  float* literal_costs = self->literal_costs_;\n  float literal_carry = 0.0;\n  float* cost_dist = self->cost_dist_;\n  float* cost_cmd = self->cost_cmd_;\n  size_t num_bytes = self->num_bytes_;\n  size_t i;\n  BrotliEstimateBitCostsForLiterals(position, num_bytes, ringbuffer_mask,\n                                    ringbuffer, self->literal_histograms,\n                                    &literal_costs[1]);\n  literal_costs[0] = 0.0;\n  for (i = 0; i < num_bytes; ++i) {\n    literal_carry += literal_costs[i + 1];\n    literal_costs[i + 1] = literal_costs[i] + literal_carry;\n    literal_carry -= literal_costs[i + 1] - literal_costs[i];\n  }\n  for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) {\n    cost_cmd[i] = (float)FastLog2(11 + (uint32_t)i);\n  }\n  for (i = 0; i < self->distance_histogram_size; ++i) {\n    cost_dist[i] = (float)FastLog2(20 + (uint32_t)i);\n  }\n  self->min_cost_cmd_ = (float)FastLog2(11);\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetCommandCost(\n    const ZopfliCostModel* self, uint16_t cmdcode) {\n  return self->cost_cmd_[cmdcode];\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetDistanceCost(\n    const ZopfliCostModel* self, size_t distcode) {\n  return self->cost_dist_[distcode];\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetLiteralCosts(\n    const ZopfliCostModel* self, size_t from, size_t to) {\n  return self->literal_costs_[to] - self->literal_costs_[from];\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetMinCostCmd(\n    const ZopfliCostModel* self) {\n  return self->min_cost_cmd_;\n}\n\n/* REQUIRES: len >= 2, start_pos <= pos */\n/* REQUIRES: cost < kInfinity, nodes[start_pos].cost < kInfinity */\n/* Maintains the \"ZopfliNode array invariant\". */\nstatic BROTLI_INLINE void UpdateZopfliNode(ZopfliNode* nodes, size_t pos,\n    size_t start_pos, size_t len, size_t len_code, size_t dist,\n    size_t short_code, float cost) {\n  ZopfliNode* next = &nodes[pos + len];\n  next->length = (uint32_t)(len | ((len + 9u - len_code) << 25));\n  next->distance = (uint32_t)dist;\n  next->dcode_insert_length = (uint32_t)(\n      (short_code << 27) | (pos - start_pos));\n  next->u.cost = cost;\n}\n\ntypedef struct PosData {\n  size_t pos;\n  int distance_cache[4];\n  float costdiff;\n  float cost;\n} PosData;\n\n/* Maintains the smallest 8 cost difference together with their positions */\ntypedef struct StartPosQueue {\n  PosData q_[8];\n  size_t idx_;\n} StartPosQueue;\n\nstatic BROTLI_INLINE void InitStartPosQueue(StartPosQueue* self) {\n  self->idx_ = 0;\n}\n\nstatic size_t StartPosQueueSize(const StartPosQueue* self) {\n  return BROTLI_MIN(size_t, self->idx_, 8);\n}\n\nstatic void StartPosQueuePush(StartPosQueue* self, const PosData* posdata) {\n  size_t offset = ~(self->idx_++) & 7;\n  size_t len = StartPosQueueSize(self);\n  size_t i;\n  PosData* q = self->q_;\n  q[offset] = *posdata;\n  /* Restore the sorted order. In the list of |len| items at most |len - 1|\n     adjacent element comparisons / swaps are required. */\n  for (i = 1; i < len; ++i) {\n    if (q[offset & 7].costdiff > q[(offset + 1) & 7].costdiff) {\n      BROTLI_SWAP(PosData, q, offset & 7, (offset + 1) & 7);\n    }\n    ++offset;\n  }\n}\n\nstatic const PosData* StartPosQueueAt(const StartPosQueue* self, size_t k) {\n  return &self->q_[(k - self->idx_) & 7];\n}\n\n/* Returns the minimum possible copy length that can improve the cost of any */\n/* future position. */\nstatic size_t ComputeMinimumCopyLength(const float start_cost,\n                                       const ZopfliNode* nodes,\n                                       const size_t num_bytes,\n                                       const size_t pos) {\n  /* Compute the minimum possible cost of reaching any future position. */\n  float min_cost = start_cost;\n  size_t len = 2;\n  size_t next_len_bucket = 4;\n  size_t next_len_offset = 10;\n  while (pos + len <= num_bytes && nodes[pos + len].u.cost <= min_cost) {\n    /* We already reached (pos + len) with no more cost than the minimum\n       possible cost of reaching anything from this pos, so there is no point in\n       looking for lengths <= len. */\n    ++len;\n    if (len == next_len_offset) {\n      /* We reached the next copy length code bucket, so we add one more\n         extra bit to the minimum cost. */\n      min_cost += 1.0f;\n      next_len_offset += next_len_bucket;\n      next_len_bucket *= 2;\n    }\n  }\n  return len;\n}\n\n/* REQUIRES: nodes[pos].cost < kInfinity\n   REQUIRES: nodes[0..pos] satisfies that \"ZopfliNode array invariant\". */\nstatic uint32_t ComputeDistanceShortcut(const size_t block_start,\n                                        const size_t pos,\n                                        const size_t max_backward_limit,\n                                        const size_t gap,\n                                        const ZopfliNode* nodes) {\n  const size_t c_len = ZopfliNodeCopyLength(&nodes[pos]);\n  const size_t i_len = nodes[pos].dcode_insert_length & 0x7FFFFFF;\n  const size_t dist = ZopfliNodeCopyDistance(&nodes[pos]);\n  /* Since |block_start + pos| is the end position of the command, the copy part\n     starts from |block_start + pos - c_len|. Distances that are greater than\n     this or greater than |max_backward_limit| + |gap| are static dictionary\n     references, and do not update the last distances.\n     Also distance code 0 (last distance) does not update the last distances. */\n  if (pos == 0) {\n    return 0;\n  } else if (dist + c_len <= block_start + pos + gap &&\n             dist <= max_backward_limit + gap &&\n             ZopfliNodeDistanceCode(&nodes[pos]) > 0) {\n    return (uint32_t)pos;\n  } else {\n    return nodes[pos - c_len - i_len].u.shortcut;\n  }\n}\n\n/* Fills in dist_cache[0..3] with the last four distances (as defined by\n   Section 4. of the Spec) that would be used at (block_start + pos) if we\n   used the shortest path of commands from block_start, computed from\n   nodes[0..pos]. The last four distances at block_start are in\n   starting_dist_cache[0..3].\n   REQUIRES: nodes[pos].cost < kInfinity\n   REQUIRES: nodes[0..pos] satisfies that \"ZopfliNode array invariant\". */\nstatic void ComputeDistanceCache(const size_t pos,\n                                 const int* starting_dist_cache,\n                                 const ZopfliNode* nodes,\n                                 int* dist_cache) {\n  int idx = 0;\n  size_t p = nodes[pos].u.shortcut;\n  while (idx < 4 && p > 0) {\n    const size_t i_len = nodes[p].dcode_insert_length & 0x7FFFFFF;\n    const size_t c_len = ZopfliNodeCopyLength(&nodes[p]);\n    const size_t dist = ZopfliNodeCopyDistance(&nodes[p]);\n    dist_cache[idx++] = (int)dist;\n    /* Because of prerequisite, p >= c_len + i_len >= 2. */\n    p = nodes[p - c_len - i_len].u.shortcut;\n  }\n  for (; idx < 4; ++idx) {\n    dist_cache[idx] = *starting_dist_cache++;\n  }\n}\n\n/* Maintains \"ZopfliNode array invariant\" and pushes node to the queue, if it\n   is eligible. */\nstatic void EvaluateNode(\n    const size_t block_start, const size_t pos, const size_t max_backward_limit,\n    const size_t gap, const int* starting_dist_cache,\n    const ZopfliCostModel* model, StartPosQueue* queue, ZopfliNode* nodes) {\n  /* Save cost, because ComputeDistanceCache invalidates it. */\n  float node_cost = nodes[pos].u.cost;\n  nodes[pos].u.shortcut = ComputeDistanceShortcut(\n      block_start, pos, max_backward_limit, gap, nodes);\n  if (node_cost <= ZopfliCostModelGetLiteralCosts(model, 0, pos)) {\n    PosData posdata;\n    posdata.pos = pos;\n    posdata.cost = node_cost;\n    posdata.costdiff = node_cost -\n        ZopfliCostModelGetLiteralCosts(model, 0, pos);\n    ComputeDistanceCache(\n        pos, starting_dist_cache, nodes, posdata.distance_cache);\n    StartPosQueuePush(queue, &posdata);\n  }\n}\n\n/* Returns longest copy length. */\nstatic size_t UpdateNodes(\n    const size_t num_bytes, const size_t block_start, const size_t pos,\n    const uint8_t* ringbuffer, const size_t ringbuffer_mask,\n    const BrotliEncoderParams* params, const size_t max_backward_limit,\n    const int* starting_dist_cache, const size_t num_matches,\n    const BackwardMatch* matches, const ZopfliCostModel* model,\n    StartPosQueue* queue, ZopfliNode* nodes) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t cur_ix = block_start + pos;\n  const size_t cur_ix_masked = cur_ix & ringbuffer_mask;\n  const size_t max_distance = BROTLI_MIN(size_t, cur_ix, max_backward_limit);\n  const size_t dictionary_start = BROTLI_MIN(size_t,\n      cur_ix + stream_offset, max_backward_limit);\n  const size_t max_len = num_bytes - pos;\n  const size_t max_zopfli_len = MaxZopfliLen(params);\n  const size_t max_iters = MaxZopfliCandidates(params);\n  size_t min_len;\n  size_t result = 0;\n  size_t k;\n  const CompoundDictionary* addon = &params->dictionary.compound;\n  size_t gap = addon->total_size;\n\n  BROTLI_DCHECK(cur_ix_masked + max_len <= ringbuffer_mask);\n\n  EvaluateNode(block_start + stream_offset, pos, max_backward_limit, gap,\n      starting_dist_cache, model, queue, nodes);\n\n  {\n    const PosData* posdata = StartPosQueueAt(queue, 0);\n    float min_cost = (posdata->cost + ZopfliCostModelGetMinCostCmd(model) +\n        ZopfliCostModelGetLiteralCosts(model, posdata->pos, pos));\n    min_len = ComputeMinimumCopyLength(min_cost, nodes, num_bytes, pos);\n  }\n\n  /* Go over the command starting positions in order of increasing cost\n     difference. */\n  for (k = 0; k < max_iters && k < StartPosQueueSize(queue); ++k) {\n    const PosData* posdata = StartPosQueueAt(queue, k);\n    const size_t start = posdata->pos;\n    const uint16_t inscode = GetInsertLengthCode(pos - start);\n    const float start_costdiff = posdata->costdiff;\n    const float base_cost = start_costdiff + (float)GetInsertExtra(inscode) +\n        ZopfliCostModelGetLiteralCosts(model, 0, pos);\n\n    /* Look for last distance matches using the distance cache from this\n       starting position. */\n    size_t best_len = min_len - 1;\n    size_t j = 0;\n    for (; j < BROTLI_NUM_DISTANCE_SHORT_CODES && best_len < max_len; ++j) {\n      const size_t idx = kDistanceCacheIndex[j];\n      const size_t backward =\n          (size_t)(posdata->distance_cache[idx] + kDistanceCacheOffset[j]);\n      size_t prev_ix = cur_ix - backward;\n      size_t len = 0;\n      uint8_t continuation = ringbuffer[cur_ix_masked + best_len];\n      if (cur_ix_masked + best_len > ringbuffer_mask) {\n        break;\n      }\n      if (BROTLI_PREDICT_FALSE(backward > dictionary_start + gap)) {\n        /* Word dictionary -> ignore. */\n        continue;\n      }\n      if (backward <= max_distance) {\n        /* Regular backward reference. */\n        if (prev_ix >= cur_ix) {\n          continue;\n        }\n\n        prev_ix &= ringbuffer_mask;\n        if (prev_ix + best_len > ringbuffer_mask ||\n            continuation != ringbuffer[prev_ix + best_len]) {\n          continue;\n        }\n        len = FindMatchLengthWithLimit(&ringbuffer[prev_ix],\n                                       &ringbuffer[cur_ix_masked],\n                                       max_len);\n      } else if (backward > dictionary_start) {\n        size_t d = 0;\n        size_t offset;\n        size_t limit;\n        const uint8_t* source;\n        offset = dictionary_start + 1 + addon->total_size - 1;\n        while (offset >= backward + addon->chunk_offsets[d + 1]) d++;\n        source = addon->chunk_source[d];\n        offset = offset - addon->chunk_offsets[d] - backward;\n        limit = addon->chunk_offsets[d + 1] - addon->chunk_offsets[d] - offset;\n        limit = limit > max_len ? max_len : limit;\n        if (best_len >= limit ||\n            continuation != source[offset + best_len]) {\n          continue;\n        }\n        len = FindMatchLengthWithLimit(&source[offset],\n                                       &ringbuffer[cur_ix_masked],\n                                       limit);\n      } else {\n        /* \"Gray\" area. It is addressable by decoder, but this encoder\n           instance does not have that data -> should not touch it. */\n        continue;\n      }\n      {\n        const float dist_cost = base_cost +\n            ZopfliCostModelGetDistanceCost(model, j);\n        size_t l;\n        for (l = best_len + 1; l <= len; ++l) {\n          const uint16_t copycode = GetCopyLengthCode(l);\n          const uint16_t cmdcode =\n              CombineLengthCodes(inscode, copycode, j == 0);\n          const float cost = (cmdcode < 128 ? base_cost : dist_cost) +\n              (float)GetCopyExtra(copycode) +\n              ZopfliCostModelGetCommandCost(model, cmdcode);\n          if (cost < nodes[pos + l].u.cost) {\n            UpdateZopfliNode(nodes, pos, start, l, l, backward, j + 1, cost);\n            result = BROTLI_MAX(size_t, result, l);\n          }\n          best_len = l;\n        }\n      }\n    }\n\n    /* At higher iterations look only for new last distance matches, since\n       looking only for new command start positions with the same distances\n       does not help much. */\n    if (k >= 2) continue;\n\n    {\n      /* Loop through all possible copy lengths at this position. */\n      size_t len = min_len;\n      for (j = 0; j < num_matches; ++j) {\n        BackwardMatch match = matches[j];\n        size_t dist = match.distance;\n        BROTLI_BOOL is_dictionary_match =\n            TO_BROTLI_BOOL(dist > dictionary_start + gap);\n        /* We already tried all possible last distance matches, so we can use\n           normal distance code here. */\n        size_t dist_code = dist + BROTLI_NUM_DISTANCE_SHORT_CODES - 1;\n        uint16_t dist_symbol;\n        uint32_t distextra;\n        uint32_t distnumextra;\n        float dist_cost;\n        size_t max_match_len;\n        PrefixEncodeCopyDistance(\n            dist_code, params->dist.num_direct_distance_codes,\n            params->dist.distance_postfix_bits, &dist_symbol, &distextra);\n        distnumextra = dist_symbol >> 10;\n        dist_cost = base_cost + (float)distnumextra +\n            ZopfliCostModelGetDistanceCost(model, dist_symbol & 0x3FF);\n\n        /* Try all copy lengths up until the maximum copy length corresponding\n           to this distance. If the distance refers to the static dictionary, or\n           the maximum length is long enough, try only one maximum length. */\n        max_match_len = BackwardMatchLength(&match);\n        if (len < max_match_len &&\n            (is_dictionary_match || max_match_len > max_zopfli_len)) {\n          len = max_match_len;\n        }\n        for (; len <= max_match_len; ++len) {\n          const size_t len_code =\n              is_dictionary_match ? BackwardMatchLengthCode(&match) : len;\n          const uint16_t copycode = GetCopyLengthCode(len_code);\n          const uint16_t cmdcode = CombineLengthCodes(inscode, copycode, 0);\n          const float cost = dist_cost + (float)GetCopyExtra(copycode) +\n              ZopfliCostModelGetCommandCost(model, cmdcode);\n          if (cost < nodes[pos + len].u.cost) {\n            UpdateZopfliNode(nodes, pos, start, len, len_code, dist, 0, cost);\n            result = BROTLI_MAX(size_t, result, len);\n          }\n        }\n      }\n    }\n  }\n  return result;\n}\n\nstatic size_t ComputeShortestPathFromNodes(size_t num_bytes,\n    ZopfliNode* nodes) {\n  size_t index = num_bytes;\n  size_t num_commands = 0;\n  while ((nodes[index].dcode_insert_length & 0x7FFFFFF) == 0 &&\n      nodes[index].length == 1) --index;\n  nodes[index].u.next = BROTLI_UINT32_MAX;\n  while (index != 0) {\n    size_t len = ZopfliNodeCommandLength(&nodes[index]);\n    index -= len;\n    nodes[index].u.next = (uint32_t)len;\n    num_commands++;\n  }\n  return num_commands;\n}\n\n/* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */\nvoid BrotliZopfliCreateCommands(const size_t num_bytes,\n    const size_t block_start, const ZopfliNode* nodes, int* dist_cache,\n    size_t* last_insert_len, const BrotliEncoderParams* params,\n    Command* commands, size_t* num_literals) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  size_t pos = 0;\n  uint32_t offset = nodes[0].u.next;\n  size_t i;\n  size_t gap = params->dictionary.compound.total_size;\n  for (i = 0; offset != BROTLI_UINT32_MAX; i++) {\n    const ZopfliNode* next = &nodes[pos + offset];\n    size_t copy_length = ZopfliNodeCopyLength(next);\n    size_t insert_length = next->dcode_insert_length & 0x7FFFFFF;\n    pos += insert_length;\n    offset = next->u.next;\n    if (i == 0) {\n      insert_length += *last_insert_len;\n      *last_insert_len = 0;\n    }\n    {\n      size_t distance = ZopfliNodeCopyDistance(next);\n      size_t len_code = ZopfliNodeLengthCode(next);\n      size_t dictionary_start = BROTLI_MIN(size_t,\n          block_start + pos + stream_offset, max_backward_limit);\n      BROTLI_BOOL is_dictionary =\n          TO_BROTLI_BOOL(distance > dictionary_start + gap);\n      size_t dist_code = ZopfliNodeDistanceCode(next);\n      InitCommand(&commands[i], &params->dist, insert_length,\n          copy_length, (int)len_code - (int)copy_length, dist_code);\n\n      if (!is_dictionary && dist_code > 0) {\n        dist_cache[3] = dist_cache[2];\n        dist_cache[2] = dist_cache[1];\n        dist_cache[1] = dist_cache[0];\n        dist_cache[0] = (int)distance;\n      }\n    }\n\n    *num_literals += insert_length;\n    pos += copy_length;\n  }\n  *last_insert_len += num_bytes - pos;\n}\n\nstatic size_t ZopfliIterate(size_t num_bytes, size_t position,\n    const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    const BrotliEncoderParams* params, const size_t gap, const int* dist_cache,\n    const ZopfliCostModel* model, const uint32_t* num_matches,\n    const BackwardMatch* matches, ZopfliNode* nodes) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  const size_t max_zopfli_len = MaxZopfliLen(params);\n  StartPosQueue queue;\n  size_t cur_match_pos = 0;\n  size_t i;\n  nodes[0].length = 0;\n  nodes[0].u.cost = 0;\n  InitStartPosQueue(&queue);\n  for (i = 0; i + 3 < num_bytes; i++) {\n    size_t skip = UpdateNodes(num_bytes, position, i, ringbuffer,\n        ringbuffer_mask, params, max_backward_limit, dist_cache,\n        num_matches[i], &matches[cur_match_pos], model, &queue, nodes);\n    if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;\n    cur_match_pos += num_matches[i];\n    if (num_matches[i] == 1 &&\n        BackwardMatchLength(&matches[cur_match_pos - 1]) > max_zopfli_len) {\n      skip = BROTLI_MAX(size_t,\n          BackwardMatchLength(&matches[cur_match_pos - 1]), skip);\n    }\n    if (skip > 1) {\n      skip--;\n      while (skip) {\n        i++;\n        if (i + 3 >= num_bytes) break;\n        EvaluateNode(position + stream_offset, i, max_backward_limit, gap,\n            dist_cache, model, &queue, nodes);\n        cur_match_pos += num_matches[i];\n        skip--;\n      }\n    }\n  }\n  return ComputeShortestPathFromNodes(num_bytes, nodes);\n}\n\nstatic void MergeMatches(BackwardMatch* dst,\n    BackwardMatch* src1, size_t len1, BackwardMatch* src2, size_t len2) {\n  while (len1 > 0 && len2 > 0) {\n    size_t l1 = BackwardMatchLength(src1);\n    size_t l2 = BackwardMatchLength(src2);\n    if (l1 < l2 || ((l1 == l2) && (src1->distance < src2->distance))) {\n      *dst++ = *src1++;\n      len1--;\n    } else {\n      *dst++ = *src2++;\n      len2--;\n    }\n  }\n  while (len1-- > 0) *dst++ = *src1++;\n  while (len2-- > 0) *dst++ = *src2++;\n}\n\n/* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */\nsize_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    const int* dist_cache, Hasher* hasher, ZopfliNode* nodes) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  const size_t max_zopfli_len = MaxZopfliLen(params);\n  StartPosQueue queue;\n  BackwardMatch* BROTLI_RESTRICT matches =\n      BROTLI_ALLOC(m, BackwardMatch, 2 * (MAX_NUM_MATCHES_H10 + 64));\n  const size_t store_end = num_bytes >= StoreLookaheadH10() ?\n      position + num_bytes - StoreLookaheadH10() + 1 : position;\n  size_t i;\n  const CompoundDictionary* addon = &params->dictionary.compound;\n  size_t gap = addon->total_size;\n  size_t lz_matches_offset =\n      (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0;\n  ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) || BROTLI_IS_NULL(matches)) {\n    return 0;\n  }\n  nodes[0].length = 0;\n  nodes[0].u.cost = 0;\n  InitZopfliCostModel(m, model, &params->dist, num_bytes);\n  if (BROTLI_IS_OOM(m)) return 0;\n  ZopfliCostModelSetFromLiteralCosts(\n      model, position, ringbuffer, ringbuffer_mask);\n  InitStartPosQueue(&queue);\n  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; i++) {\n    const size_t pos = position + i;\n    const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);\n    const size_t dictionary_start = BROTLI_MIN(size_t,\n        pos + stream_offset, max_backward_limit);\n    size_t skip;\n    size_t num_matches;\n    int dict_id = 0;\n    if (params->dictionary.contextual.context_based) {\n      uint8_t p1 = pos >= 1 ?\n          ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0;\n      uint8_t p2 = pos >= 2 ?\n          ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0;\n      dict_id = params->dictionary.contextual.context_map[\n          BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n    }\n    num_matches = FindAllMatchesH10(&hasher->privat._H10,\n        params->dictionary.contextual.dict[dict_id],\n        ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance,\n        dictionary_start + gap, params, &matches[lz_matches_offset]);\n    if (addon->num_chunks != 0) {\n      size_t cd_matches = LookupAllCompoundDictionaryMatches(addon,\n          ringbuffer, ringbuffer_mask, pos, 3, num_bytes - i,\n          dictionary_start, params->dist.max_distance,\n          &matches[lz_matches_offset - 64], 64);\n      MergeMatches(matches, &matches[lz_matches_offset - 64], cd_matches,\n          &matches[lz_matches_offset], num_matches);\n      num_matches += cd_matches;\n    }\n    if (num_matches > 0 &&\n        BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) {\n      matches[0] = matches[num_matches - 1];\n      num_matches = 1;\n    }\n    skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask,\n        params, max_backward_limit, dist_cache, num_matches, matches, model,\n        &queue, nodes);\n    if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;\n    if (num_matches == 1 && BackwardMatchLength(&matches[0]) > max_zopfli_len) {\n      skip = BROTLI_MAX(size_t, BackwardMatchLength(&matches[0]), skip);\n    }\n    if (skip > 1) {\n      /* Add the tail of the copy to the hasher. */\n      StoreRangeH10(&hasher->privat._H10,\n          ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN(\n          size_t, pos + skip, store_end));\n      skip--;\n      while (skip) {\n        i++;\n        if (i + HashTypeLengthH10() - 1 >= num_bytes) break;\n        EvaluateNode(position + stream_offset, i, max_backward_limit, gap,\n            dist_cache, model, &queue, nodes);\n        skip--;\n      }\n    }\n  }\n  CleanupZopfliCostModel(m, model);\n  BROTLI_FREE(m, model);\n  BROTLI_FREE(m, matches);\n  return ComputeShortestPathFromNodes(num_bytes, nodes);\n}\n\nvoid BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  ZopfliNode* nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return;\n  BrotliInitZopfliNodes(nodes, num_bytes + 1);\n  *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes,\n      position, ringbuffer, ringbuffer_mask, literal_context_lut, params,\n      dist_cache, hasher, nodes);\n  if (BROTLI_IS_OOM(m)) return;\n  BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache,\n      last_insert_len, params, commands, num_literals);\n  BROTLI_FREE(m, nodes);\n}\n\nvoid BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  uint32_t* num_matches = BROTLI_ALLOC(m, uint32_t, num_bytes);\n  size_t matches_size = 4 * num_bytes;\n  const size_t store_end = num_bytes >= StoreLookaheadH10() ?\n      position + num_bytes - StoreLookaheadH10() + 1 : position;\n  size_t cur_match_pos = 0;\n  size_t i;\n  size_t orig_num_literals;\n  size_t orig_last_insert_len;\n  int orig_dist_cache[4];\n  size_t orig_num_commands;\n  ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1);\n  ZopfliNode* nodes;\n  BackwardMatch* matches = BROTLI_ALLOC(m, BackwardMatch, matches_size);\n  const CompoundDictionary* addon = &params->dictionary.compound;\n  size_t gap = addon->total_size;\n  size_t shadow_matches =\n      (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) ||\n      BROTLI_IS_NULL(num_matches) || BROTLI_IS_NULL(matches)) {\n    return;\n  }\n  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; ++i) {\n    const size_t pos = position + i;\n    size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);\n    size_t dictionary_start = BROTLI_MIN(size_t,\n        pos + stream_offset, max_backward_limit);\n    size_t max_length = num_bytes - i;\n    size_t num_found_matches;\n    size_t cur_match_end;\n    size_t j;\n    int dict_id = 0;\n    if (params->dictionary.contextual.context_based) {\n      uint8_t p1 = pos >= 1 ?\n          ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0;\n      uint8_t p2 = pos >= 2 ?\n          ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0;\n      dict_id = params->dictionary.contextual.context_map[\n          BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n    }\n    /* Ensure that we have enough free slots. */\n    BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size,\n        cur_match_pos + MAX_NUM_MATCHES_H10 + shadow_matches);\n    if (BROTLI_IS_OOM(m)) return;\n    num_found_matches = FindAllMatchesH10(&hasher->privat._H10,\n        params->dictionary.contextual.dict[dict_id],\n        ringbuffer, ringbuffer_mask, pos, max_length,\n        max_distance, dictionary_start + gap, params,\n        &matches[cur_match_pos + shadow_matches]);\n    if (addon->num_chunks != 0) {\n      size_t cd_matches = LookupAllCompoundDictionaryMatches(addon,\n          ringbuffer, ringbuffer_mask, pos, 3, max_length,\n          dictionary_start, params->dist.max_distance,\n          &matches[cur_match_pos + shadow_matches - 64], 64);\n      MergeMatches(&matches[cur_match_pos],\n          &matches[cur_match_pos + shadow_matches - 64], cd_matches,\n          &matches[cur_match_pos + shadow_matches], num_found_matches);\n      num_found_matches += cd_matches;\n    }\n    cur_match_end = cur_match_pos + num_found_matches;\n    for (j = cur_match_pos; j + 1 < cur_match_end; ++j) {\n      BROTLI_DCHECK(BackwardMatchLength(&matches[j]) <=\n          BackwardMatchLength(&matches[j + 1]));\n    }\n    num_matches[i] = (uint32_t)num_found_matches;\n    if (num_found_matches > 0) {\n      const size_t match_len = BackwardMatchLength(&matches[cur_match_end - 1]);\n      if (match_len > MAX_ZOPFLI_LEN_QUALITY_11) {\n        const size_t skip = match_len - 1;\n        matches[cur_match_pos++] = matches[cur_match_end - 1];\n        num_matches[i] = 1;\n        /* Add the tail of the copy to the hasher. */\n        StoreRangeH10(&hasher->privat._H10,\n                      ringbuffer, ringbuffer_mask, pos + 1,\n                      BROTLI_MIN(size_t, pos + match_len, store_end));\n        memset(&num_matches[i + 1], 0, skip * sizeof(num_matches[0]));\n        i += skip;\n      } else {\n        cur_match_pos = cur_match_end;\n      }\n    }\n  }\n  orig_num_literals = *num_literals;\n  orig_last_insert_len = *last_insert_len;\n  memcpy(orig_dist_cache, dist_cache, 4 * sizeof(dist_cache[0]));\n  orig_num_commands = *num_commands;\n  nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return;\n  InitZopfliCostModel(m, model, &params->dist, num_bytes);\n  if (BROTLI_IS_OOM(m)) return;\n  for (i = 0; i < 2; i++) {\n    BrotliInitZopfliNodes(nodes, num_bytes + 1);\n    if (i == 0) {\n      ZopfliCostModelSetFromLiteralCosts(\n          model, position, ringbuffer, ringbuffer_mask);\n    } else {\n      ZopfliCostModelSetFromCommands(model, position, ringbuffer,\n          ringbuffer_mask, commands, *num_commands - orig_num_commands,\n          orig_last_insert_len);\n    }\n    *num_commands = orig_num_commands;\n    *num_literals = orig_num_literals;\n    *last_insert_len = orig_last_insert_len;\n    memcpy(dist_cache, orig_dist_cache, 4 * sizeof(dist_cache[0]));\n    *num_commands += ZopfliIterate(num_bytes, position, ringbuffer,\n        ringbuffer_mask, params, gap, dist_cache, model, num_matches, matches,\n        nodes);\n    BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache,\n        last_insert_len, params, commands, num_literals);\n  }\n  CleanupZopfliCostModel(m, model);\n  BROTLI_FREE(m, model);\n  BROTLI_FREE(m, nodes);\n  BROTLI_FREE(m, matches);\n  BROTLI_FREE(m, num_matches);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/backward_references_hq.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#ifndef BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_\n#define BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_\n\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"hash.h\"\n#include \"memory.h\"\n#include \"params.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nBROTLI_INTERNAL void BrotliCreateZopfliBackwardReferences(MemoryManager* m,\n    size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals);\n\nBROTLI_INTERNAL void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m,\n    size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals);\n\ntypedef struct ZopfliNode {\n  /* Best length to get up to this byte (not including this byte itself)\n     highest 7 bit is used to reconstruct the length code. */\n  uint32_t length;\n  /* Distance associated with the length. */\n  uint32_t distance;\n  /* Number of literal inserts before this copy; highest 5 bits contain\n     distance short code + 1 (or zero if no short code). */\n  uint32_t dcode_insert_length;\n\n  /* This union holds information used by dynamic-programming. During forward\n     pass |cost| it used to store the goal function. When node is processed its\n     |cost| is invalidated in favor of |shortcut|. On path back-tracing pass\n     |next| is assigned the offset to next node on the path. */\n  union {\n    /* Smallest cost to get to this byte from the beginning, as found so far. */\n    float cost;\n    /* Offset to the next node on the path. Equals to command_length() of the\n       next node on the path. For last node equals to BROTLI_UINT32_MAX */\n    uint32_t next;\n    /* Node position that provides next distance for distance cache. */\n    uint32_t shortcut;\n  } u;\n} ZopfliNode;\n\nBROTLI_INTERNAL void BrotliInitZopfliNodes(ZopfliNode* array, size_t length);\n\n/* Computes the shortest path of commands from position to at most\n   position + num_bytes.\n\n   On return, path->size() is the number of commands found and path[i] is the\n   length of the i-th command (copy length plus insert length).\n   Note that the sum of the lengths of all commands can be less than num_bytes.\n\n   On return, the nodes[0..num_bytes] array will have the following\n   \"ZopfliNode array invariant\":\n   For each i in [1..num_bytes], if nodes[i].cost < kInfinity, then\n     (1) nodes[i].copy_length() >= 2\n     (2) nodes[i].command_length() <= i and\n     (3) nodes[i - nodes[i].command_length()].cost < kInfinity */\nBROTLI_INTERNAL size_t BrotliZopfliComputeShortestPath(\n    MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    const int* dist_cache, Hasher* hasher, ZopfliNode* nodes);\n\nBROTLI_INTERNAL void BrotliZopfliCreateCommands(\n    const size_t num_bytes, const size_t block_start, const ZopfliNode* nodes,\n    int* dist_cache, size_t* last_insert_len, const BrotliEncoderParams* params,\n    Command* commands, size_t* num_literals);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/backward_references_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: EXPORT_FN, FN */\n\nstatic BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(\n    size_t num_bytes, size_t position,\n    const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  HASHER()* privat = &hasher->privat.FN(_);\n  /* Set maximum distance, see section 9.1. of the spec. */\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  const size_t position_offset = params->stream_offset;\n\n  const Command* const orig_commands = commands;\n  size_t insert_length = *last_insert_len;\n  const size_t pos_end = position + num_bytes;\n  const size_t store_end = num_bytes >= FN(StoreLookahead)() ?\n      position + num_bytes - FN(StoreLookahead)() + 1 : position;\n\n  /* For speed up heuristics for random data. */\n  const size_t random_heuristics_window_size =\n      LiteralSpreeLengthForSparseSearch(params);\n  size_t apply_random_heuristics = position + random_heuristics_window_size;\n  const size_t gap = params->dictionary.compound.total_size;\n\n  /* Minimum score to accept a backward reference. */\n  const score_t kMinScore = BROTLI_SCORE_BASE + 100;\n\n  FN(PrepareDistanceCache)(privat, dist_cache);\n\n  while (position + FN(HashTypeLength)() < pos_end) {\n    size_t max_length = pos_end - position;\n    size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit);\n    size_t dictionary_start = BROTLI_MIN(size_t,\n        position + position_offset, max_backward_limit);\n    HasherSearchResult sr;\n    int dict_id = 0;\n    uint8_t p1 = 0;\n    uint8_t p2 = 0;\n    if (params->dictionary.contextual.context_based) {\n      p1 = position >= 1 ?\n          ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0;\n      p2 = position >= 2 ?\n          ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0;\n      dict_id = params->dictionary.contextual.context_map[\n          BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n    }\n    sr.len = 0;\n    sr.len_code_delta = 0;\n    sr.distance = 0;\n    sr.score = kMinScore;\n    FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id],\n        ringbuffer, ringbuffer_mask, dist_cache, position, max_length,\n        max_distance, dictionary_start + gap, params->dist.max_distance, &sr);\n    if (ENABLE_COMPOUND_DICTIONARY) {\n      LookupCompoundDictionaryMatch(&params->dictionary.compound, ringbuffer,\n          ringbuffer_mask, dist_cache, position, max_length,\n          dictionary_start, params->dist.max_distance, &sr);\n    }\n    if (sr.score > kMinScore) {\n      /* Found a match. Let's look for something even better ahead. */\n      int delayed_backward_references_in_row = 0;\n      --max_length;\n      for (;; --max_length) {\n        const score_t cost_diff_lazy = 175;\n        HasherSearchResult sr2;\n        sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ?\n            BROTLI_MIN(size_t, sr.len - 1, max_length) : 0;\n        sr2.len_code_delta = 0;\n        sr2.distance = 0;\n        sr2.score = kMinScore;\n        max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit);\n        dictionary_start = BROTLI_MIN(size_t,\n            position + 1 + position_offset, max_backward_limit);\n        if (params->dictionary.contextual.context_based) {\n          p2 = p1;\n          p1 = ringbuffer[position & ringbuffer_mask];\n          dict_id = params->dictionary.contextual.context_map[\n              BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n        }\n        FN(FindLongestMatch)(privat,\n            params->dictionary.contextual.dict[dict_id],\n            ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length,\n            max_distance, dictionary_start + gap, params->dist.max_distance,\n            &sr2);\n        if (ENABLE_COMPOUND_DICTIONARY) {\n          LookupCompoundDictionaryMatch(\n              &params->dictionary.compound, ringbuffer,\n              ringbuffer_mask, dist_cache, position + 1, max_length,\n              dictionary_start, params->dist.max_distance, &sr2);\n        }\n        if (sr2.score >= sr.score + cost_diff_lazy) {\n          /* Ok, let's just write one byte for now and start a match from the\n             next byte. */\n          ++position;\n          ++insert_length;\n          sr = sr2;\n          if (++delayed_backward_references_in_row < 4 &&\n              position + FN(HashTypeLength)() < pos_end) {\n            continue;\n          }\n        }\n        break;\n      }\n      apply_random_heuristics =\n          position + 2 * sr.len + random_heuristics_window_size;\n      dictionary_start = BROTLI_MIN(size_t,\n          position + position_offset, max_backward_limit);\n      {\n        /* The first 16 codes are special short-codes,\n           and the minimum offset is 1. */\n        size_t distance_code = ComputeDistanceCode(\n            sr.distance, dictionary_start + gap, dist_cache);\n        if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) {\n          dist_cache[3] = dist_cache[2];\n          dist_cache[2] = dist_cache[1];\n          dist_cache[1] = dist_cache[0];\n          dist_cache[0] = (int)sr.distance;\n          FN(PrepareDistanceCache)(privat, dist_cache);\n        }\n        InitCommand(commands++, &params->dist, insert_length,\n            sr.len, sr.len_code_delta, distance_code);\n      }\n      *num_literals += insert_length;\n      insert_length = 0;\n      /* Put the hash keys into the table, if there are enough bytes left.\n         Depending on the hasher implementation, it can push all positions\n         in the given range or only a subset of them.\n         Avoid hash poisoning with RLE data. */\n      {\n        size_t range_start = position + 2;\n        size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end);\n        if (sr.distance < (sr.len >> 2)) {\n          range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t,\n              range_start, position + sr.len - (sr.distance << 2)));\n        }\n        FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start,\n                       range_end);\n      }\n      position += sr.len;\n    } else {\n      ++insert_length;\n      ++position;\n      /* If we have not seen matches for a long time, we can skip some\n         match lookups. Unsuccessful match lookups are very very expensive\n         and this kind of a heuristic speeds up compression quite\n         a lot. */\n      if (position > apply_random_heuristics) {\n        /* Going through uncompressible data, jump. */\n        if (position >\n            apply_random_heuristics + 4 * random_heuristics_window_size) {\n          /* It is quite a long time since we saw a copy, so we assume\n             that this data is not compressible, and store hashes less\n             often. Hashes of non compressible data are less likely to\n             turn out to be useful in the future, too, so we store less of\n             them to not to flood out the hash table of good compressible\n             data. */\n          const size_t kMargin =\n              BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4);\n          size_t pos_jump =\n              BROTLI_MIN(size_t, position + 16, pos_end - kMargin);\n          for (; position < pos_jump; position += 4) {\n            FN(Store)(privat, ringbuffer, ringbuffer_mask, position);\n            insert_length += 4;\n          }\n        } else {\n          const size_t kMargin =\n              BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2);\n          size_t pos_jump =\n              BROTLI_MIN(size_t, position + 8, pos_end - kMargin);\n          for (; position < pos_jump; position += 2) {\n            FN(Store)(privat, ringbuffer, ringbuffer_mask, position);\n            insert_length += 2;\n          }\n        }\n      }\n    }\n  }\n  insert_length += pos_end - position;\n  *last_insert_len = insert_length;\n  *num_commands += (size_t)(commands - orig_commands);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/bit_cost.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions to estimate the bit cost of Huffman trees. */\n\n#include \"bit_cost.h\"\n\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ndouble BrotliBitsEntropy(const uint32_t* population, size_t size) {\n  size_t sum = 0;\n  double retval = 0;\n  const uint32_t* population_end = population + size;\n  size_t p;\n  if (size & 1) {\n    goto odd_number_of_elements_left;\n  }\n  while (population < population_end) {\n    p = *population++;\n    sum += p;\n    retval -= (double)p * FastLog2(p);\n odd_number_of_elements_left:\n    p = *population++;\n    sum += p;\n    retval -= (double)p * FastLog2(p);\n  }\n  if (sum) retval += (double)sum * FastLog2(sum);\n\n  if (retval < (double)sum) {\n    /* TODO(eustas): consider doing that per-symbol? */\n    /* At least one bit per literal is needed. */\n    retval = (double)sum;\n  }\n\n  return retval;\n}\n\n#define FN(X) X ## Literal\n#include \"bit_cost_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"bit_cost_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"bit_cost_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/bit_cost.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions to estimate the bit cost of Huffman trees. */\n\n#ifndef BROTLI_ENC_BIT_COST_H_\n#define BROTLI_ENC_BIT_COST_H_\n\n#include \"../common/platform.h\"\n#include \"histogram.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nBROTLI_INTERNAL double BrotliBitsEntropy(\n    const uint32_t* population, size_t size);\nBROTLI_INTERNAL double BrotliPopulationCostLiteral(\n    const HistogramLiteral* histogram);\nBROTLI_INTERNAL double BrotliPopulationCostCommand(\n    const HistogramCommand* histogram);\nBROTLI_INTERNAL double BrotliPopulationCostDistance(\n    const HistogramDistance* histogram);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BIT_COST_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/bit_cost_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n#define HistogramType FN(Histogram)\n\ndouble FN(BrotliPopulationCost)(const HistogramType* histogram) {\n  static const double kOneSymbolHistogramCost = 12;\n  static const double kTwoSymbolHistogramCost = 20;\n  static const double kThreeSymbolHistogramCost = 28;\n  static const double kFourSymbolHistogramCost = 37;\n  const size_t data_size = FN(HistogramDataSize)();\n  int count = 0;\n  size_t s[5];\n  double bits = 0.0;\n  size_t i;\n  if (histogram->total_count_ == 0) {\n    return kOneSymbolHistogramCost;\n  }\n  for (i = 0; i < data_size; ++i) {\n    if (histogram->data_[i] > 0) {\n      s[count] = i;\n      ++count;\n      if (count > 4) break;\n    }\n  }\n  if (count == 1) {\n    return kOneSymbolHistogramCost;\n  }\n  if (count == 2) {\n    return (kTwoSymbolHistogramCost + (double)histogram->total_count_);\n  }\n  if (count == 3) {\n    const uint32_t histo0 = histogram->data_[s[0]];\n    const uint32_t histo1 = histogram->data_[s[1]];\n    const uint32_t histo2 = histogram->data_[s[2]];\n    const uint32_t histomax =\n        BROTLI_MAX(uint32_t, histo0, BROTLI_MAX(uint32_t, histo1, histo2));\n    return (kThreeSymbolHistogramCost +\n            2 * (histo0 + histo1 + histo2) - histomax);\n  }\n  if (count == 4) {\n    uint32_t histo[4];\n    uint32_t h23;\n    uint32_t histomax;\n    for (i = 0; i < 4; ++i) {\n      histo[i] = histogram->data_[s[i]];\n    }\n    /* Sort */\n    for (i = 0; i < 4; ++i) {\n      size_t j;\n      for (j = i + 1; j < 4; ++j) {\n        if (histo[j] > histo[i]) {\n          BROTLI_SWAP(uint32_t, histo, j, i);\n        }\n      }\n    }\n    h23 = histo[2] + histo[3];\n    histomax = BROTLI_MAX(uint32_t, h23, histo[0]);\n    return (kFourSymbolHistogramCost +\n            3 * h23 + 2 * (histo[0] + histo[1]) - histomax);\n  }\n\n  {\n    /* In this loop we compute the entropy of the histogram and simultaneously\n       build a simplified histogram of the code length codes where we use the\n       zero repeat code 17, but we don't use the non-zero repeat code 16. */\n    size_t max_depth = 1;\n    uint32_t depth_histo[BROTLI_CODE_LENGTH_CODES] = { 0 };\n    const double log2total = FastLog2(histogram->total_count_);\n    for (i = 0; i < data_size;) {\n      if (histogram->data_[i] > 0) {\n        /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) =\n                                    = log2(total_count) - log2(count(symbol)) */\n        double log2p = log2total - FastLog2(histogram->data_[i]);\n        /* Approximate the bit depth by round(-log2(P(symbol))) */\n        size_t depth = (size_t)(log2p + 0.5);\n        bits += histogram->data_[i] * log2p;\n        if (depth > 15) {\n          depth = 15;\n        }\n        if (depth > max_depth) {\n          max_depth = depth;\n        }\n        ++depth_histo[depth];\n        ++i;\n      } else {\n        /* Compute the run length of zeros and add the appropriate number of 0\n           and 17 code length codes to the code length code histogram. */\n        uint32_t reps = 1;\n        size_t k;\n        for (k = i + 1; k < data_size && histogram->data_[k] == 0; ++k) {\n          ++reps;\n        }\n        i += reps;\n        if (i == data_size) {\n          /* Don't add any cost for the last zero run, since these are encoded\n             only implicitly. */\n          break;\n        }\n        if (reps < 3) {\n          depth_histo[0] += reps;\n        } else {\n          reps -= 2;\n          while (reps > 0) {\n            ++depth_histo[BROTLI_REPEAT_ZERO_CODE_LENGTH];\n            /* Add the 3 extra bits for the 17 code length code. */\n            bits += 3;\n            reps >>= 3;\n          }\n        }\n      }\n    }\n    /* Add the estimated encoding cost of the code length code histogram. */\n    bits += (double)(18 + 2 * max_depth);\n    /* Add the entropy of the code length code histogram. */\n    bits += BrotliBitsEntropy(depth_histo, BROTLI_CODE_LENGTH_CODES);\n  }\n  return bits;\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/block_encoder_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2014 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n#define HistogramType FN(Histogram)\n\n/* Creates entropy codes for all block types and stores them to the bit\n   stream. */\nstatic void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self,\n    const HistogramType* histograms, const size_t histograms_size,\n    const size_t alphabet_size, HuffmanTree* tree,\n    size_t* storage_ix, uint8_t* storage) {\n  const size_t table_size = histograms_size * self->histogram_length_;\n  self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size);\n  self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size);\n  if (BROTLI_IS_OOM(m)) return;\n\n  {\n    size_t i;\n    for (i = 0; i < histograms_size; ++i) {\n      size_t ix = i * self->histogram_length_;\n      BuildAndStoreHuffmanTree(&histograms[i].data_[0], self->histogram_length_,\n          alphabet_size, tree, &self->depths_[ix], &self->bits_[ix],\n          storage_ix, storage);\n    }\n  }\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/block_splitter.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Block split point selection utilities. */\n\n#include \"block_splitter.h\"\n\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"\n#include \"cluster.h\"\n#include \"command.h\"\n#include \"fast_log.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic const size_t kMaxLiteralHistograms = 100;\nstatic const size_t kMaxCommandHistograms = 50;\nstatic const double kLiteralBlockSwitchCost = 28.1;\nstatic const double kCommandBlockSwitchCost = 13.5;\nstatic const double kDistanceBlockSwitchCost = 14.6;\nstatic const size_t kLiteralStrideLength = 70;\nstatic const size_t kCommandStrideLength = 40;\nstatic const size_t kDistanceStrideLength = 40;\nstatic const size_t kSymbolsPerLiteralHistogram = 544;\nstatic const size_t kSymbolsPerCommandHistogram = 530;\nstatic const size_t kSymbolsPerDistanceHistogram = 544;\nstatic const size_t kMinLengthForBlockSplitting = 128;\nstatic const size_t kIterMulForRefining = 2;\nstatic const size_t kMinItersForRefining = 100;\n\nstatic size_t CountLiterals(const Command* cmds, const size_t num_commands) {\n  /* Count how many we have. */\n  size_t total_length = 0;\n  size_t i;\n  for (i = 0; i < num_commands; ++i) {\n    total_length += cmds[i].insert_len_;\n  }\n  return total_length;\n}\n\nstatic void CopyLiteralsToByteArray(const Command* cmds,\n                                    const size_t num_commands,\n                                    const uint8_t* data,\n                                    const size_t offset,\n                                    const size_t mask,\n                                    uint8_t* literals) {\n  size_t pos = 0;\n  size_t from_pos = offset & mask;\n  size_t i;\n  for (i = 0; i < num_commands; ++i) {\n    size_t insert_len = cmds[i].insert_len_;\n    if (from_pos + insert_len > mask) {\n      size_t head_size = mask + 1 - from_pos;\n      memcpy(literals + pos, data + from_pos, head_size);\n      from_pos = 0;\n      pos += head_size;\n      insert_len -= head_size;\n    }\n    if (insert_len > 0) {\n      memcpy(literals + pos, data + from_pos, insert_len);\n      pos += insert_len;\n    }\n    from_pos = (from_pos + insert_len + CommandCopyLen(&cmds[i])) & mask;\n  }\n}\n\nstatic BROTLI_INLINE uint32_t MyRand(uint32_t* seed) {\n  /* Initial seed should be 7. In this case, loop length is (1 << 29). */\n  *seed *= 16807U;\n  return *seed;\n}\n\nstatic BROTLI_INLINE double BitCost(size_t count) {\n  return count == 0 ? -2.0 : FastLog2(count);\n}\n\n#define HISTOGRAMS_PER_BATCH 64\n#define CLUSTERS_PER_BATCH 16\n\n#define FN(X) X ## Literal\n#define DataType uint8_t\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_splitter_inc.h\"\n#undef DataType\n#undef FN\n\n#define FN(X) X ## Command\n#define DataType uint16_t\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_splitter_inc.h\"\n#undef FN\n\n#define FN(X) X ## Distance\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_splitter_inc.h\"\n#undef DataType\n#undef FN\n\nvoid BrotliInitBlockSplit(BlockSplit* self) {\n  self->num_types = 0;\n  self->num_blocks = 0;\n  self->types = 0;\n  self->lengths = 0;\n  self->types_alloc_size = 0;\n  self->lengths_alloc_size = 0;\n}\n\nvoid BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self) {\n  BROTLI_FREE(m, self->types);\n  BROTLI_FREE(m, self->lengths);\n}\n\n/* Extracts literals, command distance and prefix codes, then applies\n * SplitByteVector to create partitioning. */\nvoid BrotliSplitBlock(MemoryManager* m,\n                      const Command* cmds,\n                      const size_t num_commands,\n                      const uint8_t* data,\n                      const size_t pos,\n                      const size_t mask,\n                      const BrotliEncoderParams* params,\n                      BlockSplit* literal_split,\n                      BlockSplit* insert_and_copy_split,\n                      BlockSplit* dist_split) {\n  {\n    size_t literals_count = CountLiterals(cmds, num_commands);\n    uint8_t* literals = BROTLI_ALLOC(m, uint8_t, literals_count);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literals)) return;\n    /* Create a continuous array of literals. */\n    CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals);\n    /* Create the block split on the array of literals.\n     * Literal histograms can have alphabet size up to 256.\n     * Though, to accommodate context modeling, less than half of maximum size\n     * is allowed. */\n    SplitByteVectorLiteral(\n        m, literals, literals_count,\n        kSymbolsPerLiteralHistogram, kMaxLiteralHistograms,\n        kLiteralStrideLength, kLiteralBlockSwitchCost, params,\n        literal_split);\n    if (BROTLI_IS_OOM(m)) return;\n    BROTLI_FREE(m, literals);\n    /* NB: this might be a good place for injecting extra splitting without\n     *     increasing encoder complexity; however, output partition would be less\n     *     optimal than one produced with forced splitting inside\n     *     SplitByteVector (FindBlocks / ClusterBlocks). */\n  }\n\n  {\n    /* Compute prefix codes for commands. */\n    uint16_t* insert_and_copy_codes = BROTLI_ALLOC(m, uint16_t, num_commands);\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(insert_and_copy_codes)) return;\n    for (i = 0; i < num_commands; ++i) {\n      insert_and_copy_codes[i] = cmds[i].cmd_prefix_;\n    }\n    /* Create the block split on the array of command prefixes. */\n    SplitByteVectorCommand(\n        m, insert_and_copy_codes, num_commands,\n        kSymbolsPerCommandHistogram, kMaxCommandHistograms,\n        kCommandStrideLength, kCommandBlockSwitchCost, params,\n        insert_and_copy_split);\n    if (BROTLI_IS_OOM(m)) return;\n    /* TODO(eustas): reuse for distances? */\n    BROTLI_FREE(m, insert_and_copy_codes);\n  }\n\n  {\n    /* Create a continuous array of distance prefixes. */\n    uint16_t* distance_prefixes = BROTLI_ALLOC(m, uint16_t, num_commands);\n    size_t j = 0;\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_prefixes)) return;\n    for (i = 0; i < num_commands; ++i) {\n      const Command* cmd = &cmds[i];\n      if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {\n        distance_prefixes[j++] = cmd->dist_prefix_ & 0x3FF;\n      }\n    }\n    /* Create the block split on the array of distance prefixes. */\n    SplitByteVectorDistance(\n        m, distance_prefixes, j,\n        kSymbolsPerDistanceHistogram, kMaxCommandHistograms,\n        kDistanceStrideLength, kDistanceBlockSwitchCost, params,\n        dist_split);\n    if (BROTLI_IS_OOM(m)) return;\n    BROTLI_FREE(m, distance_prefixes);\n  }\n}\n\n#if defined(BROTLI_TEST)\nsize_t BrotliCountLiteralsForTest(const Command*, size_t);\nsize_t BrotliCountLiteralsForTest(const Command* cmds, size_t num_commands) {\n  return CountLiterals(cmds, num_commands);\n}\nvoid BrotliCopyLiteralsToByteArrayForTest(\n    const Command*, size_t, const uint8_t*, size_t, size_t, uint8_t*);\nvoid BrotliCopyLiteralsToByteArrayForTest(const Command* cmds,\n    size_t num_commands, const uint8_t* data, size_t offset, size_t mask,\n    uint8_t* literals) {\n  CopyLiteralsToByteArray(cmds, num_commands, data, offset, mask, literals);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/block_splitter.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Block split point selection utilities. */\n\n#ifndef BROTLI_ENC_BLOCK_SPLITTER_H_\n#define BROTLI_ENC_BLOCK_SPLITTER_H_\n\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"memory.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BlockSplit {\n  size_t num_types;  /* Amount of distinct types */\n  size_t num_blocks;  /* Amount of values in types and length */\n  uint8_t* types;\n  uint32_t* lengths;\n\n  size_t types_alloc_size;\n  size_t lengths_alloc_size;\n} BlockSplit;\n\nBROTLI_INTERNAL void BrotliInitBlockSplit(BlockSplit* self);\nBROTLI_INTERNAL void BrotliDestroyBlockSplit(MemoryManager* m,\n                                             BlockSplit* self);\n\nBROTLI_INTERNAL void BrotliSplitBlock(MemoryManager* m,\n                                      const Command* cmds,\n                                      const size_t num_commands,\n                                      const uint8_t* data,\n                                      const size_t offset,\n                                      const size_t mask,\n                                      const BrotliEncoderParams* params,\n                                      BlockSplit* literal_split,\n                                      BlockSplit* insert_and_copy_split,\n                                      BlockSplit* dist_split);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BLOCK_SPLITTER_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/block_splitter_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, DataType */\n\n#define HistogramType FN(Histogram)\n\nstatic void FN(InitialEntropyCodes)(const DataType* data, size_t length,\n                                    size_t stride,\n                                    size_t num_histograms,\n                                    HistogramType* histograms) {\n  uint32_t seed = 7;\n  size_t block_length = length / num_histograms;\n  size_t i;\n  FN(ClearHistograms)(histograms, num_histograms);\n  for (i = 0; i < num_histograms; ++i) {\n    size_t pos = length * i / num_histograms;\n    if (i != 0) {\n      pos += MyRand(&seed) % block_length;\n    }\n    if (pos + stride >= length) {\n      pos = length - stride - 1;\n    }\n    FN(HistogramAddVector)(&histograms[i], data + pos, stride);\n  }\n}\n\nstatic void FN(RandomSample)(uint32_t* seed,\n                             const DataType* data,\n                             size_t length,\n                             size_t stride,\n                             HistogramType* sample) {\n  size_t pos = 0;\n  if (stride >= length) {\n    stride = length;\n  } else {\n    pos = MyRand(seed) % (length - stride + 1);\n  }\n  FN(HistogramAddVector)(sample, data + pos, stride);\n}\n\nstatic void FN(RefineEntropyCodes)(const DataType* data, size_t length,\n                                   size_t stride,\n                                   size_t num_histograms,\n                                   HistogramType* histograms,\n                                   HistogramType* tmp) {\n  size_t iters =\n      kIterMulForRefining * length / stride + kMinItersForRefining;\n  uint32_t seed = 7;\n  size_t iter;\n  iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms;\n  for (iter = 0; iter < iters; ++iter) {\n    FN(HistogramClear)(tmp);\n    FN(RandomSample)(&seed, data, length, stride, tmp);\n    FN(HistogramAddHistogram)(&histograms[iter % num_histograms], tmp);\n  }\n}\n\n/* Assigns a block id from the range [0, num_histograms) to each data element\n   in data[0..length) and fills in block_id[0..length) with the assigned values.\n   Returns the number of blocks, i.e. one plus the number of block switches. */\nstatic size_t FN(FindBlocks)(const DataType* data, const size_t length,\n                             const double block_switch_bitcost,\n                             const size_t num_histograms,\n                             const HistogramType* histograms,\n                             double* insert_cost,\n                             double* cost,\n                             uint8_t* switch_signal,\n                             uint8_t* block_id) {\n  const size_t alphabet_size = FN(HistogramDataSize)();\n  const size_t bitmap_len = (num_histograms + 7) >> 3;\n  size_t num_blocks = 1;\n  size_t byte_ix;\n  size_t i;\n  size_t j;\n  BROTLI_DCHECK(num_histograms <= 256);\n\n  /* Trivial case: single histogram -> single block type. */\n  if (num_histograms <= 1) {\n    for (i = 0; i < length; ++i) {\n      block_id[i] = 0;\n    }\n    return 1;\n  }\n\n  /* Fill bitcost for each symbol of all histograms.\n   * Non-existing symbol cost: 2 + log2(total_count).\n   * Regular symbol cost: -log2(symbol_count / total_count). */\n  memset(insert_cost, 0,\n         sizeof(insert_cost[0]) * alphabet_size * num_histograms);\n  for (i = 0; i < num_histograms; ++i) {\n    insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_);\n  }\n  for (i = alphabet_size; i != 0;) {\n    /* Reverse order to use the 0-th row as a temporary storage. */\n    --i;\n    for (j = 0; j < num_histograms; ++j) {\n      insert_cost[i * num_histograms + j] =\n          insert_cost[j] - BitCost(histograms[j].data_[i]);\n    }\n  }\n\n  /* After each iteration of this loop, cost[k] will contain the difference\n     between the minimum cost of arriving at the current byte position using\n     entropy code k, and the minimum cost of arriving at the current byte\n     position. This difference is capped at the block switch cost, and if it\n     reaches block switch cost, it means that when we trace back from the last\n     position, we need to switch here. */\n  memset(cost, 0, sizeof(cost[0]) * num_histograms);\n  memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmap_len);\n  for (byte_ix = 0; byte_ix < length; ++byte_ix) {\n    size_t ix = byte_ix * bitmap_len;\n    size_t symbol = data[byte_ix];\n    size_t insert_cost_ix = symbol * num_histograms;\n    double min_cost = 1e99;\n    double block_switch_cost = block_switch_bitcost;\n    static const size_t prologue_length = 2000;\n    static const double multiplier = 0.07 / 2000;\n    size_t k;\n    for (k = 0; k < num_histograms; ++k) {\n      /* We are coding the symbol with entropy code k. */\n      cost[k] += insert_cost[insert_cost_ix + k];\n      if (cost[k] < min_cost) {\n        min_cost = cost[k];\n        block_id[byte_ix] = (uint8_t)k;\n      }\n    }\n    /* More blocks for the beginning. */\n    if (byte_ix < prologue_length) {\n      block_switch_cost *= 0.77 + multiplier * (double)byte_ix;\n    }\n    for (k = 0; k < num_histograms; ++k) {\n      cost[k] -= min_cost;\n      if (cost[k] >= block_switch_cost) {\n        const uint8_t mask = (uint8_t)(1u << (k & 7));\n        cost[k] = block_switch_cost;\n        BROTLI_DCHECK((k >> 3) < bitmap_len);\n        switch_signal[ix + (k >> 3)] |= mask;\n      }\n    }\n  }\n\n  byte_ix = length - 1;\n  {  /* Trace back from the last position and switch at the marked places. */\n    size_t ix = byte_ix * bitmap_len;\n    uint8_t cur_id = block_id[byte_ix];\n    while (byte_ix > 0) {\n      const uint8_t mask = (uint8_t)(1u << (cur_id & 7));\n      BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmap_len);\n      --byte_ix;\n      ix -= bitmap_len;\n      if (switch_signal[ix + (cur_id >> 3)] & mask) {\n        if (cur_id != block_id[byte_ix]) {\n          cur_id = block_id[byte_ix];\n          ++num_blocks;\n        }\n      }\n      block_id[byte_ix] = cur_id;\n    }\n  }\n  return num_blocks;\n}\n\nstatic size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length,\n                                uint16_t* new_id, const size_t num_histograms) {\n  static const uint16_t kInvalidId = 256;\n  uint16_t next_id = 0;\n  size_t i;\n  for (i = 0; i < num_histograms; ++i) {\n    new_id[i] = kInvalidId;\n  }\n  for (i = 0; i < length; ++i) {\n    BROTLI_DCHECK(block_ids[i] < num_histograms);\n    if (new_id[block_ids[i]] == kInvalidId) {\n      new_id[block_ids[i]] = next_id++;\n    }\n  }\n  for (i = 0; i < length; ++i) {\n    block_ids[i] = (uint8_t)new_id[block_ids[i]];\n    BROTLI_DCHECK(block_ids[i] < num_histograms);\n  }\n  BROTLI_DCHECK(next_id <= num_histograms);\n  return next_id;\n}\n\nstatic void FN(BuildBlockHistograms)(const DataType* data, const size_t length,\n                                     const uint8_t* block_ids,\n                                     const size_t num_histograms,\n                                     HistogramType* histograms) {\n  size_t i;\n  FN(ClearHistograms)(histograms, num_histograms);\n  for (i = 0; i < length; ++i) {\n    FN(HistogramAdd)(&histograms[block_ids[i]], data[i]);\n  }\n}\n\n/* Given the initial partitioning build partitioning with limited number\n * of histograms (and block types). */\nstatic void FN(ClusterBlocks)(MemoryManager* m,\n                              const DataType* data, const size_t length,\n                              const size_t num_blocks,\n                              uint8_t* block_ids,\n                              BlockSplit* split) {\n  uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks);\n  uint32_t* u32 =\n      BROTLI_ALLOC(m, uint32_t, num_blocks + 4 * HISTOGRAMS_PER_BATCH);\n  const size_t expected_num_clusters = CLUSTERS_PER_BATCH *\n      (num_blocks + HISTOGRAMS_PER_BATCH - 1) / HISTOGRAMS_PER_BATCH;\n  size_t all_histograms_size = 0;\n  size_t all_histograms_capacity = expected_num_clusters;\n  HistogramType* all_histograms =\n      BROTLI_ALLOC(m, HistogramType, all_histograms_capacity);\n  size_t cluster_size_size = 0;\n  size_t cluster_size_capacity = expected_num_clusters;\n  uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity);\n  size_t num_clusters = 0;\n  HistogramType* histograms = BROTLI_ALLOC(m, HistogramType,\n      BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH));\n  size_t max_num_pairs =\n      HISTOGRAMS_PER_BATCH * HISTOGRAMS_PER_BATCH / 2;\n  size_t pairs_capacity = max_num_pairs + 1;\n  HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity);\n  size_t pos = 0;\n  uint32_t* clusters;\n  size_t num_final_clusters;\n  static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX;\n  uint32_t* new_index;\n  size_t i;\n  uint32_t* BROTLI_RESTRICT const sizes =\n      u32 ? (u32 + 0 * HISTOGRAMS_PER_BATCH) : NULL;\n  uint32_t* BROTLI_RESTRICT const new_clusters =\n      u32 ? (u32 + 1 * HISTOGRAMS_PER_BATCH) : NULL;\n  uint32_t* BROTLI_RESTRICT const symbols =\n      u32 ? (u32 + 2 * HISTOGRAMS_PER_BATCH) : NULL;\n  uint32_t* BROTLI_RESTRICT const remap =\n      u32 ? (u32 + 3 * HISTOGRAMS_PER_BATCH) : NULL;\n  uint32_t* BROTLI_RESTRICT const block_lengths =\n      u32 ? (u32 + 4 * HISTOGRAMS_PER_BATCH) : NULL;\n  /* TODO(eustas): move to arena? */\n  HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 2);\n\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histogram_symbols) ||\n      BROTLI_IS_NULL(u32) || BROTLI_IS_NULL(all_histograms) ||\n      BROTLI_IS_NULL(cluster_size) || BROTLI_IS_NULL(histograms) ||\n      BROTLI_IS_NULL(pairs) || BROTLI_IS_NULL(tmp)) {\n    return;\n  }\n\n  memset(u32, 0, (num_blocks + 4 * HISTOGRAMS_PER_BATCH) * sizeof(uint32_t));\n\n  /* Calculate block lengths (convert repeating values -> series length). */\n  {\n    size_t block_idx = 0;\n    for (i = 0; i < length; ++i) {\n      BROTLI_DCHECK(block_idx < num_blocks);\n      ++block_lengths[block_idx];\n      if (i + 1 == length || block_ids[i] != block_ids[i + 1]) {\n        ++block_idx;\n      }\n    }\n    BROTLI_DCHECK(block_idx == num_blocks);\n  }\n\n  /* Pre-cluster blocks (cluster batches). */\n  for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH) {\n    const size_t num_to_combine =\n        BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH);\n    size_t num_new_clusters;\n    size_t j;\n    for (j = 0; j < num_to_combine; ++j) {\n      size_t k;\n      size_t block_length = block_lengths[i + j];\n      FN(HistogramClear)(&histograms[j]);\n      for (k = 0; k < block_length; ++k) {\n        FN(HistogramAdd)(&histograms[j], data[pos++]);\n      }\n      histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]);\n      new_clusters[j] = (uint32_t)j;\n      symbols[j] = (uint32_t)j;\n      sizes[j] = 1;\n    }\n    num_new_clusters = FN(BrotliHistogramCombine)(\n        histograms, tmp, sizes, symbols, new_clusters, pairs, num_to_combine,\n        num_to_combine, HISTOGRAMS_PER_BATCH, max_num_pairs);\n    BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms,\n        all_histograms_capacity, all_histograms_size + num_new_clusters);\n    BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size,\n        cluster_size_capacity, cluster_size_size + num_new_clusters);\n    if (BROTLI_IS_OOM(m)) return;\n    for (j = 0; j < num_new_clusters; ++j) {\n      all_histograms[all_histograms_size++] = histograms[new_clusters[j]];\n      cluster_size[cluster_size_size++] = sizes[new_clusters[j]];\n      remap[new_clusters[j]] = (uint32_t)j;\n    }\n    for (j = 0; j < num_to_combine; ++j) {\n      histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]];\n    }\n    num_clusters += num_new_clusters;\n    BROTLI_DCHECK(num_clusters == cluster_size_size);\n    BROTLI_DCHECK(num_clusters == all_histograms_size);\n  }\n  BROTLI_FREE(m, histograms);\n\n  /* Final clustering. */\n  max_num_pairs =\n      BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters);\n  if (pairs_capacity < max_num_pairs + 1) {\n    BROTLI_FREE(m, pairs);\n    pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(pairs)) return;\n  }\n  clusters = BROTLI_ALLOC(m, uint32_t, num_clusters);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(clusters)) return;\n  for (i = 0; i < num_clusters; ++i) {\n    clusters[i] = (uint32_t)i;\n  }\n  num_final_clusters = FN(BrotliHistogramCombine)(\n      all_histograms, tmp, cluster_size, histogram_symbols, clusters, pairs,\n      num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES,\n      max_num_pairs);\n  BROTLI_FREE(m, pairs);\n  BROTLI_FREE(m, cluster_size);\n\n  /* Assign blocks to final histograms. */\n  new_index = BROTLI_ALLOC(m, uint32_t, num_clusters);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return;\n  for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex;\n  pos = 0;\n  {\n    uint32_t next_index = 0;\n    for (i = 0; i < num_blocks; ++i) {\n      size_t j;\n      uint32_t best_out;\n      double best_bits;\n      FN(HistogramClear)(tmp);\n      for (j = 0; j < block_lengths[i]; ++j) {\n        FN(HistogramAdd)(tmp, data[pos++]);\n      }\n      /* Among equally good histograms prefer last used. */\n      /* TODO(eustas): should we give a block-switch discount here? */\n      best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1];\n      best_bits = FN(BrotliHistogramBitCostDistance)(\n          tmp, &all_histograms[best_out], tmp + 1);\n      for (j = 0; j < num_final_clusters; ++j) {\n        const double cur_bits = FN(BrotliHistogramBitCostDistance)(\n            tmp, &all_histograms[clusters[j]], tmp + 1);\n        if (cur_bits < best_bits) {\n          best_bits = cur_bits;\n          best_out = clusters[j];\n        }\n      }\n      histogram_symbols[i] = best_out;\n      if (new_index[best_out] == kInvalidIndex) {\n        new_index[best_out] = next_index++;\n      }\n    }\n  }\n  BROTLI_FREE(m, tmp);\n  BROTLI_FREE(m, clusters);\n  BROTLI_FREE(m, all_histograms);\n  BROTLI_ENSURE_CAPACITY(\n      m, uint8_t, split->types, split->types_alloc_size, num_blocks);\n  BROTLI_ENSURE_CAPACITY(\n      m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks);\n  if (BROTLI_IS_OOM(m)) return;\n\n  /* Rewrite final assignment to block-split. There might be less blocks\n   * than |num_blocks| due to clustering. */\n  {\n    uint32_t cur_length = 0;\n    size_t block_idx = 0;\n    uint8_t max_type = 0;\n    for (i = 0; i < num_blocks; ++i) {\n      cur_length += block_lengths[i];\n      if (i + 1 == num_blocks ||\n          histogram_symbols[i] != histogram_symbols[i + 1]) {\n        const uint8_t id = (uint8_t)new_index[histogram_symbols[i]];\n        split->types[block_idx] = id;\n        split->lengths[block_idx] = cur_length;\n        max_type = BROTLI_MAX(uint8_t, max_type, id);\n        cur_length = 0;\n        ++block_idx;\n      }\n    }\n    split->num_blocks = block_idx;\n    split->num_types = (size_t)max_type + 1;\n  }\n  BROTLI_FREE(m, new_index);\n  BROTLI_FREE(m, u32);\n  BROTLI_FREE(m, histogram_symbols);\n}\n\n/* Create BlockSplit (partitioning) given the limits, estimates and \"effort\"\n * parameters.\n *\n * NB: max_histograms is often less than number of histograms allowed by format;\n *     this is done intentionally, to save some \"space\" for context-aware\n *     clustering (here entropy is estimated for context-free symbols). */\nstatic void FN(SplitByteVector)(MemoryManager* m,\n                                const DataType* data, const size_t length,\n                                const size_t symbols_per_histogram,\n                                const size_t max_histograms,\n                                const size_t sampling_stride_length,\n                                const double block_switch_cost,\n                                const BrotliEncoderParams* params,\n                                BlockSplit* split) {\n  const size_t data_size = FN(HistogramDataSize)();\n  HistogramType* histograms;\n  HistogramType* tmp;\n  /* Calculate number of histograms; initial estimate is one histogram per\n   * specified amount of symbols; however, this value is capped. */\n  size_t num_histograms = length / symbols_per_histogram + 1;\n  if (num_histograms > max_histograms) {\n    num_histograms = max_histograms;\n  }\n\n  /* Corner case: no input. */\n  if (length == 0) {\n    split->num_types = 1;\n    return;\n  }\n\n  if (length < kMinLengthForBlockSplitting) {\n    BROTLI_ENSURE_CAPACITY(m, uint8_t,\n        split->types, split->types_alloc_size, split->num_blocks + 1);\n    BROTLI_ENSURE_CAPACITY(m, uint32_t,\n        split->lengths, split->lengths_alloc_size, split->num_blocks + 1);\n    if (BROTLI_IS_OOM(m)) return;\n    split->num_types = 1;\n    split->types[split->num_blocks] = 0;\n    split->lengths[split->num_blocks] = (uint32_t)length;\n    split->num_blocks++;\n    return;\n  }\n  histograms = BROTLI_ALLOC(m, HistogramType, num_histograms + 1);\n  tmp = histograms + num_histograms;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histograms)) return;\n  /* Find good entropy codes. */\n  FN(InitialEntropyCodes)(data, length,\n                          sampling_stride_length,\n                          num_histograms, histograms);\n  FN(RefineEntropyCodes)(data, length,\n                         sampling_stride_length,\n                         num_histograms, histograms, tmp);\n  {\n    /* Find a good path through literals with the good entropy codes. */\n    uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length);\n    size_t num_blocks = 0;\n    const size_t bitmaplen = (num_histograms + 7) >> 3;\n    double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms);\n    double* cost = BROTLI_ALLOC(m, double, num_histograms);\n    uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen);\n    uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms);\n    const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY ? 3 : 10;\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(block_ids) ||\n        BROTLI_IS_NULL(insert_cost) || BROTLI_IS_NULL(cost) ||\n        BROTLI_IS_NULL(switch_signal) || BROTLI_IS_NULL(new_id)) {\n      return;\n    }\n    for (i = 0; i < iters; ++i) {\n      num_blocks = FN(FindBlocks)(data, length,\n                                  block_switch_cost,\n                                  num_histograms, histograms,\n                                  insert_cost, cost, switch_signal,\n                                  block_ids);\n      num_histograms = FN(RemapBlockIds)(block_ids, length,\n                                         new_id, num_histograms);\n      FN(BuildBlockHistograms)(data, length, block_ids,\n                               num_histograms, histograms);\n    }\n    BROTLI_FREE(m, insert_cost);\n    BROTLI_FREE(m, cost);\n    BROTLI_FREE(m, switch_signal);\n    BROTLI_FREE(m, new_id);\n    BROTLI_FREE(m, histograms);\n    FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split);\n    if (BROTLI_IS_OOM(m)) return;\n    BROTLI_FREE(m, block_ids);\n  }\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/brotli_bit_stream.c",
    "content": "﻿/* Copyright 2014 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Brotli bit stream functions to support the low level format. There are no\n   compression algorithms here, just the right ordering of bits to match the\n   specs. */\n\n#include \"brotli_bit_stream.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"entropy_encode.h\"\n#include \"entropy_encode_static.h\"\n#include \"fast_log.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_HUFFMAN_TREE_SIZE (2 * BROTLI_NUM_COMMAND_SYMBOLS + 1)\n/* The maximum size of Huffman dictionary for distances assuming that\n   NPOSTFIX = 0 and NDIRECT = 0. */\n#define MAX_SIMPLE_DISTANCE_ALPHABET_SIZE \\\n  BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_LARGE_MAX_DISTANCE_BITS)\n/* MAX_SIMPLE_DISTANCE_ALPHABET_SIZE == 140 */\n\nstatic BROTLI_INLINE uint32_t BlockLengthPrefixCode(uint32_t len) {\n  uint32_t code = (len >= 177) ? (len >= 753 ? 20 : 14) : (len >= 41 ? 7 : 0);\n  while (code < (BROTLI_NUM_BLOCK_LEN_SYMBOLS - 1) &&\n      len >= _kBrotliPrefixCodeRanges[code + 1].offset) ++code;\n  return code;\n}\n\nstatic BROTLI_INLINE void GetBlockLengthPrefixCode(uint32_t len, size_t* code,\n    uint32_t* n_extra, uint32_t* extra) {\n  *code = BlockLengthPrefixCode(len);\n  *n_extra = _kBrotliPrefixCodeRanges[*code].nbits;\n  *extra = len - _kBrotliPrefixCodeRanges[*code].offset;\n}\n\ntypedef struct BlockTypeCodeCalculator {\n  size_t last_type;\n  size_t second_last_type;\n} BlockTypeCodeCalculator;\n\nstatic void InitBlockTypeCodeCalculator(BlockTypeCodeCalculator* self) {\n  self->last_type = 1;\n  self->second_last_type = 0;\n}\n\nstatic BROTLI_INLINE size_t NextBlockTypeCode(\n    BlockTypeCodeCalculator* calculator, uint8_t type) {\n  size_t type_code = (type == calculator->last_type + 1) ? 1u :\n      (type == calculator->second_last_type) ? 0u : type + 2u;\n  calculator->second_last_type = calculator->last_type;\n  calculator->last_type = type;\n  return type_code;\n}\n\n/* |nibblesbits| represents the 2 bits to encode MNIBBLES (0-3)\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nstatic void BrotliEncodeMlen(size_t length, uint64_t* bits,\n                             size_t* numbits, uint64_t* nibblesbits) {\n  size_t lg = (length == 1) ? 1 : Log2FloorNonZero((uint32_t)(length - 1)) + 1;\n  size_t mnibbles = (lg < 16 ? 16 : (lg + 3)) / 4;\n  BROTLI_DCHECK(length > 0);\n  BROTLI_DCHECK(length <= (1 << 24));\n  BROTLI_DCHECK(lg <= 24);\n  *nibblesbits = mnibbles - 4;\n  *numbits = mnibbles * 4;\n  *bits = length - 1;\n}\n\nstatic BROTLI_INLINE void StoreCommandExtra(\n    const Command* cmd, size_t* storage_ix, uint8_t* storage) {\n  uint32_t copylen_code = CommandCopyLenCode(cmd);\n  uint16_t inscode = GetInsertLengthCode(cmd->insert_len_);\n  uint16_t copycode = GetCopyLengthCode(copylen_code);\n  uint32_t insnumextra = GetInsertExtra(inscode);\n  uint64_t insextraval = cmd->insert_len_ - GetInsertBase(inscode);\n  uint64_t copyextraval = copylen_code - GetCopyBase(copycode);\n  uint64_t bits = (copyextraval << insnumextra) | insextraval;\n  BrotliWriteBits(\n      insnumextra + GetCopyExtra(copycode), bits, storage_ix, storage);\n}\n\n/* Data structure that stores almost everything that is needed to encode each\n   block switch command. */\ntypedef struct BlockSplitCode {\n  BlockTypeCodeCalculator type_code_calculator;\n  uint8_t type_depths[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];\n  uint16_t type_bits[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];\n  uint8_t length_depths[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n  uint16_t length_bits[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n} BlockSplitCode;\n\n/* Stores a number between 0 and 255. */\nstatic void StoreVarLenUint8(size_t n, size_t* storage_ix, uint8_t* storage) {\n  if (n == 0) {\n    BrotliWriteBits(1, 0, storage_ix, storage);\n  } else {\n    size_t nbits = Log2FloorNonZero(n);\n    BrotliWriteBits(1, 1, storage_ix, storage);\n    BrotliWriteBits(3, nbits, storage_ix, storage);\n    BrotliWriteBits(nbits, n - ((size_t)1 << nbits), storage_ix, storage);\n  }\n}\n\n/* Stores the compressed meta-block header.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nstatic void StoreCompressedMetaBlockHeader(BROTLI_BOOL is_final_block,\n                                           size_t length,\n                                           size_t* storage_ix,\n                                           uint8_t* storage) {\n  uint64_t lenbits;\n  size_t nlenbits;\n  uint64_t nibblesbits;\n\n  /* Write ISLAST bit. */\n  BrotliWriteBits(1, (uint64_t)is_final_block, storage_ix, storage);\n  /* Write ISEMPTY bit. */\n  if (is_final_block) {\n    BrotliWriteBits(1, 0, storage_ix, storage);\n  }\n\n  BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits);\n  BrotliWriteBits(2, nibblesbits, storage_ix, storage);\n  BrotliWriteBits(nlenbits, lenbits, storage_ix, storage);\n\n  if (!is_final_block) {\n    /* Write ISUNCOMPRESSED bit. */\n    BrotliWriteBits(1, 0, storage_ix, storage);\n  }\n}\n\n/* Stores the uncompressed meta-block header.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nstatic void BrotliStoreUncompressedMetaBlockHeader(size_t length,\n                                                   size_t* storage_ix,\n                                                   uint8_t* storage) {\n  uint64_t lenbits;\n  size_t nlenbits;\n  uint64_t nibblesbits;\n\n  /* Write ISLAST bit.\n     Uncompressed block cannot be the last one, so set to 0. */\n  BrotliWriteBits(1, 0, storage_ix, storage);\n  BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits);\n  BrotliWriteBits(2, nibblesbits, storage_ix, storage);\n  BrotliWriteBits(nlenbits, lenbits, storage_ix, storage);\n  /* Write ISUNCOMPRESSED bit. */\n  BrotliWriteBits(1, 1, storage_ix, storage);\n}\n\nstatic void BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(\n    const int num_codes, const uint8_t* code_length_bitdepth,\n    size_t* storage_ix, uint8_t* storage) {\n  static const BROTLI_MODEL(\"small\")\n  uint8_t kStorageOrder[BROTLI_CODE_LENGTH_CODES] = {\n    1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15\n  };\n  /* The bit lengths of the Huffman code over the code length alphabet\n     are compressed with the following static Huffman code:\n       Symbol   Code\n       ------   ----\n       0          00\n       1        1110\n       2         110\n       3          01\n       4          10\n       5        1111 */\n  static const BROTLI_MODEL(\"small\")\n  uint8_t kHuffmanBitLengthHuffmanCodeSymbols[6] = {\n     0, 7, 3, 2, 1, 15\n  };\n  static const BROTLI_MODEL(\"small\")\n  uint8_t kHuffmanBitLengthHuffmanCodeBitLengths[6] = {\n    2, 4, 3, 2, 2, 4\n  };\n\n  size_t skip_some = 0;  /* skips none. */\n\n  /* Throw away trailing zeros: */\n  size_t codes_to_store = BROTLI_CODE_LENGTH_CODES;\n  if (num_codes > 1) {\n    for (; codes_to_store > 0; --codes_to_store) {\n      if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {\n        break;\n      }\n    }\n  }\n  if (code_length_bitdepth[kStorageOrder[0]] == 0 &&\n      code_length_bitdepth[kStorageOrder[1]] == 0) {\n    skip_some = 2;  /* skips two. */\n    if (code_length_bitdepth[kStorageOrder[2]] == 0) {\n      skip_some = 3;  /* skips three. */\n    }\n  }\n  BrotliWriteBits(2, skip_some, storage_ix, storage);\n  {\n    size_t i;\n    for (i = skip_some; i < codes_to_store; ++i) {\n      size_t l = code_length_bitdepth[kStorageOrder[i]];\n      BrotliWriteBits(kHuffmanBitLengthHuffmanCodeBitLengths[l],\n          kHuffmanBitLengthHuffmanCodeSymbols[l], storage_ix, storage);\n    }\n  }\n}\n\nstatic void BrotliStoreHuffmanTreeToBitMask(\n    const size_t huffman_tree_size, const uint8_t* huffman_tree,\n    const uint8_t* huffman_tree_extra_bits, const uint8_t* code_length_bitdepth,\n    const uint16_t* code_length_bitdepth_symbols,\n    size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage) {\n  size_t i;\n  for (i = 0; i < huffman_tree_size; ++i) {\n    size_t ix = huffman_tree[i];\n    BrotliWriteBits(code_length_bitdepth[ix], code_length_bitdepth_symbols[ix],\n                    storage_ix, storage);\n    /* Extra bits */\n    switch (ix) {\n      case BROTLI_REPEAT_PREVIOUS_CODE_LENGTH:\n        BrotliWriteBits(2, huffman_tree_extra_bits[i], storage_ix, storage);\n        break;\n      case BROTLI_REPEAT_ZERO_CODE_LENGTH:\n        BrotliWriteBits(3, huffman_tree_extra_bits[i], storage_ix, storage);\n        break;\n    }\n  }\n}\n\nstatic void StoreSimpleHuffmanTree(const uint8_t* depths,\n                                   size_t symbols[4],\n                                   size_t num_symbols,\n                                   size_t max_bits,\n                                   size_t* storage_ix, uint8_t* storage) {\n  /* value of 1 indicates a simple Huffman code */\n  BrotliWriteBits(2, 1, storage_ix, storage);\n  BrotliWriteBits(2, num_symbols - 1, storage_ix, storage);  /* NSYM - 1 */\n\n  {\n    /* Sort */\n    size_t i;\n    for (i = 0; i < num_symbols; i++) {\n      size_t j;\n      for (j = i + 1; j < num_symbols; j++) {\n        if (depths[symbols[j]] < depths[symbols[i]]) {\n          BROTLI_SWAP(size_t, symbols, j, i);\n        }\n      }\n    }\n  }\n\n  if (num_symbols == 2) {\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n  } else if (num_symbols == 3) {\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n  } else {\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[3], storage_ix, storage);\n    /* tree-select */\n    BrotliWriteBits(1, depths[symbols[0]] == 1 ? 1 : 0, storage_ix, storage);\n  }\n}\n\n/* num = alphabet size\n   depths = symbol depths */\nvoid BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,\n                            HuffmanTree* tree,\n                            size_t* storage_ix, uint8_t* storage) {\n  /* Write the Huffman tree into the brotli-representation.\n     The command alphabet is the largest, so this allocation will fit all\n     alphabets. */\n  /* TODO(eustas): fix me */\n  uint8_t huffman_tree[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint8_t huffman_tree_extra_bits[BROTLI_NUM_COMMAND_SYMBOLS];\n  size_t huffman_tree_size = 0;\n  uint8_t code_length_bitdepth[BROTLI_CODE_LENGTH_CODES] = { 0 };\n  uint16_t code_length_bitdepth_symbols[BROTLI_CODE_LENGTH_CODES];\n  uint32_t huffman_tree_histogram[BROTLI_CODE_LENGTH_CODES] = { 0 };\n  size_t i;\n  int num_codes = 0;\n  size_t code = 0;\n\n  BROTLI_DCHECK(num <= BROTLI_NUM_COMMAND_SYMBOLS);\n\n  BrotliWriteHuffmanTree(depths, num, &huffman_tree_size, huffman_tree,\n                         huffman_tree_extra_bits);\n\n  /* Calculate the statistics of the Huffman tree in brotli-representation. */\n  for (i = 0; i < huffman_tree_size; ++i) {\n    ++huffman_tree_histogram[huffman_tree[i]];\n  }\n\n  for (i = 0; i < BROTLI_CODE_LENGTH_CODES; ++i) {\n    if (huffman_tree_histogram[i]) {\n      if (num_codes == 0) {\n        code = i;\n        num_codes = 1;\n      } else if (num_codes == 1) {\n        num_codes = 2;\n        break;\n      }\n    }\n  }\n\n  /* Calculate another Huffman tree to use for compressing both the\n     earlier Huffman tree with. */\n  BrotliCreateHuffmanTree(huffman_tree_histogram, BROTLI_CODE_LENGTH_CODES,\n                          5, tree, code_length_bitdepth);\n  BrotliConvertBitDepthsToSymbols(code_length_bitdepth,\n                                  BROTLI_CODE_LENGTH_CODES,\n                                  code_length_bitdepth_symbols);\n\n  /* Now, we have all the data, let's start storing it */\n  BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth,\n                                               storage_ix, storage);\n\n  if (num_codes == 1) {\n    code_length_bitdepth[code] = 0;\n  }\n\n  /* Store the real Huffman tree now. */\n  BrotliStoreHuffmanTreeToBitMask(huffman_tree_size,\n                                  huffman_tree,\n                                  huffman_tree_extra_bits,\n                                  code_length_bitdepth,\n                                  code_length_bitdepth_symbols,\n                                  storage_ix, storage);\n}\n\n/* Builds a Huffman tree from histogram[0:length] into depth[0:length] and\n   bits[0:length] and stores the encoded tree to the bit stream. */\nstatic void BuildAndStoreHuffmanTree(const uint32_t* histogram,\n                                     const size_t histogram_length,\n                                     const size_t alphabet_size,\n                                     HuffmanTree* tree,\n                                     uint8_t* depth,\n                                     uint16_t* bits,\n                                     size_t* storage_ix,\n                                     uint8_t* storage) {\n  size_t count = 0;\n  size_t s4[4] = { 0 };\n  size_t i;\n  size_t max_bits = 0;\n  for (i = 0; i < histogram_length; i++) {\n    if (histogram[i]) {\n      if (count < 4) {\n        s4[count] = i;\n      } else if (count > 4) {\n        break;\n      }\n      count++;\n    }\n  }\n\n  {\n    size_t max_bits_counter = alphabet_size - 1;\n    while (max_bits_counter) {\n      max_bits_counter >>= 1;\n      ++max_bits;\n    }\n  }\n\n  if (count <= 1) {\n    BrotliWriteBits(4, 1, storage_ix, storage);\n    BrotliWriteBits(max_bits, s4[0], storage_ix, storage);\n    depth[s4[0]] = 0;\n    bits[s4[0]] = 0;\n    return;\n  }\n\n  memset(depth, 0, histogram_length * sizeof(depth[0]));\n  BrotliCreateHuffmanTree(histogram, histogram_length, 15, tree, depth);\n  BrotliConvertBitDepthsToSymbols(depth, histogram_length, bits);\n\n  if (count <= 4) {\n    StoreSimpleHuffmanTree(depth, s4, count, max_bits, storage_ix, storage);\n  } else {\n    BrotliStoreHuffmanTree(depth, histogram_length, tree, storage_ix, storage);\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(\n    const HuffmanTree* v0, const HuffmanTree* v1) {\n  return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);\n}\n\nvoid BrotliBuildAndStoreHuffmanTreeFast(HuffmanTree* tree,\n                                        const uint32_t* histogram,\n                                        const size_t histogram_total,\n                                        const size_t max_bits,\n                                        uint8_t* depth, uint16_t* bits,\n                                        size_t* storage_ix,\n                                        uint8_t* storage) {\n  size_t count = 0;\n  size_t symbols[4] = { 0 };\n  size_t length = 0;\n  size_t total = histogram_total;\n  while (total != 0) {\n    if (histogram[length]) {\n      if (count < 4) {\n        symbols[count] = length;\n      }\n      ++count;\n      total -= histogram[length];\n    }\n    ++length;\n  }\n\n  if (count <= 1) {\n    BrotliWriteBits(4, 1, storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    depth[symbols[0]] = 0;\n    bits[symbols[0]] = 0;\n    return;\n  }\n\n  memset(depth, 0, length * sizeof(depth[0]));\n  {\n    uint32_t count_limit;\n    for (count_limit = 1; ; count_limit *= 2) {\n      HuffmanTree* node = tree;\n      size_t l;\n      for (l = length; l != 0;) {\n        --l;\n        if (histogram[l]) {\n          if (BROTLI_PREDICT_TRUE(histogram[l] >= count_limit)) {\n            InitHuffmanTree(node, histogram[l], -1, (int16_t)l);\n          } else {\n            InitHuffmanTree(node, count_limit, -1, (int16_t)l);\n          }\n          ++node;\n        }\n      }\n      {\n        const int n = (int)(node - tree);\n        HuffmanTree sentinel;\n        int i = 0;      /* Points to the next leaf node. */\n        int j = n + 1;  /* Points to the next non-leaf node. */\n        int k;\n\n        SortHuffmanTreeItems(tree, (size_t)n, SortHuffmanTree);\n        /* The nodes are:\n           [0, n): the sorted leaf nodes that we start with.\n           [n]: we add a sentinel here.\n           [n + 1, 2n): new parent nodes are added here, starting from\n                        (n+1). These are naturally in ascending order.\n           [2n]: we add a sentinel at the end as well.\n           There will be (2n+1) elements at the end. */\n        InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1);\n        *node++ = sentinel;\n        *node++ = sentinel;\n\n        for (k = n - 1; k > 0; --k) {\n          int left, right;\n          if (tree[i].total_count_ <= tree[j].total_count_) {\n            left = i;\n            ++i;\n          } else {\n            left = j;\n            ++j;\n          }\n          if (tree[i].total_count_ <= tree[j].total_count_) {\n            right = i;\n            ++i;\n          } else {\n            right = j;\n            ++j;\n          }\n          /* The sentinel node becomes the parent node. */\n          node[-1].total_count_ =\n              tree[left].total_count_ + tree[right].total_count_;\n          node[-1].index_left_ = (int16_t)left;\n          node[-1].index_right_or_value_ = (int16_t)right;\n          /* Add back the last sentinel node. */\n          *node++ = sentinel;\n        }\n        if (BrotliSetDepth(2 * n - 1, tree, depth, 14)) {\n          /* We need to pack the Huffman tree in 14 bits. If this was not\n             successful, add fake entities to the lowest values and retry. */\n          break;\n        }\n      }\n    }\n  }\n  BrotliConvertBitDepthsToSymbols(depth, length, bits);\n  if (count <= 4) {\n    size_t i;\n    /* value of 1 indicates a simple Huffman code */\n    BrotliWriteBits(2, 1, storage_ix, storage);\n    BrotliWriteBits(2, count - 1, storage_ix, storage);  /* NSYM - 1 */\n\n    /* Sort */\n    for (i = 0; i < count; i++) {\n      size_t j;\n      for (j = i + 1; j < count; j++) {\n        if (depth[symbols[j]] < depth[symbols[i]]) {\n          BROTLI_SWAP(size_t, symbols, j, i);\n        }\n      }\n    }\n\n    if (count == 2) {\n      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n    } else if (count == 3) {\n      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n    } else {\n      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[3], storage_ix, storage);\n      /* tree-select */\n      BrotliWriteBits(1, depth[symbols[0]] == 1 ? 1 : 0, storage_ix, storage);\n    }\n  } else {\n    uint8_t previous_value = 8;\n    size_t i;\n    /* Complex Huffman Tree */\n    StoreStaticCodeLengthCode(storage_ix, storage);\n\n    /* Actual RLE coding. */\n    for (i = 0; i < length;) {\n      const uint8_t value = depth[i];\n      size_t reps = 1;\n      size_t k;\n      for (k = i + 1; k < length && depth[k] == value; ++k) {\n        ++reps;\n      }\n      i += reps;\n      if (value == 0) {\n        BrotliWriteBits(kZeroRepsDepth[reps], kZeroRepsBits[reps],\n                        storage_ix, storage);\n      } else {\n        if (previous_value != value) {\n          BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value],\n                          storage_ix, storage);\n          --reps;\n        }\n        if (reps < 3) {\n          while (reps != 0) {\n            reps--;\n            BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value],\n                            storage_ix, storage);\n          }\n        } else {\n          reps -= 3;\n          BrotliWriteBits(kNonZeroRepsDepth[reps], kNonZeroRepsBits[reps],\n                          storage_ix, storage);\n        }\n        previous_value = value;\n      }\n    }\n  }\n}\n\nstatic size_t IndexOf(const uint8_t* v, size_t v_size, uint8_t value) {\n  size_t i = 0;\n  for (; i < v_size; ++i) {\n    if (v[i] == value) return i;\n  }\n  return i;\n}\n\nstatic void MoveToFront(uint8_t* v, size_t index) {\n  uint8_t value = v[index];\n  size_t i;\n  for (i = index; i != 0; --i) {\n    v[i] = v[i - 1];\n  }\n  v[0] = value;\n}\n\nstatic void MoveToFrontTransform(const uint32_t* BROTLI_RESTRICT v_in,\n                                 const size_t v_size,\n                                 uint32_t* v_out) {\n  size_t i;\n  uint8_t mtf[256];\n  uint32_t max_value;\n  if (v_size == 0) {\n    return;\n  }\n  max_value = v_in[0];\n  for (i = 1; i < v_size; ++i) {\n    if (v_in[i] > max_value) max_value = v_in[i];\n  }\n  BROTLI_DCHECK(max_value < 256u);\n  for (i = 0; i <= max_value; ++i) {\n    mtf[i] = (uint8_t)i;\n  }\n  {\n    size_t mtf_size = max_value + 1;\n    for (i = 0; i < v_size; ++i) {\n      size_t index = IndexOf(mtf, mtf_size, (uint8_t)v_in[i]);\n      BROTLI_DCHECK(index < mtf_size);\n      v_out[i] = (uint32_t)index;\n      MoveToFront(mtf, index);\n    }\n  }\n}\n\n/* Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of\n   the run length plus extra bits (lower 9 bits is the prefix code and the rest\n   are the extra bits). Non-zero values in v[] are shifted by\n   *max_length_prefix. Will not create prefix codes bigger than the initial\n   value of *max_run_length_prefix. The prefix code of run length L is simply\n   Log2Floor(L) and the number of extra bits is the same as the prefix code. */\nstatic void RunLengthCodeZeros(const size_t in_size,\n    uint32_t* BROTLI_RESTRICT v, size_t* BROTLI_RESTRICT out_size,\n    uint32_t* BROTLI_RESTRICT max_run_length_prefix) {\n  uint32_t max_reps = 0;\n  size_t i;\n  uint32_t max_prefix;\n  for (i = 0; i < in_size;) {\n    uint32_t reps = 0;\n    for (; i < in_size && v[i] != 0; ++i) ;\n    for (; i < in_size && v[i] == 0; ++i) {\n      ++reps;\n    }\n    max_reps = BROTLI_MAX(uint32_t, reps, max_reps);\n  }\n  max_prefix = max_reps > 0 ? Log2FloorNonZero(max_reps) : 0;\n  max_prefix = BROTLI_MIN(uint32_t, max_prefix, *max_run_length_prefix);\n  *max_run_length_prefix = max_prefix;\n  *out_size = 0;\n  for (i = 0; i < in_size;) {\n    BROTLI_DCHECK(*out_size <= i);\n    if (v[i] != 0) {\n      v[*out_size] = v[i] + *max_run_length_prefix;\n      ++i;\n      ++(*out_size);\n    } else {\n      uint32_t reps = 1;\n      size_t k;\n      for (k = i + 1; k < in_size && v[k] == 0; ++k) {\n        ++reps;\n      }\n      i += reps;\n      while (reps != 0) {\n        if (reps < (2u << max_prefix)) {\n          uint32_t run_length_prefix = Log2FloorNonZero(reps);\n          const uint32_t extra_bits = reps - (1u << run_length_prefix);\n          v[*out_size] = run_length_prefix + (extra_bits << 9);\n          ++(*out_size);\n          break;\n        } else {\n          const uint32_t extra_bits = (1u << max_prefix) - 1u;\n          v[*out_size] = max_prefix + (extra_bits << 9);\n          reps -= (2u << max_prefix) - 1u;\n          ++(*out_size);\n        }\n      }\n    }\n  }\n}\n\n#define SYMBOL_BITS 9\n\ntypedef struct EncodeContextMapArena {\n  uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];\n  uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];\n  uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];\n} EncodeContextMapArena;\n\nstatic void EncodeContextMap(MemoryManager* m,\n                             EncodeContextMapArena* arena,\n                             const uint32_t* context_map,\n                             size_t context_map_size,\n                             size_t num_clusters,\n                             HuffmanTree* tree,\n                             size_t* storage_ix, uint8_t* storage) {\n  size_t i;\n  uint32_t* rle_symbols;\n  uint32_t max_run_length_prefix = 6;\n  size_t num_rle_symbols = 0;\n  uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;\n  static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u;\n  uint8_t* BROTLI_RESTRICT const depths = arena->depths;\n  uint16_t* BROTLI_RESTRICT const bits = arena->bits;\n\n  StoreVarLenUint8(num_clusters - 1, storage_ix, storage);\n\n  if (num_clusters == 1) {\n    return;\n  }\n\n  rle_symbols = BROTLI_ALLOC(m, uint32_t, context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(rle_symbols)) return;\n  MoveToFrontTransform(context_map, context_map_size, rle_symbols);\n  RunLengthCodeZeros(context_map_size, rle_symbols,\n                     &num_rle_symbols, &max_run_length_prefix);\n  memset(histogram, 0, sizeof(arena->histogram));\n  for (i = 0; i < num_rle_symbols; ++i) {\n    ++histogram[rle_symbols[i] & kSymbolMask];\n  }\n  {\n    BROTLI_BOOL use_rle = TO_BROTLI_BOOL(max_run_length_prefix > 0);\n    BrotliWriteBits(1, (uint64_t)use_rle, storage_ix, storage);\n    if (use_rle) {\n      BrotliWriteBits(4, max_run_length_prefix - 1, storage_ix, storage);\n    }\n  }\n  BuildAndStoreHuffmanTree(histogram, num_clusters + max_run_length_prefix,\n                           num_clusters + max_run_length_prefix,\n                           tree, depths, bits, storage_ix, storage);\n  for (i = 0; i < num_rle_symbols; ++i) {\n    const uint32_t rle_symbol = rle_symbols[i] & kSymbolMask;\n    const uint32_t extra_bits_val = rle_symbols[i] >> SYMBOL_BITS;\n    BrotliWriteBits(depths[rle_symbol], bits[rle_symbol], storage_ix, storage);\n    if (rle_symbol > 0 && rle_symbol <= max_run_length_prefix) {\n      BrotliWriteBits(rle_symbol, extra_bits_val, storage_ix, storage);\n    }\n  }\n  BrotliWriteBits(1, 1, storage_ix, storage);  /* use move-to-front */\n  BROTLI_FREE(m, rle_symbols);\n}\n\n/* Stores the block switch command with index block_ix to the bit stream. */\nstatic BROTLI_INLINE void StoreBlockSwitch(BlockSplitCode* code,\n                                           const uint32_t block_len,\n                                           const uint8_t block_type,\n                                           BROTLI_BOOL is_first_block,\n                                           size_t* storage_ix,\n                                           uint8_t* storage) {\n  size_t typecode = NextBlockTypeCode(&code->type_code_calculator, block_type);\n  size_t lencode;\n  uint32_t len_nextra;\n  uint32_t len_extra;\n  if (!is_first_block) {\n    BrotliWriteBits(code->type_depths[typecode], code->type_bits[typecode],\n                    storage_ix, storage);\n  }\n  GetBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra);\n\n  BrotliWriteBits(code->length_depths[lencode], code->length_bits[lencode],\n                  storage_ix, storage);\n  BrotliWriteBits(len_nextra, len_extra, storage_ix, storage);\n}\n\n/* Builds a BlockSplitCode data structure from the block split given by the\n   vector of block types and block lengths and stores it to the bit stream. */\nstatic void BuildAndStoreBlockSplitCode(const uint8_t* types,\n                                        const uint32_t* lengths,\n                                        const size_t num_blocks,\n                                        const size_t num_types,\n                                        HuffmanTree* tree,\n                                        BlockSplitCode* code,\n                                        size_t* storage_ix,\n                                        uint8_t* storage) {\n  uint32_t type_histo[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];\n  uint32_t length_histo[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n  size_t i;\n  BlockTypeCodeCalculator type_code_calculator;\n  memset(type_histo, 0, (num_types + 2) * sizeof(type_histo[0]));\n  memset(length_histo, 0, sizeof(length_histo));\n  InitBlockTypeCodeCalculator(&type_code_calculator);\n  for (i = 0; i < num_blocks; ++i) {\n    size_t type_code = NextBlockTypeCode(&type_code_calculator, types[i]);\n    if (i != 0) ++type_histo[type_code];\n    ++length_histo[BlockLengthPrefixCode(lengths[i])];\n  }\n  StoreVarLenUint8(num_types - 1, storage_ix, storage);\n  if (num_types > 1) {  /* TODO(eustas): else? could StoreBlockSwitch occur? */\n    BuildAndStoreHuffmanTree(&type_histo[0], num_types + 2, num_types + 2, tree,\n                             &code->type_depths[0], &code->type_bits[0],\n                             storage_ix, storage);\n    BuildAndStoreHuffmanTree(&length_histo[0], BROTLI_NUM_BLOCK_LEN_SYMBOLS,\n                             BROTLI_NUM_BLOCK_LEN_SYMBOLS,\n                             tree, &code->length_depths[0],\n                             &code->length_bits[0], storage_ix, storage);\n    StoreBlockSwitch(code, lengths[0], types[0], 1, storage_ix, storage);\n  }\n}\n\n/* Stores a context map where the histogram type is always the block type. */\nstatic void StoreTrivialContextMap(EncodeContextMapArena* arena,\n                                   size_t num_types,\n                                   size_t context_bits,\n                                   HuffmanTree* tree,\n                                   size_t* storage_ix,\n                                   uint8_t* storage) {\n  StoreVarLenUint8(num_types - 1, storage_ix, storage);\n  if (num_types > 1) {\n    size_t repeat_code = context_bits - 1u;\n    size_t repeat_bits = (1u << repeat_code) - 1u;\n    size_t alphabet_size = num_types + repeat_code;\n    uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;\n    uint8_t* BROTLI_RESTRICT const depths = arena->depths;\n    uint16_t* BROTLI_RESTRICT const bits = arena->bits;\n    size_t i;\n    memset(histogram, 0, alphabet_size * sizeof(histogram[0]));\n    /* Write RLEMAX. */\n    BrotliWriteBits(1, 1, storage_ix, storage);\n    BrotliWriteBits(4, repeat_code - 1, storage_ix, storage);\n    histogram[repeat_code] = (uint32_t)num_types;\n    histogram[0] = 1;\n    for (i = context_bits; i < alphabet_size; ++i) {\n      histogram[i] = 1;\n    }\n    BuildAndStoreHuffmanTree(histogram, alphabet_size, alphabet_size,\n                             tree, depths, bits, storage_ix, storage);\n    for (i = 0; i < num_types; ++i) {\n      size_t code = (i == 0 ? 0 : i + context_bits - 1);\n      BrotliWriteBits(depths[code], bits[code], storage_ix, storage);\n      BrotliWriteBits(\n          depths[repeat_code], bits[repeat_code], storage_ix, storage);\n      BrotliWriteBits(repeat_code, repeat_bits, storage_ix, storage);\n    }\n    /* Write IMTF (inverse-move-to-front) bit. */\n    BrotliWriteBits(1, 1, storage_ix, storage);\n  }\n}\n\n/* Manages the encoding of one block category (literal, command or distance). */\ntypedef struct BlockEncoder {\n  size_t histogram_length_;\n  size_t num_block_types_;\n  const uint8_t* block_types_;  /* Not owned. */\n  const uint32_t* block_lengths_;  /* Not owned. */\n  size_t num_blocks_;\n  BlockSplitCode block_split_code_;\n  size_t block_ix_;\n  size_t block_len_;\n  size_t entropy_ix_;\n  uint8_t* depths_;\n  uint16_t* bits_;\n} BlockEncoder;\n\nstatic void InitBlockEncoder(BlockEncoder* self, size_t histogram_length,\n    size_t num_block_types, const uint8_t* block_types,\n    const uint32_t* block_lengths, const size_t num_blocks) {\n  self->histogram_length_ = histogram_length;\n  self->num_block_types_ = num_block_types;\n  self->block_types_ = block_types;\n  self->block_lengths_ = block_lengths;\n  self->num_blocks_ = num_blocks;\n  InitBlockTypeCodeCalculator(&self->block_split_code_.type_code_calculator);\n  self->block_ix_ = 0;\n  self->block_len_ = num_blocks == 0 ? 0 : block_lengths[0];\n  self->entropy_ix_ = 0;\n  self->depths_ = 0;\n  self->bits_ = 0;\n}\n\nstatic void CleanupBlockEncoder(MemoryManager* m, BlockEncoder* self) {\n  BROTLI_FREE(m, self->depths_);\n  BROTLI_FREE(m, self->bits_);\n}\n\n/* Creates entropy codes of block lengths and block types and stores them\n   to the bit stream. */\nstatic void BuildAndStoreBlockSwitchEntropyCodes(BlockEncoder* self,\n    HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) {\n  BuildAndStoreBlockSplitCode(self->block_types_, self->block_lengths_,\n      self->num_blocks_, self->num_block_types_, tree, &self->block_split_code_,\n      storage_ix, storage);\n}\n\n/* Stores the next symbol with the entropy code of the current block type.\n   Updates the block type and block length at block boundaries. */\nstatic void StoreSymbol(BlockEncoder* self, size_t symbol, size_t* storage_ix,\n    uint8_t* storage) {\n  if (self->block_len_ == 0) {\n    size_t block_ix = ++self->block_ix_;\n    uint32_t block_len = self->block_lengths_[block_ix];\n    uint8_t block_type = self->block_types_[block_ix];\n    self->block_len_ = block_len;\n    self->entropy_ix_ = block_type * self->histogram_length_;\n    StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0,\n        storage_ix, storage);\n  }\n  --self->block_len_;\n  {\n    size_t ix = self->entropy_ix_ + symbol;\n    BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage);\n  }\n}\n\n/* Stores the next symbol with the entropy code of the current block type and\n   context value.\n   Updates the block type and block length at block boundaries. */\nstatic void StoreSymbolWithContext(BlockEncoder* self, size_t symbol,\n    size_t context, const uint32_t* context_map, size_t* storage_ix,\n    uint8_t* storage, const size_t context_bits) {\n  if (self->block_len_ == 0) {\n    size_t block_ix = ++self->block_ix_;\n    uint32_t block_len = self->block_lengths_[block_ix];\n    uint8_t block_type = self->block_types_[block_ix];\n    self->block_len_ = block_len;\n    self->entropy_ix_ = (size_t)block_type << context_bits;\n    StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0,\n        storage_ix, storage);\n  }\n  --self->block_len_;\n  {\n    size_t histo_ix = context_map[self->entropy_ix_ + context];\n    size_t ix = histo_ix * self->histogram_length_ + symbol;\n    BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage);\n  }\n}\n\n#define FN(X) X ## Literal\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_encoder_inc.h\"\n#undef FN\n\n#define FN(X) X ## Command\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_encoder_inc.h\"\n#undef FN\n\n#define FN(X) X ## Distance\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_encoder_inc.h\"\n#undef FN\n\nstatic void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) {\n  *storage_ix = (*storage_ix + 7u) & ~7u;\n  storage[*storage_ix >> 3] = 0;\n}\n\ntypedef struct StoreMetablockArena {\n  BlockEncoder literal_enc;\n  BlockEncoder command_enc;\n  BlockEncoder distance_enc;\n  EncodeContextMapArena context_map_arena;\n} StoreMetablockArena;\n\nvoid BrotliStoreMetaBlock(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,\n    const BrotliEncoderParams* params, ContextType literal_context_mode,\n    const Command* commands, size_t n_commands, const MetaBlockSplit* mb,\n    size_t* storage_ix, uint8_t* storage) {\n\n  size_t pos = start_pos;\n  size_t i;\n  uint32_t num_distance_symbols = params->dist.alphabet_size_max;\n  uint32_t num_effective_distance_symbols = params->dist.alphabet_size_limit;\n  HuffmanTree* tree;\n  ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);\n  StoreMetablockArena* arena = NULL;\n  BlockEncoder* literal_enc = NULL;\n  BlockEncoder* command_enc = NULL;\n  BlockEncoder* distance_enc = NULL;\n  const BrotliDistanceParams* dist = &params->dist;\n  BROTLI_DCHECK(\n      num_effective_distance_symbols <= BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS);\n\n  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);\n\n  tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);\n  arena = BROTLI_ALLOC(m, StoreMetablockArena, 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree) || BROTLI_IS_NULL(arena)) return;\n  literal_enc = &arena->literal_enc;\n  command_enc = &arena->command_enc;\n  distance_enc = &arena->distance_enc;\n  InitBlockEncoder(literal_enc, BROTLI_NUM_LITERAL_SYMBOLS,\n      mb->literal_split.num_types, mb->literal_split.types,\n      mb->literal_split.lengths, mb->literal_split.num_blocks);\n  InitBlockEncoder(command_enc, BROTLI_NUM_COMMAND_SYMBOLS,\n      mb->command_split.num_types, mb->command_split.types,\n      mb->command_split.lengths, mb->command_split.num_blocks);\n  InitBlockEncoder(distance_enc, num_effective_distance_symbols,\n      mb->distance_split.num_types, mb->distance_split.types,\n      mb->distance_split.lengths, mb->distance_split.num_blocks);\n\n  BuildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, storage_ix, storage);\n  BuildAndStoreBlockSwitchEntropyCodes(command_enc, tree, storage_ix, storage);\n  BuildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, storage_ix, storage);\n\n  BrotliWriteBits(2, dist->distance_postfix_bits, storage_ix, storage);\n  BrotliWriteBits(\n      4, dist->num_direct_distance_codes >> dist->distance_postfix_bits,\n      storage_ix, storage);\n  for (i = 0; i < mb->literal_split.num_types; ++i) {\n    BrotliWriteBits(2, literal_context_mode, storage_ix, storage);\n  }\n\n  if (mb->literal_context_map_size == 0) {\n    StoreTrivialContextMap(\n        &arena->context_map_arena, mb->literal_histograms_size,\n        BROTLI_LITERAL_CONTEXT_BITS, tree, storage_ix, storage);\n  } else {\n    EncodeContextMap(m, &arena->context_map_arena,\n        mb->literal_context_map, mb->literal_context_map_size,\n        mb->literal_histograms_size, tree, storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n\n  if (mb->distance_context_map_size == 0) {\n    StoreTrivialContextMap(\n        &arena->context_map_arena, mb->distance_histograms_size,\n        BROTLI_DISTANCE_CONTEXT_BITS, tree, storage_ix, storage);\n  } else {\n    EncodeContextMap(m, &arena->context_map_arena,\n        mb->distance_context_map, mb->distance_context_map_size,\n        mb->distance_histograms_size, tree, storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n\n  BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms,\n      mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree,\n      storage_ix, storage);\n  if (BROTLI_IS_OOM(m)) return;\n  BuildAndStoreEntropyCodesCommand(m, command_enc, mb->command_histograms,\n      mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree,\n      storage_ix, storage);\n  if (BROTLI_IS_OOM(m)) return;\n  BuildAndStoreEntropyCodesDistance(m, distance_enc, mb->distance_histograms,\n      mb->distance_histograms_size, num_distance_symbols, tree,\n      storage_ix, storage);\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_FREE(m, tree);\n\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    size_t cmd_code = cmd.cmd_prefix_;\n    StoreSymbol(command_enc, cmd_code, storage_ix, storage);\n    StoreCommandExtra(&cmd, storage_ix, storage);\n    if (mb->literal_context_map_size == 0) {\n      size_t j;\n      for (j = cmd.insert_len_; j != 0; --j) {\n        StoreSymbol(literal_enc, input[pos & mask], storage_ix, storage);\n        ++pos;\n      }\n    } else {\n      size_t j;\n      for (j = cmd.insert_len_; j != 0; --j) {\n        size_t context =\n            BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);\n        uint8_t literal = input[pos & mask];\n        StoreSymbolWithContext(literal_enc, literal, context,\n            mb->literal_context_map, storage_ix, storage,\n            BROTLI_LITERAL_CONTEXT_BITS);\n        prev_byte2 = prev_byte;\n        prev_byte = literal;\n        ++pos;\n      }\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd)) {\n      prev_byte2 = input[(pos - 2) & mask];\n      prev_byte = input[(pos - 1) & mask];\n      if (cmd.cmd_prefix_ >= 128) {\n        size_t dist_code = cmd.dist_prefix_ & 0x3FF;\n        uint32_t distnumextra = cmd.dist_prefix_ >> 10;\n        uint64_t distextra = cmd.dist_extra_;\n        if (mb->distance_context_map_size == 0) {\n          StoreSymbol(distance_enc, dist_code, storage_ix, storage);\n        } else {\n          size_t context = CommandDistanceContext(&cmd);\n          StoreSymbolWithContext(distance_enc, dist_code, context,\n              mb->distance_context_map, storage_ix, storage,\n              BROTLI_DISTANCE_CONTEXT_BITS);\n        }\n        BrotliWriteBits(distnumextra, distextra, storage_ix, storage);\n      }\n    }\n  }\n  CleanupBlockEncoder(m, distance_enc);\n  CleanupBlockEncoder(m, command_enc);\n  CleanupBlockEncoder(m, literal_enc);\n  BROTLI_FREE(m, arena);\n  if (is_last) {\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\nstatic void BuildHistograms(const uint8_t* input,\n                            size_t start_pos,\n                            size_t mask,\n                            const Command* commands,\n                            size_t n_commands,\n                            HistogramLiteral* lit_histo,\n                            HistogramCommand* cmd_histo,\n                            HistogramDistance* dist_histo) {\n  size_t pos = start_pos;\n  size_t i;\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    size_t j;\n    HistogramAddCommand(cmd_histo, cmd.cmd_prefix_);\n    for (j = cmd.insert_len_; j != 0; --j) {\n      HistogramAddLiteral(lit_histo, input[pos & mask]);\n      ++pos;\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) {\n      HistogramAddDistance(dist_histo, cmd.dist_prefix_ & 0x3FF);\n    }\n  }\n}\n\nstatic void StoreDataWithHuffmanCodes(const uint8_t* input,\n                                      size_t start_pos,\n                                      size_t mask,\n                                      const Command* commands,\n                                      size_t n_commands,\n                                      const uint8_t* lit_depth,\n                                      const uint16_t* lit_bits,\n                                      const uint8_t* cmd_depth,\n                                      const uint16_t* cmd_bits,\n                                      const uint8_t* dist_depth,\n                                      const uint16_t* dist_bits,\n                                      size_t* storage_ix,\n                                      uint8_t* storage) {\n  size_t pos = start_pos;\n  size_t i;\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    const size_t cmd_code = cmd.cmd_prefix_;\n    size_t j;\n    BrotliWriteBits(\n        cmd_depth[cmd_code], cmd_bits[cmd_code], storage_ix, storage);\n    StoreCommandExtra(&cmd, storage_ix, storage);\n    for (j = cmd.insert_len_; j != 0; --j) {\n      const uint8_t literal = input[pos & mask];\n      BrotliWriteBits(\n          lit_depth[literal], lit_bits[literal], storage_ix, storage);\n      ++pos;\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) {\n      const size_t dist_code = cmd.dist_prefix_ & 0x3FF;\n      const uint32_t distnumextra = cmd.dist_prefix_ >> 10;\n      const uint32_t distextra = cmd.dist_extra_;\n      BrotliWriteBits(dist_depth[dist_code], dist_bits[dist_code],\n                      storage_ix, storage);\n      BrotliWriteBits(distnumextra, distextra, storage_ix, storage);\n    }\n  }\n}\n\n/* TODO(eustas): pull alloc/dealloc to caller? */\ntypedef struct MetablockArena {\n  HistogramLiteral lit_histo;\n  HistogramCommand cmd_histo;\n  HistogramDistance dist_histo;\n  /* TODO(eustas): merge bits and depth? */\n  uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];\n  uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];\n  uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];\n  uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];\n  HuffmanTree tree[MAX_HUFFMAN_TREE_SIZE];\n} MetablockArena;\n\nvoid BrotliStoreMetaBlockTrivial(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage) {\n  MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1);\n  uint32_t num_distance_symbols = params->dist.alphabet_size_max;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n\n  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);\n\n  HistogramClearLiteral(&arena->lit_histo);\n  HistogramClearCommand(&arena->cmd_histo);\n  HistogramClearDistance(&arena->dist_histo);\n\n  BuildHistograms(input, start_pos, mask, commands, n_commands,\n                  &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo);\n\n  BrotliWriteBits(13, 0, storage_ix, storage);\n\n  BuildAndStoreHuffmanTree(arena->lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS,\n                           BROTLI_NUM_LITERAL_SYMBOLS, arena->tree,\n                           arena->lit_depth, arena->lit_bits,\n                           storage_ix, storage);\n  BuildAndStoreHuffmanTree(arena->cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS,\n                           BROTLI_NUM_COMMAND_SYMBOLS, arena->tree,\n                           arena->cmd_depth, arena->cmd_bits,\n                           storage_ix, storage);\n  BuildAndStoreHuffmanTree(arena->dist_histo.data_,\n                           MAX_SIMPLE_DISTANCE_ALPHABET_SIZE,\n                           num_distance_symbols, arena->tree,\n                           arena->dist_depth, arena->dist_bits,\n                           storage_ix, storage);\n  StoreDataWithHuffmanCodes(input, start_pos, mask, commands,\n                            n_commands, arena->lit_depth, arena->lit_bits,\n                            arena->cmd_depth, arena->cmd_bits,\n                            arena->dist_depth, arena->dist_bits,\n                            storage_ix, storage);\n  BROTLI_FREE(m, arena);\n  if (is_last) {\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\nvoid BrotliStoreMetaBlockFast(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage) {\n  MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1);\n  uint32_t num_distance_symbols = params->dist.alphabet_size_max;\n  uint32_t distance_alphabet_bits =\n      Log2FloorNonZero(num_distance_symbols - 1) + 1;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n\n  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);\n\n  BrotliWriteBits(13, 0, storage_ix, storage);\n\n  if (n_commands <= 128) {\n    uint32_t histogram[BROTLI_NUM_LITERAL_SYMBOLS] = { 0 };\n    size_t pos = start_pos;\n    size_t num_literals = 0;\n    size_t i;\n    for (i = 0; i < n_commands; ++i) {\n      const Command cmd = commands[i];\n      size_t j;\n      for (j = cmd.insert_len_; j != 0; --j) {\n        ++histogram[input[pos & mask]];\n        ++pos;\n      }\n      num_literals += cmd.insert_len_;\n      pos += CommandCopyLen(&cmd);\n    }\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, histogram, num_literals,\n                                       /* max_bits = */ 8,\n                                       arena->lit_depth, arena->lit_bits,\n                                       storage_ix, storage);\n    StoreStaticCommandHuffmanTree(storage_ix, storage);\n    StoreStaticDistanceHuffmanTree(storage_ix, storage);\n    StoreDataWithHuffmanCodes(input, start_pos, mask, commands,\n                              n_commands, arena->lit_depth, arena->lit_bits,\n                              kStaticCommandCodeDepth,\n                              kStaticCommandCodeBits,\n                              kStaticDistanceCodeDepth,\n                              kStaticDistanceCodeBits,\n                              storage_ix, storage);\n  } else {\n    HistogramClearLiteral(&arena->lit_histo);\n    HistogramClearCommand(&arena->cmd_histo);\n    HistogramClearDistance(&arena->dist_histo);\n    BuildHistograms(input, start_pos, mask, commands, n_commands,\n                    &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo);\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->lit_histo.data_,\n                                       arena->lit_histo.total_count_,\n                                       /* max_bits = */ 8,\n                                       arena->lit_depth, arena->lit_bits,\n                                       storage_ix, storage);\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->cmd_histo.data_,\n                                       arena->cmd_histo.total_count_,\n                                       /* max_bits = */ 10,\n                                       arena->cmd_depth, arena->cmd_bits,\n                                       storage_ix, storage);\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->dist_histo.data_,\n                                       arena->dist_histo.total_count_,\n                                       /* max_bits = */\n                                       distance_alphabet_bits,\n                                       arena->dist_depth, arena->dist_bits,\n                                       storage_ix, storage);\n    StoreDataWithHuffmanCodes(input, start_pos, mask, commands,\n                              n_commands, arena->lit_depth, arena->lit_bits,\n                              arena->cmd_depth, arena->cmd_bits,\n                              arena->dist_depth, arena->dist_bits,\n                              storage_ix, storage);\n  }\n\n  BROTLI_FREE(m, arena);\n\n  if (is_last) {\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\n/* This is for storing uncompressed blocks (simple raw storage of\n   bytes-as-bytes). */\nvoid BrotliStoreUncompressedMetaBlock(BROTLI_BOOL is_final_block,\n                                      const uint8_t* BROTLI_RESTRICT input,\n                                      size_t position, size_t mask,\n                                      size_t len,\n                                      size_t* BROTLI_RESTRICT storage_ix,\n                                      uint8_t* BROTLI_RESTRICT storage) {\n  size_t masked_pos = position & mask;\n  BrotliStoreUncompressedMetaBlockHeader(len, storage_ix, storage);\n  JumpToByteBoundary(storage_ix, storage);\n\n  if (masked_pos + len > mask + 1) {\n    size_t len1 = mask + 1 - masked_pos;\n    memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len1);\n    *storage_ix += len1 << 3;\n    len -= len1;\n    masked_pos = 0;\n  }\n  memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len);\n  *storage_ix += len << 3;\n\n  /* We need to clear the next 4 bytes to continue to be\n     compatible with BrotliWriteBits. */\n  BrotliWriteBitsPrepareStorage(*storage_ix, storage);\n\n  /* Since the uncompressed block itself may not be the final block, add an\n     empty one after this. */\n  if (is_final_block) {\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\n#if defined(BROTLI_TEST)\nvoid BrotliGetBlockLengthPrefixCodeForTest(uint32_t len, size_t* code,\n                                           uint32_t* n_extra, uint32_t* extra);\nvoid BrotliGetBlockLengthPrefixCodeForTest(uint32_t len, size_t* code,\n                                           uint32_t* n_extra, uint32_t* extra) {\n  GetBlockLengthPrefixCode(len, code, n_extra, extra);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/brotli_bit_stream.h",
    "content": "﻿/* Copyright 2014 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions to convert brotli-related data structures into the\n   brotli bit stream. The functions here operate under\n   assumption that there is enough space in the storage, i.e., there are\n   no out-of-range checks anywhere.\n\n   These functions do bit addressing into a byte array. The byte array\n   is called \"storage\" and the index to the bit is called storage_ix\n   in function arguments. */\n\n#ifndef BROTLI_ENC_BROTLI_BIT_STREAM_H_\n#define BROTLI_ENC_BROTLI_BIT_STREAM_H_\n\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"entropy_encode.h\"\n#include \"memory.h\"\n#include \"metablock.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* All Store functions here will use a storage_ix, which is always the bit\n   position for the current storage. */\n\nBROTLI_INTERNAL void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,\n    HuffmanTree* tree, size_t* storage_ix, uint8_t* storage);\n\nBROTLI_INTERNAL void BrotliBuildAndStoreHuffmanTreeFast(\n    HuffmanTree* tree, const uint32_t* histogram, const size_t histogram_total,\n    const size_t max_bits, uint8_t* depth, uint16_t* bits, size_t* storage_ix,\n    uint8_t* storage);\n\n/* REQUIRES: length > 0 */\n/* REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreMetaBlock(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,\n    const BrotliEncoderParams* params, ContextType literal_context_mode,\n    const Command* commands, size_t n_commands, const MetaBlockSplit* mb,\n    size_t* storage_ix, uint8_t* storage);\n\n/* Stores the meta-block without doing any block splitting, just collects\n   one histogram per block category and uses that for entropy coding.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreMetaBlockTrivial(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage);\n\n/* Same as above, but uses static prefix codes for histograms with a only a few\n   symbols, and uses static code length prefix codes for all other histograms.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreMetaBlockFast(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage);\n\n/* This is for storing uncompressed blocks (simple raw storage of\n   bytes-as-bytes).\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock(\n    BROTLI_BOOL is_final_block, const uint8_t* BROTLI_RESTRICT input,\n    size_t position, size_t mask, size_t len,\n    size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BROTLI_BIT_STREAM_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/cluster.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions for clustering similar histograms together. */\n\n#include \"cluster.h\"\n\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"  /* BrotliPopulationCost */\n#include \"fast_log.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE BROTLI_BOOL HistogramPairIsLess(\n    const HistogramPair* p1, const HistogramPair* p2) {\n  if (p1->cost_diff != p2->cost_diff) {\n    return TO_BROTLI_BOOL(p1->cost_diff > p2->cost_diff);\n  }\n  return TO_BROTLI_BOOL((p1->idx2 - p1->idx1) > (p2->idx2 - p2->idx1));\n}\n\n/* Returns entropy reduction of the context map when we combine two clusters. */\nstatic BROTLI_INLINE double ClusterCostDiff(size_t size_a, size_t size_b) {\n  size_t size_c = size_a + size_b;\n  return (double)size_a * FastLog2(size_a) +\n    (double)size_b * FastLog2(size_b) -\n    (double)size_c * FastLog2(size_c);\n}\n\n#define CODE(X) X\n\n#define FN(X) X ## Literal\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#undef CODE\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/cluster.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions for clustering similar histograms together. */\n\n#ifndef BROTLI_ENC_CLUSTER_H_\n#define BROTLI_ENC_CLUSTER_H_\n\n#include \"../common/platform.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct HistogramPair {\n  uint32_t idx1;\n  uint32_t idx2;\n  double cost_combo;\n  double cost_diff;\n} HistogramPair;\n\n#define CODE(X) /* Declaration */;\n\n#define FN(X) X ## Literal\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#undef CODE\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_CLUSTER_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/cluster_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, CODE */\n\n#define HistogramType FN(Histogram)\n\n/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if\n   it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */\nBROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)(\n    const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size,\n    uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs,\n    size_t* num_pairs) CODE({\n  BROTLI_BOOL is_good_pair = BROTLI_FALSE;\n  HistogramPair p;\n  p.idx1 = p.idx2 = 0;\n  p.cost_diff = p.cost_combo = 0;\n  if (idx1 == idx2) {\n    return;\n  }\n  if (idx2 < idx1) {\n    uint32_t t = idx2;\n    idx2 = idx1;\n    idx1 = t;\n  }\n  p.idx1 = idx1;\n  p.idx2 = idx2;\n  p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]);\n  p.cost_diff -= out[idx1].bit_cost_;\n  p.cost_diff -= out[idx2].bit_cost_;\n\n  if (out[idx1].total_count_ == 0) {\n    p.cost_combo = out[idx2].bit_cost_;\n    is_good_pair = BROTLI_TRUE;\n  } else if (out[idx2].total_count_ == 0) {\n    p.cost_combo = out[idx1].bit_cost_;\n    is_good_pair = BROTLI_TRUE;\n  } else {\n    double threshold = *num_pairs == 0 ? 1e99 :\n        BROTLI_MAX(double, 0.0, pairs[0].cost_diff);\n    double cost_combo;\n    *tmp = out[idx1];\n    FN(HistogramAddHistogram)(tmp, &out[idx2]);\n    cost_combo = FN(BrotliPopulationCost)(tmp);\n    if (cost_combo < threshold - p.cost_diff) {\n      p.cost_combo = cost_combo;\n      is_good_pair = BROTLI_TRUE;\n    }\n  }\n  if (is_good_pair) {\n    p.cost_diff += p.cost_combo;\n    if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) {\n      /* Replace the top of the queue if needed. */\n      if (*num_pairs < max_num_pairs) {\n        pairs[*num_pairs] = pairs[0];\n        ++(*num_pairs);\n      }\n      pairs[0] = p;\n    } else if (*num_pairs < max_num_pairs) {\n      pairs[*num_pairs] = p;\n      ++(*num_pairs);\n    }\n  }\n})\n\nBROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out,\n                                                  HistogramType* tmp,\n                                                  uint32_t* cluster_size,\n                                                  uint32_t* symbols,\n                                                  uint32_t* clusters,\n                                                  HistogramPair* pairs,\n                                                  size_t num_clusters,\n                                                  size_t symbols_size,\n                                                  size_t max_clusters,\n                                                  size_t max_num_pairs) CODE({\n  double cost_diff_threshold = 0.0;\n  size_t min_cluster_size = 1;\n  size_t num_pairs = 0;\n\n  {\n    /* We maintain a vector of histogram pairs, with the property that the pair\n       with the maximum bit cost reduction is the first. */\n    size_t idx1;\n    for (idx1 = 0; idx1 < num_clusters; ++idx1) {\n      size_t idx2;\n      for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) {\n        FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1],\n            clusters[idx2], max_num_pairs, &pairs[0], &num_pairs);\n      }\n    }\n  }\n\n  while (num_clusters > min_cluster_size) {\n    uint32_t best_idx1;\n    uint32_t best_idx2;\n    size_t i;\n    if (pairs[0].cost_diff >= cost_diff_threshold) {\n      cost_diff_threshold = 1e99;\n      min_cluster_size = max_clusters;\n      continue;\n    }\n    /* Take the best pair from the top of heap. */\n    best_idx1 = pairs[0].idx1;\n    best_idx2 = pairs[0].idx2;\n    FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]);\n    out[best_idx1].bit_cost_ = pairs[0].cost_combo;\n    cluster_size[best_idx1] += cluster_size[best_idx2];\n    for (i = 0; i < symbols_size; ++i) {\n      if (symbols[i] == best_idx2) {\n        symbols[i] = best_idx1;\n      }\n    }\n    for (i = 0; i < num_clusters; ++i) {\n      if (clusters[i] == best_idx2) {\n        memmove(&clusters[i], &clusters[i + 1],\n                (num_clusters - i - 1) * sizeof(clusters[0]));\n        break;\n      }\n    }\n    --num_clusters;\n    {\n      /* Remove pairs intersecting the just combined best pair. */\n      size_t copy_to_idx = 0;\n      for (i = 0; i < num_pairs; ++i) {\n        HistogramPair* p = &pairs[i];\n        if (p->idx1 == best_idx1 || p->idx2 == best_idx1 ||\n            p->idx1 == best_idx2 || p->idx2 == best_idx2) {\n          /* Remove invalid pair from the queue. */\n          continue;\n        }\n        if (HistogramPairIsLess(&pairs[0], p)) {\n          /* Replace the top of the queue if needed. */\n          HistogramPair front = pairs[0];\n          pairs[0] = *p;\n          pairs[copy_to_idx] = front;\n        } else {\n          pairs[copy_to_idx] = *p;\n        }\n        ++copy_to_idx;\n      }\n      num_pairs = copy_to_idx;\n    }\n\n    /* Push new pairs formed with the combined histogram to the heap. */\n    for (i = 0; i < num_clusters; ++i) {\n      FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1,\n          clusters[i], max_num_pairs, &pairs[0], &num_pairs);\n    }\n  }\n  return num_clusters;\n})\n\n/* What is the bit cost of moving histogram from cur_symbol to candidate. */\nBROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)(\n    const HistogramType* histogram, const HistogramType* candidate,\n    HistogramType* tmp) CODE({\n  if (histogram->total_count_ == 0) {\n    return 0.0;\n  } else {\n    *tmp = *histogram;\n    FN(HistogramAddHistogram)(tmp, candidate);\n    return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_;\n  }\n})\n\n/* Find the best 'out' histogram for each of the 'in' histograms.\n   When called, clusters[0..num_clusters) contains the unique values from\n   symbols[0..in_size), but this property is not preserved in this function.\n   Note: we assume that out[]->bit_cost_ is already up-to-date. */\nBROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in,\n    size_t in_size, const uint32_t* clusters, size_t num_clusters,\n    HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({\n  size_t i;\n  for (i = 0; i < in_size; ++i) {\n    uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1];\n    double best_bits =\n        FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp);\n    size_t j;\n    for (j = 0; j < num_clusters; ++j) {\n      const double cur_bits =\n          FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp);\n      if (cur_bits < best_bits) {\n        best_bits = cur_bits;\n        best_out = clusters[j];\n      }\n    }\n    symbols[i] = best_out;\n  }\n\n  /* Recompute each out based on raw and symbols. */\n  for (i = 0; i < num_clusters; ++i) {\n    FN(HistogramClear)(&out[clusters[i]]);\n  }\n  for (i = 0; i < in_size; ++i) {\n    FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]);\n  }\n})\n\n/* Reorders elements of the out[0..length) array and changes values in\n   symbols[0..length) array in the following way:\n     * when called, symbols[] contains indexes into out[], and has N unique\n       values (possibly N < length)\n     * on return, symbols'[i] = f(symbols[i]) and\n                  out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length,\n       where f is a bijection between the range of symbols[] and [0..N), and\n       the first occurrences of values in symbols'[i] come in consecutive\n       increasing order.\n   Returns N, the number of unique values in symbols[]. */\nBROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m,\n    HistogramType* out, uint32_t* symbols, size_t length) CODE({\n  static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX;\n  uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length);\n  uint32_t next_index;\n  HistogramType* tmp;\n  size_t i;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0;\n  for (i = 0; i < length; ++i) {\n      new_index[i] = kInvalidIndex;\n  }\n  next_index = 0;\n  for (i = 0; i < length; ++i) {\n    if (new_index[symbols[i]] == kInvalidIndex) {\n      new_index[symbols[i]] = next_index;\n      ++next_index;\n    }\n  }\n  /* TODO(eustas): by using idea of \"cycle-sort\" we can avoid allocation of\n     tmp and reduce the number of copying by the factor of 2. */\n  tmp = BROTLI_ALLOC(m, HistogramType, next_index);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0;\n  next_index = 0;\n  for (i = 0; i < length; ++i) {\n    if (new_index[symbols[i]] == next_index) {\n      tmp[next_index] = out[symbols[i]];\n      ++next_index;\n    }\n    symbols[i] = new_index[symbols[i]];\n  }\n  BROTLI_FREE(m, new_index);\n  for (i = 0; i < next_index; ++i) {\n    out[i] = tmp[i];\n  }\n  BROTLI_FREE(m, tmp);\n  return next_index;\n})\n\nBROTLI_INTERNAL void FN(BrotliClusterHistograms)(\n    MemoryManager* m, const HistogramType* in, const size_t in_size,\n    size_t max_histograms, HistogramType* out, size_t* out_size,\n    uint32_t* histogram_symbols) CODE({\n  uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size);\n  uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size);\n  size_t num_clusters = 0;\n  const size_t max_input_histograms = 64;\n  size_t pairs_capacity = max_input_histograms * max_input_histograms / 2;\n  /* For the first pass of clustering, we allow all pairs. */\n  HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1);\n  /* TODO(eustas): move to \"persistent\" arena? */\n  HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1);\n  size_t i;\n\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) ||\n      BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) {\n    return;\n  }\n\n  for (i = 0; i < in_size; ++i) {\n    cluster_size[i] = 1;\n  }\n\n  for (i = 0; i < in_size; ++i) {\n    out[i] = in[i];\n    out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]);\n    histogram_symbols[i] = (uint32_t)i;\n  }\n\n  for (i = 0; i < in_size; i += max_input_histograms) {\n    size_t num_to_combine =\n        BROTLI_MIN(size_t, in_size - i, max_input_histograms);\n    size_t num_new_clusters;\n    size_t j;\n    for (j = 0; j < num_to_combine; ++j) {\n      clusters[num_clusters + j] = (uint32_t)(i + j);\n    }\n    num_new_clusters =\n        FN(BrotliHistogramCombine)(out, tmp, cluster_size,\n                                   &histogram_symbols[i],\n                                   &clusters[num_clusters], pairs,\n                                   num_to_combine, num_to_combine,\n                                   max_histograms, pairs_capacity);\n    num_clusters += num_new_clusters;\n  }\n\n  {\n    /* For the second pass, we limit the total number of histogram pairs.\n       After this limit is reached, we only keep searching for the best pair. */\n    size_t max_num_pairs = BROTLI_MIN(size_t,\n        64 * num_clusters, (num_clusters / 2) * num_clusters);\n    BROTLI_ENSURE_CAPACITY(\n        m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1);\n    if (BROTLI_IS_OOM(m)) return;\n\n    /* Collapse similar histograms. */\n    num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size,\n                                              histogram_symbols, clusters,\n                                              pairs, num_clusters, in_size,\n                                              max_histograms, max_num_pairs);\n  }\n  BROTLI_FREE(m, pairs);\n  BROTLI_FREE(m, cluster_size);\n  /* Find the optimal map from original histograms to the final ones. */\n  FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters,\n                           out, tmp, histogram_symbols);\n  BROTLI_FREE(m, tmp);\n  BROTLI_FREE(m, clusters);\n  /* Convert the context map to a canonical form. */\n  *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size);\n  if (BROTLI_IS_OOM(m)) return;\n})\n\n#undef HistogramType\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/command.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"command.h\"\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nconst uint32_t kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES] = {\n    0,  1,  2,  3,  4,   5,   6,   8,   10,   14,   18,   26,\n    34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594};\nconst uint32_t kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES] = {\n    0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24};\nconst uint32_t kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES] = {\n    2,  3,  4,  5,  6,  7,   8,   9,   10,  12,  14,   18,\n    22, 30, 38, 54, 70, 102, 134, 198, 326, 582, 1094, 2118};\nconst uint32_t kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES] = {\n    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24};\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/command.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* This class models a sequence of literals and a backward reference copy. */\n\n#ifndef BROTLI_ENC_COMMAND_H_\n#define BROTLI_ENC_COMMAND_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n#include \"params.h\"\n#include \"prefix.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\")\nuint32_t kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES];\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\")\nuint32_t kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES];\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\")\nuint32_t kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES];\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\")\nuint32_t kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES];\n\nstatic BROTLI_INLINE uint16_t GetInsertLengthCode(size_t insertlen) {\n  if (insertlen < 6) {\n    return (uint16_t)insertlen;\n  } else if (insertlen < 130) {\n    uint32_t nbits = Log2FloorNonZero(insertlen - 2) - 1u;\n    return (uint16_t)((nbits << 1) + ((insertlen - 2) >> nbits) + 2);\n  } else if (insertlen < 2114) {\n    return (uint16_t)(Log2FloorNonZero(insertlen - 66) + 10);\n  } else if (insertlen < 6210) {\n    return 21u;\n  } else if (insertlen < 22594) {\n    return 22u;\n  } else {\n    return 23u;\n  }\n}\n\nstatic BROTLI_INLINE uint16_t GetCopyLengthCode(size_t copylen) {\n  if (copylen < 10) {\n    return (uint16_t)(copylen - 2);\n  } else if (copylen < 134) {\n    uint32_t nbits = Log2FloorNonZero(copylen - 6) - 1u;\n    return (uint16_t)((nbits << 1) + ((copylen - 6) >> nbits) + 4);\n  } else if (copylen < 2118) {\n    return (uint16_t)(Log2FloorNonZero(copylen - 70) + 12);\n  } else {\n    return 23u;\n  }\n}\n\nstatic BROTLI_INLINE uint16_t CombineLengthCodes(\n    uint16_t inscode, uint16_t copycode, BROTLI_BOOL use_last_distance) {\n  uint16_t bits64 =\n      (uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3u));\n  if (use_last_distance && inscode < 8u && copycode < 16u) {\n    return (copycode < 8u) ? bits64 : (bits64 | 64u);\n  } else {\n    /* Specification: 5 Encoding of ... (last table) */\n    /* offset = 2 * index, where index is in range [0..8] */\n    uint32_t offset = 2u * ((copycode >> 3u) + 3u * (inscode >> 3u));\n    /* All values in specification are K * 64,\n       where   K = [2, 3, 6, 4, 5, 8, 7, 9, 10],\n           i + 1 = [1, 2, 3, 4, 5, 6, 7, 8,  9],\n       K - i - 1 = [1, 1, 3, 0, 0, 2, 0, 1,  2] = D.\n       All values in D require only 2 bits to encode.\n       Magic constant is shifted 6 bits left, to avoid final multiplication. */\n    offset = (offset << 5u) + 0x40u + ((0x520D40u >> offset) & 0xC0u);\n    return (uint16_t)(offset | bits64);\n  }\n}\n\nstatic BROTLI_INLINE void GetLengthCode(size_t insertlen, size_t copylen,\n                                        BROTLI_BOOL use_last_distance,\n                                        uint16_t* code) {\n  uint16_t inscode = GetInsertLengthCode(insertlen);\n  uint16_t copycode = GetCopyLengthCode(copylen);\n  *code = CombineLengthCodes(inscode, copycode, use_last_distance);\n}\n\nstatic BROTLI_INLINE uint32_t GetInsertBase(uint16_t inscode) {\n  return kBrotliInsBase[inscode];\n}\n\nstatic BROTLI_INLINE uint32_t GetInsertExtra(uint16_t inscode) {\n  return kBrotliInsExtra[inscode];\n}\n\nstatic BROTLI_INLINE uint32_t GetCopyBase(uint16_t copycode) {\n  return kBrotliCopyBase[copycode];\n}\n\nstatic BROTLI_INLINE uint32_t GetCopyExtra(uint16_t copycode) {\n  return kBrotliCopyExtra[copycode];\n}\n\ntypedef struct Command {\n  uint32_t insert_len_;\n  /* Stores copy_len in low 25 bits and copy_code - copy_len in high 7 bit. */\n  uint32_t copy_len_;\n  /* Stores distance extra bits. */\n  uint32_t dist_extra_;\n  uint16_t cmd_prefix_;\n  /* Stores distance code in low 10 bits\n     and number of extra bits in high 6 bits. */\n  uint16_t dist_prefix_;\n} Command;\n\n/* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */\nstatic BROTLI_INLINE void InitCommand(Command* self,\n    const BrotliDistanceParams* dist, size_t insertlen,\n    size_t copylen, int copylen_code_delta, size_t distance_code) {\n  /* Don't rely on signed int representation, use honest casts. */\n  uint32_t delta = (uint8_t)((int8_t)copylen_code_delta);\n  self->insert_len_ = (uint32_t)insertlen;\n  self->copy_len_ = (uint32_t)(copylen | (delta << 25));\n  /* The distance prefix and extra bits are stored in this Command as if\n     npostfix and ndirect were 0, they are only recomputed later after the\n     clustering if needed. */\n  PrefixEncodeCopyDistance(\n      distance_code, dist->num_direct_distance_codes,\n      dist->distance_postfix_bits, &self->dist_prefix_, &self->dist_extra_);\n  GetLengthCode(\n      insertlen, (size_t)((int)copylen + copylen_code_delta),\n      TO_BROTLI_BOOL((self->dist_prefix_ & 0x3FF) == 0), &self->cmd_prefix_);\n}\n\nstatic BROTLI_INLINE void InitInsertCommand(Command* self, size_t insertlen) {\n  self->insert_len_ = (uint32_t)insertlen;\n  self->copy_len_ = 4 << 25;\n  self->dist_extra_ = 0;\n  self->dist_prefix_ = BROTLI_NUM_DISTANCE_SHORT_CODES;\n  GetLengthCode(insertlen, 4, BROTLI_FALSE, &self->cmd_prefix_);\n}\n\nstatic BROTLI_INLINE uint32_t CommandRestoreDistanceCode(\n    const Command* self, const BrotliDistanceParams* dist) {\n  if ((self->dist_prefix_ & 0x3FFu) <\n      BROTLI_NUM_DISTANCE_SHORT_CODES + dist->num_direct_distance_codes) {\n    return self->dist_prefix_ & 0x3FFu;\n  } else {\n    uint32_t dcode = self->dist_prefix_ & 0x3FFu;\n    uint32_t nbits = self->dist_prefix_ >> 10;\n    uint32_t extra = self->dist_extra_;\n    uint32_t postfix_mask = (1U << dist->distance_postfix_bits) - 1U;\n    uint32_t hcode = (dcode - dist->num_direct_distance_codes -\n        BROTLI_NUM_DISTANCE_SHORT_CODES) >>\n        dist->distance_postfix_bits;\n    uint32_t lcode = (dcode - dist->num_direct_distance_codes -\n        BROTLI_NUM_DISTANCE_SHORT_CODES) & postfix_mask;\n    uint32_t offset = ((2U + (hcode & 1U)) << nbits) - 4U;\n    return ((offset + extra) << dist->distance_postfix_bits) + lcode +\n        dist->num_direct_distance_codes + BROTLI_NUM_DISTANCE_SHORT_CODES;\n  }\n}\n\nstatic BROTLI_INLINE uint32_t CommandDistanceContext(const Command* self) {\n  uint32_t r = self->cmd_prefix_ >> 6;\n  uint32_t c = self->cmd_prefix_ & 7;\n  if ((r == 0 || r == 2 || r == 4 || r == 7) && (c <= 2)) {\n    return c;\n  }\n  return 3;\n}\n\nstatic BROTLI_INLINE uint32_t CommandCopyLen(const Command* self) {\n  return self->copy_len_ & 0x1FFFFFF;\n}\n\nstatic BROTLI_INLINE uint32_t CommandCopyLenCode(const Command* self) {\n  uint32_t modifier = self->copy_len_ >> 25;\n  int32_t delta = (int8_t)((uint8_t)(modifier | ((modifier & 0x40) << 1)));\n  return (uint32_t)((int32_t)(self->copy_len_ & 0x1FFFFFF) + delta);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_COMMAND_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/compound_dictionary.c",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"compound_dictionary.h\"\n\n#include \"../common/platform.h\"\n#include <brotli/shared_dictionary.h>\n#include \"memory.h\"\n\nstatic PreparedDictionary* CreatePreparedDictionaryWithParams(MemoryManager* m,\n    const uint8_t* source, size_t source_size, uint32_t bucket_bits,\n    uint32_t slot_bits, uint32_t hash_bits, uint16_t bucket_limit) {\n  /* Step 1: create \"bloated\" hasher. */\n  uint32_t num_slots = 1u << slot_bits;\n  uint32_t num_buckets = 1u << bucket_bits;\n  uint32_t hash_shift = 64u - bucket_bits;\n  uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);\n  uint32_t slot_mask = num_slots - 1;\n  size_t alloc_size = (sizeof(uint32_t) << slot_bits) +\n      (sizeof(uint32_t) << slot_bits) +\n      (sizeof(uint16_t) << bucket_bits) +\n      (sizeof(uint32_t) << bucket_bits) +\n      (sizeof(uint32_t) * source_size);\n  uint8_t* flat = NULL;\n  PreparedDictionary* result = NULL;\n  uint16_t* num = NULL;\n  uint32_t* bucket_heads = NULL;\n  uint32_t* next_bucket = NULL;\n  uint32_t* slot_offsets = NULL;\n  uint16_t* heads = NULL;\n  uint32_t* items = NULL;\n  uint8_t** source_ref = NULL;\n  uint32_t i;\n  uint32_t* slot_size = NULL;\n  uint32_t* slot_limit = NULL;\n  uint32_t total_items = 0;\n  if (slot_bits > 16) return NULL;\n  if (slot_bits > bucket_bits) return NULL;\n  if (bucket_bits - slot_bits >= 16) return NULL;\n\n  flat = BROTLI_ALLOC(m, uint8_t, alloc_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(flat)) return NULL;\n\n  slot_size = (uint32_t*)flat;\n  slot_limit = (uint32_t*)(&slot_size[num_slots]);\n  num = (uint16_t*)(&slot_limit[num_slots]);\n  bucket_heads = (uint32_t*)(&num[num_buckets]);\n  next_bucket = (uint32_t*)(&bucket_heads[num_buckets]);\n  memset(num, 0, num_buckets * sizeof(num[0]));\n\n  /* TODO(eustas): apply custom \"store\" order. */\n  for (i = 0; i + 7 < source_size; ++i) {\n    const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(&source[i]) & hash_mask) *\n        kPreparedDictionaryHashMul64Long;\n    const uint32_t key = (uint32_t)(h >> hash_shift);\n    uint16_t count = num[key];\n    next_bucket[i] = (count == 0) ? ((uint32_t)(-1)) : bucket_heads[key];\n    bucket_heads[key] = i;\n    count++;\n    if (count > bucket_limit) count = bucket_limit;\n    num[key] = count;\n  }\n\n  /* Step 2: find slot limits. */\n  for (i = 0; i < num_slots; ++i) {\n    BROTLI_BOOL overflow = BROTLI_FALSE;\n    slot_limit[i] = bucket_limit;\n    while (BROTLI_TRUE) {\n      uint32_t limit = slot_limit[i];\n      size_t j;\n      uint32_t count = 0;\n      overflow = BROTLI_FALSE;\n      for (j = i; j < num_buckets; j += num_slots) {\n        uint32_t size = num[j];\n        /* Last chain may span behind 64K limit; overflow happens only if\n           we are about to use 0xFFFF+ as item offset. */\n        if (count >= 0xFFFF) {\n          overflow = BROTLI_TRUE;\n          break;\n        }\n        if (size > limit) size = limit;\n        count += size;\n      }\n      if (!overflow) {\n        slot_size[i] = count;\n        total_items += count;\n        break;\n      }\n      slot_limit[i]--;\n    }\n  }\n\n  /* Step 3: transfer data to \"slim\" hasher. */\n  alloc_size = sizeof(PreparedDictionary) + (sizeof(uint32_t) << slot_bits) +\n      (sizeof(uint16_t) << bucket_bits) + (sizeof(uint32_t) * total_items) +\n      sizeof(uint8_t*);\n\n  result = (PreparedDictionary*)BROTLI_ALLOC(m, uint8_t, alloc_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(result)) {\n    BROTLI_FREE(m, flat);\n    return NULL;\n  }\n  slot_offsets = (uint32_t*)(&result[1]);\n  heads = (uint16_t*)(&slot_offsets[num_slots]);\n  items = (uint32_t*)(&heads[num_buckets]);\n  source_ref = (uint8_t**)(&items[total_items]);\n\n  result->magic = kLeanPreparedDictionaryMagic;\n  result->num_items = total_items;\n  result->source_size = (uint32_t)source_size;\n  result->hash_bits = hash_bits;\n  result->bucket_bits = bucket_bits;\n  result->slot_bits = slot_bits;\n  BROTLI_UNALIGNED_STORE_PTR(source_ref, source);\n\n  total_items = 0;\n  for (i = 0; i < num_slots; ++i) {\n    slot_offsets[i] = total_items;\n    total_items += slot_size[i];\n    slot_size[i] = 0;\n  }\n  for (i = 0; i < num_buckets; ++i) {\n    uint32_t slot = i & slot_mask;\n    uint32_t count = num[i];\n    uint32_t pos;\n    size_t j;\n    size_t cursor = slot_size[slot];\n    if (count > slot_limit[slot]) count = slot_limit[slot];\n    if (count == 0) {\n      heads[i] = 0xFFFF;\n      continue;\n    }\n    heads[i] = (uint16_t)cursor;\n    cursor += slot_offsets[slot];\n    slot_size[slot] += count;\n    pos = bucket_heads[i];\n    for (j = 0; j < count; j++) {\n      items[cursor++] = pos;\n      pos = next_bucket[pos];\n    }\n    items[cursor - 1] |= 0x80000000;\n  }\n\n  BROTLI_FREE(m, flat);\n  return result;\n}\n\nPreparedDictionary* CreatePreparedDictionary(MemoryManager* m,\n    const uint8_t* source, size_t source_size) {\n  uint32_t bucket_bits = 17;\n  uint32_t slot_bits = 7;\n  uint32_t hash_bits = 40;\n  uint16_t bucket_limit = 32;\n  size_t volume = 16u << bucket_bits;\n  /* Tune parameters to fit dictionary size. */\n  while (volume < source_size && bucket_bits < 22) {\n    bucket_bits++;\n    slot_bits++;\n    volume <<= 1;\n  }\n  return CreatePreparedDictionaryWithParams(m,\n      source, source_size, bucket_bits, slot_bits, hash_bits, bucket_limit);\n}\n\nvoid DestroyPreparedDictionary(MemoryManager* m,\n    PreparedDictionary* dictionary) {\n  if (!dictionary) return;\n  BROTLI_FREE(m, dictionary);\n}\n\nBROTLI_BOOL AttachPreparedDictionary(\n    CompoundDictionary* compound, const PreparedDictionary* dictionary) {\n  size_t length = 0;\n  size_t index = 0;\n\n  if (compound->num_chunks == SHARED_BROTLI_MAX_COMPOUND_DICTS) {\n    return BROTLI_FALSE;\n  }\n\n  if (!dictionary) return BROTLI_FALSE;\n\n  length = dictionary->source_size;\n  index = compound->num_chunks;\n  compound->total_size += length;\n  compound->chunks[index] = dictionary;\n  compound->chunk_offsets[index + 1] = compound->total_size;\n  {\n    uint32_t* slot_offsets = (uint32_t*)(&dictionary[1]);\n    uint16_t* heads = (uint16_t*)(&slot_offsets[(size_t)1u << dictionary->slot_bits]);\n    uint32_t* items = (uint32_t*)(&heads[(size_t)1u << dictionary->bucket_bits]);\n    const void* tail = (void*)&items[dictionary->num_items];\n    if (dictionary->magic == kPreparedDictionaryMagic) {\n      compound->chunk_source[index] = (const uint8_t*)tail;\n    } else {\n      /* dictionary->magic == kLeanPreparedDictionaryMagic */\n      compound->chunk_source[index] =\n          (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);\n    }\n  }\n  compound->num_chunks++;\n  return BROTLI_TRUE;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/compound_dictionary.h",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#ifndef BROTLI_ENC_PREPARED_DICTIONARY_H_\n#define BROTLI_ENC_PREPARED_DICTIONARY_H_\n\n#include \"../common/platform.h\"\n#include <brotli/shared_dictionary.h>\n#include \"memory.h\"\n\n/* \"Fat\" prepared dictionary, could be cooked outside of C implementation,\n * e.g. on Java side. LZ77 data is copied inside PreparedDictionary struct. */\nstatic const uint32_t kPreparedDictionaryMagic = 0xDEBCEDE0;\n\nstatic const uint32_t kSharedDictionaryMagic = 0xDEBCEDE1;\n\nstatic const uint32_t kManagedDictionaryMagic = 0xDEBCEDE2;\n\n/* \"Lean\" prepared dictionary. LZ77 data is referenced. It is the responsibility\n * of caller of \"prepare dictionary\" to keep the LZ77 data while prepared\n * dictionary is in use. */\nstatic const uint32_t kLeanPreparedDictionaryMagic = 0xDEBCEDE3;\n\nstatic const uint64_t kPreparedDictionaryHashMul64Long =\n    BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);\n\ntypedef struct PreparedDictionary {\n  uint32_t magic;\n  uint32_t num_items;\n  uint32_t source_size;\n  uint32_t hash_bits;\n  uint32_t bucket_bits;\n  uint32_t slot_bits;\n\n  /* --- Dynamic size members --- */\n\n  /* uint32_t slot_offsets[1 << slot_bits]; */\n  /* uint16_t heads[1 << bucket_bits]; */\n  /* uint32_t items[variable]; */\n\n  /* [maybe] uint8_t* source_ref, depending on magic. */\n  /* [maybe] uint8_t source[source_size], depending on magic. */\n} PreparedDictionary;\n\nBROTLI_INTERNAL PreparedDictionary* CreatePreparedDictionary(MemoryManager* m,\n    const uint8_t* source, size_t source_size);\n\nBROTLI_INTERNAL void DestroyPreparedDictionary(MemoryManager* m,\n    PreparedDictionary* dictionary);\n\ntypedef struct CompoundDictionary {\n  /* LZ77 prefix, compound dictionary */\n  size_t num_chunks;\n  size_t total_size;\n  /* Client instances. */\n  const PreparedDictionary* chunks[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n  const uint8_t* chunk_source[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n  size_t chunk_offsets[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n\n  size_t num_prepared_instances_;\n  /* Owned instances. */\n  PreparedDictionary* prepared_instances_[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n} CompoundDictionary;\n\nBROTLI_INTERNAL BROTLI_BOOL AttachPreparedDictionary(\n    CompoundDictionary* compound, const PreparedDictionary* dictionary);\n\n#endif /* BROTLI_ENC_PREPARED_DICTIONARY */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/compress_fragment.c",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses one-pass processing: when we find a backward\n   match, we immediately emit the corresponding command and literal codes to\n   the bit stream.\n\n   Adapted from the CompressFragment() function in\n   https://github.com/google/snappy/blob/master/snappy.cc */\n\n#include \"compress_fragment.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"brotli_bit_stream.h\"\n#include \"entropy_encode.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"hash_base.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)\n\nstatic BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) {\n  const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << 24) * kHashMul32;\n  return (uint32_t)(h >> shift);\n}\n\nstatic BROTLI_INLINE uint32_t HashBytesAtOffset(\n    uint64_t v, int offset, size_t shift) {\n  BROTLI_DCHECK(offset >= 0);\n  BROTLI_DCHECK(offset <= 3);\n  {\n    const uint64_t h = ((v >> (8 * offset)) << 24) * kHashMul32;\n    return (uint32_t)(h >> shift);\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2) {\n  return TO_BROTLI_BOOL(\n      BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2) &&\n      p1[4] == p2[4]);\n}\n\n/* Builds a literal prefix code into \"depths\" and \"bits\" based on the statistics\n   of the \"input\" string and stores it into the bit stream.\n   Note that the prefix code here is built from the pre-LZ77 input, therefore\n   we can only approximate the statistics of the actual literal stream.\n   Moreover, for long inputs we build a histogram from a sample of the input\n   and thus have to assign a non-zero depth for each literal.\n   Returns estimated compression ratio millibytes/char for encoding given input\n   with generated code. */\nstatic size_t BuildAndStoreLiteralPrefixCode(BrotliOnePassArena* s,\n                                             const uint8_t* input,\n                                             const size_t input_size,\n                                             uint8_t depths[256],\n                                             uint16_t bits[256],\n                                             size_t* storage_ix,\n                                             uint8_t* storage) {\n  uint32_t* BROTLI_RESTRICT const histogram = s->histogram;\n  size_t histogram_total;\n  size_t i;\n  memset(histogram, 0, sizeof(s->histogram));\n\n  if (input_size < (1 << 15)) {\n    for (i = 0; i < input_size; ++i) {\n      ++histogram[input[i]];\n    }\n    histogram_total = input_size;\n    for (i = 0; i < 256; ++i) {\n      /* We weigh the first 11 samples with weight 3 to account for the\n         balancing effect of the LZ77 phase on the histogram. */\n      const uint32_t adjust = 2 * BROTLI_MIN(uint32_t, histogram[i], 11u);\n      histogram[i] += adjust;\n      histogram_total += adjust;\n    }\n  } else {\n    static const size_t kSampleRate = 29;\n    for (i = 0; i < input_size; i += kSampleRate) {\n      ++histogram[input[i]];\n    }\n    histogram_total = (input_size + kSampleRate - 1) / kSampleRate;\n    for (i = 0; i < 256; ++i) {\n      /* We add 1 to each population count to avoid 0 bit depths (since this is\n         only a sample and we don't know if the symbol appears or not), and we\n         weigh the first 11 samples with weight 3 to account for the balancing\n         effect of the LZ77 phase on the histogram (more frequent symbols are\n         more likely to be in backward references instead as literals). */\n      const uint32_t adjust = 1 + 2 * BROTLI_MIN(uint32_t, histogram[i], 11u);\n      histogram[i] += adjust;\n      histogram_total += adjust;\n    }\n  }\n  BrotliBuildAndStoreHuffmanTreeFast(s->tree, histogram, histogram_total,\n                                     /* max_bits = */ 8,\n                                     depths, bits, storage_ix, storage);\n  {\n    size_t literal_ratio = 0;\n    for (i = 0; i < 256; ++i) {\n      if (histogram[i]) literal_ratio += histogram[i] * depths[i];\n    }\n    /* Estimated encoding ratio, millibytes per symbol. */\n    return (literal_ratio * 125) / histogram_total;\n  }\n}\n\n/* Builds a command and distance prefix code (each 64 symbols) into \"depth\" and\n   \"bits\" based on \"histogram\" and stores it into the bit stream. */\nstatic void BuildAndStoreCommandPrefixCode(BrotliOnePassArena* s,\n    size_t* storage_ix, uint8_t* storage) {\n  const uint32_t* const histogram = s->cmd_histo;\n  uint8_t* const depth = s->cmd_depth;\n  uint16_t* const bits = s->cmd_bits;\n  uint8_t* BROTLI_RESTRICT const tmp_depth = s->tmp_depth;\n  uint16_t* BROTLI_RESTRICT const tmp_bits = s->tmp_bits;\n  /* TODO(eustas): do only once on initialization. */\n  memset(tmp_depth, 0, BROTLI_NUM_COMMAND_SYMBOLS);\n\n  BrotliCreateHuffmanTree(histogram, 64, 15, s->tree, depth);\n  BrotliCreateHuffmanTree(&histogram[64], 64, 14, s->tree, &depth[64]);\n  /* We have to jump through a few hoops here in order to compute\n     the command bits because the symbols are in a different order than in\n     the full alphabet. This looks complicated, but having the symbols\n     in this order in the command bits saves a few branches in the Emit*\n     functions. */\n  memcpy(tmp_depth, depth, 24);\n  memcpy(tmp_depth + 24, depth + 40, 8);\n  memcpy(tmp_depth + 32, depth + 24, 8);\n  memcpy(tmp_depth + 40, depth + 48, 8);\n  memcpy(tmp_depth + 48, depth + 32, 8);\n  memcpy(tmp_depth + 56, depth + 56, 8);\n  BrotliConvertBitDepthsToSymbols(tmp_depth, 64, tmp_bits);\n  memcpy(bits, tmp_bits, 48);\n  memcpy(bits + 24, tmp_bits + 32, 16);\n  memcpy(bits + 32, tmp_bits + 48, 16);\n  memcpy(bits + 40, tmp_bits + 24, 16);\n  memcpy(bits + 48, tmp_bits + 40, 16);\n  memcpy(bits + 56, tmp_bits + 56, 16);\n  BrotliConvertBitDepthsToSymbols(&depth[64], 64, &bits[64]);\n  {\n    /* Create the bit length array for the full command alphabet. */\n    size_t i;\n    memset(tmp_depth, 0, 64);  /* only 64 first values were used */\n    memcpy(tmp_depth, depth, 8);\n    memcpy(tmp_depth + 64, depth + 8, 8);\n    memcpy(tmp_depth + 128, depth + 16, 8);\n    memcpy(tmp_depth + 192, depth + 24, 8);\n    memcpy(tmp_depth + 384, depth + 32, 8);\n    for (i = 0; i < 8; ++i) {\n      tmp_depth[128 + 8 * i] = depth[40 + i];\n      tmp_depth[256 + 8 * i] = depth[48 + i];\n      tmp_depth[448 + 8 * i] = depth[56 + i];\n    }\n    /* TODO(eustas): could/should full-length machinery be avoided? */\n    BrotliStoreHuffmanTree(\n        tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS, s->tree, storage_ix, storage);\n  }\n  BrotliStoreHuffmanTree(&depth[64], 64, s->tree, storage_ix, storage);\n}\n\n/* REQUIRES: insertlen < 6210 */\nstatic BROTLI_INLINE void EmitInsertLen(size_t insertlen,\n                                        const uint8_t depth[128],\n                                        const uint16_t bits[128],\n                                        uint32_t histo[128],\n                                        size_t* storage_ix,\n                                        uint8_t* storage) {\n  if (insertlen < 6) {\n    const size_t code = insertlen + 40;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    ++histo[code];\n  } else if (insertlen < 130) {\n    const size_t tail = insertlen - 2;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1u;\n    const size_t prefix = tail >> nbits;\n    const size_t inscode = (nbits << 1) + prefix + 42;\n    BrotliWriteBits(depth[inscode], bits[inscode], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage);\n    ++histo[inscode];\n  } else if (insertlen < 2114) {\n    const size_t tail = insertlen - 66;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 50;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage);\n    ++histo[code];\n  } else {\n    BrotliWriteBits(depth[61], bits[61], storage_ix, storage);\n    BrotliWriteBits(12, insertlen - 2114, storage_ix, storage);\n    ++histo[61];\n  }\n}\n\nstatic BROTLI_INLINE void EmitLongInsertLen(size_t insertlen,\n                                            const uint8_t depth[128],\n                                            const uint16_t bits[128],\n                                            uint32_t histo[128],\n                                            size_t* storage_ix,\n                                            uint8_t* storage) {\n  if (insertlen < 22594) {\n    BrotliWriteBits(depth[62], bits[62], storage_ix, storage);\n    BrotliWriteBits(14, insertlen - 6210, storage_ix, storage);\n    ++histo[62];\n  } else {\n    BrotliWriteBits(depth[63], bits[63], storage_ix, storage);\n    BrotliWriteBits(24, insertlen - 22594, storage_ix, storage);\n    ++histo[63];\n  }\n}\n\nstatic BROTLI_INLINE void EmitCopyLen(size_t copylen,\n                                      const uint8_t depth[128],\n                                      const uint16_t bits[128],\n                                      uint32_t histo[128],\n                                      size_t* storage_ix,\n                                      uint8_t* storage) {\n  if (copylen < 10) {\n    BrotliWriteBits(\n        depth[copylen + 14], bits[copylen + 14], storage_ix, storage);\n    ++histo[copylen + 14];\n  } else if (copylen < 134) {\n    const size_t tail = copylen - 6;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1u;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 20;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage);\n    ++histo[code];\n  } else if (copylen < 2118) {\n    const size_t tail = copylen - 70;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 28;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage);\n    ++histo[code];\n  } else {\n    BrotliWriteBits(depth[39], bits[39], storage_ix, storage);\n    BrotliWriteBits(24, copylen - 2118, storage_ix, storage);\n    ++histo[39];\n  }\n}\n\nstatic BROTLI_INLINE void EmitCopyLenLastDistance(size_t copylen,\n                                                  const uint8_t depth[128],\n                                                  const uint16_t bits[128],\n                                                  uint32_t histo[128],\n                                                  size_t* storage_ix,\n                                                  uint8_t* storage) {\n  if (copylen < 12) {\n    BrotliWriteBits(depth[copylen - 4], bits[copylen - 4], storage_ix, storage);\n    ++histo[copylen - 4];\n  } else if (copylen < 72) {\n    const size_t tail = copylen - 8;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 4;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage);\n    ++histo[code];\n  } else if (copylen < 136) {\n    const size_t tail = copylen - 8;\n    const size_t code = (tail >> 5) + 30;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(5, tail & 31, storage_ix, storage);\n    BrotliWriteBits(depth[64], bits[64], storage_ix, storage);\n    ++histo[code];\n    ++histo[64];\n  } else if (copylen < 2120) {\n    const size_t tail = copylen - 72;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 28;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage);\n    BrotliWriteBits(depth[64], bits[64], storage_ix, storage);\n    ++histo[code];\n    ++histo[64];\n  } else {\n    BrotliWriteBits(depth[39], bits[39], storage_ix, storage);\n    BrotliWriteBits(24, copylen - 2120, storage_ix, storage);\n    BrotliWriteBits(depth[64], bits[64], storage_ix, storage);\n    ++histo[39];\n    ++histo[64];\n  }\n}\n\nstatic BROTLI_INLINE void EmitDistance(size_t distance,\n                                       const uint8_t depth[128],\n                                       const uint16_t bits[128],\n                                       uint32_t histo[128],\n                                       size_t* storage_ix, uint8_t* storage) {\n  const size_t d = distance + 3;\n  const uint32_t nbits = Log2FloorNonZero(d) - 1u;\n  const size_t prefix = (d >> nbits) & 1;\n  const size_t offset = (2 + prefix) << nbits;\n  const size_t distcode = 2 * (nbits - 1) + prefix + 80;\n  BrotliWriteBits(depth[distcode], bits[distcode], storage_ix, storage);\n  BrotliWriteBits(nbits, d - offset, storage_ix, storage);\n  ++histo[distcode];\n}\n\nstatic BROTLI_INLINE void EmitLiterals(const uint8_t* input, const size_t len,\n                                       const uint8_t depth[256],\n                                       const uint16_t bits[256],\n                                       size_t* storage_ix, uint8_t* storage) {\n  size_t j;\n  for (j = 0; j < len; j++) {\n    const uint8_t lit = input[j];\n    BrotliWriteBits(depth[lit], bits[lit], storage_ix, storage);\n  }\n}\n\n/* REQUIRES: len <= 1 << 24. */\nstatic void BrotliStoreMetaBlockHeader(\n    size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix,\n    uint8_t* storage) {\n  size_t nibbles = 6;\n  /* ISLAST */\n  BrotliWriteBits(1, 0, storage_ix, storage);\n  if (len <= (1U << 16)) {\n    nibbles = 4;\n  } else if (len <= (1U << 20)) {\n    nibbles = 5;\n  }\n  BrotliWriteBits(2, nibbles - 4, storage_ix, storage);\n  BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage);\n  /* ISUNCOMPRESSED */\n  BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage);\n}\n\nstatic void UpdateBits(size_t n_bits, uint32_t bits, size_t pos,\n    uint8_t* array) {\n  while (n_bits > 0) {\n    size_t byte_pos = pos >> 3;\n    size_t n_unchanged_bits = pos & 7;\n    size_t n_changed_bits = BROTLI_MIN(size_t, n_bits, 8 - n_unchanged_bits);\n    size_t total_bits = n_unchanged_bits + n_changed_bits;\n    uint32_t mask =\n        (~((1u << total_bits) - 1u)) | ((1u << n_unchanged_bits) - 1u);\n    uint32_t unchanged_bits = array[byte_pos] & mask;\n    uint32_t changed_bits = bits & ((1u << n_changed_bits) - 1u);\n    array[byte_pos] =\n        (uint8_t)((changed_bits << n_unchanged_bits) | unchanged_bits);\n    n_bits -= n_changed_bits;\n    bits >>= n_changed_bits;\n    pos += n_changed_bits;\n  }\n}\n\nstatic void RewindBitPosition(const size_t new_storage_ix,\n                              size_t* storage_ix, uint8_t* storage) {\n  const size_t bitpos = new_storage_ix & 7;\n  const size_t mask = (1u << bitpos) - 1;\n  storage[new_storage_ix >> 3] &= (uint8_t)mask;\n  *storage_ix = new_storage_ix;\n}\n\nstatic BROTLI_BOOL ShouldMergeBlock(BrotliOnePassArena* s,\n    const uint8_t* data, size_t len, const uint8_t* depths) {\n  uint32_t* BROTLI_RESTRICT const histo = s->histogram;\n  static const size_t kSampleRate = 43;\n  size_t i;\n  memset(histo, 0, sizeof(s->histogram));\n  for (i = 0; i < len; i += kSampleRate) {\n    ++histo[data[i]];\n  }\n  {\n    const size_t total = (len + kSampleRate - 1) / kSampleRate;\n    double r = (FastLog2(total) + 0.5) * (double)total + 200;\n    for (i = 0; i < 256; ++i) {\n      r -= (double)histo[i] * (depths[i] + FastLog2(histo[i]));\n    }\n    return TO_BROTLI_BOOL(r >= 0.0);\n  }\n}\n\n/* Acceptable loss for uncompressible speedup is 2% */\n#define MIN_RATIO 980\n\nstatic BROTLI_INLINE BROTLI_BOOL ShouldUseUncompressedMode(\n    const uint8_t* metablock_start, const uint8_t* next_emit,\n    const size_t insertlen, const size_t literal_ratio) {\n  const size_t compressed = (size_t)(next_emit - metablock_start);\n  if (compressed * 50 > insertlen) {\n    return BROTLI_FALSE;\n  } else {\n    return TO_BROTLI_BOOL(literal_ratio > MIN_RATIO);\n  }\n}\n\nstatic void EmitUncompressedMetaBlock(const uint8_t* begin, const uint8_t* end,\n                                      const size_t storage_ix_start,\n                                      size_t* storage_ix, uint8_t* storage) {\n  const size_t len = (size_t)(end - begin);\n  RewindBitPosition(storage_ix_start, storage_ix, storage);\n  BrotliStoreMetaBlockHeader(len, 1, storage_ix, storage);\n  *storage_ix = (*storage_ix + 7u) & ~7u;\n  memcpy(&storage[*storage_ix >> 3], begin, len);\n  *storage_ix += len << 3;\n  storage[*storage_ix >> 3] = 0;\n}\n\nstatic BROTLI_MODEL(\"small\") uint32_t kCmdHistoSeed[128] = {\n  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 0, 0, 0, 0,\n};\n\nstatic BROTLI_INLINE void BrotliCompressFragmentFastImpl(\n    BrotliOnePassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, int* table, size_t table_bits,\n    size_t* storage_ix, uint8_t* storage) {\n  uint8_t* BROTLI_RESTRICT const cmd_depth = s->cmd_depth;\n  uint16_t* BROTLI_RESTRICT const cmd_bits = s->cmd_bits;\n  uint32_t* BROTLI_RESTRICT const cmd_histo = s->cmd_histo;\n  uint8_t* BROTLI_RESTRICT const lit_depth = s->lit_depth;\n  uint16_t* BROTLI_RESTRICT const lit_bits = s->lit_bits;\n  const uint8_t* ip_end;\n\n  /* \"next_emit\" is a pointer to the first byte that is not covered by a\n     previous copy. Bytes between \"next_emit\" and the start of the next copy or\n     the end of the input will be emitted as literal bytes. */\n  const uint8_t* next_emit = input;\n  /* Save the start of the first block for position and distance computations.\n  */\n  const uint8_t* base_ip = input;\n\n  static const size_t kFirstBlockSize = 3 << 15;\n  static const size_t kMergeBlockSize = 1 << 16;\n\n  const size_t kInputMarginBytes = BROTLI_WINDOW_GAP;\n  const size_t kMinMatchLen = 5;\n\n  const uint8_t* metablock_start = input;\n  size_t block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize);\n  size_t total_block_size = block_size;\n  /* Save the bit position of the MLEN field of the meta-block header, so that\n     we can update it later if we decide to extend this meta-block. */\n  size_t mlen_storage_ix = *storage_ix + 3;\n\n  size_t literal_ratio;\n\n  const uint8_t* ip;\n  int last_distance;\n\n  const size_t shift = 64u - table_bits;\n\n  BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);\n  /* No block splits, no contexts. */\n  BrotliWriteBits(13, 0, storage_ix, storage);\n\n  literal_ratio = BuildAndStoreLiteralPrefixCode(\n      s, input, block_size, s->lit_depth, s->lit_bits, storage_ix, storage);\n\n  {\n    /* Store the pre-compressed command and distance prefix codes. */\n    size_t i;\n    for (i = 0; i + 7 < s->cmd_code_numbits; i += 8) {\n      BrotliWriteBits(8, s->cmd_code[i >> 3], storage_ix, storage);\n    }\n  }\n  BrotliWriteBits(s->cmd_code_numbits & 7,\n                  s->cmd_code[s->cmd_code_numbits >> 3], storage_ix, storage);\n\n emit_commands:\n  /* Initialize the command and distance histograms. We will gather\n     statistics of command and distance codes during the processing\n     of this block and use it to update the command and distance\n     prefix codes for the next block. */\n  memcpy(s->cmd_histo, kCmdHistoSeed, sizeof(kCmdHistoSeed));\n\n  /* \"ip\" is the input pointer. */\n  ip = input;\n  last_distance = -1;\n  ip_end = input + block_size;\n\n  if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) {\n    /* For the last block, we need to keep a 16 bytes margin so that we can be\n       sure that all distances are at most window size - 16.\n       For all other blocks, we only need to keep a margin of 5 bytes so that\n       we don't go over the block size with a copy. */\n    const size_t len_limit = BROTLI_MIN(size_t, block_size - kMinMatchLen,\n                                        input_size - kInputMarginBytes);\n    const uint8_t* ip_limit = input + len_limit;\n\n    uint32_t next_hash;\n    for (next_hash = Hash(++ip, shift); ; ) {\n      /* Step 1: Scan forward in the input looking for a 5-byte-long match.\n         If we get close to exhausting the input then goto emit_remainder.\n\n         Heuristic match skipping: If 32 bytes are scanned with no matches\n         found, start looking only at every other byte. If 32 more bytes are\n         scanned, look at every third byte, etc.. When a match is found,\n         immediately go back to looking at every byte. This is a small loss\n         (~5% performance, ~0.1% density) for compressible data due to more\n         bookkeeping, but for non-compressible data (such as JPEG) it's a huge\n         win since the compressor quickly \"realizes\" the data is incompressible\n         and doesn't bother looking for matches everywhere.\n\n         The \"skip\" variable keeps track of how many bytes there are since the\n         last match; dividing it by 32 (i.e. right-shifting by five) gives the\n         number of bytes to move ahead for each iteration. */\n      uint32_t skip = 32;\n\n      const uint8_t* next_ip = ip;\n      const uint8_t* candidate;\n      BROTLI_DCHECK(next_emit < ip);\ntrawl:\n      do {\n        uint32_t hash = next_hash;\n        uint32_t bytes_between_hash_lookups = skip++ >> 5;\n        BROTLI_DCHECK(hash == Hash(next_ip, shift));\n        ip = next_ip;\n        next_ip = ip + bytes_between_hash_lookups;\n        if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {\n          goto emit_remainder;\n        }\n        next_hash = Hash(next_ip, shift);\n        candidate = ip - last_distance;\n        if (IsMatch(ip, candidate)) {\n          if (BROTLI_PREDICT_TRUE(candidate < ip)) {\n            table[hash] = (int)(ip - base_ip);\n            break;\n          }\n        }\n        candidate = base_ip + table[hash];\n        BROTLI_DCHECK(candidate >= base_ip);\n        BROTLI_DCHECK(candidate < ip);\n\n        table[hash] = (int)(ip - base_ip);\n      } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate)));\n\n      /* Check copy distance. If candidate is not feasible, continue search.\n         Checking is done outside of hot loop to reduce overhead. */\n      if (ip - candidate > MAX_DISTANCE) goto trawl;\n\n      /* Step 2: Emit the found match together with the literal bytes from\n         \"next_emit\" to the bit stream, and then see if we can find a next match\n         immediately afterwards. Repeat until we find no match for the input\n         without emitting some literal bytes. */\n\n      {\n        /* We have a 5-byte match at ip, and we need to emit bytes in\n           [next_emit, ip). */\n        const uint8_t* base = ip;\n        size_t matched = 5 + FindMatchLengthWithLimit(\n            candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5);\n        int distance = (int)(base - candidate);  /* > 0 */\n        size_t insert = (size_t)(base - next_emit);\n        ip += matched;\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %lu copy = %d\\n\",\n                    (int)(next_emit - base_ip), (unsigned long)insert, 2));\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        if (BROTLI_PREDICT_TRUE(insert < 6210)) {\n          EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                        storage_ix, storage);\n        } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert,\n                                             literal_ratio)) {\n          EmitUncompressedMetaBlock(metablock_start, base, mlen_storage_ix - 3,\n                                    storage_ix, storage);\n          input_size -= (size_t)(base - input);\n          input = base;\n          next_emit = input;\n          goto next_block;\n        } else {\n          EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                            storage_ix, storage);\n        }\n        EmitLiterals(next_emit, insert, lit_depth, lit_bits,\n                     storage_ix, storage);\n        if (distance == last_distance) {\n          BrotliWriteBits(cmd_depth[64], cmd_bits[64], storage_ix, storage);\n          ++cmd_histo[64];\n        } else {\n          EmitDistance((size_t)distance, cmd_depth, cmd_bits,\n                       cmd_histo, storage_ix, storage);\n          last_distance = distance;\n        }\n        EmitCopyLenLastDistance(matched, cmd_depth, cmd_bits, cmd_histo,\n                                storage_ix, storage);\n        BROTLI_LOG((\"[CompressFragment] pos = %d distance = %d\\n\"\n                    \"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), (int)distance,\n                    (int)(base - base_ip) + 2, 0, (int)matched - 2,\n                    (int)(base - base_ip) + 2, (int)distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        /* We could immediately start working at ip now, but to improve\n           compression we first update \"table\" with the hashes of some positions\n           within the last copy. */\n        {\n          uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n          uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);\n          uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift);\n          table[prev_hash] = (int)(ip - base_ip - 3);\n          prev_hash = HashBytesAtOffset(input_bytes, 1, shift);\n          table[prev_hash] = (int)(ip - base_ip - 2);\n          prev_hash = HashBytesAtOffset(input_bytes, 2, shift);\n          table[prev_hash] = (int)(ip - base_ip - 1);\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      while (IsMatch(ip, candidate)) {\n        /* We have a 5-byte match at ip, and no need to emit any literal bytes\n           prior to ip. */\n        const uint8_t* base = ip;\n        size_t matched = 5 + FindMatchLengthWithLimit(\n            candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5);\n        if (ip - candidate > MAX_DISTANCE) break;\n        ip += matched;\n        last_distance = (int)(base - candidate);  /* > 0 */\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        EmitCopyLen(matched, cmd_depth, cmd_bits, cmd_histo,\n                    storage_ix, storage);\n        EmitDistance((size_t)last_distance, cmd_depth, cmd_bits,\n                     cmd_histo, storage_ix, storage);\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), 0, (int)matched,\n                    (int)(base - base_ip), (int)last_distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        /* We could immediately start working at ip now, but to improve\n           compression we first update \"table\" with the hashes of some positions\n           within the last copy. */\n        {\n          uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n          uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);\n          uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift);\n          table[prev_hash] = (int)(ip - base_ip - 3);\n          prev_hash = HashBytesAtOffset(input_bytes, 1, shift);\n          table[prev_hash] = (int)(ip - base_ip - 2);\n          prev_hash = HashBytesAtOffset(input_bytes, 2, shift);\n          table[prev_hash] = (int)(ip - base_ip - 1);\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      next_hash = Hash(++ip, shift);\n    }\n  }\n\n emit_remainder:\n  BROTLI_DCHECK(next_emit <= ip_end);\n  input += block_size;\n  input_size -= block_size;\n  block_size = BROTLI_MIN(size_t, input_size, kMergeBlockSize);\n\n  /* Decide if we want to continue this meta-block instead of emitting the\n     last insert-only command. */\n  if (input_size > 0 &&\n      total_block_size + block_size <= (1 << 20) &&\n      ShouldMergeBlock(s, input, block_size, lit_depth)) {\n    BROTLI_DCHECK(total_block_size > (1 << 16));\n    /* Update the size of the current meta-block and continue emitting commands.\n       We can do this because the current size and the new size both have 5\n       nibbles. */\n    total_block_size += block_size;\n    UpdateBits(20, (uint32_t)(total_block_size - 1), mlen_storage_ix, storage);\n    goto emit_commands;\n  }\n\n  /* Emit the remaining bytes as literals. */\n  if (next_emit < ip_end) {\n    const size_t insert = (size_t)(ip_end - next_emit);\n    BROTLI_LOG((\"[CompressFragment] pos = %d insert = %lu copy = %d\\n\",\n                (int)(next_emit - base_ip), (unsigned long)insert, 2));\n    if (BROTLI_PREDICT_TRUE(insert < 6210)) {\n      EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                    storage_ix, storage);\n      EmitLiterals(next_emit, insert, lit_depth, lit_bits, storage_ix, storage);\n    } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert,\n                                         literal_ratio)) {\n      EmitUncompressedMetaBlock(metablock_start, ip_end, mlen_storage_ix - 3,\n                                storage_ix, storage);\n    } else {\n      EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                        storage_ix, storage);\n      EmitLiterals(next_emit, insert, lit_depth, lit_bits,\n                   storage_ix, storage);\n    }\n  }\n  next_emit = ip_end;\n\nnext_block:\n  /* If we have more data, write a new meta-block header and prefix codes and\n     then continue emitting commands. */\n  if (input_size > 0) {\n    metablock_start = input;\n    block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize);\n    total_block_size = block_size;\n    /* Save the bit position of the MLEN field of the meta-block header, so that\n       we can update it later if we decide to extend this meta-block. */\n    mlen_storage_ix = *storage_ix + 3;\n    BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);\n    /* No block splits, no contexts. */\n    BrotliWriteBits(13, 0, storage_ix, storage);\n    literal_ratio = BuildAndStoreLiteralPrefixCode(\n        s, input, block_size, lit_depth, lit_bits, storage_ix, storage);\n    BuildAndStoreCommandPrefixCode(s, storage_ix, storage);\n    goto emit_commands;\n  }\n\n  if (!is_last) {\n    /* If this is not the last block, update the command and distance prefix\n       codes for the next block and store the compressed forms. */\n    s->cmd_code[0] = 0;\n    s->cmd_code_numbits = 0;\n    BuildAndStoreCommandPrefixCode(s, &s->cmd_code_numbits, s->cmd_code);\n  }\n}\n\n#define FOR_TABLE_BITS_(X) X(9) X(11) X(13) X(15)\n\n#define BAKE_METHOD_PARAM_(B) \\\nstatic BROTLI_NOINLINE void BrotliCompressFragmentFastImpl ## B(             \\\n    BrotliOnePassArena* s, const uint8_t* input, size_t input_size,          \\\n    BROTLI_BOOL is_last, int* table, size_t* storage_ix, uint8_t* storage) { \\\n  BrotliCompressFragmentFastImpl(s, input, input_size, is_last, table, B,    \\\n      storage_ix, storage);                                                  \\\n}\nFOR_TABLE_BITS_(BAKE_METHOD_PARAM_)\n#undef BAKE_METHOD_PARAM_\n\nvoid BrotliCompressFragmentFast(\n    BrotliOnePassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, int* table, size_t table_size,\n    size_t* storage_ix, uint8_t* storage) {\n  const size_t initial_storage_ix = *storage_ix;\n  const size_t table_bits = Log2FloorNonZero(table_size);\n\n  if (input_size == 0) {\n    BROTLI_DCHECK(is_last);\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n    return;\n  }\n\n  switch (table_bits) {\n#define CASE_(B)                                                     \\\n    case B:                                                          \\\n      BrotliCompressFragmentFastImpl ## B(                           \\\n          s, input, input_size, is_last, table, storage_ix, storage);\\\n      break;\n    FOR_TABLE_BITS_(CASE_)\n#undef CASE_\n    default: BROTLI_DCHECK(0); break;\n  }\n\n  /* If output is larger than single uncompressed block, rewrite it. */\n  if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) {\n    EmitUncompressedMetaBlock(input, input + input_size, initial_storage_ix,\n                              storage_ix, storage);\n  }\n\n  if (is_last) {\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n  }\n}\n\n#undef FOR_TABLE_BITS_\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/compress_fragment.h",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses one-pass processing: when we find a backward\n   match, we immediately emit the corresponding command and literal codes to\n   the bit stream. */\n\n#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_H_\n#define BROTLI_ENC_COMPRESS_FRAGMENT_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"entropy_encode.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BrotliOnePassArena {\n  uint8_t lit_depth[256];\n  uint16_t lit_bits[256];\n\n  /* Command and distance prefix codes (each 64 symbols, stored back-to-back)\n     used for the next block. The command prefix code is over a smaller alphabet\n     with the following 64 symbols:\n        0 - 15: insert length code 0, copy length code 0 - 15, same distance\n       16 - 39: insert length code 0, copy length code 0 - 23\n       40 - 63: insert length code 0 - 23, copy length code 0\n     Note that symbols 16 and 40 represent the same code in the full alphabet,\n     but we do not use either of them. */\n  uint8_t cmd_depth[128];\n  uint16_t cmd_bits[128];\n  uint32_t cmd_histo[128];\n\n  /* The compressed form of the command and distance prefix codes for the next\n     block. */\n  uint8_t cmd_code[512];\n  size_t cmd_code_numbits;\n\n  HuffmanTree tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1];\n  uint32_t histogram[256];\n  uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint16_t tmp_bits[64];\n} BrotliOnePassArena;\n\n/* Compresses \"input\" string to the \"*storage\" buffer as one or more complete\n   meta-blocks, and updates the \"*storage_ix\" bit position.\n\n   If \"is_last\" is 1, emits an additional empty last meta-block.\n\n   \"cmd_depth\" and \"cmd_bits\" contain the command and distance prefix codes\n   (see comment in encode.h) used for the encoding of this input fragment.\n   If \"is_last\" is 0, they are updated to reflect the statistics\n   of this input fragment, to be used for the encoding of the next fragment.\n\n   \"*cmd_code_numbits\" is the number of bits of the compressed representation\n   of the command and distance prefix codes, and \"cmd_code\" is an array of\n   at least \"(*cmd_code_numbits + 7) >> 3\" size that contains the compressed\n   command and distance prefix codes. If \"is_last\" is 0, these are also\n   updated to represent the updated \"cmd_depth\" and \"cmd_bits\".\n\n   REQUIRES: \"input_size\" is greater than zero, or \"is_last\" is 1.\n   REQUIRES: \"input_size\" is less or equal to maximal metablock size (1 << 24).\n   REQUIRES: All elements in \"table[0..table_size-1]\" are initialized to zero.\n   REQUIRES: \"table_size\" is an odd (9, 11, 13, 15) power of two\n   OUTPUT: maximal copy distance <= |input_size|\n   OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */\nBROTLI_INTERNAL void BrotliCompressFragmentFast(BrotliOnePassArena* s,\n                                                const uint8_t* input,\n                                                size_t input_size,\n                                                BROTLI_BOOL is_last,\n                                                int* table, size_t table_size,\n                                                size_t* storage_ix,\n                                                uint8_t* storage);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_COMPRESS_FRAGMENT_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/compress_fragment_two_pass.c",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses two-pass processing: in the first pass we save\n   the found backward matches and literal bytes into a buffer, and in the\n   second pass we emit them into the bit stream using prefix codes built based\n   on the actual command and literal byte histograms. */\n\n#include \"compress_fragment_two_pass.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"\n#include \"brotli_bit_stream.h\"\n#include \"entropy_encode.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"hash_base.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)\n\nstatic BROTLI_INLINE uint32_t Hash(const uint8_t* p,\n    size_t shift, size_t length) {\n  const uint64_t h =\n      (BROTLI_UNALIGNED_LOAD64LE(p) << ((8 - length) * 8)) * kHashMul32;\n  return (uint32_t)(h >> shift);\n}\n\nstatic BROTLI_INLINE uint32_t HashBytesAtOffset(uint64_t v, size_t offset,\n    size_t shift, size_t length) {\n  BROTLI_DCHECK(offset <= 8 - length);\n  {\n    const uint64_t h = ((v >> (8 * offset)) << ((8 - length) * 8)) * kHashMul32;\n    return (uint32_t)(h >> shift);\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2,\n    size_t length) {\n  if (BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2)) {\n    if (length == 4) return BROTLI_TRUE;\n    return TO_BROTLI_BOOL(p1[4] == p2[4] && p1[5] == p2[5]);\n  }\n  return BROTLI_FALSE;\n}\n\n/* Builds a command and distance prefix code (each 64 symbols) into \"depth\" and\n   \"bits\" based on \"histogram\" and stores it into the bit stream. */\nstatic void BuildAndStoreCommandPrefixCode(BrotliTwoPassArena* s,\n                                           size_t* storage_ix,\n                                           uint8_t* storage) {\n  /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */\n  /* TODO(eustas): initialize once. */\n  memset(s->tmp_depth, 0, sizeof(s->tmp_depth));\n  BrotliCreateHuffmanTree(s->cmd_histo, 64, 15, s->tmp_tree, s->cmd_depth);\n  BrotliCreateHuffmanTree(&s->cmd_histo[64], 64, 14, s->tmp_tree,\n                          &s->cmd_depth[64]);\n  /* We have to jump through a few hoops here in order to compute\n     the command bits because the symbols are in a different order than in\n     the full alphabet. This looks complicated, but having the symbols\n     in this order in the command bits saves a few branches in the Emit*\n     functions. */\n  memcpy(s->tmp_depth, s->cmd_depth + 24, 24);\n  memcpy(s->tmp_depth + 24, s->cmd_depth, 8);\n  memcpy(s->tmp_depth + 32, s->cmd_depth + 48, 8);\n  memcpy(s->tmp_depth + 40, s->cmd_depth + 8, 8);\n  memcpy(s->tmp_depth + 48, s->cmd_depth + 56, 8);\n  memcpy(s->tmp_depth + 56, s->cmd_depth + 16, 8);\n  BrotliConvertBitDepthsToSymbols(s->tmp_depth, 64, s->tmp_bits);\n  memcpy(s->cmd_bits, s->tmp_bits + 24, 16);\n  memcpy(s->cmd_bits + 8, s->tmp_bits + 40, 16);\n  memcpy(s->cmd_bits + 16, s->tmp_bits + 56, 16);\n  memcpy(s->cmd_bits + 24, s->tmp_bits, 48);\n  memcpy(s->cmd_bits + 48, s->tmp_bits + 32, 16);\n  memcpy(s->cmd_bits + 56, s->tmp_bits + 48, 16);\n  BrotliConvertBitDepthsToSymbols(&s->cmd_depth[64], 64, &s->cmd_bits[64]);\n  {\n    /* Create the bit length array for the full command alphabet. */\n    size_t i;\n    memset(s->tmp_depth, 0, 64); /* only 64 first values were used */\n    memcpy(s->tmp_depth, s->cmd_depth + 24, 8);\n    memcpy(s->tmp_depth + 64, s->cmd_depth + 32, 8);\n    memcpy(s->tmp_depth + 128, s->cmd_depth + 40, 8);\n    memcpy(s->tmp_depth + 192, s->cmd_depth + 48, 8);\n    memcpy(s->tmp_depth + 384, s->cmd_depth + 56, 8);\n    for (i = 0; i < 8; ++i) {\n      s->tmp_depth[128 + 8 * i] = s->cmd_depth[i];\n      s->tmp_depth[256 + 8 * i] = s->cmd_depth[8 + i];\n      s->tmp_depth[448 + 8 * i] = s->cmd_depth[16 + i];\n    }\n    BrotliStoreHuffmanTree(s->tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS,\n                           s->tmp_tree, storage_ix, storage);\n  }\n  BrotliStoreHuffmanTree(&s->cmd_depth[64], 64, s->tmp_tree, storage_ix,\n                         storage);\n}\n\nstatic BROTLI_INLINE void EmitInsertLen(\n    uint32_t insertlen, uint32_t** commands) {\n  if (insertlen < 6) {\n    **commands = insertlen;\n  } else if (insertlen < 130) {\n    const uint32_t tail = insertlen - 2;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1u;\n    const uint32_t prefix = tail >> nbits;\n    const uint32_t inscode = (nbits << 1) + prefix + 2;\n    const uint32_t extra = tail - (prefix << nbits);\n    **commands = inscode | (extra << 8);\n  } else if (insertlen < 2114) {\n    const uint32_t tail = insertlen - 66;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const uint32_t code = nbits + 10;\n    const uint32_t extra = tail - (1u << nbits);\n    **commands = code | (extra << 8);\n  } else if (insertlen < 6210) {\n    const uint32_t extra = insertlen - 2114;\n    **commands = 21 | (extra << 8);\n  } else if (insertlen < 22594) {\n    const uint32_t extra = insertlen - 6210;\n    **commands = 22 | (extra << 8);\n  } else {\n    const uint32_t extra = insertlen - 22594;\n    **commands = 23 | (extra << 8);\n  }\n  ++(*commands);\n}\n\nstatic BROTLI_INLINE void EmitCopyLen(size_t copylen, uint32_t** commands) {\n  if (copylen < 10) {\n    **commands = (uint32_t)(copylen + 38);\n  } else if (copylen < 134) {\n    const size_t tail = copylen - 6;\n    const size_t nbits = Log2FloorNonZero(tail) - 1;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 44;\n    const size_t extra = tail - (prefix << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n  } else if (copylen < 2118) {\n    const size_t tail = copylen - 70;\n    const size_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 52;\n    const size_t extra = tail - ((size_t)1 << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n  } else {\n    const size_t extra = copylen - 2118;\n    **commands = (uint32_t)(63 | (extra << 8));\n  }\n  ++(*commands);\n}\n\nstatic BROTLI_INLINE void EmitCopyLenLastDistance(\n    size_t copylen, uint32_t** commands) {\n  if (copylen < 12) {\n    **commands = (uint32_t)(copylen + 20);\n    ++(*commands);\n  } else if (copylen < 72) {\n    const size_t tail = copylen - 8;\n    const size_t nbits = Log2FloorNonZero(tail) - 1;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 28;\n    const size_t extra = tail - (prefix << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n    ++(*commands);\n  } else if (copylen < 136) {\n    const size_t tail = copylen - 8;\n    const size_t code = (tail >> 5) + 54;\n    const size_t extra = tail & 31;\n    **commands = (uint32_t)(code | (extra << 8));\n    ++(*commands);\n    **commands = 64;\n    ++(*commands);\n  } else if (copylen < 2120) {\n    const size_t tail = copylen - 72;\n    const size_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 52;\n    const size_t extra = tail - ((size_t)1 << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n    ++(*commands);\n    **commands = 64;\n    ++(*commands);\n  } else {\n    const size_t extra = copylen - 2120;\n    **commands = (uint32_t)(63 | (extra << 8));\n    ++(*commands);\n    **commands = 64;\n    ++(*commands);\n  }\n}\n\nstatic BROTLI_INLINE void EmitDistance(uint32_t distance, uint32_t** commands) {\n  uint32_t d = distance + 3;\n  uint32_t nbits = Log2FloorNonZero(d) - 1;\n  const uint32_t prefix = (d >> nbits) & 1;\n  const uint32_t offset = (2 + prefix) << nbits;\n  const uint32_t distcode = 2 * (nbits - 1) + prefix + 80;\n  uint32_t extra = d - offset;\n  **commands = distcode | (extra << 8);\n  ++(*commands);\n}\n\n/* REQUIRES: len <= 1 << 24. */\nstatic void BrotliStoreMetaBlockHeader(\n    size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix,\n    uint8_t* storage) {\n  size_t nibbles = 6;\n  /* ISLAST */\n  BrotliWriteBits(1, 0, storage_ix, storage);\n  if (len <= (1U << 16)) {\n    nibbles = 4;\n  } else if (len <= (1U << 20)) {\n    nibbles = 5;\n  }\n  BrotliWriteBits(2, nibbles - 4, storage_ix, storage);\n  BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage);\n  /* ISUNCOMPRESSED */\n  BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage);\n}\n\nstatic BROTLI_INLINE void CreateCommands(const uint8_t* input,\n    size_t block_size, size_t input_size, const uint8_t* base_ip, int* table,\n    size_t table_bits, size_t min_match,\n    uint8_t** literals, uint32_t** commands) {\n  /* \"ip\" is the input pointer. */\n  const uint8_t* ip = input;\n  const size_t shift = 64u - table_bits;\n  const uint8_t* ip_end = input + block_size;\n  /* \"next_emit\" is a pointer to the first byte that is not covered by a\n     previous copy. Bytes between \"next_emit\" and the start of the next copy or\n     the end of the input will be emitted as literal bytes. */\n  const uint8_t* next_emit = input;\n\n  int last_distance = -1;\n  const size_t kInputMarginBytes = BROTLI_WINDOW_GAP;\n\n  if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) {\n    /* For the last block, we need to keep a 16 bytes margin so that we can be\n       sure that all distances are at most window size - 16.\n       For all other blocks, we only need to keep a margin of 5 bytes so that\n       we don't go over the block size with a copy. */\n    const size_t len_limit = BROTLI_MIN(size_t, block_size - min_match,\n                                        input_size - kInputMarginBytes);\n    const uint8_t* ip_limit = input + len_limit;\n\n    uint32_t next_hash;\n    for (next_hash = Hash(++ip, shift, min_match); ; ) {\n      /* Step 1: Scan forward in the input looking for a 6-byte-long match.\n         If we get close to exhausting the input then goto emit_remainder.\n\n         Heuristic match skipping: If 32 bytes are scanned with no matches\n         found, start looking only at every other byte. If 32 more bytes are\n         scanned, look at every third byte, etc.. When a match is found,\n         immediately go back to looking at every byte. This is a small loss\n         (~5% performance, ~0.1% density) for compressible data due to more\n         bookkeeping, but for non-compressible data (such as JPEG) it's a huge\n         win since the compressor quickly \"realizes\" the data is incompressible\n         and doesn't bother looking for matches everywhere.\n\n         The \"skip\" variable keeps track of how many bytes there are since the\n         last match; dividing it by 32 (ie. right-shifting by five) gives the\n         number of bytes to move ahead for each iteration. */\n      uint32_t skip = 32;\n\n      const uint8_t* next_ip = ip;\n      const uint8_t* candidate;\n\n      BROTLI_DCHECK(next_emit < ip);\ntrawl:\n      do {\n        uint32_t hash = next_hash;\n        uint32_t bytes_between_hash_lookups = skip++ >> 5;\n        ip = next_ip;\n        BROTLI_DCHECK(hash == Hash(ip, shift, min_match));\n        next_ip = ip + bytes_between_hash_lookups;\n        if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {\n          goto emit_remainder;\n        }\n        next_hash = Hash(next_ip, shift, min_match);\n        candidate = ip - last_distance;\n        if (IsMatch(ip, candidate, min_match)) {\n          if (BROTLI_PREDICT_TRUE(candidate < ip)) {\n            table[hash] = (int)(ip - base_ip);\n            break;\n          }\n        }\n        candidate = base_ip + table[hash];\n        BROTLI_DCHECK(candidate >= base_ip);\n        BROTLI_DCHECK(candidate < ip);\n\n        table[hash] = (int)(ip - base_ip);\n      } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate, min_match)));\n\n      /* Check copy distance. If candidate is not feasible, continue search.\n         Checking is done outside of hot loop to reduce overhead. */\n      if (ip - candidate > MAX_DISTANCE) goto trawl;\n\n      /* Step 2: Emit the found match together with the literal bytes from\n         \"next_emit\", and then see if we can find a next match immediately\n         afterwards. Repeat until we find no match for the input\n         without emitting some literal bytes. */\n\n      {\n        /* We have a 6-byte match at ip, and we need to emit bytes in\n           [next_emit, ip). */\n        const uint8_t* base = ip;\n        size_t matched = min_match + FindMatchLengthWithLimit(\n            candidate + min_match, ip + min_match,\n            (size_t)(ip_end - ip) - min_match);\n        int distance = (int)(base - candidate);  /* > 0 */\n        int insert = (int)(base - next_emit);\n        ip += matched;\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        EmitInsertLen((uint32_t)insert, commands);\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\",\n                    (int)(next_emit - base_ip), insert, 2));\n        memcpy(*literals, next_emit, (size_t)insert);\n        *literals += insert;\n        if (distance == last_distance) {\n          **commands = 64;\n          ++(*commands);\n        } else {\n          EmitDistance((uint32_t)distance, commands);\n          last_distance = distance;\n        }\n        EmitCopyLenLastDistance(matched, commands);\n        BROTLI_LOG((\"[CompressFragment] pos = %d distance = %d\\n\"\n                    \"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), (int)distance,\n                    (int)(base - base_ip) + 2, 0, (int)matched - 2,\n                    (int)(base - base_ip) + 2, (int)distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        {\n          /* We could immediately start working at ip now, but to improve\n             compression we first update \"table\" with the hashes of some\n             positions within the last copy. */\n          uint64_t input_bytes;\n          uint32_t cur_hash;\n          uint32_t prev_hash;\n          if (min_match == 4) {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n            cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          } else {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 4);\n            prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);\n            cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          }\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      while (ip - candidate <= MAX_DISTANCE &&\n          IsMatch(ip, candidate, min_match)) {\n        /* We have a 6-byte match at ip, and no need to emit any\n           literal bytes prior to ip. */\n        const uint8_t* base = ip;\n        size_t matched = min_match + FindMatchLengthWithLimit(\n            candidate + min_match, ip + min_match,\n            (size_t)(ip_end - ip) - min_match);\n        ip += matched;\n        last_distance = (int)(base - candidate);  /* > 0 */\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        EmitCopyLen(matched, commands);\n        EmitDistance((uint32_t)last_distance, commands);\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), 0, (int)matched,\n                    (int)(base - base_ip), (int)last_distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        {\n          /* We could immediately start working at ip now, but to improve\n             compression we first update \"table\" with the hashes of some\n             positions within the last copy. */\n          uint64_t input_bytes;\n          uint32_t cur_hash;\n          uint32_t prev_hash;\n          if (min_match == 4) {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n            cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          } else {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 4);\n            prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);\n            cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          }\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      next_hash = Hash(++ip, shift, min_match);\n    }\n  }\n\nemit_remainder:\n  BROTLI_DCHECK(next_emit <= ip_end);\n  /* Emit the remaining bytes as literals. */\n  if (next_emit < ip_end) {\n    const uint32_t insert = (uint32_t)(ip_end - next_emit);\n    EmitInsertLen(insert, commands);\n    BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\",\n                (int)(next_emit - base_ip), insert, 2));\n    memcpy(*literals, next_emit, insert);\n    *literals += insert;\n  }\n}\n\nstatic void StoreCommands(BrotliTwoPassArena* s,\n                          const uint8_t* literals, const size_t num_literals,\n                          const uint32_t* commands, const size_t num_commands,\n                          size_t* storage_ix, uint8_t* storage) {\n  static const BROTLI_MODEL(\"small\") uint32_t kNumExtraBits[128] = {\n      0,  0,  0,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,\n      6,  7,  8,  9,  10, 12, 14, 24, 0,  0,  0,  0,  0,  0,  0,  0,\n      1,  1,  2,  2,  3,  3,  4,  4,  0,  0,  0,  0,  0,  0,  0,  0,\n      1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  7,  8,  9,  10, 24,\n      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n      1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,\n      9,  9,  10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,\n      17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24,\n  };\n  static const BROTLI_MODEL(\"small\") uint32_t kInsertOffset[24] = {\n      0,  1,  2,  3,  4,   5,   6,   8,   10,   14,   18,   26,\n      34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594,\n  };\n\n  size_t i;\n  memset(s->lit_histo, 0, sizeof(s->lit_histo));\n  /* TODO(eustas): is that necessary? */\n  memset(s->cmd_depth, 0, sizeof(s->cmd_depth));\n  /* TODO(eustas): is that necessary? */\n  memset(s->cmd_bits, 0, sizeof(s->cmd_bits));\n  memset(s->cmd_histo, 0, sizeof(s->cmd_histo));\n  for (i = 0; i < num_literals; ++i) {\n    ++s->lit_histo[literals[i]];\n  }\n  BrotliBuildAndStoreHuffmanTreeFast(s->tmp_tree, s->lit_histo, num_literals,\n                                     /* max_bits = */ 8, s->lit_depth,\n                                     s->lit_bits, storage_ix, storage);\n\n  for (i = 0; i < num_commands; ++i) {\n    const uint32_t code = commands[i] & 0xFF;\n    BROTLI_DCHECK(code < 128);\n    ++s->cmd_histo[code];\n  }\n  s->cmd_histo[1] += 1;\n  s->cmd_histo[2] += 1;\n  s->cmd_histo[64] += 1;\n  s->cmd_histo[84] += 1;\n  BuildAndStoreCommandPrefixCode(s, storage_ix, storage);\n\n  for (i = 0; i < num_commands; ++i) {\n    const uint32_t cmd = commands[i];\n    const uint32_t code = cmd & 0xFF;\n    const uint32_t extra = cmd >> 8;\n    BROTLI_DCHECK(code < 128);\n    BrotliWriteBits(s->cmd_depth[code], s->cmd_bits[code], storage_ix, storage);\n    BrotliWriteBits(kNumExtraBits[code], extra, storage_ix, storage);\n    if (code < 24) {\n      const uint32_t insert = kInsertOffset[code] + extra;\n      uint32_t j;\n      for (j = 0; j < insert; ++j) {\n        const uint8_t lit = *literals;\n        BrotliWriteBits(s->lit_depth[lit], s->lit_bits[lit], storage_ix,\n                        storage);\n        ++literals;\n      }\n    }\n  }\n}\n\n/* Acceptable loss for uncompressible speedup is 2% */\n#define MIN_RATIO 0.98\n#define SAMPLE_RATE 43\n\nstatic BROTLI_BOOL ShouldCompress(BrotliTwoPassArena* s,\n    const uint8_t* input, size_t input_size, size_t num_literals) {\n  double corpus_size = (double)input_size;\n  if ((double)num_literals < MIN_RATIO * corpus_size) {\n    return BROTLI_TRUE;\n  } else {\n    const double max_total_bit_cost = corpus_size * 8 * MIN_RATIO / SAMPLE_RATE;\n    size_t i;\n    memset(s->lit_histo, 0, sizeof(s->lit_histo));\n    for (i = 0; i < input_size; i += SAMPLE_RATE) {\n      ++s->lit_histo[input[i]];\n    }\n    return TO_BROTLI_BOOL(\n        BrotliBitsEntropy(s->lit_histo, 256) < max_total_bit_cost);\n  }\n}\n\nstatic void RewindBitPosition(const size_t new_storage_ix,\n                              size_t* storage_ix, uint8_t* storage) {\n  const size_t bitpos = new_storage_ix & 7;\n  const size_t mask = (1u << bitpos) - 1;\n  storage[new_storage_ix >> 3] &= (uint8_t)mask;\n  *storage_ix = new_storage_ix;\n}\n\nstatic void EmitUncompressedMetaBlock(const uint8_t* input, size_t input_size,\n                                      size_t* storage_ix, uint8_t* storage) {\n  BrotliStoreMetaBlockHeader(input_size, 1, storage_ix, storage);\n  *storage_ix = (*storage_ix + 7u) & ~7u;\n  memcpy(&storage[*storage_ix >> 3], input, input_size);\n  *storage_ix += input_size << 3;\n  storage[*storage_ix >> 3] = 0;\n}\n\nstatic BROTLI_INLINE void BrotliCompressFragmentTwoPassImpl(\n    BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,\n    int* table, size_t table_bits, size_t min_match,\n    size_t* storage_ix, uint8_t* storage) {\n  /* Save the start of the first block for position and distance computations.\n  */\n  const uint8_t* base_ip = input;\n  BROTLI_UNUSED(is_last);\n\n  while (input_size > 0) {\n    size_t block_size =\n        BROTLI_MIN(size_t, input_size, kCompressFragmentTwoPassBlockSize);\n    uint32_t* commands = command_buf;\n    uint8_t* literals = literal_buf;\n    size_t num_literals;\n    CreateCommands(input, block_size, input_size, base_ip, table,\n                   table_bits, min_match, &literals, &commands);\n    num_literals = (size_t)(literals - literal_buf);\n    if (ShouldCompress(s, input, block_size, num_literals)) {\n      const size_t num_commands = (size_t)(commands - command_buf);\n      BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);\n      /* No block splits, no contexts. */\n      BrotliWriteBits(13, 0, storage_ix, storage);\n      StoreCommands(s, literal_buf, num_literals, command_buf, num_commands,\n                    storage_ix, storage);\n    } else {\n      /* Since we did not find many backward references and the entropy of\n         the data is close to 8 bits, we can simply emit an uncompressed block.\n         This makes compression speed of uncompressible data about 3x faster. */\n      EmitUncompressedMetaBlock(input, block_size, storage_ix, storage);\n    }\n    input += block_size;\n    input_size -= block_size;\n  }\n}\n\n#define FOR_TABLE_BITS_(X) \\\n  X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17)\n\n#define BAKE_METHOD_PARAM_(B)                                                  \\\nstatic BROTLI_NOINLINE void BrotliCompressFragmentTwoPassImpl ## B(            \\\n    BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,            \\\n    BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,          \\\n    int* table, size_t* storage_ix, uint8_t* storage) {                        \\\n  size_t min_match = (B <= 15) ? 4 : 6;                                        \\\n  BrotliCompressFragmentTwoPassImpl(s, input, input_size, is_last, command_buf,\\\n      literal_buf, table, B, min_match, storage_ix, storage);                  \\\n}\nFOR_TABLE_BITS_(BAKE_METHOD_PARAM_)\n#undef BAKE_METHOD_PARAM_\n\nvoid BrotliCompressFragmentTwoPass(\n    BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,\n    int* table, size_t table_size, size_t* storage_ix, uint8_t* storage) {\n  const size_t initial_storage_ix = *storage_ix;\n  const size_t table_bits = Log2FloorNonZero(table_size);\n  switch (table_bits) {\n#define CASE_(B)                                      \\\n    case B:                                           \\\n      BrotliCompressFragmentTwoPassImpl ## B(         \\\n          s, input, input_size, is_last, command_buf, \\\n          literal_buf, table, storage_ix, storage);   \\\n      break;\n    FOR_TABLE_BITS_(CASE_)\n#undef CASE_\n    default: BROTLI_DCHECK(0); break;\n  }\n\n  /* If output is larger than single uncompressed block, rewrite it. */\n  if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) {\n    RewindBitPosition(initial_storage_ix, storage_ix, storage);\n    EmitUncompressedMetaBlock(input, input_size, storage_ix, storage);\n  }\n\n  if (is_last) {\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n  }\n}\n\n#undef FOR_TABLE_BITS_\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/compress_fragment_two_pass.h",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses two-pass processing: in the first pass we save\n   the found backward matches and literal bytes into a buffer, and in the\n   second pass we emit them into the bit stream using prefix codes built based\n   on the actual command and literal byte histograms. */\n\n#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_\n#define BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"entropy_encode.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* TODO(eustas): turn to macro. */\nstatic const size_t kCompressFragmentTwoPassBlockSize = 1 << 17;\n\ntypedef struct BrotliTwoPassArena {\n  uint32_t lit_histo[256];\n  uint8_t lit_depth[256];\n  uint16_t lit_bits[256];\n\n  uint32_t cmd_histo[128];\n  uint8_t cmd_depth[128];\n  uint16_t cmd_bits[128];\n\n  /* BuildAndStoreCommandPrefixCode */\n  HuffmanTree tmp_tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1];\n  uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint16_t tmp_bits[64];\n} BrotliTwoPassArena;\n\n/* Compresses \"input\" string to the \"*storage\" buffer as one or more complete\n   meta-blocks, and updates the \"*storage_ix\" bit position.\n\n   If \"is_last\" is 1, emits an additional empty last meta-block.\n\n   REQUIRES: \"input_size\" is greater than zero, or \"is_last\" is 1.\n   REQUIRES: \"input_size\" is less or equal to maximal metablock size (1 << 24).\n   REQUIRES: \"command_buf\" and \"literal_buf\" point to at least\n              kCompressFragmentTwoPassBlockSize long arrays.\n   REQUIRES: All elements in \"table[0..table_size-1]\" are initialized to zero.\n   REQUIRES: \"table_size\" is a power of two\n   OUTPUT: maximal copy distance <= |input_size|\n   OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */\nBROTLI_INTERNAL void BrotliCompressFragmentTwoPass(BrotliTwoPassArena* s,\n                                                   const uint8_t* input,\n                                                   size_t input_size,\n                                                   BROTLI_BOOL is_last,\n                                                   uint32_t* command_buf,\n                                                   uint8_t* literal_buf,\n                                                   int* table,\n                                                   size_t table_size,\n                                                   size_t* storage_ix,\n                                                   uint8_t* storage);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/dictionary_hash.c",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Hash table on the 4-byte prefixes of static dictionary words. */\n\n#include \"dictionary_hash.h\"\n\n#include \"../common/platform.h\"  /* IWYU pragma: keep */\n#include \"../common/static_init.h\"\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\n#include \"../common/dictionary.h\"\n#include \"hash_base.h\"\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\nBROTLI_BOOL BROTLI_COLD BrotliEncoderInitDictionaryHash(\n    const BrotliDictionary* dict, uint16_t* words, uint8_t* lengths) {\n  size_t global_idx = 0;\n  size_t len;\n  size_t i;\n  static const uint8_t frozen_idx[1688] = {0, 0, 8, 164, 32, 56, 31, 191, 36, 4,\n128, 81, 68, 132, 145, 129, 0, 0, 0, 28, 0, 8, 1, 1, 64, 3, 1, 0, 0, 0, 0, 0, 4,\n64, 1, 2, 128, 0, 132, 49, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 1, 0, 36, 152,\n0, 0, 0, 0, 128, 8, 0, 0, 128, 0, 0, 8, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,\n0, 0, 0, 1, 0, 64, 133, 0, 32, 0, 0, 128, 1, 0, 0, 0, 0, 4, 4, 4, 32, 16, 130,\n0, 128, 8, 0, 0, 0, 0, 0, 64, 0, 64, 0, 160, 0, 148, 53, 0, 0, 0, 0, 0, 128, 0,\n130, 0, 0, 0, 8, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 32, 1, 32, 129, 0, 12, 0,\n1, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 32, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8,\n0, 0, 2, 0, 0, 0, 0, 0, 32, 0, 0, 0, 2, 66, 128, 0, 0, 16, 0, 0, 0, 0, 64, 1, 6,\n128, 8, 0, 192, 24, 32, 0, 0, 8, 4, 128, 128, 2, 160, 0, 160, 0, 64, 0, 0, 2, 0,\n0, 0, 0, 0, 0, 0, 0, 0, 32, 1, 0, 0, 64, 0, 0, 0, 0, 0, 0, 32, 0, 66, 0, 2, 0,\n4, 0, 8, 0, 2, 0, 0, 33, 8, 0, 0, 0, 8, 0, 128, 162, 4, 128, 0, 2, 33, 0, 160,\n0, 8, 0, 64, 0, 160, 0, 129, 4, 0, 0, 32, 0, 0, 32, 0, 2, 0, 0, 0, 0, 0, 0, 128,\n0, 0, 0, 0, 0, 64, 10, 0, 0, 0, 0, 32, 64, 0, 0, 0, 0, 0, 16, 0, 16, 16, 0, 0,\n80, 2, 0, 0, 0, 0, 8, 0, 0, 16, 0, 8, 0, 0, 0, 8, 64, 128, 0, 0, 0, 8, 208, 0,\n0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 32, 0, 8, 0, 128, 0, 0, 0, 1, 0, 0, 0,\n16, 8, 1, 136, 0, 0, 36, 0, 64, 9, 0, 1, 32, 8, 0, 64, 64, 131, 16, 224, 32, 4,\n0, 4, 5, 160, 0, 131, 0, 4, 96, 0, 0, 184, 192, 0, 177, 205, 96, 0, 0, 0, 0, 2,\n0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 128, 0, 0, 8, 0, 0, 0, 0, 1, 4, 0, 1,\n0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 4, 0, 0, 64, 69, 0, 0, 8, 2, 66, 32, 64, 0, 0, 0,\n0, 0, 1, 0, 128, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 16, 0, 0, 4, 128, 64,\n0, 0, 0, 0, 0, 0, 0, 0, 224, 0, 8, 0, 0, 130, 16, 64, 128, 2, 64, 0, 0, 0, 128,\n2, 192, 64, 0, 65, 0, 0, 0, 16, 0, 0, 0, 32, 4, 2, 2, 76, 0, 0, 0, 4, 72, 52,\n131, 44, 76, 0, 0, 0, 0, 64, 1, 16, 148, 4, 0, 16, 10, 64, 0, 2, 0, 1, 0, 128,\n64, 68, 0, 0, 0, 0, 0, 64, 144, 0, 8, 0, 2, 0, 0, 0, 0, 0, 0, 3, 64, 0, 0, 0, 0,\n1, 128, 0, 0, 32, 66, 0, 0, 0, 40, 0, 18, 0, 0, 0, 0, 0, 33, 0, 0, 32, 0, 0, 32,\n0, 128, 4, 64, 145, 140, 0, 0, 0, 128, 0, 2, 0, 0, 20, 0, 80, 38, 0, 0, 32, 0,\n32, 64, 4, 4, 0, 4, 0, 0, 0, 129, 4, 0, 0, 144, 17, 32, 130, 16, 132, 24, 134,\n0, 0, 64, 2, 5, 50, 8, 194, 33, 1, 68, 117, 1, 8, 32, 161, 54, 0, 130, 34, 0, 0,\n0, 64, 128, 0, 0, 2, 0, 0, 0, 0, 32, 1, 0, 0, 0, 3, 14, 0, 0, 0, 0, 0, 16, 4, 0,\n0, 0, 0, 0, 0, 0, 0, 96, 1, 24, 18, 0, 1, 128, 24, 0, 64, 0, 4, 0, 16, 128, 0,\n64, 0, 0, 0, 64, 0, 8, 0, 0, 0, 0, 0, 66, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n0, 0, 0, 0, 16, 0, 64, 2, 0, 0, 0, 0, 6, 0, 8, 8, 2, 0, 64, 0, 0, 0, 0, 128, 2,\n2, 12, 64, 0, 64, 0, 8, 0, 128, 32, 0, 0, 10, 0, 0, 32, 0, 128, 32, 33, 8, 136,\n0, 96, 64, 0, 0, 0, 0, 0, 64, 4, 16, 4, 8, 0, 0, 0, 16, 0, 2, 0, 0, 1, 128, 0,\n64, 16, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 2, 0, 16, 0, 4, 0, 8, 0, 0, 0, 0, 0,\n20, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 136, 0, 0, 0, 0, 0, 8, 0,\n0, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0,\n0, 0, 4, 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,\n0, 0, 0, 0, 2, 128, 0, 0, 0, 8, 2, 0, 0, 128, 0, 16, 2, 0, 0, 4, 0, 32, 0, 0, 1,\n4, 64, 64, 0, 4, 0, 1, 0, 16, 0, 32, 68, 4, 4, 65, 10, 0, 20, 37, 18, 1, 148, 0,\n32, 128, 3, 8, 0, 64, 0, 0, 0, 0, 0, 0, 4, 0, 16, 1, 128, 0, 0, 0, 128, 16, 0,\n0, 0, 0, 1, 128, 0, 0, 128, 64, 128, 64, 0, 130, 0, 164, 8, 0, 0, 1, 64, 128, 0,\n18, 0, 2, 150, 0, 8, 0, 0, 64, 0, 81, 0, 0, 16, 128, 2, 8, 36, 32, 129, 4, 144,\n13, 0, 0, 3, 8, 1, 0, 2, 0, 0, 64, 0, 5, 0, 1, 34, 1, 32, 2, 16, 128, 128, 128,\n0, 0, 0, 2, 0, 4, 18, 8, 12, 34, 32, 192, 6, 64, 224, 33, 0, 0, 137, 72, 64, 0,\n24, 8, 128, 128, 0, 16, 0, 32, 128, 128, 132, 8, 0, 0, 16, 0, 64, 0, 0, 4, 0, 0,\n16, 0, 4, 128, 64, 0, 0, 1, 0, 4, 64, 32, 144, 130, 2, 128, 0, 192, 0, 64, 82,\n64, 1, 32, 128, 128, 2, 0, 84, 0, 32, 0, 44, 24, 72, 80, 32, 16, 0, 0, 44, 16,\n96, 64, 1, 72, 131, 0, 0, 0, 16, 0, 0, 165, 0, 129, 2, 49, 48, 64, 64, 12, 64,\n176, 64, 84, 8, 128, 20, 64, 213, 136, 104, 1, 41, 15, 83, 170, 0, 0, 41, 1, 64,\n64, 0, 193, 64, 64, 8, 0, 128, 0, 0, 64, 8, 64, 8, 1, 16, 0, 8, 0, 0, 2, 1, 128,\n28, 84, 141, 97, 0, 0, 68, 0, 0, 129, 8, 0, 16, 8, 32, 0, 64, 0, 0, 0, 24, 0, 0,\n0, 192, 0, 8, 128, 0, 0, 0, 0, 0, 64, 0, 1, 0, 0, 0, 0, 40, 1, 128, 64, 0, 4, 2,\n32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 32, 8, 0, 32, 0, 0, 0, 16, 17, 0,\n2, 4, 0, 0, 33, 128, 2, 0, 0, 0, 0, 129, 0, 2, 0, 0, 0, 36, 0, 32, 2, 0, 0, 0,\n0, 0, 0, 32, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 32, 64, 0, 0, 0, 0, 0, 0,\n32, 0, 0, 32, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 16, 0, 0, 0, 0, 0, 0, 0,\n1, 0, 136, 0, 0, 24, 192, 128, 3, 0, 17, 18, 2, 0, 66, 0, 4, 24, 0, 9, 208, 167,\n0, 144, 20, 64, 0, 130, 64, 0, 2, 16, 136, 8, 74, 32, 0, 168, 0, 65, 32, 8, 12,\n1, 3, 1, 64, 180, 3, 0, 64, 0, 8, 0, 0, 32, 65, 0, 4, 16, 4, 16, 68, 32, 64, 36,\n32, 24, 33, 1, 128, 0, 0, 8, 0, 32, 64, 81, 0, 1, 10, 19, 8, 0, 0, 4, 5, 144, 0,\n0, 8, 128, 0, 0, 4, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 0, 0, 80, 1, 0, 0,\n33, 0, 32, 66, 4, 2, 0, 1, 43, 2, 0, 0, 4, 32, 16, 0, 64, 0, 3, 32, 0, 2, 64,\n64, 116, 0, 65, 52, 64, 0, 17, 64, 192, 96, 8, 10, 8, 2, 4, 0, 17, 64, 0, 4, 0,\n0, 4, 128, 0, 0, 9, 0, 0, 130, 2, 0, 192, 0, 48, 128, 64, 0, 96, 0, 64, 0, 1,\n16, 32, 0, 1, 32, 6, 128, 2, 32, 0, 12, 0, 0, 48, 32, 8, 0, 0, 128, 0, 18, 0,\n0, 28, 24, 41, 16, 5, 32, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n0, 0, 0, 0, 1, 0, 0, 0, 16, 0, 0, 0, 0, 64, 0, 0, 0, 0, 8, 0, 0, 0, 0, 16, 128,\n0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,\n0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n0, 0, 0, 0, 0, 0, 0};\n\n  memset(lengths, 0, BROTLI_ENC_NUM_HASH_BUCKETS);\n\n  for (len = BROTLI_MAX_DICTIONARY_WORD_LENGTH;\n       len >= BROTLI_MIN_DICTIONARY_WORD_LENGTH; --len) {\n    size_t length_lt_8 = len < 8 ? 1 : 0;\n    size_t n = 1u << dict->size_bits_by_length[len];\n    const uint8_t* dict_words = dict->data + dict->offsets_by_length[len];\n    for (i = 0; i < n; ++i) {\n      size_t j = n - 1 - i;\n      const uint8_t* word = dict_words + len * j;\n      const uint32_t key = Hash14(word);\n      size_t idx = (key << 1) + length_lt_8;\n      if ((lengths[idx] & 0x80) == 0) {\n        BROTLI_BOOL is_final = TO_BROTLI_BOOL(frozen_idx[global_idx / 8] &\n                                              (1u << (global_idx % 8)));\n        words[idx] = (uint16_t)j;\n        lengths[idx] = (uint8_t)(len + (is_final ? 0x80 : 0));\n      }\n      global_idx++;\n    }\n  }\n  for (i = 0; i < BROTLI_ENC_NUM_HASH_BUCKETS; ++i) {\n    lengths[i] &= 0x7F;\n  }\n\n  return BROTLI_TRUE;\n}\n\nBROTLI_MODEL(\"small\")\nuint16_t kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS];\nBROTLI_MODEL(\"small\")\nuint8_t kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS];\n\n#else  /* BROTLI_STATIC_INIT */\n\n/* Embed kStaticDictionaryHashWords and kStaticDictionaryHashLengths. */\n#include \"dictionary_hash_inc.h\"\n\n#endif  /* BROTLI_STATIC_INIT */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/dictionary_hash.h",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Hash table on the 4-byte prefixes of static dictionary words. */\n\n#ifndef BROTLI_ENC_DICTIONARY_HASH_H_\n#define BROTLI_ENC_DICTIONARY_HASH_H_\n\n#include \"../common/platform.h\"\n#include \"../common/static_init.h\"\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\n#include \"../common/dictionary.h\"\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Bucket is (Hash14 * 2 + length_lt_8); in other words we reserve 2 buckets\n   for each hash - one for shorter words and one for longer words. */\n#define BROTLI_ENC_NUM_HASH_BUCKETS 32768\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\nBROTLI_BOOL BROTLI_INTERNAL BrotliEncoderInitDictionaryHash(\n    const BrotliDictionary* dictionary, uint16_t* words, uint8_t* lengths);\nBROTLI_INTERNAL extern BROTLI_MODEL(\"small\") uint16_t\n    kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS];\nBROTLI_INTERNAL extern BROTLI_MODEL(\"small\") uint8_t\n    kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS];\n#else\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\") uint16_t\n    kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS];\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\") uint8_t\n    kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS];\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_DICTIONARY_HASH_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/dictionary_hash_inc.h",
    "content": "﻿const BROTLI_MODEL(\"small\")\nuint16_t kStaticDictionaryHashWords[BROTLI_ENC_NUM_HASH_BUCKETS] = {\n1002,0,0,0,0,0,0,0,0,683,0,0,0,0,0,0,0,1265,0,0,0,0,0,1431,0,0,0,0,0,0,40,0,0,0,\n0,155,8,741,0,624,0,0,0,0,0,0,0,0,0,0,0,0,66,503,0,0,0,451,0,0,0,0,0,0,0,835,70,\n0,0,539,0,0,0,0,0,0,0,0,0,113,0,0,0,0,718,0,0,0,0,0,0,520,0,1070,0,0,0,0,0,1515,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,610,0,0,750,0,0,0,307,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,964,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,999,0,0,0,0,0,0,0,0,\n645,75,0,649,52,282,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1621,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,211,225,0,0,687,718,0,0,110,0,58,0,0,0,0,0,0,345,0,0,301,0,0,\n0,203,0,0,1154,674,1949,0,0,0,0,0,0,0,0,0,259,0,0,0,0,0,0,0,1275,0,0,0,1231,254,\n0,0,0,0,0,0,0,277,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,0,0,800,0,0,0,29,\n116,100,490,0,0,0,0,0,1641,0,543,0,0,0,0,41,181,0,657,0,0,202,25,0,0,0,0,0,0,0,\n0,0,0,423,0,0,0,113,0,0,0,927,963,0,976,0,206,0,0,0,0,0,0,0,0,0,2002,0,0,0,0,0,\n0,0,0,0,0,0,696,0,1170,0,0,0,0,226,13,0,769,678,551,0,0,0,0,0,0,57,0,0,0,10,188,\n0,0,0,624,0,0,0,0,0,0,0,0,0,1941,130,0,0,0,0,378,269,0,0,528,0,1146,0,0,0,1105,\n0,1616,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,656,0,1940,0,0,0,0,0,173,0,0,0,0,0,0,0,0,0,\n0,0,457,342,810,0,0,0,0,620,0,0,0,0,0,0,0,967,95,447,406,0,0,0,477,0,1268,944,\n1941,0,0,0,629,0,0,0,0,0,375,0,0,0,1636,0,0,0,0,774,0,1,1034,0,0,0,0,0,824,0,0,\n0,0,0,118,0,0,560,296,0,0,0,0,0,0,0,0,1009,894,0,0,0,0,0,0,0,0,0,0,0,0,0,1474,\n366,0,0,0,0,0,0,0,0,0,79,1723,0,0,200,0,0,0,0,0,0,0,0,1759,372,0,16,0,943,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,900,1839,707,30,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,2004,0,0,10,115,0,50,0,0,0,0,0,0,0,0,0,0,520,1,0,738,98,482,0,0,0,0,\n0,0,0,0,0,0,701,2,0,0,0,0,0,0,0,0,557,0,0,0,0,0,0,0,0,0,347,0,0,0,0,572,0,0,0,0,\n0,0,0,0,0,832,0,0,797,809,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,861,0,0,294,0,0,0,109,\n0,0,0,0,0,0,0,0,1187,290,266,0,0,0,0,49,50,748,0,0,466,399,0,0,0,0,0,0,0,378,0,\n519,0,0,0,0,0,0,0,0,0,0,0,0,667,351,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,180,\n0,0,869,0,0,0,0,0,0,0,260,0,0,0,0,0,0,0,0,0,0,523,36,0,0,587,510,809,29,260,0,0,\n0,0,0,0,0,0,570,0,565,0,1464,0,0,0,0,0,0,10,0,0,787,399,380,200,0,0,0,0,516,0,\n844,887,0,0,0,0,0,0,0,44,0,0,0,305,1655,0,0,0,0,0,0,0,0,0,0,0,0,0,0,786,10,0,0,\n0,0,0,0,0,0,0,2031,0,0,0,0,0,684,0,0,0,0,0,1480,0,0,0,27,0,0,0,395,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,813,511,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,206,\n496,0,0,0,0,0,909,0,891,0,0,0,0,0,0,0,0,0,687,0,0,0,1342,0,0,0,0,0,0,0,0,0,0,\n160,41,0,0,0,0,0,0,0,0,0,0,0,1718,778,0,0,0,0,0,0,0,0,0,0,1610,0,0,0,0,0,115,0,\n0,0,0,314,294,0,0,0,983,178,193,0,0,0,0,0,0,0,0,0,174,0,0,0,0,0,0,0,0,0,0,848,\n1796,0,0,0,0,0,0,221,0,687,1660,0,0,0,0,262,0,0,179,0,0,0,0,0,66,0,773,0,352,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,152,0,0,1197,0,0,0,0,0,0,0,0,0,0,0,0,560,0,0,\n564,0,0,0,797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,819,0,0,0,0,0,0,0,0,719,544,\n637,5,0,0,0,0,0,0,0,0,0,0,0,101,0,1441,0,0,0,893,0,0,0,0,0,0,0,0,0,238,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,1296,0,0,969,1729,314,60,0,0,0,0,0,1144,0,1147,0,0,0,0,0,\n0,0,0,0,0,437,1853,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,828,0,176,0,0,0,0,0,0,434,39,0,\n0,0,0,0,159,0,0,0,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,270,0,0,0,0,801,556,0,0,\n0,0,0,0,0,416,19,197,369,0,0,0,0,0,0,0,0,0,28,34,0,757,0,0,898,1553,0,721,0,0,0,\n0,1012,0,0,0,0,1102,0,898,183,0,0,0,0,0,0,0,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,277,0,0,0,435,0,0,0,0,0,1311,0,0,0,0,\n0,0,211,437,0,0,0,28,0,0,750,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2012,0,702,\n0,808,0,0,0,0,739,166,0,0,0,0,0,0,719,170,500,0,0,0,0,0,0,0,0,1500,327,0,0,450,\n0,0,0,1318,0,0,0,1602,0,0,331,754,0,0,0,0,0,1368,0,0,557,0,0,0,799,850,0,0,0,0,\n0,0,0,0,908,0,0,0,0,0,19,62,459,0,0,0,0,0,0,0,0,0,0,0,0,1802,0,0,0,0,0,0,0,0,0,\n1397,0,0,0,0,120,238,0,0,0,0,0,0,0,0,0,0,0,1324,0,0,0,0,0,0,0,0,602,201,0,0,164,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,615,0,0,0,0,0,0,0,0,0,0,0,0,0,1243,0,0,0,0,968,0,0,\n0,0,0,0,882,0,0,0,907,329,100,0,0,0,0,0,0,0,0,0,0,0,176,26,9,0,0,265,256,0,0,0,\n0,0,0,0,0,0,643,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,610,0,0,0,0,973,2001,0,\n0,0,0,0,0,522,0,0,0,0,0,0,0,0,0,0,0,553,0,0,0,0,0,0,1582,0,1578,0,0,0,0,0,0,0,0,\n0,0,0,795,0,0,0,432,0,0,0,0,0,0,84,126,0,0,0,0,790,0,377,64,0,1529,0,0,0,0,530,\n1857,539,1104,0,0,0,0,0,0,0,0,0,0,0,0,977,0,0,0,34,0,0,0,0,0,0,0,0,0,0,0,24,26,\n0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,183,379,0,0,0,0,0,0,0,792,\n0,0,0,0,0,0,0,0,0,1920,0,0,0,0,0,0,0,0,0,771,0,0,0,1979,0,901,254,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,0,0,0,0,0,440,37,0,\n508,0,0,0,513,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,533,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,752,920,0,1048,0,153,0,\n0,391,0,0,1952,0,0,0,0,0,0,0,0,0,0,126,0,0,0,0,640,0,483,69,1616,0,0,0,0,0,734,\n0,0,0,0,0,0,480,0,495,0,472,0,0,0,0,0,0,0,0,874,229,0,0,0,0,948,0,0,0,0,0,0,0,0,\n1009,748,0,555,0,0,0,0,0,0,193,0,653,0,0,0,0,0,0,0,0,0,0,984,0,0,0,172,0,0,0,0,\n0,0,0,0,83,1568,0,0,384,0,0,0,0,0,0,0,164,880,0,0,0,0,0,0,0,0,0,0,0,367,121,0,0,\n828,0,0,0,0,0,0,0,1541,0,0,0,0,0,0,0,343,0,0,0,0,0,0,0,0,561,57,0,0,0,0,0,0,0,\n926,0,0,0,0,827,0,194,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,\n0,0,0,896,1249,0,0,0,0,0,1614,0,0,0,860,0,0,0,0,0,0,0,0,964,102,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,569,0,0,0,0,795,2045,0,0,0,\n0,0,0,104,52,0,0,0,0,0,604,0,0,0,0,779,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,\n494,0,677,0,0,0,0,0,0,0,508,0,0,0,0,0,0,0,0,0,1014,0,957,0,0,630,310,0,0,0,570,\n0,0,449,0,64,537,0,0,0,0,0,0,0,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,702,1650,49,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,1279,0,0,0,0,0,0,0,896,0,0,\n178,0,0,0,0,0,0,0,0,0,0,0,0,0,808,695,0,0,0,0,539,1117,0,0,0,0,0,0,0,0,257,0,\n1003,0,0,0,1,448,0,516,0,0,960,0,125,4,0,1268,30,748,0,0,852,0,0,0,6,0,0,848,\n236,1385,862,1811,0,0,0,0,698,803,0,0,0,0,0,0,0,610,992,0,0,878,0,1847,0,0,0,0,\n0,0,0,383,0,1404,0,0,0,0,986,0,347,0,0,0,0,0,0,0,0,0,0,0,592,572,0,1411,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,606,0,0,0,0,0,0,\n0,0,0,0,0,0,0,1829,0,0,0,0,0,0,0,0,0,0,0,0,700,748,0,0,0,0,0,0,365,0,0,127,0,0,\n83,198,0,0,0,0,0,0,864,55,0,0,0,0,726,1752,0,0,0,0,0,0,0,0,0,0,0,0,0,1066,0,764,\n0,0,0,0,683,0,550,309,0,0,874,1212,0,0,0,1364,0,986,381,723,0,0,0,1573,0,0,0,0,\n0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1559,0,0,0,0,493,133,0,0,0,0,148,\n119,0,0,0,0,0,0,537,14,541,0,635,126,0,0,0,495,0,0,0,0,861,998,1009,0,0,0,0,0,0,\n0,359,368,0,0,0,0,304,1577,0,0,0,0,0,1107,0,0,0,0,0,929,0,0,0,1142,0,0,0,0,289,\n175,0,432,0,219,0,0,0,0,0,785,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,0,0,0,\n931,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1323,0,0,0,0,290,0,559,1751,127,0,0,0,\n934,1167,0,963,0,260,0,0,0,573,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n580,1689,0,0,0,0,0,0,0,0,0,1164,0,0,982,1922,0,63,0,0,0,0,0,793,0,0,0,0,0,0,0,0,\n0,0,0,0,0,67,790,0,0,0,0,0,0,0,0,0,0,391,443,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,271,0,0,0,0,0,0,0,0,0,0,0,1140,0,0,0,0,340,300,0,897,0,0,0,0,0,0,\n0,0,0,0,890,0,0,0,0,818,321,53,0,0,0,0,0,0,0,0,0,468,0,243,0,870,0,0,0,1765,121,\n0,0,0,180,518,0,822,419,634,0,0,0,0,0,0,0,0,0,898,0,0,0,0,454,36,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,0,0,0,0,0,0,1326,0,104,0,0,0,0,0,0,0,\n0,0,260,0,0,0,0,0,0,0,0,0,0,0,0,542,45,0,0,263,1516,42,0,0,0,0,0,468,0,1005,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,288,87,0,0,0,0,0,0,0,0,502,988,133,0,0,0,0,0,0,\n141,0,0,872,1842,0,0,0,0,0,0,0,0,261,619,0,0,0,0,189,246,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,678,0,0,0,0,0,0,0,0,0,0,0,0,285,35,0,517,0,0,0,0,0,0,0,0,0,0,\n540,214,667,0,74,0,0,125,0,0,0,0,0,761,131,0,0,0,0,0,0,0,0,0,0,0,0,0,333,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1338,94,0,0,0,0,0,0,0,0,0,0,0,0,449,0,646,103,\n86,641,2028,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,869,87,277,117,39,0,0,0,0,0,0,0,0,938,\n297,0,0,0,0,558,464,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1608,0,\n0,0,0,0,0,0,1429,0,0,733,1010,0,0,338,1656,0,0,0,1038,979,2010,0,0,0,0,0,0,0,\n1005,0,0,121,0,0,0,219,20,0,0,0,0,0,0,872,1440,0,0,0,683,0,1070,0,0,522,0,0,0,0,\n439,669,0,0,0,0,0,0,0,0,1245,0,0,0,0,0,1218,0,0,547,233,0,0,0,0,0,0,0,0,0,482,0,\n0,0,0,0,0,0,886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,795,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,371,0,0,0,0,0,0,0,0,0,0,0,0,0,622,0,625,0,0,0,339,29,0,0,338,0,0,0,\n0,130,0,0,0,0,0,0,0,0,0,307,0,0,0,0,0,0,0,0,0,0,2044,0,0,0,0,0,0,0,0,308,770,0,\n0,0,0,0,1266,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,690,739,0,0,\n0,0,0,0,0,990,0,0,0,1831,0,0,0,0,0,0,0,0,0,0,0,0,0,613,0,0,0,0,0,0,0,0,0,0,0,0,\n0,763,0,878,0,0,0,977,0,100,0,0,0,0,0,0,0,0,0,463,0,0,0,0,623,318,0,0,296,463,\n137,0,0,454,0,0,0,1527,58,0,0,0,0,0,0,0,18,48,0,0,0,0,0,729,0,0,0,442,0,0,0,0,\n40,449,0,853,0,0,0,0,0,0,227,0,0,0,0,0,0,1491,0,0,0,0,0,0,0,0,0,0,161,55,0,450,\n0,1174,62,0,207,0,0,0,0,0,0,0,0,869,0,0,0,0,80,213,0,0,0,0,0,0,0,0,0,0,354,820,\n0,0,747,0,0,0,954,0,0,1073,0,556,0,0,0,692,0,191,0,804,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,831,162,0,0,35,0,0,0,0,0,0,0,0,1235,0,0,0,0,0,1234,0,0,\n0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,149,0,0,0,902,204,0,0,833,0,287,366,0,0,0,0,0,\n0,992,2020,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,784,0,0,567,\n630,0,0,0,539,0,0,27,0,0,0,0,0,0,0,0,0,0,755,0,0,0,0,0,0,0,0,0,0,0,0,814,0,0,0,\n0,0,0,0,0,0,0,0,0,0,987,0,0,255,761,194,0,1086,0,0,0,0,0,0,1016,0,0,1396,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,562,271,913,0,0,0,0,0,0,0,0,320,153,45,475,0,0,\n0,0,0,0,0,713,0,327,0,0,0,0,0,0,604,552,3,359,0,0,0,0,853,80,0,0,0,0,0,0,0,2016,\n6,887,0,0,0,0,975,0,961,0,0,0,0,0,916,1891,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,100,101,390,708,0,0,0,587,983,512,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,851,0,0,0,\n0,0,498,140,217,0,0,0,1448,0,0,0,0,0,0,0,0,0,905,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n643,105,0,792,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,0,535,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1748,0,0,0,0,0,754,0,0,0,0,0,0,0,0,0,0,0,0,91,0,0,1565,0,91,792,\n939,3,370,0,0,0,0,95,0,0,0,0,551,7,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1150,0,\n0,0,0,0,0,0,0,0,0,0,0,0,671,0,0,0,0,0,888,368,149,0,0,105,1134,0,983,0,0,458,31,\n0,643,0,0,0,312,0,740,0,0,0,1642,0,0,0,0,0,0,0,236,0,0,0,0,0,0,0,59,68,0,0,0,0,\n0,867,795,0,0,0,0,970,1977,0,0,0,0,0,0,0,1148,0,775,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,970,0,0,0,0,0,0,0,0,0,665,71,0,0,0,0,827,0,0,0,0,0,0,0,0,0,\n0,479,0,0,0,0,0,0,0,0,99,607,0,0,0,0,0,0,0,1960,0,0,0,793,0,0,871,41,0,0,241,94,\n0,0,0,0,209,0,0,1497,0,0,0,0,0,0,0,0,0,98,0,0,0,463,0,0,0,0,291,0,0,0,0,0,0,0,0,\n0,0,984,0,0,0,0,0,205,0,0,0,0,0,0,205,42,0,801,0,0,0,0,0,635,0,0,533,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,371,0,1282,0,0,0,825,0,0,0,0,0,0,0,0,0,357,879,467,0,317,0,0,\n0,0,0,0,0,924,0,0,0,0,849,1795,0,0,0,0,895,1799,43,0,0,0,0,0,0,0,0,0,0,1820,0,0,\n0,0,0,0,0,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,0,493,0,174,417,0,0,\n0,0,0,583,733,0,0,0,0,0,0,481,215,0,0,0,0,477,0,0,0,0,0,0,0,0,308,0,0,0,0,0,0,0,\n0,297,126,0,0,361,1551,0,0,0,0,0,0,871,1807,0,0,0,0,0,1307,0,685,0,0,0,0,0,0,0,\n797,0,858,0,565,0,0,0,0,0,0,0,0,0,0,0,0,434,252,826,0,0,0,0,0,0,791,0,0,0,0,509,\n231,178,601,0,0,0,0,0,0,0,0,43,1591,0,0,0,0,0,1683,0,0,0,0,45,0,0,0,0,0,0,0,0,0,\n0,1120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,494,0,398,0,0,0,1030,0,0,0,0,0,0,\n168,0,0,0,0,0,0,0,0,0,0,973,0,642,0,0,0,0,0,0,0,0,0,1615,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,378,594,0,1093,0,679,112,0,0,0,0,1492,540,1374,714,\n1486,0,0,0,0,825,1511,0,0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,736,143,0,700,0,1540,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1557,0,0,0,860,990,0,0,0,807,0,0,0,0,0,131,\n515,0,646,0,0,0,0,117,728,508,121,0,0,0,0,0,0,357,0,0,0,0,0,0,237,0,0,0,0,0,0,0,\n0,0,1784,0,0,0,0,0,0,0,0,0,0,0,713,348,1536,0,738,0,0,0,0,0,0,0,434,0,0,0,0,0,0,\n366,1877,39,0,0,0,0,0,0,580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,873,0,0,0,0,171,0,625,\n550,107,343,943,0,0,0,0,0,0,0,768,0,0,0,0,0,0,0,799,0,0,0,894,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1673,0,0,0,0,0,0,0,0,0,0,0,1052,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n272,0,441,0,0,3,9,0,0,0,1182,0,1346,0,0,0,0,0,0,0,0,682,0,0,1004,24,0,0,968,0,0,\n0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,0,0,0,578,\n474,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,530,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,556,0,0,0,0,0,0,16,1317,0,0,97,0,0,0,703,0,0,0,0,0,0,0,0,892,0,0,0,1571,0,0,\n426,186,0,1101,0,0,0,0,0,0,0,0,937,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,644,291,\n0,0,0,0,749,0,162,0,0,381,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,762,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,628,21,0,0,0,0,0,0,0,0,919,0,0,0,0,0,0,0,0,0,\n633,0,0,0,0,332,0,0,0,0,0,0,0,0,0,1489,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,832,398,0,645,0,0,0,13,0,0,0,0,0,0,0,0,0,0,20,0,800,0,0,0,0,0,0,0,0,0,\n0,0,0,0,1993,0,0,0,0,769,0,0,0,665,0,0,0,0,0,0,0,0,0,0,1426,0,0,0,0,60,0,0,0,\n641,1874,0,644,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1757,0,0,0,0,0,937,0,1652,0,654,0,\n0,0,0,0,0,0,527,0,0,0,0,0,0,0,0,0,0,0,0,0,226,0,0,0,0,0,1486,0,0,0,0,0,0,0,0,0,\n0,0,325,0,0,0,0,0,0,0,1345,0,0,91,0,404,0,0,0,0,0,0,0,0,0,0,0,0,973,0,0,0,0,0,0,\n0,1176,0,549,0,0,0,0,0,0,0,0,0,0,976,0,0,0,0,0,21,0,0,0,0,0,51,0,0,0,0,314,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,198,6,0,1093,0,0,0,0,0,0,0,0,0,\n0,0,0,0,1776,0,0,0,0,0,1528,0,419,0,0,0,0,0,0,0,0,76,138,0,0,0,0,638,29,0,0,0,0,\n0,0,0,1418,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1710,0,0,0,0,0,\n0,0,0,0,0,0,0,532,23,0,0,0,0,0,0,0,862,0,0,946,592,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,70,0,0,0,0,0,0,0,0,0,812,0,0,0,76,0,0,988,0,442,0,0,0,896,0,0,0,0,0,0,\n483,0,0,0,0,1709,0,0,0,0,0,0,119,0,0,0,117,0,309,0,0,0,0,0,596,976,0,0,0,0,0,0,\n0,0,0,0,0,768,0,0,0,0,0,0,0,0,0,518,0,0,0,0,0,0,0,0,0,0,0,0,0,0,863,0,0,0,24,\n145,1020,0,0,1984,0,0,0,0,0,0,0,658,0,0,0,0,0,0,0,0,0,0,106,1827,0,1010,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,582,87,0,0,0,0,0,0,0,267,0,0,0,703,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,496,0,0,0,0,1121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,561,0,0,0,0,0,\n0,0,760,0,0,154,0,0,0,255,0,419,323,0,0,0,0,0,368,0,0,0,0,0,0,0,0,0,0,522,0,0,0,\n0,0,0,0,551,562,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,0,0,0,0,\n0,0,0,284,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,958,0,0,594,0,0,0,0,0,0,6,479,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,820,1641,0,1556,0,0,0,0,0,0,0,302,0,0,\n0,0,0,148,0,0,676,0,0,0,0,0,0,1674,0,0,0,0,0,0,178,0,0,0,0,0,0,0,94,389,0,0,0,0,\n91,8,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,747,0,0,0,0,0,0,0,1746,0,0,0,0,\n0,24,0,1352,158,1530,0,0,718,130,280,1401,0,0,0,0,0,1946,8,0,0,0,0,1607,0,0,0,0,\n0,0,882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,417,0,0,0,1597,633,433,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,234,0,0,0,0,0,0,0,0,680,1950,0,0,0,0,249,5,0,0,0,\n0,0,0,0,0,0,1216,0,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,180,0,0,0,0,0,0,0,1002,\n0,0,0,0,0,0,0,0,0,0,0,0,0,931,0,0,0,0,0,0,0,0,747,943,0,1837,0,0,0,0,0,0,0,641,\n0,0,0,0,280,0,0,0,5,0,0,0,0,0,72,545,0,0,0,0,0,0,0,0,0,742,0,0,254,151,872,0,0,\n0,0,0,0,0,0,0,0,0,0,921,0,0,517,833,0,1680,0,0,436,251,584,0,0,0,0,0,0,0,0,0,0,\n0,24,500,0,0,0,0,0,0,0,0,195,1775,514,389,0,0,0,0,0,0,0,743,0,0,0,0,0,0,292,0,0,\n0,227,1283,774,1805,0,0,0,0,0,0,0,0,0,0,119,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913,\n1910,0,0,0,1826,490,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1162,700,30,\n0,0,0,721,839,0,0,0,617,0,0,0,0,0,0,0,0,0,169,428,0,0,0,0,0,1648,637,1205,0,0,0,\n1596,0,0,4,266,0,0,0,0,0,0,0,0,0,0,0,862,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,\n0,279,157,391,604,0,0,713,945,877,973,0,0,0,0,0,0,0,0,0,0,0,0,0,0,859,567,628,\n1846,0,0,0,0,0,0,0,0,0,762,0,0,191,0,0,0,0,298,0,0,767,909,0,0,0,0,0,0,0,795,0,\n0,301,0,0,1970,0,0,0,0,0,0,0,0,0,1236,0,0,0,0,0,0,644,369,15,0,160,71,0,0,0,0,0,\n1447,0,0,0,0,0,0,0,0,735,1255,76,0,0,0,0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,0,\n841,0,0,0,0,0,0,0,0,0,0,836,0,0,0,0,0,1622,0,0,735,0,0,0,0,1601,804,1390,394,0,\n0,0,0,0,0,96,0,289,0,0,35,688,0,0,0,667,0,513,0,0,0,0,0,0,0,2034,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,704,0,1524,0,1078,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,306,\n0,0,0,0,0,0,0,431,0,1196,0,0,54,0,15,1448,0,1418,0,0,0,0,0,0,0,0,0,907,0,0,0,0,\n0,0,194,1767,0,0,0,0,0,840,0,900,0,0,0,0,0,0,0,0,0,0,0,1436,0,0,0,0,642,1560,0,\n0,0,0,0,0,94,386,0,0,0,0,0,0,0,0,0,0,830,416,0,0,20,731,0,0,0,0,0,0,0,0,697,0,0,\n662,0,0,0,0,0,0,0,0,0,861,0,0,0,0,0,0,0,871,671,864,0,928,7,0,332,0,0,0,0,1055,\n0,0,0,0,0,0,986,0,0,0,0,0,44,76,0,0,0,0,0,0,0,0,0,0,300,0,0,0,0,0,0,0,175,518,\n831,1108,0,0,0,836,0,1852,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,843,1804,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,246,0,0,0,610,202,0,0,36,0,0,0,240,654,13,0,0,0,0,0,0,0,\n0,391,0,403,0,0,0,0,0,0,0,0,0,0,75,0,366,815,0,0,631,0,0,0,0,0,0,0,0,345,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,0,0,0,0,0,0,0,0,0,673,35,662,0,287,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,5,34,0,0,0,0,0,0,0,0,151,0,427,0,0,382,0,0,0,329,0,0,279,0,0,0,\n0,0,0,0,0,0,0,906,0,0,366,843,0,1443,0,1372,992,0,36,123,0,649,0,0,0,0,0,767,0,\n1018,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,995,0,0,0,0,0,0,0,72,368,0,0,1345,0,0,0,\n589,0,0,0,0,0,0,0,0,0,1988,0,0,220,541,0,0,0,686,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,32,196,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0,0,0,1452,0,\n0,0,616,0,0,0,0,0,0,0,0,0,1229,0,0,0,0,0,0,0,0,0,0,667,120,0,0,0,0,0,0,0,1146,0,\n0,0,0,0,0,0,0,0,0,0,352,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,935,0,1050,0,\n147,88,0,0,923,0,0,0,0,0,934,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,341,222,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,\n637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1159,0,0,0,847,0,0,0,0,0,0,683,0,867,944,0,0,\n0,0,0,1809,0,0,0,0,0,0,0,0,0,0,395,170,0,0,0,0,0,0,0,0,0,0,618,535,0,1625,0,0,0,\n0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,778,0,0,0,0,0,46,0,2032,0,0,37,\n1458,0,938,363,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,889,0,0,0,0,0,0,0,\n0,0,0,0,462,0,0,0,0,525,0,0,23,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0,\n0,498,725,0,0,0,0,7,0,0,0,0,773,0,0,0,164,0,0,0,0,0,0,0,0,936,583,659,1462,0,\n220,0,0,0,0,803,0,0,544,119,0,0,0,0,0,0,0,0,0,0,0,181,176,0,1192,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,1878,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,0,0,0,\n944,0,0,0,0,0,0,0,273,0,0,0,0,0,855,0,0,0,0,5,127,0,0,0,0,0,0,0,0,752,230,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,162,0,654,48,156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197,\n0,0,0,0,0,0,0,963,0,0,0,0,0,0,0,0,0,0,858,0,0,0,0,0,0,0,0,0,0,676,1978,0,0,102,\n972,0,0,0,0,0,0,0,361,0,461,0,0,0,472,0,0,0,0,0,0,0,0,0,0,0,0,0,0,747,905,0,0,0,\n155,0,0,0,0,0,0,0,0,0,0,319,163,0,0,0,0,0,0,0,0,0,848,0,0,36,631,0,0,0,0,0,1769,\n0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,555,247,0,0,\n996,0,0,189,0,0,0,0,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,0,0,0,526,746,0,0,345,0,0,0,\n1017,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,651,428,0,0,0,1162,230,327,546,792,0,0,0,\n1203,0,0,0,0,0,0,0,0,0,672,189,0,0,0,0,0,0,99,0,0,0,298,0,0,0,0,0,0,555,397,0,0,\n0,0,0,1157,0,0,0,0,0,0,0,0,0,0,398,1523,0,366,0,0,787,0,0,0,282,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,157,0,941,0,0,0,0,0,1336,0,0,116,0,0,0,0,0,0,787,0,0,0,0,0,0,0,0,0,\n0,170,160,0,1815,0,0,0,0,0,866,0,0,0,0,0,0,0,0,0,689,0,0,0,0,820,0,498,108,0,0,\n0,1119,0,0,0,244,609,1005,0,581,0,0,0,0,0,895,0,0,0,1898,0,0,0,0,0,926,0,0,0,0,\n0,0,0,0,0,0,0,0,0,538,496,294,301,0,0,0,18,0,0,757,0,0,0,0,0,1263,0,820,0,722,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2028,0,0,0,0,124,1875,0,0,0,881,0,0,0,1348,\n0,0,0,0,0,0,0,911,0,954,0,0,0,0,414,0,0,0,0,517,0,0,0,0,0,816,0,0,0,0,0,0,0,0,\n713,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,593,150,0,0,0,0,\n0,553,0,0,0,0,0,0,0,0,0,0,108,0,0,0,0,420,0,0,0,0,0,0,0,0,0,0,0,1777,0,0,55,493,\n0,0,81,0,321,980,0,0,0,0,0,0,0,0,0,0,0,0,0,0,362,112,0,74,0,0,0,0,0,0,0,625,0,0,\n0,0,0,0,377,16,0,0,61,281,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,1031,0,0,0,0,0,0,51,0,\n0,0,0,0,0,0,211,309,15,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,789,173,0,439,9,648,\n0,0,294,0,0,0,0,0,0,0,374,8,0,1099,0,0,0,0,0,0,0,575,0,0,0,518,0,0,0,702,0,0,0,\n0,0,0,87,0,0,0,438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,464,122,0,0,0,1802,0,0,0,0,\n0,0,499,0,0,0,87,476,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,840,283,0,0,0,0,1620,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,609,1160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600,\n323,372,0,0,0,0,471,722,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,\n477,1304,0,1774,0,0,88,0,438,12,0,0,0,0,0,0,0,0,671,997,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,639,22,0,0,782,681,0,0,0,0,0,0,0,0,0,0,1013,664,0,942,0,1349,0,0,0,0,0,0,0,\n0,0,0,0,0,356,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,289,0,1975,\n109,450,0,0,0,0,0,0,0,0,0,0,705,0,0,664,0,0,0,0,0,0,0,1238,0,0,318,0,0,0,0,0,0,\n0,0,0,0,0,0,0,960,1872,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,0,0,0,0,0,0,0,0,0,239,\n777,0,26,0,0,0,0,0,0,0,0,0,0,0,0,375,414,0,17,0,0,0,1350,0,955,0,0,0,0,0,0,0,0,\n887,960,0,0,0,0,0,0,0,0,0,0,708,710,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,919,0,0,0,\n0,502,280,7,45,0,0,0,0,777,0,0,0,0,410,0,1110,0,0,0,0,0,0,414,341,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,787,0,0,0,436,0,0,0,0,0,0,0,1707,613,377,96,0,0,0,0,451,\n0,0,0,0,0,0,0,0,0,0,0,0,0,680,0,483,916,0,0,0,0,0,0,937,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,739,0,0,0,0,0,0,0,0,82,0,0,663,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,128,0,0,0,0,0,0,0,0,1087,0,0,0,0,0,0,0,503,0,0,0,0,0,0,9,113,104,324,0,460,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,935,702,434,485,1014,949,423,0,900,\n0,0,0,0,0,0,0,2018,574,0,0,0,0,0,0,0,0,0,0,0,0,1206,0,0,0,0,0,0,0,0,38,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,1022,0,0,0,0,143,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,2029,0,0,0,0,0,0,0,0,0,0,0,0,523,0,0,0,0,0,0,625,0,0,425,37,0,0,0,1943,0,0,0,\n0,0,765,0,0,0,0,0,0,0,0,0,0,551,0,0,0,0,0,0,0,0,0,0,0,0,168,0,0,1010,0,0,1994,0,\n0,0,91,0,0,0,0,532,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1884,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,240,15,0,0,0,1227,0,1534,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,\n0,0,0,0,0,0,0,0,0,0,0,655,562,395,0,0,0,501,1019,0,0,0,0,509,267,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1099,0,0,0,0,0,0,948,0,0,0,0,0,0,0,\n462,114,0,0,258,404,0,1717,0,0,0,0,82,1061,0,724,0,0,0,0,0,1133,0,0,0,0,0,0,\n1021,841,0,1021,0,0,0,0,0,0,0,0,0,0,488,373,37,0,0,0,0,564,0,0,0,0,0,513,0,0,0,\n825,0,0,899,0,0,778,0,0,12,1417,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,545,0,5,\n0,0,0,0,0,0,0,192,0,0,763,0,0,0,0,0,0,0,755,759,0,0,0,0,0,0,0,0,0,370,0,1237,0,\n0,0,0,0,0,298,87,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,\n0,0,0,0,814,991,0,757,57,0,0,0,0,0,0,0,0,0,540,0,0,0,0,608,0,0,0,0,0,0,0,0,1014,\n0,0,0,902,0,0,0,0,553,1668,0,0,0,0,0,0,0,0,0,559,60,0,0,0,0,0,511,0,0,675,0,0,\n156,0,0,0,0,0,0,709,0,698,0,0,0,1745,0,0,0,0,0,0,0,0,0,714,0,0,0,0,0,0,0,0,206,\n8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,776,0,0,0,0,0,0,0,0,0,1272,0,0,\n0,0,0,1059,0,0,0,0,0,0,406,0,0,0,0,0,0,0,0,0,0,947,0,0,0,0,0,0,168,0,0,0,0,0,0,\n870,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,554,0,0,0,0,784,908,0,0,0,0,0,0,\n0,396,358,0,0,0,0,0,0,0,0,2,228,0,0,0,0,0,0,0,0,0,0,0,845,14,0,716,1820,594,0,\n81,1428,0,161,0,782,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,998,0,\n0,0,0,0,0,0,0,0,0,0,0,1043,0,1496,0,0,0,0,0,0,0,0,781,0,0,0,0,0,0,0,817,1114,0,\n1814,958,0,0,0,0,812,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,236,643,0,0,0,0,0,0,0,0,0,1172,0,0,0,0,0,0,0,0,0,1338,0,0,0,\n0,0,0,0,0,0,0,0,54,0,0,0,256,0,0,351,0,955,1885,0,469,0,0,0,1270,0,744,0,313,0,\n0,0,0,0,0,0,0,402,969,0,0,0,0,0,0,50,0,0,0,0,572,0,0,0,0,847,0,0,0,0,0,0,0,248,\n43,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,766,0,363,0,0,0,0,0,0,0,0,0,0,0,678,0,0,409,\n258,82,249,0,0,0,0,0,0,0,0,0,0,0,0,32,393,0,788,0,0,0,1281,509,1968,0,0,0,0,39,\n291,0,0,0,589,0,0,54,1059,0,0,0,0,0,0,824,0,0,0,0,0,0,0,0,0,0,1005,0,1598,0,0,0,\n0,0,919,0,0,0,0,0,0,0,0,52,132,0,0,0,0,0,328,0,0,0,0,173,0,0,0,0,0,65,1411,0,0,\n0,0,0,0,0,0,0,0,442,0,842,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0,0,0,845,\n210,0,0,0,0,0,0,0,0,892,0,0,223,0,0,0,0,529,0,0,0,807,0,137,218,0,1444,0,0,0,0,\n0,332,661,0,0,0,0,0,0,0,76,1517,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,0,0,0,0,0,481,\n379,0,0,0,0,0,149,18,0,0,0,0,0,0,0,0,742,304,142,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,799,925,195,51,0,0,0,0,688,0,0,0,0,697,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,1169,751,0,0,0,452,929,0,221,0,1437,0,0,0,0,955,1251,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,132,0,0,0,0,0,865,0,0,0,0,0,0,0,767,\n672,42,0,0,0,1050,0,0,0,0,0,0,0,0,368,44,0,0,0,0,0,0,0,570,29,0,0,0,0,0,0,227,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,522,0,0,0,0,0,0,0,1529,0,0,0,0,0,0,739,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1667,0,0,0,0,0,0,132,511,0,138,208,1020,0,0,23,565,0,344,0,0,0,\n0,0,922,0,0,0,0,0,0,0,240,0,0,415,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,402,0,0,754,31,716,0,982,731,0,0,0,0,0,0,0,888,0,0,0,803,847,0,0,823,\n0,0,0,0,0,0,785,0,0,2,0,0,0,0,0,0,0,532,0,0,681,0,0,314,0,384,684,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,649,447,0,1818,1007,0,321,0,66,360,0,0,0,385,0,0,0,0,0,0,\n0,900,73,254,0,0,0,0,683,1959,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,86,0,0,725,0,0,0,0,0,196,0,0,0,0,0,831,0,0,0,0,723,0,0,0,0,0,994,627,0,0,\n0,0,0,0,0,0,0,0,764,66,0,0,0,0,205,36,0,0,0,0,0,0,0,950,0,0,0,887,111,0,0,831,\n388,165,0,0,0,0,0,155,0,0,0,0,0,0,0,0,0,0,0,0,0,0,780,755,0,0,0,0,898,146,0,0,0,\n0,0,0,0,45,7,0,0,0,0,0,0,0,0,607,0,0,0,0,0,0,65,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0,\n621,600,0,367,0,0,0,0,0,0,0,561,0,559,0,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,672,157,0,0,0,0,714,0,0,0,\n0,0,456,0,925,0,0,0,0,0,0,0,0,19,0,0,0,0,1473,0,0,0,0,0,0,0,0,0,0,113,0,0,0,0,0,\n0,0,0,0,0,0,0,0,69,463,0,0,82,193,2,471,0,0,0,0,633,0,0,0,0,0,0,1148,129,1392,\n542,803,0,0,0,0,0,0,0,0,0,0,0,0,438,0,0,0,0,0,0,875,0,0,0,0,0,237,0,0,0,0,0,0,0,\n65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,563,0,0,0,9,444,0,0,43,1260,0,0,0,0,0,0,\n971,0,0,699,0,0,0,0,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,829,242,0,\n0,593,0,0,0,0,0,0,0,0,201,36,224,0,0,0,0,0,0,1430,0,1806,0,523,0,0,212,1889,0,0,\n0,827,0,0,0,0,0,2043,136,242,0,0,0,0,0,0,284,148,10,0,0,0,0,0,0,1249,0,0,0,807,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,0,0,0,494,0,0,0,0,0,0,0,0,1510,0,0,0,0,0,\n0,0,0,0,0,505,1306,0,0,764,268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1703,0,0,0,0,159,964,583,0,0,0,\n0,0,0,515,0,0,854,0,0,0,0,0,0,0,0,0,0,0,0,1123,0,0,0,0,0,0,0,136,0,0,0,0,0,1782,\n0,0,44,1287,0,0,0,0,0,732,0,0,0,0,313,679,0,0,316,0,0,0,0,595,0,0,0,0,0,0,753,\n147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,137,0,0,0,0,414,0,1762,0,0,0,0,0,0,0,0,\n0,0,0,599,0,0,0,0,0,0,0,0,0,1749,0,0,0,1627,0,488,0,0,0,0,0,83,0,0,0,0,676,0,0,\n1639,0,0,0,0,0,0,0,0,0,278,0,0,0,0,0,0,97,0,14,1085,0,0,0,0,0,0,781,388,0,849,\n59,229,0,0,0,0,0,1115,0,0,0,0,108,0,0,0,0,700,0,0,0,0,0,0,0,0,0,1414,0,0,0,0,0,\n0,0,0,0,0,0,0,0,660,737,1035,0,0,0,0,0,0,521,690,0,0,0,0,0,0,0,0,0,0,0,0,272,0,\n0,0,0,0,0,0,0,0,0,1744,0,0,0,0,0,0,128,733,0,0,277,0,0,0,0,0,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,0,0,0,0,936,1981,40,0,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,306,0,0,0,0,\n0,0,0,979,0,0,0,0,0,611,0,0,0,0,0,178,0,0,0,1969,0,0,0,0,0,0,0,664,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,390,0,0,0,1510,0,0,0,0,0,0,0,0,0,0,0,493,0,0,37,0,0,0,0,724,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,1537,0,0,168,473,0,0,0,105,0,0,0,0,\n627,438,0,0,0,0,0,0,0,0,0,0,11,1256,0,0,0,1626,0,779,0,0,0,0,25,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,308,0,0,0,0,0,741,0,671,0,0,0,0,649,150,0,0,99,521,0,0,3,339,0,0,0,\n543,0,0,0,0,0,0,0,0,0,1358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,234,155,\n0,0,0,0,0,0,0,1628,0,766,0,0,0,0,0,0,0,0,0,0,0,0,0,829,0,0,0,1445,0,0,0,486,0,0,\n0,0,2,1635,0,0,0,0,558,0,0,0,0,0,0,0,0,0,0,1461,0,0,0,0,0,599,0,0,0,0,0,0,0,0,0,\n1376,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,0,0,0,0,0,0,447,0,0,66,1432,0,0,0,0,\n0,0,307,0,413,609,0,0,0,930,0,0,0,0,21,939,0,0,0,0,0,962,4,651,0,0,0,0,15,579,0,\n0,0,0,0,597,0,0,0,0,0,981,0,0,0,545,0,0,0,0,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,800,17,0,0,17,0,907,0,0,0,110,0,0,0,53,458,0,1983,0,0,0,0,0,0,0,0,0,0,443,0,\n0,0,0,0,0,0,0,0,0,0,924,1844,0,1232,0,0,0,0,70,519,0,993,0,0,0,0,0,0,14,530,0,\n907,0,0,0,0,0,733,0,0,0,0,0,0,0,0,55,0,188,531,56,0,0,1693,0,0,0,0,0,0,0,0,441,\n0,192,928,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1525,0,259,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,512,185,0,464,1603,0,0,0,0,0,0,0,0,0,0,0,1113,\n284,720,0,0,722,0,0,0,0,0,13,0,0,0,0,0,0,0,4,289,43,0,0,0,0,0,0,1694,0,0,0,0,\n193,0,0,0,0,409,0,0,0,0,0,0,0,0,0,0,0,0,308,0,0,1863,0,0,0,0,0,0,0,0,0,790,0,0,\n745,1002,0,0,0,0,0,0,0,0,0,289,68,477,13,0,0,0,0,0,0,0,0,0,0,609,0,0,0,0,0,0,0,\n0,0,0,0,367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,0,0,0,0,0,0,694,58,\n548,0,0,0,0,0,0,687,0,0,0,0,1749,0,0,0,0,0,0,0,0,1004,661,0,0,0,0,0,0,445,0,0,0,\n74,0,0,0,0,213,0,0,0,0,0,0,0,0,0,0,0,0,0,834,0,0,189,1672,0,0,0,0,0,0,0,1548,\n192,0,0,0,0,0,0,0,0,0,0,0,0,0,32,751,0,78,0,0,0,0,0,0,544,1602,105,473,0,0,0,0,\n0,0,156,1949,0,1779,0,0,0,0,0,0,0,0,0,0,0,763,0,0,0,0,0,0,0,0,29,0,0,0,0,0,0,0,\n0,0,0,883,0,0,0,0,0,0,0,488,0,617,0,0,50,0,694,1518,785,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,546,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,1016,0,0,0,577,0,0,0,0,0,0,\n184,935,114,720,0,0,100,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,95,14,0,969,0,0,0,0,0,0,0,\n727,0,1021,0,0,0,0,0,1190,0,0,0,0,0,0,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,0,0,798,0,\n587,0,0,695,42,0,1929,141,957,0,465,7,908,0,0,450,148,0,0,0,1166,0,0,0,0,0,0,0,\n0,0,0,0,0,253,0,1003,0,0,0,0,0,0,0,0,0,0,0,46,0,0,879,0,806,0,1868,0,0,0,0,0,\n1846,0,0,0,730,0,0,0,0,0,0,0,965,0,0,0,0,506,0,0,0,10,0,0,0,22,0,0,0,0,0,0,0,0,\n0,0,0,0,0,960,296,0,0,0,0,0,0,0,0,0,0,0,587,0,0,0,0,20,0,0,0,32,982,0,0,0,0,0,0,\n0,0,0,0,941,0,0,0,0,435,0,0,0,0,0,0,71,419,0,0,0,0,0,0,688,740,94,345,0,0,679,\n582,0,0,0,0,0,0,0,945,0,0,0,0,0,0,0,0,0,0,0,0,539,0,684,1993,0,0,0,659,0,583,0,\n803,0,704,0,0,0,0,0,198,181,347,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,481,405,203,0,0,99,826,0,0,0,0,0,0,0,492,0,408,0,0,0,0,0,0,0,0,0,0,4,0,0,\n0,0,665,349,137,0,0,0,0,612,1270,0,0,0,0,0,371,0,0,0,826,0,0,0,0,21,1535,858,\n374,0,0,0,0,0,0,311,0,0,0,991,1968,0,0,0,0,494,1647,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,769,0,0,0,0,0,642,0,0,157,123,0,0,0,1435,0,0,0,0,0,0,0,0,0,0,79,0,0,0,\n0,0,0,1425,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,106,393,486,1690,0,0,0,0,\n0,0,0,0,0,0,0,0,756,184,0,0,0,1382,0,0,0,175,0,1493,0,1007,0,0,0,0,0,0,0,0,0,0,\n0,219,0,0,0,0,515,99,0,851,0,0,0,0,0,1278,0,0,0,0,0,0,0,1000,982,0,762,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,910,1819,0,0,0,0,0,0,906,0,0,0,0,0,0,0,0,0,0,1730,0,0,\n0,0,0,0,0,0,0,0,0,1185,0,0,0,0,0,0,0,0,40,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,0,0,\n650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,30,0,553,0,0,20,597,0,1614,0,0,0,0,0,327,\n49,0,0,0,0,0,0,0,78,0,0,786,134,0,0,0,12,496,0,0,0,0,0,0,0,0,0,0,42,204,0,614,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,147,247,0,0,0,0,942,0,0,2023,0,0,0,0,\n0,0,67,285,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,532,0,0,0,0,0,0,0,\n1692,0,0,0,0,55,1704,0,0,0,0,988,0,0,0,223,0,0,0,0,0,0,0,57,1123,0,0,0,0,0,1764,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2015,0,0,0,1599,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0,\n0,0,504,621,1248,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1397,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,441,75,0,0,0,0,0,0,0,0,0,0,841,0,0,0,0,0,693,0,650,314,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913,0,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,475,0,\n0,1016,179,602,111,329,0,0,0,1864,0,0,0,0,846,1888,0,0,780,0,0,0,82,0,0,0,0,821,\n0,0,0,0,0,0,0,0,0,0,0,956,112,0,0,0,261,455,0,0,0,0,0,0,337,385,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,184,1865,0,0,721,16,0,486,0,0,0,265,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,621,0,0,0,0,0,0,0,0,234,0,0,815,0,0,743,\n1987,205,197,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,219,452,589,0,\n176,333,0,0,0,0,0,0,0,1110,47,0,0,0,0,0,0,0,0,0,0,0,864,0,0,300,0,1237,0,0,0,0,\n0,0,0,0,0,0,0,1685,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,135,395,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,631,0,0,0,0,0,0,835,0,0,0,606,459,0,979,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,612,0,0,0,0,0,0,0,0,158,372,0,854,0,0,0,0,0,\n0,0,1492,0,0,0,833,0,0,0,0,0,0,0,1739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n195,0,0,0,0,0,0,0,0,730,1997,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,266,751,0,0,0,0,0,\n0,0,821,0,0,0,715,0,0,0,868,0,959,0,0,0,0,0,0,0,0,0,0,0,1053,0,0,0,950,0,1081,0,\n1595,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,47,684,0,0,0,0,0,0,1606,0,777,0,1020,0,0,0,\n1094,0,0,0,0,0,0,0,350,0,0,0,0,0,0,242,1812,0,0,0,967,0,0,0,473,286,0,0,0,0,0,0,\n798,629,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,513,337,306,0,0,0,0,0,0,0,0,0,\n146,0,0,1646,0,0,0,0,0,465,0,0,0,525,0,0,0,0,0,0,299,165,0,0,0,0,0,0,0,1064,0,0,\n0,0,0,596,0,0,0,0,0,0,0,0,0,0,0,0,0,0,238,1741,0,1233,451,1824,0,0,0,0,733,495,\n0,0,0,0,0,1204,0,0,0,559,341,0,224,21,0,0,0,0,0,0,0,0,97,1446,0,0,0,0,0,0,0,729,\n0,0,565,727,0,1948,0,0,0,519,0,0,0,0,0,0,0,0,0,1193,0,0,0,0,0,0,790,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,323,2,201,0,0,59,0,0,34,0,896,961,0,1285,0,0,46,0,479,0,0,\n0,0,549,0,663,0,0,0,0,0,783,65,682,0,0,0,0,0,11,0,0,0,0,0,522,0,0,0,52,0,0,0,0,\n0,383,0,0,0,0,0,0,0,0,127,0,0,0,0,0,397,194,0,0,635,0,0,0,0,0,0,0,0,0,0,975,0,0,\n0,0,0,0,0,0,0,0,116,0,51,0,0,858,0,1075,535,448,0,0,0,0,0,610,0,0,0,0,0,0,0,0,0,\n0,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,267,673,319,94,92,0,551,0,0,218,\n1406,69,256,0,0,952,1980,0,833,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,81,0,0,\n0,352,634,0,0,0,0,0,618,0,0,0,0,0,0,73,339,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,759,\n0,0,0,0,0,0,0,0,0,0,0,0,0,1075,0,0,0,0,0,0,482,649,0,0,0,0,0,0,0,0,386,336,0,0,\n0,1035,0,0,0,0,0,0,0,0,0,0,0,924,0,73,0,0,0,0,0,1971,0,0,0,0,0,0,0,0,0,1344,0,\n501,0,0,0,0,0,0,0,0,46,799,0,0,0,0,0,0,0,276,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,0,\n0,0,0,0,0,158,0,0,0,0,0,1432,0,0,0,0,0,0,0,0,0,0,25,0,0,2001,0,0,0,0,0,0,0,0,0,\n0,0,0,0,478,0,0,0,0,0,0,91,1461,211,602,0,0,0,0,0,0,0,0,0,1068,0,0,124,567,0,0,\n0,1006,0,0,0,0,0,0,0,0,0,735,812,0,0,323,0,0,0,304,0,0,0,0,0,0,0,0,0,148,0,0,0,\n0,0,0,0,0,0,523,0,0,144,730,0,0,981,0,0,111,0,0,132,0,0,0,0,0,0,890,0,0,0,0,0,\n444,0,1787,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,2041,932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,937,0,995,0,0,255,0,0,138,863,965,0,0,631,0,0,0,0,1394,16,652,0,0,0,0,0,0,\n0,0,0,0,0,0,0,897,0,321,0,0,0,0,0,922,0,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,844,0,0,0,0,0,0,1659,0,1100,0,0,0,1173,0,1930,268,251,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,390,711,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,0,0,0,0,624,0,0,0,\n1998,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1125,0,0,0,594,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,268,0,0,0,0,0,0,0,563,0,0,0,0,0,0,0,0,2,39,0,0,0,1332,0,0,0,0,0,\n0,0,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,796,0,0,0,0,527,0,0,0,0,98,0,0,576,0,\n0,0,0,0,122,0,276,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,0,\n0,0,0,0,0,0,0,290,0,0,762,1292,0,0,0,1315,0,1955,0,0,0,0,0,0,0,0,0,0,210,131,0,\n0,0,0,797,0,38,0,11,488,0,936,0,441,0,0,0,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n991,0,0,0,0,0,0,0,0,0,0,0,653,0,523,0,0,0,903,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,\n0,0,0,0,0,0,432,0,0,314,0,0,0,0,232,1368,534,0,0,0,0,0,27,0,0,0,12,0,0,0,0,0,0,\n0,0,0,264,736,0,1657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1117,0,127,0,0,0,1208,0,1294,\n0,0,0,0,364,0,0,0,0,0,125,1334,0,0,0,0,0,0,0,0,0,0,0,0,0,0,792,0,0,0,0,0,0,0,\n849,699,0,0,0,0,0,968,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1446,\n124,397,0,0,0,0,0,0,0,0,0,0,0,641,0,0,0,0,0,0,0,0,0,0,0,0,127,346,0,0,517,75,0,\n0,0,0,0,0,0,0,83,0,0,0,0,0,0,1031,0,0,0,0,0,0,0,1470,0,954,0,0,345,304,410,0,0,\n0,0,734,0,0,0,0,0,1822,0,0,0,1798,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,161,\n1865,69,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,0,0,0,541,0,627,0,0,0,0,0,0,0,0,0,166,0,\n0,0,0,0,0,0,0,0,849,0,0,0,0,0,0,0,717,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600,0,0,0,0,0,\n0,654,0,0,188,273,0,0,0,543,0,410,87,0,0,941,0,0,186,250,0,1785,0,0,0,0,0,1339,\n462,961,0,780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,0,0,474,1276,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,24,948,0,0,0,0,657,753,0,0,0,0,941,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,706,985,837,0,1861,0,0,0,0,0,0,0,0,0,0,0,0,0,0,292,933,0,0,0,0,0,\n0,0,0,0,767,0,0,0,0,0,0,0,641,0,0,0,1233,114,0,883,0,274,2008,0,1794,285,0,0,\n571,0,0,0,0,0,0,0,0,0,0,823,960,16,617,0,431,0,0,0,0,0,0,0,0,0,0,567,0,401,0,2,\n781,424,33,0,2006,0,0,274,0,0,1882,0,794,0,0,0,1848,0,0,0,0,0,0,448,47,0,0,0,\n1199,0,0,0,0,0,0,0,0,417,0,0,0,0,0,0,0,0,0,0,295,0,0,0,0,0,0,0,1019,0,0,0,0,0,0,\n0,0,0,0,0,0,0,620,0,0,0,0,464,0,0,0,0,208,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,442,0,930,0,0,0,0,0,516,68,0,0,0,0,0,1128,104,0,0,0,0,0,0,0,0,787,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,491,0,0,0,0,0,0,711,0,0,9,0,101,441,0,0,0,0,0,0,0,0,\n0,0,160,396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,679,326,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,1128,0,0,0,0,0,737,0,1796,0,0,0,0,0,0,0,0,0,0,0,0,338,574,0,0,\n0,0,0,1096,491,405,0,0,0,0,0,1081,0,0,0,0,0,0,0,0,0,0,0,0,0,1676,0,1207,0,0,0,0,\n0,0,969,354,0,0,0,0,598,0,297,0,0,0,0,0,0,0,0,1772,751,0,37,0,0,1828,0,0,0,0,0,\n0,0,0,0,257,191,582,0,0,0,0,0,0,790,0,0,0,0,0,47,0,0,0,0,0,0,0,449,306,1011,0,0,\n0,0,0,299,0,0,0,0,0,0,837,0,0,0,0,0,0,10,329,0,0,0,0,0,1320,0,0,0,0,0,0,158,657,\n0,1191,0,0,0,0,0,0,7,0,974,1939,0,1665,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,288,\n66,0,0,0,0,494,175,0,1643,0,0,0,0,0,0,0,0,570,750,719,0,0,0,0,0,0,0,0,0,0,0,0,0,\n13,0,0,1247,0,0,221,356,0,0,0,0,0,0,0,0,0,0,694,1809,0,0,0,0,0,0,0,411,0,44,31,\n0,0,0,0,669,0,673,0,0,0,0,0,0,0,0,0,1303,704,299,0,0,0,275,0,0,216,1761,0,0,0,0,\n0,0,0,0,0,0,0,1319,0,0,428,0,0,0,0,0,0,0,0,0,0,514,0,0,0,0,0,0,49,55,102,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,364,0,0,0,0,379,0,921,971,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1258,0,0,0,1058,0,0,0,0,0,656,0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0,\n0,1373,10,605,0,0,0,0,0,0,0,838,0,1012,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154,365,0,0,\n0,0,0,0,0,0,0,340,0,0,0,0,0,810,0,0,0,0,0,0,495,0,0,0,0,0,0,0,0,0,261,0,535,248,\n0,358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,567,445,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,697,0,0,0,1336,0,0,0,0,0,0,0,0,917,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,972,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,351,0,0,0,0,0,0,0,0,0,0,\n0,0,0,286,0,0,56,438,0,0,0,0,0,1950,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,738,0,0,0,0,0,\n0,0,0,0,0,969,2047,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,866,0,0,0,0,0,0,0,1467,0,0,0,\n0,0,0,0,0,0,0,0,0,0,972,0,355,0,0,0,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,267,189,104,0,0,0,0,1613,0,0,0,0,0,0,0,116,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,886,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,863,0,0,0,0,0,\n0,0,1953,450,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0,\n0,0,0,0,0,1142,0,1189,0,0,0,663,0,0,0,0,0,0,0,846,0,0,528,0,393,378,0,0,0,0,0,0,\n325,899,680,1880,0,1770,0,0,0,0,0,648,0,0,0,0,0,0,185,167,0,2046,0,0,0,0,0,0,\n249,1645,0,152,0,0,0,1733,0,0,0,0,0,1006,0,0,0,0,0,420,0,0,0,832,0,0,0,0,0,351,\n0,0,0,0,6,40,0,0,60,0,0,0,0,1354,745,724,0,0,0,0,0,0,0,0,772,1951,275,108,639,0,\n0,0,0,0,0,0,0,0,500,1758,0,0,0,0,0,0,0,0,0,0,0,1886,711,205,0,0,965,865,0,0,0,\n534,0,0,0,0,691,0,0,0,237,443,0,878,0,0,0,0,0,1410,0,0,0,0,0,0,0,0,0,0,0,0,0,\n995,0,0,0,0,0,0,0,0,0,0,0,0,0,578,0,0,0,0,881,0,0,0,0,0,0,0,0,822,0,923,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,924,0,0,0,665,0,0,0,0,0,1901,0,0,0,0,0,950,498,93,\n0,0,0,1451,0,0,0,0,0,747,828,788,400,184,0,198,0,0,0,0,0,0,0,0,0,0,0,994,0,0,0,\n0,0,0,0,0,615,320,0,0,0,978,843,905,0,0,0,0,0,0,0,0,850,974,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,0,0,0,0,0,273,0,0,0,0,0,0,0,0,0,0,0,0,0,\n201,0,0,0,1041,0,0,0,1040,0,0,0,0,0,0,0,0,0,693,234,774,0,336,0,1399,22,0,805,\n802,777,167,789,0,0,1705,0,0,0,0,0,0,0,0,0,0,0,10,13,11,0,0,204,264,0,0,56,0,0,\n1917,0,470,0,0,0,0,0,0,0,0,0,0,0,1198,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,715,0,0,1002,0,0,0,298,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,867,0,0,724,0,0,0,0,0,0,0,0,0,0,0,0,768,0,0,0,0,0,1066,0,0,0,0,67,0,174,948,\n0,0,0,0,0,0,0,0,0,0,0,0,0,764,0,0,0,0,75,137,0,756,0,0,0,0,0,0,1008,842,643,0,0,\n0,67,0,0,0,0,0,0,0,0,0,0,0,135,821,0,0,0,0,0,0,0,0,736,0,389,355,0,0,786,0,0,0,\n0,0,0,2044,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1030,0,0,0,1083,0,0,0,0,0,\n1226,0,0,0,0,356,319,8,389,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,474,0,0,0,427,\n0,413,0,730,0,0,0,0,0,373,0,0,0,0,0,0,0,0,0,799,0,0,0,1793,0,0,0,322,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,290,2,0,0,0,0,0,0,0,0,0,0,672,\n699,1860,0,0,0,737,0,0,0,1612,0,0,0,0,0,0,0,0,0,0,0,145,124,884,0,0,0,0,0,387,0,\n0,0,0,0,0,0,0,0,0,0,679,0,550,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1305,0,0,0,0,0,0,0,\n576,0,0,0,0,0,0,0,686,0,607,0,0,37,0,0,0,0,0,0,0,0,0,101,1726,0,0,0,0,0,958,0,0,\n0,903,0,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,367,0,0,0,0,690,0,705,273,0,0,887,0,0,0,\n0,0,0,0,0,0,0,0,90,0,0,0,0,0,0,0,908,0,0,0,0,0,0,0,1261,0,0,497,1235,0,429,0,0,\n0,0,904,0,12,125,0,0,0,841,0,0,0,0,0,860,946,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,768,0,770,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,271,0,0,0,0,0,0,0,719,0,699,581,0,0,0,0,0,0,0,0,0,0,862,304,0,631,0,0,0,0,880,\n1513,0,0,0,0,0,981,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,434,0,0,0,0,0,550,0,0,476,930,\n824,553,0,0,452,0,151,0,0,0,0,0,0,772,0,292,135,0,0,0,0,0,0,0,504,0,0,1089,0,0,\n0,0,0,0,0,0,0,0,0,783,0,0,0,0,0,0,206,393,0,0,0,0,0,0,0,0,232,912,0,0,0,0,0,977,\n0,0,716,98,0,0,0,0,0,733,0,0,0,0,0,0,0,0,19,0,0,0,0,668,0,360,0,0,0,0,0,0,656,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,726,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,1269,0,0,463,0,\n0,0,0,0,0,1454,0,1287,245,0,989,0,0,0,0,0,0,0,0,0,107,164,0,0,0,0,0,0,0,1061,0,\n0,0,0,2,484,0,0,0,0,0,0,0,1127,0,0,0,0,0,0,0,460,0,0,0,0,0,932,0,0,0,0,0,0,0,\n588,625,0,0,0,0,76,92,0,0,0,0,0,0,0,0,0,0,0,0,0,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n763,0,622,0,0,0,253,0,546,0,0,110,0,256,916,0,0,35,212,0,0,746,0,0,0,150,0,0,\n1466,0,0,0,1299,0,0,0,0,0,0,0,0,0,1518,0,0,0,0,0,0,0,0,0,0,0,0,0,1229,0,0,0,816,\n0,0,0,0,0,0,159,0,0,0,0,0,734,869,126,1716,0,0,0,0,0,0,202,232,0,0,0,0,212,0,0,\n0,0,0,111,1003,0,0,0,0,0,0,0,0,0,0,0,1712,0,0,216,0,0,0,0,516,0,0,0,0,0,650,0,0,\n0,0,57,99,0,0,0,0,300,574,0,0,0,0,1023,0,0,302,0,1871,0,728,252,0,0,461,0,0,0,\n323,0,0,0,0,0,0,775,461,0,0,0,0,0,0,172,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,73,727,0,1023,0,0,0,0,0,0,0,0,0,0,577,0,0,0,0,0,0,0,0,1037,0,0,0,0,0,0,\n0,0,280,677,0,0,0,0,0,0,0,0,0,0,0,799,0,0,0,0,159,0,446,1730,0,0,0,0,0,0,0,0,0,\n395,0,0,0,0,145,0,0,0,0,0,0,0,20,0,0,426,608,0,0,0,0,0,977,0,250,0,0,0,0,0,100,\n0,0,0,0,1982,0,0,0,0,0,476,0,0,0,0,0,0,594,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,447,0,0,0,0,526,0,0,14,1124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,188,0,0,0,0,0,0,0,0,362,301,0,0,0,1743,0,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,831,0,0,208,202,0,0,0,0,0,0,0,1954,0,\n0,0,0,516,872,0,0,313,224,0,0,24,0,11,546,0,0,0,1937,242,241,46,0,0,0,830,1273,\n0,0,0,0,0,0,0,825,327,1006,0,0,0,0,0,1580,516,366,0,0,0,0,0,1736,0,0,0,0,0,0,0,\n0,0,0,0,1935,0,826,0,0,0,0,139,331,0,0,0,0,0,0,0,0,0,0,0,288,0,916,0,0,0,0,0,\n1888,0,0,0,0,0,0,0,1471,0,1570,0,394,0,0,0,0,0,0,0,1931,0,1719,0,658,228,0,0,0,\n0,0,374,0,0,0,0,735,0,0,0,0,0,0,323,498,0,1063,0,0,0,0,155,0,0,0,0,0,0,0,0,906,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1139,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,616,\n902,0,0,0,0,0,692,0,0,0,0,0,0,823,0,0,0,305,0,0,0,0,0,0,0,681,0,0,0,0,0,214,\n1004,0,0,0,0,0,0,0,23,0,0,1703,0,0,0,0,0,0,0,0,0,1443,0,0,19,714,0,0,0,0,64,737,\n0,0,345,1758,0,0,579,47,0,0,539,139,0,0,0,0,388,0,0,0,0,253,0,0,0,0,0,0,252,0,\n745,0,0,0,0,0,0,0,0,0,0,0,504,107,0,871,0,0,0,229,0,0,0,0,0,903,0,0,71,0,0,549,\n6,47,0,0,0,0,0,0,0,0,0,980,865,705,0,0,0,161,0,0,0,0,143,1331,0,0,0,1388,33,724,\n0,0,0,19,0,0,0,395,0,0,0,0,0,846,210,0,0,0,122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,937,497,0,0,0,0,0,718,0,0,0,0,0,0,0,1581,0,\n0,0,0,0,0,161,49,0,0,0,0,0,0,0,0,0,597,0,0,0,1094,0,0,0,811,908,0,0,0,0,0,0,0,0,\n0,0,1471,0,0,0,0,0,0,0,0,0,0,42,1935,0,0,0,2014,66,2007,0,0,586,0,0,0,0,0,0,0,0,\n0,28,1077,0,0,0,1221,0,0,62,0,0,0,0,0,0,0,0,0,0,1766,0,0,0,0,0,0,0,0,0,0,0,0,25,\n0,499,1388,0,0,97,10,0,0,0,0,0,481,0,0,0,0,0,0,0,0,0,0,37,134,155,486,0,1442,0,\n0,0,0,0,591,0,0,0,0,0,0,310,1173,0,0,0,0,409,1156,0,0,0,482,0,0,263,926,0,0,0,0,\n0,0,0,0,0,0,0,0,0,804,0,0,0,0,0,0,0,0,0,0,0,0,0,1265,0,415,0,348,0,0,0,1012,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,165,1803,0,0,0,0,0,0,0,408,\n0,0,0,0,0,0,257,1321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1138,0,0,0,249,0,\n0,0,576,0,0,0,0,231,0,0,0,288,0,0,0,0,0,0,0,0,0,433,1487,569,1678,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,0,0,0,0,0,779,538,0,0,0,413,0,0,0,\n0,0,0,0,0,0,0,495,0,0,0,0,0,191,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,530,567,\n0,0,0,0,0,1484,0,0,0,0,0,0,815,609,0,0,0,0,0,484,0,0,0,0,0,0,0,0,0,0,900,0,0,0,\n0,1335,0,1724,0,0,0,0,0,0,0,0,0,0,0,640,0,0,0,0,0,0,0,0,0,0,0,1831,0,0,0,0,0,0,\n0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,1103,0,1504,655,1034,0,0,0,0,0,305,0,0,0,0,\n0,0,0,0,0,1236,0,0,429,217,0,0,0,0,739,278,0,0,0,0,0,0,0,708,0,0,0,0,0,1840,233,\n0,0,0,0,0,0,0,0,2017,0,0,0,0,0,1488,0,0,0,1590,0,0,0,0,0,1800,28,0,0,0,0,0,0,0,\n0,0,45,0,36,0,22,1442,378,0,0,0,0,0,0,1507,0,0,0,0,0,0,0,0,0,0,39,0,0,1054,725,\n1955,0,2036,0,0,0,0,0,0,0,0,0,0,896,1871,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,2046,0,\n0,0,0,17,712,0,617,55,320,271,0,0,0,0,0,0,0,0,0,445,0,184,103,0,0,0,0,0,0,0,0,\n659,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n337,0,0,0,506,0,0,0,0,0,843,77,0,458,0,0,0,0,0,1420,382,109,142,330,0,0,0,0,0,0,\n0,0,0,0,0,0,87,0,0,0,492,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1239,0,0,0,0,0,0,\n211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1049,0,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,1985,0,0,122,0,0,234,0,0,0,1098,0,0,0,0,0,0,549,253,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,522,131,0,0,149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,507,0,0,0,0,811,630,0,0,0,343,\n0,0,0,0,0,448,591,455,0,1381,0,0,0,0,0,0,0,575,0,0,0,0,0,1175,0,0,0,0,0,0,0,0,0,\n653,0,0,0,1761,0,1198,0,0,0,0,297,1127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,678,0,0,\n164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,45,0,0,0,0,0,121,0,0,0,0,0,0,\n0,0,125,0,0,0,1622,0,0,0,0,0,721,145,0,0,0,970,792,0,0,0,715,0,0,0,0,0,1999,0,0,\n74,531,0,0,65,0,0,0,105,220,0,0,0,0,0,0,0,960,0,0,0,0,0,0,428,19,0,0,401,96,0,0,\n0,0,0,1595,116,0,1021,0,0,0,0,0,750,1961,0,0,148,0,0,0,0,0,0,0,0,0,0,0,0,0,75,0,\n0,1383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,779,0,0,0,0,0,0,0,0,598,0,424,0,0,0,0,0,0,0,\n1222,0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,0,0,0,187,0,8,0,0,0,0,0,\n0,0,429,0,685,0,0,0,0,0,0,0,0,0,0,0,132,472,0,0,0,0,0,0,0,0,0,938,0,0,874,0,0,0,\n0,0,774,0,0,0,0,0,92,0,0,0,0,0,0,830,701,0,0,0,0,0,426,350,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,603,59,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,441,163,4,0,\n0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,233,0,0,0,0,1994,0,1739,0,0,393,0,47,1038,0,0,0,\n309,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,363,0,0,0,175,0,0,0,0,0,0,0,666,\n0,0,1675,0,1600,0,0,0,808,0,0,0,0,0,0,0,0,0,0,0,280,54,0,0,0,0,0,0,0,0,421,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,0,0,103,254,0,262,1,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,1630,0,0,0,0,0,0,0,0,0,0,0,0,0,671,972,989,0,0,\n0,0,0,0,0,889,0,0,0,1382,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,0,388,202,0,0,0,0,\n16,560,0,0,0,841,0,0,566,0,0,0,938,0,0,0,0,0,0,0,0,0,0,912,0,0,0,1361,0,0,0,0,0,\n0,618,236,0,1854,0,0,318,190,0,1376,0,0,0,0,0,0,0,349,0,0,0,0,951,1972,0,0,0,0,\n0,0,344,0,0,0,0,0,0,0,0,850,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,163,85,0,487,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,145,0,83,0,0,1013,0,0,0,1922,0,0,169,557,66,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,1193,82,0,352,454,57,0,0,1333,396,107,0,370,0,0,0,0,0,0,0,0,0,204,0,0,0,\n0,0,1706,0,0,0,0,0,0,0,0,0,0,0,0,394,1204,0,0,0,0,0,1007,0,0,0,1696,0,1519,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,981,0,0,0,0,1072,0,0,0,712,0,1629,0,0,0,0,0,0,0,728,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1271,0,0,0,1608,16,0,0,0,0,485,0,0,0,0,0,0,\n153,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1991,0,0,0,0,0,0,0,0,52,0,21,0,\n0,0,0,0,0,0,0,0,819,0,0,0,0,0,917,0,0,0,0,784,0,0,0,0,135,0,0,0,0,0,454,0,0,0,0,\n0,0,0,0,0,852,1719,0,0,0,0,0,852,0,0,0,0,0,952,0,0,0,0,568,0,0,0,0,0,448,0,0,0,\n67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1826,657,0,729,666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n669,0,0,0,0,0,0,0,402,0,0,152,0,0,0,0,912,0,0,0,0,0,0,51,320,0,445,0,0,0,0,308,\n0,0,0,0,0,386,0,0,239,0,0,130,83,0,143,0,348,0,0,0,0,0,0,0,958,0,0,0,0,0,210,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,430,0,0,0,0,0,0,0,0,0,0,0,0,7,213,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,801,0,0,0,0,0,0,0,0,0,936,0,108,0,0,\n0,0,0,0,0,0,0,885,587,219,398,364,0,1165,0,0,342,241,303,0,0,0,0,0,0,0,0,0,0,\n1454,0,0,0,0,0,0,0,0,0,0,254,562,0,786,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1294,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,493,216,0,0,0,0,219,341,0,0,0,0,0,\n0,0,0,0,0,130,1734,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,701,604,0,0,879,0,195,\n666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1669,0,0,0,1791,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1228,0,0,0,0,0,623,0,0,0,0,0,0,0,798,0,0,0,0,0,0,0,0,0,0,0,0,84,\n122,0,0,0,837,0,0,0,0,0,0,1013,0,0,577,0,0,0,460,932,0,0,0,0,0,0,0,0,0,0,0,31,\n131,0,0,0,605,0,0,0,1246,0,0,0,0,68,278,165,307,781,0,0,0,0,0,0,33,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,1113,0,0,720,1953,203,0,0,0,0,0,0,0,425,326,0,0,0,0,0,\n0,0,0,0,0,241,1316,0,0,0,0,0,416,0,0,0,1300,0,847,0,0,662,358,0,0,0,0,839,1823,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,654,1522,0,0,0,0,0,0,163,0,0,0,0,0,314,978,0,0,0,\n601,0,0,0,0,0,946,434,0,0,0,402,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,1467,\n410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,0,70,0,0,0,0,1405,0,0,0,0,0,0,108,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,777,0,0,0,0,0,747,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,505,0,326,0,0,164,628,654,0,0,0,\n37,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,668,152,0,0,0,0,0,0,0,0,0,0,0,581,\n0,0,0,0,44,126,89,0,0,0,0,0,0,0,0,1531,0,0,0,0,0,0,0,0,203,1167,0,0,0,0,0,0,0,0,\n531,1232,0,0,0,0,0,943,0,670,231,880,0,1617,0,0,0,1957,0,0,0,0,0,0,0,975,0,0,0,\n0,0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,0,0,421,0,0,14,834,0,0,0,0,0,0,0,0,0,0,0,0,\n465,0,0,0,0,0,834,688,413,855,0,0,0,590,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0,\n0,45,169,0,0,0,0,0,0,0,0,0,0,0,198,0,0,565,585,0,0,0,0,0,0,0,0,0,0,0,0,0,691,0,\n0,0,593,0,0,0,0,0,0,0,0,0,913,116,0,0,0,0,1360,0,0,0,802,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,673,308,0,709,1006,1895,0,228,0,0,0,1840,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,608,0,0,0,0,0,0,0,0,0,1573,0,2039,136,540,0,0,0,0,0,0,0,\n897,0,0,938,1878,0,0,0,0,0,0,0,0,0,1469,0,999,0,299,0,0,0,0,0,0,0,578,0,0,0,0,0,\n456,0,0,0,1679,163,693,0,0,0,0,0,0,48,755,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,\n1091,0,0,0,0,695,0,0,1464,0,0,0,0,0,975,0,0,335,0,0,1979,0,0,0,0,269,1566,630,\n396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1815,634,0,0,0,966,0,0,0,0,0,0,0,9,\n412,0,958,0,0,579,382,0,212,0,0,0,0,965,681,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,655,\n0,0,0,0,67,0,0,0,0,0,0,751,0,0,0,0,423,231,0,0,1016,300,0,0,0,0,100,237,0,0,0,\n1370,0,0,0,1208,0,0,0,0,0,1219,129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,199,0,0,427,0,0,\n0,0,949,665,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,712,0,0,0,0,0,1186,0,0,0,0,0,0,0,0,0,0,295,312,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n151,0,0,0,0,588,4,0,0,0,0,0,414,104,0,0,757,263,0,561,0,0,0,320,0,0,0,0,0,0,0,0,\n0,0,0,225,0,0,0,0,37,817,0,974,0,0,0,0,0,0,0,0,0,0,0,0,0,2026,131,235,16,0,590,\n1157,0,0,0,0,0,0,0,0,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,390,0,0,0,0,\n0,0,0,1144,0,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,204,407,303,1218,0,0,0,0,5,325,0,0,\n0,0,12,800,0,1783,0,0,0,0,0,0,0,0,0,0,504,621,0,0,0,0,0,0,0,0,0,920,0,376,0,0,0,\n0,0,218,580,0,768,454,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,164,0,0,0,0,0,0,0,\n0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,120,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,343,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,0,0,1812,0,0,8,0,0,0,21,1125,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,1327,0,0,0,0,575,1598,0,0,0,0,0,0,0,0,0,895,0,0,0,959,0,0,\n0,0,0,1759,173,0,0,0,0,266,261,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,1427,0,0,300,1033,0,0,0,0,0,0,0,0,0,0,0,584,0,0,0,0,52,734,\n0,0,217,239,0,1129,0,0,0,0,0,0,0,0,732,20,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,613,0,\n0,0,0,0,0,0,0,0,632,0,0,85,984,0,0,0,0,909,694,7,1109,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,167,0,0,0,0,280,62,0,0,33,0,0,359,186,980,0,0,0,0,0,0,0,0,0,0,0,585,0,0,0,\n211,0,0,336,145,0,1130,0,873,0,0,840,263,0,0,0,0,0,0,0,0,0,916,0,0,0,0,0,0,0,0,\n0,0,155,0,0,0,461,97,0,0,0,0,0,1356,0,0,0,0,0,0,0,593,0,0,0,0,0,1392,0,0,0,0,\n126,0,0,0,0,1179,0,0,0,0,0,162,0,0,0,0,0,765,0,187,0,1286,0,0,0,0,0,0,0,0,0,635,\n0,0,23,215,0,0,0,1306,0,0,97,716,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,657,0,\n0,0,0,0,0,0,0,299,0,0,0,0,0,0,134,0,0,0,0,0,0,0,0,0,0,0,658,1082,0,0,0,0,0,2002,\n0,0,0,0,0,0,833,248,0,0,0,0,0,1654,0,0,531,0,0,0,0,0,0,634,0,0,0,0,0,0,0,0,0,\n853,573,249,0,0,0,0,0,0,0,0,527,0,0,0,0,1419,0,0,0,0,0,0,20,49,0,0,0,992,0,0,0,\n728,0,0,0,0,0,0,0,0,0,0,0,0,497,1579,0,0,0,0,62,268,0,0,0,0,0,0,0,1201,0,0,0,0,\n0,0,0,0,0,0,0,0,495,193,0,0,0,0,106,0,0,859,0,0,23,0,0,0,0,0,0,0,813,925,0,0,\n223,613,953,0,0,0,0,0,0,0,0,666,0,0,0,0,0,0,0,0,0,670,0,0,40,216,0,0,0,0,0,0,\n259,0,0,0,440,1114,0,0,0,0,0,0,0,0,74,475,0,0,188,139,0,797,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,1572,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,1594,0,0,0,0,0,0,0,290,0,232,\n0,0,887,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,14,0,0,0,0,0,741,0,0,0,992,0,\n0,0,0,0,0,0,0,111,0,0,425,0,0,0,0,0,789,0,0,0,1593,0,1768,0,0,233,0,0,0,0,943,0,\n0,0,0,0,0,0,955,225,245,0,0,0,0,0,0,241,0,0,0,0,1943,0,0,0,1284,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,709,0,0,0,0,0,0,554,0,0,0,0,0,0,0,0,1564,0,0,0,\n443,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,729,0,0,0,348,0,0,0,0,0,0,0,758,848,298,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,829,1422,189,121,0,0,632,812,0,0,556,0,0,0,0,0,436,172,\n530,844,232,984,0,0,0,0,0,0,0,0,0,0,147,0,0,0,0,0,0,0,0,537,0,0,0,0,0,859,0,0,\n842,0,0,0,0,0,0,0,0,0,0,1291,0,0,0,0,0,0,0,0,0,0,0,1482,612,392,0,0,0,262,31,0,\n0,0,0,0,0,0,0,0,0,753,549,0,0,0,0,0,0,696,0,0,0,0,0,0,0,834,0,0,0,0,0,771,0,0,0,\n0,0,0,0,0,0,0,0,0,0,921,0,0,0,674,0,0,0,0,0,0,0,0,0,0,308,444,0,0,0,0,0,0,805,\n180,0,0,278,271,0,0,214,505,0,1215,0,0,0,0,0,0,387,271,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,1645,42,92,0,459,0,0,330,1557,0,0,0,0,0,0,0,0,113,18,0,0,0,\n1742,0,0,0,965,0,0,0,0,0,0,0,0,0,0,0,0,0,182,0,0,65,0,0,0,0,0,0,0,0,0,0,0,0,973,\n0,0,0,0,0,328,0,0,588,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1786,\n0,0,962,1985,0,0,0,308,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,588,0,0,0,0,0,0,614,793,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,290,0,0,0,0,0,0,0,0,0,0,1136,0,0,0,0,0,0,0,0,0,0,796,719,0,0,\n326,210,0,0,0,701,758,472,0,0,0,1947,278,1079,0,0,0,0,0,0,497,41,0,0,634,46,961,\n0,810,524,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,532,0,997,0,0,0,0,0,0,0,0,0,0,0,1301,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1298,0,671,0,0,0,306,0,0,0,0,0,0,0,0,0,0,\n693,1823,0,0,0,759,0,0,0,0,0,1932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,182,0,0,0,1964,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,0,0,0,0,0,0,424,857,0,0,0,0,671,328,0,\n529,0,0,0,0,0,716,0,1509,80,67,0,0,0,0,59,141,0,0,0,0,0,0,783,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1498,0,0,0,0,343,430,803,1183,677,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1357,53,0,0,0,0,590,0,0,0,0,0,0,0,0,0,0,\n0,0,0,329,0,0,0,0,0,0,0,469,0,0,0,0,0,0,0,0,0,0,460,0,0,1743,0,0,963,340,0,0,0,\n0,0,1603,0,0,250,0,0,0,0,0,646,218,0,1794,0,0,0,571,0,455,0,0,0,1012,0,0,0,0,0,\n0,0,0,0,0,0,0,597,161,0,349,0,524,0,0,0,0,0,0,0,0,0,0,0,0,322,432,0,0,0,0,0,0,\n325,223,0,0,0,0,0,566,0,0,0,1394,481,436,0,48,457,610,756,618,0,0,0,755,0,1217,\n0,0,0,0,0,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,544,492,107,414,0,0,0,0,0,0,0,0,0,0,0,\n1007,0,0,0,0,5,0,0,1580,0,0,0,0,0,0,0,0,0,0,0,0,0,673,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,1843,0,0,0,0,0,0,0,0,0,165,0,0,0,0,0,0,809,885,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,498,0,0,0,306,9,0,0,0,0,0,0,0,437,721,146,0,0,0,0,0,0,0,0,0,0,0,177,0,0,0,0,\n0,0,0,1377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,0,959,0,0,0,1928,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1435,0,481,0,0,0,0,0,0,142,84,0,0,0,0,0,\n1015,0,0,0,315,0,0,0,0,0,0,759,0,0,0,0,0,0,0,0,712,0,0,0,1722,0,0,0,0,0,0,0,0,0,\n0,0,0,222,0,985,1414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1273,\n538,706,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,1781,0,0,0,0,0,431,97,665,42,\n237,0,0,0,264,0,0,213,0,0,0,0,0,0,0,455,0,0,0,906,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n624,0,574,0,0,0,0,0,0,0,0,0,0,0,0,354,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,\n235,723,1813,0,0,0,957,0,830,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,496,0,0,0,0,0,0,0,\n547,239,88,0,0,0,0,0,0,0,0,0,1310,0,0,0,0,0,0,0,0,80,1076,0,0,118,0,0,0,479,274,\n0,0,0,0,0,0,0,0,0,0,0,497,0,0,669,261,0,0,0,0,13,0,0,0,0,0,0,791,250,642,0,0,0,\n1429,939,949,0,0,0,0,0,0,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,982,330,0,0,0,0,545,0,0,0,0,0,0,947,0,1188,0,0,0,0,0,904,0,0,0,0,0,1372,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,693,377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,0,0,\n713,386,0,0,0,0,128,1575,0,0,0,0,0,0,424,893,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,904,0,0,0,0,0,552,322,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,1808,49,0,0,0,0,\n1832,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,421,0,0,442,415,0,0,289,\n0,0,0,0,0,206,110,0,0,0,0,0,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n19,1539,0,0,0,0,0,1340,0,1194,0,0,0,0,0,0,0,0,549,0,0,0,0,0,0,0,0,1720,0,0,0,0,\n0,0,0,0,0,319,0,0,0,0,112,1180,0,0,0,0,0,0,0,0,0,0,0,967,0,0,0,0,0,0,0,0,0,1940,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,735,0,0,0,0,0,0,0,0,0,897,132,0,0,0,0,0,0,0,\n0,0,0,38,838,0,0,0,379,218,8,660,1017,0,0,0,0,0,0,111,387,647,877,0,0,53,790,0,\n0,0,0,0,0,0,0,458,0,0,0,0,0,0,954,0,0,0,394,0,1367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,882,0,0,0,0,0,0,0,1409,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,124,342,199,0,0,0,0,\n0,0,0,0,0,0,724,628,0,0,0,0,804,266,0,0,0,0,0,208,0,79,0,0,0,0,0,0,0,0,741,0,0,\n0,0,0,0,0,0,0,0,606,0,1494,821,1553,0,0,135,405,0,0,178,100,0,0,0,0,0,0,0,0,0,0,\n0,0,0,481,0,0,0,1378,0,0,0,0,0,0,0,0,0,0,0,0,0,791,33,1227,857,0,467,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,447,0,0,0,0,0,0,86,128,0,0,0,0,0,0,587,0,0,0,692,1018,0,\n195,0,0,0,0,0,0,0,1546,0,0,0,0,0,0,0,0,0,0,0,684,0,0,345,0,0,0,0,0,0,365,0,1683,\n0,0,472,0,433,0,0,0,0,0,0,0,28,0,0,0,997,0,705,3,0,0,0,0,0,0,0,0,0,229,0,0,0,0,\n102,0,0,0,0,866,1022,0,0,0,0,0,0,0,0,0,55,0,115,0,0,0,0,933,0,0,0,0,0,0,0,702,0,\n0,0,0,0,0,0,1728,26,484,0,0,0,185,618,417,0,803,0,0,0,0,0,0,0,0,0,0,0,1262,0,0,\n0,0,0,0,0,0,0,0,0,0,0,633,0,0,0,0,0,0,0,0,0,0,0,0,0,479,262,0,0,0,0,0,0,830,0,0,\n0,0,26,70,0,0,0,0,0,0,0,0,217,0,640,51,0,0,360,1586,0,0,0,0,0,652,0,0,0,0,0,766,\n0,0,0,0,298,737,0,0,0,0,0,0,0,0,0,0,655,222,906,0,0,1013,991,2009,0,0,0,0,503,0,\n0,0,216,154,0,0,0,716,0,844,0,0,0,0,621,252,0,0,0,0,748,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,103,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,576,0,0,0,648,0,0,0,331,0,0,0,\n0,0,0,0,0,0,0,0,0,632,0,0,0,518,107,0,0,0,0,0,0,0,0,851,0,0,0,0,504,0,0,0,0,0,0,\n0,0,0,0,0,0,7,883,0,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,91,993,0,0,0,0,0,0,200,131,\n10,0,0,0,0,0,0,0,0,0,0,0,0,0,365,1433,0,0,0,0,28,103,0,0,798,1013,0,0,0,0,0,0,0,\n0,39,1925,0,853,0,0,271,519,0,0,0,0,338,0,0,300,470,419,0,0,0,0,0,0,836,0,0,0,0,\n0,0,1937,0,0,0,0,0,393,0,0,357,0,0,0,0,0,703,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,387,0,0,0,0,0,0,75,708,453,1351,0,303,0,0,772,0,0,0,0,0,0,0,0,749,0,0,\n0,0,0,0,0,0,0,0,0,0,0,1065,0,0,717,226,0,0,0,0,0,890,431,626,0,0,0,0,706,0,0,0,\n51,698,0,0,0,0,0,0,0,0,0,0,0,828,0,0,17,0,0,0,0,1929,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,84,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,871,498,0,101,1793,0,0,0,0,0,0,435,0,\n0,0,0,0,966,0,129,1644,0,0,0,0,0,0,0,0,0,0,0,0,0,997,502,0,0,0,0,0,0,0,0,0,0,0,\n0,823,0,1927,0,0,0,0,98,1756,0,0,0,0,0,0,0,0,0,0,0,0,8,0,160,1046,0,492,0,0,0,0,\n0,0,129,45,0,0,0,0,0,0,353,558,0,0,0,0,0,785,0,0,0,1145,189,0,0,0,26,353,0,0,0,\n0,0,2024,0,0,0,606,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,855,0,0,0,0,0,0,0,0,0,0,0,\n0,0,2011,0,0,5,4,0,0,461,764,0,0,0,1449,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1445,0,0,\n0,1168,0,0,0,233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,216,0,0,0,286,0,0,0,\n3,0,0,0,723,536,0,0,0,0,0,285,0,0,0,560,0,0,0,0,0,690,0,0,0,0,0,1246,0,0,63,0,\n33,0,0,0,0,0,520,1862,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,0,0,554,0,0,0,0,0,1001,0,\n0,0,0,0,446,0,0,0,0,0,0,0,1313,0,0,837,636,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278,\n0,0,0,0,0,0,0,0,868,0,0,0,0,1010,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1231,0,304,0,506,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,93,1408,794,\n843,704,0,285,114,485,898,145,0,19,2035,0,0,0,1933,0,0,0,0,0,0,0,1728,0,0,0,0,0,\n0,0,0,746,0,0,0,0,0,0,0,995,1964,0,0,0,0,0,0,0,0,0,0,0,1550,0,874,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,1018,0,0,0,814,126,0,0,1264,0,0,814,955,0,0,0,0,0,0,\n0,981,0,0,0,0,0,0,0,0,915,56,0,0,100,0,0,0,0,0,0,0,0,0,638,0,0,0,0,738,0,0,0,0,\n0,0,0,0,0,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1112,0,0,214,0,0,0,133,0,196,\n168,0,0,0,0,0,1152,0,1245,0,0,538,169,871,1816,0,0,413,133,0,0,0,978,0,0,43,93,\n371,0,0,0,0,0,0,526,25,0,754,335,0,0,0,0,182,0,0,0,0,0,0,0,0,0,0,0,39,601,0,0,0,\n0,0,0,0,181,370,0,0,1652,358,0,0,0,0,0,0,0,0,0,176,286,0,788,0,0,0,0,0,1223,780,\n254,1003,896,0,0,0,1447,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,126,0,\n41,788,0,0,0,629,0,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,420,37,1900,0,0,0,0,542,1570,957,0,0,0,0,0,0,\n0,373,31,0,0,0,0,125,325,0,0,0,0,0,0,323,0,0,1547,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1216,0,0,0,0,0,0,198,1905,629,15,0,0,0,0,0,0,20,75,543,1353,0,0,0,533,0,0,6,0,0,\n0,0,0,0,538,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,11,0,0,0,284,659,0,989,0,0,0,0,0,\n0,0,0,0,848,0,0,507,0,0,0,0,0,0,0,0,188,991,884,0,0,0,0,60,959,0,0,0,0,0,1653,0,\n0,922,337,0,638,0,0,500,0,0,0,0,0,0,0,0,0,0,0,166,0,0,0,0,0,0,0,0,0,0,0,0,418,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,760,0,0,0,0,0,0,1277,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,243,89,0,0,0,0,0,0,0,0,0,1396,0,\n560,0,0,3,1658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,586,0,0,1271,0,0,0,505,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1947,\n41,445,0,0,0,0,0,0,0,0,57,189,0,0,371,0,0,0,0,552,0,883,0,923,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,875,0,0,0,1788,49,0,0,0,0,0,\n0,0,0,0,0,0,661,0,0,1945,0,0,0,0,0,794,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,1135,0,0,0,745,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,410,0,976,0,0,0,0,0,703,0,0,\n0,0,0,0,187,322,0,0,0,227,0,0,0,0,560,0,31,1395,0,0,0,0,0,466,0,0,0,0,643,167,0,\n0,0,1428,0,412,0,0,0,0,0,0,0,0,0,1118,562,0,0,0,0,0,256,0,0,0,0,0,0,1771,0,0,0,\n0,0,1190,132,0,66,0,0,0,0,0,0,0,0,0,0,317,0,0,0,63,0,0,0,0,0,0,0,1475,0,0,0,0,0,\n0,0,288,0,0,0,0,608,0,0,0,0,0,0,0,0,1225,0,1189,0,0,0,0,0,0,0,1468,0,0,0,0,0,\n689,120,0,0,0,0,0,0,0,1,0,329,0,0,0,0,226,0,0,0,0,0,1855,0,0,461,0,0,0,0,1346,0,\n0,0,0,0,85,0,0,299,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1171,0,0,\n0,980,0,0,0,0,0,0,0,0,637,279,0,0,0,0,0,293,0,0,0,0,528,17,0,0,0,0,5,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,601,0,0,0,0,0,0,779,0,\n196,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1322,737,752,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,412,192,80,0,0,8,1470,0,0,0,0,0,0,0,0,0,873,0,0,0,0,0,835,0,0,0,0,256,\n38,986,0,0,0,0,0,0,0,0,0,91,257,278,911,0,0,0,0,0,0,0,0,749,151,0,0,0,0,0,0,0,0,\n0,0,0,0,989,0,0,990,0,0,90,194,0,0,0,0,0,425,0,0,0,0,0,774,0,0,0,0,0,0,0,0,0,0,\n646,827,752,0,0,0,662,0,22,21,0,0,0,0,0,0,95,239,0,0,0,431,0,0,0,0,0,874,0,0,\n265,65,0,0,0,1350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1887,0,0,0,0,0,0,0,809,\n0,696,0,1074,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,802,0,0,0,56,776,0,\n970,0,0,797,0,0,0,0,0,400,0,0,1951,0,0,41,0,11,118,0,0,0,0,0,0,0,0,251,615,0,0,\n0,1044,0,0,0,0,0,0,0,0,0,0,0,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,370,0,0,0,0,\n104,48,209,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,930,0,0,0,0,\n0,0,0,0,0,0,0,1286,0,759,0,120,385,0,0,0,429,0,0,0,0,0,0,0,0,820,0,0,0,0,0,0,\n199,0,10,151,0,0,0,761,365,0,0,0,0,0,0,0,0,0,46,1086,0,0,0,0,11,1624,58,344,0,0,\n1008,1868,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,711,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,440,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,914,1913,0,958,0,885,0,0,0,0,0,0,0,0,0,0,0,\n0,0,847,276,0,302,65,0,0,0,510,0,1514,0,0,0,0,0,0,152,291,0,0,0,0,0,0,0,0,0,0,0,\n0,282,589,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,463,42,0,0,0,0,0,372,0,0,0,0,0,0,0,\n0,0,680,0,0,0,0,0,0,0,0,977,1997,0,0,0,810,0,0,0,0,0,0,0,0,0,1390,0,0,0,644,0,0,\n867,982,0,0,0,0,0,0,0,540,0,123,0,0,0,1978,0,0,0,0,789,623,0,1723,0,1220,0,0,0,\n0,0,0,0,480,0,0,0,0,0,0,0,0,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,299,1995,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,788,179,0,0,0,0,0,0,431,156,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1373,39,80,196,0,0,507,0,0,0,646,0,0,0,0,\n0,1214,0,0,0,0,926,0,0,0,1,114,0,0,0,0,0,446,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,490,0,0,0,491,0,1584,0,0,507,250,0,0,0,158,\n10,362,1,0,0,0,0,0,0,0,0,0,408,228,860,480,0,779,0,0,0,557,0,0,142,197,0,0,0,0,\n0,0,0,0,0,0,0,1490,11,378,316,1057,0,0,18,579,299,1546,0,177,0,0,0,0,0,0,0,0,0,\n411,0,0,0,0,727,439,0,0,0,0,0,1528,0,0,0,0,0,0,58,0,482,0,0,0,505,1952,0,0,0,0,\n0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,953,0,0,0,0,802,0,0,0,0,0,0,0,0,0,0,290,0,0,791,\n52,0,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,1028,0,0,138,0,0,0,0,1811,0,0,0,0,0,0,\n934,1821,0,0,0,0,371,38,0,0,0,1296,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,723,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1330,0,0,0,0,0,0,0,1255,296,109,0,0,0,0,0,660,0,0,0,0,270,591,0,\n0,0,0,0,0,0,1090,81,0,0,0,0,391,0,0,0,0,249,322,0,0,0,0,0,0,0,1412,0,0,0,0,0,0,\n0,0,0,0,526,632,0,0,0,0,0,0,235,144,0,0,0,0,0,940,0,0,0,52,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,309,196,0,0,0,0,0,1912,0,1290,0,686,0,0,625,0,0,0,0,0,0,0,0,0,0,0,412,0,\n0,0,0,43,0,0,0,0,11,967,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,0,0,0,\n873,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,890,0,0,2,0,0,0,0,0,0,0,0,1774,\n393,263,0,0,0,0,0,0,818,456,0,0,251,178,393,97,0,0,0,0,0,674,168,0,0,0,0,0,0,0,\n159,1639,0,0,0,0,0,0,0,0,59,934,0,191,0,0,0,0,346,165,0,877,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,128,0,0,0,0,0,0,1297,0,0,0,0,0,0,164,0,0,0,15,132,241,1073,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,324,53,0,0,910,0,0,0,0,0,0,0,0,734,705,\n217,73,0,0,0,0,0,0,0,0,636,389,0,1409,0,0,0,0,0,893,0,0,0,0,21,0,0,0,0,0,0,0,0,\n0,0,0,0,0,721,0,0,0,959,0,0,0,0,1433,0,0,0,0,0,0,0,0,0,0,0,0,174,189,0,0,0,0,0,\n0,0,0,0,0,22,2,0,0,815,354,0,0,0,0,425,0,411,60,13,1611,0,0,0,0,0,0,0,0,0,0,0,0,\n0,1478,596,0,0,398,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,1159,0,0,0,0,0,\n592,223,0,0,0,0,0,0,0,245,64,0,0,0,0,278,0,604,0,0,1502,265,0,0,0,0,0,0,0,310,\n1763,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,1356,0,0,0,0,0,0,0,\n0,505,0,0,0,0,0,0,0,1000,0,0,966,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0,\n0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,590,0,0,0,0,280,0,0,0,1386,0,0,0,\n281,0,1064,0,0,0,0,0,917,0,0,15,555,0,0,1014,1883,0,0,0,965,0,0,117,33,0,0,0,\n801,0,0,0,0,0,877,0,824,0,0,0,0,0,0,0,0,0,0,0,365,0,0,0,0,0,0,774,7,0,430,0,0,\n231,360,0,0,0,0,0,0,0,0,822,740,0,0,929,1485,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,852,0,0,0,0,17,0,0,0,0,0,0,1001,0,0,0,0,35,831,0,0,384,457,0,0,0,1351,0,27,\n0,0,984,0,264,552,0,401,0,0,0,710,0,1211,0,0,11,205,0,0,0,0,0,0,0,0,0,0,0,0,5,\n579,0,717,0,0,1011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,0,0,489,0,\n0,0,1024,0,0,0,0,0,0,0,0,0,892,0,0,0,0,0,0,0,0,0,0,0,0,473,0,0,0,659,864,0,0,0,\n0,0,0,152,819,0,51,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,229,0,0,0,0,674,0,0,0,0,0,\n0,0,0,0,770,52,79,0,0,0,1666,0,409,0,0,0,0,0,0,0,195,0,688,0,0,0,0,0,0,0,0,0,0,\n0,889,174,160,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,918,569,268,0,0,0,1224,0,1361,0,0,\n0,0,0,0,0,0,0,374,0,0,0,0,0,731,0,0,0,0,190,0,0,0,0,0,0,0,202,506,444,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,835,0,17,1526,0,0,0,0,0,477,0,0,\n994,1374,76,0,0,0,0,0,0,0,355,287,0,1389,0,0,0,0,0,0,455,384,0,0,0,264,0,0,0,0,\n0,0,0,0,0,0,0,0,1001,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,851,175,359,0,0,0,0,0,0,0,\n0,287,740,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,857,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n819,1402,0,0,0,0,0,0,174,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1649,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,655,573,0,0,0,0,0,0,0,0,128,351,0,0,0,0,0,0,\n0,0,0,0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,687,0,0,0,0,0,0,0,0,0,1525,\n0,0,0,1009,0,0,0,0,0,0,0,340,0,0,0,0,0,0,0,0,0,0,861,0,176,0,0,0,0,0,0,0,0,0,96,\n985,0,615,0,0,0,0,0,0,0,1919,0,0,0,0,0,1131,0,0,0,0,0,0,0,247,0,0,0,0,27,23,0,0,\n0,0,0,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,1088,0,0,\n0,0,0,1585,0,0,0,0,227,0,0,0,478,360,0,0,0,95,0,0,0,0,0,0,699,0,0,0,26,0,0,0,0,\n1119,0,0,0,739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,741,67,0,0,0,0,0,0,464,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,0,96,0,0,0,26,342,0,0,0,0,0,0,203,0,0,449,0,\n0,0,0,0,0,0,0,0,0,256,311,0,0,0,0,0,0,758,0,0,0,0,0,0,0,0,827,0,0,0,0,581,64,0,\n1047,0,0,0,0,0,288,0,0,0,0,0,1375,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0,\n376,12,0,0,0,0,0,154,0,1520,0,1753,95,502,0,0,0,0,0,0,0,269,291,1197,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,1341,0,1017,0,0,0,0,0,0,0,\n0,857,1810,533,0,0,1453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,836,211,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,19,0,156,0,0,0,0,1009,0,0,0,0,0,0,0,0,0,0,0,0,0,820,0,0,\n0,0,0,0,0,0,0,228,0,0,0,1131,0,1276,0,0,0,0,0,0,0,0,0,0,0,0,849,1792,0,0,389,\n291,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,525,0,0,\n0,453,0,0,0,0,666,0,0,0,422,0,355,0,0,0,0,165,0,260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,865,0,0,0,0,0,0,0,1625,0,0,0,234,0,1383,0,0,0,0,0,0,0,0,306,0,0,0,802,1921,\n0,0,0,0,0,0,180,0,0,0,0,1312,814,0,0,0,0,0,0,0,0,0,0,707,0,0,0,1493,11,61,733,0,\n0,0,341,0,0,0,98,0,0,0,0,0,0,0,0,0,0,0,1014,0,0,0,0,0,0,0,142,102,0,0,30,0,0,\n823,0,1045,0,0,0,1930,0,1512,0,0,0,0,0,0,0,87,0,1243,245,0,0,0,0,0,0,0,48,68,0,\n0,0,0,0,0,0,0,126,77,625,938,0,0,351,0,0,0,174,1668,0,707,0,0,0,0,0,0,0,0,0,0,0,\n403,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,282,0,0,0,0,0,0,8,44,0,0,363,115,0,0,0,0,0,0,\n0,0,0,0,0,0,545,761,0,0,835,1254,0,0,0,0,930,1936,0,0,0,0,0,0,0,0,653,0,0,0,0,0,\n344,0,0,1483,673,185,0,0,460,93,753,478,0,0,0,0,0,1020,0,0,0,0,0,0,0,103,0,0,0,\n499,0,0,0,0,0,0,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,968,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,3,0,0,0,0,399,0,0,0,0,224,563,0,0,0,0,0,704,0,0,0,0,0,0,0,0,0,0,0,\n1559,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,861,0,0,0,0,946,333,746,0,0,0,0,0,\n0,0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,652,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1393,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1514,0,0,0,0,201,0,510,717,0,0,528,0,0,0,0,\n20,0,0,0,1251,0,0,0,1163,0,0,0,307,0,0,0,0,0,1091,0,0,0,0,0,0,0,0,0,0,0,429,0,0,\n0,881,0,0,0,0,0,621,0,0,0,0,0,0,0,736,0,348,0,868,0,0,0,0,433,0,0,0,771,1495,0,\n0,0,0,215,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,0,0,55,0,0,0,0,0,0,0,112,62,0,856,270,\n0,572,0,0,0,0,939,0,0,0,0,0,0,0,352,0,0,0,0,0,0,0,0,0,647,0,0,0,0,10,0,0,0,0,0,\n0,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,464,0,0,109,0,0,0,1746,0,0,0,515,0,0,0,566,0,\n0,0,0,0,0,67,40,0,0,722,992,0,0,923,0,0,0,0,0,0,1145,0,0,0,0,0,0,0,0,0,0,0,568,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,0,0,0,0,645,0,0,328,0,0,0,0,0,0,0,0,0,0,0,0,\n1363,0,0,0,0,0,1280,0,0,0,0,0,0,0,0,0,0,7,28,360,162,0,0,0,0,0,0,0,0,0,0,0,764,\n0,0,833,862,0,856,0,0,0,0,0,0,736,92,0,0,948,1944,0,1479,63,590,0,0,0,1521,0,0,\n0,709,0,0,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,1213,\n0,0,0,0,29,1022,0,1712,0,466,0,0,0,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,171,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,964,2005,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1100,0,0,0,954,0,0,0,0,0,0,0,0,0,1958,0,0,34,549,994,0,0,449,\n137,850,0,0,670,146,0,0,0,0,518,159,0,0,0,0,0,0,0,0,151,0,0,1027,0,0,0,0,0,0,0,\n0,0,0,983,0,0,0,0,993,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,141,501,0,0,0,\n0,0,0,0,0,0,452,0,0,0,0,0,0,0,0,0,0,233,149,0,0,0,0,0,0,0,0,582,0,0,0,801,0,0,0,\n0,0,0,70,0,0,369,0,36,0,0,0,0,0,0,0,204,721,430,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1817,16,1078,1021,0,0,\n406,0,0,0,0,0,69,0,0,0,0,0,1830,0,0,0,824,0,0,0,0,0,0,0,0,0,826,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,816,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,717,1845,0,423,0,0,\n0,0,0,0,0,0,510,0,0,1048,0,0,0,618,0,0,0,520,0,0,0,0,990,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,321,0,0,0,0,0,0,0,1135,0,0,921,0,0,0,24,397,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,856,0,0,0,139,282,981,0,288,0,0,0,1890,651,56,0,0,0,0,0,0,0,\n0,261,0,0,0,0,0,0,0,0,0,0,0,617,1403,0,1205,0,0,563,0,0,0,0,0,0,0,0,333,0,0,0,0,\n0,369,0,0,0,0,0,0,0,0,0,622,0,0,0,1407,0,0,0,0,0,0,0,0,0,0,0,0,624,160,0,363,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,619,0,174,292,0,0,656,616,0,0,0,685,0,0,0,0,0,0,0,0,0,0,0,0,0,647,0,0,0,631,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1267,0,0,0,1797,0,0,0,1684,0,0,469,0,531,\n1230,73,0,0,0,0,0,0,0,0,0,268,0,0,0,0,0,102,558,109,65,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,595,0,0,0,0,0,374,1832,0,0,0,0,0,0,16,0,405,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,881,0,1495,0,0,0,0,0,0,0,0,0,142,0,0,0,0,0,0,0,0,0,0,21,466,23,\n257,0,0,0,0,0,0,77,404,0,0,0,0,0,0,712,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,860,\n1848,0,0,652,629,0,0,0,0,13,377,0,1842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1501,0,\n0,0,1906,0,0,0,0,0,0,0,0,0,0,0,0,0,491,234,171,0,0,0,0,631,1186,0,0,0,0,0,0,0,0,\n0,0,0,0,931,0,170,0,0,0,0,0,0,0,0,0,0,1587,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n765,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,424,0,0,714,0,0,0,0,685,0,0,0,0,0,\n0,285,0,0,0,0,0,0,429,0,0,0,0,0,0,0,0,0,0,71,18,0,0,0,0,0,0,0,0,0,0,116,828,0,0,\n0,0,0,0,289,0,0,0,0,0,0,0,0,675,0,0,0,1424,0,0,0,0,0,647,0,0,0,1334,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,36,209,0,0,0,0,0,0,0,342,0,0,0,928,0,0,0,0,0,1838,118,856,654,\n318,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,915,895,454,0,0,513,1425,0,0,\n0,0,0,0,791,0,153,0,0,0,0,0,0,796,909,445,345,0,0,0,0,0,0,0,0,578,0,0,0,1387,0,\n0,0,555,0,0,0,0,0,0,766,0,0,0,0,0,0,0,0,0,0,541,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,\n0,0,0,0,1506,0,0,983,0,768,0,0,0,0,584,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,737,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,30,426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,462,0,0,0,385,0,398,0,0,0,0,0,0,\n0,0,0,347,0,0,0,0,125,1259,644,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,469,0,0,0,0,0,\n1367,0,0,0,0,0,0,0,0,0,0,0,719,0,0,0,0,0,0,0,0,0,0,0,0,0,1423,0,0,0,0,0,0,0,0,0,\n749,0,0,0,0,546,645,0,0,0,0,0,0,277,0,0,1275,0,0,0,0,0,0,0,453,536,555,0,0,987,\n1107,0,0,90,0,0,0,0,0,0,0,0,860,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n257,0,1768,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,83,\n0,835,0,0,0,0,0,0,0,2006,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,696,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,95,1718,0,0,0,0,0,0,0,26,0,550,0,0,0,0,0,901,0,0,0,0,0,\n0,822,0,0,122,0,0,0,807,0,0,0,0,0,262,0,620,601,34,0,0,170,0,0,0,0,537,0,0,0,0,\n0,0,0,0,0,332,0,0,208,1909,182,261,0,0,0,1721,0,0,0,0,0,933,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,1609,0,895,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,812,0,0,942,1916,0,0,0,0,\n0,0,0,778,0,0,0,137,0,1314,0,0,0,0,0,0,0,1661,0,0,0,0,0,0,0,1591,0,0,0,0,0,0,\n820,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,89,0,1160,230,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,63,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1740,0,0,177,\n170,0,1961,0,0,0,0,0,0,0,0,0,0,0,0,91,0,17,44,0,0,0,0,0,0,0,0,0,270,0,296,0,0,0,\n0,0,0,0,1523,0,0,0,0,0,0,0,0,0,0,757,7,0,0,0,0,0,0,0,0,0,0,530,588,0,0,0,0,0,0,\n0,0,0,786,0,0,0,0,0,580,627,88,447,57,0,0,0,0,0,0,0,0,845,735,0,0,0,0,0,31,15,0,\n460,521,12,424,0,0,0,1302,0,0,0,0,0,0,0,595,0,0,0,13,548,97,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,1472,452,1767,0,0,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,1543,0,1111,0,0,0,0,\n1,0,359,488,0,267,0,0,0,1983,0,0,0,0,0,0,0,1155,0,1575,0,1438,31,0,0,377,101,0,\n0,0,0,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,0,0,0,2023,0,0,0,0,0,1836,0,0,0,0,35,843,\n0,0,0,0,0,0,0,554,0,0,0,536,625,207,0,1371,0,0,0,424,785,336,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,896,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,750,0,0,0,0,238,0,0,\n0,0,0,383,0,0,0,0,0,0,0,0,603,725,11,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,1552,0,0,0,\n0,0,0,0,680,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,435,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1431,0,0,13,112,0,0,356,0,0,0,0,0,0,0,0,0,0,1963,0,0,0,1244,18,0,0,0,0,0,0,867,\n0,0,0,0,0,0,50,708,73,592,0,502,0,0,0,0,0,0,161,347,0,0,0,0,470,33,0,246,571,10,\n0,465,614,0,237,0,0,0,0,0,24,18,0,506,0,0,0,0,0,0,33,309,0,0,0,0,0,0,0,0,0,0,\n140,0,0,0,0,1056,0,0,0,1704,0,0,0,0,0,0,0,1036,0,0,0,0,0,0,0,0,0,1315,432,86,\n264,524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,107,0,0,0,0,0,123,927,0,0,957,1149,0,0,\n0,0,0,778,0,502,196,0,0,0,0,1312,0,0,0,0,0,0,0,855,0,0,0,0,0,0,0,0,0,0,45,1400,\n0,0,0,1003,0,0,0,0,0,1097,0,0,0,0,0,0,0,0,545,612,0,0,0,0,0,0,0,0,0,0,0,0,54,0,\n0,0,0,172,0,0,0,1029,0,0,0,0,0,0,0,0,0,568,0,0,0,732,617,0,0,974,94,989,733,0,0,\n0,0,0,0,1789,0,0,665,2015,0,0,0,0,0,0,806,287,0,0,0,0,0,1539,0,0,0,0,0,0,0,0,0,\n0,182,1563,0,0,0,0,0,0,0,0,0,484,0,0,0,0,0,1623,0,0,0,0,0,0,0,0,878,1833,0,1569,\n0,0,0,0,0,0,0,0,93,0,715,994,0,0,0,0,0,63,0,591,0,0,0,0,0,0,0,749,0,0,0,0,547,\n366,0,0,0,1747,0,0,0,0,0,0,0,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1463,0,772,\n893,0,0,0,48,0,0,941,0,0,690,1785,106,440,0,0,0,0,0,0,0,0,0,0,32,0,332,216,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,852,0,\n0,416,564,0,918,0,1764,0,0,3,0,0,274,0,0,0,0,501,0,0,0,0,0,0,0,851,743,0,49,0,\n879,0,0,47,0,0,0,0,0,0,865,0,1202,0,0,0,0,0,0,47,272,0,0,0,0,0,0,0,0,0,0,0,1455,\n0,0,0,0,891,1911,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,761,0,0,0,0,0,0,0,0,0,407,0,\n183,0,0,490,0,0,0,0,0,0,0,35,731,0,0,0,0,0,0,0,819,0,0,0,0,0,0,0,0,0,0,0,0,0,\n575,0,0,0,0,45,818,0,0,77,222,0,0,0,0,849,1880,0,0,0,633,0,1308,0,0,0,0,0,0,0,0,\n0,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,817,0,0,0,0,0,0,0,0,0,882,0,0,0,914,0,0,0,0,\n0,0,0,0,0,0,865,0,0,426,399,58,0,0,0,0,0,0,538,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,566,0,63,12,0,0,0,\n0,0,0,0,0,0,0,0,0,0,3,114,0,0,0,0,0,0,0,0,576,0,0,0,0,0,0,0,0,933,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,692,0,0,0,0,0,0,0,0,0,0,0,0,752,0,0,0,0,\n0,0,0,0,375,0,1011,0,0,96,0,0,0,0,0,0,0,0,0,148,0,0,0,0,0,0,0,0,0,0,0,337,56,\n666,0,246,394,0,0,0,0,0,0,0,0,437,0,0,0,506,0,0,0,0,1003,0,1163,0,328,0,0,0,0,0,\n0,0,0,1000,0,0,0,0,0,744,101,0,0,0,0,0,726,0,0,176,0,146,9,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,246,1931,29,0,0,1771,0,0,0,0,0,846,6,157,0,0,0,0,0,0,0,0,0,875,0,0,477,\n773,177,639,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1747,0,0,0,0,158,873,0,659,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,391,0,0,0,0,0,0,0,0,0,0,0,0,668,883,0,78,628,0,0,0,\n0,0,0,0,0,0,0,0,0,1460,0,962,0,0,0,0,0,460,0,0,0,0,0,0,0,0,0,0,0,0,0,0,34,199,0,\n0,0,388,474,0,271,0,333,608,0,0,0,0,0,0,49,0,988,0,707,617,0,0,0,0,0,0,0,756,0,\n0,0,0,0,1583,0,0,0,0,0,0,0,0,0,0,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,344,0,0,0,0,0,\n0,0,0,515,1709,0,0,0,0,0,0,0,0,404,0,0,0,0,500,0,0,0,0,0,0,0,0,0,68,216,0,0,0,0,\n0,0,0,488,353,0,0,177,236,0,0,458,490,0,0,0,0,0,0,756,1504,0,757,0,1735,0,0,108,\n598,0,0,0,0};\nconst BROTLI_MODEL(\"small\")\nuint8_t kStaticDictionaryHashLengths[BROTLI_ENC_NUM_HASH_BUCKETS] = {\n8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,4,22,5,0,\n4,0,0,0,0,0,0,0,0,0,0,0,0,14,6,0,0,0,5,0,0,0,0,0,0,0,7,13,0,0,4,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,8,0,0,0,0,0,0,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,4,0,5,13,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,9,0,8,0,0,0,0,0,0,6,0,\n0,9,0,0,0,11,0,0,6,8,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,6,8,0,0,0,0,0,\n0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0,8,4,13,7,0,0,0,0,0,\n7,0,5,0,0,0,0,8,5,0,5,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,8,0,0,0,10,4,0,5,0,4,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,8,7,0,4,9,4,0,0,0,0,0,0,\n9,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,7,18,0,0,0,0,4,9,0,0,4,0,6,0,0,0,6,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,0,0,\n0,9,0,0,0,0,0,0,0,8,6,10,6,0,0,0,4,0,6,8,6,0,0,0,4,0,0,0,0,0,5,0,0,0,6,0,0,0,0,\n10,0,12,7,0,0,0,0,0,4,0,0,0,0,0,5,0,0,8,7,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0,\n0,0,0,0,6,11,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,6,10,0,17,0,8,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,6,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n7,0,0,11,4,0,5,0,0,0,0,0,0,0,0,0,0,10,5,0,6,8,5,0,0,0,0,0,0,0,0,0,0,11,5,0,0,0,\n0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,0,0,0,0,\n0,0,0,0,0,0,5,0,0,0,6,0,0,10,0,0,0,20,0,0,0,0,0,0,0,0,6,9,5,0,0,0,0,10,4,8,0,0,\n4,13,0,0,0,0,0,0,0,9,0,9,0,0,0,0,0,0,0,0,0,0,0,0,4,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,12,5,0,0,10,4,10,7,13,\n0,0,0,0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,19,0,0,4,12,6,9,0,0,0,0,4,0,4,11,0,0,0,0,\n0,0,0,12,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,\n0,5,0,0,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,9,6,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,\n6,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,5,0,0,0,0,14,4,0,0,0,4,12,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0,\n0,0,0,0,0,12,0,9,6,0,0,0,0,13,0,0,5,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,13,0,9,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,8,7,8,4,0,0,0,0,0,0,0,0,0,0,0,7,0,7,0,0,0,4,0,\n0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,8,4,0,0,0,0,0,6,0,7,0,\n0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,0,9,5,0,0,\n0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,4,0,0,0,0,0,0,0,4,\n12,5,11,0,0,0,0,0,0,0,0,0,8,7,0,5,0,0,8,7,0,5,0,0,0,0,8,0,0,0,0,7,0,4,10,0,0,0,\n0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n13,5,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,14,5,0,0,0,7,0,0,10,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,6,0,4,0,5,0,0,0,0,8,5,0,0,0,0,0,0,9,5,9,0,0,0,0,0,0,0,0,6,9,0,\n0,4,0,0,0,7,0,0,0,6,0,0,10,4,0,0,0,0,0,6,0,0,10,0,0,0,8,5,0,0,0,0,0,0,0,0,10,0,\n0,0,0,0,18,4,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,7,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,\n0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0,\n0,4,8,7,0,0,8,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,\n0,0,0,8,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,8,7,0,0,0,0,8,0,12,6,0,6,0,0,0,0,9,7,11,7,0,0,0,\n0,0,0,0,0,0,0,0,0,11,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,6,0,0,0,7,0,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,14,0,0,0,0,0,8,4,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,20,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,12,5,0,7,0,5,0,0,10,0,0,7,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,6,0,4,9,7,0,0,0,\n0,0,7,0,0,0,0,0,0,10,0,9,0,9,0,0,0,0,0,0,0,0,4,9,0,0,0,0,6,0,0,0,0,0,0,0,0,11,4,\n0,6,0,0,0,0,0,0,8,0,8,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,13,6,0,0,11,\n0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,6,18,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,11,\n4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,0,8,\n6,0,0,0,0,0,0,9,6,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,\n0,6,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,6,0,0,10,6,0,0,0,7,0,0,8,0,8,7,0,\n0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,\n0,0,0,8,7,0,0,0,0,0,0,0,0,12,0,12,0,0,0,11,6,0,5,0,0,12,0,12,5,0,7,11,6,0,0,11,\n0,0,0,12,0,0,4,12,7,8,6,0,0,0,0,8,5,0,0,0,0,0,0,0,4,11,0,0,6,0,7,0,0,0,0,0,0,0,\n5,0,6,0,0,0,0,8,0,10,0,0,0,0,0,0,0,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,0,10,0,0,5,0,0,12,6,0,0,0,0,0,0,10,6,0,0,0,0,8,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,5,0,0,0,0,11,0,10,6,0,0,8,6,0,0,0,6,0,7,10,6,0,\n0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,10,7,0,0,0,0,\n10,6,0,0,0,0,0,0,8,5,11,0,8,4,0,0,0,4,0,0,0,0,9,4,8,0,0,0,0,0,0,0,11,6,0,0,0,0,\n10,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,7,0,0,11,0,0,\n0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,13,0,8,6,13,0,0,0,11,7,0,7,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,9,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,\n0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0,0,4,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,\n5,11,5,0,0,0,0,0,0,0,0,0,4,0,7,0,6,0,0,0,6,20,0,0,0,10,7,0,5,14,4,0,0,0,0,0,0,0,\n0,0,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,\n0,0,6,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,11,6,15,0,0,0,0,0,\n10,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,9,7,13,0,0,0,0,0,\n0,7,0,0,8,6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,0,0,0,0,0,0,0,0,0,0,12,6,8,0,12,0,0,7,0,0,0,\n0,0,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,\n14,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,8,7,10,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,18,6,\n14,7,0,0,0,0,0,0,0,0,11,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,11,7,0,0,10,7,0,0,0,6,8,6,0,0,0,0,0,0,0,6,0,0,\n19,0,0,0,9,5,0,0,0,0,0,0,11,7,0,0,0,7,0,6,0,0,11,0,0,0,0,4,8,0,0,0,0,0,0,0,0,6,\n0,0,0,0,0,6,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,\n0,7,0,0,0,7,15,0,0,5,0,0,0,0,10,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n11,7,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,\n0,0,5,0,4,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,6,0,0,8,5,14,0,0,4,0,0,0,7,\n17,0,0,0,0,0,0,0,13,5,0,0,0,0,0,5,0,0,0,5,0,0,0,0,16,6,0,4,0,0,0,0,0,0,12,0,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,5,0,5,0,6,10,0,12,0,0,0,0,0,0,0,0,7,0,0,0,0,8,4,\n0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,0,0,0,8,0,0,6,0,7,0,0,0,5,0,6,0,4,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,22,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,18,0,0,0,9,4,0,0,8,0,9,7,0,0,0,0,0,0,8,6,0,0,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,7,0,0,0,6,0,0,14,0,0,0,0,\n0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,7,10,4,\n0,6,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,6,0,0,0,0,0,0,\n0,0,11,6,12,7,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,9,6,11,6,0,0,0,0,9,5,0,0,0,0,0,0,\n0,6,8,5,0,0,0,0,8,0,10,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,\n5,10,7,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,8,7,0,0,0,6,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22,\n0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0,\n0,0,0,0,0,17,0,0,6,0,6,12,4,19,6,0,0,0,0,16,0,0,0,0,7,15,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,10,4,0,0,8,7,0,7,0,0,9,\n4,0,6,0,0,0,4,0,5,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,10,0,0,0,0,0,11,7,0,0,\n0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,\n0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,8,7,0,0,\n0,0,0,0,0,6,0,0,0,4,0,0,11,4,0,0,12,7,0,0,0,0,9,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,\n4,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,9,4,0,6,0,0,0,0,0,4,\n0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,7,9,6,0,7,0,\n0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,0,0,10,6,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,4,8,0,0,0,0,0,9,7,0,0,0,0,0,0,\n13,5,0,0,0,0,8,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,5,0,0,11,7,0,0,0,0,0,0,8,6,0,\n0,0,0,0,7,0,4,0,0,0,0,0,0,0,5,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,10,4,9,0,0,0,0,0,\n0,4,0,0,0,0,10,5,10,7,0,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,0,0,0,\n0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,4,0,0,0,7,0,0,0,0,0,0,13,0,0,\n0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,13,7,0,7,0,4,16,0,0,0,0,6,8,7,9,7,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,8,5,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,11,7,0,0,11,\n0,0,0,0,0,9,5,0,4,0,0,0,0,9,7,8,6,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,\n0,7,0,0,0,0,0,0,0,0,0,0,0,4,10,6,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,10,7,10,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,6,8,7,12,4,0,0,0,0,0,0,0,5,14,\n0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,20,4,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0,\n0,6,15,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,12,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0,18,0,0,0,10,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,9,6,0,\n6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,9,0,9,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,9,5,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,8,0,0,0,16,0,0,0,0,0,0,0,\n0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,0,0,11,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,11,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,7,0,6,\n0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,0,0,0,6,0,0,18,0,8,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0,4,0,0,0,\n0,0,0,0,0,0,0,8,0,0,0,0,0,16,0,0,0,0,0,16,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,18,0,0,0,0,0,0,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,4,0,\n0,0,0,0,0,0,0,9,4,0,0,0,0,12,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,5,0,0,10,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,11,0,0,6,0,6,0,0,\n0,7,0,0,0,0,0,0,8,0,0,0,0,6,0,0,0,0,0,0,19,0,0,0,12,0,9,0,0,0,0,0,10,7,0,0,0,0,\n0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,16,7,12,\n0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,10,5,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,4,0,0,9,0,0,0,8,0,12,4,0,0,0,0,\n0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0,\n0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,8,6,0,6,0,0,0,0,0,0,\n0,4,0,0,0,0,0,6,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,10,6,0,0,0,0,8,\n6,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,6,\n10,7,0,0,10,5,11,6,0,0,0,0,0,7,16,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,\n0,0,0,0,0,8,7,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,12,7,0,7,0,0,0,\n0,0,0,0,6,0,0,0,0,9,0,0,0,23,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,4,0,0,11,7,10,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,7,0,0,8,7,8,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0,\n0,0,0,0,18,6,8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11,0,0,0,9,7,12,6,0,0,0,0,0,0,0,0,\n0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,6,10,0,0,0,9,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,6,\n10,7,0,0,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,\n0,0,0,8,7,8,6,0,0,11,7,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,4,8,7,0,0,0,0,0,0,0,0,\n0,5,0,0,13,0,0,0,0,5,0,0,9,7,0,0,0,0,0,0,0,4,0,0,11,0,0,7,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,12,7,19,0,8,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,0,0,12,0,0,0,0,6,9,6,\n14,0,0,0,0,0,0,6,0,5,0,0,8,7,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,\n7,0,0,10,0,9,7,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,0,0,0,0,5,0,6,0,0,0,0,\n0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,13,7,\n0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,11,5,0,5,13,0,8,0,\n0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,11,5,\n9,6,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,10,0,0,0,8,5,0,0,9,0,0,0,8,7,9,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0,\n0,11,0,13,6,0,0,9,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,5,21,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,5,0,0,0,0,0,0,0,0,10,0,8,0,\n0,6,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,4,0,0,8,6,0,6,0,7,10,0,8,4,0,4,0,0,0,0,0,\n5,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,12,0,0,7,0,0,0,5,0,0,\n0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n15,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,24,7,0,0,0,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,12,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,15,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0,\n0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,9,0,9,6,\n0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,4,0,7,0,0,0,0,0,0,0,0,\n22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,7,0,0,21,7,0,7,9,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,23,0,0,0,0,7,0,0,0,\n4,0,0,0,0,0,0,0,0,9,4,11,7,0,5,0,0,0,0,11,0,0,4,20,0,0,0,0,0,0,0,0,0,0,0,11,5,0,\n7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n21,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,11,6,0,0,0,0,0,0,0,0,9,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,\n0,0,0,10,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,11,7,0,0,0,0,0,0,0,4,\n0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,7,0,\n0,0,0,0,0,0,0,0,6,0,0,21,6,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,\n0,0,0,8,7,0,0,11,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,13,7,10,4,0,\n0,0,6,0,0,0,0,0,0,0,0,0,5,10,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,8,4,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,\n0,0,0,0,7,0,0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,5,0,6,0,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,4,0,0,0,0,9,0,11,4,0,0,0,6,0,0,0,5,12,7,0,5,0,0,0,0,0,4,0,0,0,7,0,0,0,\n0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,13,6,10,0,0,0,17,0,0,4,0,0,0,0,0,6,0,4,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,7,0,0,0,7,0,0,0,6,0,0,0,0,0,0,\n0,6,0,4,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,4,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,0,0,\n0,0,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,16,4,0,0,11,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n8,7,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,8,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,\n7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,5,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,\n5,18,7,0,0,14,0,0,0,0,0,0,0,9,4,0,7,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,0,0,0,\n8,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,0,0,0,0,0,0,11,0,0,0,\n10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,14,6,0,0,0,0,11,4,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,10,7,0,6,0,0,9,0,9,5,0,0,0,0,0,\n0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,8,5,0,0,0,0,0,0,0,0,0,0,11,4,0,6,\n0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,12,4,0,6,8,6,0,0,0,0,0,0,0,0,0,0,8,0,0,5,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0,\n0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,13,4,0,7,0,0,0,7,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0,\n9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,6,21,5,0,0,0,0,8,0,0,0,0,4,0,\n7,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,\n0,7,9,6,11,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,10,0,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,19,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,9,4,10,4,0,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,9,7,9,7,10,4,0,7,0,0,0,0,0,0,0,6,12,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0,\n0,0,0,0,0,5,0,0,8,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,\n0,0,0,0,4,0,0,8,0,0,6,0,0,0,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,0,4,8,0,0,0,0,6,11,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,13,4,0,0,\n12,6,0,6,0,0,0,0,8,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,4,0,0,0,0,0,0,0,0,0,0,9,\n7,22,0,0,0,0,4,0,0,0,0,0,6,0,0,0,4,0,0,9,0,0,6,0,0,24,7,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,10,6,0,5,0,0,0,0,0,0,0,7,0,0,8,0,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,7,0,\n7,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,\n0,0,0,0,0,7,12,0,9,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,4,0,0,0,7,0,\n0,0,0,8,7,0,0,0,0,0,0,0,0,0,4,18,0,0,0,0,0,10,0,0,5,0,0,11,0,0,0,0,0,0,5,0,6,0,\n0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,\n4,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,\n0,0,0,5,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,20,7,0,0,0,0,0,0,0,0,0,0,0,4,9,0,12,\n6,8,0,14,7,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,10,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,9,6,0,7,12,0,0,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,0,9,0,\n12,6,0,5,0,0,0,6,0,4,0,6,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0,\n10,0,0,0,0,0,0,0,8,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,12,6,20,5,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,5,0,0,0,6,13,7,0,0,0,0,15,6,0,0,0,\n6,0,0,13,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,\n10,6,0,0,0,0,0,6,0,0,0,0,9,0,0,0,0,0,19,6,0,0,0,0,0,0,0,0,0,0,13,0,11,0,0,0,0,0,\n0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,10,0,0,6,0,0,0,0,8,0,0,\n0,9,0,15,4,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,\n0,0,0,0,0,8,7,0,0,0,0,0,6,10,0,0,0,0,0,0,0,0,7,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,10,5,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,6,12,0,0,0,10,7,0,5,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,6,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,4,9,6,0,0,0,7,0,0,0,0,0,0,0,0,8,6,0,0,\n0,0,0,0,0,4,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,6,9,4,0,0,8,4,0,6,\n0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,8,0,0,6,13,4,0,5,8,0,0,0,0,0,0,0,8,0,0,0,10,5,0,0,9,0,0,0,0,0,0,6,0,0,\n24,0,0,0,0,0,0,0,8,0,0,7,0,0,12,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,\n6,8,0,10,0,9,7,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,4,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,8,0,0,\n0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,10,4,0,0,0,0,0,0,0,6,0,0,0,4,20,0,0,7,\n10,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,9,6,0,0,0,0,0,0,0,4,\n12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,9,4,0,5,0,0,\n0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,6,9,0,0,0,0,7,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0,0,9,0,0,0,\n0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,17,7,0,0,13,6,14,6,0,0,0,0,\n8,0,0,0,0,0,0,7,12,7,8,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,4,0,0,0,0,0,4,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,12,4,0,0,10,7,0,0,0,\n0,0,0,10,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,12,0,0,6,\n0,0,0,0,0,0,0,0,8,7,12,0,0,0,0,0,0,6,0,6,0,4,0,0,18,6,0,0,0,6,0,0,0,0,0,6,10,6,\n0,0,0,0,0,0,8,7,14,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,\n0,0,0,8,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,5,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,9,4,8,0,0,0,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,\n0,6,0,0,9,7,0,0,0,0,0,5,0,0,0,0,8,7,0,0,14,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n0,0,0,6,0,0,0,6,0,4,0,0,0,0,0,4,0,0,0,0,12,0,0,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,12,0,16,6,0,0,0,0,0,0,11,7,0,4,8,7,0,0,0,0,0,6,0,0,0,0,16,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,10,7,0,0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,\n0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,13,4,0,0,10,0,0,0,0,0,0,0,0,0,19,0,0,0,\n0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,\n5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,18,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,14,7,0,0,11,5,0,0,0,5,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,24,6,0,0,\n0,7,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,4,0,0,0,0,8,7,0,0,\n9,6,0,0,14,5,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,5,0,0,\n0,0,12,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,13,7,0,0,0,0,0,0,14,0,11,4,0,\n0,0,4,0,0,0,0,14,5,0,0,0,0,0,5,11,5,0,0,0,0,22,5,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0,\n4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,17,0,10,0,0,0,8,0,0,0,19,\n5,18,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,10,6,0,6,0,0,0,0,10,4,0,4,0,\n0,0,0,0,0,14,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,0,9,6,12,0,0,6,0,0,0,0,0,0,0,0,\n12,0,10,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,5,13,0,9,7,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,8,0,0,0,0,0,\n22,0,0,0,0,0,0,0,23,6,14,0,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,10,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,8,5,0,0,0,0,0,0,0,0,0,7,11,6,21,0,0,0,0,0,\n0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,0,4,9,7,0,0,0,0,0,0,12,0,0,0,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,9,\n0,0,0,20,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,7,0,0,0,0,0,0,0,6,15,0,0,\n0,0,0,0,0,0,0,0,0,0,0,12,4,0,5,0,0,0,0,0,0,11,7,17,6,0,0,0,0,0,0,15,6,0,7,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,5,\n0,0,11,0,11,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,\n17,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,7,9,6,0,0,14,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,\n8,7,0,4,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,\n0,0,0,5,0,4,0,0,8,7,0,6,12,5,0,7,18,7,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,\n10,0,11,0,0,0,0,0,0,0,0,0,0,0,9,0,0,4,0,6,0,7,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,\n7,0,0,0,0,8,0,0,0,15,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,0,0,23,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0,\n0,0,0,0,12,7,9,7,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,9,0,8,7,0,0,0,\n6,0,6,0,4,0,5,0,0,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,7,10,5,0,0,11,6,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,4,9,7,0,\n0,0,0,11,7,0,0,0,0,0,5,0,0,0,7,0,0,0,0,23,6,11,4,0,0,0,0,0,0,9,0,0,0,10,6,0,0,0,\n0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,10,6,0,0,0,7,0,0,\n0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,\n6,11,7,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,6,0,0,0,5,0,6,0,6,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,8,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,4,10,0,8,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,11,6,0,4,0,0,14,5,0,7,0,0,0,0,0,6,16,0,0,0,0,0,0,0,10,0,0,7,15,0,0,0,11,7,0,0,\n0,0,0,0,0,0,0,0,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,5,0,0,0,\n0,8,0,0,6,0,0,0,0,0,0,9,5,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,6,0,\n0,0,0,0,0,0,7,0,0,0,0,15,7,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,12,6,11,7,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,\n7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,8,0,0,5,8,7,10,6,0,0,0,7,0,0,0,0,12,6,\n0,0,9,0,0,0,12,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,10,0,0,0,10,5,0,0,0,0,0,0,9,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,9,5,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,0,0,5,0,0,8,7,8,\n6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,10,0,9,4,0,0,0,0,0,0,0,6,\n11,0,0,0,0,0,0,0,0,0,0,0,8,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,8,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,\n0,0,0,10,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,\n0,0,8,4,0,5,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,8,5,0,0,0,\n0,0,0,0,7,0,0,0,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,6,0,7,0,0,0,0,\n20,0,0,0,0,0,0,0,0,0,0,7,9,0,0,0,0,0,0,6,0,6,0,7,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,\n0,0,0,14,7,0,0,0,5,0,0,22,4,10,0,0,0,0,0,0,4,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,11,5,13,0,0,0,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,10,7,0,\n0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,7,14,6,0,0,0,0,9,5,\n0,0,0,0,0,6,0,0,0,5,10,0,8,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,8,4,0,6,0,\n0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,\n14,0,0,5,0,0,18,0,8,4,0,6,0,0,20,0,13,0,0,0,0,7,0,4,0,0,0,0,0,4,8,4,0,0,0,0,0,6,\n0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,14,0,0,0,0,0,9,7,0,0,9,0,0,0,0,\n0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,20,0,14,0,0,4,0,6,8,5,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,4,12,7,0,6,0,0,9,7,10,5,\n0,0,8,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,18,0,0,0,14,7,0,0,0,0,0,4,\n0,0,0,0,0,0,17,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,23,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,7,8,4,0,0,0,0,0,0,0,0,0,6,0,0,9,5,0,0,0,7,0,0,0,\n0,0,0,0,0,0,4,10,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,18,7,\n0,0,8,0,0,5,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,\n6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,10,0,0,5,10,4,0,0,12,0,0,0,0,\n6,22,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,16,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,12,7,0,0,0,0,9,0,0,0,0,6,0,0,11,0,0,0,0,0,13,0,9,6,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,10,7,0,0,0,7,0,6,0,\n0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,11,0,15,0,22,7,0,4,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,\n18,0,0,0,0,0,0,0,0,0,14,0,0,4,0,0,0,0,8,7,9,0,0,0,0,0,9,0,0,0,14,0,0,0,0,0,0,0,\n0,0,11,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,0,0,0,0,8,0,0,0,0,\n0,11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,4,0,0,0,0,0,4,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,\n0,0,0,0,0,0,8,6,0,0,9,5,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0,\n0,10,6,9,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n11,7,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,\n0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,5,0,0,10,6,\n0,0,0,4,0,7,13,0,0,4,0,0,11,4,0,6,0,0,0,0,0,6,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,5,0,0,0,0,12,6,0,0,0,0,\n11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,11,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,\n7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,6,17,0,9,0,10,6,0,6,12,0,0,4,0,0,0,\n0,0,0,0,0,0,0,8,5,12,7,0,4,0,0,0,0,0,0,0,0,0,0,11,0,9,0,10,6,11,5,0,7,0,0,8,0,0,\n7,0,4,0,0,0,7,0,0,0,0,0,0,8,6,0,0,0,6,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,10,0,0,0,0,0,8,6,0,0,0,0,0,6,12,0,0,0,0,0,\n0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,16,0,11,5,0,0,0,0,0,\n0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,10,\n7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,9,5,0,0,0,0,8,0,9,0,0,\n0,0,0,0,0,0,7,10,0,13,0,0,6,0,0,0,0,0,0,0,0,0,6,9,4,0,0,0,0,0,0,10,0,0,0,0,0,10,\n0,0,0,0,0,0,0,10,6,11,0,0,0,0,0,9,0,0,0,0,0,0,4,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0,\n0,0,0,0,0,18,4,0,7,0,0,0,0,0,0,24,0,8,6,0,7,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,5,0,0,0,0,10,7,0,6,0,0,0,0,0,0,0,0,8,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,\n6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,4,0,5,15,0,0,0,0,7,0,7,0,0,0,0,\n0,0,0,0,0,6,10,5,0,0,0,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,12,0,0,0,0,0,0,0,0,\n0,0,5,0,0,0,0,0,0,14,4,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,11,0,10,4,9,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0,\n0,0,0,0,0,0,0,0,7,13,7,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,8,0,10,6,0,4,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,\n0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,9,7,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,11,0,0,0,0,6,0,0,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0,\n6,0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,\n0,0,0,0,0,0,0,6,0,6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,10,0,11,5,0,0,0,0,0,0,14,7,9,7,\n0,6,0,0,0,0,0,4,0,0,0,0,0,0,11,7,0,6,0,0,0,0,0,0,9,7,0,4,0,0,0,7,0,0,0,0,0,5,0,\n0,0,0,0,5,0,0,0,7,0,0,0,0,0,5,0,0,0,0,17,5,0,0,8,0,0,0,0,6,9,4,0,0,0,0,0,0,0,0,\n8,7,11,7,9,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,9,5,0,0,8,6,0,0,0,5,0,\n0,0,0,9,0,0,0,9,6,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,4,0,0,0,5,0,0,0,0,0,7,0,0,0,0,0,7,13,5,0,0,0,7,0,0,0,0,0,7,9,6,11,7,0,7,0,0,0,\n0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,8,5,0,0,0,5,9,4,0,0,0,0,0,0,0,0,8,4,0,0,0,0,\n24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,\n0,0,0,0,6,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6,0,4,0,7,20,0,8,5,9,5,9,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,7,23,5,0,0,8,4,0,0,10,0,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0,\n10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,\n6,0,0,0,0,14,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,6,0,4,0,0,0,0,0,0,8,4,\n11,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,12,0,10,7,0,0,10,0,0,0,0,\n0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,6,0,0,0,0,8,\n6,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,6,0,4,0,0,0,0,0,5,0,0,\n0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,17,7,11,0,0,0,0,0,0,0,0,0,0,4,12,6,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,5,12,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,0,20,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,4,\n0,0,0,5,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,4,13,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,12,6,0,7,0,0,0,0,10,0,23,6,0,0,\n0,4,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n10,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,11,0,9,7,0,0,\n0,0,0,0,0,0,0,0,9,7,0,4,0,0,0,0,8,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,\n0,0,0,0,0,6,0,0,10,7,10,5,0,0,8,0,8,0,0,0,0,0,0,4,0,5,10,0,0,0,0,0,0,0,9,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,6,0,0,8,\n7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,24,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,6,0,0,9,0,0,0,0,0,0,7,0,6,13,0,8,\n0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,\n4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,5,0,7,0,0,10,0,10,7,0,0,12,5,0,0,9,0,0,0,10,0,\n0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,\n12,0,0,0,0,0,8,5,13,6,0,0,0,0,0,0,9,4,0,0,0,0,8,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,14,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,17,6,0,0,0,0,12,6,0,0,0,0,8,0,0,7,0,\n7,0,4,9,0,0,6,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,0,0,0,11,0,0,4,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,18,7,0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,11,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0,\n11,0,0,0,0,0,0,0,21,0,0,6,10,0,0,0,0,0,9,0,10,0,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0,\n5,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,4,0,0,23,7,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,0,7,\n0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,\n11,6,0,0,0,0,0,0,0,6,0,0,0,0,10,7,0,0,9,4,0,0,11,0,8,5,0,0,0,7,8,5,22,0,0,0,9,6,\n0,0,0,0,0,0,0,6,10,4,0,0,0,0,0,7,9,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,\n0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,6,0,4,0,0,\n0,0,0,0,0,7,0,7,0,4,13,0,0,0,0,0,8,0,0,0,0,7,0,0,0,0,0,0,11,6,0,7,0,0,0,0,9,0,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,8,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,13,5,8,0,0,\n0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,17,6,0,0,0,0,13,4,0,0,9,6,0,0,10,5,0,\n0,10,5,0,0,0,0,13,0,0,0,0,6,0,0,0,0,0,0,10,0,12,0,0,0,0,0,0,0,0,0,0,0,8,4,0,4,0,\n0,0,4,0,0,0,0,0,4,0,0,12,0,0,5,9,4,0,0,0,0,0,0,0,0,0,5,8,5,0,0,0,7,0,0,0,0,8,7,\n0,0,0,6,12,5,0,0,0,5,0,0,0,5,0,0,0,0,0,4,12,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,9,6,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,4,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,12,7,0,0,0,7,10,7,0,0,11,0,0,0,0,0,0,0,0,0,11,7,0,0,0,6,0,0,11,0,0,0,0,\n0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22,0,10,7,0,0,8,5,0,0,0,0,0,5,0,0,0,0,0,0,\n0,0,0,0,9,6,8,7,0,6,0,0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,9,7,0,0,0,6,0,0,8,7,0,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,5,0,0,0,4,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,5,0,0,0,0,14,0,0,0,\n9,0,0,0,0,0,0,0,0,0,9,7,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,12,0,0,0,0,0,12,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,9,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0,7,12,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,\n0,7,0,0,8,6,0,0,0,0,10,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,6,0,0,0,6,0,0,0,0,0,6,16,0,0,0,0,0,0,0,0,0,9,0,17,0,14,7,8,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,0,0,11,0,0,6,8,7,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,\n9,0,0,0,0,7,0,0,0,0,11,5,0,4,9,6,8,0,0,0,0,0,0,0,0,0,10,0,11,7,0,0,0,0,0,0,0,0,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,\n0,0,0,12,0,0,0,0,0,10,5,0,4,0,0,0,0,0,7,10,6,11,6,0,0,0,0,0,0,0,0,0,0,0,0,17,0,\n0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,8,0,0,4,0,0,0,6,0,0,0,\n0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,4,0,0,0,0,9,6,0,0,0,4,0,0,0,0,0,4,10,7,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,6,0,0,0,6,0,6,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,18,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,13,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,\n0,0,0,6,0,0,0,0,0,4,8,0,0,0,11,7,0,0,0,4,0,0,0,0,0,7,0,0,8,5,0,0,16,0,0,0,13,6,\n0,0,0,0,0,0,0,6,0,0,0,0,20,0,11,6,0,0,8,7,0,0,0,0,0,6,17,0,8,0,0,0,0,0,8,7,0,0,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,\n0,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,8,\n0,8,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,6,0,0,9,0,\n0,0,0,0,8,0,0,0,0,0,18,0,0,0,0,0,0,4,9,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,9,6,0,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,7,0,0,0,0,0,0,0,0,\n0,4,0,0,0,0,0,0,14,0,0,0,0,7,0,6,0,0,8,0,20,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,8,0,0,7,0,6,0,0,0,7,0,0,0,0,0,0,0,0,\n0,0,0,4,12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,6,0,\n5,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,0,0,5,8,4,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,12,7,0,\n0,0,0,13,6,0,0,0,7,0,0,8,0,0,0,8,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,11,5,\n0,6,0,0,8,5,0,7,0,0,0,0,0,0,0,7,0,0,0,0,8,6,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,4,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n14,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,19,0,0,4,0,0,0,7,\n0,0,11,5,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,16,0,10,5,18,0,0,7,9,6,0,5,0,0,0,0,0,\n0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0,0,7,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,4,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,23,0,0,0,0,5,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,20,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,\n11,0,0,0,0,7,0,0,0,0,15,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0,\n0,4,0,0,0,0,10,0,0,0,0,0,9,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,0,11,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,5,0,0,11,0,0,0,0,7,0,0,0,0,0,0,8,7,0,\n4,0,0,0,0,11,0,0,0,0,0,11,0,0,5,0,0,8,7,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0,\n0,0,4,11,5,10,7,0,7,0,0,9,6,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,9,4,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,8,6,0,0,0,0,11,7,0,0,0,0,0,0,0,0,0,0,11,7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,8,5,0,0,8,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,\n10,7,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,10,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0,\n0,0,6,0,0,0,0,9,5,8,5,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,\n0,8,7,10,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,5,0,0,0,6,0,7,0,0,\n10,5,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,11,0,0,0,0,0,13,4,\n0,0,0,4,0,0,0,0,0,5,8,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,7,14,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,15,6,10,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,14,6,10,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,6,0,5,11,4,0,6,0,0,0,7,0,0,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,8,5,0,0,0,0,0,0,0,0,0,0,\n0,0,10,0,0,0,0,0,9,6,9,4,0,0,0,4,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0,\n0,0,0,0,0,0,0,0,0,0,4,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,\n0,0,0,7,12,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,\n4,9,6,0,4,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0,\n7,8,6,0,0,0,0,0,0,0,4,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,5,0,4,0,0,0,0,0,0,0,5,0,0,0,\n0,0,5,0,0,0,7,12,7,0,0,0,0,0,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,6,0,0,0,\n0,12,0,0,7,0,0,0,0,0,7,0,0,13,0,0,6,0,0,0,0,8,7,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,7,10,5,0,0,8,0,0,0,0,0,0,0,8,6,0,7,0,0,8,4,0,4,0,0,0,0,10,4,0,0,14,0,\n0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,17,0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,10,5,0,0,0,0,8,\n6,0,0,0,6,0,0,0,7,0,0,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,12,0,0,0,0,6,\n8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,24,0,0,\n0,0,0,12,6,0,0,10,6,0,5,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,7,0,5,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,11,5,9,0,8,7,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,5,8,7,0,0,0,\n0,8,5,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,\n0,6,12,0,8,7,0,0,0,0,0,0,0,0,0,0,16,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,22,0,0,0,\n0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,22,0,0,6,0,0,21,0,0,0,22,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,7,8,0,0,0,0,6,14,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,0,8,5,0,0,11,7,0,6,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,8,7,0,0,0,0,8,5,11,7,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,8,5,0,0,10,0,0,4,13,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,13,6,\n0,6,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,15,0,0,0,10,7,0,0,0,0,0,\n7,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,19,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,5,\n0,7,0,0,0,0,0,0,0,0,0,6,0,0,11,4,0,0,0,6,0,0,13,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,\n0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6,\n0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,\n0,0,0,8,7,0,0,0,0,9,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,10,0,\n0,6,0,0,13,0,0,0,0,0,0,0,9,6,0,0,8,6,8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,\n0,9,7,0,0,0,0,0,0,11,0,0,0,10,7,0,0,0,0,0,0,0,0,9,6,0,0,12,4,0,4,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,21,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0,0,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,\n16,0,0,4,0,0,0,0,0,7,0,0,0,6,0,6,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0,\n0,14,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,\n0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,\n0,0,0,0,6,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,14,7,0,0,9,7,0,0,11,0,0,0,0,0,10,\n4,11,5,13,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,5,0,0,0,0,0,4,0,0,9,0,0,0,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,12,5,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,4,9,4,\n0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0,0,\n0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,11,6,0,0,13,7,0,0,13,6,0,7,0,0,0,0,0,0,8,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,6,0,4,0,0,12,6,0,0,0,0,0,0,0,0,10,6,\n0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,7,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0,\n0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,\n0,0,0,5,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,5,0,0,0,4,9,5,0,0,0,7,10,6,0,0,\n0,0,0,0,9,7,0,0,8,5,8,0,8,4,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,11,7,0,0,0,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,5,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,7,0,0,0,0,8,5,0,4,0,0,0,0,0,6,0,6,14,\n6,0,0,0,0,9,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,6,0,0,0,0,14,7,9,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0,\n0,6,0,0,8,6,0,0,0,0,0,6,0,0,12,0,0,0,0,0,8,5,0,7,11,0,0,5,0,4,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,9,6,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,10,5,0,0,0,0,\n0,4,0,0,0,7,11,6,0,4,8,5,9,5,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,5,14,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,16,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,6,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,5,0,0,0,0,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,4,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,10,4,0,0,0,0,0,5,0,0,0,4,\n0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,0,10,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,7,0,0,0,0,0,0,0,0,15,0,0,0,\n0,0,0,0,0,0,0,7,0,0,0,0,0,7,10,7,9,7,0,0,0,7,0,0,8,0,0,0,0,0,0,0,9,0,0,0,8,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,15,7,12,6,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,5,0,0,0,0,\n0,0,0,6,9,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,14,0,0,0,11,7,0,0,0,0,0,\n0,0,0,0,0,0,4,0,0,11,7,0,0,0,0,8,0,0,0,0,0,0,6,8,7,0,0,0,7,10,4,0,0,0,0,0,0,0,0,\n0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,10,0,0,0,0,0,0,\n6,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,7,0,0,0,0,9,7,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,12,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,9,6,0,0,11,0,0,\n0,0,0,14,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,7,0,0,\n0,0,0,6,0,7,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,20,\n7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,0,0,0,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,5,8,5,10,4,0,0,0,0,0,\n0,13,6,9,7,0,0,10,7,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,7,0,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,10,7,0,0,\n0,0,0,0,0,0,0,0,12,4,0,0,0,0,8,7,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,\n0,0,0,0,6,0,6,9,6,0,0,12,5,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,\n0,0,0,0,0,0,0,0,0,5,8,7,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11,\n4,0,0,0,0,0,0,8,0,0,0,10,7,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,0,\n0,0,0,0,0,5,0,6,0,0,10,0,14,0,0,0,0,0,0,0,23,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0,\n5,0,0,0,0,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,22,0,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,\n0,0,0,0,0,6,18,4,0,0,0,7,10,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,\n0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,0,0,0,0,0,0,6,0,0,0,0,11,5,0,0,0,0,0,0,0,0,\n15,0,8,6,0,0,13,7,0,0,0,0,0,7,0,0,0,0,0,7,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,5,9,\n0,0,6,8,6,0,0,0,0,10,0,0,0,18,5,0,0,0,5,0,7,0,0,0,0,8,6,0,0,0,0,9,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,14,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0,\n0,0,0,0,20,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,8,4,24,0,0,0,0,0,0,\n0,0,0,0,0,0,0,9,7,0,0,0,0,10,5,0,0,8,5,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,6,0,0,0,\n0,14,0,0,4,9,5,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,8,0,0,0,0,0,11,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,8,5,11,7,0,4,0,0,10,0,0,0,0,\n0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,6,0,0,0,0,0,5,14,6,0,0,0,0,10,0,0,\n0,13,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,12,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,10,0,9,\n7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,9,7,0,0,0,\n0,0,0,0,0,0,0,0,0,24,0,11,7,0,7,0,0,0,0,0,0,8,6,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0,\n0,6,9,0,0,0,23,5,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,18,4,0,0,11,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,0,0,0,11,0,0,0,23,0,0,\n0,10,4,0,0,0,0,0,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,7,0,0,19,0,11,0,0,0,0,0,12,7,0,\n0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,\n9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,22,0,8,7,10,4,11,0,13,5,8,7,9,0,8,7,0,0,0,7,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,\n0,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,4,0,0,0,4,11,0,0,6,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,5,0,0,\n20,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,7,0,0,14,0,0,0,9,0,13,7,0,0,0,0,0,6,0,7,0,0,8,6,10,6,0,0,8,6,0,0,0,6,0,\n0,12,6,9,0,0,0,0,0,0,5,9,0,12,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,\n0,0,4,8,0,0,6,8,0,0,0,0,0,0,0,0,0,13,6,0,7,0,0,0,0,0,6,8,7,8,6,0,0,0,7,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,18,0,11,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14,\n6,0,0,0,0,12,7,8,0,0,0,0,0,0,0,8,7,0,0,0,0,10,4,0,0,0,0,0,0,10,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,15,6,9,7,0,0,0,0,0,0,15,6,11,7,0,0,0,7,0,0,21,0,0,\n0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,6,0,0,10,5,0,5,0,0,0,0,0,0,0,0,0,7,\n0,0,10,0,0,0,0,0,0,0,0,4,11,5,0,0,0,0,16,7,0,0,0,0,0,6,0,0,8,7,0,4,0,0,10,0,0,0,\n0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,\n0,0,0,10,4,0,0,0,0,0,0,0,0,0,6,0,5,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,\n0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,8,4,0,0,10,0,0,0,0,4,0,6,0,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,17,0,0,0,0,0,\n0,0,0,0,0,0,10,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,4,0,0,0,0,0,6,0,0,0,0,0,0,10,5,0,0,\n0,5,0,0,0,0,9,0,19,7,0,0,0,0,0,7,0,0,0,0,10,6,0,0,0,6,0,5,0,0,0,0,0,0,0,0,0,6,8,\n0,0,0,0,0,11,0,0,0,0,0,0,6,0,0,0,0,0,7,9,0,15,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,\n0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,6,0,0,\n0,0,0,6,10,0,0,0,0,0,0,0,23,0,14,0,0,0,0,7,0,0,0,0,0,7,0,0,9,0,0,0,0,7,0,0,0,0,\n0,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,\n0,0,0,0,0,9,5,0,0,0,0,0,4,0,0,0,0,9,5,0,0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,14,7,0,0,12,7,0,0,0,\n0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,8,6,10,0,0,0,0,0,0,0,0,0,10,7,8,5,0,0,0,0,0,0,\n0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,5,0,0,9,5,0,0,0,0,0,5,0,0,0,0,0,4,0,0,0,\n0,0,0,0,0,0,0,12,4,11,0,0,0,9,0,11,7,0,0,0,0,0,0,10,6,0,0,0,6,0,0,0,0,15,5,0,0,\n11,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,4,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,0,0,0,19,7,0,4,0,0,9,0,0,0,0,0,10,0,\n0,6,0,0,13,0,12,6,0,0,0,0,0,0,0,0,10,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,13,7,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,9,0,0,0,10,0,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,10,0,23,6,0,0,0,6,8,0,0,0,0,0,0,0,0,0,17,7,0,0,0,0,11,6,22,5,0,\n0,9,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,9,4,0,0,\n0,7,0,7,0,0,0,0,0,0,12,4,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n4,0,0,11,5,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,6,0,0,0,4,0,0,0,0,\n0,0,0,0,0,7,0,0,0,4,0,0,10,4,0,0,0,0,0,0,0,7,0,7,0,0,0,6,0,0,0,0,8,6,0,6,0,6,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,6,22,6,12,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,11,0,0,0,\n9,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,6,0,0,0,6,0,6,0,0,8,7,0,0,0,4,9,7,19,0,0,0,0,0,0,0,0,0,9,6,10,6,0,6,0,0,0,\n4,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,16,7,10,6,0,0,23,6,11,7,0,4,0,0,0,0,0,0,0,0,0,\n5,0,0,0,0,10,7,0,0,0,0,0,7,0,0,0,0,0,0,15,0,10,0,0,0,14,6,0,0,0,0,0,0,0,0,0,0,0,\n5,0,0,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,5,0,0,11,5,0,0,0,0,0,0,0,0,0,0,\n0,4,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,10,6,0,0,0,0,8,4,0,0,0,7,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,12,5,0,0,0,0,\n0,6,0,0,0,0,9,6,0,0,0,0,0,0,0,6,9,0,0,0,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,6,0,0,0,0,\n0,0,0,0,0,0,10,5,0,0,0,0,0,0,8,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,5,0,0,0,0,0,7,0,7,0,4,0,0,10,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,13,\n7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0,0,7,10,5,0,0,0,0,0,0,9,7,0,0,8,6,9,\n5,0,0,0,0,0,6,12,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,0,19,7,0,4,0,0,0,0,9,5,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,7,0,0,0,0,0,0,14,0,0,0,23,7,8,7,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,7,0,0,0,0,0,0,0,0,9,7,8,4,0,\n0,0,0,0,0,0,0,8,5,0,6,0,0,0,0,0,6,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,\n8,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,8,6,0,0,11,7,0,0,0,\n0,12,0,8,6,19,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,11,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,11,7,0,0,0,0,0,4,10,0,0,0,0,0,0,0,8,7,0,0,0,0,14,0,8,0,0,6,10,0,0,\n0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0,\n0,0,0,0,13,0,0,0,0,0,0,0,11,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,6,0,0,0,5,0,7,0,0,0,\n0,0,6,0,0,21,7,0,0,9,6,0,0,0,6,0,0,13,7,0,0,0,5,0,0,0,0,0,4,0,6,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,11,5,0,6,0,0,10,5,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,15,4,0,0,12,7,0,0,0,6,\n0,7,0,0,8,0,9,5,0,4,0,0,0,6,0,6,0,0,23,4,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,8,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,6,0,0,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0,\n9,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,11,5,0,0,0,6,0,6,0,0,0,0,0,0,0,6,0,\n4,0,0,0,0,0,0,0,0,0,0,0,5,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,8,7,0,0,0,6,0,6,0,\n0,0,0,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,10,5,9,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,23,7,0,0,0,0,0,7,0,0,10,6,18,0,0,0,\n0,0,0,0,8,7,0,6,0,0,0,0,0,0,8,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,4,12,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,13,5,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,\n11,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,0,11,0,0,0,0,0,0,0,0,0,\n17,5,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,8,7,0,0,0,0,0,0,0,\n0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,\n10,0,0,0,8,6,0,0,0,7,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,\n10,0,0,0,16,5,0,0,0,0,0,0,8,0,0,4,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,10,0,0,0,\n0,0,0,0,0,5,0,0,0,0,12,5,0,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,12,6,0,0,0,0,0,7,0,6,0,6,12,6,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n16,0,8,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,23,5,0,0,0,7,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,14,0,0,0,0,7,0,0,0,4,17,5,0,0,0,0,11,0,9,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,5,0,7,0,0,0,0,0,0,0,0,8,0,0,0,\n12,6,0,0,0,0,0,0,13,0,0,0,0,7,9,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,10,7,12,0,0,0,9,0,\n0,0,14,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,15,6,0,0,23,0,0,7,0,6,0,0,0,7,0,6,\n0,0,0,0,0,0,0,6,0,6,9,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,8,7,9,4,0,0,10,0,0,0,10,\n6,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,6,0,0,0,0,0,0,9,4,\n0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,9,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,12,0,0,\n0,0,0,8,0,0,6,11,6,0,0,8,7,8,5,0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,\n10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,\n7,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,8,0,0,0,0,6,12,5,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,0,10,\n7,0,0,8,0,0,0,0,4,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,\n0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,5,0,0,0,0,8,0,0,0,10,7,0,0,0,0,10,0,0,0,\n0,0,13,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,19,7,0,4,12,0,8,0,0,0,0,6,0,0,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,18,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,\n0,14,0,0,4,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,0,0,0,10,4,0,0,9,7,0,0,11,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,12,0,0,0,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,22,5,9,7,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,9,6,0,5,0,0,0,0,0,0,10,5,0,0,8,6,0,6,10,5,0,0,0,6,0,0,0,6,0,0,20,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,17,4,0,7,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,\n0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,\n0,0,7,0,0,8,6,12,0,0,7,18,7,0,0,8,4,0,0,0,0,9,6,0,0,0,0,0,0,0,0,13,0,0,6,0,0,0,\n0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,12,0,0,0,8,0,0,0,0,0,0,\n4,0,0,10,0,16,0,0,0,0,0,0,0,12,7,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16,6,10,0,0,5,0,0,0,0,0,6,0,0,0,0,\n0,7,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,7,0,0,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,4,0,0,0,0,\n8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,8,0,0,0,\n9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,13,5,0,5,0,0,0,7,8,4,0,0,0,0,0,0,0,\n0,12,0,0,0,0,0,0,0,0,0,0,0,8,6,0,6,0,0,11,0,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,6,0,0,10,6,0,0,\n0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,6,0,0,0,7,0,0,9,0,8,7,11,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,9,6,10,5,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0,0,11,0,9,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,15,5,12,5,\n0,0,0,0,0,0,12,7,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,12,6,0,\n0,0,0,24,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,10,4,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,\n0,0,8,0,0,0,0,7,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,\n0,0,0,0,0,14,7,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,6,0,0,0,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,7,20,7,11,4,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,9,6,0,0,12,7,0,0,0,0,0,0,10,0,12,0,\n0,0,0,0,0,4,9,6,13,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,0,0,0,0,0,0,\n0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,11,0,9,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,4,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,7,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,8,7,0,0,0,0,0,0,12,0,0,6,0,0,0,0,0,0,0,6,8,4,0,0,10,7,0,0,10,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,5,\n0,4,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,0,0,7,0,5,8,4,0,0,9,0,0,0,0,4,\n0,0,0,0,0,0,0,0,0,5,0,0,15,6,8,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,4,0,\n6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,9,5,0,6,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,12,7,0,0,0,0,\n0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,10,\n7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,8,7,9,6,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,5,12,0,\n10,5,12,6,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,5,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,\n11,7,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,6,0,7,0,0,0,0,8,0,8,5,0,6,0,0,0,6,0,0,0,\n0,0,0,0,6,0,6,0,6,9,0,0,5,17,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,7,0,0,0,0,16,5,0,0,0,0,0,0,0,4,0,0,0,5,11,5,0,7,0,0,0,4,8,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,12,0,0,0,\n0,0,12,0,0,0,0,0,0,0,0,4,10,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,20,5,0,0,\n10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,12,0,0,0,0,0,0,6,0,0,0,0,0,0,9,4,10,7,0,4,0,0,\n0,0,0,0,10,6,0,0,0,0,8,4,0,7,8,6,0,6,8,0,10,0,0,0,0,0,13,5,0,6,0,0,0,0,0,0,22,4,\n0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,10,\n5,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,10,4,0,0,10,7,0,0,0,0,0,5,0,\n5,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,4,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,\n4,0,0,0,4,10,0,0,6,13,7,8,0,0,0,0,0,0,7,0,0,12,7,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,6,0,6,\n0,0,0,0,0,0,0,0,12,0,8,4,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,5,0,0,0,0,12,5,0,0,0,7,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,10,0,0,0,20,0,0,5,0,0,10,\n7,11,7,0,0,0,0,0,0,0,0,0,0,17,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,10,7,0,4,0,6,0,0,24,0,0,5,0,0,0,0,8,0,0,\n0,0,0,0,0,10,5,0,4,0,6,0,0,8,0,0,0,0,0,0,4,0,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,\n0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,7,\n0,0,13,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,\n17,7,0,0,11,6,0,0,0,0,12,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,4,8,6,0,0,0,\n0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,9,5,0,7,18,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,0,0,0,\n0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,6,0,0,9,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,\n0,0,0,8,7,10,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,10,0,0,0,0,6,0,7,0,4,0,0,0,0,0,0,0,0,\n8,0,0,0,0,0,8,4,0,0,0,0,0,5,0,0,10,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,11,0,0,\n7,0,0,0,0,0,6,10,5,0,0,0,0,0,0,0,0,0,5,0,0,9,5,12,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,13,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,\n0,0,0,8,4,0,6,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,11,4,0,0,0,6,14,0,11,0,9,6,0,0,0,0,0,0,22,0,12,0,8,6,0,0,0,0,0,0,0,6,0,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,\n10,7,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,11,0,0,0,0,0,0,0,8,6,0,0,9,\n7,0,0,12,4,0,0,0,0,0,0,12,6,0,6,0,7,0,0,8,5,0,0,0,0};\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/enc_static_init.c",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"static_init.h\"\n\n#include \"../common/platform.h\"\n#include \"../common/static_init.h\"\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\n#include \"../common/dictionary.h\"\n#include \"dictionary_hash.h\"\n#include \"static_dict_lut.h\"\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\nstatic BROTLI_BOOL DoBrotliEncoderStaticInit(void) {\n  const BrotliDictionary* dict = BrotliGetDictionary();\n  BROTLI_BOOL ok = BrotliEncoderInitStaticDictionaryLut(\n      dict, kStaticDictionaryBuckets, kStaticDictionaryWords);\n  if (!ok) return BROTLI_FALSE;\n  ok = BrotliEncoderInitDictionaryHash(dict, kStaticDictionaryHashWords,\n                                       kStaticDictionaryHashLengths);\n  if (!ok) return BROTLI_FALSE;\n  return BROTLI_TRUE;\n}\n#endif  /* BROTLI_STATIC_INIT_NONE */\n\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)\nstatic BROTLI_BOOL kEarlyInitOk;\nstatic __attribute__((constructor)) void BrotliEncoderStaticInitEarly(void) {\n  kEarlyInitOk = DoBrotliEncoderStaticInit();\n}\n#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)\nstatic BROTLI_BOOL kLazyInitOk;\nvoid BrotliEncoderLazyStaticInitInner(void) {\n  kLazyInitOk = DoBrotliEncoderStaticInit();\n}\n#endif  /* BROTLI_STATIC_INIT_EARLY */\n\nBROTLI_BOOL BrotliEncoderEnsureStaticInit(void) {\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_NONE)\n  return BROTLI_TRUE;\n#elif (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_EARLY)\n  return kEarlyInitOk;\n#else\n  return kLazyInitOk;\n#endif\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/encode.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Implementation of Brotli compressor. */\n\n#include <brotli/encode.h>\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include <brotli/shared_dictionary.h>\n#include \"../common/version.h\"\n#include \"backward_references_hq.h\"\n#include \"backward_references.h\"\n#include \"bit_cost.h\"\n#include \"brotli_bit_stream.h\"\n#include \"command.h\"\n#include \"compound_dictionary.h\"\n#include \"compress_fragment_two_pass.h\"\n#include \"compress_fragment.h\"\n#include \"dictionary_hash.h\"\n#include \"encoder_dict.h\"\n#include \"fast_log.h\"\n#include \"hash.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"metablock.h\"\n#include \"params.h\"\n#include \"quality.h\"\n#include \"ringbuffer.h\"\n#include \"state.h\"\n#include \"static_init.h\"\n#include \"utf8_util.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define COPY_ARRAY(dst, src) memcpy(dst, src, sizeof(src));\n\nstatic size_t InputBlockSize(BrotliEncoderState* s) {\n  return (size_t)1 << s->params.lgblock;\n}\n\nstatic uint64_t UnprocessedInputSize(BrotliEncoderState* s) {\n  return s->input_pos_ - s->last_processed_pos_;\n}\n\nstatic size_t RemainingInputBlockSize(BrotliEncoderState* s) {\n  const uint64_t delta = UnprocessedInputSize(s);\n  size_t block_size = InputBlockSize(s);\n  if (delta >= block_size) return 0;\n  return block_size - (size_t)delta;\n}\n\nBROTLI_BOOL BrotliEncoderSetParameter(\n    BrotliEncoderState* state, BrotliEncoderParameter p, uint32_t value) {\n  /* Changing parameters on the fly is not implemented yet. */\n  if (state->is_initialized_) return BROTLI_FALSE;\n  /* TODO(eustas): Validate/clamp parameters here. */\n  switch (p) {\n    case BROTLI_PARAM_MODE:\n      state->params.mode = (BrotliEncoderMode)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_QUALITY:\n      state->params.quality = (int)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_LGWIN:\n      state->params.lgwin = (int)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_LGBLOCK:\n      state->params.lgblock = (int)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:\n      if ((value != 0) && (value != 1)) return BROTLI_FALSE;\n      state->params.disable_literal_context_modeling = TO_BROTLI_BOOL(!!value);\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_SIZE_HINT:\n      state->params.size_hint = value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_LARGE_WINDOW:\n      state->params.large_window = TO_BROTLI_BOOL(!!value);\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_NPOSTFIX:\n      state->params.dist.distance_postfix_bits = value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_NDIRECT:\n      state->params.dist.num_direct_distance_codes = value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_STREAM_OFFSET:\n      if (value > (1u << 30)) return BROTLI_FALSE;\n      state->params.stream_offset = value;\n      return BROTLI_TRUE;\n\n    default: return BROTLI_FALSE;\n  }\n}\n\n/* Wraps 64-bit input position to 32-bit ring-buffer position preserving\n   \"not-a-first-lap\" feature. */\nstatic uint32_t WrapPosition(uint64_t position) {\n  uint32_t result = (uint32_t)position;\n  uint64_t gb = position >> 30;\n  if (gb > 2) {\n    /* Wrap every 2GiB; The first 3GB are continuous. */\n    result = (result & ((1u << 30) - 1)) | ((uint32_t)((gb - 1) & 1) + 1) << 30;\n  }\n  return result;\n}\n\nstatic uint8_t* GetBrotliStorage(BrotliEncoderState* s, size_t size) {\n  MemoryManager* m = &s->memory_manager_;\n  if (s->storage_size_ < size) {\n    BROTLI_FREE(m, s->storage_);\n    s->storage_ = BROTLI_ALLOC(m, uint8_t, size);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->storage_)) return NULL;\n    s->storage_size_ = size;\n  }\n  return s->storage_;\n}\n\nstatic size_t HashTableSize(size_t max_table_size, size_t input_size) {\n  size_t htsize = 256;\n  while (htsize < max_table_size && htsize < input_size) {\n    htsize <<= 1;\n  }\n  return htsize;\n}\n\nstatic int* GetHashTable(BrotliEncoderState* s, int quality,\n                         size_t input_size, size_t* table_size) {\n  /* Use smaller hash table when input.size() is smaller, since we\n     fill the table, incurring O(hash table size) overhead for\n     compression, and if the input is short, we won't need that\n     many hash table entries anyway. */\n  MemoryManager* m = &s->memory_manager_;\n  const size_t max_table_size = MaxHashTableSize(quality);\n  size_t htsize = HashTableSize(max_table_size, input_size);\n  int* table;\n  BROTLI_DCHECK(max_table_size >= 256);\n  if (quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n    /* Only odd shifts are supported by fast-one-pass. */\n    if ((htsize & 0xAAAAA) == 0) {\n      htsize <<= 1;\n    }\n  }\n\n  if (htsize <= sizeof(s->small_table_) / sizeof(s->small_table_[0])) {\n    table = s->small_table_;\n  } else {\n    if (htsize > s->large_table_size_) {\n      s->large_table_size_ = htsize;\n      BROTLI_FREE(m, s->large_table_);\n      s->large_table_ = BROTLI_ALLOC(m, int, htsize);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->large_table_)) return 0;\n    }\n    table = s->large_table_;\n  }\n\n  *table_size = htsize;\n  memset(table, 0, htsize * sizeof(*table));\n  return table;\n}\n\nstatic void EncodeWindowBits(int lgwin, BROTLI_BOOL large_window,\n    uint16_t* last_bytes, uint8_t* last_bytes_bits) {\n  if (large_window) {\n    *last_bytes = (uint16_t)(((lgwin & 0x3F) << 8) | 0x11);\n    *last_bytes_bits = 14;\n  } else {\n    if (lgwin == 16) {\n      *last_bytes = 0;\n      *last_bytes_bits = 1;\n    } else if (lgwin == 17) {\n      *last_bytes = 1;\n      *last_bytes_bits = 7;\n    } else if (lgwin > 17) {\n      *last_bytes = (uint16_t)(((lgwin - 17) << 1) | 0x01);\n      *last_bytes_bits = 4;\n    } else {\n      *last_bytes = (uint16_t)(((lgwin - 8) << 4) | 0x01);\n      *last_bytes_bits = 7;\n    }\n  }\n}\n\n/* TODO(eustas): move to compress_fragment.c? */\n/* Initializes the command and distance prefix codes for the first block. */\nstatic void InitCommandPrefixCodes(BrotliOnePassArena* s) {\n  static const BROTLI_MODEL(\"small\") uint8_t kDefaultCommandDepths[128] = {\n    0, 4, 4, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8,\n    0, 0, 0, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7,\n    7, 7, 10, 10, 10, 10, 10, 10, 0, 4, 4, 5, 5, 5, 6, 6,\n    7, 8, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n    5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,\n    4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 10,\n    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n  };\n  static const BROTLI_MODEL(\"small\") uint16_t kDefaultCommandBits[128] = {\n    0,   0,   8,   9,   3,  35,   7,   71,\n    39, 103,  23,  47, 175, 111, 239,   31,\n    0,   0,   0,   4,  12,   2,  10,    6,\n    13,  29,  11,  43,  27,  59,  87,   55,\n    15,  79, 319, 831, 191, 703, 447,  959,\n    0,  14,   1,  25,   5,  21,  19,   51,\n    119, 159,  95, 223, 479, 991,  63,  575,\n    127, 639, 383, 895, 255, 767, 511, 1023,\n    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    27, 59, 7, 39, 23, 55, 30, 1, 17, 9, 25, 5, 0, 8, 4, 12,\n    2, 10, 6, 21, 13, 29, 3, 19, 11, 15, 47, 31, 95, 63, 127, 255,\n    767, 2815, 1791, 3839, 511, 2559, 1535, 3583, 1023, 3071, 2047, 4095,\n  };\n  static const BROTLI_MODEL(\"small\") uint8_t kDefaultCommandCode[] = {\n    0xff, 0x77, 0xd5, 0xbf, 0xe7, 0xde, 0xea, 0x9e, 0x51, 0x5d, 0xde, 0xc6,\n    0x70, 0x57, 0xbc, 0x58, 0x58, 0x58, 0xd8, 0xd8, 0x58, 0xd5, 0xcb, 0x8c,\n    0xea, 0xe0, 0xc3, 0x87, 0x1f, 0x83, 0xc1, 0x60, 0x1c, 0x67, 0xb2, 0xaa,\n    0x06, 0x83, 0xc1, 0x60, 0x30, 0x18, 0xcc, 0xa1, 0xce, 0x88, 0x54, 0x94,\n    0x46, 0xe1, 0xb0, 0xd0, 0x4e, 0xb2, 0xf7, 0x04, 0x00,\n  };\n  static const size_t kDefaultCommandCodeNumBits = 448;\n  COPY_ARRAY(s->cmd_depth, kDefaultCommandDepths);\n  COPY_ARRAY(s->cmd_bits, kDefaultCommandBits);\n\n  /* Initialize the pre-compressed form of the command and distance prefix\n     codes. */\n  COPY_ARRAY(s->cmd_code, kDefaultCommandCode);\n  s->cmd_code_numbits = kDefaultCommandCodeNumBits;\n}\n\n/* TODO(eustas): avoid FP calculations. */\nstatic double EstimateEntropy(const uint32_t* population, size_t size) {\n  size_t total = 0;\n  double result = 0;\n  for (size_t i = 0; i < size; ++i) {\n    uint32_t p = population[i];\n    total += p;\n    result += (double)p * FastLog2(p);\n  }\n  result = (double)total * FastLog2(total) - result;\n  return result;\n}\n\n/* Decide about the context map based on the ability of the prediction\n   ability of the previous byte UTF8-prefix on the next byte. The\n   prediction ability is calculated as Shannon entropy. Here we need\n   Shannon entropy instead of 'BrotliBitsEntropy' since the prefix will be\n   encoded with the remaining 6 bits of the following byte, and\n   BrotliBitsEntropy will assume that symbol to be stored alone using Huffman\n   coding. */\nstatic void ChooseContextMap(int quality,\n                             uint32_t* bigram_histo,\n                             size_t* num_literal_contexts,\n                             const uint32_t** literal_context_map) {\n  static const BROTLI_MODEL(\"small\")\n  uint32_t kStaticContextMapContinuation[64] = {\n    1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  };\n  static const BROTLI_MODEL(\"small\")\n  uint32_t kStaticContextMapSimpleUTF8[64] = {\n    0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  };\n\n  uint32_t monogram_histo[3] = { 0 };\n  uint32_t two_prefix_histo[6] = { 0 };\n  size_t total;\n  size_t i;\n  double entropy[4];\n  for (i = 0; i < 9; ++i) {\n    monogram_histo[i % 3] += bigram_histo[i];\n    two_prefix_histo[i % 6] += bigram_histo[i];\n  }\n  entropy[1] = EstimateEntropy(monogram_histo, 3);\n  entropy[2] = (EstimateEntropy(two_prefix_histo, 3) +\n                EstimateEntropy(two_prefix_histo + 3, 3));\n  entropy[3] = 0;\n  for (i = 0; i < 3; ++i) {\n    entropy[3] += EstimateEntropy(bigram_histo + 3 * i, 3);\n  }\n\n  total = monogram_histo[0] + monogram_histo[1] + monogram_histo[2];\n  BROTLI_DCHECK(total != 0);\n  entropy[0] = 1.0 / (double)total;\n  entropy[1] *= entropy[0];\n  entropy[2] *= entropy[0];\n  entropy[3] *= entropy[0];\n\n  if (quality < MIN_QUALITY_FOR_HQ_CONTEXT_MODELING) {\n    /* 3 context models is a bit slower, don't use it at lower qualities. */\n    entropy[3] = entropy[1] * 10;\n  }\n  /* If expected savings by symbol are less than 0.2 bits, skip the\n     context modeling -- in exchange for faster decoding speed. */\n  if (entropy[1] - entropy[2] < 0.2 &&\n      entropy[1] - entropy[3] < 0.2) {\n    *num_literal_contexts = 1;\n  } else if (entropy[2] - entropy[3] < 0.02) {\n    *num_literal_contexts = 2;\n    *literal_context_map = kStaticContextMapSimpleUTF8;\n  } else {\n    *num_literal_contexts = 3;\n    *literal_context_map = kStaticContextMapContinuation;\n  }\n}\n\n/* Decide if we want to use a more complex static context map containing 13\n   context values, based on the entropy reduction of histograms over the\n   first 5 bits of literals. */\nstatic BROTLI_BOOL ShouldUseComplexStaticContextMap(const uint8_t* input,\n    size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint,\n    size_t* num_literal_contexts, const uint32_t** literal_context_map,\n    uint32_t* arena) {\n  static const BROTLI_MODEL(\"small\")\n  uint32_t kStaticContextMapComplexUTF8[64] = {\n    11, 11, 12, 12, /* 0 special */\n    0, 0, 0, 0, /* 4 lf */\n    1, 1, 9, 9, /* 8 space */\n    2, 2, 2, 2, /* !, first after space/lf and after something else. */\n    1, 1, 1, 1, /* \" */\n    8, 3, 3, 3, /* % */\n    1, 1, 1, 1, /* ({[ */\n    2, 2, 2, 2, /* }]) */\n    8, 4, 4, 4, /* :; */\n    8, 7, 4, 4, /* . */\n    8, 0, 0, 0, /* > */\n    3, 3, 3, 3, /* [0..9] */\n    5, 5, 10, 5, /* [A-Z] */\n    5, 5, 10, 5,\n    6, 6, 6, 6, /* [a-z] */\n    6, 6, 6, 6,\n  };\n  BROTLI_UNUSED(quality);\n  /* Try the more complex static context map only for long data. */\n  if (size_hint < (1 << 20)) {\n    return BROTLI_FALSE;\n  } else {\n    const size_t end_pos = start_pos + length;\n    /* To make entropy calculations faster, we collect histograms\n       over the 5 most significant bits of literals. One histogram\n       without context and 13 additional histograms for each context value. */\n    uint32_t* BROTLI_RESTRICT const combined_histo = arena;\n    uint32_t* BROTLI_RESTRICT const context_histo = arena + 32;\n    uint32_t total = 0;\n    double entropy[3];\n    size_t i;\n    ContextLut utf8_lut = BROTLI_CONTEXT_LUT(CONTEXT_UTF8);\n    memset(arena, 0, sizeof(arena[0]) * 32 * (BROTLI_MAX_STATIC_CONTEXTS + 1));\n    for (; start_pos + 64 <= end_pos; start_pos += 4096) {\n      const size_t stride_end_pos = start_pos + 64;\n      uint8_t prev2 = input[start_pos & mask];\n      uint8_t prev1 = input[(start_pos + 1) & mask];\n      size_t pos;\n      /* To make the analysis of the data faster we only examine 64 byte long\n         strides at every 4kB intervals. */\n      for (pos = start_pos + 2; pos < stride_end_pos; ++pos) {\n        const uint8_t literal = input[pos & mask];\n        const uint8_t context = (uint8_t)kStaticContextMapComplexUTF8[\n            BROTLI_CONTEXT(prev1, prev2, utf8_lut)];\n        ++total;\n        ++combined_histo[literal >> 3];\n        ++context_histo[(context << 5) + (literal >> 3)];\n        prev2 = prev1;\n        prev1 = literal;\n      }\n    }\n    entropy[1] = EstimateEntropy(combined_histo, 32);\n    entropy[2] = 0;\n    for (i = 0; i < BROTLI_MAX_STATIC_CONTEXTS; ++i) {\n      entropy[2] += EstimateEntropy(context_histo + (i << 5), 32);\n    }\n    entropy[0] = 1.0 / (double)total;\n    entropy[1] *= entropy[0];\n    entropy[2] *= entropy[0];\n    /* The triggering heuristics below were tuned by compressing the individual\n       files of the silesia corpus. If we skip this kind of context modeling\n       for not very well compressible input (i.e. entropy using context modeling\n       is 60% of maximal entropy) or if expected savings by symbol are less\n       than 0.2 bits, then in every case when it triggers, the final compression\n       ratio is improved. Note however that this heuristics might be too strict\n       for some cases and could be tuned further. */\n    if (entropy[2] > 3.0 || entropy[1] - entropy[2] < 0.2) {\n      return BROTLI_FALSE;\n    } else {\n      *num_literal_contexts = BROTLI_MAX_STATIC_CONTEXTS;\n      *literal_context_map = kStaticContextMapComplexUTF8;\n      return BROTLI_TRUE;\n    }\n  }\n}\n\nstatic void DecideOverLiteralContextModeling(const uint8_t* input,\n    size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint,\n    size_t* num_literal_contexts, const uint32_t** literal_context_map,\n    uint32_t* arena) {\n  if (quality < MIN_QUALITY_FOR_CONTEXT_MODELING || length < 64) {\n    return;\n  } else if (ShouldUseComplexStaticContextMap(\n      input, start_pos, length, mask, quality, size_hint,\n      num_literal_contexts, literal_context_map, arena)) {\n    /* Context map was already set, nothing else to do. */\n  } else {\n    /* Gather bi-gram data of the UTF8 byte prefixes. To make the analysis of\n       UTF8 data faster we only examine 64 byte long strides at every 4kB\n       intervals. */\n    const size_t end_pos = start_pos + length;\n    uint32_t* BROTLI_RESTRICT const bigram_prefix_histo = arena;\n    memset(bigram_prefix_histo, 0, sizeof(arena[0]) * 9);\n    for (; start_pos + 64 <= end_pos; start_pos += 4096) {\n      static const int lut[4] = { 0, 0, 1, 2 };\n      const size_t stride_end_pos = start_pos + 64;\n      int prev = lut[input[start_pos & mask] >> 6] * 3;\n      size_t pos;\n      for (pos = start_pos + 1; pos < stride_end_pos; ++pos) {\n        const uint8_t literal = input[pos & mask];\n        ++bigram_prefix_histo[prev + lut[literal >> 6]];\n        prev = lut[literal >> 6] * 3;\n      }\n    }\n    ChooseContextMap(quality, &bigram_prefix_histo[0], num_literal_contexts,\n                     literal_context_map);\n  }\n}\n\nstatic BROTLI_BOOL ShouldCompress(\n    const uint8_t* data, const size_t mask, const uint64_t last_flush_pos,\n    const size_t bytes, const size_t num_literals, const size_t num_commands) {\n  /* TODO(eustas): find more precise minimal block overhead. */\n  if (bytes <= 2) return BROTLI_FALSE;\n  if (num_commands < (bytes >> 8) + 2) {\n    if ((double)num_literals > 0.99 * (double)bytes) {\n      uint32_t literal_histo[256] = { 0 };\n      static const uint32_t kSampleRate = 13;\n      static const double kInvSampleRate = 1.0 / 13.0;\n      static const double kMinEntropy = 7.92;\n      const double bit_cost_threshold =\n          (double)bytes * kMinEntropy * kInvSampleRate;\n      size_t t = (bytes + kSampleRate - 1) / kSampleRate;\n      uint32_t pos = (uint32_t)last_flush_pos;\n      size_t i;\n      for (i = 0; i < t; i++) {\n        ++literal_histo[data[pos & mask]];\n        pos += kSampleRate;\n      }\n      if (BrotliBitsEntropy(literal_histo, 256) > bit_cost_threshold) {\n        return BROTLI_FALSE;\n      }\n    }\n  }\n  return BROTLI_TRUE;\n}\n\n/* Chooses the literal context mode for a metablock */\nstatic ContextType ChooseContextMode(const BrotliEncoderParams* params,\n    const uint8_t* data, const size_t pos, const size_t mask,\n    const size_t length) {\n  /* We only do the computation for the option of something else than\n     CONTEXT_UTF8 for the highest qualities */\n  if (params->quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING &&\n      !BrotliIsMostlyUTF8(data, pos, mask, length, kMinUTF8Ratio)) {\n    return CONTEXT_SIGNED;\n  }\n  return CONTEXT_UTF8;\n}\n\nstatic void WriteMetaBlockInternal(MemoryManager* m,\n                                   const uint8_t* data,\n                                   const size_t mask,\n                                   const uint64_t last_flush_pos,\n                                   const size_t bytes,\n                                   const BROTLI_BOOL is_last,\n                                   ContextType literal_context_mode,\n                                   const BrotliEncoderParams* params,\n                                   const uint8_t prev_byte,\n                                   const uint8_t prev_byte2,\n                                   const size_t num_literals,\n                                   const size_t num_commands,\n                                   Command* commands,\n                                   const int* saved_dist_cache,\n                                   int* dist_cache,\n                                   size_t* storage_ix,\n                                   uint8_t* storage) {\n  const uint32_t wrapped_last_flush_pos = WrapPosition(last_flush_pos);\n  uint16_t last_bytes;\n  uint8_t last_bytes_bits;\n  ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);\n  BrotliEncoderParams block_params = *params;\n\n  if (bytes == 0) {\n    /* Write the ISLAST and ISEMPTY bits. */\n    BrotliWriteBits(2, 3, storage_ix, storage);\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n    return;\n  }\n\n  if (!ShouldCompress(data, mask, last_flush_pos, bytes,\n                      num_literals, num_commands)) {\n    /* Restore the distance cache, as its last update by\n       CreateBackwardReferences is now unused. */\n    memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));\n    BrotliStoreUncompressedMetaBlock(is_last, data,\n                                     wrapped_last_flush_pos, mask, bytes,\n                                     storage_ix, storage);\n    return;\n  }\n\n  BROTLI_DCHECK(*storage_ix <= 14);\n  last_bytes = (uint16_t)((storage[1] << 8) | storage[0]);\n  last_bytes_bits = (uint8_t)(*storage_ix);\n  if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) {\n    BrotliStoreMetaBlockFast(m, data, wrapped_last_flush_pos,\n                             bytes, mask, is_last, params,\n                             commands, num_commands,\n                             storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {\n    BrotliStoreMetaBlockTrivial(m, data, wrapped_last_flush_pos,\n                                bytes, mask, is_last, params,\n                                commands, num_commands,\n                                storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  } else {\n    MetaBlockSplit mb;\n    InitMetaBlockSplit(&mb);\n    if (params->quality < MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) {\n      size_t num_literal_contexts = 1;\n      const uint32_t* literal_context_map = NULL;\n      if (!params->disable_literal_context_modeling) {\n        /* TODO(eustas): pull to higher level and reuse. */\n        uint32_t* arena =\n            BROTLI_ALLOC(m, uint32_t, 32 * (BROTLI_MAX_STATIC_CONTEXTS + 1));\n        if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n        DecideOverLiteralContextModeling(\n            data, wrapped_last_flush_pos, bytes, mask, params->quality,\n            params->size_hint, &num_literal_contexts,\n            &literal_context_map, arena);\n        BROTLI_FREE(m, arena);\n      }\n      BrotliBuildMetaBlockGreedy(m, data, wrapped_last_flush_pos, mask,\n          prev_byte, prev_byte2, literal_context_lut, num_literal_contexts,\n          literal_context_map, commands, num_commands, &mb);\n      if (BROTLI_IS_OOM(m)) return;\n    } else {\n      BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, &block_params,\n                           prev_byte, prev_byte2,\n                           commands, num_commands,\n                           literal_context_mode,\n                           &mb);\n      if (BROTLI_IS_OOM(m)) return;\n    }\n    if (params->quality >= MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS) {\n      /* The number of distance symbols effectively used for distance\n         histograms. It might be less than distance alphabet size\n         for \"Large Window Brotli\" (32-bit). */\n      BrotliOptimizeHistograms(block_params.dist.alphabet_size_limit, &mb);\n    }\n    BrotliStoreMetaBlock(m, data, wrapped_last_flush_pos, bytes, mask,\n                         prev_byte, prev_byte2,\n                         is_last,\n                         &block_params,\n                         literal_context_mode,\n                         commands, num_commands,\n                         &mb,\n                         storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n    DestroyMetaBlockSplit(m, &mb);\n  }\n  if (bytes + 4 < (*storage_ix >> 3)) {\n    /* Restore the distance cache and last byte. */\n    memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));\n    storage[0] = (uint8_t)last_bytes;\n    storage[1] = (uint8_t)(last_bytes >> 8);\n    *storage_ix = last_bytes_bits;\n    BrotliStoreUncompressedMetaBlock(is_last, data,\n                                     wrapped_last_flush_pos, mask,\n                                     bytes, storage_ix, storage);\n  }\n}\n\nstatic void ChooseDistanceParams(BrotliEncoderParams* params) {\n  uint32_t distance_postfix_bits = 0;\n  uint32_t num_direct_distance_codes = 0;\n\n  if (params->quality >= MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS) {\n    uint32_t ndirect_msb;\n    if (params->mode == BROTLI_MODE_FONT) {\n      distance_postfix_bits = 1;\n      num_direct_distance_codes = 12;\n    } else {\n      distance_postfix_bits = params->dist.distance_postfix_bits;\n      num_direct_distance_codes = params->dist.num_direct_distance_codes;\n    }\n    ndirect_msb = (num_direct_distance_codes >> distance_postfix_bits) & 0x0F;\n    if (distance_postfix_bits > BROTLI_MAX_NPOSTFIX ||\n        num_direct_distance_codes > BROTLI_MAX_NDIRECT ||\n        (ndirect_msb << distance_postfix_bits) != num_direct_distance_codes) {\n      distance_postfix_bits = 0;\n      num_direct_distance_codes = 0;\n    }\n  }\n\n  BrotliInitDistanceParams(&params->dist, distance_postfix_bits,\n                           num_direct_distance_codes, params->large_window);\n}\n\nstatic BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) {\n  MemoryManager* m = &s->memory_manager_;\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  if (s->is_initialized_) return BROTLI_TRUE;\n\n  s->last_bytes_bits_ = 0;\n  s->last_bytes_ = 0;\n  s->flint_ = BROTLI_FLINT_DONE;\n  s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;\n\n  SanitizeParams(&s->params);\n  s->params.lgblock = ComputeLgBlock(&s->params);\n  ChooseDistanceParams(&s->params);\n\n  if (s->params.stream_offset != 0) {\n    s->flint_ = BROTLI_FLINT_NEEDS_2_BYTES;\n    /* Poison the distance cache. -16 +- 3 is still less than zero (invalid). */\n    s->dist_cache_[0] = -16;\n    s->dist_cache_[1] = -16;\n    s->dist_cache_[2] = -16;\n    s->dist_cache_[3] = -16;\n    memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));\n  }\n\n  RingBufferSetup(&s->params, &s->ringbuffer_);\n\n  /* Initialize last byte with stream header. */\n  {\n    int lgwin = s->params.lgwin;\n    if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n        s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n      lgwin = BROTLI_MAX(int, lgwin, 18);\n    }\n    if (s->params.stream_offset == 0) {\n      EncodeWindowBits(lgwin, s->params.large_window,\n                       &s->last_bytes_, &s->last_bytes_bits_);\n    } else {\n      /* Bigger values have the same effect, but could cause overflows. */\n      s->params.stream_offset = BROTLI_MIN(size_t,\n          s->params.stream_offset, BROTLI_MAX_BACKWARD_LIMIT(lgwin));\n    }\n  }\n\n  if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n    s->one_pass_arena_ = BROTLI_ALLOC(m, BrotliOnePassArena, 1);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    InitCommandPrefixCodes(s->one_pass_arena_);\n  } else if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    s->two_pass_arena_ = BROTLI_ALLOC(m, BrotliTwoPassArena, 1);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  }\n\n  s->is_initialized_ = BROTLI_TRUE;\n  return BROTLI_TRUE;\n}\n\nstatic void BrotliEncoderInitParams(BrotliEncoderParams* params) {\n  params->mode = BROTLI_DEFAULT_MODE;\n  params->large_window = BROTLI_FALSE;\n  params->quality = BROTLI_DEFAULT_QUALITY;\n  params->lgwin = BROTLI_DEFAULT_WINDOW;\n  params->lgblock = 0;\n  params->stream_offset = 0;\n  params->size_hint = 0;\n  params->disable_literal_context_modeling = BROTLI_FALSE;\n  BrotliInitSharedEncoderDictionary(&params->dictionary);\n  params->dist.distance_postfix_bits = 0;\n  params->dist.num_direct_distance_codes = 0;\n  params->dist.alphabet_size_max =\n      BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_MAX_DISTANCE_BITS);\n  params->dist.alphabet_size_limit = params->dist.alphabet_size_max;\n  params->dist.max_distance = BROTLI_MAX_DISTANCE;\n}\n\nstatic void BrotliEncoderCleanupParams(MemoryManager* m,\n    BrotliEncoderParams* params) {\n  BrotliCleanupSharedEncoderDictionary(m, &params->dictionary);\n}\n\n#ifdef BROTLI_REPORTING\n/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */\nvoid BrotliEncoderOnStart(const BrotliEncoderState* s);\nvoid BrotliEncoderOnFinish(const BrotliEncoderState* s);\n#define BROTLI_ENCODER_ON_START(s) BrotliEncoderOnStart(s);\n#define BROTLI_ENCODER_ON_FINISH(s) BrotliEncoderOnFinish(s);\n#else\n#if !defined(BROTLI_ENCODER_ON_START)\n#define BROTLI_ENCODER_ON_START(s) (void)(s);\n#endif\n#if !defined(BROTLI_ENCODER_ON_FINISH)\n#define BROTLI_ENCODER_ON_FINISH(s) (void)(s);\n#endif\n#endif\n\nstatic void BrotliEncoderInitState(BrotliEncoderState* s) {\n  BROTLI_ENCODER_ON_START(s);\n  BrotliEncoderInitParams(&s->params);\n  s->input_pos_ = 0;\n  s->num_commands_ = 0;\n  s->num_literals_ = 0;\n  s->last_insert_len_ = 0;\n  s->last_flush_pos_ = 0;\n  s->last_processed_pos_ = 0;\n  s->prev_byte_ = 0;\n  s->prev_byte2_ = 0;\n  s->storage_size_ = 0;\n  s->storage_ = 0;\n  HasherInit(&s->hasher_);\n  s->large_table_ = NULL;\n  s->large_table_size_ = 0;\n  s->one_pass_arena_ = NULL;\n  s->two_pass_arena_ = NULL;\n  s->command_buf_ = NULL;\n  s->literal_buf_ = NULL;\n  s->total_in_ = 0;\n  s->next_out_ = NULL;\n  s->available_out_ = 0;\n  s->total_out_ = 0;\n  s->stream_state_ = BROTLI_STREAM_PROCESSING;\n  s->is_last_block_emitted_ = BROTLI_FALSE;\n  s->is_initialized_ = BROTLI_FALSE;\n\n  RingBufferInit(&s->ringbuffer_);\n\n  s->commands_ = 0;\n  s->cmd_alloc_size_ = 0;\n\n  /* Initialize distance cache. */\n  s->dist_cache_[0] = 4;\n  s->dist_cache_[1] = 11;\n  s->dist_cache_[2] = 15;\n  s->dist_cache_[3] = 16;\n  /* Save the state of the distance cache in case we need to restore it for\n     emitting an uncompressed block. */\n  memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));\n}\n\nBrotliEncoderState* BrotliEncoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  BROTLI_BOOL healthy = BrotliEncoderEnsureStaticInit();\n  if (!healthy) {\n    return 0;\n  }\n  BrotliEncoderState* state = (BrotliEncoderState*)BrotliBootstrapAlloc(\n      sizeof(BrotliEncoderState), alloc_func, free_func, opaque);\n  if (state == NULL) {\n    /* BROTLI_DUMP(); */\n    return 0;\n  }\n  BrotliInitMemoryManager(\n      &state->memory_manager_, alloc_func, free_func, opaque);\n  BrotliEncoderInitState(state);\n  return state;\n}\n\nstatic void BrotliEncoderCleanupState(BrotliEncoderState* s) {\n  MemoryManager* m = &s->memory_manager_;\n\n  BROTLI_ENCODER_ON_FINISH(s);\n\n  if (BROTLI_IS_OOM(m)) {\n    BrotliWipeOutMemoryManager(m);\n    return;\n  }\n\n  BROTLI_FREE(m, s->storage_);\n  BROTLI_FREE(m, s->commands_);\n  RingBufferFree(m, &s->ringbuffer_);\n  DestroyHasher(m, &s->hasher_);\n  BROTLI_FREE(m, s->large_table_);\n  BROTLI_FREE(m, s->one_pass_arena_);\n  BROTLI_FREE(m, s->two_pass_arena_);\n  BROTLI_FREE(m, s->command_buf_);\n  BROTLI_FREE(m, s->literal_buf_);\n  BrotliEncoderCleanupParams(m, &s->params);\n}\n\n/* Deinitializes and frees BrotliEncoderState instance. */\nvoid BrotliEncoderDestroyInstance(BrotliEncoderState* state) {\n  if (!state) {\n    return;\n  } else {\n    BrotliEncoderCleanupState(state);\n    BrotliBootstrapFree(state, &state->memory_manager_);\n  }\n}\n\n/*\n   Copies the given input data to the internal ring buffer of the compressor.\n   No processing of the data occurs at this time and this function can be\n   called multiple times before calling WriteBrotliData() to process the\n   accumulated input. At most input_block_size() bytes of input data can be\n   copied to the ring buffer, otherwise the next WriteBrotliData() will fail.\n */\nstatic void CopyInputToRingBuffer(BrotliEncoderState* s,\n                                  const size_t input_size,\n                                  const uint8_t* input_buffer) {\n  RingBuffer* ringbuffer_ = &s->ringbuffer_;\n  MemoryManager* m = &s->memory_manager_;\n  RingBufferWrite(m, input_buffer, input_size, ringbuffer_);\n  if (BROTLI_IS_OOM(m)) return;\n  s->input_pos_ += input_size;\n\n  /* TL;DR: If needed, initialize 7 more bytes in the ring buffer to make the\n     hashing not depend on uninitialized data. This makes compression\n     deterministic and it prevents uninitialized memory warnings in Valgrind.\n     Even without erasing, the output would be valid (but nondeterministic).\n\n     Background information: The compressor stores short (at most 8 bytes)\n     substrings of the input already read in a hash table, and detects\n     repetitions by looking up such substrings in the hash table. If it\n     can find a substring, it checks whether the substring is really there\n     in the ring buffer (or it's just a hash collision). Should the hash\n     table become corrupt, this check makes sure that the output is\n     still valid, albeit the compression ratio would be bad.\n\n     The compressor populates the hash table from the ring buffer as it's\n     reading new bytes from the input. However, at the last few indexes of\n     the ring buffer, there are not enough bytes to build full-length\n     substrings from. Since the hash table always contains full-length\n     substrings, we overwrite with zeros here to make sure that those\n     substrings will contain zeros at the end instead of uninitialized\n     data.\n\n     Please note that erasing is not necessary (because the\n     memory region is already initialized since he ring buffer\n     has a `tail' that holds a copy of the beginning,) so we\n     skip erasing if we have already gone around at least once in\n     the ring buffer.\n\n     Only clear during the first round of ring-buffer writes. On\n     subsequent rounds data in the ring-buffer would be affected. */\n  if (ringbuffer_->pos_ <= ringbuffer_->mask_) {\n    /* This is the first time when the ring buffer is being written.\n       We clear 7 bytes just after the bytes that have been copied from\n       the input buffer.\n\n       The ring-buffer has a \"tail\" that holds a copy of the beginning,\n       but only once the ring buffer has been fully written once, i.e.,\n       pos <= mask. For the first time, we need to write values\n       in this tail (where index may be larger than mask), so that\n       we have exactly defined behavior and don't read uninitialized\n       memory. Due to performance reasons, hashing reads data using a\n       LOAD64, which can go 7 bytes beyond the bytes written in the\n       ring-buffer. */\n    memset(ringbuffer_->buffer_ + ringbuffer_->pos_, 0, 7);\n  }\n}\n\n/* Marks all input as processed.\n   Returns true if position wrapping occurs. */\nstatic BROTLI_BOOL UpdateLastProcessedPos(BrotliEncoderState* s) {\n  uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_);\n  uint32_t wrapped_input_pos = WrapPosition(s->input_pos_);\n  s->last_processed_pos_ = s->input_pos_;\n  return TO_BROTLI_BOOL(wrapped_input_pos < wrapped_last_processed_pos);\n}\n\nstatic void ExtendLastCommand(BrotliEncoderState* s, uint32_t* bytes,\n                              uint32_t* wrapped_last_processed_pos) {\n  Command* last_command = &s->commands_[s->num_commands_ - 1];\n  const uint8_t* data = s->ringbuffer_.buffer_;\n  const uint32_t mask = s->ringbuffer_.mask_;\n  uint64_t max_backward_distance =\n      (((uint64_t)1) << s->params.lgwin) - BROTLI_WINDOW_GAP;\n  uint64_t last_copy_len = last_command->copy_len_ & 0x1FFFFFF;\n  uint64_t last_processed_pos = s->last_processed_pos_ - last_copy_len;\n  uint64_t max_distance = last_processed_pos < max_backward_distance ?\n      last_processed_pos : max_backward_distance;\n  uint64_t cmd_dist = (uint64_t)s->dist_cache_[0];\n  uint32_t distance_code = CommandRestoreDistanceCode(last_command,\n                                                      &s->params.dist);\n  const CompoundDictionary* dict = &s->params.dictionary.compound;\n  size_t compound_dictionary_size = dict->total_size;\n  if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES ||\n      distance_code - (BROTLI_NUM_DISTANCE_SHORT_CODES - 1) == cmd_dist) {\n    if (cmd_dist <= max_distance) {\n      while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] ==\n             data[(*wrapped_last_processed_pos - cmd_dist) & mask]) {\n        last_command->copy_len_++;\n        (*bytes)--;\n        (*wrapped_last_processed_pos)++;\n      }\n    } else {\n      if ((cmd_dist - max_distance - 1) < compound_dictionary_size &&\n          last_copy_len < cmd_dist - max_distance) {\n        size_t address =\n            compound_dictionary_size - (size_t)(cmd_dist - max_distance) +\n            (size_t)last_copy_len;\n        size_t br_index = 0;\n        size_t br_offset;\n        const uint8_t* chunk;\n        size_t chunk_length;\n        while (address >= dict->chunk_offsets[br_index + 1]) br_index++;\n        br_offset = address - dict->chunk_offsets[br_index];\n        chunk = dict->chunk_source[br_index];\n        chunk_length =\n            dict->chunk_offsets[br_index + 1] - dict->chunk_offsets[br_index];\n        while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] ==\n               chunk[br_offset]) {\n          last_command->copy_len_++;\n          (*bytes)--;\n          (*wrapped_last_processed_pos)++;\n          if (++br_offset == chunk_length) {\n            br_index++;\n            br_offset = 0;\n            if (br_index != dict->num_chunks) {\n              chunk = dict->chunk_source[br_index];\n              chunk_length = dict->chunk_offsets[br_index + 1] -\n                  dict->chunk_offsets[br_index];\n            } else {\n              break;\n            }\n          }\n        }\n      }\n    }\n    /* The copy length is at most the metablock size, and thus expressible. */\n    GetLengthCode(last_command->insert_len_,\n                  (size_t)((int)(last_command->copy_len_ & 0x1FFFFFF) +\n                           (int)(last_command->copy_len_ >> 25)),\n                  TO_BROTLI_BOOL((last_command->dist_prefix_ & 0x3FF) == 0),\n                  &last_command->cmd_prefix_);\n  }\n}\n\n/*\n   Processes the accumulated input data and sets |*out_size| to the length of\n   the new output meta-block, or to zero if no new output meta-block has been\n   created (in this case the processed input data is buffered internally).\n   If |*out_size| is positive, |*output| points to the start of the output\n   data. If |is_last| or |force_flush| is BROTLI_TRUE, an output meta-block is\n   always created. However, until |is_last| is BROTLI_TRUE encoder may retain up\n   to 7 bits of the last byte of output. Byte-alignment could be enforced by\n   emitting an empty meta-data block.\n   Returns BROTLI_FALSE if the size of the input data is larger than\n   input_block_size().\n */\nstatic BROTLI_BOOL EncodeData(\n    BrotliEncoderState* s, const BROTLI_BOOL is_last,\n    const BROTLI_BOOL force_flush, size_t* out_size, uint8_t** output) {\n  const uint64_t delta = UnprocessedInputSize(s);\n  uint32_t bytes = (uint32_t)delta;\n  uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_);\n  uint8_t* data;\n  uint32_t mask;\n  MemoryManager* m = &s->memory_manager_;\n  ContextType literal_context_mode;\n  ContextLut literal_context_lut;\n  BROTLI_BOOL fast_compress =\n      s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY;\n\n  data = s->ringbuffer_.buffer_;\n  mask = s->ringbuffer_.mask_;\n\n  if (delta == 0) {  /* No new input; still might want to flush or finish. */\n    if (!data) {  /* No input has been processed so far. */\n      if (is_last) {  /* Emit complete finalized stream. */\n        BROTLI_DCHECK(s->last_bytes_bits_ <= 14);\n        s->last_bytes_ |= (uint16_t)(3u << s->last_bytes_bits_);\n        s->last_bytes_bits_ = (uint8_t)(s->last_bytes_bits_ + 2u);\n        s->tiny_buf_.u8[0] = (uint8_t)s->last_bytes_;\n        s->tiny_buf_.u8[1] = (uint8_t)(s->last_bytes_ >> 8);\n        *output = s->tiny_buf_.u8;\n        *out_size = (s->last_bytes_bits_ + 7u) >> 3u;\n        return BROTLI_TRUE;\n      } else {  /* No data, not last -> no-op. */\n        *out_size = 0;\n        return BROTLI_TRUE;\n      }\n    } else {\n      /* Fast compress performs flush every block -> flush is no-op. */\n      if (!is_last && (!force_flush || fast_compress)) {  /* Another no-op. */\n        *out_size = 0;\n        return BROTLI_TRUE;\n      }\n    }\n  }\n  BROTLI_DCHECK(data);\n\n  if (s->params.quality > s->params.dictionary.max_quality) return BROTLI_FALSE;\n  /* Adding more blocks after \"last\" block is forbidden. */\n  if (s->is_last_block_emitted_) return BROTLI_FALSE;\n  if (is_last) s->is_last_block_emitted_ = BROTLI_TRUE;\n\n  if (delta > InputBlockSize(s)) {\n    return BROTLI_FALSE;\n  }\n  if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY &&\n      !s->command_buf_) {\n    s->command_buf_ =\n        BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize);\n    s->literal_buf_ =\n        BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) ||\n        BROTLI_IS_NULL(s->literal_buf_)) {\n      return BROTLI_FALSE;\n    }\n  }\n\n  if (fast_compress) {\n    uint8_t* storage;\n    size_t storage_ix = s->last_bytes_bits_;\n    size_t table_size;\n    int* table;\n\n    storage = GetBrotliStorage(s, 2 * bytes + 503);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    storage[0] = (uint8_t)s->last_bytes_;\n    storage[1] = (uint8_t)(s->last_bytes_ >> 8);\n    table = GetHashTable(s, s->params.quality, bytes, &table_size);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n      BrotliCompressFragmentFast(\n          s->one_pass_arena_, &data[wrapped_last_processed_pos & mask],\n          bytes, is_last,\n          table, table_size,\n          &storage_ix, storage);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    } else {\n      BrotliCompressFragmentTwoPass(\n          s->two_pass_arena_, &data[wrapped_last_processed_pos & mask],\n          bytes, is_last,\n          s->command_buf_, s->literal_buf_,\n          table, table_size,\n          &storage_ix, storage);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    }\n    s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);\n    s->last_bytes_bits_ = storage_ix & 7u;\n    UpdateLastProcessedPos(s);\n    *output = &storage[0];\n    *out_size = storage_ix >> 3;\n    return BROTLI_TRUE;\n  }\n\n  {\n    /* Theoretical max number of commands is 1 per 2 bytes. */\n    size_t newsize = s->num_commands_ + bytes / 2 + 1;\n    if (newsize > s->cmd_alloc_size_) {\n      Command* new_commands;\n      /* Reserve a bit more memory to allow merging with a next block\n         without reallocation: that would impact speed. */\n      newsize += (bytes / 4) + 16;\n      s->cmd_alloc_size_ = newsize;\n      new_commands = BROTLI_ALLOC(m, Command, newsize);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_commands)) return BROTLI_FALSE;\n      if (s->commands_) {\n        memcpy(new_commands, s->commands_, sizeof(Command) * s->num_commands_);\n        BROTLI_FREE(m, s->commands_);\n      }\n      s->commands_ = new_commands;\n    }\n  }\n\n  InitOrStitchToPreviousBlock(m, &s->hasher_, data, mask, &s->params,\n      wrapped_last_processed_pos, bytes, is_last);\n\n  literal_context_mode = ChooseContextMode(\n      &s->params, data, WrapPosition(s->last_flush_pos_),\n      mask, (size_t)(s->input_pos_ - s->last_flush_pos_));\n  literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);\n\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n\n  if (s->num_commands_ && s->last_insert_len_ == 0) {\n    ExtendLastCommand(s, &bytes, &wrapped_last_processed_pos);\n  }\n\n  if (s->params.quality == ZOPFLIFICATION_QUALITY) {\n    BROTLI_DCHECK(s->params.hasher.type == 10);\n    BrotliCreateZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,\n        data, mask, literal_context_lut, &s->params,\n        &s->hasher_, s->dist_cache_,\n        &s->last_insert_len_, &s->commands_[s->num_commands_],\n        &s->num_commands_, &s->num_literals_);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  } else if (s->params.quality == HQ_ZOPFLIFICATION_QUALITY) {\n    BROTLI_DCHECK(s->params.hasher.type == 10);\n    BrotliCreateHqZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,\n        data, mask, literal_context_lut, &s->params,\n        &s->hasher_, s->dist_cache_,\n        &s->last_insert_len_, &s->commands_[s->num_commands_],\n        &s->num_commands_, &s->num_literals_);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  } else {\n    BrotliCreateBackwardReferences(bytes, wrapped_last_processed_pos,\n        data, mask, literal_context_lut, &s->params,\n        &s->hasher_, s->dist_cache_,\n        &s->last_insert_len_, &s->commands_[s->num_commands_],\n        &s->num_commands_, &s->num_literals_);\n  }\n\n  {\n    const size_t max_length = MaxMetablockSize(&s->params);\n    const size_t max_literals = max_length / 8;\n    const size_t max_commands = max_length / 8;\n    const size_t processed_bytes = (size_t)(s->input_pos_ - s->last_flush_pos_);\n    /* If maximal possible additional block doesn't fit metablock, flush now. */\n    /* TODO(eustas): Postpone decision until next block arrives? */\n    const BROTLI_BOOL next_input_fits_metablock = TO_BROTLI_BOOL(\n        processed_bytes + InputBlockSize(s) <= max_length);\n    /* If block splitting is not used, then flush as soon as there is some\n       amount of commands / literals produced. */\n    const BROTLI_BOOL should_flush = TO_BROTLI_BOOL(\n        s->params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT &&\n        s->num_literals_ + s->num_commands_ >= MAX_NUM_DELAYED_SYMBOLS);\n    if (!is_last && !force_flush && !should_flush &&\n        next_input_fits_metablock &&\n        s->num_literals_ < max_literals &&\n        s->num_commands_ < max_commands) {\n      /* Merge with next input block. Everything will happen later. */\n      if (UpdateLastProcessedPos(s)) {\n        HasherReset(&s->hasher_);\n      }\n      *out_size = 0;\n      return BROTLI_TRUE;\n    }\n  }\n\n  /* Create the last insert-only command. */\n  if (s->last_insert_len_ > 0) {\n    InitInsertCommand(&s->commands_[s->num_commands_++], s->last_insert_len_);\n    s->num_literals_ += s->last_insert_len_;\n    s->last_insert_len_ = 0;\n  }\n\n  if (!is_last && s->input_pos_ == s->last_flush_pos_) {\n    /* We have no new input data and we don't have to finish the stream, so\n       nothing to do. */\n    *out_size = 0;\n    return BROTLI_TRUE;\n  }\n  BROTLI_DCHECK(s->input_pos_ >= s->last_flush_pos_);\n  BROTLI_DCHECK(s->input_pos_ > s->last_flush_pos_ || is_last);\n  BROTLI_DCHECK(s->input_pos_ - s->last_flush_pos_ <= 1u << 24);\n  {\n    const uint32_t metablock_size =\n        (uint32_t)(s->input_pos_ - s->last_flush_pos_);\n    uint8_t* storage = GetBrotliStorage(s, 2 * metablock_size + 503);\n    size_t storage_ix = s->last_bytes_bits_;\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    storage[0] = (uint8_t)s->last_bytes_;\n    storage[1] = (uint8_t)(s->last_bytes_ >> 8);\n    WriteMetaBlockInternal(\n        m, data, mask, s->last_flush_pos_, metablock_size, is_last,\n        literal_context_mode, &s->params, s->prev_byte_, s->prev_byte2_,\n        s->num_literals_, s->num_commands_, s->commands_, s->saved_dist_cache_,\n        s->dist_cache_, &storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);\n    s->last_bytes_bits_ = storage_ix & 7u;\n    s->last_flush_pos_ = s->input_pos_;\n    if (UpdateLastProcessedPos(s)) {\n      HasherReset(&s->hasher_);\n    }\n    if (s->last_flush_pos_ > 0) {\n      s->prev_byte_ = data[((uint32_t)s->last_flush_pos_ - 1) & mask];\n    }\n    if (s->last_flush_pos_ > 1) {\n      s->prev_byte2_ = data[(uint32_t)(s->last_flush_pos_ - 2) & mask];\n    }\n    s->num_commands_ = 0;\n    s->num_literals_ = 0;\n    /* Save the state of the distance cache in case we need to restore it for\n       emitting an uncompressed block. */\n    memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));\n    *output = &storage[0];\n    *out_size = storage_ix >> 3;\n    return BROTLI_TRUE;\n  }\n}\n\n/* Dumps remaining output bits and metadata header to |header|.\n   Returns number of produced bytes.\n   REQUIRED: |header| should be 8-byte aligned and at least 16 bytes long.\n   REQUIRED: |block_size| <= (1 << 24). */\nstatic size_t WriteMetadataHeader(\n    BrotliEncoderState* s, const size_t block_size, uint8_t* header) {\n  size_t storage_ix;\n  storage_ix = s->last_bytes_bits_;\n  header[0] = (uint8_t)s->last_bytes_;\n  header[1] = (uint8_t)(s->last_bytes_ >> 8);\n  s->last_bytes_ = 0;\n  s->last_bytes_bits_ = 0;\n\n  BrotliWriteBits(1, 0, &storage_ix, header);\n  BrotliWriteBits(2, 3, &storage_ix, header);\n  BrotliWriteBits(1, 0, &storage_ix, header);\n  if (block_size == 0) {\n    BrotliWriteBits(2, 0, &storage_ix, header);\n  } else {\n    uint32_t nbits = (block_size == 1) ? 1 :\n        (Log2FloorNonZero((uint32_t)block_size - 1) + 1);\n    uint32_t nbytes = (nbits + 7) / 8;\n    BrotliWriteBits(2, nbytes, &storage_ix, header);\n    BrotliWriteBits(8 * nbytes, block_size - 1, &storage_ix, header);\n  }\n  return (storage_ix + 7u) >> 3;\n}\n\nsize_t BrotliEncoderMaxCompressedSize(size_t input_size) {\n  /* [window bits / empty metadata] + N * [uncompressed] + [last empty] */\n  size_t num_large_blocks = input_size >> 14;\n  size_t overhead = 2 + (4 * num_large_blocks) + 3 + 1;\n  size_t result = input_size + overhead;\n  if (input_size == 0) return 2;\n  return (result < input_size) ? 0 : result;\n}\n\n/* Wraps data to uncompressed brotli stream with minimal window size.\n   |output| should point at region with at least BrotliEncoderMaxCompressedSize\n   addressable bytes.\n   Returns the length of stream. */\nstatic size_t MakeUncompressedStream(\n    const uint8_t* input, size_t input_size, uint8_t* output) {\n  size_t size = input_size;\n  size_t result = 0;\n  size_t offset = 0;\n  if (input_size == 0) {\n    output[0] = 6;\n    return 1;\n  }\n  output[result++] = 0x21;  /* window bits = 10, is_last = false */\n  output[result++] = 0x03;  /* empty metadata, padding */\n  while (size > 0) {\n    uint32_t nibbles = 0;\n    uint32_t chunk_size;\n    uint32_t bits;\n    chunk_size = (size > (1u << 24)) ? (1u << 24) : (uint32_t)size;\n    if (chunk_size > (1u << 16)) nibbles = (chunk_size > (1u << 20)) ? 2 : 1;\n    bits =\n        (nibbles << 1) | ((chunk_size - 1) << 3) | (1u << (19 + 4 * nibbles));\n    output[result++] = (uint8_t)bits;\n    output[result++] = (uint8_t)(bits >> 8);\n    output[result++] = (uint8_t)(bits >> 16);\n    if (nibbles == 2) output[result++] = (uint8_t)(bits >> 24);\n    memcpy(&output[result], &input[offset], chunk_size);\n    result += chunk_size;\n    offset += chunk_size;\n    size -= chunk_size;\n  }\n  output[result++] = 3;\n  return result;\n}\n\nBROTLI_BOOL BrotliEncoderCompress(\n    int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,\n    const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],\n    size_t* encoded_size,\n    uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]) {\n  BrotliEncoderState* s;\n  size_t out_size = *encoded_size;\n  const uint8_t* input_start = input_buffer;\n  uint8_t* output_start = encoded_buffer;\n  size_t max_out_size = BrotliEncoderMaxCompressedSize(input_size);\n  if (out_size == 0) {\n    /* Output buffer needs at least one byte. */\n    return BROTLI_FALSE;\n  }\n  if (input_size == 0) {\n    /* Handle the special case of empty input. */\n    *encoded_size = 1;\n    *encoded_buffer = 6;\n    return BROTLI_TRUE;\n  }\n\n  s = BrotliEncoderCreateInstance(0, 0, 0);\n  if (!s) {\n    return BROTLI_FALSE;\n  } else {\n    size_t available_in = input_size;\n    const uint8_t* next_in = input_buffer;\n    size_t available_out = *encoded_size;\n    uint8_t* next_out = encoded_buffer;\n    size_t total_out = 0;\n    BROTLI_BOOL result = BROTLI_FALSE;\n    /* TODO(eustas): check that parameters are sane. */\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality);\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode);\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size);\n    if (lgwin > BROTLI_MAX_WINDOW_BITS) {\n      BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE);\n    }\n    result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH,\n        &available_in, &next_in, &available_out, &next_out, &total_out);\n    if (!BrotliEncoderIsFinished(s)) result = 0;\n    *encoded_size = total_out;\n    BrotliEncoderDestroyInstance(s);\n    if (!result || (max_out_size && *encoded_size > max_out_size)) {\n      goto fallback;\n    }\n    return BROTLI_TRUE;\n  }\nfallback:\n  *encoded_size = 0;\n  if (!max_out_size) return BROTLI_FALSE;\n  if (out_size >= max_out_size) {\n    *encoded_size =\n        MakeUncompressedStream(input_start, input_size, output_start);\n    return BROTLI_TRUE;\n  }\n  return BROTLI_FALSE;\n}\n\nstatic void InjectBytePaddingBlock(BrotliEncoderState* s) {\n  uint32_t seal = s->last_bytes_;\n  size_t seal_bits = s->last_bytes_bits_;\n  uint8_t* destination;\n  s->last_bytes_ = 0;\n  s->last_bytes_bits_ = 0;\n  /* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */\n  seal |= 0x6u << seal_bits;\n  seal_bits += 6;\n  /* If we have already created storage, then append to it.\n     Storage is valid until next block is being compressed. */\n  if (s->next_out_) {\n    destination = s->next_out_ + s->available_out_;\n  } else {\n    destination = s->tiny_buf_.u8;\n    s->next_out_ = destination;\n  }\n  destination[0] = (uint8_t)seal;\n  if (seal_bits > 8) destination[1] = (uint8_t)(seal >> 8);\n  if (seal_bits > 16) destination[2] = (uint8_t)(seal >> 16);\n  s->available_out_ += (seal_bits + 7) >> 3;\n}\n\n/* Fills the |total_out|, if it is not NULL. */\nstatic void SetTotalOut(BrotliEncoderState* s, size_t* total_out) {\n  if (total_out) {\n    /* Saturating conversion uint64_t -> size_t */\n    size_t result = (size_t)-1;\n    if (s->total_out_ < result) {\n      result = (size_t)s->total_out_;\n    }\n    *total_out = result;\n  }\n}\n\n/* Injects padding bits or pushes compressed data to output.\n   Returns false if nothing is done. */\nstatic BROTLI_BOOL InjectFlushOrPushOutput(BrotliEncoderState* s,\n    size_t* available_out, uint8_t** next_out, size_t* total_out) {\n  if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED &&\n      s->last_bytes_bits_ != 0) {\n    InjectBytePaddingBlock(s);\n    return BROTLI_TRUE;\n  }\n\n  if (s->available_out_ != 0 && *available_out != 0) {\n    size_t copy_output_size =\n        BROTLI_MIN(size_t, s->available_out_, *available_out);\n    memcpy(*next_out, s->next_out_, copy_output_size);\n    *next_out += copy_output_size;\n    *available_out -= copy_output_size;\n    s->next_out_ += copy_output_size;\n    s->available_out_ -= copy_output_size;\n    s->total_out_ += copy_output_size;\n    SetTotalOut(s, total_out);\n    return BROTLI_TRUE;\n  }\n\n  return BROTLI_FALSE;\n}\n\nstatic void CheckFlushComplete(BrotliEncoderState* s) {\n  if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED &&\n      s->available_out_ == 0) {\n    s->stream_state_ = BROTLI_STREAM_PROCESSING;\n    s->next_out_ = 0;\n  }\n}\n\nstatic BROTLI_BOOL BrotliEncoderCompressStreamFast(\n    BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in,\n    const uint8_t** next_in, size_t* available_out, uint8_t** next_out,\n    size_t* total_out) {\n  const size_t block_size_limit = (size_t)1 << s->params.lgwin;\n  const size_t buf_size = BROTLI_MIN(size_t, kCompressFragmentTwoPassBlockSize,\n      BROTLI_MIN(size_t, *available_in, block_size_limit));\n  uint32_t* tmp_command_buf = NULL;\n  uint32_t* command_buf = NULL;\n  uint8_t* tmp_literal_buf = NULL;\n  uint8_t* literal_buf = NULL;\n  MemoryManager* m = &s->memory_manager_;\n  if (s->params.quality != FAST_ONE_PASS_COMPRESSION_QUALITY &&\n      s->params.quality != FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    return BROTLI_FALSE;\n  }\n  if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    if (!s->command_buf_ && buf_size == kCompressFragmentTwoPassBlockSize) {\n      s->command_buf_ =\n          BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize);\n      s->literal_buf_ =\n          BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) ||\n          BROTLI_IS_NULL(s->literal_buf_)) {\n        return BROTLI_FALSE;\n      }\n    }\n    if (s->command_buf_) {\n      command_buf = s->command_buf_;\n      literal_buf = s->literal_buf_;\n    } else {\n      tmp_command_buf = BROTLI_ALLOC(m, uint32_t, buf_size);\n      tmp_literal_buf = BROTLI_ALLOC(m, uint8_t, buf_size);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp_command_buf) ||\n          BROTLI_IS_NULL(tmp_literal_buf)) {\n        return BROTLI_FALSE;\n      }\n      command_buf = tmp_command_buf;\n      literal_buf = tmp_literal_buf;\n    }\n  }\n\n  while (BROTLI_TRUE) {\n    if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {\n      continue;\n    }\n\n    /* Compress block only when internal output buffer is empty, stream is not\n       finished, there is no pending flush request, and there is either\n       additional input or pending operation. */\n    if (s->available_out_ == 0 &&\n        s->stream_state_ == BROTLI_STREAM_PROCESSING &&\n        (*available_in != 0 || op != BROTLI_OPERATION_PROCESS)) {\n      size_t block_size = BROTLI_MIN(size_t, block_size_limit, *available_in);\n      BROTLI_BOOL is_last =\n          (*available_in == block_size) && (op == BROTLI_OPERATION_FINISH);\n      BROTLI_BOOL force_flush =\n          (*available_in == block_size) && (op == BROTLI_OPERATION_FLUSH);\n      size_t max_out_size = 2 * block_size + 503;\n      BROTLI_BOOL inplace = BROTLI_TRUE;\n      uint8_t* storage = NULL;\n      size_t storage_ix = s->last_bytes_bits_;\n      size_t table_size;\n      int* table;\n\n      if (force_flush && block_size == 0) {\n        s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;\n        continue;\n      }\n      if (max_out_size <= *available_out) {\n        storage = *next_out;\n      } else {\n        inplace = BROTLI_FALSE;\n        storage = GetBrotliStorage(s, max_out_size);\n        if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      }\n      storage[0] = (uint8_t)s->last_bytes_;\n      storage[1] = (uint8_t)(s->last_bytes_ >> 8);\n      table = GetHashTable(s, s->params.quality, block_size, &table_size);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n\n      if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n        BrotliCompressFragmentFast(s->one_pass_arena_, *next_in, block_size,\n            is_last, table, table_size, &storage_ix, storage);\n        if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      } else {\n        BrotliCompressFragmentTwoPass(s->two_pass_arena_, *next_in, block_size,\n            is_last, command_buf, literal_buf, table, table_size,\n            &storage_ix, storage);\n        if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      }\n      if (block_size != 0) {\n        *next_in += block_size;\n        *available_in -= block_size;\n        s->total_in_ += block_size;\n      }\n      if (inplace) {\n        size_t out_bytes = storage_ix >> 3;\n        BROTLI_DCHECK(out_bytes <= *available_out);\n        BROTLI_DCHECK((storage_ix & 7) == 0 || out_bytes < *available_out);\n        *next_out += out_bytes;\n        *available_out -= out_bytes;\n        s->total_out_ += out_bytes;\n        SetTotalOut(s, total_out);\n      } else {\n        size_t out_bytes = storage_ix >> 3;\n        s->next_out_ = storage;\n        s->available_out_ = out_bytes;\n      }\n      s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);\n      s->last_bytes_bits_ = storage_ix & 7u;\n\n      if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;\n      if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED;\n      continue;\n    }\n    break;\n  }\n  BROTLI_FREE(m, tmp_command_buf);\n  BROTLI_FREE(m, tmp_literal_buf);\n  CheckFlushComplete(s);\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL ProcessMetadata(\n    BrotliEncoderState* s, size_t* available_in, const uint8_t** next_in,\n    size_t* available_out, uint8_t** next_out, size_t* total_out) {\n  if (*available_in > (1u << 24)) return BROTLI_FALSE;\n  /* Switch to metadata block workflow, if required. */\n  if (s->stream_state_ == BROTLI_STREAM_PROCESSING) {\n    s->remaining_metadata_bytes_ = (uint32_t)*available_in;\n    s->stream_state_ = BROTLI_STREAM_METADATA_HEAD;\n  }\n  if (s->stream_state_ != BROTLI_STREAM_METADATA_HEAD &&\n      s->stream_state_ != BROTLI_STREAM_METADATA_BODY) {\n    return BROTLI_FALSE;\n  }\n\n  while (BROTLI_TRUE) {\n    if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {\n      continue;\n    }\n    if (s->available_out_ != 0) break;\n\n    if (s->input_pos_ != s->last_flush_pos_) {\n      BROTLI_BOOL result = EncodeData(s, BROTLI_FALSE, BROTLI_TRUE,\n          &s->available_out_, &s->next_out_);\n      if (!result) return BROTLI_FALSE;\n      continue;\n    }\n\n    if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD) {\n      s->next_out_ = s->tiny_buf_.u8;\n      s->available_out_ =\n          WriteMetadataHeader(s, s->remaining_metadata_bytes_, s->next_out_);\n      s->stream_state_ = BROTLI_STREAM_METADATA_BODY;\n      continue;\n    } else {\n      /* Exit workflow only when there is no more input and no more output.\n         Otherwise client may continue producing empty metadata blocks. */\n      if (s->remaining_metadata_bytes_ == 0) {\n        s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;\n        s->stream_state_ = BROTLI_STREAM_PROCESSING;\n        break;\n      }\n      if (*available_out) {\n        /* Directly copy input to output. */\n        uint32_t copy = (uint32_t)BROTLI_MIN(\n            size_t, s->remaining_metadata_bytes_, *available_out);\n        memcpy(*next_out, *next_in, copy);\n        *next_in += copy;\n        *available_in -= copy;\n        s->total_in_ += copy;  /* not actually data input, though */\n        s->remaining_metadata_bytes_ -= copy;\n        *next_out += copy;\n        *available_out -= copy;\n      } else {\n        /* This guarantees progress in \"TakeOutput\" workflow. */\n        uint32_t copy = BROTLI_MIN(uint32_t, s->remaining_metadata_bytes_, 16);\n        s->next_out_ = s->tiny_buf_.u8;\n        memcpy(s->next_out_, *next_in, copy);\n        *next_in += copy;\n        *available_in -= copy;\n        s->total_in_ += copy;  /* not actually data input, though */\n        s->remaining_metadata_bytes_ -= copy;\n        s->available_out_ = copy;\n      }\n      continue;\n    }\n  }\n\n  return BROTLI_TRUE;\n}\n\nstatic void UpdateSizeHint(BrotliEncoderState* s, size_t available_in) {\n  if (s->params.size_hint == 0) {\n    uint64_t delta = UnprocessedInputSize(s);\n    uint64_t tail = available_in;\n    uint32_t limit = 1u << 30;\n    uint32_t total;\n    if ((delta >= limit) || (tail >= limit) || ((delta + tail) >= limit)) {\n      total = limit;\n    } else {\n      total = (uint32_t)(delta + tail);\n    }\n    s->params.size_hint = total;\n  }\n}\n\nBROTLI_BOOL BrotliEncoderCompressStream(\n    BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in,\n    const uint8_t** next_in, size_t* available_out, uint8_t** next_out,\n    size_t* total_out) {\n  if (!EnsureInitialized(s)) return BROTLI_FALSE;\n\n  /* Unfinished metadata block; check requirements. */\n  if (s->remaining_metadata_bytes_ != BROTLI_UINT32_MAX) {\n    if (*available_in != s->remaining_metadata_bytes_) return BROTLI_FALSE;\n    if (op != BROTLI_OPERATION_EMIT_METADATA) return BROTLI_FALSE;\n  }\n\n  if (op == BROTLI_OPERATION_EMIT_METADATA) {\n    UpdateSizeHint(s, 0);  /* First data metablock might be emitted here. */\n    return ProcessMetadata(\n        s, available_in, next_in, available_out, next_out, total_out);\n  }\n\n  if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD ||\n      s->stream_state_ == BROTLI_STREAM_METADATA_BODY) {\n    return BROTLI_FALSE;\n  }\n\n  if (s->stream_state_ != BROTLI_STREAM_PROCESSING && *available_in != 0) {\n    return BROTLI_FALSE;\n  }\n  if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    return BrotliEncoderCompressStreamFast(s, op, available_in, next_in,\n        available_out, next_out, total_out);\n  }\n  while (BROTLI_TRUE) {\n    size_t remaining_block_size = RemainingInputBlockSize(s);\n    /* Shorten input to flint size. */\n    if (s->flint_ >= 0 && remaining_block_size > (size_t)s->flint_) {\n      remaining_block_size = (size_t)s->flint_;\n    }\n\n    if (remaining_block_size != 0 && *available_in != 0) {\n      size_t copy_input_size =\n          BROTLI_MIN(size_t, remaining_block_size, *available_in);\n      CopyInputToRingBuffer(s, copy_input_size, *next_in);\n      *next_in += copy_input_size;\n      *available_in -= copy_input_size;\n      s->total_in_ += copy_input_size;\n      if (s->flint_ > 0) s->flint_ = (int8_t)(s->flint_ - (int)copy_input_size);\n      continue;\n    }\n\n    if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {\n      /* Exit the \"emit flint\" workflow. */\n      if (s->flint_ == BROTLI_FLINT_WAITING_FOR_FLUSHING) {\n        CheckFlushComplete(s);\n        if (s->stream_state_ == BROTLI_STREAM_PROCESSING) {\n          s->flint_ = BROTLI_FLINT_DONE;\n        }\n      }\n      continue;\n    }\n\n    /* Compress data only when internal output buffer is empty, stream is not\n       finished and there is no pending flush request. */\n    if (s->available_out_ == 0 &&\n        s->stream_state_ == BROTLI_STREAM_PROCESSING) {\n      if (remaining_block_size == 0 || op != BROTLI_OPERATION_PROCESS) {\n        BROTLI_BOOL is_last = TO_BROTLI_BOOL(\n            (*available_in == 0) && op == BROTLI_OPERATION_FINISH);\n        BROTLI_BOOL force_flush = TO_BROTLI_BOOL(\n            (*available_in == 0) && op == BROTLI_OPERATION_FLUSH);\n        BROTLI_BOOL result;\n        /* Force emitting (uncompressed) piece containing flint. */\n        if (!is_last && s->flint_ == 0) {\n          s->flint_ = BROTLI_FLINT_WAITING_FOR_FLUSHING;\n          force_flush = BROTLI_TRUE;\n        }\n        UpdateSizeHint(s, *available_in);\n        result = EncodeData(s, is_last, force_flush,\n            &s->available_out_, &s->next_out_);\n        if (!result) return BROTLI_FALSE;\n        if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;\n        if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED;\n        continue;\n      }\n    }\n    break;\n  }\n  CheckFlushComplete(s);\n  return BROTLI_TRUE;\n}\n\nBROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* s) {\n  return TO_BROTLI_BOOL(s->stream_state_ == BROTLI_STREAM_FINISHED &&\n      !BrotliEncoderHasMoreOutput(s));\n}\n\nBROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState* s) {\n  return TO_BROTLI_BOOL(s->available_out_ != 0);\n}\n\nconst uint8_t* BrotliEncoderTakeOutput(BrotliEncoderState* s, size_t* size) {\n  size_t consumed_size = s->available_out_;\n  uint8_t* result = s->next_out_;\n  if (*size) {\n    consumed_size = BROTLI_MIN(size_t, *size, s->available_out_);\n  }\n  if (consumed_size) {\n    s->next_out_ += consumed_size;\n    s->available_out_ -= consumed_size;\n    s->total_out_ += consumed_size;\n    CheckFlushComplete(s);\n    *size = consumed_size;\n  } else {\n    *size = 0;\n    result = 0;\n  }\n  return result;\n}\n\nuint32_t BrotliEncoderVersion(void) {\n  return BROTLI_VERSION;\n}\n\nBrotliEncoderPreparedDictionary* BrotliEncoderPrepareDictionary(\n    BrotliSharedDictionaryType type, size_t size,\n    const uint8_t data[BROTLI_ARRAY_PARAM(size)], int quality,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  ManagedDictionary* managed_dictionary = NULL;\n  BROTLI_BOOL type_is_known = BROTLI_FALSE;\n  type_is_known |= (type == BROTLI_SHARED_DICTIONARY_RAW);\n#if defined(BROTLI_EXPERIMENTAL)\n  type_is_known |= (type == BROTLI_SHARED_DICTIONARY_SERIALIZED);\n#endif  /* BROTLI_EXPERIMENTAL */\n  if (!type_is_known) {\n    return NULL;\n  }\n  managed_dictionary =\n      BrotliCreateManagedDictionary(alloc_func, free_func, opaque);\n  if (managed_dictionary == NULL) {\n    return NULL;\n  }\n  if (type == BROTLI_SHARED_DICTIONARY_RAW) {\n    managed_dictionary->dictionary = (uint32_t*)CreatePreparedDictionary(\n        &managed_dictionary->memory_manager_, data, size);\n  }\n#if defined(BROTLI_EXPERIMENTAL)\n  if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) {\n    SharedEncoderDictionary* dict = (SharedEncoderDictionary*)BrotliAllocate(\n        &managed_dictionary->memory_manager_, sizeof(SharedEncoderDictionary));\n    managed_dictionary->dictionary = (uint32_t*)dict;\n    if (dict != NULL) {\n      BROTLI_BOOL ok = BrotliInitCustomSharedEncoderDictionary(\n          &managed_dictionary->memory_manager_, data, size, quality, dict);\n      if (!ok) {\n        BrotliFree(&managed_dictionary->memory_manager_, dict);\n        managed_dictionary->dictionary = NULL;\n      }\n    }\n  }\n#else  /* BROTLI_EXPERIMENTAL */\n  (void)quality;\n#endif  /* BROTLI_EXPERIMENTAL */\n  if (managed_dictionary->dictionary == NULL) {\n    BrotliDestroyManagedDictionary(managed_dictionary);\n    return NULL;\n  }\n  return (BrotliEncoderPreparedDictionary*)managed_dictionary;\n}\n\nvoid BROTLI_COLD BrotliEncoderDestroyPreparedDictionary(\n    BrotliEncoderPreparedDictionary* dictionary) {\n  ManagedDictionary* dict = (ManagedDictionary*)dictionary;\n  if (!dictionary) return;\n  /* First field of dictionary structs. */\n  /* Only managed dictionaries are eligible for destruction by this method. */\n  if (dict->magic != kManagedDictionaryMagic) {\n    return;\n  }\n  if (dict->dictionary == NULL) {\n    /* This should never ever happen. */\n  } else if (*dict->dictionary == kLeanPreparedDictionaryMagic) {\n    DestroyPreparedDictionary(\n        &dict->memory_manager_, (PreparedDictionary*)dict->dictionary);\n  } else if (*dict->dictionary == kSharedDictionaryMagic) {\n    BrotliCleanupSharedEncoderDictionary(&dict->memory_manager_,\n        (SharedEncoderDictionary*)dict->dictionary);\n    BrotliFree(&dict->memory_manager_, dict->dictionary);\n  } else {\n    /* There is also kPreparedDictionaryMagic, but such instances should be\n     * constructed and destroyed by different means. */\n  }\n  dict->dictionary = NULL;\n  BrotliDestroyManagedDictionary(dict);\n}\n\nBROTLI_BOOL BROTLI_COLD BrotliEncoderAttachPreparedDictionary(\n    BrotliEncoderState* state,\n    const BrotliEncoderPreparedDictionary* dictionary) {\n  /* First field of dictionary structs */\n  const BrotliEncoderPreparedDictionary* dict = dictionary;\n  uint32_t magic = *((const uint32_t*)dict);\n  SharedEncoderDictionary* current = NULL;\n  if (magic == kManagedDictionaryMagic) {\n    /* Unwrap managed dictionary. */\n    ManagedDictionary* managed_dictionary = (ManagedDictionary*)dict;\n    magic = *managed_dictionary->dictionary;\n    dict = (BrotliEncoderPreparedDictionary*)managed_dictionary->dictionary;\n  }\n  current = &state->params.dictionary;\n  if (magic == kPreparedDictionaryMagic ||\n      magic == kLeanPreparedDictionaryMagic) {\n    const PreparedDictionary* prepared = (const PreparedDictionary*)dict;\n    if (!AttachPreparedDictionary(&current->compound, prepared)) {\n      return BROTLI_FALSE;\n    }\n  } else if (magic == kSharedDictionaryMagic) {\n    const SharedEncoderDictionary* attached =\n        (const SharedEncoderDictionary*)dict;\n    BROTLI_BOOL was_default = !current->contextual.context_based &&\n        current->contextual.num_dictionaries == 1 &&\n        current->contextual.dict[0]->hash_table_words ==\n        kStaticDictionaryHashWords &&\n        current->contextual.dict[0]->hash_table_lengths ==\n        kStaticDictionaryHashLengths;\n    BROTLI_BOOL new_default = !attached->contextual.context_based &&\n        attached->contextual.num_dictionaries == 1 &&\n        attached->contextual.dict[0]->hash_table_words ==\n        kStaticDictionaryHashWords &&\n        attached->contextual.dict[0]->hash_table_lengths ==\n        kStaticDictionaryHashLengths;\n    size_t i;\n    if (state->is_initialized_) return BROTLI_FALSE;\n    current->max_quality =\n        BROTLI_MIN(int, current->max_quality, attached->max_quality);\n    for (i = 0; i < attached->compound.num_chunks; i++) {\n      if (!AttachPreparedDictionary(&current->compound,\n          attached->compound.chunks[i])) {\n        return BROTLI_FALSE;\n      }\n    }\n    if (!new_default) {\n      if (!was_default) return BROTLI_FALSE;\n      /* Copy by value, but then set num_instances_ to 0 because their memory\n      is managed by attached, not by current */\n      current->contextual = attached->contextual;\n      current->contextual.num_instances_ = 0;\n    }\n  } else {\n    return BROTLI_FALSE;\n  }\n  return BROTLI_TRUE;\n}\n\nsize_t BROTLI_COLD BrotliEncoderEstimatePeakMemoryUsage(int quality, int lgwin,\n                                                        size_t input_size) {\n  BrotliEncoderParams params;\n  size_t memory_manager_slots = BROTLI_ENCODER_MEMORY_MANAGER_SLOTS;\n  size_t memory_manager_size = memory_manager_slots * sizeof(void*);\n  BrotliEncoderInitParams(&params);\n  params.quality = quality;\n  params.lgwin = lgwin;\n  params.size_hint = input_size;\n  params.large_window = lgwin > BROTLI_MAX_WINDOW_BITS;\n  SanitizeParams(&params);\n  params.lgblock = ComputeLgBlock(&params);\n  ChooseHasher(&params, &params.hasher);\n  if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    size_t state_size = sizeof(BrotliEncoderState);\n    size_t block_size = BROTLI_MIN(size_t, input_size, ((size_t)1ul << params.lgwin));\n    size_t hash_table_size =\n        HashTableSize(MaxHashTableSize(params.quality), block_size);\n    size_t hash_size =\n        (hash_table_size < (1u << 10)) ? 0 : sizeof(int) * hash_table_size;\n    size_t cmdbuf_size = params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY ?\n        5 * BROTLI_MIN(size_t, block_size, 1ul << 17) : 0;\n    if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n      state_size += sizeof(BrotliOnePassArena);\n    } else {\n      state_size += sizeof(BrotliTwoPassArena);\n    }\n    return hash_size + cmdbuf_size + state_size;\n  } else {\n    size_t short_ringbuffer_size = (size_t)1 << params.lgblock;\n    int ringbuffer_bits = ComputeRbBits(&params);\n    size_t ringbuffer_size = input_size < short_ringbuffer_size ?\n        input_size : ((size_t)1u << ringbuffer_bits) + short_ringbuffer_size;\n    size_t hash_size[4] = {0};\n    size_t metablock_size =\n        BROTLI_MIN(size_t, input_size, MaxMetablockSize(&params));\n    size_t inputblock_size =\n        BROTLI_MIN(size_t, input_size, (size_t)1 << params.lgblock);\n    size_t cmdbuf_size = metablock_size * 2 + inputblock_size * 6;\n    size_t outbuf_size = metablock_size * 2 + 503;\n    size_t histogram_size = 0;\n    HasherSize(&params, BROTLI_TRUE, input_size, hash_size);\n    if (params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {\n      cmdbuf_size = BROTLI_MIN(size_t, cmdbuf_size,\n          MAX_NUM_DELAYED_SYMBOLS * sizeof(Command) + inputblock_size * 12);\n    }\n    if (params.quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) {\n      /* Only a very rough estimation, based on enwik8. */\n      histogram_size = 200 << 20;\n    } else if (params.quality >= MIN_QUALITY_FOR_BLOCK_SPLIT) {\n      size_t literal_histograms =\n          BROTLI_MIN(size_t, metablock_size / 6144, 256);\n      size_t command_histograms =\n          BROTLI_MIN(size_t, metablock_size / 6144, 256);\n      size_t distance_histograms =\n          BROTLI_MIN(size_t, metablock_size / 6144, 256);\n      histogram_size = literal_histograms * sizeof(HistogramLiteral) +\n                       command_histograms * sizeof(HistogramCommand) +\n                       distance_histograms * sizeof(HistogramDistance);\n    }\n    return (memory_manager_size + ringbuffer_size +\n            hash_size[0] + hash_size[1] + hash_size[2] + hash_size[3] +\n            cmdbuf_size +\n            outbuf_size +\n            histogram_size);\n  }\n}\nsize_t BROTLI_COLD BrotliEncoderGetPreparedDictionarySize(\n    const BrotliEncoderPreparedDictionary* prepared_dictionary) {\n  /* First field of dictionary structs */\n  const BrotliEncoderPreparedDictionary* prepared = prepared_dictionary;\n  uint32_t magic = *((const uint32_t*)prepared);\n  size_t overhead = 0;\n  if (magic == kManagedDictionaryMagic) {\n    const ManagedDictionary* managed = (const ManagedDictionary*)prepared;\n    overhead = sizeof(ManagedDictionary);\n    magic = *managed->dictionary;\n    prepared = (const BrotliEncoderPreparedDictionary*)managed->dictionary;\n  }\n\n  if (magic == kPreparedDictionaryMagic) {\n    const PreparedDictionary* dictionary =\n        (const PreparedDictionary*)prepared;\n    /* Keep in sync with step 3 of CreatePreparedDictionary */\n    return sizeof(PreparedDictionary) + dictionary->source_size +\n        (sizeof(uint32_t) << dictionary->slot_bits) +\n        (sizeof(uint16_t) << dictionary->bucket_bits) +\n        (sizeof(uint32_t) * dictionary->num_items) + overhead;\n  } else if (magic == kLeanPreparedDictionaryMagic) {\n    const PreparedDictionary* dictionary =\n        (const PreparedDictionary*)prepared;\n    /* Keep in sync with step 3 of CreatePreparedDictionary */\n    return sizeof(PreparedDictionary) + sizeof(uint8_t*) +\n        (sizeof(uint32_t) << dictionary->slot_bits) +\n        (sizeof(uint16_t) << dictionary->bucket_bits) +\n        (sizeof(uint32_t) * dictionary->num_items) + overhead;\n  } else if (magic == kSharedDictionaryMagic) {\n    const SharedEncoderDictionary* dictionary =\n        (const SharedEncoderDictionary*)prepared;\n    const CompoundDictionary* compound = &dictionary->compound;\n    const ContextualEncoderDictionary* contextual = &dictionary->contextual;\n    size_t result = sizeof(*dictionary);\n    size_t i;\n    size_t num_instances;\n    const BrotliEncoderDictionary* instances;\n    for (i = 0; i < compound->num_prepared_instances_; i++) {\n      size_t size = BrotliEncoderGetPreparedDictionarySize(\n          (const BrotliEncoderPreparedDictionary*)\n          compound->prepared_instances_[i]);\n      if (!size) return 0;  /* error */\n      result += size;\n    }\n    if (contextual->context_based) {\n      num_instances = contextual->num_instances_;\n      instances = contextual->instances_;\n      result += sizeof(*instances) * num_instances;\n    } else {\n      num_instances = 1;\n      instances = &contextual->instance_;\n    }\n    for (i = 0; i < num_instances; i++) {\n      const BrotliEncoderDictionary* dict = &instances[i];\n      result += dict->trie.pool_capacity * sizeof(BrotliTrieNode);\n      if (dict->hash_table_data_words_) {\n        result += sizeof(kStaticDictionaryHashWords);\n      }\n      if (dict->hash_table_data_lengths_) {\n        result += sizeof(kStaticDictionaryHashLengths);\n      }\n      if (dict->buckets_data_) {\n        result += sizeof(*dict->buckets_data_) * dict->buckets_alloc_size_;\n      }\n      if (dict->dict_words_data_) {\n        result += sizeof(*dict->dict_words) * dict->dict_words_alloc_size_;\n      }\n      if (dict->words_instance_) {\n        result += sizeof(*dict->words_instance_);\n        /* data_size not added here: it is never allocated by the\n           SharedEncoderDictionary, instead it always points to the file\n           already loaded in memory. So if the caller wants to include\n           this memory as well, add the size of the loaded dictionary\n           file to this. */\n      }\n    }\n    return result + overhead;\n  }\n  return 0;  /* error */\n}\n\n#if defined(BROTLI_TEST)\nsize_t BrotliMakeUncompressedStreamForTest(const uint8_t*, size_t, uint8_t*);\nsize_t BrotliMakeUncompressedStreamForTest(\n    const uint8_t* input, size_t input_size, uint8_t* output) {\n  return MakeUncompressedStream(input, input_size, output);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/encoder_dict.c",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"encoder_dict.h\"\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include <brotli/shared_dictionary.h>\n#include \"../common/shared_dictionary_internal.h\"\n#include \"../common/transform.h\"\n#include <brotli/encode.h>\n#include \"compound_dictionary.h\"\n#include \"dictionary_hash.h\"\n#include \"hash_base.h\"\n#include \"hash.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n#include \"static_dict_lut.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define NUM_HASH_BITS 15u\n#define NUM_HASH_BUCKETS (1u << NUM_HASH_BITS)\n\nstatic void BrotliTrieInit(BrotliTrie* trie) {\n  trie->pool_capacity = 0;\n  trie->pool_size = 0;\n  trie->pool = 0;\n\n  /* Set up the root node */\n  trie->root.single = 0;\n  trie->root.len_ = 0;\n  trie->root.idx_ = 0;\n  trie->root.sub = 0;\n}\n\nstatic void BrotliTrieFree(MemoryManager* m, BrotliTrie* trie) {\n  BrotliFree(m, trie->pool);\n}\n\n/* Initializes to RFC 7932 static dictionary / transforms. */\nstatic void InitEncoderDictionary(BrotliEncoderDictionary* dict) {\n  dict->words = BrotliGetDictionary();\n  dict->num_transforms = (uint32_t)BrotliGetTransforms()->num_transforms;\n\n  dict->hash_table_words = kStaticDictionaryHashWords;\n  dict->hash_table_lengths = kStaticDictionaryHashLengths;\n  dict->buckets = kStaticDictionaryBuckets;\n  dict->dict_words = kStaticDictionaryWords;\n\n  dict->cutoffTransformsCount = kCutoffTransformsCount;\n  dict->cutoffTransforms = kCutoffTransforms;\n\n  dict->parent = 0;\n\n  dict->hash_table_data_words_ = 0;\n  dict->hash_table_data_lengths_ = 0;\n  dict->buckets_alloc_size_ = 0;\n  dict->buckets_data_ = 0;\n  dict->dict_words_alloc_size_ = 0;\n  dict->dict_words_data_ = 0;\n  dict->words_instance_ = 0;\n  dict->has_words_heavy = BROTLI_FALSE;\n  BrotliTrieInit(&dict->trie);\n}\n\nstatic void BrotliDestroyEncoderDictionary(MemoryManager* m,\n    BrotliEncoderDictionary* dict) {\n  BrotliFree(m, dict->hash_table_data_words_);\n  BrotliFree(m, dict->hash_table_data_lengths_);\n  BrotliFree(m, dict->buckets_data_);\n  BrotliFree(m, dict->dict_words_data_);\n  BrotliFree(m, dict->words_instance_);\n  BrotliTrieFree(m, &dict->trie);\n}\n\n#if defined(BROTLI_EXPERIMENTAL)\n/* Word length must be at least 4 bytes */\nstatic uint32_t Hash(const uint8_t* data, int bits) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - bits);\n}\n\n/* Theoretical max possible word size after transform */\n#define kTransformedBufferSize \\\n    (256 + 256 + SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH)\n\n/* To be safe buffer must have at least kTransformedBufferSize */\nstatic void TransformedDictionaryWord(uint32_t word_idx, int len, int transform,\n    const BrotliTransforms* transforms,\n    const BrotliEncoderDictionary* dict,\n    uint8_t* buffer, size_t* size) {\n  const uint8_t* dict_word = &dict->words->data[\n      dict->words->offsets_by_length[len] + (uint32_t)len * word_idx];\n  *size = (size_t)BrotliTransformDictionaryWord(buffer, dict_word, len,\n      transforms, transform);\n}\n\nstatic DictWord MakeDictWord(uint8_t len, uint8_t transform, uint16_t idx) {\n  DictWord result;\n  result.len = len;\n  result.transform = transform;\n  result.idx = idx;\n  return result;\n}\n\nstatic uint32_t BrotliTrieAlloc(MemoryManager* m, size_t num, BrotliTrie* trie,\n                                BrotliTrieNode** keep) {\n  uint32_t result;\n  uint32_t keep_index = 0;\n  if (keep && *keep != &trie->root) {\n    /* Optional node to keep, since address may change after re-allocating */\n    keep_index = (uint32_t)(*keep - trie->pool);\n  }\n  if (trie->pool_size == 0) {\n    /* Have a placeholder node in the front. We do not want the result to be 0,\n       it must be at least 1, 0 represents \"null pointer\" */\n    trie->pool_size = 1;\n  }\n  BROTLI_ENSURE_CAPACITY(m, BrotliTrieNode, trie->pool, trie->pool_capacity,\n                         trie->pool_size + num);\n  if (BROTLI_IS_OOM(m)) return 0;\n  /* Init the new nodes to empty */\n  memset(trie->pool + trie->pool_size, 0, sizeof(*trie->pool) * num);\n  result = (uint32_t)trie->pool_size;\n  trie->pool_size += num;\n  if (keep && *keep != &trie->root) {\n    *keep = trie->pool + keep_index;\n  }\n  return result;\n}\n\n/**\n * len and idx: payload for last node\n * word, size: the string\n * index: position in the string\n */\nstatic BROTLI_BOOL BrotliTrieNodeAdd(MemoryManager* m, uint8_t len,\n    uint32_t idx, const uint8_t* word, size_t size, int index,\n    BrotliTrieNode* node, BrotliTrie* trie) {\n  BrotliTrieNode* child = 0;\n  uint8_t c;\n  if ((size_t)index == size) {\n    if (!node->len_ || idx < node->idx_) {\n      node->len_ = len;\n      node->idx_ = idx;\n    }\n    return BROTLI_TRUE;\n  }\n  c = word[index];\n  if (node->single && c != node->c) {\n    BrotliTrieNode old = trie->pool[node->sub];\n    uint32_t new_nodes = BrotliTrieAlloc(m, 32, trie, &node);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    node->single = 0;\n    node->sub = new_nodes;\n    trie->pool[node->sub + (node->c >> 4)].sub = new_nodes + 16;\n    trie->pool[trie->pool[node->sub + (node->c >> 4)].sub + (node->c & 15)] =\n        old;\n  }\n  if (!node->sub) {\n    uint32_t new_node = BrotliTrieAlloc(m, 1, trie, &node);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    node->single = 1;\n    node->c = c;\n    node->sub = new_node;\n  }\n  if (node->single) {\n    child = &trie->pool[node->sub];\n  } else {\n    if (!trie->pool[node->sub + (c >> 4)].sub) {\n      uint32_t new_nodes = BrotliTrieAlloc(m, 16, trie, &node);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      trie->pool[node->sub + (c >> 4)].sub = new_nodes;\n    }\n    child = &trie->pool[trie->pool[node->sub + (c >> 4)].sub + (c & 15)];\n  }\n  return BrotliTrieNodeAdd(m, len, idx, word, size, index + 1, child, trie);\n}\n\nstatic BROTLI_BOOL BrotliTrieAdd(MemoryManager* m, uint8_t len, uint32_t idx,\n                          const uint8_t* word, size_t size, BrotliTrie* trie) {\n  return BrotliTrieNodeAdd(m, len, idx, word, size, 0, &trie->root, trie);\n}\n\nconst BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie,\n                                    const BrotliTrieNode* node, uint8_t c) {\n  BrotliTrieNode* temp_node;\n  if (node->single) {\n    if (node->c == c) return &trie->pool[node->sub];\n    return 0;\n  }\n  if (!node->sub) return 0;\n  temp_node = &trie->pool[node->sub + (c >> 4)];\n  if (!temp_node->sub) return 0;\n  return &trie->pool[temp_node->sub + (c & 15)];\n}\n\nstatic const BrotliTrieNode* BrotliTrieFind(const BrotliTrie* trie,\n                                            const uint8_t* word, size_t size) {\n  const BrotliTrieNode* node = &trie->root;\n  size_t i;\n  for (i = 0; i < size; i++) {\n    node = BrotliTrieSub(trie, node, word[i]);\n    if (!node) return 0;\n  }\n  return node;\n}\n\nstatic BROTLI_BOOL BuildDictionaryLut(MemoryManager* m,\n    const BrotliTransforms* transforms,\n    BrotliEncoderDictionary* dict) {\n  uint32_t i;\n  DictWord* dict_words;\n  uint16_t* buckets;\n  DictWord** words_by_hash;\n  size_t* words_by_hash_size;\n  size_t* words_by_hash_capacity;\n  BrotliTrie dedup;\n  uint8_t word[kTransformedBufferSize];\n  size_t word_size;\n  size_t total = 0;\n  uint8_t l;\n  uint16_t idx;\n\n  BrotliTrieInit(&dedup);\n\n  words_by_hash = (DictWord**)BrotliAllocate(m,\n      sizeof(*words_by_hash) * NUM_HASH_BUCKETS);\n  words_by_hash_size = (size_t*)BrotliAllocate(m,\n      sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS);\n  words_by_hash_capacity = (size_t*)BrotliAllocate(m,\n      sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS);\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  memset(words_by_hash, 0, sizeof(*words_by_hash) * NUM_HASH_BUCKETS);\n  memset(words_by_hash_size, 0, sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS);\n  memset(words_by_hash_capacity, 0,\n         sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS);\n\n  if (transforms->num_transforms > 0) {\n    for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;\n        l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) {\n      uint16_t n = dict->words->size_bits_by_length[l] ?\n          (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u;\n      for (idx = 0; idx < n; ++idx) {\n        uint32_t key;\n        /* First transform (usually identity) */\n        TransformedDictionaryWord(idx, l, 0, transforms, dict, word,\n                                  &word_size);\n        /* Cannot hash words smaller than 4 bytes */\n        if (word_size < 4) {\n          /* Break instead of continue, all next words of this length will have\n             same length after transform */\n          break;\n        }\n        if (!BrotliTrieAdd(m, 0, idx, word, word_size, &dedup)) {\n          return BROTLI_FALSE;\n        }\n        key = Hash(word, NUM_HASH_BITS);\n        BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],\n            words_by_hash_capacity[key], words_by_hash_size[key],\n            MakeDictWord(l, 0, idx));\n        ++total;\n      }\n    }\n  }\n\n  /* These LUT transforms only supported if no custom transforms. This is\n     ok, we will use the heavy trie instead. */\n  if (transforms == BrotliGetTransforms()) {\n    for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;\n        l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) {\n      uint16_t n = dict->words->size_bits_by_length[l] ?\n          (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u;\n      for (idx = 0; idx < n; ++idx) {\n        int k;\n        BROTLI_BOOL is_ascii = BROTLI_TRUE;\n        size_t offset = dict->words->offsets_by_length[l] + (size_t)l * idx;\n        const uint8_t* data = &dict->words->data[offset];\n        for (k = 0; k < l; ++k) {\n          if (data[k] >= 128) is_ascii = BROTLI_FALSE;\n        }\n        if (data[0] < 128) {\n          int transform = 9;  /* {empty, uppercase first, empty} */\n          uint32_t ix = idx + (uint32_t)transform * n;\n          const BrotliTrieNode* it;\n          TransformedDictionaryWord(idx, l, transform, transforms,\n                                   dict, word, &word_size);\n          it = BrotliTrieFind(&dedup, word, word_size);\n          if (!it || it->idx_ > ix) {\n            uint32_t key = Hash(word, NUM_HASH_BITS);\n            if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) {\n              return BROTLI_FALSE;\n            }\n            BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],\n                words_by_hash_capacity[key], words_by_hash_size[key],\n                MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_FIRST, idx));\n            ++total;\n          }\n        }\n        if (is_ascii) {\n          int transform = 44;  /* {empty, uppercase all, empty} */\n          uint32_t ix = idx + (uint32_t)transform * n;\n          const BrotliTrieNode* it;\n          TransformedDictionaryWord(idx, l, transform, transforms,\n                                    dict, word, &word_size);\n          it = BrotliTrieFind(&dedup, word, word_size);\n          if (!it || it->idx_ > ix) {\n            uint32_t key = Hash(word, NUM_HASH_BITS);\n            if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) {\n              return BROTLI_FALSE;\n            }\n            BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],\n                words_by_hash_capacity[key], words_by_hash_size[key],\n                MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_ALL, idx));\n            ++total;\n          }\n        }\n      }\n    }\n  }\n\n  dict_words = (DictWord*)BrotliAllocate(m,\n      sizeof(*dict->dict_words) * (total + 1));\n  buckets = (uint16_t*)BrotliAllocate(m,\n      sizeof(*dict->buckets) * NUM_HASH_BUCKETS);\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  dict->dict_words_alloc_size_ = total + 1;\n  dict->dict_words = dict->dict_words_data_ = dict_words;\n  dict->buckets_alloc_size_ = NUM_HASH_BUCKETS;\n  dict->buckets = dict->buckets_data_ = buckets;\n\n  /* Unused; makes offsets start from 1. */\n  dict_words[0] = MakeDictWord(0, 0, 0);\n  total = 1;\n  for (i = 0; i < NUM_HASH_BUCKETS; ++i) {\n    size_t num_words = words_by_hash_size[i];\n    if (num_words > 0) {\n      buckets[i] = (uint16_t)(total);\n      memcpy(&dict_words[total], &words_by_hash[i][0],\n          sizeof(dict_words[0]) * num_words);\n      total += num_words;\n      dict_words[total - 1].len |= 0x80;\n    } else {\n      buckets[i] = 0;\n    }\n  }\n\n  for (i = 0; i < NUM_HASH_BUCKETS; ++i) {\n    BrotliFree(m, words_by_hash[i]);\n  }\n  BrotliFree(m, words_by_hash);\n  BrotliFree(m, words_by_hash_size);\n  BrotliFree(m, words_by_hash_capacity);\n  BrotliTrieFree(m, &dedup);\n\n  return BROTLI_TRUE;\n}\n\nstatic void BuildDictionaryHashTable(uint16_t* hash_table_words,\n    uint8_t* hash_table_lengths, const BrotliDictionary* dict) {\n  int j, len;\n  /* The order of the loops is such that in case of collision, words with\n     shorter length are preferred, and in case of same length, words with\n     smaller index. There is only a single word per bucket. */\n  /* TODO(lode): consider adding optional user-supplied frequency_map to use\n     for preferred words instead, this can make the encoder better for\n     quality 9 and below without affecting the decoder */\n  memset(hash_table_words, 0, sizeof(kStaticDictionaryHashWords));\n  memset(hash_table_lengths, 0, sizeof(kStaticDictionaryHashLengths));\n  for (len = SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH;\n      len >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; --len) {\n    const size_t num_words = dict->size_bits_by_length[len] ?\n        (1u << dict->size_bits_by_length[len]) : 0;\n    for (j = (int)num_words - 1; j >= 0; --j) {\n      size_t offset = dict->offsets_by_length[len] +\n          (size_t)len * (size_t)j;\n      const uint8_t* word = &dict->data[offset];\n      const uint32_t key = Hash(word, 14);\n      int idx = (int)(key << 1) + (len < 8 ? 1 : 0);\n      BROTLI_DCHECK(idx < (int)NUM_HASH_BUCKETS);\n      hash_table_words[idx] = (uint16_t)j;\n      hash_table_lengths[idx] = (uint8_t)len;\n    }\n  }\n}\n\nstatic BROTLI_BOOL GenerateWordsHeavy(MemoryManager* m,\n    const BrotliTransforms* transforms,\n    BrotliEncoderDictionary* dict) {\n  int i, j, l;\n  for (j = (int)transforms->num_transforms - 1; j >= 0 ; --j) {\n    for (l = 0; l < 32; l++) {\n      int num = (int)((1u << dict->words->size_bits_by_length[l]) & ~1u);\n      for (i = 0; i < num; i++) {\n        uint8_t transformed[kTransformedBufferSize];\n        size_t size;\n        TransformedDictionaryWord(\n            (uint32_t)i, l, j, transforms, dict, transformed, &size);\n        if (size < 4) continue;\n        if (!BrotliTrieAdd(m, (uint8_t)l, (uint32_t)(i + num * j),\n            transformed, size, &dict->trie)) {\n          return BROTLI_FALSE;\n        }\n      }\n    }\n  }\n  return BROTLI_TRUE;\n}\n\n/* Computes cutoffTransformsCount (in count) and cutoffTransforms (in data) for\n   the custom transforms, where possible within the limits of the\n   cutoffTransforms encoding. The fast encoder uses this to do fast lookup for\n   transforms that remove the N last characters (OmitLast). */\nstatic void ComputeCutoffTransforms(\n    const BrotliTransforms* transforms,\n    uint32_t* count, uint64_t* data) {\n  int i;\n  /* The encoding in a 64-bit integer of transform N in the data is: (N << 2) +\n     ((cutoffTransforms >> (N * 6)) & 0x3F), so for example the identity\n     transform code must be 0-63, for N=1 the transform code must be 4-67, ...,\n     for N=9 it must be 36-99.\n     TODO(lode): consider a simple flexible uint8_t[10] instead of the uint64_t\n     for the cutoff transforms, so that shared dictionaries can have the\n     OmitLast transforms anywhere without loss. */\n  *count = 0;\n  *data = 0;\n  for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {\n    int idx = transforms->cutOffTransforms[i];\n    if (idx == -1) break;  /* Not found */\n    if (idx < (i << 2)) break;  /* Too small for the encoding */\n    if (idx >= (i << 2) + 64) break;  /* Too large for the encoding */\n    (*count)++;\n    *data |= (uint64_t)(((uint64_t)idx -\n        ((uint64_t)i << 2u)) << ((uint64_t)i * 6u));\n  }\n}\n\nstatic BROTLI_BOOL ComputeDictionary(MemoryManager* m, int quality,\n    const BrotliTransforms* transforms,\n    BrotliEncoderDictionary* current) {\n  int default_words = current->words == BrotliGetDictionary();\n  int default_transforms = transforms == BrotliGetTransforms();\n\n  if (default_words && default_transforms) {\n    /* hashes are already set to Brotli defaults */\n    return BROTLI_TRUE;\n  }\n\n  current->hash_table_data_words_ = (uint16_t*)BrotliAllocate(\n      m, sizeof(kStaticDictionaryHashWords));\n  current->hash_table_data_lengths_ = (uint8_t*)BrotliAllocate(\n      m, sizeof(kStaticDictionaryHashLengths));\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  current->hash_table_words = current->hash_table_data_words_;\n  current->hash_table_lengths = current->hash_table_data_lengths_;\n\n  BuildDictionaryHashTable(current->hash_table_data_words_,\n      current->hash_table_data_lengths_, current->words);\n\n  ComputeCutoffTransforms(transforms,\n      &current->cutoffTransformsCount, &current->cutoffTransforms);\n\n  /* Only compute the data for slow encoder if the requested quality is high\n     enough to need it */\n  if (quality >= ZOPFLIFICATION_QUALITY) {\n    if (!BuildDictionaryLut(m, transforms, current)) return BROTLI_FALSE;\n\n    /* For the built-in Brotli transforms, there is a hard-coded function to\n       handle all transforms, but for custom transforms, we use the following\n       large hammer instead */\n    current->has_words_heavy = !default_transforms;\n    if (current->has_words_heavy) {\n      if (!GenerateWordsHeavy(m, transforms, current)) return BROTLI_FALSE;\n    }\n  }\n\n  return BROTLI_TRUE;\n}\n#endif  /* BROTLI_EXPERIMENTAL */\n\nvoid BrotliInitSharedEncoderDictionary(SharedEncoderDictionary* dict) {\n  dict->magic = kSharedDictionaryMagic;\n\n  dict->compound.num_chunks = 0;\n  dict->compound.total_size = 0;\n  dict->compound.chunk_offsets[0] = 0;\n  dict->compound.num_prepared_instances_ = 0;\n\n  dict->contextual.context_based = 0;\n  dict->contextual.num_dictionaries = 1;\n  dict->contextual.instances_ = 0;\n  dict->contextual.num_instances_ = 1;  /* The instance_ field */\n  dict->contextual.dict[0] = &dict->contextual.instance_;\n  InitEncoderDictionary(&dict->contextual.instance_);\n  dict->contextual.instance_.parent = &dict->contextual;\n\n  dict->max_quality = BROTLI_MAX_QUALITY;\n}\n\n#if defined(BROTLI_EXPERIMENTAL)\n/* TODO(eustas): make sure that tooling will warn user if not all the cutoff\n   transforms are available (for low-quality encoder). */\nstatic BROTLI_BOOL InitCustomSharedEncoderDictionary(\n    MemoryManager* m, const BrotliSharedDictionary* decoded_dict,\n    int quality, SharedEncoderDictionary* dict) {\n  ContextualEncoderDictionary* contextual;\n  CompoundDictionary* compound;\n  BrotliEncoderDictionary* instances;\n  int i;\n  BrotliInitSharedEncoderDictionary(dict);\n\n  contextual = &dict->contextual;\n  compound = &dict->compound;\n\n  for (i = 0; i < (int)decoded_dict->num_prefix; i++) {\n    PreparedDictionary* prepared = CreatePreparedDictionary(m,\n        decoded_dict->prefix[i], decoded_dict->prefix_size[i]);\n    AttachPreparedDictionary(compound, prepared);\n    /* remember for cleanup */\n    compound->prepared_instances_[\n        compound->num_prepared_instances_++] = prepared;\n  }\n\n  dict->max_quality = quality;\n  contextual->context_based = decoded_dict->context_based;\n  if (decoded_dict->context_based) {\n    memcpy(contextual->context_map, decoded_dict->context_map,\n        SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS);\n  }\n\n  contextual->num_dictionaries = decoded_dict->num_dictionaries;\n  contextual->num_instances_ = decoded_dict->num_dictionaries;\n  if (contextual->num_instances_ == 1) {\n    instances = &contextual->instance_;\n  } else {\n    contextual->instances_ = (BrotliEncoderDictionary*)\n        BrotliAllocate(m, sizeof(*contextual->instances_) *\n        contextual->num_instances_);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    instances = contextual->instances_;\n  }\n  for (i = 0; i < (int)contextual->num_instances_; i++) {\n    BrotliEncoderDictionary* current = &instances[i];\n    InitEncoderDictionary(current);\n    current->parent = &dict->contextual;\n    if (decoded_dict->words[i] == BrotliGetDictionary()) {\n      current->words = BrotliGetDictionary();\n    } else {\n      current->words_instance_ = (BrotliDictionary*)BrotliAllocate(\n          m, sizeof(BrotliDictionary));\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      *current->words_instance_ = *decoded_dict->words[i];\n      current->words = current->words_instance_;\n    }\n    current->num_transforms =\n        (uint32_t)decoded_dict->transforms[i]->num_transforms;\n    if (!ComputeDictionary(\n        m, quality, decoded_dict->transforms[i], current)) {\n      return BROTLI_FALSE;\n    }\n\n    contextual->dict[i] = current;\n  }\n\n  return BROTLI_TRUE;  /* success */\n}\n\nBROTLI_BOOL BrotliInitCustomSharedEncoderDictionary(\n    MemoryManager* m, const uint8_t* encoded_dict, size_t size,\n    int quality, SharedEncoderDictionary* dict) {\n  BROTLI_BOOL success = BROTLI_FALSE;\n  BrotliSharedDictionary* decoded_dict = BrotliSharedDictionaryCreateInstance(\n      m->alloc_func, m->free_func, m->opaque);\n  if (!decoded_dict) {  /* OOM */\n    return BROTLI_FALSE;\n  }\n  success = BrotliSharedDictionaryAttach(\n      decoded_dict, BROTLI_SHARED_DICTIONARY_SERIALIZED, size, encoded_dict);\n  if (success) {\n    success = InitCustomSharedEncoderDictionary(m,\n        decoded_dict, quality, dict);\n  }\n  BrotliSharedDictionaryDestroyInstance(decoded_dict);\n  return success;\n}\n#endif  /* BROTLI_EXPERIMENTAL */\n\nvoid BrotliCleanupSharedEncoderDictionary(MemoryManager* m,\n                                          SharedEncoderDictionary* dict) {\n  size_t i;\n  for (i = 0; i < dict->compound.num_prepared_instances_; i++) {\n    DestroyPreparedDictionary(m,\n        (PreparedDictionary*)dict->compound.prepared_instances_[i]);\n  }\n  if (dict->contextual.num_instances_ == 1) {\n    BrotliDestroyEncoderDictionary(m, &dict->contextual.instance_);\n  } else if (dict->contextual.num_instances_ > 1) {\n    for (i = 0; i < dict->contextual.num_instances_; i++) {\n      BrotliDestroyEncoderDictionary(m, &dict->contextual.instances_[i]);\n    }\n    BrotliFree(m, dict->contextual.instances_);\n  }\n}\n\nManagedDictionary* BrotliCreateManagedDictionary(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  ManagedDictionary* result = (ManagedDictionary*)BrotliBootstrapAlloc(\n      sizeof(ManagedDictionary), alloc_func, free_func, opaque);\n  if (result == NULL) return NULL;\n\n  result->magic = kManagedDictionaryMagic;\n  BrotliInitMemoryManager(\n      &result->memory_manager_, alloc_func, free_func, opaque);\n  result->dictionary = NULL;\n\n  return result;\n}\n\nvoid BrotliDestroyManagedDictionary(ManagedDictionary* dictionary) {\n  if (!dictionary) return;\n  BrotliBootstrapFree(dictionary, &dictionary->memory_manager_);\n}\n\n/* Escalate internal functions visibility; for testing purposes only. */\n#if defined(BROTLI_TEST)\nvoid BrotliInitEncoderDictionaryForTest(BrotliEncoderDictionary*);\nvoid BrotliInitEncoderDictionaryForTest(BrotliEncoderDictionary* d) {\n  InitEncoderDictionary(d);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/encoder_dict.h",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#ifndef BROTLI_ENC_ENCODER_DICT_H_\n#define BROTLI_ENC_ENCODER_DICT_H_\n\n#include \"../common/dictionary.h\"\n#include <brotli/shared_dictionary.h>\n#include \"../common/platform.h\"\n#include \"compound_dictionary.h\"\n#include \"memory.h\"\n#include \"static_dict_lut.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/*\nDictionary hierarchy for Encoder:\n-SharedEncoderDictionary\n--CompoundDictionary\n---PreparedDictionary [up to 15x]\n   = prefix dictionary with precomputed hashes\n--ContextualEncoderDictionary\n---BrotliEncoderDictionary [up to 64x]\n   = for each context, precomputed static dictionary with words + transforms\n\nDictionary hierarchy from common: similar, but without precomputed hashes\n-BrotliSharedDictionary\n--BrotliDictionary [up to 64x]\n--BrotliTransforms [up to 64x]\n--const uint8_t* prefix [up to 15x]: compound dictionaries\n*/\n\ntypedef struct BrotliTrieNode {\n  uint8_t single;  /* if 1, sub is a single node for c instead of 256 */\n  uint8_t c;\n  uint8_t len_;  /* untransformed length */\n  uint32_t idx_;  /* word index + num words * transform index */\n  uint32_t sub;  /* index of sub node(s) in the pool */\n} BrotliTrieNode;\n\ntypedef struct BrotliTrie {\n  BrotliTrieNode* pool;\n  size_t pool_capacity;\n  size_t pool_size;\n  BrotliTrieNode root;\n} BrotliTrie;\n\n#if defined(BROTLI_EXPERIMENTAL)\nBROTLI_INTERNAL const BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie,\n    const BrotliTrieNode* node, uint8_t c);\n#endif  /* BROTLI_EXPERIMENTAL */\n\n/* Dictionary data (words and transforms) for 1 possible context */\ntypedef struct BrotliEncoderDictionary {\n  const BrotliDictionary* words;\n  uint32_t num_transforms;\n\n  /* cut off for fast encoder */\n  uint32_t cutoffTransformsCount;\n  uint64_t cutoffTransforms;\n\n  /* from dictionary_hash.h, for fast encoder */\n  const uint16_t* hash_table_words;\n  const uint8_t* hash_table_lengths;\n\n  /* from static_dict_lut.h, for slow encoder */\n  const uint16_t* buckets;\n  const DictWord* dict_words;\n  /* Heavy version, for use by slow encoder when there are custom transforms.\n     Contains every possible transformed dictionary word in a trie. It encodes\n     about as fast as the non-heavy encoder but consumes a lot of memory and\n     takes time to build. */\n  BrotliTrie trie;\n  BROTLI_BOOL has_words_heavy;\n\n  /* Reference to other dictionaries. */\n  const struct ContextualEncoderDictionary* parent;\n\n  /* Allocated memory, used only when not using the Brotli defaults */\n  uint16_t* hash_table_data_words_;\n  uint8_t* hash_table_data_lengths_;\n  size_t buckets_alloc_size_;\n  uint16_t* buckets_data_;\n  size_t dict_words_alloc_size_;\n  DictWord* dict_words_data_;\n  BrotliDictionary* words_instance_;\n} BrotliEncoderDictionary;\n\n/* Dictionary data for all 64 contexts */\ntypedef struct ContextualEncoderDictionary {\n  BROTLI_BOOL context_based;\n  uint8_t num_dictionaries;\n  uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n  const BrotliEncoderDictionary* dict[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* If num_instances_ is 1, instance_ is used, else dynamic allocation with\n     instances_ is used. */\n  size_t num_instances_;\n  BrotliEncoderDictionary instance_;\n  BrotliEncoderDictionary* instances_;\n} ContextualEncoderDictionary;\n\ntypedef struct SharedEncoderDictionary {\n  /* Magic value to distinguish this struct from PreparedDictionary for\n     certain external usages. */\n  uint32_t magic;\n\n  /* LZ77 prefix, compound dictionary */\n  CompoundDictionary compound;\n\n  /* Custom static dictionary (optionally context-based) */\n  ContextualEncoderDictionary contextual;\n\n  /* The maximum quality the dictionary was computed for */\n  int max_quality;\n} SharedEncoderDictionary;\n\ntypedef struct ManagedDictionary {\n  uint32_t magic;\n  MemoryManager memory_manager_;\n  uint32_t* dictionary;\n} ManagedDictionary;\n\n/* Initializes to the brotli built-in dictionary */\nBROTLI_INTERNAL void BrotliInitSharedEncoderDictionary(\n    SharedEncoderDictionary* dict);\n\n#if defined(BROTLI_EXPERIMENTAL)\n/* Initializes to shared dictionary that will be parsed from\n   encoded_dict. Requires that you keep the encoded_dict buffer\n   around, parts of data will point to it. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliInitCustomSharedEncoderDictionary(\n    MemoryManager* m, const uint8_t* encoded_dict, size_t size,\n    int quality, SharedEncoderDictionary* dict);\n#endif  /* BROTLI_EXPERIMENTAL */\n\nBROTLI_INTERNAL void BrotliCleanupSharedEncoderDictionary(\n    MemoryManager* m, SharedEncoderDictionary* dict);\n\nBROTLI_INTERNAL ManagedDictionary* BrotliCreateManagedDictionary(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\nBROTLI_INTERNAL void BrotliDestroyManagedDictionary(\n    ManagedDictionary* dictionary);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENCODER_DICT_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/entropy_encode.c",
    "content": "﻿/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Entropy encoding (Huffman) utilities. */\n\n#include \"entropy_encode.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nconst BROTLI_MODEL(\"small\") size_t kBrotliShellGaps[] = {132, 57, 23, 10, 4, 1};\n\nBROTLI_BOOL BrotliSetDepth(\n    int p0, HuffmanTree* pool, uint8_t* depth, int max_depth) {\n  int stack[16];\n  int level = 0;\n  int p = p0;\n  BROTLI_DCHECK(max_depth <= 15);\n  stack[0] = -1;\n  while (BROTLI_TRUE) {\n    if (pool[p].index_left_ >= 0) {\n      level++;\n      if (level > max_depth) return BROTLI_FALSE;\n      stack[level] = pool[p].index_right_or_value_;\n      p = pool[p].index_left_;\n      continue;\n    } else {\n      depth[pool[p].index_right_or_value_] = (uint8_t)level;\n    }\n    while (level >= 0 && stack[level] == -1) level--;\n    if (level < 0) return BROTLI_TRUE;\n    p = stack[level];\n    stack[level] = -1;\n  }\n}\n\n/* Sort the root nodes, least popular first. */\nstatic BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(\n    const HuffmanTree* v0, const HuffmanTree* v1) {\n  if (v0->total_count_ != v1->total_count_) {\n    return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);\n  }\n  return TO_BROTLI_BOOL(v0->index_right_or_value_ > v1->index_right_or_value_);\n}\n\n/* This function will create a Huffman tree.\n\n   The catch here is that the tree cannot be arbitrarily deep.\n   Brotli specifies a maximum depth of 15 bits for \"code trees\"\n   and 7 bits for \"code length code trees.\"\n\n   count_limit is the value that is to be faked as the minimum value\n   and this minimum value is raised until the tree matches the\n   maximum length requirement.\n\n   This algorithm is not of excellent performance for very long data blocks,\n   especially when population counts are longer than 2**tree_limit, but\n   we are not planning to use this with extremely long blocks.\n\n   See http://en.wikipedia.org/wiki/Huffman_coding */\nvoid BrotliCreateHuffmanTree(const uint32_t* data,\n                             const size_t length,\n                             const int tree_limit,\n                             HuffmanTree* tree,\n                             uint8_t* depth) {\n  uint32_t count_limit;\n  HuffmanTree sentinel;\n  InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1);\n  /* For block sizes below 64 kB, we never need to do a second iteration\n     of this loop. Probably all of our block sizes will be smaller than\n     that, so this loop is mostly of academic interest. If we actually\n     would need this, we would be better off with the Katajainen algorithm. */\n  for (count_limit = 1; ; count_limit *= 2) {\n    size_t n = 0;\n    size_t i;\n    size_t j;\n    size_t k;\n    for (i = length; i != 0;) {\n      --i;\n      if (data[i]) {\n        const uint32_t count = BROTLI_MAX(uint32_t, data[i], count_limit);\n        InitHuffmanTree(&tree[n++], count, -1, (int16_t)i);\n      }\n    }\n\n    if (n == 1) {\n      depth[tree[0].index_right_or_value_] = 1;  /* Only one element. */\n      break;\n    }\n\n    SortHuffmanTreeItems(tree, n, SortHuffmanTree);\n\n    /* The nodes are:\n       [0, n): the sorted leaf nodes that we start with.\n       [n]: we add a sentinel here.\n       [n + 1, 2n): new parent nodes are added here, starting from\n                    (n+1). These are naturally in ascending order.\n       [2n]: we add a sentinel at the end as well.\n       There will be (2n+1) elements at the end. */\n    tree[n] = sentinel;\n    tree[n + 1] = sentinel;\n\n    i = 0;      /* Points to the next leaf node. */\n    j = n + 1;  /* Points to the next non-leaf node. */\n    for (k = n - 1; k != 0; --k) {\n      size_t left, right;\n      if (tree[i].total_count_ <= tree[j].total_count_) {\n        left = i;\n        ++i;\n      } else {\n        left = j;\n        ++j;\n      }\n      if (tree[i].total_count_ <= tree[j].total_count_) {\n        right = i;\n        ++i;\n      } else {\n        right = j;\n        ++j;\n      }\n\n      {\n        /* The sentinel node becomes the parent node. */\n        size_t j_end = 2 * n - k;\n        tree[j_end].total_count_ =\n            tree[left].total_count_ + tree[right].total_count_;\n        tree[j_end].index_left_ = (int16_t)left;\n        tree[j_end].index_right_or_value_ = (int16_t)right;\n\n        /* Add back the last sentinel node. */\n        tree[j_end + 1] = sentinel;\n      }\n    }\n    if (BrotliSetDepth((int)(2 * n - 1), &tree[0], depth, tree_limit)) {\n      /* We need to pack the Huffman tree in tree_limit bits. If this was not\n         successful, add fake entities to the lowest values and retry. */\n      break;\n    }\n  }\n}\n\nstatic void Reverse(uint8_t* v, size_t start, size_t end) {\n  --end;\n  while (start < end) {\n    uint8_t tmp = v[start];\n    v[start] = v[end];\n    v[end] = tmp;\n    ++start;\n    --end;\n  }\n}\n\nstatic void BrotliWriteHuffmanTreeRepetitions(\n    const uint8_t previous_value,\n    const uint8_t value,\n    size_t repetitions,\n    size_t* tree_size,\n    uint8_t* tree,\n    uint8_t* extra_bits_data) {\n  BROTLI_DCHECK(repetitions > 0);\n  if (previous_value != value) {\n    tree[*tree_size] = value;\n    extra_bits_data[*tree_size] = 0;\n    ++(*tree_size);\n    --repetitions;\n  }\n  if (repetitions == 7) {\n    tree[*tree_size] = value;\n    extra_bits_data[*tree_size] = 0;\n    ++(*tree_size);\n    --repetitions;\n  }\n  if (repetitions < 3) {\n    size_t i;\n    for (i = 0; i < repetitions; ++i) {\n      tree[*tree_size] = value;\n      extra_bits_data[*tree_size] = 0;\n      ++(*tree_size);\n    }\n  } else {\n    size_t start = *tree_size;\n    repetitions -= 3;\n    while (BROTLI_TRUE) {\n      tree[*tree_size] = BROTLI_REPEAT_PREVIOUS_CODE_LENGTH;\n      extra_bits_data[*tree_size] = repetitions & 0x3;\n      ++(*tree_size);\n      repetitions >>= 2;\n      if (repetitions == 0) {\n        break;\n      }\n      --repetitions;\n    }\n    Reverse(tree, start, *tree_size);\n    Reverse(extra_bits_data, start, *tree_size);\n  }\n}\n\nstatic void BrotliWriteHuffmanTreeRepetitionsZeros(\n    size_t repetitions,\n    size_t* tree_size,\n    uint8_t* tree,\n    uint8_t* extra_bits_data) {\n  if (repetitions == 11) {\n    tree[*tree_size] = 0;\n    extra_bits_data[*tree_size] = 0;\n    ++(*tree_size);\n    --repetitions;\n  }\n  if (repetitions < 3) {\n    size_t i;\n    for (i = 0; i < repetitions; ++i) {\n      tree[*tree_size] = 0;\n      extra_bits_data[*tree_size] = 0;\n      ++(*tree_size);\n    }\n  } else {\n    size_t start = *tree_size;\n    repetitions -= 3;\n    while (BROTLI_TRUE) {\n      tree[*tree_size] = BROTLI_REPEAT_ZERO_CODE_LENGTH;\n      extra_bits_data[*tree_size] = repetitions & 0x7;\n      ++(*tree_size);\n      repetitions >>= 3;\n      if (repetitions == 0) {\n        break;\n      }\n      --repetitions;\n    }\n    Reverse(tree, start, *tree_size);\n    Reverse(extra_bits_data, start, *tree_size);\n  }\n}\n\nvoid BrotliOptimizeHuffmanCountsForRle(size_t length, uint32_t* counts,\n                                       uint8_t* good_for_rle) {\n  size_t nonzero_count = 0;\n  size_t stride;\n  size_t limit;\n  size_t sum;\n  const size_t streak_limit = 1240;\n  /* Let's make the Huffman code more compatible with RLE encoding. */\n  size_t i;\n  for (i = 0; i < length; i++) {\n    if (counts[i]) {\n      ++nonzero_count;\n    }\n  }\n  if (nonzero_count < 16) {\n    return;\n  }\n  while (length != 0 && counts[length - 1] == 0) {\n    --length;\n  }\n  if (length == 0) {\n    return;  /* All zeros. */\n  }\n  /* Now counts[0..length - 1] does not have trailing zeros. */\n  {\n    size_t nonzeros = 0;\n    uint32_t smallest_nonzero = 1 << 30;\n    for (i = 0; i < length; ++i) {\n      if (counts[i] != 0) {\n        ++nonzeros;\n        if (smallest_nonzero > counts[i]) {\n          smallest_nonzero = counts[i];\n        }\n      }\n    }\n    if (nonzeros < 5) {\n      /* Small histogram will model it well. */\n      return;\n    }\n    if (smallest_nonzero < 4) {\n      size_t zeros = length - nonzeros;\n      if (zeros < 6) {\n        for (i = 1; i < length - 1; ++i) {\n          if (counts[i - 1] != 0 && counts[i] == 0 && counts[i + 1] != 0) {\n            counts[i] = 1;\n          }\n        }\n      }\n    }\n    if (nonzeros < 28) {\n      return;\n    }\n  }\n  /* 2) Let's mark all population counts that already can be encoded\n     with an RLE code. */\n  memset(good_for_rle, 0, length);\n  {\n    /* Let's not spoil any of the existing good RLE codes.\n       Mark any seq of 0's that is longer as 5 as a good_for_rle.\n       Mark any seq of non-0's that is longer as 7 as a good_for_rle. */\n    uint32_t symbol = counts[0];\n    size_t step = 0;\n    for (i = 0; i <= length; ++i) {\n      if (i == length || counts[i] != symbol) {\n        if ((symbol == 0 && step >= 5) ||\n            (symbol != 0 && step >= 7)) {\n          size_t k;\n          for (k = 0; k < step; ++k) {\n            good_for_rle[i - k - 1] = 1;\n          }\n        }\n        step = 1;\n        if (i != length) {\n          symbol = counts[i];\n        }\n      } else {\n        ++step;\n      }\n    }\n  }\n  /* 3) Let's replace those population counts that lead to more RLE codes.\n     Math here is in 24.8 fixed point representation. */\n  stride = 0;\n  limit = 256 * (counts[0] + counts[1] + counts[2]) / 3 + 420;\n  sum = 0;\n  for (i = 0; i <= length; ++i) {\n    if (i == length || good_for_rle[i] ||\n        (i != 0 && good_for_rle[i - 1]) ||\n        (256 * counts[i] - limit + streak_limit) >= 2 * streak_limit) {\n      if (stride >= 4 || (stride >= 3 && sum == 0)) {\n        size_t k;\n        /* The stride must end, collapse what we have, if we have enough (4). */\n        size_t count = (sum + stride / 2) / stride;\n        if (count == 0) {\n          count = 1;\n        }\n        if (sum == 0) {\n          /* Don't make an all zeros stride to be upgraded to ones. */\n          count = 0;\n        }\n        for (k = 0; k < stride; ++k) {\n          /* We don't want to change value at counts[i],\n             that is already belonging to the next stride. Thus - 1. */\n          counts[i - k - 1] = (uint32_t)count;\n        }\n      }\n      stride = 0;\n      sum = 0;\n      if (i < length - 2) {\n        /* All interesting strides have a count of at least 4, */\n        /* at least when non-zeros. */\n        limit = 256 * (counts[i] + counts[i + 1] + counts[i + 2]) / 3 + 420;\n      } else if (i < length) {\n        limit = 256 * counts[i];\n      } else {\n        limit = 0;\n      }\n    }\n    ++stride;\n    if (i != length) {\n      sum += counts[i];\n      if (stride >= 4) {\n        limit = (256 * sum + stride / 2) / stride;\n      }\n      if (stride == 4) {\n        limit += 120;\n      }\n    }\n  }\n}\n\nstatic void DecideOverRleUse(const uint8_t* depth, const size_t length,\n                             BROTLI_BOOL* use_rle_for_non_zero,\n                             BROTLI_BOOL* use_rle_for_zero) {\n  size_t total_reps_zero = 0;\n  size_t total_reps_non_zero = 0;\n  size_t count_reps_zero = 1;\n  size_t count_reps_non_zero = 1;\n  size_t i;\n  for (i = 0; i < length;) {\n    const uint8_t value = depth[i];\n    size_t reps = 1;\n    size_t k;\n    for (k = i + 1; k < length && depth[k] == value; ++k) {\n      ++reps;\n    }\n    if (reps >= 3 && value == 0) {\n      total_reps_zero += reps;\n      ++count_reps_zero;\n    }\n    if (reps >= 4 && value != 0) {\n      total_reps_non_zero += reps;\n      ++count_reps_non_zero;\n    }\n    i += reps;\n  }\n  *use_rle_for_non_zero =\n      TO_BROTLI_BOOL(total_reps_non_zero > count_reps_non_zero * 2);\n  *use_rle_for_zero = TO_BROTLI_BOOL(total_reps_zero > count_reps_zero * 2);\n}\n\nvoid BrotliWriteHuffmanTree(const uint8_t* depth,\n                            size_t length,\n                            size_t* tree_size,\n                            uint8_t* tree,\n                            uint8_t* extra_bits_data) {\n  uint8_t previous_value = BROTLI_INITIAL_REPEATED_CODE_LENGTH;\n  size_t i;\n  BROTLI_BOOL use_rle_for_non_zero = BROTLI_FALSE;\n  BROTLI_BOOL use_rle_for_zero = BROTLI_FALSE;\n\n  /* Throw away trailing zeros. */\n  size_t new_length = length;\n  for (i = 0; i < length; ++i) {\n    if (depth[length - i - 1] == 0) {\n      --new_length;\n    } else {\n      break;\n    }\n  }\n\n  /* First gather statistics on if it is a good idea to do RLE. */\n  if (length > 50) {\n    /* Find RLE coding for longer codes.\n       Shorter codes seem not to benefit from RLE. */\n    DecideOverRleUse(depth, new_length,\n                     &use_rle_for_non_zero, &use_rle_for_zero);\n  }\n\n  /* Actual RLE coding. */\n  for (i = 0; i < new_length;) {\n    const uint8_t value = depth[i];\n    size_t reps = 1;\n    if ((value != 0 && use_rle_for_non_zero) ||\n        (value == 0 && use_rle_for_zero)) {\n      size_t k;\n      for (k = i + 1; k < new_length && depth[k] == value; ++k) {\n        ++reps;\n      }\n    }\n    if (value == 0) {\n      BrotliWriteHuffmanTreeRepetitionsZeros(\n          reps, tree_size, tree, extra_bits_data);\n    } else {\n      BrotliWriteHuffmanTreeRepetitions(previous_value,\n                                        value, reps, tree_size,\n                                        tree, extra_bits_data);\n      previous_value = value;\n    }\n    i += reps;\n  }\n}\n\nstatic uint16_t BrotliReverseBits(size_t num_bits, uint16_t bits) {\n  static const size_t BROTLI_MODEL(\"small\") kLut[16] =\n  {  /* Pre-reversed 4-bit values. */\n    0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E,\n    0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F\n  };\n  size_t retval = kLut[bits & 0x0F];\n  size_t i;\n  for (i = 4; i < num_bits; i += 4) {\n    retval <<= 4;\n    bits = (uint16_t)(bits >> 4);\n    retval |= kLut[bits & 0x0F];\n  }\n  retval >>= ((0 - num_bits) & 0x03);\n  return (uint16_t)retval;\n}\n\n/* 0..15 are values for bits */\n#define MAX_HUFFMAN_BITS 16\n\nvoid BrotliConvertBitDepthsToSymbols(const uint8_t* depth,\n                                     size_t len,\n                                     uint16_t* bits) {\n  /* In Brotli, all bit depths are [1..15]\n     0 bit depth means that the symbol does not exist. */\n  uint16_t bl_count[MAX_HUFFMAN_BITS] = { 0 };\n  uint16_t next_code[MAX_HUFFMAN_BITS];\n  size_t i;\n  int code = 0;\n  for (i = 0; i < len; ++i) {\n    ++bl_count[depth[i]];\n  }\n  bl_count[0] = 0;\n  next_code[0] = 0;\n  for (i = 1; i < MAX_HUFFMAN_BITS; ++i) {\n    code = (code + bl_count[i - 1]) << 1;\n    next_code[i] = (uint16_t)code;\n  }\n  for (i = 0; i < len; ++i) {\n    if (depth[i]) {\n      bits[i] = BrotliReverseBits(depth[i], next_code[depth[i]]++);\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/entropy_encode.h",
    "content": "﻿/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Entropy encoding (Huffman) utilities. */\n\n#ifndef BROTLI_ENC_ENTROPY_ENCODE_H_\n#define BROTLI_ENC_ENTROPY_ENCODE_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* A node of a Huffman tree. */\ntypedef struct HuffmanTree {\n  uint32_t total_count_;\n  int16_t index_left_;\n  int16_t index_right_or_value_;\n} HuffmanTree;\n\nstatic BROTLI_INLINE void InitHuffmanTree(HuffmanTree* self, uint32_t count,\n    int16_t left, int16_t right) {\n  self->total_count_ = count;\n  self->index_left_ = left;\n  self->index_right_or_value_ = right;\n}\n\n/* Returns 1 is assignment of depths succeeded, otherwise 0. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliSetDepth(\n    int p, HuffmanTree* pool, uint8_t* depth, int max_depth);\n\n/* This function will create a Huffman tree.\n\n   The (data,length) contains the population counts.\n   The tree_limit is the maximum bit depth of the Huffman codes.\n\n   The depth contains the tree, i.e., how many bits are used for\n   the symbol.\n\n   The actual Huffman tree is constructed in the tree[] array, which has to\n   be at least 2 * length + 1 long.\n\n   See http://en.wikipedia.org/wiki/Huffman_coding */\nBROTLI_INTERNAL void BrotliCreateHuffmanTree(const uint32_t* data,\n                                             const size_t length,\n                                             const int tree_limit,\n                                             HuffmanTree* tree,\n                                             uint8_t* depth);\n\n/* Change the population counts in a way that the consequent\n   Huffman tree compression, especially its RLE-part will be more\n   likely to compress this data more efficiently.\n\n   length contains the size of the histogram.\n   counts contains the population counts.\n   good_for_rle is a buffer of at least length size */\nBROTLI_INTERNAL void BrotliOptimizeHuffmanCountsForRle(\n    size_t length, uint32_t* counts, uint8_t* good_for_rle);\n\n/* Write a Huffman tree from bit depths into the bit-stream representation\n   of a Huffman tree. The generated Huffman tree is to be compressed once\n   more using a Huffman tree */\nBROTLI_INTERNAL void BrotliWriteHuffmanTree(const uint8_t* depth,\n                                            size_t length,\n                                            size_t* tree_size,\n                                            uint8_t* tree,\n                                            uint8_t* extra_bits_data);\n\n/* Get the actual bit values for a tree of bit depths. */\nBROTLI_INTERNAL void BrotliConvertBitDepthsToSymbols(const uint8_t* depth,\n                                                     size_t len,\n                                                     uint16_t* bits);\n\nBROTLI_INTERNAL extern BROTLI_MODEL(\"small\") const size_t kBrotliShellGaps[6];\n/* Input size optimized Shell sort. */\ntypedef BROTLI_BOOL (*HuffmanTreeComparator)(\n    const HuffmanTree*, const HuffmanTree*);\nstatic BROTLI_INLINE void SortHuffmanTreeItems(HuffmanTree* items,\n    const size_t n, HuffmanTreeComparator comparator) {\n  if (n < 13) {\n    /* Insertion sort. */\n    size_t i;\n    for (i = 1; i < n; ++i) {\n      HuffmanTree tmp = items[i];\n      size_t k = i;\n      size_t j = i - 1;\n      while (comparator(&tmp, &items[j])) {\n        items[k] = items[j];\n        k = j;\n        if (!j--) break;\n      }\n      items[k] = tmp;\n    }\n    return;\n  } else {\n    /* Shell sort. */\n    int g = n < 57 ? 2 : 0;\n    for (; g < 6; ++g) {\n      size_t gap = kBrotliShellGaps[g];\n      size_t i;\n      for (i = gap; i < n; ++i) {\n        size_t j = i;\n        HuffmanTree tmp = items[i];\n        for (; j >= gap && comparator(&tmp, &items[j - gap]); j -= gap) {\n          items[j] = items[j - gap];\n        }\n        items[j] = tmp;\n      }\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENTROPY_ENCODE_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/entropy_encode_static.h",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Static entropy codes used for faster meta-block encoding. */\n\n#ifndef BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_\n#define BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic const BROTLI_MODEL(\"small\") uint8_t kCodeLengthDepth[18] = {\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 0, 4, 4,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nuint8_t kStaticCommandCodeDepth[BROTLI_NUM_COMMAND_SYMBOLS] = {\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nuint8_t kStaticDistanceCodeDepth[64] = {\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n};\n\n/* GENERATED CODE START */\nstatic const BROTLI_MODEL(\"small\")\nuint32_t kCodeLengthBits[18] = {\n  0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 15, 31, 0, 11, 7,\n};\n\nstatic BROTLI_INLINE void StoreStaticCodeLengthCode(\n    size_t* storage_ix, uint8_t* storage) {\n  BrotliWriteBits(\n      40, BROTLI_MAKE_UINT64_T(0x0000FFu, 0x55555554u), storage_ix, storage);\n}\n\nstatic const BROTLI_MODEL(\"small\")\nuint64_t kZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = {\n  0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x00000017, 0x00000027,\n  0x00000037, 0x00000047, 0x00000057, 0x00000067, 0x00000077, 0x00000770,\n  0x00000b87, 0x00001387, 0x00001b87, 0x00002387, 0x00002b87, 0x00003387,\n  0x00003b87, 0x00000397, 0x00000b97, 0x00001397, 0x00001b97, 0x00002397,\n  0x00002b97, 0x00003397, 0x00003b97, 0x000003a7, 0x00000ba7, 0x000013a7,\n  0x00001ba7, 0x000023a7, 0x00002ba7, 0x000033a7, 0x00003ba7, 0x000003b7,\n  0x00000bb7, 0x000013b7, 0x00001bb7, 0x000023b7, 0x00002bb7, 0x000033b7,\n  0x00003bb7, 0x000003c7, 0x00000bc7, 0x000013c7, 0x00001bc7, 0x000023c7,\n  0x00002bc7, 0x000033c7, 0x00003bc7, 0x000003d7, 0x00000bd7, 0x000013d7,\n  0x00001bd7, 0x000023d7, 0x00002bd7, 0x000033d7, 0x00003bd7, 0x000003e7,\n  0x00000be7, 0x000013e7, 0x00001be7, 0x000023e7, 0x00002be7, 0x000033e7,\n  0x00003be7, 0x000003f7, 0x00000bf7, 0x000013f7, 0x00001bf7, 0x000023f7,\n  0x00002bf7, 0x000033f7, 0x00003bf7, 0x0001c387, 0x0005c387, 0x0009c387,\n  0x000dc387, 0x0011c387, 0x0015c387, 0x0019c387, 0x001dc387, 0x0001cb87,\n  0x0005cb87, 0x0009cb87, 0x000dcb87, 0x0011cb87, 0x0015cb87, 0x0019cb87,\n  0x001dcb87, 0x0001d387, 0x0005d387, 0x0009d387, 0x000dd387, 0x0011d387,\n  0x0015d387, 0x0019d387, 0x001dd387, 0x0001db87, 0x0005db87, 0x0009db87,\n  0x000ddb87, 0x0011db87, 0x0015db87, 0x0019db87, 0x001ddb87, 0x0001e387,\n  0x0005e387, 0x0009e387, 0x000de387, 0x0011e387, 0x0015e387, 0x0019e387,\n  0x001de387, 0x0001eb87, 0x0005eb87, 0x0009eb87, 0x000deb87, 0x0011eb87,\n  0x0015eb87, 0x0019eb87, 0x001deb87, 0x0001f387, 0x0005f387, 0x0009f387,\n  0x000df387, 0x0011f387, 0x0015f387, 0x0019f387, 0x001df387, 0x0001fb87,\n  0x0005fb87, 0x0009fb87, 0x000dfb87, 0x0011fb87, 0x0015fb87, 0x0019fb87,\n  0x001dfb87, 0x0001c397, 0x0005c397, 0x0009c397, 0x000dc397, 0x0011c397,\n  0x0015c397, 0x0019c397, 0x001dc397, 0x0001cb97, 0x0005cb97, 0x0009cb97,\n  0x000dcb97, 0x0011cb97, 0x0015cb97, 0x0019cb97, 0x001dcb97, 0x0001d397,\n  0x0005d397, 0x0009d397, 0x000dd397, 0x0011d397, 0x0015d397, 0x0019d397,\n  0x001dd397, 0x0001db97, 0x0005db97, 0x0009db97, 0x000ddb97, 0x0011db97,\n  0x0015db97, 0x0019db97, 0x001ddb97, 0x0001e397, 0x0005e397, 0x0009e397,\n  0x000de397, 0x0011e397, 0x0015e397, 0x0019e397, 0x001de397, 0x0001eb97,\n  0x0005eb97, 0x0009eb97, 0x000deb97, 0x0011eb97, 0x0015eb97, 0x0019eb97,\n  0x001deb97, 0x0001f397, 0x0005f397, 0x0009f397, 0x000df397, 0x0011f397,\n  0x0015f397, 0x0019f397, 0x001df397, 0x0001fb97, 0x0005fb97, 0x0009fb97,\n  0x000dfb97, 0x0011fb97, 0x0015fb97, 0x0019fb97, 0x001dfb97, 0x0001c3a7,\n  0x0005c3a7, 0x0009c3a7, 0x000dc3a7, 0x0011c3a7, 0x0015c3a7, 0x0019c3a7,\n  0x001dc3a7, 0x0001cba7, 0x0005cba7, 0x0009cba7, 0x000dcba7, 0x0011cba7,\n  0x0015cba7, 0x0019cba7, 0x001dcba7, 0x0001d3a7, 0x0005d3a7, 0x0009d3a7,\n  0x000dd3a7, 0x0011d3a7, 0x0015d3a7, 0x0019d3a7, 0x001dd3a7, 0x0001dba7,\n  0x0005dba7, 0x0009dba7, 0x000ddba7, 0x0011dba7, 0x0015dba7, 0x0019dba7,\n  0x001ddba7, 0x0001e3a7, 0x0005e3a7, 0x0009e3a7, 0x000de3a7, 0x0011e3a7,\n  0x0015e3a7, 0x0019e3a7, 0x001de3a7, 0x0001eba7, 0x0005eba7, 0x0009eba7,\n  0x000deba7, 0x0011eba7, 0x0015eba7, 0x0019eba7, 0x001deba7, 0x0001f3a7,\n  0x0005f3a7, 0x0009f3a7, 0x000df3a7, 0x0011f3a7, 0x0015f3a7, 0x0019f3a7,\n  0x001df3a7, 0x0001fba7, 0x0005fba7, 0x0009fba7, 0x000dfba7, 0x0011fba7,\n  0x0015fba7, 0x0019fba7, 0x001dfba7, 0x0001c3b7, 0x0005c3b7, 0x0009c3b7,\n  0x000dc3b7, 0x0011c3b7, 0x0015c3b7, 0x0019c3b7, 0x001dc3b7, 0x0001cbb7,\n  0x0005cbb7, 0x0009cbb7, 0x000dcbb7, 0x0011cbb7, 0x0015cbb7, 0x0019cbb7,\n  0x001dcbb7, 0x0001d3b7, 0x0005d3b7, 0x0009d3b7, 0x000dd3b7, 0x0011d3b7,\n  0x0015d3b7, 0x0019d3b7, 0x001dd3b7, 0x0001dbb7, 0x0005dbb7, 0x0009dbb7,\n  0x000ddbb7, 0x0011dbb7, 0x0015dbb7, 0x0019dbb7, 0x001ddbb7, 0x0001e3b7,\n  0x0005e3b7, 0x0009e3b7, 0x000de3b7, 0x0011e3b7, 0x0015e3b7, 0x0019e3b7,\n  0x001de3b7, 0x0001ebb7, 0x0005ebb7, 0x0009ebb7, 0x000debb7, 0x0011ebb7,\n  0x0015ebb7, 0x0019ebb7, 0x001debb7, 0x0001f3b7, 0x0005f3b7, 0x0009f3b7,\n  0x000df3b7, 0x0011f3b7, 0x0015f3b7, 0x0019f3b7, 0x001df3b7, 0x0001fbb7,\n  0x0005fbb7, 0x0009fbb7, 0x000dfbb7, 0x0011fbb7, 0x0015fbb7, 0x0019fbb7,\n  0x001dfbb7, 0x0001c3c7, 0x0005c3c7, 0x0009c3c7, 0x000dc3c7, 0x0011c3c7,\n  0x0015c3c7, 0x0019c3c7, 0x001dc3c7, 0x0001cbc7, 0x0005cbc7, 0x0009cbc7,\n  0x000dcbc7, 0x0011cbc7, 0x0015cbc7, 0x0019cbc7, 0x001dcbc7, 0x0001d3c7,\n  0x0005d3c7, 0x0009d3c7, 0x000dd3c7, 0x0011d3c7, 0x0015d3c7, 0x0019d3c7,\n  0x001dd3c7, 0x0001dbc7, 0x0005dbc7, 0x0009dbc7, 0x000ddbc7, 0x0011dbc7,\n  0x0015dbc7, 0x0019dbc7, 0x001ddbc7, 0x0001e3c7, 0x0005e3c7, 0x0009e3c7,\n  0x000de3c7, 0x0011e3c7, 0x0015e3c7, 0x0019e3c7, 0x001de3c7, 0x0001ebc7,\n  0x0005ebc7, 0x0009ebc7, 0x000debc7, 0x0011ebc7, 0x0015ebc7, 0x0019ebc7,\n  0x001debc7, 0x0001f3c7, 0x0005f3c7, 0x0009f3c7, 0x000df3c7, 0x0011f3c7,\n  0x0015f3c7, 0x0019f3c7, 0x001df3c7, 0x0001fbc7, 0x0005fbc7, 0x0009fbc7,\n  0x000dfbc7, 0x0011fbc7, 0x0015fbc7, 0x0019fbc7, 0x001dfbc7, 0x0001c3d7,\n  0x0005c3d7, 0x0009c3d7, 0x000dc3d7, 0x0011c3d7, 0x0015c3d7, 0x0019c3d7,\n  0x001dc3d7, 0x0001cbd7, 0x0005cbd7, 0x0009cbd7, 0x000dcbd7, 0x0011cbd7,\n  0x0015cbd7, 0x0019cbd7, 0x001dcbd7, 0x0001d3d7, 0x0005d3d7, 0x0009d3d7,\n  0x000dd3d7, 0x0011d3d7, 0x0015d3d7, 0x0019d3d7, 0x001dd3d7, 0x0001dbd7,\n  0x0005dbd7, 0x0009dbd7, 0x000ddbd7, 0x0011dbd7, 0x0015dbd7, 0x0019dbd7,\n  0x001ddbd7, 0x0001e3d7, 0x0005e3d7, 0x0009e3d7, 0x000de3d7, 0x0011e3d7,\n  0x0015e3d7, 0x0019e3d7, 0x001de3d7, 0x0001ebd7, 0x0005ebd7, 0x0009ebd7,\n  0x000debd7, 0x0011ebd7, 0x0015ebd7, 0x0019ebd7, 0x001debd7, 0x0001f3d7,\n  0x0005f3d7, 0x0009f3d7, 0x000df3d7, 0x0011f3d7, 0x0015f3d7, 0x0019f3d7,\n  0x001df3d7, 0x0001fbd7, 0x0005fbd7, 0x0009fbd7, 0x000dfbd7, 0x0011fbd7,\n  0x0015fbd7, 0x0019fbd7, 0x001dfbd7, 0x0001c3e7, 0x0005c3e7, 0x0009c3e7,\n  0x000dc3e7, 0x0011c3e7, 0x0015c3e7, 0x0019c3e7, 0x001dc3e7, 0x0001cbe7,\n  0x0005cbe7, 0x0009cbe7, 0x000dcbe7, 0x0011cbe7, 0x0015cbe7, 0x0019cbe7,\n  0x001dcbe7, 0x0001d3e7, 0x0005d3e7, 0x0009d3e7, 0x000dd3e7, 0x0011d3e7,\n  0x0015d3e7, 0x0019d3e7, 0x001dd3e7, 0x0001dbe7, 0x0005dbe7, 0x0009dbe7,\n  0x000ddbe7, 0x0011dbe7, 0x0015dbe7, 0x0019dbe7, 0x001ddbe7, 0x0001e3e7,\n  0x0005e3e7, 0x0009e3e7, 0x000de3e7, 0x0011e3e7, 0x0015e3e7, 0x0019e3e7,\n  0x001de3e7, 0x0001ebe7, 0x0005ebe7, 0x0009ebe7, 0x000debe7, 0x0011ebe7,\n  0x0015ebe7, 0x0019ebe7, 0x001debe7, 0x0001f3e7, 0x0005f3e7, 0x0009f3e7,\n  0x000df3e7, 0x0011f3e7, 0x0015f3e7, 0x0019f3e7, 0x001df3e7, 0x0001fbe7,\n  0x0005fbe7, 0x0009fbe7, 0x000dfbe7, 0x0011fbe7, 0x0015fbe7, 0x0019fbe7,\n  0x001dfbe7, 0x0001c3f7, 0x0005c3f7, 0x0009c3f7, 0x000dc3f7, 0x0011c3f7,\n  0x0015c3f7, 0x0019c3f7, 0x001dc3f7, 0x0001cbf7, 0x0005cbf7, 0x0009cbf7,\n  0x000dcbf7, 0x0011cbf7, 0x0015cbf7, 0x0019cbf7, 0x001dcbf7, 0x0001d3f7,\n  0x0005d3f7, 0x0009d3f7, 0x000dd3f7, 0x0011d3f7, 0x0015d3f7, 0x0019d3f7,\n  0x001dd3f7, 0x0001dbf7, 0x0005dbf7, 0x0009dbf7, 0x000ddbf7, 0x0011dbf7,\n  0x0015dbf7, 0x0019dbf7, 0x001ddbf7, 0x0001e3f7, 0x0005e3f7, 0x0009e3f7,\n  0x000de3f7, 0x0011e3f7, 0x0015e3f7, 0x0019e3f7, 0x001de3f7, 0x0001ebf7,\n  0x0005ebf7, 0x0009ebf7, 0x000debf7, 0x0011ebf7, 0x0015ebf7, 0x0019ebf7,\n  0x001debf7, 0x0001f3f7, 0x0005f3f7, 0x0009f3f7, 0x000df3f7, 0x0011f3f7,\n  0x0015f3f7, 0x0019f3f7, 0x001df3f7, 0x0001fbf7, 0x0005fbf7, 0x0009fbf7,\n  0x000dfbf7, 0x0011fbf7, 0x0015fbf7, 0x0019fbf7, 0x001dfbf7, 0x00e1c387,\n  0x02e1c387, 0x04e1c387, 0x06e1c387, 0x08e1c387, 0x0ae1c387, 0x0ce1c387,\n  0x0ee1c387, 0x00e5c387, 0x02e5c387, 0x04e5c387, 0x06e5c387, 0x08e5c387,\n  0x0ae5c387, 0x0ce5c387, 0x0ee5c387, 0x00e9c387, 0x02e9c387, 0x04e9c387,\n  0x06e9c387, 0x08e9c387, 0x0ae9c387, 0x0ce9c387, 0x0ee9c387, 0x00edc387,\n  0x02edc387, 0x04edc387, 0x06edc387, 0x08edc387, 0x0aedc387, 0x0cedc387,\n  0x0eedc387, 0x00f1c387, 0x02f1c387, 0x04f1c387, 0x06f1c387, 0x08f1c387,\n  0x0af1c387, 0x0cf1c387, 0x0ef1c387, 0x00f5c387, 0x02f5c387, 0x04f5c387,\n  0x06f5c387, 0x08f5c387, 0x0af5c387, 0x0cf5c387, 0x0ef5c387, 0x00f9c387,\n  0x02f9c387, 0x04f9c387, 0x06f9c387, 0x08f9c387, 0x0af9c387, 0x0cf9c387,\n  0x0ef9c387, 0x00fdc387, 0x02fdc387, 0x04fdc387, 0x06fdc387, 0x08fdc387,\n  0x0afdc387, 0x0cfdc387, 0x0efdc387, 0x00e1cb87, 0x02e1cb87, 0x04e1cb87,\n  0x06e1cb87, 0x08e1cb87, 0x0ae1cb87, 0x0ce1cb87, 0x0ee1cb87, 0x00e5cb87,\n  0x02e5cb87, 0x04e5cb87, 0x06e5cb87, 0x08e5cb87, 0x0ae5cb87, 0x0ce5cb87,\n  0x0ee5cb87, 0x00e9cb87, 0x02e9cb87, 0x04e9cb87, 0x06e9cb87, 0x08e9cb87,\n  0x0ae9cb87, 0x0ce9cb87, 0x0ee9cb87, 0x00edcb87, 0x02edcb87, 0x04edcb87,\n  0x06edcb87, 0x08edcb87, 0x0aedcb87, 0x0cedcb87, 0x0eedcb87, 0x00f1cb87,\n  0x02f1cb87, 0x04f1cb87, 0x06f1cb87, 0x08f1cb87, 0x0af1cb87, 0x0cf1cb87,\n  0x0ef1cb87, 0x00f5cb87, 0x02f5cb87, 0x04f5cb87, 0x06f5cb87, 0x08f5cb87,\n  0x0af5cb87, 0x0cf5cb87, 0x0ef5cb87, 0x00f9cb87, 0x02f9cb87, 0x04f9cb87,\n  0x06f9cb87, 0x08f9cb87,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nuint32_t kZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = {\n   0,  4,  8,  7,  7,  7,  7,  7,  7,  7,  7, 11, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nuint64_t kNonZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = {\n  0x0000000b, 0x0000001b, 0x0000002b, 0x0000003b, 0x000002cb, 0x000006cb,\n  0x00000acb, 0x00000ecb, 0x000002db, 0x000006db, 0x00000adb, 0x00000edb,\n  0x000002eb, 0x000006eb, 0x00000aeb, 0x00000eeb, 0x000002fb, 0x000006fb,\n  0x00000afb, 0x00000efb, 0x0000b2cb, 0x0001b2cb, 0x0002b2cb, 0x0003b2cb,\n  0x0000b6cb, 0x0001b6cb, 0x0002b6cb, 0x0003b6cb, 0x0000bacb, 0x0001bacb,\n  0x0002bacb, 0x0003bacb, 0x0000becb, 0x0001becb, 0x0002becb, 0x0003becb,\n  0x0000b2db, 0x0001b2db, 0x0002b2db, 0x0003b2db, 0x0000b6db, 0x0001b6db,\n  0x0002b6db, 0x0003b6db, 0x0000badb, 0x0001badb, 0x0002badb, 0x0003badb,\n  0x0000bedb, 0x0001bedb, 0x0002bedb, 0x0003bedb, 0x0000b2eb, 0x0001b2eb,\n  0x0002b2eb, 0x0003b2eb, 0x0000b6eb, 0x0001b6eb, 0x0002b6eb, 0x0003b6eb,\n  0x0000baeb, 0x0001baeb, 0x0002baeb, 0x0003baeb, 0x0000beeb, 0x0001beeb,\n  0x0002beeb, 0x0003beeb, 0x0000b2fb, 0x0001b2fb, 0x0002b2fb, 0x0003b2fb,\n  0x0000b6fb, 0x0001b6fb, 0x0002b6fb, 0x0003b6fb, 0x0000bafb, 0x0001bafb,\n  0x0002bafb, 0x0003bafb, 0x0000befb, 0x0001befb, 0x0002befb, 0x0003befb,\n  0x002cb2cb, 0x006cb2cb, 0x00acb2cb, 0x00ecb2cb, 0x002db2cb, 0x006db2cb,\n  0x00adb2cb, 0x00edb2cb, 0x002eb2cb, 0x006eb2cb, 0x00aeb2cb, 0x00eeb2cb,\n  0x002fb2cb, 0x006fb2cb, 0x00afb2cb, 0x00efb2cb, 0x002cb6cb, 0x006cb6cb,\n  0x00acb6cb, 0x00ecb6cb, 0x002db6cb, 0x006db6cb, 0x00adb6cb, 0x00edb6cb,\n  0x002eb6cb, 0x006eb6cb, 0x00aeb6cb, 0x00eeb6cb, 0x002fb6cb, 0x006fb6cb,\n  0x00afb6cb, 0x00efb6cb, 0x002cbacb, 0x006cbacb, 0x00acbacb, 0x00ecbacb,\n  0x002dbacb, 0x006dbacb, 0x00adbacb, 0x00edbacb, 0x002ebacb, 0x006ebacb,\n  0x00aebacb, 0x00eebacb, 0x002fbacb, 0x006fbacb, 0x00afbacb, 0x00efbacb,\n  0x002cbecb, 0x006cbecb, 0x00acbecb, 0x00ecbecb, 0x002dbecb, 0x006dbecb,\n  0x00adbecb, 0x00edbecb, 0x002ebecb, 0x006ebecb, 0x00aebecb, 0x00eebecb,\n  0x002fbecb, 0x006fbecb, 0x00afbecb, 0x00efbecb, 0x002cb2db, 0x006cb2db,\n  0x00acb2db, 0x00ecb2db, 0x002db2db, 0x006db2db, 0x00adb2db, 0x00edb2db,\n  0x002eb2db, 0x006eb2db, 0x00aeb2db, 0x00eeb2db, 0x002fb2db, 0x006fb2db,\n  0x00afb2db, 0x00efb2db, 0x002cb6db, 0x006cb6db, 0x00acb6db, 0x00ecb6db,\n  0x002db6db, 0x006db6db, 0x00adb6db, 0x00edb6db, 0x002eb6db, 0x006eb6db,\n  0x00aeb6db, 0x00eeb6db, 0x002fb6db, 0x006fb6db, 0x00afb6db, 0x00efb6db,\n  0x002cbadb, 0x006cbadb, 0x00acbadb, 0x00ecbadb, 0x002dbadb, 0x006dbadb,\n  0x00adbadb, 0x00edbadb, 0x002ebadb, 0x006ebadb, 0x00aebadb, 0x00eebadb,\n  0x002fbadb, 0x006fbadb, 0x00afbadb, 0x00efbadb, 0x002cbedb, 0x006cbedb,\n  0x00acbedb, 0x00ecbedb, 0x002dbedb, 0x006dbedb, 0x00adbedb, 0x00edbedb,\n  0x002ebedb, 0x006ebedb, 0x00aebedb, 0x00eebedb, 0x002fbedb, 0x006fbedb,\n  0x00afbedb, 0x00efbedb, 0x002cb2eb, 0x006cb2eb, 0x00acb2eb, 0x00ecb2eb,\n  0x002db2eb, 0x006db2eb, 0x00adb2eb, 0x00edb2eb, 0x002eb2eb, 0x006eb2eb,\n  0x00aeb2eb, 0x00eeb2eb, 0x002fb2eb, 0x006fb2eb, 0x00afb2eb, 0x00efb2eb,\n  0x002cb6eb, 0x006cb6eb, 0x00acb6eb, 0x00ecb6eb, 0x002db6eb, 0x006db6eb,\n  0x00adb6eb, 0x00edb6eb, 0x002eb6eb, 0x006eb6eb, 0x00aeb6eb, 0x00eeb6eb,\n  0x002fb6eb, 0x006fb6eb, 0x00afb6eb, 0x00efb6eb, 0x002cbaeb, 0x006cbaeb,\n  0x00acbaeb, 0x00ecbaeb, 0x002dbaeb, 0x006dbaeb, 0x00adbaeb, 0x00edbaeb,\n  0x002ebaeb, 0x006ebaeb, 0x00aebaeb, 0x00eebaeb, 0x002fbaeb, 0x006fbaeb,\n  0x00afbaeb, 0x00efbaeb, 0x002cbeeb, 0x006cbeeb, 0x00acbeeb, 0x00ecbeeb,\n  0x002dbeeb, 0x006dbeeb, 0x00adbeeb, 0x00edbeeb, 0x002ebeeb, 0x006ebeeb,\n  0x00aebeeb, 0x00eebeeb, 0x002fbeeb, 0x006fbeeb, 0x00afbeeb, 0x00efbeeb,\n  0x002cb2fb, 0x006cb2fb, 0x00acb2fb, 0x00ecb2fb, 0x002db2fb, 0x006db2fb,\n  0x00adb2fb, 0x00edb2fb, 0x002eb2fb, 0x006eb2fb, 0x00aeb2fb, 0x00eeb2fb,\n  0x002fb2fb, 0x006fb2fb, 0x00afb2fb, 0x00efb2fb, 0x002cb6fb, 0x006cb6fb,\n  0x00acb6fb, 0x00ecb6fb, 0x002db6fb, 0x006db6fb, 0x00adb6fb, 0x00edb6fb,\n  0x002eb6fb, 0x006eb6fb, 0x00aeb6fb, 0x00eeb6fb, 0x002fb6fb, 0x006fb6fb,\n  0x00afb6fb, 0x00efb6fb, 0x002cbafb, 0x006cbafb, 0x00acbafb, 0x00ecbafb,\n  0x002dbafb, 0x006dbafb, 0x00adbafb, 0x00edbafb, 0x002ebafb, 0x006ebafb,\n  0x00aebafb, 0x00eebafb, 0x002fbafb, 0x006fbafb, 0x00afbafb, 0x00efbafb,\n  0x002cbefb, 0x006cbefb, 0x00acbefb, 0x00ecbefb, 0x002dbefb, 0x006dbefb,\n  0x00adbefb, 0x00edbefb, 0x002ebefb, 0x006ebefb, 0x00aebefb, 0x00eebefb,\n  0x002fbefb, 0x006fbefb, 0x00afbefb, 0x00efbefb, 0x0b2cb2cb, 0x1b2cb2cb,\n  0x2b2cb2cb, 0x3b2cb2cb, 0x0b6cb2cb, 0x1b6cb2cb, 0x2b6cb2cb, 0x3b6cb2cb,\n  0x0bacb2cb, 0x1bacb2cb, 0x2bacb2cb, 0x3bacb2cb, 0x0becb2cb, 0x1becb2cb,\n  0x2becb2cb, 0x3becb2cb, 0x0b2db2cb, 0x1b2db2cb, 0x2b2db2cb, 0x3b2db2cb,\n  0x0b6db2cb, 0x1b6db2cb, 0x2b6db2cb, 0x3b6db2cb, 0x0badb2cb, 0x1badb2cb,\n  0x2badb2cb, 0x3badb2cb, 0x0bedb2cb, 0x1bedb2cb, 0x2bedb2cb, 0x3bedb2cb,\n  0x0b2eb2cb, 0x1b2eb2cb, 0x2b2eb2cb, 0x3b2eb2cb, 0x0b6eb2cb, 0x1b6eb2cb,\n  0x2b6eb2cb, 0x3b6eb2cb, 0x0baeb2cb, 0x1baeb2cb, 0x2baeb2cb, 0x3baeb2cb,\n  0x0beeb2cb, 0x1beeb2cb, 0x2beeb2cb, 0x3beeb2cb, 0x0b2fb2cb, 0x1b2fb2cb,\n  0x2b2fb2cb, 0x3b2fb2cb, 0x0b6fb2cb, 0x1b6fb2cb, 0x2b6fb2cb, 0x3b6fb2cb,\n  0x0bafb2cb, 0x1bafb2cb, 0x2bafb2cb, 0x3bafb2cb, 0x0befb2cb, 0x1befb2cb,\n  0x2befb2cb, 0x3befb2cb, 0x0b2cb6cb, 0x1b2cb6cb, 0x2b2cb6cb, 0x3b2cb6cb,\n  0x0b6cb6cb, 0x1b6cb6cb, 0x2b6cb6cb, 0x3b6cb6cb, 0x0bacb6cb, 0x1bacb6cb,\n  0x2bacb6cb, 0x3bacb6cb, 0x0becb6cb, 0x1becb6cb, 0x2becb6cb, 0x3becb6cb,\n  0x0b2db6cb, 0x1b2db6cb, 0x2b2db6cb, 0x3b2db6cb, 0x0b6db6cb, 0x1b6db6cb,\n  0x2b6db6cb, 0x3b6db6cb, 0x0badb6cb, 0x1badb6cb, 0x2badb6cb, 0x3badb6cb,\n  0x0bedb6cb, 0x1bedb6cb, 0x2bedb6cb, 0x3bedb6cb, 0x0b2eb6cb, 0x1b2eb6cb,\n  0x2b2eb6cb, 0x3b2eb6cb, 0x0b6eb6cb, 0x1b6eb6cb, 0x2b6eb6cb, 0x3b6eb6cb,\n  0x0baeb6cb, 0x1baeb6cb, 0x2baeb6cb, 0x3baeb6cb, 0x0beeb6cb, 0x1beeb6cb,\n  0x2beeb6cb, 0x3beeb6cb, 0x0b2fb6cb, 0x1b2fb6cb, 0x2b2fb6cb, 0x3b2fb6cb,\n  0x0b6fb6cb, 0x1b6fb6cb, 0x2b6fb6cb, 0x3b6fb6cb, 0x0bafb6cb, 0x1bafb6cb,\n  0x2bafb6cb, 0x3bafb6cb, 0x0befb6cb, 0x1befb6cb, 0x2befb6cb, 0x3befb6cb,\n  0x0b2cbacb, 0x1b2cbacb, 0x2b2cbacb, 0x3b2cbacb, 0x0b6cbacb, 0x1b6cbacb,\n  0x2b6cbacb, 0x3b6cbacb, 0x0bacbacb, 0x1bacbacb, 0x2bacbacb, 0x3bacbacb,\n  0x0becbacb, 0x1becbacb, 0x2becbacb, 0x3becbacb, 0x0b2dbacb, 0x1b2dbacb,\n  0x2b2dbacb, 0x3b2dbacb, 0x0b6dbacb, 0x1b6dbacb, 0x2b6dbacb, 0x3b6dbacb,\n  0x0badbacb, 0x1badbacb, 0x2badbacb, 0x3badbacb, 0x0bedbacb, 0x1bedbacb,\n  0x2bedbacb, 0x3bedbacb, 0x0b2ebacb, 0x1b2ebacb, 0x2b2ebacb, 0x3b2ebacb,\n  0x0b6ebacb, 0x1b6ebacb, 0x2b6ebacb, 0x3b6ebacb, 0x0baebacb, 0x1baebacb,\n  0x2baebacb, 0x3baebacb, 0x0beebacb, 0x1beebacb, 0x2beebacb, 0x3beebacb,\n  0x0b2fbacb, 0x1b2fbacb, 0x2b2fbacb, 0x3b2fbacb, 0x0b6fbacb, 0x1b6fbacb,\n  0x2b6fbacb, 0x3b6fbacb, 0x0bafbacb, 0x1bafbacb, 0x2bafbacb, 0x3bafbacb,\n  0x0befbacb, 0x1befbacb, 0x2befbacb, 0x3befbacb, 0x0b2cbecb, 0x1b2cbecb,\n  0x2b2cbecb, 0x3b2cbecb, 0x0b6cbecb, 0x1b6cbecb, 0x2b6cbecb, 0x3b6cbecb,\n  0x0bacbecb, 0x1bacbecb, 0x2bacbecb, 0x3bacbecb, 0x0becbecb, 0x1becbecb,\n  0x2becbecb, 0x3becbecb, 0x0b2dbecb, 0x1b2dbecb, 0x2b2dbecb, 0x3b2dbecb,\n  0x0b6dbecb, 0x1b6dbecb, 0x2b6dbecb, 0x3b6dbecb, 0x0badbecb, 0x1badbecb,\n  0x2badbecb, 0x3badbecb, 0x0bedbecb, 0x1bedbecb, 0x2bedbecb, 0x3bedbecb,\n  0x0b2ebecb, 0x1b2ebecb, 0x2b2ebecb, 0x3b2ebecb, 0x0b6ebecb, 0x1b6ebecb,\n  0x2b6ebecb, 0x3b6ebecb, 0x0baebecb, 0x1baebecb, 0x2baebecb, 0x3baebecb,\n  0x0beebecb, 0x1beebecb, 0x2beebecb, 0x3beebecb, 0x0b2fbecb, 0x1b2fbecb,\n  0x2b2fbecb, 0x3b2fbecb, 0x0b6fbecb, 0x1b6fbecb, 0x2b6fbecb, 0x3b6fbecb,\n  0x0bafbecb, 0x1bafbecb, 0x2bafbecb, 0x3bafbecb, 0x0befbecb, 0x1befbecb,\n  0x2befbecb, 0x3befbecb, 0x0b2cb2db, 0x1b2cb2db, 0x2b2cb2db, 0x3b2cb2db,\n  0x0b6cb2db, 0x1b6cb2db, 0x2b6cb2db, 0x3b6cb2db, 0x0bacb2db, 0x1bacb2db,\n  0x2bacb2db, 0x3bacb2db, 0x0becb2db, 0x1becb2db, 0x2becb2db, 0x3becb2db,\n  0x0b2db2db, 0x1b2db2db, 0x2b2db2db, 0x3b2db2db, 0x0b6db2db, 0x1b6db2db,\n  0x2b6db2db, 0x3b6db2db, 0x0badb2db, 0x1badb2db, 0x2badb2db, 0x3badb2db,\n  0x0bedb2db, 0x1bedb2db, 0x2bedb2db, 0x3bedb2db, 0x0b2eb2db, 0x1b2eb2db,\n  0x2b2eb2db, 0x3b2eb2db, 0x0b6eb2db, 0x1b6eb2db, 0x2b6eb2db, 0x3b6eb2db,\n  0x0baeb2db, 0x1baeb2db, 0x2baeb2db, 0x3baeb2db, 0x0beeb2db, 0x1beeb2db,\n  0x2beeb2db, 0x3beeb2db, 0x0b2fb2db, 0x1b2fb2db, 0x2b2fb2db, 0x3b2fb2db,\n  0x0b6fb2db, 0x1b6fb2db, 0x2b6fb2db, 0x3b6fb2db, 0x0bafb2db, 0x1bafb2db,\n  0x2bafb2db, 0x3bafb2db, 0x0befb2db, 0x1befb2db, 0x2befb2db, 0x3befb2db,\n  0x0b2cb6db, 0x1b2cb6db, 0x2b2cb6db, 0x3b2cb6db, 0x0b6cb6db, 0x1b6cb6db,\n  0x2b6cb6db, 0x3b6cb6db, 0x0bacb6db, 0x1bacb6db, 0x2bacb6db, 0x3bacb6db,\n  0x0becb6db, 0x1becb6db, 0x2becb6db, 0x3becb6db, 0x0b2db6db, 0x1b2db6db,\n  0x2b2db6db, 0x3b2db6db, 0x0b6db6db, 0x1b6db6db, 0x2b6db6db, 0x3b6db6db,\n  0x0badb6db, 0x1badb6db, 0x2badb6db, 0x3badb6db, 0x0bedb6db, 0x1bedb6db,\n  0x2bedb6db, 0x3bedb6db, 0x0b2eb6db, 0x1b2eb6db, 0x2b2eb6db, 0x3b2eb6db,\n  0x0b6eb6db, 0x1b6eb6db, 0x2b6eb6db, 0x3b6eb6db, 0x0baeb6db, 0x1baeb6db,\n  0x2baeb6db, 0x3baeb6db,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nuint32_t kNonZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = {\n   6,  6,  6,  6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n  12, 12, 12, 12, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n};\n\nstatic const BROTLI_MODEL(\"small\")\nuint16_t kStaticCommandCodeBits[BROTLI_NUM_COMMAND_SYMBOLS] = {\n    0,  256,  128,  384,   64,  320,  192,  448,\n   32,  288,  160,  416,   96,  352,  224,  480,\n   16,  272,  144,  400,   80,  336,  208,  464,\n   48,  304,  176,  432,  112,  368,  240,  496,\n    8,  264,  136,  392,   72,  328,  200,  456,\n   40,  296,  168,  424,  104,  360,  232,  488,\n   24,  280,  152,  408,   88,  344,  216,  472,\n   56,  312,  184,  440,  120,  376,  248,  504,\n    4,  260,  132,  388,   68,  324,  196,  452,\n   36,  292,  164,  420,  100,  356,  228,  484,\n   20,  276,  148,  404,   84,  340,  212,  468,\n   52,  308,  180,  436,  116,  372,  244,  500,\n   12,  268,  140,  396,   76,  332,  204,  460,\n   44,  300,  172,  428,  108,  364,  236,  492,\n   28,  284,  156,  412,   92,  348,  220,  476,\n   60,  316,  188,  444,  124,  380,  252,  508,\n    2,  258,  130,  386,   66,  322,  194,  450,\n   34,  290,  162,  418,   98,  354,  226,  482,\n   18,  274,  146,  402,   82,  338,  210,  466,\n   50,  306,  178,  434,  114,  370,  242,  498,\n   10,  266,  138,  394,   74,  330,  202,  458,\n   42,  298,  170,  426,  106,  362,  234,  490,\n   26,  282,  154,  410,   90,  346,  218,  474,\n   58,  314,  186,  442,  122,  378,  250,  506,\n    6,  262,  134,  390,   70,  326,  198,  454,\n   38,  294,  166,  422,  102,  358,  230,  486,\n   22,  278,  150,  406,   86,  342,  214,  470,\n   54,  310,  182,  438,  118,  374,  246,  502,\n   14,  270,  142,  398,   78,  334,  206,  462,\n   46,  302,  174,  430,  110,  366,  238,  494,\n   30,  286,  158,  414,   94,  350,  222,  478,\n   62,  318,  190,  446,  126,  382,  254,  510,\n    1,  257,  129,  385,   65,  321,  193,  449,\n   33,  289,  161,  417,   97,  353,  225,  481,\n   17,  273,  145,  401,   81,  337,  209,  465,\n   49,  305,  177,  433,  113,  369,  241,  497,\n    9,  265,  137,  393,   73,  329,  201,  457,\n   41,  297,  169,  425,  105,  361,  233,  489,\n   25,  281,  153,  409,   89,  345,  217,  473,\n   57,  313,  185,  441,  121,  377,  249,  505,\n    5,  261,  133,  389,   69,  325,  197,  453,\n   37,  293,  165,  421,  101,  357,  229,  485,\n   21,  277,  149,  405,   85,  341,  213,  469,\n   53,  309,  181,  437,  117,  373,  245,  501,\n   13,  269,  141,  397,   77,  333,  205,  461,\n   45,  301,  173,  429,  109,  365,  237,  493,\n   29,  285,  157,  413,   93,  349,  221,  477,\n   61,  317,  189,  445,  125,  381,  253,  509,\n    3,  259,  131,  387,   67,  323,  195,  451,\n   35,  291,  163,  419,   99,  355,  227,  483,\n   19,  275,  147,  403,   83,  339,  211,  467,\n   51,  307,  179,  435,  115,  371,  243,  499,\n   11,  267,  139,  395,   75,  331,  203,  459,\n   43,  299,  171,  427,  107,  363,  235,  491,\n   27,  283,  155,  411,   91,  347,  219,  475,\n   59,  315,  187,  443,  123,  379,  251,  507,\n    7, 1031,  519, 1543,  263, 1287,  775, 1799,\n  135, 1159,  647, 1671,  391, 1415,  903, 1927,\n   71, 1095,  583, 1607,  327, 1351,  839, 1863,\n  199, 1223,  711, 1735,  455, 1479,  967, 1991,\n   39, 1063,  551, 1575,  295, 1319,  807, 1831,\n  167, 1191,  679, 1703,  423, 1447,  935, 1959,\n  103, 1127,  615, 1639,  359, 1383,  871, 1895,\n  231, 1255,  743, 1767,  487, 1511,  999, 2023,\n   23, 1047,  535, 1559,  279, 1303,  791, 1815,\n  151, 1175,  663, 1687,  407, 1431,  919, 1943,\n   87, 1111,  599, 1623,  343, 1367,  855, 1879,\n  215, 1239,  727, 1751,  471, 1495,  983, 2007,\n   55, 1079,  567, 1591,  311, 1335,  823, 1847,\n  183, 1207,  695, 1719,  439, 1463,  951, 1975,\n  119, 1143,  631, 1655,  375, 1399,  887, 1911,\n  247, 1271,  759, 1783,  503, 1527, 1015, 2039,\n   15, 1039,  527, 1551,  271, 1295,  783, 1807,\n  143, 1167,  655, 1679,  399, 1423,  911, 1935,\n   79, 1103,  591, 1615,  335, 1359,  847, 1871,\n  207, 1231,  719, 1743,  463, 1487,  975, 1999,\n   47, 1071,  559, 1583,  303, 1327,  815, 1839,\n  175, 1199,  687, 1711,  431, 1455,  943, 1967,\n  111, 1135,  623, 1647,  367, 1391,  879, 1903,\n  239, 1263,  751, 1775,  495, 1519, 1007, 2031,\n   31, 1055,  543, 1567,  287, 1311,  799, 1823,\n  159, 1183,  671, 1695,  415, 1439,  927, 1951,\n   95, 1119,  607, 1631,  351, 1375,  863, 1887,\n  223, 1247,  735, 1759,  479, 1503,  991, 2015,\n   63, 1087,  575, 1599,  319, 1343,  831, 1855,\n  191, 1215,  703, 1727,  447, 1471,  959, 1983,\n  127, 1151,  639, 1663,  383, 1407,  895, 1919,\n  255, 1279,  767, 1791,  511, 1535, 1023, 2047,\n};\n\nstatic BROTLI_INLINE void StoreStaticCommandHuffmanTree(\n    size_t* storage_ix, uint8_t* storage) {\n  BrotliWriteBits(\n      56, BROTLI_MAKE_UINT64_T(0x926244U, 0x16307003U), storage_ix, storage);\n  BrotliWriteBits(3, 0x00000000U, storage_ix, storage);\n}\n\nstatic const BROTLI_MODEL(\"small\") uint16_t kStaticDistanceCodeBits[64] = {\n   0, 32, 16, 48,  8, 40, 24, 56,  4, 36, 20, 52, 12, 44, 28, 60,\n   2, 34, 18, 50, 10, 42, 26, 58,  6, 38, 22, 54, 14, 46, 30, 62,\n   1, 33, 17, 49,  9, 41, 25, 57,  5, 37, 21, 53, 13, 45, 29, 61,\n   3, 35, 19, 51, 11, 43, 27, 59,  7, 39, 23, 55, 15, 47, 31, 63,\n};\n\nstatic BROTLI_INLINE void StoreStaticDistanceHuffmanTree(\n    size_t* storage_ix, uint8_t* storage) {\n  BrotliWriteBits(28, 0x0369DC03u, storage_ix, storage);\n}\n/* GENERATED CODE END */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/fast_log.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"fast_log.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* \", \".join([\"%.16ff\" % x for x in [0.0]+[log2(x) for x in range(1, 256)]]) */\nconst BROTLI_MODEL(\"small\") double kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE] = {\n  0.0000000000000000f, 0.0000000000000000f, 1.0000000000000000f,\n  1.5849625007211563f, 2.0000000000000000f, 2.3219280948873622f,\n  2.5849625007211561f, 2.8073549220576042f, 3.0000000000000000f,\n  3.1699250014423126f, 3.3219280948873626f, 3.4594316186372978f,\n  3.5849625007211565f, 3.7004397181410922f, 3.8073549220576037f,\n  3.9068905956085187f, 4.0000000000000000f, 4.0874628412503400f,\n  4.1699250014423122f, 4.2479275134435852f, 4.3219280948873626f,\n  4.3923174227787607f, 4.4594316186372973f, 4.5235619560570131f,\n  4.5849625007211570f, 4.6438561897747244f, 4.7004397181410926f,\n  4.7548875021634691f, 4.8073549220576037f, 4.8579809951275728f,\n  4.9068905956085187f, 4.9541963103868758f, 5.0000000000000000f,\n  5.0443941193584534f, 5.0874628412503400f, 5.1292830169449664f,\n  5.1699250014423122f, 5.2094533656289501f, 5.2479275134435852f,\n  5.2854022188622487f, 5.3219280948873626f, 5.3575520046180838f,\n  5.3923174227787607f, 5.4262647547020979f, 5.4594316186372973f,\n  5.4918530963296748f, 5.5235619560570131f, 5.5545888516776376f,\n  5.5849625007211570f, 5.6147098441152083f, 5.6438561897747244f,\n  5.6724253419714961f, 5.7004397181410926f, 5.7279204545631996f,\n  5.7548875021634691f, 5.7813597135246599f, 5.8073549220576046f,\n  5.8328900141647422f, 5.8579809951275719f, 5.8826430493618416f,\n  5.9068905956085187f, 5.9307373375628867f, 5.9541963103868758f,\n  5.9772799234999168f, 6.0000000000000000f, 6.0223678130284544f,\n  6.0443941193584534f, 6.0660891904577721f, 6.0874628412503400f,\n  6.1085244567781700f, 6.1292830169449672f, 6.1497471195046822f,\n  6.1699250014423122f, 6.1898245588800176f, 6.2094533656289510f,\n  6.2288186904958804f, 6.2479275134435861f, 6.2667865406949019f,\n  6.2854022188622487f, 6.3037807481771031f, 6.3219280948873617f,\n  6.3398500028846252f, 6.3575520046180847f, 6.3750394313469254f,\n  6.3923174227787598f, 6.4093909361377026f, 6.4262647547020979f,\n  6.4429434958487288f, 6.4594316186372982f, 6.4757334309663976f,\n  6.4918530963296748f, 6.5077946401986964f, 6.5235619560570131f,\n  6.5391588111080319f, 6.5545888516776376f, 6.5698556083309478f,\n  6.5849625007211561f, 6.5999128421871278f, 6.6147098441152092f,\n  6.6293566200796095f, 6.6438561897747253f, 6.6582114827517955f,\n  6.6724253419714952f, 6.6865005271832185f, 6.7004397181410917f,\n  6.7142455176661224f, 6.7279204545631988f, 6.7414669864011465f,\n  6.7548875021634691f, 6.7681843247769260f, 6.7813597135246599f,\n  6.7944158663501062f, 6.8073549220576037f, 6.8201789624151887f,\n  6.8328900141647422f, 6.8454900509443757f, 6.8579809951275719f,\n  6.8703647195834048f, 6.8826430493618416f, 6.8948177633079437f,\n  6.9068905956085187f, 6.9188632372745955f, 6.9307373375628867f,\n  6.9425145053392399f, 6.9541963103868758f, 6.9657842846620879f,\n  6.9772799234999168f, 6.9886846867721664f, 7.0000000000000000f,\n  7.0112272554232540f, 7.0223678130284544f, 7.0334230015374501f,\n  7.0443941193584534f, 7.0552824355011898f, 7.0660891904577721f,\n  7.0768155970508317f, 7.0874628412503400f, 7.0980320829605272f,\n  7.1085244567781700f, 7.1189410727235076f, 7.1292830169449664f,\n  7.1395513523987937f, 7.1497471195046822f, 7.1598713367783891f,\n  7.1699250014423130f, 7.1799090900149345f, 7.1898245588800176f,\n  7.1996723448363644f, 7.2094533656289492f, 7.2191685204621621f,\n  7.2288186904958804f, 7.2384047393250794f, 7.2479275134435861f,\n  7.2573878426926521f, 7.2667865406949019f, 7.2761244052742384f,\n  7.2854022188622487f, 7.2946207488916270f, 7.3037807481771031f,\n  7.3128829552843557f, 7.3219280948873617f, 7.3309168781146177f,\n  7.3398500028846243f, 7.3487281542310781f, 7.3575520046180847f,\n  7.3663222142458151f, 7.3750394313469254f, 7.3837042924740528f,\n  7.3923174227787607f, 7.4008794362821844f, 7.4093909361377026f,\n  7.4178525148858991f, 7.4262647547020979f, 7.4346282276367255f,\n  7.4429434958487288f, 7.4512111118323299f, 7.4594316186372973f,\n  7.4676055500829976f, 7.4757334309663976f, 7.4838157772642564f,\n  7.4918530963296748f, 7.4998458870832057f, 7.5077946401986964f,\n  7.5156998382840436f, 7.5235619560570131f, 7.5313814605163119f,\n  7.5391588111080319f, 7.5468944598876373f, 7.5545888516776376f,\n  7.5622424242210728f, 7.5698556083309478f, 7.5774288280357487f,\n  7.5849625007211561f, 7.5924570372680806f, 7.5999128421871278f,\n  7.6073303137496113f, 7.6147098441152075f, 7.6220518194563764f,\n  7.6293566200796095f, 7.6366246205436488f, 7.6438561897747244f,\n  7.6510516911789290f, 7.6582114827517955f, 7.6653359171851765f,\n  7.6724253419714952f, 7.6794800995054464f, 7.6865005271832185f,\n  7.6934869574993252f, 7.7004397181410926f, 7.7073591320808825f,\n  7.7142455176661224f, 7.7210991887071856f, 7.7279204545631996f,\n  7.7347096202258392f, 7.7414669864011465f, 7.7481928495894596f,\n  7.7548875021634691f, 7.7615512324444795f, 7.7681843247769260f,\n  7.7747870596011737f, 7.7813597135246608f, 7.7879025593914317f,\n  7.7944158663501062f, 7.8008998999203047f, 7.8073549220576037f,\n  7.8137811912170374f, 7.8201789624151887f, 7.8265484872909159f,\n  7.8328900141647422f, 7.8392037880969445f, 7.8454900509443757f,\n  7.8517490414160571f, 7.8579809951275719f, 7.8641861446542798f,\n  7.8703647195834048f, 7.8765169465650002f, 7.8826430493618425f,\n  7.8887432488982601f, 7.8948177633079446f, 7.9008668079807496f,\n  7.9068905956085187f, 7.9128893362299619f, 7.9188632372745955f,\n  7.9248125036057813f, 7.9307373375628867f, 7.9366379390025719f,\n  7.9425145053392399f, 7.9483672315846778f, 7.9541963103868758f,\n  7.9600019320680806f, 7.9657842846620870f, 7.9715435539507720f,\n  7.9772799234999168f, 7.9829935746943104f, 7.9886846867721664f,\n  7.9943534368588578f\n};\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/fast_log.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Utilities for fast computation of logarithms. */\n\n#ifndef BROTLI_ENC_FAST_LOG_H_\n#define BROTLI_ENC_FAST_LOG_H_\n\n#include <math.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE uint32_t Log2FloorNonZero(size_t n) {\n#if defined(BROTLI_BSR32)\n  return BROTLI_BSR32((uint32_t)n);\n#else\n  uint32_t result = 0;\n  while (n >>= 1) result++;\n  return result;\n#endif\n}\n\n#define BROTLI_LOG2_TABLE_SIZE 256\n\n/* A lookup table for small values of log2(int) to be used in entropy\n   computation. */\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\")\ndouble kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE];\n\n/* Visual Studio 2012 and Android API levels < 18 do not have the log2()\n * function defined, so we use log() and a multiplication instead. */\n#if !defined(BROTLI_HAVE_LOG2)\n#if ((defined(_MSC_VER) && _MSC_VER <= 1700) || \\\n     (defined(__ANDROID_API__) && __ANDROID_API__ < 18))\n#define BROTLI_HAVE_LOG2 0\n#else\n#define BROTLI_HAVE_LOG2 1\n#endif\n#endif\n\n#define LOG_2_INV 1.4426950408889634\n\n/* Faster logarithm for small integers, with the property of log2(0) == 0. */\nstatic BROTLI_INLINE double FastLog2(size_t v) {\n  if (v < BROTLI_LOG2_TABLE_SIZE) {\n    return kBrotliLog2Table[v];\n  }\n#if !(BROTLI_HAVE_LOG2)\n  return log((double)v) * LOG_2_INV;\n#else\n  return log2((double)v);\n#endif\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_FAST_LOG_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/find_match_length.h",
    "content": "﻿/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find maximal matching prefixes of strings. */\n\n#ifndef BROTLI_ENC_FIND_MATCH_LENGTH_H_\n#define BROTLI_ENC_FIND_MATCH_LENGTH_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Separate implementation for little-endian 64-bit targets, for speed. */\n#if defined(BROTLI_TZCNT64) && BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN\nstatic BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,\n                                                     const uint8_t* s2,\n                                                     size_t limit) {\n  const uint8_t *s1_orig = s1;\n  for (; limit >= 8; limit -= 8) {\n    uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^\n                 BROTLI_UNALIGNED_LOAD64LE(s1);\n    s2 += 8;\n    if (x != 0) {\n      size_t matching_bits = (size_t)BROTLI_TZCNT64(x);\n      return (size_t)(s1 - s1_orig) + (matching_bits >> 3);\n    }\n    s1 += 8;\n  }\n  while (limit && *s1 == *s2) {\n    limit--;\n    ++s2;\n    ++s1;\n  }\n  return (size_t)(s1 - s1_orig);\n}\n#else\nstatic BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,\n                                                     const uint8_t* s2,\n                                                     size_t limit) {\n  size_t matched = 0;\n  const uint8_t* s2_limit = s2 + limit;\n  const uint8_t* s2_ptr = s2;\n  /* Find out how long the match is. We loop over the data 32 bits at a\n     time until we find a 32-bit block that doesn't match; then we find\n     the first non-matching bit and use that to calculate the total\n     length of the match. */\n  while (s2_ptr <= s2_limit - 4 &&\n         BrotliUnalignedRead32(s2_ptr) ==\n         BrotliUnalignedRead32(s1 + matched)) {\n    s2_ptr += 4;\n    matched += 4;\n  }\n  while ((s2_ptr < s2_limit) && (s1[matched] == *s2_ptr)) {\n    ++s2_ptr;\n    ++matched;\n  }\n  return matched;\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_FIND_MATCH_LENGTH_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash.h",
    "content": "﻿/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data. */\n\n#ifndef BROTLI_ENC_HASH_H_\n#define BROTLI_ENC_HASH_H_\n\n#include \"../common/constants.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"compound_dictionary.h\"\n#include \"encoder_dict.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"hash_base.h\"\n#include \"matching_tag_mask.h\"\n#include \"memory.h\"\n#include \"params.h\"\n#include \"quality.h\"\n#include \"static_dict.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct {\n  /**\n   * Dynamically allocated areas; regular hasher uses one or two allocations;\n   * \"composite\" hasher uses up to 4 allocations.\n   */\n  void* extra[4];\n\n  /**\n   * False before the first invocation of HasherSetup (where \"extra\" memory)\n   * is allocated.\n   */\n  BROTLI_BOOL is_setup_;\n\n  size_t dict_num_lookups;\n  size_t dict_num_matches;\n\n  BrotliHasherParams params;\n\n  /**\n   * False if hasher needs to be \"prepared\" before use (before the first\n   * invocation of HasherSetup or after HasherReset). \"preparation\" is hasher\n   * data initialization (using input ringbuffer).\n   */\n  BROTLI_BOOL is_prepared_;\n} HasherCommon;\n\n#define score_t size_t\n\nstatic const uint32_t kCutoffTransformsCount = 10;\n/*   0,  12,   27,    23,    42,    63,    56,    48,    59,    64 */\n/* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */\nstatic const uint64_t kCutoffTransforms =\n    BROTLI_MAKE_UINT64_T(0x071B520A, 0xDA2D3200);\n\ntypedef struct HasherSearchResult {\n  size_t len;\n  size_t distance;\n  score_t score;\n  int len_code_delta; /* == len_code - len */\n} HasherSearchResult;\n\nstatic BROTLI_INLINE void PrepareDistanceCache(\n    int* BROTLI_RESTRICT distance_cache, const int num_distances) {\n  if (num_distances > 4) {\n    int last_distance = distance_cache[0];\n    distance_cache[4] = last_distance - 1;\n    distance_cache[5] = last_distance + 1;\n    distance_cache[6] = last_distance - 2;\n    distance_cache[7] = last_distance + 2;\n    distance_cache[8] = last_distance - 3;\n    distance_cache[9] = last_distance + 3;\n    if (num_distances > 10) {\n      int next_last_distance = distance_cache[1];\n      distance_cache[10] = next_last_distance - 1;\n      distance_cache[11] = next_last_distance + 1;\n      distance_cache[12] = next_last_distance - 2;\n      distance_cache[13] = next_last_distance + 2;\n      distance_cache[14] = next_last_distance - 3;\n      distance_cache[15] = next_last_distance + 3;\n    }\n  }\n}\n\n#define BROTLI_LITERAL_BYTE_SCORE 135\n#define BROTLI_DISTANCE_BIT_PENALTY 30\n/* Score must be positive after applying maximal penalty. */\n#define BROTLI_SCORE_BASE (BROTLI_DISTANCE_BIT_PENALTY * 8 * sizeof(size_t))\n\n/* Usually, we always choose the longest backward reference. This function\n   allows for the exception of that rule.\n\n   If we choose a backward reference that is further away, it will\n   usually be coded with more bits. We approximate this by assuming\n   log2(distance). If the distance can be expressed in terms of the\n   last four distances, we use some heuristic constants to estimate\n   the bits cost. For the first up to four literals we use the bit\n   cost of the literals from the literal cost model, after that we\n   use the average bit cost of the cost model.\n\n   This function is used to sometimes discard a longer backward reference\n   when it is not much longer and the bit cost for encoding it is more\n   than the saved literals.\n\n   backward_reference_offset MUST be positive. */\nstatic BROTLI_INLINE score_t BackwardReferenceScore(\n    size_t copy_length, size_t backward_reference_offset) {\n  return BROTLI_SCORE_BASE + BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length -\n      BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset);\n}\n\nstatic BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance(\n    size_t copy_length) {\n  return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length +\n      BROTLI_SCORE_BASE + 15;\n}\n\nstatic BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(\n    size_t distance_short_code) {\n  return (score_t)39 + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(\n    const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx,\n    const uint8_t* data, size_t max_length, size_t max_backward,\n    size_t max_distance, HasherSearchResult* out) {\n  size_t offset;\n  size_t matchlen;\n  size_t backward;\n  score_t score;\n  offset = dictionary->words->offsets_by_length[len] + len * word_idx;\n  if (len > max_length) {\n    return BROTLI_FALSE;\n  }\n\n  matchlen =\n      FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len);\n  if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) {\n    return BROTLI_FALSE;\n  }\n  {\n    size_t cut = len - matchlen;\n    size_t transform_id = (cut << 2) +\n        (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);\n    backward = max_backward + 1 + word_idx +\n        (transform_id << dictionary->words->size_bits_by_length[len]);\n  }\n  if (backward > max_distance) {\n    return BROTLI_FALSE;\n  }\n  score = BackwardReferenceScore(matchlen, backward);\n  if (score < out->score) {\n    return BROTLI_FALSE;\n  }\n  out->len = matchlen;\n  out->len_code_delta = (int)len - (int)matchlen;\n  out->distance = backward;\n  out->score = score;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void SearchInStaticDictionary(\n    const BrotliEncoderDictionary* dictionary,\n    HasherCommon* common, const uint8_t* data, size_t max_length,\n    size_t max_backward, size_t max_distance,\n    HasherSearchResult* out, BROTLI_BOOL shallow) {\n  size_t key;\n  size_t i;\n  if (common->dict_num_matches < (common->dict_num_lookups >> 7)) {\n    return;\n  }\n  key = Hash14(data) << 1;\n  for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {\n    common->dict_num_lookups++;\n    if (dictionary->hash_table_lengths[key] != 0) {\n      BROTLI_BOOL item_matches = TestStaticDictionaryItem(\n          dictionary, dictionary->hash_table_lengths[key],\n          dictionary->hash_table_words[key], data,\n          max_length, max_backward, max_distance, out);\n      if (item_matches) {\n        common->dict_num_matches++;\n      }\n    }\n  }\n}\n\ntypedef struct BackwardMatch {\n  uint32_t distance;\n  uint32_t length_and_code;\n} BackwardMatch;\n\nstatic BROTLI_INLINE void InitBackwardMatch(BackwardMatch* self,\n    size_t dist, size_t len) {\n  self->distance = (uint32_t)dist;\n  self->length_and_code = (uint32_t)(len << 5);\n}\n\nstatic BROTLI_INLINE void InitDictionaryBackwardMatch(BackwardMatch* self,\n    size_t dist, size_t len, size_t len_code) {\n  self->distance = (uint32_t)dist;\n  self->length_and_code =\n      (uint32_t)((len << 5) | (len == len_code ? 0 : len_code));\n}\n\nstatic BROTLI_INLINE size_t BackwardMatchLength(const BackwardMatch* self) {\n  return self->length_and_code >> 5;\n}\n\nstatic BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {\n  size_t code = self->length_and_code & 31;\n  return code ? code : BackwardMatchLength(self);\n}\n\n#define EXPAND_CAT(a, b) CAT(a, b)\n#define CAT(a, b) a ## b\n#define FN(X) EXPAND_CAT(X, HASHER())\n\n#define HASHER() H10\n#define BUCKET_BITS 17\n#define MAX_TREE_SEARCH_DEPTH 64\n#define MAX_TREE_COMP_LENGTH 128\n#include \"hash_to_binary_tree_inc.h\"  /* NOLINT(build/include) */\n#undef MAX_TREE_SEARCH_DEPTH\n#undef MAX_TREE_COMP_LENGTH\n#undef BUCKET_BITS\n#undef HASHER\n/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */\n#define MAX_NUM_MATCHES_H10 128\n\n/* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression\n   a little faster (0.5% - 1%) and it compresses 0.15% better on small text\n   and HTML inputs. */\n\n#define HASHER() H2\n#define BUCKET_BITS 16\n#define BUCKET_SWEEP_BITS 0\n#define HASH_LEN 5\n#define USE_DICTIONARY 1\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef BUCKET_SWEEP_BITS\n#undef USE_DICTIONARY\n#undef HASHER\n\n#define HASHER() H3\n#define BUCKET_SWEEP_BITS 1\n#define USE_DICTIONARY 0\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef USE_DICTIONARY\n#undef BUCKET_SWEEP_BITS\n#undef BUCKET_BITS\n#undef HASHER\n\n#define HASHER() H4\n#define BUCKET_BITS 17\n#define BUCKET_SWEEP_BITS 2\n#define USE_DICTIONARY 1\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef USE_DICTIONARY\n#undef HASH_LEN\n#undef BUCKET_SWEEP_BITS\n#undef BUCKET_BITS\n#undef HASHER\n\n#define HASHER() H5\n#include \"hash_longest_match_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n\n#define HASHER() H6\n#include \"hash_longest_match64_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n\n#if defined(BROTLI_MAX_SIMD_QUALITY)\n#define HASHER() H58\n#include \"hash_longest_match_simd_inc.h\" /* NOLINT(build/include) */\n#undef HASHER\n\n#define HASHER() H68\n#include \"hash_longest_match64_simd_inc.h\" /* NOLINT(build/include) */\n#undef HASHER\n#endif\n\n#define BUCKET_BITS 15\n\n#define NUM_LAST_DISTANCES_TO_CHECK 4\n#define NUM_BANKS 1\n#define BANK_BITS 16\n#define HASHER() H40\n#include \"hash_forgetful_chain_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n#undef NUM_LAST_DISTANCES_TO_CHECK\n\n#define NUM_LAST_DISTANCES_TO_CHECK 10\n#define HASHER() H41\n#include \"hash_forgetful_chain_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n#undef NUM_LAST_DISTANCES_TO_CHECK\n#undef NUM_BANKS\n#undef BANK_BITS\n\n#define NUM_LAST_DISTANCES_TO_CHECK 16\n#define NUM_BANKS 512\n#define BANK_BITS 9\n#define HASHER() H42\n#include \"hash_forgetful_chain_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n#undef NUM_LAST_DISTANCES_TO_CHECK\n#undef NUM_BANKS\n#undef BANK_BITS\n\n#undef BUCKET_BITS\n\n#define HASHER() H54\n#define BUCKET_BITS 20\n#define BUCKET_SWEEP_BITS 2\n#define HASH_LEN 7\n#define USE_DICTIONARY 0\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef USE_DICTIONARY\n#undef HASH_LEN\n#undef BUCKET_SWEEP_BITS\n#undef BUCKET_BITS\n#undef HASHER\n\n/* fast large window hashers */\n\n#define HASHER() HROLLING_FAST\n#define CHUNKLEN 32\n#define JUMP 4\n#define NUMBUCKETS 16777216\n#define MASK ((NUMBUCKETS * 64) - 1)\n#include \"hash_rolling_inc.h\"  /* NOLINT(build/include) */\n#undef JUMP\n#undef HASHER\n\n\n#define HASHER() HROLLING\n#define JUMP 1\n#include \"hash_rolling_inc.h\"  /* NOLINT(build/include) */\n#undef MASK\n#undef NUMBUCKETS\n#undef JUMP\n#undef CHUNKLEN\n#undef HASHER\n\n#define HASHER() H35\n#define HASHER_A H3\n#define HASHER_B HROLLING_FAST\n#include \"hash_composite_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER_A\n#undef HASHER_B\n#undef HASHER\n\n#define HASHER() H55\n#define HASHER_A H54\n#define HASHER_B HROLLING_FAST\n#include \"hash_composite_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER_A\n#undef HASHER_B\n#undef HASHER\n\n#define HASHER() H65\n#define HASHER_A H6\n#define HASHER_B HROLLING\n#include \"hash_composite_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER_A\n#undef HASHER_B\n#undef HASHER\n\n#undef FN\n#undef CAT\n#undef EXPAND_CAT\n\n#if defined(BROTLI_MAX_SIMD_QUALITY)\n#define FOR_SIMPLE_HASHERS(H) \\\n  H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54) H(58) H(68)\n#else\n#define FOR_SIMPLE_HASHERS(H) \\\n  H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)\n#endif\n#define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)\n#define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)\n#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)\n\ntypedef struct {\n  HasherCommon common;\n\n  union {\n#define MEMBER_(N) \\\n    H ## N _H ## N;\n    FOR_ALL_HASHERS(MEMBER_)\n#undef MEMBER_\n  } privat;\n} Hasher;\n\n/* MUST be invoked before any other method. */\nstatic BROTLI_INLINE void HasherInit(Hasher* hasher) {\n  hasher->common.is_setup_ = BROTLI_FALSE;\n  hasher->common.extra[0] = NULL;\n  hasher->common.extra[1] = NULL;\n  hasher->common.extra[2] = NULL;\n  hasher->common.extra[3] = NULL;\n}\n\nstatic BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {\n  if (hasher->common.extra[0] != NULL) BROTLI_FREE(m, hasher->common.extra[0]);\n  if (hasher->common.extra[1] != NULL) BROTLI_FREE(m, hasher->common.extra[1]);\n  if (hasher->common.extra[2] != NULL) BROTLI_FREE(m, hasher->common.extra[2]);\n  if (hasher->common.extra[3] != NULL) BROTLI_FREE(m, hasher->common.extra[3]);\n}\n\nstatic BROTLI_INLINE void HasherReset(Hasher* hasher) {\n  hasher->common.is_prepared_ = BROTLI_FALSE;\n}\n\nstatic BROTLI_INLINE void HasherSize(const BrotliEncoderParams* params,\n    BROTLI_BOOL one_shot, const size_t input_size, size_t* alloc_size) {\n  switch (params->hasher.type) {\n#define SIZE_(N)                                                           \\\n    case N:                                                                \\\n      HashMemAllocInBytesH ## N(params, one_shot, input_size, alloc_size); \\\n      break;\n    FOR_ALL_HASHERS(SIZE_)\n#undef SIZE_\n    default:\n      break;\n  }\n}\n\nstatic BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher,\n    BrotliEncoderParams* params, const uint8_t* data, size_t position,\n    size_t input_size, BROTLI_BOOL is_last) {\n  BROTLI_BOOL one_shot = (position == 0 && is_last);\n  if (!hasher->common.is_setup_) {\n    size_t alloc_size[4] = {0};\n    size_t i;\n    ChooseHasher(params, &params->hasher);\n    hasher->common.params = params->hasher;\n    hasher->common.dict_num_lookups = 0;\n    hasher->common.dict_num_matches = 0;\n    HasherSize(params, one_shot, input_size, alloc_size);\n    for (i = 0; i < 4; ++i) {\n      if (alloc_size[i] == 0) continue;\n      hasher->common.extra[i] = BROTLI_ALLOC(m, uint8_t, alloc_size[i]);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra[i])) return;\n    }\n    switch (hasher->common.params.type) {\n#define INITIALIZE_(N)                        \\\n      case N:                                 \\\n        InitializeH ## N(&hasher->common,     \\\n            &hasher->privat._H ## N, params); \\\n        break;\n      FOR_ALL_HASHERS(INITIALIZE_);\n#undef INITIALIZE_\n      default:\n        break;\n    }\n    HasherReset(hasher);\n    hasher->common.is_setup_ = BROTLI_TRUE;\n  }\n\n  if (!hasher->common.is_prepared_) {\n    switch (hasher->common.params.type) {\n#define PREPARE_(N)                      \\\n      case N:                            \\\n        PrepareH ## N(                   \\\n            &hasher->privat._H ## N,     \\\n            one_shot, input_size, data); \\\n        break;\n      FOR_ALL_HASHERS(PREPARE_)\n#undef PREPARE_\n      default: break;\n    }\n    hasher->common.is_prepared_ = BROTLI_TRUE;\n  }\n}\n\nstatic BROTLI_INLINE void InitOrStitchToPreviousBlock(\n    MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask,\n    BrotliEncoderParams* params, size_t position, size_t input_size,\n    BROTLI_BOOL is_last) {\n  HasherSetup(m, hasher, params, data, position, input_size, is_last);\n  if (BROTLI_IS_OOM(m)) return;\n  switch (hasher->common.params.type) {\n#define INIT_(N)                             \\\n    case N:                                  \\\n      StitchToPreviousBlockH ## N(           \\\n          &hasher->privat._H ## N,           \\\n          input_size, position, data, mask); \\\n    break;\n    FOR_ALL_HASHERS(INIT_)\n#undef INIT_\n    default: break;\n  }\n}\n\n/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget\n       to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */\nstatic BROTLI_INLINE void FindCompoundDictionaryMatch(\n    const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length, const size_t distance_offset,\n    const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {\n  const uint32_t source_size = self->source_size;\n  const size_t boundary = distance_offset - source_size;\n  const uint32_t hash_bits = self->hash_bits;\n  const uint32_t bucket_bits = self->bucket_bits;\n  const uint32_t slot_bits = self->slot_bits;\n\n  const uint32_t hash_shift = 64u - bucket_bits;\n  const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits);\n  const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);\n\n  const uint32_t* slot_offsets = (uint32_t*)(&self[1]);\n  const uint16_t* heads = (uint16_t*)(&slot_offsets[(size_t)1u << slot_bits]);\n  const uint32_t* items = (uint32_t*)(&heads[(size_t)1u << bucket_bits]);\n  const uint8_t* source = NULL;\n\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  const uint64_t h =\n      (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) *\n      kPreparedDictionaryHashMul64Long;\n  const uint32_t key = (uint32_t)(h >> hash_shift);\n  const uint32_t slot = key & slot_mask;\n  const uint32_t head = heads[key];\n  const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head];\n  uint32_t item = (head == 0xFFFF) ? 1 : 0;\n\n  const void* tail = (void*)&items[self->num_items];\n  if (self->magic == kPreparedDictionaryMagic) {\n    source = (const uint8_t*)tail;\n  } else {\n    /* kLeanPreparedDictionaryMagic */\n    source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);\n  }\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  for (i = 0; i < 4; ++i) {\n    const size_t distance = (size_t)distance_cache[i];\n    size_t offset;\n    size_t limit;\n    size_t len;\n    if (distance <= boundary || distance > distance_offset) continue;\n    offset = distance_offset - distance;\n    limit = source_size - offset;\n    limit = limit > max_length ? max_length : limit;\n    len = FindMatchLengthWithLimit(&source[offset], &data[cur_ix_masked],\n                                   limit);\n    if (len >= 2) {\n      score_t score = BackwardReferenceScoreUsingLastDistance(len);\n      if (best_score < score) {\n        if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n        if (best_score < score) {\n          best_score = score;\n          if (len > best_len) best_len = len;\n          out->len = len;\n          out->len_code_delta = 0;\n          out->distance = distance;\n          out->score = best_score;\n        }\n      }\n    }\n  }\n  /* we require matches of len >4, so increase best_len to 3, so we can compare\n   * 4 bytes all the time. */\n  if (best_len < 3) {\n    best_len = 3;\n  }\n  while (item == 0) {\n    size_t offset;\n    size_t distance;\n    size_t limit;\n    item = *chain;\n    chain++;\n    offset = item & 0x7FFFFFFF;\n    item &= 0x80000000;\n    distance = distance_offset - offset;\n    limit = source_size - offset;\n    limit = (limit > max_length) ? max_length : limit;\n    if (distance > max_distance) continue;\n    if (cur_ix_masked + best_len > ring_buffer_mask || best_len >= limit ||\n        /* compare 4 bytes ending at best_len + 1 */\n        BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=\n            BrotliUnalignedRead32(&source[offset + best_len - 3])) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&source[offset],\n                                                  &data[cur_ix_masked],\n                                                  limit);\n      if (len >= 4) {\n        score_t score = BackwardReferenceScore(len, distance);\n        if (best_score < score) {\n          best_score = score;\n          best_len = len;\n          out->len = best_len;\n          out->len_code_delta = 0;\n          out->distance = distance;\n          out->score = best_score;\n        }\n      }\n    }\n  }\n}\n\n/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget\n       to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */\nstatic BROTLI_INLINE size_t FindAllCompoundDictionaryMatches(\n    const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const size_t cur_ix, const size_t min_length,\n    const size_t max_length, const size_t distance_offset,\n    const size_t max_distance, BackwardMatch* matches, size_t match_limit) {\n  const uint32_t source_size = self->source_size;\n  const uint32_t hash_bits = self->hash_bits;\n  const uint32_t bucket_bits = self->bucket_bits;\n  const uint32_t slot_bits = self->slot_bits;\n\n  const uint32_t hash_shift = 64u - bucket_bits;\n  const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits);\n  const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);\n\n  const uint32_t* slot_offsets = (uint32_t*)(&self[1]);\n  const uint16_t* heads = (uint16_t*)(&slot_offsets[(size_t)1u << slot_bits]);\n  const uint32_t* items = (uint32_t*)(&heads[(size_t)1u << bucket_bits]);\n  const uint8_t* source = NULL;\n\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  size_t best_len = min_length;\n  const uint64_t h =\n      (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) *\n      kPreparedDictionaryHashMul64Long;\n  const uint32_t key = (uint32_t)(h >> hash_shift);\n  const uint32_t slot = key & slot_mask;\n  const uint32_t head = heads[key];\n  const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head];\n  uint32_t item = (head == 0xFFFF) ? 1 : 0;\n  size_t found = 0;\n\n  const void* tail = (void*)&items[self->num_items];\n  if (self->magic == kPreparedDictionaryMagic) {\n    source = (const uint8_t*)tail;\n  } else {\n    /* kLeanPreparedDictionaryMagic */\n    source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);\n  }\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  while (item == 0) {\n    size_t offset;\n    size_t distance;\n    size_t limit;\n    size_t len;\n    item = *chain;\n    chain++;\n    offset = item & 0x7FFFFFFF;\n    item &= 0x80000000;\n    distance = distance_offset - offset;\n    limit = source_size - offset;\n    limit = (limit > max_length) ? max_length : limit;\n    if (distance > max_distance) continue;\n    if (cur_ix_masked + best_len > ring_buffer_mask ||\n        best_len >= limit ||\n        data[cur_ix_masked + best_len] != source[offset + best_len]) {\n      continue;\n    }\n    len = FindMatchLengthWithLimit(\n        &source[offset], &data[cur_ix_masked], limit);\n    if (len > best_len) {\n      best_len = len;\n      InitBackwardMatch(matches++, distance, len);\n      found++;\n      if (found == match_limit) break;\n    }\n  }\n  return found;\n}\n\nstatic BROTLI_INLINE void LookupCompoundDictionaryMatch(\n    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length,\n    const size_t max_ring_buffer_distance, const size_t max_distance,\n    HasherSearchResult* sr) {\n  size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1;\n  size_t d;\n  for (d = 0; d < addon->num_chunks; ++d) {\n    /* Only one prepared dictionary type is currently supported. */\n    FindCompoundDictionaryMatch(\n        (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask,\n        distance_cache, cur_ix, max_length,\n        base_offset - addon->chunk_offsets[d], max_distance, sr);\n  }\n}\n\nstatic BROTLI_INLINE size_t LookupAllCompoundDictionaryMatches(\n    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const size_t cur_ix, size_t min_length,\n    const size_t max_length, const size_t max_ring_buffer_distance,\n    const size_t max_distance, BackwardMatch* matches,\n    size_t match_limit) {\n  size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1;\n  size_t d;\n  size_t total_found = 0;\n  for (d = 0; d < addon->num_chunks; ++d) {\n    /* Only one prepared dictionary type is currently supported. */\n    total_found += FindAllCompoundDictionaryMatches(\n        (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask,\n        cur_ix, min_length, max_length, base_offset - addon->chunk_offsets[d],\n        max_distance, matches + total_found, match_limit - total_found);\n    if (total_found == match_limit) break;\n    if (total_found > 0) {\n      min_length = BackwardMatchLength(&matches[total_found - 1]);\n    }\n  }\n  return total_found;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_HASH_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_base.h",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Basic common hash functions / constants. */\n\n#ifndef THIRD_PARTY_BROTLI_ENC_HASH_BASE_H_\n#define THIRD_PARTY_BROTLI_ENC_HASH_BASE_H_\n\n#include \"../common/platform.h\"\n\n/* kHashMul32 multiplier has these properties:\n   * The multiplier must be odd. Otherwise we may lose the highest bit.\n   * No long streaks of ones or zeros.\n   * There is no effort to ensure that it is a prime, the oddity is enough\n     for this use.\n   * The number has been tuned heuristically against compression benchmarks. */\nstatic const uint32_t kHashMul32 = 0x1E35A7BD;\nstatic const uint64_t kHashMul64 =\n    BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);\n\nstatic BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - 14);\n}\n\nstatic BROTLI_INLINE uint32_t Hash15(const uint8_t* data) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - 15);\n}\n\n#endif  // THIRD_PARTY_BROTLI_ENC_HASH_BASE_H_\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_composite_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2018 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, HASHER_A, HASHER_B */\n\n/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A\n   and HASHER_B. */\n\n#define HashComposite HASHER()\n\n#define FN_A(X) EXPAND_CAT(X, HASHER_A)\n#define FN_B(X) EXPAND_CAT(X, HASHER_B)\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) {\n  size_t a =  FN_A(HashTypeLength)();\n  size_t b =  FN_B(HashTypeLength)();\n  return a > b ? a : b;\n}\n\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) {\n  size_t a =  FN_A(StoreLookahead)();\n  size_t b =  FN_B(StoreLookahead)();\n  return a > b ? a : b;\n}\n\ntypedef struct HashComposite {\n  HASHER_A ha;\n  HASHER_B hb;\n  HasherCommon ha_common;\n  HasherCommon hb_common;\n\n  /* Shortcuts. */\n  HasherCommon* common;\n\n  BROTLI_BOOL fresh;\n  const BrotliEncoderParams* params;\n} HashComposite;\n\nstatic void FN(Initialize)(HasherCommon* common,\n    HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) {\n  self->common = common;\n\n  self->ha_common = *self->common;\n  self->hb_common = *self->common;\n  self->fresh = BROTLI_TRUE;\n  self->params = params;\n  /* TODO(lode): Initialize of the hashers is deferred to Prepare (and params\n     remembered here) because we don't get the one_shot and input_size params\n     here that are needed to know the memory size of them. Instead provide\n     those params to all hashers FN(Initialize) */\n}\n\nstatic void FN(Prepare)(\n    HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  if (self->fresh) {\n    self->fresh = BROTLI_FALSE;\n    self->ha_common.extra[0] = self->common->extra[0];\n    self->ha_common.extra[1] = self->common->extra[1];\n    self->ha_common.extra[2] = NULL;\n    self->ha_common.extra[3] = NULL;\n    self->hb_common.extra[0] = self->common->extra[2];\n    self->hb_common.extra[1] = self->common->extra[3];\n    self->hb_common.extra[2] = NULL;\n    self->hb_common.extra[3] = NULL;\n\n    FN_A(Initialize)(&self->ha_common, &self->ha, self->params);\n    FN_B(Initialize)(&self->hb_common, &self->hb, self->params);\n  }\n  FN_A(Prepare)(&self->ha, one_shot, input_size, data);\n  FN_B(Prepare)(&self->hb, one_shot, input_size, data);\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t alloc_size_a[4] = {0};\n  size_t alloc_size_b[4] = {0};\n  FN_A(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_a);\n  FN_B(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_b);\n  /* Should never happen. */\n  if (alloc_size_a[2] != 0 || alloc_size_a[3] != 0) exit(EXIT_FAILURE);\n  if (alloc_size_b[2] != 0 || alloc_size_b[3] != 0) exit(EXIT_FAILURE);\n  alloc_size[0] = alloc_size_a[0];\n  alloc_size[1] = alloc_size_a[1];\n  alloc_size[2] = alloc_size_b[0];\n  alloc_size[3] = alloc_size_b[1];\n}\n\nstatic BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  FN_A(Store)(&self->ha, data, mask, ix);\n  FN_B(Store)(&self->hb, data, mask, ix);\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(\n    HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix_start,\n    const size_t ix_end) {\n  FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end);\n  FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end);\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashComposite* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ring_buffer_mask) {\n  FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position,\n      ringbuffer, ring_buffer_mask);\n  FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position,\n      ringbuffer, ring_buffer_mask);\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) {\n  FN_A(PrepareDistanceCache)(&self->ha, distance_cache);\n  FN_B(PrepareDistanceCache)(&self->hb, distance_cache);\n}\n\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashComposite* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask,\n      distance_cache, cur_ix, max_length, max_backward, dictionary_distance,\n      max_distance, out);\n  FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask,\n      distance_cache, cur_ix, max_length, max_backward, dictionary_distance,\n      max_distance, out);\n}\n\n#undef HashComposite\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_forgetful_chain_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, BUCKET_BITS, NUM_BANKS, BANK_BITS,\n                        NUM_LAST_DISTANCES_TO_CHECK */\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   Hashes are stored in chains which are bucketed to groups. Group of chains\n   share a storage \"bank\". When more than \"bank size\" chain nodes are added,\n   oldest nodes are replaced; this way several chains may share a tail. */\n\n#define HashForgetfulChain HASHER()\n\n#define BANK_SIZE (1 << BANK_BITS)\n\n/* Number of hash buckets. */\n#define BUCKET_SIZE (1 << BUCKET_BITS)\n\n#define CAPPED_CHAINS 0\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }\n\n/* HashBytes is the function that chooses the bucket to place the address in.*/\nstatic BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) {\n  const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - BUCKET_BITS);\n}\n\ntypedef struct FN(Slot) {\n  uint16_t delta;\n  uint16_t next;\n} FN(Slot);\n\ntypedef struct FN(Bank) {\n  FN(Slot) slots[BANK_SIZE];\n} FN(Bank);\n\ntypedef struct HashForgetfulChain {\n  uint16_t free_slot_idx[NUM_BANKS];  /* Up to 1KiB. Move to dynamic? */\n  size_t max_hops;\n\n  /* Shortcuts. */\n  void* extra[2];\n  HasherCommon* common;\n\n  /* --- Dynamic size members --- */\n\n  /* uint32_t addr[BUCKET_SIZE]; */\n\n  /* uint16_t head[BUCKET_SIZE]; */\n\n  /* Truncated hash used for quick rejection of \"distance cache\" candidates. */\n  /* uint8_t tiny_hash[65536];*/\n\n  /* FN(Bank) banks[NUM_BANKS]; */\n} HashForgetfulChain;\n\nstatic uint32_t* FN(Addr)(void* extra) {\n  return (uint32_t*)extra;\n}\n\nstatic uint16_t* FN(Head)(void* extra) {\n  return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]);\n}\n\nstatic uint8_t* FN(TinyHash)(void* extra) {\n  return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]);\n}\n\nstatic FN(Bank)* FN(Banks)(void* extra) {\n  return (FN(Bank)*)(extra);\n}\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common = common;\n  self->extra[0] = common->extra[0];\n  self->extra[1] = common->extra[1];\n\n  self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4);\n}\n\nstatic void FN(Prepare)(\n    HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);\n  uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);\n  uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]);\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = BUCKET_SIZE >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      size_t bucket = FN(HashBytes)(&data[i]);\n      /* See InitEmpty comment. */\n      addr[bucket] = 0xCCCCCCCC;\n      head[bucket] = 0xCCCC;\n    }\n  } else {\n    /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position\n       processed by hasher never reaches 3GB + 64M; this makes all new chains\n       to be terminated after the first node. */\n    memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE);\n    memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE);\n  }\n  memset(tiny_hash, 0, sizeof(uint8_t) * 65536);\n  memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx));\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  BROTLI_UNUSED(params);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE +\n                  sizeof(uint16_t) * BUCKET_SIZE + sizeof(uint8_t) * 65536;\n  alloc_size[1] = sizeof(FN(Bank)) * NUM_BANKS;\n}\n\n/* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend\n   node to corresponding chain; also update tiny_hash for current position. */\nstatic BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);\n  uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);\n  uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]);\n  FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]);\n  const size_t key = FN(HashBytes)(&data[ix & mask]);\n  const size_t bank = key & (NUM_BANKS - 1);\n  const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1);\n  size_t delta = ix - addr[key];\n  tiny_hash[(uint16_t)ix] = (uint8_t)key;\n  if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF;\n  banks[bank].slots[idx].delta = (uint16_t)delta;\n  banks[bank].slots[idx].next = head[key];\n  addr[key] = (uint32_t)ix;\n  head[key] = (uint16_t)idx;\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ring_buffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  BROTLI_UNUSED(self);\n  PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);\n  uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);\n  uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra[0]);\n  FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]);\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  const size_t key = FN(HashBytes)(&data[cur_ix_masked]);\n  const uint8_t tiny_hash = (uint8_t)(key);\n  out->len = 0;\n  out->len_code_delta = 0;\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  /* Try last distance first. */\n  for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (cur_ix - backward);\n    /* For distance code 0 we want to consider 2-byte matches. */\n    if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue;\n    if (prev_ix >= cur_ix || backward > max_backward) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 2) {\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  /* we require matches of len >4, so increase best_len to 3, so we can compare\n   * 4 bytes all the time. */\n  if (best_len < 3) {\n    best_len = 3;\n  }\n  {\n    const size_t bank = key & (NUM_BANKS - 1);\n    size_t backward = 0;\n    size_t hops = self->max_hops;\n    size_t delta = cur_ix - addr[key];\n    size_t slot = head[key];\n    while (hops--) {\n      size_t prev_ix;\n      size_t last = slot;\n      backward += delta;\n      if (backward > max_backward || (CAPPED_CHAINS && !delta)) break;\n      prev_ix = (cur_ix - backward) & ring_buffer_mask;\n      slot = banks[bank].slots[last].next;\n      delta = banks[bank].slots[last].delta;\n      if (cur_ix_masked + best_len > ring_buffer_mask ||\n          prev_ix + best_len > ring_buffer_mask ||\n          /* compare 4 bytes ending at best_len + 1 */\n          BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=\n              BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {\n        continue;\n      }\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                    &data[cur_ix_masked],\n                                                    max_length);\n        if (len >= 4) {\n          /* Comparing for >= 3 does not change the semantics, but just saves\n             for a few unnecessary binary logarithms in backward reference\n             score, since we are not interested in such short matches. */\n          score_t score = BackwardReferenceScore(len, backward);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n    FN(Store)(self, data, ring_buffer_mask, cur_ix);\n  }\n  if (out->score == min_score) {\n    SearchInStaticDictionary(dictionary,\n        self->common, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n\n#undef BANK_SIZE\n#undef BUCKET_SIZE\n#undef CAPPED_CHAINS\n\n#undef HashForgetfulChain\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_longest_match64_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   This is a hash map of fixed size (bucket_size_) to a ring buffer of\n   fixed size (block_size_). The ring buffer contains the last block_size_\n   index positions of the given hash key in the compressed data. */\n\n#define HashLongestMatch HASHER()\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }\n\n/* HashBytes is the function that chooses the bucket to place the address in. */\nstatic BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data,\n                                          uint64_t hash_mul) {\n  const uint64_t h = BROTLI_UNALIGNED_LOAD64LE(data) * hash_mul;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (size_t)(h >> (64 - 15));\n}\n\ntypedef struct HashLongestMatch {\n  /* Number of hash buckets. */\n  size_t bucket_size_;\n  /* Only block_size_ newest backward references are kept,\n     and the older are forgotten. */\n  size_t block_size_;\n  /* Hash multiplier tuned to match length. */\n  uint64_t hash_mul_;\n  /* Mask for accessing entries in a block (in a ring-buffer manner). */\n  uint32_t block_mask_;\n\n  int block_bits_;\n  int num_last_distances_to_check_;\n\n  /* Shortcuts. */\n  HasherCommon* common_;\n\n  /* --- Dynamic size members --- */\n\n  /* Number of entries in a particular bucket. */\n  uint16_t* num_;  /* uint16_t[bucket_size]; */\n\n  /* Buckets containing block_size_ of backward references. */\n  uint32_t* buckets_;  /* uint32_t[bucket_size * block_size]; */\n} HashLongestMatch;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common_ = common;\n\n  BROTLI_UNUSED(params);\n  self->hash_mul_ = kHashMul64 << (64 - 5 * 8);\n  BROTLI_DCHECK(common->params.bucket_bits == 15);\n  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;\n  self->block_bits_ = common->params.block_bits;\n  self->block_size_ = (size_t)1 << common->params.block_bits;\n  self->block_mask_ = (uint32_t)(self->block_size_ - 1);\n  self->num_last_distances_to_check_ =\n      common->params.num_last_distances_to_check;\n  self->num_ = (uint16_t*)common->extra[0];\n  self->buckets_ = (uint32_t*)common->extra[1];\n}\n\nstatic void FN(Prepare)(\n    HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = self->bucket_size_ >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const size_t key = FN(HashBytes)(&data[i], self->hash_mul_);\n      num[key] = 0;\n    }\n  } else {\n    memset(num, 0, self->bucket_size_ * sizeof(num[0]));\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;\n  size_t block_size = (size_t)1 << params->hasher.block_bits;\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint16_t) * bucket_size;\n  alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size;\n}\n\n/* Look at 4 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value of ix at that position. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t key = FN(HashBytes)(&data[ix & mask], self->hash_mul_);\n  const size_t minor_ix = num[key] & self->block_mask_;\n  const size_t offset = minor_ix + (key << self->block_bits_);\n  ++num[key];\n  buckets[offset] = (uint32_t)ix;\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  /* Precalculate the hash key and prefetch the bucket. */\n  const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_);\n  uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];\n  PREFETCH_L1(bucket);\n  if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);\n  out->len = 0;\n  out->len_code_delta = 0;\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  /* Try last distance first. */\n  for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (size_t)(cur_ix - backward);\n    if (prev_ix >= cur_ix) {\n      continue;\n    }\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n\n    if (cur_ix_masked + best_len > ring_buffer_mask) {\n      break;\n    }\n    if (prev_ix + best_len > ring_buffer_mask ||\n        data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 3 || (len == 2 && i < 2)) {\n        /* Comparing for >= 2 does not change the semantics, but just saves for\n           a few unnecessary binary logarithms in backward reference score,\n           since we are not interested in such short matches. */\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  /* we require matches of len >4, so increase best_len to 3, so we can compare\n   * 4 bytes all the time. */\n  if (best_len < 3) {\n    best_len = 3;\n  }\n  {\n    const size_t down =\n        (num[key] > self->block_size_) ?\n        (num[key] - self->block_size_) : 0u;\n    const uint32_t first4 = BrotliUnalignedRead32(data + cur_ix_masked);\n    const size_t max_length_m4 = max_length - 4;\n    i = num[key];\n    for (; i > down;) {\n      size_t prev_ix = bucket[--i & self->block_mask_];\n      uint32_t current4;\n      const size_t backward = cur_ix - prev_ix;\n      if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n        break;\n      }\n      prev_ix &= ring_buffer_mask;\n      if (cur_ix_masked + best_len > ring_buffer_mask) {\n        break;\n      }\n      if (prev_ix + best_len > ring_buffer_mask ||\n          /* compare 4 bytes ending at best_len + 1 */\n          BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=\n              BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {\n        continue;\n      }\n      current4 = BrotliUnalignedRead32(data + prev_ix);\n      if (first4 != current4) continue;\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix + 4],\n                                                    &data[cur_ix_masked + 4],\n                                                    max_length_m4) + 4;\n        const score_t score = BackwardReferenceScore(len, backward);\n        if (best_score < score) {\n          best_score = score;\n          best_len = len;\n          out->len = best_len;\n          out->distance = backward;\n          out->score = best_score;\n        }\n      }\n    }\n    bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;\n    ++num[key];\n  }\n  if (min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common_, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n\n#undef HashLongestMatch\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_longest_match64_simd_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   This is a hash map of fixed size (bucket_size_) to a ring buffer of\n   fixed size (block_size_). The ring buffer contains the last block_size_\n   index positions of the given hash key in the compressed data. */\n\n#define HashLongestMatch HASHER()\n\n#define TAG_HASH_BITS 8\n#define TAG_HASH_MASK ((1 << TAG_HASH_BITS) - 1)\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }\n\n/* HashBytes is the function that chooses the bucket to place the address in. */\nstatic BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data,\n                                          uint64_t hash_mul) {\n  const uint64_t h = BROTLI_UNALIGNED_LOAD64LE(data) * hash_mul;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (size_t)(h >> (64 - 15 - TAG_HASH_BITS));\n}\n\ntypedef struct HashLongestMatch {\n  /* Number of hash buckets. */\n  size_t bucket_size_;\n  /* Only block_size_ newest backward references are kept,\n     and the older are forgotten. */\n  size_t block_size_;\n  /* Hash multiplier tuned to match length. */\n  uint64_t hash_mul_;\n  /* Mask for accessing entries in a block (in a ring-buffer manner). */\n  uint32_t block_mask_;\n\n  int block_bits_;\n  int num_last_distances_to_check_;\n\n  /* Shortcuts. */\n  HasherCommon* common_;\n\n  /* --- Dynamic size members --- */\n\n  /* Number of entries in a particular bucket. */\n  uint16_t* num_;  /* uint16_t[bucket_size]; */\n\n  uint8_t* tags_;\n\n  /* Buckets containing block_size_ of backward references. */\n  uint32_t* buckets_;  /* uint32_t[bucket_size * block_size]; */\n} HashLongestMatch;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common_ = common;\n\n  BROTLI_UNUSED(params);\n  self->hash_mul_ = kHashMul64 << (64 - 5 * 8);\n  BROTLI_DCHECK(common->params.bucket_bits == 15);\n  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;\n  self->block_bits_ = common->params.block_bits;\n  self->block_size_ = (size_t)1 << common->params.block_bits;\n  self->block_mask_ = (uint32_t)(self->block_size_ - 1);\n  self->num_last_distances_to_check_ =\n      common->params.num_last_distances_to_check;\n  self->num_ = (uint16_t*)common->extra[0];\n  self->tags_ = (uint8_t*)common->extra[1];\n  self->buckets_ = (uint32_t*)common->extra[2];\n}\n\nstatic void FN(Prepare)(\n    HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = self->bucket_size_ >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const size_t hash = FN(HashBytes)(&data[i], self->hash_mul_);\n      const size_t key = hash >> TAG_HASH_BITS;\n      num[key] = 65535;\n    }\n  } else {\n    /* Set all the bytes of num to 255, which makes each uint16_t 65535. */\n    memset(num, 255, self->bucket_size_ * sizeof(num[0]));\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;\n  size_t block_size = (size_t)1 << params->hasher.block_bits;\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint16_t) * bucket_size;\n  alloc_size[1] = sizeof(uint8_t) * bucket_size * block_size;\n  alloc_size[2] = sizeof(uint32_t) * bucket_size * block_size;\n}\n\n/* Look at 4 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value of ix at that position. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint8_t* BROTLI_RESTRICT tags = self->tags_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t hash = FN(HashBytes)(&data[ix & mask], self->hash_mul_);\n  const size_t key = hash >> TAG_HASH_BITS;\n  const uint8_t tag = hash & TAG_HASH_MASK;\n  const size_t minor_ix = num[key] & self->block_mask_;\n  const size_t offset = minor_ix + (key << self->block_bits_);\n  --num[key];\n  buckets[offset] = (uint32_t)ix;\n  tags[offset] = tag;\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  uint8_t* BROTLI_RESTRICT tags = self->tags_;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  /* Precalculate the hash key and prefetch the bucket. */\n  const size_t hash = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_);\n  const size_t key = hash >> TAG_HASH_BITS;\n  uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];\n  uint8_t* BROTLI_RESTRICT tag_bucket = &tags[key << self->block_bits_];\n  PREFETCH_L1(bucket);\n  PREFETCH_L1(tag_bucket);\n  if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);\n  out->len = 0;\n  out->len_code_delta = 0;\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  /* Try last distance first. */\n  for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (size_t)(cur_ix - backward);\n    if (prev_ix >= cur_ix) {\n      continue;\n    }\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n\n    if (cur_ix_masked + best_len > ring_buffer_mask) {\n      break;\n    }\n    if (prev_ix + best_len > ring_buffer_mask ||\n        data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 3 || (len == 2 && i < 2)) {\n        /* Comparing for >= 2 does not change the semantics, but just saves for\n           a few unnecessary binary logarithms in backward reference score,\n           since we are not interested in such short matches. */\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  /* we require matches of len >4, so increase best_len to 3, so we can compare\n   * 4 bytes all the time. */\n  if (best_len < 3) {\n    best_len = 3;\n  }\n  {\n    const uint8_t tag = hash & TAG_HASH_MASK;\n    const uint32_t first4 = BrotliUnalignedRead32(data + cur_ix_masked);\n    const size_t max_length_m4 = max_length - 4;\n    const size_t head = (num[key] + 1) & self->block_mask_;\n    uint64_t matches =\n        GetMatchingTagMask(self->block_size_ / 16, tag, tag_bucket, head);\n    /* Mask off any matches from uninitialized tags. */\n    uint16_t n = 65535 - num[key];\n    uint64_t block_has_unused_slots = self->block_size_ > n;\n    uint64_t mask = (block_has_unused_slots << (n & (64 - 1))) - 1;\n    matches &= mask;\n    for (; matches > 0; matches &= (matches - 1)) {\n      const size_t rb_index =\n          (head + (size_t)BROTLI_TZCNT64(matches)) & self->block_mask_;\n      size_t prev_ix = bucket[rb_index];\n      uint32_t current4;\n      const size_t backward = cur_ix - prev_ix;\n      if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n        break;\n      }\n      prev_ix &= ring_buffer_mask;\n      if (cur_ix_masked + best_len > ring_buffer_mask) {\n        break;\n      }\n      if (prev_ix + best_len > ring_buffer_mask ||\n          /* compare 4 bytes ending at best_len + 1 */\n          BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=\n              BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {\n        continue;\n      }\n      current4 = BrotliUnalignedRead32(data + prev_ix);\n      if (first4 != current4) continue;\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix + 4],\n                                                    &data[cur_ix_masked + 4],\n                                                    max_length_m4) + 4;\n        const score_t score = BackwardReferenceScore(len, backward);\n        if (best_score < score) {\n          best_score = score;\n          best_len = len;\n          out->len = best_len;\n          out->distance = backward;\n          out->score = best_score;\n        }\n      }\n    }\n    bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;\n    tag_bucket[num[key] & self->block_mask_] = tag;\n    --num[key];\n  }\n  if (min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common_, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n\n#undef HashLongestMatch\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_longest_match_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   This is a hash map of fixed size (bucket_size_) to a ring buffer of\n   fixed size (block_size_). The ring buffer contains the last block_size_\n   index positions of the given hash key in the compressed data. */\n\n#define HashLongestMatch HASHER()\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }\n\n/* HashBytes is the function that chooses the bucket to place the address in. */\nstatic uint32_t FN(HashBytes)(\n    const uint8_t* BROTLI_RESTRICT data, const int shift) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (uint32_t)(h >> shift);\n}\n\ntypedef struct HashLongestMatch {\n  /* Number of hash buckets. */\n  size_t bucket_size_;\n  /* Only block_size_ newest backward references are kept,\n     and the older are forgotten. */\n  size_t block_size_;\n  /* Left-shift for computing hash bucket index from hash value. */\n  int hash_shift_;\n  /* Mask for accessing entries in a block (in a ring-buffer manner). */\n  uint32_t block_mask_;\n\n  int block_bits_;\n  int num_last_distances_to_check_;\n\n  /* Shortcuts. */\n  HasherCommon* common_;\n\n  /* --- Dynamic size members --- */\n\n  /* Number of entries in a particular bucket. */\n  uint16_t* num_;  /* uint16_t[bucket_size]; */\n\n  /* Buckets containing block_size_ of backward references. */\n  uint32_t* buckets_;  /* uint32_t[bucket_size * block_size]; */\n} HashLongestMatch;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common_ = common;\n\n  BROTLI_UNUSED(params);\n  self->hash_shift_ = 32 - common->params.bucket_bits;\n  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;\n  self->block_size_ = (size_t)1 << common->params.block_bits;\n  self->block_mask_ = (uint32_t)(self->block_size_ - 1);\n  self->num_ = (uint16_t*)common->extra[0];\n  self->buckets_ = (uint32_t*)common->extra[1];\n  self->block_bits_ = common->params.block_bits;\n  self->num_last_distances_to_check_ =\n      common->params.num_last_distances_to_check;\n}\n\nstatic void FN(Prepare)(\n    HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = self->bucket_size_ >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const uint32_t key = FN(HashBytes)(&data[i], self->hash_shift_);\n      num[key] = 0;\n    }\n  } else {\n    memset(num, 0, self->bucket_size_ * sizeof(num[0]));\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;\n  size_t block_size = (size_t)1 << params->hasher.block_bits;\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint16_t) * bucket_size;\n  alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size;\n}\n\n/* Look at 4 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value of ix at that position. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_shift_);\n  const size_t minor_ix = num[key] & self->block_mask_;\n  const size_t offset = minor_ix + (key << self->block_bits_);\n  ++num[key];\n  buckets[offset] = (uint32_t)ix;\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  /* Precalculate the hash key and prefetch the bucket. */\n  const uint32_t key =\n      FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);\n  uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];\n  PREFETCH_L1(bucket);\n  if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);\n  out->len = 0;\n  out->len_code_delta = 0;\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  /* Try last distance first. */\n  for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (size_t)(cur_ix - backward);\n    if (prev_ix >= cur_ix) {\n      continue;\n    }\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n\n    if (cur_ix_masked + best_len > ring_buffer_mask) {\n      break;\n    }\n    if (prev_ix + best_len > ring_buffer_mask ||\n        data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 3 || (len == 2 && i < 2)) {\n        /* Comparing for >= 2 does not change the semantics, but just saves for\n           a few unnecessary binary logarithms in backward reference score,\n           since we are not interested in such short matches. */\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  /* we require matches of len >4, so increase best_len to 3, so we can compare\n   * 4 bytes all the time. */\n  if (best_len < 3) {\n    best_len = 3;\n  }\n  {\n    const size_t down =\n        (num[key] > self->block_size_) ? (num[key] - self->block_size_) : 0u;\n    for (i = num[key]; i > down;) {\n      size_t prev_ix = bucket[--i & self->block_mask_];\n      const size_t backward = cur_ix - prev_ix;\n      if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n        break;\n      }\n      prev_ix &= ring_buffer_mask;\n      if (cur_ix_masked + best_len > ring_buffer_mask) {\n        break;\n      }\n      if (prev_ix + best_len > ring_buffer_mask ||\n          /* compare 4 bytes ending at best_len + 1 */\n          BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=\n              BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {\n        continue;\n      }\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                    &data[cur_ix_masked],\n                                                    max_length);\n        if (len >= 4) {\n          /* Comparing for >= 3 does not change the semantics, but just saves\n             for a few unnecessary binary logarithms in backward reference\n             score, since we are not interested in such short matches. */\n          score_t score = BackwardReferenceScore(len, backward);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n    bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;\n    ++num[key];\n  }\n  if (min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common_, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n\n#undef HashLongestMatch\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_longest_match_quickly_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN,\n                        USE_DICTIONARY\n */\n\n#define HashLongestMatchQuickly HASHER()\n\n#define BUCKET_SIZE (1 << BUCKET_BITS)\n#define BUCKET_MASK (BUCKET_SIZE - 1)\n#define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS)\n#define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3)\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }\n\n/* HashBytes is the function that chooses the bucket to place\n   the address in. The HashLongestMatch and HashLongestMatchQuickly\n   classes have separate, different implementations of hashing. */\nstatic uint32_t FN(HashBytes)(const uint8_t* data) {\n  const uint64_t h = ((BROTLI_UNALIGNED_LOAD64LE(data) << (64 - 8 * HASH_LEN)) *\n                      kHashMul64);\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (uint32_t)(h >> (64 - BUCKET_BITS));\n}\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   This is a hash map of fixed size (BUCKET_SIZE). */\ntypedef struct HashLongestMatchQuickly {\n  /* Shortcuts. */\n  HasherCommon* common;\n\n  /* --- Dynamic size members --- */\n\n  uint32_t* buckets_;  /* uint32_t[BUCKET_SIZE]; */\n} HashLongestMatchQuickly;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common = common;\n\n  BROTLI_UNUSED(params);\n  self->buckets_ = (uint32_t*)common->extra[0];\n}\n\nstatic void FN(Prepare)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = BUCKET_SIZE >> 5;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const uint32_t key = FN(HashBytes)(&data[i]);\n      if (BUCKET_SWEEP == 1) {\n        buckets[key] = 0;\n      } else {\n        uint32_t j;\n        for (j = 0; j < BUCKET_SWEEP; ++j) {\n          buckets[(key + (j << 3)) & BUCKET_MASK] = 0;\n        }\n      }\n    }\n  } else {\n    /* It is not strictly necessary to fill this buffer here, but\n       not filling will make the results of the compression stochastic\n       (but correct). This is because random data would cause the\n       system to find accidentally good backward references here and there. */\n    memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE);\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  BROTLI_UNUSED(params);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE;\n}\n\n/* Look at 5 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value somewhere within\n   [ix .. ix+3]. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  const uint32_t key = FN(HashBytes)(&data[ix & mask]);\n  if (BUCKET_SWEEP == 1) {\n    self->buckets_[key] = (uint32_t)ix;\n  } else {\n    /* Wiggle the value with the bucket sweep range. */\n    const uint32_t off = ix & BUCKET_SWEEP_MASK;\n    self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix;\n  }\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position,\n    const uint8_t* ringbuffer, size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(distance_cache);\n}\n\n/* Find a longest backward match of &data[cur_ix & ring_buffer_mask]\n   up to the length of max_length and stores the position cur_ix in the\n   hash table.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t best_len_in = out->len;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* TODO: compare 4 bytes at once (and set the minimum best len to 4) */\n  int compare_char = data[cur_ix_masked + best_len_in];\n  size_t key = FN(HashBytes)(&data[cur_ix_masked]);\n  size_t key_out;\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = best_len_in;\n  size_t cached_backward = (size_t)distance_cache[0];\n  size_t prev_ix = cur_ix - cached_backward;\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  out->len_code_delta = 0;\n  if (prev_ix < cur_ix) {\n    prev_ix &= (uint32_t)ring_buffer_mask;\n    if (compare_char == data[prev_ix + best_len]) {\n      const size_t len = FindMatchLengthWithLimit(\n          &data[prev_ix], &data[cur_ix_masked], max_length);\n      if (len >= 4) {\n        const score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          out->len = len;\n          out->distance = cached_backward;\n          out->score = score;\n          if (BUCKET_SWEEP == 1) {\n            buckets[key] = (uint32_t)cur_ix;\n            return;\n          } else {\n            best_len = len;\n            best_score = score;\n            compare_char = data[cur_ix_masked + len];\n          }\n        }\n      }\n    }\n  }\n  if (BUCKET_SWEEP == 1) {\n    size_t backward;\n    size_t len;\n    /* Only one to look for, don't bother to prepare for a loop. */\n    prev_ix = buckets[key];\n    buckets[key] = (uint32_t)cur_ix;\n    backward = cur_ix - prev_ix;\n    prev_ix &= (uint32_t)ring_buffer_mask;\n    if (compare_char != data[prev_ix + best_len_in]) {\n      return;\n    }\n    if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) {\n      return;\n    }\n    len = FindMatchLengthWithLimit(&data[prev_ix],\n                                   &data[cur_ix_masked],\n                                   max_length);\n    if (len >= 4) {\n      const score_t score = BackwardReferenceScore(len, backward);\n      if (best_score < score) {\n        out->len = len;\n        out->distance = backward;\n        out->score = score;\n        return;\n      }\n    }\n  } else {\n    size_t keys[BUCKET_SWEEP];\n    size_t i;\n    for (i = 0; i < BUCKET_SWEEP; ++i) {\n      keys[i] = (key + (i << 3)) & BUCKET_MASK;\n    }\n    key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3];\n    for (i = 0; i < BUCKET_SWEEP; ++i) {\n      size_t len;\n      size_t backward;\n      prev_ix = buckets[keys[i]];\n      backward = cur_ix - prev_ix;\n      prev_ix &= (uint32_t)ring_buffer_mask;\n      if (compare_char != data[prev_ix + best_len]) {\n        continue;\n      }\n      if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) {\n        continue;\n      }\n      len = FindMatchLengthWithLimit(&data[prev_ix],\n                                     &data[cur_ix_masked],\n                                     max_length);\n      if (len >= 4) {\n        const score_t score = BackwardReferenceScore(len, backward);\n        if (best_score < score) {\n          best_len = len;\n          out->len = len;\n          compare_char = data[cur_ix_masked + len];\n          best_score = score;\n          out->score = score;\n          out->distance = backward;\n        }\n      }\n    }\n  }\n  if (USE_DICTIONARY && min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_TRUE);\n  }\n  if (BUCKET_SWEEP != 1) {\n    buckets[key_out] = (uint32_t)cur_ix;\n  }\n}\n\n#undef BUCKET_SWEEP_MASK\n#undef BUCKET_SWEEP\n#undef BUCKET_MASK\n#undef BUCKET_SIZE\n\n#undef HashLongestMatchQuickly\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_longest_match_simd_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n/* template parameters: FN */\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n   This is a hash map of fixed size (bucket_size_) to a ring buffer of\n   fixed size (block_size_). The ring buffer contains the last block_size_\n   index positions of the given hash key in the compressed data. */\n#define HashLongestMatch HASHER()\n#define TAG_HASH_BITS 8\n#define TAG_HASH_MASK ((1 << TAG_HASH_BITS) - 1)\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }\n/* HashBytes is the function that chooses the bucket to place the address in. */\nstatic uint32_t FN(HashBytes)(\n    const uint8_t* BROTLI_RESTRICT data, const int shift) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (uint32_t)(h >> shift);\n}\ntypedef struct HashLongestMatch {\n  /* Number of hash buckets. */\n  size_t bucket_size_;\n  /* Only block_size_ newest backward references are kept,\n     and the older are forgotten. */\n  size_t block_size_;\n  /* Left-shift for computing hash bucket index from hash value. */\n  int hash_shift_;\n  /* Mask for accessing entries in a block (in a ring-buffer manner). */\n  uint32_t block_mask_;\n  int block_bits_;\n  int num_last_distances_to_check_;\n  /* Shortcuts. */\n  HasherCommon* common_;\n  /* --- Dynamic size members --- */\n  /* Number of entries in a particular bucket. */\n  uint16_t* num_;  /* uint16_t[bucket_size]; */\n  uint8_t* tags_;\n  /* Buckets containing block_size_ of backward references. */\n  uint32_t* buckets_;  /* uint32_t[bucket_size * block_size]; */\n} HashLongestMatch;\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common_ = common;\n  BROTLI_UNUSED(params);\n  self->hash_shift_ = 32 - common->params.bucket_bits - TAG_HASH_BITS;\n  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;\n  self->block_size_ = (size_t)1 << common->params.block_bits;\n  self->block_mask_ = (uint32_t)(self->block_size_ - 1);\n  self->num_ = (uint16_t*)common->extra[0];\n  self->tags_ = (uint8_t*)common->extra[1];\n  self->buckets_ = (uint32_t*)common->extra[2];\n  self->block_bits_ = common->params.block_bits;\n  self->num_last_distances_to_check_ =\n      common->params.num_last_distances_to_check;\n}\nstatic void FN(Prepare)(\n    HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = self->bucket_size_ >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const uint32_t hash = FN(HashBytes)(&data[i], self->hash_shift_);\n      const uint32_t key = hash >> TAG_HASH_BITS;\n      num[key] = 65535;\n    }\n  } else {\n    /* Set all the bytes of num to 255, which makes each uint16_t 65535. */\n    memset(num, 255, self->bucket_size_ * sizeof(num[0]));\n  }\n}\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;\n  size_t block_size = (size_t)1 << params->hasher.block_bits;\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint16_t) * bucket_size;\n  alloc_size[1] = sizeof(uint8_t) * bucket_size * block_size;\n  alloc_size[2] = sizeof(uint32_t) * bucket_size * block_size;\n}\n/* Look at 4 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value of ix at that position. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint8_t* BROTLI_RESTRICT tags = self->tags_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t hash = FN(HashBytes)(&data[ix & mask], self->hash_shift_);\n  const size_t key = hash >> TAG_HASH_BITS;\n  const uint8_t tag = hash & TAG_HASH_MASK;\n  const size_t minor_ix = num[key] & self->block_mask_;\n  const size_t offset = minor_ix + (key << self->block_bits_);\n  --num[key];\n  buckets[offset] = (uint32_t)ix;\n  tags[offset] = tag;\n}\nstatic BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  uint8_t* BROTLI_RESTRICT tags = self->tags_;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  /* Precalculate the hash key and prefetch the bucket. */\n  const uint32_t hash =\n      FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);\n  const uint32_t key = hash >> TAG_HASH_BITS;\n  uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];\n  uint8_t* BROTLI_RESTRICT tag_bucket = &tags[key << self->block_bits_];\n  PREFETCH_L1(bucket);\n  PREFETCH_L1(tag_bucket);\n  if (self->block_bits_ > 4) PREFETCH_L1(bucket + 16);\n  out->len = 0;\n  out->len_code_delta = 0;\n\n  BROTLI_DCHECK(cur_ix_masked + max_length <= ring_buffer_mask);\n\n  /* Try last distance first. */\n  for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (size_t)(cur_ix - backward);\n    if (prev_ix >= cur_ix) {\n      continue;\n    }\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n\n    if (cur_ix_masked + best_len > ring_buffer_mask) {\n      break;\n    }\n    if (prev_ix + best_len > ring_buffer_mask ||\n        data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 3 || (len == 2 && i < 2)) {\n        /* Comparing for >= 2 does not change the semantics, but just saves for\n           a few unnecessary binary logarithms in backward reference score,\n           since we are not interested in such short matches. */\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  /* we require matches of len >4, so increase best_len to 3, so we can compare\n   * 4 bytes all the time. */\n  if (best_len < 3) {\n    best_len = 3;\n  }\n  {\n    const uint8_t tag = hash & TAG_HASH_MASK;\n    const size_t head = (num[key] + 1) & self->block_mask_;\n    uint64_t matches =\n        GetMatchingTagMask(self->block_size_ / 16, tag, tag_bucket, head);\n    /* Mask off any matches from uninitialized tags. */\n    uint16_t n = 65535 - num[key];\n    uint64_t block_has_unused_slots = self->block_size_ > n;\n    uint64_t mask = (block_has_unused_slots << (n & (64 - 1))) - 1;\n    matches &= mask;\n    for (; matches > 0; matches &= (matches - 1)) {\n      const size_t rb_index =\n          (head + (size_t)BROTLI_TZCNT64(matches)) & self->block_mask_;\n      size_t prev_ix = bucket[rb_index];\n      const size_t backward = cur_ix - prev_ix;\n      if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n        break;\n      }\n      prev_ix &= ring_buffer_mask;\n      if (cur_ix_masked + best_len > ring_buffer_mask) {\n        break;\n      }\n      if (prev_ix + best_len > ring_buffer_mask ||\n          /* compare 4 bytes ending at best_len + 1 */\n          BrotliUnalignedRead32(&data[cur_ix_masked + best_len - 3]) !=\n              BrotliUnalignedRead32(&data[prev_ix + best_len - 3])) {\n        continue;\n      }\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                    &data[cur_ix_masked],\n                                                    max_length);\n        if (len >= 4) {\n          /* Comparing for >= 3 does not change the semantics, but just saves\n             for a few unnecessary binary logarithms in backward reference\n             score, since we are not interested in such short matches. */\n          score_t score = BackwardReferenceScore(len, backward);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n    bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;\n    tag_bucket[num[key] & self->block_mask_] = tag;\n    --num[key];\n  }\n  if (min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common_, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n#undef HashLongestMatch\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_rolling_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2018 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, JUMP, NUMBUCKETS, MASK, CHUNKLEN */\n/* NUMBUCKETS / (MASK + 1) = probability of storing and using hash code. */\n/* JUMP = skip bytes for speedup */\n\n/* Rolling hash for long distance long string matches. Stores one position\n   per bucket, bucket key is computed over a long region. */\n\n#define HashRolling HASHER()\n\nstatic const uint32_t FN(kRollingHashMul32) = 69069;\nstatic const uint32_t FN(kInvalidPos) = 0xffffffff;\n\n/* This hasher uses a longer forward length, but returning a higher value here\n   will hurt compression by the main hasher when combined with a composite\n   hasher. The hasher tests for forward itself instead. */\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }\n\n/* Computes a code from a single byte. A lookup table of 256 values could be\n   used, but simply adding 1 works about as good. */\nstatic uint32_t FN(HashByte)(uint8_t byte) {\n  return (uint32_t)byte + 1u;\n}\n\nstatic uint32_t FN(HashRollingFunctionInitial)(uint32_t state, uint8_t add,\n                                               uint32_t factor) {\n  return (uint32_t)(factor * state + FN(HashByte)(add));\n}\n\nstatic uint32_t FN(HashRollingFunction)(uint32_t state, uint8_t add,\n                                        uint8_t rem, uint32_t factor,\n                                        uint32_t factor_remove) {\n  return (uint32_t)(factor * state +\n      FN(HashByte)(add) - factor_remove * FN(HashByte)(rem));\n}\n\ntypedef struct HashRolling {\n  uint32_t state;\n  uint32_t* table;\n  size_t next_ix;\n\n  uint32_t chunk_len;\n  uint32_t factor;\n  uint32_t factor_remove;\n} HashRolling;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashRolling* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  size_t i;\n  self->state = 0;\n  self->next_ix = 0;\n\n  self->factor = FN(kRollingHashMul32);\n\n  /* Compute the factor of the oldest byte to remove: factor**steps modulo\n     0xffffffff (the multiplications rely on 32-bit overflow) */\n  self->factor_remove = 1;\n  for (i = 0; i < CHUNKLEN; i += JUMP) {\n    self->factor_remove *= self->factor;\n  }\n\n  self->table = (uint32_t*)common->extra[0];\n  for (i = 0; i < NUMBUCKETS; i++) {\n    self->table[i] = FN(kInvalidPos);\n  }\n\n  BROTLI_UNUSED(params);\n}\n\nstatic void FN(Prepare)(HashRolling* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  size_t i;\n  /* Too small size, cannot use this hasher. */\n  if (input_size < CHUNKLEN) return;\n  self->state = 0;\n  for (i = 0; i < CHUNKLEN; i += JUMP) {\n    self->state = FN(HashRollingFunctionInitial)(\n        self->state, data[i], self->factor);\n  }\n  BROTLI_UNUSED(one_shot);\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  BROTLI_UNUSED(params);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = NUMBUCKETS * sizeof(uint32_t);\n}\n\nstatic BROTLI_INLINE void FN(Store)(HashRolling* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(data);\n  BROTLI_UNUSED(mask);\n  BROTLI_UNUSED(ix);\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashRolling* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(data);\n  BROTLI_UNUSED(mask);\n  BROTLI_UNUSED(ix_start);\n  BROTLI_UNUSED(ix_end);\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashRolling* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ring_buffer_mask) {\n  /* In this case we must re-initialize the hasher from scratch from the\n     current position. */\n  size_t position_masked;\n  size_t available = num_bytes;\n  if ((position & (JUMP - 1)) != 0) {\n    size_t diff = JUMP - (position & (JUMP - 1));\n    available = (diff > available) ? 0 : (available - diff);\n    position += diff;\n  }\n  position_masked = position & ring_buffer_mask;\n  /* wrapping around ringbuffer not handled. */\n  if (available > ring_buffer_mask - position_masked) {\n    available = ring_buffer_mask - position_masked;\n  }\n\n  FN(Prepare)(self, BROTLI_FALSE, available,\n      ringbuffer + (position & ring_buffer_mask));\n  self->next_ix = position;\n  BROTLI_UNUSED(num_bytes);\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashRolling* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(distance_cache);\n}\n\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashRolling* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  size_t pos;\n\n  if ((cur_ix & (JUMP - 1)) != 0) return;\n\n  /* Not enough lookahead */\n  if (max_length < CHUNKLEN) return;\n\n  for (pos = self->next_ix; pos <= cur_ix; pos += JUMP) {\n    uint32_t code = self->state & MASK;\n\n    uint8_t rem = data[pos & ring_buffer_mask];\n    uint8_t add = data[(pos + CHUNKLEN) & ring_buffer_mask];\n    size_t found_ix = FN(kInvalidPos);\n\n    self->state = FN(HashRollingFunction)(\n        self->state, add, rem, self->factor, self->factor_remove);\n\n    if (code < NUMBUCKETS) {\n      found_ix = self->table[code];\n      self->table[code] = (uint32_t)pos;\n      if (pos == cur_ix && found_ix != FN(kInvalidPos)) {\n        /* The cast to 32-bit makes backward distances up to 4GB work even\n           if cur_ix is above 4GB, despite using 32-bit values in the table. */\n        size_t backward = (uint32_t)(cur_ix - found_ix);\n        if (backward <= max_backward) {\n          const size_t found_ix_masked = found_ix & ring_buffer_mask;\n          const size_t len = FindMatchLengthWithLimit(&data[found_ix_masked],\n                                                      &data[cur_ix_masked],\n                                                      max_length);\n          if (len >= 4 && len > out->len) {\n            score_t score = BackwardReferenceScore(len, backward);\n            if (score > out->score) {\n              out->len = len;\n              out->distance = backward;\n              out->score = score;\n              out->len_code_delta = 0;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  self->next_ix = cur_ix + JUMP;\n\n  /* NOTE: this hasher does not search in the dictionary. It is used as\n     backup-hasher, the main hasher already searches in it. */\n  BROTLI_UNUSED(dictionary);\n  BROTLI_UNUSED(distance_cache);\n  BROTLI_UNUSED(dictionary_distance);\n  BROTLI_UNUSED(max_distance);\n}\n\n#undef HashRolling\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/hash_to_binary_tree_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, BUCKET_BITS, MAX_TREE_COMP_LENGTH,\n                        MAX_TREE_SEARCH_DEPTH */\n\n/* A (forgetful) hash table where each hash bucket contains a binary tree of\n   sequences whose first 4 bytes share the same hash code.\n   Each sequence is MAX_TREE_COMP_LENGTH long and is identified by its starting\n   position in the input data. The binary tree is sorted by the lexicographic\n   order of the sequences, and it is also a max-heap with respect to the\n   starting positions. */\n\n#define HashToBinaryTree HASHER()\n\n#define BUCKET_SIZE (1 << BUCKET_BITS)\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) {\n  return MAX_TREE_COMP_LENGTH;\n}\n\nstatic uint32_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - BUCKET_BITS);\n}\n\ntypedef struct HashToBinaryTree {\n  /* The window size minus 1 */\n  size_t window_mask_;\n\n  /* Hash table that maps the 4-byte hashes of the sequence to the last\n     position where this hash was found, which is the root of the binary\n     tree of sequences that share this hash bucket. */\n  uint32_t* buckets_;  /* uint32_t[BUCKET_SIZE]; */\n\n  /* A position used to mark a non-existent sequence, i.e. a tree is empty if\n     its root is at invalid_pos_ and a node is a leaf if both its children\n     are at invalid_pos_. */\n  uint32_t invalid_pos_;\n\n  /* --- Dynamic size members --- */\n\n  /* The union of the binary trees of each hash bucket. The root of the tree\n     corresponding to a hash is a sequence starting at buckets_[hash] and\n     the left and right children of a sequence starting at pos are\n     forest_[2 * pos] and forest_[2 * pos + 1]. */\n  uint32_t* forest_;  /* uint32_t[2 * num_nodes] */\n} HashToBinaryTree;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashToBinaryTree* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->buckets_ = (uint32_t*)common->extra[0];\n  self->forest_ = (uint32_t*)common->extra[1];\n\n  self->window_mask_ = (1u << params->lgwin) - 1u;\n  self->invalid_pos_ = (uint32_t)(0 - self->window_mask_);\n}\n\nstatic void FN(Prepare)\n    (HashToBinaryTree* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t invalid_pos = self->invalid_pos_;\n  uint32_t i;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  BROTLI_UNUSED(data);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  for (i = 0; i < BUCKET_SIZE; i++) {\n    buckets[i] = invalid_pos;\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t num_nodes = (size_t)1 << params->lgwin;\n  if (one_shot && input_size < num_nodes) {\n    num_nodes = input_size;\n  }\n  alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE;\n  alloc_size[1] = 2 * sizeof(uint32_t) * num_nodes;\n}\n\nstatic BROTLI_INLINE size_t FN(LeftChildIndex)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    const size_t pos) {\n  return 2 * (pos & self->window_mask_);\n}\n\nstatic BROTLI_INLINE size_t FN(RightChildIndex)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    const size_t pos) {\n  return 2 * (pos & self->window_mask_) + 1;\n}\n\n/* Stores the hash of the next 4 bytes and in a single tree-traversal, the\n   hash bucket's binary tree is searched for matches and is re-rooted at the\n   current position.\n\n   If less than MAX_TREE_COMP_LENGTH data is available, the hash bucket of the\n   current position is searched for matches, but the state of the hash table\n   is not changed, since we can not know the final sorting order of the\n   current (incomplete) sequence.\n\n   This function must be called with increasing cur_ix positions. */\nstatic BROTLI_INLINE BackwardMatch* FN(StoreAndFindMatches)(\n    HashToBinaryTree* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t cur_ix, const size_t ring_buffer_mask, const size_t max_length,\n    const size_t max_backward, size_t* const BROTLI_RESTRICT best_len,\n    BackwardMatch* BROTLI_RESTRICT matches) {\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  const size_t max_comp_len =\n      BROTLI_MIN(size_t, max_length, MAX_TREE_COMP_LENGTH);\n  const BROTLI_BOOL should_reroot_tree =\n      TO_BROTLI_BOOL(max_length >= MAX_TREE_COMP_LENGTH);\n  const uint32_t key = FN(HashBytes)(&data[cur_ix_masked]);\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  uint32_t* BROTLI_RESTRICT forest = self->forest_;\n  size_t prev_ix = buckets[key];\n  /* The forest index of the rightmost node of the left subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t node_left = FN(LeftChildIndex)(self, cur_ix);\n  /* The forest index of the leftmost node of the right subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t node_right = FN(RightChildIndex)(self, cur_ix);\n  /* The match length of the rightmost node of the left subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t best_len_left = 0;\n  /* The match length of the leftmost node of the right subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t best_len_right = 0;\n  size_t depth_remaining;\n  if (should_reroot_tree) {\n    buckets[key] = (uint32_t)cur_ix;\n  }\n  for (depth_remaining = MAX_TREE_SEARCH_DEPTH; ; --depth_remaining) {\n    const size_t backward = cur_ix - prev_ix;\n    const size_t prev_ix_masked = prev_ix & ring_buffer_mask;\n    if (backward == 0 || backward > max_backward || depth_remaining == 0) {\n      if (should_reroot_tree) {\n        forest[node_left] = self->invalid_pos_;\n        forest[node_right] = self->invalid_pos_;\n      }\n      break;\n    }\n    {\n      const size_t cur_len = BROTLI_MIN(size_t, best_len_left, best_len_right);\n      size_t len;\n      BROTLI_DCHECK(cur_len <= MAX_TREE_COMP_LENGTH);\n      len = cur_len +\n          FindMatchLengthWithLimit(&data[cur_ix_masked + cur_len],\n                                   &data[prev_ix_masked + cur_len],\n                                   max_length - cur_len);\n      BROTLI_DCHECK(\n          0 == memcmp(&data[cur_ix_masked], &data[prev_ix_masked], len));\n      if (matches && len > *best_len) {\n        *best_len = len;\n        InitBackwardMatch(matches++, backward, len);\n      }\n      if (len >= max_comp_len) {\n        if (should_reroot_tree) {\n          forest[node_left] = forest[FN(LeftChildIndex)(self, prev_ix)];\n          forest[node_right] = forest[FN(RightChildIndex)(self, prev_ix)];\n        }\n        break;\n      }\n      if (data[cur_ix_masked + len] > data[prev_ix_masked + len]) {\n        best_len_left = len;\n        if (should_reroot_tree) {\n          forest[node_left] = (uint32_t)prev_ix;\n        }\n        node_left = FN(RightChildIndex)(self, prev_ix);\n        prev_ix = forest[node_left];\n      } else {\n        best_len_right = len;\n        if (should_reroot_tree) {\n          forest[node_right] = (uint32_t)prev_ix;\n        }\n        node_right = FN(LeftChildIndex)(self, prev_ix);\n        prev_ix = forest[node_right];\n      }\n    }\n  }\n  return matches;\n}\n\n/* Finds all backward matches of &data[cur_ix & ring_buffer_mask] up to the\n   length of max_length and stores the position cur_ix in the hash table.\n\n   Sets *num_matches to the number of matches found, and stores the found\n   matches in matches[0] to matches[*num_matches - 1]. The matches will be\n   sorted by strictly increasing length and (non-strictly) increasing\n   distance. */\nstatic BROTLI_INLINE size_t FN(FindAllMatches)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const BrotliEncoderParams* params,\n    BackwardMatch* matches) {\n  BackwardMatch* const orig_matches = matches;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  size_t best_len = 1;\n  const size_t short_match_max_backward =\n      params->quality != HQ_ZOPFLIFICATION_QUALITY ? 16 : 64;\n  size_t stop = cur_ix - short_match_max_backward;\n  uint32_t dict_matches[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1];\n  size_t i;\n  if (cur_ix < short_match_max_backward) { stop = 0; }\n  for (i = cur_ix - 1; i > stop && best_len <= 2; --i) {\n    size_t prev_ix = i;\n    const size_t backward = cur_ix - prev_ix;\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      break;\n    }\n    prev_ix &= ring_buffer_mask;\n    if (data[cur_ix_masked] != data[prev_ix] ||\n        data[cur_ix_masked + 1] != data[prev_ix + 1]) {\n      continue;\n    }\n    {\n      const size_t len =\n          FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked],\n                                   max_length);\n      if (len > best_len) {\n        best_len = len;\n        InitBackwardMatch(matches++, backward, len);\n      }\n    }\n  }\n  if (best_len < max_length) {\n    matches = FN(StoreAndFindMatches)(self, data, cur_ix,\n        ring_buffer_mask, max_length, max_backward, &best_len, matches);\n  }\n  for (i = 0; i <= BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN; ++i) {\n    dict_matches[i] = kInvalidMatch;\n  }\n  {\n    size_t minlen = BROTLI_MAX(size_t, 4, best_len + 1);\n    if (BrotliFindAllStaticDictionaryMatches(dictionary,\n        &data[cur_ix_masked], minlen, max_length, &dict_matches[0])) {\n      size_t maxlen = BROTLI_MIN(\n          size_t, BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN, max_length);\n      size_t l;\n      for (l = minlen; l <= maxlen; ++l) {\n        uint32_t dict_id = dict_matches[l];\n        if (dict_id < kInvalidMatch) {\n          size_t distance = dictionary_distance + (dict_id >> 5) + 1;\n          if (distance <= params->dist.max_distance) {\n            InitDictionaryBackwardMatch(matches++, distance, l, dict_id & 31);\n          }\n        }\n      }\n    }\n  }\n  return (size_t)(matches - orig_matches);\n}\n\n/* Stores the hash of the next 4 bytes and re-roots the binary tree at the\n   current sequence, without returning any matches.\n   REQUIRES: ix + MAX_TREE_COMP_LENGTH <= end-of-current-block */\nstatic BROTLI_INLINE void FN(Store)(HashToBinaryTree* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  /* Maximum distance is window size - 16, see section 9.1. of the spec. */\n  const size_t max_backward = self->window_mask_ - BROTLI_WINDOW_GAP + 1;\n  FN(StoreAndFindMatches)(self, data, ix, mask, MAX_TREE_COMP_LENGTH,\n      max_backward, NULL, NULL);\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashToBinaryTree* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i = ix_start;\n  size_t j = ix_start;\n  if (ix_start + 63 <= ix_end) {\n    i = ix_end - 63;\n  }\n  if (ix_start + 512 <= i) {\n    for (; j < i; j += 8) {\n      FN(Store)(self, data, mask, j);\n    }\n  }\n  for (; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 &&\n      position >= MAX_TREE_COMP_LENGTH) {\n    /* Store the last `MAX_TREE_COMP_LENGTH - 1` positions in the hasher.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    const size_t i_start = position - MAX_TREE_COMP_LENGTH + 1;\n    const size_t i_end = BROTLI_MIN(size_t, position, i_start + num_bytes);\n    size_t i;\n    for (i = i_start; i < i_end; ++i) {\n      /* Maximum distance is window size - 16, see section 9.1. of the spec.\n         Furthermore, we have to make sure that we don't look further back\n         from the start of the next block than the window size, otherwise we\n         could access already overwritten areas of the ring-buffer. */\n      const size_t max_backward =\n          self->window_mask_ - BROTLI_MAX(size_t,\n                                          BROTLI_WINDOW_GAP - 1,\n                                          position - i);\n      /* We know that i + MAX_TREE_COMP_LENGTH <= position + num_bytes, i.e. the\n         end of the current block and that we have at least\n         MAX_TREE_COMP_LENGTH tail in the ring-buffer. */\n      FN(StoreAndFindMatches)(self, ringbuffer, i, ringbuffer_mask,\n          MAX_TREE_COMP_LENGTH, max_backward, NULL, NULL);\n    }\n  }\n}\n\n#undef BUCKET_SIZE\n\n#undef HashToBinaryTree\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/histogram.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Build per-context histograms of literals, commands and distance codes. */\n\n#include \"histogram.h\"\n\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"block_splitter.h\"\n#include \"command.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BlockSplitIterator {\n  const BlockSplit* split_;  /* Not owned. */\n  size_t idx_;\n  size_t type_;\n  size_t length_;\n} BlockSplitIterator;\n\nstatic void InitBlockSplitIterator(BlockSplitIterator* self,\n    const BlockSplit* split) {\n  self->split_ = split;\n  self->idx_ = 0;\n  self->type_ = 0;\n  self->length_ = split->lengths ? split->lengths[0] : 0;\n}\n\nstatic void BlockSplitIteratorNext(BlockSplitIterator* self) {\n  if (self->length_ == 0) {\n    ++self->idx_;\n    self->type_ = self->split_->types[self->idx_];\n    self->length_ = self->split_->lengths[self->idx_];\n  }\n  --self->length_;\n}\n\nvoid BrotliBuildHistogramsWithContext(\n    const Command* cmds, const size_t num_commands,\n    const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split,\n    const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos,\n    size_t mask, uint8_t prev_byte, uint8_t prev_byte2,\n    const ContextType* context_modes, HistogramLiteral* literal_histograms,\n    HistogramCommand* insert_and_copy_histograms,\n    HistogramDistance* copy_dist_histograms) {\n  size_t pos = start_pos;\n  BlockSplitIterator literal_it;\n  BlockSplitIterator insert_and_copy_it;\n  BlockSplitIterator dist_it;\n  size_t i;\n\n  InitBlockSplitIterator(&literal_it, literal_split);\n  InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split);\n  InitBlockSplitIterator(&dist_it, dist_split);\n  for (i = 0; i < num_commands; ++i) {\n    const Command* cmd = &cmds[i];\n    size_t j;\n    BlockSplitIteratorNext(&insert_and_copy_it);\n    HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_],\n        cmd->cmd_prefix_);\n    /* TODO(eustas): unwrap iterator blocks. */\n    for (j = cmd->insert_len_; j != 0; --j) {\n      size_t context;\n      BlockSplitIteratorNext(&literal_it);\n      context = literal_it.type_;\n      if (context_modes) {\n        ContextLut lut = BROTLI_CONTEXT_LUT(context_modes[context]);\n        context = (context << BROTLI_LITERAL_CONTEXT_BITS) +\n            BROTLI_CONTEXT(prev_byte, prev_byte2, lut);\n      }\n      HistogramAddLiteral(&literal_histograms[context],\n          ringbuffer[pos & mask]);\n      prev_byte2 = prev_byte;\n      prev_byte = ringbuffer[pos & mask];\n      ++pos;\n    }\n    pos += CommandCopyLen(cmd);\n    if (CommandCopyLen(cmd)) {\n      prev_byte2 = ringbuffer[(pos - 2) & mask];\n      prev_byte = ringbuffer[(pos - 1) & mask];\n      if (cmd->cmd_prefix_ >= 128) {\n        size_t context;\n        BlockSplitIteratorNext(&dist_it);\n        context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) +\n            CommandDistanceContext(cmd);\n        HistogramAddDistance(&copy_dist_histograms[context],\n            cmd->dist_prefix_ & 0x3FF);\n      }\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/histogram.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Models the histograms of literals, commands and distance codes. */\n\n#ifndef BROTLI_ENC_HISTOGRAM_H_\n#define BROTLI_ENC_HISTOGRAM_H_\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"block_splitter.h\"\n#include \"command.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* The distance symbols effectively used by \"Large Window Brotli\" (32-bit). */\n#define BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS 544\n\n#define FN(X) X ## Literal\n#define DATA_SIZE BROTLI_NUM_LITERAL_SYMBOLS\n#define DataType uint8_t\n#include \"histogram_inc.h\"  /* NOLINT(build/include) */\n#undef DataType\n#undef DATA_SIZE\n#undef FN\n\n#define FN(X) X ## Command\n#define DataType uint16_t\n#define DATA_SIZE BROTLI_NUM_COMMAND_SYMBOLS\n#include \"histogram_inc.h\"  /* NOLINT(build/include) */\n#undef DATA_SIZE\n#undef FN\n\n#define FN(X) X ## Distance\n#define DATA_SIZE BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS\n#include \"histogram_inc.h\"  /* NOLINT(build/include) */\n#undef DataType\n#undef DATA_SIZE\n#undef FN\n\nBROTLI_INTERNAL void BrotliBuildHistogramsWithContext(\n    const Command* cmds, const size_t num_commands,\n    const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split,\n    const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t pos,\n    size_t mask, uint8_t prev_byte, uint8_t prev_byte2,\n    const ContextType* context_modes, HistogramLiteral* literal_histograms,\n    HistogramCommand* insert_and_copy_histograms,\n    HistogramDistance* copy_dist_histograms);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_HISTOGRAM_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/histogram_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: Histogram, DATA_SIZE, DataType */\n\n/* A simple container for histograms of data in blocks. */\n\ntypedef struct FN(Histogram) {\n  uint32_t data_[DATA_SIZE];\n  size_t total_count_;\n  double bit_cost_;\n} FN(Histogram);\n\nstatic BROTLI_INLINE void FN(HistogramClear)(FN(Histogram)* self) {\n  memset(self->data_, 0, sizeof(self->data_));\n  self->total_count_ = 0;\n  self->bit_cost_ = HUGE_VAL;\n}\n\nstatic BROTLI_INLINE void FN(ClearHistograms)(\n    FN(Histogram)* array, size_t length) {\n  size_t i;\n  for (i = 0; i < length; ++i) FN(HistogramClear)(array + i);\n}\n\nstatic BROTLI_INLINE void FN(HistogramAdd)(FN(Histogram)* self, size_t val) {\n  ++self->data_[val];\n  ++self->total_count_;\n}\n\nstatic BROTLI_INLINE void FN(HistogramAddVector)(FN(Histogram)* self,\n    const DataType* p, size_t n) {\n  self->total_count_ += n;\n  n += 1;\n  while (--n) ++self->data_[*p++];\n}\n\nstatic BROTLI_INLINE void FN(HistogramAddHistogram)(FN(Histogram)* self,\n    const FN(Histogram)* v) {\n  size_t i;\n  self->total_count_ += v->total_count_;\n  for (i = 0; i < DATA_SIZE; ++i) {\n    self->data_[i] += v->data_[i];\n  }\n}\n\nstatic BROTLI_INLINE size_t FN(HistogramDataSize)(void) { return DATA_SIZE; }\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/literal_cost.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Literal cost model to allow backward reference replacement to be efficient.\n*/\n\n#include \"literal_cost.h\"\n\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n#include \"utf8_util.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic size_t UTF8Position(size_t last, size_t c, size_t clamp) {\n  if (c < 128) {\n    return 0;  /* Next one is the 'Byte 1' again. */\n  } else if (c >= 192) {  /* Next one is the 'Byte 2' of utf-8 encoding. */\n    return BROTLI_MIN(size_t, 1, clamp);\n  } else {\n    /* Let's decide over the last byte if this ends the sequence. */\n    if (last < 0xE0) {\n      return 0;  /* Completed two or three byte coding. */\n    } else {  /* Next one is the 'Byte 3' of utf-8 encoding. */\n      return BROTLI_MIN(size_t, 2, clamp);\n    }\n  }\n}\n\nstatic size_t DecideMultiByteStatsLevel(size_t pos, size_t len, size_t mask,\n                                        const uint8_t* data) {\n  size_t counts[3] = { 0 };\n  size_t max_utf8 = 1;  /* should be 2, but 1 compresses better. */\n  size_t last_c = 0;\n  size_t i;\n  for (i = 0; i < len; ++i) {\n    size_t c = data[(pos + i) & mask];\n    ++counts[UTF8Position(last_c, c, 2)];\n    last_c = c;\n  }\n  if (counts[2] < 500) {\n    max_utf8 = 1;\n  }\n  if (counts[1] + counts[2] < 25) {\n    max_utf8 = 0;\n  }\n  return max_utf8;\n}\n\nstatic void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,\n                                            const uint8_t* data,\n                                            size_t* histogram, float* cost) {\n  /* max_utf8 is 0 (normal ASCII single byte modeling),\n     1 (for 2-byte UTF-8 modeling), or 2 (for 3-byte UTF-8 modeling). */\n  const size_t max_utf8 = DecideMultiByteStatsLevel(pos, len, mask, data);\n  size_t window_half = 495;\n  size_t in_window = BROTLI_MIN(size_t, window_half, len);\n  size_t in_window_utf8[3] = { 0 };\n  size_t i;\n  memset(histogram, 0, 3 * 256 * sizeof(histogram[0]));\n\n  {  /* Bootstrap histograms. */\n    size_t last_c = 0;\n    size_t utf8_pos = 0;\n    for (i = 0; i < in_window; ++i) {\n      size_t c = data[(pos + i) & mask];\n      ++histogram[256 * utf8_pos + c];\n      ++in_window_utf8[utf8_pos];\n      utf8_pos = UTF8Position(last_c, c, max_utf8);\n      last_c = c;\n    }\n  }\n\n  /* Compute bit costs with sliding window. */\n  for (i = 0; i < len; ++i) {\n    if (i >= window_half) {\n      /* Remove a byte in the past. */\n      size_t c =\n          i < window_half + 1 ? 0 : data[(pos + i - window_half - 1) & mask];\n      size_t last_c =\n          i < window_half + 2 ? 0 : data[(pos + i - window_half - 2) & mask];\n      size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8);\n      --histogram[256 * utf8_pos2 + data[(pos + i - window_half) & mask]];\n      --in_window_utf8[utf8_pos2];\n    }\n    if (i + window_half < len) {\n      /* Add a byte in the future. */\n      size_t c = data[(pos + i + window_half - 1) & mask];\n      size_t last_c = data[(pos + i + window_half - 2) & mask];\n      size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8);\n      ++histogram[256 * utf8_pos2 + data[(pos + i + window_half) & mask]];\n      ++in_window_utf8[utf8_pos2];\n    }\n    {\n      size_t c = i < 1 ? 0 : data[(pos + i - 1) & mask];\n      size_t last_c = i < 2 ? 0 : data[(pos + i - 2) & mask];\n      size_t utf8_pos = UTF8Position(last_c, c, max_utf8);\n      size_t masked_pos = (pos + i) & mask;\n      size_t histo = histogram[256 * utf8_pos + data[masked_pos]];\n      static const size_t prologue_length = 2000;\n      static const double multiplier = 0.35 / 2000;\n      double lit_cost;\n      if (histo == 0) {\n        histo = 1;\n      }\n      lit_cost = FastLog2(in_window_utf8[utf8_pos]) - FastLog2(histo);\n      lit_cost += 0.02905;\n      if (lit_cost < 1.0) {\n        lit_cost *= 0.5;\n        lit_cost += 0.5;\n      }\n      /* Make the first bytes more expensive -- seems to help, not sure why.\n         Perhaps because the entropy source is changing its properties\n         rapidly in the beginning of the file, perhaps because the beginning\n         of the data is a statistical \"anomaly\". */\n      if (i < prologue_length) {\n        lit_cost += 0.35 + multiplier * (double)i;\n      }\n      cost[i] = (float)lit_cost;\n    }\n  }\n}\n\nvoid BrotliEstimateBitCostsForLiterals(size_t pos, size_t len, size_t mask,\n                                       const uint8_t* data,\n                                       size_t* histogram, float* cost) {\n  if (BrotliIsMostlyUTF8(data, pos, mask, len, kMinUTF8Ratio)) {\n    EstimateBitCostsForLiteralsUTF8(pos, len, mask, data, histogram, cost);\n    return;\n  } else {\n    size_t window_half = 2000;\n    size_t in_window = BROTLI_MIN(size_t, window_half, len);\n    size_t i;\n    memset(histogram, 0, 256 * sizeof(histogram[0]));\n\n    /* Bootstrap histogram. */\n    for (i = 0; i < in_window; ++i) {\n      ++histogram[data[(pos + i) & mask]];\n    }\n\n    /* Compute bit costs with sliding window. */\n    for (i = 0; i < len; ++i) {\n      size_t histo;\n      if (i >= window_half) {\n        /* Remove a byte in the past. */\n        --histogram[data[(pos + i - window_half) & mask]];\n        --in_window;\n      }\n      if (i + window_half < len) {\n        /* Add a byte in the future. */\n        ++histogram[data[(pos + i + window_half) & mask]];\n        ++in_window;\n      }\n      histo = histogram[data[(pos + i) & mask]];\n      if (histo == 0) {\n        histo = 1;\n      }\n      {\n        double lit_cost = FastLog2(in_window) - FastLog2(histo);\n        lit_cost += 0.029;\n        if (lit_cost < 1.0) {\n          lit_cost *= 0.5;\n          lit_cost += 0.5;\n        }\n        cost[i] = (float)lit_cost;\n      }\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/literal_cost.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Literal cost model to allow backward reference replacement to be efficient.\n*/\n\n#ifndef BROTLI_ENC_LITERAL_COST_H_\n#define BROTLI_ENC_LITERAL_COST_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Estimates how many bits the literals in the interval [pos, pos + len) in the\n   ring-buffer (data, mask) will take entropy coded and writes these estimates\n   to the cost[0..len) array. */\nBROTLI_INTERNAL void BrotliEstimateBitCostsForLiterals(\n    size_t pos, size_t len, size_t mask, const uint8_t* data, size_t* histogram,\n    float* cost);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_LITERAL_COST_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/matching_tag_mask.h",
    "content": "﻿#ifndef THIRD_PARTY_BROTLI_ENC_MATCHING_TAG_MASK_H_\n#define THIRD_PARTY_BROTLI_ENC_MATCHING_TAG_MASK_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__SSE2__) || defined(_M_AMD64) || \\\n    (defined(_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))\n#define SUPPORTS_SSE_2\n#endif\n\n#if defined(SUPPORTS_SSE_2)\n#include <immintrin.h>\n#endif\n\n\nstatic BROTLI_INLINE uint64_t GetMatchingTagMask(\n    size_t chunk_count, const uint8_t tag,\n    const uint8_t* BROTLI_RESTRICT tag_bucket, const size_t head) {\n  uint64_t matches = 0;\n#if defined(SUPPORTS_SSE_2)\n  const __m128i comparison_mask = _mm_set1_epi8((char)tag);\n  size_t i;\n  for (i = 0; i < chunk_count && i < 4; i++) {\n    const __m128i chunk =\n        _mm_loadu_si128((const __m128i*)(const void*)(tag_bucket + 16 * i));\n    const __m128i equal_mask = _mm_cmpeq_epi8(chunk, comparison_mask);\n    matches |= (uint64_t)_mm_movemask_epi8(equal_mask) << 16 * i;\n  }\n#else\n  const int chunk_size = sizeof(size_t);\n  const size_t shift_amount = ((chunk_size * 8) - chunk_size);\n  const size_t xFF = ~((size_t)0);\n  const size_t x01 = xFF / 0xFF;\n  const size_t x80 = x01 << 7;\n  const size_t splat_char = tag * x01;\n  int i = ((int)chunk_count * 16) - chunk_size;\n  BROTLI_DCHECK((sizeof(size_t) == 4) || (sizeof(size_t) == 8));\n#if BROTLI_LITTLE_ENDIAN\n  const size_t extractMagic = (xFF / 0x7F) >> chunk_size;\n  do {\n      size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);\n      chunk ^= splat_char;\n      chunk = (((chunk | x80) - x01) | chunk) & x80;\n      matches <<= chunk_size;\n      matches |= (chunk * extractMagic) >> shift_amount;\n      i -= chunk_size;\n  } while (i >= 0);\n#else\n  const size_t msb = xFF ^ (xFF >> 1);\n  const size_t extractMagic = (msb / 0x1FF) | msb;\n  do {\n      size_t chunk = BrotliUnalignedReadSizeT(&tag_bucket[i]);\n      chunk ^= splat_char;\n      chunk = (((chunk | x80) - x01) | chunk) & x80;\n      matches <<= chunk_size;\n      matches |= ((chunk >> 7) * extractMagic) >> shift_amount;\n      i -= chunk_size;\n  } while (i >= 0);\n#endif\n  matches = ~matches;\n#endif\n  if (chunk_count == 1) return BrotliRotateRight16((uint16_t)matches, head);\n  if (chunk_count == 2) return BrotliRotateRight32((uint32_t)matches, head);\n  return BrotliRotateRight64(matches, head);\n}\n\n#undef SUPPORTS_SSE_2\n\n#endif  // THIRD_PARTY_BROTLI_ENC_MATCHING_TAG_MASK_H_\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/memory.c",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Algorithms for distributing the literals and commands of a metablock between\n   block types and contexts. */\n\n#include \"memory.h\"\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_NEW_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2)\n#define MAX_NEW_FREED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2)\n#define MAX_PERM_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 1)\n\n#define PERM_ALLOCATED_OFFSET 0\n#define NEW_ALLOCATED_OFFSET MAX_PERM_ALLOCATED\n#define NEW_FREED_OFFSET (MAX_PERM_ALLOCATED + MAX_NEW_ALLOCATED)\n\nvoid BrotliInitMemoryManager(\n    MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func,\n    void* opaque) {\n  if (!alloc_func) {\n    m->alloc_func = BrotliDefaultAllocFunc;\n    m->free_func = BrotliDefaultFreeFunc;\n    m->opaque = 0;\n  } else {\n    m->alloc_func = alloc_func;\n    m->free_func = free_func;\n    m->opaque = opaque;\n  }\n#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n  m->is_oom = BROTLI_FALSE;\n  m->perm_allocated = 0;\n  m->new_allocated = 0;\n  m->new_freed = 0;\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n}\n\n#if defined(BROTLI_ENCODER_EXIT_ON_OOM)\n\nvoid* BrotliAllocate(MemoryManager* m, size_t n) {\n  void* result = m->alloc_func(m->opaque, n);\n  if (!result) exit(EXIT_FAILURE);\n  return result;\n}\n\nvoid BrotliFree(MemoryManager* m, void* p) {\n  m->free_func(m->opaque, p);\n}\n\nvoid BrotliWipeOutMemoryManager(MemoryManager* m) {\n  BROTLI_UNUSED(m);\n}\n\n#else  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\nstatic void SortPointers(void** items, const size_t n) {\n  /* Shell sort. */\n  /* TODO(eustas): fine-tune for \"many slots\" case */\n  static const size_t gaps[] = {23, 10, 4, 1};\n  int g = 0;\n  for (; g < 4; ++g) {\n    size_t gap = gaps[g];\n    size_t i;\n    for (i = gap; i < n; ++i) {\n      size_t j = i;\n      void* tmp = items[i];\n      for (; j >= gap && tmp < items[j - gap]; j -= gap) {\n        items[j] = items[j - gap];\n      }\n      items[j] = tmp;\n    }\n  }\n}\n\nstatic size_t Annihilate(void** a, size_t a_len, void** b, size_t b_len) {\n  size_t a_read_index = 0;\n  size_t b_read_index = 0;\n  size_t a_write_index = 0;\n  size_t b_write_index = 0;\n  size_t annihilated = 0;\n  while (a_read_index < a_len && b_read_index < b_len) {\n    if (a[a_read_index] == b[b_read_index]) {\n      a_read_index++;\n      b_read_index++;\n      annihilated++;\n    } else if (a[a_read_index] < b[b_read_index]) {\n      a[a_write_index++] = a[a_read_index++];\n    } else {\n      b[b_write_index++] = b[b_read_index++];\n    }\n  }\n  while (a_read_index < a_len) a[a_write_index++] = a[a_read_index++];\n  while (b_read_index < b_len) b[b_write_index++] = b[b_read_index++];\n  return annihilated;\n}\n\nstatic void CollectGarbagePointers(MemoryManager* m) {\n  size_t annihilated;\n  SortPointers(m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated);\n  SortPointers(m->pointers + NEW_FREED_OFFSET, m->new_freed);\n  annihilated = Annihilate(\n      m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated,\n      m->pointers + NEW_FREED_OFFSET, m->new_freed);\n  m->new_allocated -= annihilated;\n  m->new_freed -= annihilated;\n\n  if (m->new_freed != 0) {\n    annihilated = Annihilate(\n        m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated,\n        m->pointers + NEW_FREED_OFFSET, m->new_freed);\n    m->perm_allocated -= annihilated;\n    m->new_freed -= annihilated;\n    BROTLI_DCHECK(m->new_freed == 0);\n  }\n\n  if (m->new_allocated != 0) {\n    BROTLI_DCHECK(m->perm_allocated + m->new_allocated <= MAX_PERM_ALLOCATED);\n    memcpy(m->pointers + PERM_ALLOCATED_OFFSET + m->perm_allocated,\n           m->pointers + NEW_ALLOCATED_OFFSET,\n           sizeof(void*) * m->new_allocated);\n    m->perm_allocated += m->new_allocated;\n    m->new_allocated = 0;\n    SortPointers(m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated);\n  }\n}\n\nvoid* BrotliAllocate(MemoryManager* m, size_t n) {\n  void* result = m->alloc_func(m->opaque, n);\n  if (!result) {\n    m->is_oom = BROTLI_TRUE;\n    return NULL;\n  }\n  if (m->new_allocated == MAX_NEW_ALLOCATED) CollectGarbagePointers(m);\n  m->pointers[NEW_ALLOCATED_OFFSET + (m->new_allocated++)] = result;\n  return result;\n}\n\nvoid BrotliFree(MemoryManager* m, void* p) {\n  if (!p) return;\n  m->free_func(m->opaque, p);\n  if (m->new_freed == MAX_NEW_FREED) CollectGarbagePointers(m);\n  m->pointers[NEW_FREED_OFFSET + (m->new_freed++)] = p;\n}\n\nvoid BrotliWipeOutMemoryManager(MemoryManager* m) {\n  size_t i;\n  CollectGarbagePointers(m);\n  /* Now all unfreed pointers are in perm-allocated list. */\n  for (i = 0; i < m->perm_allocated; ++i) {\n    m->free_func(m->opaque, m->pointers[PERM_ALLOCATED_OFFSET + i]);\n  }\n  m->perm_allocated = 0;\n}\n\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\nvoid* BrotliBootstrapAlloc(size_t size,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  if (!alloc_func && !free_func) {\n    return malloc(size);\n  } else if (alloc_func && free_func) {\n    return alloc_func(opaque, size);\n  }\n  return NULL;\n}\n\nvoid BrotliBootstrapFree(void* address, MemoryManager* m) {\n  if (!address) {\n    /* Should not happen! */\n    return;\n  } else {\n    /* Copy values, as those would be freed. */\n    brotli_free_func free_func = m->free_func;\n    void* opaque = m->opaque;\n    free_func(opaque, address);\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/memory.h",
    "content": "﻿/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Macros for memory management. */\n\n#ifndef BROTLI_ENC_MEMORY_H_\n#define BROTLI_ENC_MEMORY_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if !defined(BROTLI_ENCODER_CLEANUP_ON_OOM) && \\\n    !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#define BROTLI_ENCODER_EXIT_ON_OOM\n#endif\n\n#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#if defined(BROTLI_EXPERIMENTAL)\n#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS (48*1024)\n#else  /* BROTLI_EXPERIMENTAL */\n#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 256\n#endif  /* BROTLI_EXPERIMENTAL */\n#else /* BROTLI_ENCODER_EXIT_ON_OOM */\n#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 0\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\ntypedef struct MemoryManager {\n  brotli_alloc_func alloc_func;\n  brotli_free_func free_func;\n  void* opaque;\n#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n  BROTLI_BOOL is_oom;\n  size_t perm_allocated;\n  size_t new_allocated;\n  size_t new_freed;\n  void* pointers[BROTLI_ENCODER_MEMORY_MANAGER_SLOTS];\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n} MemoryManager;\n\nBROTLI_INTERNAL void BrotliInitMemoryManager(\n    MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func,\n    void* opaque);\n\nBROTLI_INTERNAL void* BrotliAllocate(MemoryManager* m, size_t n);\n#define BROTLI_ALLOC(M, T, N)                               \\\n  ((N) > 0 ? ((T*)BrotliAllocate((M), (N) * sizeof(T))) : NULL)\n\nBROTLI_INTERNAL void BrotliFree(MemoryManager* m, void* p);\n#define BROTLI_FREE(M, P) { \\\n  BrotliFree((M), (P));     \\\n  P = NULL;                 \\\n}\n\n#if defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#define BROTLI_IS_OOM(M) (!!0)\n#else  /* BROTLI_ENCODER_EXIT_ON_OOM */\n#define BROTLI_IS_OOM(M) (!!(M)->is_oom)\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\n/*\nBROTLI_IS_NULL is a fake check, BROTLI_IS_OOM does the heavy lifting.\nThe only purpose of it is to explain static analyzers the state of things.\nNB: use ONLY together with BROTLI_IS_OOM\n    AND ONLY for allocations in the current scope.\n */\n#if defined(__clang_analyzer__) && !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#define BROTLI_IS_NULL(A) ((A) == nullptr)\n#else  /* defined(__clang_analyzer__) */\n#define BROTLI_IS_NULL(A) (!!0)\n#endif  /* defined(__clang_analyzer__) */\n\nBROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m);\n\n/*\nDynamically grows array capacity to at least the requested size\nM: MemoryManager\nT: data type\nA: array\nC: capacity\nR: requested size\n*/\n#define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) {                    \\\n  if (C < (R)) {                                                   \\\n    size_t _new_size = (C == 0) ? (R) : C;                         \\\n    T* new_array;                                                  \\\n    while (_new_size < (R)) _new_size *= 2;                        \\\n    new_array = BROTLI_ALLOC((M), T, _new_size);                   \\\n    if (!BROTLI_IS_OOM(M) && !BROTLI_IS_NULL(new_array) && C != 0) \\\n      memcpy(new_array, A, C * sizeof(T));                         \\\n    BROTLI_FREE((M), A);                                           \\\n    A = new_array;                                                 \\\n    C = _new_size;                                                 \\\n  }                                                                \\\n}\n\n/*\nAppends value and dynamically grows array capacity when needed\nM: MemoryManager\nT: data type\nA: array\nC: array capacity\nS: array size\nV: value to append\n*/\n#define BROTLI_ENSURE_CAPACITY_APPEND(M, T, A, C, S, V) { \\\n  (S)++;                                                  \\\n  BROTLI_ENSURE_CAPACITY(M, T, A, C, S);                  \\\n  A[(S) - 1] = (V);                                       \\\n}\n\n/* \"Bootstrap\" allocations are not tracked by memory manager; should be used\n   only to allocate MemoryManager itself (or structure containing it). */\nBROTLI_INTERNAL void* BrotliBootstrapAlloc(size_t size,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\nBROTLI_INTERNAL void BrotliBootstrapFree(void* address, MemoryManager* m);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_MEMORY_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/metablock.c",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Algorithms for distributing the literals and commands of a metablock between\n   block types and contexts. */\n\n#include \"metablock.h\"\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"\n#include \"block_splitter.h\"\n#include \"cluster.h\"\n#include \"command.h\"\n#include \"entropy_encode.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"params.h\"\n#include \"prefix.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nvoid BrotliInitDistanceParams(BrotliDistanceParams* dist_params,\n    uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window) {\n  uint32_t alphabet_size_max;\n  uint32_t alphabet_size_limit;\n  uint32_t max_distance;\n\n  dist_params->distance_postfix_bits = npostfix;\n  dist_params->num_direct_distance_codes = ndirect;\n\n  alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n      npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);\n  alphabet_size_limit = alphabet_size_max;\n  max_distance = ndirect + (1U << (BROTLI_MAX_DISTANCE_BITS + npostfix + 2)) -\n      (1U << (npostfix + 2));\n\n  if (large_window) {\n    BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(\n        BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect);\n    alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n        npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);\n    alphabet_size_limit = limit.max_alphabet_size;\n    max_distance = limit.max_distance;\n  }\n\n  dist_params->alphabet_size_max = alphabet_size_max;\n  dist_params->alphabet_size_limit = alphabet_size_limit;\n  dist_params->max_distance = max_distance;\n}\n\nstatic void RecomputeDistancePrefixes(Command* cmds,\n                                      size_t num_commands,\n                                      const BrotliDistanceParams* orig_params,\n                                      const BrotliDistanceParams* new_params) {\n  size_t i;\n\n  if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&\n      orig_params->num_direct_distance_codes ==\n      new_params->num_direct_distance_codes) {\n    return;\n  }\n\n  for (i = 0; i < num_commands; ++i) {\n    Command* cmd = &cmds[i];\n    if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {\n      PrefixEncodeCopyDistance(CommandRestoreDistanceCode(cmd, orig_params),\n                               new_params->num_direct_distance_codes,\n                               new_params->distance_postfix_bits,\n                               &cmd->dist_prefix_,\n                               &cmd->dist_extra_);\n    }\n  }\n}\n\nstatic BROTLI_BOOL ComputeDistanceCost(const Command* cmds,\n                                       size_t num_commands,\n                                       const BrotliDistanceParams* orig_params,\n                                       const BrotliDistanceParams* new_params,\n                                       double* cost,\n                                       HistogramDistance* tmp) {\n  size_t i;\n  BROTLI_BOOL equal_params = BROTLI_FALSE;\n  uint16_t dist_prefix;\n  uint32_t dist_extra;\n  double extra_bits = 0.0;\n  HistogramClearDistance(tmp);\n\n  if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&\n      orig_params->num_direct_distance_codes ==\n      new_params->num_direct_distance_codes) {\n    equal_params = BROTLI_TRUE;\n  }\n\n  for (i = 0; i < num_commands; i++) {\n    const Command* cmd = &cmds[i];\n    if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {\n      if (equal_params) {\n        dist_prefix = cmd->dist_prefix_;\n      } else {\n        uint32_t distance = CommandRestoreDistanceCode(cmd, orig_params);\n        if (distance > new_params->max_distance) {\n          return BROTLI_FALSE;\n        }\n        PrefixEncodeCopyDistance(distance,\n                                 new_params->num_direct_distance_codes,\n                                 new_params->distance_postfix_bits,\n                                 &dist_prefix,\n                                 &dist_extra);\n      }\n      HistogramAddDistance(tmp, dist_prefix & 0x3FF);\n      extra_bits += dist_prefix >> 10;\n    }\n  }\n\n  *cost = BrotliPopulationCostDistance(tmp) + extra_bits;\n  return BROTLI_TRUE;\n}\n\nvoid BrotliBuildMetaBlock(MemoryManager* m,\n                          const uint8_t* ringbuffer,\n                          const size_t pos,\n                          const size_t mask,\n                          BrotliEncoderParams* params,\n                          uint8_t prev_byte,\n                          uint8_t prev_byte2,\n                          Command* cmds,\n                          size_t num_commands,\n                          ContextType literal_context_mode,\n                          MetaBlockSplit* mb) {\n  /* Histogram ids need to fit in one byte. */\n  static const size_t kMaxNumberOfHistograms = 256;\n  HistogramDistance* distance_histograms;\n  HistogramLiteral* literal_histograms;\n  ContextType* literal_context_modes = NULL;\n  size_t literal_histograms_size;\n  size_t distance_histograms_size;\n  size_t i;\n  size_t literal_context_multiplier = 1;\n  uint32_t npostfix;\n  uint32_t ndirect_msb = 0;\n  BROTLI_BOOL check_orig = BROTLI_TRUE;\n  double best_dist_cost = 1e99;\n  BrotliDistanceParams orig_params = params->dist;\n  BrotliDistanceParams new_params = params->dist;\n  HistogramDistance* tmp = BROTLI_ALLOC(m, HistogramDistance, 1);\n\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return;\n\n  for (npostfix = 0; npostfix <= BROTLI_MAX_NPOSTFIX; npostfix++) {\n    for (; ndirect_msb < 16; ndirect_msb++) {\n      uint32_t ndirect = ndirect_msb << npostfix;\n      BROTLI_BOOL skip;\n      double dist_cost;\n      BrotliInitDistanceParams(&new_params, npostfix, ndirect,\n                               params->large_window);\n      if (npostfix == orig_params.distance_postfix_bits &&\n          ndirect == orig_params.num_direct_distance_codes) {\n        check_orig = BROTLI_FALSE;\n      }\n      skip = !ComputeDistanceCost(\n          cmds, num_commands, &orig_params, &new_params, &dist_cost, tmp);\n      if (skip || (dist_cost > best_dist_cost)) {\n        break;\n      }\n      best_dist_cost = dist_cost;\n      params->dist = new_params;\n    }\n    if (ndirect_msb > 0) ndirect_msb--;\n    ndirect_msb /= 2;\n  }\n  if (check_orig) {\n    double dist_cost;\n    ComputeDistanceCost(cmds, num_commands, &orig_params, &orig_params,\n                        &dist_cost, tmp);\n    if (dist_cost < best_dist_cost) {\n      /* NB: currently unused; uncomment when more param tuning is added. */\n      /* best_dist_cost = dist_cost; */\n      params->dist = orig_params;\n    }\n  }\n  BROTLI_FREE(m, tmp);\n  RecomputeDistancePrefixes(cmds, num_commands, &orig_params, &params->dist);\n\n  BrotliSplitBlock(m, cmds, num_commands,\n                   ringbuffer, pos, mask, params,\n                   &mb->literal_split,\n                   &mb->command_split,\n                   &mb->distance_split);\n  if (BROTLI_IS_OOM(m)) return;\n\n  if (!params->disable_literal_context_modeling) {\n    literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS;\n    literal_context_modes =\n        BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_context_modes)) return;\n    for (i = 0; i < mb->literal_split.num_types; ++i) {\n      literal_context_modes[i] = literal_context_mode;\n    }\n  }\n\n  literal_histograms_size =\n      mb->literal_split.num_types * literal_context_multiplier;\n  literal_histograms =\n      BROTLI_ALLOC(m, HistogramLiteral, literal_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_histograms)) return;\n  ClearHistogramsLiteral(literal_histograms, literal_histograms_size);\n\n  distance_histograms_size =\n      mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;\n  distance_histograms =\n      BROTLI_ALLOC(m, HistogramDistance, distance_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_histograms)) return;\n  ClearHistogramsDistance(distance_histograms, distance_histograms_size);\n\n  BROTLI_DCHECK(mb->command_histograms == 0);\n  mb->command_histograms_size = mb->command_split.num_types;\n  mb->command_histograms =\n      BROTLI_ALLOC(m, HistogramCommand, mb->command_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->command_histograms)) return;\n  ClearHistogramsCommand(mb->command_histograms, mb->command_histograms_size);\n\n  BrotliBuildHistogramsWithContext(cmds, num_commands,\n      &mb->literal_split, &mb->command_split, &mb->distance_split,\n      ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes,\n      literal_histograms, mb->command_histograms, distance_histograms);\n  BROTLI_FREE(m, literal_context_modes);\n\n  BROTLI_DCHECK(mb->literal_context_map == 0);\n  mb->literal_context_map_size =\n      mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;\n  mb->literal_context_map =\n      BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return;\n\n  BROTLI_DCHECK(mb->literal_histograms == 0);\n  mb->literal_histograms_size = mb->literal_context_map_size;\n  mb->literal_histograms =\n      BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_histograms)) return;\n\n  BrotliClusterHistogramsLiteral(m, literal_histograms, literal_histograms_size,\n      kMaxNumberOfHistograms, mb->literal_histograms,\n      &mb->literal_histograms_size, mb->literal_context_map);\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_FREE(m, literal_histograms);\n\n  if (params->disable_literal_context_modeling) {\n    /* Distribute assignment to all contexts. */\n    for (i = mb->literal_split.num_types; i != 0;) {\n      size_t j = 0;\n      i--;\n      for (; j < (1 << BROTLI_LITERAL_CONTEXT_BITS); j++) {\n        mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =\n            mb->literal_context_map[i];\n      }\n    }\n  }\n\n  BROTLI_DCHECK(mb->distance_context_map == 0);\n  mb->distance_context_map_size =\n      mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;\n  mb->distance_context_map =\n      BROTLI_ALLOC(m, uint32_t, mb->distance_context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_context_map)) return;\n\n  BROTLI_DCHECK(mb->distance_histograms == 0);\n  mb->distance_histograms_size = mb->distance_context_map_size;\n  mb->distance_histograms =\n      BROTLI_ALLOC(m, HistogramDistance, mb->distance_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_histograms)) return;\n\n  BrotliClusterHistogramsDistance(m, distance_histograms,\n                                  mb->distance_context_map_size,\n                                  kMaxNumberOfHistograms,\n                                  mb->distance_histograms,\n                                  &mb->distance_histograms_size,\n                                  mb->distance_context_map);\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_FREE(m, distance_histograms);\n}\n\n#define FN(X) X ## Literal\n#include \"metablock_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"metablock_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"metablock_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n/* Greedy block splitter for one block category (literal, command or distance).\n   Gathers histograms for all context buckets. */\ntypedef struct ContextBlockSplitter {\n  /* Alphabet size of particular block category. */\n  size_t alphabet_size_;\n  size_t num_contexts_;\n  size_t max_block_types_;\n  /* We collect at least this many symbols for each block. */\n  size_t min_block_size_;\n  /* We merge histograms A and B if\n       entropy(A+B) < entropy(A) + entropy(B) + split_threshold_,\n     where A is the current histogram and B is the histogram of the last or the\n     second last block type. */\n  double split_threshold_;\n\n  size_t num_blocks_;\n  BlockSplit* split_;  /* not owned */\n  HistogramLiteral* histograms_;  /* not owned */\n  size_t* histograms_size_;  /* not owned */\n\n  /* The number of symbols that we want to collect before deciding on whether\n     or not to merge the block with a previous one or emit a new block. */\n  size_t target_block_size_;\n  /* The number of symbols in the current histogram. */\n  size_t block_size_;\n  /* Offset of the current histogram. */\n  size_t curr_histogram_ix_;\n  /* Offset of the histograms of the previous two block types. */\n  size_t last_histogram_ix_[2];\n  /* Entropy of the previous two block types. */\n  double last_entropy_[2 * BROTLI_MAX_STATIC_CONTEXTS];\n  /* The number of times we merged the current block with the last one. */\n  size_t merge_last_count_;\n} ContextBlockSplitter;\n\nstatic void InitContextBlockSplitter(\n    MemoryManager* m, ContextBlockSplitter* self, size_t alphabet_size,\n    size_t num_contexts, size_t min_block_size, double split_threshold,\n    size_t num_symbols, BlockSplit* split, HistogramLiteral** histograms,\n    size_t* histograms_size) {\n  size_t max_num_blocks = num_symbols / min_block_size + 1;\n  size_t max_num_types;\n  BROTLI_DCHECK(num_contexts <= BROTLI_MAX_STATIC_CONTEXTS);\n\n  self->alphabet_size_ = alphabet_size;\n  self->num_contexts_ = num_contexts;\n  self->max_block_types_ = BROTLI_MAX_NUMBER_OF_BLOCK_TYPES / num_contexts;\n  self->min_block_size_ = min_block_size;\n  self->split_threshold_ = split_threshold;\n  self->num_blocks_ = 0;\n  self->split_ = split;\n  self->histograms_size_ = histograms_size;\n  self->target_block_size_ = min_block_size;\n  self->block_size_ = 0;\n  self->curr_histogram_ix_ = 0;\n  self->merge_last_count_ = 0;\n\n  /* We have to allocate one more histogram than the maximum number of block\n     types for the current histogram when the meta-block is too big. */\n  max_num_types =\n      BROTLI_MIN(size_t, max_num_blocks, self->max_block_types_ + 1);\n  BROTLI_ENSURE_CAPACITY(m, uint8_t,\n      split->types, split->types_alloc_size, max_num_blocks);\n  BROTLI_ENSURE_CAPACITY(m, uint32_t,\n      split->lengths, split->lengths_alloc_size, max_num_blocks);\n  if (BROTLI_IS_OOM(m)) return;\n  split->num_blocks = max_num_blocks;\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_DCHECK(*histograms == 0);\n  *histograms_size = max_num_types * num_contexts;\n  *histograms = BROTLI_ALLOC(m, HistogramLiteral, *histograms_size);\n  self->histograms_ = *histograms;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return;\n  /* Clear only current histogram. */\n  ClearHistogramsLiteral(&self->histograms_[0], num_contexts);\n  self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;\n}\n\n/* Does either of three things:\n     (1) emits the current block with a new block type;\n     (2) emits the current block with the type of the second last block;\n     (3) merges the current block with the last block. */\nstatic void ContextBlockSplitterFinishBlock(\n    ContextBlockSplitter* self, MemoryManager* m, BROTLI_BOOL is_final) {\n  BlockSplit* split = self->split_;\n  const size_t num_contexts = self->num_contexts_;\n  double* last_entropy = self->last_entropy_;\n  HistogramLiteral* histograms = self->histograms_;\n\n  if (self->block_size_ < self->min_block_size_) {\n    self->block_size_ = self->min_block_size_;\n  }\n  if (self->num_blocks_ == 0) {\n    size_t i;\n    /* Create first block. */\n    split->lengths[0] = (uint32_t)self->block_size_;\n    split->types[0] = 0;\n\n    for (i = 0; i < num_contexts; ++i) {\n      last_entropy[i] =\n          BrotliBitsEntropy(histograms[i].data_, self->alphabet_size_);\n      last_entropy[num_contexts + i] = last_entropy[i];\n    }\n    ++self->num_blocks_;\n    ++split->num_types;\n    self->curr_histogram_ix_ += num_contexts;\n    if (self->curr_histogram_ix_ < *self->histograms_size_) {\n      ClearHistogramsLiteral(\n          &self->histograms_[self->curr_histogram_ix_], self->num_contexts_);\n    }\n    self->block_size_ = 0;\n  } else if (self->block_size_ > 0) {\n    /* Try merging the set of histograms for the current block type with the\n       respective set of histograms for the last and second last block types.\n       Decide over the split based on the total reduction of entropy across\n       all contexts. */\n    double entropy[BROTLI_MAX_STATIC_CONTEXTS];\n    HistogramLiteral* combined_histo =\n        BROTLI_ALLOC(m, HistogramLiteral, 2 * num_contexts);\n    double combined_entropy[2 * BROTLI_MAX_STATIC_CONTEXTS];\n    double diff[2] = { 0.0 };\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(combined_histo)) return;\n    for (i = 0; i < num_contexts; ++i) {\n      size_t curr_histo_ix = self->curr_histogram_ix_ + i;\n      size_t j;\n      entropy[i] = BrotliBitsEntropy(histograms[curr_histo_ix].data_,\n                                     self->alphabet_size_);\n      for (j = 0; j < 2; ++j) {\n        size_t jx = j * num_contexts + i;\n        size_t last_histogram_ix = self->last_histogram_ix_[j] + i;\n        combined_histo[jx] = histograms[curr_histo_ix];\n        HistogramAddHistogramLiteral(&combined_histo[jx],\n            &histograms[last_histogram_ix]);\n        combined_entropy[jx] = BrotliBitsEntropy(\n            &combined_histo[jx].data_[0], self->alphabet_size_);\n        diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx];\n      }\n    }\n\n    if (split->num_types < self->max_block_types_ &&\n        diff[0] > self->split_threshold_ &&\n        diff[1] > self->split_threshold_) {\n      /* Create new block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = (uint8_t)split->num_types;\n      self->last_histogram_ix_[1] = self->last_histogram_ix_[0];\n      self->last_histogram_ix_[0] = split->num_types * num_contexts;\n      for (i = 0; i < num_contexts; ++i) {\n        last_entropy[num_contexts + i] = last_entropy[i];\n        last_entropy[i] = entropy[i];\n      }\n      ++self->num_blocks_;\n      ++split->num_types;\n      self->curr_histogram_ix_ += num_contexts;\n      if (self->curr_histogram_ix_ < *self->histograms_size_) {\n        ClearHistogramsLiteral(\n            &self->histograms_[self->curr_histogram_ix_], self->num_contexts_);\n      }\n      self->block_size_ = 0;\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else if (diff[1] < diff[0] - 20.0) {\n      /* Combine this block with second last block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];\n      BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1);\n      for (i = 0; i < num_contexts; ++i) {\n        histograms[self->last_histogram_ix_[0] + i] =\n            combined_histo[num_contexts + i];\n        last_entropy[num_contexts + i] = last_entropy[i];\n        last_entropy[i] = combined_entropy[num_contexts + i];\n        HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]);\n      }\n      ++self->num_blocks_;\n      self->block_size_ = 0;\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else {\n      /* Combine this block with last block. */\n      split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;\n      for (i = 0; i < num_contexts; ++i) {\n        histograms[self->last_histogram_ix_[0] + i] = combined_histo[i];\n        last_entropy[i] = combined_entropy[i];\n        if (split->num_types == 1) {\n          last_entropy[num_contexts + i] = last_entropy[i];\n        }\n        HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]);\n      }\n      self->block_size_ = 0;\n      if (++self->merge_last_count_ > 1) {\n        self->target_block_size_ += self->min_block_size_;\n      }\n    }\n    BROTLI_FREE(m, combined_histo);\n  }\n  if (is_final) {\n    *self->histograms_size_ = split->num_types * num_contexts;\n    split->num_blocks = self->num_blocks_;\n  }\n}\n\n/* Adds the next symbol to the current block type and context. When the\n   current block reaches the target size, decides on merging the block. */\nstatic void ContextBlockSplitterAddSymbol(\n    ContextBlockSplitter* self, MemoryManager* m,\n    size_t symbol, size_t context) {\n  HistogramAddLiteral(&self->histograms_[self->curr_histogram_ix_ + context],\n      symbol);\n  ++self->block_size_;\n  if (self->block_size_ == self->target_block_size_) {\n    ContextBlockSplitterFinishBlock(self, m, /* is_final = */ BROTLI_FALSE);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n}\n\nstatic void MapStaticContexts(MemoryManager* m,\n                              size_t num_contexts,\n                              const uint32_t* static_context_map,\n                              MetaBlockSplit* mb) {\n  size_t i;\n  BROTLI_DCHECK(mb->literal_context_map == 0);\n  mb->literal_context_map_size =\n      mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;\n  mb->literal_context_map =\n      BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return;\n\n  for (i = 0; i < mb->literal_split.num_types; ++i) {\n    uint32_t offset = (uint32_t)(i * num_contexts);\n    size_t j;\n    for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS); ++j) {\n      mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =\n          offset + static_context_map[j];\n    }\n  }\n}\n\ntypedef struct GreedyMetablockArena {\n  union {\n    BlockSplitterLiteral plain;\n    ContextBlockSplitter ctx;\n  } lit_blocks;\n  BlockSplitterCommand cmd_blocks;\n  BlockSplitterDistance dist_blocks;\n} GreedyMetablockArena;\n\nstatic BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(\n    MemoryManager* m, GreedyMetablockArena* arena, const uint8_t* ringbuffer,\n    size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2,\n    ContextLut literal_context_lut, const size_t num_contexts,\n    const uint32_t* static_context_map, const Command* commands,\n    size_t n_commands, MetaBlockSplit* mb) {\n  size_t num_literals = 0;\n  size_t i;\n  for (i = 0; i < n_commands; ++i) {\n    num_literals += commands[i].insert_len_;\n  }\n\n  if (num_contexts == 1) {\n    InitBlockSplitterLiteral(m, &arena->lit_blocks.plain, 256, 512, 400.0,\n        num_literals, &mb->literal_split, &mb->literal_histograms,\n        &mb->literal_histograms_size);\n  } else {\n    InitContextBlockSplitter(m, &arena->lit_blocks.ctx, 256, num_contexts, 512,\n        400.0, num_literals, &mb->literal_split, &mb->literal_histograms,\n        &mb->literal_histograms_size);\n  }\n  if (BROTLI_IS_OOM(m)) return;\n  InitBlockSplitterCommand(m, &arena->cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS,\n      1024, 500.0, n_commands, &mb->command_split, &mb->command_histograms,\n      &mb->command_histograms_size);\n  if (BROTLI_IS_OOM(m)) return;\n  InitBlockSplitterDistance(m, &arena->dist_blocks, 64, 512, 100.0, n_commands,\n      &mb->distance_split, &mb->distance_histograms,\n      &mb->distance_histograms_size);\n  if (BROTLI_IS_OOM(m)) return;\n\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    size_t j;\n    BlockSplitterAddSymbolCommand(&arena->cmd_blocks, cmd.cmd_prefix_);\n    for (j = cmd.insert_len_; j != 0; --j) {\n      uint8_t literal = ringbuffer[pos & mask];\n      if (num_contexts == 1) {\n        BlockSplitterAddSymbolLiteral(&arena->lit_blocks.plain, literal);\n      } else {\n        size_t context =\n            BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);\n        ContextBlockSplitterAddSymbol(&arena->lit_blocks.ctx, m, literal,\n                                      static_context_map[context]);\n        if (BROTLI_IS_OOM(m)) return;\n      }\n      prev_byte2 = prev_byte;\n      prev_byte = literal;\n      ++pos;\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd)) {\n      prev_byte2 = ringbuffer[(pos - 2) & mask];\n      prev_byte = ringbuffer[(pos - 1) & mask];\n      if (cmd.cmd_prefix_ >= 128) {\n        BlockSplitterAddSymbolDistance(\n            &arena->dist_blocks, cmd.dist_prefix_ & 0x3FF);\n      }\n    }\n  }\n\n  if (num_contexts == 1) {\n    BlockSplitterFinishBlockLiteral(\n        &arena->lit_blocks.plain, /* is_final = */ BROTLI_TRUE);\n  } else {\n    ContextBlockSplitterFinishBlock(\n        &arena->lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n  BlockSplitterFinishBlockCommand(\n      &arena->cmd_blocks, /* is_final = */ BROTLI_TRUE);\n  BlockSplitterFinishBlockDistance(\n      &arena->dist_blocks, /* is_final = */ BROTLI_TRUE);\n\n  if (num_contexts > 1) {\n    MapStaticContexts(m, num_contexts, static_context_map, mb);\n  }\n}\n\nvoid BrotliBuildMetaBlockGreedy(MemoryManager* m,\n                                const uint8_t* ringbuffer,\n                                size_t pos,\n                                size_t mask,\n                                uint8_t prev_byte,\n                                uint8_t prev_byte2,\n                                ContextLut literal_context_lut,\n                                size_t num_contexts,\n                                const uint32_t* static_context_map,\n                                const Command* commands,\n                                size_t n_commands,\n                                MetaBlockSplit* mb) {\n  GreedyMetablockArena* arena = BROTLI_ALLOC(m, GreedyMetablockArena, 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n  if (num_contexts == 1) {\n    BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,\n        prev_byte, prev_byte2, literal_context_lut, 1, NULL, commands,\n        n_commands, mb);\n  } else {\n    BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,\n        prev_byte, prev_byte2, literal_context_lut, num_contexts,\n        static_context_map, commands, n_commands, mb);\n  }\n  BROTLI_FREE(m, arena);\n}\n\nvoid BrotliOptimizeHistograms(uint32_t num_distance_codes,\n                              MetaBlockSplit* mb) {\n  uint8_t good_for_rle[BROTLI_NUM_COMMAND_SYMBOLS];\n  size_t i;\n  for (i = 0; i < mb->literal_histograms_size; ++i) {\n    BrotliOptimizeHuffmanCountsForRle(256, mb->literal_histograms[i].data_,\n                                      good_for_rle);\n  }\n  for (i = 0; i < mb->command_histograms_size; ++i) {\n    BrotliOptimizeHuffmanCountsForRle(BROTLI_NUM_COMMAND_SYMBOLS,\n                                      mb->command_histograms[i].data_,\n                                      good_for_rle);\n  }\n  for (i = 0; i < mb->distance_histograms_size; ++i) {\n    BrotliOptimizeHuffmanCountsForRle(num_distance_codes,\n                                      mb->distance_histograms[i].data_,\n                                      good_for_rle);\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/metablock.h",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Algorithms for distributing the literals and commands of a metablock between\n   block types and contexts. */\n\n#ifndef BROTLI_ENC_METABLOCK_H_\n#define BROTLI_ENC_METABLOCK_H_\n\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"block_splitter.h\"\n#include \"command.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"params.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_MAX_STATIC_CONTEXTS 13\n\ntypedef struct MetaBlockSplit {\n  BlockSplit literal_split;\n  BlockSplit command_split;\n  BlockSplit distance_split;\n  uint32_t* literal_context_map;\n  size_t literal_context_map_size;\n  uint32_t* distance_context_map;\n  size_t distance_context_map_size;\n  HistogramLiteral* literal_histograms;\n  size_t literal_histograms_size;\n  HistogramCommand* command_histograms;\n  size_t command_histograms_size;\n  HistogramDistance* distance_histograms;\n  size_t distance_histograms_size;\n} MetaBlockSplit;\n\nstatic BROTLI_INLINE void InitMetaBlockSplit(MetaBlockSplit* mb) {\n  BrotliInitBlockSplit(&mb->literal_split);\n  BrotliInitBlockSplit(&mb->command_split);\n  BrotliInitBlockSplit(&mb->distance_split);\n  mb->literal_context_map = 0;\n  mb->literal_context_map_size = 0;\n  mb->distance_context_map = 0;\n  mb->distance_context_map_size = 0;\n  mb->literal_histograms = 0;\n  mb->literal_histograms_size = 0;\n  mb->command_histograms = 0;\n  mb->command_histograms_size = 0;\n  mb->distance_histograms = 0;\n  mb->distance_histograms_size = 0;\n}\n\nstatic BROTLI_INLINE void DestroyMetaBlockSplit(\n    MemoryManager* m, MetaBlockSplit* mb) {\n  BrotliDestroyBlockSplit(m, &mb->literal_split);\n  BrotliDestroyBlockSplit(m, &mb->command_split);\n  BrotliDestroyBlockSplit(m, &mb->distance_split);\n  BROTLI_FREE(m, mb->literal_context_map);\n  BROTLI_FREE(m, mb->distance_context_map);\n  BROTLI_FREE(m, mb->literal_histograms);\n  BROTLI_FREE(m, mb->command_histograms);\n  BROTLI_FREE(m, mb->distance_histograms);\n}\n\n/* Uses the slow shortest-path block splitter and does context clustering.\n   The distance parameters are dynamically selected based on the commands\n   which get recomputed under the new distance parameters. The new distance\n   parameters are stored into *params. */\nBROTLI_INTERNAL void BrotliBuildMetaBlock(MemoryManager* m,\n                                          const uint8_t* ringbuffer,\n                                          const size_t pos,\n                                          const size_t mask,\n                                          BrotliEncoderParams* params,\n                                          uint8_t prev_byte,\n                                          uint8_t prev_byte2,\n                                          Command* cmds,\n                                          size_t num_commands,\n                                          ContextType literal_context_mode,\n                                          MetaBlockSplit* mb);\n\n/* Uses a fast greedy block splitter that tries to merge current block with the\n   last or the second last block and uses a static context clustering which\n   is the same for all block types. */\nBROTLI_INTERNAL void BrotliBuildMetaBlockGreedy(\n    MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,\n    uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut,\n    size_t num_contexts, const uint32_t* static_context_map,\n    const Command* commands, size_t n_commands, MetaBlockSplit* mb);\n\nBROTLI_INTERNAL void BrotliOptimizeHistograms(uint32_t num_distance_codes,\n                                              MetaBlockSplit* mb);\n\nBROTLI_INTERNAL void BrotliInitDistanceParams(BrotliDistanceParams* params,\n    uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_METABLOCK_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/metablock_inc.h",
    "content": "﻿/* NOLINT(build/header_guard) */\n/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n#define HistogramType FN(Histogram)\n\n/* Greedy block splitter for one block category (literal, command or distance).\n*/\ntypedef struct FN(BlockSplitter) {\n  /* Alphabet size of particular block category. */\n  size_t alphabet_size_;\n  /* We collect at least this many symbols for each block. */\n  size_t min_block_size_;\n  /* We merge histograms A and B if\n       entropy(A+B) < entropy(A) + entropy(B) + split_threshold_,\n     where A is the current histogram and B is the histogram of the last or the\n     second last block type. */\n  double split_threshold_;\n\n  size_t num_blocks_;\n  BlockSplit* split_;  /* not owned */\n  HistogramType* histograms_;  /* not owned */\n  size_t* histograms_size_;  /* not owned */\n\n  /* Temporary storage for BlockSplitterFinishBlock. */\n  HistogramType combined_histo[2];\n\n  /* The number of symbols that we want to collect before deciding on whether\n     or not to merge the block with a previous one or emit a new block. */\n  size_t target_block_size_;\n  /* The number of symbols in the current histogram. */\n  size_t block_size_;\n  /* Offset of the current histogram. */\n  size_t curr_histogram_ix_;\n  /* Offset of the histograms of the previous two block types. */\n  size_t last_histogram_ix_[2];\n  /* Entropy of the previous two block types. */\n  double last_entropy_[2];\n  /* The number of times we merged the current block with the last one. */\n  size_t merge_last_count_;\n} FN(BlockSplitter);\n\nstatic void FN(InitBlockSplitter)(\n    MemoryManager* m, FN(BlockSplitter)* self, size_t alphabet_size,\n    size_t min_block_size, double split_threshold, size_t num_symbols,\n    BlockSplit* split, HistogramType** histograms, size_t* histograms_size) {\n  size_t max_num_blocks = num_symbols / min_block_size + 1;\n  /* We have to allocate one more histogram than the maximum number of block\n     types for the current histogram when the meta-block is too big. */\n  size_t max_num_types =\n      BROTLI_MIN(size_t, max_num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 1);\n  self->alphabet_size_ = alphabet_size;\n  self->min_block_size_ = min_block_size;\n  self->split_threshold_ = split_threshold;\n  self->num_blocks_ = 0;\n  self->split_ = split;\n  self->histograms_size_ = histograms_size;\n  self->target_block_size_ = min_block_size;\n  self->block_size_ = 0;\n  self->curr_histogram_ix_ = 0;\n  self->merge_last_count_ = 0;\n  BROTLI_ENSURE_CAPACITY(m, uint8_t,\n      split->types, split->types_alloc_size, max_num_blocks);\n  BROTLI_ENSURE_CAPACITY(m, uint32_t,\n      split->lengths, split->lengths_alloc_size, max_num_blocks);\n  if (BROTLI_IS_OOM(m)) return;\n  self->split_->num_blocks = max_num_blocks;\n  BROTLI_DCHECK(*histograms == 0);\n  *histograms_size = max_num_types;\n  *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size);\n  self->histograms_ = *histograms;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return;\n  /* Clear only current histogram. */\n  FN(HistogramClear)(&self->histograms_[0]);\n  self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;\n}\n\n/* Does either of three things:\n     (1) emits the current block with a new block type;\n     (2) emits the current block with the type of the second last block;\n     (3) merges the current block with the last block. */\nstatic void FN(BlockSplitterFinishBlock)(\n    FN(BlockSplitter)* self, BROTLI_BOOL is_final) {\n  BlockSplit* split = self->split_;\n  double* last_entropy = self->last_entropy_;\n  HistogramType* histograms = self->histograms_;\n  self->block_size_ =\n      BROTLI_MAX(size_t, self->block_size_, self->min_block_size_);\n  if (self->num_blocks_ == 0) {\n    /* Create first block. */\n    split->lengths[0] = (uint32_t)self->block_size_;\n    split->types[0] = 0;\n    last_entropy[0] =\n        BrotliBitsEntropy(histograms[0].data_, self->alphabet_size_);\n    last_entropy[1] = last_entropy[0];\n    ++self->num_blocks_;\n    ++split->num_types;\n    ++self->curr_histogram_ix_;\n    if (self->curr_histogram_ix_ < *self->histograms_size_)\n      FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n    self->block_size_ = 0;\n  } else if (self->block_size_ > 0) {\n    double entropy = BrotliBitsEntropy(\n        histograms[self->curr_histogram_ix_].data_, self->alphabet_size_);\n    double combined_entropy[2];\n    double diff[2];\n    size_t j;\n    for (j = 0; j < 2; ++j) {\n      size_t last_histogram_ix = self->last_histogram_ix_[j];\n      self->combined_histo[j] = histograms[self->curr_histogram_ix_];\n      FN(HistogramAddHistogram)(&self->combined_histo[j],\n          &histograms[last_histogram_ix]);\n      combined_entropy[j] = BrotliBitsEntropy(\n          &self->combined_histo[j].data_[0], self->alphabet_size_);\n      diff[j] = combined_entropy[j] - entropy - last_entropy[j];\n    }\n\n    if (split->num_types < BROTLI_MAX_NUMBER_OF_BLOCK_TYPES &&\n        diff[0] > self->split_threshold_ &&\n        diff[1] > self->split_threshold_) {\n      /* Create new block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = (uint8_t)split->num_types;\n      self->last_histogram_ix_[1] = self->last_histogram_ix_[0];\n      self->last_histogram_ix_[0] = (uint8_t)split->num_types;\n      last_entropy[1] = last_entropy[0];\n      last_entropy[0] = entropy;\n      ++self->num_blocks_;\n      ++split->num_types;\n      ++self->curr_histogram_ix_;\n      if (self->curr_histogram_ix_ < *self->histograms_size_)\n        FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n      self->block_size_ = 0;\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else if (diff[1] < diff[0] - 20.0) {\n      /* Combine this block with second last block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];\n      BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1);\n      histograms[self->last_histogram_ix_[0]] = self->combined_histo[1];\n      last_entropy[1] = last_entropy[0];\n      last_entropy[0] = combined_entropy[1];\n      ++self->num_blocks_;\n      self->block_size_ = 0;\n      FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else {\n      /* Combine this block with last block. */\n      split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;\n      histograms[self->last_histogram_ix_[0]] = self->combined_histo[0];\n      last_entropy[0] = combined_entropy[0];\n      if (split->num_types == 1) {\n        last_entropy[1] = last_entropy[0];\n      }\n      self->block_size_ = 0;\n      FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n      if (++self->merge_last_count_ > 1) {\n        self->target_block_size_ += self->min_block_size_;\n      }\n    }\n  }\n  if (is_final) {\n    *self->histograms_size_ = split->num_types;\n    split->num_blocks = self->num_blocks_;\n  }\n}\n\n/* Adds the next symbol to the current histogram. When the current histogram\n   reaches the target size, decides on merging the block. */\nstatic void FN(BlockSplitterAddSymbol)(FN(BlockSplitter)* self, size_t symbol) {\n  FN(HistogramAdd)(&self->histograms_[self->curr_histogram_ix_], symbol);\n  ++self->block_size_;\n  if (self->block_size_ == self->target_block_size_) {\n    FN(BlockSplitterFinishBlock)(self, /* is_final = */ BROTLI_FALSE);\n  }\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/params.h",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Parameters for the Brotli encoder with chosen quality levels. */\n\n#ifndef BROTLI_ENC_PARAMS_H_\n#define BROTLI_ENC_PARAMS_H_\n\n#include <brotli/encode.h>\n#include \"encoder_dict.h\"\n\ntypedef struct BrotliHasherParams {\n  int type;\n  int bucket_bits;\n  int block_bits;\n  int num_last_distances_to_check;\n} BrotliHasherParams;\n\ntypedef struct BrotliDistanceParams {\n  uint32_t distance_postfix_bits;\n  uint32_t num_direct_distance_codes;\n  uint32_t alphabet_size_max;\n  uint32_t alphabet_size_limit;\n  size_t max_distance;\n} BrotliDistanceParams;\n\n/* Encoding parameters */\ntypedef struct BrotliEncoderParams {\n  BrotliEncoderMode mode;\n  int quality;\n  int lgwin;\n  int lgblock;\n  size_t stream_offset;\n  size_t size_hint;\n  BROTLI_BOOL disable_literal_context_modeling;\n  BROTLI_BOOL large_window;\n  BrotliHasherParams hasher;\n  BrotliDistanceParams dist;\n  /* TODO(eustas): rename to BrotliShared... */\n  SharedEncoderDictionary dictionary;\n} BrotliEncoderParams;\n\n#endif  /* BROTLI_ENC_PARAMS_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/prefix.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions for encoding of integers into prefix codes the amount of extra\n   bits, and the actual values of the extra bits. */\n\n#ifndef BROTLI_ENC_PREFIX_H_\n#define BROTLI_ENC_PREFIX_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Here distance_code is an intermediate code, i.e. one of the special codes or\n   the actual distance increased by BROTLI_NUM_DISTANCE_SHORT_CODES - 1. */\nstatic BROTLI_INLINE void PrefixEncodeCopyDistance(size_t distance_code,\n                                                   size_t num_direct_codes,\n                                                   size_t postfix_bits,\n                                                   uint16_t* code,\n                                                   uint32_t* extra_bits) {\n  if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes) {\n    *code = (uint16_t)distance_code;\n    *extra_bits = 0;\n    return;\n  } else {\n    size_t dist = ((size_t)1 << (postfix_bits + 2u)) +\n        (distance_code - BROTLI_NUM_DISTANCE_SHORT_CODES - num_direct_codes);\n    size_t bucket = Log2FloorNonZero(dist) - 1;\n    size_t postfix_mask = (1u << postfix_bits) - 1;\n    size_t postfix = dist & postfix_mask;\n    size_t prefix = (dist >> bucket) & 1;\n    size_t offset = (2 + prefix) << bucket;\n    size_t nbits = bucket - postfix_bits;\n    *code = (uint16_t)((nbits << 10) |\n        (BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes +\n         ((2 * (nbits - 1) + prefix) << postfix_bits) + postfix));\n    *extra_bits = (uint32_t)((dist - offset) >> postfix_bits);\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_PREFIX_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/quality.h",
    "content": "﻿/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Constants and formulas that affect speed-ratio trade-offs and thus define\n   quality levels. */\n\n#ifndef BROTLI_ENC_QUALITY_H_\n#define BROTLI_ENC_QUALITY_H_\n\n#include \"../common/platform.h\"\n#include <brotli/encode.h>\n#include \"params.h\"\n\n#define FAST_ONE_PASS_COMPRESSION_QUALITY 0\n#define FAST_TWO_PASS_COMPRESSION_QUALITY 1\n#define ZOPFLIFICATION_QUALITY 10\n#define HQ_ZOPFLIFICATION_QUALITY 11\n\n#define MAX_QUALITY_FOR_STATIC_ENTROPY_CODES 2\n#define MIN_QUALITY_FOR_BLOCK_SPLIT 4\n#define MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS 4\n#define MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS 4\n#define MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH 5\n#define MIN_QUALITY_FOR_CONTEXT_MODELING 5\n#define MIN_QUALITY_FOR_HQ_CONTEXT_MODELING 7\n#define MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING 10\n\n/* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting,\n   so we buffer at most this much literals and commands. */\n#define MAX_NUM_DELAYED_SYMBOLS 0x2FFF\n\n/* Returns hash-table size for quality levels 0 and 1. */\nstatic BROTLI_INLINE size_t MaxHashTableSize(int quality) {\n  return quality == FAST_ONE_PASS_COMPRESSION_QUALITY ? 1 << 15 : 1 << 17;\n}\n\n/* The maximum length for which the zopflification uses distinct distances. */\n#define MAX_ZOPFLI_LEN_QUALITY_10 150\n#define MAX_ZOPFLI_LEN_QUALITY_11 325\n\n/* Do not thoroughly search when a long copy is found. */\n#define BROTLI_LONG_COPY_QUICK_STEP 16384\n\nstatic BROTLI_INLINE size_t MaxZopfliLen(const BrotliEncoderParams* params) {\n  return params->quality <= 10 ?\n      MAX_ZOPFLI_LEN_QUALITY_10 :\n      MAX_ZOPFLI_LEN_QUALITY_11;\n}\n\n/* Number of best candidates to evaluate to expand Zopfli chain. */\nstatic BROTLI_INLINE size_t MaxZopfliCandidates(\n  const BrotliEncoderParams* params) {\n  return params->quality <= 10 ? 1 : 5;\n}\n\nstatic BROTLI_INLINE void SanitizeParams(BrotliEncoderParams* params) {\n  params->quality = BROTLI_MIN(int, BROTLI_MAX_QUALITY,\n      BROTLI_MAX(int, BROTLI_MIN_QUALITY, params->quality));\n  if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) {\n    params->large_window = BROTLI_FALSE;\n  }\n  if (params->lgwin < BROTLI_MIN_WINDOW_BITS) {\n    params->lgwin = BROTLI_MIN_WINDOW_BITS;\n  } else {\n    int max_lgwin = params->large_window ? BROTLI_LARGE_MAX_WINDOW_BITS :\n                                           BROTLI_MAX_WINDOW_BITS;\n    if (params->lgwin > max_lgwin) params->lgwin = max_lgwin;\n  }\n}\n\n/* Returns optimized lg_block value. */\nstatic BROTLI_INLINE int ComputeLgBlock(const BrotliEncoderParams* params) {\n  int lgblock = params->lgblock;\n  if (params->quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      params->quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    lgblock = params->lgwin;\n  } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {\n    lgblock = 14;\n  } else if (lgblock == 0) {\n    lgblock = 16;\n    if (params->quality >= 9 && params->lgwin > lgblock) {\n      lgblock = BROTLI_MIN(int, 18, params->lgwin);\n    }\n  } else {\n    lgblock = BROTLI_MIN(int, BROTLI_MAX_INPUT_BLOCK_BITS,\n        BROTLI_MAX(int, BROTLI_MIN_INPUT_BLOCK_BITS, lgblock));\n  }\n  return lgblock;\n}\n\n/* Returns log2 of the size of main ring buffer area.\n   Allocate at least lgwin + 1 bits for the ring buffer so that the newly\n   added block fits there completely and we still get lgwin bits and at least\n   read_block_size_bits + 1 bits because the copy tail length needs to be\n   smaller than ring-buffer size. */\nstatic BROTLI_INLINE int ComputeRbBits(const BrotliEncoderParams* params) {\n  return 1 + BROTLI_MAX(int, params->lgwin, params->lgblock);\n}\n\nstatic BROTLI_INLINE size_t MaxMetablockSize(\n    const BrotliEncoderParams* params) {\n  int bits =\n      BROTLI_MIN(int, ComputeRbBits(params), BROTLI_MAX_INPUT_BLOCK_BITS);\n  return (size_t)1 << bits;\n}\n\n/* When searching for backward references and have not seen matches for a long\n   time, we can skip some match lookups. Unsuccessful match lookups are very\n   expensive and this kind of a heuristic speeds up compression quite a lot.\n   At first 8 byte strides are taken and every second byte is put to hasher.\n   After 4x more literals stride by 16 bytes, every put 4-th byte to hasher.\n   Applied only to qualities 2 to 9. */\nstatic BROTLI_INLINE size_t LiteralSpreeLengthForSparseSearch(\n    const BrotliEncoderParams* params) {\n  return params->quality < 9 ? 64 : 512;\n}\n\n/* Quality to hasher mapping:\n\n   - q02: h02 (longest_match_quickly), b16, l5\n\n   - q03: h03 (longest_match_quickly), b17, l5\n\n   - q04: h04 (longest_match_quickly), b17, l5\n   - q04: h54 (longest_match_quickly), b20, l7 | for large files\n\n   - q05: h58 (longest_match_simd   ), b14, l4\n   - q05: h68 (longest_match64_simd ), b15, l5 | for large files\n   - q05: h40 (forgetful_chain      ), b15, l4 | for small window\n\n   - q06: h58 (longest_match_simd   ), b14, l4\n   - q06: h68 (longest_match64_simd ), b15, l5 | for large files\n   - q06: h40 (forgetful_chain      ), b15, l4 | for small window\n\n   - q07: h58 (longest_match_simd   ), b15, l4\n   - q07: h68 (longest_match64_simd ), b15, l5 | for large files\n   - q07: h41 (forgetful_chain      ), b15, l4 | for small window\n\n   - q08: h05 (longest_match        ), b15, l4\n   - q08: h06 (longest_match64      ), b15, l5 | for large files\n   - q08: h41 (forgetful_chain      ), b15, l4 | for small window\n\n   - q09: h05 (longest_match        ), b15, l4\n   - q09: h06 (longest_match64      ), b15, l5 | for large files\n   - q09: h42 (forgetful_chain      ), b15, l4 | for small window\n\n   - q10: t10 (to_binary_tree       ), b17, l128\n\n   - q11: t10 (to_binary_tree       ), b17, l128\n\n  Where \"q\" is quality, \"h\" is hasher type, \"b\" is bucket bits,\n  \"l\" is source len. */\nstatic BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,\n                                       BrotliHasherParams* hparams) {\n  if (params->quality > 9) {\n    hparams->type = 10;\n  } else if (params->quality == 4 && params->size_hint >= (1 << 20)) {\n    hparams->type = 54;\n  } else if (params->quality < 5) {\n    hparams->type = params->quality;\n  } else if (params->lgwin <= 16) {\n    hparams->type = params->quality < 7 ? 40 : params->quality < 9 ? 41 : 42;\n  } else if (params->size_hint >= (1 << 20) && params->lgwin >= 19) {\n#if defined(BROTLI_MAX_SIMD_QUALITY)\n    hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 68 : 6;\n#else\n    hparams->type = 6;\n#endif\n    hparams->block_bits = params->quality - 1;\n    hparams->bucket_bits = 15;\n    hparams->num_last_distances_to_check =\n        params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;\n  } else {\n    /* TODO(eustas): often previous setting (H6) is faster and denser; consider\n                     adding an option to use it. */\n#if defined(BROTLI_MAX_SIMD_QUALITY)\n    hparams->type = params->quality <= BROTLI_MAX_SIMD_QUALITY ? 58 : 5;\n#else\n    hparams->type = 5;\n#endif\n    hparams->block_bits = params->quality - 1;\n    hparams->bucket_bits = params->quality < 7 ? 14 : 15;\n    hparams->num_last_distances_to_check =\n        params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;\n  }\n\n  if (params->lgwin > 24) {\n    /* Different hashers for large window brotli: not for qualities <= 2,\n       these are too fast for large window. Not for qualities >= 10: their\n       hasher already works well with large window. So the changes are:\n       H3 --> H35: for quality 3.\n       H54 --> H55: for quality 4 with size hint > 1MB\n       H6/H68 --> H65: for qualities 5, 6, 7, 8, 9. */\n    if (hparams->type == 3) {\n      hparams->type = 35;\n    }\n    if (hparams->type == 54) {\n      hparams->type = 55;\n    }\n    if (hparams->type == 6 || hparams->type == 68) {\n      hparams->type = 65;\n    }\n  }\n}\n\n#endif  /* BROTLI_ENC_QUALITY_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/ringbuffer.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Sliding window over the input data. */\n\n#ifndef BROTLI_ENC_RINGBUFFER_H_\n#define BROTLI_ENC_RINGBUFFER_H_\n\n#include \"../common/platform.h\"\n#include \"memory.h\"\n#include \"params.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* A RingBuffer(window_bits, tail_bits) contains `1 << window_bits' bytes of\n   data in a circular manner: writing a byte writes it to:\n     `position() % (1 << window_bits)'.\n   For convenience, the RingBuffer array contains another copy of the\n   first `1 << tail_bits' bytes:\n     buffer_[i] == buffer_[i + (1 << window_bits)], if i < (1 << tail_bits),\n   and another copy of the last two bytes:\n     buffer_[-1] == buffer_[(1 << window_bits) - 1] and\n     buffer_[-2] == buffer_[(1 << window_bits) - 2]. */\ntypedef struct RingBuffer {\n  /* Size of the ring-buffer is (1 << window_bits) + tail_size_. */\n  const uint32_t size_;\n  const uint32_t mask_;\n  const uint32_t tail_size_;\n  const uint32_t total_size_;\n\n  uint32_t cur_size_;\n  /* Position to write in the ring buffer. */\n  uint32_t pos_;\n  /* The actual ring buffer containing the copy of the last two bytes, the data,\n     and the copy of the beginning as a tail. */\n  uint8_t* data_;\n  /* The start of the ring-buffer. */\n  uint8_t* buffer_;\n} RingBuffer;\n\nstatic BROTLI_INLINE void RingBufferInit(RingBuffer* rb) {\n  rb->cur_size_ = 0;\n  rb->pos_ = 0;\n  rb->data_ = 0;\n  rb->buffer_ = 0;\n}\n\nstatic BROTLI_INLINE void RingBufferSetup(\n    const BrotliEncoderParams* params, RingBuffer* rb) {\n  int window_bits = ComputeRbBits(params);\n  int tail_bits = params->lgblock;\n  *(uint32_t*)&rb->size_ = 1u << window_bits;\n  *(uint32_t*)&rb->mask_ = (1u << window_bits) - 1;\n  *(uint32_t*)&rb->tail_size_ = 1u << tail_bits;\n  *(uint32_t*)&rb->total_size_ = rb->size_ + rb->tail_size_;\n}\n\nstatic BROTLI_INLINE void RingBufferFree(MemoryManager* m, RingBuffer* rb) {\n  BROTLI_FREE(m, rb->data_);\n}\n\n/* Allocates or re-allocates data_ to the given length + plus some slack\n   region before and after. Fills the slack regions with zeros. */\nstatic BROTLI_INLINE void RingBufferInitBuffer(\n    MemoryManager* m, const uint32_t buflen, RingBuffer* rb) {\n  static const size_t kSlackForEightByteHashingEverywhere = 7;\n  uint8_t* new_data = BROTLI_ALLOC(\n      m, uint8_t, 2 + buflen + kSlackForEightByteHashingEverywhere);\n  size_t i;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_data)) return;\n  if (rb->data_) {\n    memcpy(new_data, rb->data_,\n        2 + rb->cur_size_ + kSlackForEightByteHashingEverywhere);\n    BROTLI_FREE(m, rb->data_);\n  }\n  rb->data_ = new_data;\n  rb->cur_size_ = buflen;\n  rb->buffer_ = rb->data_ + 2;\n  rb->buffer_[-2] = rb->buffer_[-1] = 0;\n  for (i = 0; i < kSlackForEightByteHashingEverywhere; ++i) {\n    rb->buffer_[rb->cur_size_ + i] = 0;\n  }\n}\n\nstatic BROTLI_INLINE void RingBufferWriteTail(\n    const uint8_t* bytes, size_t n, RingBuffer* rb) {\n  const size_t masked_pos = rb->pos_ & rb->mask_;\n  if (BROTLI_PREDICT_FALSE(masked_pos < rb->tail_size_)) {\n    /* Just fill the tail buffer with the beginning data. */\n    const size_t p = rb->size_ + masked_pos;\n    memcpy(&rb->buffer_[p], bytes,\n        BROTLI_MIN(size_t, n, rb->tail_size_ - masked_pos));\n  }\n}\n\n/* Push bytes into the ring buffer. */\nstatic BROTLI_INLINE void RingBufferWrite(\n    MemoryManager* m, const uint8_t* bytes, size_t n, RingBuffer* rb) {\n  if (rb->pos_ == 0 && n < rb->tail_size_) {\n    /* Special case for the first write: to process the first block, we don't\n       need to allocate the whole ring-buffer and we don't need the tail\n       either. However, we do this memory usage optimization only if the\n       first write is less than the tail size, which is also the input block\n       size, otherwise it is likely that other blocks will follow and we\n       will need to reallocate to the full size anyway. */\n    rb->pos_ = (uint32_t)n;\n    RingBufferInitBuffer(m, rb->pos_, rb);\n    if (BROTLI_IS_OOM(m)) return;\n    memcpy(rb->buffer_, bytes, n);\n    return;\n  }\n  if (rb->cur_size_ < rb->total_size_) {\n    /* Lazily allocate the full buffer. */\n    RingBufferInitBuffer(m, rb->total_size_, rb);\n    if (BROTLI_IS_OOM(m)) return;\n    /* Initialize the last two bytes to zero, so that we don't have to worry\n       later when we copy the last two bytes to the first two positions. */\n    rb->buffer_[rb->size_ - 2] = 0;\n    rb->buffer_[rb->size_ - 1] = 0;\n    /* Initialize tail; might be touched by \"best_len++\" optimization when\n       ring buffer is \"full\". */\n    rb->buffer_[rb->size_] = 241;\n  }\n  {\n    const size_t masked_pos = rb->pos_ & rb->mask_;\n    /* The length of the writes is limited so that we do not need to worry\n       about a write */\n    RingBufferWriteTail(bytes, n, rb);\n    if (BROTLI_PREDICT_TRUE(masked_pos + n <= rb->size_)) {\n      /* A single write fits. */\n      memcpy(&rb->buffer_[masked_pos], bytes, n);\n    } else {\n      /* Split into two writes.\n         Copy into the end of the buffer, including the tail buffer. */\n      memcpy(&rb->buffer_[masked_pos], bytes,\n             BROTLI_MIN(size_t, n, rb->total_size_ - masked_pos));\n      /* Copy into the beginning of the buffer */\n      memcpy(&rb->buffer_[0], bytes + (rb->size_ - masked_pos),\n             n - (rb->size_ - masked_pos));\n    }\n  }\n  {\n    BROTLI_BOOL not_first_lap = (rb->pos_ & (1u << 31)) != 0;\n    uint32_t rb_pos_mask = (1u << 31) - 1;\n    rb->buffer_[-2] = rb->buffer_[rb->size_ - 2];\n    rb->buffer_[-1] = rb->buffer_[rb->size_ - 1];\n    rb->pos_ = (rb->pos_ & rb_pos_mask) + (uint32_t)(n & rb_pos_mask);\n    if (not_first_lap) {\n      /* Wrap, but preserve not-a-first-lap feature. */\n      rb->pos_ |= 1u << 31;\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_RINGBUFFER_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/state.h",
    "content": "﻿/* Copyright 2022 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Encoder state. */\n\n#ifndef BROTLI_ENC_STATE_H_\n#define BROTLI_ENC_STATE_H_\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"compress_fragment.h\"\n#include \"compress_fragment_two_pass.h\"\n#include \"hash.h\"\n#include \"memory.h\"\n#include \"params.h\"\n#include \"ringbuffer.h\"\n\ntypedef enum BrotliEncoderStreamState {\n  /* Default state. */\n  BROTLI_STREAM_PROCESSING = 0,\n  /* Intermediate state; after next block is emitted, byte-padding should be\n     performed before getting back to default state. */\n  BROTLI_STREAM_FLUSH_REQUESTED = 1,\n  /* Last metablock was produced; no more input is acceptable. */\n  BROTLI_STREAM_FINISHED = 2,\n  /* Flushing compressed block and writing meta-data block header. */\n  BROTLI_STREAM_METADATA_HEAD = 3,\n  /* Writing metadata block body. */\n  BROTLI_STREAM_METADATA_BODY = 4\n} BrotliEncoderStreamState;\n\ntypedef enum BrotliEncoderFlintState {\n  BROTLI_FLINT_NEEDS_2_BYTES = 2,\n  BROTLI_FLINT_NEEDS_1_BYTE = 1,\n  BROTLI_FLINT_WAITING_FOR_PROCESSING = 0,\n  BROTLI_FLINT_WAITING_FOR_FLUSHING = -1,\n  BROTLI_FLINT_DONE = -2\n} BrotliEncoderFlintState;\n\ntypedef struct BrotliEncoderStateStruct {\n  BrotliEncoderParams params;\n\n  MemoryManager memory_manager_;\n\n  uint64_t input_pos_;\n  RingBuffer ringbuffer_;\n  size_t cmd_alloc_size_;\n  Command* commands_;\n  size_t num_commands_;\n  size_t num_literals_;\n  size_t last_insert_len_;\n  uint64_t last_flush_pos_;\n  uint64_t last_processed_pos_;\n  int dist_cache_[BROTLI_NUM_DISTANCE_SHORT_CODES];\n  int saved_dist_cache_[4];\n  uint16_t last_bytes_;\n  uint8_t last_bytes_bits_;\n  /* \"Flint\" is a tiny uncompressed block emitted before the continuation\n     block to unwire literal context from previous data. Despite being int8_t,\n     field is actually BrotliEncoderFlintState enum. */\n  int8_t flint_;\n  uint8_t prev_byte_;\n  uint8_t prev_byte2_;\n  size_t storage_size_;\n  uint8_t* storage_;\n\n  Hasher hasher_;\n\n  /* Hash table for FAST_ONE_PASS_COMPRESSION_QUALITY mode. */\n  int small_table_[1 << 10];  /* 4KiB */\n  int* large_table_;          /* Allocated only when needed */\n  size_t large_table_size_;\n\n  BrotliOnePassArena* one_pass_arena_;\n  BrotliTwoPassArena* two_pass_arena_;\n\n  /* Command and literal buffers for FAST_TWO_PASS_COMPRESSION_QUALITY. */\n  uint32_t* command_buf_;\n  uint8_t* literal_buf_;\n\n  uint64_t total_in_;\n  uint8_t* next_out_;\n  size_t available_out_;\n  uint64_t total_out_;\n  /* Temporary buffer for padding flush bits or metadata block header / body. */\n  union {\n    uint64_t u64[2];\n    uint8_t u8[16];\n  } tiny_buf_;\n  uint32_t remaining_metadata_bytes_;\n  BrotliEncoderStreamState stream_state_;\n\n  BROTLI_BOOL is_last_block_emitted_;\n  BROTLI_BOOL is_initialized_;\n} BrotliEncoderStateStruct;\n\ntypedef struct BrotliEncoderStateStruct BrotliEncoderStateInternal;\n#define BrotliEncoderState BrotliEncoderStateInternal\n\n#endif  // BROTLI_ENC_STATE_H_\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/static_dict.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"static_dict.h\"\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"../common/transform.h\"\n#include \"encoder_dict.h\"\n#include \"find_match_length.h\"\n#include \"hash_base.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE void AddMatch(size_t distance, size_t len, size_t len_code,\n                                   uint32_t* matches) {\n  uint32_t match = (uint32_t)((distance << 5) + len_code);\n  matches[len] = BROTLI_MIN(uint32_t, matches[len], match);\n}\n\nstatic BROTLI_INLINE size_t DictMatchLength(const BrotliDictionary* dictionary,\n                                            const uint8_t* data,\n                                            size_t id,\n                                            size_t len,\n                                            size_t maxlen) {\n  const size_t offset = dictionary->offsets_by_length[len] + len * id;\n  return FindMatchLengthWithLimit(&dictionary->data[offset], data,\n                                  BROTLI_MIN(size_t, len, maxlen));\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL IsMatch(const BrotliDictionary* dictionary,\n    DictWord w, const uint8_t* data, size_t max_length) {\n  if (w.len > max_length) {\n    return BROTLI_FALSE;\n  } else {\n    const size_t offset = dictionary->offsets_by_length[w.len] +\n        (size_t)w.len * (size_t)w.idx;\n    const uint8_t* dict = &dictionary->data[offset];\n    if (w.transform == 0) {\n      /* Match against base dictionary word. */\n      return\n          TO_BROTLI_BOOL(FindMatchLengthWithLimit(dict, data, w.len) == w.len);\n    } else if (w.transform == 10) {\n      /* Match against uppercase first transform.\n         Note that there are only ASCII uppercase words in the lookup table. */\n      return TO_BROTLI_BOOL(dict[0] >= 'a' && dict[0] <= 'z' &&\n              (dict[0] ^ 32) == data[0] &&\n              FindMatchLengthWithLimit(&dict[1], &data[1], w.len - 1u) ==\n              w.len - 1u);\n    } else {\n      /* Match against uppercase all transform.\n         Note that there are only ASCII uppercase words in the lookup table. */\n      size_t i;\n      for (i = 0; i < w.len; ++i) {\n        if (dict[i] >= 'a' && dict[i] <= 'z') {\n          if ((dict[i] ^ 32) != data[i]) return BROTLI_FALSE;\n        } else {\n          if (dict[i] != data[i]) return BROTLI_FALSE;\n        }\n      }\n      return BROTLI_TRUE;\n    }\n  }\n}\n\n/* Finds matches for a single static dictionary */\nstatic BROTLI_BOOL BrotliFindAllStaticDictionaryMatchesFor(\n    const BrotliEncoderDictionary* dictionary, const uint8_t* data,\n    size_t min_length, size_t max_length, uint32_t* matches) {\n  BROTLI_BOOL has_found_match = BROTLI_FALSE;\n#if defined(BROTLI_EXPERIMENTAL)\n  if (dictionary->has_words_heavy) {\n    const BrotliTrieNode* node = &dictionary->trie.root;\n    size_t l = 0;\n    while (node && l < max_length) {\n      uint8_t c;\n      if (l >= min_length && node->len_) {\n        AddMatch(node->idx_, l, node->len_, matches);\n        has_found_match = BROTLI_TRUE;\n      }\n      c = data[l++];\n      node = BrotliTrieSub(&dictionary->trie, node, c);\n    }\n    return has_found_match;\n  }\n#endif  /* BROTLI_EXPERIMENTAL */\n  {\n    size_t offset = dictionary->buckets[Hash15(data)];\n    BROTLI_BOOL end = !offset;\n    while (!end) {\n      DictWord w = dictionary->dict_words[offset++];\n      const size_t l = w.len & 0x1F;\n      const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n      const size_t id = w.idx;\n      end = !!(w.len & 0x80);\n      w.len = (uint8_t)l;\n      if (w.transform == 0) {\n        const size_t matchlen =\n            DictMatchLength(dictionary->words, data, id, l, max_length);\n        const uint8_t* s;\n        size_t minlen;\n        size_t maxlen;\n        size_t len;\n        /* Transform \"\" + BROTLI_TRANSFORM_IDENTITY + \"\" */\n        if (matchlen == l) {\n          AddMatch(id, l, l, matches);\n          has_found_match = BROTLI_TRUE;\n        }\n        /* Transforms \"\" + BROTLI_TRANSFORM_OMIT_LAST_1 + \"\" and\n                      \"\" + BROTLI_TRANSFORM_OMIT_LAST_1 + \"ing \" */\n        if (matchlen >= l - 1) {\n          AddMatch(id + 12 * n, l - 1, l, matches);\n          if (l + 2 < max_length &&\n              data[l - 1] == 'i' && data[l] == 'n' && data[l + 1] == 'g' &&\n              data[l + 2] == ' ') {\n            AddMatch(id + 49 * n, l + 3, l, matches);\n          }\n          has_found_match = BROTLI_TRUE;\n        }\n        /* Transform \"\" + BROTLI_TRANSFORM_OMIT_LAST_# + \"\" (# = 2 .. 9) */\n        minlen = min_length;\n        if (l > 9) minlen = BROTLI_MAX(size_t, minlen, l - 9);\n        maxlen = BROTLI_MIN(size_t, matchlen, l - 2);\n        for (len = minlen; len <= maxlen; ++len) {\n          size_t cut = l - len;\n          size_t transform_id = (cut << 2) +\n              (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);\n          AddMatch(id + transform_id * n, len, l, matches);\n          has_found_match = BROTLI_TRUE;\n        }\n        if (matchlen < l || l + 6 >= max_length) {\n          continue;\n        }\n        s = &data[l];\n        /* Transforms \"\" + BROTLI_TRANSFORM_IDENTITY + <suffix> */\n        if (s[0] == ' ') {\n          AddMatch(id + n, l + 1, l, matches);\n          if (s[1] == 'a') {\n            if (s[2] == ' ') {\n              AddMatch(id + 28 * n, l + 3, l, matches);\n            } else if (s[2] == 's') {\n              if (s[3] == ' ') AddMatch(id + 46 * n, l + 4, l, matches);\n            } else if (s[2] == 't') {\n              if (s[3] == ' ') AddMatch(id + 60 * n, l + 4, l, matches);\n            } else if (s[2] == 'n') {\n              if (s[3] == 'd' && s[4] == ' ') {\n                AddMatch(id + 10 * n, l + 5, l, matches);\n              }\n            }\n          } else if (s[1] == 'b') {\n            if (s[2] == 'y' && s[3] == ' ') {\n              AddMatch(id + 38 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'i') {\n            if (s[2] == 'n') {\n              if (s[3] == ' ') AddMatch(id + 16 * n, l + 4, l, matches);\n            } else if (s[2] == 's') {\n              if (s[3] == ' ') AddMatch(id + 47 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'f') {\n            if (s[2] == 'o') {\n              if (s[3] == 'r' && s[4] == ' ') {\n                AddMatch(id + 25 * n, l + 5, l, matches);\n              }\n            } else if (s[2] == 'r') {\n              if (s[3] == 'o' && s[4] == 'm' && s[5] == ' ') {\n                AddMatch(id + 37 * n, l + 6, l, matches);\n              }\n            }\n          } else if (s[1] == 'o') {\n            if (s[2] == 'f') {\n              if (s[3] == ' ') AddMatch(id + 8 * n, l + 4, l, matches);\n            } else if (s[2] == 'n') {\n              if (s[3] == ' ') AddMatch(id + 45 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'n') {\n            if (s[2] == 'o' && s[3] == 't' && s[4] == ' ') {\n              AddMatch(id + 80 * n, l + 5, l, matches);\n            }\n          } else if (s[1] == 't') {\n            if (s[2] == 'h') {\n              if (s[3] == 'e') {\n                if (s[4] == ' ') AddMatch(id + 5 * n, l + 5, l, matches);\n              } else if (s[3] == 'a') {\n                if (s[4] == 't' && s[5] == ' ') {\n                  AddMatch(id + 29 * n, l + 6, l, matches);\n                }\n              }\n            } else if (s[2] == 'o') {\n              if (s[3] == ' ') AddMatch(id + 17 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'w') {\n            if (s[2] == 'i' && s[3] == 't' && s[4] == 'h' && s[5] == ' ') {\n              AddMatch(id + 35 * n, l + 6, l, matches);\n            }\n          }\n        } else if (s[0] == '\"') {\n          AddMatch(id + 19 * n, l + 1, l, matches);\n          if (s[1] == '>') {\n            AddMatch(id + 21 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '.') {\n          AddMatch(id + 20 * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + 31 * n, l + 2, l, matches);\n            if (s[2] == 'T' && s[3] == 'h') {\n              if (s[4] == 'e') {\n                if (s[5] == ' ') AddMatch(id + 43 * n, l + 6, l, matches);\n              } else if (s[4] == 'i') {\n                if (s[5] == 's' && s[6] == ' ') {\n                  AddMatch(id + 75 * n, l + 7, l, matches);\n                }\n              }\n            }\n          }\n        } else if (s[0] == ',') {\n          AddMatch(id + 76 * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + 14 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '\\n') {\n          AddMatch(id + 22 * n, l + 1, l, matches);\n          if (s[1] == '\\t') {\n            AddMatch(id + 50 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == ']') {\n          AddMatch(id + 24 * n, l + 1, l, matches);\n        } else if (s[0] == '\\'') {\n          AddMatch(id + 36 * n, l + 1, l, matches);\n        } else if (s[0] == ':') {\n          AddMatch(id + 51 * n, l + 1, l, matches);\n        } else if (s[0] == '(') {\n          AddMatch(id + 57 * n, l + 1, l, matches);\n        } else if (s[0] == '=') {\n          if (s[1] == '\"') {\n            AddMatch(id + 70 * n, l + 2, l, matches);\n          } else if (s[1] == '\\'') {\n            AddMatch(id + 86 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == 'a') {\n          if (s[1] == 'l' && s[2] == ' ') {\n            AddMatch(id + 84 * n, l + 3, l, matches);\n          }\n        } else if (s[0] == 'e') {\n          if (s[1] == 'd') {\n            if (s[2] == ' ') AddMatch(id + 53 * n, l + 3, l, matches);\n          } else if (s[1] == 'r') {\n            if (s[2] == ' ') AddMatch(id + 82 * n, l + 3, l, matches);\n          } else if (s[1] == 's') {\n            if (s[2] == 't' && s[3] == ' ') {\n              AddMatch(id + 95 * n, l + 4, l, matches);\n            }\n          }\n        } else if (s[0] == 'f') {\n          if (s[1] == 'u' && s[2] == 'l' && s[3] == ' ') {\n            AddMatch(id + 90 * n, l + 4, l, matches);\n          }\n        } else if (s[0] == 'i') {\n          if (s[1] == 'v') {\n            if (s[2] == 'e' && s[3] == ' ') {\n              AddMatch(id + 92 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'z') {\n            if (s[2] == 'e' && s[3] == ' ') {\n              AddMatch(id + 100 * n, l + 4, l, matches);\n            }\n          }\n        } else if (s[0] == 'l') {\n          if (s[1] == 'e') {\n            if (s[2] == 's' && s[3] == 's' && s[4] == ' ') {\n              AddMatch(id + 93 * n, l + 5, l, matches);\n            }\n          } else if (s[1] == 'y') {\n            if (s[2] == ' ') AddMatch(id + 61 * n, l + 3, l, matches);\n          }\n        } else if (s[0] == 'o') {\n          if (s[1] == 'u' && s[2] == 's' && s[3] == ' ') {\n            AddMatch(id + 106 * n, l + 4, l, matches);\n          }\n        }\n      } else {\n        /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and\n               is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL)\n           transform. */\n        const BROTLI_BOOL is_all_caps =\n            TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST);\n        const uint8_t* s;\n        if (!IsMatch(dictionary->words, w, data, max_length)) {\n          continue;\n        }\n        /* Transform \"\" + kUppercase{First,All} + \"\" */\n        AddMatch(id + (is_all_caps ? 44 : 9) * n, l, l, matches);\n        has_found_match = BROTLI_TRUE;\n        if (l + 1 >= max_length) {\n          continue;\n        }\n        /* Transforms \"\" + kUppercase{First,All} + <suffix> */\n        s = &data[l];\n        if (s[0] == ' ') {\n          AddMatch(id + (is_all_caps ? 68 : 4) * n, l + 1, l, matches);\n        } else if (s[0] == '\"') {\n          AddMatch(id + (is_all_caps ? 87 : 66) * n, l + 1, l, matches);\n          if (s[1] == '>') {\n            AddMatch(id + (is_all_caps ? 97 : 69) * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '.') {\n          AddMatch(id + (is_all_caps ? 101 : 79) * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 114 : 88) * n, l + 2, l, matches);\n          }\n        } else if (s[0] == ',') {\n          AddMatch(id + (is_all_caps ? 112 : 99) * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 107 : 58) * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '\\'') {\n          AddMatch(id + (is_all_caps ? 94 : 74) * n, l + 1, l, matches);\n        } else if (s[0] == '(') {\n          AddMatch(id + (is_all_caps ? 113 : 78) * n, l + 1, l, matches);\n        } else if (s[0] == '=') {\n          if (s[1] == '\"') {\n            AddMatch(id + (is_all_caps ? 105 : 104) * n, l + 2, l, matches);\n          } else if (s[1] == '\\'') {\n            AddMatch(id + (is_all_caps ? 116 : 108) * n, l + 2, l, matches);\n          }\n        }\n      }\n    }\n  }\n  /* Transforms with prefixes \" \" and \".\" */\n  if (max_length >= 5 && (data[0] == ' ' || data[0] == '.')) {\n    BROTLI_BOOL is_space = TO_BROTLI_BOOL(data[0] == ' ');\n    size_t offset = dictionary->buckets[Hash15(&data[1])];\n    BROTLI_BOOL end = !offset;\n    while (!end) {\n      DictWord w = dictionary->dict_words[offset++];\n      const size_t l = w.len & 0x1F;\n      const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n      const size_t id = w.idx;\n      end = !!(w.len & 0x80);\n      w.len = (uint8_t)l;\n      if (w.transform == 0) {\n        const uint8_t* s;\n        if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) {\n          continue;\n        }\n        /* Transforms \" \" + BROTLI_TRANSFORM_IDENTITY + \"\" and\n                      \".\" + BROTLI_TRANSFORM_IDENTITY + \"\" */\n        AddMatch(id + (is_space ? 6 : 32) * n, l + 1, l, matches);\n        has_found_match = BROTLI_TRUE;\n        if (l + 2 >= max_length) {\n          continue;\n        }\n        /* Transforms \" \" + BROTLI_TRANSFORM_IDENTITY + <suffix> and\n                      \".\" + BROTLI_TRANSFORM_IDENTITY + <suffix>\n        */\n        s = &data[l + 1];\n        if (s[0] == ' ') {\n          AddMatch(id + (is_space ? 2 : 77) * n, l + 2, l, matches);\n        } else if (s[0] == '(') {\n          AddMatch(id + (is_space ? 89 : 67) * n, l + 2, l, matches);\n        } else if (is_space) {\n          if (s[0] == ',') {\n            AddMatch(id + 103 * n, l + 2, l, matches);\n            if (s[1] == ' ') {\n              AddMatch(id + 33 * n, l + 3, l, matches);\n            }\n          } else if (s[0] == '.') {\n            AddMatch(id + 71 * n, l + 2, l, matches);\n            if (s[1] == ' ') {\n              AddMatch(id + 52 * n, l + 3, l, matches);\n            }\n          } else if (s[0] == '=') {\n            if (s[1] == '\"') {\n              AddMatch(id + 81 * n, l + 3, l, matches);\n            } else if (s[1] == '\\'') {\n              AddMatch(id + 98 * n, l + 3, l, matches);\n            }\n          }\n        }\n      } else if (is_space) {\n        /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and\n               is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL)\n           transform. */\n        const BROTLI_BOOL is_all_caps =\n            TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST);\n        const uint8_t* s;\n        if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) {\n          continue;\n        }\n        /* Transforms \" \" + kUppercase{First,All} + \"\" */\n        AddMatch(id + (is_all_caps ? 85 : 30) * n, l + 1, l, matches);\n        has_found_match = BROTLI_TRUE;\n        if (l + 2 >= max_length) {\n          continue;\n        }\n        /* Transforms \" \" + kUppercase{First,All} + <suffix> */\n        s = &data[l + 1];\n        if (s[0] == ' ') {\n          AddMatch(id + (is_all_caps ? 83 : 15) * n, l + 2, l, matches);\n        } else if (s[0] == ',') {\n          if (!is_all_caps) {\n            AddMatch(id + 109 * n, l + 2, l, matches);\n          }\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 111 : 65) * n, l + 3, l, matches);\n          }\n        } else if (s[0] == '.') {\n          AddMatch(id + (is_all_caps ? 115 : 96) * n, l + 2, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 117 : 91) * n, l + 3, l, matches);\n          }\n        } else if (s[0] == '=') {\n          if (s[1] == '\"') {\n            AddMatch(id + (is_all_caps ? 110 : 118) * n, l + 3, l, matches);\n          } else if (s[1] == '\\'') {\n            AddMatch(id + (is_all_caps ? 119 : 120) * n, l + 3, l, matches);\n          }\n        }\n      }\n    }\n  }\n  if (max_length >= 6) {\n    /* Transforms with prefixes \"e \", \"s \", \", \" and \"\\xC2\\xA0\" */\n    if ((data[1] == ' ' &&\n         (data[0] == 'e' || data[0] == 's' || data[0] == ',')) ||\n        (data[0] == 0xC2 && data[1] == 0xA0)) {\n      size_t offset = dictionary->buckets[Hash15(&data[2])];\n      BROTLI_BOOL end = !offset;\n      while (!end) {\n        DictWord w = dictionary->dict_words[offset++];\n        const size_t l = w.len & 0x1F;\n        const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n        const size_t id = w.idx;\n        end = !!(w.len & 0x80);\n        w.len = (uint8_t)l;\n        if (w.transform == 0 &&\n            IsMatch(dictionary->words, w, &data[2], max_length - 2)) {\n          if (data[0] == 0xC2) {\n            AddMatch(id + 102 * n, l + 2, l, matches);\n            has_found_match = BROTLI_TRUE;\n          } else if (l + 2 < max_length && data[l + 2] == ' ') {\n            size_t t = data[0] == 'e' ? 18 : (data[0] == 's' ? 7 : 13);\n            AddMatch(id + t * n, l + 3, l, matches);\n            has_found_match = BROTLI_TRUE;\n          }\n        }\n      }\n    }\n  }\n  if (max_length >= 9) {\n    /* Transforms with prefixes \" the \" and \".com/\" */\n    if ((data[0] == ' ' && data[1] == 't' && data[2] == 'h' &&\n         data[3] == 'e' && data[4] == ' ') ||\n        (data[0] == '.' && data[1] == 'c' && data[2] == 'o' &&\n         data[3] == 'm' && data[4] == '/')) {\n      size_t offset = dictionary->buckets[Hash15(&data[5])];\n      BROTLI_BOOL end = !offset;\n      while (!end) {\n        DictWord w = dictionary->dict_words[offset++];\n        const size_t l = w.len & 0x1F;\n        const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n        const size_t id = w.idx;\n        end = !!(w.len & 0x80);\n        w.len = (uint8_t)l;\n        if (w.transform == 0 &&\n            IsMatch(dictionary->words, w, &data[5], max_length - 5)) {\n          AddMatch(id + (data[0] == ' ' ? 41 : 72) * n, l + 5, l, matches);\n          has_found_match = BROTLI_TRUE;\n          if (l + 5 < max_length) {\n            const uint8_t* s = &data[l + 5];\n            if (data[0] == ' ') {\n              if (l + 8 < max_length &&\n                  s[0] == ' ' && s[1] == 'o' && s[2] == 'f' && s[3] == ' ') {\n                AddMatch(id + 62 * n, l + 9, l, matches);\n                if (l + 12 < max_length &&\n                    s[4] == 't' && s[5] == 'h' && s[6] == 'e' && s[7] == ' ') {\n                  AddMatch(id + 73 * n, l + 13, l, matches);\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n  return has_found_match;\n}\n\n/* Finds matches for one or more dictionaries, if multiple are present\n   in the contextual dictionary */\nBROTLI_BOOL BrotliFindAllStaticDictionaryMatches(\n    const BrotliEncoderDictionary* dictionary, const uint8_t* data,\n    size_t min_length, size_t max_length, uint32_t* matches) {\n  BROTLI_BOOL has_found_match =\n      BrotliFindAllStaticDictionaryMatchesFor(\n          dictionary, data, min_length, max_length, matches);\n\n  if (!!dictionary->parent && dictionary->parent->num_dictionaries > 1) {\n    uint32_t matches2[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1];\n    int l;\n    const BrotliEncoderDictionary* dictionary2 = dictionary->parent->dict[0];\n    if (dictionary2 == dictionary) {\n      dictionary2 = dictionary->parent->dict[1];\n    }\n\n    for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) {\n      matches2[l] = kInvalidMatch;\n    }\n\n    has_found_match |= BrotliFindAllStaticDictionaryMatchesFor(\n        dictionary2, data, min_length, max_length, matches2);\n\n    for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) {\n      if (matches2[l] != kInvalidMatch) {\n        uint32_t dist = (uint32_t)(matches2[l] >> 5);\n        uint32_t len_code = matches2[l] & 31;\n        uint32_t skipdist = (uint32_t)((uint32_t)(1 << dictionary->words->\n            size_bits_by_length[len_code]) & ~1u) *\n            (uint32_t)dictionary->num_transforms;\n        /* TODO(lode): check for dist overflow */\n        dist += skipdist;\n        AddMatch(dist, (size_t)l, len_code, matches);\n      }\n    }\n  }\n  return has_found_match;\n}\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/static_dict.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Class to model the static dictionary. */\n\n#ifndef BROTLI_ENC_STATIC_DICT_H_\n#define BROTLI_ENC_STATIC_DICT_H_\n\n#include \"../common/platform.h\"\n\n#include \"encoder_dict.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN 37\nstatic const uint32_t kInvalidMatch = 0xFFFFFFF;\n\n/* Matches data against static dictionary words, and for each length l,\n   for which a match is found, updates matches[l] to be the minimum possible\n     (distance << 5) + len_code.\n   Returns 1 if matches have been found, otherwise 0.\n   Prerequisites:\n     matches array is at least BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1 long\n     all elements are initialized to kInvalidMatch */\nBROTLI_INTERNAL BROTLI_BOOL BrotliFindAllStaticDictionaryMatches(\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* data, size_t min_length, size_t max_length,\n    uint32_t* matches);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_STATIC_DICT_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/static_dict_lut.c",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Lookup table for static dictionary and transforms. */\n\n#include \"static_dict_lut.h\"\n\n#include \"../common/platform.h\"  /* IWYU pragma: keep */\n#include \"../common/static_init.h\"\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\n#include \"../common/dictionary.h\"\n#include \"../common/transform.h\"\n#include \"hash_base.h\"\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\n\n/* TODO(eustas): deal with largest bucket(s). Not it contains 163 items. */\nstatic BROTLI_BOOL BROTLI_COLD DoBrotliEncoderInitStaticDictionaryLut(\n    const BrotliDictionary* dict, uint16_t* buckets, DictWord* words,\n    void* arena) {\n  DictWord* slots = (DictWord*)arena;\n  uint16_t* heads = (uint16_t*)(slots + BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS);\n  uint16_t* counts = heads + BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS;\n  uint16_t* prev = counts + BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS;\n  size_t next_slot = 0;\n  uint8_t transformed_word[24];\n  uint8_t transformed_other_word[24];\n  size_t l;\n  size_t pos;\n  size_t i;\n\n  memset(counts, 0, BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS * sizeof(uint16_t));\n  memset(heads, 0, BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS * sizeof(uint16_t));\n  memset(prev, 0, BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS * sizeof(uint16_t));\n\n  for (l = 4; l <= 24; ++l) {\n    size_t n = 1u << dict->size_bits_by_length[l];\n    const uint8_t* dict_words = dict->data + dict->offsets_by_length[l];\n    for (i = 0; i < n; ++i) {\n      const uint8_t* dict_word = dict_words + l * i;\n      uint32_t key = Hash15(dict_word);\n      slots[next_slot].len = (uint8_t)l;\n      slots[next_slot].transform = BROTLI_TRANSFORM_IDENTITY;\n      slots[next_slot].idx = (uint16_t)i;\n      prev[next_slot] = heads[key];\n      heads[key] = (uint16_t)next_slot;\n      counts[key]++;\n      ++next_slot;\n    }\n    for (i = 0; i < n; ++i) {\n      uint32_t key;\n      uint32_t prefix;\n      BROTLI_BOOL found;\n      size_t curr;\n      const uint8_t* dict_word = dict_words + l * i;\n      if (dict_word[0] < 'a' || dict_word[0] > 'z') continue;\n      memcpy(transformed_word, dict_word, l);\n      transformed_word[0] = transformed_word[0] - 32;\n      key = Hash15(transformed_word);\n      prefix = BROTLI_UNALIGNED_LOAD32LE(transformed_word) & ~0x20202020u;\n      found = BROTLI_FALSE;\n      curr = heads[key];\n      while (curr != 0) {\n        const uint8_t* other_word;\n        uint32_t other_prefix;\n        if (slots[curr].len != l) break;\n        other_word = dict_words + l * slots[curr].idx;\n        other_prefix = BROTLI_UNALIGNED_LOAD32LE(other_word) & ~0x20202020u;\n        if (prefix == other_prefix) {\n          if (memcmp(transformed_word, other_word, l) == 0) {\n            found = BROTLI_TRUE;\n            break;\n          }\n        }\n        curr = prev[curr];\n      }\n      if (found) continue;\n      slots[next_slot].len = (uint8_t)l;\n      slots[next_slot].transform = BROTLI_TRANSFORM_UPPERCASE_FIRST;\n      slots[next_slot].idx = (uint16_t)i;\n      prev[next_slot] = heads[key];\n      heads[key] = (uint16_t)next_slot;\n      counts[key]++;\n      ++next_slot;\n    }\n    for (i = 0; i < n; ++i) {\n      const uint8_t* dict_word = dict_words + l * i;\n      BROTLI_BOOL is_ascii = BROTLI_TRUE;\n      BROTLI_BOOL has_lower = BROTLI_FALSE;\n      size_t k;\n      uint32_t prefix;\n      uint32_t key;\n      size_t curr;\n      BROTLI_BOOL found;\n      for (k = 0; k < l; ++k) {\n        if (dict_word[k] >= 128) is_ascii = BROTLI_FALSE;\n        if (k > 0 && dict_word[k] >= 'a' && dict_word[k] <= 'z')\n          has_lower = BROTLI_TRUE;\n      }\n      if (!is_ascii || !has_lower) continue;\n      memcpy(transformed_word, dict_word, l);\n      prefix = BROTLI_UNALIGNED_LOAD32LE(transformed_word) & ~0x20202020u;\n      for (k = 0; k < l; ++k) {\n        if (transformed_word[k] >= 'a' && transformed_word[k] <= 'z') {\n          transformed_word[k] = transformed_word[k] - 32;\n        }\n      }\n      key = Hash15(transformed_word);\n      found = BROTLI_FALSE;\n      curr = heads[key];\n      while (curr != 0) {\n        const uint8_t* other_word;\n        uint32_t other_prefix;\n        if (slots[curr].len != l) break;\n        other_word = dict_words + l * slots[curr].idx;\n        other_prefix = BROTLI_UNALIGNED_LOAD32LE(other_word) & ~0x20202020u;\n        if (prefix == other_prefix) {\n          if (slots[curr].transform == BROTLI_TRANSFORM_IDENTITY) {\n            if (memcmp(transformed_word, other_word, l) == 0) {\n              found = BROTLI_TRUE;\n              break;\n            }\n          } else if (slots[curr].transform ==\n                     BROTLI_TRANSFORM_UPPERCASE_FIRST) {\n            if ((transformed_word[0] == (other_word[0] - 32)) &&\n                memcmp(transformed_word + 1, other_word + 1, l - 1) == 0) {\n              found = BROTLI_TRUE;\n              break;\n            }\n          } else {\n            for (k = 0; k < l; ++k) {\n              if (other_word[k] >= 'a' && other_word[k] <= 'z') {\n                transformed_other_word[k] = other_word[k] - 32;\n              } else {\n                transformed_other_word[k] = other_word[k];\n              }\n            }\n            if (memcmp(transformed_word, transformed_other_word, l) == 0) {\n              found = BROTLI_TRUE;\n              break;\n            }\n          }\n        }\n        curr = prev[curr];\n      }\n      if (found) {\n        continue;\n      }\n      slots[next_slot].len = (uint8_t)l;\n      slots[next_slot].transform = BROTLI_TRANSFORM_UPPERCASE_ALL;\n      slots[next_slot].idx = (uint16_t)i;\n      prev[next_slot] = heads[key];\n      heads[key] = (uint16_t)next_slot;\n      counts[key]++;\n      ++next_slot;\n    }\n  }\n\n  if (next_slot != 31704) return BROTLI_FALSE;\n  pos = 0;\n  /* Unused; makes offsets start from 1. */\n  words[pos].len = 0;\n  words[pos].transform = 0;\n  words[pos].idx = 0;\n  pos++;\n  for (i = 0; i < BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS; ++i) {\n    size_t num_words = counts[i];\n    size_t curr;\n    if (num_words == 0) {\n      buckets[i] = 0;\n      continue;\n    }\n    buckets[i] = (uint16_t)pos;\n    curr = heads[i];\n    pos += num_words;\n    for (size_t k = 0; k < num_words; ++k) {\n      words[pos - 1 - k] = slots[curr];\n      curr = prev[curr];\n    }\n    words[pos - 1].len |= 0x80;\n  }\n  return BROTLI_TRUE;\n}\n\nBROTLI_BOOL BrotliEncoderInitStaticDictionaryLut(\n    const BrotliDictionary* dict, uint16_t* buckets, DictWord* words) {\n  size_t arena_size =\n      BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS *\n          (sizeof(uint16_t) + sizeof(DictWord)) +\n      BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS * 2 * sizeof(uint16_t);\n  void* arena = malloc(arena_size);\n  BROTLI_BOOL ok;\n  if (arena == NULL) {\n    return BROTLI_FALSE;\n  }\n  ok = DoBrotliEncoderInitStaticDictionaryLut(dict, buckets, words, arena);\n  free(arena);\n  return ok;\n}\n\nBROTLI_MODEL(\"small\")\nuint16_t kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS];\nBROTLI_MODEL(\"small\")\nDictWord kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS];\n\n#else  /* BROTLI_STATIC_INIT */\n\n/* Embed kStaticDictionaryBuckets and kStaticDictionaryWords. */\n#include \"static_dict_lut_inc.h\"\n\n#endif  /* BROTLI_STATIC_INIT */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n} /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/static_dict_lut.h",
    "content": "﻿/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Lookup table for static dictionary and transforms. */\n\n#ifndef BROTLI_ENC_STATIC_DICT_LUT_H_\n#define BROTLI_ENC_STATIC_DICT_LUT_H_\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"../common/static_init.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct DictWord {\n  /* Highest bit is used to indicate end of bucket. */\n  uint8_t len;\n  uint8_t transform;\n  uint16_t idx;\n} DictWord;\n\n/* Buckets are Hash15 results. */\n#define BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS 32768\n#define BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS 31705\n\n#if (BROTLI_STATIC_INIT != BROTLI_STATIC_INIT_NONE)\nBROTLI_INTERNAL BROTLI_BOOL BrotliEncoderInitStaticDictionaryLut(\n    const BrotliDictionary* dictionary, uint16_t* buckets, DictWord* words);\nBROTLI_INTERNAL extern BROTLI_MODEL(\"small\") uint16_t\n    kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS];\nBROTLI_INTERNAL extern BROTLI_MODEL(\"small\") DictWord\n    kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS];\n#else\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\") uint16_t\n    kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS];\nBROTLI_INTERNAL extern const BROTLI_MODEL(\"small\") DictWord\n    kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS];\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_STATIC_DICT_LUT_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/static_dict_lut_inc.h",
    "content": "﻿const BROTLI_MODEL(\"small\")\nuint16_t kStaticDictionaryBuckets[BROTLI_ENC_STATIC_DICT_LUT_NUM_BUCKETS] = {\n1,0,0,0,0,0,0,0,0,3,6,0,0,0,0,0,20,0,0,0,21,0,22,0,0,0,0,0,0,0,0,23,0,0,25,0,29,\n0,53,0,0,0,0,0,0,55,0,0,0,0,0,0,61,76,0,0,0,94,0,0,0,0,0,0,96,0,97,0,98,0,0,0,0,\n0,0,0,99,101,106,108,0,0,0,0,0,110,0,111,112,0,113,118,124,0,0,0,0,0,125,128,0,0\n,0,0,129,0,0,131,0,0,0,0,0,0,132,0,0,135,0,0,0,137,0,0,0,0,0,138,139,0,0,0,0,0,0\n,0,142,143,144,0,0,0,0,0,145,0,0,0,146,149,151,152,0,0,153,0,0,0,0,0,0,0,0,0,0,0\n,0,0,0,0,154,0,0,0,0,0,0,155,0,0,0,0,160,182,0,0,0,0,0,0,183,0,0,0,188,189,0,0,\n192,0,0,0,0,0,0,194,0,0,0,0,0,0,0,0,197,202,209,0,0,210,0,224,0,0,0,225,0,0,0,0,\n0,0,0,0,0,0,231,0,0,0,232,0,240,0,0,242,0,0,0,0,0,0,0,0,0,0,0,244,0,0,0,246,0,0,\n249,251,253,0,0,0,0,0,258,0,0,261,263,0,0,0,267,0,0,268,0,269,0,0,0,0,0,0,0,0,0,\n271,0,0,0,0,0,0,272,0,273,0,277,0,278,286,0,0,0,0,287,0,289,290,291,0,0,0,295,0,\n0,296,297,0,0,0,0,0,0,0,0,0,0,298,0,0,0,299,0,0,305,0,324,0,0,0,0,0,327,0,328,\n329,0,0,0,0,336,0,0,340,0,341,342,343,0,0,346,0,348,0,0,0,0,0,0,349,351,0,0,355,\n0,363,0,364,0,368,369,0,370,0,0,0,0,0,0,0,372,0,0,0,0,0,0,0,0,0,0,0,373,0,375,0,\n0,0,0,376,377,0,0,394,395,396,0,0,398,0,0,0,0,400,0,0,408,0,0,0,0,420,0,0,0,0,0,\n0,421,0,0,422,423,0,0,429,435,436,442,0,0,443,0,444,445,453,456,0,457,0,0,0,0,0,\n458,0,0,0,459,0,0,0,460,0,462,463,465,0,0,0,0,0,0,466,469,0,0,0,0,0,0,470,0,0,0,\n474,0,476,0,0,0,0,483,0,485,0,0,0,486,0,0,488,491,492,0,0,497,499,500,0,501,0,0,\n0,505,0,0,506,0,0,0,507,0,0,0,509,0,0,0,0,511,512,519,0,0,0,0,0,0,529,530,0,0,0,\n534,0,0,0,0,543,0,0,0,0,0,0,0,0,0,553,0,0,0,0,557,560,0,0,0,0,0,0,561,0,564,0,0,\n0,0,0,0,565,566,0,575,0,619,0,620,0,0,623,624,0,0,0,625,0,0,626,627,0,0,628,0,0,\n0,0,630,0,631,0,0,0,0,0,0,0,0,0,641,0,0,0,0,643,656,668,0,0,0,673,0,0,0,674,0,0,\n0,0,0,0,0,0,682,0,687,0,690,0,693,699,700,0,0,0,0,0,0,704,705,0,0,0,0,707,710,0,\n711,0,0,0,0,726,0,0,729,0,0,0,730,731,0,0,0,0,0,752,0,0,0,762,0,763,0,0,767,0,0,\n0,770,774,0,0,775,0,0,0,0,0,0,0,0,0,0,776,0,0,0,777,783,0,0,0,785,788,0,0,0,0,\n790,0,0,0,793,0,0,0,0,794,0,0,804,819,821,0,827,0,0,0,834,0,0,835,0,0,0,841,0,\n844,0,850,851,859,0,860,0,0,0,0,0,0,0,874,0,876,0,877,890,0,0,0,0,0,0,0,0,893,\n894,898,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,0,0,900,904,906,0,0,0,907,0,908,909,\n0,910,0,0,0,0,911,0,0,0,0,0,916,0,0,0,922,925,0,930,0,934,0,0,0,0,0,943,0,0,944,\n0,953,954,0,0,0,0,0,0,955,0,962,963,0,0,976,0,0,977,978,979,980,0,981,0,0,0,0,\n984,0,0,985,0,0,987,989,991,0,0,0,0,0,0,0,0,0,992,0,0,0,993,0,0,0,0,0,0,996,0,0,\n0,1000,0,0,0,0,0,1002,0,0,0,0,1005,1007,0,0,0,1009,0,0,0,1010,0,0,0,0,0,0,1011,0\n,1012,0,0,0,0,1014,1016,0,0,0,1020,0,1021,0,0,0,0,1022,0,0,0,1024,0,0,0,0,0,0,\n1025,0,0,1026,1027,0,0,0,0,0,1031,0,1033,0,0,0,0,1034,0,0,0,1037,1040,0,0,0,1042\n,1043,0,0,1053,0,1054,0,0,1057,0,0,0,1058,0,0,1060,0,0,0,0,0,0,0,1061,0,0,1062,0\n,0,0,0,1063,0,0,0,0,1064,0,0,0,0,0,1065,0,0,0,0,1066,1067,0,0,0,1069,1070,1072,0\n,0,0,0,0,0,1073,0,1075,0,0,0,0,0,0,1080,1084,0,0,0,0,1088,0,0,0,0,0,0,1094,0,\n1095,0,1107,0,0,0,1112,1114,0,1119,0,1122,0,0,1126,0,1129,0,1130,0,0,0,0,0,1132,\n0,0,0,0,0,0,1144,0,0,1145,1146,0,1148,1149,0,0,1150,1151,0,0,0,0,1152,0,1153,0,0\n,0,0,0,1154,0,1163,0,0,0,1164,0,0,0,0,0,1165,0,1167,0,1170,0,0,0,0,0,1171,1172,0\n,0,0,0,0,0,0,0,1173,1175,1177,0,1186,0,0,0,0,0,0,0,0,0,0,1195,0,0,1221,0,0,1224,\n0,0,1227,0,0,0,0,0,1228,1229,0,0,1230,0,0,0,0,0,0,0,0,0,1231,0,0,0,1233,0,0,1243\n,1244,1246,1248,0,0,0,0,1254,1255,1258,1259,0,0,0,1260,0,0,1261,0,0,0,1262,1264,\n0,0,1265,0,0,0,0,0,0,0,0,0,0,0,0,1266,0,1267,0,0,0,0,1273,1274,1276,1289,0,0,\n1291,1292,1293,0,0,1294,1295,1296,0,0,0,0,1302,0,1304,0,0,0,0,0,0,0,0,0,1311,\n1312,0,1314,0,1316,1320,1321,0,0,0,0,0,0,0,1322,1323,1324,0,1335,0,1336,0,0,0,0,\n1341,1342,0,1346,0,1357,0,0,0,1358,1360,0,0,0,0,0,0,1361,0,0,0,1362,1365,0,1366,\n0,0,0,0,0,0,0,1379,0,0,0,0,0,0,0,0,0,0,0,0,1386,0,1388,0,0,0,0,0,0,0,0,0,0,0,0,0\n,0,1395,0,0,0,0,1403,0,1405,0,0,1407,0,0,0,0,0,1408,1409,0,1410,0,0,0,1412,1413,\n1416,0,0,1429,1451,0,0,1454,0,0,0,0,0,0,0,1455,0,0,0,0,0,0,0,1456,0,0,0,0,1459,\n1460,1461,1475,0,0,0,0,0,0,1477,0,1480,0,1481,0,0,1486,0,0,1495,0,0,0,1496,0,0,\n1498,1499,1501,1520,1521,0,0,0,1526,0,0,0,0,1528,1529,0,1533,1536,0,0,0,1537,\n1538,1549,0,1550,1558,1559,1572,0,1573,0,0,0,0,0,0,0,0,0,1575,0,0,0,0,0,1579,0,\n1599,0,1603,0,1604,0,1605,0,0,0,0,0,1608,1610,0,0,0,0,1611,0,1615,0,1616,1618,0,\n1619,0,0,1622,0,0,0,0,1634,0,0,0,1635,0,0,0,1641,0,0,0,0,0,0,0,0,0,1643,0,0,0,\n1650,0,0,1652,0,0,0,0,0,1653,0,0,0,1654,0,0,0,0,1655,0,1662,0,0,1663,1664,0,0,\n1668,0,0,1669,1670,0,1672,1673,0,0,0,0,0,1674,0,0,0,1675,1676,1680,0,1682,0,0,\n1687,0,0,0,0,0,1704,0,0,1705,0,0,1721,0,0,0,0,1734,1735,0,0,0,0,1737,0,0,0,0,\n1739,0,0,1740,0,0,0,0,0,0,0,0,0,0,1741,1743,0,0,0,0,1745,0,0,0,1749,0,0,0,1751,0\n,0,0,0,0,0,1760,0,0,0,0,1765,0,0,0,0,0,1784,0,1785,1787,0,0,0,0,1788,1789,0,0,0,\n0,1790,1791,1793,0,1798,1799,0,0,0,0,1801,0,1803,1805,0,0,0,1806,1811,0,1812,\n1814,0,1821,0,0,0,0,0,1822,1833,0,0,0,0,0,0,1848,0,0,0,0,0,0,1857,0,0,0,1859,0,0\n,0,0,1861,0,0,0,0,0,0,0,1866,0,1921,1925,0,0,0,1929,1930,0,0,0,0,0,0,0,0,0,1931,\n0,0,0,0,1932,0,0,0,1934,0,0,0,0,0,0,0,0,1946,0,0,1948,0,0,0,0,1950,0,1957,0,1958\n,0,0,0,0,0,1965,1967,0,0,0,0,1968,0,1969,0,1971,1972,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n,0,1973,0,0,0,0,1975,0,0,0,0,1976,1979,0,1982,0,0,0,0,1984,1988,0,0,0,0,1990,\n2004,2008,0,0,0,2012,2013,0,0,0,0,0,0,0,0,0,0,2015,0,2016,2017,0,0,0,0,2021,0,0,\n2025,0,0,0,0,0,2029,2036,2040,0,2042,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2043,0,0,0,0,0,\n2045,0,0,0,0,0,0,0,2046,2047,0,2048,2049,0,2059,0,0,2063,0,2064,2065,0,0,2066,0,\n0,0,0,0,0,2069,0,0,0,0,2070,0,2071,0,2072,0,0,0,0,2080,2082,2083,0,0,0,0,0,2085,\n0,2086,2088,2089,2105,0,0,0,0,2107,0,0,2116,2117,0,2120,0,0,2122,0,0,0,0,0,2123,\n0,0,2125,2127,2128,0,0,0,2130,0,0,0,2137,2139,2140,2141,0,0,0,0,0,0,0,0,0,2144,\n2145,0,0,2146,2149,0,0,0,0,2150,0,0,2151,2158,0,2159,0,2160,0,0,0,0,0,0,2161,\n2162,0,0,2194,2202,0,0,0,0,0,0,2205,2217,0,2220,0,2221,0,2222,2224,0,0,0,0,2237,\n0,0,0,0,0,2238,0,2239,2241,0,0,2242,0,0,0,0,0,2243,0,0,0,0,0,0,2252,0,0,2253,0,0\n,0,2257,2258,0,0,0,2260,0,0,0,0,0,0,0,2262,0,2264,0,0,0,0,0,2269,2270,0,0,0,0,0,\n0,0,0,0,2271,0,2273,0,0,0,0,2277,0,0,0,0,2278,0,0,0,0,2279,0,2280,0,2283,0,0,0,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2287,0,0,0,0,0,0,0,2289,2290,0,0,0,0,2291,0,2292,0,\n0,0,2293,2295,2296,0,0,0,0,0,0,0,2298,0,0,0,0,0,2303,0,2305,0,0,2306,0,2307,0,0,\n0,0,0,0,0,0,0,0,0,0,2313,2314,2315,2316,0,0,2318,0,2319,0,2322,0,0,2323,0,2324,0\n,2326,0,0,0,0,0,0,0,2335,0,2336,2338,2339,0,2340,0,0,0,2355,0,2375,0,2382,2386,0\n,2387,0,0,2394,0,0,0,0,2395,0,2397,0,0,0,0,0,2398,0,0,0,0,0,0,0,2399,2402,2404,\n2408,2411,0,0,0,2413,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2415,0,0,2416,2417,2419,0,2420,\n0,0,0,0,0,2425,0,0,0,2426,0,0,0,0,0,0,0,0,0,0,0,0,2427,2428,0,2429,0,0,2430,2434\n,0,2436,0,0,0,0,0,0,2441,2442,0,2445,0,0,2446,2457,0,2459,0,0,2462,0,2464,0,2477\n,0,2478,2486,0,0,0,2491,0,0,2493,0,0,2494,0,2495,0,2513,2523,0,0,0,0,2524,0,0,0,\n0,0,0,2528,2529,2530,0,0,2531,0,2533,0,0,2534,2535,0,2536,2537,0,2538,0,2539,\n2540,0,0,0,2545,2546,0,0,0,0,0,0,0,2548,0,0,2549,0,2550,2555,0,0,0,0,0,2557,0,\n2560,0,0,0,0,0,0,0,0,0,0,0,2561,0,2576,0,0,0,0,0,0,0,0,0,2577,2578,0,0,0,2579,0,\n0,0,0,0,0,0,2580,0,0,0,0,2581,0,0,0,0,2583,0,2584,0,2588,2590,0,0,0,2591,0,0,0,0\n,2593,2594,0,2595,0,2601,2602,0,0,2603,0,2605,0,0,0,2606,2607,2611,0,2615,0,0,0,\n2617,0,0,0,0,0,0,0,0,0,0,0,0,0,2619,0,0,2620,0,0,0,2621,0,2623,0,2625,0,0,2628,\n2629,0,0,2635,2636,2637,0,0,2639,0,0,0,2642,0,0,0,0,2643,0,2644,0,2649,0,0,0,0,0\n,0,2655,2656,0,0,2657,0,0,0,0,0,2658,0,0,0,0,0,2659,0,0,0,0,2664,2685,0,2687,0,\n2688,0,0,2689,0,0,2694,0,2695,0,0,2698,0,2701,2706,0,0,0,2707,0,2709,2710,2711,0\n,0,0,2720,2730,2735,0,0,0,0,2738,2740,0,0,0,0,2747,0,0,0,0,0,0,2748,0,0,2749,0,0\n,0,0,0,2750,0,0,2752,2754,0,0,0,0,0,2758,0,0,0,0,2762,0,0,0,0,2763,0,0,0,0,0,0,0\n,2764,2767,0,0,0,0,2768,0,0,2770,0,0,0,0,0,0,0,2771,0,0,0,0,0,0,0,0,0,2772,0,0,0\n,0,0,2773,2776,0,0,2783,0,0,2784,0,2789,0,2790,0,0,0,2792,0,0,0,0,0,0,0,0,0,0,\n2793,2795,0,0,0,0,0,0,2796,0,0,0,0,0,0,2797,2799,0,0,0,0,2803,0,0,0,0,2806,0,\n2807,2808,2817,2819,0,0,0,0,0,2821,0,0,0,0,2822,2823,0,0,0,0,0,0,0,2824,0,0,2828\n,0,2834,0,0,0,0,0,0,2836,0,2838,0,0,2839,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2841,\n0,0,0,2842,0,0,0,0,0,2843,2844,0,0,0,0,2846,0,0,2847,0,2849,0,2853,0,0,0,0,0,\n2857,0,0,0,0,2858,0,2859,0,0,2860,0,2862,2868,0,0,0,0,2875,0,2876,0,0,2877,2878,\n2884,2889,2890,0,0,2891,0,0,2892,0,0,0,2906,2912,0,2913,0,0,0,0,0,0,0,0,2916,0,\n2934,0,0,0,0,0,2935,0,0,0,0,2939,0,2940,0,0,0,0,0,0,0,2941,0,0,0,2946,0,2949,0,0\n,2950,2954,2955,0,0,0,2959,2961,0,0,2962,0,2963,0,0,0,0,0,0,2964,2965,2966,2967,\n0,0,0,0,0,0,0,2969,0,0,0,0,0,2970,2975,0,2982,2983,2984,0,0,0,0,0,2989,0,0,2990,\n0,0,0,0,0,0,0,2991,0,0,0,0,0,0,0,0,2998,0,3000,3001,0,0,3002,0,0,0,3003,0,0,3012\n,0,0,3022,0,0,3024,0,0,3025,3027,0,0,0,3030,0,0,0,0,3034,3035,0,0,3036,0,3039,0,\n3049,0,0,3050,0,0,0,0,0,0,3051,0,3053,0,0,0,0,3057,0,3058,0,0,0,0,0,0,0,0,3063,0\n,0,3073,3074,3078,3079,0,3080,3086,0,0,0,0,0,0,0,0,3087,0,3092,0,3095,0,3099,0,0\n,0,3100,0,3101,3102,0,3122,0,0,0,3124,0,3125,0,0,0,0,0,0,3132,3134,0,0,3136,0,0,\n0,0,0,0,0,3147,0,0,3149,0,0,0,0,0,3150,3151,3152,0,0,0,0,3158,0,0,3160,0,0,3161,\n0,0,3162,0,3163,3166,3168,0,0,3169,3170,0,0,3171,0,0,0,0,0,0,0,3182,0,3184,0,0,\n3188,0,0,3194,0,0,0,0,0,0,3204,0,0,0,0,3209,0,0,0,0,0,0,0,0,0,0,0,3216,3217,0,0,\n0,0,0,0,0,3219,0,0,3220,3222,0,3223,0,0,0,0,3224,0,3225,3226,0,3228,3233,0,3239,\n3241,3242,0,0,3251,3252,3253,3255,0,0,0,0,0,0,0,0,3260,0,0,3261,0,0,0,3267,0,0,0\n,0,0,0,0,0,3271,0,0,0,3278,0,3282,0,0,0,3284,0,0,0,3285,3286,0,0,0,0,0,0,0,3287,\n3292,0,0,0,0,3294,3296,0,0,3299,3300,3301,0,3302,0,0,0,0,0,3304,3306,0,0,0,0,0,0\n,3308,0,0,0,0,0,0,0,0,0,3311,0,0,0,0,0,0,0,0,3312,3314,3315,0,3318,0,0,0,0,0,0,0\n,0,3319,0,0,0,0,0,3321,0,0,0,0,0,0,0,0,0,3322,0,0,3324,3325,0,0,3326,0,0,3328,\n3329,3331,0,0,3335,0,0,3337,0,3338,0,0,0,0,3343,3347,0,0,0,3348,0,0,3351,0,0,0,0\n,0,0,3354,0,0,0,0,0,0,0,0,0,0,3355,0,0,3365,3366,3367,0,0,0,0,0,0,3368,3369,0,\n3370,0,0,3373,0,0,3376,0,0,3377,0,3379,3387,0,0,0,0,0,3390,0,0,0,0,0,0,0,3402,0,\n3403,3436,3437,3439,0,0,3441,0,0,0,3442,0,0,3449,0,0,0,3450,0,0,0,0,0,0,0,3451,0\n,0,3452,0,3453,3456,0,3457,0,0,3458,0,3459,0,0,0,0,0,0,0,0,0,3460,0,0,3469,3470,\n0,0,3475,0,0,0,3480,3487,3489,0,3490,0,0,3491,3499,0,3500,0,0,3501,0,0,0,3502,0,\n3514,0,0,0,3516,3517,0,0,0,3518,0,0,0,0,3520,3521,3522,0,0,3526,3530,0,0,0,0,\n3531,0,0,0,0,3536,0,0,0,0,0,0,0,3539,3541,0,0,3542,3544,0,3547,3548,0,0,3550,0,\n3553,0,0,0,0,0,0,0,3554,0,3555,0,3558,0,3559,0,0,0,0,0,0,0,0,3563,0,3581,0,0,0,\n3599,0,0,0,3600,0,3601,0,3602,3603,0,0,3606,3608,0,3610,3611,0,0,0,0,0,0,0,0,0,\n3612,3616,3619,0,0,0,0,0,0,0,0,0,0,0,0,0,3624,3628,0,3629,3634,3635,0,0,0,0,0,0,\n3636,0,3637,0,0,3638,3651,0,0,0,0,0,0,3652,3653,0,0,0,0,3656,3657,0,0,0,0,0,3658\n,0,0,0,0,3659,0,3661,3663,3664,0,3665,0,3692,0,0,0,3694,3696,0,0,0,0,0,0,0,0,0,0\n,0,0,3698,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3700,0,0,3701,0,0,0,3708,3709,0,0,0,3711\n,3712,0,0,0,0,0,3723,0,3724,3725,0,0,3726,0,0,0,0,0,0,3728,3729,0,3734,3735,3737\n,0,0,0,3743,0,3745,0,0,3746,0,0,3747,3748,0,3757,0,3759,3766,3767,0,3768,0,0,0,0\n,3769,0,0,3771,0,3774,0,0,0,0,0,0,3775,0,0,0,0,0,0,3776,0,3777,3786,0,3788,3789,\n0,0,0,0,0,0,0,0,0,3791,0,3811,0,0,0,0,0,3814,3815,3816,3820,0,0,0,0,0,0,0,3821,0\n,0,3825,0,0,0,0,3835,0,0,3848,3849,0,0,0,0,3850,3851,3853,0,0,0,0,3859,0,3860,\n3862,0,0,0,0,0,3863,0,0,0,0,0,0,0,0,3873,0,3874,0,3875,3886,0,3887,0,0,0,0,3892,\n3913,0,3914,0,0,0,3925,3931,0,0,0,0,3934,3941,3942,0,0,0,0,3943,0,0,0,3944,0,0,0\n,0,0,3945,0,3947,0,0,0,3956,3957,0,0,0,0,0,0,0,0,0,3958,0,3959,3965,0,0,0,0,3966\n,0,0,0,3967,0,0,0,3968,3974,0,0,0,0,0,3975,3977,3978,0,0,0,0,3980,0,3985,0,0,0,0\n,0,0,0,0,3986,4011,0,0,4017,0,0,0,0,0,0,0,0,0,0,0,4018,0,0,0,0,4019,0,4023,0,0,0\n,4027,4028,0,0,0,0,0,0,0,0,4031,4034,0,0,4035,4037,4039,4040,0,0,0,0,0,4059,0,\n4060,4061,0,4062,4063,4066,0,0,4072,0,0,0,0,0,0,0,0,0,0,0,0,0,4088,0,0,0,0,0,\n4091,0,0,0,0,4094,4095,0,0,4096,0,0,0,0,0,4098,4099,0,0,0,4101,0,4104,0,0,0,4105\n,4108,0,4113,0,0,4115,4116,0,4126,0,0,4127,0,0,0,0,0,0,0,4128,4132,4133,0,4134,0\n,0,0,4137,0,0,4141,0,0,0,0,4144,4146,4147,0,0,0,0,4148,0,0,4311,0,0,0,4314,4329,\n0,4331,4332,0,4333,0,4334,0,0,0,4335,0,4336,0,0,0,4337,0,0,0,4342,4345,4346,4350\n,0,4351,4352,0,4354,4355,0,0,4364,0,0,0,0,4369,0,0,0,4373,0,4374,0,0,0,0,4377,0,\n0,0,0,4378,0,0,0,4380,0,0,0,4381,4382,0,0,0,0,0,0,0,4384,0,0,0,0,4385,0,0,0,4386\n,0,0,0,4391,4398,0,0,0,0,4407,4409,0,0,0,0,4410,0,0,4411,0,4414,4415,4418,0,4427\n,4428,4430,0,4431,0,4448,0,0,0,0,0,4449,0,0,0,4451,4452,0,4453,4454,0,4456,0,0,0\n,0,0,0,0,4459,0,4463,0,0,0,0,0,4466,0,4467,0,4469,0,0,0,0,0,0,0,0,0,0,0,0,0,4470\n,4471,0,4473,0,0,4475,0,0,0,0,4477,4478,0,0,0,4479,4481,0,4482,0,4484,0,0,0,0,0,\n0,0,4486,0,0,4488,0,0,4497,0,4508,0,0,4510,4511,0,4520,4523,0,4524,0,4525,0,4527\n,0,0,4528,0,0,0,0,4530,0,4531,0,0,4532,0,0,0,4533,0,0,0,0,0,4535,0,0,0,4536,0,0,\n0,0,0,4541,4543,4544,4545,4547,0,4548,0,0,0,0,4550,4551,0,4553,0,0,0,0,4562,0,0,\n4571,0,0,0,4574,0,0,0,4575,0,4576,0,4577,0,0,0,4581,0,0,0,0,0,4582,0,0,4586,0,0,\n0,4588,0,0,4597,0,4598,0,0,0,0,4616,4617,0,4618,0,0,0,0,4619,0,4620,0,0,4621,0,\n4624,0,0,0,0,0,4625,0,0,0,0,4657,0,4659,0,4667,0,0,0,4668,4670,0,4672,0,0,0,0,0,\n4673,4676,0,0,0,0,4687,0,0,0,0,4697,0,0,0,0,4699,0,4701,0,0,0,0,4702,0,0,4706,0,\n0,4713,0,0,0,4714,4715,4716,0,0,0,0,0,0,0,0,0,0,0,0,4717,0,0,4720,0,4721,4729,\n4735,0,0,0,4737,0,0,0,4739,0,0,0,4740,0,0,0,4741,0,0,0,0,0,4742,0,4745,4746,4747\n,0,0,0,0,0,0,0,0,4748,0,0,0,4749,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4751,\n4786,0,4787,0,4788,4796,0,0,4797,4798,0,4799,4806,4807,0,0,0,0,4809,4810,0,0,0,0\n,0,0,4811,0,0,0,0,0,4812,0,4813,0,0,4815,0,4821,4822,0,0,0,0,4823,0,0,0,0,0,0,0,\n0,0,0,4824,0,0,0,0,4826,0,0,0,4828,0,4829,0,0,0,4843,0,0,4847,0,4853,4855,4858,0\n,0,0,0,0,4859,0,4864,0,0,4879,0,0,0,0,4880,0,0,0,0,4881,0,4882,0,0,0,0,0,0,0,0,0\n,4883,0,0,0,0,4884,0,0,0,0,0,4886,4887,4888,4894,4896,0,4902,0,0,4905,0,0,4915,0\n,0,0,0,0,0,0,4916,4917,4919,4921,0,0,0,0,0,4926,0,0,0,0,4927,0,0,0,0,0,0,0,0,\n4929,0,4930,4931,0,4938,0,4952,0,4953,4957,4960,4964,0,0,0,0,0,0,0,5019,5020,\n5022,0,0,0,0,0,5023,0,0,0,5024,0,0,0,5025,0,0,0,0,5028,0,0,0,0,5029,5030,5031,0,\n5033,0,0,0,0,0,0,0,0,0,5034,5035,0,5036,0,0,5037,0,0,0,0,5038,0,0,5039,0,0,0,\n5041,5042,0,0,0,0,5044,5049,5054,0,5055,0,5057,0,0,0,5060,0,0,0,0,0,5063,0,5064,\n5065,0,5067,0,0,0,5068,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5076,0,0,0,0,0,0,\n0,5077,0,0,5078,5080,0,0,5083,0,0,0,0,0,0,0,0,5085,0,0,0,0,0,0,5098,5099,5101,\n5105,5107,0,5108,0,5109,0,0,0,0,0,0,0,5110,0,0,0,0,0,5117,5118,0,5121,0,5122,0,0\n,5130,0,0,0,5137,0,0,0,5148,0,0,0,0,0,0,0,5151,5154,0,0,0,5155,0,0,5156,5159,\n5161,0,0,0,0,5162,0,0,0,0,5163,5164,0,5166,0,0,0,0,0,0,0,0,0,0,5167,0,0,0,5172,0\n,0,0,0,0,0,5178,5179,0,0,5190,0,0,5191,5192,5194,0,0,5198,5201,0,0,0,0,0,5203,0,\n5206,5209,0,0,0,0,0,0,5213,0,5214,5216,0,0,0,0,0,5217,0,0,0,0,0,0,0,0,5218,5219,\n0,5231,0,0,5244,5249,0,5254,0,5255,0,0,5257,0,0,0,0,0,5258,0,5260,5270,0,5277,0,\n0,0,0,0,0,5280,5281,5282,5283,0,0,0,0,0,5284,0,5285,0,0,0,0,0,5287,5288,0,0,0,0,\n0,0,0,0,0,0,5289,5291,0,0,5294,0,0,5295,0,0,0,0,0,0,0,5304,0,0,5306,5307,5308,0,\n5309,0,0,5310,0,0,0,0,5311,5312,0,5313,0,0,0,0,0,5316,0,0,0,5317,0,0,0,0,0,0,0,0\n,0,5325,0,0,0,0,0,0,5326,0,5327,5329,0,5332,0,0,0,0,5338,0,0,0,0,0,0,0,0,5340,0,\n0,5341,0,0,0,5342,0,5343,5344,0,0,5345,0,0,0,0,0,0,5347,5348,0,0,0,0,0,0,0,0,0,\n5349,0,5350,0,5354,0,0,0,0,5358,0,0,5359,0,0,5361,0,0,5365,0,5367,0,5373,0,0,0,\n5379,0,0,0,5380,0,0,0,5382,0,5384,0,0,0,0,0,0,5385,0,0,0,0,5387,0,0,0,0,0,0,5388\n,5390,5393,0,0,0,0,0,0,0,0,0,0,0,5396,0,0,0,0,5397,5402,0,0,0,0,0,5403,0,0,0,\n5404,5405,0,0,0,0,0,0,0,0,0,0,0,0,5406,0,0,0,0,5410,0,0,5411,0,5415,0,0,0,0,5416\n,5434,0,0,0,0,0,0,0,0,0,0,0,5438,0,5440,0,0,0,0,0,0,5441,5442,0,0,0,5443,5444,\n5447,0,0,5448,5449,5451,0,0,0,5456,5457,0,0,0,5459,0,0,0,5461,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,5464,0,5466,0,0,5467,0,5470,0,0,5473,0,0,5474,0,0,5476,0,0,0,0,0,0,0,0\n,0,0,0,5477,0,0,0,0,0,0,0,5484,0,0,5485,5486,0,0,0,0,0,5488,0,0,0,0,0,0,0,5489,0\n,0,0,0,0,5507,0,0,0,5510,0,5511,0,0,5512,0,0,0,5513,0,5515,0,0,5516,5517,0,5518,\n0,0,5522,0,0,0,0,0,5534,5535,0,0,5536,0,5538,0,0,5543,0,5544,0,0,5545,0,5547,0,\n5557,0,0,5558,0,5560,5567,0,0,0,0,5568,0,0,0,5571,5573,0,5574,0,5575,0,0,0,0,\n5577,0,0,5598,0,0,0,0,0,0,0,0,0,5600,5609,0,0,0,0,5610,0,0,5612,0,5624,0,5625,0,\n0,0,5629,0,5641,0,5642,5643,0,0,0,0,0,0,5651,0,0,0,5652,5653,0,5661,5662,5678,0,\n5679,0,0,0,0,5685,5686,0,0,0,0,0,5690,5692,0,5703,0,0,0,0,0,5706,0,0,0,0,5707,0,\n0,0,0,0,0,5708,0,0,5709,0,5710,0,0,0,5712,0,5733,0,5734,5735,0,0,5744,5751,0,0,0\n,0,0,0,0,0,0,0,0,0,5752,0,5754,0,0,0,0,0,0,5757,5758,0,5760,5761,0,0,0,0,5763,\n5764,5765,0,5766,0,5767,5768,0,5770,0,0,0,0,5776,5780,0,0,0,0,5782,0,0,0,0,5784,\n0,0,5788,0,0,0,0,0,0,0,0,0,0,0,5797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5799,0,0,5801,\n0,0,0,5811,0,0,0,0,0,0,5816,0,0,5827,0,0,0,0,0,0,0,0,5830,5831,0,0,5832,0,0,5833\n,0,5835,5844,5845,0,5846,0,0,0,0,0,5850,0,0,0,0,0,5852,0,5855,5857,0,0,5859,0,\n5861,0,0,5863,0,5865,0,0,0,5873,5875,0,0,0,5877,0,5879,0,0,0,5888,0,0,5889,5891,\n0,5894,0,0,0,0,0,0,5895,0,5897,0,0,0,0,0,0,5907,0,5911,0,0,5912,0,5913,5922,5924\n,0,5927,5928,0,0,0,0,5929,5930,0,5933,0,0,0,0,5949,0,0,5951,0,0,0,0,0,0,0,0,5953\n,0,0,5954,0,5959,5960,5961,0,5964,0,0,0,5976,5978,5987,5990,0,0,0,0,0,5991,0,\n5992,0,0,0,5994,5995,0,0,5996,0,0,6001,6003,0,0,0,0,6007,0,0,0,0,0,6008,0,0,6009\n,0,6010,0,0,0,6011,6015,0,6017,0,6019,0,6023,0,0,0,0,0,0,0,6025,0,0,0,0,0,0,0,0,\n0,0,6026,0,6030,0,0,6032,0,0,0,6033,6038,6040,0,0,0,6041,6045,0,0,6046,0,0,6053,\n0,0,6054,0,6055,0,0,0,0,0,0,6057,0,6063,0,0,0,6064,0,6066,6071,6072,0,0,0,0,0,0,\n6075,6076,0,0,6077,0,0,0,0,0,0,0,0,0,6078,6079,0,0,0,0,0,0,0,0,6080,0,6083,0,0,0\n,0,0,6084,0,0,6088,0,6089,0,0,6093,6105,0,0,6107,0,6110,0,0,0,6111,6125,6126,0,0\n,0,6129,0,0,0,0,6130,0,0,0,6131,6134,0,0,0,0,0,0,6142,0,0,0,0,0,6144,0,0,6146,\n6151,6153,0,6156,0,6163,0,6180,6181,0,0,0,0,0,6182,0,0,0,0,6184,6195,0,0,6206,0,\n6208,0,0,6212,6213,6214,0,6215,0,0,0,6228,0,0,0,6234,0,0,0,0,0,0,6235,6240,0,\n6242,6243,6244,0,6250,6255,0,0,0,0,0,6257,0,0,0,6258,6278,0,6284,0,0,0,6285,0,0,\n0,0,0,0,0,0,6286,0,0,0,6320,0,0,6322,6332,0,0,0,0,0,0,0,0,6334,0,0,0,0,0,0,0,\n6335,0,0,6337,0,6338,0,6339,6340,0,0,6356,6357,6369,0,0,0,6370,6371,6372,0,6373,\n0,0,0,0,0,6376,0,0,0,0,0,6382,6383,6384,0,0,0,0,6386,0,6389,6397,6400,6411,0,\n6414,0,0,0,0,0,0,0,6415,6416,0,0,0,0,0,0,6417,0,0,0,0,6418,0,0,0,0,0,0,0,6420,0,\n6421,6423,6425,0,6429,6430,0,6433,6438,0,0,0,0,0,0,0,0,0,0,6439,6440,0,0,6441,0,\n0,6444,0,0,0,0,6446,0,0,0,0,6447,6448,0,0,6450,0,0,0,6454,0,0,6455,0,6461,0,0,0,\n0,0,0,6462,0,0,6463,0,6464,0,6465,6467,0,0,0,6468,0,6479,6480,0,0,0,0,0,0,0,6481\n,0,0,6485,6487,0,0,0,0,0,0,6493,0,0,0,0,0,0,0,0,6494,6495,6496,0,0,0,0,0,6498,0,\n0,0,6507,6508,0,0,0,0,0,0,0,0,0,0,6511,6512,0,0,0,0,6513,0,0,0,6514,0,0,0,0,0,\n6516,0,0,6517,6518,0,0,0,6519,6520,6521,0,6523,0,0,0,0,6524,6528,0,6530,0,0,6532\n,0,6578,0,0,0,6583,0,6584,0,0,0,6587,0,0,0,6590,0,6591,0,0,0,0,0,6592,0,0,0,0,\n6593,6594,0,0,0,0,0,6599,6600,0,0,6601,6602,6604,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6608,0,0,0,0,0,0,0,0,6610,6611,0,6615,0,6616,6618,6620,0,6637,0,0,0,0,6639,0,0,0\n,0,6641,0,6642,0,0,0,6647,0,6660,6663,0,6664,0,6666,6669,0,6675,6676,6677,0,0,0,\n0,0,0,0,0,0,6678,0,0,0,6679,0,6680,0,0,0,0,0,0,0,6693,0,0,0,0,0,0,0,0,0,6704,\n6705,6706,0,0,6711,6713,0,0,0,0,0,6716,0,0,0,6717,0,6719,6724,0,0,0,0,0,0,0,0,\n6725,6726,0,0,0,0,0,6728,6729,6735,0,6737,6742,0,0,6743,6750,0,6751,0,0,6752,\n6753,0,0,0,0,0,0,6754,0,0,0,0,0,6756,0,0,0,0,0,0,6763,0,0,6764,6765,0,0,0,6770,0\n,0,0,6776,6780,0,6781,0,0,0,6783,0,6784,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6785,0,0,0,6792,0,0,0,6793,0,0,6802,0,0,0,0,0,6803,0,0,0,6804,0,0,0,6812,0,0,\n6823,0,6824,6839,0,0,0,0,6852,0,0,6854,0,6856,6857,0,0,0,0,0,0,0,0,0,6867,0,6868\n,6870,6872,0,0,0,6873,6874,0,0,0,0,0,6875,0,0,6877,0,0,0,0,0,0,0,6878,0,0,0,6879\n,0,6880,0,0,0,0,0,0,0,0,0,0,6887,0,6888,6891,6893,0,6895,0,0,0,0,0,0,0,0,6899,0,\n0,0,0,6901,0,0,0,0,6910,0,6911,0,0,6912,0,0,6913,6914,0,0,0,6915,0,0,0,6916,6919\n,0,0,0,0,0,0,6924,0,6925,0,0,0,6926,6927,6928,0,6929,0,6930,0,0,6931,6935,0,6936\n,0,0,0,0,6939,6940,6941,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6942,6948,6949,0,0,0,0,0,0\n,0,6952,6954,6963,6965,6966,0,0,6967,6968,0,0,0,0,0,0,0,0,0,6969,0,0,6970,6979,0\n,0,6980,0,0,6983,0,0,0,0,0,6984,0,0,0,0,0,0,0,6988,6990,6992,0,0,0,0,0,0,0,6995,\n0,0,0,7012,0,0,0,0,0,0,0,0,0,7019,0,0,0,0,0,0,0,0,7021,0,0,7022,7023,7028,0,7030\n,7033,0,0,0,0,0,0,7038,0,0,0,0,0,0,0,0,0,0,7039,0,0,0,0,0,7046,0,7047,0,0,0,0,0,\n0,0,0,0,0,0,7048,7052,0,0,0,0,0,7054,0,7060,0,0,0,0,7061,0,7065,0,0,0,0,7067,\n7069,0,7070,7071,7072,0,0,7078,0,7080,7081,0,7083,0,0,0,7084,7087,7088,0,0,7090,\n0,7093,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7107,0,0,7108,0,0,0,0,0,0,0,0,7110,0,7114,0\n,0,0,0,0,0,0,7115,0,7116,0,0,0,0,0,7117,0,0,7118,0,0,7124,0,7125,0,0,7126,0,0,0,\n0,7128,0,0,0,0,0,7129,0,7130,0,7132,7133,0,0,7134,0,0,7139,0,7148,7150,0,0,0,0,\n7152,0,0,0,7153,7156,7157,0,0,0,0,0,7158,0,0,0,0,0,0,0,0,0,0,7163,7165,7169,0,\n7171,0,0,0,0,0,0,0,0,0,7172,0,7173,7181,0,0,0,0,0,7182,7185,0,0,0,0,7187,0,7201,\n7204,0,0,0,0,0,7206,7207,0,0,0,0,7211,7216,0,7218,0,0,0,0,7226,7228,7230,7232,\n7233,7235,7237,0,0,0,0,7238,7241,0,7242,0,0,7247,0,0,0,7266,0,0,0,0,0,0,0,7289,0\n,0,7290,7291,0,0,7292,0,7297,0,0,0,0,0,0,0,0,0,0,7300,0,7301,0,0,0,0,0,0,0,0,0,0\n,0,0,7302,0,0,0,0,7305,0,0,0,0,7307,0,7308,0,7310,0,7335,0,0,0,0,0,0,0,7337,0,\n7343,7347,0,0,0,0,0,7348,0,7349,7350,7352,7354,0,0,0,0,7357,0,7358,7366,0,7367,\n7368,0,0,7373,0,0,0,7374,0,0,0,0,0,0,0,7376,0,0,0,7377,0,0,0,0,0,7378,0,7379,\n7380,0,0,0,0,0,7383,0,0,7386,0,0,0,0,7398,0,0,0,7399,7400,0,7401,0,0,0,0,0,0,0,\n7402,0,0,0,0,0,7405,0,0,0,0,0,7406,0,0,0,0,0,0,0,0,7421,7427,7429,0,0,0,7435,0,0\n,7436,0,0,0,7437,0,0,0,0,0,0,7438,7443,0,7446,0,7448,0,0,0,0,0,0,0,0,0,0,7456,0,\n0,0,0,0,7457,0,0,7461,0,0,0,0,0,7462,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7463,7466,7472,\n0,7476,0,0,7490,0,7491,0,0,7493,0,0,0,7498,7499,0,0,7508,0,0,0,0,0,7512,0,0,0,\n7513,7514,7516,0,0,0,0,7518,0,0,7519,7521,7522,0,0,0,7526,0,0,7529,0,0,7531,0,\n7536,0,7538,0,7539,0,0,7541,7542,7546,0,0,0,0,0,7547,0,7548,0,0,0,0,0,7550,0,0,\n7552,7553,0,0,0,0,0,0,0,0,0,0,7554,7563,0,7573,0,0,0,0,0,0,7574,7576,0,7578,7581\n,7583,0,0,0,7584,0,7587,0,0,0,0,0,7589,0,0,0,7594,0,0,7595,0,0,7600,7602,7610,0,\n0,0,0,0,7612,0,7613,7614,0,0,7615,0,0,7616,0,7620,0,7621,7622,0,7623,0,0,0,0,\n7626,0,0,0,0,7627,7629,7631,0,0,7633,0,0,0,0,0,7639,0,7640,7642,0,0,7643,0,0,0,0\n,7644,0,0,0,0,0,0,0,7645,0,0,0,0,0,7661,7662,7663,7665,0,7666,0,7667,0,7684,7688\n,7690,0,7691,0,0,0,0,0,0,7692,0,0,7700,0,7707,0,7708,0,7709,0,7721,0,0,0,7722,0,\n7724,0,0,0,0,0,0,7729,7731,0,7732,0,7733,7735,0,0,0,0,0,0,0,7739,0,0,7741,7745,0\n,7748,0,0,0,7751,0,0,0,7752,0,0,0,0,0,0,0,7753,0,0,7756,0,7757,0,7759,0,7760,0,0\n,0,0,7761,7768,0,0,7769,0,0,7770,0,0,7771,0,0,7772,0,0,7773,0,0,0,0,0,7778,7783,\n0,0,0,0,0,7784,7785,0,7790,0,0,0,0,7792,0,7798,0,0,0,0,0,7799,0,7810,0,0,7813,0,\n7814,0,7816,0,7818,7824,7825,7826,0,7828,7830,0,0,0,7840,0,7842,0,7843,0,0,0,0,\n7844,0,0,0,0,0,0,0,7846,0,0,0,0,0,7856,7857,7858,7862,0,7865,0,0,7866,0,0,7913,0\n,0,0,0,7914,0,0,7915,7917,7918,7919,0,7920,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7921,\n7922,0,7924,0,0,7925,0,0,7927,0,7930,7935,0,0,7937,0,0,0,0,0,0,7939,0,7940,0,0,0\n,0,0,7941,0,0,0,0,7945,0,0,0,0,7949,0,0,0,0,0,0,0,0,7950,0,7953,0,0,0,0,0,0,0,\n7968,0,0,0,0,7969,7972,7992,0,7993,0,0,0,0,0,0,0,0,0,0,0,7994,0,0,0,0,8007,8008,\n0,0,0,0,0,0,0,0,0,0,0,0,8010,0,0,0,8012,0,0,0,0,0,0,0,0,8018,0,8028,8029,0,0,\n8030,0,0,8032,8033,0,0,8034,8036,0,0,0,0,0,0,0,0,0,0,8037,0,0,0,8043,8052,8059,\n8060,0,0,8061,0,0,0,8062,0,8063,0,8064,0,8066,8068,0,0,0,8080,8081,0,8089,0,0,0,\n0,0,8092,0,0,0,0,0,0,8093,8110,0,0,0,0,0,0,0,8111,0,0,0,0,0,8112,8115,0,8117,0,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8120,8121,8122,8128,8129,8130,8131,0,0,8139,0,0,\n8144,0,0,0,0,8145,8146,8153,0,0,0,0,0,0,0,0,8154,0,8157,8160,8162,0,8164,8165,0,\n0,0,0,8166,8167,0,0,8179,0,0,0,8185,0,0,0,8186,0,0,8187,0,0,0,8188,0,0,0,0,0,\n8204,0,0,0,0,8210,0,0,0,0,0,8213,0,8214,0,0,8215,0,0,0,0,0,0,8218,0,0,0,0,0,0,0,\n0,0,8219,0,8221,0,0,8222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8225,0,0,0,8233,0,0,\n8242,0,0,0,0,0,0,0,0,0,0,0,8247,0,8248,8252,0,8256,8257,0,0,8261,0,8264,8265,0,0\n,0,0,8267,0,0,0,8269,0,0,0,0,0,0,0,0,0,8270,0,0,0,8278,0,8279,8283,0,0,8285,8286\n,8289,8292,0,0,0,0,8293,8295,8299,8300,8301,0,0,0,0,0,0,8304,8307,0,0,0,0,0,0,0,\n8321,0,0,0,8322,8323,8325,8326,8327,0,0,8332,8338,0,0,8340,0,0,0,0,0,8350,0,0,\n8351,0,8354,8355,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8360,8372,0,0,0,0,0,0,0,0,8377,0,0,\n0,0,8380,0,0,0,8383,0,8384,0,0,0,0,8386,8392,0,0,8394,0,0,0,0,0,0,0,8396,8397,0,\n8398,0,8399,0,0,0,0,0,8400,0,8401,8410,8411,0,8412,8413,8422,0,0,0,0,8423,0,0,0,\n0,8424,0,0,8425,0,0,0,0,0,0,0,8441,8442,0,0,0,0,0,0,8443,0,0,8444,0,8447,0,0,0,0\n,8451,0,8458,0,8462,0,0,8468,0,8469,0,0,0,8470,0,8473,8479,8480,0,0,0,0,8481,\n8483,0,0,0,0,0,0,0,0,0,8484,0,0,8490,0,0,0,0,0,0,8491,8493,8494,0,8528,0,0,0,0,0\n,0,0,8530,0,0,0,0,0,0,0,0,8534,8538,8540,0,0,8541,0,0,8545,0,8557,0,0,8569,8570,\n0,0,8571,8574,8575,8579,0,8583,0,0,0,0,8591,0,0,0,0,0,0,0,0,8606,0,8607,0,0,0,0,\n0,0,0,0,0,8608,0,0,8609,0,0,0,8610,0,0,0,8611,0,0,8613,8617,8621,0,0,8622,0,8623\n,0,8624,8625,0,0,0,0,0,0,0,0,0,8637,8638,8639,8650,0,0,0,0,8652,8654,8655,0,0,0,\n0,0,0,0,0,0,0,8656,0,0,0,0,0,8657,0,0,0,0,0,0,0,0,0,8658,0,0,8659,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,8660,0,0,0,0,0,0,8661,8663,8664,0,0,0,0,8665,0,8669,0,\n0,0,0,0,0,0,8671,8674,0,8684,0,8686,0,0,0,8689,0,0,0,8690,0,8706,0,0,0,0,0,0,0,0\n,0,0,0,8710,0,8711,8713,8714,8724,8727,8728,8733,8736,0,8737,8739,0,0,0,0,8742,\n8743,8745,8754,0,0,0,0,8756,0,0,0,0,0,0,8757,8760,0,0,0,0,0,8762,8763,8764,0,\n8766,8769,8770,8773,0,8774,0,8779,0,0,0,0,8780,0,0,8781,0,0,8783,0,0,0,0,0,0,0,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8784,0,0,0,0,0,0,0,0,8785,0,0,0,0,8786,0,0,0,0,8788\n,8790,0,0,0,8803,0,8813,8814,0,0,0,0,0,8815,8816,0,0,0,0,8818,0,0,0,0,8822,8828,\n8829,0,8831,0,0,0,0,8833,0,0,0,8834,0,0,0,8835,0,8836,0,0,0,8837,0,0,0,0,0,0,\n8838,8839,0,0,0,0,0,0,0,0,0,0,0,8840,0,0,0,8841,0,8842,0,0,0,8846,0,0,0,0,0,0,0,\n8847,0,8848,0,0,8864,0,0,8866,0,0,8870,8872,0,0,8873,8874,0,0,0,0,0,0,8875,0,\n8876,0,0,0,0,8896,8900,0,0,0,0,8901,0,0,0,0,0,8904,0,8907,0,0,0,0,8911,8912,8913\n,0,0,0,8914,0,8915,0,0,0,0,0,0,0,0,0,0,0,0,8916,0,0,0,8929,0,0,0,0,0,0,0,0,0,0,\n8930,0,8932,0,8943,0,0,0,8945,8947,0,0,0,0,8949,0,8950,0,8954,8957,0,0,8970,0,0,\n0,0,8971,0,8996,0,0,0,0,8997,9000,0,0,0,0,9001,9002,0,9004,9009,9024,0,0,0,0,0,0\n,0,0,0,0,0,0,9027,9082,0,0,9083,9089,0,0,0,0,0,0,9090,0,0,0,9092,0,0,9093,0,9095\n,0,0,9096,9097,9101,9102,0,0,0,0,0,0,0,0,9112,0,0,0,0,0,0,9114,0,0,9120,0,9121,\n9122,0,0,0,9123,9124,0,0,9125,0,0,9126,0,9127,0,0,9129,9131,0,0,0,9132,0,0,9136,\n0,9144,0,0,9148,0,0,0,0,0,0,9149,0,9152,9163,0,0,9165,0,0,0,0,0,0,0,0,0,0,0,0,0,\n9166,0,9169,0,0,0,0,0,0,0,9170,0,0,0,0,9172,0,9174,9175,9176,0,9177,0,0,0,0,0,0,\n0,0,9186,0,9187,0,0,0,9188,9189,0,0,9190,0,0,0,0,9191,0,0,0,9193,0,0,0,0,9197,\n9198,0,0,0,9208,9211,0,0,0,0,9216,9217,0,9220,0,0,0,0,9221,9222,9223,0,9224,9225\n,0,0,9227,0,9228,9229,0,0,9230,0,9232,0,9233,0,0,0,0,0,9234,9235,0,0,9237,0,0,0,\n0,0,0,0,0,9238,9240,0,0,9241,0,0,0,0,9244,0,0,0,0,9247,0,0,0,0,0,0,0,0,0,0,9248,\n0,0,0,9249,0,0,0,0,0,9250,0,0,0,0,9251,0,0,9252,9255,0,0,0,9256,0,0,0,0,0,0,0,\n9257,0,0,9258,0,0,0,0,0,0,9259,0,0,0,0,0,9262,9263,0,0,9265,9266,0,0,0,0,0,0,0,0\n,9268,9271,0,0,0,0,0,0,0,0,0,9273,0,0,0,9276,9277,9279,0,0,0,0,0,0,0,9280,0,0,\n9293,0,0,0,0,0,9297,9301,0,0,0,0,0,0,0,0,0,0,0,9308,9309,9313,9321,9322,0,9326,\n9327,0,0,9477,0,9479,0,0,0,0,9482,0,0,0,9483,0,9484,0,0,0,0,0,0,0,0,0,9485,0,0,\n9486,0,0,0,9489,0,0,0,0,9490,9491,0,0,0,0,9493,0,9495,9496,0,0,0,0,0,0,0,0,9500,\n0,9502,0,0,0,0,0,9504,9507,0,9509,0,9511,0,0,9513,0,0,0,0,0,0,0,0,9515,0,0,0,0,0\n,0,9516,9517,0,0,0,0,9532,0,0,9533,0,0,9538,0,9539,9540,0,0,0,0,9541,0,0,0,9542,\n0,0,0,0,0,0,0,0,9544,9545,0,9546,0,0,0,0,0,0,9547,9548,0,0,0,9550,0,9557,0,9558,\n0,9561,0,9563,9570,0,9572,9574,9575,0,0,0,9577,9592,0,0,9596,0,0,0,9598,0,9600,0\n,9601,0,0,0,0,0,0,9608,0,9638,9639,0,0,0,0,0,0,0,9641,0,0,9643,9644,9645,9646,0,\n0,0,9648,0,0,0,0,0,0,0,9650,9654,0,0,0,0,0,0,0,0,9655,0,0,0,0,0,9656,0,9657,0,0,\n0,0,9658,0,0,9659,0,0,9664,0,0,9665,0,9667,9669,0,0,0,0,0,0,0,0,0,0,0,0,9671,0,\n9673,9681,0,0,0,0,9682,9683,9684,0,0,0,0,9686,9698,0,0,9700,9701,9702,0,9703,\n9717,0,0,0,0,9718,0,9726,0,0,0,0,9727,0,0,0,9728,0,9742,0,9744,0,0,0,9750,0,9754\n,9755,0,0,0,0,0,9756,0,9757,9768,0,9769,0,0,0,9770,9771,0,9773,0,9774,0,9775,0,0\n,0,9776,9777,9784,0,0,0,9786,0,9789,0,0,0,0,9793,9794,0,0,0,9808,0,0,0,0,0,9811,\n0,0,0,0,0,0,0,0,0,0,0,0,9812,0,9820,0,9823,0,9828,0,0,0,0,9830,0,0,9833,9836,0,0\n,0,9840,0,0,0,9841,0,0,9842,0,9845,0,0,0,9847,9848,0,0,9855,0,0,0,0,0,0,9856,\n9863,9865,0,0,0,0,0,0,0,0,9866,9867,9868,9873,9875,0,0,0,0,0,0,9880,0,9886,0,0,0\n,9887,0,0,9891,0,0,0,0,0,0,0,9906,9907,9908,0,0,0,9909,0,0,0,0,0,0,9910,0,0,0,0,\n9913,0,0,0,0,9914,0,0,0,0,0,9922,0,0,0,0,9923,9925,0,0,0,0,0,0,9930,0,0,0,9931,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9932,0,9939,0,0,9940,9962,9966,0,9969,9970,0,0,9974\n,0,9979,9981,9982,0,0,0,9985,0,0,0,0,0,0,9987,0,0,0,0,0,0,0,9988,9993,0,0,9994,0\n,0,0,9997,0,10004,0,0,0,0,0,10007,10019,10020,10022,0,0,0,10031,0,0,0,0,0,10032,\n0,0,10034,0,10036,0,0,0,0,10038,0,10039,10040,10041,10042,0,0,0,0,0,10043,0,0,0,\n0,0,10045,10054,0,0,0,0,10055,0,0,10057,10058,0,0,0,0,0,0,10059,0,0,0,0,0,0,0,\n10060,0,0,0,0,0,0,0,10063,0,10066,0,0,0,10070,0,10072,0,0,10076,10077,0,0,10084,\n0,10087,10090,10091,0,0,0,10094,10097,0,0,0,0,0,0,10098,0,0,0,0,0,0,10103,0,\n10104,0,10108,0,0,0,0,0,0,0,0,10120,0,0,0,10122,0,0,10125,0,0,0,0,10127,10128,0,\n0,10134,0,10135,10136,0,10137,0,0,10147,0,10149,10150,0,0,10156,0,10158,10159,\n10160,10168,0,0,10171,0,10173,0,0,0,10176,0,0,0,0,10177,0,0,0,0,10178,0,0,0,0,\n10194,0,10202,0,0,10203,10204,0,10205,10206,0,10207,0,0,0,0,10209,0,0,0,0,0,0,0,\n10213,0,0,0,0,0,0,10217,0,10229,0,10230,10231,0,0,10232,0,0,10237,10238,10244,0,\n0,0,0,0,10250,0,10252,0,0,0,0,0,0,10255,0,0,10257,0,0,0,0,0,0,10258,0,10259,0,0,\n0,0,0,0,0,0,10260,0,0,0,0,0,0,0,10284,10288,10289,0,0,0,10290,0,10296,0,0,0,0,0,\n10297,0,0,0,0,0,0,10298,0,0,0,0,10299,10303,0,0,0,0,0,10306,0,0,0,10307,0,10308,\n0,0,0,0,10311,0,0,0,0,0,0,0,10315,10317,0,0,0,10318,10319,0,10321,0,10326,0,\n10328,0,0,0,0,10329,0,0,10331,0,10332,0,0,0,0,0,0,10334,0,0,10335,10338,0,0,0,0,\n0,10339,10349,0,0,0,0,0,0,10351,0,10353,0,0,0,0,0,0,10362,0,10368,0,10369,0,0,0,\n10372,10373,0,0,0,0,0,10374,0,0,0,10375,0,10376,0,0,10386,10388,10390,0,0,0,0,0,\n0,0,10391,0,0,10392,10394,0,0,10396,0,10397,0,10403,0,0,0,0,0,0,0,0,10404,0,\n10405,10410,0,0,10411,0,10412,0,0,0,0,0,0,0,10421,10422,10423,0,0,0,0,0,0,0,0,0,\n10425,0,0,10427,0,0,10430,0,0,0,0,0,10432,0,10433,10434,0,0,0,0,10436,10437,0,\n10438,0,10439,0,10444,10446,0,0,0,0,0,10448,0,0,0,0,0,10449,0,0,0,0,0,0,0,10451,\n0,10453,0,0,0,10454,10457,0,0,10459,0,10469,0,0,0,0,0,10472,10481,0,0,0,0,0,\n10482,10483,0,10492,0,0,0,0,0,0,0,0,0,0,10499,0,0,0,10502,0,0,10510,0,10521,\n10524,0,0,10525,10526,10528,0,0,0,0,0,0,0,0,10530,0,0,0,0,10533,0,10534,0,0,0,0,\n0,0,0,0,0,0,10535,10536,0,0,10544,0,10553,10556,0,10557,10559,0,0,0,0,0,10562,\n10563,10564,0,10565,0,0,0,10566,0,10567,0,0,0,0,10575,0,0,10576,0,10578,0,0,0,0,\n0,0,0,0,0,0,10585,10586,10587,10589,0,10590,0,0,10594,0,0,0,0,0,10598,0,0,10601,\n0,0,0,10602,0,10603,0,10604,0,10605,0,0,10607,0,10626,0,10627,0,0,0,0,0,10629,\n10630,10631,0,0,0,10646,0,0,0,10647,0,10650,0,10651,0,0,0,10652,10653,10655,0,\n10658,0,0,10659,0,10667,0,0,0,0,10669,0,0,0,0,0,0,0,0,0,10670,0,0,0,10671,0,0,0,\n0,10672,10673,0,10674,0,0,0,10676,0,0,0,0,0,0,10678,0,10682,0,0,10692,0,10697,0,\n0,0,0,10698,0,0,0,10700,0,0,0,0,0,10703,0,10704,0,0,0,0,0,0,0,10705,0,10715,\n10718,10720,0,0,10722,0,0,0,0,0,0,0,0,10723,0,0,0,0,10726,0,0,0,0,0,10727,10730,\n10743,0,0,0,0,0,0,10744,0,0,10745,0,0,0,0,0,0,10748,0,0,0,0,10750,0,0,10752,\n10753,0,0,0,10756,0,0,0,0,0,0,10758,0,0,0,10759,0,10769,0,0,10772,0,0,0,0,0,0,\n10773,0,0,0,10777,0,0,10779,0,0,0,0,0,0,0,0,10780,10784,0,0,0,10789,0,0,0,10791,\n0,0,0,0,0,0,0,0,0,10795,0,0,10796,0,10808,0,10809,0,0,0,10810,0,0,0,10812,0,0,\n10814,0,0,0,0,0,0,0,0,0,10815,0,0,0,0,10816,10817,0,0,0,0,10819,0,10820,0,0,0,0,\n10821,10822,10823,0,10826,10849,0,0,0,0,10850,0,0,10852,0,10853,0,0,10856,0,0,\n10857,10858,10859,10860,0,0,0,0,0,0,10863,0,10866,10867,10872,10890,0,0,10891,\n10892,0,0,0,0,0,10893,0,0,0,10896,10899,0,0,10900,10902,0,0,0,0,0,10903,0,0,0,0,\n0,0,0,0,0,0,0,0,10905,0,10906,0,0,0,0,10908,10911,0,10912,0,0,10916,0,0,0,0,0,\n10917,0,10918,0,0,0,10923,0,0,0,0,0,10924,0,0,10928,10929,0,0,10930,0,0,0,10932,\n0,0,0,0,10939,0,0,10945,0,0,0,10947,0,0,10948,0,0,0,0,0,0,0,0,0,0,0,0,10958,0,\n10960,10962,0,0,10964,0,0,0,10966,0,0,0,0,0,0,0,0,0,0,10967,0,0,0,10968,0,0,0,\n10973,0,0,0,0,0,10975,0,0,0,10976,10978,0,0,10982,10984,10987,0,0,10988,0,10989,\n0,0,10991,0,0,0,0,10992,0,0,0,10993,0,10995,0,0,0,10996,10997,0,0,0,10998,0,\n10999,0,11001,0,0,0,0,0,0,11010,11012,0,11013,11016,11017,0,0,11019,11020,11021,\n0,0,0,0,0,0,0,0,0,0,0,0,11022,0,0,11023,11029,0,0,0,0,11031,0,0,0,11034,0,0,0,0,\n11055,0,0,0,0,0,11056,11060,0,0,0,0,0,0,11061,0,0,11064,11065,0,11066,0,11069,0,\n11085,0,0,0,0,0,11086,0,0,0,11088,0,0,0,11094,0,0,0,11095,11096,0,0,0,0,0,0,\n11097,11098,0,0,0,0,0,0,11099,0,0,11102,11108,0,0,0,11109,0,11114,11119,0,11131,\n0,0,0,11142,0,0,11143,0,11146,0,11147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11148,0,\n11149,11152,11153,11154,0,11156,0,11157,0,0,0,11158,0,0,11159,11160,0,0,0,0,0,0,\n0,0,0,0,0,0,11163,0,0,11164,11166,0,0,0,11172,11174,0,0,0,11176,0,0,0,0,0,11182,\n11183,0,0,0,11184,11187,0,0,11188,11189,0,0,0,0,0,0,11194,0,0,0,0,0,0,0,11200,\n11202,0,0,0,0,0,0,11203,0,11204,0,0,0,0,0,11205,0,0,0,11206,0,11207,0,0,11209,0,\n11211,0,11214,0,0,11231,0,0,0,11293,11295,0,0,11296,11297,11302,0,0,0,11307,0,0,\n0,0,11309,11310,0,11311,0,0,0,11313,0,11314,0,0,0,0,11334,0,11338,0,0,0,11339,0,\n0,0,0,0,11340,0,11341,11342,0,11344,0,11345,0,0,0,11348,11349,0,0,11350,0,0,0,\n11355,0,0,0,0,0,0,11356,0,11357,11370,0,0,11371,0,11374,11376,0,0,0,11377,0,0,\n11378,11383,0,11386,11399,0,11400,11406,0,0,0,11408,0,0,11409,11412,0,0,0,0,\n11417,0,0,0,11418,0,11421,0,11426,11429,0,0,0,0,0,11430,0,11437,0,11438,0,0,0,0,\n0,11440,11453,0,0,0,0,0,0,11454,0,0,0,0,11455,0,0,11456,11460,11461,11463,0,\n11469,0,11473,0,0,0,0,11474,0,0,0,11475,0,11476,11477,11480,0,0,0,0,11481,0,0,\n11484,0,0,11487,0,0,0,0,0,0,0,0,0,0,11497,0,0,11502,0,11509,0,0,11510,11511,\n11513,0,0,0,0,0,0,0,0,0,0,11515,0,0,0,0,11516,0,11520,11521,0,0,0,0,0,0,0,0,0,0,\n0,11529,11530,11531,11534,0,0,11543,0,0,0,0,0,11547,0,11548,0,0,0,0,0,11552,\n11556,0,11557,0,0,11559,0,11560,0,0,0,0,0,0,11561,0,0,11563,11564,0,11565,0,0,0,\n0,11567,0,0,0,11569,0,11574,0,11575,0,0,0,11577,0,11578,0,0,0,11580,11581,0,0,0,\n11582,11584,0,0,0,0,0,0,0,11587,0,11588,11591,0,11595,0,0,0,0,0,0,0,0,11596,0,\n11597,0,0,0,0,11598,11601,0,0,0,11602,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11603,\n11604,0,11606,0,0,11608,0,0,0,0,11610,0,0,11611,0,0,0,0,11613,0,11622,0,0,0,\n11623,0,0,0,0,11625,0,0,11626,11627,11628,11630,0,0,0,0,0,0,11639,0,0,11646,0,\n11648,11649,0,11650,0,0,0,0,0,0,0,0,0,11651,0,0,11652,11653,11656,0,0,11677,\n11679,0,0,0,0,11680,0,0,11681,0,11685,0,0,0,0,0,0,0,0,11688,0,0,0,11716,0,11719,\n0,0,0,0,0,11721,0,0,11724,11743,0,0,0,0,0,0,0,0,11745,11748,11750,0,0,0,0,0,\n11751,0,0,0,11752,11754,0,11755,0,0,0,0,0,0,0,11759,0,0,0,0,0,0,11760,0,0,0,\n11761,0,0,0,0,0,0,11766,11767,0,11772,11773,0,11774,0,0,11775,0,11777,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,11778,11780,0,0,0,0,0,0,0,11783,0,11784,0,0,0,11785,\n0,0,0,11786,0,0,0,0,11788,0,0,11789,11791,11792,0,0,0,0,11795,11834,11835,11836,\n0,0,11837,0,0,0,11838,0,0,11846,11851,0,11852,0,11869,0,0,0,11871,0,0,0,11872,\n11874,0,0,0,0,0,0,11875,0,11876,11877,0,0,0,0,0,0,0,0,0,0,11883,0,0,0,0,0,0,0,\n11884,0,11885,0,11886,0,0,11887,0,11894,11895,11897,11909,11910,0,11912,11918,0,\n0,11920,0,11922,11924,11927,11928,0,0,0,0,11929,0,11934,0,0,0,0,0,11941,11943,\n11944,0,11945,0,0,0,0,11948,11949,0,0,0,0,11953,0,11954,0,11955,0,11956,0,0,0,0,\n0,11957,0,0,11959,0,0,0,0,0,0,0,0,11961,0,0,0,0,0,11978,0,0,0,11979,11980,11986,\n11987,0,11992,0,0,0,0,0,11993,0,0,0,11994,0,11999,12004,12005,12006,0,0,0,0,0,\n12011,0,0,12012,12014,0,0,12015,0,0,12019,12028,0,0,12029,0,0,12032,12033,0,0,0,\n0,12034,0,12041,12043,0,0,12044,0,0,0,0,0,0,0,12046,0,0,0,0,0,0,0,12054,12055,0,\n12056,0,0,0,12060,12064,0,0,0,0,0,12065,12067,12068,0,0,0,0,0,0,0,0,12074,0,0,0,\n12075,12076,0,0,0,12079,0,12081,12086,12087,0,0,12088,0,0,0,0,12089,0,12092,0,0,\n0,0,12097,0,0,0,0,0,0,0,0,12098,0,0,0,0,0,0,0,0,0,0,0,0,0,12102,12103,12104,\n12111,0,0,12114,12116,0,0,0,12118,0,0,0,12119,12120,12128,0,0,0,0,12130,0,0,0,0,\n0,0,12131,0,0,0,12132,12134,0,0,0,0,12137,0,12139,0,12141,0,0,12142,0,0,0,12144,\n0,0,0,0,0,12145,0,12148,0,12153,0,0,0,0,12154,12171,12173,0,0,0,12175,0,0,0,0,\n12178,0,0,0,0,0,0,0,12183,0,0,0,0,0,0,0,0,12184,0,0,0,12186,0,0,0,0,0,12187,\n12188,0,0,12189,0,12196,0,12197,0,0,12198,0,12201,0,0,0,0,12203,0,12209,0,0,0,0,\n12210,12211,12212,12213,0,12217,12218,0,0,0,0,0,0,0,0,0,12222,0,0,0,0,0,0,0,\n12223,0,0,12229,0,0,0,0,12233,0,0,0,0,12234,0,0,12236,12242,0,0,0,12243,0,0,0,\n12244,12253,0,12254,12256,0,12257,0,0,12275,0,0,0,0,0,12277,0,0,0,0,0,12278,0,\n12289,0,0,12290,0,12292,12293,0,0,12294,0,12295,0,0,12296,0,12297,0,12298,0,0,0,\n0,12301,0,0,0,0,0,0,0,0,0,0,0,0,0,12309,0,12338,12340,0,0,0,0,12341,0,0,0,0,0,0,\n0,0,12342,12343,0,12344,0,0,0,0,0,0,0,0,0,12345,0,0,0,0,0,0,0,0,12346,0,0,0,0,\n12348,0,0,0,0,0,0,0,0,0,0,0,0,12350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12351,0,12355,\n12356,12357,0,0,12367,12370,12371,0,0,0,0,0,12372,12376,0,0,0,0,0,0,0,0,12379,0,\n12382,0,12383,0,0,12384,0,0,0,0,12393,0,0,12394,0,0,0,0,12398,12403,0,0,12404,0,\n0,0,0,0,0,0,0,0,0,0,0,0,12410,0,0,0,12411,0,0,0,12412,0,0,0,0,12420,0,12421,0,0,\n0,0,0,12423,0,12425,12429,0,0,0,12431,12432,0,0,0,0,0,0,0,0,0,0,0,0,12434,0,0,0,\n0,0,12435,12436,0,0,0,0,0,0,0,0,12437,0,0,0,0,0,12438,0,0,0,0,0,0,0,0,12445,0,0,\n0,12450,12451,0,0,0,0,0,0,0,0,12452,12475,0,0,12493,12494,0,0,0,12495,0,0,0,0,\n12496,12502,12509,0,0,0,0,12510,0,12512,12513,0,0,0,0,12514,0,0,0,12515,0,12520,\n0,0,0,12524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12527,0,0,0,12528,0,0,0,12529,0,0,0,\n0,0,12530,0,12535,0,0,12536,0,12538,0,0,0,0,0,0,0,0,0,0,0,0,12540,0,12548,0,0,0,\n0,0,12550,0,0,0,12551,12552,0,0,0,12554,0,0,0,0,0,0,0,0,12555,0,0,12562,0,12565,\n0,12566,0,0,0,0,0,0,0,0,0,0,0,0,12569,0,0,0,12571,12574,0,0,0,0,0,0,0,12577,0,0,\n0,0,0,0,0,12578,12579,12603,0,12608,0,0,12611,0,12612,0,12615,0,12625,0,0,0,0,\n12627,12646,0,12648,0,0,12657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12670,0,0,12671,0,\n12673,12677,0,0,0,0,0,0,0,0,0,0,0,12679,0,12681,0,12682,12693,0,12694,0,12697,0,\n12701,0,0,0,12703,12704,0,0,0,0,12707,12737,0,0,12739,0,0,12740,0,0,12742,12743,\n0,0,0,0,0,0,0,0,0,12745,0,12746,12747,0,12748,0,0,12759,12767,0,0,0,0,12773,0,\n12774,12778,0,0,0,0,0,0,0,12779,0,0,0,0,0,12780,12793,0,12824,0,12825,0,12836,0,\n0,0,0,12839,0,12842,0,0,0,0,0,0,0,0,0,0,0,0,12843,12845,0,12846,0,0,0,0,12847,0,\n0,12850,12852,12853,0,0,0,12854,0,0,0,12855,0,12856,0,12858,0,0,12859,0,12862,0,\n12863,0,0,12866,0,12869,12872,12873,0,0,0,0,0,0,0,0,0,12875,0,12877,0,0,12878,0,\n0,0,0,0,0,0,0,0,12884,12885,12888,0,12889,0,0,0,0,12893,0,0,0,12895,12896,12898,\n0,0,0,0,0,0,0,12902,0,12909,12910,0,12926,0,12928,0,0,0,12929,0,12930,0,0,0,0,\n12931,0,12932,12933,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12934,0,12942,0,0,0,0,12944,\n0,0,0,0,0,0,0,0,12946,0,0,12948,0,0,12949,0,0,0,0,12950,0,0,0,0,12951,0,12952,0,\n12953,0,0,0,12954,12958,12959,0,0,0,0,0,12960,12964,0,0,0,0,0,12966,0,0,0,0,0,0,\n0,0,12970,0,12971,0,0,0,0,0,0,12972,0,0,12982,0,0,0,12984,12985,0,12986,12996,\n12997,13001,13002,0,0,0,0,13004,0,0,13005,0,0,13007,13009,0,13017,0,0,0,13020,0,\n13021,0,0,0,0,0,0,0,0,0,0,13022,0,0,0,0,0,0,0,0,13024,13027,0,0,0,0,0,13028,0,0,\n13029,0,0,0,0,0,0,0,13032,0,13037,0,0,0,0,0,0,13040,0,0,13041,0,0,0,13043,13044,\n13046,0,0,0,0,13047,0,0,0,0,0,0,0,13049,13054,0,13056,0,0,13060,13061,0,0,0,0,0,\n13067,0,0,13068,0,13071,0,0,0,0,0,13077,13078,0,0,0,0,0,13079,13080,13081,0,\n13082,0,0,0,13085,0,0,0,0,0,0,0,13086,0,13087,13088,0,0,0,0,0,13094,0,13099,0,\n13100,0,0,0,13101,0,13125,13126,13128,13129,0,0,13130,0,13131,0,0,0,0,0,0,13134,\n0,0,0,0,0,0,0,0,0,0,0,13150,0,13168,0,0,0,0,0,0,0,0,0,13169,0,0,13170,0,0,0,0,\n13174,0,0,0,13176,0,0,0,0,0,13177,0,13178,13183,13187,0,0,0,13189,0,0,13190,0,0,\n13191,0,0,13206,0,0,0,13207,0,0,0,0,0,0,0,0,0,0,13212,0,0,13219,13232,0,0,0,\n13241,0,13249,13253,0,0,0,0,0,13255,13259,0,13260,13261,0,13262,0,13272,0,0,0,0,\n13276,0,0,0,0,13277,13299,0,0,13301,13302,0,0,13303,0,0,13305,0,13310,0,0,0,\n13311,0,0,0,0,13325,0,13328,0,0,0,13329,0,0,0,0,0,0,13330,0,0,13331,0,13335,0,0,\n13342,0,0,0,0,0,13343,0,13354,0,13362,0,13366,13367,13369,0,0,13371,13372,0,\n13373,13374,0,13376,0,13380,13381,13386,0,13387,13388,0,13389,13391,13395,0,0,0,\n0,0,13401,13409,0,13410,0,0,0,0,13420,0,0,0,0,0,13422,0,0,0,0,13423,0,0,0,0,\n13425,0,0,0,0,0,13427,0,0,0,13428,0,0,13430,13438,0,13439,0,13445,0,13448,13449,\n0,0,0,0,0,0,13451,0,13457,0,0,0,0,13458,13459,0,13460,0,0,0,0,13464,13465,13466,\n13470,0,13471,13472,13474,13475,0,13476,0,0,13478,13479,0,13481,0,0,0,0,13487,0,\n13490,0,13493,0,0,13494,0,0,13495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13496,13497,0,\n13500,0,0,13516,13522,0,0,13525,13528,0,0,0,13530,13535,0,13537,13539,0,13540,0,\n13543,0,13544,0,0,0,0,0,0,13545,0,0,0,0,0,0,13547,0,0,0,13549,13555,0,0,0,13556,\n13557,0,0,0,0,0,0,0,13558,0,13563,0,0,0,0,13564,0,0,0,0,0,0,0,0,13566,0,0,0,0,0,\n0,13569,0,0,13571,0,0,0,0,13573,0,0,0,0,0,0,13578,0,0,0,0,0,0,0,0,0,0,13581,0,\n13586,0,13595,0,13600,0,0,0,0,0,0,0,0,13601,13603,0,13604,13605,13606,13607,0,0,\n13617,13618,0,0,0,0,0,0,0,13623,0,13625,13627,0,0,0,0,0,0,0,0,13629,0,0,0,13634,\n0,0,0,13638,0,0,0,0,0,0,0,0,13654,0,0,0,0,0,0,0,0,0,0,13656,0,13659,0,0,13660,0,\n0,13662,0,0,0,13663,0,13664,0,0,0,0,0,13668,0,13669,13671,0,0,13672,0,0,0,0,0,0,\n13675,13685,0,13686,0,0,0,13687,0,0,0,13692,13694,13697,0,0,0,13702,0,0,0,0,0,\n13705,0,0,0,0,13707,0,0,0,13714,0,0,0,0,0,0,0,0,0,13715,0,13716,13717,0,0,13719,\n13724,13730,13731,0,0,0,0,0,0,0,0,13732,0,0,0,0,0,0,0,13734,0,13736,0,0,13737,\n13738,13747,0,13751,0,0,13752,0,0,0,13753,0,13757,0,0,13762,13763,0,13764,13765,\n0,13766,0,0,13767,0,0,0,13768,0,0,0,0,0,0,0,13769,0,0,13772,0,13775,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,13776,13778,13787,0,0,0,13797,0,13798,0,13801,0,13804,\n13806,0,0,0,0,13816,13817,0,0,0,0,0,0,0,0,0,0,0,0,0,13834,0,13836,0,0,13838,0,0,\n13839,0,13840,0,0,0,0,13842,0,0,0,0,0,0,13843,0,0,0,0,0,0,0,0,0,13845,0,0,0,0,0,\n13858,0,0,13860,0,0,13861,0,0,13862,13863,0,13868,0,13869,13870,0,0,0,0,0,0,0,0,\n0,0,13872,0,0,0,0,13873,13878,0,0,0,0,0,0,0,0,0,0,13886,0,13888,13889,13890,0,0,\n13891,13894,0,13897,13899,13900,13904,0,0,13906,0,0,0,13909,0,0,0,13910,0,0,0,\n13911,0,0,0,0,0,13912,13917,0,0,0,0,13918,0,13919,0,0,13920,0,0,0,13921,0,0,\n13922,0,0,0,0,0,0,0,13924,0,13927,0,0,0,0,0,13932,0,13933,0,13934,0,0,13935,0,\n13944,0,0,0,13954,0,0,13955,0,0,0,0,13956,0,13957,0,13967,13969,0,0,0,0,0,0,0,0,\n0,0,0,0,13970,13990,0,13991,13994,0,13995,0,0,0,0,13996,0,0,13999,0,0,0,14018,0,\n14019,0,14021,0,0,0,0,0,0,14041,0,0,0,0,0,0,0,0,14043,0,0,0,0,14046,0,0,0,14048,\n14049,0,0,0,0,0,0,0,0,0,0,14051,0,0,14052,14056,0,14063,0,14064,14066,0,0,14067,\n0,0,0,0,0,0,0,0,0,14068,0,0,0,14072,0,14074,14075,0,14076,14079,14085,14086,\n14087,14093,0,0,0,0,14095,0,0,0,0,0,0,14096,14097,0,0,0,0,0,0,0,14098,0,14102,0,\n0,0,0,0,14103,0,0,0,14104,0,0,14105,0,0,0,14107,14108,0,0,14109,0,0,0,0,0,0,0,0,\n14117,0,0,0,0,14118,0,0,0,0,14119,0,0,14120,0,0,14121,0,14122,14127,0,14128,\n14136,0,0,14138,0,14140,0,0,0,14141,14142,0,0,0,0,14146,0,0,14149,0,14151,0,0,0,\n14152,0,0,14153,0,0,0,0,0,0,0,0,0,14154,0,14156,14157,0,0,14159,0,14161,0,0,0,0,\n14162,0,0,0,0,0,0,14163,0,0,14173,0,0,0,0,0,0,14174,0,0,14176,0,0,14178,0,0,\n14179,14181,0,0,14182,14185,14187,0,14190,0,0,14197,0,0,0,0,0,0,0,0,0,0,0,0,\n14198,0,0,0,0,0,0,14199,14200,0,0,0,14204,0,0,14208,0,0,0,0,0,0,0,0,0,0,0,14231,\n0,0,0,0,0,0,0,0,0,14234,0,0,14235,0,0,0,14240,14241,0,0,0,14246,0,0,0,14247,0,\n14250,0,0,14251,0,0,14254,0,0,14256,0,0,0,14260,0,14261,0,0,0,0,14262,14267,\n14269,0,0,14277,0,0,14278,0,14279,14282,0,0,0,14283,0,0,0,14284,14285,0,0,0,0,\n14286,0,0,0,14288,0,0,0,14289,0,14290,0,14293,14301,14302,14304,14305,0,14307,0,\n14308,14309,0,0,0,0,0,0,0,0,0,0,0,14311,14312,0,0,14317,0,0,0,0,0,0,0,14318,0,0,\n0,0,14320,0,0,0,0,14321,14322,0,0,0,0,0,14326,14329,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n14330,14331,0,0,0,0,14332,0,0,0,14333,0,0,14337,14340,0,14341,0,0,14342,0,14345,\n14346,0,0,14347,0,14362,0,0,0,0,0,14364,14365,14371,0,14373,0,0,14374,0,14379,0,\n14400,0,0,0,0,0,14401,0,0,14405,0,14406,0,14408,14409,0,0,0,14417,0,0,14424,0,0,\n0,0,0,0,0,0,0,14430,0,0,0,14431,0,0,14435,0,14440,0,0,0,0,0,0,14442,0,0,14443,0,\n0,0,0,0,14446,0,0,0,0,0,0,0,14454,0,14457,0,14460,0,0,14466,0,0,0,0,0,14467,0,0,\n0,0,0,0,14469,0,14477,0,0,0,0,0,0,14478,14482,0,0,0,14483,0,0,0,14485,14486,0,0,\n0,14487,14488,14489,14492,14493,14494,14495,14496,14497,0,14499,0,14501,0,0,0,0,\n0,0,0,0,0,0,14502,0,14507,14512,14513,14514,0,0,0,0,0,0,0,0,0,0,0,14515,14526,\n14530,0,14537,0,14544,0,14547,0,0,14548,14550,14551,0,0,14552,0,0,0,14553,0,\n14554,0,0,0,0,14556,14564,0,0,14565,14566,0,0,0,0,0,0,14568,0,0,14569,0,0,0,\n14571,14576,0,0,14577,14578,14579,0,0,14580,0,0,0,0,14582,0,0,0,0,0,0,0,0,0,0,0,\n0,14583,0,0,0,0,0,14587,0,14588,0,0,14600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,14601,0,0,14604,14605,14611,0,14613,0,0,0,0,14615,0,0,0,0,0,0,14627,0,14628,0,\n0,0,0,14631,0,14633,14634,0,0,0,0,14635,0,0,0,0,0,0,0,0,14636,0,0,14639,14642,0,\n0,0,0,14644,0,0,0,0,14645,14646,0,14653,0,0,14654,0,14658,0,14661,0,0,0,14665,0,\n0,0,14668,0,0,0,0,0,0,0,0,0,14669,0,0,14670,0,0,0,14680,0,0,14681,0,0,0,0,0,\n14682,14683,0,0,0,0,14686,0,0,0,0,14687,14697,0,0,0,0,14699,14705,14711,0,0,0,0,\n0,0,0,0,0,0,14712,0,0,0,14713,0,0,0,0,14719,0,14720,14721,14726,0,0,0,14728,\n14729,0,0,0,0,14731,0,0,0,0,0,0,0,14733,14736,14737,0,0,14740,14742,0,0,0,14744,\n14753,0,0,0,0,14755,14758,14760,0,0,0,0,0,14761,14762,14765,14771,0,14772,0,\n14773,14774,0,0,14775,0,0,14776,0,0,0,0,14777,0,14779,0,0,14782,0,0,14785,14786,\n14788,0,0,0,0,0,14795,0,0,0,0,0,0,14798,0,14803,14804,14806,0,0,0,14809,0,0,0,0,\n0,0,14810,0,0,0,0,14811,0,14812,0,0,0,0,0,14815,0,0,0,0,0,0,0,0,14816,0,14818,0,\n0,0,0,0,0,14819,0,14820,0,14823,0,0,0,14824,0,0,14826,14827,0,0,0,0,0,0,0,0,0,0,\n0,0,14830,0,0,0,0,0,14833,0,14845,0,0,0,0,0,14846,0,0,14847,14871,0,14873,0,\n14876,0,14877,14878,14880,0,0,0,0,0,14881,0,14882,14894,0,0,0,0,14895,0,14907,0,\n14908,0,0,0,0,0,0,0,14911,0,0,0,0,14920,0,0,14931,0,14932,14934,14935,0,0,14936,\n0,14945,0,0,0,0,0,0,0,14947,0,0,14948,14949,14951,0,0,14952,0,0,0,14964,14973,0,\n0,14990,0,0,0,0,14995,0,0,14998,15001,0,0,15002,15020,0,0,0,0,0,0,15021,0,15022,\n0,0,0,0,15023,0,0,15025,15029,15033,0,0,0,15034,0,0,0,15035,0,0,0,0,0,15043,\n15044,0,0,0,15045,15046,15048,15050,0,15065,0,0,0,0,15066,0,0,15075,15082,15084,\n0,0,15085,15086,0,0,0,0,0,0,0,0,15088,0,0,0,15089,0,0,0,0,15094,0,15096,0,15097,\n0,15100,0,0,15102,0,0,0,0,0,0,0,0,15105,0,0,15106,0,15109,15113,0,0,0,15115,0,\n15118,0,0,0,0,0,0,15119,0,0,15120,0,0,0,0,0,15123,15129,0,0,0,15130,0,15131,0,0,\n15134,0,15135,0,0,0,15137,15138,0,0,0,0,0,0,15139,0,0,0,0,0,15140,0,0,15154,\n15162,0,15169,15170,0,15175,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15177,0,15178,15179,0,\n0,0,0,0,15183,0,0,0,0,0,0,0,0,0,0,0,0,15185,15187,0,15194,15195,15196,0,0,0,0,0,\n0,0,15204,0,0,0,0,15206,0,0,0,0,0,15207,0,0,0,0,0,0,0,0,0,15213,0,15214,0,0,0,0,\n0,0,0,15232,0,0,0,0,15234,0,15238,15240,0,15248,0,0,0,0,15250,15251,0,0,0,0,0,0,\n0,15252,0,0,0,15255,15262,15266,0,0,0,15267,0,0,0,15277,15279,0,0,0,15280,15281,\n15282,0,0,0,0,0,15285,0,0,0,0,15289,0,0,15291,0,0,0,0,0,0,0,15296,15297,0,0,\n15304,0,0,0,0,15306,0,0,0,0,0,0,15307,15308,0,15309,0,0,15311,0,0,15312,15313,0,\n0,0,0,0,0,0,0,0,0,0,0,15314,15317,0,0,0,15318,15319,0,0,0,0,15320,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,15321,0,0,0,0,0,15324,0,15325,15326,0,15330,0,0,0,0,15334,0,\n15335,0,15341,0,0,15342,0,0,15343,15344,0,0,0,0,15345,0,0,0,0,15347,0,0,15348,\n15349,15350,0,15356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15357,0,15358,0,0,0,0,0,0,0,\n15359,15360,15364,0,15380,0,0,0,0,0,15392,0,0,15393,0,15395,0,0,0,0,0,0,0,0,\n15396,0,0,15397,15398,0,0,0,0,0,0,0,0,0,15399,0,15400,0,0,0,15402,0,15405,15410,\n0,0,0,0,15411,0,0,0,15412,0,15416,0,0,0,0,0,0,0,15428,0,15435,0,0,15438,0,0,0,0,\n15439,0,0,0,15440,0,0,0,15441,15449,15451,0,0,0,0,0,0,0,15452,0,0,15455,0,0,0,\n15456,0,0,15458,0,15460,15461,0,0,0,0,0,15462,15464,0,15465,0,0,15466,0,0,15467,\n0,0,0,0,0,15468,0,0,0,0,15481,0,0,15484,0,15485,15486,0,0,0,15487,0,0,0,0,0,\n15488,0,15492,15498,0,0,0,15499,0,0,0,15500,0,15501,0,0,15512,0,15522,0,0,0,\n15524,0,15525,15526,0,0,15527,0,0,15545,15546,0,15548,15552,0,15553,0,0,0,15554,\n0,15555,0,15557,15565,15573,15577,15578,0,15582,0,15583,0,0,0,0,0,0,0,0,0,0,0,0,\n0,15586,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15588,0,0,0,0,0,15589,0,0,0,0,0,0,0,15593,\n15594,0,0,0,0,15595,0,0,0,0,0,0,15596,0,0,0,15597,0,0,0,0,15600,0,0,15601,0,0,0,\n0,15602,15603,0,0,0,0,0,0,15604,0,15609,0,0,15612,0,0,15613,0,0,15615,15617,\n15618,0,0,15620,0,15636,15637,0,0,15649,0,0,0,0,0,0,0,15650,0,0,15651,0,0,0,\n15656,0,15658,0,0,0,15664,0,0,15665,0,0,15668,0,0,0,0,0,15669,0,0,15674,0,0,\n15675,0,0,0,0,15676,0,0,0,0,0,0,0,0,0,0,0,15677,0,0,0,0,15678,0,0,0,0,0,15679,0,\n0,15681,0,15686,0,0,0,0,15687,0,15688,0,0,15690,0,0,0,15697,0,15699,15700,0,0,0,\n0,0,0,0,0,0,15701,0,15702,15703,0,15704,0,15705,0,15707,0,15709,0,15712,15716,0,\n15717,0,15718,15720,0,0,0,0,0,15724,0,0,0,15725,0,15726,0,0,0,15740,0,15745,\n15746,0,0,15747,0,15748,0,0,0,0,0,15749,0,0,0,15752,0,15753,0,0,0,0,0,0,15759,0,\n0,0,15765,0,0,0,0,0,0,0,0,0,15767,0,0,0,15771,0,0,15784,0,0,0,0,15785,15790,\n15791,0,0,15792,0,0,0,15807,0,15811,0,0,0,0,0,0,0,0,0,0,0,0,15818,0,0,0,15819,0,\n0,0,0,15821,0,0,0,0,0,15822,15824,0,0,15827,0,0,15829,15831,0,15832,0,0,15833,0,\n15835,15838,15839,15843,0,0,0,0,0,0,0,0,0,0,0,15844,0,0,0,0,15845,15851,15856,0,\n0,0,0,0,0,0,15858,15860,0,15861,0,0,0,15864,0,0,0,0,15865,0,0,0,0,0,0,15866,0,\n15872,0,0,15876,0,0,0,0,15877,15878,15883,15885,0,0,15888,0,0,0,0,0,15889,15890,\n0,0,0,0,0,0,0,0,15892,0,0,0,0,0,0,0,15893,0,0,15894,0,0,0,15895,0,15896,15897,0,\n15898,15901,15902,0,15911,15915,0,15916,0,15924,15935,0,15937,0,0,0,0,0,15950,0,\n0,0,0,0,0,0,15958,0,0,0,15961,0,0,15966,0,15967,0,0,15977,0,0,15978,0,0,15981,\n15982,15983,0,0,0,0,0,0,0,15986,0,0,0,15990,0,15991,15995,15998,0,15999,0,16000,\n0,0,0,0,16008,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16009,16011,0,16013,0,0,0,0,\n0,0,0,0,16014,0,0,16015,16023,16024,16025,0,0,16026,0,16030,0,16032,0,16033,0,0,\n0,0,0,0,16035,16036,16037,0,0,0,0,0,16039,0,0,0,0,16041,0,0,0,0,0,16043,16044,0,\n0,16047,0,0,0,16048,0,0,16049,16050,16052,0,0,0,0,0,16055,0,0,0,0,0,0,0,0,16056,\n0,0,0,0,0,0,0,16058,16060,16061,0,0,16063,0,0,16064,0,0,0,16067,16068,0,0,16069,\n16078,0,0,0,16079,0,0,0,16080,0,16081,0,0,0,16088,0,0,0,0,0,0,0,0,0,0,0,16089,\n16093,0,16097,0,16103,0,16104,16105,0,0,16256,0,0,16259,0,0,0,0,0,0,0,16260,\n16261,0,0,16262,0,0,16263,0,16268,0,0,0,0,0,0,0,16269,0,0,16270,16273,0,16274,0,\n0,0,0,16275,16276,16277,16280,0,0,0,16281,16284,0,0,0,16286,0,16289,0,0,0,0,0,0,\n0,0,0,16290,0,0,0,0,16291,0,0,0,0,0,0,0,16292,0,0,0,0,0,0,0,0,16293,16295,16297,\n0,16302,0,16304,0,16305,0,16306,0,0,0,0,0,0,0,0,0,0,0,0,16307,16308,16312,0,0,0,\n0,0,0,16313,16315,0,16318,0,0,0,16321,0,0,0,0,0,0,0,16326,16333,16336,0,0,0,0,\n16337,16340,0,0,0,0,0,16345,0,0,16346,0,0,0,0,0,0,0,0,0,16347,0,0,16348,0,0,0,0,\n16349,0,0,0,16350,0,16357,0,0,0,0,16359,16360,0,0,0,0,16362,16363,16364,16365,0,\n0,16366,0,0,0,0,16367,16368,0,16369,16374,0,0,0,0,0,0,0,16376,0,0,0,0,16378,\n16379,0,16380,0,0,0,16381,16383,0,0,0,0,0,16390,0,0,0,16399,0,16402,16404,16406,\n16407,0,0,0,16409,16411,0,0,0,0,16412,0,16413,16415,16423,0,0,0,0,0,16424,0,0,0,\n16428,16434,16435,16449,0,16450,16451,0,0,0,16453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n16454,0,0,16456,16458,0,0,16459,0,0,16460,0,0,0,0,16462,0,16463,0,0,16466,0,0,0,\n0,0,16479,0,0,16480,0,16481,16484,0,0,0,0,0,0,0,0,0,0,16485,0,0,0,0,0,0,16489,0,\n0,0,0,0,16491,0,0,16498,0,0,16503,0,16505,0,0,0,0,0,0,0,0,16506,0,0,0,16508,\n16509,0,0,0,0,0,0,0,0,16511,16513,0,0,0,16516,0,16517,0,16519,0,16529,0,0,16531,\n0,0,0,0,0,0,16534,0,0,16541,16542,0,0,0,0,0,0,0,0,0,16543,16547,16548,0,0,0,\n16551,0,16552,0,0,0,16553,0,0,16558,0,0,16562,16565,0,0,0,16570,0,0,0,16573,\n16585,0,0,0,16586,16587,16595,0,16596,0,16598,0,0,0,16600,0,0,0,0,0,0,0,0,0,0,0,\n0,0,16601,0,0,0,0,16603,0,0,0,0,0,0,0,16604,16612,0,0,0,0,16613,0,16618,0,0,0,\n16640,0,0,16641,0,0,0,0,0,0,16645,0,0,0,0,16646,0,0,0,0,0,0,16651,0,0,0,0,16653,\n16654,0,0,0,16655,0,0,16656,16667,0,0,0,0,16671,0,16672,0,0,0,16673,0,0,0,0,0,\n16676,0,16686,0,0,0,0,16689,0,16690,0,16692,0,16693,0,16694,0,16696,0,0,0,16705,\n0,0,0,0,0,0,16707,0,0,0,16709,0,0,0,0,16711,0,16712,16713,0,0,0,16715,0,0,0,0,\n16716,0,0,0,0,0,0,0,0,0,16718,16724,0,0,16726,16727,0,0,0,0,0,0,0,16728,0,16729,\n0,0,16730,0,0,0,0,0,16731,0,0,0,16732,0,0,0,0,16734,16738,0,0,0,0,0,0,0,0,16743,\n0,0,16745,0,0,0,0,0,16749,0,16752,0,0,0,0,16756,0,0,16758,0,16759,0,0,0,0,0,\n16760,0,0,0,0,0,0,0,16762,0,16769,0,16770,0,16772,0,0,0,16777,16780,0,0,0,0,0,0,\n16781,0,0,16782,0,16784,0,0,16785,16787,16792,0,0,16794,0,0,0,16798,0,0,16809,0,\n0,16814,16816,16817,0,16819,0,0,0,0,0,0,0,0,0,0,16820,0,0,16836,16839,0,0,16841,\n16851,16857,0,0,16858,16859,0,0,16860,0,0,0,0,0,0,0,0,16862,0,16863,0,0,0,0,0,0,\n0,16864,0,0,0,0,0,0,0,16876,0,16881,16882,0,16885,16886,0,16887,0,0,0,16889,\n16891,0,0,0,0,0,16894,16895,0,0,0,0,0,0,0,0,0,0,0,16897,0,16898,0,0,0,0,0,16913,\n0,0,16924,16925,16926,0,0,16927,0,0,0,16937,16938,0,0,0,16940,16941,0,0,0,16942,\n16945,0,16946,16949,16950,0,0,0,16952,16955,0,0,0,16965,0,16969,0,0,16975,0,0,\n16976,0,0,0,0,16978,0,0,16981,0,16983,16989,0,0,0,0,16990,0,0,16991,0,0,0,16993,\n0,16994,16996,17000,0,0,0,0,0,17002,17004,0,17006,0,0,17007,0,0,0,0,17008,17013,\n17014,0,0,0,0,0,0,0,0,0,17021,0,17031,0,0,0,0,0,17033,17036,0,17038,0,0,17039,0,\n17045,0,0,17046,17047,0,0,0,0,17048,0,17049,17050,0,17051,17053,0,17054,0,17055,\n0,0,0,0,0,17063,0,0,17064,0,0,0,0,0,0,0,17065,0,0,17068,0,0,0,0,0,17072,0,0,0,0,\n0,0,17073,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17074,0,17080,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,17081,17083,17084,0,0,0,17085,0,0,0,0,17092,0,0,0,0,0,0,0,\n0,0,17093,0,17095,17102,0,0,0,0,0,0,17103,0,0,17105,0,17107,0,0,0,0,17114,0,0,0,\n0,0,17115,17125,17127,0,0,17128,0,0,0,17129,17130,0,17131,0,0,0,0,0,17132,17135,\n17145,0,0,0,0,0,0,0,0,17146,0,17147,0,17148,0,0,0,0,0,0,17149,17150,0,17151,\n17153,0,17155,0,0,0,0,17163,17171,0,17174,0,0,0,0,17179,0,0,17182,17185,0,0,0,0,\n0,17186,0,0,17188,0,0,0,0,0,0,0,17189,17191,0,17194,0,0,0,0,0,0,0,0,0,17195,\n17196,17203,17204,0,0,17205,17217,0,0,0,0,0,17218,0,0,0,0,17219,0,17220,0,17221,\n0,0,17230,0,0,0,0,0,17236,0,17238,17239,0,0,0,17241,17244,0,0,17245,0,17248,0,0,\n17251,0,17252,0,0,17264,0,17266,0,0,0,17268,0,0,0,0,17271,17272,0,17273,0,17295,\n0,17302,0,17305,0,0,0,17306,0,0,0,0,0,0,0,17308,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n17309,0,17310,17313,0,0,0,0,17314,17315,0,17317,0,0,0,0,17318,0,0,0,0,0,0,0,\n17320,0,0,0,0,0,0,17334,0,17344,17348,0,0,0,17350,17351,0,0,17353,0,0,17354,0,0,\n0,0,0,0,0,0,0,17355,0,0,0,0,0,0,17356,17357,0,0,17359,0,0,0,17371,0,17372,0,0,0,\n17393,0,0,0,0,17394,0,0,0,0,0,17395,0,0,17399,0,0,0,17401,17417,0,17418,0,17419,\n0,0,0,0,0,17422,17423,0,0,0,0,0,17424,0,0,0,0,0,17428,17429,17433,0,0,0,17437,0,\n0,17441,0,0,17442,0,0,17453,0,0,0,0,0,0,0,0,17454,17456,17462,0,0,17466,0,0,\n17468,0,0,17469,0,0,0,0,17470,0,17475,0,0,0,0,0,17479,0,0,0,17483,17484,0,17485,\n0,17486,0,17491,17492,0,0,17493,0,17494,17495,0,0,0,17496,0,0,0,17497,0,0,0,\n17502,0,0,0,0,0,17503,0,17505,0,17507,0,0,0,17512,17513,17514,0,0,17515,0,0,0,\n17519,0,0,0,17522,0,0,17523,0,0,0,0,0,0,0,0,0,17527,0,0,0,17528,0,0,0,17534,0,0,\n0,0,17536,0,0,0,17539,0,17540,17543,17549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17556,\n0,0,17558,0,17559,0,0,17560,0,0,0,17563,0,0,0,0,0,0,17564,0,0,17565,17566,0,\n17567,0,0,0,0,0,0,17569,17570,0,17575,0,0,0,0,0,0,0,0,0,0,0,17581,0,0,0,17582,\n17583,0,17586,0,0,17587,0,0,0,0,0,0,0,17588,0,0,0,0,17596,17597,0,0,17598,17600,\n0,0,0,0,0,0,17601,0,0,0,17604,0,0,17605,0,0,17607,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,17612,0,0,17618,0,17621,17622,0,0,0,0,17623,0,0,17624,0,0,17630,0,0,\n17631,17633,17634,0,0,0,0,0,0,0,17635,0,0,17636,0,0,17637,0,17638,0,17640,0,0,0,\n0,0,0,0,0,0,0,17641,0,0,0,0,0,0,0,0,0,0,17643,0,0,0,0,17645,0,0,0,0,0,0,0,0,\n17646,17662,0,0,0,0,0,0,0,0,0,17663,17664,0,17665,17666,0,0,0,17669,17671,17673,\n0,17679,0,0,0,0,0,0,0,17684,0,0,0,17686,0,17714,0,0,17720,17722,17726,0,0,17728,\n0,0,17729,0,0,0,17732,0,17733,0,17734,0,0,0,17735,0,0,0,0,17737,0,0,0,0,17739,0,\n0,0,17741,17742,0,0,0,0,17743,17744,17745,0,0,0,17749,0,17750,17751,17752,17754,\n17761,17762,0,17763,0,17766,0,17772,0,0,0,0,0,17775,0,0,0,0,0,0,0,17776,0,0,\n17777,0,0,17778,17779,0,17782,17783,0,0,0,0,0,0,0,0,0,0,17784,0,0,0,0,0,0,0,\n17821,0,0,0,17822,0,0,0,17823,17825,0,0,0,0,0,17826,17831,17832,17833,0,0,17845,\n0,0,0,17846,0,0,0,17848,17850,17854,0,17855,0,0,17859,0,0,0,0,0,0,17860,17861,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17870,17871,0,0,0,0,0,0,17872,0,0,0,17879,0,\n0,0,17881,17883,0,17884,0,17885,0,0,17886,0,0,17887,17891,17953,0,0,0,0,17954,0,\n0,17955,0,17968,0,0,17972,0,0,0,0,0,17974,0,0,0,0,17976,17978,0,0,17983,0,0,0,0,\n18003,0,0,0,0,0,18007,0,0,0,0,0,18009,0,0,0,0,0,0,0,18010,0,0,0,0,0,0,18012,0,0,\n18014,0,0,0,18015,0,0,0,18016,0,18017,0,0,0,18030,0,0,0,0,0,0,0,18031,0,0,18036,\n18037,18038,0,0,18049,18056,0,18057,18058,0,18059,0,0,0,0,0,0,0,0,18062,0,0,0,0,\n18064,0,0,0,0,0,0,0,0,18067,0,0,0,18068,0,0,18075,0,0,18078,18093,18094,0,0,0,0,\n0,0,0,0,18097,0,0,0,0,0,18098,18100,0,0,0,18108,0,18111,0,0,18112,0,18113,0,0,\n18115,18116,0,18118,0,0,0,0,18121,0,0,0,0,18123,0,0,0,0,0,0,0,0,0,18124,0,0,0,0,\n18125,18126,0,18127,0,0,18128,18135,0,0,0,0,0,0,0,0,0,18150,0,0,0,0,0,18151,\n18152,0,0,18156,18164,0,18166,18171,0,0,0,0,0,0,0,0,0,18172,18183,0,18184,0,0,0,\n0,18185,0,18187,0,0,0,0,0,18188,0,0,0,0,0,0,0,0,18189,0,0,18190,0,0,18191,18192,\n0,0,18194,18195,18196,0,0,0,18197,0,18203,0,18204,0,0,0,0,18205,0,0,0,18207,\n18208,0,0,18214,0,0,0,18215,18216,0,0,0,18220,0,0,18222,0,0,0,0,0,18223,0,18225,\n18231,0,18234,0,18235,0,0,0,0,18240,0,0,18241,18242,0,0,0,0,0,18243,18251,0,\n18253,0,18254,0,0,0,18266,0,0,0,0,0,0,18269,18270,18271,18273,18281,0,0,0,0,0,0,\n0,0,0,0,0,0,18282,0,18283,0,18284,0,0,0,0,0,0,18285,0,18287,18289,0,0,18290,0,0,\n0,0,18308,0,0,0,18310,0,0,0,0,0,0,0,0,0,0,0,0,18311,0,18312,18313,0,18315,0,0,\n18316,18320,0,18331,0,18332,0,18336,0,0,0,0,18337,0,18340,0,0,0,0,0,0,0,0,0,\n18341,0,18344,18345,0,18346,0,0,0,0,0,18348,0,18351,0,0,18356,0,0,0,0,0,0,18357,\n0,0,0,0,0,18367,0,0,0,18368,0,18369,0,18370,18371,0,0,0,18437,18444,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,18445,18450,0,0,0,0,18451,0,18452,0,0,0,18453,0,0,0,0,0,18455,0,\n0,0,18456,0,18457,0,18460,0,0,18461,0,0,0,0,0,0,0,0,18466,0,0,18467,0,0,0,0,\n18473,0,0,0,18476,0,18477,0,0,0,18478,18479,18480,0,0,0,18485,0,0,0,18486,0,0,0,\n0,0,0,18488,18490,0,0,0,0,0,0,18491,0,0,0,0,0,18495,0,0,18496,0,0,0,0,0,0,18505,\n0,18521,0,18522,18523,0,0,0,18525,18526,0,0,0,0,0,18527,0,0,0,0,18532,18533,0,\n18534,0,0,0,0,0,0,18535,18537,0,18538,0,0,0,0,0,0,18540,18541,18542,18543,0,\n18546,0,0,0,0,18553,18556,0,0,18558,0,0,18569,18571,0,0,0,18572,0,18574,0,0,0,0,\n18586,0,0,0,0,0,18588,0,0,18589,0,0,0,0,0,0,18590,0,18592,0,0,0,0,18594,0,0,0,\n18596,0,0,18597,18598,0,0,18601,0,0,0,0,18602,0,0,0,18603,18604,0,18605,0,0,0,0,\n18608,0,0,18611,0,0,0,0,0,0,0,0,0,18612,0,18616,0,0,18617,18619,0,0,0,18628,0,0,\n0,18629,0,0,18630,0,0,0,0,0,0,0,18631,0,18632,0,0,18635,18637,0,0,0,0,0,0,18641,\n18643,18648,0,18652,0,0,18653,0,18655,18656,0,0,0,18657,0,0,18666,18674,0,0,0,0,\n18677,18684,18685,0,0,18686,0,0,18690,0,0,0,0,0,0,0,18695,18696,0,0,0,0,0,0,0,0,\n0,0,18697,0,0,18700,0,0,0,0,0,0,18702,0,18708,0,0,18709,0,18710,0,0,18711,0,\n18714,0,0,18718,0,0,0,0,0,0,18719,0,0,18722,0,18726,0,0,0,0,0,0,0,0,0,0,0,0,0,\n18731,0,0,0,0,0,18739,18741,0,0,18742,0,18743,18744,18746,18748,0,18752,18753,0,\n0,18754,18763,0,18765,0,0,0,18766,0,0,0,18769,0,0,0,0,0,18773,18778,18779,18781,\n0,0,18784,18787,0,18788,0,18793,0,0,0,0,0,0,18795,0,0,18800,0,0,0,0,0,18801,\n18804,0,0,0,0,0,0,0,18806,0,0,0,18811,18815,18816,0,0,0,0,18825,0,0,18827,18829,\n0,0,18830,0,0,0,0,18831,0,0,18832,0,0,0,0,18833,0,18840,0,18841,0,18842,0,0,0,0,\n18843,0,18844,0,0,0,0,0,0,18845,18846,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n18848,0,0,0,18853,18860,0,0,18862,18866,0,0,18867,18869,0,0,18874,18881,18891,0,\n0,0,0,0,0,0,0,0,0,18892,0,0,0,0,0,0,0,0,18895,0,18896,0,0,0,18900,0,0,0,18901,0,\n18902,18915,18916,0,0,0,0,0,0,0,0,18919,0,0,0,0,0,18920,0,0,0,18921,18929,0,0,0,\n0,18930,0,0,0,0,0,0,18932,0,0,0,0,18934,18942,0,0,0,18951,18957,0,0,0,0,18958,0,\n0,0,0,18959,18960,0,0,18961,0,0,18962,0,0,0,0,18963,18964,0,0,0,18965,0,18967,0,\n0,0,0,0,0,0,0,0,18968,0,18969,0,18970,18973,18976,0,0,0,0,0,0,18977,0,0,0,18981,\n0,0,0,18990,0,18998,0,0,0,0,0,18999,19003,0,0,19005,0,0,0,19006,0,0,0,0,0,0,\n19008,19011,0,0,19018,0,0,19019,0,19024,0,19031,19032,0,19039,0,19041,19050,0,0,\n0,19051,19055,19056,0,19059,19063,19064,0,0,19088,0,0,0,19093,19094,0,0,0,0,\n19095,0,19096,0,0,0,19097,0,0,19098,0,19099,19100,0,0,19103,0,0,0,0,0,0,0,19111,\n0,0,0,0,0,0,19112,0,0,0,19116,19117,0,19121,19122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,19123,19124,0,0,0,0,0,0,0,19125,19126,0,19128,0,0,0,0,0,0,0,0,0,0,\n19129,19130,19131,19132,0,0,19146,0,0,19147,19156,19158,0,0,0,0,0,0,0,0,19182,\n19185,0,0,19187,0,0,0,19193,0,0,0,0,0,19194,0,19197,0,0,0,0,19198,0,0,0,0,0,0,0,\n0,0,0,19202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19203,0,19205,19210,\n0,0,0,19213,0,19218,0,0,0,19223,19229,0,0,19230,0,0,19231,19232,19233,19239,0,0,\n0,0,0,19240,0,19248,19249,0,0,0,0,19254,0,19256,19258,19259,0,0,19261,0,19266,0,\n0,0,19272,0,19278,19281,19282,0,0,0,0,0,0,0,0,0,0,0,0,19283,0,0,19284,0,0,19285,\n19287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19288,19291,0,19292,0,0,0,0,19297,0,19298,0,0,\n0,0,19302,19303,0,0,0,0,19304,19305,0,0,0,0,19314,0,0,19315,0,0,19321,0,0,0,0,0,\n0,0,19322,0,19333,0,19334,19335,0,19336,19337,0,0,0,0,0,0,0,0,0,0,0,19346,0,0,\n19353,0,19354,19362,0,19366,19367,0,0,19369,0,19375,0,19377,19380,19388,0,0,0,0,\n0,19389,19390,0,0,0,0,19392,0,0,0,0,0,19402,0,0,0,0,0,0,0,0,19412,0,0,19413,\n19422,0,19424,0,0,0,19425,0,0,0,19428,0,0,0,0,19431,0,0,0,0,0,19432,0,0,0,0,0,\n19448,19459,0,0,19461,0,19462,19463,0,19467,19474,19482,0,0,0,0,19494,0,0,0,0,\n19501,0,0,0,0,0,0,0,0,0,0,19502,19504,0,0,0,0,0,0,0,19505,0,0,0,0,19506,19507,0,\n0,0,19508,0,0,19511,0,0,19514,0,19515,0,19516,0,19518,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,19530,0,19537,19538,0,19543,19546,0,19547,19551,0,0,0,0,0,0,19552,\n19553,0,0,0,0,0,0,0,0,0,0,0,0,19555,0,0,19556,0,0,0,0,0,0,0,0,0,0,0,0,19560,\n19561,0,0,19562,0,0,0,0,0,0,19565,19567,0,19568,0,0,0,19569,19570,0,19578,0,0,0,\n0,19580,0,0,0,0,19581,19584,0,0,0,0,0,0,0,19585,19586,0,0,0,19587,19588,0,19589,\n0,0,0,0,0,0,19592,19593,19599,0,19600,0,0,19604,0,0,19605,0,19606,19608,19610,0,\n19613,19614,0,0,0,0,0,0,19616,19617,0,0,19618,0,0,19619,0,0,0,19620,19621,19631,\n0,0,19632,19634,19636,0,19643,0,0,19644,19658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,19659,0,0,0,0,0,0,0,0,0,0,0,19675,19677,0,0,0,0,19679,0,19683,0,19684,0,0,\n0,0,0,0,19687,0,0,0,0,0,0,0,0,19688,19689,19692,0,0,0,0,0,0,0,19695,19697,0,0,0,\n0,0,19698,19699,0,0,19700,0,19702,0,0,19703,0,0,0,0,0,0,19704,19708,0,19710,0,\n19713,0,0,0,19715,0,0,0,0,19718,0,0,0,0,0,0,0,19720,0,19722,0,0,19725,0,0,0,0,0,\n0,0,0,0,0,0,0,0,19730,0,0,0,0,0,19731,0,19734,19735,19739,0,0,19740,0,19741,0,0,\n0,19746,0,0,19747,0,19771,0,0,0,0,0,0,0,0,19772,19775,0,0,0,0,0,0,19778,0,0,0,0,\n0,19779,0,0,19780,19790,0,19791,0,0,19792,0,0,0,19793,0,0,19796,19797,0,0,0,\n19799,0,0,0,19801,0,0,0,0,19803,0,19804,0,19805,0,0,19807,0,0,0,19808,0,0,0,0,0,\n0,19809,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19816,0,19821,0,19822,19830,19831,0,0,\n0,19833,0,0,0,0,0,0,0,0,0,0,19838,0,0,0,0,19839,0,0,19843,0,0,0,0,19845,0,0,0,0,\n19847,0,0,19848,0,19849,0,0,0,0,0,0,0,19851,0,0,0,19854,0,0,0,0,0,0,0,0,0,19864,\n0,19865,0,19866,0,0,0,0,0,0,0,19868,0,0,19870,0,0,19871,0,0,19872,19873,19875,0,\n19880,19882,19884,0,0,19885,19886,19888,0,0,0,0,0,0,0,0,0,0,0,0,19890,19892,\n19893,0,0,19894,0,0,0,19895,0,19896,19902,0,0,19903,0,0,19905,0,0,0,19906,0,\n19908,0,19909,19911,0,0,0,19913,19920,0,19938,19939,19940,0,0,0,0,0,0,0,19942,0,\n19943,0,19945,0,0,0,19951,19952,19954,19960,0,19965,0,19971,0,0,0,0,0,19975,0,\n19976,0,19990,0,0,19991,0,19993,0,19995,0,0,0,19998,19999,20001,0,20003,20005,0,\n20011,20012,0,0,0,0,0,0,20014,0,20020,0,0,0,0,20021,0,0,0,0,0,20023,20024,0,0,0,\n0,0,20025,0,0,20027,0,0,20029,0,0,20032,0,0,0,0,20044,20045,0,20048,20049,0,0,\n20050,0,20052,0,0,20054,20057,0,0,0,0,0,0,0,0,0,20059,0,0,20061,0,20062,0,20064,\n0,0,20066,0,0,20067,0,0,0,0,20069,0,0,0,0,0,0,20070,20071,0,0,0,0,0,0,0,0,0,0,0,\n20072,0,0,20073,20074,0,0,0,0,0,20075,0,20078,0,0,0,0,20080,0,20081,0,0,0,0,0,0,\n20095,0,20098,0,0,0,0,0,0,0,20107,0,0,0,0,0,0,0,0,20112,0,0,0,20113,20114,0,0,0,\n20115,20123,20124,0,0,0,20131,20133,20134,0,0,0,0,20136,0,0,20137,20138,20150,0,\n20152,0,0,0,20153,0,0,20154,0,0,0,20158,0,20163,0,0,20164,0,0,0,0,0,0,0,20166,0,\n20168,0,20170,0,20175,0,0,20178,0,0,0,0,20223,0,0,0,0,20224,0,20226,0,0,20230,0,\n20231,0,0,0,0,20232,0,0,20233,20234,0,20244,0,20247,0,0,0,0,0,0,20249,0,0,0,\n20250,0,0,0,0,20251,0,20253,0,20254,0,0,0,0,20256,0,0,20264,0,0,0,0,20266,0,0,0,\n20278,0,0,20279,20282,0,0,0,0,0,20283,0,20284,0,20285,0,20287,20290,0,0,0,0,\n20292,0,0,0,0,20293,20297,0,0,0,0,0,0,20299,0,20300,20303,0,0,0,0,0,0,20307,0,0,\n20308,0,20309,0,20310,0,0,0,0,0,0,20312,0,0,0,20314,0,0,0,0,20315,20316,0,20322,\n0,0,0,0,0,0,20339,0,0,0,20342,0,0,0,0,20352,0,0,0,0,0,0,0,0,0,0,20362,0,0,20365,\n0,20375,20377,0,0,0,0,0,0,0,0,0,0,0,20378,20379,0,20380,0,0,20381,0,20382,0,\n20383,0,20388,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20390,20392,20393,0,0,20395,0,0,0,0,0,\n20396,0,0,0,0,0,0,0,0,20398,20415,0,0,0,20417,0,0,20420,0,0,20426,20428,0,20431,\n0,0,20432,0,20433,20434,20435,0,0,0,0,20440,0,0,0,0,0,20442,0,20443,0,20446,0,0,\n0,0,20448,0,20451,0,0,0,0,0,0,0,0,0,20452,20453,0,0,20454,0,0,0,0,0,0,20457,0,\n20458,0,0,0,20465,0,0,0,0,0,20469,0,0,0,20473,0,20476,0,0,0,0,0,0,0,0,20477,0,0,\n20485,0,0,20486,0,0,20487,0,20496,0,20497,0,0,20498,0,0,0,0,0,0,0,0,0,0,20499,\n20500,0,20501,0,0,0,0,0,20520,20527,0,20529,0,0,0,0,20539,0,0,20540,0,0,0,20543,\n0,0,0,20546,0,0,0,0,0,20548,0,0,20563,0,0,20564,0,20566,0,0,0,0,0,20589,0,0,0,0,\n20590,0,0,20593,20594,0,0,0,0,20595,0,20597,20598,0,0,0,20618,20620,0,0,0,0,\n20621,0,0,0,0,20627,0,0,0,0,0,20628,0,0,0,20629,0,20630,0,0,20639,0,0,0,0,0,\n20707,0,0,20709,0,0,0,20713,20714,0,0,0,0,0,20724,20725,0,0,0,0,20726,20728,\n20729,0,20733,0,20734,0,20735,20736,0,20737,0,0,20744,0,20745,0,20748,0,0,20749,\n0,0,0,0,0,0,0,0,20750,0,0,0,0,20754,0,0,0,20761,0,0,20763,0,0,0,0,0,0,0,20766,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,20767,0,0,0,0,20768,0,20769,20777,0,0,0,0,0,0,20785,0,\n0,0,20786,20795,20801,0,20802,0,20807,0,0,20808,0,0,20810,0,0,20811,0,20812,0,0,\n0,0,0,20813,0,0,20818,20820,20821,0,0,0,20822,0,20823,0,0,0,20826,0,0,0,0,0,0,0,\n20829,20830,20831,0,20832,20836,0,0,20839,0,0,20840,20842,0,20843,0,20844,0,\n20854,0,0,0,20855,0,0,0,0,20856,0,0,0,20869,0,0,20871,0,0,0,0,0,0,0,20873,0,0,0,\n0,0,20876,0,0,0,0,0,20880,0,0,20882,0,0,0,0,20883,20884,0,0,20890,0,0,0,0,0,0,0,\n0,0,20891,0,0,0,0,0,20905,0,20906,20910,0,0,20912,20915,0,0,0,0,0,20916,0,20917,\n0,20919,20920,20922,0,20927,0,20928,20929,20930,0,0,20935,0,0,20939,0,0,20941,0,\n0,0,20943,0,0,0,20946,20947,0,0,0,0,0,20950,0,20954,0,0,20955,20964,0,0,20967,0,\n0,0,0,0,20973,20975,0,0,0,20984,0,20987,20988,0,0,0,0,0,20989,0,0,0,20995,0,\n20998,0,20999,0,0,0,0,21000,21001,0,0,0,0,21008,0,21010,0,21016,0,0,0,21017,\n21018,0,0,0,0,0,21021,21026,21027,21028,0,0,21029,0,0,0,0,0,21030,0,0,0,0,0,0,0,\n0,0,0,0,0,0,21031,21032,0,0,0,0,0,21037,0,0,21038,0,0,0,0,0,0,0,0,0,21039,0,\n21041,0,21046,21047,0,0,0,21049,21053,0,0,21057,21064,21065,0,0,21066,21067,0,0,\n0,21069,0,0,0,21071,21072,0,0,21073,0,21074,0,0,21078,0,0,0,0,21079,0,0,21080,\n21081,0,0,21086,21087,0,21089,0,0,0,0,0,0,0,21091,0,21093,0,21094,0,0,0,0,0,0,0,\n0,21095,0,0,0,0,0,21096,0,21098,0,0,0,0,0,0,0,21099,0,0,21100,21101,21102,0,0,0,\n0,0,21103,0,21104,0,0,0,0,0,21105,21108,21109,0,0,21112,21113,0,0,0,0,0,0,21115,\n21122,21123,0,0,0,0,0,21125,0,0,0,0,0,0,0,0,21129,21131,0,0,21134,0,0,0,21137,\n21142,0,21143,0,0,21144,0,21145,21146,0,21152,21154,21155,21156,0,0,0,21160,0,0,\n0,0,0,0,21161,0,21164,0,21166,0,0,0,0,21170,0,0,0,0,21171,0,0,21172,0,21174,0,\n21175,0,0,0,0,0,21176,21179,21188,0,0,0,21189,0,0,21190,0,0,0,21192,0,0,21193,0,\n0,0,21198,0,21212,0,0,21213,0,0,0,0,0,0,21215,21216,0,0,21223,21225,0,21226,0,0,\n0,0,21227,21228,0,0,21229,0,0,0,0,21230,21236,0,0,0,0,0,0,0,0,0,0,0,0,0,21237,0,\n0,21238,21239,0,0,0,0,21256,0,0,0,0,0,21257,0,0,0,0,0,0,0,21259,0,0,0,21263,0,\n21272,0,21274,0,21282,0,0,0,0,0,0,0,0,21283,0,0,0,0,0,0,0,0,21294,0,0,21297,0,0,\n0,0,21298,0,0,0,21299,0,21300,21302,0,21316,0,21318,21322,21323,0,21324,0,21326,\n0,0,0,21327,21328,0,0,0,21352,0,0,21354,21361,0,0,0,0,0,0,0,0,0,0,0,0,0,21362,0,\n0,0,21363,0,0,0,0,0,0,0,0,0,21366,0,0,21367,21372,21374,0,0,0,21375,21377,0,\n21378,0,0,0,21380,0,0,0,0,0,0,0,0,0,0,21381,0,0,0,0,0,0,21382,0,21383,0,0,21384,\n0,0,21385,0,0,0,0,21389,21390,0,0,0,0,0,0,0,0,0,0,0,0,0,21397,21398,0,0,0,0,0,0,\n0,0,0,0,21399,0,21400,0,0,0,0,21402,0,0,0,21403,21404,0,21405,21406,0,0,0,21407,\n0,0,0,0,0,0,0,0,0,0,0,0,21408,0,0,0,0,21409,0,21421,0,21422,0,0,0,21425,21428,0,\n0,0,0,21429,0,0,0,0,0,21433,0,0,0,0,0,0,0,0,0,0,21434,0,21443,0,21444,21449,0,\n21452,0,21453,21454,0,0,0,21457,0,0,21458,0,0,0,21460,21461,0,0,21464,0,0,0,\n21473,21478,0,0,21479,0,0,21481,21483,0,0,0,0,0,0,0,0,21484,0,0,21485,21486,0,0,\n21488,0,0,0,0,0,0,21523,0,0,21525,0,0,0,0,0,0,0,21526,0,0,0,0,0,0,21529,21530,0,\n0,21531,0,0,21533,0,0,21539,21564,0,21567,0,0,0,0,0,0,0,0,21575,0,0,0,0,21577,0,\n0,0,0,0,21591,0,0,21604,0,0,0,0,0,0,0,0,0,21605,0,21606,0,0,21617,21618,21619,\n21620,0,0,0,0,0,0,0,0,0,0,0,0,0,21623,0,0,0,0,21631,0,21635,0,0,0,0,21639,21646,\n21653,21662,0,0,21663,21664,0,21666,0,0,21667,0,21670,21672,21673,0,21674,21683,\n0,0,0,0,0,21684,0,21694,0,0,0,0,21695,21700,0,21703,0,21704,0,0,21709,0,0,0,\n21710,0,0,0,0,0,0,0,0,21711,0,0,0,21712,0,21717,0,21730,0,0,0,21731,21733,0,0,0,\n0,21737,21741,21742,0,21747,0,0,0,21749,0,0,0,0,0,0,0,0,0,0,0,0,0,21750,0,0,0,0,\n0,21752,0,0,0,0,21753,0,0,0,0,0,0,21755,21756,0,21757,0,0,0,0,0,0,21760,0,0,\n21763,0,0,0,0,0,0,0,0,0,21764,0,0,21766,0,0,21767,0,0,0,0,0,0,0,0,0,21773,0,\n21774,0,0,21775,0,0,0,0,21776,0,0,21777,0,0,0,0,0,0,0,0,0,21780,21787,21788,\n21791,0,0,0,21797,0,0,0,0,0,21805,0,0,0,0,21806,0,21807,21809,0,21810,21811,0,\n21817,21819,21820,0,21823,0,21824,0,0,21825,0,0,21826,21832,0,0,0,0,0,21833,\n21848,21849,0,0,21867,21870,21871,21873,0,0,0,21874,0,0,0,0,0,0,0,0,0,21875,0,\n21878,0,0,0,21879,0,21881,21886,0,0,0,0,21887,0,0,21888,21894,21895,21897,0,\n21901,0,21904,0,0,21906,0,0,0,21909,21910,21911,0,0,21912,0,0,21913,21914,21915,\n0,21919,0,0,0,0,0,0,0,21921,0,0,21922,21933,21939,0,0,0,0,0,0,0,0,0,0,0,21944,0,\n0,0,0,0,21945,0,21947,0,0,0,0,0,0,0,0,0,0,21949,0,0,0,21950,0,0,0,0,0,0,0,0,0,0,\n0,0,0,21951,0,21952,0,0,0,0,0,0,0,0,0,21954,21957,0,0,0,0,21958,0,21959,0,0,0,0,\n0,0,21962,21963,0,0,0,0,0,0,0,0,21964,21965,0,0,21969,21970,0,0,0,21974,0,0,\n21980,21981,0,21982,0,0,0,0,0,21985,0,21988,0,21992,0,21999,0,0,0,0,0,0,22001,0,\n22002,0,0,0,0,0,0,22003,0,0,0,0,0,22004,0,0,0,22008,0,22009,22015,0,0,22016,0,0,\n0,22017,22019,0,0,0,0,0,0,0,0,0,22020,0,0,0,0,0,0,0,0,0,0,22021,22037,0,22039,0,\n0,0,22040,0,0,0,22048,22049,0,0,22053,22055,22056,22059,0,0,22060,22061,0,0,\n22064,0,0,0,0,22066,0,0,0,0,0,0,0,22073,0,0,0,22074,22075,0,0,0,0,0,0,0,22076,0,\n0,0,0,22077,22084,22099,0,0,0,0,0,0,0,22104,0,0,22107,0,22108,0,22109,0,22110,0,\n0,0,0,0,0,0,22111,22119,0,22120,22122,0,0,0,0,22125,0,0,0,22128,22129,0,0,0,0,0,\n0,22141,0,0,0,22142,0,0,22144,22146,0,22148,22149,22151,22154,0,0,0,22162,0,0,0,\n0,22164,22177,0,0,0,0,22179,0,22182,22183,0,0,22184,22188,0,0,0,0,0,0,0,0,22190,\n0,22194,22201,0,0,22208,0,22209,0,22212,0,0,22215,0,22223,22231,0,0,22232,0,\n22234,0,0,22235,22236,0,22237,0,22240,0,0,0,0,0,22241,0,0,0,22242,22246,22247,0,\n0,0,22259,22268,0,22269,0,0,0,0,0,0,0,22270,0,0,0,0,22271,0,22272,0,22277,0,0,0,\n0,0,22278,22280,22283,22286,0,0,22287,22289,0,0,22290,0,22293,0,0,0,0,0,0,0,0,0,\n0,22295,0,22301,22302,0,0,0,22305,0,22308,0,0,0,0,0,0,0,0,0,0,22315,0,0,0,22317,\n0,22334,0,0,0,22335,0,0,0,0,0,22336,0,22338,22344,0,22347,22349,0,22350,0,0,0,0,\n0,0,0,22357,0,0,0,0,0,22358,0,0,0,0,0,0,0,0,0,0,22359,22360,0,0,0,0,0,0,0,0,\n22361,22366,0,0,22369,0,22370,22373,0,0,0,0,0,22375,0,22377,0,0,0,0,0,22378,0,0,\n0,0,22381,0,0,0,0,22382,0,22383,0,0,0,0,0,0,0,0,0,22391,0,0,22392,22395,22396,\n22402,0,0,0,0,0,0,0,0,0,0,0,0,0,22405,0,0,22406,0,0,22408,0,0,22409,22410,0,0,0,\n0,0,0,22424,0,0,0,0,22426,0,0,0,22427,0,22428,0,22432,0,22435,22442,22443,0,0,0,\n0,22444,0,0,0,0,0,22446,0,22454,0,22455,0,0,0,22465,0,22470,0,22471,0,0,0,0,\n22472,22473,0,22487,0,0,0,22488,0,0,0,0,22489,0,0,22499,0,0,0,0,0,0,22514,0,0,\n22515,0,0,0,0,0,0,0,22516,0,0,0,22517,22520,0,0,0,22534,0,0,22535,0,0,22536,0,\n22540,22553,0,22555,0,0,0,0,22561,0,0,22562,0,0,0,0,0,0,0,0,0,0,0,22566,0,0,0,0,\n22567,22568,0,0,22575,0,22579,0,22582,22583,22585,0,0,0,0,0,22586,0,0,22587,0,0,\n22590,0,0,0,0,0,22591,0,22592,0,0,0,0,0,22593,0,22602,0,0,22604,0,0,22609,0,0,\n22618,0,0,0,0,0,0,22619,0,22624,22625,0,0,22638,0,0,0,0,0,22639,0,0,22640,0,0,0,\n0,0,0,0,22644,0,22645,22647,0,0,0,0,22652,22653,0,0,0,22654,0,22655,0,0,0,22656,\n0,0,0,0,0,0,0,0,0,0,22673,22675,22676,0,0,22678,22679,0,22691,0,0,0,0,0,0,0,\n22693,0,0,22696,0,22699,22707,22708,0,0,0,0,0,0,0,0,22718,0,22719,0,0,0,0,22723,\n0,0,0,22724,22725,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22726,22728,0,0,0,0,0,0,0,0,22729,\n0,0,22731,0,0,0,0,22732,22735,22736,0,0,0,0,22739,0,22749,0,0,22751,0,0,0,0,0,0,\n0,0,0,0,0,22758,0,0,0,0,0,22760,0,0,0,0,0,22764,22765,22766,0,22768,0,0,0,0,0,\n22769,22770,0,0,0,0,0,0,22771,0,0,22772,22775,0,22776,22777,22780,0,0,22782,\n22784,0,22787,0,22789,22796,0,0,0,0,0,22798,0,0,0,0,0,0,22802,0,22803,22804,0,0,\n0,0,0,0,0,0,0,0,22805,0,0,22810,22811,22814,22816,0,22825,22826,0,22831,22833,0,\n0,0,0,0,0,0,0,0,22834,0,22836,22838,0,22839,0,0,0,0,0,22840,0,22847,0,0,0,0,0,\n22856,22857,0,22858,22859,0,0,22862,0,0,22864,0,0,0,0,22865,0,0,0,0,0,0,0,0,0,0,\n0,22866,0,22867,22868,0,0,0,0,22869,0,22871,0,22872,0,22873,22881,22882,22884,\n22885,0,0,0,0,0,0,0,22886,22887,0,22894,0,22895,0,0,0,22900,0,22901,0,0,0,0,\n22904,0,0,0,0,22905,22907,0,0,0,22915,22917,0,0,22918,0,0,0,22920,0,0,0,22929,\n22930,0,0,0,22941,22942,0,0,0,22943,0,0,0,22944,0,0,0,0,0,0,0,22946,0,22947,0,0,\n22954,0,22956,0,0,22962,0,0,0,0,0,0,0,22963,0,0,22964,0,0,0,0,0,0,0,22965,0,\n22968,0,0,0,22969,0,0,0,0,0,22970,0,22971,0,0,0,0,0,22978,0,0,22979,0,22987,0,0,\n22989,0,0,0,0,0,0,22990,0,23005,0,0,0,0,0,0,0,23006,23007,23008,0,0,23023,23024,\n23029,0,0,0,0,23030,0,0,0,0,0,23032,0,0,0,0,0,23035,0,0,0,0,23038,0,0,0,23048,0,\n23049,23052,23053,23060,23061,0,23063,0,0,0,0,23067,23068,0,0,0,23069,23073,0,0,\n0,23127,0,23128,0,0,0,0,0,23129,0,23138,23141,0,23149,0,0,23150,0,0,0,23152,0,0,\n0,0,0,0,0,0,23154,0,0,0,0,23157,23159,23160,0,0,0,0,0,0,0,0,0,0,0,0,23180,0,0,0,\n0,23181,0,0,23188,0,23189,0,0,0,0,0,0,0,0,0,0,0,0,23195,0,0,23196,23199,0,0,0,0,\n0,0,0,0,0,23202,0,23204,0,23207,0,23209,23210,0,0,0,0,0,0,23227,23229,0,0,23230,\n23234,23238,0,0,0,23245,23246,23248,0,0,0,0,23249,23254,0,0,0,23265,0,0,0,0,0,0,\n0,23268,0,23276,0,0,0,0,23277,0,23297,0,23298,0,0,0,0,23299,0,23302,0,0,23303,\n23312,0,0,23314,0,23320,0,0,0,0,23324,0,23325,0,23328,0,23334,0,0,0,23337,0,0,0,\n0,23343,23344,23346,0,23348,0,0,0,0,0,0,0,0,23353,0,0,0,0,23355,0,23356,23358,0,\n0,0,23359,23360,0,23361,0,23367,0,23369,0,0,23373,0,23378,23379,0,23382,23383,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,23387,0,0,0,0,0,0,23388,23390,0,0,23393,23398,0,0,0,\n23399,0,0,0,23400,0,0,0,0,23401,0,0,0,23415,0,0,0,0,0,0,0,0,23416,0,23422,0,\n23443,23444,0,0,0,0,23448,0,23454,0,0,0,0,0,0,23456,0,0,23458,23464,0,0,0,0,0,0,\n23465,0,0,0,23470,23471,0,0,23472,0,0,0,23473,23496,0,0,0,0,0,0,0,0,23497,0,\n23499,0,0,23502,0,0,23503,0,0,23513,0,0,23515,0,0,0,23517,0,0,0,0,23518,23519,\n23521,23524,0,23525,23528,23539,0,0,0,0,0,23541,0,0,23544,0,0,23556,0,0,23557,0,\n0,0,0,0,0,0,0,0,0,0,0,0,23559,0,23560,0,0,23561,0,0,23566,0,0,0,0,0,23568,23569,\n23570,0,0,0,0,23571,0,23574,0,0,0,0,0,0,0,0,0,0,0,23575,0,23579,0,0,23581,0,0,0,\n0,0,0,23587,0,0,0,0,0,0,0,23596,23598,0,0,0,0,23602,23606,0,0,23607,0,23608,0,0,\n0,23614,23616,0,0,0,0,0,23618,0,0,23619,0,0,0,0,23621,23626,0,23627,0,0,0,0,0,0,\n0,23629,0,23630,0,0,0,0,23634,0,23636,0,0,0,0,0,0,23638,0,0,0,0,23640,23667,0,\n23669,0,0,0,23681,0,0,0,0,0,0,0,23682,0,23683,0,0,0,0,0,23684,0,0,0,23685,23689,\n0,23693,23694,23700,0,23702,0,23709,0,0,0,0,0,0,0,23712,0,0,0,0,0,23714,0,0,\n23715,0,0,0,0,23718,0,0,23720,0,0,0,0,23722,0,0,0,23726,23729,0,23741,23746,0,\n23748,0,0,0,0,23749,0,0,0,0,0,23750,0,0,0,0,23751,0,23753,0,0,0,0,23757,23765,0,\n0,0,23770,0,0,0,0,0,0,0,23771,0,23772,23781,0,0,23796,0,0,0,0,23798,0,23799,0,0,\n0,23802,0,0,23806,0,23807,0,0,23808,0,23809,0,23819,0,0,0,23821,0,23827,0,0,0,\n23829,0,0,0,0,0,0,0,23830,0,0,0,0,0,0,23832,23833,23834,23835,0,0,0,0,23837,\n23838,0,0,0,0,0,23846,0,0,0,0,0,0,23847,0,0,0,0,0,23879,23881,0,0,23882,23883,\n23895,0,23899,0,0,0,0,23901,0,0,0,0,0,0,23902,0,0,0,0,0,23903,23905,0,23906,0,\n23907,23918,23919,23920,0,23922,0,23924,0,23927,0,23934,0,23937,23941,0,23942,\n23946,0,0,0,0,0,23955,23956,23958,0,0,0,0,0,0,23959,0,23962,23965,0,23966,0,0,0,\n0,23967,23968,0,0,23973,0,0,23974,0,0,0,0,23975,0,23976,0,0,0,0,0,0,0,0,0,0,0,0,\n0,23977,0,0,0,0,0,0,0,0,23980,0,0,23984,0,23985,0,0,23987,0,0,23988,23990,23991,\n0,0,0,0,0,0,23992,0,0,0,0,0,0,0,0,23994,0,0,0,23998,0,0,0,0,0,0,0,0,0,23999,0,0,\n24003,0,24004,0,24006,0,0,0,24007,0,0,24008,0,0,0,0,0,0,0,24009,0,0,24010,0,0,\n24011,0,0,24013,24014,0,0,24015,24016,24027,0,24028,24029,0,24030,0,0,0,0,0,\n24033,24034,0,24035,0,0,24036,0,0,24044,0,24048,24049,24063,24067,0,24068,24070,\n0,0,24071,24078,24087,0,24090,0,0,0,24095,0,24098,24101,24104,24106,0,24107,0,0,\n0,24108,0,0,0,0,24110,24111,0,24113,0,0,24115,24120,0,0,0,0,0,0,24124,0,24125,0,\n24126,0,24127,0,0,0,0,0,24135,0,0,24136,0,24137,24142,0,0,0,24146,0,0,24147,\n24149,24154,0,24163,0,0,0,24165,24166,24167,0,0,0,0,0,0,0,0,0,0,24169,24170,\n24175,0,0,0,24178,0,0,24179,0,0,24181,0,24184,24197,0,24201,24204,0,0,0,0,0,0,\n24206,24212,24220,0,0,0,24224,0,0,0,0,0,0,0,0,24226,0,24234,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,24235,0,24236,0,0,0,0,0,24239,24240,24241,0,0,24248,0,0,24249,0,\n24251,0,0,0,0,0,0,24253,0,24268,0,0,0,24269,0,24271,24272,0,0,0,0,24273,0,0,\n24274,0,0,24279,0,0,0,0,0,0,0,24280,0,24293,24294,0,0,0,0,0,0,24296,0,0,24323,0,\n0,0,24329,24330,24331,24339,0,24351,0,0,24369,24370,0,0,0,24371,0,0,0,0,24372,\n24373,24374,0,0,0,0,0,24378,0,0,0,0,24379,0,24381,0,24383,24389,0,24390,0,0,\n24394,24395,24400,0,0,0,24401,24402,0,24406,0,0,0,24411,0,0,0,24415,0,24416,0,0,\n0,0,0,24417,0,24419,0,24422,0,24423,24428,0,24435,0,0,0,24439,0,0,0,24440,24442,\n24446,0,0,0,24447,24448,24449,24452,0,0,0,0,24453,24457,0,0,24458,24459,24460,0,\n24465,0,0,0,0,0,0,0,24470,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24471,0,24473,\n24474,24475,24476,0,24478,0,0,0,0,24480,0,0,0,0,0,0,0,0,0,0,24481,0,0,0,0,0,0,0,\n0,0,0,24482,24485,0,0,0,0,24486,0,0,0,24488,0,0,0,24494,0,0,0,0,24497,0,0,24498,\n0,0,0,24499,24506,0,0,0,24507,0,0,24511,0,0,24513,24514,0,0,0,0,0,24517,0,24518,\n0,24520,0,24521,24524,24525,0,0,0,0,0,24527,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24528,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24537,24539,0,24540,0,0,0,24548,0,0,0,0,0,24549,\n24550,0,0,0,24553,24554,0,24555,0,24556,0,24558,0,0,0,0,0,24560,0,0,0,24561,0,0,\n0,0,0,24562,0,0,0,0,0,0,0,0,0,0,0,0,0,24567,0,0,0,0,0,24569,0,0,0,24574,0,24575,\n0,0,0,0,0,0,0,0,0,0,0,24577,24581,0,24584,0,0,0,0,0,24585,0,0,0,0,0,24586,0,0,\n24587,0,24588,0,0,0,0,0,0,0,0,0,0,24590,24591,0,0,0,0,24592,0,0,0,0,0,0,0,24594,\n0,0,0,0,0,0,0,24596,24597,0,0,0,0,24602,24603,0,0,0,0,24604,0,0,24605,0,24610,0,\n0,24611,0,0,0,0,24612,24615,24616,24624,0,0,0,24627,0,24638,24639,0,0,0,0,24640,\n0,0,0,24655,24656,24657,0,0,0,0,0,0,0,0,24662,0,24663,24664,0,0,0,0,0,24665,0,0,\n0,0,24667,0,0,0,0,0,0,24668,24669,0,24670,24674,0,0,0,24675,0,24678,0,0,24679,0,\n0,0,24681,0,24683,0,0,0,0,24684,0,24685,0,0,24686,0,0,24688,24689,0,0,0,0,24690,\n24691,0,0,0,0,0,0,0,24697,0,24698,0,0,0,0,0,0,0,0,24709,0,0,0,0,0,24710,0,24712,\n0,0,0,0,0,0,24713,24714,0,24715,0,24716,24718,0,24719,0,0,0,0,24720,0,0,24725,0,\n0,24738,0,24749,24750,0,0,0,24752,0,0,0,24753,0,0,0,24758,0,0,0,0,0,24762,0,\n24763,0,0,0,0,0,0,0,24764,0,0,0,0,0,24765,24767,24768,0,24772,0,0,0,0,24773,0,0,\n0,0,24777,0,0,0,0,0,24785,0,24786,24788,0,0,0,24789,0,0,0,0,24794,24798,0,24799,\n24800,0,0,0,24803,0,24804,24806,0,24807,0,0,0,24810,0,0,0,0,0,0,24827,24828,0,\n24835,0,0,0,0,0,0,24836,0,0,0,0,0,24839,0,24843,24844,0,0,0,0,0,0,0,0,0,0,24847,\n0,0,24848,0,0,0,0,0,0,24849,0,24850,24851,0,0,0,24852,0,24853,0,0,0,0,0,0,0,0,0,\n24854,0,24855,0,0,24868,0,0,0,24883,0,0,0,24884,0,24895,24897,0,0,0,0,0,24899,0,\n0,0,0,0,24900,0,24913,0,0,0,0,0,0,24914,0,0,24917,24930,24931,0,0,0,24932,0,0,\n24939,0,0,24942,0,0,0,0,0,0,0,0,0,24945,24950,0,24951,0,0,24953,0,0,0,24954,0,\n24959,0,0,0,24961,0,0,24962,0,24964,24968,24970,24972,0,0,0,0,0,24976,0,0,0,\n24977,0,24982,0,0,24983,0,0,24984,0,0,0,24993,0,0,0,24994,0,0,25001,0,0,0,25003,\n0,0,25018,0,0,25023,0,0,0,25034,0,0,25035,25036,0,25037,0,0,0,0,0,0,0,25039,0,0,\n0,0,0,25040,0,0,0,0,0,0,0,25042,0,0,25043,25045,0,0,0,0,0,0,25049,0,0,25051,0,\n25052,25053,0,0,25054,0,0,0,25055,0,0,0,0,25057,25059,0,0,25060,25064,0,25065,\n25069,25070,0,0,0,0,25072,0,25073,0,25090,0,0,25092,25093,25101,0,0,0,0,0,0,\n25105,25108,0,0,25113,0,0,25115,25116,0,0,0,0,0,0,25117,0,0,0,25120,25121,0,0,0,\n0,0,0,0,25125,0,0,0,25126,0,25130,25134,0,25139,0,25143,0,0,0,25151,0,25161,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25163,0,0,0,0,0,0,0,25174,0,25175,0,25207,0,0,\n0,25209,0,0,0,0,25213,0,25219,0,25223,0,25225,0,0,0,25227,0,0,0,25228,0,0,0,\n25229,0,0,0,0,0,0,0,25231,25233,0,0,0,0,25237,25239,0,0,0,25243,0,0,0,25252,0,\n25257,25258,0,0,0,0,25260,25265,0,25268,0,0,25273,25324,0,25325,0,25326,0,0,0,0,\n0,0,0,0,25327,0,0,0,0,0,25328,0,0,0,0,0,0,25332,0,0,0,25333,0,0,0,25336,25337,\n25338,0,0,25343,0,25350,0,0,0,0,0,0,0,25352,0,25354,0,25375,0,25379,0,0,0,0,\n25384,0,0,0,0,0,0,0,0,0,25386,0,25388,0,25390,0,0,25399,0,0,25401,0,0,0,25402,0,\n0,0,25407,0,0,0,0,0,0,0,0,0,0,0,25413,25415,0,0,25417,0,0,0,0,0,0,0,25419,0,0,0,\n25421,0,0,0,25424,0,0,0,0,25433,0,0,0,0,0,0,0,0,0,25435,0,0,0,0,0,0,25436,0,0,0,\n25437,0,0,25440,0,0,0,0,0,0,25442,0,0,25443,0,25446,0,0,25449,0,0,0,25450,0,0,0,\n0,25452,0,25453,25454,25455,0,0,0,25456,0,25457,0,0,0,25459,0,25461,0,25468,0,0,\n0,0,0,0,0,0,25469,0,0,0,0,0,25471,0,0,0,0,0,25474,0,0,0,0,0,0,0,0,25475,0,0,0,0,\n25477,0,0,0,0,25483,0,0,0,0,0,25484,0,0,0,0,0,0,0,0,0,0,0,0,25485,0,25497,0,0,\n25498,0,25504,0,25510,0,25512,0,0,25513,25514,0,0,0,0,0,0,25517,25518,25519,0,\n25520,0,0,0,0,0,0,0,25521,0,25522,25527,25534,0,25536,0,25537,0,0,25548,25550,0,\n0,25551,0,25552,0,0,0,0,0,25554,0,25555,0,25556,25557,25568,0,0,0,25570,25571,0,\n0,0,0,0,0,25574,0,0,0,0,25579,0,0,0,25581,0,0,0,25582,0,0,0,0,0,0,0,0,0,25588,0,\n0,0,0,25589,0,0,0,0,25590,0,25591,25592,25593,0,25594,0,0,0,25596,0,25597,25615,\n0,0,0,0,0,25618,0,0,0,0,25619,25623,0,0,25629,0,0,25631,0,0,0,25635,25636,0,0,\n25649,0,0,0,0,25654,0,0,0,25661,25663,0,0,25671,0,0,25678,25698,0,25699,25702,\n25703,0,0,0,0,0,0,0,0,25704,0,0,0,0,0,25706,0,0,25710,0,25711,0,25712,0,25715,\n25716,25717,0,0,25718,25728,25732,0,0,0,25734,0,0,0,0,0,0,0,0,0,25737,0,0,25739,\n0,0,0,25740,0,25741,25745,0,25746,0,25748,25772,25778,0,0,0,0,0,25780,0,0,0,0,\n25781,0,25782,25784,25785,0,0,0,25789,0,0,0,0,0,0,25797,25801,0,0,0,25808,25809,\n0,0,25811,25814,25815,0,0,25817,0,0,0,0,0,0,0,0,25820,0,0,0,0,25832,25833,0,0,0,\n25846,0,0,0,25847,25848,0,0,0,0,0,0,0,0,0,25849,25850,0,0,25851,0,0,25852,0,\n25862,0,0,0,25863,25865,0,0,0,0,0,0,0,25867,25868,0,25869,25874,0,25875,0,25876,\n25877,0,0,0,0,25878,25902,0,0,0,0,0,0,0,25903,25904,25905,0,0,0,25908,25909,0,0,\n0,0,25910,0,0,0,0,0,0,0,25912,0,25913,0,0,0,0,0,0,0,0,25914,0,0,25916,0,0,0,0,0,\n25917,25927,0,0,0,0,25928,0,0,25930,0,0,0,25933,0,0,25938,25942,0,0,0,0,0,0,0,\n25945,0,25950,0,25956,0,0,25961,25962,0,0,25963,0,25964,25965,25966,0,0,0,0,0,\n25967,0,0,0,0,25968,0,0,0,25969,25971,0,0,0,0,0,25973,25975,0,0,0,0,0,0,0,25978,\n0,25981,0,0,0,25982,0,0,0,25984,0,0,0,0,0,0,0,25993,0,0,0,0,0,0,0,0,0,0,0,0,0,\n26002,0,0,0,26005,0,0,0,26006,26007,0,0,26014,26015,26016,0,0,0,0,0,0,26017,\n26018,26020,0,26022,26023,0,0,0,26024,26028,0,26029,26033,26034,26044,0,0,0,0,0,\n26046,0,0,26047,0,0,26049,0,26050,0,26051,0,0,0,0,0,26053,0,0,0,0,26054,26059,0,\n0,0,0,0,0,26060,0,26066,0,0,0,0,0,0,0,0,0,0,0,0,26067,0,26069,0,0,26071,0,0,0,\n26073,0,26074,26077,0,0,0,0,26078,0,0,0,26079,0,26090,0,0,26094,0,0,0,0,0,0,0,0,\n26095,0,0,0,0,0,0,0,0,0,0,0,26096,26101,0,26107,26122,0,26124,0,0,26125,0,0,0,0,\n0,0,26136,26141,26155,0,0,0,0,0,0,0,0,0,26164,26166,0,0,0,26167,0,26170,26171,0,\n0,26172,0,0,26174,0,0,0,0,0,0,0,0,0,0,0,0,0,26175,0,0,0,26176,26177,0,26321,\n26322,0,26323,0,0,26324,0,0,0,0,0,0,0,26325,0,26331,0,0,0,0,0,0,26335,0,0,0,\n26350,0,0,0,26379,0,0,26382,26383,26385,0,0,26392,26406,0,0,0,0,26411,0,0,0,0,0,\n26412,0,0,26420,0,0,26423,0,26424,26426,26432,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n26435,0,26436,0,0,0,0,0,26441,0,26444,0,0,0,26446,0,0,0,0,26447,0,0,0,0,26449,0,\n26450,26452,0,26453,26454,0,0,0,26455,0,0,0,26456,0,0,26458,0,0,26460,0,26463,0,\n0,0,0,0,0,0,0,26464,26470,0,0,0,0,0,0,0,0,0,26473,0,0,26474,0,0,0,0,0,0,0,26475,\n0,0,0,0,0,0,0,26477,0,26485,0,0,26486,0,26487,0,0,26488,26493,26494,0,0,26495,0,\n26497,26504,26506,0,0,0,0,0,26507,0,0,0,0,0,26509,0,0,26510,0,0,0,0,0,0,0,0,0,0,\n0,0,0,26512,0,26513,26515,0,0,0,26518,0,0,0,26519,0,26524,26526,0,0,0,26527,0,\n26532,0,26533,26537,26558,0,0,0,26559,0,0,0,26571,0,0,26573,0,26588,0,26593,0,0,\n0,0,0,0,26603,0,26604,0,0,0,0,0,0,0,0,0,0,26606,0,0,0,0,0,0,0,26607,26609,26611,\n26614,0,0,0,26616,26620,0,26621,0,0,0,0,0,26627,0,26629,0,0,26630,0,0,26632,\n26643,0,0,0,26644,0,0,0,0,0,0,0,0,0,26646,26647,0,0,0,26650,0,0,26656,0,0,0,0,\n26663,26670,26671,0,0,0,26685,26686,26687,0,26689,0,0,0,0,26744,0,26745,0,26747,\n26748,0,26749,26750,26751,0,0,0,0,26752,26755,0,0,0,26756,26769,0,0,0,26774,0,0,\n0,0,0,26775,0,26777,26778,0,26786,0,0,0,26787,0,0,0,0,0,0,0,0,0,0,0,0,0,26788,0,\n0,26789,0,0,0,0,0,26791,0,26792,26793,0,0,0,26794,0,26797,26798,0,0,0,26800,0,0,\n26803,0,26804,0,0,0,0,0,0,0,0,0,26805,0,0,26808,0,0,26809,0,0,0,0,0,0,0,26812,0,\n26825,0,0,0,0,0,0,0,26826,0,0,26827,26829,26834,0,0,0,0,26835,0,0,26849,0,26851,\n0,0,0,0,0,0,0,0,0,26852,0,26853,26857,0,26858,0,26859,0,0,0,0,0,0,0,26876,0,\n26878,26882,26883,0,0,0,0,26890,26894,0,0,0,0,26895,26896,0,0,0,0,0,26900,0,0,0,\n0,0,0,0,26911,26913,26914,26915,26916,26919,0,0,0,26921,26922,0,0,26925,0,0,0,\n26928,0,0,26929,26930,0,0,0,26931,0,26932,0,0,0,0,0,26933,0,0,0,0,0,0,26937,0,0,\n26943,0,0,26944,0,0,0,26946,0,0,0,0,0,0,0,26956,0,26958,0,0,26963,0,0,0,0,0,0,0,\n26965,0,26969,26970,26972,0,0,0,0,0,26973,0,26974,0,26978,0,26980,0,0,0,0,0,0,\n26982,0,26986,26987,0,26990,0,0,0,0,27003,27006,0,0,27007,27010,27012,27013,0,0,\n0,0,0,0,0,0,27014,27015,27018,0,27019,0,0,0,0,0,27025,0,0,0,27026,0,0,0,0,27029,\n27030,27031,27034,0,0,27036,27037,0,0,0,27038,27042,0,0,0,27044,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,27045,0,0,0,0,0,0,0,27046,0,0,0,0,0,0,0,27047,27049,0,27050,0,0,0,\n27051,27052,0,27055,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27056,27058,27059,0,\n27061,0,27064,0,0,0,0,0,27069,0,0,27070,0,0,0,0,0,0,0,27072,0,0,0,0,0,0,0,0,\n27076,0,0,0,0,0,27078,0,27079,0,0,0,27081,0,0,0,0,0,0,27082,0,27083,27086,0,0,0,\n0,27087,0,0,0,0,0,27088,27090,0,27094,0,0,27095,0,27099,27102,0,0,0,27103,0,0,0,\n0,27105,0,0,0,27106,0,0,0,0,0,0,27107,0,0,0,0,27108,27117,0,0,0,0,27118,0,0,\n27124,0,27126,0,0,27130,27131,0,0,0,0,0,0,27147,0,0,0,0,27148,27149,0,0,0,0,\n27150,27151,0,27152,0,27159,0,0,0,27164,0,0,0,0,0,0,0,27175,0,27189,0,0,27191,0,\n27193,0,27195,0,27198,0,0,0,0,0,27200,0,0,0,0,27202,0,0,0,0,27203,0,0,27204,0,0,\n27206,0,27207,0,0,0,0,27209,0,0,0,27213,0,0,27216,27219,27220,27222,27223,0,\n27224,0,27225,27226,0,0,27233,0,0,0,0,27235,0,27237,0,27238,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,27239,0,27242,27243,0,27250,0,0,0,27251,0,27253,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,27254,27255,27258,0,0,0,27259,0,0,0,0,0,0,27267,0,27276,27278,\n0,0,0,0,0,0,0,0,0,27296,27297,27301,0,0,0,0,0,0,27302,0,0,0,0,0,0,27312,27313,0,\n0,0,0,0,27318,0,27320,0,27329,0,27330,27331,0,27332,0,0,0,0,27340,0,0,0,27348,0,\n0,0,0,0,0,27350,0,27351,0,0,0,0,27355,0,0,27358,27359,27361,0,0,0,27365,0,27367,\n0,27376,27378,0,0,27379,0,0,0,0,0,0,27396,0,27397,27404,0,0,0,0,0,27408,0,0,0,0,\n27453,0,0,0,27456,0,0,0,27458,0,0,0,0,0,0,0,27459,0,0,0,27460,0,0,27461,0,27465,\n27467,0,0,27469,0,27470,0,27471,0,27477,27482,0,0,0,0,0,0,27484,0,0,0,0,0,0,\n27485,0,0,0,0,0,27493,0,27494,27502,0,0,0,0,0,0,0,0,0,0,0,0,27511,27532,0,0,0,\n27533,27545,0,0,0,27546,0,0,0,0,0,0,0,0,0,0,27547,0,0,27549,27550,0,27551,0,0,0,\n0,0,0,0,27555,0,0,27571,0,27573,27574,27575,27577,0,27578,0,0,27579,27585,0,0,0,\n0,0,27586,0,0,27588,27589,0,0,0,0,27596,0,0,27600,0,0,0,0,0,0,0,0,0,0,0,27608,0,\n0,0,0,0,0,0,0,0,0,0,27610,0,0,0,27618,0,0,27620,0,0,0,27631,0,0,27632,27634,0,\n27636,27638,0,0,0,27643,0,27644,27649,0,0,0,0,0,0,0,0,0,0,0,0,0,27651,27660,0,\n27661,0,0,0,0,0,0,0,27662,0,0,27664,0,27665,0,0,0,27669,0,27671,0,0,0,27673,\n27674,0,0,0,27682,0,0,0,27711,0,27712,27713,27719,27720,0,0,27728,0,27729,0,0,0,\n0,0,0,0,0,0,27731,0,0,27732,0,27733,0,27738,0,0,0,27742,0,0,0,27743,27744,0,0,0,\n0,0,0,27745,27746,0,0,0,27747,27748,27751,27752,0,0,0,27768,27770,0,0,0,27774,\n27775,0,27776,27777,0,0,27781,0,27784,0,27786,0,0,27791,0,27792,27793,27804,0,\n27812,27813,0,0,0,0,0,0,0,0,27814,0,27825,0,27827,0,0,0,0,27828,27861,27862,0,0,\n0,27864,0,0,0,27865,27884,0,27889,0,0,0,0,0,27890,0,27891,0,0,0,27892,0,0,0,0,0,\n27897,27898,0,0,27899,0,0,0,27901,27905,0,0,27920,0,0,27921,0,27922,0,0,0,27931,\n27934,0,0,0,0,0,0,0,0,0,0,27941,0,27942,0,27945,0,27947,27954,0,0,0,0,27960,\n27963,0,0,0,0,0,0,0,0,27964,27965,0,0,0,27967,0,27969,27975,0,27976,27977,0,\n27981,0,27983,28051,28052,0,0,0,0,0,28056,0,0,0,0,0,0,28058,28059,0,0,28061,0,0,\n0,0,0,0,0,28063,0,0,0,0,0,0,28066,0,0,0,0,0,0,28069,28070,28072,0,28073,0,0,\n28074,0,0,0,0,28075,0,0,0,0,0,0,0,28078,0,0,0,0,28085,0,0,0,0,28086,0,0,0,0,0,0,\n28088,0,0,0,0,0,0,0,0,28090,0,28097,28114,28115,0,0,0,0,0,0,0,28116,0,0,0,0,0,\n28118,0,28129,0,28131,0,0,28135,0,0,0,28140,28141,0,0,0,28146,0,0,0,0,28152,0,0,\n0,0,28155,28157,28161,0,0,0,0,28166,0,28167,0,0,0,0,0,0,0,0,0,0,0,28172,0,0,0,0,\n0,0,28173,0,0,28175,0,0,0,0,0,0,0,0,0,28178,28188,0,28190,0,0,0,0,0,28191,0,\n28193,28206,0,0,28207,28209,0,28211,0,28213,0,0,0,28215,28216,28217,0,28222,0,\n28223,28225,0,0,0,28226,0,28227,28229,28232,0,0,0,0,0,0,0,0,0,28235,0,28241,0,0,\n28242,0,0,0,0,28243,0,0,0,28245,0,0,0,28248,28250,0,28251,28252,0,0,0,0,0,0,\n28253,0,0,28254,28255,0,0,28256,0,0,28258,0,0,0,0,0,28259,0,0,28260,0,0,28261,0,\n0,0,0,28262,28263,0,0,28264,0,0,0,28266,0,28268,28269,0,28270,28272,28274,0,\n28277,28278,0,0,0,28279,0,28280,28281,28283,0,28292,0,28294,0,28297,0,0,0,0,\n28299,0,0,0,0,0,28300,0,0,0,0,0,0,0,28301,0,0,0,0,0,0,0,0,0,0,0,0,0,28302,28303,\n0,0,0,0,28304,0,0,28305,0,28312,0,28313,28314,0,0,0,0,0,0,28315,0,0,0,28320,\n28321,0,0,28328,0,0,0,28329,28338,0,28339,0,0,28344,0,0,0,0,0,0,0,0,28347,0,0,0,\n0,0,0,0,0,28348,0,0,0,0,0,28411,0,28412,28413,0,28416,0,0,0,28420,0,0,0,0,0,\n28421,0,0,0,0,28423,0,0,0,28424,0,0,28428,0,0,0,0,0,28429,0,0,0,28431,28434,0,\n28458,0,0,0,0,0,0,0,0,0,0,0,28464,0,0,0,0,28465,0,28467,0,0,0,0,0,0,28471,0,0,0,\n0,28474,0,28480,0,28481,0,0,28485,0,0,0,0,28486,28488,0,0,28489,0,0,0,0,28492,0,\n0,0,28495,0,28497,0,28499,0,0,0,0,28500,0,0,28502,28503,0,0,0,28508,0,0,0,28510,\n0,0,28512,28513,28514,28521,0,28526,0,28527,28528,0,0,0,0,28529,0,0,28532,0,0,\n28537,28538,0,0,0,28539,0,28548,0,28553,28554,0,0,0,0,0,0,0,0,0,0,0,0,28560,\n28563,0,0,28564,0,0,0,0,28565,0,0,0,0,0,0,0,28566,28568,0,0,0,0,0,0,28569,0,0,0,\n28570,0,28572,28573,0,0,0,0,28575,0,0,0,0,28576,28581,28588,0,0,28589,0,0,0,\n28590,28595,0,28598,0,0,28601,0,0,28605,0,0,0,0,28614,28615,28619,0,0,0,0,0,0,\n28620,0,28626,0,0,28628,0,28631,0,28632,0,0,0,0,0,0,28635,0,0,0,28637,28638,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28639,0,28643,0,0,28652,0,0,0,28662,0,\n28670,28671,0,0,0,0,0,0,0,0,0,28672,28673,28675,28676,0,0,0,0,0,0,0,28691,0,0,0,\n28695,0,0,0,28696,0,28697,28698,0,28705,0,28707,28708,28710,0,0,0,0,0,0,0,28711,\n28728,0,0,0,28736,0,0,0,28737,0,0,0,0,0,0,0,0,0,28738,0,28739,0,28741,0,0,28742,\n0,0,0,0,0,0,0,0,0,0,0,28745,0,0,0,0,0,0,28749,28750,28752,28754,28756,0,28757,0,\n0,0,0,28759,28760,0,0,0,0,0,0,28762,0,0,0,28764,0,0,0,0,0,0,28766,0,28767,28768,\n0,0,0,0,28769,28770,0,0,0,0,0,0,0,0,0,0,0,0,0,28771,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,28772,0,28773,0,28782,0,0,0,0,0,0,28784,0,28785,0,28786,0,0,0,28787,0,0,0,\n28797,0,0,0,0,0,0,28799,0,0,28801,0,0,0,0,28802,0,28805,0,0,28806,0,0,28807,0,0,\n0,0,0,0,0,28808,0,0,0,0,0,28810,28812,0,0,28816,28819,0,0,28821,0,28826,0,0,0,\n28842,28852,0,0,28853,0,28854,28855,0,0,0,28857,0,0,0,28858,0,28867,28868,28869,\n0,0,0,28874,28880,28882,28890,28892,0,0,0,0,0,0,0,28895,0,0,0,28898,28899,0,0,0,\n28900,0,0,28904,0,28906,0,0,0,0,28907,0,0,0,0,0,0,28908,0,0,0,28910,0,28914,0,0,\n0,0,0,0,0,28915,28916,28919,0,0,28920,0,28921,0,0,0,0,0,0,0,0,28924,0,0,0,0,\n28926,28929,0,0,0,28930,0,28936,0,28939,0,0,0,0,28942,0,0,0,0,0,0,28956,0,0,0,\n28966,0,0,0,0,28967,0,0,0,0,0,0,0,0,0,28968,0,28971,0,28975,28976,0,28982,28983,\n0,0,28984,28989,28996,28997,28998,0,0,0,0,0,0,28999,0,0,0,0,0,29000,0,29001,0,0,\n0,29009,0,0,29011,0,0,29021,0,0,0,0,29024,0,29025,0,0,0,0,0,29026,0,0,0,29036,0,\n0,0,29037,0,0,0,0,29038,0,29045,0,29047,0,0,0,0,0,0,0,0,0,29051,0,0,0,29054,\n29056,29062,0,29070,29082,0,0,0,29083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29084,0,0,\n0,0,29085,29088,0,0,0,0,0,0,0,29090,29097,0,0,0,29103,0,0,0,0,0,0,0,0,29105,0,0,\n0,0,0,29107,0,29109,0,0,0,29115,0,0,29120,0,0,29138,29140,0,0,0,0,0,0,0,0,0,\n29152,0,29160,29174,0,29176,0,0,29180,0,29181,0,0,0,0,0,0,0,0,29228,0,0,29229,0,\n0,29230,0,0,0,0,0,0,0,0,0,0,29234,0,0,0,29241,0,29245,0,29248,0,29250,29256,\n29280,0,29282,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29285,0,0,29286,29291,29292,0,0,0,0,\n29294,0,29295,0,0,0,0,0,29296,29297,29298,29300,0,29302,0,0,29304,29307,0,29312,\n0,0,0,29322,0,0,29323,0,0,29324,29326,29328,0,29335,0,0,0,0,0,0,0,29338,29339,0,\n0,0,0,0,29341,29343,0,0,0,0,29344,0,0,0,0,0,29345,0,0,0,0,29346,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,29347,29348,29349,0,0,29354,0,0,29355,0,0,0,0,0,0,0,0,29357,0,0,\n0,0,29364,0,29365,0,0,0,0,0,0,0,29366,0,0,29368,0,0,0,0,0,0,0,0,29378,0,29381,0,\n0,0,0,0,0,0,0,29386,0,0,0,0,0,0,29389,0,0,0,29390,0,0,29391,29397,0,29398,29412,\n29414,29418,29419,0,0,0,0,0,0,0,29420,0,0,0,0,0,0,0,29423,0,0,0,29435,0,0,0,\n29437,0,0,29439,0,29441,0,0,0,0,29443,0,29446,29450,29452,0,0,0,0,0,29456,0,0,0,\n0,0,29461,0,0,0,29464,0,0,0,0,0,0,0,0,29468,0,29473,0,0,0,29486,0,0,0,29490,0,0,\n0,29491,29492,0,0,29497,0,0,0,29498,0,29499,0,29502,29505,0,29509,0,0,0,29510,0,\n0,0,29512,0,0,0,29516,0,0,0,0,0,0,0,0,29518,0,29519,0,0,0,0,0,29520,29521,29529,\n0,0,0,0,0,0,0,0,29530,0,0,29531,29538,0,29540,0,0,0,29542,0,29543,29544,29547,0,\n0,29548,0,0,0,29549,0,0,0,29550,0,0,29552,0,0,0,0,29558,29561,0,29562,29564,0,0,\n29565,0,0,29566,0,0,0,0,0,0,0,0,0,0,29578,29584,29586,29591,0,0,0,0,29593,29594,\n0,0,29597,0,0,29613,0,29614,0,29615,0,0,0,0,29616,29617,0,0,29625,0,0,0,29632,0,\n0,0,0,0,0,0,29633,0,0,0,0,0,29634,29635,29637,0,29638,0,29641,29643,0,0,0,0,0,0,\n29644,0,29645,0,29649,0,0,0,29650,0,29653,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29656,\n29659,0,0,29660,0,0,0,29661,0,0,0,0,0,29664,0,0,0,29671,29673,0,0,0,0,0,0,0,\n29675,0,29677,29679,0,0,29684,0,0,0,0,0,29685,0,0,0,29687,0,0,0,29688,0,29689,\n29690,29700,0,29701,0,0,0,29702,0,29706,0,0,0,0,0,0,0,29720,0,29721,0,29727,0,\n29733,29734,0,29750,29761,0,29763,0,0,0,0,0,29764,0,0,29765,0,0,0,29771,0,0,0,0,\n0,0,0,0,0,0,0,0,29772,0,0,0,29773,29774,29775,0,0,0,0,0,0,0,0,0,0,0,29822,0,0,0,\n29824,0,29825,0,0,0,0,0,29827,0,0,0,0,0,0,0,0,29829,0,29832,29834,0,0,29835,0,0,\n29837,29838,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29843,0,0,0,0,29844,29845,0,0,0,\n0,0,0,0,0,0,29849,0,0,29869,29872,29890,29905,0,0,0,0,0,29907,29921,0,29922,0,0,\n29923,29926,29944,29946,0,0,0,0,0,0,0,29947,29948,0,0,0,29951,0,0,0,0,0,29953,0,\n0,29956,0,29957,0,0,29962,0,0,0,0,29971,0,0,0,29972,0,0,0,0,0,29978,0,29979,\n29992,30007,30008,30010,0,0,0,30013,0,0,0,0,30014,30016,0,0,0,0,0,0,0,0,0,0,0,\n30017,0,0,0,0,0,30023,30031,0,0,30033,0,0,0,0,0,0,0,0,0,0,30034,0,30038,0,30039,\n0,30040,0,0,0,0,0,0,30067,30068,0,0,0,30069,0,30072,0,0,0,30073,0,0,0,0,30075,0,\n0,0,0,0,0,30079,0,0,30080,0,0,0,0,0,30082,0,0,0,0,0,0,0,0,0,0,0,30084,30090,0,0,\n30091,0,0,0,0,30098,30118,0,30119,0,30121,30130,0,0,0,0,0,0,0,0,0,0,0,0,0,30131,\n30132,30133,0,0,0,0,0,0,30135,0,0,0,0,0,0,0,0,0,0,0,30136,0,0,30137,30138,0,0,0,\n30139,30146,0,0,0,0,0,30147,0,0,30148,30151,0,0,0,30168,0,30172,30173,0,0,0,0,0,\n0,0,0,30180,30181,0,30192,0,0,0,0,0,0,0,30194,30196,0,0,30199,0,0,30202,0,0,0,0,\n30203,0,0,0,0,0,0,0,0,0,0,30213,0,0,0,30216,0,0,30217,0,0,0,30218,0,0,0,0,30219,\n0,30220,0,30222,30227,0,0,0,0,0,30231,0,0,30233,30235,0,0,0,0,30238,0,30240,\n30243,30245,0,30250,30252,0,0,0,30269,0,0,30271,30272,0,0,0,30278,30280,0,0,\n30282,0,30284,0,30294,0,0,0,0,30295,30296,0,0,0,0,0,30298,30299,30302,30304,\n30306,0,0,0,0,0,0,30316,30317,0,0,0,30318,0,0,0,30319,0,30320,30322,30326,0,0,0,\n0,0,30327,0,30332,30348,30349,0,0,30356,0,0,0,0,0,0,0,0,30357,0,30358,0,30359,\n30360,0,0,30365,30366,30378,0,0,0,0,30379,0,0,30381,0,30385,0,30388,30397,0,0,0,\n30401,0,0,0,0,30403,0,0,0,0,0,30404,0,0,30405,0,30406,30408,0,30409,0,30410,0,0,\n0,30417,0,0,30418,30419,0,30420,0,30424,0,0,0,30427,30430,30432,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,30433,0,0,0,0,0,0,0,30436,0,30437,30438,0,30441,30442,0,0,\n0,30445,0,0,0,0,30452,30456,30457,0,0,0,30458,0,30464,0,0,0,0,0,0,30467,0,30469,\n0,0,0,0,0,30477,0,0,30484,0,0,0,0,0,30485,0,0,0,0,0,30486,30487,30497,30498,0,0,\n0,0,0,0,0,0,0,0,30505,0,30508,0,0,0,30509,30510,0,30514,30516,0,0,0,0,0,0,0,0,0,\n0,0,30523,0,30524,0,30525,0,0,0,0,30537,0,0,30538,0,0,0,0,0,30553,0,0,30555,\n30556,30558,30559,30560,0,0,30561,0,30562,0,0,0,0,0,0,0,0,30563,30570,30571,0,\n30586,30587,0,0,30590,0,0,30594,0,0,0,0,30611,30612,30623,30634,0,0,30636,30640,\n30655,30656,0,30657,0,0,30658,30669,0,30670,0,30676,30678,0,0,0,0,0,0,0,30679,0,\n0,0,0,0,0,0,0,0,0,0,30695,0,0,30698,0,0,0,0,30700,0,0,0,0,30701,0,30702,30703,0,\n0,0,0,30707,0,0,0,30709,0,0,30710,30719,30729,0,0,0,0,0,0,0,0,0,30731,0,0,30733,\n0,0,0,30734,0,0,0,0,0,30736,30737,0,0,0,30740,0,0,0,30743,0,30746,0,30747,30748,\n0,0,30751,30752,30753,0,0,0,30754,0,0,30760,0,0,0,0,0,0,0,30763,0,30764,0,0,\n30766,0,30769,30770,30771,30774,30777,0,0,30779,30780,30781,0,0,0,0,30790,0,0,0,\n30792,0,0,0,0,30810,0,0,0,0,0,0,0,30812,30819,0,0,30823,30824,0,30825,0,30827,0,\n0,0,0,0,0,30828,0,0,30830,0,0,0,30834,0,30835,0,30837,30838,0,30845,0,0,0,0,0,\n30846,30847,0,0,30849,0,30851,0,0,0,0,0,30852,30858,0,0,30859,0,30865,0,0,30866,\n0,0,30868,0,0,30869,0,0,0,30881,30883,0,0,0,0,0,30889,0,30891,0,0,0,0,30894,0,\n30895,0,30897,0,30898,0,0,0,30904,30906,0,30909,0,0,0,0,0,0,30910,0,0,0,30915,\n30933,30942,0,0,0,0,30943,0,0,30945,0,0,0,0,0,0,30946,0,0,30947,0,0,30955,30956,\n0,0,30960,0,0,30961,30962,30966,0,0,30969,30974,0,0,0,30976,0,0,30977,0,30978,\n30982,0,0,0,0,0,0,0,30994,30995,30998,0,31000,0,0,31001,0,0,31003,31005,0,0,\n31006,31011,0,0,31014,0,31016,0,0,0,0,31018,0,0,31020,31023,31024,31025,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,31027,31028,31029,0,0,0,0,0,0,31032,0,0,0,0,0,0,0,0,0,0,0,\n31036,31037,31038,0,0,0,31041,31043,31045,0,31047,0,0,0,31048,0,31049,0,0,0,\n31053,31054,31055,0,0,31063,0,0,0,0,0,31066,0,31068,31071,0,0,0,31072,31073,0,0,\n0,0,31075,0,0,31076,0,0,0,31077,31079,0,31080,0,0,0,0,0,0,0,0,0,0,31087,0,31142,\n0,31144,0,0,31145,31146,31147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31149,0,31151,31152,0,\n0,0,0,0,0,0,31162,31171,31174,31175,0,0,0,31176,0,0,0,0,0,0,0,31179,0,0,0,31186,\n0,0,0,31192,31195,0,0,31196,0,0,0,0,0,0,0,0,31198,0,0,0,0,0,31199,0,0,0,31205,0,\n0,0,0,31211,31215,0,0,0,0,31231,0,31232,0,0,0,0,0,0,0,0,0,0,31233,31236,31253,0,\n31254,0,0,0,0,0,0,31255,0,0,31257,0,0,0,0,0,0,0,0,0,31258,31259,0,0,31260,0,\n31261,0,0,0,0,0,31262,31263,0,0,31264,0,31266,0,31267,0,0,0,0,0,31281,0,31282,0,\n31284,0,0,31285,31287,31288,0,0,31290,0,0,0,31292,31295,0,31299,0,31300,0,0,0,0,\n0,31302,0,0,0,0,31303,0,0,0,0,0,0,31304,0,0,0,0,0,31305,31308,31309,31315,0,\n31317,0,0,0,0,0,31323,0,31324,0,0,0,0,0,31325,31327,0,0,31331,0,0,0,0,0,31333,0,\n0,0,0,0,31336,0,0,31337,0,0,0,0,0,0,31338,0,0,0,0,0,0,0,0,0,0,0,0,31339,0,0,0,0,\n0,0,0,31342,0,0,0,0,31345,0,0,0,0,0,0,0,0,31347,0,0,0,0,0,0,31348,0,0,31350,\n31351,0,31352,0,0,31354,0,0,0,0,31355,0,0,31356,0,0,0,0,0,0,0,0,0,0,31363,0,\n31372,0,0,31373,0,0,0,0,0,0,0,0,0,31376,0,31388,0,31389,0,31392,0,31401,0,31405,\n31407,31408,0,31409,0,0,0,0,0,0,31413,31415,0,0,0,31416,31418,0,0,0,0,0,0,31422,\n31423,0,0,31424,0,31425,31432,0,0,0,0,0,0,0,0,0,31433,0,0,0,0,0,0,0,0,31434,0,0,\n0,0,0,0,31435,0,0,0,0,31438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31442,0,31444,0,\n31448,0,0,31451,0,0,0,0,31452,0,31461,31465,0,0,31466,0,0,31467,0,0,31468,0,0,0,\n31469,31473,0,31476,0,0,0,0,31489,31490,0,0,0,0,0,0,0,31492,31493,31494,0,0,0,0,\n31501,31504,31505,0,0,0,0,0,0,0,0,0,31509,0,0,0,0,31510,0,0,31511,0,0,31513,0,0,\n0,0,0,0,0,0,0,31514,0,31522,31536,31539,31540,0,31541,0,0,0,0,0,0,31546,31553,\n31559,0,0,0,31560,31561,31562,0,0,31564,31567,0,31569,0,0,0,31570,0,0,0,0,31571,\n0,0,0,0,0,0,31572,31574,31580,31581,0,0,31582,31584,31585,31586,31595,0,31596,0,\n0,0,0,31597,0,31599,0,31600,31601,0,0,31603,31604,0,0,31608,31610,0,0,0,31611,0,\n31615,0,0,0,0,31616,0,0,0,0,0,0,31617,0,0,0,0,0,31618,0,0,0,0,0,0,31621,0,0,0,0,\n0,0,0,0,0,31622,31625,0,0,0,0,31627,0,31641,0,0,31642,0,0,31643,0,0,0,0,0,0,0,0,\n0,31644,0,31646,0,0,0,0,31648,0,0,0,31652,0,0,0,31657,0,0,31676,0,0,0,0,0,0,0,\n31689,31691,31692,0,31694,0,0,0,31696,0,31702,0,31703,0};\n\nconst BROTLI_MODEL(\"small\")\nDictWord kStaticDictionaryWords[BROTLI_ENC_STATIC_DICT_LUT_NUM_ITEMS] = {\n{0,0,0},{8,0,1002},{136,0,1015},{4,0,683},{4,10,325},{138,10,125},{7,11,572},{9,\n11,592},{11,11,680},{11,11,842},{11,11,924},{12,11,356},{12,11,550},{13,11,317},\n{13,11,370},{13,11,469},{13,11,471},{14,11,397},{18,11,69},{146,11,145},{134,0,\n1265},{136,11,534},{134,0,1431},{11,0,138},{140,0,40},{4,0,155},{4,10,718},{7,0,\n1689},{135,10,1216},{4,0,245},{5,0,151},{5,0,741},{6,0,1147},{7,0,498},{7,0,870}\n,{7,0,1542},{12,0,213},{14,0,36},{14,0,391},{17,0,111},{18,0,6},{18,0,46},{18,0,\n151},{19,0,36},{20,0,32},{20,0,56},{20,0,69},{20,0,102},{21,0,4},{22,0,8},{22,0,\n10},{22,0,14},{150,0,31},{4,0,624},{135,0,1752},{5,10,124},{5,10,144},{6,10,548}\n,{7,10,15},{7,10,153},{137,10,629},{6,0,503},{7,10,1531},{8,10,416},{9,0,586},{9\n,10,275},{10,10,100},{11,10,658},{11,10,979},{12,10,86},{13,0,468},{14,0,66},{14\n,10,207},{15,10,20},{15,10,25},{144,0,58},{5,0,603},{5,10,915},{6,10,1783},{7,0,\n1212},{7,10,211},{7,10,1353},{9,0,565},{9,10,83},{10,10,376},{10,10,431},{11,10,\n543},{12,10,664},{13,10,280},{13,10,428},{14,0,301},{14,10,128},{17,10,52},{145,\n10,81},{4,0,492},{133,0,451},{135,0,835},{141,0,70},{132,0,539},{7,11,748},{139,\n11,700},{7,11,1517},{11,11,597},{14,11,76},{14,11,335},{148,11,33},{6,0,113},{\n135,0,436},{4,10,338},{133,10,400},{136,0,718},{133,11,127},{133,11,418},{6,0,\n1505},{6,11,198},{7,0,520},{11,10,892},{140,11,83},{4,10,221},{5,10,659},{5,10,\n989},{7,10,697},{7,10,1211},{138,10,284},{135,0,1070},{5,11,276},{6,11,55},{135,\n11,1369},{134,0,1515},{6,11,1752},{136,11,726},{138,10,507},{4,10,188},{7,10,805\n},{143,0,78},{5,10,884},{139,10,991},{133,11,764},{134,10,1653},{6,11,309},{7,11\n,331},{138,11,550},{135,11,1861},{132,11,348},{135,11,986},{135,11,1573},{12,0,\n610},{13,0,431},{144,0,59},{9,11,799},{140,10,166},{134,0,1530},{132,0,750},{132\n,0,307},{133,0,964},{6,11,194},{7,11,133},{10,11,493},{10,11,570},{139,11,664},{\n5,11,24},{5,11,569},{6,11,3},{6,11,119},{6,11,143},{6,11,440},{7,11,295},{7,11,\n599},{7,11,1686},{7,11,1854},{8,11,424},{9,11,43},{9,11,584},{9,11,760},{10,11,\n148},{10,11,328},{11,11,159},{11,11,253},{11,11,506},{12,11,487},{12,11,531},{\n144,11,33},{136,10,760},{5,11,14},{5,11,892},{6,11,283},{7,11,234},{136,11,537},\n{135,11,1251},{4,11,126},{8,11,635},{147,11,34},{4,11,316},{135,11,1561},{6,0,\n999},{6,0,1310},{137,11,861},{4,11,64},{5,11,352},{5,11,720},{6,11,368},{139,11,\n359},{4,0,75},{5,0,180},{6,0,500},{7,0,58},{7,0,710},{8,10,770},{138,0,645},{133\n,0,649},{6,0,276},{7,0,282},{7,0,879},{7,0,924},{8,0,459},{9,0,599},{9,0,754},{\n11,0,574},{12,0,128},{12,0,494},{13,0,52},{13,0,301},{15,0,30},{143,0,132},{132,\n0,200},{4,10,89},{5,10,489},{6,10,315},{7,10,553},{7,10,1745},{138,10,243},{135,\n11,1050},{6,10,1658},{7,0,1621},{9,10,3},{10,10,154},{11,10,641},{13,10,85},{13,\n10,201},{141,10,346},{6,11,175},{137,11,289},{5,11,432},{133,11,913},{6,0,225},{\n137,0,211},{7,0,718},{8,0,687},{139,0,374},{4,10,166},{133,10,505},{6,10,1670},{\n137,0,110},{8,0,58},{9,0,724},{11,0,809},{13,0,113},{145,0,72},{6,0,345},{7,0,\n1247},{144,11,82},{5,11,931},{134,11,1698},{8,0,767},{8,0,803},{9,0,301},{137,0,\n903},{139,0,203},{134,0,1154},{7,0,1949},{136,0,674},{134,0,259},{135,0,1275},{5\n,11,774},{6,11,1637},{6,11,1686},{134,11,1751},{134,0,1231},{7,10,445},{8,10,307\n},{8,10,704},{10,10,41},{10,10,439},{11,10,237},{11,10,622},{140,10,201},{136,0,\n254},{6,11,260},{135,11,1484},{139,0,277},{135,10,1977},{4,10,189},{5,10,713},{6\n,11,573},{136,10,57},{138,10,371},{132,10,552},{134,11,344},{133,0,248},{6,11,\n240},{9,0,800},{10,0,693},{11,0,482},{11,0,734},{139,0,789},{4,0,116},{4,11,292}\n,{4,11,736},{5,0,95},{5,0,445},{5,11,871},{6,11,171},{6,11,1689},{7,0,1688},{7,\n11,1324},{7,11,1944},{8,0,29},{9,0,272},{9,11,415},{9,11,580},{11,0,509},{11,0,\n915},{14,11,230},{146,11,68},{7,0,490},{13,0,100},{143,0,75},{135,0,1641},{133,0\n,543},{7,11,209},{8,11,661},{10,11,42},{11,11,58},{12,11,58},{12,11,118},{141,11\n,32},{5,0,181},{6,11,63},{7,11,920},{136,0,41},{133,0,657},{133,11,793},{138,0,\n709},{7,0,25},{8,0,202},{138,0,536},{5,11,665},{135,10,1788},{145,10,49},{9,0,\n423},{140,0,89},{5,11,67},{6,11,62},{6,11,374},{135,11,1391},{8,0,113},{9,0,877}\n,{9,11,790},{10,0,554},{11,0,83},{12,0,136},{12,11,47},{147,0,109},{138,10,661},\n{4,0,963},{7,10,1945},{10,0,927},{142,0,442},{133,0,976},{132,0,206},{4,11,391},\n{135,11,1169},{134,0,2002},{6,0,696},{134,0,1008},{134,0,1170},{132,11,271},{7,0\n,13},{8,0,226},{10,0,537},{11,0,570},{11,0,605},{11,0,799},{11,0,804},{12,0,85},\n{12,0,516},{12,0,623},{12,11,314},{13,0,112},{13,0,361},{14,0,77},{14,0,78},{17,\n0,28},{147,0,110},{132,0,769},{134,0,1544},{4,0,551},{137,0,678},{5,10,84},{134,\n10,163},{9,0,57},{9,0,459},{10,0,425},{11,0,119},{12,0,184},{12,0,371},{13,0,358\n},{145,0,51},{4,11,253},{5,0,188},{5,0,814},{5,10,410},{5,11,544},{7,11,300},{8,\n0,10},{9,0,421},{9,0,729},{9,11,340},{10,0,609},{139,0,689},{134,0,624},{138,11,\n321},{135,0,1941},{5,10,322},{8,10,186},{9,10,262},{10,10,187},{14,10,208},{146,\n0,130},{5,11,53},{5,11,541},{6,11,94},{6,11,499},{7,11,230},{139,11,321},{133,10\n,227},{4,0,378},{4,11,920},{5,11,25},{5,11,790},{6,11,457},{135,11,853},{137,0,\n269},{132,0,528},{134,0,1146},{7,10,1395},{8,10,486},{9,10,236},{9,10,878},{10,\n10,218},{11,10,95},{19,10,17},{147,10,31},{7,10,2043},{8,10,672},{141,10,448},{\n134,0,1105},{134,0,1616},{134,11,1765},{140,11,163},{5,10,412},{133,11,822},{132\n,11,634},{6,0,656},{134,11,1730},{134,0,1940},{5,0,104},{6,0,173},{135,0,1631},{\n136,10,562},{6,11,36},{7,11,658},{8,11,454},{147,11,86},{5,0,457},{134,10,1771},\n{7,0,810},{8,0,138},{8,0,342},{9,0,84},{10,0,193},{11,0,883},{140,0,359},{7,10,\n1190},{137,0,620},{137,10,132},{7,11,975},{137,11,789},{6,0,95},{6,0,1934},{136,\n0,967},{141,11,335},{6,0,406},{10,0,409},{10,0,447},{11,0,44},{140,0,100},{4,10,\n317},{135,10,1279},{132,0,477},{134,0,1268},{5,10,63},{5,10,509},{6,0,1941},{136\n,0,944},{132,0,629},{132,11,104},{4,0,246},{133,0,375},{4,10,288},{134,0,1636},{\n135,11,1614},{8,10,89},{8,10,620},{9,0,49},{10,0,774},{11,10,628},{12,10,322},{\n143,10,124},{4,0,282},{7,0,1034},{11,0,398},{11,0,634},{12,0,1},{12,0,79},{12,0,\n544},{14,0,237},{17,0,10},{146,0,20},{132,0,824},{7,11,45},{9,11,542},{9,11,566}\n,{138,11,728},{5,0,118},{5,0,499},{6,0,476},{6,0,665},{6,0,1176},{6,0,1196},{7,0\n,600},{7,0,888},{135,0,1096},{7,0,296},{7,0,596},{8,0,560},{8,0,586},{9,0,612},{\n11,0,304},{12,0,46},{13,0,89},{14,0,112},{145,0,122},{5,0,894},{6,0,1772},{9,0,\n1009},{138,10,120},{5,11,533},{7,11,755},{138,11,780},{151,10,1},{6,0,1474},{7,\n11,87},{142,11,288},{139,0,366},{137,10,461},{7,11,988},{7,11,1939},{9,11,64},{9\n,11,502},{12,11,7},{12,11,34},{13,11,12},{13,11,234},{147,11,77},{7,0,1599},{7,0\n,1723},{8,0,79},{8,0,106},{8,0,190},{8,0,302},{8,0,383},{8,0,713},{9,0,119},{9,0\n,233},{9,0,419},{9,0,471},{10,0,181},{10,0,406},{11,0,57},{11,0,85},{11,0,120},{\n11,0,177},{11,0,296},{11,0,382},{11,0,454},{11,0,758},{11,0,999},{12,0,27},{12,0\n,98},{12,0,131},{12,0,245},{12,0,312},{12,0,446},{12,0,454},{13,0,25},{13,0,98},\n{13,0,426},{13,0,508},{14,0,70},{14,0,163},{14,0,272},{14,0,277},{14,0,370},{15,\n0,95},{15,0,138},{15,0,167},{17,0,38},{148,0,96},{135,10,1346},{10,0,200},{19,0,\n2},{151,0,22},{135,11,141},{134,10,85},{134,0,1759},{138,0,372},{145,0,16},{4,11\n,619},{136,0,943},{139,11,88},{5,11,246},{8,11,189},{9,11,355},{9,11,512},{10,11\n,124},{10,11,453},{11,11,143},{11,11,416},{11,11,859},{141,11,341},{5,0,258},{\n134,0,719},{6,0,1798},{6,0,1839},{8,0,900},{10,0,874},{10,0,886},{12,0,698},{12,\n0,732},{12,0,770},{16,0,106},{18,0,163},{18,0,170},{18,0,171},{152,0,20},{9,0,\n707},{9,11,707},{11,0,326},{11,0,339},{11,11,326},{11,11,339},{12,0,423},{12,0,\n502},{12,11,423},{12,11,502},{20,0,62},{148,11,62},{5,0,30},{7,0,495},{8,0,134},\n{9,0,788},{140,0,438},{133,11,678},{5,10,279},{6,10,235},{7,10,468},{8,10,446},{\n9,10,637},{10,10,717},{11,10,738},{140,10,514},{5,11,35},{6,11,287},{7,11,862},{\n7,11,1886},{138,11,179},{4,11,517},{7,0,1948},{135,0,2004},{5,10,17},{6,10,371},\n{137,10,528},{4,0,115},{5,0,669},{6,0,407},{8,0,311},{11,0,10},{141,0,5},{137,0,\n381},{5,0,50},{6,0,439},{7,0,780},{135,0,1040},{136,11,667},{11,11,403},{146,11,\n83},{5,0,1},{6,0,81},{138,0,520},{134,0,738},{5,0,482},{8,0,98},{9,0,172},{10,0,\n360},{10,0,700},{10,0,822},{11,0,302},{11,0,778},{12,0,50},{12,0,127},{12,0,396}\n,{13,0,62},{13,0,328},{14,0,122},{147,0,72},{9,11,157},{10,11,131},{140,11,72},{\n135,11,714},{135,11,539},{5,0,2},{6,0,512},{7,0,797},{7,0,1494},{8,0,253},{8,0,\n589},{9,0,77},{10,0,1},{10,0,129},{10,0,225},{11,0,118},{11,0,226},{11,0,251},{\n11,0,430},{11,0,701},{11,0,974},{11,0,982},{12,0,64},{12,0,260},{12,0,488},{140,\n0,690},{5,11,394},{7,11,367},{7,11,487},{7,11,857},{7,11,1713},{8,11,246},{9,11,\n537},{10,11,165},{12,11,219},{140,11,561},{136,0,557},{5,10,779},{5,10,807},{6,\n10,1655},{134,10,1676},{4,10,196},{5,10,558},{133,10,949},{11,11,827},{12,11,56}\n,{14,11,34},{143,11,148},{137,0,347},{133,0,572},{134,0,832},{4,0,12},{7,0,504},\n{7,0,522},{7,0,809},{8,0,797},{141,0,88},{4,10,752},{133,11,449},{7,11,86},{8,11\n,103},{145,11,69},{7,11,2028},{138,11,641},{5,0,528},{6,11,1},{142,11,2},{134,0,\n861},{4,10,227},{5,10,159},{5,10,409},{7,10,80},{10,0,294},{10,10,479},{12,10,\n418},{14,10,50},{14,10,249},{142,10,295},{7,10,1470},{8,10,66},{8,10,137},{8,10,\n761},{9,10,638},{11,10,80},{11,10,212},{11,10,368},{11,10,418},{12,10,8},{13,10,\n15},{16,10,61},{17,10,59},{19,10,28},{148,10,84},{7,11,1148},{148,0,109},{6,11,\n277},{7,11,1274},{7,11,1386},{7,11,1392},{12,11,129},{146,11,87},{6,11,187},{7,\n11,39},{7,11,1203},{8,11,380},{8,11,542},{14,11,117},{149,11,28},{134,0,1187},{5\n,0,266},{9,0,290},{9,0,364},{10,0,293},{11,0,606},{142,0,45},{6,11,297},{7,11,\n793},{139,11,938},{4,0,50},{6,0,594},{9,0,121},{10,0,49},{10,0,412},{139,0,834},\n{136,0,748},{7,11,464},{8,11,438},{11,11,105},{11,11,363},{12,11,231},{14,11,386\n},{15,11,102},{148,11,75},{132,0,466},{6,10,38},{7,10,1220},{8,10,185},{8,10,256\n},{9,10,22},{9,10,331},{10,10,738},{11,10,205},{11,10,540},{11,10,746},{13,0,399\n},{13,10,465},{14,0,337},{142,10,194},{9,0,378},{141,0,162},{137,0,519},{4,10,\n159},{6,10,115},{7,10,252},{7,10,257},{7,10,1928},{8,10,69},{9,10,384},{10,10,91\n},{10,10,615},{12,10,375},{14,10,235},{18,10,117},{147,10,123},{5,10,911},{5,11,\n604},{136,10,278},{132,0,667},{4,10,151},{7,10,1567},{8,0,351},{137,0,322},{134,\n0,902},{133,10,990},{5,10,194},{7,10,1662},{9,10,90},{140,0,180},{4,0,869},{134,\n0,1996},{134,0,813},{133,10,425},{137,11,761},{132,0,260},{133,10,971},{5,11,20}\n,{6,11,298},{7,11,659},{7,11,1366},{137,11,219},{4,0,39},{5,0,36},{7,0,1843},{8,\n0,407},{11,0,144},{140,0,523},{4,0,510},{10,0,587},{139,10,752},{7,0,29},{7,0,66\n},{7,0,1980},{10,0,487},{138,0,809},{9,10,662},{13,0,260},{14,0,82},{146,0,63},{\n5,10,72},{6,10,264},{7,10,21},{7,10,46},{7,10,2013},{8,10,215},{8,10,513},{10,10\n,266},{139,10,22},{134,0,570},{4,11,439},{6,0,565},{7,0,1667},{10,10,95},{11,10,\n603},{12,11,242},{13,10,443},{14,10,160},{143,10,4},{134,0,1464},{134,10,431},{5\n,10,874},{6,10,1677},{9,0,372},{15,0,2},{15,10,0},{19,0,10},{147,0,18},{132,0,\n787},{6,0,380},{7,10,939},{7,10,1172},{7,10,1671},{9,10,540},{10,10,696},{11,10,\n265},{11,10,732},{11,10,928},{11,10,937},{12,0,399},{13,10,438},{149,0,19},{137,\n0,200},{132,11,233},{132,0,516},{134,11,577},{132,0,844},{11,0,887},{14,0,365},{\n142,0,375},{132,11,482},{8,0,821},{140,0,44},{7,0,1655},{136,0,305},{5,10,682},{\n135,10,1887},{135,11,346},{132,10,696},{4,0,10},{7,0,917},{139,0,786},{5,11,795}\n,{6,11,1741},{8,11,417},{137,11,782},{4,0,1016},{134,0,2031},{4,10,726},{5,0,684\n},{133,10,630},{6,0,1021},{134,0,1480},{8,10,802},{136,10,838},{134,0,27},{134,0\n,395},{135,11,622},{7,11,625},{135,11,1750},{4,11,203},{135,11,1936},{6,10,118},\n{7,10,215},{7,10,1521},{140,10,11},{132,0,813},{136,0,511},{7,10,615},{138,10,\n251},{135,10,1044},{145,0,56},{133,10,225},{6,0,342},{6,0,496},{8,0,275},{137,0,\n206},{4,0,909},{133,0,940},{132,0,891},{7,11,311},{9,11,308},{140,11,255},{4,10,\n370},{5,10,756},{135,10,1326},{4,0,687},{134,0,1596},{134,0,1342},{6,10,1662},{7\n,10,48},{8,10,771},{10,10,116},{13,10,104},{14,10,105},{14,10,184},{15,10,168},{\n19,10,92},{148,10,68},{138,10,209},{4,11,400},{5,11,267},{135,11,232},{151,11,12\n},{6,0,41},{141,0,160},{141,11,314},{134,0,1718},{136,0,778},{142,11,261},{134,0\n,1610},{133,0,115},{132,0,294},{4,10,120},{142,0,314},{132,0,983},{5,0,193},{140\n,0,178},{138,10,429},{5,10,820},{135,10,931},{5,11,732},{6,0,994},{6,0,1051},{6,\n0,1439},{135,0,174},{4,11,100},{7,11,679},{8,11,313},{138,10,199},{6,10,151},{6,\n10,1675},{7,10,383},{151,10,10},{6,0,1796},{8,0,848},{8,0,867},{8,0,907},{10,0,\n855},{140,0,703},{140,0,221},{4,0,122},{5,0,796},{5,0,952},{6,0,1660},{6,0,1671}\n,{8,0,567},{9,0,687},{9,0,742},{10,0,686},{11,0,682},{11,0,909},{140,0,281},{5,\n11,362},{5,11,443},{6,11,318},{7,11,1019},{139,11,623},{5,11,463},{136,11,296},{\n6,10,1624},{11,0,583},{12,10,422},{13,0,262},{142,10,360},{5,0,179},{7,0,1095},{\n135,0,1213},{4,10,43},{4,11,454},{5,10,344},{133,10,357},{4,0,66},{7,0,722},{135\n,0,904},{134,0,773},{5,10,888},{135,0,352},{5,11,48},{5,11,404},{6,11,557},{7,11\n,458},{8,11,597},{10,11,455},{10,11,606},{11,11,49},{11,11,548},{12,11,476},{13,\n11,18},{141,11,450},{134,11,418},{132,10,711},{5,11,442},{135,11,1984},{141,0,35\n},{137,0,152},{134,0,1197},{135,11,1093},{137,11,203},{137,10,440},{10,0,592},{\n10,0,753},{12,0,317},{12,0,355},{12,0,465},{12,0,469},{12,0,560},{12,0,578},{141\n,0,243},{133,0,564},{134,0,797},{5,10,958},{133,10,987},{5,11,55},{7,11,376},{\n140,11,161},{133,11,450},{134,0,556},{134,0,819},{11,10,276},{142,10,293},{7,0,\n544},{138,0,61},{4,10,65},{5,10,479},{5,10,1004},{7,10,1913},{8,0,719},{8,10,317\n},{9,10,302},{10,10,612},{141,10,22},{4,0,5},{4,10,261},{4,11,213},{5,0,498},{7,\n10,510},{7,11,223},{8,0,637},{8,11,80},{137,0,521},{4,10,291},{5,0,927},{7,0,101\n},{7,11,381},{7,11,806},{7,11,820},{8,11,354},{8,11,437},{8,11,787},{9,10,515},{\n9,11,657},{10,11,58},{10,11,339},{10,11,749},{11,11,914},{12,10,152},{12,10,443}\n,{12,11,162},{13,10,392},{13,11,75},{14,10,357},{14,11,106},{14,11,198},{14,11,\n320},{14,11,413},{146,11,43},{6,0,1153},{7,0,1441},{136,11,747},{4,0,893},{5,0,\n780},{133,0,893},{138,11,654},{133,11,692},{133,0,238},{134,11,191},{4,10,130},{\n135,10,843},{5,10,42},{5,10,879},{6,0,1296},{7,10,245},{7,10,324},{7,10,1532},{\n11,10,463},{11,10,472},{13,10,363},{144,10,52},{134,0,1729},{6,0,1999},{136,0,\n969},{4,10,134},{133,10,372},{4,0,60},{7,0,941},{7,0,1800},{8,0,314},{9,0,700},{\n139,0,487},{134,0,1144},{6,11,162},{7,11,1960},{136,11,831},{132,11,706},{135,0,\n1147},{138,11,426},{138,11,89},{7,0,1853},{138,0,437},{136,0,419},{135,10,1634},\n{133,0,828},{4,10,644},{5,0,806},{7,0,176},{7,0,178},{7,0,1240},{135,0,1976},{\n135,11,1877},{5,11,420},{135,11,1449},{4,0,51},{5,0,39},{6,0,4},{7,0,591},{7,0,\n849},{7,0,951},{7,0,1613},{7,0,1760},{7,0,1988},{9,0,434},{10,0,754},{11,0,25},{\n139,0,37},{10,11,57},{138,11,277},{135,10,540},{132,11,204},{135,0,159},{139,11,\n231},{133,0,902},{7,0,928},{7,11,366},{9,11,287},{12,11,199},{12,11,556},{140,11\n,577},{6,10,623},{136,10,789},{4,10,908},{5,10,359},{5,10,508},{6,10,1723},{7,10\n,343},{7,10,1996},{135,10,2026},{134,0,270},{4,10,341},{135,10,480},{5,11,356},{\n135,11,224},{11,11,588},{11,11,864},{11,11,968},{143,11,160},{132,0,556},{137,0,\n801},{132,0,416},{142,0,372},{5,0,152},{5,0,197},{7,0,340},{7,0,867},{10,0,548},\n{10,0,581},{11,0,6},{12,0,3},{12,0,19},{14,0,110},{142,0,289},{139,0,369},{7,11,\n630},{9,11,567},{11,11,150},{11,11,444},{141,11,119},{134,11,539},{7,10,1995},{8\n,10,299},{11,10,890},{140,10,674},{7,0,34},{7,0,190},{8,0,28},{8,0,141},{8,0,444\n},{8,0,811},{9,0,468},{11,0,334},{12,0,24},{12,0,386},{140,0,576},{133,0,757},{7\n,0,1553},{136,0,898},{133,0,721},{136,0,1012},{4,0,789},{5,0,647},{135,0,1102},{\n132,0,898},{4,10,238},{5,10,503},{6,10,179},{7,10,2003},{8,10,381},{8,10,473},{9\n,10,149},{10,0,183},{10,10,788},{15,10,45},{15,10,86},{20,10,110},{150,10,57},{4\n,10,121},{5,10,156},{5,10,349},{9,0,136},{10,10,605},{14,10,342},{147,0,107},{4,\n11,235},{135,11,255},{4,11,194},{5,11,584},{6,11,384},{7,11,583},{10,11,761},{11\n,11,760},{139,11,851},{6,10,80},{6,10,1694},{7,10,173},{7,10,1974},{9,10,547},{\n10,10,730},{14,10,18},{150,10,39},{4,10,923},{134,10,1711},{5,0,277},{141,0,247}\n,{132,0,435},{133,11,562},{134,0,1311},{5,11,191},{137,11,271},{132,10,595},{7,\n11,1537},{14,11,96},{143,11,73},{5,0,437},{6,10,459},{7,0,502},{7,0,519},{7,0,\n1122},{7,0,1751},{7,10,1753},{7,10,1805},{8,10,658},{9,10,1},{11,10,959},{13,10,\n446},{142,0,211},{4,11,470},{5,11,473},{6,0,814},{6,11,153},{7,11,1503},{7,11,\n1923},{10,11,701},{11,11,132},{11,11,168},{11,11,227},{11,11,320},{11,11,436},{\n11,11,525},{11,11,855},{12,11,41},{12,11,286},{13,11,103},{13,11,284},{14,11,255\n},{14,11,262},{15,11,117},{143,11,127},{5,0,265},{6,0,212},{135,0,28},{138,0,750\n},{133,11,327},{6,11,552},{7,11,1754},{137,11,604},{134,0,2012},{132,0,702},{5,\n11,80},{6,11,405},{7,11,403},{7,11,1502},{7,11,1626},{8,11,456},{9,11,487},{9,11\n,853},{9,11,889},{10,11,309},{11,11,721},{11,11,994},{12,11,430},{141,11,165},{5\n,0,808},{135,0,2045},{5,0,166},{8,0,739},{140,0,511},{134,10,490},{4,11,453},{5,\n11,887},{6,11,535},{8,11,6},{136,11,543},{4,0,119},{5,0,170},{5,0,447},{7,0,1708\n},{7,0,1889},{9,0,357},{9,0,719},{12,0,486},{140,0,596},{137,0,500},{7,10,250},{\n136,10,507},{132,10,158},{6,0,809},{134,0,1500},{4,10,140},{7,10,362},{8,10,209}\n,{9,0,327},{9,10,10},{9,10,503},{9,10,614},{10,10,689},{11,0,350},{11,0,831},{11\n,10,327},{11,10,725},{12,10,252},{12,10,583},{13,0,352},{13,10,192},{14,10,269},\n{14,10,356},{148,10,50},{135,11,741},{4,0,450},{7,0,1158},{19,10,1},{19,10,26},{\n150,10,9},{6,0,597},{135,0,1318},{134,0,1602},{6,10,228},{7,10,1341},{9,10,408},\n{138,10,343},{7,0,1375},{7,0,1466},{138,0,331},{132,0,754},{132,10,557},{5,11,\n101},{6,11,88},{6,11,543},{7,11,1677},{9,11,100},{10,11,677},{14,11,169},{14,11,\n302},{14,11,313},{15,11,48},{143,11,84},{134,0,1368},{4,11,310},{9,11,795},{10,\n11,733},{11,11,451},{12,11,249},{14,11,115},{14,11,286},{143,11,100},{132,10,548\n},{7,10,197},{8,10,142},{8,10,325},{9,10,150},{9,10,596},{10,0,557},{10,10,353},\n{11,10,74},{11,10,315},{12,10,662},{12,10,681},{14,10,423},{143,10,141},{133,11,\n587},{5,0,850},{136,0,799},{10,0,908},{12,0,701},{12,0,757},{142,0,466},{4,0,62}\n,{5,0,275},{6,10,399},{6,10,579},{7,10,692},{7,10,846},{7,10,1015},{7,10,1799},{\n8,10,403},{9,10,394},{10,10,133},{12,10,4},{12,10,297},{12,10,452},{16,10,81},{\n18,0,19},{18,10,25},{21,10,14},{22,10,12},{151,10,18},{7,10,1546},{11,10,299},{\n12,0,459},{142,10,407},{132,10,177},{132,11,498},{7,11,217},{8,11,140},{138,11,\n610},{5,10,411},{135,10,653},{134,0,1802},{7,10,439},{10,10,727},{11,10,260},{\n139,10,684},{133,11,905},{11,11,580},{142,11,201},{134,0,1397},{5,10,208},{7,10,\n753},{135,10,1528},{7,0,238},{7,0,2033},{8,0,120},{8,0,188},{8,0,659},{9,0,598},\n{10,0,466},{12,0,342},{12,0,588},{13,0,503},{14,0,246},{143,0,92},{135,11,1041},\n{4,11,456},{7,11,105},{7,11,358},{7,11,1637},{8,11,643},{139,11,483},{6,0,1318},\n{134,0,1324},{4,0,201},{5,10,242},{7,0,1744},{8,0,602},{11,0,247},{11,0,826},{\n145,0,65},{8,0,164},{146,0,62},{133,10,953},{139,10,802},{133,0,615},{7,11,1566}\n,{8,11,269},{9,11,212},{9,11,718},{14,11,15},{14,11,132},{142,11,227},{133,10,\n290},{132,10,380},{5,10,52},{7,10,277},{9,10,368},{139,10,791},{135,0,1243},{133\n,11,539},{11,11,919},{141,11,409},{136,0,968},{133,11,470},{134,0,882},{132,0,\n907},{5,0,100},{10,0,329},{12,0,416},{149,0,29},{10,10,138},{139,10,476},{5,10,\n725},{5,10,727},{6,11,91},{7,10,1811},{135,11,435},{4,11,16},{5,11,316},{5,11,\n842},{6,11,370},{6,11,1778},{8,11,166},{11,11,812},{12,11,206},{12,11,351},{14,\n11,418},{16,11,15},{16,11,34},{18,11,3},{19,11,3},{19,11,7},{20,11,4},{149,11,21\n},{132,0,176},{5,0,636},{5,0,998},{7,0,9},{7,0,1508},{8,0,26},{9,0,317},{9,0,358\n},{10,0,210},{10,0,292},{10,0,533},{11,0,555},{12,0,526},{12,0,607},{13,0,263},{\n13,0,459},{142,0,271},{4,10,38},{6,0,256},{7,10,307},{7,10,999},{7,10,1481},{7,\n10,1732},{7,10,1738},{8,0,265},{9,10,414},{11,10,316},{12,10,52},{13,10,420},{\n147,10,100},{135,10,1296},{4,11,611},{133,11,606},{4,0,643},{142,11,21},{133,11,\n715},{133,10,723},{6,0,610},{135,11,597},{10,0,127},{141,0,27},{6,0,1995},{6,0,\n2001},{8,0,119},{136,0,973},{4,11,149},{138,11,368},{4,11,154},{5,10,109},{6,10,\n1784},{7,10,1895},{7,11,1134},{8,11,105},{12,0,522},{12,10,296},{140,10,302},{4,\n11,31},{6,11,429},{7,11,962},{9,11,458},{139,11,691},{4,11,312},{5,10,216},{7,10\n,1879},{9,10,141},{9,10,270},{9,10,679},{10,0,553},{10,10,159},{11,0,876},{11,10\n,197},{12,10,538},{12,10,559},{13,0,193},{13,0,423},{14,0,166},{14,10,144},{14,\n10,167},{15,10,67},{147,0,84},{134,0,1582},{7,0,1578},{135,11,1578},{137,10,81},\n{132,11,236},{134,10,391},{134,0,795},{7,10,322},{136,10,249},{5,11,836},{5,11,\n857},{6,11,1680},{7,11,59},{147,11,53},{135,0,432},{10,11,68},{139,11,494},{4,11\n,81},{139,11,867},{7,0,126},{136,0,84},{142,11,280},{5,11,282},{8,11,650},{9,11,\n295},{9,11,907},{138,11,443},{136,0,790},{5,10,632},{138,10,526},{6,0,64},{12,0,\n377},{13,0,309},{14,0,141},{14,0,429},{14,11,141},{142,11,429},{134,0,1529},{6,0\n,321},{7,0,1857},{7,10,948},{7,10,1042},{8,10,235},{8,10,461},{9,0,530},{9,10,\n453},{10,10,354},{17,10,77},{147,0,99},{7,0,1104},{11,0,269},{11,0,539},{11,0,\n627},{11,0,706},{11,0,975},{12,0,248},{12,0,434},{12,0,600},{12,0,622},{13,0,297\n},{13,0,485},{14,0,69},{14,0,409},{143,0,108},{4,10,362},{7,10,52},{7,10,303},{\n10,11,70},{12,11,26},{14,11,17},{14,11,178},{15,11,34},{149,11,12},{11,0,977},{\n141,0,507},{9,0,34},{139,0,484},{5,10,196},{6,10,486},{7,10,212},{8,10,309},{136\n,10,346},{6,0,1700},{7,0,26},{7,0,293},{7,0,382},{7,0,1026},{7,0,1087},{7,0,2027\n},{7,10,1912},{8,0,24},{8,0,114},{8,0,252},{8,0,727},{8,0,729},{9,0,30},{9,0,199\n},{9,0,231},{9,0,251},{9,0,334},{9,0,361},{9,0,712},{10,0,55},{10,0,60},{10,0,\n232},{10,0,332},{10,0,384},{10,0,396},{10,0,504},{10,0,542},{10,0,652},{11,0,20}\n,{11,0,48},{11,0,207},{11,0,291},{11,0,298},{11,0,342},{11,0,365},{11,0,394},{11\n,0,620},{11,0,705},{11,0,1017},{12,0,123},{12,0,340},{12,0,406},{12,0,643},{13,0\n,61},{13,0,269},{13,0,311},{13,0,319},{13,0,486},{14,0,234},{15,0,62},{15,0,85},\n{16,0,71},{18,0,119},{148,0,105},{4,11,71},{5,11,376},{7,11,119},{138,11,665},{4\n,10,686},{8,11,55},{10,0,918},{138,0,926},{138,10,625},{136,10,706},{132,11,479}\n,{4,10,30},{133,10,43},{6,0,379},{7,0,270},{7,11,607},{8,0,176},{8,0,183},{8,11,\n99},{9,0,432},{9,0,661},{12,0,247},{12,0,617},{18,0,125},{152,11,4},{5,0,792},{\n133,0,900},{4,11,612},{133,11,561},{4,10,220},{4,11,41},{5,11,74},{7,10,1535},{7\n,11,1627},{11,11,871},{140,11,619},{135,0,1920},{7,11,94},{11,11,329},{11,11,965\n},{12,11,241},{14,11,354},{15,11,22},{148,11,63},{9,11,209},{137,11,300},{134,0,\n771},{135,0,1979},{4,0,901},{133,0,776},{142,0,254},{133,11,98},{9,11,16},{141,\n11,386},{133,11,984},{4,11,182},{6,11,205},{135,11,220},{7,10,1725},{7,10,1774},\n{138,10,393},{5,10,263},{134,10,414},{4,11,42},{9,11,205},{9,11,786},{138,11,659\n},{14,0,140},{148,0,41},{6,10,178},{6,10,1750},{6,11,289},{7,11,1670},{8,0,440},\n{9,10,690},{10,0,359},{10,10,155},{10,10,373},{11,10,698},{12,11,57},{13,10,155}\n,{20,10,93},{151,11,4},{4,0,37},{5,0,334},{7,0,1253},{151,11,25},{4,0,508},{4,11\n,635},{5,10,97},{137,10,393},{139,11,533},{4,0,640},{133,0,513},{134,10,1639},{\n132,11,371},{4,11,272},{7,11,836},{7,11,1651},{145,11,89},{5,11,825},{6,11,444},\n{6,11,1640},{136,11,308},{4,10,191},{7,10,934},{8,10,647},{145,10,97},{12,0,246}\n,{15,0,162},{19,0,64},{20,0,8},{20,0,95},{22,0,24},{152,0,17},{4,0,533},{5,10,\n165},{9,10,346},{138,10,655},{5,11,737},{139,10,885},{133,10,877},{8,10,128},{\n139,10,179},{137,11,307},{140,0,752},{133,0,920},{135,0,1048},{5,0,153},{6,0,580\n},{6,10,1663},{7,10,132},{7,10,1154},{7,10,1415},{7,10,1507},{12,10,493},{15,10,\n105},{151,10,15},{5,10,459},{7,10,1073},{8,10,241},{136,10,334},{138,0,391},{135\n,0,1952},{133,11,525},{8,11,641},{11,11,388},{140,11,580},{142,0,126},{134,0,640\n},{132,0,483},{6,10,324},{6,10,520},{7,0,1616},{7,10,338},{7,10,1729},{8,10,228}\n,{9,0,69},{139,10,750},{5,11,493},{134,11,528},{135,0,734},{4,11,174},{135,11,\n911},{138,0,480},{9,0,495},{146,0,104},{135,10,705},{4,10,73},{6,10,612},{7,10,\n927},{7,10,1330},{7,10,1822},{8,10,217},{9,0,472},{9,10,765},{9,10,766},{10,10,\n408},{11,10,51},{11,10,793},{12,10,266},{15,10,158},{20,10,89},{150,10,32},{7,11\n,548},{137,11,58},{4,11,32},{5,11,215},{6,11,269},{7,11,1782},{7,11,1892},{10,11\n,16},{11,11,822},{11,11,954},{141,11,481},{132,0,874},{5,10,389},{8,10,636},{137\n,0,229},{7,11,1749},{136,11,477},{134,0,948},{5,11,308},{135,11,1088},{4,0,748},\n{139,0,1009},{136,10,21},{6,0,555},{135,0,485},{5,11,126},{8,11,297},{9,11,366},\n{9,11,445},{12,11,53},{12,11,374},{141,11,492},{7,11,1551},{139,11,361},{136,0,\n193},{136,0,472},{8,0,653},{13,0,93},{147,0,14},{132,0,984},{132,11,175},{4,11,\n685},{5,0,172},{134,0,1971},{149,11,8},{133,11,797},{5,10,189},{7,10,442},{7,10,\n443},{8,10,281},{12,10,174},{13,0,83},{141,10,261},{134,0,1568},{133,11,565},{\n139,0,384},{133,0,260},{6,10,2},{7,0,758},{7,0,880},{7,0,1359},{7,10,1262},{7,10\n,1737},{8,10,22},{8,10,270},{8,10,612},{9,0,164},{9,0,167},{9,10,312},{9,10,436}\n,{10,0,156},{10,0,588},{10,10,311},{10,10,623},{11,10,72},{11,10,330},{11,10,455\n},{12,0,101},{12,10,321},{12,10,504},{12,10,530},{12,10,543},{13,10,17},{13,10,\n156},{13,10,334},{14,0,48},{15,0,70},{17,10,60},{148,10,64},{4,11,252},{7,11,\n1068},{10,11,434},{11,11,228},{11,11,426},{13,11,231},{18,11,106},{148,11,87},{7\n,10,354},{10,10,410},{139,10,815},{6,0,367},{7,10,670},{7,10,1327},{8,10,411},{8\n,10,435},{9,10,653},{9,10,740},{10,10,385},{11,10,222},{11,10,324},{11,10,829},{\n140,10,611},{6,10,166},{7,0,1174},{135,10,374},{146,0,121},{132,0,828},{5,11,231\n},{138,11,509},{7,11,601},{9,11,277},{9,11,674},{10,11,178},{10,11,257},{10,11,\n418},{11,11,531},{11,11,544},{11,11,585},{12,11,113},{12,11,475},{13,11,99},{142\n,11,428},{134,0,1541},{135,11,1779},{5,0,343},{134,10,398},{135,10,50},{135,11,\n1683},{4,0,440},{7,0,57},{8,0,167},{8,0,375},{9,0,82},{9,0,561},{9,0,744},{9,11,\n744},{138,0,620},{134,0,926},{6,10,517},{7,10,1159},{10,10,621},{139,10,192},{\n137,0,827},{8,0,194},{136,0,756},{10,10,223},{139,10,645},{7,10,64},{136,10,245}\n,{4,11,399},{5,11,119},{5,11,494},{7,11,751},{137,11,556},{132,0,808},{135,0,22}\n,{7,10,1763},{140,10,310},{5,0,639},{6,11,584},{7,0,1249},{139,0,896},{134,0,\n1614},{135,0,860},{135,11,1121},{5,10,129},{6,10,61},{135,10,947},{4,0,102},{7,0\n,815},{7,0,1699},{139,0,964},{13,10,505},{141,10,506},{139,10,1000},{132,11,679}\n,{132,0,899},{132,0,569},{5,11,694},{137,11,714},{136,0,795},{6,0,2045},{139,11,\n7},{6,0,52},{9,0,104},{9,0,559},{12,0,308},{147,0,87},{4,0,301},{132,0,604},{133\n,10,637},{136,0,779},{5,11,143},{5,11,769},{6,11,1760},{7,11,682},{7,11,1992},{\n136,11,736},{137,10,590},{147,0,32},{137,11,527},{5,10,280},{135,10,1226},{134,0\n,494},{6,0,677},{6,0,682},{134,0,1044},{133,10,281},{135,10,1064},{5,11,860},{\n135,0,508},{6,11,422},{7,11,0},{7,11,1544},{9,11,577},{11,11,990},{12,11,141},{\n12,11,453},{13,11,47},{141,11,266},{134,0,1014},{5,11,515},{137,11,131},{134,0,\n957},{132,11,646},{6,0,310},{7,0,1849},{8,0,72},{8,0,272},{8,0,431},{9,0,12},{9,\n0,376},{10,0,563},{10,0,630},{10,0,796},{10,0,810},{11,0,367},{11,0,599},{11,0,\n686},{140,0,672},{4,11,396},{7,0,570},{7,10,120},{7,11,728},{8,10,489},{9,10,319\n},{9,11,117},{10,10,820},{11,10,1004},{12,10,379},{12,10,679},{13,10,117},{13,10\n,412},{13,11,202},{14,10,25},{15,10,52},{15,10,161},{16,10,47},{20,11,51},{149,\n10,2},{6,11,121},{6,11,124},{6,11,357},{7,11,1138},{7,11,1295},{8,11,162},{139,\n11,655},{4,10,937},{5,10,801},{8,0,449},{136,11,449},{139,11,958},{6,0,181},{7,0\n,537},{8,0,64},{9,0,127},{10,0,496},{12,0,510},{141,0,384},{138,11,253},{4,0,244\n},{135,0,233},{133,11,237},{132,10,365},{6,0,1650},{10,0,702},{139,0,245},{5,10,\n7},{139,10,774},{13,0,463},{13,11,463},{20,0,49},{148,11,49},{4,10,734},{5,10,\n662},{134,10,430},{4,10,746},{135,10,1090},{5,10,360},{136,10,237},{137,0,338},{\n143,11,10},{7,11,571},{138,11,366},{134,0,1279},{9,11,513},{10,11,22},{10,11,39}\n,{12,11,122},{140,11,187},{133,0,896},{146,0,178},{134,0,695},{137,0,808},{134,\n11,587},{7,11,107},{7,11,838},{8,11,550},{138,11,401},{7,0,1117},{136,0,539},{4,\n10,277},{5,10,608},{6,10,493},{7,10,457},{140,10,384},{133,11,768},{7,10,27},{7,\n10,316},{140,0,257},{140,0,1003},{4,0,207},{5,0,586},{5,0,676},{5,10,552},{6,0,\n448},{8,0,244},{11,0,1},{13,0,3},{16,0,54},{17,0,4},{146,0,13},{4,10,401},{137,\n10,264},{5,0,516},{7,0,1883},{135,11,1883},{4,11,894},{140,0,960},{5,0,4},{5,0,\n810},{6,0,13},{6,0,538},{6,0,1690},{6,0,1726},{7,0,499},{7,0,1819},{8,0,148},{8,\n0,696},{8,0,791},{12,0,125},{143,0,9},{135,0,1268},{9,10,543},{10,10,524},{11,0,\n30},{12,10,524},{14,0,315},{16,10,18},{20,10,26},{148,10,65},{4,10,205},{5,10,\n623},{6,0,748},{7,10,104},{136,10,519},{11,0,542},{139,0,852},{140,0,6},{132,0,\n848},{7,0,1385},{7,10,579},{9,10,41},{9,10,244},{9,10,669},{10,10,5},{11,0,582},\n{11,0,650},{11,0,901},{11,0,949},{11,10,861},{11,10,951},{11,10,980},{12,0,232},\n{12,0,236},{13,0,413},{13,0,501},{146,0,116},{4,0,945},{6,0,1811},{6,0,1845},{6,\n0,1853},{6,0,1858},{8,0,862},{12,0,782},{12,0,788},{18,0,160},{148,0,117},{132,\n10,717},{4,0,925},{5,0,803},{8,0,698},{138,0,828},{134,0,1416},{132,0,610},{139,\n0,992},{6,0,878},{134,0,1477},{135,0,1847},{138,11,531},{137,11,539},{134,11,272\n},{133,0,383},{134,0,1404},{132,10,489},{4,11,9},{5,11,128},{7,11,368},{11,11,\n480},{148,11,3},{136,0,986},{9,0,660},{138,0,347},{135,10,892},{136,11,682},{7,0\n,572},{9,0,592},{11,0,680},{12,0,356},{140,0,550},{7,0,1411},{138,11,527},{4,11,\n2},{7,11,545},{135,11,894},{137,10,473},{7,10,819},{7,11,481},{9,10,26},{9,10,\n392},{9,11,792},{10,10,152},{10,10,226},{11,0,64},{12,10,276},{12,10,426},{12,10\n,589},{13,10,460},{15,10,97},{19,10,48},{148,10,104},{135,10,51},{136,11,445},{\n136,11,646},{135,0,606},{132,10,674},{6,0,1829},{134,0,1830},{132,10,770},{5,10,\n79},{7,10,1027},{7,10,1477},{139,10,52},{5,11,530},{142,11,113},{134,10,1666},{7\n,0,748},{139,0,700},{134,10,195},{133,10,789},{4,10,251},{4,10,688},{7,10,513},{\n7,10,1284},{9,0,87},{138,0,365},{136,11,111},{133,0,127},{6,0,198},{140,0,83},{\n133,11,556},{133,10,889},{4,10,160},{5,10,330},{7,10,1434},{136,10,174},{5,0,276\n},{6,0,55},{7,0,1369},{138,0,864},{8,11,16},{140,11,568},{6,0,1752},{136,0,726},\n{135,0,1066},{133,0,764},{6,11,186},{137,11,426},{11,0,683},{139,11,683},{6,0,\n309},{7,0,331},{138,0,550},{133,10,374},{6,0,1212},{6,0,1852},{7,0,1062},{8,0,\n874},{8,0,882},{138,0,936},{132,11,585},{134,0,1364},{5,10,731},{135,0,986},{6,0\n,723},{6,0,1408},{138,0,381},{135,0,1573},{134,0,1025},{4,10,626},{5,10,642},{6,\n10,425},{10,10,202},{139,10,141},{4,11,93},{5,11,252},{6,11,229},{7,11,291},{9,\n11,550},{139,11,644},{137,11,749},{137,11,162},{132,11,381},{135,0,1559},{6,0,\n194},{7,0,133},{10,0,493},{10,0,570},{139,0,664},{5,0,24},{5,0,569},{6,0,3},{6,0\n,119},{6,0,143},{6,0,440},{7,0,295},{7,0,599},{7,0,1686},{7,0,1854},{8,0,424},{9\n,0,43},{9,0,584},{9,0,760},{10,0,148},{10,0,328},{11,0,159},{11,0,253},{11,0,506\n},{12,0,487},{140,0,531},{6,0,661},{134,0,1517},{136,10,835},{151,10,17},{5,0,14\n},{5,0,892},{6,0,283},{7,0,234},{136,0,537},{139,0,541},{4,0,126},{8,0,635},{147\n,0,34},{4,0,316},{4,0,495},{135,0,1561},{4,11,187},{5,11,184},{5,11,690},{7,11,\n1869},{138,11,756},{139,11,783},{4,0,998},{137,0,861},{136,0,1009},{139,11,292},\n{5,11,21},{6,11,77},{6,11,157},{7,11,974},{7,11,1301},{7,11,1339},{7,11,1490},{7\n,11,1873},{137,11,628},{7,11,1283},{9,11,227},{9,11,499},{10,11,341},{11,11,325}\n,{11,11,408},{14,11,180},{15,11,144},{18,11,47},{147,11,49},{4,0,64},{5,0,352},{\n5,0,720},{6,0,368},{139,0,359},{5,10,384},{8,10,455},{140,10,48},{5,10,264},{134\n,10,184},{7,0,1577},{10,0,304},{10,0,549},{12,0,365},{13,0,220},{13,0,240},{142,\n0,33},{134,0,1107},{134,0,929},{135,0,1142},{6,0,175},{137,0,289},{5,0,432},{133\n,0,913},{5,10,633},{6,0,279},{7,0,219},{135,10,1323},{7,0,785},{7,10,359},{8,10,\n243},{140,10,175},{139,0,595},{132,10,105},{8,11,398},{9,11,681},{139,11,632},{\n140,0,80},{5,0,931},{134,0,1698},{142,11,241},{134,11,20},{134,0,1323},{11,0,526\n},{11,0,939},{141,0,290},{5,0,774},{6,0,780},{6,0,1637},{6,0,1686},{6,0,1751},{8\n,0,559},{141,0,109},{141,0,127},{7,0,1167},{7,11,709},{11,0,934},{13,0,391},{145\n,0,76},{135,0,963},{6,0,260},{135,0,1484},{134,0,573},{4,10,758},{139,11,941},{\n135,10,1649},{145,11,36},{4,0,292},{137,0,580},{4,0,736},{5,0,871},{6,0,1689},{\n135,0,1944},{7,11,945},{11,11,713},{139,11,744},{134,0,1164},{135,11,937},{6,0,\n1922},{7,11,1652},{9,0,982},{15,0,173},{15,0,178},{15,0,200},{18,0,189},{18,0,\n207},{149,0,47},{7,0,1695},{139,10,128},{6,0,63},{135,0,920},{133,0,793},{143,11\n,134},{133,10,918},{5,0,67},{6,0,62},{6,0,374},{135,0,1391},{4,11,579},{5,11,226\n},{5,11,323},{7,11,960},{9,0,790},{140,0,47},{10,11,784},{141,11,191},{4,0,391},\n{135,0,1169},{137,0,443},{13,11,232},{146,11,35},{132,10,340},{132,0,271},{137,\n11,313},{5,11,973},{137,11,659},{134,0,1140},{6,11,135},{135,11,1176},{4,0,253},\n{5,0,544},{7,0,300},{137,0,340},{5,10,985},{7,0,897},{7,10,509},{145,10,96},{138\n,11,735},{135,10,1919},{138,0,890},{5,0,818},{134,0,1122},{5,0,53},{5,0,541},{6,\n0,94},{6,0,499},{7,0,230},{139,0,321},{4,0,920},{5,0,25},{5,0,790},{6,0,457},{7,\n0,853},{8,0,788},{142,11,31},{132,10,247},{135,11,314},{132,0,468},{6,10,337},{7\n,0,243},{7,10,494},{8,10,27},{8,10,599},{138,10,153},{4,10,184},{5,10,390},{7,10\n,618},{7,10,1456},{139,10,710},{134,0,870},{134,0,1238},{134,0,1765},{10,0,853},\n{10,0,943},{14,0,437},{14,0,439},{14,0,443},{14,0,446},{14,0,452},{14,0,469},{14\n,0,471},{14,0,473},{16,0,93},{16,0,102},{16,0,110},{148,0,121},{4,0,605},{7,0,\n518},{7,0,1282},{7,0,1918},{10,0,180},{139,0,218},{133,0,822},{4,0,634},{11,0,\n916},{142,0,419},{6,11,281},{7,11,6},{8,11,282},{8,11,480},{8,11,499},{9,11,198}\n,{10,11,143},{10,11,169},{10,11,211},{10,11,417},{10,11,574},{11,11,147},{11,11,\n395},{12,11,75},{12,11,407},{12,11,608},{13,11,500},{142,11,251},{134,0,898},{6,\n0,36},{7,0,658},{8,0,454},{150,11,48},{133,11,674},{135,11,1776},{4,11,419},{10,\n10,227},{11,10,497},{11,10,709},{140,10,415},{6,10,360},{7,10,1664},{136,10,478}\n,{137,0,806},{12,11,508},{14,11,102},{14,11,226},{144,11,57},{135,11,1123},{4,11\n,138},{7,11,1012},{7,11,1280},{137,11,76},{5,11,29},{140,11,638},{136,10,699},{\n134,0,1326},{132,0,104},{135,11,735},{132,10,739},{134,0,1331},{7,0,260},{135,11\n,260},{135,11,1063},{7,0,45},{9,0,542},{9,0,566},{9,10,869},{138,0,728},{4,10,67\n},{5,10,422},{7,10,1037},{7,10,1289},{7,10,1555},{9,10,741},{145,10,108},{139,0,\n263},{134,0,1516},{14,0,146},{15,0,42},{16,0,23},{17,0,86},{146,0,17},{138,0,468\n},{136,0,1005},{4,11,17},{5,11,23},{7,11,995},{11,11,383},{11,11,437},{12,11,460\n},{140,11,532},{7,0,87},{142,0,288},{138,10,96},{135,11,626},{144,10,26},{7,0,\n988},{7,0,1939},{9,0,64},{9,0,502},{12,0,22},{12,0,34},{13,0,12},{13,0,234},{147\n,0,77},{8,10,203},{11,10,823},{11,10,846},{12,10,482},{13,0,133},{13,10,277},{13\n,10,302},{13,10,464},{14,10,205},{142,10,221},{4,10,449},{133,10,718},{135,0,141\n},{6,0,1842},{136,0,872},{8,11,70},{12,11,171},{141,11,272},{4,10,355},{6,10,311\n},{9,10,256},{138,10,404},{132,0,619},{137,0,261},{10,10,758},{10,11,233},{139,\n11,76},{5,0,246},{8,0,189},{9,0,355},{9,0,512},{10,0,124},{10,0,453},{11,0,143},\n{11,0,416},{11,0,859},{141,0,341},{134,11,442},{133,10,827},{5,10,64},{140,10,\n581},{4,10,442},{7,10,1047},{7,10,1352},{135,10,1643},{134,11,1709},{5,0,678},{5\n,10,977},{6,0,305},{7,0,775},{135,0,1065},{11,11,69},{12,11,105},{12,11,117},{13\n,11,213},{14,11,13},{14,11,62},{14,11,177},{14,11,421},{15,11,19},{146,11,141},{\n137,11,309},{5,0,35},{7,0,862},{7,0,1886},{138,0,179},{136,0,285},{132,0,517},{7\n,11,976},{9,11,146},{10,11,206},{10,11,596},{13,11,218},{142,11,153},{132,10,254\n},{4,10,275},{6,0,214},{7,10,1219},{12,0,540},{140,10,376},{8,0,667},{11,0,403},\n{146,0,83},{10,11,648},{11,11,671},{12,0,74},{143,11,46},{135,0,125},{134,10,\n1753},{133,0,761},{4,11,518},{6,0,912},{6,10,369},{6,10,502},{7,10,1036},{7,11,\n1136},{8,10,348},{9,10,452},{10,10,26},{11,10,224},{11,10,387},{11,10,772},{12,\n10,95},{12,10,629},{13,10,195},{13,10,207},{13,10,241},{14,10,260},{14,10,270},{\n143,10,140},{10,0,131},{140,0,72},{132,10,269},{5,10,480},{7,10,532},{7,10,1197}\n,{7,10,1358},{8,10,291},{11,10,349},{142,10,396},{8,11,689},{137,11,863},{8,0,\n333},{138,0,182},{4,11,18},{7,11,145},{7,11,444},{7,11,1278},{8,11,49},{8,11,400\n},{9,11,71},{9,11,250},{10,11,459},{12,11,160},{144,11,24},{14,11,35},{142,11,\n191},{135,11,1864},{135,0,1338},{148,10,15},{14,0,94},{15,0,65},{16,0,4},{16,0,\n77},{16,0,80},{145,0,5},{12,11,82},{143,11,36},{133,11,1010},{133,0,449},{133,0,\n646},{7,0,86},{7,10,657},{136,0,103},{7,0,2028},{138,0,641},{136,10,533},{134,0,\n1},{139,11,970},{5,11,87},{7,11,313},{7,11,1103},{10,11,112},{10,11,582},{11,11,\n389},{11,11,813},{12,11,385},{13,11,286},{14,11,124},{146,11,108},{4,11,267},{\n134,0,869},{6,0,277},{7,0,1274},{7,0,1386},{146,0,87},{6,0,187},{7,0,39},{7,0,\n1203},{8,0,380},{14,0,117},{149,0,28},{4,10,211},{4,10,332},{5,10,335},{6,10,238\n},{7,10,269},{7,10,811},{7,10,1797},{8,10,836},{9,10,507},{141,10,242},{4,0,785}\n,{5,0,368},{6,0,297},{7,0,793},{139,0,938},{7,0,464},{8,0,558},{11,0,105},{12,0,\n231},{14,0,386},{15,0,102},{148,0,75},{133,10,1009},{8,0,877},{140,0,731},{139,\n11,289},{10,11,249},{139,11,209},{132,11,561},{134,0,1608},{132,11,760},{134,0,\n1429},{9,11,154},{140,11,485},{5,10,228},{6,10,203},{7,10,156},{8,10,347},{137,\n10,265},{7,0,1010},{11,0,733},{11,0,759},{13,0,34},{14,0,427},{146,0,45},{7,10,\n1131},{135,10,1468},{136,11,255},{7,0,1656},{9,0,369},{10,0,338},{10,0,490},{11,\n0,154},{11,0,545},{11,0,775},{13,0,77},{141,0,274},{133,11,621},{134,0,1038},{4,\n11,368},{135,11,641},{6,0,2010},{8,0,979},{8,0,985},{10,0,951},{138,0,1011},{134\n,0,1005},{5,10,291},{5,10,318},{7,10,765},{9,10,389},{12,10,548},{147,0,121},{5,\n0,20},{6,0,298},{7,0,659},{137,0,219},{7,0,1440},{11,0,854},{11,0,872},{11,0,921\n},{12,0,551},{13,0,472},{142,0,367},{5,0,490},{6,0,615},{6,0,620},{135,0,683},{6\n,0,1070},{134,0,1597},{139,0,522},{132,0,439},{136,0,669},{6,0,766},{6,0,1143},{\n6,0,1245},{10,10,525},{139,10,82},{9,11,92},{147,11,91},{6,0,668},{134,0,1218},{\n6,11,525},{9,11,876},{140,11,284},{132,0,233},{136,0,547},{132,10,422},{5,10,355\n},{145,10,0},{6,11,300},{135,11,1515},{4,0,482},{137,10,905},{4,0,886},{5,11,594\n},{135,0,346},{133,10,865},{5,10,914},{134,10,1625},{135,0,334},{5,0,795},{5,10,\n234},{134,0,1741},{135,10,1383},{6,11,1641},{136,11,820},{135,0,371},{7,11,1313}\n,{138,11,660},{135,10,1312},{135,0,622},{7,0,625},{135,0,1750},{135,0,339},{4,0,\n203},{135,0,1936},{15,0,29},{15,11,29},{16,0,38},{144,11,38},{5,0,338},{135,0,\n1256},{135,10,1493},{6,10,421},{7,10,61},{7,10,1540},{10,0,130},{138,10,501},{6,\n11,389},{7,11,149},{9,11,142},{138,11,94},{137,10,341},{11,0,678},{12,0,307},{\n142,10,98},{6,11,8},{7,11,1881},{136,11,91},{135,0,2044},{6,0,770},{6,0,802},{6,\n0,812},{6,10,102},{7,0,311},{7,10,72},{9,0,308},{12,0,255},{15,10,142},{147,10,\n67},{151,10,30},{135,10,823},{135,0,1266},{135,11,1746},{135,10,1870},{4,0,400},\n{5,0,267},{135,0,232},{7,11,24},{11,11,542},{139,11,852},{135,11,1739},{4,11,503\n},{135,11,1661},{5,11,130},{7,11,1314},{9,11,610},{10,11,718},{11,11,601},{11,11\n,819},{11,11,946},{140,11,536},{10,11,149},{11,11,280},{142,11,336},{7,0,739},{7\n,11,1946},{8,10,48},{8,10,88},{8,10,582},{8,10,681},{9,10,373},{9,10,864},{11,0,\n690},{11,10,157},{11,10,843},{148,10,27},{134,0,990},{4,10,88},{5,10,137},{5,10,\n174},{5,10,777},{6,10,1664},{6,10,1725},{7,10,77},{7,10,426},{7,10,1317},{7,10,\n1355},{8,10,126},{8,10,563},{9,10,523},{9,10,750},{10,10,310},{10,10,836},{11,10\n,42},{11,10,318},{11,10,731},{12,10,68},{12,10,92},{12,10,507},{12,10,692},{13,\n10,81},{13,10,238},{13,10,374},{14,10,436},{18,10,138},{19,10,78},{19,10,111},{\n20,10,55},{20,10,77},{148,10,92},{141,10,418},{4,10,938},{135,0,1831},{6,0,776},\n{134,0,915},{138,10,351},{5,11,348},{6,10,1668},{6,11,522},{7,10,1499},{8,10,117\n},{9,10,314},{138,10,174},{135,10,707},{132,0,613},{133,10,403},{132,11,392},{5,\n11,433},{9,11,633},{139,11,629},{133,0,763},{132,0,878},{132,0,977},{132,0,100},\n{4,10,44},{5,10,311},{6,0,463},{7,10,639},{7,10,762},{7,10,1827},{9,10,8},{9,10,\n462},{148,10,83},{134,11,234},{4,10,346},{7,10,115},{9,10,180},{9,10,456},{138,\n10,363},{5,0,362},{5,0,443},{6,0,318},{7,0,1019},{139,0,623},{5,0,463},{7,11,140\n},{7,11,1950},{8,0,296},{8,11,680},{11,11,817},{147,11,88},{7,11,1222},{138,11,\n386},{142,0,137},{132,0,454},{6,11,5},{7,0,1914},{7,10,1051},{9,10,545},{11,11,\n249},{12,11,313},{16,11,66},{145,11,26},{135,0,1527},{145,0,58},{148,11,59},{5,0\n,48},{5,0,404},{6,0,557},{7,0,458},{8,0,597},{10,0,455},{10,0,606},{11,0,49},{11\n,0,548},{12,0,476},{13,0,18},{141,0,450},{5,11,963},{134,11,1773},{133,0,729},{\n138,11,586},{5,0,442},{135,0,1984},{134,0,449},{144,0,40},{4,0,853},{7,11,180},{\n8,11,509},{136,11,792},{6,10,185},{7,10,1899},{9,10,875},{139,10,673},{134,11,\n524},{4,10,327},{5,10,478},{7,10,1332},{8,10,753},{140,0,227},{5,10,1020},{5,10,\n1022},{134,0,1491},{4,10,103},{133,10,401},{132,11,931},{4,10,499},{135,10,1421}\n,{5,0,55},{7,0,376},{140,0,161},{133,0,450},{6,0,1174},{134,0,1562},{7,11,1837},\n{10,0,62},{141,0,400},{140,0,207},{135,0,869},{4,11,773},{5,11,618},{137,11,756}\n,{132,10,96},{4,0,213},{7,0,223},{7,10,968},{136,0,80},{4,11,90},{5,11,337},{5,\n11,545},{7,11,754},{9,11,186},{10,11,72},{10,11,782},{11,11,513},{11,11,577},{11\n,11,610},{11,11,889},{11,11,961},{12,11,354},{12,11,362},{12,11,461},{12,11,595}\n,{13,11,79},{143,11,121},{7,0,381},{7,0,806},{7,0,820},{8,0,354},{8,0,437},{8,0,\n787},{9,0,657},{10,0,58},{10,0,339},{10,0,749},{11,0,914},{12,0,162},{13,0,75},{\n14,0,106},{14,0,198},{14,0,320},{14,0,413},{146,0,43},{136,0,747},{136,0,954},{\n134,0,1073},{135,0,556},{7,11,151},{9,11,329},{139,11,254},{5,0,692},{134,0,1395\n},{6,10,563},{137,10,224},{134,0,191},{132,0,804},{9,11,187},{10,11,36},{17,11,\n44},{146,11,64},{7,11,165},{7,11,919},{136,11,517},{4,11,506},{5,11,295},{7,11,\n1680},{15,11,14},{144,11,5},{4,0,706},{6,0,162},{7,0,1960},{136,0,831},{135,11,\n1376},{7,11,987},{9,11,688},{10,11,522},{11,11,788},{140,11,566},{150,0,35},{138\n,0,426},{135,0,1235},{135,11,1741},{7,11,389},{7,11,700},{7,11,940},{8,11,514},{\n9,11,116},{9,11,535},{10,11,118},{11,11,107},{11,11,148},{11,11,922},{12,11,254}\n,{12,11,421},{142,11,238},{134,0,1234},{132,11,743},{4,10,910},{5,10,832},{135,\n11,1335},{141,0,96},{135,11,185},{146,0,149},{4,0,204},{137,0,902},{4,11,784},{\n133,11,745},{136,0,833},{136,0,949},{5,11,81},{7,0,366},{7,11,146},{7,11,1342},{\n7,11,1446},{8,11,53},{8,11,561},{8,11,694},{8,11,754},{9,0,287},{9,11,97},{9,11,\n115},{9,11,894},{10,11,462},{10,11,813},{11,11,230},{11,11,657},{11,11,699},{11,\n11,748},{12,0,199},{12,0,556},{12,0,577},{12,11,119},{12,11,200},{12,11,283},{14\n,11,273},{145,11,15},{5,11,408},{137,11,747},{9,11,498},{140,11,181},{6,0,2020},\n{136,0,992},{5,0,356},{135,0,224},{134,0,784},{7,0,630},{8,10,528},{9,0,567},{9,\n10,348},{11,0,150},{11,0,444},{141,0,119},{134,0,539},{4,10,20},{133,10,616},{\n142,0,27},{7,11,30},{8,11,86},{8,11,315},{8,11,700},{9,11,576},{9,11,858},{11,11\n,310},{11,11,888},{11,11,904},{12,11,361},{141,11,248},{138,11,839},{134,0,755},\n{134,0,1063},{7,10,1091},{135,10,1765},{134,11,428},{7,11,524},{8,11,169},{8,11,\n234},{9,11,480},{138,11,646},{139,0,814},{7,11,1462},{139,11,659},{4,10,26},{5,\n10,429},{6,10,245},{7,10,704},{7,10,1379},{135,10,1474},{7,11,1205},{138,11,637}\n,{139,11,803},{132,10,621},{136,0,987},{4,11,266},{8,11,4},{9,11,39},{10,11,166}\n,{11,11,918},{12,11,635},{20,11,10},{22,11,27},{150,11,43},{4,0,235},{135,0,255}\n,{4,0,194},{5,0,584},{6,0,384},{7,0,583},{10,0,761},{11,0,760},{139,0,851},{133,\n10,542},{134,0,1086},{133,10,868},{8,0,1016},{136,0,1018},{7,0,1396},{7,11,1396}\n,{136,10,433},{135,10,1495},{138,10,215},{141,10,124},{7,11,157},{8,11,279},{9,\n11,759},{16,11,31},{16,11,39},{16,11,75},{18,11,24},{20,11,42},{152,11,1},{5,0,\n562},{134,11,604},{134,0,913},{5,0,191},{137,0,271},{4,0,470},{6,0,153},{7,0,\n1503},{7,0,1923},{10,0,701},{11,0,132},{11,0,227},{11,0,320},{11,0,436},{11,0,\n525},{11,0,855},{11,0,873},{12,0,41},{12,0,286},{13,0,103},{13,0,284},{14,0,255}\n,{14,0,262},{15,0,117},{143,0,127},{7,0,475},{12,0,45},{147,10,112},{132,11,567}\n,{137,11,859},{6,0,713},{6,0,969},{6,0,1290},{134,0,1551},{133,0,327},{6,0,552},\n{6,0,1292},{7,0,1754},{137,0,604},{4,0,223},{5,11,762},{6,0,359},{7,11,1880},{9,\n11,680},{11,0,3},{11,11,798},{13,0,108},{14,0,89},{144,0,22},{5,0,80},{6,0,405},\n{7,0,403},{7,0,1502},{8,0,456},{9,0,487},{9,0,853},{9,0,889},{10,0,309},{11,0,\n721},{11,0,994},{12,0,430},{141,0,165},{133,11,298},{132,10,647},{134,0,2016},{\n18,10,10},{146,11,10},{4,0,453},{5,0,887},{6,0,535},{8,0,6},{8,0,543},{136,0,826\n},{136,0,975},{10,0,961},{138,0,962},{138,10,220},{6,0,1891},{6,0,1893},{9,0,916\n},{9,0,965},{9,0,972},{12,0,801},{12,0,859},{12,0,883},{15,0,226},{149,0,51},{\n132,10,109},{135,11,267},{7,11,92},{7,11,182},{8,11,453},{9,11,204},{11,11,950},\n{12,11,94},{12,11,644},{16,11,20},{16,11,70},{16,11,90},{147,11,55},{134,10,1746\n},{6,11,71},{7,11,845},{7,11,1308},{8,11,160},{137,11,318},{5,0,101},{6,0,88},{7\n,0,263},{7,0,628},{7,0,1677},{7,11,237},{8,0,349},{8,11,664},{9,0,100},{9,11,42}\n,{9,11,266},{9,11,380},{9,11,645},{10,0,677},{10,11,177},{10,11,276},{14,0,169},\n{14,0,302},{14,0,313},{15,0,48},{143,0,84},{138,11,69},{4,0,310},{7,0,708},{7,0,\n996},{9,0,795},{10,0,390},{10,0,733},{11,0,451},{12,0,249},{14,0,115},{14,0,286}\n,{143,0,100},{4,10,40},{5,0,587},{10,10,67},{11,10,117},{11,10,768},{139,10,935}\n,{6,0,1942},{7,0,512},{136,0,983},{7,10,992},{8,10,301},{9,10,722},{12,10,63},{\n13,10,29},{14,10,161},{143,10,18},{136,11,76},{139,10,923},{134,0,645},{134,0,\n851},{4,0,498},{132,11,293},{7,0,217},{8,0,140},{10,0,610},{14,11,352},{17,11,53\n},{18,11,146},{18,11,152},{19,11,11},{150,11,54},{134,0,1448},{138,11,841},{133,\n0,905},{4,11,605},{7,11,518},{7,11,1282},{7,11,1918},{10,11,180},{139,11,218},{\n139,11,917},{135,10,825},{140,10,328},{4,0,456},{7,0,105},{7,0,358},{7,0,1637},{\n8,0,643},{139,0,483},{134,0,792},{6,11,96},{135,11,1426},{137,11,691},{4,11,651}\n,{133,11,289},{7,11,688},{8,11,35},{9,11,511},{10,11,767},{147,11,118},{150,0,56\n},{5,0,243},{5,0,535},{6,10,204},{10,10,320},{10,10,583},{13,10,502},{14,10,72},\n{14,10,274},{14,10,312},{14,10,344},{15,10,159},{16,10,62},{16,10,69},{17,10,30}\n,{18,10,42},{18,10,53},{18,10,84},{18,10,140},{19,10,68},{19,10,85},{20,10,5},{\n20,10,45},{20,10,101},{22,10,7},{150,10,20},{4,10,558},{6,10,390},{7,10,162},{7,\n10,689},{9,10,360},{138,10,653},{146,11,23},{135,0,1748},{5,10,856},{6,10,1672},\n{6,10,1757},{134,10,1781},{4,11,704},{5,0,539},{5,0,754},{134,0,876},{135,11,\n1078},{5,10,92},{10,10,736},{140,10,102},{5,10,590},{9,10,213},{145,0,91},{134,0\n,1565},{6,0,91},{135,0,435},{4,0,939},{140,0,792},{134,0,1399},{4,0,16},{4,11,\n720},{5,0,316},{5,0,842},{5,11,306},{6,0,370},{6,0,1778},{8,0,166},{11,0,812},{\n12,0,206},{12,0,351},{14,0,418},{16,0,15},{16,0,34},{18,0,3},{19,0,3},{19,0,7},{\n20,0,4},{149,0,21},{144,0,95},{133,11,431},{132,11,234},{135,0,551},{4,0,999},{6\n,0,1966},{134,0,2042},{7,0,619},{10,0,547},{11,0,122},{12,0,601},{15,0,7},{148,0\n,20},{5,11,464},{6,11,236},{7,11,276},{7,11,696},{7,11,914},{7,11,1108},{7,11,\n1448},{9,11,15},{9,11,564},{10,11,14},{12,11,565},{13,11,449},{14,11,53},{15,11,\n13},{16,11,64},{145,11,41},{6,0,884},{6,0,1019},{134,0,1150},{6,11,1767},{12,11,\n194},{145,11,107},{136,10,503},{133,11,840},{6,10,466},{135,0,671},{132,0,888},{\n4,0,149},{138,0,368},{4,0,154},{7,0,1134},{136,0,105},{135,0,983},{9,11,642},{11\n,11,236},{142,11,193},{4,0,31},{6,0,429},{7,0,962},{9,0,458},{139,0,691},{6,0,\n643},{134,0,1102},{132,0,312},{4,11,68},{5,11,634},{6,11,386},{7,11,794},{8,11,\n273},{9,11,563},{10,11,105},{10,11,171},{11,11,94},{139,11,354},{133,0,740},{135\n,0,1642},{4,11,95},{7,11,416},{8,11,211},{139,11,830},{132,0,236},{138,10,241},{\n7,11,731},{13,11,20},{143,11,11},{5,0,836},{5,0,857},{6,0,1680},{135,0,59},{10,0\n,68},{11,0,494},{152,11,6},{4,0,81},{139,0,867},{135,0,795},{133,11,689},{4,0,\n1001},{5,0,282},{6,0,1932},{6,0,1977},{6,0,1987},{6,0,1992},{8,0,650},{8,0,919},\n{8,0,920},{8,0,923},{8,0,926},{8,0,927},{8,0,931},{8,0,939},{8,0,947},{8,0,956},\n{8,0,997},{9,0,907},{10,0,950},{10,0,953},{10,0,954},{10,0,956},{10,0,958},{10,0\n,959},{10,0,964},{10,0,970},{10,0,972},{10,0,973},{10,0,975},{10,0,976},{10,0,\n980},{10,0,981},{10,0,984},{10,0,988},{10,0,990},{10,0,995},{10,0,999},{10,0,\n1002},{10,0,1003},{10,0,1005},{10,0,1006},{10,0,1008},{10,0,1009},{10,0,1012},{\n10,0,1014},{10,0,1015},{10,0,1019},{10,0,1020},{10,0,1022},{12,0,959},{12,0,961}\n,{12,0,962},{12,0,963},{12,0,964},{12,0,965},{12,0,967},{12,0,968},{12,0,969},{\n12,0,970},{12,0,971},{12,0,972},{12,0,973},{12,0,974},{12,0,975},{12,0,976},{12,\n0,977},{12,0,979},{12,0,981},{12,0,982},{12,0,983},{12,0,984},{12,0,985},{12,0,\n986},{12,0,987},{12,0,989},{12,0,990},{12,0,992},{12,0,993},{12,0,995},{12,0,998\n},{12,0,999},{12,0,1000},{12,0,1001},{12,0,1002},{12,0,1004},{12,0,1005},{12,0,\n1006},{12,0,1007},{12,0,1008},{12,0,1009},{12,0,1010},{12,0,1011},{12,0,1012},{\n12,0,1014},{12,0,1015},{12,0,1016},{12,0,1017},{12,0,1018},{12,0,1019},{12,0,\n1022},{12,0,1023},{14,0,475},{14,0,477},{14,0,478},{14,0,479},{14,0,480},{14,0,\n482},{14,0,483},{14,0,484},{14,0,485},{14,0,486},{14,0,487},{14,0,488},{14,0,489\n},{14,0,490},{14,0,491},{14,0,492},{14,0,493},{14,0,494},{14,0,495},{14,0,496},{\n14,0,497},{14,0,498},{14,0,499},{14,0,500},{14,0,501},{14,0,502},{14,0,503},{14,\n0,504},{14,0,506},{14,0,507},{14,0,508},{14,0,509},{14,0,510},{14,0,511},{16,0,\n113},{16,0,114},{16,0,115},{16,0,117},{16,0,118},{16,0,119},{16,0,121},{16,0,122\n},{16,0,123},{16,0,124},{16,0,125},{16,0,126},{16,0,127},{18,0,242},{18,0,243},{\n18,0,244},{18,0,245},{18,0,248},{18,0,249},{18,0,250},{18,0,251},{18,0,252},{18,\n0,253},{18,0,254},{18,0,255},{20,0,125},{20,0,126},{148,0,127},{7,11,1717},{7,11\n,1769},{138,11,546},{7,11,1127},{7,11,1572},{10,11,297},{10,11,422},{11,11,764},\n{11,11,810},{12,11,264},{13,11,102},{13,11,300},{13,11,484},{14,11,147},{14,11,\n229},{17,11,71},{18,11,118},{147,11,120},{6,0,1148},{134,0,1586},{132,0,775},{\n135,10,954},{133,11,864},{133,11,928},{138,11,189},{135,10,1958},{6,10,549},{8,\n10,34},{8,10,283},{9,10,165},{138,10,475},{5,10,652},{5,10,701},{135,10,449},{\n135,11,695},{4,10,655},{7,10,850},{17,10,75},{146,10,137},{140,11,682},{133,11,\n523},{8,0,970},{136,10,670},{136,11,555},{7,11,76},{8,11,44},{9,11,884},{10,11,\n580},{11,11,399},{11,11,894},{15,11,122},{18,11,144},{147,11,61},{6,10,159},{6,\n10,364},{7,10,516},{7,10,1439},{137,10,518},{4,0,71},{5,0,376},{7,0,119},{138,0,\n665},{141,10,151},{11,0,827},{14,0,34},{143,0,148},{133,11,518},{4,0,479},{135,\n11,1787},{135,11,1852},{135,10,993},{7,0,607},{136,0,99},{134,0,1960},{132,0,793\n},{4,0,41},{5,0,74},{7,0,1627},{11,0,871},{140,0,619},{7,0,94},{11,0,329},{11,0,\n965},{12,0,241},{14,0,354},{15,0,22},{148,0,63},{7,10,501},{9,10,111},{10,10,141\n},{11,10,332},{13,10,43},{13,10,429},{14,10,130},{14,10,415},{145,10,102},{9,0,\n209},{137,0,300},{134,0,1497},{138,11,255},{4,11,934},{5,11,138},{136,11,610},{\n133,0,98},{6,0,1316},{10,11,804},{138,11,832},{8,11,96},{9,11,36},{10,11,607},{\n11,11,423},{11,11,442},{12,11,309},{14,11,199},{15,11,90},{145,11,110},{132,0,\n463},{5,10,149},{136,10,233},{133,10,935},{4,11,652},{8,11,320},{9,11,13},{9,11,\n398},{9,11,727},{10,11,75},{10,11,184},{10,11,230},{10,11,564},{10,11,569},{11,\n11,973},{12,11,70},{12,11,189},{13,11,57},{13,11,257},{22,11,6},{150,11,16},{142\n,0,291},{12,10,582},{146,10,131},{136,10,801},{133,0,984},{145,11,116},{4,11,692\n},{133,11,321},{4,0,182},{6,0,205},{135,0,220},{4,0,42},{9,0,205},{9,0,786},{138\n,0,659},{6,0,801},{11,11,130},{140,11,609},{132,0,635},{5,11,345},{135,11,1016},\n{139,0,533},{132,0,371},{4,0,272},{135,0,836},{6,0,1282},{135,11,1100},{5,0,825}\n,{134,0,1640},{135,11,1325},{133,11,673},{4,11,287},{133,11,1018},{135,0,357},{6\n,0,467},{137,0,879},{7,0,317},{135,0,569},{6,0,924},{134,0,1588},{5,10,406},{5,\n11,34},{10,11,724},{12,11,444},{13,11,354},{18,11,32},{23,11,24},{23,11,31},{152\n,11,5},{6,0,1795},{6,0,1835},{6,0,1836},{6,0,1856},{8,0,844},{8,0,849},{8,0,854}\n,{8,0,870},{8,0,887},{10,0,852},{138,0,942},{6,10,69},{135,10,117},{137,0,307},{\n4,0,944},{6,0,1799},{6,0,1825},{10,0,848},{10,0,875},{10,0,895},{10,0,899},{10,0\n,902},{140,0,773},{11,0,43},{13,0,72},{141,0,142},{135,10,1830},{134,11,382},{4,\n10,432},{135,10,824},{132,11,329},{7,0,1820},{139,11,124},{133,10,826},{133,0,\n525},{132,11,906},{7,11,1940},{136,11,366},{138,11,10},{4,11,123},{4,11,649},{5,\n11,605},{7,11,1509},{136,11,36},{6,0,110},{135,0,1681},{133,0,493},{133,11,767},\n{4,0,174},{135,0,911},{138,11,786},{8,0,417},{137,0,782},{133,10,1000},{7,0,733}\n,{137,0,583},{4,10,297},{6,10,529},{7,10,152},{7,10,713},{7,10,1845},{8,10,710},\n{8,10,717},{12,10,639},{140,10,685},{4,0,32},{5,0,215},{6,0,269},{7,0,1782},{7,0\n,1892},{10,0,16},{11,0,822},{11,0,954},{141,0,481},{4,11,273},{5,11,658},{133,11\n,995},{136,0,477},{134,11,72},{135,11,1345},{4,10,520},{5,0,308},{7,0,1088},{135\n,10,575},{133,11,589},{5,0,126},{8,0,297},{9,0,366},{140,0,374},{7,0,1551},{139,\n0,361},{5,11,117},{6,11,514},{6,11,541},{7,11,1164},{7,11,1436},{8,11,220},{8,11\n,648},{10,11,688},{139,11,560},{133,11,686},{4,0,946},{6,0,1807},{8,0,871},{10,0\n,854},{10,0,870},{10,0,888},{10,0,897},{10,0,920},{12,0,722},{12,0,761},{12,0,\n763},{12,0,764},{14,0,454},{14,0,465},{16,0,107},{18,0,167},{18,0,168},{146,0,\n172},{132,0,175},{135,0,1307},{132,0,685},{135,11,1834},{133,0,797},{6,0,745},{6\n,0,858},{134,0,963},{133,0,565},{5,10,397},{6,10,154},{7,10,676},{7,11,196},{8,\n10,443},{8,10,609},{9,10,24},{9,10,325},{10,10,35},{10,11,765},{11,10,535},{11,\n10,672},{11,10,1018},{11,11,347},{11,11,552},{11,11,576},{11,11,790},{12,10,637}\n,{12,11,263},{13,11,246},{13,11,270},{13,11,395},{14,11,74},{14,11,176},{14,11,\n190},{14,11,398},{14,11,412},{15,11,32},{15,11,63},{16,10,30},{16,11,88},{147,11\n,105},{13,11,84},{141,11,122},{4,0,252},{7,0,1068},{10,0,434},{11,0,228},{11,0,\n426},{13,0,231},{18,0,106},{148,0,87},{137,0,826},{4,11,589},{139,11,282},{5,11,\n381},{135,11,1792},{132,0,791},{5,0,231},{5,10,981},{138,0,509},{7,0,601},{9,0,\n277},{9,0,674},{10,0,178},{10,0,418},{10,0,571},{11,0,531},{12,0,113},{12,0,475}\n,{13,0,99},{142,0,428},{4,10,56},{7,10,1791},{7,11,616},{8,10,607},{8,10,651},{\n10,11,413},{11,10,465},{11,10,835},{12,10,337},{141,10,480},{7,0,1591},{144,0,43\n},{9,10,158},{138,10,411},{135,0,1683},{8,0,289},{11,0,45},{12,0,278},{140,0,537\n},{6,11,120},{7,11,1188},{7,11,1710},{8,11,286},{9,11,667},{11,11,592},{139,11,\n730},{136,10,617},{135,0,1120},{135,11,1146},{139,10,563},{4,10,369},{4,11,352},\n{135,11,687},{143,11,38},{4,0,399},{5,0,119},{5,0,494},{7,0,751},{9,0,556},{14,\n11,179},{15,11,151},{150,11,11},{4,11,192},{5,11,49},{6,11,200},{6,11,293},{6,11\n,1696},{135,11,488},{4,0,398},{133,0,660},{6,10,622},{135,0,1030},{135,11,595},{\n141,0,168},{132,11,147},{7,0,973},{10,10,624},{142,10,279},{132,10,363},{132,0,\n642},{133,11,934},{134,0,1615},{7,11,505},{135,11,523},{7,0,594},{7,0,851},{7,0,\n1858},{9,0,411},{9,0,574},{9,0,666},{9,0,737},{10,0,346},{10,0,712},{11,0,246},{\n11,0,432},{11,0,517},{11,0,647},{11,0,679},{11,0,727},{12,0,304},{12,0,305},{12,\n0,323},{12,0,483},{12,0,572},{12,0,593},{12,0,602},{13,0,95},{13,0,101},{13,0,\n171},{13,0,315},{13,0,378},{13,0,425},{13,0,475},{14,0,63},{14,0,380},{14,0,384}\n,{15,0,133},{18,0,112},{148,0,72},{135,0,1093},{132,0,679},{8,0,913},{10,0,903},\n{10,0,915},{10,11,438},{12,0,648},{12,0,649},{14,0,455},{144,0,112},{137,0,203},\n{134,10,292},{134,0,1492},{5,10,177},{6,10,616},{7,0,1374},{7,10,827},{8,0,540},\n{9,10,525},{138,10,656},{135,0,1486},{9,0,714},{138,10,31},{136,0,825},{134,0,\n1511},{132,11,637},{134,0,952},{4,10,161},{133,10,631},{5,0,143},{5,0,769},{6,0,\n1760},{7,0,682},{7,0,1992},{136,0,736},{132,0,700},{134,0,1540},{132,11,777},{9,\n11,867},{138,11,837},{7,0,1557},{135,10,1684},{133,0,860},{6,0,422},{7,0,0},{7,0\n,1544},{9,0,605},{9,10,469},{9,10,709},{11,0,990},{12,0,235},{12,0,453},{12,10,\n512},{13,0,47},{13,0,266},{14,10,65},{145,10,12},{10,10,229},{11,0,807},{11,10,\n73},{139,10,376},{6,11,170},{7,11,1080},{8,11,395},{8,11,487},{11,11,125},{141,\n11,147},{5,0,515},{137,0,131},{7,0,1605},{11,0,962},{146,0,139},{132,0,646},{4,0\n,396},{7,0,728},{9,0,117},{13,0,202},{148,0,51},{4,11,535},{6,0,121},{6,0,124},{\n6,0,357},{6,10,558},{7,0,1138},{7,0,1295},{7,10,651},{8,0,162},{8,0,508},{8,11,\n618},{9,10,0},{10,10,34},{11,0,655},{139,10,1008},{135,11,1245},{138,0,357},{150\n,11,23},{133,0,237},{135,0,1784},{7,10,1832},{138,10,374},{132,0,713},{132,11,46\n},{5,11,811},{6,0,1536},{6,11,1679},{6,11,1714},{7,11,2032},{138,0,348},{11,11,\n182},{142,11,195},{6,0,523},{7,0,738},{7,10,771},{7,10,1731},{9,10,405},{138,10,\n421},{7,11,1458},{9,11,407},{139,11,15},{6,11,34},{7,11,69},{7,11,640},{7,11,\n1089},{8,11,708},{8,11,721},{9,11,363},{9,11,643},{10,11,628},{148,11,98},{133,0\n,434},{135,0,1877},{7,0,571},{138,0,366},{5,10,881},{133,10,885},{9,0,513},{10,0\n,25},{10,0,39},{12,0,122},{140,0,187},{132,0,580},{5,10,142},{134,10,546},{132,\n11,462},{137,0,873},{5,10,466},{11,10,571},{12,10,198},{13,10,283},{14,10,186},{\n15,10,21},{143,10,103},{4,10,185},{5,10,257},{5,10,839},{5,10,936},{7,0,171},{9,\n10,399},{10,10,258},{10,10,395},{10,10,734},{11,10,1014},{12,10,23},{13,10,350},\n{14,10,150},{147,10,6},{134,0,625},{7,0,107},{7,0,838},{8,0,550},{138,0,401},{5,\n11,73},{6,11,23},{134,11,338},{4,0,943},{6,0,1850},{12,0,713},{142,0,434},{7,10,\n404},{7,10,1377},{7,10,1430},{7,10,2017},{8,10,149},{8,10,239},{8,10,512},{8,10,\n793},{8,10,818},{9,10,474},{9,10,595},{10,10,122},{10,10,565},{10,10,649},{10,10\n,783},{11,0,588},{11,0,864},{11,0,936},{11,0,968},{11,10,239},{11,10,295},{11,10\n,447},{11,10,528},{11,10,639},{11,10,800},{12,0,73},{12,0,343},{12,0,394},{12,10\n,25},{12,10,157},{12,10,316},{12,10,390},{12,10,391},{12,10,395},{12,10,478},{12\n,10,503},{12,10,592},{12,10,680},{13,0,275},{13,10,50},{13,10,53},{13,10,132},{\n13,10,198},{13,10,322},{13,10,415},{13,10,511},{14,0,257},{14,10,71},{14,10,395}\n,{15,0,160},{15,10,71},{15,10,136},{17,10,123},{18,10,93},{147,10,58},{133,0,768\n},{11,0,103},{142,0,0},{136,10,712},{132,0,799},{132,0,894},{7,11,725},{8,11,498\n},{139,11,268},{135,11,1798},{135,11,773},{141,11,360},{4,10,377},{152,10,13},{\n135,0,1673},{132,11,583},{134,0,1052},{133,11,220},{140,11,69},{132,11,544},{4,\n10,180},{135,10,1906},{134,0,272},{4,0,441},{134,0,1421},{4,0,9},{5,0,128},{7,0,\n368},{11,0,480},{148,0,3},{5,11,176},{6,11,437},{6,11,564},{11,11,181},{141,11,\n183},{132,10,491},{7,0,1182},{141,11,67},{4,10,171},{6,0,1346},{138,10,234},{4,\n10,586},{7,10,1186},{138,10,631},{136,0,682},{134,0,1004},{15,0,24},{143,11,24},\n{134,0,968},{4,0,2},{6,0,742},{6,0,793},{7,0,545},{7,0,894},{9,10,931},{10,10,\n334},{148,10,71},{136,11,600},{133,10,765},{9,0,769},{140,0,185},{4,11,790},{5,\n11,273},{134,11,394},{7,0,474},{137,0,578},{4,11,135},{6,11,127},{7,11,1185},{7,\n11,1511},{8,11,613},{11,11,5},{12,11,133},{12,11,495},{12,11,586},{14,11,385},{\n15,11,118},{17,11,20},{146,11,98},{133,10,424},{5,0,530},{142,0,113},{6,11,230},\n{7,11,961},{7,11,1085},{136,11,462},{7,11,1954},{137,11,636},{136,10,714},{149,\n11,6},{135,10,685},{9,10,420},{10,10,269},{10,10,285},{10,10,576},{11,10,397},{\n13,10,175},{145,10,90},{132,10,429},{5,0,556},{5,11,162},{136,11,68},{132,11,654\n},{4,11,156},{7,11,998},{7,11,1045},{7,11,1860},{9,11,48},{9,11,692},{11,11,419}\n,{139,11,602},{6,0,1317},{7,11,1276},{8,0,16},{8,11,474},{9,0,825},{9,11,652},{\n140,0,568},{7,10,18},{7,10,699},{7,10,1966},{8,10,752},{9,10,273},{9,10,412},{9,\n10,703},{10,10,71},{10,10,427},{10,10,508},{146,0,97},{7,11,1454},{10,0,703},{\n138,11,703},{4,10,53},{5,10,186},{135,10,752},{134,0,892},{134,0,1571},{8,10,575\n},{10,10,289},{139,10,319},{6,0,186},{137,0,426},{134,0,1101},{132,10,675},{132,\n0,585},{6,0,1870},{137,0,937},{152,11,10},{9,11,197},{10,11,300},{12,11,473},{13\n,11,90},{141,11,405},{4,0,93},{5,0,252},{6,0,229},{7,0,291},{9,0,550},{139,0,644\n},{137,0,749},{6,10,209},{8,10,468},{9,0,162},{9,10,210},{11,10,36},{12,10,28},{\n12,10,630},{13,10,21},{13,10,349},{14,10,7},{145,10,13},{132,0,381},{132,11,606}\n,{4,10,342},{135,10,1179},{7,11,1587},{7,11,1707},{10,11,528},{139,11,504},{12,\n11,39},{13,11,265},{141,11,439},{4,10,928},{133,10,910},{7,10,1838},{7,11,1978},\n{136,11,676},{6,0,762},{6,0,796},{134,0,956},{4,10,318},{4,10,496},{7,10,856},{\n139,10,654},{137,11,242},{4,11,361},{133,11,315},{132,11,461},{132,11,472},{132,\n0,857},{5,0,21},{6,0,77},{6,0,157},{7,0,974},{7,0,1301},{7,0,1339},{7,0,1490},{7\n,0,1873},{7,10,915},{8,10,247},{9,0,628},{147,10,0},{4,10,202},{5,10,382},{6,10,\n454},{7,10,936},{7,10,1803},{8,10,758},{9,10,375},{9,10,895},{10,10,743},{10,10,\n792},{11,10,978},{11,10,1012},{142,10,109},{7,11,617},{10,11,498},{11,11,501},{\n12,11,16},{140,11,150},{7,10,1150},{7,10,1425},{7,10,1453},{10,11,747},{140,10,\n513},{133,11,155},{11,0,919},{141,0,409},{138,10,791},{10,0,633},{139,11,729},{7\n,11,163},{8,11,319},{9,11,402},{10,11,24},{10,11,681},{11,11,200},{11,11,567},{\n12,11,253},{12,11,410},{142,11,219},{5,11,475},{7,11,1780},{9,11,230},{11,11,297\n},{11,11,558},{14,11,322},{147,11,76},{6,10,445},{7,0,332},{137,10,909},{135,11,\n1956},{136,11,274},{134,10,578},{135,0,1489},{135,11,1848},{5,11,944},{134,11,\n1769},{132,11,144},{136,10,766},{4,0,832},{135,10,541},{8,0,398},{9,0,681},{139,\n0,632},{136,0,645},{9,0,791},{10,0,93},{16,0,13},{17,0,23},{18,0,135},{19,0,12},\n{20,0,1},{20,0,12},{148,0,14},{6,11,247},{137,11,555},{134,0,20},{132,0,800},{\n135,0,1841},{139,10,983},{137,10,768},{132,10,584},{141,11,51},{4,11,620},{6,0,\n1993},{138,11,280},{136,0,769},{7,11,1810},{11,0,290},{11,0,665},{11,11,866},{12\n,11,103},{13,11,495},{17,11,67},{147,11,74},{134,0,1426},{139,0,60},{4,10,326},{\n135,10,1770},{4,10,226},{7,0,1874},{137,0,641},{5,10,426},{6,0,644},{8,10,30},{9\n,10,2},{11,10,549},{147,10,122},{5,11,428},{138,11,442},{135,11,1871},{135,0,\n1757},{147,10,117},{135,0,937},{135,0,1652},{6,0,654},{134,0,1476},{133,11,99},{\n135,0,527},{132,10,345},{4,10,385},{4,11,397},{7,10,265},{135,10,587},{4,0,579},\n{5,0,226},{5,0,323},{135,0,960},{134,0,1486},{8,11,502},{144,11,9},{4,10,347},{5\n,10,423},{5,10,996},{135,10,1329},{7,11,727},{146,11,73},{4,11,485},{7,10,1259},\n{7,11,353},{7,11,1523},{9,10,125},{139,10,65},{5,10,136},{6,0,325},{6,11,366},{7\n,11,1384},{7,11,1601},{136,10,644},{138,11,160},{6,0,1345},{137,11,282},{18,0,91\n},{147,0,70},{136,0,404},{4,11,157},{133,11,471},{133,0,973},{6,0,135},{135,0,\n1176},{8,11,116},{11,11,551},{142,11,159},{4,0,549},{4,10,433},{133,10,719},{136\n,0,976},{5,11,160},{7,11,363},{7,11,589},{10,11,170},{141,11,55},{144,0,21},{144\n,0,51},{135,0,314},{135,10,1363},{4,11,108},{7,11,405},{10,11,491},{139,11,498},\n{146,0,4},{4,10,555},{8,10,536},{10,10,288},{139,10,1005},{135,11,1005},{6,0,281\n},{7,0,6},{8,0,282},{8,0,480},{8,0,499},{9,0,198},{10,0,143},{10,0,169},{10,0,\n211},{10,0,417},{10,0,574},{11,0,147},{11,0,395},{12,0,75},{12,0,407},{12,0,608}\n,{13,0,500},{142,0,251},{6,0,1093},{6,0,1405},{9,10,370},{138,10,90},{4,11,926},\n{133,11,983},{135,0,1776},{134,0,1528},{132,0,419},{132,11,538},{6,11,294},{7,11\n,1267},{136,11,624},{135,11,1772},{138,11,301},{4,10,257},{135,10,2031},{4,0,138\n},{7,0,1012},{7,0,1280},{7,10,1768},{137,0,76},{132,11,757},{5,0,29},{140,0,638}\n,{7,11,655},{135,11,1844},{6,11,257},{7,0,1418},{135,11,1522},{8,11,469},{138,11\n,47},{142,11,278},{6,10,83},{6,10,1733},{135,10,1389},{11,11,204},{11,11,243},{\n140,11,293},{135,11,1875},{6,0,1710},{135,0,2038},{137,11,299},{4,0,17},{5,0,23}\n,{7,0,995},{11,0,383},{11,0,437},{12,0,460},{140,0,532},{133,0,862},{137,10,696}\n,{6,0,592},{138,0,946},{138,11,599},{7,10,1718},{9,10,95},{9,10,274},{10,10,279}\n,{10,10,317},{10,10,420},{11,10,303},{11,10,808},{12,10,134},{12,10,367},{13,10,\n149},{13,10,347},{14,10,349},{14,10,406},{18,10,22},{18,10,89},{18,10,122},{147,\n10,47},{8,0,70},{12,0,171},{141,0,272},{133,10,26},{132,10,550},{137,0,812},{10,\n0,233},{139,0,76},{134,0,988},{134,0,442},{136,10,822},{4,10,902},{5,10,809},{6,\n10,122},{135,0,896},{5,11,150},{7,11,106},{8,11,603},{9,11,593},{9,11,634},{10,\n11,44},{10,11,173},{11,11,462},{11,11,515},{13,11,216},{13,11,288},{142,11,400},\n{136,0,483},{135,10,262},{5,10,620},{134,0,1709},{4,10,34},{5,10,574},{7,10,279}\n,{7,10,1624},{136,10,601},{137,10,170},{147,0,119},{12,11,108},{141,11,291},{11,\n0,69},{12,0,105},{12,0,117},{13,0,213},{14,0,13},{14,0,62},{14,0,177},{14,0,421}\n,{15,0,19},{146,0,141},{137,0,309},{11,11,278},{142,11,73},{7,0,608},{7,0,976},{\n9,0,146},{10,0,206},{10,0,596},{13,0,218},{142,0,153},{133,10,332},{6,10,261},{8\n,10,182},{139,10,943},{4,11,493},{144,11,55},{134,10,1721},{132,0,768},{4,10,933\n},{133,10,880},{7,11,555},{7,11,1316},{7,11,1412},{7,11,1839},{9,11,192},{9,11,\n589},{11,11,241},{11,11,676},{11,11,811},{11,11,891},{12,11,140},{12,11,346},{12\n,11,479},{13,11,30},{13,11,49},{13,11,381},{14,11,188},{15,11,150},{16,11,76},{\n18,11,30},{148,11,52},{4,0,518},{135,0,1136},{6,11,568},{7,11,112},{7,11,1804},{\n8,11,362},{8,11,410},{8,11,830},{9,11,514},{11,11,649},{142,11,157},{135,11,673}\n,{8,0,689},{137,0,863},{4,0,18},{4,11,625},{7,0,145},{7,0,444},{7,0,1278},{8,0,\n49},{8,0,400},{9,0,71},{9,0,250},{10,0,459},{12,0,160},{144,0,24},{140,0,1020},{\n4,0,997},{6,0,1946},{6,0,1984},{134,0,1998},{6,11,16},{6,11,158},{7,11,43},{7,11\n,129},{7,11,181},{8,11,276},{8,11,377},{10,11,523},{11,11,816},{12,11,455},{13,\n11,303},{142,11,135},{133,10,812},{134,0,658},{4,11,1},{7,11,1143},{7,11,1463},{\n8,11,61},{9,11,207},{9,11,390},{9,11,467},{139,11,836},{150,11,26},{140,0,106},{\n4,10,137},{6,0,1827},{7,10,1178},{7,10,1520},{7,11,1319},{10,0,931},{18,0,166},{\n148,0,114},{133,0,1010},{4,11,723},{5,11,895},{7,11,1031},{8,11,199},{8,11,340},\n{9,11,153},{9,11,215},{10,11,21},{10,11,59},{10,11,80},{10,11,224},{11,11,229},{\n11,11,652},{12,11,192},{13,11,146},{142,11,91},{132,11,295},{6,11,619},{7,11,898\n},{7,11,1092},{8,11,485},{18,11,28},{147,11,116},{137,11,51},{6,10,1661},{7,10,\n1975},{7,10,2009},{135,10,2011},{5,11,309},{140,11,211},{5,0,87},{7,0,313},{7,0,\n1103},{10,0,208},{10,0,582},{11,0,389},{11,0,813},{12,0,385},{13,0,286},{14,0,\n124},{146,0,108},{5,11,125},{8,11,77},{138,11,15},{132,0,267},{133,0,703},{137,\n11,155},{133,11,439},{11,11,164},{140,11,76},{5,10,89},{7,10,1915},{9,0,496},{9,\n10,185},{9,10,235},{10,10,64},{10,10,270},{10,10,403},{10,10,469},{10,10,529},{\n10,10,590},{11,10,140},{11,10,860},{13,10,1},{13,10,422},{14,10,341},{14,10,364}\n,{17,10,93},{18,10,113},{19,10,97},{147,10,113},{133,10,695},{135,0,1121},{5,10,\n6},{6,10,183},{7,10,680},{7,10,978},{7,10,1013},{7,10,1055},{12,10,230},{13,10,\n172},{146,10,29},{4,11,8},{7,11,1152},{7,11,1153},{7,11,1715},{9,11,374},{10,11,\n478},{139,11,648},{135,11,1099},{6,10,29},{139,10,63},{4,0,561},{10,0,249},{139,\n0,209},{132,0,760},{7,11,799},{138,11,511},{136,11,87},{9,0,154},{140,0,485},{\n136,0,255},{132,0,323},{140,0,419},{132,10,311},{134,10,1740},{4,0,368},{135,0,\n641},{7,10,170},{8,10,90},{8,10,177},{8,10,415},{11,10,714},{142,10,281},{4,11,\n69},{5,11,122},{9,11,656},{138,11,464},{5,11,849},{134,11,1633},{8,0,522},{142,0\n,328},{11,10,91},{13,10,129},{15,10,101},{145,10,125},{4,10,494},{6,10,74},{7,0,\n562},{7,10,44},{8,0,551},{11,11,499},{12,10,17},{15,10,5},{148,10,11},{4,10,276}\n,{133,10,296},{9,0,92},{147,0,91},{4,10,7},{5,10,90},{5,10,158},{6,10,542},{7,10\n,221},{7,10,1574},{9,10,490},{10,10,540},{11,10,443},{139,10,757},{6,0,525},{6,0\n,1976},{8,0,806},{9,0,876},{140,0,284},{5,11,859},{7,10,588},{7,11,1160},{8,11,\n107},{9,10,175},{9,11,291},{9,11,439},{10,10,530},{10,11,663},{11,11,609},{140,\n11,197},{7,11,168},{13,11,196},{141,11,237},{139,0,958},{133,0,594},{135,10,580}\n,{7,10,88},{136,10,627},{5,10,872},{6,0,479},{6,0,562},{6,10,57},{7,0,1060},{7,\n10,471},{9,10,447},{9,10,454},{141,0,6},{136,11,413},{145,11,19},{4,11,117},{6,\n11,372},{7,11,1905},{142,11,323},{4,11,722},{139,11,471},{5,10,31},{6,10,614},{\n145,0,61},{8,10,330},{140,10,477},{7,10,1200},{138,10,460},{6,10,424},{135,10,\n1866},{6,0,1641},{136,0,820},{6,0,1556},{134,0,1618},{9,11,5},{12,11,216},{12,11\n,294},{12,11,298},{12,11,400},{12,11,518},{13,11,229},{143,11,139},{15,11,155},{\n144,11,79},{4,0,302},{135,0,1766},{5,10,13},{134,10,142},{6,0,148},{7,0,1313},{7\n,10,116},{8,10,322},{8,10,755},{9,10,548},{10,10,714},{11,10,884},{141,10,324},{\n137,0,676},{9,11,88},{139,11,270},{5,11,12},{7,11,375},{137,11,438},{134,0,1674}\n,{7,10,1472},{135,10,1554},{7,10,1071},{7,10,1541},{7,10,1767},{7,10,1806},{11,0\n,178},{11,10,162},{11,10,242},{12,10,605},{15,10,26},{144,10,44},{6,0,389},{7,0,\n149},{9,0,142},{138,0,94},{140,11,71},{145,10,115},{6,0,8},{7,0,1881},{8,0,91},{\n11,11,966},{12,11,287},{13,11,342},{13,11,402},{15,11,110},{143,11,163},{4,11,\n258},{136,11,639},{6,11,22},{7,11,903},{138,11,577},{133,11,681},{135,10,1111},{\n135,11,1286},{8,10,1},{9,0,112},{138,10,326},{5,10,488},{6,10,527},{7,10,489},{7\n,10,1636},{8,10,121},{8,10,144},{8,10,359},{9,10,193},{9,10,241},{9,10,336},{9,\n10,882},{11,10,266},{11,10,372},{11,10,944},{12,10,401},{140,10,641},{4,11,664},\n{133,11,804},{6,0,747},{134,0,1015},{135,0,1746},{9,10,31},{10,10,244},{10,10,\n699},{12,10,149},{141,10,497},{133,10,377},{135,0,24},{5,11,32},{6,0,1352},{145,\n10,101},{7,0,1530},{10,0,158},{13,0,13},{13,0,137},{13,0,258},{14,0,111},{14,0,\n225},{14,0,253},{14,0,304},{14,0,339},{14,0,417},{146,0,33},{4,0,503},{135,0,\n1661},{5,0,130},{6,0,845},{7,0,1314},{9,0,610},{10,0,718},{11,0,601},{11,0,819},\n{11,0,946},{140,0,536},{10,0,149},{11,0,280},{142,0,336},{134,0,1401},{135,0,\n1946},{8,0,663},{144,0,8},{134,0,1607},{135,10,2023},{4,11,289},{7,11,629},{7,11\n,1698},{7,11,1711},{140,11,215},{6,11,450},{136,11,109},{10,0,882},{10,0,883},{\n10,0,914},{138,0,928},{133,10,843},{136,11,705},{132,10,554},{133,10,536},{5,0,\n417},{9,10,79},{11,10,625},{145,10,7},{7,11,1238},{142,11,37},{4,0,392},{135,0,\n1597},{4,10,424},{5,0,433},{9,0,633},{139,0,629},{7,10,336},{136,10,785},{134,11\n,355},{6,0,234},{7,0,769},{9,0,18},{138,0,358},{4,10,896},{134,10,1777},{138,11,\n323},{7,0,140},{7,0,1950},{8,0,680},{11,0,817},{147,0,88},{7,0,1222},{138,0,386}\n,{139,11,908},{11,0,249},{12,0,313},{16,0,66},{145,0,26},{134,0,5},{7,10,750},{9\n,10,223},{11,10,27},{11,10,466},{12,10,624},{14,10,265},{146,10,61},{134,11,26},\n{134,0,1216},{5,0,963},{134,0,1773},{4,11,414},{5,11,467},{9,11,654},{10,11,451}\n,{12,11,59},{141,11,375},{135,11,17},{4,10,603},{133,10,661},{4,10,11},{6,10,128\n},{7,10,231},{7,10,1533},{138,10,725},{135,11,955},{7,0,180},{8,0,509},{136,0,\n792},{132,10,476},{132,0,1002},{133,11,538},{135,10,1807},{132,0,931},{7,0,943},\n{11,0,614},{140,0,747},{135,0,1837},{9,10,20},{10,10,324},{10,10,807},{139,10,\n488},{134,0,641},{6,11,280},{10,11,502},{11,11,344},{140,11,38},{5,11,45},{7,11,\n1161},{11,11,448},{11,11,880},{13,11,139},{13,11,407},{15,11,16},{17,11,95},{18,\n11,66},{18,11,88},{18,11,123},{149,11,7},{9,0,280},{138,0,134},{22,0,22},{23,0,5\n},{151,0,29},{136,11,777},{4,0,90},{4,11,410},{5,0,545},{7,0,754},{7,11,521},{9,\n0,186},{10,0,72},{10,0,782},{11,0,577},{11,0,610},{11,0,960},{12,0,354},{12,0,\n362},{140,0,595},{135,11,1778},{5,10,112},{6,10,103},{134,10,150},{138,10,356},{\n132,0,742},{7,0,151},{9,0,329},{139,0,254},{8,0,853},{8,0,881},{8,0,911},{8,0,\n912},{10,0,872},{12,0,741},{12,0,742},{152,0,18},{4,11,573},{136,11,655},{6,0,\n921},{134,0,934},{9,0,187},{10,0,36},{11,0,1016},{17,0,44},{146,0,64},{7,0,833},\n{136,0,517},{4,0,506},{5,0,295},{135,0,1680},{4,10,708},{8,10,15},{9,10,50},{9,\n10,386},{11,10,18},{11,10,529},{140,10,228},{4,10,563},{7,0,251},{7,0,1701},{7,\n10,592},{7,10,637},{7,10,770},{8,0,436},{8,10,463},{9,10,60},{9,10,335},{9,10,\n904},{10,10,73},{11,10,434},{12,10,585},{13,10,331},{18,10,110},{148,10,60},{132\n,10,502},{136,0,584},{6,10,347},{138,10,161},{7,0,987},{7,11,899},{9,0,688},{10,\n0,522},{11,0,788},{12,0,137},{12,0,566},{14,0,9},{14,0,24},{14,0,64},{142,11,325\n},{4,0,214},{5,0,500},{5,10,102},{6,10,284},{7,10,1079},{7,10,1423},{7,10,1702},\n{8,10,470},{9,10,554},{9,10,723},{139,10,333},{7,10,246},{135,10,840},{6,10,10},\n{8,10,571},{9,10,739},{143,10,91},{133,10,626},{146,0,195},{134,0,1775},{7,0,389\n},{7,0,700},{7,0,940},{8,0,514},{9,0,116},{9,0,535},{10,0,118},{11,0,107},{11,0,\n148},{11,0,922},{12,0,254},{12,0,421},{142,0,238},{5,10,18},{6,10,526},{13,10,24\n},{13,10,110},{19,10,5},{147,10,44},{132,0,743},{4,10,309},{5,10,462},{7,10,970}\n,{7,10,1097},{139,0,292},{22,10,30},{150,10,33},{139,11,338},{135,11,1598},{7,0,\n1283},{9,0,227},{11,0,325},{11,0,408},{14,0,180},{146,0,47},{4,0,953},{6,0,1805}\n,{6,0,1814},{6,0,1862},{140,0,774},{6,11,611},{135,11,1733},{135,11,1464},{5,0,\n81},{7,0,146},{7,0,1342},{8,0,53},{8,0,561},{8,0,694},{8,0,754},{9,0,115},{9,0,\n179},{9,0,894},{10,0,462},{10,0,813},{11,0,230},{11,0,657},{11,0,699},{11,0,748}\n,{12,0,119},{12,0,200},{12,0,283},{142,0,273},{5,0,408},{6,0,789},{6,0,877},{6,0\n,1253},{6,0,1413},{137,0,747},{134,10,1704},{135,11,663},{6,0,1910},{6,0,1915},{\n6,0,1923},{9,0,913},{9,0,928},{9,0,950},{9,0,954},{9,0,978},{9,0,993},{12,0,812}\n,{12,0,819},{12,0,831},{12,0,833},{12,0,838},{12,0,909},{12,0,928},{12,0,931},{\n12,0,950},{15,0,186},{15,0,187},{15,0,195},{15,0,196},{15,0,209},{15,0,215},{15,\n0,236},{15,0,241},{15,0,249},{15,0,253},{18,0,180},{18,0,221},{18,0,224},{18,0,\n227},{18,0,229},{149,0,60},{7,0,1826},{135,0,1938},{5,10,86},{7,10,743},{9,10,85\n},{10,10,281},{10,10,432},{11,0,490},{12,10,251},{13,10,118},{14,10,378},{146,0,\n143},{5,10,524},{133,10,744},{141,11,442},{10,10,107},{140,10,436},{135,11,503},\n{134,0,1162},{132,10,927},{7,0,30},{8,0,86},{8,0,315},{8,0,700},{9,0,576},{9,0,\n858},{10,0,414},{11,0,310},{11,0,888},{11,0,904},{12,0,361},{12,10,670},{13,0,\n248},{13,0,371},{14,0,142},{146,10,94},{134,0,721},{4,11,113},{5,11,163},{5,11,\n735},{7,10,1149},{7,11,1009},{9,10,156},{9,11,9},{9,11,771},{12,11,90},{13,11,\n138},{13,11,410},{143,11,128},{138,0,839},{133,10,778},{137,0,617},{133,10,502},\n{8,10,196},{10,10,283},{139,10,406},{6,0,428},{7,0,524},{8,0,169},{8,0,234},{9,0\n,480},{138,0,646},{133,10,855},{134,0,1648},{7,0,1205},{138,0,637},{4,11,935},{5\n,11,823},{135,0,1596},{5,11,269},{7,11,434},{7,11,891},{8,11,339},{9,11,702},{11\n,11,594},{11,11,718},{145,11,100},{7,11,878},{9,11,485},{141,11,264},{4,0,266},{\n6,11,1713},{8,0,4},{9,0,39},{10,0,166},{11,0,918},{12,0,635},{20,0,10},{22,0,27}\n,{22,0,43},{150,0,52},{7,10,1400},{9,10,446},{138,10,45},{135,11,900},{132,0,862\n},{134,0,1554},{135,11,1033},{19,0,16},{147,11,16},{135,11,1208},{7,0,157},{136,\n0,279},{6,0,604},{136,0,391},{13,10,455},{15,10,99},{15,10,129},{144,10,68},{135\n,10,172},{7,0,945},{11,0,713},{139,0,744},{4,0,973},{10,0,877},{10,0,937},{10,0,\n938},{140,0,711},{139,0,1022},{132,10,568},{142,11,143},{4,0,567},{4,10,732},{\n137,0,859},{7,0,1846},{136,0,628},{136,10,733},{133,0,762},{4,10,428},{135,10,\n1789},{7,10,2015},{10,0,784},{12,10,665},{141,0,191},{133,0,298},{7,0,633},{7,0,\n905},{7,0,909},{7,0,1538},{9,0,767},{140,0,636},{138,10,806},{132,0,795},{139,0,\n301},{135,0,1970},{5,11,625},{135,11,1617},{135,11,275},{7,11,37},{8,11,425},{8,\n11,693},{9,11,720},{10,11,380},{10,11,638},{11,11,273},{11,11,307},{11,11,473},{\n12,11,61},{143,11,43},{135,11,198},{134,0,1236},{7,0,369},{12,0,644},{12,0,645},\n{144,0,90},{19,0,15},{149,0,27},{6,0,71},{6,10,1623},{6,10,1681},{7,0,845},{8,0,\n160},{137,0,318},{134,0,1447},{134,0,1255},{138,0,735},{4,11,168},{136,0,76},{6,\n10,1748},{8,10,715},{9,10,802},{10,10,46},{10,10,819},{13,10,308},{14,10,351},{\n14,10,363},{146,10,67},{135,11,91},{4,10,63},{5,10,347},{134,0,474},{133,10,749}\n,{138,0,841},{133,10,366},{4,11,225},{134,0,836},{135,0,1622},{135,10,89},{140,0\n,735},{134,0,1601},{138,11,145},{6,0,1390},{137,0,804},{142,0,394},{6,11,15},{7,\n11,70},{10,11,240},{147,11,93},{6,0,96},{135,0,1426},{4,0,651},{133,0,289},{7,10\n,977},{7,11,956},{7,11,1157},{7,11,1506},{7,11,1606},{7,11,1615},{7,11,1619},{7,\n11,1736},{7,11,1775},{8,11,590},{9,11,324},{9,11,736},{9,11,774},{9,11,776},{9,\n11,784},{10,11,567},{10,11,708},{11,11,518},{11,11,613},{11,11,695},{11,11,716},\n{11,11,739},{11,11,770},{11,11,771},{11,11,848},{11,11,857},{11,11,931},{11,11,\n947},{12,11,326},{12,11,387},{12,11,484},{12,11,528},{12,11,552},{12,11,613},{13\n,11,189},{13,11,256},{13,11,340},{13,11,432},{13,11,436},{13,11,440},{13,11,454}\n,{14,11,174},{14,11,220},{14,11,284},{14,11,390},{145,11,121},{7,0,688},{8,0,35}\n,{9,0,511},{10,0,767},{147,0,118},{134,0,667},{4,0,513},{5,10,824},{133,10,941},\n{7,10,440},{8,10,230},{139,10,106},{134,0,2034},{135,11,1399},{143,11,66},{135,\n11,1529},{4,11,145},{6,11,176},{7,11,395},{9,11,562},{144,11,28},{132,11,501},{\n132,0,704},{134,0,1524},{6,11,464},{135,0,1078},{6,11,509},{10,11,82},{20,11,91}\n,{151,11,13},{4,0,720},{133,0,306},{133,0,431},{4,10,914},{5,10,800},{5,10,852},\n{135,0,1196},{135,11,1189},{10,0,54},{141,10,115},{7,10,564},{142,10,168},{4,10,\n918},{5,0,464},{5,10,876},{6,0,236},{7,0,696},{7,0,914},{7,0,1108},{7,0,1448},{9\n,0,15},{9,0,564},{10,0,14},{12,0,565},{13,0,449},{14,0,53},{15,0,13},{16,0,64},{\n145,0,41},{6,0,1418},{134,10,1764},{4,10,92},{133,10,274},{134,0,907},{4,11,114}\n,{8,10,501},{9,11,492},{13,11,462},{142,11,215},{4,11,77},{5,11,361},{6,11,139},\n{6,11,401},{6,11,404},{7,11,413},{7,11,715},{7,11,1716},{11,11,279},{12,11,179},\n{12,11,258},{13,11,244},{142,11,358},{6,0,1767},{12,0,194},{145,0,107},{134,11,\n1717},{5,10,743},{142,11,329},{4,10,49},{7,10,280},{135,10,1633},{5,0,840},{7,11\n,1061},{8,11,82},{11,11,250},{12,11,420},{141,11,184},{135,11,724},{134,0,900},{\n136,10,47},{134,0,1436},{144,11,0},{5,10,272},{5,10,908},{5,10,942},{6,0,675},{7\n,0,1008},{7,0,1560},{8,10,197},{9,0,642},{9,10,47},{11,0,236},{11,10,538},{11,10\n,742},{142,0,193},{4,0,68},{5,0,628},{5,0,634},{6,0,386},{7,0,794},{8,0,273},{9,\n0,563},{10,0,105},{10,0,171},{11,0,94},{139,0,354},{135,10,1911},{137,10,891},{4\n,0,95},{6,0,1297},{6,0,1604},{7,0,416},{139,0,830},{6,11,513},{135,11,1052},{7,0\n,731},{13,0,20},{143,0,11},{137,11,899},{10,0,850},{140,0,697},{4,0,662},{7,11,\n1417},{12,11,382},{17,11,48},{152,11,12},{133,0,736},{132,0,861},{4,10,407},{132\n,10,560},{141,10,490},{6,11,545},{7,11,565},{7,11,1669},{10,11,114},{11,11,642},\n{140,11,618},{6,0,871},{134,0,1000},{5,0,864},{5,11,5},{10,0,648},{11,0,671},{\n143,0,46},{133,0,928},{4,10,475},{11,0,90},{11,10,35},{13,0,7},{13,10,71},{13,10\n,177},{142,10,422},{136,0,332},{135,11,192},{134,0,1055},{136,11,763},{11,0,986}\n,{140,0,682},{7,0,76},{8,0,44},{9,0,884},{10,0,580},{11,0,399},{11,0,894},{143,0\n,122},{135,11,1237},{135,10,636},{6,10,222},{7,10,1620},{8,10,409},{9,10,693},{\n139,0,300},{4,11,87},{5,11,250},{10,11,601},{13,11,298},{13,11,353},{141,11,376}\n,{5,0,518},{10,0,340},{11,0,175},{149,0,16},{140,0,771},{6,0,1108},{137,0,831},{\n132,0,836},{135,0,1852},{4,0,957},{6,0,1804},{8,0,842},{8,0,843},{8,0,851},{8,0,\n855},{140,0,767},{135,11,814},{4,11,57},{7,11,1195},{7,11,1438},{7,11,1548},{7,\n11,1835},{7,11,1904},{9,11,757},{10,11,604},{139,11,519},{133,10,882},{138,0,246\n},{4,0,934},{5,0,202},{7,11,1897},{8,0,610},{12,11,290},{13,11,80},{13,11,437},{\n145,11,74},{8,0,96},{9,0,36},{10,0,607},{10,0,804},{10,0,832},{11,0,423},{11,0,\n442},{12,0,309},{14,0,199},{15,0,90},{145,0,110},{132,10,426},{6,10,58},{7,0,654\n},{7,10,745},{7,10,1969},{8,0,240},{8,10,675},{9,10,479},{9,10,731},{10,10,330},\n{10,10,593},{10,10,817},{11,10,32},{11,10,133},{11,10,221},{145,10,68},{9,0,13},\n{9,0,398},{9,0,727},{10,0,75},{10,0,184},{10,0,230},{10,0,564},{10,0,569},{11,0,\n973},{12,0,70},{12,0,189},{13,0,57},{141,0,257},{4,11,209},{135,11,902},{7,0,391\n},{137,10,538},{134,0,403},{6,11,303},{7,11,335},{7,11,1437},{7,11,1668},{8,11,\n553},{8,11,652},{8,11,656},{9,11,558},{11,11,743},{149,11,18},{132,11,559},{11,0\n,75},{142,0,267},{6,0,815},{141,11,2},{141,0,366},{137,0,631},{133,11,1017},{5,0\n,345},{135,0,1016},{133,11,709},{134,11,1745},{133,10,566},{6,10,48},{7,0,952},{\n9,10,139},{10,10,399},{11,10,469},{12,10,634},{141,10,223},{133,0,673},{7,11,8},\n{8,11,206},{137,0,850},{6,0,662},{149,0,35},{4,0,287},{133,0,1018},{6,10,114},{7\n,10,1224},{7,10,1556},{136,10,3},{8,10,576},{137,10,267},{4,0,884},{5,0,34},{10,\n0,724},{12,0,444},{13,0,354},{18,0,32},{23,0,24},{23,0,31},{152,0,5},{133,10,933\n},{132,11,776},{138,0,151},{136,0,427},{134,0,382},{132,0,329},{9,0,846},{10,0,\n827},{138,11,33},{7,11,1297},{9,0,279},{10,0,407},{14,0,84},{150,0,18},{136,11,\n406},{132,0,906},{136,0,366},{134,0,843},{134,0,1443},{135,0,1372},{138,0,992},{\n4,0,123},{5,0,605},{7,0,1509},{136,0,36},{132,0,649},{8,11,175},{10,11,168},{138\n,11,573},{133,0,767},{134,0,1018},{135,11,1305},{12,10,30},{13,10,148},{14,10,87\n},{14,10,182},{16,10,42},{148,10,70},{134,11,607},{4,0,273},{5,0,658},{133,0,995\n},{6,0,72},{139,11,174},{7,10,56},{7,10,1989},{8,10,337},{8,10,738},{9,10,600},{\n10,0,483},{12,0,368},{13,10,447},{142,10,92},{5,11,784},{138,10,666},{135,0,1345\n},{139,11,882},{134,0,1293},{133,0,589},{134,0,1988},{5,0,117},{6,0,514},{6,0,\n541},{7,0,1164},{7,0,1436},{8,0,220},{8,0,648},{10,0,688},{139,0,560},{136,0,379\n},{5,0,686},{7,10,866},{135,10,1163},{132,10,328},{9,11,14},{9,11,441},{10,11,\n306},{139,11,9},{4,10,101},{135,10,1171},{5,10,833},{136,10,744},{5,11,161},{7,\n11,839},{135,11,887},{7,0,196},{10,0,765},{11,0,347},{11,0,552},{11,0,790},{12,0\n,263},{13,0,246},{13,0,270},{13,0,395},{14,0,176},{14,0,190},{14,0,398},{14,0,\n412},{15,0,32},{15,0,63},{16,0,88},{147,0,105},{6,10,9},{6,10,397},{7,10,53},{7,\n10,1742},{10,10,632},{11,10,828},{140,10,146},{5,0,381},{135,0,1792},{134,0,1452\n},{135,11,429},{8,0,367},{10,0,760},{14,0,79},{20,0,17},{152,0,0},{7,0,616},{138\n,0,413},{11,10,417},{12,10,223},{140,10,265},{7,11,1611},{13,11,14},{15,11,44},{\n19,11,13},{148,11,76},{135,0,1229},{6,0,120},{7,0,1188},{7,0,1710},{8,0,286},{9,\n0,667},{11,0,592},{139,0,730},{135,11,1814},{135,0,1146},{4,10,186},{5,10,157},{\n8,10,168},{138,10,6},{4,0,352},{135,0,687},{4,0,192},{5,0,49},{6,0,200},{6,0,293\n},{6,0,1696},{135,0,1151},{133,10,875},{5,10,773},{5,10,991},{6,10,1635},{134,10\n,1788},{7,10,111},{136,10,581},{6,0,935},{134,0,1151},{134,0,1050},{132,0,650},{\n132,0,147},{11,0,194},{11,11,194},{12,0,62},{12,0,88},{12,11,62},{140,11,88},{6,\n0,339},{135,0,923},{134,10,1747},{7,11,643},{136,11,236},{133,0,934},{7,10,1364}\n,{7,10,1907},{141,10,158},{132,10,659},{4,10,404},{135,10,675},{7,11,581},{9,11,\n644},{137,11,699},{13,0,211},{14,0,133},{14,0,204},{15,0,64},{15,0,69},{15,0,114\n},{16,0,10},{19,0,23},{19,0,35},{19,0,39},{19,0,51},{19,0,71},{19,0,75},{152,0,\n15},{133,10,391},{5,11,54},{135,11,1513},{5,10,540},{6,10,1697},{7,0,222},{136,0\n,341},{134,10,78},{132,11,744},{136,0,293},{137,11,701},{7,11,930},{10,11,402},{\n10,11,476},{13,11,452},{18,11,55},{147,11,104},{132,0,637},{133,10,460},{8,11,50\n},{137,11,624},{132,11,572},{134,0,1159},{4,10,199},{139,10,34},{134,0,847},{134\n,10,388},{6,11,43},{7,11,38},{8,11,248},{9,11,504},{138,11,513},{4,10,511},{6,10\n,608},{9,0,683},{9,10,333},{10,10,602},{11,10,441},{11,10,723},{11,10,976},{140,\n10,357},{9,0,867},{138,0,837},{6,0,944},{135,11,326},{135,0,1809},{5,10,938},{7,\n11,783},{136,10,707},{133,11,766},{133,11,363},{6,0,170},{7,0,1080},{8,0,395},{8\n,0,487},{141,0,147},{6,11,258},{140,11,409},{4,0,535},{5,11,249},{8,0,618},{148,\n11,82},{6,0,1379},{149,11,15},{135,0,1625},{150,0,23},{5,11,393},{6,11,378},{7,\n11,1981},{9,11,32},{9,11,591},{10,11,685},{10,11,741},{142,11,382},{133,11,788},\n{7,11,1968},{10,11,19},{139,11,911},{7,11,1401},{135,11,1476},{4,11,61},{5,11,58\n},{5,11,171},{5,11,635},{5,11,683},{5,11,700},{6,11,291},{6,11,566},{7,11,1650},\n{11,11,523},{12,11,273},{12,11,303},{15,11,39},{143,11,111},{6,10,469},{7,10,\n1709},{138,10,515},{4,0,778},{134,11,589},{132,0,46},{5,0,811},{6,0,1679},{6,0,\n1714},{135,0,2032},{7,0,1458},{9,0,407},{11,0,15},{12,0,651},{149,0,37},{4,10,\n500},{135,0,938},{6,0,34},{7,0,69},{7,0,1089},{7,0,1281},{8,0,708},{8,0,721},{9,\n0,363},{148,0,98},{10,11,231},{147,11,124},{7,11,726},{152,11,9},{5,10,68},{134,\n10,383},{136,11,583},{4,11,917},{133,11,1005},{11,10,216},{139,10,340},{135,11,\n1675},{8,0,441},{10,0,314},{143,0,3},{132,11,919},{4,10,337},{6,10,353},{7,10,\n1934},{8,10,488},{137,10,429},{7,0,889},{7,10,1795},{8,10,259},{9,10,135},{9,10,\n177},{9,10,860},{10,10,825},{11,10,115},{11,10,370},{11,10,405},{11,10,604},{12,\n10,10},{12,10,667},{12,10,669},{13,10,76},{14,10,310},{15,10,76},{15,10,147},{\n148,10,23},{4,10,15},{4,11,255},{5,10,22},{5,11,302},{6,10,244},{6,11,132},{7,10\n,40},{7,10,200},{7,10,906},{7,10,1199},{7,11,128},{7,11,283},{7,11,1299},{9,10,\n616},{10,10,716},{10,11,52},{10,11,514},{11,10,635},{11,10,801},{11,11,925},{12,\n10,458},{13,11,92},{142,11,309},{132,0,462},{137,11,173},{135,10,1735},{5,10,598\n},{7,10,791},{8,0,525},{8,10,108},{137,10,123},{5,0,73},{6,0,23},{134,0,338},{\n132,0,676},{132,10,683},{7,0,725},{8,0,498},{139,0,268},{12,0,21},{151,0,7},{135\n,0,773},{4,10,155},{135,10,1689},{4,0,164},{5,0,730},{5,10,151},{5,10,741},{6,11\n,210},{7,10,498},{7,10,870},{7,10,1542},{12,10,213},{14,10,36},{14,10,391},{17,\n10,111},{18,10,6},{18,10,46},{18,10,151},{19,10,36},{20,10,32},{20,10,56},{20,10\n,69},{20,10,102},{21,10,4},{22,10,8},{22,10,10},{22,10,14},{150,10,31},{4,10,624\n},{135,10,1752},{4,0,583},{6,11,588},{9,0,936},{15,0,214},{18,0,199},{152,0,26},\n{4,11,284},{6,11,223},{7,0,1462},{139,0,659},{133,0,220},{139,0,803},{132,0,544}\n,{4,10,492},{133,10,451},{16,0,98},{148,0,119},{4,11,218},{7,11,526},{143,11,137\n},{135,10,835},{4,11,270},{5,11,192},{6,11,332},{7,11,1322},{13,10,70},{13,11,9}\n,{14,11,104},{142,11,311},{132,10,539},{140,11,661},{5,0,176},{6,0,437},{6,0,564\n},{11,0,181},{141,0,183},{135,0,1192},{6,10,113},{135,10,436},{136,10,718},{135,\n10,520},{135,0,1878},{140,11,196},{7,11,379},{8,11,481},{137,11,377},{5,11,1003}\n,{6,11,149},{137,11,746},{8,11,262},{9,11,627},{10,11,18},{11,11,214},{11,11,404\n},{11,11,457},{11,11,780},{11,11,849},{11,11,913},{13,11,330},{13,11,401},{142,\n11,200},{149,0,26},{136,11,304},{132,11,142},{135,0,944},{4,0,790},{5,0,273},{\n134,0,394},{134,0,855},{4,0,135},{6,0,127},{7,0,1185},{7,0,1511},{8,0,613},{11,0\n,5},{12,0,336},{12,0,495},{12,0,586},{12,0,660},{12,0,668},{14,0,385},{15,0,118}\n,{17,0,20},{146,0,98},{6,0,230},{9,0,752},{12,10,610},{13,10,431},{16,10,59},{\n146,0,109},{7,0,1954},{135,11,925},{4,11,471},{5,11,51},{6,11,602},{8,11,484},{\n10,11,195},{140,11,159},{132,10,307},{136,11,688},{132,11,697},{7,11,812},{7,11,\n1261},{7,11,1360},{9,11,632},{140,11,352},{5,0,162},{5,10,964},{136,0,68},{4,0,\n654},{136,11,212},{4,0,156},{7,0,998},{7,0,1045},{7,0,1860},{9,0,48},{9,0,692},{\n11,0,419},{139,0,602},{133,11,221},{4,11,373},{5,11,283},{6,11,480},{135,11,609}\n,{142,11,216},{132,0,240},{6,11,192},{9,11,793},{145,11,55},{4,10,75},{5,10,180}\n,{6,10,500},{7,10,58},{7,10,710},{138,10,645},{4,11,132},{5,10,649},{5,11,69},{\n135,11,1242},{6,10,276},{7,10,282},{7,10,879},{7,10,924},{8,10,459},{9,10,599},{\n9,10,754},{11,10,574},{12,10,128},{12,10,494},{13,10,52},{13,10,301},{15,10,30},\n{143,10,132},{132,10,200},{4,11,111},{135,11,302},{9,0,197},{10,0,300},{12,0,473\n},{13,0,90},{141,0,405},{132,11,767},{6,11,42},{7,11,1416},{7,11,1590},{7,11,\n2005},{8,11,131},{8,11,466},{9,11,672},{13,11,252},{148,11,103},{8,0,958},{8,0,\n999},{10,0,963},{138,0,1001},{135,10,1621},{135,0,858},{4,0,606},{137,11,444},{6\n,11,44},{136,11,368},{139,11,172},{4,11,570},{133,11,120},{139,11,624},{6,10,225\n},{7,0,1978},{8,0,676},{137,10,211},{7,0,972},{8,10,687},{139,0,102},{6,11,227},\n{135,11,1589},{8,10,58},{9,10,724},{11,10,809},{13,10,113},{145,10,72},{4,0,361}\n,{133,0,315},{132,0,461},{6,10,345},{135,10,1247},{132,0,472},{8,10,767},{8,10,\n803},{9,10,301},{137,10,903},{135,11,1333},{135,11,477},{7,10,1949},{136,10,674}\n,{6,0,905},{138,0,747},{133,0,155},{134,10,259},{7,0,163},{8,0,319},{9,0,402},{\n10,0,24},{10,0,681},{11,0,200},{12,0,253},{12,0,410},{142,0,219},{5,0,475},{6,11\n,1667},{7,0,1780},{7,11,2036},{9,0,230},{10,11,600},{11,0,297},{11,0,558},{14,0,\n322},{147,0,76},{136,10,254},{6,0,848},{135,0,1956},{6,11,511},{140,11,132},{5,\n11,568},{6,11,138},{135,11,1293},{6,0,631},{137,0,838},{149,0,36},{4,11,565},{8,\n11,23},{136,11,827},{5,0,944},{134,0,1769},{4,0,144},{4,11,922},{5,11,1023},{6,0\n,842},{134,0,1400},{133,10,248},{9,10,800},{10,10,693},{11,10,482},{11,10,734},{\n139,10,789},{7,11,1002},{139,11,145},{4,10,116},{5,10,95},{5,10,445},{7,10,1688}\n,{8,10,29},{9,10,272},{11,10,509},{139,10,915},{14,0,369},{146,0,72},{135,10,\n1641},{132,11,740},{133,10,543},{140,11,116},{5,10,181},{6,0,247},{8,10,41},{137\n,0,555},{133,10,657},{136,0,996},{138,10,709},{7,0,189},{8,10,202},{138,10,536},\n{136,11,402},{4,11,716},{141,11,31},{10,0,280},{138,0,797},{9,10,423},{140,10,89\n},{8,10,113},{9,10,877},{10,10,554},{11,10,83},{12,10,136},{147,10,109},{133,10,\n976},{4,10,206},{135,0,746},{136,0,526},{139,0,345},{136,0,1017},{8,11,152},{9,\n11,53},{9,11,268},{9,11,901},{10,11,518},{10,11,829},{11,11,188},{13,11,74},{14,\n11,46},{15,11,17},{15,11,33},{17,11,40},{18,11,36},{19,11,20},{22,11,1},{152,11,\n2},{133,11,736},{136,11,532},{5,0,428},{138,0,651},{135,11,681},{135,0,1162},{7,\n0,327},{8,10,226},{10,10,537},{11,10,570},{11,10,605},{11,10,799},{11,10,804},{\n12,10,85},{12,10,516},{12,10,623},{12,11,677},{13,0,230},{13,10,361},{14,10,77},\n{14,10,78},{17,0,113},{147,10,110},{4,0,792},{4,10,769},{7,0,1717},{138,0,546},{\n4,11,684},{136,11,384},{132,10,551},{134,0,1203},{9,10,57},{9,10,459},{10,10,425\n},{11,10,119},{12,10,184},{12,10,371},{13,10,358},{145,10,51},{5,0,672},{5,10,\n814},{8,10,10},{9,10,421},{9,10,729},{10,10,609},{139,10,689},{138,0,189},{134,\n10,624},{7,11,110},{7,11,188},{8,11,290},{8,11,591},{9,11,382},{9,11,649},{11,11\n,71},{11,11,155},{11,11,313},{12,11,5},{13,11,325},{142,11,287},{133,0,99},{6,0,\n1053},{135,0,298},{7,11,360},{7,11,425},{9,11,66},{9,11,278},{138,11,644},{4,0,\n397},{136,0,555},{137,10,269},{132,10,528},{4,11,900},{133,11,861},{5,11,254},{6\n,0,1157},{7,11,985},{136,11,73},{7,11,1959},{136,11,683},{12,0,398},{20,0,39},{\n21,0,11},{150,0,41},{4,0,485},{7,0,353},{135,0,1523},{6,0,366},{7,0,1384},{135,0\n,1601},{138,0,787},{137,0,282},{5,10,104},{6,10,173},{135,10,1631},{139,11,146},\n{4,0,157},{133,0,471},{134,0,941},{132,11,725},{7,0,1336},{8,10,138},{8,10,342},\n{9,10,84},{10,10,193},{11,10,883},{140,10,359},{134,11,196},{136,0,116},{133,11,\n831},{134,0,787},{134,10,95},{6,10,406},{10,10,409},{10,10,447},{11,10,44},{140,\n10,100},{5,0,160},{7,0,363},{7,0,589},{10,0,170},{141,0,55},{134,0,1815},{132,0,\n866},{4,11,321},{6,0,889},{6,0,1067},{6,0,1183},{134,11,569},{5,11,848},{134,11,\n66},{4,11,36},{6,10,1636},{7,11,1387},{10,11,205},{11,11,755},{141,11,271},{132,\n0,689},{4,10,282},{7,10,1034},{9,0,820},{11,10,398},{11,10,634},{12,10,1},{12,10\n,79},{12,10,544},{14,10,237},{17,10,10},{146,10,20},{4,0,108},{7,0,804},{139,0,\n498},{132,11,887},{6,0,1119},{135,11,620},{6,11,165},{138,11,388},{5,0,244},{5,\n10,499},{6,10,476},{7,10,600},{7,10,888},{135,10,1096},{140,0,609},{135,0,1005},\n{4,0,412},{133,0,581},{4,11,719},{135,11,155},{7,10,296},{7,10,596},{8,10,560},{\n8,10,586},{9,10,612},{11,10,304},{12,10,46},{13,10,89},{14,10,112},{145,10,122},\n{4,0,895},{133,0,772},{142,11,307},{135,0,1898},{4,0,926},{133,0,983},{4,11,353}\n,{6,11,146},{6,11,1789},{7,11,288},{7,11,990},{7,11,1348},{9,11,665},{9,11,898},\n{11,11,893},{142,11,212},{132,0,538},{133,11,532},{6,0,294},{7,0,1267},{8,0,624}\n,{141,0,496},{4,11,45},{7,0,1325},{135,11,1257},{138,0,301},{7,10,1599},{7,10,\n1723},{8,10,79},{8,10,106},{8,10,190},{8,10,302},{8,10,383},{8,10,713},{9,0,298}\n,{9,10,119},{9,10,233},{9,10,419},{9,10,471},{10,10,181},{10,10,406},{11,10,57},\n{11,10,85},{11,10,120},{11,10,177},{11,10,296},{11,10,382},{11,10,454},{11,10,\n758},{11,10,999},{12,0,291},{12,10,27},{12,10,131},{12,10,245},{12,10,312},{12,\n10,446},{12,10,454},{13,0,276},{13,10,98},{13,10,426},{13,10,508},{14,0,6},{14,\n10,163},{14,10,272},{14,10,277},{14,10,370},{15,10,95},{15,10,138},{15,10,167},{\n17,0,18},{17,10,38},{20,10,96},{149,0,32},{132,0,757},{134,0,1263},{4,0,820},{\n134,10,1759},{133,0,722},{136,11,816},{138,10,372},{145,10,16},{134,0,1039},{4,0\n,991},{134,0,2028},{133,10,258},{7,0,1875},{139,0,124},{6,11,559},{6,11,1691},{\n135,11,586},{5,0,324},{7,0,881},{8,10,134},{9,10,788},{140,10,438},{7,11,1823},{\n139,11,693},{6,0,1348},{134,0,1545},{134,0,911},{132,0,954},{7,10,1948},{7,10,\n2004},{8,0,329},{136,0,414},{5,0,517},{6,10,439},{7,10,780},{135,10,1040},{132,0\n,816},{5,10,1},{6,10,81},{138,10,520},{5,10,482},{8,10,98},{9,0,713},{10,0,222},\n{10,10,700},{10,10,822},{11,10,302},{11,10,778},{12,10,50},{12,10,127},{12,10,\n396},{13,10,62},{13,10,328},{14,10,122},{147,10,72},{137,0,33},{5,10,2},{7,10,\n1494},{136,10,589},{6,10,512},{7,10,797},{8,10,253},{9,10,77},{10,10,1},{10,10,\n129},{10,10,225},{10,11,108},{11,10,118},{11,10,226},{11,10,251},{11,10,430},{11\n,10,701},{11,10,974},{11,10,982},{11,11,116},{12,10,64},{12,10,260},{12,10,488},\n{140,10,690},{134,11,456},{133,11,925},{5,0,150},{7,0,106},{7,0,774},{8,0,603},{\n9,0,593},{9,0,634},{10,0,44},{10,0,173},{11,0,462},{11,0,515},{13,0,216},{13,0,\n288},{142,0,400},{137,10,347},{5,0,748},{134,0,553},{12,0,108},{141,0,291},{4,10\n,12},{7,0,420},{7,10,522},{7,10,809},{8,10,797},{141,10,88},{6,11,193},{7,11,240\n},{7,11,1682},{10,11,51},{10,11,640},{11,11,410},{13,11,82},{14,11,247},{14,11,\n331},{142,11,377},{133,10,528},{135,0,1777},{4,0,493},{144,0,55},{136,11,633},{\n139,0,81},{6,0,980},{136,0,321},{148,10,109},{5,10,266},{9,10,290},{9,10,364},{\n10,10,293},{11,10,606},{142,10,45},{6,0,568},{7,0,112},{7,0,1804},{8,0,362},{8,0\n,410},{8,0,830},{9,0,514},{11,0,649},{142,0,157},{4,0,74},{6,0,510},{6,10,594},{\n9,10,121},{10,10,49},{10,10,412},{139,10,834},{134,0,838},{136,10,748},{132,10,\n466},{132,0,625},{135,11,1443},{4,11,237},{135,11,514},{9,10,378},{141,10,162},{\n6,0,16},{6,0,158},{7,0,43},{7,0,129},{7,0,181},{8,0,276},{8,0,377},{10,0,523},{\n11,0,816},{12,0,455},{13,0,303},{142,0,135},{135,0,281},{4,0,1},{7,0,1143},{7,0,\n1463},{8,0,61},{9,0,207},{9,0,390},{9,0,467},{139,0,836},{6,11,392},{7,11,65},{\n135,11,2019},{132,10,667},{4,0,723},{5,0,895},{7,0,1031},{8,0,199},{8,0,340},{9,\n0,153},{9,0,215},{10,0,21},{10,0,59},{10,0,80},{10,0,224},{10,0,838},{11,0,229},\n{11,0,652},{12,0,192},{13,0,146},{142,0,91},{132,0,295},{137,0,51},{9,11,222},{\n10,11,43},{139,11,900},{5,0,309},{140,0,211},{5,0,125},{8,0,77},{138,0,15},{136,\n11,604},{138,0,789},{4,10,39},{5,0,173},{7,10,1843},{8,10,407},{11,10,144},{140,\n10,523},{138,11,265},{133,0,439},{132,10,510},{7,0,648},{7,0,874},{7,10,1980},{\n10,10,487},{10,10,809},{11,0,164},{12,0,76},{146,0,9},{12,0,111},{13,10,260},{14\n,0,294},{18,10,63},{147,0,45},{133,11,549},{134,10,570},{4,0,8},{7,0,1152},{7,0,\n1153},{7,0,1715},{9,0,374},{10,0,478},{139,0,648},{135,0,1099},{5,0,575},{6,0,\n354},{135,0,701},{7,11,36},{8,11,201},{136,11,605},{4,10,787},{136,11,156},{6,0,\n518},{149,11,13},{140,11,224},{134,0,702},{132,10,516},{5,11,724},{10,11,305},{\n11,11,151},{12,11,33},{12,11,121},{12,11,381},{17,11,3},{17,11,27},{17,11,78},{\n18,11,18},{19,11,54},{149,11,5},{4,11,523},{5,11,638},{8,0,87},{11,10,887},{14,\n10,365},{142,10,375},{138,0,438},{136,10,821},{135,11,1908},{6,11,242},{7,11,227\n},{7,11,1581},{8,11,104},{9,11,113},{9,11,220},{9,11,427},{10,11,74},{10,11,239}\n,{11,11,579},{11,11,1023},{13,11,4},{13,11,204},{13,11,316},{18,11,95},{148,11,\n86},{4,0,69},{5,0,122},{5,0,849},{6,0,1633},{9,0,656},{138,0,464},{4,10,10},{7,0\n,1802},{139,10,786},{135,11,861},{139,0,499},{7,0,476},{7,0,1592},{138,0,87},{\n133,10,684},{4,0,840},{134,10,27},{142,0,283},{6,0,1620},{7,11,1328},{136,11,494\n},{5,0,859},{7,0,1160},{8,0,107},{9,0,291},{9,0,439},{10,0,663},{11,0,609},{140,\n0,197},{7,11,1306},{8,11,505},{9,11,482},{10,11,126},{11,11,225},{12,11,347},{12\n,11,449},{13,11,19},{142,11,218},{5,11,268},{10,11,764},{12,11,120},{13,11,39},{\n145,11,127},{145,10,56},{7,11,1672},{10,11,472},{11,11,189},{143,11,51},{6,10,\n342},{6,10,496},{8,10,275},{137,10,206},{133,0,600},{4,0,117},{6,0,372},{7,0,\n1905},{142,0,323},{4,10,909},{5,10,940},{135,11,1471},{132,10,891},{4,0,722},{\n139,0,471},{4,11,384},{135,11,1022},{132,10,687},{9,0,5},{12,0,216},{12,0,294},{\n12,0,298},{12,0,400},{12,0,518},{13,0,229},{143,0,139},{135,11,1703},{7,11,1602}\n,{10,11,698},{12,11,212},{141,11,307},{6,10,41},{141,10,160},{135,11,1077},{9,11\n,159},{11,11,28},{140,11,603},{4,0,514},{7,0,1304},{138,0,477},{134,0,1774},{9,0\n,88},{139,0,270},{5,0,12},{6,10,1718},{7,0,375},{137,0,438},{132,11,515},{136,10\n,778},{8,11,632},{8,11,697},{137,11,854},{6,0,362},{6,0,997},{146,0,51},{7,0,816\n},{7,0,1241},{9,0,283},{9,0,520},{10,0,213},{10,0,307},{10,0,463},{10,0,671},{10\n,0,746},{11,0,401},{11,0,794},{12,0,517},{18,0,107},{147,0,115},{133,10,115},{\n150,11,28},{4,11,136},{133,11,551},{142,10,314},{132,0,258},{6,0,22},{7,0,903},{\n7,0,1963},{8,0,639},{138,0,577},{5,0,681},{5,10,193},{8,0,782},{12,10,178},{13,0\n,130},{145,0,84},{9,11,17},{138,11,291},{7,11,1287},{9,11,44},{10,11,552},{10,11\n,642},{11,11,839},{12,11,274},{12,11,275},{12,11,372},{13,11,91},{142,11,125},{\n135,10,174},{4,0,664},{5,0,804},{139,0,1013},{134,0,942},{6,0,1349},{6,0,1353},{\n6,0,1450},{7,11,1518},{139,11,694},{4,10,122},{5,10,796},{5,10,952},{6,10,1660},\n{6,10,1671},{8,10,567},{9,10,687},{9,10,742},{10,10,686},{11,0,356},{11,10,682},\n{140,10,281},{5,0,32},{6,11,147},{7,11,886},{9,11,753},{138,11,268},{5,10,179},{\n7,10,1095},{135,10,1213},{4,10,66},{7,10,722},{135,10,904},{135,10,352},{9,11,\n245},{138,11,137},{4,0,289},{5,11,414},{7,0,629},{7,0,1698},{7,0,1711},{140,0,\n215},{6,0,1975},{135,11,1762},{6,0,450},{136,0,109},{141,10,35},{134,11,599},{\n136,0,705},{133,0,664},{134,11,1749},{11,11,402},{12,11,109},{12,11,431},{13,11,\n179},{13,11,206},{14,11,175},{14,11,217},{16,11,3},{148,11,53},{135,0,1238},{134\n,11,1627},{132,11,488},{10,10,592},{10,10,753},{12,10,317},{12,10,355},{12,10,\n465},{12,10,469},{12,10,560},{12,10,578},{141,0,318},{133,10,564},{132,11,83},{\n140,11,676},{6,0,1872},{6,0,1906},{6,0,1907},{9,0,934},{9,0,956},{9,0,960},{9,0,\n996},{12,0,794},{12,0,876},{12,0,880},{12,0,918},{15,0,230},{18,0,234},{18,0,238\n},{21,0,38},{149,0,62},{134,10,556},{134,11,278},{137,0,103},{7,10,544},{8,10,\n719},{138,10,61},{4,10,5},{5,10,498},{8,10,637},{137,10,521},{7,0,777},{12,0,229\n},{12,0,239},{12,11,229},{12,11,239},{15,0,12},{143,11,12},{6,0,26},{7,11,388},{\n7,11,644},{139,11,781},{7,11,229},{8,11,59},{9,11,190},{9,11,257},{10,11,378},{\n140,11,191},{133,10,927},{135,10,1441},{4,10,893},{5,10,780},{133,10,893},{4,0,\n414},{5,0,467},{9,0,654},{10,0,451},{12,0,59},{141,0,375},{142,0,173},{135,0,17}\n,{5,10,238},{135,0,1350},{135,0,955},{4,0,960},{10,0,887},{12,0,753},{18,0,161},\n{18,0,162},{152,0,19},{136,11,344},{6,10,1729},{137,11,288},{132,11,660},{4,0,\n217},{4,10,60},{5,0,710},{7,0,760},{7,0,1926},{7,10,1800},{8,10,314},{9,0,428},{\n9,0,708},{9,10,700},{10,0,254},{10,0,296},{10,0,720},{11,0,109},{11,0,255},{11,\n10,487},{12,0,165},{12,0,315},{13,0,107},{13,0,203},{14,0,54},{14,0,99},{14,0,\n114},{14,0,388},{16,0,85},{17,0,9},{17,0,33},{20,0,25},{20,0,28},{20,0,29},{21,0\n,9},{21,0,10},{21,0,34},{150,0,17},{7,11,1035},{138,11,737},{7,11,690},{9,11,217\n},{9,11,587},{140,11,521},{6,0,919},{7,11,706},{7,11,1058},{138,11,538},{7,10,\n1853},{138,10,437},{136,10,419},{6,0,280},{10,0,502},{11,0,344},{140,0,38},{5,0,\n45},{7,0,1161},{11,0,448},{11,0,880},{13,0,139},{13,0,407},{15,0,16},{17,0,95},{\n18,0,66},{18,0,88},{18,0,123},{149,0,7},{11,11,92},{11,11,196},{11,11,409},{11,\n11,450},{11,11,666},{11,11,777},{12,11,262},{13,11,385},{13,11,393},{15,11,115},\n{16,11,45},{145,11,82},{136,0,777},{134,11,1744},{4,0,410},{5,10,828},{135,0,521\n},{134,0,673},{7,0,1110},{7,0,1778},{7,10,176},{135,10,178},{5,10,806},{7,10,\n1976},{7,11,268},{136,11,569},{4,11,733},{9,11,194},{10,11,92},{11,11,198},{12,\n11,84},{12,11,87},{13,11,128},{144,11,74},{4,10,51},{5,0,341},{6,10,4},{7,0,1129\n},{7,10,591},{7,10,849},{7,10,951},{7,10,1613},{7,10,1760},{7,10,1988},{9,10,434\n},{10,10,754},{11,0,414},{11,10,25},{139,10,37},{133,10,902},{135,10,928},{135,0\n,787},{132,0,436},{134,10,270},{7,0,1587},{135,0,1707},{6,0,377},{7,0,1025},{9,0\n,613},{145,0,104},{7,11,982},{7,11,1361},{10,11,32},{143,11,56},{139,0,96},{132,\n0,451},{132,10,416},{142,10,372},{5,10,152},{5,10,197},{7,10,340},{7,10,867},{7,\n11,306},{10,10,548},{10,10,581},{11,10,6},{12,10,3},{12,10,19},{14,10,110},{142,\n10,289},{134,0,680},{134,11,609},{7,0,483},{7,10,190},{8,10,28},{8,10,141},{8,10\n,444},{8,10,811},{9,10,468},{11,10,334},{12,10,24},{12,10,386},{140,10,576},{5,\n10,757},{138,0,916},{5,10,721},{135,10,1553},{133,11,178},{134,0,937},{132,10,\n898},{133,0,739},{147,0,82},{135,0,663},{146,0,128},{5,10,277},{141,10,247},{134\n,0,1087},{132,10,435},{6,11,381},{7,11,645},{7,11,694},{136,11,546},{7,0,503},{\n135,0,1885},{6,0,1965},{8,0,925},{138,0,955},{4,0,113},{5,0,163},{5,0,735},{7,0,\n1009},{9,0,9},{9,0,771},{12,0,90},{13,0,138},{13,0,410},{143,0,128},{4,0,324},{\n138,0,104},{5,10,265},{6,10,212},{135,0,460},{133,11,105},{7,11,261},{7,11,1107}\n,{7,11,1115},{7,11,1354},{7,11,1588},{7,11,1705},{7,11,1902},{9,11,465},{10,11,\n248},{10,11,349},{10,11,647},{11,11,527},{11,11,660},{11,11,669},{12,11,529},{\n141,11,305},{5,11,438},{9,11,694},{12,11,627},{141,11,210},{152,11,11},{4,0,935}\n,{133,0,823},{132,10,702},{5,0,269},{5,10,808},{7,0,434},{7,0,891},{7,10,2045},{\n8,0,339},{9,0,702},{11,0,594},{11,0,718},{145,0,100},{7,0,1014},{9,0,485},{141,0\n,264},{134,0,1713},{7,0,1810},{11,0,866},{12,0,103},{12,11,233},{141,0,495},{4,0\n,423},{10,0,949},{138,0,1013},{135,0,900},{8,11,25},{138,11,826},{5,10,166},{8,\n10,739},{140,10,511},{134,0,2018},{7,11,1270},{139,11,612},{4,10,119},{5,10,170}\n,{5,10,447},{7,10,1708},{7,10,1889},{9,10,357},{9,10,719},{12,10,486},{140,10,\n596},{12,0,574},{140,11,574},{132,11,308},{6,0,964},{6,0,1206},{134,0,1302},{4,\n10,450},{135,10,1158},{135,11,150},{136,11,649},{14,0,213},{148,0,38},{9,11,45},\n{9,11,311},{141,11,42},{134,11,521},{7,10,1375},{7,10,1466},{138,10,331},{132,10\n,754},{5,11,339},{7,11,1442},{14,11,3},{15,11,41},{147,11,66},{136,11,378},{134,\n0,1022},{5,10,850},{136,10,799},{142,0,143},{135,0,2029},{134,11,1628},{8,0,523}\n,{150,0,34},{5,0,625},{135,0,1617},{7,0,275},{7,10,238},{7,10,2033},{8,10,120},{\n8,10,188},{8,10,659},{9,10,598},{10,10,466},{12,10,342},{12,10,588},{13,10,503},\n{14,10,246},{143,10,92},{7,0,37},{8,0,425},{8,0,693},{9,0,720},{10,0,380},{10,0,\n638},{11,0,273},{11,0,473},{12,0,61},{143,0,43},{135,11,829},{135,0,1943},{132,0\n,765},{5,11,486},{135,11,1349},{7,11,1635},{8,11,17},{10,11,217},{138,11,295},{4\n,10,201},{7,10,1744},{8,10,602},{11,10,247},{11,10,826},{145,10,65},{138,11,558}\n,{11,0,551},{142,0,159},{8,10,164},{146,10,62},{139,11,176},{132,0,168},{136,0,\n1010},{134,0,1994},{135,0,91},{138,0,532},{135,10,1243},{135,0,1884},{132,10,907\n},{5,10,100},{10,10,329},{12,10,416},{149,10,29},{134,11,447},{132,10,176},{5,10\n,636},{5,10,998},{7,10,9},{7,10,1508},{8,10,26},{9,10,317},{9,10,358},{10,10,210\n},{10,10,292},{10,10,533},{11,10,555},{12,10,526},{12,10,607},{13,10,263},{13,10\n,459},{142,10,271},{4,11,609},{135,11,756},{6,0,15},{7,0,70},{10,0,240},{147,0,\n93},{4,11,930},{133,11,947},{134,0,1227},{134,0,1534},{133,11,939},{133,11,962},\n{5,11,651},{8,11,170},{9,11,61},{9,11,63},{10,11,23},{10,11,37},{10,11,834},{11,\n11,4},{11,11,187},{11,11,281},{11,11,503},{11,11,677},{12,11,96},{12,11,130},{12\n,11,244},{14,11,5},{14,11,40},{14,11,162},{14,11,202},{146,11,133},{4,11,406},{5\n,11,579},{12,11,492},{150,11,15},{139,0,392},{6,10,610},{10,10,127},{141,10,27},\n{7,0,655},{7,0,1844},{136,10,119},{4,0,145},{6,0,176},{7,0,395},{137,0,562},{132\n,0,501},{140,11,145},{136,0,1019},{134,0,509},{139,0,267},{6,11,17},{7,11,16},{7\n,11,1001},{7,11,1982},{9,11,886},{10,11,489},{10,11,800},{11,11,782},{12,11,320}\n,{13,11,467},{14,11,145},{14,11,387},{143,11,119},{145,11,17},{5,11,458},{134,0,\n1099},{7,11,1983},{8,11,0},{8,11,171},{9,11,120},{9,11,732},{10,11,473},{11,11,\n656},{11,11,998},{18,11,0},{18,11,2},{147,11,21},{12,11,427},{146,11,38},{10,0,\n948},{138,0,968},{7,10,126},{136,10,84},{136,10,790},{4,0,114},{9,0,492},{13,0,\n462},{142,0,215},{6,10,64},{12,10,377},{141,10,309},{4,0,77},{5,0,361},{6,0,139}\n,{6,0,401},{6,0,404},{7,0,413},{7,0,715},{7,0,1716},{11,0,279},{12,0,179},{12,0,\n258},{13,0,244},{142,0,358},{134,0,1717},{7,0,772},{7,0,1061},{7,0,1647},{7,10,\n1104},{8,0,82},{11,0,250},{11,0,607},{11,10,269},{11,10,539},{11,10,627},{11,10,\n706},{11,10,975},{12,0,311},{12,0,420},{12,10,248},{12,10,434},{12,10,600},{12,\n10,622},{13,0,184},{13,0,367},{13,10,297},{13,10,485},{14,10,69},{14,10,409},{\n143,10,108},{135,0,724},{4,11,512},{4,11,519},{133,11,342},{134,0,1133},{145,11,\n29},{11,10,977},{141,10,507},{6,0,841},{6,0,1042},{6,0,1194},{10,0,993},{140,0,\n1021},{6,11,31},{7,11,491},{7,11,530},{8,11,592},{9,10,34},{11,10,484},{11,11,53\n},{11,11,779},{12,11,167},{12,11,411},{14,11,14},{14,11,136},{15,11,72},{16,11,\n17},{144,11,72},{4,0,1021},{5,11,907},{134,0,2037},{6,10,1700},{7,0,373},{7,10,\n293},{7,10,382},{7,10,1026},{7,10,1087},{7,10,2027},{8,0,335},{8,0,596},{8,10,\n252},{8,10,727},{8,10,729},{9,0,488},{9,10,30},{9,10,199},{9,10,231},{9,10,251},\n{9,10,334},{9,10,361},{9,10,712},{10,10,55},{10,10,60},{10,10,232},{10,10,332},{\n10,10,384},{10,10,396},{10,10,504},{10,10,542},{10,10,652},{11,10,20},{11,10,48}\n,{11,10,207},{11,10,291},{11,10,298},{11,10,342},{11,10,365},{11,10,394},{11,10,\n620},{11,10,705},{11,10,1017},{12,10,123},{12,10,340},{12,10,406},{12,10,643},{\n13,10,61},{13,10,269},{13,10,311},{13,10,319},{13,10,486},{14,10,234},{15,10,62}\n,{15,10,85},{16,10,71},{18,10,119},{148,10,105},{150,0,37},{4,11,208},{5,11,106}\n,{6,11,531},{8,11,408},{9,11,188},{138,11,572},{132,0,564},{6,0,513},{135,0,1052\n},{132,0,825},{9,0,899},{140,11,441},{134,0,778},{133,11,379},{7,0,1417},{12,0,\n382},{17,0,48},{152,0,12},{132,11,241},{6,10,379},{7,0,1116},{7,10,270},{8,10,\n176},{8,10,183},{9,10,432},{9,10,661},{12,10,247},{12,10,617},{146,10,125},{5,10\n,792},{133,10,900},{6,0,545},{7,0,565},{7,0,1669},{10,0,114},{11,0,642},{140,0,\n618},{133,0,5},{138,11,7},{132,11,259},{135,0,192},{134,0,701},{136,0,763},{135,\n10,1979},{4,10,901},{133,10,776},{10,0,755},{147,0,29},{133,0,759},{4,11,173},{5\n,11,312},{5,11,512},{135,11,1285},{7,11,1603},{7,11,1691},{9,11,464},{11,11,195}\n,{12,11,279},{12,11,448},{14,11,11},{147,11,102},{7,0,370},{7,0,1007},{7,0,1177}\n,{135,0,1565},{135,0,1237},{4,0,87},{5,0,250},{141,0,298},{4,11,452},{5,11,583},\n{5,11,817},{6,11,433},{7,11,593},{7,11,720},{7,11,1378},{8,11,161},{9,11,284},{\n10,11,313},{139,11,886},{4,11,547},{135,11,1409},{136,11,722},{4,10,37},{5,10,\n334},{135,10,1253},{132,10,508},{12,0,107},{146,0,31},{8,11,420},{139,11,193},{\n135,0,814},{135,11,409},{140,0,991},{4,0,57},{7,0,1195},{7,0,1438},{7,0,1548},{7\n,0,1835},{7,0,1904},{9,0,757},{10,0,604},{139,0,519},{132,0,540},{138,11,308},{\n132,10,533},{136,0,608},{144,11,65},{4,0,1014},{134,0,2029},{4,0,209},{5,11,1002\n},{7,0,902},{136,11,745},{134,0,2030},{6,0,303},{7,0,335},{7,0,1437},{7,0,1668},\n{8,0,553},{8,0,652},{8,0,656},{9,0,558},{11,0,743},{149,0,18},{5,11,575},{6,11,\n354},{135,11,701},{4,11,239},{6,11,477},{7,11,1607},{11,11,68},{139,11,617},{132\n,0,559},{8,0,527},{18,0,60},{147,0,24},{133,10,920},{138,0,511},{133,0,1017},{\n133,0,675},{138,10,391},{7,10,1952},{139,0,156},{138,11,369},{132,11,367},{133,0\n,709},{6,0,698},{134,0,887},{142,10,126},{134,0,1745},{132,10,483},{13,11,299},{\n142,11,75},{133,0,714},{7,0,8},{136,0,206},{138,10,480},{4,11,694},{9,10,495},{\n146,10,104},{7,11,1248},{11,11,621},{139,11,702},{140,11,687},{132,0,776},{139,\n10,1009},{135,0,1272},{134,0,1059},{8,10,653},{13,10,93},{147,10,14},{135,11,213\n},{136,0,406},{133,10,172},{132,0,947},{8,0,175},{10,0,168},{138,0,573},{132,0,\n870},{6,0,1567},{151,11,28},{134,11,472},{5,10,260},{136,11,132},{4,11,751},{11,\n11,390},{140,11,32},{4,11,409},{133,11,78},{6,11,473},{12,0,554},{145,11,105},{\n133,0,784},{8,0,908},{136,11,306},{139,0,882},{6,0,358},{7,0,1393},{7,11,1759},{\n8,0,396},{8,11,396},{10,0,263},{10,11,263},{14,0,154},{14,11,154},{16,0,48},{16,\n11,48},{17,0,8},{145,11,8},{13,11,163},{13,11,180},{18,11,78},{148,11,35},{14,0,\n32},{18,0,85},{20,0,2},{152,0,16},{7,0,228},{8,10,167},{8,10,375},{9,10,82},{9,\n10,561},{10,0,770},{138,10,620},{132,0,845},{9,0,14},{9,0,441},{10,0,306},{139,0\n,9},{8,10,194},{8,10,756},{11,0,966},{12,0,287},{13,0,342},{13,0,402},{15,0,110}\n,{143,0,163},{134,0,1578},{4,0,967},{6,0,1820},{6,0,1847},{140,0,716},{136,0,594\n},{7,0,1428},{7,0,1640},{7,0,1867},{7,11,883},{9,0,169},{9,0,182},{9,0,367},{9,0\n,478},{9,0,506},{9,0,551},{9,0,557},{9,0,648},{9,0,697},{9,0,705},{9,0,725},{9,0\n,787},{9,0,794},{10,0,198},{10,0,214},{10,0,267},{10,0,275},{10,0,456},{10,0,551\n},{10,0,561},{10,0,613},{10,0,627},{10,0,668},{10,0,675},{10,0,691},{10,0,695},{\n10,0,707},{10,0,715},{11,0,183},{11,0,201},{11,0,244},{11,0,262},{11,0,352},{11,\n0,439},{11,0,493},{11,0,572},{11,0,591},{11,0,608},{11,0,611},{11,0,646},{11,0,\n674},{11,0,711},{11,0,751},{11,0,761},{11,0,776},{11,0,785},{11,0,850},{11,0,853\n},{11,0,862},{11,0,865},{11,0,868},{11,0,875},{11,0,898},{11,0,902},{11,0,903},{\n11,0,910},{11,0,932},{11,0,942},{11,0,957},{11,0,967},{11,0,972},{12,0,148},{12,\n0,195},{12,0,220},{12,0,237},{12,0,318},{12,0,339},{12,0,393},{12,0,445},{12,0,\n450},{12,0,474},{12,0,505},{12,0,509},{12,0,533},{12,0,591},{12,0,594},{12,0,597\n},{12,0,621},{12,0,633},{12,0,642},{13,0,59},{13,0,60},{13,0,145},{13,0,239},{13\n,0,250},{13,0,329},{13,0,344},{13,0,365},{13,0,372},{13,0,387},{13,0,403},{13,0,\n414},{13,0,456},{13,0,470},{13,0,478},{13,0,483},{13,0,489},{14,0,55},{14,0,57},\n{14,0,81},{14,0,90},{14,0,148},{14,0,239},{14,0,266},{14,0,321},{14,0,326},{14,0\n,327},{14,0,330},{14,0,347},{14,0,355},{14,0,401},{14,0,404},{14,0,411},{14,0,\n414},{14,0,416},{14,0,420},{15,0,61},{15,0,74},{15,0,87},{15,0,88},{15,0,94},{15\n,0,96},{15,0,116},{15,0,149},{15,0,154},{16,0,50},{16,0,63},{16,0,73},{17,0,2},{\n17,0,66},{17,0,92},{17,0,103},{17,0,112},{17,0,120},{18,0,50},{18,0,54},{18,0,82\n},{18,0,86},{18,0,90},{18,0,111},{18,0,115},{18,0,156},{19,0,40},{19,0,79},{20,0\n,78},{149,0,22},{5,0,161},{135,0,839},{4,0,782},{13,11,293},{142,11,56},{133,11,\n617},{139,11,50},{135,10,22},{145,0,64},{5,10,639},{7,10,1249},{139,10,896},{138\n,0,998},{135,11,2042},{4,11,546},{142,11,233},{6,0,1043},{134,0,1574},{134,0,\n1496},{4,10,102},{7,10,815},{7,10,1699},{139,10,964},{12,0,781},{142,0,461},{4,\n11,313},{133,11,577},{6,0,639},{6,0,1114},{137,0,817},{8,11,184},{141,11,433},{7\n,0,1814},{135,11,935},{10,0,997},{140,0,958},{4,0,812},{137,11,625},{132,10,899}\n,{136,10,795},{5,11,886},{6,11,46},{6,11,1790},{7,11,14},{7,11,732},{7,11,1654},\n{8,11,95},{8,11,327},{8,11,616},{10,11,598},{10,11,769},{11,11,134},{11,11,747},\n{12,11,378},{142,11,97},{136,0,139},{6,10,52},{9,10,104},{9,10,559},{12,10,308},\n{147,10,87},{133,11,1021},{132,10,604},{132,10,301},{136,10,779},{7,0,643},{136,\n0,236},{132,11,153},{134,0,1172},{147,10,32},{133,11,798},{4,11,587},{134,0,1338\n},{6,11,598},{7,11,42},{8,11,695},{10,11,212},{11,11,158},{14,11,196},{145,11,85\n},{135,10,508},{5,11,957},{5,11,1008},{135,11,249},{4,11,129},{135,11,465},{5,0,\n54},{7,11,470},{7,11,1057},{7,11,1201},{9,11,755},{11,11,906},{140,11,527},{7,11\n,908},{146,11,7},{5,11,148},{136,11,450},{144,11,1},{4,0,256},{135,0,1488},{6,10\n,310},{7,10,1849},{8,10,72},{8,10,272},{8,10,431},{9,0,351},{9,10,12},{10,10,563\n},{10,10,630},{10,10,796},{10,10,810},{11,10,367},{11,10,599},{11,10,686},{140,\n10,672},{6,0,1885},{6,0,1898},{6,0,1899},{140,0,955},{4,0,714},{133,0,469},{6,0,\n1270},{134,0,1456},{132,0,744},{6,0,313},{7,10,537},{8,10,64},{9,10,127},{10,10,\n496},{12,10,510},{141,10,384},{4,10,244},{4,11,217},{5,11,710},{7,10,233},{7,11,\n1926},{9,11,428},{9,11,708},{10,11,254},{10,11,296},{10,11,720},{11,11,109},{11,\n11,255},{12,11,165},{12,11,315},{13,11,107},{13,11,203},{14,11,54},{14,11,99},{\n14,11,114},{14,11,388},{16,11,85},{17,11,9},{17,11,33},{20,11,25},{20,11,28},{20\n,11,29},{21,11,9},{21,11,10},{21,11,34},{150,11,17},{138,0,402},{7,0,969},{146,0\n,55},{8,0,50},{137,0,624},{134,0,1355},{132,0,572},{134,10,1650},{10,10,702},{\n139,10,245},{10,0,847},{142,0,445},{6,0,43},{7,0,38},{8,0,248},{138,0,513},{133,\n0,369},{137,10,338},{133,0,766},{133,0,363},{133,10,896},{8,11,392},{11,11,54},{\n13,11,173},{13,11,294},{148,11,7},{134,0,678},{7,11,1230},{136,11,531},{6,0,258}\n,{140,0,409},{5,0,249},{148,0,82},{7,10,1117},{136,10,539},{5,0,393},{6,0,378},{\n7,0,1981},{9,0,32},{9,0,591},{10,0,685},{10,0,741},{142,0,382},{133,0,788},{134,\n0,1281},{134,0,1295},{7,0,1968},{141,0,509},{4,0,61},{5,0,58},{5,0,171},{5,0,683\n},{6,0,291},{6,0,566},{7,0,1650},{11,0,523},{12,0,273},{12,0,303},{15,0,39},{143\n,0,111},{6,0,706},{134,0,1283},{134,0,589},{135,11,1433},{133,11,435},{5,10,4},{\n5,10,810},{6,10,13},{6,10,538},{6,10,1690},{6,10,1726},{7,0,1059},{7,10,1819},{8\n,10,148},{8,10,696},{8,10,791},{12,10,125},{13,0,54},{143,10,9},{135,10,1268},{5\n,11,85},{6,11,419},{7,11,134},{7,11,305},{7,11,361},{7,11,1337},{8,11,71},{140,\n11,519},{137,0,824},{140,11,688},{5,11,691},{7,10,1385},{7,11,345},{9,11,94},{11\n,10,582},{11,10,650},{11,10,901},{11,10,949},{12,10,232},{12,10,236},{12,11,169}\n,{13,10,413},{13,10,501},{146,10,116},{4,0,917},{133,0,1005},{5,11,183},{6,11,\n582},{7,0,1598},{9,11,344},{10,11,679},{140,11,435},{4,10,925},{5,10,803},{8,10,\n698},{138,10,828},{132,0,919},{135,11,511},{139,10,992},{4,0,255},{5,0,302},{6,0\n,132},{7,0,128},{7,0,283},{7,0,1299},{10,0,52},{10,0,514},{11,0,925},{13,0,92},{\n142,0,309},{134,0,1369},{135,10,1847},{134,0,328},{7,11,1993},{136,11,684},{133,\n10,383},{137,0,173},{134,11,583},{134,0,1411},{5,11,704},{8,11,357},{10,11,745},\n{14,11,426},{17,11,94},{19,0,65},{147,11,57},{9,10,660},{138,10,347},{4,11,179},\n{5,11,198},{133,11,697},{7,11,347},{7,11,971},{8,11,181},{138,11,711},{141,0,442\n},{7,10,572},{9,10,592},{11,0,842},{11,0,924},{11,10,680},{12,10,356},{12,10,550\n},{13,0,317},{13,0,370},{13,0,469},{13,0,471},{14,0,397},{18,0,69},{146,0,145},{\n14,11,19},{14,11,28},{144,11,29},{136,0,534},{4,11,243},{5,11,203},{7,11,19},{7,\n11,71},{7,11,113},{10,11,405},{11,11,357},{142,11,240},{6,0,210},{10,0,845},{138\n,0,862},{7,11,1351},{9,11,581},{10,11,639},{11,11,453},{140,11,584},{7,11,1450},\n{139,11,99},{10,0,892},{12,0,719},{144,0,105},{4,0,284},{6,0,223},{134,11,492},{\n5,11,134},{6,11,408},{6,11,495},{135,11,1593},{136,0,529},{137,0,807},{4,0,218},\n{7,0,526},{143,0,137},{6,0,1444},{142,11,4},{132,11,665},{4,0,270},{4,11,248},{5\n,0,192},{6,0,332},{7,0,1322},{7,11,137},{137,11,349},{140,0,661},{7,0,1517},{7,\n10,748},{11,0,597},{11,10,700},{14,0,76},{14,0,335},{148,0,33},{5,11,371},{135,\n11,563},{146,11,57},{133,10,127},{133,0,418},{4,11,374},{7,11,547},{7,11,1700},{\n7,11,1833},{139,11,858},{6,10,198},{140,10,83},{7,11,1812},{13,11,259},{13,11,\n356},{14,11,242},{147,11,114},{5,10,276},{6,10,55},{7,0,379},{7,10,1369},{8,0,\n481},{137,0,377},{138,11,286},{5,0,1003},{6,0,149},{6,10,1752},{136,10,726},{6,\n11,1647},{7,11,1552},{7,11,2010},{8,0,262},{9,0,627},{9,11,494},{9,11,509},{10,0\n,18},{11,0,214},{11,0,404},{11,0,457},{11,0,780},{11,0,913},{13,0,401},{142,0,\n200},{135,0,742},{136,0,304},{132,0,142},{133,10,764},{6,10,309},{7,10,331},{138\n,10,550},{135,10,1062},{6,11,123},{7,10,986},{7,11,214},{9,11,728},{10,11,157},{\n11,11,346},{11,11,662},{143,11,106},{135,10,1573},{7,0,925},{137,0,799},{4,0,471\n},{5,0,51},{6,0,602},{8,0,484},{138,0,195},{136,0,688},{132,0,697},{6,0,1169},{6\n,0,1241},{6,10,194},{7,10,133},{10,10,493},{10,10,570},{139,10,664},{140,0,751},\n{5,10,24},{5,10,569},{6,10,3},{6,10,119},{6,10,143},{6,10,440},{7,0,929},{7,10,\n599},{7,10,1686},{7,10,1854},{8,10,424},{9,10,43},{9,10,584},{9,10,760},{10,0,\n452},{10,10,328},{11,0,878},{11,10,159},{11,10,253},{12,10,487},{12,10,531},{144\n,0,33},{4,11,707},{13,11,106},{18,11,49},{147,11,41},{5,0,221},{5,11,588},{134,\n11,393},{134,0,1437},{6,11,211},{7,11,1690},{11,11,486},{140,11,369},{5,10,14},{\n5,10,892},{6,10,283},{7,10,234},{136,10,537},{4,0,988},{136,0,955},{135,0,1251},\n{4,10,126},{8,10,635},{147,10,34},{4,10,316},{135,10,1561},{137,10,861},{4,10,64\n},{5,10,352},{5,10,720},{6,10,368},{139,10,359},{134,0,192},{4,0,132},{5,0,69},{\n135,0,1242},{7,10,1577},{10,10,304},{10,10,549},{12,10,365},{13,10,220},{13,10,\n240},{142,10,33},{4,0,111},{6,11,219},{135,0,865},{5,11,582},{6,11,1646},{7,11,\n99},{7,11,1962},{7,11,1986},{8,11,515},{8,11,773},{9,11,23},{9,11,491},{12,11,\n620},{14,11,52},{145,11,50},{132,0,767},{7,11,568},{148,11,21},{5,11,851},{6,0,\n42},{7,0,1416},{7,0,2005},{8,0,131},{8,0,466},{9,0,672},{13,0,252},{148,0,103},{\n135,0,1050},{6,10,175},{137,10,289},{5,10,432},{133,10,913},{6,0,44},{136,0,368}\n,{135,11,784},{132,0,570},{133,0,120},{139,10,595},{140,0,29},{6,0,227},{135,0,\n1589},{4,11,98},{7,11,1365},{9,11,422},{9,11,670},{10,11,775},{11,11,210},{13,11\n,26},{13,11,457},{141,11,476},{140,10,80},{5,10,931},{134,10,1698},{133,0,522},{\n134,0,1120},{135,0,1529},{12,0,739},{14,0,448},{142,0,467},{11,10,526},{11,10,\n939},{141,10,290},{5,10,774},{6,10,1637},{6,10,1686},{134,10,1751},{6,0,1667},{\n135,0,2036},{7,10,1167},{11,10,934},{13,10,391},{145,10,76},{137,11,147},{6,10,\n260},{7,10,1484},{11,11,821},{12,11,110},{12,11,153},{18,11,41},{150,11,19},{6,0\n,511},{6,10,573},{140,0,132},{5,0,568},{6,0,138},{135,0,1293},{132,0,1020},{8,0,\n258},{9,0,208},{137,0,359},{4,0,565},{8,0,23},{136,0,827},{134,0,344},{4,0,922},\n{5,0,1023},{13,11,477},{14,11,120},{148,11,61},{134,0,240},{5,11,209},{6,11,30},\n{11,11,56},{139,11,305},{4,10,292},{4,10,736},{5,10,871},{6,0,171},{6,10,1689},{\n7,0,1002},{7,0,1324},{7,10,1944},{9,0,415},{9,10,580},{14,0,230},{146,0,68},{9,\n11,635},{139,11,559},{4,11,150},{5,11,303},{134,11,327},{6,10,63},{135,10,920},{\n133,10,793},{8,11,192},{10,11,78},{10,11,555},{11,11,308},{13,11,359},{147,11,95\n},{135,11,786},{135,11,1712},{136,0,402},{6,0,754},{6,11,1638},{7,11,79},{7,11,\n496},{9,11,138},{10,11,336},{11,11,12},{12,11,412},{12,11,440},{142,11,305},{4,0\n,716},{141,0,31},{133,0,982},{5,10,67},{6,10,62},{6,10,374},{7,10,1391},{8,0,691\n},{136,0,731},{9,10,790},{140,10,47},{139,11,556},{151,11,1},{7,11,204},{7,11,\n415},{8,11,42},{10,11,85},{11,11,33},{11,11,564},{12,11,571},{149,11,1},{7,11,\n610},{7,11,1501},{136,0,888},{4,10,391},{135,10,1169},{5,0,847},{9,0,840},{138,0\n,803},{137,0,823},{134,0,785},{8,0,152},{9,0,53},{9,0,268},{9,0,901},{10,0,518},\n{10,0,829},{11,0,188},{13,0,74},{14,0,46},{15,0,17},{15,0,33},{17,0,40},{18,0,36\n},{19,0,20},{22,0,1},{152,0,2},{4,11,3},{5,11,247},{5,11,644},{7,11,744},{7,11,\n1207},{7,11,1225},{7,11,1909},{146,11,147},{136,0,532},{135,0,681},{132,10,271},\n{140,0,314},{140,0,677},{4,0,684},{136,0,384},{5,11,285},{9,11,67},{13,11,473},{\n143,11,82},{4,10,253},{5,10,544},{7,10,300},{137,10,340},{7,0,110},{7,0,447},{8,\n0,290},{8,0,591},{9,0,382},{9,0,649},{11,0,71},{11,0,155},{11,0,313},{12,0,5},{\n13,0,325},{142,0,287},{134,0,1818},{136,0,1007},{138,0,321},{7,0,360},{7,0,425},\n{9,0,66},{9,0,278},{138,0,644},{133,10,818},{5,0,385},{5,10,541},{6,10,94},{6,10\n,499},{7,10,230},{139,10,321},{4,10,920},{5,10,25},{5,10,790},{6,10,457},{7,10,\n853},{136,10,788},{4,0,900},{133,0,861},{5,0,254},{7,0,985},{136,0,73},{7,0,1959\n},{136,0,683},{134,10,1765},{133,10,822},{132,10,634},{4,11,29},{6,11,532},{7,11\n,1628},{7,11,1648},{9,11,303},{9,11,350},{10,11,433},{11,11,97},{11,11,557},{11,\n11,745},{12,11,289},{12,11,335},{12,11,348},{12,11,606},{13,11,116},{13,11,233},\n{13,11,466},{14,11,181},{14,11,209},{14,11,232},{14,11,236},{14,11,300},{16,11,\n41},{148,11,97},{6,10,36},{7,10,658},{8,10,454},{147,0,86},{135,11,1692},{132,0,\n725},{5,11,501},{7,11,1704},{9,11,553},{11,11,520},{12,11,557},{141,11,249},{134\n,0,196},{133,0,831},{136,0,723},{7,0,1897},{13,0,80},{13,0,437},{145,0,74},{4,0,\n992},{6,0,627},{136,0,994},{135,11,1294},{132,10,104},{5,0,848},{6,0,66},{136,0,\n764},{4,0,36},{7,0,1387},{10,0,205},{139,0,755},{6,0,1046},{134,0,1485},{134,0,\n950},{132,0,887},{14,0,450},{148,0,111},{7,0,620},{7,0,831},{9,10,542},{9,10,566\n},{138,10,728},{6,0,165},{138,0,388},{139,10,263},{4,0,719},{135,0,155},{138,10,\n468},{6,11,453},{144,11,36},{134,11,129},{5,0,533},{7,0,755},{138,0,780},{134,0,\n1465},{4,0,353},{6,0,146},{6,0,1789},{7,0,427},{7,0,990},{7,0,1348},{9,0,665},{9\n,0,898},{11,0,893},{142,0,212},{7,10,87},{142,10,288},{4,0,45},{135,0,1257},{7,\n10,988},{7,10,1939},{9,10,64},{9,10,502},{12,0,7},{12,10,34},{13,10,12},{13,10,\n234},{147,10,77},{4,0,607},{5,11,60},{6,11,504},{7,11,614},{7,11,1155},{140,11,0\n},{135,10,141},{8,11,198},{11,11,29},{140,11,534},{140,0,65},{136,0,816},{132,10\n,619},{139,0,88},{5,10,246},{8,10,189},{9,10,355},{9,10,512},{10,10,124},{10,10,\n453},{11,10,143},{11,10,416},{11,10,859},{141,10,341},{4,11,379},{135,11,1397},{\n4,0,600},{137,0,621},{133,0,367},{134,0,561},{6,0,559},{134,0,1691},{6,0,585},{\n134,11,585},{135,11,1228},{4,11,118},{5,10,678},{6,11,274},{6,11,361},{7,11,75},\n{141,11,441},{135,11,1818},{137,11,841},{5,0,573},{6,0,287},{7,10,862},{7,10,\n1886},{138,10,179},{132,10,517},{140,11,693},{5,11,314},{6,11,221},{7,11,419},{\n10,11,650},{11,11,396},{12,11,156},{13,11,369},{14,11,333},{145,11,47},{140,10,\n540},{136,10,667},{11,10,403},{146,10,83},{5,10,761},{134,0,672},{9,0,157},{10,\n10,131},{140,10,72},{6,11,460},{135,0,714},{134,0,456},{133,0,925},{5,11,682},{\n135,11,1887},{136,11,510},{136,11,475},{133,11,1016},{7,11,602},{8,11,179},{9,0,\n19},{10,11,781},{140,11,126},{6,11,329},{138,11,111},{6,0,822},{134,0,1473},{144\n,11,86},{11,0,113},{139,11,113},{5,11,821},{134,11,1687},{133,10,449},{7,0,463},\n{8,10,103},{145,0,69},{7,10,2028},{138,10,641},{6,0,193},{7,0,240},{7,0,1682},{\n10,0,51},{10,0,640},{11,0,410},{13,0,82},{14,0,247},{14,0,331},{142,0,377},{6,0,\n471},{11,0,411},{142,0,2},{5,11,71},{7,11,1407},{9,11,388},{9,11,704},{10,11,261\n},{10,11,619},{11,11,547},{11,11,619},{143,11,157},{136,0,633},{135,0,1148},{6,0\n,554},{7,0,1392},{7,10,1274},{7,10,1386},{7,11,2008},{9,11,337},{10,11,517},{12,\n0,129},{146,10,87},{6,10,187},{7,0,803},{7,10,1203},{8,0,542},{8,10,380},{14,10,\n117},{149,10,28},{6,10,297},{7,10,793},{139,10,938},{7,10,464},{8,0,438},{11,0,\n363},{11,10,105},{12,10,231},{14,10,386},{15,10,102},{148,10,75},{5,11,16},{6,11\n,86},{6,11,603},{7,11,292},{7,11,561},{8,11,257},{8,11,382},{9,11,721},{9,11,778\n},{11,11,581},{140,11,466},{4,11,486},{5,11,491},{134,0,717},{132,0,875},{132,11\n,72},{6,11,265},{135,11,847},{4,0,237},{135,0,514},{6,0,392},{7,0,65},{135,0,\n2019},{140,11,261},{135,11,922},{137,11,404},{7,10,1010},{11,10,733},{11,10,759}\n,{12,0,563},{13,10,34},{14,0,101},{18,0,129},{146,10,45},{7,10,1656},{9,10,369},\n{10,10,338},{10,10,490},{11,10,154},{11,10,545},{11,10,775},{13,10,77},{141,10,\n274},{4,0,444},{10,0,146},{140,0,9},{139,11,163},{7,0,1260},{135,0,1790},{9,0,\n222},{10,0,43},{139,0,900},{137,11,234},{138,0,971},{137,0,761},{134,0,699},{136\n,11,434},{5,10,20},{6,0,1116},{6,10,298},{6,11,197},{7,0,1366},{7,10,659},{8,11,\n205},{137,10,219},{132,11,490},{11,11,820},{150,11,51},{7,10,1440},{11,10,854},{\n11,10,872},{11,10,921},{12,10,551},{13,10,472},{142,10,367},{140,11,13},{132,0,\n829},{4,10,439},{140,0,242},{136,10,669},{6,0,593},{6,11,452},{7,11,312},{138,11\n,219},{4,11,333},{9,11,176},{12,11,353},{141,11,187},{7,0,36},{8,0,201},{136,0,\n605},{140,0,224},{132,10,233},{134,0,1430},{134,0,1806},{4,0,523},{133,0,638},{6\n,0,1889},{9,0,958},{9,0,971},{9,0,976},{12,0,796},{12,0,799},{12,0,808},{12,0,\n835},{12,0,836},{12,0,914},{12,0,946},{15,0,216},{15,0,232},{18,0,183},{18,0,187\n},{18,0,194},{18,0,212},{18,0,232},{149,0,49},{132,10,482},{6,0,827},{134,0,1434\n},{135,10,346},{134,0,2043},{6,0,242},{7,0,227},{7,0,1581},{8,0,104},{9,0,113},{\n9,0,220},{9,0,427},{10,0,136},{10,0,239},{11,0,579},{11,0,1023},{13,0,4},{13,0,\n204},{13,0,316},{148,0,86},{134,11,1685},{7,0,148},{8,0,284},{141,0,63},{142,0,\n10},{135,11,584},{134,0,1249},{7,0,861},{135,10,334},{5,10,795},{6,10,1741},{137\n,11,70},{132,0,807},{7,11,135},{8,11,7},{8,11,62},{9,11,243},{10,11,658},{10,11,\n697},{11,11,456},{139,11,756},{9,11,395},{138,11,79},{137,11,108},{147,0,94},{\n136,0,494},{135,11,631},{135,10,622},{7,0,1510},{135,10,1750},{4,10,203},{135,10\n,1936},{7,11,406},{7,11,459},{8,11,606},{139,11,726},{7,0,1306},{8,0,505},{9,0,\n482},{10,0,126},{11,0,225},{12,0,347},{12,0,449},{13,0,19},{14,0,218},{142,0,435\n},{5,0,268},{10,0,764},{12,0,120},{13,0,39},{145,0,127},{142,11,68},{11,10,678},\n{140,10,307},{12,11,268},{12,11,640},{142,11,119},{135,10,2044},{133,11,612},{4,\n11,372},{7,11,482},{8,11,158},{9,11,602},{9,11,615},{10,11,245},{10,11,678},{10,\n11,744},{11,11,248},{139,11,806},{7,10,311},{9,10,308},{140,10,255},{4,0,384},{\n135,0,1022},{5,11,854},{135,11,1991},{135,10,1266},{4,10,400},{5,10,267},{135,10\n,232},{135,0,1703},{9,0,159},{11,0,661},{140,0,603},{4,0,964},{9,11,106},{9,11,\n163},{9,11,296},{10,11,167},{10,11,172},{10,11,777},{11,11,16},{14,0,438},{14,0,\n444},{14,0,456},{22,0,60},{150,0,63},{136,0,583},{132,0,515},{8,0,632},{8,0,697}\n,{137,0,854},{5,11,195},{135,11,1685},{6,0,1123},{134,0,1365},{134,11,328},{7,11\n,1997},{8,11,730},{139,11,1006},{4,0,136},{133,0,551},{134,0,1782},{7,0,1287},{9\n,0,44},{10,0,552},{10,0,642},{11,0,839},{12,0,274},{12,0,275},{12,0,372},{13,0,\n91},{142,0,125},{5,11,751},{11,11,797},{140,11,203},{133,0,732},{4,10,100},{7,0,\n679},{7,11,821},{136,0,313},{10,0,361},{142,0,316},{134,0,595},{6,0,147},{7,0,\n886},{9,0,753},{138,0,268},{5,10,362},{5,10,443},{6,10,318},{7,10,1019},{139,10,\n623},{5,10,463},{136,10,296},{4,10,454},{5,11,950},{5,11,994},{134,11,351},{138,\n0,137},{5,10,48},{5,10,404},{6,10,557},{7,10,458},{8,10,597},{10,10,455},{10,10,\n606},{11,10,49},{11,10,548},{12,10,476},{13,10,18},{141,10,450},{133,0,414},{135\n,0,1762},{5,11,421},{135,11,47},{5,10,442},{135,10,1984},{134,0,599},{134,0,1749\n},{134,0,1627},{4,0,488},{132,11,350},{137,11,751},{132,0,83},{140,0,676},{133,\n11,967},{5,10,55},{7,0,1639},{140,10,161},{4,11,473},{7,11,623},{8,11,808},{9,11\n,871},{9,11,893},{11,11,38},{11,11,431},{12,11,112},{12,11,217},{12,11,243},{12,\n11,562},{12,11,683},{13,11,141},{13,11,197},{13,11,227},{13,11,406},{13,11,487},\n{14,11,156},{14,11,203},{14,11,224},{14,11,256},{18,11,58},{150,11,0},{133,10,\n450},{7,11,736},{139,11,264},{134,0,278},{4,11,222},{7,11,286},{136,11,629},{135\n,10,869},{140,0,97},{144,0,14},{134,0,1085},{4,10,213},{7,10,223},{136,10,80},{7\n,0,388},{7,0,644},{139,0,781},{132,0,849},{7,0,229},{8,0,59},{9,0,190},{10,0,378\n},{140,0,191},{7,10,381},{7,10,806},{7,10,820},{8,10,354},{8,10,437},{8,10,787},\n{9,10,657},{10,10,58},{10,10,339},{10,10,749},{11,10,914},{12,10,162},{13,10,75}\n,{14,10,106},{14,10,198},{14,10,320},{14,10,413},{146,10,43},{141,11,306},{136,\n10,747},{134,0,1115},{8,11,146},{16,0,94},{144,0,108},{6,0,700},{6,0,817},{134,0\n,1002},{133,10,692},{4,11,465},{135,11,1663},{134,10,191},{6,0,1414},{135,11,913\n},{132,0,660},{7,0,1035},{138,0,737},{6,10,162},{7,10,1960},{136,10,831},{132,10\n,706},{7,0,690},{9,0,217},{9,0,587},{140,0,521},{138,10,426},{135,10,1235},{6,11\n,82},{7,11,138},{7,11,517},{9,11,673},{139,11,238},{138,0,272},{5,11,495},{7,11,\n834},{9,11,733},{139,11,378},{134,0,1744},{132,0,1011},{7,11,828},{142,11,116},{\n4,0,733},{5,11,559},{9,0,194},{10,0,92},{11,0,198},{12,0,84},{141,0,128},{6,11,\n21},{6,11,1737},{7,11,1444},{8,11,224},{10,0,57},{138,0,277},{4,10,204},{137,10,\n902},{136,10,833},{7,10,366},{9,10,287},{11,0,348},{12,0,99},{12,10,199},{12,10,\n556},{12,10,577},{18,0,1},{18,0,11},{147,0,4},{6,0,1981},{136,0,936},{21,0,33},{\n150,0,40},{5,11,519},{138,11,204},{5,10,356},{135,10,224},{134,0,775},{135,0,306\n},{7,10,630},{9,10,567},{11,10,150},{11,10,444},{141,10,119},{5,0,979},{134,10,\n539},{133,0,611},{4,11,402},{135,11,1679},{5,0,178},{7,11,2},{8,11,323},{136,11,\n479},{5,11,59},{135,11,672},{4,0,1010},{6,0,1969},{138,11,237},{133,11,412},{146\n,11,34},{7,11,1740},{146,11,48},{134,0,664},{139,10,814},{4,11,85},{135,11,549},\n{133,11,94},{133,11,457},{132,0,390},{134,0,1510},{4,10,235},{135,10,255},{4,10,\n194},{5,10,584},{6,10,384},{6,11,11},{7,10,583},{7,11,187},{10,10,761},{11,10,\n760},{139,10,851},{4,11,522},{139,11,802},{135,0,493},{10,11,776},{13,11,345},{\n142,11,425},{146,0,37},{4,11,52},{135,11,661},{134,0,724},{134,0,829},{133,11,\n520},{133,10,562},{4,11,281},{5,11,38},{7,11,194},{7,11,668},{7,11,1893},{137,11\n,397},{5,10,191},{137,10,271},{7,0,1537},{14,0,96},{143,0,73},{4,10,470},{5,0,\n473},{6,10,153},{7,10,1503},{7,10,1923},{10,10,701},{11,0,168},{11,10,132},{11,\n10,227},{11,10,320},{11,10,436},{11,10,525},{11,10,855},{12,10,41},{12,10,286},{\n13,10,103},{13,10,284},{14,10,255},{14,10,262},{15,10,117},{143,10,127},{133,0,\n105},{5,0,438},{9,0,694},{12,0,627},{141,0,210},{133,10,327},{6,10,552},{7,10,\n1754},{137,10,604},{134,0,1256},{152,0,11},{5,11,448},{11,11,98},{139,11,524},{5\n,10,80},{6,10,405},{7,0,1626},{7,10,403},{7,10,1502},{8,10,456},{9,10,487},{9,10\n,853},{9,10,889},{10,10,309},{11,10,721},{11,10,994},{12,10,430},{13,10,165},{14\n,11,16},{146,11,44},{132,0,779},{8,0,25},{138,0,826},{4,10,453},{5,10,887},{6,10\n,535},{8,10,6},{8,10,543},{136,10,826},{137,11,461},{140,11,632},{132,0,308},{\n135,0,741},{132,0,671},{7,0,150},{8,0,649},{136,0,1020},{6,11,336},{8,11,552},{9\n,0,99},{9,11,285},{10,11,99},{139,11,568},{134,0,521},{5,0,339},{14,0,3},{15,0,\n41},{15,0,166},{147,0,66},{6,11,423},{7,11,665},{7,11,1210},{9,11,218},{141,11,\n222},{5,10,101},{5,11,256},{6,0,543},{6,10,88},{7,10,1677},{9,10,100},{10,10,677\n},{14,10,169},{14,10,302},{14,10,313},{15,10,48},{143,10,84},{4,10,310},{7,10,\n708},{7,10,996},{9,10,795},{10,10,390},{10,10,733},{11,10,451},{12,10,249},{14,\n10,115},{14,10,286},{143,10,100},{133,10,587},{13,11,417},{14,11,129},{143,11,15\n},{134,0,1358},{136,11,554},{132,10,498},{7,10,217},{8,10,140},{138,10,610},{135\n,11,989},{135,11,634},{6,0,155},{140,0,234},{135,11,462},{132,11,618},{134,0,\n1628},{132,0,766},{4,11,339},{5,10,905},{135,11,259},{135,0,829},{4,11,759},{141\n,11,169},{4,10,456},{7,0,1445},{7,10,358},{7,10,1637},{8,10,643},{139,10,483},{5\n,0,486},{135,0,1349},{5,11,688},{135,11,712},{7,0,1635},{8,0,17},{10,0,217},{10,\n0,295},{12,0,2},{140,11,2},{138,0,558},{150,10,56},{4,11,278},{5,11,465},{135,11\n,1367},{136,11,482},{133,10,535},{6,0,1362},{6,0,1461},{10,11,274},{10,11,625},{\n139,11,530},{5,0,599},{5,11,336},{6,11,341},{6,11,478},{6,11,1763},{136,11,386},\n{7,10,1748},{137,11,151},{134,0,1376},{133,10,539},{135,11,73},{135,11,1971},{\n139,11,283},{9,0,93},{139,0,474},{6,10,91},{135,10,435},{5,11,396},{6,0,447},{\n134,11,501},{4,10,16},{5,10,316},{5,10,842},{6,10,370},{6,10,1778},{8,10,166},{\n11,10,812},{12,10,206},{12,10,351},{14,10,418},{16,10,15},{16,10,34},{18,10,3},{\n19,10,3},{19,10,7},{20,10,4},{149,10,21},{7,0,577},{7,0,1432},{9,0,475},{9,0,505\n},{9,0,526},{9,0,609},{9,0,689},{9,0,726},{9,0,735},{9,0,738},{10,0,556},{10,0,\n674},{10,0,684},{11,0,89},{11,0,202},{11,0,272},{11,0,380},{11,0,415},{11,0,505}\n,{11,0,537},{11,0,550},{11,0,562},{11,0,640},{11,0,667},{11,0,688},{11,0,847},{\n11,0,927},{11,0,930},{11,0,940},{12,0,144},{12,0,325},{12,0,329},{12,0,389},{12,\n0,403},{12,0,451},{12,0,515},{12,0,604},{12,0,616},{12,0,626},{13,0,66},{13,0,\n131},{13,0,167},{13,0,236},{13,0,368},{13,0,411},{13,0,434},{13,0,453},{13,0,461\n},{13,0,474},{14,0,59},{14,0,60},{14,0,139},{14,0,152},{14,0,276},{14,0,353},{14\n,0,402},{15,0,28},{15,0,81},{15,0,123},{15,0,152},{18,0,136},{148,0,88},{4,11,\n929},{133,11,799},{136,11,46},{142,0,307},{4,0,609},{7,0,756},{9,0,544},{11,0,\n413},{144,0,25},{7,10,619},{10,0,687},{10,10,547},{11,10,122},{140,10,601},{4,0,\n930},{133,0,947},{133,0,939},{142,0,21},{4,11,892},{133,11,770},{133,0,962},{5,0\n,651},{8,0,170},{9,0,61},{9,0,63},{10,0,23},{10,0,37},{10,0,834},{11,0,4},{11,0,\n187},{11,0,281},{11,0,503},{11,0,677},{12,0,96},{12,0,130},{12,0,244},{14,0,5},{\n14,0,40},{14,0,162},{14,0,202},{146,0,133},{4,0,406},{5,0,579},{12,0,492},{150,0\n,15},{135,11,158},{135,0,597},{132,0,981},{132,10,888},{4,10,149},{138,10,368},{\n132,0,545},{4,10,154},{7,10,1134},{136,10,105},{135,11,2001},{134,0,1558},{4,10,\n31},{6,10,429},{7,10,962},{9,10,458},{139,10,691},{132,10,312},{135,10,1642},{6,\n0,17},{6,0,1304},{7,0,16},{7,0,1001},{9,0,886},{10,0,489},{10,0,800},{11,0,782},\n{12,0,320},{13,0,467},{14,0,145},{14,0,387},{143,0,119},{135,0,1982},{7,11,1461}\n,{12,11,91},{145,0,17},{4,10,236},{132,11,602},{138,0,907},{136,0,110},{5,10,836\n},{5,10,857},{6,10,1680},{7,0,272},{147,0,53},{5,0,458},{7,11,1218},{136,11,303}\n,{7,0,1983},{8,0,0},{8,0,171},{9,0,120},{9,0,732},{10,0,473},{10,10,68},{11,0,\n656},{11,0,998},{11,10,494},{18,0,0},{18,0,2},{147,0,21},{137,11,662},{4,11,13},\n{5,11,567},{7,11,1498},{9,11,124},{11,11,521},{140,11,405},{4,10,81},{139,10,867\n},{135,11,1006},{7,11,800},{7,11,1783},{138,11,12},{5,10,282},{8,10,650},{9,0,\n295},{9,10,907},{138,0,443},{132,11,735},{4,10,775},{4,11,170},{135,11,323},{6,0\n,1844},{10,0,924},{11,11,844},{12,11,104},{140,11,625},{5,11,304},{7,11,1403},{\n140,11,498},{134,0,1232},{4,0,519},{10,0,70},{12,0,26},{14,0,17},{14,0,178},{15,\n0,34},{149,0,12},{132,0,993},{4,11,148},{133,11,742},{6,0,31},{7,0,491},{7,0,530\n},{8,0,592},{11,0,53},{11,0,779},{12,0,167},{12,0,411},{14,0,14},{14,0,136},{15,\n0,72},{16,0,17},{144,0,72},{133,0,907},{134,0,733},{133,11,111},{4,10,71},{5,10,\n376},{7,10,119},{138,10,665},{136,0,55},{8,0,430},{136,11,430},{4,0,208},{5,0,\n106},{6,0,531},{8,0,408},{9,0,188},{138,0,572},{11,10,827},{12,0,56},{14,10,34},\n{143,10,148},{134,0,1693},{133,11,444},{132,10,479},{140,0,441},{9,0,449},{10,0,\n192},{138,0,740},{134,0,928},{4,0,241},{7,10,607},{136,10,99},{8,11,123},{15,11,\n6},{144,11,7},{6,11,285},{8,11,654},{11,11,749},{12,11,190},{12,11,327},{13,11,\n120},{13,11,121},{13,11,327},{15,11,47},{146,11,40},{4,10,41},{5,10,74},{7,10,\n1627},{11,10,871},{140,10,619},{7,0,1525},{11,10,329},{11,10,965},{12,10,241},{\n14,10,354},{15,10,22},{148,10,63},{132,0,259},{135,11,183},{9,10,209},{137,10,\n300},{5,11,937},{135,11,100},{133,10,98},{4,0,173},{5,0,312},{5,0,512},{135,0,\n1285},{141,0,185},{7,0,1603},{7,0,1691},{9,0,464},{11,0,195},{12,0,279},{12,0,\n448},{14,0,11},{147,0,102},{135,0,1113},{133,10,984},{4,0,452},{5,0,583},{135,0,\n720},{4,0,547},{5,0,817},{6,0,433},{7,0,593},{7,0,1378},{8,0,161},{9,0,284},{10,\n0,313},{139,0,886},{4,10,182},{6,10,205},{7,10,220},{136,0,722},{150,0,13},{4,10\n,42},{9,10,205},{9,10,786},{138,10,659},{6,0,289},{7,0,1670},{12,0,57},{151,0,4}\n,{132,10,635},{14,0,43},{146,0,21},{139,10,533},{135,0,1694},{8,0,420},{139,0,\n193},{135,0,409},{132,10,371},{4,10,272},{135,10,836},{5,10,825},{134,10,1640},{\n5,11,251},{5,11,956},{8,11,268},{9,11,214},{146,11,142},{138,0,308},{6,0,1863},{\n141,11,37},{137,10,879},{7,10,317},{135,10,569},{132,11,294},{134,0,790},{5,0,\n1002},{136,0,745},{5,11,346},{5,11,711},{136,11,390},{135,0,289},{5,0,504},{9,10\n,307},{139,0,68},{4,0,239},{6,0,477},{7,0,1607},{139,0,617},{149,0,13},{133,0,\n609},{133,11,624},{5,11,783},{7,11,1998},{135,11,2047},{133,10,525},{132,0,367},\n{132,11,594},{5,10,493},{134,0,528},{4,10,174},{135,10,911},{8,10,417},{137,10,\n782},{132,0,694},{7,0,548},{137,0,58},{4,10,32},{5,10,215},{6,10,269},{7,10,1782\n},{7,10,1892},{10,10,16},{11,10,822},{11,10,954},{141,10,481},{140,0,687},{7,0,\n1749},{136,10,477},{132,11,569},{133,10,308},{135,10,1088},{4,0,661},{138,0,1004\n},{5,11,37},{6,11,39},{6,11,451},{7,11,218},{7,11,667},{7,11,1166},{7,11,1687},{\n8,11,662},{144,11,2},{5,10,126},{8,10,297},{9,0,445},{9,10,366},{12,0,53},{12,10\n,374},{141,0,492},{7,10,1551},{139,10,361},{148,0,74},{134,11,508},{135,0,213},{\n132,10,175},{132,10,685},{6,0,760},{6,0,834},{134,0,1248},{7,11,453},{7,11,635},\n{7,11,796},{8,11,331},{9,11,328},{9,11,330},{9,11,865},{10,11,119},{10,11,235},{\n11,11,111},{11,11,129},{11,11,240},{12,11,31},{12,11,66},{12,11,222},{12,11,269}\n,{12,11,599},{12,11,689},{13,11,186},{13,11,364},{142,11,345},{7,0,1672},{139,0,\n189},{133,10,797},{133,10,565},{6,0,1548},{6,11,98},{7,11,585},{135,11,702},{9,0\n,968},{15,0,192},{149,0,56},{4,10,252},{6,11,37},{7,10,1068},{7,11,299},{7,11,\n1666},{8,11,195},{8,11,316},{9,11,178},{9,11,276},{9,11,339},{9,11,536},{10,10,\n434},{10,11,102},{10,11,362},{10,11,785},{11,10,228},{11,10,426},{11,11,55},{11,\n11,149},{11,11,773},{13,10,231},{13,11,416},{13,11,419},{14,11,38},{14,11,41},{\n14,11,210},{18,10,106},{148,10,87},{4,0,751},{11,0,390},{140,0,32},{4,0,409},{\n133,0,78},{11,11,458},{12,11,15},{140,11,432},{5,10,231},{7,0,1602},{7,10,601},{\n9,10,277},{9,10,674},{10,0,257},{10,0,698},{10,10,178},{10,10,418},{10,10,509},{\n11,0,544},{11,0,585},{11,10,531},{12,0,212},{12,10,113},{12,10,475},{13,0,307},{\n13,10,99},{142,10,428},{6,0,473},{145,0,105},{5,11,645},{6,0,1949},{143,0,156},{\n7,10,1591},{144,10,43},{135,0,1779},{135,10,1683},{4,11,290},{135,11,1356},{134,\n0,763},{6,11,70},{7,11,1292},{10,11,762},{139,11,288},{142,0,29},{140,11,428},{7\n,0,883},{7,11,131},{7,11,422},{8,11,210},{140,11,573},{134,0,488},{4,10,399},{5,\n10,119},{5,10,494},{7,10,751},{137,10,556},{133,0,617},{132,11,936},{139,0,50},{\n7,0,1518},{139,0,694},{137,0,785},{4,0,546},{135,0,2042},{7,11,716},{13,11,97},{\n141,11,251},{132,11,653},{145,0,22},{134,0,1016},{4,0,313},{133,0,577},{136,11,\n657},{8,0,184},{141,0,433},{135,0,935},{6,0,720},{9,0,114},{146,11,80},{7,10,594\n},{7,10,851},{7,10,1858},{9,10,411},{9,10,574},{9,10,666},{9,10,737},{10,10,346}\n,{10,10,712},{11,10,246},{11,10,432},{11,10,517},{11,10,647},{11,10,679},{11,10,\n727},{12,0,186},{12,0,292},{12,10,304},{12,10,305},{12,10,323},{12,10,483},{12,\n10,572},{12,10,593},{12,10,602},{13,10,95},{13,10,101},{13,10,171},{13,10,315},{\n13,10,378},{13,10,425},{13,10,475},{14,0,100},{14,10,63},{14,10,380},{14,10,384}\n,{15,10,133},{18,0,70},{18,10,112},{148,10,72},{135,10,1093},{135,11,1836},{132,\n10,679},{137,10,203},{11,0,402},{12,0,109},{12,0,431},{13,0,179},{13,0,206},{14,\n0,217},{16,0,3},{148,0,53},{7,11,1368},{8,11,232},{8,11,361},{10,11,682},{138,11\n,742},{137,10,714},{5,0,886},{6,0,46},{6,0,1790},{7,0,14},{7,0,732},{7,0,1654},{\n8,0,95},{8,0,327},{8,0,616},{9,0,892},{9,11,534},{10,0,598},{10,0,769},{11,0,134\n},{11,0,747},{12,0,378},{142,0,97},{4,0,969},{136,10,825},{137,11,27},{6,0,727},\n{142,11,12},{133,0,1021},{134,0,1190},{134,11,1657},{5,10,143},{5,10,769},{6,10,\n1760},{7,10,682},{7,10,1992},{136,10,736},{132,0,153},{135,11,127},{133,0,798},{\n132,0,587},{6,0,598},{7,0,42},{8,0,695},{10,0,212},{11,0,158},{14,0,196},{145,0,\n85},{133,10,860},{6,0,1929},{134,0,1933},{5,0,957},{5,0,1008},{6,10,422},{7,10,0\n},{7,10,1544},{8,11,364},{9,0,577},{11,10,990},{12,0,141},{12,10,453},{13,10,47}\n,{141,10,266},{134,0,1319},{4,0,129},{135,0,465},{7,0,470},{7,0,1057},{7,0,1201}\n,{9,0,755},{11,0,906},{140,0,527},{7,0,908},{146,0,7},{5,0,148},{136,0,450},{5,\n10,515},{137,10,131},{7,10,1605},{11,10,962},{146,10,139},{132,10,646},{134,0,\n1166},{4,10,396},{7,10,728},{9,10,117},{13,10,202},{148,10,51},{6,10,121},{6,10,\n124},{6,10,357},{7,10,1138},{7,10,1295},{8,10,162},{139,10,655},{14,0,374},{142,\n11,374},{138,0,253},{139,0,1003},{5,11,909},{9,11,849},{138,11,805},{133,10,237}\n,{7,11,525},{7,11,1579},{8,11,497},{136,11,573},{137,0,46},{132,0,879},{134,0,\n806},{135,0,1868},{6,0,1837},{134,0,1846},{6,0,730},{134,0,881},{7,0,965},{7,0,\n1460},{7,0,1604},{7,11,193},{7,11,397},{7,11,1105},{8,11,124},{8,11,619},{9,11,\n305},{10,11,264},{11,11,40},{12,11,349},{13,11,134},{13,11,295},{14,11,155},{15,\n11,120},{146,11,105},{136,0,506},{143,0,10},{4,11,262},{7,10,571},{7,10,1877},{7\n,11,342},{10,10,366},{141,11,23},{133,11,641},{9,10,513},{10,0,22},{10,10,39},{\n12,10,122},{140,10,187},{135,11,1431},{150,11,49},{4,11,99},{6,11,250},{6,11,346\n},{8,11,127},{138,11,81},{6,0,2014},{8,0,928},{10,0,960},{10,0,979},{140,0,996},\n{134,0,296},{132,11,915},{5,11,75},{9,11,517},{10,11,470},{12,11,155},{141,11,\n224},{137,10,873},{4,0,854},{140,11,18},{134,0,587},{7,10,107},{7,10,838},{8,10,\n550},{138,10,401},{11,0,636},{11,10,588},{11,10,864},{11,10,968},{15,0,145},{15,\n10,160},{17,0,34},{19,0,50},{151,0,20},{135,11,216},{7,0,982},{10,0,32},{143,0,\n56},{133,10,768},{133,11,954},{6,11,304},{7,11,1114},{8,11,418},{10,11,345},{11,\n11,341},{11,11,675},{141,11,40},{9,11,410},{139,11,425},{136,0,941},{4,10,894},{\n133,0,435},{5,0,85},{6,0,419},{7,0,134},{7,0,305},{7,0,361},{7,0,1337},{8,0,71},\n{140,0,519},{140,0,688},{135,0,740},{5,0,691},{7,0,345},{9,0,94},{140,0,169},{5,\n0,183},{6,0,582},{10,0,679},{140,0,435},{134,11,14},{6,0,945},{135,0,511},{134,\n11,1708},{5,11,113},{6,11,243},{7,11,1865},{11,11,161},{16,11,37},{145,11,99},{\n132,11,274},{137,0,539},{6,10,272},{7,0,1993},{136,0,684},{6,0,659},{134,0,982},\n{4,10,9},{5,10,128},{7,10,368},{11,10,480},{148,10,3},{134,0,583},{132,0,803},{\n133,0,704},{4,0,179},{5,0,198},{133,0,697},{7,0,347},{7,0,971},{7,11,166},{8,0,\n181},{138,0,711},{136,10,682},{4,10,2},{7,10,545},{7,10,894},{136,11,521},{135,0\n,481},{132,0,243},{5,0,203},{7,0,19},{7,0,71},{7,0,113},{10,0,405},{11,0,357},{\n142,0,240},{5,11,725},{5,11,727},{135,11,1811},{6,0,826},{137,11,304},{7,0,1450}\n,{139,0,99},{133,11,654},{134,0,492},{5,0,134},{6,0,408},{6,0,495},{6,11,273},{7\n,0,1593},{10,11,188},{13,11,377},{146,11,77},{9,10,769},{140,10,185},{135,11,410\n},{142,0,4},{4,0,665},{134,11,1785},{4,0,248},{7,0,137},{137,0,349},{5,10,530},{\n142,10,113},{7,0,1270},{139,0,612},{132,11,780},{5,0,371},{135,0,563},{135,0,826\n},{6,0,1535},{23,0,21},{151,0,23},{4,0,374},{7,0,547},{7,0,1700},{7,0,1833},{139\n,0,858},{133,10,556},{7,11,612},{8,11,545},{8,11,568},{8,11,642},{9,11,717},{10,\n11,541},{10,11,763},{11,11,449},{12,11,489},{13,11,153},{13,11,296},{14,11,138},\n{14,11,392},{15,11,50},{16,11,6},{16,11,12},{148,11,9},{9,0,311},{141,0,42},{8,\n10,16},{140,10,568},{6,0,1968},{6,0,2027},{138,0,991},{6,0,1647},{7,0,1552},{7,0\n,2010},{9,0,494},{137,0,509},{133,11,948},{6,10,186},{137,10,426},{134,0,769},{\n134,0,642},{132,10,585},{6,0,123},{7,0,214},{9,0,728},{10,0,157},{11,0,346},{11,\n0,662},{143,0,106},{142,11,381},{135,0,1435},{4,11,532},{5,11,706},{135,11,662},\n{5,11,837},{134,11,1651},{4,10,93},{5,10,252},{6,10,229},{7,10,291},{9,10,550},{\n139,10,644},{148,0,79},{137,10,749},{134,0,1425},{137,10,162},{4,11,362},{7,11,\n52},{7,11,303},{140,11,166},{132,10,381},{4,11,330},{7,11,933},{7,11,2012},{136,\n11,292},{135,11,767},{4,0,707},{5,0,588},{6,0,393},{13,0,106},{18,0,49},{147,0,\n41},{6,0,211},{7,0,1690},{11,0,486},{140,0,369},{137,11,883},{4,11,703},{135,11,\n207},{4,0,187},{5,0,184},{5,0,690},{7,0,1869},{10,0,756},{139,0,783},{132,11,571\n},{134,0,1382},{5,0,175},{6,10,77},{6,10,157},{7,10,974},{7,10,1301},{7,10,1339}\n,{7,10,1490},{7,10,1873},{137,10,628},{134,0,1493},{5,11,873},{133,11,960},{134,\n0,1007},{12,11,93},{12,11,501},{13,11,362},{14,11,151},{15,11,40},{15,11,59},{16\n,11,46},{17,11,25},{18,11,14},{18,11,134},{19,11,25},{19,11,69},{20,11,16},{20,\n11,19},{20,11,66},{21,11,23},{21,11,25},{150,11,42},{11,10,919},{141,10,409},{\n134,0,219},{5,0,582},{6,0,1646},{7,0,99},{7,0,1962},{7,0,1986},{8,0,515},{8,0,\n773},{9,0,23},{9,0,491},{12,0,620},{142,0,93},{133,0,851},{5,11,33},{134,11,470}\n,{135,11,1291},{134,0,1278},{135,11,1882},{135,10,1489},{132,0,1000},{138,0,982}\n,{8,0,762},{8,0,812},{137,0,910},{6,11,47},{7,11,90},{7,11,664},{7,11,830},{7,11\n,1380},{7,11,2025},{8,11,448},{136,11,828},{4,0,98},{4,0,940},{6,0,1819},{6,0,\n1834},{6,0,1841},{7,0,1365},{8,0,859},{8,0,897},{8,0,918},{8,10,398},{9,0,422},{\n9,0,670},{9,10,681},{10,0,775},{10,0,894},{10,0,909},{10,0,910},{10,0,935},{11,0\n,210},{11,10,632},{12,0,750},{12,0,755},{13,0,26},{13,0,457},{13,0,476},{16,0,\n100},{16,0,109},{18,0,173},{146,0,175},{9,11,417},{137,11,493},{136,10,645},{138\n,0,906},{134,0,1730},{134,10,20},{133,11,1019},{134,0,1185},{8,10,769},{138,0,40\n},{6,11,208},{137,0,147},{140,0,650},{5,0,209},{6,0,30},{11,0,56},{139,0,305},{\n132,0,553},{138,11,344},{6,11,68},{7,11,398},{7,11,448},{7,11,1629},{7,11,1813},\n{8,11,387},{8,11,442},{9,11,710},{10,11,282},{138,11,722},{5,0,597},{14,0,20},{\n142,11,20},{135,0,1614},{135,10,1757},{4,0,150},{5,0,303},{6,0,327},{135,10,937}\n,{7,10,1652},{16,0,49},{144,11,49},{8,0,192},{10,0,78},{141,0,359},{135,0,786},{\n143,0,134},{6,0,1638},{7,0,79},{7,0,496},{9,0,138},{10,0,336},{11,0,12},{12,0,\n412},{12,0,440},{142,0,305},{136,11,491},{4,10,579},{5,10,226},{5,10,323},{135,\n10,960},{7,0,204},{7,0,415},{8,0,42},{10,0,85},{139,0,564},{132,0,614},{4,11,403\n},{5,11,441},{7,11,450},{11,11,101},{12,11,193},{141,11,430},{135,11,1927},{135,\n11,1330},{4,0,3},{5,0,247},{5,0,644},{7,0,744},{7,0,1207},{7,0,1225},{7,0,1909},\n{146,0,147},{136,0,942},{4,0,1019},{134,0,2023},{5,10,973},{133,11,679},{5,0,285\n},{9,0,67},{13,0,473},{143,0,82},{7,11,328},{137,11,326},{151,0,8},{6,10,135},{\n135,10,1176},{135,11,1128},{134,0,1309},{135,11,1796},{135,10,314},{4,11,574},{7\n,11,350},{7,11,1024},{8,11,338},{9,11,677},{10,11,808},{139,11,508},{7,11,818},{\n17,11,14},{17,11,45},{18,11,75},{148,11,18},{146,10,4},{135,11,1081},{4,0,29},{6\n,0,532},{7,0,1628},{7,0,1648},{9,0,350},{10,0,433},{11,0,97},{11,0,557},{11,0,\n745},{12,0,289},{12,0,335},{12,0,348},{12,0,606},{13,0,116},{13,0,233},{13,0,466\n},{14,0,181},{14,0,209},{14,0,232},{14,0,236},{14,0,300},{16,0,41},{148,0,97},{6\n,10,281},{7,0,318},{8,10,282},{8,10,480},{8,10,499},{9,10,198},{10,10,143},{10,\n10,169},{10,10,211},{10,10,417},{10,10,574},{11,10,147},{11,10,395},{12,10,75},{\n12,10,407},{12,10,608},{13,10,500},{142,10,251},{135,11,1676},{135,11,2037},{135\n,0,1692},{5,0,501},{7,0,1704},{9,0,553},{11,0,520},{12,0,557},{141,0,249},{6,0,\n1527},{14,0,324},{14,11,324},{15,0,55},{15,0,80},{15,11,55},{143,11,80},{135,10,\n1776},{8,0,988},{137,11,297},{132,10,419},{142,0,223},{139,11,234},{7,0,1123},{\n12,0,508},{14,0,102},{14,0,226},{144,0,57},{4,10,138},{7,10,1012},{7,10,1280},{\n137,10,76},{5,10,29},{7,0,1764},{140,10,638},{134,0,2015},{134,0,1599},{138,11,\n56},{6,11,306},{7,11,1140},{7,11,1340},{8,11,133},{138,11,449},{139,11,1011},{6,\n10,1710},{135,10,2038},{7,11,1763},{140,11,310},{4,10,17},{5,10,23},{6,0,129},{7\n,10,995},{11,10,383},{11,10,437},{12,10,460},{140,10,532},{5,11,329},{136,11,260\n},{133,10,862},{132,0,534},{6,0,811},{135,0,626},{132,11,657},{4,0,25},{5,0,60},\n{6,0,504},{7,0,614},{7,0,1155},{12,0,0},{152,11,7},{7,0,1248},{11,0,621},{139,0,\n702},{137,0,321},{8,10,70},{12,10,171},{141,10,272},{10,10,233},{139,10,76},{4,0\n,379},{6,10,442},{135,0,1397},{5,11,66},{7,11,1896},{136,11,288},{134,11,1643},{\n134,10,1709},{4,11,21},{5,11,91},{5,11,570},{5,11,648},{5,11,750},{5,11,781},{6,\n11,54},{6,11,112},{6,11,402},{6,11,1732},{7,11,315},{7,11,749},{7,11,1347},{7,11\n,1900},{9,11,78},{9,11,508},{10,11,611},{11,11,510},{11,11,728},{13,11,36},{14,\n11,39},{16,11,83},{17,11,124},{148,11,30},{4,0,118},{6,0,274},{6,0,361},{7,0,75}\n,{141,0,441},{10,11,322},{10,11,719},{139,11,407},{147,10,119},{12,11,549},{14,\n11,67},{147,11,60},{11,10,69},{12,10,105},{12,10,117},{13,10,213},{14,10,13},{14\n,10,62},{14,10,177},{14,10,421},{15,10,19},{146,10,141},{9,0,841},{137,10,309},{\n7,10,608},{7,10,976},{8,11,125},{8,11,369},{8,11,524},{9,10,146},{10,10,206},{10\n,10,596},{10,11,486},{11,11,13},{11,11,381},{11,11,736},{11,11,766},{11,11,845},\n{13,10,218},{13,11,114},{13,11,292},{14,10,153},{142,11,47},{7,11,759},{140,0,\n693},{5,0,314},{6,0,221},{7,0,419},{10,0,650},{11,0,396},{12,0,156},{13,0,369},{\n14,0,333},{145,0,47},{6,11,1684},{6,11,1731},{7,11,356},{7,11,1932},{8,11,54},{8\n,11,221},{9,11,225},{9,11,356},{10,11,77},{10,11,446},{10,11,731},{12,11,404},{\n141,11,491},{132,11,375},{4,10,518},{135,10,1136},{4,0,913},{4,11,411},{11,11,\n643},{140,11,115},{4,11,80},{133,11,44},{8,10,689},{137,10,863},{138,0,880},{4,\n10,18},{7,10,145},{7,10,444},{7,10,1278},{8,10,49},{8,10,400},{9,10,71},{9,10,\n250},{10,10,459},{12,10,160},{144,10,24},{136,0,475},{5,0,1016},{5,11,299},{135,\n11,1083},{7,0,602},{8,0,179},{10,0,781},{140,0,126},{6,0,329},{138,0,111},{135,0\n,1864},{4,11,219},{7,11,1761},{137,11,86},{6,0,1888},{6,0,1892},{6,0,1901},{6,0,\n1904},{9,0,953},{9,0,985},{9,0,991},{9,0,1001},{12,0,818},{12,0,846},{12,0,847},\n{12,0,861},{12,0,862},{12,0,873},{12,0,875},{12,0,877},{12,0,879},{12,0,881},{12\n,0,884},{12,0,903},{12,0,915},{12,0,926},{12,0,939},{15,0,182},{15,0,219},{15,0,\n255},{18,0,191},{18,0,209},{18,0,211},{149,0,41},{5,11,328},{135,11,918},{137,0,\n780},{12,0,82},{143,0,36},{133,10,1010},{5,0,821},{134,0,1687},{133,11,514},{132\n,0,956},{134,0,1180},{5,10,87},{7,10,313},{7,10,1103},{10,0,112},{10,10,582},{11\n,10,389},{11,10,813},{12,10,385},{13,10,286},{14,10,124},{146,10,108},{5,0,71},{\n7,0,1407},{9,0,704},{10,0,261},{10,0,619},{11,0,547},{11,0,619},{143,0,157},{4,0\n,531},{5,0,455},{5,11,301},{6,11,571},{14,11,49},{146,11,102},{132,10,267},{6,0,\n385},{7,0,2008},{9,0,337},{138,0,517},{133,11,726},{133,11,364},{4,11,76},{7,11,\n1550},{9,11,306},{9,11,430},{9,11,663},{10,11,683},{11,11,427},{11,11,753},{12,\n11,334},{12,11,442},{14,11,258},{14,11,366},{143,11,131},{6,0,1865},{6,0,1879},{\n6,0,1881},{6,0,1894},{6,0,1908},{9,0,915},{9,0,926},{9,0,940},{9,0,943},{9,0,966\n},{9,0,980},{9,0,989},{9,0,1005},{9,0,1010},{12,0,813},{12,0,817},{12,0,840},{12\n,0,843},{12,0,855},{12,0,864},{12,0,871},{12,0,872},{12,0,899},{12,0,905},{12,0,\n924},{15,0,171},{15,0,181},{15,0,224},{15,0,235},{15,0,251},{146,0,184},{137,11,\n52},{5,0,16},{6,0,86},{6,0,603},{7,0,292},{7,0,561},{8,0,257},{8,0,382},{9,0,721\n},{9,0,778},{11,0,581},{140,0,466},{4,0,486},{5,0,491},{135,10,1121},{4,0,72},{6\n,0,265},{135,0,1300},{135,11,1183},{10,10,249},{139,10,209},{132,10,561},{137,11\n,519},{4,10,760},{4,11,656},{135,11,779},{9,10,154},{140,10,485},{135,11,1793},{\n135,11,144},{136,10,255},{133,0,621},{4,10,368},{135,10,641},{135,11,1373},{7,11\n,554},{7,11,605},{141,11,10},{137,0,234},{5,0,815},{6,0,1688},{134,0,1755},{5,11\n,838},{5,11,841},{134,11,1649},{7,0,1987},{7,0,2040},{136,0,743},{133,11,1012},{\n6,0,197},{136,0,205},{6,0,314},{134,11,314},{144,11,53},{6,11,251},{7,11,365},{7\n,11,1357},{7,11,1497},{8,11,154},{141,11,281},{133,11,340},{6,0,452},{7,0,312},{\n138,0,219},{138,0,589},{4,0,333},{9,0,176},{12,0,353},{141,0,187},{9,10,92},{147\n,10,91},{134,0,1110},{11,0,47},{139,11,495},{6,10,525},{8,10,806},{9,10,876},{\n140,10,284},{8,11,261},{9,11,144},{9,11,466},{10,11,370},{12,11,470},{13,11,144}\n,{142,11,348},{137,11,897},{6,11,248},{8,0,863},{8,0,864},{8,0,868},{8,0,884},{9\n,11,546},{10,0,866},{10,0,868},{10,0,873},{10,0,911},{10,0,912},{10,0,944},{10,\n11,535},{11,11,681},{12,0,727},{141,11,135},{6,0,300},{135,0,1515},{134,0,1237},\n{139,10,958},{133,10,594},{140,11,250},{134,0,1685},{134,11,567},{7,0,135},{8,0,\n7},{8,0,62},{9,0,243},{10,0,658},{10,0,697},{11,0,456},{139,0,756},{9,0,395},{\n138,0,79},{6,10,1641},{136,10,820},{4,10,302},{135,10,1766},{134,11,174},{135,10\n,1313},{135,0,631},{134,10,1674},{134,11,395},{138,0,835},{7,0,406},{7,0,459},{8\n,0,606},{139,0,726},{134,11,617},{134,0,979},{6,10,389},{7,10,149},{9,10,142},{\n138,10,94},{5,11,878},{133,11,972},{6,10,8},{7,10,1881},{8,10,91},{136,11,511},{\n133,0,612},{132,11,351},{4,0,372},{7,0,482},{8,0,158},{9,0,602},{9,0,615},{10,0,\n245},{10,0,678},{10,0,744},{11,0,248},{139,0,806},{5,0,854},{135,0,1991},{132,11\n,286},{135,11,344},{7,11,438},{7,11,627},{7,11,1516},{8,11,40},{9,11,56},{9,11,\n294},{10,11,30},{10,11,259},{11,11,969},{146,11,148},{135,0,1492},{5,11,259},{7,\n11,414},{7,11,854},{142,11,107},{135,10,1746},{6,0,833},{134,0,998},{135,10,24},\n{6,0,750},{135,0,1739},{4,10,503},{135,10,1661},{5,10,130},{7,10,1314},{9,10,610\n},{10,10,718},{11,10,601},{11,10,819},{11,10,946},{140,10,536},{10,10,149},{11,\n10,280},{142,10,336},{132,11,738},{135,10,1946},{5,0,195},{135,0,1685},{7,0,1997\n},{8,0,730},{139,0,1006},{151,11,17},{133,11,866},{14,0,463},{14,0,470},{150,0,\n61},{4,10,392},{5,0,751},{7,10,1597},{8,0,266},{139,0,578},{5,10,433},{9,10,633}\n,{139,10,629},{135,0,821},{6,0,715},{134,0,1325},{133,11,116},{4,11,457},{134,0,\n868},{134,0,959},{6,10,234},{138,11,199},{7,0,1053},{7,10,1950},{8,10,680},{11,\n10,817},{147,10,88},{7,10,1222},{138,10,386},{5,0,950},{5,0,994},{6,0,351},{134,\n0,1124},{134,0,1081},{6,10,5},{7,0,1595},{11,10,249},{12,10,313},{16,10,66},{145\n,10,26},{148,0,59},{5,11,527},{6,11,189},{135,11,859},{5,10,963},{6,10,1773},{11\n,11,104},{11,11,554},{15,11,60},{143,11,125},{135,0,47},{137,0,684},{134,11,116}\n,{134,0,1606},{134,0,777},{7,0,1020},{8,10,509},{136,10,792},{135,0,1094},{132,0\n,350},{133,11,487},{4,11,86},{5,11,667},{5,11,753},{6,11,316},{6,11,455},{135,11\n,946},{7,0,1812},{13,0,259},{13,0,356},{14,0,242},{147,0,114},{132,10,931},{133,\n0,967},{4,0,473},{7,0,623},{8,0,808},{9,0,871},{9,0,893},{11,0,38},{11,0,431},{\n12,0,112},{12,0,217},{12,0,243},{12,0,562},{12,0,663},{12,0,683},{13,0,141},{13,\n0,197},{13,0,227},{13,0,406},{13,0,487},{14,0,156},{14,0,203},{14,0,224},{14,0,\n256},{18,0,58},{150,0,0},{138,0,286},{7,10,943},{139,10,614},{135,10,1837},{150,\n11,45},{132,0,798},{4,0,222},{7,0,286},{136,0,629},{4,11,79},{7,11,1773},{10,11,\n450},{11,11,589},{13,11,332},{13,11,493},{14,11,183},{14,11,334},{14,11,362},{14\n,11,368},{14,11,376},{14,11,379},{19,11,90},{19,11,103},{19,11,127},{148,11,90},\n{4,10,90},{5,0,337},{5,10,545},{7,10,754},{9,10,186},{10,10,72},{10,10,782},{11,\n0,513},{11,0,889},{11,0,961},{11,10,577},{11,10,610},{12,0,461},{12,10,354},{12,\n10,362},{12,10,595},{13,0,79},{143,0,121},{141,0,306},{136,0,146},{7,0,1646},{9,\n10,329},{11,10,254},{141,11,124},{4,0,465},{135,0,1663},{132,0,525},{133,11,663}\n,{9,10,187},{10,0,299},{11,10,1016},{17,10,44},{146,0,74},{4,10,506},{7,0,165},{\n7,0,919},{136,10,517},{5,10,295},{135,10,1680},{133,11,846},{134,0,1064},{5,11,\n378},{7,11,1402},{7,11,1414},{8,11,465},{9,11,286},{10,11,185},{10,11,562},{10,\n11,635},{11,11,31},{11,11,393},{12,11,456},{13,11,312},{18,11,65},{18,11,96},{\n147,11,89},{132,0,596},{7,10,987},{9,10,688},{10,10,522},{11,10,788},{140,10,566\n},{4,11,648},{6,0,82},{6,10,1775},{7,0,138},{7,0,517},{7,0,1741},{139,0,238},{7,\n0,1233},{7,10,700},{7,10,940},{8,10,514},{9,10,116},{9,10,535},{10,10,118},{11,\n10,107},{11,10,148},{11,10,922},{12,10,254},{12,10,421},{142,10,238},{4,0,962},{\n6,0,1824},{8,0,894},{12,0,708},{12,0,725},{14,0,451},{20,0,94},{22,0,59},{150,0,\n62},{5,11,945},{6,11,1656},{6,11,1787},{7,11,167},{8,11,824},{9,11,391},{10,11,\n375},{139,11,185},{5,0,495},{7,0,834},{9,0,733},{139,0,378},{4,10,743},{135,11,\n1273},{6,0,1204},{7,11,1645},{8,11,352},{137,11,249},{139,10,292},{133,0,559},{\n132,11,152},{7,10,1283},{9,0,499},{9,10,227},{10,0,341},{11,10,325},{11,10,408},\n{14,10,180},{15,0,144},{18,10,47},{147,0,49},{6,0,21},{6,0,1737},{7,0,1444},{136\n,0,224},{133,11,1006},{5,10,81},{7,0,1446},{7,10,146},{7,10,1342},{8,10,53},{8,\n10,561},{8,10,694},{8,10,754},{9,0,97},{9,10,115},{9,10,894},{10,10,462},{10,10,\n813},{11,10,230},{11,10,657},{11,10,699},{11,10,748},{12,10,119},{12,10,200},{12\n,10,283},{14,10,273},{145,0,15},{5,10,408},{137,10,747},{135,11,431},{135,11,832\n},{6,0,729},{134,0,953},{4,0,727},{5,11,351},{7,11,264},{8,0,565},{136,11,565},{\n134,0,1948},{5,0,519},{5,11,40},{7,11,598},{7,11,1638},{8,11,78},{9,11,166},{9,\n11,640},{9,11,685},{9,11,773},{11,11,215},{13,11,65},{14,11,172},{14,11,317},{\n145,11,6},{8,11,60},{9,11,343},{139,11,769},{137,11,455},{134,0,1193},{140,0,790\n},{7,11,1951},{8,11,765},{8,11,772},{140,11,671},{7,11,108},{8,11,219},{8,11,388\n},{9,11,639},{9,11,775},{11,11,275},{140,11,464},{132,11,468},{7,10,30},{8,10,86\n},{8,10,315},{8,10,700},{9,10,576},{9,10,858},{11,10,310},{11,10,888},{11,10,904\n},{12,10,361},{141,10,248},{5,11,15},{6,11,56},{7,11,1758},{8,11,500},{9,11,730}\n,{11,11,331},{13,11,150},{142,11,282},{4,0,402},{7,0,2},{8,0,323},{136,0,479},{\n138,10,839},{11,0,580},{142,0,201},{5,0,59},{135,0,672},{137,10,617},{146,0,34},\n{134,11,1886},{4,0,961},{136,0,896},{5,11,205},{6,0,1285},{6,11,438},{137,11,711\n},{134,10,428},{7,10,524},{8,10,169},{8,10,234},{9,10,480},{138,10,646},{148,0,\n46},{141,0,479},{133,11,534},{6,0,2019},{134,10,1648},{4,0,85},{7,0,549},{7,10,\n1205},{138,10,637},{4,0,663},{5,0,94},{7,11,235},{7,11,1475},{15,11,68},{146,11,\n120},{6,11,443},{9,11,237},{9,11,571},{9,11,695},{10,11,139},{11,11,715},{12,11,\n417},{141,11,421},{132,0,783},{4,0,682},{8,0,65},{9,10,39},{10,10,166},{11,10,\n918},{12,10,635},{20,10,10},{22,10,27},{22,10,43},{150,10,52},{6,0,11},{135,0,\n187},{132,0,522},{4,0,52},{135,0,661},{4,0,383},{133,0,520},{135,11,546},{11,0,\n343},{142,0,127},{4,11,578},{7,10,157},{7,11,624},{7,11,916},{8,10,279},{10,11,\n256},{11,11,87},{139,11,703},{134,10,604},{4,0,281},{5,0,38},{7,0,194},{7,0,668}\n,{7,0,1893},{137,0,397},{7,10,945},{11,10,713},{139,10,744},{139,10,1022},{9,0,\n635},{139,0,559},{5,11,923},{7,11,490},{12,11,553},{13,11,100},{14,11,118},{143,\n11,75},{132,0,975},{132,10,567},{137,10,859},{7,10,1846},{7,11,1846},{8,10,628},\n{136,11,628},{148,0,116},{138,11,750},{14,0,51},{14,11,51},{15,11,7},{148,11,20}\n,{132,0,858},{134,0,1075},{4,11,924},{133,10,762},{136,0,535},{133,0,448},{10,10\n,784},{141,10,191},{133,10,298},{7,0,610},{135,0,1501},{7,10,633},{7,10,905},{7,\n10,909},{7,10,1538},{9,10,767},{140,10,636},{4,11,265},{7,11,807},{135,11,950},{\n5,11,93},{12,11,267},{144,11,26},{136,0,191},{139,10,301},{135,10,1970},{135,0,\n267},{4,0,319},{5,0,699},{138,0,673},{6,0,336},{7,0,92},{7,0,182},{8,0,453},{8,0\n,552},{9,0,204},{9,0,285},{10,0,99},{11,0,568},{11,0,950},{12,0,94},{12,10,644},\n{16,0,20},{16,0,70},{16,10,90},{147,0,55},{6,0,551},{7,0,1308},{7,10,845},{7,11,\n994},{8,10,160},{137,10,318},{19,11,1},{19,11,26},{150,11,9},{7,0,1406},{9,0,218\n},{141,0,222},{5,0,256},{138,0,69},{5,11,233},{5,11,320},{6,11,140},{7,11,330},{\n136,11,295},{6,0,1980},{136,0,952},{4,0,833},{137,11,678},{133,11,978},{4,11,905\n},{6,11,1701},{137,11,843},{138,10,735},{136,10,76},{17,0,39},{148,0,36},{18,0,\n81},{146,11,81},{14,0,352},{17,0,53},{18,0,146},{18,0,152},{19,0,11},{150,0,54},\n{135,0,634},{138,10,841},{132,0,618},{4,0,339},{4,11,275},{7,0,259},{12,11,376},\n{145,0,73},{132,11,509},{7,11,273},{139,11,377},{4,0,759},{9,10,804},{141,0,169}\n,{6,10,96},{135,10,1426},{4,10,651},{133,10,289},{7,0,1075},{8,10,35},{9,10,511}\n,{10,10,767},{147,10,118},{6,0,649},{6,0,670},{136,0,482},{5,0,336},{6,0,341},{6\n,0,478},{6,0,1763},{136,0,386},{5,11,802},{7,11,2021},{8,11,805},{14,11,94},{15,\n11,65},{16,11,4},{16,11,77},{16,11,80},{145,11,5},{5,11,167},{5,11,899},{6,0,\n1035},{6,11,410},{137,11,777},{134,11,1705},{5,0,924},{133,0,969},{132,10,704},{\n135,0,73},{135,11,10},{135,10,1078},{5,11,11},{6,11,117},{6,11,485},{7,11,1133},\n{9,11,582},{9,11,594},{11,11,21},{11,11,818},{12,11,535},{141,11,86},{135,0,1971\n},{4,11,264},{7,11,1067},{8,11,204},{8,11,385},{139,11,953},{6,0,1458},{135,0,\n1344},{5,0,396},{134,0,501},{4,10,720},{133,10,306},{4,0,929},{5,0,799},{5,10,\n431},{8,0,46},{136,0,740},{7,11,646},{7,11,1730},{11,11,446},{141,11,178},{5,10,\n464},{6,10,236},{7,0,276},{7,10,696},{7,10,914},{7,10,1108},{7,10,1448},{9,10,15\n},{9,10,564},{10,10,14},{12,10,565},{13,10,449},{14,10,53},{15,10,13},{16,10,64}\n,{145,10,41},{4,0,892},{133,0,770},{6,10,1767},{12,10,194},{145,10,107},{135,0,\n158},{5,10,840},{138,11,608},{134,0,1432},{138,11,250},{8,11,794},{9,11,400},{10\n,11,298},{142,11,228},{151,0,25},{7,11,1131},{135,11,1468},{135,0,2001},{9,10,\n642},{11,10,236},{142,10,193},{4,10,68},{5,10,634},{6,10,386},{7,10,794},{8,10,\n273},{9,10,563},{10,10,105},{10,10,171},{11,10,94},{139,10,354},{136,11,724},{\n132,0,478},{11,11,512},{13,11,205},{19,11,30},{22,11,36},{151,11,19},{7,0,1461},\n{140,0,91},{6,11,190},{7,11,768},{135,11,1170},{4,0,602},{4,10,95},{7,10,416},{8\n,0,211},{139,10,830},{7,10,731},{13,10,20},{143,10,11},{6,0,1068},{135,0,1872},{\n4,0,13},{5,0,567},{7,0,1498},{7,11,1023},{9,0,124},{11,0,521},{140,0,405},{135,0\n,1006},{132,0,735},{138,0,812},{4,0,170},{135,0,323},{6,11,137},{9,11,75},{9,11,\n253},{10,11,194},{138,11,444},{5,0,304},{5,10,864},{7,0,1403},{10,10,648},{11,10\n,671},{143,10,46},{135,11,1180},{133,10,928},{4,0,148},{133,0,742},{11,10,986},{\n140,10,682},{133,0,523},{135,11,1743},{7,0,730},{8,10,44},{9,10,884},{10,10,580}\n,{11,10,399},{11,10,894},{15,10,122},{18,0,144},{147,0,61},{5,11,760},{7,11,542}\n,{8,11,135},{136,11,496},{136,0,981},{133,0,111},{10,0,132},{11,0,191},{11,0,358\n},{139,0,460},{7,11,319},{7,11,355},{7,11,763},{10,11,389},{145,11,43},{134,0,\n890},{134,0,1420},{136,11,557},{133,10,518},{133,0,444},{135,0,1787},{135,10,\n1852},{8,0,123},{15,0,6},{144,0,7},{6,0,2041},{10,11,38},{139,11,784},{136,0,932\n},{5,0,937},{135,0,100},{4,11,58},{5,11,286},{6,0,995},{6,11,319},{7,11,402},{7,\n11,1254},{7,11,1903},{8,11,356},{140,11,408},{4,11,389},{9,11,181},{9,11,255},{\n10,11,8},{10,11,29},{10,11,816},{11,11,311},{11,11,561},{12,11,67},{141,11,181},\n{138,0,255},{4,10,934},{5,0,138},{136,10,610},{4,0,965},{10,0,863},{138,0,898},{\n10,10,804},{138,10,832},{8,10,96},{9,10,36},{10,10,607},{11,10,423},{11,10,442},\n{12,0,631},{12,10,309},{14,10,199},{15,10,90},{145,10,110},{134,0,1394},{4,0,652\n},{8,0,320},{9,10,13},{9,10,398},{9,10,727},{10,10,75},{10,10,184},{10,10,230},{\n10,10,564},{10,10,569},{11,10,973},{12,10,70},{12,10,189},{13,10,57},{13,10,257}\n,{22,0,6},{150,0,16},{6,0,897},{134,0,1333},{4,0,692},{133,0,321},{133,11,373},{\n135,0,922},{5,0,619},{133,0,698},{137,10,631},{5,10,345},{135,10,1016},{9,0,957}\n,{9,0,1018},{12,0,828},{12,0,844},{12,0,897},{12,0,901},{12,0,943},{15,0,180},{\n18,0,197},{18,0,200},{18,0,213},{18,0,214},{146,0,226},{5,0,917},{134,0,1659},{\n135,0,1100},{134,0,1173},{134,0,1930},{5,0,251},{5,0,956},{8,0,268},{9,0,214},{\n146,0,142},{133,10,673},{137,10,850},{4,10,287},{133,10,1018},{132,11,672},{5,0,\n346},{5,0,711},{8,0,390},{11,11,752},{139,11,885},{5,10,34},{10,10,724},{12,10,\n444},{13,10,354},{18,10,32},{23,10,24},{23,10,31},{152,10,5},{4,11,710},{134,11,\n606},{134,0,744},{134,10,382},{133,11,145},{4,10,329},{7,11,884},{140,11,124},{4\n,11,467},{5,11,405},{134,11,544},{9,10,846},{138,10,827},{133,0,624},{9,11,372},\n{15,11,2},{19,11,10},{147,11,18},{4,11,387},{135,11,1288},{5,0,783},{7,0,1998},{\n135,0,2047},{132,10,906},{136,10,366},{135,11,550},{4,10,123},{4,10,649},{5,10,\n605},{7,10,1509},{136,10,36},{134,0,1125},{132,0,594},{133,10,767},{135,11,1227}\n,{136,11,467},{4,11,576},{135,11,1263},{4,0,268},{7,0,1534},{135,11,1534},{4,10,\n273},{5,10,658},{5,10,995},{5,11,919},{134,11,1673},{133,0,563},{134,10,72},{135\n,10,1345},{4,11,82},{5,11,333},{5,11,904},{6,11,207},{7,11,325},{7,11,1726},{8,\n11,101},{10,11,778},{139,11,220},{5,0,37},{5,10,589},{6,0,39},{6,0,451},{7,0,218\n},{7,0,667},{7,0,1166},{7,0,1687},{8,0,662},{144,0,2},{134,0,1332},{133,11,903},\n{134,0,508},{5,10,117},{6,10,514},{6,10,541},{7,10,1164},{7,10,1436},{8,10,220},\n{8,10,648},{10,10,688},{11,10,560},{140,11,147},{6,11,555},{135,11,485},{133,10,\n686},{7,0,453},{7,0,635},{7,0,796},{8,0,331},{9,0,330},{9,0,865},{10,0,119},{10,\n0,235},{11,0,111},{11,0,129},{11,0,240},{12,0,31},{12,0,66},{12,0,222},{12,0,269\n},{12,0,599},{12,0,684},{12,0,689},{12,0,691},{142,0,345},{135,0,1834},{4,11,705\n},{7,11,615},{138,11,251},{136,11,345},{137,0,527},{6,0,98},{7,0,702},{135,0,991\n},{7,10,196},{10,10,765},{11,0,576},{11,10,347},{11,10,552},{11,10,790},{12,10,\n263},{13,10,246},{13,10,270},{13,10,395},{14,0,74},{14,10,176},{14,10,190},{14,\n10,398},{14,10,412},{15,10,32},{15,10,63},{16,10,88},{147,10,105},{134,11,90},{\n13,0,84},{141,0,122},{6,0,37},{7,0,299},{7,0,1666},{8,0,195},{8,0,316},{9,0,178}\n,{9,0,276},{9,0,339},{9,0,536},{10,0,102},{10,0,362},{10,0,785},{11,0,55},{11,0,\n149},{11,0,773},{13,0,416},{13,0,419},{14,0,38},{14,0,41},{142,0,210},{5,10,381}\n,{135,10,1792},{7,11,813},{12,11,497},{141,11,56},{7,10,616},{138,10,413},{133,0\n,645},{6,11,125},{135,11,1277},{132,0,290},{6,0,70},{7,0,1292},{10,0,762},{139,0\n,288},{6,10,120},{7,10,1188},{7,10,1710},{8,10,286},{9,10,667},{11,10,592},{139,\n10,730},{135,11,1784},{7,0,1315},{135,11,1315},{134,0,1955},{135,10,1146},{7,0,\n131},{7,0,422},{8,0,210},{140,0,573},{4,10,352},{135,10,687},{139,0,797},{143,0,\n38},{14,0,179},{15,0,151},{150,0,11},{4,10,192},{5,10,49},{6,10,200},{6,10,293},\n{6,10,1696},{135,0,488},{132,0,936},{135,11,703},{6,11,160},{7,11,1106},{9,11,\n770},{10,11,618},{11,11,112},{140,11,413},{5,0,453},{134,0,441},{135,0,595},{132\n,10,650},{132,10,147},{6,0,991},{6,0,1182},{12,11,271},{145,11,109},{133,10,934}\n,{140,11,221},{132,0,653},{7,0,505},{135,0,523},{134,0,903},{135,11,479},{7,11,\n304},{9,11,646},{9,11,862},{10,11,262},{11,11,696},{12,11,208},{15,11,79},{147,\n11,108},{146,0,80},{135,11,981},{142,0,432},{132,0,314},{137,11,152},{7,0,1368},\n{8,0,232},{8,0,361},{10,0,682},{138,0,742},{135,11,1586},{4,11,434},{9,0,534},{\n11,11,663},{12,11,210},{13,11,166},{13,11,310},{14,11,373},{147,11,43},{7,11,\n1091},{135,11,1765},{6,11,550},{135,11,652},{137,0,27},{142,0,12},{4,10,637},{5,\n11,553},{7,11,766},{138,11,824},{7,11,737},{8,11,298},{136,11,452},{7,0,736},{\n139,0,264},{134,0,1657},{133,11,292},{138,11,135},{6,0,844},{134,0,1117},{135,0,\n127},{9,10,867},{138,10,837},{6,0,1184},{134,0,1208},{134,0,1294},{136,0,364},{6\n,0,1415},{6,10,170},{7,0,1334},{7,11,393},{8,10,395},{8,10,487},{10,11,603},{11,\n0,125},{11,11,206},{141,10,147},{137,11,748},{4,11,912},{137,11,232},{4,10,535},\n{136,10,618},{137,0,792},{7,11,1973},{136,11,716},{135,11,98},{5,0,909},{9,0,849\n},{138,0,805},{4,0,630},{132,0,699},{5,11,733},{14,11,103},{150,10,23},{12,11,\n158},{18,11,8},{19,11,62},{20,11,6},{22,11,4},{23,11,2},{151,11,9},{132,0,968},{\n132,10,778},{132,10,46},{5,10,811},{6,10,1679},{6,10,1714},{135,10,2032},{6,0,\n1446},{7,10,1458},{9,10,407},{139,10,15},{6,10,34},{7,0,206},{7,0,397},{7,0,621}\n,{7,0,640},{7,10,1089},{8,0,124},{8,0,619},{8,10,708},{8,10,721},{9,0,305},{9,0,\n643},{9,10,363},{10,0,264},{10,0,628},{11,0,40},{12,0,349},{13,0,134},{13,0,295}\n,{14,0,155},{15,0,120},{18,0,105},{148,10,98},{4,0,262},{5,0,641},{135,0,342},{\n137,11,72},{4,0,99},{6,0,250},{6,0,346},{8,0,127},{138,0,81},{132,0,915},{5,0,75\n},{9,0,517},{10,0,470},{12,0,155},{141,0,224},{132,10,462},{11,11,600},{11,11,\n670},{141,11,245},{142,0,83},{5,10,73},{6,10,23},{134,10,338},{6,0,1031},{139,11\n,923},{7,11,164},{7,11,1571},{9,11,107},{140,11,225},{134,0,1470},{133,0,954},{6\n,0,304},{8,0,418},{10,0,345},{11,0,341},{139,0,675},{9,0,410},{139,0,425},{4,11,\n27},{5,11,484},{5,11,510},{6,11,434},{7,11,1000},{7,11,1098},{8,11,2},{136,11,\n200},{134,0,734},{140,11,257},{7,10,725},{8,10,498},{139,10,268},{134,0,1822},{\n135,0,1798},{135,10,773},{132,11,460},{4,11,932},{133,11,891},{134,0,14},{132,10\n,583},{7,10,1462},{8,11,625},{139,10,659},{5,0,113},{5,10,220},{6,0,243},{6,0,\n1708},{7,0,1865},{11,0,161},{16,0,37},{145,0,99},{134,11,76},{5,11,461},{135,11,\n1925},{140,0,69},{8,11,92},{137,11,221},{139,10,803},{132,10,544},{4,0,274},{134\n,0,922},{132,0,541},{5,0,627},{6,10,437},{6,10,564},{11,10,181},{141,10,183},{\n135,10,1192},{4,11,763},{135,0,166},{133,11,253},{134,0,849},{9,11,73},{10,11,\n110},{14,11,185},{145,11,119},{5,11,212},{12,11,35},{141,11,382},{133,0,717},{\n137,0,304},{136,0,600},{133,0,654},{6,0,273},{10,0,188},{13,0,377},{146,0,77},{4\n,10,790},{5,10,273},{134,10,394},{132,0,543},{135,0,410},{11,0,98},{11,0,524},{\n141,0,87},{132,0,941},{135,11,1175},{4,0,250},{6,10,127},{7,0,1612},{7,10,1511},\n{8,10,613},{11,0,186},{12,0,133},{12,10,495},{12,10,586},{12,10,660},{12,10,668}\n,{14,10,385},{15,10,118},{17,10,20},{146,10,98},{5,11,816},{134,0,1785},{134,0,\n1339},{6,10,230},{7,0,961},{7,0,1085},{7,0,1727},{7,11,1727},{136,0,462},{7,10,\n1954},{137,0,636},{132,0,780},{5,11,869},{5,11,968},{6,11,1626},{8,11,734},{136,\n11,784},{4,11,542},{6,11,1716},{6,11,1727},{7,11,1082},{7,11,1545},{8,11,56},{8,\n11,118},{8,11,412},{8,11,564},{9,11,888},{9,11,908},{10,11,50},{10,11,423},{11,\n11,685},{11,11,697},{11,11,933},{12,11,299},{13,11,126},{13,11,136},{13,11,170},\n{141,11,190},{134,11,226},{4,11,232},{9,11,202},{10,11,474},{140,11,433},{137,11\n,500},{5,0,529},{136,10,68},{132,10,654},{4,10,156},{7,10,998},{7,10,1045},{7,10\n,1860},{9,10,48},{9,10,692},{11,10,419},{139,10,602},{6,11,108},{7,0,1276},{7,11\n,1003},{7,11,1181},{8,0,474},{8,11,343},{137,0,652},{7,11,1264},{7,11,1678},{11,\n11,945},{12,11,341},{12,11,471},{140,11,569},{134,11,1712},{5,0,948},{12,0,468},\n{19,0,96},{148,0,24},{4,11,133},{7,11,711},{7,11,1298},{7,11,1585},{135,11,1929}\n,{6,0,753},{140,0,657},{139,0,941},{6,11,99},{7,11,1808},{145,11,57},{6,11,574},\n{7,11,428},{7,11,1250},{10,11,669},{11,11,485},{11,11,840},{12,11,300},{142,11,\n250},{4,0,532},{5,0,706},{135,0,662},{5,0,837},{6,0,1651},{139,0,985},{7,0,1861}\n,{9,10,197},{10,10,300},{12,10,473},{13,10,90},{141,10,405},{137,11,252},{6,11,\n323},{135,11,1564},{4,0,330},{4,0,863},{7,0,933},{7,0,2012},{7,11,461},{8,0,292}\n,{8,11,775},{138,11,435},{132,10,606},{4,11,655},{7,11,850},{17,11,75},{146,11,\n137},{135,0,767},{7,10,1978},{136,10,676},{132,0,641},{135,11,1559},{134,0,1233}\n,{137,0,242},{4,10,361},{5,10,315},{145,0,114},{137,0,883},{132,10,461},{138,0,\n274},{134,0,2008},{134,0,1794},{4,0,703},{135,0,207},{4,10,472},{140,0,285},{132\n,0,571},{5,0,873},{5,0,960},{8,0,823},{8,11,577},{137,0,881},{7,0,617},{10,0,498\n},{11,0,501},{12,0,16},{140,0,150},{138,10,747},{132,0,431},{133,10,155},{7,10,\n163},{8,10,319},{9,10,402},{10,10,24},{10,10,681},{11,0,283},{11,0,567},{11,10,\n200},{12,10,253},{12,10,410},{142,10,219},{4,11,413},{5,11,677},{8,11,432},{140,\n11,280},{5,10,475},{7,10,1780},{9,0,401},{11,10,297},{11,10,558},{14,10,322},{\n147,10,76},{6,0,781},{9,0,134},{10,0,2},{10,0,27},{10,0,333},{11,0,722},{143,0,1\n},{5,0,33},{6,0,470},{139,0,424},{135,0,2006},{7,10,1956},{140,0,783},{136,0,274\n},{135,0,1882},{132,0,794},{135,0,1848},{5,10,944},{134,10,1769},{6,0,47},{7,0,\n90},{7,0,664},{7,0,830},{7,0,1380},{7,0,2025},{8,0,448},{136,0,828},{132,10,144}\n,{134,0,1199},{4,11,395},{139,11,762},{135,11,1504},{9,0,417},{137,0,493},{9,11,\n174},{10,11,164},{11,11,440},{11,11,841},{143,11,98},{134,11,426},{139,11,1002},\n{134,0,295},{134,0,816},{6,10,247},{137,10,555},{133,0,1019},{4,0,620},{5,11,476\n},{10,10,280},{138,10,797},{139,0,464},{5,11,76},{6,11,458},{6,11,497},{7,11,764\n},{7,11,868},{9,11,658},{10,11,594},{11,11,173},{11,11,566},{12,11,20},{12,11,\n338},{141,11,200},{134,0,208},{4,11,526},{7,11,1029},{135,11,1054},{132,11,636},\n{6,11,233},{7,11,660},{7,11,1124},{17,11,31},{19,11,22},{151,11,14},{5,10,428},{\n138,0,442},{10,0,930},{140,0,778},{6,0,68},{7,0,448},{7,0,1629},{7,0,1769},{7,0,\n1813},{7,10,1717},{8,0,442},{8,0,516},{9,0,710},{10,0,282},{10,0,722},{138,10,\n546},{134,0,1128},{11,0,844},{12,0,104},{140,0,625},{4,11,432},{135,11,824},{138\n,10,189},{133,0,787},{133,10,99},{4,11,279},{7,11,301},{137,11,362},{4,10,397},{\n8,0,491},{136,10,555},{4,11,178},{133,11,399},{134,0,711},{144,0,9},{4,0,403},{5\n,0,441},{7,0,450},{10,0,840},{11,0,101},{12,0,193},{141,0,430},{135,11,1246},{12\n,10,398},{20,10,39},{21,10,11},{150,10,41},{4,10,485},{7,10,353},{135,10,1523},{\n6,10,366},{7,10,1384},{7,10,1601},{135,11,1912},{7,0,396},{7,11,396},{138,0,160}\n,{137,10,282},{134,11,1692},{4,10,157},{5,10,471},{6,11,202},{10,11,448},{11,11,\n208},{12,11,360},{17,11,117},{17,11,118},{18,11,27},{148,11,67},{133,0,679},{137\n,0,326},{136,10,116},{7,11,872},{10,11,516},{139,11,167},{132,11,224},{5,11,546}\n,{7,11,35},{8,11,11},{8,11,12},{9,11,315},{9,11,533},{10,11,802},{11,11,166},{12\n,11,525},{142,11,243},{7,0,1128},{135,11,1920},{5,11,241},{8,11,242},{9,11,451},\n{10,11,667},{11,11,598},{140,11,429},{5,10,160},{6,0,737},{7,10,363},{7,10,589},\n{10,10,170},{141,10,55},{135,0,1796},{142,11,254},{4,0,574},{7,0,350},{7,0,1024}\n,{8,0,338},{9,0,677},{138,0,808},{134,0,1096},{137,11,516},{4,10,108},{4,11,366}\n,{7,0,405},{10,0,491},{139,10,498},{11,11,337},{142,11,303},{134,11,1736},{7,0,\n1081},{140,11,364},{7,10,1005},{140,10,609},{4,10,895},{5,10,772},{135,0,1676},{\n135,0,2037},{6,0,1207},{11,11,916},{142,11,419},{14,11,140},{148,11,41},{6,11,\n331},{136,11,623},{4,10,926},{5,10,983},{9,0,944},{9,0,969},{9,0,1022},{12,0,913\n},{12,0,936},{15,0,177},{143,0,193},{5,0,354},{135,11,506},{8,0,598},{9,0,664},{\n138,0,441},{4,11,640},{133,11,513},{137,0,297},{132,10,538},{6,10,294},{7,10,\n1267},{136,10,624},{7,0,1772},{7,11,1888},{8,11,289},{11,11,45},{12,11,278},{140\n,11,537},{135,10,1325},{138,0,751},{141,0,37},{134,0,1828},{132,10,757},{132,11,\n394},{6,0,257},{135,0,1522},{4,0,582},{7,11,1931},{137,0,191},{7,11,574},{7,11,\n1719},{137,11,145},{132,11,658},{4,11,369},{138,0,790},{9,11,781},{10,11,144},{\n11,11,385},{13,11,161},{13,11,228},{13,11,268},{148,11,107},{8,0,469},{8,11,374}\n,{138,0,47},{6,0,306},{7,0,1140},{7,0,1340},{8,0,133},{138,0,449},{139,0,1011},{\n7,10,1875},{139,10,124},{4,11,344},{6,11,498},{139,11,323},{137,0,299},{132,0,\n837},{133,11,906},{5,0,329},{8,0,260},{138,0,10},{134,0,1320},{4,0,657},{146,0,\n158},{135,0,1191},{152,0,7},{6,0,1939},{8,0,974},{138,0,996},{135,0,1665},{11,11\n,126},{139,11,287},{143,0,8},{14,11,149},{14,11,399},{143,11,57},{5,0,66},{7,0,\n1896},{136,0,288},{5,10,150},{7,0,175},{8,10,603},{9,10,593},{9,10,634},{10,0,\n494},{10,10,173},{11,10,462},{11,10,515},{13,10,216},{13,10,288},{142,10,400},{\n134,0,1643},{136,11,21},{4,0,21},{5,0,91},{5,0,648},{5,0,750},{5,0,781},{6,0,54}\n,{6,0,112},{6,0,402},{6,0,1732},{7,0,315},{7,0,749},{7,0,1427},{7,0,1900},{9,0,\n78},{9,0,508},{10,0,611},{10,0,811},{11,0,510},{11,0,728},{13,0,36},{14,0,39},{\n16,0,83},{17,0,124},{148,0,30},{4,0,668},{136,0,570},{10,0,322},{10,0,719},{139,\n0,407},{135,11,1381},{136,11,193},{12,10,108},{141,10,291},{132,11,616},{136,11,\n692},{8,0,125},{8,0,369},{8,0,524},{10,0,486},{11,0,13},{11,0,381},{11,0,736},{\n11,0,766},{11,0,845},{13,0,114},{13,0,292},{142,0,47},{134,0,1247},{6,0,1684},{6\n,0,1731},{7,0,356},{8,0,54},{8,0,221},{9,0,225},{9,0,356},{10,0,77},{10,0,446},{\n10,0,731},{12,0,404},{141,0,491},{135,10,1777},{4,10,493},{4,11,305},{144,10,55}\n,{4,0,951},{6,0,1809},{6,0,1849},{8,0,846},{8,0,866},{8,0,899},{10,0,896},{12,0,\n694},{142,0,468},{5,11,214},{7,11,603},{8,11,611},{9,11,686},{10,11,88},{11,11,\n459},{11,11,496},{12,11,463},{12,11,590},{13,11,0},{142,11,214},{132,0,411},{4,0\n,80},{133,0,44},{140,11,74},{143,0,31},{6,10,568},{7,0,669},{7,10,1804},{8,10,\n362},{8,10,410},{8,10,830},{9,10,514},{11,10,649},{142,10,157},{6,11,1703},{135,\n0,673},{132,10,625},{134,0,1303},{5,0,299},{135,0,1083},{138,0,704},{6,0,275},{6\n,10,158},{7,0,408},{7,10,129},{7,10,181},{8,10,276},{8,10,377},{10,10,523},{11,\n10,816},{12,10,455},{13,10,303},{142,10,135},{4,0,219},{7,0,367},{7,0,1713},{7,0\n,1761},{9,0,86},{9,0,537},{10,0,165},{12,0,219},{140,0,561},{4,10,1},{4,11,737},\n{6,11,317},{7,10,1143},{7,10,1463},{8,0,216},{9,10,207},{9,10,390},{9,10,467},{\n10,11,98},{11,10,836},{11,11,294},{12,11,60},{12,11,437},{13,11,64},{13,11,380},\n{142,11,430},{6,11,1758},{8,11,520},{9,11,345},{9,11,403},{142,11,350},{5,11,47}\n,{10,11,242},{138,11,579},{5,11,139},{7,11,1168},{138,11,539},{135,0,1319},{4,10\n,295},{4,10,723},{5,10,895},{7,10,1031},{8,10,199},{8,10,340},{9,10,153},{9,10,\n215},{10,10,21},{10,10,59},{10,10,80},{10,10,224},{10,10,838},{11,10,229},{11,10\n,652},{12,10,192},{13,10,146},{142,10,91},{140,0,428},{137,10,51},{133,0,514},{5\n,10,309},{140,10,211},{5,10,125},{6,0,1010},{8,10,77},{138,10,15},{4,0,55},{5,0,\n301},{6,0,571},{142,0,49},{146,0,102},{136,11,370},{4,11,107},{7,11,613},{8,11,\n358},{8,11,439},{8,11,504},{9,11,501},{10,11,383},{139,11,477},{132,11,229},{133\n,0,364},{133,10,439},{4,11,903},{135,11,1816},{11,0,379},{140,10,76},{4,0,76},{4\n,0,971},{7,0,1550},{9,0,306},{9,0,430},{9,0,663},{10,0,683},{10,0,921},{11,0,427\n},{11,0,753},{12,0,334},{12,0,442},{14,0,258},{14,0,366},{143,0,131},{137,0,52},\n{4,11,47},{6,11,373},{7,11,452},{7,11,543},{7,11,1714},{7,11,1856},{9,11,6},{11,\n11,257},{139,11,391},{4,10,8},{7,10,1152},{7,10,1153},{7,10,1715},{9,10,374},{10\n,10,478},{139,10,648},{4,11,785},{133,11,368},{135,10,1099},{135,11,860},{5,11,\n980},{134,11,1754},{134,0,1258},{6,0,1058},{6,0,1359},{7,11,536},{7,11,1331},{\n136,11,143},{4,0,656},{135,0,779},{136,10,87},{5,11,19},{6,11,533},{146,11,126},\n{7,0,144},{138,10,438},{5,11,395},{5,11,951},{134,11,1776},{135,0,1373},{7,0,554\n},{7,0,605},{141,0,10},{4,10,69},{5,10,122},{9,10,656},{138,10,464},{5,10,849},{\n134,10,1633},{5,0,838},{5,0,841},{134,0,1649},{133,0,1012},{139,10,499},{7,10,\n476},{7,10,1592},{138,10,87},{6,0,251},{7,0,365},{7,0,1357},{7,0,1497},{8,0,154}\n,{141,0,281},{132,11,441},{132,11,695},{7,11,497},{9,11,387},{147,11,81},{133,0,\n340},{14,10,283},{142,11,283},{134,0,810},{135,11,1894},{139,0,495},{5,11,284},{\n6,11,49},{6,11,350},{7,11,1},{7,11,377},{7,11,1693},{8,11,18},{8,11,678},{9,11,\n161},{9,11,585},{9,11,671},{9,11,839},{11,11,912},{141,11,427},{5,10,859},{7,10,\n1160},{8,10,107},{9,10,291},{9,10,439},{10,10,663},{11,10,609},{140,10,197},{8,0\n,261},{9,0,144},{9,0,466},{10,0,370},{12,0,470},{13,0,144},{142,0,348},{137,0,\n897},{6,0,248},{9,0,546},{10,0,535},{11,0,681},{141,0,135},{4,0,358},{135,0,1496\n},{134,0,567},{136,0,445},{4,10,117},{6,10,372},{7,10,1905},{142,10,323},{4,10,\n722},{139,10,471},{6,0,697},{134,0,996},{7,11,2007},{9,11,101},{9,11,450},{10,11\n,66},{10,11,842},{11,11,536},{140,11,587},{132,0,577},{134,0,1336},{9,10,5},{12,\n10,216},{12,10,294},{12,10,298},{12,10,400},{12,10,518},{13,10,229},{143,10,139}\n,{6,0,174},{138,0,917},{134,10,1774},{5,10,12},{7,10,375},{9,10,88},{9,10,438},{\n11,10,270},{139,11,62},{134,11,1766},{6,11,0},{7,10,816},{7,10,1241},{7,11,84},{\n9,10,283},{9,10,520},{10,10,213},{10,10,307},{10,10,463},{10,10,671},{10,10,746}\n,{11,10,401},{11,10,794},{11,11,895},{12,10,517},{17,11,11},{18,10,107},{147,10,\n115},{5,0,878},{133,0,972},{6,11,1665},{7,11,256},{7,11,1388},{138,11,499},{4,10\n,258},{136,10,639},{4,11,22},{5,11,10},{6,10,22},{7,10,903},{7,10,1963},{7,11,\n848},{8,11,97},{138,10,577},{5,10,681},{136,10,782},{133,11,481},{132,0,351},{4,\n10,664},{5,10,804},{139,10,1013},{6,11,134},{7,11,437},{7,11,959},{9,11,37},{14,\n11,285},{14,11,371},{144,11,60},{7,11,486},{8,11,155},{11,11,93},{140,11,164},{\n132,0,286},{7,0,438},{7,0,627},{7,0,1516},{8,0,40},{9,0,56},{9,0,294},{10,0,30},\n{11,0,969},{11,0,995},{146,0,148},{5,11,591},{135,11,337},{134,0,1950},{133,10,\n32},{138,11,500},{5,11,380},{5,11,650},{136,11,310},{4,11,364},{7,11,1156},{7,11\n,1187},{137,11,409},{4,0,738},{134,11,482},{4,11,781},{6,11,487},{7,11,926},{8,\n11,263},{139,11,500},{135,11,418},{4,10,289},{6,0,2047},{7,10,629},{7,10,1698},{\n7,10,1711},{10,0,969},{140,10,215},{6,10,450},{136,10,109},{134,0,818},{136,10,\n705},{133,0,866},{4,11,94},{135,11,1265},{132,11,417},{134,0,1467},{135,10,1238}\n,{4,0,972},{6,0,1851},{134,0,1857},{134,0,355},{133,0,116},{132,0,457},{135,11,\n1411},{4,11,408},{4,11,741},{135,11,500},{134,10,26},{142,11,137},{5,0,527},{6,0\n,189},{7,0,859},{136,0,267},{11,0,104},{11,0,554},{15,0,60},{143,0,125},{134,0,\n1613},{4,10,414},{5,10,467},{9,10,654},{10,10,451},{12,10,59},{141,10,375},{135,\n10,17},{134,0,116},{135,11,541},{135,10,955},{6,11,73},{135,11,177},{133,11,576}\n,{134,0,886},{133,0,487},{4,0,86},{5,0,667},{5,0,753},{6,0,316},{6,0,455},{135,0\n,946},{142,11,231},{150,0,45},{134,0,863},{134,0,1953},{6,10,280},{10,10,502},{\n11,10,344},{140,10,38},{4,0,79},{7,0,1773},{10,0,450},{11,0,589},{13,0,332},{13,\n0,493},{14,0,183},{14,0,334},{14,0,362},{14,0,368},{14,0,376},{14,0,379},{19,0,\n90},{19,0,103},{19,0,127},{148,0,90},{5,10,45},{7,10,1161},{11,10,448},{11,10,\n880},{13,10,139},{13,10,407},{15,10,16},{17,10,95},{18,10,66},{18,10,88},{18,10,\n123},{149,10,7},{136,10,777},{4,10,410},{135,10,521},{135,10,1778},{135,11,538},\n{142,0,381},{133,11,413},{134,0,1142},{6,0,1189},{136,11,495},{5,0,663},{6,0,\n1962},{134,0,2003},{7,11,54},{8,11,312},{10,11,191},{10,11,614},{140,11,567},{\n132,10,436},{133,0,846},{7,10,1587},{7,10,1707},{10,0,528},{139,0,504},{5,0,378}\n,{8,0,465},{9,0,286},{10,0,185},{10,0,562},{10,0,635},{11,0,31},{11,0,393},{13,0\n,312},{18,0,65},{18,0,96},{147,0,89},{6,11,468},{7,0,899},{7,11,567},{7,11,1478}\n,{8,11,530},{14,0,325},{142,11,290},{7,0,1880},{9,0,680},{139,0,798},{134,0,1770\n},{132,0,648},{150,11,35},{5,0,945},{6,0,1656},{6,0,1787},{7,0,167},{8,0,824},{9\n,0,391},{10,0,375},{139,0,185},{6,11,484},{135,11,822},{134,0,2046},{7,0,1645},{\n8,0,352},{137,0,249},{132,0,152},{6,0,611},{135,0,1733},{6,11,1724},{135,11,2022\n},{133,0,1006},{141,11,96},{5,0,420},{135,0,1449},{146,11,149},{135,0,832},{135,\n10,663},{133,0,351},{5,0,40},{7,0,598},{7,0,1638},{8,0,78},{9,0,166},{9,0,640},{\n9,0,685},{9,0,773},{11,0,215},{13,0,65},{14,0,172},{14,0,317},{145,0,6},{8,0,60}\n,{9,0,343},{139,0,769},{134,0,1354},{132,0,724},{137,0,745},{132,11,474},{7,0,\n1951},{8,0,765},{8,0,772},{140,0,671},{7,0,108},{8,0,219},{8,0,388},{9,0,775},{\n11,0,275},{140,0,464},{137,0,639},{135,10,503},{133,11,366},{5,0,15},{5,11,305},\n{6,0,56},{7,0,1758},{8,0,500},{9,0,730},{9,11,560},{11,0,331},{13,0,150},{13,11,\n208},{142,0,282},{4,10,113},{5,10,163},{5,10,735},{7,10,1009},{9,10,9},{9,10,771\n},{12,10,90},{13,10,138},{13,10,410},{143,10,128},{4,10,324},{138,10,104},{135,\n11,466},{142,11,27},{134,0,1886},{4,11,480},{5,0,205},{6,0,438},{6,11,167},{6,11\n,302},{6,11,1642},{7,11,130},{7,11,656},{7,11,837},{7,11,1547},{7,11,1657},{8,11\n,429},{9,0,711},{9,11,228},{10,11,643},{13,11,289},{13,11,343},{147,11,101},{134\n,0,865},{6,0,2025},{136,0,965},{7,11,278},{10,11,739},{11,11,708},{141,11,348},{\n133,0,534},{135,11,1922},{137,0,691},{4,10,935},{133,10,823},{6,0,443},{9,0,237}\n,{9,0,571},{9,0,695},{10,0,139},{11,0,715},{12,0,417},{141,0,421},{5,10,269},{7,\n10,434},{7,10,891},{8,10,339},{9,10,702},{11,10,594},{11,10,718},{145,10,100},{6\n,0,1555},{7,0,878},{9,10,485},{141,10,264},{134,10,1713},{7,10,1810},{11,10,866}\n,{12,10,103},{141,10,495},{135,10,900},{6,0,1410},{9,11,316},{139,11,256},{4,0,\n995},{135,0,1033},{132,0,578},{10,0,881},{12,0,740},{12,0,743},{140,0,759},{132,\n0,822},{133,0,923},{142,10,143},{135,11,1696},{6,11,363},{7,11,1955},{136,11,725\n},{132,0,924},{133,0,665},{135,10,2029},{135,0,1901},{4,0,265},{6,0,1092},{6,0,\n1417},{7,0,807},{135,0,950},{5,0,93},{12,0,267},{141,0,498},{135,0,1451},{5,11,\n813},{135,11,2046},{5,10,625},{135,10,1617},{135,0,747},{6,0,788},{137,0,828},{5\n,11,712},{7,0,184},{7,11,1855},{8,10,425},{8,10,693},{9,10,720},{10,10,380},{10,\n10,638},{11,0,307},{11,0,400},{11,10,473},{11,11,17},{12,10,61},{13,11,321},{15,\n0,130},{144,11,67},{135,0,198},{6,11,320},{7,11,781},{7,11,1921},{9,11,55},{10,\n11,186},{10,11,273},{10,11,664},{10,11,801},{11,11,996},{11,11,997},{13,11,157},\n{142,11,170},{136,11,271},{135,0,994},{7,11,103},{7,11,863},{11,11,184},{14,11,\n299},{145,11,62},{11,10,551},{142,10,159},{5,0,233},{5,0,320},{6,0,140},{8,0,295\n},{8,0,615},{136,11,615},{133,0,978},{4,0,905},{6,0,1701},{137,0,843},{132,10,\n168},{4,0,974},{8,0,850},{12,0,709},{12,0,768},{140,0,786},{135,10,91},{152,0,6}\n,{138,10,532},{135,10,1884},{132,0,509},{6,0,1307},{135,0,273},{5,11,77},{7,11,\n1455},{10,11,843},{19,11,73},{150,11,5},{132,11,458},{135,11,1420},{6,11,109},{\n138,11,382},{6,0,201},{6,11,330},{7,10,70},{7,11,1084},{10,10,240},{11,11,142},{\n147,10,93},{7,0,1041},{140,11,328},{133,11,354},{134,0,1040},{133,0,693},{134,0,\n774},{139,0,234},{132,0,336},{7,0,1399},{139,10,392},{20,0,22},{148,11,22},{5,0,\n802},{7,0,2021},{136,0,805},{5,0,167},{5,0,899},{6,0,410},{137,0,777},{137,0,789\n},{134,0,1705},{7,10,655},{135,10,1844},{4,10,145},{6,10,176},{7,10,395},{137,10\n,562},{132,10,501},{135,0,10},{5,0,11},{6,0,117},{6,0,485},{6,10,509},{7,0,1133}\n,{9,0,582},{9,0,594},{10,0,82},{11,0,21},{11,0,818},{12,0,535},{13,0,86},{20,0,\n91},{151,0,13},{4,0,264},{7,0,1067},{8,0,204},{8,0,385},{139,0,953},{139,11,737}\n,{138,0,56},{134,0,1917},{133,0,470},{10,11,657},{14,11,297},{142,11,361},{135,\n11,412},{7,0,1198},{7,11,1198},{8,11,556},{14,11,123},{14,11,192},{143,11,27},{7\n,11,1985},{14,11,146},{15,11,42},{16,11,23},{17,11,86},{146,11,17},{8,11,122},{\n139,0,1015},{4,10,114},{9,10,492},{13,10,462},{142,10,215},{4,10,77},{5,10,361},\n{6,10,139},{6,10,401},{6,10,404},{7,10,413},{7,10,715},{7,10,1716},{11,10,279},{\n12,10,179},{12,10,258},{13,10,244},{142,10,358},{134,10,1717},{7,10,1061},{8,10,\n82},{11,10,250},{12,10,420},{141,10,184},{133,0,715},{135,10,724},{9,0,919},{9,0\n,922},{9,0,927},{9,0,933},{9,0,962},{9,0,1000},{9,0,1002},{9,0,1021},{12,0,890},\n{12,0,907},{12,0,930},{15,0,207},{15,0,228},{15,0,238},{149,0,61},{8,0,794},{9,0\n,400},{10,0,298},{142,0,228},{5,11,430},{5,11,932},{6,11,131},{7,11,417},{9,11,\n522},{11,11,314},{141,11,390},{132,0,867},{4,11,507},{136,0,724},{137,11,261},{4\n,11,343},{133,11,511},{6,0,190},{7,0,768},{135,0,1170},{6,10,513},{135,10,1052},\n{7,11,455},{138,11,591},{134,0,1066},{137,10,899},{14,0,67},{147,0,60},{4,0,948}\n,{18,0,174},{146,0,176},{135,0,1023},{7,10,1417},{12,10,382},{17,10,48},{152,10,\n12},{134,11,575},{132,0,764},{6,10,545},{7,10,565},{7,10,1669},{10,10,114},{11,\n10,642},{140,10,618},{6,0,137},{9,0,75},{9,0,253},{10,0,194},{138,0,444},{4,0,\n756},{133,10,5},{7,10,192},{136,0,1008},{132,0,842},{8,10,763},{11,0,643},{140,0\n,115},{139,0,67},{133,10,759},{4,0,821},{5,0,760},{7,0,542},{7,11,580},{8,0,135}\n,{136,0,496},{7,10,370},{7,10,1007},{7,10,1177},{135,10,1565},{135,10,1237},{140\n,0,736},{7,0,319},{7,0,355},{7,0,763},{10,0,389},{145,0,43},{8,11,333},{138,11,\n182},{4,10,87},{5,10,250},{141,10,298},{138,0,786},{134,0,2044},{8,11,330},{140,\n11,477},{135,11,1338},{132,11,125},{134,0,1030},{134,0,1083},{132,11,721},{135,\n10,814},{7,11,776},{8,11,145},{147,11,56},{134,0,1226},{4,10,57},{7,10,1195},{7,\n10,1438},{7,10,1548},{7,10,1835},{7,10,1904},{9,10,757},{10,10,604},{139,10,519}\n,{7,11,792},{8,11,147},{10,11,821},{139,11,1021},{137,11,797},{4,0,58},{5,0,286}\n,{6,0,319},{7,0,402},{7,0,1254},{7,0,1903},{8,0,356},{140,0,408},{4,0,389},{4,0,\n815},{9,0,181},{9,0,255},{10,0,8},{10,0,29},{10,0,816},{11,0,311},{11,0,561},{12\n,0,67},{141,0,181},{7,11,1472},{135,11,1554},{7,11,1071},{7,11,1541},{7,11,1767}\n,{7,11,1806},{7,11,1999},{9,11,248},{10,11,400},{11,11,162},{11,11,178},{11,11,\n242},{12,11,605},{15,11,26},{144,11,44},{5,11,168},{5,11,930},{8,11,74},{9,11,\n623},{12,11,500},{12,11,579},{13,11,41},{143,11,93},{6,11,220},{7,11,1101},{141,\n11,105},{4,10,209},{5,0,474},{7,0,507},{7,10,902},{135,11,507},{132,0,427},{6,0,\n413},{7,10,335},{7,10,1437},{7,10,1668},{8,10,553},{8,10,652},{8,10,656},{9,10,\n558},{11,10,743},{149,10,18},{132,0,730},{6,11,19},{7,11,1413},{139,11,428},{133\n,0,373},{132,10,559},{7,11,96},{8,11,401},{137,11,896},{5,10,1017},{7,0,799},{7,\n0,1972},{138,10,511},{135,0,1793},{7,11,1961},{7,11,1965},{8,11,702},{136,11,750\n},{8,11,150},{8,11,737},{140,11,366},{132,0,322},{133,10,709},{8,11,800},{9,11,\n148},{9,11,872},{9,11,890},{11,11,309},{11,11,1001},{13,11,267},{141,11,323},{\n134,10,1745},{7,0,290},{136,10,206},{7,0,1651},{145,0,89},{139,0,2},{132,0,672},\n{6,0,1860},{8,0,905},{10,0,844},{10,0,846},{10,0,858},{12,0,699},{12,0,746},{140\n,0,772},{135,11,424},{133,11,547},{133,0,737},{5,11,490},{6,11,615},{6,11,620},{\n135,11,683},{6,0,746},{134,0,1612},{132,10,776},{9,11,385},{149,11,17},{133,0,\n145},{135,10,1272},{7,0,884},{140,0,124},{4,0,387},{135,0,1288},{5,11,133},{136,\n10,406},{136,11,187},{6,0,679},{8,11,8},{138,11,0},{135,0,550},{135,11,798},{136\n,11,685},{7,11,1086},{145,11,46},{8,10,175},{10,10,168},{138,10,573},{135,0,1305\n},{4,0,576},{135,0,1263},{6,0,686},{134,0,1563},{134,0,607},{5,0,919},{134,0,\n1673},{148,0,37},{8,11,774},{10,11,670},{140,11,51},{133,10,784},{139,10,882},{4\n,0,82},{5,0,333},{5,0,904},{6,0,207},{7,0,325},{7,0,1726},{8,0,101},{10,0,778},{\n139,0,220},{135,11,371},{132,0,958},{133,0,903},{4,11,127},{5,11,350},{6,11,356}\n,{8,11,426},{9,11,572},{10,11,247},{139,11,312},{140,0,147},{6,11,59},{7,11,885}\n,{9,11,603},{141,11,397},{9,10,14},{9,10,441},{10,0,367},{139,10,9},{11,10,966},\n{12,10,287},{13,10,342},{13,10,402},{15,10,110},{143,10,163},{134,0,690},{132,0,\n705},{7,10,1428},{7,10,1640},{7,10,1867},{9,0,651},{9,10,169},{9,10,182},{9,10,\n367},{9,10,478},{9,10,506},{9,10,551},{9,10,557},{9,10,648},{9,10,697},{9,10,705\n},{9,10,725},{9,10,787},{9,10,794},{10,10,198},{10,10,214},{10,10,267},{10,10,\n275},{10,10,456},{10,10,551},{10,10,561},{10,10,613},{10,10,627},{10,10,668},{10\n,10,675},{10,10,691},{10,10,695},{10,10,707},{10,10,715},{11,0,971},{11,10,183},\n{11,10,201},{11,10,262},{11,10,352},{11,10,439},{11,10,493},{11,10,572},{11,10,\n591},{11,10,608},{11,10,611},{11,10,646},{11,10,674},{11,10,711},{11,10,751},{11\n,10,761},{11,10,776},{11,10,785},{11,10,850},{11,10,853},{11,10,862},{11,10,865}\n,{11,10,868},{11,10,875},{11,10,898},{11,10,902},{11,10,903},{11,10,910},{11,10,\n932},{11,10,942},{11,10,957},{11,10,967},{11,10,972},{12,10,148},{12,10,195},{12\n,10,220},{12,10,237},{12,10,318},{12,10,339},{12,10,393},{12,10,445},{12,10,450}\n,{12,10,474},{12,10,505},{12,10,509},{12,10,533},{12,10,591},{12,10,594},{12,10,\n597},{12,10,621},{12,10,633},{12,10,642},{13,0,273},{13,10,59},{13,10,60},{13,10\n,145},{13,10,239},{13,10,250},{13,10,329},{13,10,344},{13,10,365},{13,10,372},{\n13,10,387},{13,10,403},{13,10,414},{13,10,456},{13,10,470},{13,10,478},{13,10,\n483},{13,10,489},{14,10,55},{14,10,57},{14,10,81},{14,10,90},{14,10,148},{14,10,\n239},{14,10,266},{14,10,321},{14,10,326},{14,10,327},{14,10,330},{14,10,347},{14\n,10,355},{14,10,401},{14,10,404},{14,10,411},{14,10,414},{14,10,416},{14,10,420}\n,{15,10,61},{15,10,74},{15,10,87},{15,10,88},{15,10,94},{15,10,96},{15,10,116},{\n15,10,149},{15,10,154},{16,10,50},{16,10,63},{16,10,73},{17,10,2},{17,10,66},{17\n,10,92},{17,10,103},{17,10,112},{17,10,120},{18,10,50},{18,10,54},{18,10,82},{18\n,10,86},{18,10,90},{18,10,111},{18,10,115},{18,10,156},{19,10,40},{19,10,79},{20\n,10,78},{149,10,22},{5,10,161},{7,0,887},{135,10,839},{142,11,98},{134,0,90},{\n138,11,356},{135,11,441},{6,11,111},{7,11,4},{8,11,163},{8,11,776},{138,11,566},\n{134,0,908},{134,0,1261},{7,0,813},{12,0,497},{141,0,56},{134,0,1235},{135,0,429\n},{135,11,1994},{138,0,904},{6,0,125},{7,0,1277},{137,0,772},{151,0,12},{4,0,841\n},{5,0,386},{133,11,386},{5,11,297},{135,11,1038},{6,0,860},{6,0,1069},{135,11,\n309},{136,0,946},{135,10,1814},{141,11,418},{136,11,363},{10,0,768},{139,0,787},\n{22,11,30},{150,11,33},{6,0,160},{7,0,1106},{9,0,770},{11,0,112},{140,0,413},{11\n,11,216},{139,11,340},{136,10,139},{135,11,1390},{135,11,808},{132,11,280},{7,10\n,643},{8,10,236},{12,0,271},{145,0,109},{140,11,54},{4,11,421},{133,11,548},{11,\n0,719},{12,0,36},{141,0,337},{7,0,581},{9,0,644},{137,0,699},{11,11,511},{13,11,\n394},{14,11,298},{14,11,318},{146,11,103},{7,0,304},{9,0,646},{9,0,862},{11,0,\n696},{12,0,208},{15,0,79},{147,0,108},{4,0,631},{7,0,1126},{135,0,1536},{135,11,\n1527},{8,0,880},{10,0,869},{138,0,913},{5,10,54},{6,11,254},{7,0,1513},{9,11,109\n},{138,11,103},{135,0,981},{133,11,729},{132,10,744},{132,0,434},{134,0,550},{6,\n11,1630},{7,0,930},{10,0,476},{10,10,402},{13,0,452},{18,10,55},{147,0,104},{5,0\n,553},{138,0,824},{136,0,452},{8,0,151},{137,10,624},{132,10,572},{132,0,772},{\n133,11,671},{133,0,292},{138,0,135},{132,11,889},{140,11,207},{6,10,43},{7,10,38\n},{8,10,248},{9,0,504},{138,10,513},{6,0,1089},{135,11,1910},{4,11,627},{133,11,\n775},{135,0,783},{133,10,766},{133,10,363},{7,0,387},{135,11,387},{7,0,393},{7,\n11,202},{10,0,603},{11,0,206},{11,11,362},{11,11,948},{140,11,388},{6,11,507},{7\n,11,451},{8,11,389},{12,11,490},{13,11,16},{13,11,215},{13,11,351},{18,11,132},{\n147,11,125},{4,0,912},{7,11,841},{137,0,232},{6,10,258},{140,10,409},{5,10,249},\n{148,10,82},{136,11,566},{6,0,977},{135,11,1214},{7,0,1973},{136,0,716},{135,0,\n98},{133,0,733},{5,11,912},{134,11,1695},{5,10,393},{6,10,378},{7,10,1981},{9,10\n,32},{9,10,591},{10,10,685},{10,10,741},{142,10,382},{133,10,788},{7,10,1968},{\n10,0,19},{11,0,911},{141,10,509},{5,0,668},{5,11,236},{6,11,572},{8,11,492},{11,\n11,618},{144,11,56},{135,11,1789},{4,0,360},{5,0,635},{5,0,700},{5,10,58},{5,10,\n171},{5,10,683},{6,10,291},{6,10,566},{7,10,1650},{11,10,523},{12,10,273},{12,10\n,303},{15,10,39},{143,10,111},{133,0,901},{134,10,589},{5,11,190},{136,11,318},{\n140,0,656},{7,0,726},{152,0,9},{4,10,917},{133,10,1005},{135,10,1598},{134,11,\n491},{4,10,919},{133,11,434},{137,0,72},{6,0,1269},{6,0,1566},{134,0,1621},{4,10\n,255},{5,10,302},{6,10,132},{7,10,128},{7,10,283},{7,10,1299},{9,0,463},{10,0,\n595},{10,10,52},{10,10,514},{11,10,925},{13,10,92},{142,10,309},{135,0,1454},{\n134,0,1287},{9,10,173},{11,0,600},{141,0,245},{136,0,989},{7,0,164},{7,0,1571},{\n9,0,107},{140,0,225},{6,0,1061},{141,10,442},{4,0,27},{5,0,484},{5,0,510},{6,0,\n434},{7,0,1000},{7,0,1098},{136,0,2},{7,11,85},{7,11,247},{8,11,585},{10,11,163}\n,{138,11,316},{11,11,103},{142,11,0},{134,0,1127},{4,0,460},{134,0,852},{134,10,\n210},{4,0,932},{133,0,891},{6,0,588},{147,11,83},{4,10,284},{6,10,223},{136,0,\n625},{134,0,76},{8,0,92},{137,0,221},{4,11,124},{10,11,457},{11,11,121},{11,11,\n169},{11,11,422},{11,11,870},{12,11,214},{13,11,389},{14,11,187},{143,11,77},{9,\n11,618},{138,11,482},{4,10,218},{7,10,526},{143,10,137},{4,10,270},{5,10,192},{6\n,10,332},{7,10,1322},{13,0,9},{14,0,104},{142,0,311},{140,10,661},{135,11,1193},\n{6,11,107},{7,11,638},{7,11,1632},{137,11,396},{132,0,763},{4,0,622},{5,11,370},\n{134,11,1756},{133,0,253},{135,0,546},{5,11,204},{9,0,73},{10,0,110},{14,0,185},\n{145,0,119},{7,0,624},{7,0,916},{10,0,256},{139,0,87},{7,10,379},{8,10,481},{137\n,10,377},{5,0,212},{5,11,970},{6,11,1706},{12,0,35},{141,0,382},{5,10,1003},{6,\n10,149},{137,0,746},{8,10,262},{9,10,627},{10,0,150},{11,0,849},{11,10,214},{11,\n10,404},{11,10,457},{11,10,780},{11,10,913},{13,0,330},{13,10,401},{142,10,200},\n{134,0,1466},{135,11,3},{4,11,35},{5,11,121},{5,11,483},{5,11,685},{6,0,1299},{6\n,11,489},{7,11,1204},{136,11,394},{135,10,742},{4,10,142},{136,10,304},{4,11,921\n},{133,11,1007},{134,0,1518},{6,0,1229},{135,0,1175},{133,0,816},{4,10,471},{4,\n11,712},{5,10,51},{6,10,602},{7,10,925},{8,10,484},{10,10,195},{140,0,159},{134,\n11,1629},{5,0,869},{5,0,968},{6,0,1626},{8,0,734},{136,0,784},{4,0,542},{6,0,\n1716},{6,0,1727},{7,0,1082},{7,0,1545},{8,0,56},{8,0,118},{8,0,412},{8,0,564},{8\n,10,688},{9,0,888},{9,0,908},{10,0,50},{10,0,423},{11,0,685},{11,0,697},{11,0,\n933},{12,0,299},{13,0,126},{13,0,136},{13,0,170},{141,0,190},{132,10,697},{4,0,\n232},{9,0,202},{10,0,474},{140,0,433},{136,0,212},{6,0,108},{7,0,1003},{7,0,1181\n},{8,0,111},{136,0,343},{5,10,221},{135,11,1255},{133,11,485},{134,0,1712},{142,\n0,216},{4,11,285},{5,0,643},{5,11,317},{6,0,516},{6,11,301},{7,11,7},{8,11,153},\n{10,11,766},{11,11,468},{12,11,467},{141,11,143},{4,0,133},{7,0,711},{7,0,1298},\n{135,0,1585},{134,0,650},{135,11,512},{6,0,99},{7,0,1808},{145,0,57},{6,0,246},{\n6,0,574},{7,0,428},{9,0,793},{10,0,669},{11,0,485},{11,0,840},{12,0,300},{14,0,\n250},{145,0,55},{4,10,132},{5,10,69},{135,10,1242},{136,0,1023},{4,10,111},{135,\n0,302},{135,0,1871},{132,0,728},{4,10,767},{137,0,252},{6,0,461},{7,0,1590},{7,\n10,1416},{7,10,2005},{8,10,131},{8,10,466},{9,10,672},{13,10,252},{148,10,103},{\n6,0,323},{135,0,1564},{7,0,461},{136,0,775},{6,10,44},{136,10,368},{139,0,172},{\n132,0,464},{4,10,570},{133,10,120},{137,11,269},{6,10,227},{135,10,1589},{6,11,\n1719},{6,11,1735},{7,11,2016},{7,11,2020},{8,11,837},{137,11,852},{7,0,727},{146\n,0,73},{132,0,1023},{135,11,852},{135,10,1529},{136,0,577},{138,11,568},{134,0,\n1037},{8,11,67},{138,11,419},{4,0,413},{5,0,677},{8,0,432},{140,0,280},{6,10,\n1667},{7,10,2036},{7,11,967},{10,0,600},{141,11,11},{6,10,511},{140,10,132},{5,\n10,568},{6,0,799},{6,10,138},{135,10,1293},{4,10,565},{8,0,159},{136,10,827},{7,\n0,646},{7,0,1730},{11,0,446},{141,0,178},{4,10,922},{133,10,1023},{135,11,11},{\n132,0,395},{7,10,1002},{139,0,145},{9,0,174},{10,0,164},{11,0,440},{11,0,514},{\n11,0,841},{15,0,98},{149,0,20},{134,0,426},{10,0,608},{139,0,1002},{7,11,320},{8\n,11,51},{12,11,481},{12,11,570},{148,11,106},{4,11,445},{9,0,977},{137,0,983},{\n138,0,250},{139,0,100},{6,0,1982},{136,10,402},{133,11,239},{4,10,716},{141,10,\n31},{5,0,476},{7,11,83},{7,11,1990},{8,11,130},{139,11,720},{8,10,691},{136,10,\n731},{5,11,123},{6,11,530},{7,11,348},{135,11,1419},{5,0,76},{6,0,458},{6,0,497}\n,{7,0,868},{9,0,658},{10,0,594},{11,0,173},{11,0,566},{12,0,20},{12,0,338},{141,\n0,200},{9,11,139},{10,11,399},{11,11,469},{12,11,634},{141,11,223},{9,10,840},{\n138,10,803},{133,10,847},{11,11,223},{140,11,168},{132,11,210},{8,0,447},{9,10,\n53},{9,10,268},{9,10,901},{10,10,518},{10,10,829},{11,10,188},{13,10,74},{14,10,\n46},{15,10,17},{15,10,33},{17,10,40},{18,10,36},{19,10,20},{22,10,1},{152,10,2},\n{4,0,526},{7,0,1029},{135,0,1054},{19,11,59},{150,11,2},{4,0,636},{6,0,1875},{6,\n0,1920},{8,10,532},{9,0,999},{12,0,807},{12,0,825},{15,0,179},{15,0,190},{146,0,\n182},{6,0,1699},{7,0,660},{7,0,1124},{17,0,31},{19,0,22},{151,0,14},{135,10,681}\n,{132,11,430},{140,10,677},{4,10,684},{136,10,384},{132,11,756},{133,11,213},{7,\n0,188},{7,10,110},{8,10,290},{8,10,591},{9,10,382},{9,10,649},{11,10,71},{11,10,\n155},{11,10,313},{12,10,5},{13,10,325},{142,10,287},{7,10,360},{7,10,425},{9,10,\n66},{9,10,278},{138,10,644},{142,11,164},{4,0,279},{7,0,301},{137,0,362},{134,11\n,586},{135,0,1743},{4,0,178},{133,0,399},{4,10,900},{133,10,861},{5,10,254},{7,\n10,985},{136,10,73},{133,11,108},{7,10,1959},{136,10,683},{133,11,219},{4,11,193\n},{5,11,916},{7,11,364},{10,11,398},{10,11,726},{11,11,317},{11,11,626},{12,11,\n142},{12,11,288},{12,11,678},{13,11,313},{15,11,113},{18,11,114},{21,11,30},{150\n,11,53},{6,11,241},{7,11,907},{8,11,832},{9,11,342},{10,11,729},{11,11,284},{11,\n11,445},{11,11,651},{11,11,863},{13,11,398},{146,11,99},{132,0,872},{134,0,831},\n{134,0,1692},{6,0,202},{6,0,1006},{9,0,832},{9,11,734},{10,0,636},{11,0,208},{12\n,0,360},{17,0,118},{18,0,27},{148,0,67},{132,10,725},{7,11,993},{138,11,666},{\n134,0,1954},{134,10,196},{7,0,872},{10,0,516},{139,0,167},{133,10,831},{4,11,562\n},{9,11,254},{139,11,879},{137,0,313},{4,0,224},{132,11,786},{8,10,723},{11,0,24\n},{140,0,170},{5,0,546},{7,0,35},{8,0,11},{8,0,12},{9,0,315},{9,0,533},{10,0,802\n},{11,0,166},{12,0,525},{142,0,243},{7,0,1937},{13,10,80},{13,10,437},{145,10,74\n},{5,0,241},{8,0,242},{9,0,451},{10,0,667},{11,0,598},{140,0,429},{150,0,46},{6,\n0,1273},{137,0,830},{5,10,848},{6,10,66},{136,10,764},{6,0,825},{134,0,993},{4,0\n,1006},{4,10,36},{7,10,1387},{10,0,327},{11,10,755},{141,0,271},{134,0,1023},{\n135,0,1580},{4,0,366},{137,0,516},{132,10,887},{6,0,1736},{135,0,1891},{6,11,216\n},{7,11,901},{7,11,1343},{136,11,493},{6,10,165},{138,10,388},{7,11,341},{139,11\n,219},{4,10,719},{135,10,155},{134,0,1935},{132,0,826},{6,0,331},{6,0,1605},{8,0\n,623},{11,0,139},{139,0,171},{135,11,1734},{10,11,115},{11,11,420},{12,11,154},{\n13,11,404},{14,11,346},{15,11,54},{143,11,112},{4,10,353},{6,10,146},{6,10,1789}\n,{7,0,288},{7,10,990},{7,10,1348},{9,10,665},{9,10,898},{11,10,893},{142,10,212}\n,{6,0,916},{134,0,1592},{4,10,45},{7,0,1888},{135,10,1257},{5,11,1011},{136,11,\n701},{139,11,596},{4,11,54},{5,11,666},{7,11,1039},{7,11,1130},{9,11,195},{138,\n11,302},{134,0,1471},{134,0,1570},{132,0,394},{140,10,65},{136,10,816},{135,0,\n1931},{7,0,574},{135,0,1719},{134,11,467},{132,0,658},{6,11,1669},{9,0,781},{10,\n0,144},{11,0,385},{13,0,161},{13,0,228},{13,0,268},{148,0,107},{136,0,374},{135,\n0,735},{4,0,344},{6,0,498},{139,0,323},{6,10,559},{6,10,1691},{7,0,586},{135,0,\n1063},{137,0,155},{133,0,906},{7,11,122},{9,11,259},{10,11,84},{11,11,470},{12,\n11,541},{141,11,379},{134,0,1139},{10,0,108},{139,0,116},{134,10,456},{133,10,\n925},{5,11,82},{5,11,131},{7,11,1755},{8,11,31},{9,11,168},{9,11,764},{139,11,\n869},{134,11,605},{5,11,278},{137,11,68},{4,11,163},{5,11,201},{5,11,307},{5,11,\n310},{6,11,335},{7,11,284},{136,11,165},{135,11,1660},{6,11,33},{135,11,1244},{4\n,0,616},{136,11,483},{4,11,199},{8,0,857},{8,0,902},{8,0,910},{10,0,879},{11,11,\n34},{140,0,726},{136,0,692},{6,10,193},{7,10,240},{7,10,1682},{10,10,51},{10,10,\n640},{11,10,410},{13,10,82},{14,10,247},{14,10,331},{142,10,377},{6,0,823},{134,\n0,983},{139,10,411},{132,0,305},{136,10,633},{138,11,203},{134,0,681},{6,11,326}\n,{7,11,677},{137,11,425},{5,0,214},{7,0,603},{8,0,611},{9,0,686},{10,0,88},{11,0\n,459},{11,0,496},{12,0,463},{12,0,590},{141,0,0},{136,0,1004},{142,0,23},{134,0,\n1703},{147,11,8},{145,11,56},{135,0,1443},{4,10,237},{135,10,514},{6,0,714},{145\n,0,19},{5,11,358},{7,11,473},{7,11,1184},{10,11,662},{13,11,212},{13,11,304},{13\n,11,333},{145,11,98},{4,0,737},{10,0,98},{11,0,294},{12,0,60},{12,0,437},{13,0,\n64},{13,0,380},{142,0,430},{6,10,392},{7,10,65},{135,10,2019},{6,0,1758},{8,0,\n520},{9,0,345},{9,0,403},{142,0,350},{5,0,47},{10,0,242},{138,0,579},{5,0,139},{\n7,0,1168},{138,0,539},{134,0,1459},{13,0,388},{141,11,388},{134,0,253},{7,10,\n1260},{135,10,1790},{9,10,222},{10,0,252},{139,10,900},{140,0,745},{133,11,946},\n{4,0,107},{7,0,613},{8,0,439},{8,0,504},{9,0,501},{10,0,383},{139,0,477},{135,11\n,1485},{132,0,871},{7,11,411},{7,11,590},{8,11,631},{9,11,323},{10,11,355},{11,\n11,491},{12,11,143},{12,11,402},{13,11,73},{14,11,408},{15,11,107},{146,11,71},{\n132,0,229},{132,0,903},{140,0,71},{133,0,549},{4,0,47},{6,0,373},{7,0,452},{7,0,\n543},{7,0,1828},{7,0,1856},{9,0,6},{11,0,257},{139,0,391},{7,11,1467},{8,11,328}\n,{10,11,544},{11,11,955},{13,11,320},{145,11,83},{5,0,980},{134,0,1754},{136,0,\n865},{5,0,705},{137,0,606},{7,0,161},{8,10,201},{136,10,605},{143,11,35},{5,11,\n835},{6,11,483},{140,10,224},{7,0,536},{7,0,1331},{136,0,143},{134,0,1388},{5,0,\n724},{10,0,305},{11,0,151},{12,0,33},{12,0,121},{12,0,381},{17,0,3},{17,0,27},{\n17,0,78},{18,0,18},{19,0,54},{149,0,5},{4,10,523},{133,10,638},{5,0,19},{134,0,\n533},{5,0,395},{5,0,951},{134,0,1776},{135,0,1908},{132,0,846},{6,10,242},{7,10,\n227},{7,10,1581},{8,10,104},{9,10,113},{9,10,220},{9,10,427},{10,0,74},{10,10,\n239},{11,0,663},{11,10,579},{11,10,1023},{12,0,210},{13,0,166},{13,0,310},{13,10\n,4},{13,10,204},{13,10,316},{14,0,373},{18,0,95},{19,0,43},{148,10,86},{9,11,716\n},{11,11,108},{13,11,123},{14,11,252},{19,11,38},{21,11,3},{151,11,11},{8,0,372}\n,{9,0,122},{138,0,175},{132,11,677},{7,11,1374},{136,11,540},{135,10,861},{132,0\n,695},{7,0,497},{9,0,387},{147,0,81},{136,0,937},{134,0,718},{7,0,1328},{136,10,\n494},{132,11,331},{5,11,747},{134,0,1581},{5,0,284},{6,0,49},{6,0,350},{7,0,1},{\n7,0,377},{7,0,1693},{8,0,18},{8,0,678},{9,0,161},{9,0,585},{9,0,671},{9,0,839},{\n11,0,912},{141,0,427},{7,10,1306},{8,10,505},{9,10,482},{10,10,126},{11,10,225},\n{12,10,347},{12,10,449},{13,10,19},{14,10,218},{142,10,435},{10,10,764},{12,10,\n120},{13,10,39},{145,10,127},{4,0,597},{133,10,268},{134,0,1094},{4,0,1008},{134\n,0,1973},{132,0,811},{139,0,908},{135,0,1471},{133,11,326},{4,10,384},{135,10,\n1022},{4,11,691},{7,0,1935},{7,11,1935},{8,0,324},{8,11,324},{9,11,35},{10,11,\n680},{11,11,364},{12,0,42},{12,11,42},{13,11,357},{146,11,16},{135,0,2014},{6,11\n,32},{7,0,2007},{7,11,385},{7,11,757},{7,11,1916},{8,11,37},{8,11,94},{8,11,711}\n,{9,0,101},{9,0,450},{9,11,541},{10,0,66},{10,0,842},{10,11,162},{10,11,795},{11\n,0,536},{11,11,989},{11,11,1010},{12,0,587},{12,11,14},{142,11,308},{139,0,586},\n{135,10,1703},{7,0,1077},{9,10,159},{11,0,28},{140,10,603},{6,0,1221},{136,10,\n583},{6,11,152},{6,11,349},{6,11,1682},{7,11,1252},{8,11,112},{9,11,435},{9,11,\n668},{10,11,290},{10,11,319},{10,11,815},{11,11,180},{11,11,837},{12,11,240},{13\n,11,152},{13,11,219},{142,11,158},{139,0,62},{132,10,515},{8,10,632},{8,10,697},\n{137,10,854},{134,0,1766},{132,11,581},{6,11,126},{7,11,573},{8,11,397},{142,11,\n44},{150,0,28},{4,10,136},{5,10,551},{11,0,670},{150,0,25},{6,0,1665},{7,0,256},\n{7,0,1388},{138,0,499},{4,0,22},{5,0,10},{7,0,1576},{136,0,97},{134,10,1782},{5,\n0,481},{7,10,1287},{9,10,44},{10,10,552},{10,10,642},{11,10,839},{12,10,274},{12\n,10,275},{12,10,372},{13,10,91},{142,10,125},{133,11,926},{7,11,1232},{137,11,\n531},{6,0,134},{7,0,437},{7,0,1824},{9,0,37},{14,0,285},{142,0,371},{7,0,486},{8\n,0,155},{11,0,93},{140,0,164},{6,0,1391},{134,0,1442},{133,11,670},{133,0,591},{\n6,10,147},{7,10,886},{7,11,1957},{9,10,753},{138,10,268},{5,0,380},{5,0,650},{7,\n0,1173},{136,0,310},{4,0,364},{7,0,1156},{7,0,1187},{137,0,409},{135,11,1621},{\n134,0,482},{133,11,506},{4,0,781},{6,0,487},{7,0,926},{8,0,263},{139,0,500},{138\n,10,137},{135,11,242},{139,11,96},{133,10,414},{135,10,1762},{134,0,804},{5,11,\n834},{7,11,1202},{8,11,14},{9,11,481},{137,11,880},{134,10,599},{4,0,94},{135,0,\n1265},{4,0,415},{132,0,417},{5,0,348},{6,0,522},{6,10,1749},{7,11,1526},{138,11,\n465},{134,10,1627},{132,0,1012},{132,10,488},{4,11,357},{6,11,172},{7,11,143},{\n137,11,413},{4,10,83},{4,11,590},{146,11,76},{140,10,676},{7,11,287},{8,11,355},\n{9,11,293},{137,11,743},{134,10,278},{5,11,169},{6,0,1803},{7,11,333},{8,11,45},\n{18,0,165},{152,0,21},{12,10,97},{140,11,97},{4,0,408},{4,0,741},{135,0,500},{\n132,11,198},{7,10,388},{7,10,644},{139,10,781},{4,11,24},{5,11,140},{5,11,185},{\n7,11,1500},{11,11,565},{139,11,838},{6,0,1321},{7,10,229},{8,10,59},{9,0,257},{9\n,10,190},{10,10,378},{140,10,191},{4,11,334},{133,11,593},{135,11,1885},{134,0,\n1138},{4,0,249},{6,0,73},{135,0,177},{133,0,576},{142,0,231},{137,0,288},{132,10\n,660},{7,10,1035},{138,10,737},{135,0,1487},{6,0,989},{7,10,690},{9,0,433},{9,10\n,587},{140,10,521},{7,0,1264},{7,0,1678},{11,0,945},{12,0,341},{12,0,471},{140,0\n,569},{132,11,709},{133,11,897},{5,11,224},{13,11,174},{146,11,52},{135,11,1840}\n,{134,10,1744},{4,10,733},{9,10,194},{10,10,92},{11,10,198},{12,0,87},{12,10,84}\n,{13,10,128},{144,0,74},{140,0,779},{135,0,538},{4,11,608},{133,11,497},{133,0,\n413},{7,11,1375},{7,11,1466},{138,11,331},{136,0,495},{6,11,540},{136,11,136},{7\n,0,54},{8,0,312},{10,0,191},{10,0,614},{140,0,567},{5,11,999},{6,0,468},{7,0,567\n},{7,0,1478},{8,0,530},{142,0,290},{4,11,299},{7,10,306},{135,11,1004},{142,11,\n296},{134,0,1484},{133,10,979},{6,0,609},{9,0,815},{12,11,137},{14,11,9},{14,11,\n24},{142,11,64},{133,11,456},{6,0,484},{135,0,822},{133,10,178},{136,11,180},{\n132,11,755},{137,0,900},{135,0,1335},{6,0,1724},{135,0,2022},{135,11,1139},{4,10\n,390},{133,0,640},{6,0,1831},{138,11,633},{135,11,566},{4,11,890},{5,11,805},{5,\n11,819},{5,11,961},{6,11,396},{6,11,1631},{6,11,1678},{7,11,1967},{7,11,2041},{9\n,11,630},{11,11,8},{11,11,1019},{12,11,176},{13,11,225},{14,11,292},{149,11,24},\n{132,0,474},{134,0,1103},{135,0,1504},{134,0,1576},{6,0,961},{6,0,1034},{140,0,\n655},{11,11,514},{149,11,20},{5,0,305},{135,11,1815},{7,11,1505},{10,11,190},{10\n,11,634},{11,11,792},{12,11,358},{140,11,447},{5,11,0},{6,11,536},{7,11,604},{13\n,11,445},{145,11,126},{5,10,105},{135,0,1236},{4,0,480},{6,0,217},{6,0,302},{6,0\n,1642},{6,11,232},{6,11,412},{7,0,130},{7,0,837},{7,0,1321},{7,0,1547},{7,0,1657\n},{7,11,1074},{8,0,429},{8,11,9},{8,11,157},{8,11,786},{9,0,228},{9,11,196},{9,\n11,352},{9,11,457},{10,11,337},{11,11,232},{11,11,877},{12,11,480},{12,11,546},{\n13,0,289},{13,0,343},{147,0,101},{5,10,438},{7,11,958},{9,10,694},{12,10,627},{\n13,10,210},{141,11,38},{4,11,382},{136,11,579},{7,0,278},{10,0,739},{11,0,708},{\n141,0,348},{4,11,212},{135,11,1206},{135,11,1898},{6,0,708},{6,0,1344},{152,10,\n11},{137,11,768},{134,0,1840},{140,0,233},{8,10,25},{138,10,826},{5,11,655},{134\n,0,2017},{6,0,1488},{139,11,290},{132,10,308},{134,0,1590},{134,0,1800},{134,0,\n1259},{6,11,231},{7,11,95},{8,11,423},{144,0,28},{133,11,300},{135,10,150},{136,\n10,649},{7,11,1874},{137,11,641},{6,11,237},{7,11,611},{8,11,100},{9,11,416},{11\n,11,335},{12,11,173},{146,11,101},{137,0,45},{134,10,521},{14,11,26},{17,0,36},{\n146,11,150},{5,10,339},{7,0,1442},{14,0,22},{15,10,41},{15,10,166},{147,10,66},{\n6,11,581},{7,11,1119},{136,0,378},{134,0,1507},{147,11,117},{139,0,39},{134,0,\n1054},{6,0,363},{7,0,1955},{136,0,725},{134,0,2036},{133,11,199},{6,0,1871},{9,0\n,935},{9,0,961},{9,0,1004},{9,0,1016},{12,0,805},{12,0,852},{12,0,853},{12,0,869\n},{12,0,882},{12,0,896},{12,0,906},{12,0,917},{12,0,940},{15,0,170},{15,0,176},{\n15,0,188},{15,0,201},{15,0,205},{15,0,212},{15,0,234},{15,0,244},{18,0,181},{18,\n0,193},{18,0,196},{18,0,201},{18,0,202},{18,0,210},{18,0,217},{18,0,235},{18,0,\n236},{18,0,237},{21,0,54},{21,0,55},{21,0,58},{21,0,59},{152,0,22},{134,10,1628}\n,{137,0,805},{5,0,813},{135,0,2046},{142,11,42},{5,0,712},{6,0,1240},{11,0,17},{\n13,0,321},{144,0,67},{132,0,617},{135,10,829},{6,0,320},{7,0,781},{7,0,1921},{9,\n0,55},{10,0,186},{10,0,273},{10,0,664},{10,0,801},{11,0,996},{11,0,997},{13,0,\n157},{142,0,170},{136,0,271},{5,10,486},{135,10,1349},{18,11,91},{147,11,70},{7,\n10,1635},{8,10,17},{10,0,445},{138,10,295},{136,11,404},{7,0,103},{7,0,863},{11,\n0,184},{145,0,62},{138,10,558},{137,0,659},{6,11,312},{6,11,1715},{10,11,584},{\n11,11,546},{11,11,692},{12,11,259},{12,11,295},{13,11,46},{141,11,154},{134,0,\n676},{132,11,588},{4,11,231},{5,11,61},{6,11,104},{7,11,729},{7,11,964},{7,11,\n1658},{140,11,414},{6,11,263},{138,11,757},{11,0,337},{142,0,303},{135,11,1363},\n{132,11,320},{140,0,506},{134,10,447},{5,0,77},{7,0,1455},{10,0,843},{147,0,73},\n{7,10,577},{7,10,1432},{9,10,475},{9,10,505},{9,10,526},{9,10,609},{9,10,689},{9\n,10,726},{9,10,735},{9,10,738},{10,10,556},{10,10,674},{10,10,684},{11,10,89},{\n11,10,202},{11,10,272},{11,10,380},{11,10,415},{11,10,505},{11,10,537},{11,10,\n550},{11,10,562},{11,10,640},{11,10,667},{11,10,688},{11,10,847},{11,10,927},{11\n,10,930},{11,10,940},{12,10,144},{12,10,325},{12,10,329},{12,10,389},{12,10,403}\n,{12,10,451},{12,10,515},{12,10,604},{12,10,616},{12,10,626},{13,10,66},{13,10,\n131},{13,10,167},{13,10,236},{13,10,368},{13,10,411},{13,10,434},{13,10,453},{13\n,10,461},{13,10,474},{14,10,59},{14,10,60},{14,10,139},{14,10,152},{14,10,276},{\n14,10,353},{14,10,402},{15,10,28},{15,10,81},{15,10,123},{15,10,152},{18,10,136}\n,{148,10,88},{132,0,458},{135,0,1420},{4,10,609},{4,11,405},{6,0,109},{7,10,756}\n,{7,11,817},{9,10,544},{10,0,382},{11,10,413},{14,10,307},{14,11,58},{16,10,25},\n{17,11,37},{146,11,124},{5,11,974},{6,0,330},{7,0,1084},{139,0,142},{4,10,930},{\n133,10,947},{5,10,939},{142,11,394},{16,0,91},{145,0,87},{5,10,962},{5,11,235},{\n7,11,1239},{11,11,131},{140,11,370},{5,10,651},{8,10,170},{9,10,61},{9,10,63},{\n10,10,23},{10,10,37},{10,10,834},{11,0,492},{11,10,4},{11,10,281},{11,10,503},{\n11,10,677},{12,10,96},{12,10,130},{12,10,244},{14,10,5},{14,10,40},{14,10,162},{\n14,10,202},{146,10,133},{4,10,406},{5,10,579},{12,10,492},{150,10,15},{9,11,137}\n,{138,11,221},{134,0,1239},{11,0,211},{140,0,145},{7,11,390},{138,11,140},{135,\n11,1418},{135,11,1144},{134,0,1049},{6,10,17},{7,0,321},{7,10,1001},{7,10,1982},\n{9,10,886},{10,10,489},{10,10,800},{11,10,782},{12,10,320},{13,10,467},{14,10,\n145},{14,10,387},{143,10,119},{145,10,17},{5,11,407},{11,11,489},{19,11,37},{20,\n11,73},{150,11,38},{133,10,458},{135,0,1985},{7,10,1983},{8,10,0},{8,10,171},{9,\n10,120},{9,10,732},{10,10,473},{11,10,656},{11,10,998},{18,10,0},{18,10,2},{147,\n10,21},{5,11,325},{7,11,1483},{8,11,5},{8,11,227},{9,11,105},{10,11,585},{140,11\n,614},{136,0,122},{132,0,234},{135,11,1196},{6,0,976},{6,0,1098},{134,0,1441},{7\n,0,253},{136,0,549},{6,11,621},{13,11,504},{144,11,19},{132,10,519},{5,0,430},{5\n,0,932},{6,0,131},{7,0,417},{9,0,522},{11,0,314},{141,0,390},{14,0,149},{14,0,\n399},{143,0,57},{5,10,907},{6,10,31},{6,11,218},{7,10,491},{7,10,530},{8,10,592}\n,{11,10,53},{11,10,779},{12,10,167},{12,10,411},{14,10,14},{14,10,136},{15,10,72\n},{16,10,17},{144,10,72},{140,11,330},{7,11,454},{7,11,782},{136,11,768},{132,0,\n507},{10,11,676},{140,11,462},{4,10,208},{5,10,106},{6,0,630},{6,10,531},{8,10,\n408},{9,0,811},{9,10,188},{138,10,572},{4,0,343},{5,0,511},{134,10,1693},{134,11\n,164},{132,0,448},{7,0,455},{138,0,591},{135,0,1381},{12,10,441},{150,11,50},{9,\n10,449},{10,10,192},{138,10,740},{4,10,241},{134,0,575},{134,0,1175},{134,0,653}\n,{134,0,1761},{134,0,1198},{132,10,259},{6,11,343},{7,11,195},{9,11,226},{10,11,\n197},{10,11,575},{11,11,502},{139,11,899},{7,0,1127},{7,0,1572},{10,0,297},{10,0\n,422},{11,0,764},{11,0,810},{12,0,264},{13,0,102},{13,0,300},{13,0,484},{14,0,\n147},{14,0,229},{17,0,71},{18,0,118},{147,0,120},{135,11,666},{132,0,678},{4,10,\n173},{5,10,312},{5,10,512},{135,10,1285},{7,10,1603},{7,10,1691},{9,10,464},{11,\n10,195},{12,10,279},{12,10,448},{14,10,11},{147,10,102},{16,0,99},{146,0,164},{7\n,11,1125},{9,11,143},{11,11,61},{14,11,405},{150,11,21},{137,11,260},{4,10,452},\n{5,10,583},{5,10,817},{6,10,433},{7,10,593},{7,10,720},{7,10,1378},{8,10,161},{9\n,10,284},{10,10,313},{139,10,886},{132,10,547},{136,10,722},{14,0,35},{142,0,191\n},{141,0,45},{138,0,121},{132,0,125},{134,0,1622},{133,11,959},{8,10,420},{139,\n10,193},{132,0,721},{135,10,409},{136,0,145},{7,0,792},{8,0,147},{8,11,173},{10,\n0,821},{11,0,970},{139,0,1021},{134,11,266},{132,0,715},{7,0,1999},{138,10,308},\n{133,0,531},{5,0,168},{5,0,930},{8,0,74},{9,0,623},{12,0,500},{140,0,579},{144,0\n,65},{138,11,246},{6,0,220},{7,0,1101},{13,0,105},{142,11,314},{5,10,1002},{136,\n10,745},{134,0,960},{20,0,0},{148,11,0},{4,0,1005},{4,10,239},{6,10,477},{7,10,\n1607},{11,10,68},{139,10,617},{6,0,19},{7,0,1413},{139,0,428},{149,10,13},{7,0,\n96},{8,0,401},{8,0,703},{8,11,300},{137,0,896},{134,0,1595},{145,0,116},{136,0,\n1021},{7,0,1961},{7,0,1965},{7,0,2030},{8,0,150},{8,0,702},{8,0,737},{8,0,750},{\n140,0,366},{11,11,75},{142,11,267},{132,10,367},{5,11,427},{5,11,734},{7,11,478}\n,{8,0,800},{8,11,52},{9,0,148},{9,0,872},{9,0,890},{11,0,309},{11,0,1001},{13,0,\n267},{141,0,323},{7,11,239},{11,11,217},{142,11,165},{132,11,323},{140,11,419},{\n13,0,299},{142,0,75},{6,11,87},{6,11,1734},{7,11,20},{7,11,1056},{8,11,732},{9,\n11,406},{9,11,911},{138,11,694},{134,0,1383},{132,10,694},{133,11,613},{137,0,\n779},{4,0,598},{140,10,687},{6,0,970},{135,0,424},{133,0,547},{7,11,32},{7,11,\n984},{8,11,85},{8,11,709},{9,11,579},{9,11,847},{9,11,856},{10,11,799},{11,11,\n258},{11,11,1007},{12,11,331},{12,11,615},{13,11,188},{13,11,435},{14,11,8},{15,\n11,165},{16,11,27},{148,11,40},{6,0,1222},{134,0,1385},{132,0,876},{138,11,151},\n{135,10,213},{4,11,167},{135,11,82},{133,0,133},{6,11,24},{7,11,74},{7,11,678},{\n137,11,258},{5,11,62},{6,11,534},{7,11,684},{7,11,1043},{7,11,1072},{8,11,280},{\n8,11,541},{8,11,686},{10,11,519},{11,11,252},{140,11,282},{136,0,187},{8,0,8},{\n10,0,0},{10,0,818},{139,0,988},{132,11,359},{7,10,1672},{11,0,429},{143,0,51},{\n136,0,685},{5,11,211},{7,11,88},{136,11,627},{134,0,472},{136,0,132},{6,11,145},\n{141,11,336},{4,10,751},{11,10,390},{140,10,32},{4,10,409},{4,11,263},{5,10,78},\n{6,0,938},{134,0,1060},{137,0,874},{4,11,916},{6,10,473},{7,10,1602},{8,0,774},{\n10,0,670},{10,10,698},{12,0,51},{12,10,212},{13,10,307},{145,10,105},{146,0,92},\n{143,10,156},{132,0,830},{137,0,701},{4,11,599},{6,11,1634},{7,11,5},{7,11,55},{\n7,11,67},{7,11,97},{7,11,691},{7,11,979},{7,11,1697},{8,11,207},{8,11,214},{8,11\n,231},{8,11,294},{8,11,336},{8,11,428},{8,11,451},{8,11,460},{8,11,471},{8,11,\n622},{8,11,626},{8,11,679},{8,11,759},{8,11,829},{9,11,11},{9,11,246},{9,11,484}\n,{9,11,573},{9,11,706},{9,11,762},{9,11,798},{9,11,855},{9,11,870},{9,11,912},{\n10,11,303},{10,11,335},{10,11,424},{10,11,461},{10,11,543},{10,11,759},{10,11,\n814},{11,11,59},{11,11,199},{11,11,235},{11,11,475},{11,11,590},{11,11,929},{11,\n11,963},{12,11,114},{12,11,182},{12,11,226},{12,11,332},{12,11,439},{12,11,575},\n{12,11,598},{13,11,8},{13,11,125},{13,11,194},{13,11,287},{14,11,197},{14,11,383\n},{15,11,53},{17,11,63},{19,11,46},{19,11,98},{19,11,106},{148,11,85},{4,0,127},\n{5,0,350},{6,0,356},{8,0,426},{9,0,572},{10,0,247},{139,0,312},{134,0,1215},{6,0\n,59},{7,11,1853},{9,0,603},{10,11,437},{141,0,397},{134,0,1762},{147,11,126},{\n135,10,883},{13,0,293},{142,0,56},{133,10,617},{139,10,50},{5,11,187},{7,10,1518\n},{139,10,694},{135,0,441},{6,0,111},{7,0,4},{8,0,163},{8,0,776},{138,0,566},{\n132,0,806},{4,11,215},{9,11,38},{10,11,3},{11,11,23},{11,11,127},{139,11,796},{4\n,10,546},{7,10,2042},{142,0,233},{135,0,1994},{134,0,1739},{135,11,1530},{136,0,\n393},{5,0,297},{7,0,1038},{14,0,359},{19,0,52},{148,0,47},{135,0,309},{4,10,313}\n,{133,10,577},{8,10,184},{141,10,433},{135,10,935},{12,10,186},{12,10,292},{14,\n10,100},{146,10,70},{136,0,363},{11,10,402},{12,10,109},{12,10,431},{13,10,179},\n{13,10,206},{14,0,175},{14,10,217},{16,10,3},{148,10,53},{5,10,886},{6,10,46},{6\n,10,1790},{7,10,14},{7,10,732},{7,10,1654},{8,10,95},{8,10,327},{8,10,616},{9,10\n,892},{10,10,598},{10,10,769},{11,10,134},{11,10,747},{12,10,378},{142,10,97},{\n136,0,666},{135,0,1675},{6,0,655},{134,0,1600},{135,0,808},{133,10,1021},{4,11,\n28},{5,11,440},{7,11,248},{11,11,833},{140,11,344},{134,11,1654},{132,0,280},{\n140,0,54},{4,0,421},{133,0,548},{132,10,153},{6,11,339},{135,11,923},{133,11,853\n},{133,10,798},{132,10,587},{6,11,249},{7,11,1234},{139,11,573},{6,10,598},{7,10\n,42},{8,10,695},{10,10,212},{11,10,158},{14,10,196},{145,10,85},{5,10,957},{5,10\n,1008},{135,0,249},{4,10,129},{135,10,465},{6,0,254},{7,0,842},{7,0,1659},{7,10,\n908},{7,10,1201},{9,0,109},{9,10,755},{10,0,103},{11,10,906},{12,10,527},{146,10\n,7},{5,0,262},{136,10,450},{144,0,1},{10,11,201},{142,11,319},{7,11,49},{7,11,\n392},{8,11,20},{8,11,172},{8,11,690},{9,11,383},{9,11,845},{10,11,48},{11,11,293\n},{11,11,832},{11,11,920},{141,11,221},{5,11,858},{133,11,992},{134,0,805},{139,\n10,1003},{6,0,1630},{134,11,307},{7,11,1512},{135,11,1794},{6,11,268},{137,11,62\n},{135,10,1868},{133,0,671},{4,0,989},{8,0,972},{136,0,998},{132,11,423},{132,0,\n889},{135,0,1382},{135,0,1910},{7,10,965},{7,10,1460},{135,10,1604},{4,0,627},{5\n,0,775},{138,11,106},{134,11,348},{7,0,202},{11,0,362},{11,0,948},{140,0,388},{\n138,11,771},{6,11,613},{136,11,223},{6,0,560},{7,0,451},{8,0,389},{12,0,490},{13\n,0,16},{13,0,215},{13,0,351},{18,0,132},{147,0,125},{135,0,841},{136,0,566},{136\n,0,938},{132,11,670},{5,0,912},{6,0,1695},{140,11,55},{9,11,40},{139,11,136},{7,\n0,1361},{7,10,982},{10,10,32},{143,10,56},{11,11,259},{140,11,270},{5,0,236},{6,\n0,572},{8,0,492},{11,0,618},{144,0,56},{8,11,572},{9,11,310},{9,11,682},{137,11,\n698},{134,0,1854},{5,0,190},{136,0,318},{133,10,435},{135,0,1376},{4,11,296},{6,\n11,352},{7,11,401},{7,11,1410},{7,11,1594},{7,11,1674},{8,11,63},{8,11,660},{137\n,11,74},{5,10,85},{6,10,419},{7,0,349},{7,10,305},{7,10,361},{7,10,1337},{8,10,\n71},{140,10,519},{4,11,139},{4,11,388},{140,11,188},{6,0,1972},{6,0,2013},{8,0,\n951},{10,0,947},{10,0,974},{10,0,1018},{142,0,476},{140,10,688},{135,10,740},{5,\n10,691},{7,10,345},{9,10,94},{140,10,169},{5,10,183},{6,10,582},{9,0,344},{10,10\n,679},{140,10,435},{135,10,511},{132,0,850},{8,11,441},{10,11,314},{143,11,3},{7\n,10,1993},{136,10,684},{4,11,747},{6,10,583},{6,11,290},{7,11,649},{7,11,1479},{\n135,11,1583},{133,11,232},{133,10,704},{134,0,910},{4,10,179},{5,10,198},{133,10\n,697},{7,10,347},{7,10,971},{8,10,181},{138,10,711},{136,11,525},{14,0,19},{14,0\n,28},{144,0,29},{7,0,85},{7,0,247},{8,0,585},{138,0,163},{4,0,487},{7,11,472},{7\n,11,1801},{10,11,748},{141,11,458},{4,10,243},{5,10,203},{7,10,19},{7,10,71},{7,\n10,113},{10,10,405},{11,10,357},{142,10,240},{7,10,1450},{139,10,99},{132,11,425\n},{138,0,145},{147,0,83},{6,10,492},{137,11,247},{4,0,1013},{134,0,2033},{5,10,\n134},{6,10,408},{6,10,495},{135,10,1593},{135,0,1922},{134,11,1768},{4,0,124},{\n10,0,457},{11,0,121},{11,0,169},{11,0,870},{11,0,874},{12,0,214},{14,0,187},{143\n,0,77},{5,0,557},{135,0,1457},{139,0,66},{5,11,943},{6,11,1779},{142,10,4},{4,10\n,248},{4,10,665},{7,10,137},{137,10,349},{5,11,245},{6,11,576},{7,0,1193},{7,11,\n582},{136,11,225},{144,0,82},{7,10,1270},{139,10,612},{5,0,454},{10,0,352},{138,\n11,352},{5,10,371},{7,10,563},{146,0,57},{135,0,1333},{6,0,107},{6,11,610},{7,0,\n638},{7,0,1632},{137,0,396},{5,0,370},{134,0,1756},{4,10,374},{7,10,547},{7,10,\n1700},{7,10,1833},{139,10,858},{133,0,204},{6,0,1305},{9,10,311},{141,10,42},{5,\n0,970},{134,0,1706},{6,10,1647},{7,10,1552},{7,10,2010},{9,10,494},{137,10,509},\n{13,11,455},{15,11,99},{15,11,129},{144,11,68},{135,0,3},{4,0,35},{5,0,121},{5,0\n,483},{5,0,685},{6,0,489},{6,0,782},{6,0,1032},{7,0,1204},{136,0,394},{4,0,921},\n{133,0,1007},{8,11,360},{138,11,63},{135,0,1696},{134,0,1519},{132,11,443},{135,\n11,944},{6,10,123},{7,10,214},{9,10,728},{10,10,157},{11,10,346},{11,10,662},{\n143,10,106},{137,0,981},{135,10,1435},{134,0,1072},{132,0,712},{134,0,1629},{134\n,0,728},{4,11,298},{137,11,483},{5,11,164},{6,0,1177},{6,0,1271},{7,11,121},{142\n,11,189},{4,10,707},{5,10,588},{6,10,393},{7,0,1608},{13,10,106},{18,10,49},{147\n,10,41},{23,0,16},{151,11,16},{6,10,211},{7,10,1690},{11,10,486},{140,10,369},{\n133,0,485},{19,11,15},{149,11,27},{4,11,172},{9,11,611},{10,11,436},{12,11,673},\n{141,11,255},{5,11,844},{10,11,484},{11,11,754},{12,11,457},{14,11,171},{14,11,\n389},{146,11,153},{4,0,285},{5,0,27},{5,0,317},{6,0,301},{7,0,7},{8,0,153},{10,0\n,766},{11,0,468},{12,0,467},{141,0,143},{134,0,1462},{9,11,263},{10,11,147},{138\n,11,492},{133,11,537},{6,0,1945},{6,0,1986},{6,0,1991},{134,0,2038},{134,10,219}\n,{137,11,842},{5,10,582},{6,10,1646},{7,10,99},{7,10,1962},{7,10,1986},{8,10,515\n},{8,10,773},{9,10,23},{9,10,491},{12,10,620},{14,0,52},{14,10,93},{145,0,50},{\n138,11,97},{5,10,851},{20,0,21},{148,0,44},{136,0,819},{139,0,917},{5,11,230},{5\n,11,392},{6,11,420},{8,10,762},{8,10,812},{9,10,910},{9,11,568},{140,11,612},{\n135,0,784},{15,0,135},{143,11,135},{10,0,454},{140,0,324},{4,11,0},{5,11,41},{7,\n11,1459},{7,11,1469},{7,11,1618},{7,11,1859},{9,11,549},{139,11,905},{4,10,98},{\n7,10,1365},{9,10,422},{9,10,670},{10,10,775},{11,10,210},{13,10,26},{13,10,457},\n{141,10,476},{6,0,1719},{6,0,1735},{7,0,2016},{7,0,2020},{8,0,837},{137,0,852},{\n133,11,696},{135,0,852},{132,0,952},{134,10,1730},{132,11,771},{138,0,568},{137,\n0,448},{139,0,146},{8,0,67},{138,0,419},{133,11,921},{137,10,147},{134,0,1826},{\n10,0,657},{14,0,297},{142,0,361},{6,0,666},{6,0,767},{134,0,1542},{139,0,729},{6\n,11,180},{7,11,1137},{8,11,751},{139,11,805},{4,11,183},{7,11,271},{11,11,824},{\n11,11,952},{13,11,278},{13,11,339},{13,11,482},{14,11,424},{148,11,99},{4,0,669}\n,{5,11,477},{5,11,596},{6,11,505},{7,11,1221},{11,11,907},{12,11,209},{141,11,\n214},{135,11,1215},{5,0,402},{6,10,30},{11,10,56},{139,10,305},{7,11,564},{142,\n11,168},{139,0,152},{7,0,912},{135,10,1614},{4,10,150},{5,10,303},{134,10,327},{\n7,0,320},{8,0,51},{9,0,868},{10,0,833},{12,0,481},{12,0,570},{148,0,106},{132,0,\n445},{7,11,274},{11,11,263},{11,11,479},{11,11,507},{140,11,277},{6,11,1645},{8,\n10,192},{10,0,555},{10,10,78},{11,0,308},{13,10,359},{147,0,95},{135,10,786},{6,\n11,92},{6,11,188},{7,11,1269},{7,11,1524},{7,11,1876},{10,11,228},{139,11,1020},\n{4,11,459},{133,11,966},{6,10,1638},{7,10,79},{7,10,496},{9,10,138},{10,10,336},\n{11,0,386},{12,10,412},{12,10,440},{142,10,305},{133,0,239},{7,0,83},{7,0,1990},\n{8,0,130},{139,0,720},{138,11,709},{4,0,143},{5,0,550},{133,0,752},{5,0,123},{6,\n0,530},{7,0,348},{135,0,1419},{135,0,2024},{6,11,18},{7,11,179},{7,11,721},{7,11\n,932},{8,11,548},{8,11,757},{9,11,54},{9,11,65},{9,11,532},{9,11,844},{10,11,113\n},{10,11,117},{10,11,236},{10,11,315},{10,11,430},{10,11,798},{11,11,153},{11,11\n,351},{11,11,375},{12,11,78},{12,11,151},{12,11,392},{14,11,248},{143,11,23},{7,\n10,204},{7,10,415},{8,10,42},{10,10,85},{139,10,564},{134,0,958},{133,11,965},{\n132,0,210},{135,11,1429},{138,11,480},{134,11,182},{139,11,345},{10,11,65},{10,\n11,488},{138,11,497},{4,10,3},{5,10,247},{5,10,644},{7,10,744},{7,10,1207},{7,10\n,1225},{7,10,1909},{146,10,147},{132,0,430},{5,10,285},{9,10,67},{13,10,473},{\n143,10,82},{144,11,16},{7,11,1162},{9,11,588},{10,11,260},{151,10,8},{133,0,213}\n,{138,0,7},{135,0,801},{134,11,1786},{135,11,308},{6,0,936},{134,0,1289},{133,0,\n108},{132,0,885},{133,0,219},{139,0,587},{4,0,193},{5,0,916},{6,0,1041},{7,0,364\n},{10,0,398},{10,0,726},{11,0,317},{11,0,626},{12,0,142},{12,0,288},{12,0,678},{\n13,0,313},{15,0,113},{146,0,114},{135,0,1165},{6,0,241},{9,0,342},{10,0,729},{11\n,0,284},{11,0,445},{11,0,651},{11,0,863},{13,0,398},{146,0,99},{7,0,907},{136,0,\n832},{4,10,29},{6,10,532},{7,10,1628},{7,10,1648},{9,0,303},{9,10,350},{10,10,\n433},{11,10,97},{11,10,557},{11,10,745},{12,10,289},{12,10,335},{12,10,348},{12,\n10,606},{13,10,116},{13,10,233},{13,10,466},{14,10,181},{14,10,209},{14,10,232},\n{14,10,236},{14,10,300},{16,10,41},{148,10,97},{7,10,1692},{7,11,423},{136,11,\n588},{6,0,931},{134,0,1454},{5,10,501},{7,10,1704},{9,10,553},{11,10,520},{12,10\n,557},{141,10,249},{136,11,287},{4,0,562},{9,0,254},{139,0,879},{132,0,786},{14,\n11,32},{18,11,85},{20,11,2},{152,11,16},{135,0,1294},{7,11,723},{135,11,1135},{6\n,0,216},{6,11,403},{7,0,901},{7,0,1343},{136,0,493},{7,11,719},{8,11,809},{136,\n11,834},{5,11,210},{6,11,213},{7,11,60},{10,11,364},{139,11,135},{5,11,607},{7,0\n,341},{8,11,326},{8,11,490},{139,0,219},{4,11,701},{5,11,472},{5,11,639},{7,11,\n1249},{9,11,758},{139,11,896},{135,11,380},{135,11,1947},{139,0,130},{135,0,1734\n},{10,0,115},{11,0,420},{12,0,154},{13,0,404},{14,0,346},{143,0,54},{134,10,129}\n,{4,11,386},{7,11,41},{8,11,405},{9,11,497},{11,11,110},{11,11,360},{15,11,37},{\n144,11,84},{141,11,282},{5,11,46},{7,11,1452},{7,11,1480},{8,11,634},{140,11,472\n},{4,11,524},{136,11,810},{10,11,238},{141,11,33},{133,0,604},{5,0,1011},{136,0,\n701},{8,0,856},{8,0,858},{8,0,879},{12,0,702},{142,0,447},{4,0,54},{5,0,666},{7,\n0,1039},{7,0,1130},{9,0,195},{138,0,302},{4,10,25},{5,10,60},{6,10,504},{7,10,\n614},{7,10,1155},{140,10,0},{7,10,1248},{11,10,621},{139,10,702},{133,11,997},{\n137,10,321},{134,0,1669},{134,0,1791},{4,10,379},{135,10,1397},{138,11,372},{5,\n11,782},{5,11,829},{134,11,1738},{135,0,1228},{4,10,118},{6,10,274},{6,10,361},{\n7,10,75},{141,10,441},{132,0,623},{9,11,279},{10,11,407},{14,11,84},{150,11,18},\n{137,10,841},{135,0,798},{140,10,693},{5,10,314},{6,10,221},{7,10,419},{10,10,\n650},{11,10,396},{12,10,156},{13,10,369},{14,10,333},{145,10,47},{135,11,1372},{\n7,0,122},{9,0,259},{10,0,84},{11,0,470},{12,0,541},{141,0,379},{134,0,837},{4,11\n,78},{5,11,96},{5,11,182},{7,11,1724},{7,11,1825},{8,0,1013},{10,11,394},{10,11,\n471},{11,11,532},{14,11,340},{145,11,88},{134,0,577},{135,11,1964},{132,10,913},\n{134,0,460},{8,0,891},{10,0,901},{10,0,919},{10,0,932},{12,0,715},{12,0,728},{12\n,0,777},{14,0,457},{144,0,103},{5,0,82},{5,0,131},{7,0,1755},{8,0,31},{9,0,168},\n{9,0,764},{139,0,869},{136,10,475},{5,10,1016},{6,0,605},{9,11,601},{9,11,619},{\n10,11,505},{10,11,732},{11,11,355},{140,11,139},{7,10,602},{8,10,179},{10,10,781\n},{140,10,126},{134,0,1246},{6,10,329},{138,10,111},{6,11,215},{7,11,1028},{7,11\n,1473},{7,11,1721},{9,11,424},{138,11,779},{5,0,278},{137,0,68},{6,0,932},{6,0,\n1084},{144,0,86},{4,0,163},{5,0,201},{5,0,307},{5,0,310},{6,0,335},{7,0,284},{7,\n0,1660},{136,0,165},{136,0,781},{134,0,707},{6,0,33},{135,0,1244},{5,10,821},{6,\n10,1687},{6,11,67},{7,11,258},{7,11,1630},{9,11,354},{9,11,675},{10,11,830},{14,\n11,80},{145,11,80},{6,11,141},{7,11,225},{9,11,59},{9,11,607},{10,11,312},{11,11\n,687},{12,11,555},{13,11,373},{13,11,494},{148,11,58},{134,0,1113},{5,10,71},{7,\n10,1407},{9,0,388},{9,10,704},{10,10,261},{10,10,619},{11,10,547},{11,10,619},{\n143,10,157},{7,0,1953},{136,0,720},{138,0,203},{7,10,2008},{9,10,337},{138,10,\n517},{6,0,326},{7,0,677},{137,0,425},{139,11,81},{7,0,1316},{7,0,1412},{7,0,1839\n},{9,0,589},{11,0,241},{11,0,676},{11,0,811},{11,0,891},{12,0,140},{12,0,346},{\n12,0,479},{13,0,140},{13,0,381},{14,0,188},{18,0,30},{148,0,108},{5,0,416},{6,10\n,86},{6,10,603},{7,10,292},{7,10,561},{8,10,257},{8,10,382},{9,10,721},{9,10,778\n},{11,10,581},{140,10,466},{4,10,486},{133,10,491},{134,0,1300},{132,10,72},{6,\n10,265},{7,0,847},{7,11,430},{139,11,46},{5,11,602},{6,11,106},{7,11,1786},{7,11\n,1821},{7,11,2018},{9,11,418},{137,11,763},{5,0,358},{7,0,535},{7,0,1184},{10,0,\n662},{13,0,212},{13,0,304},{13,0,333},{145,0,98},{5,11,65},{6,11,416},{7,11,1720\n},{7,11,1924},{8,11,677},{10,11,109},{11,11,14},{11,11,70},{11,11,569},{11,11,\n735},{15,11,153},{148,11,80},{6,0,1823},{8,0,839},{8,0,852},{8,0,903},{10,0,940}\n,{12,0,707},{140,0,775},{135,11,1229},{6,0,1522},{140,0,654},{136,11,595},{139,0\n,163},{141,0,314},{132,0,978},{4,0,601},{6,0,2035},{137,10,234},{5,10,815},{6,10\n,1688},{134,10,1755},{133,0,946},{136,0,434},{6,10,197},{136,10,205},{7,0,411},{\n7,0,590},{8,0,631},{9,0,323},{10,0,355},{11,0,491},{12,0,143},{12,0,402},{13,0,\n73},{14,0,408},{15,0,107},{146,0,71},{7,0,1467},{8,0,328},{10,0,544},{11,0,955},\n{12,0,13},{13,0,320},{145,0,83},{142,0,410},{11,0,511},{13,0,394},{14,0,298},{14\n,0,318},{146,0,103},{6,10,452},{7,10,312},{138,10,219},{138,10,589},{4,10,333},{\n9,10,176},{12,10,353},{141,10,187},{135,11,329},{132,11,469},{5,0,835},{134,0,\n483},{134,11,1743},{5,11,929},{6,11,340},{8,11,376},{136,11,807},{134,10,1685},{\n132,0,677},{5,11,218},{7,11,1610},{138,11,83},{5,11,571},{135,11,1842},{132,11,\n455},{137,0,70},{135,0,1405},{7,10,135},{8,10,7},{8,10,62},{9,10,243},{10,10,658\n},{10,10,697},{11,10,456},{139,10,756},{9,10,395},{138,10,79},{137,0,108},{6,11,\n161},{7,11,372},{137,11,597},{132,11,349},{132,0,777},{132,0,331},{135,10,631},{\n133,0,747},{6,11,432},{6,11,608},{139,11,322},{138,10,835},{5,11,468},{7,11,1809\n},{10,11,325},{11,11,856},{12,11,345},{143,11,104},{133,11,223},{7,10,406},{7,10\n,459},{8,10,606},{139,10,726},{132,11,566},{142,0,68},{4,11,59},{135,11,1394},{6\n,11,436},{139,11,481},{4,11,48},{5,11,271},{135,11,953},{139,11,170},{5,11,610},\n{136,11,457},{133,11,755},{135,11,1217},{133,10,612},{132,11,197},{132,0,505},{4\n,10,372},{7,10,482},{8,10,158},{9,10,602},{9,10,615},{10,10,245},{10,10,678},{10\n,10,744},{11,10,248},{139,10,806},{133,0,326},{5,10,854},{135,10,1991},{4,0,691}\n,{146,0,16},{6,0,628},{9,0,35},{10,0,680},{10,0,793},{11,0,364},{13,0,357},{143,\n0,164},{138,0,654},{6,0,32},{7,0,385},{7,0,757},{7,0,1916},{8,0,37},{8,0,94},{8,\n0,711},{9,0,541},{10,0,162},{10,0,795},{11,0,989},{11,0,1010},{12,0,14},{142,0,\n308},{133,11,217},{6,0,152},{6,0,349},{6,0,1682},{7,0,1252},{8,0,112},{9,0,435},\n{9,0,668},{10,0,290},{10,0,319},{10,0,815},{11,0,180},{11,0,837},{12,0,240},{13,\n0,152},{13,0,219},{142,0,158},{4,0,581},{134,0,726},{5,10,195},{135,10,1685},{6,\n0,126},{7,0,573},{8,0,397},{142,0,44},{138,0,89},{7,10,1997},{8,10,730},{139,10,\n1006},{134,0,1531},{134,0,1167},{5,0,926},{5,10,751},{140,0,203},{4,11,165},{7,\n11,1398},{135,11,1829},{7,0,1232},{137,0,531},{135,10,821},{134,0,943},{133,0,\n670},{4,0,880},{139,0,231},{134,0,1617},{135,0,1957},{5,11,9},{7,11,297},{7,11,\n966},{140,11,306},{6,0,975},{134,0,985},{5,10,950},{5,10,994},{134,10,351},{12,\n11,21},{151,11,7},{5,11,146},{6,11,411},{138,11,721},{7,0,242},{135,0,1942},{6,\n11,177},{135,11,467},{5,0,421},{7,10,47},{137,10,684},{5,0,834},{7,0,1202},{8,0,\n14},{9,0,481},{137,0,880},{138,0,465},{4,10,350},{6,0,688},{137,0,834},{132,0,\n855},{4,0,357},{6,0,172},{7,0,143},{137,0,413},{133,11,200},{132,0,590},{7,10,\n1812},{13,10,259},{13,10,356},{14,10,242},{147,10,114},{133,10,967},{4,10,473},{\n7,10,623},{8,10,808},{9,10,871},{9,10,893},{11,0,114},{11,10,431},{12,10,112},{\n12,10,217},{12,10,243},{12,10,562},{12,10,663},{12,10,683},{13,10,141},{13,10,\n197},{13,10,227},{13,10,406},{13,10,487},{14,10,156},{14,10,203},{14,10,224},{14\n,10,256},{18,10,58},{150,10,0},{138,10,286},{4,10,222},{7,10,286},{136,10,629},{\n5,0,169},{7,0,333},{136,0,45},{134,11,481},{132,0,198},{4,0,24},{4,11,84},{5,0,\n140},{5,0,185},{7,0,1500},{7,11,1482},{10,11,76},{10,11,142},{11,0,565},{139,0,\n838},{133,0,585},{141,10,306},{133,11,1015},{4,11,315},{5,11,507},{135,11,1370},\n{136,10,146},{6,0,691},{134,0,1503},{4,0,334},{133,0,593},{4,10,465},{135,10,\n1663},{142,11,173},{135,0,913},{6,11,1722},{140,0,116},{134,0,1360},{132,0,802},\n{8,11,222},{8,11,476},{9,11,238},{11,11,516},{11,11,575},{15,11,109},{146,11,100\n},{6,0,308},{7,10,138},{7,10,517},{9,0,673},{139,10,238},{132,0,709},{6,0,1876},\n{6,0,1895},{9,0,994},{9,0,1006},{12,0,829},{12,0,888},{12,0,891},{146,0,185},{\n148,10,94},{4,0,228},{133,0,897},{5,10,495},{7,0,1840},{7,10,834},{9,10,733},{\n139,10,378},{133,10,559},{6,10,21},{6,10,1737},{7,10,1444},{136,10,224},{4,0,608\n},{133,0,497},{6,11,40},{135,11,1781},{134,0,1573},{135,0,2039},{6,0,540},{136,0\n,136},{4,0,897},{5,0,786},{133,10,519},{6,0,1878},{6,0,1884},{9,0,938},{9,0,948}\n,{9,0,955},{9,0,973},{9,0,1012},{12,0,895},{12,0,927},{143,0,254},{134,0,1469},{\n133,0,999},{4,0,299},{135,0,1004},{4,0,745},{133,0,578},{136,11,574},{133,0,456}\n,{134,0,1457},{4,10,402},{135,0,1679},{7,0,693},{8,0,180},{8,10,323},{8,10,479},\n{140,0,163},{11,10,580},{142,10,201},{5,10,59},{135,10,672},{132,11,354},{146,10\n,34},{4,0,755},{135,11,1558},{7,0,1740},{146,0,48},{4,10,85},{135,10,549},{139,0\n,338},{133,10,94},{134,0,1091},{135,11,469},{5,11,830},{12,0,695},{12,0,704},{14\n,11,338},{20,0,113},{148,11,81},{135,0,1464},{6,10,11},{135,10,187},{135,0,975},\n{4,10,522},{141,0,335},{134,0,1979},{5,11,496},{135,11,203},{4,10,52},{135,10,\n661},{7,0,1566},{8,0,269},{9,0,212},{9,0,718},{14,0,15},{14,0,132},{142,0,227},{\n4,0,890},{4,10,383},{5,0,805},{5,0,819},{5,0,961},{5,10,520},{6,0,396},{6,0,1631\n},{6,0,1678},{7,0,1967},{7,0,2041},{9,0,630},{11,0,8},{11,0,1019},{12,0,176},{13\n,0,225},{14,0,292},{149,0,24},{134,11,547},{135,11,1748},{5,11,88},{137,11,239},\n{146,11,128},{7,11,650},{135,11,1310},{4,10,281},{5,10,38},{7,10,194},{7,10,668}\n,{7,10,1893},{137,10,397},{135,0,1815},{9,10,635},{139,10,559},{7,0,1505},{10,0,\n190},{10,0,634},{11,0,792},{12,0,358},{140,0,447},{5,0,0},{6,0,536},{7,0,604},{\n13,0,445},{145,0,126},{7,11,1076},{9,11,80},{11,11,78},{11,11,421},{11,11,534},{\n140,11,545},{8,0,966},{10,0,1023},{14,11,369},{146,11,72},{135,11,1641},{6,0,232\n},{6,0,412},{7,0,1074},{8,0,9},{8,0,157},{8,0,786},{9,0,196},{9,0,352},{9,0,457}\n,{10,0,337},{11,0,232},{11,0,877},{12,0,480},{140,0,546},{135,0,958},{4,0,382},{\n136,0,579},{4,0,212},{135,0,1206},{4,11,497},{5,11,657},{135,11,1584},{132,0,681\n},{8,0,971},{138,0,965},{5,10,448},{136,10,535},{14,0,16},{146,0,44},{11,0,584},\n{11,0,616},{11,11,584},{11,11,616},{14,0,275},{142,11,275},{136,11,13},{7,10,610\n},{135,10,1501},{7,11,642},{8,11,250},{11,11,123},{11,11,137},{13,11,48},{142,11\n,95},{133,0,655},{17,0,67},{147,0,74},{134,0,751},{134,0,1967},{6,0,231},{136,0,\n423},{5,0,300},{138,0,1016},{4,10,319},{5,10,699},{138,10,673},{6,0,237},{6,10,\n336},{7,0,611},{8,0,100},{8,10,552},{9,0,416},{9,10,285},{10,10,99},{11,0,335},{\n11,10,568},{12,0,173},{146,0,101},{134,0,1370},{7,10,1406},{9,10,218},{141,10,\n222},{133,10,256},{135,0,1208},{14,11,213},{148,11,38},{6,0,1219},{135,11,1642},\n{13,0,417},{14,0,129},{143,0,15},{10,11,545},{140,11,301},{17,10,39},{148,10,36}\n,{133,0,199},{4,11,904},{133,11,794},{12,0,427},{146,0,38},{134,0,949},{7,10,634\n},{136,0,665},{132,10,618},{135,10,259},{132,10,339},{133,11,761},{141,10,169},{\n132,10,759},{5,0,688},{7,0,539},{135,0,712},{7,11,386},{138,11,713},{134,0,1186}\n,{6,11,7},{6,11,35},{7,11,147},{7,11,1069},{7,11,1568},{7,11,1575},{7,11,1917},{\n8,11,43},{8,11,208},{9,11,128},{9,11,866},{10,11,20},{11,11,981},{147,11,33},{7,\n11,893},{8,10,482},{141,11,424},{6,0,312},{6,0,1715},{10,0,584},{11,0,546},{11,0\n,692},{12,0,259},{12,0,295},{13,0,46},{141,0,154},{5,10,336},{6,10,341},{6,10,\n478},{6,10,1763},{136,10,386},{137,0,151},{132,0,588},{152,0,4},{6,11,322},{9,11\n,552},{11,11,274},{13,11,209},{13,11,499},{14,11,85},{15,11,126},{145,11,70},{\n135,10,73},{4,0,231},{5,0,61},{6,0,104},{7,0,729},{7,0,964},{7,0,1658},{140,0,\n414},{6,0,263},{138,0,757},{135,10,1971},{4,0,612},{133,0,561},{132,0,320},{135,\n10,1344},{8,11,83},{8,11,817},{9,11,28},{9,11,29},{9,11,885},{10,11,387},{11,11,\n633},{11,11,740},{13,11,235},{13,11,254},{15,11,143},{143,11,146},{5,10,396},{\n134,10,501},{140,11,49},{132,0,225},{4,10,929},{5,10,799},{8,10,46},{136,10,740}\n,{4,0,405},{7,0,817},{14,0,58},{17,0,37},{146,0,124},{133,0,974},{4,11,412},{133\n,11,581},{4,10,892},{133,10,770},{4,0,996},{134,0,2026},{4,0,527},{5,0,235},{7,0\n,1239},{11,0,131},{140,0,370},{7,11,421},{9,0,16},{141,0,386},{7,0,956},{7,0,\n1157},{7,0,1506},{7,0,1606},{7,0,1615},{7,0,1619},{7,0,1736},{7,0,1775},{8,0,590\n},{9,0,324},{9,0,736},{9,0,774},{9,0,776},{9,0,784},{10,0,567},{10,0,708},{11,0,\n518},{11,0,613},{11,0,695},{11,0,716},{11,0,739},{11,0,770},{11,0,771},{11,0,848\n},{11,0,857},{11,0,931},{11,0,947},{12,0,326},{12,0,387},{12,0,484},{12,0,528},{\n12,0,552},{12,0,613},{13,0,189},{13,0,256},{13,0,340},{13,0,432},{13,0,436},{13,\n0,440},{13,0,454},{14,0,174},{14,0,220},{14,0,284},{14,0,390},{145,0,121},{135,\n10,158},{9,0,137},{138,0,221},{4,11,110},{10,11,415},{10,11,597},{142,11,206},{\n141,11,496},{135,11,205},{151,10,25},{135,11,778},{7,10,2001},{7,11,1656},{9,11,\n369},{10,11,338},{10,11,490},{11,11,154},{11,11,545},{11,11,775},{13,11,77},{141\n,11,274},{4,11,444},{10,11,146},{140,11,9},{7,0,390},{138,0,140},{135,0,1144},{\n134,0,464},{7,10,1461},{140,10,91},{132,10,602},{4,11,283},{135,11,1194},{5,0,\n407},{11,0,204},{11,0,243},{11,0,489},{12,0,293},{19,0,37},{20,0,73},{150,0,38},\n{7,0,1218},{136,0,303},{4,10,13},{5,0,325},{5,10,567},{7,10,1498},{8,0,5},{8,0,\n227},{9,0,105},{9,10,124},{10,0,585},{11,10,521},{12,0,614},{140,10,405},{135,10\n,1006},{6,11,1720},{7,0,800},{138,0,12},{135,0,1783},{132,10,735},{138,10,812},{\n4,10,170},{135,10,323},{6,0,621},{13,0,504},{144,0,89},{5,10,304},{135,10,1403},\n{137,11,216},{6,0,920},{6,0,1104},{9,11,183},{139,11,286},{4,0,376},{133,10,742}\n,{134,0,218},{8,0,641},{11,0,388},{140,0,580},{7,0,454},{7,0,782},{8,0,768},{140\n,0,686},{137,11,33},{133,10,111},{144,0,0},{10,0,676},{140,0,462},{6,0,164},{136\n,11,735},{133,10,444},{150,0,50},{7,11,1862},{12,11,491},{12,11,520},{13,11,383}\n,{14,11,244},{146,11,12},{5,11,132},{9,11,486},{9,11,715},{10,11,458},{11,11,373\n},{11,11,668},{11,11,795},{11,11,897},{12,11,272},{12,11,424},{12,11,539},{12,11\n,558},{14,11,245},{14,11,263},{14,11,264},{14,11,393},{142,11,403},{8,10,123},{\n15,10,6},{144,10,7},{6,0,285},{8,0,654},{11,0,749},{12,0,190},{12,0,327},{13,0,\n120},{13,0,121},{13,0,327},{15,0,47},{146,0,40},{5,11,8},{6,11,89},{6,11,400},{7\n,11,1569},{7,11,1623},{7,11,1850},{8,11,218},{8,11,422},{9,11,570},{138,11,626},\n{6,11,387},{7,11,882},{141,11,111},{6,0,343},{6,11,224},{7,0,195},{7,11,877},{9,\n0,226},{9,11,647},{10,0,197},{10,0,575},{11,0,502},{139,0,899},{5,10,937},{135,\n10,100},{135,11,790},{150,0,29},{147,0,8},{134,0,1812},{149,0,8},{135,11,394},{7\n,0,1125},{9,0,143},{11,0,61},{14,0,405},{150,0,21},{10,11,755},{147,11,29},{9,11\n,378},{141,11,162},{135,10,922},{5,10,619},{133,10,698},{134,0,1327},{6,0,1598},\n{137,0,575},{9,11,569},{12,11,12},{12,11,81},{12,11,319},{13,11,69},{14,11,259},\n{16,11,87},{17,11,1},{17,11,21},{17,11,24},{18,11,15},{18,11,56},{18,11,59},{18,\n11,127},{18,11,154},{19,11,19},{148,11,31},{6,0,895},{135,11,1231},{5,0,959},{7,\n11,124},{136,11,38},{5,11,261},{7,11,78},{7,11,199},{8,11,815},{9,11,126},{138,\n11,342},{5,10,917},{134,10,1659},{5,11,595},{7,0,1759},{135,11,1863},{136,0,173}\n,{134,0,266},{142,0,261},{132,11,628},{5,10,251},{5,10,956},{8,10,268},{9,10,214\n},{146,10,142},{7,11,266},{136,11,804},{135,11,208},{6,11,79},{7,11,1021},{135,\n11,1519},{11,11,704},{141,11,396},{5,10,346},{5,10,711},{136,10,390},{136,11,741\n},{134,11,376},{134,0,1427},{6,0,1033},{6,0,1217},{136,0,300},{133,10,624},{6,11\n,100},{7,11,244},{7,11,632},{7,11,1609},{8,11,178},{8,11,638},{141,11,58},{5,10,\n783},{6,0,584},{7,10,1998},{135,10,2047},{5,0,427},{5,0,734},{7,0,478},{136,0,52\n},{7,0,239},{11,0,217},{142,0,165},{134,0,1129},{6,0,168},{6,0,1734},{7,0,20},{7\n,0,1056},{8,0,732},{9,0,406},{9,0,911},{138,0,694},{132,10,594},{133,11,791},{7,\n11,686},{8,11,33},{8,11,238},{10,11,616},{11,11,467},{11,11,881},{13,11,217},{13\n,11,253},{142,11,268},{137,11,476},{134,0,418},{133,0,613},{132,0,632},{132,11,\n447},{7,0,32},{7,0,984},{8,0,85},{8,0,709},{9,0,579},{9,0,847},{9,0,856},{10,0,\n799},{11,0,258},{11,0,1007},{12,0,331},{12,0,615},{13,0,188},{13,0,435},{14,0,8}\n,{15,0,165},{16,0,27},{16,11,35},{148,0,40},{4,11,128},{5,11,415},{6,11,462},{7,\n11,294},{7,11,578},{10,11,710},{139,11,86},{5,0,694},{136,0,909},{5,10,37},{6,10\n,39},{6,10,451},{7,0,1109},{7,10,218},{7,10,1166},{7,10,1687},{8,10,662},{11,0,7\n},{144,10,2},{136,11,587},{6,11,427},{7,11,1018},{138,11,692},{4,11,195},{6,10,\n508},{135,11,802},{4,0,167},{135,0,82},{5,0,62},{6,0,24},{6,0,534},{7,0,74},{7,0\n,678},{7,0,684},{7,0,1043},{7,0,1072},{8,0,280},{8,0,541},{8,0,686},{9,0,258},{\n10,0,519},{11,0,252},{140,0,282},{138,0,33},{4,0,359},{133,11,738},{7,0,980},{7,\n10,635},{7,10,796},{8,10,331},{9,0,328},{9,10,330},{9,10,865},{10,10,119},{10,10\n,235},{11,10,111},{11,10,129},{11,10,240},{12,10,31},{12,10,66},{12,10,222},{12,\n10,269},{12,10,599},{12,10,684},{12,10,689},{12,10,691},{13,0,186},{13,0,364},{\n142,10,345},{137,10,527},{6,0,596},{7,0,585},{135,10,702},{134,11,1683},{133,0,\n211},{6,0,145},{141,0,336},{134,0,1130},{6,10,37},{7,0,873},{7,10,1666},{8,10,\n195},{8,10,316},{9,10,178},{9,10,276},{9,10,339},{9,10,536},{10,10,102},{10,10,\n362},{10,10,785},{11,10,55},{11,10,149},{11,10,773},{13,10,416},{13,10,419},{14,\n10,38},{14,10,41},{142,10,210},{8,0,840},{136,0,841},{132,0,263},{5,11,3},{8,11,\n578},{9,11,118},{10,11,705},{12,11,383},{141,11,279},{132,0,916},{133,11,229},{\n133,10,645},{8,11,102},{10,11,578},{10,11,672},{12,11,496},{13,11,408},{14,11,\n121},{15,0,155},{16,0,79},{145,11,106},{4,0,599},{5,0,592},{6,0,1634},{7,0,5},{7\n,0,55},{7,0,67},{7,0,97},{7,0,691},{7,0,979},{7,0,1600},{7,0,1697},{8,0,207},{8,\n0,214},{8,0,231},{8,0,294},{8,0,336},{8,0,428},{8,0,471},{8,0,622},{8,0,626},{8,\n0,679},{8,0,759},{8,0,829},{9,0,11},{9,0,246},{9,0,484},{9,0,573},{9,0,706},{9,0\n,762},{9,0,798},{9,0,855},{9,0,870},{9,0,912},{10,0,303},{10,0,335},{10,0,424},{\n10,0,461},{10,0,543},{10,0,759},{10,0,814},{11,0,59},{11,0,199},{11,0,235},{11,0\n,590},{11,0,631},{11,0,929},{11,0,963},{11,0,987},{12,0,114},{12,0,182},{12,0,\n226},{12,0,332},{12,0,439},{12,0,575},{12,0,598},{12,0,675},{13,0,8},{13,0,125},\n{13,0,194},{13,0,287},{14,0,197},{14,0,383},{15,0,53},{17,0,63},{19,0,46},{19,0,\n98},{19,0,106},{148,0,85},{4,10,290},{135,0,1356},{6,10,70},{7,10,1292},{10,10,\n762},{139,10,288},{150,11,55},{4,0,593},{8,11,115},{8,11,350},{9,11,489},{10,11,\n128},{11,11,306},{12,11,373},{14,11,30},{17,11,79},{147,11,80},{135,11,1235},{\n134,0,1392},{4,11,230},{133,11,702},{147,0,126},{7,10,131},{7,10,422},{8,10,210}\n,{140,10,573},{134,0,1179},{139,11,435},{139,10,797},{134,11,1728},{4,0,162},{18\n,11,26},{19,11,42},{20,11,43},{21,11,0},{23,11,27},{152,11,14},{132,10,936},{5,\n10,453},{6,0,765},{134,10,441},{133,0,187},{135,0,1286},{6,0,635},{6,0,904},{6,0\n,1210},{134,0,1489},{4,0,215},{8,0,890},{9,0,38},{10,0,923},{11,0,23},{11,0,127}\n,{139,0,796},{6,0,1165},{134,0,1306},{7,0,716},{13,0,97},{141,0,251},{132,10,653\n},{136,0,657},{146,10,80},{5,11,622},{7,11,1032},{11,11,26},{11,11,213},{11,11,\n707},{12,11,380},{13,11,226},{141,11,355},{5,11,70},{6,0,299},{6,11,334},{9,11,\n171},{11,11,637},{12,11,202},{14,11,222},{145,11,42},{142,0,134},{4,11,23},{5,11\n,313},{5,11,1014},{6,11,50},{6,11,51},{7,11,142},{7,11,384},{9,11,783},{139,11,\n741},{4,11,141},{7,11,559},{8,11,640},{9,11,460},{12,11,183},{141,11,488},{136,\n11,614},{7,10,1368},{8,10,232},{8,10,361},{10,10,682},{138,10,742},{137,10,534},\n{6,0,1082},{140,0,658},{137,10,27},{135,0,2002},{142,10,12},{4,0,28},{5,0,440},{\n7,0,248},{11,0,833},{140,0,344},{7,10,736},{139,10,264},{134,10,1657},{134,0,\n1654},{138,0,531},{5,11,222},{9,11,140},{138,11,534},{6,0,634},{6,0,798},{134,0,\n840},{138,11,503},{135,10,127},{133,0,853},{5,11,154},{7,11,1491},{10,11,379},{\n138,11,485},{6,0,249},{7,0,1234},{139,0,573},{133,11,716},{7,11,1570},{140,11,\n542},{136,10,364},{138,0,527},{4,11,91},{5,11,388},{5,11,845},{6,11,206},{6,11,\n252},{6,11,365},{7,11,136},{7,11,531},{8,11,264},{136,11,621},{134,0,1419},{135,\n11,1441},{7,0,49},{7,0,392},{8,0,20},{8,0,172},{8,0,690},{9,0,383},{9,0,845},{10\n,0,48},{11,0,293},{11,0,832},{11,0,920},{11,0,984},{141,0,221},{5,0,858},{133,0,\n992},{5,0,728},{137,10,792},{5,10,909},{9,10,849},{138,10,805},{7,0,525},{7,0,\n1579},{8,0,497},{136,0,573},{6,0,268},{137,0,62},{135,11,576},{134,0,1201},{5,11\n,771},{5,11,863},{5,11,898},{6,11,1632},{6,11,1644},{134,11,1780},{133,11,331},{\n7,0,193},{7,0,1105},{7,10,397},{8,10,124},{8,10,619},{9,10,305},{10,0,495},{11,\n10,40},{12,10,349},{13,10,134},{13,10,295},{14,10,155},{15,10,120},{146,10,105},\n{138,0,106},{5,11,107},{6,0,859},{7,11,201},{136,11,518},{6,11,446},{135,11,1817\n},{4,10,262},{7,10,342},{141,0,23},{133,10,641},{137,11,851},{6,0,925},{137,0,\n813},{132,11,504},{6,0,613},{136,0,223},{4,10,99},{6,10,250},{6,10,346},{8,10,\n127},{138,10,81},{136,0,953},{132,10,915},{139,11,892},{5,10,75},{9,10,517},{10,\n10,470},{12,10,155},{141,10,224},{4,0,666},{7,0,1017},{7,11,996},{138,11,390},{5\n,11,883},{133,11,975},{14,10,83},{142,11,83},{4,0,670},{5,11,922},{134,11,1707},\n{135,0,216},{7,11,787},{9,0,40},{139,0,136},{5,10,954},{5,11,993},{7,11,515},{\n137,11,91},{139,0,259},{6,10,304},{7,0,1114},{8,10,418},{9,0,310},{9,0,682},{10,\n0,440},{11,10,341},{11,10,675},{141,0,40},{9,10,410},{11,10,425},{142,0,296},{10\n,11,377},{12,11,363},{13,11,68},{13,11,94},{14,11,108},{142,11,306},{7,0,1401},{\n135,0,1476},{4,0,296},{6,0,475},{7,0,401},{7,0,1410},{7,0,1594},{7,0,1674},{8,0,\n63},{8,0,660},{137,0,74},{4,0,139},{4,0,388},{140,0,188},{132,0,797},{132,11,766\n},{5,11,103},{7,11,921},{8,11,580},{8,11,593},{8,11,630},{138,11,28},{4,11,911},\n{5,11,867},{133,11,1013},{134,10,14},{134,0,1572},{134,10,1708},{5,10,113},{6,10\n,243},{7,10,1865},{11,10,161},{16,10,37},{17,10,99},{149,0,39},{7,11,1563},{141,\n11,182},{5,11,135},{6,11,519},{7,11,1722},{10,11,271},{11,11,261},{145,11,54},{\n132,10,274},{134,0,1594},{4,11,300},{5,11,436},{135,11,484},{4,0,747},{6,0,290},\n{7,0,649},{7,0,1479},{135,0,1583},{133,11,535},{147,11,82},{133,0,232},{137,0,\n887},{135,10,166},{136,0,521},{4,0,14},{7,0,472},{7,0,1801},{10,0,748},{141,0,\n458},{134,0,741},{134,0,992},{9,10,304},{144,0,111},{4,0,425},{5,11,387},{7,11,\n557},{12,11,547},{142,11,86},{135,11,1747},{5,10,654},{135,11,1489},{4,11,6},{5,\n11,708},{7,0,789},{136,11,75},{6,10,273},{10,10,188},{13,10,377},{146,10,77},{4,\n11,303},{6,0,1593},{7,11,619},{10,11,547},{10,11,687},{11,11,122},{140,11,601},{\n134,0,1768},{135,10,410},{138,11,772},{11,0,233},{139,10,524},{5,0,943},{134,0,\n1779},{134,10,1785},{136,11,529},{132,0,955},{5,0,245},{6,0,576},{7,0,582},{136,\n0,225},{132,10,780},{142,0,241},{134,0,1943},{4,11,106},{7,11,310},{7,11,1785},{\n10,11,690},{139,11,717},{134,0,1284},{5,11,890},{133,11,988},{6,11,626},{142,11,\n431},{10,11,706},{145,11,32},{137,11,332},{132,11,698},{135,0,709},{5,10,948},{\n138,11,17},{136,0,554},{134,0,1564},{139,10,941},{132,0,443},{134,0,909},{134,11\n,84},{142,0,280},{4,10,532},{5,10,706},{135,10,662},{132,0,729},{5,10,837},{6,10\n,1651},{139,10,985},{135,10,1861},{4,0,348},{152,11,3},{5,11,986},{6,11,130},{7,\n11,1582},{8,11,458},{10,11,101},{10,11,318},{138,11,823},{134,0,758},{4,0,298},{\n137,0,848},{4,10,330},{7,10,933},{7,10,2012},{136,10,292},{7,11,1644},{137,11,\n129},{6,0,1422},{7,10,767},{137,0,829},{5,0,164},{7,0,121},{142,0,189},{7,0,812}\n,{7,0,1261},{7,0,1360},{9,0,632},{140,0,352},{135,11,1788},{139,0,556},{135,11,\n997},{145,10,114},{4,0,172},{9,0,611},{9,10,883},{10,0,436},{12,0,673},{141,0,\n255},{10,10,274},{139,0,530},{133,0,844},{134,0,984},{4,10,703},{7,10,207},{13,0\n,232},{146,0,35},{132,10,571},{9,0,263},{10,0,147},{138,0,492},{7,11,1756},{137,\n11,98},{5,10,873},{5,10,960},{8,10,823},{137,10,881},{133,0,537},{132,0,859},{7,\n11,1046},{139,11,160},{137,0,842},{139,10,283},{5,10,33},{6,10,470},{139,10,424}\n,{6,11,45},{7,11,433},{8,11,129},{9,11,21},{10,11,392},{11,11,79},{12,11,499},{\n13,11,199},{141,11,451},{135,0,1291},{135,10,1882},{7,11,558},{136,11,353},{134,\n0,1482},{5,0,230},{5,0,392},{6,0,420},{9,0,568},{140,0,612},{6,0,262},{7,10,90},\n{7,10,664},{7,10,830},{7,10,1380},{7,10,2025},{8,10,448},{8,10,828},{8,11,81},{9\n,11,189},{9,11,201},{11,11,478},{11,11,712},{141,11,338},{142,0,31},{5,11,353},{\n151,11,26},{132,0,753},{4,0,0},{5,0,41},{7,0,1459},{7,0,1469},{7,0,1859},{9,0,\n549},{139,0,905},{9,10,417},{137,10,493},{135,11,1113},{133,0,696},{141,11,448},\n{134,10,295},{132,0,834},{4,0,771},{5,10,1019},{6,11,25},{7,11,855},{7,11,1258},\n{144,11,32},{134,0,1076},{133,0,921},{133,0,674},{4,11,4},{7,11,1118},{7,11,1320\n},{7,11,1706},{8,11,277},{9,11,622},{10,11,9},{11,11,724},{12,11,350},{12,11,397\n},{13,11,28},{13,11,159},{15,11,89},{18,11,5},{19,11,9},{20,11,34},{150,11,47},{\n134,10,208},{6,0,444},{136,0,308},{6,0,180},{7,0,1137},{8,0,751},{139,0,805},{4,\n0,183},{7,0,271},{11,0,824},{11,0,952},{13,0,278},{13,0,339},{13,0,482},{14,0,\n424},{148,0,99},{7,11,317},{135,11,569},{4,0,19},{5,0,477},{5,0,596},{6,0,505},{\n7,0,1221},{11,0,907},{12,0,209},{141,0,214},{135,0,1215},{6,0,271},{7,0,398},{7,\n10,448},{7,10,1629},{7,10,1813},{8,0,387},{8,10,442},{9,10,710},{10,0,344},{10,\n10,282},{138,10,722},{11,10,844},{12,10,104},{140,10,625},{134,11,255},{133,10,\n787},{134,0,1645},{11,11,956},{151,11,3},{6,0,92},{6,0,188},{7,0,209},{7,0,1269}\n,{7,0,1524},{7,0,1876},{8,0,661},{10,0,42},{10,0,228},{11,0,58},{11,0,1020},{12,\n0,58},{12,0,118},{141,0,32},{4,0,459},{133,0,966},{4,11,536},{7,11,1141},{10,11,\n723},{139,11,371},{140,0,330},{134,0,1557},{7,11,285},{135,11,876},{136,10,491},\n{135,11,560},{6,0,18},{7,0,179},{7,0,932},{8,0,548},{8,0,757},{9,0,54},{9,0,65},\n{9,0,532},{9,0,844},{10,0,113},{10,0,117},{10,0,315},{10,0,560},{10,0,622},{10,0\n,798},{11,0,153},{11,0,351},{11,0,375},{12,0,78},{12,0,151},{12,0,392},{12,0,666\n},{14,0,248},{143,0,23},{4,11,690},{134,0,1742},{4,10,403},{5,10,441},{7,10,450}\n,{10,10,840},{11,10,101},{12,10,193},{141,10,430},{133,0,965},{134,0,182},{10,0,\n65},{10,0,488},{138,0,497},{135,11,1346},{6,0,973},{6,0,1158},{10,11,200},{19,11\n,2},{151,11,22},{4,11,190},{133,11,554},{133,10,679},{7,0,328},{137,10,326},{133\n,11,1001},{9,0,588},{138,0,260},{133,11,446},{135,10,1128},{135,10,1796},{147,11\n,119},{134,0,1786},{6,0,1328},{6,0,1985},{8,0,962},{138,0,1017},{135,0,308},{4,\n10,574},{7,10,350},{7,10,1024},{8,10,338},{9,10,677},{10,10,808},{139,0,508},{\n138,11,752},{135,10,1081},{137,11,96},{7,10,1676},{135,10,2037},{136,0,588},{132\n,11,304},{133,0,614},{140,0,793},{136,0,287},{137,10,297},{141,10,37},{6,11,53},\n{6,11,199},{7,11,1408},{8,11,32},{8,11,93},{9,11,437},{10,11,397},{10,11,629},{\n11,11,593},{11,11,763},{13,11,326},{145,11,35},{134,11,105},{9,11,320},{10,11,\n506},{138,11,794},{5,11,114},{5,11,255},{141,11,285},{140,0,290},{7,11,2035},{8,\n11,19},{9,11,89},{138,11,831},{134,0,1136},{6,10,306},{7,0,719},{7,10,1140},{7,\n10,1340},{8,0,796},{8,0,809},{8,0,834},{8,10,133},{138,10,449},{139,10,1011},{5,\n0,210},{6,0,213},{7,0,60},{10,0,364},{139,0,135},{5,0,607},{8,0,326},{136,0,490}\n,{138,11,176},{132,0,701},{5,0,472},{7,0,380},{137,0,758},{135,0,1947},{6,0,1079\n},{138,0,278},{138,11,391},{5,10,329},{8,10,260},{139,11,156},{4,0,386},{7,0,41}\n,{8,0,405},{8,0,728},{9,0,497},{11,0,110},{11,0,360},{15,0,37},{144,0,84},{5,0,\n46},{7,0,1452},{7,0,1480},{8,0,634},{140,0,472},{136,0,961},{4,0,524},{136,0,810\n},{10,0,238},{141,0,33},{132,10,657},{152,10,7},{133,0,532},{5,0,997},{135,10,\n1665},{7,11,594},{7,11,851},{7,11,1858},{9,11,411},{9,11,574},{9,11,666},{9,11,\n737},{10,11,346},{10,11,712},{11,11,246},{11,11,432},{11,11,517},{11,11,647},{11\n,11,679},{11,11,727},{12,11,304},{12,11,305},{12,11,323},{12,11,483},{12,11,572}\n,{12,11,593},{12,11,602},{13,11,95},{13,11,101},{13,11,171},{13,11,315},{13,11,\n378},{13,11,425},{13,11,475},{14,11,63},{14,11,380},{14,11,384},{15,11,133},{18,\n11,112},{148,11,72},{5,11,955},{136,11,814},{134,0,1301},{5,10,66},{7,10,1896},{\n136,10,288},{133,11,56},{134,10,1643},{6,0,1298},{148,11,100},{5,0,782},{5,0,829\n},{6,0,671},{6,0,1156},{6,0,1738},{137,11,621},{4,0,306},{5,0,570},{5,10,91},{5,\n10,648},{5,10,750},{5,10,781},{6,10,54},{6,10,112},{6,10,402},{6,10,1732},{7,0,\n1347},{7,10,315},{7,10,749},{7,10,1900},{9,10,78},{9,10,508},{10,10,611},{10,10,\n811},{11,10,510},{11,10,728},{13,10,36},{14,10,39},{16,10,83},{17,10,124},{148,\n10,30},{8,10,570},{9,11,477},{141,11,78},{4,11,639},{10,10,322},{10,10,719},{10,\n11,4},{11,10,407},{11,11,638},{12,11,177},{148,11,57},{7,0,1823},{139,0,693},{5,\n11,758},{7,0,759},{8,10,125},{8,10,369},{8,10,524},{10,10,486},{11,10,13},{11,10\n,381},{11,10,736},{11,10,766},{11,10,845},{13,10,114},{13,10,292},{142,10,47},{6\n,10,1684},{6,10,1731},{7,0,1932},{7,10,356},{8,10,54},{8,10,221},{9,10,225},{9,\n10,356},{10,10,77},{10,10,446},{10,10,731},{12,10,404},{141,10,491},{135,11,552}\n,{135,11,1112},{4,0,78},{5,0,96},{5,0,182},{6,0,1257},{7,0,1724},{7,0,1825},{10,\n0,394},{10,0,471},{11,0,532},{14,0,340},{145,0,88},{139,11,328},{135,0,1964},{\n132,10,411},{4,10,80},{5,10,44},{137,11,133},{5,11,110},{6,11,169},{6,11,1702},{\n7,11,400},{8,11,538},{9,11,184},{9,11,524},{140,11,218},{4,0,521},{5,10,299},{7,\n10,1083},{140,11,554},{6,11,133},{9,11,353},{12,11,628},{146,11,79},{6,0,215},{7\n,0,584},{7,0,1028},{7,0,1473},{7,0,1721},{9,0,424},{138,0,779},{7,0,857},{7,0,\n1209},{7,10,1713},{9,10,537},{10,10,165},{12,10,219},{140,10,561},{4,10,219},{6,\n11,93},{7,10,1761},{7,11,1422},{7,11,1851},{8,11,673},{9,10,86},{9,11,529},{140,\n11,43},{137,11,371},{136,0,671},{5,0,328},{135,0,918},{132,0,529},{9,11,25},{10,\n11,467},{138,11,559},{4,11,335},{135,11,942},{134,0,716},{134,0,1509},{6,0,67},{\n7,0,258},{7,0,1630},{9,0,354},{9,0,675},{10,0,830},{12,10,428},{14,0,80},{145,0,\n80},{134,0,1112},{6,0,141},{7,0,225},{9,0,59},{9,0,607},{10,0,312},{11,0,687},{\n12,0,555},{13,0,373},{13,0,494},{148,0,58},{133,10,514},{8,11,39},{10,11,773},{\n11,11,84},{12,11,205},{142,11,1},{5,11,601},{5,11,870},{136,0,783},{136,11,594},\n{4,10,55},{5,10,301},{6,10,571},{14,10,49},{146,10,102},{132,11,181},{134,11,\n1652},{133,10,364},{4,11,97},{5,11,147},{6,11,286},{7,11,1362},{141,11,176},{4,\n10,76},{7,10,1550},{9,10,306},{9,10,430},{9,10,663},{10,10,683},{11,10,427},{11,\n10,753},{12,10,334},{12,10,442},{14,10,258},{14,10,366},{143,10,131},{137,10,52}\n,{6,0,955},{134,0,1498},{6,11,375},{7,11,169},{7,11,254},{136,11,780},{7,0,430},\n{11,0,46},{14,0,343},{142,11,343},{135,0,1183},{5,0,602},{7,0,2018},{7,11,1447},\n{9,0,418},{137,0,803},{7,11,1044},{136,0,677},{139,11,285},{4,10,656},{135,10,\n779},{135,10,144},{5,11,629},{135,11,1549},{135,10,1373},{138,11,209},{7,10,554}\n,{7,10,605},{141,10,10},{5,10,838},{5,10,841},{134,10,1649},{133,10,1012},{6,0,\n1357},{134,0,1380},{144,0,53},{6,0,590},{7,10,365},{7,10,1357},{7,10,1497},{8,10\n,154},{141,10,281},{133,10,340},{132,11,420},{135,0,329},{147,11,32},{4,0,469},{\n10,11,429},{139,10,495},{8,10,261},{9,10,144},{9,10,466},{10,10,370},{12,10,470}\n,{13,10,144},{142,10,348},{142,0,460},{4,11,325},{9,10,897},{138,11,125},{6,0,\n1743},{6,10,248},{9,10,546},{10,10,535},{11,10,681},{141,10,135},{4,0,990},{5,0,\n929},{6,0,340},{8,0,376},{8,0,807},{8,0,963},{8,0,980},{138,0,1007},{134,0,1603}\n,{140,0,250},{4,11,714},{133,11,469},{134,10,567},{136,10,445},{5,0,218},{7,0,\n1610},{8,0,646},{10,0,83},{11,11,138},{140,11,40},{7,0,1512},{135,0,1794},{135,\n11,1216},{4,11,718},{11,0,0},{144,0,78},{133,0,571},{132,0,455},{134,0,1012},{5,\n11,124},{5,11,144},{6,11,548},{7,11,15},{7,11,153},{137,11,629},{142,11,10},{6,\n11,75},{7,11,1531},{8,11,416},{9,11,240},{9,11,275},{10,11,100},{11,11,658},{11,\n11,979},{12,11,86},{13,11,468},{14,11,66},{14,11,207},{15,11,20},{15,11,25},{144\n,11,58},{132,10,577},{5,11,141},{5,11,915},{6,11,1783},{7,11,211},{7,11,698},{7,\n11,1353},{9,11,83},{9,11,281},{10,11,376},{10,11,431},{11,11,543},{12,11,664},{\n13,11,280},{13,11,428},{14,11,61},{14,11,128},{17,11,52},{145,11,81},{6,0,161},{\n7,0,372},{137,0,597},{132,0,349},{10,11,702},{139,11,245},{134,0,524},{134,10,\n174},{6,0,432},{9,0,751},{139,0,322},{147,11,94},{4,11,338},{133,11,400},{5,0,\n468},{10,0,325},{11,0,856},{12,0,345},{143,0,104},{133,0,223},{132,0,566},{4,11,\n221},{5,11,659},{5,11,989},{7,11,697},{7,11,1211},{138,11,284},{135,11,1070},{4,\n0,59},{135,0,1394},{5,10,878},{5,10,972},{6,0,436},{139,0,481},{4,0,48},{5,0,271\n},{135,0,953},{5,0,610},{136,0,457},{4,0,773},{5,0,618},{137,0,756},{133,0,755},\n{135,0,1217},{138,11,507},{132,10,351},{132,0,197},{143,11,78},{4,11,188},{7,11,\n805},{11,11,276},{142,11,293},{5,11,884},{139,11,991},{132,10,286},{7,10,438},{7\n,10,627},{7,10,1516},{8,10,40},{9,10,56},{9,10,294},{10,0,259},{10,0,428},{11,10\n,969},{11,10,995},{146,10,148},{4,0,356},{5,0,217},{5,0,492},{5,0,656},{8,0,544}\n,{136,11,544},{5,0,259},{6,0,1230},{7,0,414},{7,0,854},{142,0,107},{132,0,1007},\n{15,0,14},{144,0,5},{4,10,738},{134,0,1580},{132,11,596},{132,0,673},{133,10,866\n},{6,0,1843},{135,11,1847},{4,0,165},{7,0,1398},{135,0,1829},{135,11,1634},{147,\n11,65},{6,0,885},{6,0,1009},{137,0,809},{133,10,116},{132,10,457},{136,11,770},{\n9,0,498},{10,11,361},{12,0,181},{142,11,316},{134,11,595},{5,0,9},{7,0,297},{7,0\n,966},{140,0,306},{4,11,89},{5,11,489},{6,11,315},{7,11,553},{7,11,1745},{138,11\n,243},{134,0,1487},{132,0,437},{5,0,146},{6,0,411},{138,0,721},{5,10,527},{6,10,\n189},{135,10,859},{11,10,104},{11,10,554},{15,10,60},{143,10,125},{6,11,1658},{9\n,11,3},{10,11,154},{11,11,641},{13,11,85},{13,11,201},{141,11,346},{6,0,177},{\n135,0,467},{134,0,1377},{134,10,116},{136,11,645},{4,11,166},{5,11,505},{6,11,\n1670},{137,11,110},{133,10,487},{4,10,86},{5,10,667},{5,10,753},{6,10,316},{6,10\n,455},{135,10,946},{133,0,200},{132,0,959},{6,0,1928},{134,0,1957},{139,11,203},\n{150,10,45},{4,10,79},{7,10,1773},{10,10,450},{11,10,589},{13,10,332},{13,10,493\n},{14,10,183},{14,10,334},{14,10,362},{14,10,368},{14,10,376},{14,10,379},{19,10\n,90},{19,10,103},{19,10,127},{148,10,90},{6,0,1435},{135,11,1275},{134,0,481},{7\n,11,445},{8,11,307},{8,11,704},{10,11,41},{10,11,439},{11,11,237},{11,11,622},{\n140,11,201},{135,11,869},{4,0,84},{7,0,1482},{10,0,76},{138,0,142},{11,11,277},{\n144,11,14},{135,11,1977},{4,11,189},{5,11,713},{136,11,57},{133,0,1015},{138,11,\n371},{4,0,315},{5,0,507},{135,0,1370},{4,11,552},{142,10,381},{9,0,759},{16,0,31\n},{16,0,39},{16,0,75},{18,0,24},{20,0,42},{152,0,1},{134,0,712},{134,0,1722},{\n133,10,663},{133,10,846},{8,0,222},{8,0,476},{9,0,238},{11,0,516},{11,0,575},{15\n,0,109},{146,0,100},{5,10,378},{7,0,1402},{7,0,1414},{8,10,465},{9,10,286},{10,\n10,185},{10,10,562},{10,10,635},{11,10,31},{11,10,393},{12,0,456},{13,10,312},{\n18,10,65},{18,10,96},{147,10,89},{4,0,986},{6,0,1958},{6,0,2032},{8,0,934},{138,\n0,985},{7,10,1880},{9,10,680},{139,10,798},{134,10,1770},{145,11,49},{132,11,614\n},{132,10,648},{5,10,945},{6,10,1656},{6,10,1787},{7,10,167},{8,10,824},{9,10,\n391},{10,10,375},{139,10,185},{138,11,661},{7,0,1273},{135,11,1945},{7,0,706},{7\n,0,1058},{138,0,538},{7,10,1645},{8,10,352},{137,10,249},{132,10,152},{11,0,92},\n{11,0,196},{11,0,409},{11,0,450},{11,0,666},{11,0,777},{12,0,262},{13,0,385},{13\n,0,393},{15,0,115},{16,0,45},{145,0,82},{133,10,1006},{6,0,40},{135,0,1781},{9,\n11,614},{139,11,327},{5,10,420},{135,10,1449},{135,0,431},{7,10,832},{138,0,97},\n{6,0,423},{7,0,665},{135,0,1210},{7,0,237},{8,0,664},{9,0,42},{9,0,266},{9,0,380\n},{9,0,645},{10,0,177},{138,0,276},{5,10,351},{135,0,264},{5,10,40},{7,10,598},{\n7,10,1638},{8,0,213},{9,10,166},{9,10,640},{9,10,685},{9,10,773},{11,10,215},{13\n,10,65},{14,10,172},{14,10,317},{145,10,6},{5,11,84},{134,11,163},{8,10,60},{9,\n10,343},{139,10,769},{137,0,455},{133,11,410},{8,0,906},{12,0,700},{12,0,706},{\n140,0,729},{21,11,33},{150,11,40},{7,10,1951},{8,10,765},{8,10,772},{140,10,671}\n,{7,10,108},{8,10,219},{8,10,388},{9,10,639},{9,10,775},{11,10,275},{140,10,464}\n,{5,11,322},{7,11,1941},{8,11,186},{9,11,262},{10,11,187},{14,11,208},{146,11,\n130},{139,0,624},{5,11,227},{8,0,574},{140,11,29},{7,11,1546},{11,11,299},{142,\n11,407},{5,10,15},{6,10,56},{7,10,1758},{8,10,500},{9,10,730},{11,10,331},{13,10\n,150},{142,10,282},{7,11,1395},{8,11,486},{9,11,236},{9,11,878},{10,11,218},{11,\n11,95},{19,11,17},{147,11,31},{135,11,2043},{4,0,354},{146,11,4},{140,11,80},{\n135,0,1558},{134,10,1886},{5,10,205},{6,10,438},{137,10,711},{133,11,522},{133,\n10,534},{7,0,235},{7,0,1475},{15,0,68},{146,0,120},{137,10,691},{4,0,942},{6,0,\n1813},{8,0,917},{10,0,884},{12,0,696},{12,0,717},{12,0,723},{12,0,738},{12,0,749\n},{12,0,780},{16,0,97},{146,0,169},{6,10,443},{8,11,562},{9,10,237},{9,10,571},{\n9,10,695},{10,10,139},{11,10,715},{12,10,417},{141,10,421},{135,0,957},{133,0,\n830},{134,11,1771},{146,0,23},{5,0,496},{6,0,694},{7,0,203},{7,11,1190},{137,11,\n620},{137,11,132},{6,0,547},{134,0,1549},{8,11,258},{9,11,208},{137,11,359},{4,0\n,864},{5,0,88},{137,0,239},{135,11,493},{4,11,317},{135,11,1279},{132,11,477},{4\n,10,578},{5,11,63},{133,11,509},{7,0,650},{135,0,1310},{7,0,1076},{9,0,80},{11,0\n,78},{11,0,421},{11,0,534},{140,0,545},{132,11,288},{5,10,923},{12,0,553},{142,0\n,118},{7,0,274},{11,0,479},{139,0,507},{8,11,89},{8,11,620},{9,11,49},{10,11,774\n},{11,11,628},{12,11,322},{143,11,124},{4,0,497},{135,0,1584},{4,10,924},{7,0,\n261},{7,0,1115},{7,0,1354},{7,0,1404},{7,0,1588},{7,0,1705},{7,0,1902},{9,0,465}\n,{10,0,248},{10,0,349},{10,0,647},{11,0,527},{11,0,660},{11,0,669},{12,0,529},{\n141,0,305},{133,10,665},{136,0,13},{6,0,791},{138,11,120},{7,0,642},{8,0,250},{\n11,0,123},{11,0,137},{13,0,48},{142,0,95},{4,10,265},{7,10,807},{135,10,950},{5,\n10,93},{140,10,267},{135,0,1429},{4,0,949},{10,0,885},{10,0,891},{10,0,900},{10,\n0,939},{12,0,760},{142,0,449},{139,11,366},{132,0,818},{134,11,85},{135,10,994},\n{5,10,233},{5,10,320},{6,10,140},{7,0,330},{136,10,295},{4,0,1004},{8,0,982},{\n136,0,993},{133,10,978},{4,10,905},{6,10,1701},{137,10,843},{10,0,545},{140,0,\n301},{6,0,947},{134,0,1062},{134,0,1188},{4,0,904},{5,0,794},{152,10,6},{134,0,\n1372},{135,11,608},{5,11,279},{6,11,235},{7,11,468},{8,11,446},{9,11,637},{10,11\n,717},{11,11,738},{140,11,514},{132,10,509},{5,11,17},{6,11,371},{137,11,528},{\n132,0,693},{4,11,115},{5,11,669},{6,11,407},{8,11,311},{11,11,10},{141,11,5},{7,\n10,273},{9,11,381},{139,0,377},{135,0,695},{7,0,386},{138,0,713},{135,10,1041},{\n134,0,1291},{6,0,7},{6,0,35},{7,0,147},{7,0,1069},{7,0,1568},{7,0,1575},{7,0,\n1917},{8,0,43},{8,0,208},{9,0,128},{9,0,866},{10,0,20},{11,0,981},{147,0,33},{7,\n0,893},{141,0,424},{139,10,234},{150,11,56},{5,11,779},{5,11,807},{6,11,1655},{\n134,11,1676},{5,10,802},{7,10,2021},{136,10,805},{4,11,196},{5,10,167},{5,10,899\n},{5,11,558},{5,11,949},{6,10,410},{137,10,777},{137,10,789},{134,10,1705},{8,0,\n904},{140,0,787},{6,0,322},{9,0,552},{11,0,274},{13,0,209},{13,0,499},{14,0,85},\n{15,0,126},{145,0,70},{135,10,10},{5,10,11},{6,10,117},{6,10,485},{7,10,1133},{9\n,10,582},{9,10,594},{11,10,21},{11,10,818},{12,10,535},{141,10,86},{4,10,264},{7\n,10,1067},{8,10,204},{8,10,385},{139,10,953},{132,11,752},{138,10,56},{133,10,\n470},{6,0,1808},{8,0,83},{8,0,742},{8,0,817},{9,0,28},{9,0,29},{9,0,885},{10,0,\n387},{11,0,633},{11,0,740},{13,0,235},{13,0,254},{15,0,143},{143,0,146},{140,0,\n49},{134,0,1832},{4,11,227},{5,11,159},{5,11,409},{7,11,80},{10,11,294},{10,11,\n479},{12,11,418},{14,11,50},{14,11,249},{142,11,295},{7,11,1470},{8,11,66},{8,11\n,137},{8,11,761},{9,11,638},{11,11,80},{11,11,212},{11,11,368},{11,11,418},{12,\n11,8},{13,11,15},{16,11,61},{17,11,59},{19,11,28},{148,11,84},{139,10,1015},{138\n,11,468},{135,0,421},{6,0,415},{7,0,1049},{137,0,442},{6,11,38},{7,11,1220},{8,\n11,185},{8,11,256},{9,11,22},{9,11,331},{10,11,738},{11,11,205},{11,11,540},{11,\n11,746},{13,11,399},{13,11,465},{14,11,88},{142,11,194},{139,0,289},{133,10,715}\n,{4,0,110},{10,0,415},{10,0,597},{142,0,206},{4,11,159},{6,11,115},{7,11,252},{7\n,11,257},{7,11,1928},{8,11,69},{9,11,384},{10,11,91},{10,11,615},{12,11,375},{14\n,11,235},{18,11,117},{147,11,123},{5,11,911},{136,11,278},{7,0,205},{7,0,2000},{\n8,10,794},{9,10,400},{10,10,298},{142,10,228},{135,11,1774},{4,11,151},{7,11,\n1567},{8,11,351},{137,11,322},{136,10,724},{133,11,990},{7,0,1539},{7,11,1539},{\n11,0,512},{13,0,205},{19,0,30},{22,0,36},{151,0,19},{5,11,194},{7,11,1662},{9,11\n,90},{140,11,180},{6,10,190},{7,10,768},{135,10,1170},{134,0,1340},{4,0,283},{\n135,0,1194},{133,11,425},{133,11,971},{12,0,549},{14,10,67},{147,10,60},{135,10,\n1023},{134,0,1720},{138,11,587},{5,11,72},{6,11,264},{7,11,21},{7,11,46},{7,11,\n2013},{8,11,215},{8,11,513},{10,11,266},{139,11,22},{5,0,319},{135,0,534},{6,10,\n137},{9,10,75},{9,10,253},{10,10,194},{138,10,444},{6,11,239},{7,0,1180},{7,11,\n118},{10,11,95},{11,11,603},{13,11,443},{14,11,160},{15,11,4},{148,0,112},{134,\n11,431},{5,11,874},{6,11,1677},{11,10,643},{12,10,115},{143,11,0},{134,0,967},{6\n,11,65},{7,11,939},{7,11,1172},{7,11,1671},{9,11,540},{10,11,696},{11,11,265},{\n11,11,732},{11,11,928},{11,11,937},{12,11,399},{13,11,438},{149,11,19},{137,11,\n200},{135,0,1940},{5,10,760},{7,10,542},{8,10,135},{136,10,496},{140,11,44},{7,\n11,1655},{136,11,305},{7,10,319},{7,10,355},{7,10,763},{10,10,389},{145,10,43},{\n136,0,735},{138,10,786},{137,11,19},{132,11,696},{5,0,132},{9,0,486},{9,0,715},{\n10,0,458},{11,0,373},{11,0,668},{11,0,795},{11,0,897},{12,0,272},{12,0,424},{12,\n0,539},{12,0,558},{14,0,245},{14,0,263},{14,0,264},{14,0,393},{142,0,403},{10,0,\n38},{139,0,784},{132,0,838},{4,11,302},{135,11,1766},{133,0,379},{4,11,726},{5,0\n,8},{5,11,630},{6,0,89},{6,0,400},{7,0,1569},{7,0,1623},{7,0,1850},{8,0,218},{8,\n0,422},{9,0,570},{138,0,626},{4,0,1017},{138,0,660},{6,0,387},{7,0,882},{141,0,\n111},{6,0,224},{7,0,877},{137,0,647},{4,10,58},{5,10,286},{6,10,319},{7,10,402},\n{7,10,1254},{7,10,1903},{8,10,356},{140,10,408},{135,0,790},{4,10,389},{9,0,510}\n,{9,10,181},{10,0,53},{10,10,29},{10,10,816},{11,10,311},{11,10,561},{12,10,67},\n{141,10,181},{142,0,458},{6,11,118},{7,11,215},{7,11,1521},{140,11,11},{134,0,\n954},{135,0,394},{134,0,1367},{5,10,373},{133,11,225},{132,0,882},{7,0,1409},{\n135,10,1972},{135,10,1793},{4,11,370},{5,11,756},{135,11,1326},{150,11,13},{7,11\n,354},{10,11,410},{139,11,815},{6,11,1662},{7,11,48},{8,11,771},{10,11,116},{13,\n11,104},{14,11,105},{14,11,184},{15,11,168},{19,11,92},{148,11,68},{7,0,124},{\n136,0,38},{5,0,261},{7,0,78},{7,0,199},{8,0,815},{9,0,126},{10,0,342},{140,0,647\n},{4,0,628},{140,0,724},{7,0,266},{7,10,1651},{8,0,804},{145,10,89},{135,0,208},\n{134,0,1178},{6,0,79},{135,0,1519},{132,10,672},{133,10,737},{136,0,741},{132,11\n,120},{4,0,710},{6,0,376},{134,0,606},{134,0,1347},{134,0,1494},{6,0,850},{6,0,\n1553},{137,0,821},{5,10,145},{134,11,593},{7,0,1311},{140,0,135},{4,0,467},{5,0,\n405},{134,0,544},{5,11,820},{135,11,931},{6,0,100},{7,0,244},{7,0,632},{7,0,1609\n},{8,0,178},{8,0,638},{141,0,58},{4,10,387},{135,10,1288},{6,11,151},{6,11,1675}\n,{7,11,383},{151,11,10},{132,0,481},{135,10,550},{134,0,1378},{6,11,1624},{11,11\n,11},{12,11,422},{13,11,262},{142,11,360},{133,0,791},{4,11,43},{5,11,344},{133,\n11,357},{7,0,1227},{140,0,978},{7,0,686},{8,0,33},{8,0,238},{10,0,616},{11,0,467\n},{11,0,881},{13,0,217},{13,0,253},{142,0,268},{137,0,857},{7,11,148},{8,0,467},\n{8,0,1006},{8,11,284},{141,11,63},{4,10,576},{135,10,1263},{133,11,888},{5,10,\n919},{134,10,1673},{20,10,37},{148,11,37},{132,0,447},{132,11,711},{4,0,128},{5,\n0,415},{6,0,462},{7,0,294},{7,0,578},{10,0,710},{139,0,86},{4,10,82},{5,10,333},\n{5,10,904},{6,10,207},{7,10,325},{7,10,1726},{8,10,101},{10,10,778},{139,10,220}\n,{136,0,587},{137,11,440},{133,10,903},{6,0,427},{7,0,1018},{138,0,692},{4,0,195\n},{135,0,802},{140,10,147},{134,0,1546},{134,0,684},{132,10,705},{136,0,345},{11\n,11,678},{140,11,307},{133,0,365},{134,0,1683},{4,11,65},{5,11,479},{5,11,1004},\n{7,11,1913},{8,11,317},{9,11,302},{10,11,612},{141,11,22},{138,0,472},{4,11,261}\n,{135,11,510},{134,10,90},{142,0,433},{151,0,28},{4,11,291},{7,11,101},{9,11,515\n},{12,11,152},{12,11,443},{13,11,392},{142,11,357},{140,0,997},{5,0,3},{8,0,578}\n,{9,0,118},{10,0,705},{141,0,279},{135,11,1266},{7,10,813},{12,10,497},{141,10,\n56},{133,0,229},{6,10,125},{135,10,1277},{8,0,102},{10,0,578},{10,0,672},{12,0,\n496},{13,0,408},{14,0,121},{17,0,106},{151,10,12},{6,0,866},{134,0,1080},{136,0,\n1022},{4,11,130},{135,11,843},{5,11,42},{5,11,879},{7,11,245},{7,11,324},{7,11,\n1532},{11,11,463},{11,11,472},{13,11,363},{144,11,52},{150,0,55},{4,11,134},{5,\n11,372},{8,0,115},{8,0,350},{9,0,489},{10,0,128},{11,0,306},{12,0,373},{14,0,30}\n,{17,0,79},{147,0,80},{134,0,657},{134,0,933},{135,11,1147},{4,0,230},{133,0,702\n},{134,0,1728},{4,0,484},{18,0,26},{19,0,42},{20,0,43},{21,0,0},{23,0,27},{152,0\n,14},{7,0,185},{135,0,703},{6,0,417},{7,10,1106},{9,10,770},{10,0,618},{11,10,\n112},{140,10,413},{134,0,803},{132,11,644},{134,0,1262},{7,11,540},{12,10,271},{\n145,10,109},{135,11,123},{132,0,633},{134,11,623},{4,11,908},{5,11,359},{5,11,\n508},{6,11,1723},{7,11,343},{7,11,1996},{135,11,2026},{135,0,479},{7,10,304},{9,\n10,646},{9,10,862},{10,0,262},{11,10,696},{12,10,208},{15,10,79},{147,10,108},{4\n,11,341},{135,11,480},{134,0,830},{5,0,70},{5,0,622},{6,0,334},{7,0,1032},{9,0,\n171},{11,0,26},{11,0,213},{11,0,637},{11,0,707},{12,0,202},{12,0,380},{13,0,226}\n,{13,0,355},{14,0,222},{145,0,42},{135,10,981},{143,0,217},{137,11,114},{4,0,23}\n,{4,0,141},{5,0,313},{5,0,1014},{6,0,50},{6,0,51},{7,0,142},{7,0,384},{7,0,559},\n{8,0,640},{9,0,460},{9,0,783},{11,0,741},{12,0,183},{141,0,488},{141,0,360},{7,0\n,1586},{7,11,1995},{8,11,299},{11,11,890},{140,11,674},{132,10,434},{6,10,550},{\n135,0,652},{5,10,553},{7,0,766},{138,10,824},{7,0,737},{8,0,298},{136,10,452},{4\n,11,238},{5,11,503},{6,11,179},{7,11,2003},{8,11,381},{8,11,473},{9,11,149},{10,\n11,183},{15,11,45},{143,11,86},{133,10,292},{5,0,222},{9,0,655},{138,0,534},{138\n,10,135},{4,11,121},{5,11,156},{5,11,349},{9,11,136},{10,11,605},{14,11,342},{\n147,11,107},{137,0,906},{6,0,1013},{134,0,1250},{6,0,1956},{6,0,2009},{8,0,991},\n{144,0,120},{135,11,1192},{138,0,503},{5,0,154},{7,0,1491},{10,0,379},{138,0,485\n},{6,0,1867},{6,0,1914},{6,0,1925},{9,0,917},{9,0,925},{9,0,932},{9,0,951},{9,0,\n1007},{9,0,1013},{12,0,806},{12,0,810},{12,0,814},{12,0,816},{12,0,824},{12,0,\n832},{12,0,837},{12,0,863},{12,0,868},{12,0,870},{12,0,889},{12,0,892},{12,0,900\n},{12,0,902},{12,0,908},{12,0,933},{12,0,942},{12,0,949},{12,0,954},{15,0,175},{\n15,0,203},{15,0,213},{15,0,218},{15,0,225},{15,0,231},{15,0,239},{15,0,248},{15,\n0,252},{18,0,190},{18,0,204},{18,0,215},{18,0,216},{18,0,222},{18,0,225},{18,0,\n230},{18,0,239},{18,0,241},{21,0,42},{21,0,43},{21,0,44},{21,0,45},{21,0,46},{21\n,0,53},{24,0,27},{152,0,31},{133,0,716},{135,0,844},{4,0,91},{5,0,388},{5,0,845}\n,{6,0,206},{6,0,252},{6,0,365},{7,0,136},{7,0,531},{136,0,621},{7,10,393},{10,10\n,603},{139,10,206},{6,11,80},{6,11,1694},{7,11,173},{7,11,1974},{9,11,547},{10,\n11,730},{14,11,18},{150,11,39},{137,0,748},{4,11,923},{134,11,1711},{4,10,912},{\n137,10,232},{7,10,98},{7,10,1973},{136,10,716},{5,10,733},{142,0,103},{132,11,\n595},{5,11,240},{6,11,459},{7,11,12},{7,11,114},{7,11,502},{7,11,1751},{7,11,\n1753},{7,11,1805},{8,11,658},{9,11,1},{11,11,959},{12,0,158},{13,11,446},{14,11,\n211},{18,0,8},{19,0,62},{20,0,6},{22,0,4},{23,0,2},{151,0,9},{135,0,576},{5,0,\n771},{5,0,863},{5,0,898},{6,0,648},{6,0,1632},{6,0,1644},{134,0,1780},{133,0,331\n},{7,11,633},{7,11,905},{7,11,909},{7,11,1538},{9,11,767},{140,11,636},{140,0,\n632},{5,0,107},{7,0,201},{136,0,518},{6,0,446},{6,11,490},{135,0,1817},{9,0,851}\n,{141,0,510},{7,11,250},{8,11,506},{136,11,507},{4,0,504},{137,10,72},{132,11,\n158},{4,11,140},{7,11,362},{8,11,209},{9,11,10},{9,11,160},{9,11,503},{10,11,689\n},{11,11,350},{11,11,553},{11,11,725},{12,11,252},{12,11,583},{13,11,192},{13,11\n,352},{14,11,269},{14,11,356},{148,11,50},{6,11,597},{135,11,1318},{135,10,1454}\n,{5,0,883},{5,0,975},{8,0,392},{148,0,7},{6,11,228},{7,11,1341},{9,11,408},{138,\n11,343},{11,10,600},{11,11,348},{12,11,99},{13,10,245},{18,11,1},{18,11,11},{147\n,11,4},{134,11,296},{5,0,922},{134,0,1707},{132,11,557},{4,11,548},{7,10,164},{7\n,10,1571},{9,10,107},{140,10,225},{7,11,197},{8,11,142},{8,11,325},{9,11,150},{9\n,11,596},{10,11,350},{10,11,353},{11,11,74},{11,11,315},{14,11,423},{143,11,141}\n,{5,0,993},{7,0,515},{137,0,91},{4,0,131},{5,10,484},{5,10,510},{6,10,434},{7,10\n,1000},{7,10,1098},{8,0,200},{136,10,2},{152,0,10},{4,11,62},{5,11,83},{6,11,399\n},{6,11,579},{7,11,692},{7,11,846},{7,11,1015},{7,11,1799},{8,11,403},{9,11,394}\n,{10,11,133},{12,11,4},{12,11,297},{12,11,452},{16,11,81},{18,11,19},{18,11,25},\n{21,11,14},{22,11,12},{151,11,18},{140,11,459},{132,11,177},{7,0,1433},{9,0,365}\n,{137,11,365},{132,10,460},{5,0,103},{5,11,411},{6,0,2004},{7,0,921},{7,11,653},\n{8,0,580},{8,0,593},{8,0,630},{138,0,28},{4,10,932},{133,10,891},{4,0,911},{5,0,\n867},{5,0,1013},{7,0,2034},{8,0,798},{136,0,813},{7,11,439},{10,11,727},{11,11,\n260},{139,11,684},{136,10,625},{5,11,208},{7,11,753},{135,11,1528},{5,0,461},{6,\n10,76},{7,0,1925},{12,0,39},{13,0,265},{141,0,439},{6,0,853},{8,10,92},{137,10,\n221},{5,0,135},{6,0,519},{7,0,1722},{10,0,271},{11,0,261},{145,0,54},{139,11,814\n},{14,0,338},{148,0,81},{4,0,300},{133,0,436},{5,0,419},{5,0,687},{7,0,864},{7,\n11,864},{137,0,470},{5,11,242},{137,0,836},{134,0,1937},{4,10,763},{133,11,953},\n{132,10,622},{132,0,393},{133,10,253},{7,10,546},{8,0,357},{10,0,745},{14,0,426}\n,{17,0,94},{147,0,57},{5,11,615},{146,11,37},{9,10,73},{10,10,110},{14,10,185},{\n145,10,119},{7,10,624},{7,10,916},{10,10,256},{11,0,703},{139,10,87},{133,11,290\n},{5,10,212},{12,10,35},{141,10,382},{132,11,380},{5,11,52},{7,11,277},{9,11,368\n},{139,11,791},{133,0,387},{10,11,138},{139,11,476},{4,0,6},{5,0,708},{136,0,75}\n,{7,0,1351},{9,0,581},{10,0,639},{11,0,453},{140,0,584},{132,0,303},{138,0,772},\n{135,10,1175},{4,0,749},{5,10,816},{6,11,256},{7,11,307},{7,11,999},{7,11,1481},\n{7,11,1732},{7,11,1738},{8,11,265},{9,11,414},{11,11,316},{12,11,52},{13,11,420}\n,{147,11,100},{135,11,1296},{5,10,869},{5,10,968},{6,0,1065},{6,10,1626},{8,10,\n734},{136,10,784},{4,10,542},{6,10,1716},{6,10,1727},{7,10,1082},{7,10,1545},{8,\n10,56},{8,10,118},{8,10,412},{8,10,564},{9,10,888},{9,10,908},{10,10,50},{10,10,\n423},{11,10,685},{11,10,697},{11,10,933},{12,10,299},{13,10,126},{13,10,136},{13\n,10,170},{141,10,190},{134,0,226},{4,0,106},{5,11,723},{7,0,310},{139,0,717},{4,\n10,232},{5,0,890},{5,0,988},{9,10,202},{10,10,474},{140,10,433},{6,0,626},{142,0\n,431},{10,0,706},{150,0,44},{6,10,108},{7,10,1003},{7,10,1181},{8,10,111},{8,10,\n343},{141,0,51},{132,0,698},{5,11,109},{6,11,1784},{7,11,1895},{12,11,296},{140,\n11,302},{134,0,828},{134,10,1712},{138,0,17},{4,10,133},{5,11,216},{7,0,1929},{7\n,10,711},{7,10,1298},{7,10,1585},{7,11,1879},{9,11,141},{9,11,270},{9,11,679},{\n10,11,159},{10,11,553},{11,11,197},{11,11,438},{12,11,538},{12,11,559},{13,11,\n193},{13,11,423},{14,11,144},{14,11,166},{14,11,167},{15,11,67},{147,11,84},{141\n,11,127},{7,11,1872},{137,11,81},{6,10,99},{7,10,1808},{145,10,57},{134,11,391},\n{5,0,689},{6,0,84},{6,10,574},{7,0,1250},{7,10,428},{10,10,669},{11,10,485},{11,\n10,840},{12,10,300},{142,10,250},{7,11,322},{136,11,249},{7,11,432},{135,11,1649\n},{135,10,1871},{137,10,252},{6,11,155},{140,11,234},{7,0,871},{19,0,27},{147,11\n,27},{140,0,498},{5,0,986},{6,0,130},{138,0,823},{6,0,1793},{6,10,323},{7,0,1582\n},{7,10,1564},{8,0,458},{10,0,101},{10,0,318},{10,0,945},{12,0,734},{16,0,104},{\n146,0,177},{5,11,632},{138,11,526},{7,10,461},{8,10,775},{138,0,435},{6,11,144},\n{7,11,948},{7,11,1042},{7,11,1857},{8,11,235},{8,11,461},{9,11,453},{9,11,530},{\n10,11,354},{17,11,77},{19,11,99},{148,11,79},{138,0,966},{7,0,1644},{137,0,129},\n{135,0,997},{136,0,502},{5,11,196},{6,11,486},{7,11,212},{8,11,309},{136,11,346}\n,{7,10,727},{146,10,73},{132,0,823},{132,11,686},{135,0,1927},{4,0,762},{7,0,\n1756},{137,0,98},{136,10,577},{4,11,30},{5,11,43},{24,0,8},{152,11,8},{7,0,1046}\n,{139,0,160},{4,10,413},{5,10,677},{7,0,492},{7,11,492},{8,10,432},{140,10,280},\n{6,0,45},{7,0,433},{8,0,129},{9,0,21},{10,0,392},{11,0,79},{12,0,499},{13,0,199}\n,{141,0,451},{7,0,558},{136,0,353},{4,11,220},{7,11,1535},{9,11,93},{139,11,474}\n,{7,10,646},{7,10,1730},{11,10,446},{141,10,178},{133,0,785},{134,0,1145},{8,0,\n81},{9,0,189},{9,0,201},{11,0,478},{11,0,712},{141,0,338},{5,0,353},{151,0,26},{\n4,10,395},{139,0,762},{134,0,2024},{4,0,611},{133,0,606},{9,10,174},{10,10,164},\n{11,10,440},{11,10,841},{143,10,98},{134,10,426},{10,10,608},{139,10,1002},{138,\n10,250},{6,0,25},{7,0,855},{7,0,1258},{144,0,32},{7,11,1725},{138,11,393},{5,11,\n263},{134,11,414},{5,10,476},{134,0,2011},{4,0,4},{6,11,178},{6,11,1750},{7,0,\n1118},{7,0,1320},{7,0,1706},{8,0,277},{8,11,251},{9,0,622},{9,11,690},{10,0,9},{\n10,11,155},{10,11,196},{10,11,373},{11,0,724},{11,11,698},{12,0,350},{12,0,397},\n{13,0,28},{13,0,159},{13,11,155},{15,0,89},{18,0,5},{19,0,9},{20,0,34},{20,11,93\n},{150,0,47},{5,11,97},{137,11,393},{5,10,76},{6,10,458},{6,10,497},{7,0,764},{7\n,10,868},{9,10,658},{10,10,594},{11,0,461},{11,10,566},{12,0,172},{12,10,338},{\n141,10,200},{134,0,1449},{138,11,40},{134,11,1639},{134,0,1445},{4,10,526},{6,0,\n1168},{7,10,1029},{135,10,1054},{4,11,191},{7,11,934},{8,11,647},{145,11,97},{\n132,10,636},{6,0,233},{7,10,660},{7,10,1124},{17,10,31},{19,10,22},{151,10,14},{\n6,10,1699},{136,11,110},{12,11,246},{15,11,162},{19,11,64},{20,11,8},{20,11,95},\n{22,11,24},{152,11,17},{5,11,165},{9,11,346},{138,11,655},{5,11,319},{135,11,534\n},{134,0,255},{8,11,128},{9,0,216},{139,11,179},{9,0,183},{139,0,286},{11,0,956}\n,{151,0,3},{4,0,536},{7,0,1141},{10,0,723},{139,0,371},{4,10,279},{7,10,301},{\n137,10,362},{5,11,57},{6,11,101},{6,11,1663},{7,0,285},{7,11,132},{7,11,1048},{7\n,11,1154},{7,11,1415},{7,11,1507},{12,11,493},{15,11,105},{151,11,15},{5,11,459}\n,{7,10,1743},{7,11,1073},{8,11,241},{136,11,334},{4,10,178},{133,10,399},{135,0,\n560},{132,0,690},{135,0,1246},{18,0,157},{147,0,63},{10,0,599},{11,0,33},{12,0,\n571},{149,0,1},{6,11,324},{6,11,520},{7,11,338},{7,11,1616},{7,11,1729},{8,11,\n228},{9,11,69},{139,11,750},{7,0,1862},{12,0,491},{12,0,520},{13,0,383},{142,0,\n244},{135,11,734},{134,10,1692},{6,10,202},{7,11,705},{10,0,448},{11,0,630},{12,\n10,360},{17,0,117},{17,10,118},{18,10,27},{148,10,67},{4,11,73},{6,11,612},{7,11\n,927},{7,11,1822},{8,11,217},{9,11,472},{9,11,765},{9,11,766},{10,11,408},{11,11\n,51},{11,11,793},{12,11,266},{15,11,158},{20,11,89},{150,11,32},{4,0,190},{133,0\n,554},{133,0,1001},{5,11,389},{8,11,636},{137,11,229},{5,0,446},{7,10,872},{10,\n10,516},{139,10,167},{137,10,313},{132,10,224},{134,0,1313},{5,10,546},{7,10,35}\n,{8,10,11},{8,10,12},{9,10,315},{9,10,533},{10,10,802},{11,10,166},{12,10,525},{\n142,10,243},{6,0,636},{137,0,837},{5,10,241},{8,10,242},{9,10,451},{10,10,667},{\n11,10,598},{140,10,429},{22,10,46},{150,11,46},{136,11,472},{11,0,278},{142,0,73\n},{141,11,185},{132,0,868},{134,0,972},{4,10,366},{137,10,516},{138,0,1010},{5,\n11,189},{6,10,1736},{7,11,442},{7,11,443},{8,11,281},{12,11,174},{13,11,83},{141\n,11,261},{139,11,384},{6,11,2},{7,11,191},{7,11,446},{7,11,758},{7,11,1262},{7,\n11,1737},{8,11,22},{8,11,270},{8,11,612},{9,11,4},{9,11,167},{9,11,312},{9,11,\n436},{10,11,156},{10,11,216},{10,11,311},{10,11,623},{11,11,72},{11,11,330},{11,\n11,455},{12,11,101},{12,11,321},{12,11,504},{12,11,530},{12,11,543},{13,11,17},{\n13,11,156},{13,11,334},{14,11,48},{15,11,70},{17,11,60},{148,11,64},{6,10,331},{\n136,10,623},{135,0,1231},{132,0,304},{6,11,60},{7,11,670},{7,11,1327},{8,11,411}\n,{8,11,435},{9,11,653},{9,11,740},{10,11,385},{11,11,222},{11,11,324},{11,11,829\n},{140,11,611},{6,11,166},{7,0,506},{7,11,374},{135,11,1174},{14,11,43},{146,11,\n21},{135,11,1694},{135,10,1888},{5,11,206},{134,11,398},{135,11,50},{150,0,26},{\n6,0,53},{6,0,199},{7,0,1408},{8,0,32},{8,0,93},{10,0,397},{10,0,629},{11,0,593},\n{11,0,763},{13,0,326},{145,0,35},{134,0,105},{132,10,394},{4,0,843},{138,0,794},\n{11,0,704},{141,0,396},{5,0,114},{5,0,255},{141,0,285},{6,0,619},{7,0,898},{7,0,\n1092},{7,10,1931},{8,0,485},{18,0,28},{147,0,116},{7,10,574},{7,10,1719},{137,0,\n145},{7,0,2035},{8,0,19},{9,0,89},{138,0,831},{132,10,658},{6,11,517},{7,11,1159\n},{10,11,621},{139,11,192},{7,0,1933},{7,11,1933},{9,10,781},{10,10,144},{11,10,\n385},{13,10,161},{13,10,228},{13,10,268},{148,10,107},{136,10,374},{10,11,223},{\n139,11,645},{135,0,1728},{7,11,64},{7,11,289},{136,11,245},{4,10,344},{6,10,498}\n,{139,10,323},{136,0,746},{135,10,1063},{137,10,155},{4,0,987},{6,0,1964},{6,0,\n1974},{6,0,1990},{136,0,995},{133,11,609},{133,10,906},{134,0,1550},{134,0,874},\n{5,11,129},{6,11,61},{135,11,947},{4,0,1018},{6,0,1938},{6,0,2021},{134,0,2039},\n{132,0,814},{11,0,126},{139,0,287},{134,0,1264},{5,0,955},{136,0,814},{141,11,\n506},{132,11,314},{6,0,981},{139,11,1000},{5,0,56},{8,0,892},{8,0,915},{140,0,\n776},{148,0,100},{10,0,4},{10,0,13},{11,0,638},{148,0,57},{148,11,74},{4,10,616}\n,{133,0,738},{133,11,637},{136,10,692},{133,0,758},{132,10,305},{137,11,590},{5,\n11,280},{135,11,1226},{134,11,494},{135,0,1112},{133,11,281},{5,10,214},{7,10,\n603},{8,10,611},{9,10,686},{10,10,88},{11,10,459},{11,10,496},{12,10,463},{12,10\n,590},{13,0,44},{142,0,214},{139,0,328},{135,11,1064},{137,0,133},{7,0,168},{13,\n0,196},{141,0,237},{134,10,1703},{134,0,1152},{135,0,1245},{5,0,110},{6,0,169},{\n6,0,1702},{7,0,400},{8,0,538},{9,0,184},{9,0,524},{140,0,218},{6,0,1816},{10,0,\n871},{12,0,769},{140,0,785},{132,11,630},{7,11,33},{7,11,120},{8,11,489},{9,11,\n319},{10,11,820},{11,11,1004},{12,11,379},{13,11,117},{13,11,412},{14,11,25},{15\n,11,52},{15,11,161},{16,11,47},{149,11,2},{6,0,133},{8,0,413},{9,0,353},{139,0,\n993},{145,10,19},{4,11,937},{133,11,801},{134,0,978},{6,0,93},{6,0,1508},{7,0,\n1422},{7,0,1851},{8,0,673},{9,0,529},{140,0,43},{4,10,737},{6,0,317},{10,0,512},\n{11,10,294},{12,10,60},{12,10,437},{13,10,64},{13,10,380},{142,10,430},{7,11,\n1591},{9,0,371},{144,11,43},{6,10,1758},{8,10,520},{9,10,345},{9,10,403},{142,10\n,350},{5,0,526},{10,10,242},{138,10,579},{9,0,25},{10,0,467},{138,0,559},{5,10,\n139},{7,10,1168},{138,10,539},{4,0,335},{135,0,942},{140,0,754},{132,11,365},{11\n,0,182},{142,0,195},{142,11,29},{5,11,7},{139,11,774},{4,11,746},{135,11,1090},{\n8,0,39},{10,0,773},{11,0,84},{12,0,205},{142,0,1},{5,0,601},{5,0,870},{5,11,360}\n,{136,11,237},{132,0,181},{136,0,370},{134,0,1652},{4,10,107},{7,10,613},{8,0,\n358},{8,10,439},{8,10,504},{9,10,501},{10,10,383},{139,10,477},{132,10,229},{137\n,11,785},{4,0,97},{5,0,147},{6,0,286},{7,0,1362},{141,0,176},{4,10,903},{6,0,537\n},{7,0,788},{135,0,1816},{140,10,71},{6,0,743},{134,0,1223},{6,0,375},{7,0,169},\n{7,0,254},{7,11,1493},{136,0,780},{4,10,47},{6,10,373},{7,0,1714},{7,10,452},{7,\n10,543},{7,10,1856},{9,10,6},{11,10,257},{139,10,391},{6,0,896},{136,0,1003},{\n135,0,1447},{137,11,341},{5,10,980},{134,10,1754},{145,11,22},{4,11,277},{5,11,\n608},{6,11,493},{7,11,457},{140,11,384},{7,10,536},{7,10,1331},{136,10,143},{140\n,0,744},{7,11,27},{135,11,316},{5,10,19},{6,10,533},{146,0,126},{4,0,788},{5,11,\n552},{5,11,586},{5,11,676},{6,11,448},{8,11,244},{11,0,41},{11,11,1},{11,11,41},\n{13,11,3},{16,11,54},{17,11,4},{146,11,13},{4,0,985},{4,11,401},{6,0,1801},{137,\n11,264},{5,10,395},{5,10,951},{134,10,1776},{5,0,629},{135,0,1549},{11,10,663},{\n12,10,210},{13,10,166},{13,10,310},{14,10,373},{147,10,43},{9,11,543},{10,11,524\n},{11,11,30},{12,11,524},{14,11,315},{16,11,18},{20,11,26},{148,11,65},{4,11,205\n},{5,11,623},{7,11,104},{136,11,519},{5,0,293},{134,0,601},{7,11,579},{9,11,41},\n{9,11,244},{9,11,669},{10,11,5},{11,11,861},{11,11,951},{139,11,980},{132,11,717\n},{132,10,695},{7,10,497},{9,10,387},{147,10,81},{132,0,420},{142,0,37},{6,0,\n1134},{6,0,1900},{12,0,830},{12,0,878},{12,0,894},{15,0,221},{143,0,245},{132,11\n,489},{7,0,1570},{140,0,542},{8,0,933},{136,0,957},{5,10,284},{6,0,1371},{6,10,\n49},{6,10,350},{7,0,31},{7,10,377},{7,10,1693},{8,0,373},{8,10,678},{9,10,161},{\n9,10,585},{9,10,671},{9,10,839},{11,10,912},{141,10,427},{135,11,892},{4,0,325},\n{138,0,125},{139,11,47},{132,10,597},{138,0,323},{6,0,1547},{7,11,1605},{9,11,\n473},{11,11,962},{146,11,139},{139,10,908},{7,11,819},{9,11,26},{9,11,392},{10,\n11,152},{10,11,226},{11,11,19},{12,11,276},{12,11,426},{12,11,589},{13,11,460},{\n15,11,97},{19,11,48},{148,11,104},{135,11,51},{4,0,718},{135,0,1216},{6,0,1896},\n{6,0,1905},{6,0,1912},{7,11,761},{7,11,1051},{9,0,947},{9,0,974},{9,11,545},{12,\n0,809},{12,0,850},{12,0,858},{12,0,874},{12,0,887},{12,0,904},{12,0,929},{12,0,\n948},{12,0,952},{15,0,198},{15,0,206},{15,0,220},{15,0,227},{15,0,247},{18,0,188\n},{21,0,48},{21,0,50},{24,0,25},{152,0,29},{5,0,124},{5,0,144},{6,0,548},{7,0,15\n},{7,0,153},{137,0,629},{135,11,606},{135,10,2014},{7,10,2007},{9,10,101},{9,10,\n450},{9,11,46},{10,10,66},{10,10,842},{11,10,536},{140,10,587},{6,0,75},{7,0,\n1531},{8,0,416},{9,0,240},{9,0,275},{10,0,100},{11,0,658},{11,0,979},{12,0,86},{\n14,0,207},{15,0,20},{143,0,25},{5,0,141},{5,0,915},{6,0,1783},{7,0,211},{7,0,698\n},{7,0,1353},{9,0,83},{9,0,281},{10,0,376},{10,0,431},{11,0,543},{12,0,664},{13,\n0,280},{13,0,428},{14,0,61},{14,0,128},{17,0,52},{145,0,81},{132,11,674},{135,0,\n533},{149,0,6},{132,11,770},{133,0,538},{5,11,79},{7,11,1027},{7,11,1477},{139,\n11,52},{139,10,62},{4,0,338},{133,0,400},{5,11,789},{134,11,195},{4,11,251},{4,\n11,688},{7,11,513},{7,11,1284},{9,11,87},{138,11,365},{134,10,1766},{6,0,0},{7,0\n,84},{11,0,895},{145,0,11},{139,0,892},{4,0,221},{5,0,659},{7,0,697},{7,0,1211},\n{138,0,284},{133,0,989},{133,11,889},{4,11,160},{5,11,330},{7,11,1434},{136,11,\n174},{6,10,1665},{7,10,256},{7,10,1388},{10,10,499},{139,10,670},{4,10,22},{5,10\n,10},{7,0,848},{136,10,97},{138,0,507},{133,10,481},{4,0,188},{135,0,805},{5,0,\n884},{6,0,732},{139,0,991},{135,11,968},{11,11,636},{15,11,145},{17,11,34},{19,\n11,50},{151,11,20},{6,10,134},{7,0,959},{7,10,437},{9,10,37},{14,10,285},{14,10,\n371},{144,0,60},{7,10,486},{8,10,155},{11,10,93},{140,10,164},{134,0,1653},{5,10\n,591},{135,0,337},{5,11,374},{6,0,1989},{8,0,922},{136,0,978},{132,0,638},{138,0\n,500},{133,11,731},{5,10,380},{5,10,650},{136,10,310},{138,11,381},{4,10,364},{7\n,10,1156},{7,10,1187},{137,10,409},{137,11,224},{140,0,166},{134,10,482},{4,11,\n626},{5,11,642},{6,11,425},{10,11,202},{139,11,141},{4,10,781},{6,10,487},{7,10,\n926},{8,10,263},{139,10,500},{135,0,418},{4,10,94},{135,10,1265},{136,0,760},{\n132,10,417},{136,11,835},{5,10,348},{134,10,522},{6,0,1277},{134,0,1538},{139,11\n,541},{135,11,1597},{5,11,384},{8,11,455},{140,11,48},{136,0,770},{5,11,264},{\n134,11,184},{4,0,89},{5,0,489},{6,0,315},{7,0,553},{7,0,1745},{138,0,243},{4,10,\n408},{4,10,741},{135,10,500},{134,0,1396},{133,0,560},{6,0,1658},{9,0,3},{10,0,\n154},{11,0,641},{13,0,85},{13,0,201},{141,0,346},{135,11,1595},{5,11,633},{6,11,\n28},{7,11,219},{135,11,1323},{9,11,769},{140,11,185},{135,11,785},{7,11,359},{8,\n11,243},{140,11,175},{138,0,586},{6,10,73},{135,0,1271},{132,11,105},{4,0,166},{\n5,0,505},{134,0,1670},{133,10,576},{4,11,324},{138,11,104},{142,10,231},{6,0,637\n},{7,10,1264},{7,10,1678},{11,10,945},{12,10,341},{12,10,471},{12,10,569},{23,11\n,21},{151,11,23},{8,11,559},{141,11,109},{134,0,1947},{7,0,445},{8,0,307},{8,0,\n704},{10,0,41},{10,0,439},{11,0,237},{11,0,622},{140,0,201},{135,11,963},{135,0,\n1977},{4,0,189},{5,0,713},{136,0,57},{138,0,371},{135,10,538},{132,0,552},{5,10,\n413},{134,0,883},{4,11,758},{134,0,923},{138,11,215},{136,10,495},{7,10,54},{8,\n10,312},{10,10,191},{10,10,614},{140,10,567},{7,11,351},{139,11,128},{6,10,468},\n{7,0,875},{7,10,1478},{8,10,530},{142,10,290},{135,0,1788},{5,11,918},{145,0,49}\n,{12,11,398},{20,11,39},{21,11,11},{150,11,41},{6,10,484},{7,10,822},{138,0,661}\n,{135,0,1945},{134,0,794},{137,10,900},{135,10,1335},{6,10,1724},{135,10,2022},{\n132,11,340},{134,0,1135},{4,0,784},{133,0,745},{5,0,84},{134,0,163},{133,0,410},\n{4,0,976},{5,11,985},{7,11,509},{7,11,529},{145,11,96},{132,10,474},{134,0,703},\n{135,11,1919},{5,0,322},{8,0,186},{9,0,262},{10,0,187},{142,0,208},{135,10,1504}\n,{133,0,227},{5,10,305},{9,0,560},{141,0,208},{132,11,247},{7,0,1395},{8,0,486},\n{9,0,236},{9,0,878},{10,0,218},{11,0,95},{19,0,17},{147,0,31},{7,0,2043},{8,0,\n672},{141,0,448},{4,11,184},{5,11,390},{6,11,337},{7,11,23},{7,11,494},{7,11,618\n},{7,11,1456},{8,11,27},{8,11,599},{10,11,153},{139,11,710},{135,0,466},{135,10,\n1236},{4,10,480},{6,0,167},{6,10,302},{6,10,1642},{7,0,186},{7,0,656},{7,10,837}\n,{7,10,1547},{7,10,1657},{8,10,429},{9,10,228},{10,0,643},{13,10,289},{13,10,343\n},{147,10,101},{134,0,1428},{134,0,1440},{5,0,412},{7,10,278},{10,10,739},{11,10\n,708},{141,10,348},{134,0,1118},{136,0,562},{148,11,46},{9,0,316},{139,0,256},{\n134,0,1771},{135,0,1190},{137,0,132},{10,11,227},{11,11,497},{11,11,709},{140,11\n,415},{143,0,66},{6,11,360},{7,11,1664},{136,11,478},{144,10,28},{4,0,317},{135,\n0,1279},{5,0,63},{133,0,509},{136,11,699},{145,10,36},{134,0,1475},{11,11,343},{\n142,11,127},{132,11,739},{132,0,288},{135,11,1757},{8,0,89},{8,0,620},{9,0,608},\n{11,0,628},{12,0,322},{143,0,124},{134,0,1225},{4,11,67},{5,11,422},{6,10,363},{\n7,0,1189},{7,10,1955},{7,11,1037},{7,11,1289},{7,11,1555},{8,10,725},{9,11,741},\n{145,11,108},{134,0,1468},{6,0,689},{134,0,1451},{138,0,120},{151,0,1},{137,10,\n805},{142,0,329},{5,10,813},{135,10,2046},{135,0,226},{138,11,96},{5,10,712},{7,\n0,1855},{11,10,17},{13,10,321},{144,10,67},{6,10,320},{7,10,781},{7,10,1921},{9,\n0,461},{9,10,55},{10,10,186},{10,10,273},{10,10,664},{10,10,801},{11,10,996},{11\n,10,997},{13,10,157},{142,10,170},{8,10,271},{8,11,203},{11,11,823},{11,11,846},\n{12,11,482},{13,11,133},{13,11,277},{13,11,302},{13,11,464},{14,11,205},{142,11,\n221},{135,0,1346},{4,11,449},{133,11,718},{134,0,85},{7,10,103},{7,10,863},{11,\n10,184},{14,0,299},{145,10,62},{4,11,355},{6,11,311},{9,11,256},{138,11,404},{\n137,10,659},{138,11,758},{133,11,827},{5,11,64},{140,11,581},{134,0,1171},{4,11,\n442},{7,11,1047},{7,11,1352},{135,11,1643},{132,0,980},{5,11,977},{6,11,288},{7,\n11,528},{135,11,1065},{5,0,279},{6,0,235},{7,0,468},{8,0,446},{9,0,637},{10,0,\n717},{11,0,738},{140,0,514},{132,0,293},{11,10,337},{142,10,303},{136,11,285},{4\n,11,254},{5,0,17},{6,0,371},{9,0,528},{140,0,364},{5,10,77},{7,10,1455},{10,10,\n843},{147,10,73},{150,0,5},{132,10,458},{6,11,12},{7,11,1219},{145,11,73},{135,\n10,1420},{6,10,109},{138,10,382},{135,11,125},{6,10,330},{7,10,1084},{139,10,142\n},{6,11,369},{6,11,502},{7,11,1036},{8,11,348},{9,11,452},{10,11,26},{11,11,224}\n,{11,11,387},{11,11,772},{12,11,95},{12,11,629},{13,11,195},{13,11,207},{13,11,\n241},{14,11,260},{14,11,270},{143,11,140},{132,11,269},{5,11,480},{7,11,532},{7,\n11,1197},{7,11,1358},{8,11,291},{11,11,349},{142,11,396},{150,0,48},{10,0,601},{\n13,0,353},{141,0,376},{5,0,779},{5,0,807},{6,0,1655},{134,0,1676},{142,11,223},{\n4,0,196},{5,0,558},{133,0,949},{148,11,15},{135,11,1764},{134,0,1322},{132,0,752\n},{139,0,737},{135,11,657},{136,11,533},{135,0,412},{4,0,227},{5,0,159},{5,0,409\n},{7,0,80},{8,0,556},{10,0,479},{12,0,418},{14,0,50},{14,0,123},{14,0,192},{14,0\n,249},{14,0,295},{143,0,27},{7,0,1470},{8,0,66},{8,0,137},{8,0,761},{9,0,638},{\n11,0,80},{11,0,212},{11,0,368},{11,0,418},{12,0,8},{13,0,15},{16,0,61},{17,0,59}\n,{19,0,28},{148,0,84},{135,10,1985},{4,11,211},{4,11,332},{5,11,335},{6,11,238},\n{7,11,269},{7,11,811},{7,11,1797},{8,10,122},{8,11,836},{9,11,507},{141,11,242},\n{6,0,683},{134,0,1252},{4,0,873},{132,10,234},{134,0,835},{6,0,38},{7,0,1220},{8\n,0,185},{8,0,256},{9,0,22},{9,0,331},{10,0,738},{11,0,205},{11,0,540},{11,0,746}\n,{13,0,465},{14,0,88},{142,0,194},{138,0,986},{5,11,1009},{12,11,582},{146,11,\n131},{4,0,159},{6,0,115},{7,0,252},{7,0,257},{7,0,1928},{8,0,69},{9,0,384},{10,0\n,91},{10,0,615},{12,0,375},{14,0,235},{18,0,117},{147,0,123},{133,0,911},{136,0,\n278},{5,10,430},{5,10,932},{6,10,131},{7,10,417},{9,10,522},{11,10,314},{141,10,\n390},{14,10,149},{14,10,399},{143,10,57},{4,0,151},{7,0,1567},{136,0,749},{5,11,\n228},{6,11,203},{7,11,156},{8,11,347},{137,11,265},{132,10,507},{10,0,989},{140,\n0,956},{133,0,990},{5,0,194},{6,0,927},{7,0,1662},{9,0,90},{140,0,564},{4,10,343\n},{133,10,511},{133,0,425},{7,10,455},{138,10,591},{4,0,774},{7,11,476},{7,11,\n1592},{138,11,87},{5,0,971},{135,10,1381},{5,11,318},{147,11,121},{5,11,291},{7,\n11,765},{9,11,389},{140,11,548},{134,10,575},{4,0,827},{12,0,646},{12,0,705},{12\n,0,712},{140,0,714},{139,0,752},{137,0,662},{5,0,72},{6,0,264},{7,0,21},{7,0,46}\n,{7,0,2013},{8,0,215},{8,0,513},{10,0,266},{139,0,22},{139,11,522},{6,0,239},{7,\n0,118},{10,0,95},{11,0,603},{13,0,443},{14,0,160},{143,0,4},{6,0,431},{134,0,669\n},{7,10,1127},{7,10,1572},{10,10,297},{10,10,422},{11,10,764},{11,10,810},{12,10\n,264},{13,10,102},{13,10,300},{13,10,484},{14,10,147},{14,10,229},{17,10,71},{18\n,10,118},{147,10,120},{5,0,874},{6,0,1677},{10,11,525},{11,11,82},{143,0,0},{6,0\n,65},{7,0,939},{7,0,1172},{7,0,1671},{9,0,540},{10,0,696},{11,0,265},{11,0,732},\n{11,0,928},{11,0,937},{141,0,438},{134,0,1350},{136,11,547},{132,11,422},{5,11,\n355},{145,11,0},{137,11,905},{5,0,682},{135,0,1887},{132,0,809},{4,0,696},{133,\n11,865},{6,0,1074},{6,0,1472},{14,10,35},{142,10,191},{5,11,914},{134,11,1625},{\n133,11,234},{135,11,1383},{137,11,780},{132,10,125},{4,0,726},{133,0,630},{8,0,\n802},{136,0,838},{132,10,721},{6,0,1337},{7,0,776},{8,10,145},{147,0,56},{132,0,\n970},{7,10,792},{8,10,147},{10,10,821},{139,10,1021},{139,10,970},{8,0,940},{137\n,0,797},{135,11,1312},{7,10,1999},{7,11,816},{7,11,1241},{9,0,248},{9,11,283},{9\n,11,520},{10,0,400},{10,11,213},{10,11,307},{10,11,463},{10,11,671},{10,11,746},\n{11,11,401},{11,11,794},{12,11,517},{18,11,107},{147,11,115},{6,0,1951},{134,0,\n2040},{135,11,339},{5,10,168},{5,10,930},{8,10,74},{9,10,623},{12,10,500},{12,10\n,579},{13,0,41},{143,0,93},{6,0,118},{7,0,215},{7,0,1521},{140,0,11},{6,10,220},\n{7,10,1101},{141,10,105},{6,11,421},{7,11,61},{7,11,1540},{10,11,11},{138,11,501\n},{7,0,615},{138,0,251},{140,11,631},{135,0,1044},{6,10,19},{7,10,1413},{139,10,\n428},{133,0,225},{7,10,96},{8,10,401},{8,10,703},{137,10,896},{145,10,116},{6,11\n,102},{7,11,72},{15,11,142},{147,11,67},{7,10,1961},{7,10,1965},{8,10,702},{136,\n10,750},{7,10,2030},{8,10,150},{8,10,737},{12,10,366},{151,11,30},{4,0,370},{5,0\n,756},{7,0,1326},{135,11,823},{8,10,800},{9,10,148},{9,10,872},{9,10,890},{11,10\n,309},{11,10,1001},{13,10,267},{141,10,323},{6,0,1662},{7,0,48},{8,0,771},{10,0,\n116},{13,0,104},{14,0,105},{14,0,184},{15,0,168},{19,0,92},{148,0,68},{7,11,1870\n},{138,0,209},{7,11,68},{8,11,48},{8,11,88},{8,11,582},{8,11,681},{9,11,373},{9,\n11,864},{11,11,157},{11,11,336},{11,11,843},{148,11,27},{134,0,930},{4,11,88},{5\n,11,137},{5,11,174},{5,11,777},{6,11,1664},{6,11,1725},{7,11,77},{7,11,426},{7,\n11,1317},{7,11,1355},{8,11,126},{8,11,563},{9,11,523},{9,11,750},{10,11,310},{10\n,11,836},{11,11,42},{11,11,318},{11,11,731},{12,11,68},{12,11,92},{12,11,507},{\n12,11,692},{13,11,81},{13,11,238},{13,11,374},{18,11,138},{19,11,78},{19,11,111}\n,{20,11,55},{20,11,77},{148,11,92},{4,11,938},{135,11,1831},{5,10,547},{7,10,424\n},{8,11,617},{138,11,351},{6,0,1286},{6,11,1668},{7,11,1499},{8,11,117},{9,11,\n314},{138,11,174},{6,0,759},{6,0,894},{7,11,707},{139,11,563},{4,0,120},{135,0,\n1894},{9,0,385},{149,0,17},{138,0,429},{133,11,403},{5,0,820},{135,0,931},{5,10,\n133},{138,0,199},{6,0,151},{6,0,1675},{7,0,383},{151,0,10},{6,0,761},{136,10,187\n},{8,0,365},{10,10,0},{10,10,818},{139,10,988},{4,11,44},{5,11,311},{6,11,156},{\n7,11,639},{7,11,762},{7,11,1827},{9,11,8},{9,11,462},{148,11,83},{4,11,346},{7,\n11,115},{9,11,180},{9,11,456},{138,11,363},{136,10,685},{7,0,1086},{145,0,46},{6\n,0,1624},{11,0,11},{12,0,422},{13,0,444},{142,0,360},{6,0,1020},{6,0,1260},{134,\n0,1589},{4,0,43},{5,0,344},{5,0,357},{14,0,472},{150,0,58},{6,0,1864},{6,0,1866}\n,{6,0,1868},{6,0,1869},{6,0,1874},{6,0,1877},{6,0,1903},{6,0,1911},{9,0,920},{9,\n0,921},{9,0,924},{9,0,946},{9,0,959},{9,0,963},{9,0,970},{9,0,997},{9,0,1008},{9\n,0,1017},{12,0,795},{12,0,797},{12,0,798},{12,0,800},{12,0,803},{12,0,811},{12,0\n,820},{12,0,821},{12,0,839},{12,0,841},{12,0,848},{12,0,911},{12,0,921},{12,0,\n922},{12,0,925},{12,0,937},{12,0,944},{12,0,945},{12,0,953},{15,0,184},{15,0,191\n},{15,0,199},{15,0,237},{15,0,240},{15,0,243},{15,0,246},{18,0,203},{21,0,40},{\n21,0,52},{21,0,57},{24,0,23},{24,0,28},{152,0,30},{134,0,725},{145,11,58},{133,0\n,888},{137,10,874},{4,0,711},{8,10,774},{10,10,670},{140,10,51},{144,11,40},{6,\n11,185},{7,11,1899},{139,11,673},{137,10,701},{137,0,440},{4,11,327},{5,11,478},\n{7,11,1332},{8,11,753},{140,11,227},{4,10,127},{5,10,350},{6,10,356},{8,10,426},\n{9,10,572},{10,10,247},{139,10,312},{5,11,1020},{133,11,1022},{4,11,103},{133,11\n,401},{6,0,1913},{6,0,1926},{6,0,1959},{9,0,914},{9,0,939},{9,0,952},{9,0,979},{\n9,0,990},{9,0,998},{9,0,1003},{9,0,1023},{12,0,827},{12,0,834},{12,0,845},{12,0,\n912},{12,0,935},{12,0,951},{15,0,172},{15,0,174},{18,0,198},{149,0,63},{4,11,499\n},{5,0,958},{5,0,987},{135,11,1421},{6,10,59},{6,10,1762},{7,0,885},{9,10,603},{\n141,10,397},{10,11,62},{141,11,164},{4,0,847},{135,0,326},{11,0,276},{142,0,293}\n,{4,0,65},{4,11,96},{5,0,479},{5,0,1004},{7,0,1913},{8,0,317},{9,0,302},{10,0,\n612},{141,0,22},{4,0,261},{135,0,510},{135,0,1514},{6,10,111},{7,10,4},{8,10,163\n},{8,10,776},{138,10,566},{4,0,291},{9,0,515},{12,0,152},{12,0,443},{13,0,392},{\n142,0,357},{7,11,399},{135,11,1492},{4,0,589},{139,0,282},{6,11,563},{135,10,\n1994},{5,10,297},{135,10,1038},{4,0,130},{7,0,843},{135,0,1562},{5,0,42},{5,0,\n879},{7,0,245},{7,0,324},{7,0,1532},{11,0,463},{11,0,472},{13,0,363},{144,0,52},\n{4,0,134},{133,0,372},{133,0,680},{136,10,363},{6,0,1997},{8,0,935},{136,0,977},\n{4,0,810},{135,0,1634},{135,10,1675},{4,11,910},{5,11,832},{135,0,1390},{7,10,\n808},{8,11,266},{139,11,578},{132,0,644},{4,0,982},{138,0,867},{132,10,280},{135\n,0,540},{140,10,54},{135,0,123},{134,0,1978},{4,10,421},{133,10,548},{6,0,623},{\n136,0,789},{4,0,908},{5,0,359},{5,0,508},{6,0,1723},{7,0,343},{7,0,1996},{135,0,\n2026},{134,0,1220},{4,0,341},{135,0,480},{6,10,254},{9,10,109},{138,10,103},{134\n,0,888},{8,11,528},{137,11,348},{4,11,20},{5,11,616},{7,0,1995},{8,0,299},{11,0,\n890},{140,0,674},{135,11,1094},{134,10,1630},{4,0,238},{5,0,503},{6,0,179},{7,0,\n2003},{8,0,381},{8,0,473},{9,0,149},{10,0,788},{15,0,45},{15,0,86},{20,0,110},{\n150,0,57},{133,10,671},{4,11,26},{5,11,429},{6,11,245},{7,11,704},{7,11,1379},{\n135,11,1474},{4,0,121},{5,0,156},{5,0,349},{9,0,431},{10,0,605},{142,0,342},{7,\n11,943},{139,11,614},{132,10,889},{132,11,621},{7,10,1382},{7,10,1910},{135,11,\n1382},{132,10,627},{133,10,775},{133,11,542},{133,11,868},{136,11,433},{6,0,1373\n},{7,0,1011},{11,10,362},{11,10,948},{140,10,388},{6,0,80},{7,0,173},{7,11,1495}\n,{9,0,547},{10,0,730},{14,0,18},{150,0,39},{6,0,1694},{135,0,1974},{140,0,196},{\n4,0,923},{6,0,507},{6,0,1711},{7,10,451},{8,10,389},{12,10,490},{13,10,16},{13,\n10,215},{13,10,351},{18,10,132},{147,10,125},{6,0,646},{134,0,1047},{135,10,841}\n,{136,10,566},{6,0,1611},{135,0,1214},{139,0,926},{132,11,525},{132,0,595},{5,0,\n240},{6,0,459},{7,0,12},{7,0,114},{7,0,949},{7,0,1753},{7,0,1805},{8,0,658},{9,0\n,1},{11,0,959},{141,0,446},{5,10,912},{134,10,1695},{132,0,446},{7,11,62},{12,11\n,45},{147,11,112},{5,10,236},{6,10,572},{8,10,492},{11,10,618},{144,10,56},{5,10\n,190},{136,10,318},{135,10,1376},{4,11,223},{6,11,359},{11,11,3},{13,11,108},{14\n,11,89},{144,11,22},{132,11,647},{134,0,490},{134,0,491},{134,0,1584},{135,11,\n685},{138,11,220},{7,0,250},{136,0,507},{132,0,158},{4,0,140},{7,0,362},{8,0,209\n},{9,0,10},{9,0,160},{9,0,503},{9,0,614},{10,0,689},{11,0,327},{11,0,553},{11,0,\n725},{11,0,767},{12,0,252},{12,0,583},{13,0,192},{14,0,269},{14,0,356},{148,0,50\n},{19,0,1},{19,0,26},{150,0,9},{132,11,109},{6,0,228},{7,0,1341},{9,0,408},{138,\n0,343},{4,0,373},{5,0,283},{6,0,480},{7,0,609},{10,0,860},{138,0,878},{6,0,779},\n{134,0,1209},{4,0,557},{7,11,263},{7,11,628},{136,11,349},{132,0,548},{7,0,197},\n{8,0,142},{8,0,325},{9,0,150},{9,0,596},{10,0,350},{10,0,353},{11,0,74},{11,0,\n315},{12,0,662},{12,0,681},{14,0,423},{143,0,141},{4,11,40},{10,11,67},{11,11,\n117},{11,11,768},{139,11,935},{7,11,992},{8,11,301},{9,11,722},{12,11,63},{13,11\n,29},{14,11,161},{143,11,18},{6,0,1490},{138,11,532},{5,0,580},{7,0,378},{7,0,\n674},{7,0,1424},{15,0,83},{15,11,83},{16,0,11},{144,11,11},{6,0,1057},{6,0,1335}\n,{7,10,85},{7,10,247},{8,10,585},{10,0,316},{138,10,163},{4,0,169},{5,0,83},{6,0\n,399},{6,0,579},{6,0,1513},{7,0,692},{7,0,846},{7,0,1015},{7,0,1799},{8,0,403},{\n9,0,394},{10,0,133},{12,0,4},{12,0,297},{12,0,452},{16,0,81},{18,0,25},{21,0,14}\n,{22,0,12},{151,0,18},{134,0,1106},{7,0,1546},{11,0,299},{142,0,407},{134,0,1192\n},{132,0,177},{5,0,411},{135,0,653},{7,0,439},{10,0,727},{11,0,260},{139,0,684},\n{138,10,145},{147,10,83},{5,0,208},{7,0,753},{135,0,1528},{137,11,617},{135,10,\n1922},{135,11,825},{4,10,124},{10,10,457},{11,0,422},{11,10,121},{11,10,169},{11\n,10,870},{12,10,214},{13,0,389},{14,10,187},{143,10,77},{11,0,615},{11,11,615},{\n15,0,58},{143,11,58},{9,0,618},{138,0,482},{6,0,1952},{6,0,1970},{142,0,505},{7,\n10,1193},{135,11,1838},{133,0,242},{135,10,1333},{6,10,107},{7,10,638},{7,10,\n1632},{137,10,396},{133,0,953},{5,10,370},{134,10,1756},{5,11,28},{6,11,204},{10\n,11,320},{10,11,583},{13,11,502},{14,11,72},{14,11,274},{14,11,312},{14,11,344},\n{15,11,159},{16,11,62},{16,11,69},{17,11,30},{18,11,42},{18,11,53},{18,11,84},{\n18,11,140},{19,11,68},{19,11,85},{20,11,5},{20,11,45},{20,11,101},{22,11,7},{150\n,11,20},{4,11,558},{6,11,390},{7,11,162},{7,11,689},{9,11,360},{138,11,653},{11,\n0,802},{141,0,67},{133,10,204},{133,0,290},{5,10,970},{134,10,1706},{132,0,380},\n{5,0,52},{7,0,277},{9,0,368},{139,0,791},{5,11,856},{6,11,1672},{6,11,1757},{6,\n11,1781},{7,11,1150},{7,11,1425},{7,11,1453},{140,11,513},{5,11,92},{7,10,3},{10\n,11,736},{140,11,102},{4,0,112},{5,0,653},{5,10,483},{5,10,685},{6,10,489},{7,10\n,1204},{136,10,394},{132,10,921},{5,10,1007},{134,0,1028},{5,11,590},{9,11,213},\n{145,11,91},{135,10,1696},{10,0,138},{139,0,476},{5,0,725},{5,0,727},{135,0,1811\n},{4,0,979},{6,0,1821},{6,0,1838},{8,0,876},{8,0,883},{8,0,889},{8,0,893},{8,0,\n895},{10,0,934},{12,0,720},{14,0,459},{148,0,123},{135,11,551},{4,0,38},{6,0,435\n},{7,0,307},{7,0,999},{7,0,1481},{7,0,1732},{7,0,1738},{8,0,371},{9,0,414},{11,0\n,316},{12,0,52},{13,0,420},{147,0,100},{135,0,1296},{132,10,712},{134,10,1629},{\n133,0,723},{134,0,651},{136,11,191},{9,11,791},{10,11,93},{11,11,301},{16,11,13}\n,{17,11,23},{18,11,135},{19,11,12},{20,11,1},{20,11,12},{148,11,14},{136,11,503}\n,{6,11,466},{135,11,671},{6,0,1200},{134,0,1330},{135,0,1255},{134,0,986},{5,0,\n109},{6,0,1784},{7,0,1895},{12,0,296},{140,0,302},{135,11,983},{133,10,485},{134\n,0,660},{134,0,800},{4,10,285},{5,0,216},{5,0,294},{5,10,317},{6,0,591},{6,10,\n301},{7,0,1879},{7,10,7},{8,10,153},{9,0,141},{9,0,270},{9,0,679},{10,0,159},{10\n,10,766},{11,0,197},{11,0,438},{11,10,468},{12,0,538},{12,0,559},{12,10,467},{13\n,10,143},{14,0,144},{14,0,167},{143,0,67},{136,0,945},{134,0,1090},{137,0,81},{\n12,11,468},{19,11,96},{148,11,24},{134,0,391},{138,11,241},{7,0,322},{136,0,249}\n,{134,0,1412},{135,11,795},{5,0,632},{138,0,526},{136,10,819},{6,0,144},{7,0,948\n},{7,0,1042},{7,11,954},{8,0,235},{8,0,461},{9,0,453},{9,0,796},{10,0,354},{145,\n0,77},{139,10,917},{6,0,940},{134,0,1228},{4,0,362},{7,0,52},{135,0,303},{6,11,\n549},{8,11,34},{8,11,283},{9,11,165},{138,11,475},{7,11,370},{7,11,1007},{7,11,\n1177},{135,11,1565},{5,11,652},{5,11,701},{135,11,449},{5,0,196},{6,0,486},{7,0,\n212},{8,0,309},{136,0,346},{6,10,1719},{6,10,1735},{7,10,2016},{7,10,2020},{8,10\n,837},{137,10,852},{6,11,159},{6,11,364},{7,11,516},{7,11,1439},{137,11,518},{\n135,0,1912},{135,0,1290},{132,0,686},{141,11,151},{138,0,625},{136,0,706},{138,\n10,568},{139,0,412},{4,0,30},{133,0,43},{8,10,67},{138,10,419},{7,0,967},{141,0,\n11},{12,0,758},{14,0,441},{142,0,462},{10,10,657},{14,10,297},{142,10,361},{139,\n10,729},{4,0,220},{135,0,1535},{7,11,501},{9,11,111},{10,11,141},{11,11,332},{13\n,11,43},{13,11,429},{14,11,130},{14,11,415},{145,11,102},{4,0,950},{6,0,1859},{7\n,0,11},{8,0,873},{12,0,710},{12,0,718},{12,0,748},{12,0,765},{148,0,124},{5,11,\n149},{5,11,935},{136,11,233},{142,11,291},{134,0,1579},{7,0,890},{8,10,51},{9,10\n,868},{10,10,833},{12,10,481},{12,10,570},{148,10,106},{141,0,2},{132,10,445},{\n136,11,801},{135,0,1774},{7,0,1725},{138,0,393},{5,0,263},{134,0,414},{132,11,\n322},{133,10,239},{7,0,456},{7,10,1990},{8,10,130},{139,10,720},{137,0,818},{5,\n10,123},{6,10,530},{7,10,348},{135,10,1419},{135,10,2024},{6,0,178},{6,0,1750},{\n8,0,251},{9,0,690},{10,0,155},{10,0,196},{10,0,373},{11,0,698},{13,0,155},{148,0\n,93},{5,0,97},{137,0,393},{134,0,674},{11,0,223},{140,0,168},{132,10,210},{139,\n11,464},{6,0,1639},{146,0,159},{139,11,2},{7,0,934},{8,0,647},{17,0,97},{19,0,59\n},{150,0,2},{132,0,191},{4,10,430},{5,0,165},{7,11,357},{9,0,346},{10,0,655},{\n139,0,885},{133,0,877},{5,10,213},{133,11,406},{8,0,128},{139,0,179},{6,11,69},{\n135,11,117},{135,0,1297},{11,11,43},{13,11,72},{141,11,142},{135,11,1830},{142,0\n,164},{5,0,57},{6,0,101},{6,0,586},{6,0,1663},{7,0,132},{7,0,1154},{7,0,1415},{7\n,0,1507},{12,0,493},{15,0,105},{151,0,15},{5,0,459},{7,0,1073},{8,0,241},{136,0,\n334},{133,11,826},{133,10,108},{5,10,219},{10,11,132},{11,11,191},{11,11,358},{\n139,11,460},{6,0,324},{6,0,520},{7,0,338},{7,0,1729},{8,0,228},{139,0,750},{4,10\n,193},{5,10,916},{7,10,364},{10,10,398},{10,10,726},{11,10,317},{11,10,626},{12,\n10,142},{12,10,288},{12,10,678},{13,10,313},{15,10,113},{18,10,114},{21,0,30},{\n150,0,53},{6,11,110},{135,11,1681},{135,0,910},{6,10,241},{7,10,907},{8,10,832},\n{9,10,342},{10,10,729},{11,10,284},{11,10,445},{11,10,651},{11,10,863},{13,10,\n398},{146,10,99},{5,11,1000},{7,0,705},{7,11,733},{9,0,734},{137,11,583},{4,0,73\n},{6,0,612},{7,0,927},{7,0,1822},{8,0,217},{9,0,765},{9,0,766},{10,0,408},{11,0,\n51},{11,0,793},{12,0,266},{15,0,158},{20,0,89},{150,0,32},{4,11,297},{6,11,529},\n{7,0,1330},{7,11,152},{7,11,713},{7,11,1845},{8,11,710},{8,11,717},{140,11,639},\n{5,0,389},{136,0,636},{134,0,1409},{4,10,562},{9,10,254},{139,10,879},{134,0,893\n},{132,10,786},{4,11,520},{135,11,575},{136,0,21},{140,0,721},{136,0,959},{7,11,\n1428},{7,11,1640},{9,11,169},{9,11,182},{9,11,367},{9,11,478},{9,11,506},{9,11,\n551},{9,11,648},{9,11,651},{9,11,697},{9,11,705},{9,11,725},{9,11,787},{9,11,794\n},{10,11,198},{10,11,214},{10,11,267},{10,11,275},{10,11,456},{10,11,551},{10,11\n,561},{10,11,613},{10,11,627},{10,11,668},{10,11,675},{10,11,691},{10,11,695},{\n10,11,707},{10,11,715},{11,11,183},{11,11,201},{11,11,244},{11,11,262},{11,11,\n352},{11,11,439},{11,11,493},{11,11,572},{11,11,591},{11,11,608},{11,11,611},{11\n,11,646},{11,11,674},{11,11,711},{11,11,751},{11,11,761},{11,11,776},{11,11,785}\n,{11,11,850},{11,11,853},{11,11,862},{11,11,865},{11,11,868},{11,11,898},{11,11,\n902},{11,11,903},{11,11,910},{11,11,932},{11,11,942},{11,11,957},{11,11,967},{11\n,11,972},{12,11,148},{12,11,195},{12,11,220},{12,11,237},{12,11,318},{12,11,339}\n,{12,11,393},{12,11,445},{12,11,450},{12,11,474},{12,11,509},{12,11,533},{12,11,\n591},{12,11,594},{12,11,597},{12,11,621},{12,11,633},{12,11,642},{13,11,59},{13,\n11,60},{13,11,145},{13,11,239},{13,11,250},{13,11,273},{13,11,329},{13,11,344},{\n13,11,365},{13,11,372},{13,11,387},{13,11,403},{13,11,414},{13,11,456},{13,11,\n478},{13,11,483},{13,11,489},{14,11,55},{14,11,57},{14,11,81},{14,11,90},{14,11,\n148},{14,11,239},{14,11,266},{14,11,321},{14,11,326},{14,11,327},{14,11,330},{14\n,11,347},{14,11,355},{14,11,401},{14,11,411},{14,11,414},{14,11,416},{14,11,420}\n,{15,11,61},{15,11,74},{15,11,87},{15,11,88},{15,11,94},{15,11,96},{15,11,116},{\n15,11,149},{15,11,154},{16,11,50},{16,11,63},{16,11,73},{17,11,2},{17,11,66},{17\n,11,92},{17,11,103},{17,11,112},{18,11,50},{18,11,54},{18,11,82},{18,11,86},{18,\n11,90},{18,11,111},{18,11,115},{18,11,156},{19,11,40},{19,11,79},{20,11,78},{149\n,11,22},{137,11,170},{134,0,1433},{135,11,1307},{139,11,411},{5,0,189},{7,0,442}\n,{7,0,443},{8,0,281},{12,0,174},{141,0,261},{6,10,216},{7,10,901},{7,10,1343},{\n136,10,493},{5,11,397},{6,11,154},{7,10,341},{7,11,676},{8,11,443},{8,11,609},{9\n,11,24},{9,11,325},{10,11,35},{11,10,219},{11,11,535},{11,11,672},{11,11,1018},{\n12,11,637},{144,11,30},{6,0,2},{7,0,191},{7,0,446},{7,0,1262},{7,0,1737},{8,0,22\n},{8,0,270},{8,0,612},{9,0,4},{9,0,312},{9,0,436},{9,0,626},{10,0,216},{10,0,311\n},{10,0,521},{10,0,623},{11,0,72},{11,0,330},{11,0,455},{12,0,321},{12,0,504},{\n12,0,530},{12,0,543},{13,0,17},{13,0,156},{13,0,334},{14,0,131},{17,0,60},{148,0\n,64},{7,0,354},{10,0,410},{139,0,815},{139,10,130},{7,10,1734},{137,11,631},{10,\n10,115},{11,10,420},{12,0,425},{13,10,404},{14,10,346},{15,0,112},{143,10,54},{6\n,0,60},{6,0,166},{7,0,374},{7,0,670},{7,0,1327},{8,0,411},{8,0,435},{9,0,653},{9\n,0,740},{10,0,385},{11,0,222},{11,0,324},{11,0,829},{140,0,611},{7,0,1611},{13,0\n,14},{15,0,44},{19,0,13},{148,0,76},{133,11,981},{4,11,56},{7,11,1791},{8,11,607\n},{8,11,651},{11,11,465},{11,11,835},{12,11,337},{141,11,480},{5,10,1011},{6,0,\n1478},{136,10,701},{139,0,596},{5,0,206},{134,0,398},{4,10,54},{5,10,666},{7,10,\n1039},{7,10,1130},{9,10,195},{138,10,302},{7,0,50},{9,11,158},{138,11,411},{135,\n11,1120},{6,0,517},{6,10,1669},{7,0,1159},{10,0,621},{139,0,192},{4,0,592},{6,0,\n600},{135,0,1653},{10,0,223},{139,0,645},{136,11,139},{7,0,64},{136,0,245},{142,\n0,278},{6,11,622},{135,11,1030},{136,0,604},{134,0,1502},{138,0,265},{141,11,168\n},{7,0,1763},{140,0,310},{7,10,798},{139,11,719},{7,11,160},{10,11,624},{142,11,\n279},{132,11,363},{7,10,122},{9,10,259},{10,10,84},{11,10,470},{12,10,541},{141,\n10,379},{5,0,129},{6,0,61},{135,0,947},{134,0,1356},{135,11,1191},{13,0,505},{\n141,0,506},{5,10,82},{5,10,131},{7,10,1755},{8,10,31},{9,10,168},{9,10,764},{11,\n0,1000},{139,10,869},{134,0,966},{134,10,605},{134,11,292},{5,11,177},{6,11,616}\n,{7,11,827},{9,11,525},{138,11,656},{135,11,1486},{138,11,31},{5,10,278},{137,10\n,68},{4,10,163},{5,10,201},{5,10,307},{5,10,310},{6,10,335},{7,10,284},{136,10,\n165},{6,0,839},{135,10,1660},{136,10,781},{6,10,33},{135,10,1244},{133,0,637},{4\n,11,161},{133,11,631},{137,0,590},{7,10,1953},{136,10,720},{5,0,280},{7,0,1226},\n{138,10,203},{134,0,1386},{5,0,281},{6,0,1026},{6,10,326},{7,10,677},{137,10,425\n},{7,11,1557},{135,11,1684},{135,0,1064},{9,11,469},{9,11,709},{12,11,512},{14,\n11,65},{145,11,12},{134,0,917},{10,11,229},{11,11,73},{11,11,376},{139,11,433},{\n7,0,555},{7,10,1316},{7,10,1412},{7,10,1839},{9,0,192},{9,10,589},{11,10,241},{\n11,10,676},{11,10,811},{11,10,891},{12,10,140},{12,10,346},{12,10,479},{13,0,30}\n,{13,0,49},{13,10,381},{14,10,188},{15,0,150},{16,0,76},{18,10,30},{148,0,52},{\n149,0,15},{6,0,1882},{6,0,1883},{6,0,1897},{9,0,945},{9,0,1014},{9,0,1020},{12,0\n,823},{12,0,842},{12,0,866},{12,0,934},{15,0,242},{146,0,208},{6,0,965},{134,0,\n1499},{7,0,33},{7,0,120},{8,0,489},{9,0,319},{10,0,820},{11,0,1004},{12,0,379},{\n12,0,679},{13,0,117},{13,0,412},{14,0,25},{15,0,52},{15,0,161},{16,0,47},{149,0,\n2},{6,11,558},{7,11,651},{8,11,421},{9,11,0},{138,11,34},{4,0,937},{5,0,801},{5,\n10,358},{7,0,473},{7,10,1184},{10,10,662},{13,10,212},{13,10,304},{13,10,333},{\n145,10,98},{132,0,877},{6,0,693},{134,0,824},{132,0,365},{7,11,1832},{138,11,374\n},{5,0,7},{139,0,774},{4,0,734},{5,0,662},{134,0,430},{4,0,746},{135,0,1090},{5,\n0,360},{8,0,237},{10,0,231},{147,0,124},{138,11,348},{6,11,6},{7,11,81},{7,11,\n771},{7,11,1731},{9,11,405},{138,11,421},{6,0,740},{137,0,822},{133,10,946},{7,0\n,1485},{136,0,929},{7,10,411},{8,10,631},{9,10,323},{10,10,355},{11,10,491},{12,\n10,143},{12,10,402},{13,10,73},{14,10,408},{15,10,107},{146,10,71},{135,10,590},\n{5,11,881},{133,11,885},{150,11,25},{4,0,852},{5,11,142},{134,11,546},{7,10,1467\n},{8,10,328},{10,10,544},{11,10,955},{13,10,320},{145,10,83},{9,0,17},{10,0,291}\n,{11,10,511},{13,10,394},{14,10,298},{14,10,318},{146,10,103},{5,11,466},{11,11,\n571},{12,11,198},{13,11,283},{14,11,186},{15,11,21},{143,11,103},{134,0,1001},{4\n,11,185},{5,11,257},{5,11,839},{5,11,936},{7,11,171},{9,11,399},{10,11,258},{10,\n11,395},{10,11,734},{11,11,1014},{12,11,23},{13,11,350},{14,11,150},{147,11,6},{\n143,0,35},{132,0,831},{5,10,835},{134,10,483},{4,0,277},{5,0,608},{6,0,493},{7,0\n,457},{7,11,404},{7,11,1377},{7,11,1430},{7,11,2017},{8,11,149},{8,11,239},{8,11\n,512},{8,11,793},{8,11,818},{9,11,474},{9,11,595},{10,11,122},{10,11,565},{10,11\n,649},{10,11,783},{11,11,239},{11,11,295},{11,11,447},{11,11,528},{11,11,639},{\n11,11,800},{11,11,936},{12,0,384},{12,11,25},{12,11,73},{12,11,77},{12,11,157},{\n12,11,316},{12,11,390},{12,11,391},{12,11,394},{12,11,395},{12,11,478},{12,11,\n503},{12,11,592},{12,11,680},{13,11,50},{13,11,53},{13,11,132},{13,11,198},{13,\n11,275},{13,11,322},{13,11,415},{14,11,71},{14,11,257},{14,11,395},{15,11,71},{\n15,11,136},{17,11,123},{18,11,93},{147,11,58},{134,0,1351},{7,0,27},{135,0,316},\n{136,11,712},{136,0,984},{133,0,552},{137,0,264},{132,0,401},{6,0,710},{6,0,1111\n},{134,0,1343},{134,0,1211},{9,0,543},{10,0,524},{11,0,108},{11,0,653},{12,0,524\n},{13,0,123},{14,0,252},{16,0,18},{19,0,38},{20,0,26},{20,0,65},{21,0,3},{151,0,\n11},{4,0,205},{5,0,623},{7,0,104},{8,0,519},{137,0,716},{132,10,677},{4,11,377},\n{152,11,13},{135,11,1673},{7,0,579},{9,0,41},{9,0,244},{9,0,669},{10,0,5},{11,0,\n861},{11,0,951},{139,0,980},{132,0,717},{136,0,1011},{132,0,805},{4,11,180},{135\n,11,1906},{132,10,777},{132,10,331},{132,0,489},{4,11,491},{5,10,747},{134,0,\n1024},{135,11,1182},{4,11,171},{138,11,234},{4,11,586},{7,11,1186},{138,11,631},\n{135,0,892},{135,11,336},{9,11,931},{10,11,334},{148,11,71},{137,0,473},{6,0,864\n},{11,11,926},{140,0,659},{7,0,819},{9,0,26},{9,0,392},{10,0,152},{10,0,226},{11\n,0,19},{12,0,276},{12,0,426},{12,0,589},{13,0,460},{15,0,97},{19,0,48},{148,0,\n104},{135,0,51},{133,10,326},{4,10,691},{146,10,16},{9,0,130},{10,10,680},{10,10\n,793},{11,0,765},{141,10,357},{133,11,765},{6,10,32},{7,10,385},{7,10,757},{7,10\n,1916},{8,0,229},{8,10,94},{8,10,711},{9,10,541},{10,10,162},{10,10,795},{11,10,\n989},{11,10,1010},{12,10,14},{142,10,308},{7,11,474},{137,11,578},{132,0,674},{\n132,0,770},{5,0,79},{7,0,1027},{7,0,1477},{139,0,52},{133,11,424},{134,0,1666},{\n6,0,409},{6,10,349},{6,10,1682},{7,10,1252},{8,10,112},{8,11,714},{9,10,435},{9,\n10,668},{10,10,290},{10,10,319},{10,10,815},{11,10,180},{11,10,837},{12,10,240},\n{13,10,152},{13,10,219},{142,10,158},{5,0,789},{134,0,195},{4,0,251},{4,0,688},{\n7,0,513},{135,0,1284},{132,10,581},{9,11,420},{10,11,269},{10,11,285},{10,11,576\n},{11,11,397},{13,11,175},{145,11,90},{6,10,126},{7,10,573},{8,10,397},{142,10,\n44},{132,11,429},{133,0,889},{4,0,160},{5,0,330},{7,0,1434},{136,0,174},{7,11,18\n},{7,11,699},{7,11,1966},{8,11,752},{9,11,273},{9,11,412},{9,11,703},{10,11,71},\n{10,11,427},{10,11,508},{146,11,97},{6,0,872},{134,0,899},{133,10,926},{134,0,\n1126},{134,0,918},{4,11,53},{5,11,186},{135,11,752},{7,0,268},{136,0,569},{134,0\n,1224},{6,0,1361},{7,10,1232},{137,10,531},{8,11,575},{10,11,289},{139,11,319},{\n133,10,670},{132,11,675},{133,0,374},{135,10,1957},{133,0,731},{11,0,190},{11,11\n,190},{15,0,49},{143,11,49},{4,0,626},{5,0,506},{5,0,642},{6,0,425},{10,0,202},{\n139,0,141},{137,0,444},{7,10,242},{135,10,1942},{6,11,209},{8,11,468},{9,11,210}\n,{11,11,36},{12,11,28},{12,11,630},{13,11,21},{13,11,349},{14,11,7},{145,11,13},\n{4,11,342},{135,11,1179},{5,10,834},{7,10,1202},{8,10,14},{9,10,481},{137,10,880\n},{4,11,928},{133,11,910},{4,11,318},{4,11,496},{7,11,856},{139,11,654},{136,0,\n835},{7,0,1526},{138,10,465},{151,0,17},{135,0,477},{4,10,357},{6,10,172},{7,10,\n143},{137,10,413},{6,0,1374},{138,0,994},{4,10,590},{146,0,76},{7,0,287},{8,0,\n355},{9,0,293},{137,0,743},{134,0,1389},{7,11,915},{8,11,247},{147,11,0},{4,11,\n202},{5,11,382},{6,11,454},{7,11,936},{7,11,1803},{8,11,758},{9,11,375},{9,11,\n895},{10,11,743},{10,11,792},{11,11,978},{11,11,1012},{142,11,109},{5,0,384},{8,\n0,455},{140,0,48},{132,11,390},{5,10,169},{7,10,333},{136,10,45},{5,0,264},{134,\n0,184},{138,11,791},{133,11,717},{132,10,198},{6,11,445},{7,11,332},{137,11,909}\n,{136,0,1001},{4,10,24},{5,10,140},{5,10,185},{7,10,1500},{11,10,565},{139,10,\n838},{134,11,578},{5,0,633},{6,0,28},{135,0,1323},{132,0,851},{136,11,267},{7,0,\n359},{8,0,243},{140,0,175},{4,10,334},{133,10,593},{141,11,87},{136,11,766},{10,\n0,287},{10,11,287},{12,0,138},{140,11,138},{4,0,105},{132,0,740},{140,10,116},{\n134,0,857},{135,11,1841},{6,0,1402},{137,0,819},{132,11,584},{132,10,709},{133,\n10,897},{5,0,224},{13,0,174},{146,0,52},{135,10,1840},{4,10,608},{133,10,497},{\n139,11,60},{4,0,758},{135,0,1649},{4,11,226},{4,11,326},{135,11,1770},{5,11,426}\n,{8,11,30},{9,11,2},{11,11,549},{147,11,122},{135,10,2039},{6,10,540},{136,10,\n136},{4,0,573},{4,10,897},{5,10,786},{136,0,655},{7,0,351},{139,0,128},{133,10,\n999},{4,10,299},{135,10,1004},{133,0,918},{132,11,345},{4,11,385},{7,11,265},{\n135,11,587},{133,10,456},{136,10,180},{6,0,687},{134,0,1537},{4,11,347},{5,11,\n423},{5,11,996},{135,11,1329},{132,10,755},{7,11,1259},{9,11,125},{11,11,65},{\n140,11,285},{5,11,136},{6,11,136},{136,11,644},{134,0,1525},{4,0,1009},{135,0,\n1139},{139,10,338},{132,0,340},{135,10,1464},{8,0,847},{10,0,861},{10,0,876},{10\n,0,889},{10,0,922},{10,0,929},{10,0,933},{12,0,784},{140,0,791},{139,0,176},{9,\n11,134},{10,11,2},{10,11,27},{10,11,333},{11,11,722},{143,11,1},{4,11,433},{133,\n11,719},{5,0,985},{7,0,509},{7,0,529},{145,0,96},{132,0,615},{4,10,890},{5,10,\n805},{5,10,819},{5,10,961},{6,10,396},{6,10,1631},{6,10,1678},{7,10,1967},{7,10,\n2041},{9,10,630},{11,10,8},{11,10,1019},{12,10,176},{13,10,225},{14,10,292},{149\n,10,24},{135,0,1919},{134,0,1131},{144,11,21},{144,11,51},{135,10,1815},{4,0,247\n},{7,10,1505},{10,10,190},{10,10,634},{11,10,792},{12,10,358},{140,10,447},{5,10\n,0},{6,10,536},{7,10,604},{13,10,445},{145,10,126},{4,0,184},{5,0,390},{6,0,337}\n,{7,0,23},{7,0,494},{7,0,618},{7,0,1456},{8,0,27},{8,0,599},{10,0,153},{139,0,\n710},{6,10,232},{6,10,412},{7,10,1074},{8,10,9},{8,10,157},{8,10,786},{9,10,196}\n,{9,10,352},{9,10,457},{10,10,337},{11,10,232},{11,10,877},{12,10,480},{140,10,\n546},{7,10,958},{141,0,38},{4,10,382},{136,10,579},{4,10,212},{135,10,1206},{4,\n11,555},{8,11,536},{138,11,288},{11,11,139},{139,11,171},{9,11,370},{138,11,90},\n{132,0,1015},{134,0,1088},{5,10,655},{135,11,977},{134,0,1585},{17,10,67},{147,\n10,74},{10,0,227},{11,0,497},{11,0,709},{140,0,415},{6,0,360},{7,0,1664},{136,0,\n478},{6,10,231},{7,0,95},{136,10,423},{140,11,65},{4,11,257},{135,11,2031},{135,\n11,1768},{133,10,300},{139,11,211},{136,0,699},{6,10,237},{7,10,611},{8,10,100},\n{9,10,416},{11,10,335},{12,10,173},{146,10,101},{14,0,26},{146,0,150},{6,0,581},\n{135,0,1119},{135,10,1208},{132,0,739},{6,11,83},{6,11,1733},{135,11,1389},{137,\n0,869},{4,0,67},{5,0,422},{7,0,1037},{7,0,1289},{7,0,1555},{9,0,741},{145,0,108}\n,{133,10,199},{12,10,427},{146,10,38},{136,0,464},{142,0,42},{8,11,501},{9,11,\n696},{138,0,96},{134,11,592},{4,0,512},{4,0,966},{5,0,342},{6,0,1855},{8,0,869},\n{8,0,875},{8,0,901},{144,0,26},{8,0,203},{11,0,823},{11,0,846},{12,0,482},{13,0,\n277},{13,0,302},{13,0,464},{14,0,205},{142,0,221},{4,0,449},{133,0,718},{7,11,\n1718},{9,11,95},{9,11,274},{10,11,279},{10,11,317},{10,11,420},{11,11,303},{11,\n11,808},{12,11,134},{12,11,367},{13,11,149},{13,11,347},{14,11,349},{14,11,406},\n{18,11,22},{18,11,89},{18,11,122},{147,11,47},{133,11,26},{4,0,355},{6,0,311},{9\n,0,256},{138,0,404},{132,11,550},{6,10,312},{6,10,1715},{10,0,758},{10,10,584},{\n11,10,546},{11,10,692},{12,10,259},{12,10,295},{13,10,46},{141,10,154},{136,11,\n822},{4,11,902},{5,0,827},{5,11,809},{6,11,122},{135,11,896},{5,0,64},{140,0,581\n},{4,0,442},{6,0,739},{7,0,1047},{7,0,1352},{7,0,1643},{7,11,1911},{9,11,449},{\n10,11,192},{138,11,740},{135,11,262},{132,10,588},{133,11,620},{4,11,34},{5,0,\n977},{5,11,574},{6,0,288},{7,0,528},{7,11,279},{7,11,1624},{136,11,601},{4,10,\n231},{5,10,61},{6,0,1375},{6,10,104},{7,10,729},{7,10,964},{7,10,1658},{140,10,\n414},{6,10,263},{138,10,757},{132,10,320},{4,0,254},{5,11,332},{7,0,1309},{135,\n11,1309},{6,11,261},{8,11,182},{139,11,943},{132,10,225},{6,0,12},{135,0,1219},{\n4,0,275},{6,11,1721},{12,0,376},{141,11,490},{4,11,933},{133,11,880},{4,10,405},\n{6,0,951},{6,0,1109},{6,0,1181},{7,0,154},{7,10,817},{14,10,58},{17,10,37},{146,\n10,124},{5,10,974},{134,0,1520},{134,0,1753},{6,0,369},{6,0,502},{7,0,1036},{8,0\n,348},{9,0,452},{10,0,26},{11,0,224},{11,0,387},{11,0,772},{12,0,95},{12,0,629},\n{13,0,195},{13,0,207},{13,0,241},{14,0,260},{14,0,270},{143,0,140},{132,0,269},{\n5,0,480},{7,0,532},{7,0,1197},{7,0,1358},{8,0,291},{11,0,349},{142,0,396},{5,10,\n235},{7,10,1239},{11,10,131},{140,10,370},{7,10,956},{7,10,1157},{7,10,1506},{7,\n10,1606},{7,10,1615},{7,10,1619},{7,10,1736},{7,10,1775},{8,10,590},{9,10,324},{\n9,10,736},{9,10,774},{9,10,776},{9,10,784},{10,10,567},{10,10,708},{11,10,518},{\n11,10,613},{11,10,695},{11,10,716},{11,10,739},{11,10,770},{11,10,771},{11,10,\n848},{11,10,857},{11,10,931},{11,10,947},{12,10,326},{12,10,387},{12,10,484},{12\n,10,528},{12,10,552},{12,10,613},{13,10,189},{13,10,256},{13,10,340},{13,10,432}\n,{13,10,436},{13,10,440},{13,10,454},{14,10,174},{14,10,220},{14,10,284},{14,10,\n390},{145,10,121},{8,11,598},{9,11,664},{138,11,441},{9,10,137},{138,10,221},{\n133,11,812},{148,0,15},{134,0,1341},{4,11,137},{6,0,1017},{7,11,1178},{135,11,\n1520},{7,10,390},{138,10,140},{7,11,1260},{135,11,1790},{137,11,191},{135,10,\n1144},{6,0,1810},{7,0,657},{8,0,886},{10,0,857},{14,0,440},{144,0,96},{6,11,1661\n},{7,11,1975},{7,11,2009},{7,11,2011},{136,0,533},{6,0,1453},{134,10,464},{132,\n11,715},{5,10,407},{11,10,204},{11,10,243},{11,10,489},{12,10,293},{19,10,37},{\n20,10,73},{150,10,38},{133,11,703},{4,0,211},{5,10,325},{7,0,1483},{8,10,5},{8,\n10,227},{9,10,105},{10,10,585},{140,10,614},{4,0,332},{5,0,335},{6,0,238},{7,0,\n269},{7,0,811},{7,0,1797},{8,0,836},{9,0,507},{141,0,242},{5,11,89},{7,11,1915},\n{9,11,185},{9,11,235},{9,11,496},{10,11,64},{10,11,270},{10,11,403},{10,11,469},\n{10,11,529},{10,11,590},{11,11,140},{11,11,860},{13,11,1},{13,11,422},{14,11,341\n},{14,11,364},{17,11,93},{18,11,113},{19,11,97},{147,11,113},{133,11,695},{5,11,\n6},{6,10,621},{6,11,183},{7,11,680},{7,11,978},{7,11,1013},{7,11,1055},{12,11,\n230},{13,10,504},{13,11,172},{16,0,19},{146,11,29},{136,0,156},{133,0,1009},{6,\n11,29},{139,11,63},{134,0,820},{134,10,218},{7,10,454},{7,10,782},{8,10,768},{\n140,10,686},{5,0,228},{6,0,203},{7,0,156},{8,0,347},{9,0,265},{15,11,8},{18,0,39\n},{18,11,39},{20,0,54},{20,11,54},{21,0,31},{21,11,31},{22,0,3},{22,11,3},{23,0,\n0},{151,11,0},{7,0,1131},{135,0,1468},{144,10,0},{134,0,1276},{10,10,676},{140,\n10,462},{132,11,311},{134,11,1740},{7,11,170},{8,11,90},{8,11,177},{8,11,415},{\n11,11,714},{142,11,281},{134,10,164},{6,0,1792},{138,0,849},{150,10,50},{5,0,291\n},{5,0,318},{7,0,765},{8,11,522},{9,0,389},{12,0,548},{142,11,328},{11,11,91},{\n13,11,129},{15,11,101},{145,11,125},{4,11,494},{6,11,74},{7,11,44},{7,11,407},{8\n,11,551},{12,11,17},{15,11,5},{148,11,11},{4,11,276},{133,11,296},{6,10,343},{7,\n10,195},{7,11,1777},{9,10,226},{10,10,197},{10,10,575},{11,10,502},{139,10,899},\n{10,0,525},{139,0,82},{4,11,7},{5,11,90},{5,11,158},{6,11,542},{7,11,221},{7,11,\n1574},{9,11,490},{10,11,540},{11,11,443},{11,11,757},{142,0,453},{135,0,666},{22\n,10,29},{150,11,29},{4,0,422},{147,10,8},{5,0,355},{145,0,0},{6,0,1873},{7,11,\n588},{9,0,918},{9,11,175},{138,11,530},{143,11,31},{7,10,1125},{9,10,143},{11,0,\n165},{14,10,405},{150,10,21},{9,0,260},{137,0,905},{5,11,872},{6,11,57},{6,11,\n479},{6,11,562},{7,11,471},{7,11,1060},{9,11,447},{9,11,454},{141,11,6},{138,11,\n704},{133,0,865},{5,0,914},{134,0,1625},{133,0,234},{5,11,31},{6,11,614},{7,0,\n1383},{145,11,61},{7,11,1200},{138,11,460},{6,11,424},{135,11,1866},{136,0,306},\n{5,10,959},{12,11,30},{13,11,148},{14,11,87},{14,11,182},{16,11,42},{18,11,92},{\n148,11,70},{6,0,1919},{6,0,1921},{9,0,923},{9,0,930},{9,0,941},{9,0,949},{9,0,\n987},{9,0,988},{9,0,992},{12,0,802},{12,0,815},{12,0,856},{12,0,885},{12,0,893},\n{12,0,898},{12,0,919},{12,0,920},{12,0,941},{12,0,947},{15,0,183},{15,0,185},{15\n,0,189},{15,0,197},{15,0,202},{15,0,233},{15,11,156},{18,0,218},{18,0,219},{146,\n0,233},{135,10,1759},{136,10,173},{5,11,13},{6,11,142},{13,0,163},{13,0,180},{18\n,0,78},{148,0,35},{134,10,266},{6,11,97},{7,11,116},{8,11,322},{8,11,755},{9,11,\n548},{10,11,714},{11,11,884},{141,11,324},{135,0,1312},{9,0,814},{137,11,676},{\n133,0,707},{135,0,1493},{6,0,421},{7,0,61},{7,0,1540},{10,0,11},{138,0,501},{7,\n11,866},{7,11,1163},{12,0,733},{140,0,766},{137,0,341},{142,0,98},{145,11,115},{\n135,11,1111},{136,10,300},{136,0,1014},{8,11,1},{9,11,112},{138,11,326},{132,11,\n730},{5,11,488},{6,11,527},{7,11,489},{7,11,1636},{8,11,121},{8,11,144},{8,11,\n359},{9,11,193},{9,11,241},{9,11,336},{9,11,882},{11,11,266},{11,11,372},{11,11,\n944},{12,11,401},{140,11,641},{6,0,971},{134,0,1121},{6,0,102},{7,0,72},{15,0,\n142},{147,0,67},{151,0,30},{135,0,823},{134,0,1045},{5,10,427},{5,10,734},{7,10,\n478},{136,10,52},{7,0,1930},{11,10,217},{142,10,165},{6,0,1512},{135,0,1870},{9,\n11,31},{10,11,244},{10,11,699},{12,11,149},{141,11,497},{133,11,377},{145,11,101\n},{10,11,158},{13,11,13},{13,11,137},{13,11,258},{14,11,111},{14,11,225},{14,11,\n253},{14,11,304},{14,11,339},{14,11,417},{146,11,33},{6,0,87},{6,10,1734},{7,10,\n20},{7,10,1056},{8,10,732},{9,10,406},{9,10,911},{138,10,694},{134,0,1243},{137,\n0,245},{7,0,68},{8,0,48},{8,0,88},{8,0,582},{8,0,681},{9,0,373},{9,0,864},{11,0,\n157},{11,0,336},{11,0,843},{148,0,27},{8,11,663},{144,11,8},{133,10,613},{4,0,88\n},{5,0,137},{5,0,174},{5,0,777},{6,0,1664},{6,0,1725},{7,0,77},{7,0,426},{7,0,\n1317},{7,0,1355},{8,0,126},{8,0,563},{9,0,523},{9,0,750},{10,0,310},{10,0,836},{\n11,0,42},{11,0,318},{11,0,731},{12,0,68},{12,0,92},{12,0,507},{12,0,692},{13,0,\n81},{13,0,238},{13,0,374},{14,0,436},{18,0,138},{19,0,78},{19,0,111},{20,0,55},{\n20,0,77},{148,0,92},{141,0,418},{4,0,938},{137,0,625},{138,0,351},{5,11,843},{7,\n10,32},{7,10,984},{8,10,85},{8,10,709},{9,10,579},{9,10,847},{9,10,856},{10,10,\n799},{11,10,258},{11,10,1007},{12,10,331},{12,10,615},{13,10,188},{13,10,435},{\n14,10,8},{15,10,165},{16,10,27},{148,10,40},{6,0,1668},{7,0,1499},{8,0,117},{9,0\n,314},{138,0,174},{135,0,707},{132,11,554},{133,11,536},{5,0,403},{5,11,207},{9,\n11,79},{11,11,625},{145,11,7},{132,11,424},{136,11,785},{4,10,167},{135,10,82},{\n9,0,7},{9,11,7},{23,0,6},{151,11,6},{5,10,62},{6,0,282},{6,10,534},{7,10,74},{7,\n10,678},{7,10,684},{7,10,1043},{7,10,1072},{8,10,280},{8,10,541},{8,10,686},{9,\n10,258},{10,10,519},{11,10,252},{140,10,282},{138,10,33},{132,10,359},{4,0,44},{\n5,0,311},{6,0,156},{7,0,639},{7,0,762},{7,0,1827},{9,0,8},{9,0,462},{148,0,83},{\n7,11,769},{9,11,18},{138,11,358},{4,0,346},{4,11,896},{6,11,1777},{7,0,115},{9,0\n,180},{9,0,456},{138,0,363},{133,10,211},{7,0,761},{7,0,1051},{137,0,545},{6,10,\n145},{141,10,336},{7,11,750},{9,11,223},{11,11,27},{11,11,466},{12,11,624},{14,\n11,265},{146,11,61},{6,0,752},{6,0,768},{6,0,1195},{6,0,1254},{6,0,1619},{137,0,\n835},{6,0,1936},{8,0,930},{136,0,960},{132,10,263},{132,11,249},{4,10,916},{140,\n0,653},{4,11,603},{133,11,661},{4,11,11},{6,11,128},{7,11,231},{7,11,1533},{8,0,\n344},{138,11,725},{134,0,1483},{134,0,875},{6,0,185},{7,0,1899},{9,0,875},{139,0\n,673},{15,10,155},{144,10,79},{4,10,599},{6,10,1634},{7,0,93},{7,0,210},{7,0,\n1223},{7,10,67},{7,10,691},{7,10,979},{7,10,1697},{8,0,451},{8,0,460},{8,10,207}\n,{8,10,214},{8,10,231},{8,10,294},{8,10,336},{8,10,428},{8,10,471},{8,10,622},{8\n,10,626},{8,10,679},{8,10,759},{8,10,829},{9,10,11},{9,10,246},{9,10,484},{9,10,\n573},{9,10,706},{9,10,762},{9,10,798},{9,10,855},{9,10,870},{9,10,912},{10,10,\n303},{10,10,335},{10,10,424},{10,10,461},{10,10,543},{10,10,759},{10,10,814},{11\n,0,353},{11,0,475},{11,10,59},{11,10,235},{11,10,590},{11,10,929},{11,10,963},{\n11,10,987},{12,10,114},{12,10,182},{12,10,226},{12,10,332},{12,10,439},{12,10,\n575},{12,10,598},{12,10,675},{13,10,8},{13,10,125},{13,10,194},{13,10,287},{14,\n10,197},{14,10,383},{15,10,53},{17,10,63},{19,10,46},{19,10,98},{19,10,106},{148\n,10,85},{132,11,476},{4,0,327},{5,0,478},{7,0,1332},{136,0,753},{5,0,1020},{133,\n0,1022},{135,11,1807},{4,0,103},{133,0,401},{4,0,499},{135,0,1421},{10,0,207},{\n13,0,164},{147,10,126},{9,11,20},{10,11,324},{139,11,488},{132,0,96},{9,11,280},\n{138,11,134},{135,0,968},{133,10,187},{135,10,1286},{5,11,112},{6,11,103},{134,\n11,150},{4,10,215},{8,0,914},{9,10,38},{10,0,3},{11,10,23},{11,10,127},{139,10,\n796},{135,0,399},{6,0,563},{137,0,224},{6,0,704},{134,0,1214},{4,11,708},{8,11,\n15},{9,11,50},{9,11,386},{11,11,18},{11,11,529},{140,11,228},{4,11,563},{7,11,\n109},{7,11,592},{7,11,637},{7,11,770},{7,11,1701},{8,11,436},{8,11,463},{9,11,60\n},{9,11,335},{9,11,904},{10,11,73},{11,11,434},{12,11,585},{13,11,331},{18,11,\n110},{148,11,60},{134,0,1559},{132,11,502},{6,11,347},{138,11,161},{4,11,33},{5,\n11,102},{5,11,500},{6,11,284},{7,11,1079},{7,11,1423},{7,11,1702},{8,11,470},{9,\n11,554},{9,11,723},{139,11,333},{7,11,246},{135,11,840},{6,11,10},{8,11,571},{9,\n11,739},{143,11,91},{5,11,626},{8,0,861},{10,0,905},{12,0,730},{140,0,789},{134,\n0,946},{5,0,746},{12,0,333},{12,11,333},{14,0,332},{142,11,332},{5,11,18},{6,11,\n526},{13,11,24},{13,11,110},{19,11,5},{147,11,44},{4,0,910},{5,0,832},{135,10,\n2002},{10,11,768},{139,11,787},{4,11,309},{5,11,462},{7,11,970},{135,11,1097},{4\n,10,28},{5,10,440},{7,10,248},{11,10,833},{140,10,344},{134,10,1654},{6,0,632},{\n6,0,652},{6,0,1272},{6,0,1384},{134,0,1560},{134,11,1704},{5,10,853},{134,0,1393\n},{6,10,249},{7,10,1234},{139,10,573},{5,11,86},{7,11,743},{9,11,85},{10,11,281}\n,{10,11,432},{11,11,490},{12,11,251},{13,11,118},{14,11,378},{146,11,143},{5,11,\n524},{133,11,744},{134,0,1514},{10,0,201},{142,0,319},{7,0,717},{7,10,392},{8,10\n,20},{8,10,172},{8,10,690},{9,10,383},{9,10,845},{10,0,510},{11,10,293},{11,10,\n832},{11,10,920},{11,10,984},{141,10,221},{134,0,1381},{5,10,858},{133,10,992},{\n8,0,528},{137,0,348},{10,11,107},{140,11,436},{4,0,20},{133,0,616},{134,0,1251},\n{132,11,927},{10,11,123},{12,11,670},{13,11,371},{14,11,142},{146,11,94},{134,0,\n1163},{7,11,1149},{137,11,156},{134,0,307},{133,11,778},{7,0,1091},{135,0,1765},\n{5,11,502},{6,10,268},{137,10,62},{8,11,196},{10,11,283},{139,11,406},{4,0,26},{\n5,0,429},{6,0,245},{7,0,704},{7,0,1379},{135,0,1474},{133,11,855},{132,0,881},{4\n,0,621},{135,11,1596},{7,11,1400},{9,11,446},{138,11,45},{6,0,736},{138,10,106},\n{133,0,542},{134,0,348},{133,0,868},{136,0,433},{135,0,1495},{138,0,771},{6,10,\n613},{136,10,223},{138,0,215},{141,0,124},{136,11,391},{135,11,172},{132,10,670}\n,{140,0,55},{9,10,40},{139,10,136},{7,0,62},{147,0,112},{132,0,856},{132,11,568}\n,{11,10,259},{140,0,270},{8,0,572},{137,0,698},{4,11,732},{9,10,310},{137,10,682\n},{142,10,296},{134,0,939},{136,11,733},{135,11,1435},{7,10,1401},{135,10,1476},\n{4,10,296},{6,0,352},{7,10,401},{7,10,1410},{7,10,1594},{7,10,1674},{8,10,63},{8\n,10,660},{137,10,74},{4,11,428},{133,11,668},{4,10,139},{4,10,388},{140,10,188},\n{7,11,2015},{140,11,665},{132,0,647},{146,0,10},{138,0,220},{142,0,464},{132,0,\n109},{134,0,1746},{4,10,747},{6,0,515},{6,11,1623},{6,11,1681},{7,10,649},{7,10,\n1479},{135,10,1583},{133,10,232},{135,0,566},{137,10,887},{4,0,40},{10,0,67},{11\n,0,117},{11,0,768},{139,0,935},{132,0,801},{7,0,992},{8,0,301},{9,0,722},{12,0,\n63},{13,0,29},{14,0,161},{143,0,18},{139,0,923},{6,11,1748},{8,11,715},{9,11,802\n},{10,11,46},{10,11,819},{13,11,308},{14,11,351},{14,11,363},{146,11,67},{137,11\n,745},{4,10,14},{7,0,1145},{7,10,1801},{10,10,748},{141,10,458},{4,11,63},{5,11,\n347},{134,11,474},{135,0,568},{4,10,425},{7,11,577},{7,11,1432},{9,11,475},{9,11\n,505},{9,11,526},{9,11,609},{9,11,689},{9,11,726},{9,11,735},{9,11,738},{10,11,\n556},{10,11,674},{10,11,684},{11,11,89},{11,11,202},{11,11,272},{11,11,380},{11,\n11,415},{11,11,505},{11,11,537},{11,11,550},{11,11,562},{11,11,640},{11,11,667},\n{11,11,688},{11,11,847},{11,11,927},{11,11,930},{11,11,940},{12,11,144},{12,11,\n325},{12,11,329},{12,11,389},{12,11,403},{12,11,451},{12,11,515},{12,11,604},{12\n,11,616},{12,11,626},{13,11,66},{13,11,131},{13,11,167},{13,11,236},{13,11,368},\n{13,11,411},{13,11,434},{13,11,453},{13,11,461},{13,11,474},{14,11,59},{14,11,60\n},{14,11,139},{14,11,152},{14,11,276},{14,11,353},{14,11,402},{15,11,28},{15,11,\n81},{15,11,123},{15,11,152},{18,11,136},{148,11,88},{137,0,247},{135,11,1622},{9\n,11,544},{11,11,413},{144,11,25},{4,0,645},{6,10,1768},{7,0,825},{135,11,89},{\n140,0,328},{5,10,943},{134,10,1779},{134,0,1363},{5,10,245},{6,10,576},{7,10,582\n},{136,10,225},{134,0,1280},{5,11,824},{133,11,941},{7,11,440},{8,11,230},{139,\n11,106},{5,0,28},{6,0,204},{10,0,320},{10,0,583},{13,0,502},{14,0,72},{14,0,274}\n,{14,0,312},{14,0,344},{15,0,159},{16,0,62},{16,0,69},{17,0,30},{18,0,42},{18,0,\n53},{18,0,84},{18,0,140},{19,0,68},{19,0,85},{20,0,5},{20,0,45},{20,0,101},{22,0\n,7},{150,0,20},{4,0,558},{6,0,390},{7,0,162},{7,0,689},{9,0,360},{138,0,653},{\n134,0,764},{6,0,862},{137,0,833},{5,0,856},{6,0,1672},{6,0,1757},{134,0,1781},{5\n,0,92},{10,0,736},{140,0,102},{6,0,1927},{6,0,1944},{8,0,924},{8,0,948},{10,0,\n967},{138,0,978},{134,0,1479},{5,0,590},{8,0,360},{9,0,213},{138,0,63},{134,0,\n1521},{6,0,709},{134,0,891},{132,10,443},{13,0,477},{14,0,120},{148,0,61},{4,11,\n914},{5,11,800},{133,11,852},{10,11,54},{141,11,115},{4,11,918},{133,11,876},{\n139,11,152},{4,11,92},{133,11,274},{135,11,1901},{9,11,800},{10,11,693},{11,11,\n482},{11,11,734},{139,11,789},{4,10,298},{137,0,483},{6,0,1213},{141,11,498},{\n135,11,1451},{133,11,743},{4,0,1022},{10,0,1000},{12,0,957},{12,0,980},{12,0,\n1013},{14,0,481},{144,0,116},{4,11,49},{7,11,280},{7,11,1633},{8,0,503},{145,0,\n29},{135,0,1712},{134,0,466},{136,11,47},{5,10,164},{7,10,121},{142,10,189},{7,\n10,812},{7,10,1261},{7,10,1360},{9,10,632},{140,10,352},{139,10,556},{132,0,731}\n,{5,11,272},{5,11,908},{5,11,942},{7,11,1008},{7,11,1560},{8,11,197},{9,11,47},{\n11,11,538},{139,11,742},{4,10,172},{9,10,611},{10,10,436},{12,10,673},{141,10,\n255},{133,10,844},{10,0,484},{11,0,754},{12,0,457},{14,0,171},{14,0,389},{146,0,\n153},{9,10,263},{10,10,147},{138,10,492},{137,11,891},{138,0,241},{133,10,537},{\n6,0,2005},{136,0,964},{137,10,842},{151,11,8},{4,11,407},{132,11,560},{135,11,\n1884},{6,0,1100},{134,0,1242},{135,0,954},{5,10,230},{5,10,392},{6,10,420},{9,10\n,568},{140,10,612},{4,11,475},{11,11,35},{11,11,90},{13,11,7},{13,11,71},{13,11,\n177},{142,11,422},{136,11,332},{135,0,1958},{6,0,549},{8,0,34},{8,0,283},{9,0,\n165},{138,0,475},{10,0,952},{12,0,966},{140,0,994},{5,0,652},{5,0,701},{135,0,\n449},{4,0,655},{7,0,850},{17,0,75},{146,0,137},{4,0,146},{5,10,41},{7,0,1618},{7\n,10,1459},{7,10,1469},{7,10,1859},{8,0,670},{9,10,549},{139,10,905},{133,10,696}\n,{6,0,159},{6,0,364},{7,0,516},{137,0,518},{135,0,1439},{6,11,222},{7,11,636},{7\n,11,1620},{8,11,409},{9,11,693},{139,11,77},{13,0,151},{141,11,45},{4,10,771},{4\n,11,336},{134,0,1027},{139,11,392},{10,11,121},{11,11,175},{149,11,16},{8,0,950}\n,{138,0,983},{133,10,921},{135,0,993},{6,10,180},{7,10,1137},{8,10,751},{139,10,\n805},{7,0,501},{9,0,111},{10,0,141},{11,0,332},{13,0,43},{13,0,429},{14,0,130},{\n14,0,415},{145,0,102},{4,10,183},{5,11,882},{7,10,271},{11,10,824},{11,10,952},{\n13,10,278},{13,10,339},{13,10,482},{14,10,424},{148,10,99},{4,10,19},{5,10,477},\n{5,10,596},{6,10,505},{7,10,1221},{11,10,907},{12,10,209},{141,10,214},{135,10,\n1215},{133,0,452},{132,11,426},{5,0,149},{136,0,233},{133,0,935},{6,11,58},{7,11\n,654},{7,11,745},{7,11,1969},{8,11,240},{8,11,675},{9,11,479},{9,11,731},{10,11,\n330},{10,11,593},{10,11,817},{11,11,32},{11,11,133},{11,11,221},{145,11,68},{7,\n11,102},{9,11,538},{12,0,582},{146,0,131},{136,0,801},{134,10,1645},{132,0,70},{\n6,10,92},{6,10,188},{7,10,1269},{7,10,1524},{7,10,1876},{10,10,228},{139,10,1020\n},{4,10,459},{133,10,966},{138,0,369},{12,10,330},{144,0,36},{141,11,366},{6,10,\n18},{7,0,721},{7,10,932},{8,10,757},{9,10,54},{9,10,65},{9,10,844},{10,0,236},{\n10,10,113},{10,10,315},{10,10,798},{11,10,153},{12,0,204},{12,10,151},{12,10,392\n},{12,10,666},{142,10,248},{7,0,241},{8,10,548},{9,10,532},{10,0,430},{10,10,117\n},{11,10,351},{11,10,375},{143,10,23},{134,10,1742},{133,10,965},{133,11,566},{6\n,11,48},{135,11,63},{134,10,182},{10,10,65},{10,10,488},{138,10,497},{6,11,114},\n{7,11,1224},{7,11,1556},{136,11,3},{134,0,1817},{8,11,576},{137,11,267},{6,0,\n1078},{144,0,16},{9,10,588},{138,10,260},{138,0,1021},{5,0,406},{134,0,2022},{\n133,11,933},{6,0,69},{135,0,117},{7,0,1830},{136,11,427},{4,0,432},{135,0,824},{\n134,10,1786},{133,0,826},{139,11,67},{133,11,759},{135,10,308},{137,0,816},{133,\n0,1000},{4,0,297},{6,0,529},{7,0,152},{7,0,713},{7,0,1845},{8,0,710},{8,0,717},{\n12,0,639},{140,0,685},{7,0,423},{136,10,588},{136,10,287},{136,0,510},{134,0,\n1048},{6,0,618},{7,11,56},{7,11,1989},{8,11,337},{8,11,738},{9,11,600},{10,11,\n483},{12,11,37},{13,11,447},{142,11,92},{4,0,520},{135,0,575},{8,0,990},{138,0,\n977},{135,11,774},{9,11,347},{11,11,24},{140,11,170},{136,11,379},{140,10,290},{\n132,11,328},{4,0,321},{134,0,569},{4,11,101},{135,11,1171},{5,11,833},{7,0,723},\n{7,0,1135},{136,11,744},{7,10,719},{8,10,809},{136,10,834},{8,0,921},{136,10,796\n},{5,10,210},{6,10,213},{7,10,60},{10,10,364},{139,10,135},{5,0,397},{5,10,607},\n{6,0,154},{7,0,676},{8,0,443},{8,0,609},{8,10,326},{8,10,490},{9,0,24},{9,0,325}\n,{10,0,35},{11,0,535},{11,0,672},{11,0,1018},{12,0,637},{144,0,30},{4,10,701},{5\n,10,472},{6,11,9},{6,11,397},{7,11,53},{7,11,1742},{9,10,758},{10,11,632},{11,11\n,828},{140,11,146},{135,10,380},{135,10,1947},{148,11,109},{10,10,278},{138,11,\n278},{134,0,856},{4,10,386},{7,0,139},{8,10,405},{8,10,728},{9,10,497},{11,10,\n110},{11,10,360},{15,10,37},{144,10,84},{141,0,282},{133,0,981},{5,0,288},{7,10,\n1452},{7,10,1480},{8,10,634},{140,10,472},{7,0,1890},{8,11,367},{10,11,760},{14,\n11,79},{20,11,17},{152,11,0},{4,10,524},{136,10,810},{4,0,56},{7,0,1791},{8,0,\n607},{8,0,651},{11,0,465},{11,0,835},{12,0,337},{141,0,480},{10,10,238},{141,10,\n33},{11,11,417},{12,11,223},{140,11,265},{9,0,158},{10,0,411},{140,0,261},{133,\n10,532},{133,10,997},{12,11,186},{12,11,292},{14,11,100},{146,11,70},{6,0,1403},\n{136,0,617},{134,0,1205},{139,0,563},{4,0,242},{134,0,333},{4,11,186},{5,11,157}\n,{8,11,168},{138,11,6},{132,0,369},{133,11,875},{5,10,782},{5,10,829},{134,10,\n1738},{134,0,622},{135,11,1272},{6,0,1407},{7,11,111},{136,11,581},{7,10,1823},{\n139,10,693},{7,0,160},{10,0,624},{142,0,279},{132,0,363},{10,11,589},{12,11,111}\n,{13,11,260},{14,11,82},{18,11,63},{147,11,45},{7,11,1364},{7,11,1907},{141,11,\n158},{4,11,404},{4,11,659},{135,11,675},{13,11,211},{14,11,133},{14,11,204},{15,\n11,64},{15,11,69},{15,11,114},{16,11,10},{19,11,23},{19,11,35},{19,11,39},{19,11\n,51},{19,11,71},{19,11,75},{152,11,15},{4,10,78},{5,10,96},{5,10,182},{7,10,1724\n},{7,10,1825},{10,10,394},{10,10,471},{11,10,532},{14,10,340},{145,10,88},{135,\n10,1964},{133,11,391},{11,11,887},{14,11,365},{142,11,375},{5,11,540},{6,11,1697\n},{7,11,222},{136,11,341},{134,11,78},{9,0,601},{9,0,619},{10,0,505},{10,0,732},\n{11,0,355},{140,0,139},{134,0,292},{139,0,174},{5,0,177},{6,0,616},{7,0,827},{9,\n0,525},{138,0,656},{6,10,215},{7,10,1028},{7,10,1473},{7,10,1721},{9,10,424},{10\n,0,31},{138,10,779},{135,10,584},{136,11,293},{134,0,685},{135,11,1868},{133,11,\n460},{6,10,67},{7,0,647},{7,10,1630},{9,10,354},{9,10,675},{10,10,830},{14,10,80\n},{145,10,80},{4,0,161},{133,0,631},{6,10,141},{7,10,225},{9,10,59},{9,10,607},{\n10,10,312},{11,10,687},{12,10,555},{13,10,373},{13,10,494},{148,10,58},{7,11,965\n},{7,11,1460},{135,11,1604},{136,10,783},{134,11,388},{4,11,511},{6,0,722},{6,0,\n1267},{9,11,333},{9,11,379},{10,11,602},{11,11,441},{11,11,723},{11,11,976},{140\n,11,357},{134,0,1797},{135,0,1684},{5,11,938},{8,11,707},{9,0,469},{9,0,709},{12\n,0,512},{14,0,65},{145,0,12},{7,0,1230},{136,0,531},{10,0,229},{11,0,73},{11,0,\n376},{139,0,433},{12,0,268},{12,0,640},{142,0,119},{7,10,430},{139,10,46},{6,0,\n558},{7,0,651},{8,0,421},{9,0,0},{10,0,34},{139,0,1008},{5,10,602},{6,0,106},{7,\n0,1786},{7,0,1821},{7,10,2018},{9,0,102},{9,0,763},{137,10,418},{5,0,65},{6,0,\n416},{7,0,1720},{7,0,1924},{8,10,677},{10,0,109},{11,0,14},{11,0,70},{11,0,569},\n{11,0,735},{15,0,153},{148,0,80},{135,11,1625},{137,11,772},{136,0,595},{6,11,\n469},{7,11,1709},{138,11,515},{7,0,1832},{138,0,374},{9,0,106},{9,0,163},{9,0,\n296},{10,0,167},{10,0,172},{10,0,777},{139,0,16},{6,0,6},{7,0,81},{7,0,771},{7,0\n,1731},{9,0,405},{138,0,421},{4,11,500},{135,11,938},{5,11,68},{134,11,383},{5,0\n,881},{133,0,885},{6,0,854},{6,0,1132},{6,0,1495},{6,0,1526},{6,0,1533},{134,0,\n1577},{4,11,337},{6,11,353},{7,11,1934},{8,11,488},{137,11,429},{7,11,236},{7,11\n,1795},{8,11,259},{9,11,135},{9,11,177},{10,11,825},{11,11,115},{11,11,370},{11,\n11,405},{11,11,604},{12,11,10},{12,11,667},{12,11,669},{13,11,76},{14,11,310},{\n15,11,76},{15,11,147},{148,11,23},{5,0,142},{134,0,546},{4,11,15},{5,11,22},{6,\n11,244},{7,11,40},{7,11,200},{7,11,906},{7,11,1199},{9,11,616},{10,11,716},{11,\n11,635},{11,11,801},{140,11,458},{5,0,466},{7,10,329},{11,0,571},{12,0,198},{13,\n0,283},{14,0,186},{15,0,21},{143,0,103},{4,0,185},{5,0,257},{5,0,839},{5,0,936},\n{7,11,1735},{9,0,399},{10,0,258},{10,0,395},{10,0,734},{11,0,1014},{12,0,23},{13\n,0,350},{14,0,150},{147,0,6},{12,11,36},{141,11,337},{5,11,598},{7,11,791},{8,11\n,108},{137,11,123},{132,10,469},{7,0,404},{7,0,1377},{7,0,1430},{7,0,2017},{8,0,\n149},{8,0,239},{8,0,512},{8,0,793},{8,0,818},{9,0,474},{9,0,595},{10,0,122},{10,\n0,565},{10,0,649},{10,0,783},{11,0,239},{11,0,295},{11,0,447},{11,0,528},{11,0,\n639},{11,0,800},{12,0,25},{12,0,77},{12,0,157},{12,0,256},{12,0,316},{12,0,390},\n{12,0,391},{12,0,395},{12,0,478},{12,0,503},{12,0,592},{12,0,680},{13,0,50},{13,\n0,53},{13,0,132},{13,0,198},{13,0,322},{13,0,415},{13,0,511},{14,0,71},{14,0,395\n},{15,0,71},{15,0,136},{17,0,123},{18,0,93},{147,0,58},{136,0,712},{134,10,1743}\n,{5,10,929},{6,10,340},{8,10,376},{136,10,807},{6,0,1848},{8,0,860},{10,0,856},{\n10,0,859},{10,0,925},{10,0,941},{140,0,762},{6,0,629},{6,0,906},{9,0,810},{140,0\n,652},{5,10,218},{7,10,1610},{138,10,83},{7,10,1512},{135,10,1794},{4,0,377},{4,\n11,155},{7,11,1689},{11,10,0},{16,10,78},{152,0,13},{4,11,164},{5,11,151},{5,11,\n730},{5,11,741},{7,11,498},{7,11,870},{7,11,1542},{12,11,213},{14,11,36},{14,11,\n391},{17,11,111},{18,11,6},{18,11,46},{18,11,151},{19,11,36},{20,11,32},{20,11,\n56},{20,11,69},{20,11,102},{21,11,4},{22,11,8},{22,11,10},{22,11,14},{150,11,31}\n,{5,10,571},{135,0,1842},{4,10,455},{4,11,624},{135,11,1752},{134,0,1501},{4,11,\n492},{5,11,451},{6,10,161},{7,10,372},{137,10,597},{132,10,349},{4,0,180},{135,0\n,1906},{135,11,835},{141,11,70},{132,0,491},{137,10,751},{6,10,432},{139,10,322}\n,{4,0,171},{138,0,234},{6,11,113},{135,11,436},{4,0,586},{7,0,1186},{138,0,631},\n{5,10,468},{10,10,325},{11,10,856},{12,10,345},{143,10,104},{5,10,223},{10,11,\n592},{10,11,753},{12,11,317},{12,11,355},{12,11,465},{12,11,469},{12,11,560},{12\n,11,578},{141,11,243},{132,10,566},{135,11,520},{4,10,59},{135,10,1394},{6,10,\n436},{139,10,481},{4,10,48},{5,10,271},{7,10,953},{7,11,1878},{9,0,931},{10,0,\n334},{148,0,71},{5,10,610},{8,10,457},{139,0,170},{133,10,755},{6,0,1587},{135,\n10,1217},{4,10,197},{149,11,26},{133,11,585},{137,11,521},{133,0,765},{133,10,\n217},{139,11,586},{133,0,424},{9,11,752},{12,11,610},{13,11,431},{16,11,59},{146\n,11,109},{136,0,714},{4,11,307},{135,0,685},{9,0,420},{10,0,269},{10,0,285},{10,\n0,576},{11,0,397},{13,0,175},{145,0,90},{132,0,429},{133,11,964},{9,11,463},{138\n,11,595},{7,0,18},{7,0,699},{7,0,1966},{8,0,752},{9,0,273},{9,0,412},{9,0,703},{\n10,0,71},{10,0,427},{138,0,508},{4,10,165},{7,10,1398},{135,10,1829},{4,0,53},{5\n,0,186},{7,0,752},{7,0,828},{142,0,116},{8,0,575},{10,0,289},{139,0,319},{132,0,\n675},{134,0,1424},{4,11,75},{5,11,180},{6,11,500},{7,11,58},{7,11,710},{138,11,\n645},{133,11,649},{6,11,276},{7,11,282},{7,11,879},{7,11,924},{8,11,459},{9,11,\n599},{9,11,754},{11,11,574},{12,11,128},{12,11,494},{13,11,52},{13,11,301},{15,\n11,30},{143,11,132},{6,0,647},{134,0,1095},{5,10,9},{7,10,297},{7,10,966},{140,\n10,306},{132,11,200},{134,0,1334},{5,10,146},{6,10,411},{138,10,721},{6,0,209},{\n6,0,1141},{6,0,1288},{8,0,468},{9,0,210},{11,0,36},{12,0,28},{12,0,630},{13,0,21\n},{13,0,349},{14,0,7},{145,0,13},{6,10,177},{135,10,467},{4,0,342},{135,0,1179},\n{10,11,454},{140,11,324},{4,0,928},{133,0,910},{6,11,225},{7,0,1838},{137,11,211\n},{16,0,101},{20,0,115},{20,0,118},{148,0,122},{4,0,496},{135,0,856},{4,0,318},{\n7,11,718},{11,0,654},{139,11,102},{8,11,58},{9,11,724},{11,11,809},{13,11,113},{\n145,11,72},{5,10,200},{6,11,345},{135,11,1247},{8,11,767},{8,11,803},{9,11,301},\n{137,11,903},{7,0,915},{7,11,1949},{8,0,247},{8,11,674},{147,0,0},{4,0,202},{5,0\n,382},{6,0,454},{7,0,936},{7,0,1803},{8,0,758},{9,0,375},{9,0,895},{10,0,743},{\n10,0,792},{11,0,978},{11,0,1012},{142,0,109},{7,0,1150},{7,0,1425},{7,0,1453},{\n140,0,513},{134,11,259},{138,0,791},{11,0,821},{12,0,110},{12,0,153},{18,0,41},{\n150,0,19},{134,10,481},{132,0,796},{6,0,445},{8,11,254},{137,0,909},{10,0,776},{\n13,0,345},{142,0,425},{4,10,84},{7,10,1482},{10,10,76},{138,10,142},{135,11,742}\n,{5,10,1015},{134,0,578},{4,10,315},{5,10,507},{6,0,1387},{135,10,1370},{4,0,438\n},{133,0,555},{136,0,766},{133,11,248},{134,10,1722},{4,11,116},{5,11,95},{5,11,\n445},{7,11,1688},{8,11,29},{9,11,272},{11,11,509},{139,11,915},{135,0,541},{133,\n11,543},{8,10,222},{8,10,476},{9,10,238},{11,10,516},{11,10,575},{15,10,109},{\n146,10,100},{6,0,880},{134,0,1191},{5,11,181},{136,11,41},{134,0,1506},{132,11,\n681},{7,11,25},{8,11,202},{138,11,536},{139,0,983},{137,0,768},{132,0,584},{9,11\n,423},{140,11,89},{8,11,113},{9,11,877},{10,11,554},{11,11,83},{12,11,136},{147,\n11,109},{7,10,706},{7,10,1058},{138,10,538},{133,11,976},{4,11,206},{135,11,746}\n,{136,11,526},{140,0,737},{11,10,92},{11,10,196},{11,10,409},{11,10,450},{11,10,\n666},{11,10,777},{12,10,262},{13,10,385},{13,10,393},{15,10,115},{16,10,45},{145\n,10,82},{4,0,226},{4,0,326},{4,11,319},{5,11,699},{7,0,1770},{138,11,673},{6,10,\n40},{135,10,1781},{5,0,426},{8,0,30},{9,0,2},{11,0,549},{147,0,122},{6,0,1161},{\n134,0,1329},{138,10,97},{6,10,423},{7,10,665},{135,10,1210},{7,11,13},{8,11,226}\n,{10,11,537},{11,11,570},{11,11,605},{11,11,799},{11,11,804},{12,11,85},{12,11,\n516},{12,11,623},{13,11,112},{13,11,361},{14,11,77},{14,11,78},{17,11,28},{147,\n11,110},{132,11,769},{132,11,551},{132,11,728},{147,0,117},{9,11,57},{9,11,459},\n{10,11,425},{11,11,119},{12,11,184},{12,11,371},{13,11,358},{145,11,51},{5,11,\n188},{5,11,814},{8,11,10},{9,11,421},{9,11,729},{10,11,609},{139,11,689},{134,11\n,624},{135,11,298},{135,0,462},{4,0,345},{139,10,624},{136,10,574},{4,0,385},{7,\n0,265},{135,0,587},{4,11,528},{134,0,808},{133,0,398},{132,10,354},{4,0,347},{5,\n0,423},{5,0,996},{135,0,1329},{135,10,1558},{7,0,1259},{9,0,125},{139,0,65},{5,0\n,136},{6,0,136},{136,0,644},{5,11,104},{6,11,173},{135,11,1631},{135,0,469},{133\n,10,830},{4,0,278},{5,0,465},{135,0,1367},{7,11,810},{8,11,138},{8,11,342},{9,11\n,84},{10,11,193},{11,11,883},{140,11,359},{5,10,496},{135,10,203},{4,0,433},{133\n,0,719},{6,10,547},{134,11,95},{5,10,88},{137,10,239},{6,11,406},{10,11,409},{10\n,11,447},{11,11,44},{140,11,100},{134,0,1423},{7,10,650},{135,10,1310},{134,0,\n749},{135,11,1243},{135,0,1363},{6,0,381},{7,0,645},{7,0,694},{7,10,1076},{8,0,\n546},{9,10,80},{11,10,78},{11,10,421},{11,10,534},{140,10,545},{134,11,1636},{\n135,11,1344},{7,10,274},{11,10,479},{11,10,507},{140,0,277},{4,11,282},{6,0,705}\n,{6,0,783},{6,0,1275},{6,0,1481},{7,11,1034},{11,11,398},{11,11,634},{12,11,1},{\n12,11,79},{12,11,544},{14,11,237},{17,11,10},{146,11,20},{134,0,453},{4,0,555},{\n4,10,497},{7,10,1584},{8,0,536},{10,0,288},{139,0,1005},{5,11,118},{5,11,499},{6\n,11,476},{7,11,600},{7,11,888},{135,11,1096},{138,0,987},{7,0,1107},{7,10,261},{\n7,10,1115},{7,10,1354},{7,10,1588},{7,10,1705},{7,10,1902},{9,10,465},{10,10,248\n},{10,10,349},{10,10,647},{11,10,527},{11,10,660},{11,10,669},{12,10,529},{141,\n10,305},{7,11,296},{7,11,596},{8,11,560},{8,11,586},{9,11,612},{11,11,100},{11,\n11,304},{12,11,46},{13,11,89},{14,11,112},{145,11,122},{9,0,370},{138,0,90},{136\n,10,13},{132,0,860},{7,10,642},{8,10,250},{11,10,123},{11,10,137},{13,10,48},{\n142,10,95},{135,10,1429},{137,11,321},{132,0,257},{135,0,2031},{7,0,1768},{7,11,\n1599},{7,11,1723},{8,11,79},{8,11,106},{8,11,190},{8,11,302},{8,11,383},{9,11,\n119},{9,11,233},{9,11,298},{9,11,419},{9,11,471},{10,11,181},{10,11,406},{11,11,\n57},{11,11,85},{11,11,120},{11,11,177},{11,11,296},{11,11,382},{11,11,454},{11,\n11,758},{11,11,999},{12,11,27},{12,11,98},{12,11,131},{12,11,245},{12,11,312},{\n12,11,446},{12,11,454},{13,11,25},{13,11,98},{13,11,426},{13,11,508},{14,11,6},{\n14,11,163},{14,11,272},{14,11,277},{14,11,370},{15,11,95},{15,11,138},{15,11,167\n},{17,11,18},{17,11,38},{20,11,96},{149,11,32},{5,11,722},{134,11,1759},{145,11,\n16},{6,0,1071},{134,0,1561},{10,10,545},{140,10,301},{6,0,83},{6,0,1733},{135,0,\n1389},{4,0,835},{135,0,1818},{133,11,258},{4,10,904},{133,10,794},{134,0,2006},{\n5,11,30},{7,11,495},{8,11,134},{9,11,788},{140,11,438},{135,11,2004},{137,0,696}\n,{5,11,50},{6,11,439},{7,11,780},{135,11,1040},{7,11,772},{7,11,1104},{7,11,1647\n},{11,11,269},{11,11,539},{11,11,607},{11,11,627},{11,11,706},{11,11,975},{12,11\n,248},{12,11,311},{12,11,434},{12,11,600},{12,11,622},{13,11,297},{13,11,367},{\n13,11,485},{14,11,69},{14,11,409},{143,11,108},{5,11,1},{6,11,81},{138,11,520},{\n7,0,1718},{9,0,95},{9,0,274},{10,0,279},{10,0,317},{10,0,420},{11,0,303},{11,0,\n808},{12,0,134},{12,0,367},{13,0,149},{13,0,347},{14,0,349},{14,0,406},{18,0,22}\n,{18,0,89},{18,0,122},{147,0,47},{5,11,482},{8,11,98},{9,11,172},{10,11,222},{10\n,11,700},{10,11,822},{11,11,302},{11,11,778},{12,11,50},{12,11,127},{12,11,396},\n{13,11,62},{13,11,328},{14,11,122},{147,11,72},{7,10,386},{138,10,713},{6,10,7},\n{6,10,35},{7,10,147},{7,10,1069},{7,10,1568},{7,10,1575},{7,10,1917},{8,10,43},{\n8,10,208},{9,10,128},{9,10,866},{10,10,20},{11,10,981},{147,10,33},{133,0,26},{\n132,0,550},{5,11,2},{7,11,1494},{136,11,589},{6,11,512},{7,11,797},{8,11,253},{9\n,11,77},{10,11,1},{10,11,129},{10,11,225},{11,11,118},{11,11,226},{11,11,251},{\n11,11,430},{11,11,701},{11,11,974},{11,11,982},{12,11,64},{12,11,260},{12,11,488\n},{140,11,690},{7,10,893},{141,10,424},{134,0,901},{136,0,822},{4,0,902},{5,0,\n809},{134,0,122},{6,0,807},{134,0,1366},{5,11,748},{6,11,553},{135,0,262},{133,0\n,620},{4,0,34},{5,0,574},{7,0,279},{7,0,1624},{136,0,601},{6,10,322},{9,0,170},{\n9,10,552},{11,10,274},{13,10,209},{13,10,499},{14,10,85},{15,10,126},{145,10,70}\n,{132,0,537},{4,11,12},{7,11,420},{7,11,522},{7,11,809},{8,11,797},{141,11,88},{\n133,0,332},{8,10,83},{8,10,742},{8,10,817},{9,10,28},{9,10,29},{9,10,885},{10,10\n,387},{11,10,633},{11,10,740},{13,10,235},{13,10,254},{15,10,143},{143,10,146},{\n6,0,1909},{9,0,964},{12,0,822},{12,0,854},{12,0,865},{12,0,910},{12,0,938},{15,0\n,169},{15,0,208},{15,0,211},{18,0,205},{18,0,206},{18,0,220},{18,0,223},{152,0,\n24},{140,10,49},{5,11,528},{135,11,1580},{6,0,261},{8,0,182},{139,0,943},{134,0,\n1721},{4,0,933},{133,0,880},{136,11,321},{5,11,266},{9,11,290},{9,11,364},{10,11\n,293},{11,11,606},{142,11,45},{4,11,50},{6,0,1609},{6,11,510},{6,11,594},{9,11,\n121},{10,11,49},{10,11,412},{139,11,834},{7,0,895},{136,11,748},{132,11,466},{4,\n10,110},{10,10,415},{10,10,597},{142,10,206},{133,0,812},{135,11,281},{6,0,1890}\n,{6,0,1902},{6,0,1916},{7,10,205},{7,10,2000},{9,0,929},{9,0,942},{9,0,975},{9,0\n,984},{9,0,986},{9,0,1011},{9,0,1019},{12,0,804},{12,0,851},{12,0,867},{12,0,916\n},{12,0,923},{15,0,194},{15,0,204},{15,0,210},{15,0,222},{15,0,223},{15,0,229},{\n15,0,250},{18,0,179},{18,0,186},{146,0,192},{132,11,667},{135,0,778},{4,0,137},{\n7,0,1178},{135,0,1520},{134,0,1314},{4,11,242},{134,11,333},{6,0,1661},{7,0,1975\n},{7,0,2009},{135,0,2011},{134,0,1591},{4,10,283},{135,10,1194},{11,0,820},{150,\n0,51},{4,11,39},{5,11,36},{7,11,1843},{8,11,407},{11,11,144},{140,11,523},{134,\n10,1720},{4,11,510},{7,11,29},{7,11,66},{7,11,1980},{10,11,487},{10,11,809},{146\n,11,9},{5,0,89},{7,0,1915},{9,0,185},{9,0,235},{10,0,64},{10,0,270},{10,0,403},{\n10,0,469},{10,0,529},{10,0,590},{11,0,140},{11,0,860},{13,0,1},{13,0,422},{14,0,\n341},{14,0,364},{17,0,93},{18,0,113},{19,0,97},{147,0,113},{133,0,695},{6,0,987}\n,{134,0,1160},{5,0,6},{6,0,183},{7,0,680},{7,0,978},{7,0,1013},{7,0,1055},{12,0,\n230},{13,0,172},{146,0,29},{134,11,570},{132,11,787},{134,11,518},{6,0,29},{139,\n0,63},{132,11,516},{136,11,821},{132,0,311},{134,0,1740},{7,0,170},{8,0,90},{8,0\n,177},{8,0,415},{8,10,735},{11,0,714},{142,0,281},{134,0,1961},{135,11,1405},{4,\n11,10},{7,11,917},{139,11,786},{5,10,132},{9,10,486},{9,10,715},{10,10,458},{11,\n10,373},{11,10,668},{11,10,795},{11,10,897},{12,10,272},{12,10,424},{12,10,539},\n{12,10,558},{14,10,245},{14,10,263},{14,10,264},{14,10,393},{142,10,403},{11,0,\n91},{13,0,129},{15,0,101},{145,0,125},{135,0,1132},{4,0,494},{6,0,74},{7,0,44},{\n7,0,407},{12,0,17},{15,0,5},{148,0,11},{133,10,379},{5,0,270},{5,11,684},{6,10,\n89},{6,10,400},{7,10,1569},{7,10,1623},{7,10,1850},{8,10,218},{8,10,422},{9,10,\n570},{138,10,626},{4,0,276},{133,0,296},{6,0,1523},{134,11,27},{6,10,387},{7,10,\n882},{141,10,111},{6,10,224},{7,10,877},{137,10,647},{135,10,790},{4,0,7},{5,0,\n90},{5,0,158},{6,0,542},{7,0,221},{7,0,1574},{9,0,490},{10,0,540},{11,0,443},{\n139,0,757},{7,0,588},{9,0,175},{138,0,530},{135,10,394},{142,11,23},{134,0,786},\n{135,0,580},{7,0,88},{136,0,627},{5,0,872},{6,0,57},{7,0,471},{9,0,447},{137,0,\n454},{6,11,342},{6,11,496},{8,11,275},{137,11,206},{4,11,909},{133,11,940},{4,11\n,891},{134,0,735},{7,10,1409},{8,0,845},{136,0,916},{5,0,31},{134,0,614},{11,0,\n458},{12,0,15},{140,0,432},{8,0,330},{140,0,477},{4,0,530},{4,11,687},{5,0,521},\n{7,0,1200},{138,0,460},{6,0,424},{135,0,1866},{9,0,569},{12,0,12},{12,0,81},{12,\n0,319},{13,0,69},{14,0,259},{16,0,87},{17,0,1},{17,0,21},{17,0,24},{18,0,15},{18\n,0,56},{18,0,59},{18,0,127},{18,0,154},{19,0,19},{148,0,31},{7,0,1302},{136,10,\n38},{134,11,253},{5,10,261},{7,10,78},{7,10,199},{8,10,815},{9,10,126},{138,10,\n342},{5,0,595},{135,0,1863},{6,11,41},{141,11,160},{5,0,13},{134,0,142},{6,0,97}\n,{7,0,116},{7,11,1304},{8,0,322},{8,0,755},{9,0,548},{10,0,714},{10,11,477},{11,\n0,884},{141,0,324},{132,10,628},{134,11,1718},{7,10,266},{136,10,804},{135,10,\n208},{6,10,79},{7,0,1021},{135,10,1519},{7,0,1472},{135,0,1554},{6,11,362},{146,\n11,51},{7,0,1071},{7,0,1541},{7,0,1767},{7,0,1806},{11,0,162},{11,0,242},{11,0,\n452},{12,0,605},{15,0,26},{144,0,44},{136,10,741},{133,11,115},{145,0,115},{134,\n10,376},{6,0,1406},{134,0,1543},{5,11,193},{12,11,178},{13,11,130},{145,11,84},{\n135,0,1111},{5,11,705},{8,0,1},{9,0,650},{9,11,606},{138,0,326},{5,0,488},{6,0,\n527},{7,0,489},{7,0,1636},{8,0,121},{8,0,144},{8,0,359},{9,0,193},{9,0,241},{9,0\n,336},{9,0,882},{11,0,266},{11,0,372},{11,0,944},{12,0,401},{140,0,641},{135,11,\n174},{6,0,267},{7,10,244},{7,10,632},{7,10,1609},{8,10,178},{8,10,638},{141,10,\n58},{134,0,1983},{134,0,1155},{134,0,1575},{134,0,1438},{9,0,31},{10,0,244},{10,\n0,699},{12,0,149},{141,0,497},{133,0,377},{4,11,122},{5,11,796},{5,11,952},{6,11\n,1660},{6,11,1671},{8,11,567},{9,11,687},{9,11,742},{10,11,686},{11,11,356},{11,\n11,682},{140,11,281},{145,0,101},{11,11,0},{144,11,78},{5,10,791},{5,11,179},{7,\n11,1095},{135,11,1213},{8,11,372},{9,11,122},{138,11,175},{7,10,686},{8,10,33},{\n8,10,238},{10,10,616},{11,10,467},{11,10,881},{13,10,217},{13,10,253},{142,10,\n268},{4,11,66},{7,11,722},{7,11,904},{137,0,476},{7,11,352},{137,11,684},{135,0,\n2023},{135,0,1836},{132,10,447},{5,0,843},{144,0,35},{137,11,779},{141,11,35},{4\n,10,128},{5,10,415},{6,10,462},{7,10,294},{7,10,578},{10,10,710},{139,10,86},{\n132,0,554},{133,0,536},{136,10,587},{5,0,207},{9,0,79},{11,0,625},{145,0,7},{6,\n10,427},{7,0,1371},{138,10,692},{4,0,424},{4,10,195},{135,10,802},{5,11,564},{\n136,0,785},{135,0,336},{4,0,896},{6,0,1777},{134,11,556},{137,11,103},{134,10,\n1683},{7,11,544},{8,11,719},{138,11,61},{138,10,472},{4,11,5},{5,11,498},{136,11\n,637},{7,0,750},{9,0,223},{11,0,27},{11,0,466},{12,0,624},{14,0,265},{146,0,61},\n{12,0,238},{12,11,238},{18,0,155},{146,11,155},{151,10,28},{133,11,927},{5,10,3}\n,{8,10,578},{9,10,118},{10,10,705},{12,0,383},{141,10,279},{4,11,893},{5,11,780}\n,{133,11,893},{4,0,603},{133,0,661},{4,0,11},{5,10,229},{5,11,238},{6,0,128},{7,\n0,231},{7,0,1533},{7,11,1350},{138,0,725},{8,10,102},{10,10,578},{10,10,672},{12\n,10,496},{13,10,408},{14,10,121},{145,10,106},{132,0,476},{134,0,1552},{134,11,\n1729},{8,10,115},{8,10,350},{9,10,489},{10,10,128},{11,10,306},{12,10,373},{14,\n10,30},{17,10,79},{19,10,80},{150,10,55},{135,0,1807},{4,0,680},{4,11,60},{7,11,\n760},{7,11,1800},{8,11,314},{9,11,700},{139,11,487},{4,10,230},{5,10,702},{148,\n11,94},{132,11,228},{139,0,435},{9,0,20},{10,0,324},{10,0,807},{139,0,488},{6,10\n,1728},{136,11,419},{4,10,484},{18,10,26},{19,10,42},{20,10,43},{21,10,0},{23,10\n,27},{152,10,14},{135,0,1431},{133,11,828},{5,0,112},{6,0,103},{6,0,150},{7,0,\n1303},{7,11,176},{7,11,178},{7,11,1110},{9,0,292},{10,0,481},{10,11,481},{20,0,\n13},{148,11,13},{138,0,356},{4,11,51},{5,11,39},{6,11,4},{7,11,591},{7,11,849},{\n7,11,951},{7,11,1129},{7,11,1613},{7,11,1760},{7,11,1988},{9,11,434},{10,11,754}\n,{11,11,25},{11,11,37},{139,11,414},{6,0,1963},{134,0,2000},{132,10,633},{5,11,\n902},{134,0,1244},{135,11,928},{140,0,18},{138,0,204},{135,11,1173},{134,0,867},\n{4,0,708},{8,0,15},{9,0,50},{9,0,386},{11,0,18},{11,0,529},{140,0,228},{134,11,\n270},{4,0,563},{7,0,109},{7,0,592},{7,0,637},{7,0,770},{8,0,463},{9,0,60},{9,0,\n335},{9,0,904},{10,0,73},{11,0,434},{12,0,585},{13,0,331},{18,0,110},{148,0,60},\n{132,0,502},{14,11,359},{19,11,52},{148,11,47},{6,11,377},{7,11,1025},{9,11,613}\n,{145,11,104},{5,10,70},{5,10,622},{6,0,347},{6,10,334},{7,10,1032},{9,10,171},{\n10,0,161},{11,10,26},{11,10,213},{11,10,637},{11,10,707},{12,10,202},{12,10,380}\n,{13,10,226},{13,10,355},{14,10,222},{145,10,42},{132,11,416},{4,0,33},{5,0,102}\n,{6,0,284},{7,0,1079},{7,0,1423},{7,0,1702},{8,0,470},{9,0,554},{9,0,723},{11,0,\n333},{142,11,372},{5,11,152},{5,11,197},{7,11,340},{7,11,867},{10,11,548},{10,11\n,581},{11,11,6},{12,11,3},{12,11,19},{14,11,110},{142,11,289},{7,0,246},{135,0,\n840},{6,0,10},{8,0,571},{9,0,739},{143,0,91},{4,10,23},{4,10,141},{5,10,313},{5,\n10,1014},{6,0,465},{6,10,50},{7,0,1465},{7,10,142},{7,10,559},{8,10,640},{9,10,\n460},{9,10,783},{11,10,741},{12,10,183},{141,10,488},{133,0,626},{136,0,614},{\n138,0,237},{7,11,34},{7,11,190},{8,11,28},{8,11,141},{8,11,444},{8,11,811},{9,11\n,468},{11,11,334},{12,11,24},{12,11,386},{140,11,576},{133,11,757},{5,0,18},{6,0\n,526},{13,0,24},{13,0,110},{19,0,5},{147,0,44},{6,0,506},{134,11,506},{135,11,\n1553},{4,0,309},{5,0,462},{7,0,970},{7,0,1097},{7,11,1385},{11,11,582},{11,11,\n650},{11,11,901},{11,11,949},{12,11,232},{12,11,236},{13,11,413},{13,11,501},{18\n,11,116},{22,0,30},{150,0,33},{5,10,222},{9,0,140},{138,10,534},{6,0,1056},{137,\n10,906},{134,0,1704},{138,10,503},{134,0,1036},{5,10,154},{7,10,1491},{10,10,379\n},{138,10,485},{4,11,383},{133,10,716},{134,0,1315},{5,0,86},{7,0,743},{9,0,85},\n{10,0,281},{10,0,432},{11,0,825},{12,0,251},{13,0,118},{142,0,378},{4,10,91},{5,\n10,388},{5,10,845},{6,10,206},{6,10,252},{6,10,365},{7,10,136},{7,10,531},{8,0,\n264},{136,10,621},{5,0,524},{133,0,744},{5,11,277},{141,11,247},{132,11,435},{10\n,0,107},{140,0,436},{132,0,927},{10,0,123},{12,0,670},{146,0,94},{7,0,1149},{9,0\n,156},{138,0,957},{5,11,265},{6,11,212},{135,11,28},{133,0,778},{133,0,502},{8,0\n,196},{10,0,283},{139,0,406},{135,10,576},{136,11,535},{134,0,1312},{5,10,771},{\n5,10,863},{5,10,898},{6,10,1632},{6,10,1644},{134,10,1780},{5,0,855},{5,10,331},\n{135,11,1487},{132,11,702},{5,11,808},{135,11,2045},{7,0,1400},{9,0,446},{138,0,\n45},{140,10,632},{132,0,1003},{5,11,166},{8,11,739},{140,11,511},{5,10,107},{7,\n10,201},{136,10,518},{6,10,446},{135,10,1817},{134,0,1532},{134,0,1097},{4,11,\n119},{5,11,170},{5,11,447},{7,11,1708},{7,11,1889},{9,11,357},{9,11,719},{12,11,\n486},{140,11,596},{9,10,851},{141,10,510},{4,10,504},{7,0,612},{8,0,545},{8,0,\n568},{8,0,642},{9,0,717},{10,0,541},{10,0,763},{11,0,449},{12,0,489},{13,0,153},\n{13,0,296},{14,0,138},{14,0,392},{15,0,50},{16,0,6},{16,0,12},{148,0,9},{4,11,\n450},{135,11,1158},{5,10,883},{5,10,975},{8,10,392},{11,0,54},{13,0,173},{13,0,\n294},{148,10,7},{13,0,455},{15,0,99},{15,0,129},{144,0,68},{135,0,172},{132,11,\n754},{5,10,922},{134,10,1707},{134,0,1029},{17,11,39},{148,11,36},{4,0,568},{5,\n10,993},{7,10,515},{137,10,91},{132,0,732},{10,0,617},{138,11,617},{134,0,974},{\n7,0,989},{10,0,377},{12,0,363},{13,0,68},{13,0,94},{14,0,108},{142,0,306},{136,0\n,733},{132,0,428},{7,0,1789},{135,11,1062},{7,0,2015},{140,0,665},{135,10,1433},\n{5,0,287},{7,10,921},{8,10,580},{8,10,593},{8,10,630},{138,10,28},{138,0,806},{4\n,10,911},{5,10,867},{5,10,1013},{7,10,2034},{8,10,798},{136,10,813},{134,0,1539}\n,{8,11,523},{150,11,34},{135,11,740},{7,11,238},{7,11,2033},{8,11,120},{8,11,188\n},{8,11,659},{9,11,598},{10,11,466},{12,11,342},{12,11,588},{13,11,503},{14,11,\n246},{143,11,92},{7,0,1563},{141,0,182},{5,10,135},{6,10,519},{7,10,1722},{10,10\n,271},{11,10,261},{145,10,54},{14,10,338},{148,10,81},{4,10,300},{5,10,436},{135\n,0,484},{145,11,114},{6,0,1623},{134,0,1681},{133,11,640},{4,11,201},{7,11,1744}\n,{8,11,602},{11,11,247},{11,11,826},{145,11,65},{8,11,164},{146,11,62},{6,0,1833\n},{6,0,1861},{136,0,878},{134,0,1569},{8,10,357},{10,10,745},{14,10,426},{17,10,\n94},{147,10,57},{12,0,93},{12,0,501},{13,0,362},{14,0,151},{15,0,40},{15,0,59},{\n16,0,46},{17,0,25},{18,0,14},{18,0,134},{19,0,25},{19,0,69},{20,0,16},{20,0,19},\n{20,0,66},{21,0,23},{21,0,25},{150,0,42},{6,0,1748},{8,0,715},{9,0,802},{10,0,46\n},{10,0,819},{13,0,308},{14,0,351},{14,0,363},{146,0,67},{132,0,994},{4,0,63},{\n133,0,347},{132,0,591},{133,0,749},{7,11,1577},{10,11,304},{10,11,549},{11,11,\n424},{12,11,365},{13,11,220},{13,11,240},{142,11,33},{133,0,366},{5,10,387},{7,0\n,557},{12,0,547},{142,0,86},{135,0,1747},{132,11,907},{5,11,100},{10,11,329},{12\n,11,416},{149,11,29},{4,10,6},{5,10,708},{136,10,75},{7,10,1351},{9,10,581},{10,\n10,639},{11,10,453},{140,10,584},{4,10,303},{135,0,89},{138,10,772},{132,11,176}\n,{5,11,636},{5,11,998},{8,11,26},{137,11,358},{7,11,9},{7,11,1508},{9,11,317},{\n10,11,210},{10,11,292},{10,11,533},{11,11,555},{12,11,526},{12,11,607},{13,11,\n263},{13,11,459},{142,11,271},{134,0,1463},{6,0,772},{6,0,1137},{139,11,595},{7,\n0,977},{139,11,66},{138,0,893},{20,0,48},{148,11,48},{5,0,824},{133,0,941},{134,\n11,295},{4,10,106},{7,0,1543},{7,0,1785},{10,0,690},{139,10,717},{7,0,440},{8,0,\n230},{139,0,106},{5,10,890},{133,10,988},{6,10,626},{142,10,431},{10,11,127},{\n141,11,27},{10,10,706},{17,0,32},{150,10,44},{132,0,216},{137,0,332},{4,10,698},\n{136,11,119},{139,11,267},{138,10,17},{11,11,526},{11,11,939},{141,11,290},{7,11\n,1167},{11,11,934},{13,11,391},{145,11,76},{139,11,39},{134,10,84},{4,0,914},{5,\n0,800},{133,0,852},{10,0,416},{141,0,115},{7,0,564},{142,0,168},{4,0,918},{133,0\n,876},{134,0,1764},{152,0,3},{4,0,92},{5,0,274},{7,11,126},{136,11,84},{140,10,\n498},{136,11,790},{5,10,986},{6,10,130},{7,10,1582},{8,0,501},{8,10,458},{10,10,\n101},{10,10,318},{138,10,823},{6,11,64},{12,11,377},{141,11,309},{5,0,743},{138,\n0,851},{4,0,49},{7,0,280},{135,0,1633},{134,0,879},{136,0,47},{7,10,1644},{137,\n10,129},{132,0,865},{134,0,1202},{9,11,34},{139,11,484},{135,10,997},{5,0,272},{\n5,0,908},{5,0,942},{8,0,197},{9,0,47},{11,0,538},{139,0,742},{6,11,1700},{7,11,\n26},{7,11,293},{7,11,382},{7,11,1026},{7,11,1087},{7,11,2027},{8,11,24},{8,11,\n114},{8,11,252},{8,11,727},{8,11,729},{9,11,30},{9,11,199},{9,11,231},{9,11,251}\n,{9,11,334},{9,11,361},{9,11,488},{9,11,712},{10,11,55},{10,11,60},{10,11,232},{\n10,11,332},{10,11,384},{10,11,396},{10,11,504},{10,11,542},{10,11,652},{11,11,20\n},{11,11,48},{11,11,207},{11,11,291},{11,11,298},{11,11,342},{11,11,365},{11,11,\n394},{11,11,620},{11,11,705},{11,11,1017},{12,11,123},{12,11,340},{12,11,406},{\n12,11,643},{13,11,61},{13,11,269},{13,11,311},{13,11,319},{13,11,486},{14,11,234\n},{15,11,62},{15,11,85},{16,11,71},{18,11,119},{148,11,105},{6,0,1455},{150,11,\n37},{135,10,1927},{135,0,1911},{137,0,891},{7,10,1756},{137,10,98},{7,10,1046},{\n139,10,160},{132,0,761},{6,11,379},{7,11,270},{7,11,1116},{8,11,176},{8,11,183},\n{9,11,432},{9,11,661},{12,11,247},{12,11,617},{146,11,125},{6,10,45},{7,10,433},\n{8,10,129},{9,10,21},{10,10,392},{11,10,79},{12,10,499},{13,10,199},{141,10,451}\n,{4,0,407},{5,11,792},{133,11,900},{132,0,560},{135,0,183},{7,10,558},{8,10,353}\n,{141,0,490},{4,0,475},{5,10,785},{6,0,731},{11,0,35},{13,0,71},{13,0,177},{142,\n0,422},{8,10,81},{9,10,189},{9,10,201},{11,10,478},{11,10,712},{141,10,338},{4,0\n,418},{4,0,819},{133,10,353},{151,10,26},{4,11,901},{133,11,776},{132,0,575},{7,\n0,818},{16,0,92},{17,0,14},{17,0,45},{18,0,75},{148,0,18},{6,0,222},{7,0,636},{7\n,0,1620},{8,0,409},{9,0,693},{139,0,77},{6,10,25},{7,10,855},{7,10,1258},{144,10\n,32},{6,0,1880},{6,0,1887},{6,0,1918},{6,0,1924},{9,0,967},{9,0,995},{9,0,1015},\n{12,0,826},{12,0,849},{12,0,857},{12,0,860},{12,0,886},{12,0,932},{18,0,228},{18\n,0,231},{146,0,240},{134,0,633},{134,0,1308},{4,11,37},{5,11,334},{135,11,1253},\n{4,10,4},{7,10,1118},{7,10,1320},{7,10,1706},{8,10,277},{9,10,622},{10,0,86},{11\n,10,724},{12,10,350},{12,10,397},{13,10,28},{13,10,159},{15,10,89},{18,10,5},{19\n,10,9},{20,10,34},{150,10,47},{132,11,508},{137,11,448},{12,11,107},{146,11,31},\n{132,0,817},{134,0,663},{133,0,882},{134,0,914},{132,11,540},{132,11,533},{136,\n11,608},{8,0,885},{138,0,865},{132,0,426},{6,0,58},{7,0,745},{7,0,1969},{8,0,399\n},{8,0,675},{9,0,479},{9,0,731},{10,0,330},{10,0,593},{10,0,817},{11,0,32},{11,0\n,133},{11,0,221},{145,0,68},{134,10,255},{7,0,102},{137,0,538},{137,10,216},{7,\n11,253},{136,11,549},{135,11,912},{9,10,183},{139,10,286},{11,10,956},{151,10,3}\n,{8,11,527},{18,11,60},{147,11,24},{4,10,536},{7,10,1141},{10,10,723},{139,10,\n371},{133,11,920},{7,0,876},{135,10,285},{135,10,560},{132,10,690},{142,11,126},\n{11,10,33},{12,10,571},{149,10,1},{133,0,566},{4,11,483},{9,0,139},{10,0,399},{\n11,0,469},{12,0,634},{141,0,223},{6,0,48},{135,0,63},{7,10,1862},{12,10,491},{12\n,10,520},{13,10,383},{14,10,244},{146,0,12},{135,11,1665},{132,11,448},{9,11,495\n},{146,11,104},{6,0,114},{7,0,1224},{7,0,1556},{136,0,3},{4,10,190},{133,10,554}\n,{5,10,1001},{8,0,576},{137,0,267},{133,10,446},{133,0,933},{139,11,1009},{8,11,\n653},{13,11,93},{147,11,14},{6,0,692},{6,0,821},{134,0,1077},{5,11,172},{135,11,\n801},{138,0,752},{4,0,375},{134,0,638},{134,0,1011},{140,11,540},{5,11,260},{137\n,0,96},{139,11,587},{135,10,1231},{4,10,304},{12,0,30},{13,0,148},{14,0,87},{14,\n0,182},{16,0,42},{148,0,70},{6,0,1398},{7,0,56},{7,0,1989},{8,0,337},{8,0,738},{\n9,0,600},{12,0,37},{13,0,447},{142,0,92},{138,0,666},{5,0,394},{7,0,487},{136,0,\n246},{6,10,53},{6,10,199},{7,10,1408},{8,10,32},{8,10,93},{9,0,437},{10,10,397},\n{10,10,629},{11,10,593},{11,10,763},{13,10,326},{145,10,35},{134,10,105},{9,0,\n320},{10,0,506},{138,10,794},{7,11,57},{8,11,167},{8,11,375},{9,11,82},{9,11,561\n},{10,11,620},{10,11,770},{11,10,704},{141,10,396},{5,10,114},{5,10,255},{6,0,\n1003},{141,10,285},{7,0,866},{135,0,1163},{133,11,531},{132,0,328},{7,10,2035},{\n8,10,19},{9,10,89},{138,10,831},{8,11,194},{136,11,756},{136,0,1000},{5,11,453},\n{134,11,441},{4,0,101},{5,0,833},{7,0,1171},{136,0,744},{133,0,726},{136,10,746}\n,{138,0,176},{6,0,9},{6,0,397},{7,0,53},{7,0,1742},{10,0,632},{11,0,828},{140,0,\n146},{135,11,22},{145,11,64},{132,0,839},{11,0,417},{12,0,223},{140,0,265},{4,11\n,102},{7,11,815},{7,11,1699},{139,11,964},{5,10,955},{136,10,814},{6,0,1931},{6,\n0,2007},{18,0,246},{146,0,247},{8,0,198},{11,0,29},{140,0,534},{135,0,1771},{6,0\n,846},{7,11,1010},{11,11,733},{11,11,759},{12,11,563},{13,11,34},{14,11,101},{18\n,11,45},{146,11,129},{4,0,186},{5,0,157},{8,0,168},{138,0,6},{132,11,899},{133,\n10,56},{148,10,100},{133,0,875},{5,0,773},{5,0,991},{6,0,1635},{134,0,1788},{6,0\n,1274},{9,0,477},{141,0,78},{4,0,639},{6,11,52},{7,0,111},{8,0,581},{9,11,104},{\n9,11,559},{10,10,4},{10,10,13},{11,10,638},{12,0,177},{12,11,308},{19,11,87},{\n148,10,57},{132,11,604},{4,11,301},{133,10,738},{133,10,758},{134,0,1747},{7,11,\n1440},{11,11,854},{11,11,872},{11,11,921},{12,11,551},{13,11,472},{142,11,367},{\n7,0,1364},{7,0,1907},{141,0,158},{134,0,873},{4,0,404},{4,0,659},{7,0,552},{135,\n0,675},{135,10,1112},{139,10,328},{7,11,508},{137,10,133},{133,0,391},{5,10,110}\n,{6,10,169},{6,10,1702},{7,10,400},{8,10,538},{9,10,184},{9,10,524},{140,10,218}\n,{6,11,310},{7,11,1849},{8,11,72},{8,11,272},{8,11,431},{9,11,12},{9,11,351},{10\n,11,563},{10,11,630},{10,11,810},{11,11,367},{11,11,599},{11,11,686},{140,11,672\n},{5,0,540},{6,0,1697},{136,0,668},{132,0,883},{134,0,78},{6,10,133},{9,10,353},\n{11,10,993},{12,0,628},{146,0,79},{6,11,181},{7,11,537},{8,11,64},{9,11,127},{10\n,11,496},{12,11,510},{141,11,384},{6,10,93},{7,10,1422},{7,10,1851},{8,10,673},{\n9,10,529},{140,10,43},{137,10,371},{134,0,1460},{134,0,962},{4,11,244},{135,11,\n233},{9,10,25},{10,10,467},{138,10,559},{4,10,335},{135,10,942},{133,0,460},{135\n,11,334},{134,11,1650},{4,0,199},{139,0,34},{5,10,601},{8,10,39},{10,10,773},{11\n,10,84},{12,10,205},{142,10,1},{133,10,870},{134,0,388},{14,0,474},{148,0,120},{\n133,11,369},{139,0,271},{4,0,511},{4,10,181},{9,0,333},{9,0,379},{10,0,602},{11,\n0,441},{11,0,723},{11,0,976},{140,0,357},{134,0,608},{134,10,1652},{9,11,338},{\n150,0,49},{140,0,988},{134,0,617},{5,0,938},{136,0,707},{132,10,97},{5,10,147},{\n6,10,286},{7,10,1362},{141,10,176},{6,0,756},{134,0,1149},{133,11,896},{6,10,375\n},{7,10,169},{7,10,254},{136,10,780},{134,0,1583},{135,10,1447},{139,0,285},{7,\n11,1117},{8,11,393},{136,11,539},{135,0,344},{6,0,469},{7,0,1709},{138,0,515},{5\n,10,629},{135,10,1549},{5,11,4},{5,11,810},{6,11,13},{6,11,538},{6,11,1690},{6,\n11,1726},{7,11,499},{7,11,1819},{8,11,148},{8,11,696},{8,11,791},{12,11,125},{13\n,11,54},{143,11,9},{135,11,1268},{137,0,404},{132,0,500},{5,0,68},{134,0,383},{\n11,0,216},{139,0,340},{4,11,925},{5,11,803},{8,11,698},{138,11,828},{4,0,337},{6\n,0,353},{7,0,1934},{8,0,488},{137,0,429},{7,0,236},{7,0,1795},{8,0,259},{9,0,135\n},{9,0,177},{9,0,860},{10,0,825},{11,0,115},{11,0,370},{11,0,405},{11,0,604},{12\n,0,10},{12,0,667},{12,0,669},{13,0,76},{14,0,310},{15,0,76},{15,0,147},{148,0,23\n},{4,0,15},{4,0,490},{5,0,22},{6,0,244},{7,0,40},{7,0,200},{7,0,906},{7,0,1199},\n{9,0,616},{10,0,716},{11,0,635},{11,0,801},{140,0,458},{4,10,420},{140,0,756},{\n134,0,1504},{5,11,383},{134,0,757},{6,0,1266},{135,0,1735},{5,0,598},{7,0,791},{\n7,10,1570},{8,0,108},{9,0,123},{140,10,542},{142,11,410},{9,11,660},{138,11,347}\n};\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/static_init.h",
    "content": "﻿/* Copyright 2025 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Central point for static initialization. */\n\n#ifndef THIRD_PARTY_BROTLI_ENC_STATIC_INIT_H_\n#define THIRD_PARTY_BROTLI_ENC_STATIC_INIT_H_\n\n#include \"../common/platform.h\"\n#include \"../common/static_init.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if (BROTLI_STATIC_INIT == BROTLI_STATIC_INIT_LAZY)\nBROTLI_INTERNAL void BrotliEncoderLazyStaticInitInner(void);\nBROTLI_INTERNAL void BrotliEncoderLazyStaticInit(void);\n#endif  /* BROTLI_STATIC_INIT */\n\nBROTLI_INTERNAL BROTLI_BOOL BrotliEncoderEnsureStaticInit(void);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  // THIRD_PARTY_BROTLI_ENC_STATIC_INIT_H_\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/utf8_util.c",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Heuristics for deciding about the UTF8-ness of strings. */\n\n#include \"utf8_util.h\"\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic size_t BrotliParseAsUTF8(\n    int* symbol, const uint8_t* input, size_t size) {\n  /* ASCII */\n  if ((input[0] & 0x80) == 0) {\n    *symbol = input[0];\n    if (*symbol > 0) {\n      return 1;\n    }\n  }\n  /* 2-byte UTF8 */\n  if (size > 1u &&\n      (input[0] & 0xE0) == 0xC0 &&\n      (input[1] & 0xC0) == 0x80) {\n    *symbol = (((input[0] & 0x1F) << 6) |\n               (input[1] & 0x3F));\n    if (*symbol > 0x7F) {\n      return 2;\n    }\n  }\n  /* 3-byte UFT8 */\n  if (size > 2u &&\n      (input[0] & 0xF0) == 0xE0 &&\n      (input[1] & 0xC0) == 0x80 &&\n      (input[2] & 0xC0) == 0x80) {\n    *symbol = (((input[0] & 0x0F) << 12) |\n               ((input[1] & 0x3F) << 6) |\n               (input[2] & 0x3F));\n    if (*symbol > 0x7FF) {\n      return 3;\n    }\n  }\n  /* 4-byte UFT8 */\n  if (size > 3u &&\n      (input[0] & 0xF8) == 0xF0 &&\n      (input[1] & 0xC0) == 0x80 &&\n      (input[2] & 0xC0) == 0x80 &&\n      (input[3] & 0xC0) == 0x80) {\n    *symbol = (((input[0] & 0x07) << 18) |\n               ((input[1] & 0x3F) << 12) |\n               ((input[2] & 0x3F) << 6) |\n               (input[3] & 0x3F));\n    if (*symbol > 0xFFFF && *symbol <= 0x10FFFF) {\n      return 4;\n    }\n  }\n  /* Not UTF8, emit a special symbol above the UTF8-code space */\n  *symbol = 0x110000 | input[0];\n  return 1;\n}\n\n/* Returns 1 if at least min_fraction of the data is UTF8-encoded.*/\nBROTLI_BOOL BrotliIsMostlyUTF8(\n    const uint8_t* data, const size_t pos, const size_t mask,\n    const size_t length, const double min_fraction) {\n  size_t size_utf8 = 0;\n  size_t i = 0;\n  while (i < length) {\n    int symbol;\n    size_t bytes_read =\n        BrotliParseAsUTF8(&symbol, &data[(pos + i) & mask], length - i);\n    i += bytes_read;\n    if (symbol < 0x110000) size_utf8 += bytes_read;\n  }\n  return TO_BROTLI_BOOL((double)size_utf8 > min_fraction * (double)length);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/utf8_util.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Heuristics for deciding about the UTF8-ness of strings. */\n\n#ifndef BROTLI_ENC_UTF8_UTIL_H_\n#define BROTLI_ENC_UTF8_UTIL_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic const double kMinUTF8Ratio = 0.75;\n\n/* Returns 1 if at least min_fraction of the bytes between pos and\n   pos + length in the (data, mask) ring-buffer is UTF8-encoded, otherwise\n   returns 0. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliIsMostlyUTF8(\n    const uint8_t* data, const size_t pos, const size_t mask,\n    const size_t length, const double min_fraction);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_UTF8_UTIL_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/enc/write_bits.h",
    "content": "﻿/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Write bits into a byte array. */\n\n#ifndef BROTLI_ENC_WRITE_BITS_H_\n#define BROTLI_ENC_WRITE_BITS_H_\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* This function writes bits into bytes in increasing addresses, and within\n   a byte least-significant-bit first.\n\n   The function can write up to 56 bits in one go with WriteBits\n   Example: let's assume that 3 bits (Rs below) have been written already:\n\n   BYTE-0     BYTE+1       BYTE+2\n\n   0000 0RRR    0000 0000    0000 0000\n\n   Now, we could write 5 or less bits in MSB by just shifting by 3\n   and OR'ing to BYTE-0.\n\n   For n bits, we take the last 5 bits, OR that with high bits in BYTE-0,\n   and locate the rest in BYTE+1, BYTE+2, etc. */\nstatic BROTLI_INLINE void BrotliWriteBits(size_t n_bits,\n                                          uint64_t bits,\n                                          size_t* BROTLI_RESTRICT pos,\n                                          uint8_t* BROTLI_RESTRICT array) {\n  BROTLI_LOG((\"WriteBits  %2d  0x%08x%08x  %10d\\n\", (int)n_bits,\n      (uint32_t)(bits >> 32), (uint32_t)(bits & 0xFFFFFFFF),\n      (int)*pos));\n  BROTLI_DCHECK((bits >> n_bits) == 0);\n  BROTLI_DCHECK(n_bits <= 56);\n#if defined(BROTLI_LITTLE_ENDIAN)\n  /* This branch of the code can write up to 56 bits at a time,\n     7 bits are lost by being perhaps already in *p and at least\n     1 bit is needed to initialize the bit-stream ahead (i.e. if 7\n     bits are in *p and we write 57 bits, then the next write will\n     access a byte that was never initialized). */\n  {\n    uint8_t* p = &array[*pos >> 3];\n    uint64_t v = (uint64_t)(*p);  /* Zero-extend 8 to 64 bits. */\n    v |= bits << (*pos & 7);\n    BROTLI_UNALIGNED_STORE64LE(p, v);  /* Set some bits. */\n    *pos += n_bits;\n  }\n#else\n  /* implicit & 0xFF is assumed for uint8_t arithmetics */\n  {\n    uint8_t* array_pos = &array[*pos >> 3];\n    const size_t bits_reserved_in_first_byte = (*pos & 7);\n    size_t bits_left_to_write;\n    bits <<= bits_reserved_in_first_byte;\n    *array_pos++ |= (uint8_t)bits;\n    for (bits_left_to_write = n_bits + bits_reserved_in_first_byte;\n         bits_left_to_write >= 9;\n         bits_left_to_write -= 8) {\n      bits >>= 8;\n      *array_pos++ = (uint8_t)bits;\n    }\n    *array_pos = 0;\n    *pos += n_bits;\n  }\n#endif\n}\n\nstatic BROTLI_INLINE void BrotliWriteBitsPrepareStorage(\n    size_t pos, uint8_t* array) {\n  BROTLI_LOG((\"WriteBitsPrepareStorage            %10d\\n\", (int)pos));\n  BROTLI_DCHECK((pos & 7) == 0);\n  array[pos >> 3] = 0;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_WRITE_BITS_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/include/brotli/decode.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * API for Brotli decompression.\n */\n\n#ifndef BROTLI_DEC_DECODE_H_\n#define BROTLI_DEC_DECODE_H_\n\n#include <brotli/port.h>\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>  /* IWYU pragma: export */\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/**\n * Opaque structure that holds decoder state.\n *\n * Allocated and initialized with ::BrotliDecoderCreateInstance.\n * Cleaned up and deallocated with ::BrotliDecoderDestroyInstance.\n */\ntypedef struct BrotliDecoderStateStruct BrotliDecoderState;\n\n/**\n * Result type for ::BrotliDecoderDecompress and\n * ::BrotliDecoderDecompressStream functions.\n */\ntypedef enum {\n  /** Decoding error, e.g. corrupted input or memory allocation problem. */\n  BROTLI_DECODER_RESULT_ERROR = 0,\n  /** Decoding successfully completed. */\n  BROTLI_DECODER_RESULT_SUCCESS = 1,\n  /** Partially done; should be called again with more input. */\n  BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2,\n  /** Partially done; should be called again with more output. */\n  BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3\n} BrotliDecoderResult;\n\n/**\n * Template that evaluates items of ::BrotliDecoderErrorCode.\n *\n * Example: @code {.cpp}\n * // Log Brotli error code.\n * switch (brotliDecoderErrorCode) {\n * #define CASE_(PREFIX, NAME, CODE) \\\n *   case BROTLI_DECODER ## PREFIX ## NAME: \\\n *     LOG(INFO) << \"error code:\" << #NAME; \\\n *     break;\n * #define NEWLINE_\n * BROTLI_DECODER_ERROR_CODES_LIST(CASE_, NEWLINE_)\n * #undef CASE_\n * #undef NEWLINE_\n *   default: LOG(FATAL) << \"unknown brotli error code\";\n * }\n * @endcode\n */\n#define BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE, SEPARATOR)      \\\n  BROTLI_ERROR_CODE(_, NO_ERROR, 0) SEPARATOR                              \\\n  /* Same as BrotliDecoderResult values */                                 \\\n  BROTLI_ERROR_CODE(_, SUCCESS, 1) SEPARATOR                               \\\n  BROTLI_ERROR_CODE(_, NEEDS_MORE_INPUT, 2) SEPARATOR                      \\\n  BROTLI_ERROR_CODE(_, NEEDS_MORE_OUTPUT, 3) SEPARATOR                     \\\n                                                                           \\\n  /* Errors caused by invalid input */                                     \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_NIBBLE, -1) SEPARATOR        \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, RESERVED, -2) SEPARATOR                \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_META_NIBBLE, -3) SEPARATOR   \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_ALPHABET, -4) SEPARATOR \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_SAME, -5) SEPARATOR     \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, CL_SPACE, -6) SEPARATOR                \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, HUFFMAN_SPACE, -7) SEPARATOR           \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, CONTEXT_MAP_REPEAT, -8) SEPARATOR      \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_1, -9) SEPARATOR          \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_2, -10) SEPARATOR         \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, TRANSFORM, -11) SEPARATOR              \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, DICTIONARY, -12) SEPARATOR             \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, WINDOW_BITS, -13) SEPARATOR            \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR              \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR              \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR               \\\n                                                                           \\\n  /* -17 code is reserved */                                               \\\n                                                                           \\\n  BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR           \\\n  BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR            \\\n  BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR             \\\n                                                                           \\\n  /* Memory allocation problems */                                         \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MODES, -21) SEPARATOR           \\\n  /* Literal, insert and distance trees together */                        \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, TREE_GROUPS, -22) SEPARATOR             \\\n  /* -23..-24 codes are reserved for distinct tree groups */               \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MAP, -25) SEPARATOR             \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_1, -26) SEPARATOR           \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_2, -27) SEPARATOR           \\\n  /* -28..-29 codes are reserved for dynamic ring-buffer allocation */     \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, BLOCK_TYPE_TREES, -30) SEPARATOR        \\\n                                                                           \\\n  /* \"Impossible\" states */                                                \\\n  BROTLI_ERROR_CODE(_ERROR_, UNREACHABLE, -31)\n\n/**\n * Error code for detailed logging / production debugging.\n *\n * See ::BrotliDecoderGetErrorCode and ::BROTLI_LAST_ERROR_CODE.\n */\ntypedef enum {\n#define BROTLI_COMMA_ ,\n#define BROTLI_ERROR_CODE_ENUM_ITEM_(PREFIX, NAME, CODE) \\\n    BROTLI_DECODER ## PREFIX ## NAME = CODE\n  BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_ENUM_ITEM_, BROTLI_COMMA_)\n} BrotliDecoderErrorCode;\n#undef BROTLI_ERROR_CODE_ENUM_ITEM_\n#undef BROTLI_COMMA_\n\n/**\n * The value of the last error code, negative integer.\n *\n * All other error code values are in the range from ::BROTLI_LAST_ERROR_CODE\n * to @c -1. There are also 4 other possible non-error codes @c 0 .. @c 3 in\n * ::BrotliDecoderErrorCode enumeration.\n */\n#define BROTLI_LAST_ERROR_CODE BROTLI_DECODER_ERROR_UNREACHABLE\n\n/** Options to be used with ::BrotliDecoderSetParameter. */\ntypedef enum BrotliDecoderParameter {\n  /**\n   * Disable \"canny\" ring buffer allocation strategy.\n   *\n   * Ring buffer is allocated according to window size, despite the real size of\n   * the content.\n   */\n  BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION = 0,\n  /**\n   * Flag that determines if \"Large Window Brotli\" is used.\n   */\n  BROTLI_DECODER_PARAM_LARGE_WINDOW = 1\n} BrotliDecoderParameter;\n\n/**\n * Sets the specified parameter to the given decoder instance.\n *\n * @param state decoder instance\n * @param param parameter to set\n * @param value new parameter value\n * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid\n * @returns ::BROTLI_TRUE if value is accepted\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter(\n    BrotliDecoderState* state, BrotliDecoderParameter param, uint32_t value);\n\n/**\n * Adds LZ77 prefix dictionary, adds or replaces built-in static dictionary and\n * transforms.\n *\n * Attached dictionary ownership is not transferred.\n * Data provided to this method should be kept accessible until\n * decoding is finished and decoder instance is destroyed.\n *\n * @note Dictionaries can NOT be attached after actual decoding is started.\n *\n * @param state decoder instance\n * @param type dictionary data format\n * @param data_size length of memory region pointed by @p data\n * @param data dictionary data in format corresponding to @p type\n * @returns ::BROTLI_FALSE if dictionary is corrupted,\n *          or dictionary count limit is reached\n * @returns ::BROTLI_TRUE if dictionary is accepted / attached\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderAttachDictionary(\n    BrotliDecoderState* state, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);\n\n/**\n * Creates an instance of ::BrotliDecoderState and initializes it.\n *\n * The instance can be used once for decoding and should then be destroyed with\n * ::BrotliDecoderDestroyInstance, it cannot be reused for a new decoding\n * session.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n * @returns @c 0 if instance can not be allocated or initialized\n * @returns pointer to initialized ::BrotliDecoderState otherwise\n */\nBROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\n/**\n * Deinitializes and frees ::BrotliDecoderState instance.\n *\n * @param state decoder instance to be cleaned up and deallocated\n */\nBROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state);\n\n/**\n * Performs one-shot memory-to-memory decompression.\n *\n * Decompresses the data in @p encoded_buffer into @p decoded_buffer, and sets\n * @p *decoded_size to the decompressed length.\n *\n * @param encoded_size size of @p encoded_buffer\n * @param encoded_buffer compressed data buffer with at least @p encoded_size\n *        addressable bytes\n * @param[in, out] decoded_size @b in: size of @p decoded_buffer; \\n\n *                 @b out: length of decompressed data written to\n *                 @p decoded_buffer\n * @param decoded_buffer decompressed data destination buffer\n * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory\n *          allocation failed, or @p decoded_buffer is not large enough;\n * @returns ::BROTLI_DECODER_RESULT_SUCCESS otherwise\n */\nBROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress(\n    size_t encoded_size,\n    const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],\n    size_t* decoded_size,\n    uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]);\n\n/**\n * Decompresses the input stream to the output stream.\n *\n * The values @p *available_in and @p *available_out must specify the number of\n * bytes addressable at @p *next_in and @p *next_out respectively.\n * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL.\n *\n * After each call, @p *available_in will be decremented by the amount of input\n * bytes consumed, and the @p *next_in pointer will be incremented by that\n * amount. Similarly, @p *available_out will be decremented by the amount of\n * output bytes written, and the @p *next_out pointer will be incremented by\n * that amount.\n *\n * @p total_out, if it is not a null-pointer, will be set to the number\n * of bytes decompressed since the last @p state initialization.\n *\n * @note Input is never overconsumed, so @p next_in and @p available_in could be\n * passed to the next consumer after decoding is complete.\n *\n * @param state decoder instance\n * @param[in, out] available_in @b in: amount of available input; \\n\n *                 @b out: amount of unused input\n * @param[in, out] next_in pointer to the next compressed byte\n * @param[in, out] available_out @b in: length of output buffer; \\n\n *                 @b out: remaining size of output buffer\n * @param[in, out] next_out output buffer cursor;\n *                 can be @c NULL if @p available_out is @c 0\n * @param[out] total_out number of bytes decompressed so far; can be @c NULL\n * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory\n *          allocation failed, arguments were invalid, etc.;\n *          use ::BrotliDecoderGetErrorCode to get detailed error code\n * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT decoding is blocked until\n *          more input data is provided\n * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT decoding is blocked until\n *          more output space is provided\n * @returns ::BROTLI_DECODER_RESULT_SUCCESS decoding is finished, no more\n *          input might be consumed and no more output will be produced\n */\nBROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompressStream(\n  BrotliDecoderState* state, size_t* available_in, const uint8_t** next_in,\n  size_t* available_out, uint8_t** next_out, size_t* total_out);\n\n/**\n * Checks if decoder has more output.\n *\n * @param state decoder instance\n * @returns ::BROTLI_TRUE, if decoder has some unconsumed output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderHasMoreOutput(\n    const BrotliDecoderState* state);\n\n/**\n * Acquires pointer to internal output buffer.\n *\n * This method is used to make language bindings easier and more efficient:\n *  -# push data to ::BrotliDecoderDecompressStream,\n *     until ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT is reported\n *  -# use ::BrotliDecoderTakeOutput to peek bytes and copy to language-specific\n *     entity\n *\n * Also this could be useful if there is an output stream that is able to\n * consume all the provided data (e.g. when data is saved to file system).\n *\n * @attention After every call to ::BrotliDecoderTakeOutput @p *size bytes of\n *            output are considered consumed for all consecutive calls to the\n *            instance methods; returned pointer becomes invalidated as well.\n *\n * @note Decoder output is not guaranteed to be contiguous. This means that\n *       after the size-unrestricted call to ::BrotliDecoderTakeOutput,\n *       immediate next call to ::BrotliDecoderTakeOutput may return more data.\n *\n * @param state decoder instance\n * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if\n *                 any amount could be handled; \\n\n *                 @b out: amount of data pointed by returned pointer and\n *                 considered consumed; \\n\n *                 out value is never greater than in value, unless it is @c 0\n * @returns pointer to output data\n */\nBROTLI_DEC_API const uint8_t* BrotliDecoderTakeOutput(\n    BrotliDecoderState* state, size_t* size);\n\n/**\n * Checks if instance has already consumed input.\n *\n * Instance that returns ::BROTLI_FALSE is considered \"fresh\" and could be\n * reused.\n *\n * @param state decoder instance\n * @returns ::BROTLI_TRUE if decoder has already used some input bytes\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* state);\n\n/**\n * Checks if decoder instance reached the final state.\n *\n * @param state decoder instance\n * @returns ::BROTLI_TRUE if decoder is in a state where it reached the end of\n *          the input and produced all of the output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsFinished(\n    const BrotliDecoderState* state);\n\n/**\n * Acquires a detailed error code.\n *\n * Should be used only after ::BrotliDecoderDecompressStream returns\n * ::BROTLI_DECODER_RESULT_ERROR.\n *\n * See also ::BrotliDecoderErrorString\n *\n * @param state decoder instance\n * @returns last saved error code\n */\nBROTLI_DEC_API BrotliDecoderErrorCode BrotliDecoderGetErrorCode(\n    const BrotliDecoderState* state);\n\n/**\n * Converts error code to a c-string.\n */\nBROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c);\n\n/**\n * Gets a decoder library version.\n *\n * Look at BROTLI_MAKE_HEX_VERSION for more information.\n */\nBROTLI_DEC_API uint32_t BrotliDecoderVersion(void);\n\n/**\n * Callback to fire on metadata block start.\n *\n * After this callback is fired, if @p size is not @c 0, it is followed by\n * ::brotli_decoder_metadata_chunk_func as more metadata block contents become\n * accessible.\n *\n * @param opaque callback handle\n * @param size size of metadata block\n */\ntypedef void (*brotli_decoder_metadata_start_func)(void* opaque, size_t size);\n\n/**\n * Callback to fire on metadata block chunk becomes available.\n *\n * This function can be invoked multiple times per metadata block; block should\n * be considered finished when sum of @p size matches the announced metadata\n * block size. Chunks contents pointed by @p data are transient and shouln not\n * be accessed after leaving the callback.\n *\n * @param opaque callback handle\n * @param data pointer to metadata contents\n * @param size size of metadata block chunk, at least @c 1\n */\ntypedef void (*brotli_decoder_metadata_chunk_func)(void* opaque,\n                                                   const uint8_t* data,\n                                                   size_t size);\n\n/**\n * Sets callback for receiving metadata blocks.\n *\n * @param state decoder instance\n * @param start_func callback on metadata block start\n * @param chunk_func callback on metadata block chunk\n * @param opaque callback handle\n */\nBROTLI_DEC_API void BrotliDecoderSetMetadataCallbacks(\n    BrotliDecoderState* state,\n    brotli_decoder_metadata_start_func start_func,\n    brotli_decoder_metadata_chunk_func chunk_func, void* opaque);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n} /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_DECODE_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/include/brotli/encode.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * API for Brotli compression.\n */\n\n#ifndef BROTLI_ENC_ENCODE_H_\n#define BROTLI_ENC_ENCODE_H_\n\n#include <brotli/port.h>\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>  /* IWYU pragma: export */\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/** Minimal value for ::BROTLI_PARAM_LGWIN parameter. */\n#define BROTLI_MIN_WINDOW_BITS 10\n/**\n * Maximal value for ::BROTLI_PARAM_LGWIN parameter.\n *\n * @note equal to @c BROTLI_MAX_DISTANCE_BITS constant.\n */\n#define BROTLI_MAX_WINDOW_BITS 24\n/**\n * Maximal value for ::BROTLI_PARAM_LGWIN parameter\n * in \"Large Window Brotli\" (32-bit).\n */\n#define BROTLI_LARGE_MAX_WINDOW_BITS 30\n/** Minimal value for ::BROTLI_PARAM_LGBLOCK parameter. */\n#define BROTLI_MIN_INPUT_BLOCK_BITS 16\n/** Maximal value for ::BROTLI_PARAM_LGBLOCK parameter. */\n#define BROTLI_MAX_INPUT_BLOCK_BITS 24\n/** Minimal value for ::BROTLI_PARAM_QUALITY parameter. */\n#define BROTLI_MIN_QUALITY 0\n/** Maximal value for ::BROTLI_PARAM_QUALITY parameter. */\n#define BROTLI_MAX_QUALITY 11\n\n/** Options for ::BROTLI_PARAM_MODE parameter. */\ntypedef enum BrotliEncoderMode {\n  /**\n   * Default compression mode.\n   *\n   * In this mode compressor does not know anything in advance about the\n   * properties of the input.\n   */\n  BROTLI_MODE_GENERIC = 0,\n  /** Compression mode for UTF-8 formatted text input. */\n  BROTLI_MODE_TEXT = 1,\n  /** Compression mode used in WOFF 2.0. */\n  BROTLI_MODE_FONT = 2\n} BrotliEncoderMode;\n\n/** Default value for ::BROTLI_PARAM_QUALITY parameter. */\n#define BROTLI_DEFAULT_QUALITY 11\n/** Default value for ::BROTLI_PARAM_LGWIN parameter. */\n#define BROTLI_DEFAULT_WINDOW 22\n/** Default value for ::BROTLI_PARAM_MODE parameter. */\n#define BROTLI_DEFAULT_MODE BROTLI_MODE_GENERIC\n\n/** Operations that can be performed by streaming encoder. */\ntypedef enum BrotliEncoderOperation {\n  /**\n   * Process input.\n   *\n   * Encoder may postpone producing output, until it has processed enough input.\n   */\n  BROTLI_OPERATION_PROCESS = 0,\n  /**\n   * Produce output for all processed input.\n   *\n   * Actual flush is performed when input stream is depleted and there is enough\n   * space in output stream. This means that client should repeat\n   * ::BROTLI_OPERATION_FLUSH operation until @p available_in becomes @c 0, and\n   * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired\n   * via ::BrotliEncoderTakeOutput, then operation should be repeated after\n   * output buffer is drained.\n   *\n   * @warning Until flush is complete, client @b SHOULD @b NOT swap,\n   *          reduce or extend input stream.\n   *\n   * When flush is complete, output data will be sufficient for decoder to\n   * reproduce all the given input.\n   */\n  BROTLI_OPERATION_FLUSH = 1,\n  /**\n   * Finalize the stream.\n   *\n   * Actual finalization is performed when input stream is depleted and there is\n   * enough space in output stream. This means that client should repeat\n   * ::BROTLI_OPERATION_FINISH operation until @p available_in becomes @c 0, and\n   * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired\n   * via ::BrotliEncoderTakeOutput, then operation should be repeated after\n   * output buffer is drained.\n   *\n   * @warning Until finalization is complete, client @b SHOULD @b NOT swap,\n   *          reduce or extend input stream.\n   *\n   * Helper function ::BrotliEncoderIsFinished checks if stream is finalized and\n   * output fully dumped.\n   *\n   * Adding more input data to finalized stream is impossible.\n   */\n  BROTLI_OPERATION_FINISH = 2,\n  /**\n   * Emit metadata block to stream.\n   *\n   * Metadata is opaque to Brotli: neither encoder, nor decoder processes this\n   * data or relies on it. It may be used to pass some extra information from\n   * encoder client to decoder client without interfering with main data stream.\n   *\n   * @note Encoder may emit empty metadata blocks internally, to pad encoded\n   *       stream to byte boundary.\n   *\n   * @warning Until emitting metadata is complete client @b SHOULD @b NOT swap,\n   *          reduce or extend input stream.\n   *\n   * @warning The whole content of input buffer is considered to be the content\n   *          of metadata block. Do @b NOT @e append metadata to input stream,\n   *          before it is depleted with other operations.\n   *\n   * Stream is soft-flushed before metadata block is emitted. Metadata block\n   * @b MUST be no longer than than 16MiB.\n   */\n  BROTLI_OPERATION_EMIT_METADATA = 3\n} BrotliEncoderOperation;\n\n/** Options to be used with ::BrotliEncoderSetParameter. */\ntypedef enum BrotliEncoderParameter {\n  /**\n   * Tune encoder for specific input.\n   *\n   * ::BrotliEncoderMode enumerates all available values.\n   */\n  BROTLI_PARAM_MODE = 0,\n  /**\n   * The main compression speed-density lever.\n   *\n   * The higher the quality, the slower the compression. Range is\n   * from ::BROTLI_MIN_QUALITY to ::BROTLI_MAX_QUALITY.\n   */\n  BROTLI_PARAM_QUALITY = 1,\n  /**\n   * Recommended sliding LZ77 window size.\n   *\n   * Encoder may reduce this value, e.g. if input is much smaller than\n   * window size.\n   *\n   * Window size is `(1 << value) - 16`.\n   *\n   * Range is from ::BROTLI_MIN_WINDOW_BITS to ::BROTLI_MAX_WINDOW_BITS.\n   */\n  BROTLI_PARAM_LGWIN = 2,\n  /**\n   * Recommended input block size.\n   *\n   * Encoder may reduce this value, e.g. if input is much smaller than input\n   * block size.\n   *\n   * Range is from ::BROTLI_MIN_INPUT_BLOCK_BITS to\n   * ::BROTLI_MAX_INPUT_BLOCK_BITS.\n   *\n   * @note Bigger input block size allows better compression, but consumes more\n   *       memory. \\n The rough formula of memory used for temporary input\n   *       storage is `3 << lgBlock`.\n   */\n  BROTLI_PARAM_LGBLOCK = 3,\n  /**\n   * Flag that affects usage of \"literal context modeling\" format feature.\n   *\n   * This flag is a \"decoding-speed vs compression ratio\" trade-off.\n   */\n  BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING = 4,\n  /**\n   * Estimated total input size for all ::BrotliEncoderCompressStream calls.\n   *\n   * The default value is 0, which means that the total input size is unknown.\n   */\n  BROTLI_PARAM_SIZE_HINT = 5,\n  /**\n   * Flag that determines if \"Large Window Brotli\" is used.\n   */\n  BROTLI_PARAM_LARGE_WINDOW = 6,\n  /**\n   * Recommended number of postfix bits (NPOSTFIX).\n   *\n   * Encoder may change this value.\n   *\n   * Range is from 0 to ::BROTLI_MAX_NPOSTFIX.\n   */\n  BROTLI_PARAM_NPOSTFIX = 7,\n  /**\n   * Recommended number of direct distance codes (NDIRECT).\n   *\n   * Encoder may change this value.\n   *\n   * Range is from 0 to (15 << NPOSTFIX) in steps of (1 << NPOSTFIX).\n   */\n  BROTLI_PARAM_NDIRECT = 8,\n  /**\n   * Number of bytes of input stream already processed by a different instance.\n   *\n   * @note It is important to configure all the encoder instances with same\n   *       parameters (except this one) in order to allow all the encoded parts\n   *       obey the same restrictions implied by header.\n   *\n   * If offset is not 0, then stream header is omitted.\n   * In any case output start is byte aligned, so for proper streams stitching\n   * \"predecessor\" stream must be flushed.\n   *\n   * Range is not artificially limited, but all the values greater or equal to\n   * maximal window size have the same effect. Values greater than 2**30 are not\n   * allowed.\n   */\n  BROTLI_PARAM_STREAM_OFFSET = 9\n} BrotliEncoderParameter;\n\n/**\n * Opaque structure that holds encoder state.\n *\n * Allocated and initialized with ::BrotliEncoderCreateInstance.\n * Cleaned up and deallocated with ::BrotliEncoderDestroyInstance.\n */\ntypedef struct BrotliEncoderStateStruct BrotliEncoderState;\n\n/**\n * Sets the specified parameter to the given encoder instance.\n *\n * @param state encoder instance\n * @param param parameter to set\n * @param value new parameter value\n * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid\n * @returns ::BROTLI_FALSE if value of parameter can not be changed at current\n *          encoder state (e.g. when encoding is started, window size might be\n *          already encoded and therefore it is impossible to change it)\n * @returns ::BROTLI_TRUE if value is accepted\n * @warning invalid values might be accepted in case they would not break\n *          encoding process.\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter(\n    BrotliEncoderState* state, BrotliEncoderParameter param, uint32_t value);\n\n/**\n * Creates an instance of ::BrotliEncoderState and initializes it.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n * @returns @c 0 if instance can not be allocated or initialized\n * @returns pointer to initialized ::BrotliEncoderState otherwise\n */\nBROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\n/**\n * Deinitializes and frees ::BrotliEncoderState instance.\n *\n * @param state decoder instance to be cleaned up and deallocated\n */\nBROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState* state);\n\n/* Opaque type for pointer to different possible internal structures containing\n   dictionary prepared for the encoder */\ntypedef struct BrotliEncoderPreparedDictionaryStruct\n    BrotliEncoderPreparedDictionary;\n\n/**\n * Prepares a shared dictionary from the given file format for the encoder.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @warning Created instance is \"lean\"; it does not contain copy of @p data,\n *          rather it contains only pointer to it; therefore,\n *          @p data @b MUST outlive the created instance.\n *\n * @param type type of dictionary stored in data\n * @param data_size size of @p data buffer\n * @param data pointer to the dictionary data\n * @param quality the maximum Brotli quality to prepare the dictionary for,\n *        use BROTLI_MAX_QUALITY by default\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n */\nBROTLI_ENC_API BrotliEncoderPreparedDictionary*\nBrotliEncoderPrepareDictionary(BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)],\n    int quality,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\nBROTLI_ENC_API void BrotliEncoderDestroyPreparedDictionary(\n    BrotliEncoderPreparedDictionary* dictionary);\n\n/**\n * Attaches a prepared dictionary of any type to the encoder. Can be used\n * multiple times to attach multiple dictionaries. The dictionary type was\n * determined by BrotliEncoderPrepareDictionary. Multiple raw prefix\n * dictionaries and/or max 1 serialized dictionary with custom words can be\n * attached.\n *\n * @returns ::BROTLI_FALSE in case of error\n * @returns ::BROTLI_TRUE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(\n    BrotliEncoderState* state,\n    const BrotliEncoderPreparedDictionary* dictionary);\n\n/**\n * Calculates the output size bound for the given @p input_size.\n *\n * @warning Result is only valid if quality is at least @c 2 and, in\n *          case ::BrotliEncoderCompressStream was used, no flushes\n *          (::BROTLI_OPERATION_FLUSH) were performed.\n *\n * @param input_size size of projected input\n * @returns @c 0 if result does not fit @c size_t\n */\nBROTLI_ENC_API size_t BrotliEncoderMaxCompressedSize(size_t input_size);\n\n/**\n * Performs one-shot memory-to-memory compression.\n *\n * Compresses the data in @p input_buffer into @p encoded_buffer, and sets\n * @p *encoded_size to the compressed length.\n *\n * @note If ::BrotliEncoderMaxCompressedSize(@p input_size) returns non-zero\n *       value, then output is guaranteed to be no longer than that.\n *\n * @note If @p lgwin is greater than ::BROTLI_MAX_WINDOW_BITS then resulting\n *       stream might be incompatible with RFC 7932; to decode such streams,\n *       decoder should be configured with\n *       ::BROTLI_DECODER_PARAM_LARGE_WINDOW = @c 1\n *\n * @param quality quality parameter value, e.g. ::BROTLI_DEFAULT_QUALITY\n * @param lgwin lgwin parameter value, e.g. ::BROTLI_DEFAULT_WINDOW\n * @param mode mode parameter value, e.g. ::BROTLI_DEFAULT_MODE\n * @param input_size size of @p input_buffer\n * @param input_buffer input data buffer with at least @p input_size\n *        addressable bytes\n * @param[in, out] encoded_size @b in: size of @p encoded_buffer; \\n\n *                 @b out: length of compressed data written to\n *                 @p encoded_buffer, or @c 0 if compression fails\n * @param encoded_buffer compressed data destination buffer\n * @returns ::BROTLI_FALSE in case of compression error\n * @returns ::BROTLI_FALSE if output buffer is too small\n * @returns ::BROTLI_TRUE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress(\n    int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,\n    const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],\n    size_t* encoded_size,\n    uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]);\n\n/**\n * Compresses input stream to output stream.\n *\n * The values @p *available_in and @p *available_out must specify the number of\n * bytes addressable at @p *next_in and @p *next_out respectively.\n * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL.\n *\n * After each call, @p *available_in will be decremented by the amount of input\n * bytes consumed, and the @p *next_in pointer will be incremented by that\n * amount. Similarly, @p *available_out will be decremented by the amount of\n * output bytes written, and the @p *next_out pointer will be incremented by\n * that amount.\n *\n * @p total_out, if it is not a null-pointer, will be set to the number\n * of bytes compressed since the last @p state initialization.\n *\n *\n *\n * Internally workflow consists of 3 tasks:\n *  -# (optionally) copy input data to internal buffer\n *  -# actually compress data and (optionally) store it to internal buffer\n *  -# (optionally) copy compressed bytes from internal buffer to output stream\n *\n * Whenever all 3 tasks can't move forward anymore, or error occurs, this\n * method returns the control flow to caller.\n *\n * @p op is used to perform flush, finish the stream, or inject metadata block.\n * See ::BrotliEncoderOperation for more information.\n *\n * Flushing the stream means forcing encoding of all input passed to encoder and\n * completing the current output block, so it could be fully decoded by stream\n * decoder. To perform flush set @p op to ::BROTLI_OPERATION_FLUSH.\n * Under some circumstances (e.g. lack of output stream capacity) this operation\n * would require several calls to ::BrotliEncoderCompressStream. The method must\n * be called again until both input stream is depleted and encoder has no more\n * output (see ::BrotliEncoderHasMoreOutput) after the method is called.\n *\n * Finishing the stream means encoding of all input passed to encoder and\n * adding specific \"final\" marks, so stream decoder could determine that stream\n * is complete. To perform finish set @p op to ::BROTLI_OPERATION_FINISH.\n * Under some circumstances (e.g. lack of output stream capacity) this operation\n * would require several calls to ::BrotliEncoderCompressStream. The method must\n * be called again until both input stream is depleted and encoder has no more\n * output (see ::BrotliEncoderHasMoreOutput) after the method is called.\n *\n * @warning When flushing and finishing, @p op should not change until operation\n *          is complete; input stream should not be swapped, reduced or\n *          extended as well.\n *\n * @param state encoder instance\n * @param op requested operation\n * @param[in, out] available_in @b in: amount of available input; \\n\n *                 @b out: amount of unused input\n * @param[in, out] next_in pointer to the next input byte\n * @param[in, out] available_out @b in: length of output buffer; \\n\n *                 @b out: remaining size of output buffer\n * @param[in, out] next_out compressed output buffer cursor;\n *                 can be @c NULL if @p available_out is @c 0\n * @param[out] total_out number of bytes produced so far; can be @c NULL\n * @returns ::BROTLI_FALSE if there was an error\n * @returns ::BROTLI_TRUE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompressStream(\n    BrotliEncoderState* state, BrotliEncoderOperation op, size_t* available_in,\n    const uint8_t** next_in, size_t* available_out, uint8_t** next_out,\n    size_t* total_out);\n\n/**\n * Checks if encoder instance reached the final state.\n *\n * @param state encoder instance\n * @returns ::BROTLI_TRUE if encoder is in a state where it reached the end of\n *          the input and produced all of the output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* state);\n\n/**\n * Checks if encoder has more output.\n *\n * @param state encoder instance\n * @returns ::BROTLI_TRUE, if encoder has some unconsumed output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(\n    BrotliEncoderState* state);\n\n/**\n * Acquires pointer to internal output buffer.\n *\n * This method is used to make language bindings easier and more efficient:\n *  -# push data to ::BrotliEncoderCompressStream,\n *     until ::BrotliEncoderHasMoreOutput returns BROTLI_TRUE\n *  -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific\n *     entity\n *\n * Also this could be useful if there is an output stream that is able to\n * consume all the provided data (e.g. when data is saved to file system).\n *\n * @attention After every call to ::BrotliEncoderTakeOutput @p *size bytes of\n *            output are considered consumed for all consecutive calls to the\n *            instance methods; returned pointer becomes invalidated as well.\n *\n * @note Encoder output is not guaranteed to be contiguous. This means that\n *       after the size-unrestricted call to ::BrotliEncoderTakeOutput,\n *       immediate next call to ::BrotliEncoderTakeOutput may return more data.\n *\n * @param state encoder instance\n * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if\n *                 any amount could be handled; \\n\n *                 @b out: amount of data pointed by returned pointer and\n *                 considered consumed; \\n\n *                 out value is never greater than in value, unless it is @c 0\n * @returns pointer to output data\n */\nBROTLI_ENC_API const uint8_t* BrotliEncoderTakeOutput(\n    BrotliEncoderState* state, size_t* size);\n\n/* Returns the estimated peak memory usage (in bytes) of the BrotliCompress()\n   function, not counting the memory needed for the input and output. */\nBROTLI_ENC_EXTRA_API size_t BrotliEncoderEstimatePeakMemoryUsage(\n    int quality, int lgwin, size_t input_size);\n/* Returns 0 if dictionary is not valid; otherwise returns allocation size. */\nBROTLI_ENC_EXTRA_API size_t BrotliEncoderGetPreparedDictionarySize(\n    const BrotliEncoderPreparedDictionary* dictionary);\n\n/**\n * Gets an encoder library version.\n *\n * Look at BROTLI_MAKE_HEX_VERSION for more information.\n */\nBROTLI_ENC_API uint32_t BrotliEncoderVersion(void);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENCODE_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/include/brotli/port.h",
    "content": "﻿/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Macros for compiler / platform specific API declarations. */\n\n#ifndef BROTLI_COMMON_PORT_H_\n#define BROTLI_COMMON_PORT_H_\n\n/* The following macros were borrowed from https://github.com/nemequ/hedley\n * with permission of original author - Evan Nemerson <evan@nemerson.com> */\n\n/* >>> >>> >>> hedley macros */\n\n#define BROTLI_MAKE_VERSION(major, minor, revision) \\\n  (((major) * 1000000) + ((minor) * 1000) + (revision))\n\n#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)\n#define BROTLI_GNUC_VERSION \\\n  BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)\n#elif defined(__GNUC__)\n#define BROTLI_GNUC_VERSION BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, 0)\n#endif\n\n#if defined(BROTLI_GNUC_VERSION)\n#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_GNUC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)\n#define BROTLI_MSVC_VERSION                                \\\n  BROTLI_MAKE_VERSION((_MSC_FULL_VER / 10000000),          \\\n                      (_MSC_FULL_VER % 10000000) / 100000, \\\n                      (_MSC_FULL_VER % 100000) / 100)\n#elif defined(_MSC_FULL_VER)\n#define BROTLI_MSVC_VERSION                              \\\n  BROTLI_MAKE_VERSION((_MSC_FULL_VER / 1000000),         \\\n                      (_MSC_FULL_VER % 1000000) / 10000, \\\n                      (_MSC_FULL_VER % 10000) / 10)\n#elif defined(_MSC_VER)\n#define BROTLI_MSVC_VERSION \\\n  BROTLI_MAKE_VERSION(_MSC_VER / 100, _MSC_VER % 100, 0)\n#endif\n\n#if !defined(_MSC_VER)\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) (0)\n#elif defined(_MSC_VER) && (_MSC_VER >= 1400)\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \\\n  (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))\n#elif defined(_MSC_VER) && (_MSC_VER >= 1200)\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \\\n  (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))\n#else\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \\\n  (_MSC_VER >= ((major * 100) + (minor)))\n#endif\n\n#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)\n#define BROTLI_INTEL_VERSION                   \\\n  BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100,  \\\n                      __INTEL_COMPILER % 100,  \\\n                      __INTEL_COMPILER_UPDATE)\n#elif defined(__INTEL_COMPILER)\n#define BROTLI_INTEL_VERSION \\\n  BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)\n#endif\n\n#if defined(BROTLI_INTEL_VERSION)\n#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_INTEL_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__PGI) && \\\n    defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)\n#define BROTLI_PGI_VERSION \\\n  BROTLI_MAKE_VERSION(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)\n#endif\n\n#if defined(BROTLI_PGI_VERSION)\n#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_PGI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)\n#define BROTLI_SUNPRO_VERSION                                       \\\n  BROTLI_MAKE_VERSION(                                              \\\n    (((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \\\n    (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf),   \\\n    (__SUNPRO_C & 0xf) * 10)\n#elif defined(__SUNPRO_C)\n#define BROTLI_SUNPRO_VERSION                  \\\n  BROTLI_MAKE_VERSION((__SUNPRO_C >> 8) & 0xf, \\\n                      (__SUNPRO_C >> 4) & 0xf, \\\n                      (__SUNPRO_C) & 0xf)\n#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)\n#define BROTLI_SUNPRO_VERSION                                         \\\n  BROTLI_MAKE_VERSION(                                                \\\n    (((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \\\n    (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf),   \\\n    (__SUNPRO_CC & 0xf) * 10)\n#elif defined(__SUNPRO_CC)\n#define BROTLI_SUNPRO_VERSION                   \\\n  BROTLI_MAKE_VERSION((__SUNPRO_CC >> 8) & 0xf, \\\n                      (__SUNPRO_CC >> 4) & 0xf, \\\n                      (__SUNPRO_CC) & 0xf)\n#endif\n\n#if defined(BROTLI_SUNPRO_VERSION)\n#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_SUNPRO_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)\n#define BROTLI_ARM_VERSION                                       \\\n  BROTLI_MAKE_VERSION((__ARMCOMPILER_VERSION / 1000000),         \\\n                      (__ARMCOMPILER_VERSION % 1000000) / 10000, \\\n                      (__ARMCOMPILER_VERSION % 10000) / 100)\n#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)\n#define BROTLI_ARM_VERSION                                 \\\n  BROTLI_MAKE_VERSION((__ARMCC_VERSION / 1000000),         \\\n                      (__ARMCC_VERSION % 1000000) / 10000, \\\n                      (__ARMCC_VERSION % 10000) / 100)\n#endif\n\n#if defined(BROTLI_ARM_VERSION)\n#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_ARM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__ibmxl__)\n#define BROTLI_IBM_VERSION                    \\\n  BROTLI_MAKE_VERSION(__ibmxl_version__,      \\\n                      __ibmxl_release__,      \\\n                      __ibmxl_modification__)\n#elif defined(__xlC__) && defined(__xlC_ver__)\n#define BROTLI_IBM_VERSION \\\n  BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)\n#elif defined(__xlC__)\n#define BROTLI_IBM_VERSION BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, 0)\n#endif\n\n#if defined(BROTLI_IBM_VERSION)\n#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_IBM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__TI_COMPILER_VERSION__)\n#define BROTLI_TI_VERSION                                         \\\n  BROTLI_MAKE_VERSION((__TI_COMPILER_VERSION__ / 1000000),        \\\n                      (__TI_COMPILER_VERSION__ % 1000000) / 1000, \\\n                      (__TI_COMPILER_VERSION__ % 1000))\n#endif\n\n#if defined(BROTLI_TI_VERSION)\n#define BROTLI_TI_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_TI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_TI_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__IAR_SYSTEMS_ICC__)\n#if __VER__ > 1000\n#define BROTLI_IAR_VERSION                     \\\n  BROTLI_MAKE_VERSION((__VER__ / 1000000),     \\\n                      (__VER__ / 1000) % 1000, \\\n                      (__VER__ % 1000))\n#else\n#define BROTLI_IAR_VERSION BROTLI_MAKE_VERSION(VER / 100, __VER__ % 100, 0)\n#endif\n#endif\n\n#if defined(BROTLI_IAR_VERSION)\n#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_IAR_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__TINYC__)\n#define BROTLI_TINYC_VERSION \\\n  BROTLI_MAKE_VERSION(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)\n#endif\n\n#if defined(BROTLI_TINYC_VERSION)\n#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_TINYC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__has_attribute)\n#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \\\n  __has_attribute(attribute)\n#else\n#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \\\n  BROTLI_GNUC_VERSION_CHECK(major, minor, patch)\n#endif\n\n#if defined(__has_builtin)\n#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \\\n  __has_builtin(builtin)\n#else\n#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \\\n  BROTLI_GNUC_VERSION_CHECK(major, minor, patch)\n#endif\n\n#if defined(__has_feature)\n#define BROTLI_HAS_FEATURE(feature) __has_feature(feature)\n#else\n#define BROTLI_HAS_FEATURE(feature) (0)\n#endif\n\n#if defined(_WIN32) || defined(__CYGWIN__)\n#define BROTLI_PUBLIC\n#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) ||                         \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                             \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                         \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                            \\\n    BROTLI_IBM_VERSION_CHECK(13, 1, 0) ||                           \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) &&                            \\\n     defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))\n#define BROTLI_PUBLIC __attribute__ ((visibility (\"default\")))\n#else\n#define BROTLI_PUBLIC\n#endif\n\n#if defined(_WIN32) || defined(__CYGWIN__)\n#define BROTLI_INTERNAL\n#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) ||                         \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                             \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                         \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                            \\\n    BROTLI_IBM_VERSION_CHECK(13, 1, 0) ||                           \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) &&                            \\\n     defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))\n#define BROTLI_INTERNAL __attribute__ ((visibility (\"hidden\")))\n#else\n#define BROTLI_INTERNAL\n#endif\n\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) &&   \\\n    !defined(__STDC_NO_VLA__) && !defined(__cplusplus) &&           \\\n    !defined(__PGI) && !defined(__PGIC__) && !defined(__TINYC__) && \\\n    !defined(__clang__)\n#define BROTLI_ARRAY_PARAM(name) (name)\n#else\n#define BROTLI_ARRAY_PARAM(name)\n#endif\n\n/* <<< <<< <<< end of hedley macros. */\n\n#if defined(BROTLI_SHARED_COMPILATION)\n#if defined(_WIN32)\n#if defined(BROTLICOMMON_SHARED_COMPILATION)\n#define BROTLI_COMMON_API __declspec(dllexport)\n#else  /* !BROTLICOMMON_SHARED_COMPILATION */\n#define BROTLI_COMMON_API __declspec(dllimport)\n#endif  /* BROTLICOMMON_SHARED_COMPILATION */\n#if defined(BROTLIDEC_SHARED_COMPILATION)\n#define BROTLI_DEC_API __declspec(dllexport)\n#else   /* !BROTLIDEC_SHARED_COMPILATION */\n#define BROTLI_DEC_API __declspec(dllimport)\n#endif  /* BROTLIDEC_SHARED_COMPILATION */\n#if defined(BROTLIENC_SHARED_COMPILATION)\n#define BROTLI_ENC_API __declspec(dllexport)\n#else  /* !BROTLIENC_SHARED_COMPILATION */\n#define BROTLI_ENC_API __declspec(dllimport)\n#endif  /* BROTLIENC_SHARED_COMPILATION */\n#else  /* !_WIN32 */\n#define BROTLI_COMMON_API BROTLI_PUBLIC\n#define BROTLI_DEC_API BROTLI_PUBLIC\n#define BROTLI_ENC_API BROTLI_PUBLIC\n#endif  /* _WIN32 */\n#else  /* BROTLI_SHARED_COMPILATION */\n#define BROTLI_COMMON_API\n#define BROTLI_DEC_API\n#define BROTLI_ENC_API\n#endif\n\n#if defined(BROTLI_BUILD_ENC_EXTRA_API)\n#define BROTLI_ENC_EXTRA_API BROTLI_ENC_API\n#else\n#define BROTLI_ENC_EXTRA_API BROTLI_INTERNAL\n#endif\n\n#endif  /* BROTLI_COMMON_PORT_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/include/brotli/shared_dictionary.h",
    "content": "﻿/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* (Opaque) Shared Dictionary definition and utilities. */\n\n#ifndef BROTLI_COMMON_SHARED_DICTIONARY_H_\n#define BROTLI_COMMON_SHARED_DICTIONARY_H_\n\n#include <brotli/port.h>\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH 4\n#define SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH 31\n#define SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS 64\n#define SHARED_BROTLI_MAX_COMPOUND_DICTS 15\n\n/**\n * Opaque structure that holds shared dictionary data.\n *\n * Allocated and initialized with ::BrotliSharedDictionaryCreateInstance.\n * Cleaned up and deallocated with ::BrotliSharedDictionaryDestroyInstance.\n */\ntypedef struct BrotliSharedDictionaryStruct BrotliSharedDictionary;\n\n/**\n * Input data type for ::BrotliSharedDictionaryAttach.\n */\ntypedef enum BrotliSharedDictionaryType {\n  /** Raw LZ77 prefix dictionary. */\n  BROTLI_SHARED_DICTIONARY_RAW = 0,\n  /** Serialized shared dictionary.\n   *\n   * DO NOT USE: methods accepting this value will fail.\n   */\n  BROTLI_SHARED_DICTIONARY_SERIALIZED = 1\n} BrotliSharedDictionaryType;\n\n/**\n * Creates an instance of ::BrotliSharedDictionary.\n *\n * Fresh instance has default word dictionary and transforms\n * and no LZ77 prefix dictionary.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n * @returns @c 0 if instance can not be allocated or initialized\n * @returns pointer to initialized ::BrotliSharedDictionary otherwise\n */\nBROTLI_COMMON_API BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\n/**\n * Deinitializes and frees ::BrotliSharedDictionary instance.\n *\n * @param dict shared dictionary instance to be cleaned up and deallocated\n */\nBROTLI_COMMON_API void BrotliSharedDictionaryDestroyInstance(\n    BrotliSharedDictionary* dict);\n\n/**\n * Attaches dictionary to a given instance of ::BrotliSharedDictionary.\n *\n * Dictionary to be attached is represented in a serialized format as a region\n * of memory.\n *\n * Provided data it partially referenced by a resulting (compound) dictionary,\n * and should be kept untouched, while at least one compound dictionary uses it.\n * This way memory overhead is kept minimal by the cost of additional resource\n * management.\n *\n * @param dict dictionary to extend\n * @param type type of dictionary to attach\n * @param data_size size of @p data\n * @param data serialized dictionary of type @p type, with at least @p data_size\n *        addressable bytes\n * @returns ::BROTLI_TRUE if provided dictionary is successfully attached\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_COMMON_API BROTLI_BOOL BrotliSharedDictionaryAttach(\n    BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_SHARED_DICTIONARY_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/Brotli/include/brotli/types.h",
    "content": "﻿/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * Common types used in decoder and encoder API.\n */\n\n#ifndef BROTLI_COMMON_TYPES_H_\n#define BROTLI_COMMON_TYPES_H_\n\n#include <stddef.h>  /* IWYU pragma: export */\n\n#if defined(_MSC_VER) && (_MSC_VER < 1600)\ntypedef __int8 int8_t;\ntypedef unsigned __int8 uint8_t;\ntypedef __int16 int16_t;\ntypedef unsigned __int16 uint16_t;\ntypedef __int32 int32_t;\ntypedef unsigned __int32 uint32_t;\ntypedef unsigned __int64 uint64_t;\ntypedef __int64 int64_t;\n#else\n#include <stdint.h>  /* IWYU pragma: export */\n#endif  /* defined(_MSC_VER) && (_MSC_VER < 1600) */\n\n/**\n * A portable @c bool replacement.\n *\n * ::BROTLI_BOOL is a \"documentation\" type: actually it is @c int, but in API it\n * denotes a type, whose only values are ::BROTLI_TRUE and ::BROTLI_FALSE.\n *\n * ::BROTLI_BOOL values passed to Brotli should either be ::BROTLI_TRUE or\n * ::BROTLI_FALSE, or be a result of ::TO_BROTLI_BOOL macros.\n *\n * ::BROTLI_BOOL values returned by Brotli should not be tested for equality\n * with @c true, @c false, ::BROTLI_TRUE, ::BROTLI_FALSE, but rather should be\n * evaluated, for example: @code{.cpp}\n * if (SomeBrotliFunction(encoder, BROTLI_TRUE) &&\n *     !OtherBrotliFunction(decoder, BROTLI_FALSE)) {\n *   bool x = !!YetAnotherBrotliFunction(encoder, TO_BROLTI_BOOL(2 * 2 == 4));\n *   DoSomething(x);\n * }\n * @endcode\n */\n#define BROTLI_BOOL int\n/** Portable @c true replacement. */\n#define BROTLI_TRUE 1\n/** Portable @c false replacement. */\n#define BROTLI_FALSE 0\n/** @c bool to ::BROTLI_BOOL conversion macros. */\n#define TO_BROTLI_BOOL(X) (!!(X) ? BROTLI_TRUE : BROTLI_FALSE)\n\n#define BROTLI_MAKE_UINT64_T(high, low) ((((uint64_t)(high)) << 32) | low)\n\n#define BROTLI_UINT32_MAX (~((uint32_t)0))\n#define BROTLI_SIZE_MAX (~((size_t)0))\n\n/**\n * Allocating function pointer type.\n *\n * @param opaque custom memory manager handle provided by client\n * @param size requested memory region size; can not be @c 0\n * @returns @c 0 in the case of failure\n * @returns a valid pointer to a memory region of at least @p size bytes\n *          long otherwise\n */\ntypedef void* (*brotli_alloc_func)(void* opaque, size_t size);\n\n/**\n * Deallocating function pointer type.\n *\n * This function @b SHOULD do nothing if @p address is @c 0.\n *\n * @param opaque custom memory manager handle provided by client\n * @param address memory region pointer returned by ::brotli_alloc_func, or @c 0\n */\ntypedef void (*brotli_free_func)(void* opaque, void* address);\n\n#endif  /* BROTLI_COMMON_TYPES_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/atomic.h",
    "content": "﻿/*\n * Copyright (c) 2018 Conor McCarthy\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n *\n */\n\n#ifndef FL2_ATOMIC_H\n#define FL2_ATOMIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* atomic add */\n\n#if !defined(FL2_SINGLETHREAD) && defined(_WIN32)\n\n#ifdef WINVER\n#undef WINVER\n#endif\n#define WINVER       0x0600\n\n#ifdef _WIN32_WINNT\n#undef _WIN32_WINNT\n#endif\n#define _WIN32_WINNT 0x0600\n\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n\n#include <windows.h>\n\n\ntypedef LONG volatile FL2_atomic;\n#define ATOMIC_INITIAL_VALUE -1\n#define FL2_atomic_increment(n) InterlockedIncrement(&n)\n#define FL2_atomic_add(n, a) InterlockedAdd(&n, a)\n#define FL2_nonAtomic_increment(n) (++n)\n\n#elif !defined(FL2_SINGLETHREAD) && defined(__GNUC__)\n\ntypedef long FL2_atomic;\n#define ATOMIC_INITIAL_VALUE 0\n#define FL2_atomic_increment(n) __sync_fetch_and_add(&n, 1)\n#define FL2_atomic_add(n, a) __sync_fetch_and_add(&n, a)\n#define FL2_nonAtomic_increment(n) (n++)\n\n#elif !defined(FL2_SINGLETHREAD) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) /* C11 */\n\n#include <stdatomic.h>\n\ntypedef _Atomic long FL2_atomic;\n#define ATOMIC_INITIAL_VALUE 0\n#define FL2_atomic_increment(n) atomic_fetch_add(&n, 1)\n#define FL2_atomic_add(n, a) atomic_fetch_add(&n, a)\n#define FL2_nonAtomic_increment(n) (n++)\n\n#else  /* No atomics */\n\n#\tifndef FL2_SINGLETHREAD\n#\t\terror  No atomic operations available. Change compiler config or define FL2_SINGLETHREAD for the entire build.\n#\tendif\n\ntypedef long FL2_atomic;\n#define ATOMIC_INITIAL_VALUE 0\n#define FL2_atomic_increment(n) (n++)\n#define FL2_atomic_add(n, a) (n += (a))\n#define FL2_nonAtomic_increment(n) (n++)\n\n#endif /* FL2_SINGLETHREAD */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* FL2_ATOMIC_H */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/compiler.h",
    "content": "﻿/* NanaZip Header File Redirection */\n#include \"../Zstandard/common/compiler.h\"\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/count.h",
    "content": "﻿/*\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COUNT_H_\n#define ZSTD_COUNT_H_\n\n#include \"mem.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-*************************************\n*  Match length counter\n***************************************/\nstatic unsigned ZSTD_NbCommonBytes(register size_t val)\n{\n    if (MEM_isLittleEndian()) {\n        if (MEM_64bits()) {\n#       if defined(_MSC_VER) && defined(_WIN64)\n            unsigned long r = 0;\n            _BitScanForward64(&r, (U64)val);\n            return (unsigned)(r >> 3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 4)\n            return (__builtin_ctzll((U64)val) >> 3);\n#       else\n            static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2,\n                0, 3, 1, 3, 1, 4, 2, 7,\n                0, 2, 3, 6, 1, 5, 3, 5,\n                1, 3, 4, 4, 2, 5, 6, 7,\n                7, 0, 1, 2, 3, 3, 4, 6,\n                2, 6, 5, 5, 3, 4, 5, 6,\n                7, 1, 2, 4, 6, 4, 4, 5,\n                7, 2, 6, 5, 7, 6, 7, 7 };\n            return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];\n#       endif\n        }\n        else { /* 32 bits */\n#       if defined(_MSC_VER)\n            unsigned long r = 0;\n            _BitScanForward(&r, (U32)val);\n            return (unsigned)(r >> 3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 3)\n            return (__builtin_ctz((U32)val) >> 3);\n#       else\n            static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0,\n                3, 2, 2, 1, 3, 2, 0, 1,\n                3, 3, 1, 2, 2, 2, 2, 0,\n                3, 1, 2, 0, 1, 0, 1, 1 };\n            return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];\n#       endif\n        }\n    }\n    else {  /* Big Endian CPU */\n        if (MEM_64bits()) {\n#       if defined(_MSC_VER) && defined(_WIN64)\n            unsigned long r = 0;\n            _BitScanReverse64(&r, val);\n            return (unsigned)(r >> 3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 4)\n            return (__builtin_clzll(val) >> 3);\n#       else\n            unsigned r;\n            const unsigned n32 = sizeof(size_t) * 4;   /* calculate this way due to compiler complaining in 32-bits mode */\n            if (!(val >> n32)) { r = 4; }\n            else { r = 0; val >>= n32; }\n            if (!(val >> 16)) { r += 2; val >>= 8; }\n            else { val >>= 24; }\n            r += (!val);\n            return r;\n#       endif\n        }\n        else { /* 32 bits */\n#       if defined(_MSC_VER)\n            unsigned long r = 0;\n            _BitScanReverse(&r, (unsigned long)val);\n            return (unsigned)(r >> 3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 3)\n            return (__builtin_clz((U32)val) >> 3);\n#       else\n            unsigned r;\n            if (!(val >> 16)) { r = 2; val >>= 8; }\n            else { r = 0; val >>= 24; }\n            r += (!val);\n            return r;\n#       endif\n        }\n    }\n}\n\n\nstatic size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)\n{\n    const BYTE* const pStart = pIn;\n    const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t) - 1);\n\n    if (pIn < pInLoopLimit) {\n        { size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n        if (diff) return ZSTD_NbCommonBytes(diff); }\n        pIn += sizeof(size_t); pMatch += sizeof(size_t);\n        while (pIn < pInLoopLimit) {\n            size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n            if (!diff) { pIn += sizeof(size_t); pMatch += sizeof(size_t); continue; }\n            pIn += ZSTD_NbCommonBytes(diff);\n            return (size_t)(pIn - pStart);\n        }\n    }\n    if (MEM_64bits() && (pIn<(pInLimit - 3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn += 4; pMatch += 4; }\n    if ((pIn<(pInLimit - 1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn += 2; pMatch += 2; }\n    if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;\n    return (size_t)(pIn - pStart);\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_COUNT_H_ */"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/data_block.h",
    "content": "﻿#include \"mem.h\"\n\n#ifndef FL2_DATA_BLOCK_H_\n#define FL2_DATA_BLOCK_H_\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\ntypedef struct {\n    const BYTE* data;\n    size_t start;\n    size_t end;\n} FL2_dataBlock;\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* FL2_DATA_BLOCK_H_ */"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/dict_buffer.c",
    "content": "﻿/*\n* Copyright (c) 2019, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#include <stdlib.h>\n#include \"dict_buffer.h\"\n#include \"fl2_internal.h\"\n\n#define ALIGNMENT_SIZE 16U\n#define ALIGNMENT_MASK (~(size_t)(ALIGNMENT_SIZE-1))\n\n/* DICT_buffer functions */\n\nint DICT_construct(DICT_buffer * const buf, int const async)\n{\n    buf->data[0] = NULL;\n    buf->data[1] = NULL;\n    buf->size = 0;\n\n    buf->async = (async != 0);\n\n#ifndef NO_XXHASH\n    buf->xxh = NULL;\n#endif\n\n    return 0;\n}\n\nint DICT_init(DICT_buffer * const buf, size_t const dict_size, size_t const overlap, unsigned const reset_multiplier, int const do_hash)\n{\n    /* Allocate if not yet allocated or existing dict too small */\n    if (buf->data[0] == NULL || dict_size > buf->size) {\n        /* Free any existing buffers */\n        DICT_destruct(buf);\n\n        buf->data[0] = malloc(dict_size);\n\n        buf->data[1] = NULL;\n        if (buf->async)\n            buf->data[1] = malloc(dict_size);\n\n        if (buf->data[0] == NULL || (buf->async && buf->data[1] == NULL)) {\n            DICT_destruct(buf);\n            return 1;\n        }\n    }\n    buf->index = 0;\n    buf->overlap = overlap;\n    buf->start = 0;\n    buf->end = 0;\n    buf->size = dict_size;\n    buf->total = 0;\n    buf->reset_interval = (reset_multiplier != 0) ? dict_size * reset_multiplier : ((size_t)1 << 31);\n\n#ifndef NO_XXHASH\n    if (do_hash) {\n        if (buf->xxh == NULL) {\n            buf->xxh = XXH32_createState();\n            if (buf->xxh == NULL) {\n                DICT_destruct(buf);\n                return 1;\n            }\n        }\n        XXH32_reset(buf->xxh, 0);\n    }\n    else {\n        XXH32_freeState(buf->xxh);\n        buf->xxh = NULL;\n    }\n#else\n    (void)do_hash;\n#endif\n\n    return 0;\n}\n\nvoid DICT_destruct(DICT_buffer * const buf)\n{\n    free(buf->data[0]);\n    free(buf->data[1]);\n    buf->data[0] = NULL;\n    buf->data[1] = NULL;\n    buf->size = 0;\n#ifndef NO_XXHASH\n    XXH32_freeState(buf->xxh);\n    buf->xxh = NULL;\n#endif\n}\n\nsize_t DICT_size(const DICT_buffer * const buf)\n{\n    return buf->size;\n}\n\n/* Get the dictionary buffer for adding input */\nsize_t DICT_get(DICT_buffer * const buf, void **const dict)\n{\n    DICT_shift(buf);\n\n    DEBUGLOG(5, \"Getting dict buffer %u, pos %u, avail %u\", (unsigned)buf->index, (unsigned)buf->end, (unsigned)(buf->size - buf->end));\n    *dict = buf->data[buf->index] + buf->end;\n    return buf->size - buf->end;\n}\n\n/* Update with the amount added */\nint DICT_update(DICT_buffer * const buf, size_t const added_size)\n{\n    DEBUGLOG(5, \"Added %u bytes to dict buffer %u\", (unsigned)added_size, (unsigned)buf->index);\n    buf->end += added_size;\n    assert(buf->end <= buf->size);\n    return !DICT_availSpace(buf);\n}\n\n/* Read from input and write to the dict */\nvoid DICT_put(DICT_buffer * const buf, FL2_inBuffer * const input)\n{\n    size_t const to_read = MIN(buf->size - buf->end, input->size - input->pos);\n\n    DEBUGLOG(5, \"CStream : reading %u bytes\", (U32)to_read);\n\n    memcpy(buf->data[buf->index] + buf->end, (BYTE*)input->src + input->pos, to_read);\n\n    input->pos += to_read;\n    buf->end += to_read;\n}\n\nsize_t DICT_availSpace(const DICT_buffer * const buf)\n{\n    return buf->size - buf->end;\n}\n\n/* Get the size of uncompressed data. start is set to end after compression */\nint DICT_hasUnprocessed(const DICT_buffer * const buf)\n{\n    return buf->start < buf->end;\n}\n\n/* Get the buffer, overlap and end for compression */\nvoid DICT_getBlock(DICT_buffer * const buf, FL2_dataBlock * const block)\n{\n    block->data = buf->data[buf->index];\n    block->start = buf->start;\n    block->end = buf->end;\n\n#ifndef NO_XXHASH\n    if (buf->xxh != NULL)\n        XXH32_update(buf->xxh, buf->data[buf->index] + buf->start, buf->end - buf->start);\n#endif\n\n    buf->total += buf->end - buf->start;\n    buf->start = buf->end;\n}\n\n/* Shift occurs when all is processed and end is beyond the overlap size */\nint DICT_needShift(DICT_buffer * const buf)\n{\n    if (buf->start < buf->end)\n        return 0;\n    /* Reset the dict if the next compression cycle would exceed the reset interval */\n    size_t overlap = (buf->total + buf->size - buf->overlap > buf->reset_interval) ? 0 : buf->overlap;\n    return buf->start == buf->end && (overlap == 0 || buf->end >= overlap + ALIGNMENT_SIZE);\n}\n\nint DICT_async(const DICT_buffer * const buf)\n{\n    return (int)buf->async;\n}\n\n/* Shift the overlap amount to the start of either the only dict buffer or the alternate one\n * if it exists */\nvoid DICT_shift(DICT_buffer * const buf)\n{\n    if (buf->start < buf->end)\n        return;\n\n    size_t overlap = buf->overlap;\n    /* Reset the dict if the next compression cycle would exceed the reset interval */\n    if (buf->total + buf->size - buf->overlap > buf->reset_interval) {\n        DEBUGLOG(4, \"Resetting dictionary after %u bytes\", (unsigned)buf->total);\n        overlap = 0;\n    }\n\n    if (overlap == 0) {\n        /* No overlap means a simple buffer switch */\n        buf->start = 0;\n        buf->end = 0;\n        buf->index ^= buf->async;\n        buf->total = 0;\n    }\n    else if (buf->end >= overlap + ALIGNMENT_SIZE) {\n        size_t const from = (buf->end - overlap) & ALIGNMENT_MASK;\n        const BYTE *const src = buf->data[buf->index];\n        /* Copy to the alternate if one exists */\n        BYTE *const dst = buf->data[buf->index ^ buf->async];\n\n        overlap = buf->end - from;\n\n        if (overlap <= from || dst != src) {\n            DEBUGLOG(5, \"Copy overlap data : %u bytes from %u\", (unsigned)overlap, (unsigned)from);\n            memcpy(dst, src + from, overlap);\n        }\n        else if (from != 0) {\n            DEBUGLOG(5, \"Move overlap data : %u bytes from %u\", (unsigned)overlap, (unsigned)from);\n            memmove(dst, src + from, overlap);\n        }\n        /* New data will be written after the overlap */\n        buf->start = overlap;\n        buf->end = overlap;\n        /* Switch buffers */\n        buf->index ^= buf->async;\n    }\n}\n\n#ifndef NO_XXHASH\nXXH32_hash_t DICT_getDigest(const DICT_buffer * const buf)\n{\n    return XXH32_digest(buf->xxh);\n}\n#endif\n\nsize_t DICT_memUsage(const DICT_buffer * const buf)\n{\n    return (1 + buf->async) * buf->size;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/dict_buffer.h",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#include \"fast-lzma2.h\"\n#include \"mem.h\"\n#include \"data_block.h\"\n#ifndef NO_XXHASH\n#  include \"xxhash.h\"\n#endif\n\n#ifndef FL2_DICT_BUFFER_H_\n#define FL2_DICT_BUFFER_H_\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* DICT_buffer structure.\n * Maintains one or two dictionary buffers. In a dual dict configuration (asyc==1), when the\n * current buffer is full, the overlap region will be copied to the other buffer and it\n * becomes the destination for input while the first is compressed. This is useful when I/O\n * is much slower than compression. */\ntypedef struct {\n    BYTE* data[2];\n    size_t index;\n    size_t async;\n    size_t overlap;\n    size_t start;  /* start = 0 (first block) or overlap */\n    size_t end;    /* never < overlap */\n    size_t size;   /* allocation size */\n    size_t total;  /* total size compressed after last dict reset */\n    size_t reset_interval;\n#ifndef NO_XXHASH\n    XXH32_state_t *xxh;\n#endif\n} DICT_buffer;\n\nint DICT_construct(DICT_buffer *const buf, int const async);\n\nint DICT_init(DICT_buffer *const buf, size_t const dict_size, size_t const overlap, unsigned const reset_multiplier, int const do_hash);\n\nvoid DICT_destruct(DICT_buffer *const buf);\n\nsize_t DICT_size(const DICT_buffer *const buf);\n\nsize_t DICT_get(DICT_buffer *const buf, void **const dict);\n\nint DICT_update(DICT_buffer *const buf, size_t const added_size);\n\nvoid DICT_put(DICT_buffer *const buf, FL2_inBuffer* const input);\n\nsize_t DICT_availSpace(const DICT_buffer *const buf);\n\nint DICT_hasUnprocessed(const DICT_buffer *const buf);\n\nvoid DICT_getBlock(DICT_buffer *const buf, FL2_dataBlock *const block);\n\nint DICT_needShift(DICT_buffer *const buf);\n\nint DICT_async(const DICT_buffer *const buf);\n\nvoid DICT_shift(DICT_buffer *const buf);\n\n#ifndef NO_XXHASH\nXXH32_hash_t DICT_getDigest(const DICT_buffer *const buf);\n#endif\n\nsize_t DICT_memUsage(const DICT_buffer *const buf);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* FL2_DICT_BUFFER_H_ */"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fast-lzma2.h",
    "content": "﻿/*\n * Copyright (c) 2017-present, Conor McCarthy\n * All rights reserved.\n * Based on zstd.h copyright Yann Collet\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n*/\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifndef FAST_LZMA2_H\n#define FAST_LZMA2_H\n\n/* ======   Dependency   ======*/\n#include <stddef.h>   /* size_t */\n\n\n/* =====   FL2LIB_API : control library symbols visibility   ===== */\n#ifndef FL2LIB_VISIBILITY\n#  if defined(__GNUC__) && (__GNUC__ >= 4)\n#    define FL2LIB_VISIBILITY __attribute__ ((visibility (\"default\")))\n#  else\n#    define FL2LIB_VISIBILITY\n#  endif\n#endif\n#if defined(FL2_DLL_EXPORT) && (FL2_DLL_EXPORT==1)\n#  define FL2LIB_API __declspec(dllexport) FL2LIB_VISIBILITY\n#elif defined(FL2_DLL_IMPORT) && (FL2_DLL_IMPORT==1)\n#  define FL2LIB_API __declspec(dllimport) FL2LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define FL2LIB_API FL2LIB_VISIBILITY\n#endif\n\n/* ======   Calling convention   ======*/\n\n#if !defined _WIN32 || defined __x86_64__s || defined _M_X64 || (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8)\n#  define FL2LIB_CALL\n#elif defined(__GNUC__)\n#  define FL2LIB_CALL __attribute__((cdecl))\n#elif defined(_MSC_VER)\n#  define FL2LIB_CALL __cdecl\n#else\n#  define FL2LIB_CALL\n#endif\n\n/*******************************************************************************************************\nIntroduction\n\n*********************************************************************************************************/\n\n/*------   Version   ------*/\n#define FL2_VERSION_MAJOR    1\n#define FL2_VERSION_MINOR    0\n#define FL2_VERSION_RELEASE  1\n\n#define FL2_VERSION_NUMBER  (FL2_VERSION_MAJOR *100*100 + FL2_VERSION_MINOR *100 + FL2_VERSION_RELEASE)\nFL2LIB_API unsigned FL2LIB_CALL FL2_versionNumber(void);   /**< useful to check dll version */\n\n#define FL2_LIB_VERSION FL2_VERSION_MAJOR.FL2_VERSION_MINOR.FL2_VERSION_RELEASE\n#define FL2_QUOTE(str) #str\n#define FL2_EXPAND_AND_QUOTE(str) FL2_QUOTE(str)\n#define FL2_VERSION_STRING FL2_EXPAND_AND_QUOTE(FL2_LIB_VERSION)\nFL2LIB_API const char* FL2LIB_CALL FL2_versionString(void);\n\n\n#define FL2_MAXTHREADS 200\n\n\n/***************************************\n*  Simple API\n***************************************/\n\n/*! FL2_compress() :\n *  Compresses `src` content as a single LZMA2 compressed stream into already allocated `dst`.\n *  Call FL2_compressMt() to use > 1 thread. Specify nbThreads = 0 to use all cores.\n *  @return : compressed size written into `dst` (<= `dstCapacity),\n *            or an error code if it fails (which can be tested using FL2_isError()). */\nFL2LIB_API size_t FL2LIB_CALL FL2_compress(void* dst, size_t dstCapacity,\n    const void* src, size_t srcSize,\n    int compressionLevel);\n\nFL2LIB_API size_t FL2LIB_CALL FL2_compressMt(void* dst, size_t dstCapacity,\n    const void* src, size_t srcSize,\n    int compressionLevel,\n    unsigned nbThreads);\n\n/*! FL2_decompress() :\n *  Decompresses a single LZMA2 compressed stream from `src` into already allocated `dst`.\n *  `compressedSize` : must be at least the size of the LZMA2 stream.\n *  `dstCapacity` is the original, uncompressed size to regenerate, returned by calling\n *  FL2_findDecompressedSize().\n *  Call FL2_decompressMt() to use > 1 thread. Specify nbThreads = 0 to use all cores. The stream\n *  must contain dictionary resets to use multiple threads. These are inserted during compression by\n *  default. The frequency can be changed/disabled with the FL2_p_resetInterval parameter setting.\n *  @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n *            or an errorCode if it fails (which can be tested using FL2_isError()). */\nFL2LIB_API size_t FL2LIB_CALL FL2_decompress(void* dst, size_t dstCapacity,\n    const void* src, size_t compressedSize);\n\nFL2LIB_API size_t FL2LIB_CALL FL2_decompressMt(void* dst, size_t dstCapacity,\n    const void* src, size_t compressedSize,\n    unsigned nbThreads);\n\n/*! FL2_findDecompressedSize()\n *  `src` should point to the start of a LZMA2 encoded stream.\n *  `srcSize` must be at least as large as the LZMA2 stream including end marker.\n *  A property byte is assumed to exist at position 0 in `src`. If the stream was created without one,\n *  subtract 1 byte from `src` when passing it to the function.\n *  @return : - decompressed size of the stream in `src`, if known\n *            - FL2_CONTENTSIZE_ERROR if an error occurred (e.g. corruption, srcSize too small)\n *   note 1 : a 0 return value means the stream is valid but \"empty\".\n *   note 2 : decompressed size can be very large (64-bits value),\n *            potentially larger than what local system can handle as a single memory segment.\n *            In which case, it's necessary to use streaming mode to decompress data.\n *   note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified.\n *            Always ensure return value fits within application's authorized limits.\n *            Each application can set its own limits. */\n#define FL2_CONTENTSIZE_ERROR (size_t)-1\nFL2LIB_API unsigned long long FL2LIB_CALL FL2_findDecompressedSize(const void *src, size_t srcSize);\n\n\n/*======  Helper functions  ======*/\nFL2LIB_API size_t      FL2LIB_CALL FL2_compressBound(size_t srcSize); /*!< maximum compressed size in worst case scenario */\nFL2LIB_API unsigned    FL2LIB_CALL FL2_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */\nFL2LIB_API unsigned    FL2LIB_CALL FL2_isTimedOut(size_t code);       /*!< tells if a `size_t` function result is the timeout code */\nFL2LIB_API const char* FL2LIB_CALL FL2_getErrorName(size_t code);     /*!< provides readable string from an error code */\nFL2LIB_API int         FL2LIB_CALL FL2_maxCLevel(void);               /*!< maximum compression level available */\nFL2LIB_API int         FL2LIB_CALL FL2_maxHighCLevel(void);           /*!< maximum compression level available in high mode */\n\n\n/***************************************\n*  Explicit memory management\n***************************************/\n\n/*= Compression context\n *  When compressing many times, it is recommended to allocate a context just once,\n *  and re-use it for each successive compression operation. This will make workload\n *  friendlier for system's memory. The context may not use the number of threads requested\n *  if the library is compiled for single-threaded compression or nbThreads > FL2_MAXTHREADS.\n *  Call FL2_getCCtxThreadCount to obtain the actual number allocated. */\ntypedef struct FL2_CCtx_s FL2_CCtx;\nFL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtx(void);\nFL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtxMt(unsigned nbThreads);\nFL2LIB_API void      FL2LIB_CALL FL2_freeCCtx(FL2_CCtx* cctx);\n\nFL2LIB_API unsigned FL2LIB_CALL FL2_getCCtxThreadCount(const FL2_CCtx* cctx);\n\n/*! FL2_compressCCtx() :\n *  Same as FL2_compress(), but requires an allocated FL2_CCtx (see FL2_createCCtx()). */\nFL2LIB_API size_t FL2LIB_CALL FL2_compressCCtx(FL2_CCtx* cctx,\n    void* dst, size_t dstCapacity,\n    const void* src, size_t srcSize,\n    int compressionLevel);\n\n/*! FL2_getCCtxDictProp() :\n *  Get the dictionary size property.\n *  Intended for use with the FL2_p_omitProperties parameter for creating a\n *  7-zip or XZ compatible LZMA2 stream. */\nFL2LIB_API unsigned char FL2LIB_CALL FL2_getCCtxDictProp(FL2_CCtx* cctx);\n\n\n/****************************\n*  Decompression\n****************************/\n\n/*= Decompression context\n *  When decompressing many times, it is recommended to allocate a context only once,\n *  and re-use it for each successive decompression operation. This will make the workload\n *  friendlier for the system's memory.\n *  The context may not allocate the number of threads requested if the library is\n *  compiled for single-threaded compression or nbThreads > FL2_MAXTHREADS.\n *  Call FL2_getDCtxThreadCount to obtain the actual number allocated.\n *  At least nbThreads dictionary resets must exist in the stream to use all of the\n *  threads. Dictionary resets are inserted into the stream according to the\n *  FL2_p_resetInterval parameter used in the compression context. */\ntypedef struct FL2_DCtx_s FL2_DCtx;\nFL2LIB_API FL2_DCtx* FL2LIB_CALL FL2_createDCtx(void);\nFL2LIB_API FL2_DCtx* FL2LIB_CALL FL2_createDCtxMt(unsigned nbThreads);\nFL2LIB_API size_t    FL2LIB_CALL FL2_freeDCtx(FL2_DCtx* dctx);\n\nFL2LIB_API unsigned FL2LIB_CALL FL2_getDCtxThreadCount(const FL2_DCtx* dctx);\n\n\n/*! FL2_initDCtx() :\n *  Use only when a property byte is not present at input byte 0. No init is necessary otherwise.\n *  The caller must store the result from FL2_getCCtxDictProp() and pass it to this function. */\nFL2LIB_API size_t FL2LIB_CALL FL2_initDCtx(FL2_DCtx* dctx, unsigned char prop);\n\n/*! FL2_decompressDCtx() :\n *  Same as FL2_decompress(), requires an allocated FL2_DCtx (see FL2_createDCtx()) */\nFL2LIB_API size_t FL2LIB_CALL FL2_decompressDCtx(FL2_DCtx* cctx,\n    void* dst, size_t dstCapacity,\n    const void* src, size_t srcSize);\n\n/****************************\n*  Streaming\n****************************/\n\ntypedef struct {\n    const void* src;    /**< start of input buffer */\n    size_t size;        /**< size of input buffer */\n    size_t pos;         /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */\n} FL2_inBuffer;\n\ntypedef struct {\n    void*  dst;         /**< start of output buffer */\n    size_t size;        /**< size of output buffer */\n    size_t pos;         /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */\n} FL2_outBuffer;\n\n/*** Push/pull structs ***/\n\ntypedef struct {\n    void*  dst;         /**< start of available dict buffer */\n    unsigned long size; /**< size of dict remaining */\n} FL2_dictBuffer;\n\ntypedef struct {\n    const void* src;    /**< start of compressed data */\n    size_t size;        /**< size of compressed data */\n} FL2_cBuffer;\n\n/*-***********************************************************************\n *  Streaming compression\n *\n *  A FL2_CStream object is required to track streaming operation.\n *  Use FL2_createCStream() and FL2_freeCStream() to create/release resources.\n *  FL2_CStream objects can be reused multiple times on consecutive compression operations.\n *  It is recommended to re-use FL2_CStream in situations where many streaming operations will be done\n *  consecutively, since it will reduce allocation and initialization time.\n *\n *  Call FL2_createCStreamMt() with a nonzero dualBuffer parameter to use two input dictionary buffers.\n *  The stream will not block on FL2_compressStream() and continues to accept data while compression is\n *  underway, until both buffers are full. Useful when I/O is slow.\n *  To compress with a single thread with dual buffering, call FL2_createCStreamMt with nbThreads=1.\n *\n *  Use FL2_initCStream() on the FL2_CStream object to start a new compression operation.\n *\n *  Use FL2_compressStream() repetitively to consume input stream.\n *  The function will automatically update the `pos` field.\n *  It will always consume the entire input unless an error occurs or the dictionary buffer is filled,\n *  unlike the decompression function.\n *\n *  The radix match finder allows compressed data to be stored in its match table during encoding.\n *  Applications may call streaming compression functions with output == NULL. In this case,\n *  when the function returns 1, the compressed data must be read from the internal buffers.\n *  Call FL2_getNextCompressedBuffer() repeatedly until it returns 0.\n *  Each call returns buffer information in the FL2_inBuffer parameter. Applications typically will \n *  passed this to an I/O write function or downstream filter.\n *  Alternately, applications may pass an FL2_outBuffer object pointer to receive the output. In this\n *  case the return value is 1 if the buffer is full and more compressed data remains.\n *\n *  FL2_endStream() instructs to finish a stream. It will perform a flush and write the LZMA2\n *  termination byte (required). Call FL2_endStream() repeatedly until it returns 0.\n *\n *  Most functions may return a size_t error code, which can be tested using FL2_isError().\n *\n * *******************************************************************/\n\ntypedef struct FL2_CCtx_s FL2_CStream;\n\n/*===== FL2_CStream management functions =====*/\nFL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStream(void);\nFL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStreamMt(unsigned nbThreads, int dualBuffer);\nFL2LIB_API void FL2LIB_CALL FL2_freeCStream(FL2_CStream * fcs);\n\n/*===== Streaming compression functions =====*/\n\n/*! FL2_initCStream() :\n *  Call this function before beginning a new compressed data stream. To keep the stream object's\n *  current parameters, specify zero for the compression level. The object is set to the default\n *  level upon creation. */\nFL2LIB_API size_t FL2LIB_CALL FL2_initCStream(FL2_CStream* fcs, int compressionLevel);\n\n/*! FL2_setCStreamTimeout() :\n *  Sets a timeout in milliseconds. Zero disables the timeout (default). If a nonzero timout is set, functions\n *  FL2_compressStream(), FL2_getDictionaryBuffer(), FL2_updateDictionary(), FL2_getNextCompressedBuffer(),\n *  FL2_flushStream(), and FL2_endStream() may return a timeout code before compression of the current\n *  dictionary of data completes. FL2_isError() returns true for the timeout code, so check the code with\n *  FL2_isTimedOut() before testing for errors. With the exception of FL2_updateDictionary(), the above\n *  functions may be called again to wait for completion. A typical application for timeouts is to update the\n *  user on compression progress. */\nFL2LIB_API size_t FL2LIB_CALL FL2_setCStreamTimeout(FL2_CStream * fcs, unsigned timeout);\n\n/*! FL2_compressStream() :\n *  Reads data from input into the dictionary buffer. Compression will begin if the buffer fills up.\n *  A dual buffering stream will fill the second buffer while compression proceeds on the first.\n *  A call to FL2_compressStream() will wait for ongoing compression to complete if all dictionary space\n *  is filled. FL2_compressStream() must not be called with output == NULL unless the caller has read all\n *  compressed data from the CStream object.\n *  Returns 1 to indicate compressed data must be read (or output is full), or 0 otherwise. */\nFL2LIB_API size_t FL2LIB_CALL FL2_compressStream(FL2_CStream* fcs, FL2_outBuffer *output, FL2_inBuffer* input);\n\n/*! FL2_copyCStreamOutput() :\n *  Copies compressed data to the output buffer until the buffer is full or all available data is copied.\n *  If asynchronous compression is in progress, the function returns 0 without waiting.\n *  Returns 1 to indicate some compressed data remains, or 0 otherwise. */\nFL2LIB_API size_t FL2LIB_CALL FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output);\n\n/*** Push/pull functions ***/\n\n/*! FL2_getDictionaryBuffer() :\n *  Returns a buffer in the FL2_outBuffer object, which the caller can directly read data into.\n *  Applications will normally pass this buffer to an I/O read function or upstream filter.\n *  Returns 0, or an error or timeout code. */\nFL2LIB_API size_t FL2LIB_CALL FL2_getDictionaryBuffer(FL2_CStream* fcs, FL2_dictBuffer* dict);\n\n/*! FL2_updateDictionary() :\n *  Informs the CStream how much data was added to the buffer. Compression begins if the dictionary\n *  was filled. Returns 1 to indicate compressed data must be read, 0 if not, or an error code. */\nFL2LIB_API size_t FL2LIB_CALL FL2_updateDictionary(FL2_CStream* fcs, size_t addedSize);\n\n/*! FL2_getNextCompressedBuffer() :\n *  Returns a buffer containing a slice of the compressed data. Call this function and process the data\n *  until the function returns zero. In most cases it will return a buffer for each compression thread\n *  used. It is sometimes less but never more than nbThreads. If asynchronous compression is in progress,\n *  this function will wait for completion before returning, or it will return the timeout code. */\nFL2LIB_API size_t FL2LIB_CALL FL2_getNextCompressedBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf);\n\n/******/\n\n/*! FL2_getCStreamProgress() :\n *  Returns the number of bytes processed since the stream was initialized. This is a synthetic\n *  estimate because the match finder does not proceed sequentially through the data. If\n *  outputSize is not NULL, returns the number of bytes of compressed data generated. */\nFL2LIB_API unsigned long long FL2LIB_CALL FL2_getCStreamProgress(const FL2_CStream * fcs, unsigned long long *outputSize);\n\n/*! FL2_waitCStream() :\n *  Waits for compression to end. This function returns after the timeout set using\n *  FL2_setCStreamTimeout has elapsed. Unnecessary when no timeout is set.\n *  Returns 1 if compressed output is available, 0 if not, or the timeout code. */\nFL2LIB_API size_t FL2LIB_CALL FL2_waitCStream(FL2_CStream * fcs);\n\n/*! FL2_cancelCStream() :\n *  Cancels any compression operation underway. Useful only when dual buffering and/or timeouts\n *  are enabled. The stream will be returned to an uninitialized state. */\nFL2LIB_API void FL2LIB_CALL FL2_cancelCStream(FL2_CStream *fcs);\n\n/*! FL2_remainingOutputSize() :\n *  The amount of compressed data remaining to be read from the CStream object. */\nFL2LIB_API size_t FL2LIB_CALL FL2_remainingOutputSize(const FL2_CStream* fcs);\n\n/*! FL2_flushStream() :\n *  Compress all data remaining in the dictionary buffer(s). It may be necessary to call\n *  FL2_flushStream() more than once. If output == NULL the compressed data must be read from the\n *  CStream object after each call.\n *  Flushing is not normally useful and produces larger output.\n *  Returns 1 if input or output still exists in the CStream object, 0 if complete, or an error code. */\nFL2LIB_API size_t FL2LIB_CALL FL2_flushStream(FL2_CStream* fcs, FL2_outBuffer *output);\n\n/*! FL2_endStream() :\n *  Compress all data remaining in the dictionary buffer(s) and write the stream end marker. It may\n *  be necessary to call FL2_endStream() more than once. If output == NULL the compressed data must\n *  be read from the CStream object after each call.\n *  Returns 0 when compression is complete and all output has been flushed, 1 if not complete, or\n *  an error code. */\nFL2LIB_API size_t FL2LIB_CALL FL2_endStream(FL2_CStream* fcs, FL2_outBuffer *output);\n\n/*-***************************************************************************\n *  Streaming decompression\n *\n *  A FL2_DStream object is required to track streaming operations.\n *  Use FL2_createDStream() and FL2_freeDStream() to create/release resources.\n *  FL2_DStream objects can be re-used multiple times.\n *\n *  Use FL2_initDStream() to start a new decompression operation.\n *  @return : zero or an error code\n *\n *  Use FL2_decompressStream() repetitively to consume your input.\n *  The function will update both `pos` fields.\n *  If `input.pos < input.size`, some input has not been consumed.\n *  It's up to the caller to present again the remaining data.\n *  If `output.pos < output.size`, decoder has flushed everything it could.\n *  @return : 0 when a stream is completely decoded and fully flushed,\n *            1, which means there is still some decoding to do to complete the stream,\n *            or an error code, which can be tested using FL2_isError().\n * *******************************************************************************/\n\ntypedef struct FL2_DStream_s FL2_DStream;\n\n/*===== FL2_DStream management functions =====*/\nFL2LIB_API FL2_DStream* FL2LIB_CALL FL2_createDStream(void);\nFL2LIB_API FL2_DStream* FL2LIB_CALL FL2_createDStreamMt(unsigned nbThreads);\nFL2LIB_API size_t FL2LIB_CALL FL2_freeDStream(FL2_DStream* fds);\n\n/*! FL2_setDStreamMemoryLimitMt() :\n *  Set a total size limit for multithreaded decoder input and output buffers. MT decoder memory\n *  usage is unknown until the input is parsed. If the limit is exceeded, the decoder switches to\n *  using a single thread.\n *  MT decoding memory usage is typically dictionary_size * 4 * nbThreads for the output\n *  buffers plus the size of the compressed input for that amount of output. */\nFL2LIB_API void FL2LIB_CALL FL2_setDStreamMemoryLimitMt(FL2_DStream* fds, size_t limit);\n\n/*! FL2_setDStreamTimeout() :\n *  Sets a timeout in milliseconds. Zero disables the timeout. If a nonzero timout is set,\n *  FL2_decompressStream() may return a timeout code before decompression of the available data\n *  completes. FL2_isError() returns true for the timeout code, so check the code with FL2_isTimedOut()\n *  before testing for errors. After a timeout occurs, do not call FL2_decompressStream() again unless\n *  a call to FL2_waitDStream() returns 1. A typical application for timeouts is to update the user on\n *  decompression progress. */\nFL2LIB_API size_t FL2LIB_CALL FL2_setDStreamTimeout(FL2_DStream * fds, unsigned timeout);\n\n/*! FL2_waitDStream() :\n *  Waits for decompression to end after a timeout has occurred. This function returns after the\n *  timeout set using FL2_setDStreamTimeout() has elapsed, or when decompression of available input is\n *  complete. Unnecessary when no timeout is set.\n *  Returns 0 if the stream is complete, 1 if not complete, or an error code. */\nFL2LIB_API size_t FL2LIB_CALL FL2_waitDStream(FL2_DStream * fds);\n\n/*! FL2_cancelDStream() :\n *  Frees memory allocated for MT decoding. If a timeout is set and the caller is waiting\n *  for completion of MT decoding, decompression in progress will be canceled. */\nFL2LIB_API void FL2LIB_CALL FL2_cancelDStream(FL2_DStream *fds);\n\n/*! FL2_getDStreamProgress() :\n *  Returns the number of bytes decoded since the stream was initialized. */\nFL2LIB_API unsigned long long FL2LIB_CALL FL2_getDStreamProgress(const FL2_DStream * fds);\n\n/*===== Streaming decompression functions =====*/\n\n/*! FL2_initDStream() :\n *  Call this function before decompressing a stream. FL2_initDStream_withProp()\n *  must be used for streams which do not include a property byte at position zero.\n *  The caller is responsible for storing and passing the property byte.\n *  Returns 0 if okay, or an error if the stream object is still in use from a\n *  previous call to FL2_decompressStream() (see timeout info above). */\nFL2LIB_API size_t FL2LIB_CALL FL2_initDStream(FL2_DStream* fds);\nFL2LIB_API size_t FL2LIB_CALL FL2_initDStream_withProp(FL2_DStream* fds, unsigned char prop);\n\n/*! FL2_decompressStream() :\n *  Reads data from input and decompresses to output.\n *  Returns 1 if the stream is unfinished, 0 if the terminator was encountered (he'll be back)\n *  and all data was written to output, or an error code. Call this function repeatedly if\n *  necessary, removing data from output and/or loading data into input before each call. */\nFL2LIB_API size_t FL2LIB_CALL FL2_decompressStream(FL2_DStream* fds, FL2_outBuffer* output, FL2_inBuffer* input);\n\n/*-***************************************************************************\n *  Compression parameters\n *\n *  Any function that takes a 'compressionLevel' parameter will replace any\n *  parameters affected by compression level that are already set.\n *  To use a preset level and modify it, call FL2_CCtx_setParameter with\n *  FL2_p_compressionLevel to set the level, then call FL2_CCtx_setParameter again\n *  with any other settings to change.\n *  Specify a compressionLevel of 0 when calling a compression function to keep\n *  the current parameters.\n * *******************************************************************************/\n\n#define FL2_DICTLOG_MIN      20\n#define FL2_DICTLOG_MAX_32   27\n#define FL2_DICTLOG_MAX_64   30\n#define FL2_DICTLOG_MAX      ((unsigned)(sizeof(size_t) == 4 ? FL2_DICTLOG_MAX_32 : FL2_DICTLOG_MAX_64))\n#define FL2_DICTSIZE_MAX     (1U << FL2_DICTLOG_MAX)\n#define FL2_DICTSIZE_MIN     (1U << FL2_DICTLOG_MIN)\n#define FL2_BLOCK_OVERLAP_MIN 0\n#define FL2_BLOCK_OVERLAP_MAX 14\n#define FL2_RESET_INTERVAL_MIN 1\n#define FL2_RESET_INTERVAL_MAX 16  /* small enough to fit FL2_DICTSIZE_MAX * FL2_RESET_INTERVAL_MAX in 32-bit size_t */\n#define FL2_BUFFER_RESIZE_MIN 0\n#define FL2_BUFFER_RESIZE_MAX 4\n#define FL2_BUFFER_RESIZE_DEFAULT 2\n#define FL2_CHAINLOG_MIN       4\n#define FL2_CHAINLOG_MAX       14\n#define FL2_HYBRIDCYCLES_MIN    1\n#define FL2_HYBRIDCYCLES_MAX   64\n#define FL2_SEARCH_DEPTH_MIN 6\n#define FL2_SEARCH_DEPTH_MAX 254\n#define FL2_FASTLENGTH_MIN    6   /* only used by optimizer */\n#define FL2_FASTLENGTH_MAX  273   /* only used by optimizer */\n#define FL2_LC_MIN 0\n#define FL2_LC_MAX 4\n#define FL2_LP_MIN 0\n#define FL2_LP_MAX 4\n#define FL2_PB_MIN 0\n#define FL2_PB_MAX 4\n#define FL2_LCLP_MAX 4\n\ntypedef enum {\n    FL2_fast,\n    FL2_opt,\n    FL2_ultra\n} FL2_strategy;\n\ntypedef struct {\n    size_t   dictionarySize;   /* largest match distance : larger == more compression, more memory needed during decompression; > 64Mb == more memory per byte, slower */\n    unsigned overlapFraction;  /* overlap between consecutive blocks in 1/16 units: larger == more compression, slower */\n    unsigned chainLog;         /* HC3 sliding window : larger == more compression, slower; hybrid mode only (ultra) */\n    unsigned cyclesLog;        /* nb of searches : larger == more compression, slower; hybrid mode only (ultra) */\n    unsigned searchDepth;      /* maximum depth for resolving string matches : larger == more compression, slower */\n    unsigned fastLength;       /* acceptable match size for parser : larger == more compression, slower; fast bytes parameter from 7-Zip */\n    unsigned divideAndConquer; /* split long chains of 2-byte matches into shorter chains with a small overlap : faster, somewhat less compression; enabled by default */\n    FL2_strategy strategy;     /* encoder strategy : fast, optimized or ultra (hybrid) */\n} FL2_compressionParameters;\n\ntypedef enum {\n    /* compression parameters */\n    FL2_p_compressionLevel, /* Update all compression parameters according to pre-defined cLevel table\n                             * Default level is FL2_CLEVEL_DEFAULT==6.\n                             * Setting FL2_p_highCompression to 1 switches to an alternate cLevel table. */\n    FL2_p_highCompression,  /* Maximize compression ratio for a given dictionary size.\n                             * Levels 1..10 = dictionaryLog 20..29 (1 Mb..512 Mb).\n                             * Typically provides a poor speed/ratio tradeoff. */\n    FL2_p_dictionaryLog,    /* Maximum allowed back-reference distance, expressed as power of 2.\n                             * Must be clamped between FL2_DICTLOG_MIN and FL2_DICTLOG_MAX.\n                             * Default = 24 */\n    FL2_p_dictionarySize,   /* Same as above but expressed as an absolute value. \n                             * Must be clamped between FL2_DICTSIZE_MIN and FL2_DICTSIZE_MAX.\n                             * Default = 16 Mb */\n    FL2_p_overlapFraction,  /* The radix match finder is block-based, so some overlap is retained from\n                             * each block to improve compression of the next. This value is expressed\n                             * as n / 16 of the block size (dictionary size). Larger values are slower.\n                             * Values above 2 mostly yield only a small improvement in compression.\n                             * A large value for a small dictionary may worsen multithreaded compression.\n                             * Default = 2 */\n    FL2_p_resetInterval,    /* For multithreaded decompression. A dictionary reset will occur\n                             * after each dictionarySize * resetInterval bytes of input.\n                             * Default = 4 */\n    FL2_p_bufferResize,     /* Buffering speeds up the matchfinder. Buffer resize determines the percentage of\n                             * the normal buffer size used, which depends on dictionary size.\n                             * 0=50, 1=75, 2=100, 3=150, 4=200. Higher number = slower, better\n                             * compression, higher memory usage. A CPU with a large memory cache\n                             * may make effective use of a larger buffer.\n                             * Default = 2 */\n    FL2_p_hybridChainLog,   /* Size of the hybrid mode HC3 hash chain, as a power of 2.\n                             * Resulting table size is (1 << (chainLog+2)) bytes.\n                             * Larger tables result in better and slower compression.\n                             * This parameter is only used by the hybrid \"ultra\" strategy.\n                             * Default = 9 */\n    FL2_p_hybridCycles,     /* Number of search attempts made by the HC3 match finder.\n                             * Used only by the hybrid \"ultra\" strategy.\n                             * More attempts result in slightly better and slower compression.\n                             * Default = 1 */\n    FL2_p_searchDepth,      /* Match finder will resolve string matches up to this length. If a longer\n                             * match exists further back in the input, it will not be found.\n                             * Default = 42 */\n    FL2_p_fastLength,       /* Only useful for strategies >= opt.\n                             * Length of match considered \"good enough\" to stop search.\n                             * Larger values make compression stronger and slower.\n                             * Default = 48 */\n    FL2_p_divideAndConquer, /* Split long chains of 2-byte matches into shorter chains with a small overlap\n                             * for further processing. Allows buffering of all chains at length 2.\n                             * Faster, less compression. Generally a good tradeoff.\n                             * Default = enabled */\n    FL2_p_strategy,         /* 1 = fast; 2 = optimized, 3 = ultra (hybrid mode).\n                             * The higher the value of the selected strategy, the more complex it is,\n                             * resulting in stronger and slower compression.\n                             * Default = ultra */\n    FL2_p_literalCtxBits,   /* lc value for LZMA2 encoder\n                             * Default = 3 */\n    FL2_p_literalPosBits,   /* lp value for LZMA2 encoder\n                             * Default = 0 */\n    FL2_p_posBits,          /* pb value for LZMA2 encoder\n                             * Default = 2 */\n    FL2_p_omitProperties,   /* Omit the property byte at the start of the stream. For use within 7-zip */\n                            /* or other containers which store the property byte elsewhere. */\n                            /* A stream compressed under this setting cannot be decoded by this library. */\n#ifndef NO_XXHASH\n    FL2_p_doXXHash,         /* Calculate a 32-bit xxhash value from the input data and store it \n                             * after the stream terminator. The value will be checked on decompression.\n                             * 0 = do not calculate; 1 = calculate (default) */\n#endif\n#ifdef RMF_REFERENCE\n    FL2_p_useReferenceMF    /* Use the reference matchfinder for development purposes. SLOW. */\n#endif\n} FL2_cParameter;\n\n\n/*! FL2_CCtx_setParameter() :\n *  Set one compression parameter, selected by enum FL2_cParameter.\n *  @result : informational value (typically, the one being set, possibly corrected),\n *            or an error code (which can be tested with FL2_isError()). */\nFL2LIB_API size_t FL2LIB_CALL FL2_CCtx_setParameter(FL2_CCtx* cctx, FL2_cParameter param, size_t value);\n\n/*! FL2_CCtx_getParameter() :\n *  Get one compression parameter, selected by enum FL2_cParameter.\n *  @result : the parameter value, or the parameter_unsupported error code\n *            (which can be tested with FL2_isError()). */\nFL2LIB_API size_t FL2LIB_CALL FL2_CCtx_getParameter(FL2_CCtx* cctx, FL2_cParameter param);\n\n/*! FL2_CStream_setParameter() :\n *  Set one compression parameter, selected by enum FL2_cParameter.\n *  @result : informational value (typically, the one being set, possibly corrected),\n *            or an error code (which can be tested with FL2_isError()). */\nFL2LIB_API size_t FL2LIB_CALL FL2_CStream_setParameter(FL2_CStream* fcs, FL2_cParameter param, size_t value);\n\n/*! FL2_CStream_getParameter() :\n *  Get one compression parameter, selected by enum FL2_cParameter.\n *  @result : the parameter value, or the parameter_unsupported error code\n *            (which can be tested with FL2_isError()). */\nFL2LIB_API size_t FL2LIB_CALL FL2_CStream_getParameter(FL2_CStream* fcs, FL2_cParameter param);\n\n/*! FL2_getLevelParameters() :\n *  Get all compression parameter values defined by the preset compressionLevel.\n *  @result : the values in a FL2_compressionParameters struct, or the parameter_outOfBound error code\n *            (which can be tested with FL2_isError()) if compressionLevel is invalid. */\nFL2LIB_API size_t FL2LIB_CALL FL2_getLevelParameters(int compressionLevel, int high, FL2_compressionParameters *params);\n\n\n/***************************************\n*  Context memory usage\n***************************************/\n\n/*! FL2_estimate*() :\n*  These functions estimate memory usage of a CCtx before its creation or before any operation has begun.\n*  FL2_estimateCCtxSize() will provide a budget large enough for any compression level up to selected one.\n*  To use FL2_estimateCCtxSize_usingCCtx, set the compression level and any other settings for the context,\n*  then call the function. Some allocation occurs when the context is created, but the large memory buffers\n*  used for string matching are allocated only when compression is initialized. */\n\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize(int compressionLevel, unsigned nbThreads); /*!< memory usage determined by level */\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_byParams(const FL2_compressionParameters *params, unsigned nbThreads); /*!< memory usage determined by params */\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_usingCCtx(const FL2_CCtx* cctx);           /*!< memory usage determined by settings */\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize(int compressionLevel, unsigned nbThreads, int dualBuffer); /*!< memory usage determined by level */\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_byParams(const FL2_compressionParameters *params, unsigned nbThreads, int dualBuffer); /*!< memory usage determined by params */\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_usingCStream(const FL2_CStream* fcs);   /*!< memory usage determined by settings */\n\n/*! FL2_getDictSizeFromProp() :\n *  Get the dictionary size from the property byte for a stream. The property byte is the first byte\n*   in the stream, unless omitProperties was enabled, in which case the caller must store it. */\nFL2LIB_API size_t FL2LIB_CALL FL2_getDictSizeFromProp(unsigned char prop);\n\n/*! FL2_estimateDCtxSize() :\n *  The size of a DCtx does not include a dictionary buffer because the caller must supply one. */\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateDCtxSize(unsigned nbThreads);\n\n/*! FL2_estimateDStreamSize() :\n *  Estimate decompression memory use from the dictionary size and number of threads.\n *  For nbThreads == 0 the number of available cores will be used.\n *  Obtain dictSize by passing the property byte to FL2_getDictSizeFromProp. */\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateDStreamSize(size_t dictSize, unsigned nbThreads); /*!<  obtain dictSize from FL2_getDictSizeFromProp() */\n\n#endif  /* FAST_LZMA2_H */\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fastpos_table.h",
    "content": "﻿/* This file has been automatically generated by fastpos_tablegen.c. */\n/* Copied from the XZ project */\n\n\nstatic const BYTE distance_table[1 << kFastDistBits] = {\n\t  0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,\n\t  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,\n\t 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n\t 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n\t 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n\t 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n\t 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\n\t 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,\n\t 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n\t 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n\t 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n\t 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n\t 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n\t 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n\t 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n\t 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,\n\t 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23\n};\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_common.c",
    "content": "﻿/*\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * All rights reserved.\n * Modified for FL2 by Conor McCarthy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"fast-lzma2.h\"\n#include \"fl2_errors.h\"\n#include \"fl2_internal.h\"\n#include \"lzma2_enc.h\"\n\n\n/*-****************************************\n*  Version\n******************************************/\nFL2LIB_API unsigned FL2LIB_CALL FL2_versionNumber(void) { return FL2_VERSION_NUMBER; }\n\nFL2LIB_API const char* FL2LIB_CALL FL2_versionString(void) { return FL2_VERSION_STRING; }\n\n\n/*-****************************************\n*  Compression helpers\n******************************************/\nFL2LIB_API size_t FL2LIB_CALL FL2_compressBound(size_t srcSize)\n{\n\treturn LZMA2_compressBound(srcSize);\n}\n\n/*-****************************************\n*  FL2 Error Management\n******************************************/\nHINT_INLINE\nunsigned IsError(size_t code)\n{\n    return (code > FL2_ERROR(maxCode));\n}\n\n/*! FL2_isError() :\n *  tells if a return value is an error code */\nFL2LIB_API unsigned FL2LIB_CALL FL2_isError(size_t code)\n{\n    return IsError(code);\n}\n\n/*! FL2_isTimedOut() :\n *  tells if a return value is the timeout code */\nFL2LIB_API unsigned FL2LIB_CALL FL2_isTimedOut(size_t code)\n{\n    return (code == FL2_ERROR(timedOut));\n}\n\n/*! FL2_getErrorName() :\n *  provides error code string from function result (useful for debugging) */\nFL2LIB_API const char* FL2LIB_CALL FL2_getErrorName(size_t code)\n{\n    return FL2_getErrorString(FL2_getErrorCode(code));\n}\n\n/*! FL2_getError() :\n *  convert a `size_t` function result into a proper FL2_errorCode enum */\nFL2LIB_API FL2_ErrorCode FL2LIB_CALL FL2_getErrorCode(size_t code)\n{\n    if (!IsError(code)) \n        return (FL2_ErrorCode)0;\n\n    return (FL2_ErrorCode)(0 - code);\n}\n\n/*! FL2_getErrorString() :\n *  provides error code string from enum */\nFL2LIB_API const char* FL2LIB_CALL FL2_getErrorString(FL2_ErrorCode code)\n{\n    static const char* const notErrorCode = \"Unspecified error code\";\n    switch (code)\n    {\n    case PREFIX(no_error): return \"No error detected\";\n    case PREFIX(GENERIC):  return \"Error (generic)\";\n    case PREFIX(internal): return \"Internal error (bug)\";\n    case PREFIX(corruption_detected): return \"Corrupted block detected\";\n    case PREFIX(checksum_wrong): return \"Restored data doesn't match checksum\";\n    case PREFIX(parameter_unsupported): return \"Unsupported parameter\";\n    case PREFIX(parameter_outOfBound): return \"Parameter is out of bound\";\n    case PREFIX(lclpMax_exceeded): return \"Parameters lc+lp > 4\";\n    case PREFIX(stage_wrong): return \"Not possible at this stage of encoding\";\n    case PREFIX(init_missing): return \"Context should be init first\";\n    case PREFIX(memory_allocation): return \"Allocation error : not enough memory\";\n    case PREFIX(dstSize_tooSmall): return \"Destination buffer is too small\";\n    case PREFIX(srcSize_wrong): return \"Src size is incorrect\";\n    case PREFIX(canceled): return \"Processing was canceled by a call to FL2_cancelCStream() or FL2_cancelDStream()\";\n    case PREFIX(buffer): return \"Streaming progress halted due to buffer(s) full/empty\";\n    case PREFIX(timedOut): return \"Wait timed out. Timeouts should be handled before errors using FL2_isTimedOut()\";\n        /* following error codes are not stable and may be removed or changed in a future version */\n    case PREFIX(maxCode):\n    default: return notErrorCode;\n    }\n}\n\n/*! g_debuglog_enable :\n *  turn on/off debug traces (global switch) */\n#if defined(FL2_DEBUG) && (FL2_DEBUG >= 2)\nint g_debuglog_enable = 1;\n#endif\n\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_compress.c",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n* Parts based on zstd_compress.c copyright Yann Collet\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#include <string.h>\n#include \"fast-lzma2.h\"\n#include \"fl2_errors.h\"\n#include \"fl2_internal.h\"\n#include \"platform.h\"\n#include \"mem.h\"\n#include \"util.h\"\n#include \"fl2_compress_internal.h\"\n#include \"fl2_threading.h\"\n#include \"fl2_pool.h\"\n#include \"radix_mf.h\"\n#include \"lzma2_enc.h\"\n\n#define FL2_MAX_LOOPS 10U\n\n/*-=====  Pre-defined compression levels  =====-*/\n\n#define MB *(1U<<20)\n\n#define FL2_MAX_HIGH_CLEVEL 10\n\n#ifdef FL2_XZ_BUILD\n\n#define FL2_CLEVEL_DEFAULT  6\n#define FL2_MAX_CLEVEL      9\n\nstatic const FL2_compressionParameters FL2_defaultCParameters[FL2_MAX_CLEVEL + 1] = {\n    { 0,0,0,0,0,0,0,0 },\n    { 1 MB, 1, 7, 0, 6, 32, 1, FL2_fast }, /* 1 */\n    { 2 MB, 2, 7, 0, 14, 32, 1, FL2_fast }, /* 2 */\n    { 2 MB, 2, 7, 0, 14, 40, 1, FL2_opt }, /* 3 */\n    { 8 MB, 2, 7, 0, 26, 40, 1, FL2_opt }, /* 4 */\n    { 16 MB, 2, 8, 0, 42, 48, 1, FL2_opt }, /* 5 */\n    { 16 MB, 2, 9, 1, 42, 48, 1, FL2_ultra }, /* 6 */\n    { 32 MB, 2, 10, 1, 50, 64, 1, FL2_ultra }, /* 7 */\n    { 64 MB, 2, 11, 2, 62, 96, 1, FL2_ultra }, /* 8 */\n    { 128 MB, 2, 12, 3, 90, 128, 1, FL2_ultra }, /* 9 */\n};\n\n#elif defined(FL2_7ZIP_BUILD)\n\n#define FL2_CLEVEL_DEFAULT  5\n#define FL2_MAX_CLEVEL      9\n\nstatic const FL2_compressionParameters FL2_defaultCParameters[FL2_MAX_CLEVEL + 1] = {\n    { 0,0,0,0,0,0,0,0 },\n    { 1 MB, 1, 7, 0, 6, 32, 1, FL2_fast }, /* 1 */\n    { 2 MB, 2, 7, 0, 10, 32, 1, FL2_fast }, /* 2 */\n    { 2 MB, 2, 7, 0, 10, 32, 1, FL2_opt }, /* 3 */\n    { 4 MB, 2, 7, 0, 14, 32, 1, FL2_opt }, /* 4 */\n    { 16 MB, 2, 9, 0, 42, 48, 1, FL2_ultra }, /* 5 */\n    { 32 MB, 2, 10, 0, 50, 64, 1, FL2_ultra }, /* 6 */\n    { 64 MB, 2, 11, 1, 62, 96, 1, FL2_ultra }, /* 7 */\n    { 64 MB, 4, 12, 2, 90, 273, 1, FL2_ultra }, /* 8 */\n    { 128 MB, 2, 14, 3, 254, 273, 0, FL2_ultra } /* 9 */\n};\n\n#else\n\n#define FL2_CLEVEL_DEFAULT   6\n#define FL2_MAX_CLEVEL      10\n\nstatic const FL2_compressionParameters FL2_defaultCParameters[FL2_MAX_CLEVEL + 1] = {\n    { 0,0,0,0,0,0,0,0 },\n    { 1 MB, 1, 7, 0, 6, 32, 1, FL2_fast }, /* 1 */\n    { 2 MB, 2, 7, 0, 10, 32, 1, FL2_fast }, /* 2 */\n    { 2 MB, 2, 7, 0, 10, 32, 1, FL2_opt }, /* 3 */\n    { 4 MB, 2, 7, 0, 26, 40, 1, FL2_opt }, /* 4 */\n    { 8 MB, 2, 8, 0, 42, 48, 1, FL2_opt }, /* 5 */\n    { 16 MB, 2, 9, 0, 42, 48, 1, FL2_ultra }, /* 6 */\n    { 32 MB, 2, 10, 0, 50, 64, 1, FL2_ultra }, /* 7 */\n    { 64 MB, 2, 11, 1, 62, 96, 1, FL2_ultra }, /* 8 */\n    { 64 MB, 4, 12, 2, 90, 273, 1, FL2_ultra }, /* 9 */\n    { 128 MB, 2, 14, 3, 254, 273, 0, FL2_ultra } /* 10 */\n};\n\n#endif\n\nstatic const FL2_compressionParameters FL2_highCParameters[FL2_MAX_HIGH_CLEVEL + 1] = {\n    { 0,0,0,0,0,0,0,0 },\n    { 1 MB, 4, 9, 2, 254, 273, 0, FL2_ultra }, /* 1 */\n    { 2 MB, 4, 10, 2, 254, 273, 0, FL2_ultra }, /* 2 */\n    { 4 MB, 4, 11, 2, 254, 273, 0, FL2_ultra }, /* 3 */\n    { 8 MB, 4, 12, 2, 254, 273, 0, FL2_ultra }, /* 4 */\n    { 16 MB, 4, 13, 3, 254, 273, 0, FL2_ultra }, /* 5 */\n    { 32 MB, 4, 14, 3, 254, 273, 0, FL2_ultra }, /* 6 */\n    { 64 MB, 4, 14, 4, 254, 273, 0, FL2_ultra }, /* 7 */\n    { 128 MB, 4, 14, 4, 254, 273, 0, FL2_ultra }, /* 8 */\n    { 256 MB, 4, 14, 5, 254, 273, 0, FL2_ultra }, /* 9 */\n    { 512 MB, 4, 14, 5, 254, 273, 0, FL2_ultra } /* 10 */\n};\n\n#undef MB\n\nFL2LIB_API int FL2LIB_CALL FL2_maxCLevel(void)\n{\n    return FL2_MAX_CLEVEL;\n}\n\nFL2LIB_API int FL2LIB_CALL FL2_maxHighCLevel(void)\n{\n    return FL2_MAX_HIGH_CLEVEL;\n}\n\nstatic void FL2_fillParameters(FL2_CCtx* const cctx, const FL2_compressionParameters* const params)\n{\n    FL2_lzma2Parameters* const cParams = &cctx->params.cParams;\n    cParams->lc = 3;\n    cParams->lp = 0;\n    cParams->pb = 2;\n    cParams->fast_length = params->fastLength;\n    cParams->match_cycles = 1U << params->cyclesLog;\n    cParams->strategy = params->strategy;\n    cParams->second_dict_bits = params->chainLog;\n\n    RMF_parameters* const rParams = &cctx->params.rParams;\n    rParams->dictionary_size = MIN(params->dictionarySize, FL2_DICTSIZE_MAX); /* allows for reduced dict in 32-bit version */\n    rParams->match_buffer_resize = FL2_BUFFER_RESIZE_DEFAULT;\n    rParams->overlap_fraction = params->overlapFraction;\n    rParams->divide_and_conquer = params->divideAndConquer;\n    rParams->depth = params->searchDepth;\n#ifdef RMF_REFERENCE\n    rParams->use_ref_mf = 1;\n#endif\n}\n\nstatic FL2_CCtx* FL2_createCCtx_internal(unsigned nbThreads, int const dualBuffer)\n{\n    nbThreads = FL2_checkNbThreads(nbThreads);\n\n    DEBUGLOG(3, \"FL2_createCCtxMt : %u threads\", nbThreads);\n\n    FL2_CCtx* const cctx = calloc(1, sizeof(FL2_CCtx) + (nbThreads - 1) * sizeof(FL2_job));\n    if (cctx == NULL)\n        return NULL;\n\n    cctx->jobCount = nbThreads;\n    for (unsigned u = 0; u < nbThreads; ++u)\n        cctx->jobs[u].enc = NULL;\n\n#ifndef NO_XXHASH\n    cctx->params.doXXH = 1;\n#endif\n\n    cctx->matchTable = NULL;\n\n#ifndef FL2_SINGLETHREAD\n    cctx->compressThread = NULL;\n    cctx->factory = FL2POOL_create(nbThreads - 1);\n    if (nbThreads > 1 && cctx->factory == NULL) {\n        FL2_freeCCtx(cctx);\n        return NULL;\n    }\n    if (dualBuffer) {\n      cctx->compressThread = FL2POOL_create(1);\n      if (cctx->compressThread == NULL)\n        return NULL;\n    }\n#endif\n\n    for (unsigned u = 0; u < nbThreads; ++u) {\n        cctx->jobs[u].enc = LZMA2_createECtx();\n        if (cctx->jobs[u].enc == NULL) {\n            FL2_freeCCtx(cctx);\n            return NULL;\n        }\n        cctx->jobs[u].cctx = cctx;\n    }\n\n    DICT_construct(&cctx->buf, dualBuffer);\n\n    FL2_CCtx_setParameter(cctx, FL2_p_compressionLevel, FL2_CLEVEL_DEFAULT);\n    cctx->params.cParams.reset_interval = 4;\n\n    return cctx;\n}\n\nFL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtx(void)\n{\n    return FL2_createCCtx_internal(1, 0);\n}\n\nFL2LIB_API FL2_CCtx* FL2LIB_CALL FL2_createCCtxMt(unsigned nbThreads)\n{\n    return FL2_createCCtx_internal(nbThreads, 0);\n}\n\nFL2LIB_API void FL2LIB_CALL FL2_freeCCtx(FL2_CCtx* cctx)\n{\n    if (cctx == NULL) \n        return;\n\n    DEBUGLOG(3, \"FL2_freeCCtx : %u threads\", cctx->jobCount);\n\n    DICT_destruct(&cctx->buf);\n\n    for (unsigned u = 0; u < cctx->jobCount; ++u) {\n        LZMA2_freeECtx(cctx->jobs[u].enc);\n    }\n\n#ifndef FL2_SINGLETHREAD\n    FL2POOL_free(cctx->factory);\n    FL2POOL_free(cctx->compressThread);\n#endif\n\n    RMF_freeMatchTable(cctx->matchTable);\n    free(cctx);\n}\n\nFL2LIB_API unsigned FL2LIB_CALL FL2_getCCtxThreadCount(const FL2_CCtx* cctx)\n{\n    return cctx->jobCount;\n}\n\n/* FL2_buildRadixTable() : FL2POOL_function type */\nstatic void FL2_buildRadixTable(void* const jobDescription, ptrdiff_t const n)\n{\n    FL2_CCtx* const cctx = (FL2_CCtx*)jobDescription;\n\n    RMF_buildTable(cctx->matchTable, n, 1, cctx->curBlock);\n}\n\n/* FL2_compressRadixChunk() : FL2POOL_function type */\nstatic void FL2_compressRadixChunk(void* const jobDescription, ptrdiff_t const n)\n{\n    FL2_CCtx* const cctx = (FL2_CCtx*)jobDescription;\n\n    cctx->jobs[n].cSize = LZMA2_encode(cctx->jobs[n].enc, cctx->matchTable,\n        cctx->jobs[n].block,\n        &cctx->params.cParams,\n        -1,\n        &cctx->progressIn, &cctx->progressOut, &cctx->canceled);\n}\n\nstatic int FL2_initEncoders(FL2_CCtx* const cctx)\n{\n    for(unsigned u = 0; u < cctx->jobCount; ++u) {\n        if (LZMA2_hashAlloc(cctx->jobs[u].enc, &cctx->params.cParams) != 0)\n            return 1;\n    }\n    return 0;\n}\n\nstatic void FL2_initProgress(FL2_CCtx* const cctx)\n{\n    RMF_initProgress(cctx->matchTable);\n    cctx->progressIn = 0;\n    cctx->streamCsize += cctx->progressOut;\n    cctx->progressOut = 0;\n    cctx->canceled = 0;\n}\n\n/* FL2_compressCurBlock_blocking() :\n * Compress cctx->curBlock and wait until complete.\n * Write streamProp as the first byte if >= 0\n */\nstatic size_t FL2_compressCurBlock_blocking(FL2_CCtx* const cctx, int const streamProp)\n{\n    size_t const encodeSize = (cctx->curBlock.end - cctx->curBlock.start);\n#ifndef FL2_SINGLETHREAD\n    size_t mfThreads = cctx->curBlock.end / RMF_MIN_BYTES_PER_THREAD;\n    size_t nbThreads = MIN(cctx->jobCount, encodeSize / ENC_MIN_BYTES_PER_THREAD);\n    nbThreads += !nbThreads;\n#else\n    size_t mfThreads = 1;\n    size_t nbThreads = 1;\n#endif\n\n    DEBUGLOG(5, \"FL2_compressCurBlock : %u threads, %u start, %u bytes\", (U32)nbThreads, (U32)cctx->curBlock.start, (U32)encodeSize);\n\n    size_t sliceStart = cctx->curBlock.start;\n    size_t const sliceSize = encodeSize / nbThreads;\n    cctx->jobs[0].block.data = cctx->curBlock.data;\n    cctx->jobs[0].block.start = sliceStart;\n    cctx->jobs[0].block.end = sliceStart + sliceSize;\n\n    for (size_t u = 1; u < nbThreads; ++u) {\n        sliceStart += sliceSize;\n        cctx->jobs[u].block.data = cctx->curBlock.data;\n        cctx->jobs[u].block.start = sliceStart;\n        cctx->jobs[u].block.end = sliceStart + sliceSize;\n    }\n    cctx->jobs[nbThreads - 1].block.end = cctx->curBlock.end;\n\n    /* initialize to length 2 */\n    RMF_initTable(cctx->matchTable, cctx->curBlock.data, cctx->curBlock.end);\n\n    if (cctx->canceled) {\n        RMF_resetIncompleteBuild(cctx->matchTable);\n        return FL2_ERROR(canceled);\n    }\n\n#ifndef FL2_SINGLETHREAD\n\n    mfThreads = MIN(RMF_threadCount(cctx->matchTable), mfThreads);\n    FL2POOL_addRange(cctx->factory, FL2_buildRadixTable, cctx, 1, mfThreads);\n\n#endif\n\n    int err = RMF_buildTable(cctx->matchTable, 0, mfThreads > 1, cctx->curBlock);\n\n#ifndef FL2_SINGLETHREAD\n\n    FL2POOL_waitAll(cctx->factory, 0);\n\n    if (err)\n        return FL2_ERROR(canceled);\n\n#ifdef RMF_CHECK_INTEGRITY\n    err = RMF_integrityCheck(cctx->matchTable, cctx->curBlock.data, cctx->curBlock.start, cctx->curBlock.end, cctx->params.rParams.depth);\n    if (err)\n        return FL2_ERROR(internal);\n#endif\n\n    FL2POOL_addRange(cctx->factory, FL2_compressRadixChunk, cctx, 1, nbThreads);\n\n    cctx->jobs[0].cSize = LZMA2_encode(cctx->jobs[0].enc, cctx->matchTable,\n        cctx->jobs[0].block,\n        &cctx->params.cParams, streamProp,\n        &cctx->progressIn, &cctx->progressOut, &cctx->canceled);\n\n    FL2POOL_waitAll(cctx->factory, 0);\n\n#else /* FL2_SINGLETHREAD */\n\n    if (err)\n        return FL2_ERROR(canceled);\n\n#ifdef RMF_CHECK_INTEGRITY\n    err = RMF_integrityCheck(cctx->matchTable, cctx->curBlock.data, cctx->curBlock.start, cctx->curBlock.end, cctx->params.rParams.depth);\n    if (err)\n        return FL2_ERROR(internal);\n#endif\n    cctx->jobs[0].cSize = LZMA2_encode(cctx->jobs[0].enc, cctx->matchTable,\n        cctx->jobs[0].block,\n        &cctx->params.cParams, streamProp,\n        &cctx->progressIn, &cctx->progressOut, &cctx->canceled);\n\n#endif\n\n    for (size_t u = 0; u < nbThreads; ++u)\n        if (FL2_isError(cctx->jobs[u].cSize))\n            return cctx->jobs[u].cSize;\n\n    cctx->threadCount = nbThreads;\n\n    return FL2_error_no_error;\n}\n\n/* FL2_compressCurBlock_async() : FL2POOL_function type */\nstatic void FL2_compressCurBlock_async(void* const jobDescription, ptrdiff_t const n)\n{\n    FL2_CCtx* const cctx = (FL2_CCtx*)jobDescription;\n\n    cctx->asyncRes = FL2_compressCurBlock_blocking(cctx, (int)n);\n}\n\n/* FL2_compressCurBlock() :\n * Update total input size.\n * Clear the compressed data buffers.\n * Init progress info.\n * Start compression of cctx->curBlock, and wait for completion if no async compression thread exists.\n */\nstatic size_t FL2_compressCurBlock(FL2_CCtx* const cctx, int const streamProp)\n{\n    FL2_initProgress(cctx);\n\n    if (cctx->curBlock.start == cctx->curBlock.end)\n        return FL2_error_no_error;\n\n    /* update largest dict size used */\n    cctx->dictMax = MAX(cctx->dictMax, cctx->curBlock.end);\n\n    cctx->outThread = 0;\n    cctx->threadCount = 0;\n    cctx->outPos = 0;\n\n    U32 rmfWeight = ZSTD_highbit32((U32)cctx->curBlock.end);\n    U32 depthWeight = 2 + (cctx->params.rParams.depth >= 12) + (cctx->params.rParams.depth >= 28);\n    U32 encWeight;\n\n    if (rmfWeight >= 20) {\n        rmfWeight = depthWeight * (rmfWeight - 10) + (rmfWeight - 19) * 12;\n        if (cctx->params.cParams.strategy == 0)\n            encWeight = 20;\n        else if (cctx->params.cParams.strategy == 1)\n            encWeight = 50;\n        else\n            encWeight = 60 + cctx->params.cParams.second_dict_bits + ZSTD_highbit32(cctx->params.cParams.fast_length) * 3U;\n        rmfWeight = (rmfWeight << 4) / (rmfWeight + encWeight);\n        encWeight = 16 - rmfWeight;\n    }\n    else {\n        rmfWeight = 8;\n        encWeight = 8;\n    }\n\n    cctx->rmfWeight = rmfWeight;\n    cctx->encWeight = encWeight;\n\n#ifndef FL2_SINGLETHREAD\n    if(cctx->compressThread != NULL)\n        FL2POOL_add(cctx->compressThread, FL2_compressCurBlock_async, cctx, streamProp);\n    else\n#endif\n        cctx->asyncRes = FL2_compressCurBlock_blocking(cctx, streamProp);\n\n    return cctx->asyncRes;\n}\n\n/* FL2_getProp() :\n * Get the LZMA2 dictionary size property byte. If xxhash is enabled, includes the xxhash flag bit.\n */\nstatic BYTE FL2_getProp(FL2_CCtx* const cctx, size_t const dictionarySize)\n{\n#ifndef NO_XXHASH\n    return LZMA2_getDictSizeProp(dictionarySize) | (BYTE)((cctx->params.doXXH != 0) << FL2_PROP_HASH_BIT);\n#else\n    (void)cctx;\n    return LZMA2_getDictSizeProp(dictionarySize);\n#endif\n}\n\nstatic void FL2_preBeginFrame(FL2_CCtx* const cctx, size_t const dictReduce)\n{\n    /* Free unsuitable match table before reallocating anything else */\n    if (cctx->matchTable && !RMF_compatibleParameters(cctx->matchTable, &cctx->params.rParams, dictReduce)) {\n        RMF_freeMatchTable(cctx->matchTable);\n        cctx->matchTable = NULL;\n    }\n}\n\nstatic size_t FL2_beginFrame(FL2_CCtx* const cctx, size_t const dictReduce)\n{\n    if (FL2_initEncoders(cctx) != 0) /* Create hash objects together, leaving the (large) match table last */\n        return FL2_ERROR(memory_allocation);\n\n    if (cctx->matchTable == NULL) {\n        cctx->matchTable = RMF_createMatchTable(&cctx->params.rParams, dictReduce, cctx->jobCount);\n        if (cctx->matchTable == NULL)\n            return FL2_ERROR(memory_allocation);\n    }\n    else {\n        DEBUGLOG(5, \"Have compatible match table\");\n        RMF_applyParameters(cctx->matchTable, &cctx->params.rParams, dictReduce);\n    }\n\n    cctx->dictMax = 0;\n    cctx->streamTotal = 0;\n    cctx->streamCsize = 0;\n    cctx->progressIn = 0;\n    cctx->progressOut = 0;\n    RMF_initProgress(cctx->matchTable);\n    cctx->asyncRes = 0;\n    cctx->outThread = 0;\n    cctx->threadCount = 0;\n    cctx->outPos = 0;\n    cctx->curBlock.start = 0;\n    cctx->curBlock.end = 0;\n    cctx->lockParams = 1;\n\n    return FL2_error_no_error;\n}\n\nstatic void FL2_endFrame(FL2_CCtx* const cctx)\n{\n    cctx->dictMax = 0;\n    cctx->asyncRes = 0;\n    cctx->lockParams = 0;\n}\n\n/* Compress a memory buffer which may be larger than the dictionary.\n * The property byte is written first unless the omit flag is set.\n * Return: compressed size.\n */\nstatic size_t FL2_compressBuffer(FL2_CCtx* const cctx,\n    const void* const src, size_t srcSize,\n    void* const dst, size_t dstCapacity)\n{\n    if (srcSize == 0)\n        return 0;\n\n    BYTE* dstBuf = dst;\n    size_t const dictionarySize = cctx->params.rParams.dictionary_size;\n    size_t const blockOverlap = OVERLAP_FROM_DICT_SIZE(dictionarySize, cctx->params.rParams.overlap_fraction);\n    int streamProp = cctx->params.omitProp ? -1 : FL2_getProp(cctx, MIN(srcSize, dictionarySize));\n\n    cctx->curBlock.data = src;\n    cctx->curBlock.start = 0;\n\n    size_t blockTotal = 0;\n\n    do {\n        cctx->curBlock.end = cctx->curBlock.start + MIN(srcSize, dictionarySize - cctx->curBlock.start);\n        blockTotal += cctx->curBlock.end - cctx->curBlock.start;\n\n        CHECK_F(FL2_compressCurBlock(cctx, streamProp));\n\n        streamProp = -1;\n\n        for (size_t u = 0; u < cctx->threadCount; ++u) {\n            DEBUGLOG(5, \"Write thread %u : %u bytes\", (U32)u, (U32)cctx->jobs[u].cSize);\n\n            if (dstCapacity < cctx->jobs[u].cSize) \n                return FL2_ERROR(dstSize_tooSmall);\n\n            const BYTE* const outBuf = RMF_getTableAsOutputBuffer(cctx->matchTable, cctx->jobs[u].block.start);\n            memcpy(dstBuf, outBuf, cctx->jobs[u].cSize);\n\n            dstBuf += cctx->jobs[u].cSize;\n            dstCapacity -= cctx->jobs[u].cSize;\n        }\n        srcSize -= cctx->curBlock.end - cctx->curBlock.start;\n        if (cctx->params.cParams.reset_interval\n            && blockTotal + MIN(dictionarySize - blockOverlap, srcSize) > dictionarySize * cctx->params.cParams.reset_interval) {\n            /* periodically reset the dictionary for mt decompression */\n            DEBUGLOG(4, \"Resetting dictionary after %u bytes\", (unsigned)blockTotal);\n            cctx->curBlock.start = 0;\n            blockTotal = 0;\n        }\n        else {\n            cctx->curBlock.start = blockOverlap;\n        }\n        cctx->curBlock.data += cctx->curBlock.end - cctx->curBlock.start;\n    } while (srcSize != 0);\n    return dstBuf - (const BYTE*)dst;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_compressCCtx(FL2_CCtx* cctx,\n    void* dst, size_t dstCapacity,\n    const void* src, size_t srcSize,\n    int compressionLevel)\n{\n    if (dstCapacity < 2U - cctx->params.omitProp) /* empty LZMA2 stream is byte sequence {0, 0} */\n        return FL2_ERROR(dstSize_tooSmall);\n\n    if (compressionLevel > 0)\n        FL2_CCtx_setParameter(cctx, FL2_p_compressionLevel, compressionLevel);\n\n    DEBUGLOG(4, \"FL2_compressCCtx : level %u, %u src => %u avail\", cctx->params.compressionLevel, (U32)srcSize, (U32)dstCapacity);\n\n#ifndef FL2_SINGLETHREAD\n    /* No async compression for in-memory function */\n    FL2POOL_free(cctx->compressThread);\n    cctx->compressThread = NULL;\n    cctx->timeout = 0;\n#endif\n\n    FL2_preBeginFrame(cctx, srcSize);\n    CHECK_F(FL2_beginFrame(cctx, srcSize));\n\n    size_t const cSize = FL2_compressBuffer(cctx, src, srcSize, dst, dstCapacity);\n\n    if (FL2_isError(cSize))\n        return cSize;\n\n    BYTE* dstBuf = dst;\n    BYTE* const end = dstBuf + dstCapacity;\n\n    dstBuf += cSize;\n    if(dstBuf >= end)\n        return FL2_ERROR(dstSize_tooSmall);\n\n    if (cSize == 0)\n        *dstBuf++ = FL2_getProp(cctx, 0);\n\n    *dstBuf++ = LZMA2_END_MARKER;\n\n#ifndef NO_XXHASH\n    if (cctx->params.doXXH && !cctx->params.omitProp) {\n        XXH32_canonical_t canonical;\n        DEBUGLOG(5, \"Writing hash\");\n        // **************** 7-Zip ZS Modification Start ****************\n        //if(end - dstBuf < XXHASH_SIZEOF)\n        if (end - dstBuf < (long)XXHASH_SIZEOF)\n        // **************** 7-Zip ZS Modification End ****************\n            return FL2_ERROR(dstSize_tooSmall);\n        XXH32_canonicalFromHash(&canonical, XXH32(src, srcSize, 0));\n        memcpy(dstBuf, &canonical, XXHASH_SIZEOF);\n        dstBuf += XXHASH_SIZEOF;\n    }\n#endif\n    \n    FL2_endFrame(cctx);\n\n    return dstBuf - (BYTE*)dst;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_compressMt(void* dst, size_t dstCapacity,\n    const void* src, size_t srcSize,\n    int compressionLevel,\n    unsigned nbThreads)\n{\n    FL2_CCtx* const cctx = FL2_createCCtxMt(nbThreads);\n    if (cctx == NULL)\n        return FL2_ERROR(memory_allocation);\n\n    size_t const cSize = FL2_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);\n\n    FL2_freeCCtx(cctx);\n\n    return cSize;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_compress(void* dst, size_t dstCapacity,\n    const void* src, size_t srcSize,\n    int compressionLevel)\n{\n    return FL2_compressMt(dst, dstCapacity, src, srcSize, compressionLevel, 1);\n}\n\nFL2LIB_API BYTE FL2LIB_CALL FL2_getCCtxDictProp(FL2_CCtx* cctx)\n{\n    return LZMA2_getDictSizeProp(cctx->dictMax ? cctx->dictMax : cctx->params.rParams.dictionary_size);\n}\n\n#define MAXCHECK(val,max) do {            \\\n    if ((val)>(max)) {     \\\n        return FL2_ERROR(parameter_outOfBound);  \\\n}   } while(0)\n\n#define CLAMPCHECK(val,min,max) do {            \\\n    if (((val)<(min)) | ((val)>(max))) {     \\\n        return FL2_ERROR(parameter_outOfBound);  \\\n}   } while(0)\n\n\nFL2LIB_API size_t FL2LIB_CALL FL2_CCtx_setParameter(FL2_CCtx* cctx, FL2_cParameter param, size_t value)\n{\n    if (cctx->lockParams\n        && param != FL2_p_literalCtxBits && param != FL2_p_literalPosBits && param != FL2_p_posBits)\n        return FL2_ERROR(stage_wrong);\n\n    switch (param)\n    {\n    case FL2_p_compressionLevel:\n        if (cctx->params.highCompression) {\n            CLAMPCHECK(value, 1, FL2_MAX_HIGH_CLEVEL);\n            FL2_fillParameters(cctx, &FL2_highCParameters[value]);\n        }\n        else {\n            CLAMPCHECK(value, 1, FL2_MAX_CLEVEL);\n            FL2_fillParameters(cctx, &FL2_defaultCParameters[value]);\n        }\n        cctx->params.compressionLevel = (unsigned)value;\n        break;\n\n    case FL2_p_highCompression:\n        cctx->params.highCompression = value != 0;\n        FL2_CCtx_setParameter(cctx, FL2_p_compressionLevel, cctx->params.compressionLevel);\n        break;\n\n    case FL2_p_dictionaryLog:\n        CLAMPCHECK(value, FL2_DICTLOG_MIN, FL2_DICTLOG_MAX);\n        cctx->params.rParams.dictionary_size = (size_t)1 << value;\n        break;\n\n    case FL2_p_dictionarySize:\n        CLAMPCHECK(value, FL2_DICTSIZE_MIN, FL2_DICTSIZE_MAX);\n        cctx->params.rParams.dictionary_size = value;\n        break;\n\n    case FL2_p_overlapFraction:\n        MAXCHECK(value, FL2_BLOCK_OVERLAP_MAX);\n        cctx->params.rParams.overlap_fraction = (unsigned)value;\n        break;\n\n    case FL2_p_resetInterval:\n        if (value != 0)\n            CLAMPCHECK(value, FL2_RESET_INTERVAL_MIN, FL2_RESET_INTERVAL_MAX);\n        cctx->params.cParams.reset_interval = (unsigned)value;\n        break;\n\n    case FL2_p_bufferResize:\n        MAXCHECK(value, FL2_BUFFER_RESIZE_MAX);\n        cctx->params.rParams.match_buffer_resize = (unsigned)value;\n        break;\n\n    case FL2_p_hybridChainLog:\n        CLAMPCHECK(value, FL2_CHAINLOG_MIN, FL2_CHAINLOG_MAX);\n        cctx->params.cParams.second_dict_bits = (unsigned)value;\n        break;\n\n    case FL2_p_hybridCycles:\n        CLAMPCHECK(value, FL2_HYBRIDCYCLES_MIN, FL2_HYBRIDCYCLES_MAX);\n        cctx->params.cParams.match_cycles = (unsigned)value;\n        break;\n\n    case FL2_p_searchDepth:\n        CLAMPCHECK(value, FL2_SEARCH_DEPTH_MIN, FL2_SEARCH_DEPTH_MAX);\n        cctx->params.rParams.depth = (unsigned)value;\n        break;\n\n    case FL2_p_fastLength:\n        CLAMPCHECK(value, FL2_FASTLENGTH_MIN, FL2_FASTLENGTH_MAX);\n        cctx->params.cParams.fast_length = (unsigned)value;\n        break;\n\n    case FL2_p_divideAndConquer:\n        cctx->params.rParams.divide_and_conquer = value != 0;\n        break;\n\n    case FL2_p_strategy:\n        MAXCHECK(value, (unsigned)FL2_ultra);\n        cctx->params.cParams.strategy = (FL2_strategy)value;\n        break;\n\n        /* lc, lp, pb can be changed between encoder chunks.\n         * A condition where lc+lp > 4 is permitted to allow sequential setting,\n         * but will return an error code to alert the calling function.\n         * If lc+lp is still >4 when encoding begins, lc will be reduced. */\n    case FL2_p_literalCtxBits:\n        MAXCHECK(value, FL2_LC_MAX);\n        cctx->params.cParams.lc = (unsigned)value;\n        if (value + cctx->params.cParams.lp > FL2_LCLP_MAX)\n            return FL2_ERROR(lclpMax_exceeded);\n        break;\n\n    case FL2_p_literalPosBits:\n        MAXCHECK(value, FL2_LP_MAX);\n        cctx->params.cParams.lp = (unsigned)value;\n        if (cctx->params.cParams.lc + value > FL2_LCLP_MAX)\n            return FL2_ERROR(lclpMax_exceeded);\n        break;\n\n    case FL2_p_posBits:\n        MAXCHECK(value, FL2_PB_MAX);\n        cctx->params.cParams.pb = (unsigned)value;\n        break;\n\n#ifndef NO_XXHASH\n    case FL2_p_doXXHash:\n        cctx->params.doXXH = value != 0;\n        break;\n#endif\n\n    case FL2_p_omitProperties:\n        cctx->params.omitProp = value != 0;\n        break;\n#ifdef RMF_REFERENCE\n    case FL2_p_useReferenceMF:\n        cctx->params.rParams.use_ref_mf = value != 0;\n        break;\n#endif\n    default: return FL2_ERROR(parameter_unsupported);\n    }\n    return value;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_CCtx_getParameter(FL2_CCtx* cctx, FL2_cParameter param)\n{\n    switch (param)\n    {\n    case FL2_p_compressionLevel:\n        return cctx->params.compressionLevel;\n\n    case FL2_p_highCompression:\n        return cctx->params.highCompression;\n\n    case FL2_p_dictionaryLog: {\n        size_t dictLog = FL2_DICTLOG_MIN;\n        while (((size_t)1 << dictLog) < cctx->params.rParams.dictionary_size)\n            ++dictLog;\n        return dictLog;\n    }\n\n    case FL2_p_dictionarySize:\n        return cctx->params.rParams.dictionary_size;\n\n    case FL2_p_overlapFraction:\n        return cctx->params.rParams.overlap_fraction;\n\n    case FL2_p_resetInterval:\n        return cctx->params.cParams.reset_interval;\n\n    case FL2_p_bufferResize:\n        return cctx->params.rParams.match_buffer_resize;\n\n    case FL2_p_hybridChainLog:\n        return cctx->params.cParams.second_dict_bits;\n\n    case FL2_p_hybridCycles:\n        return cctx->params.cParams.match_cycles;\n\n    case FL2_p_literalCtxBits:\n        return cctx->params.cParams.lc;\n\n    case FL2_p_literalPosBits:\n        return cctx->params.cParams.lp;\n\n    case FL2_p_posBits:\n        return cctx->params.cParams.pb;\n\n    case FL2_p_searchDepth:\n        return cctx->params.rParams.depth;\n\n    case FL2_p_fastLength:\n        return cctx->params.cParams.fast_length;\n\n    case FL2_p_divideAndConquer:\n        return cctx->params.rParams.divide_and_conquer;\n\n    case FL2_p_strategy:\n        return (size_t)cctx->params.cParams.strategy;\n\n#ifndef NO_XXHASH\n    case FL2_p_doXXHash:\n        return cctx->params.doXXH;\n#endif\n\n    case FL2_p_omitProperties:\n        return cctx->params.omitProp;\n#ifdef RMF_REFERENCE\n    case FL2_p_useReferenceMF:\n        return cctx->params.rParams.use_ref_mf;\n#endif\n    default: return FL2_ERROR(parameter_unsupported);\n    }\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_CStream_setParameter(FL2_CStream* fcs, FL2_cParameter param, size_t value)\n{\n    return FL2_CCtx_setParameter(fcs, param, value);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_CStream_getParameter(FL2_CStream* fcs, FL2_cParameter param)\n{\n    return FL2_CCtx_getParameter(fcs, param);\n}\n\nFL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStream(void)\n{\n    return FL2_createCCtx_internal(1, 0);\n}\n\nFL2LIB_API FL2_CStream* FL2LIB_CALL FL2_createCStreamMt(unsigned nbThreads, int dualBuffer)\n{\n    return FL2_createCCtx_internal(nbThreads, dualBuffer);\n}\n\nFL2LIB_API void FL2LIB_CALL FL2_freeCStream(FL2_CStream * fcs)\n{\n    FL2_freeCCtx(fcs);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_initCStream(FL2_CStream* fcs, int compressionLevel)\n{\n    DEBUGLOG(4, \"FL2_initCStream level %d\", compressionLevel);\n\n    fcs->endMarked = 0;\n    fcs->wroteProp = 0;\n    fcs->loopCount = 0;\n\n    if(compressionLevel > 0)\n        FL2_CCtx_setParameter(fcs, FL2_p_compressionLevel, compressionLevel);\n\n    DICT_buffer *const buf = &fcs->buf;\n    size_t const dictSize = fcs->params.rParams.dictionary_size;\n\n    /* Free unsuitable objects before reallocating anything new */\n    if (DICT_size(buf) < dictSize)\n        DICT_destruct(buf);\n\n    FL2_preBeginFrame(fcs, 0);\n\n#ifdef NO_XXHASH\n    int const doHash = 0;\n#else\n    int const doHash = (fcs->params.doXXH && !fcs->params.omitProp);\n#endif\n    size_t dictOverlap = OVERLAP_FROM_DICT_SIZE(fcs->params.rParams.dictionary_size, fcs->params.rParams.overlap_fraction);\n    if (DICT_init(buf, dictSize, dictOverlap, fcs->params.cParams.reset_interval, doHash) != 0)\n        return FL2_ERROR(memory_allocation);\n\n    CHECK_F(FL2_beginFrame(fcs, 0));\n\n    return 0;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_setCStreamTimeout(FL2_CStream * fcs, unsigned timeout)\n{\n#ifndef FL2_SINGLETHREAD\n    if (timeout != 0) {\n        if (fcs->compressThread == NULL) {\n            fcs->compressThread = FL2POOL_create(1);\n            if (fcs->compressThread == NULL)\n                return FL2_ERROR(memory_allocation);\n        }\n    }\n    else if (!DICT_async(&fcs->buf) && fcs->dictMax == 0) {\n        /* Only free the thread if not dual buffering and compression not underway */\n        FL2POOL_free(fcs->compressThread);\n        fcs->compressThread = NULL;\n    }\n    fcs->timeout = timeout;\n#endif\n    return FL2_error_no_error;\n}\n\nstatic size_t FL2_compressStream_internal(FL2_CStream* const fcs, int const ending)\n{\n    CHECK_F(FL2_waitCStream(fcs));\n\n    DICT_buffer *const buf = &fcs->buf;\n\n    /* no compression can occur while compressed output exists */\n    if (fcs->outThread == fcs->threadCount && DICT_hasUnprocessed(buf)) {\n        fcs->streamTotal += fcs->curBlock.end - fcs->curBlock.start;\n\n        DICT_getBlock(buf, &fcs->curBlock);\n\n        int streamProp = -1;\n\n        if (!fcs->wroteProp && !fcs->params.omitProp) {\n            /* If the LZMA2 property byte is required and not already written,\n             * pass it to the compression function \n             */\n            size_t dictionarySize = ending ? MAX(fcs->dictMax, fcs->curBlock.end)\n                : fcs->params.rParams.dictionary_size;\n            streamProp = FL2_getProp(fcs, dictionarySize);\n            DEBUGLOG(4, \"Writing property byte : 0x%X\", streamProp);\n            fcs->wroteProp = 1;\n        }\n\n        CHECK_F(FL2_compressCurBlock(fcs, streamProp));\n    }\n    return FL2_error_no_error;\n}\n\n/* Copy the compressed output stored in the match table buffer.\n * One slice exists per thread.\n */\nFL2LIB_API size_t FL2LIB_CALL FL2_copyCStreamOutput(FL2_CStream* fcs, FL2_outBuffer *output)\n{\n    for (; fcs->outThread < fcs->threadCount; ++fcs->outThread) {\n        const BYTE* const outBuf = RMF_getTableAsOutputBuffer(fcs->matchTable, fcs->jobs[fcs->outThread].block.start) + fcs->outPos;\n        BYTE* const dstBuf = (BYTE*)output->dst + output->pos;\n        size_t const dstCapacity = output->size - output->pos;\n        size_t toWrite = fcs->jobs[fcs->outThread].cSize;\n\n        toWrite = MIN(toWrite - fcs->outPos, dstCapacity);\n\n        DEBUGLOG(5, \"CStream : writing %u bytes\", (U32)toWrite);\n\n        memcpy(dstBuf, outBuf, toWrite);\n        fcs->outPos += toWrite;\n        output->pos += toWrite;\n\n        /* If the slice is not flushed, the output is full */\n        if (fcs->outPos < fcs->jobs[fcs->outThread].cSize)\n            return 1;\n\n        fcs->outPos = 0;\n    }\n    return 0;\n}\n\nstatic size_t FL2_compressStream_input(FL2_CStream* fcs, FL2_inBuffer* input)\n{\n    CHECK_F(fcs->asyncRes);\n\n    DICT_buffer * const buf = &fcs->buf;\n\n    while (input->pos < input->size) {\n        /* read input until the buffer(s) are full */\n        if (DICT_needShift(buf)) {\n            /* cannot shift single dict during compression */\n            if(!DICT_async(buf))\n                CHECK_F(FL2_waitCStream(fcs));\n            DICT_shift(buf);\n        }\n        \n        CHECK_F(fcs->asyncRes);\n\n        DICT_put(buf, input);\n        \n        if (!DICT_availSpace(buf)) {\n            /* break if the compressor is not available */\n            if (fcs->outThread < fcs->threadCount)\n                break;\n\n            CHECK_F(FL2_compressStream_internal(fcs, 0));\n        }\n\n        CHECK_F(fcs->asyncRes);\n    }\n\n    return FL2_error_no_error;\n}\n\nstatic size_t FL2_loopCheck(FL2_CStream* fcs, int unchanged)\n{\n    if (unchanged) {\n        ++fcs->loopCount;\n        if (fcs->loopCount > FL2_MAX_LOOPS) {\n            FL2_cancelCStream(fcs);\n            return FL2_ERROR(buffer);\n        }\n    }\n    else {\n        fcs->loopCount = 0;\n    }\n    return FL2_error_no_error;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_compressStream(FL2_CStream* fcs, FL2_outBuffer *output, FL2_inBuffer* input)\n{\n    if (!fcs->lockParams)\n        return FL2_ERROR(init_missing);\n\n    size_t const prevIn = input->pos;\n    size_t const prevOut = (output != NULL) ? output->pos : 0;\n\n    if (output != NULL && fcs->outThread < fcs->threadCount)\n        FL2_copyCStreamOutput(fcs, output);\n\n    CHECK_F(FL2_compressStream_input(fcs, input));\n\n    if(output != NULL && fcs->outThread < fcs->threadCount)\n        FL2_copyCStreamOutput(fcs, output);\n\n    CHECK_F(FL2_loopCheck(fcs, prevIn == input->pos && (output == NULL || prevOut == output->pos)));\n\n    return fcs->outThread < fcs->threadCount;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_getDictionaryBuffer(FL2_CStream * fcs, FL2_dictBuffer * dict)\n{\n    if (!fcs->lockParams)\n        return FL2_ERROR(init_missing);\n\n    CHECK_F(fcs->asyncRes);\n\n    DICT_buffer *buf = &fcs->buf;\n\n    if (!DICT_availSpace(buf) && DICT_hasUnprocessed(buf))\n        CHECK_F(FL2_compressStream_internal(fcs, 0));\n\n    if (DICT_needShift(buf) && !DICT_async(buf))\n        CHECK_F(FL2_waitCStream(fcs));\n\n    dict->size = (unsigned long)DICT_get(buf, &dict->dst);\n\n    return FL2_error_no_error;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_updateDictionary(FL2_CStream * fcs, size_t addedSize)\n{\n    if (DICT_update(&fcs->buf, addedSize))\n        CHECK_F(FL2_compressStream_internal(fcs, 0));\n\n    return fcs->outThread < fcs->threadCount;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_getNextCompressedBuffer(FL2_CStream* fcs, FL2_cBuffer* cbuf)\n{\n    cbuf->src = NULL;\n    cbuf->size = 0;\n\n#ifndef FL2_SINGLETHREAD\n    CHECK_F(FL2_waitCStream(fcs));\n#endif\n\n    if (fcs->outThread < fcs->threadCount) {\n        cbuf->src = RMF_getTableAsOutputBuffer(fcs->matchTable, fcs->jobs[fcs->outThread].block.start) + fcs->outPos;\n        cbuf->size = fcs->jobs[fcs->outThread].cSize - fcs->outPos;\n        ++fcs->outThread;\n        fcs->outPos = 0;\n    }\n    return cbuf->size;\n}\n\nFL2LIB_API unsigned long long FL2LIB_CALL FL2_getCStreamProgress(const FL2_CStream * fcs, unsigned long long *outputSize)\n{\n    if (outputSize != NULL)\n        *outputSize = fcs->streamCsize + fcs->progressOut;\n\n    U64 const encodeSize = fcs->curBlock.end - fcs->curBlock.start;\n\n    if (fcs->progressIn == 0 && fcs->curBlock.end != 0)\n        return fcs->streamTotal + ((fcs->matchTable->progress * encodeSize / fcs->curBlock.end * fcs->rmfWeight) >> 4);\n\n    return fcs->streamTotal + ((fcs->rmfWeight * encodeSize) >> 4) + ((fcs->progressIn * fcs->encWeight) >> 4);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_waitCStream(FL2_CStream * fcs)\n{\n#ifndef FL2_SINGLETHREAD\n    if (FL2POOL_waitAll(fcs->compressThread, fcs->timeout) != 0)\n        return FL2_ERROR(timedOut);\n    CHECK_F(fcs->asyncRes);\n#endif\n    return fcs->outThread < fcs->threadCount;\n}\n\nFL2LIB_API void FL2LIB_CALL FL2_cancelCStream(FL2_CStream *fcs)\n{\n#ifndef FL2_SINGLETHREAD\n    if (fcs->compressThread != NULL) {\n        fcs->canceled = 1;\n\n        RMF_cancelBuild(fcs->matchTable);\n        FL2POOL_waitAll(fcs->compressThread, 0);\n\n        fcs->canceled = 0;\n    }\n#endif\n    FL2_endFrame(fcs);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_remainingOutputSize(const FL2_CStream* fcs)\n{\n    CHECK_F(fcs->asyncRes);\n\n    size_t cSize = 0;\n    for (size_t u = fcs->outThread; u < fcs->threadCount; ++u)\n        cSize += fcs->jobs[u].cSize;\n\n    return cSize;\n}\n\n/* Write the properties byte (if required), the hash and the end marker\n * into the output buffer.\n */\nstatic void FL2_writeEnd(FL2_CStream* const fcs)\n{\n    size_t thread = fcs->threadCount - 1;\n    if (fcs->outThread == fcs->threadCount) {\n        fcs->outThread = 0; \n        fcs->threadCount = 1;\n        fcs->jobs[0].cSize = 0;\n        thread = 0;\n    }\n    BYTE *const dst = RMF_getTableAsOutputBuffer(fcs->matchTable, fcs->jobs[thread].block.start)\n        + fcs->jobs[thread].cSize;\n\n    size_t pos = 0;\n\n    if (!fcs->wroteProp && !fcs->params.omitProp) {\n        /* no compression occurred */\n        dst[pos] = FL2_getProp(fcs, 0);\n        DEBUGLOG(4, \"Writing property byte : 0x%X\", dst[pos]);\n        ++pos;\n        fcs->wroteProp = 1;\n    }\n\n    DEBUGLOG(4, \"Writing end marker\");\n    dst[pos++] = LZMA2_END_MARKER;\n\n#ifndef NO_XXHASH\n    if (fcs->params.doXXH && !fcs->params.omitProp) {\n        XXH32_canonical_t canonical;\n\n        XXH32_canonicalFromHash(&canonical, DICT_getDigest(&fcs->buf));\n        DEBUGLOG(4, \"Writing XXH32\");\n        memcpy(dst + pos, &canonical, XXHASH_SIZEOF);\n\n        pos += XXHASH_SIZEOF;\n    }\n#endif\n    fcs->jobs[thread].cSize += pos;\n    fcs->endMarked = 1;\n\n    FL2_endFrame(fcs);\n}\n\nstatic size_t FL2_flushStream_internal(FL2_CStream* fcs, int const ending)\n{\n    CHECK_F(fcs->asyncRes);\n\n    DEBUGLOG(4, \"FL2_flushStream_internal : %u to compress, %u to write\",\n        (U32)(fcs->buf.end - fcs->buf.start),\n        (U32)FL2_remainingOutputSize(fcs));\n\n    CHECK_F(FL2_compressStream_internal(fcs, ending));\n\n    return fcs->outThread < fcs->threadCount;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_flushStream(FL2_CStream* fcs, FL2_outBuffer *output)\n{\n    if (!fcs->lockParams)\n        return FL2_ERROR(init_missing);\n\n    size_t const prevOut = (output != NULL) ? output->pos : 0;\n\n    if (output != NULL && fcs->outThread < fcs->threadCount)\n        FL2_copyCStreamOutput(fcs, output);\n\n    size_t res = FL2_flushStream_internal(fcs, 0);\n    CHECK_F(res);\n\n    if (output != NULL && res != 0) {\n        FL2_copyCStreamOutput(fcs, output);\n        res = fcs->outThread < fcs->threadCount;\n    }\n\n    CHECK_F(FL2_loopCheck(fcs, output != NULL && prevOut == output->pos));\n\n    return res;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_endStream(FL2_CStream* fcs, FL2_outBuffer *output)\n{\n    if (!fcs->endMarked && !fcs->lockParams)\n        return FL2_ERROR(init_missing);\n\n    size_t const prevOut = (output != NULL) ? output->pos : 0;\n    \n    if (output != NULL && fcs->outThread < fcs->threadCount)\n        FL2_copyCStreamOutput(fcs, output);\n\n    CHECK_F(FL2_flushStream_internal(fcs, 1));\n\n    size_t res = FL2_waitCStream(fcs);\n    CHECK_F(res);\n\n    if (!fcs->endMarked && !DICT_hasUnprocessed(&fcs->buf)) {\n        FL2_writeEnd(fcs);\n        res = 1;\n    }\n\n    if (output != NULL && res != 0) {\n        FL2_copyCStreamOutput(fcs, output);\n        res = fcs->outThread < fcs->threadCount || DICT_hasUnprocessed(&fcs->buf);\n    }\n\n    CHECK_F(FL2_loopCheck(fcs, output != NULL && prevOut == output->pos));\n\n    return res;\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_getLevelParameters(int compressionLevel, int high, FL2_compressionParameters * params)\n{\n    if (high) {\n        if (compressionLevel < 0 || compressionLevel > FL2_MAX_HIGH_CLEVEL)\n            return FL2_ERROR(parameter_outOfBound);\n        *params = FL2_highCParameters[compressionLevel];\n    }\n    else {\n        if (compressionLevel < 0 || compressionLevel > FL2_MAX_CLEVEL)\n            return FL2_ERROR(parameter_outOfBound);\n        *params = FL2_defaultCParameters[compressionLevel];\n    }\n    return FL2_error_no_error;\n}\n\nstatic size_t FL2_memoryUsage_internal(size_t const dictionarySize, unsigned const bufferResize,\n    unsigned const chainLog,\n    FL2_strategy const strategy,\n    unsigned const nbThreads)\n{\n    return RMF_memoryUsage(dictionarySize, bufferResize, nbThreads)\n        + LZMA2_encMemoryUsage(chainLog, strategy, nbThreads);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize(int compressionLevel, unsigned nbThreads)\n{\n    if (compressionLevel == 0)\n        compressionLevel = FL2_CLEVEL_DEFAULT;\n\n    CLAMPCHECK(compressionLevel, 1, FL2_MAX_CLEVEL);\n\n    return FL2_estimateCCtxSize_byParams(FL2_defaultCParameters + compressionLevel, nbThreads);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_byParams(const FL2_compressionParameters * params, unsigned nbThreads)\n{\n    nbThreads = FL2_checkNbThreads(nbThreads);\n    return FL2_memoryUsage_internal(params->dictionarySize,\n        FL2_BUFFER_RESIZE_DEFAULT,\n        params->chainLog,\n        params->strategy,\n        nbThreads);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCCtxSize_usingCCtx(const FL2_CCtx * cctx)\n{\n    return FL2_memoryUsage_internal(cctx->params.rParams.dictionary_size,\n        cctx->params.rParams.match_buffer_resize,\n        cctx->params.cParams.second_dict_bits,\n        cctx->params.cParams.strategy,\n        cctx->jobCount) + DICT_memUsage(&cctx->buf);\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize(int compressionLevel, unsigned nbThreads, int dualBuffer)\n{\n    return FL2_estimateCCtxSize(compressionLevel, nbThreads)\n        + (FL2_defaultCParameters[compressionLevel].dictionarySize << (dualBuffer != 0));\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_byParams(const FL2_compressionParameters * params, unsigned nbThreads, int dualBuffer)\n{\n    return FL2_estimateCCtxSize_byParams(params, nbThreads)\n        + (params->dictionarySize << (dualBuffer != 0));\n}\n\nFL2LIB_API size_t FL2LIB_CALL FL2_estimateCStreamSize_usingCStream(const FL2_CStream* fcs)\n{\n    return FL2_estimateCCtxSize_usingCCtx(fcs);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_compress_internal.h",
    "content": "﻿/*\n * Copyright (c) 2018, Conor McCarthy\n * All rights reserved.\n * Parts based on zstd_compress_internal.h copyright Yann Collet\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef FL2_COMPRESS_H\n#define FL2_COMPRESS_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"mem.h\"\n#include \"data_block.h\"\n#include \"radix_internal.h\"\n#include \"lzma2_enc.h\"\n#include \"fast-lzma2.h\"\n#include \"fl2_threading.h\"\n#include \"fl2_pool.h\"\n#include \"dict_buffer.h\"\n#ifndef NO_XXHASH\n#  include \"xxhash.h\"\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-*************************************\n*  Context memory management\n***************************************/\n\ntypedef struct {\n    FL2_lzma2Parameters cParams;\n    RMF_parameters rParams;\n    unsigned compressionLevel;\n    BYTE highCompression;\n#ifndef NO_XXHASH\n    BYTE doXXH;\n#endif\n    BYTE omitProp;\n} FL2_CCtx_params;\n\ntypedef struct {\n    FL2_CCtx* cctx;\n    LZMA2_ECtx* enc;\n    FL2_dataBlock block;\n    size_t cSize;\n} FL2_job;\n\nstruct FL2_CCtx_s {\n    DICT_buffer buf;\n    FL2_CCtx_params params;\n#ifndef FL2_SINGLETHREAD\n    FL2POOL_ctx* factory;\n    FL2POOL_ctx* compressThread;\n#endif\n    FL2_dataBlock curBlock;\n    size_t asyncRes;\n    size_t threadCount;\n    size_t outThread;\n    size_t outPos;\n    size_t dictMax;\n    U64 streamTotal;\n    U64 streamCsize;\n    FL2_matchTable* matchTable;\n#ifndef FL2_SINGLETHREAD\n    U32 timeout;\n#endif\n    U32 rmfWeight;\n    U32 encWeight;\n    FL2_atomic progressIn;\n    FL2_atomic progressOut;\n    int canceled;\n    BYTE wroteProp;\n    BYTE endMarked;\n    BYTE loopCount;\n    BYTE lockParams;\n    unsigned jobCount;\n    FL2_job jobs[1];\n};\n\n#if defined (__cplusplus)\n}\n#endif\n\n\n#endif /* FL2_COMPRESS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_errors.h",
    "content": "﻿/*\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * All rights reserved.\n * Modified for FL2 by Conor McCarthy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef FL2_ERRORS_H_398273423\n#define FL2_ERRORS_H_398273423\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*===== dependency =====*/\n#include <stddef.h>   /* size_t */\n\n#include \"fast-lzma2.h\"\n\n/*-****************************************\n *  error codes list\n *  note : this API is still considered unstable\n *         and shall not be used with a dynamic library.\n *         only static linking is allowed\n ******************************************/\ntypedef enum {\n  FL2_error_no_error                = 0,\n  FL2_error_GENERIC                 = 1,\n  FL2_error_internal                = 2,\n  FL2_error_corruption_detected     = 3,\n  FL2_error_checksum_wrong          = 4,\n  FL2_error_parameter_unsupported   = 5,\n  FL2_error_parameter_outOfBound    = 6,\n  FL2_error_lclpMax_exceeded        = 7,\n  FL2_error_stage_wrong             = 8,\n  FL2_error_init_missing            = 9,\n  FL2_error_memory_allocation       = 10,\n  FL2_error_dstSize_tooSmall        = 11,\n  FL2_error_srcSize_wrong           = 12,\n  FL2_error_canceled                = 13,\n  FL2_error_buffer                  = 14,\n  FL2_error_timedOut                = 15,\n  FL2_error_maxCode                 = 20  /* never EVER use this value directly, it can change in future versions! Use FL2_isError() instead */\n} FL2_ErrorCode;\n\n/*! FL2_getErrorCode() :\n    convert a `size_t` function result into a `FL2_ErrorCode` enum type,\n    which can be used to compare with enum list published above */\nFL2LIB_API FL2_ErrorCode FL2LIB_CALL FL2_getErrorCode(size_t functionResult);\nFL2LIB_API const char* FL2LIB_CALL FL2_getErrorString(FL2_ErrorCode code);   /**< Same as FL2_getErrorName, but using a `FL2_ErrorCode` enum argument */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* FL2_ERRORS_H_398273423 */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_internal.h",
    "content": "﻿/*\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * All rights reserved.\n * Modified for FL2 by Conor McCarthy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef FL2_INTERNAL_H_\n#define FL2_INTERNAL_H_\n\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"mem.h\"\n#include \"compiler.h\"\n\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*-****************************************\n*  Error codes handling\n******************************************/\n#define PREFIX(name) FL2_error_##name\n#define FL2_ERROR(name) ((size_t)-PREFIX(name))\n\n\n/*-*************************************\n*  Stream properties\n***************************************/\n#define FL2_PROP_HASH_BIT 7\n#define FL2_LZMA_PROP_MASK 0x3FU\n#ifndef NO_XXHASH\n#  define XXHASH_SIZEOF sizeof(XXH32_canonical_t)\n#endif\n\n\n/*-*************************************\n*  Debug\n***************************************/\n#if defined(FL2_DEBUG) && (FL2_DEBUG>=1)\n#  include <assert.h>\n#else\n#  ifndef assert\n#    define assert(condition) ((void)0)\n#  endif\n#endif\n\n#define FL2_STATIC_ASSERT(c) { enum { FL2_static_assert = 1/(int)(!!(c)) }; }\n\n// **************** NanaZip Modification Start ****************\n#if 0 // ******** Annotated FastLZMA2 Mainline Source Code snippet Start ********\n#if defined(FL2_DEBUG) && (FL2_DEBUG>=2)\n#  include <stdio.h>\nextern int g_debuglog_enable;\n/* recommended values for FL2_DEBUG display levels :\n * 1 : no display, enables assert() only\n * 2 : reserved for currently active debugging path\n * 3 : events once per object lifetime (CCtx, CDict)\n * 4 : events once per frame\n * 5 : events once per block\n * 6 : events once per sequence (*very* verbose) */\n#  define RAWLOG(l, ...) {                                 \\\n                if ((g_debuglog_enable) & (l<=FL2_DEBUG)) { \\\n                    fprintf(stderr, __VA_ARGS__);            \\\n            }   }\n#  define DEBUGLOG(l, ...) {                                 \\\n                if ((g_debuglog_enable) & (l<=FL2_DEBUG)) { \\\n                    fprintf(stderr, __FILE__ \": \");          \\\n                    fprintf(stderr, __VA_ARGS__);            \\\n                    fprintf(stderr, \" \\n\");                  \\\n            }   }\n#else\n#  define RAWLOG(l, ...)      {}    /* disabled */\n#  define DEBUGLOG(l, ...)    {}    /* disabled */\n#endif\n#endif // ******** Annotated FastLZMA2 Mainline Source Code snippet End ********\n// **************** NanaZip Modification End ****************\n\n\n/*-*************************************\n*  shared macros\n***************************************/\n#undef MIN\n#undef MAX\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n#define CHECK_F(f) do { size_t const errcod = f; if (FL2_isError(errcod)) return errcod; } while(0)  /* check and Forward error code */\n#define CHECK_E(f, e) do { size_t const errcod = f; if (FL2_isError(errcod)) return FL2_ERROR(e); } while(0)  /* check and send Error code */\n\nMEM_STATIC U32 ZSTD_highbit32(U32 val)\n{\n    assert(val != 0);\n    {\n#   if defined(_MSC_VER)   /* Visual */\n        unsigned long r=0;\n        _BitScanReverse(&r, val);\n        return (unsigned)r;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* GCC Intrinsic */\n        return 31 - __builtin_clz(val);\n#   else   /* Software version */\n        static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n        U32 v = val;\n        int r;\n        v |= v >> 1;\n        v |= v >> 2;\n        v |= v >> 4;\n        v |= v >> 8;\n        v |= v >> 16;\n        r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];\n        return r;\n#   endif\n    }\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* FL2_INTERNAL_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_pool.c",
    "content": "﻿/*\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * All rights reserved.\n * Modified for FL2 by Conor McCarthy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ======   Dependencies   ======= */\n#include <stddef.h>  /* size_t */\n#include <stdlib.h>  /* malloc, calloc */\n#include \"fl2_pool.h\"\n#include \"fl2_internal.h\"\n\n\n#ifndef FL2_SINGLETHREAD\n\n#include \"fl2_threading.h\"   /* pthread adaptation */\n\nstruct FL2POOL_ctx_s {\n    /* Keep track of the threads */\n    size_t numThreads;\n\n    /* All threads work on the same function and object during a job */\n    FL2POOL_function function;\n    void *opaque;\n\n    /* The number of threads working on jobs */\n    size_t numThreadsBusy;\n    /* Indicates the number of threads requested and the values to pass */\n    ptrdiff_t queueIndex;\n    ptrdiff_t queueEnd;\n\n    /* The mutex protects the queue */\n    FL2_pthread_mutex_t queueMutex;\n    /* Condition variable for pushers to wait on when the queue is full */\n    FL2_pthread_cond_t busyCond;\n    /* Condition variable for poppers to wait on when the queue is empty */\n    FL2_pthread_cond_t newJobsCond;\n    /* Indicates if the queue is shutting down */\n    int shutdown;\n\n    /* The threads. Extras to be calloc'd */\n    FL2_pthread_t threads[1];\n};\n\n/* FL2POOL_thread() :\n   Work thread for the thread pool.\n   Waits for jobs and executes them.\n   @returns : NULL on failure else non-null.\n*/\nstatic void* FL2POOL_thread(void* opaque)\n{\n    FL2POOL_ctx* const ctx = (FL2POOL_ctx*)opaque;\n    if (!ctx) { return NULL; }\n    FL2_pthread_mutex_lock(&ctx->queueMutex);\n    for (;;) {\n\n        /* While the mutex is locked, wait for a non-empty queue or until shutdown */\n        while (ctx->queueIndex >= ctx->queueEnd && !ctx->shutdown) {\n            FL2_pthread_cond_wait(&ctx->newJobsCond, &ctx->queueMutex);\n        }\n        /* empty => shutting down: so stop */\n        if (ctx->shutdown) {\n            FL2_pthread_mutex_unlock(&ctx->queueMutex);\n            return opaque;\n        }\n        /* Pop a job off the queue */\n        size_t n = ctx->queueIndex;\n        ++ctx->queueIndex;\n        ++ctx->numThreadsBusy;\n        /* Unlock the mutex and run the job */\n        FL2_pthread_mutex_unlock(&ctx->queueMutex);\n\n        ctx->function(ctx->opaque, n);\n\n        FL2_pthread_mutex_lock(&ctx->queueMutex);\n        --ctx->numThreadsBusy;\n        /* Signal the master thread waiting for jobs to complete */\n        FL2_pthread_cond_signal(&ctx->busyCond);\n    }  /* for (;;) */\n    /* Unreachable */\n}\n\nFL2POOL_ctx* FL2POOL_create(size_t numThreads)\n{\n    FL2POOL_ctx* ctx;\n    /* Check the parameters */\n    if (!numThreads) { return NULL; }\n    /* Allocate the context and zero initialize */\n    ctx = calloc(1, sizeof(FL2POOL_ctx) + (numThreads - 1) * sizeof(FL2_pthread_t));\n    if (!ctx) { return NULL; }\n    /* Initialize the busy count and jobs range */\n    ctx->numThreadsBusy = 0;\n    ctx->queueIndex = 0;\n    ctx->queueEnd = 0;\n    (void)FL2_pthread_mutex_init(&ctx->queueMutex, NULL);\n    (void)FL2_pthread_cond_init(&ctx->busyCond, NULL);\n    (void)FL2_pthread_cond_init(&ctx->newJobsCond, NULL);\n    ctx->shutdown = 0;\n    ctx->numThreads = 0;\n    /* Initialize the threads */\n    {   size_t i;\n        for (i = 0; i < numThreads; ++i) {\n            if (FL2_pthread_create(&ctx->threads[i], NULL, &FL2POOL_thread, ctx)) {\n                ctx->numThreads = i;\n                FL2POOL_free(ctx);\n                return NULL;\n        }   }\n        ctx->numThreads = numThreads;\n    }\n    return ctx;\n}\n\n/*! FL2POOL_join() :\n    Shutdown the queue, wake any sleeping threads, and join all of the threads.\n*/\nstatic void FL2POOL_join(FL2POOL_ctx* ctx)\n{\n    /* Shut down the queue */\n    FL2_pthread_mutex_lock(&ctx->queueMutex);\n    ctx->shutdown = 1;\n    /* Wake up sleeping threads */\n    FL2_pthread_cond_broadcast(&ctx->newJobsCond);\n    FL2_pthread_mutex_unlock(&ctx->queueMutex);\n    /* Join all of the threads */\n    for (size_t i = 0; i < ctx->numThreads; ++i)\n        FL2_pthread_join(ctx->threads[i], NULL);\n}\n\nvoid FL2POOL_free(FL2POOL_ctx *ctx)\n{\n    if (!ctx) { return; }\n    FL2POOL_join(ctx);\n    FL2_pthread_mutex_destroy(&ctx->queueMutex);\n    FL2_pthread_cond_destroy(&ctx->busyCond);\n    FL2_pthread_cond_destroy(&ctx->newJobsCond);\n    free(ctx);\n}\n\nsize_t FL2POOL_sizeof(FL2POOL_ctx *ctx)\n{\n    if (ctx==NULL) return 0;  /* supports sizeof NULL */\n    return sizeof(*ctx) + ctx->numThreads * sizeof(FL2_pthread_t);\n}\n\nvoid FL2POOL_addRange(void* ctxVoid, FL2POOL_function function, void *opaque, ptrdiff_t first, ptrdiff_t end)\n{\n    FL2POOL_ctx* const ctx = (FL2POOL_ctx*)ctxVoid;\n    if (!ctx)\n\t\treturn; \n\n    /* Callers always wait for jobs to complete before adding a new set */\n    assert(!ctx->numThreadsBusy);\n\n    FL2_pthread_mutex_lock(&ctx->queueMutex);\n    ctx->function = function;\n    ctx->opaque = opaque;\n    ctx->queueIndex = first;\n    ctx->queueEnd = end;\n    FL2_pthread_cond_broadcast(&ctx->newJobsCond);\n    FL2_pthread_mutex_unlock(&ctx->queueMutex);\n}\n\nvoid FL2POOL_add(void* ctxVoid, FL2POOL_function function, void *opaque, ptrdiff_t n)\n{\n    FL2POOL_addRange(ctxVoid, function, opaque, n, n + 1);\n}\n\nint FL2POOL_waitAll(void *ctxVoid, unsigned timeout)\n{\n    FL2POOL_ctx* const ctx = (FL2POOL_ctx*)ctxVoid;\n    if (!ctx || (!ctx->numThreadsBusy && ctx->queueIndex >= ctx->queueEnd) || ctx->shutdown) { return 0; }\n\n    FL2_pthread_mutex_lock(&ctx->queueMutex);\n    /* Need to test for ctx->queueIndex < ctx->queueEnd in case not all jobs have started */\n    if (timeout != 0) {\n        if ((ctx->numThreadsBusy || ctx->queueIndex < ctx->queueEnd) && !ctx->shutdown)\n            FL2_pthread_cond_timedwait(&ctx->busyCond, &ctx->queueMutex, timeout);\n    }\n    else {\n        while ((ctx->numThreadsBusy || ctx->queueIndex < ctx->queueEnd) && !ctx->shutdown)\n            FL2_pthread_cond_wait(&ctx->busyCond, &ctx->queueMutex);\n    }\n    FL2_pthread_mutex_unlock(&ctx->queueMutex);\n    return ctx->numThreadsBusy && !ctx->shutdown;\n}\n\nsize_t FL2POOL_threadsBusy(void * ctx)\n{\n    return ((FL2POOL_ctx*)ctx)->numThreadsBusy;\n}\n\n#endif  /* FL2_SINGLETHREAD */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_pool.h",
    "content": "﻿/*\n* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n* All rights reserved.\n* Modified for FL2 by Conor McCarthy\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#ifndef FL2POOL_H\n#define FL2POOL_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n#include <stddef.h>   /* size_t */\n\ntypedef struct FL2POOL_ctx_s FL2POOL_ctx;\n\n/*! FL2POOL_create() :\n*  Create a thread pool with at most `numThreads` threads.\n* `numThreads` must be at least 1.\n* @return : FL2POOL_ctx pointer on success, else NULL.\n*/\nFL2POOL_ctx *FL2POOL_create(size_t numThreads);\n\n\n/*! FL2POOL_free() :\nFree a thread pool returned by FL2POOL_create().\n*/\nvoid FL2POOL_free(FL2POOL_ctx *ctx);\n\n/*! FL2POOL_sizeof() :\nreturn memory usage of pool returned by FL2POOL_create().\n*/\nsize_t FL2POOL_sizeof(FL2POOL_ctx *ctx);\n\n/*! FL2POOL_function :\nThe function type that can be added to a thread pool.\n*/\ntypedef void(*FL2POOL_function)(void *, ptrdiff_t);\n\n/*! FL2POOL_add() :\nAdd the job `function(opaque)` to the thread pool.\nFL2POOL_addRange adds multiple jobs with size_t parameter from first to less than end.\nPossibly blocks until there is room in the queue.\nNote : The function may be executed asynchronously, so `opaque` must live until the function has been completed.\n*/\nvoid FL2POOL_add(void* ctxVoid, FL2POOL_function function, void *opaque, ptrdiff_t n);\nvoid FL2POOL_addRange(void *ctx, FL2POOL_function function, void *opaque, ptrdiff_t first, ptrdiff_t end);\n\nint FL2POOL_waitAll(void *ctx, unsigned timeout);\n\nsize_t FL2POOL_threadsBusy(void *ctx);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_threading.c",
    "content": "﻿/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n/**\n * This file will hold wrapper for systems, which do not support pthreads\n */\n\n/* create fake symbol to avoid empty translation unit warning */\nint g_ZSTD_threading_useles_symbol;\n\n#include \"fast-lzma2.h\"\n#include \"fl2_threading.h\"\n#include \"util.h\"\n\n#if !defined(FL2_SINGLETHREAD) && defined(_WIN32)\n\n/**\n * Windows minimalist Pthread Wrapper, based on :\n * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html\n */\n\n\n/* ===  Dependencies  === */\n#include <process.h>\n#include <errno.h>\n\n\n/* ===  Implementation  === */\n\nstatic unsigned __stdcall worker(void *arg)\n{\n    FL2_pthread_t* const thread = (FL2_pthread_t*) arg;\n    thread->arg = thread->start_routine(thread->arg);\n    return 0;\n}\n\nint FL2_pthread_create(FL2_pthread_t* thread, const void* unused,\n            void* (*start_routine) (void*), void* arg)\n{\n    (void)unused;\n    thread->arg = arg;\n    thread->start_routine = start_routine;\n    thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);\n\n    if (!thread->handle)\n        return errno;\n    else\n        return 0;\n}\n\nint FL2_pthread_join(FL2_pthread_t thread, void **value_ptr)\n{\n    DWORD result;\n\n    if (!thread.handle) return 0;\n\n    result = WaitForSingleObject(thread.handle, INFINITE);\n    switch (result) {\n    case WAIT_OBJECT_0:\n        if (value_ptr) *value_ptr = thread.arg;\n        return 0;\n    case WAIT_ABANDONED:\n        return EINVAL;\n    default:\n        return GetLastError();\n    }\n}\n\n#endif   /* FL2_SINGLETHREAD */\n\nunsigned FL2_checkNbThreads(unsigned nbThreads)\n{\n#ifndef FL2_SINGLETHREAD\n    if (nbThreads == 0) {\n        nbThreads = UTIL_countPhysicalCores();\n        nbThreads += !nbThreads;\n    }\n    if (nbThreads > FL2_MAXTHREADS) {\n        nbThreads = FL2_MAXTHREADS;\n    }\n#else\n    nbThreads = 1;\n#endif\n    return nbThreads;\n}\n\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/fl2_threading.h",
    "content": "﻿/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#ifndef THREADING_H_938743\n#define THREADING_H_938743\n\n#include \"mem.h\"\n\n#ifndef FL2_XZ_BUILD\n#  ifdef _WIN32\n#    define MYTHREAD_VISTA\n#  else\n#    define MYTHREAD_POSIX  /* posix assumed ; need a better detection method */\n#  endif\n#elif defined(HAVE_CONFIG_H)\n#  include <config.h>\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nunsigned FL2_checkNbThreads(unsigned nbThreads);\n\n\n#if !defined(FL2_SINGLETHREAD) && defined(MYTHREAD_VISTA)\n\n/**\n * Windows minimalist Pthread Wrapper, based on :\n * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html\n */\n#ifdef WINVER\n#  undef WINVER\n#endif\n#define WINVER       0x0600\n\n#ifdef _WIN32_WINNT\n#  undef _WIN32_WINNT\n#endif\n#define _WIN32_WINNT 0x0600\n\n#ifndef WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n#endif\n\n#include <windows.h>\n#include <synchapi.h>\n\n\n/* mutex */\n#define FL2_pthread_mutex_t           CRITICAL_SECTION\n#define FL2_pthread_mutex_init(a, b)  (InitializeCriticalSection((a)), 0)\n#define FL2_pthread_mutex_destroy(a)  DeleteCriticalSection((a))\n#define FL2_pthread_mutex_lock(a)     EnterCriticalSection((a))\n#define FL2_pthread_mutex_unlock(a)   LeaveCriticalSection((a))\n\n/* condition variable */\n#define FL2_pthread_cond_t                     CONDITION_VARIABLE\n#define FL2_pthread_cond_init(a, b)            (InitializeConditionVariable((a)), 0)\n#define FL2_pthread_cond_destroy(a)            /* No delete */\n#define FL2_pthread_cond_wait(a, b)            SleepConditionVariableCS((a), (b), INFINITE)\n#define FL2_pthread_cond_timedwait(a, b, c)    SleepConditionVariableCS((a), (b), (c))\n#define FL2_pthread_cond_signal(a)             WakeConditionVariable((a))\n#define FL2_pthread_cond_broadcast(a)          WakeAllConditionVariable((a))\n\n/* FL2_pthread_create() and FL2_pthread_join() */\ntypedef struct {\n    HANDLE handle;\n    void* (*start_routine)(void*);\n    void* arg;\n} FL2_pthread_t;\n\nint FL2_pthread_create(FL2_pthread_t* thread, const void* unused,\n                   void* (*start_routine) (void*), void* arg);\n\nint FL2_pthread_join(FL2_pthread_t thread, void** value_ptr);\n\n/**\n * add here more wrappers as required\n */\n\n\n#elif !defined(FL2_SINGLETHREAD) && defined(MYTHREAD_POSIX)\n/* ===   POSIX Systems   === */\n#  include <sys/time.h>\n#  include <pthread.h>\n\n#define FL2_pthread_mutex_t            pthread_mutex_t\n#define FL2_pthread_mutex_init(a, b)   pthread_mutex_init((a), (b))\n#define FL2_pthread_mutex_destroy(a)   pthread_mutex_destroy((a))\n#define FL2_pthread_mutex_lock(a)      pthread_mutex_lock((a))\n#define FL2_pthread_mutex_unlock(a)    pthread_mutex_unlock((a))\n\n#define FL2_pthread_cond_t             pthread_cond_t\n#define FL2_pthread_cond_init(a, b)    pthread_cond_init((a), (b))\n#define FL2_pthread_cond_destroy(a)    pthread_cond_destroy((a))\n#define FL2_pthread_cond_wait(a, b)    pthread_cond_wait((a), (b))\n#define FL2_pthread_cond_signal(a)     pthread_cond_signal((a))\n#define FL2_pthread_cond_broadcast(a)  pthread_cond_broadcast((a))\n\n#define FL2_pthread_t                  pthread_t\n#define FL2_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))\n#define FL2_pthread_join(a, b)         pthread_join((a),(b))\n\n/* Timed wait functions from XZ by Lasse Collin\n*/\n\n/* Sets condtime to the absolute time that is timeout_ms milliseconds\n * in the future.\n */\nstatic inline void\nmythread_condtime_set(struct timespec *condtime, U32 timeout_ms)\n{\n\tcondtime->tv_sec = timeout_ms / 1000;\n\tcondtime->tv_nsec = (timeout_ms % 1000) * 1000000;\n\n\tstruct timeval now;\n\tgettimeofday(&now, NULL);\n\n\tcondtime->tv_sec += now.tv_sec;\n\tcondtime->tv_nsec += now.tv_usec * 1000L;\n\n\t/* tv_nsec must stay in the range [0, 999_999_999]. */\n\tif (condtime->tv_nsec >= 1000000000L) {\n\t\tcondtime->tv_nsec -= 1000000000L;\n\t\t++condtime->tv_sec;\n\t}\n}\n\n/* Waits on a condition or until a timeout expires. If the timeout expires,\n * non-zero is returned, otherwise zero is returned.\n */\nstatic inline void\nFL2_pthread_cond_timedwait(FL2_pthread_cond_t *cond, FL2_pthread_mutex_t *mutex,\n    U32 timeout_ms)\n{\n    struct timespec condtime;\n    mythread_condtime_set(&condtime, timeout_ms);\n\tpthread_cond_timedwait(cond, mutex, &condtime);\n}\n\n\n#elif defined(FL2_SINGLETHREAD)\n/* No multithreading support */\n\ntypedef int FL2_pthread_mutex_t;\n#define FL2_pthread_mutex_init(a, b)   ((void)a, 0)\n#define FL2_pthread_mutex_destroy(a)\n#define FL2_pthread_mutex_lock(a)\n#define FL2_pthread_mutex_unlock(a)\n\ntypedef int FL2_pthread_cond_t;\n#define FL2_pthread_cond_init(a, b)    ((void)a, 0)\n#define FL2_pthread_cond_destroy(a)\n#define FL2_pthread_cond_wait(a, b)\n#define FL2_pthread_cond_signal(a)\n#define FL2_pthread_cond_broadcast(a)\n\n/* do not use FL2_pthread_t */\n\n#else\n#  error FL2_SINGLETHREAD not defined but no threading support found\n#endif /* FL2_SINGLETHREAD */\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* THREADING_H_938743 */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/lzma2_enc.c",
    "content": "﻿/* lzma2_enc.c -- LZMA2 Encoder\nBased on LzmaEnc.c and Lzma2Enc.c : Igor Pavlov\nModified for FL2 by Conor McCarthy\nPublic domain\n*/\n\n#include <stdlib.h>\n#include <math.h>\n\n#include \"fl2_errors.h\"\n#include \"fl2_internal.h\"\n#include \"lzma2_enc.h\"\n#include \"fl2_compress_internal.h\"\n#include \"mem.h\"\n#include \"count.h\"\n#include \"radix_mf.h\"\n#include \"range_enc.h\"\n\n#ifdef FL2_XZ_BUILD\n#  include \"tuklib_integer.h\"\n#  define MEM_readLE32(a) unaligned_read32le(a)\n\n#  ifdef TUKLIB_FAST_UNALIGNED_ACCESS\n#    define MEM_read16(a) (*(const U16*)(a))\n#  endif\n\n#endif\n\n#define kNumReps 4U\n#define kNumStates 12U\n\n#define kNumLiterals 0x100U\n#define kNumLitTables 3U\n\n#define kNumLenToPosStates 4U\n#define kNumPosSlotBits 6U\n#define kDicLogSizeMin 18U\n#define kDicLogSizeMax 31U\n#define kDistTableSizeMax (kDicLogSizeMax * 2U)\n\n#define kNumAlignBits 4U\n#define kAlignTableSize (1U << kNumAlignBits)\n#define kAlignMask (kAlignTableSize - 1U)\n#define kMatchRepriceFrequency 64U\n#define kRepLenRepriceFrequency 64U\n\n#define kStartPosModelIndex 4U\n#define kEndPosModelIndex 14U\n#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)\n\n#define kNumFullDistancesBits (kEndPosModelIndex >> 1U)\n#define kNumFullDistances (1U << kNumFullDistancesBits)\n\n#define kNumPositionBitsMax 4U\n#define kNumPositionStatesMax (1U << kNumPositionBitsMax)\n#define kNumLiteralContextBitsMax 4U\n#define kNumLiteralPosBitsMax 4U\n#define kLcLpMax 4U\n\n\n#define kLenNumLowBits 3U\n#define kLenNumLowSymbols (1U << kLenNumLowBits)\n#define kLenNumHighBits 8U\n#define kLenNumHighSymbols (1U << kLenNumHighBits)\n\n#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)\n\n#define kMatchLenMin 2U\n#define kMatchLenMax (kMatchLenMin + kLenNumSymbolsTotal - 1U)\n\n#define kMatchesMax 65U /* Doesn't need to be larger than FL2_HYBRIDCYCLES_MAX + 1 */\n\n#define kOptimizerEndSize 32U\n#define kOptimizerBufferSize (kMatchLenMax * 2U + kOptimizerEndSize)\n#define kOptimizerSkipSize 16U\n#define kInfinityPrice (1UL << 30U)\n#define kNullDist (U32)-1\n\n#define kMaxMatchEncodeSize 20\n\n#define kMaxChunkCompressedSize (1UL << 16U)\n/* Need to leave sufficient space for expanded output from a full opt buffer with bad starting probs */\n#define kChunkSize (kMaxChunkCompressedSize - 2048U)\n#define kSqrtChunkSize 252U\n\n/* Hard to define where the match table read pos definitely catches up with the output size, but\n * 64 bytes of input expanding beyond 256 bytes right after an encoder reset is most likely impossible.\n * The encoder will error out if this happens. */\n#define kTempMinOutput 256U\n#define kTempBufferSize (kTempMinOutput + kOptimizerBufferSize + kOptimizerBufferSize / 4U)\n\n#define kMaxChunkUncompressedSize (1UL << 21U)\n\n#define kChunkHeaderSize 5U\n#define kChunkResetShift 5U\n#define kChunkUncompressedDictReset 1U\n#define kChunkUncompressed 2U\n#define kChunkCompressedFlag 0x80U\n#define kChunkNothingReset 0U\n#define kChunkStateReset (1U << kChunkResetShift)\n#define kChunkStatePropertiesReset (2U << kChunkResetShift)\n#define kChunkAllReset (3U << kChunkResetShift)\n\n#define kMaxHashDictBits 14U\n#define kHash3Bits 14U\n#define kNullLink -1\n\n#define kMinTestChunkSize 0x4000U\n#define kRandomFilterMarginBits 8U\n\n#define kState_LitAfterMatch 4\n#define kState_LitAfterRep   5\n#define kState_MatchAfterLit 7\n#define kState_RepAfterLit   8\n\nstatic const BYTE kLiteralNextStates[kNumStates] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };\n#define LIT_NEXT_STATE(s) kLiteralNextStates[s]\nstatic const BYTE kMatchNextStates[kNumStates] = { 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 };\n#define MATCH_NEXT_STATE(s) kMatchNextStates[s]\nstatic const BYTE kRepNextStates[kNumStates] = { 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11 };\n#define REP_NEXT_STATE(s) kRepNextStates[s]\nstatic const BYTE kShortRepNextStates[kNumStates] = { 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11 };\n#define SHORT_REP_NEXT_STATE(s) kShortRepNextStates[s]\n\n#include \"fastpos_table.h\"\n#include \"radix_get.h\"\n\n/* Probabilities and prices for encoding match lengths.\n * Two objects of this type are needed, one for normal matches\n * and another for rep matches.\n */\ntypedef struct\n{\n    size_t table_size;\n    unsigned prices[kNumPositionStatesMax][kLenNumSymbolsTotal];\n    LZMA2_prob choice; /* low[0] is choice_2. Must be consecutive for speed */\n    LZMA2_prob low[kNumPositionStatesMax << (kLenNumLowBits + 1)];\n    LZMA2_prob high[kLenNumHighSymbols];\n} LZMA2_lenStates;\n\n/* All probabilities for the encoder. This is a separate from the encoder object\n * so the state can be saved and restored in case a chunk is not compressible.\n */\ntypedef struct\n{\n    /* Fields are ordered for speed */\n    LZMA2_lenStates rep_len_states;\n    LZMA2_prob is_rep0_long[kNumStates][kNumPositionStatesMax];\n\n    size_t state;\n    U32 reps[kNumReps];\n\n    LZMA2_prob is_match[kNumStates][kNumPositionStatesMax];\n    LZMA2_prob is_rep[kNumStates];\n    LZMA2_prob is_rep_G0[kNumStates];\n    LZMA2_prob is_rep_G1[kNumStates];\n    LZMA2_prob is_rep_G2[kNumStates];\n\n    LZMA2_lenStates len_states;\n\n    LZMA2_prob dist_slot_encoders[kNumLenToPosStates][1 << kNumPosSlotBits];\n    LZMA2_prob dist_align_encoders[1 << kNumAlignBits];\n    LZMA2_prob dist_encoders[kNumFullDistances - kEndPosModelIndex];\n\n    LZMA2_prob literal_probs[(kNumLiterals * kNumLitTables) << kLcLpMax];\n} LZMA2_encStates;\n\n/*\n * Linked list item for optimal parsing\n */\ntypedef struct\n{\n    size_t state;\n    U32 price;\n    unsigned extra; /*  0   : normal\n                     *  1   : LIT : MATCH\n                     *  > 1 : MATCH (extra-1) : LIT : REP0 (len) */\n    unsigned len;\n    U32 dist;\n    U32 reps[kNumReps];\n} LZMA2_node;\n\n#define MARK_LITERAL(node) (node).dist = kNullDist; (node).extra = 0;\n#define MARK_SHORT_REP(node) (node).dist = 0; (node).extra = 0;\n\n/*\n * Table and chain for 3-byte hash. Extra elements in hash_chain_3 are malloced.\n */\ntypedef struct {\n    S32 table_3[1 << kHash3Bits];\n    S32 hash_chain_3[1];\n} LZMA2_hc3;\n\n/*\n * LZMA2 encoder.\n */\nstruct LZMA2_ECtx_s\n{\n    unsigned lc;\n    unsigned lp;\n    unsigned pb;\n    unsigned fast_length;\n    size_t len_end_max;\n    size_t lit_pos_mask;\n    size_t pos_mask;\n    unsigned match_cycles;\n    FL2_strategy strategy;\n\n    RC_encoder rc;\n    /* Finish writing the chunk at this size */\n    size_t chunk_size;\n    /* Don't encode a symbol beyond this limit (used by fast mode) */\n    size_t chunk_limit;\n\n    LZMA2_encStates states;\n\n    unsigned match_price_count;\n    unsigned rep_len_price_count;\n    size_t dist_price_table_size;\n    unsigned align_prices[kAlignTableSize];\n    unsigned dist_slot_prices[kNumLenToPosStates][kDistTableSizeMax];\n    unsigned distance_prices[kNumLenToPosStates][kNumFullDistances];\n\n    /* All access must be via MATCH_TBL_INDEX() to allow access to index (-1) in LZMA_optimalParse */\n    RMF_match matches[kMatchesMax + 1];\n    size_t match_count;\n\n    LZMA2_node opt_buf[kOptimizerBufferSize];\n\n    LZMA2_hc3* hash_buf;\n    ptrdiff_t chain_mask_2;\n    ptrdiff_t chain_mask_3;\n    ptrdiff_t hash_dict_3;\n    ptrdiff_t hash_prev_index;\n    ptrdiff_t hash_alloc_3;\n\n    /* Temp output buffer before space frees up in the match table */\n    BYTE out_buf[kTempBufferSize];\n};\n\nLZMA2_ECtx* LZMA2_createECtx(void)\n{\n    LZMA2_ECtx *const enc = malloc(sizeof(LZMA2_ECtx));\n    DEBUGLOG(3, \"LZMA2_createECtx\");\n    if (enc == NULL)\n        return NULL;\n\n    enc->lc = 3;\n    enc->lp = 0;\n    enc->pb = 2;\n    enc->fast_length = 48;\n    enc->len_end_max = kOptimizerBufferSize - 1;\n    enc->lit_pos_mask = (1 << enc->lp) - 1;\n    enc->pos_mask = (1 << enc->pb) - 1;\n    enc->match_cycles = 1;\n    enc->strategy = FL2_ultra;\n    enc->match_price_count = 0;\n    enc->rep_len_price_count = 0;\n    enc->dist_price_table_size = kDistTableSizeMax;\n    enc->hash_buf = NULL;\n    enc->hash_dict_3 = 0;\n    enc->chain_mask_3 = 0;\n    enc->hash_alloc_3 = 0;\n    return enc;\n}\n\nvoid LZMA2_freeECtx(LZMA2_ECtx *const enc)\n{\n    if (enc == NULL)\n        return;\n    free(enc->hash_buf);\n    free(enc);\n}\n\n#define LITERAL_PROBS(enc, pos, prev_symbol) (enc->states.literal_probs + ((((pos) & enc->lit_pos_mask) << enc->lc) + ((prev_symbol) >> (8 - enc->lc))) * kNumLiterals * kNumLitTables)\n\n#define LEN_TO_DIST_STATE(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)\n\n#define IS_LIT_STATE(state) ((state) < 7)\n\n#define MATCH_TBL_INDEX(index) ((index) + 1)\n\nHINT_INLINE\nunsigned LZMA_getRepLen1Price(LZMA2_ECtx* const enc, size_t const state, size_t const pos_state)\n{\n    unsigned const rep_G0_prob = enc->states.is_rep_G0[state];\n    unsigned const rep0_long_prob = enc->states.is_rep0_long[state][pos_state];\n    return GET_PRICE_0(rep_G0_prob) + GET_PRICE_0(rep0_long_prob);\n}\n\nstatic unsigned LZMA_getRepPrice(LZMA2_ECtx* const enc, size_t const rep_index, size_t const state, size_t const pos_state)\n{\n    unsigned price;\n    unsigned const rep_G0_prob = enc->states.is_rep_G0[state];\n    if (rep_index == 0) {\n        unsigned const rep0_long_prob = enc->states.is_rep0_long[state][pos_state];\n        price = GET_PRICE_0(rep_G0_prob);\n        price += GET_PRICE_1(rep0_long_prob);\n    }\n    else {\n        unsigned const rep_G1_prob = enc->states.is_rep_G1[state];\n        price = GET_PRICE_1(rep_G0_prob);\n        if (rep_index == 1) {\n            price += GET_PRICE_0(rep_G1_prob);\n        }\n        else {\n            unsigned const rep_G2_prob = enc->states.is_rep_G2[state];\n            price += GET_PRICE_1(rep_G1_prob);\n            price += GET_PRICE(rep_G2_prob, rep_index - 2);\n        }\n    }\n    return price;\n}\n\nstatic unsigned LZMA_getRepMatch0Price(LZMA2_ECtx *const enc, size_t const len, size_t const state, size_t const pos_state)\n{\n    unsigned const rep_G0_prob = enc->states.is_rep_G0[state];\n    unsigned const rep0_long_prob = enc->states.is_rep0_long[state][pos_state];\n    return enc->states.rep_len_states.prices[pos_state][len - kMatchLenMin]\n        + GET_PRICE_0(rep_G0_prob)\n        + GET_PRICE_1(rep0_long_prob);\n}\n\nstatic unsigned LZMA_getLiteralPriceMatched(const LZMA2_prob *const prob_table, U32 symbol, unsigned match_byte)\n{\n    unsigned price = 0;\n    unsigned offs = 0x100;\n    symbol |= 0x100;\n    do {\n        match_byte <<= 1;\n        price += GET_PRICE(prob_table[offs + (match_byte & offs) + (symbol >> 8)], (symbol >> 7) & 1);\n        symbol <<= 1;\n        offs &= ~(match_byte ^ symbol);\n    } while (symbol < 0x10000);\n    return price;\n}\n\nHINT_INLINE\nvoid LZMA_encodeLiteral(LZMA2_ECtx *const enc, size_t const pos, U32 symbol, unsigned const prev_symbol)\n{\n    RC_encodeBit0(&enc->rc, &enc->states.is_match[enc->states.state][pos & enc->pos_mask]);\n    enc->states.state = LIT_NEXT_STATE(enc->states.state);\n\n    LZMA2_prob* const prob_table = LITERAL_PROBS(enc, pos, prev_symbol);\n    symbol |= 0x100;\n    do {\n        RC_encodeBit(&enc->rc, prob_table + (symbol >> 8), symbol & (1 << 7));\n        symbol <<= 1;\n    } while (symbol < 0x10000);\n}\n\nHINT_INLINE\nvoid LZMA_encodeLiteralMatched(LZMA2_ECtx *const enc, const BYTE* const data_block, size_t const pos, U32 symbol)\n{\n    RC_encodeBit0(&enc->rc, &enc->states.is_match[enc->states.state][pos & enc->pos_mask]);\n    enc->states.state = LIT_NEXT_STATE(enc->states.state);\n\n    unsigned match_symbol = data_block[pos - enc->states.reps[0] - 1];\n    LZMA2_prob* const prob_table = LITERAL_PROBS(enc, pos, data_block[pos - 1]);\n    unsigned offset = 0x100;\n    symbol |= 0x100;\n    do {\n        match_symbol <<= 1;\n        size_t prob_index = offset + (match_symbol & offset) + (symbol >> 8);\n        RC_encodeBit(&enc->rc, prob_table + prob_index, symbol & (1 << 7));\n        symbol <<= 1;\n        offset &= ~(match_symbol ^ symbol);\n    } while (symbol < 0x10000);\n}\n\nHINT_INLINE\nvoid LZMA_encodeLiteralBuf(LZMA2_ECtx *const enc, const BYTE* const data_block, size_t const pos)\n{\n    U32 const symbol = data_block[pos];\n    if (IS_LIT_STATE(enc->states.state)) {\n        unsigned const prev_symbol = data_block[pos - 1];\n        LZMA_encodeLiteral(enc, pos, symbol, prev_symbol);\n    }\n    else {\n        LZMA_encodeLiteralMatched(enc, data_block, pos, symbol);\n    }\n}\n\nstatic void LZMA_lengthStates_SetPrices(const LZMA2_prob *probs, U32 start_price, unsigned *prices)\n{\n    for (size_t i = 0; i < 8; i += 2) {\n        U32 prob = probs[4 + (i >> 1)];\n        U32 price = start_price + GET_PRICE(probs[1], (i >> 2))\n            + GET_PRICE(probs[2 + (i >> 2)], (i >> 1) & 1);\n        prices[i] = price + GET_PRICE_0(prob);\n        prices[i + 1] = price + GET_PRICE_1(prob);\n    }\n}\n\nFORCE_NOINLINE\n// **************** NanaZip Modification Start ****************\n//static void LZMA_lengthStates_updatePrices(LZMA2_ECtx *const enc, LZMA2_lenStates* const ls)\nvoid LZMA_lengthStates_updatePrices(LZMA2_ECtx* const enc, LZMA2_lenStates* const ls)\n// **************** NanaZip Modification End ****************\n{\n    U32 b;\n\n    {\n        unsigned const prob = ls->choice;\n        U32 a, c;\n        b = GET_PRICE_1(prob);\n        a = GET_PRICE_0(prob);\n        c = b + GET_PRICE_0(ls->low[0]);\n        for (size_t pos_state = 0; pos_state <= enc->pos_mask; pos_state++) {\n            unsigned *const prices = ls->prices[pos_state];\n            const LZMA2_prob *const probs = ls->low + (pos_state << (1 + kLenNumLowBits));\n            LZMA_lengthStates_SetPrices(probs, a, prices);\n            LZMA_lengthStates_SetPrices(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols);\n        }\n    }\n\n    size_t i = ls->table_size;\n\n    if (i > kLenNumLowSymbols * 2) {\n        const LZMA2_prob *const probs = ls->high;\n        unsigned *const prices = ls->prices[0] + kLenNumLowSymbols * 2;\n        i = (i - (kLenNumLowSymbols * 2 - 1)) >> 1;\n        b += GET_PRICE_1(ls->low[0]);\n        do {\n            --i;\n            size_t sym = i + (1 << (kLenNumHighBits - 1));\n            U32 price = b;\n            do {\n                size_t bit = sym & 1;\n                sym >>= 1;\n                price += GET_PRICE(probs[sym], bit);\n            } while (sym >= 2);\n\n            unsigned const prob = probs[i + (1 << (kLenNumHighBits - 1))];\n            prices[i * 2] = price + GET_PRICE_0(prob);\n            prices[i * 2 + 1] = price + GET_PRICE_1(prob);\n        } while (i);\n\n        size_t const size = (ls->table_size - kLenNumLowSymbols * 2) * sizeof(ls->prices[0][0]);\n        for (size_t pos_state = 1; pos_state <= enc->pos_mask; pos_state++)\n            memcpy(ls->prices[pos_state] + kLenNumLowSymbols * 2, ls->prices[0] + kLenNumLowSymbols * 2, size);\n    }\n}\n\n/* Rare enough that not inlining is faster overall */\nFORCE_NOINLINE\n// **************** NanaZip Modification Start ****************\n//static void LZMA_encodeLength_MidHigh(LZMA2_ECtx *const enc, LZMA2_lenStates* const len_prob_table, unsigned const len, size_t const pos_state)\nvoid LZMA_encodeLength_MidHigh(LZMA2_ECtx* const enc, LZMA2_lenStates* const len_prob_table, unsigned const len, size_t const pos_state)\n// **************** NanaZip Modification End ****************\n{\n    RC_encodeBit1(&enc->rc, &len_prob_table->choice);\n    if (len < kLenNumLowSymbols * 2) {\n        RC_encodeBit0(&enc->rc, &len_prob_table->low[0]);\n        RC_encodeBitTree(&enc->rc, len_prob_table->low + kLenNumLowSymbols + (pos_state << (1 + kLenNumLowBits)), kLenNumLowBits, len - kLenNumLowSymbols);\n    }\n    else {\n        RC_encodeBit1(&enc->rc, &len_prob_table->low[0]);\n        RC_encodeBitTree(&enc->rc, len_prob_table->high, kLenNumHighBits, len - kLenNumLowSymbols * 2);\n    }\n}\n\nHINT_INLINE\nvoid LZMA_encodeLength(LZMA2_ECtx *const enc, LZMA2_lenStates* const len_prob_table, unsigned len, size_t const pos_state)\n{\n    len -= kMatchLenMin;\n    if (len < kLenNumLowSymbols) {\n        RC_encodeBit0(&enc->rc, &len_prob_table->choice);\n        RC_encodeBitTree(&enc->rc, len_prob_table->low + (pos_state << (1 + kLenNumLowBits)), kLenNumLowBits, len);\n    }\n    else {\n        LZMA_encodeLength_MidHigh(enc, len_prob_table, len, pos_state);\n    }\n}\n\nFORCE_NOINLINE\n// **************** NanaZip Modification Start ****************\n//static void LZMA_encodeRepMatchShort(LZMA2_ECtx *const enc, size_t const pos_state)\nvoid LZMA_encodeRepMatchShort(LZMA2_ECtx* const enc, size_t const pos_state)\n// **************** NanaZip Modification End ****************\n{\n    DEBUGLOG(7, \"LZMA_encodeRepMatchShort\");\n    RC_encodeBit1(&enc->rc, &enc->states.is_match[enc->states.state][pos_state]);\n    RC_encodeBit1(&enc->rc, &enc->states.is_rep[enc->states.state]);\n    RC_encodeBit0(&enc->rc, &enc->states.is_rep_G0[enc->states.state]);\n    RC_encodeBit0(&enc->rc, &enc->states.is_rep0_long[enc->states.state][pos_state]);\n    enc->states.state = SHORT_REP_NEXT_STATE(enc->states.state);\n}\n\nFORCE_NOINLINE\n// **************** NanaZip Modification Start ****************\n//static void LZMA_encodeRepMatchLong(LZMA2_ECtx *const enc, unsigned const len, unsigned const rep, size_t const pos_state)\nvoid LZMA_encodeRepMatchLong(LZMA2_ECtx* const enc, unsigned const len, unsigned const rep, size_t const pos_state)\n// **************** NanaZip Modification End ****************\n{\n    DEBUGLOG(7, \"LZMA_encodeRepMatchLong : length %u, rep %u\", len, rep);\n    RC_encodeBit1(&enc->rc, &enc->states.is_match[enc->states.state][pos_state]);\n    RC_encodeBit1(&enc->rc, &enc->states.is_rep[enc->states.state]);\n    if (rep == 0) {\n        RC_encodeBit0(&enc->rc, &enc->states.is_rep_G0[enc->states.state]);\n        RC_encodeBit1(&enc->rc, &enc->states.is_rep0_long[enc->states.state][pos_state]);\n    }\n    else {\n        U32 const distance = enc->states.reps[rep];\n        RC_encodeBit1(&enc->rc, &enc->states.is_rep_G0[enc->states.state]);\n        if (rep == 1) {\n            RC_encodeBit0(&enc->rc, &enc->states.is_rep_G1[enc->states.state]);\n        }\n        else {\n            RC_encodeBit1(&enc->rc, &enc->states.is_rep_G1[enc->states.state]);\n            RC_encodeBit(&enc->rc, &enc->states.is_rep_G2[enc->states.state], rep - 2);\n            if (rep == 3)\n                enc->states.reps[3] = enc->states.reps[2];\n            enc->states.reps[2] = enc->states.reps[1];\n        }\n        enc->states.reps[1] = enc->states.reps[0];\n        enc->states.reps[0] = distance;\n    }\n    LZMA_encodeLength(enc, &enc->states.rep_len_states, len, pos_state);\n    enc->states.state = REP_NEXT_STATE(enc->states.state);\n    ++enc->rep_len_price_count;\n}\n\n\n/*\n * Distance slot functions based on fastpos.h from XZ\n */\n\nHINT_INLINE\nunsigned LZMA_fastDistShift(unsigned const n)\n{\n    return n * (kFastDistBits - 1);\n}\n\nHINT_INLINE\nunsigned LZMA_fastDistResult(U32 const dist, unsigned const n)\n{\n    return distance_table[dist >> LZMA_fastDistShift(n)]\n        + 2 * LZMA_fastDistShift(n);\n}\n\nstatic size_t LZMA_getDistSlot(U32 const distance)\n{\n    U32 limit = 1UL << kFastDistBits;\n    /* If it is small enough, we can pick the result directly from */\n    /* the precalculated table. */\n    if (distance < limit) {\n        return distance_table[distance];\n    }\n    limit <<= LZMA_fastDistShift(1);\n    if (distance < limit) {\n        return LZMA_fastDistResult(distance, 1);\n    }\n    return LZMA_fastDistResult(distance, 2);\n}\n\n/* * */\n\n\nHINT_INLINE\nvoid LZMA_encodeNormalMatch(LZMA2_ECtx *const enc, unsigned const len, U32 const dist, size_t const pos_state)\n{\n    DEBUGLOG(7, \"LZMA_encodeNormalMatch : length %u, dist %u\", len, dist);\n    RC_encodeBit1(&enc->rc, &enc->states.is_match[enc->states.state][pos_state]);\n    RC_encodeBit0(&enc->rc, &enc->states.is_rep[enc->states.state]);\n    enc->states.state = MATCH_NEXT_STATE(enc->states.state);\n\n    LZMA_encodeLength(enc, &enc->states.len_states, len, pos_state);\n\n    size_t const dist_slot = LZMA_getDistSlot(dist);\n    RC_encodeBitTree(&enc->rc, enc->states.dist_slot_encoders[LEN_TO_DIST_STATE(len)], kNumPosSlotBits, (unsigned)dist_slot);\n    if (dist_slot >= kStartPosModelIndex) {\n        unsigned const footer_bits = ((unsigned)(dist_slot >> 1) - 1);\n        size_t const base = ((2 | (dist_slot & 1)) << footer_bits);\n        unsigned const dist_reduced = (unsigned)(dist - base);\n        if (dist_slot < kEndPosModelIndex) {\n            RC_encodeBitTreeReverse(&enc->rc, enc->states.dist_encoders + base - dist_slot - 1, footer_bits, dist_reduced);\n        }\n        else {\n            RC_encodeDirect(&enc->rc, dist_reduced >> kNumAlignBits, footer_bits - kNumAlignBits);\n            RC_encodeBitTreeReverse(&enc->rc, enc->states.dist_align_encoders, kNumAlignBits, dist_reduced & kAlignMask);\n        }\n    }\n    enc->states.reps[3] = enc->states.reps[2];\n    enc->states.reps[2] = enc->states.reps[1];\n    enc->states.reps[1] = enc->states.reps[0];\n    enc->states.reps[0] = dist;\n\n    ++enc->match_price_count;\n}\n\nFORCE_INLINE_TEMPLATE\nsize_t LZMA_encodeChunkFast(LZMA2_ECtx *const enc,\n    FL2_dataBlock const block,\n    FL2_matchTable* const tbl,\n    int const struct_tbl,\n    size_t pos,\n    size_t const uncompressed_end)\n{\n    size_t const pos_mask = enc->pos_mask;\n    size_t prev = pos;\n    unsigned const search_depth = tbl->params.depth;\n\n    while (pos < uncompressed_end && enc->rc.out_index < enc->chunk_size) {\n        size_t max_len;\n        const BYTE* data;\n        /* Table of distance restrictions for short matches */\n        static const U32 max_dist_table[] = { 0, 0, 0, 1 << 6, 1 << 14 };\n        /* Get a match from the table, extended to its full length */\n        RMF_match best_match = RMF_getMatch(block, tbl, search_depth, struct_tbl, pos);\n        if (best_match.length < kMatchLenMin) {\n            ++pos;\n            continue;\n        }\n        /* Use if near enough */\n        if (best_match.length >= 5 || best_match.dist < max_dist_table[best_match.length])\n            best_match.dist += kNumReps;\n        else\n            best_match.length = 0;\n\n        max_len = MIN(kMatchLenMax, block.end - pos);\n        data = block.data + pos;\n\n        RMF_match best_rep = { 0, 0 };\n        RMF_match rep_match;\n        /* Search all of the rep distances */\n        for (rep_match.dist = 0; rep_match.dist < kNumReps; ++rep_match.dist) {\n            const BYTE *data_2 = data - enc->states.reps[rep_match.dist] - 1;\n            if (MEM_read16(data) != MEM_read16(data_2))\n                continue;\n\n            rep_match.length = (U32)(ZSTD_count(data + 2, data_2 + 2, data + max_len) + 2);\n            if (rep_match.length >= max_len) {\n                best_match = rep_match;\n                goto _encode;\n            }\n            if (rep_match.length > best_rep.length)\n                best_rep = rep_match;\n        }\n        /* Encode if it is kMatchLenMax or completes the block */\n        if (best_match.length >= max_len)\n            goto _encode;\n\n        if (best_rep.length >= 2) {\n            if (best_rep.length > best_match.length) {\n                best_match = best_rep;\n            }\n            else {\n                /* Modified ZSTD scheme for estimating cost */\n                int const gain2 = (int)(best_rep.length * 3 - best_rep.dist);\n                int const gain1 = (int)(best_match.length * 3 - ZSTD_highbit32(best_match.dist + 1) + 1);\n                if (gain2 > gain1) {\n                    DEBUGLOG(7, \"Replace match (%u, %u) with rep (%u, %u)\", best_match.length, best_match.dist, best_rep.length, best_rep.dist);\n                    best_match = best_rep;\n                }\n            }\n        }\n\n        if (best_match.length < kMatchLenMin) {\n            ++pos;\n            continue;\n        }\n\n        for (size_t next = pos + 1; best_match.length < kMatchLenMax && next < uncompressed_end; ++next) {\n            /* lazy matching scheme from ZSTD */\n            RMF_match next_match = RMF_getNextMatch(block, tbl, search_depth, struct_tbl, next);\n            if (next_match.length >= kMatchLenMin) {\n                best_rep.length = 0;\n                data = block.data + next;\n                max_len = MIN(kMatchLenMax, block.end - next);\n                for (rep_match.dist = 0; rep_match.dist < kNumReps; ++rep_match.dist) {\n                    const BYTE *data_2 = data - enc->states.reps[rep_match.dist] - 1;\n                    if (MEM_read16(data) != MEM_read16(data_2))\n                        continue;\n\n                    rep_match.length = (U32)(ZSTD_count(data + 2, data_2 + 2, data + max_len) + 2);\n                    if (rep_match.length > best_rep.length)\n                        best_rep = rep_match;\n                }\n                if (best_rep.length >= 3) {\n                    int const gain2 = (int)(best_rep.length * 3 - best_rep.dist);\n                    int const gain1 = (int)(best_match.length * 3 - ZSTD_highbit32((U32)best_match.dist + 1) + 1);\n                    if (gain2 > gain1) {\n                        DEBUGLOG(7, \"Replace match (%u, %u) with rep (%u, %u)\", best_match.length, best_match.dist, best_rep.length, best_rep.dist);\n                        best_match = best_rep;\n                        pos = next;\n                    }\n                }\n                if (next_match.length >= 3 && next_match.dist != best_match.dist) {\n                    int const gain2 = (int)(next_match.length * 4 - ZSTD_highbit32((U32)next_match.dist + 1));   /* raw approx */\n                    int const gain1 = (int)(best_match.length * 4 - ZSTD_highbit32((U32)best_match.dist + 1) + 4);\n                    if (gain2 > gain1) {\n                        DEBUGLOG(7, \"Replace match (%u, %u) with match (%u, %u)\", best_match.length, best_match.dist, next_match.length, next_match.dist + kNumReps);\n                        best_match = next_match;\n                        best_match.dist += kNumReps;\n                        pos = next;\n                        continue;\n                    }\n                }\n            }\n            ++next;\n            /* Recheck next < uncompressed_end. uncompressed_end could be block.end so decrementing the max chunk size won't obviate the need. */\n            if (next >= uncompressed_end)\n                break;\n\n            next_match = RMF_getNextMatch(block, tbl, search_depth, struct_tbl, next);\n            if (next_match.length < 4)\n                break;\n\n            data = block.data + next;\n            max_len = MIN(kMatchLenMax, block.end - next);\n            best_rep.length = 0;\n\n            for (rep_match.dist = 0; rep_match.dist < kNumReps; ++rep_match.dist) {\n                const BYTE *data_2 = data - enc->states.reps[rep_match.dist] - 1;\n                if (MEM_read16(data) != MEM_read16(data_2))\n                    continue;\n\n                rep_match.length = (U32)(ZSTD_count(data + 2, data_2 + 2, data + max_len) + 2);\n                if (rep_match.length > best_rep.length)\n                    best_rep = rep_match;\n            }\n            if (best_rep.length >= 4) {\n                int const gain2 = (int)(best_rep.length * 4 - (best_rep.dist >> 1));\n                int const gain1 = (int)(best_match.length * 4 - ZSTD_highbit32((U32)best_match.dist + 1) + 1);\n                if (gain2 > gain1) {\n                    DEBUGLOG(7, \"Replace match (%u, %u) with rep (%u, %u)\", best_match.length, best_match.dist, best_rep.length, best_rep.dist);\n                    best_match = best_rep;\n                    pos = next;\n                }\n            }\n            if (next_match.dist != best_match.dist) {\n                int const gain2 = (int)(next_match.length * 4 - ZSTD_highbit32((U32)next_match.dist + 1));\n                int const gain1 = (int)(best_match.length * 4 - ZSTD_highbit32((U32)best_match.dist + 1) + 7);\n                if (gain2 > gain1) {\n                    DEBUGLOG(7, \"Replace match (%u, %u) with match (%u, %u)\", best_match.length, best_match.dist, next_match.length, next_match.dist + kNumReps);\n                    best_match = next_match;\n                    best_match.dist += kNumReps;\n                    pos = next;\n                    continue;\n                }\n            }\n\n            break;\n        }\n_encode:\n        assert(pos + best_match.length <= block.end);\n\n        while (prev < pos) {\n            if (enc->rc.out_index >= enc->chunk_limit)\n                return prev;\n\n            if (block.data[prev] != block.data[prev - enc->states.reps[0] - 1]) {\n                LZMA_encodeLiteralBuf(enc, block.data, prev);\n                ++prev;\n            }\n            else {\n                LZMA_encodeRepMatchShort(enc, prev & pos_mask);\n                ++prev;\n            }\n        }\n\n        if(best_match.length >= kMatchLenMin) {\n            if (best_match.dist >= kNumReps) {\n                LZMA_encodeNormalMatch(enc, best_match.length, best_match.dist - kNumReps, pos & pos_mask);\n                pos += best_match.length;\n                prev = pos;\n            }\n            else {\n                LZMA_encodeRepMatchLong(enc, best_match.length, best_match.dist, pos & pos_mask);\n                pos += best_match.length;\n                prev = pos;\n            }\n        }\n    }\n    while (prev < pos && enc->rc.out_index < enc->chunk_limit) {\n        if (block.data[prev] != block.data[prev - enc->states.reps[0] - 1])\n            LZMA_encodeLiteralBuf(enc, block.data, prev);\n        else\n            LZMA_encodeRepMatchShort(enc, prev & pos_mask);\n        ++prev;\n    }\n    return prev;\n}\n\n/*\n * Reverse the direction of the linked list generated by the optimal parser\n */\nFORCE_NOINLINE\n// **************** NanaZip Modification Start ****************\n//static void LZMA_reverseOptimalChain(LZMA2_node* const opt_buf, size_t cur)\nvoid LZMA_reverseOptimalChain(LZMA2_node* const opt_buf, size_t cur)\n// **************** NanaZip Modification End ****************\n{\n    unsigned len = (unsigned)opt_buf[cur].len;\n    U32 dist = opt_buf[cur].dist;\n\n    for(;;) {\n        unsigned const extra = (unsigned)opt_buf[cur].extra;\n        cur -= len;\n\n        if (extra) {\n            opt_buf[cur].len = (U32)len;\n            len = extra;\n            if (extra == 1) {\n                opt_buf[cur].dist = dist;\n                dist = kNullDist;\n                --cur;\n            }\n            else {\n                opt_buf[cur].dist = 0;\n                --cur;\n                --len;\n                opt_buf[cur].dist = kNullDist;\n                opt_buf[cur].len = 1;\n                cur -= len;\n            }\n        }\n\n        unsigned const next_len = opt_buf[cur].len;\n        U32 const next_dist = opt_buf[cur].dist;\n\n        opt_buf[cur].dist = dist;\n        opt_buf[cur].len = (U32)len;\n\n        if (cur == 0)\n            break;\n\n        len = next_len;\n        dist = next_dist;\n    }\n}\n\nstatic unsigned LZMA_getLiteralPrice(LZMA2_ECtx *const enc, size_t const pos, size_t const state, unsigned const prev_symbol, U32 symbol, unsigned const match_byte)\n{\n    const LZMA2_prob* const prob_table = LITERAL_PROBS(enc, pos, prev_symbol);\n    if (IS_LIT_STATE(state)) {\n        unsigned price = 0;\n        symbol |= 0x100;\n        do {\n            price += GET_PRICE(prob_table[symbol >> 8], (symbol >> 7) & 1);\n            symbol <<= 1;\n        } while (symbol < 0x10000);\n        return price;\n    }\n    return LZMA_getLiteralPriceMatched(prob_table, symbol, match_byte);\n}\n\n/*\n * Reset the hash object for encoding a new slice of a block\n */\nstatic void LZMA_hashReset(LZMA2_ECtx *const enc, unsigned const dictionary_bits_3)\n{\n    enc->hash_dict_3 = (ptrdiff_t)1 << dictionary_bits_3;\n    enc->chain_mask_3 = enc->hash_dict_3 - 1;\n    memset(enc->hash_buf->table_3, 0xFF, sizeof(enc->hash_buf->table_3));\n}\n\n/*\n * Create hash table and chain with dict size dictionary_bits_3. Frees any existing object.\n */\nstatic int LZMA_hashCreate(LZMA2_ECtx *const enc, unsigned const dictionary_bits_3)\n{\n    DEBUGLOG(3, \"Create hash chain : dict bits %u\", dictionary_bits_3);\n\n    if (enc->hash_buf)\n        free(enc->hash_buf);\n\n    enc->hash_alloc_3 = (ptrdiff_t)1 << dictionary_bits_3;\n    enc->hash_buf = malloc(sizeof(LZMA2_hc3) + (enc->hash_alloc_3 - 1) * sizeof(S32));\n\n    if (enc->hash_buf == NULL)\n        return 1;\n\n    LZMA_hashReset(enc, dictionary_bits_3);\n\n    return 0;\n}\n\n/* Create a hash chain for hybrid mode if options require one.\n * Used for allocating before compression begins. Any existing table will be reused if\n * it is at least as large as required.\n */\nint LZMA2_hashAlloc(LZMA2_ECtx *const enc, const FL2_lzma2Parameters* const options)\n{\n    if (enc->strategy == FL2_ultra && enc->hash_alloc_3 < ((ptrdiff_t)1 << options->second_dict_bits))\n        return LZMA_hashCreate(enc, options->second_dict_bits);\n\n    return 0;\n}\n\n#define GET_HASH_3(data) ((((MEM_readLE32(data)) << 8) * 506832829U) >> (32 - kHash3Bits))\n\n/* Find matches nearer than the match from the RMF. If none is at least as long as\n * the RMF match (most likely), insert that match at the end of the list.\n */\nHINT_INLINE\nsize_t LZMA_hashGetMatches(LZMA2_ECtx *const enc, FL2_dataBlock const block,\n    ptrdiff_t const pos,\n    size_t const length_limit,\n    RMF_match const match)\n{\n    ptrdiff_t const hash_dict_3 = enc->hash_dict_3;\n    const BYTE* data = block.data;\n    LZMA2_hc3* const tbl = enc->hash_buf;\n    ptrdiff_t const chain_mask_3 = enc->chain_mask_3;\n\n    enc->match_count = 0;\n    enc->hash_prev_index = MAX(enc->hash_prev_index, pos - hash_dict_3);\n    /* Update hash tables and chains for any positions that were skipped */\n    while (++enc->hash_prev_index < pos) {\n        size_t hash = GET_HASH_3(data + enc->hash_prev_index);\n        tbl->hash_chain_3[enc->hash_prev_index & chain_mask_3] = tbl->table_3[hash];\n        tbl->table_3[hash] = (S32)enc->hash_prev_index;\n    }\n    data += pos;\n\n    size_t const hash = GET_HASH_3(data);\n    ptrdiff_t const first_3 = tbl->table_3[hash];\n    tbl->table_3[hash] = (S32)pos;\n\n    size_t max_len = 2;\n\n    if (first_3 >= 0) {\n        int cycles = enc->match_cycles;\n        ptrdiff_t const end_index = pos - (((ptrdiff_t)match.dist < hash_dict_3) ? match.dist : hash_dict_3);\n        ptrdiff_t match_3 = first_3;\n        if (match_3 >= end_index) {\n            do {\n                --cycles;\n                const BYTE* data_2 = block.data + match_3;\n                size_t len_test = ZSTD_count(data + 1, data_2 + 1, data + length_limit) + 1;\n                if (len_test > max_len) {\n                    enc->matches[MATCH_TBL_INDEX(enc->match_count)].length = (U32)len_test;\n                    enc->matches[MATCH_TBL_INDEX(enc->match_count)].dist = (U32)(pos - match_3 - 1);\n                    ++enc->match_count;\n                    max_len = len_test;\n                    if (len_test >= length_limit)\n                        break;\n                }\n                if (cycles <= 0)\n                    break;\n                match_3 = tbl->hash_chain_3[match_3 & chain_mask_3];\n            } while (match_3 >= end_index);\n        }\n    }\n    tbl->hash_chain_3[pos & chain_mask_3] = (S32)first_3;\n    if ((unsigned)max_len < match.length) {\n        /* Insert the match from the RMF */\n        enc->matches[MATCH_TBL_INDEX(enc->match_count)] = match;\n        ++enc->match_count;\n        return match.length;\n    }\n    return max_len;\n}\n\n/* The speed of this function is critical. The sections have many variables\n* in common, so breaking it up into shorter functions is not feasible.\n* For each position cur, starting at 1, check some or all possible\n* encoding choices - a literal, 1-byte rep 0 match, all rep match lengths, and\n* all match lengths at available distances. It also checks the combined\n* sequences literal+rep0, rep+lit+rep0 and match+lit+rep0.\n* If is_hybrid != 0, this method works in hybrid mode, using the\n* hash chain to find shorter matches at near distances. */\nFORCE_INLINE_TEMPLATE\nsize_t LZMA_optimalParse(LZMA2_ECtx* const enc, FL2_dataBlock const block,\n    RMF_match match,\n    size_t const pos,\n    size_t const cur,\n    size_t len_end,\n    int const is_hybrid,\n    U32* const reps)\n{\n    LZMA2_node* const cur_opt = &enc->opt_buf[cur];\n    size_t const pos_mask = enc->pos_mask;\n    size_t const pos_state = (pos & pos_mask);\n    const BYTE* const data = block.data + pos;\n    size_t const fast_length = enc->fast_length;\n    size_t prev_index = cur - cur_opt->len;\n    size_t state;\n    size_t bytes_avail;\n    U32 match_price;\n    U32 rep_match_price;\n\n    /* Update the states according to how this location was reached */\n    if (cur_opt->len == 1) {\n        /* Literal or 1-byte rep */\n        const BYTE *next_state = (cur_opt->dist == 0) ? kShortRepNextStates : kLiteralNextStates;\n        state = next_state[enc->opt_buf[prev_index].state];\n    }\n    else {\n        /* Match or rep match */\n        size_t const dist = cur_opt->dist;\n\n        if (cur_opt->extra) {\n            prev_index -= cur_opt->extra;\n            state = kState_RepAfterLit - ((dist >= kNumReps) & (cur_opt->extra == 1));\n        }\n        else {\n            state = enc->opt_buf[prev_index].state;\n            state = MATCH_NEXT_STATE(state) + (dist < kNumReps);\n        }\n        const LZMA2_node *const prev_opt = &enc->opt_buf[prev_index];\n        if (dist < kNumReps) {\n            /* Move the chosen rep to the front.\n             * The table is hideous but faster than branching :D */\n            reps[0] = prev_opt->reps[dist];\n            size_t table = 1 | (2 << 2) | (3 << 4)\n                | (0 << 8) | (2 << 10) | (3 << 12)\n                | (0L << 16) | (1L << 18) | (3L << 20)\n                | (0L << 24) | (1L << 26) | (2L << 28);\n            table >>= (dist << 3);\n            reps[1] = prev_opt->reps[table & 3];\n            table >>= 2;\n            reps[2] = prev_opt->reps[table & 3];\n            table >>= 2;\n            reps[3] = prev_opt->reps[table & 3];\n        }\n        else {\n            reps[0] = (U32)(dist - kNumReps);\n            reps[1] = prev_opt->reps[0];\n            reps[2] = prev_opt->reps[1];\n            reps[3] = prev_opt->reps[2];\n        }\n    }\n    cur_opt->state = state;\n    memcpy(cur_opt->reps, reps, sizeof(cur_opt->reps));\n    LZMA2_prob const is_rep_prob = enc->states.is_rep[state];\n\n    {   LZMA2_node *const next_opt = &enc->opt_buf[cur + 1];\n        U32 const cur_price = cur_opt->price;\n        U32 const next_price = next_opt->price;\n        LZMA2_prob const is_match_prob = enc->states.is_match[state][pos_state];\n        unsigned const cur_byte = *data;\n        unsigned const match_byte = *(data - reps[0] - 1);\n\n        U32 cur_and_lit_price = cur_price + GET_PRICE_0(is_match_prob);\n        /* This is a compromise to try to filter out cases where literal + rep0 is unlikely to be cheaper */\n        BYTE try_lit = cur_and_lit_price + kMinLitPrice / 2U <= next_price;\n        if (try_lit) {\n            /* cur_and_lit_price is used later for the literal + rep0 test */\n            cur_and_lit_price += LZMA_getLiteralPrice(enc, pos, state, data[-1], cur_byte, match_byte);\n            /* Try literal */\n            if (cur_and_lit_price < next_price) {\n                next_opt->price = cur_and_lit_price;\n                next_opt->len = 1;\n                MARK_LITERAL(*next_opt);\n                if (is_hybrid) /* Evaluates as a constant expression due to inlining */\n                    try_lit = 0;\n            }\n        }\n        match_price = cur_price + GET_PRICE_1(is_match_prob);\n        rep_match_price = match_price + GET_PRICE_1(is_rep_prob);\n        if (match_byte == cur_byte) {\n            /* Try 1-byte rep0 */\n            U32 short_rep_price = rep_match_price + LZMA_getRepLen1Price(enc, state, pos_state);\n            if (short_rep_price <= next_opt->price) {\n                next_opt->price = short_rep_price;\n                next_opt->len = 1;\n                MARK_SHORT_REP(*next_opt);\n            }\n        }\n        bytes_avail = MIN(block.end - pos, kOptimizerBufferSize - 1 - cur);\n        if (bytes_avail < 2)\n            return len_end;\n\n        /* If match_byte == cur_byte a rep0 begins at the current position */\n        if (is_hybrid && try_lit && match_byte != cur_byte) {\n            /* Try literal + rep0 */\n            const BYTE *const data_2 = data - reps[0];\n            size_t limit = MIN(bytes_avail - 1, fast_length);\n            size_t len_test_2 = ZSTD_count(data + 1, data_2, data + 1 + limit);\n            if (len_test_2 >= 2) {\n                size_t const state_2 = LIT_NEXT_STATE(state);\n                size_t const pos_state_next = (pos + 1) & pos_mask;\n                U32 const next_rep_match_price = cur_and_lit_price +\n                    GET_PRICE_1(enc->states.is_match[state_2][pos_state_next]) +\n                    GET_PRICE_1(enc->states.is_rep[state_2]);\n                U32 const cur_and_len_price = next_rep_match_price + LZMA_getRepMatch0Price(enc, len_test_2, state_2, pos_state_next);\n                size_t const offset = cur + 1 + len_test_2;\n                if (cur_and_len_price < enc->opt_buf[offset].price) {\n                    len_end = MAX(len_end, offset);\n                    enc->opt_buf[offset].price = cur_and_len_price;\n                    enc->opt_buf[offset].len = (unsigned)len_test_2;\n                    enc->opt_buf[offset].dist = 0;\n                    enc->opt_buf[offset].extra = 1;\n                }\n            }\n        }\n    }\n\n    size_t const max_length = MIN(bytes_avail, fast_length);\n    size_t start_len = 2;\n\n    if (match.length > 0) {\n        size_t len_test;\n        size_t len;\n        U32 cur_rep_price;\n        for (size_t rep_index = 0; rep_index < kNumReps; ++rep_index) {\n            const BYTE *const data_2 = data - reps[rep_index] - 1;\n            if (MEM_read16(data) != MEM_read16(data_2))\n                continue;\n            /* Test is limited to fast_length, but it is rare for the RMF to miss the longest match,\n             * therefore this function is rarely called when a rep len > fast_length exists */\n            len_test = ZSTD_count(data + 2, data_2 + 2, data + max_length) + 2;\n            len_end = MAX(len_end, cur + len_test);\n            cur_rep_price = rep_match_price + LZMA_getRepPrice(enc, rep_index, state, pos_state);\n            len = 2;\n            /* Try rep match */\n            do {\n                U32 const cur_and_len_price = cur_rep_price + enc->states.rep_len_states.prices[pos_state][len - kMatchLenMin];\n                LZMA2_node *const opt = &enc->opt_buf[cur + len];\n                if (cur_and_len_price < opt->price) {\n                    opt->price = cur_and_len_price;\n                    opt->len = (unsigned)len;\n                    opt->dist = (U32)rep_index;\n                    opt->extra = 0;\n                }\n            } while (++len <= len_test);\n\n            if (rep_index == 0) {\n                /* Save time by exluding normal matches not longer than the rep */\n                start_len = len_test + 1;\n            }\n            /* rep + literal + rep0 is not common so this test is skipped for faster, non-hybrid encoding */\n            if (is_hybrid && len_test + 3 <= bytes_avail && MEM_read16(data + len_test + 1) == MEM_read16(data_2 + len_test + 1)) {\n                /* Try rep + literal + rep0.\n                 * The second rep may be > fast_length, but it is not worth the extra time to handle this case\n                 * and the price table is not filled for it */\n                size_t const len_test_2 = ZSTD_count(data + len_test + 3,\n                    data_2 + len_test + 3,\n                    data + MIN(len_test + 1 + fast_length, bytes_avail)) + 2;\n                size_t state_2 = REP_NEXT_STATE(state);\n                size_t pos_state_next = (pos + len_test) & pos_mask;\n                U32 rep_lit_rep_total_price =\n                    cur_rep_price + enc->states.rep_len_states.prices[pos_state][len_test - kMatchLenMin]\n                    + GET_PRICE_0(enc->states.is_match[state_2][pos_state_next])\n                    + LZMA_getLiteralPriceMatched(LITERAL_PROBS(enc, pos + len_test, data[len_test - 1]),\n                        data[len_test], data_2[len_test]);\n\n                state_2 = kState_LitAfterRep;\n                pos_state_next = (pos + len_test + 1) & pos_mask;\n                rep_lit_rep_total_price +=\n                    GET_PRICE_1(enc->states.is_match[state_2][pos_state_next]) +\n                    GET_PRICE_1(enc->states.is_rep[state_2]);\n                size_t const offset = cur + len_test + 1 + len_test_2;\n                rep_lit_rep_total_price += LZMA_getRepMatch0Price(enc, len_test_2, state_2, pos_state_next);\n                if (rep_lit_rep_total_price < enc->opt_buf[offset].price) {\n                    len_end = MAX(len_end, offset);\n                    enc->opt_buf[offset].price = rep_lit_rep_total_price;\n                    enc->opt_buf[offset].len = (unsigned)len_test_2;\n                    enc->opt_buf[offset].dist = (U32)rep_index;\n                    enc->opt_buf[offset].extra = (unsigned)(len_test + 1);\n                }\n            }\n        }\n    }\n    if (match.length >= start_len && max_length >= start_len) {\n        /* Try normal match */\n        U32 const normal_match_price = match_price + GET_PRICE_0(is_rep_prob);\n        if (!is_hybrid) {\n            /* Normal mode - single match */\n            size_t const length = MIN(match.length, max_length);\n            size_t const cur_dist = match.dist;\n            size_t const dist_slot = LZMA_getDistSlot(match.dist);\n            size_t len_test = length;\n            len_end = MAX(len_end, cur + length);\n            for (; len_test >= start_len; --len_test) {\n                U32 cur_and_len_price = normal_match_price + enc->states.len_states.prices[pos_state][len_test - kMatchLenMin];\n                size_t const len_to_dist_state = LEN_TO_DIST_STATE(len_test);\n\n                if (cur_dist < kNumFullDistances)\n                    cur_and_len_price += enc->distance_prices[len_to_dist_state][cur_dist];\n                else\n                    cur_and_len_price += enc->dist_slot_prices[len_to_dist_state][dist_slot] + enc->align_prices[cur_dist & kAlignMask];\n\n                LZMA2_node *const opt = &enc->opt_buf[cur + len_test];\n                if (cur_and_len_price < opt->price) {\n                    opt->price = cur_and_len_price;\n                    opt->len = (unsigned)len_test;\n                    opt->dist = (U32)(cur_dist + kNumReps);\n                    opt->extra = 0;\n                }\n                else break;\n            }\n        }\n        else {\n            /* Hybrid mode */\n            size_t main_len;\n\n            match.length = MIN(match.length, (U32)max_length);\n            /* Need to test max_length < 4 because the hash fn reads a U32 */\n            if (match.length < 3 || max_length < 4) {\n                enc->matches[MATCH_TBL_INDEX(0)] = match;\n                enc->match_count = 1;\n                main_len = match.length;\n            }\n            else {\n                main_len = LZMA_hashGetMatches(enc, block, pos, max_length, match);\n            }\n            ptrdiff_t match_index = enc->match_count - 1;\n            len_end = MAX(len_end, cur + main_len);\n\n            /* Start with a match longer than the best rep if one exists */\n            ptrdiff_t start_match = 0;\n            while (start_len > enc->matches[MATCH_TBL_INDEX(start_match)].length)\n                ++start_match;\n\n            enc->matches[MATCH_TBL_INDEX(start_match - 1)].length = (U32)start_len - 1; /* Avoids an if..else branch in the loop. [-1] is ok */\n\n            for (; match_index >= start_match; --match_index) {\n                size_t len_test = enc->matches[MATCH_TBL_INDEX(match_index)].length;\n                size_t const cur_dist = enc->matches[MATCH_TBL_INDEX(match_index)].dist;\n                const BYTE *const data_2 = data - cur_dist - 1;\n                size_t const rep_0_pos = len_test + 1;\n                size_t dist_slot = LZMA_getDistSlot((U32)cur_dist);\n                U32 cur_and_len_price;\n                /* Test from the full length down to 1 more than the next shorter match */\n                size_t base_len = enc->matches[MATCH_TBL_INDEX(match_index - 1)].length + 1;\n                for (; len_test >= base_len; --len_test) {\n                    cur_and_len_price = normal_match_price + enc->states.len_states.prices[pos_state][len_test - kMatchLenMin];\n                    size_t const len_to_dist_state = LEN_TO_DIST_STATE(len_test);\n                    if (cur_dist < kNumFullDistances)\n                        cur_and_len_price += enc->distance_prices[len_to_dist_state][cur_dist];\n                    else\n                        cur_and_len_price += enc->dist_slot_prices[len_to_dist_state][dist_slot] + enc->align_prices[cur_dist & kAlignMask];\n\n                    BYTE const sub_len = len_test < enc->matches[MATCH_TBL_INDEX(match_index)].length;\n\n                    LZMA2_node *const opt = &enc->opt_buf[cur + len_test];\n                    if (cur_and_len_price < opt->price) {\n                        opt->price = cur_and_len_price;\n                        opt->len = (unsigned)len_test;\n                        opt->dist = (U32)(cur_dist + kNumReps);\n                        opt->extra = 0;\n                    }\n                    else if(sub_len)\n                        break; /* End the tests if prices for shorter lengths are not lower than those already recorded */\n\n                    if (!sub_len && rep_0_pos + 2 <= bytes_avail && MEM_read16(data + rep_0_pos) == MEM_read16(data_2 + rep_0_pos)) {\n                        /* Try match + literal + rep0 */\n                        size_t const limit = MIN(rep_0_pos + fast_length, bytes_avail);\n                        size_t const len_test_2 = ZSTD_count(data + rep_0_pos + 2, data_2 + rep_0_pos + 2, data + limit) + 2;\n                        size_t state_2 = MATCH_NEXT_STATE(state);\n                        size_t pos_state_next = (pos + len_test) & pos_mask;\n                        U32 match_lit_rep_total_price = cur_and_len_price +\n                            GET_PRICE_0(enc->states.is_match[state_2][pos_state_next]) +\n                            LZMA_getLiteralPriceMatched(LITERAL_PROBS(enc, pos + len_test, data[len_test - 1]),\n                                data[len_test], data_2[len_test]);\n\n                        state_2 = kState_LitAfterMatch;\n                        pos_state_next = (pos_state_next + 1) & pos_mask;\n                        match_lit_rep_total_price +=\n                            GET_PRICE_1(enc->states.is_match[state_2][pos_state_next]) +\n                            GET_PRICE_1(enc->states.is_rep[state_2]);\n                        size_t const offset = cur + rep_0_pos + len_test_2;\n                        match_lit_rep_total_price += LZMA_getRepMatch0Price(enc, len_test_2, state_2, pos_state_next);\n                        if (match_lit_rep_total_price < enc->opt_buf[offset].price) {\n                            len_end = MAX(len_end, offset);\n                            enc->opt_buf[offset].price = match_lit_rep_total_price;\n                            enc->opt_buf[offset].len = (unsigned)len_test_2;\n                            enc->opt_buf[offset].extra = (unsigned)rep_0_pos;\n                            enc->opt_buf[offset].dist = (U32)(cur_dist + kNumReps);\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return len_end;\n}\n\nFORCE_NOINLINE\n// **************** NanaZip Modification Start ****************\n//static void LZMA_initMatchesPos0(LZMA2_ECtx *const enc,\nvoid LZMA_initMatchesPos0(LZMA2_ECtx* const enc,\n// **************** NanaZip Modification End ****************\n    RMF_match const match,\n    size_t const pos_state,\n    size_t len,\n    unsigned const normal_match_price)\n{\n    if ((unsigned)len <= match.length) {\n        size_t const distance = match.dist;\n        size_t const slot = LZMA_getDistSlot(match.dist);\n        /* Test every available length of the match */\n        do {\n            unsigned cur_and_len_price = normal_match_price + enc->states.len_states.prices[pos_state][len - kMatchLenMin];\n            size_t const len_to_dist_state = LEN_TO_DIST_STATE(len);\n\n            if (distance < kNumFullDistances)\n                cur_and_len_price += enc->distance_prices[len_to_dist_state][distance];\n            else\n                cur_and_len_price += enc->align_prices[distance & kAlignMask] + enc->dist_slot_prices[len_to_dist_state][slot];\n\n            if (cur_and_len_price < enc->opt_buf[len].price) {\n                enc->opt_buf[len].price = cur_and_len_price;\n                enc->opt_buf[len].len = (unsigned)len;\n                enc->opt_buf[len].dist = (U32)(distance + kNumReps);\n                enc->opt_buf[len].extra = 0;\n            }\n            ++len;\n        } while ((U32)len <= match.length);\n    }\n}\n\nFORCE_NOINLINE\n// **************** NanaZip Modification Start ****************\n//static size_t LZMA_initMatchesPos0Best(LZMA2_ECtx *const enc, FL2_dataBlock const block,\nsize_t LZMA_initMatchesPos0Best(LZMA2_ECtx* const enc, FL2_dataBlock const block,\n// **************** NanaZip Modification End ****************\n    RMF_match const match,\n    size_t const pos,\n    size_t start_len,\n    unsigned const normal_match_price)\n{\n    if (start_len <= match.length) {\n        size_t main_len;\n        if (match.length < 3 || block.end - pos < 4) {\n            enc->matches[MATCH_TBL_INDEX(0)] = match;\n            enc->match_count = 1;\n            main_len = match.length;\n        }\n        else {\n            main_len = LZMA_hashGetMatches(enc, block, pos, MIN(block.end - pos, enc->fast_length), match);\n        }\n\n        ptrdiff_t start_match = 0;\n        while (start_len > enc->matches[MATCH_TBL_INDEX(start_match)].length)\n            ++start_match;\n\n        enc->matches[MATCH_TBL_INDEX(start_match - 1)].length = (U32)start_len - 1; /* Avoids an if..else branch in the loop. [-1] is ok */\n\n        size_t pos_state = pos & enc->pos_mask;\n\n        for (ptrdiff_t match_index = enc->match_count - 1; match_index >= start_match; --match_index) {\n            size_t len_test = enc->matches[MATCH_TBL_INDEX(match_index)].length;\n            size_t const distance = enc->matches[MATCH_TBL_INDEX(match_index)].dist;\n            size_t const slot = LZMA_getDistSlot((U32)distance);\n            size_t const base_len = enc->matches[MATCH_TBL_INDEX(match_index - 1)].length + 1;\n            /* Test every available match length at the shortest distance. The buffer is sorted */\n            /* in order of increasing length, and therefore increasing distance too. */\n            for (; len_test >= base_len; --len_test) {\n                unsigned cur_and_len_price = normal_match_price\n                    + enc->states.len_states.prices[pos_state][len_test - kMatchLenMin];\n                size_t const len_to_dist_state = LEN_TO_DIST_STATE(len_test);\n\n                if (distance < kNumFullDistances)\n                    cur_and_len_price += enc->distance_prices[len_to_dist_state][distance];\n                else\n                    cur_and_len_price += enc->align_prices[distance & kAlignMask] + enc->dist_slot_prices[len_to_dist_state][slot];\n\n                if (cur_and_len_price < enc->opt_buf[len_test].price) {\n                    enc->opt_buf[len_test].price = cur_and_len_price;\n                    enc->opt_buf[len_test].len = (unsigned)len_test;\n                    enc->opt_buf[len_test].dist = (U32)(distance + kNumReps);\n                    enc->opt_buf[len_test].extra = 0;\n                }\n                else break;\n            }\n        }\n        return main_len;\n    }\n    return 0;\n}\n\n/* Test all available options at position 0 of the optimizer buffer.\n* The prices at this point are all initialized to kInfinityPrice.\n* This function must not be called at a position where no match is\n* available. */\nFORCE_INLINE_TEMPLATE\nsize_t LZMA_initOptimizerPos0(LZMA2_ECtx *const enc, FL2_dataBlock const block,\n    RMF_match const match,\n    size_t const pos,\n    int const is_hybrid,\n    U32* const reps)\n{\n    size_t const max_length = MIN(block.end - pos, kMatchLenMax);\n    const BYTE *const data = block.data + pos;\n    const BYTE *data_2;\n    size_t rep_max_index = 0;\n    size_t rep_lens[kNumReps];\n\n    /* Find any rep matches */\n    for (size_t i = 0; i < kNumReps; ++i) {\n        reps[i] = enc->states.reps[i];\n        data_2 = data - reps[i] - 1;\n        if (MEM_read16(data) != MEM_read16(data_2)) {\n            rep_lens[i] = 0;\n            continue;\n        }\n        rep_lens[i] = ZSTD_count(data + 2, data_2 + 2, data + max_length) + 2;\n        if (rep_lens[i] > rep_lens[rep_max_index])\n            rep_max_index = i;\n    }\n    if (rep_lens[rep_max_index] >= enc->fast_length) {\n        enc->opt_buf[0].len = (unsigned)(rep_lens[rep_max_index]);\n        enc->opt_buf[0].dist = (U32)rep_max_index;\n        return 0;\n    }\n    if (match.length >= enc->fast_length) {\n        enc->opt_buf[0].len = match.length;\n        enc->opt_buf[0].dist = match.dist + kNumReps;\n        return 0;\n    }\n\n    unsigned const cur_byte = *data;\n    unsigned const match_byte = *(data - reps[0] - 1);\n    size_t const state = enc->states.state;\n    size_t const pos_state = pos & enc->pos_mask;\n    LZMA2_prob const is_match_prob = enc->states.is_match[state][pos_state];\n    LZMA2_prob const is_rep_prob = enc->states.is_rep[state];\n\n    enc->opt_buf[0].state = state;\n    /* Set the price for literal */\n    enc->opt_buf[1].price = GET_PRICE_0(is_match_prob) +\n        LZMA_getLiteralPrice(enc, pos, state, data[-1], cur_byte, match_byte);\n    MARK_LITERAL(enc->opt_buf[1]);\n\n    unsigned const match_price = GET_PRICE_1(is_match_prob);\n    unsigned const rep_match_price = match_price + GET_PRICE_1(is_rep_prob);\n    if (match_byte == cur_byte) {\n        /* Try 1-byte rep0 */\n        unsigned const short_rep_price = rep_match_price + LZMA_getRepLen1Price(enc, state, pos_state);\n        if (short_rep_price < enc->opt_buf[1].price) {\n            enc->opt_buf[1].price = short_rep_price;\n            MARK_SHORT_REP(enc->opt_buf[1]);\n        }\n    }\n    memcpy(enc->opt_buf[0].reps, reps, sizeof(enc->opt_buf[0].reps));\n    enc->opt_buf[1].len = 1;\n    /* Test the rep match prices */\n    for (size_t i = 0; i < kNumReps; ++i) {\n        size_t rep_len = rep_lens[i];\n        if (rep_len < 2)\n            continue;\n\n        unsigned const price = rep_match_price + LZMA_getRepPrice(enc, i, state, pos_state);\n        /* Test every available length of the rep */\n        do {\n            unsigned const cur_and_len_price = price + enc->states.rep_len_states.prices[pos_state][rep_len - kMatchLenMin];\n            if (cur_and_len_price < enc->opt_buf[rep_len].price) {\n                enc->opt_buf[rep_len].price = cur_and_len_price;\n                enc->opt_buf[rep_len].len = (unsigned)rep_len;\n                enc->opt_buf[rep_len].dist = (U32)i;\n                enc->opt_buf[rep_len].extra = 0;\n            }\n        } while (--rep_len >= kMatchLenMin);\n    }\n    unsigned const normal_match_price = match_price + GET_PRICE_0(is_rep_prob);\n    size_t const len = (rep_lens[0] >= 2) ? rep_lens[0] + 1 : 2;\n    /* Test the match prices */\n    if (!is_hybrid) {\n        /* Normal mode */\n        LZMA_initMatchesPos0(enc, match, pos_state, len, normal_match_price);\n        return MAX(match.length, rep_lens[rep_max_index]);\n    }\n    else {\n        /* Hybrid mode */\n        size_t main_len = LZMA_initMatchesPos0Best(enc, block, match, pos, len, normal_match_price);\n        return MAX(main_len, rep_lens[rep_max_index]);\n    }\n}\n\nFORCE_INLINE_TEMPLATE\nsize_t LZMA_encodeOptimumSequence(LZMA2_ECtx *const enc, FL2_dataBlock const block,\n    FL2_matchTable* const tbl,\n    int const struct_tbl,\n    int const is_hybrid,\n    size_t start_index,\n    size_t const uncompressed_end,\n    RMF_match match)\n{\n    size_t len_end = enc->len_end_max;\n    unsigned const search_depth = tbl->params.depth;\n    do {\n        size_t const pos_mask = enc->pos_mask;\n\n        /* Reset all prices that were set last time */\n        for (; (len_end & 3) != 0; --len_end)\n            enc->opt_buf[len_end].price = kInfinityPrice;\n        for (; len_end >= 4; len_end -= 4) {\n            enc->opt_buf[len_end].price = kInfinityPrice;\n            enc->opt_buf[len_end - 1].price = kInfinityPrice;\n            enc->opt_buf[len_end - 2].price = kInfinityPrice;\n            enc->opt_buf[len_end - 3].price = kInfinityPrice;\n        }\n\n        /* Set everything up at position 0 */\n        size_t pos = start_index;\n        U32 reps[kNumReps];\n        len_end = LZMA_initOptimizerPos0(enc, block, match, pos, is_hybrid, reps);\n        match.length = 0;\n        size_t cur = 1;\n\n        /* len_end == 0 if a match of fast_length was found */\n        if (len_end > 0) {\n            ++pos;\n            for (; cur < len_end; ++cur, ++pos) {\n                /* Terminate if the farthest calculated price is too near the buffer end */\n                if (len_end >= kOptimizerBufferSize - kOptimizerEndSize) {\n                    U32 price = enc->opt_buf[cur].price;\n                    /* This is a compromise to favor more distant end points\n                     * even if the price is a bit higher */\n                    U32 const delta = price / (U32)cur / 2U;\n                    for (size_t j = cur + 1; j <= len_end; j++) {\n                        U32 const price2 = enc->opt_buf[j].price;\n                        if (price >= price2) {\n                            price = price2;\n                            cur = j;\n                        }\n                        price += delta;\n                    }\n                    break;\n                }\n\n                /* Skip ahead if a lower or equal price is available at greater distance */\n                size_t const end = MIN(cur + kOptimizerSkipSize, len_end);\n                U32 price = enc->opt_buf[cur].price;\n                for (size_t j = cur + 1; j <= end; j++) {\n                    U32 const price2 = enc->opt_buf[j].price;\n                    if (price >= price2) {\n                        price = price2;\n                        pos += j - cur;\n                        cur = j;\n                        if (cur == len_end)\n                            goto reverse;\n                    }\n                }\n\n                match = RMF_getMatch(block, tbl, search_depth, struct_tbl, pos);\n                if (match.length >= enc->fast_length)\n                    break;\n\n                len_end = LZMA_optimalParse(enc, block, match, pos, cur, len_end, is_hybrid, reps);\n            }\nreverse:\n            DEBUGLOG(6, \"End optimal parse at %u\", (U32)cur);\n            LZMA_reverseOptimalChain(enc->opt_buf, cur);\n        }\n        /* Encode the selections in the buffer */\n        size_t i = 0;\n        do {\n            unsigned const len = enc->opt_buf[i].len;\n\n            if (len == 1 && enc->opt_buf[i].dist == kNullDist) {\n                LZMA_encodeLiteralBuf(enc, block.data, start_index + i);\n                ++i;\n            }\n            else {\n                size_t const pos_state = (start_index + i) & pos_mask;\n                U32 const dist = enc->opt_buf[i].dist;\n                /* Updating i separately for each case may allow a branch to be eliminated */\n                if (dist >= kNumReps) {\n                    LZMA_encodeNormalMatch(enc, len, dist - kNumReps, pos_state);\n                    i += len;\n                }\n                else if(len == 1) {\n                    LZMA_encodeRepMatchShort(enc, pos_state);\n                    ++i;\n                }\n                else {\n                    LZMA_encodeRepMatchLong(enc, len, dist, pos_state);\n                    i += len;\n                }\n            }\n        } while (i < cur);\n        start_index += i;\n        /* Do another round if there is a long match pending,\n         * because the reps must be checked and the match encoded. */\n    } while (match.length >= enc->fast_length && start_index < uncompressed_end && enc->rc.out_index < enc->chunk_size);\n\n    enc->len_end_max = len_end;\n\n    return start_index;\n}\n\n// **************** NanaZip Modification Start ****************\n//static void FORCE_NOINLINE LZMA_fillAlignPrices(LZMA2_ECtx *const enc)\nFORCE_NOINLINE void LZMA_fillAlignPrices(LZMA2_ECtx* const enc)\n// **************** NanaZip Modification End ****************\n{\n    unsigned i;\n    const LZMA2_prob *const probs = enc->states.dist_align_encoders;\n    for (i = 0; i < kAlignTableSize / 2; i++) {\n        U32 price = 0;\n        unsigned sym = i;\n        unsigned m = 1;\n        unsigned bit;\n        bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[m], bit); m = (m << 1) + bit;\n        bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[m], bit); m = (m << 1) + bit;\n        bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[m], bit); m = (m << 1) + bit;\n        U32 const prob = probs[m];\n        enc->align_prices[i] = price + GET_PRICE_0(prob);\n        enc->align_prices[i + 8] = price + GET_PRICE_1(prob);\n    }\n}\n\n// **************** NanaZip Modification Start ****************\n//static void FORCE_NOINLINE LZMA_fillDistancesPrices(LZMA2_ECtx *const enc)\nFORCE_NOINLINE void LZMA_fillDistancesPrices(LZMA2_ECtx* const enc)\n// **************** NanaZip Modification End ****************\n{\n    U32 * const temp_prices = enc->distance_prices[kNumLenToPosStates - 1];\n\n    enc->match_price_count = 0;\n\n    for (size_t i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++) {\n        unsigned const dist_slot = distance_table[i];\n        unsigned footer_bits = (dist_slot >> 1) - 1;\n        size_t base = ((2 | (dist_slot & 1)) << footer_bits);\n        const LZMA2_prob *probs = enc->states.dist_encoders + base * 2U;\n        base += i;\n        probs = probs - distance_table[base] - 1;\n        U32 price = 0;\n        unsigned m = 1;\n        unsigned sym = (unsigned)i;\n        unsigned const offset = (unsigned)1 << footer_bits;\n\n        for (; footer_bits != 0; --footer_bits) {\n            unsigned bit = sym & 1;\n            sym >>= 1;\n            price += GET_PRICE(probs[m], bit);\n            m = (m << 1) + bit;\n        };\n\n        unsigned const prob = probs[m];\n        temp_prices[base] = price + GET_PRICE_0(prob);\n        temp_prices[base + offset] = price + GET_PRICE_1(prob);\n    }\n\n    for (unsigned lps = 0; lps < kNumLenToPosStates; lps++) {\n        size_t slot;\n        size_t const dist_table_size2 = (enc->dist_price_table_size + 1) >> 1;\n        U32 *const dist_slot_prices = enc->dist_slot_prices[lps];\n        const LZMA2_prob *const probs = enc->states.dist_slot_encoders[lps];\n\n        for (slot = 0; slot < dist_table_size2; slot++) {\n            /* dist_slot_prices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices); */\n            U32 price;\n            unsigned bit;\n            unsigned sym = (unsigned)slot + (1 << (kNumPosSlotBits - 1));\n            bit = sym & 1; sym >>= 1; price = GET_PRICE(probs[sym], bit);\n            bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);\n            bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);\n            bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);\n            bit = sym & 1; sym >>= 1; price += GET_PRICE(probs[sym], bit);\n            unsigned const prob = probs[slot + (1 << (kNumPosSlotBits - 1))];\n            dist_slot_prices[slot * 2] = price + GET_PRICE_0(prob);\n            dist_slot_prices[slot * 2 + 1] = price + GET_PRICE_1(prob);\n        }\n\n        {\n            U32 delta = ((U32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);\n            for (slot = kEndPosModelIndex / 2; slot < dist_table_size2; slot++) {\n                dist_slot_prices[slot * 2] += delta;\n                dist_slot_prices[slot * 2 + 1] += delta;\n                delta += ((U32)1 << kNumBitPriceShiftBits);\n            }\n        }\n\n        {\n            U32 *const dp = enc->distance_prices[lps];\n\n            dp[0] = dist_slot_prices[0];\n            dp[1] = dist_slot_prices[1];\n            dp[2] = dist_slot_prices[2];\n            dp[3] = dist_slot_prices[3];\n\n            for (size_t i = 4; i < kNumFullDistances; i += 2) {\n                U32 slot_price = dist_slot_prices[distance_table[i]];\n                dp[i] = slot_price + temp_prices[i];\n                dp[i + 1] = slot_price + temp_prices[i + 1];\n            }\n        }\n    }\n}\n\nFORCE_INLINE_TEMPLATE\nsize_t LZMA_encodeChunkBest(LZMA2_ECtx *const enc,\n    FL2_dataBlock const block,\n    FL2_matchTable* const tbl,\n    int const struct_tbl,\n    size_t pos,\n    size_t const uncompressed_end)\n{\n    unsigned const search_depth = tbl->params.depth;\n    LZMA_fillDistancesPrices(enc);\n    LZMA_fillAlignPrices(enc);\n    LZMA_lengthStates_updatePrices(enc, &enc->states.len_states);\n    LZMA_lengthStates_updatePrices(enc, &enc->states.rep_len_states);\n\n    while (pos < uncompressed_end && enc->rc.out_index < enc->chunk_size)\n    {\n        RMF_match const match = RMF_getMatch(block, tbl, search_depth, struct_tbl, pos);\n        if (match.length > 1) {\n            /* Template-like inline function */\n            if (enc->strategy == FL2_ultra) {\n                pos = LZMA_encodeOptimumSequence(enc, block, tbl, struct_tbl, 1, pos, uncompressed_end, match);\n            }\n            else {\n                pos = LZMA_encodeOptimumSequence(enc, block, tbl, struct_tbl, 0, pos, uncompressed_end, match);\n            }\n            if (enc->match_price_count >= kMatchRepriceFrequency) {\n                LZMA_fillAlignPrices(enc);\n                LZMA_fillDistancesPrices(enc);\n                LZMA_lengthStates_updatePrices(enc, &enc->states.len_states);\n            }\n            if (enc->rep_len_price_count >= kRepLenRepriceFrequency) {\n                enc->rep_len_price_count = 0;\n                LZMA_lengthStates_updatePrices(enc, &enc->states.rep_len_states);\n            }\n        }\n        else {\n            if (block.data[pos] != block.data[pos - enc->states.reps[0] - 1]) {\n                LZMA_encodeLiteralBuf(enc, block.data, pos);\n                ++pos;\n            }\n            else {\n                LZMA_encodeRepMatchShort(enc, pos & enc->pos_mask);\n                ++pos;\n            }\n        }\n    }\n    return pos;\n}\n\nstatic void LZMA_lengthStates_Reset(LZMA2_lenStates* const ls, unsigned const fast_length)\n{\n    ls->choice = kProbInitValue;\n\n    for (size_t i = 0; i < (kNumPositionStatesMax << (kLenNumLowBits + 1)); ++i)\n        ls->low[i] = kProbInitValue;\n\n    for (size_t i = 0; i < kLenNumHighSymbols; ++i)\n        ls->high[i] = kProbInitValue;\n\n    ls->table_size = fast_length + 1 - kMatchLenMin;\n}\n\nstatic void LZMA_encoderStates_Reset(LZMA2_encStates* const es, unsigned const lc, unsigned const lp, unsigned fast_length)\n{\n    es->state = 0;\n\n    for (size_t i = 0; i < kNumReps; ++i)\n        es->reps[i] = 0;\n\n    for (size_t i = 0; i < kNumStates; ++i) {\n        for (size_t j = 0; j < kNumPositionStatesMax; ++j) {\n            es->is_match[i][j] = kProbInitValue;\n            es->is_rep0_long[i][j] = kProbInitValue;\n        }\n        es->is_rep[i] = kProbInitValue;\n        es->is_rep_G0[i] = kProbInitValue;\n        es->is_rep_G1[i] = kProbInitValue;\n        es->is_rep_G2[i] = kProbInitValue;\n    }\n    size_t const num = (size_t)(kNumLiterals * kNumLitTables) << (lp + lc);\n    for (size_t i = 0; i < num; ++i)\n        es->literal_probs[i] = kProbInitValue;\n\n    for (size_t i = 0; i < kNumLenToPosStates; ++i) {\n        LZMA2_prob *probs = es->dist_slot_encoders[i];\n        for (size_t j = 0; j < (1 << kNumPosSlotBits); ++j)\n            probs[j] = kProbInitValue;\n    }\n    for (size_t i = 0; i < kNumFullDistances - kEndPosModelIndex; ++i)\n        es->dist_encoders[i] = kProbInitValue;\n\n    LZMA_lengthStates_Reset(&es->len_states, fast_length);\n    LZMA_lengthStates_Reset(&es->rep_len_states, fast_length);\n\n    for (size_t i = 0; i < (1 << kNumAlignBits); ++i)\n        es->dist_align_encoders[i] = kProbInitValue;\n}\n\nBYTE LZMA2_getDictSizeProp(size_t const dictionary_size)\n{\n    BYTE dict_size_prop = 0;\n    for (BYTE bit = 11; bit < 32; ++bit) {\n        if (((size_t)2 << bit) >= dictionary_size) {\n            dict_size_prop = (bit - 11) << 1;\n            break;\n        }\n        if (((size_t)3 << bit) >= dictionary_size) {\n            dict_size_prop = ((bit - 11) << 1) | 1;\n            break;\n        }\n    }\n    return dict_size_prop;\n}\n\nsize_t LZMA2_compressBound(size_t src_size)\n{\n\t/* Minimum average uncompressed size. An average size of half kChunkSize should be assumed\n\t * to account for thread_count incomplete end chunks per block. LZMA expansion is < 2% so 1/16\n\t * is a safe overestimate. */\n\tstatic const unsigned chunk_min_avg = (kChunkSize - (kChunkSize / 16U)) / 2U;\n\t/* Maximum size of data stored in a sequence of uncompressed chunks */\n\treturn src_size + ((src_size + chunk_min_avg - 1) / chunk_min_avg) * 3 + 6;\n}\n\nsize_t LZMA2_encMemoryUsage(unsigned const chain_log, FL2_strategy const strategy, unsigned const thread_count)\n{\n    size_t size = sizeof(LZMA2_ECtx);\n    if(strategy == FL2_ultra)\n        size += sizeof(LZMA2_hc3) + (sizeof(U32) << chain_log) - sizeof(U32);\n    return size * thread_count;\n}\n\nstatic void LZMA2_reset(LZMA2_ECtx *const enc, size_t const max_distance)\n{\n    DEBUGLOG(5, \"LZMA encoder reset : max_distance %u\", (unsigned)max_distance);\n    RC_reset(&enc->rc);\n    LZMA_encoderStates_Reset(&enc->states, enc->lc, enc->lp, enc->fast_length);\n    enc->pos_mask = (1 << enc->pb) - 1;\n    enc->lit_pos_mask = (1 << enc->lp) - 1;\n    U32 i = 0;\n    for (; max_distance > (size_t)1 << i; ++i) {\n    }\n    enc->dist_price_table_size = i * 2;\n    enc->rep_len_price_count = 0;\n    enc->match_price_count = 0;\n}\n\nstatic BYTE LZMA_getLcLpPbCode(LZMA2_ECtx *const enc)\n{\n    return (BYTE)((enc->pb * 5 + enc->lp) * 9 + enc->lc);\n}\n\n/* Integer square root from https://stackoverflow.com/a/1101217 */\nstatic U32 LZMA2_isqrt(U32 op)\n{\n    U32 res = 0;\n    /* \"one\" starts at the highest power of four <= than the argument. */\n    U32 one = (U32)1 << (ZSTD_highbit32(op) & ~1);\n\n    while (one != 0) {\n        if (op >= res + one) {\n            op -= res + one;\n            res = res + 2U * one;\n        }\n        res >>= 1;\n        one >>= 2;\n    }\n    return res;\n}\n\nstatic BYTE LZMA2_isChunkIncompressible(const FL2_matchTable* const tbl,\n    FL2_dataBlock const block, size_t const start,\n\tunsigned const strategy)\n{\n\tif (block.end - start >= kMinTestChunkSize) {\n\t\tstatic const size_t max_dist_table[][5] = {\n\t\t\t{ 0, 0, 0, 1U << 6, 1U << 14 }, /* fast */\n\t\t\t{ 0, 0, 1U << 6, 1U << 14, 1U << 22 }, /* opt */\n\t\t\t{ 0, 0, 1U << 6, 1U << 14, 1U << 22 } }; /* ultra */\n\t\tstatic const size_t margin_divisor[3] = { 60U, 45U, 120U };\n\t\tstatic const U32 dev_table[3] = { 24, 24, 20};\n\n\t\tsize_t const end = MIN(start + kChunkSize, block.end);\n\t\tsize_t const chunk_size = end - start;\n\t\tsize_t count = 0;\n\t\tsize_t const margin = chunk_size / margin_divisor[strategy];\n\t\tsize_t const terminator = start + margin;\n\n\t\tif (tbl->is_struct) {\n\t\t\tsize_t prev_dist = 0;\n\t\t\tfor (size_t pos = start; pos < end; ) {\n\t\t\t\tU32 const link = GetMatchLink(tbl->table, pos);\n\t\t\t\tif (link == RADIX_NULL_LINK) {\n\t\t\t\t\t++pos;\n\t\t\t\t\t++count;\n\t\t\t\t\tprev_dist = 0;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsize_t const length = GetMatchLength(tbl->table, pos);\n\t\t\t\t\tsize_t const dist = pos - GetMatchLink(tbl->table, pos);\n                    if (length > 4) {\n                        /* Increase the cost if it's not the same match */\n                        count += dist != prev_dist;\n                    }\n                    else {\n                        /* Increment the cost for a short match. The cost is the entire length if it's too far */\n                        count += (dist < max_dist_table[strategy][length]) ? 1 : length;\n                    }\n\t\t\t\t\tpos += length;\n\t\t\t\t\tprev_dist = dist;\n\t\t\t\t}\n\t\t\t\tif (count + terminator <= pos)\n\t\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tsize_t prev_dist = 0;\n\t\t\tfor (size_t pos = start; pos < end; ) {\n\t\t\t\tU32 const link = tbl->table[pos];\n\t\t\t\tif (link == RADIX_NULL_LINK) {\n\t\t\t\t\t++pos;\n\t\t\t\t\t++count;\n\t\t\t\t\tprev_dist = 0;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsize_t const length = link >> RADIX_LINK_BITS;\n\t\t\t\t\tsize_t const dist = pos - (link & RADIX_LINK_MASK);\n\t\t\t\t\tif (length > 4)\n\t\t\t\t\t\tcount += dist != prev_dist;\n\t\t\t\t\telse\n\t\t\t\t\t\tcount += (dist < max_dist_table[strategy][length]) ? 1 : length;\n\t\t\t\t\tpos += length;\n\t\t\t\t\tprev_dist = dist;\n\t\t\t\t}\n\t\t\t\tif (count + terminator <= pos)\n\t\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n        U32 char_count[256];\n        U32 char_total = 0;\n        /* Expected normal character count * 4 */\n        U32 const avg = (U32)(chunk_size / 64U);\n\n        memset(char_count, 0, sizeof(char_count));\n        for (size_t pos = start; pos < end; ++pos)\n            char_count[block.data[pos]] += 4;\n        /* Sum the deviations */\n        for (size_t i = 0; i < 256; ++i) {\n            S32 delta = char_count[i] - avg;\n            char_total += delta * delta;\n        }\n        U32 sqrt_chunk = (chunk_size == kChunkSize) ? kSqrtChunkSize : LZMA2_isqrt((U32)chunk_size);\n        /* Result base on character count std dev */\n        return LZMA2_isqrt(char_total) / sqrt_chunk <= dev_table[strategy];\n\t}\n\treturn 0;\n}\n\nstatic size_t LZMA2_encodeChunk(LZMA2_ECtx *const enc,\n    FL2_matchTable* const tbl,\n    FL2_dataBlock const block,\n    size_t const pos, size_t const uncompressed_end)\n{\n    /* Template-like inline functions */\n    if (enc->strategy == FL2_fast) {\n        if (tbl->is_struct) {\n            return LZMA_encodeChunkFast(enc, block, tbl, 1,\n                pos, uncompressed_end);\n        }\n        else {\n            return LZMA_encodeChunkFast(enc, block, tbl, 0,\n                pos, uncompressed_end);\n        }\n    }\n    else {\n        if (tbl->is_struct) {\n            return LZMA_encodeChunkBest(enc, block, tbl, 1,\n                pos, uncompressed_end);\n        }\n        else {\n            return LZMA_encodeChunkBest(enc, block, tbl, 0,\n                pos, uncompressed_end);\n        }\n    }\n}\n\nsize_t LZMA2_encode(LZMA2_ECtx *const enc,\n    FL2_matchTable* const tbl,\n    FL2_dataBlock const block,\n    const FL2_lzma2Parameters* const options,\n    int stream_prop,\n    FL2_atomic *const progress_in,\n    FL2_atomic *const progress_out,\n    int *const canceled)\n{\n    size_t const start = block.start;\n\n    /* Output starts in the temp buffer */\n    BYTE* out_dest = enc->out_buf;\n    enc->chunk_size = kTempMinOutput;\n    enc->chunk_limit = kTempBufferSize - kMaxMatchEncodeSize * 2;\n\n    /* Each encoder writes a properties byte because the upstream encoder(s) could */\n\t/* write only uncompressed chunks with no properties. */\n\tBYTE encode_properties = 1;\n    BYTE incompressible = 0;\n\n    if (block.end <= block.start)\n        return 0;\n\n    enc->lc = options->lc;\n    enc->lp = MIN(options->lp, kNumLiteralPosBitsMax);\n\n    if (enc->lc + enc->lp > kLcLpMax)\n        enc->lc = kLcLpMax - enc->lp;\n\n    enc->pb = MIN(options->pb, kNumPositionBitsMax);\n    enc->strategy = options->strategy;\n    enc->fast_length = MIN(options->fast_length, kMatchLenMax);\n    enc->match_cycles = MIN(options->match_cycles, kMatchesMax - 1);\n\n    LZMA2_reset(enc, block.end);\n\n    if (enc->strategy == FL2_ultra) {\n        /* Create a hash chain to put the encoder into hybrid mode */\n        if (enc->hash_alloc_3 < ((ptrdiff_t)1 << options->second_dict_bits)) {\n            if(LZMA_hashCreate(enc, options->second_dict_bits) != 0)\n                return FL2_ERROR(memory_allocation);\n        }\n        else {\n            LZMA_hashReset(enc, options->second_dict_bits);\n        }\n        enc->hash_prev_index = (start >= (size_t)enc->hash_dict_3) ? (ptrdiff_t)(start - enc->hash_dict_3) : (ptrdiff_t)-1;\n    }\n    enc->len_end_max = kOptimizerBufferSize - 1;\n\n    /* Limit the matches near the end of this slice to not exceed block.end */\n    RMF_limitLengths(tbl, block.end);\n\n    for (size_t pos = start; pos < block.end;) {\n        size_t header_size = (stream_prop >= 0) + (encode_properties ? kChunkHeaderSize + 1 : kChunkHeaderSize);\n        LZMA2_encStates saved_states;\n        size_t next_index;\n\n        RC_reset(&enc->rc);\n        RC_setOutputBuffer(&enc->rc, out_dest + header_size);\n\n        if (!incompressible) {\n            size_t cur = pos;\n            size_t const end = (enc->strategy == FL2_fast) ? MIN(block.end, pos + kMaxChunkUncompressedSize - kMatchLenMax + 1)\n                : MIN(block.end, pos + kMaxChunkUncompressedSize - kOptimizerBufferSize + 2); /* last byte of opt_buf unused */\n\n            /* Copy states in case chunk is incompressible */\n            saved_states = enc->states;\n\n            if (pos == 0) {\n                /* First byte of the dictionary */\n                LZMA_encodeLiteral(enc, 0, block.data[0], 0);\n                ++cur;\n            }\n            if (pos == start) {\n                /* After kTempMinOutput bytes we can write data to the match table because the */\n                /* compressed data will never catch up with the table position being read. */\n                cur = LZMA2_encodeChunk(enc, tbl, block, cur, end);\n\n\t\t\t\tif (header_size + enc->rc.out_index > kTempBufferSize)\n\t\t\t\t\treturn FL2_ERROR(internal);\n\n                /* Switch to the match table as output buffer */\n                out_dest = RMF_getTableAsOutputBuffer(tbl, start);\n                memcpy(out_dest, enc->out_buf, header_size + enc->rc.out_index);\n                enc->rc.out_buffer = out_dest + header_size;\n\n                /* Now encode up to the full chunk size */\n                enc->chunk_size = kChunkSize;\n                enc->chunk_limit = kMaxChunkCompressedSize - kMaxMatchEncodeSize * 2;\n            }\n            next_index = LZMA2_encodeChunk(enc, tbl, block, cur, end);\n            RC_flush(&enc->rc);\n        }\n        else {\n            next_index = MIN(pos + kChunkSize, block.end);\n        }\n        size_t compressed_size = enc->rc.out_index;\n        size_t uncompressed_size = next_index - pos;\n\n        if (compressed_size > kMaxChunkCompressedSize || uncompressed_size > kMaxChunkUncompressedSize)\n            return FL2_ERROR(internal);\n\n        BYTE* header = out_dest;\n\n        if (stream_prop >= 0) {\n            *header++ = (BYTE)stream_prop;\n            stream_prop = -1;\n        }\n\n        header[1] = (BYTE)((uncompressed_size - 1) >> 8);\n        header[2] = (BYTE)(uncompressed_size - 1);\n        /* Output an uncompressed chunk if necessary */\n        if (incompressible || uncompressed_size + 3 <= compressed_size + header_size) {\n            DEBUGLOG(6, \"Storing chunk : was %u => %u\", (unsigned)uncompressed_size, (unsigned)compressed_size);\n\n            header[0] = (pos == 0) ? kChunkUncompressedDictReset : kChunkUncompressed;\n\n            /* Copy uncompressed data into the output */\n            memcpy(header + 3, block.data + pos, uncompressed_size);\n\n            compressed_size = uncompressed_size;\n            header_size = 3 + (header - out_dest);\n\n            /* Restore states if compression was attempted */\n            if (!incompressible)\n                enc->states = saved_states;\n        }\n        else {\n            DEBUGLOG(6, \"Compressed chunk : %u => %u\", (unsigned)uncompressed_size, (unsigned)compressed_size);\n\n            if (pos == 0)\n                header[0] = kChunkCompressedFlag | kChunkAllReset;\n            else if (encode_properties)\n                header[0] = kChunkCompressedFlag | kChunkStatePropertiesReset;\n            else\n                header[0] = kChunkCompressedFlag | kChunkNothingReset;\n\n            header[0] |= (BYTE)((uncompressed_size - 1) >> 16);\n            header[3] = (BYTE)((compressed_size - 1) >> 8);\n            header[4] = (BYTE)(compressed_size - 1);\n            if (encode_properties) {\n                header[5] = LZMA_getLcLpPbCode(enc);\n                encode_properties = 0;\n            }\n        }\n        if (incompressible || uncompressed_size + 3 <= compressed_size + (compressed_size >> kRandomFilterMarginBits) + header_size) {\n            /* Test the next chunk for compressibility */\n            incompressible = LZMA2_isChunkIncompressible(tbl, block, next_index, enc->strategy);\n        }\n        out_dest += compressed_size + header_size;\n\n        /* Update progress concurrently with other encoder threads */\n        FL2_atomic_add(*progress_in, (long)(next_index - pos));\n        FL2_atomic_add(*progress_out, (long)(compressed_size + header_size));\n\n        pos = next_index;\n\n        if (*canceled)\n            return FL2_ERROR(canceled);\n    }\n    return out_dest - RMF_getTableAsOutputBuffer(tbl, start);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/lzma2_enc.h",
    "content": "﻿/* lzma2_enc.h -- LZMA2 Encoder\nBased on LzmaEnc.h and Lzma2Enc.h : Igor Pavlov\nModified for FL2 by Conor McCarthy\nPublic domain\n*/\n\n#ifndef RADYX_LZMA2_ENCODER_H\n#define RADYX_LZMA2_ENCODER_H\n\n#include \"mem.h\"\n#include \"data_block.h\"\n#include \"radix_mf.h\"\n#include \"atomic.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#define kFastDistBits 12U\n\n#define LZMA2_END_MARKER '\\0'\n#define ENC_MIN_BYTES_PER_THREAD 0x1C000 /* Enough for 8 threads, 1 Mb dict, 2/16 overlap */\n\n\ntypedef struct LZMA2_ECtx_s LZMA2_ECtx;\n\ntypedef struct\n{\n    unsigned lc;\n    unsigned lp;\n    unsigned pb;\n    unsigned fast_length;\n    unsigned match_cycles;\n    FL2_strategy strategy;\n    unsigned second_dict_bits;\n    unsigned reset_interval;\n} FL2_lzma2Parameters;\n\n\nLZMA2_ECtx* LZMA2_createECtx(void);\n\nvoid LZMA2_freeECtx(LZMA2_ECtx *const enc);\n\nint LZMA2_hashAlloc(LZMA2_ECtx *const enc, const FL2_lzma2Parameters* const options);\n\nsize_t LZMA2_encode(LZMA2_ECtx *const enc,\n    FL2_matchTable* const tbl,\n    FL2_dataBlock const block,\n    const FL2_lzma2Parameters* const options,\n    int stream_prop,\n    FL2_atomic *const progress_in,\n    FL2_atomic *const progress_out,\n    int *const canceled);\n\nBYTE LZMA2_getDictSizeProp(size_t const dictionary_size);\n\nsize_t LZMA2_compressBound(size_t src_size);\n\nsize_t LZMA2_encMemoryUsage(unsigned const chain_log, FL2_strategy const strategy, unsigned const thread_count);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* RADYX_LZMA2_ENCODER_H */"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/mem.h",
    "content": "﻿/* NanaZip Header File Redirection */\n#include \"../Zstandard/common/mem.h\"\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/platform.h",
    "content": "﻿/*\n * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef PLATFORM_H_MODULE\n#define PLATFORM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* **************************************\n*  Compiler Options\n****************************************/\n#if defined(_MSC_VER)\n#  define _CRT_SECURE_NO_WARNINGS    /* Disable Visual Studio warning messages for fopen, strncpy, strerror */\n#  if (_MSC_VER <= 1800)             /* 1800 == Visual Studio 2013 */\n#    define _CRT_SECURE_NO_DEPRECATE /* VS2005 - must be declared before <io.h> and <windows.h> */\n#    define snprintf sprintf_s       /* snprintf unsupported by Visual <= 2013 */\n#  endif\n#endif\n\n\n/* **************************************\n*  Detect 64-bit OS\n*  http://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros\n****************************************/\n#if defined __ia64 || defined _M_IA64                                                                               /* Intel Itanium */ \\\n  || defined __powerpc64__ || defined __ppc64__ || defined __PPC64__                                                /* POWER 64-bit */  \\\n  || (defined __sparc && (defined __sparcv9 || defined __sparc_v9__ || defined __arch64__)) || defined __sparc64__  /* SPARC 64-bit */  \\\n  || defined __x86_64__s || defined _M_X64                                                                          /* x86 64-bit */    \\\n  || defined __arm64__ || defined __aarch64__ || defined __ARM64_ARCH_8__                                           /* ARM 64-bit */    \\\n  || (defined __mips  && (__mips == 64 || __mips == 4 || __mips == 3))                                              /* MIPS 64-bit */   \\\n  || defined _LP64 || defined __LP64__ /* NetBSD, OpenBSD */ || defined __64BIT__ /* AIX */ || defined _ADDR64 /* Cray */               \\\n  || (defined __SIZEOF_POINTER__ && __SIZEOF_POINTER__ == 8) /* gcc */\n#  if !defined(__64BIT__)\n#    define __64BIT__  1\n#  endif\n#endif\n\n\n/* *********************************************************\n*  Turn on Large Files support (>4GB) for 32-bit Linux/Unix\n***********************************************************/\n#if !defined(__64BIT__) || defined(__MINGW32__)    /* No point defining Large file for 64 bit but MinGW-w64 requires it */\n#  if !defined(_FILE_OFFSET_BITS)\n#    define _FILE_OFFSET_BITS 64                   /* turn off_t into a 64-bit type for ftello, fseeko */\n#  endif\n#  if !defined(_LARGEFILE_SOURCE)                  /* obsolete macro, replaced with _FILE_OFFSET_BITS */\n#    define _LARGEFILE_SOURCE 1                    /* Large File Support extension (LFS) - fseeko, ftello */\n#  endif\n#  if defined(_AIX) || defined(__hpux)\n#    define _LARGE_FILES                           /* Large file support on 32-bits AIX and HP-UX */\n#  endif\n#endif\n\n\n/* ************************************************************\n*  Detect POSIX version\n*  PLATFORM_POSIX_VERSION = 0 for non-Unix e.g. Windows\n*  PLATFORM_POSIX_VERSION = 1 for Unix-like but non-POSIX\n*  PLATFORM_POSIX_VERSION > 1 is equal to found _POSIX_VERSION\n*  Value of PLATFORM_POSIX_VERSION can be forced on command line\n***************************************************************/\n#ifndef PLATFORM_POSIX_VERSION\n\n#  if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */ \\\n     || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)  /* BSD distros */\n     /* exception rule : force posix version to 200112L,\n      * note: it's better to use unistd.h's _POSIX_VERSION whenever possible */\n#    define PLATFORM_POSIX_VERSION 200112L\n\n/* try to determine posix version through official unistd.h's _POSIX_VERSION (http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html).\n * note : there is no simple way to know in advance if <unistd.h> is present or not on target system,\n * Posix specification mandates its presence and its content, but target system must respect this spec.\n * It's necessary to _not_ #include <unistd.h> whenever target OS is not unix-like\n * otherwise it will block preprocessing stage.\n * The following list of build macros tries to \"guess\" if target OS is likely unix-like, and therefore can #include <unistd.h>\n */\n#  elif !defined(_WIN32) \\\n     && (defined(__unix__) || defined(__unix) \\\n     || defined(__midipix__) || defined(__VMS) || defined(__HAIKU__))\n\n#    if defined(__linux__) || defined(__linux)\n#      ifndef _POSIX_C_SOURCE\n#        define _POSIX_C_SOURCE 200112L  /* feature test macro : https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html */\n#      endif\n#    endif\n#    include <unistd.h>  /* declares _POSIX_VERSION */\n#    if defined(_POSIX_VERSION)  /* POSIX compliant */\n#      define PLATFORM_POSIX_VERSION _POSIX_VERSION\n#    else\n#      define PLATFORM_POSIX_VERSION 1\n#    endif\n\n#  else  /* non-unix target platform (like Windows) */\n#    define PLATFORM_POSIX_VERSION 0\n#  endif\n\n#endif   /* PLATFORM_POSIX_VERSION */\n\n/*-*********************************************\n*  Detect if isatty() and fileno() are available\n************************************************/\n#if (defined(__linux__) && (PLATFORM_POSIX_VERSION > 1)) \\\n || (PLATFORM_POSIX_VERSION >= 200112L) \\\n || defined(__DJGPP__) \\\n || defined(__MSYS__)\n#  include <unistd.h>   /* isatty */\n#  define IS_CONSOLE(stdStream) isatty(fileno(stdStream))\n#elif defined(MSDOS) || defined(OS2) || defined(__CYGWIN__)\n#  include <io.h>       /* _isatty */\n#  define IS_CONSOLE(stdStream) _isatty(_fileno(stdStream))\n#elif defined(WIN32) || defined(_WIN32)\n#  include <io.h>      /* _isatty */\n#  include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */\n#  include <stdio.h>   /* FILE */\nstatic __inline int IS_CONSOLE(FILE* stdStream) {\n    DWORD dummy;\n    return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy);\n}\n#else\n#  define IS_CONSOLE(stdStream) 0\n#endif\n\n\n/******************************\n*  OS-specific IO behaviors\n******************************/\n#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32)\n#  include <fcntl.h>   /* _O_BINARY */\n#  include <io.h>      /* _setmode, _fileno, _get_osfhandle */\n#  if !defined(__DJGPP__)\n#    include <windows.h> /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */\n#    include <winioctl.h> /* FSCTL_SET_SPARSE */\n#    define SET_BINARY_MODE(file) { int const unused=_setmode(_fileno(file), _O_BINARY); (void)unused; }\n#    define SET_SPARSE_FILE_MODE(file) { DWORD dw; DeviceIoControl((HANDLE) _get_osfhandle(_fileno(file)), FSCTL_SET_SPARSE, 0, 0, 0, 0, &dw, 0); }\n#  else\n#    define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)\n#    define SET_SPARSE_FILE_MODE(file)\n#  endif\n#else\n#  define SET_BINARY_MODE(file)\n#  define SET_SPARSE_FILE_MODE(file)\n#endif\n\n\n#ifndef ZSTD_SPARSE_DEFAULT\n#  if (defined(__APPLE__) && defined(__MACH__))\n#    define ZSTD_SPARSE_DEFAULT 0\n#  else\n#    define ZSTD_SPARSE_DEFAULT 1\n#  endif\n#endif\n\n\n#ifndef ZSTD_START_SYMBOLLIST_FRAME\n#  ifdef __linux__\n#    define ZSTD_START_SYMBOLLIST_FRAME 2\n#  elif defined __APPLE__\n#    define ZSTD_START_SYMBOLLIST_FRAME 4\n#  else\n#    define ZSTD_START_SYMBOLLIST_FRAME 0\n#  endif\n#endif\n\n\n#ifndef ZSTD_SETPRIORITY_SUPPORT\n   /* mandates presence of <sys/resource.h> and support for setpriority() : http://man7.org/linux/man-pages/man2/setpriority.2.html */\n#  define ZSTD_SETPRIORITY_SUPPORT (PLATFORM_POSIX_VERSION >= 200112L)\n#endif\n\n\n#ifndef ZSTD_NANOSLEEP_SUPPORT\n   /* mandates support of nanosleep() within <time.h> : http://man7.org/linux/man-pages/man2/nanosleep.2.html */\n#  if (defined(__linux__) && (PLATFORM_POSIX_VERSION >= 199309L)) \\\n   || (PLATFORM_POSIX_VERSION >= 200112L)\n#     define ZSTD_NANOSLEEP_SUPPORT 1\n#  else\n#     define ZSTD_NANOSLEEP_SUPPORT 0\n#  endif\n#endif\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* PLATFORM_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/radix_bitpack.c",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#include \"mem.h\"          /* U32, U64 */\n#include \"fl2_threading.h\"\n#include \"fl2_internal.h\"\n#include \"radix_internal.h\"\n\n#undef MIN\n#define MIN(a,b) ((a) < (b) ? (a) : (b))\n\n#define RMF_BITPACK\n\n#define RADIX_MAX_LENGTH BITPACK_MAX_LENGTH\n\n#define InitMatchLink(pos, link) tbl->table[pos] = link\n\n#define GetMatchLink(link) (tbl->table[link] & RADIX_LINK_MASK)\n\n#define GetInitialMatchLink(pos) tbl->table[pos]\n\n#define GetMatchLength(pos) (tbl->table[pos] >> RADIX_LINK_BITS)\n\n#define SetMatchLink(pos, link, length) tbl->table[pos] = (link) | ((U32)(length) << RADIX_LINK_BITS)\n\n#define SetMatchLength(pos, link, length) tbl->table[pos] = (link) | ((U32)(length) << RADIX_LINK_BITS)\n\n#define SetMatchLinkAndLength(pos, link, length) tbl->table[pos] = (link) | ((U32)(length) << RADIX_LINK_BITS)\n\n#define SetNull(pos) tbl->table[pos] = RADIX_NULL_LINK\n\n#define IsNull(pos) (tbl->table[pos] == RADIX_NULL_LINK)\n\nBYTE* RMF_bitpackAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos)\n{\n    return (BYTE*)(tbl->table + pos);\n}\n\n/* Restrict the match lengths so that they don't reach beyond pos */\nvoid RMF_bitpackLimitLengths(FL2_matchTable* const tbl, size_t const pos)\n{\n    DEBUGLOG(5, \"RMF_limitLengths : end %u, max length %u\", (U32)pos, RADIX_MAX_LENGTH);\n    SetNull(pos - 1);\n    for (U32 length = 2; length < RADIX_MAX_LENGTH && length <= pos; ++length) {\n        U32 const link = tbl->table[pos - length];\n        if (link != RADIX_NULL_LINK)\n            tbl->table[pos - length] = (MIN(length, link >> RADIX_LINK_BITS) << RADIX_LINK_BITS) | (link & RADIX_LINK_MASK);\n    }\n}\n\n#include \"radix_engine.h\""
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/radix_engine.h",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#include <stdio.h>  \n\n#define MAX_READ_BEYOND_DEPTH 2\n\n/* If a repeating byte is found, fill that section of the table with matches of distance 1 */\nstatic size_t RMF_handleRepeat(RMF_builder* const tbl, const BYTE* const data_block, size_t const start, ptrdiff_t i, U32 depth)\n{\n    /* Normally the last 2 bytes, but may be 4 if depth == 4 */\n    ptrdiff_t const last_2 = i + MAX_REPEAT / 2 - 1;\n\n    /* Find the start */\n    i += (4 - (i & 3)) & 3;\n    U32 u = *(U32*)(data_block + i);\n    while (i != 0 && *(U32*)(data_block + i - 4) == u)\n      i -= 4;\n    while (i != 0 && data_block[i - 1] == (BYTE)u)\n      --i;\n\n    ptrdiff_t const rpt_index = i;\n    /* No point if it's in the overlap region */\n    if (last_2 >= (ptrdiff_t)start) {\n        U32 len = depth;\n        /* Set matches at distance 1 and available length */\n        for (i = last_2; i > rpt_index && len <= RADIX_MAX_LENGTH; --i) {\n            SetMatchLinkAndLength(i, (U32)(i - 1), len);\n            ++len;\n        }\n        /* Set matches at distance 1 and max length */\n        for (; i > rpt_index; --i)\n            SetMatchLinkAndLength(i, (U32)(i - 1), RADIX_MAX_LENGTH);\n    }\n    return rpt_index;\n}\n\n/* If a 2-byte repeat is found, fill that section of the table with matches of distance 2 */\nstatic size_t RMF_handleRepeat2(RMF_builder* const tbl, const BYTE* const data_block, size_t const start, ptrdiff_t i, U32 depth)\n{\n    /* Normally the last 2 bytes, but may be 4 if depth == 4 */\n    ptrdiff_t const last_2 = i + MAX_REPEAT * 2U - 4;\n\n    /* Find the start */\n    ptrdiff_t realign = i & 1;\n    i += (4 - (i & 3)) & 3;\n    U32 u = *(U32*)(data_block + i);\n    while (i != 0 && *(U32*)(data_block + i - 4) == u)\n        i -= 4;\n    while (i != 0 && data_block[i - 1] == data_block[i + 1])\n        --i;\n    i += (i & 1) ^ realign;\n\n    ptrdiff_t const rpt_index = i;\n    /* No point if it's in the overlap region */\n    if (i >= (ptrdiff_t)start) {\n        U32 len = depth + (data_block[last_2 + depth] == data_block[last_2]);\n        /* Set matches at distance 2 and available length */\n        for (i = last_2; i > rpt_index && len <= RADIX_MAX_LENGTH; i -= 2) {\n            SetMatchLinkAndLength(i, (U32)(i - 2), len);\n            len += 2;\n        }\n        /* Set matches at distance 2 and max length */\n        for (; i > rpt_index; i -= 2)\n            SetMatchLinkAndLength(i, (U32)(i - 2), RADIX_MAX_LENGTH);\n    }\n    return rpt_index;\n}\n\n/* Initialization for the reference algortithm */\n#ifdef RMF_REFERENCE\nstatic void RMF_initReference(FL2_matchTable* const tbl, const void* const data, size_t const end)\n{\n    const BYTE* const data_block = (const BYTE*)data;\n    ptrdiff_t const block_size = end - 1;\n    size_t st_index = 0;\n    for (ptrdiff_t i = 0; i < block_size; ++i)\n    {\n        size_t const radix_16 = ((size_t)data_block[i] << 8) | data_block[i + 1];\n        U32 const prev = tbl->list_heads[radix_16].head;\n        if (prev != RADIX_NULL_LINK) {\n            SetMatchLinkAndLength(i, prev, 2U);\n            tbl->list_heads[radix_16].head = (U32)i;\n            ++tbl->list_heads[radix_16].count;\n        }\n        else {\n            SetNull(i);\n            tbl->list_heads[radix_16].head = (U32)i;\n            tbl->list_heads[radix_16].count = 1;\n            tbl->stack[st_index++] = (U32)radix_16;\n        }\n    }\n    SetNull(end - 1);\n    tbl->end_index = (U32)st_index;\n    tbl->st_index = ATOMIC_INITIAL_VALUE;\n}\n#endif\n\nvoid\n#ifdef RMF_BITPACK\nRMF_bitpackInit\n#else\nRMF_structuredInit\n#endif\n(FL2_matchTable* const tbl, const void* const data, size_t const end)\n{\n    if (end <= 2) {\n        for (size_t i = 0; i < end; ++i)\n            SetNull(i);\n        tbl->end_index = 0;\n        return;\n    }\n#ifdef RMF_REFERENCE\n    if (tbl->params.use_ref_mf) {\n        RMF_initReference(tbl, data, end);\n        return;\n    }\n#endif\n\n    SetNull(0);\n\n    const BYTE* const data_block = (const BYTE*)data;\n    size_t st_index = 0;\n    /* Initial 2-byte radix value */\n    size_t radix_16 = ((size_t)data_block[0] << 8) | data_block[1];\n    tbl->stack[st_index++] = (U32)radix_16;\n    tbl->list_heads[radix_16].head = 0;\n    tbl->list_heads[radix_16].count = 1;\n\n    radix_16 = ((size_t)((BYTE)radix_16) << 8) | data_block[2];\n\n    ptrdiff_t i = 1;\n    ptrdiff_t const block_size = end - 2;\n    for (; i < block_size; ++i) {\n        /* Pre-load the next value for speed increase on some hardware. Execution can continue while memory read is pending */\n        size_t const next_radix = ((size_t)((BYTE)radix_16) << 8) | data_block[i + 2];\n\n        U32 const prev = tbl->list_heads[radix_16].head;\n        if (prev != RADIX_NULL_LINK) {\n            /* Link this position to the previous occurrence */\n            InitMatchLink(i, prev);\n            /* Set the previous to this position */\n            tbl->list_heads[radix_16].head = (U32)i;\n            ++tbl->list_heads[radix_16].count;\n            radix_16 = next_radix;\n        }\n        else {\n            SetNull(i);\n            tbl->list_heads[radix_16].head = (U32)i;\n            tbl->list_heads[radix_16].count = 1;\n            tbl->stack[st_index++] = (U32)radix_16;\n            radix_16 = next_radix;\n        }\n    }\n    /* Handle the last value */\n    if (tbl->list_heads[radix_16].head != RADIX_NULL_LINK)\n        SetMatchLinkAndLength(block_size, tbl->list_heads[radix_16].head, 2);\n    else\n        SetNull(block_size);\n\n    /* Never a match at the last byte */\n    SetNull(end - 1);\n\n    tbl->end_index = (U32)st_index;\n}\n\n/* Copy the list into a buffer and recurse it there. This decreases cache misses and allows */\n/* data characters to be loaded every fourth pass and stored for use in the next 4 passes */\nstatic void RMF_recurseListsBuffered(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t const block_end,\n    size_t link,\n    U32 depth,\n    U32 const max_depth,\n    U32 orig_list_count,\n    size_t const stack_base)\n{\n    if (orig_list_count < 2 || tbl->match_buffer_limit < 2)\n        return;\n\n    /* Create an offset data buffer pointer for reading the next bytes */\n    const BYTE* data_src = data_block + depth;\n    size_t start = 0;\n\n    do {\n        U32 list_count = (U32)(start + orig_list_count);\n\n        if (list_count > tbl->match_buffer_limit)\n            list_count = (U32)tbl->match_buffer_limit;\n\n        size_t count = start;\n        size_t prev_link = (size_t)-1;\n        size_t rpt = 0;\n        size_t rpt_tail = link;\n        for (; count < list_count; ++count) {\n            /* Pre-load next link */\n            size_t const next_link = GetMatchLink(link);\n            size_t dist = prev_link - link;\n            if (dist > 2) {\n                /* Get 4 data characters for later. This doesn't block on a cache miss. */\n                tbl->match_buffer[count].src.u32 = MEM_read32(data_src + link);\n                /* Record the actual location of this suffix */\n                tbl->match_buffer[count].from = (U32)link;\n                /* Initialize the next link */\n                tbl->match_buffer[count].next = (U32)(count + 1) | (depth << 24);\n                rpt = 0;\n                prev_link = link;\n                rpt_tail = link;\n                link = next_link;\n            }\n            else {\n                rpt += 3 - dist;\n                /* Do the usual if the repeat is too short */\n                if (rpt < MAX_REPEAT - 2) {\n                    /* Get 4 data characters for later. This doesn't block on a cache miss. */\n                    tbl->match_buffer[count].src.u32 = MEM_read32(data_src + link);\n                    /* Record the actual location of this suffix */\n                    tbl->match_buffer[count].from = (U32)link;\n                    /* Initialize the next link */\n                    tbl->match_buffer[count].next = (U32)(count + 1) | (depth << 24);\n                    prev_link = link;\n                    link = next_link;\n                }\n                else {\n                    /* Eliminate the repeat from the linked list to save time */\n                    if (dist == 1) {\n                        link = RMF_handleRepeat(tbl, data_block, block_start, link, depth);\n                        count -= MAX_REPEAT / 2;\n                        orig_list_count -= (U32)(rpt_tail - link);\n                    }\n                    else {\n                        link = RMF_handleRepeat2(tbl, data_block, block_start, link, depth);\n                        count -= MAX_REPEAT - 1;\n                        orig_list_count -= (U32)(rpt_tail - link) >> 1;\n                    }\n                    rpt = 0;\n                    list_count = (U32)(start + orig_list_count);\n\n                    if (list_count > tbl->match_buffer_limit)\n                        list_count = (U32)tbl->match_buffer_limit;\n                }\n            }\n        }\n        count = list_count;\n        /* Make the last element circular so pre-loading doesn't read past the end. */\n        tbl->match_buffer[count - 1].next = (U32)(count - 1) | (depth << 24);\n        U32 overlap = 0;\n        if (list_count < (U32)(start + orig_list_count)) {\n            overlap = list_count >> MATCH_BUFFER_OVERLAP;\n            overlap += !overlap;\n        }\n        RMF_recurseListChunk(tbl, data_block, block_start, block_end, depth, max_depth, list_count, stack_base);\n        orig_list_count -= (U32)(list_count - start);\n        /* Copy everything back, except the last link which never changes, and any extra overlap */\n        count -= overlap + (overlap == 0);\n#ifdef RMF_BITPACK\n        if (max_depth > RADIX_MAX_LENGTH) for (size_t pos = 0; pos < count; ++pos) {\n            size_t const from = tbl->match_buffer[pos].from;\n            if (from < block_start)\n                return;\n            U32 length = tbl->match_buffer[pos].next >> 24;\n            length = (length > RADIX_MAX_LENGTH) ? RADIX_MAX_LENGTH : length;\n            size_t const next = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n            SetMatchLinkAndLength(from, tbl->match_buffer[next].from, length);\n        }\n        else\n#endif\n            for (size_t pos = 0; pos < count; ++pos) {\n            size_t const from = tbl->match_buffer[pos].from;\n            if (from < block_start)\n                return;\n            U32 const length = tbl->match_buffer[pos].next >> 24;\n            size_t const next = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n            SetMatchLinkAndLength(from, tbl->match_buffer[next].from, length);\n        }\n        start = 0;\n        if (overlap) {\n            size_t dest = 0;\n            for (size_t src = list_count - overlap; src < list_count; ++src) {\n                tbl->match_buffer[dest].from = tbl->match_buffer[src].from;\n                tbl->match_buffer[dest].src.u32 = MEM_read32(data_src + tbl->match_buffer[src].from);\n                tbl->match_buffer[dest].next = (U32)(dest + 1) | (depth << 24);\n                ++dest;\n            }\n            start = dest;\n        }\n    } while (orig_list_count != 0);\n}\n\n/* Parse the list with an upper bound check on data reads. Stop at the point where bound checks are not required. */\n/* Buffering is used so that parsing can continue below the bound to find a few matches without altering the main table. */\nstatic void RMF_recurseListsBound(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    ptrdiff_t const block_size,\n    RMF_tableHead* const list_head,\n    U32 max_depth)\n{\n    U32 list_count = list_head->count;\n    if (list_count < 2)\n        return;\n\n    ptrdiff_t link = list_head->head;\n    ptrdiff_t const bounded_size = max_depth + MAX_READ_BEYOND_DEPTH;\n    ptrdiff_t const bounded_start = block_size - MIN(block_size, bounded_size);\n    size_t count = 0;\n    size_t extra_count = (max_depth >> 4) + 4;\n\n    list_count = MIN((U32)bounded_size, list_count);\n    list_count = MIN(list_count, (U32)tbl->match_buffer_size);\n    for (; count < list_count && extra_count; ++count) {\n        ptrdiff_t next_link = GetMatchLink(link);\n        if (link >= bounded_start) {\n            --list_head->count;\n            if (next_link < bounded_start)\n                list_head->head = (U32)next_link;\n        }\n        else {\n            --extra_count;\n        }\n        /* Record the actual location of this suffix */\n        tbl->match_buffer[count].from = (U32)link;\n        /* Initialize the next link */\n        tbl->match_buffer[count].next = (U32)(count + 1) | ((U32)2 << 24);\n        link = next_link;\n    }\n    list_count = (U32)count;\n    ptrdiff_t limit = block_size - 2;\n    /* Create an offset data buffer pointer for reading the next bytes */\n    const BYTE* data_src = data_block + 2;\n    U32 depth = 3;\n    size_t pos = 0;\n    size_t st_index = 0;\n    RMF_listTail* const tails_8 = tbl->tails_8;\n    do {\n        link = tbl->match_buffer[pos].from;\n        if (link < limit) {\n            size_t const radix_8 = data_src[link];\n            /* Seen this char before? */\n            U32 const prev = tails_8[radix_8].prev_index;\n            tails_8[radix_8].prev_index = (U32)pos;\n            if (prev != RADIX_NULL_LINK) {\n                ++tails_8[radix_8].list_count;\n                /* Link the previous occurrence to this one and record the new length */\n                tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n            }\n            else {\n                tails_8[radix_8].list_count = 1;\n                /* Add the new sub list to the stack */\n                tbl->stack[st_index].head = (U32)pos;\n                /* This will be converted to a count at the end */\n                tbl->stack[st_index].count = (U32)radix_8;\n                ++st_index;\n            }\n        }\n        ++pos;\n    } while (pos < list_count);\n    /* Convert radix values on the stack to counts and reset any used tail slots */\n    for (size_t j = 0; j < st_index; ++j) {\n        tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;\n        tbl->stack[j].count = tails_8[tbl->stack[j].count].list_count;\n    }\n    while (st_index > 0) {\n        size_t prev_st_index;\n\n        /* Pop an item off the stack */\n        --st_index;\n        list_count = tbl->stack[st_index].count;\n        if (list_count < 2) /* Nothing to match with */\n            continue;\n\n        pos = tbl->stack[st_index].head;\n        depth = (tbl->match_buffer[pos].next >> 24);\n        if (depth >= max_depth)\n            continue;\n        link = tbl->match_buffer[pos].from;\n        if (link < bounded_start) {\n            /* Chain starts before the bounded region */\n            continue;\n        }\n        data_src = data_block + depth;\n        limit = block_size - depth;\n        ++depth;\n        prev_st_index = st_index;\n        do {\n            link = tbl->match_buffer[pos].from;\n            if (link < limit) {\n                size_t const radix_8 = data_src[link];\n                U32 const prev = tails_8[radix_8].prev_index;\n                tails_8[radix_8].prev_index = (U32)pos;\n                if (prev != RADIX_NULL_LINK) {\n                    ++tails_8[radix_8].list_count;\n                    tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n                }\n                else {\n                    tails_8[radix_8].list_count = 1;\n                    tbl->stack[st_index].head = (U32)pos;\n                    tbl->stack[st_index].count = (U32)radix_8;\n                    ++st_index;\n                }\n            }\n            pos = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n        } while (--list_count != 0);\n        for (size_t j = prev_st_index; j < st_index; ++j) {\n            tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;\n            tbl->stack[j].count = tails_8[tbl->stack[j].count].list_count;\n        }\n    }\n    /* Copy everything back above the bound */\n    --count;\n    for (pos = 0; pos < count; ++pos) {\n        ptrdiff_t const from = tbl->match_buffer[pos].from;\n        if (from < bounded_start)\n            break;\n\n        U32 length = tbl->match_buffer[pos].next >> 24;\n        length = MIN(length, (U32)(block_size - from));\n        length = MIN(length, RADIX_MAX_LENGTH);\n\n        size_t const next = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n        SetMatchLinkAndLength(from, tbl->match_buffer[next].from, length);\n    }\n}\n\n/* Compare each string with all others to find the best match */\nstatic void RMF_bruteForce(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t link,\n    size_t const list_count,\n    U32 const depth,\n    U32 const max_depth)\n{\n    const BYTE* data_src = data_block + depth;\n    size_t buffer[MAX_BRUTE_FORCE_LIST_SIZE + 1];\n    size_t const limit = max_depth - depth;\n    size_t i = 1;\n\n    buffer[0] = link;\n    /* Pre-load all locations */\n    do {\n        link = GetMatchLink(link);\n        buffer[i] = link;\n    } while (++i < list_count);\n\n    i = 0;\n    do {\n        size_t longest = 0;\n        size_t j = i + 1;\n        size_t longest_index = j;\n        const BYTE* const data = data_src + buffer[i];\n        do {\n            const BYTE* data_2 = data_src + buffer[j];\n            size_t len_test = 0;\n            while (data[len_test] == data_2[len_test] && len_test < limit)\n                ++len_test;\n\n            if (len_test > longest) {\n                longest_index = j;\n                longest = len_test;\n                if (len_test >= limit)\n                    break;\n            }\n        } while (++j < list_count);\n\n        if (longest > 0)\n            SetMatchLinkAndLength(buffer[i], (U32)buffer[longest_index], depth + (U32)longest);\n\n        ++i;\n    /* Test with block_start to avoid wasting time matching strings in the overlap region with each other */\n    } while (i < list_count - 1 && buffer[i] >= block_start);\n}\n\n/* RMF_recurseLists16() : \n * Match strings at depth 2 using a 16-bit radix to lengthen to depth 4\n */\nstatic void RMF_recurseLists16(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t const block_end,\n    size_t link,\n    U32 count,\n    U32 const max_depth)\n{\n    U32 const table_max_depth = MIN(max_depth, RADIX_MAX_LENGTH);\n    /* Offset data pointer. This function is only called at depth 2 */\n    const BYTE* const data_src = data_block + 2;\n    /* Load radix values from the data chars */\n    size_t next_radix_8 = data_src[link];\n    size_t next_radix_16 = next_radix_8 + ((size_t)(data_src[link + 1]) << 8);\n    size_t reset_list[RADIX8_TABLE_SIZE];\n    size_t reset_count = 0;\n    size_t st_index = 0;\n    /* Last one is done separately */\n    --count;\n    do\n    {\n        /* Pre-load the next link */\n        size_t const next_link = GetInitialMatchLink(link);\n        size_t const radix_8 = next_radix_8;\n        size_t const radix_16 = next_radix_16;\n        /* Initialization doesn't set lengths to 2 because it's a waste of time if buffering is used */\n        SetMatchLength(link, (U32)next_link, 2);\n\n        next_radix_8 = data_src[next_link];\n        next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);\n\n        U32 prev = tbl->tails_8[radix_8].prev_index;\n        tbl->tails_8[radix_8].prev_index = (U32)link;\n        if (prev != RADIX_NULL_LINK) {\n            /* Link the previous occurrence to this one at length 3. */\n            /* This will be overwritten if a 4 is found. */\n            SetMatchLinkAndLength(prev, (U32)link, 3);\n        }\n        else {\n            reset_list[reset_count++] = radix_8;\n        }\n\n        prev = tbl->tails_16[radix_16].prev_index;\n        tbl->tails_16[radix_16].prev_index = (U32)link;\n        if (prev != RADIX_NULL_LINK) {\n            ++tbl->tails_16[radix_16].list_count;\n            /* Link at length 4, overwriting the 3 */\n            SetMatchLinkAndLength(prev, (U32)link, 4);\n        }\n        else {\n            tbl->tails_16[radix_16].list_count = 1;\n            tbl->stack[st_index].head = (U32)link;\n            /* Store a reference to this table location to retrieve the count at the end */\n            tbl->stack[st_index].count = (U32)radix_16;\n            ++st_index;\n        }\n        link = next_link;\n    } while (--count > 0);\n\n    /* Do the last location */\n    U32 prev = tbl->tails_8[next_radix_8].prev_index;\n    if (prev != RADIX_NULL_LINK)\n        SetMatchLinkAndLength(prev, (U32)link, 3);\n\n    prev = tbl->tails_16[next_radix_16].prev_index;\n    if (prev != RADIX_NULL_LINK) {\n        ++tbl->tails_16[next_radix_16].list_count;\n        SetMatchLinkAndLength(prev, (U32)link, 4);\n    }\n\n    for (size_t i = 0; i < reset_count; ++i)\n        tbl->tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;\n\n    for (size_t i = 0; i < st_index; ++i) {\n        tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;\n        tbl->stack[i].count = tbl->tails_16[tbl->stack[i].count].list_count;\n    }\n\n    while (st_index > 0) {\n        --st_index;\n        U32 const list_count = tbl->stack[st_index].count;\n        if (list_count < 2) {\n            /* Nothing to do */\n            continue;\n        }\n        link = tbl->stack[st_index].head;\n        if (link < block_start)\n            continue;\n        if (st_index > STACK_SIZE - RADIX16_TABLE_SIZE\n            && st_index > STACK_SIZE - list_count)\n        {\n            /* Potential stack overflow. Rare. */\n            continue;\n        }\n        /* The current depth */\n        U32 const depth = GetMatchLength(link);\n        if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE) {\n            /* Quicker to use brute force, each string compared with all previous strings */\n            RMF_bruteForce(tbl, data_block,\n                block_start,\n                link,\n                list_count,\n                depth,\n                table_max_depth);\n            continue;\n        }\n        /* Send to the buffer at depth 4 */\n        RMF_recurseListsBuffered(tbl,\n            data_block,\n            block_start,\n            block_end,\n            link,\n            (BYTE)depth,\n            (BYTE)max_depth,\n            list_count,\n            st_index);\n    }\n}\n\n#if 0\n/* Unbuffered complete processing to max_depth.\n * This may be faster on CPUs without a large memory cache.\n */\nstatic void RMF_recurseListsUnbuf16(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t link,\n    U32 count,\n    U32 const max_depth)\n{\n    /* Offset data pointer. This method is only called at depth 2 */\n    const BYTE* data_src = data_block + 2;\n    /* Load radix values from the data chars */\n    size_t next_radix_8 = data_src[link];\n    size_t next_radix_16 = next_radix_8 + ((size_t)(data_src[link + 1]) << 8);\n    RMF_listTail* tails_8 = tbl->tails_8;\n    size_t reset_list[RADIX8_TABLE_SIZE];\n    size_t reset_count = 0;\n    size_t st_index = 0;\n    /* Last one is done separately */\n    --count;\n    do\n    {\n        /* Pre-load the next link */\n        size_t next_link = GetInitialMatchLink(link);\n        /* Initialization doesn't set lengths to 2 because it's a waste of time if buffering is used */\n        SetMatchLength(link, (U32)next_link, 2);\n        size_t radix_8 = next_radix_8;\n        size_t radix_16 = next_radix_16;\n        next_radix_8 = data_src[next_link];\n        next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);\n        U32 prev = tails_8[radix_8].prev_index;\n        if (prev != RADIX_NULL_LINK) {\n            /* Link the previous occurrence to this one at length 3. */\n            /* This will be overwritten if a 4 is found. */\n            SetMatchLinkAndLength(prev, (U32)link, 3);\n        }\n        else {\n            reset_list[reset_count++] = radix_8;\n        }\n        tails_8[radix_8].prev_index = (U32)link;\n        prev = tbl->tails_16[radix_16].prev_index;\n        if (prev != RADIX_NULL_LINK) {\n            ++tbl->tails_16[radix_16].list_count;\n            /* Link at length 4, overwriting the 3 */\n            SetMatchLinkAndLength(prev, (U32)link, 4);\n        }\n        else {\n            tbl->tails_16[radix_16].list_count = 1;\n            tbl->stack[st_index].head = (U32)link;\n            tbl->stack[st_index].count = (U32)radix_16;\n            ++st_index;\n        }\n        tbl->tails_16[radix_16].prev_index = (U32)link;\n        link = next_link;\n    } while (--count > 0);\n    /* Do the last location */\n    U32 prev = tails_8[next_radix_8].prev_index;\n    if (prev != RADIX_NULL_LINK) {\n        SetMatchLinkAndLength(prev, (U32)link, 3);\n    }\n    prev = tbl->tails_16[next_radix_16].prev_index;\n    if (prev != RADIX_NULL_LINK) {\n        ++tbl->tails_16[next_radix_16].list_count;\n        SetMatchLinkAndLength(prev, (U32)link, 4);\n    }\n    for (size_t i = 0; i < reset_count; ++i) {\n        tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;\n    }\n    reset_count = 0;\n    for (size_t i = 0; i < st_index; ++i) {\n        tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;\n        tbl->stack[i].count = tbl->tails_16[tbl->stack[i].count].list_count;\n    }\n    while (st_index > 0) {\n        --st_index;\n        U32 list_count = tbl->stack[st_index].count;\n        if (list_count < 2) {\n            /* Nothing to do */\n            continue;\n        }\n        link = tbl->stack[st_index].head;\n        if (link < block_start)\n            continue;\n        if (st_index > STACK_SIZE - RADIX16_TABLE_SIZE\n            && st_index > STACK_SIZE - list_count)\n        {\n            /* Potential stack overflow. Rare. */\n            continue;\n        }\n        /* The current depth */\n        U32 depth = GetMatchLength(link);\n        if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE) {\n            /* Quicker to use brute force, each string compared with all previous strings */\n            RMF_bruteForce(tbl, data_block,\n                block_start,\n                link,\n                list_count,\n                depth,\n                max_depth);\n            continue;\n        }\n        const BYTE* data_src = data_block + depth;\n        size_t next_radix_8 = data_src[link];\n        size_t next_radix_16 = next_radix_8 + ((size_t)(data_src[link + 1]) << 8);\n        /* Next depth for 1 extra char */\n        ++depth;\n        /* and for 2 */\n        U32 depth_2 = depth + 1;\n        size_t prev_st_index = st_index;\n        /* Last location is done separately */\n        --list_count;\n        /* Last pass is done separately. Both of these values are always even. */\n        if (depth_2 < max_depth) {\n            do {\n                size_t radix_8 = next_radix_8;\n                size_t radix_16 = next_radix_16;\n                size_t next_link = GetMatchLink(link);\n                next_radix_8 = data_src[next_link];\n                next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);\n                size_t prev = tbl->tails_8[radix_8].prev_index;\n                if (prev != RADIX_NULL_LINK) {\n                    /* Odd numbered match length, will be overwritten if 2 chars are matched */\n                    SetMatchLinkAndLength(prev, (U32)(link), depth);\n                }\n                else {\n                    reset_list[reset_count++] = radix_8;\n                }\n                tbl->tails_8[radix_8].prev_index = (U32)link;\n                prev = tbl->tails_16[radix_16].prev_index;\n                if (prev != RADIX_NULL_LINK) {\n                    ++tbl->tails_16[radix_16].list_count;\n                    SetMatchLinkAndLength(prev, (U32)(link), depth_2);\n                }\n                else {\n                    tbl->tails_16[radix_16].list_count = 1;\n                    tbl->stack[st_index].head = (U32)(link);\n                    tbl->stack[st_index].count = (U32)(radix_16);\n                    ++st_index;\n                }\n                tbl->tails_16[radix_16].prev_index = (U32)(link);\n                link = next_link;\n            } while (--list_count != 0);\n            size_t prev = tbl->tails_8[next_radix_8].prev_index;\n            if (prev != RADIX_NULL_LINK) {\n                SetMatchLinkAndLength(prev, (U32)(link), depth);\n            }\n            prev = tbl->tails_16[next_radix_16].prev_index;\n            if (prev != RADIX_NULL_LINK) {\n                ++tbl->tails_16[next_radix_16].list_count;\n                SetMatchLinkAndLength(prev, (U32)(link), depth_2);\n            }\n            for (size_t i = prev_st_index; i < st_index; ++i) {\n                tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;\n                tbl->stack[i].count = tbl->tails_16[tbl->stack[i].count].list_count;\n            }\n            for (size_t i = 0; i < reset_count; ++i) {\n                tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;\n            }\n            reset_count = 0;\n        }\n        else {\n            do {\n                size_t radix_8 = next_radix_8;\n                size_t radix_16 = next_radix_16;\n                size_t next_link = GetMatchLink(link);\n                next_radix_8 = data_src[next_link];\n                next_radix_16 = next_radix_8 + ((size_t)(data_src[next_link + 1]) << 8);\n                size_t prev = tbl->tails_8[radix_8].prev_index;\n                if (prev != RADIX_NULL_LINK) {\n                    SetMatchLinkAndLength(prev, (U32)(link), depth);\n                }\n                else {\n                    reset_list[reset_count++] = radix_8;\n                }\n                tbl->tails_8[radix_8].prev_index = (U32)link;\n                prev = tbl->tails_16[radix_16].prev_index;\n                if (prev != RADIX_NULL_LINK) {\n                    SetMatchLinkAndLength(prev, (U32)(link), depth_2);\n                }\n                else {\n                    tbl->stack[st_index].count = (U32)radix_16;\n                    ++st_index;\n                }\n                tbl->tails_16[radix_16].prev_index = (U32)(link);\n                link = next_link;\n            } while (--list_count != 0);\n            size_t prev = tbl->tails_8[next_radix_8].prev_index;\n            if (prev != RADIX_NULL_LINK) {\n                SetMatchLinkAndLength(prev, (U32)(link), depth);\n            }\n            prev = tbl->tails_16[next_radix_16].prev_index;\n            if (prev != RADIX_NULL_LINK) {\n                SetMatchLinkAndLength(prev, (U32)(link), depth_2);\n            }\n            for (size_t i = prev_st_index; i < st_index; ++i) {\n                tbl->tails_16[tbl->stack[i].count].prev_index = RADIX_NULL_LINK;\n            }\n            st_index = prev_st_index;\n            for (size_t i = 0; i < reset_count; ++i) {\n                tails_8[reset_list[i]].prev_index = RADIX_NULL_LINK;\n            }\n            reset_count = 0;\n        }\n    }\n}\n#endif\n\n#ifdef RMF_REFERENCE\n\n/* Simple, slow, complete parsing for reference */\nstatic void RMF_recurseListsReference(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_size,\n    size_t link,\n    U32 count,\n    U32 const max_depth)\n{\n    /* Offset data pointer. This method is only called at depth 2 */\n    const BYTE* data_src = data_block + 2;\n    size_t limit = block_size - 2;\n    size_t st_index = 0;\n\n    do\n    {\n        if (link < limit) {\n            size_t const radix_8 = data_src[link];\n            size_t const prev = tbl->tails_8[radix_8].prev_index;\n            if (prev != RADIX_NULL_LINK) {\n                ++tbl->tails_8[radix_8].list_count;\n                SetMatchLinkAndLength(prev, (U32)link, 3);\n            }\n            else {\n                tbl->tails_8[radix_8].list_count = 1;\n                tbl->stack[st_index].head = (U32)link;\n                tbl->stack[st_index].count = (U32)radix_8;\n                ++st_index;\n            }\n            tbl->tails_8[radix_8].prev_index = (U32)link;\n        }\n        link = GetMatchLink(link);\n    } while (--count > 0);\n    for (size_t i = 0; i < st_index; ++i) {\n        tbl->stack[i].count = tbl->tails_8[tbl->stack[i].count].list_count;\n    }\n    memset(tbl->tails_8, 0xFF, sizeof(tbl->tails_8));\n    while (st_index > 0) {\n        --st_index;\n        U32 list_count = tbl->stack[st_index].count;\n        if (list_count < 2) {\n            /* Nothing to do */\n            continue;\n        }\n        if (st_index > STACK_SIZE - RADIX8_TABLE_SIZE\n            && st_index > STACK_SIZE - list_count)\n        {\n            /* Potential stack overflow. Rare. */\n            continue;\n        }\n        link = tbl->stack[st_index].head;\n        /* The current depth */\n        U32 depth = GetMatchLength(link);\n        if (depth >= max_depth)\n            continue;\n        data_src = data_block + depth;\n        limit = block_size - depth;\n        /* Next depth for 1 extra char */\n        ++depth;\n        size_t prev_st_index = st_index;\n        do {\n            if (link < limit) {\n                size_t const radix_8 = data_src[link];\n                size_t const prev = tbl->tails_8[radix_8].prev_index;\n                if (prev != RADIX_NULL_LINK) {\n                    ++tbl->tails_8[radix_8].list_count;\n                    SetMatchLinkAndLength(prev, (U32)link, depth);\n                }\n                else {\n                    tbl->tails_8[radix_8].list_count = 1;\n                    tbl->stack[st_index].head = (U32)link;\n                    tbl->stack[st_index].count = (U32)radix_8;\n                    ++st_index;\n                }\n                tbl->tails_8[radix_8].prev_index = (U32)link;\n            }\n            link = GetMatchLink(link);\n        } while (--list_count != 0);\n        for (size_t i = prev_st_index; i < st_index; ++i) {\n            tbl->stack[i].count = tbl->tails_8[tbl->stack[i].count].list_count;\n        }\n        memset(tbl->tails_8, 0xFF, sizeof(tbl->tails_8));\n    }\n}\n\n#endif /* RMF_REFERENCE */\n\n/* Atomically take a list from the head table */\nstatic ptrdiff_t RMF_getNextList_mt(FL2_matchTable* const tbl)\n{\n    if (tbl->st_index < tbl->end_index) {\n        long pos = FL2_atomic_increment(tbl->st_index);\n        if (pos < tbl->end_index)\n            return pos;\n    }\n    return -1;\n}\n\n/* Non-atomically take a list from the head table */\nstatic ptrdiff_t RMF_getNextList_st(FL2_matchTable* const tbl)\n{\n    if (tbl->st_index < tbl->end_index) {\n        long pos = FL2_nonAtomic_increment(tbl->st_index);\n        if (pos < tbl->end_index)\n            return pos;\n    }\n    return -1;\n}\n\n/* Iterate the head table concurrently with other threads, and recurse each list until max_depth is reached */\nvoid\n#ifdef RMF_BITPACK\nRMF_bitpackBuildTable\n#else\nRMF_structuredBuildTable\n#endif\n(FL2_matchTable* const tbl,\n    size_t const job,\n    unsigned const multi_thread,\n    FL2_dataBlock const block)\n{\n    if (block.end == 0)\n        return;\n\n    unsigned const best = !tbl->params.divide_and_conquer;\n    unsigned const max_depth = MIN(tbl->params.depth, STRUCTURED_MAX_LENGTH) & ~1;\n    size_t bounded_start = max_depth + MAX_READ_BEYOND_DEPTH;\n    bounded_start = block.end - MIN(block.end, bounded_start);\n    ptrdiff_t next_progress = (job == 0) ? 0 : RADIX16_TABLE_SIZE;\n    ptrdiff_t(*getNextList)(FL2_matchTable* const tbl)\n        = multi_thread ? RMF_getNextList_mt : RMF_getNextList_st;\n\n    for (;;)\n    {\n        /* Get the next to process */\n        ptrdiff_t pos = getNextList(tbl);\n\n        if (pos < 0)\n            break;\n\n        while (next_progress < pos) {\n            /* initial value of next_progress ensures only thread 0 executes this */\n            tbl->progress += tbl->list_heads[tbl->stack[next_progress]].count;\n            ++next_progress;\n        }\n        pos = tbl->stack[pos];\n        RMF_tableHead list_head = tbl->list_heads[pos];\n        tbl->list_heads[pos].head = RADIX_NULL_LINK;\n        if (list_head.count < 2 || list_head.head < block.start)\n            continue;\n\n#ifdef RMF_REFERENCE\n        if (tbl->params.use_ref_mf) {\n            RMF_recurseListsReference(tbl->builders[job], block.data, block.end, list_head.head, list_head.count, max_depth);\n            continue;\n        }\n#endif\n        if (list_head.head >= bounded_start) {\n            RMF_recurseListsBound(tbl->builders[job], block.data, block.end, &list_head, max_depth);\n            if (list_head.count < 2 || list_head.head < block.start)\n                continue;\n        }\n        if (best && list_head.count > tbl->builders[job]->match_buffer_limit)\n        {\n            /* Not worth buffering or too long */\n            RMF_recurseLists16(tbl->builders[job], block.data, block.start, block.end, list_head.head, list_head.count, max_depth);\n        }\n        else {\n            RMF_recurseListsBuffered(tbl->builders[job], block.data, block.start, block.end, list_head.head, 2, (BYTE)max_depth, list_head.count, 0);\n        }\n    }\n}\n\nint\n#ifdef RMF_BITPACK\nRMF_bitpackIntegrityCheck\n#else\nRMF_structuredIntegrityCheck\n#endif\n(const FL2_matchTable* const tbl, const BYTE* const data, size_t pos, size_t const end, unsigned max_depth)\n{\n    max_depth &= ~1;\n    int err = 0;\n    for (pos += !pos; pos < end; ++pos) {\n        if (IsNull(pos))\n            continue;\n        U32 const link = GetMatchLink(pos);\n        if (link >= pos) {\n            printf(\"Forward link at %X to %u\\r\\n\", (U32)pos, link);\n            err = 1;\n            continue;\n        }\n        U32 const length = GetMatchLength(pos);\n        if (pos && length < RADIX_MAX_LENGTH && link - 1 == GetMatchLink(pos - 1) && length + 1 == GetMatchLength(pos - 1))\n            continue;\n        U32 len_test = 0;\n        U32 const limit = MIN((U32)(end - pos), RADIX_MAX_LENGTH);\n        for (; len_test < limit && data[link + len_test] == data[pos + len_test]; ++len_test) {\n        }\n        if (len_test < length) {\n            printf(\"Failed integrity check: pos %X, length %u, actual %u\\r\\n\", (U32)pos, length, len_test);\n            err = 1;\n        }\n        if (length < max_depth && len_test > length)\n            /* These occur occasionally due to splitting of chains in the buffer when long repeats are present */\n            printf(\"Shortened match at %X: %u of %u\\r\\n\", (U32)pos, length, len_test);\n    }\n    return err;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/radix_get.h",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#ifndef FL2_RADIX_GET_H_\n#define FL2_RADIX_GET_H_\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\ntypedef struct\n{\n    U32 length;\n    U32 dist;\n} RMF_match;\n\nstatic size_t RMF_bitpackExtendMatch(const BYTE* const data,\n    const U32* const table,\n    ptrdiff_t const start_index,\n    ptrdiff_t limit,\n    U32 const link,\n    size_t const length)\n{\n    ptrdiff_t end_index = start_index + length;\n    ptrdiff_t const dist = start_index - link;\n\n    if (limit > start_index + (ptrdiff_t)kMatchLenMax)\n        limit = start_index + kMatchLenMax;\n\n    while (end_index < limit && end_index - (ptrdiff_t)(table[end_index] & RADIX_LINK_MASK) == dist)\n        end_index += table[end_index] >> RADIX_LINK_BITS;\n\n    if (end_index >= limit) {\n        DEBUGLOG(7, \"RMF_bitpackExtendMatch : pos %u, link %u, init length %u, full length %u\", (U32)start_index, link, (U32)length, (U32)(limit - start_index));\n        return limit - start_index;\n    }\n\n    while (end_index < limit && data[end_index - dist] == data[end_index])\n        ++end_index;\n\n    DEBUGLOG(7, \"RMF_bitpackExtendMatch : pos %u, link %u, init length %u, full length %u\", (U32)start_index, link, (U32)length, (U32)(end_index - start_index));\n    return end_index - start_index;\n}\n\n#define GetMatchLink(table, pos) ((const RMF_unit*)(table))[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK]\n\n#define GetMatchLength(table, pos) ((const RMF_unit*)(table))[(pos) >> UNIT_BITS].lengths[(pos) & UNIT_MASK]\n\nstatic size_t RMF_structuredExtendMatch(const BYTE* const data,\n    const U32* const table,\n    ptrdiff_t const start_index,\n    ptrdiff_t limit,\n    U32 const link,\n    size_t const length)\n{\n    ptrdiff_t end_index = start_index + length;\n    ptrdiff_t const dist = start_index - link;\n\n    if (limit > start_index + (ptrdiff_t)kMatchLenMax)\n        limit = start_index + kMatchLenMax;\n\n    while (end_index < limit && end_index - (ptrdiff_t)GetMatchLink(table, end_index) == dist)\n        end_index += GetMatchLength(table, end_index);\n\n    if (end_index >= limit) {\n        DEBUGLOG(7, \"RMF_structuredExtendMatch : pos %u, link %u, init length %u, full length %u\", (U32)start_index, link, (U32)length, (U32)(limit - start_index));\n        return limit - start_index;\n    }\n\n    while (end_index < limit && data[end_index - dist] == data[end_index])\n        ++end_index;\n\n    DEBUGLOG(7, \"RMF_structuredExtendMatch : pos %u, link %u, init length %u, full length %u\", (U32)start_index, link, (U32)length, (U32)(end_index - start_index));\n    return end_index - start_index;\n}\n\nFORCE_INLINE_TEMPLATE\nRMF_match RMF_getMatch(FL2_dataBlock block,\n    FL2_matchTable* tbl,\n    unsigned max_depth,\n    int structTbl,\n    size_t pos)\n{\n    if (structTbl)\n    {\n        U32 const link = GetMatchLink(tbl->table, pos);\n\n        RMF_match match;\n        match.length = 0;\n\n        if (link == RADIX_NULL_LINK)\n            return match;\n\n        size_t const length = GetMatchLength(tbl->table, pos);\n        size_t const dist = pos - link - 1;\n\n        if (length == max_depth || length == STRUCTURED_MAX_LENGTH /* from HandleRepeat */)\n            match.length = (U32)RMF_structuredExtendMatch(block.data, tbl->table, pos, block.end, link, length);\n        else\n            match.length = (U32)length;\n\n        match.dist = (U32)dist;\n\n        return match;\n    }\n    else {\n        U32 link = tbl->table[pos];\n\n        RMF_match match;\n        match.length = 0;\n\n        if (link == RADIX_NULL_LINK)\n            return match;\n\n        size_t const length = link >> RADIX_LINK_BITS;\n        link &= RADIX_LINK_MASK;\n        size_t const dist = pos - link - 1;\n\n        if (length == max_depth || length == BITPACK_MAX_LENGTH /* from HandleRepeat */)\n            match.length = (U32)RMF_bitpackExtendMatch(block.data, tbl->table, pos, block.end, link, length);\n        else\n            match.length = (U32)length;\n\n        match.dist = (U32)dist;\n\n        return match;\n    }\n}\n\nFORCE_INLINE_TEMPLATE\nRMF_match RMF_getNextMatch(FL2_dataBlock block,\n    FL2_matchTable* tbl,\n    unsigned max_depth,\n    int structTbl,\n    size_t pos)\n{\n    if (structTbl)\n    {\n        U32 const link = GetMatchLink(tbl->table, pos);\n\n        RMF_match match;\n        match.length = 0;\n\n        if (link == RADIX_NULL_LINK)\n            return match;\n\n        size_t const length = GetMatchLength(tbl->table, pos);\n        size_t const dist = pos - link - 1;\n\n        /* same distance, one byte shorter */\n        if (link - 1 == GetMatchLink(tbl->table, pos - 1))\n            return match;\n\n        if (length == max_depth || length == STRUCTURED_MAX_LENGTH /* from HandleRepeat */)\n            match.length = (U32)RMF_structuredExtendMatch(block.data, tbl->table, pos, block.end, link, length);\n        else\n            match.length = (U32)length;\n\n        match.dist = (U32)dist;\n\n        return match;\n    }\n    else {\n        U32 link = tbl->table[pos];\n\n        RMF_match match;\n        match.length = 0;\n\n        if (link == RADIX_NULL_LINK)\n            return match;\n\n        size_t const length = link >> RADIX_LINK_BITS;\n        link &= RADIX_LINK_MASK;\n        size_t const dist = pos - link - 1;\n\n        /* same distance, one byte shorter */\n        if (link - 1 == (tbl->table[pos - 1] & RADIX_LINK_MASK))\n            return match;\n\n        if (length == max_depth || length == BITPACK_MAX_LENGTH /* from HandleRepeat */)\n            match.length = (U32)RMF_bitpackExtendMatch(block.data, tbl->table, pos, block.end, link, length);\n        else\n            match.length = (U32)length;\n\n        match.dist = (U32)dist;\n\n        return match;\n    }\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* FL2_RADIX_GET_H_ */"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/radix_internal.h",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#ifndef RADIX_INTERNAL_H\n#define RADIX_INTERNAL_H\n\n#include \"atomic.h\"\n#include \"radix_mf.h\"\n\n#if defined(FL2_XZ_BUILD) && defined(TUKLIB_FAST_UNALIGNED_ACCESS)\n#  define MEM_read32(a) (*(const U32*)(a))\n#endif\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#define DICTIONARY_LOG_MIN 12U\n#define DICTIONARY_LOG_MAX_64 30U\n#define DICTIONARY_LOG_MAX_32 27U\n#define DICTIONARY_SIZE_MIN ((size_t)1 << DICTIONARY_LOG_MIN)\n#define DICTIONARY_SIZE_MAX_64 ((size_t)1 << DICTIONARY_LOG_MAX_64)\n#define DICTIONARY_SIZE_MAX_32 ((size_t)1 << DICTIONARY_LOG_MAX_32)\n#define MAX_REPEAT 24\n#define RADIX16_TABLE_SIZE ((size_t)1 << 16)\n#define RADIX8_TABLE_SIZE ((size_t)1 << 8)\n#define STACK_SIZE (RADIX16_TABLE_SIZE * 3)\n#define MAX_BRUTE_FORCE_LIST_SIZE 5\n#define BUFFER_LINK_MASK 0xFFFFFFU\n#define MATCH_BUFFER_OVERLAP 6\n#define BITPACK_MAX_LENGTH 63U\n#define STRUCTURED_MAX_LENGTH 255U\n\n#define RADIX_LINK_BITS 26\n#define RADIX_LINK_MASK ((1U << RADIX_LINK_BITS) - 1)\n#define RADIX_NULL_LINK 0xFFFFFFFFU\n\n#define UNIT_BITS 2\n#define UNIT_MASK ((1U << UNIT_BITS) - 1)\n\n#define RADIX_CANCEL_INDEX (long)(RADIX16_TABLE_SIZE + FL2_MAXTHREADS + 2)\n\ntypedef struct\n{\n    U32 head;\n    U32 count;\n} RMF_tableHead;\n\nunion src_data_u {\n    BYTE chars[4];\n    U32 u32;\n};\n\ntypedef struct\n{\n    U32 from;\n    union src_data_u src;\n    U32 next;\n} RMF_buildMatch;\n\ntypedef struct\n{\n    U32 prev_index;\n    U32 list_count;\n} RMF_listTail;\n\ntypedef struct\n{\n    U32 links[1 << UNIT_BITS];\n    BYTE lengths[1 << UNIT_BITS];\n} RMF_unit;\n\ntypedef struct\n{\n    unsigned max_len;\n    U32* table;\n    size_t match_buffer_size;\n    size_t match_buffer_limit;\n    RMF_listTail tails_8[RADIX8_TABLE_SIZE];\n    RMF_tableHead stack[STACK_SIZE];\n    RMF_listTail tails_16[RADIX16_TABLE_SIZE];\n    RMF_buildMatch match_buffer[1];\n} RMF_builder;\n\nstruct FL2_matchTable_s\n{\n    FL2_atomic st_index;\n    long end_index;\n    int is_struct;\n    int alloc_struct;\n    unsigned thread_count;\n    size_t unreduced_dict_size;\n    size_t progress;\n    RMF_parameters params;\n    RMF_builder** builders;\n    U32 stack[RADIX16_TABLE_SIZE];\n    RMF_tableHead list_heads[RADIX16_TABLE_SIZE];\n    U32 table[1];\n};\n\nvoid RMF_bitpackInit(struct FL2_matchTable_s* const tbl, const void* data, size_t const end);\nvoid RMF_structuredInit(struct FL2_matchTable_s* const tbl, const void* data, size_t const end);\nvoid RMF_bitpackBuildTable(struct FL2_matchTable_s* const tbl,\n    size_t const job,\n    unsigned const multi_thread,\n    FL2_dataBlock const block);\nvoid RMF_structuredBuildTable(struct FL2_matchTable_s* const tbl,\n    size_t const job,\n    unsigned const multi_thread,\n    FL2_dataBlock const block);\nvoid RMF_recurseListChunk(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t const block_end,\n    U32 const depth,\n    U32 const max_depth,\n    U32 const list_count,\n    size_t const stack_base);\nint RMF_bitpackIntegrityCheck(const struct FL2_matchTable_s* const tbl, const BYTE* const data, size_t pos, size_t const end, unsigned max_depth);\nint RMF_structuredIntegrityCheck(const struct FL2_matchTable_s* const tbl, const BYTE* const data, size_t pos, size_t const end, unsigned max_depth);\nvoid RMF_bitpackLimitLengths(struct FL2_matchTable_s* const tbl, size_t const pos);\nvoid RMF_structuredLimitLengths(struct FL2_matchTable_s* const tbl, size_t const pos);\nBYTE* RMF_bitpackAsOutputBuffer(struct FL2_matchTable_s* const tbl, size_t const pos);\nBYTE* RMF_structuredAsOutputBuffer(struct FL2_matchTable_s* const tbl, size_t const pos);\nsize_t RMF_bitpackGetMatch(const struct FL2_matchTable_s* const tbl,\n    const BYTE* const data,\n    size_t const pos,\n    size_t const limit,\n    unsigned const max_depth,\n    size_t* const offset_ptr);\nsize_t RMF_structuredGetMatch(const struct FL2_matchTable_s* const tbl,\n    const BYTE* const data,\n    size_t const pos,\n    size_t const limit,\n    unsigned const max_depth,\n    size_t* const offset_ptr);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* RADIX_INTERNAL_H */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/radix_mf.c",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#include <stddef.h>     /* size_t, ptrdiff_t */\n#include <stdlib.h>     /* malloc, free */\n#include \"fast-lzma2.h\"\n#include \"fl2_errors.h\"\n#include \"mem.h\"          /* U32, U64, MEM_64bits */\n#include \"fl2_internal.h\"\n#include \"radix_internal.h\"\n\n#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)\n#  pragma GCC diagnostic ignored \"-Wmaybe-uninitialized\" /* warning: 'rpt_head_next' may be used uninitialized in this function */\n#elif defined(_MSC_VER)\n#  pragma warning(disable : 4701) /* warning: 'rpt_head_next' may be used uninitialized in this function */\n#endif\n\n#define MATCH_BUFFER_SHIFT 8;\n#define MATCH_BUFFER_ELBOW_BITS 17\n#define MATCH_BUFFER_ELBOW (1UL << MATCH_BUFFER_ELBOW_BITS)\n#define MIN_MATCH_BUFFER_SIZE 256U /* min buffer size at least FL2_SEARCH_DEPTH_MAX + 2 for bounded build */\n#define MAX_MATCH_BUFFER_SIZE (1UL << 24) /* max buffer size constrained by 24-bit link values */\n\nstatic void RMF_initTailTable(RMF_builder* const tbl)\n{\n    for (size_t i = 0; i < RADIX8_TABLE_SIZE; i += 2) {\n        tbl->tails_8[i].prev_index = RADIX_NULL_LINK;\n        tbl->tails_8[i + 1].prev_index = RADIX_NULL_LINK;\n    }\n    for (size_t i = 0; i < RADIX16_TABLE_SIZE; i += 2) {\n        tbl->tails_16[i].prev_index = RADIX_NULL_LINK;\n        tbl->tails_16[i + 1].prev_index = RADIX_NULL_LINK;\n    }\n}\n\nstatic RMF_builder* RMF_createBuilder(size_t match_buffer_size)\n{\n    match_buffer_size = MIN(match_buffer_size, MAX_MATCH_BUFFER_SIZE);\n    match_buffer_size = MAX(match_buffer_size, MIN_MATCH_BUFFER_SIZE);\n\n    RMF_builder* const builder = malloc(\n        sizeof(RMF_builder) + (match_buffer_size - 1) * sizeof(RMF_buildMatch));\n\n    if (builder == NULL)\n        return NULL;\n\n    builder->match_buffer_size = match_buffer_size;\n    builder->match_buffer_limit = match_buffer_size;\n\n    RMF_initTailTable(builder);\n\n    return builder;\n}\n\nstatic void RMF_freeBuilderTable(RMF_builder** const builders, unsigned const size)\n{\n    if (builders == NULL)\n        return;\n\n    for (unsigned i = 0; i < size; ++i)\n        free(builders[i]);\n\n    free(builders);\n}\n\n/* RMF_createBuilderTable() : \n * Create one match table builder object per thread.\n * max_len : maximum match length supported by the table structure \n * size : number of threads \n */\nstatic RMF_builder** RMF_createBuilderTable(U32* const match_table, size_t const match_buffer_size, unsigned const max_len, unsigned const size)\n{\n    DEBUGLOG(3, \"RMF_createBuilderTable : match_buffer_size %u, builders %u\", (U32)match_buffer_size, size);\n\n    RMF_builder** const builders = malloc(size * sizeof(RMF_builder*));\n\n    if (builders == NULL)\n        return NULL;\n\n    for (unsigned i = 0; i < size; ++i)\n        builders[i] = NULL;\n\n    for (unsigned i = 0; i < size; ++i) {\n        builders[i] = RMF_createBuilder(match_buffer_size);\n        if (builders[i] == NULL) {\n            RMF_freeBuilderTable(builders, i);\n            return NULL;\n        }\n        builders[i]->table = match_table;\n        builders[i]->max_len = max_len;\n    }\n    return builders;\n}\n\nstatic int RMF_isStruct(size_t const dictionary_size)\n{\n    return dictionary_size > ((size_t)1 << RADIX_LINK_BITS);\n}\n\n/* RMF_clampParams() :\n*  Make param values within valid range.\n*  Return : valid RMF_parameters */\nstatic RMF_parameters RMF_clampParams(RMF_parameters params)\n{\n#   define CLAMP(val,min,max) {      \\\n        if (val<(min)) val=(min);        \\\n        else if (val>(max)) val=(max);   \\\n    }\n#   define MAXCLAMP(val,max) {      \\\n        if (val>(max)) val=(max);   \\\n    }\n    CLAMP(params.dictionary_size, DICTIONARY_SIZE_MIN, MEM_64bits() ? DICTIONARY_SIZE_MAX_64 : DICTIONARY_SIZE_MAX_32);\n    MAXCLAMP(params.match_buffer_resize, FL2_BUFFER_RESIZE_MAX);\n    MAXCLAMP(params.overlap_fraction, FL2_BLOCK_OVERLAP_MAX);\n    CLAMP(params.depth, FL2_SEARCH_DEPTH_MIN, FL2_SEARCH_DEPTH_MAX);\n    return params;\n#   undef MAXCLAMP\n#   undef CLAMP\n}\n\nstatic size_t RMF_calBufSize(size_t dictionary_size, unsigned buffer_resize)\n{\n    size_t buffer_size = dictionary_size >> MATCH_BUFFER_SHIFT;\n    if (buffer_size > MATCH_BUFFER_ELBOW) {\n        size_t extra = 0;\n        unsigned n = MATCH_BUFFER_ELBOW_BITS - 1;\n        for (; (4UL << n) <= buffer_size; ++n)\n            extra += MATCH_BUFFER_ELBOW >> 4;\n        if((3UL << n) <= buffer_size)\n            extra += MATCH_BUFFER_ELBOW >> 5;\n        buffer_size = MATCH_BUFFER_ELBOW + extra;\n    }\n    if (buffer_resize > 2)\n        buffer_size += buffer_size >> (4 - buffer_resize);\n    else if (buffer_resize < 2)\n        buffer_size -= buffer_size >> (buffer_resize + 1);\n    return buffer_size;\n}\n\n/* RMF_applyParameters_internal() :\n * Set parameters to those specified.\n * Create a builder table if none exists. Free an existing one if incompatible.\n * Set match_buffer_limit and max supported match length.\n * Returns an error if dictionary won't fit.\n */\nstatic size_t RMF_applyParameters_internal(FL2_matchTable* const tbl, const RMF_parameters* const params)\n{\n    int const is_struct = RMF_isStruct(params->dictionary_size);\n    size_t const dictionary_size = tbl->params.dictionary_size;\n    /* dictionary is allocated with the struct and is immutable */\n    if (params->dictionary_size > tbl->params.dictionary_size\n        || (params->dictionary_size == tbl->params.dictionary_size && is_struct > tbl->alloc_struct))\n        return FL2_ERROR(parameter_unsupported);\n\n    size_t const match_buffer_size = RMF_calBufSize(tbl->unreduced_dict_size, params->match_buffer_resize);\n    tbl->params = *params;\n    tbl->params.dictionary_size = dictionary_size;\n    tbl->is_struct = is_struct;\n    if (tbl->builders == NULL\n        || match_buffer_size > tbl->builders[0]->match_buffer_size)\n    {\n        RMF_freeBuilderTable(tbl->builders, tbl->thread_count);\n        tbl->builders = RMF_createBuilderTable(tbl->table, match_buffer_size, tbl->is_struct ? STRUCTURED_MAX_LENGTH : BITPACK_MAX_LENGTH, tbl->thread_count);\n        if (tbl->builders == NULL) {\n            return FL2_ERROR(memory_allocation);\n        }\n    }\n    else {\n        for (unsigned i = 0; i < tbl->thread_count; ++i) {\n            tbl->builders[i]->match_buffer_limit = match_buffer_size;\n            tbl->builders[i]->max_len = tbl->is_struct ? STRUCTURED_MAX_LENGTH : BITPACK_MAX_LENGTH;\n        }\n    }\n    return 0;\n}\n\n/* RMF_reduceDict() : \n * Reduce dictionary and match buffer size if the total input size is known and < dictionary_size.\n */\nstatic void RMF_reduceDict(RMF_parameters* const params, size_t const dict_reduce)\n{\n    if (dict_reduce)\n        params->dictionary_size = MIN(params->dictionary_size, MAX(dict_reduce, DICTIONARY_SIZE_MIN));\n}\n\nstatic void RMF_initListHeads(FL2_matchTable* const tbl)\n{\n    for (size_t i = 0; i < RADIX16_TABLE_SIZE; i += 2) {\n        tbl->list_heads[i].head = RADIX_NULL_LINK;\n        tbl->list_heads[i].count = 0;\n        tbl->list_heads[i + 1].head = RADIX_NULL_LINK;\n        tbl->list_heads[i + 1].count = 0;\n    }\n}\n\n/* RMF_createMatchTable() :\n * Create a match table. Reduce the dict size to input size if possible.\n * A thread_count of 0 will be raised to 1.\n */\nFL2_matchTable* RMF_createMatchTable(const RMF_parameters* const p, size_t const dict_reduce, unsigned const thread_count)\n{\n    RMF_parameters params = RMF_clampParams(*p);\n    size_t unreduced_dict_size = params.dictionary_size;\n    RMF_reduceDict(&params, dict_reduce);\n\n    int const is_struct = RMF_isStruct(params.dictionary_size);\n    size_t dictionary_size = params.dictionary_size;\n\n    DEBUGLOG(3, \"RMF_createMatchTable : is_struct %d, dict %u\", is_struct, (U32)dictionary_size);\n\n    size_t const table_bytes = is_struct ? ((dictionary_size + 3U) / 4U) * sizeof(RMF_unit)\n        : dictionary_size * sizeof(U32);\n    FL2_matchTable* const tbl = malloc(sizeof(FL2_matchTable) + table_bytes - sizeof(U32));\n    if (tbl == NULL)\n        return NULL;\n\n    tbl->is_struct = is_struct;\n    tbl->alloc_struct = is_struct;\n    tbl->thread_count = thread_count + !thread_count;\n    tbl->params = params;\n    tbl->unreduced_dict_size = unreduced_dict_size;\n    tbl->builders = NULL;\n\n    RMF_applyParameters_internal(tbl, &params);\n\n    RMF_initListHeads(tbl);\n\n    RMF_initProgress(tbl);\n    \n    return tbl;\n}\n\nvoid RMF_freeMatchTable(FL2_matchTable* const tbl)\n{\n    if (tbl == NULL)\n        return;\n\n    DEBUGLOG(3, \"RMF_freeMatchTable\");\n\n    RMF_freeBuilderTable(tbl->builders, tbl->thread_count);\n    free(tbl);\n}\n\nBYTE RMF_compatibleParameters(const FL2_matchTable* const tbl, const RMF_parameters * const p, size_t const dict_reduce)\n{\n    RMF_parameters params = RMF_clampParams(*p);\n    RMF_reduceDict(&params, dict_reduce);\n    return tbl->params.dictionary_size > params.dictionary_size\n        || (tbl->params.dictionary_size == params.dictionary_size && tbl->alloc_struct >= RMF_isStruct(params.dictionary_size));\n}\n\nsize_t RMF_applyParameters(FL2_matchTable* const tbl, const RMF_parameters* const p, size_t const dict_reduce)\n{\n    RMF_parameters params = RMF_clampParams(*p);\n    RMF_reduceDict(&params, dict_reduce);\n    return RMF_applyParameters_internal(tbl, &params);\n}\n\nsize_t RMF_threadCount(const FL2_matchTable* const tbl)\n{\n    return tbl->thread_count;\n}\n\nvoid RMF_initProgress(FL2_matchTable * const tbl)\n{\n    if (tbl != NULL)\n        tbl->progress = 0;\n}\n\nvoid RMF_initTable(FL2_matchTable* const tbl, const void* const data, size_t const end)\n{\n    DEBUGLOG(5, \"RMF_initTable : size %u\", (U32)end);\n\n    tbl->st_index = ATOMIC_INITIAL_VALUE;\n\n    if (tbl->is_struct)\n        RMF_structuredInit(tbl, data, end);\n    else\n        RMF_bitpackInit(tbl, data, end);\n}\n\nstatic void RMF_handleRepeat(RMF_buildMatch* const match_buffer,\n    const BYTE* const data_block,\n    const BYTE* const data_block_end,\n    size_t const next,\n    U32 count,\n    U32 const rpt_len,\n    U32 const depth,\n    U32 const max_len)\n{\n    size_t pos = next;\n    U32 length = depth + rpt_len;\n\n    const BYTE* const data = data_block + match_buffer[pos].from;\n    const BYTE* const data_2 = data - rpt_len;\n    U32 block_max_len = MIN(max_len, (U32)(data_block_end - data));\n\n    while (length < block_max_len && data[length] == data_2[length])\n        ++length;\n\n    for (; length <= max_len && count; --count) {\n        size_t next_i = match_buffer[pos].next & 0xFFFFFF;\n        match_buffer[pos].next = (U32)next_i | (length << 24);\n        length += rpt_len;\n        pos = next_i;\n    }\n    for (; count; --count) {\n        size_t next_i = match_buffer[pos].next & 0xFFFFFF;\n        match_buffer[pos].next = (U32)next_i | (max_len << 24);\n        pos = next_i;\n    }\n}\n\ntypedef struct\n{\n    size_t pos;\n    const BYTE* data_src;\n    union src_data_u src;\n} BruteForceMatch;\n\nstatic void RMF_bruteForceBuffered(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t pos,\n    size_t const list_count,\n    size_t const slot,\n    size_t const depth,\n    size_t const max_depth)\n{\n    BruteForceMatch buffer[MAX_BRUTE_FORCE_LIST_SIZE + 1];\n    const BYTE* const data_src = data_block + depth;\n    size_t const limit = max_depth - depth;\n    const BYTE* const start = data_src + block_start;\n    size_t i = 0;\n    for (;;) {\n        /* Load all locations from the match buffer */\n        buffer[i].pos = pos;\n        buffer[i].data_src = data_src + tbl->match_buffer[pos].from;\n        buffer[i].src.u32 = tbl->match_buffer[pos].src.u32;\n\n        if (++i >= list_count)\n            break;\n\n        pos = tbl->match_buffer[pos].next & 0xFFFFFF;\n    }\n    i = 0;\n    do {\n        size_t longest = 0;\n        size_t j = i + 1;\n        size_t longest_index = j;\n        const BYTE* const data = buffer[i].data_src;\n        do {\n            /* Begin with the remaining chars pulled from the match buffer */\n            size_t len_test = slot;\n            while (len_test < 4 && buffer[i].src.chars[len_test] == buffer[j].src.chars[len_test] && len_test - slot < limit)\n                ++len_test;\n\n            len_test -= slot;\n            if (len_test) {\n                /* Complete the match length count in the raw input buffer */\n                const BYTE* data_2 = buffer[j].data_src;\n                while (data[len_test] == data_2[len_test] && len_test < limit)\n                    ++len_test;\n            }\n            if (len_test > longest) {\n                longest_index = j;\n                longest = len_test;\n                if (len_test >= limit)\n                    break;\n            }\n        } while (++j < list_count);\n        if (longest > 0) {\n            /* If the existing match was extended, store the new link and length info in the match buffer */\n            pos = buffer[i].pos;\n            tbl->match_buffer[pos].next = (U32)(buffer[longest_index].pos | ((depth + longest) << 24));\n        }\n        ++i;\n    } while (i < list_count - 1 && buffer[i].data_src >= start);\n}\n\n/* Lengthen and divide buffered chains into smaller chains, save them on a stack and process in turn. \n * The match finder spends most of its time here.\n */\nFORCE_INLINE_TEMPLATE\nvoid RMF_recurseListChunk_generic(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t const block_end,\n    U32 depth,\n    U32 const max_depth,\n    U32 list_count,\n    size_t const stack_base)\n{\n    U32 const base_depth = depth;\n    size_t st_index = stack_base;\n    size_t pos = 0;\n    ++depth;\n    /* The last element is done separately and won't be copied back at the end */\n    --list_count;\n    do {\n        size_t const radix_8 = tbl->match_buffer[pos].src.chars[0];\n        /* Seen this char before? */\n        U32 const prev = tbl->tails_8[radix_8].prev_index;\n        tbl->tails_8[radix_8].prev_index = (U32)pos;\n        if (prev != RADIX_NULL_LINK) {\n            ++tbl->tails_8[radix_8].list_count;\n            /* Link the previous occurrence to this one and record the new length */\n            tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n        }\n        else {\n            tbl->tails_8[radix_8].list_count = 1;\n            /* Add the new sub list to the stack */\n            tbl->stack[st_index].head = (U32)pos;\n            /* This will be converted to a count at the end */\n            tbl->stack[st_index].count = (U32)radix_8;\n            ++st_index;\n        }\n        ++pos;\n    } while (pos < list_count);\n\n    {   /* Do the last element */\n        size_t const radix_8 = tbl->match_buffer[pos].src.chars[0];\n        /* Nothing to do if there was no previous */\n        U32 const prev = tbl->tails_8[radix_8].prev_index;\n        if (prev != RADIX_NULL_LINK) {\n            ++tbl->tails_8[radix_8].list_count;\n            tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n        }\n    }\n    /* Convert radix values on the stack to counts and reset any used tail slots */\n    for (size_t j = stack_base; j < st_index; ++j) {\n        tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;\n        tbl->stack[j].count = (U32)tbl->tails_8[tbl->stack[j].count].list_count;\n    }\n    while (st_index > stack_base) {\n        /* Pop an item off the stack */\n        --st_index;\n        list_count = tbl->stack[st_index].count;\n        if (list_count < 2) {\n            /* Nothing to match with */\n            continue;\n        }\n        pos = tbl->stack[st_index].head;\n        size_t link = tbl->match_buffer[pos].from;\n        if (link < block_start) {\n            /* Chain starts in the overlap region which is already encoded */\n            continue;\n        }\n        /* Check stack space. The first comparison is unnecessary but it's a constant so should be faster */\n        if (st_index > STACK_SIZE - RADIX8_TABLE_SIZE\n            && st_index > STACK_SIZE - list_count)\n        {\n            /* Stack may not be able to fit all possible new items. This is very rare. */\n            continue;\n        }\n        depth = tbl->match_buffer[pos].next >> 24;\n        /* Index into the 4-byte pre-loaded input char cache */\n        size_t slot = (depth - base_depth) & 3;\n        if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE) {\n            /* Quicker to use brute force, each string compared with all previous strings */\n            RMF_bruteForceBuffered(tbl,\n                data_block,\n                block_start,\n                pos,\n                list_count,\n                slot,\n                depth,\n                max_depth);\n            continue;\n        }\n        /* check for repeats at depth 4,8,16,32 etc unless depth is near max_depth */\n        U32 const test = max_depth != 6 && ((depth & 3) == 0)\n            && (depth & (depth - 1)) == 0\n            && (max_depth >= depth + (depth >> 1));\n        ++depth;\n        /* Create an offset data buffer pointer for reading the next bytes */\n        const BYTE* const data_src = data_block + depth;\n        /* Last pass is done separately */\n        if (!test && depth < max_depth) {\n            size_t const prev_st_index = st_index;\n            /* Last element done separately */\n            --list_count;\n            /* If slot is 3 then chars need to be loaded. */\n            if (slot == 3 && max_depth != 6) do {\n                size_t const radix_8 = tbl->match_buffer[pos].src.chars[3];\n                size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n                /* Pre-load the next link and data bytes. On some hardware execution can continue\n                 * ahead while the data is retrieved if no operations except move are done on the data. */\n                tbl->match_buffer[pos].src.u32 = MEM_read32(data_src + link);\n                size_t const next_link = tbl->match_buffer[next_index].from;\n                U32 const prev = tbl->tails_8[radix_8].prev_index;\n                tbl->tails_8[radix_8].prev_index = (U32)pos;\n                if (prev != RADIX_NULL_LINK) {\n                    /* This char has occurred before in the chain. Link the previous (> pos) occurance with this */\n                    ++tbl->tails_8[radix_8].list_count;\n                    tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n                }\n                else {\n                    /* First occurrence in the chain */\n                    tbl->tails_8[radix_8].list_count = 1;\n                    tbl->stack[st_index].head = (U32)pos;\n                    /* Save the char as a reference to load the count at the end */\n                    tbl->stack[st_index].count = (U32)radix_8;\n                    ++st_index;\n                }\n                pos = next_index;\n                link = next_link;\n            } while (--list_count != 0);\n            else do {\n                size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];\n                size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n                /* Pre-load the next link to avoid waiting for RAM access */\n                size_t const next_link = tbl->match_buffer[next_index].from;\n                U32 const prev = tbl->tails_8[radix_8].prev_index;\n                tbl->tails_8[radix_8].prev_index = (U32)pos;\n                if (prev != RADIX_NULL_LINK) {\n                    ++tbl->tails_8[radix_8].list_count;\n                    tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n                }\n                else {\n                    tbl->tails_8[radix_8].list_count = 1;\n                    tbl->stack[st_index].head = (U32)pos;\n                    tbl->stack[st_index].count = (U32)radix_8;\n                    ++st_index;\n                }\n                pos = next_index;\n                link = next_link;\n            } while (--list_count != 0);\n\n            size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];\n            U32 const prev = tbl->tails_8[radix_8].prev_index;\n            if (prev != RADIX_NULL_LINK) {\n                if (slot == 3)\n                    tbl->match_buffer[pos].src.u32 = MEM_read32(data_src + link);\n\n                ++tbl->tails_8[radix_8].list_count;\n                tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n            }\n            for (size_t j = prev_st_index; j < st_index; ++j) {\n                tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;\n                tbl->stack[j].count = (U32)tbl->tails_8[tbl->stack[j].count].list_count;\n            }\n        }\n        else if (test) {\n            S32 rpt = -1;\n            size_t rpt_head_next;\n            U32 rpt_dist = 0;\n            size_t const prev_st_index = st_index;\n            U32 const rpt_depth = depth - 1;\n            /* Last element done separately */\n            --list_count;\n            do {\n                size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];\n                size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n                size_t const next_link = tbl->match_buffer[next_index].from;\n                if ((link - next_link) > rpt_depth) {\n                    if (rpt > 0)\n                        RMF_handleRepeat(tbl->match_buffer, data_block, data_block + block_end, rpt_head_next, rpt, rpt_dist, rpt_depth, tbl->max_len);\n\n                    rpt = -1;\n                    U32 const prev = tbl->tails_8[radix_8].prev_index;\n                    tbl->tails_8[radix_8].prev_index = (U32)pos;\n                    if (prev != RADIX_NULL_LINK) {\n                        ++tbl->tails_8[radix_8].list_count;\n                        tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n                    }\n                    else {\n                        tbl->tails_8[radix_8].list_count = 1;\n                        tbl->stack[st_index].head = (U32)pos;\n                        tbl->stack[st_index].count = (U32)radix_8;\n                        ++st_index;\n                    }\n                    pos = next_index;\n                    link = next_link;\n                }\n                else {\n                    U32 const dist = (U32)(link - next_link);\n                    if (rpt < 0 || dist != rpt_dist) {\n                        if (rpt > 0)\n                            RMF_handleRepeat(tbl->match_buffer, data_block, data_block + block_end, rpt_head_next, rpt, rpt_dist, rpt_depth, tbl->max_len);\n\n                        rpt = 0;\n                        rpt_head_next = next_index;\n                        rpt_dist = dist;\n                        U32 const prev = tbl->tails_8[radix_8].prev_index;\n                        tbl->tails_8[radix_8].prev_index = (U32)pos;\n                        if (prev != RADIX_NULL_LINK) {\n                            ++tbl->tails_8[radix_8].list_count;\n                            tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n                        }\n                        else {\n                            tbl->tails_8[radix_8].list_count = 1;\n                            tbl->stack[st_index].head = (U32)pos;\n                            tbl->stack[st_index].count = (U32)radix_8;\n                            ++st_index;\n                        }\n                    }\n                    else {\n                        ++rpt;\n                    }\n                    pos = next_index;\n                    link = next_link;\n                }\n            } while (--list_count != 0);\n\n            if (rpt > 0)\n                RMF_handleRepeat(tbl->match_buffer, data_block, data_block + block_end, rpt_head_next, rpt, rpt_dist, rpt_depth, tbl->max_len);\n\n            size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];\n            U32 const prev = tbl->tails_8[radix_8].prev_index;\n            if (prev != RADIX_NULL_LINK) {\n                if (slot == 3) {\n                    tbl->match_buffer[pos].src.u32 = MEM_read32(data_src + link);\n                }\n                ++tbl->tails_8[radix_8].list_count;\n                tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n            }\n            for (size_t j = prev_st_index; j < st_index; ++j) {\n                tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;\n                tbl->stack[j].count = (U32)tbl->tails_8[tbl->stack[j].count].list_count;\n            }\n        }\n        else {\n            size_t const prev_st_index = st_index;\n            /* The last pass at max_depth */\n            do {\n                size_t const radix_8 = tbl->match_buffer[pos].src.chars[slot];\n                size_t const next_index = tbl->match_buffer[pos].next & BUFFER_LINK_MASK;\n                /* Pre-load the next link. */\n                /* The last element in tbl->match_buffer is circular so this is never an access violation. */\n                size_t const next_link = tbl->match_buffer[next_index].from;\n                U32 const prev = tbl->tails_8[radix_8].prev_index;\n                tbl->tails_8[radix_8].prev_index = (U32)pos;\n                if (prev != RADIX_NULL_LINK) {\n                    tbl->match_buffer[prev].next = (U32)pos | (depth << 24);\n                }\n                else {\n                    tbl->stack[st_index].count = (U32)radix_8;\n                    ++st_index;\n                }\n                pos = next_index;\n                link = next_link;\n            } while (--list_count != 0);\n            for (size_t j = prev_st_index; j < st_index; ++j) {\n                tbl->tails_8[tbl->stack[j].count].prev_index = RADIX_NULL_LINK;\n            }\n            st_index = prev_st_index;\n        }\n    }\n}\n\nvoid RMF_recurseListChunk(RMF_builder* const tbl,\n    const BYTE* const data_block,\n    size_t const block_start,\n    size_t const block_end,\n    U32 const depth,\n    U32 const max_depth,\n    U32 const list_count,\n    size_t const stack_base)\n{\n    if (list_count < 2)\n        return;\n    /* Template-like inline functions */\n    if (list_count <= MAX_BRUTE_FORCE_LIST_SIZE)\n        RMF_bruteForceBuffered(tbl, data_block, block_start, 0, list_count, 0, depth, max_depth);\n    else if (max_depth > 6)\n        RMF_recurseListChunk_generic(tbl, data_block, block_start, block_end, depth, max_depth, list_count, stack_base);\n    else\n        RMF_recurseListChunk_generic(tbl, data_block, block_start, block_end, depth, 6, list_count, stack_base);\n}\n\n/* Iterate the head table concurrently with other threads, and recurse each list until max_depth is reached */\nint RMF_buildTable(FL2_matchTable* const tbl,\n    size_t const job,\n    unsigned const multi_thread,\n    FL2_dataBlock const block)\n{\n    DEBUGLOG(5, \"RMF_buildTable : thread %u\", (U32)job);\n\n    if (tbl->is_struct)\n        RMF_structuredBuildTable(tbl, job, multi_thread, block);\n    else\n        RMF_bitpackBuildTable(tbl, job, multi_thread, block);\n\n    if (job == 0 && tbl->st_index >= RADIX_CANCEL_INDEX) {\n        RMF_initListHeads(tbl);\n        return 1;\n    }\n    return 0;\n}\n\nvoid RMF_cancelBuild(FL2_matchTable * const tbl)\n{\n    if(tbl != NULL)\n        FL2_atomic_add(tbl->st_index, RADIX_CANCEL_INDEX - ATOMIC_INITIAL_VALUE);\n}\n\nvoid RMF_resetIncompleteBuild(FL2_matchTable * const tbl)\n{\n    RMF_initListHeads(tbl);\n}\n\nint RMF_integrityCheck(const FL2_matchTable* const tbl, const BYTE* const data, size_t const pos, size_t const end, unsigned const max_depth)\n{\n    if (tbl->is_struct)\n        return RMF_structuredIntegrityCheck(tbl, data, pos, end, max_depth);\n    else\n        return RMF_bitpackIntegrityCheck(tbl, data, pos, end, max_depth);\n}\n\nvoid RMF_limitLengths(FL2_matchTable* const tbl, size_t const pos)\n{\n    if (tbl->is_struct)\n        RMF_structuredLimitLengths(tbl, pos);\n    else\n        RMF_bitpackLimitLengths(tbl, pos);\n}\n\nBYTE* RMF_getTableAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos)\n{\n    if (tbl->is_struct)\n        return RMF_structuredAsOutputBuffer(tbl, pos);\n    else\n        return RMF_bitpackAsOutputBuffer(tbl, pos);\n}\n\nsize_t RMF_memoryUsage(size_t const dict_size, unsigned const buffer_resize, unsigned const thread_count)\n{\n    size_t size = (size_t)(4U + RMF_isStruct(dict_size)) * dict_size;\n    size_t const buf_size = RMF_calBufSize(dict_size, buffer_resize);\n    size += ((buf_size - 1) * sizeof(RMF_buildMatch) + sizeof(RMF_builder)) * thread_count;\n    return size;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/radix_mf.h",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#ifndef RADIX_MF_H\n#define RADIX_MF_H\n\n#include \"fast-lzma2.h\"\n#include \"data_block.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\ntypedef struct FL2_matchTable_s FL2_matchTable;\n\n#define OVERLAP_FROM_DICT_SIZE(d, o) (((d) >> 4) * (o))\n\n#define RMF_MIN_BYTES_PER_THREAD 1024\n\ntypedef struct\n{\n    size_t dictionary_size;\n    unsigned match_buffer_resize;\n    unsigned overlap_fraction;\n    unsigned divide_and_conquer;\n    unsigned depth;\n#ifdef RMF_REFERENCE\n    unsigned use_ref_mf;\n#endif\n} RMF_parameters;\n\nFL2_matchTable* RMF_createMatchTable(const RMF_parameters* const params, size_t const dict_reduce, unsigned const thread_count);\nvoid RMF_freeMatchTable(FL2_matchTable* const tbl);\nBYTE RMF_compatibleParameters(const FL2_matchTable* const tbl, const RMF_parameters* const params, size_t const dict_reduce);\nsize_t RMF_applyParameters(FL2_matchTable* const tbl, const RMF_parameters* const params, size_t const dict_reduce);\nsize_t RMF_threadCount(const FL2_matchTable * const tbl);\nvoid RMF_initProgress(FL2_matchTable * const tbl);\nvoid RMF_initTable(FL2_matchTable* const tbl, const void* const data, size_t const end);\nint RMF_buildTable(FL2_matchTable* const tbl,\n    size_t const job,\n    unsigned const multi_thread,\n    FL2_dataBlock const block);\nvoid RMF_cancelBuild(FL2_matchTable* const tbl);\nvoid RMF_resetIncompleteBuild(FL2_matchTable* const tbl);\nint RMF_integrityCheck(const FL2_matchTable* const tbl, const BYTE* const data, size_t const pos, size_t const end, unsigned const max_depth);\nvoid RMF_limitLengths(FL2_matchTable* const tbl, size_t const pos);\nBYTE* RMF_getTableAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos);\nsize_t RMF_memoryUsage(size_t const dict_size, unsigned const buffer_resize, unsigned const thread_count);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* RADIX_MF_H */"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/radix_struct.c",
    "content": "﻿/*\n* Copyright (c) 2018, Conor McCarthy\n* All rights reserved.\n*\n* This source code is licensed under both the BSD-style license (found in the\n* LICENSE file in the root directory of this source tree) and the GPLv2 (found\n* in the COPYING file in the root directory of this source tree).\n* You may select, at your option, one of the above-listed licenses.\n*/\n\n#include \"mem.h\"          /* U32, U64 */\n#include \"fl2_threading.h\"\n#include \"fl2_internal.h\"\n#include \"radix_internal.h\"\n\n#undef MIN\n#define MIN(a,b) ((a) < (b) ? (a) : (b))\n\n#define RMF_STRUCTURED\n\n#define RADIX_MAX_LENGTH STRUCTURED_MAX_LENGTH\n\n#define InitMatchLink(pos, link) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] = (U32)(link)\n\n#define GetMatchLink(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK]\n\n#define GetInitialMatchLink(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK]\n\n#define GetMatchLength(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].lengths[(pos) & UNIT_MASK]\n\n#define SetMatchLink(pos, link, length) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] = (U32)(link)\n\n#define SetMatchLength(pos, link, length) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].lengths[(pos) & UNIT_MASK] = (BYTE)(length)\n\n#define SetMatchLinkAndLength(pos, link, length) do { size_t i_ = (pos) >> UNIT_BITS, u_ = (pos) & UNIT_MASK; ((RMF_unit*)tbl->table)[i_].links[u_] = (U32)(link); ((RMF_unit*)tbl->table)[i_].lengths[u_] = (BYTE)(length); } while(0)\n\n#define SetNull(pos) ((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] = RADIX_NULL_LINK\n\n#define IsNull(pos) (((RMF_unit*)tbl->table)[(pos) >> UNIT_BITS].links[(pos) & UNIT_MASK] == RADIX_NULL_LINK)\n\nBYTE* RMF_structuredAsOutputBuffer(FL2_matchTable* const tbl, size_t const pos)\n{\n    return (BYTE*)((RMF_unit*)tbl->table + (pos >> UNIT_BITS) + ((pos & UNIT_MASK) != 0));\n}\n\n/* Restrict the match lengths so that they don't reach beyond pos */\nvoid RMF_structuredLimitLengths(FL2_matchTable* const tbl, size_t const pos)\n{\n    DEBUGLOG(5, \"RMF_limitLengths : end %u, max length %u\", (U32)pos, RADIX_MAX_LENGTH);\n    SetNull(pos - 1);\n    for (size_t length = 2; length < RADIX_MAX_LENGTH && length <= pos; ++length) {\n        size_t const i = (pos - length) >> UNIT_BITS;\n        size_t const u = (pos - length) & UNIT_MASK;\n        if (((RMF_unit*)tbl->table)[i].links[u] != RADIX_NULL_LINK) {\n            ((RMF_unit*)tbl->table)[i].lengths[u] = MIN((BYTE)length, ((RMF_unit*)tbl->table)[i].lengths[u]);\n        }\n    }\n}\n\n#include \"radix_engine.h\""
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/range_enc.c",
    "content": "﻿/*\n* Bitwise range encoder by Igor Pavlov\n* Modified by Conor McCarthy\n*\n* Public domain\n*/\n\n#include \"fl2_internal.h\"\n#include \"mem.h\"\n#include \"platform.h\"\n#include \"range_enc.h\"\n\n/* The first and last elements of these tables are never used */\nBYTE price_table[2][kPriceTableSize] = { {\n   0, 193, 182, 166, 154, 145, 137, 131,\n 125, 120, 115, 111, 107, 103, 100,  97,\n  94,  91,  89,  86,  84,  82,  80,  78,\n  76,  74,  72,  71,  69,  67,  66,  64,\n  63,  61,  60,  59,  57,  56,  55,  54,\n  53,  52,  50,  49,  48,  47,  46,  45,\n  44,  43,  42,  42,  41,  40,  39,  38,\n  37,  36,  36,  35,  34,  33,  33,  32,\n  31,  30,  30,  29,  28,  28,  27,  26,\n  26,  25,  25,  24,  23,  23,  22,  21,\n  21,  20,  20,  19,  19,  18,  18,  17,\n  17,  16,  16,  15,  15,  14,  14,  13,\n  13,  12,  12,  11,  11,  10,  10,   9,\n   9,   8,   8,   8,   7,   7,   6,   6,\n   5,   5,   5,   4,   4,   3,   3,   3,\n   2,   2,   2,   1,   1,   0,   0,   0\n}, {\n   0,   0,   0,   1,   1,   2,   2,   2,\n   3,   3,   3,   4,   4,   5,   5,   5,\n   6,   6,   7,   7,   8,   8,   8,   9,\n   9,  10,  10,  11,  11,  12,  12,  13,\n  13,  13,  14,  14,  15,  15,  16,  17,\n  17,  18,  18,  19,  19,  20,  20,  21,\n  21,  22,  23,  23,  24,  24,  25,  26,\n  26,  27,  28,  28,  29,  30,  30,  31,\n  32,  33,  33,  34,  35,  36,  36,  37,\n  38,  39,  40,  41,  41,  42,  43,  44,\n  45,  46,  47,  48,  49,  50,  51,  53,\n  54,  55,  56,  57,  59,  60,  61,  63,\n  64,  66,  67,  69,  70,  72,  74,  76,\n  78,  80,  82,  84,  86,  89,  91,  94,\n  97, 100, 103, 107, 111, 115, 119, 125,\n 130, 137, 145, 154, 165, 181, 192,   0\n} };\n\n#if 0\n\n#include <stdio.h>\n\n/* Generates price_table */\nvoid RC_printPriceTable()\n{\n    static const unsigned test_size = 0x4000;\n    const unsigned test_div = test_size >> 8;\n    BYTE buf[0x3062];\n    unsigned table0[kPriceTableSize];\n    unsigned table1[kPriceTableSize];\n    unsigned count[kPriceTableSize];\n    memset(table0, 0, sizeof(table0));\n    memset(table1, 0, sizeof(table1));\n    memset(count, 0, sizeof(count));\n    for (LZMA2_prob i = 31; i <= kBitModelTotal - 31; ++i) {\n        RC_encoder rc;\n        RC_reset(&rc);\n        RC_setOutputBuffer(&rc, buf);\n        for (unsigned j = 0; j < test_size; ++j) {\n            LZMA2_prob prob = i;\n            RC_encodeBit0(&rc, &prob);\n        }\n        RC_flush(&rc);\n        table0[i >> kNumMoveReducingBits] += (unsigned)rc.out_index - 5;\n        RC_reset(&rc);\n        RC_setOutputBuffer(&rc, buf);\n        for (unsigned j = 0; j < test_size; ++j) {\n            LZMA2_prob prob = i;\n            RC_encodeBit1(&rc, &prob);\n        }\n        RC_flush(&rc);\n        table1[i >> kNumMoveReducingBits] += (unsigned)rc.out_index - 5;\n        ++count[i >> kNumMoveReducingBits];\n    }\n    for (int i = 0; i < kPriceTableSize; ++i) if (count[i]) {\n        table0[i] = (table0[i] / count[i]) / test_div;\n        table1[i] = (table1[i] / count[i]) / test_div;\n    }\n    fputs(\"const BYTE price_table[2][kPriceTableSize] = {\\r\\n\", stdout);\n    for (int i = 0; i < kPriceTableSize;) {\n        for (int j = 0; j < 8; ++j, ++i)\n            printf(\"%4d,\", table0[i]);\n        fputs(\"\\r\\n\", stdout);\n    }\n    fputs(\"}, {\\r\\n\", stdout);\n    for (int i = 0; i < kPriceTableSize;) {\n        for (int j = 0; j < 8; ++j, ++i)\n            printf(\"%4d,\", table1[i]);\n        fputs(\"\\r\\n\", stdout);\n    }\n    fputs(\"} };\\r\\n\", stdout);\n}\n\n#endif\n\nvoid RC_setOutputBuffer(RC_encoder* const rc, BYTE *const out_buffer)\n{\n    rc->out_buffer = out_buffer;\n    rc->out_index = 0;\n}\n\nvoid RC_reset(RC_encoder* const rc)\n{\n    rc->low = 0;\n    rc->range = (U32)-1;\n    rc->cache_size = 0;\n    rc->cache = 0;\n}\n\n#ifdef __64BIT__\n\n// **************** NanaZip Modification Start ****************\n//void FORCE_NOINLINE RC_shiftLow(RC_encoder* const rc)\nvoid RC_shiftLow(RC_encoder* const rc)\n// **************** NanaZip Modification End ****************\n{\n    U64 low = rc->low;\n    rc->low = (U32)(low << 8);\n    /* VC15 compiles 'if (low < 0xFF000000 || low > 0xFFFFFFFF)' to this single-branch conditional */\n    if (low + 0xFFFFFFFF01000000 > 0xFFFFFF) {\n        BYTE high = (BYTE)(low >> 32);\n        rc->out_buffer[rc->out_index++] = rc->cache + high;\n        rc->cache = (BYTE)(low >> 24);\n        if (rc->cache_size != 0) {\n            high += 0xFF;\n            do {\n                rc->out_buffer[rc->out_index++] = high;\n            } while (--rc->cache_size != 0);\n        }\n    }\n    else {\n        rc->cache_size++;\n    }\n}\n\n#else\n\n// **************** NanaZip Modification Start ****************\n//void FORCE_NOINLINE RC_shiftLow(RC_encoder* const rc)\nvoid RC_shiftLow(RC_encoder* const rc)\n// **************** NanaZip Modification End ****************\n{\n    U32 low = (U32)rc->low;\n    unsigned high = (unsigned)(rc->low >> 32);\n    rc->low = low << 8;\n    if (low < (U32)0xFF000000 || high != 0) {\n        rc->out_buffer[rc->out_index++] = rc->cache + (BYTE)high;\n        rc->cache = (BYTE)(low >> 24);\n        if (rc->cache_size != 0) {\n            high += 0xFF;\n            do {\n                rc->out_buffer[rc->out_index++] = (BYTE)high;\n            } while (--rc->cache_size != 0);\n        }\n    }\n    else {\n        rc->cache_size++;\n    }\n}\n\n#endif\n\nvoid RC_encodeBitTree(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol)\n{\n    assert(bit_count > 1);\n    --bit_count;\n    unsigned bit = symbol >> bit_count;\n    RC_encodeBit(rc, &probs[1], bit);\n    size_t tree_index = 1;\n    do {\n        --bit_count;\n        tree_index = (tree_index << 1) | bit;\n        bit = (symbol >> bit_count) & 1;\n        RC_encodeBit(rc, &probs[tree_index], bit);\n    } while (bit_count != 0);\n}\n\nvoid RC_encodeBitTreeReverse(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol)\n{\n    assert(bit_count != 0);\n    unsigned bit = symbol & 1;\n    RC_encodeBit(rc, &probs[1], bit);\n    unsigned tree_index = 1;\n    while (--bit_count != 0) {\n        tree_index = (tree_index << 1) + bit;\n        symbol >>= 1;\n        bit = symbol & 1;\n\t\tRC_encodeBit(rc, &probs[tree_index], bit);\n\t}\n}\n\n// **************** NanaZip Modification Start ****************\n//void FORCE_NOINLINE RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count)\nvoid RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count)\n// **************** NanaZip Modification End ****************\n{\n\tassert(bit_count > 0);\n\tdo {\n        rc->range >>= 1;\n\t\t--bit_count;\n        rc->low += rc->range & -((int)(value >> bit_count) & 1);\n\t\tif (rc->range < kTopValue) {\n            rc->range <<= 8;\n\t\t\tRC_shiftLow(rc);\n\t\t}\n\t} while (bit_count != 0);\n}\n\n\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/range_enc.h",
    "content": "﻿/*\n* Bitwise range encoder by Igor Pavlov\n* Modified by Conor McCarthy\n*\n* Public domain\n*/\n\n#ifndef RANGE_ENCODER_H\n#define RANGE_ENCODER_H\n\n#include \"mem.h\"\n#include \"compiler.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifdef LZMA_ENC_PROB32\ntypedef U32 LZMA2_prob;\n#else\ntypedef U16 LZMA2_prob;\n#endif\n\n#define kNumTopBits 24U\n#define kTopValue (1UL << kNumTopBits)\n#define kNumBitModelTotalBits 11U\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\n#define kNumMoveBits 5U\n#define kProbInitValue (kBitModelTotal >> 1U)\n#define kNumMoveReducingBits 4U\n#define kNumBitPriceShiftBits 5U\n#define kPriceTableSize (kBitModelTotal >> kNumMoveReducingBits)\n\nextern BYTE price_table[2][kPriceTableSize];\n#if 0\nvoid RC_printPriceTable();\n#endif\n\ntypedef struct\n{\n\tBYTE *out_buffer;\n\tsize_t out_index;\n\tU64 cache_size;\n\tU64 low;\n\tU32 range;\n\tBYTE cache;\n} RC_encoder;\n\nvoid RC_reset(RC_encoder* const rc);\n\nvoid RC_setOutputBuffer(RC_encoder* const rc, BYTE *const out_buffer);\n\n// **************** NanaZip Modification Start ****************\n//void FORCE_NOINLINE RC_shiftLow(RC_encoder* const rc);\nvoid RC_shiftLow(RC_encoder* const rc);\n// **************** NanaZip Modification End ****************\n\nvoid RC_encodeBitTree(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol);\n\nvoid RC_encodeBitTreeReverse(RC_encoder* const rc, LZMA2_prob *const probs, unsigned bit_count, unsigned symbol);\n\n// **************** NanaZip Modification Start ****************\n//void FORCE_NOINLINE RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count);\nvoid RC_encodeDirect(RC_encoder* const rc, unsigned value, unsigned bit_count);\n// **************** NanaZip Modification End ****************\n\nHINT_INLINE\nvoid RC_encodeBit0(RC_encoder* const rc, LZMA2_prob *const rprob)\n{\n\tunsigned prob = *rprob;\n    rc->range = (rc->range >> kNumBitModelTotalBits) * prob;\n\tprob += (kBitModelTotal - prob) >> kNumMoveBits;\n\t*rprob = (LZMA2_prob)prob;\n\tif (rc->range < kTopValue) {\n        rc->range <<= 8;\n\t\tRC_shiftLow(rc);\n\t}\n}\n\nHINT_INLINE\nvoid RC_encodeBit1(RC_encoder* const rc, LZMA2_prob *const rprob)\n{\n\tunsigned prob = *rprob;\n\tU32 new_bound = (rc->range >> kNumBitModelTotalBits) * prob;\n    rc->low += new_bound;\n    rc->range -= new_bound;\n\tprob -= prob >> kNumMoveBits;\n\t*rprob = (LZMA2_prob)prob;\n\tif (rc->range < kTopValue) {\n        rc->range <<= 8;\n\t\tRC_shiftLow(rc);\n\t}\n}\n\nHINT_INLINE\nvoid RC_encodeBit(RC_encoder* const rc, LZMA2_prob *const rprob, unsigned const bit)\n{\n\tunsigned prob = *rprob;\n\tif (bit != 0) {\n\t\tU32 const new_bound = (rc->range >> kNumBitModelTotalBits) * prob;\n        rc->low += new_bound;\n        rc->range -= new_bound;\n\t\tprob -= prob >> kNumMoveBits;\n\t}\n\telse {\n        rc->range = (rc->range >> kNumBitModelTotalBits) * prob;\n\t\tprob += (kBitModelTotal - prob) >> kNumMoveBits;\n\t}\n\t*rprob = (LZMA2_prob)prob;\n\tif (rc->range < kTopValue) {\n        rc->range <<= 8;\n\t\tRC_shiftLow(rc);\n\t}\n}\n\n#define GET_PRICE(prob, symbol) \\\n  price_table[symbol][(prob) >> kNumMoveReducingBits]\n\n#define GET_PRICE_0(prob) price_table[0][(prob) >> kNumMoveReducingBits]\n\n#define GET_PRICE_1(prob) price_table[1][(prob) >> kNumMoveReducingBits]\n\n#define kMinLitPrice 8U\n\nHINT_INLINE\nunsigned RC_getTreePrice(const LZMA2_prob* const prob_table, unsigned bit_count, size_t symbol)\n{\n\tunsigned price = 0;\n    symbol |= ((size_t)1 << bit_count);\n    do {\n\t\tsize_t const next_symbol = symbol >> 1;\n\t\tunsigned prob = prob_table[next_symbol];\n        size_t bit = symbol & 1;\n\t\tprice += GET_PRICE(prob, bit);\n\t\tsymbol = next_symbol;\n    } while (symbol != 1);\n\treturn price;\n}\n\nHINT_INLINE\nunsigned RC_getReverseTreePrice(const LZMA2_prob* const prob_table, unsigned bit_count, size_t symbol)\n{\n    unsigned prob = prob_table[1];\n    size_t bit = symbol & 1;\n    unsigned price = GET_PRICE(prob, bit);\n    size_t m = 1;\n    while (--bit_count != 0) {\n        m = (m << 1) | bit;\n        symbol >>= 1;\n        prob = prob_table[m];\n        bit = symbol & 1;\n        price += GET_PRICE(prob, bit);\n    }\n    return price;\n}\n\nHINT_INLINE\nvoid RC_flush(RC_encoder* const rc)\n{\n    for (int i = 0; i < 5; ++i)\n        RC_shiftLow(rc);\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* RANGE_ENCODER_H */\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/util.c",
    "content": "﻿/*\n * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include \"util.h\"       /* note : ensure that platform.h is included first ! */\n#include <errno.h>\n#include <assert.h>\n\n\nint UTIL_fileExist(const char* filename)\n{\n    stat_t statbuf;\n#if defined(_MSC_VER)\n    int const stat_error = _stat64(filename, &statbuf);\n#else\n    int const stat_error = stat(filename, &statbuf);\n#endif\n    return !stat_error;\n}\n\nint UTIL_isRegularFile(const char* infilename)\n{\n    stat_t statbuf;\n    return UTIL_getFileStat(infilename, &statbuf); /* Only need to know whether it is a regular file */\n}\n\nint UTIL_getFileStat(const char* infilename, stat_t *statbuf)\n{\n    int r;\n#if defined(_MSC_VER)\n    r = _stat64(infilename, statbuf);\n    if (r || !(statbuf->st_mode & S_IFREG)) return 0;   /* No good... */\n#else\n    r = stat(infilename, statbuf);\n    if (r || !S_ISREG(statbuf->st_mode)) return 0;   /* No good... */\n#endif\n    return 1;\n}\n\nint UTIL_setFileStat(const char *filename, stat_t *statbuf)\n{\n    int res = 0;\n    struct utimbuf timebuf;\n\n    if (!UTIL_isRegularFile(filename))\n        return -1;\n\n    timebuf.actime = time(NULL);\n    timebuf.modtime = statbuf->st_mtime;\n    res += utime(filename, &timebuf);  /* set access and modification times */\n\n#if !defined(_WIN32)\n    res += chown(filename, statbuf->st_uid, statbuf->st_gid);  /* Copy ownership */\n#endif\n\n    res += chmod(filename, statbuf->st_mode & 07777);  /* Copy file permissions */\n\n    errno = 0;\n    return -res; /* number of errors is returned */\n}\n\nU32 UTIL_isDirectory(const char* infilename)\n{\n    int r;\n    stat_t statbuf;\n#if defined(_MSC_VER)\n    r = _stat64(infilename, &statbuf);\n    if (!r && (statbuf.st_mode & _S_IFDIR)) return 1;\n#else\n    r = stat(infilename, &statbuf);\n    if (!r && S_ISDIR(statbuf.st_mode)) return 1;\n#endif\n    return 0;\n}\n\nU32 UTIL_isLink(const char* infilename)\n{\n/* macro guards, as defined in : https://linux.die.net/man/2/lstat */\n#ifndef __STRICT_ANSI__\n#if defined(_BSD_SOURCE) \\\n    || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \\\n    || (defined(_XOPEN_SOURCE) && defined(_XOPEN_SOURCE_EXTENDED)) \\\n    || (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \\\n    || (defined(__APPLE__) && defined(__MACH__)) \\\n    || defined(__OpenBSD__) \\\n    || defined(__FreeBSD__)\n    int r;\n    stat_t statbuf;\n    r = lstat(infilename, &statbuf);\n    if (!r && S_ISLNK(statbuf.st_mode)) return 1;\n#endif\n#endif\n    (void)infilename;\n    return 0;\n}\n\nU64 UTIL_getFileSize(const char* infilename)\n{\n    if (!UTIL_isRegularFile(infilename)) return UTIL_FILESIZE_UNKNOWN;\n    {   int r;\n#if defined(_MSC_VER)\n        struct __stat64 statbuf;\n        r = _stat64(infilename, &statbuf);\n        if (r || !(statbuf.st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;\n#elif defined(__MINGW32__) && defined (__MSVCRT__)\n        struct _stati64 statbuf;\n        r = _stati64(infilename, &statbuf);\n        if (r || !(statbuf.st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;\n#else\n        struct stat statbuf;\n        r = stat(infilename, &statbuf);\n        if (r || !S_ISREG(statbuf.st_mode)) return UTIL_FILESIZE_UNKNOWN;\n#endif\n        return (U64)statbuf.st_size;\n    }\n}\n\n\nU64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles)\n{\n    U64 total = 0;\n    int error = 0;\n    unsigned n;\n    for (n=0; n<nbFiles; n++) {\n        U64 const size = UTIL_getFileSize(fileNamesTable[n]);\n        error |= (size == UTIL_FILESIZE_UNKNOWN);\n        total += size;\n    }\n    return error ? UTIL_FILESIZE_UNKNOWN : total;\n}\n\n#ifdef _WIN32\nint UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)\n{\n    char* path;\n    int dirLength, fnameLength, pathLength, nbFiles = 0;\n    WIN32_FIND_DATAA cFile;\n    HANDLE hFile;\n\n    dirLength = (int)strlen(dirName);\n    path = (char*) malloc(dirLength + 3);\n    if (!path) return 0;\n\n    memcpy(path, dirName, dirLength);\n    path[dirLength] = '\\\\';\n    path[dirLength+1] = '*';\n    path[dirLength+2] = 0;\n\n    hFile=FindFirstFileA(path, &cFile);\n    if (hFile == INVALID_HANDLE_VALUE) {\n        UTIL_DISPLAYLEVEL(1, \"Cannot open directory '%s'\\n\", dirName);\n        return 0;\n    }\n    free(path);\n\n    do {\n        fnameLength = (int)strlen(cFile.cFileName);\n        path = (char*) malloc(dirLength + fnameLength + 2);\n        if (!path) { FindClose(hFile); return 0; }\n        memcpy(path, dirName, dirLength);\n        path[dirLength] = '\\\\';\n        memcpy(path+dirLength+1, cFile.cFileName, fnameLength);\n        pathLength = dirLength+1+fnameLength;\n        path[pathLength] = 0;\n        if (cFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\n            if ( strcmp (cFile.cFileName, \"..\") == 0\n              || strcmp (cFile.cFileName, \".\") == 0 )\n                continue;\n            /* Recursively call \"UTIL_prepareFileList\" with the new path. */\n            nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks);\n            if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }\n        } else if ( (cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)\n                 || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)\n                 || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ) {\n            if (*bufStart + *pos + pathLength >= *bufEnd) {\n                ptrdiff_t const newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;\n                *bufStart = (char*)UTIL_realloc(*bufStart, newListSize);\n                if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }\n                *bufEnd = *bufStart + newListSize;\n            }\n            if (*bufStart + *pos + pathLength < *bufEnd) {\n                memcpy(*bufStart + *pos, path, pathLength+1 /* include final \\0 */);\n                *pos += pathLength + 1;\n                nbFiles++;\n            }\n        }\n        free(path);\n    } while (FindNextFileA(hFile, &cFile));\n\n    FindClose(hFile);\n    return nbFiles;\n}\n\n#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */\n\nint UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)\n{\n    DIR *dir;\n    struct dirent *entry;\n    char* path;\n    int dirLength, fnameLength, pathLength, nbFiles = 0;\n\n    if (!(dir = opendir(dirName))) {\n        UTIL_DISPLAYLEVEL(1, \"Cannot open directory '%s': %s\\n\", dirName, strerror(errno));\n        return 0;\n    }\n\n    dirLength = (int)strlen(dirName);\n    errno = 0;\n    while ((entry = readdir(dir)) != NULL) {\n        if (strcmp (entry->d_name, \"..\") == 0 ||\n            strcmp (entry->d_name, \".\") == 0) continue;\n        fnameLength = (int)strlen(entry->d_name);\n        path = (char*) malloc(dirLength + fnameLength + 2);\n        if (!path) { closedir(dir); return 0; }\n        memcpy(path, dirName, dirLength);\n\n        path[dirLength] = '/';\n        memcpy(path+dirLength+1, entry->d_name, fnameLength);\n        pathLength = dirLength+1+fnameLength;\n        path[pathLength] = 0;\n\n        if (!followLinks && UTIL_isLink(path)) {\n            UTIL_DISPLAYLEVEL(2, \"Warning : %s is a symbolic link, ignoring\\n\", path);\n            continue;\n        }\n\n        if (UTIL_isDirectory(path)) {\n            nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks);  /* Recursively call \"UTIL_prepareFileList\" with the new path. */\n            if (*bufStart == NULL) { free(path); closedir(dir); return 0; }\n        } else {\n            if (*bufStart + *pos + pathLength >= *bufEnd) {\n                ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;\n                *bufStart = (char*)UTIL_realloc(*bufStart, newListSize);\n                *bufEnd = *bufStart + newListSize;\n                if (*bufStart == NULL) { free(path); closedir(dir); return 0; }\n            }\n            if (*bufStart + *pos + pathLength < *bufEnd) {\n                memcpy(*bufStart + *pos, path, pathLength + 1);  /* with final \\0 */\n                *pos += pathLength + 1;\n                nbFiles++;\n            }\n        }\n        free(path);\n        errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */\n    }\n\n    if (errno != 0) {\n        UTIL_DISPLAYLEVEL(1, \"readdir(%s) error: %s\\n\", dirName, strerror(errno));\n        free(*bufStart);\n        *bufStart = NULL;\n    }\n    closedir(dir);\n    return nbFiles;\n}\n\n#else\n\nint UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)\n{\n    (void)bufStart; (void)bufEnd; (void)pos; (void)followLinks;\n    UTIL_DISPLAYLEVEL(1, \"Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\\n\", dirName);\n    return 0;\n}\n\n#endif /* #ifdef _WIN32 */\n\n/*\n * UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,\n *                       and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).\n * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)\n * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.\n */\nconst char**\nUTIL_createFileList(const char **inputNames, unsigned inputNamesNb,\n                    char** allocatedBuffer, unsigned* allocatedNamesNb,\n                    int followLinks)\n{\n    size_t pos;\n    unsigned i, nbFiles;\n    char* buf = (char*)malloc(LIST_SIZE_INCREASE);\n    char* bufend = buf + LIST_SIZE_INCREASE;\n    const char** fileTable;\n\n    if (!buf) return NULL;\n\n    for (i=0, pos=0, nbFiles=0; i<inputNamesNb; i++) {\n        if (!UTIL_isDirectory(inputNames[i])) {\n            size_t const len = strlen(inputNames[i]);\n            if (buf + pos + len >= bufend) {\n                ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE;\n                buf = (char*)UTIL_realloc(buf, newListSize);\n                bufend = buf + newListSize;\n                if (!buf) return NULL;\n            }\n            if (buf + pos + len < bufend) {\n                memcpy(buf+pos, inputNames[i], len+1);  /* with final \\0 */\n                pos += len + 1;\n                nbFiles++;\n            }\n        } else {\n            nbFiles += UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend, followLinks);\n            if (buf == NULL) return NULL;\n    }   }\n\n    if (nbFiles == 0) { free(buf); return NULL; }\n\n    fileTable = (const char**)malloc((nbFiles+1) * sizeof(const char*));\n    if (!fileTable) { free(buf); return NULL; }\n\n    for (i=0, pos=0; i<nbFiles; i++) {\n        fileTable[i] = buf + pos;\n        pos += strlen(fileTable[i]) + 1;\n    }\n\n    if (buf + pos > bufend) { free(buf); free((void*)fileTable); return NULL; }\n\n    *allocatedBuffer = buf;\n    *allocatedNamesNb = nbFiles;\n\n    return fileTable;\n}\n\n/*-****************************************\n*  Console log\n******************************************/\nint g_utilDisplayLevel;\n\n\n/*-****************************************\n*  Time functions\n******************************************/\n#if defined(_WIN32)   /* Windows */\n\nUTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; }\n\nU64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)\n{\n    static LARGE_INTEGER ticksPerSecond;\n    static int init = 0;\n    if (!init) {\n        if (!QueryPerformanceFrequency(&ticksPerSecond))\n            UTIL_DISPLAYLEVEL(1, \"ERROR: QueryPerformanceFrequency() failure\\n\");\n        init = 1;\n    }\n    return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;\n}\n\nU64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)\n{\n    static LARGE_INTEGER ticksPerSecond;\n    static int init = 0;\n    if (!init) {\n        if (!QueryPerformanceFrequency(&ticksPerSecond))\n            UTIL_DISPLAYLEVEL(1, \"ERROR: QueryPerformanceFrequency() failure\\n\");\n        init = 1;\n    }\n    return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart;\n}\n\n#elif defined(__APPLE__) && defined(__MACH__)\n\nUTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); }\n\nU64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd)\n{\n    static mach_timebase_info_data_t rate;\n    static int init = 0;\n    if (!init) {\n        mach_timebase_info(&rate);\n        init = 1;\n    }\n    return (((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom))/1000ULL;\n}\n\nU64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd)\n{\n    static mach_timebase_info_data_t rate;\n    static int init = 0;\n    if (!init) {\n        mach_timebase_info(&rate);\n        init = 1;\n    }\n    return ((clockEnd - clockStart) * (U64)rate.numer) / ((U64)rate.denom);\n}\n\n#elif (PLATFORM_POSIX_VERSION >= 200112L) \\\n   && (defined(__UCLIBC__)                \\\n      || (defined(__GLIBC__)              \\\n          && ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \\\n             || (__GLIBC__ > 2))))\n\nUTIL_time_t UTIL_getTime(void)\n{\n    UTIL_time_t time;\n    if (clock_gettime(CLOCK_MONOTONIC, &time))\n        UTIL_DISPLAYLEVEL(1, \"ERROR: Failed to get time\\n\");   /* we could also exit() */\n    return time;\n}\n\nUTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end)\n{\n    UTIL_time_t diff;\n    if (end.tv_nsec < begin.tv_nsec) {\n        diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec;\n        diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec;\n    } else {\n        diff.tv_sec = end.tv_sec - begin.tv_sec;\n        diff.tv_nsec = end.tv_nsec - begin.tv_nsec;\n    }\n    return diff;\n}\n\nU64 UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end)\n{\n    UTIL_time_t const diff = UTIL_getSpanTime(begin, end);\n    U64 micro = 0;\n    micro += 1000000ULL * diff.tv_sec;\n    micro += diff.tv_nsec / 1000ULL;\n    return micro;\n}\n\nU64 UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end)\n{\n    UTIL_time_t const diff = UTIL_getSpanTime(begin, end);\n    U64 nano = 0;\n    nano += 1000000000ULL * diff.tv_sec;\n    nano += diff.tv_nsec;\n    return nano;\n}\n\n#else   /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */\n\nUTIL_time_t UTIL_getTime(void) { return clock(); }\nU64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }\nU64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; }\n\n#endif\n\n/* returns time span in microseconds */\nU64 UTIL_clockSpanMicro(UTIL_time_t clockStart )\n{\n    UTIL_time_t const clockEnd = UTIL_getTime();\n    return UTIL_getSpanTimeMicro(clockStart, clockEnd);\n}\n\n/* returns time span in microseconds */\nU64 UTIL_clockSpanNano(UTIL_time_t clockStart )\n{\n    UTIL_time_t const clockEnd = UTIL_getTime();\n    return UTIL_getSpanTimeNano(clockStart, clockEnd);\n}\n\nvoid UTIL_waitForNextTick(void)\n{\n    UTIL_time_t const clockStart = UTIL_getTime();\n    UTIL_time_t clockEnd;\n    do {\n        clockEnd = UTIL_getTime();\n    } while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0);\n}\n\n/* count the number of physical cores */\n#if defined(_WIN32) || defined(WIN32)\n\n#include <windows.h>\n\ntypedef BOOL(WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);\n\nint UTIL_countPhysicalCores(void)\n{\n    static int numPhysicalCores = 0;\n    if (numPhysicalCores != 0) return numPhysicalCores;\n\n    {   LPFN_GLPI glpi;\n        BOOL done = FALSE;\n        PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;\n        PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;\n        DWORD returnLength = 0;\n        size_t byteOffset = 0;\n\n        glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT(\"kernel32\")),\n                                         \"GetLogicalProcessorInformation\");\n\n        if (glpi == NULL) {\n            goto failed;\n        }\n\n        while(!done) {\n            DWORD rc = glpi(buffer, &returnLength);\n            if (FALSE == rc) {\n                if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {\n                    if (buffer)\n                        free(buffer);\n                    buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);\n\n                    if (buffer == NULL) {\n                        perror(\"zstd\");\n                        exit(1);\n                    }\n                } else {\n                    /* some other error */\n                    goto failed;\n                }\n            } else {\n                done = TRUE;\n            }\n        }\n\n        ptr = buffer;\n\n        while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) {\n\n            if (ptr->Relationship == RelationProcessorCore) {\n                numPhysicalCores++;\n            }\n\n            ptr++;\n            byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);\n        }\n\n        free(buffer);\n\n        return numPhysicalCores;\n    }\n\nfailed:\n    /* try to fall back on GetSystemInfo */\n    {   SYSTEM_INFO sysinfo;\n        GetSystemInfo(&sysinfo);\n        numPhysicalCores = sysinfo.dwNumberOfProcessors;\n        if (numPhysicalCores == 0) numPhysicalCores = 1; /* just in case */\n    }\n    return numPhysicalCores;\n}\n\n#elif defined(__APPLE__)\n\n#include <sys/sysctl.h>\n\n/* Use apple-provided syscall\n * see: man 3 sysctl */\nint UTIL_countPhysicalCores(void)\n{\n    static S32 numPhysicalCores = 0; /* apple specifies int32_t */\n    if (numPhysicalCores != 0) return numPhysicalCores;\n\n    {   size_t size = sizeof(S32);\n        int const ret = sysctlbyname(\"hw.physicalcpu\", &numPhysicalCores, &size, NULL, 0);\n        if (ret != 0) {\n            if (errno == ENOENT) {\n                /* entry not present, fall back on 1 */\n                numPhysicalCores = 1;\n            } else {\n                perror(\"zstd: can't get number of physical cpus\");\n                exit(1);\n            }\n        }\n\n        return numPhysicalCores;\n    }\n}\n\n#elif defined(__linux__)\n\n/* parse /proc/cpuinfo\n * siblings / cpu cores should give hyperthreading ratio\n * otherwise fall back on sysconf */\nint UTIL_countPhysicalCores(void)\n{\n    static int numPhysicalCores = 0;\n\n    if (numPhysicalCores != 0) return numPhysicalCores;\n\n    numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);\n    if (numPhysicalCores == -1) {\n        /* value not queryable, fall back on 1 */\n        return numPhysicalCores = 1;\n    }\n\n    /* try to determine if there's hyperthreading */\n    {   FILE* const cpuinfo = fopen(\"/proc/cpuinfo\", \"r\");\n#define BUF_SIZE 80\n        char buff[BUF_SIZE];\n\n        int siblings = 0;\n        int cpu_cores = 0;\n        int ratio = 1;\n\n        if (cpuinfo == NULL) {\n            /* fall back on the sysconf value */\n            return numPhysicalCores;\n        }\n\n        /* assume the cpu cores/siblings values will be constant across all\n         * present processors */\n        while (!feof(cpuinfo)) {\n            if (fgets(buff, BUF_SIZE, cpuinfo) != NULL) {\n                if (strncmp(buff, \"siblings\", 8) == 0) {\n                    const char* const sep = strchr(buff, ':');\n                    if (*sep == '\\0') {\n                        /* formatting was broken? */\n                        goto failed;\n                    }\n\n                    siblings = atoi(sep + 1);\n                }\n                if (strncmp(buff, \"cpu cores\", 9) == 0) {\n                    const char* const sep = strchr(buff, ':');\n                    if (*sep == '\\0') {\n                        /* formatting was broken? */\n                        goto failed;\n                    }\n\n                    cpu_cores = atoi(sep + 1);\n                }\n            } else if (ferror(cpuinfo)) {\n                /* fall back on the sysconf value */\n                goto failed;\n            }\n        }\n        if (siblings && cpu_cores) {\n            ratio = siblings / cpu_cores;\n        }\nfailed:\n        fclose(cpuinfo);\n        return numPhysicalCores = numPhysicalCores / ratio;\n    }\n}\n\n#elif defined(__FreeBSD__)\n\n#include <sys/param.h>\n#include <sys/sysctl.h>\n\n/* Use physical core sysctl when available\n * see: man 4 smp, man 3 sysctl */\nint UTIL_countPhysicalCores(void)\n{\n    static int numPhysicalCores = 0; /* freebsd sysctl is native int sized */\n    if (numPhysicalCores != 0) return numPhysicalCores;\n\n#if __FreeBSD_version >= 1300008\n    {   size_t size = sizeof(numPhysicalCores);\n        int ret = sysctlbyname(\"kern.smp.cores\", &numPhysicalCores, &size, NULL, 0);\n        if (ret == 0) return numPhysicalCores;\n        if (errno != ENOENT) {\n            perror(\"zstd: can't get number of physical cpus\");\n            exit(1);\n        }\n        /* sysctl not present, fall through to older sysconf method */\n    }\n#endif\n\n    numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);\n    if (numPhysicalCores == -1) {\n        /* value not queryable, fall back on 1 */\n        numPhysicalCores = 1;\n    }\n    return numPhysicalCores;\n}\n\n#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)\n\n/* Use POSIX sysconf\n * see: man 3 sysconf */\nint UTIL_countPhysicalCores(void)\n{\n    static int numPhysicalCores = 0;\n\n    if (numPhysicalCores != 0) return numPhysicalCores;\n\n    numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);\n    if (numPhysicalCores == -1) {\n        /* value not queryable, fall back on 1 */\n        return numPhysicalCores = 1;\n    }\n    return numPhysicalCores;\n}\n\n#else\n\nint UTIL_countPhysicalCores(void)\n{\n    /* assume 1 */\n    return 1;\n}\n\n#endif\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/FastLZMA2/util.h",
    "content": "﻿/*\n * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef UTIL_H_MODULE\n#define UTIL_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include \"platform.h\"     /* PLATFORM_POSIX_VERSION, ZSTD_NANOSLEEP_SUPPORT, ZSTD_SETPRIORITY_SUPPORT */\n#include <stdlib.h>       /* malloc, realloc, free */\n#include <stddef.h>       /* size_t, ptrdiff_t */\n#include <stdio.h>        /* fprintf */\n#include <sys/types.h>    /* stat, utime */\n#include <sys/stat.h>     /* stat, chmod */\n#if defined(_MSC_VER)\n#  include <sys/utime.h>  /* utime */\n#  include <io.h>         /* _chmod */\n#else\n#  include <unistd.h>     /* chown, stat */\n#  include <utime.h>      /* utime */\n#endif\n#include <time.h>         /* clock_t, clock, CLOCKS_PER_SEC, nanosleep */\n#include \"mem.h\"          /* U32, U64 */\n\n\n/*-************************************************************\n* Avoid fseek()'s 2GiB barrier with MSVC, macOS, *BSD, MinGW\n***************************************************************/\n#if defined(_MSC_VER) && (_MSC_VER >= 1400)\n#   define UTIL_fseek _fseeki64\n#elif !defined(__64BIT__) && (PLATFORM_POSIX_VERSION >= 200112L) /* No point defining Large file for 64 bit */\n#  define UTIL_fseek fseeko\n#elif defined(__MINGW32__) && defined(__MSVCRT__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS)\n#   define UTIL_fseek fseeko64\n#else\n#   define UTIL_fseek fseek\n#endif\n\n\n/*-*************************************************\n*  Sleep & priority functions: Windows - Posix - others\n***************************************************/\n#if defined(_WIN32)\n#  include <windows.h>\n#  define SET_REALTIME_PRIORITY SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)\n#  define UTIL_sleep(s) Sleep(1000*s)\n#  define UTIL_sleepMilli(milli) Sleep(milli)\n\n#elif PLATFORM_POSIX_VERSION > 0 /* Unix-like operating system */\n#  include <unistd.h>   /* sleep */\n#  define UTIL_sleep(s) sleep(s)\n#  if ZSTD_NANOSLEEP_SUPPORT   /* necessarily defined in platform.h */\n#      define UTIL_sleepMilli(milli) { struct timespec t; t.tv_sec=0; t.tv_nsec=milli*1000000ULL; nanosleep(&t, NULL); }\n#  else\n#      define UTIL_sleepMilli(milli) /* disabled */\n#  endif\n#  if ZSTD_SETPRIORITY_SUPPORT\n#    include <sys/resource.h> /* setpriority */\n#    define SET_REALTIME_PRIORITY setpriority(PRIO_PROCESS, 0, -20)\n#  else\n#    define SET_REALTIME_PRIORITY /* disabled */\n#  endif\n\n#else  /* unknown non-unix operating systen */\n#  define UTIL_sleep(s)          /* disabled */\n#  define UTIL_sleepMilli(milli) /* disabled */\n#  define SET_REALTIME_PRIORITY  /* disabled */\n#endif\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define LIST_SIZE_INCREASE   (8*1024)\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(__INTEL_COMPILER)\n#  pragma warning(disable : 177)    /* disable: message #177: function was declared but never referenced, useful with UTIL_STATIC */\n#endif\n#if defined(__GNUC__)\n#  define UTIL_STATIC static __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define UTIL_STATIC static inline\n#elif defined(_MSC_VER)\n#  define UTIL_STATIC static __inline\n#else\n#  define UTIL_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/*-****************************************\n*  Console log\n******************************************/\nextern int g_utilDisplayLevel;\n#define UTIL_DISPLAY(...)         fprintf(stderr, __VA_ARGS__)\n#define UTIL_DISPLAYLEVEL(l, ...) { if (g_utilDisplayLevel>=l) { UTIL_DISPLAY(__VA_ARGS__); } }\n\n\n/*-****************************************\n*  Time functions\n******************************************/\n#if defined(_WIN32)   /* Windows */\n\n    #define UTIL_TIME_INITIALIZER { { 0, 0 } }\n    typedef LARGE_INTEGER UTIL_time_t;\n\n#elif defined(__APPLE__) && defined(__MACH__)\n\n    #include <mach/mach_time.h>\n    #define UTIL_TIME_INITIALIZER 0\n    typedef U64 UTIL_time_t;\n\n#elif (PLATFORM_POSIX_VERSION >= 200112L) \\\n   && (defined(__UCLIBC__)                \\\n      || (defined(__GLIBC__)              \\\n          && ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) \\\n             || (__GLIBC__ > 2))))\n\n    #define UTIL_TIME_INITIALIZER { 0, 0 }\n    typedef struct timespec UTIL_freq_t;\n    typedef struct timespec UTIL_time_t;\n\n    UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end);\n\n#else   /* relies on standard C (note : clock_t measurements can be wrong when using multi-threading) */\n\n    typedef clock_t UTIL_time_t;\n    #define UTIL_TIME_INITIALIZER 0\n\n#endif\n\nUTIL_time_t UTIL_getTime(void);\nU64 UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd);\nU64 UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd);\n\n#define SEC_TO_MICRO 1000000\n\n/* returns time span in microseconds */\nU64 UTIL_clockSpanMicro(UTIL_time_t clockStart);\n\n/* returns time span in microseconds */\nU64 UTIL_clockSpanNano(UTIL_time_t clockStart);\nvoid UTIL_waitForNextTick(void);\n\n/*-****************************************\n*  File functions\n******************************************/\n#if defined(_MSC_VER)\n    #define chmod _chmod\n    typedef struct __stat64 stat_t;\n#else\n    typedef struct stat stat_t;\n#endif\n\n\nint UTIL_fileExist(const char* filename);\nint UTIL_isRegularFile(const char* infilename);\nint UTIL_setFileStat(const char* filename, stat_t* statbuf);\nU32 UTIL_isDirectory(const char* infilename);\nint UTIL_getFileStat(const char* infilename, stat_t* statbuf);\n\nU32 UTIL_isLink(const char* infilename);\n#define UTIL_FILESIZE_UNKNOWN  ((U64)(-1))\nU64 UTIL_getFileSize(const char* infilename);\n\nU64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles);\n\n/*\n * A modified version of realloc().\n * If UTIL_realloc() fails the original block is freed.\n*/\nUTIL_STATIC void* UTIL_realloc(void *ptr, size_t size)\n{\n    void *newptr = realloc(ptr, size);\n    if (newptr) return newptr;\n    free(ptr);\n    return NULL;\n}\n\nint UTIL_prepareFileList(const char* dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks);\n#ifdef _WIN32\n#  define UTIL_HAS_CREATEFILELIST\n#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L)  /* opendir, readdir require POSIX.1-2001 */\n#  define UTIL_HAS_CREATEFILELIST\n#  include <dirent.h>       /* opendir, readdir */\n#  include <string.h>       /* strerror, memcpy */\n#else\n#endif /* #ifdef _WIN32 */\n\n/*\n * UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,\n *                       and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).\n * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)\n * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.\n */\nconst char**\nUTIL_createFileList(const char **inputNames, unsigned inputNamesNb,\n                    char** allocatedBuffer, unsigned* allocatedNamesNb,\n                    int followLinks);\n\nUTIL_STATIC void UTIL_freeFileList(const char** filenameTable, char* allocatedBuffer)\n{\n    if (allocatedBuffer) free(allocatedBuffer);\n    if (filenameTable) free((void*)filenameTable);\n}\n\nint UTIL_countPhysicalCores(void);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* UTIL_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/FreeBSD/dinode.h",
    "content": "﻿/*-\n * SPDX-License-Identifier: (BSD-2-Clause AND BSD-3-Clause)\n *\n * Copyright (c) 2002 Networks Associates Technology, Inc.\n * All rights reserved.\n *\n * This software was developed for the FreeBSD Project by Marshall\n * Kirk McKusick and Network Associates Laboratories, the Security\n * Research Division of Network Associates, Inc. under DARPA/SPAWAR\n * contract N66001-01-C-8035 (\"CBOSS\"), as part of the DARPA CHATS\n * research program\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * Copyright (c) 1982, 1989, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n * (c) UNIX System Laboratories, Inc.\n * All or some portions of this file are derived from material licensed\n * to the University of California by American Telephone and Telegraph\n * Co. or Unix System Laboratories, Inc. and are reproduced herein with\n * the permission of UNIX System Laboratories, Inc.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. The names of the authors may not be used to endorse or promote\n *    products derived from this software without specific prior written\n *    permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)dinode.h\t8.3 (Berkeley) 1/21/94\n */\n\n#ifndef _UFS_UFS_DINODE_H_\n#define\t_UFS_UFS_DINODE_H_\n\n#include <stdint.h>\n#include <sys/types.h>\n\n/*\n * The root inode is the root of the filesystem.  Inode 0 can't be used for\n * normal purposes and historically bad blocks were linked to inode 1, thus\n * the root inode is 2.  (Inode 1 is no longer used for this purpose, however\n * numerous dump tapes make this assumption, so we are stuck with it).\n */\n#define\tUFS_ROOTINO\t((ino_t)2)\n\n/*\n * The Whiteout inode# is a dummy non-zero inode number which will\n * never be allocated to a real file.  It is used as a place holder\n * in the directory entry which has been tagged as a DT_WHT entry.\n * See the comments about UFS_ROOTINO above.\n */\n#define\tUFS_WINO\t((ino_t)1)\n\n/*\n * The size of physical and logical block numbers and time fields in UFS.\n */\ntypedef\tint32_t\tufs1_daddr_t;\ntypedef\tint64_t\tufs2_daddr_t;\ntypedef int64_t ufs_lbn_t;\ntypedef int64_t ufs_time_t;\n\n/* File permissions. */\n#define\tIEXEC\t\t0000100\t\t/* Executable. */\n#define\tIWRITE\t\t0000200\t\t/* Writeable. */\n#define\tIREAD\t\t0000400\t\t/* Readable. */\n#define\tISVTX\t\t0001000\t\t/* Sticky bit. */\n#define\tISGID\t\t0002000\t\t/* Set-gid. */\n#define\tISUID\t\t0004000\t\t/* Set-uid. */\n\n/* File types. */\n#define\tIFMT\t\t0170000\t\t/* Mask of file type. */\n#define\tIFIFO\t\t0010000\t\t/* Named pipe (fifo). */\n#define\tIFCHR\t\t0020000\t\t/* Character device. */\n#define\tIFDIR\t\t0040000\t\t/* Directory file. */\n#define\tIFBLK\t\t0060000\t\t/* Block device. */\n#define\tIFREG\t\t0100000\t\t/* Regular file. */\n#define\tIFLNK\t\t0120000\t\t/* Symbolic link. */\n#define\tIFSOCK\t\t0140000\t\t/* UNIX domain socket. */\n#define\tIFWHT\t\t0160000\t\t/* Whiteout. */\n\n/*\n * A dinode contains all the meta-data associated with a UFS2 file.\n * This structure defines the on-disk format of a dinode. Since\n * this structure describes an on-disk structure, all its fields\n * are defined by types with precise widths.\n */\n\n#define\tUFS_NXADDR\t2\t\t/* External addresses in inode. */\n#define\tUFS_NDADDR\t12\t\t/* Direct addresses in inode. */\n#define\tUFS_NIADDR\t3\t\t/* Indirect addresses in inode. */\n\nstruct ufs2_dinode {\n\tuint16_t\tdi_mode;\t/*   0: IFMT, permissions; see below. */\n\tuint16_t\tdi_nlink;\t/*   2: File link count. */\n\tuint32_t\tdi_uid;\t\t/*   4: File owner. */\n\tuint32_t\tdi_gid;\t\t/*   8: File group. */\n\tuint32_t\tdi_blksize;\t/*  12: Inode blocksize. */\n\tuint64_t\tdi_size;\t/*  16: File byte count. */\n\tuint64_t\tdi_blocks;\t/*  24: Blocks actually held. */\n\tufs_time_t\tdi_atime;\t/*  32: Last access time. */\n\tufs_time_t\tdi_mtime;\t/*  40: Last modified time. */\n\tufs_time_t\tdi_ctime;\t/*  48: Last inode change time. */\n\tufs_time_t\tdi_birthtime;\t/*  56: Inode creation time. */\n\tint32_t\t\tdi_mtimensec;\t/*  64: Last modified time. */\n\tint32_t\t\tdi_atimensec;\t/*  68: Last access time. */\n\tint32_t\t\tdi_ctimensec;\t/*  72: Last inode change time. */\n\tint32_t\t\tdi_birthnsec;\t/*  76: Inode creation time. */\n\tuint32_t\tdi_gen;\t\t/*  80: Generation number. */\n\tuint32_t\tdi_kernflags;\t/*  84: Kernel flags. */\n\tuint32_t\tdi_flags;\t/*  88: Status flags (chflags). */\n\tuint32_t\tdi_extsize;\t/*  92: External attributes size. */\n\tufs2_daddr_t\tdi_extb[UFS_NXADDR];/* 96: External attributes block. */\n\tunion {\n\t\tstruct {\n\t\t\tufs2_daddr_t\tdi_db /* 112: Direct disk blocks. */\n\t\t\t    [UFS_NDADDR];\n\t\t\tufs2_daddr_t\tdi_ib /* 208: Indirect disk blocks. */\n\t\t\t    [UFS_NIADDR];\n\t\t};\n\t\tchar\tdi_shortlink\t/* 112: Embedded symbolic link. */\n\t\t    [(UFS_NDADDR + UFS_NIADDR) * sizeof(ufs2_daddr_t)];\n\t};\n\tuint64_t\tdi_modrev;\t/* 232: i_modrev for NFSv4 */\n\tunion {\n\t\tuint32_t di_freelink;\t/* 240: SUJ: Next unlinked inode. */\n\t\tuint32_t di_dirdepth;\t/* 240: IFDIR: depth from root dir */\n\t};\n\tuint32_t\tdi_ckhash;\t/* 244: if CK_INODE, its check-hash */\n\tuint32_t\tdi_spare[2];\t/* 248: Reserved; currently unused */\n};\n\n/*\n * The di_db fields may be overlaid with other information for\n * file types that do not have associated disk storage. Block\n * and character devices overlay the first data block with their\n * dev_t value. Short symbolic links place their path in the\n * di_db area.\n */\n#define\tdi_rdev di_db[0]\n\n/*\n * A UFS1 dinode contains all the meta-data associated with a UFS1 file.\n * This structure defines the on-disk format of a UFS1 dinode. Since\n * this structure describes an on-disk structure, all its fields\n * are defined by types with precise widths.\n */\nstruct ufs1_dinode {\n\tuint16_t\tdi_mode;\t/*   0: IFMT, permissions; see below. */\n\tuint16_t\tdi_nlink;\t/*   2: File link count. */\n\tunion {\n\t\tuint32_t di_freelink;\t/*   4: SUJ: Next unlinked inode. */\n\t\tuint32_t di_dirdepth;\t/*   4: IFDIR: depth from root dir */\n\t};\n\tuint64_t\tdi_size;\t/*   8: File byte count. */\n\tint32_t\t\tdi_atime;\t/*  16: Last access time. */\n\tint32_t\t\tdi_atimensec;\t/*  20: Last access time. */\n\tint32_t\t\tdi_mtime;\t/*  24: Last modified time. */\n\tint32_t\t\tdi_mtimensec;\t/*  28: Last modified time. */\n\tint32_t\t\tdi_ctime;\t/*  32: Last inode change time. */\n\tint32_t\t\tdi_ctimensec;\t/*  36: Last inode change time. */\n\tunion {\n\t\tstruct {\n\t\t\tufs1_daddr_t\tdi_db /*  40: Direct disk blocks. */\n\t\t\t    [UFS_NDADDR];\n\t\t\tufs1_daddr_t\tdi_ib /*  88: Indirect disk blocks. */\n\t\t\t    [UFS_NIADDR];\n\t\t};\n\t\tchar\tdi_shortlink\t/*  40: Embedded symbolic link. */\n\t\t    [(UFS_NDADDR + UFS_NIADDR) * sizeof(ufs1_daddr_t)];\n\t};\n\tuint32_t\tdi_flags;\t/* 100: Status flags (chflags). */\n\tuint32_t\tdi_blocks;\t/* 104: Blocks actually held. */\n\tuint32_t\tdi_gen;\t\t/* 108: Generation number. */\n\tuint32_t\tdi_uid;\t\t/* 112: File owner. */\n\tuint32_t\tdi_gid;\t\t/* 116: File group. */\n\tuint64_t\tdi_modrev;\t/* 120: i_modrev for NFSv4 */\n};\n\n#define\tUFS_LINK_MAX\t65500\t/* leave a few spare for special values */\n\n#endif /* _UFS_UFS_DINODE_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/FreeBSD/dir.h",
    "content": "﻿/*-\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Copyright (c) 1982, 1986, 1989, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n * (c) UNIX System Laboratories, Inc.\n * All or some portions of this file are derived from material licensed\n * to the University of California by American Telephone and Telegraph\n * Co. or Unix System Laboratories, Inc. and are reproduced herein with\n * the permission of UNIX System Laboratories, Inc.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)dir.h\t8.2 (Berkeley) 1/21/94\n */\n\n#ifndef _UFS_UFS_DIR_H_\n#define\t_UFS_UFS_DIR_H_\n\n#include <stdint.h>\n\n/*\n * Theoretically, directories can be more than 2Gb in length, however, in\n * practice this seems unlikely. So, we define the type doff_t as a 32-bit\n * quantity to keep down the cost of doing lookup on a 32-bit machine.\n */\n#define\tdoff_t\t\tint32_t\n#define\tMAXDIRSIZE\t(0x7fffffff)\n\n/*\n * A directory consists of some number of blocks of DIRBLKSIZ\n * bytes, where DIRBLKSIZ is chosen such that it can be transferred\n * to disk in a single atomic operation (e.g. 512 bytes on most machines).\n *\n * Each DIRBLKSIZ byte block contains some number of directory entry\n * structures, which are of variable length.  Each directory entry has\n * a struct direct at the front of it, containing its inode number,\n * the length of the entry, and the length of the name contained in\n * the entry.  These are followed by the name padded to a 4 byte boundary\n * with null bytes.  All names are guaranteed null terminated.\n * The maximum length of a name in a directory is UFS_MAXNAMLEN.\n *\n * The macro DIRSIZ(fmt, dp) gives the amount of space required to represent\n * a directory entry.  Free space in a directory is represented by\n * entries which have dp->d_reclen > DIRSIZ(fmt, dp).  All DIRBLKSIZ bytes\n * in a directory block are claimed by the directory entries.  This\n * usually results in the last entry in a directory having a large\n * dp->d_reclen.  When entries are deleted from a directory, the\n * space is returned to the previous entry in the same directory\n * block by increasing its dp->d_reclen.  If the first entry of\n * a directory block is free, then its dp->d_ino is set to 0.\n * Entries other than the first in a directory do not normally have\n * dp->d_ino set to 0.\n */\n#define\tDIRBLKSIZ\tDEV_BSIZE\n#define\tUFS_MAXNAMLEN\t255\n\nstruct\tdirect {\n\tuint32_t d_ino;\t\t/* inode number of entry */\n\tuint16_t d_reclen;\t\t/* length of this record */\n\tuint8_t  d_type; \t\t/* file type, see below */\n\tuint8_t  d_namlen;\t\t/* length of string in d_name */\n\tchar\t  d_name[UFS_MAXNAMLEN + 1];\n\t\t\t\t\t/* name with length <= UFS_MAXNAMLEN */\n};\n\n/*\n * File types\n */\n#define\tDT_UNKNOWN\t 0\n#define\tDT_FIFO\t\t 1\n#define\tDT_CHR\t\t 2\n#define\tDT_DIR\t\t 4\n#define\tDT_BLK\t\t 6\n#define\tDT_REG\t\t 8\n#define\tDT_LNK\t\t10\n#define\tDT_SOCK\t\t12\n#define\tDT_WHT\t\t14\n\n/*\n * Convert between stat structure types and directory types.\n */\n#define\tIFTODT(mode)\t(((mode) & 0170000) >> 12)\n#define\tDTTOIF(dirtype)\t((dirtype) << 12)\n\n/*\n * The DIRSIZ macro gives the minimum record length which will hold\n * the directory entry.  This requires the amount of space in struct direct\n * without the d_name field, plus enough space for the name with a terminating\n * null byte (dp->d_namlen + 1), rounded up to a 4 byte boundary.\n */\n#define\tDIR_ROUNDUP\t4\t/* Directory name roundup size */\n#define\tDIRECTSIZ(namlen) \\\n    (roundup2(__offsetof(struct direct, d_name) + (namlen) + 1, DIR_ROUNDUP))\n#if (BYTE_ORDER == LITTLE_ENDIAN)\n#define\tDIRSIZ(oldfmt, dp) \\\n    ((oldfmt) ? DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))\n#else\n#define\tDIRSIZ(oldfmt, dp) \\\n    DIRECTSIZ((dp)->d_namlen)\n#endif\n#define\tOLDDIRFMT\t1\n#define\tNEWDIRFMT\t0\n\n/*\n * Template for manipulating directories.  Should use struct direct's,\n * but the name field is UFS_MAXNAMLEN - 1, and this just won't do.\n */\nstruct dirtemplate {\n\tuint32_t\tdot_ino;\n\tint16_t\t\tdot_reclen;\n\tuint8_t\tdot_type;\n\tuint8_t\tdot_namlen;\n\tchar\t\tdot_name[4];\t/* must be multiple of 4 */\n\tuint32_t\tdotdot_ino;\n\tint16_t\t\tdotdot_reclen;\n\tuint8_t\tdotdot_type;\n\tuint8_t\tdotdot_namlen;\n\tchar\t\tdotdot_name[4];\t/* ditto */\n};\n\n/*\n * This is the old format of directories, sanz type element.\n */\nstruct odirtemplate {\n\tuint32_t\tdot_ino;\n\tint16_t\t\tdot_reclen;\n\tuint16_t\tdot_namlen;\n\tchar\t\tdot_name[4];\t/* must be multiple of 4 */\n\tuint32_t\tdotdot_ino;\n\tint16_t\t\tdotdot_reclen;\n\tuint16_t\tdotdot_namlen;\n\tchar\t\tdotdot_name[4];\t/* ditto */\n};\n#endif /* !_DIR_H_ */\n"
  },
  {
    "path": "NanaZip.Codecs/FreeBSD/fs.h",
    "content": "﻿/*-\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Copyright (c) 1982, 1986, 1993\n *\tThe Regents of the University of California.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the University nor the names of its contributors\n *    may be used to endorse or promote products derived from this software\n *    without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n *\t@(#)fs.h\t8.13 (Berkeley) 3/21/95\n */\n\n#ifndef _UFS_FFS_FS_H_\n#define\t_UFS_FFS_FS_H_\n\n#include <stdint.h>\n#include \"dinode.h\"\n\n#define NBBY 8 /* number of bits in a byte */\n\n#ifndef howmany\n#define howmany(x, y) (((x)+((y)-1))/(y))\n#endif\n\n/*\n * Each disk drive contains some number of filesystems.\n * A filesystem consists of a number of cylinder groups.\n * Each cylinder group has inodes and data.\n *\n * A filesystem is described by its super-block, which in turn\n * describes the cylinder groups.  The super-block is critical\n * data and is replicated in each cylinder group to protect against\n * catastrophic loss.  This is done at `newfs' time and the critical\n * super-block data does not change, so the copies need not be\n * referenced further unless disaster strikes.\n *\n * For filesystem fs, the offsets of the various blocks of interest\n * are given in the super block as:\n *\t[fs->fs_sblkno]\t\tSuper-block\n *\t[fs->fs_cblkno]\t\tCylinder group block\n *\t[fs->fs_iblkno]\t\tInode blocks\n *\t[fs->fs_dblkno]\t\tData blocks\n * The beginning of cylinder group cg in fs, is given by\n * the ``cgbase(fs, cg)'' macro.\n *\n * Depending on the architecture and the media, the superblock may\n * reside in any one of four places. For tiny media where every block \n * counts, it is placed at the very front of the partition. Historically,\n * UFS1 placed it 8K from the front to leave room for the disk label and\n * a small bootstrap. For UFS2 it got moved to 64K from the front to leave\n * room for the disk label and a bigger bootstrap, and for really piggy\n * systems we check at 256K from the front if the first three fail. In\n * all cases the size of the superblock will be SBLOCKSIZE. All values are\n * given in byte-offset form, so they do not imply a sector size. The\n * SBLOCKSEARCH specifies the order in which the locations should be searched.\n */\n#define\tSBLOCK_FLOPPY\t     0\n#define\tSBLOCK_UFS1\t  8192\n#define\tSBLOCK_UFS2\t 65536\n#define\tSBLOCK_PIGGY\t262144\n#define\tSBLOCKSIZE\t  8192\n#define\tSBLOCKSEARCH \\\n\t{ SBLOCK_UFS2, SBLOCK_UFS1, SBLOCK_FLOPPY, SBLOCK_PIGGY, -1 }\n/*\n * Request standard superblock location in ffs_sbget().\n */\n#define\tUFS_STDSB\t-1\t/* Search standard places for superblock */\n\n/*\n * UFS_NOMSG indicates that superblock inconsistency error messages\n *    should not be printed. It is used by programs like fsck that\n *    want to print their own error message.\n *\n * UFS_NOCSUM causes only the superblock itself to be returned, but does\n *    not read in any auxiliary data structures like the cylinder group\n *    summary information. It is used by clients like glabel that just\n *    want to check for possible filesystem types. Using UFS_NOCSUM\n *    skips the superblock checks for csum data which allows superblocks\n *    that have corrupted csum data to be read and used.\n *\n * UFS_NOHASHFAIL will note that the check hash is wrong but will still\n *    return the superblock. This is used by the bootstrap code to\n *    give the system a chance to come up so that fsck can be run to\n *    correct the problem.\n *\n * UFS_NOWARNFAIL will warn about inconsistencies but still return the\n *    superblock. It includes UFS_NOHASHFAIL. UFS_NOWARNFAIL is used by\n *    programs like fsck_ffs(8) to debug broken filesystems.\n *\n * UFS_FSRONLY will only validate the superblock fields needed to\n *    calculate where the backup filesystem superblocks are located.\n *    If these values pass their validation tests, then the superblock\n *    is returned. This flag is used as part of the attempt to find\n *    alternate superblocks when using ffs_sbsearch().\n */\n#define\tUFS_NOHASHFAIL\t0x0001\t/* Ignore check-hash failure */\n#define\tUFS_NOWARNFAIL\t0x0003\t/* Ignore non-fatal inconsistencies */\n#define\tUFS_NOMSG\t0x0004\t/* Print no error message */\n#define\tUFS_NOCSUM\t0x0008\t/* Read just the superblock without csum */\n#define\tUFS_FSRONLY\t0x0010\t/* Validate only values needed for recovery\n\t\t\t\t   of alternate superblocks */\n#define\tUFS_ALTSBLK\t0x1000\t/* Flag used internally */\n\n/*\n * Max number of fragments per block. This value is NOT tweakable.\n */\n#define\tMAXFRAG \t8\n\n/*\n * Addresses stored in inodes are capable of addressing fragments\n * of `blocks'. File system blocks of at most size MAXBSIZE can\n * be optionally broken into 2, 4, or 8 pieces, each of which is\n * addressable; these pieces may be DEV_BSIZE, or some multiple of\n * a DEV_BSIZE unit.\n *\n * Large files consist of exclusively large data blocks.  To avoid\n * undue wasted disk space, the last data block of a small file may be\n * allocated as only as many fragments of a large block as are\n * necessary.  The filesystem format retains only a single pointer\n * to such a fragment, which is a piece of a single large block that\n * has been divided.  The size of such a fragment is determinable from\n * information in the inode, using the ``blksize(fs, ip, lbn)'' macro.\n *\n * The filesystem records space availability at the fragment level;\n * to determine block availability, aligned fragments are examined.\n */\n\n/*\n * MINBSIZE is the smallest allowable block size.\n * In order to insure that it is possible to create files of size\n * 2^32 with only two levels of indirection, MINBSIZE is set to 4096.\n * MINBSIZE must be big enough to hold a cylinder group block,\n * thus changes to (struct cg) must keep its size within MINBSIZE.\n * Note that super blocks are always of size SBLOCKSIZE,\n * and that both SBLOCKSIZE and MAXBSIZE must be >= MINBSIZE.\n */\n#define\tMINBSIZE\t4096\n\n/*\n * The path name on which the filesystem is mounted is maintained\n * in fs_fsmnt. MAXMNTLEN defines the amount of space allocated in\n * the super block for this name.\n */\n#define\tMAXMNTLEN\t468\n\n/*\n * The volume name for this filesystem is maintained in fs_volname.\n * MAXVOLLEN defines the length of the buffer allocated.\n */\n#define\tMAXVOLLEN\t32\n\n/*\n * There is a 128-byte region in the superblock reserved for in-core\n * pointers to summary information. Originally this included an array\n * of pointers to blocks of struct csum; now there are just a few\n * pointers and the remaining space is padded with fs_ocsp[].\n *\n * NOCSPTRS determines the size of this padding. Historically this\n * space was used to store pointers to structures that summaried\n * filesystem usage and layout information. However, these pointers\n * left various kernel pointers in the superblock which made otherwise\n * identical superblocks appear to have differences. So, all the\n * pointers in the superblock were moved to a fs_summary_info structure\n * reducing the superblock to having only a single pointer to this\n * structure. When writing the superblock to disk, this pointer is\n * temporarily NULL'ed out so that the kernel pointer will not appear\n * in the on-disk copy of the superblock.\n */\n#define\tNOCSPTRS\t((128 / sizeof(void *)) - 1)\n\n/*\n * A summary of contiguous blocks of various sizes is maintained\n * in each cylinder group. Normally this is set by the initial\n * value of fs_maxcontig. To conserve space, a maximum summary size\n * is set by FS_MAXCONTIG.\n */\n#define\tFS_MAXCONTIG\t16\n\n/*\n * MINFREE gives the minimum acceptable percentage of filesystem\n * blocks which may be free. If the freelist drops below this level\n * only the superuser may continue to allocate blocks. This may\n * be set to 0 if no reserve of free blocks is deemed necessary,\n * however throughput drops by fifty percent if the filesystem\n * is run at between 95% and 100% full; thus the minimum default\n * value of fs_minfree is 5%. However, to get good clustering\n * performance, 10% is a better choice. hence we use 10% as our\n * default value. With 10% free space, fragmentation is not a\n * problem, so we choose to optimize for time.\n */\n#define\tMINFREE\t\t8\n#define\tDEFAULTOPT\tFS_OPTTIME\n\n/*\n * Grigoriy Orlov <gluk@ptci.ru> has done some extensive work to fine\n * tune the layout preferences for directories within a filesystem.\n * His algorithm can be tuned by adjusting the following parameters\n * which tell the system the average file size and the average number\n * of files per directory. These defaults are well selected for typical\n * filesystems, but may need to be tuned for odd cases like filesystems\n * being used for squid caches or news spools.\n */\n#define\tAVFILESIZ\t16384\t/* expected average file size */\n#define\tAFPDIR\t\t64\t/* expected number of files per directory */\n\n/*\n * The maximum number of snapshot nodes that can be associated\n * with each filesystem. This limit affects only the number of\n * snapshot files that can be recorded within the superblock so\n * that they can be found when the filesystem is mounted. However,\n * maintaining too many will slow the filesystem performance, so\n * having this limit is a good idea.\n */\n#define\tFSMAXSNAP 20\n\n/*\n * Used to identify special blocks in snapshots:\n *\n * BLK_NOCOPY - A block that was unallocated at the time the snapshot\n *\twas taken, hence does not need to be copied when written.\n * BLK_SNAP - A block held by another snapshot that is not needed by this\n *\tsnapshot. When the other snapshot is freed, the BLK_SNAP entries\n *\tare converted to BLK_NOCOPY. These are needed to allow fsck to\n *\tidentify blocks that are in use by other snapshots (which are\n *\texpunged from this snapshot).\n */\n#define\tBLK_NOCOPY ((ufs2_daddr_t)(1))\n#define\tBLK_SNAP ((ufs2_daddr_t)(2))\n\n/*\n * Sysctl values for the fast filesystem.\n */\n#define\tFFS_ADJ_REFCNT\t\t 1\t/* adjust inode reference count */\n#define\tFFS_ADJ_BLKCNT\t\t 2\t/* adjust inode used block count */\n#define\tFFS_BLK_FREE\t\t 3\t/* free range of blocks in map */\n#define\tFFS_DIR_FREE\t\t 4\t/* free specified dir inodes in map */\n#define\tFFS_FILE_FREE\t\t 5\t/* free specified file inodes in map */\n#define\tFFS_SET_FLAGS\t\t 6\t/* set filesystem flags */\n#define\tFFS_ADJ_NDIR\t\t 7\t/* adjust number of directories */\n#define\tFFS_ADJ_NBFREE\t\t 8\t/* adjust number of free blocks */\n#define\tFFS_ADJ_NIFREE\t\t 9\t/* adjust number of free inodes */\n#define\tFFS_ADJ_NFFREE\t\t10 \t/* adjust number of free frags */\n#define\tFFS_ADJ_NUMCLUSTERS\t11\t/* adjust number of free clusters */\n#define\tFFS_SET_CWD\t\t12\t/* set current directory */\n#define\tFFS_SET_DOTDOT\t\t13\t/* set inode number for \"..\" */\n#define\tFFS_UNLINK\t\t14\t/* remove a name in the filesystem */\n/* Was FFS_SET_INODE\t\t15 */\n/* Was FFS_SET_BUFOUTPUT\t16 */\n#define\tFFS_SET_SIZE\t\t17\t/* set inode size */\n#define\tFFS_ADJ_DEPTH\t\t18\t/* adjust directory inode depth */\n#define\tFFS_MAXID\t\t18\t/* number of valid ffs ids */\n\n/*\n * Command structure passed in to the filesystem to adjust filesystem values.\n */\n#define\tFFS_CMD_VERSION\t\t0x19790518\t/* version ID */\nstruct fsck_cmd {\n\tint32_t\tversion;\t/* version of command structure */\n\tint32_t\thandle;\t\t/* reference to filesystem to be changed */\n\tint64_t\tvalue;\t\t/* inode or block number to be affected */\n\tint64_t\tsize;\t\t/* amount or range to be adjusted */\n\tint64_t\tspare;\t\t/* reserved for future use */\n};\n\n/*\n * A recovery structure placed at the end of the boot block area by newfs\n * that can be used by fsck to search for alternate superblocks.\n */\nstruct fsrecovery {\n\tint32_t\tfsr_magic;\t/* magic number */\n\tint32_t\tfsr_fsbtodb;\t/* fsbtodb and dbtofsb shift constant */\n\tint32_t\tfsr_sblkno;\t/* offset of super-block in filesys */\n\tint32_t\tfsr_fpg;\t/* blocks per group * fs_frag */\n\tuint32_t fsr_ncg;\t/* number of cylinder groups */\n};\n\n/*\n * Per cylinder group information; summarized in blocks allocated\n * from first cylinder group data blocks.  These blocks have to be\n * read in from fs_csaddr (size fs_cssize) in addition to the\n * super block.\n */\nstruct csum {\n\tint32_t\tcs_ndir;\t\t/* number of directories */\n\tint32_t\tcs_nbfree;\t\t/* number of free blocks */\n\tint32_t\tcs_nifree;\t\t/* number of free inodes */\n\tint32_t\tcs_nffree;\t\t/* number of free frags */\n};\nstruct csum_total {\n\tint64_t\tcs_ndir;\t\t/* number of directories */\n\tint64_t\tcs_nbfree;\t\t/* number of free blocks */\n\tint64_t\tcs_nifree;\t\t/* number of free inodes */\n\tint64_t\tcs_nffree;\t\t/* number of free frags */\n\tint64_t\tcs_numclusters;\t\t/* number of free clusters */\n\tint64_t\tcs_spare[3];\t\t/* future expansion */\n};\n\n/*\n * Pointers to super block summary information. Placed in a separate\n * structure so there is just one pointer in the superblock.\n *\n * The pointers in this structure are used as follows:\n *   fs_contigdirs references an array that tracks the creation of new\n *\tdirectories\n *   fs_csp references a contiguous array of struct csum for\n *\tall cylinder groups\n *   fs_maxcluster references an array of cluster sizes that is computed\n *\tas cylinder groups are inspected\n *   fs_active is used when creating snapshots; it points to a bitmap\n *\tof cylinder groups for which the free-block bitmap has changed\n *\tsince the snapshot operation began.\n */\nstruct fs_summary_info {\n\tuint8_t\t*si_contigdirs;\t\t/* (u) # of contig. allocated dirs */\n\tstruct\tcsum *si_csp;\t\t/* (u) cg summary info buffer */\n\tint32_t\t*si_maxcluster;\t\t/* (u) max cluster in each cyl group */\n\tuint64_t *si_active;\t\t/* (u) used by snapshots to track fs */\n};\n#define fs_contigdirs\tfs_si->si_contigdirs\n#define fs_csp\t\tfs_si->si_csp\n#define fs_maxcluster\tfs_si->si_maxcluster\n#define fs_active\tfs_si->si_active\n\n/*\n * Super block for an FFS filesystem.\n */\nstruct fs {\n\tint32_t\t fs_firstfield;\t\t/* historic filesystem linked list, */\n\tint32_t\t fs_unused_1;\t\t/*     used for incore super blocks */\n\tint32_t\t fs_sblkno;\t\t/* offset of super-block in filesys */\n\tint32_t\t fs_cblkno;\t\t/* offset of cyl-block in filesys */\n\tint32_t\t fs_iblkno;\t\t/* offset of inode-blocks in filesys */\n\tint32_t\t fs_dblkno;\t\t/* offset of first data after cg */\n\tint32_t\t fs_old_cgoffset;\t/* cylinder group offset in cylinder */\n\tint32_t\t fs_old_cgmask;\t\t/* used to calc mod fs_ntrak */\n\tint32_t  fs_old_time;\t\t/* last time written */\n\tint32_t\t fs_old_size;\t\t/* number of blocks in fs */\n\tint32_t\t fs_old_dsize;\t\t/* number of data blocks in fs */\n\tuint32_t fs_ncg;\t\t/* number of cylinder groups */\n\tint32_t\t fs_bsize;\t\t/* size of basic blocks in fs */\n\tint32_t\t fs_fsize;\t\t/* size of frag blocks in fs */\n\tint32_t\t fs_frag;\t\t/* number of frags in a block in fs */\n/* these are configuration parameters */\n\tint32_t\t fs_minfree;\t\t/* minimum percentage of free blocks */\n\tint32_t\t fs_old_rotdelay;\t/* num of ms for optimal next block */\n\tint32_t\t fs_old_rps;\t\t/* disk revolutions per second */\n/* these fields can be computed from the others */\n\tint32_t\t fs_bmask;\t\t/* ``blkoff'' calc of blk offsets */\n\tint32_t\t fs_fmask;\t\t/* ``fragoff'' calc of frag offsets */\n\tint32_t\t fs_bshift;\t\t/* ``lblkno'' calc of logical blkno */\n\tint32_t\t fs_fshift;\t\t/* ``numfrags'' calc number of frags */\n/* these are configuration parameters */\n\tint32_t\t fs_maxcontig;\t\t/* max number of contiguous blks */\n\tint32_t\t fs_maxbpg;\t\t/* max number of blks per cyl group */\n/* these fields can be computed from the others */\n\tint32_t\t fs_fragshift;\t\t/* block to frag shift */\n\tint32_t\t fs_fsbtodb;\t\t/* fsbtodb and dbtofsb shift constant */\n\tint32_t\t fs_sbsize;\t\t/* actual size of super block */\n\tint32_t\t fs_spare1[2];\t\t/* old fs_csmask */\n\t\t\t\t\t/* old fs_csshift */\n\tint32_t\t fs_nindir;\t\t/* value of NINDIR */\n\tuint32_t fs_inopb;\t\t/* value of INOPB */\n\tint32_t\t fs_old_nspf;\t\t/* value of NSPF */\n/* yet another configuration parameter */\n\tint32_t\t fs_optim;\t\t/* optimization preference, see below */\n\tint32_t\t fs_old_npsect;\t\t/* # sectors/track including spares */\n\tint32_t\t fs_old_interleave;\t/* hardware sector interleave */\n\tint32_t\t fs_old_trackskew;\t/* sector 0 skew, per track */\n\tint32_t\t fs_id[2];\t\t/* unique filesystem id */\n/* sizes determined by number of cylinder groups and their sizes */\n\tint32_t\t fs_old_csaddr;\t\t/* blk addr of cyl grp summary area */\n\tint32_t\t fs_cssize;\t\t/* size of cyl grp summary area */\n\tint32_t\t fs_cgsize;\t\t/* cylinder group size */\n\tint32_t\t fs_spare2;\t\t/* old fs_ntrak */\n\tint32_t\t fs_old_nsect;\t\t/* sectors per track */\n\tint32_t  fs_old_spc;\t\t/* sectors per cylinder */\n\tint32_t\t fs_old_ncyl;\t\t/* cylinders in filesystem */\n\tint32_t\t fs_old_cpg;\t\t/* cylinders per group */\n\tuint32_t fs_ipg;\t\t/* inodes per group */\n\tint32_t\t fs_fpg;\t\t/* blocks per group * fs_frag */\n/* this data must be re-computed after crashes */\n\tstruct\tcsum fs_old_cstotal;\t/* cylinder summary information */\n/* these fields are cleared at mount time */\n\tint8_t   fs_fmod;\t\t/* super block modified flag */\n\tint8_t   fs_clean;\t\t/* filesystem is clean flag */\n\tint8_t \t fs_ronly;\t\t/* mounted read-only flag */\n\tint8_t   fs_old_flags;\t\t/* old FS_ flags */\n\tuint8_t\t fs_fsmnt[MAXMNTLEN];\t/* name mounted on */\n\tuint8_t\t fs_volname[MAXVOLLEN];\t/* volume name */\n\tuint64_t fs_swuid;\t\t/* system-wide uid */\n\tint32_t  fs_pad;\t\t/* due to alignment of fs_swuid */\n/* these fields retain the current block allocation info */\n\tint32_t\t fs_cgrotor;\t\t/* last cg searched */\n\tvoid \t*fs_ocsp[NOCSPTRS];\t/* padding; was list of fs_cs buffers */\n\tstruct\t fs_summary_info *fs_si;/* In-core pointer to summary info */\n\tint32_t\t fs_old_cpc;\t\t/* cyl per cycle in postbl */\n\tint32_t\t fs_maxbsize;\t\t/* maximum blocking factor permitted */\n\tint64_t\t fs_unrefs;\t\t/* number of unreferenced inodes */\n\tint64_t  fs_providersize;\t/* size of underlying GEOM provider */\n\tint64_t\t fs_metaspace;\t\t/* size of area reserved for metadata */\n\tint64_t\t fs_sparecon64[13];\t/* old rotation block list head */\n\tint64_t\t fs_sblockactualloc;\t/* byte offset of this superblock */\n\tint64_t\t fs_sblockloc;\t\t/* byte offset of standard superblock */\n\tstruct\tcsum_total fs_cstotal;\t/* (u) cylinder summary information */\n\tufs_time_t fs_time;\t\t/* last time written */\n\tint64_t\t fs_size;\t\t/* number of blocks in fs */\n\tint64_t\t fs_dsize;\t\t/* number of data blocks in fs */\n\tufs2_daddr_t fs_csaddr;\t\t/* blk addr of cyl grp summary area */\n\tint64_t\t fs_pendingblocks;\t/* (u) blocks being freed */\n\tuint32_t fs_pendinginodes;\t/* (u) inodes being freed */\n\tuint32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */\n\tuint32_t fs_avgfilesize;\t/* expected average file size */\n\tuint32_t fs_avgfpdir;\t\t/* expected # of files per directory */\n\tint32_t\t fs_save_cgsize;\t/* save real cg size to use fs_bsize */\n\tufs_time_t fs_mtime;\t\t/* Last mount or fsck time. */\n\tint32_t  fs_sujfree;\t\t/* SUJ free list */\n\tint32_t\t fs_sparecon32[21];\t/* reserved for future constants */\n\tuint32_t fs_ckhash;\t\t/* if CK_SUPERBLOCK, its check-hash */\n\tuint32_t fs_metackhash;\t/* metadata check-hash, see CK_ below */\n\tint32_t  fs_flags;\t\t/* see FS_ flags below */\n\tint32_t\t fs_contigsumsize;\t/* size of cluster summary array */ \n\tint32_t\t fs_maxsymlinklen;\t/* max length of an internal symlink */\n\tint32_t\t fs_old_inodefmt;\t/* format of on-disk inodes */\n\tuint64_t fs_maxfilesize;\t/* maximum representable file size */\n\tint64_t\t fs_qbmask;\t\t/* ~fs_bmask for use with 64-bit size */\n\tint64_t\t fs_qfmask;\t\t/* ~fs_fmask for use with 64-bit size */\n\tint32_t\t fs_state;\t\t/* validate fs_clean field */\n\tint32_t\t fs_old_postblformat;\t/* format of positional layout tables */\n\tint32_t\t fs_old_nrpos;\t\t/* number of rotational positions */\n\tint32_t\t fs_spare5[2];\t\t/* old fs_postbloff */\n\t\t\t\t\t/* old fs_rotbloff */\n\tint32_t\t fs_magic;\t\t/* magic number */\n};\n\n/* Sanity checking. */\n#ifdef CTASSERT\nCTASSERT(sizeof(struct fs) == 1376);\n#endif\n\n/*\n * Filesystem identification\n */\n#define\tFS_UFS1_MAGIC\t0x011954\t/* UFS1 fast filesystem magic number */\n#define\tFS_UFS2_MAGIC\t0x19540119\t/* UFS2 fast filesystem magic number */\n#define\tFS_BAD_MAGIC\t0x19960408\t/* UFS incomplete newfs magic number */\n#define\tFS_42INODEFMT\t-1\t\t/* 4.2BSD inode format */\n#define\tFS_44INODEFMT\t2\t\t/* 4.4BSD inode format */\n\n/*\n * Preference for optimization.\n */\n#define\tFS_OPTTIME\t0\t/* minimize allocation time */\n#define\tFS_OPTSPACE\t1\t/* minimize disk fragmentation */\n\n/*\n * Filesystem flags.\n *\n * The FS_UNCLEAN flag is set by the kernel when the filesystem was\n * mounted with fs_clean set to zero. The FS_DOSOFTDEP flag indicates\n * that the filesystem should be managed by the soft updates code.\n * Note that the FS_NEEDSFSCK flag is set and cleared by the fsck\n * utility. It is set when background fsck finds an unexpected\n * inconsistency which requires a traditional foreground fsck to be\n * run. Such inconsistencies should only be found after an uncorrectable\n * disk error. The FS_NEEDSFSCK can also be set when a mounted filesystem\n * discovers an internal inconsistency such as freeing a freed inode.\n * A foreground fsck will clear the FS_NEEDSFSCK flag when it has\n * successfully cleaned up the filesystem. The kernel uses this\n * flag to enforce that inconsistent filesystems be mounted read-only.\n *\n * The FS_METACKHASH flag when set indicates that the kernel maintains\n * one or more check hashes. The actual set of supported check hashes\n * is stored in the fs_metackhash field. Kernels that do not support\n * check hashes clear the FS_METACKHASH flag to indicate that the\n * check hashes need to be rebuilt (by fsck) before they can be used.\n *\n * When a filesystem is mounted, any flags not included in FS_SUPPORTED\n * are cleared. This lets newer features know that the filesystem has\n * been run on an older version of the filesystem and thus that data\n * structures associated with those features are out-of-date and need\n * to be rebuilt.\n *\n * FS_ACLS indicates that POSIX.1e ACLs are administratively enabled\n * for the file system, so they should be loaded from extended attributes,\n * observed for access control purposes, and be administered by object\n * owners.  FS_NFS4ACLS indicates that NFSv4 ACLs are administratively\n * enabled.  This flag is mutually exclusive with FS_ACLS.  FS_MULTILABEL\n * indicates that the TrustedBSD MAC Framework should attempt to back MAC\n * labels into extended attributes on the file system rather than maintain\n * a single mount label for all objects.\n */\n#define\tFS_UNCLEAN\t0x00000001 /* filesystem not clean at mount */\n#define\tFS_DOSOFTDEP\t0x00000002 /* filesystem using soft dependencies */\n#define\tFS_NEEDSFSCK\t0x00000004 /* filesystem needs sync fsck before mount */\n#define\tFS_SUJ       \t0x00000008 /* Filesystem using softupdate journal */\n#define\tFS_ACLS\t\t0x00000010 /* file system has POSIX.1e ACLs enabled */\n#define\tFS_MULTILABEL\t0x00000020 /* file system is MAC multi-label */\n#define\tFS_GJOURNAL\t0x00000040 /* gjournaled file system */\n#define\tFS_FLAGS_UPDATED 0x0000080 /* flags have been moved to new location */\n#define\tFS_NFS4ACLS\t0x00000100 /* file system has NFSv4 ACLs enabled */\n#define\tFS_METACKHASH\t0x00000200 /* kernel supports metadata check hashes */\n#define\tFS_TRIM\t\t0x00000400 /* issue BIO_DELETE for deleted blocks */\n#define\tFS_SUPPORTED\t0x00FFFFFF /* supported flags, others cleared at mount*/\n/*\n * Things that we may someday support, but currently do not.\n * These flags are all cleared so we know if we ran on a kernel\n * that does not support them.\n */\n#define\tFS_INDEXDIRS\t0x01000000 /* kernel supports indexed directories */\n#define\tFS_VARBLKSIZE\t0x02000000 /* kernel supports variable block sizes */\n#define\tFS_COOLOPT1\t0x04000000 /* kernel supports cool option 1 */\n#define\tFS_COOLOPT2\t0x08000000 /* kernel supports cool option 2 */\n#define\tFS_COOLOPT3\t0x10000000 /* kernel supports cool option 3 */\n#define\tFS_COOLOPT4\t0x20000000 /* kernel supports cool option 4 */\n#define\tFS_COOLOPT5\t0x40000000 /* kernel supports cool option 5 */\n#define\tFS_COOLOPT6\t0x80000000 /* kernel supports cool option 6 */\n\n/*\n * The fs_metackhash field indicates the types of metadata check-hash\n * that are maintained for a filesystem. Not all filesystems check-hash\n * all metadata.\n */\n#define\tCK_SUPERBLOCK\t0x0001\t/* the superblock */\n#define\tCK_CYLGRP\t0x0002\t/* the cylinder groups */\n#define\tCK_INODE\t0x0004\t/* inodes */\n#define\tCK_INDIR\t0x0008\t/* indirect blocks */\n#define\tCK_DIR\t\t0x0010\t/* directory contents */\n#define\tCK_SUPPORTED\t0x0007\t/* supported flags, others cleared at mount */\n/*\n * The BX_FSPRIV buffer b_xflags are used to track types of data in buffers.\n */\n#define\tBX_SUPERBLOCK\t0x00010000\t/* superblock */\n#define\tBX_CYLGRP\t0x00020000\t/* cylinder groups */\n#define\tBX_INODE\t0x00040000\t/* inodes */\n#define\tBX_INDIR\t0x00080000\t/* indirect blocks */\n#define\tBX_DIR\t\t0x00100000\t/* directory contents */\n\n#define\tPRINT_UFS_BUF_XFLAGS \"\\20\\25dir\\24indir\\23inode\\22cylgrp\\21superblock\"\n\n/*\n * Macros to access bits in the fs_active array.\n */\n#define\tACTIVECGNUM(fs, cg)  ((fs)->fs_active[(cg) / (NBBY * sizeof(uint64_t))])\n#define\tACTIVECGOFF(cg)\t     (1 << ((cg) % (NBBY * sizeof(uint64_t))))\n#define\tACTIVESET(fs, cg)    do {\t\t\t\t\t\\\n\tif ((fs)->fs_active)\t\t\t\t\t\t\\\n\t\tACTIVECGNUM((fs), (cg)) |= ACTIVECGOFF((cg));\t\t\\\n} while (0)\n#define\tACTIVECLEAR(fs, cg)\tdo {\t\t\t\t\t\\\n\tif ((fs)->fs_active)\t\t\t\t\t\t\\\n\t\tACTIVECGNUM((fs), (cg)) &= ~ACTIVECGOFF((cg));\t\t\\\n} while (0)\n\n/*\n * The size of a cylinder group is calculated by CGSIZE. The maximum size\n * is limited by the fact that cylinder groups are at most one block.\n * Its size is derived from the size of the maps maintained in the\n * cylinder group and the (struct cg) size.\n */\n#define\tCGSIZE(fs) \\\n    /* base cg */\t(sizeof(struct cg) + \\\n    /* old btotoff */\t(fs)->fs_old_cpg * sizeof(int32_t) + \\\n    /* old boff */\t(fs)->fs_old_cpg * sizeof(uint16_t) + \\\n    /* inode map */\thowmany((fs)->fs_ipg, NBBY) + \\\n    /* block map */\thowmany((fs)->fs_fpg, NBBY) + sizeof(int32_t) + \\\n    /* if present */\t((fs)->fs_contigsumsize <= 0 ? 0 : \\\n    /* cluster sum */\t(fs)->fs_contigsumsize * sizeof(int32_t) + \\\n    /* cluster map */\thowmany(fragstoblks(fs, (fs)->fs_fpg), NBBY)))\n\n/*\n * The minimal number of cylinder groups that should be created.\n */\n#define\tMINCYLGRPS\t4\n\n/*\n * Convert cylinder group to base address of its global summary info.\n */\n#define\tfs_cs(fs, indx) fs_csp[indx]\n\n/*\n * Cylinder group block for a filesystem.\n */\n#define\tCG_MAGIC\t0x090255\nstruct cg {\n\tint32_t\t cg_firstfield;\t\t/* historic cyl groups linked list */\n\tint32_t\t cg_magic;\t\t/* magic number */\n\tint32_t  cg_old_time;\t\t/* time last written */\n\tuint32_t cg_cgx;\t\t/* we are the cgx'th cylinder group */\n\tint16_t\t cg_old_ncyl;\t\t/* number of cyl's this cg */\n\tint16_t  cg_old_niblk;\t\t/* number of inode blocks this cg */\n\tuint32_t cg_ndblk;\t\t/* number of data blocks this cg */\n\tstruct\t csum cg_cs;\t\t/* cylinder summary information */\n\tuint32_t cg_rotor;\t\t/* position of last used block */\n\tuint32_t cg_frotor;\t\t/* position of last used frag */\n\tuint32_t cg_irotor;\t\t/* position of last used inode */\n\tuint32_t cg_frsum[MAXFRAG];\t/* counts of available frags */\n\tint32_t\t cg_old_btotoff;\t/* (int32) block totals per cylinder */\n\tint32_t\t cg_old_boff;\t\t/* (uint16) free block positions */\n\tuint32_t cg_iusedoff;\t\t/* (uint8) used inode map */\n\tuint32_t cg_freeoff;\t\t/* (uint8) free block map */\n\tuint32_t cg_nextfreeoff;\t/* (uint8) next available space */\n\tuint32_t cg_clustersumoff;\t/* (uint32) counts of avail clusters */\n\tuint32_t cg_clusteroff;\t\t/* (uint8) free cluster map */\n\tuint32_t cg_nclusterblks;\t/* number of clusters this cg */\n\tuint32_t cg_niblk;\t\t/* number of inode blocks this cg */\n\tuint32_t cg_initediblk;\t\t/* last initialized inode */\n\tuint32_t cg_unrefs;\t\t/* number of unreferenced inodes */\n\tint32_t\t cg_sparecon32[1];\t/* reserved for future use */\n\tuint32_t cg_ckhash;\t\t/* check-hash of this cg */\n\tufs_time_t cg_time;\t\t/* time last written */\n\tint64_t\t cg_sparecon64[3];\t/* reserved for future use */\n\t/* actually longer - space used for cylinder group maps */\n};\n\n/*\n * Macros for access to cylinder group array structures\n */\n#define\tcg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)\n#define\tcg_inosused(cgp) \\\n    ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_iusedoff))\n#define\tcg_blksfree(cgp) \\\n    ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_freeoff))\n#define\tcg_clustersfree(cgp) \\\n    ((uint8_t *)((uint8_t *)(cgp) + (cgp)->cg_clusteroff))\n#define\tcg_clustersum(cgp) \\\n    ((int32_t *)((uintptr_t)(cgp) + (cgp)->cg_clustersumoff))\n\n/*\n * Turn filesystem block numbers into disk block addresses.\n * This maps filesystem blocks to device size blocks.\n */\n#define\tfsbtodb(fs, b)\t((daddr_t)(b) << (fs)->fs_fsbtodb)\n#define\tdbtofsb(fs, b)\t((b) >> (fs)->fs_fsbtodb)\n\n/*\n * Cylinder group macros to locate things in cylinder groups.\n * They calc filesystem addresses of cylinder group data structures.\n */\n#define\tcgbase(fs, c)\t(((ufs2_daddr_t)(fs)->fs_fpg) * (c))\n#define\tcgdata(fs, c)\t(cgdmin(fs, c) + (fs)->fs_metaspace)\t/* data zone */\n#define\tcgmeta(fs, c)\t(cgdmin(fs, c))\t\t\t\t/* meta data */\n#define\tcgdmin(fs, c)\t(cgstart(fs, c) + (fs)->fs_dblkno)\t/* 1st data */\n#define\tcgimin(fs, c)\t(cgstart(fs, c) + (fs)->fs_iblkno)\t/* inode blk */\n#define\tcgsblock(fs, c)\t(cgstart(fs, c) + (fs)->fs_sblkno)\t/* super blk */\n#define\tcgtod(fs, c)\t(cgstart(fs, c) + (fs)->fs_cblkno)\t/* cg block */\n#define\tcgstart(fs, c)\t\t\t\t\t\t\t\\\n       ((fs)->fs_magic == FS_UFS2_MAGIC ? cgbase(fs, c) :\t\t\\\n       (cgbase(fs, c) + (fs)->fs_old_cgoffset * ((c) & ~((fs)->fs_old_cgmask))))\n\n/*\n * Macros for handling inode numbers:\n *     inode number to filesystem block offset.\n *     inode number to cylinder group number.\n *     inode number to filesystem block address.\n */\n#define\tino_to_cg(fs, x)\t(((ino_t)(x)) / (fs)->fs_ipg)\n#define\tino_to_fsba(fs, x)\t\t\t\t\t\t\\\n\t((ufs2_daddr_t)(cgimin(fs, ino_to_cg(fs, (ino_t)(x))) +\t\t\\\n\t    (blkstofrags((fs), ((((ino_t)(x)) % (fs)->fs_ipg) / INOPB(fs))))))\n#define\tino_to_fsbo(fs, x)\t(((ino_t)(x)) % INOPB(fs))\n\n/*\n * Give cylinder group number for a filesystem block.\n * Give cylinder group block number for a filesystem block.\n */\n#define\tdtog(fs, d)\t((d) / (fs)->fs_fpg)\n#define\tdtogd(fs, d)\t((d) % (fs)->fs_fpg)\n\n/*\n * Extract the bits for a block from a map.\n * Compute the cylinder and rotational position of a cyl block addr.\n */\n#define\tblkmap(fs, map, loc) \\\n    (((map)[(loc) / NBBY] >> ((loc) % NBBY)) & (0xff >> (NBBY - (fs)->fs_frag)))\n\n/*\n * The following macros optimize certain frequently calculated\n * quantities by using shifts and masks in place of divisions\n * modulos and multiplications.\n */\n#define\tblkoff(fs, loc)\t\t/* calculates (loc % fs->fs_bsize) */ \\\n\t((loc) & (fs)->fs_qbmask)\n#define\tfragoff(fs, loc)\t/* calculates (loc % fs->fs_fsize) */ \\\n\t((loc) & (fs)->fs_qfmask)\n#define\tlfragtosize(fs, frag)\t/* calculates ((off_t)frag * fs->fs_fsize) */ \\\n\t(((off_t)(frag)) << (fs)->fs_fshift)\n#define\tlblktosize(fs, blk)\t/* calculates ((off_t)blk * fs->fs_bsize) */ \\\n\t(((off_t)(blk)) << (fs)->fs_bshift)\n/* Use this only when `blk' is known to be small, e.g., < UFS_NDADDR. */\n#define\tsmalllblktosize(fs, blk)    /* calculates (blk * fs->fs_bsize) */ \\\n\t((blk) << (fs)->fs_bshift)\n#define\tlblkno(fs, loc)\t\t/* calculates (loc / fs->fs_bsize) */ \\\n\t((loc) >> (fs)->fs_bshift)\n#define\tnumfrags(fs, loc)\t/* calculates (loc / fs->fs_fsize) */ \\\n\t((loc) >> (fs)->fs_fshift)\n#define\tblkroundup(fs, size)\t/* calculates roundup(size, fs->fs_bsize) */ \\\n\t(((size) + (fs)->fs_qbmask) & (fs)->fs_bmask)\n#define\tfragroundup(fs, size)\t/* calculates roundup(size, fs->fs_fsize) */ \\\n\t(((size) + (fs)->fs_qfmask) & (fs)->fs_fmask)\n#define\tfragstoblks(fs, frags)\t/* calculates (frags / fs->fs_frag) */ \\\n\t((frags) >> (fs)->fs_fragshift)\n#define\tblkstofrags(fs, blks)\t/* calculates (blks * fs->fs_frag) */ \\\n\t((blks) << (fs)->fs_fragshift)\n#define\tfragnum(fs, fsb)\t/* calculates (fsb % fs->fs_frag) */ \\\n\t((fsb) & ((fs)->fs_frag - 1))\n#define\tblknum(fs, fsb)\t\t/* calculates rounddown(fsb, fs->fs_frag) */ \\\n\t((fsb) &~ ((fs)->fs_frag - 1))\n\n/*\n * Determine the number of available frags given a\n * percentage to hold in reserve.\n */\n#define\tfreespace(fs, percentreserved) \\\n\t(blkstofrags((fs), (fs)->fs_cstotal.cs_nbfree) + \\\n\t(fs)->fs_cstotal.cs_nffree - \\\n\t(((off_t)((fs)->fs_dsize)) * (percentreserved) / 100))\n\n/*\n * Determining the size of a file block in the filesystem.\n */\n#define\tblksize(fs, ip, lbn) \\\n\t(((lbn) >= UFS_NDADDR || (ip)->i_size >= \\\n\t    (uint64_t)smalllblktosize(fs, (lbn) + 1)) \\\n\t    ? (fs)->fs_bsize \\\n\t    : (fragroundup(fs, blkoff(fs, (ip)->i_size))))\n#define\tsblksize(fs, size, lbn) \\\n\t(((lbn) >= UFS_NDADDR || (size) >= ((lbn) + 1) << (fs)->fs_bshift) \\\n\t  ? (fs)->fs_bsize \\\n\t  : (fragroundup(fs, blkoff(fs, (size)))))\n\n/*\n * Number of indirects in a filesystem block.\n */\n#define\tNINDIR(fs)\t((fs)->fs_nindir)\n\n/*\n * Indirect lbns are aligned on UFS_NDADDR addresses where single indirects\n * are the negated address of the lowest lbn reachable, double indirects\n * are this lbn - 1 and triple indirects are this lbn - 2.  This yields\n * an unusual bit order to determine level.\n */\nstatic inline int\nlbn_level(ufs_lbn_t lbn)\n{\n\tif (lbn >= 0)\n\t\treturn 0;\n\tswitch (lbn & 0x3) {\n\tcase 0:\n\t\treturn (0);\n\tcase 1:\n\t\tbreak;\n\tcase 2:\n\t\treturn (2);\n\tcase 3:\n\t\treturn (1);\n\tdefault:\n\t\tbreak;\n\t}\n\treturn (-1);\n}\n\nstatic inline ufs_lbn_t\nlbn_offset(struct fs *fs, int level)\n{\n\tufs_lbn_t res;\n\n\tfor (res = 1; level > 0; level--)\n\t\tres *= NINDIR(fs);\n\treturn (res);\n}\n\n/*\n * Number of inodes in a secondary storage block/fragment.\n */\n#define\tINOPB(fs)\t((fs)->fs_inopb)\n#define\tINOPF(fs)\t((fs)->fs_inopb >> (fs)->fs_fragshift)\n\n/*\n * Softdep journal record format.\n */\n#define\tJOP_UNKNOWN\t0\t/* JOP operation is unknown */\n#define\tJOP_ADDREF\t1\t/* Add a reference to an inode. */\n#define\tJOP_REMREF\t2\t/* Remove a reference from an inode. */\n#define\tJOP_NEWBLK\t3\t/* Allocate a block. */\n#define\tJOP_FREEBLK\t4\t/* Free a block or a tree of blocks. */\n#define\tJOP_MVREF\t5\t/* Move a reference from one off to another. */\n#define\tJOP_TRUNC\t6\t/* Partial truncation record. */\n#define\tJOP_SYNC\t7\t/* fsync() complete record. */\n#define\tJOP_NUMJOPTYPES\t8\n#define JOP_NAMES {\t\\\n        \"unknown\",\t\\\n\t\"JOP_ADDREF\",\t\\\n\t\"JOP_REMREF\",\t\\\n\t\"JOP_NEWBLK\",\t\\\n\t\"JOP_FREEBLK\",\t\\\n\t\"JOP_MVREF\",\t\\\n\t\"JOP_TRUNC\",\t\\\n\t\"JOP_SYNC\" }\n#define JOP_OPTYPE(op) \\\n\t(op) < JOP_NUMJOPTYPES ? joptype[op] : joptype[JOP_UNKNOWN]\n\n#define\tJREC_SIZE\t32\t/* Record and segment header size. */\n\n#define\tSUJ_MIN\t\t(4 * 1024 * 1024)\t/* Minimum journal size */\n#define\tSUJ_FILE\t\".sujournal\"\t\t/* Journal file name */\n\n/*\n * Size of the segment record header.  There is at most one for each disk\n * block in the journal.  The segment header is followed by an array of\n * records.  fsck depends on the first element in each record being 'op'\n * and the second being 'ino'.  Segments may span multiple disk blocks but\n * the header is present on each.\n */\nstruct jsegrec {\n\tuint64_t\tjsr_seq;\t/* Our sequence number */\n\tuint64_t\tjsr_oldest;\t/* Oldest valid sequence number */\n\tuint16_t\tjsr_cnt;\t/* Count of valid records */\n\tuint16_t\tjsr_blocks;\t/* Count of device bsize blocks. */\n\tuint32_t\tjsr_crc;\t/* 32bit crc of the valid space */\n\tufs_time_t\tjsr_time;\t/* timestamp for mount instance */\n};\n\n/*\n * Reference record.  Records a single link count modification.\n */\nstruct jrefrec {\n\tuint32_t\tjr_op;\n\tuint32_t\tjr_ino;\n\tuint32_t\tjr_parent;\n\tuint16_t\tjr_nlink;\n\tuint16_t\tjr_mode;\n\tint64_t\t\tjr_diroff;\n\tuint64_t\tjr_unused;\n};\n\n/*\n * Move record.  Records a reference moving within a directory block.  The\n * nlink is unchanged but we must search both locations.\n */\nstruct jmvrec {\n\tuint32_t\tjm_op;\n\tuint32_t\tjm_ino;\n\tuint32_t\tjm_parent;\n\tuint16_t\tjm_unused;\n\tint64_t\t\tjm_oldoff;\n\tint64_t\t\tjm_newoff;\n};\n\n/*\n * Block record.  A set of frags or tree of blocks starting at an indirect are\n * freed or a set of frags are allocated.\n */\nstruct jblkrec {\n\tuint32_t\tjb_op;\n\tuint32_t\tjb_ino;\n\tufs2_daddr_t\tjb_blkno;\n\tufs_lbn_t\tjb_lbn;\n\tuint16_t\tjb_frags;\n\tuint16_t\tjb_oldfrags;\n\tuint32_t\tjb_unused;\n};\n\n/*\n * Truncation record.  Records a partial truncation so that it may be\n * completed at check time.  Also used for sync records.\n */\nstruct jtrncrec {\n\tuint32_t\tjt_op;\n\tuint32_t\tjt_ino;\n\tint64_t\t\tjt_size;\n\tuint32_t\tjt_extsize;\n\tuint32_t\tjt_pad[3];\n};\n\nunion jrec {\n\tstruct jsegrec\trec_jsegrec;\n\tstruct jrefrec\trec_jrefrec;\n\tstruct jmvrec\trec_jmvrec;\n\tstruct jblkrec\trec_jblkrec;\n\tstruct jtrncrec\trec_jtrncrec;\n};\n\n#ifdef CTASSERT\nCTASSERT(sizeof(struct jsegrec) == JREC_SIZE);\nCTASSERT(sizeof(struct jrefrec) == JREC_SIZE);\nCTASSERT(sizeof(struct jmvrec) == JREC_SIZE);\nCTASSERT(sizeof(struct jblkrec) == JREC_SIZE);\nCTASSERT(sizeof(struct jtrncrec) == JREC_SIZE);\nCTASSERT(sizeof(union jrec) == JREC_SIZE);\n#endif\n\nextern int inside[], around[];\nextern uint8_t *fragtbl[];\n\n/*\n * IOCTLs used for filesystem write suspension.\n */\n#define\tUFSSUSPEND\t_IOW('U', 1, fsid_t)\n#define\tUFSRESUME\t_IO('U', 2)\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/GmSSL/endian.h",
    "content": "﻿/*\n *  Copyright 2014-2022 The GmSSL Project. All Rights Reserved.\n *\n *  Licensed under the Apache License, Version 2.0 (the License); you may\n *  not use this file except in compliance with the License.\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n */\n\n\n#ifndef GMSSL_ENDIAN_H\n#define GMSSL_ENDIAN_H\n\n\n/* Big Endian R/W */\n\n#define GETU16(p) \\\n\t((uint16_t)(p)[0] <<  8 | \\\n\t (uint16_t)(p)[1])\n\n#define GETU32(p) \\\n\t((uint32_t)(p)[0] << 24 | \\\n\t (uint32_t)(p)[1] << 16 | \\\n\t (uint32_t)(p)[2] <<  8 | \\\n\t (uint32_t)(p)[3])\n\n#define GETU64(p) \\\n\t((uint64_t)(p)[0] << 56 | \\\n\t (uint64_t)(p)[1] << 48 | \\\n\t (uint64_t)(p)[2] << 40 | \\\n\t (uint64_t)(p)[3] << 32 | \\\n\t (uint64_t)(p)[4] << 24 | \\\n\t (uint64_t)(p)[5] << 16 | \\\n\t (uint64_t)(p)[6] <<  8 | \\\n\t (uint64_t)(p)[7])\n\n\n// 注意：PUTU32(buf, val++) 会出错！\n#define PUTU16(p,V) \\\n\t((p)[0] = (uint8_t)((V) >> 8), \\\n\t (p)[1] = (uint8_t)(V))\n\n#define PUTU32(p,V) \\\n\t((p)[0] = (uint8_t)((V) >> 24), \\\n\t (p)[1] = (uint8_t)((V) >> 16), \\\n\t (p)[2] = (uint8_t)((V) >>  8), \\\n\t (p)[3] = (uint8_t)(V))\n\n#define PUTU64(p,V) \\\n\t((p)[0] = (uint8_t)((V) >> 56), \\\n\t (p)[1] = (uint8_t)((V) >> 48), \\\n\t (p)[2] = (uint8_t)((V) >> 40), \\\n\t (p)[3] = (uint8_t)((V) >> 32), \\\n\t (p)[4] = (uint8_t)((V) >> 24), \\\n\t (p)[5] = (uint8_t)((V) >> 16), \\\n\t (p)[6] = (uint8_t)((V) >>  8), \\\n\t (p)[7] = (uint8_t)(V))\n\n/* Little Endian R/W */\n\n#define GETU16_LE(p)\t(*(const uint16_t *)(p))\n#define GETU32_LE(p)\t(*(const uint32_t *)(p))\n#define GETU64_LE(p)\t(*(const uint64_t *)(p))\n\n#define PUTU16_LE(p,V)\t*(uint16_t *)(p) = (V)\n#define PUTU32_LE(p,V)\t*(uint32_t *)(p) = (V)\n#define PUTU64_LE(p,V)\t*(uint64_t *)(p) = (V)\n\n/* Rotate */\n\n#define ROL32(a,n)     (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))\n#define ROL64(a,n)\t(((a)<<(n))|((a)>>(64-(n))))\n\n#define ROR32(a,n)\tROL32((a),32-(n))\n#define ROR64(a,n)\tROL64(a,64-n)\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/GmSSL/sm3.c",
    "content": "﻿/*\n *  Copyright 2014-2023 The GmSSL Project. All Rights Reserved.\n *\n *  Licensed under the Apache License, Version 2.0 (the License); you may\n *  not use this file except in compliance with the License.\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n */\n\n\n#include <string.h>\n#include \"sm3.h\"\n#include \"endian.h\"\n\n\n#ifdef SM3_SSE3\n# include <x86intrin.h>\n# include <immintrin.h>\n\n# define _mm_rotl_epi32(X,i) \\\n\t_mm_xor_si128(_mm_slli_epi32((X),(i)), _mm_srli_epi32((X),32-(i)))\n#endif\n\n\n#define ROTL(x,n)  (((x)<<(n)) | ((x)>>(32-(n))))\n#define P0(x) ((x) ^ ROL32((x), 9) ^ ROL32((x),17))\n#define P1(x) ((x) ^ ROL32((x),15) ^ ROL32((x),23))\n\n#define FF00(x,y,z)  ((x) ^ (y) ^ (z))\n#define FF16(x,y,z)  (((x)&(y)) | ((x)&(z)) | ((y)&(z)))\n#define GG00(x,y,z)  ((x) ^ (y) ^ (z))\n#define GG16(x,y,z)  ((((y)^(z)) & (x)) ^ (z))\n\n#define R(A, B, C, D, E, F, G, H, xx)\t\t\t\t\\\n\tSS1 = ROL32((ROL32(A, 12) + E + K[j]), 7);\t\t\\\n\tSS2 = SS1 ^ ROL32(A, 12);\t\t\t\t\\\n\tTT1 = FF##xx(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]);\t\\\n\tTT2 = GG##xx(E, F, G) + H + SS1 + W[j];\t\t\t\\\n\tB = ROL32(B, 9);\t\t\t\t\t\\\n\tH = TT1;\t\t\t\t\t\t\\\n\tF = ROL32(F, 19);\t\t\t\t\t\\\n\tD = P0(TT2);\t\t\t\t\t\t\\\n\tj++\n\n#define R8(A, B, C, D, E, F, G, H, xx)\t\t\t\t\\\n\tR(A, B, C, D, E, F, G, H, xx);\t\t\t\t\\\n\tR(H, A, B, C, D, E, F, G, xx);\t\t\t\t\\\n\tR(G, H, A, B, C, D, E, F, xx);\t\t\t\t\\\n\tR(F, G, H, A, B, C, D, E, xx);\t\t\t\t\\\n\tR(E, F, G, H, A, B, C, D, xx);\t\t\t\t\\\n\tR(D, E, F, G, H, A, B, C, xx);\t\t\t\t\\\n\tR(C, D, E, F, G, H, A, B, xx);\t\t\t\t\\\n\tR(B, C, D, E, F, G, H, A, xx)\n\n\n\n#define T00 0x79cc4519U\n#define T16 0x7a879d8aU\n\n#define K0\t0x79cc4519U\n#define K1\t0xf3988a32U\n#define K2\t0xe7311465U\n#define K3\t0xce6228cbU\n#define K4\t0x9cc45197U\n#define K5\t0x3988a32fU\n#define K6\t0x7311465eU\n#define K7\t0xe6228cbcU\n#define K8\t0xcc451979U\n#define K9\t0x988a32f3U\n#define K10\t0x311465e7U\n#define K11\t0x6228cbceU\n#define K12\t0xc451979cU\n#define K13\t0x88a32f39U\n#define K14\t0x11465e73U\n#define K15\t0x228cbce6U\n#define K16\t0x9d8a7a87U\n#define K17\t0x3b14f50fU\n#define K18\t0x7629ea1eU\n#define K19\t0xec53d43cU\n#define K20\t0xd8a7a879U\n#define K21\t0xb14f50f3U\n#define K22\t0x629ea1e7U\n#define K23\t0xc53d43ceU\n#define K24\t0x8a7a879dU\n#define K25\t0x14f50f3bU\n#define K26\t0x29ea1e76U\n#define K27\t0x53d43cecU\n#define K28\t0xa7a879d8U\n#define K29\t0x4f50f3b1U\n#define K30\t0x9ea1e762U\n#define K31\t0x3d43cec5U\n#define K32\t0x7a879d8aU\n#define K33\t0xf50f3b14U\n#define K34\t0xea1e7629U\n#define K35\t0xd43cec53U\n#define K36\t0xa879d8a7U\n#define K37\t0x50f3b14fU\n#define K38\t0xa1e7629eU\n#define K39\t0x43cec53dU\n#define K40\t0x879d8a7aU\n#define K41\t0x0f3b14f5U\n#define K42\t0x1e7629eaU\n#define K43\t0x3cec53d4U\n#define K44\t0x79d8a7a8U\n#define K45\t0xf3b14f50U\n#define K46\t0xe7629ea1U\n#define K47\t0xcec53d43U\n#define K48\t0x9d8a7a87U\n#define K49\t0x3b14f50fU\n#define K50\t0x7629ea1eU\n#define K51\t0xec53d43cU\n#define K52\t0xd8a7a879U\n#define K53\t0xb14f50f3U\n#define K54\t0x629ea1e7U\n#define K55\t0xc53d43ceU\n#define K56\t0x8a7a879dU\n#define K57\t0x14f50f3bU\n#define K58\t0x29ea1e76U\n#define K59\t0x53d43cecU\n#define K60\t0xa7a879d8U\n#define K61\t0x4f50f3b1U\n#define K62\t0x9ea1e762U\n#define K63\t0x3d43cec5U\n\nstatic uint32_t K[64] = {\n\tK0,  K1,  K2,  K3,  K4,  K5,  K6,  K7,\n\tK8,  K9,  K10, K11, K12, K13, K14, K15,\n\tK16, K17, K18, K19, K20, K21, K22, K23,\n\tK24, K25, K26, K27, K28, K29, K30, K31,\n\tK32, K33, K34, K35, K36, K37, K38, K39,\n\tK40, K41, K42, K43, K44, K45, K46, K47,\n\tK48, K49, K50, K51, K52, K53, K54, K55,\n\tK56, K57, K58, K59, K60, K61, K62, K63,\n\t/*\n\t0x79cc4519U, 0xf3988a32U, 0xe7311465U, 0xce6228cbU,\n\t0x9cc45197U, 0x3988a32fU, 0x7311465eU, 0xe6228cbcU,\n\t0xcc451979U, 0x988a32f3U, 0x311465e7U, 0x6228cbceU,\n\t0xc451979cU, 0x88a32f39U, 0x11465e73U, 0x228cbce6U,\n\t0x9d8a7a87U, 0x3b14f50fU, 0x7629ea1eU, 0xec53d43cU,\n\t0xd8a7a879U, 0xb14f50f3U, 0x629ea1e7U, 0xc53d43ceU,\n\t0x8a7a879dU, 0x14f50f3bU, 0x29ea1e76U, 0x53d43cecU,\n\t0xa7a879d8U, 0x4f50f3b1U, 0x9ea1e762U, 0x3d43cec5U,\n\t0x7a879d8aU, 0xf50f3b14U, 0xea1e7629U, 0xd43cec53U,\n\t0xa879d8a7U, 0x50f3b14fU, 0xa1e7629eU, 0x43cec53dU,\n\t0x879d8a7aU, 0x0f3b14f5U, 0x1e7629eaU, 0x3cec53d4U,\n\t0x79d8a7a8U, 0xf3b14f50U, 0xe7629ea1U, 0xcec53d43U,\n\t0x9d8a7a87U, 0x3b14f50fU, 0x7629ea1eU, 0xec53d43cU,\n\t0xd8a7a879U, 0xb14f50f3U, 0x629ea1e7U, 0xc53d43ceU,\n\t0x8a7a879dU, 0x14f50f3bU, 0x29ea1e76U, 0x53d43cecU,\n\t0xa7a879d8U, 0x4f50f3b1U, 0x9ea1e762U, 0x3d43cec5U,\n\t*/\n};\n\n#ifndef SM3_AVX_BMI2\nvoid sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks)\n{\n\tuint32_t A;\n\tuint32_t B;\n\tuint32_t C;\n\tuint32_t D;\n\tuint32_t E;\n\tuint32_t F;\n\tuint32_t G;\n\tuint32_t H;\n\tuint32_t W[68];\n\tuint32_t SS1, SS2, TT1, TT2;\n\tint j;\n\n#ifdef SM3_SSE3\n\t__m128i X, T, R;\n\t__m128i M = _mm_setr_epi32(0, 0, 0, 0xffffffff);\n\t__m128i V = _mm_setr_epi8(3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12);\n#endif\n\n\twhile (blocks--) {\n\n\t\tA = digest[0];\n\t\tB = digest[1];\n\t\tC = digest[2];\n\t\tD = digest[3];\n\t\tE = digest[4];\n\t\tF = digest[5];\n\t\tG = digest[6];\n\t\tH = digest[7];\n\n\n#ifdef SM3_SSE3\n\n\t\tfor (j = 0; j < 16; j += 4) {\n\t\t\tX = _mm_loadu_si128((__m128i *)(data + j * 4));\n\t\t\tX = _mm_shuffle_epi8(X, V);\n\t\t\t_mm_storeu_si128((__m128i *)(W + j), X);\n\t\t}\n\n\t\tfor (j = 16; j < 68; j += 4) {\n\t\t\t/* X = (W[j - 3], W[j - 2], W[j - 1], 0) */\n\t\t\tX = _mm_loadu_si128((__m128i *)(W + j - 3));\n\t\t\tX = _mm_andnot_si128(M, X);\n\n\t\t\tX = _mm_rotl_epi32(X, 15);\n\t\t\tT = _mm_loadu_si128((__m128i *)(W + j - 9));\n\t\t\tX = _mm_xor_si128(X, T);\n\t\t\tT = _mm_loadu_si128((__m128i *)(W + j - 16));\n\t\t\tX = _mm_xor_si128(X, T);\n\n\t\t\t/* P1() */\n\t\t\tT = _mm_rotl_epi32(X, (23 - 15));\n\t\t\tT = _mm_xor_si128(T, X);\n\t\t\tT = _mm_rotl_epi32(T, 15);\n\t\t\tX = _mm_xor_si128(X, T);\n\n\t\t\tT = _mm_loadu_si128((__m128i *)(W + j - 13));\n\t\t\tT = _mm_rotl_epi32(T, 7);\n\t\t\tX = _mm_xor_si128(X, T);\n\t\t\tT = _mm_loadu_si128((__m128i *)(W + j - 6));\n\t\t\tX = _mm_xor_si128(X, T);\n\n\t\t\t/* W[j + 3] ^= P1(ROL32(W[j + 1], 15)) */\n\t\t\tR = _mm_shuffle_epi32(X, 0);\n\t\t\tR = _mm_and_si128(R, M);\n\t\t\tT = _mm_rotl_epi32(R, 15);\n\t\t\tT = _mm_xor_si128(T, R);\n\t\t\tT = _mm_rotl_epi32(T, 9);\n\t\t\tR = _mm_xor_si128(R, T);\n\t\t\tR = _mm_rotl_epi32(R, 6);\n\t\t\tX = _mm_xor_si128(X, R);\n\n\t\t\t_mm_storeu_si128((__m128i *)(W + j), X);\n\t\t}\n#else\n\t\tfor (j = 0; j < 16; j++)\n\t\t\tW[j] = GETU32(data + j*4);\n\n\t\tfor (; j < 68; j++)\n\t\t\tW[j] = P1(W[j - 16] ^ W[j - 9] ^ ROL32(W[j - 3], 15))\n\t\t\t\t^ ROL32(W[j - 13], 7) ^ W[j - 6];\n#endif\n\n\n\t\tj = 0;\n\n#define FULL_UNROLL\n#ifdef FULL_UNROLL\n\t\tR8(A, B, C, D, E, F, G, H, 00);\n\t\tR8(A, B, C, D, E, F, G, H, 00);\n\t\tR8(A, B, C, D, E, F, G, H, 16);\n\t\tR8(A, B, C, D, E, F, G, H, 16);\n\t\tR8(A, B, C, D, E, F, G, H, 16);\n\t\tR8(A, B, C, D, E, F, G, H, 16);\n\t\tR8(A, B, C, D, E, F, G, H, 16);\n\t\tR8(A, B, C, D, E, F, G, H, 16);\n#else\n\t\tfor (; j < 16; j++) {\n\t\t\tSS1 = ROL32((ROL32(A, 12) + E + K(j)), 7);\n\t\t\tSS2 = SS1 ^ ROL32(A, 12);\n\t\t\tTT1 = FF00(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]);\n\t\t\tTT2 = GG00(E, F, G) + H + SS1 + W[j];\n\t\t\tD = C;\n\t\t\tC = ROL32(B, 9);\n\t\t\tB = A;\n\t\t\tA = TT1;\n\t\t\tH = G;\n\t\t\tG = ROL32(F, 19);\n\t\t\tF = E;\n\t\t\tE = P0(TT2);\n\t\t}\n\n\t\tfor (; j < 64; j++) {\n\t\t\tSS1 = ROL32((ROL32(A, 12) + E + K(j)), 7);\n\t\t\tSS2 = SS1 ^ ROL32(A, 12);\n\t\t\tTT1 = FF16(A, B, C) + D + SS2 + (W[j] ^ W[j + 4]);\n\t\t\tTT2 = GG16(E, F, G) + H + SS1 + W[j];\n\t\t\tD = C;\n\t\t\tC = ROL32(B, 9);\n\t\t\tB = A;\n\t\t\tA = TT1;\n\t\t\tH = G;\n\t\t\tG = ROL32(F, 19);\n\t\t\tF = E;\n\t\t\tE = P0(TT2);\n\t\t}\n#endif\n\n\t\tdigest[0] ^= A;\n\t\tdigest[1] ^= B;\n\t\tdigest[2] ^= C;\n\t\tdigest[3] ^= D;\n\t\tdigest[4] ^= E;\n\t\tdigest[5] ^= F;\n\t\tdigest[6] ^= G;\n\t\tdigest[7] ^= H;\n\n\t\tdata += 64;\n\t}\n}\n#endif\n\nvoid sm3_init(SM3_CTX *ctx)\n{\n\tmemset(ctx, 0, sizeof(*ctx));\n\tctx->digest[0] = 0x7380166F;\n\tctx->digest[1] = 0x4914B2B9;\n\tctx->digest[2] = 0x172442D7;\n\tctx->digest[3] = 0xDA8A0600;\n\tctx->digest[4] = 0xA96F30BC;\n\tctx->digest[5] = 0x163138AA;\n\tctx->digest[6] = 0xE38DEE4D;\n\tctx->digest[7] = 0xB0FB0E4E;\n}\n\nvoid sm3_update(SM3_CTX *ctx, const uint8_t *data, size_t data_len)\n{\n\tsize_t blocks;\n\n\tctx->num &= 0x3f;\n\tif (ctx->num) {\n\t\tsize_t left = SM3_BLOCK_SIZE - ctx->num;\n\t\tif (data_len < left) {\n\t\t\tmemcpy(ctx->block + ctx->num, data, data_len);\n\t\t\tctx->num += data_len;\n\t\t\treturn;\n\t\t} else {\n\t\t\tmemcpy(ctx->block + ctx->num, data, left);\n\t\t\tsm3_compress_blocks(ctx->digest, ctx->block, 1);\n\t\t\tctx->nblocks++;\n\t\t\tdata += left;\n\t\t\tdata_len -= left;\n\t\t}\n\t}\n\n\tblocks = data_len / SM3_BLOCK_SIZE;\n\tif (blocks) {\n\t\tsm3_compress_blocks(ctx->digest, data, blocks);\n\t\tctx->nblocks += blocks;\n\t\tdata += SM3_BLOCK_SIZE * blocks;\n\t\tdata_len -= SM3_BLOCK_SIZE * blocks;\n\t}\n\n\tctx->num = data_len;\n\tif (data_len) {\n\t\tmemcpy(ctx->block, data, data_len);\n\t}\n}\n\nvoid sm3_finish(SM3_CTX *ctx, uint8_t *digest)\n{\n\tint i;\n\n\tctx->num &= 0x3f;\n\tctx->block[ctx->num] = 0x80;\n\n\tif (ctx->num <= SM3_BLOCK_SIZE - 9) {\n\t\tmemset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 9);\n\t} else {\n\t\tmemset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 1);\n\t\tsm3_compress_blocks(ctx->digest, ctx->block, 1);\n\t\tmemset(ctx->block, 0, SM3_BLOCK_SIZE - 8);\n\t}\n\tPUTU32(ctx->block + 56, ctx->nblocks >> 23);\n\tPUTU32(ctx->block + 60, (ctx->nblocks << 9) + (ctx->num << 3));\n\n\tsm3_compress_blocks(ctx->digest, ctx->block, 1);\n\tfor (i = 0; i < 8; i++) {\n\t\tPUTU32(digest + i*4, ctx->digest[i]);\n\t}\n}\n\nvoid sm3_digest(const uint8_t *msg, size_t msglen,\n\tuint8_t dgst[SM3_DIGEST_SIZE])\n{\n\tSM3_CTX ctx;\n\tsm3_init(&ctx);\n\tsm3_update(&ctx, msg, msglen);\n\tsm3_finish(&ctx, dgst);\n\tmemset(&ctx, 0, sizeof(ctx));\n}\n"
  },
  {
    "path": "NanaZip.Codecs/GmSSL/sm3.h",
    "content": "﻿/*\n *  Copyright 2014-2022 The GmSSL Project. All Rights Reserved.\n *\n *  Licensed under the Apache License, Version 2.0 (the License); you may\n *  not use this file except in compliance with the License.\n *\n *  http://www.apache.org/licenses/LICENSE-2.0\n */\n\n\n#ifndef GMSSL_SM3_H\n#define GMSSL_SM3_H\n\n#include <string.h>\n#include <stdint.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\nSM3 Public API\n\n\tSM3_DIGEST_SIZE\n\tSM3_HMAC_SIZE\n\n\tSM3_CTX\n\tsm3_init\n\tsm3_update\n\tsm3_finish\n\n\tSM3_HMAC_CTX\n\tsm3_hmac_init\n\tsm3_hmac_update\n\tsm3_hmac_finish\n\n\tsm3_digest\n\tsm3_hmac\n*/\n\n#define SM3_IS_BIG_ENDIAN\t1\n\n#define SM3_DIGEST_SIZE\t\t32\n#define SM3_BLOCK_SIZE\t\t64\n#define SM3_STATE_WORDS\t\t8\n#define SM3_HMAC_SIZE\t\t(SM3_DIGEST_SIZE)\n\n\ntypedef struct {\n\tuint32_t digest[SM3_STATE_WORDS];\n\tuint64_t nblocks;\n\tuint8_t block[SM3_BLOCK_SIZE];\n\tsize_t num;\n} SM3_CTX;\n\nvoid sm3_init(SM3_CTX *ctx);\nvoid sm3_update(SM3_CTX *ctx, const uint8_t *data, size_t datalen);\nvoid sm3_finish(SM3_CTX *ctx, uint8_t dgst[SM3_DIGEST_SIZE]);\nvoid sm3_digest(const uint8_t *data, size_t datalen, uint8_t dgst[SM3_DIGEST_SIZE]);\n\nvoid sm3_compress_blocks(uint32_t digest[8], const uint8_t *data, size_t blocks);\n\ntypedef struct {\n\tSM3_CTX sm3_ctx;\n\tuint8_t key[SM3_BLOCK_SIZE];\n} SM3_HMAC_CTX;\n\nvoid sm3_hmac_init(SM3_HMAC_CTX *ctx, const uint8_t *key, size_t keylen);\nvoid sm3_hmac_update(SM3_HMAC_CTX *ctx, const uint8_t *data, size_t datalen);\nvoid sm3_hmac_finish(SM3_HMAC_CTX *ctx, uint8_t mac[SM3_HMAC_SIZE]);\nvoid sm3_hmac(const uint8_t *key, size_t keylen,\n\tconst uint8_t *data, size_t datalen,\n\tuint8_t mac[SM3_HMAC_SIZE]);\n\n\ntypedef struct {\n\tSM3_CTX sm3_ctx;\n\tsize_t outlen;\n} SM3_KDF_CTX;\n\nvoid sm3_kdf_init(SM3_KDF_CTX *ctx, size_t outlen);\nvoid sm3_kdf_update(SM3_KDF_CTX *ctx, const uint8_t *data, size_t datalen);\nvoid sm3_kdf_finish(SM3_KDF_CTX *ctx, uint8_t *out);\n\n\n#ifdef __cplusplus\n}\n#endif\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LZ4/lz4.c",
    "content": "﻿/*\n   LZ4 - Fast LZ compression algorithm\n   Copyright (C) 2011-2023, Yann Collet.\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n    - LZ4 homepage : http://www.lz4.org\n    - LZ4 source repository : https://github.com/lz4/lz4\n*/\n\n/*-************************************\n*  Tuning parameters\n**************************************/\n/*\n * LZ4_HEAPMODE :\n * Select how stateless compression functions like `LZ4_compress_default()`\n * allocate memory for their hash table,\n * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).\n */\n#ifndef LZ4_HEAPMODE\n#  define LZ4_HEAPMODE 0\n#endif\n\n/*\n * LZ4_ACCELERATION_DEFAULT :\n * Select \"acceleration\" for LZ4_compress_fast() when parameter value <= 0\n */\n#define LZ4_ACCELERATION_DEFAULT 1\n/*\n * LZ4_ACCELERATION_MAX :\n * Any \"acceleration\" value higher than this threshold\n * get treated as LZ4_ACCELERATION_MAX instead (fix #876)\n */\n#define LZ4_ACCELERATION_MAX 65537\n\n\n/*-************************************\n*  CPU Feature Detection\n**************************************/\n/* LZ4_FORCE_MEMORY_ACCESS\n * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.\n * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.\n * The below switch allow to select different access method for improved performance.\n * Method 0 (default) : use `memcpy()`. Safe and portable.\n * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).\n *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.\n * Method 2 : direct access. This method is portable but violate C standard.\n *            It can generate buggy code on targets which assembly generation depends on alignment.\n *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)\n * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.\n * Prefer these methods in priority order (0 > 1 > 2)\n */\n#ifndef LZ4_FORCE_MEMORY_ACCESS   /* can be defined externally */\n#  if defined(__GNUC__) && \\\n  ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) \\\n  || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )\n#    define LZ4_FORCE_MEMORY_ACCESS 2\n#  elif (defined(__INTEL_COMPILER) && !defined(_WIN32)) || defined(__GNUC__) || defined(_MSC_VER)\n#    define LZ4_FORCE_MEMORY_ACCESS 1\n#  endif\n#endif\n\n/*\n * LZ4_FORCE_SW_BITCOUNT\n * Define this parameter if your target system or compiler does not support hardware bit count\n */\n#if defined(_MSC_VER) && defined(_WIN32_WCE)   /* Visual Studio for WinCE doesn't support Hardware bit count */\n#  undef  LZ4_FORCE_SW_BITCOUNT  /* avoid double def */\n#  define LZ4_FORCE_SW_BITCOUNT\n#endif\n\n\n\n/*-************************************\n*  Dependency\n**************************************/\n/*\n * LZ4_SRC_INCLUDED:\n * Amalgamation flag, whether lz4.c is included\n */\n#ifndef LZ4_SRC_INCLUDED\n#  define LZ4_SRC_INCLUDED 1\n#endif\n\n#ifndef LZ4_DISABLE_DEPRECATE_WARNINGS\n#  define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */\n#endif\n\n#ifndef LZ4_STATIC_LINKING_ONLY\n#  define LZ4_STATIC_LINKING_ONLY\n#endif\n#include \"lz4.h\"\n/* see also \"memory routines\" below */\n\n\n/*-************************************\n*  Compiler Options\n**************************************/\n#if defined(_MSC_VER) && (_MSC_VER >= 1400)  /* Visual Studio 2005+ */\n#  include <intrin.h>               /* only present in VS2005+ */\n#  pragma warning(disable : 4127)   /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 6237)   /* disable: C6237: conditional expression is always 0 */\n#  pragma warning(disable : 6239)   /* disable: C6239: (<non-zero constant> && <expression>) always evaluates to the result of <expression> */\n#  pragma warning(disable : 6240)   /* disable: C6240: (<expression> && <non-zero constant>) always evaluates to the result of <expression> */\n#  pragma warning(disable : 6326)   /* disable: C6326: Potential comparison of a constant with another constant */\n#endif  /* _MSC_VER */\n\n#ifndef LZ4_FORCE_INLINE\n#  if defined (_MSC_VER) && !defined (__clang__)    /* MSVC */\n#    define LZ4_FORCE_INLINE static __forceinline\n#  else\n#    if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#      if defined (__GNUC__) || defined (__clang__)\n#        define LZ4_FORCE_INLINE static inline __attribute__((always_inline))\n#      else\n#        define LZ4_FORCE_INLINE static inline\n#      endif\n#    else\n#      define LZ4_FORCE_INLINE static\n#    endif /* __STDC_VERSION__ */\n#  endif  /* _MSC_VER */\n#endif /* LZ4_FORCE_INLINE */\n\n/* LZ4_FORCE_O2 and LZ4_FORCE_INLINE\n * gcc on ppc64le generates an unrolled SIMDized loop for LZ4_wildCopy8,\n * together with a simple 8-byte copy loop as a fall-back path.\n * However, this optimization hurts the decompression speed by >30%,\n * because the execution does not go to the optimized loop\n * for typical compressible data, and all of the preamble checks\n * before going to the fall-back path become useless overhead.\n * This optimization happens only with the -O3 flag, and -O2 generates\n * a simple 8-byte copy loop.\n * With gcc on ppc64le, all of the LZ4_decompress_* and LZ4_wildCopy8\n * functions are annotated with __attribute__((optimize(\"O2\"))),\n * and also LZ4_wildCopy8 is forcibly inlined, so that the O2 attribute\n * of LZ4_wildCopy8 does not affect the compression speed.\n */\n#if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) && defined(__GNUC__) && !defined(__clang__)\n#  define LZ4_FORCE_O2  __attribute__((optimize(\"O2\")))\n#  undef LZ4_FORCE_INLINE\n#  define LZ4_FORCE_INLINE  static __inline __attribute__((optimize(\"O2\"),always_inline))\n#else\n#  define LZ4_FORCE_O2\n#endif\n\n#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)\n#  define expect(expr,value)    (__builtin_expect ((expr),(value)) )\n#else\n#  define expect(expr,value)    (expr)\n#endif\n\n#ifndef likely\n#define likely(expr)     expect((expr) != 0, 1)\n#endif\n#ifndef unlikely\n#define unlikely(expr)   expect((expr) != 0, 0)\n#endif\n\n/* Should the alignment test prove unreliable, for some reason,\n * it can be disabled by setting LZ4_ALIGN_TEST to 0 */\n#ifndef LZ4_ALIGN_TEST  /* can be externally provided */\n# define LZ4_ALIGN_TEST 1\n#endif\n\n\n/*-************************************\n*  Memory routines\n**************************************/\n\n/*! LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION :\n *  Disable relatively high-level LZ4/HC functions that use dynamic memory\n *  allocation functions (malloc(), calloc(), free()).\n *\n *  Note that this is a compile-time switch. And since it disables\n *  public/stable LZ4 v1 API functions, we don't recommend using this\n *  symbol to generate a library for distribution.\n *\n *  The following public functions are removed when this symbol is defined.\n *  - lz4   : LZ4_createStream, LZ4_freeStream,\n *            LZ4_createStreamDecode, LZ4_freeStreamDecode, LZ4_create (deprecated)\n *  - lz4hc : LZ4_createStreamHC, LZ4_freeStreamHC,\n *            LZ4_createHC (deprecated), LZ4_freeHC  (deprecated)\n *  - lz4frame, lz4file : All LZ4F_* functions\n */\n#if defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\n#  define ALLOC(s)          lz4_error_memory_allocation_is_disabled\n#  define ALLOC_AND_ZERO(s) lz4_error_memory_allocation_is_disabled\n#  define FREEMEM(p)        lz4_error_memory_allocation_is_disabled\n#elif defined(LZ4_USER_MEMORY_FUNCTIONS)\n/* memory management functions can be customized by user project.\n * Below functions must exist somewhere in the Project\n * and be available at link time */\nvoid* LZ4_malloc(size_t s);\nvoid* LZ4_calloc(size_t n, size_t s);\nvoid  LZ4_free(void* p);\n# define ALLOC(s)          LZ4_malloc(s)\n# define ALLOC_AND_ZERO(s) LZ4_calloc(1,s)\n# define FREEMEM(p)        LZ4_free(p)\n#else\n# include <stdlib.h>   /* malloc, calloc, free */\n# define ALLOC(s)          malloc(s)\n# define ALLOC_AND_ZERO(s) calloc(1,s)\n# define FREEMEM(p)        free(p)\n#endif\n\n#if ! LZ4_FREESTANDING\n#  include <string.h>   /* memset, memcpy */\n#endif\n#if !defined(LZ4_memset)\n#  define LZ4_memset(p,v,s) memset((p),(v),(s))\n#endif\n#define MEM_INIT(p,v,s)   LZ4_memset((p),(v),(s))\n\n\n/*-************************************\n*  Common Constants\n**************************************/\n#define MINMATCH 4\n\n#define WILDCOPYLENGTH 8\n#define LASTLITERALS   5   /* see ../doc/lz4_Block_format.md#parsing-restrictions */\n#define MFLIMIT       12   /* see ../doc/lz4_Block_format.md#parsing-restrictions */\n#define MATCH_SAFEGUARD_DISTANCE  ((2*WILDCOPYLENGTH) - MINMATCH)   /* ensure it's possible to write 2 x wildcopyLength without overflowing output buffer */\n#define FASTLOOP_SAFE_DISTANCE 64\nstatic const int LZ4_minLength = (MFLIMIT+1);\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define LZ4_DISTANCE_ABSOLUTE_MAX 65535\n#if (LZ4_DISTANCE_MAX > LZ4_DISTANCE_ABSOLUTE_MAX)   /* max supported by LZ4 format */\n#  error \"LZ4_DISTANCE_MAX is too big : must be <= 65535\"\n#endif\n\n#define ML_BITS  4\n#define ML_MASK  ((1U<<ML_BITS)-1)\n#define RUN_BITS (8-ML_BITS)\n#define RUN_MASK ((1U<<RUN_BITS)-1)\n\n\n/*-************************************\n*  Error detection\n**************************************/\n#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)\n#  include <assert.h>\n#else\n#  ifndef assert\n#    define assert(condition) ((void)0)\n#  endif\n#endif\n\n#define LZ4_STATIC_ASSERT(c)   { enum { LZ4_static_assert = 1/(int)(!!(c)) }; }   /* use after variable declarations */\n\n#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2)\n#  include <stdio.h>\n   static int g_debuglog_enable = 1;\n#  define DEBUGLOG(l, ...) {                          \\\n        if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) {  \\\n            fprintf(stderr, __FILE__  \" %i: \", __LINE__); \\\n            fprintf(stderr, __VA_ARGS__);             \\\n            fprintf(stderr, \" \\n\");                   \\\n    }   }\n#else\n#  define DEBUGLOG(l, ...) {}    /* disabled */\n#endif\n\nstatic int LZ4_isAligned(const void* ptr, size_t alignment)\n{\n    return ((size_t)ptr & (alignment -1)) == 0;\n}\n\n\n/*-************************************\n*  Types\n**************************************/\n#include <limits.h>\n#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# include <stdint.h>\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef uintptr_t uptrval;\n#else\n# if UINT_MAX != 4294967295UL\n#   error \"LZ4 code (when not C++ or C99) assumes that sizeof(int) == 4\"\n# endif\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef size_t              uptrval;   /* generally true, except OpenVMS-64 */\n#endif\n\n#if defined(__x86_64__)\n  typedef U64    reg_t;   /* 64-bits in x32 mode */\n#else\n  typedef size_t reg_t;   /* 32-bits in x32 mode */\n#endif\n\ntypedef enum {\n    notLimited = 0,\n    limitedOutput = 1,\n    fillOutput = 2\n} limitedOutput_directive;\n\n\n/*-************************************\n*  Reading and writing into memory\n**************************************/\n\n/**\n * LZ4 relies on memcpy with a constant size being inlined. In freestanding\n * environments, the compiler can't assume the implementation of memcpy() is\n * standard compliant, so it can't apply its specialized memcpy() inlining\n * logic. When possible, use __builtin_memcpy() to tell the compiler to analyze\n * memcpy() as if it were standard compliant, so it can inline it in freestanding\n * environments. This is needed when decompressing the Linux Kernel, for example.\n */\n#if !defined(LZ4_memcpy)\n#  if defined(__GNUC__) && (__GNUC__ >= 4)\n#    define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)\n#  else\n#    define LZ4_memcpy(dst, src, size) memcpy(dst, src, size)\n#  endif\n#endif\n\n#if !defined(LZ4_memmove)\n#  if defined(__GNUC__) && (__GNUC__ >= 4)\n#    define LZ4_memmove __builtin_memmove\n#  else\n#    define LZ4_memmove memmove\n#  endif\n#endif\n\nstatic unsigned LZ4_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental */\n    return one.c[0];\n}\n\n#if defined(__GNUC__) || defined(__INTEL_COMPILER)\n#define LZ4_PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))\n#elif defined(_MSC_VER)\n#define LZ4_PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))\n#endif\n\n#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)\n/* lie to the compiler about data alignment; use with caution */\n\nstatic U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; }\nstatic U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; }\nstatic reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; }\n\nstatic void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }\nstatic void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }\n\n#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1)\n\n/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */\n/* currently only defined for gcc and icc */\nLZ4_PACK(typedef struct { U16 u16; }) LZ4_unalign16;\nLZ4_PACK(typedef struct { U32 u32; }) LZ4_unalign32;\nLZ4_PACK(typedef struct { reg_t uArch; }) LZ4_unalignST;\n\nstatic U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign16*)ptr)->u16; }\nstatic U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign32*)ptr)->u32; }\nstatic reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalignST*)ptr)->uArch; }\n\nstatic void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign16*)memPtr)->u16 = value; }\nstatic void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign32*)memPtr)->u32 = value; }\n\n#else  /* safe and portable access using memcpy() */\n\nstatic U16 LZ4_read16(const void* memPtr)\n{\n    U16 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic U32 LZ4_read32(const void* memPtr)\n{\n    U32 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic reg_t LZ4_read_ARCH(const void* memPtr)\n{\n    reg_t val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic void LZ4_write16(void* memPtr, U16 value)\n{\n    LZ4_memcpy(memPtr, &value, sizeof(value));\n}\n\nstatic void LZ4_write32(void* memPtr, U32 value)\n{\n    LZ4_memcpy(memPtr, &value, sizeof(value));\n}\n\n#endif /* LZ4_FORCE_MEMORY_ACCESS */\n\n\nstatic U16 LZ4_readLE16(const void* memPtr)\n{\n    if (LZ4_isLittleEndian()) {\n        return LZ4_read16(memPtr);\n    } else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)((U16)p[0] | (p[1]<<8));\n    }\n}\n\n#ifdef LZ4_STATIC_LINKING_ONLY_ENDIANNESS_INDEPENDENT_OUTPUT\nstatic U32 LZ4_readLE32(const void* memPtr)\n{\n    if (LZ4_isLittleEndian()) {\n        return LZ4_read32(memPtr);\n    } else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);\n    }\n}\n#endif\n\nstatic void LZ4_writeLE16(void* memPtr, U16 value)\n{\n    if (LZ4_isLittleEndian()) {\n        LZ4_write16(memPtr, value);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE) value;\n        p[1] = (BYTE)(value>>8);\n    }\n}\n\n/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */\nLZ4_FORCE_INLINE\nvoid LZ4_wildCopy8(void* dstPtr, const void* srcPtr, void* dstEnd)\n{\n    BYTE* d = (BYTE*)dstPtr;\n    const BYTE* s = (const BYTE*)srcPtr;\n    BYTE* const e = (BYTE*)dstEnd;\n\n    do { LZ4_memcpy(d,s,8); d+=8; s+=8; } while (d<e);\n}\n\nstatic const unsigned inc32table[8] = {0, 1, 2,  1,  0,  4, 4, 4};\nstatic const int      dec64table[8] = {0, 0, 0, -1, -4,  1, 2, 3};\n\n\n#ifndef LZ4_FAST_DEC_LOOP\n#  if defined __i386__ || defined _M_IX86 || defined __x86_64__ || defined _M_X64\n#    define LZ4_FAST_DEC_LOOP 1\n#  elif defined(__aarch64__) && defined(__APPLE__)\n#    define LZ4_FAST_DEC_LOOP 1\n#  elif defined(__aarch64__) && !defined(__clang__)\n     /* On non-Apple aarch64, we disable this optimization for clang because\n      * on certain mobile chipsets, performance is reduced with clang. For\n      * more information refer to https://github.com/lz4/lz4/pull/707 */\n#    define LZ4_FAST_DEC_LOOP 1\n#  else\n#    define LZ4_FAST_DEC_LOOP 0\n#  endif\n#endif\n\n#if LZ4_FAST_DEC_LOOP\n\nLZ4_FORCE_INLINE void\nLZ4_memcpy_using_offset_base(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)\n{\n    assert(srcPtr + offset == dstPtr);\n    if (offset < 8) {\n        LZ4_write32(dstPtr, 0);   /* silence an msan warning when offset==0 */\n        dstPtr[0] = srcPtr[0];\n        dstPtr[1] = srcPtr[1];\n        dstPtr[2] = srcPtr[2];\n        dstPtr[3] = srcPtr[3];\n        srcPtr += inc32table[offset];\n        LZ4_memcpy(dstPtr+4, srcPtr, 4);\n        srcPtr -= dec64table[offset];\n        dstPtr += 8;\n    } else {\n        LZ4_memcpy(dstPtr, srcPtr, 8);\n        dstPtr += 8;\n        srcPtr += 8;\n    }\n\n    LZ4_wildCopy8(dstPtr, srcPtr, dstEnd);\n}\n\n/* customized variant of memcpy, which can overwrite up to 32 bytes beyond dstEnd\n * this version copies two times 16 bytes (instead of one time 32 bytes)\n * because it must be compatible with offsets >= 16. */\nLZ4_FORCE_INLINE void\nLZ4_wildCopy32(void* dstPtr, const void* srcPtr, void* dstEnd)\n{\n    BYTE* d = (BYTE*)dstPtr;\n    const BYTE* s = (const BYTE*)srcPtr;\n    BYTE* const e = (BYTE*)dstEnd;\n\n    do { LZ4_memcpy(d,s,16); LZ4_memcpy(d+16,s+16,16); d+=32; s+=32; } while (d<e);\n}\n\n/* LZ4_memcpy_using_offset()  presumes :\n * - dstEnd >= dstPtr + MINMATCH\n * - there is at least 12 bytes available to write after dstEnd */\nLZ4_FORCE_INLINE void\nLZ4_memcpy_using_offset(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd, const size_t offset)\n{\n    BYTE v[8];\n\n    assert(dstEnd >= dstPtr + MINMATCH);\n\n    switch(offset) {\n    case 1:\n        MEM_INIT(v, *srcPtr, 8);\n        break;\n    case 2:\n        LZ4_memcpy(v, srcPtr, 2);\n        LZ4_memcpy(&v[2], srcPtr, 2);\n#if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */\n#  pragma warning(push)\n#  pragma warning(disable : 6385) /* warning C6385: Reading invalid data from 'v'. */\n#endif\n        LZ4_memcpy(&v[4], v, 4);\n#if defined(_MSC_VER) && (_MSC_VER <= 1937) /* MSVC 2022 ver 17.7 or earlier */\n#  pragma warning(pop)\n#endif\n        break;\n    case 4:\n        LZ4_memcpy(v, srcPtr, 4);\n        LZ4_memcpy(&v[4], srcPtr, 4);\n        break;\n    default:\n        LZ4_memcpy_using_offset_base(dstPtr, srcPtr, dstEnd, offset);\n        return;\n    }\n\n    LZ4_memcpy(dstPtr, v, 8);\n    dstPtr += 8;\n    while (dstPtr < dstEnd) {\n        LZ4_memcpy(dstPtr, v, 8);\n        dstPtr += 8;\n    }\n}\n#endif\n\n\n/*-************************************\n*  Common functions\n**************************************/\nstatic unsigned LZ4_NbCommonBytes (reg_t val)\n{\n    assert(val != 0);\n    if (LZ4_isLittleEndian()) {\n        if (sizeof(val) == 8) {\n#       if defined(_MSC_VER) && (_MSC_VER >= 1800) && (defined(_M_AMD64) && !defined(_M_ARM64EC)) && !defined(LZ4_FORCE_SW_BITCOUNT)\n/*-*************************************************************************************************\n* ARM64EC is a Microsoft-designed ARM64 ABI compatible with AMD64 applications on ARM64 Windows 11.\n* The ARM64EC ABI does not support AVX/AVX2/AVX512 instructions, nor their relevant intrinsics\n* including _tzcnt_u64. Therefore, we need to neuter the _tzcnt_u64 code path for ARM64EC.\n****************************************************************************************************/\n#         if defined(__clang__) && (__clang_major__ < 10)\n            /* Avoid undefined clang-cl intrinsics issue.\n             * See https://github.com/lz4/lz4/pull/1017 for details. */\n            return (unsigned)__builtin_ia32_tzcnt_u64(val) >> 3;\n#         else\n            /* x64 CPUS without BMI support interpret `TZCNT` as `REP BSF` */\n            return (unsigned)_tzcnt_u64(val) >> 3;\n#         endif\n#       elif defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)\n            unsigned long r = 0;\n            _BitScanForward64(&r, (U64)val);\n            return (unsigned)r >> 3;\n#       elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \\\n                            ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \\\n                                        !defined(LZ4_FORCE_SW_BITCOUNT)\n            return (unsigned)__builtin_ctzll((U64)val) >> 3;\n#       else\n            const U64 m = 0x0101010101010101ULL;\n            val ^= val - 1;\n            return (unsigned)(((U64)((val & (m - 1)) * m)) >> 56);\n#       endif\n        } else /* 32 bits */ {\n#       if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)\n            unsigned long r;\n            _BitScanForward(&r, (U32)val);\n            return (unsigned)r >> 3;\n#       elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \\\n                            ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \\\n                        !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)\n            return (unsigned)__builtin_ctz((U32)val) >> 3;\n#       else\n            const U32 m = 0x01010101;\n            return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24;\n#       endif\n        }\n    } else   /* Big Endian CPU */ {\n        if (sizeof(val)==8) {\n#       if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \\\n                            ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \\\n                        !defined(__TINYC__) && !defined(LZ4_FORCE_SW_BITCOUNT)\n            return (unsigned)__builtin_clzll((U64)val) >> 3;\n#       else\n#if 1\n            /* this method is probably faster,\n             * but adds a 128 bytes lookup table */\n            static const unsigned char ctz7_tab[128] = {\n                7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n                4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n                5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n                4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n                6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n                4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n                5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n                4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,\n            };\n            U64 const mask = 0x0101010101010101ULL;\n            U64 const t = (((val >> 8) - mask) | val) & mask;\n            return ctz7_tab[(t * 0x0080402010080402ULL) >> 57];\n#else\n            /* this method doesn't consume memory space like the previous one,\n             * but it contains several branches,\n             * that may end up slowing execution */\n            static const U32 by32 = sizeof(val)*4;  /* 32 on 64 bits (goal), 16 on 32 bits.\n            Just to avoid some static analyzer complaining about shift by 32 on 32-bits target.\n            Note that this code path is never triggered in 32-bits mode. */\n            unsigned r;\n            if (!(val>>by32)) { r=4; } else { r=0; val>>=by32; }\n            if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }\n            r += (!val);\n            return r;\n#endif\n#       endif\n        } else /* 32 bits */ {\n#       if (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \\\n                            ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \\\n                                        !defined(LZ4_FORCE_SW_BITCOUNT)\n            return (unsigned)__builtin_clz((U32)val) >> 3;\n#       else\n            val >>= 8;\n            val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |\n              (val + 0x00FF0000)) >> 24;\n            return (unsigned)val ^ 3;\n#       endif\n        }\n    }\n}\n\n\n#define STEPSIZE sizeof(reg_t)\nLZ4_FORCE_INLINE\nunsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)\n{\n    const BYTE* const pStart = pIn;\n\n    if (likely(pIn < pInLimit-(STEPSIZE-1))) {\n        reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);\n        if (!diff) {\n            pIn+=STEPSIZE; pMatch+=STEPSIZE;\n        } else {\n            return LZ4_NbCommonBytes(diff);\n    }   }\n\n    while (likely(pIn < pInLimit-(STEPSIZE-1))) {\n        reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);\n        if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }\n        pIn += LZ4_NbCommonBytes(diff);\n        return (unsigned)(pIn - pStart);\n    }\n\n    if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }\n    if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }\n    if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;\n    return (unsigned)(pIn - pStart);\n}\n\n\n#ifndef LZ4_COMMONDEFS_ONLY\n/*-************************************\n*  Local Constants\n**************************************/\nstatic const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));\nstatic const U32 LZ4_skipTrigger = 6;  /* Increase this value ==> compression run slower on incompressible data */\n\n\n/*-************************************\n*  Local Structures and types\n**************************************/\ntypedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t;\n\n/**\n * This enum distinguishes several different modes of accessing previous\n * content in the stream.\n *\n * - noDict        : There is no preceding content.\n * - withPrefix64k : Table entries up to ctx->dictSize before the current blob\n *                   blob being compressed are valid and refer to the preceding\n *                   content (of length ctx->dictSize), which is available\n *                   contiguously preceding in memory the content currently\n *                   being compressed.\n * - usingExtDict  : Like withPrefix64k, but the preceding content is somewhere\n *                   else in memory, starting at ctx->dictionary with length\n *                   ctx->dictSize.\n * - usingDictCtx  : Everything concerning the preceding content is\n *                   in a separate context, pointed to by ctx->dictCtx.\n *                   ctx->dictionary, ctx->dictSize, and table entries\n *                   in the current context that refer to positions\n *                   preceding the beginning of the current compression are\n *                   ignored. Instead, ctx->dictCtx->dictionary and ctx->dictCtx\n *                   ->dictSize describe the location and size of the preceding\n *                   content, and matches are found by looking in the ctx\n *                   ->dictCtx->hashTable.\n */\ntypedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } dict_directive;\ntypedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;\n\n\n/*-************************************\n*  Local Utils\n**************************************/\nint LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }\nconst char* LZ4_versionString(void) { return LZ4_VERSION_STRING; }\nint LZ4_compressBound(int isize)  { return LZ4_COMPRESSBOUND(isize); }\nint LZ4_sizeofState(void) { return sizeof(LZ4_stream_t); }\n\n\n/*-****************************************\n*  Internal Definitions, used only in Tests\n*******************************************/\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\nint LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize);\n\nint LZ4_decompress_safe_forceExtDict(const char* source, char* dest,\n                                     int compressedSize, int maxOutputSize,\n                                     const void* dictStart, size_t dictSize);\nint LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,\n                                     int compressedSize, int targetOutputSize, int dstCapacity,\n                                     const void* dictStart, size_t dictSize);\n#if defined (__cplusplus)\n}\n#endif\n\n/*-******************************\n*  Compression functions\n********************************/\nLZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType)\n{\n    if (tableType == byU16)\n        return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));\n    else\n        return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));\n}\n\nLZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType)\n{\n    const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG;\n    if (LZ4_isLittleEndian()) {\n        const U64 prime5bytes = 889523592379ULL;\n        return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog));\n    } else {\n        const U64 prime8bytes = 11400714785074694791ULL;\n        return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog));\n    }\n}\n\nLZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType)\n{\n    if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType);\n\n#ifdef LZ4_STATIC_LINKING_ONLY_ENDIANNESS_INDEPENDENT_OUTPUT\n    return LZ4_hash4(LZ4_readLE32(p), tableType);\n#else\n    return LZ4_hash4(LZ4_read32(p), tableType);\n#endif\n}\n\nLZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t const tableType)\n{\n    switch (tableType)\n    {\n    default: /* fallthrough */\n    case clearedTable: { /* illegal! */ assert(0); return; }\n    case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = NULL; return; }\n    case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = 0; return; }\n    case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = 0; return; }\n    }\n}\n\nLZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase, tableType_t const tableType)\n{\n    switch (tableType)\n    {\n    default: /* fallthrough */\n    case clearedTable: /* fallthrough */\n    case byPtr: { /* illegal! */ assert(0); return; }\n    case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = idx; return; }\n    case byU16: { U16* hashTable = (U16*) tableBase; assert(idx < 65536); hashTable[h] = (U16)idx; return; }\n    }\n}\n\n/* LZ4_putPosition*() : only used in byPtr mode */\nLZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h,\n                                  void* tableBase, tableType_t const tableType)\n{\n    const BYTE** const hashTable = (const BYTE**)tableBase;\n    assert(tableType == byPtr); (void)tableType;\n    hashTable[h] = p;\n}\n\nLZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType)\n{\n    U32 const h = LZ4_hashPosition(p, tableType);\n    LZ4_putPositionOnHash(p, h, tableBase, tableType);\n}\n\n/* LZ4_getIndexOnHash() :\n * Index of match position registered in hash table.\n * hash position must be calculated by using base+index, or dictBase+index.\n * Assumption 1 : only valid if tableType == byU32 or byU16.\n * Assumption 2 : h is presumed valid (within limits of hash table)\n */\nLZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, tableType_t tableType)\n{\n    LZ4_STATIC_ASSERT(LZ4_MEMORY_USAGE > 2);\n    if (tableType == byU32) {\n        const U32* const hashTable = (const U32*) tableBase;\n        assert(h < (1U << (LZ4_MEMORY_USAGE-2)));\n        return hashTable[h];\n    }\n    if (tableType == byU16) {\n        const U16* const hashTable = (const U16*) tableBase;\n        assert(h < (1U << (LZ4_MEMORY_USAGE-1)));\n        return hashTable[h];\n    }\n    assert(0); return 0;  /* forbidden case */\n}\n\nstatic const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, tableType_t tableType)\n{\n    assert(tableType == byPtr); (void)tableType;\n    { const BYTE* const* hashTable = (const BYTE* const*) tableBase; return hashTable[h]; }\n}\n\nLZ4_FORCE_INLINE const BYTE*\nLZ4_getPosition(const BYTE* p,\n                const void* tableBase, tableType_t tableType)\n{\n    U32 const h = LZ4_hashPosition(p, tableType);\n    return LZ4_getPositionOnHash(h, tableBase, tableType);\n}\n\nLZ4_FORCE_INLINE void\nLZ4_prepareTable(LZ4_stream_t_internal* const cctx,\n           const int inputSize,\n           const tableType_t tableType) {\n    /* If the table hasn't been used, it's guaranteed to be zeroed out, and is\n     * therefore safe to use no matter what mode we're in. Otherwise, we figure\n     * out if it's safe to leave as is or whether it needs to be reset.\n     */\n    if ((tableType_t)cctx->tableType != clearedTable) {\n        assert(inputSize >= 0);\n        if ((tableType_t)cctx->tableType != tableType\n          || ((tableType == byU16) && cctx->currentOffset + (unsigned)inputSize >= 0xFFFFU)\n          || ((tableType == byU32) && cctx->currentOffset > 1 GB)\n          || tableType == byPtr\n          || inputSize >= 4 KB)\n        {\n            DEBUGLOG(4, \"LZ4_prepareTable: Resetting table in %p\", cctx);\n            MEM_INIT(cctx->hashTable, 0, LZ4_HASHTABLESIZE);\n            cctx->currentOffset = 0;\n            cctx->tableType = (U32)clearedTable;\n        } else {\n            DEBUGLOG(4, \"LZ4_prepareTable: Re-use hash table (no reset)\");\n        }\n    }\n\n    /* Adding a gap, so all previous entries are > LZ4_DISTANCE_MAX back,\n     * is faster than compressing without a gap.\n     * However, compressing with currentOffset == 0 is faster still,\n     * so we preserve that case.\n     */\n    if (cctx->currentOffset != 0 && tableType == byU32) {\n        DEBUGLOG(5, \"LZ4_prepareTable: adding 64KB to currentOffset\");\n        cctx->currentOffset += 64 KB;\n    }\n\n    /* Finally, clear history */\n    cctx->dictCtx = NULL;\n    cctx->dictionary = NULL;\n    cctx->dictSize = 0;\n}\n\n/** LZ4_compress_generic_validated() :\n *  inlined, to ensure branches are decided at compilation time.\n *  The following conditions are presumed already validated:\n *  - source != NULL\n *  - inputSize > 0\n */\nLZ4_FORCE_INLINE int LZ4_compress_generic_validated(\n                 LZ4_stream_t_internal* const cctx,\n                 const char* const source,\n                 char* const dest,\n                 const int inputSize,\n                 int*  inputConsumed, /* only written when outputDirective == fillOutput */\n                 const int maxOutputSize,\n                 const limitedOutput_directive outputDirective,\n                 const tableType_t tableType,\n                 const dict_directive dictDirective,\n                 const dictIssue_directive dictIssue,\n                 const int acceleration)\n{\n    int result;\n    const BYTE* ip = (const BYTE*)source;\n\n    U32 const startIndex = cctx->currentOffset;\n    const BYTE* base = (const BYTE*)source - startIndex;\n    const BYTE* lowLimit;\n\n    const LZ4_stream_t_internal* dictCtx = (const LZ4_stream_t_internal*) cctx->dictCtx;\n    const BYTE* const dictionary =\n        dictDirective == usingDictCtx ? dictCtx->dictionary : cctx->dictionary;\n    const U32 dictSize =\n        dictDirective == usingDictCtx ? dictCtx->dictSize : cctx->dictSize;\n    const U32 dictDelta =\n        (dictDirective == usingDictCtx) ? startIndex - dictCtx->currentOffset : 0;   /* make indexes in dictCtx comparable with indexes in current context */\n\n    int const maybe_extMem = (dictDirective == usingExtDict) || (dictDirective == usingDictCtx);\n    U32 const prefixIdxLimit = startIndex - dictSize;   /* used when dictDirective == dictSmall */\n    const BYTE* const dictEnd = dictionary ? dictionary + dictSize : dictionary;\n    const BYTE* anchor = (const BYTE*) source;\n    const BYTE* const iend = ip + inputSize;\n    const BYTE* const mflimitPlusOne = iend - MFLIMIT + 1;\n    const BYTE* const matchlimit = iend - LASTLITERALS;\n\n    /* the dictCtx currentOffset is indexed on the start of the dictionary,\n     * while a dictionary in the current context precedes the currentOffset */\n    const BYTE* dictBase = (dictionary == NULL) ? NULL :\n                           (dictDirective == usingDictCtx) ?\n                            dictionary + dictSize - dictCtx->currentOffset :\n                            dictionary + dictSize - startIndex;\n\n    BYTE* op = (BYTE*) dest;\n    BYTE* const olimit = op + maxOutputSize;\n\n    U32 offset = 0;\n    U32 forwardH;\n\n    DEBUGLOG(5, \"LZ4_compress_generic_validated: srcSize=%i, tableType=%u\", inputSize, tableType);\n    assert(ip != NULL);\n    if (tableType == byU16) assert(inputSize<LZ4_64Klimit);  /* Size too large (not within 64K limit) */\n    if (tableType == byPtr) assert(dictDirective==noDict);   /* only supported use case with byPtr */\n    /* If init conditions are not met, we don't have to mark stream\n     * as having dirty context, since no action was taken yet */\n    if (outputDirective == fillOutput && maxOutputSize < 1) { return 0; } /* Impossible to store anything */\n    assert(acceleration >= 1);\n\n    lowLimit = (const BYTE*)source - (dictDirective == withPrefix64k ? dictSize : 0);\n\n    /* Update context state */\n    if (dictDirective == usingDictCtx) {\n        /* Subsequent linked blocks can't use the dictionary. */\n        /* Instead, they use the block we just compressed. */\n        cctx->dictCtx = NULL;\n        cctx->dictSize = (U32)inputSize;\n    } else {\n        cctx->dictSize += (U32)inputSize;\n    }\n    cctx->currentOffset += (U32)inputSize;\n    cctx->tableType = (U32)tableType;\n\n    if (inputSize<LZ4_minLength) goto _last_literals;        /* Input too small, no compression (all literals) */\n\n    /* First Byte */\n    {   U32 const h = LZ4_hashPosition(ip, tableType);\n        if (tableType == byPtr) {\n            LZ4_putPositionOnHash(ip, h, cctx->hashTable, byPtr);\n        } else {\n            LZ4_putIndexOnHash(startIndex, h, cctx->hashTable, tableType);\n    }   }\n    ip++; forwardH = LZ4_hashPosition(ip, tableType);\n\n    /* Main Loop */\n    for ( ; ; ) {\n        const BYTE* match;\n        BYTE* token;\n        const BYTE* filledIp;\n\n        /* Find a match */\n        if (tableType == byPtr) {\n            const BYTE* forwardIp = ip;\n            int step = 1;\n            int searchMatchNb = acceleration << LZ4_skipTrigger;\n            do {\n                U32 const h = forwardH;\n                ip = forwardIp;\n                forwardIp += step;\n                step = (searchMatchNb++ >> LZ4_skipTrigger);\n\n                if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;\n                assert(ip < mflimitPlusOne);\n\n                match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType);\n                forwardH = LZ4_hashPosition(forwardIp, tableType);\n                LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType);\n\n            } while ( (match+LZ4_DISTANCE_MAX < ip)\n                   || (LZ4_read32(match) != LZ4_read32(ip)) );\n\n        } else {   /* byU32, byU16 */\n\n            const BYTE* forwardIp = ip;\n            int step = 1;\n            int searchMatchNb = acceleration << LZ4_skipTrigger;\n            do {\n                U32 const h = forwardH;\n                U32 const current = (U32)(forwardIp - base);\n                U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);\n                assert(matchIndex <= current);\n                assert(forwardIp - base < (ptrdiff_t)(2 GB - 1));\n                ip = forwardIp;\n                forwardIp += step;\n                step = (searchMatchNb++ >> LZ4_skipTrigger);\n\n                if (unlikely(forwardIp > mflimitPlusOne)) goto _last_literals;\n                assert(ip < mflimitPlusOne);\n\n                if (dictDirective == usingDictCtx) {\n                    if (matchIndex < startIndex) {\n                        /* there was no match, try the dictionary */\n                        assert(tableType == byU32);\n                        matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);\n                        match = dictBase + matchIndex;\n                        matchIndex += dictDelta;   /* make dictCtx index comparable with current context */\n                        lowLimit = dictionary;\n                    } else {\n                        match = base + matchIndex;\n                        lowLimit = (const BYTE*)source;\n                    }\n                } else if (dictDirective == usingExtDict) {\n                    if (matchIndex < startIndex) {\n                        DEBUGLOG(7, \"extDict candidate: matchIndex=%5u  <  startIndex=%5u\", matchIndex, startIndex);\n                        assert(startIndex - matchIndex >= MINMATCH);\n                        assert(dictBase);\n                        match = dictBase + matchIndex;\n                        lowLimit = dictionary;\n                    } else {\n                        match = base + matchIndex;\n                        lowLimit = (const BYTE*)source;\n                    }\n                } else {   /* single continuous memory segment */\n                    match = base + matchIndex;\n                }\n                forwardH = LZ4_hashPosition(forwardIp, tableType);\n                LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);\n\n                DEBUGLOG(7, \"candidate at pos=%u  (offset=%u \\n\", matchIndex, current - matchIndex);\n                if ((dictIssue == dictSmall) && (matchIndex < prefixIdxLimit)) { continue; }    /* match outside of valid area */\n                assert(matchIndex < current);\n                if ( ((tableType != byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX))\n                  && (matchIndex+LZ4_DISTANCE_MAX < current)) {\n                    continue;\n                } /* too far */\n                assert((current - matchIndex) <= LZ4_DISTANCE_MAX);  /* match now expected within distance */\n\n                if (LZ4_read32(match) == LZ4_read32(ip)) {\n                    if (maybe_extMem) offset = current - matchIndex;\n                    break;   /* match found */\n                }\n\n            } while(1);\n        }\n\n        /* Catch up */\n        filledIp = ip;\n        assert(ip > anchor); /* this is always true as ip has been advanced before entering the main loop */\n        if ((match > lowLimit) && unlikely(ip[-1] == match[-1])) {\n            do { ip--; match--; } while (((ip > anchor) & (match > lowLimit)) && (unlikely(ip[-1] == match[-1])));\n        }\n\n        /* Encode Literals */\n        {   unsigned const litLength = (unsigned)(ip - anchor);\n            token = op++;\n            if ((outputDirective == limitedOutput) &&  /* Check output buffer overflow */\n                (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)) ) {\n                return 0;   /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */\n            }\n            if ((outputDirective == fillOutput) &&\n                (unlikely(op + (litLength+240)/255 /* litlen */ + litLength /* literals */ + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit))) {\n                op--;\n                goto _last_literals;\n            }\n            if (litLength >= RUN_MASK) {\n                unsigned len = litLength - RUN_MASK;\n                *token = (RUN_MASK<<ML_BITS);\n                for(; len >= 255 ; len-=255) *op++ = 255;\n                *op++ = (BYTE)len;\n            }\n            else *token = (BYTE)(litLength<<ML_BITS);\n\n            /* Copy Literals */\n            LZ4_wildCopy8(op, anchor, op+litLength);\n            op+=litLength;\n            DEBUGLOG(6, \"seq.start:%i, literals=%u, match.start:%i\",\n                        (int)(anchor-(const BYTE*)source), litLength, (int)(ip-(const BYTE*)source));\n        }\n\n_next_match:\n        /* at this stage, the following variables must be correctly set :\n         * - ip : at start of LZ operation\n         * - match : at start of previous pattern occurrence; can be within current prefix, or within extDict\n         * - offset : if maybe_ext_memSegment==1 (constant)\n         * - lowLimit : must be == dictionary to mean \"match is within extDict\"; must be == source otherwise\n         * - token and *token : position to write 4-bits for match length; higher 4-bits for literal length supposed already written\n         */\n\n        if ((outputDirective == fillOutput) &&\n            (op + 2 /* offset */ + 1 /* token */ + MFLIMIT - MINMATCH /* min last literals so last match is <= end - MFLIMIT */ > olimit)) {\n            /* the match was too close to the end, rewind and go to last literals */\n            op = token;\n            goto _last_literals;\n        }\n\n        /* Encode Offset */\n        if (maybe_extMem) {   /* static test */\n            DEBUGLOG(6, \"             with offset=%u  (ext if > %i)\", offset, (int)(ip - (const BYTE*)source));\n            assert(offset <= LZ4_DISTANCE_MAX && offset > 0);\n            LZ4_writeLE16(op, (U16)offset); op+=2;\n        } else  {\n            DEBUGLOG(6, \"             with offset=%u  (same segment)\", (U32)(ip - match));\n            assert(ip-match <= LZ4_DISTANCE_MAX);\n            LZ4_writeLE16(op, (U16)(ip - match)); op+=2;\n        }\n\n        /* Encode MatchLength */\n        {   unsigned matchCode;\n\n            if ( (dictDirective==usingExtDict || dictDirective==usingDictCtx)\n              && (lowLimit==dictionary) /* match within extDict */ ) {\n                const BYTE* limit = ip + (dictEnd-match);\n                assert(dictEnd > match);\n                if (limit > matchlimit) limit = matchlimit;\n                matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);\n                ip += (size_t)matchCode + MINMATCH;\n                if (ip==limit) {\n                    unsigned const more = LZ4_count(limit, (const BYTE*)source, matchlimit);\n                    matchCode += more;\n                    ip += more;\n                }\n                DEBUGLOG(6, \"             with matchLength=%u starting in extDict\", matchCode+MINMATCH);\n            } else {\n                matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n                ip += (size_t)matchCode + MINMATCH;\n                DEBUGLOG(6, \"             with matchLength=%u\", matchCode+MINMATCH);\n            }\n\n            if ((outputDirective) &&    /* Check output buffer overflow */\n                (unlikely(op + (1 + LASTLITERALS) + (matchCode+240)/255 > olimit)) ) {\n                if (outputDirective == fillOutput) {\n                    /* Match description too long : reduce it */\n                    U32 newMatchCode = 15 /* in token */ - 1 /* to avoid needing a zero byte */ + ((U32)(olimit - op) - 1 - LASTLITERALS) * 255;\n                    ip -= matchCode - newMatchCode;\n                    assert(newMatchCode < matchCode);\n                    matchCode = newMatchCode;\n                    if (unlikely(ip <= filledIp)) {\n                        /* We have already filled up to filledIp so if ip ends up less than filledIp\n                         * we have positions in the hash table beyond the current position. This is\n                         * a problem if we reuse the hash table. So we have to remove these positions\n                         * from the hash table.\n                         */\n                        const BYTE* ptr;\n                        DEBUGLOG(5, \"Clearing %u positions\", (U32)(filledIp - ip));\n                        for (ptr = ip; ptr <= filledIp; ++ptr) {\n                            U32 const h = LZ4_hashPosition(ptr, tableType);\n                            LZ4_clearHash(h, cctx->hashTable, tableType);\n                        }\n                    }\n                } else {\n                    assert(outputDirective == limitedOutput);\n                    return 0;   /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */\n                }\n            }\n            if (matchCode >= ML_MASK) {\n                *token += ML_MASK;\n                matchCode -= ML_MASK;\n                LZ4_write32(op, 0xFFFFFFFF);\n                while (matchCode >= 4*255) {\n                    op+=4;\n                    LZ4_write32(op, 0xFFFFFFFF);\n                    matchCode -= 4*255;\n                }\n                op += matchCode / 255;\n                *op++ = (BYTE)(matchCode % 255);\n            } else\n                *token += (BYTE)(matchCode);\n        }\n        /* Ensure we have enough space for the last literals. */\n        assert(!(outputDirective == fillOutput && op + 1 + LASTLITERALS > olimit));\n\n        anchor = ip;\n\n        /* Test end of chunk */\n        if (ip >= mflimitPlusOne) break;\n\n        /* Fill table */\n        {   U32 const h = LZ4_hashPosition(ip-2, tableType);\n            if (tableType == byPtr) {\n                LZ4_putPositionOnHash(ip-2, h, cctx->hashTable, byPtr);\n            } else {\n                U32 const idx = (U32)((ip-2) - base);\n                LZ4_putIndexOnHash(idx, h, cctx->hashTable, tableType);\n        }   }\n\n        /* Test next position */\n        if (tableType == byPtr) {\n\n            match = LZ4_getPosition(ip, cctx->hashTable, tableType);\n            LZ4_putPosition(ip, cctx->hashTable, tableType);\n            if ( (match+LZ4_DISTANCE_MAX >= ip)\n              && (LZ4_read32(match) == LZ4_read32(ip)) )\n            { token=op++; *token=0; goto _next_match; }\n\n        } else {   /* byU32, byU16 */\n\n            U32 const h = LZ4_hashPosition(ip, tableType);\n            U32 const current = (U32)(ip-base);\n            U32 matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType);\n            assert(matchIndex < current);\n            if (dictDirective == usingDictCtx) {\n                if (matchIndex < startIndex) {\n                    /* there was no match, try the dictionary */\n                    assert(tableType == byU32);\n                    matchIndex = LZ4_getIndexOnHash(h, dictCtx->hashTable, byU32);\n                    match = dictBase + matchIndex;\n                    lowLimit = dictionary;   /* required for match length counter */\n                    matchIndex += dictDelta;\n                } else {\n                    match = base + matchIndex;\n                    lowLimit = (const BYTE*)source;  /* required for match length counter */\n                }\n            } else if (dictDirective==usingExtDict) {\n                if (matchIndex < startIndex) {\n                    assert(dictBase);\n                    match = dictBase + matchIndex;\n                    lowLimit = dictionary;   /* required for match length counter */\n                } else {\n                    match = base + matchIndex;\n                    lowLimit = (const BYTE*)source;   /* required for match length counter */\n                }\n            } else {   /* single memory segment */\n                match = base + matchIndex;\n            }\n            LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType);\n            assert(matchIndex < current);\n            if ( ((dictIssue==dictSmall) ? (matchIndex >= prefixIdxLimit) : 1)\n              && (((tableType==byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) ? 1 : (matchIndex+LZ4_DISTANCE_MAX >= current))\n              && (LZ4_read32(match) == LZ4_read32(ip)) ) {\n                token=op++;\n                *token=0;\n                if (maybe_extMem) offset = current - matchIndex;\n                DEBUGLOG(6, \"seq.start:%i, literals=%u, match.start:%i\",\n                            (int)(anchor-(const BYTE*)source), 0, (int)(ip-(const BYTE*)source));\n                goto _next_match;\n            }\n        }\n\n        /* Prepare next loop */\n        forwardH = LZ4_hashPosition(++ip, tableType);\n\n    }\n\n_last_literals:\n    /* Encode Last Literals */\n    {   size_t lastRun = (size_t)(iend - anchor);\n        if ( (outputDirective) &&  /* Check output buffer overflow */\n            (op + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > olimit)) {\n            if (outputDirective == fillOutput) {\n                /* adapt lastRun to fill 'dst' */\n                assert(olimit >= op);\n                lastRun  = (size_t)(olimit-op) - 1/*token*/;\n                lastRun -= (lastRun + 256 - RUN_MASK) / 256;  /*additional length tokens*/\n            } else {\n                assert(outputDirective == limitedOutput);\n                return 0;   /* cannot compress within `dst` budget. Stored indexes in hash table are nonetheless fine */\n            }\n        }\n        DEBUGLOG(6, \"Final literal run : %i literals\", (int)lastRun);\n        if (lastRun >= RUN_MASK) {\n            size_t accumulator = lastRun - RUN_MASK;\n            *op++ = RUN_MASK << ML_BITS;\n            for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;\n            *op++ = (BYTE) accumulator;\n        } else {\n            *op++ = (BYTE)(lastRun<<ML_BITS);\n        }\n        LZ4_memcpy(op, anchor, lastRun);\n        ip = anchor + lastRun;\n        op += lastRun;\n    }\n\n    if (outputDirective == fillOutput) {\n        *inputConsumed = (int) (((const char*)ip)-source);\n    }\n    result = (int)(((char*)op) - dest);\n    assert(result > 0);\n    DEBUGLOG(5, \"LZ4_compress_generic: compressed %i bytes into %i bytes\", inputSize, result);\n    return result;\n}\n\n/** LZ4_compress_generic() :\n *  inlined, to ensure branches are decided at compilation time;\n *  takes care of src == (NULL, 0)\n *  and forward the rest to LZ4_compress_generic_validated */\nLZ4_FORCE_INLINE int LZ4_compress_generic(\n                 LZ4_stream_t_internal* const cctx,\n                 const char* const src,\n                 char* const dst,\n                 const int srcSize,\n                 int *inputConsumed, /* only written when outputDirective == fillOutput */\n                 const int dstCapacity,\n                 const limitedOutput_directive outputDirective,\n                 const tableType_t tableType,\n                 const dict_directive dictDirective,\n                 const dictIssue_directive dictIssue,\n                 const int acceleration)\n{\n    DEBUGLOG(5, \"LZ4_compress_generic: srcSize=%i, dstCapacity=%i\",\n                srcSize, dstCapacity);\n\n    if ((U32)srcSize > (U32)LZ4_MAX_INPUT_SIZE) { return 0; }  /* Unsupported srcSize, too large (or negative) */\n    if (srcSize == 0) {   /* src == NULL supported if srcSize == 0 */\n        if (outputDirective != notLimited && dstCapacity <= 0) return 0;  /* no output, can't write anything */\n        DEBUGLOG(5, \"Generating an empty block\");\n        assert(outputDirective == notLimited || dstCapacity >= 1);\n        assert(dst != NULL);\n        dst[0] = 0;\n        if (outputDirective == fillOutput) {\n            assert (inputConsumed != NULL);\n            *inputConsumed = 0;\n        }\n        return 1;\n    }\n    assert(src != NULL);\n\n    return LZ4_compress_generic_validated(cctx, src, dst, srcSize,\n                inputConsumed, /* only written into if outputDirective == fillOutput */\n                dstCapacity, outputDirective,\n                tableType, dictDirective, dictIssue, acceleration);\n}\n\n\nint LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)\n{\n    LZ4_stream_t_internal* const ctx = & LZ4_initStream(state, sizeof(LZ4_stream_t)) -> internal_donotuse;\n    assert(ctx != NULL);\n    if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;\n    if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;\n    if (maxOutputSize >= LZ4_compressBound(inputSize)) {\n        if (inputSize < LZ4_64Klimit) {\n            return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, byU16, noDict, noDictIssue, acceleration);\n        } else {\n            const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32;\n            return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);\n        }\n    } else {\n        if (inputSize < LZ4_64Klimit) {\n            return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration);\n        } else {\n            const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)source > LZ4_DISTANCE_MAX)) ? byPtr : byU32;\n            return LZ4_compress_generic(ctx, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, noDict, noDictIssue, acceleration);\n        }\n    }\n}\n\n/**\n * LZ4_compress_fast_extState_fastReset() :\n * A variant of LZ4_compress_fast_extState().\n *\n * Using this variant avoids an expensive initialization step. It is only safe\n * to call if the state buffer is known to be correctly initialized already\n * (see comment in lz4.h on LZ4_resetStream_fast() for a definition of\n * \"correctly initialized\").\n */\nint LZ4_compress_fast_extState_fastReset(void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration)\n{\n    LZ4_stream_t_internal* const ctx = &((LZ4_stream_t*)state)->internal_donotuse;\n    if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;\n    if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;\n    assert(ctx != NULL);\n\n    if (dstCapacity >= LZ4_compressBound(srcSize)) {\n        if (srcSize < LZ4_64Klimit) {\n            const tableType_t tableType = byU16;\n            LZ4_prepareTable(ctx, srcSize, tableType);\n            if (ctx->currentOffset) {\n                return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, dictSmall, acceleration);\n            } else {\n                return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);\n            }\n        } else {\n            const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;\n            LZ4_prepareTable(ctx, srcSize, tableType);\n            return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, 0, notLimited, tableType, noDict, noDictIssue, acceleration);\n        }\n    } else {\n        if (srcSize < LZ4_64Klimit) {\n            const tableType_t tableType = byU16;\n            LZ4_prepareTable(ctx, srcSize, tableType);\n            if (ctx->currentOffset) {\n                return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, dictSmall, acceleration);\n            } else {\n                return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);\n            }\n        } else {\n            const tableType_t tableType = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;\n            LZ4_prepareTable(ctx, srcSize, tableType);\n            return LZ4_compress_generic(ctx, src, dst, srcSize, NULL, dstCapacity, limitedOutput, tableType, noDict, noDictIssue, acceleration);\n        }\n    }\n}\n\n\nint LZ4_compress_fast(const char* src, char* dest, int srcSize, int dstCapacity, int acceleration)\n{\n    int result;\n#if (LZ4_HEAPMODE)\n    LZ4_stream_t* const ctxPtr = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */\n    if (ctxPtr == NULL) return 0;\n#else\n    LZ4_stream_t ctx;\n    LZ4_stream_t* const ctxPtr = &ctx;\n#endif\n    result = LZ4_compress_fast_extState(ctxPtr, src, dest, srcSize, dstCapacity, acceleration);\n\n#if (LZ4_HEAPMODE)\n    FREEMEM(ctxPtr);\n#endif\n    return result;\n}\n\n\nint LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity)\n{\n    return LZ4_compress_fast(src, dst, srcSize, dstCapacity, 1);\n}\n\n\n/* Note!: This function leaves the stream in an unclean/broken state!\n * It is not safe to subsequently use the same state with a _fastReset() or\n * _continue() call without resetting it. */\nstatic int LZ4_compress_destSize_extState_internal(LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int acceleration)\n{\n    void* const s = LZ4_initStream(state, sizeof (*state));\n    assert(s != NULL); (void)s;\n\n    if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) {  /* compression success is guaranteed */\n        return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, acceleration);\n    } else {\n        if (*srcSizePtr < LZ4_64Klimit) {\n            return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, byU16, noDict, noDictIssue, acceleration);\n        } else {\n            tableType_t const addrMode = ((sizeof(void*)==4) && ((uptrval)src > LZ4_DISTANCE_MAX)) ? byPtr : byU32;\n            return LZ4_compress_generic(&state->internal_donotuse, src, dst, *srcSizePtr, srcSizePtr, targetDstSize, fillOutput, addrMode, noDict, noDictIssue, acceleration);\n    }   }\n}\n\nint LZ4_compress_destSize_extState(void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int acceleration)\n{\n    int const r = LZ4_compress_destSize_extState_internal((LZ4_stream_t*)state, src, dst, srcSizePtr, targetDstSize, acceleration);\n    /* clean the state on exit */\n    LZ4_initStream(state, sizeof (LZ4_stream_t));\n    return r;\n}\n\n\nint LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)\n{\n#if (LZ4_HEAPMODE)\n    LZ4_stream_t* const ctx = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));   /* malloc-calloc always properly aligned */\n    if (ctx == NULL) return 0;\n#else\n    LZ4_stream_t ctxBody;\n    LZ4_stream_t* const ctx = &ctxBody;\n#endif\n\n    int result = LZ4_compress_destSize_extState_internal(ctx, src, dst, srcSizePtr, targetDstSize, 1);\n\n#if (LZ4_HEAPMODE)\n    FREEMEM(ctx);\n#endif\n    return result;\n}\n\n\n\n/*-******************************\n*  Streaming functions\n********************************/\n\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nLZ4_stream_t* LZ4_createStream(void)\n{\n    LZ4_stream_t* const lz4s = (LZ4_stream_t*)ALLOC(sizeof(LZ4_stream_t));\n    LZ4_STATIC_ASSERT(sizeof(LZ4_stream_t) >= sizeof(LZ4_stream_t_internal));\n    DEBUGLOG(4, \"LZ4_createStream %p\", lz4s);\n    if (lz4s == NULL) return NULL;\n    LZ4_initStream(lz4s, sizeof(*lz4s));\n    return lz4s;\n}\n#endif\n\nstatic size_t LZ4_stream_t_alignment(void)\n{\n#if LZ4_ALIGN_TEST\n    typedef struct { char c; LZ4_stream_t t; } t_a;\n    return sizeof(t_a) - sizeof(LZ4_stream_t);\n#else\n    return 1;  /* effectively disabled */\n#endif\n}\n\nLZ4_stream_t* LZ4_initStream (void* buffer, size_t size)\n{\n    DEBUGLOG(5, \"LZ4_initStream\");\n    if (buffer == NULL) { return NULL; }\n    if (size < sizeof(LZ4_stream_t)) { return NULL; }\n    if (!LZ4_isAligned(buffer, LZ4_stream_t_alignment())) return NULL;\n    MEM_INIT(buffer, 0, sizeof(LZ4_stream_t_internal));\n    return (LZ4_stream_t*)buffer;\n}\n\n/* resetStream is now deprecated,\n * prefer initStream() which is more general */\nvoid LZ4_resetStream (LZ4_stream_t* LZ4_stream)\n{\n    DEBUGLOG(5, \"LZ4_resetStream (ctx:%p)\", LZ4_stream);\n    MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t_internal));\n}\n\nvoid LZ4_resetStream_fast(LZ4_stream_t* ctx) {\n    LZ4_prepareTable(&(ctx->internal_donotuse), 0, byU32);\n}\n\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nint LZ4_freeStream (LZ4_stream_t* LZ4_stream)\n{\n    if (!LZ4_stream) return 0;   /* support free on NULL */\n    DEBUGLOG(5, \"LZ4_freeStream %p\", LZ4_stream);\n    FREEMEM(LZ4_stream);\n    return (0);\n}\n#endif\n\n\ntypedef enum { _ld_fast, _ld_slow } LoadDict_mode_e;\n#define HASH_UNIT sizeof(reg_t)\nint LZ4_loadDict_internal(LZ4_stream_t* LZ4_dict,\n                    const char* dictionary, int dictSize,\n                    LoadDict_mode_e _ld)\n{\n    LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;\n    const tableType_t tableType = byU32;\n    const BYTE* p = (const BYTE*)dictionary;\n    const BYTE* const dictEnd = p + dictSize;\n    U32 idx32;\n\n    DEBUGLOG(4, \"LZ4_loadDict (%i bytes from %p into %p)\", dictSize, dictionary, LZ4_dict);\n\n    /* It's necessary to reset the context,\n     * and not just continue it with prepareTable()\n     * to avoid any risk of generating overflowing matchIndex\n     * when compressing using this dictionary */\n    LZ4_resetStream(LZ4_dict);\n\n    /* We always increment the offset by 64 KB, since, if the dict is longer,\n     * we truncate it to the last 64k, and if it's shorter, we still want to\n     * advance by a whole window length so we can provide the guarantee that\n     * there are only valid offsets in the window, which allows an optimization\n     * in LZ4_compress_fast_continue() where it uses noDictIssue even when the\n     * dictionary isn't a full 64k. */\n    dict->currentOffset += 64 KB;\n\n    if (dictSize < (int)HASH_UNIT) {\n        return 0;\n    }\n\n    if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB;\n    dict->dictionary = p;\n    dict->dictSize = (U32)(dictEnd - p);\n    dict->tableType = (U32)tableType;\n    idx32 = dict->currentOffset - dict->dictSize;\n\n    while (p <= dictEnd-HASH_UNIT) {\n        U32 const h = LZ4_hashPosition(p, tableType);\n        /* Note: overwriting => favors positions end of dictionary */\n        LZ4_putIndexOnHash(idx32, h, dict->hashTable, tableType);\n        p+=3; idx32+=3;\n    }\n\n    if (_ld == _ld_slow) {\n        /* Fill hash table with additional references, to improve compression capability */\n        p = dict->dictionary;\n        idx32 = dict->currentOffset - dict->dictSize;\n        while (p <= dictEnd-HASH_UNIT) {\n            U32 const h = LZ4_hashPosition(p, tableType);\n            U32 const limit = dict->currentOffset - 64 KB;\n            if (LZ4_getIndexOnHash(h, dict->hashTable, tableType) <= limit) {\n                /* Note: not overwriting => favors positions beginning of dictionary */\n                LZ4_putIndexOnHash(idx32, h, dict->hashTable, tableType);\n            }\n            p++; idx32++;\n        }\n    }\n\n    return (int)dict->dictSize;\n}\n\nint LZ4_loadDict(LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)\n{\n    return LZ4_loadDict_internal(LZ4_dict, dictionary, dictSize, _ld_fast);\n}\n\nint LZ4_loadDictSlow(LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize)\n{\n    return LZ4_loadDict_internal(LZ4_dict, dictionary, dictSize, _ld_slow);\n}\n\nvoid LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream_t* dictionaryStream)\n{\n    const LZ4_stream_t_internal* dictCtx = (dictionaryStream == NULL) ? NULL :\n        &(dictionaryStream->internal_donotuse);\n\n    DEBUGLOG(4, \"LZ4_attach_dictionary (%p, %p, size %u)\",\n             workingStream, dictionaryStream,\n             dictCtx != NULL ? dictCtx->dictSize : 0);\n\n    if (dictCtx != NULL) {\n        /* If the current offset is zero, we will never look in the\n         * external dictionary context, since there is no value a table\n         * entry can take that indicate a miss. In that case, we need\n         * to bump the offset to something non-zero.\n         */\n        if (workingStream->internal_donotuse.currentOffset == 0) {\n            workingStream->internal_donotuse.currentOffset = 64 KB;\n        }\n\n        /* Don't actually attach an empty dictionary.\n         */\n        if (dictCtx->dictSize == 0) {\n            dictCtx = NULL;\n        }\n    }\n    workingStream->internal_donotuse.dictCtx = dictCtx;\n}\n\n\nstatic void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize)\n{\n    assert(nextSize >= 0);\n    if (LZ4_dict->currentOffset + (unsigned)nextSize > 0x80000000) {   /* potential ptrdiff_t overflow (32-bits mode) */\n        /* rescale hash table */\n        U32 const delta = LZ4_dict->currentOffset - 64 KB;\n        const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize;\n        int i;\n        DEBUGLOG(4, \"LZ4_renormDictT\");\n        for (i=0; i<LZ4_HASH_SIZE_U32; i++) {\n            if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0;\n            else LZ4_dict->hashTable[i] -= delta;\n        }\n        LZ4_dict->currentOffset = 64 KB;\n        if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB;\n        LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize;\n    }\n}\n\n\nint LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,\n                                const char* source, char* dest,\n                                int inputSize, int maxOutputSize,\n                                int acceleration)\n{\n    const tableType_t tableType = byU32;\n    LZ4_stream_t_internal* const streamPtr = &LZ4_stream->internal_donotuse;\n    const char* dictEnd = streamPtr->dictSize ? (const char*)streamPtr->dictionary + streamPtr->dictSize : NULL;\n\n    DEBUGLOG(5, \"LZ4_compress_fast_continue (inputSize=%i, dictSize=%u)\", inputSize, streamPtr->dictSize);\n\n    LZ4_renormDictT(streamPtr, inputSize);   /* fix index overflow */\n    if (acceleration < 1) acceleration = LZ4_ACCELERATION_DEFAULT;\n    if (acceleration > LZ4_ACCELERATION_MAX) acceleration = LZ4_ACCELERATION_MAX;\n\n    /* invalidate tiny dictionaries */\n    if ( (streamPtr->dictSize < 4)     /* tiny dictionary : not enough for a hash */\n      && (dictEnd != source)           /* prefix mode */\n      && (inputSize > 0)               /* tolerance : don't lose history, in case next invocation would use prefix mode */\n      && (streamPtr->dictCtx == NULL)  /* usingDictCtx */\n      ) {\n        DEBUGLOG(5, \"LZ4_compress_fast_continue: dictSize(%u) at addr:%p is too small\", streamPtr->dictSize, streamPtr->dictionary);\n        /* remove dictionary existence from history, to employ faster prefix mode */\n        streamPtr->dictSize = 0;\n        streamPtr->dictionary = (const BYTE*)source;\n        dictEnd = source;\n    }\n\n    /* Check overlapping input/dictionary space */\n    {   const char* const sourceEnd = source + inputSize;\n        if ((sourceEnd > (const char*)streamPtr->dictionary) && (sourceEnd < dictEnd)) {\n            streamPtr->dictSize = (U32)(dictEnd - sourceEnd);\n            if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB;\n            if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;\n            streamPtr->dictionary = (const BYTE*)dictEnd - streamPtr->dictSize;\n        }\n    }\n\n    /* prefix mode : source data follows dictionary */\n    if (dictEnd == source) {\n        if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset))\n            return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, dictSmall, acceleration);\n        else\n            return LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, withPrefix64k, noDictIssue, acceleration);\n    }\n\n    /* external dictionary mode */\n    {   int result;\n        if (streamPtr->dictCtx) {\n            /* We depend here on the fact that dictCtx'es (produced by\n             * LZ4_loadDict) guarantee that their tables contain no references\n             * to offsets between dictCtx->currentOffset - 64 KB and\n             * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe\n             * to use noDictIssue even when the dict isn't a full 64 KB.\n             */\n            if (inputSize > 4 KB) {\n                /* For compressing large blobs, it is faster to pay the setup\n                 * cost to copy the dictionary's tables into the active context,\n                 * so that the compression loop is only looking into one table.\n                 */\n                LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr));\n                result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);\n            } else {\n                result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration);\n            }\n        } else {  /* small data <= 4 KB */\n            if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {\n                result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, dictSmall, acceleration);\n            } else {\n                result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration);\n            }\n        }\n        streamPtr->dictionary = (const BYTE*)source;\n        streamPtr->dictSize = (U32)inputSize;\n        return result;\n    }\n}\n\n\n/* Hidden debug function, to force-test external dictionary mode */\nint LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int srcSize)\n{\n    LZ4_stream_t_internal* const streamPtr = &LZ4_dict->internal_donotuse;\n    int result;\n\n    LZ4_renormDictT(streamPtr, srcSize);\n\n    if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) {\n        result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, dictSmall, 1);\n    } else {\n        result = LZ4_compress_generic(streamPtr, source, dest, srcSize, NULL, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);\n    }\n\n    streamPtr->dictionary = (const BYTE*)source;\n    streamPtr->dictSize = (U32)srcSize;\n\n    return result;\n}\n\n\n/*! LZ4_saveDict() :\n *  If previously compressed data block is not guaranteed to remain available at its memory location,\n *  save it into a safer place (char* safeBuffer).\n *  Note : no need to call LZ4_loadDict() afterwards, dictionary is immediately usable,\n *         one can therefore call LZ4_compress_fast_continue() right after.\n * @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.\n */\nint LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)\n{\n    LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse;\n\n    DEBUGLOG(5, \"LZ4_saveDict : dictSize=%i, safeBuffer=%p\", dictSize, safeBuffer);\n\n    if ((U32)dictSize > 64 KB) { dictSize = 64 KB; } /* useless to define a dictionary > 64 KB */\n    if ((U32)dictSize > dict->dictSize) { dictSize = (int)dict->dictSize; }\n\n    if (safeBuffer == NULL) assert(dictSize == 0);\n    if (dictSize > 0) {\n        const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize;\n        assert(dict->dictionary);\n        LZ4_memmove(safeBuffer, previousDictEnd - dictSize, (size_t)dictSize);\n    }\n\n    dict->dictionary = (const BYTE*)safeBuffer;\n    dict->dictSize = (U32)dictSize;\n\n    return dictSize;\n}\n\n\n\n/*-*******************************\n *  Decompression functions\n ********************************/\n\ntypedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;\n\n#undef MIN\n#define MIN(a,b)    ( (a) < (b) ? (a) : (b) )\n\n\n/* variant for decompress_unsafe()\n * does not know end of input\n * presumes input is well formed\n * note : will consume at least one byte */\nstatic size_t read_long_length_no_check(const BYTE** pp)\n{\n    size_t b, l = 0;\n    do { b = **pp; (*pp)++; l += b; } while (b==255);\n    DEBUGLOG(6, \"read_long_length_no_check: +length=%zu using %zu input bytes\", l, l/255 + 1)\n    return l;\n}\n\n/* core decoder variant for LZ4_decompress_fast*()\n * for legacy support only : these entry points are deprecated.\n * - Presumes input is correctly formed (no defense vs malformed inputs)\n * - Does not know input size (presume input buffer is \"large enough\")\n * - Decompress a full block (only)\n * @return : nb of bytes read from input.\n * Note : this variant is not optimized for speed, just for maintenance.\n *        the goal is to remove support of decompress_fast*() variants by v2.0\n**/\nLZ4_FORCE_INLINE int\nLZ4_decompress_unsafe_generic(\n                 const BYTE* const istart,\n                 BYTE* const ostart,\n                 int decompressedSize,\n\n                 size_t prefixSize,\n                 const BYTE* const dictStart,  /* only if dict==usingExtDict */\n                 const size_t dictSize         /* note: =0 if dictStart==NULL */\n                 )\n{\n    const BYTE* ip = istart;\n    BYTE* op = (BYTE*)ostart;\n    BYTE* const oend = ostart + decompressedSize;\n    const BYTE* const prefixStart = ostart - prefixSize;\n\n    DEBUGLOG(5, \"LZ4_decompress_unsafe_generic\");\n    if (dictStart == NULL) assert(dictSize == 0);\n\n    while (1) {\n        /* start new sequence */\n        unsigned token = *ip++;\n\n        /* literals */\n        {   size_t ll = token >> ML_BITS;\n            if (ll==15) {\n                /* long literal length */\n                ll += read_long_length_no_check(&ip);\n            }\n            if ((size_t)(oend-op) < ll) return -1; /* output buffer overflow */\n            LZ4_memmove(op, ip, ll); /* support in-place decompression */\n            op += ll;\n            ip += ll;\n            if ((size_t)(oend-op) < MFLIMIT) {\n                if (op==oend) break;  /* end of block */\n                DEBUGLOG(5, \"invalid: literals end at distance %zi from end of block\", oend-op);\n                /* incorrect end of block :\n                 * last match must start at least MFLIMIT==12 bytes before end of output block */\n                return -1;\n        }   }\n\n        /* match */\n        {   size_t ml = token & 15;\n            size_t const offset = LZ4_readLE16(ip);\n            ip+=2;\n\n            if (ml==15) {\n                /* long literal length */\n                ml += read_long_length_no_check(&ip);\n            }\n            ml += MINMATCH;\n\n            if ((size_t)(oend-op) < ml) return -1; /* output buffer overflow */\n\n            {   const BYTE* match = op - offset;\n\n                /* out of range */\n                if (offset > (size_t)(op - prefixStart) + dictSize) {\n                    DEBUGLOG(6, \"offset out of range\");\n                    return -1;\n                }\n\n                /* check special case : extDict */\n                if (offset > (size_t)(op - prefixStart)) {\n                    /* extDict scenario */\n                    const BYTE* const dictEnd = dictStart + dictSize;\n                    const BYTE* extMatch = dictEnd - (offset - (size_t)(op-prefixStart));\n                    size_t const extml = (size_t)(dictEnd - extMatch);\n                    if (extml > ml) {\n                        /* match entirely within extDict */\n                        LZ4_memmove(op, extMatch, ml);\n                        op += ml;\n                        ml = 0;\n                    } else {\n                        /* match split between extDict & prefix */\n                        LZ4_memmove(op, extMatch, extml);\n                        op += extml;\n                        ml -= extml;\n                    }\n                    match = prefixStart;\n                }\n\n                /* match copy - slow variant, supporting overlap copy */\n                {   size_t u;\n                    for (u=0; u<ml; u++) {\n                        op[u] = match[u];\n            }   }   }\n            op += ml;\n            if ((size_t)(oend-op) < LASTLITERALS) {\n                DEBUGLOG(5, \"invalid: match ends at distance %zi from end of block\", oend-op);\n                /* incorrect end of block :\n                 * last match must stop at least LASTLITERALS==5 bytes before end of output block */\n                return -1;\n            }\n        } /* match */\n    } /* main loop */\n    return (int)(ip - istart);\n}\n\n\n/* Read the variable-length literal or match length.\n *\n * @ip : input pointer\n * @ilimit : position after which if length is not decoded, the input is necessarily corrupted.\n * @initial_check - check ip >= ipmax before start of loop.  Returns initial_error if so.\n * @error (output) - error code.  Must be set to 0 before call.\n**/\ntypedef size_t Rvl_t;\nstatic const Rvl_t rvl_error = (Rvl_t)(-1);\nLZ4_FORCE_INLINE Rvl_t\nread_variable_length(const BYTE** ip, const BYTE* ilimit,\n                     int initial_check)\n{\n    Rvl_t s, length = 0;\n    assert(ip != NULL);\n    assert(*ip !=  NULL);\n    assert(ilimit != NULL);\n    if (initial_check && unlikely((*ip) >= ilimit)) {    /* read limit reached */\n        return rvl_error;\n    }\n    s = **ip;\n    (*ip)++;\n    length += s;\n    if (unlikely((*ip) > ilimit)) {    /* read limit reached */\n        return rvl_error;\n    }\n    /* accumulator overflow detection (32-bit mode only) */\n    if ((sizeof(length) < 8) && unlikely(length > ((Rvl_t)(-1)/2)) ) {\n        return rvl_error;\n    }\n    if (likely(s != 255)) return length;\n    do {\n        s = **ip;\n        (*ip)++;\n        length += s;\n        if (unlikely((*ip) > ilimit)) {    /* read limit reached */\n            return rvl_error;\n        }\n        /* accumulator overflow detection (32-bit mode only) */\n        if ((sizeof(length) < 8) && unlikely(length > ((Rvl_t)(-1)/2)) ) {\n            return rvl_error;\n        }\n    } while (s == 255);\n\n    return length;\n}\n\n/*! LZ4_decompress_generic() :\n *  This generic decompression function covers all use cases.\n *  It shall be instantiated several times, using different sets of directives.\n *  Note that it is important for performance that this function really get inlined,\n *  in order to remove useless branches during compilation optimization.\n */\nLZ4_FORCE_INLINE int\nLZ4_decompress_generic(\n                 const char* const src,\n                 char* const dst,\n                 int srcSize,\n                 int outputSize,         /* If endOnInput==endOnInputSize, this value is `dstCapacity` */\n\n                 earlyEnd_directive partialDecoding,  /* full, partial */\n                 dict_directive dict,                 /* noDict, withPrefix64k, usingExtDict */\n                 const BYTE* const lowPrefix,  /* always <= dst, == dst when no prefix */\n                 const BYTE* const dictStart,  /* only if dict==usingExtDict */\n                 const size_t dictSize         /* note : = 0 if noDict */\n                 )\n{\n    if ((src == NULL) || (outputSize < 0)) { return -1; }\n\n    {   const BYTE* ip = (const BYTE*) src;\n        const BYTE* const iend = ip + srcSize;\n\n        BYTE* op = (BYTE*) dst;\n        BYTE* const oend = op + outputSize;\n        BYTE* cpy;\n\n        const BYTE* const dictEnd = (dictStart == NULL) ? NULL : dictStart + dictSize;\n\n        const int checkOffset = (dictSize < (int)(64 KB));\n\n\n        /* Set up the \"end\" pointers for the shortcut. */\n        const BYTE* const shortiend = iend - 14 /*maxLL*/ - 2 /*offset*/;\n        const BYTE* const shortoend = oend - 14 /*maxLL*/ - 18 /*maxML*/;\n\n        const BYTE* match;\n        size_t offset;\n        unsigned token;\n        size_t length;\n\n\n        DEBUGLOG(5, \"LZ4_decompress_generic (srcSize:%i, dstSize:%i)\", srcSize, outputSize);\n\n        /* Special cases */\n        assert(lowPrefix <= op);\n        if (unlikely(outputSize==0)) {\n            /* Empty output buffer */\n            if (partialDecoding) return 0;\n            return ((srcSize==1) && (*ip==0)) ? 0 : -1;\n        }\n        if (unlikely(srcSize==0)) { return -1; }\n\n    /* LZ4_FAST_DEC_LOOP:\n     * designed for modern OoO performance cpus,\n     * where copying reliably 32-bytes is preferable to an unpredictable branch.\n     * note : fast loop may show a regression for some client arm chips. */\n#if LZ4_FAST_DEC_LOOP\n        if ((oend - op) < FASTLOOP_SAFE_DISTANCE) {\n            DEBUGLOG(6, \"move to safe decode loop\");\n            goto safe_decode;\n        }\n\n        /* Fast loop : decode sequences as long as output < oend-FASTLOOP_SAFE_DISTANCE */\n        DEBUGLOG(6, \"using fast decode loop\");\n        while (1) {\n            /* Main fastloop assertion: We can always wildcopy FASTLOOP_SAFE_DISTANCE */\n            assert(oend - op >= FASTLOOP_SAFE_DISTANCE);\n            assert(ip < iend);\n            token = *ip++;\n            length = token >> ML_BITS;  /* literal length */\n            DEBUGLOG(7, \"blockPos%6u: litLength token = %u\", (unsigned)(op-(BYTE*)dst), (unsigned)length);\n\n            /* decode literal length */\n            if (length == RUN_MASK) {\n                size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);\n                if (addl == rvl_error) {\n                    DEBUGLOG(6, \"error reading long literal length\");\n                    goto _output_error;\n                }\n                length += addl;\n                if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */\n                if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */\n\n                /* copy literals */\n                LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);\n                if ((op+length>oend-32) || (ip+length>iend-32)) { goto safe_literal_copy; }\n                LZ4_wildCopy32(op, ip, op+length);\n                ip += length; op += length;\n            } else if (ip <= iend-(16 + 1/*max lit + offset + nextToken*/)) {\n                /* We don't need to check oend, since we check it once for each loop below */\n                DEBUGLOG(7, \"copy %u bytes in a 16-bytes stripe\", (unsigned)length);\n                /* Literals can only be <= 14, but hope compilers optimize better when copy by a register size */\n                LZ4_memcpy(op, ip, 16);\n                ip += length; op += length;\n            } else {\n                goto safe_literal_copy;\n            }\n\n            /* get offset */\n            offset = LZ4_readLE16(ip); ip+=2;\n            DEBUGLOG(6, \"blockPos%6u: offset = %u\", (unsigned)(op-(BYTE*)dst), (unsigned)offset);\n            match = op - offset;\n            assert(match <= op);  /* overflow check */\n\n            /* get matchlength */\n            length = token & ML_MASK;\n            DEBUGLOG(7, \"  match length token = %u (len==%u)\", (unsigned)length, (unsigned)length+MINMATCH);\n\n            if (length == ML_MASK) {\n                size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);\n                if (addl == rvl_error) {\n                    DEBUGLOG(5, \"error reading long match length\");\n                    goto _output_error;\n                }\n                length += addl;\n                length += MINMATCH;\n                DEBUGLOG(7, \"  long match length == %u\", (unsigned)length);\n                if (unlikely((uptrval)(op)+length<(uptrval)op)) { goto _output_error; } /* overflow detection */\n                if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {\n                    goto safe_match_copy;\n                }\n            } else {\n                length += MINMATCH;\n                if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {\n                    DEBUGLOG(7, \"moving to safe_match_copy (ml==%u)\", (unsigned)length);\n                    goto safe_match_copy;\n                }\n\n                /* Fastpath check: skip LZ4_wildCopy32 when true */\n                if ((dict == withPrefix64k) || (match >= lowPrefix)) {\n                    if (offset >= 8) {\n                        assert(match >= lowPrefix);\n                        assert(match <= op);\n                        assert(op + 18 <= oend);\n\n                        LZ4_memcpy(op, match, 8);\n                        LZ4_memcpy(op+8, match+8, 8);\n                        LZ4_memcpy(op+16, match+16, 2);\n                        op += length;\n                        continue;\n            }   }   }\n\n            if ( checkOffset && (unlikely(match + dictSize < lowPrefix)) ) {\n                DEBUGLOG(5, \"Error : pos=%zi, offset=%zi => outside buffers\", op-lowPrefix, op-match);\n                goto _output_error;\n            }\n            /* match starting within external dictionary */\n            if ((dict==usingExtDict) && (match < lowPrefix)) {\n                assert(dictEnd != NULL);\n                if (unlikely(op+length > oend-LASTLITERALS)) {\n                    if (partialDecoding) {\n                        DEBUGLOG(7, \"partialDecoding: dictionary match, close to dstEnd\");\n                        length = MIN(length, (size_t)(oend-op));\n                    } else {\n                        DEBUGLOG(6, \"end-of-block condition violated\")\n                        goto _output_error;\n                }   }\n\n                if (length <= (size_t)(lowPrefix-match)) {\n                    /* match fits entirely within external dictionary : just copy */\n                    LZ4_memmove(op, dictEnd - (lowPrefix-match), length);\n                    op += length;\n                } else {\n                    /* match stretches into both external dictionary and current block */\n                    size_t const copySize = (size_t)(lowPrefix - match);\n                    size_t const restSize = length - copySize;\n                    LZ4_memcpy(op, dictEnd - copySize, copySize);\n                    op += copySize;\n                    if (restSize > (size_t)(op - lowPrefix)) {  /* overlap copy */\n                        BYTE* const endOfMatch = op + restSize;\n                        const BYTE* copyFrom = lowPrefix;\n                        while (op < endOfMatch) { *op++ = *copyFrom++; }\n                    } else {\n                        LZ4_memcpy(op, lowPrefix, restSize);\n                        op += restSize;\n                }   }\n                continue;\n            }\n\n            /* copy match within block */\n            cpy = op + length;\n\n            assert((op <= oend) && (oend-op >= 32));\n            if (unlikely(offset<16)) {\n                LZ4_memcpy_using_offset(op, match, cpy, offset);\n            } else {\n                LZ4_wildCopy32(op, match, cpy);\n            }\n\n            op = cpy;   /* wildcopy correction */\n        }\n    safe_decode:\n#endif\n\n        /* Main Loop : decode remaining sequences where output < FASTLOOP_SAFE_DISTANCE */\n        DEBUGLOG(6, \"using safe decode loop\");\n        while (1) {\n            assert(ip < iend);\n            token = *ip++;\n            length = token >> ML_BITS;  /* literal length */\n            DEBUGLOG(7, \"blockPos%6u: litLength token = %u\", (unsigned)(op-(BYTE*)dst), (unsigned)length);\n\n            /* A two-stage shortcut for the most common case:\n             * 1) If the literal length is 0..14, and there is enough space,\n             * enter the shortcut and copy 16 bytes on behalf of the literals\n             * (in the fast mode, only 8 bytes can be safely copied this way).\n             * 2) Further if the match length is 4..18, copy 18 bytes in a similar\n             * manner; but we ensure that there's enough space in the output for\n             * those 18 bytes earlier, upon entering the shortcut (in other words,\n             * there is a combined check for both stages).\n             */\n            if ( (length != RUN_MASK)\n                /* strictly \"less than\" on input, to re-enter the loop with at least one byte */\n              && likely((ip < shortiend) & (op <= shortoend)) ) {\n                /* Copy the literals */\n                LZ4_memcpy(op, ip, 16);\n                op += length; ip += length;\n\n                /* The second stage: prepare for match copying, decode full info.\n                 * If it doesn't work out, the info won't be wasted. */\n                length = token & ML_MASK; /* match length */\n                DEBUGLOG(7, \"blockPos%6u: matchLength token = %u (len=%u)\", (unsigned)(op-(BYTE*)dst), (unsigned)length, (unsigned)length + 4);\n                offset = LZ4_readLE16(ip); ip += 2;\n                match = op - offset;\n                assert(match <= op); /* check overflow */\n\n                /* Do not deal with overlapping matches. */\n                if ( (length != ML_MASK)\n                  && (offset >= 8)\n                  && (dict==withPrefix64k || match >= lowPrefix) ) {\n                    /* Copy the match. */\n                    LZ4_memcpy(op + 0, match + 0, 8);\n                    LZ4_memcpy(op + 8, match + 8, 8);\n                    LZ4_memcpy(op +16, match +16, 2);\n                    op += length + MINMATCH;\n                    /* Both stages worked, load the next token. */\n                    continue;\n                }\n\n                /* The second stage didn't work out, but the info is ready.\n                 * Propel it right to the point of match copying. */\n                goto _copy_match;\n            }\n\n            /* decode literal length */\n            if (length == RUN_MASK) {\n                size_t const addl = read_variable_length(&ip, iend-RUN_MASK, 1);\n                if (addl == rvl_error) { goto _output_error; }\n                length += addl;\n                if (unlikely((uptrval)(op)+length<(uptrval)(op))) { goto _output_error; } /* overflow detection */\n                if (unlikely((uptrval)(ip)+length<(uptrval)(ip))) { goto _output_error; } /* overflow detection */\n            }\n\n#if LZ4_FAST_DEC_LOOP\n        safe_literal_copy:\n#endif\n            /* copy literals */\n            cpy = op+length;\n\n            LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH);\n            if ((cpy>oend-MFLIMIT) || (ip+length>iend-(2+1+LASTLITERALS))) {\n                /* We've either hit the input parsing restriction or the output parsing restriction.\n                 * In the normal scenario, decoding a full block, it must be the last sequence,\n                 * otherwise it's an error (invalid input or dimensions).\n                 * In partialDecoding scenario, it's necessary to ensure there is no buffer overflow.\n                 */\n                if (partialDecoding) {\n                    /* Since we are partial decoding we may be in this block because of the output parsing\n                     * restriction, which is not valid since the output buffer is allowed to be undersized.\n                     */\n                    DEBUGLOG(7, \"partialDecoding: copying literals, close to input or output end\")\n                    DEBUGLOG(7, \"partialDecoding: literal length = %u\", (unsigned)length);\n                    DEBUGLOG(7, \"partialDecoding: remaining space in dstBuffer : %i\", (int)(oend - op));\n                    DEBUGLOG(7, \"partialDecoding: remaining space in srcBuffer : %i\", (int)(iend - ip));\n                    /* Finishing in the middle of a literals segment,\n                     * due to lack of input.\n                     */\n                    if (ip+length > iend) {\n                        length = (size_t)(iend-ip);\n                        cpy = op + length;\n                    }\n                    /* Finishing in the middle of a literals segment,\n                     * due to lack of output space.\n                     */\n                    if (cpy > oend) {\n                        cpy = oend;\n                        assert(op<=oend);\n                        length = (size_t)(oend-op);\n                    }\n                } else {\n                     /* We must be on the last sequence (or invalid) because of the parsing limitations\n                      * so check that we exactly consume the input and don't overrun the output buffer.\n                      */\n                    if ((ip+length != iend) || (cpy > oend)) {\n                        DEBUGLOG(5, \"should have been last run of literals\")\n                        DEBUGLOG(5, \"ip(%p) + length(%i) = %p != iend (%p)\", ip, (int)length, ip+length, iend);\n                        DEBUGLOG(5, \"or cpy(%p) > (oend-MFLIMIT)(%p)\", cpy, oend-MFLIMIT);\n                        DEBUGLOG(5, \"after writing %u bytes / %i bytes available\", (unsigned)(op-(BYTE*)dst), outputSize);\n                        goto _output_error;\n                    }\n                }\n                LZ4_memmove(op, ip, length);  /* supports overlapping memory regions, for in-place decompression scenarios */\n                ip += length;\n                op += length;\n                /* Necessarily EOF when !partialDecoding.\n                 * When partialDecoding, it is EOF if we've either\n                 * filled the output buffer or\n                 * can't proceed with reading an offset for following match.\n                 */\n                if (!partialDecoding || (cpy == oend) || (ip >= (iend-2))) {\n                    break;\n                }\n            } else {\n                LZ4_wildCopy8(op, ip, cpy);   /* can overwrite up to 8 bytes beyond cpy */\n                ip += length; op = cpy;\n            }\n\n            /* get offset */\n            offset = LZ4_readLE16(ip); ip+=2;\n            match = op - offset;\n\n            /* get matchlength */\n            length = token & ML_MASK;\n            DEBUGLOG(7, \"blockPos%6u: matchLength token = %u\", (unsigned)(op-(BYTE*)dst), (unsigned)length);\n\n    _copy_match:\n            if (length == ML_MASK) {\n                size_t const addl = read_variable_length(&ip, iend - LASTLITERALS + 1, 0);\n                if (addl == rvl_error) { goto _output_error; }\n                length += addl;\n                if (unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error;   /* overflow detection */\n            }\n            length += MINMATCH;\n\n#if LZ4_FAST_DEC_LOOP\n        safe_match_copy:\n#endif\n            if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) goto _output_error;   /* Error : offset outside buffers */\n            /* match starting within external dictionary */\n            if ((dict==usingExtDict) && (match < lowPrefix)) {\n                assert(dictEnd != NULL);\n                if (unlikely(op+length > oend-LASTLITERALS)) {\n                    if (partialDecoding) length = MIN(length, (size_t)(oend-op));\n                    else goto _output_error;   /* doesn't respect parsing restriction */\n                }\n\n                if (length <= (size_t)(lowPrefix-match)) {\n                    /* match fits entirely within external dictionary : just copy */\n                    LZ4_memmove(op, dictEnd - (lowPrefix-match), length);\n                    op += length;\n                } else {\n                    /* match stretches into both external dictionary and current block */\n                    size_t const copySize = (size_t)(lowPrefix - match);\n                    size_t const restSize = length - copySize;\n                    LZ4_memcpy(op, dictEnd - copySize, copySize);\n                    op += copySize;\n                    if (restSize > (size_t)(op - lowPrefix)) {  /* overlap copy */\n                        BYTE* const endOfMatch = op + restSize;\n                        const BYTE* copyFrom = lowPrefix;\n                        while (op < endOfMatch) *op++ = *copyFrom++;\n                    } else {\n                        LZ4_memcpy(op, lowPrefix, restSize);\n                        op += restSize;\n                }   }\n                continue;\n            }\n            assert(match >= lowPrefix);\n\n            /* copy match within block */\n            cpy = op + length;\n\n            /* partialDecoding : may end anywhere within the block */\n            assert(op<=oend);\n            if (partialDecoding && (cpy > oend-MATCH_SAFEGUARD_DISTANCE)) {\n                size_t const mlen = MIN(length, (size_t)(oend-op));\n                const BYTE* const matchEnd = match + mlen;\n                BYTE* const copyEnd = op + mlen;\n                if (matchEnd > op) {   /* overlap copy */\n                    while (op < copyEnd) { *op++ = *match++; }\n                } else {\n                    LZ4_memcpy(op, match, mlen);\n                }\n                op = copyEnd;\n                if (op == oend) { break; }\n                continue;\n            }\n\n            if (unlikely(offset<8)) {\n                LZ4_write32(op, 0);   /* silence msan warning when offset==0 */\n                op[0] = match[0];\n                op[1] = match[1];\n                op[2] = match[2];\n                op[3] = match[3];\n                match += inc32table[offset];\n                LZ4_memcpy(op+4, match, 4);\n                match -= dec64table[offset];\n            } else {\n                LZ4_memcpy(op, match, 8);\n                match += 8;\n            }\n            op += 8;\n\n            if (unlikely(cpy > oend-MATCH_SAFEGUARD_DISTANCE)) {\n                BYTE* const oCopyLimit = oend - (WILDCOPYLENGTH-1);\n                if (cpy > oend-LASTLITERALS) { goto _output_error; } /* Error : last LASTLITERALS bytes must be literals (uncompressed) */\n                if (op < oCopyLimit) {\n                    LZ4_wildCopy8(op, match, oCopyLimit);\n                    match += oCopyLimit - op;\n                    op = oCopyLimit;\n                }\n                while (op < cpy) { *op++ = *match++; }\n            } else {\n                LZ4_memcpy(op, match, 8);\n                if (length > 16) { LZ4_wildCopy8(op+8, match+8, cpy); }\n            }\n            op = cpy;   /* wildcopy correction */\n        }\n\n        /* end of decoding */\n        DEBUGLOG(5, \"decoded %i bytes\", (int) (((char*)op)-dst));\n        return (int) (((char*)op)-dst);     /* Nb of output bytes decoded */\n\n        /* Overflow error detected */\n    _output_error:\n        return (int) (-(((const char*)ip)-src))-1;\n    }\n}\n\n\n/*===== Instantiate the API decoding functions. =====*/\n\nLZ4_FORCE_O2\nint LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)\n{\n    return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize,\n                                  decode_full_block, noDict,\n                                  (BYTE*)dest, NULL, 0);\n}\n\nLZ4_FORCE_O2\nint LZ4_decompress_safe_partial(const char* src, char* dst, int compressedSize, int targetOutputSize, int dstCapacity)\n{\n    dstCapacity = MIN(targetOutputSize, dstCapacity);\n    return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity,\n                                  partial_decode,\n                                  noDict, (BYTE*)dst, NULL, 0);\n}\n\nLZ4_FORCE_O2\nint LZ4_decompress_fast(const char* source, char* dest, int originalSize)\n{\n    DEBUGLOG(5, \"LZ4_decompress_fast\");\n    return LZ4_decompress_unsafe_generic(\n                (const BYTE*)source, (BYTE*)dest, originalSize,\n                0, NULL, 0);\n}\n\n/*===== Instantiate a few more decoding cases, used more than once. =====*/\n\nLZ4_FORCE_O2 /* Exported, an obsolete API function. */\nint LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)\n{\n    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                  decode_full_block, withPrefix64k,\n                                  (BYTE*)dest - 64 KB, NULL, 0);\n}\n\nLZ4_FORCE_O2\nstatic int LZ4_decompress_safe_partial_withPrefix64k(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity)\n{\n    dstCapacity = MIN(targetOutputSize, dstCapacity);\n    return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,\n                                  partial_decode, withPrefix64k,\n                                  (BYTE*)dest - 64 KB, NULL, 0);\n}\n\n/* Another obsolete API function, paired with the previous one. */\nint LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)\n{\n    return LZ4_decompress_unsafe_generic(\n                (const BYTE*)source, (BYTE*)dest, originalSize,\n                64 KB, NULL, 0);\n}\n\nLZ4_FORCE_O2\nstatic int LZ4_decompress_safe_withSmallPrefix(const char* source, char* dest, int compressedSize, int maxOutputSize,\n                                               size_t prefixSize)\n{\n    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                  decode_full_block, noDict,\n                                  (BYTE*)dest-prefixSize, NULL, 0);\n}\n\nLZ4_FORCE_O2\nstatic int LZ4_decompress_safe_partial_withSmallPrefix(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity,\n                                               size_t prefixSize)\n{\n    dstCapacity = MIN(targetOutputSize, dstCapacity);\n    return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,\n                                  partial_decode, noDict,\n                                  (BYTE*)dest-prefixSize, NULL, 0);\n}\n\nLZ4_FORCE_O2\nint LZ4_decompress_safe_forceExtDict(const char* source, char* dest,\n                                     int compressedSize, int maxOutputSize,\n                                     const void* dictStart, size_t dictSize)\n{\n    DEBUGLOG(5, \"LZ4_decompress_safe_forceExtDict\");\n    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                  decode_full_block, usingExtDict,\n                                  (BYTE*)dest, (const BYTE*)dictStart, dictSize);\n}\n\nLZ4_FORCE_O2\nint LZ4_decompress_safe_partial_forceExtDict(const char* source, char* dest,\n                                     int compressedSize, int targetOutputSize, int dstCapacity,\n                                     const void* dictStart, size_t dictSize)\n{\n    dstCapacity = MIN(targetOutputSize, dstCapacity);\n    return LZ4_decompress_generic(source, dest, compressedSize, dstCapacity,\n                                  partial_decode, usingExtDict,\n                                  (BYTE*)dest, (const BYTE*)dictStart, dictSize);\n}\n\nLZ4_FORCE_O2\nstatic int LZ4_decompress_fast_extDict(const char* source, char* dest, int originalSize,\n                                       const void* dictStart, size_t dictSize)\n{\n    return LZ4_decompress_unsafe_generic(\n                (const BYTE*)source, (BYTE*)dest, originalSize,\n                0, (const BYTE*)dictStart, dictSize);\n}\n\n/* The \"double dictionary\" mode, for use with e.g. ring buffers: the first part\n * of the dictionary is passed as prefix, and the second via dictStart + dictSize.\n * These routines are used only once, in LZ4_decompress_*_continue().\n */\nLZ4_FORCE_INLINE\nint LZ4_decompress_safe_doubleDict(const char* source, char* dest, int compressedSize, int maxOutputSize,\n                                   size_t prefixSize, const void* dictStart, size_t dictSize)\n{\n    return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                  decode_full_block, usingExtDict,\n                                  (BYTE*)dest-prefixSize, (const BYTE*)dictStart, dictSize);\n}\n\n/*===== streaming decompression functions =====*/\n\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nLZ4_streamDecode_t* LZ4_createStreamDecode(void)\n{\n    LZ4_STATIC_ASSERT(sizeof(LZ4_streamDecode_t) >= sizeof(LZ4_streamDecode_t_internal));\n    return (LZ4_streamDecode_t*) ALLOC_AND_ZERO(sizeof(LZ4_streamDecode_t));\n}\n\nint LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)\n{\n    if (LZ4_stream == NULL) { return 0; }  /* support free on NULL */\n    FREEMEM(LZ4_stream);\n    return 0;\n}\n#endif\n\n/*! LZ4_setStreamDecode() :\n *  Use this function to instruct where to find the dictionary.\n *  This function is not necessary if previous data is still available where it was decoded.\n *  Loading a size of 0 is allowed (same effect as no dictionary).\n * @return : 1 if OK, 0 if error\n */\nint LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize)\n{\n    LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;\n    lz4sd->prefixSize = (size_t)dictSize;\n    if (dictSize) {\n        assert(dictionary != NULL);\n        lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize;\n    } else {\n        lz4sd->prefixEnd = (const BYTE*) dictionary;\n    }\n    lz4sd->externalDict = NULL;\n    lz4sd->extDictSize  = 0;\n    return 1;\n}\n\n/*! LZ4_decoderRingBufferSize() :\n *  when setting a ring buffer for streaming decompression (optional scenario),\n *  provides the minimum size of this ring buffer\n *  to be compatible with any source respecting maxBlockSize condition.\n *  Note : in a ring buffer scenario,\n *  blocks are presumed decompressed next to each other.\n *  When not enough space remains for next block (remainingSize < maxBlockSize),\n *  decoding resumes from beginning of ring buffer.\n * @return : minimum ring buffer size,\n *           or 0 if there is an error (invalid maxBlockSize).\n */\nint LZ4_decoderRingBufferSize(int maxBlockSize)\n{\n    if (maxBlockSize < 0) return 0;\n    if (maxBlockSize > LZ4_MAX_INPUT_SIZE) return 0;\n    if (maxBlockSize < 16) maxBlockSize = 16;\n    return LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize);\n}\n\n/*\n*_continue() :\n    These decoding functions allow decompression of multiple blocks in \"streaming\" mode.\n    Previously decoded blocks must still be available at the memory position where they were decoded.\n    If it's not possible, save the relevant part of decoded data into a safe buffer,\n    and indicate where it stands using LZ4_setStreamDecode()\n*/\nLZ4_FORCE_O2\nint LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)\n{\n    LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse;\n    int result;\n\n    if (lz4sd->prefixSize == 0) {\n        /* The first call, no dictionary yet. */\n        assert(lz4sd->extDictSize == 0);\n        result = LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize);\n        if (result <= 0) return result;\n        lz4sd->prefixSize = (size_t)result;\n        lz4sd->prefixEnd = (BYTE*)dest + result;\n    } else if (lz4sd->prefixEnd == (BYTE*)dest) {\n        /* They're rolling the current segment. */\n        if (lz4sd->prefixSize >= 64 KB - 1)\n            result = LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize);\n        else if (lz4sd->extDictSize == 0)\n            result = LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize,\n                                                         lz4sd->prefixSize);\n        else\n            result = LZ4_decompress_safe_doubleDict(source, dest, compressedSize, maxOutputSize,\n                                                    lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize);\n        if (result <= 0) return result;\n        lz4sd->prefixSize += (size_t)result;\n        lz4sd->prefixEnd  += result;\n    } else {\n        /* The buffer wraps around, or they're switching to another buffer. */\n        lz4sd->extDictSize = lz4sd->prefixSize;\n        lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;\n        result = LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize,\n                                                  lz4sd->externalDict, lz4sd->extDictSize);\n        if (result <= 0) return result;\n        lz4sd->prefixSize = (size_t)result;\n        lz4sd->prefixEnd  = (BYTE*)dest + result;\n    }\n\n    return result;\n}\n\nLZ4_FORCE_O2 int\nLZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode,\n                        const char* source, char* dest, int originalSize)\n{\n    LZ4_streamDecode_t_internal* const lz4sd =\n        (assert(LZ4_streamDecode!=NULL), &LZ4_streamDecode->internal_donotuse);\n    int result;\n\n    DEBUGLOG(5, \"LZ4_decompress_fast_continue (toDecodeSize=%i)\", originalSize);\n    assert(originalSize >= 0);\n\n    if (lz4sd->prefixSize == 0) {\n        DEBUGLOG(5, \"first invocation : no prefix nor extDict\");\n        assert(lz4sd->extDictSize == 0);\n        result = LZ4_decompress_fast(source, dest, originalSize);\n        if (result <= 0) return result;\n        lz4sd->prefixSize = (size_t)originalSize;\n        lz4sd->prefixEnd = (BYTE*)dest + originalSize;\n    } else if (lz4sd->prefixEnd == (BYTE*)dest) {\n        DEBUGLOG(5, \"continue using existing prefix\");\n        result = LZ4_decompress_unsafe_generic(\n                        (const BYTE*)source, (BYTE*)dest, originalSize,\n                        lz4sd->prefixSize,\n                        lz4sd->externalDict, lz4sd->extDictSize);\n        if (result <= 0) return result;\n        lz4sd->prefixSize += (size_t)originalSize;\n        lz4sd->prefixEnd  += originalSize;\n    } else {\n        DEBUGLOG(5, \"prefix becomes extDict\");\n        lz4sd->extDictSize = lz4sd->prefixSize;\n        lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize;\n        result = LZ4_decompress_fast_extDict(source, dest, originalSize,\n                                             lz4sd->externalDict, lz4sd->extDictSize);\n        if (result <= 0) return result;\n        lz4sd->prefixSize = (size_t)originalSize;\n        lz4sd->prefixEnd  = (BYTE*)dest + originalSize;\n    }\n\n    return result;\n}\n\n\n/*\nAdvanced decoding functions :\n*_usingDict() :\n    These decoding functions work the same as \"_continue\" ones,\n    the dictionary must be explicitly provided within parameters\n*/\n\nint LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)\n{\n    if (dictSize==0)\n        return LZ4_decompress_safe(source, dest, compressedSize, maxOutputSize);\n    if (dictStart+dictSize == dest) {\n        if (dictSize >= 64 KB - 1) {\n            return LZ4_decompress_safe_withPrefix64k(source, dest, compressedSize, maxOutputSize);\n        }\n        assert(dictSize >= 0);\n        return LZ4_decompress_safe_withSmallPrefix(source, dest, compressedSize, maxOutputSize, (size_t)dictSize);\n    }\n    assert(dictSize >= 0);\n    return LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, dictStart, (size_t)dictSize);\n}\n\nint LZ4_decompress_safe_partial_usingDict(const char* source, char* dest, int compressedSize, int targetOutputSize, int dstCapacity, const char* dictStart, int dictSize)\n{\n    if (dictSize==0)\n        return LZ4_decompress_safe_partial(source, dest, compressedSize, targetOutputSize, dstCapacity);\n    if (dictStart+dictSize == dest) {\n        if (dictSize >= 64 KB - 1) {\n            return LZ4_decompress_safe_partial_withPrefix64k(source, dest, compressedSize, targetOutputSize, dstCapacity);\n        }\n        assert(dictSize >= 0);\n        return LZ4_decompress_safe_partial_withSmallPrefix(source, dest, compressedSize, targetOutputSize, dstCapacity, (size_t)dictSize);\n    }\n    assert(dictSize >= 0);\n    return LZ4_decompress_safe_partial_forceExtDict(source, dest, compressedSize, targetOutputSize, dstCapacity, dictStart, (size_t)dictSize);\n}\n\nint LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)\n{\n    if (dictSize==0 || dictStart+dictSize == dest)\n        return LZ4_decompress_unsafe_generic(\n                        (const BYTE*)source, (BYTE*)dest, originalSize,\n                        (size_t)dictSize, NULL, 0);\n    assert(dictSize >= 0);\n    return LZ4_decompress_fast_extDict(source, dest, originalSize, dictStart, (size_t)dictSize);\n}\n\n\n/*=*************************************************\n*  Obsolete Functions\n***************************************************/\n/* obsolete compression functions */\nint LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize)\n{\n    return LZ4_compress_default(source, dest, inputSize, maxOutputSize);\n}\nint LZ4_compress(const char* src, char* dest, int srcSize)\n{\n    return LZ4_compress_default(src, dest, srcSize, LZ4_compressBound(srcSize));\n}\nint LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize)\n{\n    return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1);\n}\nint LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize)\n{\n    return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1);\n}\nint LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int dstCapacity)\n{\n    return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, dstCapacity, 1);\n}\nint LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize)\n{\n    return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1);\n}\n\n/*\nThese decompression functions are deprecated and should no longer be used.\nThey are only provided here for compatibility with older user programs.\n- LZ4_uncompress is totally equivalent to LZ4_decompress_fast\n- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe\n*/\nint LZ4_uncompress (const char* source, char* dest, int outputSize)\n{\n    return LZ4_decompress_fast(source, dest, outputSize);\n}\nint LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize)\n{\n    return LZ4_decompress_safe(source, dest, isize, maxOutputSize);\n}\n\n/* Obsolete Streaming functions */\n\nint LZ4_sizeofStreamState(void) { return sizeof(LZ4_stream_t); }\n\nint LZ4_resetStreamState(void* state, char* inputBuffer)\n{\n    (void)inputBuffer;\n    LZ4_resetStream((LZ4_stream_t*)state);\n    return 0;\n}\n\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nvoid* LZ4_create (char* inputBuffer)\n{\n    (void)inputBuffer;\n    return LZ4_createStream();\n}\n#endif\n\nchar* LZ4_slideInputBuffer (void* state)\n{\n    /* avoid const char * -> char * conversion warning */\n    return (char *)(uptrval)((LZ4_stream_t*)state)->internal_donotuse.dictionary;\n}\n\n#endif   /* LZ4_COMMONDEFS_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/LZ4/lz4.h",
    "content": "﻿/*\n *  LZ4 - Fast LZ compression algorithm\n *  Header File\n *  Copyright (C) 2011-2023, Yann Collet.\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n    - LZ4 homepage : http://www.lz4.org\n    - LZ4 source repository : https://github.com/lz4/lz4\n*/\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifndef LZ4_H_2983827168210\n#define LZ4_H_2983827168210\n\n/* --- Dependency --- */\n#include <stddef.h>   /* size_t */\n\n\n/**\n  Introduction\n\n  LZ4 is lossless compression algorithm, providing compression speed >500 MB/s per core,\n  scalable with multi-cores CPU. It features an extremely fast decoder, with speed in\n  multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.\n\n  The LZ4 compression library provides in-memory compression and decompression functions.\n  It gives full buffer control to user.\n  Compression can be done in:\n    - a single step (described as Simple Functions)\n    - a single step, reusing a context (described in Advanced Functions)\n    - unbounded multiple steps (described as Streaming compression)\n\n  lz4.h generates and decodes LZ4-compressed blocks (doc/lz4_Block_format.md).\n  Decompressing such a compressed block requires additional metadata.\n  Exact metadata depends on exact decompression function.\n  For the typical case of LZ4_decompress_safe(),\n  metadata includes block's compressed size, and maximum bound of decompressed size.\n  Each application is free to encode and pass such metadata in whichever way it wants.\n\n  lz4.h only handle blocks, it can not generate Frames.\n\n  Blocks are different from Frames (doc/lz4_Frame_format.md).\n  Frames bundle both blocks and metadata in a specified manner.\n  Embedding metadata is required for compressed data to be self-contained and portable.\n  Frame format is delivered through a companion API, declared in lz4frame.h.\n  The `lz4` CLI can only manage frames.\n*/\n\n/*^***************************************************************\n*  Export parameters\n*****************************************************************/\n/*\n*  LZ4_DLL_EXPORT :\n*  Enable exporting of functions when building a Windows DLL\n*  LZ4LIB_VISIBILITY :\n*  Control library symbols visibility.\n*/\n#ifndef LZ4LIB_VISIBILITY\n#  if defined(__GNUC__) && (__GNUC__ >= 4)\n#    define LZ4LIB_VISIBILITY __attribute__ ((visibility (\"default\")))\n#  else\n#    define LZ4LIB_VISIBILITY\n#  endif\n#endif\n#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)\n#  define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY\n#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)\n#  define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define LZ4LIB_API LZ4LIB_VISIBILITY\n#endif\n\n/*! LZ4_FREESTANDING :\n *  When this macro is set to 1, it enables \"freestanding mode\" that is\n *  suitable for typical freestanding environment which doesn't support\n *  standard C library.\n *\n *  - LZ4_FREESTANDING is a compile-time switch.\n *  - It requires the following macros to be defined:\n *    LZ4_memcpy, LZ4_memmove, LZ4_memset.\n *  - It only enables LZ4/HC functions which don't use heap.\n *    All LZ4F_* functions are not supported.\n *  - See tests/freestanding.c to check its basic setup.\n */\n#if defined(LZ4_FREESTANDING) && (LZ4_FREESTANDING == 1)\n#  define LZ4_HEAPMODE 0\n#  define LZ4HC_HEAPMODE 0\n#  define LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION 1\n#  if !defined(LZ4_memcpy)\n#    error \"LZ4_FREESTANDING requires macro 'LZ4_memcpy'.\"\n#  endif\n#  if !defined(LZ4_memset)\n#    error \"LZ4_FREESTANDING requires macro 'LZ4_memset'.\"\n#  endif\n#  if !defined(LZ4_memmove)\n#    error \"LZ4_FREESTANDING requires macro 'LZ4_memmove'.\"\n#  endif\n#elif ! defined(LZ4_FREESTANDING)\n#  define LZ4_FREESTANDING 0\n#endif\n\n\n/*------   Version   ------*/\n#define LZ4_VERSION_MAJOR    1    /* for breaking interface changes  */\n#define LZ4_VERSION_MINOR   10    /* for new (non-breaking) interface capabilities */\n#define LZ4_VERSION_RELEASE  0    /* for tweaks, bug-fixes, or development */\n\n#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)\n\n#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE\n#define LZ4_QUOTE(str) #str\n#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)\n#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)  /* requires v1.7.3+ */\n\nLZ4LIB_API int LZ4_versionNumber (void);  /**< library version number; useful to check dll version; requires v1.3.0+ */\nLZ4LIB_API const char* LZ4_versionString (void);   /**< library version string; useful to check dll version; requires v1.7.5+ */\n\n\n/*-************************************\n*  Tuning memory usage\n**************************************/\n/*!\n * LZ4_MEMORY_USAGE :\n * Can be selected at compile time, by setting LZ4_MEMORY_USAGE.\n * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB)\n * Increasing memory usage improves compression ratio, generally at the cost of speed.\n * Reduced memory usage may improve speed at the cost of ratio, thanks to better cache locality.\n * Default value is 14, for 16KB, which nicely fits into most L1 caches.\n */\n#ifndef LZ4_MEMORY_USAGE\n# define LZ4_MEMORY_USAGE LZ4_MEMORY_USAGE_DEFAULT\n#endif\n\n/* These are absolute limits, they should not be changed by users */\n#define LZ4_MEMORY_USAGE_MIN 10\n#define LZ4_MEMORY_USAGE_DEFAULT 14\n#define LZ4_MEMORY_USAGE_MAX 20\n\n#if (LZ4_MEMORY_USAGE < LZ4_MEMORY_USAGE_MIN)\n#  error \"LZ4_MEMORY_USAGE is too small !\"\n#endif\n\n#if (LZ4_MEMORY_USAGE > LZ4_MEMORY_USAGE_MAX)\n#  error \"LZ4_MEMORY_USAGE is too large !\"\n#endif\n\n/*-************************************\n*  Simple Functions\n**************************************/\n/*! LZ4_compress_default() :\n *  Compresses 'srcSize' bytes from buffer 'src'\n *  into already allocated 'dst' buffer of size 'dstCapacity'.\n *  Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).\n *  It also runs faster, so it's a recommended setting.\n *  If the function cannot compress 'src' into a more limited 'dst' budget,\n *  compression stops *immediately*, and the function result is zero.\n *  In which case, 'dst' content is undefined (invalid).\n *      srcSize : max supported value is LZ4_MAX_INPUT_SIZE.\n *      dstCapacity : size of buffer 'dst' (which must be already allocated)\n *     @return  : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)\n *                or 0 if compression fails\n * Note : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).\n */\nLZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);\n\n/*! LZ4_decompress_safe() :\n * @compressedSize : is the exact complete size of the compressed block.\n * @dstCapacity : is the size of destination buffer (which must be already allocated),\n *                presumed an upper bound of decompressed size.\n * @return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)\n *           If destination buffer is not large enough, decoding will stop and output an error code (negative value).\n *           If the source stream is detected malformed, the function will stop decoding and return a negative result.\n * Note 1 : This function is protected against malicious data packets :\n *          it will never writes outside 'dst' buffer, nor read outside 'source' buffer,\n *          even if the compressed block is maliciously modified to order the decoder to do these actions.\n *          In such case, the decoder stops immediately, and considers the compressed block malformed.\n * Note 2 : compressedSize and dstCapacity must be provided to the function, the compressed block does not contain them.\n *          The implementation is free to send / store / derive this information in whichever way is most beneficial.\n *          If there is a need for a different format which bundles together both compressed data and its metadata, consider looking at lz4frame.h instead.\n */\nLZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);\n\n\n/*-************************************\n*  Advanced Functions\n**************************************/\n#define LZ4_MAX_INPUT_SIZE        0x7E000000   /* 2 113 929 216 bytes */\n#define LZ4_COMPRESSBOUND(isize)  ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)\n\n/*! LZ4_compressBound() :\n    Provides the maximum size that LZ4 compression may output in a \"worst case\" scenario (input data not compressible)\n    This function is primarily useful for memory allocation purposes (destination buffer size).\n    Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).\n    Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)\n        inputSize  : max supported value is LZ4_MAX_INPUT_SIZE\n        return : maximum output size in a \"worst case\" scenario\n              or 0, if input size is incorrect (too large or negative)\n*/\nLZ4LIB_API int LZ4_compressBound(int inputSize);\n\n/*! LZ4_compress_fast() :\n    Same as LZ4_compress_default(), but allows selection of \"acceleration\" factor.\n    The larger the acceleration value, the faster the algorithm, but also the lesser the compression.\n    It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.\n    An acceleration value of \"1\" is the same as regular LZ4_compress_default()\n    Values <= 0 will be replaced by LZ4_ACCELERATION_DEFAULT (currently == 1, see lz4.c).\n    Values > LZ4_ACCELERATION_MAX will be replaced by LZ4_ACCELERATION_MAX (currently == 65537, see lz4.c).\n*/\nLZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);\n\n\n/*! LZ4_compress_fast_extState() :\n *  Same as LZ4_compress_fast(), using an externally allocated memory space for its state.\n *  Use LZ4_sizeofState() to know how much memory must be allocated,\n *  and allocate it on 8-bytes boundaries (using `malloc()` typically).\n *  Then, provide this buffer as `void* state` to compression function.\n */\nLZ4LIB_API int LZ4_sizeofState(void);\nLZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);\n\n/*! LZ4_compress_destSize() :\n *  Reverse the logic : compresses as much data as possible from 'src' buffer\n *  into already allocated buffer 'dst', of size >= 'dstCapacity'.\n *  This function either compresses the entire 'src' content into 'dst' if it's large enough,\n *  or fill 'dst' buffer completely with as much data as possible from 'src'.\n *  note: acceleration parameter is fixed to \"default\".\n *\n * *srcSizePtr : in+out parameter. Initially contains size of input.\n *               Will be modified to indicate how many bytes where read from 'src' to fill 'dst'.\n *               New value is necessarily <= input value.\n * @return : Nb bytes written into 'dst' (necessarily <= dstCapacity)\n *           or 0 if compression fails.\n *\n * Note : from v1.8.2 to v1.9.1, this function had a bug (fixed in v1.9.2+):\n *        the produced compressed content could, in specific circumstances,\n *        require to be decompressed into a destination buffer larger\n *        by at least 1 byte than the content to decompress.\n *        If an application uses `LZ4_compress_destSize()`,\n *        it's highly recommended to update liblz4 to v1.9.2 or better.\n *        If this can't be done or ensured,\n *        the receiving decompression function should provide\n *        a dstCapacity which is > decompressedSize, by at least 1 byte.\n *        See https://github.com/lz4/lz4/issues/859 for details\n */\nLZ4LIB_API int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize);\n\n/*! LZ4_decompress_safe_partial() :\n *  Decompress an LZ4 compressed block, of size 'srcSize' at position 'src',\n *  into destination buffer 'dst' of size 'dstCapacity'.\n *  Up to 'targetOutputSize' bytes will be decoded.\n *  The function stops decoding on reaching this objective.\n *  This can be useful to boost performance\n *  whenever only the beginning of a block is required.\n *\n * @return : the number of bytes decoded in `dst` (necessarily <= targetOutputSize)\n *           If source stream is detected malformed, function returns a negative result.\n *\n *  Note 1 : @return can be < targetOutputSize, if compressed block contains less data.\n *\n *  Note 2 : targetOutputSize must be <= dstCapacity\n *\n *  Note 3 : this function effectively stops decoding on reaching targetOutputSize,\n *           so dstCapacity is kind of redundant.\n *           This is because in older versions of this function,\n *           decoding operation would still write complete sequences.\n *           Therefore, there was no guarantee that it would stop writing at exactly targetOutputSize,\n *           it could write more bytes, though only up to dstCapacity.\n *           Some \"margin\" used to be required for this operation to work properly.\n *           Thankfully, this is no longer necessary.\n *           The function nonetheless keeps the same signature, in an effort to preserve API compatibility.\n *\n *  Note 4 : If srcSize is the exact size of the block,\n *           then targetOutputSize can be any value,\n *           including larger than the block's decompressed size.\n *           The function will, at most, generate block's decompressed size.\n *\n *  Note 5 : If srcSize is _larger_ than block's compressed size,\n *           then targetOutputSize **MUST** be <= block's decompressed size.\n *           Otherwise, *silent corruption will occur*.\n */\nLZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);\n\n\n/*-*********************************************\n*  Streaming Compression Functions\n***********************************************/\ntypedef union LZ4_stream_u LZ4_stream_t;  /* incomplete type (defined later) */\n\n/*!\n Note about RC_INVOKED\n\n - RC_INVOKED is predefined symbol of rc.exe (the resource compiler which is part of MSVC/Visual Studio).\n   https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros\n\n - Since rc.exe is a legacy compiler, it truncates long symbol (> 30 chars)\n   and reports warning \"RC4011: identifier truncated\".\n\n - To eliminate the warning, we surround long preprocessor symbol with\n   \"#if !defined(RC_INVOKED) ... #endif\" block that means\n   \"skip this block when rc.exe is trying to read it\".\n*/\n#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nLZ4LIB_API LZ4_stream_t* LZ4_createStream(void);\nLZ4LIB_API int           LZ4_freeStream (LZ4_stream_t* streamPtr);\n#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */\n#endif\n\n/*! LZ4_resetStream_fast() : v1.9.0+\n *  Use this to prepare an LZ4_stream_t for a new chain of dependent blocks\n *  (e.g., LZ4_compress_fast_continue()).\n *\n *  An LZ4_stream_t must be initialized once before usage.\n *  This is automatically done when created by LZ4_createStream().\n *  However, should the LZ4_stream_t be simply declared on stack (for example),\n *  it's necessary to initialize it first, using LZ4_initStream().\n *\n *  After init, start any new stream with LZ4_resetStream_fast().\n *  A same LZ4_stream_t can be re-used multiple times consecutively\n *  and compress multiple streams,\n *  provided that it starts each new stream with LZ4_resetStream_fast().\n *\n *  LZ4_resetStream_fast() is much faster than LZ4_initStream(),\n *  but is not compatible with memory regions containing garbage data.\n *\n *  Note: it's only useful to call LZ4_resetStream_fast()\n *        in the context of streaming compression.\n *        The *extState* functions perform their own resets.\n *        Invoking LZ4_resetStream_fast() before is redundant, and even counterproductive.\n */\nLZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);\n\n/*! LZ4_loadDict() :\n *  Use this function to reference a static dictionary into LZ4_stream_t.\n *  The dictionary must remain available during compression.\n *  LZ4_loadDict() triggers a reset, so any previous data will be forgotten.\n *  The same dictionary will have to be loaded on decompression side for successful decoding.\n *  Dictionary are useful for better compression of small data (KB range).\n *  While LZ4 itself accepts any input as dictionary, dictionary efficiency is also a topic.\n *  When in doubt, employ the Zstandard's Dictionary Builder.\n *  Loading a size of 0 is allowed, and is the same as reset.\n * @return : loaded dictionary size, in bytes (note: only the last 64 KB are loaded)\n */\nLZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);\n\n/*! LZ4_loadDictSlow() : v1.10.0+\n *  Same as LZ4_loadDict(),\n *  but uses a bit more cpu to reference the dictionary content more thoroughly.\n *  This is expected to slightly improve compression ratio.\n *  The extra-cpu cost is likely worth it if the dictionary is re-used across multiple sessions.\n * @return : loaded dictionary size, in bytes (note: only the last 64 KB are loaded)\n */\nLZ4LIB_API int LZ4_loadDictSlow(LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);\n\n/*! LZ4_attach_dictionary() : stable since v1.10.0\n *\n *  This allows efficient re-use of a static dictionary multiple times.\n *\n *  Rather than re-loading the dictionary buffer into a working context before\n *  each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a\n *  working LZ4_stream_t, this function introduces a no-copy setup mechanism,\n *  in which the working stream references @dictionaryStream in-place.\n *\n *  Several assumptions are made about the state of @dictionaryStream.\n *  Currently, only states which have been prepared by LZ4_loadDict() or\n *  LZ4_loadDictSlow() should be expected to work.\n *\n *  Alternatively, the provided @dictionaryStream may be NULL,\n *  in which case any existing dictionary stream is unset.\n *\n *  If a dictionary is provided, it replaces any pre-existing stream history.\n *  The dictionary contents are the only history that can be referenced and\n *  logically immediately precede the data compressed in the first subsequent\n *  compression call.\n *\n *  The dictionary will only remain attached to the working stream through the\n *  first compression call, at the end of which it is cleared.\n * @dictionaryStream stream (and source buffer) must remain in-place / accessible / unchanged\n *  through the completion of the compression session.\n *\n *  Note: there is no equivalent LZ4_attach_*() method on the decompression side\n *  because there is no initialization cost, hence no need to share the cost across multiple sessions.\n *  To decompress LZ4 blocks using dictionary, attached or not,\n *  just employ the regular LZ4_setStreamDecode() for streaming,\n *  or the stateless LZ4_decompress_safe_usingDict() for one-shot decompression.\n */\nLZ4LIB_API void\nLZ4_attach_dictionary(LZ4_stream_t* workingStream,\n                const LZ4_stream_t* dictionaryStream);\n\n/*! LZ4_compress_fast_continue() :\n *  Compress 'src' content using data from previously compressed blocks, for better compression ratio.\n * 'dst' buffer must be already allocated.\n *  If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.\n *\n * @return : size of compressed block\n *           or 0 if there is an error (typically, cannot fit into 'dst').\n *\n *  Note 1 : Each invocation to LZ4_compress_fast_continue() generates a new block.\n *           Each block has precise boundaries.\n *           Each block must be decompressed separately, calling LZ4_decompress_*() with relevant metadata.\n *           It's not possible to append blocks together and expect a single invocation of LZ4_decompress_*() to decompress them together.\n *\n *  Note 2 : The previous 64KB of source data is __assumed__ to remain present, unmodified, at same address in memory !\n *\n *  Note 3 : When input is structured as a double-buffer, each buffer can have any size, including < 64 KB.\n *           Make sure that buffers are separated, by at least one byte.\n *           This construction ensures that each block only depends on previous block.\n *\n *  Note 4 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.\n *\n *  Note 5 : After an error, the stream status is undefined (invalid), it can only be reset or freed.\n */\nLZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);\n\n/*! LZ4_saveDict() :\n *  If last 64KB data cannot be guaranteed to remain available at its current memory location,\n *  save it into a safer place (char* safeBuffer).\n *  This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),\n *  but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.\n * @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.\n */\nLZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);\n\n\n/*-**********************************************\n*  Streaming Decompression Functions\n*  Bufferless synchronous API\n************************************************/\ntypedef union LZ4_streamDecode_u LZ4_streamDecode_t;   /* tracking context */\n\n/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :\n *  creation / destruction of streaming decompression tracking context.\n *  A tracking context can be re-used multiple times.\n */\n#if !defined(RC_INVOKED) /* https://docs.microsoft.com/en-us/windows/win32/menurc/predefined-macros */\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nLZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);\nLZ4LIB_API int                 LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);\n#endif /* !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION) */\n#endif\n\n/*! LZ4_setStreamDecode() :\n *  An LZ4_streamDecode_t context can be allocated once and re-used multiple times.\n *  Use this function to start decompression of a new stream of blocks.\n *  A dictionary can optionally be set. Use NULL or size 0 for a reset order.\n *  Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.\n * @return : 1 if OK, 0 if error\n */\nLZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);\n\n/*! LZ4_decoderRingBufferSize() : v1.8.2+\n *  Note : in a ring buffer scenario (optional),\n *  blocks are presumed decompressed next to each other\n *  up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),\n *  at which stage it resumes from beginning of ring buffer.\n *  When setting such a ring buffer for streaming decompression,\n *  provides the minimum size of this ring buffer\n *  to be compatible with any source respecting maxBlockSize condition.\n * @return : minimum ring buffer size,\n *           or 0 if there is an error (invalid maxBlockSize).\n */\nLZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);\n#define LZ4_DECODER_RING_BUFFER_SIZE(maxBlockSize) (65536 + 14 + (maxBlockSize))  /* for static allocation; maxBlockSize presumed valid */\n\n/*! LZ4_decompress_safe_continue() :\n *  This decoding function allows decompression of consecutive blocks in \"streaming\" mode.\n *  The difference with the usual independent blocks is that\n *  new blocks are allowed to find references into former blocks.\n *  A block is an unsplittable entity, and must be presented entirely to the decompression function.\n *  LZ4_decompress_safe_continue() only accepts one block at a time.\n *  It's modeled after `LZ4_decompress_safe()` and behaves similarly.\n *\n * @LZ4_streamDecode : decompression state, tracking the position in memory of past data\n * @compressedSize : exact complete size of one compressed block.\n * @dstCapacity : size of destination buffer (which must be already allocated),\n *                must be an upper bound of decompressed size.\n * @return : number of bytes decompressed into destination buffer (necessarily <= dstCapacity)\n *           If destination buffer is not large enough, decoding will stop and output an error code (negative value).\n *           If the source stream is detected malformed, the function will stop decoding and return a negative result.\n *\n *  The last 64KB of previously decoded data *must* remain available and unmodified\n *  at the memory position where they were previously decoded.\n *  If less than 64KB of data has been decoded, all the data must be present.\n *\n *  Special : if decompression side sets a ring buffer, it must respect one of the following conditions :\n *  - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).\n *    maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.\n *    In which case, encoding and decoding buffers do not need to be synchronized.\n *    Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.\n *  - Synchronized mode :\n *    Decompression buffer size is _exactly_ the same as compression buffer size,\n *    and follows exactly same update rule (block boundaries at same positions),\n *    and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),\n *    _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).\n *  - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.\n *    In which case, encoding and decoding buffers do not need to be synchronized,\n *    and encoding ring buffer can have any size, including small ones ( < 64 KB).\n *\n *  Whenever these conditions are not possible,\n *  save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,\n *  then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.\n*/\nLZ4LIB_API int\nLZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode,\n                        const char* src, char* dst,\n                        int srcSize, int dstCapacity);\n\n\n/*! LZ4_decompress_safe_usingDict() :\n *  Works the same as\n *  a combination of LZ4_setStreamDecode() followed by LZ4_decompress_safe_continue()\n *  However, it's stateless: it doesn't need any LZ4_streamDecode_t state.\n *  Dictionary is presumed stable : it must remain accessible and unmodified during decompression.\n *  Performance tip : Decompression speed can be substantially increased\n *                    when dst == dictStart + dictSize.\n */\nLZ4LIB_API int\nLZ4_decompress_safe_usingDict(const char* src, char* dst,\n                              int srcSize, int dstCapacity,\n                              const char* dictStart, int dictSize);\n\n/*! LZ4_decompress_safe_partial_usingDict() :\n *  Behaves the same as LZ4_decompress_safe_partial()\n *  with the added ability to specify a memory segment for past data.\n *  Performance tip : Decompression speed can be substantially increased\n *                    when dst == dictStart + dictSize.\n */\nLZ4LIB_API int\nLZ4_decompress_safe_partial_usingDict(const char* src, char* dst,\n                                      int compressedSize,\n                                      int targetOutputSize, int maxOutputSize,\n                                      const char* dictStart, int dictSize);\n\n#endif /* LZ4_H_2983827168210 */\n\n\n/*^*************************************\n * !!!!!!   STATIC LINKING ONLY   !!!!!!\n ***************************************/\n\n/*-****************************************************************************\n * Experimental section\n *\n * Symbols declared in this section must be considered unstable. Their\n * signatures or semantics may change, or they may be removed altogether in the\n * future. They are therefore only safe to depend on when the caller is\n * statically linked against the library.\n *\n * To protect against unsafe usage, not only are the declarations guarded,\n * the definitions are hidden by default\n * when building LZ4 as a shared/dynamic library.\n *\n * In order to access these declarations,\n * define LZ4_STATIC_LINKING_ONLY in your application\n * before including LZ4's headers.\n *\n * In order to make their implementations accessible dynamically, you must\n * define LZ4_PUBLISH_STATIC_FUNCTIONS when building the LZ4 library.\n ******************************************************************************/\n\n#ifdef LZ4_STATIC_LINKING_ONLY\n\n#ifndef LZ4_STATIC_3504398509\n#define LZ4_STATIC_3504398509\n\n#ifdef LZ4_PUBLISH_STATIC_FUNCTIONS\n# define LZ4LIB_STATIC_API LZ4LIB_API\n#else\n# define LZ4LIB_STATIC_API\n#endif\n\n\n/*! LZ4_compress_fast_extState_fastReset() :\n *  A variant of LZ4_compress_fast_extState().\n *\n *  Using this variant avoids an expensive initialization step.\n *  It is only safe to call if the state buffer is known to be correctly initialized already\n *  (see above comment on LZ4_resetStream_fast() for a definition of \"correctly initialized\").\n *  From a high level, the difference is that\n *  this function initializes the provided state with a call to something like LZ4_resetStream_fast()\n *  while LZ4_compress_fast_extState() starts with a call to LZ4_resetStream().\n */\nLZ4LIB_STATIC_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);\n\n/*! LZ4_compress_destSize_extState() : introduced in v1.10.0\n *  Same as LZ4_compress_destSize(), but using an externally allocated state.\n *  Also: exposes @acceleration\n */\nint LZ4_compress_destSize_extState(void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize, int acceleration);\n\n/*! In-place compression and decompression\n *\n * It's possible to have input and output sharing the same buffer,\n * for highly constrained memory environments.\n * In both cases, it requires input to lay at the end of the buffer,\n * and decompression to start at beginning of the buffer.\n * Buffer size must feature some margin, hence be larger than final size.\n *\n * |<------------------------buffer--------------------------------->|\n *                             |<-----------compressed data--------->|\n * |<-----------decompressed size------------------>|\n *                                                  |<----margin---->|\n *\n * This technique is more useful for decompression,\n * since decompressed size is typically larger,\n * and margin is short.\n *\n * In-place decompression will work inside any buffer\n * which size is >= LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize).\n * This presumes that decompressedSize > compressedSize.\n * Otherwise, it means compression actually expanded data,\n * and it would be more efficient to store such data with a flag indicating it's not compressed.\n * This can happen when data is not compressible (already compressed, or encrypted).\n *\n * For in-place compression, margin is larger, as it must be able to cope with both\n * history preservation, requiring input data to remain unmodified up to LZ4_DISTANCE_MAX,\n * and data expansion, which can happen when input is not compressible.\n * As a consequence, buffer size requirements are much higher,\n * and memory savings offered by in-place compression are more limited.\n *\n * There are ways to limit this cost for compression :\n * - Reduce history size, by modifying LZ4_DISTANCE_MAX.\n *   Note that it is a compile-time constant, so all compressions will apply this limit.\n *   Lower values will reduce compression ratio, except when input_size < LZ4_DISTANCE_MAX,\n *   so it's a reasonable trick when inputs are known to be small.\n * - Require the compressor to deliver a \"maximum compressed size\".\n *   This is the `dstCapacity` parameter in `LZ4_compress*()`.\n *   When this size is < LZ4_COMPRESSBOUND(inputSize), then compression can fail,\n *   in which case, the return code will be 0 (zero).\n *   The caller must be ready for these cases to happen,\n *   and typically design a backup scheme to send data uncompressed.\n * The combination of both techniques can significantly reduce\n * the amount of margin required for in-place compression.\n *\n * In-place compression can work in any buffer\n * which size is >= (maxCompressedSize)\n * with maxCompressedSize == LZ4_COMPRESSBOUND(srcSize) for guaranteed compression success.\n * LZ4_COMPRESS_INPLACE_BUFFER_SIZE() depends on both maxCompressedSize and LZ4_DISTANCE_MAX,\n * so it's possible to reduce memory requirements by playing with them.\n */\n\n#define LZ4_DECOMPRESS_INPLACE_MARGIN(compressedSize)          (((compressedSize) >> 8) + 32)\n#define LZ4_DECOMPRESS_INPLACE_BUFFER_SIZE(decompressedSize)   ((decompressedSize) + LZ4_DECOMPRESS_INPLACE_MARGIN(decompressedSize))  /**< note: presumes that compressedSize < decompressedSize. note2: margin is overestimated a bit, since it could use compressedSize instead */\n\n#ifndef LZ4_DISTANCE_MAX   /* history window size; can be user-defined at compile time */\n#  define LZ4_DISTANCE_MAX 65535   /* set to maximum value by default */\n#endif\n\n#define LZ4_COMPRESS_INPLACE_MARGIN                           (LZ4_DISTANCE_MAX + 32)   /* LZ4_DISTANCE_MAX can be safely replaced by srcSize when it's smaller */\n#define LZ4_COMPRESS_INPLACE_BUFFER_SIZE(maxCompressedSize)   ((maxCompressedSize) + LZ4_COMPRESS_INPLACE_MARGIN)  /**< maxCompressedSize is generally LZ4_COMPRESSBOUND(inputSize), but can be set to any lower value, with the risk that compression can fail (return code 0(zero)) */\n\n#endif   /* LZ4_STATIC_3504398509 */\n#endif   /* LZ4_STATIC_LINKING_ONLY */\n\n\n\n#ifndef LZ4_H_98237428734687\n#define LZ4_H_98237428734687\n\n/*-************************************************************\n *  Private Definitions\n **************************************************************\n * Do not use these definitions directly.\n * They are only exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.\n * Accessing members will expose user code to API and/or ABI break in future versions of the library.\n **************************************************************/\n#define LZ4_HASHLOG   (LZ4_MEMORY_USAGE-2)\n#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)\n#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG)       /* required as macro for static allocation */\n\n#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# include <stdint.h>\n  typedef  int8_t  LZ4_i8;\n  typedef uint8_t  LZ4_byte;\n  typedef uint16_t LZ4_u16;\n  typedef uint32_t LZ4_u32;\n#else\n  typedef   signed char  LZ4_i8;\n  typedef unsigned char  LZ4_byte;\n  typedef unsigned short LZ4_u16;\n  typedef unsigned int   LZ4_u32;\n#endif\n\n/*! LZ4_stream_t :\n *  Never ever use below internal definitions directly !\n *  These definitions are not API/ABI safe, and may change in future versions.\n *  If you need static allocation, declare or allocate an LZ4_stream_t object.\n**/\n\ntypedef struct LZ4_stream_t_internal LZ4_stream_t_internal;\nstruct LZ4_stream_t_internal {\n    LZ4_u32 hashTable[LZ4_HASH_SIZE_U32];\n    const LZ4_byte* dictionary;\n    const LZ4_stream_t_internal* dictCtx;\n    LZ4_u32 currentOffset;\n    LZ4_u32 tableType;\n    LZ4_u32 dictSize;\n    /* Implicit padding to ensure structure is aligned */\n};\n\n#define LZ4_STREAM_MINSIZE  ((1UL << (LZ4_MEMORY_USAGE)) + 32)  /* static size, for inter-version compatibility */\nunion LZ4_stream_u {\n    char minStateSize[LZ4_STREAM_MINSIZE];\n    LZ4_stream_t_internal internal_donotuse;\n}; /* previously typedef'd to LZ4_stream_t */\n\n\n/*! LZ4_initStream() : v1.9.0+\n *  An LZ4_stream_t structure must be initialized at least once.\n *  This is automatically done when invoking LZ4_createStream(),\n *  but it's not when the structure is simply declared on stack (for example).\n *\n *  Use LZ4_initStream() to properly initialize a newly declared LZ4_stream_t.\n *  It can also initialize any arbitrary buffer of sufficient size,\n *  and will @return a pointer of proper type upon initialization.\n *\n *  Note : initialization fails if size and alignment conditions are not respected.\n *         In which case, the function will @return NULL.\n *  Note2: An LZ4_stream_t structure guarantees correct alignment and size.\n *  Note3: Before v1.9.0, use LZ4_resetStream() instead\n**/\nLZ4LIB_API LZ4_stream_t* LZ4_initStream (void* stateBuffer, size_t size);\n\n\n/*! LZ4_streamDecode_t :\n *  Never ever use below internal definitions directly !\n *  These definitions are not API/ABI safe, and may change in future versions.\n *  If you need static allocation, declare or allocate an LZ4_streamDecode_t object.\n**/\ntypedef struct {\n    const LZ4_byte* externalDict;\n    const LZ4_byte* prefixEnd;\n    size_t extDictSize;\n    size_t prefixSize;\n} LZ4_streamDecode_t_internal;\n\n#define LZ4_STREAMDECODE_MINSIZE 32\nunion LZ4_streamDecode_u {\n    char minStateSize[LZ4_STREAMDECODE_MINSIZE];\n    LZ4_streamDecode_t_internal internal_donotuse;\n} ;   /* previously typedef'd to LZ4_streamDecode_t */\n\n\n\n/*-************************************\n*  Obsolete Functions\n**************************************/\n\n/*! Deprecation warnings\n *\n *  Deprecated functions make the compiler generate a warning when invoked.\n *  This is meant to invite users to update their source code.\n *  Should deprecation warnings be a problem, it is generally possible to disable them,\n *  typically with -Wno-deprecated-declarations for gcc\n *  or _CRT_SECURE_NO_WARNINGS in Visual.\n *\n *  Another method is to define LZ4_DISABLE_DEPRECATE_WARNINGS\n *  before including the header file.\n */\n#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS\n#  define LZ4_DEPRECATED(message)   /* disable deprecation warnings */\n#else\n#  if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */\n#    define LZ4_DEPRECATED(message) [[deprecated(message)]]\n#  elif defined(_MSC_VER)\n#    define LZ4_DEPRECATED(message) __declspec(deprecated(message))\n#  elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 45))\n#    define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))\n#  elif defined(__GNUC__) && (__GNUC__ * 10 + __GNUC_MINOR__ >= 31)\n#    define LZ4_DEPRECATED(message) __attribute__((deprecated))\n#  else\n#    pragma message(\"WARNING: LZ4_DEPRECATED needs custom implementation for this compiler\")\n#    define LZ4_DEPRECATED(message)   /* disabled */\n#  endif\n#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */\n\n/*! Obsolete compression functions (since v1.7.3) */\nLZ4_DEPRECATED(\"use LZ4_compress_default() instead\")       LZ4LIB_API int LZ4_compress               (const char* src, char* dest, int srcSize);\nLZ4_DEPRECATED(\"use LZ4_compress_default() instead\")       LZ4LIB_API int LZ4_compress_limitedOutput (const char* src, char* dest, int srcSize, int maxOutputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_fast_extState() instead\") LZ4LIB_API int LZ4_compress_withState               (void* state, const char* source, char* dest, int inputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_fast_extState() instead\") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_fast_continue() instead\") LZ4LIB_API int LZ4_compress_continue                (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_fast_continue() instead\") LZ4LIB_API int LZ4_compress_limitedOutput_continue  (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);\n\n/*! Obsolete decompression functions (since v1.8.0) */\nLZ4_DEPRECATED(\"use LZ4_decompress_fast() instead\") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);\nLZ4_DEPRECATED(\"use LZ4_decompress_safe() instead\") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);\n\n/* Obsolete streaming functions (since v1.7.0)\n * degraded functionality; do not use!\n *\n * In order to perform streaming compression, these functions depended on data\n * that is no longer tracked in the state. They have been preserved as well as\n * possible: using them will still produce a correct output. However, they don't\n * actually retain any history between compression calls. The compression ratio\n * achieved will therefore be no better than compressing each chunk\n * independently.\n */\nLZ4_DEPRECATED(\"Use LZ4_createStream() instead\") LZ4LIB_API void* LZ4_create (char* inputBuffer);\nLZ4_DEPRECATED(\"Use LZ4_createStream() instead\") LZ4LIB_API int   LZ4_sizeofStreamState(void);\nLZ4_DEPRECATED(\"Use LZ4_resetStream() instead\")  LZ4LIB_API int   LZ4_resetStreamState(void* state, char* inputBuffer);\nLZ4_DEPRECATED(\"Use LZ4_saveDict() instead\")     LZ4LIB_API char* LZ4_slideInputBuffer (void* state);\n\n/*! Obsolete streaming decoding functions (since v1.7.0) */\nLZ4_DEPRECATED(\"use LZ4_decompress_safe_usingDict() instead\") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);\nLZ4_DEPRECATED(\"use LZ4_decompress_fast_usingDict() instead\") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);\n\n/*! Obsolete LZ4_decompress_fast variants (since v1.9.0) :\n *  These functions used to be faster than LZ4_decompress_safe(),\n *  but this is no longer the case. They are now slower.\n *  This is because LZ4_decompress_fast() doesn't know the input size,\n *  and therefore must progress more cautiously into the input buffer to not read beyond the end of block.\n *  On top of that `LZ4_decompress_fast()` is not protected vs malformed or malicious inputs, making it a security liability.\n *  As a consequence, LZ4_decompress_fast() is strongly discouraged, and deprecated.\n *\n *  The last remaining LZ4_decompress_fast() specificity is that\n *  it can decompress a block without knowing its compressed size.\n *  Such functionality can be achieved in a more secure manner\n *  by employing LZ4_decompress_safe_partial().\n *\n *  Parameters:\n *  originalSize : is the uncompressed size to regenerate.\n *                 `dst` must be already allocated, its size must be >= 'originalSize' bytes.\n * @return : number of bytes read from source buffer (== compressed size).\n *           The function expects to finish at block's end exactly.\n *           If the source stream is detected malformed, the function stops decoding and returns a negative result.\n *  note : LZ4_decompress_fast*() requires originalSize. Thanks to this information, it never writes past the output buffer.\n *         However, since it doesn't know its 'src' size, it may read an unknown amount of input, past input buffer bounds.\n *         Also, since match offsets are not validated, match reads from 'src' may underflow too.\n *         These issues never happen if input (compressed) data is correct.\n *         But they may happen if input data is invalid (error or intentional tampering).\n *         As a consequence, use these functions in trusted environments with trusted data **only**.\n */\nLZ4_DEPRECATED(\"This function is deprecated and unsafe. Consider using LZ4_decompress_safe_partial() instead\")\nLZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);\nLZ4_DEPRECATED(\"This function is deprecated and unsafe. Consider migrating towards LZ4_decompress_safe_continue() instead. \"\n               \"Note that the contract will change (requires block's compressed size, instead of decompressed size)\")\nLZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);\nLZ4_DEPRECATED(\"This function is deprecated and unsafe. Consider using LZ4_decompress_safe_partial_usingDict() instead\")\nLZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);\n\n/*! LZ4_resetStream() :\n *  An LZ4_stream_t structure must be initialized at least once.\n *  This is done with LZ4_initStream(), or LZ4_resetStream().\n *  Consider switching to LZ4_initStream(),\n *  invoking LZ4_resetStream() will trigger deprecation warnings in the future.\n */\nLZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);\n\n\n#endif /* LZ4_H_98237428734687 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LZ4/lz4frame.c",
    "content": "﻿/*\n * LZ4 auto-framing library\n * Copyright (C) 2011-2016, Yann Collet.\n *\n * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * - Redistributions of source code must retain the above copyright\n *   notice, this list of conditions and the following disclaimer.\n * - Redistributions in binary form must reproduce the above\n *   copyright notice, this list of conditions and the following disclaimer\n *   in the documentation and/or other materials provided with the\n *   distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * You can contact the author at :\n * - LZ4 homepage : http://www.lz4.org\n * - LZ4 source repository : https://github.com/lz4/lz4\n */\n\n/* LZ4F is a stand-alone API to create LZ4-compressed Frames\n * in full conformance with specification v1.6.1 .\n * This library rely upon memory management capabilities (malloc, free)\n * provided either by <stdlib.h>,\n * or redirected towards another library of user's choice\n * (see Memory Routines below).\n */\n\n\n/*-************************************\n*  Compiler Options\n**************************************/\n#include <limits.h>\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)   /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/*-************************************\n*  Tuning parameters\n**************************************/\n/*\n * LZ4F_HEAPMODE :\n * Control how LZ4F_compressFrame allocates the Compression State,\n * either on stack (0:default, fastest), or in memory heap (1:requires malloc()).\n */\n#ifndef LZ4F_HEAPMODE\n#  define LZ4F_HEAPMODE 0\n#endif\n\n\n/*-************************************\n*  Library declarations\n**************************************/\n#define LZ4F_STATIC_LINKING_ONLY\n#include \"lz4frame.h\"\n#define LZ4_STATIC_LINKING_ONLY\n#include \"lz4.h\"\n#define LZ4_HC_STATIC_LINKING_ONLY\n#include \"lz4hc.h\"\n#define XXH_STATIC_LINKING_ONLY\n#include \"xxhash.h\"\n\n\n/*-************************************\n*  Memory routines\n**************************************/\n/*\n * User may redirect invocations of\n * malloc(), calloc() and free()\n * towards another library or solution of their choice\n * by modifying below section.\n**/\n\n#include <string.h>   /* memset, memcpy, memmove */\n#ifndef LZ4_SRC_INCLUDED  /* avoid redefinition when sources are coalesced */\n#  define MEM_INIT(p,v,s)   memset((p),(v),(s))\n#endif\n\n#ifndef LZ4_SRC_INCLUDED   /* avoid redefinition when sources are coalesced */\n#  include <stdlib.h>   /* malloc, calloc, free */\n#  define ALLOC(s)          malloc(s)\n#  define ALLOC_AND_ZERO(s) calloc(1,(s))\n#  define FREEMEM(p)        free(p)\n#endif\n\nstatic void* LZ4F_calloc(size_t s, LZ4F_CustomMem cmem)\n{\n    /* custom calloc defined : use it */\n    if (cmem.customCalloc != NULL) {\n        return cmem.customCalloc(cmem.opaqueState, s);\n    }\n    /* nothing defined : use default <stdlib.h>'s calloc() */\n    if (cmem.customAlloc == NULL) {\n        return ALLOC_AND_ZERO(s);\n    }\n    /* only custom alloc defined : use it, and combine it with memset() */\n    {   void* const p = cmem.customAlloc(cmem.opaqueState, s);\n        if (p != NULL) MEM_INIT(p, 0, s);\n        return p;\n}   }\n\nstatic void* LZ4F_malloc(size_t s, LZ4F_CustomMem cmem)\n{\n    /* custom malloc defined : use it */\n    if (cmem.customAlloc != NULL) {\n        return cmem.customAlloc(cmem.opaqueState, s);\n    }\n    /* nothing defined : use default <stdlib.h>'s malloc() */\n    return ALLOC(s);\n}\n\nstatic void LZ4F_free(void* p, LZ4F_CustomMem cmem)\n{\n    if (p == NULL) return;\n    if (cmem.customFree != NULL) {\n        /* custom allocation defined : use it */\n        cmem.customFree(cmem.opaqueState, p);\n        return;\n    }\n    /* nothing defined : use default <stdlib.h>'s free() */\n    FREEMEM(p);\n}\n\n\n/*-************************************\n*  Debug\n**************************************/\n#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=1)\n#  include <assert.h>\n#else\n#  ifndef assert\n#    define assert(condition) ((void)0)\n#  endif\n#endif\n\n#define LZ4F_STATIC_ASSERT(c)    { enum { LZ4F_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) && !defined(DEBUGLOG)\n#  include <stdio.h>\nstatic int g_debuglog_enable = 1;\n#  define DEBUGLOG(l, ...) {                                  \\\n                if ((g_debuglog_enable) && (l<=LZ4_DEBUG)) {  \\\n                    fprintf(stderr, __FILE__ \" (%i): \", __LINE__ );  \\\n                    fprintf(stderr, __VA_ARGS__);             \\\n                    fprintf(stderr, \" \\n\");                   \\\n            }   }\n#else\n#  define DEBUGLOG(l, ...)      {}    /* disabled */\n#endif\n\n\n/*-************************************\n*  Basic Types\n**************************************/\n#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# include <stdint.h>\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n#endif\n\n\n/* unoptimized version; solves endianness & alignment issues */\nstatic U32 LZ4F_readLE32 (const void* src)\n{\n    const BYTE* const srcPtr = (const BYTE*)src;\n    U32 value32 = srcPtr[0];\n    value32 |= ((U32)srcPtr[1])<< 8;\n    value32 |= ((U32)srcPtr[2])<<16;\n    value32 |= ((U32)srcPtr[3])<<24;\n    return value32;\n}\n\nstatic void LZ4F_writeLE32 (void* dst, U32 value32)\n{\n    BYTE* const dstPtr = (BYTE*)dst;\n    dstPtr[0] = (BYTE)value32;\n    dstPtr[1] = (BYTE)(value32 >> 8);\n    dstPtr[2] = (BYTE)(value32 >> 16);\n    dstPtr[3] = (BYTE)(value32 >> 24);\n}\n\nstatic U64 LZ4F_readLE64 (const void* src)\n{\n    const BYTE* const srcPtr = (const BYTE*)src;\n    U64 value64 = srcPtr[0];\n    value64 |= ((U64)srcPtr[1]<<8);\n    value64 |= ((U64)srcPtr[2]<<16);\n    value64 |= ((U64)srcPtr[3]<<24);\n    value64 |= ((U64)srcPtr[4]<<32);\n    value64 |= ((U64)srcPtr[5]<<40);\n    value64 |= ((U64)srcPtr[6]<<48);\n    value64 |= ((U64)srcPtr[7]<<56);\n    return value64;\n}\n\nstatic void LZ4F_writeLE64 (void* dst, U64 value64)\n{\n    BYTE* const dstPtr = (BYTE*)dst;\n    dstPtr[0] = (BYTE)value64;\n    dstPtr[1] = (BYTE)(value64 >> 8);\n    dstPtr[2] = (BYTE)(value64 >> 16);\n    dstPtr[3] = (BYTE)(value64 >> 24);\n    dstPtr[4] = (BYTE)(value64 >> 32);\n    dstPtr[5] = (BYTE)(value64 >> 40);\n    dstPtr[6] = (BYTE)(value64 >> 48);\n    dstPtr[7] = (BYTE)(value64 >> 56);\n}\n\n\n/*-************************************\n*  Constants\n**************************************/\n#ifndef LZ4_SRC_INCLUDED   /* avoid double definition */\n#  define KB *(1<<10)\n#  define MB *(1<<20)\n#  define GB *(1<<30)\n#endif\n\n#define _1BIT  0x01\n#define _2BITS 0x03\n#define _3BITS 0x07\n#define _4BITS 0x0F\n#define _8BITS 0xFF\n\n#define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U\n#define LZ4F_BLOCKSIZEID_DEFAULT LZ4F_max64KB\n\nstatic const size_t minFHSize = LZ4F_HEADER_SIZE_MIN;   /*  7 */\nstatic const size_t maxFHSize = LZ4F_HEADER_SIZE_MAX;   /* 19 */\nstatic const size_t BHSize = LZ4F_BLOCK_HEADER_SIZE;  /* block header : size, and compress flag */\nstatic const size_t BFSize = LZ4F_BLOCK_CHECKSUM_SIZE;  /* block footer : checksum (optional) */\n\n\n/*-************************************\n*  Structures and local types\n**************************************/\n\ntypedef enum { LZ4B_COMPRESSED, LZ4B_UNCOMPRESSED} LZ4F_BlockCompressMode_e;\ntypedef enum { ctxNone, ctxFast, ctxHC } LZ4F_CtxType_e;\n\ntypedef struct LZ4F_cctx_s\n{\n    LZ4F_CustomMem cmem;\n    LZ4F_preferences_t prefs;\n    U32    version;\n    U32    cStage;     /* 0 : compression uninitialized ; 1 : initialized, can compress */\n    const LZ4F_CDict* cdict;\n    size_t maxBlockSize;\n    size_t maxBufferSize;\n    BYTE*  tmpBuff;    /* internal buffer, for streaming */\n    BYTE*  tmpIn;      /* starting position of data compress within internal buffer (>= tmpBuff) */\n    size_t tmpInSize;  /* amount of data to compress after tmpIn */\n    U64    totalInSize;\n    XXH32_state_t xxh;\n    void*  lz4CtxPtr;\n    U16    lz4CtxAlloc; /* sized for: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */\n    U16    lz4CtxType;  /* in use as: 0 = none, 1 = lz4 ctx, 2 = lz4hc ctx */\n    LZ4F_BlockCompressMode_e  blockCompressMode;\n} LZ4F_cctx_t;\n\n\n/*-************************************\n*  Error management\n**************************************/\n#define LZ4F_GENERATE_STRING(STRING) #STRING,\nstatic const char* LZ4F_errorStrings[] = { LZ4F_LIST_ERRORS(LZ4F_GENERATE_STRING) };\n\n\nunsigned LZ4F_isError(LZ4F_errorCode_t code)\n{\n    return (code > (LZ4F_errorCode_t)(-LZ4F_ERROR_maxCode));\n}\n\nconst char* LZ4F_getErrorName(LZ4F_errorCode_t code)\n{\n    static const char* codeError = \"Unspecified error code\";\n    if (LZ4F_isError(code)) return LZ4F_errorStrings[-(int)(code)];\n    return codeError;\n}\n\nLZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult)\n{\n    if (!LZ4F_isError(functionResult)) return LZ4F_OK_NoError;\n    return (LZ4F_errorCodes)(-(ptrdiff_t)functionResult);\n}\n\nstatic LZ4F_errorCode_t LZ4F_returnErrorCode(LZ4F_errorCodes code)\n{\n    /* A compilation error here means sizeof(ptrdiff_t) is not large enough */\n    LZ4F_STATIC_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t));\n    return (LZ4F_errorCode_t)-(ptrdiff_t)code;\n}\n\n#define RETURN_ERROR(e) return LZ4F_returnErrorCode(LZ4F_ERROR_ ## e)\n\n#define RETURN_ERROR_IF(c,e) do {  \\\n        if (c) {                   \\\n            DEBUGLOG(3, \"Error: \" #c); \\\n            RETURN_ERROR(e);       \\\n        }                          \\\n    } while (0)\n\n#define FORWARD_IF_ERROR(r) do { if (LZ4F_isError(r)) return (r); } while (0)\n\nunsigned LZ4F_getVersion(void) { return LZ4F_VERSION; }\n\nint LZ4F_compressionLevel_max(void) { return LZ4HC_CLEVEL_MAX; }\n\nsize_t LZ4F_getBlockSize(LZ4F_blockSizeID_t blockSizeID)\n{\n    static const size_t blockSizes[4] = { 64 KB, 256 KB, 1 MB, 4 MB };\n\n    if (blockSizeID == 0) blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;\n    if (blockSizeID < LZ4F_max64KB || blockSizeID > LZ4F_max4MB)\n        RETURN_ERROR(maxBlockSize_invalid);\n    {   int const blockSizeIdx = (int)blockSizeID - (int)LZ4F_max64KB;\n        return blockSizes[blockSizeIdx];\n}   }\n\n/*-************************************\n*  Private functions\n**************************************/\n#define MIN(a,b)   ( (a) < (b) ? (a) : (b) )\n\nstatic BYTE LZ4F_headerChecksum (const void* header, size_t length)\n{\n    U32 const xxh = XXH32(header, length, 0);\n    return (BYTE)(xxh >> 8);\n}\n\n\n/*-************************************\n*  Simple-pass compression functions\n**************************************/\nstatic LZ4F_blockSizeID_t LZ4F_optimalBSID(const LZ4F_blockSizeID_t requestedBSID,\n                                           const size_t srcSize)\n{\n    LZ4F_blockSizeID_t proposedBSID = LZ4F_max64KB;\n    size_t maxBlockSize = 64 KB;\n    while (requestedBSID > proposedBSID) {\n        if (srcSize <= maxBlockSize)\n            return proposedBSID;\n        proposedBSID = (LZ4F_blockSizeID_t)((int)proposedBSID + 1);\n        maxBlockSize <<= 2;\n    }\n    return requestedBSID;\n}\n\n/*! LZ4F_compressBound_internal() :\n *  Provides dstCapacity given a srcSize to guarantee operation success in worst case situations.\n *  prefsPtr is optional : if NULL is provided, preferences will be set to cover worst case scenario.\n * @return is always the same for a srcSize and prefsPtr, so it can be relied upon to size reusable buffers.\n *  When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() operations.\n */\nstatic size_t LZ4F_compressBound_internal(size_t srcSize,\n                                    const LZ4F_preferences_t* preferencesPtr,\n                                          size_t alreadyBuffered)\n{\n    LZ4F_preferences_t prefsNull = LZ4F_INIT_PREFERENCES;\n    prefsNull.frameInfo.contentChecksumFlag = LZ4F_contentChecksumEnabled;   /* worst case */\n    prefsNull.frameInfo.blockChecksumFlag = LZ4F_blockChecksumEnabled;   /* worst case */\n    {   const LZ4F_preferences_t* const prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;\n        U32 const flush = prefsPtr->autoFlush | (srcSize==0);\n        LZ4F_blockSizeID_t const blockID = prefsPtr->frameInfo.blockSizeID;\n        size_t const blockSize = LZ4F_getBlockSize(blockID);\n        size_t const maxBuffered = blockSize - 1;\n        size_t const bufferedSize = MIN(alreadyBuffered, maxBuffered);\n        size_t const maxSrcSize = srcSize + bufferedSize;\n        unsigned const nbFullBlocks = (unsigned)(maxSrcSize / blockSize);\n        size_t const partialBlockSize = maxSrcSize & (blockSize-1);\n        size_t const lastBlockSize = flush ? partialBlockSize : 0;\n        unsigned const nbBlocks = nbFullBlocks + (lastBlockSize>0);\n\n        size_t const blockCRCSize = BFSize * prefsPtr->frameInfo.blockChecksumFlag;\n        size_t const frameEnd = BHSize + (prefsPtr->frameInfo.contentChecksumFlag*BFSize);\n\n        return ((BHSize + blockCRCSize) * nbBlocks) +\n               (blockSize * nbFullBlocks) + lastBlockSize + frameEnd;\n    }\n}\n\nsize_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)\n{\n    LZ4F_preferences_t prefs;\n    size_t const headerSize = maxFHSize;      /* max header size, including optional fields */\n\n    if (preferencesPtr!=NULL) prefs = *preferencesPtr;\n    else MEM_INIT(&prefs, 0, sizeof(prefs));\n    prefs.autoFlush = 1;\n\n    return headerSize + LZ4F_compressBound_internal(srcSize, &prefs, 0);;\n}\n\n\n/*! LZ4F_compressFrame_usingCDict() :\n *  Compress srcBuffer using a dictionary, in a single step.\n *  cdict can be NULL, in which case, no dictionary is used.\n *  dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).\n *  The LZ4F_preferences_t structure is optional : you may provide NULL as argument,\n *  however, it's the only way to provide a dictID, so it's not recommended.\n * @return : number of bytes written into dstBuffer,\n *           or an error code if it fails (can be tested using LZ4F_isError())\n */\nsize_t LZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx,\n                                     void* dstBuffer, size_t dstCapacity,\n                               const void* srcBuffer, size_t srcSize,\n                               const LZ4F_CDict* cdict,\n                               const LZ4F_preferences_t* preferencesPtr)\n{\n    LZ4F_preferences_t prefs;\n    LZ4F_compressOptions_t options;\n    BYTE* const dstStart = (BYTE*) dstBuffer;\n    BYTE* dstPtr = dstStart;\n    BYTE* const dstEnd = dstStart + dstCapacity;\n\n    DEBUGLOG(4, \"LZ4F_compressFrame_usingCDict (srcSize=%u)\", (unsigned)srcSize);\n    if (preferencesPtr!=NULL)\n        prefs = *preferencesPtr;\n    else\n        MEM_INIT(&prefs, 0, sizeof(prefs));\n    if (prefs.frameInfo.contentSize != 0)\n        prefs.frameInfo.contentSize = (U64)srcSize;   /* auto-correct content size if selected (!=0) */\n\n    prefs.frameInfo.blockSizeID = LZ4F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);\n    prefs.autoFlush = 1;\n    if (srcSize <= LZ4F_getBlockSize(prefs.frameInfo.blockSizeID))\n        prefs.frameInfo.blockMode = LZ4F_blockIndependent;   /* only one block => no need for inter-block link */\n\n    MEM_INIT(&options, 0, sizeof(options));\n    options.stableSrc = 1;\n\n    RETURN_ERROR_IF(dstCapacity < LZ4F_compressFrameBound(srcSize, &prefs), dstMaxSize_tooSmall);\n\n    { size_t const headerSize = LZ4F_compressBegin_usingCDict(cctx, dstBuffer, dstCapacity, cdict, &prefs);  /* write header */\n      FORWARD_IF_ERROR(headerSize);\n      dstPtr += headerSize;   /* header size */ }\n\n    assert(dstEnd >= dstPtr);\n    { size_t const cSize = LZ4F_compressUpdate(cctx, dstPtr, (size_t)(dstEnd-dstPtr), srcBuffer, srcSize, &options);\n      FORWARD_IF_ERROR(cSize);\n      dstPtr += cSize; }\n\n    assert(dstEnd >= dstPtr);\n    { size_t const tailSize = LZ4F_compressEnd(cctx, dstPtr, (size_t)(dstEnd-dstPtr), &options);   /* flush last block, and generate suffix */\n      FORWARD_IF_ERROR(tailSize);\n      dstPtr += tailSize; }\n\n    assert(dstEnd >= dstStart);\n    return (size_t)(dstPtr - dstStart);\n}\n\n\n/*! LZ4F_compressFrame() :\n *  Compress an entire srcBuffer into a valid LZ4 frame, in a single step.\n *  dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).\n *  The LZ4F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.\n * @return : number of bytes written into dstBuffer.\n *           or an error code if it fails (can be tested using LZ4F_isError())\n */\nsize_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity,\n                    const void* srcBuffer, size_t srcSize,\n                    const LZ4F_preferences_t* preferencesPtr)\n{\n    size_t result;\n#if (LZ4F_HEAPMODE)\n    LZ4F_cctx_t* cctxPtr;\n    result = LZ4F_createCompressionContext(&cctxPtr, LZ4F_VERSION);\n    FORWARD_IF_ERROR(result);\n#else\n    LZ4F_cctx_t cctx;\n    LZ4_stream_t lz4ctx;\n    LZ4F_cctx_t* const cctxPtr = &cctx;\n\n    MEM_INIT(&cctx, 0, sizeof(cctx));\n    cctx.version = LZ4F_VERSION;\n    cctx.maxBufferSize = 5 MB;   /* mess with real buffer size to prevent dynamic allocation; works only because autoflush==1 & stableSrc==1 */\n    if ( preferencesPtr == NULL\n      || preferencesPtr->compressionLevel < LZ4HC_CLEVEL_MIN ) {\n        LZ4_initStream(&lz4ctx, sizeof(lz4ctx));\n        cctxPtr->lz4CtxPtr = &lz4ctx;\n        cctxPtr->lz4CtxAlloc = 1;\n        cctxPtr->lz4CtxType = ctxFast;\n    }\n#endif\n    DEBUGLOG(4, \"LZ4F_compressFrame\");\n\n    result = LZ4F_compressFrame_usingCDict(cctxPtr, dstBuffer, dstCapacity,\n                                           srcBuffer, srcSize,\n                                           NULL, preferencesPtr);\n\n#if (LZ4F_HEAPMODE)\n    LZ4F_freeCompressionContext(cctxPtr);\n#else\n    if ( preferencesPtr != NULL\n      && preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN ) {\n        LZ4F_free(cctxPtr->lz4CtxPtr, cctxPtr->cmem);\n    }\n#endif\n    return result;\n}\n\n\n/*-***************************************************\n*   Dictionary compression\n*****************************************************/\n\nstruct LZ4F_CDict_s {\n    LZ4F_CustomMem cmem;\n    void* dictContent;\n    LZ4_stream_t* fastCtx;\n    LZ4_streamHC_t* HCCtx;\n}; /* typedef'd to LZ4F_CDict within lz4frame_static.h */\n\nLZ4F_CDict*\nLZ4F_createCDict_advanced(LZ4F_CustomMem cmem, const void* dictBuffer, size_t dictSize)\n{\n    const char* dictStart = (const char*)dictBuffer;\n    LZ4F_CDict* const cdict = (LZ4F_CDict*)LZ4F_malloc(sizeof(*cdict), cmem);\n    DEBUGLOG(4, \"LZ4F_createCDict_advanced\");\n    if (!cdict) return NULL;\n    cdict->cmem = cmem;\n    if (dictSize > 64 KB) {\n        dictStart += dictSize - 64 KB;\n        dictSize = 64 KB;\n    }\n    cdict->dictContent = LZ4F_malloc(dictSize, cmem);\n    /* note: using @cmem to allocate => can't use default create */\n    cdict->fastCtx = (LZ4_stream_t*)LZ4F_malloc(sizeof(LZ4_stream_t), cmem);\n    cdict->HCCtx = (LZ4_streamHC_t*)LZ4F_malloc(sizeof(LZ4_streamHC_t), cmem);\n    if (!cdict->dictContent || !cdict->fastCtx || !cdict->HCCtx) {\n        LZ4F_freeCDict(cdict);\n        return NULL;\n    }\n    memcpy(cdict->dictContent, dictStart, dictSize);\n    LZ4_initStream(cdict->fastCtx, sizeof(LZ4_stream_t));\n    LZ4_loadDictSlow(cdict->fastCtx, (const char*)cdict->dictContent, (int)dictSize);\n    LZ4_initStreamHC(cdict->HCCtx, sizeof(LZ4_streamHC_t));\n    /* note: we don't know at this point which compression level is going to be used\n     * as a consequence, HCCtx is created for the more common HC mode */\n    LZ4_setCompressionLevel(cdict->HCCtx, LZ4HC_CLEVEL_DEFAULT);\n    LZ4_loadDictHC(cdict->HCCtx, (const char*)cdict->dictContent, (int)dictSize);\n    return cdict;\n}\n\n/*! LZ4F_createCDict() :\n *  When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.\n *  LZ4F_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.\n *  LZ4F_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.\n * @dictBuffer can be released after LZ4F_CDict creation, since its content is copied within CDict\n * @return : digested dictionary for compression, or NULL if failed */\nLZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize)\n{\n    DEBUGLOG(4, \"LZ4F_createCDict\");\n    return LZ4F_createCDict_advanced(LZ4F_defaultCMem, dictBuffer, dictSize);\n}\n\nvoid LZ4F_freeCDict(LZ4F_CDict* cdict)\n{\n    if (cdict==NULL) return;  /* support free on NULL */\n    LZ4F_free(cdict->dictContent, cdict->cmem);\n    LZ4F_free(cdict->fastCtx, cdict->cmem);\n    LZ4F_free(cdict->HCCtx, cdict->cmem);\n    LZ4F_free(cdict, cdict->cmem);\n}\n\n\n/*-*********************************\n*  Advanced compression functions\n***********************************/\n\nLZ4F_cctx*\nLZ4F_createCompressionContext_advanced(LZ4F_CustomMem customMem, unsigned version)\n{\n    LZ4F_cctx* const cctxPtr =\n        (LZ4F_cctx*)LZ4F_calloc(sizeof(LZ4F_cctx), customMem);\n    if (cctxPtr==NULL) return NULL;\n\n    cctxPtr->cmem = customMem;\n    cctxPtr->version = version;\n    cctxPtr->cStage = 0;   /* Uninitialized. Next stage : init cctx */\n\n    return cctxPtr;\n}\n\n/*! LZ4F_createCompressionContext() :\n *  The first thing to do is to create a compressionContext object, which will be used in all compression operations.\n *  This is achieved using LZ4F_createCompressionContext(), which takes as argument a version and an LZ4F_preferences_t structure.\n *  The version provided MUST be LZ4F_VERSION. It is intended to track potential incompatible differences between different binaries.\n *  The function will provide a pointer to an allocated LZ4F_compressionContext_t object.\n *  If the result LZ4F_errorCode_t is not OK_NoError, there was an error during context creation.\n *  Object can release its memory using LZ4F_freeCompressionContext();\n**/\nLZ4F_errorCode_t\nLZ4F_createCompressionContext(LZ4F_cctx** LZ4F_compressionContextPtr, unsigned version)\n{\n    assert(LZ4F_compressionContextPtr != NULL); /* considered a violation of narrow contract */\n    /* in case it nonetheless happen in production */\n    RETURN_ERROR_IF(LZ4F_compressionContextPtr == NULL, parameter_null);\n\n    *LZ4F_compressionContextPtr = LZ4F_createCompressionContext_advanced(LZ4F_defaultCMem, version);\n    RETURN_ERROR_IF(*LZ4F_compressionContextPtr==NULL, allocation_failed);\n    return LZ4F_OK_NoError;\n}\n\nLZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctxPtr)\n{\n    if (cctxPtr != NULL) {  /* support free on NULL */\n       LZ4F_free(cctxPtr->lz4CtxPtr, cctxPtr->cmem);  /* note: LZ4_streamHC_t and LZ4_stream_t are simple POD types */\n       LZ4F_free(cctxPtr->tmpBuff, cctxPtr->cmem);\n       LZ4F_free(cctxPtr, cctxPtr->cmem);\n    }\n    return LZ4F_OK_NoError;\n}\n\n\n/**\n * This function prepares the internal LZ4(HC) stream for a new compression,\n * resetting the context and attaching the dictionary, if there is one.\n *\n * It needs to be called at the beginning of each independent compression\n * stream (i.e., at the beginning of a frame in blockLinked mode, or at the\n * beginning of each block in blockIndependent mode).\n */\nstatic void LZ4F_initStream(void* ctx,\n                            const LZ4F_CDict* cdict,\n                            int level,\n                            LZ4F_blockMode_t blockMode) {\n    if (level < LZ4HC_CLEVEL_MIN) {\n        if (cdict || blockMode == LZ4F_blockLinked) {\n            /* In these cases, we will call LZ4_compress_fast_continue(),\n             * which needs an already reset context. Otherwise, we'll call a\n             * one-shot API. The non-continued APIs internally perform their own\n             * resets at the beginning of their calls, where they know what\n             * tableType they need the context to be in. So in that case this\n             * would be misguided / wasted work. */\n            LZ4_resetStream_fast((LZ4_stream_t*)ctx);\n            if (cdict)\n                LZ4_attach_dictionary((LZ4_stream_t*)ctx, cdict->fastCtx);\n        }\n        /* In these cases, we'll call a one-shot API.\n         * The non-continued APIs internally perform their own resets\n         * at the beginning of their calls, where they know\n         * which tableType they need the context to be in.\n         * Therefore, a reset here would be wasted work. */\n    } else {\n        LZ4_resetStreamHC_fast((LZ4_streamHC_t*)ctx, level);\n        if (cdict)\n            LZ4_attach_HC_dictionary((LZ4_streamHC_t*)ctx, cdict->HCCtx);\n    }\n}\n\nstatic int ctxTypeID_to_size(int ctxTypeID) {\n    switch(ctxTypeID) {\n    case 1:\n        return LZ4_sizeofState();\n    case 2:\n        return LZ4_sizeofStateHC();\n    default:\n        return 0;\n    }\n}\n\n/* LZ4F_compressBegin_internal()\n * Note: only accepts @cdict _or_ @dictBuffer as non NULL.\n */\nsize_t LZ4F_compressBegin_internal(LZ4F_cctx* cctx,\n                          void* dstBuffer, size_t dstCapacity,\n                          const void* dictBuffer, size_t dictSize,\n                          const LZ4F_CDict* cdict,\n                          const LZ4F_preferences_t* preferencesPtr)\n{\n    LZ4F_preferences_t const prefNull = LZ4F_INIT_PREFERENCES;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n\n    RETURN_ERROR_IF(dstCapacity < maxFHSize, dstMaxSize_tooSmall);\n    if (preferencesPtr == NULL) preferencesPtr = &prefNull;\n    cctx->prefs = *preferencesPtr;\n\n    /* cctx Management */\n    {   U16 const ctxTypeID = (cctx->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) ? 1 : 2;\n        int requiredSize = ctxTypeID_to_size(ctxTypeID);\n        int allocatedSize = ctxTypeID_to_size(cctx->lz4CtxAlloc);\n        if (allocatedSize < requiredSize) {\n            /* not enough space allocated */\n            LZ4F_free(cctx->lz4CtxPtr, cctx->cmem);\n            if (cctx->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {\n                /* must take ownership of memory allocation,\n                 * in order to respect custom allocator contract */\n                cctx->lz4CtxPtr = LZ4F_malloc(sizeof(LZ4_stream_t), cctx->cmem);\n                if (cctx->lz4CtxPtr)\n                    LZ4_initStream(cctx->lz4CtxPtr, sizeof(LZ4_stream_t));\n            } else {\n                cctx->lz4CtxPtr = LZ4F_malloc(sizeof(LZ4_streamHC_t), cctx->cmem);\n                if (cctx->lz4CtxPtr)\n                    LZ4_initStreamHC(cctx->lz4CtxPtr, sizeof(LZ4_streamHC_t));\n            }\n            RETURN_ERROR_IF(cctx->lz4CtxPtr == NULL, allocation_failed);\n            cctx->lz4CtxAlloc = ctxTypeID;\n            cctx->lz4CtxType = ctxTypeID;\n        } else if (cctx->lz4CtxType != ctxTypeID) {\n            /* otherwise, a sufficient buffer is already allocated,\n             * but we need to reset it to the correct context type */\n            if (cctx->prefs.compressionLevel < LZ4HC_CLEVEL_MIN) {\n                LZ4_initStream((LZ4_stream_t*)cctx->lz4CtxPtr, sizeof(LZ4_stream_t));\n            } else {\n                LZ4_initStreamHC((LZ4_streamHC_t*)cctx->lz4CtxPtr, sizeof(LZ4_streamHC_t));\n                LZ4_setCompressionLevel((LZ4_streamHC_t*)cctx->lz4CtxPtr, cctx->prefs.compressionLevel);\n            }\n            cctx->lz4CtxType = ctxTypeID;\n    }   }\n\n    /* Buffer Management */\n    if (cctx->prefs.frameInfo.blockSizeID == 0)\n        cctx->prefs.frameInfo.blockSizeID = LZ4F_BLOCKSIZEID_DEFAULT;\n    cctx->maxBlockSize = LZ4F_getBlockSize(cctx->prefs.frameInfo.blockSizeID);\n\n    {   size_t const requiredBuffSize = preferencesPtr->autoFlush ?\n                ((cctx->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 64 KB : 0) :  /* only needs past data up to window size */\n                cctx->maxBlockSize + ((cctx->prefs.frameInfo.blockMode == LZ4F_blockLinked) ? 128 KB : 0);\n\n        if (cctx->maxBufferSize < requiredBuffSize) {\n            cctx->maxBufferSize = 0;\n            LZ4F_free(cctx->tmpBuff, cctx->cmem);\n            cctx->tmpBuff = (BYTE*)LZ4F_malloc(requiredBuffSize, cctx->cmem);\n            RETURN_ERROR_IF(cctx->tmpBuff == NULL, allocation_failed);\n            cctx->maxBufferSize = requiredBuffSize;\n    }   }\n    cctx->tmpIn = cctx->tmpBuff;\n    cctx->tmpInSize = 0;\n    (void)XXH32_reset(&(cctx->xxh), 0);\n\n    /* context init */\n    cctx->cdict = cdict;\n    if (cctx->prefs.frameInfo.blockMode == LZ4F_blockLinked) {\n        /* frame init only for blockLinked : blockIndependent will be init at each block */\n        LZ4F_initStream(cctx->lz4CtxPtr, cdict, cctx->prefs.compressionLevel, LZ4F_blockLinked);\n    }\n    if (preferencesPtr->compressionLevel >= LZ4HC_CLEVEL_MIN) {\n        LZ4_favorDecompressionSpeed((LZ4_streamHC_t*)cctx->lz4CtxPtr, (int)preferencesPtr->favorDecSpeed);\n    }\n    if (dictBuffer) {\n        assert(cdict == NULL);\n        RETURN_ERROR_IF(dictSize > INT_MAX, parameter_invalid);\n        if (cctx->lz4CtxType == ctxFast) {\n            /* lz4 fast*/\n            LZ4_loadDict((LZ4_stream_t*)cctx->lz4CtxPtr, (const char*)dictBuffer, (int)dictSize);\n        } else {\n            /* lz4hc */\n            assert(cctx->lz4CtxType == ctxHC);\n            LZ4_loadDictHC((LZ4_streamHC_t*)cctx->lz4CtxPtr, (const char*)dictBuffer, (int)dictSize);\n        }\n    }\n\n    /* Stage 2 : Write Frame Header */\n\n    /* Magic Number */\n    LZ4F_writeLE32(dstPtr, LZ4F_MAGICNUMBER);\n    dstPtr += 4;\n    {   BYTE* const headerStart = dstPtr;\n\n        /* FLG Byte */\n        *dstPtr++ = (BYTE)(((1 & _2BITS) << 6)    /* Version('01') */\n            + ((cctx->prefs.frameInfo.blockMode & _1BIT ) << 5)\n            + ((cctx->prefs.frameInfo.blockChecksumFlag & _1BIT ) << 4)\n            + ((unsigned)(cctx->prefs.frameInfo.contentSize > 0) << 3)\n            + ((cctx->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2)\n            +  (cctx->prefs.frameInfo.dictID > 0) );\n        /* BD Byte */\n        *dstPtr++ = (BYTE)((cctx->prefs.frameInfo.blockSizeID & _3BITS) << 4);\n        /* Optional Frame content size field */\n        if (cctx->prefs.frameInfo.contentSize) {\n            LZ4F_writeLE64(dstPtr, cctx->prefs.frameInfo.contentSize);\n            dstPtr += 8;\n            cctx->totalInSize = 0;\n        }\n        /* Optional dictionary ID field */\n        if (cctx->prefs.frameInfo.dictID) {\n            LZ4F_writeLE32(dstPtr, cctx->prefs.frameInfo.dictID);\n            dstPtr += 4;\n        }\n        /* Header CRC Byte */\n        *dstPtr = LZ4F_headerChecksum(headerStart, (size_t)(dstPtr - headerStart));\n        dstPtr++;\n    }\n\n    cctx->cStage = 1;   /* header written, now request input data block */\n    return (size_t)(dstPtr - dstStart);\n}\n\nsize_t LZ4F_compressBegin(LZ4F_cctx* cctx,\n                          void* dstBuffer, size_t dstCapacity,\n                          const LZ4F_preferences_t* preferencesPtr)\n{\n    return LZ4F_compressBegin_internal(cctx, dstBuffer, dstCapacity,\n                                        NULL, 0,\n                                        NULL, preferencesPtr);\n}\n\n/* LZ4F_compressBegin_usingDictOnce:\n * Hidden implementation,\n * employed for multi-threaded compression\n * when frame defines linked blocks */\nsize_t LZ4F_compressBegin_usingDictOnce(LZ4F_cctx* cctx,\n                          void* dstBuffer, size_t dstCapacity,\n                          const void* dict, size_t dictSize,\n                          const LZ4F_preferences_t* preferencesPtr)\n{\n    return LZ4F_compressBegin_internal(cctx, dstBuffer, dstCapacity,\n                                        dict, dictSize,\n                                        NULL, preferencesPtr);\n}\n\nsize_t LZ4F_compressBegin_usingDict(LZ4F_cctx* cctx,\n                          void* dstBuffer, size_t dstCapacity,\n                          const void* dict, size_t dictSize,\n                          const LZ4F_preferences_t* preferencesPtr)\n{\n    /* note : incorrect implementation :\n     * this will only use the dictionary once,\n     * instead of once *per* block when frames defines independent blocks */\n    return LZ4F_compressBegin_usingDictOnce(cctx, dstBuffer, dstCapacity,\n                                        dict, dictSize,\n                                        preferencesPtr);\n}\n\nsize_t LZ4F_compressBegin_usingCDict(LZ4F_cctx* cctx,\n                          void* dstBuffer, size_t dstCapacity,\n                          const LZ4F_CDict* cdict,\n                          const LZ4F_preferences_t* preferencesPtr)\n{\n    return LZ4F_compressBegin_internal(cctx, dstBuffer, dstCapacity,\n                                        NULL, 0,\n                                       cdict, preferencesPtr);\n}\n\n\n/*  LZ4F_compressBound() :\n * @return minimum capacity of dstBuffer for a given srcSize to handle worst case scenario.\n *  LZ4F_preferences_t structure is optional : if NULL, preferences will be set to cover worst case scenario.\n *  This function cannot fail.\n */\nsize_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr)\n{\n    if (preferencesPtr && preferencesPtr->autoFlush) {\n        return LZ4F_compressBound_internal(srcSize, preferencesPtr, 0);\n    }\n    return LZ4F_compressBound_internal(srcSize, preferencesPtr, (size_t)-1);\n}\n\n\ntypedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level, const LZ4F_CDict* cdict);\n\n\n/*! LZ4F_makeBlock():\n *  compress a single block, add header and optional checksum.\n *  assumption : dst buffer capacity is >= BHSize + srcSize + crcSize\n */\nstatic size_t LZ4F_makeBlock(void* dst,\n                       const void* src, size_t srcSize,\n                             compressFunc_t compress, void* lz4ctx, int level,\n                       const LZ4F_CDict* cdict,\n                             LZ4F_blockChecksum_t crcFlag)\n{\n    BYTE* const cSizePtr = (BYTE*)dst;\n    U32 cSize;\n    assert(compress != NULL);\n    cSize = (U32)compress(lz4ctx, (const char*)src, (char*)(cSizePtr+BHSize),\n                          (int)(srcSize), (int)(srcSize-1),\n                          level, cdict);\n\n    if (cSize == 0 || cSize >= srcSize) {\n        cSize = (U32)srcSize;\n        LZ4F_writeLE32(cSizePtr, cSize | LZ4F_BLOCKUNCOMPRESSED_FLAG);\n        memcpy(cSizePtr+BHSize, src, srcSize);\n    } else {\n        LZ4F_writeLE32(cSizePtr, cSize);\n    }\n    if (crcFlag) {\n        U32 const crc32 = XXH32(cSizePtr+BHSize, cSize, 0);  /* checksum of compressed data */\n        LZ4F_writeLE32(cSizePtr+BHSize+cSize, crc32);\n    }\n    return BHSize + cSize + ((U32)crcFlag)*BFSize;\n}\n\n\nstatic int LZ4F_compressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)\n{\n    int const acceleration = (level < 0) ? -level + 1 : 1;\n    DEBUGLOG(5, \"LZ4F_compressBlock (srcSize=%i)\", srcSize);\n    LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);\n    if (cdict) {\n        return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);\n    } else {\n        return LZ4_compress_fast_extState_fastReset(ctx, src, dst, srcSize, dstCapacity, acceleration);\n    }\n}\n\nstatic int LZ4F_compressBlock_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)\n{\n    int const acceleration = (level < 0) ? -level + 1 : 1;\n    (void)cdict; /* init once at beginning of frame */\n    DEBUGLOG(5, \"LZ4F_compressBlock_continue (srcSize=%i)\", srcSize);\n    return LZ4_compress_fast_continue((LZ4_stream_t*)ctx, src, dst, srcSize, dstCapacity, acceleration);\n}\n\nstatic int LZ4F_compressBlockHC(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)\n{\n    LZ4F_initStream(ctx, cdict, level, LZ4F_blockIndependent);\n    if (cdict) {\n        return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);\n    }\n    return LZ4_compress_HC_extStateHC_fastReset(ctx, src, dst, srcSize, dstCapacity, level);\n}\n\nstatic int LZ4F_compressBlockHC_continue(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)\n{\n    (void)level; (void)cdict; /* init once at beginning of frame */\n    return LZ4_compress_HC_continue((LZ4_streamHC_t*)ctx, src, dst, srcSize, dstCapacity);\n}\n\nstatic int LZ4F_doNotCompressBlock(void* ctx, const char* src, char* dst, int srcSize, int dstCapacity, int level, const LZ4F_CDict* cdict)\n{\n    (void)ctx; (void)src; (void)dst; (void)srcSize; (void)dstCapacity; (void)level; (void)cdict;\n    return 0;\n}\n\nstatic compressFunc_t LZ4F_selectCompression(LZ4F_blockMode_t blockMode, int level, LZ4F_BlockCompressMode_e  compressMode)\n{\n    if (compressMode == LZ4B_UNCOMPRESSED)\n        return LZ4F_doNotCompressBlock;\n    if (level < LZ4HC_CLEVEL_MIN) {\n        if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlock;\n        return LZ4F_compressBlock_continue;\n    }\n    if (blockMode == LZ4F_blockIndependent) return LZ4F_compressBlockHC;\n    return LZ4F_compressBlockHC_continue;\n}\n\n/* Save history (up to 64KB) into @tmpBuff */\nstatic int LZ4F_localSaveDict(LZ4F_cctx_t* cctxPtr)\n{\n    if (cctxPtr->prefs.compressionLevel < LZ4HC_CLEVEL_MIN)\n        return LZ4_saveDict ((LZ4_stream_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);\n    return LZ4_saveDictHC ((LZ4_streamHC_t*)(cctxPtr->lz4CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);\n}\n\ntypedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ4F_lastBlockStatus;\n\nstatic const LZ4F_compressOptions_t k_cOptionsNull = { 0, { 0, 0, 0 } };\n\n\n /*! LZ4F_compressUpdateImpl() :\n *  LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.\n *  When successful, the function always entirely consumes @srcBuffer.\n *  src data is either buffered or compressed into @dstBuffer.\n *  If the block compression does not match the compression of the previous block, the old data is flushed\n *  and operations continue with the new compression mode.\n * @dstCapacity MUST be >= LZ4F_compressBound(srcSize, preferencesPtr) when block compression is turned on.\n * @compressOptionsPtr is optional : provide NULL to mean \"default\".\n * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered.\n *           or an error code if it fails (which can be tested using LZ4F_isError())\n *  After an error, the state is left in a UB state, and must be re-initialized.\n */\nstatic size_t LZ4F_compressUpdateImpl(LZ4F_cctx* cctxPtr,\n                     void* dstBuffer, size_t dstCapacity,\n                     const void* srcBuffer, size_t srcSize,\n                     const LZ4F_compressOptions_t* compressOptionsPtr,\n                     LZ4F_BlockCompressMode_e blockCompression)\n  {\n    size_t const blockSize = cctxPtr->maxBlockSize;\n    const BYTE* srcPtr = (const BYTE*)srcBuffer;\n    const BYTE* const srcEnd = srcPtr + srcSize;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    LZ4F_lastBlockStatus lastBlockCompressed = notDone;\n    compressFunc_t const compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel, blockCompression);\n    size_t bytesWritten;\n    DEBUGLOG(4, \"LZ4F_compressUpdate (srcSize=%zu)\", srcSize);\n\n    RETURN_ERROR_IF(cctxPtr->cStage != 1, compressionState_uninitialized);   /* state must be initialized and waiting for next block */\n    if (dstCapacity < LZ4F_compressBound_internal(srcSize, &(cctxPtr->prefs), cctxPtr->tmpInSize))\n        RETURN_ERROR(dstMaxSize_tooSmall);\n\n    if (blockCompression == LZ4B_UNCOMPRESSED && dstCapacity < srcSize)\n        RETURN_ERROR(dstMaxSize_tooSmall);\n\n    /* flush currently written block, to continue with new block compression */\n    if (cctxPtr->blockCompressMode != blockCompression) {\n        bytesWritten = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);\n        dstPtr += bytesWritten;\n        cctxPtr->blockCompressMode = blockCompression;\n    }\n\n    if (compressOptionsPtr == NULL) compressOptionsPtr = &k_cOptionsNull;\n\n    /* complete tmp buffer */\n    if (cctxPtr->tmpInSize > 0) {   /* some data already within tmp buffer */\n        size_t const sizeToCopy = blockSize - cctxPtr->tmpInSize;\n        assert(blockSize > cctxPtr->tmpInSize);\n        if (sizeToCopy > srcSize) {\n            /* add src to tmpIn buffer */\n            memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);\n            srcPtr = srcEnd;\n            cctxPtr->tmpInSize += srcSize;\n            /* still needs some CRC */\n        } else {\n            /* complete tmpIn block and then compress it */\n            lastBlockCompressed = fromTmpBuffer;\n            memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);\n            srcPtr += sizeToCopy;\n\n            dstPtr += LZ4F_makeBlock(dstPtr,\n                                     cctxPtr->tmpIn, blockSize,\n                                     compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,\n                                     cctxPtr->cdict,\n                                     cctxPtr->prefs.frameInfo.blockChecksumFlag);\n            if (cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) cctxPtr->tmpIn += blockSize;\n            cctxPtr->tmpInSize = 0;\n    }   }\n\n    while ((size_t)(srcEnd - srcPtr) >= blockSize) {\n        /* compress full blocks */\n        lastBlockCompressed = fromSrcBuffer;\n        dstPtr += LZ4F_makeBlock(dstPtr,\n                                 srcPtr, blockSize,\n                                 compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,\n                                 cctxPtr->cdict,\n                                 cctxPtr->prefs.frameInfo.blockChecksumFlag);\n        srcPtr += blockSize;\n    }\n\n    if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {\n        /* autoFlush : remaining input (< blockSize) is compressed */\n        lastBlockCompressed = fromSrcBuffer;\n        dstPtr += LZ4F_makeBlock(dstPtr,\n                                 srcPtr, (size_t)(srcEnd - srcPtr),\n                                 compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,\n                                 cctxPtr->cdict,\n                                 cctxPtr->prefs.frameInfo.blockChecksumFlag);\n        srcPtr = srcEnd;\n    }\n\n    /* preserve dictionary within @tmpBuff whenever necessary */\n    if ((cctxPtr->prefs.frameInfo.blockMode==LZ4F_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) {\n        /* linked blocks are only supported in compressed mode, see LZ4F_uncompressedUpdate */\n        assert(blockCompression == LZ4B_COMPRESSED);\n        if (compressOptionsPtr->stableSrc) {\n            cctxPtr->tmpIn = cctxPtr->tmpBuff;  /* src is stable : dictionary remains in src across invocations */\n        } else {\n            int const realDictSize = LZ4F_localSaveDict(cctxPtr);\n            assert(0 <= realDictSize && realDictSize <= 64 KB);\n            cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n        }\n    }\n\n    /* keep tmpIn within limits */\n    if (!(cctxPtr->prefs.autoFlush)  /* no autoflush : there may be some data left within internal buffer */\n      && (cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize) )  /* not enough room to store next block */\n    {\n        /* only preserve 64KB within internal buffer. Ensures there is enough room for next block.\n         * note: this situation necessarily implies lastBlockCompressed==fromTmpBuffer */\n        int const realDictSize = LZ4F_localSaveDict(cctxPtr);\n        cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n        assert((cctxPtr->tmpIn + blockSize) <= (cctxPtr->tmpBuff + cctxPtr->maxBufferSize));\n    }\n\n    /* some input data left, necessarily < blockSize */\n    if (srcPtr < srcEnd) {\n        /* fill tmp buffer */\n        size_t const sizeToCopy = (size_t)(srcEnd - srcPtr);\n        memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);\n        cctxPtr->tmpInSize = sizeToCopy;\n    }\n\n    if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled)\n        (void)XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);\n\n    cctxPtr->totalInSize += srcSize;\n    return (size_t)(dstPtr - dstStart);\n}\n\n/*! LZ4F_compressUpdate() :\n *  LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.\n *  When successful, the function always entirely consumes @srcBuffer.\n *  src data is either buffered or compressed into @dstBuffer.\n *  If previously an uncompressed block was written, buffered data is flushed\n *  before appending compressed data is continued.\n * @dstCapacity MUST be >= LZ4F_compressBound(srcSize, preferencesPtr).\n * @compressOptionsPtr is optional : provide NULL to mean \"default\".\n * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered.\n *           or an error code if it fails (which can be tested using LZ4F_isError())\n *  After an error, the state is left in a UB state, and must be re-initialized.\n */\nsize_t LZ4F_compressUpdate(LZ4F_cctx* cctxPtr,\n                           void* dstBuffer, size_t dstCapacity,\n                     const void* srcBuffer, size_t srcSize,\n                     const LZ4F_compressOptions_t* compressOptionsPtr)\n{\n     return LZ4F_compressUpdateImpl(cctxPtr,\n                                   dstBuffer, dstCapacity,\n                                   srcBuffer, srcSize,\n                                   compressOptionsPtr, LZ4B_COMPRESSED);\n}\n\n/*! LZ4F_uncompressedUpdate() :\n *  Same as LZ4F_compressUpdate(), but requests blocks to be sent uncompressed.\n *  This symbol is only supported when LZ4F_blockIndependent is used\n * @dstCapacity MUST be >= LZ4F_compressBound(srcSize, preferencesPtr).\n * @compressOptionsPtr is optional : provide NULL to mean \"default\".\n * @return : the number of bytes written into dstBuffer. It can be zero, meaning input data was just buffered.\n *           or an error code if it fails (which can be tested using LZ4F_isError())\n *  After an error, the state is left in a UB state, and must be re-initialized.\n */\nsize_t LZ4F_uncompressedUpdate(LZ4F_cctx* cctxPtr,\n                               void* dstBuffer, size_t dstCapacity,\n                         const void* srcBuffer, size_t srcSize,\n                         const LZ4F_compressOptions_t* compressOptionsPtr)\n{\n    return LZ4F_compressUpdateImpl(cctxPtr,\n                                   dstBuffer, dstCapacity,\n                                   srcBuffer, srcSize,\n                                   compressOptionsPtr, LZ4B_UNCOMPRESSED);\n}\n\n\n/*! LZ4F_flush() :\n *  When compressed data must be sent immediately, without waiting for a block to be filled,\n *  invoke LZ4_flush(), which will immediately compress any remaining data stored within LZ4F_cctx.\n *  The result of the function is the number of bytes written into dstBuffer.\n *  It can be zero, this means there was no data left within LZ4F_cctx.\n *  The function outputs an error code if it fails (can be tested using LZ4F_isError())\n *  LZ4F_compressOptions_t* is optional. NULL is a valid argument.\n */\nsize_t LZ4F_flush(LZ4F_cctx* cctxPtr,\n                  void* dstBuffer, size_t dstCapacity,\n            const LZ4F_compressOptions_t* compressOptionsPtr)\n{\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    compressFunc_t compress;\n\n    if (cctxPtr->tmpInSize == 0) return 0;   /* nothing to flush */\n    RETURN_ERROR_IF(cctxPtr->cStage != 1, compressionState_uninitialized);\n    RETURN_ERROR_IF(dstCapacity < (cctxPtr->tmpInSize + BHSize + BFSize), dstMaxSize_tooSmall);\n    (void)compressOptionsPtr;   /* not useful (yet) */\n\n    /* select compression function */\n    compress = LZ4F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel, cctxPtr->blockCompressMode);\n\n    /* compress tmp buffer */\n    dstPtr += LZ4F_makeBlock(dstPtr,\n                             cctxPtr->tmpIn, cctxPtr->tmpInSize,\n                             compress, cctxPtr->lz4CtxPtr, cctxPtr->prefs.compressionLevel,\n                             cctxPtr->cdict,\n                             cctxPtr->prefs.frameInfo.blockChecksumFlag);\n    assert(((void)\"flush overflows dstBuffer!\", (size_t)(dstPtr - dstStart) <= dstCapacity));\n\n    if (cctxPtr->prefs.frameInfo.blockMode == LZ4F_blockLinked)\n        cctxPtr->tmpIn += cctxPtr->tmpInSize;\n    cctxPtr->tmpInSize = 0;\n\n    /* keep tmpIn within limits */\n    if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) {  /* necessarily LZ4F_blockLinked */\n        int const realDictSize = LZ4F_localSaveDict(cctxPtr);\n        cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n    }\n\n    return (size_t)(dstPtr - dstStart);\n}\n\n\n/*! LZ4F_compressEnd() :\n *  When you want to properly finish the compressed frame, just call LZ4F_compressEnd().\n *  It will flush whatever data remained within compressionContext (like LZ4_flush())\n *  but also properly finalize the frame, with an endMark and an (optional) checksum.\n *  LZ4F_compressOptions_t structure is optional : you can provide NULL as argument.\n * @return: the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))\n *       or an error code if it fails (can be tested using LZ4F_isError())\n *  The context can then be used again to compress a new frame, starting with LZ4F_compressBegin().\n */\nsize_t LZ4F_compressEnd(LZ4F_cctx* cctxPtr,\n                        void* dstBuffer, size_t dstCapacity,\n                  const LZ4F_compressOptions_t* compressOptionsPtr)\n{\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n\n    size_t const flushSize = LZ4F_flush(cctxPtr, dstBuffer, dstCapacity, compressOptionsPtr);\n    DEBUGLOG(5,\"LZ4F_compressEnd: dstCapacity=%u\", (unsigned)dstCapacity);\n    FORWARD_IF_ERROR(flushSize);\n    dstPtr += flushSize;\n\n    assert(flushSize <= dstCapacity);\n    dstCapacity -= flushSize;\n\n    RETURN_ERROR_IF(dstCapacity < 4, dstMaxSize_tooSmall);\n    LZ4F_writeLE32(dstPtr, 0);\n    dstPtr += 4;   /* endMark */\n\n    if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ4F_contentChecksumEnabled) {\n        U32 const xxh = XXH32_digest(&(cctxPtr->xxh));\n        RETURN_ERROR_IF(dstCapacity < 8, dstMaxSize_tooSmall);\n        DEBUGLOG(5,\"Writing 32-bit content checksum (0x%0X)\", xxh);\n        LZ4F_writeLE32(dstPtr, xxh);\n        dstPtr+=4;   /* content Checksum */\n    }\n\n    cctxPtr->cStage = 0;   /* state is now re-usable (with identical preferences) */\n\n    if (cctxPtr->prefs.frameInfo.contentSize) {\n        if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)\n            RETURN_ERROR(frameSize_wrong);\n    }\n\n    return (size_t)(dstPtr - dstStart);\n}\n\n\n/*-***************************************************\n*   Frame Decompression\n*****************************************************/\n\ntypedef enum {\n    dstage_getFrameHeader=0, dstage_storeFrameHeader,\n    dstage_init,\n    dstage_getBlockHeader, dstage_storeBlockHeader,\n    dstage_copyDirect, dstage_getBlockChecksum,\n    dstage_getCBlock, dstage_storeCBlock,\n    dstage_flushOut,\n    dstage_getSuffix, dstage_storeSuffix,\n    dstage_getSFrameSize, dstage_storeSFrameSize,\n    dstage_skipSkippable\n} dStage_t;\n\nstruct LZ4F_dctx_s {\n    LZ4F_CustomMem cmem;\n    LZ4F_frameInfo_t frameInfo;\n    U32    version;\n    dStage_t dStage;\n    U64    frameRemainingSize;\n    size_t maxBlockSize;\n    size_t maxBufferSize;\n    BYTE*  tmpIn;\n    size_t tmpInSize;\n    size_t tmpInTarget;\n    BYTE*  tmpOutBuffer;\n    const BYTE* dict;\n    size_t dictSize;\n    BYTE*  tmpOut;\n    size_t tmpOutSize;\n    size_t tmpOutStart;\n    XXH32_state_t xxh;\n    XXH32_state_t blockChecksum;\n    int    skipChecksum;\n    BYTE   header[LZ4F_HEADER_SIZE_MAX];\n};  /* typedef'd to LZ4F_dctx in lz4frame.h */\n\n\nLZ4F_dctx* LZ4F_createDecompressionContext_advanced(LZ4F_CustomMem customMem, unsigned version)\n{\n    LZ4F_dctx* const dctx = (LZ4F_dctx*)LZ4F_calloc(sizeof(LZ4F_dctx), customMem);\n    if (dctx == NULL) return NULL;\n\n    dctx->cmem = customMem;\n    dctx->version = version;\n    return dctx;\n}\n\n/*! LZ4F_createDecompressionContext() :\n *  Create a decompressionContext object, which will track all decompression operations.\n *  Provides a pointer to a fully allocated and initialized LZ4F_decompressionContext object.\n *  Object can later be released using LZ4F_freeDecompressionContext().\n * @return : if != 0, there was an error during context creation.\n */\nLZ4F_errorCode_t\nLZ4F_createDecompressionContext(LZ4F_dctx** LZ4F_decompressionContextPtr, unsigned versionNumber)\n{\n    assert(LZ4F_decompressionContextPtr != NULL);  /* violation of narrow contract */\n    RETURN_ERROR_IF(LZ4F_decompressionContextPtr == NULL, parameter_null);  /* in case it nonetheless happen in production */\n\n    *LZ4F_decompressionContextPtr = LZ4F_createDecompressionContext_advanced(LZ4F_defaultCMem, versionNumber);\n    if (*LZ4F_decompressionContextPtr == NULL) {  /* failed allocation */\n        RETURN_ERROR(allocation_failed);\n    }\n    return LZ4F_OK_NoError;\n}\n\nLZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx)\n{\n    LZ4F_errorCode_t result = LZ4F_OK_NoError;\n    if (dctx != NULL) {   /* can accept NULL input, like free() */\n      result = (LZ4F_errorCode_t)dctx->dStage;\n      LZ4F_free(dctx->tmpIn, dctx->cmem);\n      LZ4F_free(dctx->tmpOutBuffer, dctx->cmem);\n      LZ4F_free(dctx, dctx->cmem);\n    }\n    return result;\n}\n\n\n/*==---   Streaming Decompression operations   ---==*/\nvoid LZ4F_resetDecompressionContext(LZ4F_dctx* dctx)\n{\n    DEBUGLOG(5, \"LZ4F_resetDecompressionContext\");\n    dctx->dStage = dstage_getFrameHeader;\n    dctx->dict = NULL;\n    dctx->dictSize = 0;\n    dctx->skipChecksum = 0;\n    dctx->frameRemainingSize = 0;\n}\n\n\n/*! LZ4F_decodeHeader() :\n *  input   : `src` points at the **beginning of the frame**\n *  output  : set internal values of dctx, such as\n *            dctx->frameInfo and dctx->dStage.\n *            Also allocates internal buffers.\n *  @return : nb Bytes read from src (necessarily <= srcSize)\n *            or an error code (testable with LZ4F_isError())\n */\nstatic size_t LZ4F_decodeHeader(LZ4F_dctx* dctx, const void* src, size_t srcSize)\n{\n    unsigned blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, dictIDFlag, blockSizeID;\n    size_t frameHeaderSize;\n    const BYTE* srcPtr = (const BYTE*)src;\n\n    DEBUGLOG(5, \"LZ4F_decodeHeader\");\n    /* need to decode header to get frameInfo */\n    RETURN_ERROR_IF(srcSize < minFHSize, frameHeader_incomplete);   /* minimal frame header size */\n    MEM_INIT(&(dctx->frameInfo), 0, sizeof(dctx->frameInfo));\n\n    /* special case : skippable frames */\n    if ((LZ4F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START) {\n        dctx->frameInfo.frameType = LZ4F_skippableFrame;\n        if (src == (void*)(dctx->header)) {\n            dctx->tmpInSize = srcSize;\n            dctx->tmpInTarget = 8;\n            dctx->dStage = dstage_storeSFrameSize;\n            return srcSize;\n        } else {\n            dctx->dStage = dstage_getSFrameSize;\n            return 4;\n    }   }\n\n    /* control magic number */\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    if (LZ4F_readLE32(srcPtr) != LZ4F_MAGICNUMBER) {\n        DEBUGLOG(4, \"frame header error : unknown magic number\");\n        RETURN_ERROR(frameType_unknown);\n    }\n#endif\n    dctx->frameInfo.frameType = LZ4F_frame;\n\n    /* Flags */\n    {   U32 const FLG = srcPtr[4];\n        U32 const version = (FLG>>6) & _2BITS;\n        blockChecksumFlag = (FLG>>4) & _1BIT;\n        blockMode = (FLG>>5) & _1BIT;\n        contentSizeFlag = (FLG>>3) & _1BIT;\n        contentChecksumFlag = (FLG>>2) & _1BIT;\n        dictIDFlag = FLG & _1BIT;\n        /* validate */\n        if (((FLG>>1)&_1BIT) != 0) RETURN_ERROR(reservedFlag_set); /* Reserved bit */\n        if (version != 1) RETURN_ERROR(headerVersion_wrong);       /* Version Number, only supported value */\n    }\n    DEBUGLOG(6, \"contentSizeFlag: %u\", contentSizeFlag);\n\n    /* Frame Header Size */\n    frameHeaderSize = minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);\n\n    if (srcSize < frameHeaderSize) {\n        /* not enough input to fully decode frame header */\n        if (srcPtr != dctx->header)\n            memcpy(dctx->header, srcPtr, srcSize);\n        dctx->tmpInSize = srcSize;\n        dctx->tmpInTarget = frameHeaderSize;\n        dctx->dStage = dstage_storeFrameHeader;\n        return srcSize;\n    }\n\n    {   U32 const BD = srcPtr[5];\n        blockSizeID = (BD>>4) & _3BITS;\n        /* validate */\n        if (((BD>>7)&_1BIT) != 0) RETURN_ERROR(reservedFlag_set);   /* Reserved bit */\n        if (blockSizeID < 4) RETURN_ERROR(maxBlockSize_invalid);    /* 4-7 only supported values for the time being */\n        if (((BD>>0)&_4BITS) != 0) RETURN_ERROR(reservedFlag_set);  /* Reserved bits */\n    }\n\n    /* check header */\n    assert(frameHeaderSize > 5);\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    {   BYTE const HC = LZ4F_headerChecksum(srcPtr+4, frameHeaderSize-5);\n        RETURN_ERROR_IF(HC != srcPtr[frameHeaderSize-1], headerChecksum_invalid);\n    }\n#endif\n\n    /* save */\n    dctx->frameInfo.blockMode = (LZ4F_blockMode_t)blockMode;\n    dctx->frameInfo.blockChecksumFlag = (LZ4F_blockChecksum_t)blockChecksumFlag;\n    dctx->frameInfo.contentChecksumFlag = (LZ4F_contentChecksum_t)contentChecksumFlag;\n    dctx->frameInfo.blockSizeID = (LZ4F_blockSizeID_t)blockSizeID;\n    dctx->maxBlockSize = LZ4F_getBlockSize((LZ4F_blockSizeID_t)blockSizeID);\n    if (contentSizeFlag) {\n        dctx->frameRemainingSize = dctx->frameInfo.contentSize = LZ4F_readLE64(srcPtr+6);\n    }\n    if (dictIDFlag)\n        dctx->frameInfo.dictID = LZ4F_readLE32(srcPtr + frameHeaderSize - 5);\n\n    dctx->dStage = dstage_init;\n\n    return frameHeaderSize;\n}\n\n\n/*! LZ4F_headerSize() :\n * @return : size of frame header\n *           or an error code, which can be tested using LZ4F_isError()\n */\nsize_t LZ4F_headerSize(const void* src, size_t srcSize)\n{\n    RETURN_ERROR_IF(src == NULL, srcPtr_wrong);\n\n    /* minimal srcSize to determine header size */\n    if (srcSize < LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH)\n        RETURN_ERROR(frameHeader_incomplete);\n\n    /* special case : skippable frames */\n    if ((LZ4F_readLE32(src) & 0xFFFFFFF0U) == LZ4F_MAGIC_SKIPPABLE_START)\n        return 8;\n\n    /* control magic number */\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    if (LZ4F_readLE32(src) != LZ4F_MAGICNUMBER)\n        RETURN_ERROR(frameType_unknown);\n#endif\n\n    /* Frame Header Size */\n    {   BYTE const FLG = ((const BYTE*)src)[4];\n        U32 const contentSizeFlag = (FLG>>3) & _1BIT;\n        U32 const dictIDFlag = FLG & _1BIT;\n        return minFHSize + (contentSizeFlag?8:0) + (dictIDFlag?4:0);\n    }\n}\n\n/*! LZ4F_getFrameInfo() :\n *  This function extracts frame parameters (max blockSize, frame checksum, etc.).\n *  Usage is optional. Objective is to provide relevant information for allocation purposes.\n *  This function works in 2 situations :\n *   - At the beginning of a new frame, in which case it will decode this information from `srcBuffer`, and start the decoding process.\n *     Amount of input data provided must be large enough to successfully decode the frame header.\n *     A header size is variable, but is guaranteed to be <= LZ4F_HEADER_SIZE_MAX bytes. It's possible to provide more input data than this minimum.\n *   - After decoding has been started. In which case, no input is read, frame parameters are extracted from dctx.\n *  The number of bytes consumed from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).\n *  Decompression must resume from (srcBuffer + *srcSizePtr).\n * @return : an hint about how many srcSize bytes LZ4F_decompress() expects for next call,\n *           or an error code which can be tested using LZ4F_isError()\n *  note 1 : in case of error, dctx is not modified. Decoding operations can resume from where they stopped.\n *  note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure.\n */\nLZ4F_errorCode_t LZ4F_getFrameInfo(LZ4F_dctx* dctx,\n                                   LZ4F_frameInfo_t* frameInfoPtr,\n                             const void* srcBuffer, size_t* srcSizePtr)\n{\n    LZ4F_STATIC_ASSERT(dstage_getFrameHeader < dstage_storeFrameHeader);\n    if (dctx->dStage > dstage_storeFrameHeader) {\n        /* frameInfo already decoded */\n        size_t o=0, i=0;\n        *srcSizePtr = 0;\n        *frameInfoPtr = dctx->frameInfo;\n        /* returns : recommended nb of bytes for LZ4F_decompress() */\n        return LZ4F_decompress(dctx, NULL, &o, NULL, &i, NULL);\n    } else {\n        if (dctx->dStage == dstage_storeFrameHeader) {\n            /* frame decoding already started, in the middle of header => automatic fail */\n            *srcSizePtr = 0;\n            RETURN_ERROR(frameDecoding_alreadyStarted);\n        } else {\n            size_t const hSize = LZ4F_headerSize(srcBuffer, *srcSizePtr);\n            if (LZ4F_isError(hSize)) { *srcSizePtr=0; return hSize; }\n            if (*srcSizePtr < hSize) {\n                *srcSizePtr=0;\n                RETURN_ERROR(frameHeader_incomplete);\n            }\n\n            {   size_t decodeResult = LZ4F_decodeHeader(dctx, srcBuffer, hSize);\n                if (LZ4F_isError(decodeResult)) {\n                    *srcSizePtr = 0;\n                } else {\n                    *srcSizePtr = decodeResult;\n                    decodeResult = BHSize;   /* block header size */\n                }\n                *frameInfoPtr = dctx->frameInfo;\n                return decodeResult;\n    }   }   }\n}\n\n\n/* LZ4F_updateDict() :\n * only used for LZ4F_blockLinked mode\n * Condition : @dstPtr != NULL\n */\nstatic void LZ4F_updateDict(LZ4F_dctx* dctx,\n                      const BYTE* dstPtr, size_t dstSize, const BYTE* dstBufferStart,\n                      unsigned withinTmp)\n{\n    assert(dstPtr != NULL);\n    if (dctx->dictSize==0) dctx->dict = (const BYTE*)dstPtr;  /* will lead to prefix mode */\n    assert(dctx->dict != NULL);\n\n    if (dctx->dict + dctx->dictSize == dstPtr) {  /* prefix mode, everything within dstBuffer */\n        dctx->dictSize += dstSize;\n        return;\n    }\n\n    assert(dstPtr >= dstBufferStart);\n    if ((size_t)(dstPtr - dstBufferStart) + dstSize >= 64 KB) {  /* history in dstBuffer becomes large enough to become dictionary */\n        dctx->dict = (const BYTE*)dstBufferStart;\n        dctx->dictSize = (size_t)(dstPtr - dstBufferStart) + dstSize;\n        return;\n    }\n\n    assert(dstSize < 64 KB);   /* if dstSize >= 64 KB, dictionary would be set into dstBuffer directly */\n\n    /* dstBuffer does not contain whole useful history (64 KB), so it must be saved within tmpOutBuffer */\n    assert(dctx->tmpOutBuffer != NULL);\n\n    if (withinTmp && (dctx->dict == dctx->tmpOutBuffer)) {   /* continue history within tmpOutBuffer */\n        /* withinTmp expectation : content of [dstPtr,dstSize] is same as [dict+dictSize,dstSize], so we just extend it */\n        assert(dctx->dict + dctx->dictSize == dctx->tmpOut + dctx->tmpOutStart);\n        dctx->dictSize += dstSize;\n        return;\n    }\n\n    if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */\n        size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);\n        size_t copySize = 64 KB - dctx->tmpOutSize;\n        const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;\n        if (dctx->tmpOutSize > 64 KB) copySize = 0;\n        if (copySize > preserveSize) copySize = preserveSize;\n\n        memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);\n\n        dctx->dict = dctx->tmpOutBuffer;\n        dctx->dictSize = preserveSize + dctx->tmpOutStart + dstSize;\n        return;\n    }\n\n    if (dctx->dict == dctx->tmpOutBuffer) {    /* copy dst into tmp to complete dict */\n        if (dctx->dictSize + dstSize > dctx->maxBufferSize) {  /* tmp buffer not large enough */\n            size_t const preserveSize = 64 KB - dstSize;\n            memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);\n            dctx->dictSize = preserveSize;\n        }\n        memcpy(dctx->tmpOutBuffer + dctx->dictSize, dstPtr, dstSize);\n        dctx->dictSize += dstSize;\n        return;\n    }\n\n    /* join dict & dest into tmp */\n    {   size_t preserveSize = 64 KB - dstSize;\n        if (preserveSize > dctx->dictSize) preserveSize = dctx->dictSize;\n        memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - preserveSize, preserveSize);\n        memcpy(dctx->tmpOutBuffer + preserveSize, dstPtr, dstSize);\n        dctx->dict = dctx->tmpOutBuffer;\n        dctx->dictSize = preserveSize + dstSize;\n    }\n}\n\n\n/*! LZ4F_decompress() :\n *  Call this function repetitively to regenerate compressed data in srcBuffer.\n *  The function will attempt to decode up to *srcSizePtr bytes from srcBuffer\n *  into dstBuffer of capacity *dstSizePtr.\n *\n *  The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).\n *\n *  The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).\n *  If number of bytes read is < number of bytes provided, then decompression operation is not complete.\n *  Remaining data will have to be presented again in a subsequent invocation.\n *\n *  The function result is an hint of the better srcSize to use for next call to LZ4F_decompress.\n *  Schematically, it's the size of the current (or remaining) compressed block + header of next block.\n *  Respecting the hint provides a small boost to performance, since it allows less buffer shuffling.\n *  Note that this is just a hint, and it's always possible to any srcSize value.\n *  When a frame is fully decoded, @return will be 0.\n *  If decompression failed, @return is an error code which can be tested using LZ4F_isError().\n */\nsize_t LZ4F_decompress(LZ4F_dctx* dctx,\n                       void* dstBuffer, size_t* dstSizePtr,\n                       const void* srcBuffer, size_t* srcSizePtr,\n                       const LZ4F_decompressOptions_t* decompressOptionsPtr)\n{\n    LZ4F_decompressOptions_t optionsNull;\n    const BYTE* const srcStart = (const BYTE*)srcBuffer;\n    const BYTE* const srcEnd = srcStart + *srcSizePtr;\n    const BYTE* srcPtr = srcStart;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* const dstEnd = dstStart ? dstStart + *dstSizePtr : NULL;\n    BYTE* dstPtr = dstStart;\n    const BYTE* selectedIn = NULL;\n    unsigned doAnotherStage = 1;\n    size_t nextSrcSizeHint = 1;\n\n\n    DEBUGLOG(5, \"LZ4F_decompress: src[%p](%u) => dst[%p](%u)\",\n            srcBuffer, (unsigned)*srcSizePtr, dstBuffer, (unsigned)*dstSizePtr);\n    if (dstBuffer == NULL) assert(*dstSizePtr == 0);\n    MEM_INIT(&optionsNull, 0, sizeof(optionsNull));\n    if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;\n    *srcSizePtr = 0;\n    *dstSizePtr = 0;\n    assert(dctx != NULL);\n    dctx->skipChecksum |= (decompressOptionsPtr->skipChecksums != 0); /* once set, disable for the remainder of the frame */\n\n    /* behaves as a state machine */\n\n    while (doAnotherStage) {\n\n        switch(dctx->dStage)\n        {\n\n        case dstage_getFrameHeader:\n            DEBUGLOG(6, \"dstage_getFrameHeader\");\n            if ((size_t)(srcEnd-srcPtr) >= maxFHSize) {  /* enough to decode - shortcut */\n                size_t const hSize = LZ4F_decodeHeader(dctx, srcPtr, (size_t)(srcEnd-srcPtr));  /* will update dStage appropriately */\n                FORWARD_IF_ERROR(hSize);\n                srcPtr += hSize;\n                break;\n            }\n            dctx->tmpInSize = 0;\n            if (srcEnd-srcPtr == 0) return minFHSize;   /* 0-size input */\n            dctx->tmpInTarget = minFHSize;   /* minimum size to decode header */\n            dctx->dStage = dstage_storeFrameHeader;\n            /* fall-through */\n\n        case dstage_storeFrameHeader:\n            DEBUGLOG(6, \"dstage_storeFrameHeader\");\n            {   size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize, (size_t)(srcEnd - srcPtr));\n                memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);\n                dctx->tmpInSize += sizeToCopy;\n                srcPtr += sizeToCopy;\n            }\n            if (dctx->tmpInSize < dctx->tmpInTarget) {\n                nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize) + BHSize;   /* rest of header + nextBlockHeader */\n                doAnotherStage = 0;   /* not enough src data, ask for some more */\n                break;\n            }\n            FORWARD_IF_ERROR( LZ4F_decodeHeader(dctx, dctx->header, dctx->tmpInTarget) ); /* will update dStage appropriately */\n            break;\n\n        case dstage_init:\n            DEBUGLOG(6, \"dstage_init\");\n            if (dctx->frameInfo.contentChecksumFlag) (void)XXH32_reset(&(dctx->xxh), 0);\n            /* internal buffers allocation */\n            {   size_t const bufferNeeded = dctx->maxBlockSize\n                    + ((dctx->frameInfo.blockMode==LZ4F_blockLinked) ? 128 KB : 0);\n                if (bufferNeeded > dctx->maxBufferSize) {   /* tmp buffers too small */\n                    dctx->maxBufferSize = 0;   /* ensure allocation will be re-attempted on next entry*/\n                    LZ4F_free(dctx->tmpIn, dctx->cmem);\n                    dctx->tmpIn = (BYTE*)LZ4F_malloc(dctx->maxBlockSize + BFSize /* block checksum */, dctx->cmem);\n                    RETURN_ERROR_IF(dctx->tmpIn == NULL, allocation_failed);\n                    LZ4F_free(dctx->tmpOutBuffer, dctx->cmem);\n                    dctx->tmpOutBuffer= (BYTE*)LZ4F_malloc(bufferNeeded, dctx->cmem);\n                    RETURN_ERROR_IF(dctx->tmpOutBuffer== NULL, allocation_failed);\n                    dctx->maxBufferSize = bufferNeeded;\n            }   }\n            dctx->tmpInSize = 0;\n            dctx->tmpInTarget = 0;\n            dctx->tmpOut = dctx->tmpOutBuffer;\n            dctx->tmpOutStart = 0;\n            dctx->tmpOutSize = 0;\n\n            dctx->dStage = dstage_getBlockHeader;\n            /* fall-through */\n\n        case dstage_getBlockHeader:\n            if ((size_t)(srcEnd - srcPtr) >= BHSize) {\n                selectedIn = srcPtr;\n                srcPtr += BHSize;\n            } else {\n                /* not enough input to read cBlockSize field */\n                dctx->tmpInSize = 0;\n                dctx->dStage = dstage_storeBlockHeader;\n            }\n\n            if (dctx->dStage == dstage_storeBlockHeader)   /* can be skipped */\n        case dstage_storeBlockHeader:\n            {   size_t const remainingInput = (size_t)(srcEnd - srcPtr);\n                size_t const wantedData = BHSize - dctx->tmpInSize;\n                size_t const sizeToCopy = MIN(wantedData, remainingInput);\n                memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctx->tmpInSize += sizeToCopy;\n\n                if (dctx->tmpInSize < BHSize) {   /* not enough input for cBlockSize */\n                    nextSrcSizeHint = BHSize - dctx->tmpInSize;\n                    doAnotherStage  = 0;\n                    break;\n                }\n                selectedIn = dctx->tmpIn;\n            }   /* if (dctx->dStage == dstage_storeBlockHeader) */\n\n        /* decode block header */\n            {   U32 const blockHeader = LZ4F_readLE32(selectedIn);\n                size_t const nextCBlockSize = blockHeader & 0x7FFFFFFFU;\n                size_t const crcSize = dctx->frameInfo.blockChecksumFlag * BFSize;\n                if (blockHeader==0) {  /* frameEnd signal, no more block */\n                    DEBUGLOG(5, \"end of frame\");\n                    dctx->dStage = dstage_getSuffix;\n                    break;\n                }\n                if (nextCBlockSize > dctx->maxBlockSize) {\n                    RETURN_ERROR(maxBlockSize_invalid);\n                }\n                if (blockHeader & LZ4F_BLOCKUNCOMPRESSED_FLAG) {\n                    /* next block is uncompressed */\n                    dctx->tmpInTarget = nextCBlockSize;\n                    DEBUGLOG(5, \"next block is uncompressed (size %u)\", (U32)nextCBlockSize);\n                    if (dctx->frameInfo.blockChecksumFlag) {\n                        (void)XXH32_reset(&dctx->blockChecksum, 0);\n                    }\n                    dctx->dStage = dstage_copyDirect;\n                    break;\n                }\n                /* next block is a compressed block */\n                dctx->tmpInTarget = nextCBlockSize + crcSize;\n                dctx->dStage = dstage_getCBlock;\n                if (dstPtr==dstEnd || srcPtr==srcEnd) {\n                    nextSrcSizeHint = BHSize + nextCBlockSize + crcSize;\n                    doAnotherStage = 0;\n                }\n                break;\n            }\n\n        case dstage_copyDirect:   /* uncompressed block */\n            DEBUGLOG(6, \"dstage_copyDirect\");\n            {   size_t sizeToCopy;\n                if (dstPtr == NULL) {\n                    sizeToCopy = 0;\n                } else {\n                    size_t const minBuffSize = MIN((size_t)(srcEnd-srcPtr), (size_t)(dstEnd-dstPtr));\n                    sizeToCopy = MIN(dctx->tmpInTarget, minBuffSize);\n                    memcpy(dstPtr, srcPtr, sizeToCopy);\n                    if (!dctx->skipChecksum) {\n                        if (dctx->frameInfo.blockChecksumFlag) {\n                            (void)XXH32_update(&dctx->blockChecksum, srcPtr, sizeToCopy);\n                        }\n                        if (dctx->frameInfo.contentChecksumFlag)\n                            (void)XXH32_update(&dctx->xxh, srcPtr, sizeToCopy);\n                    }\n                    if (dctx->frameInfo.contentSize)\n                        dctx->frameRemainingSize -= sizeToCopy;\n\n                    /* history management (linked blocks only)*/\n                    if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {\n                        LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 0);\n                    }\n                    srcPtr += sizeToCopy;\n                    dstPtr += sizeToCopy;\n                }\n                if (sizeToCopy == dctx->tmpInTarget) {   /* all done */\n                    if (dctx->frameInfo.blockChecksumFlag) {\n                        dctx->tmpInSize = 0;\n                        dctx->dStage = dstage_getBlockChecksum;\n                    } else\n                        dctx->dStage = dstage_getBlockHeader;  /* new block */\n                    break;\n                }\n                dctx->tmpInTarget -= sizeToCopy;  /* need to copy more */\n            }\n            nextSrcSizeHint = dctx->tmpInTarget +\n                            +(dctx->frameInfo.blockChecksumFlag ? BFSize : 0)\n                            + BHSize /* next header size */;\n            doAnotherStage = 0;\n            break;\n\n        /* check block checksum for recently transferred uncompressed block */\n        case dstage_getBlockChecksum:\n            DEBUGLOG(6, \"dstage_getBlockChecksum\");\n            {   const void* crcSrc;\n                if ((srcEnd-srcPtr >= 4) && (dctx->tmpInSize==0)) {\n                    crcSrc = srcPtr;\n                    srcPtr += 4;\n                } else {\n                    size_t const stillToCopy = 4 - dctx->tmpInSize;\n                    size_t const sizeToCopy = MIN(stillToCopy, (size_t)(srcEnd-srcPtr));\n                    memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);\n                    dctx->tmpInSize += sizeToCopy;\n                    srcPtr += sizeToCopy;\n                    if (dctx->tmpInSize < 4) {  /* all input consumed */\n                        doAnotherStage = 0;\n                        break;\n                    }\n                    crcSrc = dctx->header;\n                }\n                if (!dctx->skipChecksum) {\n                    U32 const readCRC = LZ4F_readLE32(crcSrc);\n                    U32 const calcCRC = XXH32_digest(&dctx->blockChecksum);\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n                    DEBUGLOG(6, \"compare block checksum\");\n                    if (readCRC != calcCRC) {\n                        DEBUGLOG(4, \"incorrect block checksum: %08X != %08X\",\n                                readCRC, calcCRC);\n                        RETURN_ERROR(blockChecksum_invalid);\n                    }\n#else\n                    (void)readCRC;\n                    (void)calcCRC;\n#endif\n            }   }\n            dctx->dStage = dstage_getBlockHeader;  /* new block */\n            break;\n\n        case dstage_getCBlock:\n            DEBUGLOG(6, \"dstage_getCBlock\");\n            if ((size_t)(srcEnd-srcPtr) < dctx->tmpInTarget) {\n                dctx->tmpInSize = 0;\n                dctx->dStage = dstage_storeCBlock;\n                break;\n            }\n            /* input large enough to read full block directly */\n            selectedIn = srcPtr;\n            srcPtr += dctx->tmpInTarget;\n\n            if (0)  /* always jump over next block */\n        case dstage_storeCBlock:\n            {   size_t const wantedData = dctx->tmpInTarget - dctx->tmpInSize;\n                size_t const inputLeft = (size_t)(srcEnd-srcPtr);\n                size_t const sizeToCopy = MIN(wantedData, inputLeft);\n                memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);\n                dctx->tmpInSize += sizeToCopy;\n                srcPtr += sizeToCopy;\n                if (dctx->tmpInSize < dctx->tmpInTarget) { /* need more input */\n                    nextSrcSizeHint = (dctx->tmpInTarget - dctx->tmpInSize)\n                                    + (dctx->frameInfo.blockChecksumFlag ? BFSize : 0)\n                                    + BHSize /* next header size */;\n                    doAnotherStage = 0;\n                    break;\n                }\n                selectedIn = dctx->tmpIn;\n            }\n\n            /* At this stage, input is large enough to decode a block */\n\n            /* First, decode and control block checksum if it exists */\n            if (dctx->frameInfo.blockChecksumFlag) {\n                assert(dctx->tmpInTarget >= 4);\n                dctx->tmpInTarget -= 4;\n                assert(selectedIn != NULL);  /* selectedIn is defined at this stage (either srcPtr, or dctx->tmpIn) */\n                {   U32 const readBlockCrc = LZ4F_readLE32(selectedIn + dctx->tmpInTarget);\n                    U32 const calcBlockCrc = XXH32(selectedIn, dctx->tmpInTarget, 0);\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n                    RETURN_ERROR_IF(readBlockCrc != calcBlockCrc, blockChecksum_invalid);\n#else\n                    (void)readBlockCrc;\n                    (void)calcBlockCrc;\n#endif\n            }   }\n\n            /* decode directly into destination buffer if there is enough room */\n            if ( ((size_t)(dstEnd-dstPtr) >= dctx->maxBlockSize)\n                 /* unless the dictionary is stored in tmpOut:\n                  * in which case it's faster to decode within tmpOut\n                  * to benefit from prefix speedup */\n              && !(dctx->dict!= NULL && (const BYTE*)dctx->dict + dctx->dictSize == dctx->tmpOut) )\n            {\n                const char* dict = (const char*)dctx->dict;\n                size_t dictSize = dctx->dictSize;\n                int decodedSize;\n                assert(dstPtr != NULL);\n                if (dict && dictSize > 1 GB) {\n                    /* overflow control : dctx->dictSize is an int, avoid truncation / sign issues */\n                    dict += dictSize - 64 KB;\n                    dictSize = 64 KB;\n                }\n                decodedSize = LZ4_decompress_safe_usingDict(\n                        (const char*)selectedIn, (char*)dstPtr,\n                        (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,\n                        dict, (int)dictSize);\n                RETURN_ERROR_IF(decodedSize < 0, decompressionFailed);\n                if ((dctx->frameInfo.contentChecksumFlag) && (!dctx->skipChecksum))\n                    XXH32_update(&(dctx->xxh), dstPtr, (size_t)decodedSize);\n                if (dctx->frameInfo.contentSize)\n                    dctx->frameRemainingSize -= (size_t)decodedSize;\n\n                /* dictionary management */\n                if (dctx->frameInfo.blockMode==LZ4F_blockLinked) {\n                    LZ4F_updateDict(dctx, dstPtr, (size_t)decodedSize, dstStart, 0);\n                }\n\n                dstPtr += decodedSize;\n                dctx->dStage = dstage_getBlockHeader;  /* end of block, let's get another one */\n                break;\n            }\n\n            /* not enough place into dst : decode into tmpOut */\n\n            /* manage dictionary */\n            if (dctx->frameInfo.blockMode == LZ4F_blockLinked) {\n                if (dctx->dict == dctx->tmpOutBuffer) {\n                    /* truncate dictionary to 64 KB if too big */\n                    if (dctx->dictSize > 128 KB) {\n                        memcpy(dctx->tmpOutBuffer, dctx->dict + dctx->dictSize - 64 KB, 64 KB);\n                        dctx->dictSize = 64 KB;\n                    }\n                    dctx->tmpOut = dctx->tmpOutBuffer + dctx->dictSize;\n                } else {  /* dict not within tmpOut */\n                    size_t const reservedDictSpace = MIN(dctx->dictSize, 64 KB);\n                    dctx->tmpOut = dctx->tmpOutBuffer + reservedDictSpace;\n            }   }\n\n            /* Decode block into tmpOut */\n            {   const char* dict = (const char*)dctx->dict;\n                size_t dictSize = dctx->dictSize;\n                int decodedSize;\n                if (dict && dictSize > 1 GB) {\n                    /* the dictSize param is an int, avoid truncation / sign issues */\n                    dict += dictSize - 64 KB;\n                    dictSize = 64 KB;\n                }\n                decodedSize = LZ4_decompress_safe_usingDict(\n                        (const char*)selectedIn, (char*)dctx->tmpOut,\n                        (int)dctx->tmpInTarget, (int)dctx->maxBlockSize,\n                        dict, (int)dictSize);\n                RETURN_ERROR_IF(decodedSize < 0, decompressionFailed);\n                if (dctx->frameInfo.contentChecksumFlag && !dctx->skipChecksum)\n                    XXH32_update(&(dctx->xxh), dctx->tmpOut, (size_t)decodedSize);\n                if (dctx->frameInfo.contentSize)\n                    dctx->frameRemainingSize -= (size_t)decodedSize;\n                dctx->tmpOutSize = (size_t)decodedSize;\n                dctx->tmpOutStart = 0;\n                dctx->dStage = dstage_flushOut;\n            }\n            /* fall-through */\n\n        case dstage_flushOut:  /* flush decoded data from tmpOut to dstBuffer */\n            DEBUGLOG(6, \"dstage_flushOut\");\n            if (dstPtr != NULL) {\n                size_t const sizeToCopy = MIN(dctx->tmpOutSize - dctx->tmpOutStart, (size_t)(dstEnd-dstPtr));\n                memcpy(dstPtr, dctx->tmpOut + dctx->tmpOutStart, sizeToCopy);\n\n                /* dictionary management */\n                if (dctx->frameInfo.blockMode == LZ4F_blockLinked)\n                    LZ4F_updateDict(dctx, dstPtr, sizeToCopy, dstStart, 1 /*withinTmp*/);\n\n                dctx->tmpOutStart += sizeToCopy;\n                dstPtr += sizeToCopy;\n            }\n            if (dctx->tmpOutStart == dctx->tmpOutSize) { /* all flushed */\n                dctx->dStage = dstage_getBlockHeader;  /* get next block */\n                break;\n            }\n            /* could not flush everything : stop there, just request a block header */\n            doAnotherStage = 0;\n            nextSrcSizeHint = BHSize;\n            break;\n\n        case dstage_getSuffix:\n            RETURN_ERROR_IF(dctx->frameRemainingSize, frameSize_wrong);   /* incorrect frame size decoded */\n            if (!dctx->frameInfo.contentChecksumFlag) {  /* no checksum, frame is completed */\n                nextSrcSizeHint = 0;\n                LZ4F_resetDecompressionContext(dctx);\n                doAnotherStage = 0;\n                break;\n            }\n            if ((srcEnd - srcPtr) < 4) {  /* not enough size for entire CRC */\n                dctx->tmpInSize = 0;\n                dctx->dStage = dstage_storeSuffix;\n            } else {\n                selectedIn = srcPtr;\n                srcPtr += 4;\n            }\n\n            if (dctx->dStage == dstage_storeSuffix)   /* can be skipped */\n        case dstage_storeSuffix:\n            {   size_t const remainingInput = (size_t)(srcEnd - srcPtr);\n                size_t const wantedData = 4 - dctx->tmpInSize;\n                size_t const sizeToCopy = MIN(wantedData, remainingInput);\n                memcpy(dctx->tmpIn + dctx->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctx->tmpInSize += sizeToCopy;\n                if (dctx->tmpInSize < 4) { /* not enough input to read complete suffix */\n                    nextSrcSizeHint = 4 - dctx->tmpInSize;\n                    doAnotherStage=0;\n                    break;\n                }\n                selectedIn = dctx->tmpIn;\n            }   /* if (dctx->dStage == dstage_storeSuffix) */\n\n        /* case dstage_checkSuffix: */   /* no direct entry, avoid initialization risks */\n            if (!dctx->skipChecksum) {\n                U32 const readCRC = LZ4F_readLE32(selectedIn);\n                U32 const resultCRC = XXH32_digest(&(dctx->xxh));\n                DEBUGLOG(4, \"frame checksum: stored 0x%0X vs 0x%0X processed\", readCRC, resultCRC);\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n                RETURN_ERROR_IF(readCRC != resultCRC, contentChecksum_invalid);\n#else\n                (void)readCRC;\n                (void)resultCRC;\n#endif\n            }\n            nextSrcSizeHint = 0;\n            LZ4F_resetDecompressionContext(dctx);\n            doAnotherStage = 0;\n            break;\n\n        case dstage_getSFrameSize:\n            if ((srcEnd - srcPtr) >= 4) {\n                selectedIn = srcPtr;\n                srcPtr += 4;\n            } else {\n                /* not enough input to read cBlockSize field */\n                dctx->tmpInSize = 4;\n                dctx->tmpInTarget = 8;\n                dctx->dStage = dstage_storeSFrameSize;\n            }\n\n            if (dctx->dStage == dstage_storeSFrameSize)\n        case dstage_storeSFrameSize:\n            {   size_t const sizeToCopy = MIN(dctx->tmpInTarget - dctx->tmpInSize,\n                                             (size_t)(srcEnd - srcPtr) );\n                memcpy(dctx->header + dctx->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctx->tmpInSize += sizeToCopy;\n                if (dctx->tmpInSize < dctx->tmpInTarget) {\n                    /* not enough input to get full sBlockSize; wait for more */\n                    nextSrcSizeHint = dctx->tmpInTarget - dctx->tmpInSize;\n                    doAnotherStage = 0;\n                    break;\n                }\n                selectedIn = dctx->header + 4;\n            }   /* if (dctx->dStage == dstage_storeSFrameSize) */\n\n        /* case dstage_decodeSFrameSize: */   /* no direct entry */\n            {   size_t const SFrameSize = LZ4F_readLE32(selectedIn);\n                dctx->frameInfo.contentSize = SFrameSize;\n                dctx->tmpInTarget = SFrameSize;\n                dctx->dStage = dstage_skipSkippable;\n                break;\n            }\n\n        case dstage_skipSkippable:\n            {   size_t const skipSize = MIN(dctx->tmpInTarget, (size_t)(srcEnd-srcPtr));\n                srcPtr += skipSize;\n                dctx->tmpInTarget -= skipSize;\n                doAnotherStage = 0;\n                nextSrcSizeHint = dctx->tmpInTarget;\n                if (nextSrcSizeHint) break;  /* still more to skip */\n                /* frame fully skipped : prepare context for a new frame */\n                LZ4F_resetDecompressionContext(dctx);\n                break;\n            }\n        }   /* switch (dctx->dStage) */\n    }   /* while (doAnotherStage) */\n\n    /* preserve history within tmpOut whenever necessary */\n    LZ4F_STATIC_ASSERT((unsigned)dstage_init == 2);\n    if ( (dctx->frameInfo.blockMode==LZ4F_blockLinked)  /* next block will use up to 64KB from previous ones */\n      && (dctx->dict != dctx->tmpOutBuffer)             /* dictionary is not already within tmp */\n      && (dctx->dict != NULL)                           /* dictionary exists */\n      && (!decompressOptionsPtr->stableDst)             /* cannot rely on dst data to remain there for next call */\n      && ((unsigned)(dctx->dStage)-2 < (unsigned)(dstage_getSuffix)-2) )  /* valid stages : [init ... getSuffix[ */\n    {\n        if (dctx->dStage == dstage_flushOut) {\n            size_t const preserveSize = (size_t)(dctx->tmpOut - dctx->tmpOutBuffer);\n            size_t copySize = 64 KB - dctx->tmpOutSize;\n            const BYTE* oldDictEnd = dctx->dict + dctx->dictSize - dctx->tmpOutStart;\n            if (dctx->tmpOutSize > 64 KB) copySize = 0;\n            if (copySize > preserveSize) copySize = preserveSize;\n            assert(dctx->tmpOutBuffer != NULL);\n\n            memcpy(dctx->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);\n\n            dctx->dict = dctx->tmpOutBuffer;\n            dctx->dictSize = preserveSize + dctx->tmpOutStart;\n        } else {\n            const BYTE* const oldDictEnd = dctx->dict + dctx->dictSize;\n            size_t const newDictSize = MIN(dctx->dictSize, 64 KB);\n\n            memcpy(dctx->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);\n\n            dctx->dict = dctx->tmpOutBuffer;\n            dctx->dictSize = newDictSize;\n            dctx->tmpOut = dctx->tmpOutBuffer + newDictSize;\n        }\n    }\n\n    *srcSizePtr = (size_t)(srcPtr - srcStart);\n    *dstSizePtr = (size_t)(dstPtr - dstStart);\n    return nextSrcSizeHint;\n}\n\n/*! LZ4F_decompress_usingDict() :\n *  Same as LZ4F_decompress(), using a predefined dictionary.\n *  Dictionary is used \"in place\", without any preprocessing.\n *  It must remain accessible throughout the entire frame decoding.\n */\nsize_t LZ4F_decompress_usingDict(LZ4F_dctx* dctx,\n                       void* dstBuffer, size_t* dstSizePtr,\n                       const void* srcBuffer, size_t* srcSizePtr,\n                       const void* dict, size_t dictSize,\n                       const LZ4F_decompressOptions_t* decompressOptionsPtr)\n{\n    if (dctx->dStage <= dstage_init) {\n        dctx->dict = (const BYTE*)dict;\n        dctx->dictSize = dictSize;\n    }\n    return LZ4F_decompress(dctx, dstBuffer, dstSizePtr,\n                           srcBuffer, srcSizePtr,\n                           decompressOptionsPtr);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/LZ4/lz4frame.h",
    "content": "﻿/*\n   LZ4F - LZ4-Frame library\n   Header File\n   Copyright (C) 2011-2020, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ4 source repository : https://github.com/lz4/lz4\n   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* LZ4F is a stand-alone API able to create and decode LZ4 frames\n * conformant with specification v1.6.1 in doc/lz4_Frame_format.md .\n * Generated frames are compatible with `lz4` CLI.\n *\n * LZ4F also offers streaming capabilities.\n *\n * lz4.h is not required when using lz4frame.h,\n * except to extract common constants such as LZ4_VERSION_NUMBER.\n * */\n\n#ifndef LZ4F_H_09782039843\n#define LZ4F_H_09782039843\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* ---   Dependency   --- */\n#include <stddef.h>   /* size_t */\n\n\n/**\n * Introduction\n *\n * lz4frame.h implements LZ4 frame specification: see doc/lz4_Frame_format.md .\n * LZ4 Frames are compatible with `lz4` CLI,\n * and designed to be interoperable with any system.\n**/\n\n/*-***************************************************************\n *  Compiler specifics\n *****************************************************************/\n/*  LZ4_DLL_EXPORT :\n *  Enable exporting of functions when building a Windows DLL\n *  LZ4FLIB_VISIBILITY :\n *  Control library symbols visibility.\n */\n#ifndef LZ4FLIB_VISIBILITY\n#  if defined(__GNUC__) && (__GNUC__ >= 4)\n#    define LZ4FLIB_VISIBILITY __attribute__ ((visibility (\"default\")))\n#  else\n#    define LZ4FLIB_VISIBILITY\n#  endif\n#endif\n#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)\n#  define LZ4FLIB_API __declspec(dllexport) LZ4FLIB_VISIBILITY\n#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)\n#  define LZ4FLIB_API __declspec(dllimport) LZ4FLIB_VISIBILITY\n#else\n#  define LZ4FLIB_API LZ4FLIB_VISIBILITY\n#endif\n\n#ifdef LZ4F_DISABLE_DEPRECATE_WARNINGS\n#  define LZ4F_DEPRECATE(x) x\n#else\n#  if defined(_MSC_VER)\n#    define LZ4F_DEPRECATE(x) x   /* __declspec(deprecated) x - only works with C++ */\n#  elif defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))\n#    define LZ4F_DEPRECATE(x) x __attribute__((deprecated))\n#  else\n#    define LZ4F_DEPRECATE(x) x   /* no deprecation warning for this compiler */\n#  endif\n#endif\n\n\n/*-************************************\n *  Error management\n **************************************/\ntypedef size_t LZ4F_errorCode_t;\n\nLZ4FLIB_API unsigned    LZ4F_isError(LZ4F_errorCode_t code);   /**< tells when a function result is an error code */\nLZ4FLIB_API const char* LZ4F_getErrorName(LZ4F_errorCode_t code);   /**< return error code string; for debugging */\n\n\n/*-************************************\n *  Frame compression types\n ************************************* */\n/* #define LZ4F_ENABLE_OBSOLETE_ENUMS   // uncomment to enable obsolete enums */\n#ifdef LZ4F_ENABLE_OBSOLETE_ENUMS\n#  define LZ4F_OBSOLETE_ENUM(x) , LZ4F_DEPRECATE(x) = LZ4F_##x\n#else\n#  define LZ4F_OBSOLETE_ENUM(x)\n#endif\n\n/* The larger the block size, the (slightly) better the compression ratio,\n * though there are diminishing returns.\n * Larger blocks also increase memory usage on both compression and decompression sides.\n */\ntypedef enum {\n    LZ4F_default=0,\n    LZ4F_max64KB=4,\n    LZ4F_max256KB=5,\n    LZ4F_max1MB=6,\n    LZ4F_max4MB=7\n    LZ4F_OBSOLETE_ENUM(max64KB)\n    LZ4F_OBSOLETE_ENUM(max256KB)\n    LZ4F_OBSOLETE_ENUM(max1MB)\n    LZ4F_OBSOLETE_ENUM(max4MB)\n} LZ4F_blockSizeID_t;\n\n/* Linked blocks sharply reduce inefficiencies when using small blocks,\n * they compress better.\n * However, some LZ4 decoders are only compatible with independent blocks */\ntypedef enum {\n    LZ4F_blockLinked=0,\n    LZ4F_blockIndependent\n    LZ4F_OBSOLETE_ENUM(blockLinked)\n    LZ4F_OBSOLETE_ENUM(blockIndependent)\n} LZ4F_blockMode_t;\n\ntypedef enum {\n    LZ4F_noContentChecksum=0,\n    LZ4F_contentChecksumEnabled\n    LZ4F_OBSOLETE_ENUM(noContentChecksum)\n    LZ4F_OBSOLETE_ENUM(contentChecksumEnabled)\n} LZ4F_contentChecksum_t;\n\ntypedef enum {\n    LZ4F_noBlockChecksum=0,\n    LZ4F_blockChecksumEnabled\n} LZ4F_blockChecksum_t;\n\ntypedef enum {\n    LZ4F_frame=0,\n    LZ4F_skippableFrame\n    LZ4F_OBSOLETE_ENUM(skippableFrame)\n} LZ4F_frameType_t;\n\n#ifdef LZ4F_ENABLE_OBSOLETE_ENUMS\ntypedef LZ4F_blockSizeID_t blockSizeID_t;\ntypedef LZ4F_blockMode_t blockMode_t;\ntypedef LZ4F_frameType_t frameType_t;\ntypedef LZ4F_contentChecksum_t contentChecksum_t;\n#endif\n\n/*! LZ4F_frameInfo_t :\n *  makes it possible to set or read frame parameters.\n *  Structure must be first init to 0, using memset() or LZ4F_INIT_FRAMEINFO,\n *  setting all parameters to default.\n *  It's then possible to update selectively some parameters */\ntypedef struct {\n  LZ4F_blockSizeID_t     blockSizeID;         /* max64KB, max256KB, max1MB, max4MB; 0 == default (LZ4F_max64KB) */\n  LZ4F_blockMode_t       blockMode;           /* LZ4F_blockLinked, LZ4F_blockIndependent; 0 == default (LZ4F_blockLinked) */\n  LZ4F_contentChecksum_t contentChecksumFlag; /* 1: add a 32-bit checksum of frame's decompressed data; 0 == default (disabled) */\n  LZ4F_frameType_t       frameType;           /* read-only field : LZ4F_frame or LZ4F_skippableFrame */\n  unsigned long long     contentSize;         /* Size of uncompressed content ; 0 == unknown */\n  unsigned               dictID;              /* Dictionary ID, sent by compressor to help decoder select correct dictionary; 0 == no dictID provided */\n  LZ4F_blockChecksum_t   blockChecksumFlag;   /* 1: each block followed by a checksum of block's compressed data; 0 == default (disabled) */\n} LZ4F_frameInfo_t;\n\n#define LZ4F_INIT_FRAMEINFO   { LZ4F_max64KB, LZ4F_blockLinked, LZ4F_noContentChecksum, LZ4F_frame, 0ULL, 0U, LZ4F_noBlockChecksum }    /* v1.8.3+ */\n\n/*! LZ4F_preferences_t :\n *  makes it possible to supply advanced compression instructions to streaming interface.\n *  Structure must be first init to 0, using memset() or LZ4F_INIT_PREFERENCES,\n *  setting all parameters to default.\n *  All reserved fields must be set to zero. */\ntypedef struct {\n  LZ4F_frameInfo_t frameInfo;\n  int      compressionLevel;    /* 0: default (fast mode); values > LZ4HC_CLEVEL_MAX count as LZ4HC_CLEVEL_MAX; values < 0 trigger \"fast acceleration\" */\n  unsigned autoFlush;           /* 1: always flush; reduces usage of internal buffers */\n  unsigned favorDecSpeed;       /* 1: parser favors decompression speed vs compression ratio. Only works for high compression modes (>= LZ4HC_CLEVEL_OPT_MIN) */  /* v1.8.2+ */\n  unsigned reserved[3];         /* must be zero for forward compatibility */\n} LZ4F_preferences_t;\n\n#define LZ4F_INIT_PREFERENCES   { LZ4F_INIT_FRAMEINFO, 0, 0u, 0u, { 0u, 0u, 0u } }    /* v1.8.3+ */\n\n\n/*-*********************************\n*  Simple compression function\n***********************************/\n\n/*! LZ4F_compressFrame() :\n *  Compress srcBuffer content into an LZ4-compressed frame.\n *  It's a one shot operation, all input content is consumed, and all output is generated.\n *\n *  Note : it's a stateless operation (no LZ4F_cctx state needed).\n *  In order to reduce load on the allocator, LZ4F_compressFrame(), by default,\n *  uses the stack to allocate space for the compression state and some table.\n *  If this usage of the stack is too much for your application,\n *  consider compiling `lz4frame.c` with compile-time macro LZ4F_HEAPMODE set to 1 instead.\n *  All state allocations will use the Heap.\n *  It also means each invocation of LZ4F_compressFrame() will trigger several internal alloc/free invocations.\n *\n * @dstCapacity MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).\n * @preferencesPtr is optional : one can provide NULL, in which case all preferences are set to default.\n * @return : number of bytes written into dstBuffer.\n *           or an error code if it fails (can be tested using LZ4F_isError())\n */\nLZ4FLIB_API size_t LZ4F_compressFrame(void* dstBuffer, size_t dstCapacity,\n                                const void* srcBuffer, size_t srcSize,\n                                const LZ4F_preferences_t* preferencesPtr);\n\n/*! LZ4F_compressFrameBound() :\n *  Returns the maximum possible compressed size with LZ4F_compressFrame() given srcSize and preferences.\n * `preferencesPtr` is optional. It can be replaced by NULL, in which case, the function will assume default preferences.\n *  Note : this result is only usable with LZ4F_compressFrame().\n *         It may also be relevant to LZ4F_compressUpdate() _only if_ no flush() operation is ever performed.\n */\nLZ4FLIB_API size_t LZ4F_compressFrameBound(size_t srcSize, const LZ4F_preferences_t* preferencesPtr);\n\n\n/*! LZ4F_compressionLevel_max() :\n * @return maximum allowed compression level (currently: 12)\n */\nLZ4FLIB_API int LZ4F_compressionLevel_max(void);   /* v1.8.0+ */\n\n\n/*-***********************************\n*  Advanced compression functions\n*************************************/\ntypedef struct LZ4F_cctx_s LZ4F_cctx;   /* incomplete type */\ntypedef LZ4F_cctx* LZ4F_compressionContext_t;  /* for compatibility with older APIs, prefer using LZ4F_cctx */\n\ntypedef struct {\n  unsigned stableSrc;    /* 1 == src content will remain present on future calls to LZ4F_compress(); skip copying src content within tmp buffer */\n  unsigned reserved[3];\n} LZ4F_compressOptions_t;\n\n/*---   Resource Management   ---*/\n\n#define LZ4F_VERSION 100    /* This number can be used to check for an incompatible API breaking change */\nLZ4FLIB_API unsigned LZ4F_getVersion(void);\n\n/*! LZ4F_createCompressionContext() :\n *  The first thing to do is to create a compressionContext object,\n *  which will keep track of operation state during streaming compression.\n *  This is achieved using LZ4F_createCompressionContext(), which takes as argument a version,\n *  and a pointer to LZ4F_cctx*, to write the resulting pointer into.\n *  @version provided MUST be LZ4F_VERSION. It is intended to track potential version mismatch, notably when using DLL.\n *  The function provides a pointer to a fully allocated LZ4F_cctx object.\n *  @cctxPtr MUST be != NULL.\n *  If @return != zero, context creation failed.\n *  A created compression context can be employed multiple times for consecutive streaming operations.\n *  Once all streaming compression jobs are completed,\n *  the state object can be released using LZ4F_freeCompressionContext().\n *  Note1 : LZ4F_freeCompressionContext() is always successful. Its return value can be ignored.\n *  Note2 : LZ4F_freeCompressionContext() works fine with NULL input pointers (do nothing).\n**/\nLZ4FLIB_API LZ4F_errorCode_t LZ4F_createCompressionContext(LZ4F_cctx** cctxPtr, unsigned version);\nLZ4FLIB_API LZ4F_errorCode_t LZ4F_freeCompressionContext(LZ4F_cctx* cctx);\n\n\n/*----    Compression    ----*/\n\n#define LZ4F_HEADER_SIZE_MIN  7   /* LZ4 Frame header size can vary, depending on selected parameters */\n#define LZ4F_HEADER_SIZE_MAX 19\n\n/* Size in bytes of a block header in little-endian format. Highest bit indicates if block data is uncompressed */\n#define LZ4F_BLOCK_HEADER_SIZE 4\n\n/* Size in bytes of a block checksum footer in little-endian format. */\n#define LZ4F_BLOCK_CHECKSUM_SIZE 4\n\n/* Size in bytes of the content checksum. */\n#define LZ4F_CONTENT_CHECKSUM_SIZE 4\n\n/*! LZ4F_compressBegin() :\n *  will write the frame header into dstBuffer.\n *  dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes.\n * `prefsPtr` is optional : NULL can be provided to set all preferences to default.\n * @return : number of bytes written into dstBuffer for the header\n *           or an error code (which can be tested using LZ4F_isError())\n */\nLZ4FLIB_API size_t LZ4F_compressBegin(LZ4F_cctx* cctx,\n                                      void* dstBuffer, size_t dstCapacity,\n                                      const LZ4F_preferences_t* prefsPtr);\n\n/*! LZ4F_compressBound() :\n *  Provides minimum dstCapacity required to guarantee success of\n *  LZ4F_compressUpdate(), given a srcSize and preferences, for a worst case scenario.\n *  When srcSize==0, LZ4F_compressBound() provides an upper bound for LZ4F_flush() and LZ4F_compressEnd() instead.\n *  Note that the result is only valid for a single invocation of LZ4F_compressUpdate().\n *  When invoking LZ4F_compressUpdate() multiple times,\n *  if the output buffer is gradually filled up instead of emptied and re-used from its start,\n *  one must check if there is enough remaining capacity before each invocation, using LZ4F_compressBound().\n * @return is always the same for a srcSize and prefsPtr.\n *  prefsPtr is optional : when NULL is provided, preferences will be set to cover worst case scenario.\n *  tech details :\n * @return if automatic flushing is not enabled, includes the possibility that internal buffer might already be filled by up to (blockSize-1) bytes.\n *  It also includes frame footer (ending + checksum), since it might be generated by LZ4F_compressEnd().\n * @return doesn't include frame header, as it was already generated by LZ4F_compressBegin().\n */\nLZ4FLIB_API size_t LZ4F_compressBound(size_t srcSize, const LZ4F_preferences_t* prefsPtr);\n\n/*! LZ4F_compressUpdate() :\n *  LZ4F_compressUpdate() can be called repetitively to compress as much data as necessary.\n *  Important rule: dstCapacity MUST be large enough to ensure operation success even in worst case situations.\n *  This value is provided by LZ4F_compressBound().\n *  If this condition is not respected, LZ4F_compress() will fail (result is an errorCode).\n *  After an error, the state is left in a UB state, and must be re-initialized or freed.\n *  If previously an uncompressed block was written, buffered data is flushed\n *  before appending compressed data is continued.\n * `cOptPtr` is optional : NULL can be provided, in which case all options are set to default.\n * @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered).\n *           or an error code if it fails (which can be tested using LZ4F_isError())\n */\nLZ4FLIB_API size_t LZ4F_compressUpdate(LZ4F_cctx* cctx,\n                                       void* dstBuffer, size_t dstCapacity,\n                                 const void* srcBuffer, size_t srcSize,\n                                 const LZ4F_compressOptions_t* cOptPtr);\n\n/*! LZ4F_flush() :\n *  When data must be generated and sent immediately, without waiting for a block to be completely filled,\n *  it's possible to call LZ4_flush(). It will immediately compress any data buffered within cctx.\n * `dstCapacity` must be large enough to ensure the operation will be successful.\n * `cOptPtr` is optional : it's possible to provide NULL, all options will be set to default.\n * @return : nb of bytes written into dstBuffer (can be zero, when there is no data stored within cctx)\n *           or an error code if it fails (which can be tested using LZ4F_isError())\n *  Note : LZ4F_flush() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr).\n */\nLZ4FLIB_API size_t LZ4F_flush(LZ4F_cctx* cctx,\n                              void* dstBuffer, size_t dstCapacity,\n                        const LZ4F_compressOptions_t* cOptPtr);\n\n/*! LZ4F_compressEnd() :\n *  To properly finish an LZ4 frame, invoke LZ4F_compressEnd().\n *  It will flush whatever data remained within `cctx` (like LZ4_flush())\n *  and properly finalize the frame, with an endMark and a checksum.\n * `cOptPtr` is optional : NULL can be provided, in which case all options will be set to default.\n * @return : nb of bytes written into dstBuffer, necessarily >= 4 (endMark),\n *           or an error code if it fails (which can be tested using LZ4F_isError())\n *  Note : LZ4F_compressEnd() is guaranteed to be successful when dstCapacity >= LZ4F_compressBound(0, prefsPtr).\n *  A successful call to LZ4F_compressEnd() makes `cctx` available again for another compression task.\n */\nLZ4FLIB_API size_t LZ4F_compressEnd(LZ4F_cctx* cctx,\n                                    void* dstBuffer, size_t dstCapacity,\n                              const LZ4F_compressOptions_t* cOptPtr);\n\n\n/*-*********************************\n*  Decompression functions\n***********************************/\ntypedef struct LZ4F_dctx_s LZ4F_dctx;   /* incomplete type */\ntypedef LZ4F_dctx* LZ4F_decompressionContext_t;   /* compatibility with previous API versions */\n\ntypedef struct {\n  unsigned stableDst;     /* pledges that last 64KB decompressed data is present right before @dstBuffer pointer.\n                           * This optimization skips internal storage operations.\n                           * Once set, this pledge must remain valid up to the end of current frame. */\n  unsigned skipChecksums; /* disable checksum calculation and verification, even when one is present in frame, to save CPU time.\n                           * Setting this option to 1 once disables all checksums for the rest of the frame. */\n  unsigned reserved1;     /* must be set to zero for forward compatibility */\n  unsigned reserved0;     /* idem */\n} LZ4F_decompressOptions_t;\n\n\n/* Resource management */\n\n/*! LZ4F_createDecompressionContext() :\n *  Create an LZ4F_dctx object, to track all decompression operations.\n *  @version provided MUST be LZ4F_VERSION.\n *  @dctxPtr MUST be valid.\n *  The function fills @dctxPtr with the value of a pointer to an allocated and initialized LZ4F_dctx object.\n *  The @return is an errorCode, which can be tested using LZ4F_isError().\n *  dctx memory can be released using LZ4F_freeDecompressionContext();\n *  Result of LZ4F_freeDecompressionContext() indicates current state of decompressionContext when being released.\n *  That is, it should be == 0 if decompression has been completed fully and correctly.\n */\nLZ4FLIB_API LZ4F_errorCode_t LZ4F_createDecompressionContext(LZ4F_dctx** dctxPtr, unsigned version);\nLZ4FLIB_API LZ4F_errorCode_t LZ4F_freeDecompressionContext(LZ4F_dctx* dctx);\n\n\n/*-***********************************\n*  Streaming decompression functions\n*************************************/\n\n#define LZ4F_MAGICNUMBER 0x184D2204U\n#define LZ4F_MAGIC_SKIPPABLE_START 0x184D2A50U\n#define LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH 5\n\n/*! LZ4F_headerSize() : v1.9.0+\n *  Provide the header size of a frame starting at `src`.\n * `srcSize` must be >= LZ4F_MIN_SIZE_TO_KNOW_HEADER_LENGTH,\n *  which is enough to decode the header length.\n * @return : size of frame header\n *           or an error code, which can be tested using LZ4F_isError()\n *  note : Frame header size is variable, but is guaranteed to be\n *         >= LZ4F_HEADER_SIZE_MIN bytes, and <= LZ4F_HEADER_SIZE_MAX bytes.\n */\nLZ4FLIB_API size_t LZ4F_headerSize(const void* src, size_t srcSize);\n\n/*! LZ4F_getFrameInfo() :\n *  This function extracts frame parameters (max blockSize, dictID, etc.).\n *  Its usage is optional: user can also invoke LZ4F_decompress() directly.\n *\n *  Extracted information will fill an existing LZ4F_frameInfo_t structure.\n *  This can be useful for allocation and dictionary identification purposes.\n *\n *  LZ4F_getFrameInfo() can work in the following situations :\n *\n *  1) At the beginning of a new frame, before any invocation of LZ4F_decompress().\n *     It will decode header from `srcBuffer`,\n *     consuming the header and starting the decoding process.\n *\n *     Input size must be large enough to contain the full frame header.\n *     Frame header size can be known beforehand by LZ4F_headerSize().\n *     Frame header size is variable, but is guaranteed to be >= LZ4F_HEADER_SIZE_MIN bytes,\n *     and not more than <= LZ4F_HEADER_SIZE_MAX bytes.\n *     Hence, blindly providing LZ4F_HEADER_SIZE_MAX bytes or more will always work.\n *     It's allowed to provide more input data than the header size,\n *     LZ4F_getFrameInfo() will only consume the header.\n *\n *     If input size is not large enough,\n *     aka if it's smaller than header size,\n *     function will fail and return an error code.\n *\n *  2) After decoding has been started,\n *     it's possible to invoke LZ4F_getFrameInfo() anytime\n *     to extract already decoded frame parameters stored within dctx.\n *\n *     Note that, if decoding has barely started,\n *     and not yet read enough information to decode the header,\n *     LZ4F_getFrameInfo() will fail.\n *\n *  The number of bytes consumed from srcBuffer will be updated in *srcSizePtr (necessarily <= original value).\n *  LZ4F_getFrameInfo() only consumes bytes when decoding has not yet started,\n *  and when decoding the header has been successful.\n *  Decompression must then resume from (srcBuffer + *srcSizePtr).\n *\n * @return : a hint about how many srcSize bytes LZ4F_decompress() expects for next call,\n *           or an error code which can be tested using LZ4F_isError().\n *  note 1 : in case of error, dctx is not modified. Decoding operation can resume from beginning safely.\n *  note 2 : frame parameters are *copied into* an already allocated LZ4F_frameInfo_t structure.\n */\nLZ4FLIB_API size_t\nLZ4F_getFrameInfo(LZ4F_dctx* dctx,\n                  LZ4F_frameInfo_t* frameInfoPtr,\n            const void* srcBuffer, size_t* srcSizePtr);\n\n/*! LZ4F_decompress() :\n *  Call this function repetitively to regenerate data compressed in `srcBuffer`.\n *\n *  The function requires a valid dctx state.\n *  It will read up to *srcSizePtr bytes from srcBuffer,\n *  and decompress data into dstBuffer, of capacity *dstSizePtr.\n *\n *  The nb of bytes consumed from srcBuffer will be written into *srcSizePtr (necessarily <= original value).\n *  The nb of bytes decompressed into dstBuffer will be written into *dstSizePtr (necessarily <= original value).\n *\n *  The function does not necessarily read all input bytes, so always check value in *srcSizePtr.\n *  Unconsumed source data must be presented again in subsequent invocations.\n *\n * `dstBuffer` can freely change between each consecutive function invocation.\n * `dstBuffer` content will be overwritten.\n *\n *  Note: if `LZ4F_getFrameInfo()` is called before `LZ4F_decompress()`, srcBuffer must be updated to reflect\n *  the number of bytes consumed after reading the frame header. Failure to update srcBuffer before calling\n *  `LZ4F_decompress()` will cause decompression failure or, even worse, successful but incorrect decompression.\n *  See the `LZ4F_getFrameInfo()` docs for details.\n *\n * @return : an hint of how many `srcSize` bytes LZ4F_decompress() expects for next call.\n *  Schematically, it's the size of the current (or remaining) compressed block + header of next block.\n *  Respecting the hint provides some small speed benefit, because it skips intermediate buffers.\n *  This is just a hint though, it's always possible to provide any srcSize.\n *\n *  When a frame is fully decoded, @return will be 0 (no more data expected).\n *  When provided with more bytes than necessary to decode a frame,\n *  LZ4F_decompress() will stop reading exactly at end of current frame, and @return 0.\n *\n *  If decompression failed, @return is an error code, which can be tested using LZ4F_isError().\n *  After a decompression error, the `dctx` context is not resumable.\n *  Use LZ4F_resetDecompressionContext() to return to clean state.\n *\n *  After a frame is fully decoded, dctx can be used again to decompress another frame.\n */\nLZ4FLIB_API size_t\nLZ4F_decompress(LZ4F_dctx* dctx,\n                void* dstBuffer, size_t* dstSizePtr,\n          const void* srcBuffer, size_t* srcSizePtr,\n          const LZ4F_decompressOptions_t* dOptPtr);\n\n\n/*! LZ4F_resetDecompressionContext() : added in v1.8.0\n *  In case of an error, the context is left in \"undefined\" state.\n *  In which case, it's necessary to reset it, before re-using it.\n *  This method can also be used to abruptly stop any unfinished decompression,\n *  and start a new one using same context resources. */\nLZ4FLIB_API void LZ4F_resetDecompressionContext(LZ4F_dctx* dctx);   /* always successful */\n\n\n/**********************************\n *  Dictionary compression API\n *********************************/\n\n/* A Dictionary is useful for the compression of small messages (KB range).\n * It dramatically improves compression efficiency.\n *\n * LZ4 can ingest any input as dictionary, though only the last 64 KB are useful.\n * Better results are generally achieved by using Zstandard's Dictionary Builder\n * to generate a high-quality dictionary from a set of samples.\n *\n * The same dictionary will have to be used on the decompression side\n * for decoding to be successful.\n * To help identify the correct dictionary at decoding stage,\n * the frame header allows optional embedding of a dictID field.\n */\n\n/*! LZ4F_compressBegin_usingDict() : stable since v1.10\n *  Inits dictionary compression streaming, and writes the frame header into dstBuffer.\n * @dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes.\n * @prefsPtr is optional : one may provide NULL as argument,\n *  however, it's the only way to provide dictID in the frame header.\n * @dictBuffer must outlive the compression session.\n * @return : number of bytes written into dstBuffer for the header,\n *           or an error code (which can be tested using LZ4F_isError())\n *  NOTE: The LZ4Frame spec allows each independent block to be compressed with the dictionary,\n *        but this entry supports a more limited scenario, where only the first block uses the dictionary.\n *        This is still useful for small data, which only need one block anyway.\n *        For larger inputs, one may be more interested in LZ4F_compressFrame_usingCDict() below.\n */\nLZ4FLIB_API size_t\nLZ4F_compressBegin_usingDict(LZ4F_cctx* cctx,\n                            void* dstBuffer, size_t dstCapacity,\n                      const void* dictBuffer, size_t dictSize,\n                      const LZ4F_preferences_t* prefsPtr);\n\n/*! LZ4F_decompress_usingDict() : stable since v1.10\n *  Same as LZ4F_decompress(), using a predefined dictionary.\n *  Dictionary is used \"in place\", without any preprocessing.\n**  It must remain accessible throughout the entire frame decoding. */\nLZ4FLIB_API size_t\nLZ4F_decompress_usingDict(LZ4F_dctx* dctxPtr,\n                          void* dstBuffer, size_t* dstSizePtr,\n                    const void* srcBuffer, size_t* srcSizePtr,\n                    const void* dict, size_t dictSize,\n                    const LZ4F_decompressOptions_t* decompressOptionsPtr);\n\n/*****************************************\n *  Bulk processing dictionary compression\n *****************************************/\n\n/* Loading a dictionary has a cost, since it involves construction of tables.\n * The Bulk processing dictionary API makes it possible to share this cost\n * over an arbitrary number of compression jobs, even concurrently,\n * markedly improving compression latency for these cases.\n *\n * Note that there is no corresponding bulk API for the decompression side,\n * because dictionary does not carry any initialization cost for decompression.\n * Use the regular LZ4F_decompress_usingDict() there.\n */\ntypedef struct LZ4F_CDict_s LZ4F_CDict;\n\n/*! LZ4_createCDict() : stable since v1.10\n *  When compressing multiple messages / blocks using the same dictionary, it's recommended to initialize it just once.\n *  LZ4_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.\n *  LZ4_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.\n * @dictBuffer can be released after LZ4_CDict creation, since its content is copied within CDict. */\nLZ4FLIB_API LZ4F_CDict* LZ4F_createCDict(const void* dictBuffer, size_t dictSize);\nLZ4FLIB_API void        LZ4F_freeCDict(LZ4F_CDict* CDict);\n\n/*! LZ4_compressFrame_usingCDict() : stable since v1.10\n *  Compress an entire srcBuffer into a valid LZ4 frame using a digested Dictionary.\n * @cctx must point to a context created by LZ4F_createCompressionContext().\n *  If @cdict==NULL, compress without a dictionary.\n * @dstBuffer MUST be >= LZ4F_compressFrameBound(srcSize, preferencesPtr).\n *  If this condition is not respected, function will fail (@return an errorCode).\n *  The LZ4F_preferences_t structure is optional : one may provide NULL as argument,\n *  but it's not recommended, as it's the only way to provide @dictID in the frame header.\n * @return : number of bytes written into dstBuffer.\n *           or an error code if it fails (can be tested using LZ4F_isError())\n *  Note: for larger inputs generating multiple independent blocks,\n *        this entry point uses the dictionary for each block. */\nLZ4FLIB_API size_t\nLZ4F_compressFrame_usingCDict(LZ4F_cctx* cctx,\n                              void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize,\n                        const LZ4F_CDict* cdict,\n                        const LZ4F_preferences_t* preferencesPtr);\n\n/*! LZ4F_compressBegin_usingCDict() : stable since v1.10\n *  Inits streaming dictionary compression, and writes the frame header into dstBuffer.\n * @dstCapacity must be >= LZ4F_HEADER_SIZE_MAX bytes.\n * @prefsPtr is optional : one may provide NULL as argument,\n *  note however that it's the only way to insert a @dictID in the frame header.\n * @cdict must outlive the compression session.\n * @return : number of bytes written into dstBuffer for the header,\n *           or an error code, which can be tested using LZ4F_isError(). */\nLZ4FLIB_API size_t\nLZ4F_compressBegin_usingCDict(LZ4F_cctx* cctx,\n                              void* dstBuffer, size_t dstCapacity,\n                        const LZ4F_CDict* cdict,\n                        const LZ4F_preferences_t* prefsPtr);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* LZ4F_H_09782039843 */\n\n#if defined(LZ4F_STATIC_LINKING_ONLY) && !defined(LZ4F_H_STATIC_09782039843)\n#define LZ4F_H_STATIC_09782039843\n\n/* Note :\n * The below declarations are not stable and may change in the future.\n * They are therefore only safe to depend on\n * when the caller is statically linked against the library.\n * To access their declarations, define LZ4F_STATIC_LINKING_ONLY.\n *\n * By default, these symbols aren't published into shared/dynamic libraries.\n * You can override this behavior and force them to be published\n * by defining LZ4F_PUBLISH_STATIC_FUNCTIONS.\n * Use at your own risk.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifdef LZ4F_PUBLISH_STATIC_FUNCTIONS\n# define LZ4FLIB_STATIC_API LZ4FLIB_API\n#else\n# define LZ4FLIB_STATIC_API\n#endif\n\n\n/* ---   Error List   --- */\n#define LZ4F_LIST_ERRORS(ITEM) \\\n        ITEM(OK_NoError) \\\n        ITEM(ERROR_GENERIC) \\\n        ITEM(ERROR_maxBlockSize_invalid) \\\n        ITEM(ERROR_blockMode_invalid) \\\n        ITEM(ERROR_parameter_invalid) \\\n        ITEM(ERROR_compressionLevel_invalid) \\\n        ITEM(ERROR_headerVersion_wrong) \\\n        ITEM(ERROR_blockChecksum_invalid) \\\n        ITEM(ERROR_reservedFlag_set) \\\n        ITEM(ERROR_allocation_failed) \\\n        ITEM(ERROR_srcSize_tooLarge) \\\n        ITEM(ERROR_dstMaxSize_tooSmall) \\\n        ITEM(ERROR_frameHeader_incomplete) \\\n        ITEM(ERROR_frameType_unknown) \\\n        ITEM(ERROR_frameSize_wrong) \\\n        ITEM(ERROR_srcPtr_wrong) \\\n        ITEM(ERROR_decompressionFailed) \\\n        ITEM(ERROR_headerChecksum_invalid) \\\n        ITEM(ERROR_contentChecksum_invalid) \\\n        ITEM(ERROR_frameDecoding_alreadyStarted) \\\n        ITEM(ERROR_compressionState_uninitialized) \\\n        ITEM(ERROR_parameter_null) \\\n        ITEM(ERROR_io_write) \\\n        ITEM(ERROR_io_read) \\\n        ITEM(ERROR_maxCode)\n\n#define LZ4F_GENERATE_ENUM(ENUM) LZ4F_##ENUM,\n\n/* enum list is exposed, to handle specific errors */\ntypedef enum { LZ4F_LIST_ERRORS(LZ4F_GENERATE_ENUM)\n              _LZ4F_dummy_error_enum_for_c89_never_used } LZ4F_errorCodes;\n\nLZ4FLIB_STATIC_API LZ4F_errorCodes LZ4F_getErrorCode(size_t functionResult);\n\n/**********************************\n *  Advanced compression operations\n *********************************/\n\n/*! LZ4F_getBlockSize() :\n * @return, in scalar format (size_t),\n *          the maximum block size associated with @blockSizeID,\n *          or an error code (can be tested using LZ4F_isError()) if @blockSizeID is invalid.\n**/\nLZ4FLIB_STATIC_API size_t LZ4F_getBlockSize(LZ4F_blockSizeID_t blockSizeID);\n\n/*! LZ4F_uncompressedUpdate() :\n *  LZ4F_uncompressedUpdate() can be called repetitively to add data stored as uncompressed blocks.\n *  Important rule: dstCapacity MUST be large enough to store the entire source buffer as\n *  no compression is done for this operation\n *  If this condition is not respected, LZ4F_uncompressedUpdate() will fail (result is an errorCode).\n *  After an error, the state is left in a UB state, and must be re-initialized or freed.\n *  If previously a compressed block was written, buffered data is flushed first,\n *  before appending uncompressed data is continued.\n *  This operation is only supported when LZ4F_blockIndependent is used.\n * `cOptPtr` is optional : NULL can be provided, in which case all options are set to default.\n * @return : number of bytes written into `dstBuffer` (it can be zero, meaning input data was just buffered).\n *           or an error code if it fails (which can be tested using LZ4F_isError())\n */\nLZ4FLIB_STATIC_API size_t\nLZ4F_uncompressedUpdate(LZ4F_cctx* cctx,\n                        void* dstBuffer, size_t dstCapacity,\n                  const void* srcBuffer, size_t srcSize,\n                  const LZ4F_compressOptions_t* cOptPtr);\n\n/**********************************\n *  Custom memory allocation\n *********************************/\n\n/*! Custom memory allocation : v1.9.4+\n *  These prototypes make it possible to pass custom allocation/free functions.\n *  LZ4F_customMem is provided at state creation time, using LZ4F_create*_advanced() listed below.\n *  All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones.\n */\ntypedef void* (*LZ4F_AllocFunction) (void* opaqueState, size_t size);\ntypedef void* (*LZ4F_CallocFunction) (void* opaqueState, size_t size);\ntypedef void  (*LZ4F_FreeFunction) (void* opaqueState, void* address);\ntypedef struct {\n    LZ4F_AllocFunction customAlloc;\n    LZ4F_CallocFunction customCalloc; /* optional; when not defined, uses customAlloc + memset */\n    LZ4F_FreeFunction customFree;\n    void* opaqueState;\n} LZ4F_CustomMem;\nstatic\n#ifdef __GNUC__\n__attribute__((__unused__))\n#endif\nLZ4F_CustomMem const LZ4F_defaultCMem = { NULL, NULL, NULL, NULL };  /**< this constant defers to stdlib's functions */\n\nLZ4FLIB_STATIC_API LZ4F_cctx* LZ4F_createCompressionContext_advanced(LZ4F_CustomMem customMem, unsigned version);\nLZ4FLIB_STATIC_API LZ4F_dctx* LZ4F_createDecompressionContext_advanced(LZ4F_CustomMem customMem, unsigned version);\nLZ4FLIB_STATIC_API LZ4F_CDict* LZ4F_createCDict_advanced(LZ4F_CustomMem customMem, const void* dictBuffer, size_t dictSize);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* defined(LZ4F_STATIC_LINKING_ONLY) && !defined(LZ4F_H_STATIC_09782039843) */\n"
  },
  {
    "path": "NanaZip.Codecs/LZ4/lz4frame_static.h",
    "content": "﻿/*\n   LZ4 auto-framing library\n   Header File for static linking only\n   Copyright (C) 2011-2020, Yann Collet.\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ4 source repository : https://github.com/lz4/lz4\n   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n#ifndef LZ4FRAME_STATIC_H_0398209384\n#define LZ4FRAME_STATIC_H_0398209384\n\n/* The declarations that formerly were made here have been merged into\n * lz4frame.h, protected by the LZ4F_STATIC_LINKING_ONLY macro. Going forward,\n * it is recommended to simply include that header directly.\n */\n\n#define LZ4F_STATIC_LINKING_ONLY\n#include \"lz4frame.h\"\n\n#endif /* LZ4FRAME_STATIC_H_0398209384 */\n"
  },
  {
    "path": "NanaZip.Codecs/LZ4/lz4hc.c",
    "content": "﻿/*\n    LZ4 HC - High Compression Mode of LZ4\n    Copyright (C) 2011-2020, Yann Collet.\n\n    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n       - LZ4 source repository : https://github.com/lz4/lz4\n       - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n/* note : lz4hc is not an independent module, it requires lz4.h/lz4.c for proper compilation */\n\n\n/* *************************************\n*  Tuning Parameter\n***************************************/\n\n/*! HEAPMODE :\n *  Select how stateless HC compression functions like `LZ4_compress_HC()`\n *  allocate memory for their workspace:\n *  in stack (0:fastest), or in heap (1:default, requires malloc()).\n *  Since workspace is rather large, heap mode is recommended.\n**/\n#ifndef LZ4HC_HEAPMODE\n#  define LZ4HC_HEAPMODE 1\n#endif\n\n\n/*===    Dependency    ===*/\n#define LZ4_HC_STATIC_LINKING_ONLY\n#include \"lz4hc.h\"\n#include <limits.h>\n\n\n/*===   Shared lz4.c code   ===*/\n#ifndef LZ4_SRC_INCLUDED\n# if defined(__GNUC__)\n#  pragma GCC diagnostic ignored \"-Wunused-function\"\n# endif\n# if defined (__clang__)\n#  pragma clang diagnostic ignored \"-Wunused-function\"\n# endif\n# define LZ4_COMMONDEFS_ONLY\n# include \"lz4.c\"   /* LZ4_count, constants, mem */\n#endif\n\n\n/*===   Enums   ===*/\ntypedef enum { noDictCtx, usingDictCtxHc } dictCtx_directive;\n\n\n/*===   Constants   ===*/\n#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)\n#define LZ4_OPT_NUM   (1<<12)\n\n\n/*===   Macros   ===*/\n#define MIN(a,b)   ( (a) < (b) ? (a) : (b) )\n#define MAX(a,b)   ( (a) > (b) ? (a) : (b) )\n\n\n/*===   Levels definition   ===*/\ntypedef enum { lz4mid, lz4hc, lz4opt } lz4hc_strat_e;\ntypedef struct {\n    lz4hc_strat_e strat;\n    int nbSearches;\n    U32 targetLength;\n} cParams_t;\nstatic const cParams_t k_clTable[LZ4HC_CLEVEL_MAX+1] = {\n    { lz4mid,    2, 16 },  /* 0, unused */\n    { lz4mid,    2, 16 },  /* 1, unused */\n    { lz4mid,    2, 16 },  /* 2 */\n    { lz4hc,     4, 16 },  /* 3 */\n    { lz4hc,     8, 16 },  /* 4 */\n    { lz4hc,    16, 16 },  /* 5 */\n    { lz4hc,    32, 16 },  /* 6 */\n    { lz4hc,    64, 16 },  /* 7 */\n    { lz4hc,   128, 16 },  /* 8 */\n    { lz4hc,   256, 16 },  /* 9 */\n    { lz4opt,   96, 64 },  /*10==LZ4HC_CLEVEL_OPT_MIN*/\n    { lz4opt,  512,128 },  /*11 */\n    { lz4opt,16384,LZ4_OPT_NUM },  /* 12==LZ4HC_CLEVEL_MAX */\n};\n\nstatic cParams_t LZ4HC_getCLevelParams(int cLevel)\n{\n    /* note : clevel convention is a bit different from lz4frame,\n     * possibly something worth revisiting for consistency */\n    if (cLevel < 1)\n        cLevel = LZ4HC_CLEVEL_DEFAULT;\n    cLevel = MIN(LZ4HC_CLEVEL_MAX, cLevel);\n    return k_clTable[cLevel];\n}\n\n\n/*===   Hashing   ===*/\n#define LZ4HC_HASHSIZE 4\n#define HASH_FUNCTION(i)      (((i) * 2654435761U) >> ((MINMATCH*8)-LZ4HC_HASH_LOG))\nstatic U32 LZ4HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ4_read32(ptr)); }\n\n#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2)\n/* lie to the compiler about data alignment; use with caution */\nstatic U64 LZ4_read64(const void* memPtr) { return *(const U64*) memPtr; }\n\n#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1)\n/* __pack instructions are safer, but compiler specific */\nLZ4_PACK(typedef struct { U64 u64; }) LZ4_unalign64;\nstatic U64 LZ4_read64(const void* ptr) { return ((const LZ4_unalign64*)ptr)->u64; }\n\n#else  /* safe and portable access using memcpy() */\nstatic U64 LZ4_read64(const void* memPtr)\n{\n    U64 val; LZ4_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\n#endif /* LZ4_FORCE_MEMORY_ACCESS */\n\n#define LZ4MID_HASHSIZE 8\n#define LZ4MID_HASHLOG (LZ4HC_HASH_LOG-1)\n#define LZ4MID_HASHTABLESIZE (1 << LZ4MID_HASHLOG)\n\nstatic U32 LZ4MID_hash4(U32 v) { return (v * 2654435761U) >> (32-LZ4MID_HASHLOG); }\nstatic U32 LZ4MID_hash4Ptr(const void* ptr) { return LZ4MID_hash4(LZ4_read32(ptr)); }\n/* note: hash7 hashes the lower 56-bits.\n * It presumes input was read using little endian.*/\nstatic U32 LZ4MID_hash7(U64 v) { return (U32)(((v  << (64-56)) * 58295818150454627ULL) >> (64-LZ4MID_HASHLOG)) ; }\nstatic U64 LZ4_readLE64(const void* memPtr);\nstatic U32 LZ4MID_hash8Ptr(const void* ptr) { return LZ4MID_hash7(LZ4_readLE64(ptr)); }\n\nstatic U64 LZ4_readLE64(const void* memPtr)\n{\n    if (LZ4_isLittleEndian()) {\n        return LZ4_read64(memPtr);\n    } else {\n        const BYTE* p = (const BYTE*)memPtr;\n        /* note: relies on the compiler to simplify this expression */\n        return (U64)p[0] | ((U64)p[1]<<8) | ((U64)p[2]<<16) | ((U64)p[3]<<24)\n            | ((U64)p[4]<<32) | ((U64)p[5]<<40) | ((U64)p[6]<<48) | ((U64)p[7]<<56);\n    }\n}\n\n\n/*===   Count match length   ===*/\nLZ4_FORCE_INLINE\nunsigned LZ4HC_NbCommonBytes32(U32 val)\n{\n    assert(val != 0);\n    if (LZ4_isLittleEndian()) {\n#     if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)\n        unsigned long r;\n        _BitScanReverse(&r, val);\n        return (unsigned)((31 - r) >> 3);\n#     elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \\\n                            ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \\\n                                        !defined(LZ4_FORCE_SW_BITCOUNT)\n        return (unsigned)__builtin_clz(val) >> 3;\n#     else\n        val >>= 8;\n        val = ((((val + 0x00FFFF00) | 0x00FFFFFF) + val) |\n              (val + 0x00FF0000)) >> 24;\n        return (unsigned)val ^ 3;\n#     endif\n    } else {\n#     if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(LZ4_FORCE_SW_BITCOUNT)\n        unsigned long r;\n        _BitScanForward(&r, val);\n        return (unsigned)(r >> 3);\n#     elif (defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 3) || \\\n                            ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))) && \\\n                                        !defined(LZ4_FORCE_SW_BITCOUNT)\n        return (unsigned)__builtin_ctz(val) >> 3;\n#     else\n        const U32 m = 0x01010101;\n        return (unsigned)((((val - 1) ^ val) & (m - 1)) * m) >> 24;\n#     endif\n    }\n}\n\n/** LZ4HC_countBack() :\n * @return : negative value, nb of common bytes before ip/match */\nLZ4_FORCE_INLINE\nint LZ4HC_countBack(const BYTE* const ip, const BYTE* const match,\n                    const BYTE* const iMin, const BYTE* const mMin)\n{\n    int back = 0;\n    int const min = (int)MAX(iMin - ip, mMin - match);\n    assert(min <= 0);\n    assert(ip >= iMin); assert((size_t)(ip-iMin) < (1U<<31));\n    assert(match >= mMin); assert((size_t)(match - mMin) < (1U<<31));\n\n    while ((back - min) > 3) {\n        U32 const v = LZ4_read32(ip + back - 4) ^ LZ4_read32(match + back - 4);\n        if (v) {\n            return (back - (int)LZ4HC_NbCommonBytes32(v));\n        } else back -= 4; /* 4-byte step */\n    }\n    /* check remainder if any */\n    while ( (back > min)\n         && (ip[back-1] == match[back-1]) )\n            back--;\n    return back;\n}\n\n/*===   Chain table updates   ===*/\n#define DELTANEXTU16(table, pos) table[(U16)(pos)]   /* faster */\n/* Make fields passed to, and updated by LZ4HC_encodeSequence explicit */\n#define UPDATABLE(ip, op, anchor) &ip, &op, &anchor\n\n\n/**************************************\n*  Init\n**************************************/\nstatic void LZ4HC_clearTables (LZ4HC_CCtx_internal* hc4)\n{\n    MEM_INIT(hc4->hashTable, 0, sizeof(hc4->hashTable));\n    MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));\n}\n\nstatic void LZ4HC_init_internal (LZ4HC_CCtx_internal* hc4, const BYTE* start)\n{\n    size_t const bufferSize = (size_t)(hc4->end - hc4->prefixStart);\n    size_t newStartingOffset = bufferSize + hc4->dictLimit;\n    DEBUGLOG(5, \"LZ4HC_init_internal\");\n    assert(newStartingOffset >= bufferSize);  /* check overflow */\n    if (newStartingOffset > 1 GB) {\n        LZ4HC_clearTables(hc4);\n        newStartingOffset = 0;\n    }\n    newStartingOffset += 64 KB;\n    hc4->nextToUpdate = (U32)newStartingOffset;\n    hc4->prefixStart = start;\n    hc4->end = start;\n    hc4->dictStart = start;\n    hc4->dictLimit = (U32)newStartingOffset;\n    hc4->lowLimit = (U32)newStartingOffset;\n}\n\n\n/**************************************\n*  Encode\n**************************************/\n/* LZ4HC_encodeSequence() :\n * @return : 0 if ok,\n *           1 if buffer issue detected */\nLZ4_FORCE_INLINE int LZ4HC_encodeSequence (\n    const BYTE** _ip,\n    BYTE** _op,\n    const BYTE** _anchor,\n    int matchLength,\n    int offset,\n    limitedOutput_directive limit,\n    BYTE* oend)\n{\n#define ip      (*_ip)\n#define op      (*_op)\n#define anchor  (*_anchor)\n\n    size_t length;\n    BYTE* const token = op++;\n\n#if defined(LZ4_DEBUG) && (LZ4_DEBUG >= 6)\n    static const BYTE* start = NULL;\n    static U32 totalCost = 0;\n    U32 const pos = (start==NULL) ? 0 : (U32)(anchor - start);\n    U32 const ll = (U32)(ip - anchor);\n    U32 const llAdd = (ll>=15) ? ((ll-15) / 255) + 1 : 0;\n    U32 const mlAdd = (matchLength>=19) ? ((matchLength-19) / 255) + 1 : 0;\n    U32 const cost = 1 + llAdd + ll + 2 + mlAdd;\n    if (start==NULL) start = anchor;  /* only works for single segment */\n    /* g_debuglog_enable = (pos >= 2228) & (pos <= 2262); */\n    DEBUGLOG(6, \"pos:%7u -- literals:%4u, match:%4i, offset:%5i, cost:%4u + %5u\",\n                pos,\n                (U32)(ip - anchor), matchLength, offset,\n                cost, totalCost);\n    totalCost += cost;\n#endif\n\n    /* Encode Literal length */\n    length = (size_t)(ip - anchor);\n    LZ4_STATIC_ASSERT(notLimited == 0);\n    /* Check output limit */\n    if (limit && ((op + (length / 255) + length + (2 + 1 + LASTLITERALS)) > oend)) {\n        DEBUGLOG(6, \"Not enough room to write %i literals (%i bytes remaining)\",\n                (int)length, (int)(oend - op));\n        return 1;\n    }\n    if (length >= RUN_MASK) {\n        size_t len = length - RUN_MASK;\n        *token = (RUN_MASK << ML_BITS);\n        for(; len >= 255 ; len -= 255) *op++ = 255;\n        *op++ = (BYTE)len;\n    } else {\n        *token = (BYTE)(length << ML_BITS);\n    }\n\n    /* Copy Literals */\n    LZ4_wildCopy8(op, anchor, op + length);\n    op += length;\n\n    /* Encode Offset */\n    assert(offset <= LZ4_DISTANCE_MAX );\n    assert(offset > 0);\n    LZ4_writeLE16(op, (U16)(offset)); op += 2;\n\n    /* Encode MatchLength */\n    assert(matchLength >= MINMATCH);\n    length = (size_t)matchLength - MINMATCH;\n    if (limit && (op + (length / 255) + (1 + LASTLITERALS) > oend)) {\n        DEBUGLOG(6, \"Not enough room to write match length\");\n        return 1;   /* Check output limit */\n    }\n    if (length >= ML_MASK) {\n        *token += ML_MASK;\n        length -= ML_MASK;\n        for(; length >= 510 ; length -= 510) { *op++ = 255; *op++ = 255; }\n        if (length >= 255) { length -= 255; *op++ = 255; }\n        *op++ = (BYTE)length;\n    } else {\n        *token += (BYTE)(length);\n    }\n\n    /* Prepare next loop */\n    ip += matchLength;\n    anchor = ip;\n\n    return 0;\n\n#undef ip\n#undef op\n#undef anchor\n}\n\n\ntypedef struct {\n    int off;\n    int len;\n    int back;  /* negative value */\n} LZ4HC_match_t;\n\nLZ4HC_match_t LZ4HC_searchExtDict(const BYTE* ip, U32 ipIndex,\n        const BYTE* const iLowLimit, const BYTE* const iHighLimit,\n        const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex,\n        int currentBestML, int nbAttempts)\n{\n    size_t const lDictEndIndex = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;\n    U32 lDictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];\n    U32 matchIndex = lDictMatchIndex + gDictEndIndex - (U32)lDictEndIndex;\n    int offset = 0, sBack = 0;\n    assert(lDictEndIndex <= 1 GB);\n    if (lDictMatchIndex>0)\n        DEBUGLOG(7, \"lDictEndIndex = %zu, lDictMatchIndex = %u\", lDictEndIndex, lDictMatchIndex);\n    while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) {\n        const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + lDictMatchIndex;\n\n        if (LZ4_read32(matchPtr) == LZ4_read32(ip)) {\n            int mlt;\n            int back = 0;\n            const BYTE* vLimit = ip + (lDictEndIndex - lDictMatchIndex);\n            if (vLimit > iHighLimit) vLimit = iHighLimit;\n            mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;\n            back = (ip > iLowLimit) ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0;\n            mlt -= back;\n            if (mlt > currentBestML) {\n                currentBestML = mlt;\n                offset = (int)(ipIndex - matchIndex);\n                sBack = back;\n                DEBUGLOG(7, \"found match of length %i within extDictCtx\", currentBestML);\n        }   }\n\n        {   U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, lDictMatchIndex);\n            lDictMatchIndex -= nextOffset;\n            matchIndex -= nextOffset;\n    }   }\n\n    {   LZ4HC_match_t md;\n        md.len = currentBestML;\n        md.off = offset;\n        md.back = sBack;\n        return md;\n    }\n}\n\ntypedef LZ4HC_match_t (*LZ4MID_searchIntoDict_f)(const BYTE* ip, U32 ipIndex,\n        const BYTE* const iHighLimit,\n        const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex);\n\nstatic LZ4HC_match_t LZ4MID_searchHCDict(const BYTE* ip, U32 ipIndex,\n        const BYTE* const iHighLimit,\n        const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex)\n{\n    return LZ4HC_searchExtDict(ip,ipIndex,\n                            ip, iHighLimit,\n                            dictCtx, gDictEndIndex,\n                            MINMATCH-1, 2);\n}\n\nstatic LZ4HC_match_t LZ4MID_searchExtDict(const BYTE* ip, U32 ipIndex,\n        const BYTE* const iHighLimit,\n        const LZ4HC_CCtx_internal* dictCtx, U32 gDictEndIndex)\n{\n    size_t const lDictEndIndex = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;\n    const U32* const hash4Table = dictCtx->hashTable;\n    const U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE;\n    DEBUGLOG(7, \"LZ4MID_searchExtDict (ipIdx=%u)\", ipIndex);\n\n    /* search long match first */\n    {   U32 l8DictMatchIndex = hash8Table[LZ4MID_hash8Ptr(ip)];\n        U32 m8Index = l8DictMatchIndex + gDictEndIndex - (U32)lDictEndIndex;\n        assert(lDictEndIndex <= 1 GB);\n        if (ipIndex - m8Index <= LZ4_DISTANCE_MAX) {\n            const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + l8DictMatchIndex;\n            const size_t safeLen = MIN(lDictEndIndex - l8DictMatchIndex, (size_t)(iHighLimit - ip));\n            int mlt = (int)LZ4_count(ip, matchPtr, ip + safeLen);\n            if (mlt >= MINMATCH) {\n                LZ4HC_match_t md;\n                DEBUGLOG(7, \"Found long ExtDict match of len=%u\", mlt);\n                md.len = mlt;\n                md.off = (int)(ipIndex - m8Index);\n                md.back = 0;\n                return md;\n            }\n        }\n    }\n\n    /* search for short match second */\n    {   U32 l4DictMatchIndex = hash4Table[LZ4MID_hash4Ptr(ip)];\n        U32 m4Index = l4DictMatchIndex + gDictEndIndex - (U32)lDictEndIndex;\n        if (ipIndex - m4Index <= LZ4_DISTANCE_MAX) {\n            const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + l4DictMatchIndex;\n            const size_t safeLen = MIN(lDictEndIndex - l4DictMatchIndex, (size_t)(iHighLimit - ip));\n            int mlt = (int)LZ4_count(ip, matchPtr, ip + safeLen);\n            if (mlt >= MINMATCH) {\n                LZ4HC_match_t md;\n                DEBUGLOG(7, \"Found short ExtDict match of len=%u\", mlt);\n                md.len = mlt;\n                md.off = (int)(ipIndex - m4Index);\n                md.back = 0;\n                return md;\n            }\n        }\n    }\n\n    /* nothing found */\n    {   LZ4HC_match_t const md = {0, 0, 0 };\n        return md;\n    }\n}\n\n/**************************************\n*  Mid Compression (level 2)\n**************************************/\n\nLZ4_FORCE_INLINE void\nLZ4MID_addPosition(U32* hTable, U32 hValue, U32 index)\n{\n    hTable[hValue] = index;\n}\n\n#define ADDPOS8(_p, _idx) LZ4MID_addPosition(hash8Table, LZ4MID_hash8Ptr(_p), _idx)\n#define ADDPOS4(_p, _idx) LZ4MID_addPosition(hash4Table, LZ4MID_hash4Ptr(_p), _idx)\n\n/* Fill hash tables with references into dictionary.\n * The resulting table is only exploitable by LZ4MID (level 2) */\nstatic void\nLZ4MID_fillHTable (LZ4HC_CCtx_internal* cctx, const void* dict, size_t size)\n{\n    U32* const hash4Table = cctx->hashTable;\n    U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE;\n    const BYTE* const prefixPtr = (const BYTE*)dict;\n    U32 const prefixIdx = cctx->dictLimit;\n    U32 const target = prefixIdx + (U32)size - LZ4MID_HASHSIZE;\n    U32 idx = cctx->nextToUpdate;\n    assert(dict == cctx->prefixStart);\n    DEBUGLOG(4, \"LZ4MID_fillHTable (size:%zu)\", size);\n    if (size <= LZ4MID_HASHSIZE)\n        return;\n\n    for (; idx < target; idx += 3) {\n        ADDPOS4(prefixPtr+idx-prefixIdx, idx);\n        ADDPOS8(prefixPtr+idx+1-prefixIdx, idx+1);\n    }\n\n    idx = (size > 32 KB + LZ4MID_HASHSIZE) ? target - 32 KB : cctx->nextToUpdate;\n    for (; idx < target; idx += 1) {\n        ADDPOS8(prefixPtr+idx-prefixIdx, idx);\n    }\n\n    cctx->nextToUpdate = target;\n}\n\nstatic LZ4MID_searchIntoDict_f select_searchDict_function(const LZ4HC_CCtx_internal* dictCtx)\n{\n    if (dictCtx == NULL) return NULL;\n    if (LZ4HC_getCLevelParams(dictCtx->compressionLevel).strat == lz4mid)\n        return LZ4MID_searchExtDict;\n    return LZ4MID_searchHCDict;\n}\n\nstatic int LZ4MID_compress (\n    LZ4HC_CCtx_internal* const ctx,\n    const char* const src,\n    char* const dst,\n    int* srcSizePtr,\n    int const maxOutputSize,\n    const limitedOutput_directive limit,\n    const dictCtx_directive dict\n    )\n{\n    U32* const hash4Table = ctx->hashTable;\n    U32* const hash8Table = hash4Table + LZ4MID_HASHTABLESIZE;\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + *srcSizePtr;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n    const BYTE* const ilimit = (iend - LZ4MID_HASHSIZE);\n    BYTE* op = (BYTE*)dst;\n    BYTE* oend = op + maxOutputSize;\n\n    const BYTE* const prefixPtr = ctx->prefixStart;\n    const U32 prefixIdx = ctx->dictLimit;\n    const U32 ilimitIdx = (U32)(ilimit - prefixPtr) + prefixIdx;\n    const BYTE* const dictStart = ctx->dictStart;\n    const U32 dictIdx = ctx->lowLimit;\n    const U32 gDictEndIndex = ctx->lowLimit;\n    const LZ4MID_searchIntoDict_f searchIntoDict = (dict == usingDictCtxHc) ? select_searchDict_function(ctx->dictCtx) : NULL;\n    unsigned matchLength;\n    unsigned matchDistance;\n\n    /* input sanitization */\n    DEBUGLOG(5, \"LZ4MID_compress (%i bytes)\", *srcSizePtr);\n    if (dict == usingDictCtxHc) DEBUGLOG(5, \"usingDictCtxHc\");\n    assert(*srcSizePtr >= 0);\n    if (*srcSizePtr) assert(src != NULL);\n    if (maxOutputSize) assert(dst != NULL);\n    if (*srcSizePtr < 0) return 0;  /* invalid */\n    if (maxOutputSize < 0) return 0; /* invalid */\n    if (*srcSizePtr > LZ4_MAX_INPUT_SIZE) {\n        /* forbidden: no input is allowed to be that large */\n        return 0;\n    }\n    if (limit == fillOutput) oend -= LASTLITERALS;  /* Hack for support LZ4 format restriction */\n    if (*srcSizePtr < LZ4_minLength)\n        goto _lz4mid_last_literals;  /* Input too small, no compression (all literals) */\n\n    /* main loop */\n    while (ip <= mflimit) {\n        const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;\n        /* search long match */\n        {   U32 const h8 = LZ4MID_hash8Ptr(ip);\n            U32 const pos8 = hash8Table[h8];\n            assert(h8 < LZ4MID_HASHTABLESIZE);\n            assert(pos8 < ipIndex);\n            LZ4MID_addPosition(hash8Table, h8, ipIndex);\n            if (ipIndex - pos8 <= LZ4_DISTANCE_MAX) {\n                /* match candidate found */\n                if (pos8 >= prefixIdx) {\n                    const BYTE* const matchPtr = prefixPtr + pos8 - prefixIdx;\n                    assert(matchPtr < ip);\n                    matchLength = LZ4_count(ip, matchPtr, matchlimit);\n                    if (matchLength >= MINMATCH) {\n                        DEBUGLOG(7, \"found long match at pos %u (len=%u)\", pos8, matchLength);\n                        matchDistance = ipIndex - pos8;\n                        goto _lz4mid_encode_sequence;\n                    }\n                } else {\n                    if (pos8 >= dictIdx) {\n                        /* extDict match candidate */\n                        const BYTE* const matchPtr = dictStart + (pos8 - dictIdx);\n                        const size_t safeLen = MIN(prefixIdx - pos8, (size_t)(matchlimit - ip));\n                        matchLength = LZ4_count(ip, matchPtr, ip + safeLen);\n                        if (matchLength >= MINMATCH) {\n                            DEBUGLOG(7, \"found long match at ExtDict pos %u (len=%u)\", pos8, matchLength);\n                            matchDistance = ipIndex - pos8;\n                            goto _lz4mid_encode_sequence;\n                        }\n                    }\n                }\n        }   }\n        /* search short match */\n        {   U32 const h4 = LZ4MID_hash4Ptr(ip);\n            U32 const pos4 = hash4Table[h4];\n            assert(h4 < LZ4MID_HASHTABLESIZE);\n            assert(pos4 < ipIndex);\n            LZ4MID_addPosition(hash4Table, h4, ipIndex);\n            if (ipIndex - pos4 <= LZ4_DISTANCE_MAX) {\n                /* match candidate found */\n                if (pos4 >= prefixIdx) {\n                /* only search within prefix */\n                    const BYTE* const matchPtr = prefixPtr + (pos4 - prefixIdx);\n                    assert(matchPtr < ip);\n                    assert(matchPtr >= prefixPtr);\n                    matchLength = LZ4_count(ip, matchPtr, matchlimit);\n                    if (matchLength >= MINMATCH) {\n                        /* short match found, let's just check ip+1 for longer */\n                        U32 const h8 = LZ4MID_hash8Ptr(ip+1);\n                        U32 const pos8 = hash8Table[h8];\n                        U32 const m2Distance = ipIndex + 1 - pos8;\n                        matchDistance = ipIndex - pos4;\n                        if ( m2Distance <= LZ4_DISTANCE_MAX\n                        && pos8 >= prefixIdx /* only search within prefix */\n                        && likely(ip < mflimit)\n                        ) {\n                            const BYTE* const m2Ptr = prefixPtr + (pos8 - prefixIdx);\n                            unsigned ml2 = LZ4_count(ip+1, m2Ptr, matchlimit);\n                            if (ml2 > matchLength) {\n                                LZ4MID_addPosition(hash8Table, h8, ipIndex+1);\n                                ip++;\n                                matchLength = ml2;\n                                matchDistance = m2Distance;\n                        }   }\n                        goto _lz4mid_encode_sequence;\n                    }\n                } else {\n                    if (pos4 >= dictIdx) {\n                        /* extDict match candidate */\n                        const BYTE* const matchPtr = dictStart + (pos4 - dictIdx);\n                        const size_t safeLen = MIN(prefixIdx - pos4, (size_t)(matchlimit - ip));\n                        matchLength = LZ4_count(ip, matchPtr, ip + safeLen);\n                        if (matchLength >= MINMATCH) {\n                            DEBUGLOG(7, \"found match at ExtDict pos %u (len=%u)\", pos4, matchLength);\n                            matchDistance = ipIndex - pos4;\n                            goto _lz4mid_encode_sequence;\n                        }\n                    }\n                }\n        }   }\n        /* no match found in prefix */\n        if ( (dict == usingDictCtxHc)\n          && (ipIndex - gDictEndIndex < LZ4_DISTANCE_MAX - 8) ) {\n            /* search a match into external dictionary */\n            LZ4HC_match_t dMatch = searchIntoDict(ip, ipIndex,\n                    matchlimit,\n                    ctx->dictCtx, gDictEndIndex);\n            if (dMatch.len >= MINMATCH) {\n                DEBUGLOG(7, \"found Dictionary match (offset=%i)\", dMatch.off);\n                assert(dMatch.back == 0);\n                matchLength = (unsigned)dMatch.len;\n                matchDistance = (unsigned)dMatch.off;\n                goto _lz4mid_encode_sequence;\n            }\n        }\n        /* no match found */\n        ip += 1 + ((ip-anchor) >> 9);  /* skip faster over incompressible data */\n        continue;\n\n_lz4mid_encode_sequence:\n        /* catch back */\n        while (((ip > anchor) & ((U32)(ip-prefixPtr) > matchDistance)) && (unlikely(ip[-1] == ip[-(int)matchDistance-1]))) {\n            ip--;  matchLength++;\n        };\n\n        /* fill table with beginning of match */\n        ADDPOS8(ip+1, ipIndex+1);\n        ADDPOS8(ip+2, ipIndex+2);\n        ADDPOS4(ip+1, ipIndex+1);\n\n        /* encode */\n        {   BYTE* const saved_op = op;\n            /* LZ4HC_encodeSequence always updates @op; on success, it updates @ip and @anchor */\n            if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),\n                    (int)matchLength, (int)matchDistance,\n                    limit, oend) ) {\n                op = saved_op;  /* restore @op value before failed LZ4HC_encodeSequence */\n                goto _lz4mid_dest_overflow;\n            }\n        }\n\n        /* fill table with end of match */\n        {   U32 endMatchIdx = (U32)(ip-prefixPtr) + prefixIdx;\n            U32 pos_m2 = endMatchIdx - 2;\n            if (pos_m2 < ilimitIdx) {\n                if (likely(ip - prefixPtr > 5)) {\n                    ADDPOS8(ip-5, endMatchIdx - 5);\n                }\n                ADDPOS8(ip-3, endMatchIdx - 3);\n                ADDPOS8(ip-2, endMatchIdx - 2);\n                ADDPOS4(ip-2, endMatchIdx - 2);\n                ADDPOS4(ip-1, endMatchIdx - 1);\n            }\n        }\n    }\n\n_lz4mid_last_literals:\n    /* Encode Last Literals */\n    {   size_t lastRunSize = (size_t)(iend - anchor);  /* literals */\n        size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;\n        size_t const totalSize = 1 + llAdd + lastRunSize;\n        if (limit == fillOutput) oend += LASTLITERALS;  /* restore correct value */\n        if (limit && (op + totalSize > oend)) {\n            if (limit == limitedOutput) return 0;  /* not enough space in @dst */\n            /* adapt lastRunSize to fill 'dest' */\n            lastRunSize  = (size_t)(oend - op) - 1 /*token*/;\n            llAdd = (lastRunSize + 256 - RUN_MASK) / 256;\n            lastRunSize -= llAdd;\n        }\n        DEBUGLOG(6, \"Final literal run : %i literals\", (int)lastRunSize);\n        ip = anchor + lastRunSize;  /* can be != iend if limit==fillOutput */\n\n        if (lastRunSize >= RUN_MASK) {\n            size_t accumulator = lastRunSize - RUN_MASK;\n            *op++ = (RUN_MASK << ML_BITS);\n            for(; accumulator >= 255 ; accumulator -= 255)\n                *op++ = 255;\n            *op++ = (BYTE) accumulator;\n        } else {\n            *op++ = (BYTE)(lastRunSize << ML_BITS);\n        }\n        assert(lastRunSize <= (size_t)(oend - op));\n        LZ4_memcpy(op, anchor, lastRunSize);\n        op += lastRunSize;\n    }\n\n    /* End */\n    DEBUGLOG(5, \"compressed %i bytes into %i bytes\", *srcSizePtr, (int)((char*)op - dst));\n    assert(ip >= (const BYTE*)src);\n    assert(ip <= iend);\n    *srcSizePtr = (int)(ip - (const BYTE*)src);\n    assert((char*)op >= dst);\n    assert(op <= oend);\n    assert((char*)op - dst < INT_MAX);\n    return (int)((char*)op - dst);\n\n_lz4mid_dest_overflow:\n    if (limit == fillOutput) {\n        /* Assumption : @ip, @anchor, @optr and @matchLength must be set correctly */\n        size_t const ll = (size_t)(ip - anchor);\n        size_t const ll_addbytes = (ll + 240) / 255;\n        size_t const ll_totalCost = 1 + ll_addbytes + ll;\n        BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */\n        DEBUGLOG(6, \"Last sequence is overflowing : %u literals, %u remaining space\",\n                (unsigned)ll, (unsigned)(oend-op));\n        if (op + ll_totalCost <= maxLitPos) {\n            /* ll validated; now adjust match length */\n            size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));\n            size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);\n            assert(maxMlSize < INT_MAX);\n            if ((size_t)matchLength > maxMlSize) matchLength= (unsigned)maxMlSize;\n            if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + matchLength >= MFLIMIT) {\n            DEBUGLOG(6, \"Let's encode a last sequence (ll=%u, ml=%u)\", (unsigned)ll, matchLength);\n                LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),\n                        (int)matchLength, (int)matchDistance,\n                        notLimited, oend);\n        }   }\n        DEBUGLOG(6, \"Let's finish with a run of literals (%u bytes left)\", (unsigned)(oend-op));\n        goto _lz4mid_last_literals;\n    }\n    /* compression failed */\n    return 0;\n}\n\n\n/**************************************\n*  HC Compression - Search\n**************************************/\n\n/* Update chains up to ip (excluded) */\nLZ4_FORCE_INLINE void LZ4HC_Insert (LZ4HC_CCtx_internal* hc4, const BYTE* ip)\n{\n    U16* const chainTable = hc4->chainTable;\n    U32* const hashTable  = hc4->hashTable;\n    const BYTE* const prefixPtr = hc4->prefixStart;\n    U32 const prefixIdx = hc4->dictLimit;\n    U32 const target = (U32)(ip - prefixPtr) + prefixIdx;\n    U32 idx = hc4->nextToUpdate;\n    assert(ip >= prefixPtr);\n    assert(target >= prefixIdx);\n\n    while (idx < target) {\n        U32 const h = LZ4HC_hashPtr(prefixPtr+idx-prefixIdx);\n        size_t delta = idx - hashTable[h];\n        if (delta>LZ4_DISTANCE_MAX) delta = LZ4_DISTANCE_MAX;\n        DELTANEXTU16(chainTable, idx) = (U16)delta;\n        hashTable[h] = idx;\n        idx++;\n    }\n\n    hc4->nextToUpdate = target;\n}\n\n#if defined(_MSC_VER)\n#  define LZ4HC_rotl32(x,r) _rotl(x,r)\n#else\n#  define LZ4HC_rotl32(x,r) ((x << r) | (x >> (32 - r)))\n#endif\n\n\nstatic U32 LZ4HC_rotatePattern(size_t const rotate, U32 const pattern)\n{\n    size_t const bitsToRotate = (rotate & (sizeof(pattern) - 1)) << 3;\n    if (bitsToRotate == 0) return pattern;\n    return LZ4HC_rotl32(pattern, (int)bitsToRotate);\n}\n\n/* LZ4HC_countPattern() :\n * pattern32 must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) */\nstatic unsigned\nLZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32)\n{\n    const BYTE* const iStart = ip;\n    reg_t const pattern = (sizeof(pattern)==8) ?\n        (reg_t)pattern32 + (((reg_t)pattern32) << (sizeof(pattern)*4)) : pattern32;\n\n    while (likely(ip < iEnd-(sizeof(pattern)-1))) {\n        reg_t const diff = LZ4_read_ARCH(ip) ^ pattern;\n        if (!diff) { ip+=sizeof(pattern); continue; }\n        ip += LZ4_NbCommonBytes(diff);\n        return (unsigned)(ip - iStart);\n    }\n\n    if (LZ4_isLittleEndian()) {\n        reg_t patternByte = pattern;\n        while ((ip<iEnd) && (*ip == (BYTE)patternByte)) {\n            ip++; patternByte >>= 8;\n        }\n    } else {  /* big endian */\n        U32 bitOffset = (sizeof(pattern)*8) - 8;\n        while (ip < iEnd) {\n            BYTE const byte = (BYTE)(pattern >> bitOffset);\n            if (*ip != byte) break;\n            ip ++; bitOffset -= 8;\n    }   }\n\n    return (unsigned)(ip - iStart);\n}\n\n/* LZ4HC_reverseCountPattern() :\n * pattern must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!)\n * read using natural platform endianness */\nstatic unsigned\nLZ4HC_reverseCountPattern(const BYTE* ip, const BYTE* const iLow, U32 pattern)\n{\n    const BYTE* const iStart = ip;\n\n    while (likely(ip >= iLow+4)) {\n        if (LZ4_read32(ip-4) != pattern) break;\n        ip -= 4;\n    }\n    {   const BYTE* bytePtr = (const BYTE*)(&pattern) + 3; /* works for any endianness */\n        while (likely(ip>iLow)) {\n            if (ip[-1] != *bytePtr) break;\n            ip--; bytePtr--;\n    }   }\n    return (unsigned)(iStart - ip);\n}\n\n/* LZ4HC_protectDictEnd() :\n * Checks if the match is in the last 3 bytes of the dictionary, so reading the\n * 4 byte MINMATCH would overflow.\n * @returns true if the match index is okay.\n */\nstatic int LZ4HC_protectDictEnd(U32 const dictLimit, U32 const matchIndex)\n{\n    return ((U32)((dictLimit - 1) - matchIndex) >= 3);\n}\n\ntypedef enum { rep_untested, rep_not, rep_confirmed } repeat_state_e;\ntypedef enum { favorCompressionRatio=0, favorDecompressionSpeed } HCfavor_e;\n\n\nLZ4_FORCE_INLINE LZ4HC_match_t\nLZ4HC_InsertAndGetWiderMatch (\n        LZ4HC_CCtx_internal* const hc4,\n        const BYTE* const ip,\n        const BYTE* const iLowLimit, const BYTE* const iHighLimit,\n        int longest,\n        const int maxNbAttempts,\n        const int patternAnalysis, const int chainSwap,\n        const dictCtx_directive dict,\n        const HCfavor_e favorDecSpeed)\n{\n    U16* const chainTable = hc4->chainTable;\n    U32* const hashTable = hc4->hashTable;\n    const LZ4HC_CCtx_internal* const dictCtx = hc4->dictCtx;\n    const BYTE* const prefixPtr = hc4->prefixStart;\n    const U32 prefixIdx = hc4->dictLimit;\n    const U32 ipIndex = (U32)(ip - prefixPtr) + prefixIdx;\n    const int withinStartDistance = (hc4->lowLimit + (LZ4_DISTANCE_MAX + 1) > ipIndex);\n    const U32 lowestMatchIndex = (withinStartDistance) ? hc4->lowLimit : ipIndex - LZ4_DISTANCE_MAX;\n    const BYTE* const dictStart = hc4->dictStart;\n    const U32 dictIdx = hc4->lowLimit;\n    const BYTE* const dictEnd = dictStart + prefixIdx - dictIdx;\n    int const lookBackLength = (int)(ip-iLowLimit);\n    int nbAttempts = maxNbAttempts;\n    U32 matchChainPos = 0;\n    U32 const pattern = LZ4_read32(ip);\n    U32 matchIndex;\n    repeat_state_e repeat = rep_untested;\n    size_t srcPatternLength = 0;\n    int offset = 0, sBack = 0;\n\n    DEBUGLOG(7, \"LZ4HC_InsertAndGetWiderMatch\");\n    /* First Match */\n    LZ4HC_Insert(hc4, ip);  /* insert all prior positions up to ip (excluded) */\n    matchIndex = hashTable[LZ4HC_hashPtr(ip)];\n    DEBUGLOG(7, \"First candidate match for pos %u found at index %u / %u (lowestMatchIndex)\",\n                ipIndex, matchIndex, lowestMatchIndex);\n\n    while ((matchIndex>=lowestMatchIndex) && (nbAttempts>0)) {\n        int matchLength=0;\n        nbAttempts--;\n        assert(matchIndex < ipIndex);\n        if (favorDecSpeed && (ipIndex - matchIndex < 8)) {\n            /* do nothing:\n             * favorDecSpeed intentionally skips matches with offset < 8 */\n        } else if (matchIndex >= prefixIdx) {   /* within current Prefix */\n            const BYTE* const matchPtr = prefixPtr + (matchIndex - prefixIdx);\n            assert(matchPtr < ip);\n            assert(longest >= 1);\n            if (LZ4_read16(iLowLimit + longest - 1) == LZ4_read16(matchPtr - lookBackLength + longest - 1)) {\n                if (LZ4_read32(matchPtr) == pattern) {\n                    int const back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, prefixPtr) : 0;\n                    matchLength = MINMATCH + (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);\n                    matchLength -= back;\n                    if (matchLength > longest) {\n                        longest = matchLength;\n                        offset = (int)(ipIndex - matchIndex);\n                        sBack = back;\n                        DEBUGLOG(7, \"Found match of len=%i within prefix, offset=%i, back=%i\", longest, offset, -back);\n            }   }   }\n        } else {   /* lowestMatchIndex <= matchIndex < dictLimit : within Ext Dict */\n            const BYTE* const matchPtr = dictStart + (matchIndex - dictIdx);\n            assert(matchIndex >= dictIdx);\n            if ( likely(matchIndex <= prefixIdx - 4)\n              && (LZ4_read32(matchPtr) == pattern) ) {\n                int back = 0;\n                const BYTE* vLimit = ip + (prefixIdx - matchIndex);\n                if (vLimit > iHighLimit) vLimit = iHighLimit;\n                matchLength = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+matchLength == vLimit) && (vLimit < iHighLimit))\n                    matchLength += LZ4_count(ip+matchLength, prefixPtr, iHighLimit);\n                back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictStart) : 0;\n                matchLength -= back;\n                if (matchLength > longest) {\n                    longest = matchLength;\n                    offset = (int)(ipIndex - matchIndex);\n                    sBack = back;\n                    DEBUGLOG(7, \"Found match of len=%i within dict, offset=%i, back=%i\", longest, offset, -back);\n        }   }   }\n\n        if (chainSwap && matchLength==longest) {   /* better match => select a better chain */\n            assert(lookBackLength==0);   /* search forward only */\n            if (matchIndex + (U32)longest <= ipIndex) {\n                int const kTrigger = 4;\n                U32 distanceToNextMatch = 1;\n                int const end = longest - MINMATCH + 1;\n                int step = 1;\n                int accel = 1 << kTrigger;\n                int pos;\n                for (pos = 0; pos < end; pos += step) {\n                    U32 const candidateDist = DELTANEXTU16(chainTable, matchIndex + (U32)pos);\n                    step = (accel++ >> kTrigger);\n                    if (candidateDist > distanceToNextMatch) {\n                        distanceToNextMatch = candidateDist;\n                        matchChainPos = (U32)pos;\n                        accel = 1 << kTrigger;\n                }   }\n                if (distanceToNextMatch > 1) {\n                    if (distanceToNextMatch > matchIndex) break;   /* avoid overflow */\n                    matchIndex -= distanceToNextMatch;\n                    continue;\n        }   }   }\n\n        {   U32 const distNextMatch = DELTANEXTU16(chainTable, matchIndex);\n            if (patternAnalysis && distNextMatch==1 && matchChainPos==0) {\n                U32 const matchCandidateIdx = matchIndex-1;\n                /* may be a repeated pattern */\n                if (repeat == rep_untested) {\n                    if ( ((pattern & 0xFFFF) == (pattern >> 16))\n                      &  ((pattern & 0xFF)   == (pattern >> 24)) ) {\n                        DEBUGLOG(7, \"Repeat pattern detected, char %02X\", pattern >> 24);\n                        repeat = rep_confirmed;\n                        srcPatternLength = LZ4HC_countPattern(ip+sizeof(pattern), iHighLimit, pattern) + sizeof(pattern);\n                    } else {\n                        repeat = rep_not;\n                }   }\n                if ( (repeat == rep_confirmed) && (matchCandidateIdx >= lowestMatchIndex)\n                  && LZ4HC_protectDictEnd(prefixIdx, matchCandidateIdx) ) {\n                    const int extDict = matchCandidateIdx < prefixIdx;\n                    const BYTE* const matchPtr = extDict ? dictStart + (matchCandidateIdx - dictIdx) : prefixPtr + (matchCandidateIdx - prefixIdx);\n                    if (LZ4_read32(matchPtr) == pattern) {  /* good candidate */\n                        const BYTE* const iLimit = extDict ? dictEnd : iHighLimit;\n                        size_t forwardPatternLength = LZ4HC_countPattern(matchPtr+sizeof(pattern), iLimit, pattern) + sizeof(pattern);\n                        if (extDict && matchPtr + forwardPatternLength == iLimit) {\n                            U32 const rotatedPattern = LZ4HC_rotatePattern(forwardPatternLength, pattern);\n                            forwardPatternLength += LZ4HC_countPattern(prefixPtr, iHighLimit, rotatedPattern);\n                        }\n                        {   const BYTE* const lowestMatchPtr = extDict ? dictStart : prefixPtr;\n                            size_t backLength = LZ4HC_reverseCountPattern(matchPtr, lowestMatchPtr, pattern);\n                            size_t currentSegmentLength;\n                            if (!extDict\n                              && matchPtr - backLength == prefixPtr\n                              && dictIdx < prefixIdx) {\n                                U32 const rotatedPattern = LZ4HC_rotatePattern((U32)(-(int)backLength), pattern);\n                                backLength += LZ4HC_reverseCountPattern(dictEnd, dictStart, rotatedPattern);\n                            }\n                            /* Limit backLength not go further than lowestMatchIndex */\n                            backLength = matchCandidateIdx - MAX(matchCandidateIdx - (U32)backLength, lowestMatchIndex);\n                            assert(matchCandidateIdx - backLength >= lowestMatchIndex);\n                            currentSegmentLength = backLength + forwardPatternLength;\n                            /* Adjust to end of pattern if the source pattern fits, otherwise the beginning of the pattern */\n                            if ( (currentSegmentLength >= srcPatternLength)   /* current pattern segment large enough to contain full srcPatternLength */\n                              && (forwardPatternLength <= srcPatternLength) ) { /* haven't reached this position yet */\n                                U32 const newMatchIndex = matchCandidateIdx + (U32)forwardPatternLength - (U32)srcPatternLength;  /* best position, full pattern, might be followed by more match */\n                                if (LZ4HC_protectDictEnd(prefixIdx, newMatchIndex))\n                                    matchIndex = newMatchIndex;\n                                else {\n                                    /* Can only happen if started in the prefix */\n                                    assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);\n                                    matchIndex = prefixIdx;\n                                }\n                            } else {\n                                U32 const newMatchIndex = matchCandidateIdx - (U32)backLength;   /* farthest position in current segment, will find a match of length currentSegmentLength + maybe some back */\n                                if (!LZ4HC_protectDictEnd(prefixIdx, newMatchIndex)) {\n                                    assert(newMatchIndex >= prefixIdx - 3 && newMatchIndex < prefixIdx && !extDict);\n                                    matchIndex = prefixIdx;\n                                } else {\n                                    matchIndex = newMatchIndex;\n                                    if (lookBackLength==0) {  /* no back possible */\n                                        size_t const maxML = MIN(currentSegmentLength, srcPatternLength);\n                                        if ((size_t)longest < maxML) {\n                                            assert(prefixPtr - prefixIdx + matchIndex != ip);\n                                            if ((size_t)(ip - prefixPtr) + prefixIdx - matchIndex > LZ4_DISTANCE_MAX) break;\n                                            assert(maxML < 2 GB);\n                                            longest = (int)maxML;\n                                            offset = (int)(ipIndex - matchIndex);\n                                            assert(sBack == 0);\n                                            DEBUGLOG(7, \"Found repeat pattern match of len=%i, offset=%i\", longest, offset);\n                                        }\n                                        {   U32 const distToNextPattern = DELTANEXTU16(chainTable, matchIndex);\n                                            if (distToNextPattern > matchIndex) break;  /* avoid overflow */\n                                            matchIndex -= distToNextPattern;\n                        }   }   }   }   }\n                        continue;\n                }   }\n        }   }   /* PA optimization */\n\n        /* follow current chain */\n        matchIndex -= DELTANEXTU16(chainTable, matchIndex + matchChainPos);\n\n    }  /* while ((matchIndex>=lowestMatchIndex) && (nbAttempts)) */\n\n    if ( dict == usingDictCtxHc\n      && nbAttempts > 0\n      && withinStartDistance) {\n        size_t const dictEndOffset = (size_t)(dictCtx->end - dictCtx->prefixStart) + dictCtx->dictLimit;\n        U32 dictMatchIndex = dictCtx->hashTable[LZ4HC_hashPtr(ip)];\n        assert(dictEndOffset <= 1 GB);\n        matchIndex = dictMatchIndex + lowestMatchIndex - (U32)dictEndOffset;\n        if (dictMatchIndex>0) DEBUGLOG(7, \"dictEndOffset = %zu, dictMatchIndex = %u => relative matchIndex = %i\", dictEndOffset, dictMatchIndex, (int)dictMatchIndex - (int)dictEndOffset);\n        while (ipIndex - matchIndex <= LZ4_DISTANCE_MAX && nbAttempts--) {\n            const BYTE* const matchPtr = dictCtx->prefixStart - dictCtx->dictLimit + dictMatchIndex;\n\n            if (LZ4_read32(matchPtr) == pattern) {\n                int mlt;\n                int back = 0;\n                const BYTE* vLimit = ip + (dictEndOffset - dictMatchIndex);\n                if (vLimit > iHighLimit) vLimit = iHighLimit;\n                mlt = (int)LZ4_count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;\n                back = lookBackLength ? LZ4HC_countBack(ip, matchPtr, iLowLimit, dictCtx->prefixStart) : 0;\n                mlt -= back;\n                if (mlt > longest) {\n                    longest = mlt;\n                    offset = (int)(ipIndex - matchIndex);\n                    sBack = back;\n                    DEBUGLOG(7, \"found match of length %i within extDictCtx\", longest);\n            }   }\n\n            {   U32 const nextOffset = DELTANEXTU16(dictCtx->chainTable, dictMatchIndex);\n                dictMatchIndex -= nextOffset;\n                matchIndex -= nextOffset;\n    }   }   }\n\n    {   LZ4HC_match_t md;\n        assert(longest >= 0);\n        md.len = longest;\n        md.off = offset;\n        md.back = sBack;\n        return md;\n    }\n}\n\nLZ4_FORCE_INLINE LZ4HC_match_t\nLZ4HC_InsertAndFindBestMatch(LZ4HC_CCtx_internal* const hc4,   /* Index table will be updated */\n                       const BYTE* const ip, const BYTE* const iLimit,\n                       const int maxNbAttempts,\n                       const int patternAnalysis,\n                       const dictCtx_directive dict)\n{\n    DEBUGLOG(7, \"LZ4HC_InsertAndFindBestMatch\");\n    /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),\n     * but this won't be the case here, as we define iLowLimit==ip,\n     * so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */\n    return LZ4HC_InsertAndGetWiderMatch(hc4, ip, ip, iLimit, MINMATCH-1, maxNbAttempts, patternAnalysis, 0 /*chainSwap*/, dict, favorCompressionRatio);\n}\n\n\nLZ4_FORCE_INLINE int LZ4HC_compress_hashChain (\n    LZ4HC_CCtx_internal* const ctx,\n    const char* const source,\n    char* const dest,\n    int* srcSizePtr,\n    int const maxOutputSize,\n    int maxNbAttempts,\n    const limitedOutput_directive limit,\n    const dictCtx_directive dict\n    )\n{\n    const int inputSize = *srcSizePtr;\n    const int patternAnalysis = (maxNbAttempts > 128);   /* levels 9+ */\n\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + inputSize;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    BYTE* optr = (BYTE*) dest;\n    BYTE* op = (BYTE*) dest;\n    BYTE* oend = op + maxOutputSize;\n\n    const BYTE* start0;\n    const BYTE* start2 = NULL;\n    const BYTE* start3 = NULL;\n    LZ4HC_match_t m0, m1, m2, m3;\n    const LZ4HC_match_t nomatch = {0, 0, 0};\n\n    /* init */\n    DEBUGLOG(5, \"LZ4HC_compress_hashChain (dict?=>%i)\", dict);\n    *srcSizePtr = 0;\n    if (limit == fillOutput) oend -= LASTLITERALS;                  /* Hack for support LZ4 format restriction */\n    if (inputSize < LZ4_minLength) goto _last_literals;             /* Input too small, no compression (all literals) */\n\n    /* Main Loop */\n    while (ip <= mflimit) {\n        m1 = LZ4HC_InsertAndFindBestMatch(ctx, ip, matchlimit, maxNbAttempts, patternAnalysis, dict);\n        if (m1.len<MINMATCH) { ip++; continue; }\n\n        /* saved, in case we would skip too much */\n        start0 = ip; m0 = m1;\n\n_Search2:\n        DEBUGLOG(7, \"_Search2 (currently found match of size %i)\", m1.len);\n        if (ip+m1.len <= mflimit) {\n            start2 = ip + m1.len - 2;\n            m2 = LZ4HC_InsertAndGetWiderMatch(ctx,\n                            start2, ip + 0, matchlimit, m1.len,\n                            maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);\n            start2 += m2.back;\n        } else {\n            m2 = nomatch;  /* do not search further */\n        }\n\n        if (m2.len <= m1.len) { /* No better match => encode ML1 immediately */\n            optr = op;\n            if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),\n                    m1.len, m1.off,\n                    limit, oend) )\n                goto _dest_overflow;\n            continue;\n        }\n\n        if (start0 < ip) {   /* first match was skipped at least once */\n            if (start2 < ip + m0.len) {  /* squeezing ML1 between ML0(original ML1) and ML2 */\n                ip = start0; m1 = m0;  /* restore initial Match1 */\n        }   }\n\n        /* Here, start0==ip */\n        if ((start2 - ip) < 3) {  /* First Match too small : removed */\n            ip = start2;\n            m1 = m2;\n            goto _Search2;\n        }\n\n_Search3:\n        if ((start2 - ip) < OPTIMAL_ML) {\n            int correction;\n            int new_ml = m1.len;\n            if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;\n            if (ip+new_ml > start2 + m2.len - MINMATCH)\n                new_ml = (int)(start2 - ip) + m2.len - MINMATCH;\n            correction = new_ml - (int)(start2 - ip);\n            if (correction > 0) {\n                start2 += correction;\n                m2.len -= correction;\n            }\n        }\n\n        if (start2 + m2.len <= mflimit) {\n            start3 = start2 + m2.len - 3;\n            m3 = LZ4HC_InsertAndGetWiderMatch(ctx,\n                            start3, start2, matchlimit, m2.len,\n                            maxNbAttempts, patternAnalysis, 0, dict, favorCompressionRatio);\n            start3 += m3.back;\n        } else {\n            m3 = nomatch;  /* do not search further */\n        }\n\n        if (m3.len <= m2.len) {  /* No better match => encode ML1 and ML2 */\n            /* ip & ref are known; Now for ml */\n            if (start2 < ip+m1.len) m1.len = (int)(start2 - ip);\n            /* Now, encode 2 sequences */\n            optr = op;\n            if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),\n                    m1.len, m1.off,\n                    limit, oend) )\n                goto _dest_overflow;\n            ip = start2;\n            optr = op;\n            if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),\n                    m2.len, m2.off,\n                    limit, oend) ) {\n                m1 = m2;\n                goto _dest_overflow;\n            }\n            continue;\n        }\n\n        if (start3 < ip+m1.len+3) {  /* Not enough space for match 2 : remove it */\n            if (start3 >= (ip+m1.len)) {  /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */\n                if (start2 < ip+m1.len) {\n                    int correction = (int)(ip+m1.len - start2);\n                    start2 += correction;\n                    m2.len -= correction;\n                    if (m2.len < MINMATCH) {\n                        start2 = start3;\n                        m2 = m3;\n                    }\n                }\n\n                optr = op;\n                if (LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),\n                        m1.len, m1.off,\n                        limit, oend) )\n                    goto _dest_overflow;\n                ip  = start3;\n                m1 = m3;\n\n                start0 = start2;\n                m0 = m2;\n                goto _Search2;\n            }\n\n            start2 = start3;\n            m2 = m3;\n            goto _Search3;\n        }\n\n        /*\n        * OK, now we have 3 ascending matches;\n        * let's write the first one ML1.\n        * ip & ref are known; Now decide ml.\n        */\n        if (start2 < ip+m1.len) {\n            if ((start2 - ip) < OPTIMAL_ML) {\n                int correction;\n                if (m1.len > OPTIMAL_ML) m1.len = OPTIMAL_ML;\n                if (ip + m1.len > start2 + m2.len - MINMATCH)\n                    m1.len = (int)(start2 - ip) + m2.len - MINMATCH;\n                correction = m1.len - (int)(start2 - ip);\n                if (correction > 0) {\n                    start2 += correction;\n                    m2.len -= correction;\n                }\n            } else {\n                m1.len = (int)(start2 - ip);\n            }\n        }\n        optr = op;\n        if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor),\n                m1.len, m1.off,\n                limit, oend) )\n            goto _dest_overflow;\n\n        /* ML2 becomes ML1 */\n        ip = start2; m1 = m2;\n\n        /* ML3 becomes ML2 */\n        start2 = start3; m2 = m3;\n\n        /* let's find a new ML3 */\n        goto _Search3;\n    }\n\n_last_literals:\n    /* Encode Last Literals */\n    {   size_t lastRunSize = (size_t)(iend - anchor);  /* literals */\n        size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;\n        size_t const totalSize = 1 + llAdd + lastRunSize;\n        if (limit == fillOutput) oend += LASTLITERALS;  /* restore correct value */\n        if (limit && (op + totalSize > oend)) {\n            if (limit == limitedOutput) return 0;\n            /* adapt lastRunSize to fill 'dest' */\n            lastRunSize  = (size_t)(oend - op) - 1 /*token*/;\n            llAdd = (lastRunSize + 256 - RUN_MASK) / 256;\n            lastRunSize -= llAdd;\n        }\n        DEBUGLOG(6, \"Final literal run : %i literals\", (int)lastRunSize);\n        ip = anchor + lastRunSize;  /* can be != iend if limit==fillOutput */\n\n        if (lastRunSize >= RUN_MASK) {\n            size_t accumulator = lastRunSize - RUN_MASK;\n            *op++ = (RUN_MASK << ML_BITS);\n            for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;\n            *op++ = (BYTE) accumulator;\n        } else {\n            *op++ = (BYTE)(lastRunSize << ML_BITS);\n        }\n        LZ4_memcpy(op, anchor, lastRunSize);\n        op += lastRunSize;\n    }\n\n    /* End */\n    *srcSizePtr = (int) (((const char*)ip) - source);\n    return (int) (((char*)op)-dest);\n\n_dest_overflow:\n    if (limit == fillOutput) {\n        /* Assumption : @ip, @anchor, @optr and @m1 must be set correctly */\n        size_t const ll = (size_t)(ip - anchor);\n        size_t const ll_addbytes = (ll + 240) / 255;\n        size_t const ll_totalCost = 1 + ll_addbytes + ll;\n        BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */\n        DEBUGLOG(6, \"Last sequence overflowing\");\n        op = optr;  /* restore correct out pointer */\n        if (op + ll_totalCost <= maxLitPos) {\n            /* ll validated; now adjust match length */\n            size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));\n            size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);\n            assert(maxMlSize < INT_MAX); assert(m1.len >= 0);\n            if ((size_t)m1.len > maxMlSize) m1.len = (int)maxMlSize;\n            if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + m1.len >= MFLIMIT) {\n                LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), m1.len, m1.off, notLimited, oend);\n        }   }\n        goto _last_literals;\n    }\n    /* compression failed */\n    return 0;\n}\n\n\nstatic int LZ4HC_compress_optimal( LZ4HC_CCtx_internal* ctx,\n    const char* const source, char* dst,\n    int* srcSizePtr, int dstCapacity,\n    int const nbSearches, size_t sufficient_len,\n    const limitedOutput_directive limit, int const fullUpdate,\n    const dictCtx_directive dict,\n    const HCfavor_e favorDecSpeed);\n\nLZ4_FORCE_INLINE int\nLZ4HC_compress_generic_internal (\n            LZ4HC_CCtx_internal* const ctx,\n            const char* const src,\n            char* const dst,\n            int* const srcSizePtr,\n            int const dstCapacity,\n            int cLevel,\n            const limitedOutput_directive limit,\n            const dictCtx_directive dict\n            )\n{\n    DEBUGLOG(5, \"LZ4HC_compress_generic_internal(src=%p, srcSize=%d)\",\n                src, *srcSizePtr);\n\n    if (limit == fillOutput && dstCapacity < 1) return 0;   /* Impossible to store anything */\n    if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0;  /* Unsupported input size (too large or negative) */\n\n    ctx->end += *srcSizePtr;\n    {   cParams_t const cParam = LZ4HC_getCLevelParams(cLevel);\n        HCfavor_e const favor = ctx->favorDecSpeed ? favorDecompressionSpeed : favorCompressionRatio;\n        int result;\n\n        if (cParam.strat == lz4mid) {\n            result = LZ4MID_compress(ctx,\n                                src, dst, srcSizePtr, dstCapacity,\n                                limit, dict);\n        } else if (cParam.strat == lz4hc) {\n            result = LZ4HC_compress_hashChain(ctx,\n                                src, dst, srcSizePtr, dstCapacity,\n                                cParam.nbSearches, limit, dict);\n        } else {\n            assert(cParam.strat == lz4opt);\n            result = LZ4HC_compress_optimal(ctx,\n                                src, dst, srcSizePtr, dstCapacity,\n                                cParam.nbSearches, cParam.targetLength, limit,\n                                cLevel >= LZ4HC_CLEVEL_MAX,   /* ultra mode */\n                                dict, favor);\n        }\n        if (result <= 0) ctx->dirty = 1;\n        return result;\n    }\n}\n\nstatic void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock);\n\nstatic int\nLZ4HC_compress_generic_noDictCtx (\n        LZ4HC_CCtx_internal* const ctx,\n        const char* const src,\n        char* const dst,\n        int* const srcSizePtr,\n        int const dstCapacity,\n        int cLevel,\n        limitedOutput_directive limit\n        )\n{\n    assert(ctx->dictCtx == NULL);\n    return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, noDictCtx);\n}\n\nstatic int isStateCompatible(const LZ4HC_CCtx_internal* ctx1, const LZ4HC_CCtx_internal* ctx2)\n{\n    int const isMid1 = LZ4HC_getCLevelParams(ctx1->compressionLevel).strat == lz4mid;\n    int const isMid2 = LZ4HC_getCLevelParams(ctx2->compressionLevel).strat == lz4mid;\n    return !(isMid1 ^ isMid2);\n}\n\nstatic int\nLZ4HC_compress_generic_dictCtx (\n        LZ4HC_CCtx_internal* const ctx,\n        const char* const src,\n        char* const dst,\n        int* const srcSizePtr,\n        int const dstCapacity,\n        int cLevel,\n        limitedOutput_directive limit\n        )\n{\n    const size_t position = (size_t)(ctx->end - ctx->prefixStart) + (ctx->dictLimit - ctx->lowLimit);\n    assert(ctx->dictCtx != NULL);\n    if (position >= 64 KB) {\n        ctx->dictCtx = NULL;\n        return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);\n    } else if (position == 0 && *srcSizePtr > 4 KB && isStateCompatible(ctx, ctx->dictCtx)) {\n        LZ4_memcpy(ctx, ctx->dictCtx, sizeof(LZ4HC_CCtx_internal));\n        LZ4HC_setExternalDict(ctx, (const BYTE *)src);\n        ctx->compressionLevel = (short)cLevel;\n        return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);\n    } else {\n        return LZ4HC_compress_generic_internal(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit, usingDictCtxHc);\n    }\n}\n\nstatic int\nLZ4HC_compress_generic (\n        LZ4HC_CCtx_internal* const ctx,\n        const char* const src,\n        char* const dst,\n        int* const srcSizePtr,\n        int const dstCapacity,\n        int cLevel,\n        limitedOutput_directive limit\n        )\n{\n    if (ctx->dictCtx == NULL) {\n        return LZ4HC_compress_generic_noDictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);\n    } else {\n        return LZ4HC_compress_generic_dictCtx(ctx, src, dst, srcSizePtr, dstCapacity, cLevel, limit);\n    }\n}\n\n\nint LZ4_sizeofStateHC(void) { return (int)sizeof(LZ4_streamHC_t); }\n\nstatic size_t LZ4_streamHC_t_alignment(void)\n{\n#if LZ4_ALIGN_TEST\n    typedef struct { char c; LZ4_streamHC_t t; } t_a;\n    return sizeof(t_a) - sizeof(LZ4_streamHC_t);\n#else\n    return 1;  /* effectively disabled */\n#endif\n}\n\n/* state is presumed correctly initialized,\n * in which case its size and alignment have already been validate */\nint LZ4_compress_HC_extStateHC_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)\n{\n    LZ4HC_CCtx_internal* const ctx = &((LZ4_streamHC_t*)state)->internal_donotuse;\n    if (!LZ4_isAligned(state, LZ4_streamHC_t_alignment())) return 0;\n    LZ4_resetStreamHC_fast((LZ4_streamHC_t*)state, compressionLevel);\n    LZ4HC_init_internal (ctx, (const BYTE*)src);\n    if (dstCapacity < LZ4_compressBound(srcSize))\n        return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, limitedOutput);\n    else\n        return LZ4HC_compress_generic (ctx, src, dst, &srcSize, dstCapacity, compressionLevel, notLimited);\n}\n\nint LZ4_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)\n{\n    LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx));\n    if (ctx==NULL) return 0;   /* init failure */\n    return LZ4_compress_HC_extStateHC_fastReset(state, src, dst, srcSize, dstCapacity, compressionLevel);\n}\n\nint LZ4_compress_HC(const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel)\n{\n    int cSize;\n#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1\n    LZ4_streamHC_t* const statePtr = (LZ4_streamHC_t*)ALLOC(sizeof(LZ4_streamHC_t));\n    if (statePtr==NULL) return 0;\n#else\n    LZ4_streamHC_t state;\n    LZ4_streamHC_t* const statePtr = &state;\n#endif\n    DEBUGLOG(5, \"LZ4_compress_HC\")\n    cSize = LZ4_compress_HC_extStateHC(statePtr, src, dst, srcSize, dstCapacity, compressionLevel);\n#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1\n    FREEMEM(statePtr);\n#endif\n    return cSize;\n}\n\n/* state is presumed sized correctly (>= sizeof(LZ4_streamHC_t)) */\nint LZ4_compress_HC_destSize(void* state, const char* source, char* dest, int* sourceSizePtr, int targetDestSize, int cLevel)\n{\n    LZ4_streamHC_t* const ctx = LZ4_initStreamHC(state, sizeof(*ctx));\n    if (ctx==NULL) return 0;   /* init failure */\n    LZ4HC_init_internal(&ctx->internal_donotuse, (const BYTE*) source);\n    LZ4_setCompressionLevel(ctx, cLevel);\n    return LZ4HC_compress_generic(&ctx->internal_donotuse, source, dest, sourceSizePtr, targetDestSize, cLevel, fillOutput);\n}\n\n\n\n/**************************************\n*  Streaming Functions\n**************************************/\n/* allocation */\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nLZ4_streamHC_t* LZ4_createStreamHC(void)\n{\n    LZ4_streamHC_t* const state =\n        (LZ4_streamHC_t*)ALLOC_AND_ZERO(sizeof(LZ4_streamHC_t));\n    if (state == NULL) return NULL;\n    LZ4_setCompressionLevel(state, LZ4HC_CLEVEL_DEFAULT);\n    return state;\n}\n\nint LZ4_freeStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr)\n{\n    DEBUGLOG(4, \"LZ4_freeStreamHC(%p)\", LZ4_streamHCPtr);\n    if (!LZ4_streamHCPtr) return 0;  /* support free on NULL */\n    FREEMEM(LZ4_streamHCPtr);\n    return 0;\n}\n#endif\n\n\nLZ4_streamHC_t* LZ4_initStreamHC (void* buffer, size_t size)\n{\n    LZ4_streamHC_t* const LZ4_streamHCPtr = (LZ4_streamHC_t*)buffer;\n    DEBUGLOG(4, \"LZ4_initStreamHC(%p, %u)\", buffer, (unsigned)size);\n    /* check conditions */\n    if (buffer == NULL) return NULL;\n    if (size < sizeof(LZ4_streamHC_t)) return NULL;\n    if (!LZ4_isAligned(buffer, LZ4_streamHC_t_alignment())) return NULL;\n    /* init */\n    { LZ4HC_CCtx_internal* const hcstate = &(LZ4_streamHCPtr->internal_donotuse);\n      MEM_INIT(hcstate, 0, sizeof(*hcstate)); }\n    LZ4_setCompressionLevel(LZ4_streamHCPtr, LZ4HC_CLEVEL_DEFAULT);\n    return LZ4_streamHCPtr;\n}\n\n/* just a stub */\nvoid LZ4_resetStreamHC (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)\n{\n    LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));\n    LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel);\n}\n\nvoid LZ4_resetStreamHC_fast (LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)\n{\n    LZ4HC_CCtx_internal* const s = &LZ4_streamHCPtr->internal_donotuse;\n    DEBUGLOG(5, \"LZ4_resetStreamHC_fast(%p, %d)\", LZ4_streamHCPtr, compressionLevel);\n    if (s->dirty) {\n        LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));\n    } else {\n        assert(s->end >= s->prefixStart);\n        s->dictLimit += (U32)(s->end - s->prefixStart);\n        s->prefixStart = NULL;\n        s->end = NULL;\n        s->dictCtx = NULL;\n    }\n    LZ4_setCompressionLevel(LZ4_streamHCPtr, compressionLevel);\n}\n\nvoid LZ4_setCompressionLevel(LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel)\n{\n    DEBUGLOG(5, \"LZ4_setCompressionLevel(%p, %d)\", LZ4_streamHCPtr, compressionLevel);\n    if (compressionLevel < 1) compressionLevel = LZ4HC_CLEVEL_DEFAULT;\n    if (compressionLevel > LZ4HC_CLEVEL_MAX) compressionLevel = LZ4HC_CLEVEL_MAX;\n    LZ4_streamHCPtr->internal_donotuse.compressionLevel = (short)compressionLevel;\n}\n\nvoid LZ4_favorDecompressionSpeed(LZ4_streamHC_t* LZ4_streamHCPtr, int favor)\n{\n    LZ4_streamHCPtr->internal_donotuse.favorDecSpeed = (favor!=0);\n}\n\n/* LZ4_loadDictHC() :\n * LZ4_streamHCPtr is presumed properly initialized */\nint LZ4_loadDictHC (LZ4_streamHC_t* LZ4_streamHCPtr,\n              const char* dictionary, int dictSize)\n{\n    LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;\n    cParams_t cp;\n    DEBUGLOG(4, \"LZ4_loadDictHC(ctx:%p, dict:%p, dictSize:%d, clevel=%d)\", LZ4_streamHCPtr, dictionary, dictSize, ctxPtr->compressionLevel);\n    assert(dictSize >= 0);\n    assert(LZ4_streamHCPtr != NULL);\n    if (dictSize > 64 KB) {\n        dictionary += (size_t)dictSize - 64 KB;\n        dictSize = 64 KB;\n    }\n    /* need a full initialization, there are bad side-effects when using resetFast() */\n    {   int const cLevel = ctxPtr->compressionLevel;\n        LZ4_initStreamHC(LZ4_streamHCPtr, sizeof(*LZ4_streamHCPtr));\n        LZ4_setCompressionLevel(LZ4_streamHCPtr, cLevel);\n        cp = LZ4HC_getCLevelParams(cLevel);\n    }\n    LZ4HC_init_internal (ctxPtr, (const BYTE*)dictionary);\n    ctxPtr->end = (const BYTE*)dictionary + dictSize;\n    if (cp.strat == lz4mid) {\n        LZ4MID_fillHTable (ctxPtr, dictionary, (size_t)dictSize);\n    } else {\n        if (dictSize >= LZ4HC_HASHSIZE) LZ4HC_Insert (ctxPtr, ctxPtr->end-3);\n    }\n    return dictSize;\n}\n\nvoid LZ4_attach_HC_dictionary(LZ4_streamHC_t *working_stream, const LZ4_streamHC_t *dictionary_stream) {\n    working_stream->internal_donotuse.dictCtx = dictionary_stream != NULL ? &(dictionary_stream->internal_donotuse) : NULL;\n}\n\n/* compression */\n\nstatic void LZ4HC_setExternalDict(LZ4HC_CCtx_internal* ctxPtr, const BYTE* newBlock)\n{\n    DEBUGLOG(4, \"LZ4HC_setExternalDict(%p, %p)\", ctxPtr, newBlock);\n    if ( (ctxPtr->end >= ctxPtr->prefixStart + 4)\n      && (LZ4HC_getCLevelParams(ctxPtr->compressionLevel).strat != lz4mid) ) {\n        LZ4HC_Insert (ctxPtr, ctxPtr->end-3);  /* Referencing remaining dictionary content */\n    }\n\n    /* Only one memory segment for extDict, so any previous extDict is lost at this stage */\n    ctxPtr->lowLimit  = ctxPtr->dictLimit;\n    ctxPtr->dictStart  = ctxPtr->prefixStart;\n    ctxPtr->dictLimit += (U32)(ctxPtr->end - ctxPtr->prefixStart);\n    ctxPtr->prefixStart = newBlock;\n    ctxPtr->end  = newBlock;\n    ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */\n\n    /* cannot reference an extDict and a dictCtx at the same time */\n    ctxPtr->dictCtx = NULL;\n}\n\nstatic int\nLZ4_compressHC_continue_generic (LZ4_streamHC_t* LZ4_streamHCPtr,\n                                 const char* src, char* dst,\n                                 int* srcSizePtr, int dstCapacity,\n                                 limitedOutput_directive limit)\n{\n    LZ4HC_CCtx_internal* const ctxPtr = &LZ4_streamHCPtr->internal_donotuse;\n    DEBUGLOG(5, \"LZ4_compressHC_continue_generic(ctx=%p, src=%p, srcSize=%d, limit=%d)\",\n                LZ4_streamHCPtr, src, *srcSizePtr, limit);\n    assert(ctxPtr != NULL);\n    /* auto-init if forgotten */\n    if (ctxPtr->prefixStart == NULL)\n        LZ4HC_init_internal (ctxPtr, (const BYTE*) src);\n\n    /* Check overflow */\n    if ((size_t)(ctxPtr->end - ctxPtr->prefixStart) + ctxPtr->dictLimit > 2 GB) {\n        size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->prefixStart);\n        if (dictSize > 64 KB) dictSize = 64 KB;\n        LZ4_loadDictHC(LZ4_streamHCPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);\n    }\n\n    /* Check if blocks follow each other */\n    if ((const BYTE*)src != ctxPtr->end)\n        LZ4HC_setExternalDict(ctxPtr, (const BYTE*)src);\n\n    /* Check overlapping input/dictionary space */\n    {   const BYTE* sourceEnd = (const BYTE*) src + *srcSizePtr;\n        const BYTE* const dictBegin = ctxPtr->dictStart;\n        const BYTE* const dictEnd   = ctxPtr->dictStart + (ctxPtr->dictLimit - ctxPtr->lowLimit);\n        if ((sourceEnd > dictBegin) && ((const BYTE*)src < dictEnd)) {\n            if (sourceEnd > dictEnd) sourceEnd = dictEnd;\n            ctxPtr->lowLimit += (U32)(sourceEnd - ctxPtr->dictStart);\n            ctxPtr->dictStart += (U32)(sourceEnd - ctxPtr->dictStart);\n            /* invalidate dictionary is it's too small */\n            if (ctxPtr->dictLimit - ctxPtr->lowLimit < LZ4HC_HASHSIZE) {\n                ctxPtr->lowLimit = ctxPtr->dictLimit;\n                ctxPtr->dictStart = ctxPtr->prefixStart;\n    }   }   }\n\n    return LZ4HC_compress_generic (ctxPtr, src, dst, srcSizePtr, dstCapacity, ctxPtr->compressionLevel, limit);\n}\n\nint LZ4_compress_HC_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int srcSize, int dstCapacity)\n{\n    DEBUGLOG(5, \"LZ4_compress_HC_continue\");\n    if (dstCapacity < LZ4_compressBound(srcSize))\n        return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, limitedOutput);\n    else\n        return LZ4_compressHC_continue_generic (LZ4_streamHCPtr, src, dst, &srcSize, dstCapacity, notLimited);\n}\n\nint LZ4_compress_HC_continue_destSize (LZ4_streamHC_t* LZ4_streamHCPtr, const char* src, char* dst, int* srcSizePtr, int targetDestSize)\n{\n    return LZ4_compressHC_continue_generic(LZ4_streamHCPtr, src, dst, srcSizePtr, targetDestSize, fillOutput);\n}\n\n\n/* LZ4_saveDictHC :\n * save history content\n * into a user-provided buffer\n * which is then used to continue compression\n */\nint LZ4_saveDictHC (LZ4_streamHC_t* LZ4_streamHCPtr, char* safeBuffer, int dictSize)\n{\n    LZ4HC_CCtx_internal* const streamPtr = &LZ4_streamHCPtr->internal_donotuse;\n    int const prefixSize = (int)(streamPtr->end - streamPtr->prefixStart);\n    DEBUGLOG(5, \"LZ4_saveDictHC(%p, %p, %d)\", LZ4_streamHCPtr, safeBuffer, dictSize);\n    assert(prefixSize >= 0);\n    if (dictSize > 64 KB) dictSize = 64 KB;\n    if (dictSize < 4) dictSize = 0;\n    if (dictSize > prefixSize) dictSize = prefixSize;\n    if (safeBuffer == NULL) assert(dictSize == 0);\n    if (dictSize > 0)\n        LZ4_memmove(safeBuffer, streamPtr->end - dictSize, (size_t)dictSize);\n    {   U32 const endIndex = (U32)(streamPtr->end - streamPtr->prefixStart) + streamPtr->dictLimit;\n        streamPtr->end = (safeBuffer == NULL) ? NULL : (const BYTE*)safeBuffer + dictSize;\n        streamPtr->prefixStart = (const BYTE*)safeBuffer;\n        streamPtr->dictLimit = endIndex - (U32)dictSize;\n        streamPtr->lowLimit = endIndex - (U32)dictSize;\n        streamPtr->dictStart = streamPtr->prefixStart;\n        if (streamPtr->nextToUpdate < streamPtr->dictLimit)\n            streamPtr->nextToUpdate = streamPtr->dictLimit;\n    }\n    return dictSize;\n}\n\n\n/* ================================================\n *  LZ4 Optimal parser (levels [LZ4HC_CLEVEL_OPT_MIN - LZ4HC_CLEVEL_MAX])\n * ===============================================*/\ntypedef struct {\n    int price;\n    int off;\n    int mlen;\n    int litlen;\n} LZ4HC_optimal_t;\n\n/* price in bytes */\nLZ4_FORCE_INLINE int LZ4HC_literalsPrice(int const litlen)\n{\n    int price = litlen;\n    assert(litlen >= 0);\n    if (litlen >= (int)RUN_MASK)\n        price += 1 + ((litlen-(int)RUN_MASK) / 255);\n    return price;\n}\n\n/* requires mlen >= MINMATCH */\nLZ4_FORCE_INLINE int LZ4HC_sequencePrice(int litlen, int mlen)\n{\n    int price = 1 + 2 ; /* token + 16-bit offset */\n    assert(litlen >= 0);\n    assert(mlen >= MINMATCH);\n\n    price += LZ4HC_literalsPrice(litlen);\n\n    if (mlen >= (int)(ML_MASK+MINMATCH))\n        price += 1 + ((mlen-(int)(ML_MASK+MINMATCH)) / 255);\n\n    return price;\n}\n\nLZ4_FORCE_INLINE LZ4HC_match_t\nLZ4HC_FindLongerMatch(LZ4HC_CCtx_internal* const ctx,\n                      const BYTE* ip, const BYTE* const iHighLimit,\n                      int minLen, int nbSearches,\n                      const dictCtx_directive dict,\n                      const HCfavor_e favorDecSpeed)\n{\n    LZ4HC_match_t const match0 = { 0 , 0, 0 };\n    /* note : LZ4HC_InsertAndGetWiderMatch() is able to modify the starting position of a match (*startpos),\n     * but this won't be the case here, as we define iLowLimit==ip,\n    ** so LZ4HC_InsertAndGetWiderMatch() won't be allowed to search past ip */\n    LZ4HC_match_t md = LZ4HC_InsertAndGetWiderMatch(ctx, ip, ip, iHighLimit, minLen, nbSearches, 1 /*patternAnalysis*/, 1 /*chainSwap*/, dict, favorDecSpeed);\n    assert(md.back == 0);\n    if (md.len <= minLen) return match0;\n    if (favorDecSpeed) {\n        if ((md.len>18) & (md.len<=36)) md.len=18;   /* favor dec.speed (shortcut) */\n    }\n    return md;\n}\n\n\nstatic int LZ4HC_compress_optimal ( LZ4HC_CCtx_internal* ctx,\n                                    const char* const source,\n                                    char* dst,\n                                    int* srcSizePtr,\n                                    int dstCapacity,\n                                    int const nbSearches,\n                                    size_t sufficient_len,\n                                    const limitedOutput_directive limit,\n                                    int const fullUpdate,\n                                    const dictCtx_directive dict,\n                                    const HCfavor_e favorDecSpeed)\n{\n    int retval = 0;\n#define TRAILING_LITERALS 3\n#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1\n    LZ4HC_optimal_t* const opt = (LZ4HC_optimal_t*)ALLOC(sizeof(LZ4HC_optimal_t) * (LZ4_OPT_NUM + TRAILING_LITERALS));\n#else\n    LZ4HC_optimal_t opt[LZ4_OPT_NUM + TRAILING_LITERALS];   /* ~64 KB, which is a bit large for stack... */\n#endif\n\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + *srcSizePtr;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = iend - LASTLITERALS;\n    BYTE* op = (BYTE*) dst;\n    BYTE* opSaved = (BYTE*) dst;\n    BYTE* oend = op + dstCapacity;\n    int ovml = MINMATCH;  /* overflow - last sequence */\n    int ovoff = 0;\n\n    /* init */\n#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1\n    if (opt == NULL) goto _return_label;\n#endif\n    DEBUGLOG(5, \"LZ4HC_compress_optimal(dst=%p, dstCapa=%u)\", dst, (unsigned)dstCapacity);\n    *srcSizePtr = 0;\n    if (limit == fillOutput) oend -= LASTLITERALS;   /* Hack for support LZ4 format restriction */\n    if (sufficient_len >= LZ4_OPT_NUM) sufficient_len = LZ4_OPT_NUM-1;\n\n    /* Main Loop */\n    while (ip <= mflimit) {\n         int const llen = (int)(ip - anchor);\n         int best_mlen, best_off;\n         int cur, last_match_pos = 0;\n\n         LZ4HC_match_t const firstMatch = LZ4HC_FindLongerMatch(ctx, ip, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed);\n         if (firstMatch.len==0) { ip++; continue; }\n\n         if ((size_t)firstMatch.len > sufficient_len) {\n             /* good enough solution : immediate encoding */\n             int const firstML = firstMatch.len;\n             opSaved = op;\n             if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), firstML, firstMatch.off, limit, oend) ) {  /* updates ip, op and anchor */\n                 ovml = firstML;\n                 ovoff = firstMatch.off;\n                 goto _dest_overflow;\n             }\n             continue;\n         }\n\n         /* set prices for first positions (literals) */\n         {   int rPos;\n             for (rPos = 0 ; rPos < MINMATCH ; rPos++) {\n                 int const cost = LZ4HC_literalsPrice(llen + rPos);\n                 opt[rPos].mlen = 1;\n                 opt[rPos].off = 0;\n                 opt[rPos].litlen = llen + rPos;\n                 opt[rPos].price = cost;\n                 DEBUGLOG(7, \"rPos:%3i => price:%3i (litlen=%i) -- initial setup\",\n                             rPos, cost, opt[rPos].litlen);\n         }   }\n         /* set prices using initial match */\n         {   int const matchML = firstMatch.len;   /* necessarily < sufficient_len < LZ4_OPT_NUM */\n             int const offset = firstMatch.off;\n             int mlen;\n             assert(matchML < LZ4_OPT_NUM);\n             for (mlen = MINMATCH ; mlen <= matchML ; mlen++) {\n                 int const cost = LZ4HC_sequencePrice(llen, mlen);\n                 opt[mlen].mlen = mlen;\n                 opt[mlen].off = offset;\n                 opt[mlen].litlen = llen;\n                 opt[mlen].price = cost;\n                 DEBUGLOG(7, \"rPos:%3i => price:%3i (matchlen=%i) -- initial setup\",\n                             mlen, cost, mlen);\n         }   }\n         last_match_pos = firstMatch.len;\n         {   int addLit;\n             for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) {\n                 opt[last_match_pos+addLit].mlen = 1; /* literal */\n                 opt[last_match_pos+addLit].off = 0;\n                 opt[last_match_pos+addLit].litlen = addLit;\n                 opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit);\n                 DEBUGLOG(7, \"rPos:%3i => price:%3i (litlen=%i) -- initial setup\",\n                             last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit);\n         }   }\n\n         /* check further positions */\n         for (cur = 1; cur < last_match_pos; cur++) {\n             const BYTE* const curPtr = ip + cur;\n             LZ4HC_match_t newMatch;\n\n             if (curPtr > mflimit) break;\n             DEBUGLOG(7, \"rPos:%u[%u] vs [%u]%u\",\n                     cur, opt[cur].price, opt[cur+1].price, cur+1);\n             if (fullUpdate) {\n                 /* not useful to search here if next position has same (or lower) cost */\n                 if ( (opt[cur+1].price <= opt[cur].price)\n                   /* in some cases, next position has same cost, but cost rises sharply after, so a small match would still be beneficial */\n                   && (opt[cur+MINMATCH].price < opt[cur].price + 3/*min seq price*/) )\n                     continue;\n             } else {\n                 /* not useful to search here if next position has same (or lower) cost */\n                 if (opt[cur+1].price <= opt[cur].price) continue;\n             }\n\n             DEBUGLOG(7, \"search at rPos:%u\", cur);\n             if (fullUpdate)\n                 newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, MINMATCH-1, nbSearches, dict, favorDecSpeed);\n             else\n                 /* only test matches of minimum length; slightly faster, but misses a few bytes */\n                 newMatch = LZ4HC_FindLongerMatch(ctx, curPtr, matchlimit, last_match_pos - cur, nbSearches, dict, favorDecSpeed);\n             if (!newMatch.len) continue;\n\n             if ( ((size_t)newMatch.len > sufficient_len)\n               || (newMatch.len + cur >= LZ4_OPT_NUM) ) {\n                 /* immediate encoding */\n                 best_mlen = newMatch.len;\n                 best_off = newMatch.off;\n                 last_match_pos = cur + 1;\n                 goto encode;\n             }\n\n             /* before match : set price with literals at beginning */\n             {   int const baseLitlen = opt[cur].litlen;\n                 int litlen;\n                 for (litlen = 1; litlen < MINMATCH; litlen++) {\n                     int const price = opt[cur].price - LZ4HC_literalsPrice(baseLitlen) + LZ4HC_literalsPrice(baseLitlen+litlen);\n                     int const pos = cur + litlen;\n                     if (price < opt[pos].price) {\n                         opt[pos].mlen = 1; /* literal */\n                         opt[pos].off = 0;\n                         opt[pos].litlen = baseLitlen+litlen;\n                         opt[pos].price = price;\n                         DEBUGLOG(7, \"rPos:%3i => price:%3i (litlen=%i)\",\n                                     pos, price, opt[pos].litlen);\n             }   }   }\n\n             /* set prices using match at position = cur */\n             {   int const matchML = newMatch.len;\n                 int ml = MINMATCH;\n\n                 assert(cur + newMatch.len < LZ4_OPT_NUM);\n                 for ( ; ml <= matchML ; ml++) {\n                     int const pos = cur + ml;\n                     int const offset = newMatch.off;\n                     int price;\n                     int ll;\n                     DEBUGLOG(7, \"testing price rPos %i (last_match_pos=%i)\",\n                                 pos, last_match_pos);\n                     if (opt[cur].mlen == 1) {\n                         ll = opt[cur].litlen;\n                         price = ((cur > ll) ? opt[cur - ll].price : 0)\n                               + LZ4HC_sequencePrice(ll, ml);\n                     } else {\n                         ll = 0;\n                         price = opt[cur].price + LZ4HC_sequencePrice(0, ml);\n                     }\n\n                    assert((U32)favorDecSpeed <= 1);\n                     if (pos > last_match_pos+TRAILING_LITERALS\n                      || price <= opt[pos].price - (int)favorDecSpeed) {\n                         DEBUGLOG(7, \"rPos:%3i => price:%3i (matchlen=%i)\",\n                                     pos, price, ml);\n                         assert(pos < LZ4_OPT_NUM);\n                         if ( (ml == matchML)  /* last pos of last match */\n                           && (last_match_pos < pos) )\n                             last_match_pos = pos;\n                         opt[pos].mlen = ml;\n                         opt[pos].off = offset;\n                         opt[pos].litlen = ll;\n                         opt[pos].price = price;\n             }   }   }\n             /* complete following positions with literals */\n             {   int addLit;\n                 for (addLit = 1; addLit <= TRAILING_LITERALS; addLit ++) {\n                     opt[last_match_pos+addLit].mlen = 1; /* literal */\n                     opt[last_match_pos+addLit].off = 0;\n                     opt[last_match_pos+addLit].litlen = addLit;\n                     opt[last_match_pos+addLit].price = opt[last_match_pos].price + LZ4HC_literalsPrice(addLit);\n                     DEBUGLOG(7, \"rPos:%3i => price:%3i (litlen=%i)\", last_match_pos+addLit, opt[last_match_pos+addLit].price, addLit);\n             }   }\n         }  /* for (cur = 1; cur <= last_match_pos; cur++) */\n\n         assert(last_match_pos < LZ4_OPT_NUM + TRAILING_LITERALS);\n         best_mlen = opt[last_match_pos].mlen;\n         best_off = opt[last_match_pos].off;\n         cur = last_match_pos - best_mlen;\n\nencode: /* cur, last_match_pos, best_mlen, best_off must be set */\n         assert(cur < LZ4_OPT_NUM);\n         assert(last_match_pos >= 1);  /* == 1 when only one candidate */\n         DEBUGLOG(6, \"reverse traversal, looking for shortest path (last_match_pos=%i)\", last_match_pos);\n         {   int candidate_pos = cur;\n             int selected_matchLength = best_mlen;\n             int selected_offset = best_off;\n             while (1) {  /* from end to beginning */\n                 int const next_matchLength = opt[candidate_pos].mlen;  /* can be 1, means literal */\n                 int const next_offset = opt[candidate_pos].off;\n                 DEBUGLOG(7, \"pos %i: sequence length %i\", candidate_pos, selected_matchLength);\n                 opt[candidate_pos].mlen = selected_matchLength;\n                 opt[candidate_pos].off = selected_offset;\n                 selected_matchLength = next_matchLength;\n                 selected_offset = next_offset;\n                 if (next_matchLength > candidate_pos) break; /* last match elected, first match to encode */\n                 assert(next_matchLength > 0);  /* can be 1, means literal */\n                 candidate_pos -= next_matchLength;\n         }   }\n\n         /* encode all recorded sequences in order */\n         {   int rPos = 0;  /* relative position (to ip) */\n             while (rPos < last_match_pos) {\n                 int const ml = opt[rPos].mlen;\n                 int const offset = opt[rPos].off;\n                 if (ml == 1) { ip++; rPos++; continue; }  /* literal; note: can end up with several literals, in which case, skip them */\n                 rPos += ml;\n                 assert(ml >= MINMATCH);\n                 assert((offset >= 1) && (offset <= LZ4_DISTANCE_MAX));\n                 opSaved = op;\n                 if ( LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ml, offset, limit, oend) ) {  /* updates ip, op and anchor */\n                     ovml = ml;\n                     ovoff = offset;\n                     goto _dest_overflow;\n         }   }   }\n     }  /* while (ip <= mflimit) */\n\n_last_literals:\n     /* Encode Last Literals */\n     {   size_t lastRunSize = (size_t)(iend - anchor);  /* literals */\n         size_t llAdd = (lastRunSize + 255 - RUN_MASK) / 255;\n         size_t const totalSize = 1 + llAdd + lastRunSize;\n         if (limit == fillOutput) oend += LASTLITERALS;  /* restore correct value */\n         if (limit && (op + totalSize > oend)) {\n             if (limit == limitedOutput) { /* Check output limit */\n                retval = 0;\n                goto _return_label;\n             }\n             /* adapt lastRunSize to fill 'dst' */\n             lastRunSize  = (size_t)(oend - op) - 1 /*token*/;\n             llAdd = (lastRunSize + 256 - RUN_MASK) / 256;\n             lastRunSize -= llAdd;\n         }\n         DEBUGLOG(6, \"Final literal run : %i literals\", (int)lastRunSize);\n         ip = anchor + lastRunSize; /* can be != iend if limit==fillOutput */\n\n         if (lastRunSize >= RUN_MASK) {\n             size_t accumulator = lastRunSize - RUN_MASK;\n             *op++ = (RUN_MASK << ML_BITS);\n             for(; accumulator >= 255 ; accumulator -= 255) *op++ = 255;\n             *op++ = (BYTE) accumulator;\n         } else {\n             *op++ = (BYTE)(lastRunSize << ML_BITS);\n         }\n         LZ4_memcpy(op, anchor, lastRunSize);\n         op += lastRunSize;\n     }\n\n     /* End */\n     *srcSizePtr = (int) (((const char*)ip) - source);\n     retval = (int) ((char*)op-dst);\n     goto _return_label;\n\n_dest_overflow:\nif (limit == fillOutput) {\n     /* Assumption : ip, anchor, ovml and ovref must be set correctly */\n     size_t const ll = (size_t)(ip - anchor);\n     size_t const ll_addbytes = (ll + 240) / 255;\n     size_t const ll_totalCost = 1 + ll_addbytes + ll;\n     BYTE* const maxLitPos = oend - 3; /* 2 for offset, 1 for token */\n     DEBUGLOG(6, \"Last sequence overflowing (only %i bytes remaining)\", (int)(oend-1-opSaved));\n     op = opSaved;  /* restore correct out pointer */\n     if (op + ll_totalCost <= maxLitPos) {\n         /* ll validated; now adjust match length */\n         size_t const bytesLeftForMl = (size_t)(maxLitPos - (op+ll_totalCost));\n         size_t const maxMlSize = MINMATCH + (ML_MASK-1) + (bytesLeftForMl * 255);\n         assert(maxMlSize < INT_MAX); assert(ovml >= 0);\n         if ((size_t)ovml > maxMlSize) ovml = (int)maxMlSize;\n         if ((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1 + ovml >= MFLIMIT) {\n             DEBUGLOG(6, \"Space to end : %i + ml (%i)\", (int)((oend + LASTLITERALS) - (op + ll_totalCost + 2) - 1), ovml);\n             DEBUGLOG(6, \"Before : ip = %p, anchor = %p\", ip, anchor);\n             LZ4HC_encodeSequence(UPDATABLE(ip, op, anchor), ovml, ovoff, notLimited, oend);\n             DEBUGLOG(6, \"After : ip = %p, anchor = %p\", ip, anchor);\n     }   }\n     goto _last_literals;\n}\n_return_label:\n#if defined(LZ4HC_HEAPMODE) && LZ4HC_HEAPMODE==1\n     if (opt) FREEMEM(opt);\n#endif\n     return retval;\n}\n\n\n/***************************************************\n*  Deprecated Functions\n***************************************************/\n\n/* These functions currently generate deprecation warnings */\n\n/* Wrappers for deprecated compression functions */\nint LZ4_compressHC(const char* src, char* dst, int srcSize) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), 0); }\nint LZ4_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, 0); }\nint LZ4_compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC (src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }\nint LZ4_compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC(src, dst, srcSize, maxDstSize, cLevel); }\nint LZ4_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, LZ4_compressBound(srcSize), 0); }\nint LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }\nint LZ4_compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, LZ4_compressBound(srcSize), cLevel); }\nint LZ4_compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ4_compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }\nint LZ4_compressHC_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, LZ4_compressBound(srcSize)); }\nint LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }\n\n\n/* Deprecated streaming functions */\nint LZ4_sizeofStreamStateHC(void) { return sizeof(LZ4_streamHC_t); }\n\n/* state is presumed correctly sized, aka >= sizeof(LZ4_streamHC_t)\n * @return : 0 on success, !=0 if error */\nint LZ4_resetStreamStateHC(void* state, char* inputBuffer)\n{\n    LZ4_streamHC_t* const hc4 = LZ4_initStreamHC(state, sizeof(*hc4));\n    if (hc4 == NULL) return 1;   /* init failed */\n    LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer);\n    return 0;\n}\n\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nvoid* LZ4_createHC (const char* inputBuffer)\n{\n    LZ4_streamHC_t* const hc4 = LZ4_createStreamHC();\n    if (hc4 == NULL) return NULL;   /* not enough memory */\n    LZ4HC_init_internal (&hc4->internal_donotuse, (const BYTE*)inputBuffer);\n    return hc4;\n}\n\nint LZ4_freeHC (void* LZ4HC_Data)\n{\n    if (!LZ4HC_Data) return 0;  /* support free on NULL */\n    FREEMEM(LZ4HC_Data);\n    return 0;\n}\n#endif\n\nint LZ4_compressHC2_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int cLevel)\n{\n    return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, 0, cLevel, notLimited);\n}\n\nint LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* src, char* dst, int srcSize, int dstCapacity, int cLevel)\n{\n    return LZ4HC_compress_generic (&((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse, src, dst, &srcSize, dstCapacity, cLevel, limitedOutput);\n}\n\nchar* LZ4_slideInputBufferHC(void* LZ4HC_Data)\n{\n    LZ4HC_CCtx_internal* const s = &((LZ4_streamHC_t*)LZ4HC_Data)->internal_donotuse;\n    const BYTE* const bufferStart = s->prefixStart - s->dictLimit + s->lowLimit;\n    LZ4_resetStreamHC_fast((LZ4_streamHC_t*)LZ4HC_Data, s->compressionLevel);\n    /* ugly conversion trick, required to evade (const char*) -> (char*) cast-qual warning :( */\n    return (char*)(uptrval)bufferStart;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/LZ4/lz4hc.h",
    "content": "﻿/*\n   LZ4 HC - High Compression Mode of LZ4\n   Header File\n   Copyright (C) 2011-2020, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ4 source repository : https://github.com/lz4/lz4\n   - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n#ifndef LZ4_HC_H_19834876238432\n#define LZ4_HC_H_19834876238432\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* --- Dependency --- */\n/* note : lz4hc requires lz4.h/lz4.c for compilation */\n#include \"lz4.h\"   /* stddef, LZ4LIB_API, LZ4_DEPRECATED */\n\n\n/* --- Useful constants --- */\n#define LZ4HC_CLEVEL_MIN         2\n#define LZ4HC_CLEVEL_DEFAULT     9\n#define LZ4HC_CLEVEL_OPT_MIN    10\n#define LZ4HC_CLEVEL_MAX        12\n\n\n/*-************************************\n *  Block Compression\n **************************************/\n/*! LZ4_compress_HC() :\n *  Compress data from `src` into `dst`, using the powerful but slower \"HC\" algorithm.\n * `dst` must be already allocated.\n *  Compression is guaranteed to succeed if `dstCapacity >= LZ4_compressBound(srcSize)` (see \"lz4.h\")\n *  Max supported `srcSize` value is LZ4_MAX_INPUT_SIZE (see \"lz4.h\")\n * `compressionLevel` : any value between 1 and LZ4HC_CLEVEL_MAX will work.\n *                      Values > LZ4HC_CLEVEL_MAX behave the same as LZ4HC_CLEVEL_MAX.\n * @return : the number of bytes written into 'dst'\n *           or 0 if compression fails.\n */\nLZ4LIB_API int LZ4_compress_HC (const char* src, char* dst, int srcSize, int dstCapacity, int compressionLevel);\n\n\n/* Note :\n *   Decompression functions are provided within \"lz4.h\" (BSD license)\n */\n\n\n/*! LZ4_compress_HC_extStateHC() :\n *  Same as LZ4_compress_HC(), but using an externally allocated memory segment for `state`.\n * `state` size is provided by LZ4_sizeofStateHC().\n *  Memory segment must be aligned on 8-bytes boundaries (which a normal malloc() should do properly).\n */\nLZ4LIB_API int LZ4_sizeofStateHC(void);\nLZ4LIB_API int LZ4_compress_HC_extStateHC(void* stateHC, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);\n\n\n/*! LZ4_compress_HC_destSize() : v1.9.0+\n *  Will compress as much data as possible from `src`\n *  to fit into `targetDstSize` budget.\n *  Result is provided in 2 parts :\n * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)\n *           or 0 if compression fails.\n * `srcSizePtr` : on success, *srcSizePtr is updated to indicate how much bytes were read from `src`\n */\nLZ4LIB_API int LZ4_compress_HC_destSize(void* stateHC,\n                                  const char* src, char* dst,\n                                        int* srcSizePtr, int targetDstSize,\n                                        int compressionLevel);\n\n\n/*-************************************\n *  Streaming Compression\n *  Bufferless synchronous API\n **************************************/\n typedef union LZ4_streamHC_u LZ4_streamHC_t;   /* incomplete type (defined later) */\n\n/*! LZ4_createStreamHC() and LZ4_freeStreamHC() :\n *  These functions create and release memory for LZ4 HC streaming state.\n *  Newly created states are automatically initialized.\n *  A same state can be used multiple times consecutively,\n *  starting with LZ4_resetStreamHC_fast() to start a new stream of blocks.\n */\nLZ4LIB_API LZ4_streamHC_t* LZ4_createStreamHC(void);\nLZ4LIB_API int             LZ4_freeStreamHC (LZ4_streamHC_t* streamHCPtr);\n\n/*\n  These functions compress data in successive blocks of any size,\n  using previous blocks as dictionary, to improve compression ratio.\n  One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.\n  There is an exception for ring buffers, which can be smaller than 64 KB.\n  Ring-buffer scenario is automatically detected and handled within LZ4_compress_HC_continue().\n\n  Before starting compression, state must be allocated and properly initialized.\n  LZ4_createStreamHC() does both, though compression level is set to LZ4HC_CLEVEL_DEFAULT.\n\n  Selecting the compression level can be done with LZ4_resetStreamHC_fast() (starts a new stream)\n  or LZ4_setCompressionLevel() (anytime, between blocks in the same stream) (experimental).\n  LZ4_resetStreamHC_fast() only works on states which have been properly initialized at least once,\n  which is automatically the case when state is created using LZ4_createStreamHC().\n\n  After reset, a first \"fictional block\" can be designated as initial dictionary,\n  using LZ4_loadDictHC() (Optional).\n  Note: In order for LZ4_loadDictHC() to create the correct data structure,\n  it is essential to set the compression level _before_ loading the dictionary.\n\n  Invoke LZ4_compress_HC_continue() to compress each successive block.\n  The number of blocks is unlimited.\n  Previous input blocks, including initial dictionary when present,\n  must remain accessible and unmodified during compression.\n\n  It's allowed to update compression level anytime between blocks,\n  using LZ4_setCompressionLevel() (experimental).\n\n @dst buffer should be sized to handle worst case scenarios\n  (see LZ4_compressBound(), it ensures compression success).\n  In case of failure, the API does not guarantee recovery,\n  so the state _must_ be reset.\n  To ensure compression success\n  whenever @dst buffer size cannot be made >= LZ4_compressBound(),\n  consider using LZ4_compress_HC_continue_destSize().\n\n  Whenever previous input blocks can't be preserved unmodified in-place during compression of next blocks,\n  it's possible to copy the last blocks into a more stable memory space, using LZ4_saveDictHC().\n  Return value of LZ4_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer' (<= 64 KB)\n\n  After completing a streaming compression,\n  it's possible to start a new stream of blocks, using the same LZ4_streamHC_t state,\n  just by resetting it, using LZ4_resetStreamHC_fast().\n*/\n\nLZ4LIB_API void LZ4_resetStreamHC_fast(LZ4_streamHC_t* streamHCPtr, int compressionLevel);   /* v1.9.0+ */\nLZ4LIB_API int  LZ4_loadDictHC (LZ4_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);\n\nLZ4LIB_API int LZ4_compress_HC_continue (LZ4_streamHC_t* streamHCPtr,\n                                   const char* src, char* dst,\n                                         int srcSize, int maxDstSize);\n\n/*! LZ4_compress_HC_continue_destSize() : v1.9.0+\n *  Similar to LZ4_compress_HC_continue(),\n *  but will read as much data as possible from `src`\n *  to fit into `targetDstSize` budget.\n *  Result is provided into 2 parts :\n * @return : the number of bytes written into 'dst' (necessarily <= targetDstSize)\n *           or 0 if compression fails.\n * `srcSizePtr` : on success, *srcSizePtr will be updated to indicate how much bytes were read from `src`.\n *           Note that this function may not consume the entire input.\n */\nLZ4LIB_API int LZ4_compress_HC_continue_destSize(LZ4_streamHC_t* LZ4_streamHCPtr,\n                                           const char* src, char* dst,\n                                                 int* srcSizePtr, int targetDstSize);\n\nLZ4LIB_API int LZ4_saveDictHC (LZ4_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);\n\n\n/*! LZ4_attach_HC_dictionary() : stable since v1.10.0\n *  This API allows for the efficient re-use of a static dictionary many times.\n *\n *  Rather than re-loading the dictionary buffer into a working context before\n *  each compression, or copying a pre-loaded dictionary's LZ4_streamHC_t into a\n *  working LZ4_streamHC_t, this function introduces a no-copy setup mechanism,\n *  in which the working stream references the dictionary stream in-place.\n *\n *  Several assumptions are made about the state of the dictionary stream.\n *  Currently, only streams which have been prepared by LZ4_loadDictHC() should\n *  be expected to work.\n *\n *  Alternatively, the provided dictionary stream pointer may be NULL, in which\n *  case any existing dictionary stream is unset.\n *\n *  A dictionary should only be attached to a stream without any history (i.e.,\n *  a stream that has just been reset).\n *\n *  The dictionary will remain attached to the working stream only for the\n *  current stream session. Calls to LZ4_resetStreamHC(_fast) will remove the\n *  dictionary context association from the working stream. The dictionary\n *  stream (and source buffer) must remain in-place / accessible / unchanged\n *  through the lifetime of the stream session.\n */\nLZ4LIB_API void\nLZ4_attach_HC_dictionary(LZ4_streamHC_t* working_stream,\n                   const LZ4_streamHC_t* dictionary_stream);\n\n\n/*^**********************************************\n * !!!!!!   STATIC LINKING ONLY   !!!!!!\n ***********************************************/\n\n/*-******************************************************************\n * PRIVATE DEFINITIONS :\n * Do not use these definitions directly.\n * They are merely exposed to allow static allocation of `LZ4_streamHC_t`.\n * Declare an `LZ4_streamHC_t` directly, rather than any type below.\n * Even then, only do so in the context of static linking, as definitions may change between versions.\n ********************************************************************/\n\n#define LZ4HC_DICTIONARY_LOGSIZE 16\n#define LZ4HC_MAXD (1<<LZ4HC_DICTIONARY_LOGSIZE)\n#define LZ4HC_MAXD_MASK (LZ4HC_MAXD - 1)\n\n#define LZ4HC_HASH_LOG 15\n#define LZ4HC_HASHTABLESIZE (1 << LZ4HC_HASH_LOG)\n#define LZ4HC_HASH_MASK (LZ4HC_HASHTABLESIZE - 1)\n\n\n/* Never ever use these definitions directly !\n * Declare or allocate an LZ4_streamHC_t instead.\n**/\ntypedef struct LZ4HC_CCtx_internal LZ4HC_CCtx_internal;\nstruct LZ4HC_CCtx_internal\n{\n    LZ4_u32 hashTable[LZ4HC_HASHTABLESIZE];\n    LZ4_u16 chainTable[LZ4HC_MAXD];\n    const LZ4_byte* end;     /* next block here to continue on current prefix */\n    const LZ4_byte* prefixStart;  /* Indexes relative to this position */\n    const LZ4_byte* dictStart; /* alternate reference for extDict */\n    LZ4_u32 dictLimit;       /* below that point, need extDict */\n    LZ4_u32 lowLimit;        /* below that point, no more history */\n    LZ4_u32 nextToUpdate;    /* index from which to continue dictionary update */\n    short   compressionLevel;\n    LZ4_i8  favorDecSpeed;   /* favor decompression speed if this flag set,\n                                otherwise, favor compression ratio */\n    LZ4_i8  dirty;           /* stream has to be fully reset if this flag is set */\n    const LZ4HC_CCtx_internal* dictCtx;\n};\n\n#define LZ4_STREAMHC_MINSIZE  262200  /* static size, for inter-version compatibility */\nunion LZ4_streamHC_u {\n    char minStateSize[LZ4_STREAMHC_MINSIZE];\n    LZ4HC_CCtx_internal internal_donotuse;\n}; /* previously typedef'd to LZ4_streamHC_t */\n\n/* LZ4_streamHC_t :\n * This structure allows static allocation of LZ4 HC streaming state.\n * This can be used to allocate statically on stack, or as part of a larger structure.\n *\n * Such state **must** be initialized using LZ4_initStreamHC() before first use.\n *\n * Note that invoking LZ4_initStreamHC() is not required when\n * the state was created using LZ4_createStreamHC() (which is recommended).\n * Using the normal builder, a newly created state is automatically initialized.\n *\n * Static allocation shall only be used in combination with static linking.\n */\n\n/* LZ4_initStreamHC() : v1.9.0+\n * Required before first use of a statically allocated LZ4_streamHC_t.\n * Before v1.9.0 : use LZ4_resetStreamHC() instead\n */\nLZ4LIB_API LZ4_streamHC_t* LZ4_initStreamHC(void* buffer, size_t size);\n\n\n/*-************************************\n*  Deprecated Functions\n**************************************/\n/* see lz4.h LZ4_DISABLE_DEPRECATE_WARNINGS to turn off deprecation warnings */\n\n/* deprecated compression functions */\nLZ4_DEPRECATED(\"use LZ4_compress_HC() instead\") LZ4LIB_API int LZ4_compressHC               (const char* source, char* dest, int inputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_HC() instead\") LZ4LIB_API int LZ4_compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_HC() instead\") LZ4LIB_API int LZ4_compressHC2              (const char* source, char* dest, int inputSize, int compressionLevel);\nLZ4_DEPRECATED(\"use LZ4_compress_HC() instead\") LZ4LIB_API int LZ4_compressHC2_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_extStateHC() instead\") LZ4LIB_API int LZ4_compressHC_withStateHC               (void* state, const char* source, char* dest, int inputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_extStateHC() instead\") LZ4LIB_API int LZ4_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_extStateHC() instead\") LZ4LIB_API int LZ4_compressHC2_withStateHC              (void* state, const char* source, char* dest, int inputSize, int compressionLevel);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_extStateHC() instead\") LZ4LIB_API int LZ4_compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_continue() instead\") LZ4LIB_API int LZ4_compressHC_continue               (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_continue() instead\") LZ4LIB_API int LZ4_compressHC_limitedOutput_continue (LZ4_streamHC_t* LZ4_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);\n\n/* Obsolete streaming functions; degraded functionality; do not use!\n *\n * In order to perform streaming compression, these functions depended on data\n * that is no longer tracked in the state. They have been preserved as well as\n * possible: using them will still produce a correct output. However, use of\n * LZ4_slideInputBufferHC() will truncate the history of the stream, rather\n * than preserve a window-sized chunk of history.\n */\n#if !defined(LZ4_STATIC_LINKING_ONLY_DISABLE_MEMORY_ALLOCATION)\nLZ4_DEPRECATED(\"use LZ4_createStreamHC() instead\") LZ4LIB_API void* LZ4_createHC (const char* inputBuffer);\nLZ4_DEPRECATED(\"use LZ4_freeStreamHC() instead\") LZ4LIB_API   int   LZ4_freeHC (void* LZ4HC_Data);\n#endif\nLZ4_DEPRECATED(\"use LZ4_saveDictHC() instead\") LZ4LIB_API     char* LZ4_slideInputBufferHC (void* LZ4HC_Data);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_continue() instead\") LZ4LIB_API int LZ4_compressHC2_continue               (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);\nLZ4_DEPRECATED(\"use LZ4_compress_HC_continue() instead\") LZ4LIB_API int LZ4_compressHC2_limitedOutput_continue (void* LZ4HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);\nLZ4_DEPRECATED(\"use LZ4_createStreamHC() instead\") LZ4LIB_API int   LZ4_sizeofStreamStateHC(void);\nLZ4_DEPRECATED(\"use LZ4_initStreamHC() instead\") LZ4LIB_API  int   LZ4_resetStreamStateHC(void* state, char* inputBuffer);\n\n\n/* LZ4_resetStreamHC() is now replaced by LZ4_initStreamHC().\n * The intention is to emphasize the difference with LZ4_resetStreamHC_fast(),\n * which is now the recommended function to start a new stream of blocks,\n * but cannot be used to initialize a memory segment containing arbitrary garbage data.\n *\n * It is recommended to switch to LZ4_initStreamHC().\n * LZ4_resetStreamHC() will generate deprecation warnings in a future version.\n */\nLZ4LIB_API void LZ4_resetStreamHC (LZ4_streamHC_t* streamHCPtr, int compressionLevel);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* LZ4_HC_H_19834876238432 */\n\n\n/*-**************************************************\n * !!!!!     STATIC LINKING ONLY     !!!!!\n * Following definitions are considered experimental.\n * They should not be linked from DLL,\n * as there is no guarantee of API stability yet.\n * Prototypes will be promoted to \"stable\" status\n * after successful usage in real-life scenarios.\n ***************************************************/\n#ifdef LZ4_HC_STATIC_LINKING_ONLY   /* protection macro */\n#ifndef LZ4_HC_SLO_098092834\n#define LZ4_HC_SLO_098092834\n\n#define LZ4_STATIC_LINKING_ONLY   /* LZ4LIB_STATIC_API */\n#include \"lz4.h\"\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*! LZ4_setCompressionLevel() : v1.8.0+ (experimental)\n *  It's possible to change compression level\n *  between successive invocations of LZ4_compress_HC_continue*()\n *  for dynamic adaptation.\n */\nLZ4LIB_STATIC_API void LZ4_setCompressionLevel(\n    LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);\n\n/*! LZ4_favorDecompressionSpeed() : v1.8.2+ (experimental)\n *  Opt. Parser will favor decompression speed over compression ratio.\n *  Only applicable to levels >= LZ4HC_CLEVEL_OPT_MIN.\n */\nLZ4LIB_STATIC_API void LZ4_favorDecompressionSpeed(\n    LZ4_streamHC_t* LZ4_streamHCPtr, int favor);\n\n/*! LZ4_resetStreamHC_fast() : v1.9.0+\n *  When an LZ4_streamHC_t is known to be in a internally coherent state,\n *  it can often be prepared for a new compression with almost no work, only\n *  sometimes falling back to the full, expensive reset that is always required\n *  when the stream is in an indeterminate state (i.e., the reset performed by\n *  LZ4_resetStreamHC()).\n *\n *  LZ4_streamHCs are guaranteed to be in a valid state when:\n *  - returned from LZ4_createStreamHC()\n *  - reset by LZ4_resetStreamHC()\n *  - memset(stream, 0, sizeof(LZ4_streamHC_t))\n *  - the stream was in a valid state and was reset by LZ4_resetStreamHC_fast()\n *  - the stream was in a valid state and was then used in any compression call\n *    that returned success\n *  - the stream was in an indeterminate state and was used in a compression\n *    call that fully reset the state (LZ4_compress_HC_extStateHC()) and that\n *    returned success\n *\n *  Note:\n *  A stream that was last used in a compression call that returned an error\n *  may be passed to this function. However, it will be fully reset, which will\n *  clear any existing history and settings from the context.\n */\nLZ4LIB_STATIC_API void LZ4_resetStreamHC_fast(\n    LZ4_streamHC_t* LZ4_streamHCPtr, int compressionLevel);\n\n/*! LZ4_compress_HC_extStateHC_fastReset() :\n *  A variant of LZ4_compress_HC_extStateHC().\n *\n *  Using this variant avoids an expensive initialization step. It is only safe\n *  to call if the state buffer is known to be correctly initialized already\n *  (see above comment on LZ4_resetStreamHC_fast() for a definition of\n *  \"correctly initialized\"). From a high level, the difference is that this\n *  function initializes the provided state with a call to\n *  LZ4_resetStreamHC_fast() while LZ4_compress_HC_extStateHC() starts with a\n *  call to LZ4_resetStreamHC().\n */\nLZ4LIB_STATIC_API int LZ4_compress_HC_extStateHC_fastReset (\n    void* state,\n    const char* src, char* dst,\n    int srcSize, int dstCapacity,\n    int compressionLevel);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* LZ4_HC_SLO_098092834 */\n#endif   /* LZ4_HC_STATIC_LINKING_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5.c",
    "content": "﻿/*\n   LZ5 - Fast LZ compression algorithm\n   Copyright (C) 2011-2015, Yann Collet.\n   Copyright (C) 2015, Przemyslaw Skibinski <inikep@gmail.com>\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ5 source repository : https://github.com/inikep/lz5\n   - LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c\n*/\n\n\n\n/**************************************\n*  Includes\n**************************************/\n#include \"lz5common.h\"\n#include \"lz5.h\"\n#include <stdio.h>\n\n\n/**************************************\n*  Local Constants\n**************************************/\n#define LZ5_HASHLOG   (LZ5_MEMORY_USAGE-2)\n#define HASH_SIZE_U32 (1 << LZ5_HASHLOG)       /* required as macro for static allocation */\n\nstatic const int LZ5_64Klimit = ((64 KB) + (MFLIMIT-1));\nstatic const U32 LZ5_skipTrigger = 6;  /* Increase this value ==> compression run slower on incompressible data */\n\n\n/**************************************\n*  Local Structures and types\n**************************************/\ntypedef struct {\n    U32 hashTable[HASH_SIZE_U32];\n    U32 currentOffset;\n    U32 initCheck;\n    const BYTE* dictionary;\n    BYTE* bufferStart;   /* obsolete, used for slideInputBuffer */\n    U32 dictSize;\n} LZ5_stream_t_internal;\n\ntypedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;\ntypedef enum { byPtr, byU32, byU16 } tableType_t;\n\ntypedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;\ntypedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;\n\ntypedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;\ntypedef enum { full = 0, partial = 1 } earlyEnd_directive;\n\n\n/**************************************\n*  Local Utils\n**************************************/\nint LZ5_versionNumber (void) { return LZ5_VERSION_NUMBER; }\nint LZ5_compressBound(int isize)  { return LZ5_COMPRESSBOUND(isize); }\nint LZ5_sizeofState() { return LZ5_STREAMSIZE; }\n\n\n\n/********************************\n*  Compression functions\n********************************/\n\nstatic U32 LZ5_hashSequence(U32 sequence, tableType_t const tableType)\n{\n    if (tableType == byU16)\n        return (((sequence) * prime4bytes) >> ((32)-(LZ5_HASHLOG+1)));\n    else\n        return (((sequence) * prime4bytes) >> ((32)-LZ5_HASHLOG));\n}\n\nstatic U32 LZ5_hashSequence64(size_t sequence, tableType_t const tableType)\n{\n    const U32 hashLog = (tableType == byU16) ? LZ5_HASHLOG+1 : LZ5_HASHLOG;\n    const U32 hashMask = (1<<hashLog) - 1;\n    return ((sequence * prime5bytes) >> (40 - hashLog)) & hashMask;\n}\n\nstatic U32 LZ5_hashSequenceT(size_t sequence, tableType_t const tableType)\n{\n    if (MEM_64bits())\n        return LZ5_hashSequence64(sequence, tableType);\n    return LZ5_hashSequence((U32)sequence, tableType);\n}\n\nstatic U32 LZ5_hashPosition(const void* p, tableType_t tableType) { return LZ5_hashSequenceT(MEM_read_ARCH(p), tableType); }\n\nstatic void LZ5_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase)\n{\n    switch (tableType)\n    {\n    case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }\n    case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }\n    case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }\n    }\n}\n\nstatic void LZ5_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)\n{\n    U32 h = LZ5_hashPosition(p, tableType);\n    LZ5_putPositionOnHash(p, h, tableBase, tableType, srcBase);\n}\n\nstatic const BYTE* LZ5_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)\n{\n    if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; }\n    if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; }\n    { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; }   /* default, to ensure a return */\n}\n\nstatic const BYTE* LZ5_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase)\n{\n    U32 h = LZ5_hashPosition(p, tableType);\n    return LZ5_getPositionOnHash(h, tableBase, tableType, srcBase);\n}\n\nFORCE_INLINE int LZ5_compress_generic(\n                 void* const ctx,\n                 const char* const source,\n                 char* const dest,\n                 const int inputSize,\n                 const int maxOutputSize,\n                 const limitedOutput_directive outputLimited,\n                 const tableType_t tableType,\n                 const dict_directive dict,\n                 const dictIssue_directive dictIssue,\n                 const U32 acceleration)\n{\n    LZ5_stream_t_internal* const dictPtr = (LZ5_stream_t_internal*)ctx;\n\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* base;\n    const BYTE* lowLimit;\n    const BYTE* const lowRefLimit = ip - dictPtr->dictSize;\n    const BYTE* const dictionary = dictPtr->dictionary;\n    const BYTE* const dictEnd = dictionary + dictPtr->dictSize;\n    const size_t dictDelta = dictEnd - (const BYTE*)source;\n    const BYTE* anchor = (const BYTE*) source;\n    const BYTE* const iend = ip + inputSize;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = iend - LASTLITERALS;\n\n    BYTE* op = (BYTE*) dest;\n    BYTE* const olimit = op + maxOutputSize;\n\n    U32 forwardH, last_off=1;\n    size_t refDelta=0;\n\n    /* Init conditions */\n    if ((U32)inputSize > (U32)LZ5_MAX_INPUT_SIZE) return 0;   /* Unsupported input size, too large (or negative) */\n    switch(dict)\n    {\n    case noDict:\n    default:\n        base = (const BYTE*)source;\n        lowLimit = (const BYTE*)source;\n        break;\n    case withPrefix64k:\n        base = (const BYTE*)source - dictPtr->currentOffset;\n        lowLimit = (const BYTE*)source - dictPtr->dictSize;\n        break;\n    case usingExtDict:\n        base = (const BYTE*)source - dictPtr->currentOffset;\n        lowLimit = (const BYTE*)source;\n        break;\n    }\n    if ((tableType == byU16) && (inputSize>=LZ5_64Klimit)) return 0;   /* Size too large (not within 64K limit) */\n    if (inputSize<LZ5_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */\n\n    /* First Byte */\n    LZ5_putPosition(ip, ctx, tableType, base);\n    ip++; forwardH = LZ5_hashPosition(ip, tableType);\n\n    /* Main Loop */\n    for ( ; ; )\n    {\n        const BYTE* match;\n        BYTE* token;\n        {\n            const BYTE* forwardIp = ip;\n            unsigned step = 1;\n            unsigned searchMatchNb = acceleration << LZ5_skipTrigger;\n\n            /* Find a match */\n            do {\n                U32 h = forwardH;\n                ip = forwardIp;\n                forwardIp += step;\n                step = (searchMatchNb++ >> LZ5_skipTrigger);\n\n                if (unlikely(forwardIp > mflimit)) goto _last_literals;\n\n                match = LZ5_getPositionOnHash(h, ctx, tableType, base);\n                if (dict==usingExtDict)\n                {\n                    if (match<(const BYTE*)source)\n                    {\n                        refDelta = dictDelta;\n                        lowLimit = dictionary;\n                    }\n                    else\n                    {\n                        refDelta = 0;\n                        lowLimit = (const BYTE*)source;\n                    }\n                }\n                forwardH = LZ5_hashPosition(forwardIp, tableType);\n                LZ5_putPositionOnHash(ip, h, ctx, tableType, base);\n\n            } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)\n                || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))\n                || (MEM_read32(match+refDelta) != MEM_read32(ip)) );\n        }\n\n        /* Catch up */\n        while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }\n\n        {\n            /* Encode Literal length */\n            unsigned litLength = (unsigned)(ip - anchor);\n            token = op++;\n            if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit)))\n                return 0;   /* Check output limit */\n\n            if (ip-match >= LZ5_SHORT_OFFSET_DISTANCE && ip-match < LZ5_MID_OFFSET_DISTANCE && (U32)(ip-match) != last_off)\n            {\n                if (litLength>=RUN_MASK)\n                {\n                    int len = (int)litLength-RUN_MASK;\n                    *token=(RUN_MASK<<ML_BITS);\n                    for(; len >= 255 ; len-=255) *op++ = 255;\n                    *op++ = (BYTE)len;\n                }\n                else *token = (BYTE)(litLength<<ML_BITS);\n            }\n            else\n            {\n                if (litLength>=RUN_MASK2)\n                {\n                    int len = (int)litLength-RUN_MASK2;\n                    *token=(RUN_MASK2<<ML_BITS);\n                    for(; len >= 255 ; len-=255) *op++ = 255;\n                    *op++ = (BYTE)len;\n                }\n                else *token = (BYTE)(litLength<<ML_BITS);\n            }\n\n            /* Copy Literals */\n            MEM_wildCopy(op, anchor, op+litLength);\n            op+=litLength;\n        }\n\n_next_match:\n\t\t{\n\t\t\t/* Encode Offset */\n\t\t\tU32 offset = (U32)(ip-match);\n\t\t\tif (offset == last_off)\n\t\t\t{\n\t\t\t\t*token+=(3<<ML_RUN_BITS2);\n\t\t\t}\n\t\t\telse\n\t\t\tif (ip-match < LZ5_SHORT_OFFSET_DISTANCE)\n\t\t\t{\n\t\t\t\t*token+=(BYTE)((4+(offset>>8))<<ML_RUN_BITS2);\n\t\t\t\t*op++=(BYTE)offset;\n\t\t\t}\n\t\t\telse\n\t\t\tif (ip-match < LZ5_MID_OFFSET_DISTANCE)\n\t\t\t{\n\t\t\t\tMEM_writeLE16(op, (U16)offset); op+=2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*token+=(2<<ML_RUN_BITS2);\n\t\t\t\tMEM_writeLE24(op, (U32)offset); op+=3;\n\t\t\t}\n\t\t\tlast_off = offset;\n\t\t}\n\n        /* Encode MatchLength */\n        {\n            size_t matchLength;\n\n            if ((dict==usingExtDict) && (lowLimit==dictionary))\n            {\n                const BYTE* limit;\n                match += refDelta;\n                limit = ip + (dictEnd-match);\n                if (limit > matchlimit) limit = matchlimit;\n                matchLength = MEM_count(ip+MINMATCH, match+MINMATCH, limit);\n                ip += MINMATCH + matchLength;\n                if (ip==limit)\n                {\n                    size_t more = MEM_count(ip, (const BYTE*)source, matchlimit);\n                    matchLength += more;\n                    ip += more;\n                }\n            }\n            else\n            {\n                matchLength = MEM_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n                ip += MINMATCH + matchLength;\n            }\n\n            if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit)))\n                return 0;    /* Check output limit */\n            if (matchLength>=ML_MASK)\n            {\n                *token += ML_MASK;\n                matchLength -= ML_MASK;\n                for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; }\n                if (matchLength >= 255) { matchLength-=255; *op++ = 255; }\n                *op++ = (BYTE)matchLength;\n            }\n            else *token += (BYTE)(matchLength);\n        }\n\n        anchor = ip;\n\n        /* Test end of chunk */\n        if (ip > mflimit) break;\n\n        /* Fill table */\n        LZ5_putPosition(ip-2, ctx, tableType, base);\n\n        /* Test next position */\n        match = LZ5_getPosition(ip, ctx, tableType, base);\n        if (dict==usingExtDict)\n        {\n            if (match<(const BYTE*)source)\n            {\n                refDelta = dictDelta;\n                lowLimit = dictionary;\n            }\n            else\n            {\n                refDelta = 0;\n                lowLimit = (const BYTE*)source;\n            }\n        }\n        LZ5_putPosition(ip, ctx, tableType, base);\n        if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)\n            && (match+MAX_DISTANCE>=ip)\n            && (MEM_read32(match+refDelta)==MEM_read32(ip)) )\n        { token=op++; *token=0; goto _next_match; }\n\n        /* Prepare next loop */\n        forwardH = LZ5_hashPosition(++ip, tableType);\n    }\n\n_last_literals:\n    /* Encode Last Literals */\n    {\n        const size_t lastRun = (size_t)(iend - anchor);\n        if ((outputLimited) && ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize))\n            return 0;   /* Check output limit */\n        if (lastRun >= RUN_MASK)\n        {\n            size_t accumulator = lastRun - RUN_MASK;\n            *op++ = RUN_MASK << ML_BITS;\n            for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;\n            *op++ = (BYTE) accumulator;\n        }\n        else\n        {\n            *op++ = (BYTE)(lastRun<<ML_BITS);\n        }\n        memcpy(op, anchor, lastRun);\n        op += lastRun;\n    }\n\n    /* End */\n    return (int) (((char*)op)-dest);\n}\n\n\nint LZ5_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)\n{\n    LZ5_resetStream((LZ5_stream_t*)state);\n    if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;\n\n    if (maxOutputSize >= LZ5_compressBound(inputSize))\n    {\n        if (inputSize < LZ5_64Klimit)\n            return LZ5_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16,                        noDict, noDictIssue, acceleration);\n        else\n            return LZ5_compress_generic(state, source, dest, inputSize, 0, notLimited, MEM_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);\n    }\n    else\n    {\n        if (inputSize < LZ5_64Klimit)\n            return LZ5_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16,                        noDict, noDictIssue, acceleration);\n        else\n            return LZ5_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, MEM_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);\n    }\n}\n\n\nint LZ5_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)\n{\n#if (HEAPMODE)\n    void* ctxPtr = ALLOCATOR(1, sizeof(LZ5_stream_t));   /* malloc-calloc always properly aligned */\n#else\n    LZ5_stream_t ctx;\n    void* ctxPtr = &ctx;\n#endif\n\n    int result = LZ5_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration);\n\n#if (HEAPMODE)\n    FREEMEM(ctxPtr);\n#endif\n    return result;\n}\n\n\nint LZ5_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize)\n{\n    return LZ5_compress_fast(source, dest, inputSize, maxOutputSize, 1);\n}\n\n\n/* hidden debug function */\n/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */\nint LZ5_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)\n{\n    LZ5_stream_t ctx;\n\n    LZ5_resetStream(&ctx);\n\n    if (inputSize < LZ5_64Klimit)\n        return LZ5_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16,                        noDict, noDictIssue, acceleration);\n    else\n        return LZ5_compress_generic(&ctx, source, dest, inputSize, maxOutputSize, limitedOutput, MEM_64bits() ? byU32 : byPtr, noDict, noDictIssue, acceleration);\n}\n\n\n/********************************\n*  destSize variant\n********************************/\n\nstatic int LZ5_compress_destSize_generic(\n                       void* const ctx,\n                 const char* const src,\n                       char* const dst,\n                       int*  const srcSizePtr,\n                 const int targetDstSize,\n                 const tableType_t tableType)\n{\n    const BYTE* ip = (const BYTE*) src;\n    const BYTE* base = (const BYTE*) src;\n    const BYTE* lowLimit = (const BYTE*) src;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + *srcSizePtr;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = iend - LASTLITERALS;\n\n    BYTE* op = (BYTE*) dst;\n    BYTE* const oend = op + targetDstSize;\n    BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */;\n    BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */);\n    BYTE* const oMaxSeq = oMaxLit - 1 /* token */;\n\n    U32 forwardH, last_off=1;\n\n\n    /* Init conditions */\n    if (targetDstSize < 1) return 0;                                     /* Impossible to store anything */\n    if ((U32)*srcSizePtr > (U32)LZ5_MAX_INPUT_SIZE) return 0;            /* Unsupported input size, too large (or negative) */\n    if ((tableType == byU16) && (*srcSizePtr>=LZ5_64Klimit)) return 0;   /* Size too large (not within 64K limit) */\n    if (*srcSizePtr<LZ5_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */\n\n    /* First Byte */\n    *srcSizePtr = 0;\n    LZ5_putPosition(ip, ctx, tableType, base);\n    ip++; forwardH = LZ5_hashPosition(ip, tableType);\n\n    /* Main Loop */\n    for ( ; ; )\n    {\n        const BYTE* match;\n        BYTE* token;\n        {\n            const BYTE* forwardIp = ip;\n            unsigned step = 1;\n            unsigned searchMatchNb = 1 << LZ5_skipTrigger;\n\n            /* Find a match */\n            do {\n                U32 h = forwardH;\n                ip = forwardIp;\n                forwardIp += step;\n                step = (searchMatchNb++ >> LZ5_skipTrigger);\n\n                if (unlikely(forwardIp > mflimit))\n                    goto _last_literals;\n\n                match = LZ5_getPositionOnHash(h, ctx, tableType, base);\n                forwardH = LZ5_hashPosition(forwardIp, tableType);\n                LZ5_putPositionOnHash(ip, h, ctx, tableType, base);\n\n            } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))\n                || (MEM_read32(match) != MEM_read32(ip)) );\n        }\n\n        /* Catch up */\n        while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; }\n\n        {\n            /* Encode Literal length */\n            unsigned litLength = (unsigned)(ip - anchor);\n            token = op++;\n            if (op + ((litLength+240)/255) + litLength > oMaxLit)\n            {\n                /* Not enough space for a last match */\n                op--;\n                goto _last_literals;\n            }\n\n            if ((U32)(ip-match) >= LZ5_SHORT_OFFSET_DISTANCE && (U32)(ip-match) < LZ5_MID_OFFSET_DISTANCE && (U32)(ip-match) != last_off)\n            {\n                if (litLength>=RUN_MASK)\n                {\n                    int len = (int)litLength-RUN_MASK;\n                    *token=(RUN_MASK<<ML_BITS);\n                    for(; len >= 255 ; len-=255) *op++ = 255;\n                    *op++ = (BYTE)len;\n                }\n                else *token = (BYTE)(litLength<<ML_BITS);\n            }\n            else\n            {\n                if (litLength>=RUN_MASK2)\n                {\n                    int len = (int)litLength-RUN_MASK2;\n                    *token=(RUN_MASK2<<ML_BITS);\n                    for(; len >= 255 ; len-=255) *op++ = 255;\n                    *op++ = (BYTE)len;\n                }\n                else *token = (BYTE)(litLength<<ML_BITS);\n            }\n\n            /* Copy Literals */\n            MEM_wildCopy(op, anchor, op+litLength);\n            op += litLength;\n        }\n\n_next_match:\n\t\t{\n\t\t\tU32 offset = (U32)(ip-match);\n\t\t\t/* Encode Offset */\n\t\t\tif (offset == last_off)\n\t\t\t{\n\t\t\t\t*token+=(3<<ML_RUN_BITS2);          \n\t\t\t}\n\t\t\telse\n\t\t\tif (ip-match < LZ5_SHORT_OFFSET_DISTANCE)\n\t\t\t{\n\t\t\t\t*token+=(BYTE)((4+(offset>>8))<<ML_RUN_BITS2);\n\t\t\t\t*op++=(BYTE)offset;\n\t\t\t}\n\t\t\telse\n\t\t\tif (ip-match < LZ5_MID_OFFSET_DISTANCE)\n\t\t\t{\n\t\t\t\tMEM_writeLE16(op, (U16)offset); op+=2;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*token+=(2<<ML_RUN_BITS2);\n\t\t\t\tMEM_writeLE24(op, (U32)offset); op+=3;\n\t\t\t}\n\t\t\tlast_off = offset;\n\t\t}\n\n        /* Encode MatchLength */\n        {\n            size_t matchLength;\n\n            matchLength = MEM_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n\n            if (op + ((matchLength+240)/255) > oMaxMatch)\n            {\n                /* Match description too long : reduce it */\n                matchLength = (15-1) + (oMaxMatch-op) * 255;\n            }\n            ip += MINMATCH + matchLength;\n\n            if (matchLength>=ML_MASK)\n            {\n                *token += ML_MASK;\n                matchLength -= ML_MASK;\n                while (matchLength >= 255) { matchLength-=255; *op++ = 255; }\n                *op++ = (BYTE)matchLength;\n            }\n            else *token += (BYTE)(matchLength);\n        }\n\n        anchor = ip;\n\n        /* Test end of block */\n        if (ip > mflimit) break;\n        if (op > oMaxSeq) break;\n\n        /* Fill table */\n        LZ5_putPosition(ip-2, ctx, tableType, base);\n\n        /* Test next position */\n        match = LZ5_getPosition(ip, ctx, tableType, base);\n        LZ5_putPosition(ip, ctx, tableType, base);\n        if ( (match+MAX_DISTANCE>=ip)\n            && (MEM_read32(match)==MEM_read32(ip)) )\n        { token=op++; *token=0; goto _next_match; }\n\n        /* Prepare next loop */\n        forwardH = LZ5_hashPosition(++ip, tableType);\n    }\n\n_last_literals:\n    /* Encode Last Literals */\n    {\n        size_t lastRunSize = (size_t)(iend - anchor);\n        if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend)\n        {\n            /* adapt lastRunSize to fill 'dst' */\n            lastRunSize  = (oend-op) - 1;\n            lastRunSize -= (lastRunSize+240)/255;\n        }\n        ip = anchor + lastRunSize;\n\n        if (lastRunSize >= RUN_MASK)\n        {\n            size_t accumulator = lastRunSize - RUN_MASK;\n            *op++ = RUN_MASK << ML_BITS;\n            for(; accumulator >= 255 ; accumulator-=255) *op++ = 255;\n            *op++ = (BYTE) accumulator;\n        }\n        else\n        {\n            *op++ = (BYTE)(lastRunSize<<ML_BITS);\n        }\n        memcpy(op, anchor, lastRunSize);\n        op += lastRunSize;\n    }\n\n    /* End */\n    *srcSizePtr = (int) (((const char*)ip)-src);\n    return (int) (((char*)op)-dst);\n}\n\n\nstatic int LZ5_compress_destSize_extState (void* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize)\n{\n    LZ5_resetStream((LZ5_stream_t*)state);\n\n    if (targetDstSize >= LZ5_compressBound(*srcSizePtr))   /* compression success is guaranteed */\n    {\n        return LZ5_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1);\n    }\n    else\n    {\n        if (*srcSizePtr < LZ5_64Klimit)\n            return LZ5_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, byU16);\n        else\n            return LZ5_compress_destSize_generic(state, src, dst, srcSizePtr, targetDstSize, MEM_64bits() ? byU32 : byPtr);\n    }\n}\n\n\nint LZ5_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize)\n{\n#if (HEAPMODE)\n    void* ctx = ALLOCATOR(1, sizeof(LZ5_stream_t));   /* malloc-calloc always properly aligned */\n#else\n    LZ5_stream_t ctxBody;\n    void* ctx = &ctxBody;\n#endif\n\n    int result = LZ5_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize);\n\n#if (HEAPMODE)\n    FREEMEM(ctx);\n#endif\n    return result;\n}\n\n\n\n/********************************\n*  Streaming functions\n********************************/\n\nLZ5_stream_t* LZ5_createStream(void)\n{\n    LZ5_stream_t* lz5s = (LZ5_stream_t*)ALLOCATOR(8, LZ5_STREAMSIZE_U64);\n    LZ5_STATIC_ASSERT(LZ5_STREAMSIZE >= sizeof(LZ5_stream_t_internal));    /* A compilation error here means LZ5_STREAMSIZE is not large enough */\n    LZ5_resetStream(lz5s);\n    return lz5s;\n}\n\nvoid LZ5_resetStream (LZ5_stream_t* LZ5_stream)\n{\n    MEM_INIT(LZ5_stream, 0, sizeof(LZ5_stream_t));\n}\n\nint LZ5_freeStream (LZ5_stream_t* LZ5_stream)\n{\n    FREEMEM(LZ5_stream);\n    return (0);\n}\n\n\n#define HASH_UNIT sizeof(size_t)\nint LZ5_loadDict (LZ5_stream_t* LZ5_dict, const char* dictionary, int dictSize)\n{\n    LZ5_stream_t_internal* dict = (LZ5_stream_t_internal*) LZ5_dict;\n    const BYTE* p = (const BYTE*)dictionary;\n    const BYTE* const dictEnd = p + dictSize;\n    const BYTE* base;\n\n    if ((dict->initCheck) || (dict->currentOffset > 1 GB))  /* Uninitialized structure, or reuse overflow */\n        LZ5_resetStream(LZ5_dict);\n\n /*   if (dictSize < (int)HASH_UNIT)\n    {\n        dict->dictionary = NULL;\n        dict->dictSize = 0;\n        return 0;\n    }*/\n\n    if ((dictEnd - p) > LZ5_DICT_SIZE) p = dictEnd - LZ5_DICT_SIZE;\n    dict->currentOffset += LZ5_DICT_SIZE;\n    base = p - dict->currentOffset;\n    dict->dictionary = p;\n    dict->dictSize = (U32)(dictEnd - p);\n    dict->currentOffset += dict->dictSize;\n\n    while (p <= dictEnd-HASH_UNIT)\n    {\n        LZ5_putPosition(p, dict->hashTable, byU32, base);\n        p+=3;\n    }\n\n    return dict->dictSize;\n}\n\n\nstatic void LZ5_renormDictT(LZ5_stream_t_internal* LZ5_dict, const BYTE* src)\n{\n    if ((LZ5_dict->currentOffset > 0x80000000) ||\n        ((size_t)LZ5_dict->currentOffset > (size_t)src))   /* address space overflow */\n    {\n        /* rescale hash table */\n        U32 delta = LZ5_dict->currentOffset - LZ5_DICT_SIZE;\n        const BYTE* dictEnd = LZ5_dict->dictionary + LZ5_dict->dictSize;\n        int i;\n        for (i=0; i<HASH_SIZE_U32; i++)\n        {\n            if (LZ5_dict->hashTable[i] < delta) LZ5_dict->hashTable[i]=0;\n            else LZ5_dict->hashTable[i] -= delta;\n        }\n        LZ5_dict->currentOffset = LZ5_DICT_SIZE;\n        if (LZ5_dict->dictSize > LZ5_DICT_SIZE) LZ5_dict->dictSize = LZ5_DICT_SIZE;\n        LZ5_dict->dictionary = dictEnd - LZ5_dict->dictSize;\n    }\n}\n\n\nint LZ5_compress_fast_continue (LZ5_stream_t* LZ5_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration)\n{\n    LZ5_stream_t_internal* streamPtr = (LZ5_stream_t_internal*)LZ5_stream;\n    const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;\n\n    const BYTE* smallest = (const BYTE*) source;\n    if (streamPtr->initCheck) return 0;   /* Uninitialized structure detected */\n    if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd;\n    LZ5_renormDictT(streamPtr, smallest);\n    if (acceleration < 1) acceleration = ACCELERATION_DEFAULT;\n\n    /* Check overlapping input/dictionary space */\n    {\n        const BYTE* sourceEnd = (const BYTE*) source + inputSize;\n        if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd))\n        {\n            streamPtr->dictSize = (U32)(dictEnd - sourceEnd);\n            if (streamPtr->dictSize > LZ5_DICT_SIZE) streamPtr->dictSize = LZ5_DICT_SIZE;\n            if (streamPtr->dictSize < 4) streamPtr->dictSize = 0;\n            streamPtr->dictionary = dictEnd - streamPtr->dictSize;\n        }\n    }\n\n    /* prefix mode : source data follows dictionary */\n    if (dictEnd == (const BYTE*)source)\n    {\n        int result;\n        if ((streamPtr->dictSize < LZ5_DICT_SIZE) && (streamPtr->dictSize < streamPtr->currentOffset))\n            result = LZ5_compress_generic(LZ5_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration);\n        else\n            result = LZ5_compress_generic(LZ5_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration);\n        streamPtr->dictSize += (U32)inputSize;\n        streamPtr->currentOffset += (U32)inputSize;\n        return result;\n    }\n\n    /* external dictionary mode */\n    {\n        int result;\n        if ((streamPtr->dictSize < LZ5_DICT_SIZE) && (streamPtr->dictSize < streamPtr->currentOffset))\n            result = LZ5_compress_generic(LZ5_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration);\n        else\n            result = LZ5_compress_generic(LZ5_stream, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration);\n        streamPtr->dictionary = (const BYTE*)source;\n        streamPtr->dictSize = (U32)inputSize;\n        streamPtr->currentOffset += (U32)inputSize;\n        return result;\n    }\n}\n\n\n/* Hidden debug function, to force external dictionary mode */\nint LZ5_compress_forceExtDict (LZ5_stream_t* LZ5_dict, const char* source, char* dest, int inputSize)\n{\n    LZ5_stream_t_internal* streamPtr = (LZ5_stream_t_internal*)LZ5_dict;\n    int result;\n    const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize;\n\n    const BYTE* smallest = dictEnd;\n    if (smallest > (const BYTE*) source) smallest = (const BYTE*) source;\n    LZ5_renormDictT((LZ5_stream_t_internal*)LZ5_dict, smallest);\n\n    result = LZ5_compress_generic(LZ5_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1);\n\n    streamPtr->dictionary = (const BYTE*)source;\n    streamPtr->dictSize = (U32)inputSize;\n    streamPtr->currentOffset += (U32)inputSize;\n\n    return result;\n}\n\n\nint LZ5_saveDict (LZ5_stream_t* LZ5_dict, char* safeBuffer, int dictSize)\n{\n    LZ5_stream_t_internal* dict = (LZ5_stream_t_internal*) LZ5_dict;\n\tconst BYTE* previousDictEnd = dict->dictionary + dict->dictSize;\n\tif (!dict->dictionary)\n        return 0;\n\n    if ((U32)dictSize > LZ5_DICT_SIZE) dictSize = LZ5_DICT_SIZE;   /* useless to define a dictionary > LZ5_DICT_SIZE */\n    if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize;\n\n    memmove(safeBuffer, previousDictEnd - dictSize, dictSize);\n\n    dict->dictionary = (const BYTE*)safeBuffer;\n    dict->dictSize = (U32)dictSize;\n\n    return dictSize;\n}\n\n\n\n/*******************************\n*  Decompression functions\n*******************************/\n/*\n * This generic decompression function cover all use cases.\n * It shall be instantiated several times, using different sets of directives\n * Note that it is essential this generic function is really inlined,\n * in order to remove useless branches during compilation optimization.\n */\nFORCE_INLINE int LZ5_decompress_generic(\n                 const char* const source,\n                 char* const dest,\n                 int inputSize,\n                 int outputSize,         /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */\n\n                 int endOnInput,         /* endOnOutputSize, endOnInputSize */\n                 int partialDecoding,    /* full, partial */\n                 int targetOutputSize,   /* only used if partialDecoding==partial */\n                 int dict,               /* noDict, withPrefix64k, usingExtDict */\n                 const BYTE* const lowPrefix,  /* == dest if dict == noDict */\n                 const BYTE* const dictStart,  /* only if dict==usingExtDict */\n                 const size_t dictSize         /* note : = 0 if noDict */\n                 )\n{\n    /* Local Variables */\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* const iend = ip + inputSize;\n\n    BYTE* op = (BYTE*) dest;\n    BYTE* const oend = op + outputSize;\n    BYTE* cpy;\n    BYTE* oexit = op + targetOutputSize;\n    const BYTE* const lowLimit = lowPrefix - dictSize;\n\n    const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;\n    const unsigned dec32table[] = {4, 1, 2, 1, 4, 4, 4, 4};\n    const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3};\n\n    const int safeDecode = (endOnInput==endOnInputSize);\n    const int checkOffset = ((safeDecode) && (dictSize < (int)(LZ5_DICT_SIZE)));\n\n    size_t last_off = 1;\n\n    /* Special cases */\n    if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT;                         /* targetOutputSize too high => decode everything */\n    if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1;  /* Empty output buffer */\n    if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1);\n\n\n    /* Main Loop */\n    while (1)\n    {\n        unsigned token;\n        size_t length;\n        const BYTE* match;\n        size_t offset;\n\n        /* get literal length */\n        token = *ip++;\n        if (token>>6)\n        {\n            if ((length=(token>>ML_BITS)&RUN_MASK2) == RUN_MASK2)\n            {\n                unsigned s;\n                do\n                {\n                    s = *ip++;\n                    length += s;\n                }\n                while (likely((endOnInput)?ip<iend-RUN_MASK2:1) && (s==255));\n                if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error;   /* overflow detection */\n                if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error;   /* overflow detection */\n            }\n        }\n        else\n        {\n            if ((length=(token>>ML_BITS)&RUN_MASK) == RUN_MASK)\n            {\n                unsigned s;\n                do\n                {\n                    s = *ip++;\n                    length += s;\n                }\n                while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255));\n                if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error;   /* overflow detection */\n                if ((safeDecode) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error;   /* overflow detection */\n            }\n        }\n\n        /* copy literals */\n        cpy = op+length;\n        if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-WILDCOPYLENGTH)) || (ip+length>iend-(0+1+LASTLITERALS))) )\n            || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)))\n        {\n            if (partialDecoding)\n            {\n                if (cpy > oend) goto _output_error;                           /* Error : write attempt beyond end of output buffer */\n                if ((endOnInput) && (ip+length > iend)) goto _output_error;   /* Error : read attempt beyond end of input buffer */\n            }\n            else\n            {\n                if ((!endOnInput) && (cpy != oend)) goto _output_error;       /* Error : block decoding must stop exactly there */\n                if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error;   /* Error : input must be consumed */\n            }\n            memcpy(op, ip, length);\n            ip += length;\n            op += length;\n            break;     /* Necessarily EOF, due to parsing restrictions */\n        }\n        MEM_wildCopy(op, ip, cpy);\n        ip += length; op = cpy;\n\n        /* get offset */\n#if 0\n        switch (token>>6)\n        {\n            default: offset = *ip + (((token>>ML_RUN_BITS2)&3)<<8); ip++; break;\n            case 0: offset = MEM_readLE16(ip); ip+=2; break;\n            case 1:\n                if ((token>>5) == 3)\n                    offset = last_off;\n                else // (token>>ML_RUN_BITS2) == 2\n                {    offset = MEM_readLE24(ip); ip+=3; }\n                break;\n        }\n#else \n        if (token>>7)\n        {\n            offset = *ip + (((token>>ML_RUN_BITS2)&3)<<8); ip++;\n        }\n        else \n        if ((token>>ML_RUN_BITS) == 0)\n        {\n            offset = MEM_readLE16(ip); ip+=2;\n        }\n        else\n        if ((token>>ML_RUN_BITS2) == 2)\n        {\n            offset = MEM_readLE24(ip); ip+=3;\n        }\n        else // (token>>ML_RUN_BITS2) == 3\n        {\n            offset = last_off;\n        }\n#endif\n\n        last_off = offset;\n        match = op - offset;\n        if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error;   /* Error : offset outside buffers */\n\n        /* get matchlength */\n        length = token & ML_MASK;\n        if (length == ML_MASK)\n        {\n            unsigned s;\n            do\n            {\n                if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error;\n                s = *ip++;\n                length += s;\n            } while (s==255);\n            if ((safeDecode) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error;   /* overflow detection */\n        }\n        length += MINMATCH;\n\n        /* check external dictionary */\n        if ((dict==usingExtDict) && (match < lowPrefix))\n        {\n            if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error;   /* doesn't respect parsing restriction */\n\n            if (length <= (size_t)(lowPrefix-match))\n            {\n                /* match can be copied as a single segment from external dictionary */\n                match = dictEnd - (lowPrefix-match);\n                memmove(op, match, length); op += length;\n            }\n            else\n            {\n                /* match encompass external dictionary and current block */\n                size_t copySize = (size_t)(lowPrefix-match);\n                memcpy(op, dictEnd - copySize, copySize);\n                op += copySize;\n                copySize = length - copySize;\n                if (copySize > (size_t)(op-lowPrefix))   /* overlap copy */\n                {\n                    BYTE* const endOfMatch = op + copySize;\n                    const BYTE* copyFrom = lowPrefix;\n                    while (op < endOfMatch) *op++ = *copyFrom++;\n                }\n                else\n                {\n                    memcpy(op, lowPrefix, copySize);\n                    op += copySize;\n                }\n            }\n            continue;\n        }\n\n        /* copy match within block */\n        cpy = op + length;\n        if (unlikely(offset<8))\n        {\n            const int dec64 = dec64table[offset];\n            op[0] = match[0];\n            op[1] = match[1];\n            op[2] = match[2];\n            op[3] = match[3];\n            match += dec32table[offset];\n            memcpy(op+4, match, 4);\n            match -= dec64;\n        } else { MEM_copy8(op, match); match+=8; }\n        op += 8;\n\n        if (unlikely(cpy>oend-(16-MINMATCH)))\n        {\n            BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1);\n            if (cpy > oend-LASTLITERALS) goto _output_error;    /* Error : last LASTLITERALS bytes must be literals (uncompressed) */\n            if (op < oCopyLimit)\n            {\n                MEM_wildCopy(op, match, oCopyLimit);\n                match += oCopyLimit - op;\n                op = oCopyLimit;\n            }\n            while (op<cpy) *op++ = *match++;\n        }\n        else\n            MEM_wildCopy(op, match, cpy);\n        op=cpy;   /* correction */\n    }\n\n    /* end of decoding */\n    if (endOnInput)\n       return (int) (((char*)op)-dest);     /* Nb of output bytes decoded */\n    else\n       return (int) (((const char*)ip)-source);   /* Nb of input bytes read */\n\n    /* Overflow error detected */\n_output_error:\n    return (int) (-(((const char*)ip)-source))-1;\n}\n\n\nint LZ5_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)\n{\n    return LZ5_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);\n}\n\nint LZ5_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)\n{\n    return LZ5_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);\n}\n\nint LZ5_decompress_fast(const char* source, char* dest, int originalSize)\n{\n    return LZ5_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - LZ5_DICT_SIZE), NULL, LZ5_DICT_SIZE);\n}\n\n\n/* streaming decompression functions */\n\ntypedef struct\n{\n    const BYTE* externalDict;\n    size_t extDictSize;\n    const BYTE* prefixEnd;\n    size_t prefixSize;\n} LZ5_streamDecode_t_internal;\n\n/*\n * If you prefer dynamic allocation methods,\n * LZ5_createStreamDecode()\n * provides a pointer (void*) towards an initialized LZ5_streamDecode_t structure.\n */\nLZ5_streamDecode_t* LZ5_createStreamDecode(void)\n{\n    LZ5_streamDecode_t* lz5s = (LZ5_streamDecode_t*) ALLOCATOR(1, sizeof(LZ5_streamDecode_t));\n    return lz5s;\n}\n\nint LZ5_freeStreamDecode (LZ5_streamDecode_t* LZ5_stream)\n{\n    FREEMEM(LZ5_stream);\n    return 0;\n}\n\n/*\n * LZ5_setStreamDecode\n * Use this function to instruct where to find the dictionary\n * This function is not necessary if previous data is still available where it was decoded.\n * Loading a size of 0 is allowed (same effect as no dictionary).\n * Return : 1 if OK, 0 if error\n */\nint LZ5_setStreamDecode (LZ5_streamDecode_t* LZ5_streamDecode, const char* dictionary, int dictSize)\n{\n    LZ5_streamDecode_t_internal* lz5sd = (LZ5_streamDecode_t_internal*) LZ5_streamDecode;\n    lz5sd->prefixSize = (size_t) dictSize;\n    lz5sd->prefixEnd = (const BYTE*) dictionary + dictSize;\n    lz5sd->externalDict = NULL;\n    lz5sd->extDictSize  = 0;\n    return 1;\n}\n\n/*\n*_continue() :\n    These decoding functions allow decompression of multiple blocks in \"streaming\" mode.\n    Previously decoded blocks must still be available at the memory position where they were decoded.\n    If it's not possible, save the relevant part of decoded data into a safe buffer,\n    and indicate where it stands using LZ5_setStreamDecode()\n*/\nint LZ5_decompress_safe_continue (LZ5_streamDecode_t* LZ5_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)\n{\n    LZ5_streamDecode_t_internal* lz5sd = (LZ5_streamDecode_t_internal*) LZ5_streamDecode;\n    int result;\n\n    if (lz5sd->prefixEnd == (BYTE*)dest)\n    {\n        result = LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                        endOnInputSize, full, 0,\n                                        usingExtDict, lz5sd->prefixEnd - lz5sd->prefixSize, lz5sd->externalDict, lz5sd->extDictSize);\n        if (result <= 0) return result;\n        lz5sd->prefixSize += result;\n        lz5sd->prefixEnd  += result;\n    }\n    else\n    {\n        lz5sd->extDictSize = lz5sd->prefixSize;\n        lz5sd->externalDict = lz5sd->prefixEnd - lz5sd->extDictSize;\n        result = LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                        endOnInputSize, full, 0,\n                                        usingExtDict, (BYTE*)dest, lz5sd->externalDict, lz5sd->extDictSize);\n        if (result <= 0) return result;\n        lz5sd->prefixSize = result;\n        lz5sd->prefixEnd  = (BYTE*)dest + result;\n    }\n\n    return result;\n}\n\nint LZ5_decompress_fast_continue (LZ5_streamDecode_t* LZ5_streamDecode, const char* source, char* dest, int originalSize)\n{\n    LZ5_streamDecode_t_internal* lz5sd = (LZ5_streamDecode_t_internal*) LZ5_streamDecode;\n    int result;\n\n    if (lz5sd->prefixEnd == (BYTE*)dest)\n    {\n        result = LZ5_decompress_generic(source, dest, 0, originalSize,\n                                        endOnOutputSize, full, 0,\n                                        usingExtDict, lz5sd->prefixEnd - lz5sd->prefixSize, lz5sd->externalDict, lz5sd->extDictSize);\n        if (result <= 0) return result;\n        lz5sd->prefixSize += originalSize;\n        lz5sd->prefixEnd  += originalSize;\n    }\n    else\n    {\n        lz5sd->extDictSize = lz5sd->prefixSize;\n        lz5sd->externalDict = (BYTE*)dest - lz5sd->extDictSize;\n        result = LZ5_decompress_generic(source, dest, 0, originalSize,\n                                        endOnOutputSize, full, 0,\n                                        usingExtDict, (BYTE*)dest, lz5sd->externalDict, lz5sd->extDictSize);\n        if (result <= 0) return result;\n        lz5sd->prefixSize = originalSize;\n        lz5sd->prefixEnd  = (BYTE*)dest + originalSize;\n    }\n\n    return result;\n}\n\n\n/*\nAdvanced decoding functions :\n*_usingDict() :\n    These decoding functions work the same as \"_continue\" ones,\n    the dictionary must be explicitly provided within parameters\n*/\n\nFORCE_INLINE int LZ5_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize)\n{\n    if (dictSize==0)\n        return LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0);\n    if (dictStart+dictSize == dest)\n    {\n        if (dictSize >= (int)(LZ5_DICT_SIZE - 1))\n            return LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-LZ5_DICT_SIZE, NULL, 0);\n        return LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);\n    }\n    return LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);\n}\n\nint LZ5_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)\n{\n    return LZ5_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize);\n}\n\nint LZ5_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize)\n{\n    return LZ5_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize);\n}\n\n/* debug function */\nint LZ5_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)\n{\n    return LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);\n}\n\n\n/***************************************************\n*  Obsolete Functions\n***************************************************/\n/* obsolete compression functions */\nint LZ5_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ5_compress_default(source, dest, inputSize, maxOutputSize); }\nint LZ5_compress(const char* source, char* dest, int inputSize) { return LZ5_compress_default(source, dest, inputSize, LZ5_compressBound(inputSize)); }\nint LZ5_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ5_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); }\nint LZ5_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ5_compress_fast_extState(state, src, dst, srcSize, LZ5_compressBound(srcSize), 1); }\nint LZ5_compress_limitedOutput_continue (LZ5_stream_t* LZ5_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ5_compress_fast_continue(LZ5_stream, src, dst, srcSize, maxDstSize, 1); }\nint LZ5_compress_continue (LZ5_stream_t* LZ5_stream, const char* source, char* dest, int inputSize) { return LZ5_compress_fast_continue(LZ5_stream, source, dest, inputSize, LZ5_compressBound(inputSize), 1); }\n\n/*\nThese function names are deprecated and should no longer be used.\nThey are only provided here for compatibility with older user programs.\n- LZ5_uncompress is totally equivalent to LZ5_decompress_fast\n- LZ5_uncompress_unknownOutputSize is totally equivalent to LZ5_decompress_safe\n*/\nint LZ5_uncompress (const char* source, char* dest, int outputSize) { return LZ5_decompress_fast(source, dest, outputSize); }\nint LZ5_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ5_decompress_safe(source, dest, isize, maxOutputSize); }\n\n\n/* Obsolete Streaming functions */\n\nint LZ5_sizeofStreamState() { return LZ5_STREAMSIZE; }\n\nstatic void LZ5_init(LZ5_stream_t_internal* lz5ds, BYTE* base)\n{\n    MEM_INIT(lz5ds, 0, LZ5_STREAMSIZE);\n    lz5ds->bufferStart = base;\n}\n\nint LZ5_resetStreamState(void* state, char* inputBuffer)\n{\n    if ((((size_t)state) & 3) != 0) return 1;   /* Error : pointer is not aligned on 4-bytes boundary */\n    LZ5_init((LZ5_stream_t_internal*)state, (BYTE*)inputBuffer);\n    return 0;\n}\n\nvoid* LZ5_create (char* inputBuffer)\n{\n    void* lz5ds = ALLOCATOR(8, LZ5_STREAMSIZE_U64);\n    LZ5_init ((LZ5_stream_t_internal*)lz5ds, (BYTE*)inputBuffer);\n    return lz5ds;\n}\n\nchar* LZ5_slideInputBuffer (void* LZ5_Data)\n{\n    LZ5_stream_t_internal* ctx = (LZ5_stream_t_internal*)LZ5_Data;\n    int dictSize = LZ5_saveDict((LZ5_stream_t*)LZ5_Data, (char*)ctx->bufferStart, LZ5_DICT_SIZE);\n    return (char*)(ctx->bufferStart + dictSize);\n}\n\n/* Obsolete streaming decompression functions */\n\nint LZ5_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize)\n{\n    return LZ5_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - LZ5_DICT_SIZE, NULL, LZ5_DICT_SIZE);\n}\n\nint LZ5_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize)\n{\n    return LZ5_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - LZ5_DICT_SIZE, NULL, LZ5_DICT_SIZE);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5.h",
    "content": "﻿/*\n   LZ5 - Fast LZ compression algorithm\n   Header File\n   Copyright (C) 2011-2015, Yann Collet.\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ5 source repository : https://github.com/inikep/lz5\n   - LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c\n*/\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*\n * lz5.h provides block compression functions, and gives full buffer control to programmer.\n * If you need to generate inter-operable compressed data (respecting LZ5 frame specification),\n * and can let the library handle its own memory, please use lz5frame.h instead.\n*/\n\n/**************************************\n*  Version\n**************************************/\n#define LZ5_VERSION          \"v1.5.0\"\n#define LZ5_VERSION_MAJOR    1    /* for breaking interface changes  */\n#define LZ5_VERSION_MINOR    5    /* for new (non-breaking) interface capabilities */\n#define LZ5_VERSION_RELEASE  0    /* for tweaks, bug-fixes, or development */\n#define LZ5_VERSION_NUMBER (LZ5_VERSION_MAJOR *100*100 + LZ5_VERSION_MINOR *100 + LZ5_VERSION_RELEASE)\nint LZ5_versionNumber (void);\n\n#define LZ5HC_MAX_CLEVEL     15\n\n\n/**************************************\n*  Tuning parameter\n**************************************/\n/*\n * LZ5_MEMORY_USAGE :\n * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n * Increasing memory usage improves compression ratio\n * Reduced memory usage can improve speed, due to cache effect\n */\n#define LZ5_MEMORY_USAGE 20\n\n\n/**************************************\n*  Simple Functions\n**************************************/\n\nint LZ5_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);\nint LZ5_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);\n\n/*\nLZ5_compress_default() :\n    Compresses 'sourceSize' bytes from buffer 'source'\n    into already allocated 'dest' buffer of size 'maxDestSize'.\n    Compression is guaranteed to succeed if 'maxDestSize' >= LZ5_compressBound(sourceSize).\n    It also runs faster, so it's a recommended setting.\n    If the function cannot compress 'source' into a more limited 'dest' budget,\n    compression stops *immediately*, and the function result is zero.\n    As a consequence, 'dest' content is not valid.\n    This function never writes outside 'dest' buffer, nor read outside 'source' buffer.\n        sourceSize  : Max supported value is LZ5_MAX_INPUT_VALUE\n        maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)\n        return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)\n              or 0 if compression fails\n\nLZ5_decompress_safe() :\n    compressedSize : is the precise full size of the compressed block.\n    maxDecompressedSize : is the size of destination buffer, which must be already allocated.\n    return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)\n             If destination buffer is not large enough, decoding will stop and output an error code (<0).\n             If the source stream is detected malformed, the function will stop decoding and return a negative result.\n             This function is protected against buffer overflow exploits, including malicious data packets.\n             It never writes outside output buffer, nor reads outside input buffer.\n*/\n\n\n/**************************************\n*  Advanced Functions\n**************************************/\n#define LZ5_MAX_INPUT_SIZE        0x7E000000   /* 2 113 929 216 bytes */\n#define LZ5_COMPRESSBOUND(isize)  ((unsigned)(isize) > (unsigned)LZ5_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/128) + 16)\n\n/*\nLZ5_compressBound() :\n    Provides the maximum size that LZ5 compression may output in a \"worst case\" scenario (input data not compressible)\n    This function is primarily useful for memory allocation purposes (destination buffer size).\n    Macro LZ5_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).\n    Note that LZ5_compress_default() compress faster when dest buffer size is >= LZ5_compressBound(srcSize)\n        inputSize  : max supported value is LZ5_MAX_INPUT_SIZE\n        return : maximum output size in a \"worst case\" scenario\n              or 0, if input size is too large ( > LZ5_MAX_INPUT_SIZE)\n*/\nint LZ5_compressBound(int inputSize);\n\n/*\nLZ5_compress_fast() :\n    Same as LZ5_compress_default(), but allows to select an \"acceleration\" factor.\n    The larger the acceleration value, the faster the algorithm, but also the lesser the compression.\n    It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.\n    An acceleration value of \"1\" is the same as regular LZ5_compress_default()\n    Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz5.c), which is 1.\n*/\nint LZ5_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);\n\n\n/*\nLZ5_compress_fast_extState() :\n    Same compression function, just using an externally allocated memory space to store compression state.\n    Use LZ5_sizeofState() to know how much memory must be allocated,\n    and allocate it on 8-bytes boundaries (using malloc() typically).\n    Then, provide it as 'void* state' to compression function.\n*/\nint LZ5_sizeofState(void);\nint LZ5_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);\n\n\n/*\nLZ5_compress_destSize() :\n    Reverse the logic, by compressing as much data as possible from 'source' buffer\n    into already allocated buffer 'dest' of size 'targetDestSize'.\n    This function either compresses the entire 'source' content into 'dest' if it's large enough,\n    or fill 'dest' buffer completely with as much data as possible from 'source'.\n        *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.\n                         New value is necessarily <= old value.\n        return : Nb bytes written into 'dest' (necessarily <= targetDestSize)\n              or 0 if compression fails\n*/\nint LZ5_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);\n\n\n/*\nLZ5_decompress_fast() :\n    originalSize : is the original and therefore uncompressed size\n    return : the number of bytes read from the source buffer (in other words, the compressed size)\n             If the source stream is detected malformed, the function will stop decoding and return a negative result.\n             Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.\n    note : This function fully respect memory boundaries for properly formed compressed data.\n           It is a bit faster than LZ5_decompress_safe().\n           However, it does not provide any protection against intentionally modified data stream (malicious input).\n           Use this function in trusted environment only (data to decode comes from a trusted source).\n*/\nint LZ5_decompress_fast (const char* source, char* dest, int originalSize);\n\n/*\nLZ5_decompress_safe_partial() :\n    This function decompress a compressed block of size 'compressedSize' at position 'source'\n    into destination buffer 'dest' of size 'maxDecompressedSize'.\n    The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,\n    reducing decompression time.\n    return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)\n       Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.\n             Always control how many bytes were decoded.\n             If the source stream is detected malformed, the function will stop decoding and return a negative result.\n             This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets\n*/\nint LZ5_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);\n\n\n/***********************************************\n*  Streaming Compression Functions\n***********************************************/\n#define LZ5_STREAMSIZE_U64 ((1 << (LZ5_MEMORY_USAGE-3)) + 4)\n#define LZ5_STREAMSIZE     (LZ5_STREAMSIZE_U64 * sizeof(long long))\n/*\n * LZ5_stream_t\n * information structure to track an LZ5 stream.\n * important : init this structure content before first use !\n * note : only allocated directly the structure if you are statically linking LZ5\n *        If you are using liblz5 as a DLL, please use below construction methods instead.\n */\ntypedef struct { long long table[LZ5_STREAMSIZE_U64]; } LZ5_stream_t;\n\n/*\n * LZ5_resetStream\n * Use this function to init an allocated LZ5_stream_t structure\n */\nvoid LZ5_resetStream (LZ5_stream_t* streamPtr);\n\n/*\n * LZ5_createStream will allocate and initialize an LZ5_stream_t structure\n * LZ5_freeStream releases its memory.\n * In the context of a DLL (liblz5), please use these methods rather than the static struct.\n * They are more future proof, in case of a change of LZ5_stream_t size.\n */\nLZ5_stream_t* LZ5_createStream(void);\nint           LZ5_freeStream (LZ5_stream_t* streamPtr);\n\n/*\n * LZ5_loadDict\n * Use this function to load a static dictionary into LZ5_stream.\n * Any previous data will be forgotten, only 'dictionary' will remain in memory.\n * Loading a size of 0 is allowed.\n * Return : dictionary size, in bytes (necessarily <= 64 KB)\n */\nint LZ5_loadDict (LZ5_stream_t* streamPtr, const char* dictionary, int dictSize);\n\n/*\n * LZ5_compress_fast_continue\n * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.\n * Important : Previous data blocks are assumed to still be present and unmodified !\n * 'dst' buffer must be already allocated.\n * If maxDstSize >= LZ5_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.\n * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.\n */\nint LZ5_compress_fast_continue (LZ5_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);\n\n/*\n * LZ5_saveDict\n * If previously compressed data block is not guaranteed to remain available at its memory location\n * save it into a safer place (char* safeBuffer)\n * Note : you don't need to call LZ5_loadDict() afterwards,\n *        dictionary is immediately usable, you can therefore call LZ5_compress_fast_continue()\n * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error\n */\nint LZ5_saveDict (LZ5_stream_t* streamPtr, char* safeBuffer, int dictSize);\n\n\n/************************************************\n*  Streaming Decompression Functions\n************************************************/\n\n#define LZ5_STREAMDECODESIZE_U64  4\n#define LZ5_STREAMDECODESIZE     (LZ5_STREAMDECODESIZE_U64 * sizeof(unsigned long long))\ntypedef struct { unsigned long long table[LZ5_STREAMDECODESIZE_U64]; } LZ5_streamDecode_t;\n/*\n * LZ5_streamDecode_t\n * information structure to track an LZ5 stream.\n * init this structure content using LZ5_setStreamDecode or memset() before first use !\n *\n * In the context of a DLL (liblz5) please prefer usage of construction methods below.\n * They are more future proof, in case of a change of LZ5_streamDecode_t size in the future.\n * LZ5_createStreamDecode will allocate and initialize an LZ5_streamDecode_t structure\n * LZ5_freeStreamDecode releases its memory.\n */\nLZ5_streamDecode_t* LZ5_createStreamDecode(void);\nint                 LZ5_freeStreamDecode (LZ5_streamDecode_t* LZ5_stream);\n\n/*\n * LZ5_setStreamDecode\n * Use this function to instruct where to find the dictionary.\n * Setting a size of 0 is allowed (same effect as reset).\n * Return : 1 if OK, 0 if error\n */\nint LZ5_setStreamDecode (LZ5_streamDecode_t* LZ5_streamDecode, const char* dictionary, int dictSize);\n\n/*\n*_continue() :\n    These decoding functions allow decompression of multiple blocks in \"streaming\" mode.\n    Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)\n    In the case of a ring buffers, decoding buffer must be either :\n    - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)\n      In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).\n    - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.\n      maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.\n      In which case, encoding and decoding buffers do not need to be synchronized,\n      and encoding ring buffer can have any size, including small ones ( < 64 KB).\n    - _At least_ 64 KB + 8 bytes + maxBlockSize.\n      In which case, encoding and decoding buffers do not need to be synchronized,\n      and encoding ring buffer can have any size, including larger than decoding buffer.\n    Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,\n    and indicate where it is saved using LZ5_setStreamDecode()\n*/\nint LZ5_decompress_safe_continue (LZ5_streamDecode_t* LZ5_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);\nint LZ5_decompress_fast_continue (LZ5_streamDecode_t* LZ5_streamDecode, const char* source, char* dest, int originalSize);\n\n\n/*\nAdvanced decoding functions :\n*_usingDict() :\n    These decoding functions work the same as\n    a combination of LZ5_setStreamDecode() followed by LZ5_decompress_x_continue()\n    They are stand-alone. They don't need nor update an LZ5_streamDecode_t structure.\n*/\nint LZ5_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);\nint LZ5_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);\n\n\n/**************************************\n*  Obsolete Functions\n**************************************/\n/* Deprecate Warnings */\n/* Should these warnings messages be a problem,\n   it is generally possible to disable them,\n   with -Wno-deprecated-declarations for gcc\n   or _CRT_SECURE_NO_WARNINGS in Visual for example.\n   Otherwise, you can also define LZ5_DISABLE_DEPRECATE_WARNINGS */\n#define LZ5_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#ifdef LZ5_DISABLE_DEPRECATE_WARNINGS\n#  define LZ5_DEPRECATED()   /* disable deprecation warnings */\n#else\n#  if (LZ5_GCC_VERSION >= 405) || defined(__clang__)\n#    define LZ5_DEPRECATED(message) __attribute__((deprecated(message)))\n#  elif (LZ5_GCC_VERSION >= 301)\n#    define LZ5_DEPRECATED(message) __attribute__((deprecated))\n#  elif defined(_MSC_VER)\n#    define LZ5_DEPRECATED(message) __declspec(deprecated(message))\n#  else\n#    pragma message(\"WARNING: You need to implement LZ5_DEPRECATED for this compiler\")\n#    define LZ5_DEPRECATED(message)\n#  endif\n#endif /* LZ5_DISABLE_DEPRECATE_WARNINGS */\n\n/* Obsolete compression functions */\n/* These functions will generate warnings in a future release */\nint LZ5_compress               (const char* source, char* dest, int sourceSize);\nint LZ5_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);\nint LZ5_compress_withState               (void* state, const char* source, char* dest, int inputSize);\nint LZ5_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);\nint LZ5_compress_continue                (LZ5_stream_t* LZ5_streamPtr, const char* source, char* dest, int inputSize);\nint LZ5_compress_limitedOutput_continue  (LZ5_stream_t* LZ5_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);\n\n/* Obsolete decompression functions */\n/* These function names are completely deprecated and must no longer be used.\n   They are only provided in lz5.c for compatibility with older programs.\n    - LZ5_uncompress is the same as LZ5_decompress_fast\n    - LZ5_uncompress_unknownOutputSize is the same as LZ5_decompress_safe\n   These function prototypes are now disabled; uncomment them only if you really need them.\n   It is highly recommended to stop using these prototypes and migrate to maintained ones */\n/* int LZ5_uncompress (const char* source, char* dest, int outputSize); */\n/* int LZ5_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */\n\n/* Obsolete streaming functions; use new streaming interface whenever possible */\nLZ5_DEPRECATED(\"use LZ5_createStream() instead\") void* LZ5_create (char* inputBuffer);\nLZ5_DEPRECATED(\"use LZ5_createStream() instead\") int   LZ5_sizeofStreamState(void);\nLZ5_DEPRECATED(\"use LZ5_resetStream() instead\")  int   LZ5_resetStreamState(void* state, char* inputBuffer);\nLZ5_DEPRECATED(\"use LZ5_saveDict() instead\")     char* LZ5_slideInputBuffer (void* state);\n\n/* Obsolete streaming decoding functions */\nLZ5_DEPRECATED(\"use LZ5_decompress_safe_usingDict() instead\") int LZ5_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);\nLZ5_DEPRECATED(\"use LZ5_decompress_fast_usingDict() instead\") int LZ5_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5common.h",
    "content": "﻿#ifndef LZ5COMMON_H\n#define LZ5COMMON_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/**************************************\n*  Tuning parameters\n**************************************/\n/*\n * HEAPMODE :\n * Select how default compression functions will allocate memory for their hash table,\n * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).\n */\n#ifdef _MSC_VER\n\t#define HEAPMODE 1   /* Default stack size for VC++ is 1 MB and size of LZ5_stream_t exceeds that limit */ \n#else\n\t#define HEAPMODE 0\n#endif\n\n\n/*\n * ACCELERATION_DEFAULT :\n * Select \"acceleration\" for LZ5_compress_fast() when parameter value <= 0\n */\n#define ACCELERATION_DEFAULT 1\n\n\n\n\n/**************************************\n*  Compiler Options\n**************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4293)        /* disable: C4293: too large shift (32-bits) */\n#else\n#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)   /* C99 */\n#    if defined(__GNUC__) || defined(__clang__)\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif   /* __STDC_VERSION__ */\n#endif  /* _MSC_VER */\n\n#define LZ5_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n\n#if (LZ5_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)\n#  define expect(expr,value)    (__builtin_expect ((expr),(value)) )\n#else\n#  define expect(expr,value)    (expr)\n#endif\n\n#define likely(expr)     expect((expr) != 0, 1)\n#define unlikely(expr)   expect((expr) != 0, 0)\n\n\n\n/**************************************\n*  Memory routines\n**************************************/\n#include <stdlib.h>   /* malloc, calloc, free */\n#define ALLOCATOR(n,s) calloc(n,s)\n#define FREEMEM        free\n#include <string.h>   /* memset, memcpy */\n#define MEM_INIT       memset\n\n\n/**************************************\n*  Common Constants\n**************************************/\n#define MINMATCH 3 // should be 3 or 4\n\n#define WILDCOPYLENGTH 8\n#define LASTLITERALS 5\n#define MFLIMIT (WILDCOPYLENGTH+MINMATCH)\nstatic const int LZ5_minLength = (MFLIMIT+1);\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define MAXD_LOG 22\n#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)\n#define LZ5_DICT_SIZE (1 << MAXD_LOG)\n\n#define ML_BITS  3\n#define ML_MASK  ((1U<<ML_BITS)-1)\n#define RUN_BITS 3\n#define RUN_MASK ((1U<<RUN_BITS)-1)\n#define RUN_BITS2 2\n#define RUN_MASK2 ((1U<<RUN_BITS2)-1)\n#define ML_RUN_BITS (ML_BITS + RUN_BITS)\n#define ML_RUN_BITS2 (ML_BITS + RUN_BITS2)\n\n#define LZ5_SHORT_OFFSET_BITS 10\n#define LZ5_SHORT_OFFSET_DISTANCE (1<<LZ5_SHORT_OFFSET_BITS)\n#define LZ5_MID_OFFSET_BITS 16\n#define LZ5_MID_OFFSET_DISTANCE (1<<LZ5_MID_OFFSET_BITS)\n\n\n/**************************************\n*  Common Utils\n**************************************/\n#define LZ5_STATIC_ASSERT(c)    { enum { LZ5_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# include <stdint.h>\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/* *************************************\n*  HC Inline functions and Macros\n***************************************/\n#include \"mem.h\" // MEM_read\n#include \"lz5.h\" // LZ5HC_MAX_CLEVEL\n\n    \nstatic const U32 prime4bytes = 2654435761U;\nstatic const U64 prime5bytes = 889523592379ULL;\n\n#ifdef LZ5HC_INCLUDES\nstatic const U32 prime3bytes = 506832829U;\nstatic const U64 prime6bytes = 227718039650203ULL;\nstatic const U64 prime7bytes = 58295818150454627ULL;\n\nstatic U32 LZ5HC_hash3(U32 u, U32 h) { return (u * prime3bytes) << (32-24) >> (32-h) ; }\nstatic size_t LZ5HC_hash3Ptr(const void* ptr, U32 h) { return LZ5HC_hash3(MEM_read32(ptr), h); }\n\nstatic U32 LZ5HC_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }\nstatic size_t LZ5HC_hash4Ptr(const void* ptr, U32 h) { return LZ5HC_hash4(MEM_read32(ptr), h); }\n\nstatic size_t LZ5HC_hash5(U64 u, U32 h) { return (size_t)((u * prime5bytes) << (64-40) >> (64-h)) ; }\nstatic size_t LZ5HC_hash5Ptr(const void* p, U32 h) { return LZ5HC_hash5(MEM_read64(p), h); }\n\nstatic size_t LZ5HC_hash6(U64 u, U32 h) { return (size_t)((u * prime6bytes) << (64-48) >> (64-h)) ; }\nstatic size_t LZ5HC_hash6Ptr(const void* p, U32 h) { return LZ5HC_hash6(MEM_read64(p), h); }\n\nstatic size_t LZ5HC_hash7(U64 u, U32 h) { return (size_t)((u * prime7bytes) << (64-56) >> (64-h)) ; }\nstatic size_t LZ5HC_hash7Ptr(const void* p, U32 h) { return LZ5HC_hash7(MEM_read64(p), h); }\n\nstatic size_t LZ5HC_hashPtr(const void* p, U32 hBits, U32 mls)\n{\n    switch(mls)\n    {\n    default:\n    case 4: return LZ5HC_hash4Ptr(p, hBits);\n    case 5: return LZ5HC_hash5Ptr(p, hBits);\n    case 6: return LZ5HC_hash6Ptr(p, hBits);\n    case 7: return LZ5HC_hash7Ptr(p, hBits);\n    }\n}\n\n\n/**************************************\n*  HC Local Macros\n**************************************/\n#define LZ5HC_DEBUG(fmt, ...) //printf(fmt, __VA_ARGS__)\n#define LZ5_LOG_PARSER(fmt, ...) //printf(fmt, __VA_ARGS__)\n#define LZ5_LOG_PRICE(fmt, ...) //printf(fmt, __VA_ARGS__)\n#define LZ5_LOG_ENCODE(fmt, ...) //printf(fmt, __VA_ARGS__)\n\n#define MAX(a,b) ((a)>(b))?(a):(b)\n#define LZ5_OPT_NUM   (1<<12)\n\n#define LZ5_SHORT_LITERALS          ((1<<RUN_BITS2)-1)\n#define LZ5_LITERALS                ((1<<RUN_BITS)-1)\n\n#define LZ5_SHORT_LITLEN_COST(len)  (len<LZ5_SHORT_LITERALS ? 0 : (len-LZ5_SHORT_LITERALS < 255 ? 1 : (len-LZ5_SHORT_LITERALS-255 < (1<<7) ? 2 : 3)))\n#define LZ5_LEN_COST(len)           (len<LZ5_LITERALS ? 0 : (len-LZ5_LITERALS < 255 ? 1 : (len-LZ5_LITERALS-255 < (1<<7) ? 2 : 3)))\n\nstatic size_t LZ5_LIT_COST(size_t len, size_t offset){ return (len)+(((offset > LZ5_MID_OFFSET_DISTANCE) || (offset<LZ5_SHORT_OFFSET_DISTANCE)) ? LZ5_SHORT_LITLEN_COST(len) : LZ5_LEN_COST(len)); }\nstatic size_t LZ5_MATCH_COST(size_t mlen, size_t offset) { return LZ5_LEN_COST(mlen) + ((offset == 0) ? 1 : (offset<LZ5_SHORT_OFFSET_DISTANCE ? 2 : (offset<LZ5_MID_OFFSET_DISTANCE ? 3 : 4))); }\n\n#define LZ5_CODEWORD_COST(litlen,offset,mlen)   (LZ5_MATCH_COST(mlen,offset) + LZ5_LIT_COST(litlen,offset))\n#define LZ5_LIT_ONLY_COST(len)                  ((len)+(LZ5_LEN_COST(len))+1)\n\n#define LZ5_NORMAL_MATCH_COST(mlen,offset)  (LZ5_MATCH_COST(mlen,offset))\n#define LZ5_NORMAL_LIT_COST(len)            (len)\n\n\n\nFORCE_INLINE size_t LZ5HC_get_price(size_t litlen, size_t offset, size_t mlen)\n{\n\treturn LZ5_CODEWORD_COST(litlen, offset, mlen);\n}\n\nFORCE_INLINE size_t LZ5HC_better_price(size_t best_off, size_t best_common, size_t off, size_t common, size_t last_off)\n{\n  return LZ5_NORMAL_MATCH_COST(common - MINMATCH, (off == last_off) ? 0 : off) < LZ5_NORMAL_MATCH_COST(best_common - MINMATCH, (best_off == last_off) ? 0 : best_off) + (LZ5_NORMAL_LIT_COST(common - best_common) );\n}\n\n\nFORCE_INLINE size_t LZ5HC_more_profitable(size_t best_off, size_t best_common, size_t off, size_t common, size_t literals, size_t last_off)\n{\n\tsize_t sum;\n\t\n\tif (literals > 0)\n\t\tsum = MAX(common + literals, best_common);\n\telse\n\t\tsum = MAX(common, best_common - literals);\n\t\n//\treturn LZ5_CODEWORD_COST(sum - common, (off == last_off) ? 0 : (off), common - MINMATCH) <= LZ5_CODEWORD_COST(sum - best_common, (best_off == last_off) ? 0 : (best_off), best_common - MINMATCH);\n\treturn LZ5_NORMAL_MATCH_COST(common - MINMATCH, (off == last_off) ? 0 : off) + LZ5_NORMAL_LIT_COST(sum - common) <= LZ5_NORMAL_MATCH_COST(best_common - MINMATCH, (best_off == last_off) ? 0 : (best_off)) + LZ5_NORMAL_LIT_COST(sum - best_common);\n}\n\n#endif // LZ5HC_INCLUDES\n\n\n\n/* *************************************\n*  HC Types\n***************************************/\n/** from faster to stronger */\ntypedef enum { LZ5HC_fast, LZ5HC_price_fast, LZ5HC_lowest_price, LZ5HC_optimal_price, LZ5HC_optimal_price_bt } LZ5HC_strategy;\n\ntypedef struct\n{\n    U32 windowLog;     /* largest match distance : impact decompression buffer size */\n    U32 contentLog;    /* full search segment : larger == more compression, slower, more memory (useless for fast) */\n    U32 hashLog;       /* dispatch table : larger == more memory, faster*/\n    U32 hashLog3;      /* dispatch table : larger == more memory, faster*/\n    U32 searchNum;     /* nb of searches : larger == more compression, slower*/\n    U32 searchLength;  /* size of matches : larger == faster decompression */\n    U32 sufficientLength;  /* used only by optimal parser: size of matches which is acceptable: larger == more compression, slower */\n    U32 fullSearch;    /* used only by optimal parser: perform full search of matches: 1 == more compression, slower */\n    LZ5HC_strategy strategy;\n} LZ5HC_parameters;\n\n\nstruct LZ5HC_Data_s\n{\n    U32*   hashTable;\n    U32*   hashTable3;\n    U32*   chainTable;\n    const BYTE* end;        /* next block here to continue on current prefix */\n    const BYTE* base;       /* All index relative to this position */\n    const BYTE* dictBase;   /* alternate base for extDict */\n    const BYTE* inputBuffer;      /* for debugging */\n    const BYTE* outputBuffer;     /* for debugging */\n    U32   dictLimit;        /* below that point, need extDict */\n    U32   lowLimit;         /* below that point, no more dict */\n    U32   nextToUpdate;     /* index from which to continue dictionary update */\n    U32   compressionLevel;\n    U32   last_off;\n    LZ5HC_parameters params;\n};\n\ntypedef struct\n{\n\tint off;\n\tint len;\n\tint back;\n} LZ5HC_match_t;\n\ntypedef struct\n{\n\tint price;\n\tint off;\n\tint mlen;\n\tint litlen;\n   \tint rep;\n} LZ5HC_optimal_t;\n\n\n\n/* *************************************\n*  HC Pre-defined compression levels\n***************************************/\n\nstatic const int g_maxCompressionLevel = LZ5HC_MAX_CLEVEL;\nstatic const int LZ5HC_compressionLevel_default = 6;\n\nstatic const LZ5HC_parameters LZ5HC_defaultParameters[LZ5HC_MAX_CLEVEL+1] =\n{\n    /* windLog, contentLog,  H, H3,  Snum, SL, SuffL, FS, Strategy */\n    {        0,          0,  0,  0,     0,  0,     0,  0, LZ5HC_fast             }, // level 0 - never used\n    { MAXD_LOG,   MAXD_LOG, 13,  0,     4,  6,     0,  0, LZ5HC_fast             }, // level 1\n    { MAXD_LOG,   MAXD_LOG, 13,  0,     2,  6,     0,  0, LZ5HC_fast             }, // level 2\n    { MAXD_LOG,   MAXD_LOG, 13,  0,     1,  5,     0,  0, LZ5HC_fast             }, // level 3\n    { MAXD_LOG,   MAXD_LOG, 14, 13,     1,  4,     0,  0, LZ5HC_price_fast       }, // level 4\n    { MAXD_LOG,   MAXD_LOG, 17, 13,     1,  4,     0,  0, LZ5HC_price_fast       }, // level 5\n    { MAXD_LOG,   MAXD_LOG, 15, 13,     1,  4,     0,  0, LZ5HC_lowest_price     }, // level 6\n    { MAXD_LOG,   MAXD_LOG, 17, 13,     1,  4,     0,  0, LZ5HC_lowest_price     }, // level 7\n    { MAXD_LOG,   MAXD_LOG, 19, 16,     1,  4,     0,  0, LZ5HC_lowest_price     }, // level 8\n    { MAXD_LOG,   MAXD_LOG, 23, 16,     3,  4,     0,  0, LZ5HC_lowest_price     }, // level 9\n    { MAXD_LOG,   MAXD_LOG, 23, 16,     8,  4,     0,  0, LZ5HC_lowest_price     }, // level 10\n    { MAXD_LOG,   MAXD_LOG, 23, 16,     8,  4,    12,  0, LZ5HC_optimal_price    }, // level 11\n    { MAXD_LOG,   MAXD_LOG, 23, 16,     8,  4,    64,  0, LZ5HC_optimal_price    }, // level 12\n    { MAXD_LOG, MAXD_LOG+1, 23, 16,     8,  4,    64,  1, LZ5HC_optimal_price_bt }, // level 13\n    { MAXD_LOG, MAXD_LOG+1, 23, 16,   128,  4,    64,  1, LZ5HC_optimal_price_bt }, // level 14\n    { MAXD_LOG, MAXD_LOG+1, 28, 24, 1<<10,  4, 1<<10,  1, LZ5HC_optimal_price_bt }, // level 15\n//  {       10,         10, 10,  0,     0,  4,     0,  0, LZ5HC_fast          }, // min values\n//  {       24,         24, 28, 24, 1<<24,  7, 1<<24,  2, LZ5HC_optimal_price }, // max values\n};\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* LZ5COMMON_H */\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5frame.c",
    "content": "﻿/*\nLZ5 auto-framing library\nCopyright (C) 2011-2015, Yann Collet.\n\nBSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nYou can contact the author at :\n- LZ5 source repository : https://github.com/inikep/lz5\n- LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c\n*/\n\n/* LZ5F is a stand-alone API to create LZ5-compressed Frames\n*  in full conformance with specification v1.5.0\n*  All related operations, including memory management, are handled by the library.\n* */\n\n\n/**************************************\n*  Compiler Options\n**************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/**************************************\n*  Memory routines\n**************************************/\n#include <stdlib.h>   /* malloc, calloc, free */\n#define ALLOCATOR(s)   calloc(1,s)\n#define FREEMEM        free\n#include <string.h>   /* memset, memcpy, memmove */\n#include <stdio.h>\n#define MEM_INIT       memset\n\n\n/**************************************\n*  Includes\n**************************************/\n#include \"lz5frame_static.h\"\n#include \"lz5.h\"\n#include \"lz5hc.h\"\n#define XXH_STATIC_LINKING_ONLY\n#include \"xxhash.h\"\n\n\n/**************************************\n*  Basic Types\n**************************************/\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)   /* C99 */\n# include <stdint.h>\ntypedef  uint8_t BYTE;\ntypedef uint16_t U16;\ntypedef uint32_t U32;\ntypedef  int32_t S32;\ntypedef uint64_t U64;\n#else\ntypedef unsigned char       BYTE;\ntypedef unsigned short      U16;\ntypedef unsigned int        U32;\ntypedef   signed int        S32;\ntypedef unsigned long long  U64;\n#endif\n\n\n/**************************************\n*  Constants\n**************************************/\n#define KB *(1<<10)\n#define MB *(1<<20)\n#define GB *(1<<30)\n\n#define _1BIT  0x01\n#define _2BITS 0x03\n#define _3BITS 0x07\n#define _4BITS 0x0F\n#define _8BITS 0xFF\n\n#define LZ5F_MAGIC_SKIPPABLE_START 0x184D2A50U\n#define LZ5F_MAGICNUMBER 0x184D2205U\n#define LZ5F_BLOCKUNCOMPRESSED_FLAG 0x80000000U\n#define LZ5F_BLOCKSIZEID_DEFAULT LZ5F_max64KB\n#define LZ5F_DICT_SIZE (1 << 22)\n\nstatic const size_t minFHSize = 7;\nstatic const size_t maxFHSize = 15;\nstatic const size_t BHSize = 4;\nstatic const int    minHClevel = 1;\n\n\n/**************************************\n*  Structures and local types\n**************************************/\ntypedef struct LZ5F_cctx_s\n{\n    LZ5F_preferences_t prefs;\n    U32    version;\n    U32    cStage;\n    size_t maxBlockSize;\n    size_t maxBufferSize;\n    BYTE*  tmpBuff;\n    BYTE*  tmpIn;\n    size_t tmpInSize;\n    U64    totalInSize;\n    XXH32_state_t xxh;\n    void*  lz5CtxPtr;\n    U32    lz5CtxLevel;     /* 0: unallocated;  1: LZ5_stream_t;  3: LZ5_streamHC_t */\n} LZ5F_cctx_t;\n\ntypedef struct LZ5F_dctx_s\n{\n    LZ5F_frameInfo_t frameInfo;\n    U32    version;\n    U32    dStage;\n    U64    frameRemainingSize;\n    size_t maxBlockSize;\n    size_t maxBufferSize;\n    const BYTE* srcExpect;\n    BYTE*  tmpIn;\n    size_t tmpInSize;\n    size_t tmpInTarget;\n    BYTE*  tmpOutBuffer;\n    const BYTE*  dict;\n    size_t dictSize;\n    BYTE*  tmpOut;\n    size_t tmpOutSize;\n    size_t tmpOutStart;\n    XXH32_state_t xxh;\n    BYTE   header[16];\n} LZ5F_dctx_t;\n\n\n/**************************************\n*  Error management\n**************************************/\n#define LZ5F_GENERATE_STRING(STRING) #STRING,\nstatic const char* LZ5F_errorStrings[] = { LZ5F_LIST_ERRORS(LZ5F_GENERATE_STRING) };\n\n\nunsigned LZ5F_isError(LZ5F_errorCode_t code)\n{\n    return (code > (LZ5F_errorCode_t)(-LZ5F_ERROR_maxCode));\n}\n\nconst char* LZ5F_getErrorName(LZ5F_errorCode_t code)\n{\n    static const char* codeError = \"Unspecified error code\";\n    if (LZ5F_isError(code)) return LZ5F_errorStrings[-(int)(code)];\n    return codeError;\n}\n\n\n/**************************************\n*  Private functions\n**************************************/\nstatic size_t LZ5F_getBlockSize(unsigned blockSizeID)\n{\n    static const size_t blockSizes[7] = { 64 KB, 256 KB, 1 MB, 4 MB, 16 MB, 64 MB, 256 MB };\n\n    if (blockSizeID == 0) blockSizeID = LZ5F_BLOCKSIZEID_DEFAULT;\n    blockSizeID -= 1;\n    if (blockSizeID >= 7) return (size_t)-LZ5F_ERROR_maxBlockSize_invalid;\n\n  //  printf(\"LZ5F_getBlockSize %d %d\\n\", blockSizeID+1, (int)blockSizes[blockSizeID]);\n    return blockSizes[blockSizeID];\n}\n\n\n/* unoptimized version; solves endianess & alignment issues */\nstatic U32 LZ5F_readLE32 (const BYTE* srcPtr)\n{\n    U32 value32 = srcPtr[0];\n    value32 += (srcPtr[1]<<8);\n    value32 += (srcPtr[2]<<16);\n    value32 += ((U32)srcPtr[3])<<24;\n    return value32;\n}\n\nstatic void LZ5F_writeLE32 (BYTE* dstPtr, U32 value32)\n{\n    dstPtr[0] = (BYTE)value32;\n    dstPtr[1] = (BYTE)(value32 >> 8);\n    dstPtr[2] = (BYTE)(value32 >> 16);\n    dstPtr[3] = (BYTE)(value32 >> 24);\n}\n\nstatic U64 LZ5F_readLE64 (const BYTE* srcPtr)\n{\n    U64 value64 = srcPtr[0];\n    value64 += ((U64)srcPtr[1]<<8);\n    value64 += ((U64)srcPtr[2]<<16);\n    value64 += ((U64)srcPtr[3]<<24);\n    value64 += ((U64)srcPtr[4]<<32);\n    value64 += ((U64)srcPtr[5]<<40);\n    value64 += ((U64)srcPtr[6]<<48);\n    value64 += ((U64)srcPtr[7]<<56);\n    return value64;\n}\n\nstatic void LZ5F_writeLE64 (BYTE* dstPtr, U64 value64)\n{\n    dstPtr[0] = (BYTE)value64;\n    dstPtr[1] = (BYTE)(value64 >> 8);\n    dstPtr[2] = (BYTE)(value64 >> 16);\n    dstPtr[3] = (BYTE)(value64 >> 24);\n    dstPtr[4] = (BYTE)(value64 >> 32);\n    dstPtr[5] = (BYTE)(value64 >> 40);\n    dstPtr[6] = (BYTE)(value64 >> 48);\n    dstPtr[7] = (BYTE)(value64 >> 56);\n}\n\n\nstatic BYTE LZ5F_headerChecksum (const void* header, size_t length)\n{\n    U32 xxh = XXH32(header, length, 0);\n    return (BYTE)(xxh >> 8);\n}\n\n\n/**************************************\n*  Simple compression functions\n**************************************/\nstatic LZ5F_blockSizeID_t LZ5F_optimalBSID(const LZ5F_blockSizeID_t requestedBSID, const size_t srcSize)\n{\n    LZ5F_blockSizeID_t proposedBSID = LZ5F_max64KB;\n    size_t maxBlockSize = 64 KB;\n    while (requestedBSID > proposedBSID)\n    {\n        if (srcSize <= maxBlockSize)\n            return proposedBSID;\n        proposedBSID = (LZ5F_blockSizeID_t)((int)proposedBSID + 1);\n        maxBlockSize <<= 2;\n    }\n    return requestedBSID;\n}\n\n\nvoid LZ5F_freeStream(LZ5F_cctx_t* cctxPtr)\n{\n    if (cctxPtr->lz5CtxLevel == 1)\n        LZ5_freeStream((LZ5_stream_t*)cctxPtr->lz5CtxPtr);\n    else if (cctxPtr->lz5CtxLevel == 2)\n        LZ5_freeStreamHC((LZ5_streamHC_t*)cctxPtr->lz5CtxPtr);\n    cctxPtr->lz5CtxLevel = 0;\n}\n\n\nsize_t LZ5F_compressFrameBound(size_t srcSize, const LZ5F_preferences_t* preferencesPtr)\n{\n    LZ5F_preferences_t prefs;\n    size_t headerSize;\n    size_t streamSize;\n\n    if (preferencesPtr!=NULL) prefs = *preferencesPtr;\n    else memset(&prefs, 0, sizeof(prefs));\n\n    prefs.frameInfo.blockSizeID = LZ5F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);\n    prefs.autoFlush = 1;\n\n    headerSize = maxFHSize;      /* header size, including magic number and frame content size*/\n    streamSize = LZ5F_compressBound(srcSize, &prefs);\n\n    return headerSize + streamSize;\n}\n\n\n/* LZ5F_compressFrame()\n* Compress an entire srcBuffer into a valid LZ5 frame, as defined by specification v1.5.0, in a single step.\n* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n* You can get the minimum value of dstMaxSize by using LZ5F_compressFrameBound()\n* If this condition is not respected, LZ5F_compressFrame() will fail (result is an errorCode)\n* The LZ5F_preferences_t structure is optional : you can provide NULL as argument. All preferences will then be set to default.\n* The result of the function is the number of bytes written into dstBuffer.\n* The function outputs an error code if it fails (can be tested using LZ5F_isError())\n*/\nsize_t LZ5F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ5F_preferences_t* preferencesPtr)\n{\n    LZ5F_cctx_t cctxI;\n    LZ5F_preferences_t prefs;\n    LZ5F_compressOptions_t options;\n    LZ5F_errorCode_t errorCode;\n    BYTE* const dstStart = (BYTE*) dstBuffer;\n    BYTE* dstPtr = dstStart;\n    BYTE* const dstEnd = dstStart + dstMaxSize;\n\n    memset(&cctxI, 0, sizeof(cctxI));   /* works because no allocation */\n    memset(&options, 0, sizeof(options));\n\n    cctxI.version = LZ5F_VERSION;\n    cctxI.maxBufferSize = 5 MB;   /* mess with real buffer size to prevent allocation; works because autoflush==1 & stableSrc==1 */\n\n    if (preferencesPtr!=NULL)\n        prefs = *preferencesPtr;\n    else\n        memset(&prefs, 0, sizeof(prefs));\n    if (prefs.frameInfo.contentSize != 0)\n        prefs.frameInfo.contentSize = (U64)srcSize;   /* auto-correct content size if selected (!=0) */\n\n    prefs.frameInfo.blockSizeID = LZ5F_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);\n    prefs.autoFlush = 1;\n    if (srcSize <= LZ5F_getBlockSize(prefs.frameInfo.blockSizeID))\n        prefs.frameInfo.blockMode = LZ5F_blockIndependent;   /* no need for linked blocks */\n\n    options.stableSrc = 1;\n\n    if (dstMaxSize < LZ5F_compressFrameBound(srcSize, &prefs))\n        return (size_t)-LZ5F_ERROR_dstMaxSize_tooSmall;\n\n    errorCode = LZ5F_compressBegin(&cctxI, dstBuffer, dstMaxSize, &prefs);  /* write header */\n    if (LZ5F_isError(errorCode)) return errorCode;\n    dstPtr += errorCode;   /* header size */\n\n    errorCode = LZ5F_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options);\n    if (LZ5F_isError(errorCode)) return errorCode;\n    dstPtr += errorCode;\n\n    errorCode = LZ5F_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options);   /* flush last block, and generate suffix */\n    if (LZ5F_isError(errorCode)) return errorCode;\n    dstPtr += errorCode;\n\n    LZ5F_freeStream(&cctxI);\n\n    return (dstPtr - dstStart);\n}\n\n\n/***********************************\n*  Advanced compression functions\n***********************************/\n\n/* LZ5F_createCompressionContext() :\n* The first thing to do is to create a compressionContext object, which will be used in all compression operations.\n* This is achieved using LZ5F_createCompressionContext(), which takes as argument a version and an LZ5F_preferences_t structure.\n* The version provided MUST be LZ5F_VERSION. It is intended to track potential version differences between different binaries.\n* The function will provide a pointer to an allocated LZ5F_compressionContext_t object.\n* If the result LZ5F_errorCode_t is not OK_NoError, there was an error during context creation.\n* Object can release its memory using LZ5F_freeCompressionContext();\n*/\nLZ5F_errorCode_t LZ5F_createCompressionContext(LZ5F_compressionContext_t* LZ5F_compressionContextPtr, unsigned version)\n{\n    LZ5F_cctx_t* cctxPtr;\n\n    cctxPtr = (LZ5F_cctx_t*)ALLOCATOR(sizeof(LZ5F_cctx_t));\n    if (cctxPtr==NULL) return (LZ5F_errorCode_t)(-LZ5F_ERROR_allocation_failed);\n\n    cctxPtr->version = version;\n    cctxPtr->cStage = 0;   /* Next stage : write header */\n\n    *LZ5F_compressionContextPtr = (LZ5F_compressionContext_t)cctxPtr;\n\n    return LZ5F_OK_NoError;\n}\n\n\nLZ5F_errorCode_t LZ5F_freeCompressionContext(LZ5F_compressionContext_t LZ5F_compressionContext)\n{\n    LZ5F_cctx_t* cctxPtr = (LZ5F_cctx_t*)LZ5F_compressionContext;\n\n    if (cctxPtr != NULL)   /* null pointers can be safely provided to this function, like free() */\n    {\n        LZ5F_freeStream(cctxPtr);\n        FREEMEM(cctxPtr->tmpBuff);\n        FREEMEM(LZ5F_compressionContext);\n    }\n\n    return LZ5F_OK_NoError;\n}\n\n\n/* LZ5F_compressBegin() :\n* will write the frame header into dstBuffer.\n* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is LZ5F_MAXHEADERFRAME_SIZE bytes.\n* The result of the function is the number of bytes written into dstBuffer for the header\n* or an error code (can be tested using LZ5F_isError())\n*/\nsize_t LZ5F_compressBegin(LZ5F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ5F_preferences_t* preferencesPtr)\n{\n    LZ5F_preferences_t prefNull;\n    LZ5F_cctx_t* cctxPtr = (LZ5F_cctx_t*)compressionContext;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    BYTE* headerStart;\n    size_t requiredBuffSize;\n\n    if (dstMaxSize < maxFHSize) return (size_t)-LZ5F_ERROR_dstMaxSize_tooSmall;\n    if (cctxPtr->cStage != 0) return (size_t)-LZ5F_ERROR_GENERIC;\n    memset(&prefNull, 0, sizeof(prefNull));\n    if (preferencesPtr == NULL) preferencesPtr = &prefNull;\n    cctxPtr->prefs = *preferencesPtr;\n    cctxPtr->prefs.frameInfo.blockMode = LZ5F_blockIndependent;\n\n    /* ctx Management */\n    {\n        U32 tableID = (cctxPtr->prefs.compressionLevel < minHClevel) ? 1 : 2;  /* 0:nothing ; 1:LZ5_createStream ; 2:LZ5_createStreamHC */\n      //  printf(\"BEFORE lz5CtxLevel=%d tableID=%d compressionLevel=%d minHClevel=%d\\n\", (int)cctxPtr->lz5CtxLevel, (int)tableID, (int)cctxPtr->prefs.compressionLevel, minHClevel);\n        if (cctxPtr->lz5CtxLevel != tableID)\n        {\n            LZ5F_freeStream(cctxPtr);\n\n            cctxPtr->lz5CtxLevel = tableID;\n            if (cctxPtr->lz5CtxLevel == 1)\n                cctxPtr->lz5CtxPtr = (void*)LZ5_createStream();\n            else\n                cctxPtr->lz5CtxPtr = (void*)LZ5_createStreamHC(cctxPtr->prefs.compressionLevel);\n        }\n    }\n\n    /* Buffer Management */\n    if (cctxPtr->prefs.frameInfo.blockSizeID == 0) cctxPtr->prefs.frameInfo.blockSizeID = LZ5F_BLOCKSIZEID_DEFAULT;\n    cctxPtr->maxBlockSize = LZ5F_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);\n\n    requiredBuffSize = cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LZ5F_blockLinked) * 2 * LZ5F_DICT_SIZE);\n    if (preferencesPtr->autoFlush)\n        requiredBuffSize = (cctxPtr->prefs.frameInfo.blockMode == LZ5F_blockLinked) * LZ5F_DICT_SIZE;   /* just needs dict */\n\n    if (cctxPtr->maxBufferSize < requiredBuffSize)\n    {\n        cctxPtr->maxBufferSize = requiredBuffSize;\n        FREEMEM(cctxPtr->tmpBuff);\n        cctxPtr->tmpBuff = (BYTE*)ALLOCATOR(requiredBuffSize);\n        if (cctxPtr->tmpBuff == NULL) return (size_t)-LZ5F_ERROR_allocation_failed;\n    }\n    cctxPtr->tmpIn = cctxPtr->tmpBuff;\n    cctxPtr->tmpInSize = 0;\n    XXH32_reset(&(cctxPtr->xxh), 0);\n    if (cctxPtr->prefs.compressionLevel < minHClevel)\n        LZ5_resetStream((LZ5_stream_t*)(cctxPtr->lz5CtxPtr));\n    else\n        LZ5_resetStreamHC((LZ5_streamHC_t*)(cctxPtr->lz5CtxPtr));\n\n    /* Magic Number */\n    LZ5F_writeLE32(dstPtr, LZ5F_MAGICNUMBER);\n    dstPtr += 4;\n    headerStart = dstPtr;\n\n    /* FLG Byte */\n    *dstPtr++ = (BYTE)(((1 & _2BITS) << 6)    /* Version('01') */\n        + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5)    /* Block mode */\n        + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2)   /* Frame checksum */\n        + ((cctxPtr->prefs.frameInfo.contentSize > 0) << 3));   /* Frame content size */\n    /* BD Byte */\n    *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);\n    /* Optional Frame content size field */\n    if (cctxPtr->prefs.frameInfo.contentSize)\n    {\n        LZ5F_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize);\n        dstPtr += 8;\n        cctxPtr->totalInSize = 0;\n    }\n    /* CRC Byte */\n    *dstPtr = LZ5F_headerChecksum(headerStart, dstPtr - headerStart);\n    dstPtr++;\n\n    cctxPtr->cStage = 1;   /* header written, now request input data block */\n\n    return (dstPtr - dstStart);\n}\n\n\n/* LZ5F_compressBound() : gives the size of Dst buffer given a srcSize to handle worst case situations.\n*                        The LZ5F_frameInfo_t structure is optional :\n*                        you can provide NULL as argument, preferences will then be set to cover worst case situations.\n* */\nsize_t LZ5F_compressBound(size_t srcSize, const LZ5F_preferences_t* preferencesPtr)\n{\n    LZ5F_preferences_t prefsNull;\n    memset(&prefsNull, 0, sizeof(prefsNull));\n    prefsNull.frameInfo.contentChecksumFlag = LZ5F_contentChecksumEnabled;   /* worst case */\n    {\n        const LZ5F_preferences_t* prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;\n        LZ5F_blockSizeID_t bid = prefsPtr->frameInfo.blockSizeID;\n        size_t blockSize = LZ5F_getBlockSize(bid);\n        unsigned nbBlocks = (unsigned)(srcSize / blockSize) + 1;\n        size_t lastBlockSize = prefsPtr->autoFlush ? srcSize % blockSize : blockSize;\n        size_t blockInfo = 4;   /* default, without block CRC option */\n        size_t frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);\n\n        return (blockInfo * nbBlocks) + (blockSize * (nbBlocks-1)) + lastBlockSize + frameEnd;;\n    }\n}\n\n\ntypedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize);\n\nstatic size_t LZ5F_compressBlock(void* dst, const void* src, size_t srcSize, compressFunc_t compress, void* lz5ctx)\n{\n    /* compress one block */\n    BYTE* cSizePtr = (BYTE*)dst;\n    U32 cSize;\n    cSize = (U32)compress(lz5ctx, (const char*)src, (char*)(cSizePtr+4), (int)(srcSize), (int)(srcSize-1));\n    LZ5F_writeLE32(cSizePtr, cSize);\n    if (cSize == 0)   /* compression failed */\n    {\n        cSize = (U32)srcSize;\n        LZ5F_writeLE32(cSizePtr, cSize + LZ5F_BLOCKUNCOMPRESSED_FLAG);\n        memcpy(cSizePtr+4, src, srcSize);\n    }\n    return cSize + 4;\n}\n\n\nstatic int LZ5F_localLZ5_compress_limitedOutput_withState(void* ctx, const char* src, char* dst, int srcSize, int dstSize)\n{\n    return LZ5_compress_limitedOutput_withState(ctx, src, dst, srcSize, dstSize);\n}\n\nstatic int LZ5F_localLZ5_compress_limitedOutput_continue(void* ctx, const char* src, char* dst, int srcSize, int dstSize)\n{\n    return LZ5_compress_limitedOutput_continue((LZ5_stream_t*)ctx, src, dst, srcSize, dstSize);\n}\n\nstatic int LZ5F_localLZ5_compressHC_limitedOutput_continue(void* ctx, const char* src, char* dst, int srcSize, int dstSize)\n{\n    return LZ5_compress_HC_continue((LZ5_streamHC_t*)ctx, src, dst, srcSize, dstSize);\n}\n\nstatic compressFunc_t LZ5F_selectCompression(LZ5F_blockMode_t blockMode, int level)\n{\n    if (level < minHClevel)\n    {\n        if (blockMode == LZ5F_blockIndependent) return LZ5F_localLZ5_compress_limitedOutput_withState;\n        return LZ5F_localLZ5_compress_limitedOutput_continue;\n    }\n    if (blockMode == LZ5F_blockIndependent) return LZ5_compress_HC_extStateHC;\n    return LZ5F_localLZ5_compressHC_limitedOutput_continue;\n}\n\nstatic int LZ5F_localSaveDict(LZ5F_cctx_t* cctxPtr)\n{\n    if (cctxPtr->prefs.compressionLevel < minHClevel)\n        return LZ5_saveDict ((LZ5_stream_t*)(cctxPtr->lz5CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);\n    return LZ5_saveDictHC ((LZ5_streamHC_t*)(cctxPtr->lz5CtxPtr), (char*)(cctxPtr->tmpBuff), 64 KB);\n}\n\ntypedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LZ5F_lastBlockStatus;\n\n/* LZ5F_compressUpdate()\n* LZ5F_compressUpdate() can be called repetitively to compress as much data as necessary.\n* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n* If this condition is not respected, LZ5F_compress() will fail (result is an errorCode)\n* You can get the minimum value of dstMaxSize by using LZ5F_compressBound()\n* The LZ5F_compressOptions_t structure is optional : you can provide NULL as argument.\n* The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.\n* The function outputs an error code if it fails (can be tested using LZ5F_isError())\n*/\nsize_t LZ5F_compressUpdate(LZ5F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ5F_compressOptions_t* compressOptionsPtr)\n{\n    LZ5F_compressOptions_t cOptionsNull;\n    LZ5F_cctx_t* cctxPtr = (LZ5F_cctx_t*)compressionContext;\n    size_t blockSize = cctxPtr->maxBlockSize;\n    const BYTE* srcPtr = (const BYTE*)srcBuffer;\n    const BYTE* const srcEnd = srcPtr + srcSize;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    LZ5F_lastBlockStatus lastBlockCompressed = notDone;\n    compressFunc_t compress;\n\n\n    if (cctxPtr->cStage != 1) return (size_t)-LZ5F_ERROR_GENERIC;\n    if (dstMaxSize < LZ5F_compressBound(srcSize, &(cctxPtr->prefs))) return (size_t)-LZ5F_ERROR_dstMaxSize_tooSmall;\n    memset(&cOptionsNull, 0, sizeof(cOptionsNull));\n    if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;\n\n    /* select compression function */\n    compress = LZ5F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);\n\n    /* complete tmp buffer */\n    if (cctxPtr->tmpInSize > 0)   /* some data already within tmp buffer */\n    {\n        size_t sizeToCopy = blockSize - cctxPtr->tmpInSize;\n        if (sizeToCopy > srcSize)\n        {\n            /* add src to tmpIn buffer */\n            memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);\n            srcPtr = srcEnd;\n            cctxPtr->tmpInSize += srcSize;\n            /* still needs some CRC */\n        }\n        else\n        {\n            /* complete tmpIn block and then compress it */\n            lastBlockCompressed = fromTmpBuffer;\n            memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);\n            srcPtr += sizeToCopy;\n\n            dstPtr += LZ5F_compressBlock(dstPtr, cctxPtr->tmpIn, blockSize, compress, cctxPtr->lz5CtxPtr);\n\n            if (cctxPtr->prefs.frameInfo.blockMode==LZ5F_blockLinked) cctxPtr->tmpIn += blockSize;\n            cctxPtr->tmpInSize = 0;\n        }\n    }\n\n    while ((size_t)(srcEnd - srcPtr) >= blockSize)\n    {\n        /* compress full block */\n        lastBlockCompressed = fromSrcBuffer;\n        dstPtr += LZ5F_compressBlock(dstPtr, srcPtr, blockSize, compress, cctxPtr->lz5CtxPtr);\n        srcPtr += blockSize;\n    }\n\n    if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd))\n    {\n        /* compress remaining input < blockSize */\n        lastBlockCompressed = fromSrcBuffer;\n        dstPtr += LZ5F_compressBlock(dstPtr, srcPtr, srcEnd - srcPtr, compress, cctxPtr->lz5CtxPtr);\n        srcPtr  = srcEnd;\n    }\n\n    /* preserve dictionary if necessary */\n    if ((cctxPtr->prefs.frameInfo.blockMode==LZ5F_blockLinked) && (lastBlockCompressed==fromSrcBuffer))\n    {\n        if (compressOptionsPtr->stableSrc)\n        {\n            cctxPtr->tmpIn = cctxPtr->tmpBuff;\n        }\n        else\n        {\n            int realDictSize = LZ5F_localSaveDict(cctxPtr);\n            if (realDictSize==0) return (size_t)-LZ5F_ERROR_GENERIC;\n            cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n        }\n    }\n\n    /* keep tmpIn within limits */\n    if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)   /* necessarily LZ5F_blockLinked && lastBlockCompressed==fromTmpBuffer */\n        && !(cctxPtr->prefs.autoFlush))\n    {\n        int realDictSize = LZ5F_localSaveDict(cctxPtr);\n        cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n    }\n\n    /* some input data left, necessarily < blockSize */\n    if (srcPtr < srcEnd)\n    {\n        /* fill tmp buffer */\n        size_t sizeToCopy = srcEnd - srcPtr;\n        memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);\n        cctxPtr->tmpInSize = sizeToCopy;\n    }\n\n    if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ5F_contentChecksumEnabled)\n        XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);\n\n    cctxPtr->totalInSize += srcSize;\n    return dstPtr - dstStart;\n}\n\n\n/* LZ5F_flush()\n* Should you need to create compressed data immediately, without waiting for a block to be filled,\n* you can call LZ5_flush(), which will immediately compress any remaining data stored within compressionContext.\n* The result of the function is the number of bytes written into dstBuffer\n* (it can be zero, this means there was no data left within compressionContext)\n* The function outputs an error code if it fails (can be tested using LZ5F_isError())\n* The LZ5F_compressOptions_t structure is optional : you can provide NULL as argument.\n*/\nsize_t LZ5F_flush(LZ5F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ5F_compressOptions_t* compressOptionsPtr)\n{\n    LZ5F_cctx_t* cctxPtr = (LZ5F_cctx_t*)compressionContext;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    compressFunc_t compress;\n\n\n    if (cctxPtr->tmpInSize == 0) return 0;   /* nothing to flush */\n    if (cctxPtr->cStage != 1) return (size_t)-LZ5F_ERROR_GENERIC;\n    if (dstMaxSize < (cctxPtr->tmpInSize + 8)) return (size_t)-LZ5F_ERROR_dstMaxSize_tooSmall;   /* +8 : block header(4) + block checksum(4) */\n    (void)compressOptionsPtr;   /* not yet useful */\n\n    /* select compression function */\n    compress = LZ5F_selectCompression(cctxPtr->prefs.frameInfo.blockMode, cctxPtr->prefs.compressionLevel);\n\n    /* compress tmp buffer */\n    dstPtr += LZ5F_compressBlock(dstPtr, cctxPtr->tmpIn, cctxPtr->tmpInSize, compress, cctxPtr->lz5CtxPtr);\n    if (cctxPtr->prefs.frameInfo.blockMode==LZ5F_blockLinked) cctxPtr->tmpIn += cctxPtr->tmpInSize;\n    cctxPtr->tmpInSize = 0;\n\n    /* keep tmpIn within limits */\n    if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize))   /* necessarily LZ5F_blockLinked */\n    {\n        int realDictSize = LZ5F_localSaveDict(cctxPtr);\n        cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n    }\n\n    return dstPtr - dstStart;\n}\n\n\n/* LZ5F_compressEnd()\n* When you want to properly finish the compressed frame, just call LZ5F_compressEnd().\n* It will flush whatever data remained within compressionContext (like LZ5_flush())\n* but also properly finalize the frame, with an endMark and a checksum.\n* The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))\n* The function outputs an error code if it fails (can be tested using LZ5F_isError())\n* The LZ5F_compressOptions_t structure is optional : you can provide NULL as argument.\n* compressionContext can then be used again, starting with LZ5F_compressBegin(). The preferences will remain the same.\n*/\nsize_t LZ5F_compressEnd(LZ5F_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LZ5F_compressOptions_t* compressOptionsPtr)\n{\n    LZ5F_cctx_t* cctxPtr = (LZ5F_cctx_t*)compressionContext;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    size_t errorCode;\n\n    errorCode = LZ5F_flush(compressionContext, dstBuffer, dstMaxSize, compressOptionsPtr);\n    if (LZ5F_isError(errorCode)) return errorCode;\n    dstPtr += errorCode;\n\n    LZ5F_writeLE32(dstPtr, 0);\n    dstPtr+=4;   /* endMark */\n\n    if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LZ5F_contentChecksumEnabled)\n    {\n        U32 xxh = XXH32_digest(&(cctxPtr->xxh));\n        LZ5F_writeLE32(dstPtr, xxh);\n        dstPtr+=4;   /* content Checksum */\n    }\n\n    cctxPtr->cStage = 0;   /* state is now re-usable (with identical preferences) */\n\n    if (cctxPtr->prefs.frameInfo.contentSize)\n    {\n        if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)\n            return (size_t)-LZ5F_ERROR_frameSize_wrong;\n    }\n\n    return dstPtr - dstStart;\n}\n\n\n/**********************************\n*  Decompression functions\n**********************************/\n\n/* Resource management */\n\n/* LZ5F_createDecompressionContext() :\n* The first thing to do is to create a decompressionContext object, which will be used in all decompression operations.\n* This is achieved using LZ5F_createDecompressionContext().\n* The function will provide a pointer to a fully allocated and initialized LZ5F_decompressionContext object.\n* If the result LZ5F_errorCode_t is not zero, there was an error during context creation.\n* Object can release its memory using LZ5F_freeDecompressionContext();\n*/\nLZ5F_errorCode_t LZ5F_createDecompressionContext(LZ5F_decompressionContext_t* LZ5F_decompressionContextPtr, unsigned versionNumber)\n{\n    LZ5F_dctx_t* dctxPtr;\n\n    dctxPtr = (LZ5F_dctx_t*)ALLOCATOR(sizeof(LZ5F_dctx_t));\n    if (dctxPtr==NULL) return (LZ5F_errorCode_t)-LZ5F_ERROR_GENERIC;\n\n    dctxPtr->version = versionNumber;\n    *LZ5F_decompressionContextPtr = (LZ5F_decompressionContext_t)dctxPtr;\n    return LZ5F_OK_NoError;\n}\n\nLZ5F_errorCode_t LZ5F_freeDecompressionContext(LZ5F_decompressionContext_t LZ5F_decompressionContext)\n{\n    LZ5F_errorCode_t result = LZ5F_OK_NoError;\n    LZ5F_dctx_t* dctxPtr = (LZ5F_dctx_t*)LZ5F_decompressionContext;\n    if (dctxPtr != NULL)   /* can accept NULL input, like free() */\n    {\n      result = (LZ5F_errorCode_t)dctxPtr->dStage;\n      FREEMEM(dctxPtr->tmpIn);\n      FREEMEM(dctxPtr->tmpOutBuffer);\n      FREEMEM(dctxPtr);\n    }\n    return result;\n}\n\n\n/* ******************************************************************** */\n/* ********************* Decompression ******************************** */\n/* ******************************************************************** */\n\ntypedef enum { dstage_getHeader=0, dstage_storeHeader,\n    dstage_getCBlockSize, dstage_storeCBlockSize,\n    dstage_copyDirect,\n    dstage_getCBlock, dstage_storeCBlock,\n    dstage_decodeCBlock, dstage_decodeCBlock_intoDst,\n    dstage_decodeCBlock_intoTmp, dstage_flushOut,\n    dstage_getSuffix, dstage_storeSuffix,\n    dstage_getSFrameSize, dstage_storeSFrameSize,\n    dstage_skipSkippable\n} dStage_t;\n\n\n/* LZ5F_decodeHeader\n   return : nb Bytes read from srcVoidPtr (necessarily <= srcSize)\n            or an error code (testable with LZ5F_isError())\n   output : set internal values of dctx, such as\n            dctxPtr->frameInfo and dctxPtr->dStage.\n   input  : srcVoidPtr points at the **beginning of the frame**\n*/\nstatic size_t LZ5F_decodeHeader(LZ5F_dctx_t* dctxPtr, const void* srcVoidPtr, size_t srcSize)\n{\n    BYTE FLG, BD, HC;\n    unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, blockSizeID;\n    size_t bufferNeeded;\n    size_t frameHeaderSize;\n    const BYTE* srcPtr = (const BYTE*)srcVoidPtr;\n\n    /* need to decode header to get frameInfo */\n    if (srcSize < minFHSize) return (size_t)-LZ5F_ERROR_frameHeader_incomplete;   /* minimal frame header size */\n    memset(&(dctxPtr->frameInfo), 0, sizeof(dctxPtr->frameInfo));\n\n    /* special case : skippable frames */\n    if ((LZ5F_readLE32(srcPtr) & 0xFFFFFFF0U) == LZ5F_MAGIC_SKIPPABLE_START)\n    {\n        dctxPtr->frameInfo.frameType = LZ5F_skippableFrame;\n        if (srcVoidPtr == (void*)(dctxPtr->header))\n        {\n            dctxPtr->tmpInSize = srcSize;\n            dctxPtr->tmpInTarget = 8;\n            dctxPtr->dStage = dstage_storeSFrameSize;\n            return srcSize;\n        }\n        else\n        {\n            dctxPtr->dStage = dstage_getSFrameSize;\n            return 4;\n        }\n    }\n\n    /* control magic number */\n    if (LZ5F_readLE32(srcPtr) != LZ5F_MAGICNUMBER) return (size_t)-LZ5F_ERROR_frameType_unknown;\n    dctxPtr->frameInfo.frameType = LZ5F_frame;\n\n    /* Flags */\n    FLG = srcPtr[4];\n    version = (FLG>>6) & _2BITS;\n    blockMode = (FLG>>5) & _1BIT;\n    blockChecksumFlag = (FLG>>4) & _1BIT;\n    contentSizeFlag = (FLG>>3) & _1BIT;\n    contentChecksumFlag = (FLG>>2) & _1BIT;\n\n    /* Frame Header Size */\n    frameHeaderSize = contentSizeFlag ? maxFHSize : minFHSize;\n\n    if (srcSize < frameHeaderSize)\n    {\n        /* not enough input to fully decode frame header */\n        if (srcPtr != dctxPtr->header)\n            memcpy(dctxPtr->header, srcPtr, srcSize);\n        dctxPtr->tmpInSize = srcSize;\n        dctxPtr->tmpInTarget = frameHeaderSize;\n        dctxPtr->dStage = dstage_storeHeader;\n        return srcSize;\n    }\n\n    BD = srcPtr[5];\n    blockSizeID = (BD>>4) & _3BITS;\n\n    /* validate */\n    if (version != 1) return (size_t)-LZ5F_ERROR_headerVersion_wrong;        /* Version Number, only supported value */\n    if (blockChecksumFlag != 0) return (size_t)-LZ5F_ERROR_blockChecksum_unsupported; /* Not supported for the time being */\n    if (((FLG>>0)&_2BITS) != 0) return (size_t)-LZ5F_ERROR_reservedFlag_set; /* Reserved bits */\n    if (((BD>>7)&_1BIT) != 0) return (size_t)-LZ5F_ERROR_reservedFlag_set;   /* Reserved bit */\n    if (blockSizeID < 1) return (size_t)-LZ5F_ERROR_maxBlockSize_invalid;    /* 1-7 only supported values for the time being */\n    if (((BD>>0)&_4BITS) != 0) return (size_t)-LZ5F_ERROR_reservedFlag_set;  /* Reserved bits */\n\n    /* check */\n    HC = LZ5F_headerChecksum(srcPtr+4, frameHeaderSize-5);\n    if (HC != srcPtr[frameHeaderSize-1]) return (size_t)-LZ5F_ERROR_headerChecksum_invalid;   /* Bad header checksum error */\n\n    /* save */\n    dctxPtr->frameInfo.blockMode = (LZ5F_blockMode_t)blockMode;\n    dctxPtr->frameInfo.contentChecksumFlag = (LZ5F_contentChecksum_t)contentChecksumFlag;\n    dctxPtr->frameInfo.blockSizeID = (LZ5F_blockSizeID_t)blockSizeID;\n    dctxPtr->maxBlockSize = LZ5F_getBlockSize(blockSizeID);\n    if (contentSizeFlag)\n        dctxPtr->frameRemainingSize = dctxPtr->frameInfo.contentSize = LZ5F_readLE64(srcPtr+6);\n\n    /* init */\n    if (contentChecksumFlag) XXH32_reset(&(dctxPtr->xxh), 0);\n\n    /* alloc */\n    bufferNeeded = dctxPtr->maxBlockSize + ((dctxPtr->frameInfo.blockMode==LZ5F_blockLinked) * 2 * LZ5F_DICT_SIZE);\n    if (bufferNeeded > dctxPtr->maxBufferSize)   /* tmp buffers too small */\n    {\n        FREEMEM(dctxPtr->tmpIn);\n        FREEMEM(dctxPtr->tmpOutBuffer);\n        dctxPtr->maxBufferSize = bufferNeeded;\n        dctxPtr->tmpIn = (BYTE*)ALLOCATOR(dctxPtr->maxBlockSize);\n        if (dctxPtr->tmpIn == NULL) return (size_t)-LZ5F_ERROR_GENERIC;\n        dctxPtr->tmpOutBuffer= (BYTE*)ALLOCATOR(dctxPtr->maxBufferSize);\n        if (dctxPtr->tmpOutBuffer== NULL) return (size_t)-LZ5F_ERROR_GENERIC;\n    }\n    dctxPtr->tmpInSize = 0;\n    dctxPtr->tmpInTarget = 0;\n    dctxPtr->dict = dctxPtr->tmpOutBuffer;\n    dctxPtr->dictSize = 0;\n    dctxPtr->tmpOut = dctxPtr->tmpOutBuffer;\n    dctxPtr->tmpOutStart = 0;\n    dctxPtr->tmpOutSize = 0;\n\n    dctxPtr->dStage = dstage_getCBlockSize;\n\n    return frameHeaderSize;\n}\n\n\n/* LZ5F_getFrameInfo()\n* This function decodes frame header information, such as blockSize.\n* It is optional : you could start by calling directly LZ5F_decompress() instead.\n* The objective is to extract header information without starting decompression, typically for allocation purposes.\n* LZ5F_getFrameInfo() can also be used *after* starting decompression, on a valid LZ5F_decompressionContext_t.\n* The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).\n* You are expected to resume decompression from where it stopped (srcBuffer + *srcSizePtr)\n* The function result is an hint of the better srcSize to use for next call to LZ5F_decompress,\n* or an error code which can be tested using LZ5F_isError().\n*/\nLZ5F_errorCode_t LZ5F_getFrameInfo(LZ5F_decompressionContext_t dCtx, LZ5F_frameInfo_t* frameInfoPtr,\n                                   const void* srcBuffer, size_t* srcSizePtr)\n{\n    LZ5F_dctx_t* dctxPtr = (LZ5F_dctx_t*)dCtx;\n\n    if (dctxPtr->dStage > dstage_storeHeader)   /* note : requires dstage_* header related to be at beginning of enum */\n    {\n        size_t o=0, i=0;\n        /* frameInfo already decoded */\n        *srcSizePtr = 0;\n        *frameInfoPtr = dctxPtr->frameInfo;\n        return LZ5F_decompress(dCtx, NULL, &o, NULL, &i, NULL);\n    }\n    else\n    {\n        size_t o=0;\n        size_t nextSrcSize = LZ5F_decompress(dCtx, NULL, &o, srcBuffer, srcSizePtr, NULL);\n        if (dctxPtr->dStage <= dstage_storeHeader)   /* note : requires dstage_* header related to be at beginning of enum */\n            return (size_t)-LZ5F_ERROR_frameHeader_incomplete;\n        *frameInfoPtr = dctxPtr->frameInfo;\n        return nextSrcSize;\n    }\n}\n\n\n/* trivial redirector, for common prototype */\nstatic int LZ5F_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize)\n{\n    (void)dictStart; (void)dictSize;\n    return LZ5_decompress_safe (source, dest, compressedSize, maxDecompressedSize);\n}\n\n\nstatic void LZ5F_updateDict(LZ5F_dctx_t* dctxPtr, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)\n{\n    if (dctxPtr->dictSize==0)\n        dctxPtr->dict = (const BYTE*)dstPtr;   /* priority to dictionary continuity */\n\n    if (dctxPtr->dict + dctxPtr->dictSize == dstPtr)   /* dictionary continuity */\n    {\n        dctxPtr->dictSize += dstSize;\n        return;\n    }\n\n    if (dstPtr - dstPtr0 + dstSize >= 64 KB)   /* dstBuffer large enough to become dictionary */\n    {\n        dctxPtr->dict = (const BYTE*)dstPtr0;\n        dctxPtr->dictSize = dstPtr - dstPtr0 + dstSize;\n        return;\n    }\n\n    if ((withinTmp) && (dctxPtr->dict == dctxPtr->tmpOutBuffer))\n    {\n        /* assumption : dctxPtr->dict + dctxPtr->dictSize == dctxPtr->tmpOut + dctxPtr->tmpOutStart */\n        dctxPtr->dictSize += dstSize;\n        return;\n    }\n\n    if (withinTmp) /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */\n    {\n        size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;\n        size_t copySize = 64 KB - dctxPtr->tmpOutSize;\n        const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;\n        if (dctxPtr->tmpOutSize > 64 KB) copySize = 0;\n        if (copySize > preserveSize) copySize = preserveSize;\n\n        memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);\n\n        dctxPtr->dict = dctxPtr->tmpOutBuffer;\n        dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart + dstSize;\n        return;\n    }\n\n    if (dctxPtr->dict == dctxPtr->tmpOutBuffer)     /* copy dst into tmp to complete dict */\n    {\n        if (dctxPtr->dictSize + dstSize > dctxPtr->maxBufferSize)   /* tmp buffer not large enough */\n        {\n            size_t preserveSize = 64 KB - dstSize;   /* note : dstSize < 64 KB */\n            memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);\n            dctxPtr->dictSize = preserveSize;\n        }\n        memcpy(dctxPtr->tmpOutBuffer + dctxPtr->dictSize, dstPtr, dstSize);\n        dctxPtr->dictSize += dstSize;\n        return;\n    }\n\n    /* join dict & dest into tmp */\n    {\n        size_t preserveSize = 64 KB - dstSize;   /* note : dstSize < 64 KB */\n        if (preserveSize > dctxPtr->dictSize) preserveSize = dctxPtr->dictSize;\n        memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);\n        memcpy(dctxPtr->tmpOutBuffer + preserveSize, dstPtr, dstSize);\n        dctxPtr->dict = dctxPtr->tmpOutBuffer;\n        dctxPtr->dictSize = preserveSize + dstSize;\n    }\n}\n\n\n\n/* LZ5F_decompress()\n* Call this function repetitively to regenerate data compressed within srcBuffer.\n* The function will attempt to decode *srcSizePtr from srcBuffer, into dstBuffer of maximum size *dstSizePtr.\n*\n* The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).\n*\n* The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).\n* If the number of bytes read is < number of bytes provided, then the decompression operation is not complete.\n* You will have to call it again, continuing from where it stopped.\n*\n* The function result is an hint of the better srcSize to use for next call to LZ5F_decompress.\n* Basically, it's the size of the current (or remaining) compressed block + header of next block.\n* Respecting the hint provides some boost to performance, since it allows less buffer shuffling.\n* Note that this is just a hint, you can always provide any srcSize you want.\n* When a frame is fully decoded, the function result will be 0.\n* If decompression failed, function result is an error code which can be tested using LZ5F_isError().\n*/\nsize_t LZ5F_decompress(LZ5F_decompressionContext_t decompressionContext,\n                       void* dstBuffer, size_t* dstSizePtr,\n                       const void* srcBuffer, size_t* srcSizePtr,\n                       const LZ5F_decompressOptions_t* decompressOptionsPtr)\n{\n    LZ5F_dctx_t* dctxPtr = (LZ5F_dctx_t*)decompressionContext;\n    LZ5F_decompressOptions_t optionsNull;\n    const BYTE* const srcStart = (const BYTE*)srcBuffer;\n    const BYTE* const srcEnd = srcStart + *srcSizePtr;\n    const BYTE* srcPtr = srcStart;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* const dstEnd = dstStart + *dstSizePtr;\n    BYTE* dstPtr = dstStart;\n    const BYTE* selectedIn = NULL;\n    unsigned doAnotherStage = 1;\n    size_t nextSrcSizeHint = 1;\n\n\n    memset(&optionsNull, 0, sizeof(optionsNull));\n    if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;\n    *srcSizePtr = 0;\n    *dstSizePtr = 0;\n\n    /* expect to continue decoding src buffer where it left previously */\n    if (dctxPtr->srcExpect != NULL)\n    {\n        if (srcStart != dctxPtr->srcExpect) return (size_t)-LZ5F_ERROR_srcPtr_wrong;\n    }\n\n    /* programmed as a state machine */\n\n    while (doAnotherStage)\n    {\n\n        switch(dctxPtr->dStage)\n        {\n\n        case dstage_getHeader:\n            {\n                if ((size_t)(srcEnd-srcPtr) >= maxFHSize)   /* enough to decode - shortcut */\n                {\n                    LZ5F_errorCode_t errorCode = LZ5F_decodeHeader(dctxPtr, srcPtr, srcEnd-srcPtr);\n                    if (LZ5F_isError(errorCode)) return errorCode;\n                    srcPtr += errorCode;\n                    break;\n                }\n                dctxPtr->tmpInSize = 0;\n                dctxPtr->tmpInTarget = minFHSize;   /* minimum to attempt decode */\n                dctxPtr->dStage = dstage_storeHeader;\n            }\n\n        case dstage_storeHeader:\n            {\n                size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy =  srcEnd - srcPtr;\n                memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                dctxPtr->tmpInSize += sizeToCopy;\n                srcPtr += sizeToCopy;\n                if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget)\n                {\n                    nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize;   /* rest of header + nextBlockHeader */\n                    doAnotherStage = 0;   /* not enough src data, ask for some more */\n                    break;\n                }\n                {\n                    LZ5F_errorCode_t errorCode = LZ5F_decodeHeader(dctxPtr, dctxPtr->header, dctxPtr->tmpInTarget);\n                    if (LZ5F_isError(errorCode)) return errorCode;\n                }\n                break;\n            }\n\n        case dstage_getCBlockSize:\n            {\n                if ((size_t)(srcEnd - srcPtr) >= BHSize)\n                {\n                    selectedIn = srcPtr;\n                    srcPtr += BHSize;\n                }\n                else\n                {\n                /* not enough input to read cBlockSize field */\n                    dctxPtr->tmpInSize = 0;\n                    dctxPtr->dStage = dstage_storeCBlockSize;\n                }\n            }\n\n            if (dctxPtr->dStage == dstage_storeCBlockSize)\n        case dstage_storeCBlockSize:\n            {\n                size_t sizeToCopy = BHSize - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;\n                memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctxPtr->tmpInSize += sizeToCopy;\n                if (dctxPtr->tmpInSize < BHSize) /* not enough input to get full cBlockSize; wait for more */\n                {\n                    nextSrcSizeHint = BHSize - dctxPtr->tmpInSize;\n                    doAnotherStage  = 0;\n                    break;\n                }\n                selectedIn = dctxPtr->tmpIn;\n            }\n\n        /* case dstage_decodeCBlockSize: */   /* no more direct access, to prevent scan-build warning */\n            {\n                size_t nextCBlockSize = LZ5F_readLE32(selectedIn) & 0x7FFFFFFFU;\n                if (nextCBlockSize==0)   /* frameEnd signal, no more CBlock */\n                {\n                    dctxPtr->dStage = dstage_getSuffix;\n                    break;\n                }\n                if (nextCBlockSize > dctxPtr->maxBlockSize) return (size_t)-LZ5F_ERROR_GENERIC; /* invalid cBlockSize */\n                dctxPtr->tmpInTarget = nextCBlockSize;\n                if (LZ5F_readLE32(selectedIn) & LZ5F_BLOCKUNCOMPRESSED_FLAG)\n                {\n                    dctxPtr->dStage = dstage_copyDirect;\n                    break;\n                }\n                dctxPtr->dStage = dstage_getCBlock;\n                if (dstPtr==dstEnd)\n                {\n                    nextSrcSizeHint = nextCBlockSize + BHSize;\n                    doAnotherStage = 0;\n                }\n                break;\n            }\n\n        case dstage_copyDirect:   /* uncompressed block */\n            {\n                size_t sizeToCopy = dctxPtr->tmpInTarget;\n                if ((size_t)(srcEnd-srcPtr) < sizeToCopy) sizeToCopy = srcEnd - srcPtr;  /* not enough input to read full block */\n                if ((size_t)(dstEnd-dstPtr) < sizeToCopy) sizeToCopy = dstEnd - dstPtr;\n                memcpy(dstPtr, srcPtr, sizeToCopy);\n                if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), srcPtr, sizeToCopy);\n                if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= sizeToCopy;\n\n                /* dictionary management */\n                if (dctxPtr->frameInfo.blockMode==LZ5F_blockLinked)\n                    LZ5F_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 0);\n\n                srcPtr += sizeToCopy;\n                dstPtr += sizeToCopy;\n                if (sizeToCopy == dctxPtr->tmpInTarget)   /* all copied */\n                {\n                    dctxPtr->dStage = dstage_getCBlockSize;\n                    break;\n                }\n                dctxPtr->tmpInTarget -= sizeToCopy;   /* still need to copy more */\n                nextSrcSizeHint = dctxPtr->tmpInTarget + BHSize;\n                doAnotherStage = 0;\n                break;\n            }\n\n        case dstage_getCBlock:   /* entry from dstage_decodeCBlockSize */\n            {\n                if ((size_t)(srcEnd-srcPtr) < dctxPtr->tmpInTarget)\n                {\n                    dctxPtr->tmpInSize = 0;\n                    dctxPtr->dStage = dstage_storeCBlock;\n                    break;\n                }\n                selectedIn = srcPtr;\n                srcPtr += dctxPtr->tmpInTarget;\n                dctxPtr->dStage = dstage_decodeCBlock;\n                break;\n            }\n\n        case dstage_storeCBlock:\n            {\n                size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd-srcPtr)) sizeToCopy = srcEnd-srcPtr;\n                memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                dctxPtr->tmpInSize += sizeToCopy;\n                srcPtr += sizeToCopy;\n                if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget)  /* need more input */\n                {\n                    nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize;\n                    doAnotherStage=0;\n                    break;\n                }\n                selectedIn = dctxPtr->tmpIn;\n                dctxPtr->dStage = dstage_decodeCBlock;\n                break;\n            }\n\n        case dstage_decodeCBlock:\n            {\n                if ((size_t)(dstEnd-dstPtr) < dctxPtr->maxBlockSize)   /* not enough place into dst : decode into tmpOut */\n                    dctxPtr->dStage = dstage_decodeCBlock_intoTmp;\n                else\n                    dctxPtr->dStage = dstage_decodeCBlock_intoDst;\n                break;\n            }\n\n        case dstage_decodeCBlock_intoDst:\n            {\n                int (*decoder)(const char*, char*, int, int, const char*, int);\n                int decodedSize;\n\n                if (dctxPtr->frameInfo.blockMode == LZ5F_blockLinked)\n                    decoder = LZ5_decompress_safe_usingDict;\n                else\n                    decoder = LZ5F_decompress_safe;\n\n                decodedSize = decoder((const char*)selectedIn, (char*)dstPtr, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);\n                if (decodedSize < 0) return (size_t)-LZ5F_ERROR_GENERIC;    /* decompression failed */\n                if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dstPtr, decodedSize);\n                if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;\n\n                /* dictionary management */\n                if (dctxPtr->frameInfo.blockMode==LZ5F_blockLinked)\n                    LZ5F_updateDict(dctxPtr, dstPtr, decodedSize, dstStart, 0);\n\n                dstPtr += decodedSize;\n                dctxPtr->dStage = dstage_getCBlockSize;\n                break;\n            }\n\n        case dstage_decodeCBlock_intoTmp:\n            {\n                /* not enough place into dst : decode into tmpOut */\n                int (*decoder)(const char*, char*, int, int, const char*, int);\n                int decodedSize;\n\n                if (dctxPtr->frameInfo.blockMode == LZ5F_blockLinked)\n                    decoder = LZ5_decompress_safe_usingDict;\n                else\n                    decoder = LZ5F_decompress_safe;\n\n                /* ensure enough place for tmpOut */\n                if (dctxPtr->frameInfo.blockMode == LZ5F_blockLinked)\n                {\n                    if (dctxPtr->dict == dctxPtr->tmpOutBuffer)\n                    {\n                        if (dctxPtr->dictSize > 128 KB)\n                        {\n                            memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - 64 KB, 64 KB);\n                            dctxPtr->dictSize = 64 KB;\n                        }\n                        dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + dctxPtr->dictSize;\n                    }\n                    else   /* dict not within tmp */\n                    {\n                        size_t reservedDictSpace = dctxPtr->dictSize;\n                        if (reservedDictSpace > 64 KB) reservedDictSpace = 64 KB;\n                        dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + reservedDictSpace;\n                    }\n                }\n\n                /* Decode */\n                decodedSize = decoder((const char*)selectedIn, (char*)dctxPtr->tmpOut, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);\n                if (decodedSize < 0) return (size_t)-LZ5F_ERROR_decompressionFailed;   /* decompression failed */\n                if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dctxPtr->tmpOut, decodedSize);\n                if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;\n                dctxPtr->tmpOutSize = decodedSize;\n                dctxPtr->tmpOutStart = 0;\n                dctxPtr->dStage = dstage_flushOut;\n                break;\n            }\n\n        case dstage_flushOut:  /* flush decoded data from tmpOut to dstBuffer */\n            {\n                size_t sizeToCopy = dctxPtr->tmpOutSize - dctxPtr->tmpOutStart;\n                if (sizeToCopy > (size_t)(dstEnd-dstPtr)) sizeToCopy = dstEnd-dstPtr;\n                memcpy(dstPtr, dctxPtr->tmpOut + dctxPtr->tmpOutStart, sizeToCopy);\n\n                /* dictionary management */\n                if (dctxPtr->frameInfo.blockMode==LZ5F_blockLinked)\n                    LZ5F_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 1);\n\n                dctxPtr->tmpOutStart += sizeToCopy;\n                dstPtr += sizeToCopy;\n\n                /* end of flush ? */\n                if (dctxPtr->tmpOutStart == dctxPtr->tmpOutSize)\n                {\n                    dctxPtr->dStage = dstage_getCBlockSize;\n                    break;\n                }\n                nextSrcSizeHint = BHSize;\n                doAnotherStage = 0;   /* still some data to flush */\n                break;\n            }\n\n        case dstage_getSuffix:\n            {\n                size_t suffixSize = dctxPtr->frameInfo.contentChecksumFlag * 4;\n                if (dctxPtr->frameRemainingSize) return (size_t)-LZ5F_ERROR_frameSize_wrong;   /* incorrect frame size decoded */\n                if (suffixSize == 0)   /* frame completed */\n                {\n                    nextSrcSizeHint = 0;\n                    dctxPtr->dStage = dstage_getHeader;\n                    doAnotherStage = 0;\n                    break;\n                }\n                if ((srcEnd - srcPtr) < 4)   /* not enough size for entire CRC */\n                {\n                    dctxPtr->tmpInSize = 0;\n                    dctxPtr->dStage = dstage_storeSuffix;\n                }\n                else\n                {\n                    selectedIn = srcPtr;\n                    srcPtr += 4;\n                }\n            }\n\n            if (dctxPtr->dStage == dstage_storeSuffix)\n        case dstage_storeSuffix:\n            {\n                size_t sizeToCopy = 4 - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;\n                memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctxPtr->tmpInSize += sizeToCopy;\n                if (dctxPtr->tmpInSize < 4)  /* not enough input to read complete suffix */\n                {\n                    nextSrcSizeHint = 4 - dctxPtr->tmpInSize;\n                    doAnotherStage=0;\n                    break;\n                }\n                selectedIn = dctxPtr->tmpIn;\n            }\n\n        /* case dstage_checkSuffix: */   /* no direct call, to avoid scan-build warning */\n            {\n                U32 readCRC = LZ5F_readLE32(selectedIn);\n                U32 resultCRC = XXH32_digest(&(dctxPtr->xxh));\n                if (readCRC != resultCRC) return (size_t)-LZ5F_ERROR_contentChecksum_invalid;\n                nextSrcSizeHint = 0;\n                dctxPtr->dStage = dstage_getHeader;\n                doAnotherStage = 0;\n                break;\n            }\n\n        case dstage_getSFrameSize:\n            {\n                if ((srcEnd - srcPtr) >= 4)\n                {\n                    selectedIn = srcPtr;\n                    srcPtr += 4;\n                }\n                else\n                {\n                /* not enough input to read cBlockSize field */\n                    dctxPtr->tmpInSize = 4;\n                    dctxPtr->tmpInTarget = 8;\n                    dctxPtr->dStage = dstage_storeSFrameSize;\n                }\n            }\n\n            if (dctxPtr->dStage == dstage_storeSFrameSize)\n        case dstage_storeSFrameSize:\n            {\n                size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;\n                memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctxPtr->tmpInSize += sizeToCopy;\n                if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) /* not enough input to get full sBlockSize; wait for more */\n                {\n                    nextSrcSizeHint = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                    doAnotherStage = 0;\n                    break;\n                }\n                selectedIn = dctxPtr->header + 4;\n            }\n\n        /* case dstage_decodeSFrameSize: */   /* no direct access */\n            {\n                size_t SFrameSize = LZ5F_readLE32(selectedIn);\n                dctxPtr->frameInfo.contentSize = SFrameSize;\n                dctxPtr->tmpInTarget = SFrameSize;\n                dctxPtr->dStage = dstage_skipSkippable;\n                break;\n            }\n\n        case dstage_skipSkippable:\n            {\n                size_t skipSize = dctxPtr->tmpInTarget;\n                if (skipSize > (size_t)(srcEnd-srcPtr)) skipSize = srcEnd-srcPtr;\n                srcPtr += skipSize;\n                dctxPtr->tmpInTarget -= skipSize;\n                doAnotherStage = 0;\n                nextSrcSizeHint = dctxPtr->tmpInTarget;\n                if (nextSrcSizeHint) break;\n                dctxPtr->dStage = dstage_getHeader;\n                break;\n            }\n        }\n    }\n\n    /* preserve dictionary within tmp if necessary */\n    if ( (dctxPtr->frameInfo.blockMode==LZ5F_blockLinked)\n        &&(dctxPtr->dict != dctxPtr->tmpOutBuffer)\n        &&(!decompressOptionsPtr->stableDst)\n        &&((unsigned)(dctxPtr->dStage-1) < (unsigned)(dstage_getSuffix-1))\n        )\n    {\n        if (dctxPtr->dStage == dstage_flushOut)\n        {\n            size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;\n            size_t copySize = 64 KB - dctxPtr->tmpOutSize;\n            const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;\n            if (dctxPtr->tmpOutSize > 64 KB) copySize = 0;\n            if (copySize > preserveSize) copySize = preserveSize;\n\n            memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);\n\n            dctxPtr->dict = dctxPtr->tmpOutBuffer;\n            dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart;\n        }\n        else\n        {\n            size_t newDictSize = dctxPtr->dictSize;\n            const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize;\n            if ((newDictSize) > 64 KB) newDictSize = 64 KB;\n\n            memcpy(dctxPtr->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);\n\n            dctxPtr->dict = dctxPtr->tmpOutBuffer;\n            dctxPtr->dictSize = newDictSize;\n            dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + newDictSize;\n        }\n    }\n\n    /* require function to be called again from position where it stopped */\n    if (srcPtr<srcEnd)\n        dctxPtr->srcExpect = srcPtr;\n    else\n        dctxPtr->srcExpect = NULL;\n\n    *srcSizePtr = (srcPtr - srcStart);\n    *dstSizePtr = (dstPtr - dstStart);\n    return nextSrcSizeHint;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5frame.h",
    "content": "﻿/*\n   LZ5 auto-framing library\n   Header File\n   Copyright (C) 2011-2015, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ5 source repository : https://github.com/inikep/lz5\n   - LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c\n*/\n\n/* LZ5F is a stand-alone API to create LZ5-compressed frames\n * conformant with specification v1.5.1.\n * All related operations, including memory management, are handled internally by the library.\n * You don't need lz5.h when using lz5frame.h.\n * */\n\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/**************************************\n*  Includes\n**************************************/\n#include <stddef.h>   /* size_t */\n\n\n/**************************************\n*  Error management\n**************************************/\ntypedef size_t LZ5F_errorCode_t;\n\nunsigned    LZ5F_isError(LZ5F_errorCode_t code);\nconst char* LZ5F_getErrorName(LZ5F_errorCode_t code);   /* return error code string; useful for debugging */\n\n\n/**************************************\n*  Frame compression types\n**************************************/\n//#define LZ5F_DISABLE_OBSOLETE_ENUMS\n#ifndef LZ5F_DISABLE_OBSOLETE_ENUMS\n#  define LZ5F_OBSOLETE_ENUM(x) ,x\n#else\n#  define LZ5F_OBSOLETE_ENUM(x)\n#endif\n\ntypedef enum {\n    LZ5F_default=0,\n    LZ5F_max64KB=1,\n    LZ5F_max256KB=2,\n    LZ5F_max1MB=3,\n    LZ5F_max4MB=4,\n    LZ5F_max16MB=5,\n    LZ5F_max64MB=6,\n    LZ5F_max256MB=7\n    LZ5F_OBSOLETE_ENUM(max64KB = LZ5F_max64KB)\n    LZ5F_OBSOLETE_ENUM(max256KB = LZ5F_max256KB)\n    LZ5F_OBSOLETE_ENUM(max1MB = LZ5F_max1MB)\n    LZ5F_OBSOLETE_ENUM(max4MB = LZ5F_max4MB)\n} LZ5F_blockSizeID_t;\n\ntypedef enum {\n    LZ5F_blockLinked=0,\n    LZ5F_blockIndependent\n    LZ5F_OBSOLETE_ENUM(blockLinked = LZ5F_blockLinked)\n    LZ5F_OBSOLETE_ENUM(blockIndependent = LZ5F_blockIndependent)\n} LZ5F_blockMode_t;\n\ntypedef enum {\n    LZ5F_noContentChecksum=0,\n    LZ5F_contentChecksumEnabled\n    LZ5F_OBSOLETE_ENUM(noContentChecksum = LZ5F_noContentChecksum)\n    LZ5F_OBSOLETE_ENUM(contentChecksumEnabled = LZ5F_contentChecksumEnabled)\n} LZ5F_contentChecksum_t;\n\ntypedef enum {\n    LZ5F_frame=0,\n    LZ5F_skippableFrame\n    LZ5F_OBSOLETE_ENUM(skippableFrame = LZ5F_skippableFrame)\n} LZ5F_frameType_t;\n\n#ifndef LZ5F_DISABLE_OBSOLETE_ENUMS\ntypedef LZ5F_blockSizeID_t blockSizeID_t;\ntypedef LZ5F_blockMode_t blockMode_t;\ntypedef LZ5F_frameType_t frameType_t;\ntypedef LZ5F_contentChecksum_t contentChecksum_t;\n#endif\n\ntypedef struct {\n  LZ5F_blockSizeID_t     blockSizeID;           /* max64KB, max256KB, max1MB, max4MB ; 0 == default */\n  LZ5F_blockMode_t       blockMode;             /* blockLinked, blockIndependent ; 0 == default */\n  LZ5F_contentChecksum_t contentChecksumFlag;   /* noContentChecksum, contentChecksumEnabled ; 0 == default  */\n  LZ5F_frameType_t       frameType;             /* LZ5F_frame, skippableFrame ; 0 == default */\n  unsigned long long     contentSize;           /* Size of uncompressed (original) content ; 0 == unknown */\n  unsigned               reserved[2];           /* must be zero for forward compatibility */\n} LZ5F_frameInfo_t;\n\ntypedef struct {\n  LZ5F_frameInfo_t frameInfo;\n  int      compressionLevel;       /* 0 == default (fast mode); values above 16 count as 16; values below 0 count as 0 */\n  unsigned autoFlush;              /* 1 == always flush (reduce need for tmp buffer) */\n  unsigned reserved[4];            /* must be zero for forward compatibility */\n} LZ5F_preferences_t;\n\n\n/***********************************\n*  Simple compression function\n***********************************/\nsize_t LZ5F_compressFrameBound(size_t srcSize, const LZ5F_preferences_t* preferencesPtr);\n\nsize_t LZ5F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ5F_preferences_t* preferencesPtr);\n/* LZ5F_compressFrame()\n * Compress an entire srcBuffer into a valid LZ5 frame, as defined by specification v1.5.1\n * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n * You can get the minimum value of dstMaxSize by using LZ5F_compressFrameBound()\n * If this condition is not respected, LZ5F_compressFrame() will fail (result is an errorCode)\n * The LZ5F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.\n * The result of the function is the number of bytes written into dstBuffer.\n * The function outputs an error code if it fails (can be tested using LZ5F_isError())\n */\n\n\n\n/**********************************\n*  Advanced compression functions\n**********************************/\ntypedef struct LZ5F_cctx_s* LZ5F_compressionContext_t;   /* must be aligned on 8-bytes */\n\ntypedef struct {\n  unsigned stableSrc;    /* 1 == src content will remain available on future calls to LZ5F_compress(); avoid saving src content within tmp buffer as future dictionary */\n  unsigned reserved[3];\n} LZ5F_compressOptions_t;\n\n/* Resource Management */\n\n#define LZ5F_VERSION 100\nLZ5F_errorCode_t LZ5F_createCompressionContext(LZ5F_compressionContext_t* cctxPtr, unsigned version);\nLZ5F_errorCode_t LZ5F_freeCompressionContext(LZ5F_compressionContext_t cctx);\n/* LZ5F_createCompressionContext() :\n * The first thing to do is to create a compressionContext object, which will be used in all compression operations.\n * This is achieved using LZ5F_createCompressionContext(), which takes as argument a version and an LZ5F_preferences_t structure.\n * The version provided MUST be LZ5F_VERSION. It is intended to track potential version differences between different binaries.\n * The function will provide a pointer to a fully allocated LZ5F_compressionContext_t object.\n * If the result LZ5F_errorCode_t is not zero, there was an error during context creation.\n * Object can release its memory using LZ5F_freeCompressionContext();\n */\n\n\n/* Compression */\n\nsize_t LZ5F_compressBegin(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ5F_preferences_t* prefsPtr);\n/* LZ5F_compressBegin() :\n * will write the frame header into dstBuffer.\n * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.\n * The LZ5F_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default.\n * The result of the function is the number of bytes written into dstBuffer for the header\n * or an error code (can be tested using LZ5F_isError())\n */\n\nsize_t LZ5F_compressBound(size_t srcSize, const LZ5F_preferences_t* prefsPtr);\n/* LZ5F_compressBound() :\n * Provides the minimum size of Dst buffer given srcSize to handle worst case situations.\n * Different preferences can produce different results.\n * prefsPtr is optional : you can provide NULL as argument, all preferences will then be set to cover worst case.\n * This function includes frame termination cost (4 bytes, or 8 if frame checksum is enabled)\n */\n\nsize_t LZ5F_compressUpdate(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ5F_compressOptions_t* cOptPtr);\n/* LZ5F_compressUpdate()\n * LZ5F_compressUpdate() can be called repetitively to compress as much data as necessary.\n * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n * You can get the minimum value of dstMaxSize by using LZ5F_compressBound().\n * If this condition is not respected, LZ5F_compress() will fail (result is an errorCode).\n * LZ5F_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.\n * The LZ5F_compressOptions_t structure is optional : you can provide NULL as argument.\n * The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.\n * The function outputs an error code if it fails (can be tested using LZ5F_isError())\n */\n\nsize_t LZ5F_flush(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ5F_compressOptions_t* cOptPtr);\n/* LZ5F_flush()\n * Should you need to generate compressed data immediately, without waiting for the current block to be filled,\n * you can call LZ5_flush(), which will immediately compress any remaining data buffered within cctx.\n * Note that dstMaxSize must be large enough to ensure the operation will be successful.\n * LZ5F_compressOptions_t structure is optional : you can provide NULL as argument.\n * The result of the function is the number of bytes written into dstBuffer\n * (it can be zero, this means there was no data left within cctx)\n * The function outputs an error code if it fails (can be tested using LZ5F_isError())\n */\n\nsize_t LZ5F_compressEnd(LZ5F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ5F_compressOptions_t* cOptPtr);\n/* LZ5F_compressEnd()\n * When you want to properly finish the compressed frame, just call LZ5F_compressEnd().\n * It will flush whatever data remained within compressionContext (like LZ5_flush())\n * but also properly finalize the frame, with an endMark and a checksum.\n * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark), or 8 if optional frame checksum is enabled)\n * The function outputs an error code if it fails (can be tested using LZ5F_isError())\n * The LZ5F_compressOptions_t structure is optional : you can provide NULL as argument.\n * A successful call to LZ5F_compressEnd() makes cctx available again for next compression task.\n */\n\n\n/***********************************\n*  Decompression functions\n***********************************/\n\ntypedef struct LZ5F_dctx_s* LZ5F_decompressionContext_t;   /* must be aligned on 8-bytes */\n\ntypedef struct {\n  unsigned stableDst;       /* guarantee that decompressed data will still be there on next function calls (avoid storage into tmp buffers) */\n  unsigned reserved[3];\n} LZ5F_decompressOptions_t;\n\n\n/* Resource management */\n\nLZ5F_errorCode_t LZ5F_createDecompressionContext(LZ5F_decompressionContext_t* dctxPtr, unsigned version);\nLZ5F_errorCode_t LZ5F_freeDecompressionContext(LZ5F_decompressionContext_t dctx);\n/* LZ5F_createDecompressionContext() :\n * The first thing to do is to create an LZ5F_decompressionContext_t object, which will be used in all decompression operations.\n * This is achieved using LZ5F_createDecompressionContext().\n * The version provided MUST be LZ5F_VERSION. It is intended to track potential breaking differences between different versions.\n * The function will provide a pointer to a fully allocated and initialized LZ5F_decompressionContext_t object.\n * The result is an errorCode, which can be tested using LZ5F_isError().\n * dctx memory can be released using LZ5F_freeDecompressionContext();\n * The result of LZ5F_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.\n * That is, it should be == 0 if decompression has been completed fully and correctly.\n */\n\n\n/* Decompression */\n\nsize_t LZ5F_getFrameInfo(LZ5F_decompressionContext_t dctx,\n                         LZ5F_frameInfo_t* frameInfoPtr,\n                         const void* srcBuffer, size_t* srcSizePtr);\n/* LZ5F_getFrameInfo()\n * This function decodes frame header information (such as max blockSize, frame checksum, etc.).\n * Its usage is optional. The objective is to extract frame header information, typically for allocation purposes.\n * A header size is variable and can be from 7 to 15 bytes. It's also possible to input more bytes than that. \n * The number of bytes read from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).\n * (note that LZ5F_getFrameInfo() can also be used anytime *after* starting decompression, in this case 0 input byte is enough)\n * Frame header info is *copied into* an already allocated LZ5F_frameInfo_t structure.\n * The function result is an hint about how many srcSize bytes LZ5F_decompress() expects for next call,\n *                        or an error code which can be tested using LZ5F_isError()\n *                        (typically, when there is not enough src bytes to fully decode the frame header)\n * Decompression is expected to resume from where it stopped (srcBuffer + *srcSizePtr)\n */\n\nsize_t LZ5F_decompress(LZ5F_decompressionContext_t dctx,\n                       void* dstBuffer, size_t* dstSizePtr,\n                       const void* srcBuffer, size_t* srcSizePtr,\n                       const LZ5F_decompressOptions_t* dOptPtr);\n/* LZ5F_decompress()\n * Call this function repetitively to regenerate data compressed within srcBuffer.\n * The function will attempt to decode *srcSizePtr bytes from srcBuffer, into dstBuffer of maximum size *dstSizePtr.\n *\n * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).\n *\n * The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).\n * If number of bytes read is < number of bytes provided, then decompression operation is not completed.\n * It typically happens when dstBuffer is not large enough to contain all decoded data.\n * LZ5F_decompress() must be called again, starting from where it stopped (srcBuffer + *srcSizePtr)\n * The function will check this condition, and refuse to continue if it is not respected.\n *\n * dstBuffer is supposed to be flushed between each call to the function, since its content will be overwritten.\n * dst arguments can be changed at will with each consecutive call to the function.\n *\n * The function result is an hint of how many srcSize bytes LZ5F_decompress() expects for next call.\n * Schematically, it's the size of the current (or remaining) compressed block + header of next block.\n * Respecting the hint provides some boost to performance, since it does skip intermediate buffers.\n * This is just a hint, you can always provide any srcSize you want.\n * When a frame is fully decoded, the function result will be 0 (no more data expected).\n * If decompression failed, function result is an error code, which can be tested using LZ5F_isError().\n *\n * After a frame is fully decoded, dctx can be used again to decompress another frame.\n */\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5frame_static.h",
    "content": "﻿/*\n   LZ5 auto-framing library\n   Header File for static linking only\n   Copyright (C) 2011-2015, Yann Collet.\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ5 source repository : https://github.com/inikep/lz5\n   - LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c\n*/\n\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* lz5frame_static.h should be used solely in the context of static linking.\n * It contains definitions which may still change overtime.\n * Never use it in the context of DLL linking.\n * */\n\n\n/**************************************\n*  Includes\n**************************************/\n#include \"lz5frame.h\"\n\n\n/**************************************\n * Error management\n * ************************************/\n#define LZ5F_LIST_ERRORS(ITEM) \\\n        ITEM(OK_NoError) ITEM(ERROR_GENERIC) \\\n        ITEM(ERROR_maxBlockSize_invalid) ITEM(ERROR_blockMode_invalid) ITEM(ERROR_contentChecksumFlag_invalid) \\\n        ITEM(ERROR_compressionLevel_invalid) \\\n        ITEM(ERROR_headerVersion_wrong) ITEM(ERROR_blockChecksum_unsupported) ITEM(ERROR_reservedFlag_set) \\\n        ITEM(ERROR_allocation_failed) \\\n        ITEM(ERROR_srcSize_tooLarge) ITEM(ERROR_dstMaxSize_tooSmall) \\\n        ITEM(ERROR_frameHeader_incomplete) ITEM(ERROR_frameType_unknown) ITEM(ERROR_frameSize_wrong) \\\n        ITEM(ERROR_srcPtr_wrong) \\\n        ITEM(ERROR_decompressionFailed) \\\n        ITEM(ERROR_headerChecksum_invalid) ITEM(ERROR_contentChecksum_invalid) \\\n        ITEM(ERROR_maxCode)\n\n//#define LZ5F_DISABLE_OLD_ENUMS\n#ifndef LZ5F_DISABLE_OLD_ENUMS\n#define LZ5F_GENERATE_ENUM(ENUM) LZ5F_##ENUM, ENUM = LZ5F_##ENUM,\n#else\n#define LZ5F_GENERATE_ENUM(ENUM) LZ5F_##ENUM,\n#endif\ntypedef enum { LZ5F_LIST_ERRORS(LZ5F_GENERATE_ENUM) } LZ5F_errorCodes;  /* enum is exposed, to handle specific errors; compare function result to -enum value */\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5hc.c",
    "content": "﻿/*\n    LZ5 HC - High Compression Mode of LZ5\n    Copyright (C) 2011-2015, Yann Collet.\n    Copyright (C) 2015, Przemyslaw Skibinski <inikep@gmail.com>\n\n    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n       - LZ5 source repository : https://github.com/inikep/lz5\n       - LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c\n*/\n\n\n\n\n/* *************************************\n*  Includes\n***************************************/\n#define LZ5HC_INCLUDES\n#include \"lz5common.h\"\n#include \"lz5.h\"\n#include \"lz5hc.h\"\n#include <stdio.h>\n#include <stdint.h>\n\n\n/**************************************\n*  HC Compression\n**************************************/\n\n\nint LZ5_alloc_mem_HC(LZ5HC_Data_Structure* ctx, int compressionLevel)\n{\n    ctx->compressionLevel = compressionLevel;  \n    if (compressionLevel > g_maxCompressionLevel) ctx->compressionLevel = g_maxCompressionLevel;\n    if (compressionLevel < 1) ctx->compressionLevel = LZ5HC_compressionLevel_default;\n\n    ctx->params = LZ5HC_defaultParameters[ctx->compressionLevel];\n\n    ctx->hashTable = (U32*) malloc(sizeof(U32)*(((size_t)1 << ctx->params.hashLog3)+((size_t)1 << ctx->params.hashLog)));\n    if (!ctx->hashTable)\n        return 0;\n\n    ctx->hashTable3 = ctx->hashTable + ((size_t)1 << ctx->params.hashLog);\n\n    ctx->chainTable = (U32*) malloc(sizeof(U32)*((size_t)1 << ctx->params.contentLog));\n    if (!ctx->chainTable)\n    {\n        FREEMEM(ctx->hashTable);\n        ctx->hashTable = NULL;\n        return 0;\n    }\n\n    return 1;\n}\n\nvoid LZ5_free_mem_HC(LZ5HC_Data_Structure* ctx)\n{\n    if (!ctx) return;\n    if (ctx->chainTable) FREEMEM(ctx->chainTable);\n    if (ctx->hashTable) FREEMEM(ctx->hashTable);    \n    ctx->base = NULL;\n}\n\nstatic void LZ5HC_init (LZ5HC_Data_Structure* ctx, const BYTE* start)\n{\n#ifdef LZ5_RESET_MEM\n    MEM_INIT((void*)ctx->hashTable, 0, sizeof(U32)*((1 << ctx->params.hashLog) + (1 << ctx->params.hashLog3)));\n    if (ctx->params.strategy >= LZ5HC_lowest_price)\n        MEM_INIT(ctx->chainTable, 0x01, sizeof(U32)*(1 << ctx->params.contentLog));\n#else\n#ifdef _DEBUG\n\tint i, len = sizeof(U32)*((1 << ctx->params.hashLog) + (1 << ctx->params.hashLog3));\n    unsigned char* bytes = (unsigned char*)ctx->hashTable;\n\tsrand(0);\n    for (i=0; i<len; i++)\n\t\tbytes[i] = (unsigned char)rand();\n#endif\n#endif\n\n    ctx->nextToUpdate = (U32)((size_t)1 << ctx->params.windowLog);\n    ctx->base = start - ((size_t)1 << ctx->params.windowLog);\n    ctx->end = start;\n    ctx->dictBase = start - ((size_t)1 << ctx->params.windowLog);\n    ctx->dictLimit = (U32)((size_t)1 << ctx->params.windowLog);\n    ctx->lowLimit = (U32)((size_t)1 << ctx->params.windowLog);\n    ctx->last_off = 1;\n}\n\n\n/* Update chains up to ip (excluded) */\nFORCE_INLINE void LZ5HC_BinTree_Insert(LZ5HC_Data_Structure* ctx, const BYTE* ip)\n{\n#if MINMATCH == 3\n    U32* HashTable3  = ctx->hashTable3;\n    const BYTE* const base = ctx->base;\n    const U32 target = (U32)(ip - base);\n    U32 idx = ctx->nextToUpdate;\n    \n    while(idx < target)\n    {\n        HashTable3[LZ5HC_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;\n        idx++;\n    }\n\n    ctx->nextToUpdate = target;\n#endif \n}\n\n\n/* Update chains up to \"end\" (excluded) */\nFORCE_INLINE void LZ5HC_BinTree_InsertFull(LZ5HC_Data_Structure* ctx, const BYTE* end, const BYTE* iHighLimit)\n{\n    U32* chainTable = ctx->chainTable;\n    U32* HashTable  = ctx->hashTable;\n#if MINMATCH == 3\n    U32* HashTable3  = ctx->hashTable3;\n#endif \n\n    U32 idx = ctx->nextToUpdate;\n    const BYTE* const base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);\n    const U32 current = (U32)(end - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance > idx) ? ctx->lowLimit : idx - (maxDistance - 1);\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* match, *ip;\n    int nbAttempts;\n    U32 *ptr0, *ptr1, *HashPos;\n    U32 matchIndex, delta0, delta1;\n\tsize_t mlt;\n\n    \n    while(idx < current)\n    {\n        ip = base + idx;\n        if (ip + MINMATCH > iHighLimit) return;\n\n        HashPos = &HashTable[LZ5HC_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n        matchIndex = *HashPos;\n#if MINMATCH == 3\n        HashTable3[LZ5HC_hash3Ptr(ip, ctx->params.hashLog3)] = idx;\n#endif \n\n        // check rest of matches\n        ptr0 = &chainTable[(idx*2+1) & contentMask];\n        ptr1 = &chainTable[(idx*2) & contentMask];\n        delta0 = delta1 = idx - matchIndex;\n        nbAttempts = ctx->params.searchNum;\n        *HashPos = idx;\n\n  //      while ((matchIndex >= dictLimit) && (matchIndex < idx) && (idx - matchIndex) < MAX_DISTANCE && nbAttempts)\n        while ((matchIndex < current) && (matchIndex < idx) && (matchIndex>=lowLimit) && (nbAttempts))\n        {\n            nbAttempts--;\n            mlt = 0;\n            if (matchIndex >= dictLimit)\n            {\n                match = base + matchIndex;\n                if (MEM_read24(match) == MEM_read24(ip))\n                {\n                    mlt = MINMATCH + MEM_count(ip+MINMATCH, match+MINMATCH, iHighLimit);\n\n                    if (mlt > LZ5_OPT_NUM) break;\n                }\n            }\n            else\n            {\n                match = dictBase + matchIndex;\n                if (MEM_read32(match) == MEM_read32(ip))\n                {\n                    const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                    if (vLimit > iHighLimit) vLimit = iHighLimit;\n                    mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                    if ((ip+mlt == vLimit) && (vLimit < iHighLimit))\n                        mlt += MEM_count(ip+mlt, base+dictLimit, iHighLimit);\n\n                    if (mlt > LZ5_OPT_NUM) break;\n                }\n            }\n            \n            if (*(ip+mlt) < *(match+mlt))\n            {\n                *ptr0 = delta0;\n                ptr0 = &chainTable[(matchIndex*2) & contentMask];\n                if (*ptr0 == (U32)-1) break;\n                delta0 = *ptr0;\n                delta1 += delta0;\n                matchIndex -= delta0;\n            }\n            else\n            {\n                *ptr1 = delta1;\n                ptr1 = &chainTable[(matchIndex*2+1) & contentMask];\n                if (*ptr1 == (U32)-1) break;\n                delta1 = *ptr1;\n                delta0 += delta1;\n                matchIndex -= delta1;\n            }\n        }\n\n        *ptr0 = (U32)-1;\n        *ptr1 = (U32)-1;\n\n    //    LZ5_LOG_MATCH(\"%d: LZMAX_UPDATE_HASH_BINTREE hash=%d inp=%d,%d,%d,%d (%c%c%c%c)\\n\", (int)(inp-base), hash, inp[0], inp[1], inp[2], inp[3], inp[0], inp[1], inp[2], inp[3]);\n\n        idx++;\n    }\n\n    ctx->nextToUpdate = current;\n}\n\n\n/* Update chains up to ip (excluded) */\nFORCE_INLINE void LZ5HC_Insert (LZ5HC_Data_Structure* ctx, const BYTE* ip)\n{\n    U32* chainTable = ctx->chainTable;\n    U32* HashTable  = ctx->hashTable;\n#if MINMATCH == 3\n    U32* HashTable3  = ctx->hashTable3;\n#endif \n    const BYTE* const base = ctx->base;\n    const U32 target = (U32)(ip - base);\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    U32 idx = ctx->nextToUpdate;\n\n    while(idx < target)\n    {\n        size_t h = LZ5HC_hashPtr(base+idx, ctx->params.hashLog, ctx->params.searchLength);\n        chainTable[idx & contentMask] = (U32)(idx - HashTable[h]);\n//        if (chainTable[idx & contentMask] == 1) chainTable[idx & contentMask] = (U32)0x01010101;\n        HashTable[h] = idx;\n#if MINMATCH == 3\n        HashTable3[LZ5HC_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;\n#endif \n       idx++;\n    }\n\n    ctx->nextToUpdate = target;\n}\n\n    \nFORCE_INLINE int LZ5HC_FindBestMatch (LZ5HC_Data_Structure* ctx,   /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const U32 dictLimit = ctx->dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);     \n\tconst U32 current = (U32)(ip - base);\n\tconst U32 lowLimit = (ctx->lowLimit + maxDistance > current) ? ctx->lowLimit : current - (maxDistance - 1);\n\tconst U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    U32 matchIndex;\n    const BYTE* match;\n    int nbAttempts=ctx->params.searchNum;\n    size_t ml=0, mlt;\n\n    matchIndex = HashTable[LZ5HC_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n\n    match = ip - ctx->last_off;\n    if (MEM_read24(match) == MEM_read24(ip))\n    {\n        ml = MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n        *matchpos = match;\n        return (int)ml;\n    }\n\n#if MINMATCH == 3\n\t{\n\t\tU32 matchIndex3 = ctx->hashTable3[LZ5HC_hash3Ptr(ip, ctx->params.hashLog3)];\n\t\tif (matchIndex3 < current && matchIndex3 >= lowLimit)\n\t\t{\n\t\t\tsize_t offset = (size_t)current - matchIndex3;\n\t\t\tif (offset < LZ5_SHORT_OFFSET_DISTANCE)\n\t\t\t{\n\t\t\t\tmatch = ip - offset;\n\t\t\t\tif (match > base && MEM_read24(ip) == MEM_read24(match))\n\t\t\t\t{\n\t\t\t\t\tml = 3;//MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n\t\t\t\t\t*matchpos = match;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n    while ((matchIndex < current) && (matchIndex>=lowLimit) && (nbAttempts))\n    {\n        nbAttempts--;\n        if (matchIndex >= dictLimit)\n        {\n            match = base + matchIndex;\n            if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip)))\n            {\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n\t\t\t\tif (!ml || (mlt > ml && LZ5HC_better_price((ip - *matchpos), ml, (ip - match), mlt, ctx->last_off)))\n//                if (mlt > ml && (LZ5_NORMAL_MATCH_COST(mlt - MINMATCH, (ip - match == ctx->last_off) ? 0 : (ip - match)) < LZ5_NORMAL_MATCH_COST(ml - MINMATCH, (ip - *matchpos == ctx->last_off) ? 0 : (ip - *matchpos)) + (LZ5_NORMAL_LIT_COST(mlt - ml))))\n                { ml = mlt; *matchpos = match; }\n            }\n        }\n        else\n        {\n            match = dictBase + matchIndex;\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                if (vLimit > iLimit) vLimit = iLimit;\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+mlt == vLimit) && (vLimit < iLimit))\n                    mlt += MEM_count(ip+mlt, base+dictLimit, iLimit);\n                if (!ml || (mlt > ml && LZ5HC_better_price((ip - *matchpos), ml, (ip - match), mlt, ctx->last_off)))\n             //   if (mlt > ml && (LZ5_NORMAL_MATCH_COST(mlt - MINMATCH, (ip - match == ctx->last_off) ? 0 : (ip - match)) < LZ5_NORMAL_MATCH_COST(ml - MINMATCH, (ip - *matchpos == ctx->last_off) ? 0 : (ip - *matchpos)) + (LZ5_NORMAL_LIT_COST(mlt - ml))))\n                { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */\n            }\n        }\n        matchIndex -= chainTable[matchIndex & contentMask];\n    }\n\n    return (int)ml;\n}\n\n\nFORCE_INLINE int LZ5HC_FindMatchFast (LZ5HC_Data_Structure* ctx, U32 matchIndex, U32 matchIndex3, /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const U32 dictLimit = ctx->dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);     \n\tconst U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance > current) ? ctx->lowLimit : current - (maxDistance - 1);\n    const BYTE* match;\n    size_t ml=0, mlt;\n\n    match = ip - ctx->last_off;\n    if (MEM_read24(match) == MEM_read24(ip))\n    {\n        ml = MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n        *matchpos = match;\n        return (int)ml;\n    }\n\n#if MINMATCH == 3\n\tif (matchIndex3 < current && matchIndex3 >= lowLimit)\n\t{\n\t\tsize_t offset = (size_t)current - matchIndex3;\n\t\tif (offset < LZ5_SHORT_OFFSET_DISTANCE)\n\t\t{\n\t\t\tmatch = ip - offset;\n\t\t\tif (match > base && MEM_read24(ip) == MEM_read24(match))\n\t\t\t{\n\t\t\t\tml = 3;//MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n\t\t\t\t*matchpos = match;\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n    if ((matchIndex < current) && (matchIndex>=lowLimit))\n    {\n        if (matchIndex >= dictLimit)\n        {\n            match = base + matchIndex;\n            if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip)))\n            {\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                if (!ml || (mlt > ml && LZ5HC_better_price((ip - *matchpos), ml, (ip - match), mlt, ctx->last_off)))\n         //       if (ml==0 || ((mlt > ml) && LZ5_NORMAL_MATCH_COST(mlt - MINMATCH, (ip - match == ctx->last_off) ? 0 : (ip - match)) < LZ5_NORMAL_MATCH_COST(ml - MINMATCH, (ip - *matchpos == ctx->last_off) ? 0 : (ip - *matchpos)) + (LZ5_NORMAL_LIT_COST(mlt - ml))))\n                { ml = mlt; *matchpos = match; }\n            }\n        }\n        else\n        {\n            match = dictBase + matchIndex;\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                if (vLimit > iLimit) vLimit = iLimit;\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+mlt == vLimit) && (vLimit < iLimit))\n                    mlt += MEM_count(ip+mlt, base+dictLimit, iLimit);\n                if (!ml || (mlt > ml && LZ5HC_better_price((ip - *matchpos), ml, (ip - match), mlt, ctx->last_off)))\n//                if (ml==0 || ((mlt > ml) && LZ5_NORMAL_MATCH_COST(mlt - MINMATCH, (ip - match == ctx->last_off) ? 0 : (ip - match)) < LZ5_NORMAL_MATCH_COST(ml - MINMATCH, (ip - *matchpos == ctx->last_off) ? 0 : (ip - *matchpos)) + (LZ5_NORMAL_LIT_COST(mlt - ml))))\n                { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */\n            }\n        }\n    }\n    \n    return (int)ml;\n}\n\n\nFORCE_INLINE int LZ5HC_FindMatchFaster (LZ5HC_Data_Structure* ctx, U32 matchIndex,  /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const U32 dictLimit = ctx->dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);     \n\tconst U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance > current) ? ctx->lowLimit : current - (maxDistance - 1);\n    const BYTE* match;\n    size_t ml=0, mlt;\n\n    match = ip - ctx->last_off;\n    if (MEM_read24(match) == MEM_read24(ip))\n    {\n        ml = MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n        *matchpos = match;\n        return (int)ml;\n    }\n\n\tif (matchIndex < current && matchIndex >= lowLimit)\n    {\n        if (matchIndex >= dictLimit)\n        {\n            match = base + matchIndex;\n            if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip)))\n            {\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                if (mlt > ml) { ml = mlt; *matchpos = match; }\n            }\n        }\n        else\n        {\n            match = dictBase + matchIndex;\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                if (vLimit > iLimit) vLimit = iLimit;\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+mlt == vLimit) && (vLimit < iLimit))\n                    mlt += MEM_count(ip+mlt, base+dictLimit, iLimit);\n                if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */\n            }\n        }\n    }\n    \n    return (int)ml;\n}\n\n\nFORCE_INLINE int LZ5HC_FindMatchFastest (LZ5HC_Data_Structure* ctx, U32 matchIndex,  /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const U32 dictLimit = ctx->dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);     \n\tconst U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance > current) ? ctx->lowLimit : current - (maxDistance - 1);\n    const BYTE* match;\n    size_t ml=0, mlt;\n\n\tif (matchIndex < current && matchIndex >= lowLimit)\n    {\n        if (matchIndex >= dictLimit)\n        {\n            match = base + matchIndex;\n            if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip)))\n            {\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                if (mlt > ml) { ml = mlt; *matchpos = match; }\n            }\n        }\n        else\n        {\n            match = dictBase + matchIndex;\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                if (vLimit > iLimit) vLimit = iLimit;\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+mlt == vLimit) && (vLimit < iLimit))\n                    mlt += MEM_count(ip+mlt, base+dictLimit, iLimit);\n                if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */\n            }\n        }\n    }\n    \n    return (int)ml;\n}\n\n\nFORCE_INLINE size_t LZ5HC_GetWiderMatch (\n    LZ5HC_Data_Structure* ctx,\n    const BYTE* const ip,\n    const BYTE* const iLowLimit,\n    const BYTE* const iHighLimit,\n    size_t longest,\n    const BYTE** matchpos,\n    const BYTE** startpos)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);\n\tconst U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance > current) ? ctx->lowLimit : current - (maxDistance - 1);\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* match;\n    U32   matchIndex;\n    int nbAttempts = ctx->params.searchNum;\n\n\n    /* First Match */\n    matchIndex = HashTable[LZ5HC_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n\n    match = ip - ctx->last_off;\n    if (MEM_read24(match) == MEM_read24(ip))\n    {\n        size_t mlt = MEM_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;\n        \n        int back = 0;\n        while ((ip+back>iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n        mlt -= back;\n\n        if (mlt > longest)\n        {\n            *matchpos = match+back;\n            *startpos = ip+back;\n            longest = (int)mlt;\n        }\n    }\n\n#if MINMATCH == 3\n\t{\n        U32 matchIndex3 = ctx->hashTable3[LZ5HC_hash3Ptr(ip, ctx->params.hashLog3)];\n\t\tif (matchIndex3 < current && matchIndex3 >= lowLimit)\n\t\t{\n\t\t\tsize_t offset = (size_t)current - matchIndex3;\n\t\t\tif (offset < LZ5_SHORT_OFFSET_DISTANCE)\n\t\t\t{\n\t\t\t\tmatch = ip - offset;\n\t\t\t\tif (match > base && MEM_read24(ip) == MEM_read24(match))\n\t\t\t\t{\n\t\t\t\t\tsize_t mlt = MEM_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;\n\n\t\t\t\t\tint back = 0;\n\t\t\t\t\twhile ((ip + back > iLowLimit) && (match + back > lowPrefixPtr) && (ip[back - 1] == match[back - 1])) back--;\n\t\t\t\t\tmlt -= back;\n\n\t\t\t\t\tif (!longest || (mlt > longest && LZ5HC_better_price((ip + back - *matchpos), longest, (ip - match), mlt, ctx->last_off)))\n\t\t\t\t\t\t//          if (!longest || (mlt > longest && LZ5_NORMAL_MATCH_COST(mlt - MINMATCH, (ip - match == ctx->last_off) ? 0 : (ip - match)) < LZ5_NORMAL_MATCH_COST(longest - MINMATCH, (ip+back - *matchpos == ctx->last_off) ? 0 : (ip+back - *matchpos)) + LZ5_NORMAL_LIT_COST(mlt - longest)))\n\t\t\t\t\t{\n\t\t\t\t\t\t*matchpos = match + back;\n\t\t\t\t\t\t*startpos = ip + back;\n\t\t\t\t\t\tlongest = (int)mlt;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n#endif\n\n    while ((matchIndex < current) && (matchIndex>=lowLimit) && (nbAttempts))\n    {\n        nbAttempts--;\n        if (matchIndex >= dictLimit)\n        {\n            match = base + matchIndex;\n\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                size_t mlt = MINMATCH + MEM_count(ip+MINMATCH, match+MINMATCH, iHighLimit);\n                int back = 0;\n\n                while ((ip+back>iLowLimit)\n                       && (match+back > lowPrefixPtr)\n                       && (ip[back-1] == match[back-1]))\n                        back--;\n\n                mlt -= back;\n\n                if (!longest || (mlt > longest && LZ5HC_better_price((ip+back - *matchpos), longest, (ip - match), mlt, ctx->last_off)))\n                {\n                    longest = (int)mlt;\n                    *matchpos = match+back;\n                    *startpos = ip+back;\n                }\n            }\n        }\n        else\n        {\n            match = dictBase + matchIndex;\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                size_t mlt;\n                int back=0;\n                const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                if (vLimit > iHighLimit) vLimit = iHighLimit;\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+mlt == vLimit) && (vLimit < iHighLimit))\n                    mlt += MEM_count(ip+mlt, base+dictLimit, iHighLimit);\n                while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == match[back-1])) back--;\n                mlt -= back;\n                if (mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }\n            }\n        }\n        matchIndex -= chainTable[matchIndex & contentMask];\n    }\n\n\n    return longest;\n}\n\n\nFORCE_INLINE int LZ5HC_GetAllMatches (\n    LZ5HC_Data_Structure* ctx,\n    const BYTE* const ip,\n    const BYTE* const iLowLimit,\n    const BYTE* const iHighLimit,\n    size_t best_mlen,\n    LZ5HC_match_t* matches)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    U32* const HashTable3 = ctx->hashTable3;\n    const BYTE* const base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);\n    const U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance > current) ? ctx->lowLimit : current - (maxDistance - 1);\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* match;\n    U32   matchIndex;\n    int nbAttempts = ctx->params.searchNum;\n //   bool fullSearch = (ctx->params.fullSearch >= 2);\n    int mnum = 0;\n    U32* HashPos, *HashPos3;\n\n    if (ip + MINMATCH > iHighLimit) return 0;\n\n    /* First Match */\n    HashPos = &HashTable[LZ5HC_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n    matchIndex = *HashPos;\n#if MINMATCH == 3\n    HashPos3 = &HashTable3[LZ5HC_hash3Ptr(ip, ctx->params.hashLog3)];\n\n    if ((*HashPos3 < current) && (*HashPos3 >= lowLimit)) \n\t{\n\t\tsize_t offset = current - *HashPos3;\n\t\tif (offset < LZ5_SHORT_OFFSET_DISTANCE)\n\t\t{\n\t\t\tmatch = ip - offset;\n\t\t\tif (match > base && MEM_read24(ip) == MEM_read24(match))\n\t\t\t{\n\t\t\t\tsize_t mlt = MEM_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;\n\n\t\t\t\tint back = 0;\n\t\t\t\twhile ((ip + back > iLowLimit) && (match + back > lowPrefixPtr) && (ip[back - 1] == match[back - 1])) back--;\n\t\t\t\tmlt -= back;\n\n\t\t\t\tmatches[mnum].off = (int)offset;\n\t\t\t\tmatches[mnum].len = (int)mlt;\n\t\t\t\tmatches[mnum].back = -back;\n\t\t\t\tmnum++;\n\t\t\t}\n\t\t}\n\t}\n\n    *HashPos3 = current;\n#endif\n\n\n    chainTable[current & contentMask] = (U32)(current - matchIndex);\n    *HashPos =  current;\n    ctx->nextToUpdate++;\n\n\n    while ((matchIndex < current) && (matchIndex>=lowLimit) && (nbAttempts))\n    {\n        nbAttempts--;\n        if (matchIndex >= dictLimit)\n        {\n            match = base + matchIndex;\n\n            if ((/*fullSearch ||*/ ip[best_mlen] == match[best_mlen]) && (MEM_read24(match) == MEM_read24(ip)))\n            {\n                size_t mlt = MINMATCH + MEM_count(ip+MINMATCH, match+MINMATCH, iHighLimit);\n                int back = 0;\n\n                while ((ip+back>iLowLimit)\n                       && (match+back > lowPrefixPtr)\n                       && (ip[back-1] == match[back-1]))\n                        back--;\n\n                mlt -= back;\n\n                if (mlt > best_mlen)\n                {\n                    best_mlen = mlt;\n                    matches[mnum].off = (int)(ip - match);\n                    matches[mnum].len = (int)mlt;\n                    matches[mnum].back = -back;\n                    mnum++;\n                }\n\n                if (best_mlen > LZ5_OPT_NUM) break;\n            }\n        }\n        else\n        {\n            match = dictBase + matchIndex;\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                size_t mlt;\n                int back=0;\n                const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                if (vLimit > iHighLimit) vLimit = iHighLimit;\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+mlt == vLimit) && (vLimit < iHighLimit))\n                    mlt += MEM_count(ip+mlt, base+dictLimit, iHighLimit);\n                while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == match[back-1])) back--;\n                mlt -= back;\n                \n                if (mlt > best_mlen)\n                {\n                    best_mlen = mlt;\n                    matches[mnum].off = (int)(ip - match);\n                    matches[mnum].len = (int)mlt;\n                    matches[mnum].back = -back;\n                    mnum++;\n                }\n\n                if (best_mlen > LZ5_OPT_NUM) break;\n            }\n        }\n        matchIndex -= chainTable[matchIndex & contentMask];\n    }\n\n\n    return mnum;\n}\n\n\n\nFORCE_INLINE int LZ5HC_BinTree_GetAllMatches (\n    LZ5HC_Data_Structure* ctx,\n    const BYTE* const ip,\n    const BYTE* const iHighLimit,\n    size_t best_mlen,\n    LZ5HC_match_t* matches)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog);\n    const U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance > current) ? ctx->lowLimit : current - (maxDistance - 1);\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* match;\n    int nbAttempts = ctx->params.searchNum;\n    int mnum = 0;\n    U32 *ptr0, *ptr1;\n    U32 matchIndex, delta0, delta1;\n    size_t mlt = 0;\n    U32* HashPos, *HashPos3;\n    \n    if (ip + MINMATCH > iHighLimit) return 0;\n\n    /* First Match */\n    HashPos = &HashTable[LZ5HC_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n    matchIndex = *HashPos;\n\n    \n#if MINMATCH == 3\n    HashPos3 = &ctx->hashTable3[LZ5HC_hash3Ptr(ip, ctx->params.hashLog3)];\n\n    if ((*HashPos3 < current) && (*HashPos3 >= lowLimit)) \n\t{\n\t\tsize_t offset = current - *HashPos3;\n\t\tif (offset < LZ5_SHORT_OFFSET_DISTANCE)\n\t\t{\n\t\t\tmatch = ip - offset;\n\t\t\tif (match > base && MEM_read24(ip) == MEM_read24(match))\n\t\t\t{\n\t\t\t\tmlt = MEM_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;\n\n\t\t\t\tmatches[mnum].off = (int)offset;\n\t\t\t\tmatches[mnum].len = (int)mlt;\n\t\t\t\tmatches[mnum].back = 0;\n\t\t\t\tmnum++;\n\t\t\t}\n\t\t}\n\n\t\t*HashPos3 = current;\n\t}\n#endif\n    \n\n    *HashPos = current;\n    ctx->nextToUpdate++;\n\n    // check rest of matches\n    ptr0 = &chainTable[(current*2+1) & contentMask];\n    ptr1 = &chainTable[(current*2) & contentMask];\n    delta0 = delta1 = current - matchIndex;\n\n    while ((matchIndex < current) && (matchIndex>=lowLimit) && (nbAttempts))\n    {\n        nbAttempts--;\n        mlt = 0;\n        if (matchIndex >= dictLimit)\n        {\n            match = base + matchIndex;\n\n            if (MEM_read24(match) == MEM_read24(ip))\n            {\n                mlt = MINMATCH + MEM_count(ip+MINMATCH, match+MINMATCH, iHighLimit);\n\n                if (mlt > best_mlen)\n                {\n                    best_mlen = mlt;\n                    matches[mnum].off = (int)(ip - match);\n                    matches[mnum].len = (int)mlt;\n                    matches[mnum].back = 0;\n                    mnum++;\n                }\n\n                if (best_mlen > LZ5_OPT_NUM) break;\n            }\n        }\n        else\n        {\n            match = dictBase + matchIndex;\n            if (MEM_read32(match) == MEM_read32(ip))\n            {\n                const BYTE* vLimit = ip + (dictLimit - matchIndex);\n                if (vLimit > iHighLimit) vLimit = iHighLimit;\n                mlt = MEM_count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;\n                if ((ip+mlt == vLimit) && (vLimit < iHighLimit))\n                    mlt += MEM_count(ip+mlt, base+dictLimit, iHighLimit);\n                \n                if (mlt > best_mlen)\n                {\n                    best_mlen = mlt;\n                    matches[mnum].off = (int)(ip - match);\n                    matches[mnum].len = (int)mlt;\n                    matches[mnum].back = 0;\n                    mnum++;\n                }\n\n                if (best_mlen > LZ5_OPT_NUM) break;\n            }\n        }\n        \n        if (*(ip+mlt) < *(match+mlt))\n        {\n            *ptr0 = delta0;\n            ptr0 = &chainTable[(matchIndex*2) & contentMask];\n    //\t\tprintf(\"delta0=%d\\n\", delta0);\n            if (*ptr0 == (U32)-1) break;\n            delta0 = *ptr0;\n            delta1 += delta0;\n            matchIndex -= delta0;\n        }\n        else\n        {\n            *ptr1 = delta1;\n            ptr1 = &chainTable[(matchIndex*2+1) & contentMask];\n    //\t\tprintf(\"delta1=%d\\n\", delta1);\n            if (*ptr1 == (U32)-1) break;\n            delta1 = *ptr1;\n            delta0 += delta1;\n            matchIndex -= delta1;\n        }\n    }\n\n    *ptr0 = (U32)-1;\n    *ptr1 = (U32)-1;\n\n    return mnum;\n}\n\n\n\n\ntypedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;\n\n/*\nLZ5 uses 3 types of codewords from 2 to 4 bytes long:\n- 1_OO_LL_MMM OOOOOOOO - 10-bit offset, 3-bit match length, 2-bit literal length\n- 00_LLL_MMM OOOOOOOO OOOOOOOO - 16-bit offset, 3-bit match length, 3-bit literal length\n- 010_LL_MMM OOOOOOOO OOOOOOOO OOOOOOOO - 24-bit offset, 3-bit match length, 2-bit literal length \n- 011_LL_MMM - last offset, 3-bit match length, 2-bit literal length\n*/\n\nFORCE_INLINE int LZ5HC_encodeSequence (\n    LZ5HC_Data_Structure* ctx,\n    const BYTE** ip,\n    BYTE** op,\n    const BYTE** anchor,\n    int matchLength,\n    const BYTE* const match,\n    limitedOutput_directive limitedOutputBuffer,\n    BYTE* oend)\n{\n    int length;\n    BYTE* token;\n\n    /* Encode Literal length */\n    length = (int)(*ip - *anchor);\n    token = (*op)++;\n\n    if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1;   /* Check output limit */\n\n    if (*ip-match >= LZ5_SHORT_OFFSET_DISTANCE && *ip-match < LZ5_MID_OFFSET_DISTANCE && (U32)(*ip-match) != 0)\n    {\n        if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255;  *(*op)++ = (BYTE)len; }\n        else *token = (BYTE)(length<<ML_BITS);\n    }\n    else\n    {\n        if (length>=(int)RUN_MASK2) { int len; *token=(RUN_MASK2<<ML_BITS); len = length-RUN_MASK2; for(; len > 254 ; len-=255) *(*op)++ = 255;  *(*op)++ = (BYTE)len; }\n        else *token = (BYTE)(length<<ML_BITS);\n        \n    }\n\n    /* Copy Literals */\n    MEM_wildCopy(*op, *anchor, (*op) + length);\n    *op += length;\n\n    /* Encode Offset */\n    if ((U32)(*ip-match) == 0)\n    {\n        *token+=(3<<ML_RUN_BITS2);\n    }\n    else\n    {\n\t\tctx->last_off = (U32)(*ip-match);\n        if (ctx->last_off < LZ5_SHORT_OFFSET_DISTANCE)\n        {\n            *token+=(BYTE)((4+(ctx->last_off>>8))<<ML_RUN_BITS2);\n            **op=(BYTE)ctx->last_off; (*op)++;\n        }\n        else\n        if (*ip-match < LZ5_MID_OFFSET_DISTANCE)\n        {\n            MEM_writeLE16(*op, (U16)ctx->last_off); *op+=2;\n        }\n        else\n        {\n            *token+=(2<<ML_RUN_BITS2);\n            MEM_writeLE24(*op, (U32)ctx->last_off); *op+=3;\n        }\n    }\n\n    /* Encode MatchLength */\n    length = (int)(matchLength-MINMATCH);\n    if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1;   /* Check output limit */\n    if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; }\n    else *token += (BYTE)(length);\n\n    LZ5HC_DEBUG(\"%u: ENCODE literals=%u off=%u mlen=%u out=%u\\n\", (U32)(*ip - ctx->inputBuffer), (U32)(*ip - *anchor), (U32)(*ip-match), (U32)matchLength, 2+(U32)(*op - ctx->outputBuffer));\n\n    /* Prepare next loop */\n    *ip += matchLength;\n    *anchor = *ip;\n\n    return 0;\n}\n\n\n#define SET_PRICE(pos, mlen, offset, litlen, price)   \\\n    {                                                 \\\n        while (last_pos < pos)  { opt[last_pos+1].price = 1<<30; last_pos++; } \\\n        opt[pos].mlen = (int)mlen;                         \\\n        opt[pos].off = (int)offset;                        \\\n        opt[pos].litlen = (int)litlen;                     \\\n        opt[pos].price = (int)price;                       \\\n        LZ5_LOG_PARSER(\"%d: SET price[%d/%d]=%d litlen=%d len=%d off=%d\\n\", (int)(inr-source), pos, last_pos, opt[pos].price, opt[pos].litlen, opt[pos].mlen, opt[pos].off); \\\n    }\n\n\nstatic int LZ5HC_compress_optimal_price (\n    LZ5HC_Data_Structure* ctx,\n    const BYTE* source,\n    char* dest,\n    int inputSize,\n    int maxOutputSize,\n    limitedOutput_directive limit\n    )\n{\n\tLZ5HC_optimal_t opt[LZ5_OPT_NUM + 4];\n\tLZ5HC_match_t matches[LZ5_OPT_NUM + 1];\n\tconst BYTE *inr;\n\tsize_t res, cur, cur2, skip_num = 0;\n\tsize_t i, llen, litlen, mlen, best_mlen, price, offset, best_off, match_num, last_pos;\n\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + inputSize;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n    BYTE* op = (BYTE*) dest;\n    BYTE* const oend = op + maxOutputSize;\n    const size_t sufficient_len = ctx->params.sufficientLength;\n    const int faster_get_matches = (ctx->params.fullSearch == 0); \n \n\n    /* init */\n\tctx->inputBuffer = (const BYTE*)source;\n\tctx->outputBuffer = (const BYTE*)dest;\n\tctx->end += inputSize;\n    ip++;\n\n    /* Main Loop */\n    while (ip < mflimit)\n    {\n        memset(opt, 0, sizeof(LZ5HC_optimal_t));\n        last_pos = 0;\n        llen = ip - anchor;\n\n        // check rep\n        mlen = MEM_count(ip, ip - ctx->last_off, matchlimit);\n        if (mlen >= MINMATCH)\n        {\n            LZ5_LOG_PARSER(\"%d: start try REP rep=%d mlen=%d\\n\", (int)(ip-source), ctx->last_off, mlen);\n            if (mlen > sufficient_len || mlen >= LZ5_OPT_NUM)\n            {\n                best_mlen = mlen; best_off = 0; cur = 0; last_pos = 1;\n                goto encode;\n            }\n\n            do\n            {\n                litlen = 0;\n                price = LZ5HC_get_price(llen, 0, mlen - MINMATCH) - llen;\n                if (mlen > last_pos || price < (size_t)opt[mlen].price)\n                    SET_PRICE(mlen, mlen, 0, litlen, price);\n                mlen--;\n            }\n            while (mlen >= MINMATCH);\n        }\n\n \n       best_mlen = (last_pos) ? last_pos : MINMATCH;\n\n       if (faster_get_matches && last_pos)\n           match_num = 0;\n       else\n       {\n            if (ctx->params.strategy == LZ5HC_optimal_price)\n            {\n                LZ5HC_Insert(ctx, ip);\n                match_num = LZ5HC_GetAllMatches(ctx, ip, ip, matchlimit, best_mlen, matches);\n            }\n            else\n            {\n                if (ctx->params.fullSearch < 2)\n                    LZ5HC_BinTree_Insert(ctx, ip);\n                else\n                    LZ5HC_BinTree_InsertFull(ctx, ip, matchlimit);\n                match_num = LZ5HC_BinTree_GetAllMatches(ctx, ip, matchlimit, best_mlen, matches);\n            }\n       }\n\n       LZ5_LOG_PARSER(\"%d: match_num=%d last_pos=%d\\n\", (int)(ip-source), match_num, last_pos);\n       if (!last_pos && !match_num) { ip++; continue; }\n\n       if (match_num && (size_t)matches[match_num-1].len > sufficient_len)\n       {\n            best_mlen = matches[match_num-1].len;\n            best_off = matches[match_num-1].off;\n            cur = 0;\n            last_pos = 1;\n            goto encode;\n       }\n\n       // set prices using matches at position = 0\n       for (i = 0; i < match_num; i++)\n       {\n           mlen = (i>0) ? (size_t)matches[i-1].len+1 : best_mlen;\n           best_mlen = (matches[i].len < LZ5_OPT_NUM) ? matches[i].len : LZ5_OPT_NUM;\n           LZ5_LOG_PARSER(\"%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\\n\", (int)(ip-source), matches[i].len, matches[i].off, best_mlen, last_pos);\n           while (mlen <= best_mlen)\n           {\n                litlen = 0;\n                price = LZ5HC_get_price(llen + litlen, matches[i].off, mlen - MINMATCH) - llen;\n                if (mlen > last_pos || price < (size_t)opt[mlen].price)\n                    SET_PRICE(mlen, mlen, matches[i].off, litlen, price);\n                mlen++;\n           }\n        }\n\n        if (last_pos < MINMATCH) { ip++; continue; }\n\n        opt[0].rep = opt[1].rep = ctx->last_off;\n        opt[0].mlen = opt[1].mlen = 1;\n\n        // check further positions\n        for (skip_num = 0, cur = 1; cur <= last_pos; cur++)\n        { \n           inr = ip + cur;\n\n           if (opt[cur-1].mlen == 1)\n           {\n                litlen = opt[cur-1].litlen + 1;\n                \n                if (cur != litlen)\n                {\n                    price = opt[cur - litlen].price + LZ5_LIT_ONLY_COST(litlen);\n                    LZ5_LOG_PRICE(\"%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\\n\", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);\n                }\n                else\n                {\n                    price = LZ5_LIT_ONLY_COST(llen + litlen) - llen;\n                    LZ5_LOG_PRICE(\"%d: TRY2 price=%d cur=%d litlen=%d llen=%d\\n\", (int)(inr-source), price, cur, litlen, llen);\n                }\n           }\n           else\n           {\n                litlen = 1;\n                price = opt[cur - 1].price + LZ5_LIT_ONLY_COST(litlen);                  \n                LZ5_LOG_PRICE(\"%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\\n\", (int)(inr-source), price, cur, litlen, LZ5_LIT_ONLY_COST(litlen));\n           }\n           \n           mlen = 1;\n           best_mlen = 0;\n           LZ5_LOG_PARSER(\"%d: TRY price=%d opt[%d].price=%d\\n\", (int)(inr-source), price, cur, opt[cur].price);\n\n           if (cur > last_pos || price <= (size_t)opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))\n                SET_PRICE(cur, mlen, best_mlen, litlen, price);\n\n           if (cur == last_pos) break;\n\n           if (opt[cur].mlen > 1)\n           {\n                mlen = opt[cur].mlen;\n                offset = opt[cur].off;\n                if (offset < 1)\n                {\n                    opt[cur].rep = opt[cur-mlen].rep;\n                    LZ5_LOG_PARSER(\"%d: COPYREP1 cur=%d mlen=%d rep=%d\\n\", (int)(inr-source), cur, mlen, opt[cur-mlen].rep);\n                }\n                else\n                {\n                    opt[cur].rep = (int)offset;\n                    LZ5_LOG_PARSER(\"%d: COPYREP2 cur=%d offset=%d rep=%d\\n\", (int)(inr-source), cur, offset, opt[cur].rep);\n                }\n           }\n           else\n           {\n                opt[cur].rep = opt[cur-1].rep; // copy rep\n           }\n\n\n            LZ5_LOG_PARSER(\"%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(inr-source), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep); \n\n           // check rep\n           // best_mlen = 0;\n           mlen = MEM_count(inr, inr - opt[cur].rep, matchlimit);\n           if (mlen >= MINMATCH && mlen > best_mlen)\n           {\n              LZ5_LOG_PARSER(\"%d: try REP rep=%d mlen=%d\\n\", (int)(inr-source), opt[cur].rep, mlen);   \n              LZ5_LOG_PARSER(\"%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\\n\", (int)(inr-source), mlen, 0, opt[cur].rep, cur, opt[cur].off);\n\n              if (mlen > sufficient_len || cur + mlen >= LZ5_OPT_NUM)\n              {\n                best_mlen = mlen;\n                best_off = 0;\n                LZ5_LOG_PARSER(\"%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\\n\", (int)(inr-source), sufficient_len, best_mlen, best_off, last_pos);\n                last_pos = cur + 1;\n                goto encode;\n               }\n\n               if (opt[cur].mlen == 1)\n               {\n                    litlen = opt[cur].litlen;\n\n                    if (cur != litlen)\n                    {\n                        price = opt[cur - litlen].price + LZ5HC_get_price(litlen, 0, mlen - MINMATCH);\n                        LZ5_LOG_PRICE(\"%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\\n\", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);\n                    }\n                    else\n                    {\n                        price = LZ5HC_get_price(llen + litlen, 0, mlen - MINMATCH) - llen;\n                        LZ5_LOG_PRICE(\"%d: TRY2 price=%d cur=%d litlen=%d llen=%d\\n\", (int)(inr-source), price, cur, litlen, llen);\n                    }\n                }\n                else\n                {\n                    litlen = 0;\n                    price = opt[cur].price + LZ5HC_get_price(litlen, 0, mlen - MINMATCH);\n                    LZ5_LOG_PRICE(\"%d: TRY3 price=%d cur=%d litlen=%d getprice=%d\\n\", (int)(inr-source), price, cur, litlen, LZ5HC_get_price(litlen, 0, mlen - MINMATCH));\n                }\n\n                best_mlen = mlen;\n                if (faster_get_matches)\n                    skip_num = best_mlen;\n\n                LZ5_LOG_PARSER(\"%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\\n\", (int)(inr-source), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price);\n\n                do\n                {\n                    if (cur + mlen > last_pos || price <= (size_t)opt[cur + mlen].price) // || ((price == opt[cur + mlen].price) && (opt[cur].mlen == 1) && (cur != litlen))) // at equal price prefer REP instead of MATCH\n                        SET_PRICE(cur + mlen, mlen, 0, litlen, price);\n                    mlen--;\n                }\n                while (mlen >= MINMATCH);\n            }\n\n            if (faster_get_matches && skip_num > 0)\n            {\n                skip_num--; \n                continue;\n            }\n\n\n            best_mlen = (best_mlen > MINMATCH) ? best_mlen : MINMATCH;      \n\n            if (ctx->params.strategy == LZ5HC_optimal_price)\n            {\n                LZ5HC_Insert(ctx, inr);\n                match_num = LZ5HC_GetAllMatches(ctx, inr, ip, matchlimit, best_mlen, matches);\n                LZ5_LOG_PARSER(\"%d: LZ5HC_GetAllMatches match_num=%d\\n\", (int)(inr-source), match_num);\n            }\n            else\n            {\n                if (ctx->params.fullSearch < 2)\n                    LZ5HC_BinTree_Insert(ctx, inr);\n                else\n                    LZ5HC_BinTree_InsertFull(ctx, inr, matchlimit);\n                match_num = LZ5HC_BinTree_GetAllMatches(ctx, inr, matchlimit, best_mlen, matches);\n                LZ5_LOG_PARSER(\"%d: LZ5HC_BinTree_GetAllMatches match_num=%d\\n\", (int)(inr-source), match_num);\n            }\n\n\n            if (match_num > 0 && (size_t)matches[match_num-1].len > sufficient_len)\n            {\n                cur -= matches[match_num-1].back;\n                best_mlen = matches[match_num-1].len;\n                best_off = matches[match_num-1].off;\n                last_pos = cur + 1;\n                goto encode;\n            }\n\n            // set prices using matches at position = cur\n            for (i = 0; i < match_num; i++)\n            {\n                mlen = (i>0) ? (size_t)matches[i-1].len+1 : best_mlen;\n                cur2 = cur - matches[i].back;\n                best_mlen = (cur2 + matches[i].len < LZ5_OPT_NUM) ? (size_t)matches[i].len : LZ5_OPT_NUM - cur2;\n                LZ5_LOG_PARSER(\"%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\\n\", (int)(inr-source), cur, cur2, matches[i].len, matches[i].off, best_mlen, last_pos);\n\n                if (mlen < (size_t)matches[i].back + 1)\n                    mlen = matches[i].back + 1; \n\n                while (mlen <= best_mlen)\n                {\n                    if (opt[cur2].mlen == 1)\n                    {\n                        litlen = opt[cur2].litlen;\n\n                        if (cur2 != litlen)\n                            price = opt[cur2 - litlen].price + LZ5HC_get_price(litlen, matches[i].off, mlen - MINMATCH);\n                        else\n                            price = LZ5HC_get_price(llen + litlen, matches[i].off, mlen - MINMATCH) - llen;\n                    }\n                    else\n                    {\n                        litlen = 0;\n                        price = opt[cur2].price + LZ5HC_get_price(litlen, matches[i].off, mlen - MINMATCH);\n                    }\n\n                    LZ5_LOG_PARSER(\"%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\\n\", (int)(inr-source), matches[i].back, mlen, best_mlen, matches[i].off, price, litlen, cur - litlen, opt[cur - litlen].price);\n    //                if (cur2 + mlen > last_pos || ((matches[i].off != opt[cur2 + mlen].off) && (price < opt[cur2 + mlen].price)))\n                    if (cur2 + mlen > last_pos || price < (size_t)opt[cur2 + mlen].price)\n                    {\n                        SET_PRICE(cur2 + mlen, mlen, matches[i].off, litlen, price);\n                    }\n\n                    mlen++;\n                }\n            }\n        } //  for (skip_num = 0, cur = 1; cur <= last_pos; cur++)\n\n\n        best_mlen = opt[last_pos].mlen;\n        best_off = opt[last_pos].off;\n        cur = last_pos - best_mlen;\n\nencode: // cur, last_pos, best_mlen, best_off have to be set\n        for (i = 1; i <= last_pos; i++)\n        {\n            LZ5_LOG_PARSER(\"%d: price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep); \n        }\n\n        LZ5_LOG_PARSER(\"%d: cur=%d/%d best_mlen=%d best_off=%d rep=%d\\n\", (int)(ip-source+cur), cur, last_pos, best_mlen, best_off, opt[cur].rep); \n\n        opt[0].mlen = 1;\n        \n        while (1)\n        {\n            mlen = opt[cur].mlen;\n            offset = opt[cur].off;\n            opt[cur].mlen = (int)best_mlen; \n            opt[cur].off = (int)best_off;\n            best_mlen = mlen;\n            best_off = offset;\n            if (mlen > cur) break;\n            cur -= mlen;\n        }\n          \n        for (i = 0; i <= last_pos;)\n        {\n            LZ5_LOG_PARSER(\"%d: price2[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep); \n            i += opt[i].mlen;\n        }\n\n        cur = 0;\n\n        while (cur < last_pos)\n        {\n            LZ5_LOG_PARSER(\"%d: price3[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(ip-source+cur), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep); \n            mlen = opt[cur].mlen;\n            if (mlen == 1) { ip++; cur++; continue; }\n            offset = opt[cur].off;\n            cur += mlen;\n\n            LZ5_LOG_ENCODE(\"%d: ENCODE literals=%d off=%d mlen=%d \", (int)(ip-source), (int)(ip-anchor), (int)(offset), mlen);\n            res = LZ5HC_encodeSequence(ctx, &ip, &op, &anchor, (int)mlen, ip - offset, limit, oend);\n            LZ5_LOG_ENCODE(\"out=%d\\n\", (int)((char*)op - dest));\n\n            if (res) return 0; \n\n            LZ5_LOG_PARSER(\"%d: offset=%d rep=%d\\n\", (int)(ip-source), offset, ctx->last_off);\n        }\n    }\n\n    /* Encode Last Literals */\n    {\n        int lastRun = (int)(iend - anchor);\n    //    if (inputSize > LASTLITERALS && lastRun < LASTLITERALS) { printf(\"ERROR: lastRun=%d\\n\", lastRun); }\n        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */\n        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }\n        else *op++ = (BYTE)(lastRun<<ML_BITS);\n        LZ5_LOG_ENCODE(\"%d: ENCODE_LAST literals=%d out=%d\\n\", (int)(ip-source), (int)(iend-anchor), (int)((char*)op -dest));\n        memcpy(op, anchor, iend - anchor);\n        op += iend-anchor;\n    }\n\n    /* End */\n    return (int) ((char*)op-dest);\n}\n\n\n\nstatic int LZ5HC_compress_lowest_price (\n    LZ5HC_Data_Structure* ctx,\n    const char* source,\n    char* dest,\n    int inputSize,\n    int maxOutputSize,\n    limitedOutput_directive limit\n    )\n{\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + inputSize;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    BYTE* op = (BYTE*) dest;\n    BYTE* const oend = op + maxOutputSize;\n\n    int   ml, ml2, ml0;\n    const BYTE* ref=NULL;\n    const BYTE* start2=NULL;\n    const BYTE* ref2=NULL;\n    const BYTE* start0;\n    const BYTE* ref0;\n    const BYTE* lowPrefixPtr = ctx->base + ctx->dictLimit;\n\n    /* init */\n\tctx->inputBuffer = (const BYTE*)source;\n\tctx->outputBuffer = (const BYTE*)dest;\n\tctx->end += inputSize;\n\n    ip++;\n\n    /* Main Loop */\n    while (ip < mflimit)\n    {\n        LZ5HC_Insert(ctx, ip);\n        ml = LZ5HC_FindBestMatch (ctx, ip, matchlimit, (&ref));\n        if (!ml) { ip++; continue; }\n\n\t\t{\n\t\t\tint back = 0;\n\t\t\twhile ((ip + back > anchor) && (ref + back > lowPrefixPtr) && (ip[back - 1] == ref[back - 1])) back--;\n\t\t\tml -= back;\n\t\t\tip += back;\n\t\t\tref += back;\n\t\t}\n\n        /* saved, in case we would skip too much */\n        start0 = ip;\n        ref0 = ref;\n        ml0 = ml;\n\n_Search:\n        if (ip+ml >= mflimit) goto _Encode;\n\n        LZ5HC_Insert(ctx, ip);\n        ml2 = (int)LZ5HC_GetWiderMatch(ctx, ip + ml - 2, anchor, matchlimit, 0, &ref2, &start2);\n        if (ml2 == 0) goto _Encode;\n\n        {\n        int price, best_price;\n        U32 off0=0, off1=0;\n        const uint8_t *pos, *best_pos;\n\n    //\tfind the lowest price for encoding ml bytes\n        best_pos = ip;\n        best_price = 1<<30;\n        off0 = (U32)(ip - ref);\n        off1 = (U32)(start2 - ref2);\n\n        for (pos = ip + ml; pos >= start2; pos--)\n        {\n            int common0 = (int)(pos - ip);\n            if (common0 >= MINMATCH)\n            {\n                price = (int)LZ5_CODEWORD_COST(ip - anchor, (off0 == ctx->last_off) ? 0 : off0, common0 - MINMATCH);\n                \n\t\t\t\t{\n\t\t\t\t\tint common1 = (int)(start2 + ml2 - pos);\n\t\t\t\t\tif (common1 >= MINMATCH)\n\t\t\t\t\t\tprice += (int)LZ5_CODEWORD_COST(0, (off1 == off0) ? 0 : (off1), common1 - MINMATCH);\n\t\t\t\t\telse\n\t\t\t\t\t\tprice += LZ5_LIT_ONLY_COST(common1) - 1;\n\t\t\t\t}\n\n                if (price < best_price)\n                {\n                    best_price = price;\n                    best_pos = pos;\n                }\n            }\n            else\n            {\n                price = (int)LZ5_CODEWORD_COST(start2 - anchor, (off1 == ctx->last_off) ? 0 : off1, ml2 - MINMATCH);\n\n                if (price < best_price)\n                    best_pos = pos;\n                break;\n            }\n        }\n    //    LZ5HC_DEBUG(\"%u: TRY last_off=%d literals=%u off=%u mlen=%u literals2=%u off2=%u mlen2=%u best=%d\\n\", (U32)(ip - ctx->inputBuffer), ctx->last_off, (U32)(ip - anchor), off0, (U32)ml,  (U32)(start2 - anchor), off1, ml2, (U32)(best_pos - ip));\n        ml = (int)(best_pos - ip);\n        }\n\n\n        if (ml < MINMATCH)\n        {\n            ip = start2;\n            ref = ref2;\n            ml = ml2;\n            goto _Search;\n        }\n        \n_Encode:\n\n        if (start0 < ip)\n        {\n            if (LZ5HC_more_profitable((ip - ref), ml,(start0 - ref0), ml0, (ref0 - ref), ctx->last_off))\n            {\n                ip = start0;\n                ref = ref0;\n                ml = ml0;\n            }\n        }\n\n        if (LZ5HC_encodeSequence(ctx, &ip, &op, &anchor, ml, ref, limit, oend)) return 0;\n    }\n\n    /* Encode Last Literals */\n    {\n        int lastRun = (int)(iend - anchor);\n        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */\n        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }\n        else *op++ = (BYTE)(lastRun<<ML_BITS);\n        memcpy(op, anchor, iend - anchor);\n        op += iend-anchor;\n    }\n\n    /* End */\n    return (int) (((char*)op)-dest);\n}\n\n\n\nstatic int LZ5HC_compress_price_fast (\n    LZ5HC_Data_Structure* ctx,\n    const char* source,\n    char* dest,\n    int inputSize,\n    int maxOutputSize,\n    limitedOutput_directive limit\n    )\n{\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + inputSize;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    BYTE* op = (BYTE*) dest;\n    BYTE* const oend = op + maxOutputSize;\n\n    int   ml, ml2=0;\n    const BYTE* ref=NULL;\n    const BYTE* start2=NULL;\n    const BYTE* ref2=NULL;\n    const BYTE* lowPrefixPtr = ctx->base + ctx->dictLimit;\n    U32* HashTable  = ctx->hashTable;\n#if MINMATCH == 3\n    U32* HashTable3  = ctx->hashTable3;\n#endif \n    const BYTE* const base = ctx->base;\n    U32* HashPos, *HashPos3;\n\n    /* init */\n\tctx->inputBuffer = (const BYTE*)source;\n\tctx->outputBuffer = (const BYTE*)dest;\n\tctx->end += inputSize;\n\n    ip++;\n\n    /* Main Loop */\n    while (ip < mflimit)\n    {\n        HashPos = &HashTable[LZ5HC_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n#if MINMATCH == 3\n        HashPos3 = &HashTable3[LZ5HC_hash3Ptr(ip, ctx->params.hashLog3)];\n        ml = LZ5HC_FindMatchFast (ctx, *HashPos, *HashPos3, ip, matchlimit, (&ref));\n        *HashPos3 = (U32)(ip - base);\n#else\n        ml = LZ5HC_FindMatchFast (ctx, *HashPos, 0, ip, matchlimit, (&ref));\n#endif \n        *HashPos =  (U32)(ip - base);\n\n        if (!ml) { ip++; continue; }\n\n        if ((U32)(ip - ref) == ctx->last_off) { ml2=0; goto _Encode; }\n        \n        {\n        int back = 0;\n        while ((ip+back>anchor) && (ref+back > lowPrefixPtr) && (ip[back-1] == ref[back-1])) back--;\n        ml -= back;\n        ip += back;\n        ref += back;\n        }\n        \n_Search:\n        if (ip+ml >= mflimit) goto _Encode;\n\n        start2 = ip + ml - 2;\n        HashPos = &HashTable[LZ5HC_hashPtr(start2, ctx->params.hashLog, ctx->params.searchLength)];\n        ml2 = LZ5HC_FindMatchFaster(ctx, *HashPos, start2, matchlimit, (&ref2));      \n        *HashPos = (U32)(start2 - base);\n        if (!ml2) goto _Encode;\n\n        {\n        int back = 0;\n        while ((start2+back>ip) && (ref2+back > lowPrefixPtr) && (start2[back-1] == ref2[back-1])) back--;\n        ml2 -= back;\n        start2 += back;\n        ref2 += back;\n        }\n\n    //    LZ5HC_DEBUG(\"%u: TRY last_off=%d literals=%u off=%u mlen=%u literals2=%u off2=%u mlen2=%u best=%d\\n\", (U32)(ip - ctx->inputBuffer), ctx->last_off, (U32)(ip - anchor), off0, (U32)ml,  (U32)(start2 - anchor), off1, ml2, (U32)(best_pos - ip));\n\n        if (ml2 <= ml) { ml2 = 0; goto _Encode; }\n\n        if (start2 <= ip)\n        {\n            ip = start2; ref = ref2; ml = ml2;\n            ml2 = 0;\n            goto _Encode;\n        }\n\n        if (start2 - ip < 3) \n        { \n            ip = start2; ref = ref2; ml = ml2;\n            ml2 = 0; \n            goto _Search; \n        }\n\n\n        if (start2 < ip + ml) \n        {\n            int correction = ml - (int)(start2 - ip);\n            start2 += correction;\n            ref2 += correction;\n            ml2 -= correction;\n            if (ml2 < 3) { ml2 = 0; }\n        }\n        \n_Encode:\n        if (LZ5HC_encodeSequence(ctx, &ip, &op, &anchor, ml, ref, limit, oend)) return 0;\n\n        if (ml2)\n        {\n            ip = start2; ref = ref2; ml = ml2;\n            ml2 = 0;\n            goto _Search;\n        }\n    }\n\n    /* Encode Last Literals */\n    {\n        int lastRun = (int)(iend - anchor);\n        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */\n        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }\n        else *op++ = (BYTE)(lastRun<<ML_BITS);\n        memcpy(op, anchor, iend - anchor);\n        op += iend-anchor;\n    }\n\n    /* End */\n    return (int) (((char*)op)-dest);\n}\n\n\n\nstatic int LZ5HC_compress_fast (\n    LZ5HC_Data_Structure* ctx,\n    const char* source,\n    char* dest,\n    int inputSize,\n    int maxOutputSize,\n    limitedOutput_directive limit\n    )\n{\n    const BYTE* ip = (const BYTE*) source;\n    const BYTE* anchor = ip;\n    const BYTE* const iend = ip + inputSize;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    BYTE* op = (BYTE*) dest;\n    BYTE* const oend = op + maxOutputSize;\n\n    int   ml;\n    const BYTE* ref=NULL;\n    const BYTE* lowPrefixPtr = ctx->base + ctx->dictLimit;\n    const BYTE* const base = ctx->base;\n    U32* HashPos;\n    U32* HashTable  = ctx->hashTable;\n\tconst int accel = (ctx->params.searchNum>0)?ctx->params.searchNum:1;\n    \n    /* init */\n\tctx->inputBuffer = (const BYTE*)source;\n\tctx->outputBuffer = (const BYTE*)dest;\n\tctx->end += inputSize;\n\n    ip++;\n\n    /* Main Loop */\n    while (ip < mflimit)\n    {\n        HashPos = &HashTable[LZ5HC_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n        ml = LZ5HC_FindMatchFastest (ctx, *HashPos, ip, matchlimit, (&ref));\n        *HashPos =  (U32)(ip - base);\n        if (!ml) { ip+=accel; continue; }\n\n\t\t{\n\t\t\tint back = 0;\n\t\t\twhile ((ip + back > anchor) && (ref + back > lowPrefixPtr) && (ip[back - 1] == ref[back - 1])) back--;\n\t\t\tml -= back;\n\t\t\tip += back;\n\t\t\tref += back;\n\t\t}\n\n        if (LZ5HC_encodeSequence(ctx, &ip, &op, &anchor, ml, ref, limit, oend)) return 0;\n\n    }\n\n    /* Encode Last Literals */\n    {\n        int lastRun = (int)(iend - anchor);\n        if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0;  /* Check output limit */\n        if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }\n        else *op++ = (BYTE)(lastRun<<ML_BITS);\n        memcpy(op, anchor, iend - anchor);\n        op += iend-anchor;\n    }\n\n    /* End */\n    return (int) (((char*)op)-dest);\n}\n\n\n\nstatic int LZ5HC_compress_generic (void* ctxvoid, const char* source, char* dest, int inputSize, int maxOutputSize, limitedOutput_directive limit)\n{\n    LZ5HC_Data_Structure* ctx = (LZ5HC_Data_Structure*) ctxvoid;\n\n    switch(ctx->params.strategy)\n    {\n    default:\n    case LZ5HC_fast:\n        return LZ5HC_compress_fast(ctx, source, dest, inputSize, maxOutputSize, limit);\n    case LZ5HC_price_fast:\n        return LZ5HC_compress_price_fast(ctx, source, dest, inputSize, maxOutputSize, limit);\n    case LZ5HC_lowest_price:\n        return LZ5HC_compress_lowest_price(ctx, source, dest, inputSize, maxOutputSize, limit);\n    case LZ5HC_optimal_price:\n    case LZ5HC_optimal_price_bt:\n        return LZ5HC_compress_optimal_price(ctx, (const BYTE* )source, dest, inputSize, maxOutputSize, limit);\n    }\n}\n\n\nint LZ5_sizeofStateHC(void) { return sizeof(LZ5HC_Data_Structure); }\n\nint LZ5_compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize)\n{\n    if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0;   /* Error : state is not aligned for pointers (32 or 64 bits) */\n    LZ5HC_init ((LZ5HC_Data_Structure*)state, (const BYTE*)src);\n    if (maxDstSize < LZ5_compressBound(srcSize))\n        return LZ5HC_compress_generic (state, src, dst, srcSize, maxDstSize, limitedOutput);\n    else\n        return LZ5HC_compress_generic (state, src, dst, srcSize, maxDstSize, noLimit);\n}\n\n\nint LZ5_compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)\n{\n    LZ5HC_Data_Structure state;\n    LZ5HC_Data_Structure* const statePtr = &state;\n    int cSize = 0;\n\n    if (!LZ5_alloc_mem_HC(statePtr, compressionLevel))\n        return 0;\n    cSize = LZ5_compress_HC_extStateHC(statePtr, src, dst, srcSize, maxDstSize);\n\n    LZ5_free_mem_HC(statePtr);\n\n    return cSize;\n}\n\n\n\n/**************************************\n*  Streaming Functions\n**************************************/\n/* allocation */\nLZ5_streamHC_t* LZ5_createStreamHC(int compressionLevel) \n{ \n    LZ5_streamHC_t* statePtr = (LZ5_streamHC_t*)malloc(sizeof(LZ5_streamHC_t));\n    if (!statePtr)\n        return NULL;\n\n    if (!LZ5_alloc_mem_HC((LZ5HC_Data_Structure*)statePtr, compressionLevel))\n    {\n        FREEMEM(statePtr);\n        return NULL;\n    }\n    return statePtr; \n}\n\nint LZ5_freeStreamHC (LZ5_streamHC_t* LZ5_streamHCPtr)\n{\n    LZ5HC_Data_Structure* statePtr = (LZ5HC_Data_Structure*)LZ5_streamHCPtr;\n    if (statePtr)\n    {\n        LZ5_free_mem_HC(statePtr);\n        free(LZ5_streamHCPtr); \n    }\n    return 0; \n}\n\n\n/* initialization */\nvoid LZ5_resetStreamHC (LZ5_streamHC_t* LZ5_streamHCPtr)\n{\n    LZ5_STATIC_ASSERT(sizeof(LZ5HC_Data_Structure) <= sizeof(LZ5_streamHC_t));   /* if compilation fails here, LZ5_STREAMHCSIZE must be increased */\n    ((LZ5HC_Data_Structure*)LZ5_streamHCPtr)->base = NULL;\n}\n\nint LZ5_loadDictHC (LZ5_streamHC_t* LZ5_streamHCPtr, const char* dictionary, int dictSize)\n{\n    LZ5HC_Data_Structure* ctxPtr = (LZ5HC_Data_Structure*) LZ5_streamHCPtr;\n    if (dictSize > LZ5_DICT_SIZE)\n    {\n        dictionary += dictSize - LZ5_DICT_SIZE;\n        dictSize = LZ5_DICT_SIZE;\n    }\n    LZ5HC_init (ctxPtr, (const BYTE*)dictionary);\n    if (dictSize >= 4) LZ5HC_Insert (ctxPtr, (const BYTE*)dictionary +(dictSize-3));\n    ctxPtr->end = (const BYTE*)dictionary + dictSize;\n    return dictSize;\n}\n\n\n/* compression */\n\nstatic void LZ5HC_setExternalDict(LZ5HC_Data_Structure* ctxPtr, const BYTE* newBlock)\n{\n    if (ctxPtr->end >= ctxPtr->base + 4)\n        LZ5HC_Insert (ctxPtr, ctxPtr->end-3);   /* Referencing remaining dictionary content */\n    /* Only one memory segment for extDict, so any previous extDict is lost at this stage */\n    ctxPtr->lowLimit  = ctxPtr->dictLimit;\n    ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);\n    ctxPtr->dictBase  = ctxPtr->base;\n    ctxPtr->base = newBlock - ctxPtr->dictLimit;\n    ctxPtr->end  = newBlock;\n    ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */\n}\n\nstatic int LZ5_compressHC_continue_generic (LZ5HC_Data_Structure* ctxPtr,\n                                            const char* source, char* dest,\n                                            int inputSize, int maxOutputSize, limitedOutput_directive limit)\n{\n    /* auto-init if forgotten */\n    if (ctxPtr->base == NULL)\n        LZ5HC_init (ctxPtr, (const BYTE*) source);\n\n    /* Check overflow */\n    if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)\n    {\n        size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;\n        if (dictSize > LZ5_DICT_SIZE) dictSize = LZ5_DICT_SIZE;\n\n        LZ5_loadDictHC((LZ5_streamHC_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);\n    }\n\n    /* Check if blocks follow each other */\n    if ((const BYTE*)source != ctxPtr->end)\n        LZ5HC_setExternalDict(ctxPtr, (const BYTE*)source);\n\n    /* Check overlapping input/dictionary space */\n    {\n        const BYTE* sourceEnd = (const BYTE*) source + inputSize;\n        const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;\n        const BYTE* dictEnd   = ctxPtr->dictBase + ctxPtr->dictLimit;\n        if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd))\n        {\n            if (sourceEnd > dictEnd) sourceEnd = dictEnd;\n            ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);\n            if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;\n        }\n    }\n\n    return LZ5HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, limit);\n}\n\nint LZ5_compress_HC_continue (LZ5_streamHC_t* LZ5_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)\n{\n    if (maxOutputSize < LZ5_compressBound(inputSize))\n        return LZ5_compressHC_continue_generic ((LZ5HC_Data_Structure*)LZ5_streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);\n    else\n        return LZ5_compressHC_continue_generic ((LZ5HC_Data_Structure*)LZ5_streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit);\n}\n\n\n/* dictionary saving */\n\nint LZ5_saveDictHC (LZ5_streamHC_t* LZ5_streamHCPtr, char* safeBuffer, int dictSize)\n{\n    LZ5HC_Data_Structure* streamPtr = (LZ5HC_Data_Structure*)LZ5_streamHCPtr;\n    int prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));\n    if (dictSize > LZ5_DICT_SIZE) dictSize = LZ5_DICT_SIZE;\n  //  if (dictSize < 4) dictSize = 0;\n    if (dictSize > prefixSize) dictSize = prefixSize;\n    memmove(safeBuffer, streamPtr->end - dictSize, dictSize);\n    {\n        U32 endIndex = (U32)(streamPtr->end - streamPtr->base);\n        streamPtr->end = (const BYTE*)safeBuffer + dictSize;\n        streamPtr->base = streamPtr->end - endIndex;\n        streamPtr->dictLimit = endIndex - dictSize;\n        streamPtr->lowLimit = endIndex - dictSize;\n        if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;\n    }\n    return dictSize;\n}\n\n/***********************************\n*  Deprecated Functions\n***********************************/\n/* Deprecated compression functions */\n/* These functions are planned to start generate warnings by r132 approximately */\nint LZ5_compressHC(const char* src, char* dst, int srcSize) { return LZ5_compress_HC (src, dst, srcSize, LZ5_compressBound(srcSize), 0); }\nint LZ5_compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ5_compress_HC(src, dst, srcSize, maxDstSize, 0); }\nint LZ5_compressHC_continue (LZ5_streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ5_compress_HC_continue (ctx, src, dst, srcSize, LZ5_compressBound(srcSize)); }\nint LZ5_compressHC_limitedOutput_continue (LZ5_streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ5_compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); } \nint LZ5_compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ5_compress_HC_extStateHC (state, src, dst, srcSize, LZ5_compressBound(srcSize)); }\nint LZ5_compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ5_compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize); } \n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/lz5hc.h",
    "content": "﻿/*\n   LZ5 HC - High Compression Mode of LZ5\n   Header File\n   Copyright (C) 2011-2015, Yann Collet.\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - LZ5 source repository : https://github.com/inikep/lz5\n   - LZ5 public forum : https://groups.google.com/forum/#!forum/lz5c\n*/\n#pragma once\n\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*****************************\n*  Includes\n*****************************/\n#include <stddef.h>   /* size_t */\n\n\n/**************************************\n*  Block Compression\n**************************************/\nint LZ5_compress_HC (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);\n/*\nLZ5_compress_HC :\n    Destination buffer 'dst' must be already allocated.\n    Compression completion is guaranteed if 'dst' buffer is sized to handle worst circumstances (data not compressible)\n    Worst size evaluation is provided by function LZ5_compressBound() (see \"lz5.h\")\n      srcSize  : Max supported value is LZ5_MAX_INPUT_SIZE (see \"lz5.h\")\n      compressionLevel : Recommended values are between 4 and 9, although any value between 0 and LZ5HC_MAX_CLEVEL (equal to 15) will work.\n                         0 means \"use default value\" (see lz5hc.c).\n                         Values >LZ5HC_MAX_CLEVEL behave the same as LZ5HC_MAX_CLEVEL.\n      return : the number of bytes written into buffer 'dst'\n            or 0 if compression fails.\n*/\n\n\n/* Note :\n   Decompression functions are provided within LZ5 source code (see \"lz5.h\") (BSD license)\n*/\n\ntypedef struct LZ5HC_Data_s LZ5HC_Data_Structure;\n\nint LZ5_alloc_mem_HC(LZ5HC_Data_Structure* statePtr, int compressionLevel);\nvoid LZ5_free_mem_HC(LZ5HC_Data_Structure* statePtr);\n\nint LZ5_sizeofStateHC(void);\nint LZ5_compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize);\n/*\nLZ5_compress_HC_extStateHC() :\n   Use this function if you prefer to manually allocate memory for compression tables.\n   To know how much memory must be allocated for the compression tables, use :\n      int LZ5_sizeofStateHC();\n\n   Allocated memory must be aligned on 8-bytes boundaries (which a normal malloc() will do properly).\n\n   The allocated memory can then be provided to the compression functions using 'void* state' parameter.\n   LZ5_compress_HC_extStateHC() is equivalent to previously described function.\n   It just uses externally allocated memory for stateHC.\n*/\n\n\n/**************************************\n*  Streaming Compression\n**************************************/\n#define LZ5_STREAMHCSIZE        262192\n#define LZ5_STREAMHCSIZE_SIZET (LZ5_STREAMHCSIZE / sizeof(size_t))\ntypedef struct { size_t table[LZ5_STREAMHCSIZE_SIZET]; } LZ5_streamHC_t;\n/*\n  LZ5_streamHC_t\n  This structure allows static allocation of LZ5 HC streaming state.\n  State must then be initialized using LZ5_resetStreamHC() before first use.\n\n  Static allocation should only be used in combination with static linking.\n  If you want to use LZ5 as a DLL, please use construction functions below, which are future-proof.\n*/\n\n\nLZ5_streamHC_t* LZ5_createStreamHC(int compressionLevel);\nint             LZ5_freeStreamHC (LZ5_streamHC_t* streamHCPtr);\n/*\n  These functions create and release memory for LZ5 HC streaming state.\n  Newly created states are already initialized.\n  Existing state space can be re-used anytime using LZ5_resetStreamHC().\n  If you use LZ5 as a DLL, use these functions instead of static structure allocation,\n  to avoid size mismatch between different versions.\n*/\n\nvoid LZ5_resetStreamHC (LZ5_streamHC_t* streamHCPtr);\nint  LZ5_loadDictHC (LZ5_streamHC_t* streamHCPtr, const char* dictionary, int dictSize);\n\nint LZ5_compress_HC_continue (LZ5_streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize);\n\nint LZ5_saveDictHC (LZ5_streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);\n\n/*\n  These functions compress data in successive blocks of any size, using previous blocks as dictionary.\n  One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.\n  There is an exception for ring buffers, which can be smaller 64 KB.\n  Such case is automatically detected and correctly handled by LZ5_compress_HC_continue().\n\n  Before starting compression, state must be properly initialized, using LZ5_resetStreamHC().\n  A first \"fictional block\" can then be designated as initial dictionary, using LZ5_loadDictHC() (Optional).\n\n  Then, use LZ5_compress_HC_continue() to compress each successive block.\n  It works like LZ5_compress_HC(), but use previous memory blocks as dictionary to improve compression.\n  Previous memory blocks (including initial dictionary when present) must remain accessible and unmodified during compression.\n  As a reminder, size 'dst' buffer to handle worst cases, using LZ5_compressBound(), to ensure success of compression operation.\n\n  If, for any reason, previous data blocks can't be preserved unmodified in memory during next compression block,\n  you must save it to a safer memory space, using LZ5_saveDictHC().\n  Return value of LZ5_saveDictHC() is the size of dictionary effectively saved into 'safeBuffer'.\n*/\n\n\n\n/**************************************\n*  Deprecated Functions\n**************************************/\n/* Deprecate Warnings */\n/* Should these warnings messages be a problem,\n   it is generally possible to disable them,\n   with -Wno-deprecated-declarations for gcc\n   or _CRT_SECURE_NO_WARNINGS in Visual for example.\n   You can also define LZ5_DEPRECATE_WARNING_DEFBLOCK. */\n#ifndef LZ5_DEPRECATE_WARNING_DEFBLOCK\n#  define LZ5_DEPRECATE_WARNING_DEFBLOCK\n#  if (LZ5_GCC_VERSION >= 405) || defined(__clang__)\n#    define LZ5_DEPRECATED(message) __attribute__((deprecated(message)))\n#  elif (LZ5_GCC_VERSION >= 301)\n#    define LZ5_DEPRECATED(message) __attribute__((deprecated))\n#  elif defined(_MSC_VER)\n#    define LZ5_DEPRECATED(message) __declspec(deprecated(message))\n#  else\n#    pragma message(\"WARNING: You need to implement LZ5_DEPRECATED for this compiler\")\n#    define LZ5_DEPRECATED(message)\n#  endif\n#endif // LZ5_DEPRECATE_WARNING_DEFBLOCK\n\n/* compression functions */\n/* these functions are planned to trigger warning messages by r132 approximately */\nint LZ5_compressHC                (const char* source, char* dest, int inputSize);\nint LZ5_compressHC_limitedOutput  (const char* source, char* dest, int inputSize, int maxOutputSize);\nint LZ5_compressHC_continue               (LZ5_streamHC_t* LZ5_streamHCPtr, const char* source, char* dest, int inputSize);\nint LZ5_compressHC_limitedOutput_continue (LZ5_streamHC_t* LZ5_streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);\nint LZ5_compressHC_withStateHC               (void* state, const char* source, char* dest, int inputSize);\nint LZ5_compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); \n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LZ5/mem.h",
    "content": "﻿/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define MEM_STATIC static inline\n#elif defined(_MSC_VER)\n#  define MEM_STATIC static __inline\n#elif defined(__GNUC__)\n#  define MEM_STATIC static __attribute__((unused))\n#else\n#  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n/* MEM_FORCE_MEMORY_ACCESS\n * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.\n * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.\n * The below switch allow to select different access method for improved performance.\n * Method 0 (default) : use `memcpy()`. Safe and portable.\n * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).\n *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.\n * Method 2 : direct access. This method is portable but violate C standard.\n *            It can generate buggy code on targets generating assembly depending on alignment.\n *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)\n * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.\n * Prefer these methods in priority order (0 > 1 > 2)\n */\n#ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */\n#  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )\n#    define MEM_FORCE_MEMORY_ACCESS 2\n#  elif defined(__INTEL_COMPILER) || \\\n  (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))\n#    define MEM_FORCE_MEMORY_ACCESS 1\n#  endif\n#endif\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\n#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)\n\n/* violates C standard on structure alignment.\nOnly use if no other choice to achieve best performance on target platform */\nMEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }\nMEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }\nMEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }\n\n#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)\n\n/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */\n/* currently only defined for gcc and icc */\ntypedef union { U16 u16; U32 u32; U64 u64; } __attribute__((packed)) unalign;\n\nMEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }\nMEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }\nMEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }\n\n#else\n\n/* default method, safe and standard.\n   can sometimes prove slower */\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write32(void* memPtr, U32 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write64(void* memPtr, U64 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\n#endif // MEM_FORCE_MEMORY_ACCESS\n\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write16(memPtr, val);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n    {\n        U32 val32 = 0;\n        memcpy(&val32, memPtr, 3);\n        return val32;\n    }\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)(p[0] + (p[1]<<8) + (p[2]<<16));\n    }\n} \n\nMEM_STATIC void MEM_writeLE24(void* memPtr, U32 value)\n{\n    if (MEM_isLittleEndian())\n    {\n        memcpy(memPtr, &value, 3);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE) value;\n        p[1] = (BYTE)(value>>8);\n        p[2] = (BYTE)(value>>16);\n    }\n}\n\n \nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\nMEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write32(memPtr, val32);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val32;\n        p[1] = (BYTE)(val32>>8);\n        p[2] = (BYTE)(val32>>16);\n        p[3] = (BYTE)(val32>>24);\n    }\n}\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\nMEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write64(memPtr, val64);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val64;\n        p[1] = (BYTE)(val64>>8);\n        p[2] = (BYTE)(val64>>16);\n        p[3] = (BYTE)(val64>>24);\n        p[4] = (BYTE)(val64>>32);\n        p[5] = (BYTE)(val64>>40);\n        p[6] = (BYTE)(val64>>48);\n        p[7] = (BYTE)(val64>>56);\n    }\n}\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)\n{\n    if (MEM_32bits())\n        MEM_writeLE32(memPtr, (U32)val);\n    else\n        MEM_writeLE64(memPtr, (U64)val);\n}\n\n\n#if MINMATCH == 3\n    #define MEM_read24(ptr) (U32)(MEM_read32(ptr)<<8) \n#else\n    #define MEM_read24(ptr) (U32)(MEM_read32(ptr)) \n#endif\n\n\n/* **************************************\n*  Function body to include for inlining\n****************************************/\nstatic size_t MEM_read_ARCH(const void* p) { size_t r; memcpy(&r, p, sizeof(r)); return r; }\n\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n\n\n/*static unsigned MEM_highbit(U32 val)\n{\n#   if defined(_MSC_VER)   // Visual \n    unsigned long r=0;\n    _BitScanReverse(&r, val);\n    return (unsigned)r;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   // GCC Intrinsic\n    return 31 - __builtin_clz(val);\n#   else   // Software version \n    static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    int r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}*/\n\n\nMEM_STATIC unsigned MEM_NbCommonBytes (register size_t val)\n{\n    if (MEM_isLittleEndian())\n    {\n        if (MEM_64bits())\n        {\n#       if defined(_MSC_VER) && defined(_WIN64)\n            unsigned long r = 0;\n            _BitScanForward64( &r, (U64)val );\n            return (int)(r>>3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 3)\n            return (__builtin_ctzll((U64)val) >> 3);\n#       else\n            static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };\n            return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];\n#       endif\n        }\n        else /* 32 bits */\n        {\n#       if defined(_MSC_VER)\n            unsigned long r=0;\n            _BitScanForward( &r, (U32)val );\n            return (int)(r>>3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 3)\n            return (__builtin_ctz((U32)val) >> 3);\n#       else\n            static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };\n            return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];\n#       endif\n        }\n    }\n    else   /* Big Endian CPU */\n    {\n        if (MEM_32bits())\n        {\n#       if defined(_MSC_VER) && defined(_WIN64)\n            unsigned long r = 0;\n            _BitScanReverse64( &r, val );\n            return (unsigned)(r>>3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 3)\n            return (__builtin_clzll(val) >> 3);\n#       else\n            unsigned r;\n            const unsigned n32 = sizeof(size_t)*4;   /* calculate this way due to compiler complaining in 32-bits mode */\n            if (!(val>>n32)) { r=4; } else { r=0; val>>=n32; }\n            if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }\n            r += (!val);\n            return r;\n#       endif\n        }\n        else /* 32 bits */\n        {\n#       if defined(_MSC_VER)\n            unsigned long r = 0;\n            _BitScanReverse( &r, (unsigned long)val );\n            return (unsigned)(r>>3);\n#       elif defined(__GNUC__) && (__GNUC__ >= 3)\n            return (__builtin_clz((U32)val) >> 3);\n#       else\n            unsigned r;\n            if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }\n            r += (!val);\n            return r;\n#       endif\n        }\n    }\n}\n\n\nMEM_STATIC size_t MEM_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)\n{\n    const BYTE* const pStart = pIn;\n\n    while ((pIn<pInLimit-(sizeof(size_t)-1)))\n    {\n        size_t diff = MEM_read_ARCH(pMatch) ^ MEM_read_ARCH(pIn);\n        if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }\n        pIn += MEM_NbCommonBytes(diff);\n        return (size_t)(pIn - pStart);\n    }\n\n    if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }\n    if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }\n    if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;\n    return (size_t)(pIn - pStart);\n}\n\n\nstatic void MEM_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { MEM_copy8(d,s); d+=8; s+=8; }\n\n\n/*! MEM_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */\n/*static void MEM_wildcopy(void* dst, const void* src, size_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n} */ \n\n/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */\nstatic void MEM_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)\n{\n    BYTE* d = (BYTE*)dstPtr;\n    const BYTE* s = (const BYTE*)srcPtr;\n    BYTE* const e = (BYTE*)dstEnd;\n\n    do { MEM_copy8(d,s); d+=8; s+=8; } while (d<e);\n}  \n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n"
  },
  {
    "path": "NanaZip.Codecs/LittleFS/lfs.c",
    "content": "﻿/*\n * The little filesystem\n *\n * Copyright (c) 2022, The littlefs authors.\n * Copyright (c) 2017, Arm Limited. All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n */\n#include \"lfs.h\"\n#include \"lfs_util.h\"\n\n\n// some constants used throughout the code\n#define LFS_BLOCK_NULL ((lfs_block_t)-1)\n#define LFS_BLOCK_INLINE ((lfs_block_t)-2)\n\nenum {\n    LFS_OK_RELOCATED = 1,\n    LFS_OK_DROPPED   = 2,\n    LFS_OK_ORPHANED  = 3,\n};\n\nenum {\n    LFS_CMP_EQ = 0,\n    LFS_CMP_LT = 1,\n    LFS_CMP_GT = 2,\n};\n\n\n/// Caching block device operations ///\n\nstatic inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) {\n    // do not zero, cheaper if cache is readonly or only going to be\n    // written with identical data (during relocates)\n    (void)lfs;\n    rcache->block = LFS_BLOCK_NULL;\n}\n\nstatic inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) {\n    // zero to avoid information leak\n    memset(pcache->buffer, 0xff, lfs->cfg->cache_size);\n    pcache->block = LFS_BLOCK_NULL;\n}\n\nstatic int lfs_bd_read(lfs_t *lfs,\n        const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint,\n        lfs_block_t block, lfs_off_t off,\n        void *buffer, lfs_size_t size) {\n    uint8_t *data = buffer;\n    if (off+size > lfs->cfg->block_size\n            || (lfs->block_count && block >= lfs->block_count)) {\n        return LFS_ERR_CORRUPT;\n    }\n\n    while (size > 0) {\n        lfs_size_t diff = size;\n\n        if (pcache && block == pcache->block &&\n                off < pcache->off + pcache->size) {\n            if (off >= pcache->off) {\n                // is already in pcache?\n                diff = lfs_min(diff, pcache->size - (off-pcache->off));\n                memcpy(data, &pcache->buffer[off-pcache->off], diff);\n\n                data += diff;\n                off += diff;\n                size -= diff;\n                continue;\n            }\n\n            // pcache takes priority\n            diff = lfs_min(diff, pcache->off-off);\n        }\n\n        if (block == rcache->block &&\n                off < rcache->off + rcache->size) {\n            if (off >= rcache->off) {\n                // is already in rcache?\n                diff = lfs_min(diff, rcache->size - (off-rcache->off));\n                memcpy(data, &rcache->buffer[off-rcache->off], diff);\n\n                data += diff;\n                off += diff;\n                size -= diff;\n                continue;\n            }\n\n            // rcache takes priority\n            diff = lfs_min(diff, rcache->off-off);\n        }\n\n        if (size >= hint && off % lfs->cfg->read_size == 0 &&\n                size >= lfs->cfg->read_size) {\n            // bypass cache?\n            diff = lfs_aligndown(diff, lfs->cfg->read_size);\n            int err = lfs->cfg->read(lfs->cfg, block, off, data, diff);\n            if (err) {\n                return err;\n            }\n\n            data += diff;\n            off += diff;\n            size -= diff;\n            continue;\n        }\n\n        // load to cache, first condition can no longer fail\n        LFS_ASSERT(!lfs->block_count || block < lfs->block_count);\n        rcache->block = block;\n        rcache->off = lfs_aligndown(off, lfs->cfg->read_size);\n        rcache->size = lfs_min(\n                lfs_min(\n                    lfs_alignup(off+hint, lfs->cfg->read_size),\n                    lfs->cfg->block_size)\n                - rcache->off,\n                lfs->cfg->cache_size);\n        int err = lfs->cfg->read(lfs->cfg, rcache->block,\n                rcache->off, rcache->buffer, rcache->size);\n        LFS_ASSERT(err <= 0);\n        if (err) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n\nstatic int lfs_bd_cmp(lfs_t *lfs,\n        const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint,\n        lfs_block_t block, lfs_off_t off,\n        const void *buffer, lfs_size_t size) {\n    const uint8_t *data = buffer;\n    lfs_size_t diff = 0;\n\n    for (lfs_off_t i = 0; i < size; i += diff) {\n        uint8_t dat[8];\n\n        diff = lfs_min(size-i, sizeof(dat));\n        int err = lfs_bd_read(lfs,\n                pcache, rcache, hint-i,\n                block, off+i, &dat, diff);\n        if (err) {\n            return err;\n        }\n\n        int res = memcmp(dat, data + i, diff);\n        if (res) {\n            return res < 0 ? LFS_CMP_LT : LFS_CMP_GT;\n        }\n    }\n\n    return LFS_CMP_EQ;\n}\n\nstatic int lfs_bd_crc(lfs_t *lfs,\n        const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint,\n        lfs_block_t block, lfs_off_t off, lfs_size_t size, uint32_t *crc) {\n    lfs_size_t diff = 0;\n\n    for (lfs_off_t i = 0; i < size; i += diff) {\n        uint8_t dat[8];\n        diff = lfs_min(size-i, sizeof(dat));\n        int err = lfs_bd_read(lfs,\n                pcache, rcache, hint-i,\n                block, off+i, &dat, diff);\n        if (err) {\n            return err;\n        }\n\n        *crc = lfs_crc(*crc, &dat, diff);\n    }\n\n    return 0;\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_bd_flush(lfs_t *lfs,\n        lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {\n    if (pcache->block != LFS_BLOCK_NULL && pcache->block != LFS_BLOCK_INLINE) {\n        LFS_ASSERT(pcache->block < lfs->block_count);\n        lfs_size_t diff = lfs_alignup(pcache->size, lfs->cfg->prog_size);\n        int err = lfs->cfg->prog(lfs->cfg, pcache->block,\n                pcache->off, pcache->buffer, diff);\n        LFS_ASSERT(err <= 0);\n        if (err) {\n            return err;\n        }\n\n        if (validate) {\n            // check data on disk\n            lfs_cache_drop(lfs, rcache);\n            int res = lfs_bd_cmp(lfs,\n                    NULL, rcache, diff,\n                    pcache->block, pcache->off, pcache->buffer, diff);\n            if (res < 0) {\n                return res;\n            }\n\n            if (res != LFS_CMP_EQ) {\n                return LFS_ERR_CORRUPT;\n            }\n        }\n\n        lfs_cache_zero(lfs, pcache);\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_bd_sync(lfs_t *lfs,\n        lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {\n    lfs_cache_drop(lfs, rcache);\n\n    int err = lfs_bd_flush(lfs, pcache, rcache, validate);\n    if (err) {\n        return err;\n    }\n\n    err = lfs->cfg->sync(lfs->cfg);\n    LFS_ASSERT(err <= 0);\n    return err;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_bd_prog(lfs_t *lfs,\n        lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate,\n        lfs_block_t block, lfs_off_t off,\n        const void *buffer, lfs_size_t size) {\n    const uint8_t *data = buffer;\n    LFS_ASSERT(block == LFS_BLOCK_INLINE || block < lfs->block_count);\n    LFS_ASSERT(off + size <= lfs->cfg->block_size);\n\n    while (size > 0) {\n        if (block == pcache->block &&\n                off >= pcache->off &&\n                off < pcache->off + lfs->cfg->cache_size) {\n            // already fits in pcache?\n            lfs_size_t diff = lfs_min(size,\n                    lfs->cfg->cache_size - (off-pcache->off));\n            memcpy(&pcache->buffer[off-pcache->off], data, diff);\n\n            data += diff;\n            off += diff;\n            size -= diff;\n\n            pcache->size = lfs_max(pcache->size, off - pcache->off);\n            if (pcache->size == lfs->cfg->cache_size) {\n                // eagerly flush out pcache if we fill up\n                int err = lfs_bd_flush(lfs, pcache, rcache, validate);\n                if (err) {\n                    return err;\n                }\n            }\n\n            continue;\n        }\n\n        // pcache must have been flushed, either by programming and\n        // entire block or manually flushing the pcache\n        LFS_ASSERT(pcache->block == LFS_BLOCK_NULL);\n\n        // prepare pcache, first condition can no longer fail\n        pcache->block = block;\n        pcache->off = lfs_aligndown(off, lfs->cfg->prog_size);\n        pcache->size = 0;\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_bd_erase(lfs_t *lfs, lfs_block_t block) {\n    LFS_ASSERT(block < lfs->block_count);\n    int err = lfs->cfg->erase(lfs->cfg, block);\n    LFS_ASSERT(err <= 0);\n    return err;\n}\n#endif\n\n\n/// Small type-level utilities ///\n\n// some operations on paths\nstatic inline lfs_size_t lfs_path_namelen(const char *path) {\n    return strcspn(path, \"/\");\n}\n\nstatic inline bool lfs_path_islast(const char *path) {\n    lfs_size_t namelen = lfs_path_namelen(path);\n    return path[namelen + strspn(path + namelen, \"/\")] == '\\0';\n}\n\nstatic inline bool lfs_path_isdir(const char *path) {\n    return path[lfs_path_namelen(path)] != '\\0';\n}\n\n// operations on block pairs\nstatic inline void lfs_pair_swap(lfs_block_t pair[2]) {\n    lfs_block_t t = pair[0];\n    pair[0] = pair[1];\n    pair[1] = t;\n}\n\nstatic inline bool lfs_pair_isnull(const lfs_block_t pair[2]) {\n    return pair[0] == LFS_BLOCK_NULL || pair[1] == LFS_BLOCK_NULL;\n}\n\nstatic inline int lfs_pair_cmp(\n        const lfs_block_t paira[2],\n        const lfs_block_t pairb[2]) {\n    return !(paira[0] == pairb[0] || paira[1] == pairb[1] ||\n             paira[0] == pairb[1] || paira[1] == pairb[0]);\n}\n\nstatic inline bool lfs_pair_issync(\n        const lfs_block_t paira[2],\n        const lfs_block_t pairb[2]) {\n    return (paira[0] == pairb[0] && paira[1] == pairb[1]) ||\n           (paira[0] == pairb[1] && paira[1] == pairb[0]);\n}\n\nstatic inline void lfs_pair_fromle32(lfs_block_t pair[2]) {\n    pair[0] = lfs_fromle32(pair[0]);\n    pair[1] = lfs_fromle32(pair[1]);\n}\n\n#ifndef LFS_READONLY\nstatic inline void lfs_pair_tole32(lfs_block_t pair[2]) {\n    pair[0] = lfs_tole32(pair[0]);\n    pair[1] = lfs_tole32(pair[1]);\n}\n#endif\n\n// operations on 32-bit entry tags\ntypedef uint32_t lfs_tag_t;\ntypedef int32_t lfs_stag_t;\n\n#define LFS_MKTAG(type, id, size) \\\n    (((lfs_tag_t)(type) << 20) | ((lfs_tag_t)(id) << 10) | (lfs_tag_t)(size))\n\n#define LFS_MKTAG_IF(cond, type, id, size) \\\n    ((cond) ? LFS_MKTAG(type, id, size) : LFS_MKTAG(LFS_FROM_NOOP, 0, 0))\n\n#define LFS_MKTAG_IF_ELSE(cond, type1, id1, size1, type2, id2, size2) \\\n    ((cond) ? LFS_MKTAG(type1, id1, size1) : LFS_MKTAG(type2, id2, size2))\n\nstatic inline bool lfs_tag_isvalid(lfs_tag_t tag) {\n    return !(tag & 0x80000000);\n}\n\nstatic inline bool lfs_tag_isdelete(lfs_tag_t tag) {\n    return ((int32_t)(tag << 22) >> 22) == -1;\n}\n\nstatic inline uint16_t lfs_tag_type1(lfs_tag_t tag) {\n    return (tag & 0x70000000) >> 20;\n}\n\nstatic inline uint16_t lfs_tag_type2(lfs_tag_t tag) {\n    return (tag & 0x78000000) >> 20;\n}\n\nstatic inline uint16_t lfs_tag_type3(lfs_tag_t tag) {\n    return (tag & 0x7ff00000) >> 20;\n}\n\nstatic inline uint8_t lfs_tag_chunk(lfs_tag_t tag) {\n    return (tag & 0x0ff00000) >> 20;\n}\n\nstatic inline int8_t lfs_tag_splice(lfs_tag_t tag) {\n    return (int8_t)lfs_tag_chunk(tag);\n}\n\nstatic inline uint16_t lfs_tag_id(lfs_tag_t tag) {\n    return (tag & 0x000ffc00) >> 10;\n}\n\nstatic inline lfs_size_t lfs_tag_size(lfs_tag_t tag) {\n    return tag & 0x000003ff;\n}\n\nstatic inline lfs_size_t lfs_tag_dsize(lfs_tag_t tag) {\n    return sizeof(tag) + lfs_tag_size(tag + lfs_tag_isdelete(tag));\n}\n\n// operations on attributes in attribute lists\nstruct lfs_mattr {\n    lfs_tag_t tag;\n    const void *buffer;\n};\n\nstruct lfs_diskoff {\n    lfs_block_t block;\n    lfs_off_t off;\n};\n\n#define LFS_MKATTRS(...) \\\n    (struct lfs_mattr[]){__VA_ARGS__}, \\\n    sizeof((struct lfs_mattr[]){__VA_ARGS__}) / sizeof(struct lfs_mattr)\n\n// operations on global state\nstatic inline void lfs_gstate_xor(lfs_gstate_t *a, const lfs_gstate_t *b) {\n    a->tag ^= b->tag;\n    a->pair[0] ^= b->pair[0];\n    a->pair[1] ^= b->pair[1];\n}\n\nstatic inline bool lfs_gstate_iszero(const lfs_gstate_t *a) {\n    return a->tag == 0\n            && a->pair[0] == 0\n            && a->pair[1] == 0;\n}\n\n#ifndef LFS_READONLY\nstatic inline bool lfs_gstate_hasorphans(const lfs_gstate_t *a) {\n    return lfs_tag_size(a->tag);\n}\n\nstatic inline uint8_t lfs_gstate_getorphans(const lfs_gstate_t *a) {\n    return lfs_tag_size(a->tag) & 0x1ff;\n}\n\nstatic inline bool lfs_gstate_hasmove(const lfs_gstate_t *a) {\n    return lfs_tag_type1(a->tag);\n}\n#endif\n\nstatic inline bool lfs_gstate_needssuperblock(const lfs_gstate_t *a) {\n    return lfs_tag_size(a->tag) >> 9;\n}\n\nstatic inline bool lfs_gstate_hasmovehere(const lfs_gstate_t *a,\n        const lfs_block_t *pair) {\n    return lfs_tag_type1(a->tag) && lfs_pair_cmp(a->pair, pair) == 0;\n}\n\nstatic inline void lfs_gstate_fromle32(lfs_gstate_t *a) {\n    a->tag     = lfs_fromle32(a->tag);\n    a->pair[0] = lfs_fromle32(a->pair[0]);\n    a->pair[1] = lfs_fromle32(a->pair[1]);\n}\n\n#ifndef LFS_READONLY\nstatic inline void lfs_gstate_tole32(lfs_gstate_t *a) {\n    a->tag     = lfs_tole32(a->tag);\n    a->pair[0] = lfs_tole32(a->pair[0]);\n    a->pair[1] = lfs_tole32(a->pair[1]);\n}\n#endif\n\n// operations on forward-CRCs used to track erased state\nstruct lfs_fcrc {\n    lfs_size_t size;\n    uint32_t crc;\n};\n\nstatic void lfs_fcrc_fromle32(struct lfs_fcrc *fcrc) {\n    fcrc->size = lfs_fromle32(fcrc->size);\n    fcrc->crc = lfs_fromle32(fcrc->crc);\n}\n\n#ifndef LFS_READONLY\nstatic void lfs_fcrc_tole32(struct lfs_fcrc *fcrc) {\n    fcrc->size = lfs_tole32(fcrc->size);\n    fcrc->crc = lfs_tole32(fcrc->crc);\n}\n#endif\n\n// other endianness operations\nstatic void lfs_ctz_fromle32(struct lfs_ctz *ctz) {\n    ctz->head = lfs_fromle32(ctz->head);\n    ctz->size = lfs_fromle32(ctz->size);\n}\n\n#ifndef LFS_READONLY\nstatic void lfs_ctz_tole32(struct lfs_ctz *ctz) {\n    ctz->head = lfs_tole32(ctz->head);\n    ctz->size = lfs_tole32(ctz->size);\n}\n#endif\n\nstatic inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) {\n    superblock->version     = lfs_fromle32(superblock->version);\n    superblock->block_size  = lfs_fromle32(superblock->block_size);\n    superblock->block_count = lfs_fromle32(superblock->block_count);\n    superblock->name_max    = lfs_fromle32(superblock->name_max);\n    superblock->file_max    = lfs_fromle32(superblock->file_max);\n    superblock->attr_max    = lfs_fromle32(superblock->attr_max);\n}\n\n#ifndef LFS_READONLY\nstatic inline void lfs_superblock_tole32(lfs_superblock_t *superblock) {\n    superblock->version     = lfs_tole32(superblock->version);\n    superblock->block_size  = lfs_tole32(superblock->block_size);\n    superblock->block_count = lfs_tole32(superblock->block_count);\n    superblock->name_max    = lfs_tole32(superblock->name_max);\n    superblock->file_max    = lfs_tole32(superblock->file_max);\n    superblock->attr_max    = lfs_tole32(superblock->attr_max);\n}\n#endif\n\n#ifndef LFS_NO_ASSERT\nstatic bool lfs_mlist_isopen(struct lfs_mlist *head,\n        struct lfs_mlist *node) {\n    for (struct lfs_mlist **p = &head; *p; p = &(*p)->next) {\n        if (*p == (struct lfs_mlist*)node) {\n            return true;\n        }\n    }\n\n    return false;\n}\n#endif\n\nstatic void lfs_mlist_remove(lfs_t *lfs, struct lfs_mlist *mlist) {\n    for (struct lfs_mlist **p = &lfs->mlist; *p; p = &(*p)->next) {\n        if (*p == mlist) {\n            *p = (*p)->next;\n            break;\n        }\n    }\n}\n\nstatic void lfs_mlist_append(lfs_t *lfs, struct lfs_mlist *mlist) {\n    mlist->next = lfs->mlist;\n    lfs->mlist = mlist;\n}\n\n// some other filesystem operations\nstatic uint32_t lfs_fs_disk_version(lfs_t *lfs) {\n    (void)lfs;\n#ifdef LFS_MULTIVERSION\n    if (lfs->cfg->disk_version) {\n        return lfs->cfg->disk_version;\n    } else\n#endif\n    {\n        return LFS_DISK_VERSION;\n    }\n}\n\nstatic uint16_t lfs_fs_disk_version_major(lfs_t *lfs) {\n    return 0xffff & (lfs_fs_disk_version(lfs) >> 16);\n\n}\n\nstatic uint16_t lfs_fs_disk_version_minor(lfs_t *lfs) {\n    return 0xffff & (lfs_fs_disk_version(lfs) >> 0);\n}\n\n\n/// Internal operations predeclared here ///\n#ifndef LFS_READONLY\nstatic int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,\n        const struct lfs_mattr *attrs, int attrcount);\nstatic int lfs_dir_compact(lfs_t *lfs,\n        lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,\n        lfs_mdir_t *source, uint16_t begin, uint16_t end);\nstatic lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,\n        const void *buffer, lfs_size_t size);\nstatic lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file,\n        const void *buffer, lfs_size_t size);\nstatic int lfs_file_sync_(lfs_t *lfs, lfs_file_t *file);\nstatic int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);\nstatic int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);\n\nstatic int lfs_fs_deorphan(lfs_t *lfs, bool powerloss);\nstatic int lfs_fs_preporphans(lfs_t *lfs, int8_t orphans);\nstatic void lfs_fs_prepmove(lfs_t *lfs,\n        uint16_t id, const lfs_block_t pair[2]);\nstatic int lfs_fs_pred(lfs_t *lfs, const lfs_block_t dir[2],\n        lfs_mdir_t *pdir);\nstatic lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2],\n        lfs_mdir_t *parent);\nstatic int lfs_fs_forceconsistency(lfs_t *lfs);\n#endif\n\nstatic void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock);\n\n#ifdef LFS_MIGRATE\nstatic int lfs1_traverse(lfs_t *lfs,\n        int (*cb)(void*, lfs_block_t), void *data);\n#endif\n\nstatic int lfs_dir_rewind_(lfs_t *lfs, lfs_dir_t *dir);\n\nstatic lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,\n        void *buffer, lfs_size_t size);\nstatic lfs_ssize_t lfs_file_read_(lfs_t *lfs, lfs_file_t *file,\n        void *buffer, lfs_size_t size);\nstatic int lfs_file_close_(lfs_t *lfs, lfs_file_t *file);\nstatic lfs_soff_t lfs_file_size_(lfs_t *lfs, lfs_file_t *file);\n\nstatic lfs_ssize_t lfs_fs_size_(lfs_t *lfs);\nstatic int lfs_fs_traverse_(lfs_t *lfs,\n        int (*cb)(void *data, lfs_block_t block), void *data,\n        bool includeorphans);\n\nstatic int lfs_deinit(lfs_t *lfs);\nstatic int lfs_unmount_(lfs_t *lfs);\n\n\n/// Block allocator ///\n\n// allocations should call this when all allocated blocks are committed to\n// the filesystem\n//\n// after a checkpoint, the block allocator may realloc any untracked blocks\nstatic void lfs_alloc_ckpoint(lfs_t *lfs) {\n    lfs->lookahead.ckpoint = lfs->block_count;\n}\n\n// drop the lookahead buffer, this is done during mounting and failed\n// traversals in order to avoid invalid lookahead state\nstatic void lfs_alloc_drop(lfs_t *lfs) {\n    lfs->lookahead.size = 0;\n    lfs->lookahead.next = 0;\n    lfs_alloc_ckpoint(lfs);\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_alloc_lookahead(void *p, lfs_block_t block) {\n    lfs_t *lfs = (lfs_t*)p;\n    lfs_block_t off = ((block - lfs->lookahead.start)\n            + lfs->block_count) % lfs->block_count;\n\n    if (off < lfs->lookahead.size) {\n        lfs->lookahead.buffer[off / 8] |= 1U << (off % 8);\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_alloc_scan(lfs_t *lfs) {\n    // move lookahead buffer to the first unused block\n    //\n    // note we limit the lookahead buffer to at most the amount of blocks\n    // checkpointed, this prevents the math in lfs_alloc from underflowing\n    lfs->lookahead.start = (lfs->lookahead.start + lfs->lookahead.next) \n            % lfs->block_count;\n    lfs->lookahead.next = 0;\n    lfs->lookahead.size = lfs_min(\n            8*lfs->cfg->lookahead_size,\n            lfs->lookahead.ckpoint);\n\n    // find mask of free blocks from tree\n    memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size);\n    int err = lfs_fs_traverse_(lfs, lfs_alloc_lookahead, lfs, true);\n    if (err) {\n        lfs_alloc_drop(lfs);\n        return err;\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {\n    while (true) {\n        // scan our lookahead buffer for free blocks\n        while (lfs->lookahead.next < lfs->lookahead.size) {\n            if (!(lfs->lookahead.buffer[lfs->lookahead.next / 8]\n                    & (1U << (lfs->lookahead.next % 8)))) {\n                // found a free block\n                *block = (lfs->lookahead.start + lfs->lookahead.next)\n                        % lfs->block_count;\n\n                // eagerly find next free block to maximize how many blocks\n                // lfs_alloc_ckpoint makes available for scanning\n                while (true) {\n                    lfs->lookahead.next += 1;\n                    lfs->lookahead.ckpoint -= 1;\n\n                    if (lfs->lookahead.next >= lfs->lookahead.size\n                            || !(lfs->lookahead.buffer[lfs->lookahead.next / 8]\n                                & (1U << (lfs->lookahead.next % 8)))) {\n                        return 0;\n                    }\n                }\n            }\n\n            lfs->lookahead.next += 1;\n            lfs->lookahead.ckpoint -= 1;\n        }\n\n        // In order to keep our block allocator from spinning forever when our\n        // filesystem is full, we mark points where there are no in-flight\n        // allocations with a checkpoint before starting a set of allocations.\n        //\n        // If we've looked at all blocks since the last checkpoint, we report\n        // the filesystem as out of storage.\n        //\n        if (lfs->lookahead.ckpoint <= 0) {\n            LFS_ERROR(\"No more free space 0x%\"PRIx32,\n                    (lfs->lookahead.start + lfs->lookahead.next)\n                        % lfs->block_count);\n            return LFS_ERR_NOSPC;\n        }\n\n        // No blocks in our lookahead buffer, we need to scan the filesystem for\n        // unused blocks in the next lookahead window.\n        int err = lfs_alloc_scan(lfs);\n        if(err) {\n            return err;\n        }\n    }\n}\n#endif\n\n/// Metadata pair and directory operations ///\nstatic lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir,\n        lfs_tag_t gmask, lfs_tag_t gtag,\n        lfs_off_t goff, void *gbuffer, lfs_size_t gsize) {\n    lfs_off_t off = dir->off;\n    lfs_tag_t ntag = dir->etag;\n    lfs_stag_t gdiff = 0;\n\n    // synthetic moves\n    if (lfs_gstate_hasmovehere(&lfs->gdisk, dir->pair) &&\n            lfs_tag_id(gmask) != 0) {\n        if (lfs_tag_id(lfs->gdisk.tag) == lfs_tag_id(gtag)) {\n            return LFS_ERR_NOENT;\n        } else if (lfs_tag_id(lfs->gdisk.tag) < lfs_tag_id(gtag)) {\n            gdiff -= LFS_MKTAG(0, 1, 0);\n        }\n    }\n\n    // iterate over dir block backwards (for faster lookups)\n    while (off >= sizeof(lfs_tag_t) + lfs_tag_dsize(ntag)) {\n        off -= lfs_tag_dsize(ntag);\n        lfs_tag_t tag = ntag;\n        int err = lfs_bd_read(lfs,\n                NULL, &lfs->rcache, sizeof(ntag),\n                dir->pair[0], off, &ntag, sizeof(ntag));\n        if (err) {\n            return err;\n        }\n\n        ntag = (lfs_frombe32(ntag) ^ tag) & 0x7fffffff;\n\n        if (lfs_tag_id(gmask) != 0 &&\n                lfs_tag_type1(tag) == LFS_TYPE_SPLICE &&\n                lfs_tag_id(tag) <= lfs_tag_id(gtag - gdiff)) {\n            if (tag == (LFS_MKTAG(LFS_TYPE_CREATE, 0, 0) |\n                    (LFS_MKTAG(0, 0x3ff, 0) & (gtag - gdiff)))) {\n                // found where we were created\n                return LFS_ERR_NOENT;\n            }\n\n            // move around splices\n            gdiff += LFS_MKTAG(0, lfs_tag_splice(tag), 0);\n        }\n\n        if ((gmask & tag) == (gmask & (gtag - gdiff))) {\n            if (lfs_tag_isdelete(tag)) {\n                return LFS_ERR_NOENT;\n            }\n\n            lfs_size_t diff = lfs_min(lfs_tag_size(tag), gsize);\n            err = lfs_bd_read(lfs,\n                    NULL, &lfs->rcache, diff,\n                    dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff);\n            if (err) {\n                return err;\n            }\n\n            memset((uint8_t*)gbuffer + diff, 0, gsize - diff);\n\n            return tag + gdiff;\n        }\n    }\n\n    return LFS_ERR_NOENT;\n}\n\nstatic lfs_stag_t lfs_dir_get(lfs_t *lfs, const lfs_mdir_t *dir,\n        lfs_tag_t gmask, lfs_tag_t gtag, void *buffer) {\n    return lfs_dir_getslice(lfs, dir,\n            gmask, gtag,\n            0, buffer, lfs_tag_size(gtag));\n}\n\nstatic int lfs_dir_getread(lfs_t *lfs, const lfs_mdir_t *dir,\n        const lfs_cache_t *pcache, lfs_cache_t *rcache, lfs_size_t hint,\n        lfs_tag_t gmask, lfs_tag_t gtag,\n        lfs_off_t off, void *buffer, lfs_size_t size) {\n    uint8_t *data = buffer;\n    if (off+size > lfs->cfg->block_size) {\n        return LFS_ERR_CORRUPT;\n    }\n\n    while (size > 0) {\n        lfs_size_t diff = size;\n\n        if (pcache && pcache->block == LFS_BLOCK_INLINE &&\n                off < pcache->off + pcache->size) {\n            if (off >= pcache->off) {\n                // is already in pcache?\n                diff = lfs_min(diff, pcache->size - (off-pcache->off));\n                memcpy(data, &pcache->buffer[off-pcache->off], diff);\n\n                data += diff;\n                off += diff;\n                size -= diff;\n                continue;\n            }\n\n            // pcache takes priority\n            diff = lfs_min(diff, pcache->off-off);\n        }\n\n        if (rcache->block == LFS_BLOCK_INLINE &&\n                off < rcache->off + rcache->size) {\n            if (off >= rcache->off) {\n                // is already in rcache?\n                diff = lfs_min(diff, rcache->size - (off-rcache->off));\n                memcpy(data, &rcache->buffer[off-rcache->off], diff);\n\n                data += diff;\n                off += diff;\n                size -= diff;\n                continue;\n            }\n\n            // rcache takes priority\n            diff = lfs_min(diff, rcache->off-off);\n        }\n\n        // load to cache, first condition can no longer fail\n        rcache->block = LFS_BLOCK_INLINE;\n        rcache->off = lfs_aligndown(off, lfs->cfg->read_size);\n        rcache->size = lfs_min(lfs_alignup(off+hint, lfs->cfg->read_size),\n                lfs->cfg->cache_size);\n        int err = lfs_dir_getslice(lfs, dir, gmask, gtag,\n                rcache->off, rcache->buffer, rcache->size);\n        if (err < 0) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_traverse_filter(void *p,\n        lfs_tag_t tag, const void *buffer) {\n    lfs_tag_t *filtertag = p;\n    (void)buffer;\n\n    // which mask depends on unique bit in tag structure\n    uint32_t mask = (tag & LFS_MKTAG(0x100, 0, 0))\n            ? LFS_MKTAG(0x7ff, 0x3ff, 0)\n            : LFS_MKTAG(0x700, 0x3ff, 0);\n\n    // check for redundancy\n    if ((mask & tag) == (mask & *filtertag) ||\n            lfs_tag_isdelete(*filtertag) ||\n            (LFS_MKTAG(0x7ff, 0x3ff, 0) & tag) == (\n                LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) |\n                    (LFS_MKTAG(0, 0x3ff, 0) & *filtertag))) {\n        *filtertag = LFS_MKTAG(LFS_FROM_NOOP, 0, 0);\n        return true;\n    }\n\n    // check if we need to adjust for created/deleted tags\n    if (lfs_tag_type1(tag) == LFS_TYPE_SPLICE &&\n            lfs_tag_id(tag) <= lfs_tag_id(*filtertag)) {\n        *filtertag += LFS_MKTAG(0, lfs_tag_splice(tag), 0);\n    }\n\n    return false;\n}\n#endif\n\n#ifndef LFS_READONLY\n// maximum recursive depth of lfs_dir_traverse, the deepest call:\n//\n// traverse with commit\n// '-> traverse with move\n//     '-> traverse with filter\n//\n#define LFS_DIR_TRAVERSE_DEPTH 3\n\nstruct lfs_dir_traverse {\n    const lfs_mdir_t *dir;\n    lfs_off_t off;\n    lfs_tag_t ptag;\n    const struct lfs_mattr *attrs;\n    int attrcount;\n\n    lfs_tag_t tmask;\n    lfs_tag_t ttag;\n    uint16_t begin;\n    uint16_t end;\n    int16_t diff;\n\n    int (*cb)(void *data, lfs_tag_t tag, const void *buffer);\n    void *data;\n\n    lfs_tag_t tag;\n    const void *buffer;\n    struct lfs_diskoff disk;\n};\n\nstatic int lfs_dir_traverse(lfs_t *lfs,\n        const lfs_mdir_t *dir, lfs_off_t off, lfs_tag_t ptag,\n        const struct lfs_mattr *attrs, int attrcount,\n        lfs_tag_t tmask, lfs_tag_t ttag,\n        uint16_t begin, uint16_t end, int16_t diff,\n        int (*cb)(void *data, lfs_tag_t tag, const void *buffer), void *data) {\n    // This function in inherently recursive, but bounded. To allow tool-based\n    // analysis without unnecessary code-cost we use an explicit stack\n    struct lfs_dir_traverse stack[LFS_DIR_TRAVERSE_DEPTH-1];\n    unsigned sp = 0;\n    int res;\n\n    // iterate over directory and attrs\n    lfs_tag_t tag;\n    const void *buffer;\n    struct lfs_diskoff disk = {0};\n    while (true) {\n        {\n            if (off+lfs_tag_dsize(ptag) < dir->off) {\n                off += lfs_tag_dsize(ptag);\n                int err = lfs_bd_read(lfs,\n                        NULL, &lfs->rcache, sizeof(tag),\n                        dir->pair[0], off, &tag, sizeof(tag));\n                if (err) {\n                    return err;\n                }\n\n                tag = (lfs_frombe32(tag) ^ ptag) | 0x80000000;\n                disk.block = dir->pair[0];\n                disk.off = off+sizeof(lfs_tag_t);\n                buffer = &disk;\n                ptag = tag;\n            } else if (attrcount > 0) {\n                tag = attrs[0].tag;\n                buffer = attrs[0].buffer;\n                attrs += 1;\n                attrcount -= 1;\n            } else {\n                // finished traversal, pop from stack?\n                res = 0;\n                break;\n            }\n\n            // do we need to filter?\n            lfs_tag_t mask = LFS_MKTAG(0x7ff, 0, 0);\n            if ((mask & tmask & tag) != (mask & tmask & ttag)) {\n                continue;\n            }\n\n            if (lfs_tag_id(tmask) != 0) {\n                LFS_ASSERT(sp < LFS_DIR_TRAVERSE_DEPTH);\n                // recurse, scan for duplicates, and update tag based on\n                // creates/deletes\n                stack[sp] = (struct lfs_dir_traverse){\n                    .dir        = dir,\n                    .off        = off,\n                    .ptag       = ptag,\n                    .attrs      = attrs,\n                    .attrcount  = attrcount,\n                    .tmask      = tmask,\n                    .ttag       = ttag,\n                    .begin      = begin,\n                    .end        = end,\n                    .diff       = diff,\n                    .cb         = cb,\n                    .data       = data,\n                    .tag        = tag,\n                    .buffer     = buffer,\n                    .disk       = disk,\n                };\n                sp += 1;\n\n                tmask = 0;\n                ttag = 0;\n                begin = 0;\n                end = 0;\n                diff = 0;\n                cb = lfs_dir_traverse_filter;\n                data = &stack[sp-1].tag;\n                continue;\n            }\n        }\n\npopped:\n        // in filter range?\n        if (lfs_tag_id(tmask) != 0 &&\n                !(lfs_tag_id(tag) >= begin && lfs_tag_id(tag) < end)) {\n            continue;\n        }\n\n        // handle special cases for mcu-side operations\n        if (lfs_tag_type3(tag) == LFS_FROM_NOOP) {\n            // do nothing\n        } else if (lfs_tag_type3(tag) == LFS_FROM_MOVE) {\n            // Without this condition, lfs_dir_traverse can exhibit an\n            // extremely expensive O(n^3) of nested loops when renaming.\n            // This happens because lfs_dir_traverse tries to filter tags by\n            // the tags in the source directory, triggering a second\n            // lfs_dir_traverse with its own filter operation.\n            //\n            // traverse with commit\n            // '-> traverse with filter\n            //     '-> traverse with move\n            //         '-> traverse with filter\n            //\n            // However we don't actually care about filtering the second set of\n            // tags, since duplicate tags have no effect when filtering.\n            //\n            // This check skips this unnecessary recursive filtering explicitly,\n            // reducing this runtime from O(n^3) to O(n^2).\n            if (cb == lfs_dir_traverse_filter) {\n                continue;\n            }\n\n            // recurse into move\n            stack[sp] = (struct lfs_dir_traverse){\n                .dir        = dir,\n                .off        = off,\n                .ptag       = ptag,\n                .attrs      = attrs,\n                .attrcount  = attrcount,\n                .tmask      = tmask,\n                .ttag       = ttag,\n                .begin      = begin,\n                .end        = end,\n                .diff       = diff,\n                .cb         = cb,\n                .data       = data,\n                .tag        = LFS_MKTAG(LFS_FROM_NOOP, 0, 0),\n            };\n            sp += 1;\n\n            uint16_t fromid = lfs_tag_size(tag);\n            uint16_t toid = lfs_tag_id(tag);\n            dir = buffer;\n            off = 0;\n            ptag = 0xffffffff;\n            attrs = NULL;\n            attrcount = 0;\n            tmask = LFS_MKTAG(0x600, 0x3ff, 0);\n            ttag = LFS_MKTAG(LFS_TYPE_STRUCT, 0, 0);\n            begin = fromid;\n            end = fromid+1;\n            diff = toid-fromid+diff;\n        } else if (lfs_tag_type3(tag) == LFS_FROM_USERATTRS) {\n            for (unsigned i = 0; i < lfs_tag_size(tag); i++) {\n                const struct lfs_attr *a = buffer;\n                res = cb(data, LFS_MKTAG(LFS_TYPE_USERATTR + a[i].type,\n                        lfs_tag_id(tag) + diff, a[i].size), a[i].buffer);\n                if (res < 0) {\n                    return res;\n                }\n\n                if (res) {\n                    break;\n                }\n            }\n        } else {\n            res = cb(data, tag + LFS_MKTAG(0, diff, 0), buffer);\n            if (res < 0) {\n                return res;\n            }\n\n            if (res) {\n                break;\n            }\n        }\n    }\n\n    if (sp > 0) {\n        // pop from the stack and return, fortunately all pops share\n        // a destination\n        dir         = stack[sp-1].dir;\n        off         = stack[sp-1].off;\n        ptag        = stack[sp-1].ptag;\n        attrs       = stack[sp-1].attrs;\n        attrcount   = stack[sp-1].attrcount;\n        tmask       = stack[sp-1].tmask;\n        ttag        = stack[sp-1].ttag;\n        begin       = stack[sp-1].begin;\n        end         = stack[sp-1].end;\n        diff        = stack[sp-1].diff;\n        cb          = stack[sp-1].cb;\n        data        = stack[sp-1].data;\n        tag         = stack[sp-1].tag;\n        buffer      = stack[sp-1].buffer;\n        disk        = stack[sp-1].disk;\n        sp -= 1;\n        goto popped;\n    } else {\n        return res;\n    }\n}\n#endif\n\nstatic lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,\n        lfs_mdir_t *dir, const lfs_block_t pair[2],\n        lfs_tag_t fmask, lfs_tag_t ftag, uint16_t *id,\n        int (*cb)(void *data, lfs_tag_t tag, const void *buffer), void *data) {\n    // we can find tag very efficiently during a fetch, since we're already\n    // scanning the entire directory\n    lfs_stag_t besttag = -1;\n\n    // if either block address is invalid we return LFS_ERR_CORRUPT here,\n    // otherwise later writes to the pair could fail\n    if (lfs->block_count \n            && (pair[0] >= lfs->block_count || pair[1] >= lfs->block_count)) {\n        return LFS_ERR_CORRUPT;\n    }\n\n    // find the block with the most recent revision\n    uint32_t revs[2] = {0, 0};\n    int r = 0;\n    for (int i = 0; i < 2; i++) {\n        int err = lfs_bd_read(lfs,\n                NULL, &lfs->rcache, sizeof(revs[i]),\n                pair[i], 0, &revs[i], sizeof(revs[i]));\n        revs[i] = lfs_fromle32(revs[i]);\n        if (err && err != LFS_ERR_CORRUPT) {\n            return err;\n        }\n\n        if (err != LFS_ERR_CORRUPT &&\n                lfs_scmp(revs[i], revs[(i+1)%2]) > 0) {\n            r = i;\n        }\n    }\n\n    dir->pair[0] = pair[(r+0)%2];\n    dir->pair[1] = pair[(r+1)%2];\n    dir->rev = revs[(r+0)%2];\n    dir->off = 0; // nonzero = found some commits\n\n    // now scan tags to fetch the actual dir and find possible match\n    for (int i = 0; i < 2; i++) {\n        lfs_off_t off = 0;\n        lfs_tag_t ptag = 0xffffffff;\n\n        uint16_t tempcount = 0;\n        lfs_block_t temptail[2] = {LFS_BLOCK_NULL, LFS_BLOCK_NULL};\n        bool tempsplit = false;\n        lfs_stag_t tempbesttag = besttag;\n\n        // assume not erased until proven otherwise\n        bool maybeerased = false;\n        bool hasfcrc = false;\n        struct lfs_fcrc fcrc;\n\n        dir->rev = lfs_tole32(dir->rev);\n        uint32_t crc = lfs_crc(0xffffffff, &dir->rev, sizeof(dir->rev));\n        dir->rev = lfs_fromle32(dir->rev);\n\n        while (true) {\n            // extract next tag\n            lfs_tag_t tag;\n            off += lfs_tag_dsize(ptag);\n            int err = lfs_bd_read(lfs,\n                    NULL, &lfs->rcache, lfs->cfg->block_size,\n                    dir->pair[0], off, &tag, sizeof(tag));\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    // can't continue?\n                    break;\n                }\n                return err;\n            }\n\n            crc = lfs_crc(crc, &tag, sizeof(tag));\n            tag = lfs_frombe32(tag) ^ ptag;\n\n            // next commit not yet programmed?\n            if (!lfs_tag_isvalid(tag)) {\n                // we only might be erased if the last tag was a crc\n                maybeerased = (lfs_tag_type2(ptag) == LFS_TYPE_CCRC);\n                break;\n            // out of range?\n            } else if (off + lfs_tag_dsize(tag) > lfs->cfg->block_size) {\n                break;\n            }\n\n            ptag = tag;\n\n            if (lfs_tag_type2(tag) == LFS_TYPE_CCRC) {\n                // check the crc attr\n                uint32_t dcrc;\n                err = lfs_bd_read(lfs,\n                        NULL, &lfs->rcache, lfs->cfg->block_size,\n                        dir->pair[0], off+sizeof(tag), &dcrc, sizeof(dcrc));\n                if (err) {\n                    if (err == LFS_ERR_CORRUPT) {\n                        break;\n                    }\n                    return err;\n                }\n                dcrc = lfs_fromle32(dcrc);\n\n                if (crc != dcrc) {\n                    break;\n                }\n\n                // reset the next bit if we need to\n                ptag ^= (lfs_tag_t)(lfs_tag_chunk(tag) & 1U) << 31;\n\n                // toss our crc into the filesystem seed for\n                // pseudorandom numbers, note we use another crc here\n                // as a collection function because it is sufficiently\n                // random and convenient\n                lfs->seed = lfs_crc(lfs->seed, &crc, sizeof(crc));\n\n                // update with what's found so far\n                besttag = tempbesttag;\n                dir->off = off + lfs_tag_dsize(tag);\n                dir->etag = ptag;\n                dir->count = tempcount;\n                dir->tail[0] = temptail[0];\n                dir->tail[1] = temptail[1];\n                dir->split = tempsplit;\n\n                // reset crc, hasfcrc\n                crc = 0xffffffff;\n                continue;\n            }\n\n            // crc the entry first, hopefully leaving it in the cache\n            err = lfs_bd_crc(lfs,\n                    NULL, &lfs->rcache, lfs->cfg->block_size,\n                    dir->pair[0], off+sizeof(tag),\n                    lfs_tag_dsize(tag)-sizeof(tag), &crc);\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    break;\n                }\n                return err;\n            }\n\n            // directory modification tags?\n            if (lfs_tag_type1(tag) == LFS_TYPE_NAME) {\n                // increase count of files if necessary\n                if (lfs_tag_id(tag) >= tempcount) {\n                    tempcount = lfs_tag_id(tag) + 1;\n                }\n            } else if (lfs_tag_type1(tag) == LFS_TYPE_SPLICE) {\n                tempcount += lfs_tag_splice(tag);\n\n                if (tag == (LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) |\n                        (LFS_MKTAG(0, 0x3ff, 0) & tempbesttag))) {\n                    tempbesttag |= 0x80000000;\n                } else if (tempbesttag != -1 &&\n                        lfs_tag_id(tag) <= lfs_tag_id(tempbesttag)) {\n                    tempbesttag += LFS_MKTAG(0, lfs_tag_splice(tag), 0);\n                }\n            } else if (lfs_tag_type1(tag) == LFS_TYPE_TAIL) {\n                tempsplit = (lfs_tag_chunk(tag) & 1);\n\n                err = lfs_bd_read(lfs,\n                        NULL, &lfs->rcache, lfs->cfg->block_size,\n                        dir->pair[0], off+sizeof(tag), &temptail, 8);\n                if (err) {\n                    if (err == LFS_ERR_CORRUPT) {\n                        break;\n                    }\n                    return err;\n                }\n                lfs_pair_fromle32(temptail);\n            } else if (lfs_tag_type3(tag) == LFS_TYPE_FCRC) {\n                err = lfs_bd_read(lfs,\n                        NULL, &lfs->rcache, lfs->cfg->block_size,\n                        dir->pair[0], off+sizeof(tag),\n                        &fcrc, sizeof(fcrc));\n                if (err) {\n                    if (err == LFS_ERR_CORRUPT) {\n                        break;\n                    }\n                }\n\n                lfs_fcrc_fromle32(&fcrc);\n                hasfcrc = true;\n            }\n\n            // found a match for our fetcher?\n            if ((fmask & tag) == (fmask & ftag)) {\n                int res = cb(data, tag, &(struct lfs_diskoff){\n                        dir->pair[0], off+sizeof(tag)});\n                if (res < 0) {\n                    if (res == LFS_ERR_CORRUPT) {\n                        break;\n                    }\n                    return res;\n                }\n\n                if (res == LFS_CMP_EQ) {\n                    // found a match\n                    tempbesttag = tag;\n                } else if ((LFS_MKTAG(0x7ff, 0x3ff, 0) & tag) ==\n                        (LFS_MKTAG(0x7ff, 0x3ff, 0) & tempbesttag)) {\n                    // found an identical tag, but contents didn't match\n                    // this must mean that our besttag has been overwritten\n                    tempbesttag = -1;\n                } else if (res == LFS_CMP_GT &&\n                        lfs_tag_id(tag) <= lfs_tag_id(tempbesttag)) {\n                    // found a greater match, keep track to keep things sorted\n                    tempbesttag = tag | 0x80000000;\n                }\n            }\n        }\n\n        // found no valid commits?\n        if (dir->off == 0) {\n            // try the other block?\n            lfs_pair_swap(dir->pair);\n            dir->rev = revs[(r+1)%2];\n            continue;\n        }\n\n        // did we end on a valid commit? we may have an erased block\n        dir->erased = false;\n        if (maybeerased && dir->off % lfs->cfg->prog_size == 0) {\n        #ifdef LFS_MULTIVERSION\n            // note versions < lfs2.1 did not have fcrc tags, if\n            // we're < lfs2.1 treat missing fcrc as erased data\n            //\n            // we don't strictly need to do this, but otherwise writing\n            // to lfs2.0 disks becomes very inefficient\n            if (lfs_fs_disk_version(lfs) < 0x00020001) {\n                dir->erased = true;\n\n            } else\n        #endif\n            if (hasfcrc) {\n                // check for an fcrc matching the next prog's erased state, if\n                // this failed most likely a previous prog was interrupted, we\n                // need a new erase\n                uint32_t fcrc_ = 0xffffffff;\n                int err = lfs_bd_crc(lfs,\n                        NULL, &lfs->rcache, lfs->cfg->block_size,\n                        dir->pair[0], dir->off, fcrc.size, &fcrc_);\n                if (err && err != LFS_ERR_CORRUPT) {\n                    return err;\n                }\n\n                // found beginning of erased part?\n                dir->erased = (fcrc_ == fcrc.crc);\n            }\n        }\n\n        // synthetic move\n        if (lfs_gstate_hasmovehere(&lfs->gdisk, dir->pair)) {\n            if (lfs_tag_id(lfs->gdisk.tag) == lfs_tag_id(besttag)) {\n                besttag |= 0x80000000;\n            } else if (besttag != -1 &&\n                    lfs_tag_id(lfs->gdisk.tag) < lfs_tag_id(besttag)) {\n                besttag -= LFS_MKTAG(0, 1, 0);\n            }\n        }\n\n        // found tag? or found best id?\n        if (id) {\n            *id = lfs_min(lfs_tag_id(besttag), dir->count);\n        }\n\n        if (lfs_tag_isvalid(besttag)) {\n            return besttag;\n        } else if (lfs_tag_id(besttag) < dir->count) {\n            return LFS_ERR_NOENT;\n        } else {\n            return 0;\n        }\n    }\n\n    LFS_ERROR(\"Corrupted dir pair at {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n            dir->pair[0], dir->pair[1]);\n    return LFS_ERR_CORRUPT;\n}\n\nstatic int lfs_dir_fetch(lfs_t *lfs,\n        lfs_mdir_t *dir, const lfs_block_t pair[2]) {\n    // note, mask=-1, tag=-1 can never match a tag since this\n    // pattern has the invalid bit set\n    return (int)lfs_dir_fetchmatch(lfs, dir, pair,\n            (lfs_tag_t)-1, (lfs_tag_t)-1, NULL, NULL, NULL);\n}\n\nstatic int lfs_dir_getgstate(lfs_t *lfs, const lfs_mdir_t *dir,\n        lfs_gstate_t *gstate) {\n    lfs_gstate_t temp;\n    lfs_stag_t res = lfs_dir_get(lfs, dir, LFS_MKTAG(0x7ff, 0, 0),\n            LFS_MKTAG(LFS_TYPE_MOVESTATE, 0, sizeof(temp)), &temp);\n    if (res < 0 && res != LFS_ERR_NOENT) {\n        return res;\n    }\n\n    if (res != LFS_ERR_NOENT) {\n        // xor together to find resulting gstate\n        lfs_gstate_fromle32(&temp);\n        lfs_gstate_xor(gstate, &temp);\n    }\n\n    return 0;\n}\n\nstatic int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir,\n        uint16_t id, struct lfs_info *info) {\n    if (id == 0x3ff) {\n        // special case for root\n        strcpy(info->name, \"/\");\n        info->type = LFS_TYPE_DIR;\n        return 0;\n    }\n\n    lfs_stag_t tag = lfs_dir_get(lfs, dir, LFS_MKTAG(0x780, 0x3ff, 0),\n            LFS_MKTAG(LFS_TYPE_NAME, id, lfs->name_max+1), info->name);\n    if (tag < 0) {\n        return (int)tag;\n    }\n\n    info->type = lfs_tag_type3(tag);\n\n    struct lfs_ctz ctz;\n    tag = lfs_dir_get(lfs, dir, LFS_MKTAG(0x700, 0x3ff, 0),\n            LFS_MKTAG(LFS_TYPE_STRUCT, id, sizeof(ctz)), &ctz);\n    if (tag < 0) {\n        return (int)tag;\n    }\n    lfs_ctz_fromle32(&ctz);\n\n    if (lfs_tag_type3(tag) == LFS_TYPE_CTZSTRUCT) {\n        info->size = ctz.size;\n    } else if (lfs_tag_type3(tag) == LFS_TYPE_INLINESTRUCT) {\n        info->size = lfs_tag_size(tag);\n    }\n\n    return 0;\n}\n\nstruct lfs_dir_find_match {\n    lfs_t *lfs;\n    const void *name;\n    lfs_size_t size;\n};\n\nstatic int lfs_dir_find_match(void *data,\n        lfs_tag_t tag, const void *buffer) {\n    struct lfs_dir_find_match *name = data;\n    lfs_t *lfs = name->lfs;\n    const struct lfs_diskoff *disk = buffer;\n\n    // compare with disk\n    lfs_size_t diff = lfs_min(name->size, lfs_tag_size(tag));\n    int res = lfs_bd_cmp(lfs,\n            NULL, &lfs->rcache, diff,\n            disk->block, disk->off, name->name, diff);\n    if (res != LFS_CMP_EQ) {\n        return res;\n    }\n\n    // only equal if our size is still the same\n    if (name->size != lfs_tag_size(tag)) {\n        return (name->size < lfs_tag_size(tag)) ? LFS_CMP_LT : LFS_CMP_GT;\n    }\n\n    // found a match!\n    return LFS_CMP_EQ;\n}\n\n// lfs_dir_find tries to set path and id even if file is not found\n//\n// returns:\n// - 0                  if file is found\n// - LFS_ERR_NOENT      if file or parent is not found\n// - LFS_ERR_NOTDIR     if parent is not a dir\nstatic lfs_stag_t lfs_dir_find(lfs_t *lfs, lfs_mdir_t *dir,\n        const char **path, uint16_t *id) {\n    // we reduce path to a single name if we can find it\n    const char *name = *path;\n\n    // default to root dir\n    lfs_stag_t tag = LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0);\n    dir->tail[0] = lfs->root[0];\n    dir->tail[1] = lfs->root[1];\n\n    // empty paths are not allowed\n    if (*name == '\\0') {\n        return LFS_ERR_INVAL;\n    }\n\n    while (true) {\nnextname:\n        // skip slashes if we're a directory\n        if (lfs_tag_type3(tag) == LFS_TYPE_DIR) {\n            name += strspn(name, \"/\");\n        }\n        lfs_size_t namelen = strcspn(name, \"/\");\n\n        // skip '.'\n        if (namelen == 1 && memcmp(name, \".\", 1) == 0) {\n            name += namelen;\n            goto nextname;\n        }\n\n        // error on unmatched '..', trying to go above root?\n        if (namelen == 2 && memcmp(name, \"..\", 2) == 0) {\n            return LFS_ERR_INVAL;\n        }\n\n        // skip if matched by '..' in name\n        const char *suffix = name + namelen;\n        lfs_size_t sufflen;\n        int depth = 1;\n        while (true) {\n            suffix += strspn(suffix, \"/\");\n            sufflen = strcspn(suffix, \"/\");\n            if (sufflen == 0) {\n                break;\n            }\n\n            if (sufflen == 1 && memcmp(suffix, \".\", 1) == 0) {\n                // noop\n            } else if (sufflen == 2 && memcmp(suffix, \"..\", 2) == 0) {\n                depth -= 1;\n                if (depth == 0) {\n                    name = suffix + sufflen;\n                    goto nextname;\n                }\n            } else {\n                depth += 1;\n            }\n\n            suffix += sufflen;\n        }\n\n        // found path\n        if (*name == '\\0') {\n            return tag;\n        }\n\n        // update what we've found so far\n        *path = name;\n\n        // only continue if we're a directory\n        if (lfs_tag_type3(tag) != LFS_TYPE_DIR) {\n            return LFS_ERR_NOTDIR;\n        }\n\n        // grab the entry data\n        if (lfs_tag_id(tag) != 0x3ff) {\n            lfs_stag_t res = lfs_dir_get(lfs, dir, LFS_MKTAG(0x700, 0x3ff, 0),\n                    LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), dir->tail);\n            if (res < 0) {\n                return res;\n            }\n            lfs_pair_fromle32(dir->tail);\n        }\n\n        // find entry matching name\n        while (true) {\n            tag = lfs_dir_fetchmatch(lfs, dir, dir->tail,\n                    LFS_MKTAG(0x780, 0, 0),\n                    LFS_MKTAG(LFS_TYPE_NAME, 0, namelen),\n                    id,\n                    lfs_dir_find_match, &(struct lfs_dir_find_match){\n                        lfs, name, namelen});\n            if (tag < 0) {\n                return tag;\n            }\n\n            if (tag) {\n                break;\n            }\n\n            if (!dir->split) {\n                return LFS_ERR_NOENT;\n            }\n        }\n\n        // to next name\n        name += namelen;\n    }\n}\n\n// commit logic\nstruct lfs_commit {\n    lfs_block_t block;\n    lfs_off_t off;\n    lfs_tag_t ptag;\n    uint32_t crc;\n\n    lfs_off_t begin;\n    lfs_off_t end;\n};\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_commitprog(lfs_t *lfs, struct lfs_commit *commit,\n        const void *buffer, lfs_size_t size) {\n    int err = lfs_bd_prog(lfs,\n            &lfs->pcache, &lfs->rcache, false,\n            commit->block, commit->off ,\n            (const uint8_t*)buffer, size);\n    if (err) {\n        return err;\n    }\n\n    commit->crc = lfs_crc(commit->crc, buffer, size);\n    commit->off += size;\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit,\n        lfs_tag_t tag, const void *buffer) {\n    // check if we fit\n    lfs_size_t dsize = lfs_tag_dsize(tag);\n    if (commit->off + dsize > commit->end) {\n        return LFS_ERR_NOSPC;\n    }\n\n    // write out tag\n    lfs_tag_t ntag = lfs_tobe32((tag & 0x7fffffff) ^ commit->ptag);\n    int err = lfs_dir_commitprog(lfs, commit, &ntag, sizeof(ntag));\n    if (err) {\n        return err;\n    }\n\n    if (!(tag & 0x80000000)) {\n        // from memory\n        err = lfs_dir_commitprog(lfs, commit, buffer, dsize-sizeof(tag));\n        if (err) {\n            return err;\n        }\n    } else {\n        // from disk\n        const struct lfs_diskoff *disk = buffer;\n        for (lfs_off_t i = 0; i < dsize-sizeof(tag); i++) {\n            // rely on caching to make this efficient\n            uint8_t dat;\n            err = lfs_bd_read(lfs,\n                    NULL, &lfs->rcache, dsize-sizeof(tag)-i,\n                    disk->block, disk->off+i, &dat, 1);\n            if (err) {\n                return err;\n            }\n\n            err = lfs_dir_commitprog(lfs, commit, &dat, 1);\n            if (err) {\n                return err;\n            }\n        }\n    }\n\n    commit->ptag = tag & 0x7fffffff;\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\n\nstatic int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {\n    // align to program units\n    //\n    // this gets a bit complex as we have two types of crcs:\n    // - 5-word crc with fcrc to check following prog (middle of block)\n    // - 2-word crc with no following prog (end of block)\n    const lfs_off_t end = lfs_alignup(\n            lfs_min(commit->off + 5*sizeof(uint32_t), lfs->cfg->block_size),\n            lfs->cfg->prog_size);\n\n    lfs_off_t off1 = 0;\n    uint32_t crc1 = 0;\n\n    // create crc tags to fill up remainder of commit, note that\n    // padding is not crced, which lets fetches skip padding but\n    // makes committing a bit more complicated\n    while (commit->off < end) {\n        lfs_off_t noff = (\n                lfs_min(end - (commit->off+sizeof(lfs_tag_t)), 0x3fe)\n                + (commit->off+sizeof(lfs_tag_t)));\n        // too large for crc tag? need padding commits\n        if (noff < end) {\n            noff = lfs_min(noff, end - 5*sizeof(uint32_t));\n        }\n\n        // space for fcrc?\n        uint8_t eperturb = (uint8_t)-1;\n        if (noff >= end && noff <= lfs->cfg->block_size - lfs->cfg->prog_size) {\n            // first read the leading byte, this always contains a bit\n            // we can perturb to avoid writes that don't change the fcrc\n            int err = lfs_bd_read(lfs,\n                    NULL, &lfs->rcache, lfs->cfg->prog_size,\n                    commit->block, noff, &eperturb, 1);\n            if (err && err != LFS_ERR_CORRUPT) {\n                return err;\n            }\n\n        #ifdef LFS_MULTIVERSION\n            // unfortunately fcrcs break mdir fetching < lfs2.1, so only write\n            // these if we're a >= lfs2.1 filesystem\n            if (lfs_fs_disk_version(lfs) <= 0x00020000) {\n                // don't write fcrc\n            } else\n        #endif\n            {\n                // find the expected fcrc, don't bother avoiding a reread\n                // of the eperturb, it should still be in our cache\n                struct lfs_fcrc fcrc = {\n                    .size = lfs->cfg->prog_size,\n                    .crc = 0xffffffff\n                };\n                err = lfs_bd_crc(lfs,\n                        NULL, &lfs->rcache, lfs->cfg->prog_size,\n                        commit->block, noff, fcrc.size, &fcrc.crc);\n                if (err && err != LFS_ERR_CORRUPT) {\n                    return err;\n                }\n\n                lfs_fcrc_tole32(&fcrc);\n                err = lfs_dir_commitattr(lfs, commit,\n                        LFS_MKTAG(LFS_TYPE_FCRC, 0x3ff, sizeof(struct lfs_fcrc)),\n                        &fcrc);\n                if (err) {\n                    return err;\n                }\n            }\n        }\n\n        // build commit crc\n        struct {\n            lfs_tag_t tag;\n            uint32_t crc;\n        } ccrc;\n        lfs_tag_t ntag = LFS_MKTAG(\n                LFS_TYPE_CCRC + (((uint8_t)~eperturb) >> 7), 0x3ff,\n                noff - (commit->off+sizeof(lfs_tag_t)));\n        ccrc.tag = lfs_tobe32(ntag ^ commit->ptag);\n        commit->crc = lfs_crc(commit->crc, &ccrc.tag, sizeof(lfs_tag_t));\n        ccrc.crc = lfs_tole32(commit->crc);\n\n        int err = lfs_bd_prog(lfs,\n                &lfs->pcache, &lfs->rcache, false,\n                commit->block, commit->off, &ccrc, sizeof(ccrc));\n        if (err) {\n            return err;\n        }\n\n        // keep track of non-padding checksum to verify\n        if (off1 == 0) {\n            off1 = commit->off + sizeof(lfs_tag_t);\n            crc1 = commit->crc;\n        }\n\n        commit->off = noff;\n        // perturb valid bit?\n        commit->ptag = ntag ^ ((0x80UL & ~eperturb) << 24);\n        // reset crc for next commit\n        commit->crc = 0xffffffff;\n\n        // manually flush here since we don't prog the padding, this confuses\n        // the caching layer\n        if (noff >= end || noff >= lfs->pcache.off + lfs->cfg->cache_size) {\n            // flush buffers\n            int err = lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false);\n            if (err) {\n                return err;\n            }\n        }\n    }\n\n    // successful commit, check checksums to make sure\n    //\n    // note that we don't need to check padding commits, worst\n    // case if they are corrupted we would have had to compact anyways\n    lfs_off_t off = commit->begin;\n    uint32_t crc = 0xffffffff;\n    int err = lfs_bd_crc(lfs,\n            NULL, &lfs->rcache, off1+sizeof(uint32_t),\n            commit->block, off, off1-off, &crc);\n    if (err) {\n        return err;\n    }\n\n    // check non-padding commits against known crc\n    if (crc != crc1) {\n        return LFS_ERR_CORRUPT;\n    }\n\n    // make sure to check crc in case we happen to pick\n    // up an unrelated crc (frozen block?)\n    err = lfs_bd_crc(lfs,\n            NULL, &lfs->rcache, sizeof(uint32_t),\n            commit->block, off1, sizeof(uint32_t), &crc);\n    if (err) {\n        return err;\n    }\n\n    if (crc != 0) {\n        return LFS_ERR_CORRUPT;\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {\n    // allocate pair of dir blocks (backwards, so we write block 1 first)\n    for (int i = 0; i < 2; i++) {\n        int err = lfs_alloc(lfs, &dir->pair[(i+1)%2]);\n        if (err) {\n            return err;\n        }\n    }\n\n    // zero for reproducibility in case initial block is unreadable\n    dir->rev = 0;\n\n    // rather than clobbering one of the blocks we just pretend\n    // the revision may be valid\n    int err = lfs_bd_read(lfs,\n            NULL, &lfs->rcache, sizeof(dir->rev),\n            dir->pair[0], 0, &dir->rev, sizeof(dir->rev));\n    dir->rev = lfs_fromle32(dir->rev);\n    if (err && err != LFS_ERR_CORRUPT) {\n        return err;\n    }\n\n    // to make sure we don't immediately evict, align the new revision count\n    // to our block_cycles modulus, see lfs_dir_compact for why our modulus\n    // is tweaked this way\n    if (lfs->cfg->block_cycles > 0) {\n        dir->rev = lfs_alignup(dir->rev, ((lfs->cfg->block_cycles+1)|1));\n    }\n\n    // set defaults\n    dir->off = sizeof(dir->rev);\n    dir->etag = 0xffffffff;\n    dir->count = 0;\n    dir->tail[0] = LFS_BLOCK_NULL;\n    dir->tail[1] = LFS_BLOCK_NULL;\n    dir->erased = false;\n    dir->split = false;\n\n    // don't write out yet, let caller take care of that\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, lfs_mdir_t *tail) {\n    // steal state\n    int err = lfs_dir_getgstate(lfs, tail, &lfs->gdelta);\n    if (err) {\n        return err;\n    }\n\n    // steal tail\n    lfs_pair_tole32(tail->tail);\n    err = lfs_dir_commit(lfs, dir, LFS_MKATTRS(\n            {LFS_MKTAG(LFS_TYPE_TAIL + tail->split, 0x3ff, 8), tail->tail}));\n    lfs_pair_fromle32(tail->tail);\n    if (err) {\n        return err;\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_split(lfs_t *lfs,\n        lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,\n        lfs_mdir_t *source, uint16_t split, uint16_t end) {\n    // create tail metadata pair\n    lfs_mdir_t tail;\n    int err = lfs_dir_alloc(lfs, &tail);\n    if (err) {\n        return err;\n    }\n\n    tail.split = dir->split;\n    tail.tail[0] = dir->tail[0];\n    tail.tail[1] = dir->tail[1];\n\n    // note we don't care about LFS_OK_RELOCATED\n    int res = lfs_dir_compact(lfs, &tail, attrs, attrcount, source, split, end);\n    if (res < 0) {\n        return res;\n    }\n\n    dir->tail[0] = tail.pair[0];\n    dir->tail[1] = tail.pair[1];\n    dir->split = true;\n\n    // update root if needed\n    if (lfs_pair_cmp(dir->pair, lfs->root) == 0 && split == 0) {\n        lfs->root[0] = tail.pair[0];\n        lfs->root[1] = tail.pair[1];\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_commit_size(void *p, lfs_tag_t tag, const void *buffer) {\n    lfs_size_t *size = p;\n    (void)buffer;\n\n    *size += lfs_tag_dsize(tag);\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstruct lfs_dir_commit_commit {\n    lfs_t *lfs;\n    struct lfs_commit *commit;\n};\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_commit_commit(void *p, lfs_tag_t tag, const void *buffer) {\n    struct lfs_dir_commit_commit *commit = p;\n    return lfs_dir_commitattr(commit->lfs, commit->commit, tag, buffer);\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic bool lfs_dir_needsrelocation(lfs_t *lfs, lfs_mdir_t *dir) {\n    // If our revision count == n * block_cycles, we should force a relocation,\n    // this is how littlefs wear-levels at the metadata-pair level. Note that we\n    // actually use (block_cycles+1)|1, this is to avoid two corner cases:\n    // 1. block_cycles = 1, which would prevent relocations from terminating\n    // 2. block_cycles = 2n, which, due to aliasing, would only ever relocate\n    //    one metadata block in the pair, effectively making this useless\n    return (lfs->cfg->block_cycles > 0\n            && ((dir->rev + 1) % ((lfs->cfg->block_cycles+1)|1) == 0));\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_compact(lfs_t *lfs,\n        lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,\n        lfs_mdir_t *source, uint16_t begin, uint16_t end) {\n    // save some state in case block is bad\n    bool relocated = false;\n    bool tired = lfs_dir_needsrelocation(lfs, dir);\n\n    // increment revision count\n    dir->rev += 1;\n\n    // do not proactively relocate blocks during migrations, this\n    // can cause a number of failure states such: clobbering the\n    // v1 superblock if we relocate root, and invalidating directory\n    // pointers if we relocate the head of a directory. On top of\n    // this, relocations increase the overall complexity of\n    // lfs_migration, which is already a delicate operation.\n#ifdef LFS_MIGRATE\n    if (lfs->lfs1) {\n        tired = false;\n    }\n#endif\n\n    if (tired && lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) != 0) {\n        // we're writing too much, time to relocate\n        goto relocate;\n    }\n\n    // begin loop to commit compaction to blocks until a compact sticks\n    while (true) {\n        {\n            // setup commit state\n            struct lfs_commit commit = {\n                .block = dir->pair[1],\n                .off = 0,\n                .ptag = 0xffffffff,\n                .crc = 0xffffffff,\n\n                .begin = 0,\n                .end = (lfs->cfg->metadata_max ?\n                    lfs->cfg->metadata_max : lfs->cfg->block_size) - 8,\n            };\n\n            // erase block to write to\n            int err = lfs_bd_erase(lfs, dir->pair[1]);\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    goto relocate;\n                }\n                return err;\n            }\n\n            // write out header\n            dir->rev = lfs_tole32(dir->rev);\n            err = lfs_dir_commitprog(lfs, &commit,\n                    &dir->rev, sizeof(dir->rev));\n            dir->rev = lfs_fromle32(dir->rev);\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    goto relocate;\n                }\n                return err;\n            }\n\n            // traverse the directory, this time writing out all unique tags\n            err = lfs_dir_traverse(lfs,\n                    source, 0, 0xffffffff, attrs, attrcount,\n                    LFS_MKTAG(0x400, 0x3ff, 0),\n                    LFS_MKTAG(LFS_TYPE_NAME, 0, 0),\n                    begin, end, -begin,\n                    lfs_dir_commit_commit, &(struct lfs_dir_commit_commit){\n                        lfs, &commit});\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    goto relocate;\n                }\n                return err;\n            }\n\n            // commit tail, which may be new after last size check\n            if (!lfs_pair_isnull(dir->tail)) {\n                lfs_pair_tole32(dir->tail);\n                err = lfs_dir_commitattr(lfs, &commit,\n                        LFS_MKTAG(LFS_TYPE_TAIL + dir->split, 0x3ff, 8),\n                        dir->tail);\n                lfs_pair_fromle32(dir->tail);\n                if (err) {\n                    if (err == LFS_ERR_CORRUPT) {\n                        goto relocate;\n                    }\n                    return err;\n                }\n            }\n\n            // bring over gstate?\n            lfs_gstate_t delta = {0};\n            if (!relocated) {\n                lfs_gstate_xor(&delta, &lfs->gdisk);\n                lfs_gstate_xor(&delta, &lfs->gstate);\n            }\n            lfs_gstate_xor(&delta, &lfs->gdelta);\n            delta.tag &= ~LFS_MKTAG(0, 0, 0x3ff);\n\n            err = lfs_dir_getgstate(lfs, dir, &delta);\n            if (err) {\n                return err;\n            }\n\n            if (!lfs_gstate_iszero(&delta)) {\n                lfs_gstate_tole32(&delta);\n                err = lfs_dir_commitattr(lfs, &commit,\n                        LFS_MKTAG(LFS_TYPE_MOVESTATE, 0x3ff,\n                            sizeof(delta)), &delta);\n                if (err) {\n                    if (err == LFS_ERR_CORRUPT) {\n                        goto relocate;\n                    }\n                    return err;\n                }\n            }\n\n            // complete commit with crc\n            err = lfs_dir_commitcrc(lfs, &commit);\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    goto relocate;\n                }\n                return err;\n            }\n\n            // successful compaction, swap dir pair to indicate most recent\n            LFS_ASSERT(commit.off % lfs->cfg->prog_size == 0);\n            lfs_pair_swap(dir->pair);\n            dir->count = end - begin;\n            dir->off = commit.off;\n            dir->etag = commit.ptag;\n            // update gstate\n            lfs->gdelta = (lfs_gstate_t){0};\n            if (!relocated) {\n                lfs->gdisk = lfs->gstate;\n            }\n        }\n        break;\n\nrelocate:\n        // commit was corrupted, drop caches and prepare to relocate block\n        relocated = true;\n        lfs_cache_drop(lfs, &lfs->pcache);\n        if (!tired) {\n            LFS_DEBUG(\"Bad block at 0x%\"PRIx32, dir->pair[1]);\n        }\n\n        // can't relocate superblock, filesystem is now frozen\n        if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {\n            LFS_WARN(\"Superblock 0x%\"PRIx32\" has become unwritable\",\n                    dir->pair[1]);\n            return LFS_ERR_NOSPC;\n        }\n\n        // relocate half of pair\n        int err = lfs_alloc(lfs, &dir->pair[1]);\n        if (err && (err != LFS_ERR_NOSPC || !tired)) {\n            return err;\n        }\n\n        tired = false;\n        continue;\n    }\n\n    return relocated ? LFS_OK_RELOCATED : 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,\n        const struct lfs_mattr *attrs, int attrcount,\n        lfs_mdir_t *source, uint16_t begin, uint16_t end) {\n    while (true) {\n        // find size of first split, we do this by halving the split until\n        // the metadata is guaranteed to fit\n        //\n        // Note that this isn't a true binary search, we never increase the\n        // split size. This may result in poorly distributed metadata but isn't\n        // worth the extra code size or performance hit to fix.\n        lfs_size_t split = begin;\n        while (end - split > 1) {\n            lfs_size_t size = 0;\n            int err = lfs_dir_traverse(lfs,\n                    source, 0, 0xffffffff, attrs, attrcount,\n                    LFS_MKTAG(0x400, 0x3ff, 0),\n                    LFS_MKTAG(LFS_TYPE_NAME, 0, 0),\n                    split, end, -split,\n                    lfs_dir_commit_size, &size);\n            if (err) {\n                return err;\n            }\n\n            // space is complicated, we need room for:\n            //\n            // - tail:         4+2*4 = 12 bytes\n            // - gstate:       4+3*4 = 16 bytes\n            // - move delete:  4     = 4 bytes\n            // - crc:          4+4   = 8 bytes\n            //                 total = 40 bytes\n            //\n            // And we cap at half a block to avoid degenerate cases with\n            // nearly-full metadata blocks.\n            //\n            lfs_size_t metadata_max = (lfs->cfg->metadata_max)\n                    ? lfs->cfg->metadata_max\n                    : lfs->cfg->block_size;\n            if (end - split < 0xff\n                    && size <= lfs_min(\n                        metadata_max - 40,\n                        lfs_alignup(\n                            metadata_max/2,\n                            lfs->cfg->prog_size))) {\n                break;\n            }\n\n            split = split + ((end - split) / 2);\n        }\n\n        if (split == begin) {\n            // no split needed\n            break;\n        }\n\n        // split into two metadata pairs and continue\n        int err = lfs_dir_split(lfs, dir, attrs, attrcount,\n                source, split, end);\n        if (err && err != LFS_ERR_NOSPC) {\n            return err;\n        }\n\n        if (err) {\n            // we can't allocate a new block, try to compact with degraded\n            // performance\n            LFS_WARN(\"Unable to split {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n                    dir->pair[0], dir->pair[1]);\n            break;\n        } else {\n            end = split;\n        }\n    }\n\n    if (lfs_dir_needsrelocation(lfs, dir)\n            && lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {\n        // oh no! we're writing too much to the superblock,\n        // should we expand?\n        lfs_ssize_t size = lfs_fs_size_(lfs);\n        if (size < 0) {\n            return size;\n        }\n\n        // littlefs cannot reclaim expanded superblocks, so expand cautiously\n        //\n        // if our filesystem is more than ~88% full, don't expand, this is\n        // somewhat arbitrary\n        if (lfs->block_count - size > lfs->block_count/8) {\n            LFS_DEBUG(\"Expanding superblock at rev %\"PRIu32, dir->rev);\n            int err = lfs_dir_split(lfs, dir, attrs, attrcount,\n                    source, begin, end);\n            if (err && err != LFS_ERR_NOSPC) {\n                return err;\n            }\n\n            if (err) {\n                // welp, we tried, if we ran out of space there's not much\n                // we can do, we'll error later if we've become frozen\n                LFS_WARN(\"Unable to expand superblock\");\n            } else {\n                // duplicate the superblock entry into the new superblock\n                end = 1;\n            }\n        }\n    }\n\n    return lfs_dir_compact(lfs, dir, attrs, attrcount, source, begin, end);\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_relocatingcommit(lfs_t *lfs, lfs_mdir_t *dir,\n        const lfs_block_t pair[2],\n        const struct lfs_mattr *attrs, int attrcount,\n        lfs_mdir_t *pdir) {\n    int state = 0;\n\n    // calculate changes to the directory\n    bool hasdelete = false;\n    for (int i = 0; i < attrcount; i++) {\n        if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_CREATE) {\n            dir->count += 1;\n        } else if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_DELETE) {\n            LFS_ASSERT(dir->count > 0);\n            dir->count -= 1;\n            hasdelete = true;\n        } else if (lfs_tag_type1(attrs[i].tag) == LFS_TYPE_TAIL) {\n            dir->tail[0] = ((lfs_block_t*)attrs[i].buffer)[0];\n            dir->tail[1] = ((lfs_block_t*)attrs[i].buffer)[1];\n            dir->split = (lfs_tag_chunk(attrs[i].tag) & 1);\n            lfs_pair_fromle32(dir->tail);\n        }\n    }\n\n    // should we actually drop the directory block?\n    if (hasdelete && dir->count == 0) {\n        LFS_ASSERT(pdir);\n        int err = lfs_fs_pred(lfs, dir->pair, pdir);\n        if (err && err != LFS_ERR_NOENT) {\n            return err;\n        }\n\n        if (err != LFS_ERR_NOENT && pdir->split) {\n            state = LFS_OK_DROPPED;\n            goto fixmlist;\n        }\n    }\n\n    if (dir->erased) {\n        // try to commit\n        struct lfs_commit commit = {\n            .block = dir->pair[0],\n            .off = dir->off,\n            .ptag = dir->etag,\n            .crc = 0xffffffff,\n\n            .begin = dir->off,\n            .end = (lfs->cfg->metadata_max ?\n                lfs->cfg->metadata_max : lfs->cfg->block_size) - 8,\n        };\n\n        // traverse attrs that need to be written out\n        lfs_pair_tole32(dir->tail);\n        int err = lfs_dir_traverse(lfs,\n                dir, dir->off, dir->etag, attrs, attrcount,\n                0, 0, 0, 0, 0,\n                lfs_dir_commit_commit, &(struct lfs_dir_commit_commit){\n                    lfs, &commit});\n        lfs_pair_fromle32(dir->tail);\n        if (err) {\n            if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {\n                goto compact;\n            }\n            return err;\n        }\n\n        // commit any global diffs if we have any\n        lfs_gstate_t delta = {0};\n        lfs_gstate_xor(&delta, &lfs->gstate);\n        lfs_gstate_xor(&delta, &lfs->gdisk);\n        lfs_gstate_xor(&delta, &lfs->gdelta);\n        delta.tag &= ~LFS_MKTAG(0, 0, 0x3ff);\n        if (!lfs_gstate_iszero(&delta)) {\n            err = lfs_dir_getgstate(lfs, dir, &delta);\n            if (err) {\n                return err;\n            }\n\n            lfs_gstate_tole32(&delta);\n            err = lfs_dir_commitattr(lfs, &commit,\n                    LFS_MKTAG(LFS_TYPE_MOVESTATE, 0x3ff,\n                        sizeof(delta)), &delta);\n            if (err) {\n                if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {\n                    goto compact;\n                }\n                return err;\n            }\n        }\n\n        // finalize commit with the crc\n        err = lfs_dir_commitcrc(lfs, &commit);\n        if (err) {\n            if (err == LFS_ERR_NOSPC || err == LFS_ERR_CORRUPT) {\n                goto compact;\n            }\n            return err;\n        }\n\n        // successful commit, update dir\n        LFS_ASSERT(commit.off % lfs->cfg->prog_size == 0);\n        dir->off = commit.off;\n        dir->etag = commit.ptag;\n        // and update gstate\n        lfs->gdisk = lfs->gstate;\n        lfs->gdelta = (lfs_gstate_t){0};\n\n        goto fixmlist;\n    }\n\ncompact:\n    // fall back to compaction\n    lfs_cache_drop(lfs, &lfs->pcache);\n\n    state = lfs_dir_splittingcompact(lfs, dir, attrs, attrcount,\n            dir, 0, dir->count);\n    if (state < 0) {\n        return state;\n    }\n\n    goto fixmlist;\n\nfixmlist:;\n    // this complicated bit of logic is for fixing up any active\n    // metadata-pairs that we may have affected\n    //\n    // note we have to make two passes since the mdir passed to\n    // lfs_dir_commit could also be in this list, and even then\n    // we need to copy the pair so they don't get clobbered if we refetch\n    // our mdir.\n    lfs_block_t oldpair[2] = {pair[0], pair[1]};\n    for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) {\n        if (lfs_pair_cmp(d->m.pair, oldpair) == 0) {\n            d->m = *dir;\n            if (d->m.pair != pair) {\n                for (int i = 0; i < attrcount; i++) {\n                    if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_DELETE &&\n                            d->id == lfs_tag_id(attrs[i].tag) &&\n                            d->type != LFS_TYPE_DIR) {\n                        d->m.pair[0] = LFS_BLOCK_NULL;\n                        d->m.pair[1] = LFS_BLOCK_NULL;\n                    } else if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_DELETE &&\n                            d->id > lfs_tag_id(attrs[i].tag)) {\n                        d->id -= 1;\n                        if (d->type == LFS_TYPE_DIR) {\n                            ((lfs_dir_t*)d)->pos -= 1;\n                        }\n                    } else if (lfs_tag_type3(attrs[i].tag) == LFS_TYPE_CREATE &&\n                            d->id >= lfs_tag_id(attrs[i].tag)) {\n                        d->id += 1;\n                        if (d->type == LFS_TYPE_DIR) {\n                            ((lfs_dir_t*)d)->pos += 1;\n                        }\n                    }\n                }\n            }\n\n            while (d->id >= d->m.count && d->m.split) {\n                // we split and id is on tail now\n                if (lfs_pair_cmp(d->m.tail, lfs->root) != 0) {\n                    d->id -= d->m.count;\n                }\n                int err = lfs_dir_fetch(lfs, &d->m, d->m.tail);\n                if (err) {\n                    return err;\n                }\n            }\n        }\n    }\n\n    return state;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_orphaningcommit(lfs_t *lfs, lfs_mdir_t *dir,\n        const struct lfs_mattr *attrs, int attrcount) {\n    // check for any inline files that aren't RAM backed and\n    // forcefully evict them, needed for filesystem consistency\n    for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) {\n        if (dir != &f->m && lfs_pair_cmp(f->m.pair, dir->pair) == 0 &&\n                f->type == LFS_TYPE_REG && (f->flags & LFS_F_INLINE) &&\n                f->ctz.size > lfs->cfg->cache_size) {\n            int err = lfs_file_outline(lfs, f);\n            if (err) {\n                return err;\n            }\n\n            err = lfs_file_flush(lfs, f);\n            if (err) {\n                return err;\n            }\n        }\n    }\n\n    lfs_block_t lpair[2] = {dir->pair[0], dir->pair[1]};\n    lfs_mdir_t ldir = *dir;\n    lfs_mdir_t pdir;\n    int state = lfs_dir_relocatingcommit(lfs, &ldir, dir->pair,\n            attrs, attrcount, &pdir);\n    if (state < 0) {\n        return state;\n    }\n\n    // update if we're not in mlist, note we may have already been\n    // updated if we are in mlist\n    if (lfs_pair_cmp(dir->pair, lpair) == 0) {\n        *dir = ldir;\n    }\n\n    // commit was successful, but may require other changes in the\n    // filesystem, these would normally be tail recursive, but we have\n    // flattened them here avoid unbounded stack usage\n\n    // need to drop?\n    if (state == LFS_OK_DROPPED) {\n        // steal state\n        int err = lfs_dir_getgstate(lfs, dir, &lfs->gdelta);\n        if (err) {\n            return err;\n        }\n\n        // steal tail, note that this can't create a recursive drop\n        lpair[0] = pdir.pair[0];\n        lpair[1] = pdir.pair[1];\n        lfs_pair_tole32(dir->tail);\n        state = lfs_dir_relocatingcommit(lfs, &pdir, lpair, LFS_MKATTRS(\n                    {LFS_MKTAG(LFS_TYPE_TAIL + dir->split, 0x3ff, 8),\n                        dir->tail}),\n                NULL);\n        lfs_pair_fromle32(dir->tail);\n        if (state < 0) {\n            return state;\n        }\n\n        ldir = pdir;\n    }\n\n    // need to relocate?\n    bool orphans = false;\n    while (state == LFS_OK_RELOCATED) {\n        LFS_DEBUG(\"Relocating {0x%\"PRIx32\", 0x%\"PRIx32\"} \"\n                    \"-> {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n                lpair[0], lpair[1], ldir.pair[0], ldir.pair[1]);\n        state = 0;\n\n        // update internal root\n        if (lfs_pair_cmp(lpair, lfs->root) == 0) {\n            lfs->root[0] = ldir.pair[0];\n            lfs->root[1] = ldir.pair[1];\n        }\n\n        // update internally tracked dirs\n        for (struct lfs_mlist *d = lfs->mlist; d; d = d->next) {\n            if (lfs_pair_cmp(lpair, d->m.pair) == 0) {\n                d->m.pair[0] = ldir.pair[0];\n                d->m.pair[1] = ldir.pair[1];\n            }\n\n            if (d->type == LFS_TYPE_DIR &&\n                    lfs_pair_cmp(lpair, ((lfs_dir_t*)d)->head) == 0) {\n                ((lfs_dir_t*)d)->head[0] = ldir.pair[0];\n                ((lfs_dir_t*)d)->head[1] = ldir.pair[1];\n            }\n        }\n\n        // find parent\n        lfs_stag_t tag = lfs_fs_parent(lfs, lpair, &pdir);\n        if (tag < 0 && tag != LFS_ERR_NOENT) {\n            return tag;\n        }\n\n        bool hasparent = (tag != LFS_ERR_NOENT);\n        if (tag != LFS_ERR_NOENT) {\n            // note that if we have a parent, we must have a pred, so this will\n            // always create an orphan\n            int err = lfs_fs_preporphans(lfs, +1);\n            if (err) {\n                return err;\n            }\n\n            // fix pending move in this pair? this looks like an optimization but\n            // is in fact _required_ since relocating may outdate the move.\n            uint16_t moveid = 0x3ff;\n            if (lfs_gstate_hasmovehere(&lfs->gstate, pdir.pair)) {\n                moveid = lfs_tag_id(lfs->gstate.tag);\n                LFS_DEBUG(\"Fixing move while relocating \"\n                        \"{0x%\"PRIx32\", 0x%\"PRIx32\"} 0x%\"PRIx16\"\\n\",\n                        pdir.pair[0], pdir.pair[1], moveid);\n                lfs_fs_prepmove(lfs, 0x3ff, NULL);\n                if (moveid < lfs_tag_id(tag)) {\n                    tag -= LFS_MKTAG(0, 1, 0);\n                }\n            }\n\n            lfs_block_t ppair[2] = {pdir.pair[0], pdir.pair[1]};\n            lfs_pair_tole32(ldir.pair);\n            state = lfs_dir_relocatingcommit(lfs, &pdir, ppair, LFS_MKATTRS(\n                        {LFS_MKTAG_IF(moveid != 0x3ff,\n                            LFS_TYPE_DELETE, moveid, 0), NULL},\n                        {tag, ldir.pair}),\n                    NULL);\n            lfs_pair_fromle32(ldir.pair);\n            if (state < 0) {\n                return state;\n            }\n\n            if (state == LFS_OK_RELOCATED) {\n                lpair[0] = ppair[0];\n                lpair[1] = ppair[1];\n                ldir = pdir;\n                orphans = true;\n                continue;\n            }\n        }\n\n        // find pred\n        int err = lfs_fs_pred(lfs, lpair, &pdir);\n        if (err && err != LFS_ERR_NOENT) {\n            return err;\n        }\n        LFS_ASSERT(!(hasparent && err == LFS_ERR_NOENT));\n\n        // if we can't find dir, it must be new\n        if (err != LFS_ERR_NOENT) {\n            if (lfs_gstate_hasorphans(&lfs->gstate)) {\n                // next step, clean up orphans\n                err = lfs_fs_preporphans(lfs, -(int8_t)hasparent);\n                if (err) {\n                    return err;\n                }\n            }\n\n            // fix pending move in this pair? this looks like an optimization\n            // but is in fact _required_ since relocating may outdate the move.\n            uint16_t moveid = 0x3ff;\n            if (lfs_gstate_hasmovehere(&lfs->gstate, pdir.pair)) {\n                moveid = lfs_tag_id(lfs->gstate.tag);\n                LFS_DEBUG(\"Fixing move while relocating \"\n                        \"{0x%\"PRIx32\", 0x%\"PRIx32\"} 0x%\"PRIx16\"\\n\",\n                        pdir.pair[0], pdir.pair[1], moveid);\n                lfs_fs_prepmove(lfs, 0x3ff, NULL);\n            }\n\n            // replace bad pair, either we clean up desync, or no desync occured\n            lpair[0] = pdir.pair[0];\n            lpair[1] = pdir.pair[1];\n            lfs_pair_tole32(ldir.pair);\n            state = lfs_dir_relocatingcommit(lfs, &pdir, lpair, LFS_MKATTRS(\n                        {LFS_MKTAG_IF(moveid != 0x3ff,\n                            LFS_TYPE_DELETE, moveid, 0), NULL},\n                        {LFS_MKTAG(LFS_TYPE_TAIL + pdir.split, 0x3ff, 8),\n                            ldir.pair}),\n                    NULL);\n            lfs_pair_fromle32(ldir.pair);\n            if (state < 0) {\n                return state;\n            }\n\n            ldir = pdir;\n        }\n    }\n\n    return orphans ? LFS_OK_ORPHANED : 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,\n        const struct lfs_mattr *attrs, int attrcount) {\n    int orphans = lfs_dir_orphaningcommit(lfs, dir, attrs, attrcount);\n    if (orphans < 0) {\n        return orphans;\n    }\n\n    if (orphans) {\n        // make sure we've removed all orphans, this is a noop if there\n        // are none, but if we had nested blocks failures we may have\n        // created some\n        int err = lfs_fs_deorphan(lfs, false);\n        if (err) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n#endif\n\n\n/// Top level directory operations ///\n#ifndef LFS_READONLY\nstatic int lfs_mkdir_(lfs_t *lfs, const char *path) {\n    // deorphan if we haven't yet, needed at most once after poweron\n    int err = lfs_fs_forceconsistency(lfs);\n    if (err) {\n        return err;\n    }\n\n    struct lfs_mlist cwd;\n    cwd.next = lfs->mlist;\n    uint16_t id;\n    err = lfs_dir_find(lfs, &cwd.m, &path, &id);\n    if (!(err == LFS_ERR_NOENT && lfs_path_islast(path))) {\n        return (err < 0) ? err : LFS_ERR_EXIST;\n    }\n\n    // check that name fits\n    lfs_size_t nlen = lfs_path_namelen(path);\n    if (nlen > lfs->name_max) {\n        return LFS_ERR_NAMETOOLONG;\n    }\n\n    // build up new directory\n    lfs_alloc_ckpoint(lfs);\n    lfs_mdir_t dir;\n    err = lfs_dir_alloc(lfs, &dir);\n    if (err) {\n        return err;\n    }\n\n    // find end of list\n    lfs_mdir_t pred = cwd.m;\n    while (pred.split) {\n        err = lfs_dir_fetch(lfs, &pred, pred.tail);\n        if (err) {\n            return err;\n        }\n    }\n\n    // setup dir\n    lfs_pair_tole32(pred.tail);\n    err = lfs_dir_commit(lfs, &dir, LFS_MKATTRS(\n            {LFS_MKTAG(LFS_TYPE_SOFTTAIL, 0x3ff, 8), pred.tail}));\n    lfs_pair_fromle32(pred.tail);\n    if (err) {\n        return err;\n    }\n\n    // current block not end of list?\n    if (cwd.m.split) {\n        // update tails, this creates a desync\n        err = lfs_fs_preporphans(lfs, +1);\n        if (err) {\n            return err;\n        }\n\n        // it's possible our predecessor has to be relocated, and if\n        // our parent is our predecessor's predecessor, this could have\n        // caused our parent to go out of date, fortunately we can hook\n        // ourselves into littlefs to catch this\n        cwd.type = 0;\n        cwd.id = 0;\n        lfs->mlist = &cwd;\n\n        lfs_pair_tole32(dir.pair);\n        err = lfs_dir_commit(lfs, &pred, LFS_MKATTRS(\n                {LFS_MKTAG(LFS_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair}));\n        lfs_pair_fromle32(dir.pair);\n        if (err) {\n            lfs->mlist = cwd.next;\n            return err;\n        }\n\n        lfs->mlist = cwd.next;\n        err = lfs_fs_preporphans(lfs, -1);\n        if (err) {\n            return err;\n        }\n    }\n\n    // now insert into our parent block\n    lfs_pair_tole32(dir.pair);\n    err = lfs_dir_commit(lfs, &cwd.m, LFS_MKATTRS(\n            {LFS_MKTAG(LFS_TYPE_CREATE, id, 0), NULL},\n            {LFS_MKTAG(LFS_TYPE_DIR, id, nlen), path},\n            {LFS_MKTAG(LFS_TYPE_DIRSTRUCT, id, 8), dir.pair},\n            {LFS_MKTAG_IF(!cwd.m.split,\n                LFS_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair}));\n    lfs_pair_fromle32(dir.pair);\n    if (err) {\n        return err;\n    }\n\n    return 0;\n}\n#endif\n\nstatic int lfs_dir_open_(lfs_t *lfs, lfs_dir_t *dir, const char *path) {\n    lfs_stag_t tag = lfs_dir_find(lfs, &dir->m, &path, NULL);\n    if (tag < 0) {\n        return tag;\n    }\n\n    if (lfs_tag_type3(tag) != LFS_TYPE_DIR) {\n        return LFS_ERR_NOTDIR;\n    }\n\n    lfs_block_t pair[2];\n    if (lfs_tag_id(tag) == 0x3ff) {\n        // handle root dir separately\n        pair[0] = lfs->root[0];\n        pair[1] = lfs->root[1];\n    } else {\n        // get dir pair from parent\n        lfs_stag_t res = lfs_dir_get(lfs, &dir->m, LFS_MKTAG(0x700, 0x3ff, 0),\n                LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);\n        if (res < 0) {\n            return res;\n        }\n        lfs_pair_fromle32(pair);\n    }\n\n    // fetch first pair\n    int err = lfs_dir_fetch(lfs, &dir->m, pair);\n    if (err) {\n        return err;\n    }\n\n    // setup entry\n    dir->head[0] = dir->m.pair[0];\n    dir->head[1] = dir->m.pair[1];\n    dir->id = 0;\n    dir->pos = 0;\n\n    // add to list of mdirs\n    dir->type = LFS_TYPE_DIR;\n    lfs_mlist_append(lfs, (struct lfs_mlist *)dir);\n\n    return 0;\n}\n\nstatic int lfs_dir_close_(lfs_t *lfs, lfs_dir_t *dir) {\n    // remove from list of mdirs\n    lfs_mlist_remove(lfs, (struct lfs_mlist *)dir);\n\n    return 0;\n}\n\nstatic int lfs_dir_read_(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {\n    memset(info, 0, sizeof(*info));\n\n    // special offset for '.' and '..'\n    if (dir->pos == 0) {\n        info->type = LFS_TYPE_DIR;\n        strcpy(info->name, \".\");\n        dir->pos += 1;\n        return true;\n    } else if (dir->pos == 1) {\n        info->type = LFS_TYPE_DIR;\n        strcpy(info->name, \"..\");\n        dir->pos += 1;\n        return true;\n    }\n\n    while (true) {\n        if (dir->id == dir->m.count) {\n            if (!dir->m.split) {\n                return false;\n            }\n\n            int err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail);\n            if (err) {\n                return err;\n            }\n\n            dir->id = 0;\n        }\n\n        int err = lfs_dir_getinfo(lfs, &dir->m, dir->id, info);\n        if (err && err != LFS_ERR_NOENT) {\n            return err;\n        }\n\n        dir->id += 1;\n        if (err != LFS_ERR_NOENT) {\n            break;\n        }\n    }\n\n    dir->pos += 1;\n    return true;\n}\n\nstatic int lfs_dir_seek_(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {\n    // simply walk from head dir\n    int err = lfs_dir_rewind_(lfs, dir);\n    if (err) {\n        return err;\n    }\n\n    // first two for ./..\n    dir->pos = lfs_min(2, off);\n    off -= dir->pos;\n\n    // skip superblock entry\n    dir->id = (off > 0 && lfs_pair_cmp(dir->head, lfs->root) == 0);\n\n    while (off > 0) {\n        if (dir->id == dir->m.count) {\n            if (!dir->m.split) {\n                return LFS_ERR_INVAL;\n            }\n\n            err = lfs_dir_fetch(lfs, &dir->m, dir->m.tail);\n            if (err) {\n                return err;\n            }\n\n            dir->id = 0;\n        }\n\n        int diff = lfs_min(dir->m.count - dir->id, off);\n        dir->id += diff;\n        dir->pos += diff;\n        off -= diff;\n    }\n\n    return 0;\n}\n\nstatic lfs_soff_t lfs_dir_tell_(lfs_t *lfs, lfs_dir_t *dir) {\n    (void)lfs;\n    return dir->pos;\n}\n\nstatic int lfs_dir_rewind_(lfs_t *lfs, lfs_dir_t *dir) {\n    // reload the head dir\n    int err = lfs_dir_fetch(lfs, &dir->m, dir->head);\n    if (err) {\n        return err;\n    }\n\n    dir->id = 0;\n    dir->pos = 0;\n    return 0;\n}\n\n\n/// File index list operations ///\nstatic int lfs_ctz_index(lfs_t *lfs, lfs_off_t *off) {\n    lfs_off_t size = *off;\n    lfs_off_t b = lfs->cfg->block_size - 2*4;\n    lfs_off_t i = size / b;\n    if (i == 0) {\n        return 0;\n    }\n\n    i = (size - 4*(lfs_popc(i-1)+2)) / b;\n    *off = size - b*i - 4*lfs_popc(i);\n    return i;\n}\n\nstatic int lfs_ctz_find(lfs_t *lfs,\n        const lfs_cache_t *pcache, lfs_cache_t *rcache,\n        lfs_block_t head, lfs_size_t size,\n        lfs_size_t pos, lfs_block_t *block, lfs_off_t *off) {\n    if (size == 0) {\n        *block = LFS_BLOCK_NULL;\n        *off = 0;\n        return 0;\n    }\n\n    lfs_off_t current = lfs_ctz_index(lfs, &(lfs_off_t){size-1});\n    lfs_off_t target = lfs_ctz_index(lfs, &pos);\n\n    while (current > target) {\n        lfs_size_t skip = lfs_min(\n                lfs_npw2(current-target+1) - 1,\n                lfs_ctz(current));\n\n        int err = lfs_bd_read(lfs,\n                pcache, rcache, sizeof(head),\n                head, 4*skip, &head, sizeof(head));\n        head = lfs_fromle32(head);\n        if (err) {\n            return err;\n        }\n\n        current -= 1 << skip;\n    }\n\n    *block = head;\n    *off = pos;\n    return 0;\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_ctz_extend(lfs_t *lfs,\n        lfs_cache_t *pcache, lfs_cache_t *rcache,\n        lfs_block_t head, lfs_size_t size,\n        lfs_block_t *block, lfs_off_t *off) {\n    while (true) {\n        // go ahead and grab a block\n        lfs_block_t nblock;\n        int err = lfs_alloc(lfs, &nblock);\n        if (err) {\n            return err;\n        }\n\n        {\n            err = lfs_bd_erase(lfs, nblock);\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    goto relocate;\n                }\n                return err;\n            }\n\n            if (size == 0) {\n                *block = nblock;\n                *off = 0;\n                return 0;\n            }\n\n            lfs_size_t noff = size - 1;\n            lfs_off_t index = lfs_ctz_index(lfs, &noff);\n            noff = noff + 1;\n\n            // just copy out the last block if it is incomplete\n            if (noff != lfs->cfg->block_size) {\n                for (lfs_off_t i = 0; i < noff; i++) {\n                    uint8_t data;\n                    err = lfs_bd_read(lfs,\n                            NULL, rcache, noff-i,\n                            head, i, &data, 1);\n                    if (err) {\n                        return err;\n                    }\n\n                    err = lfs_bd_prog(lfs,\n                            pcache, rcache, true,\n                            nblock, i, &data, 1);\n                    if (err) {\n                        if (err == LFS_ERR_CORRUPT) {\n                            goto relocate;\n                        }\n                        return err;\n                    }\n                }\n\n                *block = nblock;\n                *off = noff;\n                return 0;\n            }\n\n            // append block\n            index += 1;\n            lfs_size_t skips = lfs_ctz(index) + 1;\n            lfs_block_t nhead = head;\n            for (lfs_off_t i = 0; i < skips; i++) {\n                nhead = lfs_tole32(nhead);\n                err = lfs_bd_prog(lfs, pcache, rcache, true,\n                        nblock, 4*i, &nhead, 4);\n                nhead = lfs_fromle32(nhead);\n                if (err) {\n                    if (err == LFS_ERR_CORRUPT) {\n                        goto relocate;\n                    }\n                    return err;\n                }\n\n                if (i != skips-1) {\n                    err = lfs_bd_read(lfs,\n                            NULL, rcache, sizeof(nhead),\n                            nhead, 4*i, &nhead, sizeof(nhead));\n                    nhead = lfs_fromle32(nhead);\n                    if (err) {\n                        return err;\n                    }\n                }\n            }\n\n            *block = nblock;\n            *off = 4*skips;\n            return 0;\n        }\n\nrelocate:\n        LFS_DEBUG(\"Bad block at 0x%\"PRIx32, nblock);\n\n        // just clear cache and try a new block\n        lfs_cache_drop(lfs, pcache);\n    }\n}\n#endif\n\nstatic int lfs_ctz_traverse(lfs_t *lfs,\n        const lfs_cache_t *pcache, lfs_cache_t *rcache,\n        lfs_block_t head, lfs_size_t size,\n        int (*cb)(void*, lfs_block_t), void *data) {\n    if (size == 0) {\n        return 0;\n    }\n\n    lfs_off_t index = lfs_ctz_index(lfs, &(lfs_off_t){size-1});\n\n    while (true) {\n        int err = cb(data, head);\n        if (err) {\n            return err;\n        }\n\n        if (index == 0) {\n            return 0;\n        }\n\n        lfs_block_t heads[2];\n        int count = 2 - (index & 1);\n        err = lfs_bd_read(lfs,\n                pcache, rcache, count*sizeof(head),\n                head, 0, &heads, count*sizeof(head));\n        heads[0] = lfs_fromle32(heads[0]);\n        heads[1] = lfs_fromle32(heads[1]);\n        if (err) {\n            return err;\n        }\n\n        for (int i = 0; i < count-1; i++) {\n            err = cb(data, heads[i]);\n            if (err) {\n                return err;\n            }\n        }\n\n        head = heads[count-1];\n        index -= count;\n    }\n}\n\n\n/// Top level file operations ///\nstatic int lfs_file_opencfg_(lfs_t *lfs, lfs_file_t *file,\n        const char *path, int flags,\n        const struct lfs_file_config *cfg) {\n#ifndef LFS_READONLY\n    // deorphan if we haven't yet, needed at most once after poweron\n    if ((flags & LFS_O_WRONLY) == LFS_O_WRONLY) {\n        int err = lfs_fs_forceconsistency(lfs);\n        if (err) {\n            return err;\n        }\n    }\n#else\n    LFS_ASSERT((flags & LFS_O_RDONLY) == LFS_O_RDONLY);\n#endif\n\n    // setup simple file details\n    int err;\n    file->cfg = cfg;\n    file->flags = flags;\n    file->pos = 0;\n    file->off = 0;\n    file->cache.buffer = NULL;\n\n    // allocate entry for file if it doesn't exist\n    lfs_stag_t tag = lfs_dir_find(lfs, &file->m, &path, &file->id);\n    if (tag < 0 && !(tag == LFS_ERR_NOENT && lfs_path_islast(path))) {\n        err = tag;\n        goto cleanup;\n    }\n\n    // get id, add to list of mdirs to catch update changes\n    file->type = LFS_TYPE_REG;\n    lfs_mlist_append(lfs, (struct lfs_mlist *)file);\n\n#ifdef LFS_READONLY\n    if (tag == LFS_ERR_NOENT) {\n        err = LFS_ERR_NOENT;\n        goto cleanup;\n#else\n    if (tag == LFS_ERR_NOENT) {\n        if (!(flags & LFS_O_CREAT)) {\n            err = LFS_ERR_NOENT;\n            goto cleanup;\n        }\n\n        // don't allow trailing slashes\n        if (lfs_path_isdir(path)) {\n            err = LFS_ERR_NOTDIR;\n            goto cleanup;\n        }\n\n        // check that name fits\n        lfs_size_t nlen = lfs_path_namelen(path);\n        if (nlen > lfs->name_max) {\n            err = LFS_ERR_NAMETOOLONG;\n            goto cleanup;\n        }\n\n        // get next slot and create entry to remember name\n        err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(\n                {LFS_MKTAG(LFS_TYPE_CREATE, file->id, 0), NULL},\n                {LFS_MKTAG(LFS_TYPE_REG, file->id, nlen), path},\n                {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0), NULL}));\n\n        // it may happen that the file name doesn't fit in the metadata blocks, e.g., a 256 byte file name will\n        // not fit in a 128 byte block.\n        err = (err == LFS_ERR_NOSPC) ? LFS_ERR_NAMETOOLONG : err;\n        if (err) {\n            goto cleanup;\n        }\n\n        tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, 0);\n    } else if (flags & LFS_O_EXCL) {\n        err = LFS_ERR_EXIST;\n        goto cleanup;\n#endif\n    } else if (lfs_tag_type3(tag) != LFS_TYPE_REG) {\n        err = LFS_ERR_ISDIR;\n        goto cleanup;\n#ifndef LFS_READONLY\n    } else if (flags & LFS_O_TRUNC) {\n        // truncate if requested\n        tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0);\n        file->flags |= LFS_F_DIRTY;\n#endif\n    } else {\n        // try to load what's on disk, if it's inlined we'll fix it later\n        tag = lfs_dir_get(lfs, &file->m, LFS_MKTAG(0x700, 0x3ff, 0),\n                LFS_MKTAG(LFS_TYPE_STRUCT, file->id, 8), &file->ctz);\n        if (tag < 0) {\n            err = tag;\n            goto cleanup;\n        }\n        lfs_ctz_fromle32(&file->ctz);\n    }\n\n    // fetch attrs\n    for (unsigned i = 0; i < file->cfg->attr_count; i++) {\n        // if opened for read / read-write operations\n        if ((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY) {\n            lfs_stag_t res = lfs_dir_get(lfs, &file->m,\n                    LFS_MKTAG(0x7ff, 0x3ff, 0),\n                    LFS_MKTAG(LFS_TYPE_USERATTR + file->cfg->attrs[i].type,\n                        file->id, file->cfg->attrs[i].size),\n                        file->cfg->attrs[i].buffer);\n            if (res < 0 && res != LFS_ERR_NOENT) {\n                err = res;\n                goto cleanup;\n            }\n        }\n\n#ifndef LFS_READONLY\n        // if opened for write / read-write operations\n        if ((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY) {\n            if (file->cfg->attrs[i].size > lfs->attr_max) {\n                err = LFS_ERR_NOSPC;\n                goto cleanup;\n            }\n\n            file->flags |= LFS_F_DIRTY;\n        }\n#endif\n    }\n\n    // allocate buffer if needed\n    if (file->cfg->buffer) {\n        file->cache.buffer = file->cfg->buffer;\n    } else {\n        file->cache.buffer = lfs_malloc(lfs->cfg->cache_size);\n        if (!file->cache.buffer) {\n            err = LFS_ERR_NOMEM;\n            goto cleanup;\n        }\n    }\n\n    // zero to avoid information leak\n    lfs_cache_zero(lfs, &file->cache);\n\n    if (lfs_tag_type3(tag) == LFS_TYPE_INLINESTRUCT) {\n        // load inline files\n        file->ctz.head = LFS_BLOCK_INLINE;\n        file->ctz.size = lfs_tag_size(tag);\n        file->flags |= LFS_F_INLINE;\n        file->cache.block = file->ctz.head;\n        file->cache.off = 0;\n        file->cache.size = lfs->cfg->cache_size;\n\n        // don't always read (may be new/trunc file)\n        if (file->ctz.size > 0) {\n            lfs_stag_t res = lfs_dir_get(lfs, &file->m,\n                    LFS_MKTAG(0x700, 0x3ff, 0),\n                    LFS_MKTAG(LFS_TYPE_STRUCT, file->id,\n                        lfs_min(file->cache.size, 0x3fe)),\n                    file->cache.buffer);\n            if (res < 0) {\n                err = res;\n                goto cleanup;\n            }\n        }\n    }\n\n    return 0;\n\ncleanup:\n    // clean up lingering resources\n#ifndef LFS_READONLY\n    file->flags |= LFS_F_ERRED;\n#endif\n    lfs_file_close_(lfs, file);\n    return err;\n}\n\n#ifndef LFS_NO_MALLOC\nstatic int lfs_file_open_(lfs_t *lfs, lfs_file_t *file,\n        const char *path, int flags) {\n    static const struct lfs_file_config defaults = {0};\n    int err = lfs_file_opencfg_(lfs, file, path, flags, &defaults);\n    return err;\n}\n#endif\n\nstatic int lfs_file_close_(lfs_t *lfs, lfs_file_t *file) {\n#ifndef LFS_READONLY\n    int err = lfs_file_sync_(lfs, file);\n#else\n    int err = 0;\n#endif\n\n    // remove from list of mdirs\n    lfs_mlist_remove(lfs, (struct lfs_mlist*)file);\n\n    // clean up memory\n    if (!file->cfg->buffer) {\n        lfs_free(file->cache.buffer);\n    }\n\n    return err;\n}\n\n\n#ifndef LFS_READONLY\nstatic int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {\n    while (true) {\n        // just relocate what exists into new block\n        lfs_block_t nblock;\n        int err = lfs_alloc(lfs, &nblock);\n        if (err) {\n            return err;\n        }\n\n        err = lfs_bd_erase(lfs, nblock);\n        if (err) {\n            if (err == LFS_ERR_CORRUPT) {\n                goto relocate;\n            }\n            return err;\n        }\n\n        // either read from dirty cache or disk\n        for (lfs_off_t i = 0; i < file->off; i++) {\n            uint8_t data;\n            if (file->flags & LFS_F_INLINE) {\n                err = lfs_dir_getread(lfs, &file->m,\n                        // note we evict inline files before they can be dirty\n                        NULL, &file->cache, file->off-i,\n                        LFS_MKTAG(0xfff, 0x1ff, 0),\n                        LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0),\n                        i, &data, 1);\n                if (err) {\n                    return err;\n                }\n            } else {\n                err = lfs_bd_read(lfs,\n                        &file->cache, &lfs->rcache, file->off-i,\n                        file->block, i, &data, 1);\n                if (err) {\n                    return err;\n                }\n            }\n\n            err = lfs_bd_prog(lfs,\n                    &lfs->pcache, &lfs->rcache, true,\n                    nblock, i, &data, 1);\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    goto relocate;\n                }\n                return err;\n            }\n        }\n\n        // copy over new state of file\n        memcpy(file->cache.buffer, lfs->pcache.buffer, lfs->cfg->cache_size);\n        file->cache.block = lfs->pcache.block;\n        file->cache.off = lfs->pcache.off;\n        file->cache.size = lfs->pcache.size;\n        lfs_cache_zero(lfs, &lfs->pcache);\n\n        file->block = nblock;\n        file->flags |= LFS_F_WRITING;\n        return 0;\n\nrelocate:\n        LFS_DEBUG(\"Bad block at 0x%\"PRIx32, nblock);\n\n        // just clear cache and try a new block\n        lfs_cache_drop(lfs, &lfs->pcache);\n    }\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {\n    file->off = file->pos;\n    lfs_alloc_ckpoint(lfs);\n    int err = lfs_file_relocate(lfs, file);\n    if (err) {\n        return err;\n    }\n\n    file->flags &= ~LFS_F_INLINE;\n    return 0;\n}\n#endif\n\nstatic int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {\n    if (file->flags & LFS_F_READING) {\n        if (!(file->flags & LFS_F_INLINE)) {\n            lfs_cache_drop(lfs, &file->cache);\n        }\n        file->flags &= ~LFS_F_READING;\n    }\n\n#ifndef LFS_READONLY\n    if (file->flags & LFS_F_WRITING) {\n        lfs_off_t pos = file->pos;\n\n        if (!(file->flags & LFS_F_INLINE)) {\n            // copy over anything after current branch\n            lfs_file_t orig = {\n                .ctz.head = file->ctz.head,\n                .ctz.size = file->ctz.size,\n                .flags = LFS_O_RDONLY,\n                .pos = file->pos,\n                .cache = lfs->rcache,\n            };\n            lfs_cache_drop(lfs, &lfs->rcache);\n\n            while (file->pos < file->ctz.size) {\n                // copy over a byte at a time, leave it up to caching\n                // to make this efficient\n                uint8_t data;\n                lfs_ssize_t res = lfs_file_flushedread(lfs, &orig, &data, 1);\n                if (res < 0) {\n                    return res;\n                }\n\n                res = lfs_file_flushedwrite(lfs, file, &data, 1);\n                if (res < 0) {\n                    return res;\n                }\n\n                // keep our reference to the rcache in sync\n                if (lfs->rcache.block != LFS_BLOCK_NULL) {\n                    lfs_cache_drop(lfs, &orig.cache);\n                    lfs_cache_drop(lfs, &lfs->rcache);\n                }\n            }\n\n            // write out what we have\n            while (true) {\n                int err = lfs_bd_flush(lfs, &file->cache, &lfs->rcache, true);\n                if (err) {\n                    if (err == LFS_ERR_CORRUPT) {\n                        goto relocate;\n                    }\n                    return err;\n                }\n\n                break;\n\nrelocate:\n                LFS_DEBUG(\"Bad block at 0x%\"PRIx32, file->block);\n                err = lfs_file_relocate(lfs, file);\n                if (err) {\n                    return err;\n                }\n            }\n        } else {\n            file->pos = lfs_max(file->pos, file->ctz.size);\n        }\n\n        // actual file updates\n        file->ctz.head = file->block;\n        file->ctz.size = file->pos;\n        file->flags &= ~LFS_F_WRITING;\n        file->flags |= LFS_F_DIRTY;\n\n        file->pos = pos;\n    }\n#endif\n\n    return 0;\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_file_sync_(lfs_t *lfs, lfs_file_t *file) {\n    if (file->flags & LFS_F_ERRED) {\n        // it's not safe to do anything if our file errored\n        return 0;\n    }\n\n    int err = lfs_file_flush(lfs, file);\n    if (err) {\n        file->flags |= LFS_F_ERRED;\n        return err;\n    }\n\n\n    if ((file->flags & LFS_F_DIRTY) &&\n            !lfs_pair_isnull(file->m.pair)) {\n        // before we commit metadata, we need sync the disk to make sure\n        // data writes don't complete after metadata writes\n        if (!(file->flags & LFS_F_INLINE)) {\n            err = lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false);\n            if (err) {\n                return err;\n            }\n        }\n\n        // update dir entry\n        uint16_t type;\n        const void *buffer;\n        lfs_size_t size;\n        struct lfs_ctz ctz;\n        if (file->flags & LFS_F_INLINE) {\n            // inline the whole file\n            type = LFS_TYPE_INLINESTRUCT;\n            buffer = file->cache.buffer;\n            size = file->ctz.size;\n        } else {\n            // update the ctz reference\n            type = LFS_TYPE_CTZSTRUCT;\n            // copy ctz so alloc will work during a relocate\n            ctz = file->ctz;\n            lfs_ctz_tole32(&ctz);\n            buffer = &ctz;\n            size = sizeof(ctz);\n        }\n\n        // commit file data and attributes\n        err = lfs_dir_commit(lfs, &file->m, LFS_MKATTRS(\n                {LFS_MKTAG(type, file->id, size), buffer},\n                {LFS_MKTAG(LFS_FROM_USERATTRS, file->id,\n                    file->cfg->attr_count), file->cfg->attrs}));\n        if (err) {\n            file->flags |= LFS_F_ERRED;\n            return err;\n        }\n\n        file->flags &= ~LFS_F_DIRTY;\n    }\n\n    return 0;\n}\n#endif\n\nstatic lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,\n        void *buffer, lfs_size_t size) {\n    uint8_t *data = buffer;\n    lfs_size_t nsize = size;\n\n    if (file->pos >= file->ctz.size) {\n        // eof if past end\n        return 0;\n    }\n\n    size = lfs_min(size, file->ctz.size - file->pos);\n    nsize = size;\n\n    while (nsize > 0) {\n        // check if we need a new block\n        if (!(file->flags & LFS_F_READING) ||\n                file->off == lfs->cfg->block_size) {\n            if (!(file->flags & LFS_F_INLINE)) {\n                int err = lfs_ctz_find(lfs, NULL, &file->cache,\n                        file->ctz.head, file->ctz.size,\n                        file->pos, &file->block, &file->off);\n                if (err) {\n                    return err;\n                }\n            } else {\n                file->block = LFS_BLOCK_INLINE;\n                file->off = file->pos;\n            }\n\n            file->flags |= LFS_F_READING;\n        }\n\n        // read as much as we can in current block\n        lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);\n        if (file->flags & LFS_F_INLINE) {\n            int err = lfs_dir_getread(lfs, &file->m,\n                    NULL, &file->cache, lfs->cfg->block_size,\n                    LFS_MKTAG(0xfff, 0x1ff, 0),\n                    LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0),\n                    file->off, data, diff);\n            if (err) {\n                return err;\n            }\n        } else {\n            int err = lfs_bd_read(lfs,\n                    NULL, &file->cache, lfs->cfg->block_size,\n                    file->block, file->off, data, diff);\n            if (err) {\n                return err;\n            }\n        }\n\n        file->pos += diff;\n        file->off += diff;\n        data += diff;\n        nsize -= diff;\n    }\n\n    return size;\n}\n\nstatic lfs_ssize_t lfs_file_read_(lfs_t *lfs, lfs_file_t *file,\n        void *buffer, lfs_size_t size) {\n    LFS_ASSERT((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY);\n\n#ifndef LFS_READONLY\n    if (file->flags & LFS_F_WRITING) {\n        // flush out any writes\n        int err = lfs_file_flush(lfs, file);\n        if (err) {\n            return err;\n        }\n    }\n#endif\n\n    return lfs_file_flushedread(lfs, file, buffer, size);\n}\n\n\n#ifndef LFS_READONLY\nstatic lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,\n        const void *buffer, lfs_size_t size) {\n    const uint8_t *data = buffer;\n    lfs_size_t nsize = size;\n\n    if ((file->flags & LFS_F_INLINE) &&\n            lfs_max(file->pos+nsize, file->ctz.size) > lfs->inline_max) {\n        // inline file doesn't fit anymore\n        int err = lfs_file_outline(lfs, file);\n        if (err) {\n            file->flags |= LFS_F_ERRED;\n            return err;\n        }\n    }\n\n    while (nsize > 0) {\n        // check if we need a new block\n        if (!(file->flags & LFS_F_WRITING) ||\n                file->off == lfs->cfg->block_size) {\n            if (!(file->flags & LFS_F_INLINE)) {\n                if (!(file->flags & LFS_F_WRITING) && file->pos > 0) {\n                    // find out which block we're extending from\n                    int err = lfs_ctz_find(lfs, NULL, &file->cache,\n                            file->ctz.head, file->ctz.size,\n                            file->pos-1, &file->block, &(lfs_off_t){0});\n                    if (err) {\n                        file->flags |= LFS_F_ERRED;\n                        return err;\n                    }\n\n                    // mark cache as dirty since we may have read data into it\n                    lfs_cache_zero(lfs, &file->cache);\n                }\n\n                // extend file with new blocks\n                lfs_alloc_ckpoint(lfs);\n                int err = lfs_ctz_extend(lfs, &file->cache, &lfs->rcache,\n                        file->block, file->pos,\n                        &file->block, &file->off);\n                if (err) {\n                    file->flags |= LFS_F_ERRED;\n                    return err;\n                }\n            } else {\n                file->block = LFS_BLOCK_INLINE;\n                file->off = file->pos;\n            }\n\n            file->flags |= LFS_F_WRITING;\n        }\n\n        // program as much as we can in current block\n        lfs_size_t diff = lfs_min(nsize, lfs->cfg->block_size - file->off);\n        while (true) {\n            int err = lfs_bd_prog(lfs, &file->cache, &lfs->rcache, true,\n                    file->block, file->off, data, diff);\n            if (err) {\n                if (err == LFS_ERR_CORRUPT) {\n                    goto relocate;\n                }\n                file->flags |= LFS_F_ERRED;\n                return err;\n            }\n\n            break;\nrelocate:\n            err = lfs_file_relocate(lfs, file);\n            if (err) {\n                file->flags |= LFS_F_ERRED;\n                return err;\n            }\n        }\n\n        file->pos += diff;\n        file->off += diff;\n        data += diff;\n        nsize -= diff;\n\n        lfs_alloc_ckpoint(lfs);\n    }\n\n    return size;\n}\n\nstatic lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file,\n        const void *buffer, lfs_size_t size) {\n    LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);\n\n    if (file->flags & LFS_F_READING) {\n        // drop any reads\n        int err = lfs_file_flush(lfs, file);\n        if (err) {\n            return err;\n        }\n    }\n\n    if ((file->flags & LFS_O_APPEND) && file->pos < file->ctz.size) {\n        file->pos = file->ctz.size;\n    }\n\n    if (file->pos + size > lfs->file_max) {\n        // Larger than file limit?\n        return LFS_ERR_FBIG;\n    }\n\n    if (!(file->flags & LFS_F_WRITING) && file->pos > file->ctz.size) {\n        // fill with zeros\n        lfs_off_t pos = file->pos;\n        file->pos = file->ctz.size;\n\n        while (file->pos < pos) {\n            lfs_ssize_t res = lfs_file_flushedwrite(lfs, file, &(uint8_t){0}, 1);\n            if (res < 0) {\n                return res;\n            }\n        }\n    }\n\n    lfs_ssize_t nsize = lfs_file_flushedwrite(lfs, file, buffer, size);\n    if (nsize < 0) {\n        return nsize;\n    }\n\n    file->flags &= ~LFS_F_ERRED;\n    return nsize;\n}\n#endif\n\nstatic lfs_soff_t lfs_file_seek_(lfs_t *lfs, lfs_file_t *file,\n        lfs_soff_t off, int whence) {\n    // find new pos\n    //\n    // fortunately for us, littlefs is limited to 31-bit file sizes, so we\n    // don't have to worry too much about integer overflow\n    lfs_off_t npos = file->pos;\n    if (whence == LFS_SEEK_SET) {\n        npos = off;\n    } else if (whence == LFS_SEEK_CUR) {\n        npos = file->pos + (lfs_off_t)off;\n    } else if (whence == LFS_SEEK_END) {\n        npos = (lfs_off_t)lfs_file_size_(lfs, file) + (lfs_off_t)off;\n    }\n\n    if (npos > lfs->file_max) {\n        // file position out of range\n        return LFS_ERR_INVAL;\n    }\n\n    if (file->pos == npos) {\n        // noop - position has not changed\n        return npos;\n    }\n\n    // if we're only reading and our new offset is still in the file's cache\n    // we can avoid flushing and needing to reread the data\n    if ((file->flags & LFS_F_READING)\n            && file->off != lfs->cfg->block_size) {\n        int oindex = lfs_ctz_index(lfs, &(lfs_off_t){file->pos});\n        lfs_off_t noff = npos;\n        int nindex = lfs_ctz_index(lfs, &noff);\n        if (oindex == nindex\n                && noff >= file->cache.off\n                && noff < file->cache.off + file->cache.size) {\n            file->pos = npos;\n            file->off = noff;\n            return npos;\n        }\n    }\n\n    // write out everything beforehand, may be noop if rdonly\n    int err = lfs_file_flush(lfs, file);\n    if (err) {\n        return err;\n    }\n\n    // update pos\n    file->pos = npos;\n    return npos;\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_file_truncate_(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {\n    LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);\n\n    if (size > LFS_FILE_MAX) {\n        return LFS_ERR_INVAL;\n    }\n\n    lfs_off_t pos = file->pos;\n    lfs_off_t oldsize = lfs_file_size_(lfs, file);\n    if (size < oldsize) {\n        // revert to inline file?\n        if (size <= lfs->inline_max) {\n            // flush+seek to head\n            lfs_soff_t res = lfs_file_seek_(lfs, file, 0, LFS_SEEK_SET);\n            if (res < 0) {\n                return (int)res;\n            }\n\n            // read our data into rcache temporarily\n            lfs_cache_drop(lfs, &lfs->rcache);\n            res = lfs_file_flushedread(lfs, file,\n                    lfs->rcache.buffer, size);\n            if (res < 0) {\n                return (int)res;\n            }\n\n            file->ctz.head = LFS_BLOCK_INLINE;\n            file->ctz.size = size;\n            file->flags |= LFS_F_DIRTY | LFS_F_READING | LFS_F_INLINE;\n            file->cache.block = file->ctz.head;\n            file->cache.off = 0;\n            file->cache.size = lfs->cfg->cache_size;\n            memcpy(file->cache.buffer, lfs->rcache.buffer, size);\n\n        } else {\n            // need to flush since directly changing metadata\n            int err = lfs_file_flush(lfs, file);\n            if (err) {\n                return err;\n            }\n\n            // lookup new head in ctz skip list\n            err = lfs_ctz_find(lfs, NULL, &file->cache,\n                    file->ctz.head, file->ctz.size,\n                    size-1, &file->block, &(lfs_off_t){0});\n            if (err) {\n                return err;\n            }\n\n            // need to set pos/block/off consistently so seeking back to\n            // the old position does not get confused\n            file->pos = size;\n            file->ctz.head = file->block;\n            file->ctz.size = size;\n            file->flags |= LFS_F_DIRTY | LFS_F_READING;\n        }\n    } else if (size > oldsize) {\n        // flush+seek if not already at end\n        lfs_soff_t res = lfs_file_seek_(lfs, file, 0, LFS_SEEK_END);\n        if (res < 0) {\n            return (int)res;\n        }\n\n        // fill with zeros\n        while (file->pos < size) {\n            res = lfs_file_write_(lfs, file, &(uint8_t){0}, 1);\n            if (res < 0) {\n                return (int)res;\n            }\n        }\n    }\n\n    // restore pos\n    lfs_soff_t res = lfs_file_seek_(lfs, file, pos, LFS_SEEK_SET);\n    if (res < 0) {\n      return (int)res;\n    }\n\n    return 0;\n}\n#endif\n\nstatic lfs_soff_t lfs_file_tell_(lfs_t *lfs, lfs_file_t *file) {\n    (void)lfs;\n    return file->pos;\n}\n\nstatic int lfs_file_rewind_(lfs_t *lfs, lfs_file_t *file) {\n    lfs_soff_t res = lfs_file_seek_(lfs, file, 0, LFS_SEEK_SET);\n    if (res < 0) {\n        return (int)res;\n    }\n\n    return 0;\n}\n\nstatic lfs_soff_t lfs_file_size_(lfs_t *lfs, lfs_file_t *file) {\n    (void)lfs;\n\n#ifndef LFS_READONLY\n    if (file->flags & LFS_F_WRITING) {\n        return lfs_max(file->pos, file->ctz.size);\n    }\n#endif\n\n    return file->ctz.size;\n}\n\n\n/// General fs operations ///\nstatic int lfs_stat_(lfs_t *lfs, const char *path, struct lfs_info *info) {\n    lfs_mdir_t cwd;\n    lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);\n    if (tag < 0) {\n        return (int)tag;\n    }\n\n    // only allow trailing slashes on dirs\n    if (strchr(path, '/') != NULL\n            && lfs_tag_type3(tag) != LFS_TYPE_DIR) {\n        return LFS_ERR_NOTDIR;\n    }\n\n    return lfs_dir_getinfo(lfs, &cwd, lfs_tag_id(tag), info);\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_remove_(lfs_t *lfs, const char *path) {\n    // deorphan if we haven't yet, needed at most once after poweron\n    int err = lfs_fs_forceconsistency(lfs);\n    if (err) {\n        return err;\n    }\n\n    lfs_mdir_t cwd;\n    lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);\n    if (tag < 0 || lfs_tag_id(tag) == 0x3ff) {\n        return (tag < 0) ? (int)tag : LFS_ERR_INVAL;\n    }\n\n    struct lfs_mlist dir;\n    dir.next = lfs->mlist;\n    if (lfs_tag_type3(tag) == LFS_TYPE_DIR) {\n        // must be empty before removal\n        lfs_block_t pair[2];\n        lfs_stag_t res = lfs_dir_get(lfs, &cwd, LFS_MKTAG(0x700, 0x3ff, 0),\n                LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);\n        if (res < 0) {\n            return (int)res;\n        }\n        lfs_pair_fromle32(pair);\n\n        err = lfs_dir_fetch(lfs, &dir.m, pair);\n        if (err) {\n            return err;\n        }\n\n        if (dir.m.count > 0 || dir.m.split) {\n            return LFS_ERR_NOTEMPTY;\n        }\n\n        // mark fs as orphaned\n        err = lfs_fs_preporphans(lfs, +1);\n        if (err) {\n            return err;\n        }\n\n        // I know it's crazy but yes, dir can be changed by our parent's\n        // commit (if predecessor is child)\n        dir.type = 0;\n        dir.id = 0;\n        lfs->mlist = &dir;\n    }\n\n    // delete the entry\n    err = lfs_dir_commit(lfs, &cwd, LFS_MKATTRS(\n            {LFS_MKTAG(LFS_TYPE_DELETE, lfs_tag_id(tag), 0), NULL}));\n    if (err) {\n        lfs->mlist = dir.next;\n        return err;\n    }\n\n    lfs->mlist = dir.next;\n    if (lfs_tag_type3(tag) == LFS_TYPE_DIR) {\n        // fix orphan\n        err = lfs_fs_preporphans(lfs, -1);\n        if (err) {\n            return err;\n        }\n\n        err = lfs_fs_pred(lfs, dir.m.pair, &cwd);\n        if (err) {\n            return err;\n        }\n\n        err = lfs_dir_drop(lfs, &cwd, &dir.m);\n        if (err) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) {\n    // deorphan if we haven't yet, needed at most once after poweron\n    int err = lfs_fs_forceconsistency(lfs);\n    if (err) {\n        return err;\n    }\n\n    // find old entry\n    lfs_mdir_t oldcwd;\n    lfs_stag_t oldtag = lfs_dir_find(lfs, &oldcwd, &oldpath, NULL);\n    if (oldtag < 0 || lfs_tag_id(oldtag) == 0x3ff) {\n        return (oldtag < 0) ? (int)oldtag : LFS_ERR_INVAL;\n    }\n\n    // find new entry\n    lfs_mdir_t newcwd;\n    uint16_t newid;\n    lfs_stag_t prevtag = lfs_dir_find(lfs, &newcwd, &newpath, &newid);\n    if ((prevtag < 0 || lfs_tag_id(prevtag) == 0x3ff) &&\n            !(prevtag == LFS_ERR_NOENT && lfs_path_islast(newpath))) {\n        return (prevtag < 0) ? (int)prevtag : LFS_ERR_INVAL;\n    }\n\n    // if we're in the same pair there's a few special cases...\n    bool samepair = (lfs_pair_cmp(oldcwd.pair, newcwd.pair) == 0);\n    uint16_t newoldid = lfs_tag_id(oldtag);\n\n    struct lfs_mlist prevdir;\n    prevdir.next = lfs->mlist;\n    if (prevtag == LFS_ERR_NOENT) {\n        // if we're a file, don't allow trailing slashes\n        if (lfs_path_isdir(newpath)\n                && lfs_tag_type3(oldtag) != LFS_TYPE_DIR) {\n            return LFS_ERR_NOTDIR;\n        }\n\n        // check that name fits\n        lfs_size_t nlen = lfs_path_namelen(newpath);\n        if (nlen > lfs->name_max) {\n            return LFS_ERR_NAMETOOLONG;\n        }\n\n        // there is a small chance we are being renamed in the same\n        // directory/ to an id less than our old id, the global update\n        // to handle this is a bit messy\n        if (samepair && newid <= newoldid) {\n            newoldid += 1;\n        }\n    } else if (lfs_tag_type3(prevtag) != lfs_tag_type3(oldtag)) {\n        return (lfs_tag_type3(prevtag) == LFS_TYPE_DIR)\n                ? LFS_ERR_ISDIR\n                : LFS_ERR_NOTDIR;\n    } else if (samepair && newid == newoldid) {\n        // we're renaming to ourselves??\n        return 0;\n    } else if (lfs_tag_type3(prevtag) == LFS_TYPE_DIR) {\n        // must be empty before removal\n        lfs_block_t prevpair[2];\n        lfs_stag_t res = lfs_dir_get(lfs, &newcwd, LFS_MKTAG(0x700, 0x3ff, 0),\n                LFS_MKTAG(LFS_TYPE_STRUCT, newid, 8), prevpair);\n        if (res < 0) {\n            return (int)res;\n        }\n        lfs_pair_fromle32(prevpair);\n\n        // must be empty before removal\n        err = lfs_dir_fetch(lfs, &prevdir.m, prevpair);\n        if (err) {\n            return err;\n        }\n\n        if (prevdir.m.count > 0 || prevdir.m.split) {\n            return LFS_ERR_NOTEMPTY;\n        }\n\n        // mark fs as orphaned\n        err = lfs_fs_preporphans(lfs, +1);\n        if (err) {\n            return err;\n        }\n\n        // I know it's crazy but yes, dir can be changed by our parent's\n        // commit (if predecessor is child)\n        prevdir.type = 0;\n        prevdir.id = 0;\n        lfs->mlist = &prevdir;\n    }\n\n    if (!samepair) {\n        lfs_fs_prepmove(lfs, newoldid, oldcwd.pair);\n    }\n\n    // move over all attributes\n    err = lfs_dir_commit(lfs, &newcwd, LFS_MKATTRS(\n            {LFS_MKTAG_IF(prevtag != LFS_ERR_NOENT,\n                LFS_TYPE_DELETE, newid, 0), NULL},\n            {LFS_MKTAG(LFS_TYPE_CREATE, newid, 0), NULL},\n            {LFS_MKTAG(lfs_tag_type3(oldtag),\n                newid, lfs_path_namelen(newpath)), newpath},\n            {LFS_MKTAG(LFS_FROM_MOVE, newid, lfs_tag_id(oldtag)), &oldcwd},\n            {LFS_MKTAG_IF(samepair,\n                LFS_TYPE_DELETE, newoldid, 0), NULL}));\n    if (err) {\n        lfs->mlist = prevdir.next;\n        return err;\n    }\n\n    // let commit clean up after move (if we're different! otherwise move\n    // logic already fixed it for us)\n    if (!samepair && lfs_gstate_hasmove(&lfs->gstate)) {\n        // prep gstate and delete move id\n        lfs_fs_prepmove(lfs, 0x3ff, NULL);\n        err = lfs_dir_commit(lfs, &oldcwd, LFS_MKATTRS(\n                {LFS_MKTAG(LFS_TYPE_DELETE, lfs_tag_id(oldtag), 0), NULL}));\n        if (err) {\n            lfs->mlist = prevdir.next;\n            return err;\n        }\n    }\n\n    lfs->mlist = prevdir.next;\n    if (prevtag != LFS_ERR_NOENT\n            && lfs_tag_type3(prevtag) == LFS_TYPE_DIR) {\n        // fix orphan\n        err = lfs_fs_preporphans(lfs, -1);\n        if (err) {\n            return err;\n        }\n\n        err = lfs_fs_pred(lfs, prevdir.m.pair, &newcwd);\n        if (err) {\n            return err;\n        }\n\n        err = lfs_dir_drop(lfs, &newcwd, &prevdir.m);\n        if (err) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n#endif\n\nstatic lfs_ssize_t lfs_getattr_(lfs_t *lfs, const char *path,\n        uint8_t type, void *buffer, lfs_size_t size) {\n    lfs_mdir_t cwd;\n    lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);\n    if (tag < 0) {\n        return tag;\n    }\n\n    uint16_t id = lfs_tag_id(tag);\n    if (id == 0x3ff) {\n        // special case for root\n        id = 0;\n        int err = lfs_dir_fetch(lfs, &cwd, lfs->root);\n        if (err) {\n            return err;\n        }\n    }\n\n    tag = lfs_dir_get(lfs, &cwd, LFS_MKTAG(0x7ff, 0x3ff, 0),\n            LFS_MKTAG(LFS_TYPE_USERATTR + type,\n                id, lfs_min(size, lfs->attr_max)),\n            buffer);\n    if (tag < 0) {\n        if (tag == LFS_ERR_NOENT) {\n            return LFS_ERR_NOATTR;\n        }\n\n        return tag;\n    }\n\n    return lfs_tag_size(tag);\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_commitattr(lfs_t *lfs, const char *path,\n        uint8_t type, const void *buffer, lfs_size_t size) {\n    lfs_mdir_t cwd;\n    lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);\n    if (tag < 0) {\n        return tag;\n    }\n\n    uint16_t id = lfs_tag_id(tag);\n    if (id == 0x3ff) {\n        // special case for root\n        id = 0;\n        int err = lfs_dir_fetch(lfs, &cwd, lfs->root);\n        if (err) {\n            return err;\n        }\n    }\n\n    return lfs_dir_commit(lfs, &cwd, LFS_MKATTRS(\n            {LFS_MKTAG(LFS_TYPE_USERATTR + type, id, size), buffer}));\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_setattr_(lfs_t *lfs, const char *path,\n        uint8_t type, const void *buffer, lfs_size_t size) {\n    if (size > lfs->attr_max) {\n        return LFS_ERR_NOSPC;\n    }\n\n    return lfs_commitattr(lfs, path, type, buffer, size);\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_removeattr_(lfs_t *lfs, const char *path, uint8_t type) {\n    return lfs_commitattr(lfs, path, type, NULL, 0x3ff);\n}\n#endif\n\n\n/// Filesystem operations ///\n\n// compile time checks, see lfs.h for why these limits exist\n#if LFS_NAME_MAX > 1022\n#error \"Invalid LFS_NAME_MAX, must be <= 1022\"\n#endif\n\n#if LFS_FILE_MAX > 2147483647\n#error \"Invalid LFS_FILE_MAX, must be <= 2147483647\"\n#endif\n\n#if LFS_ATTR_MAX > 1022\n#error \"Invalid LFS_ATTR_MAX, must be <= 1022\"\n#endif\n\n// common filesystem initialization\nstatic int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {\n    lfs->cfg = cfg;\n    lfs->block_count = cfg->block_count;  // May be 0\n    int err = 0;\n\n#ifdef LFS_MULTIVERSION\n    // this driver only supports minor version < current minor version\n    LFS_ASSERT(!lfs->cfg->disk_version || (\n            (0xffff & (lfs->cfg->disk_version >> 16))\n                    == LFS_DISK_VERSION_MAJOR\n                && (0xffff & (lfs->cfg->disk_version >> 0))\n                    <= LFS_DISK_VERSION_MINOR));\n#endif\n\n    // check that bool is a truthy-preserving type\n    //\n    // note the most common reason for this failure is a before-c99 compiler,\n    // which littlefs currently does not support\n    LFS_ASSERT((bool)0x80000000);\n\n    // check that the required io functions are provided\n    LFS_ASSERT(lfs->cfg->read != NULL);\n#ifndef LFS_READONLY\n    LFS_ASSERT(lfs->cfg->prog != NULL);\n    LFS_ASSERT(lfs->cfg->erase != NULL);\n    LFS_ASSERT(lfs->cfg->sync != NULL);\n#endif\n\n    // validate that the lfs-cfg sizes were initiated properly before\n    // performing any arithmetic logics with them\n    LFS_ASSERT(lfs->cfg->read_size != 0);\n    LFS_ASSERT(lfs->cfg->prog_size != 0);\n    LFS_ASSERT(lfs->cfg->cache_size != 0);\n\n    // check that block size is a multiple of cache size is a multiple\n    // of prog and read sizes\n    LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0);\n    LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->prog_size == 0);\n    LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->cache_size == 0);\n\n    // check that the block size is large enough to fit all ctz pointers\n    LFS_ASSERT(lfs->cfg->block_size >= 128);\n    // this is the exact calculation for all ctz pointers, if this fails\n    // and the simpler assert above does not, math must be broken\n    LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))\n            <= lfs->cfg->block_size);\n\n    // block_cycles = 0 is no longer supported.\n    //\n    // block_cycles is the number of erase cycles before littlefs evicts\n    // metadata logs as a part of wear leveling. Suggested values are in the\n    // range of 100-1000, or set block_cycles to -1 to disable block-level\n    // wear-leveling.\n    LFS_ASSERT(lfs->cfg->block_cycles != 0);\n\n    // check that compact_thresh makes sense\n    //\n    // metadata can't be compacted below block_size/2, and metadata can't\n    // exceed a block_size\n    LFS_ASSERT(lfs->cfg->compact_thresh == 0\n            || lfs->cfg->compact_thresh >= lfs->cfg->block_size/2);\n    LFS_ASSERT(lfs->cfg->compact_thresh == (lfs_size_t)-1\n            || lfs->cfg->compact_thresh <= lfs->cfg->block_size);\n\n    // check that metadata_max is a multiple of read_size and prog_size,\n    // and a factor of the block_size\n    LFS_ASSERT(!lfs->cfg->metadata_max\n            || lfs->cfg->metadata_max % lfs->cfg->read_size == 0);\n    LFS_ASSERT(!lfs->cfg->metadata_max\n            || lfs->cfg->metadata_max % lfs->cfg->prog_size == 0);\n    LFS_ASSERT(!lfs->cfg->metadata_max\n            || lfs->cfg->block_size % lfs->cfg->metadata_max == 0);\n\n    // setup read cache\n    if (lfs->cfg->read_buffer) {\n        lfs->rcache.buffer = lfs->cfg->read_buffer;\n    } else {\n        lfs->rcache.buffer = lfs_malloc(lfs->cfg->cache_size);\n        if (!lfs->rcache.buffer) {\n            err = LFS_ERR_NOMEM;\n            goto cleanup;\n        }\n    }\n\n    // setup program cache\n    if (lfs->cfg->prog_buffer) {\n        lfs->pcache.buffer = lfs->cfg->prog_buffer;\n    } else {\n        lfs->pcache.buffer = lfs_malloc(lfs->cfg->cache_size);\n        if (!lfs->pcache.buffer) {\n            err = LFS_ERR_NOMEM;\n            goto cleanup;\n        }\n    }\n\n    // zero to avoid information leaks\n    lfs_cache_zero(lfs, &lfs->rcache);\n    lfs_cache_zero(lfs, &lfs->pcache);\n\n    // setup lookahead buffer, note mount finishes initializing this after\n    // we establish a decent pseudo-random seed\n    LFS_ASSERT(lfs->cfg->lookahead_size > 0);\n    if (lfs->cfg->lookahead_buffer) {\n        lfs->lookahead.buffer = lfs->cfg->lookahead_buffer;\n    } else {\n        lfs->lookahead.buffer = lfs_malloc(lfs->cfg->lookahead_size);\n        if (!lfs->lookahead.buffer) {\n            err = LFS_ERR_NOMEM;\n            goto cleanup;\n        }\n    }\n\n    // check that the size limits are sane\n    LFS_ASSERT(lfs->cfg->name_max <= LFS_NAME_MAX);\n    lfs->name_max = lfs->cfg->name_max;\n    if (!lfs->name_max) {\n        lfs->name_max = LFS_NAME_MAX;\n    }\n\n    LFS_ASSERT(lfs->cfg->file_max <= LFS_FILE_MAX);\n    lfs->file_max = lfs->cfg->file_max;\n    if (!lfs->file_max) {\n        lfs->file_max = LFS_FILE_MAX;\n    }\n\n    LFS_ASSERT(lfs->cfg->attr_max <= LFS_ATTR_MAX);\n    lfs->attr_max = lfs->cfg->attr_max;\n    if (!lfs->attr_max) {\n        lfs->attr_max = LFS_ATTR_MAX;\n    }\n\n    LFS_ASSERT(lfs->cfg->metadata_max <= lfs->cfg->block_size);\n\n    LFS_ASSERT(lfs->cfg->inline_max == (lfs_size_t)-1\n            || lfs->cfg->inline_max <= lfs->cfg->cache_size);\n    LFS_ASSERT(lfs->cfg->inline_max == (lfs_size_t)-1\n            || lfs->cfg->inline_max <= lfs->attr_max);\n    LFS_ASSERT(lfs->cfg->inline_max == (lfs_size_t)-1\n            || lfs->cfg->inline_max <= ((lfs->cfg->metadata_max)\n                ? lfs->cfg->metadata_max\n                : lfs->cfg->block_size)/8);\n    lfs->inline_max = lfs->cfg->inline_max;\n    if (lfs->inline_max == (lfs_size_t)-1) {\n        lfs->inline_max = 0;\n    } else if (lfs->inline_max == 0) {\n        lfs->inline_max = lfs_min(\n                lfs->cfg->cache_size,\n                lfs_min(\n                    lfs->attr_max,\n                    ((lfs->cfg->metadata_max)\n                        ? lfs->cfg->metadata_max\n                        : lfs->cfg->block_size)/8));\n    }\n\n    // setup default state\n    lfs->root[0] = LFS_BLOCK_NULL;\n    lfs->root[1] = LFS_BLOCK_NULL;\n    lfs->mlist = NULL;\n    lfs->seed = 0;\n    lfs->gdisk = (lfs_gstate_t){0};\n    lfs->gstate = (lfs_gstate_t){0};\n    lfs->gdelta = (lfs_gstate_t){0};\n#ifdef LFS_MIGRATE\n    lfs->lfs1 = NULL;\n#endif\n\n    return 0;\n\ncleanup:\n    lfs_deinit(lfs);\n    return err;\n}\n\nstatic int lfs_deinit(lfs_t *lfs) {\n    // free allocated memory\n    if (!lfs->cfg->read_buffer) {\n        lfs_free(lfs->rcache.buffer);\n    }\n\n    if (!lfs->cfg->prog_buffer) {\n        lfs_free(lfs->pcache.buffer);\n    }\n\n    if (!lfs->cfg->lookahead_buffer) {\n        lfs_free(lfs->lookahead.buffer);\n    }\n\n    return 0;\n}\n\n\n\n#ifndef LFS_READONLY\nstatic int lfs_format_(lfs_t *lfs, const struct lfs_config *cfg) {\n    int err = 0;\n    {\n        err = lfs_init(lfs, cfg);\n        if (err) {\n            return err;\n        }\n\n        LFS_ASSERT(cfg->block_count != 0);\n\n        // create free lookahead\n        memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size);\n        lfs->lookahead.start = 0;\n        lfs->lookahead.size = lfs_min(8*lfs->cfg->lookahead_size,\n                lfs->block_count);\n        lfs->lookahead.next = 0;\n        lfs_alloc_ckpoint(lfs);\n\n        // create root dir\n        lfs_mdir_t root;\n        err = lfs_dir_alloc(lfs, &root);\n        if (err) {\n            goto cleanup;\n        }\n\n        // write one superblock\n        lfs_superblock_t superblock = {\n            .version     = lfs_fs_disk_version(lfs),\n            .block_size  = lfs->cfg->block_size,\n            .block_count = lfs->block_count,\n            .name_max    = lfs->name_max,\n            .file_max    = lfs->file_max,\n            .attr_max    = lfs->attr_max,\n        };\n\n        lfs_superblock_tole32(&superblock);\n        err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(\n                {LFS_MKTAG(LFS_TYPE_CREATE, 0, 0), NULL},\n                {LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), \"littlefs\"},\n                {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),\n                    &superblock}));\n        if (err) {\n            goto cleanup;\n        }\n\n        // force compaction to prevent accidentally mounting any\n        // older version of littlefs that may live on disk\n        root.erased = false;\n        err = lfs_dir_commit(lfs, &root, NULL, 0);\n        if (err) {\n            goto cleanup;\n        }\n\n        // sanity check that fetch works\n        err = lfs_dir_fetch(lfs, &root, (const lfs_block_t[2]){0, 1});\n        if (err) {\n            goto cleanup;\n        }\n    }\n\ncleanup:\n    lfs_deinit(lfs);\n    return err;\n\n}\n#endif\n\nstruct lfs_tortoise_t {\n    lfs_block_t pair[2];\n    lfs_size_t i;\n    lfs_size_t period;\n};\n\nstatic int lfs_tortoise_detectcycles(\n    const lfs_mdir_t *dir, struct lfs_tortoise_t *tortoise) {\n    // detect cycles with Brent's algorithm\n    if (lfs_pair_issync(dir->tail, tortoise->pair)) {\n        LFS_WARN(\"Cycle detected in tail list\");\n        return LFS_ERR_CORRUPT;\n    }\n    if (tortoise->i == tortoise->period) {\n        tortoise->pair[0] = dir->tail[0];\n        tortoise->pair[1] = dir->tail[1];\n        tortoise->i = 0;\n        tortoise->period *= 2;\n    }\n    tortoise->i += 1;\n\n    return LFS_ERR_OK;\n}\n\nstatic int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) {\n    int err = lfs_init(lfs, cfg);\n    if (err) {\n        return err;\n    }\n\n    // scan directory blocks for superblock and any global updates\n    lfs_mdir_t dir = {.tail = {0, 1}};\n    struct lfs_tortoise_t tortoise = {\n        .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL},\n        .i = 1,\n        .period = 1,\n    };\n    while (!lfs_pair_isnull(dir.tail)) {\n        err = lfs_tortoise_detectcycles(&dir, &tortoise);\n        if (err < 0) {\n            goto cleanup;\n        }\n\n        // fetch next block in tail list\n        lfs_stag_t tag = lfs_dir_fetchmatch(lfs, &dir, dir.tail,\n                LFS_MKTAG(0x7ff, 0x3ff, 0),\n                LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8),\n                NULL,\n                lfs_dir_find_match, &(struct lfs_dir_find_match){\n                    lfs, \"littlefs\", 8});\n        if (tag < 0) {\n            err = tag;\n            goto cleanup;\n        }\n\n        // has superblock?\n        if (tag && !lfs_tag_isdelete(tag)) {\n            // update root\n            lfs->root[0] = dir.pair[0];\n            lfs->root[1] = dir.pair[1];\n\n            // grab superblock\n            lfs_superblock_t superblock;\n            tag = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x7ff, 0x3ff, 0),\n                    LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),\n                    &superblock);\n            if (tag < 0) {\n                err = tag;\n                goto cleanup;\n            }\n            lfs_superblock_fromle32(&superblock);\n\n            // check version\n            uint16_t major_version = (0xffff & (superblock.version >> 16));\n            uint16_t minor_version = (0xffff & (superblock.version >>  0));\n            if (major_version != lfs_fs_disk_version_major(lfs)\n                    || minor_version > lfs_fs_disk_version_minor(lfs)) {\n                LFS_ERROR(\"Invalid version \"\n                        \"v%\"PRIu16\".%\"PRIu16\" != v%\"PRIu16\".%\"PRIu16,\n                        major_version,\n                        minor_version,\n                        lfs_fs_disk_version_major(lfs),\n                        lfs_fs_disk_version_minor(lfs));\n                err = LFS_ERR_INVAL;\n                goto cleanup;\n            }\n\n            // found older minor version? set an in-device only bit in the\n            // gstate so we know we need to rewrite the superblock before\n            // the first write\n            bool needssuperblock = false;\n            if (minor_version < lfs_fs_disk_version_minor(lfs)) {\n                LFS_DEBUG(\"Found older minor version \"\n                        \"v%\"PRIu16\".%\"PRIu16\" < v%\"PRIu16\".%\"PRIu16,\n                        major_version,\n                        minor_version,\n                        lfs_fs_disk_version_major(lfs),\n                        lfs_fs_disk_version_minor(lfs));\n                needssuperblock = true;\n            }\n            // note this bit is reserved on disk, so fetching more gstate\n            // will not interfere here\n            lfs_fs_prepsuperblock(lfs, needssuperblock);\n\n            // check superblock configuration\n            if (superblock.name_max) {\n                if (superblock.name_max > lfs->name_max) {\n                    LFS_ERROR(\"Unsupported name_max (%\"PRIu32\" > %\"PRIu32\")\",\n                            superblock.name_max, lfs->name_max);\n                    err = LFS_ERR_INVAL;\n                    goto cleanup;\n                }\n\n                lfs->name_max = superblock.name_max;\n            }\n\n            if (superblock.file_max) {\n                if (superblock.file_max > lfs->file_max) {\n                    LFS_ERROR(\"Unsupported file_max (%\"PRIu32\" > %\"PRIu32\")\",\n                            superblock.file_max, lfs->file_max);\n                    err = LFS_ERR_INVAL;\n                    goto cleanup;\n                }\n\n                lfs->file_max = superblock.file_max;\n            }\n\n            if (superblock.attr_max) {\n                if (superblock.attr_max > lfs->attr_max) {\n                    LFS_ERROR(\"Unsupported attr_max (%\"PRIu32\" > %\"PRIu32\")\",\n                            superblock.attr_max, lfs->attr_max);\n                    err = LFS_ERR_INVAL;\n                    goto cleanup;\n                }\n\n                lfs->attr_max = superblock.attr_max;\n\n                // we also need to update inline_max in case attr_max changed\n                lfs->inline_max = lfs_min(lfs->inline_max, lfs->attr_max);\n            }\n\n            // this is where we get the block_count from disk if block_count=0\n            if (lfs->cfg->block_count\n                    && superblock.block_count != lfs->cfg->block_count) {\n                LFS_ERROR(\"Invalid block count (%\"PRIu32\" != %\"PRIu32\")\",\n                        superblock.block_count, lfs->cfg->block_count);\n                err = LFS_ERR_INVAL;\n                goto cleanup;\n            }\n\n            lfs->block_count = superblock.block_count;\n\n            if (superblock.block_size != lfs->cfg->block_size) {\n                LFS_ERROR(\"Invalid block size (%\"PRIu32\" != %\"PRIu32\")\",\n                        superblock.block_size, lfs->cfg->block_size);\n                err = LFS_ERR_INVAL;\n                goto cleanup;\n            }\n        }\n\n        // has gstate?\n        err = lfs_dir_getgstate(lfs, &dir, &lfs->gstate);\n        if (err) {\n            goto cleanup;\n        }\n    }\n\n    // update littlefs with gstate\n    if (!lfs_gstate_iszero(&lfs->gstate)) {\n        LFS_DEBUG(\"Found pending gstate 0x%08\"PRIx32\"%08\"PRIx32\"%08\"PRIx32,\n                lfs->gstate.tag,\n                lfs->gstate.pair[0],\n                lfs->gstate.pair[1]);\n    }\n    lfs->gstate.tag += !lfs_tag_isvalid(lfs->gstate.tag);\n    lfs->gdisk = lfs->gstate;\n\n    // setup free lookahead, to distribute allocations uniformly across\n    // boots, we start the allocator at a random location\n    lfs->lookahead.start = lfs->seed % lfs->block_count;\n    lfs_alloc_drop(lfs);\n\n    return 0;\n\ncleanup:\n    lfs_unmount_(lfs);\n    return err;\n}\n\nstatic int lfs_unmount_(lfs_t *lfs) {\n    return lfs_deinit(lfs);\n}\n\n\n/// Filesystem filesystem operations ///\nstatic int lfs_fs_stat_(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {\n    // if the superblock is up-to-date, we must be on the most recent\n    // minor version of littlefs\n    if (!lfs_gstate_needssuperblock(&lfs->gstate)) {\n        fsinfo->disk_version = lfs_fs_disk_version(lfs);\n\n    // otherwise we need to read the minor version on disk\n    } else {\n        // fetch the superblock\n        lfs_mdir_t dir;\n        int err = lfs_dir_fetch(lfs, &dir, lfs->root);\n        if (err) {\n            return err;\n        }\n\n        lfs_superblock_t superblock;\n        lfs_stag_t tag = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x7ff, 0x3ff, 0),\n                LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),\n                &superblock);\n        if (tag < 0) {\n            return tag;\n        }\n        lfs_superblock_fromle32(&superblock);\n\n        // read the on-disk version\n        fsinfo->disk_version = superblock.version;\n    }\n\n    // filesystem geometry\n    fsinfo->block_size = lfs->cfg->block_size;\n    fsinfo->block_count = lfs->block_count;\n\n    // other on-disk configuration, we cache all of these for internal use\n    fsinfo->name_max = lfs->name_max;\n    fsinfo->file_max = lfs->file_max;\n    fsinfo->attr_max = lfs->attr_max;\n\n    return 0;\n}\n\nint lfs_fs_traverse_(lfs_t *lfs,\n        int (*cb)(void *data, lfs_block_t block), void *data,\n        bool includeorphans) {\n    // iterate over metadata pairs\n    lfs_mdir_t dir = {.tail = {0, 1}};\n\n#ifdef LFS_MIGRATE\n    // also consider v1 blocks during migration\n    if (lfs->lfs1) {\n        int err = lfs1_traverse(lfs, cb, data);\n        if (err) {\n            return err;\n        }\n\n        dir.tail[0] = lfs->root[0];\n        dir.tail[1] = lfs->root[1];\n    }\n#endif\n\n    struct lfs_tortoise_t tortoise = {\n        .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL},\n        .i = 1,\n        .period = 1,\n    };\n    int err = LFS_ERR_OK;\n    while (!lfs_pair_isnull(dir.tail)) {\n        err = lfs_tortoise_detectcycles(&dir, &tortoise);\n        if (err < 0) {\n            return LFS_ERR_CORRUPT;\n        }\n\n        for (int i = 0; i < 2; i++) {\n            int err = cb(data, dir.tail[i]);\n            if (err) {\n                return err;\n            }\n        }\n\n        // iterate through ids in directory\n        int err = lfs_dir_fetch(lfs, &dir, dir.tail);\n        if (err) {\n            return err;\n        }\n\n        for (uint16_t id = 0; id < dir.count; id++) {\n            struct lfs_ctz ctz;\n            lfs_stag_t tag = lfs_dir_get(lfs, &dir, LFS_MKTAG(0x700, 0x3ff, 0),\n                    LFS_MKTAG(LFS_TYPE_STRUCT, id, sizeof(ctz)), &ctz);\n            if (tag < 0) {\n                if (tag == LFS_ERR_NOENT) {\n                    continue;\n                }\n                return tag;\n            }\n            lfs_ctz_fromle32(&ctz);\n\n            if (lfs_tag_type3(tag) == LFS_TYPE_CTZSTRUCT) {\n                err = lfs_ctz_traverse(lfs, NULL, &lfs->rcache,\n                        ctz.head, ctz.size, cb, data);\n                if (err) {\n                    return err;\n                }\n            } else if (includeorphans &&\n                    lfs_tag_type3(tag) == LFS_TYPE_DIRSTRUCT) {\n                for (int i = 0; i < 2; i++) {\n                    err = cb(data, (&ctz.head)[i]);\n                    if (err) {\n                        return err;\n                    }\n                }\n            }\n        }\n    }\n\n#ifndef LFS_READONLY\n    // iterate over any open files\n    for (lfs_file_t *f = (lfs_file_t*)lfs->mlist; f; f = f->next) {\n        if (f->type != LFS_TYPE_REG) {\n            continue;\n        }\n\n        if ((f->flags & LFS_F_DIRTY) && !(f->flags & LFS_F_INLINE)) {\n            int err = lfs_ctz_traverse(lfs, &f->cache, &lfs->rcache,\n                    f->ctz.head, f->ctz.size, cb, data);\n            if (err) {\n                return err;\n            }\n        }\n\n        if ((f->flags & LFS_F_WRITING) && !(f->flags & LFS_F_INLINE)) {\n            int err = lfs_ctz_traverse(lfs, &f->cache, &lfs->rcache,\n                    f->block, f->pos, cb, data);\n            if (err) {\n                return err;\n            }\n        }\n    }\n#endif\n\n    return 0;\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_pred(lfs_t *lfs,\n        const lfs_block_t pair[2], lfs_mdir_t *pdir) {\n    // iterate over all directory directory entries\n    pdir->tail[0] = 0;\n    pdir->tail[1] = 1;\n    struct lfs_tortoise_t tortoise = {\n        .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL},\n        .i = 1,\n        .period = 1,\n    };\n    int err = LFS_ERR_OK;\n    while (!lfs_pair_isnull(pdir->tail)) {\n        err = lfs_tortoise_detectcycles(pdir, &tortoise);\n        if (err < 0) {\n            return LFS_ERR_CORRUPT;\n        }\n\n        if (lfs_pair_cmp(pdir->tail, pair) == 0) {\n            return 0;\n        }\n\n        int err = lfs_dir_fetch(lfs, pdir, pdir->tail);\n        if (err) {\n            return err;\n        }\n    }\n\n    return LFS_ERR_NOENT;\n}\n#endif\n\n#ifndef LFS_READONLY\nstruct lfs_fs_parent_match {\n    lfs_t *lfs;\n    const lfs_block_t pair[2];\n};\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_parent_match(void *data,\n        lfs_tag_t tag, const void *buffer) {\n    struct lfs_fs_parent_match *find = data;\n    lfs_t *lfs = find->lfs;\n    const struct lfs_diskoff *disk = buffer;\n    (void)tag;\n\n    lfs_block_t child[2];\n    int err = lfs_bd_read(lfs,\n            &lfs->pcache, &lfs->rcache, lfs->cfg->block_size,\n            disk->block, disk->off, &child, sizeof(child));\n    if (err) {\n        return err;\n    }\n\n    lfs_pair_fromle32(child);\n    return (lfs_pair_cmp(child, find->pair) == 0) ? LFS_CMP_EQ : LFS_CMP_LT;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2],\n        lfs_mdir_t *parent) {\n    // use fetchmatch with callback to find pairs\n    parent->tail[0] = 0;\n    parent->tail[1] = 1;\n    struct lfs_tortoise_t tortoise = {\n        .pair = {LFS_BLOCK_NULL, LFS_BLOCK_NULL},\n        .i = 1,\n        .period = 1,\n    };\n    int err = LFS_ERR_OK;\n    while (!lfs_pair_isnull(parent->tail)) {\n        err = lfs_tortoise_detectcycles(parent, &tortoise);\n        if (err < 0) {\n            return err;\n        }\n\n        lfs_stag_t tag = lfs_dir_fetchmatch(lfs, parent, parent->tail,\n                LFS_MKTAG(0x7ff, 0, 0x3ff),\n                LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, 8),\n                NULL,\n                lfs_fs_parent_match, &(struct lfs_fs_parent_match){\n                    lfs, {pair[0], pair[1]}});\n        if (tag && tag != LFS_ERR_NOENT) {\n            return tag;\n        }\n    }\n\n    return LFS_ERR_NOENT;\n}\n#endif\n\nstatic void lfs_fs_prepsuperblock(lfs_t *lfs, bool needssuperblock) {\n    lfs->gstate.tag = (lfs->gstate.tag & ~LFS_MKTAG(0, 0, 0x200))\n            | (uint32_t)needssuperblock << 9;\n}\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_preporphans(lfs_t *lfs, int8_t orphans) {\n    LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0x000 || orphans >= 0);\n    LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) < 0x1ff || orphans <= 0);\n    lfs->gstate.tag += orphans;\n    lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x800, 0, 0)) |\n            ((uint32_t)lfs_gstate_hasorphans(&lfs->gstate) << 31));\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic void lfs_fs_prepmove(lfs_t *lfs,\n        uint16_t id, const lfs_block_t pair[2]) {\n    lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x7ff, 0x3ff, 0)) |\n            ((id != 0x3ff) ? LFS_MKTAG(LFS_TYPE_DELETE, id, 0) : 0));\n    lfs->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0;\n    lfs->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_desuperblock(lfs_t *lfs) {\n    if (!lfs_gstate_needssuperblock(&lfs->gstate)) {\n        return 0;\n    }\n\n    LFS_DEBUG(\"Rewriting superblock {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n            lfs->root[0],\n            lfs->root[1]);\n\n    lfs_mdir_t root;\n    int err = lfs_dir_fetch(lfs, &root, lfs->root);\n    if (err) {\n        return err;\n    }\n\n    // write a new superblock\n    lfs_superblock_t superblock = {\n        .version     = lfs_fs_disk_version(lfs),\n        .block_size  = lfs->cfg->block_size,\n        .block_count = lfs->block_count,\n        .name_max    = lfs->name_max,\n        .file_max    = lfs->file_max,\n        .attr_max    = lfs->attr_max,\n    };\n\n    lfs_superblock_tole32(&superblock);\n    err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(\n            {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),\n                &superblock}));\n    if (err) {\n        return err;\n    }\n\n    lfs_fs_prepsuperblock(lfs, false);\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_demove(lfs_t *lfs) {\n    if (!lfs_gstate_hasmove(&lfs->gdisk)) {\n        return 0;\n    }\n\n    // Fix bad moves\n    LFS_DEBUG(\"Fixing move {0x%\"PRIx32\", 0x%\"PRIx32\"} 0x%\"PRIx16,\n            lfs->gdisk.pair[0],\n            lfs->gdisk.pair[1],\n            lfs_tag_id(lfs->gdisk.tag));\n\n    // no other gstate is supported at this time, so if we found something else\n    // something most likely went wrong in gstate calculation\n    LFS_ASSERT(lfs_tag_type3(lfs->gdisk.tag) == LFS_TYPE_DELETE);\n\n    // fetch and delete the moved entry\n    lfs_mdir_t movedir;\n    int err = lfs_dir_fetch(lfs, &movedir, lfs->gdisk.pair);\n    if (err) {\n        return err;\n    }\n\n    // prep gstate and delete move id\n    uint16_t moveid = lfs_tag_id(lfs->gdisk.tag);\n    lfs_fs_prepmove(lfs, 0x3ff, NULL);\n    err = lfs_dir_commit(lfs, &movedir, LFS_MKATTRS(\n            {LFS_MKTAG(LFS_TYPE_DELETE, moveid, 0), NULL}));\n    if (err) {\n        return err;\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_deorphan(lfs_t *lfs, bool powerloss) {\n    if (!lfs_gstate_hasorphans(&lfs->gstate)) {\n        return 0;\n    }\n\n    // Check for orphans in two separate passes:\n    // - 1 for half-orphans (relocations)\n    // - 2 for full-orphans (removes/renames)\n    //\n    // Two separate passes are needed as half-orphans can contain outdated\n    // references to full-orphans, effectively hiding them from the deorphan\n    // search.\n    //\n    int pass = 0;\n    while (pass < 2) {\n        // Fix any orphans\n        lfs_mdir_t pdir = {.split = true, .tail = {0, 1}};\n        lfs_mdir_t dir;\n        bool moreorphans = false;\n\n        // iterate over all directory directory entries\n        while (!lfs_pair_isnull(pdir.tail)) {\n            int err = lfs_dir_fetch(lfs, &dir, pdir.tail);\n            if (err) {\n                return err;\n            }\n\n            // check head blocks for orphans\n            if (!pdir.split) {\n                // check if we have a parent\n                lfs_mdir_t parent;\n                lfs_stag_t tag = lfs_fs_parent(lfs, pdir.tail, &parent);\n                if (tag < 0 && tag != LFS_ERR_NOENT) {\n                    return tag;\n                }\n\n                if (pass == 0 && tag != LFS_ERR_NOENT) {\n                    lfs_block_t pair[2];\n                    lfs_stag_t state = lfs_dir_get(lfs, &parent,\n                            LFS_MKTAG(0x7ff, 0x3ff, 0), tag, pair);\n                    if (state < 0) {\n                        return state;\n                    }\n                    lfs_pair_fromle32(pair);\n\n                    if (!lfs_pair_issync(pair, pdir.tail)) {\n                        // we have desynced\n                        LFS_DEBUG(\"Fixing half-orphan \"\n                                \"{0x%\"PRIx32\", 0x%\"PRIx32\"} \"\n                                \"-> {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n                                pdir.tail[0], pdir.tail[1], pair[0], pair[1]);\n\n                        // fix pending move in this pair? this looks like an\n                        // optimization but is in fact _required_ since\n                        // relocating may outdate the move.\n                        uint16_t moveid = 0x3ff;\n                        if (lfs_gstate_hasmovehere(&lfs->gstate, pdir.pair)) {\n                            moveid = lfs_tag_id(lfs->gstate.tag);\n                            LFS_DEBUG(\"Fixing move while fixing orphans \"\n                                    \"{0x%\"PRIx32\", 0x%\"PRIx32\"} 0x%\"PRIx16\"\\n\",\n                                    pdir.pair[0], pdir.pair[1], moveid);\n                            lfs_fs_prepmove(lfs, 0x3ff, NULL);\n                        }\n\n                        lfs_pair_tole32(pair);\n                        state = lfs_dir_orphaningcommit(lfs, &pdir, LFS_MKATTRS(\n                                {LFS_MKTAG_IF(moveid != 0x3ff,\n                                    LFS_TYPE_DELETE, moveid, 0), NULL},\n                                {LFS_MKTAG(LFS_TYPE_SOFTTAIL, 0x3ff, 8),\n                                    pair}));\n                        lfs_pair_fromle32(pair);\n                        if (state < 0) {\n                            return state;\n                        }\n\n                        // did our commit create more orphans?\n                        if (state == LFS_OK_ORPHANED) {\n                            moreorphans = true;\n                        }\n\n                        // refetch tail\n                        continue;\n                    }\n                }\n\n                // note we only check for full orphans if we may have had a\n                // power-loss, otherwise orphans are created intentionally\n                // during operations such as lfs_mkdir\n                if (pass == 1 && tag == LFS_ERR_NOENT && powerloss) {\n                    // we are an orphan\n                    LFS_DEBUG(\"Fixing orphan {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n                            pdir.tail[0], pdir.tail[1]);\n\n                    // steal state\n                    err = lfs_dir_getgstate(lfs, &dir, &lfs->gdelta);\n                    if (err) {\n                        return err;\n                    }\n\n                    // steal tail\n                    lfs_pair_tole32(dir.tail);\n                    int state = lfs_dir_orphaningcommit(lfs, &pdir, LFS_MKATTRS(\n                            {LFS_MKTAG(LFS_TYPE_TAIL + dir.split, 0x3ff, 8),\n                                dir.tail}));\n                    lfs_pair_fromle32(dir.tail);\n                    if (state < 0) {\n                        return state;\n                    }\n\n                    // did our commit create more orphans?\n                    if (state == LFS_OK_ORPHANED) {\n                        moreorphans = true;\n                    }\n\n                    // refetch tail\n                    continue;\n                }\n            }\n\n            pdir = dir;\n        }\n\n        pass = moreorphans ? 0 : pass+1;\n    }\n\n    // mark orphans as fixed\n    return lfs_fs_preporphans(lfs, -lfs_gstate_getorphans(&lfs->gstate));\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_forceconsistency(lfs_t *lfs) {\n    int err = lfs_fs_desuperblock(lfs);\n    if (err) {\n        return err;\n    }\n\n    err = lfs_fs_demove(lfs);\n    if (err) {\n        return err;\n    }\n\n    err = lfs_fs_deorphan(lfs, true);\n    if (err) {\n        return err;\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_mkconsistent_(lfs_t *lfs) {\n    // lfs_fs_forceconsistency does most of the work here\n    int err = lfs_fs_forceconsistency(lfs);\n    if (err) {\n        return err;\n    }\n\n    // do we have any pending gstate?\n    lfs_gstate_t delta = {0};\n    lfs_gstate_xor(&delta, &lfs->gdisk);\n    lfs_gstate_xor(&delta, &lfs->gstate);\n    if (!lfs_gstate_iszero(&delta)) {\n        // lfs_dir_commit will implicitly write out any pending gstate\n        lfs_mdir_t root;\n        err = lfs_dir_fetch(lfs, &root, lfs->root);\n        if (err) {\n            return err;\n        }\n\n        err = lfs_dir_commit(lfs, &root, NULL, 0);\n        if (err) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n#endif\n\nstatic int lfs_fs_size_count(void *p, lfs_block_t block) {\n    (void)block;\n    lfs_size_t *size = p;\n    *size += 1;\n    return 0;\n}\n\nstatic lfs_ssize_t lfs_fs_size_(lfs_t *lfs) {\n    lfs_size_t size = 0;\n    int err = lfs_fs_traverse_(lfs, lfs_fs_size_count, &size, false);\n    if (err) {\n        return err;\n    }\n\n    return size;\n}\n\n// explicit garbage collection\n#ifndef LFS_READONLY\nstatic int lfs_fs_gc_(lfs_t *lfs) {\n    // force consistency, even if we're not necessarily going to write,\n    // because this function is supposed to take care of janitorial work\n    // isn't it?\n    int err = lfs_fs_forceconsistency(lfs);\n    if (err) {\n        return err;\n    }\n\n    // try to compact metadata pairs, note we can't really accomplish\n    // anything if compact_thresh doesn't at least leave a prog_size\n    // available\n    if (lfs->cfg->compact_thresh\n            < lfs->cfg->block_size - lfs->cfg->prog_size) {\n        // iterate over all mdirs\n        lfs_mdir_t mdir = {.tail = {0, 1}};\n        while (!lfs_pair_isnull(mdir.tail)) {\n            err = lfs_dir_fetch(lfs, &mdir, mdir.tail);\n            if (err) {\n                return err;\n            }\n\n            // not erased? exceeds our compaction threshold?\n            if (!mdir.erased || ((lfs->cfg->compact_thresh == 0)\n                    ? mdir.off > lfs->cfg->block_size - lfs->cfg->block_size/8\n                    : mdir.off > lfs->cfg->compact_thresh)) {\n                // the easiest way to trigger a compaction is to mark\n                // the mdir as unerased and add an empty commit\n                mdir.erased = false;\n                err = lfs_dir_commit(lfs, &mdir, NULL, 0);\n                if (err) {\n                    return err;\n                }\n            }\n        }\n    }\n\n    // try to populate the lookahead buffer, unless it's already full\n    if (lfs->lookahead.size < 8*lfs->cfg->lookahead_size) {\n        err = lfs_alloc_scan(lfs);\n        if (err) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n#endif\n\n#ifndef LFS_READONLY\nstatic int lfs_fs_grow_(lfs_t *lfs, lfs_size_t block_count) {\n    // shrinking is not supported\n    LFS_ASSERT(block_count >= lfs->block_count);\n\n    if (block_count > lfs->block_count) {\n        lfs->block_count = block_count;\n\n        // fetch the root\n        lfs_mdir_t root;\n        int err = lfs_dir_fetch(lfs, &root, lfs->root);\n        if (err) {\n            return err;\n        }\n\n        // update the superblock\n        lfs_superblock_t superblock;\n        lfs_stag_t tag = lfs_dir_get(lfs, &root, LFS_MKTAG(0x7ff, 0x3ff, 0),\n                LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),\n                &superblock);\n        if (tag < 0) {\n            return tag;\n        }\n        lfs_superblock_fromle32(&superblock);\n\n        superblock.block_count = lfs->block_count;\n\n        lfs_superblock_tole32(&superblock);\n        err = lfs_dir_commit(lfs, &root, LFS_MKATTRS(\n                {tag, &superblock}));\n        if (err) {\n            return err;\n        }\n    }\n\n    return 0;\n}\n#endif\n\n#ifdef LFS_MIGRATE\n////// Migration from littelfs v1 below this //////\n\n/// Version info ///\n\n// Software library version\n// Major (top-nibble), incremented on backwards incompatible changes\n// Minor (bottom-nibble), incremented on feature additions\n#define LFS1_VERSION 0x00010007\n#define LFS1_VERSION_MAJOR (0xffff & (LFS1_VERSION >> 16))\n#define LFS1_VERSION_MINOR (0xffff & (LFS1_VERSION >>  0))\n\n// Version of On-disk data structures\n// Major (top-nibble), incremented on backwards incompatible changes\n// Minor (bottom-nibble), incremented on feature additions\n#define LFS1_DISK_VERSION 0x00010001\n#define LFS1_DISK_VERSION_MAJOR (0xffff & (LFS1_DISK_VERSION >> 16))\n#define LFS1_DISK_VERSION_MINOR (0xffff & (LFS1_DISK_VERSION >>  0))\n\n\n/// v1 Definitions ///\n\n// File types\nenum lfs1_type {\n    LFS1_TYPE_REG        = 0x11,\n    LFS1_TYPE_DIR        = 0x22,\n    LFS1_TYPE_SUPERBLOCK = 0x2e,\n};\n\ntypedef struct lfs1 {\n    lfs_block_t root[2];\n} lfs1_t;\n\ntypedef struct lfs1_entry {\n    lfs_off_t off;\n\n    struct lfs1_disk_entry {\n        uint8_t type;\n        uint8_t elen;\n        uint8_t alen;\n        uint8_t nlen;\n        union {\n            struct {\n                lfs_block_t head;\n                lfs_size_t size;\n            } file;\n            lfs_block_t dir[2];\n        } u;\n    } d;\n} lfs1_entry_t;\n\ntypedef struct lfs1_dir {\n    struct lfs1_dir *next;\n    lfs_block_t pair[2];\n    lfs_off_t off;\n\n    lfs_block_t head[2];\n    lfs_off_t pos;\n\n    struct lfs1_disk_dir {\n        uint32_t rev;\n        lfs_size_t size;\n        lfs_block_t tail[2];\n    } d;\n} lfs1_dir_t;\n\ntypedef struct lfs1_superblock {\n    lfs_off_t off;\n\n    struct lfs1_disk_superblock {\n        uint8_t type;\n        uint8_t elen;\n        uint8_t alen;\n        uint8_t nlen;\n        lfs_block_t root[2];\n        uint32_t block_size;\n        uint32_t block_count;\n        uint32_t version;\n        char magic[8];\n    } d;\n} lfs1_superblock_t;\n\n\n/// Low-level wrappers v1->v2 ///\nstatic void lfs1_crc(uint32_t *crc, const void *buffer, size_t size) {\n    *crc = lfs_crc(*crc, buffer, size);\n}\n\nstatic int lfs1_bd_read(lfs_t *lfs, lfs_block_t block,\n        lfs_off_t off, void *buffer, lfs_size_t size) {\n    // if we ever do more than writes to alternating pairs,\n    // this may need to consider pcache\n    return lfs_bd_read(lfs, &lfs->pcache, &lfs->rcache, size,\n            block, off, buffer, size);\n}\n\nstatic int lfs1_bd_crc(lfs_t *lfs, lfs_block_t block,\n        lfs_off_t off, lfs_size_t size, uint32_t *crc) {\n    for (lfs_off_t i = 0; i < size; i++) {\n        uint8_t c;\n        int err = lfs1_bd_read(lfs, block, off+i, &c, 1);\n        if (err) {\n            return err;\n        }\n\n        lfs1_crc(crc, &c, 1);\n    }\n\n    return 0;\n}\n\n\n/// Endian swapping functions ///\nstatic void lfs1_dir_fromle32(struct lfs1_disk_dir *d) {\n    d->rev     = lfs_fromle32(d->rev);\n    d->size    = lfs_fromle32(d->size);\n    d->tail[0] = lfs_fromle32(d->tail[0]);\n    d->tail[1] = lfs_fromle32(d->tail[1]);\n}\n\nstatic void lfs1_dir_tole32(struct lfs1_disk_dir *d) {\n    d->rev     = lfs_tole32(d->rev);\n    d->size    = lfs_tole32(d->size);\n    d->tail[0] = lfs_tole32(d->tail[0]);\n    d->tail[1] = lfs_tole32(d->tail[1]);\n}\n\nstatic void lfs1_entry_fromle32(struct lfs1_disk_entry *d) {\n    d->u.dir[0] = lfs_fromle32(d->u.dir[0]);\n    d->u.dir[1] = lfs_fromle32(d->u.dir[1]);\n}\n\nstatic void lfs1_entry_tole32(struct lfs1_disk_entry *d) {\n    d->u.dir[0] = lfs_tole32(d->u.dir[0]);\n    d->u.dir[1] = lfs_tole32(d->u.dir[1]);\n}\n\nstatic void lfs1_superblock_fromle32(struct lfs1_disk_superblock *d) {\n    d->root[0]     = lfs_fromle32(d->root[0]);\n    d->root[1]     = lfs_fromle32(d->root[1]);\n    d->block_size  = lfs_fromle32(d->block_size);\n    d->block_count = lfs_fromle32(d->block_count);\n    d->version     = lfs_fromle32(d->version);\n}\n\n\n///// Metadata pair and directory operations ///\nstatic inline lfs_size_t lfs1_entry_size(const lfs1_entry_t *entry) {\n    return 4 + entry->d.elen + entry->d.alen + entry->d.nlen;\n}\n\nstatic int lfs1_dir_fetch(lfs_t *lfs,\n        lfs1_dir_t *dir, const lfs_block_t pair[2]) {\n    // copy out pair, otherwise may be aliasing dir\n    const lfs_block_t tpair[2] = {pair[0], pair[1]};\n    bool valid = false;\n\n    // check both blocks for the most recent revision\n    for (int i = 0; i < 2; i++) {\n        struct lfs1_disk_dir test;\n        int err = lfs1_bd_read(lfs, tpair[i], 0, &test, sizeof(test));\n        lfs1_dir_fromle32(&test);\n        if (err) {\n            if (err == LFS_ERR_CORRUPT) {\n                continue;\n            }\n            return err;\n        }\n\n        if (valid && lfs_scmp(test.rev, dir->d.rev) < 0) {\n            continue;\n        }\n\n        if ((0x7fffffff & test.size) < sizeof(test)+4 ||\n            (0x7fffffff & test.size) > lfs->cfg->block_size) {\n            continue;\n        }\n\n        uint32_t crc = 0xffffffff;\n        lfs1_dir_tole32(&test);\n        lfs1_crc(&crc, &test, sizeof(test));\n        lfs1_dir_fromle32(&test);\n        err = lfs1_bd_crc(lfs, tpair[i], sizeof(test),\n                (0x7fffffff & test.size) - sizeof(test), &crc);\n        if (err) {\n            if (err == LFS_ERR_CORRUPT) {\n                continue;\n            }\n            return err;\n        }\n\n        if (crc != 0) {\n            continue;\n        }\n\n        valid = true;\n\n        // setup dir in case it's valid\n        dir->pair[0] = tpair[(i+0) % 2];\n        dir->pair[1] = tpair[(i+1) % 2];\n        dir->off = sizeof(dir->d);\n        dir->d = test;\n    }\n\n    if (!valid) {\n        LFS_ERROR(\"Corrupted dir pair at {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n                tpair[0], tpair[1]);\n        return LFS_ERR_CORRUPT;\n    }\n\n    return 0;\n}\n\nstatic int lfs1_dir_next(lfs_t *lfs, lfs1_dir_t *dir, lfs1_entry_t *entry) {\n    while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) {\n        if (!(0x80000000 & dir->d.size)) {\n            entry->off = dir->off;\n            return LFS_ERR_NOENT;\n        }\n\n        int err = lfs1_dir_fetch(lfs, dir, dir->d.tail);\n        if (err) {\n            return err;\n        }\n\n        dir->off = sizeof(dir->d);\n        dir->pos += sizeof(dir->d) + 4;\n    }\n\n    int err = lfs1_bd_read(lfs, dir->pair[0], dir->off,\n            &entry->d, sizeof(entry->d));\n    lfs1_entry_fromle32(&entry->d);\n    if (err) {\n        return err;\n    }\n\n    entry->off = dir->off;\n    dir->off += lfs1_entry_size(entry);\n    dir->pos += lfs1_entry_size(entry);\n    return 0;\n}\n\n/// littlefs v1 specific operations ///\nint lfs1_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {\n    if (lfs_pair_isnull(lfs->lfs1->root)) {\n        return 0;\n    }\n\n    // iterate over metadata pairs\n    lfs1_dir_t dir;\n    lfs1_entry_t entry;\n    lfs_block_t cwd[2] = {0, 1};\n\n    while (true) {\n        for (int i = 0; i < 2; i++) {\n            int err = cb(data, cwd[i]);\n            if (err) {\n                return err;\n            }\n        }\n\n        int err = lfs1_dir_fetch(lfs, &dir, cwd);\n        if (err) {\n            return err;\n        }\n\n        // iterate over contents\n        while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) {\n            err = lfs1_bd_read(lfs, dir.pair[0], dir.off,\n                    &entry.d, sizeof(entry.d));\n            lfs1_entry_fromle32(&entry.d);\n            if (err) {\n                return err;\n            }\n\n            dir.off += lfs1_entry_size(&entry);\n            if ((0x70 & entry.d.type) == (0x70 & LFS1_TYPE_REG)) {\n                err = lfs_ctz_traverse(lfs, NULL, &lfs->rcache,\n                        entry.d.u.file.head, entry.d.u.file.size, cb, data);\n                if (err) {\n                    return err;\n                }\n            }\n        }\n\n        // we also need to check if we contain a threaded v2 directory\n        lfs_mdir_t dir2 = {.split=true, .tail={cwd[0], cwd[1]}};\n        while (dir2.split) {\n            err = lfs_dir_fetch(lfs, &dir2, dir2.tail);\n            if (err) {\n                break;\n            }\n\n            for (int i = 0; i < 2; i++) {\n                err = cb(data, dir2.pair[i]);\n                if (err) {\n                    return err;\n                }\n            }\n        }\n\n        cwd[0] = dir.d.tail[0];\n        cwd[1] = dir.d.tail[1];\n\n        if (lfs_pair_isnull(cwd)) {\n            break;\n        }\n    }\n\n    return 0;\n}\n\nstatic int lfs1_moved(lfs_t *lfs, const void *e) {\n    if (lfs_pair_isnull(lfs->lfs1->root)) {\n        return 0;\n    }\n\n    // skip superblock\n    lfs1_dir_t cwd;\n    int err = lfs1_dir_fetch(lfs, &cwd, (const lfs_block_t[2]){0, 1});\n    if (err) {\n        return err;\n    }\n\n    // iterate over all directory directory entries\n    lfs1_entry_t entry;\n    while (!lfs_pair_isnull(cwd.d.tail)) {\n        err = lfs1_dir_fetch(lfs, &cwd, cwd.d.tail);\n        if (err) {\n            return err;\n        }\n\n        while (true) {\n            err = lfs1_dir_next(lfs, &cwd, &entry);\n            if (err && err != LFS_ERR_NOENT) {\n                return err;\n            }\n\n            if (err == LFS_ERR_NOENT) {\n                break;\n            }\n\n            if (!(0x80 & entry.d.type) &&\n                 memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) {\n                return true;\n            }\n        }\n    }\n\n    return false;\n}\n\n/// Filesystem operations ///\nstatic int lfs1_mount(lfs_t *lfs, struct lfs1 *lfs1,\n        const struct lfs_config *cfg) {\n    int err = 0;\n    {\n        err = lfs_init(lfs, cfg);\n        if (err) {\n            return err;\n        }\n\n        lfs->lfs1 = lfs1;\n        lfs->lfs1->root[0] = LFS_BLOCK_NULL;\n        lfs->lfs1->root[1] = LFS_BLOCK_NULL;\n\n        // setup free lookahead\n        lfs->lookahead.start = 0;\n        lfs->lookahead.size = 0;\n        lfs->lookahead.next = 0;\n        lfs_alloc_ckpoint(lfs);\n\n        // load superblock\n        lfs1_dir_t dir;\n        lfs1_superblock_t superblock;\n        err = lfs1_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});\n        if (err && err != LFS_ERR_CORRUPT) {\n            goto cleanup;\n        }\n\n        if (!err) {\n            err = lfs1_bd_read(lfs, dir.pair[0], sizeof(dir.d),\n                    &superblock.d, sizeof(superblock.d));\n            lfs1_superblock_fromle32(&superblock.d);\n            if (err) {\n                goto cleanup;\n            }\n\n            lfs->lfs1->root[0] = superblock.d.root[0];\n            lfs->lfs1->root[1] = superblock.d.root[1];\n        }\n\n        if (err || memcmp(superblock.d.magic, \"littlefs\", 8) != 0) {\n            LFS_ERROR(\"Invalid superblock at {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n                    0, 1);\n            err = LFS_ERR_CORRUPT;\n            goto cleanup;\n        }\n\n        uint16_t major_version = (0xffff & (superblock.d.version >> 16));\n        uint16_t minor_version = (0xffff & (superblock.d.version >>  0));\n        if ((major_version != LFS1_DISK_VERSION_MAJOR ||\n             minor_version > LFS1_DISK_VERSION_MINOR)) {\n            LFS_ERROR(\"Invalid version v%d.%d\", major_version, minor_version);\n            err = LFS_ERR_INVAL;\n            goto cleanup;\n        }\n\n        return 0;\n    }\n\ncleanup:\n    lfs_deinit(lfs);\n    return err;\n}\n\nstatic int lfs1_unmount(lfs_t *lfs) {\n    return lfs_deinit(lfs);\n}\n\n/// v1 migration ///\nstatic int lfs_migrate_(lfs_t *lfs, const struct lfs_config *cfg) {\n    struct lfs1 lfs1;\n\n    // Indeterminate filesystem size not allowed for migration.\n    LFS_ASSERT(cfg->block_count != 0);\n\n    int err = lfs1_mount(lfs, &lfs1, cfg);\n    if (err) {\n        return err;\n    }\n\n    {\n        // iterate through each directory, copying over entries\n        // into new directory\n        lfs1_dir_t dir1;\n        lfs_mdir_t dir2;\n        dir1.d.tail[0] = lfs->lfs1->root[0];\n        dir1.d.tail[1] = lfs->lfs1->root[1];\n        while (!lfs_pair_isnull(dir1.d.tail)) {\n            // iterate old dir\n            err = lfs1_dir_fetch(lfs, &dir1, dir1.d.tail);\n            if (err) {\n                goto cleanup;\n            }\n\n            // create new dir and bind as temporary pretend root\n            err = lfs_dir_alloc(lfs, &dir2);\n            if (err) {\n                goto cleanup;\n            }\n\n            dir2.rev = dir1.d.rev;\n            dir1.head[0] = dir1.pair[0];\n            dir1.head[1] = dir1.pair[1];\n            lfs->root[0] = dir2.pair[0];\n            lfs->root[1] = dir2.pair[1];\n\n            err = lfs_dir_commit(lfs, &dir2, NULL, 0);\n            if (err) {\n                goto cleanup;\n            }\n\n            while (true) {\n                lfs1_entry_t entry1;\n                err = lfs1_dir_next(lfs, &dir1, &entry1);\n                if (err && err != LFS_ERR_NOENT) {\n                    goto cleanup;\n                }\n\n                if (err == LFS_ERR_NOENT) {\n                    break;\n                }\n\n                // check that entry has not been moved\n                if (entry1.d.type & 0x80) {\n                    int moved = lfs1_moved(lfs, &entry1.d.u);\n                    if (moved < 0) {\n                        err = moved;\n                        goto cleanup;\n                    }\n\n                    if (moved) {\n                        continue;\n                    }\n\n                    entry1.d.type &= ~0x80;\n                }\n\n                // also fetch name\n                char name[LFS_NAME_MAX+1];\n                memset(name, 0, sizeof(name));\n                err = lfs1_bd_read(lfs, dir1.pair[0],\n                        entry1.off + 4+entry1.d.elen+entry1.d.alen,\n                        name, entry1.d.nlen);\n                if (err) {\n                    goto cleanup;\n                }\n\n                bool isdir = (entry1.d.type == LFS1_TYPE_DIR);\n\n                // create entry in new dir\n                err = lfs_dir_fetch(lfs, &dir2, lfs->root);\n                if (err) {\n                    goto cleanup;\n                }\n\n                uint16_t id;\n                err = lfs_dir_find(lfs, &dir2, &(const char*){name}, &id);\n                if (!(err == LFS_ERR_NOENT && id != 0x3ff)) {\n                    err = (err < 0) ? err : LFS_ERR_EXIST;\n                    goto cleanup;\n                }\n\n                lfs1_entry_tole32(&entry1.d);\n                err = lfs_dir_commit(lfs, &dir2, LFS_MKATTRS(\n                        {LFS_MKTAG(LFS_TYPE_CREATE, id, 0), NULL},\n                        {LFS_MKTAG_IF_ELSE(isdir,\n                            LFS_TYPE_DIR, id, entry1.d.nlen,\n                            LFS_TYPE_REG, id, entry1.d.nlen),\n                                name},\n                        {LFS_MKTAG_IF_ELSE(isdir,\n                            LFS_TYPE_DIRSTRUCT, id, sizeof(entry1.d.u),\n                            LFS_TYPE_CTZSTRUCT, id, sizeof(entry1.d.u)),\n                                &entry1.d.u}));\n                lfs1_entry_fromle32(&entry1.d);\n                if (err) {\n                    goto cleanup;\n                }\n            }\n\n            if (!lfs_pair_isnull(dir1.d.tail)) {\n                // find last block and update tail to thread into fs\n                err = lfs_dir_fetch(lfs, &dir2, lfs->root);\n                if (err) {\n                    goto cleanup;\n                }\n\n                while (dir2.split) {\n                    err = lfs_dir_fetch(lfs, &dir2, dir2.tail);\n                    if (err) {\n                        goto cleanup;\n                    }\n                }\n\n                lfs_pair_tole32(dir2.pair);\n                err = lfs_dir_commit(lfs, &dir2, LFS_MKATTRS(\n                        {LFS_MKTAG(LFS_TYPE_SOFTTAIL, 0x3ff, 8), dir1.d.tail}));\n                lfs_pair_fromle32(dir2.pair);\n                if (err) {\n                    goto cleanup;\n                }\n            }\n\n            // Copy over first block to thread into fs. Unfortunately\n            // if this fails there is not much we can do.\n            LFS_DEBUG(\"Migrating {0x%\"PRIx32\", 0x%\"PRIx32\"} \"\n                        \"-> {0x%\"PRIx32\", 0x%\"PRIx32\"}\",\n                    lfs->root[0], lfs->root[1], dir1.head[0], dir1.head[1]);\n\n            err = lfs_bd_erase(lfs, dir1.head[1]);\n            if (err) {\n                goto cleanup;\n            }\n\n            err = lfs_dir_fetch(lfs, &dir2, lfs->root);\n            if (err) {\n                goto cleanup;\n            }\n\n            for (lfs_off_t i = 0; i < dir2.off; i++) {\n                uint8_t dat;\n                err = lfs_bd_read(lfs,\n                        NULL, &lfs->rcache, dir2.off,\n                        dir2.pair[0], i, &dat, 1);\n                if (err) {\n                    goto cleanup;\n                }\n\n                err = lfs_bd_prog(lfs,\n                        &lfs->pcache, &lfs->rcache, true,\n                        dir1.head[1], i, &dat, 1);\n                if (err) {\n                    goto cleanup;\n                }\n            }\n\n            err = lfs_bd_flush(lfs, &lfs->pcache, &lfs->rcache, true);\n            if (err) {\n                goto cleanup;\n            }\n        }\n\n        // Create new superblock. This marks a successful migration!\n        err = lfs1_dir_fetch(lfs, &dir1, (const lfs_block_t[2]){0, 1});\n        if (err) {\n            goto cleanup;\n        }\n\n        dir2.pair[0] = dir1.pair[0];\n        dir2.pair[1] = dir1.pair[1];\n        dir2.rev = dir1.d.rev;\n        dir2.off = sizeof(dir2.rev);\n        dir2.etag = 0xffffffff;\n        dir2.count = 0;\n        dir2.tail[0] = lfs->lfs1->root[0];\n        dir2.tail[1] = lfs->lfs1->root[1];\n        dir2.erased = false;\n        dir2.split = true;\n\n        lfs_superblock_t superblock = {\n            .version     = LFS_DISK_VERSION,\n            .block_size  = lfs->cfg->block_size,\n            .block_count = lfs->cfg->block_count,\n            .name_max    = lfs->name_max,\n            .file_max    = lfs->file_max,\n            .attr_max    = lfs->attr_max,\n        };\n\n        lfs_superblock_tole32(&superblock);\n        err = lfs_dir_commit(lfs, &dir2, LFS_MKATTRS(\n                {LFS_MKTAG(LFS_TYPE_CREATE, 0, 0), NULL},\n                {LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), \"littlefs\"},\n                {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),\n                    &superblock}));\n        if (err) {\n            goto cleanup;\n        }\n\n        // sanity check that fetch works\n        err = lfs_dir_fetch(lfs, &dir2, (const lfs_block_t[2]){0, 1});\n        if (err) {\n            goto cleanup;\n        }\n\n        // force compaction to prevent accidentally mounting v1\n        dir2.erased = false;\n        err = lfs_dir_commit(lfs, &dir2, NULL, 0);\n        if (err) {\n            goto cleanup;\n        }\n    }\n\ncleanup:\n    lfs1_unmount(lfs);\n    return err;\n}\n\n#endif\n\n\n/// Public API wrappers ///\n\n// Here we can add tracing/thread safety easily\n\n// Thread-safe wrappers if enabled\n#ifdef LFS_THREADSAFE\n#define LFS_LOCK(cfg)   cfg->lock(cfg)\n#define LFS_UNLOCK(cfg) cfg->unlock(cfg)\n#else\n#define LFS_LOCK(cfg)   ((void)cfg, 0)\n#define LFS_UNLOCK(cfg) ((void)cfg)\n#endif\n\n// Public API\n#ifndef LFS_READONLY\nint lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {\n    int err = LFS_LOCK(cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_format(%p, %p {.context=%p, \"\n                \".read=%p, .prog=%p, .erase=%p, .sync=%p, \"\n                \".read_size=%\"PRIu32\", .prog_size=%\"PRIu32\", \"\n                \".block_size=%\"PRIu32\", .block_count=%\"PRIu32\", \"\n                \".block_cycles=%\"PRId32\", .cache_size=%\"PRIu32\", \"\n                \".lookahead_size=%\"PRIu32\", .read_buffer=%p, \"\n                \".prog_buffer=%p, .lookahead_buffer=%p, \"\n                \".name_max=%\"PRIu32\", .file_max=%\"PRIu32\", \"\n                \".attr_max=%\"PRIu32\"})\",\n            (void*)lfs, (void*)cfg, cfg->context,\n            (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,\n            (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,\n            cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,\n            cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,\n            cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,\n            cfg->name_max, cfg->file_max, cfg->attr_max);\n\n    err = lfs_format_(lfs, cfg);\n\n    LFS_TRACE(\"lfs_format -> %d\", err);\n    LFS_UNLOCK(cfg);\n    return err;\n}\n#endif\n\nint lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {\n    int err = LFS_LOCK(cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_mount(%p, %p {.context=%p, \"\n                \".read=%p, .prog=%p, .erase=%p, .sync=%p, \"\n                \".read_size=%\"PRIu32\", .prog_size=%\"PRIu32\", \"\n                \".block_size=%\"PRIu32\", .block_count=%\"PRIu32\", \"\n                \".block_cycles=%\"PRId32\", .cache_size=%\"PRIu32\", \"\n                \".lookahead_size=%\"PRIu32\", .read_buffer=%p, \"\n                \".prog_buffer=%p, .lookahead_buffer=%p, \"\n                \".name_max=%\"PRIu32\", .file_max=%\"PRIu32\", \"\n                \".attr_max=%\"PRIu32\"})\",\n            (void*)lfs, (void*)cfg, cfg->context,\n            (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,\n            (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,\n            cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,\n            cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,\n            cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,\n            cfg->name_max, cfg->file_max, cfg->attr_max);\n\n    err = lfs_mount_(lfs, cfg);\n\n    LFS_TRACE(\"lfs_mount -> %d\", err);\n    LFS_UNLOCK(cfg);\n    return err;\n}\n\nint lfs_unmount(lfs_t *lfs) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_unmount(%p)\", (void*)lfs);\n\n    err = lfs_unmount_(lfs);\n\n    LFS_TRACE(\"lfs_unmount -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\n#ifndef LFS_READONLY\nint lfs_remove(lfs_t *lfs, const char *path) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_remove(%p, \\\"%s\\\")\", (void*)lfs, path);\n\n    err = lfs_remove_(lfs, path);\n\n    LFS_TRACE(\"lfs_remove -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\n#ifndef LFS_READONLY\nint lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_rename(%p, \\\"%s\\\", \\\"%s\\\")\", (void*)lfs, oldpath, newpath);\n\n    err = lfs_rename_(lfs, oldpath, newpath);\n\n    LFS_TRACE(\"lfs_rename -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\nint lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_stat(%p, \\\"%s\\\", %p)\", (void*)lfs, path, (void*)info);\n\n    err = lfs_stat_(lfs, path, info);\n\n    LFS_TRACE(\"lfs_stat -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nlfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,\n        uint8_t type, void *buffer, lfs_size_t size) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_getattr(%p, \\\"%s\\\", %\"PRIu8\", %p, %\"PRIu32\")\",\n            (void*)lfs, path, type, buffer, size);\n\n    lfs_ssize_t res = lfs_getattr_(lfs, path, type, buffer, size);\n\n    LFS_TRACE(\"lfs_getattr -> %\"PRId32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n\n#ifndef LFS_READONLY\nint lfs_setattr(lfs_t *lfs, const char *path,\n        uint8_t type, const void *buffer, lfs_size_t size) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_setattr(%p, \\\"%s\\\", %\"PRIu8\", %p, %\"PRIu32\")\",\n            (void*)lfs, path, type, buffer, size);\n\n    err = lfs_setattr_(lfs, path, type, buffer, size);\n\n    LFS_TRACE(\"lfs_setattr -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\n#ifndef LFS_READONLY\nint lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_removeattr(%p, \\\"%s\\\", %\"PRIu8\")\", (void*)lfs, path, type);\n\n    err = lfs_removeattr_(lfs, path, type);\n\n    LFS_TRACE(\"lfs_removeattr -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\n#ifndef LFS_NO_MALLOC\nint lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_open(%p, %p, \\\"%s\\\", %x)\",\n            (void*)lfs, (void*)file, path, (unsigned)flags);\n    LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    err = lfs_file_open_(lfs, file, path, flags);\n\n    LFS_TRACE(\"lfs_file_open -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\nint lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,\n        const char *path, int flags,\n        const struct lfs_file_config *cfg) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_opencfg(%p, %p, \\\"%s\\\", %x, %p {\"\n                 \".buffer=%p, .attrs=%p, .attr_count=%\"PRIu32\"})\",\n            (void*)lfs, (void*)file, path, (unsigned)flags,\n            (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);\n    LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    err = lfs_file_opencfg_(lfs, file, path, flags, cfg);\n\n    LFS_TRACE(\"lfs_file_opencfg -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nint lfs_file_close(lfs_t *lfs, lfs_file_t *file) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_close(%p, %p)\", (void*)lfs, (void*)file);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    err = lfs_file_close_(lfs, file);\n\n    LFS_TRACE(\"lfs_file_close -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\n#ifndef LFS_READONLY\nint lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_sync(%p, %p)\", (void*)lfs, (void*)file);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    err = lfs_file_sync_(lfs, file);\n\n    LFS_TRACE(\"lfs_file_sync -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\nlfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,\n        void *buffer, lfs_size_t size) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_read(%p, %p, %p, %\"PRIu32\")\",\n            (void*)lfs, (void*)file, buffer, size);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    lfs_ssize_t res = lfs_file_read_(lfs, file, buffer, size);\n\n    LFS_TRACE(\"lfs_file_read -> %\"PRId32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n\n#ifndef LFS_READONLY\nlfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,\n        const void *buffer, lfs_size_t size) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_write(%p, %p, %p, %\"PRIu32\")\",\n            (void*)lfs, (void*)file, buffer, size);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    lfs_ssize_t res = lfs_file_write_(lfs, file, buffer, size);\n\n    LFS_TRACE(\"lfs_file_write -> %\"PRId32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n#endif\n\nlfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,\n        lfs_soff_t off, int whence) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_seek(%p, %p, %\"PRId32\", %d)\",\n            (void*)lfs, (void*)file, off, whence);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    lfs_soff_t res = lfs_file_seek_(lfs, file, off, whence);\n\n    LFS_TRACE(\"lfs_file_seek -> %\"PRId32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n\n#ifndef LFS_READONLY\nint lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_truncate(%p, %p, %\"PRIu32\")\",\n            (void*)lfs, (void*)file, size);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    err = lfs_file_truncate_(lfs, file, size);\n\n    LFS_TRACE(\"lfs_file_truncate -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\nlfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_tell(%p, %p)\", (void*)lfs, (void*)file);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    lfs_soff_t res = lfs_file_tell_(lfs, file);\n\n    LFS_TRACE(\"lfs_file_tell -> %\"PRId32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n\nint lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_rewind(%p, %p)\", (void*)lfs, (void*)file);\n\n    err = lfs_file_rewind_(lfs, file);\n\n    LFS_TRACE(\"lfs_file_rewind -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nlfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_file_size(%p, %p)\", (void*)lfs, (void*)file);\n    LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));\n\n    lfs_soff_t res = lfs_file_size_(lfs, file);\n\n    LFS_TRACE(\"lfs_file_size -> %\"PRIu32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n\n#ifndef LFS_READONLY\nint lfs_mkdir(lfs_t *lfs, const char *path) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_mkdir(%p, \\\"%s\\\")\", (void*)lfs, path);\n\n    err = lfs_mkdir_(lfs, path);\n\n    LFS_TRACE(\"lfs_mkdir -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\nint lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_dir_open(%p, %p, \\\"%s\\\")\", (void*)lfs, (void*)dir, path);\n    LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)dir));\n\n    err = lfs_dir_open_(lfs, dir, path);\n\n    LFS_TRACE(\"lfs_dir_open -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nint lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_dir_close(%p, %p)\", (void*)lfs, (void*)dir);\n\n    err = lfs_dir_close_(lfs, dir);\n\n    LFS_TRACE(\"lfs_dir_close -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nint lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_dir_read(%p, %p, %p)\",\n            (void*)lfs, (void*)dir, (void*)info);\n\n    err = lfs_dir_read_(lfs, dir, info);\n\n    LFS_TRACE(\"lfs_dir_read -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nint lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_dir_seek(%p, %p, %\"PRIu32\")\",\n            (void*)lfs, (void*)dir, off);\n\n    err = lfs_dir_seek_(lfs, dir, off);\n\n    LFS_TRACE(\"lfs_dir_seek -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nlfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_dir_tell(%p, %p)\", (void*)lfs, (void*)dir);\n\n    lfs_soff_t res = lfs_dir_tell_(lfs, dir);\n\n    LFS_TRACE(\"lfs_dir_tell -> %\"PRId32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n\nint lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_dir_rewind(%p, %p)\", (void*)lfs, (void*)dir);\n\n    err = lfs_dir_rewind_(lfs, dir);\n\n    LFS_TRACE(\"lfs_dir_rewind -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nint lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_fs_stat(%p, %p)\", (void*)lfs, (void*)fsinfo);\n\n    err = lfs_fs_stat_(lfs, fsinfo);\n\n    LFS_TRACE(\"lfs_fs_stat -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\nlfs_ssize_t lfs_fs_size(lfs_t *lfs) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_fs_size(%p)\", (void*)lfs);\n\n    lfs_ssize_t res = lfs_fs_size_(lfs);\n\n    LFS_TRACE(\"lfs_fs_size -> %\"PRId32, res);\n    LFS_UNLOCK(lfs->cfg);\n    return res;\n}\n\nint lfs_fs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_fs_traverse(%p, %p, %p)\",\n            (void*)lfs, (void*)(uintptr_t)cb, data);\n\n    err = lfs_fs_traverse_(lfs, cb, data, true);\n\n    LFS_TRACE(\"lfs_fs_traverse -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n\n#ifndef LFS_READONLY\nint lfs_fs_mkconsistent(lfs_t *lfs) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_fs_mkconsistent(%p)\", (void*)lfs);\n\n    err = lfs_fs_mkconsistent_(lfs);\n\n    LFS_TRACE(\"lfs_fs_mkconsistent -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\n#ifndef LFS_READONLY\nint lfs_fs_gc(lfs_t *lfs) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_fs_gc(%p)\", (void*)lfs);\n\n    err = lfs_fs_gc_(lfs);\n\n    LFS_TRACE(\"lfs_fs_gc -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\n#ifndef LFS_READONLY\nint lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count) {\n    int err = LFS_LOCK(lfs->cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_fs_grow(%p, %\"PRIu32\")\", (void*)lfs, block_count);\n\n    err = lfs_fs_grow_(lfs, block_count);\n\n    LFS_TRACE(\"lfs_fs_grow -> %d\", err);\n    LFS_UNLOCK(lfs->cfg);\n    return err;\n}\n#endif\n\n#ifdef LFS_MIGRATE\nint lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {\n    int err = LFS_LOCK(cfg);\n    if (err) {\n        return err;\n    }\n    LFS_TRACE(\"lfs_migrate(%p, %p {.context=%p, \"\n                \".read=%p, .prog=%p, .erase=%p, .sync=%p, \"\n                \".read_size=%\"PRIu32\", .prog_size=%\"PRIu32\", \"\n                \".block_size=%\"PRIu32\", .block_count=%\"PRIu32\", \"\n                \".block_cycles=%\"PRId32\", .cache_size=%\"PRIu32\", \"\n                \".lookahead_size=%\"PRIu32\", .read_buffer=%p, \"\n                \".prog_buffer=%p, .lookahead_buffer=%p, \"\n                \".name_max=%\"PRIu32\", .file_max=%\"PRIu32\", \"\n                \".attr_max=%\"PRIu32\"})\",\n            (void*)lfs, (void*)cfg, cfg->context,\n            (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,\n            (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,\n            cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,\n            cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,\n            cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,\n            cfg->name_max, cfg->file_max, cfg->attr_max);\n\n    err = lfs_migrate_(lfs, cfg);\n\n    LFS_TRACE(\"lfs_migrate -> %d\", err);\n    LFS_UNLOCK(cfg);\n    return err;\n}\n#endif\n\n"
  },
  {
    "path": "NanaZip.Codecs/LittleFS/lfs.h",
    "content": "﻿/*\n * The little filesystem\n *\n * Copyright (c) 2022, The littlefs authors.\n * Copyright (c) 2017, Arm Limited. All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n */\n#ifndef LFS_H\n#define LFS_H\n\n#include \"lfs_util.h\"\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n\n/// Version info ///\n\n// Software library version\n// Major (top-nibble), incremented on backwards incompatible changes\n// Minor (bottom-nibble), incremented on feature additions\n#define LFS_VERSION 0x0002000a\n#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))\n#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >>  0))\n\n// Version of On-disk data structures\n// Major (top-nibble), incremented on backwards incompatible changes\n// Minor (bottom-nibble), incremented on feature additions\n#define LFS_DISK_VERSION 0x00020001\n#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))\n#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >>  0))\n\n\n/// Definitions ///\n\n// Type definitions\ntypedef uint32_t lfs_size_t;\ntypedef uint32_t lfs_off_t;\n\ntypedef int32_t  lfs_ssize_t;\ntypedef int32_t  lfs_soff_t;\n\ntypedef uint32_t lfs_block_t;\n\n// Maximum name size in bytes, may be redefined to reduce the size of the\n// info struct. Limited to <= 1022. Stored in superblock and must be\n// respected by other littlefs drivers.\n#ifndef LFS_NAME_MAX\n#define LFS_NAME_MAX 255\n#endif\n\n// Maximum size of a file in bytes, may be redefined to limit to support other\n// drivers. Limited on disk to <= 2147483647. Stored in superblock and must be\n// respected by other littlefs drivers.\n#ifndef LFS_FILE_MAX\n#define LFS_FILE_MAX 2147483647\n#endif\n\n// Maximum size of custom attributes in bytes, may be redefined, but there is\n// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022. Stored\n// in superblock and must be respected by other littlefs drivers.\n#ifndef LFS_ATTR_MAX\n#define LFS_ATTR_MAX 1022\n#endif\n\n// Possible error codes, these are negative to allow\n// valid positive return values\nenum lfs_error {\n    LFS_ERR_OK          = 0,    // No error\n    LFS_ERR_IO          = -5,   // Error during device operation\n    LFS_ERR_CORRUPT     = -84,  // Corrupted\n    LFS_ERR_NOENT       = -2,   // No directory entry\n    LFS_ERR_EXIST       = -17,  // Entry already exists\n    LFS_ERR_NOTDIR      = -20,  // Entry is not a dir\n    LFS_ERR_ISDIR       = -21,  // Entry is a dir\n    LFS_ERR_NOTEMPTY    = -39,  // Dir is not empty\n    LFS_ERR_BADF        = -9,   // Bad file number\n    LFS_ERR_FBIG        = -27,  // File too large\n    LFS_ERR_INVAL       = -22,  // Invalid parameter\n    LFS_ERR_NOSPC       = -28,  // No space left on device\n    LFS_ERR_NOMEM       = -12,  // No more memory available\n    LFS_ERR_NOATTR      = -61,  // No data/attr available\n    LFS_ERR_NAMETOOLONG = -36,  // File name too long\n};\n\n// File types\nenum lfs_type {\n    // file types\n    LFS_TYPE_REG            = 0x001,\n    LFS_TYPE_DIR            = 0x002,\n\n    // internally used types\n    LFS_TYPE_SPLICE         = 0x400,\n    LFS_TYPE_NAME           = 0x000,\n    LFS_TYPE_STRUCT         = 0x200,\n    LFS_TYPE_USERATTR       = 0x300,\n    LFS_TYPE_FROM           = 0x100,\n    LFS_TYPE_TAIL           = 0x600,\n    LFS_TYPE_GLOBALS        = 0x700,\n    LFS_TYPE_CRC            = 0x500,\n\n    // internally used type specializations\n    LFS_TYPE_CREATE         = 0x401,\n    LFS_TYPE_DELETE         = 0x4ff,\n    LFS_TYPE_SUPERBLOCK     = 0x0ff,\n    LFS_TYPE_DIRSTRUCT      = 0x200,\n    LFS_TYPE_CTZSTRUCT      = 0x202,\n    LFS_TYPE_INLINESTRUCT   = 0x201,\n    LFS_TYPE_SOFTTAIL       = 0x600,\n    LFS_TYPE_HARDTAIL       = 0x601,\n    LFS_TYPE_MOVESTATE      = 0x7ff,\n    LFS_TYPE_CCRC           = 0x500,\n    LFS_TYPE_FCRC           = 0x5ff,\n\n    // internal chip sources\n    LFS_FROM_NOOP           = 0x000,\n    LFS_FROM_MOVE           = 0x101,\n    LFS_FROM_USERATTRS      = 0x102,\n};\n\n// File open flags\nenum lfs_open_flags {\n    // open flags\n    LFS_O_RDONLY = 1,         // Open a file as read only\n#ifndef LFS_READONLY\n    LFS_O_WRONLY = 2,         // Open a file as write only\n    LFS_O_RDWR   = 3,         // Open a file as read and write\n    LFS_O_CREAT  = 0x0100,    // Create a file if it does not exist\n    LFS_O_EXCL   = 0x0200,    // Fail if a file already exists\n    LFS_O_TRUNC  = 0x0400,    // Truncate the existing file to zero size\n    LFS_O_APPEND = 0x0800,    // Move to end of file on every write\n#endif\n\n    // internally used flags\n#ifndef LFS_READONLY\n    LFS_F_DIRTY   = 0x010000, // File does not match storage\n    LFS_F_WRITING = 0x020000, // File has been written since last flush\n#endif\n    LFS_F_READING = 0x040000, // File has been read since last flush\n#ifndef LFS_READONLY\n    LFS_F_ERRED   = 0x080000, // An error occurred during write\n#endif\n    LFS_F_INLINE  = 0x100000, // Currently inlined in directory entry\n};\n\n// File seek flags\nenum lfs_whence_flags {\n    LFS_SEEK_SET = 0,   // Seek relative to an absolute position\n    LFS_SEEK_CUR = 1,   // Seek relative to the current file position\n    LFS_SEEK_END = 2,   // Seek relative to the end of the file\n};\n\n\n// Configuration provided during initialization of the littlefs\nstruct lfs_config {\n    // Opaque user provided context that can be used to pass\n    // information to the block device operations\n    void *context;\n\n    // Read a region in a block. Negative error codes are propagated\n    // to the user.\n    int (*read)(const struct lfs_config *c, lfs_block_t block,\n            lfs_off_t off, void *buffer, lfs_size_t size);\n\n    // Program a region in a block. The block must have previously\n    // been erased. Negative error codes are propagated to the user.\n    // May return LFS_ERR_CORRUPT if the block should be considered bad.\n    int (*prog)(const struct lfs_config *c, lfs_block_t block,\n            lfs_off_t off, const void *buffer, lfs_size_t size);\n\n    // Erase a block. A block must be erased before being programmed.\n    // The state of an erased block is undefined. Negative error codes\n    // are propagated to the user.\n    // May return LFS_ERR_CORRUPT if the block should be considered bad.\n    int (*erase)(const struct lfs_config *c, lfs_block_t block);\n\n    // Sync the state of the underlying block device. Negative error codes\n    // are propagated to the user.\n    int (*sync)(const struct lfs_config *c);\n\n#ifdef LFS_THREADSAFE\n    // Lock the underlying block device. Negative error codes\n    // are propagated to the user.\n    int (*lock)(const struct lfs_config *c);\n\n    // Unlock the underlying block device. Negative error codes\n    // are propagated to the user.\n    int (*unlock)(const struct lfs_config *c);\n#endif\n\n    // Minimum size of a block read in bytes. All read operations will be a\n    // multiple of this value.\n    lfs_size_t read_size;\n\n    // Minimum size of a block program in bytes. All program operations will be\n    // a multiple of this value.\n    lfs_size_t prog_size;\n\n    // Size of an erasable block in bytes. This does not impact ram consumption\n    // and may be larger than the physical erase size. However, non-inlined\n    // files take up at minimum one block. Must be a multiple of the read and\n    // program sizes.\n    lfs_size_t block_size;\n\n    // Number of erasable blocks on the device. Defaults to block_count stored\n    // on disk when zero.\n    lfs_size_t block_count;\n\n    // Number of erase cycles before littlefs evicts metadata logs and moves\n    // the metadata to another block. Suggested values are in the\n    // range 100-1000, with large values having better performance at the cost\n    // of less consistent wear distribution.\n    //\n    // Set to -1 to disable block-level wear-leveling.\n    int32_t block_cycles;\n\n    // Size of block caches in bytes. Each cache buffers a portion of a block in\n    // RAM. The littlefs needs a read cache, a program cache, and one additional\n    // cache per file. Larger caches can improve performance by storing more\n    // data and reducing the number of disk accesses. Must be a multiple of the\n    // read and program sizes, and a factor of the block size.\n    lfs_size_t cache_size;\n\n    // Size of the lookahead buffer in bytes. A larger lookahead buffer\n    // increases the number of blocks found during an allocation pass. The\n    // lookahead buffer is stored as a compact bitmap, so each byte of RAM\n    // can track 8 blocks.\n    lfs_size_t lookahead_size;\n\n    // Threshold for metadata compaction during lfs_fs_gc in bytes. Metadata\n    // pairs that exceed this threshold will be compacted during lfs_fs_gc.\n    // Defaults to ~88% block_size when zero, though the default may change\n    // in the future.\n    //\n    // Note this only affects lfs_fs_gc. Normal compactions still only occur\n    // when full.\n    //\n    // Set to -1 to disable metadata compaction during lfs_fs_gc.\n    lfs_size_t compact_thresh;\n\n    // Optional statically allocated read buffer. Must be cache_size.\n    // By default lfs_malloc is used to allocate this buffer.\n    void *read_buffer;\n\n    // Optional statically allocated program buffer. Must be cache_size.\n    // By default lfs_malloc is used to allocate this buffer.\n    void *prog_buffer;\n\n    // Optional statically allocated lookahead buffer. Must be lookahead_size.\n    // By default lfs_malloc is used to allocate this buffer.\n    void *lookahead_buffer;\n\n    // Optional upper limit on length of file names in bytes. No downside for\n    // larger names except the size of the info struct which is controlled by\n    // the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX or name_max stored on\n    // disk when zero.\n    lfs_size_t name_max;\n\n    // Optional upper limit on files in bytes. No downside for larger files\n    // but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX or file_max stored\n    // on disk when zero.\n    lfs_size_t file_max;\n\n    // Optional upper limit on custom attributes in bytes. No downside for\n    // larger attributes size but must be <= LFS_ATTR_MAX. Defaults to\n    // LFS_ATTR_MAX or attr_max stored on disk when zero.\n    lfs_size_t attr_max;\n\n    // Optional upper limit on total space given to metadata pairs in bytes. On\n    // devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB)\n    // can help bound the metadata compaction time. Must be <= block_size.\n    // Defaults to block_size when zero.\n    lfs_size_t metadata_max;\n\n    // Optional upper limit on inlined files in bytes. Inlined files live in\n    // metadata and decrease storage requirements, but may be limited to\n    // improve metadata-related performance. Must be <= cache_size, <=\n    // attr_max, and <= block_size/8. Defaults to the largest possible\n    // inline_max when zero.\n    //\n    // Set to -1 to disable inlined files.\n    lfs_size_t inline_max;\n\n#ifdef LFS_MULTIVERSION\n    // On-disk version to use when writing in the form of 16-bit major version\n    // + 16-bit minor version. This limiting metadata to what is supported by\n    // older minor versions. Note that some features will be lost. Defaults to \n    // to the most recent minor version when zero.\n    uint32_t disk_version;\n#endif\n};\n\n// File info structure\nstruct lfs_info {\n    // Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR\n    uint8_t type;\n\n    // Size of the file, only valid for REG files. Limited to 32-bits.\n    lfs_size_t size;\n\n    // Name of the file stored as a null-terminated string. Limited to\n    // LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to\n    // reduce RAM. LFS_NAME_MAX is stored in superblock and must be\n    // respected by other littlefs drivers.\n    char name[LFS_NAME_MAX+1];\n};\n\n// Filesystem info structure\nstruct lfs_fsinfo {\n    // On-disk version.\n    uint32_t disk_version;\n\n    // Size of a logical block in bytes.\n    lfs_size_t block_size;\n\n    // Number of logical blocks in filesystem.\n    lfs_size_t block_count;\n\n    // Upper limit on the length of file names in bytes.\n    lfs_size_t name_max;\n\n    // Upper limit on the size of files in bytes.\n    lfs_size_t file_max;\n\n    // Upper limit on the size of custom attributes in bytes.\n    lfs_size_t attr_max;\n};\n\n// Custom attribute structure, used to describe custom attributes\n// committed atomically during file writes.\nstruct lfs_attr {\n    // 8-bit type of attribute, provided by user and used to\n    // identify the attribute\n    uint8_t type;\n\n    // Pointer to buffer containing the attribute\n    void *buffer;\n\n    // Size of attribute in bytes, limited to LFS_ATTR_MAX\n    lfs_size_t size;\n};\n\n// Optional configuration provided during lfs_file_opencfg\nstruct lfs_file_config {\n    // Optional statically allocated file buffer. Must be cache_size.\n    // By default lfs_malloc is used to allocate this buffer.\n    void *buffer;\n\n    // Optional list of custom attributes related to the file. If the file\n    // is opened with read access, these attributes will be read from disk\n    // during the open call. If the file is opened with write access, the\n    // attributes will be written to disk every file sync or close. This\n    // write occurs atomically with update to the file's contents.\n    //\n    // Custom attributes are uniquely identified by an 8-bit type and limited\n    // to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller\n    // than the buffer, it will be padded with zeros. If the stored attribute\n    // is larger, then it will be silently truncated. If the attribute is not\n    // found, it will be created implicitly.\n    struct lfs_attr *attrs;\n\n    // Number of custom attributes in the list\n    lfs_size_t attr_count;\n};\n\n\n/// internal littlefs data structures ///\ntypedef struct lfs_cache {\n    lfs_block_t block;\n    lfs_off_t off;\n    lfs_size_t size;\n    uint8_t *buffer;\n} lfs_cache_t;\n\ntypedef struct lfs_mdir {\n    lfs_block_t pair[2];\n    uint32_t rev;\n    lfs_off_t off;\n    uint32_t etag;\n    uint16_t count;\n    bool erased;\n    bool split;\n    lfs_block_t tail[2];\n} lfs_mdir_t;\n\n// littlefs directory type\ntypedef struct lfs_dir {\n    struct lfs_dir *next;\n    uint16_t id;\n    uint8_t type;\n    lfs_mdir_t m;\n\n    lfs_off_t pos;\n    lfs_block_t head[2];\n} lfs_dir_t;\n\n// littlefs file type\ntypedef struct lfs_file {\n    struct lfs_file *next;\n    uint16_t id;\n    uint8_t type;\n    lfs_mdir_t m;\n\n    struct lfs_ctz {\n        lfs_block_t head;\n        lfs_size_t size;\n    } ctz;\n\n    uint32_t flags;\n    lfs_off_t pos;\n    lfs_block_t block;\n    lfs_off_t off;\n    lfs_cache_t cache;\n\n    const struct lfs_file_config *cfg;\n} lfs_file_t;\n\ntypedef struct lfs_superblock {\n    uint32_t version;\n    lfs_size_t block_size;\n    lfs_size_t block_count;\n    lfs_size_t name_max;\n    lfs_size_t file_max;\n    lfs_size_t attr_max;\n} lfs_superblock_t;\n\ntypedef struct lfs_gstate {\n    uint32_t tag;\n    lfs_block_t pair[2];\n} lfs_gstate_t;\n\n// The littlefs filesystem type\ntypedef struct lfs {\n    lfs_cache_t rcache;\n    lfs_cache_t pcache;\n\n    lfs_block_t root[2];\n    struct lfs_mlist {\n        struct lfs_mlist *next;\n        uint16_t id;\n        uint8_t type;\n        lfs_mdir_t m;\n    } *mlist;\n    uint32_t seed;\n\n    lfs_gstate_t gstate;\n    lfs_gstate_t gdisk;\n    lfs_gstate_t gdelta;\n\n    struct lfs_lookahead {\n        lfs_block_t start;\n        lfs_block_t size;\n        lfs_block_t next;\n        lfs_block_t ckpoint;\n        uint8_t *buffer;\n    } lookahead;\n\n    const struct lfs_config *cfg;\n    lfs_size_t block_count;\n    lfs_size_t name_max;\n    lfs_size_t file_max;\n    lfs_size_t attr_max;\n    lfs_size_t inline_max;\n\n#ifdef LFS_MIGRATE\n    struct lfs1 *lfs1;\n#endif\n} lfs_t;\n\n\n/// Filesystem functions ///\n\n#ifndef LFS_READONLY\n// Format a block device with the littlefs\n//\n// Requires a littlefs object and config struct. This clobbers the littlefs\n// object, and does not leave the filesystem mounted. The config struct must\n// be zeroed for defaults and backwards compatibility.\n//\n// Returns a negative error code on failure.\nint lfs_format(lfs_t *lfs, const struct lfs_config *config);\n#endif\n\n// Mounts a littlefs\n//\n// Requires a littlefs object and config struct. Multiple filesystems\n// may be mounted simultaneously with multiple littlefs objects. Both\n// lfs and config must be allocated while mounted. The config struct must\n// be zeroed for defaults and backwards compatibility.\n//\n// Returns a negative error code on failure.\nint lfs_mount(lfs_t *lfs, const struct lfs_config *config);\n\n// Unmounts a littlefs\n//\n// Does nothing besides releasing any allocated resources.\n// Returns a negative error code on failure.\nint lfs_unmount(lfs_t *lfs);\n\n/// General operations ///\n\n#ifndef LFS_READONLY\n// Removes a file or directory\n//\n// If removing a directory, the directory must be empty.\n// Returns a negative error code on failure.\nint lfs_remove(lfs_t *lfs, const char *path);\n#endif\n\n#ifndef LFS_READONLY\n// Rename or move a file or directory\n//\n// If the destination exists, it must match the source in type.\n// If the destination is a directory, the directory must be empty.\n//\n// Returns a negative error code on failure.\nint lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);\n#endif\n\n// Find info about a file or directory\n//\n// Fills out the info structure, based on the specified file or directory.\n// Returns a negative error code on failure.\nint lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);\n\n// Get a custom attribute\n//\n// Custom attributes are uniquely identified by an 8-bit type and limited\n// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than\n// the buffer, it will be padded with zeros. If the stored attribute is larger,\n// then it will be silently truncated. If no attribute is found, the error\n// LFS_ERR_NOATTR is returned and the buffer is filled with zeros.\n//\n// Returns the size of the attribute, or a negative error code on failure.\n// Note, the returned size is the size of the attribute on disk, irrespective\n// of the size of the buffer. This can be used to dynamically allocate a buffer\n// or check for existence.\nlfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,\n        uint8_t type, void *buffer, lfs_size_t size);\n\n#ifndef LFS_READONLY\n// Set custom attributes\n//\n// Custom attributes are uniquely identified by an 8-bit type and limited\n// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be\n// implicitly created.\n//\n// Returns a negative error code on failure.\nint lfs_setattr(lfs_t *lfs, const char *path,\n        uint8_t type, const void *buffer, lfs_size_t size);\n#endif\n\n#ifndef LFS_READONLY\n// Removes a custom attribute\n//\n// If an attribute is not found, nothing happens.\n//\n// Returns a negative error code on failure.\nint lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);\n#endif\n\n\n/// File operations ///\n\n#ifndef LFS_NO_MALLOC\n// Open a file\n//\n// The mode that the file is opened in is determined by the flags, which\n// are values from the enum lfs_open_flags that are bitwise-ored together.\n//\n// Returns a negative error code on failure.\nint lfs_file_open(lfs_t *lfs, lfs_file_t *file,\n        const char *path, int flags);\n\n// if LFS_NO_MALLOC is defined, lfs_file_open() will fail with LFS_ERR_NOMEM\n// thus use lfs_file_opencfg() with config.buffer set.\n#endif\n\n// Open a file with extra configuration\n//\n// The mode that the file is opened in is determined by the flags, which\n// are values from the enum lfs_open_flags that are bitwise-ored together.\n//\n// The config struct provides additional config options per file as described\n// above. The config struct must remain allocated while the file is open, and\n// the config struct must be zeroed for defaults and backwards compatibility.\n//\n// Returns a negative error code on failure.\nint lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,\n        const char *path, int flags,\n        const struct lfs_file_config *config);\n\n// Close a file\n//\n// Any pending writes are written out to storage as though\n// sync had been called and releases any allocated resources.\n//\n// Returns a negative error code on failure.\nint lfs_file_close(lfs_t *lfs, lfs_file_t *file);\n\n// Synchronize a file on storage\n//\n// Any pending writes are written out to storage.\n// Returns a negative error code on failure.\nint lfs_file_sync(lfs_t *lfs, lfs_file_t *file);\n\n// Read data from file\n//\n// Takes a buffer and size indicating where to store the read data.\n// Returns the number of bytes read, or a negative error code on failure.\nlfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,\n        void *buffer, lfs_size_t size);\n\n#ifndef LFS_READONLY\n// Write data to file\n//\n// Takes a buffer and size indicating the data to write. The file will not\n// actually be updated on the storage until either sync or close is called.\n//\n// Returns the number of bytes written, or a negative error code on failure.\nlfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,\n        const void *buffer, lfs_size_t size);\n#endif\n\n// Change the position of the file\n//\n// The change in position is determined by the offset and whence flag.\n// Returns the new position of the file, or a negative error code on failure.\nlfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,\n        lfs_soff_t off, int whence);\n\n#ifndef LFS_READONLY\n// Truncates the size of the file to the specified size\n//\n// Returns a negative error code on failure.\nint lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);\n#endif\n\n// Return the position of the file\n//\n// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)\n// Returns the position of the file, or a negative error code on failure.\nlfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);\n\n// Change the position of the file to the beginning of the file\n//\n// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_SET)\n// Returns a negative error code on failure.\nint lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);\n\n// Return the size of the file\n//\n// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)\n// Returns the size of the file, or a negative error code on failure.\nlfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);\n\n\n/// Directory operations ///\n\n#ifndef LFS_READONLY\n// Create a directory\n//\n// Returns a negative error code on failure.\nint lfs_mkdir(lfs_t *lfs, const char *path);\n#endif\n\n// Open a directory\n//\n// Once open a directory can be used with read to iterate over files.\n// Returns a negative error code on failure.\nint lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);\n\n// Close a directory\n//\n// Releases any allocated resources.\n// Returns a negative error code on failure.\nint lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);\n\n// Read an entry in the directory\n//\n// Fills out the info structure, based on the specified file or directory.\n// Returns a positive value on success, 0 at the end of directory,\n// or a negative error code on failure.\nint lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);\n\n// Change the position of the directory\n//\n// The new off must be a value previous returned from tell and specifies\n// an absolute offset in the directory seek.\n//\n// Returns a negative error code on failure.\nint lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);\n\n// Return the position of the directory\n//\n// The returned offset is only meant to be consumed by seek and may not make\n// sense, but does indicate the current position in the directory iteration.\n//\n// Returns the position of the directory, or a negative error code on failure.\nlfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);\n\n// Change the position of the directory to the beginning of the directory\n//\n// Returns a negative error code on failure.\nint lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);\n\n\n/// Filesystem-level filesystem operations\n\n// Find on-disk info about the filesystem\n//\n// Fills out the fsinfo structure based on the filesystem found on-disk.\n// Returns a negative error code on failure.\nint lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo);\n\n// Finds the current size of the filesystem\n//\n// Note: Result is best effort. If files share COW structures, the returned\n// size may be larger than the filesystem actually is.\n//\n// Returns the number of allocated blocks, or a negative error code on failure.\nlfs_ssize_t lfs_fs_size(lfs_t *lfs);\n\n// Traverse through all blocks in use by the filesystem\n//\n// The provided callback will be called with each block address that is\n// currently in use by the filesystem. This can be used to determine which\n// blocks are in use or how much of the storage is available.\n//\n// Returns a negative error code on failure.\nint lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);\n\n#ifndef LFS_READONLY\n// Attempt to make the filesystem consistent and ready for writing\n//\n// Calling this function is not required, consistency will be implicitly\n// enforced on the first operation that writes to the filesystem, but this\n// function allows the work to be performed earlier and without other\n// filesystem changes.\n//\n// Returns a negative error code on failure.\nint lfs_fs_mkconsistent(lfs_t *lfs);\n#endif\n\n#ifndef LFS_READONLY\n// Attempt any janitorial work\n//\n// This currently:\n// 1. Calls mkconsistent if not already consistent\n// 2. Compacts metadata > compact_thresh\n// 3. Populates the block allocator\n//\n// Though additional janitorial work may be added in the future.\n//\n// Calling this function is not required, but may allow the offloading of\n// expensive janitorial work to a less time-critical code path.\n//\n// Returns a negative error code on failure. Accomplishing nothing is not\n// an error.\nint lfs_fs_gc(lfs_t *lfs);\n#endif\n\n#ifndef LFS_READONLY\n// Grows the filesystem to a new size, updating the superblock with the new\n// block count.\n//\n// Note: This is irreversible.\n//\n// Returns a negative error code on failure.\nint lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count);\n#endif\n\n#ifndef LFS_READONLY\n#ifdef LFS_MIGRATE\n// Attempts to migrate a previous version of littlefs\n//\n// Behaves similarly to the lfs_format function. Attempts to mount\n// the previous version of littlefs and update the filesystem so it can be\n// mounted with the current version of littlefs.\n//\n// Requires a littlefs object and config struct. This clobbers the littlefs\n// object, and does not leave the filesystem mounted. The config struct must\n// be zeroed for defaults and backwards compatibility.\n//\n// Returns a negative error code on failure.\nint lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);\n#endif\n#endif\n\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LittleFS/lfs_util.c",
    "content": "﻿/*\n * lfs util functions\n *\n * Copyright (c) 2022, The littlefs authors.\n * Copyright (c) 2017, Arm Limited. All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n */\n#include \"lfs_util.h\"\n\n// Only compile if user does not provide custom config\n#ifndef LFS_CONFIG\n\n\n// If user provides their own CRC impl we don't need this\n#ifndef LFS_CRC\n// Software CRC implementation with small lookup table\nuint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {\n    static const uint32_t rtable[16] = {\n        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,\n        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,\n        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,\n        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,\n    };\n\n    const uint8_t *data = buffer;\n\n    for (size_t i = 0; i < size; i++) {\n        crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];\n        crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];\n    }\n\n    return crc;\n}\n#endif\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/LittleFS/lfs_util.h",
    "content": "﻿/*\n * lfs utility functions\n *\n * Copyright (c) 2022, The littlefs authors.\n * Copyright (c) 2017, Arm Limited. All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n */\n#ifndef LFS_UTIL_H\n#define LFS_UTIL_H\n\n#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)\n#define LFS_STRINGIZE2(x) #x\n\n// Users can override lfs_util.h with their own configuration by defining\n// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).\n//\n// If LFS_CONFIG is used, none of the default utils will be emitted and must be\n// provided by the config file. To start, I would suggest copying lfs_util.h\n// and modifying as needed.\n#ifdef LFS_CONFIG\n#include LFS_STRINGIZE(LFS_CONFIG)\n#else\n\n// Alternatively, users can provide a header file which defines\n// macros and other things consumed by littlefs.\n//\n// For example, provide my_defines.h, which contains\n// something like:\n//\n// #include <stddef.h>\n// extern void *my_malloc(size_t sz);\n// #define LFS_MALLOC(sz) my_malloc(sz)\n//\n// And build littlefs with the header by defining LFS_DEFINES.\n// (-DLFS_DEFINES=my_defines.h)\n\n#ifdef LFS_DEFINES\n#include LFS_STRINGIZE(LFS_DEFINES)\n#endif\n\n// System includes\n#include <stdint.h>\n#include <stdbool.h>\n#include <string.h>\n#include <inttypes.h>\n\n#ifndef LFS_NO_MALLOC\n#include <stdlib.h>\n#endif\n#ifndef LFS_NO_ASSERT\n#include <assert.h>\n#endif\n#if !defined(LFS_NO_DEBUG) || \\\n        !defined(LFS_NO_WARN) || \\\n        !defined(LFS_NO_ERROR) || \\\n        defined(LFS_YES_TRACE)\n#include <stdio.h>\n#endif\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n\n// Macros, may be replaced by system specific wrappers. Arguments to these\n// macros must not have side-effects as the macros can be removed for a smaller\n// code footprint\n\n// Logging functions\n#ifndef LFS_TRACE\n#ifdef LFS_YES_TRACE\n#define LFS_TRACE_(fmt, ...) \\\n    printf(\"%s:%d:trace: \" fmt \"%s\\n\", __FILE__, __LINE__, __VA_ARGS__)\n#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, \"\")\n#else\n#define LFS_TRACE(...)\n#endif\n#endif\n\n#ifndef LFS_DEBUG\n#ifndef LFS_NO_DEBUG\n#define LFS_DEBUG_(fmt, ...) \\\n    printf(\"%s:%d:debug: \" fmt \"%s\\n\", __FILE__, __LINE__, __VA_ARGS__)\n#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, \"\")\n#else\n#define LFS_DEBUG(...)\n#endif\n#endif\n\n#ifndef LFS_WARN\n#ifndef LFS_NO_WARN\n#define LFS_WARN_(fmt, ...) \\\n    printf(\"%s:%d:warn: \" fmt \"%s\\n\", __FILE__, __LINE__, __VA_ARGS__)\n#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, \"\")\n#else\n#define LFS_WARN(...)\n#endif\n#endif\n\n#ifndef LFS_ERROR\n#ifndef LFS_NO_ERROR\n#define LFS_ERROR_(fmt, ...) \\\n    printf(\"%s:%d:error: \" fmt \"%s\\n\", __FILE__, __LINE__, __VA_ARGS__)\n#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, \"\")\n#else\n#define LFS_ERROR(...)\n#endif\n#endif\n\n// Runtime assertions\n#ifndef LFS_ASSERT\n#ifndef LFS_NO_ASSERT\n#define LFS_ASSERT(test) assert(test)\n#else\n#define LFS_ASSERT(test)\n#endif\n#endif\n\n\n// Builtin functions, these may be replaced by more efficient\n// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more\n// expensive basic C implementation for debugging purposes\n\n// Min/max functions for unsigned 32-bit numbers\nstatic inline uint32_t lfs_max(uint32_t a, uint32_t b) {\n    return (a > b) ? a : b;\n}\n\nstatic inline uint32_t lfs_min(uint32_t a, uint32_t b) {\n    return (a < b) ? a : b;\n}\n\n// Align to nearest multiple of a size\nstatic inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {\n    return a - (a % alignment);\n}\n\nstatic inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {\n    return lfs_aligndown(a + alignment-1, alignment);\n}\n\n// Find the smallest power of 2 greater than or equal to a\nstatic inline uint32_t lfs_npw2(uint32_t a) {\n#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))\n    return 32 - __builtin_clz(a-1);\n#else\n    uint32_t r = 0;\n    uint32_t s;\n    a -= 1;\n    s = (a > 0xffff) << 4; a >>= s; r |= s;\n    s = (a > 0xff  ) << 3; a >>= s; r |= s;\n    s = (a > 0xf   ) << 2; a >>= s; r |= s;\n    s = (a > 0x3   ) << 1; a >>= s; r |= s;\n    return (r | (a >> 1)) + 1;\n#endif\n}\n\n// Count the number of trailing binary zeros in a\n// lfs_ctz(0) may be undefined\nstatic inline uint32_t lfs_ctz(uint32_t a) {\n#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)\n    return __builtin_ctz(a);\n#else\n    return lfs_npw2((a & -a) + 1) - 1;\n#endif\n}\n\n// Count the number of binary ones in a\nstatic inline uint32_t lfs_popc(uint32_t a) {\n#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))\n    return __builtin_popcount(a);\n#else\n    a = a - ((a >> 1) & 0x55555555);\n    a = (a & 0x33333333) + ((a >> 2) & 0x33333333);\n    return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;\n#endif\n}\n\n// Find the sequence comparison of a and b, this is the distance\n// between a and b ignoring overflow\nstatic inline int lfs_scmp(uint32_t a, uint32_t b) {\n    return (int)(unsigned)(a - b);\n}\n\n// Convert between 32-bit little-endian and native order\nstatic inline uint32_t lfs_fromle32(uint32_t a) {\n#if (defined(  BYTE_ORDER  ) && defined(  ORDER_LITTLE_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_LITTLE_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER  ) && defined(__ORDER_LITTLE_ENDIAN  ) && __BYTE_ORDER   == __ORDER_LITTLE_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n    return a;\n#elif !defined(LFS_NO_INTRINSICS) && ( \\\n    (defined(  BYTE_ORDER  ) && defined(  ORDER_BIG_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_BIG_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER  ) && defined(__ORDER_BIG_ENDIAN  ) && __BYTE_ORDER   == __ORDER_BIG_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))\n    return __builtin_bswap32(a);\n#else\n    return (((uint8_t*)&a)[0] <<  0) |\n           (((uint8_t*)&a)[1] <<  8) |\n           (((uint8_t*)&a)[2] << 16) |\n           (((uint8_t*)&a)[3] << 24);\n#endif\n}\n\nstatic inline uint32_t lfs_tole32(uint32_t a) {\n    return lfs_fromle32(a);\n}\n\n// Convert between 32-bit big-endian and native order\nstatic inline uint32_t lfs_frombe32(uint32_t a) {\n#if !defined(LFS_NO_INTRINSICS) && ( \\\n    (defined(  BYTE_ORDER  ) && defined(  ORDER_LITTLE_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_LITTLE_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER  ) && defined(__ORDER_LITTLE_ENDIAN  ) && __BYTE_ORDER   == __ORDER_LITTLE_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))\n    return __builtin_bswap32(a);\n#elif (defined(  BYTE_ORDER  ) && defined(  ORDER_BIG_ENDIAN  ) &&   BYTE_ORDER   ==   ORDER_BIG_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER  ) && defined(__ORDER_BIG_ENDIAN  ) && __BYTE_ORDER   == __ORDER_BIG_ENDIAN  ) || \\\n    (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n    return a;\n#else\n    return (((uint8_t*)&a)[0] << 24) |\n           (((uint8_t*)&a)[1] << 16) |\n           (((uint8_t*)&a)[2] <<  8) |\n           (((uint8_t*)&a)[3] <<  0);\n#endif\n}\n\nstatic inline uint32_t lfs_tobe32(uint32_t a) {\n    return lfs_frombe32(a);\n}\n\n// Calculate CRC-32 with polynomial = 0x04c11db7\n#ifdef LFS_CRC\nuint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {\n    return LFS_CRC(crc, buffer, size)\n}\n#else\nuint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);\n#endif\n\n// Allocate memory, only used if buffers are not provided to littlefs\n//\n// littlefs current has no alignment requirements, as it only allocates\n// byte-level buffers.\nstatic inline void *lfs_malloc(size_t size) {\n#if defined(LFS_MALLOC)\n    return LFS_MALLOC(size);\n#elif !defined(LFS_NO_MALLOC)\n    return malloc(size);\n#else\n    (void)size;\n    return NULL;\n#endif\n}\n\n// Deallocate memory, only used if buffers are not provided to littlefs\nstatic inline void lfs_free(void *p) {\n#if defined(LFS_FREE)\n    LFS_FREE(p);\n#elif !defined(LFS_NO_MALLOC)\n    free(p);\n#else\n    (void)p;\n#endif\n}\n\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif\n\n#endif\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/bitstream.h",
    "content": "﻿/* NanaZip Header File Redirection */\n#include \"../../Zstandard/common/zstd_deps.h\" /* ZSTD_memset */\n#include \"../../Zstandard/common/bitstream.h\"\n#define BIT_highbit32 ZSTD_highbit32\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/compiler.h",
    "content": "﻿/* NanaZip Header File Redirection */\n#include \"../../Zstandard/common/compiler.h\"\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/debug.h",
    "content": "﻿/* NanaZip Header File Redirection */\n#include \"../../Zstandard/common/debug.h\"\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/error_private.h",
    "content": "﻿/* ******************************************************************\n   Error codes and messages\n   Copyright (C) 2013-2016, Yann Collet\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Homepage : http://www.zstd.net\n****************************************************************** */\n/* Note : this module is expected to remain private, do not expose it */\n\n#ifndef ERROR_H_MODULE\n#define ERROR_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* ****************************************\n*  Dependencies\n******************************************/\n#include <stddef.h>        /* size_t */\n#include \"error_public.h\"  /* enum list */\n\n\n/* ****************************************\n*  Compiler-specific\n******************************************/\n#if defined(__GNUC__)\n#  define ERR_STATIC static __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define ERR_STATIC static inline\n#elif defined(_MSC_VER)\n#  define ERR_STATIC static __inline\n#else\n#  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/*-****************************************\n*  Customization (error_public.h)\n******************************************/\ntypedef FSE_ErrorCode ERR_enum;\n#define PREFIX(name) FSE_error_##name\n\n\n/*-****************************************\n*  Error codes handling\n******************************************/\n#ifdef ERROR\n#  undef ERROR   /* reported already defined on VS 2015 (Rich Geldreich) */\n#endif\n#define ERROR(name) ((size_t)-PREFIX(name))\n\nERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }\n\nERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }\n\n/* check and forward error code */\n#define CHECK_V_F(e, f) size_t const e = f; if (ERR_isError(e)) return e\n#define CHECK_F(f)   { CHECK_V_F(_var_err__, f); }\n\n\n/*-****************************************\n*  Error Strings\n******************************************/\n\nERR_STATIC const char* ERR_getErrorString(ERR_enum code)\n{\n    static const char* notErrorCode = \"Unspecified error code\";\n    switch( code )\n    {\n    case PREFIX(no_error): return \"No error detected\";\n    case PREFIX(GENERIC):  return \"Error (generic)\";\n    case PREFIX(dstSize_tooSmall): return \"Destination buffer is too small\";\n    case PREFIX(srcSize_wrong): return \"Src size is incorrect\";\n    case PREFIX(corruption_detected): return \"Corrupted block detected\";\n    case PREFIX(tableLog_tooLarge): return \"tableLog requires too much memory : unsupported\";\n    case PREFIX(maxSymbolValue_tooLarge): return \"Unsupported max Symbol Value : too large\";\n    case PREFIX(maxSymbolValue_tooSmall): return \"Specified maxSymbolValue is too small\";\n    case PREFIX(workSpace_tooSmall): return \"workspace buffer is too small\";\n    case PREFIX(maxCode):\n    default: return notErrorCode;\n    }\n}\n\nERR_STATIC const char* ERR_getErrorName(size_t code)\n{\n    return ERR_getErrorString(ERR_getErrorCode(code));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ERROR_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/error_public.h",
    "content": "﻿/* ******************************************************************\n   Error codes list\n   Copyright (C) 2016, Yann Collet\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef ERROR_PUBLIC_H_MODULE\n#define ERROR_PUBLIC_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n *  error codes list\n ******************************************/\ntypedef enum {\n  FSE_error_no_error,\n  FSE_error_GENERIC,\n  FSE_error_dstSize_tooSmall,\n  FSE_error_srcSize_wrong,\n  FSE_error_corruption_detected,\n  FSE_error_tableLog_tooLarge,\n  FSE_error_maxSymbolValue_tooLarge,\n  FSE_error_maxSymbolValue_tooSmall,\n  FSE_error_workSpace_tooSmall,\n  FSE_error_maxCode\n} FSE_ErrorCode;\n\n/* note : compare with size_t function results using FSE_getError() */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ERROR_PUBLIC_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/fse.h",
    "content": "﻿/* ******************************************************************\n * FSE : Finite State Entropy codec\n * Public Prototypes declaration\n * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifndef FSE_H\n#define FSE_H\n\n/* *** Solve definition conflicts between zstd and NGE library *** */\n#define FSE_isError NGEF_isError\n#define FSE_versionNumber NGEF_versionNumber\n#define FSE_getErrorName NGEF_getErrorName\n#define FSE_readNCount NGEF_readNCount\n#define FSE_buildCTable_wksp NGEF_buildCTable_wksp\n#define FSE_NCountWriteBound NGEF_NCountWriteBound\n#define FSE_writeNCount NGEF_writeNCount\n#define FSE_optimalTableLog_internal NGEF_optimalTableLog_internal\n#define FSE_optimalTableLog NGEF_optimalTableLog\n#define FSE_normalizeCount NGEF_normalizeCount\n#define FSE_buildCTable_rle NGEF_buildCTable_rle\n#define FSE_compress_usingCTable NGEF_compress_usingCTable\n#define FSE_compressBound NGEF_compressBound\n\n\n/*-*****************************************\n*  Dependencies\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n\n\n/*-*****************************************\n*  FSE_PUBLIC_API : control library symbols visibility\n******************************************/\n#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)\n#  define FSE_PUBLIC_API __attribute__ ((visibility (\"default\")))\n#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1)   /* Visual expected */\n#  define FSE_PUBLIC_API __declspec(dllexport)\n#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)\n#  define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define FSE_PUBLIC_API\n#endif\n\n/*------   Version   ------*/\n#define FSE_VERSION_MAJOR    0\n#define FSE_VERSION_MINOR    9\n#define FSE_VERSION_RELEASE  0\n\n#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE\n#define FSE_QUOTE(str) #str\n#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)\n#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)\n\n#define FSE_VERSION_NUMBER  (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)\nFSE_PUBLIC_API unsigned FSE_versionNumber(void);   /**< library version number; to be used when checking dll version */\n\n\n/*-****************************************\n*  FSE simple functions\n******************************************/\n/*! FSE_compress() :\n    Compress content of buffer 'src', of size 'srcSize', into destination buffer 'dst'.\n    'dst' buffer must be already allocated. Compression runs faster is dstCapacity >= FSE_compressBound(srcSize).\n    @return : size of compressed data (<= dstCapacity).\n    Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!\n                     if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression instead.\n                     if FSE_isError(return), compression failed (more details using FSE_getErrorName())\n*/\nFSE_PUBLIC_API size_t FSE_compress(void* dst, size_t dstCapacity,\n                             const void* src, size_t srcSize);\n\n/*! FSE_decompress():\n    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstCapacity'.\n    @return : size of regenerated data (<= maxDstSize),\n              or an error code, which can be tested using FSE_isError() .\n\n    ** Important ** : FSE_decompress() does not decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\nFSE_PUBLIC_API size_t FSE_decompress(void* dst,  size_t dstCapacity,\n                               const void* cSrc, size_t cSrcSize);\n\n\n/*-*****************************************\n*  Tool functions\n******************************************/\nFSE_PUBLIC_API size_t FSE_compressBound(size_t size);       /* maximum compressed size */\n\n/* Error Management */\nFSE_PUBLIC_API unsigned    FSE_isError(size_t code);        /* tells if a return value is an error code */\nFSE_PUBLIC_API const char* FSE_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n/*-*****************************************\n*  FSE advanced functions\n******************************************/\n/*! FSE_compress2() :\n    Same as FSE_compress(), but allows the selection of 'maxSymbolValue' and 'tableLog'\n    Both parameters can be defined as '0' to mean : use default value\n    @return : size of compressed data\n    Special values : if return == 0, srcData is not compressible => Nothing is stored within cSrc !!!\n                     if return == 1, srcData is a single byte symbol * srcSize times. Use RLE compression.\n                     if FSE_isError(return), it's an error code.\n*/\nFSE_PUBLIC_API size_t FSE_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);\n\n\n/*-*****************************************\n*  FSE detailed API\n******************************************/\n/*!\nFSE_compress() does the following:\n1. count symbol occurrence from source[] into table count[] (see hist.h)\n2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)\n3. save normalized counters to memory buffer using writeNCount()\n4. build encoding table 'CTable' from normalized counters\n5. encode the data stream using encoding table 'CTable'\n\nFSE_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n/* *** COMPRESSION *** */\n\n/*! FSE_optimalTableLog():\n    dynamically downsize 'tableLog' when conditions are met.\n    It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.\n    @return : recommended tableLog (necessarily <= 'maxTableLog') */\nFSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);\n\n/*! FSE_normalizeCount():\n    normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)\n    'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).\n    @return : tableLog,\n              or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,\n                    const unsigned* count, size_t srcSize, unsigned maxSymbolValue);\n\n/*! FSE_NCountWriteBound():\n    Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.\n    Typically useful for allocation purpose. */\nFSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSE_writeNCount():\n    Compactly save 'normalizedCounter' into 'buffer'.\n    @return : size of the compressed table,\n              or an errorCode, which can be tested using FSE_isError(). */\nFSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,\n                                 const short* normalizedCounter,\n                                 unsigned maxSymbolValue, unsigned tableLog);\n\n/*! Constructor and Destructor of FSE_CTable.\n    Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's only meant to be more restrictive than void* */\nFSE_PUBLIC_API FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog);\nFSE_PUBLIC_API void        FSE_freeCTable (FSE_CTable* ct);\n\n/*! FSE_buildCTable():\n    Builds `ct`, which must be already allocated, using FSE_createCTable().\n    @return : 0, or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSE_compress_usingCTable():\n    Compress `src` using `ct` into `dst` which must be already allocated.\n    @return : size of compressed data (<= `dstCapacity`),\n              or 0 if compressed data could not fit into `dst`,\n              or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);\n\n/*!\nTutorial :\n----------\nThe first step is to count all symbols. FSE_count() does this job very fast.\nResult will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.\n'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]\nmaxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)\nFSE_count() will return the number of occurrence of the most frequent symbol.\nThis can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).\n\nThe next step is to normalize the frequencies.\nFSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.\nIt also guarantees a minimum of 1 to any Symbol with frequency >= 1.\nYou can use 'tableLog'==0 to mean \"use default tableLog value\".\nIf you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),\nwhich will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means \"default\").\n\nThe result of FSE_normalizeCount() will be saved into a table,\ncalled 'normalizedCounter', which is a table of signed short.\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.\nThe return value is tableLog if everything proceeded as expected.\nIt is 0 if there is a single symbol within distribution.\nIf there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).\n\n'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().\n'buffer' must be already allocated.\nFor guaranteed success, buffer size must be at least FSE_headerBound().\nThe result of the function is the number of bytes written into 'buffer'.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).\n\n'normalizedCounter' can then be used to create the compression table 'CTable'.\nThe space required by 'CTable' must be already allocated, using FSE_createCTable().\nYou can then use FSE_buildCTable() to fill 'CTable'.\nIf there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).\n\n'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().\nSimilar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'\nThe function returns the size of compressed data (without header), necessarily <= `dstCapacity`.\nIf it returns '0', compressed data could not fit into 'dst'.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*! FSE_readNCount():\n    Read compactly saved 'normalizedCounter' from 'rBuffer'.\n    @return : size read from 'rBuffer',\n              or an errorCode, which can be tested using FSE_isError().\n              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nFSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,\n                           unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,\n                           const void* rBuffer, size_t rBuffSize);\n\n/*! Constructor and Destructor of FSE_DTable.\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\nFSE_PUBLIC_API FSE_DTable* FSE_createDTable(unsigned tableLog);\nFSE_PUBLIC_API void        FSE_freeDTable(FSE_DTable* dt);\n\n/*! FSE_buildDTable():\n    Builds 'dt', which must be already allocated, using FSE_createDTable().\n    return : 0, or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_buildDTable (FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSE_decompress_usingDTable():\n    Decompress compressed source `cSrc` of size `cSrcSize` using `dt`\n    into `dst` which must be already allocated.\n    @return : size of regenerated data (necessarily <= `dstCapacity`),\n              or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSE_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\nThe next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.\nThis is performed by the function FSE_buildDTable().\nThe space required by 'FSE_DTable' must be already allocated using FSE_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\n`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().\n`cSrcSize` must be strictly correct, otherwise decompression will fail.\nFSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).\nIf there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)\n*/\n\n#endif  /* FSE_H */\n\n#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)\n#define FSE_H_FSE_STATIC_LINKING_ONLY\n\n/* *** Dependency *** */\n#include \"bitstream.h\"\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<(maxTableLog)))\n\n/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */\n#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue)   (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))\n#define FSE_DTABLE_SIZE(maxTableLog)                   (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))\n\n\n/* *****************************************\n *  FSE advanced API\n ***************************************** */\n\nunsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);\n/**< same as FSE_optimalTableLog(), which used `minus==2` */\n\n/* FSE_compress_wksp() :\n * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).\n * FSE_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable.\n */\n#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue)   ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) )\nsize_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);\n\nsize_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits);\n/**< build a fake FSE_CTable, designed for a flat distribution, where each symbol uses nbBits */\n\nsize_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);\n/**< build a fake FSE_CTable, designed to compress always the same symbolValue */\n\n/* FSE_buildCTable_wksp() :\n * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).\n * `wkspSize` must be >= `(1<<tableLog)`.\n */\nsize_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);\n\nsize_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);\n/**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */\n\nsize_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);\n/**< build a fake FSE_DTable, designed to always generate the same symbolValue */\n\nsize_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog);\n/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */\n\ntypedef enum {\n   FSE_repeat_none,  /**< Cannot use the previous table */\n   FSE_repeat_check, /**< Can use the previous table but it must be checked */\n   FSE_repeat_valid  /**< Can use the previous table and it is assumed to be valid */\n } FSE_repeat;\n\n/* *****************************************\n*  FSE symbol compression API\n*******************************************/\n/*!\n   This API consists of small unitary functions, which highly benefit from being inlined.\n   Hence their body are included in next section.\n*/\ntypedef struct {\n    ptrdiff_t   value;\n    const void* stateTable;\n    const void* symbolTT;\n    unsigned    stateLog;\n} FSE_CState_t;\n\nstatic void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);\n\nstatic void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);\n\nstatic void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);\n\n/**<\nThese functions are inner components of FSE_compress_usingCTable().\nThey allow the creation of custom streams, mixing multiple tables and bit sources.\n\nA key property to keep in mind is that encoding and decoding are done **in reverse direction**.\nSo the first symbol you will encode is the last you will decode, like a LIFO stack.\n\nYou will need a few variables to track your CStream. They are :\n\nFSE_CTable    ct;         // Provided by FSE_buildCTable()\nBIT_CStream_t bitStream;  // bitStream tracking structure\nFSE_CState_t  state;      // State tracking structure (can have several)\n\n\nThe first thing to do is to init bitStream and state.\n    size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);\n    FSE_initCState(&state, ct);\n\nNote that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();\nYou can then encode your input data, byte after byte.\nFSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.\nRemember decoding will be done in reverse direction.\n    FSE_encodeByte(&bitStream, &state, symbol);\n\nAt any time, you can also add any bit sequence.\nNote : maximum allowed nbBits is 25, for compatibility with 32-bits decoders\n    BIT_addBits(&bitStream, bitField, nbBits);\n\nThe above methods don't commit data to memory, they just store it into local register, for speed.\nLocal register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).\nWriting data to memory is a manual operation, performed by the flushBits function.\n    BIT_flushBits(&bitStream);\n\nYour last FSE encoding operation shall be to flush your last state value(s).\n    FSE_flushState(&bitStream, &state);\n\nFinally, you must close the bitStream.\nThe function returns the size of CStream in bytes.\nIf data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)\nIf there is an error, it returns an errorCode (which can be tested using FSE_isError()).\n    size_t size = BIT_closeCStream(&bitStream);\n*/\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct {\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n/**<\nLet's now decompose FSE_decompress_usingDTable() into its unitary components.\nYou will decode FSE-encoded symbols from the bitStream,\nand also any other bitFields you put in, **in reverse order**.\n\nYou will need a few variables to track your bitStream. They are :\n\nBIT_DStream_t DStream;    // Stream context\nFSE_DState_t  DState;     // State context. Multiple ones are possible\nFSE_DTable*   DTablePtr;  // Decoding table, provided by FSE_buildDTable()\n\nThe first thing to do is to init the bitStream.\n    errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);\n\nYou should then retrieve your initial state(s)\n(in reverse flushing order if you have several ones) :\n    errorCode = FSE_initDState(&DState, &DStream, DTablePtr);\n\nYou can then decode your data, symbol after symbol.\nFor information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.\nKeep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).\n    unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);\n\nYou can retrieve any bitfield you eventually stored into the bitStream (in reverse order)\nNote : maximum allowed nbBits is 25, for 32-bits compatibility\n    size_t bitField = BIT_readBits(&DStream, nbBits);\n\nAll above operations only read from local register (which size depends on size_t).\nRefueling the register from memory is manually performed by the reload method.\n    endSignal = FSE_reloadDStream(&DStream);\n\nBIT_reloadDStream() result tells if there is still some more data to read from DStream.\nBIT_DStream_unfinished : there is still some data left into the DStream.\nBIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.\nBIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.\nBIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.\n\nWhen reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,\nto properly detect the exact end of stream.\nAfter each decoded symbol, check if DStream is fully consumed using this simple test :\n    BIT_reloadDStream(&DStream) >= BIT_DStream_completed\n\nWhen it's done, verify decompression is fully completed, by checking both DStream and the relevant states.\nChecking if DStream has reached its end is performed by :\n    BIT_endOfDStream(&DStream);\nCheck also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.\n    FSE_endOfDState(&DState);\n*/\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\ntypedef struct {\n    int deltaFindState;\n    U32 deltaNbBits;\n} FSE_symbolCompressionTransform; /* total 8 bytes */\n\nMEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)\n{\n    const void* ptr = ct;\n    const U16* u16ptr = (const U16*) ptr;\n    const U32 tableLog = MEM_read16(ptr);\n    statePtr->value = (ptrdiff_t)1<<tableLog;\n    statePtr->stateTable = u16ptr+2;\n    statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);\n    statePtr->stateLog = tableLog;\n}\n\n\n/*! FSE_initCState2() :\n*   Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)\n*   uses the smallest state value possible, saving the cost of this symbol */\nMEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)\n{\n    FSE_initCState(statePtr, ct);\n    {   const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];\n        const U16* stateTable = (const U16*)(statePtr->stateTable);\n        U32 nbBitsOut  = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);\n        statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;\n        statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];\n    }\n}\n\nMEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)\n{\n    FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];\n    const U16* const stateTable = (const U16*)(statePtr->stateTable);\n    U32 const nbBitsOut  = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);\n    BIT_addBits(bitC, statePtr->value, nbBitsOut);\n    statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];\n}\n\nMEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)\n{\n    BIT_addBits(bitC, statePtr->value, statePtr->stateLog);\n    BIT_flushBits(bitC);\n}\n\n\n/* FSE_getMaxNbBits() :\n * Approximate maximum cost of a symbol, in bits.\n * Fractional get rounded up (i.e : a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)\n * note 1 : assume symbolValue is valid (<= maxSymbolValue)\n * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */\nMEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)\n{\n    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;\n    return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;\n}\n\n/* FSE_bitCost() :\n * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)\n * note 1 : assume symbolValue is valid (<= maxSymbolValue)\n * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */\nMEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)\n{\n    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;\n    U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;\n    U32 const threshold = (minNbBits+1) << 16;\n    assert(tableLog < 16);\n    assert(accuracyLog < 31-tableLog);  /* ensure enough room for renormalization double shift */\n    {   U32 const tableSize = 1 << tableLog;\n        U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);\n        U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog;   /* linear interpolation (very approximate) */\n        U32 const bitMultiplier = 1 << accuracyLog;\n        assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);\n        assert(normalizedDeltaFromThreshold <= bitMultiplier);\n        return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;\n    }\n}\n\n\n/* ======    Decompression    ====== */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;\n    DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n    DStatePtr->state = DInfo.newState + lowBits;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/*! FSE_decodeSymbolFast() :\n    unsafe, only works if no symbol has a probability > 50% */\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#ifndef FSE_MAX_MEMORY_USAGE\n#  define FSE_MAX_MEMORY_USAGE 14\n#endif\n#ifndef FSE_DEFAULT_MEMORY_USAGE\n#  define FSE_DEFAULT_MEMORY_USAGE 13\n#endif\n#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)\n#  error \"FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE\"\n#endif\n\n/*!FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#ifndef FSE_MAX_SYMBOL_VALUE\n#  define FSE_MAX_SYMBOL_VALUE 255\n#endif\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n#define FSE_DECODE_TYPE FSE_decode_t\n\n\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#  error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)\n\n\n#endif /* FSE_STATIC_LINKING_ONLY */\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/hist.h",
    "content": "﻿/* NanaZip Header File Redirection */\n#include \"../../Zstandard/compress/hist.h\"\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/huf.h",
    "content": "﻿/* ******************************************************************\n * huff0 huffman codec,\n * part of Finite State Entropy library\n * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifndef HUF_H_298734234\n#define HUF_H_298734234\n\n/* *** Solve definition conflicts between zstd and NGE library *** */\n#define HUF_optimalTableLog NGEH_optimalTableLog\n#define HUF_readCTable NGEH_readCTable\n#define HUF_buildCTable_wksp NGEH_buildCTable_wksp\n#define HUF_estimateCompressedSize NGEH_estimateCompressedSize\n#define HUF_validateCTable NGEH_validateCTable\n#define HUF_compressBound NGEH_compressBound\n#define HUF_compress1X_usingCTable NGEH_compress1X_usingCTable\n#define HUF_compress4X_usingCTable NGEH_compress4X_usingCTable\n#define HUF_compress1X_repeat NGEH_compress1X_repeat\n#define HUF_compress4X_repeat NGEH_compress4X_repeat\n#define HUF_readDTableX1_wksp NGEH_readDTableX1_wksp\n#define HUF_decompress1X1_DCtx_wksp NGEH_decompress1X1_DCtx_wksp\n#define HUF_readDTableX2_wksp NGEH_readDTableX2_wksp\n#define HUF_decompress1X2_DCtx_wksp NGEH_decompress1X2_DCtx_wksp\n#define HUF_decompress1X_usingDTable NGEH_decompress1X_usingDTable\n#define HUF_decompress4X_usingDTable NGEH_decompress4X_usingDTable\n#define HUF_selectDecoder NGEH_selectDecoder\n#define HUF_decompress4X_hufOnly_wksp NGEH_decompress4X_hufOnly_wksp\n#define HUF_decompress1X_DCtx_wksp NGEH_decompress1X_DCtx_wksp\n#define HUF_compress NGEH_compress\n#define HUF_isError NGEH_isError\n#define HUF_decompress NGEH_decompress\n#define HUF_getErrorName NGEH_getErrorName\n#define HUF_readStats NGEH_readStats\n\n\n/* *** Dependencies *** */\n#include <stddef.h>    /* size_t */\n\n\n/* *** library symbols visibility *** */\n/* Note : when linking with -fvisibility=hidden on gcc, or by default on Visual,\n *        HUF symbols remain \"private\" (internal symbols for library only).\n *        Set macro FSE_DLL_EXPORT to 1 if you want HUF symbols visible on DLL interface */\n#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)\n#  define HUF_PUBLIC_API __attribute__ ((visibility (\"default\")))\n#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1)   /* Visual expected */\n#  define HUF_PUBLIC_API __declspec(dllexport)\n#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)\n#  define HUF_PUBLIC_API __declspec(dllimport)  /* not required, just to generate faster code (saves a function pointer load from IAT and an indirect jump) */\n#else\n#  define HUF_PUBLIC_API\n#endif\n\n\n/* ========================== */\n/* ***  simple functions  *** */\n/* ========================== */\n\n/** HUF_compress() :\n *  Compress content from buffer 'src', of size 'srcSize', into buffer 'dst'.\n * 'dst' buffer must be already allocated.\n *  Compression runs faster if `dstCapacity` >= HUF_compressBound(srcSize).\n * `srcSize` must be <= `HUF_BLOCKSIZE_MAX` == 128 KB.\n * @return : size of compressed data (<= `dstCapacity`).\n *  Special values : if return == 0, srcData is not compressible => Nothing is stored within dst !!!\n *                   if HUF_isError(return), compression failed (more details using HUF_getErrorName())\n */\nHUF_PUBLIC_API size_t HUF_compress(void* dst, size_t dstCapacity,\n                             const void* src, size_t srcSize);\n\n/** HUF_decompress() :\n *  Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',\n *  into already allocated buffer 'dst', of minimum size 'dstSize'.\n * `originalSize` : **must** be the ***exact*** size of original (uncompressed) data.\n *  Note : in contrast with FSE, HUF_decompress can regenerate\n *         RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,\n *         because it knows size to regenerate (originalSize).\n * @return : size of regenerated data (== originalSize),\n *           or an error code, which can be tested using HUF_isError()\n */\nHUF_PUBLIC_API size_t HUF_decompress(void* dst,  size_t originalSize,\n                               const void* cSrc, size_t cSrcSize);\n\n\n/* ***   Tool functions *** */\n#define HUF_BLOCKSIZE_MAX (128 * 1024)                  /**< maximum input size for a single block compressed with HUF_compress */\nHUF_PUBLIC_API size_t HUF_compressBound(size_t size);   /**< maximum compressed size (worst case) */\n\n/* Error Management */\nHUF_PUBLIC_API unsigned    HUF_isError(size_t code);       /**< tells if a return value is an error code */\nHUF_PUBLIC_API const char* HUF_getErrorName(size_t code);  /**< provides error code string (useful for debugging) */\n\n\n/* ***   Advanced function   *** */\n\n/** HUF_compress2() :\n *  Same as HUF_compress(), but offers control over `maxSymbolValue` and `tableLog`.\n * `maxSymbolValue` must be <= HUF_SYMBOLVALUE_MAX .\n * `tableLog` must be `<= HUF_TABLELOG_MAX` . */\nHUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                               unsigned maxSymbolValue, unsigned tableLog);\n\n/** HUF_compress4X_wksp() :\n *  Same as HUF_compress2(), but uses externally allocated `workSpace`.\n * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */\n#define HUF_WORKSPACE_SIZE ((6 << 10) + 256)\n#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))\nHUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,\n                                     const void* src, size_t srcSize,\n                                     unsigned maxSymbolValue, unsigned tableLog,\n                                     void* workSpace, size_t wkspSize);\n\n#endif   /* HUF_H_298734234 */\n\n/* ******************************************************************\n *  WARNING !!\n *  The following section contains advanced and experimental definitions\n *  which shall never be used in the context of a dynamic library,\n *  because they are not guaranteed to remain stable in the future.\n *  Only consider them in association with static linking.\n * *****************************************************************/\n#if defined(HUF_STATIC_LINKING_ONLY) && !defined(HUF_H_HUF_STATIC_LINKING_ONLY)\n#define HUF_H_HUF_STATIC_LINKING_ONLY\n\n/* *** Dependencies *** */\n#include \"mem.h\"   /* U32 */\n\n\n/* *** Constants *** */\n#define HUF_TABLELOG_MAX      12      /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */\n#define HUF_TABLELOG_DEFAULT  11      /* default tableLog value when none specified */\n#define HUF_SYMBOLVALUE_MAX  255\n\n#define HUF_TABLELOG_ABSOLUTEMAX  15  /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)\n#  error \"HUF_TABLELOG_MAX is too large !\"\n#endif\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* HUF buffer bounds */\n#define HUF_CTABLEBOUND 129\n#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true when incompressible is pre-filtered with fast heuristic */\n#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of HUF's Compression Table */\n#define HUF_CTABLE_SIZE_U32(maxSymbolValue)   ((maxSymbolValue)+1)   /* Use tables of U32, for proper alignment */\n#define HUF_CTABLE_SIZE(maxSymbolValue)       (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32))\n#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \\\n    U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \\\n    void* name##hv = &(name##hb); \\\n    HUF_CElt* name = (HUF_CElt*)(name##hv)   /* no final ; */\n\n/* static allocation of HUF's DTable */\ntypedef U32 HUF_DTable;\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<(maxTableLog)))\n#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \\\n        HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) }\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nsize_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\n#endif\n\nsize_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< decodes RLE and uncompressed */\nsize_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */\nsize_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize); /**< considers RLE and uncompressed as errors */\nsize_t HUF_decompress4X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /**< single-symbol decoder */\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\nsize_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /**< double-symbols decoder */\n#endif\n\n\n/* ****************************************\n *  HUF detailed API\n * ****************************************/\n\n/*! HUF_compress() does the following:\n *  1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within \"fse.h\")\n *  2. (optional) refine tableLog using HUF_optimalTableLog()\n *  3. build Huffman table from count using HUF_buildCTable()\n *  4. save Huffman table to memory buffer using HUF_writeCTable()\n *  5. encode the data stream using HUF_compress4X_usingCTable()\n *\n *  The following API allows targeting specific sub-functions for advanced tasks.\n *  For example, it's possible to compress several blocks using the same 'CTable',\n *  or to save and regenerate 'CTable' using external methods.\n */\nunsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);\ntypedef struct HUF_CElt_s HUF_CElt;   /* incomplete type */\nsize_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits);   /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */\nsize_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);\nsize_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);\nsize_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);\nint HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);\n\ntypedef enum {\n   HUF_repeat_none,  /**< Cannot use the previous table */\n   HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */\n   HUF_repeat_valid  /**< Can use the previous table and it is assumed to be valid */\n } HUF_repeat;\n/** HUF_compress4X_repeat() :\n *  Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.\n *  If it uses hufTable it does not modify hufTable or repeat.\n *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.\n *  If preferRepeat then the old table will always be used if valid. */\nsize_t HUF_compress4X_repeat(void* dst, size_t dstSize,\n                       const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned tableLog,\n                       void* workSpace, size_t wkspSize,    /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */\n                       HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);\n\n/** HUF_buildCTable_wksp() :\n *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.\n * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.\n */\n#define HUF_CTABLE_WORKSPACE_SIZE_U32 (2*HUF_SYMBOLVALUE_MAX +1 +1)\n#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))\nsize_t HUF_buildCTable_wksp (HUF_CElt* tree,\n                       const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,\n                             void* workSpace, size_t wkspSize);\n\n/*! HUF_readStats() :\n *  Read compact Huffman tree, saved by HUF_writeCTable().\n * `huffWeight` is destination buffer.\n * @return : size read from `src` , or an error Code .\n *  Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */\nsize_t HUF_readStats(BYTE* huffWeight, size_t hwSize,\n                     U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize);\n\n/** HUF_readCTable() :\n *  Loading a CTable saved with HUF_writeCTable() */\nsize_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);\n\n/** HUF_getNbBits() :\n *  Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX\n *  Note 1 : is not inlined, as HUF_CElt definition is private\n *  Note 2 : const void* used, so that it can provide a statically allocated table as argument (which uses type U32) */\nU32 HUF_getNbBits(const void* symbolTable, U32 symbolValue);\n\n/*\n * HUF_decompress() does the following:\n * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics\n * 2. build Huffman table from save, using HUF_readDTableX?()\n * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()\n */\n\n/** HUF_selectDecoder() :\n *  Tells which decoder is likely to decode faster,\n *  based on a set of pre-computed metrics.\n * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .\n *  Assumption : 0 < dstSize <= 128 KB */\nU32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);\n\n/**\n *  The minimum workspace size for the `workSpace` used in\n *  HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp().\n *\n *  The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when\n *  HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.\n *  Buffer overflow errors may potentially occur if code modifications result in\n *  a required workspace size greater than that specified in the following\n *  macro.\n */\n#define HUF_DECOMPRESS_WORKSPACE_SIZE (2 << 10)\n#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))\n\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_readDTableX1 (HUF_DTable* DTable, const void* src, size_t srcSize);\nsize_t HUF_readDTableX1_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);\n#endif\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_readDTableX2 (HUF_DTable* DTable, const void* src, size_t srcSize);\nsize_t HUF_readDTableX2_wksp (HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize);\n#endif\n\nsize_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress4X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);\n#endif\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);\n#endif\n\n\n/* ====================== */\n/* single stream variants */\n/* ====================== */\n\nsize_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);\nsize_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);  /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */\nsize_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);\n/** HUF_compress1X_repeat() :\n *  Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.\n *  If it uses hufTable it does not modify hufTable or repeat.\n *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.\n *  If preferRepeat then the old table will always be used if valid. */\nsize_t HUF_compress1X_repeat(void* dst, size_t dstSize,\n                       const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned tableLog,\n                       void* workSpace, size_t wkspSize,   /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */\n                       HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);\n\nsize_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */\n#endif\n\nsize_t HUF_decompress1X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\nsize_t HUF_decompress1X_DCtx_wksp (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /**< single-symbol decoder */\n#endif\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress1X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\nsize_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize);   /**< double-symbols decoder */\n#endif\n\nsize_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);   /**< automatic selection of sing or double symbol decoder, based on DTable */\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);\n#endif\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable);\n#endif\n\n/* BMI2 variants.\n * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.\n */\nsize_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);\n#endif\nsize_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2);\nsize_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2);\n\n#endif /* HUF_STATIC_LINKING_ONLY */\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/lizard_entropy_common.c",
    "content": "﻿/* ******************************************************************\n * Common functions of New Generation Entropy library\n * Copyright (c) 2016-2020, Yann Collet, Facebook, Inc.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* *************************************\n*  Dependencies\n***************************************/\n#include \"mem.h\"\n#include \"error_private.h\"       /* ERR_*, ERROR */\n#define FSE_STATIC_LINKING_ONLY  /* FSE_MIN_TABLELOG */\n#include \"fse.h\"\n#define HUF_STATIC_LINKING_ONLY  /* HUF_TABLELOG_ABSOLUTEMAX */\n#include \"huf.h\"\n\n\n/*===   Version   ===*/\nunsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }\n\n\n/*===   Error Management   ===*/\nunsigned FSE_isError(size_t code) { return ERR_isError(code); }\nconst char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\nunsigned HUF_isError(size_t code) { return ERR_isError(code); }\nconst char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/*-**************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nsize_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) {\n        /* This function only works when hbSize >= 4 */\n        char buffer[4] = {0};\n        memcpy(buffer, headerBuffer, hbSize);\n        {   size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,\n                                                    buffer, sizeof(buffer));\n            if (FSE_isError(countSize)) return countSize;\n            if (countSize > hbSize) return ERROR(corruption_detected);\n            return countSize;\n    }   }\n    assert(hbSize >= 4);\n\n    /* init */\n    memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0]));   /* all symbols not present in NCount have a frequency of 0 */\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) & (charnum<=*maxSVPtr)) {\n        if (previous0) {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF) {\n                n0 += 24;\n                if (ip < iend-5) {\n                    ip += 2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                } else {\n                    bitStream >>= 16;\n                    bitCount   += 16;\n            }   }\n            while ((bitStream & 3) == 3) {\n                n0 += 3;\n                bitStream >>= 2;\n                bitCount += 2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                assert((bitCount >> 3) <= 3); /* For first condition to work */\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            } else {\n                bitStream >>= 2;\n        }   }\n        {   int const max = (2*threshold-1) - remaining;\n            int count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = bitStream & (threshold-1);\n                bitCount += nbBits-1;\n            } else {\n                count = bitStream & (2*threshold-1);\n                if (count >= threshold) count -= max;\n                bitCount += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= count < 0 ? -count : count;   /* -1 means +1 */\n            normalizedCounter[charnum++] = (short)count;\n            previous0 = !count;\n            while (remaining < threshold) {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n    }   }   /* while ((remaining>1) & (charnum<=*maxSVPtr)) */\n    if (remaining != 1) return ERROR(corruption_detected);\n    if (bitCount > 32) return ERROR(corruption_detected);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    return ip-istart;\n}\n\n\n/*! HUF_readStats() :\n    Read compact Huffman tree, saved by HUF_writeCTable().\n    `huffWeight` is destination buffer.\n    `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.\n    @return : size read from `src` , or an error Code .\n    Note : Needed by HUF_readCTable() and HUF_readDTableX?() .\n*/\nsize_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128) {  /* special header */\n        oSize = iSize - 127;\n        iSize = ((oSize+1)/2);\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        if (oSize >= hwSize) return ERROR(corruption_detected);\n        ip += 1;\n        {   U32 n;\n            for (n=0; n<oSize; n+=2) {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }\n    else  {   /* header compressed with FSE (normal case) */\n        FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)];  /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSE_decompress_wksp(huffWeight, hwSize-1, ip+1, iSize, fseWorkspace, 6);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));\n    weightTotal = 0;\n    {   U32 n; for (n=0; n<oSize; n++) {\n            if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected);\n            rankStats[huffWeight[n]]++;\n            weightTotal += (1 << huffWeight[n]) >> 1;\n    }   }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    {   U32 const tableLog = BIT_highbit32(weightTotal) + 1;\n        if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected);\n        *tableLogPtr = tableLog;\n        /* determine last weight */\n        {   U32 const total = 1 << tableLog;\n            U32 const rest = total - weightTotal;\n            U32 const verif = 1 << BIT_highbit32(rest);\n            U32 const lastWeight = BIT_highbit32(rest) + 1;\n            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n            huffWeight[oSize] = (BYTE)lastWeight;\n            rankStats[lastWeight]++;\n    }   }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    return iSize+1;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/lizard_fse_compress.c",
    "content": "﻿/* ******************************************************************\n * FSE : Finite State Entropy encoder\n * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include \"compiler.h\"\n#include \"mem.h\"        /* U32, U16, etc. */\n#include \"debug.h\"      /* assert, DEBUGLOG */\n#include \"hist.h\"       /* HIST_count_wksp */\n#include \"bitstream.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n#include \"error_private.h\"\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\n\n/* FSE_buildCTable_wksp() :\n * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).\n * wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`\n * workSpace must also be properly aligned with FSE_FUNCTION_TYPE requirements\n */\nsize_t FSE_buildCTable_wksp(FSE_CTable* ct,\n                      const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,\n                            void* workSpace, size_t wkspSize)\n{\n    U32 const tableSize = 1 << tableLog;\n    U32 const tableMask = tableSize - 1;\n    void* const ptr = ct;\n    U16* const tableU16 = ( (U16*) ptr) + 2;\n    void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;\n    FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);\n    U32 const step = FSE_TABLESTEP(tableSize);\n    U32 cumul[FSE_MAX_SYMBOL_VALUE+2];\n\n    FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)workSpace;\n    U32 highThreshold = tableSize-1;\n\n    /* CTable header */\n    if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) return ERROR(tableLog_tooLarge);\n    tableU16[-2] = (U16) tableLog;\n    tableU16[-1] = (U16) maxSymbolValue;\n    assert(tableLog < 16);   /* required for threshold strategy to work */\n\n    /* For explanations on how to distribute symbol values over the table :\n     * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */\n\n     #ifdef __clang_analyzer__\n     memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize);   /* useless initialization, just to keep scan-build happy */\n     #endif\n\n    /* symbol start positions */\n    {   U32 u;\n        cumul[0] = 0;\n        for (u=1; u <= maxSymbolValue+1; u++) {\n            if (normalizedCounter[u-1]==-1) {  /* Low proba symbol */\n                cumul[u] = cumul[u-1] + 1;\n                tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1);\n            } else {\n                cumul[u] = cumul[u-1] + normalizedCounter[u-1];\n        }   }\n        cumul[maxSymbolValue+1] = tableSize+1;\n    }\n\n    /* Spread symbols */\n    {   U32 position = 0;\n        U32 symbol;\n        for (symbol=0; symbol<=maxSymbolValue; symbol++) {\n            int nbOccurrences;\n            int const freq = normalizedCounter[symbol];\n            for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {\n                tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;\n                position = (position + step) & tableMask;\n                while (position > highThreshold)\n                    position = (position + step) & tableMask;   /* Low proba area */\n        }   }\n\n        assert(position==0);  /* Must have initialized all positions */\n    }\n\n    /* Build table */\n    {   U32 u; for (u=0; u<tableSize; u++) {\n        FSE_FUNCTION_TYPE s = tableSymbol[u];   /* note : static analyzer may not understand tableSymbol is properly initialized */\n        tableU16[cumul[s]++] = (U16) (tableSize+u);   /* TableU16 : sorted by symbol order; gives next state value */\n    }   }\n\n    /* Build Symbol Transformation Table */\n    {   unsigned total = 0;\n        unsigned s;\n        for (s=0; s<=maxSymbolValue; s++) {\n            switch (normalizedCounter[s])\n            {\n            case  0:\n                /* filling nonetheless, for compatibility with FSE_getMaxNbBits() */\n                symbolTT[s].deltaNbBits = ((tableLog+1) << 16) - (1<<tableLog);\n                break;\n\n            case -1:\n            case  1:\n                symbolTT[s].deltaNbBits = (tableLog << 16) - (1<<tableLog);\n                symbolTT[s].deltaFindState = total - 1;\n                total ++;\n                break;\n            default :\n                {\n                    U32 const maxBitsOut = tableLog - BIT_highbit32 (normalizedCounter[s]-1);\n                    U32 const minStatePlus = normalizedCounter[s] << maxBitsOut;\n                    symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;\n                    symbolTT[s].deltaFindState = total - normalizedCounter[s];\n                    total +=  normalizedCounter[s];\n    }   }   }   }\n\n#if 0  /* debug : symbol costs */\n    DEBUGLOG(5, \"\\n --- table statistics : \");\n    {   U32 symbol;\n        for (symbol=0; symbol<=maxSymbolValue; symbol++) {\n            DEBUGLOG(5, \"%3u: w=%3i,   maxBits=%u, fracBits=%.2f\",\n                symbol, normalizedCounter[symbol],\n                FSE_getMaxNbBits(symbolTT, symbol),\n                (double)FSE_bitCost(symbolTT, tableLog, symbol, 8) / 256);\n        }\n    }\n#endif\n\n    return 0;\n}\n\n\nsize_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE];   /* memset() is not necessary, even if static analyzer complain about it */\n    return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol));\n}\n\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n\n/*-**************************************************************\n*  FSE NCount encoding\n****************************************************************/\nsize_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)\n{\n    size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog) >> 3) + 3;\n    return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND;  /* maxSymbolValue==0 ? use default */\n}\n\nstatic size_t\nFSE_writeNCount_generic (void* header, size_t headerBufferSize,\n                   const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,\n                         unsigned writeIsSafe)\n{\n    BYTE* const ostart = (BYTE*) header;\n    BYTE* out = ostart;\n    BYTE* const oend = ostart + headerBufferSize;\n    int nbBits;\n    const int tableSize = 1 << tableLog;\n    int remaining;\n    int threshold;\n    U32 bitStream = 0;\n    int bitCount = 0;\n    unsigned symbol = 0;\n    unsigned const alphabetSize = maxSymbolValue + 1;\n    int previousIs0 = 0;\n\n    /* Table Size */\n    bitStream += (tableLog-FSE_MIN_TABLELOG) << bitCount;\n    bitCount  += 4;\n\n    /* Init */\n    remaining = tableSize+1;   /* +1 for extra accuracy */\n    threshold = tableSize;\n    nbBits = tableLog+1;\n\n    while ((symbol < alphabetSize) && (remaining>1)) {  /* stops at 1 */\n        if (previousIs0) {\n            unsigned start = symbol;\n            while ((symbol < alphabetSize) && !normalizedCounter[symbol]) symbol++;\n            if (symbol == alphabetSize) break;   /* incorrect distribution */\n            while (symbol >= start+24) {\n                start+=24;\n                bitStream += 0xFFFFU << bitCount;\n                if ((!writeIsSafe) && (out > oend-2))\n                    return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n                out[0] = (BYTE) bitStream;\n                out[1] = (BYTE)(bitStream>>8);\n                out+=2;\n                bitStream>>=16;\n            }\n            while (symbol >= start+3) {\n                start+=3;\n                bitStream += 3 << bitCount;\n                bitCount += 2;\n            }\n            bitStream += (symbol-start) << bitCount;\n            bitCount += 2;\n            if (bitCount>16) {\n                if ((!writeIsSafe) && (out > oend - 2))\n                    return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n                out[0] = (BYTE)bitStream;\n                out[1] = (BYTE)(bitStream>>8);\n                out += 2;\n                bitStream >>= 16;\n                bitCount -= 16;\n        }   }\n        {   int count = normalizedCounter[symbol++];\n            int const max = (2*threshold-1) - remaining;\n            remaining -= count < 0 ? -count : count;\n            count++;   /* +1 for extra accuracy */\n            if (count>=threshold)\n                count += max;   /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */\n            bitStream += count << bitCount;\n            bitCount  += nbBits;\n            bitCount  -= (count<max);\n            previousIs0  = (count==1);\n            if (remaining<1) return ERROR(GENERIC);\n            while (remaining<threshold) { nbBits--; threshold>>=1; }\n        }\n        if (bitCount>16) {\n            if ((!writeIsSafe) && (out > oend - 2))\n                return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n            out[0] = (BYTE)bitStream;\n            out[1] = (BYTE)(bitStream>>8);\n            out += 2;\n            bitStream >>= 16;\n            bitCount -= 16;\n    }   }\n\n    if (remaining != 1)\n        return ERROR(GENERIC);  /* incorrect normalized distribution */\n    assert(symbol <= alphabetSize);\n\n    /* flush remaining bitStream */\n    if ((!writeIsSafe) && (out > oend - 2))\n        return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n    out[0] = (BYTE)bitStream;\n    out[1] = (BYTE)(bitStream>>8);\n    out+= (bitCount+7) /8;\n\n    return (out-ostart);\n}\n\n\nsize_t FSE_writeNCount (void* buffer, size_t bufferSize,\n                  const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);   /* Unsupported */\n    if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC);   /* Unsupported */\n\n    if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))\n        return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0);\n\n    return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1 /* write in buffer is safe */);\n}\n\n\n/*-**************************************************************\n*  FSE Compression Code\n****************************************************************/\n\nFSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog)\n{\n    size_t size;\n    if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;\n    size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32);\n    return (FSE_CTable*)malloc(size);\n}\n\nvoid FSE_freeCTable (FSE_CTable* ct) { free(ct); }\n\n/* provides the minimum logSize to safely represent a distribution */\nstatic unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)\n{\n    U32 minBitsSrc = BIT_highbit32((U32)(srcSize)) + 1;\n    U32 minBitsSymbols = BIT_highbit32(maxSymbolValue) + 2;\n    U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    return minBits;\n}\n\nunsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus)\n{\n    U32 maxBitsSrc = BIT_highbit32((U32)(srcSize - 1)) - minus;\n    U32 tableLog = maxTableLog;\n    U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;\n    if (maxBitsSrc < tableLog) tableLog = maxBitsSrc;   /* Accuracy can be reduced */\n    if (minBits > tableLog) tableLog = minBits;   /* Need a minimum to safely represent all symbol values */\n    if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG;\n    if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG;\n    return tableLog;\n}\n\nunsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)\n{\n    return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2);\n}\n\n\n/* Secondary normalization method.\n   To be used when primary method fails. */\n\nstatic size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue)\n{\n    short const NOT_YET_ASSIGNED = -2;\n    U32 s;\n    U32 distributed = 0;\n    U32 ToDistribute;\n\n    /* Init */\n    U32 const lowThreshold = (U32)(total >> tableLog);\n    U32 lowOne = (U32)((total * 3) >> (tableLog + 1));\n\n    for (s=0; s<=maxSymbolValue; s++) {\n        if (count[s] == 0) {\n            norm[s]=0;\n            continue;\n        }\n        if (count[s] <= lowThreshold) {\n            norm[s] = -1;\n            distributed++;\n            total -= count[s];\n            continue;\n        }\n        if (count[s] <= lowOne) {\n            norm[s] = 1;\n            distributed++;\n            total -= count[s];\n            continue;\n        }\n\n        norm[s]=NOT_YET_ASSIGNED;\n    }\n    ToDistribute = (1 << tableLog) - distributed;\n\n    if (ToDistribute == 0)\n        return 0;\n\n    if ((total / ToDistribute) > lowOne) {\n        /* risk of rounding to zero */\n        lowOne = (U32)((total * 3) / (ToDistribute * 2));\n        for (s=0; s<=maxSymbolValue; s++) {\n            if ((norm[s] == NOT_YET_ASSIGNED) && (count[s] <= lowOne)) {\n                norm[s] = 1;\n                distributed++;\n                total -= count[s];\n                continue;\n        }   }\n        ToDistribute = (1 << tableLog) - distributed;\n    }\n\n    if (distributed == maxSymbolValue+1) {\n        /* all values are pretty poor;\n           probably incompressible data (should have already been detected);\n           find max, then give all remaining points to max */\n        U32 maxV = 0, maxC = 0;\n        for (s=0; s<=maxSymbolValue; s++)\n            if (count[s] > maxC) { maxV=s; maxC=count[s]; }\n        norm[maxV] += (short)ToDistribute;\n        return 0;\n    }\n\n    if (total == 0) {\n        /* all of the symbols were low enough for the lowOne or lowThreshold */\n        for (s=0; ToDistribute > 0; s = (s+1)%(maxSymbolValue+1))\n            if (norm[s] > 0) { ToDistribute--; norm[s]++; }\n        return 0;\n    }\n\n    {   U64 const vStepLog = 62 - tableLog;\n        U64 const mid = (1ULL << (vStepLog-1)) - 1;\n        U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total;   /* scale on remaining */\n        U64 tmpTotal = mid;\n        for (s=0; s<=maxSymbolValue; s++) {\n            if (norm[s]==NOT_YET_ASSIGNED) {\n                U64 const end = tmpTotal + (count[s] * rStep);\n                U32 const sStart = (U32)(tmpTotal >> vStepLog);\n                U32 const sEnd = (U32)(end >> vStepLog);\n                U32 const weight = sEnd - sStart;\n                if (weight < 1)\n                    return ERROR(GENERIC);\n                norm[s] = (short)weight;\n                tmpTotal = end;\n    }   }   }\n\n    return 0;\n}\n\n\nsize_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,\n                           const unsigned* count, size_t total,\n                           unsigned maxSymbolValue)\n{\n    /* Sanity checks */\n    if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;\n    if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC);   /* Unsupported size */\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);   /* Unsupported size */\n    if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC);   /* Too small tableLog, compression potentially impossible */\n\n    {   static U32 const rtbTable[] = {     0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };\n        U64 const scale = 62 - tableLog;\n        U64 const step = ((U64)1<<62) / total;   /* <== here, one division ! */\n        U64 const vStep = 1ULL<<(scale-20);\n        int stillToDistribute = 1<<tableLog;\n        unsigned s;\n        unsigned largest=0;\n        short largestP=0;\n        U32 lowThreshold = (U32)(total >> tableLog);\n\n        for (s=0; s<=maxSymbolValue; s++) {\n            if (count[s] == total) return 0;   /* rle special case */\n            if (count[s] == 0) { normalizedCounter[s]=0; continue; }\n            if (count[s] <= lowThreshold) {\n                normalizedCounter[s] = -1;\n                stillToDistribute--;\n            } else {\n                short proba = (short)((count[s]*step) >> scale);\n                if (proba<8) {\n                    U64 restToBeat = vStep * rtbTable[proba];\n                    proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat;\n                }\n                if (proba > largestP) { largestP=proba; largest=s; }\n                normalizedCounter[s] = proba;\n                stillToDistribute -= proba;\n        }   }\n        if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {\n            /* corner case, need another normalization method */\n            size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue);\n            if (FSE_isError(errorCode)) return errorCode;\n        }\n        else normalizedCounter[largest] += (short)stillToDistribute;\n    }\n\n#if 0\n    {   /* Print Table (debug) */\n        U32 s;\n        U32 nTotal = 0;\n        for (s=0; s<=maxSymbolValue; s++)\n            RAWLOG(2, \"%3i: %4i \\n\", s, normalizedCounter[s]);\n        for (s=0; s<=maxSymbolValue; s++)\n            nTotal += abs(normalizedCounter[s]);\n        if (nTotal != (1U<<tableLog))\n            RAWLOG(2, \"Warning !!! Total == %u != %u !!!\", nTotal, 1U<<tableLog);\n        getchar();\n    }\n#endif\n\n    return tableLog;\n}\n\n\n/* fake FSE_CTable, for raw (uncompressed) input */\nsize_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits)\n{\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    void* const ptr = ct;\n    U16* const tableU16 = ( (U16*) ptr) + 2;\n    void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableSize>>1);   /* assumption : tableLog >= 1 */\n    FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);             /* min size */\n\n    /* header */\n    tableU16[-2] = (U16) nbBits;\n    tableU16[-1] = (U16) maxSymbolValue;\n\n    /* Build table */\n    for (s=0; s<tableSize; s++)\n        tableU16[s] = (U16)(tableSize + s);\n\n    /* Build Symbol Transformation Table */\n    {   const U32 deltaNbBits = (nbBits << 16) - (1 << nbBits);\n        for (s=0; s<=maxSymbolValue; s++) {\n            symbolTT[s].deltaNbBits = deltaNbBits;\n            symbolTT[s].deltaFindState = s-1;\n    }   }\n\n    return 0;\n}\n\n/* fake FSE_CTable, for rle input (always same symbol) */\nsize_t FSE_buildCTable_rle (FSE_CTable* ct, BYTE symbolValue)\n{\n    void* ptr = ct;\n    U16* tableU16 = ( (U16*) ptr) + 2;\n    void* FSCTptr = (U32*)ptr + 2;\n    FSE_symbolCompressionTransform* symbolTT = (FSE_symbolCompressionTransform*) FSCTptr;\n\n    /* header */\n    tableU16[-2] = (U16) 0;\n    tableU16[-1] = (U16) symbolValue;\n\n    /* Build table */\n    tableU16[0] = 0;\n    tableU16[1] = 0;   /* just in case */\n\n    /* Build Symbol Transformation Table */\n    symbolTT[symbolValue].deltaNbBits = 0;\n    symbolTT[symbolValue].deltaFindState = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_compress_usingCTable_generic (void* dst, size_t dstSize,\n                           const void* src, size_t srcSize,\n                           const FSE_CTable* ct, const unsigned fast)\n{\n    const BYTE* const istart = (const BYTE*) src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip=iend;\n\n    BIT_CStream_t bitC;\n    FSE_CState_t CState1, CState2;\n\n    /* init */\n    if (srcSize <= 2) return 0;\n    { size_t const initError = BIT_initCStream(&bitC, dst, dstSize);\n      if (FSE_isError(initError)) return 0; /* not enough space available to write a bitstream */ }\n\n#define FSE_FLUSHBITS(s)  (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))\n\n    if (srcSize & 1) {\n        FSE_initCState2(&CState1, ct, *--ip);\n        FSE_initCState2(&CState2, ct, *--ip);\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        FSE_FLUSHBITS(&bitC);\n    } else {\n        FSE_initCState2(&CState2, ct, *--ip);\n        FSE_initCState2(&CState1, ct, *--ip);\n    }\n\n    /* join to mod 4 */\n    srcSize -= 2;\n    if ((sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) && (srcSize & 2)) {  /* test bit 2 */\n        FSE_encodeSymbol(&bitC, &CState2, *--ip);\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        FSE_FLUSHBITS(&bitC);\n    }\n\n    /* 2 or 4 encoding per loop */\n    while ( ip>istart ) {\n\n        FSE_encodeSymbol(&bitC, &CState2, *--ip);\n\n        if (sizeof(bitC.bitContainer)*8 < FSE_MAX_TABLELOG*2+7 )   /* this test must be static */\n            FSE_FLUSHBITS(&bitC);\n\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n\n        if (sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) {  /* this test must be static */\n            FSE_encodeSymbol(&bitC, &CState2, *--ip);\n            FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        }\n\n        FSE_FLUSHBITS(&bitC);\n    }\n\n    FSE_flushCState(&bitC, &CState2);\n    FSE_flushCState(&bitC, &CState1);\n    return BIT_closeCStream(&bitC);\n}\n\nsize_t FSE_compress_usingCTable (void* dst, size_t dstSize,\n                           const void* src, size_t srcSize,\n                           const FSE_CTable* ct)\n{\n    unsigned const fast = (dstSize >= FSE_BLOCKBOUND(srcSize));\n\n    if (fast)\n        return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1);\n    else\n        return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0);\n}\n\n\nsize_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); }\n\n/* FSE_compress_wksp() :\n * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`).\n * `wkspSize` size must be `(1<<tableLog)`.\n */\nsize_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + dstSize;\n\n    unsigned count[FSE_MAX_SYMBOL_VALUE+1];\n    S16   norm[FSE_MAX_SYMBOL_VALUE+1];\n    FSE_CTable* CTable = (FSE_CTable*)workSpace;\n    size_t const CTableSize = FSE_CTABLE_SIZE_U32(tableLog, maxSymbolValue);\n    void* scratchBuffer = (void*)(CTable + CTableSize);\n    size_t const scratchBufferSize = wkspSize - (CTableSize * sizeof(FSE_CTable));\n\n    /* init conditions */\n    if (wkspSize < FSE_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge);\n    if (srcSize <= 1) return 0;  /* Not compressible */\n    if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG;\n\n    /* Scan input and build symbol stats */\n    {   CHECK_V_F(maxCount, HIST_count_wksp(count, &maxSymbolValue, src, srcSize, scratchBuffer, scratchBufferSize) );\n        if (maxCount == srcSize) return 1;   /* only a single symbol in src : rle */\n        if (maxCount == 1) return 0;         /* each symbol present maximum once => not compressible */\n        if (maxCount < (srcSize >> 7)) return 0;   /* Heuristic : not compressible enough */\n    }\n\n    tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue);\n    CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue) );\n\n    /* Write table description header */\n    {   CHECK_V_F(nc_err, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) );\n        op += nc_err;\n    }\n\n    /* Compress */\n    CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, scratchBufferSize) );\n    {   CHECK_V_F(cSize, FSE_compress_usingCTable(op, oend - op, src, srcSize, CTable) );\n        if (cSize == 0) return 0;   /* not enough space for compressed data */\n        op += cSize;\n    }\n\n    /* check compressibility */\n    if ( (size_t)(op-ostart) >= srcSize-1 ) return 0;\n\n    return op-ostart;\n}\n\ntypedef struct {\n    FSE_CTable CTable_max[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)];\n    union {\n      U32 hist_wksp[HIST_WKSP_SIZE_U32];\n      BYTE scratchBuffer[1 << FSE_MAX_TABLELOG];\n    } workspace;\n} fseWkspMax_t;\n\nsize_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog)\n{\n    fseWkspMax_t scratchBuffer;\n    DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE));   /* compilation failures here means scratchBuffer is not large enough */\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer));\n}\n\nsize_t FSE_compress (void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return FSE_compress2(dst, dstCapacity, src, srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG);\n}\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/lizard_fse_decompress.c",
    "content": "﻿/* ******************************************************************\n * FSE : Finite State Entropy decoder\n * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include \"debug.h\"      /* assert */\n#include \"bitstream.h\"\n#include \"compiler.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n#include \"error_private.h\"\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\nFSE_DTable* FSE_createDTable (unsigned tableLog)\n{\n    if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX;\n    return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );\n}\n\nvoid FSE_freeDTable (FSE_DTable* dt)\n{\n    free(dt);\n}\n\nsize_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n    U32 highThreshold = tableSize-1;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    {   FSE_DTableHeader DTableH;\n        DTableH.tableLog = (U16)tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    symbolNext[s] = normalizedCounter[s];\n        }   }   }\n        memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    {   U32 const tableMask = tableSize-1;\n        U32 const step = FSE_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            for (i=0; i<normalizedCounter[s]; i++) {\n                tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n                position = (position + step) & tableMask;\n                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {   U32 u;\n        for (u=0; u<tableSize; u++) {\n            FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);\n            U32 const nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );\n            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n    }   }\n\n    return 0;\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nsize_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSE_decode_t* const cell = (FSE_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nsize_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSV1 = tableMask+1;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<maxSV1; s++) {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n\n    /* Init */\n    CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1) {\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n        *op++ = FSE_GETSYMBOL(&state1);\n        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {\n            *op++ = FSE_GETSYMBOL(&state2);\n            break;\n        }\n\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n        *op++ = FSE_GETSYMBOL(&state2);\n        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {\n            *op++ = FSE_GETSYMBOL(&state1);\n            break;\n    }   }\n\n    return op-ostart;\n}\n\n\nsize_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;\n    const U32 fastMode = DTableH->fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nsize_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n\n    /* normal FSE decoding mode */\n    size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(NCountLength)) return NCountLength;\n    if (tableLog > maxLog) return ERROR(tableLog_tooLarge);\n    assert(NCountLength <= cSrcSize);\n    ip += NCountLength;\n    cSrcSize -= NCountLength;\n\n    CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) );\n\n    return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace);   /* always return, even if it is an error code */\n}\n\n\ntypedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\nsize_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize)\n{\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, dt, FSE_MAX_TABLELOG);\n}\n\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/lizard_huf_compress.c",
    "content": "﻿/* ******************************************************************\n * Huffman encoder, part of New Generation Entropy library\n * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n#include \"compiler.h\"\n#include \"bitstream.h\"\n#include \"hist.h\"\n#define FSE_STATIC_LINKING_ONLY   /* FSE_optimalTableLog_internal */\n#include \"fse.h\"        /* header compression */\n#define HUF_STATIC_LINKING_ONLY\n#include \"huf.h\"\n#include \"error_private.h\"\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n\n#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Utils\n****************************************************************/\nunsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)\n{\n    return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);\n}\n\n\n/* *******************************************************\n*  HUF : Huffman block compression\n*********************************************************/\n/* HUF_compressWeights() :\n * Same as FSE_compress(), but dedicated to huff0's weights compression.\n * The use case needs much less stack memory.\n * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.\n */\n#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6\nstatic size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weightTable, size_t wtSize)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + dstSize;\n\n    unsigned maxSymbolValue = HUF_TABLELOG_MAX;\n    U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;\n\n    FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];\n    BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER];\n\n    unsigned count[HUF_TABLELOG_MAX+1];\n    S16 norm[HUF_TABLELOG_MAX+1];\n\n    /* init conditions */\n    if (wtSize <= 1) return 0;  /* Not compressible */\n\n    /* Scan input and build symbol stats */\n    {   unsigned const maxCount = HIST_count_simple(count, &maxSymbolValue, weightTable, wtSize);   /* never fails */\n        if (maxCount == wtSize) return 1;   /* only a single symbol in src : rle */\n        if (maxCount == 1) return 0;        /* each symbol present maximum once => not compressible */\n    }\n\n    tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);\n    CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) );\n\n    /* Write table description header */\n    {   CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) );\n        op += hSize;\n    }\n\n    /* Compress */\n    CHECK_F( FSE_buildCTable_wksp(CTable, norm, maxSymbolValue, tableLog, scratchBuffer, sizeof(scratchBuffer)) );\n    {   CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, CTable) );\n        if (cSize == 0) return 0;   /* not enough space for compressed data */\n        op += cSize;\n    }\n\n    return (size_t)(op-ostart);\n}\n\n\nstruct HUF_CElt_s {\n  U16  val;\n  BYTE nbBits;\n};   /* typedef'd to HUF_CElt within \"huf.h\" */\n\n/*! HUF_writeCTable() :\n    `CTable` : Huffman tree to save, using huf representation.\n    @return : size of saved CTable */\nsize_t HUF_writeCTable (void* dst, size_t maxDstSize,\n                        const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog)\n{\n    BYTE bitsToWeight[HUF_TABLELOG_MAX + 1];   /* precomputed conversion table */\n    BYTE huffWeight[HUF_SYMBOLVALUE_MAX];\n    BYTE* op = (BYTE*)dst;\n    U32 n;\n\n     /* check conditions */\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);\n\n    /* convert to weight */\n    bitsToWeight[0] = 0;\n    for (n=1; n<huffLog+1; n++)\n        bitsToWeight[n] = (BYTE)(huffLog + 1 - n);\n    for (n=0; n<maxSymbolValue; n++)\n        huffWeight[n] = bitsToWeight[CTable[n].nbBits];\n\n    /* attempt weights compression by FSE */\n    {   CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, huffWeight, maxSymbolValue) );\n        if ((hSize>1) & (hSize < maxSymbolValue/2)) {   /* FSE compressed */\n            op[0] = (BYTE)hSize;\n            return hSize+1;\n    }   }\n\n    /* write raw values as 4-bits (max : 15) */\n    if (maxSymbolValue > (256-128)) return ERROR(GENERIC);   /* should not happen : likely means source cannot be compressed */\n    if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall);   /* not enough space within dst buffer */\n    op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));\n    huffWeight[maxSymbolValue] = 0;   /* to be sure it doesn't cause msan issue in final combination */\n    for (n=0; n<maxSymbolValue; n+=2)\n        op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);\n    return ((maxSymbolValue+1)/2) + 1;\n}\n\n\nsize_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights)\n{\n    BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];   /* init not required, even though some static analyzer may complain */\n    U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n\n    /* get symbol weights */\n    CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));\n\n    /* check result */\n    if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);\n\n    /* Prepare base value per rank */\n    {   U32 n, nextRankStart = 0;\n        for (n=1; n<=tableLog; n++) {\n            U32 current = nextRankStart;\n            nextRankStart += (rankVal[n] << (n-1));\n            rankVal[n] = current;\n    }   }\n\n    /* fill nbBits */\n    *hasZeroWeights = 0;\n    {   U32 n; for (n=0; n<nbSymbols; n++) {\n            const U32 w = huffWeight[n];\n            *hasZeroWeights |= (w == 0);\n            CTable[n].nbBits = (BYTE)(tableLog + 1 - w) & -(w != 0);\n    }   }\n\n    /* fill val */\n    {   U16 nbPerRank[HUF_TABLELOG_MAX+2]  = {0};  /* support w=0=>n=tableLog+1 */\n        U16 valPerRank[HUF_TABLELOG_MAX+2] = {0};\n        { U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[CTable[n].nbBits]++; }\n        /* determine stating value per rank */\n        valPerRank[tableLog+1] = 0;   /* for w==0 */\n        {   U16 min = 0;\n            U32 n; for (n=tableLog; n>0; n--) {  /* start at n=tablelog <-> w=1 */\n                valPerRank[n] = min;     /* get starting value within each rank */\n                min += nbPerRank[n];\n                min >>= 1;\n        }   }\n        /* assign value within rank, symbol order */\n        { U32 n; for (n=0; n<nbSymbols; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }\n    }\n\n    *maxSymbolValuePtr = nbSymbols - 1;\n    return readSize;\n}\n\nU32 HUF_getNbBits(const void* symbolTable, U32 symbolValue)\n{\n    const HUF_CElt* table = (const HUF_CElt*)symbolTable;\n    assert(symbolValue <= HUF_SYMBOLVALUE_MAX);\n    return table[symbolValue].nbBits;\n}\n\n\ntypedef struct nodeElt_s {\n    U32 count;\n    U16 parent;\n    BYTE byte;\n    BYTE nbBits;\n} nodeElt;\n\nstatic U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)\n{\n    const U32 largestBits = huffNode[lastNonNull].nbBits;\n    if (largestBits <= maxNbBits) return largestBits;   /* early exit : no elt > maxNbBits */\n\n    /* there are several too large elements (at least >= 2) */\n    {   int totalCost = 0;\n        const U32 baseCost = 1 << (largestBits - maxNbBits);\n        int n = (int)lastNonNull;\n\n        while (huffNode[n].nbBits > maxNbBits) {\n            totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));\n            huffNode[n].nbBits = (BYTE)maxNbBits;\n            n --;\n        }  /* n stops at huffNode[n].nbBits <= maxNbBits */\n        while (huffNode[n].nbBits == maxNbBits) n--;   /* n end at index of smallest symbol using < maxNbBits */\n\n        /* renorm totalCost */\n        totalCost >>= (largestBits - maxNbBits);  /* note : totalCost is necessarily a multiple of baseCost */\n\n        /* repay normalized cost */\n        {   U32 const noSymbol = 0xF0F0F0F0;\n            U32 rankLast[HUF_TABLELOG_MAX+2];\n\n            /* Get pos of last (smallest) symbol per rank */\n            memset(rankLast, 0xF0, sizeof(rankLast));\n            {   U32 currentNbBits = maxNbBits;\n                int pos;\n                for (pos=n ; pos >= 0; pos--) {\n                    if (huffNode[pos].nbBits >= currentNbBits) continue;\n                    currentNbBits = huffNode[pos].nbBits;   /* < maxNbBits */\n                    rankLast[maxNbBits-currentNbBits] = (U32)pos;\n            }   }\n\n            while (totalCost > 0) {\n                U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1;\n                for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {\n                    U32 const highPos = rankLast[nBitsToDecrease];\n                    U32 const lowPos = rankLast[nBitsToDecrease-1];\n                    if (highPos == noSymbol) continue;\n                    if (lowPos == noSymbol) break;\n                    {   U32 const highTotal = huffNode[highPos].count;\n                        U32 const lowTotal = 2 * huffNode[lowPos].count;\n                        if (highTotal <= lowTotal) break;\n                }   }\n                /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */\n                /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */\n                while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol))\n                    nBitsToDecrease ++;\n                totalCost -= 1 << (nBitsToDecrease-1);\n                if (rankLast[nBitsToDecrease-1] == noSymbol)\n                    rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease];   /* this rank is no longer empty */\n                huffNode[rankLast[nBitsToDecrease]].nbBits ++;\n                if (rankLast[nBitsToDecrease] == 0)    /* special case, reached largest symbol */\n                    rankLast[nBitsToDecrease] = noSymbol;\n                else {\n                    rankLast[nBitsToDecrease]--;\n                    if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease)\n                        rankLast[nBitsToDecrease] = noSymbol;   /* this rank is now empty */\n            }   }   /* while (totalCost > 0) */\n\n            while (totalCost < 0) {  /* Sometimes, cost correction overshoot */\n                if (rankLast[1] == noSymbol) {  /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */\n                    while (huffNode[n].nbBits == maxNbBits) n--;\n                    huffNode[n+1].nbBits--;\n                    assert(n >= 0);\n                    rankLast[1] = (U32)(n+1);\n                    totalCost++;\n                    continue;\n                }\n                huffNode[ rankLast[1] + 1 ].nbBits--;\n                rankLast[1]++;\n                totalCost ++;\n    }   }   }   /* there are several too large elements (at least >= 2) */\n\n    return maxNbBits;\n}\n\ntypedef struct {\n    U32 base;\n    U32 current;\n} rankPos;\n\ntypedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];\n\n#define RANK_POSITION_TABLE_SIZE 32\n\ntypedef struct {\n  huffNodeTable huffNodeTbl;\n  rankPos rankPosition[RANK_POSITION_TABLE_SIZE];\n} HUF_buildCTable_wksp_tables;\n\nstatic void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition)\n{\n    U32 n;\n\n    memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE);\n    for (n=0; n<=maxSymbolValue; n++) {\n        U32 r = BIT_highbit32(count[n] + 1);\n        rankPosition[r].base ++;\n    }\n    for (n=30; n>0; n--) rankPosition[n-1].base += rankPosition[n].base;\n    for (n=0; n<32; n++) rankPosition[n].current = rankPosition[n].base;\n    for (n=0; n<=maxSymbolValue; n++) {\n        U32 const c = count[n];\n        U32 const r = BIT_highbit32(c+1) + 1;\n        U32 pos = rankPosition[r].current++;\n        while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) {\n            huffNode[pos] = huffNode[pos-1];\n            pos--;\n        }\n        huffNode[pos].count = c;\n        huffNode[pos].byte  = (BYTE)n;\n    }\n}\n\n\n/** HUF_buildCTable_wksp() :\n *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.\n *  `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables).\n */\n#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)\n\nsize_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)\n{\n    HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace;\n    nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;\n    nodeElt* const huffNode = huffNode0+1;\n    int nonNullRank;\n    int lowS, lowN;\n    int nodeNb = STARTNODE;\n    int n, nodeRoot;\n\n    /* safety checks */\n    if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC);  /* must be aligned on 4-bytes boundaries */\n    if (wkspSize < sizeof(HUF_buildCTable_wksp_tables))\n      return ERROR(workSpace_tooSmall);\n    if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)\n      return ERROR(maxSymbolValue_tooLarge);\n    memset(huffNode0, 0, sizeof(huffNodeTable));\n\n    /* sort, decreasing order */\n    HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition);\n\n    /* init for parents */\n    nonNullRank = (int)maxSymbolValue;\n    while(huffNode[nonNullRank].count == 0) nonNullRank--;\n    lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb;\n    huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count;\n    huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb;\n    nodeNb++; lowS-=2;\n    for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30);\n    huffNode0[0].count = (U32)(1U<<31);  /* fake entry, strong barrier */\n\n    /* create parents */\n    while (nodeNb <= nodeRoot) {\n        int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;\n        int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;\n        huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count;\n        huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb;\n        nodeNb++;\n    }\n\n    /* distribute weights (unlimited tree height) */\n    huffNode[nodeRoot].nbBits = 0;\n    for (n=nodeRoot-1; n>=STARTNODE; n--)\n        huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;\n    for (n=0; n<=nonNullRank; n++)\n        huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;\n\n    /* enforce maxTableLog */\n    maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits);\n\n    /* fill result into tree (val, nbBits) */\n    {   U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};\n        U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};\n        int const alphabetSize = (int)(maxSymbolValue + 1);\n        if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC);   /* check fit into table */\n        for (n=0; n<=nonNullRank; n++)\n            nbPerRank[huffNode[n].nbBits]++;\n        /* determine stating value per rank */\n        {   U16 min = 0;\n            for (n=(int)maxNbBits; n>0; n--) {\n                valPerRank[n] = min;      /* get starting value within each rank */\n                min += nbPerRank[n];\n                min >>= 1;\n        }   }\n        for (n=0; n<alphabetSize; n++)\n            tree[huffNode[n].byte].nbBits = huffNode[n].nbBits;   /* push nbBits per symbol, symbol order */\n        for (n=0; n<alphabetSize; n++)\n            tree[n].val = valPerRank[tree[n].nbBits]++;   /* assign value within rank, symbol order */\n    }\n\n    return maxNbBits;\n}\n\n/** HUF_buildCTable() :\n * @return : maxNbBits\n *  Note : count is used before tree is written, so they can safely overlap\n */\nsize_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits)\n{\n    HUF_buildCTable_wksp_tables workspace;\n    return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace));\n}\n\nsize_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)\n{\n    size_t nbBits = 0;\n    int s;\n    for (s = 0; s <= (int)maxSymbolValue; ++s) {\n        nbBits += CTable[s].nbBits * count[s];\n    }\n    return nbBits >> 3;\n}\n\nint HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) {\n  int bad = 0;\n  int s;\n  for (s = 0; s <= (int)maxSymbolValue; ++s) {\n    bad |= (count[s] != 0) & (CTable[s].nbBits == 0);\n  }\n  return !bad;\n}\n\nsize_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }\n\nFORCE_INLINE_TEMPLATE void\nHUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable)\n{\n    BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);\n}\n\n#define HUF_FLUSHBITS(s)  BIT_flushBits(s)\n\n#define HUF_FLUSHBITS_1(stream) \\\n    if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*2+7) HUF_FLUSHBITS(stream)\n\n#define HUF_FLUSHBITS_2(stream) \\\n    if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*4+7) HUF_FLUSHBITS(stream)\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,\n                                   const void* src, size_t srcSize,\n                                   const HUF_CElt* CTable)\n{\n    const BYTE* ip = (const BYTE*) src;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart;\n    size_t n;\n    BIT_CStream_t bitC;\n\n    /* init */\n    if (dstSize < 8) return 0;   /* not enough space to compress */\n    { size_t const initErr = BIT_initCStream(&bitC, op, (size_t)(oend-op));\n      if (HUF_isError(initErr)) return 0; }\n\n    n = srcSize & ~3;  /* join to mod 4 */\n    switch (srcSize & 3)\n    {\n        case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable);\n                 HUF_FLUSHBITS_2(&bitC);\n\t\t /* fall-through */\n        case 2 : HUF_encodeSymbol(&bitC, ip[n+ 1], CTable);\n                 HUF_FLUSHBITS_1(&bitC);\n\t\t /* fall-through */\n        case 1 : HUF_encodeSymbol(&bitC, ip[n+ 0], CTable);\n                 HUF_FLUSHBITS(&bitC);\n\t\t /* fall-through */\n        case 0 : /* fall-through */\n        default: break;\n    }\n\n    for (; n>0; n-=4) {  /* note : n&3==0 at this stage */\n        HUF_encodeSymbol(&bitC, ip[n- 1], CTable);\n        HUF_FLUSHBITS_1(&bitC);\n        HUF_encodeSymbol(&bitC, ip[n- 2], CTable);\n        HUF_FLUSHBITS_2(&bitC);\n        HUF_encodeSymbol(&bitC, ip[n- 3], CTable);\n        HUF_FLUSHBITS_1(&bitC);\n        HUF_encodeSymbol(&bitC, ip[n- 4], CTable);\n        HUF_FLUSHBITS(&bitC);\n    }\n\n    return BIT_closeCStream(&bitC);\n}\n\n#if DYNAMIC_BMI2\n\nstatic TARGET_ATTRIBUTE(\"bmi2\") size_t\nHUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,\n                                   const void* src, size_t srcSize,\n                                   const HUF_CElt* CTable)\n{\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\nstatic size_t\nHUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize,\n                                      const void* src, size_t srcSize,\n                                      const HUF_CElt* CTable)\n{\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\nstatic size_t\nHUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, const int bmi2)\n{\n    if (bmi2) {\n        return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable);\n    }\n    return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable);\n}\n\n#else\n\nstatic size_t\nHUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, const int bmi2)\n{\n    (void)bmi2;\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\n#endif\n\nsize_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)\n{\n    return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);\n}\n\n\nstatic size_t\nHUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, int bmi2)\n{\n    size_t const segmentSize = (srcSize+3)/4;   /* first 3 segments */\n    const BYTE* ip = (const BYTE*) src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart;\n\n    if (dstSize < 6 + 1 + 1 + 1 + 8) return 0;   /* minimum space to compress successfully */\n    if (srcSize < 12) return 0;   /* no saving possible : too small input */\n    op += 6;   /* jumpTable */\n\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );\n        if (cSize==0) return 0;\n        assert(cSize <= 65535);\n        MEM_writeLE16(ostart, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );\n        if (cSize==0) return 0;\n        assert(cSize <= 65535);\n        MEM_writeLE16(ostart+2, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );\n        if (cSize==0) return 0;\n        assert(cSize <= 65535);\n        MEM_writeLE16(ostart+4, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    assert(ip <= iend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, bmi2) );\n        if (cSize==0) return 0;\n        op += cSize;\n    }\n\n    return (size_t)(op-ostart);\n}\n\nsize_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)\n{\n    return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);\n}\n\ntypedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;\n\nstatic size_t HUF_compressCTable_internal(\n                BYTE* const ostart, BYTE* op, BYTE* const oend,\n                const void* src, size_t srcSize,\n                HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int bmi2)\n{\n    size_t const cSize = (nbStreams==HUF_singleStream) ?\n                         HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2) :\n                         HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, bmi2);\n    if (HUF_isError(cSize)) { return cSize; }\n    if (cSize==0) { return 0; }   /* incompressible */\n    op += cSize;\n    /* check compressibility */\n    assert(op >= ostart);\n    if ((size_t)(op-ostart) >= srcSize-1) { return 0; }\n    return (size_t)(op-ostart);\n}\n\ntypedef struct {\n    unsigned count[HUF_SYMBOLVALUE_MAX + 1];\n    HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];\n    HUF_buildCTable_wksp_tables buildCTable_wksp;\n} HUF_compress_tables_t;\n\n/* HUF_compress_internal() :\n * `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */\nstatic size_t\nHUF_compress_internal (void* dst, size_t dstSize,\n                 const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned huffLog,\n                       HUF_nbStreams_e nbStreams,\n                       void* workSpace, size_t wkspSize,\n                       HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,\n                 const int bmi2)\n{\n    HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart;\n\n    HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE);\n\n    /* checks & inits */\n    if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC);  /* must be aligned on 4-bytes boundaries */\n    if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall);\n    if (!srcSize) return 0;  /* Uncompressed */\n    if (!dstSize) return 0;  /* cannot fit anything within dst budget */\n    if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);   /* current block size limit */\n    if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);\n    if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX;\n    if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;\n\n    /* Heuristic : If old table is valid, use it for small inputs */\n    if (preferRepeat && repeat && *repeat == HUF_repeat_valid) {\n        return HUF_compressCTable_internal(ostart, op, oend,\n                                           src, srcSize,\n                                           nbStreams, oldHufTable, bmi2);\n    }\n\n    /* Scan input and build symbol stats */\n    {   CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) );\n        if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; }   /* single symbol, rle */\n        if (largest <= (srcSize >> 7)+4) return 0;   /* heuristic : probably not compressible enough */\n    }\n\n    /* Check validity of previous table */\n    if ( repeat\n      && *repeat == HUF_repeat_check\n      && !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) {\n        *repeat = HUF_repeat_none;\n    }\n    /* Heuristic : use existing table for small inputs */\n    if (preferRepeat && repeat && *repeat != HUF_repeat_none) {\n        return HUF_compressCTable_internal(ostart, op, oend,\n                                           src, srcSize,\n                                           nbStreams, oldHufTable, bmi2);\n    }\n\n    /* Build Huffman Tree */\n    huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue);\n    {   size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,\n                                            maxSymbolValue, huffLog,\n                                            &table->buildCTable_wksp, sizeof(table->buildCTable_wksp));\n        CHECK_F(maxBits);\n        huffLog = (U32)maxBits;\n        /* Zero unused symbols in CTable, so we can check it for validity */\n        memset(table->CTable + (maxSymbolValue + 1), 0,\n               sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt)));\n    }\n\n    /* Write table description header */\n    {   CHECK_V_F(hSize, HUF_writeCTable (op, dstSize, table->CTable, maxSymbolValue, huffLog) );\n        /* Check if using previous huffman table is beneficial */\n        if (repeat && *repeat != HUF_repeat_none) {\n            size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);\n            size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue);\n            if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {\n                return HUF_compressCTable_internal(ostart, op, oend,\n                                                   src, srcSize,\n                                                   nbStreams, oldHufTable, bmi2);\n        }   }\n\n        /* Use the new huffman table */\n        if (hSize + 12ul >= srcSize) { return 0; }\n        op += hSize;\n        if (repeat) { *repeat = HUF_repeat_none; }\n        if (oldHufTable)\n            memcpy(oldHufTable, table->CTable, sizeof(table->CTable));  /* Save new table */\n    }\n    return HUF_compressCTable_internal(ostart, op, oend,\n                                       src, srcSize,\n                                       nbStreams, table->CTable, bmi2);\n}\n\n\nsize_t HUF_compress1X_wksp (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize)\n{\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_singleStream,\n                                 workSpace, wkspSize,\n                                 NULL, NULL, 0, 0 /*bmi2*/);\n}\n\nsize_t HUF_compress1X_repeat (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize,\n                      HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)\n{\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_singleStream,\n                                 workSpace, wkspSize, hufTable,\n                                 repeat, preferRepeat, bmi2);\n}\n\nsize_t HUF_compress1X (void* dst, size_t dstSize,\n                 const void* src, size_t srcSize,\n                 unsigned maxSymbolValue, unsigned huffLog)\n{\n    unsigned workSpace[HUF_WORKSPACE_SIZE_U32];\n    return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));\n}\n\n/* HUF_compress4X_repeat():\n * compress input using 4 streams.\n * provide workspace to generate compression tables */\nsize_t HUF_compress4X_wksp (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize)\n{\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_fourStreams,\n                                 workSpace, wkspSize,\n                                 NULL, NULL, 0, 0 /*bmi2*/);\n}\n\n/* HUF_compress4X_repeat():\n * compress input using 4 streams.\n * re-use an existing huffman compression table */\nsize_t HUF_compress4X_repeat (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize,\n                      HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)\n{\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_fourStreams,\n                                 workSpace, wkspSize,\n                                 hufTable, repeat, preferRepeat, bmi2);\n}\n\nsize_t HUF_compress2 (void* dst, size_t dstSize,\n                const void* src, size_t srcSize,\n                unsigned maxSymbolValue, unsigned huffLog)\n{\n    unsigned workSpace[HUF_WORKSPACE_SIZE_U32];\n    return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));\n}\n\nsize_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/lizard_huf_decompress.c",
    "content": "﻿/* ******************************************************************\n * huff0 huffman decoder,\n * part of Finite State Entropy library\n * Copyright (c) 2013-2020, Yann Collet, Facebook, Inc.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Dependencies\n****************************************************************/\n#include <string.h>     /* memcpy, memset */\n#include \"compiler.h\"\n#include \"bitstream.h\"  /* BIT_* */\n#include \"fse.h\"        /* to compress headers */\n#define HUF_STATIC_LINKING_ONLY\n#include \"huf.h\"\n#include \"error_private.h\"\n\n/* **************************************************************\n*  Macros\n****************************************************************/\n\n/* These two optional macros force the use one way or another of the two\n * Huffman decompression implementations. You can't force in both directions\n * at the same time.\n */\n#if defined(HUF_FORCE_DECOMPRESS_X1) && \\\n    defined(HUF_FORCE_DECOMPRESS_X2)\n#error \"Cannot force the use of the X1 and X2 decoders at the same time!\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n\n\n/* **************************************************************\n*  Byte alignment for workSpace management\n****************************************************************/\n#define HUF_ALIGN(x, a)         HUF_ALIGN_MASK((x), (a) - 1)\n#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))\n\n\n/* **************************************************************\n*  BMI2 Variant Wrappers\n****************************************************************/\n#if DYNAMIC_BMI2\n\n#define HUF_DGEN(fn)                                                        \\\n                                                                            \\\n    static size_t fn##_default(                                             \\\n                  void* dst,  size_t dstSize,                               \\\n            const void* cSrc, size_t cSrcSize,                              \\\n            const HUF_DTable* DTable)                                       \\\n    {                                                                       \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }                                                                       \\\n                                                                            \\\n    static TARGET_ATTRIBUTE(\"bmi2\") size_t fn##_bmi2(                       \\\n                  void* dst,  size_t dstSize,                               \\\n            const void* cSrc, size_t cSrcSize,                              \\\n            const HUF_DTable* DTable)                                       \\\n    {                                                                       \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }                                                                       \\\n                                                                            \\\n    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \\\n                     size_t cSrcSize, HUF_DTable const* DTable, int bmi2)   \\\n    {                                                                       \\\n        if (bmi2) {                                                         \\\n            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \\\n        }                                                                   \\\n        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \\\n    }\n\n#else\n\n#define HUF_DGEN(fn)                                                        \\\n    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \\\n                     size_t cSrcSize, HUF_DTable const* DTable, int bmi2)   \\\n    {                                                                       \\\n        (void)bmi2;                                                         \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }\n\n#endif\n\n\n/*-***************************/\n/*  generic DTableDesc       */\n/*-***************************/\ntypedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;\n\nstatic DTableDesc HUF_getDTableDesc(const HUF_DTable* table)\n{\n    DTableDesc dtd;\n    memcpy(&dtd, table, sizeof(dtd));\n    return dtd;\n}\n\n\n#ifndef HUF_FORCE_DECOMPRESS_X2\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1;   /* single-symbol decoding */\n\nsize_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize)\n{\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n    size_t iSize;\n    void* const dtPtr = DTable + 1;\n    HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;\n\n    U32* rankVal;\n    BYTE* huffWeight;\n    size_t spaceUsed32 = 0;\n\n    rankVal = (U32 *)workSpace + spaceUsed32;\n    spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1;\n    huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32);\n    spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;\n\n    if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);\n\n    DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));\n    /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* Table header */\n    {   DTableDesc dtd = HUF_getDTableDesc(DTable);\n        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, Huffman tree cannot fit in */\n        dtd.tableType = 0;\n        dtd.tableLog = (BYTE)tableLog;\n        memcpy(DTable, &dtd, sizeof(dtd));\n    }\n\n    /* Calculate starting value for each rank */\n    {   U32 n, nextRankStart = 0;\n        for (n=1; n<tableLog+1; n++) {\n            U32 const current = nextRankStart;\n            nextRankStart += (rankVal[n] << (n-1));\n            rankVal[n] = current;\n    }   }\n\n    /* fill DTable */\n    {   U32 n;\n        size_t const nEnd = nbSymbols;\n        for (n=0; n<nEnd; n++) {\n            size_t const w = huffWeight[n];\n            size_t const length = (1 << w) >> 1;\n            size_t const uStart = rankVal[w];\n            size_t const uEnd = uStart + length;\n            size_t u;\n            HUF_DEltX1 D;\n            D.byte = (BYTE)n;\n            D.nbBits = (BYTE)(tableLog + 1 - w);\n            rankVal[w] = (U32)uEnd;\n            if (length < 4) {\n                /* Use length in the loop bound so the compiler knows it is short. */\n                for (u = 0; u < length; ++u)\n                    dt[uStart + u] = D;\n            } else {\n                /* Unroll the loop 4 times, we know it is a power of 2. */\n                for (u = uStart; u < uEnd; u += 4) {\n                    dt[u + 0] = D;\n                    dt[u + 1] = D;\n                    dt[u + 2] = D;\n                    dt[u + 3] = D;\n    }   }   }   }\n    return iSize;\n}\n\nsize_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize)\n{\n    U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n    return HUF_readDTableX1_wksp(DTable, src, srcSize,\n                                 workSpace, sizeof(workSpace));\n}\n\nFORCE_INLINE_TEMPLATE BYTE\nHUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n    BYTE const c = dt[val].byte;\n    BIT_skipBits(Dstream, dt[val].nbBits);\n    return c;\n}\n\n#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \\\n    *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr)  \\\n    if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \\\n        HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr)\n\nHINT_INLINE size_t\nHUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {\n        HUF_DECODE_SYMBOLX1_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX1_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX1_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n    }\n\n    /* [0-3] symbols remaining */\n    if (MEM_32bits())\n        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))\n            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress1X1_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + dstSize;\n    const void* dtPtr = DTable + 1;\n    const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;\n    BIT_DStream_t bitD;\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n    U32 const dtLog = dtd.tableLog;\n\n    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );\n\n    HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);\n\n    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress4X1_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        BYTE* const olimit = oend - 3;\n        const void* const dtPtr = DTable + 1;\n        const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n        U32 endSignal = 1;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );\n        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );\n        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );\n        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );\n\n        /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */\n        for ( ; (endSignal) & (op4 < olimit) ; ) {\n            HUF_DECODE_SYMBOLX1_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX1_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX1_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX1_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX1_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX1_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX1_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX1_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX1_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX1_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX1_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX1_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX1_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX1_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX1_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX1_0(op4, &bitD4);\n            endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;\n            endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;\n            endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;\n            endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;\n        }\n\n        /* check corruption */\n        /* note : should not be necessary : op# advance in lock step, and we control op4.\n         *        but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX1(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\ntypedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,\n                                               const void *cSrc,\n                                               size_t cSrcSize,\n                                               const HUF_DTable *DTable);\n\nHUF_DGEN(HUF_decompress1X1_usingDTable_internal)\nHUF_DGEN(HUF_decompress4X1_usingDTable_internal)\n\n\n\nsize_t HUF_decompress1X1_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    DTableDesc dtd = HUF_getDTableDesc(DTable);\n    if (dtd.tableType != 0) return ERROR(GENERIC);\n    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n}\n\nsize_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX1_wksp(DCtx, cSrc, cSrcSize, workSpace, wkspSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);\n}\n\n\nsize_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,\n                              const void* cSrc, size_t cSrcSize)\n{\n    U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n    return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,\n                                       workSpace, sizeof(workSpace));\n}\n\nsize_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);\n    return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\nsize_t HUF_decompress4X1_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    DTableDesc dtd = HUF_getDTableDesc(DTable);\n    if (dtd.tableType != 0) return ERROR(GENERIC);\n    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n}\n\nstatic size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int bmi2)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize,\n                                                workSpace, wkspSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);\n}\n\nsize_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize)\n{\n    return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, 0);\n}\n\n\nsize_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n    return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,\n                                       workSpace, sizeof(workSpace));\n}\nsize_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX);\n    return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n#endif /* HUF_FORCE_DECOMPRESS_X2 */\n\n\n#ifndef HUF_FORCE_DECOMPRESS_X1\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2;  /* double-symbols decoding */\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\ntypedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];\ntypedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];\n\n\n/* HUF_fillDTableX2Level2() :\n * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */\nstatic void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUF_DEltX2 DElt;\n    U32 rankVal[HUF_TABLELOG_MAX + 1];\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1) {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    {   U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */\n            const U32 symbol = sortedSymbols[s].symbol;\n            const U32 weight = sortedSymbols[s].weight;\n            const U32 nbBits = nbBitsBaseline - weight;\n            const U32 length = 1 << (sizeLog-nbBits);\n            const U32 start = rankVal[weight];\n            U32 i = start;\n            const U32 end = start + length;\n\n            MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n            DElt.nbBits = (BYTE)(nbBits + consumed);\n            DElt.length = 2;\n            do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n            rankVal[weight] += length;\n    }   }\n}\n\n\nstatic void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUF_TABLELOG_MAX + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        } else {\n            HUF_DEltX2 DElt;\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits = (BYTE)(nbBits);\n            DElt.length = 1;\n            {   U32 const end = start + length;\n                U32 u;\n                for (u = start; u < end; u++) DTable[u] = DElt;\n        }   }\n        rankVal[weight] += length;\n    }\n}\n\nsize_t HUF_readDTableX2_wksp(HUF_DTable* DTable,\n                       const void* src, size_t srcSize,\n                             void* workSpace, size_t wkspSize)\n{\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    DTableDesc dtd = HUF_getDTableDesc(DTable);\n    U32 const maxTableLog = dtd.maxTableLog;\n    size_t iSize;\n    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */\n    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;\n    U32 *rankStart;\n\n    rankValCol_t* rankVal;\n    U32* rankStats;\n    U32* rankStart0;\n    sortedSymbol_t* sortedSymbol;\n    BYTE* weightList;\n    size_t spaceUsed32 = 0;\n\n    rankVal = (rankValCol_t *)((U32 *)workSpace + spaceUsed32);\n    spaceUsed32 += (sizeof(rankValCol_t) * HUF_TABLELOG_MAX) >> 2;\n    rankStats = (U32 *)workSpace + spaceUsed32;\n    spaceUsed32 += HUF_TABLELOG_MAX + 1;\n    rankStart0 = (U32 *)workSpace + spaceUsed32;\n    spaceUsed32 += HUF_TABLELOG_MAX + 2;\n    sortedSymbol = (sortedSymbol_t *)workSpace + (spaceUsed32 * sizeof(U32)) / sizeof(sortedSymbol_t);\n    spaceUsed32 += HUF_ALIGN(sizeof(sortedSymbol_t) * (HUF_SYMBOLVALUE_MAX + 1), sizeof(U32)) >> 2;\n    weightList = (BYTE *)((U32 *)workSpace + spaceUsed32);\n    spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2;\n\n    if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge);\n\n    rankStart = rankStart0 + 1;\n    memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1));\n\n    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable));   /* if compiler fails here, assertion is wrong */\n    if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    /* memset(weightList, 0, sizeof(weightList)); */  /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {   U32 w, nextRankStart = 0;\n        for (w=1; w<maxW+1; w++) {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {   U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 const w = weightList[s];\n            U32 const r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {   U32* const rankVal0 = rankVal[0];\n        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */\n            U32 nextRankVal = 0;\n            U32 w;\n            for (w=1; w<maxW+1; w++) {\n                U32 current = nextRankVal;\n                nextRankVal += rankStats[w] << (w+rescale);\n                rankVal0[w] = current;\n        }   }\n        {   U32 const minBits = tableLog+1 - maxW;\n            U32 consumed;\n            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {\n                U32* const rankValPtr = rankVal[consumed];\n                U32 w;\n                for (w = 1; w < maxW+1; w++) {\n                    rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }   }\n\n    HUF_fillDTableX2(dt, maxTableLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    dtd.tableLog = (BYTE)maxTableLog;\n    dtd.tableType = 1;\n    memcpy(DTable, &dtd, sizeof(dtd));\n    return iSize;\n}\n\nsize_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize)\n{\n  U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n  return HUF_readDTableX2_wksp(DTable, src, srcSize,\n                               workSpace, sizeof(workSpace));\n}\n\n\nFORCE_INLINE_TEMPLATE U32\nHUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nFORCE_INLINE_TEMPLATE U32\nHUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);\n    else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);\n    }   }\n    return 1;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \\\n        ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog)\n\nHINT_INLINE size_t\nHUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,\n                const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to end : up to 2 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress1X2_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    BIT_DStream_t bitD;\n\n    /* Init */\n    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );\n\n    /* decode */\n    {   BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */\n        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);\n    }\n\n    /* check */\n    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress4X2_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        BYTE* const olimit = oend - (sizeof(size_t)-1);\n        const void* const dtPtr = DTable+1;\n        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal = 1;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );\n        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );\n        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );\n        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        for ( ; (endSignal) & (op4 < olimit); ) {\n#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;\n            endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;\n            endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;\n#else\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal = (U32)LIKELY(\n                        (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)\n                      & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)\n                      & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)\n                      & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));\n#endif\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\nHUF_DGEN(HUF_decompress1X2_usingDTable_internal)\nHUF_DGEN(HUF_decompress4X2_usingDTable_internal)\n\nsize_t HUF_decompress1X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    DTableDesc dtd = HUF_getDTableDesc(DTable);\n    if (dtd.tableType != 1) return ERROR(GENERIC);\n    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n}\n\nsize_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,\n                                               workSpace, wkspSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, /* bmi2 */ 0);\n}\n\n\nsize_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize,\n                              const void* cSrc, size_t cSrcSize)\n{\n    U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n    return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize,\n                                       workSpace, sizeof(workSpace));\n}\n\nsize_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);\n    return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\nsize_t HUF_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    DTableDesc dtd = HUF_getDTableDesc(DTable);\n    if (dtd.tableType != 1) return ERROR(GENERIC);\n    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n}\n\nstatic size_t HUF_decompress4X2_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int bmi2)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,\n                                         workSpace, wkspSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);\n}\n\nsize_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize)\n{\n    return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, /* bmi2 */ 0);\n}\n\n\nsize_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,\n                              const void* cSrc, size_t cSrcSize)\n{\n    U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n    return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,\n                                       workSpace, sizeof(workSpace));\n}\n\nsize_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX);\n    return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n#endif /* HUF_FORCE_DECOMPRESS_X1 */\n\n\n/* ***********************************/\n/* Universal decompression selectors */\n/* ***********************************/\n\nsize_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize,\n                                    const void* cSrc, size_t cSrcSize,\n                                    const HUF_DTable* DTable)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n#else\n    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :\n                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n#endif\n}\n\nsize_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,\n                                    const void* cSrc, size_t cSrcSize,\n                                    const HUF_DTable* DTable)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n#else\n    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0) :\n                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, /* bmi2 */ 0);\n#endif\n}\n\n\n#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n#endif\n\n/** HUF_selectDecoder() :\n *  Tells which decoder is likely to decode faster,\n *  based on a set of pre-computed metrics.\n * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .\n *  Assumption : 0 < dstSize <= 128 KB */\nU32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)\n{\n    assert(dstSize > 0);\n    assert(dstSize <= 128*1024);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dstSize;\n    (void)cSrcSize;\n    return 0;\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dstSize;\n    (void)cSrcSize;\n    return 1;\n#else\n    /* decoder timing evaluation */\n    {   U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 */\n        U32 const D256 = (U32)(dstSize >> 8);\n        U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);\n        U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);\n        DTime1 += DTime1 >> 3;  /* advantage to algorithm using less memory, to reduce cache eviction */\n        return DTime1 < DTime0;\n    }\n#endif\n}\n\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nsize_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)\n    static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 };\n#endif\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);\n#else\n        return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n#endif\n    }\n}\n\nsize_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize);\n#else\n        return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :\n                        HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;\n#endif\n    }\n}\n\nsize_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n    return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize,\n                                         workSpace, sizeof(workSpace));\n}\n\n\nsize_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst,\n                                     size_t dstSize, const void* cSrc,\n                                     size_t cSrcSize, void* workSpace,\n                                     size_t wkspSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize == 0) return ERROR(corruption_detected);\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);\n#else\n        return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                            cSrcSize, workSpace, wkspSize):\n                        HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize);\n#endif\n    }\n}\n\nsize_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                  const void* cSrc, size_t cSrcSize,\n                                  void* workSpace, size_t wkspSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize);\n#else\n        return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize):\n                        HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize);\n#endif\n    }\n}\n\nsize_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize,\n                             const void* cSrc, size_t cSrcSize)\n{\n    U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];\n    return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize,\n                                      workSpace, sizeof(workSpace));\n}\n\n\nsize_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);\n#else\n    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :\n                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);\n#endif\n}\n\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, bmi2);\n}\n#endif\n\nsize_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);\n#else\n    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2) :\n                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, bmi2);\n#endif\n}\n\nsize_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize == 0) return ERROR(corruption_detected);\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);\n#else\n        return algoNb ? HUF_decompress4X2_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2) :\n                        HUF_decompress4X1_DCtx_wksp_bmi2(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, bmi2);\n#endif\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/entropy/mem.h",
    "content": "﻿/* NanaZip Header File Redirection */\n#include \"../../Zstandard/common/mem.h\"\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_common.h",
    "content": "﻿/*\n    Lizard - Fast LZ compression algorithm \n    Copyright (C) 2011-2015, Yann Collet\n    Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>\n\n    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n       - Lizard source repository : https://github.com/inikep/lizard\n*/\n\n#ifndef LIZARD_COMMON_H_2983\n#define LIZARD_COMMON_H_2983\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*-************************************\n*  Memory routines\n**************************************/\n#include <stdlib.h>   /* malloc, calloc, free */\n#include <string.h>   /* memset, memcpy */\n#include <stdint.h>   /* intptr_t */\n#include \"entropy/mem.h\"\n#include \"lizard_compress.h\"      /* LIZARD_GCC_VERSION */\n\n//#define LIZARD_USE_LOGS\n#define LIZARD_LOG_COMPRESS(...) //printf(__VA_ARGS__)\n#define LIZARD_LOG_DECOMPRESS(...) //printf(__VA_ARGS__)\n\n#define LIZARD_LOG_COMPRESS_LZ4(...) //printf(__VA_ARGS__)\n#define COMPLOG_CODEWORDS_LZ4(...) //printf(__VA_ARGS__)\n#define LIZARD_LOG_DECOMPRESS_LZ4(...) //printf(__VA_ARGS__)\n#define DECOMPLOG_CODEWORDS_LZ4(...) //printf(__VA_ARGS__)\n\n#define LIZARD_LOG_COMPRESS_LIZv1(...) //printf(__VA_ARGS__)\n#define COMPLOG_CODEWORDS_LIZv1(...) //printf(__VA_ARGS__)\n#define LIZARD_LOG_DECOMPRESS_LIZv1(...) //printf(__VA_ARGS__)\n#define DECOMPLOG_CODEWORDS_LIZv1(...) //printf(__VA_ARGS__)\n\n\n\n\n/*-************************************\n*  Common Constants\n**************************************/\n#define MINMATCH 4\n//#define USE_LZ4_ONLY\n//#define LIZARD_USE_TEST\n\n#define LIZARD_DICT_SIZE       (1<<24)\n#define WILDCOPYLENGTH      16\n#define LASTLITERALS WILDCOPYLENGTH\n#define MFLIMIT (WILDCOPYLENGTH+MINMATCH)\n\n#define LIZARD_MAX_PRICE           (1<<28)\n#define LIZARD_INIT_LAST_OFFSET    0\n#define LIZARD_MAX_16BIT_OFFSET    (1<<16)\n#define MM_LONGOFF              16\n#define LIZARD_BLOCK_SIZE_PAD      (LIZARD_BLOCK_SIZE+32)\n#define LIZARD_COMPRESS_ADD_BUF    (5*LIZARD_BLOCK_SIZE_PAD)\n#ifndef LIZARD_NO_HUFFMAN\n    #define LIZARD_COMPRESS_ADD_HUF    HUF_compressBound(LIZARD_BLOCK_SIZE_PAD)\n    #define LIZARD_HUF_BLOCK_SIZE      LIZARD_BLOCK_SIZE\n#else\n    #define LIZARD_COMPRESS_ADD_HUF    0\n    #define LIZARD_HUF_BLOCK_SIZE      1\n#endif\n\n/* LZ4 codewords */\n#define ML_BITS_LZ4  4\n#define ML_MASK_LZ4  ((1U<<ML_BITS_LZ4)-1)\n#define RUN_BITS_LZ4 (8-ML_BITS_LZ4)\n#define RUN_MASK_LZ4 ((1U<<RUN_BITS_LZ4)-1)\n\n/* LIZv1 codewords */\n#define ML_BITS_LIZv1       4\n#define RUN_BITS_LIZv1      3\n#define ML_RUN_BITS         (ML_BITS_LIZv1 + RUN_BITS_LIZv1)\n#define MAX_SHORT_LITLEN    7\n#define MAX_SHORT_MATCHLEN  15\n#define LIZARD_LAST_LONG_OFF   31\n\n/* header byte */\n#define LIZARD_FLAG_LITERALS       1\n#define LIZARD_FLAG_FLAGS          2\n#define LIZARD_FLAG_OFFSET16       4\n#define LIZARD_FLAG_OFFSET24       8\n#define LIZARD_FLAG_LEN            16\n#define LIZARD_FLAG_UNCOMPRESSED   128\n\n/* stream numbers */\n#define LIZARD_STREAM_LITERALS       0\n#define LIZARD_STREAM_FLAGS          1\n#define LIZARD_STREAM_OFFSET16       2\n#define LIZARD_STREAM_OFFSET24       3\n#define LIZARD_STREAM_LEN            4\n#define LIZARD_STREAM_UNCOMPRESSED   5\n\n\n\n\ntypedef enum { Lizard_parser_fastSmall, Lizard_parser_fast, Lizard_parser_fastBig, Lizard_parser_noChain, Lizard_parser_hashChain, Lizard_parser_priceFast, Lizard_parser_lowestPrice, Lizard_parser_optimalPrice, Lizard_parser_optimalPriceBT } Lizard_parser_type;   /* from faster to stronger */ \ntypedef enum { Lizard_coderwords_LZ4, Lizard_coderwords_LIZv1 } Lizard_decompress_type;\ntypedef struct\n{\n    U32 windowLog;     /* largest match distance : impact decompression buffer size */\n    U32 contentLog;    /* full search segment : larger == more compression, slower, more memory (useless for fast) */\n    U32 hashLog;       /* dispatch table : larger == more memory, faster*/\n    U32 hashLog3;      /* dispatch table : larger == more memory, faster*/\n    U32 searchNum;     /* nb of searches : larger == more compression, slower*/\n    U32 searchLength;  /* size of matches : larger == faster decompression */\n    U32 minMatchLongOff;  /* min match size with offsets >= 1<<16 */ \n    U32 sufficientLength;  /* used only by optimal parser: size of matches which is acceptable: larger == more compression, slower */\n    U32 fullSearch;    /* used only by optimal parser: perform full search of matches: 1 == more compression, slower */\n    Lizard_parser_type parserType;\n    Lizard_decompress_type decompressType;\n} Lizard_parameters; \n\n\nstruct Lizard_stream_s\n{\n    const BYTE* end;        /* next block here to continue on current prefix */\n    const BYTE* base;       /* All index relative to this position */\n    const BYTE* dictBase;   /* alternate base for extDict */\n    U32   dictLimit;        /* below that point, need extDict */\n    U32   lowLimit;         /* below that point, no more dict */\n    U32   nextToUpdate;     /* index from which to continue dictionary update */\n    U32   allocatedMemory;\n    int   compressionLevel;\n    Lizard_parameters params;\n    U32   hashTableSize;\n    U32   chainTableSize;\n    U32*  chainTable;\n    U32*  hashTable;\n    int   last_off;\n    const BYTE* off24pos;\n    U32   huffType;\n    U32   comprStreamLen;\n\n    BYTE*  huffBase;\n    BYTE*  huffEnd;\n    BYTE*  offset16Base;\n    BYTE*  offset24Base;\n    BYTE*  lenBase;\n    BYTE*  literalsBase;\n    BYTE*  flagsBase;\n    BYTE*  offset16Ptr;\n    BYTE*  offset24Ptr;\n    BYTE*  lenPtr;\n    BYTE*  literalsPtr;\n    BYTE*  flagsPtr;\n    BYTE*  offset16End;\n    BYTE*  offset24End;\n    BYTE*  lenEnd;\n    BYTE*  literalsEnd;\n    BYTE*  flagsEnd;\n    U32 flagFreq[256];\n    U32 litFreq[256];\n    U32 litSum, flagSum;\n    U32 litPriceSum, log2LitSum, log2FlagSum;\n    U32  cachedPrice;\n    U32  cachedLitLength;\n    const BYTE* cachedLiterals; \n    const BYTE* diffBase;\n    const BYTE* srcBase;\n    const BYTE* destBase;\n};\n\nstruct Lizard_streamDecode_s {\n    const BYTE* externalDict;\n    size_t extDictSize;\n    const BYTE* prefixEnd;\n    size_t prefixSize;\n};\n\nstruct Lizard_dstream_s\n{\n    const BYTE*  offset16Ptr;\n    const BYTE*  offset24Ptr;\n    const BYTE*  lenPtr;\n    const BYTE*  literalsPtr;\n    const BYTE*  flagsPtr;\n    const BYTE*  offset16End;\n    const BYTE*  offset24End;\n    const BYTE*  lenEnd;\n    const BYTE*  literalsEnd;\n    const BYTE*  flagsEnd;\n    const BYTE*  diffBase;\n    intptr_t last_off;\n};\n\ntypedef struct Lizard_dstream_s Lizard_dstream_t;\n\n/* *************************************\n*  HC Pre-defined compression levels\n***************************************/\n#define LIZARD_WINDOWLOG_LZ4   16\n#define LIZARD_CHAINLOG_LZ4    LIZARD_WINDOWLOG_LZ4\n#define LIZARD_HASHLOG_LZ4     18\n#define LIZARD_HASHLOG_LZ4SM   12\n\n#define LIZARD_WINDOWLOG_LIZv1 22\n#define LIZARD_CHAINLOG_LIZv1  LIZARD_WINDOWLOG_LIZv1\n#define LIZARD_HASHLOG_LIZv1   18\n\n\n\nstatic const Lizard_parameters Lizard_defaultParameters[LIZARD_MAX_CLEVEL+1-LIZARD_MIN_CLEVEL] =\n{\n    /*               windLog,              contentLog,               HashLog,  H3,  Snum, SL,   MMLongOff, SuffL, FS, Parser function,           Decompressor type  */\n    {   LIZARD_WINDOWLOG_LZ4,                       0,  LIZARD_HASHLOG_LZ4SM,   0,     0,  0,           0,     0,  0, Lizard_parser_fastSmall,      Lizard_coderwords_LZ4   }, // level 10\n    {   LIZARD_WINDOWLOG_LZ4,                       0,    LIZARD_HASHLOG_LZ4,   0,     0,  0,           0,     0,  0, Lizard_parser_fast,           Lizard_coderwords_LZ4   }, // level 11\n    {   LIZARD_WINDOWLOG_LZ4,                       0,    LIZARD_HASHLOG_LZ4,   0,     0,  0,           0,     0,  0, Lizard_parser_noChain,        Lizard_coderwords_LZ4   }, // level 12\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,     2,  5,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 13\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,     4,  5,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 14\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,     8,  5,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 15\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,    16,  4,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 16\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,   256,  4,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 17\n    {   LIZARD_WINDOWLOG_LZ4,   LIZARD_WINDOWLOG_LZ4+1,   LIZARD_HASHLOG_LZ4,  16,    16,  4,           0, 1<<10,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LZ4   }, // level 18\n    {   LIZARD_WINDOWLOG_LZ4,   LIZARD_WINDOWLOG_LZ4+1,                   23,  16,   256,  4,           0, 1<<10,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LZ4   }, // level 19\n    /*              windLog,                contentLog,              HashLog,  H3,  Snum, SL,   MMLongOff, SuffL, FS, Parser function,           Decompressor type  */\n    { LIZARD_WINDOWLOG_LIZv1,                        0,                   14,   0,     1,  5,  MM_LONGOFF,     0,  0, Lizard_parser_fastBig,        Lizard_coderwords_LIZv1 }, // level 20\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1,                   14,  13,     1,  5,  MM_LONGOFF,     0,  0, Lizard_parser_priceFast,      Lizard_coderwords_LIZv1 }, // level 21\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1,  13,     1,  5,  MM_LONGOFF,     0,  0, Lizard_parser_priceFast,      Lizard_coderwords_LIZv1 }, // level 22\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1,  13,     1,  5,  MM_LONGOFF,    64,  0, Lizard_parser_lowestPrice,    Lizard_coderwords_LIZv1 }, // level 23\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1,                   23,  16,     2,  5,  MM_LONGOFF,    64,  0, Lizard_parser_lowestPrice,    Lizard_coderwords_LIZv1 }, // level 24\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1,                   23,  16,     8,  4,  MM_LONGOFF,    64,  0, Lizard_parser_lowestPrice,    Lizard_coderwords_LIZv1 }, // level 25\n    { LIZARD_WINDOWLOG_LIZv1,  LIZARD_CHAINLOG_LIZv1+1,                   23,  16,     8,  4,  MM_LONGOFF,    64,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 26\n    { LIZARD_WINDOWLOG_LIZv1,  LIZARD_CHAINLOG_LIZv1+1,                   23,  16,   128,  4,  MM_LONGOFF,    64,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 27\n    { LIZARD_WINDOWLOG_LIZv1,  LIZARD_CHAINLOG_LIZv1+1,                   23,  24, 1<<10,  4,  MM_LONGOFF, 1<<10,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 28\n    {                     24,                       25,                   23,  24, 1<<10,  4,  MM_LONGOFF, 1<<10,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 29\n#ifndef LIZARD_NO_HUFFMAN\n    /*               windLog,               contentLog,              HashLog,  H3,  Snum, SL,   MMLongOff, SuffL, FS, Parser function,           Decompressor type  */\n    {   LIZARD_WINDOWLOG_LZ4,                        0, LIZARD_HASHLOG_LZ4SM,   0,     0,  0,           0,     0,  0, Lizard_parser_fastSmall,      Lizard_coderwords_LZ4   }, // level 30\n    {   LIZARD_WINDOWLOG_LZ4,                        0,   LIZARD_HASHLOG_LZ4,   0,     0,  0,           0,     0,  0, Lizard_parser_fast,           Lizard_coderwords_LZ4   }, // level 31\n    {   LIZARD_WINDOWLOG_LZ4,                        0,                   14,   0,     0,  0,           0,     0,  0, Lizard_parser_noChain,        Lizard_coderwords_LZ4   }, // level 32\n    {   LIZARD_WINDOWLOG_LZ4,                        0,   LIZARD_HASHLOG_LZ4,   0,     0,  0,           0,     0,  0, Lizard_parser_noChain,        Lizard_coderwords_LZ4   }, // level 33\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,     2,  5,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 34\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,     4,  5,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 35\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,     8,  5,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 36\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,    16,  4,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 37\n    {   LIZARD_WINDOWLOG_LZ4,      LIZARD_CHAINLOG_LZ4,   LIZARD_HASHLOG_LZ4,   0,   256,  4,           0,     0,  0, Lizard_parser_hashChain,      Lizard_coderwords_LZ4   }, // level 38\n    {   LIZARD_WINDOWLOG_LZ4,   LIZARD_WINDOWLOG_LZ4+1,                   23,  16,   256,  4,           0, 1<<10,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LZ4   }, // level 39\n    /*               windLog,               contentLog,              HashLog,  H3,  Snum, SL,   MMLongOff, SuffL, FS, Parser function,           Decompressor type  */\n    { LIZARD_WINDOWLOG_LIZv1,                        0,                   14,   0,     1,  5,  MM_LONGOFF,     0,  0, Lizard_parser_fastBig,        Lizard_coderwords_LIZv1 }, // level 40\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1,                   14,  13,     1,  5,  MM_LONGOFF,     0,  0, Lizard_parser_priceFast,      Lizard_coderwords_LIZv1 }, // level 41\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1,  13,     1,  5,  MM_LONGOFF,     0,  0, Lizard_parser_priceFast,      Lizard_coderwords_LIZv1 }, // level 42\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1, LIZARD_HASHLOG_LIZv1,  13,     1,  5,  MM_LONGOFF,    64,  0, Lizard_parser_lowestPrice,    Lizard_coderwords_LIZv1 }, // level 43\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1,                   23,  16,     2,  5,  MM_LONGOFF,    64,  0, Lizard_parser_lowestPrice,    Lizard_coderwords_LIZv1 }, // level 44\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1,                   23,  16,     8,  4,  MM_LONGOFF,    64,  0, Lizard_parser_lowestPrice,    Lizard_coderwords_LIZv1 }, // level 45\n    { LIZARD_WINDOWLOG_LIZv1,    LIZARD_CHAINLOG_LIZv1,                   23,  16,     8,  4,  MM_LONGOFF,    64,  0, Lizard_parser_optimalPrice,   Lizard_coderwords_LIZv1 }, // level 46\n    { LIZARD_WINDOWLOG_LIZv1,  LIZARD_CHAINLOG_LIZv1+1,                   23,  16,     8,  4,  MM_LONGOFF,    64,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 47\n    { LIZARD_WINDOWLOG_LIZv1,  LIZARD_CHAINLOG_LIZv1+1,                   23,  16,   128,  4,  MM_LONGOFF,    64,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 48\n    {                     24,                       25,                   23,  24, 1<<10,  4,  MM_LONGOFF, 1<<10,  1, Lizard_parser_optimalPriceBT, Lizard_coderwords_LIZv1 }, // level 49\n#endif\n//  {                     10,                       10,                   10,   0,     0,  4,           0,     0,  0, Lizard_fast          }, // min values\n//  {                     24,                       24,                   28,  24, 1<<24,  7,           0, 1<<24,  2, Lizard_optimal_price }, // max values\n};\n\n\n\n/*-************************************\n*  Compiler Options\n**************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4293)        /* disable: C4293: too large shift (32-bits) */\n#else\n#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)   /* C99 */\n#    if defined(__GNUC__) || defined(__clang__)\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif   /* __STDC_VERSION__ */\n#endif  /* _MSC_VER */\n\n#ifdef __clang__\n#define NO_SANITIZE_MEMORY __attribute__((no_sanitize(\"memory\")))\n#else\n#define NO_SANITIZE_MEMORY\n#endif\n\n#define LIZARD_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#if (LIZARD_GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)\n#  define expect(expr,value)    (__builtin_expect ((expr),(value)) )\n#else\n#  define expect(expr,value)    (expr)\n#endif\n\n#define likely(expr)     expect((expr) != 0, 1)\n#define unlikely(expr)   expect((expr) != 0, 0)\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define ALLOCATOR(n,s) calloc(n,s)\n#define FREEMEM        free\n#define MEM_INIT       memset\n#ifndef MAX\n    #define MAX(a,b) ((a)>(b))?(a):(b)\n#endif\n#ifndef MIN\n\t#define MIN(a,b) ((a)<(b)?(a):(b))\n#endif\n\n#if MINMATCH == 3\n    #define MEM_readMINMATCH(ptr) (U32)(MEM_read32(ptr)<<8) \n#else\n    #define MEM_readMINMATCH(ptr) (U32)(MEM_read32(ptr)) \n#endif \n\n\n\n\n/*-************************************\n*  Reading and writing into memory\n**************************************/\n#define STEPSIZE sizeof(size_t)\n\n\nMEM_STATIC void Lizard_copy8(void* dst, const void* src)\n{\n    memcpy(dst,src,8);\n}\n\n/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */\nMEM_STATIC void Lizard_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)\n{\n    BYTE* d = (BYTE*)dstPtr;\n    const BYTE* s = (const BYTE*)srcPtr;\n    BYTE* const e = (BYTE*)dstEnd;\n\n#if 0\n    const size_t l2 = 8 - (((size_t)d) & (sizeof(void*)-1));\n    Lizard_copy8(d,s); if (d>e-9) return;\n    d+=l2; s+=l2;\n#endif /* join to align */\n\n    do { Lizard_copy8(d,s); d+=8; s+=8; } while (d<e);\n}\n\nMEM_STATIC void Lizard_wildCopy16(BYTE* dstPtr, const BYTE* srcPtr, BYTE* dstEnd)\n{\n    do {\n        Lizard_copy8(dstPtr, srcPtr);\n        Lizard_copy8(dstPtr+8, srcPtr+8);\n        dstPtr += 16;\n        srcPtr += 16;\n    }\n    while (dstPtr < dstEnd);\n}\n\n/*\n * LIZARD_FORCE_SW_BITCOUNT\n * Define this parameter if your target system or compiler does not support hardware bit count\n */\n#if defined(_MSC_VER) && defined(_WIN32_WCE)   /* Visual Studio for Windows CE does not support Hardware bit count */\n#  define LIZARD_FORCE_SW_BITCOUNT\n#endif\n\n\n/* **************************************\n*  Function body to include for inlining\n****************************************/\nMEM_STATIC U32 Lizard_highbit32(U32 val) NO_SANITIZE_MEMORY\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r=0;\n    _BitScanReverse(&r, val);\n    return (unsigned)r;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* GCC Intrinsic */\n    return 31 - __builtin_clz(val);\n#   else   /* Software version */\n    static const int DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    int r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[(U32)(v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n/*-************************************\n*  Common functions\n**************************************/\nMEM_STATIC unsigned Lizard_NbCommonBytes (size_t val)\n{\n    if (MEM_isLittleEndian()) {\n        if (MEM_64bits()) {\n#       if defined(_MSC_VER) && defined(_WIN64) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            unsigned long r = 0;\n            _BitScanForward64( &r, (U64)val );\n            return (int)(r>>3);\n#       elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            return (__builtin_ctzll((U64)val) >> 3);\n#       else\n            static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };\n            return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];\n#       endif\n        } else /* 32 bits */ {\n#       if defined(_MSC_VER) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            unsigned long r;\n            _BitScanForward( &r, (U32)val );\n            return (int)(r>>3);\n#       elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            return (__builtin_ctz((U32)val) >> 3);\n#       else\n            static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };\n            return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];\n#       endif\n        }\n    } else   /* Big Endian CPU */ {\n        if (MEM_64bits()) {\n#       if defined(_MSC_VER) && defined(_WIN64) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            unsigned long r = 0;\n            _BitScanReverse64( &r, val );\n            return (unsigned)(r>>3);\n#       elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            return (__builtin_clzll((U64)val) >> 3);\n#       else\n            unsigned r;\n            if (!(val>>32)) { r=4; } else { r=0; val>>=32; }\n            if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }\n            r += (!val);\n            return r;\n#       endif\n        } else /* 32 bits */ {\n#       if defined(_MSC_VER) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            unsigned long r = 0;\n            _BitScanReverse( &r, (unsigned long)val );\n            return (unsigned)(r>>3);\n#       elif (defined(__clang__) || (LIZARD_GCC_VERSION >= 304)) && !defined(LIZARD_FORCE_SW_BITCOUNT)\n            return (__builtin_clz((U32)val) >> 3);\n#       else\n            unsigned r;\n            if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }\n            r += (!val);\n            return r;\n#       endif\n        }\n    }\n}\n\nMEM_STATIC unsigned Lizard_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)\n{\n    const BYTE* const pStart = pIn;\n\n    while (likely(pIn<pInLimit-(STEPSIZE-1))) {\n        size_t diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n        if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }\n        pIn += Lizard_NbCommonBytes(diff);\n        return (unsigned)(pIn - pStart);\n    }\n\n    if (MEM_64bits()) if ((pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }\n    if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }\n    if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;\n    return (unsigned)(pIn - pStart);\n}\n\n/* alias to functions with compressionLevel=1 */\nint Lizard_sizeofState_MinLevel(void);\nint Lizard_compress_MinLevel(const char* source, char* dest, int sourceSize, int maxDestSize);\nint Lizard_compress_extState_MinLevel (void* state, const char* source, char* dest, int inputSize, int maxDestSize);\nLizard_stream_t* Lizard_resetStream_MinLevel (Lizard_stream_t* streamPtr);\nLizard_stream_t* Lizard_createStream_MinLevel(void);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* LIZARD_COMMON_H_2983827168210 */\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_compress.c",
    "content": "﻿/*\n    Lizard - Fast LZ compression algorithm \n    Copyright (C) 2011-2015, Yann Collet\n    Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>\n\n    BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOTLizard_hash4Ptr\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n       - Lizard source repository : https://github.com/inikep/lizard\n*/\n\n\n/* *************************************\n*  Includes\n***************************************/\n#include \"lizard_compress.h\"\n#include \"lizard_common.h\"\n#include <stdio.h>\n#include <stdint.h> // intptr_t\n#ifndef USE_LZ4_ONLY\n    #ifdef LIZARD_USE_TEST\n        #include \"test/lizard_common_test.h\"\n        #include \"test/lizard_compress_test.h\"\n    #else\n        #include \"lizard_compress_liz.h\"\n    #endif\n#endif\n#include \"lizard_compress_lz4.h\"\n#include \"entropy/huf.h\"\n\n\n/* *************************************\n*  Local Macros\n***************************************/\n#define DELTANEXT(p)        chainTable[(p) & contentMask]\n#define LIZARD_MINIMAL_HUFF_GAIN(comprSize) (comprSize + (comprSize/8) + 512)\n#define LIZARD_MINIMAL_BLOCK_GAIN(comprSize) (comprSize + (comprSize/32) + 512)\n\n\n/*-************************************\n*  Local Utils\n**************************************/\nint Lizard_versionNumber (void) { return LIZARD_VERSION_NUMBER; }\nint Lizard_compressBound(int isize)  { return LIZARD_COMPRESSBOUND(isize); }\nint Lizard_sizeofState_MinLevel(void) { return Lizard_sizeofState(LIZARD_MIN_CLEVEL); }\n\n\n\n/* *************************************\n*  Hash functions\n***************************************/\n#define HASH_UPDATE_LIMIT 8  /* equal to MEM_read64 */\nstatic const U32 prime4bytes = 2654435761U;\nstatic const U64 prime5bytes = 889523592379ULL;\nstatic const U64 prime6bytes = 227718039650203ULL;\nstatic const U64 prime7bytes = 58295818150454627ULL;\n\n#if MINMATCH == 3\nstatic const U32 prime3bytes = 506832829U;\nstatic U32 Lizard_hash3(U32 u, U32 h) { return (u * prime3bytes) << (32-24) >> (32-h) ; }\nstatic size_t Lizard_hash3Ptr(const void* ptr, U32 h) { return Lizard_hash3(MEM_read32(ptr), h); }\n#endif\n\nstatic U32 Lizard_hash4(U32 u, U32 h) { return (u * prime4bytes) >> (32-h) ; }\nstatic size_t Lizard_hash4Ptr(const void* ptr, U32 h) { return Lizard_hash4(MEM_read32(ptr), h); }\n\nstatic size_t Lizard_hash5(U64 u, U32 h) { return (size_t)((u * prime5bytes) << (64-40) >> (64-h)) ; }\nstatic size_t Lizard_hash5Ptr(const void* p, U32 h) { return Lizard_hash5(MEM_read64(p), h); }\n\nstatic size_t Lizard_hash6(U64 u, U32 h) { return (size_t)((u * prime6bytes) << (64-48) >> (64-h)) ; }\nstatic size_t Lizard_hash6Ptr(const void* p, U32 h) { return Lizard_hash6(MEM_read64(p), h); }\n\nstatic size_t Lizard_hash7(U64 u, U32 h) { return (size_t)((u * prime7bytes) << (64-56) >> (64-h)) ; }\nstatic size_t Lizard_hash7Ptr(const void* p, U32 h) { return Lizard_hash7(MEM_read64(p), h); }\n\nstatic size_t Lizard_hashPtr(const void* p, U32 hBits, U32 mls)\n{\n    switch(mls)\n    {\n    default:\n    case 4: return Lizard_hash4Ptr(p, hBits);\n    case 5: return Lizard_hash5Ptr(p, hBits);\n    case 6: return Lizard_hash6Ptr(p, hBits);\n    case 7: return Lizard_hash7Ptr(p, hBits);\n    }\n} \n\n\n\n\n/**************************************\n*  Internal functions\n**************************************/\n/** Lizard_count_2segments() :\n*   can count match length with `ip` & `match` in 2 different segments.\n*   convention : on reaching mEnd, match count continue starting from iStart\n*/\nstatic size_t Lizard_count_2segments(const BYTE* ip, const BYTE* match, const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)\n{\n    const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);\n    size_t const matchLength = Lizard_count(ip, match, vEnd);\n    if (match + matchLength != mEnd) return matchLength;\n    return matchLength + Lizard_count(ip+matchLength, iStart, iEnd);\n}\n\n\nvoid Lizard_initBlock(Lizard_stream_t* ctx)\n{\n    ctx->offset16Ptr = ctx->offset16Base;\n    ctx->offset24Ptr = ctx->offset24Base;\n    ctx->lenPtr      = ctx->lenBase;\n    ctx->literalsPtr = ctx->literalsBase;\n    ctx->flagsPtr = ctx->flagsBase;\n    ctx->last_off = LIZARD_INIT_LAST_OFFSET; /* reset last offset */\n}\n\n\nFORCE_INLINE int Lizard_writeStream(int useHuff, Lizard_stream_t* ctx, BYTE* streamPtr, uint32_t streamLen, BYTE** op, BYTE* oend)\n{\n    if (useHuff && streamLen > 1024) {\n#ifndef LIZARD_NO_HUFFMAN\n        int useHuffBuf;\n        if (*op + 6 > oend) { LIZARD_LOG_COMPRESS(\"*op[%p] + 6 > oend[%p]\\n\", *op, oend); return -1; }\n\n        useHuffBuf = ((size_t)(oend - (*op + 6)) < HUF_compressBound(streamLen)); \n        if (useHuffBuf) {\n            if (streamLen > LIZARD_BLOCK_SIZE) { LIZARD_LOG_COMPRESS(\"streamLen[%d] > LIZARD_BLOCK_SIZE\\n\", streamLen); return -1; }\n            ctx->comprStreamLen = (U32)HUF_compress(ctx->huffBase, ctx->huffEnd - ctx->huffBase, streamPtr, streamLen);\n        } else {\n            ctx->comprStreamLen = (U32)HUF_compress(*op + 6, oend - (*op + 6), streamPtr, streamLen);\n        }\n\n        if (!HUF_isError(ctx->comprStreamLen)) {\n            if (ctx->comprStreamLen > 0 && (LIZARD_MINIMAL_HUFF_GAIN(ctx->comprStreamLen) < streamLen)) { /* compressible */\n                MEM_writeLE24(*op, streamLen);\n                MEM_writeLE24(*op+3, ctx->comprStreamLen);\n                if (useHuffBuf) {\n                    if ((size_t)(oend - (*op + 6)) < ctx->comprStreamLen) { LIZARD_LOG_COMPRESS(\"*op[%p] oend[%p] comprStreamLen[%d]\\n\", *op, oend, (int)ctx->comprStreamLen); return -1; }\n                    memcpy(*op + 6, ctx->huffBase, ctx->comprStreamLen);\n                }\n                *op += ctx->comprStreamLen + 6;\n                LIZARD_LOG_COMPRESS(\"HUF_compress streamLen=%d comprStreamLen=%d\\n\", (int)streamLen, (int)ctx->comprStreamLen);\n                return 1;\n            } else { LIZARD_LOG_COMPRESS(\"HUF_compress ERROR comprStreamLen=%d streamLen=%d\\n\", (int)ctx->comprStreamLen, (int)streamLen); }\n        } else { LIZARD_LOG_COMPRESS(\"HUF_compress ERROR %d: %s\\n\", (int)ctx->comprStreamLen, HUF_getErrorName(ctx->comprStreamLen)); }\n#else\n        LIZARD_LOG_COMPRESS(\"compiled with LIZARD_NO_HUFFMAN\\n\");\n        (void)ctx;\n        return -1; \n#endif\n    } else ctx->comprStreamLen = 0;\n\n    if (*op + 3 + streamLen > oend) { LIZARD_LOG_COMPRESS(\"*op[%p] + 3 + streamLen[%d] > oend[%p]\\n\", *op, streamLen, oend); return -1; }\n    MEM_writeLE24(*op, streamLen);\n    *op += 3;\n    memcpy(*op, streamPtr, streamLen);\n    *op += streamLen;\n    LIZARD_LOG_COMPRESS(\"Uncompressed streamLen=%d\\n\", (int)streamLen);\n    return 0;\n}\n\n\nint Lizard_writeBlock(Lizard_stream_t* ctx, const BYTE* ip, uint32_t inputSize, BYTE** op, BYTE* oend)\n{\n    int res;\n    uint32_t flagsLen = (uint32_t)(ctx->flagsPtr - ctx->flagsBase);\n    uint32_t literalsLen = (uint32_t)(ctx->literalsPtr - ctx->literalsBase);\n    uint32_t lenLen = (uint32_t)(ctx->lenPtr - ctx->lenBase);\n    uint32_t offset16Len = (uint32_t)(ctx->offset16Ptr - ctx->offset16Base);\n    uint32_t offset24Len = (uint32_t)(ctx->offset24Ptr - ctx->offset24Base);\n    uint32_t sum = flagsLen + literalsLen + lenLen + offset16Len + offset24Len;\n#ifdef LIZARD_USE_LOGS\n    uint32_t comprFlagsLen, comprLiteralsLen;\n#endif\n\n    BYTE* start = *op;\n    \n    if ((literalsLen < WILDCOPYLENGTH) || (sum+5*3+1 > inputSize)) goto _write_uncompressed;\n\n    *start = 0;\n    *op += 1;\n\n    res = Lizard_writeStream(0, ctx, ctx->lenBase, lenLen, op, oend);\n    if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_LEN);\n\n    res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_OFFSET16, ctx, ctx->offset16Base, offset16Len, op, oend);\n    if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_OFFSET16);\n\n    res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_OFFSET24, ctx, ctx->offset24Base, offset24Len, op, oend);\n    if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_OFFSET24);\n\n    res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_FLAGS, ctx, ctx->flagsBase, flagsLen, op, oend);\n    if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_FLAGS);\n#ifdef LIZARD_USE_LOGS\n    comprFlagsLen = ctx->comprStreamLen;\n#endif\n\n    res = Lizard_writeStream(ctx->huffType&LIZARD_FLAG_LITERALS, ctx, ctx->literalsBase, literalsLen, op, oend);\n    if (res < 0) goto _output_error; else *start += (BYTE)(res*LIZARD_FLAG_LITERALS);\n#ifdef LIZARD_USE_LOGS\n    comprLiteralsLen = ctx->comprStreamLen;\n    sum = (int)(*op-start);\n#endif\n\n    if (LIZARD_MINIMAL_BLOCK_GAIN((uint32_t)(*op-start)) > inputSize) goto _write_uncompressed;\n\n    LIZARD_LOG_COMPRESS(\"%d: total=%d block=%d flagsLen[%.2f%%]=%d comprFlagsLen[%.2f%%]=%d literalsLen[%.2f%%]=%d comprLiteralsLen[%.2f%%]=%d lenLen=%d offset16Len[%.2f%%]=%d offset24Len[%.2f%%]=%d\\n\", (int)(ip - ctx->srcBase),\n            (int)(*op - ctx->destBase), sum, (flagsLen*100.0)/sum, flagsLen, (comprFlagsLen*100.0)/sum, comprFlagsLen, (literalsLen*100.0)/sum, literalsLen, (comprLiteralsLen*100.0)/sum, comprLiteralsLen,\n            lenLen, (offset16Len*100.0)/sum, offset16Len, (offset24Len*100.0)/sum, offset24Len);\n    return 0;\n\n_write_uncompressed:\n    LIZARD_LOG_COMPRESS(\"%d: total=%d block=%d UNCOMPRESSED inputSize=%u outSize=%d\\n\", (int)(ip - ctx->srcBase),\n            (int)(*op - ctx->destBase), (int)(*op-start), inputSize, (int)(oend-start));\n    if ((uint32_t)(oend - start) < inputSize + 4) goto _output_error;\n    *start = LIZARD_FLAG_UNCOMPRESSED;\n    *op = start + 1;\n    MEM_writeLE24(*op, inputSize);\n    *op += 3;\n    memcpy(*op, ip, inputSize);\n    *op += inputSize;\n    return 0;\n\n_output_error:\n    LIZARD_LOG_COMPRESS(\"Lizard_writeBlock ERROR size=%d/%d flagsLen=%d literalsLen=%d lenLen=%d offset16Len=%d offset24Len=%d\\n\", (int)(*op-start), (int)(oend-start), flagsLen, literalsLen, lenLen, offset16Len, offset24Len);\n    return 1;\n}\n\n\nFORCE_INLINE int Lizard_encodeSequence (\n    Lizard_stream_t* ctx,\n    const BYTE** ip,\n    const BYTE** anchor,\n    size_t matchLength,\n    const BYTE* const match)\n{\n#ifdef USE_LZ4_ONLY\n    return Lizard_encodeSequence_LZ4(ctx, ip, anchor, matchLength, match);\n#else\n    if (ctx->params.decompressType == Lizard_coderwords_LZ4)\n        return Lizard_encodeSequence_LZ4(ctx, ip, anchor, matchLength, match);\n\n    return Lizard_encodeSequence_LIZv1(ctx, ip, anchor, matchLength, match);\n#endif\n}\n\n\nFORCE_INLINE int Lizard_encodeLastLiterals (\n    Lizard_stream_t* ctx,\n    const BYTE** ip,\n    const BYTE** anchor)\n{\n    LIZARD_LOG_COMPRESS(\"Lizard_encodeLastLiterals Lizard_coderwords_LZ4=%d\\n\", ctx->params.decompressType == Lizard_coderwords_LZ4);    \n#ifdef USE_LZ4_ONLY\n    return Lizard_encodeLastLiterals_LZ4(ctx, ip, anchor);\n#else\n    if (ctx->params.decompressType == Lizard_coderwords_LZ4)\n        return Lizard_encodeLastLiterals_LZ4(ctx, ip, anchor);\n\n    return Lizard_encodeLastLiterals_LIZv1(ctx, ip, anchor);\n#endif\n}\n\n\n/**************************************\n*  Include parsers\n**************************************/\n#include \"lizard_parser_hashchain.h\"\n#include \"lizard_parser_nochain.h\"\n#include \"lizard_parser_fast.h\"\n#include \"lizard_parser_fastsmall.h\"\n#include \"lizard_parser_fastbig.h\"\n#ifndef USE_LZ4_ONLY\n    #include \"lizard_parser_optimal.h\"\n    #include \"lizard_parser_lowestprice.h\"\n    #include \"lizard_parser_pricefast.h\"\n#endif\n\n\nint Lizard_verifyCompressionLevel(int compressionLevel)\n{\n    if (compressionLevel > LIZARD_MAX_CLEVEL) compressionLevel = LIZARD_MAX_CLEVEL;\n    if (compressionLevel < LIZARD_MIN_CLEVEL) compressionLevel = LIZARD_DEFAULT_CLEVEL;\n    return compressionLevel;\n}\n\n\nint Lizard_sizeofState(int compressionLevel) \n{ \n    Lizard_parameters params;\n    U32 hashTableSize, chainTableSize;\n\n    compressionLevel = Lizard_verifyCompressionLevel(compressionLevel);\n    params = Lizard_defaultParameters[compressionLevel - LIZARD_MIN_CLEVEL];\n//    hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog3)+((size_t)1 << params.hashLog)));\n    hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog)));\n    chainTableSize = (U32)(sizeof(U32)*((size_t)1 << params.contentLog));\n\n    return sizeof(Lizard_stream_t) + hashTableSize + chainTableSize + LIZARD_COMPRESS_ADD_BUF + (int)LIZARD_COMPRESS_ADD_HUF;\n}\n\n\nstatic void Lizard_init(Lizard_stream_t* ctx, const BYTE* start)\n{\n // No need to use memset() on tables as values are always bound checked\n#ifdef LIZARD_RESET_MEM\n    MEM_INIT((void*)ctx->hashTable, 0, ctx->hashTableSize);\n    MEM_INIT(ctx->chainTable, 0x01, ctx->chainTableSize);\n#endif\n //   printf(\"memset hashTable=%p hashEnd=%p chainTable=%p chainEnd=%p\\n\", ctx->hashTable, ((BYTE*)ctx->hashTable) + ctx->hashTableSize, ctx->chainTable, ((BYTE*)ctx->chainTable)+ctx->chainTableSize);\n    ctx->nextToUpdate = LIZARD_DICT_SIZE;\n    ctx->base = start - LIZARD_DICT_SIZE;\n    ctx->end = start;\n    ctx->dictBase = start - LIZARD_DICT_SIZE;\n    ctx->dictLimit = LIZARD_DICT_SIZE;\n    ctx->lowLimit = LIZARD_DICT_SIZE;\n    ctx->last_off = LIZARD_INIT_LAST_OFFSET;\n    ctx->litSum = 0;\n}\n\n\n/* if ctx==NULL memory is allocated and returned as value */\nLizard_stream_t* Lizard_initStream(Lizard_stream_t* ctx, int compressionLevel) \n{ \n    Lizard_parameters params;\n    U32 hashTableSize, chainTableSize;\n    void *tempPtr;\n\n    compressionLevel = Lizard_verifyCompressionLevel(compressionLevel);\n    params = Lizard_defaultParameters[compressionLevel - LIZARD_MIN_CLEVEL];\n//    hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog3)+((size_t)1 << params.hashLog)));\n    hashTableSize = (U32)(sizeof(U32)*(((size_t)1 << params.hashLog)));\n    chainTableSize = (U32)(sizeof(U32)*((size_t)1 << params.contentLog));\n    \n    if (!ctx)\n    {\n        ctx = (Lizard_stream_t*)malloc(sizeof(Lizard_stream_t) + hashTableSize + chainTableSize + LIZARD_COMPRESS_ADD_BUF + LIZARD_COMPRESS_ADD_HUF);\n        if (!ctx) { printf(\"ERROR: Cannot allocate %d MB (compressionLevel=%d)\\n\", (int)(sizeof(Lizard_stream_t) + hashTableSize + chainTableSize)>>20, compressionLevel); return 0; }\n        LIZARD_LOG_COMPRESS(\"Allocated %d MB (compressionLevel=%d)\\n\", (int)(sizeof(Lizard_stream_t) + hashTableSize + chainTableSize)>>20, compressionLevel); \n        ctx->allocatedMemory = sizeof(Lizard_stream_t) + hashTableSize + chainTableSize + LIZARD_COMPRESS_ADD_BUF + (U32)LIZARD_COMPRESS_ADD_HUF;\n      //  printf(\"malloc from=%p to=%p hashTable=%p hashEnd=%p chainTable=%p chainEnd=%p\\n\", ctx, ((BYTE*)ctx)+sizeof(Lizard_stream_t) + hashTableSize + chainTableSize, ctx->hashTable, ((BYTE*)ctx->hashTable) + hashTableSize, ctx->chainTable, ((BYTE*)ctx->chainTable)+chainTableSize);\n    }\n    \n    tempPtr = ctx;\n    ctx->hashTable = (U32*)(tempPtr) + sizeof(Lizard_stream_t)/4;\n    ctx->hashTableSize = hashTableSize;\n    ctx->chainTable = ctx->hashTable + hashTableSize/4;\n    ctx->chainTableSize = chainTableSize;\n    ctx->params = params;\n    ctx->compressionLevel = (unsigned)compressionLevel;\n    if (compressionLevel < 30)\n        ctx->huffType = 0;\n    else\n        ctx->huffType = LIZARD_FLAG_LITERALS + LIZARD_FLAG_FLAGS; // + LIZARD_FLAG_OFFSET16 + LIZARD_FLAG_OFFSET24;\n\n    ctx->literalsBase = (BYTE*)ctx->hashTable + ctx->hashTableSize + ctx->chainTableSize;\n    ctx->flagsBase    = ctx->literalsEnd = ctx->literalsBase + LIZARD_BLOCK_SIZE_PAD;\n    ctx->lenBase      = ctx->flagsEnd    = ctx->flagsBase    + LIZARD_BLOCK_SIZE_PAD;\n    ctx->offset16Base = ctx->lenEnd      = ctx->lenBase      + LIZARD_BLOCK_SIZE_PAD;\n    ctx->offset24Base = ctx->offset16End = ctx->offset16Base + LIZARD_BLOCK_SIZE_PAD;\n    ctx->huffBase     = ctx->offset24End = ctx->offset24Base + LIZARD_BLOCK_SIZE_PAD;\n                        ctx->huffEnd     = ctx->huffBase     + LIZARD_COMPRESS_ADD_HUF;\n\n    return ctx;\n}\n\n\n\nLizard_stream_t* Lizard_createStream(int compressionLevel) \n{ \n    Lizard_stream_t* ctx = Lizard_initStream(NULL, compressionLevel);\n    if (ctx) ctx->base = NULL;\n    return ctx; \n}\n\n\n/* initialization */\nLizard_stream_t* Lizard_resetStream(Lizard_stream_t* ctx, int compressionLevel)\n{\n    size_t wanted = Lizard_sizeofState(compressionLevel);\n\n    if (ctx->allocatedMemory < wanted) {\n        Lizard_freeStream(ctx);\n        ctx = Lizard_createStream(compressionLevel);\n    } else {\n        Lizard_initStream(ctx, compressionLevel);\n    }\n\n    if (ctx) ctx->base = NULL;\n    return ctx;\n}\n\n\nint Lizard_freeStream(Lizard_stream_t* ctx) \n{ \n    if (ctx) {\n        free(ctx);\n    }\n    return 0; \n}\n\n\nint Lizard_loadDict(Lizard_stream_t* Lizard_streamPtr, const char* dictionary, int dictSize)\n{\n    Lizard_stream_t* ctxPtr = (Lizard_stream_t*) Lizard_streamPtr;\n    if (dictSize > LIZARD_DICT_SIZE) {\n        dictionary += dictSize - LIZARD_DICT_SIZE;\n        dictSize = LIZARD_DICT_SIZE;\n    }\n    Lizard_init(ctxPtr, (const BYTE*)dictionary);\n    if (dictSize >= HASH_UPDATE_LIMIT) Lizard_Insert (ctxPtr, (const BYTE*)dictionary + (dictSize - (HASH_UPDATE_LIMIT-1)));\n    ctxPtr->end = (const BYTE*)dictionary + dictSize;\n    return dictSize;\n}\n\n\nstatic void Lizard_setExternalDict(Lizard_stream_t* ctxPtr, const BYTE* newBlock)\n{\n    if (ctxPtr->end >= ctxPtr->base + HASH_UPDATE_LIMIT) Lizard_Insert (ctxPtr, ctxPtr->end - (HASH_UPDATE_LIMIT-1));   /* Referencing remaining dictionary content */\n    /* Only one memory segment for extDict, so any previous extDict is lost at this stage */\n    ctxPtr->lowLimit  = ctxPtr->dictLimit;\n    ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);\n    ctxPtr->dictBase  = ctxPtr->base;\n    ctxPtr->base = newBlock - ctxPtr->dictLimit;\n    ctxPtr->end  = newBlock;\n    ctxPtr->nextToUpdate = ctxPtr->dictLimit;   /* match referencing will resume from there */\n}\n\n\n/* dictionary saving */\nint Lizard_saveDict (Lizard_stream_t* Lizard_streamPtr, char* safeBuffer, int dictSize)\n{\n    Lizard_stream_t* const ctx = (Lizard_stream_t*)Lizard_streamPtr;\n    int const prefixSize = (int)(ctx->end - (ctx->base + ctx->dictLimit));\n    if (dictSize > LIZARD_DICT_SIZE) dictSize = LIZARD_DICT_SIZE;\n    if (dictSize < 4) dictSize = 0;\n    if (dictSize > prefixSize) dictSize = prefixSize;\n    memmove(safeBuffer, ctx->end - dictSize, dictSize);\n    {   U32 const endIndex = (U32)(ctx->end - ctx->base);\n        ctx->end = (const BYTE*)safeBuffer + dictSize;\n        ctx->base = ctx->end - endIndex;\n        ctx->dictLimit = endIndex - dictSize;\n        ctx->lowLimit = endIndex - dictSize;\n        if (ctx->nextToUpdate < ctx->dictLimit) ctx->nextToUpdate = ctx->dictLimit;\n    }\n    return dictSize;\n}\n\nFORCE_INLINE int Lizard_compress_generic (\n    void* ctxvoid,\n    const char* source,\n    char* dest,\n    int inputSize,\n    int maxOutputSize)\n{\n    Lizard_stream_t* ctx = (Lizard_stream_t*) ctxvoid;\n    size_t dictSize = (size_t)(ctx->end - ctx->base) - ctx->dictLimit;\n    const BYTE* ip = (const BYTE*) source;\n    BYTE* op = (BYTE*) dest;\n    BYTE* const oend = op + maxOutputSize;\n    int res;\n\n    (void)dictSize;\n    LIZARD_LOG_COMPRESS(\"Lizard_compress_generic source=%p inputSize=%d dest=%p maxOutputSize=%d cLevel=%d dictBase=%p dictSize=%d\\n\", source, inputSize, dest, maxOutputSize, ctx->compressionLevel, ctx->dictBase, (int)dictSize); \n    *op++ = (BYTE)ctx->compressionLevel;\n    maxOutputSize--; // can be lower than 0\n    ctx->end += inputSize;\n    ctx->srcBase = ctx->off24pos = ip;\n    ctx->destBase = (BYTE*)dest;\n\n    while (inputSize > 0)\n    {\n        int inputPart = MIN(LIZARD_BLOCK_SIZE, inputSize);\n\n        if (ctx->huffType) Lizard_rescaleFreqs(ctx);\n        Lizard_initBlock(ctx);\n        ctx->diffBase = ip;\n\n        switch(ctx->params.parserType)\n        {\n        default:\n        case Lizard_parser_fastSmall:\n            res = Lizard_compress_fastSmall(ctx, ip, ip+inputPart); break;\n        case Lizard_parser_fast:\n            res = Lizard_compress_fast(ctx, ip, ip+inputPart); break;\n        case Lizard_parser_noChain:\n            res = Lizard_compress_noChain(ctx, ip, ip+inputPart); break;\n        case Lizard_parser_hashChain:\n            res = Lizard_compress_hashChain(ctx, ip, ip+inputPart); break;\n#ifndef USE_LZ4_ONLY\n        case Lizard_parser_fastBig:\n            res = Lizard_compress_fastBig(ctx, ip, ip+inputPart); break;\n        case Lizard_parser_priceFast:\n            res = Lizard_compress_priceFast(ctx, ip, ip+inputPart); break;\n        case Lizard_parser_lowestPrice:\n            res = Lizard_compress_lowestPrice(ctx, ip, ip+inputPart); break;\n        case Lizard_parser_optimalPrice:\n        case Lizard_parser_optimalPriceBT:\n            res = Lizard_compress_optimalPrice(ctx, ip, ip+inputPart); break;\n#else\n        case Lizard_parser_priceFast:\n        case Lizard_parser_lowestPrice:\n        case Lizard_parser_optimalPrice:\n        case Lizard_parser_optimalPriceBT:\n            res = 0;\n#endif\n        }\n\n        LIZARD_LOG_COMPRESS(\"Lizard_compress_generic res=%d inputPart=%d \\n\", res, inputPart);\n        if (res <= 0) return res;\n\n        if (Lizard_writeBlock(ctx, ip, inputPart, &op, oend)) goto _output_error;\n\n        ip += inputPart;\n        inputSize -= inputPart;\n        LIZARD_LOG_COMPRESS(\"Lizard_compress_generic in=%d out=%d\\n\", (int)(ip-(const BYTE*)source), (int)(op-(BYTE*)dest));\n    }\n\n    LIZARD_LOG_COMPRESS(\"Lizard_compress_generic total=%d\\n\", (int)(op-(BYTE*)dest));\n    return (int)(op-(BYTE*)dest);\n_output_error:\n    LIZARD_LOG_COMPRESS(\"Lizard_compress_generic ERROR\\n\");\n    return 0;\n}\n\n\nint Lizard_compress_continue (Lizard_stream_t* ctxPtr,\n                                            const char* source, char* dest,\n                                            int inputSize, int maxOutputSize)\n{\n    /* auto-init if required */\n    if (ctxPtr->base == NULL) Lizard_init(ctxPtr, (const BYTE*) source);\n\n    /* Check overflow */\n    if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB) {\n        size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;\n        if (dictSize > LIZARD_DICT_SIZE) dictSize = LIZARD_DICT_SIZE;\n        Lizard_loadDict((Lizard_stream_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);\n    }\n\n    /* Check if blocks follow each other */\n    if ((const BYTE*)source != ctxPtr->end) \n        Lizard_setExternalDict(ctxPtr, (const BYTE*)source);\n\n    /* Check overlapping input/dictionary space */\n    {   const BYTE* sourceEnd = (const BYTE*) source + inputSize;\n        const BYTE* const dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;\n        const BYTE* const dictEnd   = ctxPtr->dictBase + ctxPtr->dictLimit;\n        if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd)) {\n            if (sourceEnd > dictEnd) sourceEnd = dictEnd;\n            ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);\n            if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;\n        }\n    }\n\n    return Lizard_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize);\n}\n\n\nint Lizard_compress_extState (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)\n{\n    Lizard_stream_t* ctx = (Lizard_stream_t*) state;\n    if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0;   /* Error : state is not aligned for pointers (32 or 64 bits) */\n\n    /* initialize stream */\n    Lizard_initStream(ctx, compressionLevel);\n    Lizard_init((Lizard_stream_t*)state, (const BYTE*)src);\n\n    return Lizard_compress_generic (state, src, dst, srcSize, maxDstSize);\n}\n\n\nint Lizard_compress(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)\n{\n    int cSize;\n    Lizard_stream_t* statePtr = Lizard_createStream(compressionLevel);\n\n    if (!statePtr) return 0;\n    cSize = Lizard_compress_extState(statePtr, src, dst, srcSize, maxDstSize, compressionLevel);\n\n    Lizard_freeStream(statePtr);\n    return cSize;\n}\n\n\n/**************************************\n*  Level1 functions\n**************************************/\nint Lizard_compress_extState_MinLevel(void* state, const char* source, char* dest, int inputSize, int maxOutputSize)\n{\n    return Lizard_compress_extState(state, source, dest, inputSize, maxOutputSize, LIZARD_MIN_CLEVEL);\n}\n\nint Lizard_compress_MinLevel(const char* source, char* dest, int inputSize, int maxOutputSize)\n{\n    return Lizard_compress(source, dest, inputSize, maxOutputSize, LIZARD_MIN_CLEVEL);\n}\n\nLizard_stream_t* Lizard_createStream_MinLevel(void)\n{\n    return Lizard_createStream(LIZARD_MIN_CLEVEL);\n}\n\nLizard_stream_t* Lizard_resetStream_MinLevel(Lizard_stream_t* Lizard_stream)\n{\n    return Lizard_resetStream (Lizard_stream, LIZARD_MIN_CLEVEL);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_compress.h",
    "content": "﻿/*\n   Lizard - Fast LZ compression algorithm\n   Header File\n   Copyright (C) 2011-2016, Yann Collet\n   Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n    - Lizard source repository : https://github.com/inikep/lizard\n*/\n#ifndef LIZARD_H_2983\n#define LIZARD_H_2983\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*\n * lizard_compress.h provides block compression functions. It gives full buffer control to user.\n * Block compression functions are not-enough to send information,\n * since it's still necessary to provide metadata (such as compressed size),\n * and each application can do it in whichever way it wants.\n * For interoperability, there is Lizard frame specification (lizard_Frame_format.md).\n * A library is provided to take care of it, see lizard_frame.h.\n*/\n\n\n/*^***************************************************************\n*  Export parameters\n*****************************************************************/\n/*\n*  LIZARD_DLL_EXPORT :\n*  Enable exporting of functions when building a Windows DLL\n*/\n#if defined(LIZARD_DLL_EXPORT) && (LIZARD_DLL_EXPORT==1)\n#  define LIZARDLIB_API __declspec(dllexport)\n#elif defined(LIZARD_DLL_IMPORT) && (LIZARD_DLL_IMPORT==1)\n#  define LIZARDLIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define LIZARDLIB_API\n#endif\n\n\n/*-************************************\n*  Version\n**************************************/\n#define LIZARD_VERSION_MAJOR    2    /* for breaking interface changes  */\n#define LIZARD_VERSION_MINOR    1    /* for new (non-breaking) interface capabilities */\n#define LIZARD_VERSION_RELEASE  0    /* for tweaks, bug-fixes, or development */\n\n#define LIZARD_VERSION_NUMBER (LIZARD_VERSION_MAJOR *100*100 + LIZARD_VERSION_MINOR *100 + LIZARD_VERSION_RELEASE)\nint Lizard_versionNumber (void);\n\n#define LIZARD_LIB_VERSION LIZARD_VERSION_MAJOR.LIZARD_VERSION_MINOR.LIZARD_VERSION_RELEASE\n#define LIZARD_QUOTE(str) #str\n#define LIZARD_EXPAND_AND_QUOTE(str) LIZARD_QUOTE(str)\n#define LIZARD_VERSION_STRING LIZARD_EXPAND_AND_QUOTE(LIZARD_LIB_VERSION)\nconst char* Lizard_versionString (void);\n\ntypedef struct Lizard_stream_s Lizard_stream_t;\n\n#define LIZARD_MIN_CLEVEL      10  /* minimum compression level */\n#ifndef LIZARD_NO_HUFFMAN\n    #define LIZARD_MAX_CLEVEL      49  /* maximum compression level */\n#else\n    #define LIZARD_MAX_CLEVEL      29  /* maximum compression level */\n#endif\n#define LIZARD_DEFAULT_CLEVEL  17\n\n\n/*-************************************\n*  Simple Functions\n**************************************/\n\nLIZARDLIB_API int Lizard_compress (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel); \n\n/*\nLizard_compress() :\n    Compresses 'sourceSize' bytes from buffer 'source'\n    into already allocated 'dest' buffer of size 'maxDestSize'.\n    Compression is guaranteed to succeed if 'maxDestSize' >= Lizard_compressBound(sourceSize).\n    It also runs faster, so it's a recommended setting.\n    If the function cannot compress 'source' into a more limited 'dest' budget,\n    compression stops *immediately*, and the function result is zero.\n    As a consequence, 'dest' content is not valid.\n    This function never writes outside 'dest' buffer, nor read outside 'source' buffer.\n        sourceSize  : Max supported value is LIZARD_MAX_INPUT_VALUE\n        maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)\n        return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)\n              or 0 if compression fails\n*/\n\n\n/*-************************************\n*  Advanced Functions\n**************************************/\n#define LIZARD_MAX_INPUT_SIZE  0x7E000000   /* 2 113 929 216 bytes */\n#define LIZARD_BLOCK_SIZE      (1<<17)\n#define LIZARD_BLOCK64K_SIZE   (1<<16)\n#define LIZARD_COMPRESSBOUND(isize)  ((unsigned)(isize) > (unsigned)LIZARD_MAX_INPUT_SIZE ? 0 : (isize) + 1 + 1 + ((isize/LIZARD_BLOCK_SIZE)+1)*4)\n\n\n/*!\nLizard_compressBound() :\n    Provides the maximum size that Lizard compression may output in a \"worst case\" scenario (input data not compressible)\n    This function is primarily useful for memory allocation purposes (destination buffer size).\n    Macro LIZARD_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).\n    Note that Lizard_compress() compress faster when dest buffer size is >= Lizard_compressBound(srcSize)\n        inputSize  : max supported value is LIZARD_MAX_INPUT_SIZE\n        return : maximum output size in a \"worst case\" scenario\n              or 0, if input size is too large ( > LIZARD_MAX_INPUT_SIZE)\n*/\nLIZARDLIB_API int Lizard_compressBound(int inputSize);\n\n\n/*!\nLizard_compress_extState() :\n    Same compression function, just using an externally allocated memory space to store compression state.\n    Use Lizard_sizeofState() to know how much memory must be allocated,\n    and allocate it on 8-bytes boundaries (using malloc() typically).\n    Then, provide it as 'void* state' to compression function.\n*/\nLIZARDLIB_API int Lizard_sizeofState(int compressionLevel); \n\nLIZARDLIB_API int Lizard_compress_extState(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);\n\n\n\n/*-*********************************************\n*  Streaming Compression Functions\n***********************************************/\n\n/*! Lizard_createStream() will allocate and initialize an `Lizard_stream_t` structure.\n *  Lizard_freeStream() releases its memory.\n *  In the context of a DLL (liblizard), please use these methods rather than the static struct.\n *  They are more future proof, in case of a change of `Lizard_stream_t` size.\n */\nLIZARDLIB_API Lizard_stream_t* Lizard_createStream(int compressionLevel);\nLIZARDLIB_API int           Lizard_freeStream (Lizard_stream_t* streamPtr);\n\n\n/*! Lizard_resetStream() :\n *  Use this function to reset/reuse an allocated `Lizard_stream_t` structure\n */\nLIZARDLIB_API Lizard_stream_t* Lizard_resetStream (Lizard_stream_t* streamPtr, int compressionLevel); \n\n\n/*! Lizard_loadDict() :\n *  Use this function to load a static dictionary into Lizard_stream.\n *  Any previous data will be forgotten, only 'dictionary' will remain in memory.\n *  Loading a size of 0 is allowed.\n *  Return : dictionary size, in bytes (necessarily <= LIZARD_DICT_SIZE)\n */\nLIZARDLIB_API int Lizard_loadDict (Lizard_stream_t* streamPtr, const char* dictionary, int dictSize);\n\n\n/*! Lizard_compress_continue() :\n *  Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.\n *  Important : Previous data blocks are assumed to still be present and unmodified !\n *  'dst' buffer must be already allocated.\n *  If maxDstSize >= Lizard_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.\n *  If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.\n */\nLIZARDLIB_API int Lizard_compress_continue (Lizard_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize);\n\n\n/*! Lizard_saveDict() :\n *  If previously compressed data block is not guaranteed to remain available at its memory location,\n *  save it into a safer place (char* safeBuffer).\n *  Note : you don't need to call Lizard_loadDict() afterwards,\n *         dictionary is immediately usable, you can therefore call Lizard_compress_continue().\n *  Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error.\n */\nLIZARDLIB_API int Lizard_saveDict (Lizard_stream_t* streamPtr, char* safeBuffer, int dictSize);\n\n\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* LIZARD_H_2983827168210 */\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_compress_liz.h",
    "content": "﻿#define LIZARD_FREQ_DIV   5\n\nFORCE_INLINE void Lizard_setLog2Prices(Lizard_stream_t* ctx)\n{\n    ctx->log2LitSum = Lizard_highbit32(ctx->litSum+1);\n    ctx->log2FlagSum = Lizard_highbit32(ctx->flagSum+1);\n}\n\n\nMEM_STATIC void Lizard_rescaleFreqs(Lizard_stream_t* ctx)\n{\n    unsigned u;\n\n    ctx->cachedLiterals = NULL;\n    ctx->cachedPrice = ctx->cachedLitLength = 0;\n    \n    ctx->litPriceSum = 0;\n\n    if (ctx->litSum == 0) {\n        ctx->litSum = 2 * 256;\n        ctx->flagSum = 2 * 256;\n\n        for (u=0; u < 256; u++) {\n            ctx->litFreq[u] = 2;\n            ctx->flagFreq[u] = 2;\n        }\n    } else {\n        ctx->litSum = 0;\n        ctx->flagSum = 0;\n\n        for (u=0; u < 256; u++) {\n            ctx->litFreq[u] = 1 + (ctx->litFreq[u]>>LIZARD_FREQ_DIV);\n            ctx->litSum += ctx->litFreq[u];\n            ctx->flagFreq[u] = 1 + (ctx->flagFreq[u]>>LIZARD_FREQ_DIV);\n            ctx->flagSum += ctx->flagFreq[u];\n        }\n    }\n\n    Lizard_setLog2Prices(ctx);\n}\n\n\nFORCE_INLINE int Lizard_encodeSequence_LIZv1 (\n    Lizard_stream_t* ctx,\n    const BYTE** ip,\n    const BYTE** anchor,\n    size_t matchLength,\n    const BYTE* const match)\n{\n    U32 offset = (U32)(*ip - match);\n    size_t length = (size_t)(*ip - *anchor);\n    BYTE* token = (ctx->flagsPtr)++;\n\n    if (length > 0 || offset < LIZARD_MAX_16BIT_OFFSET) {\n        /* Encode Literal length */\n      //  if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - length - LIZARD_LENGTH_SIZE_LIZv1(length) - WILDCOPYLENGTH)) { LIZARD_LOG_COMPRESS_LIZv1(\"encodeSequence overflow1\\n\"); return 1; }   /* Check output limit */\n        if (length >= MAX_SHORT_LITLEN) \n        {   size_t len; \n            *token = MAX_SHORT_LITLEN; \n            len = length - MAX_SHORT_LITLEN;\n            if (len >= (1<<16)) { *(ctx->literalsPtr) = 255;  MEM_writeLE24(ctx->literalsPtr+1, (U32)(len));  ctx->literalsPtr += 4; }\n            else if (len >= 254) { *(ctx->literalsPtr) = 254;  MEM_writeLE16(ctx->literalsPtr+1, (U16)(len));  ctx->literalsPtr += 3; }\n            else *(ctx->literalsPtr)++ = (BYTE)len;\n        }\n        else *token = (BYTE)length;\n\n        /* Copy Literals */\n        Lizard_wildCopy(ctx->literalsPtr, *anchor, (ctx->literalsPtr) + length);\n#ifndef LIZARD_NO_HUFFMAN\n        if (ctx->huffType) { \n            ctx->litSum += (U32)length;\n            ctx->litPriceSum += (U32)(length * ctx->log2LitSum);\n            {   U32 u;\n                for (u=0; u < length; u++) {\n                    ctx->litPriceSum -= Lizard_highbit32(ctx->litFreq[ctx->literalsPtr[u]]+1);\n                    ctx->litFreq[ctx->literalsPtr[u]]++;\n            }   }\n        }\n#endif\n        ctx->literalsPtr += length;\n\n\n        if (offset >= LIZARD_MAX_16BIT_OFFSET) {\n            COMPLOG_CODEWORDS_LIZv1(\"T32+ literal=%u match=%u offset=%d\\n\", (U32)length, 0, 0);\n            *token+=(1<<ML_RUN_BITS);\n#ifndef LIZARD_NO_HUFFMAN\n            if (ctx->huffType) { \n                ctx->flagFreq[*token]++;\n                ctx->flagSum++;\n            }\n#endif\n            token = (ctx->flagsPtr)++;\n        }\n    }\n\n    /* Encode Offset */\n    if (offset >= LIZARD_MAX_16BIT_OFFSET)  // 24-bit offset\n    {\n        if (matchLength < MM_LONGOFF) printf(\"ERROR matchLength=%d/%d\\n\", (int)matchLength, MM_LONGOFF), exit(1);\n\n      //  if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - 8 /*LIZARD_LENGTH_SIZE_LIZv1(length)*/)) { LIZARD_LOG_COMPRESS_LIZv1(\"encodeSequence overflow2\\n\"); return 1; }   /* Check output limit */\n        if (matchLength - MM_LONGOFF >= LIZARD_LAST_LONG_OFF) \n        {\n            size_t len = matchLength - MM_LONGOFF - LIZARD_LAST_LONG_OFF;\n            *token = LIZARD_LAST_LONG_OFF;\n            if (len >= (1<<16)) { *(ctx->literalsPtr) = 255;  MEM_writeLE24(ctx->literalsPtr+1, (U32)(len));  ctx->literalsPtr += 4; }\n            else if (len >= 254) { *(ctx->literalsPtr) = 254;  MEM_writeLE16(ctx->literalsPtr+1, (U16)(len));  ctx->literalsPtr += 3; }\n            else *(ctx->literalsPtr)++ = (BYTE)len; \n            COMPLOG_CODEWORDS_LIZv1(\"T31 literal=%u match=%u offset=%d\\n\", 0, (U32)matchLength, offset);\n        }\n        else\n        {\n            COMPLOG_CODEWORDS_LIZv1(\"T0-30 literal=%u match=%u offset=%d\\n\", 0, (U32)matchLength, offset);\n            *token = (BYTE)(matchLength - MM_LONGOFF);\n        }\n\n        MEM_writeLE24(ctx->offset24Ptr, offset); \n        ctx->offset24Ptr += 3;\n        ctx->last_off = offset;\n        ctx->off24pos = *ip;\n    }\n    else\n    {\n        COMPLOG_CODEWORDS_LIZv1(\"T32+ literal=%u match=%u offset=%d\\n\", (U32)length, (U32)matchLength, offset);\n        if (offset == 0)\n        {\n            *token+=(1<<ML_RUN_BITS);\n        }\n        else\n        {\n            // it should never happen\n            if (offset < 8) { printf(\"ERROR offset=%d\\n\", (int)offset); exit(1); }\n            if (matchLength < MINMATCH) { printf(\"ERROR matchLength[%d] < MINMATCH  offset=%d\\n\", (int)matchLength, (int)ctx->last_off); exit(1); }\n            \n            ctx->last_off = offset;\n            MEM_writeLE16(ctx->offset16Ptr, (U16)ctx->last_off); ctx->offset16Ptr += 2;\n        }\n\n        /* Encode MatchLength */\n        length = matchLength;\n       // if ((limitedOutputBuffer) && (ctx->literalsPtr > oend - 5 /*LIZARD_LENGTH_SIZE_LIZv1(length)*/)) { LIZARD_LOG_COMPRESS_LIZv1(\"encodeSequence overflow2\\n\"); return 1; }   /* Check output limit */\n        if (length >= MAX_SHORT_MATCHLEN) {\n            *token += (BYTE)(MAX_SHORT_MATCHLEN<<RUN_BITS_LIZv1);\n            length -= MAX_SHORT_MATCHLEN;\n            if (length >= (1<<16)) { *(ctx->literalsPtr) = 255;  MEM_writeLE24(ctx->literalsPtr+1, (U32)(length));  ctx->literalsPtr += 4; }\n            else if (length >= 254) { *(ctx->literalsPtr) = 254;  MEM_writeLE16(ctx->literalsPtr+1, (U16)(length));  ctx->literalsPtr += 3; }\n            else *(ctx->literalsPtr)++ = (BYTE)length;\n        }\n        else *token += (BYTE)(length<<RUN_BITS_LIZv1);\n    }\n\n#ifndef LIZARD_NO_HUFFMAN\n    if (ctx->huffType) { \n        ctx->flagFreq[*token]++;\n        ctx->flagSum++;\n        Lizard_setLog2Prices(ctx);\n    }\n#endif\n\n    /* Prepare next loop */\n    *ip += matchLength;\n    *anchor = *ip;\n\n    return 0;\n}\n\n\nFORCE_INLINE int Lizard_encodeLastLiterals_LIZv1 (\n    Lizard_stream_t* ctx,\n    const BYTE** ip,\n    const BYTE** anchor)\n{\n    size_t length = (int)(*ip - *anchor);\n    (void)ctx;\n\n    memcpy(ctx->literalsPtr, *anchor, length);\n    ctx->literalsPtr += length;\n    return 0;\n}\n\n\n#define LIZARD_PRICE_MULT 1\n#define LIZARD_GET_TOKEN_PRICE_LIZv1(token)  (LIZARD_PRICE_MULT * (ctx->log2FlagSum - Lizard_highbit32(ctx->flagFreq[token]+1)))\n\n\nFORCE_INLINE size_t Lizard_get_price_LIZv1(Lizard_stream_t* const ctx, int rep, const BYTE *ip, const BYTE *off24pos, size_t litLength, U32 offset, size_t matchLength) \n{\n    size_t price = 0;\n    BYTE token = 0;\n#ifndef LIZARD_NO_HUFFMAN\n    const BYTE* literals = ip - litLength;\n    U32 u;\n    if ((ctx->huffType) && (ctx->params.parserType != Lizard_parser_lowestPrice)) {\n        if (ctx->cachedLiterals == literals && litLength >= ctx->cachedLitLength) {\n            size_t const additional = litLength - ctx->cachedLitLength;\n            const BYTE* literals2 = ctx->cachedLiterals + ctx->cachedLitLength;\n            price = ctx->cachedPrice + LIZARD_PRICE_MULT * additional * ctx->log2LitSum;\n            for (u=0; u < additional; u++)\n                price -= LIZARD_PRICE_MULT * Lizard_highbit32(ctx->litFreq[literals2[u]]+1);\n            ctx->cachedPrice = (U32)price;\n            ctx->cachedLitLength = (U32)litLength;\n        } else {\n            price = LIZARD_PRICE_MULT * litLength * ctx->log2LitSum;\n            for (u=0; u < litLength; u++)\n                price -= LIZARD_PRICE_MULT * Lizard_highbit32(ctx->litFreq[literals[u]]+1);\n\n            if (litLength >= 12) {\n                ctx->cachedLiterals = literals;\n                ctx->cachedPrice = (U32)price;\n                ctx->cachedLitLength = (U32)litLength;\n            }\n        }\n    }\n    else\n        price += 8*litLength;  /* Copy Literals */\n#else\n    price += 8*litLength;  /* Copy Literals */\n    (void)ip;\n    (void)ctx;\n#endif\n\n    (void)off24pos;\n    (void)rep;\n\n    if (litLength > 0 || offset < LIZARD_MAX_16BIT_OFFSET) {\n        /* Encode Literal length */\n        if (litLength >= MAX_SHORT_LITLEN) \n        {   size_t len = litLength - MAX_SHORT_LITLEN;\n            token = MAX_SHORT_LITLEN; \n            if (len >= (1<<16)) price += 32;\n            else if (len >= 254) price += 24;\n            else price += 8;\n        }\n        else token = (BYTE)litLength;\n\n        if (offset >= LIZARD_MAX_16BIT_OFFSET) {\n            token+=(1<<ML_RUN_BITS);\n            if (ctx->huffType && ctx->params.parserType != Lizard_parser_lowestPrice)\n                price += LIZARD_GET_TOKEN_PRICE_LIZv1(token);\n            else\n                price += 8;\n       }\n    }\n\n    /* Encode Offset */\n    if (offset >= LIZARD_MAX_16BIT_OFFSET) { // 24-bit offset\n        if (matchLength < MM_LONGOFF) return LIZARD_MAX_PRICE; // error\n\n        if (matchLength - MM_LONGOFF >= LIZARD_LAST_LONG_OFF) {\n            size_t len = matchLength - MM_LONGOFF - LIZARD_LAST_LONG_OFF;\n            token = LIZARD_LAST_LONG_OFF;\n            if (len >= (1<<16)) price += 32;\n            else if (len >= 254) price += 24;\n            else price += 8;\n        } else {\n            token = (BYTE)(matchLength - MM_LONGOFF);\n        }\n\n        price += 24;\n    } else {\n        size_t length;\n        if (offset == 0) {\n            token+=(1<<ML_RUN_BITS);\n        } else {\n            if (offset < 8) return LIZARD_MAX_PRICE; // error\n            if (matchLength < MINMATCH) return LIZARD_MAX_PRICE; // error\n            price += 16;\n        }\n\n        /* Encode MatchLength */\n        length = matchLength;\n        if (length >= MAX_SHORT_MATCHLEN) {\n            token += (BYTE)(MAX_SHORT_MATCHLEN<<RUN_BITS_LIZv1);\n            length -= MAX_SHORT_MATCHLEN;\n            if (length >= (1<<16)) price += 32;\n            else if (length >= 254) price += 24;\n            else price += 8;\n        }\n        else token += (BYTE)(length<<RUN_BITS_LIZv1);\n    }\n\n    if (offset > 0 || matchLength > 0) {\n        int offset_load = Lizard_highbit32(offset);\n        if (ctx->huffType) {\n            price += ((offset_load>=20) ? ((offset_load-19)*4) : 0);\n            price += 4 + (matchLength==1);\n        } else {\n            price += ((offset_load>=16) ? ((offset_load-15)*4) : 0);\n            price += 6 + (matchLength==1);\n        }\n        if (ctx->huffType && ctx->params.parserType != Lizard_parser_lowestPrice)\n            price += LIZARD_GET_TOKEN_PRICE_LIZv1(token);\n        else\n            price += 8;\n    } else {\n        if (ctx->huffType && ctx->params.parserType != Lizard_parser_lowestPrice)\n            price += LIZARD_GET_TOKEN_PRICE_LIZv1(token);  // 1=better ratio\n    }\n\n    return price;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_compress_lz4.h",
    "content": "﻿#define LIZARD_LENGTH_SIZE_LZ4(len) ((len >= (1<<16)+RUN_MASK_LZ4) ? 5 : ((len >= 254+RUN_MASK_LZ4) ? 3 : ((len >= RUN_MASK_LZ4) ? 1 : 0)))\n\nFORCE_INLINE int Lizard_encodeSequence_LZ4 (\n    Lizard_stream_t* ctx,\n    const BYTE** ip,\n    const BYTE** anchor,\n    size_t matchLength,\n    const BYTE* const match)\n{\n    size_t length = (size_t)(*ip - *anchor);\n    BYTE* token = (ctx->flagsPtr)++;\n    (void) ctx;\n\n    COMPLOG_CODEWORDS_LZ4(\"literal : %u  --  match : %u  --  offset : %u\\n\", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));\n  \n    /* Encode Literal length */\n //   if (ctx->literalsPtr > ctx->literalsEnd - length - LIZARD_LENGTH_SIZE_LZ4(length) - 2 - WILDCOPYLENGTH) { LIZARD_LOG_COMPRESS_LZ4(\"encodeSequence overflow1\\n\"); return 1; }   /* Check output limit */\n    if (length >= RUN_MASK_LZ4) \n    {   size_t len = length - RUN_MASK_LZ4;\n        *token = RUN_MASK_LZ4; \n        if (len >= (1<<16)) { *(ctx->literalsPtr) = 255;  MEM_writeLE24(ctx->literalsPtr+1, (U32)(len));  ctx->literalsPtr += 4; }\n        else if (len >= 254) { *(ctx->literalsPtr) = 254;  MEM_writeLE16(ctx->literalsPtr+1, (U16)(len));  ctx->literalsPtr += 3; }\n        else *(ctx->literalsPtr)++ = (BYTE)len;\n    }\n    else *token = (BYTE)length;\n\n    /* Copy Literals */\n    if (length > 0) {\n        Lizard_wildCopy(ctx->literalsPtr, *anchor, (ctx->literalsPtr) + length);\n#if 0 //def LIZARD_USE_HUFFMAN\n        ctx->litSum += (U32)length;\n        ctx->litPriceSum += (U32)(length * ctx->log2LitSum);\n        {   U32 u;\n            for (u=0; u < length; u++) {\n                ctx->litPriceSum -= Lizard_highbit32(ctx->litFreq[ctx->literalsPtr[u]]+1);\n                ctx->litFreq[ctx->literalsPtr[u]]++;\n        }   }\n#endif\n        ctx->literalsPtr += length;\n    }\n\n    /* Encode Offset */\n    MEM_writeLE16(ctx->literalsPtr, (U16)(*ip-match));\n    ctx->literalsPtr+=2;\n\n    /* Encode MatchLength */\n    length = matchLength - MINMATCH;\n  //  if (ctx->literalsPtr > ctx->literalsEnd - 5 /*LIZARD_LENGTH_SIZE_LZ4(length)*/) { LIZARD_LOG_COMPRESS_LZ4(\"encodeSequence overflow2\\n\"); return 1; }   /* Check output limit */\n    if (length >= ML_MASK_LZ4) {\n        *token += (BYTE)(ML_MASK_LZ4<<RUN_BITS_LZ4);\n        length -= ML_MASK_LZ4;\n        if (length >= (1<<16)) { *(ctx->literalsPtr) = 255;  MEM_writeLE24(ctx->literalsPtr+1, (U32)(length));  ctx->literalsPtr += 4; }\n        else if (length >= 254) { *(ctx->literalsPtr) = 254;  MEM_writeLE16(ctx->literalsPtr+1, (U16)(length));  ctx->literalsPtr += 3; }\n        else *(ctx->literalsPtr)++ = (BYTE)length;\n    }\n    else *token += (BYTE)(length<<RUN_BITS_LZ4);\n\n#ifndef LIZARD_NO_HUFFMAN\n    if (ctx->huffType) { \n        ctx->flagFreq[*token]++;\n        ctx->flagSum++;\n        Lizard_setLog2Prices(ctx);\n    }\n#endif\n\n    /* Prepare next loop */\n    *ip += matchLength;\n    *anchor = *ip;\n\n    return 0;\n}\n\n\nFORCE_INLINE int Lizard_encodeLastLiterals_LZ4 (\n    Lizard_stream_t* ctx,\n    const BYTE** ip,\n    const BYTE** anchor)\n{\n    size_t length = (int)(*ip - *anchor);\n\n    (void)ctx;\n\n    memcpy(ctx->literalsPtr, *anchor, length);\n    ctx->literalsPtr += length;\n    return 0;\n}\n\n\n#define LIZARD_GET_TOKEN_PRICE_LZ4(token)  (ctx->log2FlagSum - Lizard_highbit32(ctx->flagFreq[token]+1))\n\nFORCE_INLINE size_t Lizard_get_price_LZ4(Lizard_stream_t* const ctx, const BYTE *ip, const size_t litLength, U32 offset, size_t matchLength) \n{\n    size_t price = 0;\n    BYTE token = 0;\n#if 0 //def LIZARD_USE_HUFFMAN\n    const BYTE* literals = ip - litLength;\n    U32 u;\n\n    if (ctx->cachedLiterals == literals && litLength >= ctx->cachedLitLength) {\n        size_t const additional = litLength - ctx->cachedLitLength;\n        const BYTE* literals2 = ctx->cachedLiterals + ctx->cachedLitLength;\n        price = ctx->cachedPrice + additional * ctx->log2LitSum;\n        for (u=0; u < additional; u++)\n            price -= Lizard_highbit32(ctx->litFreq[literals2[u]]+1);\n        ctx->cachedPrice = (U32)price;\n        ctx->cachedLitLength = (U32)litLength;\n    } else {\n        price = litLength * ctx->log2LitSum;\n        for (u=0; u < litLength; u++)\n            price -= Lizard_highbit32(ctx->litFreq[literals[u]]+1);\n\n        if (litLength >= 12) {\n            ctx->cachedLiterals = literals;\n            ctx->cachedPrice = (U32)price;\n            ctx->cachedLitLength = (U32)litLength;\n        }\n    }\n#else\n    price += 8*litLength;  /* Copy Literals */\n    (void)ip;\n    (void)ctx;\n#endif\n\n    /* Encode Literal length */\n    if (litLength >= RUN_MASK_LZ4) {\n        size_t len = litLength - RUN_MASK_LZ4;\n        token = RUN_MASK_LZ4; \n        if (len >= (1<<16)) price += 32;\n        else if (len >= 254) price += 24;\n        else price += 8;\n    }\n    else token = (BYTE)litLength;\n\n\n    /* Encode MatchLength */\n    if (offset) {\n        size_t length;\n        price += 16; /* Encode Offset */\n\n        if (offset < 8) return LIZARD_MAX_PRICE; // error\n        if (matchLength < MINMATCH) return LIZARD_MAX_PRICE; // error\n            \n        length = matchLength - MINMATCH;\n        if (length >= ML_MASK_LZ4) {\n            token += (BYTE)(ML_MASK_LZ4<<RUN_BITS_LZ4);\n            length -= ML_MASK_LZ4;\n            if (length >= (1<<16)) price += 32;\n            else if (length >= 254) price += 24;\n            else price += 8;\n        }\n        else token += (BYTE)(length<<RUN_BITS_LZ4);\n    }\n\n    if (ctx->huffType) { \n        if (offset > 0 || matchLength > 0) price += 2;\n        price += LIZARD_GET_TOKEN_PRICE_LZ4(token);\n    } else {\n        price += 8; // token\n    }\n\n    return price;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_decompress.c",
    "content": "﻿/*\n   Lizard - Fast LZ compression algorithm\n   Copyright (C) 2011-2016, Yann Collet\n   Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n    - Lizard source repository : https://github.com/inikep/lizard\n*/\n\n\n/**************************************\n*  Includes\n**************************************/\n//#define LIZARD_STATS 1 // 0=simple stats, 1=more, 2=full\n#ifdef LIZARD_STATS\n    #include \"test/lizard_stats.h\"\n#endif\n#include \"lizard_compress.h\"\n#include \"lizard_decompress.h\"\n#include \"lizard_common.h\"\n#include <stdio.h> // printf\n#include <stdint.h> // intptr_t\n\n\n/*-************************************\n*  Local Structures and types\n**************************************/\ntypedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;\ntypedef enum { full = 0, partial = 1 } earlyEnd_directive;\n\n#include \"lizard_decompress_lz4.h\"\n#ifndef USE_LZ4_ONLY\n    #ifdef LIZARD_USE_TEST\n        #include \"test/lizard_common_test.h\"\n        #include \"test/lizard_decompress_test.h\"\n    #else\n        #include \"lizard_decompress_liz.h\"\n    #endif\n#endif\n#include \"entropy/huf.h\"\n\n\n/*-*****************************\n*  Decompression functions\n*******************************/\n\nFORCE_INLINE size_t Lizard_readStream(int flag, const BYTE** ip, const BYTE* const iend, BYTE* op, BYTE* const oend, const BYTE** streamPtr, const BYTE** streamEnd, int streamFlag)\n{\n    if (!flag) {\n        if (*ip > iend - 3) return 0;\n        *streamPtr = *ip + 3;\n        *streamEnd = *streamPtr + MEM_readLE24(*ip);\n        if (*streamEnd < *streamPtr) return 0;\n        *ip = *streamEnd;\n#ifdef LIZARD_STATS\n        uncompr_stream[streamFlag] += *streamEnd-*streamPtr;\n#else\n        (void)streamFlag;\n#endif\n        return 1;\n    } else {\n#ifndef LIZARD_NO_HUFFMAN\n        size_t res, streamLen, comprStreamLen;\n\n        if (*ip > iend - 6) return 0;\n        streamLen = MEM_readLE24(*ip);\n        comprStreamLen = MEM_readLE24(*ip + 3);\n\n        if ((op > oend - streamLen) || (*ip + comprStreamLen > iend - 6)) return 0;\n        res = HUF_decompress(op, streamLen, *ip + 6, comprStreamLen);\n        if (HUF_isError(res) || (res != streamLen)) return 0;\n        \n        *ip += comprStreamLen + 6;\n        *streamPtr = op;\n        *streamEnd = *streamPtr + streamLen;\n#ifdef LIZARD_STATS\n        compr_stream[streamFlag] += comprStreamLen + 6;\n        decompr_stream[streamFlag] += *streamEnd-*streamPtr;\n#endif\n        return 1;\n#else\n        fprintf(stderr, \"compiled with LIZARD_NO_HUFFMAN\\n\");\n        (void)op; (void)oend;\n        return 0;\n#endif\n    }\n}\n\n\nFORCE_INLINE int Lizard_decompress_generic(\n                 const char* source,\n                 char* const dest,\n                 int inputSize,\n                 int outputSize,         /* this value is the max size of Output Buffer. */\n                 int partialDecoding,    /* full, partial */\n                 int targetOutputSize,   /* only used if partialDecoding==partial */\n                 int dict,               /* noDict, withPrefix64k, usingExtDict */\n                 const BYTE* const lowPrefix,  /* == dest if dict == noDict */\n                 const BYTE* const dictStart,  /* only if dict==usingExtDict */\n                 const size_t dictSize         /* note : = 0 if noDict */\n                 )\n{\n    /* Local Variables */\n    const BYTE* ip = (const BYTE*) source, *istart = (const BYTE*) source;\n    const BYTE* const iend = ip + inputSize;\n    BYTE* op = (BYTE*) dest;\n    BYTE* const oend = op + outputSize;\n    BYTE* oexit = op + targetOutputSize;\n    Lizard_parameters params;\n    Lizard_dstream_t ctx;\n    BYTE* decompFlagsBase, *decompOff24Base, *decompOff16Base, *decompLiteralsBase = NULL;\n    int res, compressionLevel;\n\n    if (inputSize < 1) { LIZARD_LOG_DECOMPRESS(\"inputSize=%d outputSize=%d targetOutputSize=%d partialDecoding=%d\\n\", inputSize, outputSize, targetOutputSize, partialDecoding); return 0; }\n\n    compressionLevel = *ip++;\n\n    if (compressionLevel < LIZARD_MIN_CLEVEL || compressionLevel > LIZARD_MAX_CLEVEL) {\n        LIZARD_LOG_DECOMPRESS(\"ERROR Lizard_decompress_generic inputSize=%d compressionLevel=%d\\n\", inputSize, compressionLevel);\n        return -1;\n    }\n\n    LIZARD_LOG_DECOMPRESS(\"Lizard_decompress_generic ip=%p inputSize=%d targetOutputSize=%d dest=%p outputSize=%d cLevel=%d dict=%d dictSize=%d dictStart=%p partialDecoding=%d\\n\", ip, inputSize, targetOutputSize, dest, outputSize, compressionLevel, dict, (int)dictSize, dictStart, partialDecoding);\n\n    decompLiteralsBase = (BYTE*)malloc(4*LIZARD_HUF_BLOCK_SIZE);\n    if (!decompLiteralsBase) return -1;\n    decompFlagsBase = decompLiteralsBase + LIZARD_HUF_BLOCK_SIZE;\n    decompOff24Base = decompFlagsBase + LIZARD_HUF_BLOCK_SIZE;\n    decompOff16Base = decompOff24Base + LIZARD_HUF_BLOCK_SIZE;\n\n#ifdef LIZARD_STATS\n    init_stats();\n#endif\n    (void)istart;\n\n    while (ip < iend)\n    {\n        res = *ip++;\n        if (res == LIZARD_FLAG_UNCOMPRESSED) /* uncompressed */\n        {\n            uint32_t length;\n            if (ip > iend - 3) { LIZARD_LOG_DECOMPRESS(\"UNCOMPRESSED  ip[%p] > iend[%p] - 3\\n\", ip, iend); goto _output_error; }\n            length = MEM_readLE24(ip);\n            ip += 3;\n         //   printf(\"%d: total=%d block=%d UNCOMPRESSED op=%p oexit=%p oend=%p\\n\", (int)(op-(BYTE*)dest) ,(int)(ip-istart), length, op, oexit, oend);\n            if (ip + length > iend || op + length > oend) { LIZARD_LOG_DECOMPRESS(\"UNCOMPRESSED  ip[%p]+length[%d] > iend[%p]\\n\", ip, length, iend); goto _output_error; }\n            memcpy(op, ip, length);\n            op += length;\n            ip += length;\n            if ((partialDecoding) && (op >= oexit)) break;\n#ifdef LIZARD_STATS\n            uncompr_stream[LIZARD_STREAM_UNCOMPRESSED] += length;\n#endif\n            continue;\n        }\n        \n        if (res&LIZARD_FLAG_LEN) {\n            LIZARD_LOG_DECOMPRESS(\"res=%d\\n\", res); goto _output_error;\n        }\n\n        if (ip > iend - 5*3) goto _output_error;\n        ctx.lenPtr = (const BYTE*)ip + 3;\n        ctx.lenEnd = ctx.lenPtr + MEM_readLE24(ip);\n        if (ctx.lenEnd < ctx.lenPtr || (ctx.lenEnd > iend - 3)) goto _output_error;\n#ifdef LIZARD_STATS\n        uncompr_stream[LIZARD_STREAM_LEN] += ctx.lenEnd-ctx.lenPtr + 3;\n#endif\n        ip = ctx.lenEnd;\n\n        {   size_t streamLen;\n#ifdef LIZARD_USE_LOGS\n            const BYTE* ipos;\n            size_t comprFlagsLen, comprLiteralsLen, total;\n#endif\n            streamLen = Lizard_readStream(res&LIZARD_FLAG_OFFSET16, &ip, iend, decompOff16Base, decompOff16Base + LIZARD_HUF_BLOCK_SIZE, &ctx.offset16Ptr, &ctx.offset16End, LIZARD_STREAM_OFFSET16);\n            if (streamLen == 0) goto _output_error;\n\n            streamLen = Lizard_readStream(res&LIZARD_FLAG_OFFSET24, &ip, iend, decompOff24Base, decompOff24Base + LIZARD_HUF_BLOCK_SIZE, &ctx.offset24Ptr, &ctx.offset24End, LIZARD_STREAM_OFFSET24);\n            if (streamLen == 0) goto _output_error;\n\n#ifdef LIZARD_USE_LOGS\n            ipos = ip;\n            streamLen = Lizard_readStream(res&LIZARD_FLAG_FLAGS, &ip, iend, decompFlagsBase, decompFlagsBase + LIZARD_HUF_BLOCK_SIZE, &ctx.flagsPtr, &ctx.flagsEnd, LIZARD_STREAM_FLAGS);\n            if (streamLen == 0) goto _output_error;\n            streamLen = (size_t)(ctx.flagsEnd-ctx.flagsPtr);\n            comprFlagsLen = ((size_t)(ip - ipos) + 3 >= streamLen) ? 0 : (size_t)(ip - ipos);\n            ipos = ip;\n#else\n            streamLen = Lizard_readStream(res&LIZARD_FLAG_FLAGS, &ip, iend, decompFlagsBase, decompFlagsBase + LIZARD_HUF_BLOCK_SIZE, &ctx.flagsPtr, &ctx.flagsEnd, LIZARD_STREAM_FLAGS);\n            if (streamLen == 0) goto _output_error;\n#endif\n\n            streamLen = Lizard_readStream(res&LIZARD_FLAG_LITERALS, &ip, iend, decompLiteralsBase, decompLiteralsBase + LIZARD_HUF_BLOCK_SIZE, &ctx.literalsPtr, &ctx.literalsEnd, LIZARD_STREAM_LITERALS);\n            if (streamLen == 0) goto _output_error;\n#ifdef LIZARD_USE_LOGS\n            streamLen = (size_t)(ctx.literalsEnd-ctx.literalsPtr);\n            comprLiteralsLen = ((size_t)(ip - ipos) + 3 >= streamLen) ? 0 : (size_t)(ip - ipos);\n            total = (size_t)(ip-(ctx.lenEnd-1));\n#endif\n\n            if (ip > iend) goto _output_error;\n\n            LIZARD_LOG_DECOMPRESS(\"%d: total=%d block=%d flagsLen=%d(HUF=%d) literalsLen=%d(HUF=%d) offset16Len=%d offset24Len=%d lengthsLen=%d \\n\", (int)(op-(BYTE*)dest) ,(int)(ip-istart), (int)total, \n                        (int)(ctx.flagsEnd-ctx.flagsPtr), (int)comprFlagsLen, (int)(ctx.literalsEnd-ctx.literalsPtr), (int)comprLiteralsLen, \n                        (int)(ctx.offset16End-ctx.offset16Ptr), (int)(ctx.offset24End-ctx.offset24Ptr), (int)(ctx.lenEnd-ctx.lenPtr));\n        }\n\n        ctx.last_off = -LIZARD_INIT_LAST_OFFSET;\n        params = Lizard_defaultParameters[compressionLevel - LIZARD_MIN_CLEVEL];\n        if (params.decompressType == Lizard_coderwords_LZ4)\n            res = Lizard_decompress_LZ4(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);\n        else \n#ifdef USE_LZ4_ONLY\n            res = Lizard_decompress_LZ4(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);\n#else\n            res = Lizard_decompress_LIZv1(&ctx, op, outputSize, partialDecoding, targetOutputSize, dict, lowPrefix, dictStart, dictSize, compressionLevel);\n#endif        \n        LIZARD_LOG_DECOMPRESS(\"Lizard_decompress_generic res=%d inputSize=%d\\n\", res, (int)(ctx.literalsEnd-ctx.lenEnd));\n\n        if (res <= 0) { free(decompLiteralsBase); return res; }\n        \n        op += res;\n        outputSize -= res;\n        if ((partialDecoding) && (op >= oexit)) break;\n    }\n\n#ifdef LIZARD_STATS\n    print_stats();\n#endif\n\n    LIZARD_LOG_DECOMPRESS(\"Lizard_decompress_generic total=%d\\n\", (int)(op-(BYTE*)dest));\n    free(decompLiteralsBase);\n    return (int)(op-(BYTE*)dest);\n\n_output_error:\n    LIZARD_LOG_DECOMPRESS(\"Lizard_decompress_generic ERROR ip=%p iend=%p\\n\", ip, iend);\n    free(decompLiteralsBase);\n    return -1;\n}\n\n\nint Lizard_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize)\n{\n    return Lizard_decompress_generic(source, dest, compressedSize, maxDecompressedSize, full, 0, noDict, (BYTE*)dest, NULL, 0);\n}\n\nint Lizard_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize)\n{\n    return Lizard_decompress_generic(source, dest, compressedSize, maxDecompressedSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0);\n}\n\n\n/*===== streaming decompression functions =====*/\n\n\n/*\n * If you prefer dynamic allocation methods,\n * Lizard_createStreamDecode()\n * provides a pointer (void*) towards an initialized Lizard_streamDecode_t structure.\n */\nLizard_streamDecode_t* Lizard_createStreamDecode(void)\n{\n    Lizard_streamDecode_t* lizards = (Lizard_streamDecode_t*) ALLOCATOR(1, sizeof(Lizard_streamDecode_t));\n    return lizards;\n}\n\nint Lizard_freeStreamDecode (Lizard_streamDecode_t* Lizard_stream)\n{\n    FREEMEM(Lizard_stream);\n    return 0;\n}\n\n/*!\n * Lizard_setStreamDecode() :\n * Use this function to instruct where to find the dictionary.\n * This function is not necessary if previous data is still available where it was decoded.\n * Loading a size of 0 is allowed (same effect as no dictionary).\n * Return : 1 if OK, 0 if error\n */\nint Lizard_setStreamDecode (Lizard_streamDecode_t* Lizard_streamDecode, const char* dictionary, int dictSize)\n{\n    Lizard_streamDecode_t* lizardsd = (Lizard_streamDecode_t*) Lizard_streamDecode;\n    lizardsd->prefixSize = (size_t) dictSize;\n    lizardsd->prefixEnd = (const BYTE*) dictionary + dictSize;\n    lizardsd->externalDict = NULL;\n    lizardsd->extDictSize  = 0;\n    return 1;\n}\n\n/*\n*_continue() :\n    These decoding functions allow decompression of multiple blocks in \"streaming\" mode.\n    Previously decoded blocks must still be available at the memory position where they were decoded.\n    If it's not possible, save the relevant part of decoded data into a safe buffer,\n    and indicate where it stands using Lizard_setStreamDecode()\n*/\nint Lizard_decompress_safe_continue (Lizard_streamDecode_t* Lizard_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize)\n{\n    Lizard_streamDecode_t* lizardsd = (Lizard_streamDecode_t*) Lizard_streamDecode;\n    int result;\n\n    if (lizardsd->prefixEnd == (BYTE*)dest) {\n        result = Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                        full, 0, usingExtDict, lizardsd->prefixEnd - lizardsd->prefixSize, lizardsd->externalDict, lizardsd->extDictSize);\n        if (result <= 0) return result;\n        lizardsd->prefixSize += result;\n        lizardsd->prefixEnd  += result;\n    } else {\n        lizardsd->extDictSize = lizardsd->prefixSize;\n        lizardsd->externalDict = lizardsd->prefixEnd - lizardsd->extDictSize;\n        result = Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize,\n                                        full, 0, usingExtDict, (BYTE*)dest, lizardsd->externalDict, lizardsd->extDictSize);\n        if (result <= 0) return result;\n        lizardsd->prefixSize = result;\n        lizardsd->prefixEnd  = (BYTE*)dest + result;\n    }\n\n    return result;\n}\n\n\n/*\nAdvanced decoding functions :\n*_usingDict() :\n    These decoding functions work the same as \"_continue\" ones,\n    the dictionary must be explicitly provided within parameters\n*/\n\nint Lizard_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)\n{\n    if (dictSize==0)\n        return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, noDict, (BYTE*)dest, NULL, 0);\n    if (dictStart+dictSize == dest)\n    {\n        if (dictSize >= (int)(LIZARD_DICT_SIZE - 1))\n            return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, withPrefix64k, (BYTE*)dest-LIZARD_DICT_SIZE, NULL, 0);\n        return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0);\n    }\n    return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);\n}\n\n/* debug function */\nint Lizard_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize)\n{\n    return Lizard_decompress_generic(source, dest, compressedSize, maxOutputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize);\n}\n\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_decompress.h",
    "content": "﻿/*\n   Lizard - Fast LZ compression algorithm\n   Header File\n   Copyright (C) 2011-2016, Yann Collet\n   Copyright (C) 2016-2017, Przemyslaw Skibinski <inikep@gmail.com>\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n    - Lizard source repository : https://github.com/inikep/lizard\n*/\n#ifndef LIZARD_DECOMPRESS_H_2983\n#define LIZARD_DECOMPRESS_H_2983\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*^***************************************************************\n*  Export parameters\n*****************************************************************/\n/*\n*  LIZARD_DLL_EXPORT :\n*  Enable exporting of functions when building a Windows DLL\n*/\n#if defined(LIZARD_DLL_EXPORT) && (LIZARD_DLL_EXPORT==1)\n#  define LIZARDDLIB_API __declspec(dllexport)\n#elif defined(LIZARD_DLL_IMPORT) && (LIZARD_DLL_IMPORT==1)\n#  define LIZARDDLIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define LIZARDDLIB_API\n#endif\n\n\n/*-************************************\n*  Simple Functions\n**************************************/\n\n/*\nLizard_decompress_safe() :\n    compressedSize : is the precise full size of the compressed block.\n    maxDecompressedSize : is the size of destination buffer, which must be already allocated.\n    return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)\n             If destination buffer is not large enough, decoding will stop and output an error code (<0).\n             If the source stream is detected malformed, the function will stop decoding and return a negative result.\n             This function is protected against buffer overflow exploits, including malicious data packets.\n             It never writes outside output buffer, nor reads outside input buffer.\n*/\nLIZARDDLIB_API int Lizard_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);\n\n\n\n/*!\nLizard_decompress_safe_partial() :\n    This function decompress a compressed block of size 'compressedSize' at position 'source'\n    into destination buffer 'dest' of size 'maxDecompressedSize'.\n    The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,\n    reducing decompression time.\n    return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)\n       Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.\n             Always control how many bytes were decoded.\n             If the source stream is detected malformed, the function will stop decoding and return a negative result.\n             This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets\n*/\nLIZARDDLIB_API int Lizard_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);\n\n\n\n/*-**********************************************\n*  Streaming Decompression Functions\n************************************************/\ntypedef struct Lizard_streamDecode_s Lizard_streamDecode_t;\n\n/*\n * Lizard_streamDecode_t\n * information structure to track an Lizard stream.\n * init this structure content using Lizard_setStreamDecode or memset() before first use !\n *\n * In the context of a DLL (liblizard) please prefer usage of construction methods below.\n * They are more future proof, in case of a change of Lizard_streamDecode_t size in the future.\n * Lizard_createStreamDecode will allocate and initialize an Lizard_streamDecode_t structure\n * Lizard_freeStreamDecode releases its memory.\n */\nLIZARDDLIB_API Lizard_streamDecode_t* Lizard_createStreamDecode(void);\nLIZARDDLIB_API int                 Lizard_freeStreamDecode (Lizard_streamDecode_t* Lizard_stream);\n\n/*! Lizard_setStreamDecode() :\n *  Use this function to instruct where to find the dictionary.\n *  Setting a size of 0 is allowed (same effect as reset).\n *  @return : 1 if OK, 0 if error\n */\nLIZARDDLIB_API int Lizard_setStreamDecode (Lizard_streamDecode_t* Lizard_streamDecode, const char* dictionary, int dictSize);\n\n/*\n*_continue() :\n    These decoding functions allow decompression of multiple blocks in \"streaming\" mode.\n    Previously decoded blocks *must* remain available at the memory position where they were decoded (up to LIZARD_DICT_SIZE)\n    In the case of a ring buffers, decoding buffer must be either :\n    - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)\n      In which case, the decoding & encoding ring buffer can have any size, including small ones ( < LIZARD_DICT_SIZE).\n    - Larger than encoding buffer, by a minimum of maxBlockSize more bytes.\n      maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.\n      In which case, encoding and decoding buffers do not need to be synchronized,\n      and encoding ring buffer can have any size, including small ones ( < LIZARD_DICT_SIZE).\n    - _At least_ LIZARD_DICT_SIZE + 8 bytes + maxBlockSize.\n      In which case, encoding and decoding buffers do not need to be synchronized,\n      and encoding ring buffer can have any size, including larger than decoding buffer.\n    Whenever these conditions are not possible, save the last LIZARD_DICT_SIZE of decoded data into a safe buffer,\n    and indicate where it is saved using Lizard_setStreamDecode()\n*/\nLIZARDDLIB_API int Lizard_decompress_safe_continue (Lizard_streamDecode_t* Lizard_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);\n\n\n/*\nAdvanced decoding functions :\n*_usingDict() :\n    These decoding functions work the same as\n    a combination of Lizard_setStreamDecode() followed by Lizard_decompress_x_continue()\n    They are stand-alone. They don't need nor update an Lizard_streamDecode_t structure.\n*/\nLIZARDDLIB_API int Lizard_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* LIZARD_DECOMPRESS_H_2983827168210 */\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_decompress_liz.h",
    "content": "﻿/*\n  [0_MMMM_LLL] - 16-bit offset, 4-bit match length (4-15+), 3-bit literal length (0-7+)\n  [1_MMMM_LLL] -   last offset, 4-bit match length (0-15+), 3-bit literal length (0-7+)\n  flag 31      - 24-bit offset,        match length (47+),    no literal length\n  flag 0-30    - 24-bit offset,  31 match lengths (16-46),    no literal length\n*/\n\n/*! Lizard_decompress_LIZv1() :\n *  This generic decompression function cover all use cases.\n *  It shall be instantiated several times, using different sets of directives\n *  Note that it is important this generic function is really inlined,\n *  in order to remove useless branches during compilation optimization.\n */\nFORCE_INLINE int Lizard_decompress_LIZv1(\n                 Lizard_dstream_t* ctx,\n                 BYTE* const dest,\n                 int outputSize,         /* this value is the max size of Output Buffer. */\n\n                 int partialDecoding,    /* full, partial */\n                 int targetOutputSize,   /* only used if partialDecoding==partial */\n                 int dict,               /* noDict, withPrefix64k, usingExtDict */\n                 const BYTE* const lowPrefix,  /* == dest if dict == noDict */\n                 const BYTE* const dictStart,  /* only if dict==usingExtDict */\n                 const size_t dictSize,         /* note : = 0 if noDict */\n                 int compressionLevel\n                 )\n{\n    /* Local Variables */\n    int inputSize = (int)(ctx->flagsEnd - ctx->flagsPtr);\n    const BYTE* const blockBase = ctx->flagsPtr;\n    const BYTE* const iend = ctx->literalsEnd;\n\n    BYTE* op = dest;\n    BYTE* const oend = op + outputSize;\n    BYTE* cpy = NULL;\n    BYTE* oexit = op + targetOutputSize;\n    const BYTE* const lowLimit = lowPrefix - dictSize;\n    const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;\n\n    const int checkOffset = (dictSize < (int)(LIZARD_DICT_SIZE));\n\n    intptr_t last_off = ctx->last_off;\n    intptr_t length = 0;\n    (void)compressionLevel;\n\n    /* Special cases */\n    if (unlikely(outputSize==0)) return ((inputSize==1) && (*ctx->flagsPtr==0)) ? 0 : -1;  /* Empty output buffer */\n\n    /* Main Loop : decode sequences */\n    while (ctx->flagsPtr < ctx->flagsEnd) {\n        unsigned token;\n        const BYTE* match;\n    //    intptr_t litLength;\n\n        if ((partialDecoding) && (op >= oexit)) return (int) (op-dest); \n\n        /* get literal length */\n        token = *ctx->flagsPtr++;\n\n        if (token >= 32)\n        {\n            if ((length=(token & MAX_SHORT_LITLEN)) == MAX_SHORT_LITLEN) {\n                if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"1A\"); goto _output_error; }\n                length = *ctx->literalsPtr;\n                ctx->literalsPtr++;\n                if unlikely(length >= 254) {\n                    if (length == 254) {\n                        if (unlikely(ctx->literalsPtr > iend - 2)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"1B\"); goto _output_error; }  /* overflow detection */\n                        length = MEM_readLE16(ctx->literalsPtr);\n                        ctx->literalsPtr += 2;\n                    } else {\n                        if (unlikely(ctx->literalsPtr > iend - 3)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"1C\"); goto _output_error; }  /* overflow detection */\n                        length = MEM_readLE24(ctx->literalsPtr);\n                        ctx->literalsPtr += 3;\n                    }\n                }\n                length += MAX_SHORT_LITLEN;\n                if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LIZv1(\"2\"); goto _output_error; }  /* overflow detection */\n                if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZARD_LOG_DECOMPRESS_LIZv1(\"3\"); goto _output_error; }   /* overflow detection */\n            }\n\n            /* copy literals */\n            cpy = op + length;\n            if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr > iend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"offset outside buffers\\n\"); goto _output_error; }   /* Error : offset outside buffers */\n    #if 1\n            Lizard_wildCopy16(op, ctx->literalsPtr, cpy);\n            op = cpy;\n            ctx->literalsPtr += length; \n    #else\n            Lizard_copy8(op, ctx->literalsPtr);\n            Lizard_copy8(op+8, ctx->literalsPtr+8);\n            if (length > 16)\n                Lizard_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);\n            op = cpy;\n            ctx->literalsPtr += length; \n    #endif\n\n            /* get offset */\n#if 1\n            if (likely(ctx->offset16End - ctx->offset16Ptr >= 2)) {\n                /* branchless */\n                intptr_t new_off = MEM_readLE16(ctx->offset16Ptr);\n                uintptr_t not_repCode = (uintptr_t)(token >> ML_RUN_BITS) - 1;\n                last_off ^= not_repCode & (last_off ^ -new_off);\n                ctx->offset16Ptr = (BYTE*)((uintptr_t)ctx->offset16Ptr + (not_repCode & 2));\n            }\n#else\n            int has_offset = ((token >> ML_RUN_BITS) == 0) && (ctx->offset16End - ctx->offset16Ptr >= 2);\n\n            if (likely(has_offset)) {\n                last_off = -(intptr_t)MEM_readLE16(ctx->offset16Ptr); \n                ctx->offset16Ptr += 2;\n            }\n#endif\n\n            /* get matchlength */\n            length = (token >> RUN_BITS_LIZv1) & MAX_SHORT_MATCHLEN;\n            if (length == MAX_SHORT_MATCHLEN) {\n                if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"6\"); goto _output_error; } \n                length = *ctx->literalsPtr;\n                if unlikely(length >= 254) {\n                    if (length == 254) {\n                        length = MEM_readLE16(ctx->literalsPtr+1);\n                        ctx->literalsPtr += 2;\n                    } else {\n                        length = MEM_readLE24(ctx->literalsPtr+1);\n                        ctx->literalsPtr += 3;\n                    }\n                }\n                length += MAX_SHORT_MATCHLEN;\n                ctx->literalsPtr++;\n                if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LIZv1(\"7\"); goto _output_error; }  /* overflow detection */\n            }\n\n            DECOMPLOG_CODEWORDS_LIZv1(\"T32+ literal=%u match=%u offset=%d ipos=%d opos=%d\\n\", (U32)litLength, (U32)length, (int)-last_off, (U32)(ctx->flagsPtr-blockBase), (U32)(op-dest));\n        }\n        else\n        if (token < LIZARD_LAST_LONG_OFF)\n        {\n            if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"8\"); goto _output_error; } \n            length = token + MM_LONGOFF;\n            last_off = -(intptr_t)MEM_readLE24(ctx->offset24Ptr); \n            ctx->offset24Ptr += 3;\n            DECOMPLOG_CODEWORDS_LIZv1(\"T0-30 literal=%u match=%u offset=%d\\n\", 0, (U32)length, (int)-last_off);\n        }\n        else \n        { \n            if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"9\"); goto _output_error; } \n            length = *ctx->literalsPtr;\n            if unlikely(length >= 254) {\n                if (length == 254) {\n                    length = MEM_readLE16(ctx->literalsPtr+1);\n                    ctx->literalsPtr += 2;\n                } else {\n                    length = MEM_readLE24(ctx->literalsPtr+1);\n                    ctx->literalsPtr += 3;\n                }\n            }\n            ctx->literalsPtr++;\n            length += LIZARD_LAST_LONG_OFF + MM_LONGOFF;\n\n            if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"10\"); goto _output_error; } \n            last_off = -(intptr_t)MEM_readLE24(ctx->offset24Ptr); \n            ctx->offset24Ptr += 3;\n        }\n\n\n        match = op + last_off;\n        if ((checkOffset) && ((unlikely((uintptr_t)(-last_off) > (uintptr_t)op) || (match < lowLimit)))) { LIZARD_LOG_DECOMPRESS_LIZv1(\"lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-last_off[%d]\\n\", lowPrefix, (int)dictSize, lowLimit, match, op, (int)last_off); goto _output_error; }  /* Error : offset outside buffers */\n\n        /* check external dictionary */\n        if ((dict==usingExtDict) && (match < lowPrefix)) {\n            if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"12\"); goto _output_error; }  /* doesn't respect parsing restriction */\n\n            if (length <= (intptr_t)(lowPrefix - match)) {\n                /* match can be copied as a single segment from external dictionary */\n                memmove(op, dictEnd - (lowPrefix-match), length);\n                op += length;\n            } else {\n                /* match encompass external dictionary and current block */\n                size_t const copySize = (size_t)(lowPrefix-match);\n                size_t const restSize = length - copySize;\n                memcpy(op, dictEnd - copySize, copySize);\n                op += copySize;\n                if (restSize > (size_t)(op-lowPrefix)) {  /* overlap copy */\n                    BYTE* const endOfMatch = op + restSize;\n                    const BYTE* copyFrom = lowPrefix;\n                    while (op < endOfMatch) *op++ = *copyFrom++;\n                } else {\n                    memcpy(op, lowPrefix, restSize);\n                    op += restSize;\n            }   }\n            continue;\n        }\n\n        /* copy match within block */\n        cpy = op + length;\n        if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"13match=%p lowLimit=%p\\n\", match, lowLimit); goto _output_error; }   /* Error : offset outside buffers */\n        Lizard_copy8(op, match);\n        Lizard_copy8(op+8, match+8);\n        if (length > 16)\n            Lizard_wildCopy16(op + 16, match + 16, cpy);\n        op = cpy;\n    }\n\n    /* last literals */\n    length = ctx->literalsEnd - ctx->literalsPtr;\n    cpy = op + length;\n    if ((length < 0) || (ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZARD_LOG_DECOMPRESS_LIZv1(\"14\"); goto _output_error; }   /* Error : input must be consumed */\n    memcpy(op, ctx->literalsPtr, length);\n    ctx->literalsPtr += length;\n    op += length;\n\n    /* end of decoding */\n    ctx->last_off = last_off;\n    return (int) (op-dest);     /* Nb of output bytes decoded */\n\n    /* Overflow error detected */\n_output_error:\n    LIZARD_LOG_DECOMPRESS_LIZv1(\"_output_error=%d ctx->flagsPtr=%p blockBase=%p\\n\", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);\n    LIZARD_LOG_DECOMPRESS_LIZv1(\"cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\\n\", cpy, oend, (int)length, ctx->literalsPtr+length, iend);\n    return (int) (-(ctx->flagsPtr-blockBase))-1;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_decompress_lz4.h",
    "content": "﻿/*! Lizard_decompress_LZ4() :\n *  This generic decompression function cover all use cases.\n *  It shall be instantiated several times, using different sets of directives\n *  Note that it is important this generic function is really inlined,\n *  in order to remove useless branches during compilation optimization.\n */\nFORCE_INLINE int Lizard_decompress_LZ4(\n                 Lizard_dstream_t* ctx,\n                 BYTE* const dest,\n                 int outputSize,         /* this value is the max size of Output Buffer. */\n\n                 int partialDecoding,    /* full, partial */\n                 int targetOutputSize,   /* only used if partialDecoding==partial */\n                 int dict,               /* noDict, withPrefix64k, usingExtDict */\n                 const BYTE* const lowPrefix,  /* == dest if dict == noDict */\n                 const BYTE* const dictStart,  /* only if dict==usingExtDict */\n                 const size_t dictSize,         /* note : = 0 if noDict */\n                 int compressionLevel\n                 )\n{\n    /* Local Variables */\n    int inputSize = (int)(ctx->flagsEnd - ctx->flagsPtr);\n    const BYTE* const blockBase = ctx->flagsPtr;\n    const BYTE* const iend = ctx->literalsEnd;\n    BYTE* op = dest;\n    BYTE* const oend = op + outputSize;\n    BYTE* cpy = NULL;\n    BYTE* oexit = op + targetOutputSize;\n    const BYTE* const lowLimit = lowPrefix - dictSize;\n    const BYTE* const dictEnd = dictStart ? (const BYTE*)dictStart + dictSize : NULL;\n\n    const int checkOffset = (dictSize < (int)(LIZARD_DICT_SIZE));\n\n    intptr_t length = 0;\n    (void)compressionLevel;\n\n    /* Special cases */\n    if (unlikely(outputSize==0)) return ((inputSize==1) && (*ctx->flagsPtr==0)) ? 0 : -1;  /* Empty output buffer */\n\n    /* Main Loop : decode sequences */\n    while (ctx->flagsPtr < ctx->flagsEnd) {\n        unsigned token;\n        const BYTE* match;\n        size_t offset;\n\n        /* get literal length */\n        token = *ctx->flagsPtr++;\n        if ((length=(token & RUN_MASK_LZ4)) == RUN_MASK_LZ4) {\n            if (unlikely(ctx->literalsPtr > iend - 5)) { LIZARD_LOG_DECOMPRESS_LZ4(\"0\"); goto _output_error; } \n            length = *ctx->literalsPtr;\n            if unlikely(length >= 254) {\n                if (length == 254) {\n                    length = MEM_readLE16(ctx->literalsPtr+1);\n                    ctx->literalsPtr += 2;\n                } else {\n                    length = MEM_readLE24(ctx->literalsPtr+1);\n                    ctx->literalsPtr += 3;\n                }\n            }\n            length += RUN_MASK_LZ4;\n            ctx->literalsPtr++;\n            if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LZ4(\"1\"); goto _output_error; }  /* overflow detection */\n            if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZARD_LOG_DECOMPRESS_LZ4(\"2\"); goto _output_error; }   /* overflow detection */\n        }\n\n        /* copy literals */\n        cpy = op + length;\n        if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr + length > iend - (2 + WILDCOPYLENGTH))) { LIZARD_LOG_DECOMPRESS_LZ4(\"offset outside buffers\\n\"); goto _output_error; }   /* Error : offset outside buffers */\n\n#if 1\n        Lizard_wildCopy16(op, ctx->literalsPtr, cpy);\n        op = cpy;\n        ctx->literalsPtr += length; \n#else\n        Lizard_copy8(op, ctx->literalsPtr);\n        Lizard_copy8(op+8, ctx->literalsPtr+8);\n        if (length > 16)\n            Lizard_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);\n        op = cpy;\n        ctx->literalsPtr += length; \n#endif\n        if ((partialDecoding) && (op >= oexit)) return (int) (op-dest);\n\n        /* get offset */\n        offset = MEM_readLE16(ctx->literalsPtr); \n        ctx->literalsPtr += 2;\n\n        match = op - offset;\n        if ((checkOffset) && (unlikely(match < lowLimit))) { LIZARD_LOG_DECOMPRESS_LZ4(\"lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-offset[%d]\\n\", lowPrefix, (int)dictSize, lowLimit, match, op, (int)offset); goto _output_error; }  /* Error : offset outside buffers */\n\n        /* get matchlength */\n        length = token >> RUN_BITS_LZ4;\n        if (length == ML_MASK_LZ4) {\n            if (unlikely(ctx->literalsPtr > iend - 5)) { LIZARD_LOG_DECOMPRESS_LZ4(\"4\"); goto _output_error; } \n            length = *ctx->literalsPtr;\n            if unlikely(length >= 254) {\n                if (length == 254) {\n                    length = MEM_readLE16(ctx->literalsPtr+1);\n                    ctx->literalsPtr += 2;\n                } else {\n                    length = MEM_readLE24(ctx->literalsPtr+1);\n                    ctx->literalsPtr += 3;\n                }\n            }\n            length += ML_MASK_LZ4;\n            ctx->literalsPtr++;\n            if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LZ4(\"5\"); goto _output_error; }  /* overflow detection */\n        }\n        length += MINMATCH;\n\n        /* check external dictionary */\n        if ((dict==usingExtDict) && (match < lowPrefix)) {\n            if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LZ4(\"6\"); goto _output_error; }  /* doesn't respect parsing restriction */\n\n            if (length <= (intptr_t)(lowPrefix - match)) {\n                /* match can be copied as a single segment from external dictionary */\n                memmove(op, dictEnd - (lowPrefix-match), length);\n                op += length;\n            } else {\n                /* match encompass external dictionary and current block */\n                size_t const copySize = (size_t)(lowPrefix-match);\n                size_t const restSize = length - copySize;\n                memcpy(op, dictEnd - copySize, copySize);\n                op += copySize;\n                if (restSize > (size_t)(op-lowPrefix)) {  /* overlap copy */\n                    BYTE* const endOfMatch = op + restSize;\n                    const BYTE* copyFrom = lowPrefix;\n                    while (op < endOfMatch) *op++ = *copyFrom++;\n                } else {\n                    memcpy(op, lowPrefix, restSize);\n                    op += restSize;\n            }   }\n            continue;\n        }\n\n        /* copy match within block */\n        cpy = op + length;\n        if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LZ4(\"1match=%p lowLimit=%p\\n\", match, lowLimit); goto _output_error; }   /* Error : offset outside buffers */\n        Lizard_copy8(op, match);\n        Lizard_copy8(op+8, match+8);\n        if (length > 16)\n            Lizard_wildCopy16(op + 16, match + 16, cpy);\n        op = cpy;\n        if ((partialDecoding) && (op >= oexit)) return (int) (op-dest);\n    }\n\n    /* last literals */\n    length = ctx->literalsEnd - ctx->literalsPtr;\n    cpy = op + length;\n    if ((length < 0) || (ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZARD_LOG_DECOMPRESS_LZ4(\"9\"); goto _output_error; }   /* Error : input must be consumed */\n    memcpy(op, ctx->literalsPtr, length);\n    ctx->literalsPtr += length;\n    op += length;\n\n    /* end of decoding */\n    return (int) (op-dest);     /* Nb of output bytes decoded */\n\n    /* Overflow error detected */\n_output_error:\n    LIZARD_LOG_DECOMPRESS_LZ4(\"_output_error=%d ctx->flagsPtr=%p blockBase=%p\\n\", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);\n    LIZARD_LOG_DECOMPRESS_LZ4(\"cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\\n\", cpy, oend, (int)length, ctx->literalsPtr+length, iend);\n    return (int) (-(ctx->flagsPtr-blockBase))-1;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_frame.c",
    "content": "﻿/*\nLizard auto-framing library\nCopyright (C) 2011-2016, Yann Collet\nCopyright (C) 2016-2017, Przemyslaw Skibinski\n\nBSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nYou can contact the author at :\n- Lizard source repository : https://github.com/inikep/lizard\n*/\n\n/* LizardF is a stand-alone API to create Lizard-compressed Frames\n*  in full conformance with specification v1.5.0\n*  All related operations, including memory management, are handled by the library.\n* */\n\n\n/*-************************************\n*  Compiler Options\n**************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n\n/*-************************************\n*  Includes\n**************************************/\n#include \"lizard_frame_static.h\"\n#include \"lizard_compress.h\"\n#include \"lizard_decompress.h\"\n#include \"lizard_common.h\"  /* LIZARD_DICT_SIZE */\n#define XXH_STATIC_LINKING_ONLY\n#include <xxhash.h>\n#include <stdio.h>\n\n\n\n/* unoptimized version; solves endianess & alignment issues */\nstatic U32 LizardF_readLE32 (const void* src)\n{\n    const BYTE* const srcPtr = (const BYTE*)src;\n    U32 value32 = srcPtr[0];\n    value32 += (srcPtr[1]<<8);\n    value32 += (srcPtr[2]<<16);\n    value32 += ((U32)srcPtr[3])<<24;\n    return value32;\n}\n\nstatic void LizardF_writeLE32 (BYTE* dstPtr, U32 value32)\n{\n    dstPtr[0] = (BYTE)value32;\n    dstPtr[1] = (BYTE)(value32 >> 8);\n    dstPtr[2] = (BYTE)(value32 >> 16);\n    dstPtr[3] = (BYTE)(value32 >> 24);\n}\n\nstatic U64 LizardF_readLE64 (const BYTE* srcPtr)\n{\n    U64 value64 = srcPtr[0];\n    value64 += ((U64)srcPtr[1]<<8);\n    value64 += ((U64)srcPtr[2]<<16);\n    value64 += ((U64)srcPtr[3]<<24);\n    value64 += ((U64)srcPtr[4]<<32);\n    value64 += ((U64)srcPtr[5]<<40);\n    value64 += ((U64)srcPtr[6]<<48);\n    value64 += ((U64)srcPtr[7]<<56);\n    return value64;\n}\n\nstatic void LizardF_writeLE64 (BYTE* dstPtr, U64 value64)\n{\n    dstPtr[0] = (BYTE)value64;\n    dstPtr[1] = (BYTE)(value64 >> 8);\n    dstPtr[2] = (BYTE)(value64 >> 16);\n    dstPtr[3] = (BYTE)(value64 >> 24);\n    dstPtr[4] = (BYTE)(value64 >> 32);\n    dstPtr[5] = (BYTE)(value64 >> 40);\n    dstPtr[6] = (BYTE)(value64 >> 48);\n    dstPtr[7] = (BYTE)(value64 >> 56);\n}\n\n\n/*-************************************\n*  Constants\n**************************************/\n#define _1BIT  0x01\n#define _2BITS 0x03\n#define _3BITS 0x07\n#define _4BITS 0x0F\n#define _8BITS 0xFF\n\n#define LIZARDF_MAGIC_SKIPPABLE_START  0x184D2A50U\n#define LIZARDF_MAGICNUMBER            0x184D2206U\n#define LIZARDF_BLOCKUNCOMPRESSED_FLAG 0x80000000U\n#define LIZARDF_BLOCKSIZEID_DEFAULT LizardF_max128KB\n\nstatic const size_t minFHSize = 7;\nstatic const size_t maxFHSize = 15;\nstatic const size_t BHSize = 4;\n\n\n/*-************************************\n*  Structures and local types\n**************************************/\ntypedef struct LizardF_cctx_s\n{\n    LizardF_preferences_t prefs;\n    U32    version;\n    U32    cStage;\n    size_t maxBlockSize;\n    size_t maxBufferSize;\n    BYTE*  tmpBuff;\n    BYTE*  tmpIn;\n    size_t tmpInSize;\n    U64    totalInSize;\n    XXH32_state_t xxh;\n    Lizard_stream_t* lizardCtxPtr;\n    U32    lizardCtxLevel;     /* 0: unallocated;  1: Lizard_stream_t;  */\n} LizardF_cctx_t;\n\ntypedef struct LizardF_dctx_s\n{\n    LizardF_frameInfo_t frameInfo;\n    U32    version;\n    U32    dStage;\n    U64    frameRemainingSize;\n    size_t maxBlockSize;\n    size_t maxBufferSize;\n    const BYTE* srcExpect;\n    BYTE*  tmpIn;\n    size_t tmpInSize;\n    size_t tmpInTarget;\n    BYTE*  tmpOutBuffer;\n    const BYTE*  dict;\n    size_t dictSize;\n    BYTE*  tmpOut;\n    size_t tmpOutSize;\n    size_t tmpOutStart;\n    XXH32_state_t xxh;\n    BYTE   header[16];\n} LizardF_dctx_t;\n\n\n/*-************************************\n*  Error management\n**************************************/\n#define LIZARDF_GENERATE_STRING(STRING) #STRING,\nstatic const char* LizardF_errorStrings[] = { LIZARDF_LIST_ERRORS(LIZARDF_GENERATE_STRING) };\n\n\nunsigned LizardF_isError(LizardF_errorCode_t code)\n{\n    return (code > (LizardF_errorCode_t)(-LizardF_ERROR_maxCode));\n}\n\nconst char* LizardF_getErrorName(LizardF_errorCode_t code)\n{\n    static const char* codeError = \"Unspecified error code\";\n    if (LizardF_isError(code)) return LizardF_errorStrings[-(int)(code)];\n    return codeError;\n}\n\n\n/*-************************************\n*  Private functions\n**************************************/\nstatic size_t LizardF_getBlockSize(unsigned blockSizeID)\n{\n    static const size_t blockSizes[7] = { 128 KB, 256 KB, 1 MB, 4 MB, 16 MB, 64 MB, 256 MB };\n\n    if (blockSizeID == 0) blockSizeID = LIZARDF_BLOCKSIZEID_DEFAULT;\n    blockSizeID -= 1;\n    if (blockSizeID >= 7) return (size_t)-LizardF_ERROR_maxBlockSize_invalid;\n\n    return blockSizes[blockSizeID];\n}\n\nstatic LizardF_blockSizeID_t LizardF_optimalBSID(const LizardF_blockSizeID_t requestedBSID, const size_t srcSize)\n{\n    LizardF_blockSizeID_t proposedBSID = LizardF_max128KB;\n    size_t maxBlockSize;\n\n    while (requestedBSID > proposedBSID)\n    {\n        maxBlockSize = LizardF_getBlockSize(proposedBSID);\n        if (srcSize <= maxBlockSize) {\n            return proposedBSID;\n        }\n        proposedBSID = (LizardF_blockSizeID_t)((int)proposedBSID + 1);\n    }\n    return requestedBSID;\n}\n\n\nstatic BYTE LizardF_headerChecksum (const void* header, size_t length)\n{\n    U32 xxh = XXH32(header, length, 0);\n    return (BYTE)(xxh >> 8);\n}\n\n\n/*-************************************\n*  Simple compression functions\n**************************************/\n\nsize_t LizardF_compressFrameBound(size_t srcSize, const LizardF_preferences_t* preferencesPtr)\n{\n    LizardF_preferences_t prefs;\n    size_t headerSize;\n    size_t streamSize;\n\n    if (preferencesPtr!=NULL) prefs = *preferencesPtr;\n    else memset(&prefs, 0, sizeof(prefs));\n\n    prefs.frameInfo.blockSizeID = LizardF_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);\n    prefs.autoFlush = 1;\n\n    headerSize = maxFHSize;      /* header size, including magic number and frame content size*/\n    streamSize = LizardF_compressBound(srcSize, &prefs);\n\n    return headerSize + streamSize;\n}\n\n\n\n/*! LizardF_compressFrame() :\n* Compress an entire srcBuffer into a valid Lizard frame, as defined by specification v1.5.0, in a single step.\n* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n* You can get the minimum value of dstMaxSize by using LizardF_compressFrameBound()\n* If this condition is not respected, LizardF_compressFrame() will fail (result is an errorCode)\n* The LizardF_preferences_t structure is optional : you can provide NULL as argument. All preferences will then be set to default.\n* The result of the function is the number of bytes written into dstBuffer.\n* The function outputs an error code if it fails (can be tested using LizardF_isError())\n*/\nsize_t LizardF_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_preferences_t* preferencesPtr)\n{\n    LizardF_cctx_t cctxI;\n    LizardF_preferences_t prefs;\n    LizardF_compressOptions_t options;\n    LizardF_errorCode_t errorCode;\n    BYTE* const dstStart = (BYTE*) dstBuffer;\n    BYTE* dstPtr = dstStart;\n    BYTE* const dstEnd = dstStart + dstMaxSize;\n\n    memset(&cctxI, 0, sizeof(cctxI));   /* works because no allocation */\n    memset(&options, 0, sizeof(options));\n\n    cctxI.version = LIZARDF_VERSION;\n    cctxI.maxBufferSize = 5 MB;   /* mess with real buffer size to prevent allocation; works because autoflush==1 & stableSrc==1 */\n\n    if (preferencesPtr!=NULL)\n        prefs = *preferencesPtr;\n    else\n        memset(&prefs, 0, sizeof(prefs));\n    if (prefs.frameInfo.contentSize != 0)\n        prefs.frameInfo.contentSize = (U64)srcSize;   /* auto-correct content size if selected (!=0) */\n\n    prefs.frameInfo.blockSizeID = LizardF_optimalBSID(prefs.frameInfo.blockSizeID, srcSize);\n    prefs.autoFlush = 1;\n    if (srcSize <= LizardF_getBlockSize(prefs.frameInfo.blockSizeID))\n        prefs.frameInfo.blockMode = LizardF_blockIndependent;   /* no need for linked blocks */\n\n    options.stableSrc = 1;\n\n    if (dstMaxSize < LizardF_compressFrameBound(srcSize, &prefs))\n        return (size_t)-LizardF_ERROR_dstMaxSize_tooSmall;\n\n    errorCode = LizardF_compressBegin(&cctxI, dstBuffer, dstMaxSize, &prefs);  /* write header */\n    if (LizardF_isError(errorCode)) goto error;\n    dstPtr += errorCode;   /* header size */\n\n    errorCode = LizardF_compressUpdate(&cctxI, dstPtr, dstEnd-dstPtr, srcBuffer, srcSize, &options);\n    if (LizardF_isError(errorCode)) goto error;\n    dstPtr += errorCode;\n\n    errorCode = LizardF_compressEnd(&cctxI, dstPtr, dstEnd-dstPtr, &options);   /* flush last block, and generate suffix */\n    if (LizardF_isError(errorCode)) goto error;\n    dstPtr += errorCode;\n\n    Lizard_freeStream(cctxI.lizardCtxPtr);\n    FREEMEM(cctxI.tmpBuff);\n    return (dstPtr - dstStart);\nerror:\n    Lizard_freeStream(cctxI.lizardCtxPtr);\n    FREEMEM(cctxI.tmpBuff);\n    return errorCode;\n}\n\n\n/*-*********************************\n*  Advanced compression functions\n***********************************/\n\n/* LizardF_createCompressionContext() :\n* The first thing to do is to create a compressionContext object, which will be used in all compression operations.\n* This is achieved using LizardF_createCompressionContext(), which takes as argument a version and an LizardF_preferences_t structure.\n* The version provided MUST be LIZARDF_VERSION. It is intended to track potential version differences between different binaries.\n* The function will provide a pointer to an allocated LizardF_compressionContext_t object.\n* If the result LizardF_errorCode_t is not OK_NoError, there was an error during context creation.\n* Object can release its memory using LizardF_freeCompressionContext();\n*/\nLizardF_errorCode_t LizardF_createCompressionContext(LizardF_compressionContext_t* LizardF_compressionContextPtr, unsigned version)\n{\n    LizardF_cctx_t* cctxPtr;\n\n    cctxPtr = (LizardF_cctx_t*)ALLOCATOR(1, sizeof(LizardF_cctx_t));\n    if (cctxPtr==NULL) return (LizardF_errorCode_t)(-LizardF_ERROR_allocation_failed);\n\n    cctxPtr->version = version;\n    cctxPtr->cStage = 0;   /* Next stage : write header */\n\n    *LizardF_compressionContextPtr = (LizardF_compressionContext_t)cctxPtr;\n\n    return LizardF_OK_NoError;\n}\n\n\nLizardF_errorCode_t LizardF_freeCompressionContext(LizardF_compressionContext_t LizardF_compressionContext)\n{\n    LizardF_cctx_t* cctxPtr = (LizardF_cctx_t*)LizardF_compressionContext;\n\n    if (cctxPtr != NULL) {  /* null pointers can be safely provided to this function, like free() */\n       Lizard_freeStream(cctxPtr->lizardCtxPtr);\n       FREEMEM(cctxPtr->tmpBuff);\n       FREEMEM(LizardF_compressionContext);\n    }\n\n    return LizardF_OK_NoError;\n}\n\n\n/*! LizardF_compressBegin() :\n* will write the frame header into dstBuffer.\n* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is LizardF_MAXHEADERFRAME_SIZE bytes.\n* The result of the function is the number of bytes written into dstBuffer for the header\n* or an error code (can be tested using LizardF_isError())\n*/\nsize_t LizardF_compressBegin(LizardF_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LizardF_preferences_t* preferencesPtr)\n{\n    LizardF_preferences_t prefNull;\n    LizardF_cctx_t* cctxPtr = (LizardF_cctx_t*)compressionContext;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    BYTE* headerStart;\n    size_t requiredBuffSize;\n\n    if (dstMaxSize < maxFHSize) return (size_t)-LizardF_ERROR_dstMaxSize_tooSmall;\n    if (cctxPtr->cStage != 0) return (size_t)-LizardF_ERROR_GENERIC;\n    memset(&prefNull, 0, sizeof(prefNull));\n    if (preferencesPtr == NULL) preferencesPtr = &prefNull;\n    cctxPtr->prefs = *preferencesPtr;\n\n    /* ctx Management */\n    if (cctxPtr->lizardCtxLevel == 0) {\n        cctxPtr->lizardCtxPtr = Lizard_createStream(cctxPtr->prefs.compressionLevel);\n        cctxPtr->lizardCtxLevel = 1;\n    }\n\n    /* Buffer Management */\n    if (cctxPtr->prefs.frameInfo.blockSizeID == 0) cctxPtr->prefs.frameInfo.blockSizeID = LIZARDF_BLOCKSIZEID_DEFAULT;\n    cctxPtr->maxBlockSize = LizardF_getBlockSize(cctxPtr->prefs.frameInfo.blockSizeID);\n    requiredBuffSize = cctxPtr->maxBlockSize + ((cctxPtr->prefs.frameInfo.blockMode == LizardF_blockLinked) * 2 * LIZARD_DICT_SIZE);\n\n    if (preferencesPtr->autoFlush)\n        requiredBuffSize = (cctxPtr->prefs.frameInfo.blockMode == LizardF_blockLinked) * LIZARD_DICT_SIZE;   /* just needs dict */\n\n    if (cctxPtr->maxBufferSize < requiredBuffSize) {\n        cctxPtr->maxBufferSize = requiredBuffSize;\n        FREEMEM(cctxPtr->tmpBuff);\n        cctxPtr->tmpBuff = (BYTE*)ALLOCATOR(1, requiredBuffSize);\n        if (cctxPtr->tmpBuff == NULL) { printf(\"ERROR in LizardF_compressBegin: Cannot allocate %d MB\\n\", (int)(requiredBuffSize>>20)); return (size_t)-LizardF_ERROR_allocation_failed; }\n    }\n    cctxPtr->tmpIn = cctxPtr->tmpBuff;\n    cctxPtr->tmpInSize = 0;\n    XXH32_reset(&(cctxPtr->xxh), 0);\n    cctxPtr->lizardCtxPtr = Lizard_resetStream((Lizard_stream_t*)(cctxPtr->lizardCtxPtr), cctxPtr->prefs.compressionLevel);\n    if (!cctxPtr->lizardCtxPtr) return (size_t)-LizardF_ERROR_allocation_failed;\n\n    /* Magic Number */\n    LizardF_writeLE32(dstPtr, LIZARDF_MAGICNUMBER);\n    dstPtr += 4;\n    headerStart = dstPtr;\n\n    /* FLG Byte */\n    *dstPtr++ = (BYTE)(((1 & _2BITS) << 6)    /* Version('01') */\n        + ((cctxPtr->prefs.frameInfo.blockMode & _1BIT ) << 5)    /* Block mode */\n        + ((cctxPtr->prefs.frameInfo.contentChecksumFlag & _1BIT ) << 2)   /* Frame checksum */\n        + ((cctxPtr->prefs.frameInfo.contentSize > 0) << 3));   /* Frame content size */\n    /* BD Byte */\n    *dstPtr++ = (BYTE)((cctxPtr->prefs.frameInfo.blockSizeID & _3BITS) << 4);\n    /* Optional Frame content size field */\n    if (cctxPtr->prefs.frameInfo.contentSize) {\n        LizardF_writeLE64(dstPtr, cctxPtr->prefs.frameInfo.contentSize);\n        dstPtr += 8;\n        cctxPtr->totalInSize = 0;\n    }\n    /* CRC Byte */\n    *dstPtr = LizardF_headerChecksum(headerStart, dstPtr - headerStart);\n    dstPtr++;\n\n    cctxPtr->cStage = 1;   /* header written, now request input data block */\n\n    return (dstPtr - dstStart);\n}\n\n\n/* LizardF_compressBound() : gives the size of Dst buffer given a srcSize to handle worst case situations.\n*                        The LizardF_frameInfo_t structure is optional :\n*                        you can provide NULL as argument, preferences will then be set to cover worst case situations.\n* */\nsize_t LizardF_compressBound(size_t srcSize, const LizardF_preferences_t* preferencesPtr)\n{\n    LizardF_preferences_t prefsNull;\n    memset(&prefsNull, 0, sizeof(prefsNull));\n    prefsNull.frameInfo.contentChecksumFlag = LizardF_contentChecksumEnabled;   /* worst case */\n    {   const LizardF_preferences_t* prefsPtr = (preferencesPtr==NULL) ? &prefsNull : preferencesPtr;\n        LizardF_blockSizeID_t bid = prefsPtr->frameInfo.blockSizeID;\n        size_t blockSize = LizardF_getBlockSize(bid);\n        unsigned nbBlocks = (unsigned)(srcSize / blockSize) + 1;\n        size_t lastBlockSize = prefsPtr->autoFlush ? srcSize % blockSize : blockSize;\n        size_t blockInfo = 4;   /* default, without block CRC option */\n        size_t frameEnd = 4 + (prefsPtr->frameInfo.contentChecksumFlag*4);\n\n        return (blockInfo * nbBlocks) + (blockSize * (nbBlocks-1)) + lastBlockSize + frameEnd;;\n    }\n}\n\n\ntypedef int (*compressFunc_t)(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level);\n\nstatic size_t LizardF_compressBlock(void* dst, const void* src, size_t srcSize, compressFunc_t compress, void* lizardctx, int level)\n{\n    /* compress one block */\n    BYTE* cSizePtr = (BYTE*)dst;\n    U32 cSize;\n    cSize = (U32)compress(lizardctx, (const char*)src, (char*)(cSizePtr+4), (int)(srcSize), (int)(srcSize-1), level);\n    LizardF_writeLE32(cSizePtr, cSize);\n    if (cSize == 0) {  /* compression failed */\n        cSize = (U32)srcSize;\n        LizardF_writeLE32(cSizePtr, cSize + LIZARDF_BLOCKUNCOMPRESSED_FLAG);\n        memcpy(cSizePtr+4, src, srcSize);\n    }\n    return cSize + 4;\n}\n\n\n\nstatic int LizardF_localLizard_compress_continue(void* ctx, const char* src, char* dst, int srcSize, int dstSize, int level)\n{\n    (void)level;\n    return Lizard_compress_continue((Lizard_stream_t*)ctx, src, dst, srcSize, dstSize);\n}\n\nstatic compressFunc_t LizardF_selectCompression(LizardF_blockMode_t blockMode)\n{\n    if (blockMode == LizardF_blockIndependent) return Lizard_compress_extState;\n    return LizardF_localLizard_compress_continue;\n}\n\nstatic int LizardF_localSaveDict(LizardF_cctx_t* cctxPtr)\n{\n    return Lizard_saveDict ((Lizard_stream_t*)(cctxPtr->lizardCtxPtr), (char*)(cctxPtr->tmpBuff), LIZARD_DICT_SIZE);\n}\n\ntypedef enum { notDone, fromTmpBuffer, fromSrcBuffer } LizardF_lastBlockStatus;\n\n/*! LizardF_compressUpdate() :\n* LizardF_compressUpdate() can be called repetitively to compress as much data as necessary.\n* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n* If this condition is not respected, LizardF_compress() will fail (result is an errorCode)\n* You can get the minimum value of dstMaxSize by using LizardF_compressBound()\n* The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.\n* The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.\n* The function outputs an error code if it fails (can be tested using LizardF_isError())\n*/\nsize_t LizardF_compressUpdate(LizardF_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_compressOptions_t* compressOptionsPtr)\n{\n    LizardF_compressOptions_t cOptionsNull;\n    LizardF_cctx_t* cctxPtr = (LizardF_cctx_t*)compressionContext;\n    size_t blockSize = cctxPtr->maxBlockSize;\n    const BYTE* srcPtr = (const BYTE*)srcBuffer;\n    const BYTE* const srcEnd = srcPtr + srcSize;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    LizardF_lastBlockStatus lastBlockCompressed = notDone;\n    compressFunc_t compress;\n\n\n    if (cctxPtr->cStage != 1) return (size_t)-LizardF_ERROR_GENERIC;\n    if (dstMaxSize < LizardF_compressBound(srcSize, &(cctxPtr->prefs))) return (size_t)-LizardF_ERROR_dstMaxSize_tooSmall;\n    memset(&cOptionsNull, 0, sizeof(cOptionsNull));\n    if (compressOptionsPtr == NULL) compressOptionsPtr = &cOptionsNull;\n\n    /* select compression function */\n    compress = LizardF_selectCompression(cctxPtr->prefs.frameInfo.blockMode);\n\n    /* complete tmp buffer */\n    if (cctxPtr->tmpInSize > 0) {   /* some data already within tmp buffer */\n        size_t sizeToCopy = blockSize - cctxPtr->tmpInSize;\n        if (sizeToCopy > srcSize) {\n            /* add src to tmpIn buffer */\n            memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, srcSize);\n            srcPtr = srcEnd;\n            cctxPtr->tmpInSize += srcSize;\n            /* still needs some CRC */\n        } else {\n            /* complete tmpIn block and then compress it */\n            lastBlockCompressed = fromTmpBuffer;\n            memcpy(cctxPtr->tmpIn + cctxPtr->tmpInSize, srcBuffer, sizeToCopy);\n            srcPtr += sizeToCopy;\n\n            dstPtr += LizardF_compressBlock(dstPtr, cctxPtr->tmpIn, blockSize, compress, cctxPtr->lizardCtxPtr, cctxPtr->prefs.compressionLevel);\n\n            if (cctxPtr->prefs.frameInfo.blockMode==LizardF_blockLinked) cctxPtr->tmpIn += blockSize;\n            cctxPtr->tmpInSize = 0;\n        }\n    }\n\n    while ((size_t)(srcEnd - srcPtr) >= blockSize) {\n        /* compress full block */\n        lastBlockCompressed = fromSrcBuffer;\n        dstPtr += LizardF_compressBlock(dstPtr, srcPtr, blockSize, compress, cctxPtr->lizardCtxPtr, cctxPtr->prefs.compressionLevel);\n        srcPtr += blockSize;\n    }\n\n    if ((cctxPtr->prefs.autoFlush) && (srcPtr < srcEnd)) {\n        /* compress remaining input < blockSize */\n        lastBlockCompressed = fromSrcBuffer;\n        dstPtr += LizardF_compressBlock(dstPtr, srcPtr, srcEnd - srcPtr, compress, cctxPtr->lizardCtxPtr, cctxPtr->prefs.compressionLevel);\n        srcPtr  = srcEnd;\n    }\n\n    /* preserve dictionary if necessary */\n    if ((cctxPtr->prefs.frameInfo.blockMode==LizardF_blockLinked) && (lastBlockCompressed==fromSrcBuffer)) {\n        if (compressOptionsPtr->stableSrc) {\n            cctxPtr->tmpIn = cctxPtr->tmpBuff;\n        } else {\n            int realDictSize = LizardF_localSaveDict(cctxPtr);\n            if (realDictSize==0) return (size_t)-LizardF_ERROR_GENERIC;\n            cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n        }\n    }\n\n    /* keep tmpIn within limits */\n    if ((cctxPtr->tmpIn + blockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)   /* necessarily LizardF_blockLinked && lastBlockCompressed==fromTmpBuffer */\n        && !(cctxPtr->prefs.autoFlush))\n    {\n        int realDictSize = LizardF_localSaveDict(cctxPtr);\n        cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n    }\n\n    /* some input data left, necessarily < blockSize */\n    if (srcPtr < srcEnd) {\n        /* fill tmp buffer */\n        size_t sizeToCopy = srcEnd - srcPtr;\n        memcpy(cctxPtr->tmpIn, srcPtr, sizeToCopy);\n        cctxPtr->tmpInSize = sizeToCopy;\n    }\n\n    if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LizardF_contentChecksumEnabled)\n        XXH32_update(&(cctxPtr->xxh), srcBuffer, srcSize);\n\n    cctxPtr->totalInSize += srcSize;\n    return dstPtr - dstStart;\n}\n\n\n/*! LizardF_flush() :\n* Should you need to create compressed data immediately, without waiting for a block to be filled,\n* you can call Lizard_flush(), which will immediately compress any remaining data stored within compressionContext.\n* The result of the function is the number of bytes written into dstBuffer\n* (it can be zero, this means there was no data left within compressionContext)\n* The function outputs an error code if it fails (can be tested using LizardF_isError())\n* The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.\n*/\nsize_t LizardF_flush(LizardF_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* compressOptionsPtr)\n{\n    LizardF_cctx_t* cctxPtr = (LizardF_cctx_t*)compressionContext;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    compressFunc_t compress;\n\n\n    if (cctxPtr->tmpInSize == 0) return 0;   /* nothing to flush */\n    if (cctxPtr->cStage != 1) return (size_t)-LizardF_ERROR_GENERIC;\n    if (dstMaxSize < (cctxPtr->tmpInSize + 8)) return (size_t)-LizardF_ERROR_dstMaxSize_tooSmall;   /* +8 : block header(4) + block checksum(4) */\n    (void)compressOptionsPtr;   /* not yet useful */\n\n    /* select compression function */\n    compress = LizardF_selectCompression(cctxPtr->prefs.frameInfo.blockMode);\n\n    /* compress tmp buffer */\n    dstPtr += LizardF_compressBlock(dstPtr, cctxPtr->tmpIn, cctxPtr->tmpInSize, compress, cctxPtr->lizardCtxPtr, cctxPtr->prefs.compressionLevel);\n    if (cctxPtr->prefs.frameInfo.blockMode==LizardF_blockLinked) cctxPtr->tmpIn += cctxPtr->tmpInSize;\n    cctxPtr->tmpInSize = 0;\n\n    /* keep tmpIn within limits */\n    if ((cctxPtr->tmpIn + cctxPtr->maxBlockSize) > (cctxPtr->tmpBuff + cctxPtr->maxBufferSize)) {  /* necessarily LizardF_blockLinked */\n        int realDictSize = LizardF_localSaveDict(cctxPtr);\n        cctxPtr->tmpIn = cctxPtr->tmpBuff + realDictSize;\n    }\n\n    return dstPtr - dstStart;\n}\n\n\n/*! LizardF_compressEnd() :\n* When you want to properly finish the compressed frame, just call LizardF_compressEnd().\n* It will flush whatever data remained within compressionContext (like Lizard_flush())\n* but also properly finalize the frame, with an endMark and a checksum.\n* The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark size))\n* The function outputs an error code if it fails (can be tested using LizardF_isError())\n* The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.\n* compressionContext can then be used again, starting with LizardF_compressBegin(). The preferences will remain the same.\n*/\nsize_t LizardF_compressEnd(LizardF_compressionContext_t compressionContext, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* compressOptionsPtr)\n{\n    LizardF_cctx_t* cctxPtr = (LizardF_cctx_t*)compressionContext;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* dstPtr = dstStart;\n    size_t errorCode;\n\n    errorCode = LizardF_flush(compressionContext, dstBuffer, dstMaxSize, compressOptionsPtr);\n    if (LizardF_isError(errorCode)) return errorCode;\n    dstPtr += errorCode;\n\n    LizardF_writeLE32(dstPtr, 0);\n    dstPtr+=4;   /* endMark */\n\n    if (cctxPtr->prefs.frameInfo.contentChecksumFlag == LizardF_contentChecksumEnabled) {\n        U32 xxh = XXH32_digest(&(cctxPtr->xxh));\n        LizardF_writeLE32(dstPtr, xxh);\n        dstPtr+=4;   /* content Checksum */\n    }\n\n    cctxPtr->cStage = 0;   /* state is now re-usable (with identical preferences) */\n    cctxPtr->maxBufferSize = 0;  /* reuse HC context */\n\n    if (cctxPtr->prefs.frameInfo.contentSize) {\n        if (cctxPtr->prefs.frameInfo.contentSize != cctxPtr->totalInSize)\n            return (size_t)-LizardF_ERROR_frameSize_wrong;\n    }\n\n    return dstPtr - dstStart;\n}\n\n\n/*-***************************************************\n*   Frame Decompression\n*****************************************************/\n\n/* Resource management */\n\n/*! LizardF_createDecompressionContext() :\n*   Create a decompressionContext object, which will track all decompression operations.\n*   Provides a pointer to a fully allocated and initialized LizardF_decompressionContext object.\n*   Object can later be released using LizardF_freeDecompressionContext().\n*   @return : if != 0, there was an error during context creation.\n*/\nLizardF_errorCode_t LizardF_createDecompressionContext(LizardF_decompressionContext_t* LizardF_decompressionContextPtr, unsigned versionNumber)\n{\n    LizardF_dctx_t* const dctxPtr = (LizardF_dctx_t*)ALLOCATOR(1, sizeof(LizardF_dctx_t));\n    if (dctxPtr==NULL) return (LizardF_errorCode_t)-LizardF_ERROR_GENERIC;\n\n    dctxPtr->version = versionNumber;\n    *LizardF_decompressionContextPtr = (LizardF_decompressionContext_t)dctxPtr;\n    return LizardF_OK_NoError;\n}\n\nLizardF_errorCode_t LizardF_freeDecompressionContext(LizardF_decompressionContext_t LizardF_decompressionContext)\n{\n    LizardF_errorCode_t result = LizardF_OK_NoError;\n    LizardF_dctx_t* const dctxPtr = (LizardF_dctx_t*)LizardF_decompressionContext;\n    if (dctxPtr != NULL) {   /* can accept NULL input, like free() */\n      result = (LizardF_errorCode_t)dctxPtr->dStage;\n      FREEMEM(dctxPtr->tmpIn);\n      FREEMEM(dctxPtr->tmpOutBuffer);\n      FREEMEM(dctxPtr);\n    }\n    return result;\n}\n\n\n/* ******************************************************************** */\n/* ********************* Decompression ******************************** */\n/* ******************************************************************** */\n\ntypedef enum { dstage_getHeader=0, dstage_storeHeader,\n    dstage_getCBlockSize, dstage_storeCBlockSize,\n    dstage_copyDirect,\n    dstage_getCBlock, dstage_storeCBlock,\n    dstage_decodeCBlock, dstage_decodeCBlock_intoDst,\n    dstage_decodeCBlock_intoTmp, dstage_flushOut,\n    dstage_getSuffix, dstage_storeSuffix,\n    dstage_getSFrameSize, dstage_storeSFrameSize,\n    dstage_skipSkippable\n} dStage_t;\n\n\n/*! LizardF_headerSize() :\n*   @return : size of frame header\n*             or an error code, which can be tested using LizardF_isError()\n*/\nstatic size_t LizardF_headerSize(const void* src, size_t srcSize)\n{\n    /* minimal srcSize to determine header size */\n    if (srcSize < 5) return (size_t)-LizardF_ERROR_frameHeader_incomplete;\n\n    /* special case : skippable frames */\n    if ((LizardF_readLE32(src) & 0xFFFFFFF0U) == LIZARDF_MAGIC_SKIPPABLE_START) return 8;\n\n    /* control magic number */\n    if (LizardF_readLE32(src) != LIZARDF_MAGICNUMBER) return (size_t)-LizardF_ERROR_frameType_unknown;\n\n    /* Frame Header Size */\n    {   BYTE const FLG = ((const BYTE*)src)[4];\n        U32 const contentSizeFlag = (FLG>>3) & _1BIT;\n        return contentSizeFlag ? maxFHSize : minFHSize;\n    }\n}\n\n\n/*! LizardF_decodeHeader() :\n   input   : `srcVoidPtr` points at the **beginning of the frame**\n   output  : set internal values of dctx, such as\n             dctxPtr->frameInfo and dctxPtr->dStage.\n             Also allocates internal buffers.\n   @return : nb Bytes read from srcVoidPtr (necessarily <= srcSize)\n             or an error code (testable with LizardF_isError())\n*/\nstatic size_t LizardF_decodeHeader(LizardF_dctx_t* dctxPtr, const void* srcVoidPtr, size_t srcSize)\n{\n    BYTE FLG, BD, HC;\n    unsigned version, blockMode, blockChecksumFlag, contentSizeFlag, contentChecksumFlag, blockSizeID;\n    size_t bufferNeeded, currentBlockSize;\n    size_t frameHeaderSize;\n    const BYTE* srcPtr = (const BYTE*)srcVoidPtr;\n\n    /* need to decode header to get frameInfo */\n    if (srcSize < minFHSize) return (size_t)-LizardF_ERROR_frameHeader_incomplete;   /* minimal frame header size */\n    memset(&(dctxPtr->frameInfo), 0, sizeof(dctxPtr->frameInfo));\n\n    /* special case : skippable frames */\n    if ((LizardF_readLE32(srcPtr) & 0xFFFFFFF0U) == LIZARDF_MAGIC_SKIPPABLE_START) {\n        dctxPtr->frameInfo.frameType = LizardF_skippableFrame;\n        if (srcVoidPtr == (void*)(dctxPtr->header)) {\n            dctxPtr->tmpInSize = srcSize;\n            dctxPtr->tmpInTarget = 8;\n            dctxPtr->dStage = dstage_storeSFrameSize;\n            return srcSize;\n        } else {\n            dctxPtr->dStage = dstage_getSFrameSize;\n            return 4;\n        }\n    }\n\n    /* control magic number */\n    if (LizardF_readLE32(srcPtr) != LIZARDF_MAGICNUMBER) return (size_t)-LizardF_ERROR_frameType_unknown;\n    dctxPtr->frameInfo.frameType = LizardF_frame;\n\n    /* Flags */\n    FLG = srcPtr[4];\n    version = (FLG>>6) & _2BITS;\n    blockMode = (FLG>>5) & _1BIT;\n    blockChecksumFlag = (FLG>>4) & _1BIT;\n    contentSizeFlag = (FLG>>3) & _1BIT;\n    contentChecksumFlag = (FLG>>2) & _1BIT;\n\n    /* Frame Header Size */\n    frameHeaderSize = contentSizeFlag ? maxFHSize : minFHSize;\n\n    if (srcSize < frameHeaderSize) {\n        /* not enough input to fully decode frame header */\n        if (srcPtr != dctxPtr->header)\n            memcpy(dctxPtr->header, srcPtr, srcSize);\n        dctxPtr->tmpInSize = srcSize;\n        dctxPtr->tmpInTarget = frameHeaderSize;\n        dctxPtr->dStage = dstage_storeHeader;\n        return srcSize;\n    }\n\n    BD = srcPtr[5];\n    blockSizeID = (BD>>4) & _3BITS;\n\n    /* validate */\n    if (version != 1) return (size_t)-LizardF_ERROR_headerVersion_wrong;        /* Version Number, only supported value */\n    if (blockChecksumFlag != 0) return (size_t)-LizardF_ERROR_blockChecksum_unsupported; /* Not supported for the time being */\n    if (((FLG>>0)&_2BITS) != 0) return (size_t)-LizardF_ERROR_reservedFlag_set; /* Reserved bits */\n    if (((BD>>7)&_1BIT) != 0) return (size_t)-LizardF_ERROR_reservedFlag_set;   /* Reserved bit */\n    if (blockSizeID < 1) return (size_t)-LizardF_ERROR_maxBlockSize_invalid;    /* 1-7 only supported values for the time being */\n    if (((BD>>0)&_4BITS) != 0) return (size_t)-LizardF_ERROR_reservedFlag_set;  /* Reserved bits */\n\n    /* check */\n    HC = LizardF_headerChecksum(srcPtr+4, frameHeaderSize-5);\n    if (HC != srcPtr[frameHeaderSize-1]) return (size_t)-LizardF_ERROR_headerChecksum_invalid;   /* Bad header checksum error */\n\n    /* save */\n    dctxPtr->frameInfo.blockMode = (LizardF_blockMode_t)blockMode;\n    dctxPtr->frameInfo.contentChecksumFlag = (LizardF_contentChecksum_t)contentChecksumFlag;\n    dctxPtr->frameInfo.blockSizeID = (LizardF_blockSizeID_t)blockSizeID;\n    currentBlockSize = dctxPtr->maxBlockSize;\n    dctxPtr->maxBlockSize = LizardF_getBlockSize(blockSizeID);\n    if (contentSizeFlag)\n        dctxPtr->frameRemainingSize = dctxPtr->frameInfo.contentSize = LizardF_readLE64(srcPtr+6);\n\n    /* init */\n    if (contentChecksumFlag) XXH32_reset(&(dctxPtr->xxh), 0);\n\n    /* alloc */\n    bufferNeeded = dctxPtr->maxBlockSize + ((dctxPtr->frameInfo.blockMode==LizardF_blockLinked) * 2 * LIZARD_DICT_SIZE);\n    if (bufferNeeded > dctxPtr->maxBufferSize || dctxPtr->maxBlockSize > currentBlockSize) {   /* tmp buffers too small */\n        FREEMEM(dctxPtr->tmpIn);\n        FREEMEM(dctxPtr->tmpOutBuffer);\n        dctxPtr->maxBufferSize = 0;\n        dctxPtr->tmpIn = (BYTE*)ALLOCATOR(1, dctxPtr->maxBlockSize);\n        if (dctxPtr->tmpIn == NULL) return (size_t)-LizardF_ERROR_GENERIC;\n        dctxPtr->tmpOutBuffer= (BYTE*)ALLOCATOR(1, bufferNeeded);\n        if (dctxPtr->tmpOutBuffer== NULL) return (size_t)-LizardF_ERROR_GENERIC;\n        dctxPtr->maxBufferSize = bufferNeeded;\n    }\n    dctxPtr->tmpInSize = 0;\n    dctxPtr->tmpInTarget = 0;\n    dctxPtr->dict = dctxPtr->tmpOutBuffer;\n    dctxPtr->dictSize = 0;\n    dctxPtr->tmpOut = dctxPtr->tmpOutBuffer;\n    dctxPtr->tmpOutStart = 0;\n    dctxPtr->tmpOutSize = 0;\n\n    dctxPtr->dStage = dstage_getCBlockSize;\n\n    return frameHeaderSize;\n}\n\n\n/*! LizardF_getFrameInfo() :\n*   Decodes frame header information, such as blockSize.\n*   It is optional : you could start by calling directly LizardF_decompress() instead.\n*   The objective is to extract header information without starting decompression, typically for allocation purposes.\n*   LizardF_getFrameInfo() can also be used *after* starting decompression, on a valid LizardF_decompressionContext_t.\n*   The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).\n*   You are expected to resume decompression from where it stopped (srcBuffer + *srcSizePtr)\n*   @return : hint of the better `srcSize` to use for next call to LizardF_decompress,\n*             or an error code which can be tested using LizardF_isError().\n*/\nLizardF_errorCode_t LizardF_getFrameInfo(LizardF_decompressionContext_t dCtx, LizardF_frameInfo_t* frameInfoPtr,\n                                   const void* srcBuffer, size_t* srcSizePtr)\n{\n    LizardF_dctx_t* dctxPtr = (LizardF_dctx_t*)dCtx;\n\n    if (dctxPtr->dStage > dstage_storeHeader) {  /* note : requires dstage_* header related to be at beginning of enum */\n        /* frameInfo already decoded */\n        size_t o=0, i=0;\n        *srcSizePtr = 0;\n        *frameInfoPtr = dctxPtr->frameInfo;\n        return LizardF_decompress(dCtx, NULL, &o, NULL, &i, NULL);  /* returns : recommended nb of bytes for LizardF_decompress() */\n    } else {\n        size_t nextSrcSize, o=0;\n        size_t const hSize = LizardF_headerSize(srcBuffer, *srcSizePtr);\n        if (LizardF_isError(hSize)) { *srcSizePtr=0; return hSize; }\n        if (*srcSizePtr < hSize) { *srcSizePtr=0; return (size_t)-LizardF_ERROR_frameHeader_incomplete; }\n\n        *srcSizePtr = hSize;\n        nextSrcSize = LizardF_decompress(dCtx, NULL, &o, srcBuffer, srcSizePtr, NULL);\n        if (dctxPtr->dStage <= dstage_storeHeader) return (size_t)-LizardF_ERROR_frameHeader_incomplete; /* should not happen, already checked */\n        *frameInfoPtr = dctxPtr->frameInfo;\n        return nextSrcSize;\n    }\n}\n\n\n/* trivial redirector, for common prototype */\nstatic int LizardF_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize)\n{\n    (void)dictStart; (void)dictSize;\n    return Lizard_decompress_safe (source, dest, compressedSize, maxDecompressedSize);\n}\n\n\nstatic void LizardF_updateDict(LizardF_dctx_t* dctxPtr, const BYTE* dstPtr, size_t dstSize, const BYTE* dstPtr0, unsigned withinTmp)\n{\n    if (dctxPtr->dictSize==0)\n        dctxPtr->dict = (const BYTE*)dstPtr;   /* priority to dictionary continuity */\n\n    if (dctxPtr->dict + dctxPtr->dictSize == dstPtr) {  /* dictionary continuity */\n        dctxPtr->dictSize += dstSize;\n        return;\n    }\n\n    if (dstPtr - dstPtr0 + dstSize >= LIZARD_DICT_SIZE) {  /* dstBuffer large enough to become dictionary */\n        dctxPtr->dict = (const BYTE*)dstPtr0;\n        dctxPtr->dictSize = dstPtr - dstPtr0 + dstSize;\n        return;\n    }\n\n    if ((withinTmp) && (dctxPtr->dict == dctxPtr->tmpOutBuffer)) {\n        /* assumption : dctxPtr->dict + dctxPtr->dictSize == dctxPtr->tmpOut + dctxPtr->tmpOutStart */\n        dctxPtr->dictSize += dstSize;\n        return;\n    }\n\n    if (withinTmp) { /* copy relevant dict portion in front of tmpOut within tmpOutBuffer */\n        size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;\n        size_t copySize = LIZARD_DICT_SIZE - dctxPtr->tmpOutSize;\n        const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;\n        if (dctxPtr->tmpOutSize > LIZARD_DICT_SIZE) copySize = 0;\n        if (copySize > preserveSize) copySize = preserveSize;\n\n        memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);\n\n        dctxPtr->dict = dctxPtr->tmpOutBuffer;\n        dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart + dstSize;\n        return;\n    }\n\n    if (dctxPtr->dict == dctxPtr->tmpOutBuffer) {    /* copy dst into tmp to complete dict */\n        if (dctxPtr->dictSize + dstSize > dctxPtr->maxBufferSize) {  /* tmp buffer not large enough */\n            size_t preserveSize = LIZARD_DICT_SIZE - dstSize;   /* note : dstSize < LIZARD_DICT_SIZE */\n            memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);\n            dctxPtr->dictSize = preserveSize;\n        }\n        memcpy(dctxPtr->tmpOutBuffer + dctxPtr->dictSize, dstPtr, dstSize);\n        dctxPtr->dictSize += dstSize;\n        return;\n    }\n\n    /* join dict & dest into tmp */\n    {   size_t preserveSize = LIZARD_DICT_SIZE - dstSize;   /* note : dstSize < LIZARD_DICT_SIZE */\n        if (preserveSize > dctxPtr->dictSize) preserveSize = dctxPtr->dictSize;\n        memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - preserveSize, preserveSize);\n        memcpy(dctxPtr->tmpOutBuffer + preserveSize, dstPtr, dstSize);\n        dctxPtr->dict = dctxPtr->tmpOutBuffer;\n        dctxPtr->dictSize = preserveSize + dstSize;\n    }\n}\n\n\n\n/*! LizardF_decompress() :\n* Call this function repetitively to regenerate data compressed within srcBuffer.\n* The function will attempt to decode *srcSizePtr from srcBuffer, into dstBuffer of maximum size *dstSizePtr.\n*\n* The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).\n*\n* The number of bytes effectively read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).\n* If the number of bytes read is < number of bytes provided, then the decompression operation is not complete.\n* You will have to call it again, continuing from where it stopped.\n*\n* The function result is an hint of the better srcSize to use for next call to LizardF_decompress.\n* Basically, it's the size of the current (or remaining) compressed block + header of next block.\n* Respecting the hint provides some boost to performance, since it allows less buffer shuffling.\n* Note that this is just a hint, you can always provide any srcSize you want.\n* When a frame is fully decoded, the function result will be 0.\n* If decompression failed, function result is an error code which can be tested using LizardF_isError().\n*/\nsize_t LizardF_decompress(LizardF_decompressionContext_t decompressionContext,\n                       void* dstBuffer, size_t* dstSizePtr,\n                       const void* srcBuffer, size_t* srcSizePtr,\n                       const LizardF_decompressOptions_t* decompressOptionsPtr)\n{\n    LizardF_dctx_t* dctxPtr = (LizardF_dctx_t*)decompressionContext;\n    LizardF_decompressOptions_t optionsNull;\n    const BYTE* const srcStart = (const BYTE*)srcBuffer;\n    const BYTE* const srcEnd = srcStart + *srcSizePtr;\n    const BYTE* srcPtr = srcStart;\n    BYTE* const dstStart = (BYTE*)dstBuffer;\n    BYTE* const dstEnd = dstStart + *dstSizePtr;\n    BYTE* dstPtr = dstStart;\n    const BYTE* selectedIn = NULL;\n    unsigned doAnotherStage = 1;\n    size_t nextSrcSizeHint = 1;\n\n\n    memset(&optionsNull, 0, sizeof(optionsNull));\n    if (decompressOptionsPtr==NULL) decompressOptionsPtr = &optionsNull;\n    *srcSizePtr = 0;\n    *dstSizePtr = 0;\n\n    /* expect to continue decoding src buffer where it left previously */\n    if (dctxPtr->srcExpect != NULL) {\n        if (srcStart != dctxPtr->srcExpect) return (size_t)-LizardF_ERROR_srcPtr_wrong;\n    }\n\n    /* programmed as a state machine */\n\n    while (doAnotherStage) {\n\n        switch(dctxPtr->dStage)\n        {\n\n        case dstage_getHeader:\n            if ((size_t)(srcEnd-srcPtr) >= maxFHSize) {  /* enough to decode - shortcut */\n                LizardF_errorCode_t const hSize = LizardF_decodeHeader(dctxPtr, srcPtr, srcEnd-srcPtr);\n                if (LizardF_isError(hSize)) return hSize;\n                srcPtr += hSize;\n                break;\n            }\n            dctxPtr->tmpInSize = 0;\n            dctxPtr->tmpInTarget = minFHSize;   /* minimum to attempt decode */\n            dctxPtr->dStage = dstage_storeHeader;\n            /* fallthrough */\n\n        case dstage_storeHeader:\n            {   size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy =  srcEnd - srcPtr;\n                memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                dctxPtr->tmpInSize += sizeToCopy;\n                srcPtr += sizeToCopy;\n                if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) {\n                    nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize;   /* rest of header + nextBlockHeader */\n                    doAnotherStage = 0;   /* not enough src data, ask for some more */\n                    break;\n                }\n                {   LizardF_errorCode_t const hSize = LizardF_decodeHeader(dctxPtr, dctxPtr->header, dctxPtr->tmpInTarget);\n                    if (LizardF_isError(hSize)) return hSize;\n                }\n                break;\n            }\n\n        case dstage_getCBlockSize:\n            if ((size_t)(srcEnd - srcPtr) >= BHSize) {\n                selectedIn = srcPtr;\n                srcPtr += BHSize;\n            } else {\n                /* not enough input to read cBlockSize field */\n                dctxPtr->tmpInSize = 0;\n                dctxPtr->dStage = dstage_storeCBlockSize;\n            }\n\n            if (dctxPtr->dStage == dstage_storeCBlockSize)   /* can be skipped */\n        case dstage_storeCBlockSize:\n            {\n                size_t sizeToCopy = BHSize - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;\n                memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctxPtr->tmpInSize += sizeToCopy;\n                if (dctxPtr->tmpInSize < BHSize) {   /* not enough input to get full cBlockSize; wait for more */\n                    nextSrcSizeHint = BHSize - dctxPtr->tmpInSize;\n                    doAnotherStage  = 0;\n                    break;\n                }\n                selectedIn = dctxPtr->tmpIn;\n            }\n\n        /* case dstage_decodeCBlockSize: */   /* no more direct access, to prevent scan-build warning */\n            {   size_t const nextCBlockSize = LizardF_readLE32(selectedIn) & 0x7FFFFFFFU;\n                if (nextCBlockSize==0) {  /* frameEnd signal, no more CBlock */\n                    dctxPtr->dStage = dstage_getSuffix;\n                    break;\n                }\n                if (nextCBlockSize > dctxPtr->maxBlockSize) return (size_t)-LizardF_ERROR_GENERIC;   /* invalid cBlockSize */\n                dctxPtr->tmpInTarget = nextCBlockSize;\n                if (LizardF_readLE32(selectedIn) & LIZARDF_BLOCKUNCOMPRESSED_FLAG) {\n                    dctxPtr->dStage = dstage_copyDirect;\n                    break;\n                }\n                dctxPtr->dStage = dstage_getCBlock;\n                if (dstPtr==dstEnd) {\n                    nextSrcSizeHint = nextCBlockSize + BHSize;\n                    doAnotherStage = 0;\n                }\n                break;\n            }\n\n        case dstage_copyDirect:   /* uncompressed block */\n            {   size_t sizeToCopy = dctxPtr->tmpInTarget;\n                if ((size_t)(srcEnd-srcPtr) < sizeToCopy) sizeToCopy = srcEnd - srcPtr;  /* not enough input to read full block */\n                if ((size_t)(dstEnd-dstPtr) < sizeToCopy) sizeToCopy = dstEnd - dstPtr;\n                memcpy(dstPtr, srcPtr, sizeToCopy);\n                if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), srcPtr, sizeToCopy);\n                if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= sizeToCopy;\n\n                /* dictionary management */\n                if (dctxPtr->frameInfo.blockMode==LizardF_blockLinked)\n                    LizardF_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 0);\n\n                srcPtr += sizeToCopy;\n                dstPtr += sizeToCopy;\n                if (sizeToCopy == dctxPtr->tmpInTarget) {  /* all copied */\n                    dctxPtr->dStage = dstage_getCBlockSize;\n                    break;\n                }\n                dctxPtr->tmpInTarget -= sizeToCopy;   /* still need to copy more */\n                nextSrcSizeHint = dctxPtr->tmpInTarget + BHSize;\n                doAnotherStage = 0;\n                break;\n            }\n\n        case dstage_getCBlock:   /* entry from dstage_decodeCBlockSize */\n            if ((size_t)(srcEnd-srcPtr) < dctxPtr->tmpInTarget) {\n                dctxPtr->tmpInSize = 0;\n                dctxPtr->dStage = dstage_storeCBlock;\n                break;\n            }\n            selectedIn = srcPtr;\n            srcPtr += dctxPtr->tmpInTarget;\n            dctxPtr->dStage = dstage_decodeCBlock;\n            break;\n\n        case dstage_storeCBlock:\n            {   size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd-srcPtr)) sizeToCopy = srcEnd-srcPtr;\n                memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                dctxPtr->tmpInSize += sizeToCopy;\n                srcPtr += sizeToCopy;\n                if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) { /* need more input */\n                    nextSrcSizeHint = (dctxPtr->tmpInTarget - dctxPtr->tmpInSize) + BHSize;\n                    doAnotherStage=0;\n                    break;\n                }\n                selectedIn = dctxPtr->tmpIn;\n                dctxPtr->dStage = dstage_decodeCBlock;\n            }\n            /* fallthrough */\n\n        case dstage_decodeCBlock:\n            if ((size_t)(dstEnd-dstPtr) < dctxPtr->maxBlockSize)   /* not enough place into dst : decode into tmpOut */\n                dctxPtr->dStage = dstage_decodeCBlock_intoTmp;\n            else\n                dctxPtr->dStage = dstage_decodeCBlock_intoDst;\n            break;\n\n        case dstage_decodeCBlock_intoDst:\n            {   int (*decoder)(const char*, char*, int, int, const char*, int);\n                int decodedSize;\n\n                if (dctxPtr->frameInfo.blockMode == LizardF_blockLinked)\n                    decoder = Lizard_decompress_safe_usingDict;\n                else\n                    decoder = LizardF_decompress_safe;\n\n                decodedSize = decoder((const char*)selectedIn, (char*)dstPtr, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);\n                if (decodedSize < 0) return (size_t)-LizardF_ERROR_GENERIC;   /* decompression failed */\n                if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dstPtr, decodedSize);\n                if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;\n\n                /* dictionary management */\n                if (dctxPtr->frameInfo.blockMode==LizardF_blockLinked)\n                    LizardF_updateDict(dctxPtr, dstPtr, decodedSize, dstStart, 0);\n\n                dstPtr += decodedSize;\n                dctxPtr->dStage = dstage_getCBlockSize;\n                break;\n            }\n\n        case dstage_decodeCBlock_intoTmp:\n            /* not enough place into dst : decode into tmpOut */\n            {   int (*decoder)(const char*, char*, int, int, const char*, int);\n                int decodedSize;\n\n                if (dctxPtr->frameInfo.blockMode == LizardF_blockLinked)\n                    decoder = Lizard_decompress_safe_usingDict;\n                else\n                    decoder = LizardF_decompress_safe;\n\n                /* ensure enough place for tmpOut */\n                if (dctxPtr->frameInfo.blockMode == LizardF_blockLinked) {\n                    if (dctxPtr->dict == dctxPtr->tmpOutBuffer) {\n                        if (dctxPtr->dictSize > 2 * LIZARD_DICT_SIZE) {\n                            memcpy(dctxPtr->tmpOutBuffer, dctxPtr->dict + dctxPtr->dictSize - LIZARD_DICT_SIZE, LIZARD_DICT_SIZE);\n                            dctxPtr->dictSize = LIZARD_DICT_SIZE;\n                        }\n                        dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + dctxPtr->dictSize;\n                    } else {  /* dict not within tmp */\n                        size_t reservedDictSpace = dctxPtr->dictSize;\n                        if (reservedDictSpace > LIZARD_DICT_SIZE) reservedDictSpace = LIZARD_DICT_SIZE;\n                        dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + reservedDictSpace;\n                    }\n                }\n\n                /* Decode */\n                decodedSize = decoder((const char*)selectedIn, (char*)dctxPtr->tmpOut, (int)dctxPtr->tmpInTarget, (int)dctxPtr->maxBlockSize, (const char*)dctxPtr->dict, (int)dctxPtr->dictSize);\n                if (decodedSize < 0) return (size_t)-LizardF_ERROR_decompressionFailed;   /* decompression failed */\n                if (dctxPtr->frameInfo.contentChecksumFlag) XXH32_update(&(dctxPtr->xxh), dctxPtr->tmpOut, decodedSize);\n                if (dctxPtr->frameInfo.contentSize) dctxPtr->frameRemainingSize -= decodedSize;\n                dctxPtr->tmpOutSize = decodedSize;\n                dctxPtr->tmpOutStart = 0;\n                dctxPtr->dStage = dstage_flushOut;\n                break;\n            }\n\n        case dstage_flushOut:  /* flush decoded data from tmpOut to dstBuffer */\n            {   size_t sizeToCopy = dctxPtr->tmpOutSize - dctxPtr->tmpOutStart;\n                if (sizeToCopy > (size_t)(dstEnd-dstPtr)) sizeToCopy = dstEnd-dstPtr;\n                memcpy(dstPtr, dctxPtr->tmpOut + dctxPtr->tmpOutStart, sizeToCopy);\n\n                /* dictionary management */\n                if (dctxPtr->frameInfo.blockMode==LizardF_blockLinked)\n                    LizardF_updateDict(dctxPtr, dstPtr, sizeToCopy, dstStart, 1);\n\n                dctxPtr->tmpOutStart += sizeToCopy;\n                dstPtr += sizeToCopy;\n\n                /* end of flush ? */\n                if (dctxPtr->tmpOutStart == dctxPtr->tmpOutSize) {\n                    dctxPtr->dStage = dstage_getCBlockSize;\n                    break;\n                }\n                nextSrcSizeHint = BHSize;\n                doAnotherStage = 0;   /* still some data to flush */\n                break;\n            }\n\n        case dstage_getSuffix:\n            {   size_t const suffixSize = dctxPtr->frameInfo.contentChecksumFlag * 4;\n                if (dctxPtr->frameRemainingSize) return (size_t)-LizardF_ERROR_frameSize_wrong;   /* incorrect frame size decoded */\n                if (suffixSize == 0) {  /* frame completed */\n                    nextSrcSizeHint = 0;\n                    dctxPtr->dStage = dstage_getHeader;\n                    doAnotherStage = 0;\n                    break;\n                }\n                if ((srcEnd - srcPtr) < 4) {  /* not enough size for entire CRC */\n                    dctxPtr->tmpInSize = 0;\n                    dctxPtr->dStage = dstage_storeSuffix;\n                } else {\n                    selectedIn = srcPtr;\n                    srcPtr += 4;\n                }\n            }\n\n            if (dctxPtr->dStage == dstage_storeSuffix)   /* can be skipped */\n        case dstage_storeSuffix:\n            {\n                size_t sizeToCopy = 4 - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;\n                memcpy(dctxPtr->tmpIn + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctxPtr->tmpInSize += sizeToCopy;\n                if (dctxPtr->tmpInSize < 4) { /* not enough input to read complete suffix */\n                    nextSrcSizeHint = 4 - dctxPtr->tmpInSize;\n                    doAnotherStage=0;\n                    break;\n                }\n                selectedIn = dctxPtr->tmpIn;\n            }\n\n        /* case dstage_checkSuffix: */   /* no direct call, to avoid scan-build warning */\n            {   U32 const readCRC = LizardF_readLE32(selectedIn);\n                U32 const resultCRC = XXH32_digest(&(dctxPtr->xxh));\n                if (readCRC != resultCRC) return (size_t)-LizardF_ERROR_contentChecksum_invalid;\n                nextSrcSizeHint = 0;\n                dctxPtr->dStage = dstage_getHeader;\n                doAnotherStage = 0;\n                break;\n            }\n\n        case dstage_getSFrameSize:\n            if ((srcEnd - srcPtr) >= 4) {\n                selectedIn = srcPtr;\n                srcPtr += 4;\n            } else {\n                /* not enough input to read cBlockSize field */\n                dctxPtr->tmpInSize = 4;\n                dctxPtr->tmpInTarget = 8;\n                dctxPtr->dStage = dstage_storeSFrameSize;\n            }\n\n            if (dctxPtr->dStage == dstage_storeSFrameSize)\n        case dstage_storeSFrameSize:\n            {\n                size_t sizeToCopy = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                if (sizeToCopy > (size_t)(srcEnd - srcPtr)) sizeToCopy = srcEnd - srcPtr;\n                memcpy(dctxPtr->header + dctxPtr->tmpInSize, srcPtr, sizeToCopy);\n                srcPtr += sizeToCopy;\n                dctxPtr->tmpInSize += sizeToCopy;\n                if (dctxPtr->tmpInSize < dctxPtr->tmpInTarget) { /* not enough input to get full sBlockSize; wait for more */\n                    nextSrcSizeHint = dctxPtr->tmpInTarget - dctxPtr->tmpInSize;\n                    doAnotherStage = 0;\n                    break;\n                }\n                selectedIn = dctxPtr->header + 4;\n            }\n\n        /* case dstage_decodeSFrameSize: */   /* no direct access */\n            {   size_t const SFrameSize = LizardF_readLE32(selectedIn);\n                dctxPtr->frameInfo.contentSize = SFrameSize;\n                dctxPtr->tmpInTarget = SFrameSize;\n                dctxPtr->dStage = dstage_skipSkippable;\n                break;\n            }\n\n        case dstage_skipSkippable:\n            {   size_t skipSize = dctxPtr->tmpInTarget;\n                if (skipSize > (size_t)(srcEnd-srcPtr)) skipSize = srcEnd-srcPtr;\n                srcPtr += skipSize;\n                dctxPtr->tmpInTarget -= skipSize;\n                doAnotherStage = 0;\n                nextSrcSizeHint = dctxPtr->tmpInTarget;\n                if (nextSrcSizeHint) break;\n                dctxPtr->dStage = dstage_getHeader;\n                break;\n            }\n        }\n    }\n\n    /* preserve dictionary within tmp if necessary */\n    if ( (dctxPtr->frameInfo.blockMode==LizardF_blockLinked)\n        &&(dctxPtr->dict != dctxPtr->tmpOutBuffer)\n        &&(!decompressOptionsPtr->stableDst)\n        &&((unsigned)(dctxPtr->dStage-1) < (unsigned)(dstage_getSuffix-1))\n        )\n    {\n        if (dctxPtr->dStage == dstage_flushOut) {\n            size_t preserveSize = dctxPtr->tmpOut - dctxPtr->tmpOutBuffer;\n            size_t copySize = LIZARD_DICT_SIZE - dctxPtr->tmpOutSize;\n            const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize - dctxPtr->tmpOutStart;\n            if (dctxPtr->tmpOutSize > LIZARD_DICT_SIZE) copySize = 0;\n            if (copySize > preserveSize) copySize = preserveSize;\n\n            memcpy(dctxPtr->tmpOutBuffer + preserveSize - copySize, oldDictEnd - copySize, copySize);\n\n            dctxPtr->dict = dctxPtr->tmpOutBuffer;\n            dctxPtr->dictSize = preserveSize + dctxPtr->tmpOutStart;\n        } else {\n            size_t newDictSize = dctxPtr->dictSize;\n            const BYTE* oldDictEnd = dctxPtr->dict + dctxPtr->dictSize;\n            if ((newDictSize) > LIZARD_DICT_SIZE) newDictSize = LIZARD_DICT_SIZE;\n\n            memcpy(dctxPtr->tmpOutBuffer, oldDictEnd - newDictSize, newDictSize);\n\n            dctxPtr->dict = dctxPtr->tmpOutBuffer;\n            dctxPtr->dictSize = newDictSize;\n            dctxPtr->tmpOut = dctxPtr->tmpOutBuffer + newDictSize;\n        }\n    }\n\n    /* require function to be called again from position where it stopped */\n    if (srcPtr<srcEnd)\n        dctxPtr->srcExpect = srcPtr;\n    else\n        dctxPtr->srcExpect = NULL;\n\n    *srcSizePtr = (srcPtr - srcStart);\n    *dstSizePtr = (dstPtr - dstStart);\n    return nextSrcSizeHint;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_frame.h",
    "content": "﻿/*\n   Lizard auto-framing library\n   Header File\n   Copyright (C) 2011-2015, Yann Collet\n   Copyright (C) 2016-2017, Przemyslaw Skibinski\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Lizard source repository : https://github.com/inikep/lizard\n*/\n\n/* LizardF is a stand-alone API to create Lizard-compressed frames\n * conformant with specification v1.5.1.\n * All related operations, including memory management, are handled internally by the library.\n * You don't need lizard_compress.h when using lizard_frame.h.\n * */\n\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-************************************\n*  Includes\n**************************************/\n#include <stddef.h>   /* size_t */\n\n\n/*-************************************\n*  Error management\n**************************************/\ntypedef size_t LizardF_errorCode_t;\n\nunsigned    LizardF_isError(LizardF_errorCode_t code);\nconst char* LizardF_getErrorName(LizardF_errorCode_t code);   /* return error code string; useful for debugging */\n\n\n/*-************************************\n*  Frame compression types\n**************************************/\n//#define LIZARDF_DISABLE_OBSOLETE_ENUMS\n#ifndef LIZARDF_DISABLE_OBSOLETE_ENUMS\n#  define LIZARDF_OBSOLETE_ENUM(x) ,x\n#else\n#  define LIZARDF_OBSOLETE_ENUM(x)\n#endif\n\ntypedef enum {\n    LizardF_default=0,\n    LizardF_max128KB=1,\n    LizardF_max256KB=2,\n    LizardF_max1MB=3,\n    LizardF_max4MB=4,\n    LizardF_max16MB=5,\n    LizardF_max64MB=6,\n    LizardF_max256MB=7\n} LizardF_blockSizeID_t;\n\ntypedef enum {\n    LizardF_blockLinked=0,\n    LizardF_blockIndependent\n    LIZARDF_OBSOLETE_ENUM(blockLinked = LizardF_blockLinked)\n    LIZARDF_OBSOLETE_ENUM(blockIndependent = LizardF_blockIndependent)\n} LizardF_blockMode_t;\n\ntypedef enum {\n    LizardF_noContentChecksum=0,\n    LizardF_contentChecksumEnabled\n    LIZARDF_OBSOLETE_ENUM(noContentChecksum = LizardF_noContentChecksum)\n    LIZARDF_OBSOLETE_ENUM(contentChecksumEnabled = LizardF_contentChecksumEnabled)\n} LizardF_contentChecksum_t;\n\ntypedef enum {\n    LizardF_frame=0,\n    LizardF_skippableFrame\n    LIZARDF_OBSOLETE_ENUM(skippableFrame = LizardF_skippableFrame)\n} LizardF_frameType_t;\n\n#ifndef LIZARDF_DISABLE_OBSOLETE_ENUMS\ntypedef LizardF_blockSizeID_t blockSizeID_t;\ntypedef LizardF_blockMode_t blockMode_t;\ntypedef LizardF_frameType_t frameType_t;\ntypedef LizardF_contentChecksum_t contentChecksum_t;\n#endif\n\ntypedef struct {\n  LizardF_blockSizeID_t     blockSizeID;           /* max64KB, max256KB, max1MB, max4MB ; 0 == default */\n  LizardF_blockMode_t       blockMode;             /* blockLinked, blockIndependent ; 0 == default */\n  LizardF_contentChecksum_t contentChecksumFlag;   /* noContentChecksum, contentChecksumEnabled ; 0 == default  */\n  LizardF_frameType_t       frameType;             /* LizardF_frame, skippableFrame ; 0 == default */\n  unsigned long long     contentSize;           /* Size of uncompressed (original) content ; 0 == unknown */\n  unsigned               reserved[2];           /* must be zero for forward compatibility */\n} LizardF_frameInfo_t;\n\ntypedef struct {\n  LizardF_frameInfo_t frameInfo;\n  int      compressionLevel;       /* 0 == default (fast mode); values above 16 count as 16; values below 0 count as 0 */\n  unsigned autoFlush;              /* 1 == always flush (reduce need for tmp buffer) */\n  unsigned reserved[4];            /* must be zero for forward compatibility */\n} LizardF_preferences_t;\n\n\n/*-*********************************\n*  Simple compression function\n***********************************/\nsize_t LizardF_compressFrameBound(size_t srcSize, const LizardF_preferences_t* preferencesPtr);\n\n/*!LizardF_compressFrame() :\n * Compress an entire srcBuffer into a valid Lizard frame, as defined by specification v1.5.1\n * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n * You can get the minimum value of dstMaxSize by using LizardF_compressFrameBound()\n * If this condition is not respected, LizardF_compressFrame() will fail (result is an errorCode)\n * The LizardF_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.\n * The result of the function is the number of bytes written into dstBuffer.\n * The function outputs an error code if it fails (can be tested using LizardF_isError())\n */\nsize_t LizardF_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_preferences_t* preferencesPtr);\n\n\n\n/*-***********************************\n*  Advanced compression functions\n*************************************/\ntypedef struct LizardF_cctx_s* LizardF_compressionContext_t;   /* must be aligned on 8-bytes */\n\ntypedef struct {\n  unsigned stableSrc;    /* 1 == src content will remain available on future calls to LizardF_compress(); avoid saving src content within tmp buffer as future dictionary */\n  unsigned reserved[3];\n} LizardF_compressOptions_t;\n\n/* Resource Management */\n\n#define LIZARDF_VERSION 100\nLizardF_errorCode_t LizardF_createCompressionContext(LizardF_compressionContext_t* cctxPtr, unsigned version);\nLizardF_errorCode_t LizardF_freeCompressionContext(LizardF_compressionContext_t cctx);\n/* LizardF_createCompressionContext() :\n * The first thing to do is to create a compressionContext object, which will be used in all compression operations.\n * This is achieved using LizardF_createCompressionContext(), which takes as argument a version and an LizardF_preferences_t structure.\n * The version provided MUST be LIZARDF_VERSION. It is intended to track potential version differences between different binaries.\n * The function will provide a pointer to a fully allocated LizardF_compressionContext_t object.\n * If the result LizardF_errorCode_t is not zero, there was an error during context creation.\n * Object can release its memory using LizardF_freeCompressionContext();\n */\n\n\n/* Compression */\n\nsize_t LizardF_compressBegin(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_preferences_t* prefsPtr);\n/* LizardF_compressBegin() :\n * will write the frame header into dstBuffer.\n * dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.\n * The LizardF_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default.\n * The result of the function is the number of bytes written into dstBuffer for the header\n * or an error code (can be tested using LizardF_isError())\n */\n\nsize_t LizardF_compressBound(size_t srcSize, const LizardF_preferences_t* prefsPtr);\n/* LizardF_compressBound() :\n * Provides the minimum size of Dst buffer given srcSize to handle worst case situations.\n * Different preferences can produce different results.\n * prefsPtr is optional : you can provide NULL as argument, all preferences will then be set to cover worst case.\n * This function includes frame termination cost (4 bytes, or 8 if frame checksum is enabled)\n */\n\nsize_t LizardF_compressUpdate(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LizardF_compressOptions_t* cOptPtr);\n/* LizardF_compressUpdate()\n * LizardF_compressUpdate() can be called repetitively to compress as much data as necessary.\n * The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.\n * You can get the minimum value of dstMaxSize by using LizardF_compressBound().\n * If this condition is not respected, LizardF_compress() will fail (result is an errorCode).\n * LizardF_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.\n * The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.\n * The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.\n * The function outputs an error code if it fails (can be tested using LizardF_isError())\n */\n\nsize_t LizardF_flush(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* cOptPtr);\n/* LizardF_flush()\n * Should you need to generate compressed data immediately, without waiting for the current block to be filled,\n * you can call Lizard_flush(), which will immediately compress any remaining data buffered within cctx.\n * Note that dstMaxSize must be large enough to ensure the operation will be successful.\n * LizardF_compressOptions_t structure is optional : you can provide NULL as argument.\n * The result of the function is the number of bytes written into dstBuffer\n * (it can be zero, this means there was no data left within cctx)\n * The function outputs an error code if it fails (can be tested using LizardF_isError())\n */\n\nsize_t LizardF_compressEnd(LizardF_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LizardF_compressOptions_t* cOptPtr);\n/* LizardF_compressEnd()\n * When you want to properly finish the compressed frame, just call LizardF_compressEnd().\n * It will flush whatever data remained within compressionContext (like Lizard_flush())\n * but also properly finalize the frame, with an endMark and a checksum.\n * The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark), or 8 if optional frame checksum is enabled)\n * The function outputs an error code if it fails (can be tested using LizardF_isError())\n * The LizardF_compressOptions_t structure is optional : you can provide NULL as argument.\n * A successful call to LizardF_compressEnd() makes cctx available again for next compression task.\n */\n\n\n/*-*********************************\n*  Decompression functions\n***********************************/\n\ntypedef struct LizardF_dctx_s* LizardF_decompressionContext_t;   /* must be aligned on 8-bytes */\n\ntypedef struct {\n  unsigned stableDst;       /* guarantee that decompressed data will still be there on next function calls (avoid storage into tmp buffers) */\n  unsigned reserved[3];\n} LizardF_decompressOptions_t;\n\n\n/* Resource management */\n\n/*!LizardF_createDecompressionContext() :\n * Create an LizardF_decompressionContext_t object, which will be used to track all decompression operations.\n * The version provided MUST be LIZARDF_VERSION. It is intended to track potential breaking differences between different versions.\n * The function will provide a pointer to a fully allocated and initialized LizardF_decompressionContext_t object.\n * The result is an errorCode, which can be tested using LizardF_isError().\n * dctx memory can be released using LizardF_freeDecompressionContext();\n * The result of LizardF_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.\n * That is, it should be == 0 if decompression has been completed fully and correctly.\n */\nLizardF_errorCode_t LizardF_createDecompressionContext(LizardF_decompressionContext_t* dctxPtr, unsigned version);\nLizardF_errorCode_t LizardF_freeDecompressionContext(LizardF_decompressionContext_t dctx);\n\n\n/*======   Decompression   ======*/\n\n/*!LizardF_getFrameInfo() :\n * This function decodes frame header information (such as max blockSize, frame checksum, etc.).\n * Its usage is optional. The objective is to extract frame header information, typically for allocation purposes.\n * A header size is variable and can be from 7 to 15 bytes. It's also possible to input more bytes than that.\n * The number of bytes read from srcBuffer will be updated within *srcSizePtr (necessarily <= original value).\n * (note that LizardF_getFrameInfo() can also be used anytime *after* starting decompression, in this case 0 input byte is enough)\n * Frame header info is *copied into* an already allocated LizardF_frameInfo_t structure.\n * The function result is an hint about how many srcSize bytes LizardF_decompress() expects for next call,\n *                        or an error code which can be tested using LizardF_isError()\n *                        (typically, when there is not enough src bytes to fully decode the frame header)\n * Decompression is expected to resume from where it stopped (srcBuffer + *srcSizePtr)\n */\nsize_t LizardF_getFrameInfo(LizardF_decompressionContext_t dctx,\n                         LizardF_frameInfo_t* frameInfoPtr,\n                         const void* srcBuffer, size_t* srcSizePtr);\n\n/*!LizardF_decompress() :\n * Call this function repetitively to regenerate data compressed within srcBuffer.\n * The function will attempt to decode *srcSizePtr bytes from srcBuffer, into dstBuffer of maximum size *dstSizePtr.\n *\n * The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).\n *\n * The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).\n * If number of bytes read is < number of bytes provided, then decompression operation is not completed.\n * It typically happens when dstBuffer is not large enough to contain all decoded data.\n * LizardF_decompress() must be called again, starting from where it stopped (srcBuffer + *srcSizePtr)\n * The function will check this condition, and refuse to continue if it is not respected.\n *\n * `dstBuffer` is expected to be flushed between each call to the function, its content will be overwritten.\n * `dst` arguments can be changed at will at each consecutive call to the function.\n *\n * The function result is an hint of how many `srcSize` bytes LizardF_decompress() expects for next call.\n * Schematically, it's the size of the current (or remaining) compressed block + header of next block.\n * Respecting the hint provides some boost to performance, since it does skip intermediate buffers.\n * This is just a hint though, it's always possible to provide any srcSize.\n * When a frame is fully decoded, the function result will be 0 (no more data expected).\n * If decompression failed, function result is an error code, which can be tested using LizardF_isError().\n *\n * After a frame is fully decoded, dctx can be used again to decompress another frame.\n */\nsize_t LizardF_decompress(LizardF_decompressionContext_t dctx,\n                       void* dstBuffer, size_t* dstSizePtr,\n                       const void* srcBuffer, size_t* srcSizePtr,\n                       const LizardF_decompressOptions_t* dOptPtr);\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_frame_static.h",
    "content": "﻿/*\n   Lizard auto-framing library\n   Header File for static linking only\n   Copyright (C) 2011-2015, Yann Collet.\n   Copyright (C) 2016-2017, Przemyslaw Skibinski\n\n   BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Lizard source repository : https://github.com/inikep/lizard\n*/\n\n#pragma once\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* lizard_frame_static.h should be used solely in the context of static linking.\n * It contains definitions which may still change overtime.\n * Never use it in the context of DLL linking.\n * */\n\n\n/**************************************\n*  Includes\n**************************************/\n#include \"lizard_frame.h\"\n\n\n/**************************************\n * Error management\n * ************************************/\n#define LIZARDF_LIST_ERRORS(ITEM) \\\n        ITEM(OK_NoError) ITEM(ERROR_GENERIC) \\\n        ITEM(ERROR_maxBlockSize_invalid) ITEM(ERROR_blockMode_invalid) ITEM(ERROR_contentChecksumFlag_invalid) \\\n        ITEM(ERROR_compressionLevel_invalid) \\\n        ITEM(ERROR_headerVersion_wrong) ITEM(ERROR_blockChecksum_unsupported) ITEM(ERROR_reservedFlag_set) \\\n        ITEM(ERROR_allocation_failed) \\\n        ITEM(ERROR_srcSize_tooLarge) ITEM(ERROR_dstMaxSize_tooSmall) \\\n        ITEM(ERROR_frameHeader_incomplete) ITEM(ERROR_frameType_unknown) ITEM(ERROR_frameSize_wrong) \\\n        ITEM(ERROR_srcPtr_wrong) \\\n        ITEM(ERROR_decompressionFailed) \\\n        ITEM(ERROR_headerChecksum_invalid) ITEM(ERROR_contentChecksum_invalid) \\\n        ITEM(ERROR_maxCode)\n\n//#define LIZARDF_DISABLE_OLD_ENUMS\n#ifndef LIZARDF_DISABLE_OLD_ENUMS\n#define LIZARDF_GENERATE_ENUM(ENUM) LizardF_##ENUM, ENUM = LizardF_##ENUM,\n#else\n#define LIZARDF_GENERATE_ENUM(ENUM) LizardF_##ENUM,\n#endif\ntypedef enum { LIZARDF_LIST_ERRORS(LIZARDF_GENERATE_ENUM) } LizardF_errorCodes;  /* enum is exposed, to handle specific errors; compare function result to -enum value */\n\n\n#if defined (__cplusplus)\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_fast.h",
    "content": "﻿#define LIZARD_FAST_MIN_OFFSET 8\n#define LIZARD_FAST_LONGOFF_MM 0 /* not used with offsets > 1<<16 */\n\n/**************************************\n*  Hash Functions\n**************************************/\nstatic size_t Lizard_hashPosition(const void* p) \n{\n    if (MEM_64bits())\n        return Lizard_hash5Ptr(p, LIZARD_HASHLOG_LZ4);\n    return Lizard_hash4Ptr(p, LIZARD_HASHLOG_LZ4);\n}\n\nstatic void Lizard_putPositionOnHash(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)\n{\n    hashTable[h] = (U32)(p-srcBase);\n}\n\nstatic void Lizard_putPosition(const BYTE* p, U32* hashTable, const BYTE* srcBase)\n{\n    size_t const h = Lizard_hashPosition(p);\n    Lizard_putPositionOnHash(p, h, hashTable, srcBase);\n}\n\nstatic U32 Lizard_getPositionOnHash(size_t h, U32* hashTable)\n{\n    return hashTable[h];\n}\n\nstatic U32 Lizard_getPosition(const BYTE* p, U32* hashTable)\n{\n    size_t const h = Lizard_hashPosition(p);\n    return Lizard_getPositionOnHash(h, hashTable);\n}\n\n\nstatic const U32 Lizard_skipTrigger = 6;  /* Increase this value ==> compression run slower on incompressible data */\nstatic const U32 Lizard_minLength = (MFLIMIT+1);\n\n\nFORCE_INLINE int Lizard_compress_fast(\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    const U32 acceleration = 1;\n    const BYTE* base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = iend - LASTLITERALS;\n    const BYTE* anchor = ip;\n\n    size_t forwardH, matchIndex;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip - base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;\n\n    /* Init conditions */\n    if ((U32)(iend-ip) > (U32)LIZARD_MAX_INPUT_SIZE) goto _output_error;   /* Unsupported inputSize, too large (or negative) */\n\n    if ((U32)(iend-ip) < Lizard_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */\n\n    /* First Byte */\n    Lizard_putPosition(ip, ctx->hashTable, base);\n    ip++; forwardH = Lizard_hashPosition(ip);\n\n    /* Main Loop */\n    for ( ; ; ) {\n        const BYTE* match;\n        size_t matchLength;\n\n        /* Find a match */\n        {   const BYTE* forwardIp = ip;\n            unsigned step = 1;\n            unsigned searchMatchNb = acceleration << Lizard_skipTrigger;\n            while (1) {\n                size_t const h = forwardH;\n                ip = forwardIp;\n                forwardIp += step;\n                step = (searchMatchNb++ >> Lizard_skipTrigger);\n\n                if (unlikely(forwardIp > mflimit)) goto _last_literals;\n\n                matchIndex = Lizard_getPositionOnHash(h, ctx->hashTable);\n                forwardH = Lizard_hashPosition(forwardIp);\n                Lizard_putPositionOnHash(ip, h, ctx->hashTable, base);\n\n                if ((matchIndex < lowLimit) || (matchIndex >= (U32)(ip - base)) || (base + matchIndex + maxDistance < ip)) continue;\n\n                if (matchIndex >= dictLimit) {\n                    match = base + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                    if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                    if (MEM_read32(match) == MEM_read32(ip))\n                    {\n                        int back = 0;\n                        matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n\n                        while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                        matchLength -= back;\n#if LIZARD_FAST_LONGOFF_MM > 0\n                        if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        {\n                            ip += back;\n                            match += back;\n                            break;\n                        }\n                    }\n                } else {\n                    match = dictBase + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                    if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                    if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                    if (MEM_read32(match) == MEM_read32(ip)) {\n                        const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;\n                        int back = 0;\n                        matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);\n\n                        while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;\n                        matchLength -= back;\n                        match = base + matchIndex + back;\n#if LIZARD_FAST_LONGOFF_MM > 0\n                        if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        {\n                            ip += back;\n                            break;\n                        }\n                    }\n                }\n            } // while (1)\n        }\n\n_next_match:\n        if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;\n        \n        /* Test end of chunk */\n        if (ip > mflimit) break;\n\n        /* Fill table */\n        Lizard_putPosition(ip-2, ctx->hashTable, base);\n\n        /* Test next position */\n        matchIndex = Lizard_getPosition(ip, ctx->hashTable);\n        Lizard_putPosition(ip, ctx->hashTable, base);\n        if ((matchIndex >= lowLimit) && (matchIndex < (U32)(ip - base)) && (base + matchIndex + maxDistance >= ip))\n        {\n            if (matchIndex >= dictLimit) {\n                match = base + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                if (MEM_read32(match) == MEM_read32(ip))\n                {\n                    matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n#if LIZARD_FAST_LONGOFF_MM > 0\n                    if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        goto _next_match;\n                }\n            } else {\n                match = dictBase + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_read32(match) == MEM_read32(ip)) {\n                    matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);\n                    match = base + matchIndex;\n#if LIZARD_FAST_LONGOFF_MM > 0\n                    if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        goto _next_match;\n                }\n            }\n        }\n\n        /* Prepare next loop */\n        forwardH = Lizard_hashPosition(++ip);\n    }\n\n_last_literals:\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_fastbig.h",
    "content": "﻿#define LIZARD_FASTBIG_LONGOFF_MM MM_LONGOFF\n\n/**************************************\n*  Hash Functions\n**************************************/\nstatic size_t Lizard_hashPositionHLog(const void* p, int hashLog) \n{\n    if (MEM_64bits())\n        return Lizard_hash5Ptr(p, hashLog);\n    return Lizard_hash4Ptr(p, hashLog);\n}\n\nstatic void Lizard_putPositionOnHashHLog(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)\n{\n    hashTable[h] = (U32)(p-srcBase);\n}\n\nstatic void Lizard_putPositionHLog(const BYTE* p, U32* hashTable, const BYTE* srcBase, int hashLog)\n{\n    size_t const h = Lizard_hashPositionHLog(p, hashLog);\n    Lizard_putPositionOnHashHLog(p, h, hashTable, srcBase);\n}\n\nstatic U32 Lizard_getPositionOnHashHLog(size_t h, U32* hashTable)\n{\n    return hashTable[h];\n}\n\nstatic U32 Lizard_getPositionHLog(const BYTE* p, U32* hashTable, int hashLog)\n{\n    size_t const h = Lizard_hashPositionHLog(p, hashLog);\n    return Lizard_getPositionOnHashHLog(h, hashTable);\n}\n\nFORCE_INLINE int Lizard_compress_fastBig(\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    const U32 acceleration = 1;\n    const BYTE* base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = iend - LASTLITERALS;\n    const BYTE* anchor = ip;\n\n    size_t forwardH, matchIndex;\n    const int hashLog = ctx->params.hashLog;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip - base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;\n\n    /* Init conditions */\n    if ((U32)(iend-ip) > (U32)LIZARD_MAX_INPUT_SIZE) goto _output_error;   /* Unsupported inputSize, too large (or negative) */\n\n    if ((U32)(iend-ip) < Lizard_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */\n\n    /* First Byte */\n    Lizard_putPositionHLog(ip, ctx->hashTable, base, hashLog);\n    ip++; forwardH = Lizard_hashPositionHLog(ip, hashLog);\n\n    /* Main Loop */\n    for ( ; ; ) {\n        const BYTE* match;\n        size_t matchLength;\n\n        /* Find a match */\n        {   const BYTE* forwardIp = ip;\n            unsigned step = 1;\n            unsigned searchMatchNb = acceleration << Lizard_skipTrigger;\n            while (1) {\n                size_t const h = forwardH;\n                ip = forwardIp;\n                forwardIp += step;\n                step = (searchMatchNb++ >> Lizard_skipTrigger);\n\n                if (unlikely(forwardIp > mflimit)) goto _last_literals;\n\n                matchIndex = Lizard_getPositionOnHashHLog(h, ctx->hashTable);\n                forwardH = Lizard_hashPositionHLog(forwardIp, hashLog);\n                Lizard_putPositionOnHashHLog(ip, h, ctx->hashTable, base);\n\n                if ((matchIndex < lowLimit) || (matchIndex >= (U32)(ip - base)) || (base + matchIndex + maxDistance < ip)) continue;\n\n                if (matchIndex >= dictLimit) {\n                    match = base + matchIndex;\n                    if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)\n                    if (MEM_read32(match) == MEM_read32(ip))\n                    {\n                        int back = 0;\n                        matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n\n                        while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                        matchLength -= back;\n                        if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                        {\n                            ip += back;\n                            match += back;\n                            break;\n                        }\n                    }\n                } else {\n                    match = dictBase + matchIndex;\n                    if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)\n                    if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                    if (MEM_read32(match) == MEM_read32(ip)) {\n                        const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;\n                        int back = 0;\n                        matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);\n\n                        while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;\n                        matchLength -= back;\n                        match = base + matchIndex + back;\n                        if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                        {\n                            ip += back;\n                            break;\n                        }\n                    }\n                }\n            } // while (1)\n        }\n\n_next_match:\n        if (Lizard_encodeSequence_LIZv1(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;\n        \n        /* Test end of chunk */\n        if (ip > mflimit) break;\n\n        /* Fill table */\n        Lizard_putPositionHLog(ip-2, ctx->hashTable, base, hashLog);\n\n        /* Test next position */\n        matchIndex = Lizard_getPositionHLog(ip, ctx->hashTable, hashLog);\n        Lizard_putPositionHLog(ip, ctx->hashTable, base, hashLog);\n        if ((matchIndex >= lowLimit) && (matchIndex < (U32)(ip - base)) && (base + matchIndex + maxDistance >= ip))\n        {\n            if (matchIndex >= dictLimit) {\n                match = base + matchIndex;\n                if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)\n                if (MEM_read32(match) == MEM_read32(ip))\n                {\n                    matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n                    if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                        goto _next_match;\n                }\n            } else {\n                match = dictBase + matchIndex;\n                if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_read32(match) == MEM_read32(ip)) {\n                    matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);\n                    match = base + matchIndex;\n                    if ((matchLength >= LIZARD_FASTBIG_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                        goto _next_match;\n                }\n            }\n        }\n\n        /* Prepare next loop */\n        forwardH = Lizard_hashPositionHLog(++ip, hashLog);\n    }\n\n_last_literals:\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals_LIZv1(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_fastsmall.h",
    "content": "﻿/**************************************\n*  Hash Functions\n**************************************/\nstatic size_t Lizard_hashPositionSmall(const void* p) \n{\n    if (MEM_64bits())\n        return Lizard_hash5Ptr(p, LIZARD_HASHLOG_LZ4SM);\n    return Lizard_hash4Ptr(p, LIZARD_HASHLOG_LZ4SM);\n}\n\nstatic void Lizard_putPositionOnHashSmall(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)\n{\n    hashTable[h] = (U32)(p-srcBase);\n}\n\nstatic void Lizard_putPositionSmall(const BYTE* p, U32* hashTable, const BYTE* srcBase)\n{\n    size_t const h = Lizard_hashPositionSmall(p);\n    Lizard_putPositionOnHashSmall(p, h, hashTable, srcBase);\n}\n\nstatic U32 Lizard_getPositionOnHashSmall(size_t h, U32* hashTable)\n{\n    return hashTable[h];\n}\n\nstatic U32 Lizard_getPositionSmall(const BYTE* p, U32* hashTable)\n{\n    size_t const h = Lizard_hashPositionSmall(p);\n    return Lizard_getPositionOnHashSmall(h, hashTable);\n}\n\n\nFORCE_INLINE int Lizard_compress_fastSmall(\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    const U32 acceleration = 1;\n    const BYTE* base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = iend - LASTLITERALS;\n    const BYTE* anchor = ip;\n\n    size_t forwardH, matchIndex;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip - base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;\n\n    /* Init conditions */\n    if ((U32)(iend-ip) > (U32)LIZARD_MAX_INPUT_SIZE) goto _output_error;   /* Unsupported inputSize, too large (or negative) */\n\n    if ((U32)(iend-ip) < Lizard_minLength) goto _last_literals;                  /* Input too small, no compression (all literals) */\n\n    /* First Byte */\n    Lizard_putPositionSmall(ip, ctx->hashTable, base);\n    ip++; forwardH = Lizard_hashPositionSmall(ip);\n\n    /* Main Loop */\n    for ( ; ; ) {\n        const BYTE* match;\n        size_t matchLength;\n\n        /* Find a match */\n        {   const BYTE* forwardIp = ip;\n            unsigned step = 1;\n            unsigned searchMatchNb = acceleration << Lizard_skipTrigger;\n            while (1) {\n                size_t const h = forwardH;\n                ip = forwardIp;\n                forwardIp += step;\n                step = (searchMatchNb++ >> Lizard_skipTrigger);\n\n                if (unlikely(forwardIp > mflimit)) goto _last_literals;\n\n                matchIndex = Lizard_getPositionOnHashSmall(h, ctx->hashTable);\n                forwardH = Lizard_hashPositionSmall(forwardIp);\n                Lizard_putPositionOnHashSmall(ip, h, ctx->hashTable, base);\n\n                if ((matchIndex < lowLimit) || (matchIndex >= (U32)(ip - base)) || (base + matchIndex + maxDistance < ip)) continue;\n\n                if (matchIndex >= dictLimit) {\n                    match = base + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                    if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                    if (MEM_read32(match) == MEM_read32(ip))\n                    {\n                        int back = 0;\n                        matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n\n                        while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                        matchLength -= back;\n#if LIZARD_FAST_LONGOFF_MM > 0\n                        if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        {\n                            ip += back;\n                            match += back;\n                            break;\n                        }\n                    }\n                } else {\n                    match = dictBase + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                    if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                    if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                    if (MEM_read32(match) == MEM_read32(ip)) {\n                        const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;\n                        int back = 0;\n                        matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);\n\n                        while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;\n                        matchLength -= back;\n                        match = base + matchIndex + back;\n#if LIZARD_FAST_LONGOFF_MM > 0\n                        if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        {\n                            ip += back;\n                            break;\n                        }\n                    }\n                }\n            } // while (1)\n        }\n\n_next_match:\n        if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;\n        \n        /* Test end of chunk */\n        if (ip > mflimit) break;\n\n        /* Fill table */\n        Lizard_putPositionSmall(ip-2, ctx->hashTable, base);\n\n        /* Test next position */\n        matchIndex = Lizard_getPositionSmall(ip, ctx->hashTable);\n        Lizard_putPositionSmall(ip, ctx->hashTable, base);\n        if ((matchIndex >= lowLimit) && (matchIndex < (U32)(ip - base)) && (base + matchIndex + maxDistance >= ip))\n        {\n            if (matchIndex >= dictLimit) {\n                match = base + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                if (MEM_read32(match) == MEM_read32(ip))\n                {\n                    matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);\n#if LIZARD_FAST_LONGOFF_MM > 0\n                    if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        goto _next_match;\n                }\n            } else {\n                match = dictBase + matchIndex;\n#if LIZARD_FAST_MIN_OFFSET > 0\n                if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)\n#endif\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_read32(match) == MEM_read32(ip)) {\n                    matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);\n                    match = base + matchIndex;\n#if LIZARD_FAST_LONGOFF_MM > 0\n                    if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                        goto _next_match;\n                }\n            }\n        }\n\n        /* Prepare next loop */\n        forwardH = Lizard_hashPositionSmall(++ip);\n    }\n\n_last_literals:\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_hashchain.h",
    "content": "﻿#define LIZARD_HC_MIN_OFFSET 8\n#define LIZARD_HC_LONGOFF_MM 0 /* not used with offsets > 1<<16 */\n#define OPTIMAL_ML (int)((ML_MASK_LZ4-1)+MINMATCH)\n#define GET_MINMATCH(offset) (MINMATCH)\n\n#if 1\n    #define LIZARD_HC_HASH_FUNCTION(ip, hashLog) Lizard_hashPtr(ip, hashLog, ctx->params.searchLength)\n#else\n    #define LIZARD_HC_HASH_FUNCTION(ip, hashLog) Lizard_hash5Ptr(ip, hashLog)\n#endif\n\n/* Update chains up to ip (excluded) */\nFORCE_INLINE void Lizard_Insert (Lizard_stream_t* ctx, const BYTE* ip)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const hashTable  = ctx->hashTable;\n#if MINMATCH == 3\n    U32* HashTable3  = ctx->hashTable3;\n#endif \n    const BYTE* const base = ctx->base;\n    U32 const target = (U32)(ip - base);\n    U32 idx = ctx->nextToUpdate;\n    const int hashLog = ctx->params.hashLog;\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n\n    while (idx < target) {\n        size_t const h = Lizard_hashPtr(base+idx, hashLog, ctx->params.searchLength);\n        size_t delta = idx - hashTable[h];\n        if (delta>maxDistance) delta = maxDistance;\n        DELTANEXT(idx) = (U32)delta;\n        if ((hashTable[h] >= idx) || (idx >= hashTable[h] + LIZARD_HC_MIN_OFFSET))\n            hashTable[h] = idx;\n#if MINMATCH == 3\n        HashTable3[Lizard_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;\n#endif \n        idx++;\n    }\n\n    ctx->nextToUpdate = target;\n}\n\n\n\nFORCE_INLINE int Lizard_InsertAndFindBestMatch (Lizard_stream_t* ctx,   /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    U32 matchIndex, delta;\n    const BYTE* match;\n    int nbAttempts=ctx->params.searchNum;\n    size_t ml=0;\n    const int hashLog = ctx->params.hashLog;\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;\n\n    /* HC4 match finder */\n    Lizard_Insert(ctx, ip);\n    matchIndex = HashTable[LIZARD_HC_HASH_FUNCTION(ip, hashLog)];\n\n    while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {\n        nbAttempts--;\n        if (matchIndex >= dictLimit) {\n            match = base + matchIndex;\n#if LIZARD_HC_MIN_OFFSET > 0\n            if ((U32)(ip - match) >= LIZARD_HC_MIN_OFFSET)\n#endif\n            if (*(match+ml) == *(ip+ml)\n                && (MEM_read32(match) == MEM_read32(ip)))\n            {\n                size_t const mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n#if LIZARD_HC_LONGOFF_MM > 0\n                if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                if (mlt > ml) { ml = mlt; *matchpos = match; }\n            }\n        } else {\n            match = dictBase + matchIndex;\n#if LIZARD_HC_MIN_OFFSET > 0\n            if ((U32)(ip - (base + matchIndex)) >= LIZARD_HC_MIN_OFFSET)\n#endif\n            if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n#if LIZARD_HC_LONGOFF_MM > 0\n                if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - (base + matchIndex)) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */\n            }\n        }\n        delta = DELTANEXT(matchIndex);\n        if (delta > matchIndex) break;\n        matchIndex -= delta;\n    }\n\n    return (int)ml;\n}\n\n\nFORCE_INLINE int Lizard_InsertAndGetWiderMatch (\n    Lizard_stream_t* ctx,\n    const BYTE* const ip,\n    const BYTE* const iLowLimit,\n    const BYTE* const iHighLimit,\n    int longest,\n    const BYTE** matchpos,\n    const BYTE** startpos)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    U32   matchIndex, delta;\n    int nbAttempts = ctx->params.searchNum;\n    int LLdelta = (int)(ip-iLowLimit);\n    const int hashLog = ctx->params.hashLog;\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;\n\n    /* First Match */\n    Lizard_Insert(ctx, ip);\n    matchIndex = HashTable[LIZARD_HC_HASH_FUNCTION(ip, hashLog)];\n\n    while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {\n        nbAttempts--;\n        if (matchIndex >= dictLimit) {\n            const BYTE* match = base + matchIndex;\n#if LIZARD_HC_MIN_OFFSET > 0\n            if ((U32)(ip - match) >= LIZARD_HC_MIN_OFFSET)\n#endif\n            if (*(iLowLimit + longest) == *(match - LLdelta + longest)) {\n                if (MEM_read32(match) == MEM_read32(ip)) {\n                    int mlt = MINMATCH + Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit);\n                    int back = 0;\n                    while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                    mlt -= back;\n\n#if LIZARD_HC_LONGOFF_MM > 0\n                    if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                    if (mlt > longest) {\n                        longest = (int)mlt;\n                        *matchpos = match+back;\n                        *startpos = ip+back;\n                    }\n                }\n            }\n        } else {\n            const BYTE* match = dictBase + matchIndex;\n#if LIZARD_HC_MIN_OFFSET > 0\n            if ((U32)(ip - (base + matchIndex)) >= LIZARD_HC_MIN_OFFSET)\n#endif\n            if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                int back=0;\n                size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == match[back-1])) back--;\n                mlt -= back;\n#if LIZARD_HC_LONGOFF_MM > 0\n                if ((mlt >= LIZARD_HC_LONGOFF_MM) || ((U32)(ip - (base + matchIndex)) < LIZARD_MAX_16BIT_OFFSET))\n#endif\n                if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }\n            }\n        }\n        delta = DELTANEXT(matchIndex);\n        if (delta > matchIndex) break;\n        matchIndex -= delta;\n    }\n\n    return longest;\n}\n\n\nFORCE_INLINE int Lizard_compress_hashChain (\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    const BYTE* anchor = ip;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    int   ml, ml2, ml3, ml0;\n    const BYTE* ref = NULL;\n    const BYTE* start2 = NULL;\n    const BYTE* ref2 = NULL;\n    const BYTE* start3 = NULL;\n    const BYTE* ref3 = NULL;\n    const BYTE* start0;\n    const BYTE* ref0;\n\n    /* init */\n    ip++;\n\n    /* Main Loop */\n    while (ip < mflimit) {\n        ml = Lizard_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref));\n        if (!ml) { ip++; continue; }\n\n        /* saved, in case we would skip too much */\n        start0 = ip;\n        ref0 = ref;\n        ml0 = ml;\n\n_Search2:\n        if (ip+ml < mflimit)\n            ml2 = Lizard_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);\n        else ml2 = ml;\n\n        if (ml2 == ml) { /* No better match */\n            if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n            continue;\n        }\n\n        if (start0 < ip) {\n            if (start2 < ip + ml0) {  /* empirical */\n                ip = start0;\n                ref = ref0;\n                ml = ml0;\n            }\n        }\n\n        /* Here, start0==ip */\n        if ((start2 - ip) < 3) {  /* First Match too small : removed */\n            ml = ml2;\n            ip = start2;\n            ref =ref2;\n            goto _Search2;\n        }\n\n_Search3:\n        /*\n        * Currently we have :\n        * ml2 > ml1, and\n        * ip1+3 <= ip2 (usually < ip1+ml1)\n        */\n        if ((start2 - ip) < OPTIMAL_ML) {\n            int correction;\n            int new_ml = ml;\n            if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;\n            if (ip+new_ml > start2 + ml2 - GET_MINMATCH((U32)(start2 - ref2))) {\n                new_ml = (int)(start2 - ip) + ml2 - GET_MINMATCH((U32)(start2 - ref2));\n                if (new_ml < GET_MINMATCH((U32)(ip - ref))) { // match2 doesn't fit\n                    if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n                    continue;\n                }\n            }\n            correction = new_ml - (int)(start2 - ip);\n            if (correction > 0) {\n                start2 += correction;\n                ref2 += correction;\n                ml2 -= correction;\n            }\n        }\n        /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */\n\n        if (start2 + ml2 < mflimit)\n            ml3 = Lizard_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);\n        else ml3 = ml2;\n\n        if (ml3 == ml2) {  /* No better match : 2 sequences to encode */\n            /* ip & ref are known; Now for ml */\n            if (start2 < ip+ml)  ml = (int)(start2 - ip);\n            /* Now, encode 2 sequences */\n            if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n            ip = start2;\n            if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml2, ref2)) return 0;\n            continue;\n        }\n\n        if (start3 < ip+ml+3) {  /* Not enough space for match 2 : remove it */\n            if (start3 >= (ip+ml)) {  /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */\n                if (start2 < ip+ml) {\n                    int correction = (int)(ip+ml - start2);\n                    start2 += correction;\n                    ref2 += correction;\n                    ml2 -= correction;\n                    if (ml2 < GET_MINMATCH((U32)(start2 - ref2))) {\n                        start2 = start3;\n                        ref2 = ref3;\n                        ml2 = ml3;\n                    }\n                }\n\n                if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n                ip  = start3;\n                ref = ref3;\n                ml  = ml3;\n\n                start0 = start2;\n                ref0 = ref2;\n                ml0 = ml2;\n                goto _Search2;\n            }\n\n            start2 = start3;\n            ref2 = ref3;\n            ml2 = ml3;\n            goto _Search3;\n        }\n\n        /*\n        * OK, now we have 3 ascending matches; let's write at least the first one\n        * ip & ref are known; Now for ml\n        */\n        if (start2 < ip+ml) {\n            if ((start2 - ip) < (int)ML_MASK_LZ4) {\n                int correction;\n                if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;\n                if (ip + ml > start2 + ml2 - GET_MINMATCH((U32)(start2 - ref2))) {\n                    ml = (int)(start2 - ip) + ml2 - GET_MINMATCH((U32)(start2 - ref2));\n                    if (ml < GET_MINMATCH((U32)(ip - ref))) { // match2 doesn't fit, remove it\n                        if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n                        ip  = start3;\n                        ref = ref3;\n                        ml  = ml3;\n\n                        start0 = start2;\n                        ref0 = ref2;\n                        ml0 = ml2;\n                        goto _Search2;\n                    }\n                }\n                correction = ml - (int)(start2 - ip);\n                if (correction > 0) {\n                    start2 += correction;\n                    ref2 += correction;\n                    ml2 -= correction;\n                }\n            } else {\n                ml = (int)(start2 - ip);\n            }\n        }\n        if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n\n        ip = start2;\n        ref = ref2;\n        ml = ml2;\n\n        start2 = start3;\n        ref2 = ref3;\n        ml2 = ml3;\n\n        goto _Search3;\n    }\n\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_lowestprice.h",
    "content": "﻿#define LIZARD_LOWESTPRICE_MIN_OFFSET 8\n\n\nFORCE_INLINE size_t Lizard_more_profitable(Lizard_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, size_t literals, int last_off)\n{\n    size_t sum;\n\n    if (literals > 0)\n        sum = MAX(common + literals, best_common);\n    else\n        sum = MAX(common, best_common - literals);\n\n    if ((int)off == last_off) off = 0; // rep code\n    if ((int)best_off == last_off) best_off = 0;\n\n    return Lizard_get_price_LIZv1(ctx, last_off, ip, ctx->off24pos, sum - common, (U32)off, common) <= Lizard_get_price_LIZv1(ctx, last_off, best_ip, ctx->off24pos, sum - best_common, (U32)best_off, best_common);\n} \n\n\nFORCE_INLINE size_t Lizard_better_price(Lizard_stream_t* const ctx, const BYTE *best_ip, size_t best_off, size_t best_common, const BYTE *ip, size_t off, size_t common, int last_off)\n{\n    if ((int)off == last_off) off = 0; // rep code\n    if ((int)best_off == last_off) best_off = 0;\n\n    return Lizard_get_price_LIZv1(ctx, last_off, ip, ctx->off24pos, 0, (U32)off, common) < Lizard_get_price_LIZv1(ctx, last_off, best_ip, ctx->off24pos, common - best_common, (U32)best_off, best_common);\n}\n\n\nFORCE_INLINE int Lizard_FindMatchLowestPrice (Lizard_stream_t* ctx,   /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const intptr_t dictLimit = ctx->dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;\n    const intptr_t current = (ip - base);\n    const intptr_t lowLimit = ((intptr_t)ctx->lowLimit + maxDistance >= current) ? (intptr_t)ctx->lowLimit : current - maxDistance;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    intptr_t matchIndex;\n    const BYTE* match, *matchDict;\n    int nbAttempts=ctx->params.searchNum;\n    size_t ml=0, mlt;\n\n    matchIndex = HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n\n    if (ctx->last_off >= LIZARD_LOWESTPRICE_MIN_OFFSET) {\n        intptr_t matchIndexLO = (ip - ctx->last_off) - base;\n        if (matchIndexLO >= lowLimit) {\n            if (matchIndexLO >= dictLimit) {\n                match = base + matchIndexLO;\n                mlt = Lizard_count(ip, match, iLimit);// + MINMATCH;\n          //      if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET))\n                if (mlt > REPMINMATCH) {\n                    *matchpos = match;\n                    return (int)mlt;\n                }\n            } else {\n                match = dictBase + matchIndexLO;\n                if ((U32)((dictLimit-1) - matchIndexLO) >= 3) {  /* intentional overflow */\n                    mlt = Lizard_count_2segments(ip, match, iLimit, dictEnd, lowPrefixPtr);\n                 //   if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) \n                    if (mlt > REPMINMATCH) {\n                        *matchpos = base + matchIndexLO;  /* virtual matchpos */\n                        return (int)mlt;\n                    }\n               }\n            }\n        }\n    }\n\n\n#if MINMATCH == 3\n    {\n        U32 matchIndex3 = ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];\n        if (matchIndex3 < current && matchIndex3 >= lowLimit)\n        {\n            size_t offset = (size_t)current - matchIndex3;\n            if (offset < LIZARD_MAX_8BIT_OFFSET)\n            {\n                match = ip - offset;\n                if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match))\n                {\n                    ml = 3;//Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                    *matchpos = match;\n                }\n            }\n        }\n    }\n#endif\n    while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {\n        nbAttempts--;\n        match = base + matchIndex;\n        if ((U32)(ip - match) >= LIZARD_LOWESTPRICE_MIN_OFFSET) {\n            if (matchIndex >= dictLimit) {\n                if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip))) {\n                    mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (!ml || (mlt > ml && Lizard_better_price(ctx, ip, (ip - *matchpos), ml, ip, (ip - match), mlt, ctx->last_off)))\n                    { ml = mlt; *matchpos = match; }\n                }\n            } else {\n                matchDict = dictBase + matchIndex;\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_read32(matchDict) == MEM_read32(ip)) {\n                    mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (!ml || (mlt > ml && Lizard_better_price(ctx, ip, (ip - *matchpos), ml, ip, (U32)(ip - match), mlt, ctx->last_off)))\n                    { ml = mlt; *matchpos = match; }   /* virtual matchpos */\n                }\n            }\n        }\n        matchIndex -= chainTable[matchIndex & contentMask];\n    }\n\n    return (int)ml;\n}\n\n\nFORCE_INLINE size_t Lizard_GetWiderMatch (\n    Lizard_stream_t* ctx,\n    const BYTE* const ip,\n    const BYTE* const iLowLimit,\n    const BYTE* const iHighLimit,\n    size_t longest,\n    const BYTE** matchpos,\n    const BYTE** startpos)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const intptr_t dictLimit = ctx->dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;\n    const intptr_t current = (ip - base);\n    const intptr_t lowLimit = ((intptr_t)ctx->lowLimit + maxDistance >= current) ? (intptr_t)ctx->lowLimit : current - maxDistance;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const BYTE* match, *matchDict;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    intptr_t matchIndex;\n    int nbAttempts = ctx->params.searchNum;\n    size_t mlt;\n\n    /* First Match */\n    matchIndex = HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n\n    if (ctx->last_off >= LIZARD_LOWESTPRICE_MIN_OFFSET) {\n        intptr_t matchIndexLO = (ip - ctx->last_off) - base;\n        if (matchIndexLO >= lowLimit) {\n            if (matchIndexLO >= dictLimit) {\n                match = base + matchIndexLO;\n                if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {\n                    int back = 0;\n                    mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;\n                    while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                    mlt -= back;\n\n                    if (mlt > longest)\n                    if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) {\n                        *matchpos = match+back;\n                        *startpos = ip+back;\n                        longest = mlt;\n                    }\n                }\n            } else {\n                match = dictBase + matchIndexLO;\n                if ((U32)((dictLimit-1) - matchIndexLO) >= 3)  /* intentional overflow */\n                if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {\n                    int back=0;\n                    mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                    while ((ip+back > iLowLimit) && (matchIndexLO+back > lowLimit) && (ip[back-1] == match[back-1])) back--;\n                    mlt -= back;\n\n                    if (mlt > longest)\n                    if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) {\n                        *matchpos = base + matchIndexLO + back;  /* virtual matchpos */\n                        *startpos = ip+back;\n                        longest = mlt;\n                    }\n                }\n            }\n        }\n    }\n\n#if MINMATCH == 3\n    {\n        U32 matchIndex3 = ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];\n        if (matchIndex3 < current && matchIndex3 >= lowLimit) {\n            size_t offset = (size_t)current - matchIndex3;\n            if (offset < LIZARD_MAX_8BIT_OFFSET) {\n                match = ip - offset;\n                if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match)) {\n                    mlt = Lizard_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;\n\n                    int back = 0;\n                    while ((ip + back > iLowLimit) && (match + back > lowPrefixPtr) && (ip[back - 1] == match[back - 1])) back--;\n                    mlt -= back;\n\n                    if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off))) {\n                        *matchpos = match + back;\n                        *startpos = ip + back;\n                        longest = mlt;\n                    }\n                }\n            }\n        }\n    }\n#endif\n\n    while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {\n        nbAttempts--;\n        match = base + matchIndex;\n        if ((U32)(ip - match) >= LIZARD_LOWESTPRICE_MIN_OFFSET) {\n            if (matchIndex >= dictLimit) {\n                if (MEM_read32(match) == MEM_read32(ip)) {\n                    int back = 0;\n                    mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;\n                    while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                    mlt -= back;\n\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (ip - match), mlt, ctx->last_off)))\n                    { longest = mlt; *startpos = ip+back; *matchpos = match+back; }\n                }\n            } else {\n                matchDict = dictBase + matchIndex;\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_read32(matchDict) == MEM_read32(ip)) {\n                    int back=0;\n                    mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                    while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchDict[back-1])) back--;\n                    mlt -= back;\n\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (!longest || (mlt > longest && Lizard_better_price(ctx, *startpos, (*startpos - *matchpos), longest, ip, (U32)(ip - match), mlt, ctx->last_off)))\n                    { longest = mlt; *startpos = ip+back;  *matchpos = match+back; }   /* virtual matchpos */\n                }\n            }\n        }\n        matchIndex -= chainTable[matchIndex & contentMask];\n    }\n\n    return longest;\n}\n\n\n\n\nFORCE_INLINE int Lizard_compress_lowestPrice(\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    const BYTE* anchor = ip;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    size_t   ml, ml2, ml0;\n    const BYTE* ref=NULL;\n    const BYTE* start2=NULL;\n    const BYTE* ref2=NULL;\n    const BYTE* start0;\n    const BYTE* ref0;\n    const BYTE* lowPrefixPtr = ctx->base + ctx->dictLimit;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    const size_t sufficient_len = ctx->params.sufficientLength;\n\n    /* Main Loop */\n    while (ip < mflimit)\n    {\n        Lizard_Insert(ctx, ip);\n        ml = Lizard_FindMatchLowestPrice (ctx, ip, matchlimit, (&ref));\n        if (!ml) { ip++; continue; }\n\n        {\n            int back = 0;\n            while ((ip + back > anchor) && (ref + back > lowPrefixPtr) && (ip[back - 1] == ref[back - 1])) back--;\n            ml -= back;\n            ip += back;\n            ref += back;\n        }\n\n        /* saved, in case we would skip too much */\n        start0 = ip;\n        ref0 = ref;\n        ml0 = ml;\n    //    goto _Encode;\n\n_Search:\n        if (ip+ml >= mflimit) { goto _Encode; }\n        if (ml >= sufficient_len) { goto _Encode; }\n\n        Lizard_Insert(ctx, ip);\n        ml2 = (int)Lizard_GetWiderMatch(ctx, ip + ml - 2, anchor, matchlimit, 0, &ref2, &start2);\n        if (!ml2) goto _Encode;\n\n        {\n        U64 price, best_price;\n        int off0=0, off1=0;\n        const BYTE *pos, *best_pos;\n\n    //\tfind the lowest price for encoding ml bytes\n        best_pos = ip;\n        best_price = LIZARD_MAX_PRICE;\n        off0 = (int)(ip - ref);\n        off1 = (int)(start2 - ref2);\n\n        for (pos = ip + ml; pos >= start2; pos--)\n        {\n            int common0 = (int)(pos - ip);\n            if (common0 >= MINMATCH) {\n                price = (int)Lizard_get_price_LIZv1(ctx, ctx->last_off, ip, ctx->off24pos, ip - anchor, (off0 == ctx->last_off) ? 0 : off0, common0);\n                \n                {\n                    int common1 = (int)(start2 + ml2 - pos);\n                    if (common1 >= MINMATCH)\n                        price += Lizard_get_price_LIZv1(ctx, ctx->last_off, pos, ctx->off24pos, 0, (off1 == off0) ? 0 : (off1), common1);\n                    else\n                        price += Lizard_get_price_LIZv1(ctx, ctx->last_off, pos, ctx->off24pos, common1, 0, 0);\n                }\n\n                if (price < best_price) {\n                    best_price = price;\n                    best_pos = pos;\n                }\n            } else {\n                price = Lizard_get_price_LIZv1(ctx, ctx->last_off, ip, ctx->off24pos, start2 - anchor, (off1 == ctx->last_off) ? 0 : off1, ml2);\n\n                if (price < best_price)\n                    best_pos = pos;\n                break;\n            }\n        }\n        ml = (int)(best_pos - ip);\n        }\n\n\n        if ((ml < MINMATCH) || ((ml < minMatchLongOff) && ((U32)(ip-ref) >= LIZARD_MAX_16BIT_OFFSET)))\n        {\n            ip = start2;\n            ref = ref2;\n            ml = ml2;\n            goto _Search;\n        }\n\n_Encode:\n        if (start0 < ip)\n        {\n            if (Lizard_more_profitable(ctx, ip, (ip - ref), ml, start0, (start0 - ref0), ml0, (ref0 - ref), ctx->last_off))\n            {\n                ip = start0;\n                ref = ref0;\n                ml = ml0;\n            }\n        }\n\n        if (Lizard_encodeSequence_LIZv1(ctx, &ip, &anchor, ml, ((ip - ref == ctx->last_off) ? ip : ref))) return 0;\n    }\n\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals_LIZv1(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_nochain.h",
    "content": "﻿#define OPTIMAL_ML (int)((ML_MASK_LZ4-1)+MINMATCH)\n\n//#define LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog) Lizard_hashPtr(ip, hashLog, ctx->params.searchLength)\n#define LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog) Lizard_hash5Ptr(ip, hashLog)\n#define LIZARD_NOCHAIN_MIN_OFFSET 8\n\n/* Update chains up to ip (excluded) */\nFORCE_INLINE void Lizard_InsertNoChain (Lizard_stream_t* ctx, const BYTE* ip)\n{\n    U32* const hashTable  = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    U32 const target = (U32)(ip - base);\n    U32 idx = ctx->nextToUpdate;\n    const int hashLog = ctx->params.hashLog;\n\n    while (idx < target) {\n        size_t const h = LIZARD_NOCHAIN_HASH_FUNCTION(base+idx, hashLog);\n        if ((hashTable[h] >= idx) || (idx >= hashTable[h] + LIZARD_NOCHAIN_MIN_OFFSET))\n            hashTable[h] = idx;\n        idx++;\n    }\n\n    ctx->nextToUpdate = target;\n}\n\n\nFORCE_INLINE int Lizard_InsertAndFindBestMatchNoChain (Lizard_stream_t* ctx,   /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    U32 matchIndex;\n    const BYTE* match;\n    size_t ml=0;\n    const int hashLog = ctx->params.hashLog;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;\n\n    /* HC4 match finder */\n    Lizard_InsertNoChain(ctx, ip);\n    matchIndex = HashTable[LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog)];\n\n    if ((matchIndex < current) && (matchIndex >= lowLimit)) {\n        if (matchIndex >= dictLimit) {\n            match = base + matchIndex;\n#if LIZARD_NOCHAIN_MIN_OFFSET > 0\n            if ((U32)(ip - match) >= LIZARD_NOCHAIN_MIN_OFFSET)\n#endif\n            if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip)))\n            {\n                size_t const mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                if (mlt > ml) { ml = mlt; *matchpos = match; }\n            }\n        } else {\n            match = dictBase + matchIndex;\n#if LIZARD_NOCHAIN_MIN_OFFSET > 0\n            if ((U32)(ip - (base + matchIndex)) >= LIZARD_NOCHAIN_MIN_OFFSET)\n#endif\n            if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; }   /* virtual matchpos */\n            }\n        }\n    }\n\n    return (int)ml;\n}\n\n\nFORCE_INLINE int Lizard_InsertAndGetWiderMatchNoChain (\n    Lizard_stream_t* ctx,\n    const BYTE* const ip,\n    const BYTE* const iLowLimit,\n    const BYTE* const iHighLimit,\n    int longest,\n    const BYTE** matchpos,\n    const BYTE** startpos)\n{\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    U32   matchIndex;\n    int LLdelta = (int)(ip-iLowLimit);\n    const int hashLog = ctx->params.hashLog;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;\n\n    /* First Match */\n    Lizard_InsertNoChain(ctx, ip);\n    matchIndex = HashTable[LIZARD_NOCHAIN_HASH_FUNCTION(ip, hashLog)];\n\n    if ((matchIndex < current) && (matchIndex >= lowLimit)) {\n        if (matchIndex >= dictLimit) {\n            const BYTE* match = base + matchIndex;\n#if LIZARD_NOCHAIN_MIN_OFFSET > 0\n            if ((U32)(ip - match) >= LIZARD_NOCHAIN_MIN_OFFSET)\n#endif\n            if (*(iLowLimit + longest) == *(match - LLdelta + longest)) {\n                if (MEM_read32(match) == MEM_read32(ip)) {\n                    int mlt = MINMATCH + Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit);\n                    int back = 0;\n                    while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                    mlt -= back;\n\n                    if (mlt > longest) {\n                        longest = (int)mlt;\n                        *matchpos = match+back;\n                        *startpos = ip+back;\n                    }\n                }\n            }\n        } else {\n            const BYTE* match = dictBase + matchIndex;\n#if LIZARD_NOCHAIN_MIN_OFFSET > 0\n            if ((U32)(ip - (base + matchIndex)) >= LIZARD_NOCHAIN_MIN_OFFSET)\n#endif\n            if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                int back=0;\n                size_t mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == match[back-1])) back--;\n                mlt -= back;\n                if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }\n            }\n        }\n    }\n\n    return longest;\n}\n\n\nFORCE_INLINE int Lizard_compress_noChain (\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    const BYTE* anchor = ip;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    int   ml, ml2, ml3, ml0;\n    const BYTE* ref = NULL;\n    const BYTE* start2 = NULL;\n    const BYTE* ref2 = NULL;\n    const BYTE* start3 = NULL;\n    const BYTE* ref3 = NULL;\n    const BYTE* start0;\n    const BYTE* ref0;\n\n    /* init */\n    ip++;\n\n    /* Main Loop */\n    while (ip < mflimit) {\n        ml = Lizard_InsertAndFindBestMatchNoChain (ctx, ip, matchlimit, (&ref));\n        if (!ml) { ip++; continue; }\n\n        /* saved, in case we would skip too much */\n        start0 = ip;\n        ref0 = ref;\n        ml0 = ml;\n\n_Search2:\n        if (ip+ml < mflimit)\n            ml2 = Lizard_InsertAndGetWiderMatchNoChain(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2);\n        else ml2 = ml;\n\n        if (ml2 == ml) { /* No better match */\n            if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n            continue;\n        }\n\n        if (start0 < ip) {\n            if (start2 < ip + ml0) {  /* empirical */\n                ip = start0;\n                ref = ref0;\n                ml = ml0;\n            }\n        }\n\n        /* Here, start0==ip */\n        if ((start2 - ip) < 3) {  /* First Match too small : removed */\n            ml = ml2;\n            ip = start2;\n            ref =ref2;\n            goto _Search2;\n        }\n\n_Search3:\n        /*\n        * Currently we have :\n        * ml2 > ml1, and\n        * ip1+3 <= ip2 (usually < ip1+ml1)\n        */\n        if ((start2 - ip) < OPTIMAL_ML) {\n            int correction;\n            int new_ml = ml;\n            if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;\n            if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;\n            correction = new_ml - (int)(start2 - ip);\n            if (correction > 0) {\n                start2 += correction;\n                ref2 += correction;\n                ml2 -= correction;\n            }\n        }\n        /* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */\n\n        if (start2 + ml2 < mflimit)\n            ml3 = Lizard_InsertAndGetWiderMatchNoChain(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3);\n        else ml3 = ml2;\n\n        if (ml3 == ml2) {  /* No better match : 2 sequences to encode */\n            /* ip & ref are known; Now for ml */\n            if (start2 < ip+ml)  ml = (int)(start2 - ip);\n            /* Now, encode 2 sequences */\n            if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n            ip = start2;\n            if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml2, ref2)) return 0;\n            continue;\n        }\n\n        if (start3 < ip+ml+3) {  /* Not enough space for match 2 : remove it */\n            if (start3 >= (ip+ml)) {  /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */\n                if (start2 < ip+ml) {\n                    int correction = (int)(ip+ml - start2);\n                    start2 += correction;\n                    ref2 += correction;\n                    ml2 -= correction;\n                    if (ml2 < MINMATCH) {\n                        start2 = start3;\n                        ref2 = ref3;\n                        ml2 = ml3;\n                    }\n                }\n\n                if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n                ip  = start3;\n                ref = ref3;\n                ml  = ml3;\n\n                start0 = start2;\n                ref0 = ref2;\n                ml0 = ml2;\n                goto _Search2;\n            }\n\n            start2 = start3;\n            ref2 = ref3;\n            ml2 = ml3;\n            goto _Search3;\n        }\n\n        /*\n        * OK, now we have 3 ascending matches; let's write at least the first one\n        * ip & ref are known; Now for ml\n        */\n        if (start2 < ip+ml) {\n            if ((start2 - ip) < (int)ML_MASK_LZ4) {\n                int correction;\n                if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;\n                if (ip + ml > start2 + ml2 - MINMATCH) {\n                    ml = (int)(start2 - ip) + ml2 - MINMATCH;\n                    if (ml < MINMATCH) { // match2 doesn't fit, remove it\n                        if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n                        ip  = start3;\n                        ref = ref3;\n                        ml  = ml3;\n\n                        start0 = start2;\n                        ref0 = ref2;\n                        ml0 = ml2;\n                        goto _Search2;\n                    }\n                }\n                correction = ml - (int)(start2 - ip);\n                if (correction > 0) {\n                    start2 += correction;\n                    ref2 += correction;\n                    ml2 -= correction;\n                }\n            } else {\n                ml = (int)(start2 - ip);\n            }\n        }\n        if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, ml, ref)) return 0;\n\n        ip = start2;\n        ref = ref2;\n        ml = ml2;\n\n        start2 = start3;\n        ref2 = ref3;\n        ml2 = ml3;\n\n        goto _Search3;\n    }\n\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_optimal.h",
    "content": "﻿#define LIZARD_LOG_PARSER(fmt, ...) //printf(fmt, __VA_ARGS__)\n#define LIZARD_LOG_PRICE(fmt, ...) //printf(fmt, __VA_ARGS__)\n#define LIZARD_LOG_ENCODE(fmt, ...) //printf(fmt, __VA_ARGS__) \n\n#define LIZARD_OPTIMAL_MIN_OFFSET  8\n#define LIZARD_OPT_NUM             (1<<12) \n#define REPMINMATCH             1\n\n\nFORCE_INLINE size_t Lizard_get_price(Lizard_stream_t* const ctx, int rep, const BYTE *ip, const BYTE *off24pos, size_t litLength, U32 offset, size_t matchLength)\n{\n    if (ctx->params.decompressType == Lizard_coderwords_LZ4)\n        return Lizard_get_price_LZ4(ctx, ip, litLength, offset, matchLength);\n\n    return Lizard_get_price_LIZv1(ctx, rep, ip, off24pos, litLength, offset, matchLength);\n}\n\n\n\ntypedef struct\n{\n    int off;\n    int len;\n    int back;\n} Lizard_match_t;\n\ntypedef struct\n{\n    int price;\n    int off;\n    int mlen;\n    int litlen;\n    int rep;\n    const BYTE* off24pos;\n} Lizard_optimal_t; \n\n\n/* Update chains up to ip (excluded) */\nFORCE_INLINE void Lizard_BinTree_Insert(Lizard_stream_t* ctx, const BYTE* ip)\n{\n#if MINMATCH == 3\n    U32* HashTable3  = ctx->hashTable3;\n    const BYTE* const base = ctx->base;\n    const U32 target = (U32)(ip - base);\n    U32 idx = ctx->nextToUpdate;\n    \n    while(idx < target) {\n        HashTable3[Lizard_hash3Ptr(base+idx, ctx->params.hashLog3)] = idx;\n        idx++;\n    }\n\n    ctx->nextToUpdate = target;\n#else\n    (void)ctx; (void)ip;\n#endif\n}\n\n\n\nFORCE_INLINE int Lizard_GetAllMatches (\n    Lizard_stream_t* ctx,\n    const BYTE* const ip,\n    const BYTE* const iLowLimit,\n    const BYTE* const iHighLimit,\n    size_t best_mlen,\n    Lizard_match_t* matches)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const intptr_t dictLimit = ctx->dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;\n    const intptr_t current = (ip - base);\n    const intptr_t lowLimit = ((intptr_t)ctx->lowLimit + maxDistance >= current) ? (intptr_t)ctx->lowLimit : current - maxDistance;\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const BYTE* match, *matchDict;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    intptr_t matchIndex;\n    int nbAttempts = ctx->params.searchNum;\n //   bool fullSearch = (ctx->params.fullSearch >= 2);\n    int mnum = 0;\n    U32* HashPos;\n    size_t mlt;\n\n    if (ip + MINMATCH > iHighLimit) return 0;\n\n    /* First Match */\n    HashPos = &HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n    matchIndex = *HashPos;\n#if MINMATCH == 3\n    {\n    U32* const HashTable3 = ctx->hashTable3;\n    U32* HashPos3 = &HashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];\n\n    if ((*HashPos3 < current) && (*HashPos3 >= lowLimit)) {\n        size_t offset = current - *HashPos3;\n        if (offset < LIZARD_MAX_8BIT_OFFSET) {\n            match = ip - offset;\n            if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match)) {\n                size_t mlt = Lizard_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;\n\n                int back = 0;\n                while ((ip + back > iLowLimit) && (match + back > lowPrefixPtr) && (ip[back - 1] == match[back - 1])) back--;\n                mlt -= back;\n\n                matches[mnum].off = (int)offset;\n                matches[mnum].len = (int)mlt;\n                matches[mnum].back = -back;\n                mnum++;\n            }\n        }\n    }\n\n    *HashPos3 = current;\n    }\n#endif\n\n    chainTable[current & contentMask] = (U32)(current - matchIndex);\n    *HashPos =  (U32)current;\n    ctx->nextToUpdate++;\n\n    if (best_mlen < MINMATCH-1) best_mlen = MINMATCH-1;\n\n    while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {\n        nbAttempts--;\n        match = base + matchIndex;\n        if ((U32)(ip - match) >= LIZARD_OPTIMAL_MIN_OFFSET) {\n            if (matchIndex >= dictLimit) {\n                if ((/*fullSearch ||*/ ip[best_mlen] == match[best_mlen]) && (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip))) {\n                    int back = 0;\n                    mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iHighLimit) + MINMATCH;\n                    while ((ip+back > iLowLimit) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;\n                    mlt -= back;\n\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (mlt > best_mlen) {\n                        best_mlen = mlt;\n                        matches[mnum].off = (int)(ip - match);\n                        matches[mnum].len = (int)mlt;\n                        matches[mnum].back = -back;\n                        mnum++;\n\n                        if (best_mlen > LIZARD_OPT_NUM) break;\n                    }\n                }\n            } else {\n                matchDict = dictBase + matchIndex;\n    //            fprintf(stderr, \"dictBase[%p]+matchIndex[%d]=match[%p] dictLimit=%d base=%p ip=%p iLimit=%p off=%d\\n\", dictBase, matchIndex, match, dictLimit, base, ip, iLimit, (U32)(ip-match));\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_readMINMATCH(matchDict) == MEM_readMINMATCH(ip)) {\n                    int back=0;\n                    mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iHighLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                    while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchDict[back-1])) back--;\n                    mlt -= back;\n\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (mlt > best_mlen) {\n                        best_mlen = mlt;\n                        matches[mnum].off = (int)(ip - match);\n                        matches[mnum].len = (int)mlt;\n                        matches[mnum].back = -back;\n                        mnum++;\n                        \n                        if (best_mlen > LIZARD_OPT_NUM) break;\n                    }\n                }\n            }\n        }\n        matchIndex -= chainTable[matchIndex & contentMask];\n    }\n\n    return mnum;\n}\n\n\n\n\nFORCE_INLINE int Lizard_BinTree_GetAllMatches (\n    Lizard_stream_t* ctx,\n    const BYTE* const ip,\n    const BYTE* const iHighLimit,\n    size_t best_mlen,\n    Lizard_match_t* matches)\n{\n    U32* const chainTable = ctx->chainTable;\n    U32* const HashTable = ctx->hashTable;\n    const BYTE* const base = ctx->base;\n    const intptr_t dictLimit = ctx->dictLimit;\n    const BYTE* const dictBase = ctx->dictBase;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const U32 contentMask = (1 << ctx->params.contentLog) - 1;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;\n    const intptr_t current = (ip - base);\n    const intptr_t lowLimit = ((intptr_t)ctx->lowLimit + maxDistance >= current) ? (intptr_t)ctx->lowLimit : current - maxDistance;\n    const BYTE* match;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    int nbAttempts = ctx->params.searchNum;\n    int mnum = 0;\n    U32 *ptr0, *ptr1, delta0, delta1;\n    intptr_t matchIndex;\n    size_t mlt = 0;\n    U32* HashPos;\n\n    if (ip + MINMATCH > iHighLimit) return 0;\n\n    /* First Match */\n    HashPos = &HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n    matchIndex = *HashPos;\n\n    \n#if MINMATCH == 3\n    {\n    U32* HashPos3 = &ctx->hashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];\n\n    if ((*HashPos3 < current) && (*HashPos3 >= lowLimit)) {\n        size_t offset = current - *HashPos3;\n        if (offset < LIZARD_MAX_8BIT_OFFSET) {\n            match = ip - offset;\n            if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match))\n            {\n                mlt = Lizard_count(ip + MINMATCH, match + MINMATCH, iHighLimit) + MINMATCH;\n\n                matches[mnum].off = (int)offset;\n                matches[mnum].len = (int)mlt;\n                matches[mnum].back = 0;\n                mnum++;\n            }\n        }\n        *HashPos3 = current;\n    }\n    }\n#endif\n\n    *HashPos = (U32)current;\n    ctx->nextToUpdate++;\n\n    // check rest of matches\n    ptr0 = &chainTable[(current*2+1) & contentMask];\n    ptr1 = &chainTable[(current*2) & contentMask];\n    delta0 = delta1 = (U32)(current - matchIndex);\n\n    if (best_mlen < MINMATCH-1) best_mlen = MINMATCH-1;\n\n    while ((matchIndex < current) && (matchIndex >= lowLimit) && (nbAttempts)) {\n        nbAttempts--;\n        if (matchIndex >= dictLimit) {\n            match = base + matchIndex;\n           // if (ip[mlt] == match[mlt])\n                mlt = Lizard_count(ip, match, iHighLimit);\n        } else {\n            match = dictBase + matchIndex;\n            mlt = Lizard_count_2segments(ip, match, iHighLimit, dictEnd, lowPrefixPtr);\n            if (matchIndex + (int)mlt >= dictLimit) \n                match = base + matchIndex;   /* to prepare for next usage of match[mlt] */ \n        }\n\n        if ((U32)(current - matchIndex) >= LIZARD_OPTIMAL_MIN_OFFSET) {\n            if ((mlt >= minMatchLongOff) || ((U32)(current - matchIndex) < LIZARD_MAX_16BIT_OFFSET))\n            if (mlt > best_mlen) {\n                best_mlen = mlt;\n                matches[mnum].off = (int)(current - matchIndex);\n                matches[mnum].len = (int)mlt;\n                matches[mnum].back = 0;\n                mnum++;\n\n                if (mlt > LIZARD_OPT_NUM) break;\n                if (ip + mlt >= iHighLimit) break;\n            }\n        } else {\n#if 1\n            intptr_t newMatchIndex;\n            size_t newml = 0, newoff = 0;\n            do {\n                newoff += (int)(current - matchIndex);\n            } while (newoff < LIZARD_OPTIMAL_MIN_OFFSET);\n            newMatchIndex = current - newoff;\n            if (newMatchIndex >= dictLimit) newml = Lizard_count(ip, base + newMatchIndex, iHighLimit);\n\n        //    printf(\"%d: off=%d mlt=%d\\n\", (U32)current, (U32)(current - matchIndex), (int)mlt);\n        //    printf(\"%d: newoff=%d newml=%d\\n\", (U32)current, (int)newoff, (int)newml);\n\n            if ((newml >= minMatchLongOff) && (newml > best_mlen)) {\n                best_mlen = newml;\n                matches[mnum].off = (int)newoff;\n                matches[mnum].len = (int)newml;\n                matches[mnum].back = 0;\n                mnum++;\n\n                if (newml > LIZARD_OPT_NUM) break;\n                if (ip + newml >= iHighLimit) break;\n            }\n#endif\n        }\n\n        if (ip[mlt] < match[mlt]) {\n            *ptr0 = delta0;\n            ptr0 = &chainTable[(matchIndex*2) & contentMask];\n            if (*ptr0 == (U32)-1) break;\n            delta0 = *ptr0;\n            delta1 += delta0;\n            matchIndex -= delta0;\n        } else {\n            *ptr1 = delta1;\n            ptr1 = &chainTable[(matchIndex*2+1) & contentMask];\n            if (*ptr1 == (U32)-1) break;\n            delta1 = *ptr1;\n            delta0 += delta1;\n            matchIndex -= delta1;\n        }\n    }\n\n    *ptr0 = (U32)-1;\n    *ptr1 = (U32)-1;\n\n    return mnum;\n}\n\n\n#define SET_PRICE(pos, mlen, offset, litlen, price)   \\\n    {                                                 \\\n        while (last_pos < pos)  { opt[last_pos+1].price = LIZARD_MAX_PRICE; last_pos++; } \\\n        opt[pos].mlen = (int)mlen;                         \\\n        opt[pos].off = (int)offset;                        \\\n        opt[pos].litlen = (int)litlen;                     \\\n        opt[pos].price = (int)price;                       \\\n        LIZARD_LOG_PARSER(\"%d: SET price[%d/%d]=%d litlen=%d len=%d off=%d\\n\", (int)(inr-source), pos, last_pos, opt[pos].price, opt[pos].litlen, opt[pos].mlen, opt[pos].off); \\\n    }\n\n\nFORCE_INLINE int Lizard_compress_optimalPrice(\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    Lizard_optimal_t opt[LIZARD_OPT_NUM + 4];\n    Lizard_match_t matches[LIZARD_OPT_NUM + 1];\n    const BYTE *inr;\n    size_t res, cur, cur2, skip_num = 0;\n    size_t i, llen, litlen, mlen, best_mlen, price, offset, best_off, match_num, last_pos;\n\n    const BYTE* anchor = ip;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const intptr_t dictLimit = ctx->dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const intptr_t lowLimit = ctx->lowLimit;\n    const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;\n\n    const size_t sufficient_len = ctx->params.sufficientLength;\n    const int faster_get_matches = (ctx->params.fullSearch == 0); \n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    const int lizardOptimalMinOffset = (ctx->params.decompressType == Lizard_coderwords_LZ4) ? (1<<30) : LIZARD_OPTIMAL_MIN_OFFSET;\n    const size_t repMinMatch = (ctx->params.decompressType == Lizard_coderwords_LZ4) ? MINMATCH : REPMINMATCH;\n\n    /* Main Loop */\n    while (ip < mflimit) {\n        memset(opt, 0, sizeof(Lizard_optimal_t));\n        last_pos = 0;\n        llen = ip - anchor;\n\n        /* check rep code */\n\n        if (ctx->last_off >= lizardOptimalMinOffset) {\n            intptr_t matchIndexLO = (ip - ctx->last_off) - base;\n            mlen = 0;\n            if ((matchIndexLO >= lowLimit) && (base + matchIndexLO + maxDistance >= ip)) {\n                if (matchIndexLO >= dictLimit) {\n                    mlen = Lizard_count(ip, base + matchIndexLO, matchlimit);\n                } else {\n                    mlen = Lizard_count_2segments(ip, dictBase + matchIndexLO, matchlimit, dictEnd, lowPrefixPtr);\n                }\n            }\n            if (mlen >= REPMINMATCH) {\n                if (mlen > sufficient_len || mlen >= LIZARD_OPT_NUM) {\n                    best_mlen = mlen; best_off = 0; cur = 0; last_pos = 1;\n                    goto encode;\n                }\n\n                do\n                {\n                    litlen = 0;\n                    price = Lizard_get_price(ctx, ctx->last_off, ip, ctx->off24pos, llen, 0, mlen);\n                    if (mlen > last_pos || price < (size_t)opt[mlen].price)\n                        SET_PRICE(mlen, mlen, 0, litlen, price);\n                    mlen--;\n                }\n                while (mlen >= REPMINMATCH);\n            }\n        }\n\n        if (faster_get_matches && last_pos)\n           match_num = 0;\n        else\n        {\n            if (ctx->params.parserType == Lizard_parser_optimalPrice) {\n                Lizard_Insert(ctx, ip);\n                match_num = Lizard_GetAllMatches(ctx, ip, ip, matchlimit, last_pos, matches);\n            } else {\n                Lizard_BinTree_Insert(ctx, ip);\n                match_num = Lizard_BinTree_GetAllMatches(ctx, ip, matchlimit, last_pos, matches);\n            }\n        }\n\n        LIZARD_LOG_PARSER(\"%d: match_num=%d last_pos=%d\\n\", (int)(ip-source), match_num, last_pos);\n        if (!last_pos && !match_num) { ip++; continue; }\n\n        if (match_num && (size_t)matches[match_num-1].len > sufficient_len) {\n            best_mlen = matches[match_num-1].len;\n            best_off = matches[match_num-1].off;\n            cur = 0;\n            last_pos = 1;\n            goto encode;\n        }\n\n        // set prices using matches at position = 0\n        best_mlen = (last_pos > MINMATCH) ? last_pos : MINMATCH;\n\n        for (i = 0; i < match_num; i++) {\n            mlen = (i>0) ? (size_t)matches[i-1].len+1 : best_mlen;\n            best_mlen = (matches[i].len < LIZARD_OPT_NUM) ? matches[i].len : LIZARD_OPT_NUM;\n            LIZARD_LOG_PARSER(\"%d: start Found mlen=%d off=%d best_mlen=%d last_pos=%d\\n\", (int)(ip-source), matches[i].len, matches[i].off, best_mlen, last_pos);\n            while (mlen <= best_mlen){\n                litlen = 0;\n                price = Lizard_get_price(ctx, ctx->last_off, ip, ctx->off24pos, llen + litlen, matches[i].off, mlen);\n\n                if ((mlen >= minMatchLongOff) || (matches[i].off < LIZARD_MAX_16BIT_OFFSET))\n                if (mlen > last_pos || price < (size_t)opt[mlen].price)\n                    SET_PRICE(mlen, mlen, matches[i].off, litlen, price);\n                mlen++;\n            }\n        }\n\n        if (last_pos < repMinMatch) { ip++; continue; }\n\n        opt[0].off24pos = ctx->off24pos;\n        opt[0].rep = ctx->last_off;\n        opt[0].mlen = 1;\n        opt[0].off = -1;\n\n        // check further positions\n        for (skip_num = 0, cur = 1; cur <= last_pos; cur++) {\n            int rep;\n            inr = ip + cur;\n\n            if (opt[cur-1].off == -1) { // -1 = literals, 0 = rep\n                litlen = opt[cur-1].litlen + 1;\n\n                if (cur != litlen) {\n                    price = opt[cur - litlen].price + Lizard_get_price(ctx, opt[cur-litlen].rep, inr, ctx->off24pos, litlen, 0, 0);\n                    LIZARD_LOG_PRICE(\"%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\\n\", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);\n                } else {\n                    price = Lizard_get_price(ctx, ctx->last_off, inr, ctx->off24pos, llen + litlen, 0, 0);\n                    LIZARD_LOG_PRICE(\"%d: TRY2 price=%d cur=%d litlen=%d llen=%d\\n\", (int)(inr-source), price, cur, litlen, llen);\n                }\n            } else {\n                litlen = 1;\n                price = opt[cur - 1].price + Lizard_get_price(ctx, opt[cur-1].rep, inr, ctx->off24pos, litlen, 0, 0);\n                LIZARD_LOG_PRICE(\"%d: TRY3 price=%d cur=%d litlen=%d litonly=%d\\n\", (int)(inr-source), price, cur, litlen, Lizard_get_price(ctx, rep, inr, ctx->off24pos, litlen, 0, 0));\n            }\n           \n            mlen = 1;\n            best_mlen = 0;\n            LIZARD_LOG_PARSER(\"%d: TRY price=%d opt[%d].price=%d\\n\", (int)(inr-source), price, cur, opt[cur].price);\n\n            if (cur > last_pos || price <= (size_t)opt[cur].price) // || ((price == opt[cur].price) && (opt[cur-1].mlen == 1) && (cur != litlen)))\n                SET_PRICE(cur, mlen, -1, litlen, price);\n\n            if (cur == last_pos) break;\n\n\n\n            /* set rep code */\n            if (opt[cur].off != -1) {\n                mlen = opt[cur].mlen;\n                offset = opt[cur].off;\n                if (offset < 1) {\n                    opt[cur].rep = opt[cur-mlen].rep;\n                    opt[cur].off24pos = opt[cur-mlen].off24pos;\n                    LIZARD_LOG_PARSER(\"%d: COPYREP1 cur=%d mlen=%d rep=%d\\n\", (int)(inr-source), cur, mlen, opt[cur-mlen].rep);\n                } else {\n                    opt[cur].rep = (int)offset;\n                    opt[cur].off24pos = (offset >= LIZARD_MAX_16BIT_OFFSET) ? inr : opt[cur-mlen].off24pos;\n                    LIZARD_LOG_PARSER(\"%d: COPYREP2 cur=%d offset=%d rep=%d\\n\", (int)(inr-source), cur, offset, opt[cur].rep);\n                }\n            } else {\n                opt[cur].rep = opt[cur-1].rep; // copy rep\n                opt[cur].off24pos = opt[cur-1].off24pos;\n            }\n\n            rep = opt[cur].rep;\n            LIZARD_LOG_PARSER(\"%d: CURRENT price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(inr-source), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep); \n\n\n            /* check rep code */\n            if (opt[cur].rep >= lizardOptimalMinOffset) {\n                intptr_t matchIndexLO = (inr - opt[cur].rep) - base;\n                mlen = 0;\n                if ((matchIndexLO >= lowLimit) && (base + matchIndexLO + maxDistance >= inr)) {\n                    if (matchIndexLO >= dictLimit) {\n                        mlen = Lizard_count(inr, base + matchIndexLO, matchlimit);\n                    } else {\n                        mlen = Lizard_count_2segments(inr, dictBase + matchIndexLO, matchlimit, dictEnd, lowPrefixPtr);\n                    }\n                }\n                if (mlen >= REPMINMATCH/* && mlen > best_mlen*/) {\n                    LIZARD_LOG_PARSER(\"%d: try REP rep=%d mlen=%d\\n\", (int)(inr-source), opt[cur].rep, mlen);   \n                    LIZARD_LOG_PARSER(\"%d: Found REP mlen=%d off=%d rep=%d opt[%d].off=%d\\n\", (int)(inr-source), mlen, 0, opt[cur].rep, cur, opt[cur].off);\n\n                    if (mlen > sufficient_len || cur + mlen >= LIZARD_OPT_NUM) {\n                        best_mlen = mlen;\n                        best_off = 0;\n                        LIZARD_LOG_PARSER(\"%d: REP sufficient_len=%d best_mlen=%d best_off=%d last_pos=%d\\n\", (int)(inr-source), sufficient_len, best_mlen, best_off, last_pos);\n                        last_pos = cur + 1;\n                        goto encode;\n                    }\n\n                    best_mlen = mlen;\n                    if (faster_get_matches)\n                        skip_num = best_mlen;\n\n                    do\n                    {\n                        //if (opt[cur].mlen == 1)\n                        if (opt[cur].off == -1) {\n                            litlen = opt[cur].litlen;\n\n                            if (cur != litlen) {\n                                price = opt[cur - litlen].price + Lizard_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen);\n                                LIZARD_LOG_PRICE(\"%d: TRY1 opt[%d].price=%d price=%d cur=%d litlen=%d\\n\", (int)(inr-source), cur - litlen, opt[cur - litlen].price, price, cur, litlen);\n                            } else {\n                                price = Lizard_get_price(ctx, rep, inr, ctx->off24pos, llen + litlen, 0, mlen);\n                                LIZARD_LOG_PRICE(\"%d: TRY2 price=%d cur=%d litlen=%d llen=%d\\n\", (int)(inr-source), price, cur, litlen, llen);\n                            }\n                        } else {\n                            litlen = 0;\n                            price = opt[cur].price + Lizard_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen);\n                            LIZARD_LOG_PRICE(\"%d: TRY3 price=%d cur=%d litlen=%d getprice=%d\\n\", (int)(inr-source), price, cur, litlen, Lizard_get_price(ctx, rep, inr, opt[cur].off24pos, litlen, 0, mlen - MINMATCH));\n                        }\n\n                        LIZARD_LOG_PARSER(\"%d: Found REP mlen=%d off=%d price=%d litlen=%d price[%d]=%d\\n\", (int)(inr-source), mlen, 0, price, litlen, cur - litlen, opt[cur - litlen].price);\n\n                        if (cur + mlen > last_pos || price <= (size_t)opt[cur + mlen].price) // || ((price == opt[cur + mlen].price) && (opt[cur].mlen == 1) && (cur != litlen))) // at equal price prefer REP instead of MATCH\n                            SET_PRICE(cur + mlen, mlen, 0, litlen, price);\n                        mlen--;\n                    }\n                    while (mlen >= REPMINMATCH);\n                }\n            }\n\n            if (faster_get_matches && skip_num > 0) {\n                skip_num--; \n                continue;\n            }\n\n            if (ctx->params.parserType == Lizard_parser_optimalPrice) {\n                Lizard_Insert(ctx, inr);\n                match_num = Lizard_GetAllMatches(ctx, inr, ip, matchlimit, best_mlen, matches);\n                LIZARD_LOG_PARSER(\"%d: Lizard_GetAllMatches match_num=%d\\n\", (int)(inr-source), match_num);\n            } else {\n                Lizard_BinTree_Insert(ctx, inr);\n                match_num = Lizard_BinTree_GetAllMatches(ctx, inr, matchlimit, best_mlen, matches);\n                LIZARD_LOG_PARSER(\"%d: Lizard_BinTree_GetAllMatches match_num=%d\\n\", (int)(inr-source), match_num);\n            }\n\n\n            if (match_num > 0 && (size_t)matches[match_num-1].len > sufficient_len) {\n                cur -= matches[match_num-1].back;\n                best_mlen = matches[match_num-1].len;\n                best_off = matches[match_num-1].off;\n                last_pos = cur + 1;\n                goto encode;\n            }\n\n            // set prices using matches at position = cur\n            best_mlen = (best_mlen > MINMATCH) ? best_mlen : MINMATCH;\n\n            for (i = 0; i < match_num; i++) {\n                mlen = (i>0) ? (size_t)matches[i-1].len+1 : best_mlen;\n                cur2 = cur - matches[i].back;\n                best_mlen = (cur2 + matches[i].len < LIZARD_OPT_NUM) ? (size_t)matches[i].len : LIZARD_OPT_NUM - cur2;\n                LIZARD_LOG_PARSER(\"%d: Found1 cur=%d cur2=%d mlen=%d off=%d best_mlen=%d last_pos=%d\\n\", (int)(inr-source), cur, cur2, matches[i].len, matches[i].off, best_mlen, last_pos);\n\n                if (mlen < (size_t)matches[i].back + 1)\n                    mlen = matches[i].back + 1; \n\n                while (mlen <= best_mlen) {\n                  //  if (opt[cur2].mlen == 1)\n                    if (opt[cur2].off == -1)\n                    {\n                        litlen = opt[cur2].litlen;\n\n                        if (cur2 != litlen)\n                            price = opt[cur2 - litlen].price + Lizard_get_price(ctx, rep, inr, opt[cur2].off24pos, litlen, matches[i].off, mlen);\n                        else\n                            price = Lizard_get_price(ctx, rep, inr, ctx->off24pos, llen + litlen, matches[i].off, mlen);\n                    } else {\n                        litlen = 0;\n                        price = opt[cur2].price + Lizard_get_price(ctx, rep, inr, opt[cur2].off24pos, litlen, matches[i].off, mlen);\n                    }\n\n                    LIZARD_LOG_PARSER(\"%d: Found2 pred=%d mlen=%d best_mlen=%d off=%d price=%d litlen=%d price[%d]=%d\\n\", (int)(inr-source), matches[i].back, mlen, best_mlen, matches[i].off, price, litlen, cur - litlen, opt[cur - litlen].price);\n        //                if (cur2 + mlen > last_pos || ((matches[i].off != opt[cur2 + mlen].off) && (price < opt[cur2 + mlen].price)))\n\n                    if ((mlen >= minMatchLongOff) || (matches[i].off < LIZARD_MAX_16BIT_OFFSET))\n                    if (cur2 + mlen > last_pos || price < (size_t)opt[cur2 + mlen].price)\n                    {\n                        SET_PRICE(cur2 + mlen, mlen, matches[i].off, litlen, price);\n                    }\n\n                    mlen++;\n                }\n            }\n        } //  for (skip_num = 0, cur = 1; cur <= last_pos; cur++)\n\n\n        best_mlen = opt[last_pos].mlen;\n        best_off = opt[last_pos].off;\n        cur = last_pos - best_mlen;\n\n        encode: // cur, last_pos, best_mlen, best_off have to be set\n        for (i = 1; i <= last_pos; i++) {\n            LIZARD_LOG_PARSER(\"%d: price[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep); \n        }\n\n        LIZARD_LOG_PARSER(\"%d: cur=%d/%d best_mlen=%d best_off=%d rep=%d\\n\", (int)(ip-source+cur), cur, last_pos, best_mlen, best_off, opt[cur].rep); \n\n        opt[0].mlen = 1;\n\n        while (1) {\n            mlen = opt[cur].mlen;\n            offset = opt[cur].off;\n            opt[cur].mlen = (int)best_mlen; \n            opt[cur].off = (int)best_off;\n            best_mlen = mlen;\n            best_off = offset;\n            if (mlen > cur) break;\n            cur -= mlen;\n        }\n          \n        for (i = 0; i <= last_pos;) {\n            LIZARD_LOG_PARSER(\"%d: price2[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(ip-source+i), i, last_pos, opt[i].price, opt[i].off, opt[i].mlen, opt[i].litlen, opt[i].rep); \n            i += opt[i].mlen;\n        }\n\n        cur = 0;\n\n        while (cur < last_pos) {\n            LIZARD_LOG_PARSER(\"%d: price3[%d/%d]=%d off=%d mlen=%d litlen=%d rep=%d\\n\", (int)(ip-source+cur), cur, last_pos, opt[cur].price, opt[cur].off, opt[cur].mlen, opt[cur].litlen, opt[cur].rep); \n            mlen = opt[cur].mlen;\n        //            if (mlen == 1) { ip++; cur++; continue; }\n            if (opt[cur].off == -1) { ip++; cur++; continue; }\n            offset = opt[cur].off;\n            cur += mlen;\n\n            LIZARD_LOG_ENCODE(\"%d: ENCODE literals=%d off=%d mlen=%d \", (int)(ip-source), (int)(ip-anchor), (int)(offset), mlen);\n            res = Lizard_encodeSequence(ctx, &ip, &anchor, mlen, ip - offset);\n            if (res) return 0; \n\n            LIZARD_LOG_PARSER(\"%d: offset=%d rep=%d\\n\", (int)(ip-source), offset, ctx->last_off);\n        }\n    }\n\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n\n"
  },
  {
    "path": "NanaZip.Codecs/Lizard/lizard_parser_pricefast.h",
    "content": "﻿#define LIZARD_PRICEFAST_MIN_OFFSET 8\n\nFORCE_INLINE int Lizard_FindMatchFast(Lizard_stream_t* ctx, intptr_t matchIndex, intptr_t matchIndex3, /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const intptr_t dictLimit = ctx->dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const intptr_t maxDistance = (1 << ctx->params.windowLog) - 1;\n    const intptr_t current = (U32)(ip - base);\n    const intptr_t lowLimit = ((intptr_t)ctx->lowLimit + maxDistance >= current) ? (intptr_t)ctx->lowLimit : current - maxDistance;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    const BYTE* match, *matchDict;\n    size_t ml=0, mlt;\n\n    if (ctx->last_off >= LIZARD_PRICEFAST_MIN_OFFSET) {\n        intptr_t matchIndexLO = (ip - ctx->last_off) - base;\n        if (matchIndexLO >= lowLimit) {\n            if (matchIndexLO >= dictLimit) {\n                match = base + matchIndexLO;\n                if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {\n                    mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                 //   if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) \n                    {\n                        *matchpos = match;\n                        return (int)mlt;\n                    }\n                }\n            } else {\n                match = dictBase + matchIndexLO;\n                if ((U32)((dictLimit-1) - matchIndexLO) >= 3)  /* intentional overflow */\n                if (MEM_readMINMATCH(match) == MEM_readMINMATCH(ip)) {\n                    mlt = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                 //   if ((mlt >= minMatchLongOff) || (ctx->last_off < LIZARD_MAX_16BIT_OFFSET)) \n                    {\n                        *matchpos = base + matchIndexLO;  /* virtual matchpos */\n                        return (int)mlt;\n                    }\n                }\n            }\n        }\n    }\n\n\n#if MINMATCH == 3\n    if (matchIndex3 < current && matchIndex3 >= lowLimit) {\n        intptr_t offset = current - matchIndex3;\n        if (offset < LIZARD_MAX_8BIT_OFFSET) {\n            match = ip - offset;\n            if (match > base && MEM_readMINMATCH(ip) == MEM_readMINMATCH(match)) {\n                ml = 3;//Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                *matchpos = match;\n            }\n        }\n    }\n#else\n    (void)matchIndex3;\n#endif\n\n    if ((matchIndex < current) && (matchIndex >= lowLimit)) {\n        match = base + matchIndex;\n        if ((U32)(ip - match) >= LIZARD_PRICEFAST_MIN_OFFSET) {\n            if (matchIndex >= dictLimit) {\n                if (*(match+ml) == *(ip+ml) && (MEM_read32(match) == MEM_read32(ip))) {\n                    mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (!ml || (mlt > ml)) // && Lizard_better_price((ip - *matchpos), ml, (ip - match), mlt, ctx->last_off)))\n                    { ml = mlt; *matchpos = match; }\n                }\n            } else {\n                matchDict = dictBase + matchIndex;\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_read32(matchDict) == MEM_read32(ip)) {\n                    mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    if (!ml || (mlt > ml)) // && Lizard_better_price((ip - *matchpos), ml, (U32)(ip - match), mlt, ctx->last_off)))\n                    { ml = mlt; *matchpos = match; }   /* virtual matchpos */\n                }\n            }\n        }\n    }\n    \n    return (int)ml;\n}\n\n\nFORCE_INLINE int Lizard_FindMatchFaster (Lizard_stream_t* ctx, U32 matchIndex,  /* Index table will be updated */\n                                               const BYTE* ip, const BYTE* const iLimit,\n                                               const BYTE** matchpos)\n{\n    const BYTE* const base = ctx->base;\n    const BYTE* const dictBase = ctx->dictBase;\n    const U32 dictLimit = ctx->dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const U32 maxDistance = (1 << ctx->params.windowLog) - 1;\n    const U32 current = (U32)(ip - base);\n    const U32 lowLimit = (ctx->lowLimit + maxDistance >= current) ? ctx->lowLimit : current - maxDistance;\n    const BYTE* const lowPrefixPtr = base + dictLimit;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    const BYTE* match, *matchDict;\n    size_t ml=0, mlt;\n\n    if (matchIndex < current && matchIndex >= lowLimit) {\n        match = base + matchIndex;\n        if ((U32)(ip - match) >= LIZARD_PRICEFAST_MIN_OFFSET) {\n            if (matchIndex >= dictLimit) {\n                if (MEM_read32(match) == MEM_read32(ip)) {\n                    mlt = Lizard_count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    { ml = mlt; *matchpos = match; }\n                }\n            } else {\n                matchDict = dictBase + matchIndex;\n                if ((U32)((dictLimit-1) - matchIndex) >= 3)  /* intentional overflow */\n                if (MEM_read32(matchDict) == MEM_read32(ip)) {\n                    mlt = Lizard_count_2segments(ip+MINMATCH, matchDict+MINMATCH, iLimit, dictEnd, lowPrefixPtr) + MINMATCH;\n                    if ((mlt >= minMatchLongOff) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))\n                    { ml = mlt; *matchpos = match; }   /* virtual matchpos */\n                }\n            }\n        }\n    }\n    \n    return (int)ml;\n}\n\n\n\nFORCE_INLINE int Lizard_compress_priceFast(\n        Lizard_stream_t* const ctx,\n        const BYTE* ip,\n        const BYTE* const iend)\n{\n    const BYTE* anchor = ip;\n    const BYTE* const mflimit = iend - MFLIMIT;\n    const BYTE* const matchlimit = (iend - LASTLITERALS);\n\n    size_t ml, ml2=0;\n    const BYTE* ref=NULL;\n    const BYTE* start2=NULL;\n    const BYTE* ref2=NULL;\n    const BYTE* lowPrefixPtr = ctx->base + ctx->dictLimit;\n    U32* HashTable  = ctx->hashTable;\n#if MINMATCH == 3\n    U32* HashTable3  = ctx->hashTable3;\n#endif \n    const BYTE* const base = ctx->base;\n    const size_t minMatchLongOff = ctx->params.minMatchLongOff;\n    U32* HashPos;\n\n    /* init */\n    ip++;\n\n    /* Main Loop */\n    while (ip < mflimit)\n    {\n        HashPos = &HashTable[Lizard_hashPtr(ip, ctx->params.hashLog, ctx->params.searchLength)];\n#if MINMATCH == 3\n        {\n        U32* HashPos3 = &HashTable3[Lizard_hash3Ptr(ip, ctx->params.hashLog3)];\n        ml = Lizard_FindMatchFast (ctx, *HashPos, *HashPos3, ip, matchlimit, (&ref));\n        *HashPos3 = (U32)(ip - base);\n        }\n#else\n        ml = Lizard_FindMatchFast (ctx, *HashPos, 0, ip, matchlimit, (&ref));\n#endif \n        if ((*HashPos >= (U32)(ip - base)) || ((U32)(ip - base) >= *HashPos + LIZARD_PRICEFAST_MIN_OFFSET))\n            *HashPos = (U32)(ip - base);\n\n        if (!ml) { ip++; continue; }\n        if ((int)(ip - ref) == ctx->last_off) { ml2=0; ref=ip; goto _Encode; }\n\n        {\n        int back = 0;\n        while ((ip+back>anchor) && (ref+back > lowPrefixPtr) && (ip[back-1] == ref[back-1])) back--;\n        ml -= back;\n        ip += back;\n        ref += back;\n        }\n        \n_Search:\n        if (ip+ml >= mflimit) goto _Encode;\n\n        start2 = ip + ml - 2;\n        HashPos = &HashTable[Lizard_hashPtr(start2, ctx->params.hashLog, ctx->params.searchLength)];\n        ml2 = Lizard_FindMatchFaster(ctx, *HashPos, start2, matchlimit, (&ref2));      \n        if ((*HashPos >= (U32)(start2 - base)) || ((U32)(start2 - base) >= *HashPos + LIZARD_PRICEFAST_MIN_OFFSET))\n            *HashPos = (U32)(start2 - base);\n\n        if (!ml2) goto _Encode;\n\n        {\n        int back = 0;\n        while ((start2+back>ip) && (ref2+back > lowPrefixPtr) && (start2[back-1] == ref2[back-1])) back--;\n        ml2 -= back;\n        start2 += back;\n        ref2 += back;\n        }\n\n        if (ml2 <= ml) { ml2 = 0; goto _Encode; }\n\n        if (start2 <= ip)\n        {\n\n            ip = start2; ref = ref2; ml = ml2;\n            ml2 = 0;\n            goto _Encode;\n        }\n\n        if (start2 - ip < 3) \n        { \n            ip = start2; ref = ref2; ml = ml2;\n            ml2 = 0; \n            goto _Search; \n        }\n\n        if (start2 < ip + ml) \n        {\n            size_t correction = ml - (int)(start2 - ip);\n            start2 += correction;\n            ref2 += correction;\n            ml2 -= correction;\n            if (ml2 < 3) { ml2 = 0; }\n            if ((ml2 < minMatchLongOff) && ((U32)(start2 - ref2) >= LIZARD_MAX_16BIT_OFFSET))  { ml2 = 0; }\n        }\n\n_Encode:\n        if (Lizard_encodeSequence_LIZv1(ctx, &ip, &anchor, ml, ref)) goto _output_error;\n\n        if (ml2)\n        {\n            ip = start2; ref = ref2; ml = ml2;\n            ml2 = 0;\n            goto _Search;\n        }\n    }\n\n    /* Encode Last Literals */\n    ip = iend;\n    if (Lizard_encodeLastLiterals_LIZv1(ctx, &ip, &anchor)) goto _output_error;\n\n    /* End */\n    return 1;\n_output_error:\n    return 0;\n}\n\n"
  },
  {
    "path": "NanaZip.Codecs/Mile.Helpers.Portable.Base.Unstaged.cpp",
    "content": "﻿/*\n * PROJECT:    Mouri Internal Library Essentials\n * FILE:       Mile.Helpers.Portable.Base.Unstaged.cpp\n * PURPOSE:    Implementation for unstaged portable essential helper functions\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\nEXTERN_C MO_UINT8 MileReadUInt8(\n    _In_ MO_CONSTANT_POINTER BaseAddress)\n{\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n    return Base[0];\n}\n\nEXTERN_C MO_UINT16 MileReadUInt16BigEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress)\n{\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n    return\n        (static_cast<MO_UINT16>(Base[0]) << 8) |\n        (static_cast<MO_UINT16>(Base[1]));\n}\n\nEXTERN_C MO_UINT16 MileReadUInt16LittleEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress)\n{\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n    return\n        (static_cast<MO_UINT16>(Base[0])) |\n        (static_cast<MO_UINT16>(Base[1]) << 8);\n}\n\nEXTERN_C MO_UINT32 MileReadUInt32BigEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress)\n{\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n    return\n        (static_cast<MO_UINT32>(Base[0]) << 24) |\n        (static_cast<MO_UINT32>(Base[1]) << 16) |\n        (static_cast<MO_UINT32>(Base[2]) << 8) |\n        (static_cast<MO_UINT32>(Base[3]));\n}\n\nEXTERN_C MO_UINT32 MileReadUInt32LittleEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress)\n{\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n    return\n        (static_cast<MO_UINT32>(Base[0])) |\n        (static_cast<MO_UINT32>(Base[1]) << 8) |\n        (static_cast<MO_UINT32>(Base[2]) << 16) |\n        (static_cast<MO_UINT32>(Base[3]) << 24);\n}\n\n\nEXTERN_C MO_UINT64 MileReadUInt64BigEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress)\n{\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n    return\n        (static_cast<MO_UINT64>(Base[0]) << 56) |\n        (static_cast<MO_UINT64>(Base[1]) << 48) |\n        (static_cast<MO_UINT64>(Base[2]) << 40) |\n        (static_cast<MO_UINT64>(Base[3]) << 32) |\n        (static_cast<MO_UINT64>(Base[4]) << 24) |\n        (static_cast<MO_UINT64>(Base[5]) << 16) |\n        (static_cast<MO_UINT64>(Base[6]) << 8) |\n        (static_cast<MO_UINT64>(Base[7]));\n}\n\nEXTERN_C MO_UINT64 MileReadUInt64LittleEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress)\n{\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n    return\n        (static_cast<MO_UINT64>(Base[0])) |\n        (static_cast<MO_UINT64>(Base[1]) << 8) |\n        (static_cast<MO_UINT64>(Base[2]) << 16) |\n        (static_cast<MO_UINT64>(Base[3]) << 24) |\n        (static_cast<MO_UINT64>(Base[4]) << 32) |\n        (static_cast<MO_UINT64>(Base[5]) << 40) |\n        (static_cast<MO_UINT64>(Base[6]) << 48) |\n        (static_cast<MO_UINT64>(Base[7]) << 56);\n}\n\nEXTERN_C MO_INT8 MileSequenceCompare8(\n    _In_ MO_UINT8 Left,\n    _In_ MO_UINT8 Right)\n{\n    return static_cast<MO_INT8>(static_cast<MO_UINT8>(Left - Right));\n}\n\nEXTERN_C MO_INT16 MileSequenceCompare16(\n    _In_ MO_UINT16 Left,\n    _In_ MO_UINT16 Right)\n{\n    return static_cast<MO_INT16>(static_cast<MO_UINT16>(Left - Right));\n}\n\nEXTERN_C MO_INT32 MileSequenceCompare32(\n    _In_ MO_UINT32 Left,\n    _In_ MO_UINT32 Right)\n{\n    return static_cast<MO_INT32>(static_cast<MO_UINT32>(Left - Right));\n}\n\nEXTERN_C MO_INT64 MileSequenceCompare64(\n    _In_ MO_UINT64 Left,\n    _In_ MO_UINT64 Right)\n{\n    return static_cast<MO_INT64>(static_cast<MO_UINT64>(Left - Right));\n}\n\nEXTERN_C MO_UINT8 MileDecodeLeb128(\n    _In_ MO_CONSTANT_POINTER BaseAddress,\n    _In_ MO_UINT8 MaximumBits,\n    _In_ MO_BOOL SignedMode,\n    _Out_ PMO_UINT64 OutputValue)\n{\n    if (!BaseAddress || MaximumBits < 1 || MaximumBits > 64 || !OutputValue)\n    {\n        // Invalid parameters.\n        return 0;\n    }\n    *OutputValue = 0;\n\n    if (1 == MaximumBits && SignedMode)\n    {\n        // Signed mode with 1 bit is not valid.\n        return 0;\n    }\n\n    MO_UINT8 MaximumByteCount = (MaximumBits + 6) / 7;\n\n    MO_UINT8 MaximumByteValidBits = MaximumBits % 7;\n    if (MaximumByteValidBits == 0)\n    {\n        // If the maximum bits is a multiple of 7, we can use all 7 bits of the\n        // last byte.\n        MaximumByteValidBits = 7;\n    }\n\n    MO_UINT8 MaximumByteMask = (1 << MaximumByteValidBits) - 1;\n\n    CONST MO_UINT8* Base = reinterpret_cast<CONST MO_UINT8*>(BaseAddress);\n\n    MO_UINT64 Value = 0;\n    MO_UINT8 Index = 0;\n    MO_UINT8 Shift = 0;\n    MO_UINT8 Byte = 0;\n    for (;;)\n    {\n        if (!(Index < MaximumByteCount))\n        {\n            // Exceeded maximum bytes.\n            return 0;\n        }\n\n        Byte = Base[Index++];\n        Value |= static_cast<MO_UINT64>(Byte & 0x7F) << Shift;\n        Shift += 7;\n        if (!(Byte & 0x80))\n        {\n            // No more bytes.\n            break;\n        }\n    }\n\n    if (SignedMode)\n    {\n        if (Shift < MaximumBits)\n        {\n            // Sign extend, second-highest bit is the sign bit\n            if (Byte & 0x40)\n            {\n                Value |= static_cast<MO_UINT64>(-1) << Shift;\n            }\n        }\n        else\n        {\n            // Clear the top bits beyond MaximumBits.\n            Value &= (static_cast<MO_UINT64>(1) << MaximumBits) - 1;\n\n            MO_UINT8 SignBitMask = (1 << (MaximumByteValidBits - 1));\n            MO_UINT8 TopBitsMask = ~MaximumByteMask;\n            MO_UINT8 TopBitsValue = 0x7F - MaximumByteMask;\n\n            MO_BOOL IsSignBitSet = (Byte & SignBitMask);\n            MO_UINT8 TopBits = (Byte & TopBitsMask);\n            if ((IsSignBitSet && TopBitsValue != TopBits) ||\n                (!IsSignBitSet && 0 != TopBits))\n            {\n                // Overflow.\n                return 0;\n            }\n\n            if (IsSignBitSet)\n            {\n                // Sign extend the value if the sign bit is set.\n                if (Value & (static_cast<MO_UINT64>(1) << (MaximumBits - 1)))\n                {\n                    Value |= static_cast<MO_UINT64>(-1) << MaximumBits;\n                }\n            }\n        }\n    }\n    else\n    {\n        if (!(Shift < MaximumBits))\n        {\n            if (Byte & ~MaximumByteMask)\n            {\n                // Overflow.\n                return 0;\n            }\n        }\n    }\n\n    *OutputValue = Value;\n    return Index;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Mile.Helpers.Portable.Base.Unstaged.h",
    "content": "﻿/*\n * PROJECT:    Mouri Internal Library Essentials\n * FILE:       Mile.Helpers.Portable.Base.Unstaged.h\n * PURPOSE:    Definition for unstaged portable essential helper functions\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef MILE_PORTABLE_HELPERS_BASE_UNSTAGED\n#define MILE_PORTABLE_HELPERS_BASE_UNSTAGED\n\n#include <Mile.Mobility.Portable.Types.h>\n#ifndef MILE_MOBILITY_ENABLE_MINIMUM_SAL\n#include <sal.h>\n#endif // !MILE_MOBILITY_ENABLE_MINIMUM_SAL\n\n/**\n * @brief Reads an unsigned 8-bit integer from the specified memory address.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least 1 byte of\n*                     readable memory.\n * @return The unsigned 8-bit integer value.\n */\nEXTERN_C MO_UINT8 MileReadUInt8(\n    _In_ MO_CONSTANT_POINTER BaseAddress);\n\n/**\n * @brief Reads an unsigned 16-bit integer from the specified memory address in\n *        big-endian byte order.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least 2 bytes of\n*                     readable memory.\n * @return The unsigned 16-bit integer value.\n */\nEXTERN_C MO_UINT16 MileReadUInt16BigEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress);\n\n/**\n * @brief Reads an unsigned 16-bit integer from the specified memory address in\n *        little-endian byte order.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least 2 bytes of\n*                     readable memory.\n * @return The unsigned 16-bit integer value.\n */\nEXTERN_C MO_UINT16 MileReadUInt16LittleEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress);\n\n/**\n * @brief Reads an unsigned 32-bit integer from the specified memory address in\n *        big-endian byte order.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least 4 bytes of\n*                     readable memory.\n * @return The unsigned 32-bit integer value.\n */\nEXTERN_C MO_UINT32 MileReadUInt32BigEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress);\n\n/**\n * @brief Reads an unsigned 32-bit integer from the specified memory address in\n *        little-endian byte order.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least 4 bytes of\n*                     readable memory.\n * @return The unsigned 32-bit integer value.\n */\nEXTERN_C MO_UINT32 MileReadUInt32LittleEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress);\n\n/**\n * @brief Reads an unsigned 64-bit integer from the specified memory address in\n *        big-endian byte order.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least 8 bytes of\n*                     readable memory.\n * @return The unsigned 64-bit integer value.\n */\nEXTERN_C MO_UINT64 MileReadUInt64BigEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress);\n\n/**\n * @brief Reads an unsigned 64-bit integer from the specified memory address in\n *        little-endian byte order.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least 8 bytes of\n*                     readable memory.\n * @return The unsigned 64-bit integer value.\n */\nEXTERN_C MO_UINT64 MileReadUInt64LittleEndian(\n    _In_ MO_CONSTANT_POINTER BaseAddress);\n\n/**\n * @brief Calculates the distance between two 8-bit unsigned integers Left and\n *        Right with sequence comparison which ignores overflow.\n * @param Left The left operand you want to calculate the distance.\n * @param Right The right operand you want to calculate the distance.\n * @return The distance between Left and Right as an 8-bit signed integer, where\n *         a positive value indicates Left is greater than Right, a negative\n *         value indicates Left is less than Right, and zero indicates they are\n *         equal.\n */\nEXTERN_C MO_INT8 MileSequenceCompare8(\n    _In_ MO_UINT8 Left,\n    _In_ MO_UINT8 Right);\n\n/**\n * @brief Calculates the distance between two 16-bit unsigned integers Left and\n *        Right with sequence comparison which ignores overflow.\n * @param Left The left operand you want to calculate the distance.\n * @param Right The right operand you want to calculate the distance.\n * @return The distance between Left and Right as a 16-bit signed integer, where\n *         a positive value indicates Left is greater than Right, a negative\n *         value indicates Left is less than Right, and zero indicates they are\n *         equal.\n */\nEXTERN_C MO_INT16 MileSequenceCompare16(\n    _In_ MO_UINT16 Left,\n    _In_ MO_UINT16 Right);\n\n/**\n * @brief Calculates the distance between two 32-bit unsigned integers Left and\n *        Right with sequence comparison which ignores overflow.\n * @param Left The left operand you want to calculate the distance.\n * @param Right The right operand you want to calculate the distance.\n * @return The distance between Left and Right as a 32-bit signed integer, where\n *         a positive value indicates Left is greater than Right, a negative\n *         value indicates Left is less than Right, and zero indicates they are\n *         equal.\n */\nEXTERN_C MO_INT32 MileSequenceCompare32(\n    _In_ MO_UINT32 Left,\n    _In_ MO_UINT32 Right);\n\n/**\n * @brief Calculates the distance between two 64-bit unsigned integers Left and\n *        Right with sequence comparison which ignores overflow.\n * @param Left The left operand you want to calculate the distance.\n * @param Right The right operand you want to calculate the distance.\n * @return The distance between Left and Right as a 64-bit signed integer, where\n *         a positive value indicates Left is greater than Right, a negative\n *         value indicates Left is less than Right, and zero indicates they are\n *         equal.\n */\nEXTERN_C MO_INT64 MileSequenceCompare64(\n    _In_ MO_UINT64 Left,\n    _In_ MO_UINT64 Right);\n\n/**\n * @brief Decodes a LEB128-encoded value from the specified memory address.\n * @param BaseAddress The memory address to read. The caller must ensure that\n *                    the memory address is valid with at least\n *                    ((MaximumBits + 6) / 7) bytes of readable memory.\n * @param MaximumBits The maximum number of bits for the decoded value. This\n *                    must be between 1 and 64,\n * @param SignedMode If true, the value is treated as a signed integer; otherwise,\n *                   the value is treated as an unsigned integer.\n * @param OutputValue The memory address to store the decoded value. The caller\n *                    must ensure that the memory address is valid with at least\n *                    8 bytes of writable memory.\n * @return The number of processed bytes, or 0 if the decoding failed due to\n *         invalid parameters, overflow, or exceeding the maximum bits.\n */\nEXTERN_C MO_UINT8 MileDecodeLeb128(\n    _In_ MO_CONSTANT_POINTER BaseAddress,\n    _In_ MO_UINT8 MaximumBits,\n    _In_ MO_BOOL SignedMode,\n    _Out_ PMO_UINT64 OutputValue);\n\n#endif // !MILE_PORTABLE_HELPERS_BASE_UNSTAGED\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Archive.DotNetSingleFile.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Archive.DotNetSingleFile.cpp\n * PURPOSE:    Implementation for .NET Single File Application readonly support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\n#include <map>\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\nnamespace\n{\n    struct PropertyItem\n    {\n        PROPID Property;\n        VARTYPE Type;\n    };\n\n    const PropertyItem g_ArchivePropertyItems[] =\n    {\n        { SevenZipArchiveUnpackVersion, VT_UI8 },\n    };\n\n    const std::size_t g_ArchivePropertyItemsCount =\n        sizeof(g_ArchivePropertyItems) / sizeof(*g_ArchivePropertyItems);\n\n    const PropertyItem g_PropertyItems[] =\n    {\n        { SevenZipArchivePath, VT_BSTR },\n        { SevenZipArchiveSize, VT_UI8 },\n        { SevenZipArchivePackSize, VT_UI8 },\n    };\n\n    const std::size_t g_PropertyItemsCount =\n        sizeof(g_PropertyItems) / sizeof(*g_PropertyItems);\n\n    // Reference in https://github.com/dotnet/runtime/tree/v9.0.1.\n    // - src/native/corehost/apphost/bundle_marker.cpp\n    // - src/native/corehost/bundle/file_entry.h\n    // - src/native/corehost/bundle/file_type.h\n    // - src/native/corehost/bundle/header.h\n    // - src/installer/managed/Microsoft.NET.HostModel/Bundle/FileType.cs\n    // - src/installer/managed/Microsoft.NET.HostModel/Bundle/Manifest.cs\n    //\n    // FileEntry: Records information about embedded files.\n    //\n    // The bundle manifest records the following meta-data for each\n    // file embedded in the bundle:\n    // Fixed size portion (file_entry_fixed_t)\n    //   - Offset\n    //   - Size\n    //   - CompressedSize  - only in bundleVersion 6+\n    //   - File Entry Type\n    // Variable Size portion\n    //   - relative path (7-bit extension encoded length prefixed string)\n    //\n    // The Bundle Header (v1)\n    // Fixed size thunk (header_fixed_t)\n    //   - Major Version\n    //   - Minor Version\n    //   - Number of embedded files\n    // Variable size portion:\n    //   - Bundle ID (7-bit extension encoded length prefixed string)\n    // The Bundle Header (v2) [additional content]\n    // Fixed size thunk (header_fixed_v2_t)\n    //   - DepsJson Location (Offset, Size)\n    //   - RuntimeConfig Location (Offset, Size)\n    //   - Flags\n\n    const std::uint8_t g_BundleSignature[] =\n    {\n        // Represent the bundle signature: SHA-256 for \".net core bundle\"\n        0x8b, 0x12, 0x02, 0xb9, 0x6a, 0x61, 0x20, 0x38,\n        0x72, 0x7b, 0x93, 0x02, 0x14, 0xd7, 0xa0, 0x32,\n        0x13, 0xf5, 0xb9, 0xe6, 0xef, 0xae, 0x33, 0x18,\n        0xee, 0x3b, 0x2d, 0xce, 0x24, 0xb3, 0x6a, 0xae\n    };\n\n    // Set the signature search buffer size to 20 MiB because .NET AppHost\n    // which contained the signature should smaller than 20 MiB in the current\n    // implementations.\n    const std::size_t g_SignatureSearchBufferSize = 20 << 20;\n\n    /**\n     * @brief Identifies the type of file embedded into the bundle. The bundler\n     *        differentiates a few kinds of files via the manifest, with respect\n     *        to the way in which they'll be used by the runtime.\n     */\n    enum BundleFileType : std::uint8_t\n    {\n        /**\n         * @brief Type not determined.\n         */\n        Unknown,\n        /**\n         * @brief IL and R2R Assemblies\n         */\n        Assembly,\n        /**\n         * @brief Native Binaries\n         */\n        NativeBinary,\n        /**\n         * @brief .deps.json configuration file\n         */\n        DepsJson,\n        /**\n         * @brief .runtimeconfig.json configuration file\n         */\n        RuntimeConfigJson,\n        /**\n         * @brief PDB Files\n         */\n        Symbols,\n        /**\n         * @brief The counter of file types, must be the last one.\n         */\n        TypeCount,\n    };\n\n    struct BundleFileEntry\n    {\n        std::int64_t Offset = 0;\n        std::int64_t Size = 0;\n        std::int64_t CompressedSize = 0; // Only in bundleVersion 6+\n        BundleFileType Type = BundleFileType::Unknown;\n        std::string RelativePath;\n    };\n\n    enum BundleFileHeaderFlags : std::uint64_t\n    {\n        None = 0,\n        /**\n         * @brief NetcoreApp3CompatMode flag is set on a .net5+ app, which\n         *        chooses to build single-file apps in .netcore3.x compat mode.\n         *        This indicates that:\n         *        - All published files are bundled into the app; some of them\n         *          will be extracted to disk.\n         *        - AppContext.BaseDirectory is set to the extraction directory\n         *          (and not the AppHost directory).\n         *        This mode is expected to be deprecated in future versions of\n         *        .NET.\n         */\n        NetcoreApp3CompatMode = 1\n    };\n\n    struct BundleFileLocation\n    {\n        std::int64_t Offset = 0;\n        std::int64_t Size = 0;\n    };\n\n    struct BundleFileHeader\n    {\n        std::uint32_t MajorVersion = 0;\n        std::uint32_t MinorVersion = 0;\n        std::int32_t NumberOfEmbeddedFiles = 0;\n        /**\n         * @brief Bundle ID is a string that is used to uniquely identify this\n         *        bundle. It is chosen to be compatible with path-names so that\n         *        the AppHost can use it in extraction path.\n         */\n        std::string BundleId;\n        BundleFileLocation DepsJsonLocation;\n        BundleFileLocation RuntimeConfigLocation;\n        BundleFileHeaderFlags Flags = BundleFileHeaderFlags::None;\n    };\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    struct DotNetSingleFile :\n        public Mile::ComObject<DotNetSingleFile, IInArchive>\n    {\n    private:\n\n        IInStream* m_FileStream = nullptr;\n        std::uint64_t m_FullSize = 0;\n        std::uint32_t m_MajorVersion = 0;\n        std::vector<BundleFileEntry> m_FilePaths;\n        bool m_IsInitialized = false;\n\n    private:\n\n        std::uint8_t ReadUInt8(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt8(BaseAddress);\n        }\n\n        std::uint16_t ReadUInt16(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt16LittleEndian(BaseAddress);\n        }\n\n        std::uint32_t ReadUInt32(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt32LittleEndian(BaseAddress);\n        }\n\n        std::uint64_t ReadUInt64(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt64LittleEndian(BaseAddress);\n        }\n\n        std::int8_t ReadInt8(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int8_t>(this->ReadUInt8(BaseAddress));\n        }\n\n        std::int16_t ReadInt16(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int16_t>(this->ReadUInt16(BaseAddress));\n        }\n\n        std::int32_t ReadInt32(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int32_t>(this->ReadUInt32(BaseAddress));\n        }\n\n        std::int64_t ReadInt64(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int64_t>(this->ReadUInt64(BaseAddress));\n        }\n\n        void ValidateBound(\n            std::size_t Size,\n            std::size_t Start,\n            std::size_t Length)\n        {\n            if (Size < Start || Size - Start < Length)\n            {\n                throw std::exception();\n            }\n        }\n\n        HRESULT ReadFileStream(\n            _In_ INT64 Offset,\n            _Out_ PVOID Buffer,\n            _In_ SIZE_T NumberOfBytesToRead)\n        {\n            if (!this->m_FileStream)\n            {\n                return S_FALSE;\n            }\n\n            if (SUCCEEDED(this->m_FileStream->Seek(\n                Offset,\n                STREAM_SEEK_SET,\n                nullptr)))\n            {\n                SIZE_T NumberOfBytesRead = 0;\n                if (SUCCEEDED(::NanaZipCodecsReadInputStream(\n                    this->m_FileStream,\n                    Buffer,\n                    NumberOfBytesToRead,\n                    &NumberOfBytesRead)))\n                {\n                    if (NumberOfBytesToRead == NumberOfBytesRead)\n                    {\n                        return S_OK;\n                    }\n                }\n            }\n\n            return S_FALSE;\n        }\n\n    public:\n\n        DotNetSingleFile()\n        {\n\n        }\n\n        HRESULT STDMETHODCALLTYPE Open(\n            _In_ IInStream* Stream,\n            _In_opt_ const PUINT64 MaxCheckStartPosition,\n            _In_opt_ IArchiveOpenCallback* OpenCallback)\n        {\n            UNREFERENCED_PARAMETER(MaxCheckStartPosition);\n            UNREFERENCED_PARAMETER(OpenCallback);\n\n            if (!Stream)\n            {\n                return E_INVALIDARG;\n            }\n\n            HRESULT hr = S_FALSE;\n\n            do\n            {\n                this->Close();\n\n                this->m_FileStream = Stream;\n                this->m_FileStream->AddRef();\n\n                UINT64 BundleSize = 0;\n                if (FAILED(this->m_FileStream->Seek(\n                    0,\n                    STREAM_SEEK_END,\n                    &BundleSize)))\n                {\n                    break;\n                }\n\n                const std::size_t MinimumOffset =\n                    (2 * sizeof(std::uint8_t)) + sizeof(std::uint64_t);\n\n                if (BundleSize < sizeof(g_BundleSignature) + MinimumOffset)\n                {\n                    break;\n                }\n\n                std::size_t SearchBufferSize = static_cast<std::size_t>(\n                    BundleSize < g_SignatureSearchBufferSize\n                    ? BundleSize\n                    : g_SignatureSearchBufferSize);\n\n                std::vector<std::uint8_t> SearchBuffer(SearchBufferSize);\n                if (FAILED(this->ReadFileStream(\n                    0,\n                    &SearchBuffer[0],\n                    SearchBufferSize)))\n                {\n                    break;\n                }\n\n                if ('M' != SearchBuffer[0] || 'Z' != SearchBuffer[1])\n                {\n                    break;\n                }\n\n                // According to the .NET Single File Application bundle design,\n                // the signature should be located at the executable stub, which\n                // is beginning of the bundle.\n                std::size_t MaximumSearchOffset =\n                    SearchBufferSize - sizeof(g_BundleSignature);\n\n                std::size_t BundleHeaderOffset = 0;\n\n                // Initial value is skip 'M', 'Z' and the bundle header offset.\n                for (size_t i = MinimumOffset; i < MaximumSearchOffset; ++i)\n                {\n                    if (g_BundleSignature[0] != SearchBuffer[i])\n                    {\n                        continue;\n                    }\n\n                    if (0 != std::memcmp(\n                        &SearchBuffer[i],\n                        g_BundleSignature,\n                        sizeof(g_BundleSignature)))\n                    {\n                        continue;\n                    }\n\n                    std::int64_t RawCandidate = this->ReadInt64(\n                        &SearchBuffer[i - sizeof(std::int64_t)]);\n                    if (0 >= RawCandidate)\n                    {\n                        // Must be a positive number according to the .NET\n                        // Single File Application bundle design.\n                        continue;\n                    }\n                    std::size_t Candidate = RawCandidate;\n                    std::size_t SignatureEnd = i + sizeof(g_BundleSignature);\n                    if (Candidate < SignatureEnd || Candidate > BundleSize)\n                    {\n                        // According to the .NET Single File Application bundle\n                        // design, the bundle header should be located (much)\n                        // after the signature and the bundle header offset\n                        // should be within the bundle.\n                        continue;\n                    }\n\n                    BundleHeaderOffset = Candidate;\n                }\n                SearchBuffer.clear();\n                if (!BundleHeaderOffset)\n                {\n                    // Invalid .NET Single File Application bundle.\n                    break;\n                }\n\n                std::size_t HeaderBufferSize = static_cast<std::size_t>(\n                    BundleSize - BundleHeaderOffset);\n\n                std::vector<std::uint8_t> HeaderBuffer(HeaderBufferSize);\n                if (FAILED(this->ReadFileStream(\n                    BundleHeaderOffset,\n                    &HeaderBuffer[0],\n                    HeaderBufferSize)))\n                {\n                    break;\n                }\n\n                BundleFileHeader Header;\n                std::map<std::string, BundleFileEntry> Files;\n\n                try\n                {\n                    std::size_t Current = 0;\n                    this->ValidateBound(\n                        HeaderBufferSize,\n                        Current,\n                        sizeof(std::uint32_t));\n                    Header.MajorVersion =\n                        this->ReadUInt32(&HeaderBuffer[Current]);\n                    this->m_MajorVersion = Header.MajorVersion;\n                    Current += sizeof(std::uint32_t);\n                    this->ValidateBound(\n                        HeaderBufferSize,\n                        Current,\n                        sizeof(std::uint32_t));\n                    Header.MinorVersion =\n                        this->ReadUInt32(&HeaderBuffer[Current]);\n                    Current += sizeof(std::uint32_t);\n                    this->ValidateBound(\n                        HeaderBufferSize,\n                        Current,\n                        sizeof(std::int32_t));\n                    Header.NumberOfEmbeddedFiles =\n                        this->ReadInt32(&HeaderBuffer[Current]);\n                    if (Header.NumberOfEmbeddedFiles <= 0)\n                    {\n                        // Invalid number of embedded files.\n                        throw std::exception();\n                    }\n                    Current += sizeof(std::int32_t);\n                    this->ValidateBound(\n                        HeaderBufferSize,\n                        Current,\n                        sizeof(std::uint8_t));\n                    std::uint8_t BundleIdLength =\n                        this->ReadUInt8(&HeaderBuffer[Current]);\n                    Current += sizeof(std::uint8_t);\n                    this->ValidateBound(\n                        HeaderBufferSize,\n                        Current,\n                        BundleIdLength);\n                    Header.BundleId = std::string(\n                        reinterpret_cast<char*>(&HeaderBuffer[Current]),\n                        BundleIdLength);\n                    Current += BundleIdLength;\n                    if (Header.MajorVersion >= 2)\n                    {\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::int64_t));\n                        Header.DepsJsonLocation.Offset =\n                            this->ReadInt64(&HeaderBuffer[Current]);\n                        Current += sizeof(std::int64_t);\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::int64_t));\n                        Header.DepsJsonLocation.Size =\n                            this->ReadInt64(&HeaderBuffer[Current]);\n                        Current += sizeof(std::int64_t);\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::int64_t));\n                        Header.RuntimeConfigLocation.Offset =\n                            this->ReadInt64(&HeaderBuffer[Current]);\n                        Current += sizeof(std::int64_t);\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::int64_t));\n                        Header.RuntimeConfigLocation.Size =\n                            this->ReadInt64(&HeaderBuffer[Current]);\n                        Current += sizeof(std::int64_t);\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::uint64_t));\n                        Header.Flags = static_cast<BundleFileHeaderFlags>(\n                            this->ReadUInt64(&HeaderBuffer[Current]));\n                        Current += sizeof(std::uint64_t);\n                    }\n\n                    for (std::int32_t i = 0;\n                        i < Header.NumberOfEmbeddedFiles;\n                        ++i)\n                    {\n                        BundleFileEntry Entry;\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::int64_t));\n                        Entry.Offset =\n                            this->ReadInt64(&HeaderBuffer[Current]);\n                        if (Entry.Offset <= 0)\n                        {\n                            // Invalid file offset.\n                            throw std::exception();\n                        }\n                        Current += sizeof(std::int64_t);\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::int64_t));\n                        Entry.Size =\n                            this->ReadInt64(&HeaderBuffer[Current]);\n                        if (Entry.Size < 0)\n                        {\n                            // Invalid file size.\n                            throw std::exception();\n                        }\n                        Current += sizeof(std::int64_t);\n                        if (Header.MajorVersion >= 6)\n                        {\n                            this->ValidateBound(\n                                HeaderBufferSize,\n                                Current,\n                                sizeof(std::int64_t));\n                            Entry.CompressedSize =\n                                this->ReadInt64(&HeaderBuffer[Current]);\n                            if (Entry.CompressedSize < 0)\n                            {\n                                // Invalid compressed file size.\n                                throw std::exception();\n                            }\n                            Current += sizeof(std::int64_t);\n                        }\n                        else\n                        {\n                            Entry.CompressedSize = Entry.Size;\n                        }\n                        if (0 == Entry.CompressedSize)\n                        {\n                            Entry.CompressedSize = Entry.Size;\n                        }\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            sizeof(std::uint8_t));\n                        Entry.Type = static_cast<BundleFileType>(\n                            this->ReadUInt8(&HeaderBuffer[Current]));\n                        if (BundleFileType::TypeCount <= Entry.Type)\n                        {\n                            // Invalid file type.\n                            throw std::exception();\n                        }\n                        Current += sizeof(std::uint8_t);\n                        std::uint16_t RelativePathLength = 0;\n                        {\n                            this->ValidateBound(\n                                HeaderBufferSize,\n                                Current,\n                                sizeof(std::uint8_t));\n                            std::uint8_t FirstByte =\n                                this->ReadUInt8(&HeaderBuffer[Current]);\n                            Current += sizeof(std::uint8_t);\n                            if (0x80 & FirstByte)\n                            {\n                                this->ValidateBound(\n                                    HeaderBufferSize,\n                                    Current,\n                                    sizeof(std::uint8_t));\n                                std::uint8_t SecondByte =\n                                    this->ReadUInt8(&HeaderBuffer[Current]);\n                                Current += sizeof(std::uint8_t);\n                                if (0x80 & SecondByte)\n                                {\n                                    // Invalid relative path length.\n                                    throw std::exception();\n                                }\n                                RelativePathLength = (SecondByte & 0x7F);\n                                RelativePathLength <<= 7;\n                                RelativePathLength |= (FirstByte & 0x7F);\n                            }\n                            else\n                            {\n                                RelativePathLength = (FirstByte & 0x7F);\n                            }\n                            if (0 == RelativePathLength)\n                            {\n                                // Invalid relative path length.\n                                throw std::exception();\n                            }\n                        }\n                        this->ValidateBound(\n                            HeaderBufferSize,\n                            Current,\n                            RelativePathLength);\n                        Entry.RelativePath = std::string(\n                            reinterpret_cast<char*>(&HeaderBuffer[Current]),\n                            RelativePathLength);\n                        Current += RelativePathLength;\n                        Files.emplace(Entry.RelativePath, Entry);\n                    }\n                    this->m_FullSize = BundleHeaderOffset + Current;\n                }\n                catch (...)\n                {\n                    break;\n                }\n\n                HeaderBuffer.clear();\n\n                std::uint64_t TotalFiles = Files.size();\n                std::uint64_t TotalBytes = this->m_FullSize;\n\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                for (auto const& File : Files)\n                {\n                    this->m_FilePaths.emplace_back(File.second);\n                }\n\n                hr = S_OK;\n\n            } while (false);\n\n            if (S_OK != hr)\n            {\n                this->Close();\n            }\n            else\n            {\n                this->m_IsInitialized = true;\n            }\n\n            return hr;\n        }\n\n        HRESULT STDMETHODCALLTYPE Close()\n        {\n            this->m_IsInitialized = false;\n            this->m_FilePaths.clear();\n            this->m_MajorVersion = 0;\n            this->m_FullSize = 0;\n            if (this->m_FileStream)\n            {\n                this->m_FileStream->Release();\n                this->m_FileStream = nullptr;\n            }\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfItems(\n            _Out_ PUINT32 NumItems)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!NumItems)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetProperty(\n            _In_ UINT32 Index,\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!(Index < this->m_FilePaths.size()))\n            {\n                return E_INVALIDARG;\n            }\n\n            BundleFileEntry& Information = this->m_FilePaths[Index];\n\n            switch (PropId)\n            {\n            case SevenZipArchivePath:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_FilePaths[Index].RelativePath).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePackSize:\n            {\n                Value->uhVal.QuadPart = Information.CompressedSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            UNREFERENCED_PARAMETER(Value);\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE Extract(\n            _In_opt_ const PUINT32 Indices,\n            _In_ UINT32 NumItems,\n            _In_ BOOL TestMode,\n            _In_ IArchiveExtractCallback* ExtractCallback)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            HRESULT hr = S_OK;\n\n            INT32 AskMode = TestMode\n                ? SevenZipExtractAskModeTest\n                : SevenZipExtractAskModeExtract;\n\n            const bool AllFilesMode =\n                static_cast<UINT32>(-1) == NumItems;\n            if (AllFilesMode)\n            {\n                NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            }\n\n            UINT64 TotalSize = 0;\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                BundleFileEntry& Information =\n                    this->m_FilePaths[ActualFileIndex];\n                TotalSize += Information.Size;\n            }\n            ExtractCallback->SetTotal(TotalSize);\n\n            UINT64 Completed = 0;\n\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                BundleFileEntry& Information =\n                    this->m_FilePaths[ActualFileIndex];\n\n                Completed += Information.Size;\n                hr = ExtractCallback->SetCompleted(&Completed);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                hr = ExtractCallback->PrepareOperation(AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                ISequentialOutStream* OutputStream = nullptr;\n                hr = ExtractCallback->GetStream(\n                    Indices[i],\n                    &OutputStream,\n                    AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n                if (!OutputStream)\n                {\n                    continue;\n                }\n\n                bool Succeeded = false;\n                if (Information.Size == Information.CompressedSize)\n                {\n                    std::vector<std::uint8_t> Buffer(\n                        static_cast<std::size_t>(Information.Size));\n                    if (SUCCEEDED(this->ReadFileStream(\n                        Information.Offset,\n                        &Buffer[0],\n                        static_cast<std::size_t>(Information.Size))))\n                    {\n                        UINT32 ProceededSize = 0;\n                        Succeeded = SUCCEEDED(OutputStream->Write(\n                            &Buffer[0],\n                            static_cast<UINT32>(Information.Size),\n                            &ProceededSize));\n                    }\n                }\n\n                OutputStream->Release();\n\n                ExtractCallback->SetOperationResult(\n                    Succeeded\n                    ? SevenZipExtractOperationResultSuccess\n                    : SevenZipExtractOperationResultUnavailable);\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchiveProperty(\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!Value)\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!this->m_IsInitialized)\n            {\n                Value->vt = VT_EMPTY;\n                return S_OK;\n            }\n\n            switch (PropId)\n            {\n            case SevenZipArchivePhysicalSize:\n            {\n                Value->uhVal.QuadPart = this->m_FullSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveUnpackVersion:\n            {\n                Value->uhVal.QuadPart = this->m_MajorVersion;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumProps = g_PropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetPropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_PropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_PropertyItems[Index].Property;\n            *VarType = g_PropertyItems[Index].Type;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfArchiveProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n            *NumProps = g_ArchivePropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchivePropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_ArchivePropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_ArchivePropertyItems[Index].Property;\n            *VarType = g_ArchivePropertyItems[Index].Type;\n            return S_OK;\n        }\n    };\n\n    IInArchive* CreateDotNetSingleFile()\n    {\n        return new DotNetSingleFile();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Archive.ElectronAsar.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Archive.ElectronAsar.cpp\n * PURPOSE:    Implementation for Electron Archive (asar) readonly support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\n#include <map>\n#include <Mile.Json.h>\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\nnamespace\n{\n    struct PropertyItem\n    {\n        PROPID Property;\n        VARTYPE Type;\n    };\n\n    const PropertyItem g_PropertyItems[] =\n    {\n        { SevenZipArchivePath, VT_BSTR },\n        { SevenZipArchiveSize, VT_UI8 },\n        { SevenZipArchivePackSize, VT_UI8 },\n    };\n\n    const std::size_t g_PropertyItemsCount =\n        sizeof(g_PropertyItems) / sizeof(*g_PropertyItems);\n\n    struct BundleFileEntry\n    {\n        std::uint64_t Offset = 0;\n        std::uint64_t Size = 0;\n        std::string RelativePath;\n    };\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    struct ElectronAsar : public Mile::ComObject<ElectronAsar, IInArchive>\n    {\n    private:\n\n        IInStream* m_FileStream = nullptr;\n        std::uint64_t m_FullSize = 0;\n        std::uint64_t m_GlobalOffset = 0;\n        std::map<std::string, BundleFileEntry> m_TemporaryFilePaths;\n        std::vector<BundleFileEntry> m_FilePaths;\n        bool m_IsInitialized = false;\n\n    private:\n\n        std::uint32_t ReadUInt32(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt32LittleEndian(BaseAddress);\n        }\n\n        HRESULT ReadFileStream(\n            _In_ INT64 Offset,\n            _Out_ PVOID Buffer,\n            _In_ SIZE_T NumberOfBytesToRead)\n        {\n            if (!this->m_FileStream)\n            {\n                return S_FALSE;\n            }\n\n            if (SUCCEEDED(this->m_FileStream->Seek(\n                Offset,\n                STREAM_SEEK_SET,\n                nullptr)))\n            {\n                SIZE_T NumberOfBytesRead = 0;\n                if (SUCCEEDED(::NanaZipCodecsReadInputStream(\n                    this->m_FileStream,\n                    Buffer,\n                    NumberOfBytesToRead,\n                    &NumberOfBytesRead)))\n                {\n                    if (NumberOfBytesToRead == NumberOfBytesRead)\n                    {\n                        return S_OK;\n                    }\n                }\n            }\n\n            return S_FALSE;\n        }\n\n    private:\n\n        void GetAllPaths(\n            nlohmann::json const& RootJson,\n            std::string const& RootPath)\n        {\n            nlohmann::json Files = Mile::Json::ToObject(\n                Mile::Json::GetSubKey(RootJson, \"files\"));\n            if (!Files.empty())\n            {\n                for (auto const& File : Files.items())\n                {\n                    this->GetAllPaths(\n                        File.value(),\n                        RootPath + File.key() + \"/\");\n                }\n            }\n            else\n            {\n                BundleFileEntry Entry;\n                Entry.RelativePath = RootPath;\n                Entry.RelativePath.resize(Entry.RelativePath.size() - 1);\n                Entry.Offset = Mile::ToUInt64(Mile::Json::ToString(\n                    Mile::Json::GetSubKey(RootJson, \"offset\"),\n                    \"-1\"));\n                Entry.Size = Mile::Json::ToUInt64(\n                    Mile::Json::GetSubKey(RootJson, \"size\"));\n                if (static_cast<std::uint64_t>(-1) != Entry.Offset)\n                {\n                    this->m_TemporaryFilePaths.emplace(\n                        Entry.RelativePath,\n                        Entry);\n                }\n            }\n        }\n\n    public:\n\n        ElectronAsar()\n        {\n\n        }\n\n        HRESULT STDMETHODCALLTYPE Open(\n            _In_ IInStream* Stream,\n            _In_opt_ const PUINT64 MaxCheckStartPosition,\n            _In_opt_ IArchiveOpenCallback* OpenCallback)\n        {\n            UNREFERENCED_PARAMETER(MaxCheckStartPosition);\n            UNREFERENCED_PARAMETER(OpenCallback);\n\n            if (!Stream)\n            {\n                return E_INVALIDARG;\n            }\n\n            HRESULT hr = S_FALSE;\n\n            do\n            {\n                this->Close();\n\n                this->m_FileStream = Stream;\n                this->m_FileStream->AddRef();\n\n                UINT64 BundleSize = 0;\n                if (FAILED(this->m_FileStream->Seek(\n                    0,\n                    STREAM_SEEK_END,\n                    &BundleSize)))\n                {\n                    break;\n                }\n\n                const std::size_t BinaryHeaderSize = 4 * sizeof(std::uint32_t);\n\n                if (BundleSize < BinaryHeaderSize)\n                {\n                    break;\n                }\n\n                std::uint8_t BinaryHeaderBuffer[BinaryHeaderSize];\n                if (FAILED(this->ReadFileStream(\n                    0,\n                    &BinaryHeaderBuffer[0],\n                    BinaryHeaderSize)))\n                {\n                    break;\n                }\n\n                std::uint32_t HeaderSizeVariableSize = this->ReadUInt32(\n                    &BinaryHeaderBuffer[0 * sizeof(std::uint32_t)]);\n                std::uint32_t HeaderSize = this->ReadUInt32(\n                    &BinaryHeaderBuffer[1 * sizeof(std::uint32_t)]);\n                std::uint32_t HeaderBufferSize = this->ReadUInt32(\n                    &BinaryHeaderBuffer[2 * sizeof(std::uint32_t)]);\n                std::uint32_t HeaderStringSize = this->ReadUInt32(\n                    &BinaryHeaderBuffer[3 * sizeof(std::uint32_t)]);\n\n                if (sizeof(std::uint32_t) != HeaderSizeVariableSize)\n                {\n                    break;\n                }\n                if (HeaderSize != sizeof(std::uint32_t) + HeaderBufferSize)\n                {\n                    break;\n                }\n                if (HeaderStringSize > HeaderBufferSize)\n                {\n                    break;\n                }\n                this->m_GlobalOffset = BinaryHeaderSize + HeaderStringSize;\n\n                if (this->m_GlobalOffset % 4 != 0)\n                {\n                    this->m_GlobalOffset += 4 - this->m_GlobalOffset % 4;\n                }\n\n                std::string HeaderString(HeaderStringSize, '\\0');\n                if (FAILED(this->ReadFileStream(\n                    BinaryHeaderSize,\n                    &HeaderString[0],\n                    HeaderStringSize)))\n                {\n                    break;\n                }\n\n                try\n                {\n                    nlohmann::json HeaderObject =\n                        nlohmann::json::parse(HeaderString);\n                    this->GetAllPaths(HeaderObject, \"\");\n                }\n                catch (...)\n                {\n                    break;\n                }\n\n                this->m_FullSize = this->m_GlobalOffset;\n                for (auto const& Item : this->m_TemporaryFilePaths)\n                {\n                    this->m_FullSize += Item.second.Size;\n                }\n\n                std::uint64_t TotalFiles = this->m_TemporaryFilePaths.size();\n                std::uint64_t TotalBytes = this->m_FullSize;\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                this->m_FilePaths.clear();\n\n                for (auto const& Item : this->m_TemporaryFilePaths)\n                {\n                    this->m_FilePaths.emplace_back(Item.second);\n                }\n                this->m_TemporaryFilePaths.clear();\n\n                hr = S_OK;\n\n            } while (false);\n\n            if (S_OK != hr)\n            {\n                this->Close();\n            }\n            else\n            {\n                this->m_IsInitialized = true;\n            }\n\n            return hr;\n        }\n\n        HRESULT STDMETHODCALLTYPE Close()\n        {\n            this->m_IsInitialized = false;\n            this->m_FilePaths.clear();\n            this->m_GlobalOffset = 0;\n            this->m_FullSize = 0;\n            if (this->m_FileStream)\n            {\n                this->m_FileStream->Release();\n                this->m_FileStream = nullptr;\n            }\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfItems(\n            _Out_ PUINT32 NumItems)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!NumItems)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetProperty(\n            _In_ UINT32 Index,\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!(Index < this->m_FilePaths.size()))\n            {\n                return E_INVALIDARG;\n            }\n\n            BundleFileEntry& Information = this->m_FilePaths[Index];\n\n            switch (PropId)\n            {\n            case SevenZipArchivePath:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_FilePaths[Index].RelativePath).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePackSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            UNREFERENCED_PARAMETER(Value);\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE Extract(\n            _In_opt_ const PUINT32 Indices,\n            _In_ UINT32 NumItems,\n            _In_ BOOL TestMode,\n            _In_ IArchiveExtractCallback* ExtractCallback)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            HRESULT hr = S_OK;\n\n            INT32 AskMode = TestMode\n                ? SevenZipExtractAskModeTest\n                : SevenZipExtractAskModeExtract;\n\n            const bool AllFilesMode =\n                static_cast<UINT32>(-1) == NumItems;\n            if (AllFilesMode)\n            {\n                NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            }\n\n            UINT64 TotalSize = 0;\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                BundleFileEntry& Information =\n                    this->m_FilePaths[ActualFileIndex];\n                TotalSize += Information.Size;\n            }\n            ExtractCallback->SetTotal(TotalSize);\n\n            UINT64 Completed = 0;\n\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                BundleFileEntry& Information =\n                    this->m_FilePaths[ActualFileIndex];\n\n                Completed += Information.Size;\n                hr = ExtractCallback->SetCompleted(&Completed);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                hr = ExtractCallback->PrepareOperation(AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                ISequentialOutStream* OutputStream = nullptr;\n                hr = ExtractCallback->GetStream(\n                    Indices[i],\n                    &OutputStream,\n                    AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n                if (!OutputStream)\n                {\n                    continue;\n                }\n\n                bool Succeeded = false;\n                std::vector<std::uint8_t> Buffer(\n                    static_cast<std::size_t>(Information.Size));\n                if (SUCCEEDED(this->ReadFileStream(\n                    this->m_GlobalOffset + Information.Offset,\n                    &Buffer[0],\n                    static_cast<std::size_t>(Information.Size))))\n                {\n                    UINT32 ProceededSize = 0;\n                    Succeeded = SUCCEEDED(OutputStream->Write(\n                        &Buffer[0],\n                        static_cast<UINT32>(Information.Size),\n                        &ProceededSize));\n                }\n\n                OutputStream->Release();\n\n                ExtractCallback->SetOperationResult(\n                    Succeeded\n                    ? SevenZipExtractOperationResultSuccess\n                    : SevenZipExtractOperationResultUnavailable);\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchiveProperty(\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!Value)\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!this->m_IsInitialized)\n            {\n                Value->vt = VT_EMPTY;\n                return S_OK;\n            }\n\n            switch (PropId)\n            {\n            case SevenZipArchivePhysicalSize:\n            {\n                Value->uhVal.QuadPart = this->m_FullSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumProps = g_PropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetPropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_PropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_PropertyItems[Index].Property;\n            *VarType = g_PropertyItems[Index].Type;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfArchiveProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n            *NumProps = 0;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchivePropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            UNREFERENCED_PARAMETER(Index);\n            UNREFERENCED_PARAMETER(Name);\n            UNREFERENCED_PARAMETER(PropId);\n            UNREFERENCED_PARAMETER(VarType);\n            return E_INVALIDARG;\n        }\n    };\n\n    IInArchive* CreateElectronAsar()\n    {\n        return new ElectronAsar();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Archive.Littlefs.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Archive.Littlefs.cpp\n * PURPOSE:    Implementation for littlefs file system image readonly support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\n#ifdef _MSC_VER\n#if _MSC_VER > 1000\n#pragma once\n#endif\n#if (_MSC_VER >= 1200)\n#pragma warning(push)\n#endif\n// unary minus operator applied to unsigned type, result still unsigned\n#pragma warning(disable:4146)\n#endif\n\n#include \"LittleFS/lfs.h\"\n\n#ifdef _MSC_VER\n#if (_MSC_VER >= 1200)\n#pragma warning(pop)\n#else\n// unary minus operator applied to unsigned type, result still unsigned\n#pragma warning(default:4146)\n#endif\n#endif\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\nnamespace\n{\n    struct PropertyItem\n    {\n        PROPID Property;\n        VARTYPE Type;\n    };\n\n    const PropertyItem g_ArchivePropertyItems[] =\n    {\n        { SevenZipArchiveFreeSpace, VT_UI8 },\n        { SevenZipArchiveClusterSize, VT_UI4 },\n        { SevenZipArchiveUnpackVersion, VT_UI8 },\n    };\n\n    const std::size_t g_ArchivePropertyItemsCount =\n        sizeof(g_ArchivePropertyItems) / sizeof(*g_ArchivePropertyItems);\n\n    const PropertyItem g_PropertyItems[] =\n    {\n        { SevenZipArchivePath, VT_BSTR },\n        { SevenZipArchiveIsDirectory, VT_BOOL },\n        { SevenZipArchiveSize, VT_UI8 },\n        { SevenZipArchivePackSize, VT_UI8 },\n        { SevenZipArchiveInode, VT_UI8 },\n    };\n\n    const std::size_t g_PropertyItemsCount =\n        sizeof(g_PropertyItems) / sizeof(*g_PropertyItems);\n\n    // References:\n    // - https://github.com/littlefs-project/littlefs/blob/v1-prefix/SPEC.md\n    // - https://github.com/littlefs-project/littlefs/blob/v1-prefix/lfs1.h\n    // - https://github.com/littlefs-project/littlefs/blob/v2-prefix/SPEC.md\n    // - https://github.com/littlefs-project/littlefs/blob/v2-prefix/lfs2.h\n\n    // Notes:\n    // - All values in littlefs v1 are stored in little-endian byte order.\n    // - All values in littlefs v2 are stored in little-endian byte order, only\n    //   except the tags are stored in commits are stored in big-endian.\n    // - Block pointers are stored in 32 bits, with the special value 0xFFFFFFFF\n    //   representing a null block address.\n\n    const std::uint32_t LfsNullBlock = 0xFFFFFFFF;\n\n    const char LfsSuperBlockMagic[] = { 'l', 'i', 't', 't', 'l', 'e', 'f', 's' };\n\n    /**\n     * @brief Pair-pointer for pointing to the specific metadata-pair in the\n     *        filesystem. A null pair-pointer (0xffffffff, 0xffffffff) indicates\n     *        the end of the list.\n     */\n    struct Lfs1MetadataPairPointer\n    {\n        std::uint32_t Lower;\n        std::uint32_t Upper;\n    };\n\n    // Metadata pairs form the backbone of the littlefs and provide a system for\n    // atomic updates. Even the superblock is stored in a metadata pair.\n    // As their name suggests, a metadata pair is stored in two blocks, with one\n    // block acting as a redundant backup in case the other is corrupted. These\n    // two blocks could be anywhere in the disk and may not be next to each\n    // other, so any pointers to directory pairs need to be stored as two block\n    // pointers.\n\n    /**\n     * @brief The beginning of the metadata used in the metadata pairs.\n     */\n    struct Lfs1MetadataHeader\n    {\n        /**\n         * @brief Incremented every update, only the uncorrupted metadata-block\n         *        with the most recent revision count contains the valid\n         *        metadata. Comparison between revision counts must use sequence\n         *        comparison since the revision counts may overflow.\n         */\n        std::uint32_t Revision;\n\n        /**\n         * @brief Size in bytes of the contents in the current metadata block,\n         *        including the metadata-pair metadata. Additionally, the\n         *        highest bit of the dir size may be set to indicate that the\n         *        directory's contents continue on the next metadata-pair\n         *        pointed to by the tail pointer.\n         */\n        std::uint32_t Size;\n\n        /**\n         * @brief Pointer to the next metadata-pair in the filesystem. A null\n         *        pair-pointer (0xffffffff, 0xffffffff) indicates the end of the\n         *        list. If the highest bit in the dir size is set, this points\n         *        to the next metadata-pair in the current directory, otherwise\n         *        it points to an arbitrary metadata-pair. Starting with the\n         *        superblock, the tail-pointers form a linked-list containing\n         *        all metadata-pairs in the filesystem.\n         */\n        Lfs1MetadataPairPointer Tail;\n    };\n\n    /**\n     * @brief The ending‌ of the metadata used in the metadata pairs.\n     */\n    struct Lfs1MetadataFooter\n    {\n        /**\n         * @brief 32-bit CRC used to detect corruption from power-lost, from\n         *        block end-of-life, or just from noise on the storage bus. The\n         *        CRC is appended to the end of each metadata-block. The\n         *        littlefs uses the standard CRC-32, which uses a polynomial of\n         *        0x04c11db7, initialized with 0xffffffff.\n         */\n        std::uint32_t Crc;\n    };\n\n    /**\n     * @brief Type of the entry, currently this is limited to the following.\n     *        Additionally, the type is broken into two 4 bit nibbles, with the\n     *        upper nibble specifying the type's data structure used when\n     *        scanning the filesystem. The lower nibble clarifies the type\n     *        further when multiple entries share the same data structure.\n     *        The highest bit is reserved for marking the entry as \"moved\". If\n     *        an entry is marked as \"moved\", the entry may also exist somewhere\n     *        else in the filesystem. If the entry exists elsewhere, this entry\n     *        must be treated as though it does not exist.\n     */\n    enum Lfs1EntryTypes\n    {\n        Lfs1FileEntry = 0x11,\n        Lfs1DirectoryEntry = 0x22,\n        Lfs1SuperBlockEntry = 0x2E,\n    };\n\n    struct Lfs1EntryHeader\n    {\n        /**\n         * @brief Type of the entry, which is one of the Lfs1EntryTypes.\n         */\n        std::uint8_t EntryType;\n\n        /**\n         * @brief Length in bytes of the entry-specific data. This does not\n         *        include the entry type size, attributes, or name. The full\n         *        size in bytes of the entry is sizeof(Lfs1EntryHeader) +\n         *        EntryLength + AttributeLength + NameLength.\n         */\n        std::uint8_t EntryLength;\n\n        /**\n         * @brief Length of system-specific attributes in bytes. Since\n         *        attributes are system specific, there is not much\n         *        guarantee on the values in this section, and systems\n         *        are expected to work even when it is empty.\n         */\n        std::uint8_t AttributeLength;\n\n        /**\n         * @brief Length of the entry name. Entry names are stored as UTF8,\n         *        although most systems will probably only support ASCII. Entry\n         *        names can not contain '/' and can not be '.' or '..' as these\n         *        are a part of the syntax of filesystem paths.\n         */\n        std::uint8_t NameLength;\n    };\n\n    /**\n     * @brief The superblock is the anchor for the littlefs. The superblock is\n     *        stored as a metadata pair containing a single superblock entry.\n     *        It is through the superblock that littlefs can access the rest of\n     *        the filesystem.\n     *        The superblock can always be found in blocks 0 and 1, however\n     *        fetching the superblock requires knowing the block size. The block\n     *        size can be guessed by searching the beginning of disk for the\n     *        string \"littlefs\", although currently the filesystems relies on\n     *        the user providing the correct block size.\n     *        The superblock is the most valuable block in the filesystem. It is\n     *        updated very rarely, only during format or when the root directory\n     *        must be moved. It is encouraged to always write out both\n     *        superblock pairs even though it is not required.\n     */\n    struct Lfs1SuperBlockEntryContent\n    {\n        /**\n         * @brief Pointer to the root directory's metadata pair.\n         */\n        Lfs1MetadataPairPointer RootDirectory;\n\n        /**\n         * @brief Size of the logical block size used by the filesystem.\n         */\n        std::uint32_t BlockSize;\n\n        /**\n         * @brief Number of blocks in the filesystem.\n         */\n        std::uint32_t BlockCount;\n\n        /**\n         * @brief The littlefs version encoded as a 32 bit value. The upper 16\n         *        bits encodes the major version, which is incremented when a\n         *        breaking-change is introduced in the filesystem specification.\n         *        The lower 16 bits encodes the minor version, which is\n         *        incremented when a backwards-compatible change is introduced.\n         *        Non-standard Attribute changes do not change the version. This\n         *        specification describes version 1.1 (0x00010001), which is the\n         *        first version of littlefs.\n         */\n        std::uint32_t Version;\n    };\n\n    /**\n     * @brief Directories are stored in entries with a pointer to the first\n     *        metadata pair in the directory. Keep in mind that a directory\n     *        may be composed of multiple metadata pairs connected by the tail\n     *        pointer when the highest bit in the dir size is set.\n     */\n    struct Lfs1DirectoryEntryContent\n    {\n        /**\n         * @brief Pointer to the first metadata pair in the directory.\n         */\n        Lfs1MetadataPairPointer Directory;\n    };\n\n    /**\n     * @brief Files are stored in entries with a pointer to the head of the file\n     *        and the size of the file. This is enough information to determine\n     *        the state of the CTZ skip-list that is being referenced.\n     *        A terribly quick summary: For every nth block where n is divisible\n     *        by 2^x, the block contains a pointer to block n-2^x. These\n     *        pointers are stored in increasing order of x in each block of the\n     *        file preceding the data in the block.\n     *        The maximum number of pointers in a block is bounded by the\n     *        maximum file size divided by the block size. With 32 bits for file\n     *        size, this results in a minimum block size of 104 bytes.\n     */\n    struct Lfs1FileEntryContent\n    {\n        /**\n         * @brief Pointer to the block that is the head of the file's CTZ\n         *        skip-list.\n         */\n        std::uint32_t FileHead;\n\n        /**\n         * @brief Size of file in bytes.\n         */\n        std::uint32_t FileSize;\n    };\n\n    // littlefs v2 definitions (work in progress)\n\n    const std::uint32_t g_LfsInitialTag = 0xffffffff;\n\n    // Version of On-disk data structures\n    // Major (top-nibble), incremented on backwards incompatible changes\n    // Minor (bottom-nibble), incremented on feature additions\n\n    const std::uint32_t g_LfsDiskVersion = 0x00020001;\n    const std::uint16_t g_LfsDiskVersionMajor =\n        static_cast<const std::uint16_t>(g_LfsDiskVersion >> 16);\n    const std::uint32_t g_LfsDiskVersionMinor =\n        static_cast<const std::uint16_t>(g_LfsDiskVersion >> 0);\n\n    // Maximum name size in bytes, may be redefined to reduce the size of the\n    // info struct. Limited to <= 1022. Stored in superblock and must be\n    // respected by other littlefs drivers.\n    const std::uint32_t g_LfsMaximumNameLength = 255;\n\n    // Maximum size of a file in bytes, may be redefined to limit to support\n    // other drivers. Limited on disk to <= 2147483647. Stored in superblock\n    // and must be respected by other littlefs drivers.\n    const std::uint32_t g_LfsMaximumFileLength = 2147483647;\n\n    // Maximum size of custom attributes in bytes, may be redefined, but there\n    // is no real benefit to using a smaller g_LfsMaximumAttributeLength.\n    // Limited to <= 1022. Stored in superblock and must be respected by other\n    // littlefs drivers.\n    const std::uint32_t g_LfsMaximumAttributeLength = 1022;\n\n    // File types\n    enum LfsTypes\n    {\n        // file types\n\n        LfsTypeRegular = 0x001,\n        LfsTypeDirectory = 0x002,\n\n        // internally used types\n\n        LfsTypeSplice = 0x400,\n        LfsTypeName = 0x000,\n        LfsTypeStruct = 0x200,\n        LfsTypeUserAttribute = 0x300,\n        LfsTypeFrom = 0x100,\n        LfsTypeTail = 0x600,\n        LfsTypeGlobals = 0x700,\n        LfsTypeCrc = 0x500,\n\n        // internally used type specializations\n\n        LfsTypeCreate = 0x401,\n        LfsTypeDelete = 0x4ff,\n        LfsTypeSuperBlock = 0x0ff,\n        LfsTypeDirectoryStructure = 0x200,\n        LfsTypeCtzStructure = 0x202,\n        LfsTypeInlineStructure = 0x201,\n        LfsTypeSoftTail = 0x600,\n        LfsTypeHardTail = 0x601,\n        LfsTypeMoveState = 0x7ff,\n        LfsTypeCcrc = 0x500,\n        LfsTypeFcrc = 0x5ff,\n\n        // internal chip sources\n\n        LfsFromNoop = 0x000,\n        LfsFromMove = 0x101,\n        LfsFromUserAttributes = 0x102,\n    };\n\n    union LfsMetadataTag\n    {\n        std::uint32_t AsRaw;\n        struct\n        {\n            std::uint32_t Length : 10;\n            std::uint32_t Id : 10;\n            std::uint32_t Type : 11;\n            std::uint32_t Invalid : 1;\n        } Information;\n\n        bool CheckWith(\n            std::uint16_t const& Type,\n            std::uint16_t const& Id,\n            std::uint16_t const& Size)\n        {\n            return (\n                !this->Information.Invalid &&\n                Type == this->Information.Type &&\n                Id == this->Information.Id &&\n                Size == this->Information.Length);\n        }\n    };\n\n    // The superblock must always be the first entry (id 0) in the metadata\n    // pair, and the name tag must always be the first tag in the metadata pair.\n    // This makes it so that the magic string \"littlefs\" will always reside at\n    // offset = 8 in a valid littlefs superblock.\n\n    struct LfsSuperBlockInlineStructure\n    {\n        // The version of littlefs at format time. The version is encoded in a\n        // 32-bit value with the upper 16-bits containing the major version, and\n        // the lower 16-bits containing the minor version.\n        // This specification describes version 2.0 (`0x00020000`).\n        std::uint32_t Version;\n        // Size of the logical block size used by the filesystem in bytes.\n        std::uint32_t BlockSize;\n        // Number of blocks in the filesystem.\n        std::uint32_t BlockCount;\n        // Maximum size of file names in bytes.\n        std::uint32_t MaximumNameLength;\n        // Maximum size of files in bytes.\n        std::uint32_t MaximumFileLength;\n        // Maximum size of file attributes in bytes.\n        std::uint32_t MaximumAttributeLength;\n    };\n\n    struct LfsSuperMetadataHeader\n    {\n        std::uint32_t RawRevisionCount;\n        std::uint32_t RawSuperBlockTag;\n        char RawSignature[8];\n        std::uint32_t RawStructureTag;\n        LfsSuperBlockInlineStructure RawStructure;\n    };\n\n    struct LittlefsFilePathInformation\n    {\n        std::uint32_t Inode = 0;\n        // Type of the file, either LfsTypeRegular or LfsTypeDirectory\n        std::uint8_t Type = 0;\n        std::uint32_t Size = 0;\n        std::string Path;\n        // TODO: Currently just ultimate raw block extractor for analyzing\n        std::uint64_t Offset = 0;\n        //std::vector<std::uint32_t> BlockOffsets;\n    };\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    struct Littlefs : public Mile::ComObject<Littlefs, IInArchive>\n    {\n    private:\n\n        IInStream* m_FileStream = nullptr;\n        LfsSuperMetadataHeader m_SuperMetadataHeader = {};\n        std::vector<LittlefsFilePathInformation> m_FilePaths;\n        bool m_IsInitialized = false;\n\n    private:\n\n        std::uint8_t ReadUInt8(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt8(BaseAddress);\n        }\n\n        std::uint16_t ReadUInt16(\n            const void* BaseAddress)\n        {\n            ::MileReadUInt16LittleEndian(BaseAddress);\n        }\n\n        std::uint32_t ReadUInt32(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt32LittleEndian(BaseAddress);\n        }\n\n        std::int8_t ReadInt8(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int8_t>(this->ReadUInt8(BaseAddress));\n        }\n\n        std::int16_t ReadInt16(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int16_t>(this->ReadUInt16(BaseAddress));\n        }\n\n        std::int32_t ReadInt32(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int32_t>(this->ReadUInt32(BaseAddress));\n        }\n\n        HRESULT ReadFileStream(\n            _In_ INT64 Offset,\n            _Out_ PVOID Buffer,\n            _In_ SIZE_T NumberOfBytesToRead)\n        {\n            if (!this->m_FileStream)\n            {\n                return S_FALSE;\n            }\n\n            if (SUCCEEDED(this->m_FileStream->Seek(\n                Offset,\n                STREAM_SEEK_SET,\n                nullptr)))\n            {\n                SIZE_T NumberOfBytesRead = 0;\n                if (SUCCEEDED(::NanaZipCodecsReadInputStream(\n                    this->m_FileStream,\n                    Buffer,\n                    NumberOfBytesToRead,\n                    &NumberOfBytesRead)))\n                {\n                    if (NumberOfBytesToRead == NumberOfBytesRead)\n                    {\n                        return S_OK;\n                    }\n                }\n            }\n\n            return S_FALSE;\n        }\n\n    private:\n\n        std::uint32_t ReadRawMetadataTag(\n            const void* BaseAddress)\n        {\n            const std::uint8_t* Base =\n                reinterpret_cast<const std::uint8_t*>(BaseAddress);\n            // Tags stored in commits are actually stored in big-endian (and is\n            // the only thing in littlefs stored in big-endian).\n            return\n                (static_cast<std::uint32_t>(Base[3])) |\n                (static_cast<std::uint32_t>(Base[2]) << 8) |\n                (static_cast<std::uint32_t>(Base[1]) << 16) |\n                (static_cast<std::uint32_t>(Base[0]) << 24);\n        }\n\n    public:\n\n        Littlefs()\n        {\n\n        }\n\n        HRESULT STDMETHODCALLTYPE Open(\n            _In_ IInStream* Stream,\n            _In_opt_ const PUINT64 MaxCheckStartPosition,\n            _In_opt_ IArchiveOpenCallback* OpenCallback)\n        {\n            UNREFERENCED_PARAMETER(MaxCheckStartPosition);\n            UNREFERENCED_PARAMETER(OpenCallback);\n\n            if (!Stream)\n            {\n                return E_INVALIDARG;\n            }\n\n            HRESULT hr = S_FALSE;\n\n            do\n            {\n                this->Close();\n\n                this->m_FileStream = Stream;\n                this->m_FileStream->AddRef();\n\n                UINT64 BundleSize = 0;\n                if (FAILED(this->m_FileStream->Seek(\n                    0,\n                    STREAM_SEEK_END,\n                    &BundleSize)))\n                {\n                    break;\n                }\n\n                LfsMetadataTag PreviousTag = {};\n                PreviousTag.AsRaw = g_LfsInitialTag;\n\n                if (BundleSize < sizeof(LfsSuperMetadataHeader))\n                {\n                    break;\n                }\n\n                if (FAILED(this->ReadFileStream(\n                    0,\n                    &this->m_SuperMetadataHeader,\n                    sizeof(LfsSuperMetadataHeader))))\n                {\n                    break;\n                }\n\n                PreviousTag.AsRaw ^= this->ReadRawMetadataTag(\n                    &this->m_SuperMetadataHeader.RawSuperBlockTag);\n                if (!PreviousTag.CheckWith(\n                    LfsTypeSuperBlock,\n                    0,\n                    sizeof(::LfsSuperBlockMagic)))\n                {\n                    break;\n                }\n\n                if (0 != std::memcmp(\n                    this->m_SuperMetadataHeader.RawSignature,\n                    ::LfsSuperBlockMagic,\n                    sizeof(::LfsSuperBlockMagic)))\n                {\n                    break;\n                }\n\n                PreviousTag.AsRaw ^= this->ReadRawMetadataTag(\n                    &this->m_SuperMetadataHeader.RawStructureTag);\n                if (!PreviousTag.CheckWith(\n                    LfsTypeInlineStructure,\n                    0,\n                    sizeof(LfsSuperBlockInlineStructure)))\n                {\n                    break;\n                }\n\n                std::uint32_t DiskVersion = this->ReadUInt32(\n                    &this->m_SuperMetadataHeader.RawStructure.Version);\n                if (g_LfsDiskVersionMajor != static_cast<const std::uint16_t>(\n                    DiskVersion >> 16))\n                {\n                    break;\n                }\n\n                std::uint32_t BlockSize = this->ReadUInt32(\n                    &this->m_SuperMetadataHeader.RawStructure.BlockSize);\n                std::uint32_t BlockCount = this->ReadUInt32(\n                    &this->m_SuperMetadataHeader.RawStructure.BlockCount);\n\n                std::uint64_t TotalFiles = 0;\n                std::uint64_t TotalBytes = 0;\n\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                // TODO: this->GetAllPaths\n\n                // TODO: OpenCallback->SetTotal with new TotalFiles\n\n                this->m_FilePaths.clear();\n\n                // TODO: Currently just ultimate raw block extractor for analyzing\n                for (std::uint32_t i = 0; i < BlockCount; ++i)\n                {\n                    LittlefsFilePathInformation Information;\n                    Information.Inode = i;\n                    Information.Type = LfsTypeRegular;\n                    Information.Size = BlockSize;\n                    Information.Path = Mile::FormatString(\"[%d]\", i);\n                    Information.Offset = i * BlockSize;\n                    this->m_FilePaths.emplace_back(Information);\n                }\n\n                hr = S_OK;\n\n            } while (false);\n\n            if (S_OK != hr)\n            {\n                this->Close();\n            }\n            else\n            {\n                this->m_IsInitialized = true;\n            }\n\n            return hr;\n        }\n\n        HRESULT STDMETHODCALLTYPE Close()\n        {\n            this->m_IsInitialized = false;\n            this->m_FilePaths.clear();\n            this->m_SuperMetadataHeader = {};\n            if (this->m_FileStream)\n            {\n                this->m_FileStream->Release();\n                this->m_FileStream = nullptr;\n            }\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfItems(\n            _Out_ PUINT32 NumItems)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!NumItems)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetProperty(\n            _In_ UINT32 Index,\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!(Index < this->m_FilePaths.size()))\n            {\n                return E_INVALIDARG;\n            }\n\n            LittlefsFilePathInformation& Information = this->m_FilePaths[Index];\n\n            switch (PropId)\n            {\n            case SevenZipArchivePath:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_FilePaths[Index].Path).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveIsDirectory:\n            {\n                Value->boolVal = LfsTypeDirectory == Information.Type\n                    ? VARIANT_TRUE\n                    : VARIANT_FALSE;\n                Value->vt = VT_BOOL;\n                break;\n            }\n            case SevenZipArchiveSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePackSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveInode:\n            {\n                Value->uhVal.QuadPart = Information.Inode;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            UNREFERENCED_PARAMETER(Value);\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE Extract(\n            _In_opt_ const PUINT32 Indices,\n            _In_ UINT32 NumItems,\n            _In_ BOOL TestMode,\n            _In_ IArchiveExtractCallback* ExtractCallback)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            HRESULT hr = S_OK;\n\n            INT32 AskMode = TestMode\n                ? SevenZipExtractAskModeTest\n                : SevenZipExtractAskModeExtract;\n\n            const bool AllFilesMode =\n                static_cast<UINT32>(-1) == NumItems;\n            if (AllFilesMode)\n            {\n                NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            }\n\n            UINT64 TotalSize = 0;\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                LittlefsFilePathInformation& Information =\n                    this->m_FilePaths[ActualFileIndex];\n                TotalSize += Information.Size;\n            }\n            ExtractCallback->SetTotal(TotalSize);\n\n            UINT64 Completed = 0;\n\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                LittlefsFilePathInformation& Information =\n                    this->m_FilePaths[ActualFileIndex];\n\n                Completed += Information.Size;\n                hr = ExtractCallback->SetCompleted(&Completed);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                hr = ExtractCallback->PrepareOperation(AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                ISequentialOutStream* OutputStream = nullptr;\n                hr = ExtractCallback->GetStream(\n                    Indices[i],\n                    &OutputStream,\n                    AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n                if (!OutputStream)\n                {\n                    continue;\n                }\n\n                bool Succeeded = false;\n\n                // TODO: Currently just ultimate raw block extractor for analyzing\n\n                std::vector<std::uint8_t> Buffer(Information.Size);\n                if (SUCCEEDED(this->ReadFileStream(\n                    Information.Offset,\n                    &Buffer[0],\n                    Information.Size)))\n                {\n                    UINT32 ProceededSize = 0;\n                    Succeeded = SUCCEEDED(OutputStream->Write(\n                        &Buffer[0],\n                        static_cast<UINT32>(Information.Size),\n                        &ProceededSize));\n                }\n\n                OutputStream->Release();\n\n                ExtractCallback->SetOperationResult(\n                    Succeeded\n                    ? SevenZipExtractOperationResultSuccess\n                    : SevenZipExtractOperationResultUnavailable);\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchiveProperty(\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!Value)\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!this->m_IsInitialized)\n            {\n                Value->vt = VT_EMPTY;\n                return S_OK;\n            }\n\n            switch (PropId)\n            {\n            case SevenZipArchivePhysicalSize:\n            {\n                std::uint32_t BlockSize = this->ReadUInt32(\n                    &this->m_SuperMetadataHeader.RawStructure.BlockSize);\n                std::uint32_t BlockCount = this->ReadUInt32(\n                    &this->m_SuperMetadataHeader.RawStructure.BlockCount);\n\n                Value->uhVal.QuadPart = BlockSize * BlockCount;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveFreeSpace:\n            {\n                // TODO: Unimplemented\n                Value->uhVal.QuadPart = 0;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveClusterSize:\n            {\n                std::uint32_t BlockSize = this->ReadUInt32(\n                    &this->m_SuperMetadataHeader.RawStructure.BlockSize);\n\n                Value->ulVal = BlockSize;\n                Value->vt = VT_UI4;\n                break;\n            }\n            case SevenZipArchiveUnpackVersion:\n            {\n                std::uint32_t DiskVersion = this->ReadUInt32(\n                    &this->m_SuperMetadataHeader.RawStructure.Version);\n                Value->uhVal.QuadPart = static_cast<UINT64>(DiskVersion >> 16);\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumProps = g_PropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetPropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_PropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_PropertyItems[Index].Property;\n            *VarType = g_PropertyItems[Index].Type;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfArchiveProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n            *NumProps = g_ArchivePropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchivePropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_ArchivePropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_ArchivePropertyItems[Index].Property;\n            *VarType = g_ArchivePropertyItems[Index].Type;\n            return S_OK;\n        }\n    };\n\n    IInArchive* CreateLittlefs()\n    {\n        return new Littlefs();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Archive.Romfs.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Archive.Romfs.cpp\n * PURPOSE:    Implementation for ROMFS file system image readonly support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\n#include <map>\n#include <unordered_set>\n#include <deque>\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\nnamespace\n{\n    struct PropertyItem\n    {\n        PROPID Property;\n        VARTYPE Type;\n    };\n\n    const PropertyItem g_ArchivePropertyItems[] =\n    {\n        { SevenZipArchiveVolumeName, VT_BSTR },\n    };\n\n    const std::size_t g_ArchivePropertyItemsCount =\n        sizeof(g_ArchivePropertyItems) / sizeof(*g_ArchivePropertyItems);\n\n    const PropertyItem g_PropertyItems[] =\n    {\n        { SevenZipArchivePath, VT_BSTR },\n        { SevenZipArchiveIsDirectory, VT_BOOL },\n        { SevenZipArchiveSize, VT_UI8 },\n        { SevenZipArchivePackSize, VT_UI8 },\n        { SevenZipArchiveSymbolicLink, VT_BSTR },\n        { SevenZipArchiveHardLink, VT_BSTR },\n        { SevenZipArchiveInode, VT_UI8 },\n    };\n\n    const std::size_t g_PropertyItemsCount =\n        sizeof(g_PropertyItems) / sizeof(*g_PropertyItems);\n\n    // Reference: https://www.kernel.org/doc/html/v6.12/filesystems/romfs.html\n    // Every multi byte value (32 bit words, I will use the longwords term from\n    // now on) must be in big endian order.\n\n    const char g_RomfsSignature[] = { '-', 'r', 'o', 'm', '1', 'f', 's', '-' };\n\n    // The Windows MAX_PATH as the maximum path length should enough for most\n    // ROMFS cases.\n    const std::size_t g_RomfsMaximumPathLength = MAX_PATH;\n\n    // Limit resource consumption.\n    const std::size_t g_RomfsMaximumEntries = 10000;\n    // Protect against excessively-deep directory structures.\n    const std::size_t g_RomfsMaximumVisitDepth = 1000;\n\n    struct RomfsHeader\n    {\n        // The ASCII representation of those bytes (i.e. \"-rom1fs-\")\n        char Signature[8];\n        // The number of accessible bytes in this fs\n        std::uint32_t FullSize;\n        // The checksum of the first 512 bytes (or the number of bytes\n        // accessible, whichever is smaller)\n        std::uint32_t CheckSum;\n        // The zero terminated name of the volume, padded to 16 byte boundary\n        char VolumeName[1];\n    };\n\n    enum RomfsFileType\n    {\n        // link destination [file header]\n        HardLink,\n        // first file's header\n        Directory,\n        // unused, must be zero [MBZ]\n        RegularFile,\n        // unused, MBZ (file data is the link content)\n        SymbolicLink,\n        // 16/16 bits major/minor number\n        BlockDevice,\n        // - \" -\n        CharDevice,\n        // unused, MBZ\n        Socket,\n        // unused, MBZ\n        Fifo,\n        Mask = 0x7,\n    };\n\n    struct RomfsFileHeader\n    {\n        // The offset of the next file header (zero if no more files)\n        std::uint32_t NextOffsetAndType;\n        // Info for directories/hard links/devices\n        std::uint32_t SpecInfo;\n        // The size of this file in bytes\n        std::uint32_t Size;\n        // Covering the meta data, including the file name, and padding\n        std::uint32_t CheckSum;\n        // The zero terminated name of the file, padded to 16 byte boundary\n        char FileName[1];\n    };\n\n    struct RomfsFilePathInformation\n    {\n        std::uint32_t Inode = 0;\n        RomfsFileType Type = RomfsFileType::HardLink;\n        std::uint32_t Size = 0;\n        std::uint32_t Offset = 0;\n        std::string Path;\n    };\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    struct Romfs : public Mile::ComObject<Romfs, IInArchive>\n    {\n    private:\n\n        IInStream* m_FileStream = nullptr;\n        std::uint32_t m_FullSize = 0;\n        std::string m_VolumeName;\n\n        // For GetAllPaths.\n        std::deque<std::pair<std::uint32_t, std::string>> m_VisitQueue;\n        // Protect against recursive structures.\n        std::unordered_set<std::uint32_t> m_VisitedOffsets;\n\n        std::map<std::string, RomfsFilePathInformation> m_TemporaryFilePaths;\n        std::vector<RomfsFilePathInformation> m_FilePaths;\n        bool m_IsInitialized = false;\n\n    private:\n\n        std::uint32_t ReadUInt32(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt32BigEndian(BaseAddress);\n        }\n\n        std::uint32_t GetAlignedSize(\n            int Size,\n            int Alignment)\n        {\n            return (Size + Alignment - 1) & ~(Alignment - 1);\n        }\n\n        HRESULT ReadFileStream(\n            _In_ INT64 Offset,\n            _Out_ PVOID Buffer,\n            _In_ SIZE_T NumberOfBytesToRead)\n        {\n            if (!this->m_FileStream)\n            {\n                return S_FALSE;\n            }\n\n            if (SUCCEEDED(this->m_FileStream->Seek(\n                Offset,\n                STREAM_SEEK_SET,\n                nullptr)))\n            {\n                SIZE_T NumberOfBytesRead = 0;\n                if (SUCCEEDED(::NanaZipCodecsReadInputStream(\n                    this->m_FileStream,\n                    Buffer,\n                    NumberOfBytesToRead,\n                    &NumberOfBytesRead)))\n                {\n                    if (NumberOfBytesToRead == NumberOfBytesRead)\n                    {\n                        return S_OK;\n                    }\n                }\n            }\n\n            return S_FALSE;\n        }\n\n    private:\n\n        HRESULT GetOnePath(\n            std::uint32_t Offset,\n            std::string const& Path)\n        {\n            while (Offset)\n            {\n                RomfsFilePathInformation Information;\n                Information.Inode = Offset;\n\n                if (m_VisitedOffsets.size() >= g_RomfsMaximumEntries)\n                {\n                    // Too many files, softly bail out.\n                    return S_OK;\n                }\n\n                auto [Iterator, Inserted] = m_VisitedOffsets.insert(Offset);\n                if (!Inserted)\n                {\n                    // We have visited recursively. Bail out.\n                    return HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT);\n                }\n\n                std::uint8_t FileHeaderBuffer[\n                    offsetof(RomfsFileHeader, FileName)] = {};\n                if (FAILED(this->ReadFileStream(\n                    Offset,\n                    &FileHeaderBuffer[0],\n                    sizeof(FileHeaderBuffer))))\n                {\n                    break;\n                }\n                Offset += offsetof(RomfsFileHeader, FileName);\n\n                std::uint32_t NextOffsetAndType = this->ReadUInt32(\n                    &FileHeaderBuffer[\n                        offsetof(RomfsFileHeader, NextOffsetAndType)]);\n                std::uint32_t NextOffset = NextOffsetAndType & 0xFFFFFFF0;\n\n                Information.Type = static_cast<RomfsFileType>(\n                    NextOffsetAndType & RomfsFileType::Mask);\n                Information.Size = this->ReadUInt32(\n                    &FileHeaderBuffer[offsetof(RomfsFileHeader, Size)]);\n                std::string FileName = std::string(\n                    m_FullSize - Offset < g_RomfsMaximumPathLength\n                    ? m_FullSize - Offset\n                    : g_RomfsMaximumPathLength,\n                    '\\0');\n                if (FAILED(this->ReadFileStream(\n                    Offset,\n                    &FileName[0],\n                    FileName.size())))\n                {\n                    break;\n                }\n                FileName.resize(std::strlen(FileName.c_str()));\n                Offset += this->GetAlignedSize(\n                    static_cast<std::uint32_t>(FileName.size()) + 1,\n                    16);\n\n                if (\".\" != FileName && \"..\" != FileName)\n                {\n                    Information.Offset = Offset;\n                    Information.Path = Path + FileName;\n\n                    if (RomfsFileType::Directory == Information.Type)\n                    {\n                        if (m_VisitQueue.size() < g_RomfsMaximumVisitDepth)\n                        {\n                            m_VisitQueue.emplace_back(\n                                Offset,\n                                Information.Path + \"/\");\n                        }\n                        else\n                        {\n                            // Exceeded our internal limit, bail out.\n                            return HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT);\n                        }\n                    }\n                    else if (RomfsFileType::HardLink == Information.Type)\n                    {\n                        Information.Inode = this->ReadUInt32(&FileHeaderBuffer[\n                            offsetof(RomfsFileHeader, SpecInfo)]);\n                    }\n\n                    this->m_TemporaryFilePaths.emplace(\n                        Information.Path,\n                        Information);\n                }\n\n                Offset = NextOffset;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT GetAllPaths(std::uint32_t RootOffset)\n        {\n            m_VisitQueue.clear();\n            m_VisitedOffsets.clear();\n            m_VisitQueue.emplace_back(RootOffset, \"\");\n\n            while (!m_VisitQueue.empty())\n            {\n                HRESULT Result;\n\n                // Get the entry out before visiting.\n                auto [Offset, Path] = std::move(m_VisitQueue.front());\n                m_VisitQueue.pop_front();\n                Result = this->GetOnePath(Offset, Path);\n                if (S_OK != Result)\n                {\n                    return Result;\n                }\n            }\n\n            return S_OK;\n        }\n\n    public:\n\n        Romfs()\n        {\n\n        }\n\n        HRESULT STDMETHODCALLTYPE Open(\n            _In_ IInStream* Stream,\n            _In_opt_ const PUINT64 MaxCheckStartPosition,\n            _In_opt_ IArchiveOpenCallback* OpenCallback)\n        {\n            UNREFERENCED_PARAMETER(MaxCheckStartPosition);\n            UNREFERENCED_PARAMETER(OpenCallback);\n\n            if (!Stream)\n            {\n                return E_INVALIDARG;\n            }\n\n            HRESULT hr = S_FALSE;\n\n            do\n            {\n                this->Close();\n\n                this->m_FileStream = Stream;\n                this->m_FileStream->AddRef();\n\n                UINT64 BundleSize = 0;\n                if (FAILED(this->m_FileStream->Seek(\n                    0,\n                    STREAM_SEEK_END,\n                    &BundleSize)))\n                {\n                    break;\n                }\n\n                const std::size_t MinimumHeaderSize =\n                    this->GetAlignedSize(sizeof(RomfsHeader), 16);\n\n                if (BundleSize < MinimumHeaderSize)\n                {\n                    break;\n                }\n\n                std::uint32_t Offset = 0;\n\n                std::uint8_t HeaderBuffer[\n                    offsetof(RomfsHeader, VolumeName)] = {};\n                if (FAILED(this->ReadFileStream(\n                    0,\n                    &HeaderBuffer[0],\n                    sizeof(HeaderBuffer))))\n                {\n                    break;\n                }\n                Offset += offsetof(RomfsHeader, VolumeName);\n\n                if (0 != std::memcmp(\n                    HeaderBuffer,\n                    g_RomfsSignature,\n                    sizeof(g_RomfsSignature)))\n                {\n                    break;\n                }\n\n                this->m_FullSize = this->ReadUInt32(\n                    &HeaderBuffer[offsetof(RomfsHeader, FullSize)]);\n                this->m_VolumeName = std::string(\n                    static_cast<std::size_t>(\n                        BundleSize - Offset < g_RomfsMaximumPathLength\n                        ? BundleSize - Offset\n                        : g_RomfsMaximumPathLength),\n                    '\\0');\n                if (FAILED(this->ReadFileStream(\n                    Offset,\n                    &this->m_VolumeName[0],\n                    this->m_VolumeName.size())))\n                {\n                    break;\n                }\n                this->m_VolumeName.resize(\n                    std::strlen(this->m_VolumeName.c_str()));\n                Offset += this->GetAlignedSize(\n                    static_cast<std::uint32_t>(this->m_VolumeName.size()) + 1,\n                    16);\n\n                std::uint64_t TotalFiles = 0;\n                std::uint64_t TotalBytes = BundleSize;\n\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                hr = this->GetAllPaths(Offset);\n                if (FAILED(hr))\n                {\n                    break;\n                }\n\n                TotalFiles = this->m_TemporaryFilePaths.size();\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                this->m_FilePaths.clear();\n\n                for (auto const& Item : this->m_TemporaryFilePaths)\n                {\n                    this->m_FilePaths.emplace_back(Item.second);\n                }\n                this->m_TemporaryFilePaths.clear();\n\n                hr = S_OK;\n\n            } while (false);\n\n            if (S_OK != hr)\n            {\n                this->Close();\n            }\n            else\n            {\n                this->m_IsInitialized = true;\n            }\n\n            return hr;\n        }\n\n        HRESULT STDMETHODCALLTYPE Close()\n        {\n            this->m_IsInitialized = false;\n            this->m_FilePaths.clear();\n            this->m_VolumeName.clear();\n            this->m_FullSize = 0;\n            if (this->m_FileStream)\n            {\n                this->m_FileStream->Release();\n                this->m_FileStream = nullptr;\n            }\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfItems(\n            _Out_ PUINT32 NumItems)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!NumItems)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetProperty(\n            _In_ UINT32 Index,\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!(Index < this->m_FilePaths.size()))\n            {\n                return E_INVALIDARG;\n            }\n\n            RomfsFilePathInformation& Information = this->m_FilePaths[Index];\n\n            switch (PropId)\n            {\n            case SevenZipArchivePath:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_FilePaths[Index].Path).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveIsDirectory:\n            {\n                Value->boolVal =\n                    RomfsFileType::Directory == Information.Type\n                    ? VARIANT_TRUE\n                    : VARIANT_FALSE;\n                Value->vt = VT_BOOL;\n                break;\n            }\n            case SevenZipArchiveSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePackSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveSymbolicLink:\n            {\n                if (RomfsFileType::SymbolicLink == Information.Type)\n                {\n                    std::string SymbolicLink(Information.Size, '\\0');\n                    if (FAILED(this->ReadFileStream(\n                        Information.Offset,\n                        &SymbolicLink[0],\n                        SymbolicLink.size())))\n                    {\n                        SymbolicLink.clear();\n                    }\n\n                    if (!SymbolicLink.empty())\n                    {\n                        Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                            CP_UTF8,\n                            SymbolicLink).c_str());\n                        if (Value->bstrVal)\n                        {\n                            Value->vt = VT_BSTR;\n                        }\n                    }\n                }\n                break;\n            }\n            case SevenZipArchiveHardLink:\n            {\n                if (RomfsFileType::HardLink == Information.Type)\n                {\n                    std::string HardLink;\n                    for (RomfsFilePathInformation& Item : this->m_FilePaths)\n                    {\n                        if (Item.Inode == Information.Inode &&\n                            Item.Path != Information.Path)\n                        {\n                            HardLink = Item.Path;\n                            break;\n                        }\n                    }\n\n                    if (!HardLink.empty())\n                    {\n                        Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                            CP_UTF8,\n                            HardLink).c_str());\n                        if (Value->bstrVal)\n                        {\n                            Value->vt = VT_BSTR;\n                        }\n                    }\n                }\n                break;\n            }\n            case SevenZipArchiveInode:\n            {\n                Value->uhVal.QuadPart = this->m_FilePaths[Index].Inode;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            UNREFERENCED_PARAMETER(Value);\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE Extract(\n            _In_opt_ const PUINT32 Indices,\n            _In_ UINT32 NumItems,\n            _In_ BOOL TestMode,\n            _In_ IArchiveExtractCallback* ExtractCallback)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            HRESULT hr = S_OK;\n\n            INT32 AskMode = TestMode\n                ? SevenZipExtractAskModeTest\n                : SevenZipExtractAskModeExtract;\n\n            const bool AllFilesMode =\n                static_cast<UINT32>(-1) == NumItems;\n            if (AllFilesMode)\n            {\n                NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            }\n\n            UINT64 TotalSize = 0;\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                RomfsFilePathInformation& Information =\n                    this->m_FilePaths[ActualFileIndex];\n                TotalSize += Information.Size;\n            }\n            ExtractCallback->SetTotal(TotalSize);\n\n            UINT64 Completed = 0;\n\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                RomfsFilePathInformation& Information =\n                    this->m_FilePaths[ActualFileIndex];\n\n                Completed += Information.Size;\n                hr = ExtractCallback->SetCompleted(&Completed);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                hr = ExtractCallback->PrepareOperation(AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                ISequentialOutStream* OutputStream = nullptr;\n                hr = ExtractCallback->GetStream(\n                    Indices[i],\n                    &OutputStream,\n                    AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n                if (!OutputStream)\n                {\n                    continue;\n                }\n\n                bool Succeeded = false;\n                std::vector<std::uint8_t> Buffer(Information.Size);\n                if (SUCCEEDED(this->ReadFileStream(\n                    Information.Offset,\n                    &Buffer[0],\n                    Information.Size)))\n                {\n                    UINT32 ProceededSize = 0;\n                    Succeeded = SUCCEEDED(OutputStream->Write(\n                        &Buffer[0],\n                        static_cast<UINT32>(Information.Size),\n                        &ProceededSize));\n                }\n\n                OutputStream->Release();\n\n                ExtractCallback->SetOperationResult(\n                    Succeeded\n                    ? SevenZipExtractOperationResultSuccess\n                    : SevenZipExtractOperationResultUnavailable);\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchiveProperty(\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!Value)\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!this->m_IsInitialized)\n            {\n                Value->vt = VT_EMPTY;\n                return S_OK;\n            }\n\n            switch (PropId)\n            {\n            case SevenZipArchivePhysicalSize:\n            {\n                Value->uhVal.QuadPart = this->m_FullSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveVolumeName:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_VolumeName).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            default:\n                break;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumProps = g_PropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetPropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_PropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_PropertyItems[Index].Property;\n            *VarType = g_PropertyItems[Index].Type;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfArchiveProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n            *NumProps = g_ArchivePropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchivePropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_ArchivePropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_ArchivePropertyItems[Index].Property;\n            *VarType = g_ArchivePropertyItems[Index].Type;\n            return S_OK;\n        }\n    };\n\n    IInArchive* CreateRomfs()\n    {\n        return new Romfs();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Archive.Ufs.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Archive.Ufs.cpp\n * PURPOSE:    Implementation for UFS/UFS2 file system image readonly support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\n#ifdef _MSC_VER\n#if _MSC_VER > 1000\n#pragma once\n#endif\n#if (_MSC_VER >= 1200)\n#pragma warning(push)\n#endif\n#pragma warning(disable:4201) // nameless struct/union\n#endif\n\n#include \"FreeBSD/fs.h\"\n#include \"FreeBSD/dir.h\"\n\n#ifdef _MSC_VER\n#if (_MSC_VER >= 1200)\n#pragma warning(pop)\n#else\n#pragma warning(default:4201) // nameless struct/union\n#endif\n#endif\n\n#include <map>\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\nnamespace\n{\n    // Win32 time epoch is 00:00:00, January 1 1601.\n    // UNIX time epoch is 00:00:00, January 1 1970.\n    // There are 11644473600 seconds between these two epochs.\n    const std::uint64_t SecondsBetweenWin32TimeAndUnixTime = 11644473600ULL;\n\n    FILETIME ToFileTime(\n        std::uint64_t UnixTimeSeconds,\n        std::uint64_t UnixTimeNanoseconds)\n    {\n        std::uint64_t RawResult = UnixTimeSeconds;\n        RawResult += SecondsBetweenWin32TimeAndUnixTime;\n        RawResult *= 1000 * 1000 * 10;\n        RawResult += UnixTimeNanoseconds / 100;\n        FILETIME Result;\n        Result.dwLowDateTime = static_cast<DWORD>(RawResult);\n        Result.dwHighDateTime = static_cast<DWORD>(RawResult >> 32);\n        return Result;\n    }\n\n    const std::int32_t g_SuperBlockSearchList[] = SBLOCKSEARCH;\n\n    struct PropertyItem\n    {\n        PROPID Property;\n        VARTYPE Type;\n    };\n\n    const PropertyItem g_ArchivePropertyItems[] =\n    {\n        { SevenZipArchiveModifiedTime, VT_FILETIME },\n        { SevenZipArchiveFreeSpace, VT_UI8 },\n        { SevenZipArchiveClusterSize, VT_UI4 },\n        { SevenZipArchiveVolumeName, VT_BSTR },\n        { SevenZipArchiveUnpackVersion, VT_UI8 },\n    };\n\n    const std::size_t g_ArchivePropertyItemsCount =\n        sizeof(g_ArchivePropertyItems) / sizeof(*g_ArchivePropertyItems);\n\n    const PropertyItem g_PropertyItems[] =\n    {\n        { SevenZipArchivePath, VT_BSTR },\n        { SevenZipArchiveIsDirectory, VT_BOOL },\n        { SevenZipArchiveSize, VT_UI8 },\n        { SevenZipArchivePackSize, VT_UI8 },\n        { SevenZipArchiveCreationTime, VT_FILETIME },\n        { SevenZipArchiveAccessTime, VT_FILETIME },\n        { SevenZipArchiveModifiedTime, VT_FILETIME },\n        { SevenZipArchiveLinks, VT_UI8 },\n        { SevenZipArchivePosixAttributes, VT_UI4 },\n        { SevenZipArchiveSymbolicLink, VT_BSTR },\n        { SevenZipArchiveInode, VT_UI8 },\n        { SevenZipArchiveUserId, VT_UI4 },\n        { SevenZipArchiveGroupId, VT_UI4 },\n    };\n\n    const std::size_t g_PropertyItemsCount =\n        sizeof(g_PropertyItems) / sizeof(*g_PropertyItems);\n\n    struct UfsInodeInformation\n    {\n        std::uint16_t Mode = 0;\n        std::uint16_t NumberOfHardLinks = 0;\n        std::uint32_t OwnerUserId = 0;\n        std::uint32_t GroupId = 0;\n        std::int64_t DeviceId = 0;\n        std::uint64_t FileSize = 0;\n        std::uint64_t AllocatedBlocks = 0;\n        std::int64_t LastAccessTimeSeconds = 0;\n        std::int64_t LastWriteTimeSeconds = 0;\n        std::int64_t ChangeTimeSeconds = 0;\n        std::int64_t BirthTimeSeconds = 0;\n        std::int32_t LastAccessTimeNanoseconds = 0;\n        std::int32_t LastWriteTimeNanoseconds = 0;\n        std::int32_t ChangeTimeNanoseconds = 0;\n        std::int32_t BirthTimeNanoseconds = 0;\n        std::string EmbeddedSymbolLink;\n        std::vector<std::uint64_t> BlockOffsets;\n    };\n\n    struct UfsFilePathInformation\n    {\n        std::string Path;\n        std::uint32_t Inode = 0;\n        UfsInodeInformation Information;\n    };\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    struct Ufs : public Mile::ComObject<Ufs, IInArchive>\n    {\n    private:\n\n        IInStream* m_FileStream = nullptr;\n        bool m_IsUfs2 = false;\n        bool m_IsBigEndian = false;\n        fs m_SuperBlock = {};\n        std::map<std::string, std::uint32_t> m_TemporaryFilePaths;\n        std::vector<UfsFilePathInformation> m_FilePaths;\n        bool m_IsInitialized = false;\n\n    private:\n\n        std::uint8_t ReadUInt8(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt8(BaseAddress);\n        }\n\n        std::uint16_t ReadUInt16(\n            const void* BaseAddress)\n        {\n            return this->m_IsBigEndian\n                ? ::MileReadUInt16BigEndian(BaseAddress)\n                : ::MileReadUInt16LittleEndian(BaseAddress);\n        }\n\n        std::uint32_t ReadUInt32(\n            const void* BaseAddress)\n        {\n            return this->m_IsBigEndian\n                ? ::MileReadUInt32BigEndian(BaseAddress)\n                : ::MileReadUInt32LittleEndian(BaseAddress);\n        }\n\n        std::uint64_t ReadUInt64(\n            const void* BaseAddress)\n        {\n            return this->m_IsBigEndian\n                ? ::MileReadUInt64BigEndian(BaseAddress)\n                : ::MileReadUInt64LittleEndian(BaseAddress);\n        }\n\n        std::int8_t ReadInt8(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int8_t>(this->ReadUInt8(BaseAddress));\n        }\n\n        std::int16_t ReadInt16(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int16_t>(this->ReadUInt16(BaseAddress));\n        }\n\n        std::int32_t ReadInt32(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int32_t>(this->ReadUInt32(BaseAddress));\n        }\n\n        std::int64_t ReadInt64(\n            const void* BaseAddress)\n        {\n            return static_cast<std::int64_t>(this->ReadUInt64(BaseAddress));\n        }\n\n        HRESULT ReadFileStream(\n            _In_ INT64 Offset,\n            _Out_ PVOID Buffer,\n            _In_ SIZE_T NumberOfBytesToRead)\n        {\n            if (!this->m_FileStream)\n            {\n                return S_FALSE;\n            }\n\n            if (SUCCEEDED(this->m_FileStream->Seek(\n                Offset,\n                STREAM_SEEK_SET,\n                nullptr)))\n            {\n                SIZE_T NumberOfBytesRead = 0;\n                if (SUCCEEDED(::NanaZipCodecsReadInputStream(\n                    this->m_FileStream,\n                    Buffer,\n                    NumberOfBytesToRead,\n                    &NumberOfBytesRead)))\n                {\n                    if (NumberOfBytesToRead == NumberOfBytesRead)\n                    {\n                        return S_OK;\n                    }\n                }\n            }\n\n            return S_FALSE;\n        }\n\n    private:\n\n        std::uint64_t GetTotalBlocks()\n        {\n            return this->m_IsUfs2\n                ? this->ReadInt64(&this->m_SuperBlock.fs_dsize)\n                : this->ReadInt32(&this->m_SuperBlock.fs_old_dsize);\n        }\n\n        std::uint64_t GetCylinderGroupStart(\n            std::uint64_t const& CylinderGroup)\n        {\n            std::uint64_t Result = CylinderGroup;\n            Result *= this->ReadInt32(&this->m_SuperBlock.fs_fpg);\n            if (!this->m_IsUfs2)\n            {\n                std::int32_t Offset = this->ReadInt32(\n                    &this->m_SuperBlock.fs_old_cgoffset);\n                std::int32_t Mask = this->ReadInt32(\n                    &this->m_SuperBlock.fs_old_cgmask);\n                Result += Offset * (CylinderGroup & ~Mask);\n            }\n            return Result;\n        }\n\n        std::int32_t GetFragmentBlockSize()\n        {\n            return this->ReadInt32(&this->m_SuperBlock.fs_fsize);\n        }\n\n        std::int32_t GetBlockSize()\n        {\n            return this->ReadInt32(&this->m_SuperBlock.fs_bsize);\n        }\n\n        std::size_t GetDirectoryInodeSize()\n        {\n            return this->m_IsUfs2 ? sizeof(ufs2_dinode) : sizeof(ufs1_dinode);\n        }\n\n        std::int32_t GetMaximumEmbeddedSymbolLinkLength()\n        {\n            return this->ReadInt32(&this->m_SuperBlock.fs_maxsymlinklen);\n        }\n\n        std::uint64_t GetInodeOffset(\n            std::uint32_t const& Inode)\n        {\n            std::uint32_t InodePerCylinderGroup = this->ReadUInt32(\n                &this->m_SuperBlock.fs_ipg);\n            std::uint32_t CylinderGroup = Inode / InodePerCylinderGroup;\n            std::uint32_t SubIndex = Inode % InodePerCylinderGroup;\n            std::uint64_t Result = this->GetCylinderGroupStart(CylinderGroup);\n            Result += this->ReadInt32(&this->m_SuperBlock.fs_iblkno);\n            Result *= this->GetFragmentBlockSize();\n            Result += SubIndex * this->GetDirectoryInodeSize();\n            return Result;\n        }\n\n        bool GetInodeInformation(\n            std::uint32_t const& Inode,\n            UfsInodeInformation& Information)\n        {\n            Information = UfsInodeInformation();\n\n            std::vector<std::uint8_t> DirectoryInodeBuffer(\n                this->GetDirectoryInodeSize());\n            ufs1_dinode* Ufs1DirectoryInode = reinterpret_cast<ufs1_dinode*>(\n                &DirectoryInodeBuffer[0]);\n            ufs2_dinode* Ufs2DirectoryInode = reinterpret_cast<ufs2_dinode*>(\n                &DirectoryInodeBuffer[0]);\n\n            if (FAILED(this->ReadFileStream(\n                this->GetInodeOffset(Inode),\n                &DirectoryInodeBuffer[0],\n                DirectoryInodeBuffer.size())))\n            {\n                return false;\n            }\n\n            Information.Mode = this->ReadUInt16(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_mode\n                : &Ufs1DirectoryInode->di_mode);\n            Information.NumberOfHardLinks = this->ReadUInt16(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_nlink\n                : &Ufs1DirectoryInode->di_nlink);\n            if (UFS_LINK_MAX - 1 < Information.NumberOfHardLinks)\n            {\n                // Maximum number of hard links is UFS_LINK_MAX - 1, more than\n                // that are reserved for special values.\n                return false;\n            }\n            Information.OwnerUserId = this->ReadUInt32(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_uid\n                : &Ufs1DirectoryInode->di_uid);\n            Information.GroupId = this->ReadUInt32(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_gid\n                : &Ufs1DirectoryInode->di_gid);\n            Information.DeviceId = this->m_IsUfs2\n                ? this->ReadInt64(&Ufs2DirectoryInode->di_db[0])\n                : this->ReadInt32(&Ufs1DirectoryInode->di_db[0]);\n            Information.FileSize = this->ReadUInt64(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_size\n                : &Ufs1DirectoryInode->di_size);\n            Information.AllocatedBlocks = this->m_IsUfs2\n                ? this->ReadInt64(&Ufs2DirectoryInode->di_blocks)\n                : this->ReadInt32(&Ufs1DirectoryInode->di_blocks);\n            Information.LastAccessTimeSeconds = this->m_IsUfs2\n                ? this->ReadInt64(&Ufs2DirectoryInode->di_atime)\n                : this->ReadInt32(&Ufs1DirectoryInode->di_atime);\n            Information.LastWriteTimeSeconds = this->m_IsUfs2\n                ? this->ReadInt64(&Ufs2DirectoryInode->di_mtime)\n                : this->ReadInt32(&Ufs1DirectoryInode->di_mtime);\n            Information.ChangeTimeSeconds = this->m_IsUfs2\n                ? this->ReadInt64(&Ufs2DirectoryInode->di_ctime)\n                : this->ReadInt32(&Ufs1DirectoryInode->di_ctime);\n            if (this->m_IsUfs2)\n            {\n                Information.BirthTimeSeconds = this->ReadInt64(\n                    &Ufs2DirectoryInode->di_birthtime);\n            }\n            Information.LastAccessTimeNanoseconds = this->ReadInt32(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_atimensec\n                : &Ufs1DirectoryInode->di_atimensec);\n            Information.LastWriteTimeNanoseconds = this->ReadInt32(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_mtimensec\n                : &Ufs1DirectoryInode->di_mtimensec);\n            Information.ChangeTimeNanoseconds = this->ReadInt32(\n                this->m_IsUfs2\n                ? &Ufs2DirectoryInode->di_ctimensec\n                : &Ufs1DirectoryInode->di_ctimensec);\n            if (this->m_IsUfs2)\n            {\n                Information.BirthTimeNanoseconds = this->ReadInt32(\n                    &Ufs2DirectoryInode->di_birthnsec);\n            }\n\n            if ((Information.Mode & IFMT) == IFLNK)\n            {\n                if (Information.FileSize\n                    <= this->GetMaximumEmbeddedSymbolLinkLength())\n                {\n                    std::string EmbeddedSymbolLink = std::string(\n                        reinterpret_cast<char*>(this->m_IsUfs2\n                            ? Ufs2DirectoryInode->di_shortlink\n                            : Ufs1DirectoryInode->di_shortlink),\n                        this->m_IsUfs2\n                        ? sizeof(Ufs2DirectoryInode->di_shortlink)\n                        : sizeof(Ufs1DirectoryInode->di_shortlink));\n                    EmbeddedSymbolLink.resize(\n                        std::strlen(EmbeddedSymbolLink.c_str()));\n                    Information.EmbeddedSymbolLink = EmbeddedSymbolLink;\n                    return true;\n                }\n            }\n\n            std::int32_t BlockSize = this->GetBlockSize();\n            std::int32_t FragmentBlockSize = this->GetFragmentBlockSize();\n            std::uint64_t ActualFileSize = 0;\n\n            for (std::size_t i = 0; i < UFS_NDADDR; ++i)\n            {\n                std::int64_t CurrentBlock = this->m_IsUfs2\n                    ? this->ReadInt64(&Ufs2DirectoryInode->di_db[i])\n                    : this->ReadInt32(&Ufs1DirectoryInode->di_db[i]);\n                Information.BlockOffsets.emplace_back(\n                    CurrentBlock * FragmentBlockSize);\n                ActualFileSize += BlockSize;\n                if (ActualFileSize >= Information.FileSize)\n                {\n                    return true;\n                }\n            }\n\n            std::vector<std::uint8_t> IndirectBuffer0(BlockSize);\n            std::vector<std::uint8_t> IndirectBuffer1(BlockSize);\n            std::vector<std::uint8_t> IndirectBuffer2(BlockSize);\n\n            std::int32_t* Ufs1IndirectBlocks0 =\n                reinterpret_cast<std::int32_t*>(&IndirectBuffer0[0]);\n            std::int32_t* Ufs1IndirectBlocks1 =\n                reinterpret_cast<std::int32_t*>(&IndirectBuffer1[0]);\n            std::int32_t* Ufs1IndirectBlocks2 =\n                reinterpret_cast<std::int32_t*>(&IndirectBuffer2[0]);\n            std::uint64_t Ufs1IndirectBlockMaximum =\n                BlockSize / sizeof(std::int32_t);\n\n            std::int64_t* Ufs2IndirectBlocks0 =\n                reinterpret_cast<std::int64_t*>(&IndirectBuffer0[0]);\n            std::int64_t* Ufs2IndirectBlocks1 =\n                reinterpret_cast<std::int64_t*>(&IndirectBuffer1[0]);\n            std::int64_t* Ufs2IndirectBlocks2 =\n                reinterpret_cast<std::int64_t*>(&IndirectBuffer2[0]);\n            std::uint64_t Ufs2IndirectBlockMaximum =\n                BlockSize / sizeof(std::int64_t);\n\n            std::uint64_t IndirectBlockMaximum = this->m_IsUfs2\n                ? Ufs2IndirectBlockMaximum\n                : Ufs1IndirectBlockMaximum;\n\n            if (FAILED(this->ReadFileStream(\n                FragmentBlockSize * (this->m_IsUfs2\n                    ? this->ReadInt64(&Ufs2DirectoryInode->di_ib[0])\n                    : this->ReadInt32(&Ufs1DirectoryInode->di_ib[0])),\n                &IndirectBuffer0[0],\n                BlockSize)))\n            {\n                return false;\n            }\n\n            for (std::size_t i = 0; i < IndirectBlockMaximum; ++i)\n            {\n                std::int64_t CurrentBlock = this->m_IsUfs2\n                    ? this->ReadInt64(&Ufs2IndirectBlocks0[i])\n                    : this->ReadInt32(&Ufs1IndirectBlocks0[i]);\n                Information.BlockOffsets.emplace_back(\n                    CurrentBlock * FragmentBlockSize);\n                ActualFileSize += BlockSize;\n                if (ActualFileSize >= Information.FileSize)\n                {\n                    return true;\n                }\n            }\n\n            if (FAILED(this->ReadFileStream(\n                FragmentBlockSize * (this->m_IsUfs2\n                    ? this->ReadInt64(&Ufs2DirectoryInode->di_ib[1])\n                    : this->ReadInt32(&Ufs1DirectoryInode->di_ib[1])),\n                &IndirectBuffer1[0],\n                BlockSize)))\n            {\n                return false;\n            }\n\n            for (std::size_t j = 0; j < IndirectBlockMaximum; ++j)\n            {\n                if (FAILED(this->ReadFileStream(\n                    FragmentBlockSize * (this->m_IsUfs2\n                        ? this->ReadInt64(&Ufs2IndirectBlocks1[j])\n                        : this->ReadInt32(&Ufs1IndirectBlocks1[j])),\n                    &IndirectBuffer0[0],\n                    BlockSize)))\n                {\n                    return false;\n                }\n\n                for (std::size_t i = 0; i < IndirectBlockMaximum; ++i)\n                {\n                    std::int64_t CurrentBlock = this->m_IsUfs2\n                        ? this->ReadInt64(&Ufs2IndirectBlocks0[i])\n                        : this->ReadInt32(&Ufs1IndirectBlocks0[i]);\n                    Information.BlockOffsets.emplace_back(\n                        CurrentBlock * FragmentBlockSize);\n                    ActualFileSize += BlockSize;\n                    if (ActualFileSize >= Information.FileSize)\n                    {\n                        return true;\n                    }\n                }\n            }\n\n            if (FAILED(this->ReadFileStream(\n                FragmentBlockSize * (this->m_IsUfs2\n                    ? this->ReadInt64(&Ufs2DirectoryInode->di_ib[2])\n                    : this->ReadInt32(&Ufs1DirectoryInode->di_ib[2])),\n                &IndirectBuffer2[0],\n                BlockSize)))\n            {\n                return false;\n            }\n\n            for (std::size_t k = 0; k < IndirectBlockMaximum; ++k)\n            {\n                if (FAILED(this->ReadFileStream(\n                    FragmentBlockSize * (this->m_IsUfs2\n                        ? this->ReadInt64(&Ufs2IndirectBlocks2[k])\n                        : this->ReadInt32(&Ufs1IndirectBlocks2[k])),\n                    &IndirectBuffer1[0],\n                    BlockSize)))\n                {\n                    return false;\n                }\n\n                for (std::size_t j = 0; j < IndirectBlockMaximum; ++j)\n                {\n                    if (FAILED(this->ReadFileStream(\n                        FragmentBlockSize * (this->m_IsUfs2\n                            ? this->ReadInt64(&Ufs2IndirectBlocks1[j])\n                            : this->ReadInt32(&Ufs1IndirectBlocks1[j])),\n                        &IndirectBuffer0[0],\n                        BlockSize)))\n                    {\n                        return false;\n                    }\n\n                    for (std::size_t i = 0; i < IndirectBlockMaximum; ++i)\n                    {\n                        std::int64_t CurrentBlock = this->m_IsUfs2\n                            ? this->ReadInt64(&Ufs2IndirectBlocks0[i])\n                            : this->ReadInt32(&Ufs1IndirectBlocks0[i]);\n                        Information.BlockOffsets.emplace_back(\n                            CurrentBlock * FragmentBlockSize);\n                        ActualFileSize += BlockSize;\n                        if (ActualFileSize >= Information.FileSize)\n                        {\n                            return true;\n                        }\n                    }\n                }\n            }\n\n            // The blocks described by the inode should be enough to cover the\n            // file size, if we reach here, it means the image is corrupted or\n            // something is wrong with the implementation.\n            return false;\n        }\n\n        bool GetAllPaths(\n            std::uint32_t const& RootInode,\n            std::string const& RootPath)\n        {\n            UfsInodeInformation Information;\n            if (!this->GetInodeInformation(RootInode, Information))\n            {\n                return false;\n            }\n\n            if (!RootPath.empty())\n            {\n                UfsFilePathInformation Current;\n                Current.Path = RootPath;\n                // Remove the slash.\n                Current.Path.resize(Current.Path.size() - 1);\n                Current.Inode = RootInode;\n                Current.Information = Information;\n                this->m_FilePaths.emplace_back(Current);\n            }\n\n            std::int32_t BlockSize = this->GetBlockSize();\n\n            std::size_t BlockOffsetsCount = Information.BlockOffsets.size();\n\n            std::size_t ActualSize = BlockOffsetsCount * BlockSize;\n            if (MAXDIRSIZE < ActualSize)\n            {\n                // The directory entries buffer size is too large.\n                // Information.FileSize is bigger than the actual size of the\n                // directory entries via GetInodeInformation method before.\n                return false;\n            }\n\n            std::vector<std::uint8_t> Buffer(ActualSize);\n            for (std::size_t i = 0; i < BlockOffsetsCount; ++i)\n            {\n                if (FAILED(this->ReadFileStream(\n                    Information.BlockOffsets[i],\n                    &Buffer[i * BlockSize],\n                    BlockSize)))\n                {\n                    return false;\n                }\n            }\n\n            // The minimum size of a directory entry can be contained the empty\n            // name string with the null terminator because all names are\n            // guaranteed null terminated.\n            const std::size_t MinimumDirectoryEntrySize =\n                offsetof(direct, d_name) + 1;\n\n            std::size_t EndOffset = static_cast<std::size_t>(\n                Information.FileSize);\n            for (size_t CurrentOffset = 0; CurrentOffset < EndOffset;)\n            {\n                if (EndOffset < CurrentOffset + MinimumDirectoryEntrySize)\n                {\n                    // The directory entry is too small to be valid.\n                    return false;\n                }\n\n                direct* Current = reinterpret_cast<direct*>(\n                    &Buffer[CurrentOffset]);\n\n                std::uint32_t Inode = this->ReadUInt32(&Current->d_ino);\n                std::uint16_t RecordLength = this->ReadUInt16(&Current->d_reclen);\n                if (MinimumDirectoryEntrySize > RecordLength ||\n                    EndOffset < CurrentOffset + RecordLength)\n                {\n                    // The directory entry record length is invalid.\n                    return false;\n                }\n                std::uint8_t Type = this->ReadUInt8(&Current->d_type);\n                std::uint8_t NameLength = this->ReadUInt8(&Current->d_namlen);\n                if (UFS_MAXNAMLEN < NameLength)\n                {\n                    // The directory entry name length is too large.\n                    return false;\n                }\n                Current->d_name[NameLength] = '\\0';\n                std::string Name = std::string(Current->d_name);\n                if (\".\" == Name || \"..\" == Name)\n                {\n                    // Just Skip\n                }\n                else if (DT_DIR == Type)\n                {\n                    if (!this->GetAllPaths(Inode, RootPath + Name + \"/\"))\n                    {\n                        return false;\n                    }\n                }\n                else\n                {\n                    this->m_TemporaryFilePaths.emplace(RootPath + Name, Inode);\n                }\n\n                CurrentOffset += RecordLength;\n            }\n\n            return true;\n        }\n\n    public:\n\n        Ufs()\n        {\n\n        }\n\n        HRESULT STDMETHODCALLTYPE Open(\n            _In_ IInStream* Stream,\n            _In_opt_ const PUINT64 MaxCheckStartPosition,\n            _In_opt_ IArchiveOpenCallback* OpenCallback)\n        {\n            UNREFERENCED_PARAMETER(MaxCheckStartPosition);\n            UNREFERENCED_PARAMETER(OpenCallback);\n\n            if (!Stream)\n            {\n                return E_INVALIDARG;\n            }\n\n            HRESULT hr = S_FALSE;\n\n            do\n            {\n                this->Close();\n\n                this->m_FileStream = Stream;\n                this->m_FileStream->AddRef();\n\n                for (size_t i = 0; -1 != g_SuperBlockSearchList[i]; ++i)\n                {\n                    if (FAILED(this->ReadFileStream(\n                        g_SuperBlockSearchList[i],\n                        &this->m_SuperBlock,\n                        sizeof(this->m_SuperBlock))))\n                    {\n                        break;\n                    }\n\n                    this->m_IsBigEndian = false;\n                    std::uint32_t Signature = this->ReadUInt32(\n                        &this->m_SuperBlock.fs_magic);\n                    if (FS_UFS2_MAGIC == Signature)\n                    {\n                        this->m_IsUfs2 = true;\n                    }\n                    else if (FS_UFS1_MAGIC == Signature)\n                    {\n                        this->m_IsUfs2 = false;\n                    }\n                    else\n                    {\n                        this->m_IsBigEndian = true;\n                        Signature = this->ReadUInt32(\n                            &this->m_SuperBlock.fs_magic);\n                        if (FS_UFS2_MAGIC == Signature)\n                        {\n                            this->m_IsUfs2 = true;\n                        }\n                        else if (FS_UFS1_MAGIC == Signature)\n                        {\n                            this->m_IsUfs2 = false;\n                        }\n                        else\n                        {\n                            continue;\n                        }\n                    }\n\n                    std::int64_t SuperBlockLocation = this->ReadInt64(\n                        &this->m_SuperBlock.fs_sblockloc);\n                    if (this->m_IsUfs2)\n                    {\n                        if (SBLOCK_UFS2 != SuperBlockLocation)\n                        {\n                            continue;\n                        }\n                    }\n                    else\n                    {\n                        if (SuperBlockLocation < 0 ||\n                            SuperBlockLocation > SBLOCK_UFS1)\n                        {\n                            continue;\n                        }\n                    }\n\n                    std::int32_t FragmentsCount = this->ReadInt32(\n                        &this->m_SuperBlock.fs_frag);\n                    if (FragmentsCount < 1)\n                    {\n                        continue;\n                    }\n\n                    std::uint32_t CylinderGroupsCount = this->ReadUInt32(\n                        &this->m_SuperBlock.fs_ncg);\n                    if (CylinderGroupsCount < 1)\n                    {\n                        continue;\n                    }\n\n                    std::int32_t BlockSize = this->GetBlockSize();\n                    if (BlockSize < MINBSIZE)\n                    {\n                        continue;\n                    }\n\n                    std::int32_t SuperBlockSize = this->ReadInt32(\n                        &this->m_SuperBlock.fs_sbsize);\n                    if (SuperBlockSize > SBLOCKSIZE ||\n                        SuperBlockSize < sizeof(fs))\n                    {\n                        continue;\n                    }\n\n                    hr = S_OK;\n                    break;\n                }\n                if (S_OK != hr)\n                {\n                    break;\n                }\n\n                std::uint64_t TotalFiles = 0;\n                std::uint64_t TotalBytes =\n                    this->GetTotalBlocks() * this->GetFragmentBlockSize();\n\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                this->m_FilePaths.clear();\n\n                if (!this->GetAllPaths(UFS_ROOTINO, \"\"))\n                {\n                    // The file system image is corrupted or something is wrong\n                    // with the implementation.\n                    return S_FALSE;\n                }\n                TotalFiles = this->m_FilePaths.size();\n\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                for (auto const& Item : this->m_TemporaryFilePaths)\n                {\n                    UfsFilePathInformation Current;\n                    Current.Path = Item.first;\n                    Current.Inode = Item.second;\n                    if (!this->GetInodeInformation(\n                        Current.Inode,\n                        Current.Information))\n                    {\n                        continue;\n                    }\n                    this->m_FilePaths.emplace_back(Current);\n                }\n                this->m_TemporaryFilePaths.clear();\n\n            } while (false);\n\n            if (S_OK != hr)\n            {\n                this->Close();\n            }\n            else\n            {\n                this->m_IsInitialized = true;\n            }\n\n            return hr;\n        }\n\n        HRESULT STDMETHODCALLTYPE Close()\n        {\n            this->m_IsInitialized = false;\n            this->m_FilePaths.clear();\n            std::memset(&this->m_SuperBlock, 0, sizeof(this->m_SuperBlock));\n            this->m_IsBigEndian = false;\n            this->m_IsUfs2 = false;\n            if (this->m_FileStream)\n            {\n                this->m_FileStream->Release();\n                this->m_FileStream = nullptr;\n            }\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfItems(\n            _Out_ PUINT32 NumItems)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!NumItems)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetProperty(\n            _In_ UINT32 Index,\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!(Index < this->m_FilePaths.size()))\n            {\n                return E_INVALIDARG;\n            }\n\n            UfsInodeInformation& Information =\n                this->m_FilePaths[Index].Information;\n\n            switch (PropId)\n            {\n            case SevenZipArchivePath:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_FilePaths[Index].Path).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveIsDirectory:\n            {\n                Value->boolVal =\n                    Information.Mode & IFDIR\n                    ? VARIANT_TRUE\n                    : VARIANT_FALSE;\n                Value->vt = VT_BOOL;\n                break;\n            }\n            case SevenZipArchiveSize:\n            {\n                Value->uhVal.QuadPart = Information.FileSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePackSize:\n            {\n                // block size used in the stat struct\n                const std::uint64_t S_BLKSIZE = 512;\n                Value->uhVal.QuadPart = Information.AllocatedBlocks * S_BLKSIZE;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveCreationTime:\n            {\n                if (this->m_IsUfs2)\n                {\n                    Value->filetime = ::ToFileTime(\n                        Information.BirthTimeSeconds,\n                        Information.BirthTimeNanoseconds);\n                    Value->vt = VT_FILETIME;\n                }\n                break;\n            }\n            case SevenZipArchiveAccessTime:\n            {\n                Value->filetime = ::ToFileTime(\n                    Information.LastAccessTimeSeconds,\n                    Information.LastAccessTimeNanoseconds);\n                Value->vt = VT_FILETIME;\n                break;\n            }\n            case SevenZipArchiveModifiedTime:\n            {\n                Value->filetime = ::ToFileTime(\n                    Information.LastWriteTimeSeconds,\n                    Information.LastWriteTimeNanoseconds);\n                Value->vt = VT_FILETIME;\n                break;\n            }\n            case SevenZipArchiveLinks:\n            {\n                Value->uhVal.QuadPart = Information.NumberOfHardLinks;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePosixAttributes:\n            {\n                Value->ulVal = Information.Mode;\n                Value->vt = VT_UI4;\n                break;\n            }\n            case SevenZipArchiveSymbolicLink:\n            {\n                if ((Information.Mode & IFMT) == IFLNK)\n                {\n                    std::string SymbolLink;\n\n                    if (!Information.EmbeddedSymbolLink.empty())\n                    {\n                        SymbolLink = Information.EmbeddedSymbolLink;\n                    }\n                    else\n                    {\n                        std::int32_t BlockSize =\n                            this->GetBlockSize();\n                        std::size_t BlockOffsetsCount =\n                            Information.BlockOffsets.size();\n                        std::vector<std::uint8_t> Buffer(\n                            BlockOffsetsCount * BlockSize);\n                        for (std::size_t i = 0; i < BlockOffsetsCount; ++i)\n                        {\n                            if (FAILED(this->ReadFileStream(\n                                Information.BlockOffsets[i],\n                                &Buffer[i * BlockSize],\n                                BlockSize)))\n                            {\n                                Buffer.clear();\n                                break;\n                            }\n                        }\n                        if (!Buffer.empty())\n                        {\n                            // The path length of the symbolic link should be\n                            // less than MAXDIRSIZE (0x7FFFFFFF).\n                            SymbolLink = std::string(\n                                reinterpret_cast<char*>(&Buffer[0]),\n                                static_cast<std::size_t>(Information.FileSize));\n                        }\n                    }\n\n                    if (!SymbolLink.empty())\n                    {\n                        Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                            CP_UTF8,\n                            SymbolLink).c_str());\n                        if (Value->bstrVal)\n                        {\n                            Value->vt = VT_BSTR;\n                        }\n                    }\n                }\n                break;\n            }\n            case SevenZipArchiveInode:\n            {\n                Value->uhVal.QuadPart = this->m_FilePaths[Index].Inode;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveUserId:\n            {\n                Value->ulVal = Information.OwnerUserId;\n                Value->vt = VT_UI4;\n                break;\n            }\n            case SevenZipArchiveGroupId:\n            {\n                Value->ulVal = Information.GroupId;\n                Value->vt = VT_UI4;\n                break;\n            }\n            default:\n                break;\n            }\n\n            UNREFERENCED_PARAMETER(Value);\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE Extract(\n            _In_opt_ const PUINT32 Indices,\n            _In_ UINT32 NumItems,\n            _In_ BOOL TestMode,\n            _In_ IArchiveExtractCallback* ExtractCallback)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            HRESULT hr = S_OK;\n\n            INT32 AskMode = TestMode\n                ? SevenZipExtractAskModeTest\n                : SevenZipExtractAskModeExtract;\n\n            const bool AllFilesMode =\n                static_cast<UINT32>(-1) == NumItems;\n            if (AllFilesMode)\n            {\n                NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            }\n\n            UINT64 TotalSize = 0;\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                UfsInodeInformation& Information =\n                    this->m_FilePaths[ActualFileIndex].Information;\n                TotalSize += Information.FileSize;\n            }\n            ExtractCallback->SetTotal(TotalSize);\n\n            UINT64 Completed = 0;\n\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                UfsInodeInformation& Information =\n                    this->m_FilePaths[ActualFileIndex].Information;\n\n                Completed += Information.FileSize;\n                hr = ExtractCallback->SetCompleted(&Completed);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                hr = ExtractCallback->PrepareOperation(AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                ISequentialOutStream* OutputStream = nullptr;\n                hr = ExtractCallback->GetStream(\n                    Indices[i],\n                    &OutputStream,\n                    AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n                if (!OutputStream)\n                {\n                    continue;\n                }\n\n                std::uint32_t BlockSize = this->GetBlockSize();\n\n                UINT32 Todo = static_cast<UINT32>(Information.FileSize);\n                UINT32 Done = 0;\n\n                bool Failed = false;\n                for (std::uint64_t const& Offset : Information.BlockOffsets)\n                {\n                    if (!Todo)\n                    {\n                        // Done\n                        break;\n                    }\n\n                    UINT32 CurrentDo = Todo > BlockSize ? BlockSize : Todo;\n\n                    std::vector<std::uint8_t> Buffer(CurrentDo);\n                    if (FAILED(this->ReadFileStream(\n                        Offset,\n                        &Buffer[0],\n                        CurrentDo)))\n                    {\n                        Failed = true;\n                        break;\n                    }\n\n                    UINT32 ProceededSize = 0;\n                    hr = OutputStream->Write(\n                        &Buffer[0],\n                        CurrentDo,\n                        &ProceededSize);\n                    if (FAILED(hr))\n                    {\n                        Failed = true;\n                        break;\n                    }\n\n                    Todo -= CurrentDo;\n                    Done += CurrentDo;\n                }\n\n                OutputStream->Release();\n\n                ExtractCallback->SetOperationResult(\n                    Failed\n                    ? SevenZipExtractOperationResultUnavailable\n                    : SevenZipExtractOperationResultSuccess);\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchiveProperty(\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!Value)\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!this->m_IsInitialized)\n            {\n                Value->vt = VT_EMPTY;\n                return S_OK;\n            }\n\n            switch (PropId)\n            {\n            case SevenZipArchiveModifiedTime:\n            {\n                std::uint64_t PosixModifiedTimeSecond = 0;\n                if (this->m_IsUfs2)\n                {\n                    PosixModifiedTimeSecond = this->ReadInt64(\n                        &this->m_SuperBlock.fs_time);\n                }\n                else\n                {\n                    PosixModifiedTimeSecond = this->ReadInt32(\n                        &this->m_SuperBlock.fs_old_time);\n                }\n\n                Value->filetime = ::ToFileTime(PosixModifiedTimeSecond, 0);\n                Value->vt = VT_FILETIME;\n                break;\n            }\n            case SevenZipArchivePhysicalSize:\n            {\n                Value->uhVal.QuadPart =\n                    this->GetTotalBlocks() * this->GetFragmentBlockSize();\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveFreeSpace:\n            {\n                std::uint64_t FreeBlocks = 0;\n                if (this->m_IsUfs2)\n                {\n                    FreeBlocks = this->ReadInt64(\n                        &this->m_SuperBlock.fs_cstotal.cs_nbfree);\n                }\n                else\n                {\n                    FreeBlocks = this->ReadInt32(\n                        &this->m_SuperBlock.fs_old_cstotal.cs_nbfree);\n                }\n                FreeBlocks *= this->ReadInt32(\n                    &this->m_SuperBlock.fs_frag);\n                if (this->m_IsUfs2)\n                {\n                    FreeBlocks += this->ReadInt64(\n                        &this->m_SuperBlock.fs_cstotal.cs_nffree);\n                }\n                else\n                {\n                    FreeBlocks += this->ReadInt32(\n                        &this->m_SuperBlock.fs_old_cstotal.cs_nffree);\n                }\n                FreeBlocks +=\n                    this->ReadInt64(&this->m_SuperBlock.fs_pendingblocks)\n                    >> this->ReadInt32(&this->m_SuperBlock.fs_fsbtodb);\n\n                std::uint64_t FreeSize = this->GetFragmentBlockSize();\n                FreeSize *= FreeBlocks;\n\n                Value->uhVal.QuadPart = FreeSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveClusterSize:\n            {\n                Value->ulVal = this->GetFragmentBlockSize();\n                Value->vt = VT_UI4;\n                break;\n            }\n            case SevenZipArchiveVolumeName:\n            {\n                std::string VolumeName = std::string(\n                    reinterpret_cast<char*>(this->m_SuperBlock.fs_volname),\n                    MAXVOLLEN);\n                VolumeName.resize(std::strlen(VolumeName.c_str()));\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    VolumeName).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveUnpackVersion:\n            {\n                Value->uhVal.QuadPart = this->m_IsUfs2 ? 2 : 1;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumProps = g_PropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetPropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_PropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_PropertyItems[Index].Property;\n            *VarType = g_PropertyItems[Index].Type;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfArchiveProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n            *NumProps = g_ArchivePropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchivePropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_ArchivePropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_ArchivePropertyItems[Index].Property;\n            *VarType = g_ArchivePropertyItems[Index].Type;\n            return S_OK;\n        }\n    };\n\n    IInArchive* CreateUfs()\n    {\n        return new Ufs();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Archive.WebAssembly.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Archive.WebAssembly.cpp\n * PURPOSE:    Implementation for WebAssembly (WASM) binary file readonly support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\n#include <map>\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\nnamespace\n{\n    struct PropertyItem\n    {\n        PROPID Property;\n        VARTYPE Type;\n    };\n\n    const PropertyItem g_PropertyItems[] =\n    {\n        { SevenZipArchivePath, VT_BSTR },\n        { SevenZipArchiveSize, VT_UI8 },\n        { SevenZipArchivePackSize, VT_UI8 },\n        { SevenZipArchiveOffset, VT_UI8 },\n    };\n\n    const std::size_t g_PropertyItemsCount =\n        sizeof(g_PropertyItems) / sizeof(*g_PropertyItems);\n\n    const char g_WebAssemblySignature[] = { '\\0', 'a', 's', 'm' };\n\n    namespace WebAssemblySectionType\n    {\n        enum\n        {\n            Custom,\n            Type,\n            Import,\n            Function,\n            Table,\n            Memory,\n            Global,\n            Export,\n            Start,\n            Element,\n            Code,\n            Data,\n            DataCount,\n            Unknown\n        };\n    }\n\n    const char* ToWebAssemblySectionTypeName(\n        std::uint8_t const& Type)\n    {\n        static const char* TypeNames[] =\n        {\n            \"[CUSTOM]\",\n            \".type\",\n            \".import\",\n            \".function\",\n            \".table\",\n            \".memory\",\n            \".global\",\n            \".export\",\n            \".start\",\n            \".element\",\n            \".code\",\n            \".data\",\n            \".data_count\",\n            \"[UNKNOWN]\"\n        };\n\n        if (Type < WebAssemblySectionType::Unknown)\n        {\n            return TypeNames[Type];\n        }\n\n        return TypeNames[WebAssemblySectionType::Unknown];\n    }\n\n    struct WebAssemblySection\n    {\n        std::uint64_t Offset = 0;\n        // According to https://www.w3.org/TR/wasm-core-1/#sections%E2%91%A0 ,\n        // we will know each section consists of the u32 size of the contents,\n        // in bytes.\n        std::uint32_t Size = 0;\n        std::string Name;\n    };\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    struct WebAssembly : public Mile::ComObject<WebAssembly, IInArchive>\n    {\n    private:\n\n        IInStream* m_FileStream = nullptr;\n        std::uint64_t m_FullSize = 0;\n        std::vector<WebAssemblySection> m_Sections;\n        bool m_IsInitialized = false;\n\n    private:\n\n        std::uint32_t ReadUleb128(\n            const void* BaseAddress,\n            std::uint8_t* ProcessedBytes = nullptr)\n        {\n            if (ProcessedBytes)\n            {\n                *ProcessedBytes = 0;\n            }\n\n            MO_UINT64 Value = 0;\n            MO_UINT8 Result = ::MileDecodeLeb128(BaseAddress, 32, false, &Value);\n            if (Result)\n            {\n                if (ProcessedBytes)\n                {\n                    *ProcessedBytes = Result;\n                }\n                return static_cast<std::uint32_t>(Value);\n            }\n\n            return static_cast<std::uint32_t>(-1);\n        }\n\n        HRESULT ReadFileStream(\n            _In_ INT64 Offset,\n            _Out_ PVOID Buffer,\n            _In_ SIZE_T NumberOfBytesToRead)\n        {\n            if (!this->m_FileStream)\n            {\n                return S_FALSE;\n            }\n\n            if (SUCCEEDED(this->m_FileStream->Seek(\n                Offset,\n                STREAM_SEEK_SET,\n                nullptr)))\n            {\n                SIZE_T NumberOfBytesRead = 0;\n                if (SUCCEEDED(::NanaZipCodecsReadInputStream(\n                    this->m_FileStream,\n                    Buffer,\n                    NumberOfBytesToRead,\n                    &NumberOfBytesRead)))\n                {\n                    if (NumberOfBytesToRead == NumberOfBytesRead)\n                    {\n                        return S_OK;\n                    }\n                }\n            }\n\n            return S_FALSE;\n        }\n\n    public:\n\n        WebAssembly()\n        {\n\n        }\n\n        HRESULT STDMETHODCALLTYPE Open(\n            _In_ IInStream* Stream,\n            _In_opt_ const PUINT64 MaxCheckStartPosition,\n            _In_opt_ IArchiveOpenCallback* OpenCallback)\n        {\n            UNREFERENCED_PARAMETER(MaxCheckStartPosition);\n            UNREFERENCED_PARAMETER(OpenCallback);\n\n            if (!Stream)\n            {\n                return E_INVALIDARG;\n            }\n\n            HRESULT hr = S_FALSE;\n\n            do\n            {\n                this->Close();\n\n                this->m_FileStream = Stream;\n                this->m_FileStream->AddRef();\n\n                UINT64 BundleSize = 0;\n                if (FAILED(this->m_FileStream->Seek(\n                    0,\n                    STREAM_SEEK_END,\n                    &BundleSize)))\n                {\n                    break;\n                }\n\n                const std::size_t HeaderSize = 2 * sizeof(std::uint32_t);\n\n                if (BundleSize < HeaderSize)\n                {\n                    break;\n                }\n\n                std::uint8_t HeaderBuffer[HeaderSize];\n                if (FAILED(this->ReadFileStream(\n                    0,\n                    HeaderBuffer,\n                    HeaderSize)))\n                {\n                    break;\n                }\n\n                if (0 != std::memcmp(\n                    HeaderBuffer,\n                    g_WebAssemblySignature,\n                    sizeof(g_WebAssemblySignature)))\n                {\n                    break;\n                }\n\n                std::uint32_t Version = ::MileReadUInt32LittleEndian(\n                    &HeaderBuffer[sizeof(std::uint32_t)]);\n                if (1 != Version)\n                {\n                    break;\n                }\n\n                std::multimap<std::string, WebAssemblySection> Sections;\n                for (UINT64 i = HeaderSize; i < BundleSize;)\n                {\n                    std::uint8_t Type = 0;\n                    std::uint32_t Size = 0;\n                    {\n                        const std::size_t MaximumSize =\n                            sizeof(std::uint8_t) * (1 + 5);\n                        std::size_t AcquireSize = static_cast<std::size_t>(\n                            BundleSize - i < MaximumSize\n                            ? BundleSize - i\n                            : MaximumSize);\n                        std::uint8_t Buffer[MaximumSize] = {};\n                        if (FAILED(this->ReadFileStream(\n                            i,\n                            Buffer,\n                            AcquireSize)))\n                        {\n                            break;\n                        }\n                        Type = Buffer[0];\n                        std::uint8_t ProcessedBytes = 0;\n                        Size = this->ReadUleb128(\n                            &Buffer[1],\n                            &ProcessedBytes);\n                        i += sizeof(std::uint8_t) + ProcessedBytes;\n                    }\n                    if (WebAssemblySectionType::Custom == Type && 0 == Size)\n                    {\n                        this->m_FullSize = i;\n                        break;\n                    }\n\n                    std::string CustomName;\n                    if (WebAssemblySectionType::Custom == Type)\n                    {\n                        std::uint32_t NameSize = 0;\n                        {\n                            const std::size_t MaximumSize =\n                                sizeof(std::uint8_t) * 5;\n                            std::size_t AcquireSize = static_cast<std::size_t>(\n                                BundleSize - i < MaximumSize\n                                ? BundleSize - i\n                                : MaximumSize);\n                            std::uint8_t Buffer[MaximumSize] = {};\n                            if (FAILED(this->ReadFileStream(\n                                i,\n                                Buffer,\n                                AcquireSize)))\n                            {\n                                break;\n                            }\n                            std::uint8_t ProcessedBytes = 0;\n                            NameSize = this->ReadUleb128(\n                                Buffer,\n                                &ProcessedBytes);\n                            i += ProcessedBytes;\n                            Size -= ProcessedBytes;\n                        }\n                        if (NameSize)\n                        {\n                            CustomName = std::string(NameSize, '\\0');\n                            if (FAILED(this->ReadFileStream(\n                                i,\n                                &CustomName[0],\n                                NameSize)))\n                            {\n                                break;\n                            }\n                            i += sizeof(char) * NameSize;\n                            Size -= sizeof(char) * NameSize;\n                        }\n                    }\n                    WebAssemblySection Section;\n                    Section.Offset = i;\n                    Section.Size = Size;\n                    Section.Name = CustomName.empty()\n                        ? ::ToWebAssemblySectionTypeName(Type)\n                        : std::string(\".\") + CustomName;\n                    Sections.emplace(Section.Name, Section);\n                    i += Size;\n                }\n                if (!this->m_FullSize && !Sections.empty())\n                {\n                    this->m_FullSize = BundleSize;\n                }\n\n                std::uint64_t TotalFiles = Sections.size();\n                std::uint64_t TotalBytes = this->m_FullSize;\n\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                this->m_Sections.clear();\n\n                for (auto const& Item : Sections)\n                {\n                    this->m_Sections.emplace_back(Item.second);\n                }\n\n                hr = S_OK;\n\n            } while (false);\n\n            if (S_OK != hr)\n            {\n                this->Close();\n            }\n            else\n            {\n                this->m_IsInitialized = true;\n            }\n\n            return hr;\n        }\n\n        HRESULT STDMETHODCALLTYPE Close()\n        {\n            this->m_IsInitialized = false;\n            this->m_Sections.clear();\n            this->m_FullSize = 0;\n            if (this->m_FileStream)\n            {\n                this->m_FileStream->Release();\n                this->m_FileStream = nullptr;\n            }\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfItems(\n            _Out_ PUINT32 NumItems)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!NumItems)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumItems = static_cast<UINT32>(this->m_Sections.size());\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetProperty(\n            _In_ UINT32 Index,\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!(Index < this->m_Sections.size()))\n            {\n                return E_INVALIDARG;\n            }\n\n            WebAssemblySection& Information = this->m_Sections[Index];\n\n            switch (PropId)\n            {\n            case SevenZipArchivePath:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_Sections[Index].Name).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePackSize:\n            {\n                Value->uhVal.QuadPart = Information.Size;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveOffset:\n            {\n                Value->uhVal.QuadPart = Information.Offset;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            UNREFERENCED_PARAMETER(Value);\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE Extract(\n            _In_opt_ const PUINT32 Indices,\n            _In_ UINT32 NumItems,\n            _In_ BOOL TestMode,\n            _In_ IArchiveExtractCallback* ExtractCallback)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            HRESULT hr = S_OK;\n\n            INT32 AskMode = TestMode\n                ? SevenZipExtractAskModeTest\n                : SevenZipExtractAskModeExtract;\n\n            const bool AllFilesMode =\n                static_cast<UINT32>(-1) == NumItems;\n            if (AllFilesMode)\n            {\n                NumItems = static_cast<UINT32>(this->m_Sections.size());\n            }\n\n            UINT64 TotalSize = 0;\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                WebAssemblySection& Information =\n                    this->m_Sections[ActualFileIndex];\n                TotalSize += Information.Size;\n            }\n            ExtractCallback->SetTotal(TotalSize);\n\n            UINT64 Completed = 0;\n\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                WebAssemblySection& Information =\n                    this->m_Sections[ActualFileIndex];\n\n                Completed += Information.Size;\n                hr = ExtractCallback->SetCompleted(&Completed);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                hr = ExtractCallback->PrepareOperation(AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                ISequentialOutStream* OutputStream = nullptr;\n                hr = ExtractCallback->GetStream(\n                    Indices[i],\n                    &OutputStream,\n                    AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n                if (!OutputStream)\n                {\n                    continue;\n                }\n\n                bool Succeeded = false;\n                std::vector<std::uint8_t> Buffer(Information.Size);\n                if (SUCCEEDED(this->ReadFileStream(\n                    Information.Offset,\n                    &Buffer[0],\n                    Information.Size)))\n                {\n                    UINT32 ProceededSize = 0;\n                    Succeeded = SUCCEEDED(OutputStream->Write(\n                        &Buffer[0],\n                        static_cast<UINT32>(Information.Size),\n                        &ProceededSize));\n                }\n\n                OutputStream->Release();\n\n                ExtractCallback->SetOperationResult(\n                    Succeeded\n                    ? SevenZipExtractOperationResultSuccess\n                    : SevenZipExtractOperationResultUnavailable);\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchiveProperty(\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!Value)\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!this->m_IsInitialized)\n            {\n                Value->vt = VT_EMPTY;\n                return S_OK;\n            }\n\n            switch (PropId)\n            {\n            case SevenZipArchivePhysicalSize:\n            {\n                Value->uhVal.QuadPart = this->m_FullSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumProps = g_PropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetPropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_PropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_PropertyItems[Index].Property;\n            *VarType = g_PropertyItems[Index].Type;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfArchiveProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n            *NumProps = 0;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchivePropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            UNREFERENCED_PARAMETER(Index);\n            UNREFERENCED_PARAMETER(Name);\n            UNREFERENCED_PARAMETER(PropId);\n            UNREFERENCED_PARAMETER(VarType);\n            return E_INVALIDARG;\n        }\n    };\n\n    IInArchive* CreateWebAssembly()\n    {\n        return new WebAssembly();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Archive.Zealfs.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Archive.Zealfs.cpp\n * PURPOSE:    Implementation for ZealFS file system image readonly support\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\n#include <map>\n\n#include \"Mile.Helpers.Portable.Base.Unstaged.h\"\n\n#include \"NanaZip.Codecs.Specification.Zealfs.h\"\n\nnamespace\n{\n    struct PropertyItem\n    {\n        PROPID Property;\n        VARTYPE Type;\n    };\n\n    const PropertyItem g_ArchivePropertyItems[] =\n    {\n        { SevenZipArchiveFreeSpace, VT_UI8 },\n        { SevenZipArchiveClusterSize, VT_UI4 },\n    };\n\n    const std::size_t g_ArchivePropertyItemsCount =\n        sizeof(g_ArchivePropertyItems) / sizeof(*g_ArchivePropertyItems);\n\n    const PropertyItem g_PropertyItems[] =\n    {\n        { SevenZipArchivePath, VT_BSTR },\n        { SevenZipArchiveIsDirectory, VT_BOOL },\n        { SevenZipArchiveSize, VT_UI8 },\n        { SevenZipArchivePackSize, VT_UI8 },\n        { SevenZipArchiveCreationTime, VT_FILETIME },\n        { SevenZipArchiveInode, VT_UI8 },\n    };\n\n    const std::size_t g_PropertyItemsCount =\n        sizeof(g_PropertyItems) / sizeof(*g_PropertyItems);\n\n    // Reference: https://github.com/Zeal8bit/ZealFS\n\n    const std::uint16_t g_ZealfsMaximumNameLength = 16;\n\n    const std::uint8_t ZealfsFileFlagDirectory = 0x01;\n    const std::uint8_t ZealfsFileFlagOccupied = 0x80;\n\n    struct ZealfsFileEntry\n    {\n        // Bit 0: 1 = directory, 0 = file\n        // bit n: reserved\n        // Bit 7: 1 = occupied, 0 = free\n        // IS_DIR, IS_FILE, etc...\n        std::uint8_t Flags;\n        char Name[g_ZealfsMaximumNameLength];\n        std::uint8_t StartPage;\n        // Size of the file in bytes, little-endian!\n        std::uint16_t Size;\n        // Date of creation.\n        ZEALOS_TIME CreationTime;\n        // Reserved for future use\n        std::uint8_t Reserved[4];\n    };\n\n    // According to zealfs_fuse.c's implementation\n    const std::uint8_t g_ZealfsCurrentVersion = 1;\n\n    struct ZealfsFilePathInformation\n    {\n        std::string Path;\n        ZealfsFileEntry Information;\n    };\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    struct Zealfs : public Mile::ComObject<Zealfs, IInArchive>\n    {\n    private:\n\n        IInStream* m_FileStream = nullptr;\n        std::uint32_t m_PhysicalSize = 0;\n        std::uint32_t m_FreeSpace = 0;\n        std::string m_VolumeName;\n        std::map<std::string, ZealfsFileEntry> m_TemporaryFilePaths;\n        std::vector<ZealfsFilePathInformation> m_FilePaths;\n        bool m_IsInitialized = false;\n\n    private:\n\n        std::uint16_t ReadUInt16(\n            const void* BaseAddress)\n        {\n            return ::MileReadUInt16LittleEndian(BaseAddress);\n        }\n\n        std::uint32_t GetAlignedSize(\n            int Size,\n            int Alignment)\n        {\n            return (Size + Alignment - 1) & ~(Alignment - 1);\n        }\n\n        std::uint8_t ReadBcd(\n            const void* BaseAddress)\n        {\n            const std::uint8_t* Base =\n                reinterpret_cast<const std::uint8_t*>(BaseAddress);\n            return (*Base >> 4) * 10 + (*Base & 0xF);\n        }\n\n        HRESULT ReadFileStream(\n            _In_ INT64 Offset,\n            _Out_ PVOID Buffer,\n            _In_ SIZE_T NumberOfBytesToRead)\n        {\n            if (!this->m_FileStream)\n            {\n                return S_FALSE;\n            }\n\n            if (SUCCEEDED(this->m_FileStream->Seek(\n                Offset,\n                STREAM_SEEK_SET,\n                nullptr)))\n            {\n                SIZE_T NumberOfBytesRead = 0;\n                if (SUCCEEDED(::NanaZipCodecsReadInputStream(\n                    this->m_FileStream,\n                    Buffer,\n                    NumberOfBytesToRead,\n                    &NumberOfBytesRead)))\n                {\n                    if (NumberOfBytesToRead == NumberOfBytesRead)\n                    {\n                        return S_OK;\n                    }\n                }\n            }\n\n            return S_FALSE;\n        }\n\n    private:\n\n        FILETIME GetFileTime(\n            ZEALOS_TIME const& Value)\n        {\n            SYSTEMTIME LocalTime = {};\n            LocalTime.wYear = this->ReadBcd(&Value.Year[0]) * 100;\n            LocalTime.wYear += this->ReadBcd(&Value.Year[1]);\n            LocalTime.wMonth = this->ReadBcd(&Value.Month);\n            LocalTime.wDayOfWeek = this->ReadBcd(&Value.Date);\n            LocalTime.wDay = this->ReadBcd(&Value.Day);\n            LocalTime.wHour = this->ReadBcd(&Value.Hours);\n            LocalTime.wMinute = this->ReadBcd(&Value.Minutes);\n            LocalTime.wSecond = this->ReadBcd(&Value.Seconds);\n            SYSTEMTIME SystemTime = {};\n            ::TzSpecificLocalTimeToSystemTime(nullptr, &LocalTime, &SystemTime);\n            FILETIME Result = {};\n            ::SystemTimeToFileTime(&SystemTime, &Result);\n            return Result;\n        }\n\n        void GetAllPaths(\n            std::uint32_t Offset,\n            std::string const& RootPath)\n        {\n            std::uint32_t MaximumOffset =\n                this->GetAlignedSize(Offset, ZEALFS_V1_PAGE_SIZE);\n\n            std::uint8_t MaximumCount = static_cast<std::uint8_t>(\n                (MaximumOffset - Offset) / sizeof(ZealfsFileEntry));\n\n            for (std::uint8_t i = 0; i < MaximumCount; ++i)\n            {\n                ZealfsFileEntry Information = {};\n                if (FAILED(this->ReadFileStream(\n                    Offset + (i * sizeof(ZealfsFileEntry)),\n                    &Information,\n                    sizeof(ZealfsFileEntry))))\n                {\n                    break;\n                }\n\n                if (!(Information.Flags & ZealfsFileFlagOccupied))\n                {\n                    continue;\n                }\n\n                std::string FileName =\n                    std::string(Information.Name, g_ZealfsMaximumNameLength);\n                FileName.resize(std::strlen(FileName.c_str()));\n\n                std::string Path = RootPath + FileName;\n\n                if (Information.Flags & ZealfsFileFlagDirectory)\n                {\n                    this->GetAllPaths(\n                        Information.StartPage * ZEALFS_V1_PAGE_SIZE,\n                        Path + \"/\");\n                }\n\n                this->m_TemporaryFilePaths.emplace(Path, Information);\n            }\n        }\n\n    public:\n\n        Zealfs()\n        {\n\n        }\n\n        HRESULT STDMETHODCALLTYPE Open(\n            _In_ IInStream* Stream,\n            _In_opt_ const PUINT64 MaxCheckStartPosition,\n            _In_opt_ IArchiveOpenCallback* OpenCallback)\n        {\n            UNREFERENCED_PARAMETER(MaxCheckStartPosition);\n            UNREFERENCED_PARAMETER(OpenCallback);\n\n            if (!Stream)\n            {\n                return E_INVALIDARG;\n            }\n\n            HRESULT hr = S_FALSE;\n\n            do\n            {\n                this->Close();\n\n                this->m_FileStream = Stream;\n                this->m_FileStream->AddRef();\n\n                UINT64 BundleSize = 0;\n                if (FAILED(this->m_FileStream->Seek(\n                    0,\n                    STREAM_SEEK_END,\n                    &BundleSize)))\n                {\n                    break;\n                }\n\n                if (BundleSize < ZEALFS_V1_MINIMUM_PARTITION_SIZE)\n                {\n                    break;\n                }\n\n                ZEALFS_V1_HEADER Header = {};\n                if (FAILED(this->ReadFileStream(\n                    0,\n                    &Header,\n                    sizeof(ZEALFS_V1_HEADER))))\n                {\n                    break;\n                }\n\n                if (ZEALFS_MAGIC != Header.Common.Magic)\n                {\n                    break;\n                }\n\n                if (g_ZealfsCurrentVersion != Header.Common.Version)\n                {\n                    break;\n                }\n\n                if (!Header.BitmapSize)\n                {\n                    break;\n                }\n\n                this->m_PhysicalSize = ZEALFS_V1_PAGE_SIZE * Header.BitmapSize * 8;\n                this->m_FreeSpace = 0;\n                for (std::uint8_t i = 0; i < Header.BitmapSize; ++i)\n                {\n                    this->m_FreeSpace += !(0x01 & Header.PagesBitmap[i]);\n                    this->m_FreeSpace += !(0x02 & Header.PagesBitmap[i]);\n                    this->m_FreeSpace += !(0x04 & Header.PagesBitmap[i]);\n                    this->m_FreeSpace += !(0x08 & Header.PagesBitmap[i]);\n                    this->m_FreeSpace += !(0x10 & Header.PagesBitmap[i]);\n                    this->m_FreeSpace += !(0x20 & Header.PagesBitmap[i]);\n                    this->m_FreeSpace += !(0x40 & Header.PagesBitmap[i]);\n                    this->m_FreeSpace += !(0x80 & Header.PagesBitmap[i]);\n                }\n                this->m_FreeSpace *= ZEALFS_V1_PAGE_SIZE;\n\n                std::uint64_t TotalFiles = 0;\n                std::uint64_t TotalBytes = this->m_PhysicalSize;\n\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                this->GetAllPaths(sizeof(ZEALFS_V1_HEADER), \"\");\n\n                TotalFiles = this->m_TemporaryFilePaths.size();\n                if (OpenCallback)\n                {\n                    OpenCallback->SetTotal(&TotalFiles, &TotalBytes);\n                }\n\n                this->m_FilePaths.clear();\n\n                for (auto const& Item : this->m_TemporaryFilePaths)\n                {\n                    ZealfsFilePathInformation Current;\n                    Current.Path = Item.first;\n                    Current.Information = Item.second;\n                    this->m_FilePaths.emplace_back(Current);\n                }\n                this->m_TemporaryFilePaths.clear();\n\n                hr = S_OK;\n\n            } while (false);\n\n            if (S_OK != hr)\n            {\n                this->Close();\n            }\n            else\n            {\n                this->m_IsInitialized = true;\n            }\n\n            return hr;\n        }\n\n        HRESULT STDMETHODCALLTYPE Close()\n        {\n            this->m_IsInitialized = false;\n            this->m_FilePaths.clear();\n            this->m_VolumeName.clear();\n            this->m_FreeSpace = 0;\n            this->m_PhysicalSize = 0;\n            if (this->m_FileStream)\n            {\n                this->m_FileStream->Release();\n                this->m_FileStream = nullptr;\n            }\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfItems(\n            _Out_ PUINT32 NumItems)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!NumItems)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetProperty(\n            _In_ UINT32 Index,\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            if (!(Index < this->m_FilePaths.size()))\n            {\n                return E_INVALIDARG;\n            }\n\n            ZealfsFileEntry& Information = this->m_FilePaths[Index].Information;\n\n            switch (PropId)\n            {\n            case SevenZipArchivePath:\n            {\n                Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                    CP_UTF8,\n                    this->m_FilePaths[Index].Path).c_str());\n                if (Value->bstrVal)\n                {\n                    Value->vt = VT_BSTR;\n                }\n                break;\n            }\n            case SevenZipArchiveIsDirectory:\n            {\n                Value->boolVal = Information.Flags & ZealfsFileFlagDirectory\n                    ? VARIANT_TRUE\n                    : VARIANT_FALSE;\n                Value->vt = VT_BOOL;\n                break;\n            }\n            case SevenZipArchiveSize:\n            {\n                Value->uhVal.QuadPart = this->ReadUInt16(&Information.Size);\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchivePackSize:\n            {\n                Value->uhVal.QuadPart = this->ReadUInt16(&Information.Size);\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveCreationTime:\n            {\n                Value->filetime = this->GetFileTime(Information.CreationTime);\n                Value->vt = VT_FILETIME;\n                break;\n            }\n            case SevenZipArchiveInode:\n            {\n                Value->uhVal.QuadPart = Information.StartPage;\n                Value->vt = VT_UI8;\n                break;\n            }\n            default:\n                break;\n            }\n\n            UNREFERENCED_PARAMETER(Value);\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE Extract(\n            _In_opt_ const PUINT32 Indices,\n            _In_ UINT32 NumItems,\n            _In_ BOOL TestMode,\n            _In_ IArchiveExtractCallback* ExtractCallback)\n        {\n            if (!this->m_IsInitialized)\n            {\n                return S_FALSE;\n            }\n\n            HRESULT hr = S_OK;\n\n            INT32 AskMode = TestMode\n                ? SevenZipExtractAskModeTest\n                : SevenZipExtractAskModeExtract;\n\n            const bool AllFilesMode =\n                static_cast<UINT32>(-1) == NumItems;\n            if (AllFilesMode)\n            {\n                NumItems = static_cast<UINT32>(this->m_FilePaths.size());\n            }\n\n            UINT64 TotalSize = 0;\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                ZealfsFileEntry& Information =\n                    this->m_FilePaths[ActualFileIndex].Information;\n                TotalSize += Information.Size;\n            }\n            ExtractCallback->SetTotal(TotalSize);\n\n            UINT64 Completed = 0;\n\n            for (UINT32 i = 0; i < NumItems; ++i)\n            {\n                UINT32 ActualFileIndex = AllFilesMode ? i : Indices[i];\n                ZealfsFileEntry& Information =\n                    this->m_FilePaths[ActualFileIndex].Information;\n\n                Completed += Information.Size;\n                hr = ExtractCallback->SetCompleted(&Completed);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                hr = ExtractCallback->PrepareOperation(AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n\n                ISequentialOutStream* OutputStream = nullptr;\n                hr = ExtractCallback->GetStream(\n                    Indices[i],\n                    &OutputStream,\n                    AskMode);\n                if (FAILED(hr))\n                {\n                    continue;\n                }\n                if (!OutputStream)\n                {\n                    continue;\n                }\n\n                std::uint16_t Todo = this->ReadUInt16(&Information.Size);\n                std::uint16_t Done = 0;\n                std::uint16_t CurrentOffset =\n                    Information.StartPage * ZEALFS_V1_PAGE_SIZE;\n\n                bool Failed = false;\n                while (Todo && CurrentOffset)\n                {\n                    std::uint16_t CurrentDo = Todo > ZEALFS_V1_PAGE_SIZE - 1\n                        ? ZEALFS_V1_PAGE_SIZE - 1\n                        : Todo;\n\n                    std::uint8_t Buffer[ZEALFS_V1_PAGE_SIZE];\n                    if (FAILED(this->ReadFileStream(\n                        CurrentOffset,\n                        Buffer,\n                        ZEALFS_V1_PAGE_SIZE)))\n                    {\n                        Failed = true;\n                        break;\n                    }\n\n                    UINT32 ProceededSize = 0;\n                    hr = OutputStream->Write(\n                        &Buffer[1],\n                        CurrentDo,\n                        &ProceededSize);\n                    if (FAILED(hr))\n                    {\n                        Failed = true;\n                        break;\n                    }\n\n                    Todo -= CurrentDo;\n                    Done += CurrentDo;\n                    CurrentOffset = Buffer[0] * ZEALFS_V1_PAGE_SIZE;\n                }\n\n                OutputStream->Release();\n\n                ExtractCallback->SetOperationResult(\n                    Failed\n                    ? SevenZipExtractOperationResultUnavailable\n                    : SevenZipExtractOperationResultSuccess);\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchiveProperty(\n            _In_ PROPID PropId,\n            _Inout_ LPPROPVARIANT Value)\n        {\n            if (!Value)\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!this->m_IsInitialized)\n            {\n                Value->vt = VT_EMPTY;\n                return S_OK;\n            }\n\n            switch (PropId)\n            {\n            case SevenZipArchivePhysicalSize:\n            {\n                Value->uhVal.QuadPart = this->m_PhysicalSize;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveFreeSpace:\n            {\n                Value->uhVal.QuadPart = this->m_FreeSpace;\n                Value->vt = VT_UI8;\n                break;\n            }\n            case SevenZipArchiveClusterSize:\n            {\n                Value->ulVal = ZEALFS_V1_PAGE_SIZE;\n                Value->vt = VT_UI4;\n                break;\n            }\n            default:\n                break;\n            }\n\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n\n            *NumProps = g_PropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetPropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_PropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_PropertyItems[Index].Property;\n            *VarType = g_PropertyItems[Index].Type;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetNumberOfArchiveProperties(\n            _Out_ PUINT32 NumProps)\n        {\n            if (!NumProps)\n            {\n                return E_INVALIDARG;\n            }\n            *NumProps = g_ArchivePropertyItemsCount;\n            return S_OK;\n        }\n\n        HRESULT STDMETHODCALLTYPE GetArchivePropertyInfo(\n            _In_ UINT32 Index,\n            _Out_ BSTR* Name,\n            _Out_ PROPID* PropId,\n            _Out_ VARTYPE* VarType)\n        {\n            if (!(Index < g_ArchivePropertyItemsCount))\n            {\n                return E_INVALIDARG;\n            }\n\n            if (!Name || !PropId || !VarType)\n            {\n                return E_INVALIDARG;\n            }\n\n            *Name = nullptr;\n            *PropId = g_ArchivePropertyItems[Index].Property;\n            *VarType = g_ArchivePropertyItems[Index].Type;\n            return S_OK;\n        }\n    };\n\n    IInArchive* CreateZealfs()\n    {\n        return new Zealfs();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Aich.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Aich.cpp\n * PURPOSE:    Implementation for EMule AICH hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <aich.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Aich : public Mile::ComObject<Aich, IHasher>\n    {\n    private:\n\n        aich_ctx Context;\n\n    public:\n\n        Aich()\n        {\n            this->Init();\n        }\n\n        ~Aich()\n        {\n            ::rhash_aich_cleanup(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_aich_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_aich_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_aich_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return 20;\n        }\n    };\n\n    IHasher* CreateAich()\n    {\n        return new Aich();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.BCryptProvider.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.BCryptProvider.cpp\n * PURPOSE:    Implementation for Windows CNG Hash Algorithm Provider\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <K7Base.h>\n\n#include <string>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct BCryptProvider : public Mile::ComObject<BCryptProvider, IHasher>\n    {\n    private:\n\n        K7_BASE_HASH_ALGORITHM_TYPE m_Algorithm;\n        K7_BASE_HASH_HANDLE m_HashHandle = nullptr;\n\n        void DestroyContext()\n        {\n            if (this->m_HashHandle)\n            {\n                ::K7BaseHashDestroy(this->m_HashHandle);\n                this->m_HashHandle = nullptr;\n            }\n        }\n\n    public:\n\n        BCryptProvider(\n            _In_ K7_BASE_HASH_ALGORITHM_TYPE Algorithm)\n        {\n            this->m_Algorithm = Algorithm;\n            this->Init();\n        }\n\n        ~BCryptProvider()\n        {\n            this->DestroyContext();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            this->DestroyContext();\n            ::K7BaseHashCreate(\n                &this->m_HashHandle,\n                this->m_Algorithm,\n                nullptr,\n                0);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::K7BaseHashUpdate(\n                this->m_HashHandle,\n                const_cast<LPVOID>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::K7BaseHashFinal(\n                this->m_HashHandle,\n                Digest,\n                this->GetDigestSize());\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            UINT32 HashSize = 0;\n            ::K7BaseHashGetSize(this->m_HashHandle, &HashSize);\n            return HashSize;\n        }\n    };\n\n    IHasher* CreateMd2()\n    {\n        return new BCryptProvider(K7_BASE_HASH_ALGORITHM_MD2);\n    }\n\n    IHasher* CreateMd4()\n    {\n        return new BCryptProvider(K7_BASE_HASH_ALGORITHM_MD4);\n    }\n\n    IHasher* CreateMd5()\n    {\n        return new BCryptProvider(K7_BASE_HASH_ALGORITHM_MD5);\n    }\n\n    IHasher* CreateSha1()\n    {\n        return new BCryptProvider(K7_BASE_HASH_ALGORITHM_SHA1);\n    }\n\n    IHasher* CreateSha256()\n    {\n        return new BCryptProvider(K7_BASE_HASH_ALGORITHM_SHA256);\n    }\n\n    IHasher* CreateSha384()\n    {\n        return new BCryptProvider(K7_BASE_HASH_ALGORITHM_SHA384);\n    }\n\n    IHasher* CreateSha512()\n    {\n        return new BCryptProvider(K7_BASE_HASH_ALGORITHM_SHA512);\n    }\n}\n\n#pragma region RHash Wrappers\n\n#include \"RHash/sha1.h\"\n\nvoid rhash_sha1_init(\n    sha1_ctx* ctx)\n{\n    if (!ctx)\n    {\n        return;\n    }\n    std::memset(ctx, 0, sizeof(sha1_ctx));\n\n    ::K7BaseHashCreate(\n        &ctx->context,\n        K7_BASE_HASH_ALGORITHM_SHA1,\n        nullptr,\n        0);\n}\n\nvoid rhash_sha1_update(\n    sha1_ctx* ctx,\n    const unsigned char* msg,\n    size_t size)\n{\n    if (!ctx)\n    {\n        return;\n    }\n\n    ::K7BaseHashUpdate(\n        ctx->context,\n        const_cast<LPVOID>(reinterpret_cast<LPCVOID>(msg)),\n        static_cast<UINT32>(size));\n    ctx->length += size;\n}\n\nvoid rhash_sha1_final(\n    sha1_ctx* ctx,\n    unsigned char* result)\n{\n    if (!ctx)\n    {\n        return;\n    }\n\n    ::K7BaseHashFinal(\n        ctx->context,\n        ctx->hash,\n        sha1_hash_size);\n    if (result)\n    {\n        std::memcpy(result, ctx->hash, sha1_hash_size);\n    }\n}\n\n#pragma endregion\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Blake2b.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Blake2b.cpp\n * PURPOSE:    Implementation for BLAKE2b hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <blake2b.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Blake2b : public Mile::ComObject<Blake2b, IHasher>\n    {\n    private:\n\n        blake2b_ctx Context;\n\n    public:\n\n        Blake2b()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_blake2b_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_blake2b_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_blake2b_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return blake2b_hash_size;\n        }\n    };\n\n    IHasher* CreateBlake2b()\n    {\n        return new Blake2b();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Blake3.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Blake3.cpp\n * PURPOSE:    Implementation for BLAKE3 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <blake3.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Blake3 : public Mile::ComObject<Blake3, IHasher>\n    {\n    private:\n\n        blake3_hasher Context;\n\n    public:\n\n        Blake3()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::blake3_hasher_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::blake3_hasher_update(\n                &this->Context,\n                Data,\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::blake3_hasher_finalize(\n                &this->Context,\n                Digest,\n                this->GetDigestSize());\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return BLAKE3_OUT_LEN;\n        }\n    };\n\n    IHasher* CreateBlake3()\n    {\n        return new Blake3();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Ed2k.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Ed2k.cpp\n * PURPOSE:    Implementation for ED2K hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <K7Base.h>\n\n// Comments copy from RHash's ed2k.c\n//\n// This file implements eMule-compatible version of algorithm. Note that\n// eDonkey and eMule ed2k hashes are different only for files containing\n// exactly multiple of 9728000 bytes.\n// The file data is divided into full chunks of 9500 KiB (9728000 bytes) plus a\n// remainder chunk, and a separate 128-bit MD4 hash is computed for each. If the\n// file length is an exact multiple of 9500 KiB, the remainder zero size chunk\n// is still used at the end of the hash list. The ed2k hash is computed by\n// concatenating the chunks' MD4 hashes in order and hashing the result using\n// MD4. Although, if the file is composed of a single non-full chunk, its MD4\n// hash is returned with no further modifications.\n// See http://en.wikipedia.org/wiki/EDonkey_network for algorithm description.\n\n// Each hashed file is divided into 9500 KiB sized chunks\n#define ED2K_CHUNK_SIZE 9728000\n\n#define MD4_HASH_SIZE 16\n#define ED2K_HASH_SIZE MD4_HASH_SIZE\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Ed2k : public Mile::ComObject<Ed2k, IHasher>\n    {\n    private:\n\n        // MD4 context to hash file blocks.\n        K7_BASE_HASH_HANDLE m_BlockHashHandle = nullptr;\n\n        // MD4 context to hash block hashes.\n        K7_BASE_HASH_HANDLE m_HashesHashHandle = nullptr;\n\n        // false for eMule ED2K algorithm.\n        bool m_NotEmule = false;\n\n        // The processed size for hash file blocks.\n        UINT32 m_BlockProcessedSize = 0;\n\n        // The processed size for hash block hashes.\n        UINT32 m_HashesProcessedSize = 0;\n\n        void DestroyContext()\n        {\n            if (this->m_BlockHashHandle)\n            {\n                ::K7BaseHashDestroy(this->m_BlockHashHandle);\n                this->m_BlockHashHandle = nullptr;\n            }\n            if (this->m_HashesHashHandle)\n            {\n                ::K7BaseHashDestroy(this->m_HashesHashHandle);\n                this->m_HashesHashHandle = nullptr;\n            }\n        }\n\n    public:\n\n        Ed2k()\n        {\n            this->Init();\n        }\n\n        ~Ed2k()\n        {\n            this->DestroyContext();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            this->DestroyContext();\n            ::K7BaseHashCreate(\n                &this->m_BlockHashHandle,\n                K7_BASE_HASH_ALGORITHM_MD4,\n                nullptr,\n                0);\n            ::K7BaseHashCreate(\n                &this->m_HashesHashHandle,\n                K7_BASE_HASH_ALGORITHM_MD4,\n                nullptr,\n                0);\n            this->m_NotEmule = false;\n            this->m_BlockProcessedSize = 0;\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            BYTE BlockHash[MD4_HASH_SIZE];\n            UINT32 BlockLeft = ED2K_CHUNK_SIZE - this->m_BlockProcessedSize;\n\n            // Note: eMule-compatible algorithm hashes by md4_inner the messages\n            // which sizes are multiple of 9728000 and then processes obtained\n            // hash by external MD4.\n\n            while (Size >= BlockLeft)\n            {\n                if (Size == BlockLeft && this->m_NotEmule)\n                {\n                    break;\n                }\n\n                // If internal ED2K chunk is full, then finalize it.\n                ::K7BaseHashUpdate(\n                    this->m_BlockHashHandle,\n                    const_cast<LPVOID>(Data),\n                    BlockLeft);\n                this->m_BlockProcessedSize += BlockLeft;\n                Data = reinterpret_cast<LPCVOID>(\n                    reinterpret_cast<UINT_PTR>(Data) + BlockLeft);\n                Size -= BlockLeft;\n                BlockLeft = ED2K_CHUNK_SIZE;\n\n                // Just finished an ED2K chunk, updating MD4 external context.\n                ::K7BaseHashFinal(\n                    this->m_BlockHashHandle,\n                    BlockHash,\n                    MD4_HASH_SIZE);\n                this->m_BlockProcessedSize = 0;\n                ::K7BaseHashUpdate(\n                    this->m_HashesHashHandle,\n                    BlockHash,\n                    MD4_HASH_SIZE);\n                this->m_HashesProcessedSize += MD4_HASH_SIZE;\n            }\n\n            if (Size)\n            {\n                // Hash leftovers.\n                ::K7BaseHashUpdate(\n                    this->m_BlockHashHandle,\n                    const_cast<LPVOID>(Data),\n                    Size);\n                this->m_BlockProcessedSize += Size;\n            }\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            // Check if hashed message size is greater or equal to\n            // ED2K_CHUNK_SIZE.\n            if (this->m_HashesProcessedSize)\n            {\n                // Note: Weird eMule algorithm always processes the inner MD4\n                // context, no matter if it contains data or is empty.\n\n                // If any data are left in the m_BlockHashHandle.\n                if (this->m_BlockProcessedSize || !this->m_NotEmule)\n                {\n                    // eMule algorithm processes aditional block, even if it's\n                    // empty.\n\n                    BYTE BlockHash[MD4_HASH_SIZE];\n                    ::K7BaseHashFinal(\n                        this->m_BlockHashHandle,\n                        BlockHash,\n                        MD4_HASH_SIZE);\n                    this->m_BlockProcessedSize = 0;\n                    ::K7BaseHashUpdate(\n                        this->m_HashesHashHandle,\n                        BlockHash,\n                        MD4_HASH_SIZE);\n                    this->m_HashesProcessedSize += MD4_HASH_SIZE;\n                }\n\n                // Call final to flush MD4 buffer and finalize the hash value.\n                ::K7BaseHashFinal(\n                    this->m_HashesHashHandle,\n                    Digest,\n                    ED2K_HASH_SIZE);\n                this->m_HashesProcessedSize = 0;\n            }\n            else\n            {\n                // Just return the message MD4 hash.\n                ::K7BaseHashFinal(\n                    this->m_BlockHashHandle,\n                    Digest,\n                    MD4_HASH_SIZE);\n                this->m_BlockProcessedSize = 0;\n            }\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return ED2K_HASH_SIZE;\n        }\n    };\n\n    IHasher* CreateEd2k()\n    {\n        return new Ed2k();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.EdonR224.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.EdonR224.cpp\n * PURPOSE:    Implementation for EDON-R 224 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <edonr.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct EdonR224 : public Mile::ComObject<EdonR224, IHasher>\n    {\n    private:\n\n        edonr_ctx Context;\n\n    public:\n\n        EdonR224()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_edonr224_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_edonr256_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_edonr256_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return edonr224_hash_size;\n        }\n    };\n\n    IHasher* CreateEdonR224()\n    {\n        return new EdonR224();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.EdonR256.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.EdonR256.cpp\n * PURPOSE:    Implementation for EDON-R 256 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <edonr.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct EdonR256 : public Mile::ComObject<EdonR256, IHasher>\n    {\n    private:\n\n        edonr_ctx Context;\n\n    public:\n\n        EdonR256()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_edonr256_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_edonr256_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_edonr256_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return edonr256_hash_size;\n        }\n    };\n\n    IHasher* CreateEdonR256()\n    {\n        return new EdonR256();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.EdonR384.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.EdonR384.cpp\n * PURPOSE:    Implementation for EDON-R 384 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <edonr.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct EdonR384 : public Mile::ComObject<EdonR384, IHasher>\n    {\n    private:\n\n        edonr_ctx Context;\n\n    public:\n\n        EdonR384()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_edonr384_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_edonr512_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_edonr512_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return edonr384_hash_size;\n        }\n    };\n\n    IHasher* CreateEdonR384()\n    {\n        return new EdonR384();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.EdonR512.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.EdonR512.cpp\n * PURPOSE:    Implementation for EDON-R 512 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <edonr.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct EdonR512 : public Mile::ComObject<EdonR512, IHasher>\n    {\n    private:\n\n        edonr_ctx Context;\n\n    public:\n\n        EdonR512()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_edonr512_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_edonr512_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_edonr512_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return edonr512_hash_size;\n        }\n    };\n\n    IHasher* CreateEdonR512()\n    {\n        return new EdonR512();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Gost12256.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Gost12256.cpp\n * PURPOSE:    Implementation for GOST R 34.11-2012 256 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <gost12.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Gost12256 : public Mile::ComObject<Gost12256, IHasher>\n    {\n    private:\n\n        gost12_ctx Context;\n\n    public:\n\n        Gost12256()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_gost12_256_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_gost12_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_gost12_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return gost12_256_hash_size;\n        }\n    };\n\n    IHasher* CreateGost12256()\n    {\n        return new Gost12256();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Gost12512.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Gost12512.cpp\n * PURPOSE:    Implementation for GOST R 34.11-2012 512 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <gost12.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Gost12512 : public Mile::ComObject<Gost12512, IHasher>\n    {\n    private:\n\n        gost12_ctx Context;\n\n    public:\n\n        Gost12512()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_gost12_512_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_gost12_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_gost12_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return gost12_512_hash_size;\n        }\n    };\n\n    IHasher* CreateGost12512()\n    {\n        return new Gost12512();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Gost94.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Gost94.cpp\n * PURPOSE:    Implementation for GOST R 34.11-94 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <gost94.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Gost94 : public Mile::ComObject<Gost94, IHasher>\n    {\n    private:\n\n        gost94_ctx Context;\n\n    public:\n\n        Gost94()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_gost94_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_gost94_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_gost94_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return gost94_hash_length;\n        }\n    };\n\n    IHasher* CreateGost94()\n    {\n        return new Gost94();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Gost94CryptoPro.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Gost94CryptoPro.cpp\n * PURPOSE:    Implementation for GOST R 34.11-94 CryptoPro hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <gost94.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Gost94CryptoPro : public Mile::ComObject<Gost94CryptoPro, IHasher>\n    {\n    private:\n\n        gost94_ctx Context;\n\n    public:\n\n        Gost94CryptoPro()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_gost94_cryptopro_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_gost94_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_gost94_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return gost94_hash_length;\n        }\n    };\n\n    IHasher* CreateGost94CryptoPro()\n    {\n        return new Gost94CryptoPro();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Has160.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Has160.cpp\n * PURPOSE:    Implementation for HAS-160 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <has160.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Has160 : public Mile::ComObject<Has160, IHasher>\n    {\n    private:\n\n        has160_ctx Context;\n\n    public:\n\n        Has160()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_has160_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_has160_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_has160_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return has160_hash_size;\n        }\n    };\n\n    IHasher* CreateHas160()\n    {\n        return new Has160();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Ripemd160.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Ripemd160.cpp\n * PURPOSE:    Implementation for RIPEMD-160 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <ripemd-160.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Ripemd160 : public Mile::ComObject<Ripemd160, IHasher>\n    {\n    private:\n\n        ripemd160_ctx Context;\n\n    public:\n\n        Ripemd160()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_ripemd160_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_ripemd160_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_ripemd160_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return ripemd160_hash_size;\n        }\n    };\n\n    IHasher* CreateRipemd160()\n    {\n        return new Ripemd160();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Sha224.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Sha224.cpp\n * PURPOSE:    Implementation for SHA-224 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <sha256.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Sha224 : public Mile::ComObject<Sha224, IHasher>\n    {\n    private:\n\n        sha256_ctx Context;\n\n    public:\n\n        Sha224()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_sha224_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_sha256_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_sha256_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return sha224_hash_size;\n        }\n    };\n\n    IHasher* CreateSha224()\n    {\n        return new Sha224();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Sha3224.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Sha3224.cpp\n * PURPOSE:    Implementation for SHA3-224 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <sha3.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Sha3224 : public Mile::ComObject<Sha3224, IHasher>\n    {\n    private:\n\n        sha3_ctx Context;\n\n    public:\n\n        Sha3224()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_sha3_224_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_sha3_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_sha3_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return sha3_224_hash_size;\n        }\n    };\n\n    IHasher* CreateSha3224()\n    {\n        return new Sha3224();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Sha3256.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Sha3256.cpp\n * PURPOSE:    Implementation for SHA3-256 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <sha3.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Sha3256 : public Mile::ComObject<Sha3256, IHasher>\n    {\n    private:\n\n        sha3_ctx Context;\n\n    public:\n\n        Sha3256()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_sha3_256_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_sha3_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_sha3_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return sha3_256_hash_size;\n        }\n    };\n\n    IHasher* CreateSha3256()\n    {\n        return new Sha3256();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Sha3384.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Sha3384.cpp\n * PURPOSE:    Implementation for SHA3-384 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <sha3.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Sha3384 : public Mile::ComObject<Sha3384, IHasher>\n    {\n    private:\n\n        sha3_ctx Context;\n\n    public:\n\n        Sha3384()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_sha3_384_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_sha3_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_sha3_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return sha3_384_hash_size;\n        }\n    };\n\n    IHasher* CreateSha3384()\n    {\n        return new Sha3384();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Sha3512.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Sha3512.cpp\n * PURPOSE:    Implementation for SHA3-512 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <sha3.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Sha3512 : public Mile::ComObject<Sha3512, IHasher>\n    {\n    private:\n\n        sha3_ctx Context;\n\n    public:\n\n        Sha3512()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_sha3_512_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_sha3_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_sha3_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return sha3_512_hash_size;\n        }\n    };\n\n    IHasher* CreateSha3512()\n    {\n        return new Sha3512();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Sm3.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Sm3.cpp\n * PURPOSE:    Implementation for SM3 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <sm3.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Sm3 : public Mile::ComObject<Sm3, IHasher>\n    {\n    private:\n\n        SM3_CTX Context;\n\n    public:\n\n        Sm3()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::sm3_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::sm3_update(\n                &this->Context,\n                reinterpret_cast<const std::uint8_t*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::sm3_finish(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return SM3_DIGEST_SIZE;\n        }\n    };\n\n    IHasher* CreateSm3()\n    {\n        return new Sm3();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Snefru128.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Snefru128.cpp\n * PURPOSE:    Implementation for Snefru-128 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <snefru.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Snefru128 : public Mile::ComObject<Snefru128, IHasher>\n    {\n    private:\n\n        snefru_ctx Context;\n\n    public:\n\n        Snefru128()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_snefru128_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_snefru_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_snefru_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return snefru128_hash_length;\n        }\n    };\n\n    IHasher* CreateSnefru128()\n    {\n        return new Snefru128();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Snefru256.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Snefru256.cpp\n * PURPOSE:    Implementation for Snefru-256 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <snefru.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Snefru256 : public Mile::ComObject<Snefru256, IHasher>\n    {\n    private:\n\n        snefru_ctx Context;\n\n    public:\n\n        Snefru256()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_snefru256_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_snefru_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_snefru_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return snefru256_hash_length;\n        }\n    };\n\n    IHasher* CreateSnefru256()\n    {\n        return new Snefru256();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Tiger.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Tiger.cpp\n * PURPOSE:    Implementation for Tiger hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <tiger.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Tiger : public Mile::ComObject<Tiger, IHasher>\n    {\n    private:\n\n        tiger_ctx Context;\n\n    public:\n\n        Tiger()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_tiger_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_tiger_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_tiger_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return tiger_hash_length;\n        }\n    };\n\n    IHasher* CreateTiger()\n    {\n        return new Tiger();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Tiger2.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Tiger2.cpp\n * PURPOSE:    Implementation for Tiger2 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <tiger.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Tiger2 : public Mile::ComObject<Tiger2, IHasher>\n    {\n    private:\n\n        tiger_ctx Context;\n\n    public:\n\n        Tiger2()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_tiger2_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_tiger_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_tiger_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return tiger_hash_length;\n        }\n    };\n\n    IHasher* CreateTiger2()\n    {\n        return new Tiger2();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Torrent.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Torrent.cpp\n * PURPOSE:    Implementation for BitTorrent InfoHash (BTIH) hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <torrent.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Torrent : public Mile::ComObject<Torrent, IHasher>\n    {\n    private:\n\n        torrent_ctx Context;\n\n    public:\n\n        Torrent()\n        {\n            this->Init();\n        }\n\n        ~Torrent()\n        {\n            ::bt_cleanup(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::bt_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::bt_update(\n                &this->Context,\n                reinterpret_cast<const void*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::bt_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return btih_hash_size;\n        }\n    };\n\n    IHasher* CreateTorrent()\n    {\n        return new Torrent();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Tth.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Tth.cpp\n * PURPOSE:    Implementation for Tiger Tree Hash (TTH) hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <tth.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Tth : public Mile::ComObject<Tth, IHasher>\n    {\n    private:\n\n        tth_ctx Context;\n\n    public:\n\n        Tth()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_tth_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_tth_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_tth_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return 24;\n        }\n    };\n\n    IHasher* CreateTth()\n    {\n        return new Tth();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Whirlpool.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Whirlpool.cpp\n * PURPOSE:    Implementation for Whirlpool hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <whirlpool.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Whirlpool : public Mile::ComObject<Whirlpool, IHasher>\n    {\n    private:\n\n        whirlpool_ctx Context;\n\n    public:\n\n        Whirlpool()\n        {\n            this->Init();\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::rhash_whirlpool_init(\n                &this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::rhash_whirlpool_update(\n                &this->Context,\n                reinterpret_cast<const unsigned char*>(Data),\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            ::rhash_whirlpool_final(\n                &this->Context,\n                Digest);\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return 64;\n        }\n    };\n\n    IHasher* CreateWhirlpool()\n    {\n        return new Whirlpool();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Xxh3128.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Xxh3128.cpp\n * PURPOSE:    Implementation for XXH3_128bits hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#define XXH_STATIC_LINKING_ONLY\n#include <xxhash.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Xxh3128 : public Mile::ComObject<Xxh3128, IHasher>\n    {\n    private:\n\n        XXH3_state_t* Context;\n\n    public:\n\n        Xxh3128()\n        {\n            this->Context = ::XXH3_createState();\n        }\n\n        ~Xxh3128()\n        {\n            ::XXH3_freeState(\n                this->Context);\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::XXH3_128bits_reset(\n                this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::XXH3_128bits_update(\n                this->Context,\n                Data,\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            XXH128_hash_t FinalDigest = ::XXH3_128bits_digest(\n                this->Context);\n            XXH128_canonical_t CanonicalDigest = {};\n            ::XXH128_canonicalFromHash(&CanonicalDigest, FinalDigest);\n            std::memcpy(\n                Digest,\n                &CanonicalDigest.digest,\n                this->GetDigestSize());\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return 16;\n        }\n    };\n\n    IHasher* CreateXxh3128()\n    {\n        return new Xxh3128();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Xxh32.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Xxh32.cpp\n * PURPOSE:    Implementation for XXH32 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#define XXH_STATIC_LINKING_ONLY\n#include <xxhash.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Xxh32 : public Mile::ComObject<Xxh32, IHasher>\n    {\n    private:\n\n        XXH32_state_t* Context;\n\n    public:\n\n        Xxh32()\n        {\n            this->Context = ::XXH32_createState();\n        }\n\n\n        ~Xxh32()\n        {\n            ::XXH32_freeState(\n                this->Context);\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::XXH32_reset(\n                this->Context,\n                0);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::XXH32_update(\n                this->Context,\n                Data,\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            XXH32_hash_t FinalDigest = ::XXH32_digest(\n                this->Context);\n            // Warning: The 7-Zip Plugin Host will use little-endian for digest\n            // not longer than 8 bytes.\n            std::memcpy(\n                Digest,\n                &FinalDigest,\n                this->GetDigestSize());\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return 4;\n        }\n    };\n\n    IHasher* CreateXxh32()\n    {\n        return new Xxh32();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Xxh364.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Xxh364.cpp\n * PURPOSE:    Implementation for XXH3_64bits hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#define XXH_STATIC_LINKING_ONLY\n#include <xxhash.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Xxh364 : public Mile::ComObject<Xxh364, IHasher>\n    {\n    private:\n\n        XXH3_state_t* Context;\n\n    public:\n\n        Xxh364()\n        {\n            this->Context = ::XXH3_createState();\n        }\n\n        ~Xxh364()\n        {\n            ::XXH3_freeState(\n                this->Context);\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::XXH3_64bits_reset(\n                this->Context);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::XXH3_64bits_update(\n                this->Context,\n                Data,\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            XXH64_hash_t FinalDigest = ::XXH3_64bits_digest(\n                this->Context);\n            // Warning: The 7-Zip Plugin Host will use little-endian for digest\n            // not longer than 8 bytes.\n            std::memcpy(\n                Digest,\n                &FinalDigest,\n                this->GetDigestSize());\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return 8;\n        }\n    };\n\n    IHasher* CreateXxh364()\n    {\n        return new Xxh364();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Hash.Xxh64.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Hash.Xxh64.cpp\n * PURPOSE:    Implementation for XXH64 hash algorithm\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#define XXH_STATIC_LINKING_ONLY\n#include <xxhash.h>\n\nnamespace NanaZip::Codecs::Hash\n{\n    struct Xxh64 : public Mile::ComObject<Xxh64, IHasher>\n    {\n    private:\n\n        XXH64_state_t* Context;\n\n    public:\n\n        Xxh64()\n        {\n            this->Context = ::XXH64_createState();\n        }\n\n        ~Xxh64()\n        {\n            ::XXH64_freeState(\n                this->Context);\n        }\n\n        void STDMETHODCALLTYPE Init()\n        {\n            ::XXH64_reset(\n                this->Context,\n                0);\n        }\n\n        void STDMETHODCALLTYPE Update(\n            _In_ LPCVOID Data,\n            _In_ UINT32 Size)\n        {\n            ::XXH64_update(\n                this->Context,\n                Data,\n                Size);\n        }\n\n        void STDMETHODCALLTYPE Final(\n            _Out_ PBYTE Digest)\n        {\n            XXH64_hash_t FinalDigest = ::XXH64_digest(\n                this->Context);\n            // Warning: The 7-Zip Plugin Host will use little-endian for digest\n            // not longer than 8 bytes.\n            std::memcpy(\n                Digest,\n                &FinalDigest,\n                this->GetDigestSize());\n        }\n\n        UINT32 STDMETHODCALLTYPE GetDigestSize()\n        {\n            return 8;\n        }\n    };\n\n    IHasher* CreateXxh64()\n    {\n        return new Xxh64();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.Brotli.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.Brotli.cpp\n * PURPOSE:    Implementation for Brotli Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.Brotli.h\"\n\n#include <cstddef>\n\nEXTERN_C int NanaZipCodecsBrotliRead(\n    void* Context,\n    BROTLIMT_Buffer* Input)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedInput;\n    ConvertedInput.Buffer = Input->buf;\n    ConvertedInput.Size = Input->size;\n    ConvertedInput.Allocated = Input->allocated;\n    int Result = ::NanaZipCodecsCommonRead(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedInput);\n    Input->buf = ConvertedInput.Buffer;\n    Input->size = ConvertedInput.Size;\n    Input->allocated = ConvertedInput.Allocated;\n    return Result;\n}\n\nEXTERN_C int NanaZipCodecsBrotliWrite(\n    void* Context,\n    BROTLIMT_Buffer* Output)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedOutput;\n    ConvertedOutput.Buffer = Output->buf;\n    ConvertedOutput.Size = Output->size;\n    ConvertedOutput.Allocated = Output->allocated;\n    return ::NanaZipCodecsCommonWrite(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedOutput);\n}\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsBrotliDecode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize)\n{\n    BROTLIMT_RdWr_t ReadWrite = {};\n    ReadWrite.fn_read = ::NanaZipCodecsBrotliRead;\n    ReadWrite.fn_write = ::NanaZipCodecsBrotliWrite;\n    ReadWrite.arg_read = reinterpret_cast<void*>(StreamContext);\n    ReadWrite.arg_write = reinterpret_cast<void*>(StreamContext);\n\n    BROTLIMT_DCtx* Context = ::BROTLIMT_createDCtx(NumberOfThreads, InputSize);\n    if (!Context)\n    {\n        return S_FALSE;\n    }\n\n    std::size_t Result = ::BROTLIMT_decompressDCtx(Context, &ReadWrite);\n    if (::BROTLIMT_isError(Result))\n    {\n        if (MT_ERROR(canceled) == Result)\n        {\n            return E_ABORT;\n        }\n\n        return E_FAIL;\n    }\n\n    ::BROTLIMT_freeDCtx(Context);\n\n    return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.Brotli.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.Brotli.h\n * PURPOSE:    Definition for Brotli Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_CODECS_MULTI_THREAD_WRAPPER_BROTLI\n#define NANAZIP_CODECS_MULTI_THREAD_WRAPPER_BROTLI\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.Common.h\"\n\n#include <stdint.h>\n#include <brotli-mt.h>\n\nEXTERN_C int NanaZipCodecsBrotliRead(\n    void* Context,\n    BROTLIMT_Buffer* Input);\n\nEXTERN_C int NanaZipCodecsBrotliWrite(\n    void* Context,\n    BROTLIMT_Buffer* Output);\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsBrotliDecode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize);\n\n#endif // !NANAZIP_CODECS_MULTI_THREAD_WRAPPER_BROTLI\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.Common.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.Common.cpp\n * PURPOSE:    Implementation for Common Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.Common.h\"\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\nEXTERN_C int NanaZipCodecsCommonRead(\n    PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context,\n    PNANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT Input)\n{\n    SIZE_T ProcessedSize = 0;\n    HRESULT hr = ::NanaZipCodecsReadInputStream(\n        Context->InputStream,\n        Input->Buffer,\n        Input->Size,\n        &ProcessedSize);\n\n    // catch errors\n    if (E_ABORT == hr)\n    {\n        return -2;\n    }\n    else if (E_OUTOFMEMORY == hr)\n    {\n        return -3;\n    }\n\n    // some other error -> read_fail\n    if (S_OK != hr)\n    {\n        return -1;\n    }\n\n    Input->Size = ProcessedSize;\n    *Context->ProcessedInputSize += ProcessedSize;\n\n    return 0;\n}\n\nEXTERN_C int NanaZipCodecsCommonWrite(\n    PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context,\n    PNANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT Output)\n{\n    UINT32 Todo = static_cast<UINT32>(Output->Size);\n    UINT32 Done = 0;\n\n    while (Todo)\n    {\n        UINT32 Block = 0;\n\n        HRESULT hr = Context->OutputStream->Write(\n            reinterpret_cast<PBYTE>(Output->Buffer) + Done,\n            Todo,\n            &Block);\n\n        // catch errors\n        if (E_ABORT == hr)\n        {\n            return -2;\n        }\n        else if (E_OUTOFMEMORY == hr)\n        {\n            return -3;\n        }\n\n        Done += Block;\n\n        if (SEVENZIP_ERROR_WRITING_WAS_CUT == hr)\n        {\n            break;\n        }\n\n        // some other error -> write_fail\n        if (S_OK != hr)\n        {\n            return -1;\n        }\n\n        if (!Block)\n        {\n            return -1;\n        }\n\n        Todo -= Block;\n    }\n\n    *Context->ProcessedOutputSize += Done;\n\n    // we need no lock here, cause only one thread can write\n    if (Context->Progress)\n    {\n        Context->Progress->SetRatioInfo(\n            Context->ProcessedInputSize,\n            Context->ProcessedOutputSize);\n    }\n\n    return 0;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.Common.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.Common.h\n * PURPOSE:    Definition for Common Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_CODECS_MULTI_THREAD_WRAPPER_COMMON\n#define NANAZIP_CODECS_MULTI_THREAD_WRAPPER_COMMON\n\n#if defined(ZIP7_INC_COMPILER_H) || defined(__7Z_COMPILER_H)\n#include <Windows.h>\n#else\n#include <NanaZip.Specification.SevenZip.h>\n#endif\n\ntypedef struct _NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT\n{\n    ISequentialInStream* InputStream;\n    ISequentialOutStream* OutputStream;\n    ICompressProgressInfo* Progress;\n    PUINT64 ProcessedInputSize;\n    PUINT64 ProcessedOutputSize;\n} NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT, *PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT;\n\ntypedef struct _NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT\n{\n    PVOID Buffer;\n    SIZE_T Size;\n    SIZE_T Allocated;\n} NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT, *PNANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT;\n\nEXTERN_C int NanaZipCodecsCommonRead(\n    PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context,\n    PNANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT Input);\n\nEXTERN_C int NanaZipCodecsCommonWrite(\n    PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context,\n    PNANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT Output);\n\n#endif // !NANAZIP_CODECS_MULTI_THREAD_WRAPPER_COMMON\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.LZ4.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.LZ4.cpp\n * PURPOSE:    Implementation for LZ4 Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.LZ4.h\"\n\n#include <cstddef>\n\nEXTERN_C int NanaZipCodecsLz4Read(\n    void* Context,\n    LZ4MT_Buffer* Input)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedInput;\n    ConvertedInput.Buffer = Input->buf;\n    ConvertedInput.Size = Input->size;\n    ConvertedInput.Allocated = Input->allocated;\n    int Result = ::NanaZipCodecsCommonRead(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedInput);\n    Input->buf = ConvertedInput.Buffer;\n    Input->size = ConvertedInput.Size;\n    Input->allocated = ConvertedInput.Allocated;\n    return Result;\n}\n\nEXTERN_C int NanaZipCodecsLz4Write(\n    void* Context,\n    LZ4MT_Buffer* Output)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedOutput;\n    ConvertedOutput.Buffer = Output->buf;\n    ConvertedOutput.Size = Output->size;\n    ConvertedOutput.Allocated = Output->allocated;\n    return ::NanaZipCodecsCommonWrite(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedOutput);\n}\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsLz4Decode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize)\n{\n    LZ4MT_RdWr_t ReadWrite = {};\n    ReadWrite.fn_read = ::NanaZipCodecsLz4Read;\n    ReadWrite.fn_write = ::NanaZipCodecsLz4Write;\n    ReadWrite.arg_read = reinterpret_cast<void*>(StreamContext);\n    ReadWrite.arg_write = reinterpret_cast<void*>(StreamContext);\n\n    LZ4MT_DCtx* Context = ::LZ4MT_createDCtx(NumberOfThreads, InputSize);\n    if (!Context)\n    {\n        return S_FALSE;\n    }\n\n    std::size_t Result = ::LZ4MT_decompressDCtx(Context, &ReadWrite);\n    if (::LZ4MT_isError(Result))\n    {\n        if (ERROR(canceled) == Result)\n        {\n            return E_ABORT;\n        }\n\n        return E_FAIL;\n    }\n\n    ::LZ4MT_freeDCtx(Context);\n\n    return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.LZ4.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.LZ4.h\n * PURPOSE:    Definition for LZ4 Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LZ4\n#define NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LZ4\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.Common.h\"\n\n#include <stdint.h>\n#include <lz4-mt.h>\n\nEXTERN_C int NanaZipCodecsLz4Read(\n    void* Context,\n    LZ4MT_Buffer* Input);\n\nEXTERN_C int NanaZipCodecsLz4Write(\n    void* Context,\n    LZ4MT_Buffer* Output);\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsLz4Decode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize);\n\n#endif // !NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LZ4\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.LZ5.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.LZ5.cpp\n * PURPOSE:    Implementation for LZ5 Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.LZ5.h\"\n\n#include <cstddef>\n\nEXTERN_C int NanaZipCodecsLz5Read(\n    void* Context,\n    LZ5MT_Buffer* Input)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedInput;\n    ConvertedInput.Buffer = Input->buf;\n    ConvertedInput.Size = Input->size;\n    ConvertedInput.Allocated = Input->allocated;\n    int Result = ::NanaZipCodecsCommonRead(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedInput);\n    Input->buf = ConvertedInput.Buffer;\n    Input->size = ConvertedInput.Size;\n    Input->allocated = ConvertedInput.Allocated;\n    return Result;\n}\n\nEXTERN_C int NanaZipCodecsLz5Write(\n    void* Context,\n    LZ5MT_Buffer* Output)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedOutput;\n    ConvertedOutput.Buffer = Output->buf;\n    ConvertedOutput.Size = Output->size;\n    ConvertedOutput.Allocated = Output->allocated;\n    return ::NanaZipCodecsCommonWrite(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedOutput);\n}\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsLz5Decode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize)\n{\n    LZ5MT_RdWr_t ReadWrite = {};\n    ReadWrite.fn_read = ::NanaZipCodecsLz5Read;\n    ReadWrite.fn_write = ::NanaZipCodecsLz5Write;\n    ReadWrite.arg_read = reinterpret_cast<void*>(StreamContext);\n    ReadWrite.arg_write = reinterpret_cast<void*>(StreamContext);\n\n    LZ5MT_DCtx* Context = ::LZ5MT_createDCtx(NumberOfThreads, InputSize);\n    if (!Context)\n    {\n        return S_FALSE;\n    }\n\n    std::size_t Result = ::LZ5MT_decompressDCtx(Context, &ReadWrite);\n    if (::LZ5MT_isError(Result))\n    {\n        if (ERROR(canceled) == Result)\n        {\n            return E_ABORT;\n        }\n\n        return E_FAIL;\n    }\n\n    ::LZ5MT_freeDCtx(Context);\n\n    return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.LZ5.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.LZ5.h\n * PURPOSE:    Definition for LZ5 Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LZ5\n#define NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LZ5\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.Common.h\"\n\n#include <stdint.h>\n#include <lz5-mt.h>\n\nEXTERN_C int NanaZipCodecsLz5Read(\n    void* Context,\n    LZ5MT_Buffer* Input);\n\nEXTERN_C int NanaZipCodecsLz5Write(\n    void* Context,\n    LZ5MT_Buffer* Output);\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsLz5Decode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize);\n\n#endif // !NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LZ5\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.Lizard.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.Lizard.cpp\n * PURPOSE:    Implementation for Lizard Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.Lizard.h\"\n\n#include <cstddef>\n\nEXTERN_C int NanaZipCodecsLizardRead(\n    void* Context,\n    LIZARDMT_Buffer* Input)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedInput;\n    ConvertedInput.Buffer = Input->buf;\n    ConvertedInput.Size = Input->size;\n    ConvertedInput.Allocated = Input->allocated;\n    int Result = ::NanaZipCodecsCommonRead(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedInput);\n    Input->buf = ConvertedInput.Buffer;\n    Input->size = ConvertedInput.Size;\n    Input->allocated = ConvertedInput.Allocated;\n    return Result;\n}\n\nEXTERN_C int NanaZipCodecsLizardWrite(\n    void* Context,\n    LIZARDMT_Buffer* Output)\n{\n    NANAZIP_CODECS_ZSTDMT_BUFFER_CONTEXT ConvertedOutput;\n    ConvertedOutput.Buffer = Output->buf;\n    ConvertedOutput.Size = Output->size;\n    ConvertedOutput.Allocated = Output->allocated;\n    return ::NanaZipCodecsCommonWrite(\n        reinterpret_cast<PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT>(Context),\n        &ConvertedOutput);\n}\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsLizardDecode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize)\n{\n    LIZARDMT_RdWr_t ReadWrite = {};\n    ReadWrite.fn_read = ::NanaZipCodecsLizardRead;\n    ReadWrite.fn_write = ::NanaZipCodecsLizardWrite;\n    ReadWrite.arg_read = reinterpret_cast<void*>(StreamContext);\n    ReadWrite.arg_write = reinterpret_cast<void*>(StreamContext);\n\n    LIZARDMT_DCtx* Context = ::LIZARDMT_createDCtx(NumberOfThreads, InputSize);\n    if (!Context)\n    {\n        return S_FALSE;\n    }\n\n    std::size_t Result = ::LIZARDMT_decompressDCtx(Context, &ReadWrite);\n    if (::LIZARDMT_isError(Result))\n    {\n        if (ERROR(canceled) == Result)\n        {\n            return E_ABORT;\n        }\n\n        return E_FAIL;\n    }\n\n    ::LIZARDMT_freeDCtx(Context);\n\n    return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.MultiThreadWrapper.Lizard.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.MultiThreadWrapper.Lizard.h\n * PURPOSE:    Definition for Lizard Multi Thread Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LIZARD\n#define NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LIZARD\n\n#include \"NanaZip.Codecs.MultiThreadWrapper.Common.h\"\n\n#include <stdint.h>\n#include <lizard-mt.h>\n\nEXTERN_C int NanaZipCodecsLizardRead(\n    void* Context,\n    LIZARDMT_Buffer* Input);\n\nEXTERN_C int NanaZipCodecsLizardWrite(\n    void* Context,\n    LIZARDMT_Buffer* Output);\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsLizardDecode(\n    _In_ PNANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT StreamContext,\n    _In_ UINT32 NumberOfThreads,\n    _In_ UINT32 InputSize);\n\n#endif // !NANAZIP_CODECS_MULTI_THREAD_WRAPPER_LIZARD\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.SevenZipWrapper.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.SevenZipWrapper.cpp\n * PURPOSE:    Implementation for 7-Zip Codec Interface Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.SevenZipWrapper.h\"\n\nnamespace\n{\n    const UINT32 BlockSize = static_cast<UINT32>(1) << 31;\n}\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsReadInputStream(\n    _In_ ISequentialInStream* InputStream,\n    _Out_ PVOID Buffer,\n    _In_ SIZE_T NumberOfBytesToRead,\n    _Out_opt_ PSIZE_T NumberOfBytesRead)\n{\n    SIZE_T ProcessedBytes = 0;\n    while (0 != NumberOfBytesToRead)\n    {\n        UINT32 CurrentSize =\n            NumberOfBytesToRead < BlockSize\n            ? static_cast<UINT32>(NumberOfBytesToRead)\n            : BlockSize;\n        UINT32 CurrentProcessedBytes = 0;\n        HRESULT hr = InputStream->Read(\n            Buffer,\n            CurrentSize,\n            &CurrentProcessedBytes);\n        ProcessedBytes += CurrentProcessedBytes;\n        Buffer = static_cast<PVOID>(\n            static_cast<PBYTE>(Buffer) + CurrentProcessedBytes);\n        NumberOfBytesToRead -= CurrentProcessedBytes;\n        if (S_OK != hr)\n        {\n            return hr;\n        }\n        if (0 == CurrentProcessedBytes)\n        {\n            break;\n        }\n    }\n    if (NumberOfBytesRead)\n    {\n        *NumberOfBytesRead = ProcessedBytes;\n    }\n    return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.SevenZipWrapper.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.SevenZipWrapper.h\n * PURPOSE:    Definition for 7-Zip Codec Interface Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_CODECS_SEVENZIP_WRAPPER\n#define NANAZIP_CODECS_SEVENZIP_WRAPPER\n\n#if defined(ZIP7_INC_COMPILER_H) || defined(__7Z_COMPILER_H)\n#include <Windows.h>\n#else\n#include <NanaZip.Specification.SevenZip.h>\n#endif\n\nEXTERN_C HRESULT WINAPI NanaZipCodecsReadInputStream(\n    _In_ ISequentialInStream* InputStream,\n    _Out_ PVOID Buffer,\n    _In_ SIZE_T NumberOfBytesToRead,\n    _Out_opt_ PSIZE_T NumberOfBytesRead);\n\n#endif // !NANAZIP_CODECS_SEVENZIP_WRAPPER\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Sfx.Shared.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaZip\n  FILE:       NanaZip.Codecs.Sfx.Shared.props\n  PURPOSE:    MSBuild Properties for NanaZip.Codecs.Sfx.Shared\n\n  LICENSE:    The MIT License\n\n  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n-->\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory)xxHash\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Zstandard\\;$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <Link>\n      <AdditionalDependencies>$(OutDir)NanaZip.Codecs.Sfx.Shared.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)NanaZip.Codecs.Sfx.Shared.vcxproj\">\n      <Project>{1E894B34-F9D2-4258-9401-6519AAE91620}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Sfx.Shared.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{1E894B34-F9D2-4258-9401-6519AAE91620}</ProjectGuid>\n    <RootNamespace>NanaZip.Codecs.Sfx.Shared</RootNamespace>\n    <MileProjectType>StaticLibrary</MileProjectType>\n  </PropertyGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory)xxHash\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Zstandard\\;$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"xxHash\\xxhash.c\" />\n    <ClCompile Include=\"Zstandard\\common\\debug.c\" />\n    <ClCompile Include=\"Zstandard\\common\\entropy_common.c\" />\n    <ClCompile Include=\"Zstandard\\common\\error_private.c\" />\n    <ClCompile Include=\"Zstandard\\common\\fse_decompress.c\" />\n    <ClCompile Include=\"Zstandard\\common\\pool.c\" />\n    <ClCompile Include=\"Zstandard\\common\\threading.c\" />\n    <ClCompile Include=\"Zstandard\\common\\zstd_common.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\huf_decompress.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_ddict.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress_block.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"xxHash\\xxhash.h\" />\n    <ClInclude Include=\"Zstandard\\common\\allocations.h\" />\n    <ClInclude Include=\"Zstandard\\common\\bits.h\" />\n    <ClInclude Include=\"Zstandard\\common\\bitstream.h\" />\n    <ClInclude Include=\"Zstandard\\common\\compiler.h\" />\n    <ClInclude Include=\"Zstandard\\common\\cpu.h\" />\n    <ClInclude Include=\"Zstandard\\common\\debug.h\" />\n    <ClInclude Include=\"Zstandard\\common\\error_private.h\" />\n    <ClInclude Include=\"Zstandard\\common\\fse.h\" />\n    <ClInclude Include=\"Zstandard\\common\\huf.h\" />\n    <ClInclude Include=\"Zstandard\\common\\mem.h\" />\n    <ClInclude Include=\"Zstandard\\common\\pool.h\" />\n    <ClInclude Include=\"Zstandard\\common\\portability_macros.h\" />\n    <ClInclude Include=\"Zstandard\\common\\threading.h\" />\n    <ClInclude Include=\"Zstandard\\common\\zstd_deps.h\" />\n    <ClInclude Include=\"Zstandard\\common\\zstd_internal.h\" />\n    <ClInclude Include=\"Zstandard\\common\\zstd_trace.h\" />\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_ddict.h\" />\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_block.h\" />\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_internal.h\" />\n    <ClInclude Include=\"Zstandard\\zstd.h\" />\n    <ClInclude Include=\"Zstandard\\zstd_errors.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Codecs.Sfx.Shared.props\" />\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Sfx.Shared.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <ClCompile Include=\"xxHash\\xxhash.c\">\n      <Filter>xxHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\debug.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\entropy_common.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\error_private.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\fse_decompress.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\pool.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\threading.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\zstd_common.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\huf_decompress.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_ddict.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress_block.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <Filter Include=\"xxHash\">\n      <UniqueIdentifier>{c1b717a9-c9d9-472f-ba5c-dc5fe82b7cc5}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\">\n      <UniqueIdentifier>{f48719f6-2f78-4486-8e50-29c661801111}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\\common\">\n      <UniqueIdentifier>{6c79f254-3586-4307-bf3f-707a5567916f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\\decompress\">\n      <UniqueIdentifier>{aba1fb7a-0be1-4311-8d33-9d8ae70b3e17}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"xxHash\\xxhash.h\">\n      <Filter>xxHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\zstd.h\">\n      <Filter>Zstandard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\zstd_errors.h\">\n      <Filter>Zstandard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\allocations.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\bits.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\bitstream.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\compiler.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\cpu.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\debug.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\error_private.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\fse.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\huf.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\mem.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\pool.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\portability_macros.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\threading.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\zstd_deps.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\zstd_internal.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\zstd_trace.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_ddict.h\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_block.h\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_internal.h\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Codecs.Sfx.Shared.props\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Specification.Fat.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Specification.Fat.h\n * PURPOSE:    Definition for the FAT series file system on-disk structure\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n// References\n// - FastFat file system driver implementation in Windows driver samples\n//   - fat.h\n//   - lfn.h\n// - FreeBSD 14.2.0 source code\n//   - sys/fs/msdosfs/bootsect.h\n//   - sys/fs/msdosfs/bpb.h\n\n#ifndef NANAZIP_CODECS_SPECIFICATION_FAT\n#define NANAZIP_CODECS_SPECIFICATION_FAT\n\n#include <Windows.h>\n\n// Note: All on-disk structure of the FAT series file system is little-endian.\n\n// The following nomenclature is used to describe the FAT on-disk structure:\n//   LBN - is the number of a sector relative to the start of the disk.\n//   VBN - is the number of a sector relative to the start of a file, directory,\n//         or allocation.\n//   LBO - is a byte offset relative to the start of the disk.\n//   VBO - is a byte offset relative to the start of a file, directory or\n//         allocation.\n\n// LBO is >32 bits for FAT32.\ntypedef LONGLONG LBO;\n\ntypedef LBO *PLBO;\n\ntypedef ULONG32 VBO;\ntypedef VBO *PVBO;\n\n// The boot sector is the first physical sector (LBN == 0) on the volume. Part\n// of the sector contains a BIOS Parameter Block. The BIOS in the sector is\n// packed (i.e., unaligned) so we'll supply a unpacking macro to translate a\n// packed BIOS into its unpacked equivalent. The unpacked BIOS structure is\n// already defined in ntioapi.h so we only need to define the packed BIOS.\n\n/**\n * @brief Packed BIOS Parameter Block for FAT12 and FAT16.\n */\ntypedef struct _PACKED_BIOS_PARAMETER_BLOCK\n{\n    UINT8 BytesPerSector[2];\n    UINT8 SectorsPerCluster;\n    UINT8 ReservedSectors[2];\n    UINT8 Fats;\n    UINT8 RootEntries[2];\n    UINT8 Sectors[2];\n    UINT8 Media;\n    // FAT32 if SectorsPerFat is 0.\n    UINT8 SectorsPerFat[2];\n    UINT8 SectorsPerTrack[2];\n    UINT8 Heads[2];\n    UINT8 HiddenSectors[4];\n    UINT8 LargeSectors[4];\n} PACKED_BIOS_PARAMETER_BLOCK, *PPACKED_BIOS_PARAMETER_BLOCK;\nC_ASSERT(sizeof(PACKED_BIOS_PARAMETER_BLOCK) == 25);\n\n/**\n * @brief Packed BIOS Parameter Block for FAT32.\n */\ntypedef struct _PACKED_BIOS_PARAMETER_BLOCK_EX\n{\n    PACKED_BIOS_PARAMETER_BLOCK Bpb;\n    UINT8 LargeSectorsPerFat[4];\n    // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |\n    // |     ActiveFat     | Reserved0 | M |         Reserved1         |\n    // M: MirrorDisabled\n    UINT8 ExtendedFlags[2];\n    UINT8 FsVersion[2];\n    UINT8 RootDirFirstCluster[4];\n    UINT8 FsInfoSector[2];\n    UINT8 BackupBootSector[2];\n    UINT8 Reserved[12];\n} PACKED_BIOS_PARAMETER_BLOCK_EX, *PPACKED_BIOS_PARAMETER_BLOCK_EX;\nC_ASSERT(sizeof(PACKED_BIOS_PARAMETER_BLOCK_EX) == 53);\n\n/**\n * @brief Boot sector for FAT12 and FAT16.\n */\ntypedef struct _PACKED_BOOT_SECTOR\n{\n    UINT8 Jump[3];\n    UINT8 Oem[8];\n    PACKED_BIOS_PARAMETER_BLOCK PackedBpb;\n    UINT8 PhysicalDriveNumber;\n    UINT8 CurrentHead;\n    UINT8 Signature;\n    UINT8 Id[4];\n    UINT8 VolumeLabel[11];\n    UINT8 SystemId[8];\n} PACKED_BOOT_SECTOR, *PPACKED_BOOT_SECTOR;\nC_ASSERT(sizeof(PACKED_BOOT_SECTOR) == 62);\n\n/**\n * @brief Boot sector for FAT32.\n */\ntypedef struct _PACKED_BOOT_SECTOR_EX\n{\n    UINT8 Jump[3];\n    UINT8 Oem[8];\n    PACKED_BIOS_PARAMETER_BLOCK_EX PackedBpb;\n    UINT8 PhysicalDriveNumber;\n    UINT8 CurrentHead;\n    UINT8 Signature;\n    UINT8 Id[4];\n    UINT8 VolumeLabel[11];\n    UINT8 SystemId[8];\n} PACKED_BOOT_SECTOR_EX, *PPACKED_BOOT_SECTOR_EX;;\nC_ASSERT(sizeof(PACKED_BOOT_SECTOR_EX) == 90);\n\n/**\n * @brief File system information sector for FAT32.\n */\ntypedef struct _PACKED_FSINFO_SECTOR\n{\n    // UINT32\n    UINT8 SectorBeginSignature[4];\n    UINT8 ExtraBootCode[480];\n    // UINT32\n    UINT8 FsInfoSignature[4];\n    // UINT32\n    UINT8 FreeClusterCount[4];\n    // UINT32\n    UINT8 NextFreeCluster[4];\n    UINT8 Reserved[12];\n    // UINT32\n    UINT8 SectorEndSignature[4];\n} PACKED_FSINFO_SECTOR, *PPACKED_FSINFO_SECTOR;\nC_ASSERT(sizeof(PACKED_FSINFO_SECTOR) == 512);\n\n#define FSINFO_SECTOR_BEGIN_SIGNATURE 0x41615252\n#define FSINFO_SECTOR_END_SIGNATURE 0xAA550000\n\n#define FSINFO_SIGNATURE 0x61417272\n\n// We use the CurrentHead field for our dirty partition info.\n\n#define FAT_BOOT_SECTOR_DIRTY 0x01\n#define FAT_BOOT_SECTOR_TEST_SURFACE 0x02\n\n// Define a Fat Entry type. This type is used when representing a fat table\n// entry. It also used to be used when dealing with a fat table index and a\n// count of entries, but the ensuing type casting nightmare sealed this fate.\n// These other two types are represented as ULONGs.\ntypedef UINT32 FAT_ENTRY;\n\n#define FAT32_ENTRY_MASK 0x0FFFFFFFUL\n\n// We use these special index values to set the dirty info for DOS/Win9x\n// compatibility.\n\n#define FAT_CLEAN_VOLUME (~FAT32_ENTRY_MASK | 0)\n#define FAT_DIRTY_VOLUME (~FAT32_ENTRY_MASK | 1)\n\n#define FAT_DIRTY_BIT_INDEX 1\n\n// Physically, the entry is fully set if clean, and the high bit knocked out if\n// it is dirty (i.e., it is really a clean bit). This means it is different\n// per-FAT size.\n\n#define FAT_CLEAN_ENTRY (~0)\n\n#define FAT12_DIRTY_ENTRY 0x7ff\n#define FAT16_DIRTY_ENTRY 0x7fff\n#define FAT32_DIRTY_ENTRY 0x7fffffff\n\n// The following constants the are the valid Fat index values.\n\n#define FAT_CLUSTER_AVAILABLE (FAT_ENTRY)0x00000000\n#define FAT_CLUSTER_RESERVED (FAT_ENTRY)0x0ffffff0\n#define FAT_CLUSTER_BAD (FAT_ENTRY)0x0ffffff7\n#define FAT_CLUSTER_LAST (FAT_ENTRY)0x0fffffff\n\n// Fat files have the following time/date structures. Note that the following\n// structure is a 32 bits long but USHORT aligned.\n\n/**\n * @brief Packed FAT time.\n */\ntypedef struct _PACKED_FAT_TIME\n{\n    // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |\n    // |   DoubleSeconds   |        Minute         |       Hour        |\n    // UINT16\n    UINT8 Time[2];\n} PACKED_FAT_TIME, *PPACKED_FAT_TIME;\n\n/**\n * @brief Packed FAT date.\n */\ntypedef struct _PACKED_FAT_DATE\n{\n    // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |\n    // |        Day        |     Month     |  Year (Relative to 1980)  |\n    // UINT16\n    UINT8 Date[2];\n} PACKED_FAT_DATE, *PPACKED_FAT_DATE;\n\n/**\n * @brief Packed FAT time stamp.\n */\ntypedef struct _PACKED_FAT_TIME_STAMP\n{\n    PACKED_FAT_TIME Time;\n    PACKED_FAT_DATE Date;\n} PACKED_FAT_TIME_STAMP, *PPACKED_FAT_TIME_STAMP;\n\n/**\n * @brief FAT files have 8 character file names and 3 character extensions.\n */\ntypedef UINT8 FAT8DOT3[11], *PFAT8DOT3;\n\n/**\n * @brief The packed directory entry record exists for every file/directory on\n *        the disk except for the root directory.\n */\ntypedef struct _PACKED_DIRENT\n{\n    FAT8DOT3 FileName;\n    UINT8 Attributes;\n    UINT8 NtByte;\n    UINT8 CreationMSec;\n    PACKED_FAT_TIME_STAMP CreationTime;\n    PACKED_FAT_DATE LastAccessDate;\n    union\n    {\n        // UINT16\n        UINT8 ExtendedAttributes[2];\n        // UINT16\n        UINT8 FirstClusterOfFileHi[2];\n    };\n    PACKED_FAT_TIME_STAMP LastWriteTime;\n    // UINT16\n    UINT8 FirstClusterOfFile[2];\n    ULONG32 FileSize;\n} PACKED_DIRENT, *PPACKED_DIRENT;\nC_ASSERT(sizeof(PACKED_DIRENT) == 32);\n\n// The first byte of a dirent describes the dirent. There is also a routine to\n// help in deciding how to interpret the dirent.\n\n#define FAT_DIRENT_NEVER_USED 0x00\n#define FAT_DIRENT_REALLY_0E5 0x05\n#define FAT_DIRENT_DIRECTORY_ALIAS 0x2e\n#define FAT_DIRENT_DELETED 0xe5\n\n// Define the NtByte bits. These two bits are used for EFS on FAT.\n//   0x1 means the file contents are encrypted\n//   0x2 means the EFS metadata header is big. (this optimization means we don't\n//       have to read in the first sector of the file stream to get the normal\n//       header size)\n\n#define FAT_DIRENT_NT_BYTE_ENCRYPTED 0x01\n#define FAT_DIRENT_NT_BYTE_BIG_HEADER 0x02\n\n// These two bits optimize the case in which either the name or extension are\n// all lower case.\n\n#define FAT_DIRENT_NT_BYTE_8_LOWER_CASE 0x08\n#define FAT_DIRENT_NT_BYTE_3_LOWER_CASE 0x10\n\n// Define the various dirent attributes\n\n#define FAT_DIRENT_ATTR_READ_ONLY 0x01\n#define FAT_DIRENT_ATTR_HIDDEN 0x02\n#define FAT_DIRENT_ATTR_SYSTEM 0x04\n#define FAT_DIRENT_ATTR_VOLUME_ID 0x08\n#define FAT_DIRENT_ATTR_DIRECTORY 0x10\n#define FAT_DIRENT_ATTR_ARCHIVE 0x20\n#define FAT_DIRENT_ATTR_DEVICE 0x40\n#define FAT_DIRENT_ATTR_LFN ( \\\n    FAT_DIRENT_ATTR_READ_ONLY | FAT_DIRENT_ATTR_HIDDEN | \\\n    FAT_DIRENT_ATTR_SYSTEM | FAT_DIRENT_ATTR_VOLUME_ID)\n\n/**\n * @brief This strucure defines the on disk format on long file name dirents.\n */\ntypedef struct _PACKED_LFN_DIRENT\n{\n    UINT8 Ordinal;\n    // Actually 5 chars, but not WCHAR aligned.\n    UINT8 Name1[10];\n    UINT8 Attributes;\n    UINT8 Type;\n    UINT8 Checksum;\n    WCHAR Name2[6];\n    // UINT16\n    UINT8 MustBeZero[2];\n    WCHAR Name3[2];\n} PACKED_LFN_DIRENT, *PPACKED_LFN_DIRENT;\nC_ASSERT(sizeof(PACKED_LFN_DIRENT) == 32);\n\n// Ordinal field\n#define FAT_LAST_LONG_ENTRY 0x40\n// Type field\n#define FAT_LONG_NAME_COMP 0x0\n\n// This is the largest size buffer we would ever need to read an LFN\n\n#define MAX_LFN_CHARACTERS 260\n#define MAX_LFN_DIRENTS 20\n\n// On-disk extension for EFS files.\n\n#define FAT_EFS_EXTENSION L\".PFILE\"\n#define FAT_EFS_EXTENSION_CHARCOUNT (6)\n#define FAT_EFS_EXTENSION_BYTECOUNT (12)\n\n// On-disk extension for EA data.\n\n#define EA_FILE_SIGNATURE (0x4445) // \"ED\"\n#define EA_SET_SIGNATURE (0x4145) // \"EA\"\n\n// If the volume contains any ea data then there is one EA file called\n// \"EA DATA. SF\" located in the root directory as Hidden, System and ReadOnly.\n\ntypedef UINT8 PACKED_EA_OFFSET[2], *PPACKED_EA_OFFSET;\n\n/**\n * @brief Packed EA file header.\n */\ntypedef struct _PACKED_EA_FILE_HEADER\n{\n    // UINT16\n    UINT8 Signature[2];\n    // UINT16\n    UINT8 FormatType[2];\n    // UINT16\n    UINT8 LogType[2];\n    // UINT16\n    UINT8 Cluster1[2];\n    // UINT16\n    UINT8 NewCValue1[2];\n    // UINT16\n    UINT8 Cluster2[2];\n    // UINT16\n    UINT8 NewCValue2[2];\n    // UINT16\n    UINT8 Cluster3[2];\n    // UINT16\n    UINT8 NewCValue3[2];\n    // UINT16\n    UINT8 Handle[2];\n    // UINT16\n    UINT8 NewHOffset[2];\n    UINT8 Reserved[10];\n    PACKED_EA_OFFSET EaBaseTable[240];\n} PACKED_EA_FILE_HEADER, *PPACKED_EA_FILE_HEADER;\nC_ASSERT(sizeof(PACKED_EA_FILE_HEADER) == 512);\n\ntypedef PACKED_EA_OFFSET EA_OFFSET_TABLE[128], *PEA_OFFSET_TABLE;\n\n/**\n * @brief Every file with an extended attribute contains in its dirent an index\n *        into the EaMapTable. The map table contains an offset within the EA\n *        file (cluster aligned) of the EA data for the file. The individual EA\n *        data for each file is prefaced with an EA Data Header.\n */\ntypedef struct _PACKED_EA_SET_HEADER\n{\n    // UINT16\n    UINT8 Signature[2];\n    // UINT16\n    UINT8 OwnEaHandle[2];\n    // UINT32\n    UINT8 NeedEaCount[4];\n    UINT8 OwnerFileName[14];\n    UINT8 Reserved[4];\n    // UINT32\n    UINT8 cbList[4];\n    UINT8 PackedEas[ANYSIZE_ARRAY];\n} PACKED_EA_SET_HEADER, *PPACKED_EA_SET_HEADER;\n#define SIZE_OF_EA_SET_HEADER 30\n#define ACTUAL_SIZE_OF_EA_SET_HEADER \\\n    FIELD_OFFSET(PACKED_EA_SET_HEADER, PackedEas)\nC_ASSERT(ACTUAL_SIZE_OF_EA_SET_HEADER == SIZE_OF_EA_SET_HEADER);\n\n#define MAXIMUM_EA_SIZE 0x0000ffff\n\n/**\n * @brief Every individual EA in an EA set is declared the following packed EA.\n */\ntypedef struct _PACKED_EA {\n    UINT8 Flags;\n    // The null terminator is not included in the length. But the EA name is\n    // always null terminated.\n    UINT8 EaNameLength;\n    // UINT16\n    UINT8 EaValueLength[2];\n    UINT8 EaName[ANYSIZE_ARRAY];\n} PACKED_EA, *PPACKED_EA;\n\n#define EA_NEED_EA_FLAG 0x80\n#define MIN_EA_HANDLE 1\n#define MAX_EA_HANDLE 30719\n#define UNUSED_EA_HANDLE 0xffff\n#define EA_CBLIST_OFFSET 0x1a\n#define MAX_EA_BASE_INDEX 240\n#define MAX_EA_OFFSET_INDEX 128\n\n#endif // !NANAZIP_CODECS_SPECIFICATION_FAT\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.Specification.Zealfs.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.Specification.Zealfs.h\n * PURPOSE:    Definition for the ZealFS series file system on-disk structure\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n// References\n// - https://github.com/Zeal8bit/Zeal-8-bit-OS\n//   - include/time_h.asm\n//   - kernel_headers/sdcc/include/zos_time.h\n// - https://github.com/Zeal8bit/ZealFS\n//   - include/zealfs_v1.h\n//   - include/zealfs_v2.h\n\n#ifndef NANAZIP_CODECS_SPECIFICATION_ZEALFS\n#define NANAZIP_CODECS_SPECIFICATION_ZEALFS\n\n#include <Mile.Mobility.Portable.Types.h>\n#ifndef MILE_MOBILITY_ENABLE_MINIMUM_SAL\n#include <sal.h>\n#endif // !MILE_MOBILITY_ENABLE_MINIMUM_SAL\n\n/**\n * @brief Specifies a date and time, using individual members for the month,\n *        day, year, weekday, hour, minute, and second, with the format used\n *        in the Zeal 8-bit OS, which is using BCD encoding for all values.\n */\ntypedef struct _ZEALOS_TIME\n{\n    /**\n     * @brief The year. The valid values for this member are 1970 through 2999.\n     *        The Year[0] member contains the high part (hundreds) of the year,\n     *        and the Year[1] member contains the low part of the year.\n     */\n    MO_UINT8 Year[2];\n\n    /**\n     * @brief The month. The valid values for this member are 1 through 12. The\n     *        1 is January, 2 is February, and so on.\n     */\n    MO_UINT8 Month;\n\n    /**\n     * @brief The day of the month. The valid values for this member are 1\n     *        through 31.\n     */\n    MO_UINT8 Day;\n\n    /**\n     * @brief The day of the week. The valid values for this member are 0\n     *        through 6. The 0 is Sunday, 1 is Monday, and so on.\n     */\n    MO_UINT8 Date;\n\n    /**\n     * @brief The hour. The valid values for this member are 0 through 23.\n     */\n    MO_UINT8 Hours;\n\n    /**\n     * @brief The minute. The valid values for this member are 0 through 59.\n     */\n    MO_UINT8 Minutes;\n\n    /**\n     * @brief The second. The valid values for this member are 0 through 59.\n     */\n    MO_UINT8 Seconds;\n} ZEALOS_TIME, *PZEALOS_TIME;\n\n/**\n * @brief The signature for all ZealFS versions, must be 'Z' ascii code.\n */\n#define ZEALFS_MAGIC 'Z'\n\n/**\n * @brief The structure of the common partition header for all ZealFS versions.\n */\ntypedef struct _ZEALFS_COMMON_HEADER\n{\n    /**\n     * @brief Must be ZEALFS_MAGIC.\n     */\n    MO_UINT8 Magic;\n\n    /**\n     * @brief Version of the file system.\n     */\n    MO_UINT8 Version;\n} ZEALFS_COMMON_HEADER, *PZEALFS_COMMON_HEADER;\n\n/**\n * @brief The page size for ZealFS v1.\n */\n#define ZEALFS_V1_PAGE_SIZE 256\n\n/**\n * @brief The maximum number of pages for ZealFS v1.\n */\n#define ZEALFS_V1_MAXIMUM_PAGE_COUNT 256\n\n/**\n * @brief The bitmap size for ZealFS v1.\n */\n#define ZEALFS_V1_BITMAP_SIZE (ZEALFS_V1_MAXIMUM_PAGE_COUNT / 8)\n\n/**\n * @brief The reserved size in partition header for ZealFS v1.\n */\n#define ZEALFS_V1_RESERVED_SIZE 28\n\n/**\n * @brief The minimum partition size for ZealFS v1. According to related FUSE\n *        implementation, the minimum bitmap size seems to be 1 a.k.a. 8 bits\n *        which for 8 pages.\n */\n#define ZEALFS_V1_MINIMUM_PARTITION_SIZE (8 * ZEALFS_V1_PAGE_SIZE)\n\n/**\n * @brief The partition header for ZealFS v1.\n */\ntypedef struct _ZEALFS_V1_HEADER\n{\n    /**\n     * @brief The common partition header for all ZealFS versions.\n     */\n    ZEALFS_COMMON_HEADER Common;\n\n    /**\n     * @brief Number of bytes composing the bitmap. No matter how big the disk\n     *        actually is, the bitmap is always ZEALFS_V1_BITMAP_SIZE bytes big,\n     *        thus we need field to mark the actual number of bytes we will be\n     *        using.\n     */\n    MO_UINT8 BitmapSize;\n\n    /**\n     * @brief Number of free pages.\n     */\n    MO_UINT8 FreePages;\n\n    /**\n     * @brief Bitmap for the free pages. A used page is marked as 1, else 0.\n     *        (256 pages/8-bit = 32)\n     */\n    MO_UINT8 PagesBitmap[ZEALFS_V1_BITMAP_SIZE];\n\n    /**\n     * @brief Reserved bytes, to align the entries and for future use, such as\n     *        extended root directory, volume name, extra bitmap, etc...\n     */\n    MO_UINT8 Reserved[ZEALFS_V1_RESERVED_SIZE];\n} ZEALFS_V1_HEADER, *PZEALFS_V1_HEADER;\n\n#endif // !NANAZIP_CODECS_SPECIFICATION_ZEALFS\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.cpp\n * PURPOSE:    Implementation for NanaZip.Codecs\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Codecs.h\"\n\n#include <Mile.Helpers.CppBase.h>\n\n#include <string>\n#include <vector>\n#include <utility>\n\nnamespace\n{\n    struct HashProviderItem\n    {\n        const char* Name;\n        IHasher* (*Create)();\n    };\n\n    // Registered Hashers\n    // DO NOT CHANGE THE SEQUENCE FOR COMPATIBILITY\n    HashProviderItem g_Hashers[] =\n    {\n        { \"MD2\", NanaZip::Codecs::Hash::CreateMd2 },\n        { \"MD4\", NanaZip::Codecs::Hash::CreateMd4 },\n        { \"MD5\", NanaZip::Codecs::Hash::CreateMd5 },\n        { \"SHA1\", NanaZip::Codecs::Hash::CreateSha1 },\n        { \"SHA256\", NanaZip::Codecs::Hash::CreateSha256 },\n        { \"SHA384\", NanaZip::Codecs::Hash::CreateSha384 },\n        { \"SHA512\", NanaZip::Codecs::Hash::CreateSha512 },\n        { \"SHA3-256\", NanaZip::Codecs::Hash::CreateSha3256 },\n        { \"SHA3-384\", NanaZip::Codecs::Hash::CreateSha3384 },\n        { \"SHA3-512\", NanaZip::Codecs::Hash::CreateSha3512 },\n        { \"BLAKE3\", NanaZip::Codecs::Hash::CreateBlake3 },\n        { \"SM3\", NanaZip::Codecs::Hash::CreateSm3 },\n        { \"AICH\", NanaZip::Codecs::Hash::CreateAich },\n        { \"BLAKE2b\", NanaZip::Codecs::Hash::CreateBlake2b },\n        { \"ED2K\", NanaZip::Codecs::Hash::CreateEd2k },\n        { \"EDON-R-224\", NanaZip::Codecs::Hash::CreateEdonR224 },\n        { \"EDON-R-256\", NanaZip::Codecs::Hash::CreateEdonR256 },\n        { \"EDON-R-384\", NanaZip::Codecs::Hash::CreateEdonR384 },\n        { \"EDON-R-512\", NanaZip::Codecs::Hash::CreateEdonR512 },\n        { \"GOST94\", NanaZip::Codecs::Hash::CreateGost94 },\n        { \"GOST94CryptoPro\", NanaZip::Codecs::Hash::CreateGost94CryptoPro },\n        { \"GOST12-256\", NanaZip::Codecs::Hash::CreateGost12256 },\n        { \"GOST12-512\", NanaZip::Codecs::Hash::CreateGost12512 },\n        { \"HAS-160\", NanaZip::Codecs::Hash::CreateHas160 },\n        { \"RIPEMD-160\", NanaZip::Codecs::Hash::CreateRipemd160 },\n        { \"SHA224\", NanaZip::Codecs::Hash::CreateSha224 },\n        { \"SHA3-224\", NanaZip::Codecs::Hash::CreateSha3224 },\n        { \"SNEFRU-128\", NanaZip::Codecs::Hash::CreateSnefru128 },\n        { \"SNEFRU-256\", NanaZip::Codecs::Hash::CreateSnefru256 },\n        { \"TIGER\", NanaZip::Codecs::Hash::CreateTiger },\n        { \"TIGER2\", NanaZip::Codecs::Hash::CreateTiger2 },\n        { \"BTIH\", NanaZip::Codecs::Hash::CreateTorrent },\n        { \"TTH\", NanaZip::Codecs::Hash::CreateTth },\n        { \"WHIRLPOOL\", NanaZip::Codecs::Hash::CreateWhirlpool },\n        { \"XXH32\", NanaZip::Codecs::Hash::CreateXxh32 },\n        { \"XXH64\", NanaZip::Codecs::Hash::CreateXxh64 },\n        { \"XXH3_64bits\", NanaZip::Codecs::Hash::CreateXxh364 },\n        { \"XXH3_128bits\", NanaZip::Codecs::Hash::CreateXxh3128 },\n    };\n\n    const std::size_t g_HashersCount =\n        sizeof(g_Hashers) / sizeof(*g_Hashers);\n\n    struct ArchiverProviderItem\n    {\n        const char* Name;\n        const char* Extension;\n        const char* AddExtension;\n        std::uint32_t Flags;\n        std::uint32_t TimeFlags;\n        const uint8_t* Signature;\n        std::uint16_t SignatureOffset;\n        std::uint8_t SignatureSize;\n        bool Update;\n        IInArchive* (*CreateIn)();\n    };\n\n    // Registered Archivers\n    // DO NOT CHANGE THE SEQUENCE FOR COMPATIBILITY\n    ArchiverProviderItem g_Archivers[] =\n    {\n        {\n            \"UFS\",\n            \"ufs ufs2 img\",\n            nullptr,\n            SevenZipHandlerFlagBackwardOpen,\n            0,\n            nullptr,\n            0,\n            0,\n            false,\n            NanaZip::Codecs::Archive::CreateUfs\n        },\n        {\n            \".NET Single File Application\",\n            \"coreclrapphost\",\n            nullptr,\n            SevenZipHandlerFlagBackwardOpen,\n            0,\n            nullptr,\n            0,\n            0,\n            false,\n            NanaZip::Codecs::Archive::CreateDotNetSingleFile\n        },\n        {\n            \".Electron Archive (asar)\",\n            \"asar\",\n            nullptr,\n            SevenZipHandlerFlagBackwardOpen,\n            0,\n            nullptr,\n            0,\n            0,\n            false,\n            NanaZip::Codecs::Archive::CreateElectronAsar\n        },\n        {\n            \"ROMFS\",\n            \"romfs\",\n            nullptr,\n            SevenZipHandlerFlagFindSignature,\n            0,\n            reinterpret_cast<const std::uint8_t*>(\"-rom1fs-\"),\n            0,\n            8,\n            false,\n            NanaZip::Codecs::Archive::CreateRomfs\n        },\n        {\n            \"ZealFS\",\n            \"zealfs\",\n            nullptr,\n            SevenZipHandlerFlagFindSignature,\n            0,\n            reinterpret_cast<const std::uint8_t*>(\"Z\"),\n            0,\n            1,\n            false,\n            NanaZip::Codecs::Archive::CreateZealfs\n        },\n        {\n            \"WebAssembly (WASM)\",\n            \"wasm\",\n            nullptr,\n            SevenZipHandlerFlagFindSignature,\n            0,\n            reinterpret_cast<const std::uint8_t*>(\"\\0asm\"),\n            0,\n            4,\n            false,\n            NanaZip::Codecs::Archive::CreateWebAssembly\n        },\n        {\n            \"littlefs\",\n            \"littlefs\",\n            nullptr,\n            SevenZipHandlerFlagBackwardOpen,\n            0,\n            nullptr,\n            0,\n            0,\n            false,\n            NanaZip::Codecs::Archive::CreateLittlefs\n        },\n    };\n\n    const std::size_t g_ArchiversCount =\n        sizeof(g_Archivers) / sizeof(*g_Archivers);\n}\n\nstruct HasherFactory : public Mile::ComObject<\n    HasherFactory, IHashers>\n{\npublic:\n\n    UINT32 STDMETHODCALLTYPE GetNumHashers()\n    {\n        return static_cast<UINT32>(g_HashersCount);\n    }\n\n    HRESULT STDMETHODCALLTYPE GetHasherProp(\n        _In_ UINT32 Index,\n        _In_ PROPID PropId,\n        _Inout_ LPPROPVARIANT Value)\n    {\n        if (!(Index < this->GetNumHashers()))\n        {\n            return E_INVALIDARG;\n        }\n\n        if (!Value)\n        {\n            return E_INVALIDARG;\n        }\n\n        ::PropVariantClear(Value);\n\n        switch (PropId)\n        {\n        case SevenZipHasherId:\n        {\n            Value->uhVal.QuadPart =\n                NanaZip::Codecs::HashProviderIdBase | Index;\n            Value->vt = VT_UI8;\n            break;\n        }\n        case SevenZipHasherName:\n        {\n            Value->bstrVal = ::SysAllocString(\n                Mile::ToWideString(CP_UTF8, g_Hashers[Index].Name).c_str());\n            if (Value->bstrVal)\n            {\n                Value->vt = VT_BSTR;\n            }\n            break;\n        }\n        case SevenZipHasherEncoder:\n        {\n            GUID EncoderGuid;\n            EncoderGuid.Data1 = SevenZipGuidData1;\n            EncoderGuid.Data2 = SevenZipGuidData2;\n            EncoderGuid.Data3 = SevenZipGuidData3Hasher;\n            *reinterpret_cast<PUINT64>(EncoderGuid.Data4) =\n                NanaZip::Codecs::HashProviderIdBase | Index;\n            Value->bstrVal = ::SysAllocStringByteLen(\n                reinterpret_cast<LPCSTR>(&EncoderGuid),\n                sizeof(EncoderGuid));\n            if (Value->bstrVal)\n            {\n                Value->vt = VT_BSTR;\n            }\n            break;\n        }\n        case SevenZipHasherDigestSize:\n        {\n            IHasher* Hasher = g_Hashers[Index].Create();\n            if (Hasher)\n            {\n                Value->ulVal = Hasher->GetDigestSize();\n                Value->vt = VT_UI4;\n                Hasher->Release();\n            }\n            break;\n        }\n        default:\n            return E_INVALIDARG;\n        }\n\n        return S_OK;\n    }\n\n    HRESULT STDMETHODCALLTYPE CreateHasher(\n        _In_ UINT32 Index,\n        _Out_ IHasher** Hasher)\n    {\n        if (!(Index < this->GetNumHashers()))\n        {\n            return E_INVALIDARG;\n        }\n\n        if (!Hasher)\n        {\n            return E_INVALIDARG;\n        }\n\n        *Hasher = g_Hashers[Index].Create();\n        return *Hasher ? S_OK : E_NOINTERFACE;\n    }\n};\n\nEXTERN_C HRESULT WINAPI GetHashers(\n    _Out_ IHashers** Hashers)\n{\n    if (!Hashers)\n    {\n        return E_INVALIDARG;\n    }\n\n    *Hashers = new HasherFactory();\n    return S_OK;\n}\n\nEXTERN_C HRESULT WINAPI CreateObject(\n    _In_ REFCLSID Clsid,\n    _In_ REFIID Iid,\n    _Out_ LPVOID* OutObject)\n{\n    if (!OutObject)\n    {\n        return E_INVALIDARG;\n    }\n\n    if (Iid == __uuidof(IHasher))\n    {\n        if (Clsid.Data1 == SevenZipGuidData1 &&\n            Clsid.Data2 == SevenZipGuidData2 &&\n            Clsid.Data3 == SevenZipGuidData3Hasher)\n        {\n            std::uint64_t ProviderId =\n                *reinterpret_cast<const std::uint64_t*>(Clsid.Data4);\n            std::uint64_t ProviderIdBase = ProviderId & 0xFFFFFFFF00000000;\n            std::uint32_t ProviderIndex =\n                static_cast<std::uint32_t>(ProviderId);\n            if (NanaZip::Codecs::HashProviderIdBase == ProviderIdBase)\n            {\n                if (ProviderIndex < g_HashersCount)\n                {\n                    *OutObject = g_Hashers[ProviderIndex].Create();\n                    return S_OK;\n                }\n            }\n        }\n    }\n    else if (Iid == __uuidof(IInArchive))\n    {\n        if (Clsid.Data1 == SevenZipGuidData1 &&\n            Clsid.Data2 == SevenZipGuidData2 &&\n            Clsid.Data3 == SevenZipGuidData3Common)\n        {\n            std::uint64_t ProviderId =\n                *reinterpret_cast<const std::uint64_t*>(Clsid.Data4);\n            std::uint64_t ProviderIdBase = ProviderId & 0xFFFFFFFF00000000;\n            std::uint32_t ProviderIndex =\n                static_cast<std::uint32_t>(ProviderId);\n            if (NanaZip::Codecs::ArchiverProviderIdBase == ProviderIdBase)\n            {\n                if (ProviderIndex < g_ArchiversCount)\n                {\n                    *OutObject = g_Archivers[ProviderIndex].CreateIn();\n                    return S_OK;\n                }\n            }\n        }\n    }\n\n    return E_NOINTERFACE;\n}\n\nEXTERN_C HRESULT WINAPI GetNumberOfFormats(\n    _Out_ PUINT32 NumFormats)\n{\n    if (!NumFormats)\n    {\n        return E_INVALIDARG;\n    }\n\n    *NumFormats = g_ArchiversCount;\n    return S_OK;\n}\n\nEXTERN_C HRESULT WINAPI GetHandlerProperty2(\n    _In_ UINT32 Index,\n    _In_ PROPID PropId,\n    _Inout_ LPPROPVARIANT Value)\n{\n    if (!(Index < g_ArchiversCount))\n    {\n        return E_INVALIDARG;\n    }\n\n    if (!Value)\n    {\n        return E_INVALIDARG;\n    }\n\n    switch (PropId)\n    {\n    case SevenZipHandlerName:\n    {\n        Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n            CP_UTF8,\n            g_Archivers[Index].Name).c_str());\n        if (Value->bstrVal)\n        {\n            Value->vt = VT_BSTR;\n        }\n        break;\n    }\n    case SevenZipHandlerClassId:\n    {\n        GUID ClassId;\n        ClassId.Data1 = SevenZipGuidData1;\n        ClassId.Data2 = SevenZipGuidData2;\n        ClassId.Data3 = SevenZipGuidData3Common;\n        *reinterpret_cast<PUINT64>(ClassId.Data4) =\n            NanaZip::Codecs::ArchiverProviderIdBase | Index;\n        Value->bstrVal = ::SysAllocStringByteLen(\n            reinterpret_cast<LPCSTR>(&ClassId),\n            sizeof(ClassId));\n        if (Value->bstrVal)\n        {\n            Value->vt = VT_BSTR;\n        }\n        break;\n    }\n    case SevenZipHandlerExtension:\n    {\n        if (g_Archivers[Index].Extension)\n        {\n            Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                CP_UTF8,\n                g_Archivers[Index].Extension).c_str());\n            if (Value->bstrVal)\n            {\n                Value->vt = VT_BSTR;\n            }\n        }\n        break;\n    }\n    case SevenZipHandlerAddExtension:\n    {\n        if (g_Archivers[Index].AddExtension)\n        {\n            Value->bstrVal = ::SysAllocString(Mile::ToWideString(\n                CP_UTF8,\n                g_Archivers[Index].AddExtension).c_str());\n            if (Value->bstrVal)\n            {\n                Value->vt = VT_BSTR;\n            }\n        }\n        break;\n    }\n    case SevenZipHandlerUpdate:\n    {\n        Value->boolVal =\n            g_Archivers[Index].Update\n            ? VARIANT_TRUE\n            : VARIANT_FALSE;\n        Value->vt = VT_BOOL;\n        break;\n    }\n    case SevenZipHandlerKeepName:\n    {\n        Value->boolVal =\n            g_Archivers[Index].Flags & SevenZipHandlerFlagKeepName\n            ? VARIANT_TRUE\n            : VARIANT_FALSE;\n        Value->vt = VT_BOOL;\n        break;\n    }\n    case SevenZipHandlerSignature:\n    {\n        if (g_Archivers[Index].SignatureSize &&\n            !(g_Archivers[Index].Flags & SevenZipHandlerFlagMultiSignature))\n        {\n            Value->bstrVal = ::SysAllocStringByteLen(\n                reinterpret_cast<LPCSTR>(g_Archivers[Index].Signature),\n                g_Archivers[Index].SignatureSize);\n            if (Value->bstrVal)\n            {\n                Value->vt = VT_BSTR;\n            }\n        }\n        break;\n    }\n    case SevenZipHandlerMultiSignature:\n    {\n        if (g_Archivers[Index].SignatureSize &&\n            g_Archivers[Index].Flags & SevenZipHandlerFlagMultiSignature)\n        {\n            Value->bstrVal = ::SysAllocStringByteLen(\n                reinterpret_cast<LPCSTR>(g_Archivers[Index].Signature),\n                g_Archivers[Index].SignatureSize);\n            if (Value->bstrVal)\n            {\n                Value->vt = VT_BSTR;\n            }\n        }\n        break;\n    }\n    case SevenZipHandlerSignatureOffset:\n    {\n        Value->ulVal = g_Archivers[Index].SignatureOffset;\n        Value->vt = VT_UI4;\n        break;\n    }\n    case SevenZipHandlerAlternateStream:\n    {\n        Value->boolVal =\n            g_Archivers[Index].Flags & SevenZipHandlerFlagAlternateStreams\n            ? VARIANT_TRUE\n            : VARIANT_FALSE;\n        Value->vt = VT_BOOL;\n        break;\n    }\n    case SevenZipHandlerNtSecurity:\n    {\n        Value->boolVal =\n            g_Archivers[Index].Flags & SevenZipHandlerFlagNtSecurity\n            ? VARIANT_TRUE\n            : VARIANT_FALSE;\n        Value->vt = VT_BOOL;\n        break;\n    }\n    case SevenZipHandlerFlags:\n    {\n        Value->ulVal = g_Archivers[Index].Flags;\n        Value->vt = VT_UI4;\n        break;\n    }\n    case SevenZipHandlerTimeFlags:\n    {\n        Value->ulVal = g_Archivers[Index].TimeFlags;\n        Value->vt = VT_UI4;\n        break;\n    }\n    default:\n        return E_INVALIDARG;\n    }\n\n    return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.def",
    "content": "﻿LIBRARY\n\nEXPORTS\n\nGetHashers\n\nCreateObject\nGetNumberOfFormats\nGetHandlerProperty2\n\nNanaZipCodecsBrotliRead\nNanaZipCodecsBrotliWrite\nNanaZipCodecsLizardRead\nNanaZipCodecsLizardWrite\nNanaZipCodecsLz4Read\nNanaZipCodecsLz4Write\nNanaZipCodecsLz5Read\nNanaZipCodecsLz5Write\n\nNanaZipCodecsBrotliDecode\nNanaZipCodecsLizardDecode\nNanaZipCodecsLz4Decode\nNanaZipCodecsLz5Decode\n\nBrotliDecoderDestroyInstance\nBrotliDecoderDecompressStream\nBrotliDecoderCreateInstance\n\nLZ4_decompress_safe\n\nBROTLIMT_compressCCtx\nBROTLIMT_createCCtx\nBROTLIMT_freeCCtx\nBROTLIMT_isError\nLIZARDMT_compressCCtx\nLIZARDMT_createCCtx\nLIZARDMT_freeCCtx\nLIZARDMT_isError\nLZ4MT_compressCCtx\nLZ4MT_createCCtx\nLZ4MT_freeCCtx\nLZ4MT_isError\nLZ5MT_compressCCtx\nLZ5MT_createCCtx\nLZ5MT_freeCCtx\nLZ5MT_isError\n\nFL2_cancelCStream\nFL2_CCtx_getParameter\nFL2_CCtx_setParameter\nFL2_createCStreamMt\nFL2_endStream\nFL2_freeCCtx\nFL2_getCStreamProgress\nFL2_getDictionaryBuffer\nFL2_getErrorCode\nFL2_getNextCompressedBuffer\nFL2_initCStream\nFL2_isError\nFL2_isTimedOut\nFL2_setCStreamTimeout\nFL2_updateDictionary\nFL2_waitCStream\n\nZSTD_isError\nZSTD_maxCLevel\nZSTD_createCCtx\nZSTD_createDCtx\nZSTD_freeCCtx\nZSTD_freeDCtx\nZSTD_CCtx_setParameter\nZSTD_DCtx_reset\nZSTD_DCtx_setParameter\nZSTD_compressStream2\nZSTD_decompressStream\nZSTD_CStreamInSize\nZSTD_CStreamOutSize\nZSTD_DStreamInSize\nZSTD_DStreamOutSize\nZSTD_getErrorCode\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       NanaZip.Codecs.h\n * PURPOSE:    Definition for NanaZip.Codecs\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_CODECS\n#define NANAZIP_CODECS\n\n#include <Windows.h>\n\n#include <NanaZip.Specification.SevenZip.h>\n\n#include <Mile.Helpers.CppBase.h>\n\n/**\n * Definition of NanaZip interface constants\n *\n * I had mentioned one of the reasons that I call this project NanaZip because\n * Nana is the romaji of なな which means seven in Japanese. But I had not\n * mentioned the way I confirm that: I had recalled one of the Japanese VTubers\n * called Kagura Nana when I waiting my elder sister for dinner at Taiyanggong\n * subway station, Beijing. For playing more puns, NanaZip uses the K7 prefix in\n * some definitions. (K -> Kagura, 7 -> Nana)\n */\n\nnamespace NanaZip::Codecs\n{\n    /**\n     * @brief The ID base value of NanaZip Hash Providers.\n     * @remark 0x4823374B is little-endian representation of K7#H (H -> Hash)\n     */\n    const UINT64 HashProviderIdBase = 0x4823374B00000000;\n\n    /**\n     * @brief The ID base value of NanaZip Decoder Providers.\n     * @remark 0x4423374B is little-endian representation of K7#D (D -> Decoder)\n     */\n    const UINT64 DecoderProviderIdBase = 0x4423374B00000000;\n\n    /**\n     * @brief The ID base value of NanaZip Encoder Providers.\n     * @remark 0x4523374B is little-endian representation of K7#E (E -> Encoder)\n     */\n    const UINT64 EncoderProviderIdBase = 0x4523374B00000000;\n\n    /**\n     * @brief The ID base value of NanaZip Archiver Providers.\n     * @remark 0x4523374B is little-endian representation of K7#A (A -> Archiver)\n     */\n    const UINT64 ArchiverProviderIdBase = 0x4123374B00000000;\n}\n\nnamespace NanaZip::Codecs::Hash\n{\n    IHasher* CreateMd2();\n    IHasher* CreateMd4();\n    IHasher* CreateMd5();\n    IHasher* CreateSha1();\n    IHasher* CreateSha256();\n    IHasher* CreateSha384();\n    IHasher* CreateSha512();\n    IHasher* CreateBlake3();\n    IHasher* CreateSm3();\n    IHasher* CreateAich();\n    IHasher* CreateBlake2b();\n    IHasher* CreateEd2k();\n    IHasher* CreateEdonR224();\n    IHasher* CreateEdonR256();\n    IHasher* CreateEdonR384();\n    IHasher* CreateEdonR512();\n    IHasher* CreateGost94();\n    IHasher* CreateGost94CryptoPro();\n    IHasher* CreateGost12256();\n    IHasher* CreateGost12512();\n    IHasher* CreateHas160();\n    IHasher* CreateRipemd160();\n    IHasher* CreateSha224();\n    IHasher* CreateSha3224();\n    IHasher* CreateSha3256();\n    IHasher* CreateSha3384();\n    IHasher* CreateSha3512();\n    IHasher* CreateSnefru128();\n    IHasher* CreateSnefru256();\n    IHasher* CreateTiger();\n    IHasher* CreateTiger2();\n    IHasher* CreateTorrent();\n    IHasher* CreateTth();\n    IHasher* CreateWhirlpool();\n    IHasher* CreateXxh32();\n    IHasher* CreateXxh64();\n    IHasher* CreateXxh364();\n    IHasher* CreateXxh3128();\n}\n\nnamespace NanaZip::Codecs::Decoder\n{\n\n}\n\nnamespace NanaZip::Codecs::Encoder\n{\n\n}\n\nnamespace NanaZip::Codecs::Archive\n{\n    IInArchive* CreateUfs();\n    IInArchive* CreateDotNetSingleFile();\n    IInArchive* CreateElectronAsar();\n    IInArchive* CreateRomfs();\n    IInArchive* CreateZealfs();\n    IInArchive* CreateWebAssembly();\n    IInArchive* CreateLittlefs();\n}\n\n#endif // !NANAZIP_CODECS\n"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaZip\n  FILE:       NanaZip.Codecs.props\n  PURPOSE:    MSBuild Properties for NanaZip.Codecs\n\n  LICENSE:    The MIT License\n\n  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n-->\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"..\\NanaZip.Specification\\NanaZip.Specification.props\" />\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory)BLAKE3\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Brotli\\include\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)FastLZMA2\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)GmSSL\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Heimdal\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Lizard\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)LZ4\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)LZ5\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)RHash\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)xxHash\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Zstandard\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)ZSTDMT\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <Link>\n      <PreprocessorDefinitions>ZSTD_MULTITHREAD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalDependencies>$(OutDir)NanaZip.Codecs.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)NanaZip.Codecs.vcxproj\">\n      <Project>{89B81A5B-FF0D-4193-9CB1-738692775DD2}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{89B81A5B-FF0D-4193-9CB1-738692775DD2}</ProjectGuid>\n    <RootNamespace>NanaZip.Codecs</RootNamespace>\n    <MileProjectType>DynamicLibrary</MileProjectType>\n    <WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Codecs</MileProjectFileDescription>\n    <MileProjectInternalName>NanaZip.Codecs</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>NanaZip.Codecs.dll</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.ARM64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Condition=\"'$(Platform)' == 'x64'\" Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.props\" />\n  <Import Project=\"..\\K7Base\\K7Base.props\" />\n  <Import Project=\"..\\NanaZip.Specification\\NanaZip.Specification.props\" />\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory)BLAKE3\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Brotli\\include\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)FastLZMA2\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)GmSSL\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Heimdal\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Lizard\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)LZ4\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)LZ5\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)RHash\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)xxHash\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)Zstandard\\;$(IncludePath)</IncludePath>\n    <IncludePath>$(MSBuildThisFileDirectory)ZSTDMT\\;$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>NO_XXHASH;FL2_7ZIP_BUILD;ZSTD_LEGACY_SUPPORT;ZSTD_MULTITHREAD;NO_IMPORT_EXPORT;LFS_READONLY;LFS_MULTIVERSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <ModuleDefinitionFile>NanaZip.Codecs.def</ModuleDefinitionFile>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Codecs.def\" />\n    <None Include=\"NanaZip.Codecs.props\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"Brotli\\dec\\prefix.c\" />\n    <ClCompile Include=\"Brotli\\dec\\dec_static_init.c\" />\n    <ClCompile Include=\"Brotli\\enc\\static_dict_lut.c\" />\n    <ClCompile Include=\"Brotli\\enc\\enc_static_init.c\" />\n    <ClCompile Include=\"LittleFS\\lfs.c\">\n      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <DisableSpecificWarnings>4146;4244;4267;4456;4701;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"LittleFS\\lfs_util.c\">\n      <DisableSpecificWarnings>4146;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\entropy\\lizard_entropy_common.c\" />\n    <ClCompile Include=\"Lizard\\entropy\\lizard_fse_compress.c\" />\n    <ClCompile Include=\"Lizard\\entropy\\lizard_fse_decompress.c\" />\n    <ClCompile Include=\"Lizard\\entropy\\lizard_huf_compress.c\" />\n    <ClCompile Include=\"Lizard\\entropy\\lizard_huf_decompress.c\" />\n    <ClCompile Include=\"Mile.Helpers.Portable.Base.Unstaged.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.DotNetSingleFile.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.ElectronAsar.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Littlefs.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Romfs.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Ufs.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.WebAssembly.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Zealfs.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Aich.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.BCryptProvider.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Blake2b.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Blake3.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Ed2k.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR224.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR384.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR512.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost12256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost12512.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost94.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost94CryptoPro.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Has160.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Ripemd160.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha224.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3224.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3384.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3512.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sm3.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Snefru128.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Snefru256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Tiger.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Tiger2.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Torrent.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Tth.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Whirlpool.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh3128.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh32.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh364.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh64.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.Brotli.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.Common.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.Lizard.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ4.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ5.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.SevenZipWrapper.cpp\" />\n    <ClCompile Include=\"Zstandard\\common\\debug.c\" />\n    <ClCompile Include=\"Zstandard\\common\\entropy_common.c\" />\n    <ClCompile Include=\"Zstandard\\common\\error_private.c\" />\n    <ClCompile Include=\"Zstandard\\common\\fse_decompress.c\" />\n    <ClCompile Include=\"Zstandard\\common\\pool.c\" />\n    <ClCompile Include=\"Zstandard\\common\\threading.c\" />\n    <ClCompile Include=\"Zstandard\\common\\zstd_common.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\fse_compress.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\hist.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\huf_compress.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstdmt_compress.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress_literals.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress_sequences.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress_superblock.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_double_fast.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_fast.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_lazy.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_ldm.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_opt.c\" />\n    <ClCompile Include=\"FastLZMA2\\dict_buffer.c\" />\n    <ClCompile Include=\"FastLZMA2\\fl2_common.c\" />\n    <ClCompile Include=\"FastLZMA2\\fl2_compress.c\" />\n    <ClCompile Include=\"FastLZMA2\\fl2_pool.c\" />\n    <ClCompile Include=\"FastLZMA2\\fl2_threading.c\" />\n    <ClCompile Include=\"FastLZMA2\\lzma2_enc.c\" />\n    <ClCompile Include=\"FastLZMA2\\radix_bitpack.c\" />\n    <ClCompile Include=\"FastLZMA2\\radix_mf.c\" />\n    <ClCompile Include=\"FastLZMA2\\radix_struct.c\" />\n    <ClCompile Include=\"FastLZMA2\\range_enc.c\" />\n    <ClCompile Include=\"FastLZMA2\\util.c\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_preSplit.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\huf_decompress.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_ddict.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress.c\" />\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress_block.c\" />\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v01.c\" />\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v02.c\" />\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v03.c\" />\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v04.c\" />\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v05.c\" />\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v06.c\" />\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v07.c\" />\n    <ClCompile Include=\"ZSTDMT\\brotli-mt_common.c\" />\n    <ClCompile Include=\"ZSTDMT\\brotli-mt_compress.c\" />\n    <ClCompile Include=\"ZSTDMT\\brotli-mt_decompress.c\" />\n    <ClCompile Include=\"ZSTDMT\\lizard-mt_common.c\" />\n    <ClCompile Include=\"ZSTDMT\\lizard-mt_compress.c\" />\n    <ClCompile Include=\"ZSTDMT\\lizard-mt_decompress.c\" />\n    <ClCompile Include=\"ZSTDMT\\lz4-mt_common.c\" />\n    <ClCompile Include=\"ZSTDMT\\lz4-mt_compress.c\" />\n    <ClCompile Include=\"ZSTDMT\\lz4-mt_decompress.c\" />\n    <ClCompile Include=\"ZSTDMT\\lz5-mt_common.c\" />\n    <ClCompile Include=\"ZSTDMT\\lz5-mt_compress.c\" />\n    <ClCompile Include=\"ZSTDMT\\lz5-mt_decompress.c\" />\n    <ClCompile Include=\"ZSTDMT\\zstd-mt_threading.c\" />\n    <ClCompile Include=\"Lizard\\lizard_compress.c\" />\n    <ClCompile Include=\"Lizard\\lizard_decompress.c\" />\n    <ClCompile Include=\"Lizard\\lizard_frame.c\" />\n    <ClCompile Include=\"LZ5\\lz5.c\" />\n    <ClCompile Include=\"LZ5\\lz5frame.c\" />\n    <ClCompile Include=\"LZ5\\lz5hc.c\" />\n    <ClCompile Include=\"LZ4\\lz4.c\" />\n    <ClCompile Include=\"LZ4\\lz4frame.c\" />\n    <ClCompile Include=\"LZ4\\lz4hc.c\" />\n    <ClCompile Include=\"xxHash\\xxhash.c\">\n      <DisableSpecificWarnings>4113;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\common\\constants.c\" />\n    <ClCompile Include=\"Brotli\\common\\context.c\" />\n    <ClCompile Include=\"Brotli\\common\\dictionary.c\" />\n    <ClCompile Include=\"Brotli\\common\\platform.c\" />\n    <ClCompile Include=\"Brotli\\common\\shared_dictionary.c\" />\n    <ClCompile Include=\"Brotli\\common\\transform.c\" />\n    <ClCompile Include=\"Brotli\\dec\\bit_reader.c\">\n      <DisableSpecificWarnings>4100;4127;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\decode.c\">\n      <DisableSpecificWarnings>4100;4127;4334;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\huffman.c\" />\n    <ClCompile Include=\"Brotli\\dec\\state.c\">\n      <DisableSpecificWarnings>4100;4127;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\backward_references.c\">\n      <DisableSpecificWarnings>4127;4189;4334;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\backward_references_hq.c\">\n      <DisableSpecificWarnings>4127;4189;4334;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\bit_cost.c\" />\n    <ClCompile Include=\"Brotli\\enc\\block_splitter.c\">\n      <DisableSpecificWarnings>4127;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\brotli_bit_stream.c\">\n      <DisableSpecificWarnings>4127;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\cluster.c\">\n      <DisableSpecificWarnings>4127;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\command.c\" />\n    <ClCompile Include=\"Brotli\\enc\\compound_dictionary.c\">\n      <DisableSpecificWarnings>4127;4334;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\compress_fragment.c\" />\n    <ClCompile Include=\"Brotli\\enc\\compress_fragment_two_pass.c\" />\n    <ClCompile Include=\"Brotli\\enc\\dictionary_hash.c\" />\n    <ClCompile Include=\"Brotli\\enc\\encode.c\">\n      <DisableSpecificWarnings>4127;4189;4334;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\encoder_dict.c\">\n      <DisableSpecificWarnings>4127;4189;4334;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\entropy_encode.c\" />\n    <ClCompile Include=\"Brotli\\enc\\fast_log.c\" />\n    <ClCompile Include=\"Brotli\\enc\\histogram.c\" />\n    <ClCompile Include=\"Brotli\\enc\\literal_cost.c\" />\n    <ClCompile Include=\"Brotli\\enc\\memory.c\" />\n    <ClCompile Include=\"Brotli\\enc\\metablock.c\">\n      <DisableSpecificWarnings>4127;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\static_dict.c\" />\n    <ClCompile Include=\"Brotli\\enc\\utf8_util.c\" />\n    <ClCompile Include=\"RHash\\aich.c\" />\n    <ClCompile Include=\"RHash\\blake2b.c\" />\n    <ClCompile Include=\"RHash\\byte_order.c\">\n      <DisableSpecificWarnings>4146;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\edonr.c\" />\n    <ClCompile Include=\"RHash\\gost12.c\">\n      <DisableSpecificWarnings>4267;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\gost94.c\" />\n    <ClCompile Include=\"RHash\\has160.c\" />\n    <ClCompile Include=\"RHash\\hex.c\" />\n    <ClCompile Include=\"RHash\\rhash_sha256.c\" />\n    <ClCompile Include=\"RHash\\rhash_util.c\" />\n    <ClCompile Include=\"RHash\\ripemd-160.c\" />\n    <ClCompile Include=\"RHash\\sha3.c\" />\n    <ClCompile Include=\"RHash\\snefru.c\">\n      <DisableSpecificWarnings>4127;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\tiger.c\" />\n    <ClCompile Include=\"RHash\\tiger_sbox.c\" />\n    <ClCompile Include=\"RHash\\torrent.c\">\n      <DisableSpecificWarnings>4146;4200;</DisableSpecificWarnings>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\tth.c\" />\n    <ClCompile Include=\"RHash\\whirlpool.c\" />\n    <ClCompile Include=\"RHash\\whirlpool_sbox.c\" />\n    <ClCompile Include=\"GmSSL\\sm3.c\" />\n    <ClCompile Include=\"BLAKE3\\blake3.c\">\n      <DisableSpecificWarnings>4244;4245;</DisableSpecificWarnings>\n    </ClCompile>\n    <None Include=\"BLAKE3\\blake3_avx2_x86-64_windows_msvc.asm\" />\n    <None Include=\"BLAKE3\\blake3_avx512_x86-64_windows_msvc.asm\" />\n    <ClCompile Include=\"BLAKE3\\blake3_dispatch.c\">\n      <DisableSpecificWarnings>4189;4702;</DisableSpecificWarnings>\n    </ClCompile>\n    <None Include=\"BLAKE3\\blake3_neon.c\" />\n    <ClCompile Include=\"BLAKE3\\blake3_portable.c\" />\n    <None Include=\"BLAKE3\\blake3_sse2_x86-64_windows_msvc.asm\" />\n    <None Include=\"BLAKE3\\blake3_sse41_x86-64_windows_msvc.asm\" />\n    <ClCompile Include=\"NanaZip.Codecs.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"Brotli\\common\\dictionary_inc.h\" />\n    <ClInclude Include=\"Brotli\\common\\static_init.h\" />\n    <ClInclude Include=\"Brotli\\dec\\prefix_inc.h\" />\n    <ClInclude Include=\"Brotli\\dec\\static_init.h\" />\n    <ClInclude Include=\"Brotli\\enc\\dictionary_hash_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_base.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match64_simd_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match_simd_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\matching_tag_mask.h\" />\n    <ClInclude Include=\"Brotli\\enc\\static_dict_lut_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\static_init.h\" />\n    <ClInclude Include=\"FreeBSD\\dinode.h\" />\n    <ClInclude Include=\"FreeBSD\\dir.h\" />\n    <ClInclude Include=\"FreeBSD\\fs.h\" />\n    <ClInclude Include=\"LittleFS\\lfs.h\" />\n    <ClInclude Include=\"LittleFS\\lfs_util.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\bitstream.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\compiler.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\debug.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\error_private.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\error_public.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\fse.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\hist.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\huf.h\" />\n    <ClInclude Include=\"Lizard\\entropy\\mem.h\" />\n    <ClInclude Include=\"Mile.Helpers.Portable.Base.Unstaged.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.Brotli.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.Common.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.Lizard.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ4.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ5.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.SevenZipWrapper.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.Specification.Fat.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.Specification.Zealfs.h\" />\n    <ClInclude Include=\"Zstandard\\common\\allocations.h\" />\n    <ClInclude Include=\"Zstandard\\common\\bits.h\" />\n    <ClInclude Include=\"Zstandard\\common\\bitstream.h\" />\n    <ClInclude Include=\"Zstandard\\common\\compiler.h\" />\n    <ClInclude Include=\"Zstandard\\common\\cpu.h\" />\n    <ClInclude Include=\"Zstandard\\common\\debug.h\" />\n    <ClInclude Include=\"Zstandard\\common\\error_private.h\" />\n    <ClInclude Include=\"Zstandard\\common\\fse.h\" />\n    <ClInclude Include=\"Zstandard\\common\\huf.h\" />\n    <ClInclude Include=\"Zstandard\\common\\mem.h\" />\n    <ClInclude Include=\"Zstandard\\common\\pool.h\" />\n    <ClInclude Include=\"Zstandard\\common\\portability_macros.h\" />\n    <ClInclude Include=\"Zstandard\\common\\threading.h\" />\n    <ClInclude Include=\"Zstandard\\common\\zstd_deps.h\" />\n    <ClInclude Include=\"Zstandard\\common\\zstd_internal.h\" />\n    <ClInclude Include=\"Zstandard\\common\\zstd_trace.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\clevels.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\hist.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstdmt_compress.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_internal.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_literals.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_sequences.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_superblock.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_cwksp.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_double_fast.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_fast.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_lazy.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_ldm.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_ldm_geartab.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_opt.h\" />\n    <ClInclude Include=\"Zstandard\\compress\\zstd_preSplit.h\" />\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_ddict.h\" />\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_block.h\" />\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_internal.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_legacy.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v01.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v02.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v03.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v04.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v05.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v06.h\" />\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v07.h\" />\n    <ClInclude Include=\"Zstandard\\zstd.h\" />\n    <ClInclude Include=\"Zstandard\\zstd_errors.h\" />\n    <ClInclude Include=\"FastLZMA2\\atomic.h\" />\n    <ClInclude Include=\"FastLZMA2\\compiler.h\" />\n    <ClInclude Include=\"FastLZMA2\\count.h\" />\n    <ClInclude Include=\"FastLZMA2\\data_block.h\" />\n    <ClInclude Include=\"FastLZMA2\\dict_buffer.h\" />\n    <ClInclude Include=\"FastLZMA2\\fast-lzma2.h\" />\n    <ClInclude Include=\"FastLZMA2\\fastpos_table.h\" />\n    <ClInclude Include=\"FastLZMA2\\fl2_compress_internal.h\" />\n    <ClInclude Include=\"FastLZMA2\\fl2_errors.h\" />\n    <ClInclude Include=\"FastLZMA2\\fl2_internal.h\" />\n    <ClInclude Include=\"FastLZMA2\\fl2_pool.h\" />\n    <ClInclude Include=\"FastLZMA2\\fl2_threading.h\" />\n    <ClInclude Include=\"FastLZMA2\\lzma2_enc.h\" />\n    <ClInclude Include=\"FastLZMA2\\mem.h\" />\n    <ClInclude Include=\"FastLZMA2\\platform.h\" />\n    <ClInclude Include=\"FastLZMA2\\radix_engine.h\" />\n    <ClInclude Include=\"FastLZMA2\\radix_get.h\" />\n    <ClInclude Include=\"FastLZMA2\\radix_internal.h\" />\n    <ClInclude Include=\"FastLZMA2\\radix_mf.h\" />\n    <ClInclude Include=\"FastLZMA2\\range_enc.h\" />\n    <ClInclude Include=\"FastLZMA2\\util.h\" />\n    <ClInclude Include=\"ZSTDMT\\brotli-mt.h\" />\n    <ClInclude Include=\"ZSTDMT\\list.h\" />\n    <ClInclude Include=\"ZSTDMT\\lizard-mt.h\" />\n    <ClInclude Include=\"ZSTDMT\\lz4-mt.h\" />\n    <ClInclude Include=\"ZSTDMT\\lz5-mt.h\" />\n    <ClInclude Include=\"ZSTDMT\\memmt.h\" />\n    <ClInclude Include=\"ZSTDMT\\threading.h\" />\n    <ClInclude Include=\"Lizard\\lizard_common.h\" />\n    <ClInclude Include=\"Lizard\\lizard_compress.h\" />\n    <ClInclude Include=\"Lizard\\lizard_compress_liz.h\" />\n    <ClInclude Include=\"Lizard\\lizard_compress_lz4.h\" />\n    <ClInclude Include=\"Lizard\\lizard_decompress.h\" />\n    <ClInclude Include=\"Lizard\\lizard_decompress_liz.h\" />\n    <ClInclude Include=\"Lizard\\lizard_decompress_lz4.h\" />\n    <ClInclude Include=\"Lizard\\lizard_frame.h\" />\n    <ClInclude Include=\"Lizard\\lizard_frame_static.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_fast.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_fastbig.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_fastsmall.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_hashchain.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_lowestprice.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_nochain.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_optimal.h\" />\n    <ClInclude Include=\"Lizard\\lizard_parser_pricefast.h\" />\n    <ClInclude Include=\"LZ5\\lz5.h\" />\n    <ClInclude Include=\"LZ5\\lz5common.h\" />\n    <ClInclude Include=\"LZ5\\lz5frame.h\" />\n    <ClInclude Include=\"LZ5\\lz5frame_static.h\" />\n    <ClInclude Include=\"LZ5\\lz5hc.h\" />\n    <ClInclude Include=\"LZ5\\mem.h\" />\n    <ClInclude Include=\"LZ4\\lz4.h\" />\n    <ClInclude Include=\"LZ4\\lz4frame.h\" />\n    <ClInclude Include=\"LZ4\\lz4frame_static.h\" />\n    <ClInclude Include=\"LZ4\\lz4hc.h\" />\n    <ClInclude Include=\"xxHash\\xxhash.h\" />\n    <ClInclude Include=\"Brotli\\common\\constants.h\" />\n    <ClInclude Include=\"Brotli\\common\\context.h\" />\n    <ClInclude Include=\"Brotli\\common\\dictionary.h\" />\n    <ClInclude Include=\"Brotli\\common\\platform.h\" />\n    <ClInclude Include=\"Brotli\\common\\shared_dictionary_internal.h\" />\n    <ClInclude Include=\"Brotli\\common\\transform.h\" />\n    <ClInclude Include=\"Brotli\\common\\version.h\" />\n    <ClInclude Include=\"Brotli\\dec\\bit_reader.h\" />\n    <ClInclude Include=\"Brotli\\dec\\huffman.h\" />\n    <ClInclude Include=\"Brotli\\dec\\prefix.h\" />\n    <ClInclude Include=\"Brotli\\dec\\state.h\" />\n    <ClInclude Include=\"Brotli\\enc\\backward_references.h\" />\n    <ClInclude Include=\"Brotli\\enc\\backward_references_hq.h\" />\n    <ClInclude Include=\"Brotli\\enc\\backward_references_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\bit_cost.h\" />\n    <ClInclude Include=\"Brotli\\enc\\bit_cost_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\block_encoder_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\block_splitter.h\" />\n    <ClInclude Include=\"Brotli\\enc\\block_splitter_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\brotli_bit_stream.h\" />\n    <ClInclude Include=\"Brotli\\enc\\cluster.h\" />\n    <ClInclude Include=\"Brotli\\enc\\cluster_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\command.h\" />\n    <ClInclude Include=\"Brotli\\enc\\compound_dictionary.h\" />\n    <ClInclude Include=\"Brotli\\enc\\compress_fragment.h\" />\n    <ClInclude Include=\"Brotli\\enc\\compress_fragment_two_pass.h\" />\n    <ClInclude Include=\"Brotli\\enc\\dictionary_hash.h\" />\n    <ClInclude Include=\"Brotli\\enc\\encoder_dict.h\" />\n    <ClInclude Include=\"Brotli\\enc\\entropy_encode.h\" />\n    <ClInclude Include=\"Brotli\\enc\\entropy_encode_static.h\" />\n    <ClInclude Include=\"Brotli\\enc\\fast_log.h\" />\n    <ClInclude Include=\"Brotli\\enc\\find_match_length.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_composite_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_forgetful_chain_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match64_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match_quickly_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_rolling_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\hash_to_binary_tree_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\histogram.h\" />\n    <ClInclude Include=\"Brotli\\enc\\histogram_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\literal_cost.h\" />\n    <ClInclude Include=\"Brotli\\enc\\memory.h\" />\n    <ClInclude Include=\"Brotli\\enc\\metablock.h\" />\n    <ClInclude Include=\"Brotli\\enc\\metablock_inc.h\" />\n    <ClInclude Include=\"Brotli\\enc\\params.h\" />\n    <ClInclude Include=\"Brotli\\enc\\prefix.h\" />\n    <ClInclude Include=\"Brotli\\enc\\quality.h\" />\n    <ClInclude Include=\"Brotli\\enc\\ringbuffer.h\" />\n    <ClInclude Include=\"Brotli\\enc\\state.h\" />\n    <ClInclude Include=\"Brotli\\enc\\static_dict.h\" />\n    <ClInclude Include=\"Brotli\\enc\\static_dict_lut.h\" />\n    <ClInclude Include=\"Brotli\\enc\\utf8_util.h\" />\n    <ClInclude Include=\"Brotli\\enc\\write_bits.h\" />\n    <ClInclude Include=\"Brotli\\include\\brotli\\decode.h\" />\n    <ClInclude Include=\"Brotli\\include\\brotli\\encode.h\" />\n    <ClInclude Include=\"Brotli\\include\\brotli\\port.h\" />\n    <ClInclude Include=\"Brotli\\include\\brotli\\shared_dictionary.h\" />\n    <ClInclude Include=\"Brotli\\include\\brotli\\types.h\" />\n    <ClInclude Include=\"RHash\\aich.h\" />\n    <ClInclude Include=\"RHash\\blake2b.h\" />\n    <ClInclude Include=\"RHash\\byte_order.h\" />\n    <ClInclude Include=\"RHash\\edonr.h\" />\n    <ClInclude Include=\"RHash\\gost12.h\" />\n    <ClInclude Include=\"RHash\\gost94.h\" />\n    <ClInclude Include=\"RHash\\has160.h\" />\n    <ClInclude Include=\"RHash\\hex.h\" />\n    <ClInclude Include=\"RHash\\ripemd-160.h\" />\n    <ClInclude Include=\"RHash\\sha1.h\" />\n    <ClInclude Include=\"RHash\\sha256.h\" />\n    <ClInclude Include=\"RHash\\sha3.h\" />\n    <ClInclude Include=\"RHash\\snefru.h\" />\n    <ClInclude Include=\"RHash\\tiger.h\" />\n    <ClInclude Include=\"RHash\\torrent.h\" />\n    <ClInclude Include=\"RHash\\tth.h\" />\n    <ClInclude Include=\"RHash\\ustd.h\" />\n    <ClInclude Include=\"RHash\\util.h\" />\n    <ClInclude Include=\"RHash\\whirlpool.h\" />\n    <ClInclude Include=\"GmSSL\\endian.h\" />\n    <ClInclude Include=\"GmSSL\\sm3.h\" />\n    <ClInclude Include=\"BLAKE3\\blake3.h\" />\n    <ClInclude Include=\"BLAKE3\\blake3_impl.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Windows.Helpers\">\n      <Version>1.0.1171</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Json\">\n      <Version>1.0.1057</Version>\n    </PackageReference>\n  </ItemGroup>\n  <Target Name=\"NanaZipCodecsBlake3HardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"BLAKE3\\blake3_avx2_x86-64_windows_msvc.asm\" />\n      <MASM Include=\"BLAKE3\\blake3_avx512_x86-64_windows_msvc.asm\" />\n      <MASM Include=\"BLAKE3\\blake3_sse2_x86-64_windows_msvc.asm\" />\n      <MASM Include=\"BLAKE3\\blake3_sse41_x86-64_windows_msvc.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCodecsBlake3HardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' == 'ARM64'\">\n      <ClCompile Include=\"BLAKE3\\blake3_neon.c\" />\n    </ItemGroup>\n  </Target>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n  <Import Condition=\"'$(Platform)' == 'x64'\" Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.targets\" />\n</Project>"
  },
  {
    "path": "NanaZip.Codecs/NanaZip.Codecs.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <ClCompile Include=\"NanaZip.Codecs.cpp\" />\n    <ClCompile Include=\"BLAKE3\\blake3.c\">\n      <Filter>BLAKE3</Filter>\n    </ClCompile>\n    <None Include=\"BLAKE3\\blake3_avx2_x86-64_windows_msvc.asm\">\n      <Filter>BLAKE3</Filter>\n    </None>\n    <None Include=\"BLAKE3\\blake3_avx512_x86-64_windows_msvc.asm\">\n      <Filter>BLAKE3</Filter>\n    </None>\n    <ClCompile Include=\"BLAKE3\\blake3_dispatch.c\">\n      <Filter>BLAKE3</Filter>\n    </ClCompile>\n    <None Include=\"BLAKE3\\blake3_neon.c\">\n      <Filter>BLAKE3</Filter>\n    </None>\n    <ClCompile Include=\"BLAKE3\\blake3_portable.c\">\n      <Filter>BLAKE3</Filter>\n    </ClCompile>\n    <None Include=\"BLAKE3\\blake3_sse2_x86-64_windows_msvc.asm\">\n      <Filter>BLAKE3</Filter>\n    </None>\n    <None Include=\"BLAKE3\\blake3_sse41_x86-64_windows_msvc.asm\">\n      <Filter>BLAKE3</Filter>\n    </None>\n    <ClCompile Include=\"GmSSL\\sm3.c\">\n      <Filter>GmSSL</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\aich.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\blake2b.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\byte_order.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\edonr.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\gost12.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\gost94.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\has160.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\hex.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\ripemd-160.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\rhash_sha256.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\sha3.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\snefru.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\tiger.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\tiger_sbox.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\torrent.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\tth.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\rhash_util.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\whirlpool.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"RHash\\whirlpool_sbox.c\">\n      <Filter>RHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\common\\constants.c\">\n      <Filter>Brotli\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\common\\context.c\">\n      <Filter>Brotli\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\common\\dictionary.c\">\n      <Filter>Brotli\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\common\\platform.c\">\n      <Filter>Brotli\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\common\\shared_dictionary.c\">\n      <Filter>Brotli\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\common\\transform.c\">\n      <Filter>Brotli\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\bit_reader.c\">\n      <Filter>Brotli\\dec</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\decode.c\">\n      <Filter>Brotli\\dec</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\huffman.c\">\n      <Filter>Brotli\\dec</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\state.c\">\n      <Filter>Brotli\\dec</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\backward_references.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\backward_references_hq.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\bit_cost.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\block_splitter.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\brotli_bit_stream.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\cluster.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\command.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\compound_dictionary.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\compress_fragment.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\compress_fragment_two_pass.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\dictionary_hash.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\encode.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\encoder_dict.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\entropy_encode.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\fast_log.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\histogram.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\literal_cost.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\memory.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\metablock.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\static_dict.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\utf8_util.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"xxHash\\xxhash.c\">\n      <Filter>xxHash</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZ4\\lz4.c\">\n      <Filter>LZ4</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZ4\\lz4frame.c\">\n      <Filter>LZ4</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZ4\\lz4hc.c\">\n      <Filter>LZ4</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZ5\\lz5.c\">\n      <Filter>LZ5</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZ5\\lz5frame.c\">\n      <Filter>LZ5</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LZ5\\lz5hc.c\">\n      <Filter>LZ5</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\lizard_compress.c\">\n      <Filter>Lizard</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\lizard_decompress.c\">\n      <Filter>Lizard</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\lizard_frame.c\">\n      <Filter>Lizard</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\brotli-mt_common.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\brotli-mt_compress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\brotli-mt_decompress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lizard-mt_common.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lizard-mt_compress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lizard-mt_decompress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lz4-mt_common.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lz4-mt_compress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lz4-mt_decompress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lz5-mt_common.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lz5-mt_compress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\lz5-mt_decompress.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"ZSTDMT\\zstd-mt_threading.c\">\n      <Filter>ZSTDMT</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\dict_buffer.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\fl2_common.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\fl2_compress.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\fl2_pool.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\fl2_threading.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\lzma2_enc.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\radix_bitpack.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\radix_mf.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\radix_struct.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\range_enc.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"FastLZMA2\\util.c\">\n      <Filter>FastLZMA2</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\debug.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\entropy_common.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\error_private.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\fse_decompress.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\pool.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\threading.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\common\\zstd_common.c\">\n      <Filter>Zstandard\\common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\fse_compress.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\hist.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\huf_compress.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstdmt_compress.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress_literals.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress_sequences.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_compress_superblock.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_double_fast.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_fast.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_lazy.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_ldm.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\compress\\zstd_opt.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Blake3.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sm3.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Aich.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Blake2b.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Ed2k.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR224.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR384.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.EdonR512.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost94.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost94CryptoPro.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost12256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Gost12512.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Has160.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Ripemd160.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha224.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3224.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3384.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Sha3512.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Snefru128.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Snefru256.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Tiger.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Tiger2.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Torrent.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Tth.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Whirlpool.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh32.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh64.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh364.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.Xxh3128.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.Common.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.Brotli.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.Lizard.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ4.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ5.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.SevenZipWrapper.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Hash.BCryptProvider.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Ufs.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.DotNetSingleFile.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.ElectronAsar.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Romfs.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Zealfs.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.WebAssembly.cpp\" />\n    <ClCompile Include=\"NanaZip.Codecs.Archive.Littlefs.cpp\" />\n    <ClCompile Include=\"Zstandard\\compress\\zstd_preSplit.c\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_decompress_block.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\huf_decompress.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\decompress\\zstd_ddict.c\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v03.c\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v04.c\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v05.c\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v06.c\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v07.c\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v01.c\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Zstandard\\legacy\\zstd_v02.c\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\entropy\\lizard_huf_compress.c\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\entropy\\lizard_huf_decompress.c\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\entropy\\lizard_fse_compress.c\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\entropy\\lizard_fse_decompress.c\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Lizard\\entropy\\lizard_entropy_common.c\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Mile.Helpers.Portable.Base.Unstaged.cpp\">\n      <Filter>Mile.Portable.Helpers.Unstaged</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LittleFS\\lfs.c\">\n      <Filter>LittleFS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"LittleFS\\lfs_util.c\">\n      <Filter>LittleFS</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\prefix.c\">\n      <Filter>Brotli\\dec</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\dec\\dec_static_init.c\">\n      <Filter>Brotli\\dec</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\static_dict_lut.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Brotli\\enc\\enc_static_init.c\">\n      <Filter>Brotli\\enc</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Codecs.def\" />\n    <None Include=\"NanaZip.Codecs.props\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Filter Include=\"BLAKE3\">\n      <UniqueIdentifier>{8780e049-c08c-40bf-a1ef-6ac34ab857a4}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"GmSSL\">\n      <UniqueIdentifier>{650c97a1-a641-4c99-8209-76a265fbfc24}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"RHash\">\n      <UniqueIdentifier>{c13ab0bc-bcc5-44ec-8b4b-8f3ee60c2ec1}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Brotli\">\n      <UniqueIdentifier>{733d7abb-fff3-4dfd-a2fa-de0451280840}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Brotli\\common\">\n      <UniqueIdentifier>{69f0ece3-1d69-4527-ae66-d992b96c6146}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Brotli\\dec\">\n      <UniqueIdentifier>{82cb3ecc-338a-4805-9568-4b3cd99946c2}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Brotli\\enc\">\n      <UniqueIdentifier>{4299b44f-18e5-45ef-b87b-66dc2bd371ce}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Brotli\\include\">\n      <UniqueIdentifier>{988d17a2-5e4e-472a-9923-67a046c33253}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Brotli\\include\\brotli\">\n      <UniqueIdentifier>{fbcd39e0-c2a1-4146-92e5-4e217a1f49bd}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"xxHash\">\n      <UniqueIdentifier>{4a2fdc00-56e0-4024-b1e4-65edd9491b7a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"LZ4\">\n      <UniqueIdentifier>{a09b9f72-7fa1-4190-a850-c3ff3c812272}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"LZ5\">\n      <UniqueIdentifier>{50cd4f8e-720b-44a2-912e-8febdaa5c7c6}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Lizard\">\n      <UniqueIdentifier>{3bd67c07-e7a9-462e-bfa1-a18141e2e67c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"ZSTDMT\">\n      <UniqueIdentifier>{0f78d39c-0bbe-4715-9237-133b2a02b2fd}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"FastLZMA2\">\n      <UniqueIdentifier>{fd31c8de-7c34-43cb-abb3-ddc8bad2d7fd}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\">\n      <UniqueIdentifier>{8d863b60-943f-4fda-8869-fa161291bb01}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\\common\">\n      <UniqueIdentifier>{4b9b3550-9d14-47ac-8cd9-a96615b9ddda}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\\compress\">\n      <UniqueIdentifier>{a75fe35b-0362-43ad-b9f2-29e3b7c0466a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"FreeBSD\">\n      <UniqueIdentifier>{70c4b67c-1fa7-4430-a788-11ad86f1ac56}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\\decompress\">\n      <UniqueIdentifier>{50d76346-416e-4ceb-90d4-9a78fcd52386}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Zstandard\\legacy\">\n      <UniqueIdentifier>{b18e7303-5e49-475c-aefe-4b289407e2fe}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Lizard\\entropy\">\n      <UniqueIdentifier>{114a5a2f-28cd-4e17-9570-ecf119db33d9}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Mile.Portable.Helpers.Unstaged\">\n      <UniqueIdentifier>{2ede4493-6888-4402-aa9d-823628b6bd21}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"LittleFS\">\n      <UniqueIdentifier>{f72fbfc5-1b3e-43d1-9a15-d52e8b570b3f}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"BLAKE3\\blake3.h\">\n      <Filter>BLAKE3</Filter>\n    </ClInclude>\n    <ClInclude Include=\"BLAKE3\\blake3_impl.h\">\n      <Filter>BLAKE3</Filter>\n    </ClInclude>\n    <ClInclude Include=\"GmSSL\\endian.h\">\n      <Filter>GmSSL</Filter>\n    </ClInclude>\n    <ClInclude Include=\"GmSSL\\sm3.h\">\n      <Filter>GmSSL</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\aich.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\blake2b.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\byte_order.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\edonr.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\gost12.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\gost94.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\has160.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\hex.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\ripemd-160.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\sha1.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\sha256.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\sha3.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\snefru.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\tiger.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\torrent.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\tth.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\ustd.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\util.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"RHash\\whirlpool.h\">\n      <Filter>RHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\constants.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\context.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\dictionary.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\platform.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\shared_dictionary_internal.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\transform.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\version.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\dec\\bit_reader.h\">\n      <Filter>Brotli\\dec</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\dec\\huffman.h\">\n      <Filter>Brotli\\dec</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\dec\\prefix.h\">\n      <Filter>Brotli\\dec</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\dec\\state.h\">\n      <Filter>Brotli\\dec</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\backward_references.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\backward_references_hq.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\backward_references_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\bit_cost.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\bit_cost_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\block_encoder_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\block_splitter.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\block_splitter_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\brotli_bit_stream.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\cluster.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\cluster_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\command.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\compound_dictionary.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\compress_fragment.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\compress_fragment_two_pass.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\dictionary_hash.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\encoder_dict.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\entropy_encode.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\entropy_encode_static.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\fast_log.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\find_match_length.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_composite_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_forgetful_chain_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match64_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match_quickly_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_rolling_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_to_binary_tree_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\histogram.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\histogram_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\literal_cost.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\memory.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\metablock.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\metablock_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\params.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\prefix.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\quality.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\ringbuffer.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\state.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\static_dict.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\static_dict_lut.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\utf8_util.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\write_bits.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\include\\brotli\\decode.h\">\n      <Filter>Brotli\\include\\brotli</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\include\\brotli\\encode.h\">\n      <Filter>Brotli\\include\\brotli</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\include\\brotli\\port.h\">\n      <Filter>Brotli\\include\\brotli</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\include\\brotli\\shared_dictionary.h\">\n      <Filter>Brotli\\include\\brotli</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\include\\brotli\\types.h\">\n      <Filter>Brotli\\include\\brotli</Filter>\n    </ClInclude>\n    <ClInclude Include=\"xxHash\\xxhash.h\">\n      <Filter>xxHash</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ4\\lz4.h\">\n      <Filter>LZ4</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ4\\lz4frame.h\">\n      <Filter>LZ4</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ4\\lz4frame_static.h\">\n      <Filter>LZ4</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ4\\lz4hc.h\">\n      <Filter>LZ4</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ5\\lz5.h\">\n      <Filter>LZ5</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ5\\lz5common.h\">\n      <Filter>LZ5</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ5\\lz5frame.h\">\n      <Filter>LZ5</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ5\\lz5frame_static.h\">\n      <Filter>LZ5</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ5\\lz5hc.h\">\n      <Filter>LZ5</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LZ5\\mem.h\">\n      <Filter>LZ5</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_common.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_compress.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_compress_liz.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_compress_lz4.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_decompress.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_decompress_liz.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_decompress_lz4.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_frame.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_frame_static.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_fast.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_fastbig.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_fastsmall.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_hashchain.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_lowestprice.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_nochain.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_optimal.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\lizard_parser_pricefast.h\">\n      <Filter>Lizard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ZSTDMT\\brotli-mt.h\">\n      <Filter>ZSTDMT</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ZSTDMT\\list.h\">\n      <Filter>ZSTDMT</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ZSTDMT\\lizard-mt.h\">\n      <Filter>ZSTDMT</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ZSTDMT\\lz4-mt.h\">\n      <Filter>ZSTDMT</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ZSTDMT\\lz5-mt.h\">\n      <Filter>ZSTDMT</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ZSTDMT\\memmt.h\">\n      <Filter>ZSTDMT</Filter>\n    </ClInclude>\n    <ClInclude Include=\"ZSTDMT\\threading.h\">\n      <Filter>ZSTDMT</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\atomic.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\compiler.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\count.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\data_block.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\dict_buffer.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\fast-lzma2.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\fastpos_table.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\fl2_compress_internal.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\fl2_errors.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\fl2_internal.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\fl2_pool.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\fl2_threading.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\lzma2_enc.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\mem.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\platform.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\radix_engine.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\radix_get.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\radix_internal.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\radix_mf.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\range_enc.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FastLZMA2\\util.h\">\n      <Filter>FastLZMA2</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\zstd.h\">\n      <Filter>Zstandard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\zstd_errors.h\">\n      <Filter>Zstandard</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\allocations.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\bits.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\bitstream.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\compiler.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\cpu.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\debug.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\error_private.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\fse.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\huf.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\mem.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\pool.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\portability_macros.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\threading.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\zstd_deps.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\zstd_internal.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\common\\zstd_trace.h\">\n      <Filter>Zstandard\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\clevels.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\hist.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstdmt_compress.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_internal.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_literals.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_sequences.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_compress_superblock.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_cwksp.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_double_fast.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_fast.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_lazy.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_ldm.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_ldm_geartab.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_opt.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"NanaZip.Codecs.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.Common.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.Brotli.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.Lizard.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ4.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.MultiThreadWrapper.LZ5.h\" />\n    <ClInclude Include=\"NanaZip.Codecs.SevenZipWrapper.h\" />\n    <ClInclude Include=\"FreeBSD\\dir.h\">\n      <Filter>FreeBSD</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FreeBSD\\fs.h\">\n      <Filter>FreeBSD</Filter>\n    </ClInclude>\n    <ClInclude Include=\"FreeBSD\\dinode.h\">\n      <Filter>FreeBSD</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\compress\\zstd_preSplit.h\">\n      <Filter>Zstandard\\compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_block.h\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_decompress_internal.h\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\decompress\\zstd_ddict.h\">\n      <Filter>Zstandard\\decompress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v03.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v04.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v05.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v06.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v07.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_legacy.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v01.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Zstandard\\legacy\\zstd_v02.h\">\n      <Filter>Zstandard\\legacy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\mem.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\huf.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\error_private.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\fse.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\bitstream.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\compiler.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\debug.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\error_public.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Lizard\\entropy\\hist.h\">\n      <Filter>Lizard\\entropy</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Mile.Helpers.Portable.Base.Unstaged.h\">\n      <Filter>Mile.Portable.Helpers.Unstaged</Filter>\n    </ClInclude>\n    <ClInclude Include=\"NanaZip.Codecs.Specification.Fat.h\" />\n    <ClInclude Include=\"LittleFS\\lfs.h\">\n      <Filter>LittleFS</Filter>\n    </ClInclude>\n    <ClInclude Include=\"LittleFS\\lfs_util.h\">\n      <Filter>LittleFS</Filter>\n    </ClInclude>\n    <ClInclude Include=\"NanaZip.Codecs.Specification.Zealfs.h\" />\n    <ClInclude Include=\"Brotli\\common\\dictionary_inc.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\common\\static_init.h\">\n      <Filter>Brotli\\common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\dec\\prefix_inc.h\">\n      <Filter>Brotli\\dec</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\dec\\static_init.h\">\n      <Filter>Brotli\\dec</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\dictionary_hash_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_base.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match_simd_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\hash_longest_match64_simd_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\matching_tag_mask.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\static_dict_lut_inc.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Brotli\\enc\\static_init.h\">\n      <Filter>Brotli\\enc</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Codecs/RHash/aich.c",
    "content": "﻿/* aich.c - an implementation of EMule AICH Algorithm.\n * Description: http://www.amule.org/wiki/index.php/AICH.\n *\n * Copyright (c) 2008, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n *\n * The AICH Algorithm:\n *\n * Each ed2k chunk (9728000 bytes) is divided into 53 parts (52x 180KB and\n * 1x 140KB) and each of these parts are hashed using the SHA1 algorithm.\n * Each of these hashes is called a Block Hash. By combining pairs of Block\n * Hashes (i.e. each part with the part next to it) algorithm will get a whole\n * tree of hashes (this tree which is therefore a hashset made of all of the\n * other Block Hashes is called the AICH Hashset). Each hash which is neither\n * a Block Hash nor the Root Hash, is a Verifying Hash. The hash at the top\n * level is the Root Hash and it is supposed to be provided by the ed2k link\n * when releasing.\n */\n\n#include \"aich.h\"\n#include \"util.h\"\n#include <assert.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n\n#if defined(USE_OPENSSL)\n#define SHA1_INIT(ctx) ((pinit_t)ctx->sha1_methods.init)(&ctx->sha1_context)\n#define SHA1_UPDATE(ctx, msg, size) ((pupdate_t)ctx->sha1_methods.update)(&ctx->sha1_context, (msg), (size))\n#define SHA1_FINAL(ctx, result) ((pfinal_t)ctx->sha1_methods.final)(&ctx->sha1_context, (result))\n#else\n# define SHA1_INIT(ctx) rhash_sha1_init(&ctx->sha1_context)\n# define SHA1_UPDATE(ctx, msg, size) rhash_sha1_update(&ctx->sha1_context, (msg), (size))\n# define SHA1_FINAL(ctx, result) rhash_sha1_final(&ctx->sha1_context, (result))\n#endif\n\n#define ED2K_CHUNK_SIZE  9728000\n#define FULL_BLOCK_SIZE  184320\n#define LAST_BLOCK_SIZE  143360\n#define BLOCKS_PER_CHUNK 53\n#define BLOCK_HASHES_SIZE (BLOCKS_PER_CHUNK * sha1_hash_size)\n\n/*\n * AICH algorithm could be implemented a bit faster if it knows\n * a hashed message size beforehand. It would allow\n * to build balanced tree while hashing the message.\n *\n * This AICH implementation works with unknown\n * message size like other well-known hash algorithms.\n * So, it just stores sha1 hashes and builds balanced tree\n * only on the last step, when the full message processed\n * and its size got to be known.\n */\n\n/**\n * Initialize algorithm context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_aich_init(aich_ctx* ctx)\n{\n\tmemset(ctx, 0, sizeof(aich_ctx));\n\n#if defined(USE_OPENSSL)\n\tassert(rhash_info_table[3].info->hash_id == EXTENDED_SHA1);\n\tassert(rhash_info_table[3].context_size <= (sizeof(sha1_ctx) + sizeof(unsigned long)));\n\trhash_load_sha1_methods(&ctx->sha1_methods, METHODS_SELECTED);\n#endif\n\n\tSHA1_INIT(ctx);\n}\n\n/* define macrosses to access chunk table */\n#define CT_BITS 8\n#define CT_GROUP_SIZE (1 << CT_BITS)\ntypedef unsigned char hash_pair_t[2][sha1_hash_size];\ntypedef hash_pair_t hash_pairs_group_t[CT_GROUP_SIZE];\n\n#define CT_INDEX(chunk_num) ((chunk_num) & (CT_GROUP_SIZE - 1))\n#define GET_HASH_PAIR(ctx, chunk_num) \\\n\t(((hash_pair_t*)(ctx->chunk_table[chunk_num >> CT_BITS]))[CT_INDEX(chunk_num)])\n\n/**\n * Resize the table if needed to ensure it contains space for given chunk_num.\n * and allocate hash_pairs_group_t element at this index.\n *\n * @param ctx algorithm context\n * @param chunk_num the number of chunks required\n */\nstatic void rhash_aich_chunk_table_extend(aich_ctx* ctx, unsigned chunk_num)\n{\n\tunsigned index = (chunk_num >> CT_BITS);\n\tassert(CT_INDEX(chunk_num) == 0);\n\tRHASH_ASSERT(sizeof(hash_pair_t) == 40);\n\tRHASH_ASSERT(sizeof(hash_pairs_group_t) == (40 * CT_GROUP_SIZE)); /* 10KiB */\n\tRHASH_ASSERT(CT_GROUP_SIZE == 256);\n\n\t/* check main assumptions */\n\tassert(ctx->chunk_table == 0 || ctx->chunk_table[index - 1] != 0); /* table is empty or full */\n\tassert(index <= ctx->allocated);\n\n\t/* check if there is enough space allocated */\n\tif (index >= ctx->allocated) {\n\t\t/* resize the table by allocating some extra space */\n\t\tsize_t new_size = (ctx->allocated == 0 ? 64 : ctx->allocated * 2);\n\t\tvoid** new_block;\n\t\tassert(index == ctx->allocated);\n\n\t\t/* re-size the chunk table to new_size */\n\t\tnew_block = (void**)realloc(ctx->chunk_table, new_size * sizeof(void*));\n\t\tif (new_block == 0) {\n\t\t\tfree(ctx->chunk_table);\n\t\t\tctx->chunk_table = 0;\n\t\t\tctx->error = 1;\n\t\t\treturn;\n\t\t}\n\n\t\tmemset(new_block + ctx->allocated, 0, (new_size - ctx->allocated) * sizeof(void*));\n\t\tctx->chunk_table = new_block;\n\t\tctx->allocated = new_size;\n\t}\n\n\t/* add new hash_pairs_group_t block to the table */\n\tassert(index < ctx->allocated);\n\tassert(ctx->chunk_table != 0);\n\tassert(ctx->chunk_table[index] == 0);\n\n\tctx->chunk_table[index] = malloc(sizeof(hash_pairs_group_t));\n\tif (ctx->chunk_table[index] == 0)\n\t\tctx->error = 1;\n}\n\n/**\n * Free dynamically allocated memory for internal structures\n * used by hashing algorithm.\n *\n * @param ctx AICH algorithm context to cleanup\n */\nvoid rhash_aich_cleanup(aich_ctx* ctx)\n{\n\tsize_t i;\n\tsize_t table_size = (ctx->chunks_count + CT_GROUP_SIZE - 1) / CT_GROUP_SIZE;\n\n\tif (ctx->chunk_table != 0) {\n\t\tassert(table_size <= ctx->allocated);\n\t\tassert(table_size == ctx->allocated || ctx->chunk_table[table_size] == 0);\n\t\tfor (i = 0;  i < table_size; i++)\n\t\t\tfree(ctx->chunk_table[i]);\n\t\tfree(ctx->chunk_table);\n\t\tctx->chunk_table = 0;\n\t}\n\n\tfree(ctx->block_hashes);\n\tctx->block_hashes = 0;\n}\n\n#define AICH_HASH_FULL_TREE 0\n#define AICH_HASH_LEFT_BRANCH 1\n#define AICH_HASH_RIGHT_BRANCH 2\n\n/**\n * Calculate an AICH tree hash, based ether on hashes of 180KB parts\n * (for an ed2k chunk) or on stored ed2k chunks (for the whole tree hash).\n *\n * @param ctx algorithm context\n * @param result pointer to receive calculated tree hash\n * @param type the type of hash to calculate, can be one of constants\n *   AICH_HASH_LEFT_BRANCH, AICH_HASH_RIGHT_BRANCH or AICH_HASH_FULL_TREE.\n */\nstatic void rhash_aich_hash_tree(aich_ctx* ctx, unsigned char* result, int type)\n{\n\tunsigned index = 0; /* leaf index */\n\tunsigned blocks;\n\tint      level = 0;\n\tunsigned is_left_branch = (type == AICH_HASH_RIGHT_BRANCH ? 0x0 : 0x1);\n\tuint64_t path  = is_left_branch;\n\tunsigned blocks_stack[56];\n\tunsigned char sha1_stack[56][sha1_hash_size];\n\n\tif (ctx->error)\n\t\treturn;\n\tassert(ctx->index <= ED2K_CHUNK_SIZE);\n\tassert(type == AICH_HASH_FULL_TREE ? ctx->chunk_table != 0 : ctx->block_hashes != 0);\n\n\t/* calculate number of leafs in the tree */\n\tblocks_stack[0] = blocks = (unsigned)(type == AICH_HASH_FULL_TREE ?\n\t\tctx->chunks_count : (ctx->index + FULL_BLOCK_SIZE - 1) / FULL_BLOCK_SIZE);\n\n\twhile (1) {\n\t\tunsigned char sha1_message[sha1_hash_size];\n\t\tunsigned char* leaf_hash;\n\n\t\t/* go into the left branches until a leaf block is reached */\n\t\twhile (blocks > 1) {\n\t\t\t/* step down into the left branch */\n\t\t\tblocks = (blocks + ((unsigned)path & 0x1)) / 2;\n\t\t\tlevel++;\n\t\t\tassert(level < 56); /* assumption filesize < (2^56 * 9MiB) */\n\t\t\tblocks_stack[level] = blocks;\n\t\t\tpath = (path << 1) | 0x1; /* mark branch as left */\n\t\t}\n\n\t\t/* read a leaf hash */\n\t\tleaf_hash = &(ctx->block_hashes[index][0]);\n\n\t\tif (type == AICH_HASH_FULL_TREE) {\n\t\t\tis_left_branch = (unsigned)path & 0x1;\n\n\t\t\tleaf_hash = GET_HASH_PAIR(ctx, index)[is_left_branch];\n\t\t}\n\t\tindex++;\n\n\t\t/* climb up the tree until a left branch is reached */\n\t\tfor (; level > 0 && (path & 0x01) == 0; path >>= 1) {\n\t\t\tSHA1_INIT(ctx);\n\t\t\tSHA1_UPDATE(ctx, sha1_stack[level], sha1_hash_size);\n\t\t\tSHA1_UPDATE(ctx, leaf_hash, sha1_hash_size);\n\t\t\tSHA1_FINAL(ctx, sha1_message);\n\t\t\tleaf_hash = sha1_message;\n\t\t\tlevel--;\n\t\t}\n\t\tmemcpy((level > 0 ? sha1_stack[level] : result), leaf_hash, 20);\n\n\t\tif (level == 0) break;\n\n\t\t/* jump at the current level from left to right branch */\n\t\tpath &= ~0x1; /* mark branch as right */\n\t\tis_left_branch = ((unsigned)path >> 1) & 1;\n\n\t\t/* calculate number of blocks at right branch of the current level */\n\t\tblocks_stack[level] =\n\t\t\t(blocks_stack[level - 1] + 1 - is_left_branch) / 2;\n\t\tblocks = blocks_stack[level];\n\t}\n}\n\n#define AICH_PROCESS_FINAL_BLOCK 1\n#define AICH_PROCESS_FLUSH_BLOCK 2\n\n/**\n * Calculate and store a hash for a 180K/140K block.\n * Also, if it is the last block of a 9.2MiB ed2k chunk or of the hashed message,\n * then also calculate the AICH tree-hash of the current ed2k chunk.\n *\n * @param ctx algorithm context\n * @param type the actions to take, can be combination of bits AICH_PROCESS_FINAL_BLOCK\n *             and AICH_PROCESS_FLUSH_BLOCK\n */\nstatic void rhash_aich_process_block(aich_ctx* ctx, int type)\n{\n\tassert(type != 0);\n\tassert(ctx->index <= ED2K_CHUNK_SIZE);\n\n\t/* if there is unprocessed data left in the current 180K block. */\n\tif ((type & AICH_PROCESS_FLUSH_BLOCK) != 0)\n\t{\n\t\t/* ensure that the block_hashes array is allocated to save the result */\n\t\tif (ctx->block_hashes == NULL) {\n\t\t\tctx->block_hashes = (unsigned char (*)[sha1_hash_size])malloc(BLOCK_HASHES_SIZE);\n\t\t\tif (ctx->block_hashes == NULL) {\n\t\t\t\tctx->error = 1;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/* store the 180-KiB block hash to the block_hashes array */\n\t\tassert(((ctx->index - 1) / FULL_BLOCK_SIZE) < BLOCKS_PER_CHUNK);\n\t\tSHA1_FINAL(ctx, ctx->block_hashes[(ctx->index - 1) / FULL_BLOCK_SIZE]);\n\t}\n\n\t/* check, if it's time to calculate the tree hash for the current ed2k chunk */\n\tif (ctx->index >= ED2K_CHUNK_SIZE || (type & AICH_PROCESS_FINAL_BLOCK)) {\n\t\tunsigned char (*pair)[sha1_hash_size];\n\n\t\t/* ensure, that we have the space to store tree hash */\n\t\tif (CT_INDEX(ctx->chunks_count) == 0) {\n\t\t\trhash_aich_chunk_table_extend(ctx, (unsigned)ctx->chunks_count);\n\t\t\tif (ctx->error)\n\t\t\t\treturn;\n\t\t}\n\t\tassert(ctx->chunk_table  != 0);\n\t\tassert(ctx->block_hashes != 0);\n\n\t\t/* calculate tree hash and save results to chunk_table */\n\t\tpair = GET_HASH_PAIR(ctx, ctx->chunks_count);\n\n\t\t/* small optimization: skip a left-branch-hash for the last chunk */\n\t\tif (!(type & AICH_PROCESS_FINAL_BLOCK) || ctx->chunks_count == 0) {\n\t\t\t/* calculate a tree hash to be used in left branch */\n\t\t\trhash_aich_hash_tree(ctx, pair[1], AICH_HASH_LEFT_BRANCH);\n\t\t}\n\n\t\t/* small optimization: skip right-branch-hash for the very first chunk */\n\t\tif (ctx->chunks_count > 0) {\n\t\t\t/* calculate a tree hash to be used in right branch */\n\t\t\trhash_aich_hash_tree(ctx, pair[0], AICH_HASH_RIGHT_BRANCH);\n\t\t}\n\n\t\tctx->index = 0; /* mark that the entire ed2k chunk has been processed */\n\t\tctx->chunks_count++;\n\t}\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_aich_update(aich_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tif (ctx->error)\n\t\treturn;\n\twhile (size > 0) {\n\t\tunsigned left_in_chunk = ED2K_CHUNK_SIZE - ctx->index;\n\t\tunsigned block_left = (left_in_chunk <= LAST_BLOCK_SIZE ? left_in_chunk :\n\t\t\tFULL_BLOCK_SIZE - ctx->index % FULL_BLOCK_SIZE);\n\t\tassert(block_left > 0);\n\n\t\tif (size >= block_left) {\n\t\t\tSHA1_UPDATE(ctx, msg, block_left);\n\t\t\tmsg  += block_left;\n\t\t\tsize -= block_left;\n\t\t\tctx->index += block_left;\n\n\t\t\t/* process a 180KiB-blok */\n\t\t\trhash_aich_process_block(ctx, AICH_PROCESS_FLUSH_BLOCK);\n\t\t\tSHA1_INIT(ctx);\n\t\t} else {\n\t\t\t/* add to a leaf block */\n\t\t\tSHA1_UPDATE(ctx, msg, size);\n\t\t\tctx->index += (unsigned)size;\n\t\t\tbreak;\n\t\t}\n\t}\n\tassert(ctx->index < ED2K_CHUNK_SIZE);\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_aich_final(aich_ctx* ctx, unsigned char result[20])\n{\n\tuint64_t total_size =\n\t\t((uint64_t)ctx->chunks_count * ED2K_CHUNK_SIZE) + ctx->index;\n\tunsigned char* const hash = (unsigned char*)ctx->sha1_context.hash;\n\n\tif (ctx->chunks_count == 0 && ctx->block_hashes == NULL) {\n\t\tassert(ctx->index < FULL_BLOCK_SIZE);\n#if defined(USE_OPENSSL)\n\t\tSHA1_FINAL(ctx, hash); /* return just sha1 hash */\n#else\n\t\tSHA1_FINAL(ctx, 0); /* return just sha1 hash */\n#if IS_LITTLE_ENDIAN\n\t\trhash_u32_mem_swap(ctx->sha1_context.hash, 5);\n#endif\n#endif\n\t\tif (result) memcpy(result, hash, sha1_hash_size);\n\t\treturn;\n\t}\n\n\t/* if there is unprocessed data left in the last 180K block */\n\tif ((ctx->index % FULL_BLOCK_SIZE) > 0) {\n\t\t/* then process the last block */\n\t\trhash_aich_process_block(ctx, ctx->block_hashes != NULL ?\n\t\t\tAICH_PROCESS_FINAL_BLOCK | AICH_PROCESS_FLUSH_BLOCK : AICH_PROCESS_FLUSH_BLOCK);\n\t}\n\n\t/* if processed message was shorter than a ed2k chunk */\n\tif (ctx->chunks_count == 0) {\n\t\t/* then return the aich hash for the first chunk */\n\t\trhash_aich_hash_tree(ctx, hash, AICH_HASH_LEFT_BRANCH);\n\t} else {\n\t\tif (ctx->index > 0) {\n\t\t\t/* process the last block of the message */\n\t\t\trhash_aich_process_block(ctx, AICH_PROCESS_FINAL_BLOCK);\n\t\t}\n\t\tassert(ctx->chunks_count > 0);\n\t\tassert(ctx->block_hashes != NULL);\n\n\t\trhash_aich_hash_tree(ctx, hash, AICH_HASH_FULL_TREE);\n\t}\n\n\trhash_aich_cleanup(ctx);\n\tctx->sha1_context.length = total_size; /* store total message size  */\n\tif (result) memcpy(result, hash, sha1_hash_size);\n}\n\n#if !defined(NO_IMPORT_EXPORT)\n# define AICH_CTX_OSSL_FLAG 0x10\n\n/**\n * Export aich context to a memory region, or calculate the\n * size required for context export.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param out pointer to the memory region or NULL\n * @param size size of memory region\n * @return the size of the exported data on success, 0 on fail.\n */\nsize_t rhash_aich_export(const aich_ctx* ctx, void* out, size_t size)\n{\n\tconst size_t head_size = sizeof(size_t);\n\tconst size_t ctx_head_size = offsetof(aich_ctx, block_hashes);\n\tconst size_t block_hashes_size = (ctx->block_hashes ? BLOCK_HASHES_SIZE : 0);\n\tconst size_t chunk_table_size = sizeof(hash_pair_t) * ctx->chunks_count;\n\tconst size_t exported_size = head_size + ctx_head_size + block_hashes_size + chunk_table_size;\n\tchar* out_ptr = (char*)out;\n\tif (!out)\n\t\treturn exported_size;\n\tif (size < exported_size)\n\t\treturn 0;\n\t*(size_t*)out_ptr = sizeof(aich_ctx);\n\tout_ptr += head_size;\n\tmemcpy(out_ptr, ctx, ctx_head_size);\n\tout_ptr += ctx_head_size;\n\tif (ctx->block_hashes) {\n\t\tmemcpy(out_ptr, ctx->block_hashes, BLOCK_HASHES_SIZE);\n\t\tout_ptr += BLOCK_HASHES_SIZE;\n\t}\n\tif (chunk_table_size > 0) {\n\t\tsize_t left_size = chunk_table_size;\n\t\tsize_t index;\n\t\tassert(ctx->chunk_table != NULL);\n\t\tfor (index = 0; left_size > 0; index++) {\n\t\t\tsize_t group_size = (left_size < sizeof(hash_pairs_group_t) ?\n\t\t\t\tleft_size : sizeof(hash_pairs_group_t));\n\t\t\tmemcpy(out_ptr, ctx->chunk_table[index], group_size);\n\t\t\tout_ptr += group_size;\n\t\t\tleft_size -= group_size;\n\t\t}\n\t\tassert(left_size == 0);\n\t}\n\tassert(!out || (size_t)(out_ptr - (char*)out) == exported_size);\n#if defined(USE_OPENSSL)\n\tif (out_ptr && ARE_OPENSSL_METHODS(ctx->sha1_methods)) {\n\t\tint* error_ptr = (int*)((char*)out + head_size + offsetof(aich_ctx, error));\n\t\t*error_ptr |= AICH_CTX_OSSL_FLAG;\n\t\tRHASH_ASSERT(sizeof(*error_ptr) == sizeof(ctx->error));\n\t}\n#endif\n\treturn exported_size;\n}\n\n/**\n * Import aich context from a memory region.\n *\n * @param ctx pointer to the algorithm context\n * @param in pointer to the data to import\n * @param size size of data to import\n * @return the size of the imported data on success, 0 on fail.\n */\nsize_t rhash_aich_import(aich_ctx* ctx, const void* in, size_t size)\n{\n\tconst size_t head_size = sizeof(size_t);\n\tconst size_t ctx_head_size = offsetof(aich_ctx, block_hashes);\n\tconst char* in_ptr = (const char*)in;\n\tsize_t imported_size = head_size + ctx_head_size;\n\tsize_t block_hashes_size;\n\tsize_t chunk_table_size;\n\tif (size < imported_size)\n\t\treturn 0;\n\tif(*(size_t*)in_ptr != sizeof(aich_ctx))\n\t\treturn 0;\n\tin_ptr += head_size;\n\tmemset(ctx, 0, sizeof(aich_ctx));\n\tmemcpy(ctx, in_ptr, ctx_head_size);\n\tin_ptr += ctx_head_size;\n\tblock_hashes_size = (ctx->block_hashes ? BLOCK_HASHES_SIZE : 0);\n\tchunk_table_size = sizeof(hash_pair_t) * ctx->chunks_count;\n\timported_size += block_hashes_size + chunk_table_size;\n\tif (size < imported_size)\n\t\treturn 0;\n\tif (ctx->block_hashes != NULL) {\n\t\tctx->block_hashes = (unsigned char (*)[sha1_hash_size])malloc(BLOCK_HASHES_SIZE);\n\t\tif (!ctx->block_hashes)\n\t\t\treturn 0;\n\t\tmemcpy(ctx->block_hashes, in_ptr, BLOCK_HASHES_SIZE);\n\t\tin_ptr += BLOCK_HASHES_SIZE;\n\t}\n\tif (ctx->allocated > 0) {\n\t\tsize_t index;\n\t\tctx->chunk_table = (void**)malloc(ctx->allocated * sizeof(void*));\n\t\tif (!ctx->chunk_table) {\n\t\t\tctx->error = 1;\n\t\t\treturn 0;\n\t\t}\n\t\tmemset(ctx->chunk_table, 0, ctx->allocated * sizeof(void*));\n\t\tfor (index = 0; chunk_table_size > 0; index++) {\n\t\t\tsize_t group_size = (chunk_table_size < sizeof(hash_pairs_group_t) ?\n\t\t\t\tchunk_table_size : sizeof(hash_pairs_group_t));\n\t\t\tassert(index < ctx->allocated);\n\t\t\tctx->chunk_table[index] = malloc(sizeof(hash_pairs_group_t));\n\t\t\tif (ctx->chunk_table[index] == 0) {\n\t\t\t\tctx->error = 1;\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tmemcpy(ctx->chunk_table[index], in_ptr, group_size);\n\t\t\tchunk_table_size -= group_size;\n\t\t\tin_ptr += group_size;\n\t\t}\n\t}\n\tassert((size_t)(in_ptr - (char*)in) == imported_size);\n#if defined(USE_OPENSSL)\n\tif ((ctx->error & AICH_CTX_OSSL_FLAG) != 0) {\n\t\tctx->error &= ~AICH_CTX_OSSL_FLAG;\n\t\trhash_load_sha1_methods(&ctx->sha1_methods, METHODS_OPENSSL);\n\t} else {\n\t\trhash_load_sha1_methods(&ctx->sha1_methods, METHODS_RHASH);\n\t}\n#endif\n\treturn imported_size;\n}\n#endif /* !defined(NO_IMPORT_EXPORT) */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/aich.h",
    "content": "﻿/* aich.h */\n#ifndef AICH_H\n#define AICH_H\n#include \"byte_order.h\"\n#include \"sha1.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* algorithm context */\ntypedef struct aich_ctx\n{\n\tsha1_ctx sha1_context; /* context used to hash tree leaves */\n#if defined(USE_OPENSSL) || defined(OPENSSL_RUNTIME)\n\tunsigned long reserved; /* need more space for openssl sha1 context */\n#endif\n\tunsigned index;        /* algorithm position in the current ed2k chunk */\n\tint error;             /* non-zero if a memory error occurred, 0 otherwise */\n\tsize_t chunks_count;   /* the number of ed2k chunks hashed */\n\tsize_t allocated;      /* allocated size of the chunk_table */\n\tunsigned char (*block_hashes)[sha1_hash_size];\n\tvoid** chunk_table;    /* table of chunk hashes */\n#if defined(USE_OPENSSL) || defined(OPENSSL_RUNTIME)\n\trhash_hashing_methods sha1_methods;\n#endif\n} aich_ctx;\n\n/* hash functions */\n\nvoid rhash_aich_init(aich_ctx* ctx);\nvoid rhash_aich_update(aich_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_aich_final(aich_ctx* ctx, unsigned char result[20]);\n\n#if !defined(NO_IMPORT_EXPORT)\nsize_t rhash_aich_export(const aich_ctx* ctx, void* out, size_t size);\nsize_t rhash_aich_import(aich_ctx* ctx, const void* in, size_t size);\n#endif /* !defined(NO_IMPORT_EXPORT) */\n\n/* Clean up context by freeing allocated memory.\n * The function is called automatically by rhash_aich_final.\n * Shall be called when aborting hash calculations. */\nvoid rhash_aich_cleanup(aich_ctx* ctx);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* AICH_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/blake2b.c",
    "content": "﻿/* blake2b.c - an implementation of blake2b hash function.\n *\n * Copyright (c) 2012, Samuel Neves <sneves@dei.uc.pt>\n * Copyright (c) 2021, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"blake2b.h\"\n#include \"byte_order.h\"\n#include <string.h>\n\nstatic const uint64_t blake2b_IV[8] =\n{\n\tI64(0x6a09e667f3bcc908), I64(0xbb67ae8584caa73b),\n\tI64(0x3c6ef372fe94f82b), I64(0xa54ff53a5f1d36f1),\n\tI64(0x510e527fade682d1), I64(0x9b05688c2b3e6c1f),\n\tI64(0x1f83d9abfb41bd6b), I64(0x5be0cd19137e2179)\n};\n\nstatic const uint8_t blake2b_sigma[12][16] =\n{\n\t{  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 },\n\t{ 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 },\n\t{ 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 },\n\t{  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 },\n\t{  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 },\n\t{  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 },\n\t{ 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 },\n\t{ 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 },\n\t{  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 },\n\t{ 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0 },\n\t{  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 },\n\t{ 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }\n};\n\nvoid rhash_blake2b_init(blake2b_ctx* ctx)\n{\n\tmemset(ctx, 0, sizeof(*ctx));\n\t/* init state by xoring IV with blake2b input parameter block */\n\tctx->hash[0] = blake2b_IV[0] ^ I64(0x01010040);\n\tctx->hash[1] = blake2b_IV[1];\n\tctx->hash[2] = blake2b_IV[2];\n\tctx->hash[3] = blake2b_IV[3];\n\tctx->hash[4] = blake2b_IV[4];\n\tctx->hash[5] = blake2b_IV[5];\n\tctx->hash[6] = blake2b_IV[6];\n\tctx->hash[7] = blake2b_IV[7];\n}\n\n#define G(r,i,a,b,c,d) \\\n\tdo { \\\n\t\ta = a + b + m[blake2b_sigma[r][2*i+0]]; \\\n\t\td = ROTR64(d ^ a, 32); \\\n\t\tc = c + d; \\\n\t\tb = ROTR64(b ^ c, 24); \\\n\t\ta = a + b + m[blake2b_sigma[r][2*i+1]]; \\\n\t\td = ROTR64(d ^ a, 16); \\\n\t\tc = c + d; \\\n\t\tb = ROTR64(b ^ c, 63); \\\n\t} while(0)\n\n#define ROUND(r) \\\n\tdo { \\\n\t\tG(r,0,v[0],v[4],v[ 8],v[12]); \\\n\t\tG(r,1,v[1],v[5],v[ 9],v[13]); \\\n\t\tG(r,2,v[2],v[6],v[10],v[14]); \\\n\t\tG(r,3,v[3],v[7],v[11],v[15]); \\\n\t\tG(r,4,v[0],v[5],v[10],v[15]); \\\n\t\tG(r,5,v[1],v[6],v[11],v[12]); \\\n\t\tG(r,6,v[2],v[7],v[ 8],v[13]); \\\n\t\tG(r,7,v[3],v[4],v[ 9],v[14]); \\\n\t} while(0)\n\nstatic void rhash_blake2b_process_block(blake2b_ctx* ctx, const uint64_t* m, uint64_t finalization_flag)\n{\n\tuint64_t v[16];\n\tsize_t i;\n\n\tmemcpy(v, ctx->hash, sizeof(uint64_t) * 8);\n\tv[ 8] = blake2b_IV[0];\n\tv[ 9] = blake2b_IV[1];\n\tv[10] = blake2b_IV[2];\n\tv[11] = blake2b_IV[3];\n\tv[12] = blake2b_IV[4] ^ ctx->length; /* length correction */\n\tv[13] = blake2b_IV[5];\n\tv[14] = blake2b_IV[6] ^ finalization_flag;\n\tv[15] = blake2b_IV[7];\n\n\tROUND(0);\n\tROUND(1);\n\tROUND(2);\n\tROUND(3);\n\tROUND(4);\n\tROUND(5);\n\tROUND(6);\n\tROUND(7);\n\tROUND(8);\n\tROUND(9);\n\tROUND(10);\n\tROUND(11);\n\n\tfor(i = 0; i < 8; ++i)\n\t\tctx->hash[i] ^= v[i] ^ v[i + 8];\n}\n\nvoid rhash_blake2b_update(blake2b_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tif(size > 0)\n\t{\n\t\tsize_t index = (size_t)ctx->length & 127;\n\t\tif(index)\n\t\t{\n\t\t\tsize_t rest = blake2b_block_size - index;\n\t\t\tif (size > rest) {\n\t\t\t\tle64_copy(ctx->message, index, msg, rest); /* fill the block */\n\n\t\t\t\t/* process the block */\n\t\t\t\tsize -= rest;\n\t\t\t\tmsg += rest;\n\t\t\t\tctx->length += rest;\n\t\t\t\tindex = 0;\n\t\t\t\trhash_blake2b_process_block(ctx, ctx->message, I64(0));\n\t\t\t}\n\t\t} else if (ctx->length) {\n\t\t\trhash_blake2b_process_block(ctx, ctx->message, I64(0));\n\t\t}\n\t\twhile(size > blake2b_block_size) {\n\t\t\tuint64_t* aligned_message_block;\n\t\t\tif (IS_LITTLE_ENDIAN && IS_ALIGNED_64(msg)) {\n\t\t\t\taligned_message_block = (uint64_t*)msg;\n\t\t\t} else {\n\t\t\t\tle64_copy(ctx->message, 0, msg, blake2b_block_size);\n\t\t\t\taligned_message_block = ctx->message;\n\t\t\t}\n\t\t\tsize -= blake2b_block_size;\n\t\t\tmsg += blake2b_block_size;\n\t\t\tctx->length += blake2b_block_size;\n\t\t\trhash_blake2b_process_block(ctx, aligned_message_block, I64(0));\n\t\t}\n\t\tle64_copy(ctx->message, index, msg, size); /* save leftovers */\n\t\tctx->length += size;\n\t}\n}\n\nvoid rhash_blake2b_final(blake2b_ctx* ctx, unsigned char *result)\n{\n\tsize_t length = (size_t)ctx->length & 127;\n\tif (length)\n\t{\n\t\t/* pad the message with zeros */\n\t\tsize_t index = length >> 3;\n\t\tsize_t shift = (length & 7) * 8;\n\t\tctx->message[index] &= ~(I64(0xFFFFFFFFFFFFFFFF) << shift);\n\t\tfor(index++; index < 16; index++)\n\t\t\tctx->message[index] = 0;\n\t}\n\trhash_blake2b_process_block(ctx, ctx->message, I64(0xFFFFFFFFFFFFFFFF));\n\n\t/* convert hash state to result bytes */\n\tle64_copy(result, 0, ctx->hash, blake2b_hash_size);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/blake2b.h",
    "content": "﻿/* blake2b.h */\n#ifndef BLAKE2B_H\n#define BLAKE2B_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define blake2b_block_size 128\n#define blake2b_hash_size  64\n\ntypedef struct blake2b_ctx\n{\n\tuint64_t hash[8];\n\tuint64_t message[16];\n\tuint64_t length;\n} blake2b_ctx;\n\nvoid rhash_blake2b_init(blake2b_ctx* ctx);\nvoid rhash_blake2b_update(blake2b_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_blake2b_final(blake2b_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* BLAKE2B_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/byte_order.c",
    "content": "﻿/* byte_order.c - byte order related platform dependent routines,\n *\n * Copyright (c) 2008, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n#include \"byte_order.h\"\n#include <string.h>\n\n#ifndef rhash_ctz\n\n#  if _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64) /* if MSVC++ >= 2002 on x86/x64 */\n#  include <intrin.h>\n#  pragma intrinsic(_BitScanForward)\n\n/**\n * Returns index of the trailing bit of x.\n *\n * @param x the number to process\n * @return zero-based index of the trailing bit\n */\nunsigned rhash_ctz(unsigned x)\n{\n\tunsigned long index;\n\tunsigned char isNonzero = _BitScanForward(&index, x); /* MSVC intrinsic */\n\treturn (isNonzero ? (unsigned)index : 0);\n}\n#  else /* _MSC_VER >= 1300... */\n\n/**\n * Returns index of the least significant set bit in a 32-bit number.\n * This operation is also known as Count Trailing Zeros (CTZ).\n *\n * The function is a portable, branch-free equivalent of GCC's __builtin_ctz(),\n * using a De Bruijn sequence for constant-time lookup.\n *\n * @param x 32-bit unsigned integer to analyze (must not be zero)\n * @return zero-based index of the least significant set bit (0 to 31)\n *\n * @note Undefined behavior when `x == 0`. The current implementation\n *       returns 0, but this value must not be relied upon.\n */\nunsigned rhash_ctz(unsigned x)\n{\n\t/* array for conversion to bit position */\n\tstatic unsigned char bit_pos[32] =  {\n\t\t0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,\n\t\t31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9\n\t};\n\n\t/* The De Bruijn bit-scan was devised in 1997, according to Donald Knuth\n\t * by Martin Lauter. The constant 0x077CB531UL is a De Bruijn sequence,\n\t * which produces a unique pattern of bits into the high 5 bits for each\n\t * possible bit position that it is multiplied against.\n\t * See http://graphics.stanford.edu/~seander/bithacks.html\n\t * and http://chessprogramming.wikispaces.com/BitScan */\n\treturn (unsigned)bit_pos[((uint32_t)((x & -x) * 0x077CB531U)) >> 27];\n}\n#  endif /* _MSC_VER >= 1300... */\n#endif /* rhash_ctz */\n\n#ifndef rhash_ctz64\n/**\n * Returns the zero-based index of the least significant set bit in a 64-bit number.\n * This operation is also known as Count Trailing Zeros (CTZ).\n *\n * The function is a portable, branch-free equivalent of GCC's __builtin_ctzll().\n * Uses a 32-bit optimized implementation with magic constant `0x78291ACF`,\n * based on Matt Taylor's original algorithm (2003).\n *\n * @param x 64-bit unsigned integer to analyze (must not be zero)\n * @return zero-based index of the least significant set bit (0 to 63)\n *\n * @note Undefined behavior when `x == 0`. The current implementation\n *       returns 63, but this value must not be relied upon.\n * @see rhash_ctz() for 32-bit version.\n */\nunsigned rhash_ctz64(uint64_t x)\n{\n\t/* lookup table mapping hash values to bit position */\n\tstatic unsigned char bit_pos[64] =  {\n\t\t63, 30,  3, 32, 59, 14, 11, 33, 60, 24, 50,  9, 55, 19, 21, 34,\n\t\t61, 29,  2, 53, 51, 23, 41, 18, 56, 28,  1, 43, 46, 27,  0, 35,\n\t\t62, 31, 58,  4,  5, 49, 54,  6, 15, 52, 12, 40,  7, 42, 45, 16,\n\t\t25, 57, 48, 13, 10, 39,  8, 44, 20, 47, 38, 22, 17, 37, 36, 26\n\t};\n\t/* transform 0b01000 -> 0b01111 (isolate least significant bit) */\n\tx ^= x - 1;\n\t/* fold 64-bit value to 32-bit to be efficient on 32-bit systems */\n\tuint32_t folded = (uint32_t)((x >> 32) ^ x);\n\t/* Use Matt Taylor's multiplication trick (2003):\n\t * - multiply by (specially chosen) magic constant 0x78291ACF\n\t * - use top 6 bits of result (>>26) as table index\n\t * Original discussion:\n\t * https://groups.google.com/g/comp.lang.asm.x86/c/3pVGzQGb1ys/m/fPpKBKNi848J\n\t * https://groups.google.com/g/comp.lang.asm.x86/c/3pVGzQGb1ys/m/230qffQJYvQJ\n\t */\n\treturn bit_pos[folded * 0x78291ACF >> 26];\n}\n#endif /* rhash_ctz64 */\n\n#ifndef rhash_popcount\n/**\n * Returns the number of 1-bits in x.\n *\n * @param x the value to process\n * @return the number of 1-bits\n */\nunsigned rhash_popcount(unsigned x)\n{\n\tx -= (x >>1) & 0x55555555;\n\tx = ((x >> 2) & 0x33333333) + (x & 0x33333333);\n\tx = ((x >> 4) + x) & 0x0f0f0f0f;\n\treturn (x * 0x01010101) >> 24;\n}\n#endif /* rhash_popcount */\n\n/**\n * Copy a memory block with simultaneous exchanging byte order.\n * The byte order is changed from little-endian 32-bit integers\n * to big-endian (or vice-versa).\n *\n * @param to the pointer where to copy memory block\n * @param index the index to start writing from\n * @param from  the source block to copy\n * @param length length of the memory block\n */\nvoid rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length)\n{\n\t/* if all pointers and length are 32-bits aligned */\n\tif ( 0 == (( (uintptr_t)to | (uintptr_t)from | (uintptr_t)index | length ) & 3) ) {\n\t\t/* copy memory as 32-bit words */\n\t\tconst uint32_t* src = (const uint32_t*)from;\n\t\tconst uint32_t* end = (const uint32_t*)((const char*)src + length);\n\t\tuint32_t* dst = (uint32_t*)((char*)to + index);\n\t\tfor (; src < end; dst++, src++)\n\t\t\t*dst = bswap_32(*src);\n\t} else {\n\t\tconst char* src = (const char*)from;\n\t\tfor (length += index; (size_t)index < length; index++)\n\t\t\t((char*)to)[index ^ 3] = *(src++);\n\t}\n}\n\n/**\n * Fill a memory block by a character with changing byte order.\n * The byte order is changed from little-endian 32-bit integers\n * to big-endian (or vice-versa).\n *\n * @param to the pointer where to copy memory block\n * @param index the index to start writing from\n * @param c the character to fill the block with\n * @param length length of the memory block\n */\nvoid rhash_swap_memset_to_u32(void* to, int index, int c, size_t length)\n{\n\tconst size_t end = length + (size_t)index;\n\tfor (; (index & 3) && (size_t)index < end; index++)\n\t\t((char*)to)[index ^ 3] = (char)c;\n\tlength = end - (size_t)index;\n\tmemset((char*)to + index, c, length & ~3);\n\tfor (; (size_t)index < end; index++)\n\t\t((char*)to)[index ^ 3] = (char)c;\n}\n\n/**\n * Copy a memory block with changed byte order.\n * The byte order is changed from little-endian 64-bit integers\n * to big-endian (or vice-versa).\n *\n * @param to     the pointer where to copy memory block\n * @param index  the index to start writing from\n * @param from   the source block to copy\n * @param length length of the memory block\n */\nvoid rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length)\n{\n\t/* if all pointers and length are 64-bits aligned */\n\tif ( 0 == (( (uintptr_t)to | (uintptr_t)from | (uintptr_t)index | length ) & 7) ) {\n\t\t/* copy aligned memory block as 64-bit integers */\n\t\tconst uint64_t* src = (const uint64_t*)from;\n\t\tconst uint64_t* end = (const uint64_t*)((const char*)src + length);\n\t\tuint64_t* dst = (uint64_t*)((char*)to + index);\n\t\twhile (src < end) *(dst++) = bswap_64( *(src++) );\n\t} else {\n\t\tconst char* src = (const char*)from;\n\t\tfor (length += index; (size_t)index < length; index++) ((char*)to)[index ^ 7] = *(src++);\n\t}\n}\n\n/**\n * Copy data from a sequence of 64-bit words to a binary string of given length,\n * while changing byte order.\n *\n * @param to     the binary string to receive data\n * @param from   the source sequence of 64-bit words\n * @param length the size in bytes of the data being copied\n */\nvoid rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length)\n{\n\t/* if all pointers and length are 64-bits aligned */\n\tif ( 0 == (( (uintptr_t)to | (uintptr_t)from | length ) & 7) ) {\n\t\t/* copy aligned memory block as 64-bit integers */\n\t\tconst uint64_t* src = (const uint64_t*)from;\n\t\tconst uint64_t* end = (const uint64_t*)((const char*)src + length);\n\t\tuint64_t* dst = (uint64_t*)to;\n\t\twhile (src < end) *(dst++) = bswap_64( *(src++) );\n\t} else {\n\t\tsize_t index;\n\t\tchar* dst = (char*)to;\n\t\tfor (index = 0; index < length; index++) *(dst++) = ((char*)from)[index ^ 7];\n\t}\n}\n\n/**\n * Exchange byte order in the given array of 32-bit integers.\n *\n * @param arr    the array to process\n * @param length array length\n */\nvoid rhash_u32_mem_swap(unsigned* arr, int length)\n{\n\tunsigned* end = arr + length;\n\tfor (; arr < end; arr++) {\n\t\t*arr = bswap_32(*arr);\n\t}\n}\n\n#if !defined(has_cpu_feature)\n# if defined(HAS_GCC_INTEL_CPUID)\n#  include <cpuid.h>\n#  define RHASH_CPUID(id, regs) \\\n\t__get_cpuid(id, &(regs[0]), &(regs[1]), &(regs[2]), &(regs[3]));\n#  if HAS_GNUC(6, 3)\n#   define RHASH_CPUIDEX(id, sub_id, regs) \\\n\t__get_cpuid_count(id, sub_id, &regs[0], &regs[1], &regs[2], &regs[3]);\n#  endif\n# elif defined(HAS_MSVC_INTEL_CPUID)\n#  define RHASH_CPUID(id, regs) __cpuid((int*)regs, id)\n#  if _MSC_VER >= 1600\n#   define RHASH_CPUIDEX(id, sub_id, regs) __cpuidex((int*)regs, id, sub_id);\n#  endif\n# else\n#  error \"Unsupported platform\"\n#endif /* HAS_GCC_INTEL_CPUID */\n\nstatic uint64_t get_cpuid_features(void)\n{\n\tuint32_t cpu_info[4] = {0};\n\tuint64_t result = 0;\n\t/* Request basic CPU functions */\n\tRHASH_CPUID(1, cpu_info);\n\t/* Store features, but clear bit 29 to store SHANI bit later */\n\tresult = ((((uint64_t)cpu_info[2]) << 32) ^\n\t\t(cpu_info[3] & ~(1 << 29)));\n#ifdef RHASH_CPUIDEX\n\t/* Check if CPUID requests for feature_id >= 7 are supported */\n\tRHASH_CPUID(0, cpu_info);\n\tif (cpu_info[0] >= 7)\n\t{\n\t\t/* Request CPUID AX=7 CX=0 to get SHANI bit */\n\t\tRHASH_CPUIDEX(7, 0, cpu_info);\n\t\tresult |= (cpu_info[1] & (1 << 29));\n\t}\n#endif\n\treturn result;\n}\n\nint has_cpu_feature(unsigned feature_bit)\n{\n\tstatic uint64_t features;\n\tconst uint64_t feature = I64(1) << feature_bit;\n\tif (!features)\n\t\tfeatures = (get_cpuid_features() | 1);\n\treturn !!(features & feature);\n}\n#endif /* has_cpu_feature */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/byte_order.h",
    "content": "﻿/* byte_order.h */\n#ifndef BYTE_ORDER_H\n#define BYTE_ORDER_H\n#include \"ustd.h\"\n#include <stdlib.h>\n\n#if defined(__GLIBC__)\n# include <endian.h>\n#endif\n#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)\n# include <sys/types.h>\n#elif defined (__NetBSD__) || defined(__OpenBSD__)\n# include <sys/param.h>\n#endif\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* if x86 compatible cpu */\n#if defined(i386) || defined(__i386__) || defined(__i486__) || \\\n\tdefined(__i586__) || defined(__i686__) || defined(__pentium__) || \\\n\tdefined(__pentiumpro__) || defined(__pentium4__) || \\\n\tdefined(__nocona__) || defined(prescott) || defined(__core2__) || \\\n\tdefined(__k6__) || defined(__k8__) || defined(__athlon__) || \\\n\tdefined(__amd64) || defined(__amd64__) || \\\n\tdefined(__x86_64) || defined(__x86_64__) || defined(_M_IX86) || \\\n\tdefined(_M_AMD64) || defined(_M_IA64) || defined(_M_X64)\n/* detect if x86-64 instruction set is supported */\n# if defined(_LP64) || defined(__LP64__) || defined(__x86_64) || \\\n\tdefined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)\n#  define CPU_X64\n# else\n#  define CPU_IA32\n# endif\n#endif\n\n#define RHASH_BYTE_ORDER_LE 1234\n#define RHASH_BYTE_ORDER_BE 4321\n\n#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \\\n    (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#  define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_LE\n#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \\\n      (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#  define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_BE\n#elif defined(_BYTE_ORDER)\n#  if defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN)\n#    define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_LE\n#  elif defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN)\n#    define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_BE\n#  endif\n#elif defined(__sun) && defined(_LITTLE_ENDIAN)\n#  define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_LE\n#elif defined(__sun) && defined(_BIG_ENDIAN)\n#  define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_BE\n#endif\n\n/* try detecting endianness by CPU */\n#ifdef RHASH_BYTE_ORDER\n#elif defined(CPU_IA32) || defined(CPU_X64) || defined(__ia64) || defined(__ia64__) || \\\n      defined(__alpha__) || defined(_M_ALPHA) || defined(vax) || defined(MIPSEL) || \\\n      defined(_ARM_) || defined(__arm__) || defined(_M_ARM64) || defined(_M_ARM64EC) || \\\n      defined(__loongarch64) || defined(__sw_64)\n#  define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_LE\n#elif defined(__sparc) || defined(__sparc__) || defined(sparc) || \\\n      defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_POWER) || \\\n      defined(__POWERPC__) || defined(POWERPC) || defined(__powerpc) || \\\n      defined(__powerpc__) || defined(__powerpc64__) || defined(__ppc__) || \\\n      defined(__hpux)  || defined(_MIPSEB) || defined(mc68000) || \\\n      defined(__s390__) || defined(__s390x__) || defined(sel) || defined(__hppa__)\n# define RHASH_BYTE_ORDER RHASH_BYTE_ORDER_BE\n#else\n#  error \"Can't detect CPU architechture\"\n#endif\n\n#define IS_BIG_ENDIAN (RHASH_BYTE_ORDER == RHASH_BYTE_ORDER_BE)\n#define IS_LITTLE_ENDIAN (RHASH_BYTE_ORDER == RHASH_BYTE_ORDER_LE)\n\n#ifndef __has_builtin\n# define __has_builtin(x) 0\n#endif\n\n#ifdef __clang__\n# define HAS_CLANG_BUILTIN(x) __has_builtin(x)\n#else\n# define HAS_CLANG_BUILTIN(x) 0\n#endif\n\n#ifdef __GNUC__\n# define HAS_GNUC(a, b) (__GNUC__ > a || (__GNUC__ == a && __GNUC_MINOR__ >= b))\n#else\n# define HAS_GNUC(a, b) 0\n#endif\n\n#define IS_ALIGNED_32(p) (0 == (3 & (uintptr_t)(p)))\n#define IS_ALIGNED_64(p) (0 == (7 & (uintptr_t)(p)))\n\n#if defined(_MSC_VER)\n#define ALIGN_ATTR(n) __declspec(align(n))\n#elif defined(__GNUC__)\n#define ALIGN_ATTR(n) __attribute__((aligned (n)))\n#else\n#define ALIGN_ATTR(n) /* nothing */\n#endif\n\n\n#if defined(_MSC_VER) || defined(__BORLANDC__)\n#define I64(x) x##ui64\n#else\n#define I64(x) x##ULL\n#endif\n\n#if defined(_MSC_VER)\n#define RHASH_INLINE __inline\n#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)\n#define RHASH_INLINE inline\n#elif defined(__GNUC__)\n#define RHASH_INLINE __inline__\n#else\n#define RHASH_INLINE\n#endif\n\n/* rhash_ctz - count traling zero bits */\n#if HAS_GNUC(3, 4) || HAS_CLANG_BUILTIN(__builtin_ctz)\n# define rhash_ctz(x) __builtin_ctz(x)\n# define rhash_ctz64(x) __builtin_ctzll(x)\n#else\nunsigned rhash_ctz(unsigned);\nunsigned rhash_ctz64(uint64_t);\n#endif\n\n/* rhash_popcount - count the number of 1-bits */\n#if HAS_GNUC(3, 4) || HAS_CLANG_BUILTIN(__builtin_popcount)\n# define rhash_popcount(x) __builtin_popcount(x)\n#else\nunsigned rhash_popcount(unsigned); /* define as function */\n#endif\n\nvoid rhash_swap_copy_str_to_u32(void* to, int index, const void* from, size_t length);\nvoid rhash_swap_memset_to_u32(void* to, int index, int c, size_t length);\nvoid rhash_swap_copy_str_to_u64(void* to, int index, const void* from, size_t length);\nvoid rhash_swap_copy_u64_to_str(void* to, const void* from, size_t length);\nvoid rhash_u32_mem_swap(unsigned* p, int length_in_u32);\n\n/* bswap definitions */\n#if HAS_GNUC(4, 3) || \\\n    (HAS_CLANG_BUILTIN(__builtin_bswap32) && HAS_CLANG_BUILTIN(__builtin_bswap64))\n# define bswap_32(x) __builtin_bswap32(x)\n# define bswap_64(x) __builtin_bswap64(x)\n#elif (_MSC_VER > 1300) && (defined(CPU_IA32) || defined(CPU_X64)) /* MS VC */\n# define bswap_32(x) ((uint32_t)_byteswap_ulong((unsigned long)x))\n# define bswap_64(x) ((uint64_t)_byteswap_uint64((__int64)x))\n#else\n/* fallback to generic bswap definition */\nstatic RHASH_INLINE uint32_t bswap_32(uint32_t x)\n{\n# if defined(__GNUC__) && defined(CPU_IA32) && !defined(__i386__) && !defined(RHASH_NO_ASM)\n\t__asm(\"bswap\\t%0\" : \"=r\" (x) : \"0\" (x)); /* gcc x86 version */\n\treturn x;\n# else\n\tx = ((x << 8) & 0xFF00FF00u) | ((x >> 8) & 0x00FF00FFu);\n\treturn (x >> 16) | (x << 16);\n# endif\n}\nstatic RHASH_INLINE uint64_t bswap_64(uint64_t x)\n{\n\tunion {\n\t\tuint64_t ll;\n\t\tuint32_t l[2];\n\t} w, r;\n\tw.ll = x;\n\tr.l[0] = bswap_32(w.l[1]);\n\tr.l[1] = bswap_32(w.l[0]);\n\treturn r.ll;\n}\n#endif /* bswap definitions */\n\n#if IS_BIG_ENDIAN\n# define be2me_32(x) (x)\n# define be2me_64(x) (x)\n# define le2me_32(x) bswap_32(x)\n# define le2me_64(x) bswap_64(x)\n\n# define be32_copy(to, index, from, length) memcpy((char*)(to) + (index), (from), (length))\n# define le32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))\n# define be32_memset(to, index, c, length) memset((char*)(to) + (index), (c), (length))\n# define le32_memset(to, index, c, length) rhash_swap_memset_to_u32((to), (index), (c), (length))\n# define be64_copy(to, index, from, length) memcpy((char*)(to) + (index), (from), (length))\n# define le64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))\n# define me64_to_be_str(to, from, length) memcpy((to), (from), (length))\n# define me64_to_le_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))\n\n#else /* IS_BIG_ENDIAN */\n# define be2me_32(x) bswap_32(x)\n# define be2me_64(x) bswap_64(x)\n# define le2me_32(x) (x)\n# define le2me_64(x) (x)\n\n# define be32_copy(to, index, from, length) rhash_swap_copy_str_to_u32((to), (index), (from), (length))\n# define le32_copy(to, index, from, length) memcpy((char*)(to) + (index), (from), (length))\n# define be32_memset(to, index, c, length) rhash_swap_memset_to_u32((to), (index), (c), (length))\n# define le32_memset(to, index, c, length) memset((char*)(to) + (index), (c), (length))\n# define be64_copy(to, index, from, length) rhash_swap_copy_str_to_u64((to), (index), (from), (length))\n# define le64_copy(to, index, from, length) memcpy((char*)(to) + (index), (from), (length))\n# define me64_to_be_str(to, from, length) rhash_swap_copy_u64_to_str((to), (from), (length))\n# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))\n#endif /* IS_BIG_ENDIAN */\n\n/* ROTL/ROTR macros rotate a 32/64-bit word left/right by n bits */\n#define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n))))\n#define ROTR32(dword, n) ((dword) >> (n) ^ ((dword) << (32 - (n))))\n#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))\n#define ROTR64(qword, n) ((qword) >> (n) ^ ((qword) << (64 - (n))))\n\n#define CPU_FEATURE_SSE4_2 (52)\n#define CPU_FEATURE_SHANI (29)\n\n#if (HAS_GNUC(3, 4) || defined(__clang__)) && (defined(CPU_X64) || defined(CPU_IA32))\n# define HAS_GCC_INTEL_CPUID\nint has_cpu_feature(unsigned feature_bit);\n#elif (_MSC_VER >= 1310) && (_M_IX86 || _M_AMD64)\n# define HAS_MSVC_INTEL_CPUID\nint has_cpu_feature(unsigned feature_bit);\n#else\n# define NO_HAS_CPU_FEATURE\n# define has_cpu_feature(x) (0)\n#endif\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* BYTE_ORDER_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/edonr.c",
    "content": "﻿/* edonr.c - an implementation of EDON-R 256/224/384/512 hash functions\n *\n * Copyright (c) 2011, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n *\n * This implementation is based on the article:\n *    D. Gligoroski, R. S. Odegard, M. Mihova, S. J. Knapskog, ...,\n *    Cryptographic Hash Function EDON-R - Submission to NIST, 2008\n *\n * EDON-R has been designed to be much more efficient than SHA-2\n * cryptographic hash functions, offering the same or better security.\n */\n\n#include <string.h>\n#include \"byte_order.h\"\n#include \"edonr.h\"\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_edonr256_init(edonr_ctx* ctx)\n{\n\tstatic const unsigned EDONR256_H0[16] = {\n\t\t0x40414243, 0x44454647, 0x48494a4b, 0x4c4d4e4f, 0x50515253, 0x54555657,\n\t\t0x58595a5b, 0x5c5d5e5f, 0x60616263, 0x64656667, 0x68696a6b, 0x6c6d6e6f,\n\t\t0x70717273, 0x74757677, 0x78797a7b, 0x7c7d7e7f\n\t};\n\n#if FULL_CTX_INITIALIZATION\n\tmemset(ctx, 0, sizeof(*ctx));\n#else\n\tctx->length = 0;\n#endif\n\tctx->digest_length = edonr256_hash_size;\n\tmemcpy(ctx->u.data256.hash, EDONR256_H0, sizeof(EDONR256_H0));\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_edonr224_init(struct edonr_ctx* ctx)\n{\n\tstatic const unsigned EDONR224_H0[16] = {\n\t\t0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617,\n\t\t0x18191a1b, 0x1c1d1e1f, 0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f,\n\t\t0x30313233, 0x24353637, 0x38393a3b, 0x3c3d3e3f\n\t};\n\n#if FULL_CTX_INITIALIZATION\n\tmemset(ctx, 0, sizeof(*ctx));\n#else\n\tctx->length = 0;\n#endif\n\tctx->digest_length = edonr224_hash_size;\n\tmemcpy(ctx->u.data256.hash, EDONR224_H0, sizeof(EDONR224_H0));\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_edonr512_init(edonr_ctx* ctx)\n{\n\tstatic const uint64_t EDONR512_H0[16] = {\n\t\tI64(0x8081828384858687), I64(0x88898a8b8c8d8e8f), I64(0x9091929394959697),\n\t\tI64(0x98999a9b9c9d9e9f), I64(0xa0a1a2a3a4a5a6a7), I64(0xa8a9aaabacadaeaf),\n\t\tI64(0xb0b1b2b3b4b5b6b7), I64(0xb8b9babbbcbdbebf), I64(0xc0c1c2c3c4c5c6c7),\n\t\tI64(0xc8c9cacbcccdcecf), I64(0xd0d1d2d3d4d5d6d7), I64(0xd8d9dadbdcdddedf),\n\t\tI64(0xe0e1e2e3e4e5e6e7), I64(0xe8e9eaebecedeeef), I64(0xf0f1f2f3f4f5f6f7),\n\t\tI64(0xf8f9fafbfcfdfeff)\n\t};\n\n#if FULL_CTX_INITIALIZATION\n\tmemset(ctx, 0, sizeof(*ctx));\n#else\n\tctx->length = 0;\n#endif\n\tctx->digest_length = edonr512_hash_size;\n\tmemcpy(ctx->u.data512.hash, EDONR512_H0, sizeof(EDONR512_H0));\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_edonr384_init(struct edonr_ctx* ctx)\n{\n\tstatic const uint64_t EDONR384_H0[16] = {\n\t\tI64(0x0001020304050607), I64(0x08090a0b0c0d0e0f), I64(0x1011121314151617),\n\t\tI64(0x18191a1b1c1d1e1f), I64(0x2021222324252627), I64(0x28292a2b2c2d2e2f),\n\t\tI64(0x3031323324353637), I64(0x38393a3b3c3d3e3f), I64(0x4041424344454647),\n\t\tI64(0x48494a4b4c4d4e4f), I64(0x5051525354555657), I64(0x58595a5b5c5d5e5f),\n\t\tI64(0x6061626364656667), I64(0x68696a6b6c6d6e6f), I64(0x7071727374757677),\n\t\tI64(0x78797a7b7c7d7e7f)\n\t};\n\n#if FULL_CTX_INITIALIZATION\n\tmemset(ctx, 0, sizeof(*ctx));\n#else\n\tctx->length = 0;\n#endif\n\tctx->digest_length = edonr384_hash_size;\n\tmemcpy(ctx->u.data512.hash, EDONR384_H0, sizeof(EDONR384_H0));\n}\n\n/* Q256 macro, taken from eBASH submission */\n#define Q256(x0,x1,x2,x3,x4,x5,x6,x7,y0,y1,y2,y3,y4,y5,y6,y7,z0,z1,z2,z3,z4,z5,z6,z7) \\\n{\\\n\t/* The First Latin Square\\\n\t0   7   1   3   2   4   6   5\\\n\t4   1   7   6   3   0   5   2\\\n\t7   0   4   2   5   3   1   6\\\n\t1   4   0   5   6   2   7   3\\\n\t2   3   6   7   1   5   0   4\\\n\t5   2   3   1   7   6   4   0\\\n\t3   6   5   0   4   7   2   1\\\n\t6   5   2   4   0   1   3   7\\\n\t*/\\\n\tt8  = x0 + x4; \\\n\tt9  = x1 + x7; \\\n\tt12 = t8 + t9; \\\n\tt10 = x2 + x3; \\\n\tt11 = x5 + x6; \\\n\tt13 = t10 + t11; \\\n\tt0  = 0xaaaaaaaa + t12 + x2; \\\n\tt1  = t12 + x3; \\\n\tt1  = ROTL32((t1), 5); \\\n\tt2  = t12 + x6; \\\n\tt2  = ROTL32((t2), 11); \\\n\tt3  = t13 + x7; \\\n\tt3  = ROTL32((t3), 13); \\\n\tt4  = x1 + t13; \\\n\tt4  = ROTL32((t4), 17); \\\n\tt5  = t8 + t10 + x5; \\\n\tt5  = ROTL32((t5), 19); \\\n\tt6  = x0 + t9 + t11; \\\n\tt6  = ROTL32((t6), 29); \\\n\tt7  = t13 + x4; \\\n\tt7  = ROTL32((t7), 31); \\\n\t\\\n\tt16 = t0 ^ t4; \\\n\tt17 = t1 ^ t7; \\\n\tt18 = t2 ^ t3; \\\n\tt19 = t5 ^ t6; \\\n\tt8  = t3 ^ t19; \\\n\tt9  = t2 ^ t19; \\\n\tt10 = t18 ^ t5; \\\n\tt11 = t16 ^ t1; \\\n\tt12 = t16 ^ t7; \\\n\tt13 = t17 ^ t6; \\\n\tt14 = t18 ^ t4; \\\n\tt15 = t0 ^ t17; \\\n\t\\\n\t/* The Second Orthogonal Latin Square\\\n\t0   4   2   3   1   6   5   7\\\n\t7   6   3   2   5   4   1   0\\\n\t5   3   1   6   0   2   7   4\\\n\t1   0   5   4   3   7   2   6\\\n\t2   1   0   7   4   5   6   3\\\n\t3   5   7   0   6   1   4   2\\\n\t4   7   6   1   2   0   3   5\\\n\t6   2   4   5   7   3   0   1\\\n\t*/\\\n\tt16 = y0  + y1; \\\n\tt17 = y2  + y5; \\\n\tt20 = t16 + t17; \\\n\tt18 = y3  + y4; \\\n\tt22 = t16 + t18; \\\n\tt19 = y6  + y7; \\\n\tt21 = t18 + t19; \\\n\tt23 = t17 + t19; \\\n\tt0  = 0x55555555 + t20 + y7; \\\n\tt1  = t22 + y6; \\\n\tt1  = ROTL32((t1), 3); \\\n\tt2  = t20 + y3; \\\n\tt2  = ROTL32((t2), 7); \\\n\tt3  = y2 + t21; \\\n\tt3  = ROTL32((t3), 11); \\\n\tt4  = t22 + y5; \\\n\tt4  = ROTL32((t4), 17); \\\n\tt5  = t23 + y4; \\\n\tt5  = ROTL32((t5), 19); \\\n\tt6  = y1 + t23; \\\n\tt6  = ROTL32((t6), 23); \\\n\tt7  = y0 + t21; \\\n\tt7  = ROTL32((t7), 29); \\\n\t\\\n\tt16  = t0 ^ t1; \\\n\tt17  = t2 ^ t5; \\\n\tt18  = t3 ^ t4; \\\n\tt19  = t6 ^ t7; \\\n\tz5   = t8  + (t18 ^ t6); \\\n\tz6   = t9  + (t17 ^ t7); \\\n\tz7   = t10 + (t4 ^ t19); \\\n\tz0   = t11 + (t16 ^ t5); \\\n\tz1   = t12 + (t2 ^ t19); \\\n\tz2   = t13 + (t16 ^ t3); \\\n\tz3   = t14 + (t0 ^ t18); \\\n\tz4   = t15 + (t1 ^ t17); \\\n}\n\n/* Q512 macro, taken from eBASH submission */\n#define Q512(x0,x1,x2,x3,x4,x5,x6,x7,y0,y1,y2,y3,y4,y5,y6,y7,z0,z1,z2,z3,z4,z5,z6,z7) \\\n{\\\n\t/* First Latin Square\\\n\t0   7   1   3   2   4   6   5\\\n\t4   1   7   6   3   0   5   2\\\n\t7   0   4   2   5   3   1   6\\\n\t1   4   0   5   6   2   7   3\\\n\t2   3   6   7   1   5   0   4\\\n\t5   2   3   1   7   6   4   0\\\n\t3   6   5   0   4   7   2   1\\\n\t6   5   2   4   0   1   3   7\\\n\t*/\\\n\tt8  = x0 + x4; \\\n\tt9  = x1 + x7; \\\n\tt12 = t8 + t9; \\\n\tt10 = x2 + x3; \\\n\tt11 = x5 + x6; \\\n\tt13 = t10 + t11; \\\n\tt0  = I64(0xaaaaaaaaaaaaaaaa) + t12 + x2; \\\n\tt1  = t12 + x3; \\\n\tt1  = ROTL64((t1), 5); \\\n\tt2  = t12 + x6; \\\n\tt2  = ROTL64((t2),19); \\\n\tt3  = t13 + x7; \\\n\tt3  = ROTL64((t3),29); \\\n\tt4  = x1 + t13; \\\n\tt4  = ROTL64((t4),31); \\\n\tt5  = t8 + t10 + x5; \\\n\tt5  = ROTL64((t5),41); \\\n\tt6  = x0 + t9 + t11; \\\n\tt6  = ROTL64((t6),57); \\\n\tt7  = t13 + x4; \\\n\tt7  = ROTL64((t7),61); \\\n\t\\\n\tt16 = t0 ^ t4; \\\n\tt17 = t1 ^ t7; \\\n\tt18 = t2 ^ t3; \\\n\tt19 = t5 ^ t6; \\\n\tt8  = t3 ^ t19; \\\n\tt9  = t2 ^ t19; \\\n\tt10 = t18 ^ t5; \\\n\tt11 = t16 ^ t1; \\\n\tt12 = t16 ^ t7; \\\n\tt13 = t17 ^ t6; \\\n\tt14 = t18 ^ t4; \\\n\tt15 = t0 ^ t17; \\\n\t\\\n\t/* Second Orthogonal Latin Square\\\n\t0   4   2   3   1   6   5   7\\\n\t7   6   3   2   5   4   1   0\\\n\t5   3   1   6   0   2   7   4\\\n\t1   0   5   4   3   7   2   6\\\n\t2   1   0   7   4   5   6   3\\\n\t3   5   7   0   6   1   4   2\\\n\t4   7   6   1   2   0   3   5\\\n\t6   2   4   5   7   3   0   1\\\n\t*/\\\n\tt16 = y0  + y1; \\\n\tt17 = y2  + y5; \\\n\tt20 = t16 + t17; \\\n\tt18 = y3  + y4; \\\n\tt22 = t16 + t18; \\\n\tt19 = y6  + y7; \\\n\tt21 = t18 + t19; \\\n\tt23 = t17 + t19; \\\n\tt0  = I64(0x5555555555555555) + t20 + y7; \\\n\tt1  = t22 + y6; \\\n\tt1  = ROTL64((t1), 3); \\\n\tt2  = t20 + y3; \\\n\tt2  = ROTL64((t2), 17); \\\n\tt3  = y2 + t21; \\\n\tt3  = ROTL64((t3), 23); \\\n\tt4  = t22 + y5; \\\n\tt4  = ROTL64((t4), 31); \\\n\tt5  = t23 + y4; \\\n\tt5  = ROTL64((t5), 37); \\\n\tt6  = y1 + t23; \\\n\tt6  = ROTL64((t6), 45); \\\n\tt7  = y0 + t21; \\\n\tt7  = ROTL64((t7), 59); \\\n\t\\\n\tt16  = t0 ^ t1; \\\n\tt17  = t2 ^ t5; \\\n\tt18  = t3 ^ t4; \\\n\tt19  = t6 ^ t7; \\\n\tz5   = t8  + (t18 ^ t6); \\\n\tz6   = t9  + (t17 ^ t7); \\\n\tz7   = t10 + (t4 ^ t19); \\\n\tz0   = t11 + (t16 ^ t5); \\\n\tz1   = t12 + (t2 ^ t19); \\\n\tz2   = t13 + (t16 ^ t3); \\\n\tz3   = t14 + (t0 ^ t18); \\\n\tz4   = t15 + (t1 ^ t17); \\\n}\n\n/**\n * The core transformation. Process a 512-bit block.\n *\n * @param hash algorithm state\n * @param block the message block to process\n */\nstatic void rhash_edonr256_process_block(unsigned hash[16], const unsigned* block, size_t count)\n{\n\twhile (1) {\n\t\tuint32_t t0,  t1,  t2,  t3,  t4,  t5,  t6,  t7;\n\t\tuint32_t t8,  t9, t10, t11, t12, t13, t14, t15;\n\t\tuint32_t t16, t17,t18, t19, t20, t21, t22, t23;\n\t\tuint32_t p16, p17, p18, p19, p20, p21, p22, p23;\n\t\tuint32_t p24, p25, p26, p27, p28, p29, p30, p31;\n\n\t\t/* First row of quasigroup e-transformations */\n\t\tQ256(block[15], block[14], block[13], block[12], block[11], block[10], block[ 9], block[ 8],\n\t\t\tblock[ 0], block[ 1], block[ 2], block[ 3], block[ 4], block[ 5], block[ 6], block[ 7],\n\t\t\tp16, p17, p18, p19, p20, p21, p22, p23);\n\t\tQ256(p16, p17, p18, p19, p20, p21, p22, p23,\n\t\t\tblock[ 8], block[ 9], block[10], block[11], block[12], block[13], block[14], block[15],\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31);\n\n\t\t/* Second row of quasigroup e-transformations */\n\t\tQ256(hash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15],\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23);\n\t\tQ256(p16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31,\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31);\n\n\t\t/* Third row of quasigroup e-transformations */\n\t\tQ256(p16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\thash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23);\n\t\tQ256(p24, p25, p26, p27, p28, p29, p30, p31,\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31);\n\n\t\t/* Fourth row of quasigroup e-transformations */\n\t\tQ256(block[ 7], block[ 6], block[ 5], block[ 4], block[ 3], block[ 2], block[ 1], block[ 0],\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\thash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7]);\n\t\tQ256(hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31,\n\t\t\thash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]);\n\n\t\tif (!--count) return;\n\t\tblock += edonr256_block_size / sizeof(unsigned);\n\t};\n}\n\n/**\n * The core transformation. Process a 1024-bit block.\n *\n * @param hash algorithm state\n * @param block the message block to process\n */\nstatic void rhash_edonr512_process_block(uint64_t hash[16], const uint64_t* block, size_t count)\n{\n\twhile (1) {\n\t\tuint64_t t0,  t1,  t2,  t3,  t4,  t5,  t6,  t7;\n\t\tuint64_t t8,  t9, t10, t11, t12, t13, t14, t15;\n\t\tuint64_t t16, t17,t18, t19, t20, t21, t22, t23;\n\t\tuint64_t p16, p17, p18, p19, p20, p21, p22, p23;\n\t\tuint64_t p24, p25, p26, p27, p28, p29, p30, p31;\n\n\t\t/* First row of quasigroup e-transformations */\n\t\tQ512(block[15], block[14], block[13], block[12], block[11], block[10], block[ 9], block[ 8],\n\t\t\tblock[ 0], block[ 1], block[ 2], block[ 3], block[ 4], block[ 5], block[ 6], block[ 7],\n\t\t\tp16, p17, p18, p19, p20, p21, p22, p23);\n\t\tQ512(p16, p17, p18, p19, p20, p21, p22, p23,\n\t\t\tblock[ 8], block[ 9], block[10], block[11], block[12], block[13], block[14], block[15],\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31);\n\n\t\t/* Second row of quasigroup e-transformations */\n\t\tQ512(hash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15],\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23);\n\t\tQ512(p16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31,\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31);\n\n\t\t/* Third row of quasigroup e-transformations */\n\t\tQ512(p16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\thash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23);\n\t\tQ512(p24, p25, p26, p27, p28, p29, p30, p31,\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31);\n\n\t\t/* Fourth row of quasigroup e-transformations */\n\t\tQ512(block[ 7], block[ 6], block[ 5], block[ 4], block[ 3], block[ 2], block[ 1], block[ 0],\n\t\t\tp16,  p17, p18, p19, p20, p21, p22, p23,\n\t\t\thash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7]);\n\t\tQ512(hash[ 0], hash[ 1], hash[ 2], hash[ 3], hash[ 4], hash[ 5], hash[ 6], hash[ 7],\n\t\t\tp24, p25, p26, p27, p28, p29, p30, p31,\n\t\t\thash[ 8], hash[ 9], hash[10], hash[11], hash[12], hash[13], hash[14], hash[15]);\n\n\t\tif (!--count) return;\n\t\tblock += edonr512_block_size / sizeof(uint64_t);\n\t};\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_edonr256_update(edonr_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tsize_t index = (size_t)ctx->length & 63;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tsize_t left = edonr256_block_size - index;\n\t\tle32_copy(ctx->u.data256.message, index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\n\tif (size >= edonr256_block_size) {\n#if defined(CPU_IA32) || defined(CPU_X64)\n\t\tif (1)\n#else\n\t\tif (IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg))\n#endif\n\t\t{\n\t\t\t/* the most common case is processing a 32-bit aligned message\n\t\t\ton a little-endian CPU without copying it */\n\t\t\tsize_t count = size / edonr256_block_size;\n\t\t\trhash_edonr256_process_block(ctx->u.data256.hash, (unsigned*)msg, count);\n\t\t\tmsg  += edonr256_block_size * count;\n\t\t\tsize -= edonr256_block_size * count;\n\t\t} else {\n\t\t\tdo {\n\t\t\t\tle32_copy(ctx->u.data256.message, 0, msg, edonr256_block_size);\n\t\t\t\trhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);\n\t\t\t\tmsg  += edonr256_block_size;\n\t\t\t\tsize -= edonr256_block_size;\n\t\t\t} while (size >= edonr256_block_size);\n\t\t}\n\t}\n\n\tif (size) {\n\t\tle32_copy(ctx->u.data256.message, 0, msg, size); /* save leftovers */\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_edonr256_final(edonr_ctx* ctx, unsigned char* result)\n{\n\tsize_t index = ((unsigned)ctx->length & 63) >> 2;\n\tunsigned shift = ((unsigned)ctx->length & 3) * 8;\n\n\t/* pad message and run for the last block */\n\n\t/* append the byte 0x80 to the message */\n\tctx->u.data256.message[index]   &= ~(0xFFFFFFFFu << shift);\n\tctx->u.data256.message[index++] ^= 0x80u << shift;\n\n\t/* if no room left in the message to store 64-bit message length */\n\tif (index > 14) {\n\t\t/* then fill the rest with zeros and process it */\n\t\twhile (index < 16) {\n\t\t\tctx->u.data256.message[index++] = 0;\n\t\t}\n\t\trhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);\n\t\tindex = 0;\n\t}\n\twhile (index < 14) {\n\t\tctx->u.data256.message[index++] = 0;\n\t}\n\t/* store message length in bits */\n\tctx->u.data256.message[14] = (unsigned)(ctx->length << 3);\n\tctx->u.data256.message[15] = (unsigned)(ctx->length >> 29);\n\trhash_edonr256_process_block(ctx->u.data256.hash, ctx->u.data256.message, 1);\n\n\tif (result) {\n\t\t/* copy last bytes of intermidiate hash */\n\t\tint off = (ctx->digest_length <= 256 ? 64 : 128) - ctx->digest_length;\n\t\tle32_copy(result, 0, ((char*)ctx->u.data256.hash) + off, ctx->digest_length);\n\t}\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_edonr512_update(edonr_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tsize_t index = (size_t)ctx->length & 127;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tsize_t left = edonr512_block_size - index;\n\t\tle64_copy(ctx->u.data512.message, index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\tif (size >= edonr512_block_size) {\n#if defined(CPU_IA32) || defined(CPU_X64)\n\t\tif (1)\n#else\n\t\tif (IS_LITTLE_ENDIAN && IS_ALIGNED_64(msg))\n#endif\n\t\t{\n\t\t\t/* the most common case is processing a 64-bit aligned message\n\t\t\ton a little-endian CPU without copying it */\n\t\t\tsize_t count = size / edonr512_block_size;\n\t\t\trhash_edonr512_process_block(ctx->u.data512.hash, (uint64_t*)msg, count);\n\t\t\tmsg  += edonr512_block_size * count;\n\t\t\tsize -= edonr512_block_size * count;\n\t\t} else {\n\t\t\tdo {\n\t\t\t\tle64_copy(ctx->u.data512.message, 0, msg, edonr512_block_size);\n\t\t\t\trhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);\n\t\t\t\tmsg  += edonr512_block_size;\n\t\t\t\tsize -= edonr512_block_size;\n\t\t\t} while (size >= edonr512_block_size);\n\t\t}\n\t}\n\n\tif (size) {\n\t\tle64_copy(ctx->u.data512.message, 0, msg, size); /* save leftovers */\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_edonr512_final(edonr_ctx* ctx, unsigned char* result)\n{\n\tsize_t index = ((unsigned)ctx->length & 127) >> 3;\n\tunsigned shift = ((unsigned)ctx->length & 7) * 8;\n\n\t/* pad message and run for the last block */\n\n\t/* append the byte 0x80 to the message */\n\tctx->u.data512.message[index]   &= ~(I64(0xFFFFFFFFFFFFFFFF) << shift);\n\tctx->u.data512.message[index++] ^= I64(0x80) << shift;\n\n\t/* if no room left in the message to store 64-bit message length */\n\tif (index == 16) {\n\t\trhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);\n\t\tindex = 0;\n\t}\n\twhile (index < 15) {\n\t\tctx->u.data512.message[index++] = 0;\n\t}\n\t/* store message length in bits */\n\tctx->u.data512.message[15] = ctx->length << 3;\n\trhash_edonr512_process_block(ctx->u.data512.hash, ctx->u.data512.message, 1);\n\n\tif (result) {\n\t\t/* copy last bytes of intermidiate hash */\n\t\tint off = edonr512_block_size - ctx->digest_length;\n\t\tle64_copy(result, 0, ((char*)ctx->u.data512.hash) + off, ctx->digest_length);\n\t}\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/edonr.h",
    "content": "﻿/* edonr.h EDON-R 224/256/384/512 hash functions */\n#ifndef EDONR_H\n#define EDONR_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define edonr224_hash_size  28\n#define edonr256_hash_size  32\n#define edonr256_block_size 64\n\n#define edonr384_hash_size  48\n#define edonr512_hash_size  64\n#define edonr512_block_size 128\n\nstruct edonr256_data {\n\tunsigned message[16];  /* 512-bit buffer for leftovers */\n\tunsigned hash[16];     /* 512-bit algorithm internal hashing state */\n};\n\nstruct edonr512_data {\n\tuint64_t message[16];  /* 1024-bit buffer for leftovers */\n\tuint64_t hash[16];     /* 1024-bit algorithm internal hashing state */\n};\n\n/* algorithm context */\ntypedef struct edonr_ctx\n{\n\tunion {\n\t\tstruct edonr256_data data256;\n\t\tstruct edonr512_data data512;\n\t} u;\n\tuint64_t length;        /* number of processed bytes */\n\tunsigned digest_length; /* length of the algorithm digest in bytes */\n} edonr_ctx;\n\nvoid rhash_edonr224_init(edonr_ctx* ctx);\nvoid rhash_edonr256_init(edonr_ctx* ctx);\nvoid rhash_edonr256_update(edonr_ctx* ctx, const unsigned char* data, size_t length);\nvoid rhash_edonr256_final(edonr_ctx* ctx, unsigned char* result);\n\nvoid rhash_edonr384_init(edonr_ctx* ctx);\nvoid rhash_edonr512_init(edonr_ctx* ctx);\nvoid rhash_edonr512_update(edonr_ctx* ctx, const unsigned char* data, size_t length);\nvoid rhash_edonr512_final(edonr_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* EDONR_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/gost12.c",
    "content": "﻿/* gost12.c - an implementation of the GOST R 34.11-2012 hash function,\n * the Russian cryptographic standard.\n * See also RFC 6986.\n *\n * Copyright (c) 2019, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"gost12.h\"\n#include <string.h>\n#include \"byte_order.h\"\n\n#if defined(__GNUC__) && defined(CPU_IA32) && !defined(__clang__) && !defined(RHASH_NO_ASM)\n# define USE_GCC_ASM_IA32\n#elif defined(__GNUC__) && defined(CPU_X64) && !defined(RHASH_NO_ASM)\n# define USE_GCC_ASM_X64\n#endif\n\nALIGN_ATTR(64)\nstatic const uint64_t TR[8][256] =\n{\n\t{\n\t\tI64(0xD01F715B5C7EF8E6),I64(0x16FA240980778325),I64(0xA8A42E857EE049C8),I64(0x6AC1068FA186465B),\n\t\tI64(0x6E417BD7A2E9320B),I64(0x665C8167A437DAAB),I64(0x7666681AA89617F6),I64(0x4B959163700BDCF5),\n\t\tI64(0xF14BE6B78DF36248),I64(0xC585BD689A625CFF),I64(0x9557D7FCA67D82CB),I64(0x89F0B969AF6DD366),\n\t\tI64(0xB0833D48749F6C35),I64(0xA1998C23B1ECBC7C),I64(0x8D70C431AC02A736),I64(0xD6DFBC2FD0A8B69E),\n\t\tI64(0x37AEB3E551FA198B),I64(0x0B7D128A40B5CF9C),I64(0x5A8F2008B5780CBC),I64(0xEDEC882284E333E5),\n\t\tI64(0xD25FC177D3C7C2CE),I64(0x5E0F5D50B61778EC),I64(0x1D873683C0C24CB9),I64(0xAD040BCBB45D208C),\n\t\tI64(0x2F89A0285B853C76),I64(0x5732FFF6791B8D58),I64(0x3E9311439EF6EC3F),I64(0xC9183A809FD3C00F),\n\t\tI64(0x83ADF3F5260A01EE),I64(0xA6791941F4E8EF10),I64(0x103AE97D0CA1CD5D),I64(0x2CE948121DEE1B4A),\n\t\tI64(0x39738421DBF2BF53),I64(0x093DA2A6CF0CF5B4),I64(0xCD9847D89CBCB45F),I64(0xF9561C078B2D8AE8),\n\t\tI64(0x9C6A755A6971777F),I64(0xBC1EBAA0712EF0C5),I64(0x72E61542ABF963A6),I64(0x78BB5FDE229EB12E),\n\t\tI64(0x14BA94250FCEB90D),I64(0x844D6697630E5282),I64(0x98EA08026A1E032F),I64(0xF06BBEA144217F5C),\n\t\tI64(0xDB6263D11CCB377A),I64(0x641C314B2B8EE083),I64(0x320E96AB9B4770CF),I64(0x1EE7DEB986A96B85),\n\t\tI64(0xE96CF57A878C47B5),I64(0xFDD6615F8842FEB8),I64(0xC83862965601DD1B),I64(0x2EA9F83E92572162),\n\t\tI64(0xF876441142FF97FC),I64(0xEB2C455608357D9D),I64(0x5612A7E0B0C9904C),I64(0x6C01CBFB2D500823),\n\t\tI64(0x4548A6A7FA037A2D),I64(0xABC4C6BF388B6EF4),I64(0xBADE77D4FDF8BEBD),I64(0x799B07C8EB4CAC3A),\n\t\tI64(0x0C9D87E805B19CF0),I64(0xCB588AAC106AFA27),I64(0xEA0C1D40C1E76089),I64(0x2869354A1E816F1A),\n\t\tI64(0xFF96D17307FBC490),I64(0x9F0A9D602F1A5043),I64(0x96373FC6E016A5F7),I64(0x5292DAB8B3A6E41C),\n\t\tI64(0x9B8AE0382C752413),I64(0x4F15EC3B7364A8A5),I64(0x3FB349555724F12B),I64(0xC7C50D4415DB66D7),\n\t\tI64(0x92B7429EE379D1A7),I64(0xD37F99611A15DFDA),I64(0x231427C05E34A086),I64(0xA439A96D7B51D538),\n\t\tI64(0xB403401077F01865),I64(0xDDA2AEA5901D7902),I64(0x0A5D4A9C8967D288),I64(0xC265280ADF660F93),\n\t\tI64(0x8BB0094520D4E94E),I64(0x2A29856691385532),I64(0x42A833C5BF072941),I64(0x73C64D54622B7EB2),\n\t\tI64(0x07E095624504536C),I64(0x8A905153E906F45A),I64(0x6F6123C16B3B2F1F),I64(0xC6E55552DC097BC3),\n\t\tI64(0x4468FEB133D16739),I64(0xE211E7F0C7398829),I64(0xA2F96419F7879B40),I64(0x19074BDBC3AD38E9),\n\t\tI64(0xF4EBC3F9474E0B0C),I64(0x43886BD376D53455),I64(0xD8028BEB5AA01046),I64(0x51F23282F5CDC320),\n\t\tI64(0xE7B1C2BE0D84E16D),I64(0x081DFAB006DEE8A0),I64(0x3B33340D544B857B),I64(0x7F5BCABC679AE242),\n\t\tI64(0x0EDD37C48A08A6D8),I64(0x81ED43D9A9B33BC6),I64(0xB1A3655EBD4D7121),I64(0x69A1EEB5E7ED6167),\n\t\tI64(0xF6AB73D5C8F73124),I64(0x1A67A3E185C61FD5),I64(0x2DC91004D43C065E),I64(0x0240B02C8FB93A28),\n\t\tI64(0x90F7F2B26CC0EB8F),I64(0x3CD3A16F114FD617),I64(0xAAE49EA9F15973E0),I64(0x06C0CD748CD64E78),\n\t\tI64(0xDA423BC7D5192A6E),I64(0xC345701C16B41287),I64(0x6D2193EDE4821537),I64(0xFCF639494190E3AC),\n\t\tI64(0x7C3B228621F1C57E),I64(0xFB16AC2B0494B0C0),I64(0xBF7E529A3745D7F9),I64(0x6881B6A32E3F7C73),\n\t\tI64(0xCA78D2BAD9B8E733),I64(0xBBFE2FC2342AA3A9),I64(0x0DBDDFFECC6381E4),I64(0x70A6A56E2440598E),\n\t\tI64(0xE4D12A844BEFC651),I64(0x8C509C2765D0BA22),I64(0xEE8C6018C28814D9),I64(0x17DA7C1F49A59E31),\n\t\tI64(0x609C4C1328E194D3),I64(0xB3E3D57232F44B09),I64(0x91D7AAA4A512F69B),I64(0x0FFD6FD243DABBCC),\n\t\tI64(0x50D26A943C1FDE34),I64(0x6BE15E9968545B4F),I64(0x94778FEA6FAF9FDF),I64(0x2B09DD7058EA4826),\n\t\tI64(0x677CD9716DE5C7BF),I64(0x49D5214FFFB2E6DD),I64(0x0360E83A466B273C),I64(0x1FC786AF4F7B7691),\n\t\tI64(0xA0B9D435783EA168),I64(0xD49F0C035F118CB6),I64(0x01205816C9D21D14),I64(0xAC2453DD7D8F3D98),\n\t\tI64(0x545217CC3F70AA64),I64(0x26B4028E9489C9C2),I64(0xDEC2469FD6765E3E),I64(0x04807D58036F7450),\n\t\tI64(0xE5F17292823DDB45),I64(0xF30B569B024A5860),I64(0x62DCFC3FA758AEFB),I64(0xE84CAD6C4E5E5AA1),\n\t\tI64(0xCCB81FCE556EA94B),I64(0x53B282AE7A74F908),I64(0x1B47FBF74C1402C1),I64(0x368EEBF39828049F),\n\t\tI64(0x7AFBEFF2AD278B06),I64(0xBE5E0A8CFE97CAED),I64(0xCFD8F7F413058E77),I64(0xF78B2BC301252C30),\n\t\tI64(0x4D555C17FCDD928D),I64(0x5F2F05467FC565F8),I64(0x24F4B2A21B30F3EA),I64(0x860DD6BBECB768AA),\n\t\tI64(0x4C750401350F8F99),I64(0x0000000000000000),I64(0xECCCD0344D312EF1),I64(0xB5231806BE220571),\n\t\tI64(0xC105C030990D28AF),I64(0x653C695DE25CFD97),I64(0x159ACC33C61CA419),I64(0xB89EC7F872418495),\n\t\tI64(0xA9847693B73254DC),I64(0x58CF90243AC13694),I64(0x59EFC832F3132B80),I64(0x5C4FED7C39AE42C4),\n\t\tI64(0x828DABE3EFD81CFA),I64(0xD13F294D95ACE5F2),I64(0x7D1B7A90E823D86A),I64(0xB643F03CF849224D),\n\t\tI64(0x3DF3F979D89DCB03),I64(0x7426D836272F2DDE),I64(0xDFE21E891FA4432A),I64(0x3A136C1B9D99986F),\n\t\tI64(0xFA36F43DCD46ADD4),I64(0xC025982650DF35BB),I64(0x856D3E81AADC4F96),I64(0xC4A5E57E53B041EB),\n\t\tI64(0x4708168B75BA4005),I64(0xAF44BBE73BE41AA4),I64(0x971767D029C4B8E3),I64(0xB9BE9FEEBB939981),\n\t\tI64(0x215497ECD18D9AAE),I64(0x316E7E91DD2C57F3),I64(0xCEF8AFE2DAD79363),I64(0x3853DC371220A247),\n\t\tI64(0x35EE03C9DE4323A3),I64(0xE6919AA8C456FC79),I64(0xE05157DC4880B201),I64(0x7BDBB7E464F59612),\n\t\tI64(0x127A59518318F775),I64(0x332ECEBD52956DDB),I64(0x8F30741D23BB9D1E),I64(0xD922D3FD93720D52),\n\t\tI64(0x7746300C61440AE2),I64(0x25D4EAB4D2E2EEFE),I64(0x75068020EEFD30CA),I64(0x135A01474ACAEA61),\n\t\tI64(0x304E268714FE4AE7),I64(0xA519F17BB283C82C),I64(0xDC82F6B359CF6416),I64(0x5BAF781E7CAA11A8),\n\t\tI64(0xB2C38D64FB26561D),I64(0x34CE5BDF17913EB7),I64(0x5D6FB56AF07C5FD0),I64(0x182713CD0A7F25FD),\n\t\tI64(0x9E2AC576E6C84D57),I64(0x9AAAB82EE5A73907),I64(0xA3D93C0F3E558654),I64(0x7E7B92AAAE48FF56),\n\t\tI64(0x872D8EAD256575BE),I64(0x41C8DBFFF96C0E7D),I64(0x99CA5014A3CC1E3B),I64(0x40E883E930BE1369),\n\t\tI64(0x1CA76E95091051AD),I64(0x4E35B42DBAB6B5B1),I64(0x05A0254ECABD6944),I64(0xE1710FCA8152AF15),\n\t\tI64(0xF22B0E8DCB984574),I64(0xB763A82A319B3F59),I64(0x63FCA4296E8AB3EF),I64(0x9D4A2D4CA0A36A6B),\n\t\tI64(0xE331BFE60EEB953D),I64(0xD5BF541596C391A2),I64(0xF5CB9BEF8E9C1618),I64(0x46284E9DBC685D11),\n\t\tI64(0x2074CFFA185F87BA),I64(0xBD3EE2B6B8FCEDD1),I64(0xAE64E3F1F23607B0),I64(0xFEB68965CE29D984),\n\t\tI64(0x55724FDAF6A2B770),I64(0x29496D5CD753720E),I64(0xA75941573D3AF204),I64(0x8E102C0BEA69800A),\n\t\tI64(0x111AB16BC573D049),I64(0xD7FFE439197AAB8A),I64(0xEFAC380E0B5A09CD),I64(0x48F579593660FBC9),\n\t\tI64(0x22347FD697E6BD92),I64(0x61BC1405E13389C7),I64(0x4AB5C975B9D9C1E1),I64(0x80CD1BCF606126D2),\n\t\tI64(0x7186FD78ED92449A),I64(0x93971A882AABCCB3),I64(0x88D0E17F66BFCE72),I64(0x27945A985D5BD4D6)\n\t},\n\t{\n\t\tI64(0xDE553F8C05A811C8),I64(0x1906B59631B4F565),I64(0x436E70D6B1964FF7),I64(0x36D343CB8B1E9D85),\n\t\tI64(0x843DFACC858AAB5A),I64(0xFDFC95C299BFC7F9),I64(0x0F634BDEA1D51FA2),I64(0x6D458B3B76EFB3CD),\n\t\tI64(0x85C3F77CF8593F80),I64(0x3C91315FBE737CB2),I64(0x2148B03366ACE398),I64(0x18F8B8264C6761BF),\n\t\tI64(0xC830C1C495C9FB0F),I64(0x981A76102086A0AA),I64(0xAA16012142F35760),I64(0x35CC54060C763CF6),\n\t\tI64(0x42907D66CC45DB2D),I64(0x8203D44B965AF4BC),I64(0x3D6F3CEFC3A0E868),I64(0xBC73FF69D292BDA7),\n\t\tI64(0x8722ED0102E20A29),I64(0x8F8185E8CD34DEB7),I64(0x9B0561DDA7EE01D9),I64(0x5335A0193227FAD6),\n\t\tI64(0xC9CECC74E81A6FD5),I64(0x54F5832E5C2431EA),I64(0x99E47BA05D553470),I64(0xF7BEE756ACD226CE),\n\t\tI64(0x384E05A5571816FD),I64(0xD1367452A47D0E6A),I64(0xF29FDE1C386AD85B),I64(0x320C77316275F7CA),\n\t\tI64(0xD0C879E2D9AE9AB0),I64(0xDB7406C69110EF5D),I64(0x45505E51A2461011),I64(0xFC029872E46C5323),\n\t\tI64(0xFA3CB6F5F7BC0CC5),I64(0x031F17CD8768A173),I64(0xBD8DF2D9AF41297D),I64(0x9D3B4F5AB43E5E3F),\n\t\tI64(0x4071671B36FEEE84),I64(0x716207E7D3E3B83D),I64(0x48D20FF2F9283A1A),I64(0x27769EB4757CBC7E),\n\t\tI64(0x5C56EBC793F2E574),I64(0xA48B474F9EF5DC18),I64(0x52CBADA94FF46E0C),I64(0x60C7DA982D8199C6),\n\t\tI64(0x0E9D466EDC068B78),I64(0x4EEC2175EAF865FC),I64(0x550B8E9E21F7A530),I64(0x6B7BA5BC653FEC2B),\n\t\tI64(0x5EB7F1BA6949D0DD),I64(0x57EA94E3DB4C9099),I64(0xF640EAE6D101B214),I64(0xDD4A284182C0B0BB),\n\t\tI64(0xFF1D8FBF6304F250),I64(0xB8ACCB933BF9D7E8),I64(0xE8867C478EB68C4D),I64(0x3F8E2692391BDDC1),\n\t\tI64(0xCB2FD60912A15A7C),I64(0xAEC935DBAB983D2F),I64(0xF55FFD2B56691367),I64(0x80E2CE366CE1C115),\n\t\tI64(0x179BF3F8EDB27E1D),I64(0x01FE0DB07DD394DA),I64(0xDA8A0B76ECC37B87),I64(0x44AE53E1DF9584CB),\n\t\tI64(0xB310B4B77347A205),I64(0xDFAB323C787B8512),I64(0x3B511268D070B78E),I64(0x65E6E3D2B9396753),\n\t\tI64(0x6864B271E2574D58),I64(0x259784C98FC789D7),I64(0x02E11A7DFABB35A9),I64(0x8841A6DFA337158B),\n\t\tI64(0x7ADE78C39B5DCDD0),I64(0xB7CF804D9A2CC84A),I64(0x20B6BD831B7F7742),I64(0x75BD331D3A88D272),\n\t\tI64(0x418F6AAB4B2D7A5E),I64(0xD9951CBB6BABDAF4),I64(0xB6318DFDE7FF5C90),I64(0x1F389B112264AA83),\n\t\tI64(0x492C024284FBAEC0),I64(0xE33A0363C608F9A0),I64(0x2688930408AF28A4),I64(0xC7538A1A341CE4AD),\n\t\tI64(0x5DA8E677EE2171AE),I64(0x8C9E92254A5C7FC4),I64(0x63D8CD55AAE938B5),I64(0x29EBD8DAA97A3706),\n\t\tI64(0x959827B37BE88AA1),I64(0x1484E4356ADADF6E),I64(0xA7945082199D7D6B),I64(0xBF6CE8A455FA1CD4),\n\t\tI64(0x9CC542EAC9EDCAE5),I64(0x79C16F0E1C356CA3),I64(0x89BFAB6FDEE48151),I64(0xD4174D1830C5F0FF),\n\t\tI64(0x9258048415EB419D),I64(0x6139D72850520D1C),I64(0x6A85A80C18EC78F1),I64(0xCD11F88E0171059A),\n\t\tI64(0xCCEFF53E7CA29140),I64(0xD229639F2315AF19),I64(0x90B91EF9EF507434),I64(0x5977D28D074A1BE1),\n\t\tI64(0x311360FCE51D56B9),I64(0xC093A92D5A1F2F91),I64(0x1A19A25BB6DC5416),I64(0xEB996B8A09DE2D3E),\n\t\tI64(0xFEE3820F1ED7668A),I64(0xD7085AD5B7AD518C),I64(0x7FFF41890FE53345),I64(0xEC5948BD67DDE602),\n\t\tI64(0x2FD5F65DBAAA68E0),I64(0xA5754AFFE32648C2),I64(0xF8DDAC880D07396C),I64(0x6FA491468C548664),\n\t\tI64(0x0C7C5C1326BDBED1),I64(0x4A33158F03930FB3),I64(0x699ABFC19F84D982),I64(0xE4FA2054A80B329C),\n\t\tI64(0x6707F9AF438252FA),I64(0x08A368E9CFD6D49E),I64(0x47B1442C58FD25B8),I64(0xBBB3DC5EBC91769B),\n\t\tI64(0x1665FE489061EAC7),I64(0x33F27A811FA66310),I64(0x93A609346838D547),I64(0x30ED6D4C98CEC263),\n\t\tI64(0x1DD9816CD8DF9F2A),I64(0x94662A03063B1E7B),I64(0x83FDD9FBEB896066),I64(0x7B207573E68E590A),\n\t\tI64(0x5F49FC0A149A4407),I64(0x343259B671A5A82C),I64(0xFBC2BB458A6F981F),I64(0xC272B350A0A41A38),\n\t\tI64(0x3AAF1FD8ADA32354),I64(0x6CBB868B0B3C2717),I64(0xA2B569C88D2583FE),I64(0xF180C9D1BF027928),\n\t\tI64(0xAF37386BD64BA9F5),I64(0x12BACAB2790A8088),I64(0x4C0D3B0810435055),I64(0xB2EEB9070E9436DF),\n\t\tI64(0xC5B29067CEA7D104),I64(0xDCB425F1FF132461),I64(0x4F122CC5972BF126),I64(0xAC282FA651230886),\n\t\tI64(0xE7E537992F6393EF),I64(0xE61B3A2952B00735),I64(0x709C0A57AE302CE7),I64(0xE02514AE416058D3),\n\t\tI64(0xC44C9DD7B37445DE),I64(0x5A68C5408022BA92),I64(0x1C278CDCA50C0BF0),I64(0x6E5A9CF6F18712BE),\n\t\tI64(0x86DCE0B17F319EF3),I64(0x2D34EC2040115D49),I64(0x4BCD183F7E409B69),I64(0x2815D56AD4A9A3DC),\n\t\tI64(0x24698979F2141D0D),I64(0x0000000000000000),I64(0x1EC696A15FB73E59),I64(0xD86B110B16784E2E),\n\t\tI64(0x8E7F8858B0E74A6D),I64(0x063E2E8713D05FE6),I64(0xE2C40ED3BBDB6D7A),I64(0xB1F1AECA89FC97AC),\n\t\tI64(0xE1DB191E3CB3CC09),I64(0x6418EE62C4EAF389),I64(0xC6AD87AA49CF7077),I64(0xD6F65765CA7EC556),\n\t\tI64(0x9AFB6C6DDA3D9503),I64(0x7CE05644888D9236),I64(0x8D609F95378FEB1E),I64(0x23A9AA4E9C17D631),\n\t\tI64(0x6226C0E5D73AAC6F),I64(0x56149953A69F0443),I64(0xEEB852C09D66D3AB),I64(0x2B0AC2A753C102AF),\n\t\tI64(0x07C023376E03CB3C),I64(0x2CCAE1903DC2C993),I64(0xD3D76E2F5EC63BC3),I64(0x9E2458973356FF4C),\n\t\tI64(0xA66A5D32644EE9B1),I64(0x0A427294356DE137),I64(0x783F62BE61E6F879),I64(0x1344C70204D91452),\n\t\tI64(0x5B96C8F0FDF12E48),I64(0xA90916ECC59BF613),I64(0xBE92E5142829880E),I64(0x727D102A548B194E),\n\t\tI64(0x1BE7AFEBCB0FC0CC),I64(0x3E702B2244C8491B),I64(0xD5E940A84D166425),I64(0x66F9F41F3E51C620),\n\t\tI64(0xABE80C913F20C3BA),I64(0xF07EC461C2D1EDF2),I64(0xF361D3AC45B94C81),I64(0x0521394A94B8FE95),\n\t\tI64(0xADD622162CF09C5C),I64(0xE97871F7F3651897),I64(0xF4A1F09B2BBA87BD),I64(0x095D6559B2054044),\n\t\tI64(0x0BBC7F2448BE75ED),I64(0x2AF4CF172E129675),I64(0x157AE98517094BB4),I64(0x9FDA55274E856B96),\n\t\tI64(0x914713499283E0EE),I64(0xB952C623462A4332),I64(0x74433EAD475B46A8),I64(0x8B5EB112245FB4F8),\n\t\tI64(0xA34B6478F0F61724),I64(0x11A5DD7FFE6221FB),I64(0xC16DA49D27CCBB4B),I64(0x76A224D0BDE07301),\n\t\tI64(0x8AA0BCA2598C2022),I64(0x4DF336B86D90C48F),I64(0xEA67663A740DB9E4),I64(0xEF465F70E0B54771),\n\t\tI64(0x39B008152ACB8227),I64(0x7D1E5BF4F55E06EC),I64(0x105BD0CF83B1B521),I64(0x775C2960C033E7DB),\n\t\tI64(0x7E014C397236A79F),I64(0x811CC386113255CF),I64(0xEDA7450D1A0E72D8),I64(0x5889DF3D7A998F3B),\n\t\tI64(0x2E2BFBEDC779FC3A),I64(0xCE0EEF438619A4E9),I64(0x372D4E7BF6CD095F),I64(0x04DF34FAE96B6A4F),\n\t\tI64(0xF923A13870D4ADB6),I64(0xA1AA7E050A4D228D),I64(0xA8F71B5CB84862C9),I64(0xB52E9A306097FDE3),\n\t\tI64(0x0D8251A35B6E2A0B),I64(0x2257A7FEE1C442EB),I64(0x73831D9A29588D94),I64(0x51D4BA64C89CCF7F),\n\t\tI64(0x502AB7D4B54F5BA5),I64(0x97793DCE8153BF08),I64(0xE5042DE4D5D8A646),I64(0x9687307EFC802BD2),\n\t\tI64(0xA05473B5779EB657),I64(0xB4D097801D446939),I64(0xCFF0E2F3FBCA3033),I64(0xC38CBEE0DD778EE2),\n\t\tI64(0x464F499C252EB162),I64(0xCAD1DBB96F72CEA6),I64(0xBA4DD1EEC142E241),I64(0xB00FA37AF42F0376)\n\t},\n\t{\n\t\tI64(0xCCE4CD3AA968B245),I64(0x089D5484E80B7FAF),I64(0x638246C1B3548304),I64(0xD2FE0EC8C2355492),\n\t\tI64(0xA7FBDF7FF2374EEE),I64(0x4DF1600C92337A16),I64(0x84E503EA523B12FB),I64(0x0790BBFD53AB0C4A),\n\t\tI64(0x198A780F38F6EA9D),I64(0x2AB30C8F55EC48CB),I64(0xE0F7FED6B2C49DB5),I64(0xB6ECF3F422CADBDC),\n\t\tI64(0x409C9A541358DF11),I64(0xD3CE8A56DFDE3FE3),I64(0xC3E9224312C8C1A0),I64(0x0D6DFA58816BA507),\n\t\tI64(0xDDF3E1B179952777),I64(0x04C02A42748BB1D9),I64(0x94C2ABFF9F2DECB8),I64(0x4F91752DA8F8ACF4),\n\t\tI64(0x78682BEFB169BF7B),I64(0xE1C77A48AF2FF6C4),I64(0x0C5D7EC69C80CE76),I64(0x4CC1E4928FD81167),\n\t\tI64(0xFEED3D24D9997B62),I64(0x518BB6DFC3A54A23),I64(0x6DBF2D26151F9B90),I64(0xB5BC624B05EA664F),\n\t\tI64(0xE86AAA525ACFE21A),I64(0x4801CED0FB53A0BE),I64(0xC91463E6C00868ED),I64(0x1027A815CD16FE43),\n\t\tI64(0xF67069A0319204CD),I64(0xB04CCC976C8ABCE7),I64(0xC0B9B3FC35E87C33),I64(0xF380C77C58F2DE65),\n\t\tI64(0x50BB3241DE4E2152),I64(0xDF93F490435EF195),I64(0xF1E0D25D62390887),I64(0xAF668BFB1A3C3141),\n\t\tI64(0xBC11B251F00A7291),I64(0x73A5EED47E427D47),I64(0x25BEE3F6EE4C3B2E),I64(0x43CC0BEB34786282),\n\t\tI64(0xC824E778DDE3039C),I64(0xF97D86D98A327728),I64(0xF2B043E24519B514),I64(0xE297EBF7880F4B57),\n\t\tI64(0x3A94A49A98FAB688),I64(0x868516CB68F0C419),I64(0xEFFA11AF0964EE50),I64(0xA4AB4EC0D517F37D),\n\t\tI64(0xA9C6B498547C567A),I64(0x8E18424F80FBBBB6),I64(0x0BCDC53BCF2BC23C),I64(0x137739AAEA3643D0),\n\t\tI64(0x2C1333EC1BAC2FF0),I64(0x8D48D3F0A7DB0625),I64(0x1E1AC3F26B5DE6D7),I64(0xF520F81F16B2B95E),\n\t\tI64(0x9F0F6EC450062E84),I64(0x0130849E1DEB6B71),I64(0xD45E31AB8C7533A9),I64(0x652279A2FD14E43F),\n\t\tI64(0x3209F01E70F1C927),I64(0xBE71A770CAC1A473),I64(0x0E3D6BE7A64B1894),I64(0x7EC8148CFF29D840),\n\t\tI64(0xCB7476C7FAC3BE0F),I64(0x72956A4A63A91636),I64(0x37F95EC21991138F),I64(0x9E3FEA5A4DED45F5),\n\t\tI64(0x7B38BA50964902E8),I64(0x222E580BBDE73764),I64(0x61E253E0899F55E6),I64(0xFC8D2805E352AD80),\n\t\tI64(0x35994BE3235AC56D),I64(0x09ADD01AF5E014DE),I64(0x5E8659A6780539C6),I64(0xB17C48097161D796),\n\t\tI64(0x026015213ACBD6E2),I64(0xD1AE9F77E515E901),I64(0xB7DC776A3F21B0AD),I64(0xABA6A1B96EB78098),\n\t\tI64(0x9BCF4486248D9F5D),I64(0x582666C536455EFD),I64(0xFDBDAC9BFEB9C6F1),I64(0xC47999BE4163CDEA),\n\t\tI64(0x765540081722A7EF),I64(0x3E548ED8EC710751),I64(0x3D041F67CB51BAC2),I64(0x7958AF71AC82D40A),\n\t\tI64(0x36C9DA5C047A78FE),I64(0xED9A048E33AF38B2),I64(0x26EE7249C96C86BD),I64(0x900281BDEBA65D61),\n\t\tI64(0x11172C8BD0FD9532),I64(0xEA0ABF73600434F8),I64(0x42FC8F75299309F3),I64(0x34A9CF7D3EB1AE1C),\n\t\tI64(0x2B838811480723BA),I64(0x5CE64C8742CEEF24),I64(0x1ADAE9B01FD6570E),I64(0x3C349BF9D6BAD1B3),\n\t\tI64(0x82453C891C7B75C0),I64(0x97923A40B80D512B),I64(0x4A61DBF1C198765C),I64(0xB48CE6D518010D3E),\n\t\tI64(0xCFB45C858E480FD6),I64(0xD933CBF30D1E96AE),I64(0xD70EA014AB558E3A),I64(0xC189376228031742),\n\t\tI64(0x9262949CD16D8B83),I64(0xEB3A3BED7DEF5F89),I64(0x49314A4EE6B8CBCF),I64(0xDCC3652F647E4C06),\n\t\tI64(0xDA635A4C2A3E2B3D),I64(0x470C21A940F3D35B),I64(0x315961A157D174B4),I64(0x6672E81DDA3459AC),\n\t\tI64(0x5B76F77A1165E36E),I64(0x445CB01667D36EC8),I64(0xC5491D205C88A69B),I64(0x456C34887A3805B9),\n\t\tI64(0xFFDDB9BAC4721013),I64(0x99AF51A71E4649BF),I64(0xA15BE01CBC7729D5),I64(0x52DB2760E485F7B0),\n\t\tI64(0x8C78576EBA306D54),I64(0xAE560F6507D75A30),I64(0x95F22F6182C687C9),I64(0x71C5FBF54489ABA5),\n\t\tI64(0xCA44F259E728D57E),I64(0x88B87D2CCEBBDC8D),I64(0xBAB18D32BE4A15AA),I64(0x8BE8EC93E99B611E),\n\t\tI64(0x17B713E89EBDF209),I64(0xB31C5D284BAA0174),I64(0xEECA9531148F8521),I64(0xB8D198138481C348),\n\t\tI64(0x8988F9B2D350B7FC),I64(0xB9E11C8D996AA839),I64(0x5A4673E40C8E881F),I64(0x1687977683569978),\n\t\tI64(0xBF4123EED72ACF02),I64(0x4EA1F1B3B513C785),I64(0xE767452BE16F91FF),I64(0x7505D1B730021A7C),\n\t\tI64(0xA59BCA5EC8FC980C),I64(0xAD069EDA20F7E7A3),I64(0x38F4B1BBA231606A),I64(0x60D2D77E94743E97),\n\t\tI64(0x9AFFC0183966F42C),I64(0x248E6768F3A7505F),I64(0xCDD449A4B483D934),I64(0x87B59255751BAF68),\n\t\tI64(0x1BEA6D2E023D3C7F),I64(0x6B1F12455B5FFCAB),I64(0x743555292DE9710D),I64(0xD8034F6D10F5FDDF),\n\t\tI64(0xC6198C9F7BA81B08),I64(0xBB8109ACA3A17EDB),I64(0xFA2D1766AD12CABB),I64(0xC729080166437079),\n\t\tI64(0x9C5FFF7B77269317),I64(0x0000000000000000),I64(0x15D706C9A47624EB),I64(0x6FDF38072FD44D72),\n\t\tI64(0x5FB6DD3865EE52B7),I64(0xA33BF53D86BCFF37),I64(0xE657C1B5FC84FA8E),I64(0xAA962527735CEBE9),\n\t\tI64(0x39C43525BFDA0B1B),I64(0x204E4D2A872CE186),I64(0x7A083ECE8BA26999),I64(0x554B9C9DB72EFBFA),\n\t\tI64(0xB22CD9B656416A05),I64(0x96A2BEDEA5E63A5A),I64(0x802529A826B0A322),I64(0x8115AD363B5BC853),\n\t\tI64(0x8375B81701901EB1),I64(0x3069E53F4A3A1FC5),I64(0xBD2136CFEDE119E0),I64(0x18BAFC91251D81EC),\n\t\tI64(0x1D4A524D4C7D5B44),I64(0x05F0AEDC6960DAA8),I64(0x29E39D3072CCF558),I64(0x70F57F6B5962C0D4),\n\t\tI64(0x989FD53903AD22CE),I64(0xF84D024797D91C59),I64(0x547B1803AAC5908B),I64(0xF0D056C37FD263F6),\n\t\tI64(0xD56EB535919E58D8),I64(0x1C7AD6D351963035),I64(0x2E7326CD2167F912),I64(0xAC361A443D1C8CD2),\n\t\tI64(0x697F076461942A49),I64(0x4B515F6FDC731D2D),I64(0x8AD8680DF4700A6F),I64(0x41AC1ECA0EB3B460),\n\t\tI64(0x7D988533D80965D3),I64(0xA8F6300649973D0B),I64(0x7765C4960AC9CC9E),I64(0x7CA801ADC5E20EA2),\n\t\tI64(0xDEA3700E5EB59AE4),I64(0xA06B6482A19C42A4),I64(0x6A2F96DB46B497DA),I64(0x27DEF6D7D487EDCC),\n\t\tI64(0x463CA5375D18B82A),I64(0xA6CB5BE1EFDC259F),I64(0x53EBA3FEF96E9CC1),I64(0xCE84D81B93A364A7),\n\t\tI64(0xF4107C810B59D22F),I64(0x333974806D1AA256),I64(0x0F0DEF79BBA073E5),I64(0x231EDC95A00C5C15),\n\t\tI64(0xE437D494C64F2C6C),I64(0x91320523F64D3610),I64(0x67426C83C7DF32DD),I64(0x6EEFBC99323F2603),\n\t\tI64(0x9D6F7BE56ACDF866),I64(0x5916E25B2BAE358C),I64(0x7FF89012E2C2B331),I64(0x035091BF2720BD93),\n\t\tI64(0x561B0D22900E4669),I64(0x28D319AE6F279E29),I64(0x2F43A2533C8C9263),I64(0xD09E1BE9F8FE8270),\n\t\tI64(0xF740ED3E2C796FBC),I64(0xDB53DED237D5404C),I64(0x62B2C25FAEBFE875),I64(0x0AFD41A5D2C0A94D),\n\t\tI64(0x6412FD3CE0FF8F4E),I64(0xE3A76F6995E42026),I64(0x6C8FA9B808F4F0E1),I64(0xC2D9A6DD0F23AAD1),\n\t\tI64(0x8F28C6D19D10D0C7),I64(0x85D587744FD0798A),I64(0xA20B71A39B579446),I64(0x684F83FA7C7F4138),\n\t\tI64(0xE507500ADBA4471D),I64(0x3F640A46F19A6C20),I64(0x1247BD34F7DD28A1),I64(0x2D23B77206474481),\n\t\tI64(0x93521002CC86E0F2),I64(0x572B89BC8DE52D18),I64(0xFB1D93F8B0F9A1CA),I64(0xE95A2ECC4724896B),\n\t\tI64(0x3BA420048511DDF9),I64(0xD63E248AB6BEE54B),I64(0x5DD6C8195F258455),I64(0x06A03F634E40673B),\n\t\tI64(0x1F2A476C76B68DA6),I64(0x217EC9B49AC78AF7),I64(0xECAA80102E4453C3),I64(0x14E78257B99D4F9A)\n\t},\n\t{\n\t\tI64(0x20329B2CC87BBA05),I64(0x4F5EB6F86546A531),I64(0xD4F44775F751B6B1),I64(0x8266A47B850DFA8B),\n\t\tI64(0xBB986AA15A6CA985),I64(0xC979EB08F9AE0F99),I64(0x2DA6F447A2375EA1),I64(0x1E74275DCD7D8576),\n\t\tI64(0xBC20180A800BC5F8),I64(0xB4A2F701B2DC65BE),I64(0xE726946F981B6D66),I64(0x48E6C453BF21C94C),\n\t\tI64(0x42CAD9930F0A4195),I64(0xEFA47B64AACCCD20),I64(0x71180A8960409A42),I64(0x8BB3329BF6A44E0C),\n\t\tI64(0xD34C35DE2D36DACC),I64(0xA92F5B7CBC23DC96),I64(0xB31A85AA68BB09C3),I64(0x13E04836A73161D2),\n\t\tI64(0xB24DFC4129C51D02),I64(0x8AE44B70B7DA5ACD),I64(0xE671ED84D96579A7),I64(0xA4BB3417D66F3832),\n\t\tI64(0x4572AB38D56D2DE8),I64(0xB1B47761EA47215C),I64(0xE81C09CF70ABA15D),I64(0xFFBDB872CE7F90AC),\n\t\tI64(0xA8782297FD5DC857),I64(0x0D946F6B6A4CE4A4),I64(0xE4DF1F4F5B995138),I64(0x9EBC71EDCA8C5762),\n\t\tI64(0x0A2C1DC0B02B88D9),I64(0x3B503C115D9D7B91),I64(0xC64376A8111EC3A2),I64(0xCEC199A323C963E4),\n\t\tI64(0xDC76A87EC58616F7),I64(0x09D596E073A9B487),I64(0x14583A9D7D560DAF),I64(0xF4C6DC593F2A0CB4),\n\t\tI64(0xDD21D19584F80236),I64(0x4A4836983DDDE1D3),I64(0xE58866A41AE745F9),I64(0xF591A5B27E541875),\n\t\tI64(0x891DC05074586693),I64(0x5B068C651810A89E),I64(0xA30346BC0C08544F),I64(0x3DBF3751C684032D),\n\t\tI64(0x2A1E86EC785032DC),I64(0xF73F5779FCA830EA),I64(0xB60C05CA30204D21),I64(0x0CC316802B32F065),\n\t\tI64(0x8770241BDD96BE69),I64(0xB861E18199EE95DB),I64(0xF805CAD91418FCD1),I64(0x29E70DCCBBD20E82),\n\t\tI64(0xC7140F435060D763),I64(0x0F3A9DA0E8B0CC3B),I64(0xA2543F574D76408E),I64(0xBD7761E1C175D139),\n\t\tI64(0x4B1F4F737CA3F512),I64(0x6DC2DF1F2FC137AB),I64(0xF1D05C3967B14856),I64(0xA742BF3715ED046C),\n\t\tI64(0x654030141D1697ED),I64(0x07B872ABDA676C7D),I64(0x3CE84EBA87FA17EC),I64(0xC1FB0403CB79AFDF),\n\t\tI64(0x3E46BC7105063F73),I64(0x278AE987121CD678),I64(0xA1ADB4778EF47CD0),I64(0x26DD906C5362C2B9),\n\t\tI64(0x05168060589B44E2),I64(0xFBFC41F9D79AC08F),I64(0x0E6DE44BA9CED8FA),I64(0x9FEB08068BF243A3),\n\t\tI64(0x7B341749D06B129B),I64(0x229C69E74A87929A),I64(0xE09EE6C4427C011B),I64(0x5692E30E725C4C3A),\n\t\tI64(0xDA99A33E5E9F6E4B),I64(0x353DD85AF453A36B),I64(0x25241B4C90E0FEE7),I64(0x5DE987258309D022),\n\t\tI64(0xE230140FC0802984),I64(0x93281E86A0C0B3C6),I64(0xF229D719A4337408),I64(0x6F6C2DD4AD3D1F34),\n\t\tI64(0x8EA5B2FBAE3F0AEE),I64(0x8331DD90C473EE4A),I64(0x346AA1B1B52DB7AA),I64(0xDF8F235E06042AA9),\n\t\tI64(0xCC6F6B68A1354B7B),I64(0x6C95A6F46EBF236A),I64(0x52D31A856BB91C19),I64(0x1A35DED6D498D555),\n\t\tI64(0xF37EAEF2E54D60C9),I64(0x72E181A9A3C2A61C),I64(0x98537AAD51952FDE),I64(0x16F6C856FFAA2530),\n\t\tI64(0xD960281E9D1D5215),I64(0x3A0745FA1CE36F50),I64(0x0B7B642BF1559C18),I64(0x59A87EAE9AEC8001),\n\t\tI64(0x5E100C05408BEC7C),I64(0x0441F98B19E55023),I64(0xD70DCC5534D38AEF),I64(0x927F676DE1BEA707),\n\t\tI64(0x9769E70DB925E3E5),I64(0x7A636EA29115065A),I64(0x468B201816EF11B6),I64(0xAB81A9B73EDFF409),\n\t\tI64(0xC0AC7DE88A07BB1E),I64(0x1F235EB68C0391B7),I64(0x6056B074458DD30F),I64(0xBE8EEAC102F7ED67),\n\t\tI64(0xCD381283E04B5FBA),I64(0x5CBEFECEC277C4E3),I64(0xD21B4C356C48CE0D),I64(0x1019C31664B35D8C),\n\t\tI64(0x247362A7D19EEA26),I64(0xEBE582EFB3299D03),I64(0x02AEF2CB82FC289F),I64(0x86275DF09CE8AAA8),\n\t\tI64(0x28B07427FAAC1A43),I64(0x38A9B7319E1F47CF),I64(0xC82E92E3B8D01B58),I64(0x06EF0B409B1978BC),\n\t\tI64(0x62F842BFC771FB90),I64(0x9904034610EB3B1F),I64(0xDED85AB5477A3E68),I64(0x90D195A663428F98),\n\t\tI64(0x5384636E2AC708D8),I64(0xCBD719C37B522706),I64(0xAE9729D76644B0EB),I64(0x7C8C65E20A0C7EE6),\n\t\tI64(0x80C856B007F1D214),I64(0x8C0B40302CC32271),I64(0xDBCEDAD51FE17A8A),I64(0x740E8AE938DBDEA0),\n\t\tI64(0xA615C6DC549310AD),I64(0x19CC55F6171AE90B),I64(0x49B1BDB8FE5FDD8D),I64(0xED0A89AF2830E5BF),\n\t\tI64(0x6A7AADB4F5A65BD6),I64(0x7E22972988F05679),I64(0xF952B3325566E810),I64(0x39FECEDADF61530E),\n\t\tI64(0x6101C99F04F3C7CE),I64(0x2E5F7F6761B562FF),I64(0xF08725D226CF5C97),I64(0x63AF3B54860FEF51),\n\t\tI64(0x8FF2CB10EF411E2F),I64(0x884AB9BB35267252),I64(0x4DF04433E7BA8DAE),I64(0x9AFD8866D3690741),\n\t\tI64(0x66B9BB34DE94ABB3),I64(0x9BAAF18D92171380),I64(0x543C11C5F0A064A5),I64(0x17A1B1BDBED431F1),\n\t\tI64(0xB5F58EEAF3A2717F),I64(0xC355F6C849858740),I64(0xEC5DF044694EF17E),I64(0xD83751F5DC6346D4),\n\t\tI64(0xFC4433520DFDACF2),I64(0x0000000000000000),I64(0x5A51F58E596EBC5F),I64(0x3285AAF12E34CF16),\n\t\tI64(0x8D5C39DB6DBD36B0),I64(0x12B731DDE64F7513),I64(0x94906C2D7AA7DFBB),I64(0x302B583AACC8E789),\n\t\tI64(0x9D45FACD090E6B3C),I64(0x2165E2C78905AEC4),I64(0x68D45F7F775A7349),I64(0x189B2C1D5664FDCA),\n\t\tI64(0xE1C99F2F030215DA),I64(0x6983269436246788),I64(0x8489AF3B1E148237),I64(0xE94B702431D5B59C),\n\t\tI64(0x33D2D31A6F4ADBD7),I64(0xBFD9932A4389F9A6),I64(0xB0E30E8AAB39359D),I64(0xD1E2C715AFCAF253),\n\t\tI64(0x150F43763C28196E),I64(0xC4ED846393E2EB3D),I64(0x03F98B20C3823C5E),I64(0xFD134AB94C83B833),\n\t\tI64(0x556B682EB1DE7064),I64(0x36C4537A37D19F35),I64(0x7559F30279A5CA61),I64(0x799AE58252973A04),\n\t\tI64(0x9C12832648707FFD),I64(0x78CD9C6913E92EC5),I64(0x1D8DAC7D0EFFB928),I64(0x439DA0784E745554),\n\t\tI64(0x413352B3CC887DCB),I64(0xBACF134A1B12BD44),I64(0x114EBAFD25CD494D),I64(0x2F08068C20CB763E),\n\t\tI64(0x76A07822BA27F63F),I64(0xEAB2FB04F25789C2),I64(0xE3676DE481FE3D45),I64(0x1B62A73D95E6C194),\n\t\tI64(0x641749FF5C68832C),I64(0xA5EC4DFC97112CF3),I64(0xF6682E92BDD6242B),I64(0x3F11C59A44782BB2),\n\t\tI64(0x317C21D1EDB6F348),I64(0xD65AB5BE75AD9E2E),I64(0x6B2DD45FB4D84F17),I64(0xFAAB381296E4D44E),\n\t\tI64(0xD0B5BEFEEEB4E692),I64(0x0882EF0B32D7A046),I64(0x512A91A5A83B2047),I64(0x963E9EE6F85BF724),\n\t\tI64(0x4E09CF132438B1F0),I64(0x77F701C9FB59E2FE),I64(0x7DDB1C094B726A27),I64(0x5F4775EE01F5F8BD),\n\t\tI64(0x9186EC4D223C9B59),I64(0xFEEAC1998F01846D),I64(0xAC39DB1CE4B89874),I64(0xB75B7C21715E59E0),\n\t\tI64(0xAFC0503C273AA42A),I64(0x6E3B543FEC430BF5),I64(0x704F7362213E8E83),I64(0x58FF0745DB9294C0),\n\t\tI64(0x67EEC2DF9FEABF72),I64(0xA0FACD9CCF8A6811),I64(0xB936986AD890811A),I64(0x95C715C63BD9CB7A),\n\t\tI64(0xCA8060283A2C33C7),I64(0x507DE84EE9453486),I64(0x85DED6D05F6A96F6),I64(0x1CDAD5964F81ADE9),\n\t\tI64(0xD5A33E9EB62FA270),I64(0x40642B588DF6690A),I64(0x7F75EEC2C98E42B8),I64(0x2CF18DACE3494A60),\n\t\tI64(0x23CB100C0BF9865B),I64(0xEEF3028FEBB2D9E1),I64(0x4425D2D394133929),I64(0xAAD6D05C7FA1E0C8),\n\t\tI64(0xAD6EA2F7A5C68CB5),I64(0xC2028F2308FB9381),I64(0x819F2F5B468FC6D5),I64(0xC5BAFD88D29CFFFC),\n\t\tI64(0x47DC59F357910577),I64(0x2B49FF07392E261D),I64(0x57C59AE5332258FB),I64(0x73B6F842E2BCB2DD),\n\t\tI64(0xCF96E04862B77725),I64(0x4CA73DD8A6C4996F),I64(0x015779EB417E14C1),I64(0x37932A9176AF8BF4)\n\t},\n\t{\n\t\tI64(0x190A2C9B249DF23E),I64(0x2F62F8B62263E1E9),I64(0x7A7F754740993655),I64(0x330B7BA4D5564D9F),\n\t\tI64(0x4C17A16A46672582),I64(0xB22F08EB7D05F5B8),I64(0x535F47F40BC148CC),I64(0x3AEC5D27D4883037),\n\t\tI64(0x10ED0A1825438F96),I64(0x516101F72C233D17),I64(0x13CC6F949FD04EAE),I64(0x739853C441474BFD),\n\t\tI64(0x653793D90D3F5B1B),I64(0x5240647B96B0FC2F),I64(0x0C84890AD27623E0),I64(0xD7189B32703AAEA3),\n\t\tI64(0x2685DE3523BD9C41),I64(0x99317C5B11BFFEFA),I64(0x0D9BAA854F079703),I64(0x70B93648FBD48AC5),\n\t\tI64(0xA80441FCE30BC6BE),I64(0x7287704BDC36FF1E),I64(0xB65384ED33DC1F13),I64(0xD36417343EE34408),\n\t\tI64(0x39CD38AB6E1BF10F),I64(0x5AB861770A1F3564),I64(0x0EBACF09F594563B),I64(0xD04572B884708530),\n\t\tI64(0x3CAE9722BDB3AF47),I64(0x4A556B6F2F5CBAF2),I64(0xE1704F1F76C4BD74),I64(0x5EC4ED7144C6DFCF),\n\t\tI64(0x16AFC01D4C7810E6),I64(0x283F113CD629CA7A),I64(0xAF59A8761741ED2D),I64(0xEED5A3991E215FAC),\n\t\tI64(0x3BF37EA849F984D4),I64(0xE413E096A56CE33C),I64(0x2C439D3A98F020D1),I64(0x637559DC6404C46B),\n\t\tI64(0x9E6C95D1E5F5D569),I64(0x24BB9836045FE99A),I64(0x44EFA466DAC8ECC9),I64(0xC6EAB2A5C80895D6),\n\t\tI64(0x803B50C035220CC4),I64(0x0321658CBA93C138),I64(0x8F9EBC465DC7EE1C),I64(0xD15A5137190131D3),\n\t\tI64(0x0FA5EC8668E5E2D8),I64(0x91C979578D1037B1),I64(0x0642CA05693B9F70),I64(0xEFCA80168350EB4F),\n\t\tI64(0x38D21B24F36A45EC),I64(0xBEAB81E1AF73D658),I64(0x8CBFD9CAE7542F24),I64(0xFD19CC0D81F11102),\n\t\tI64(0x0AC6430FBB4DBC90),I64(0x1D76A09D6A441895),I64(0x2A01573FF1CBBFA1),I64(0xB572E161894FDE2B),\n\t\tI64(0x8124734FA853B827),I64(0x614B1FDF43E6B1B0),I64(0x68AC395C4238CC18),I64(0x21D837BFD7F7B7D2),\n\t\tI64(0x20C714304A860331),I64(0x5CFAAB726324AA14),I64(0x74C5BA4EB50D606E),I64(0xF3A3030474654739),\n\t\tI64(0x23E671BCF015C209),I64(0x45F087E947B9582A),I64(0xD8BD77B418DF4C7B),I64(0xE06F6C90EBB50997),\n\t\tI64(0x0BD96080263C0873),I64(0x7E03F9410E40DCFE),I64(0xB8E94BE4C6484928),I64(0xFB5B0608E8CA8E72),\n\t\tI64(0x1A2B49179E0E3306),I64(0x4E29E76961855059),I64(0x4F36C4E6FCF4E4BA),I64(0x49740EE395CF7BCA),\n\t\tI64(0xC2963EA386D17F7D),I64(0x90D65AD810618352),I64(0x12D34C1B02A1FA4D),I64(0xFA44258775BB3A91),\n\t\tI64(0x18150F14B9EC46DD),I64(0x1491861E6B9A653D),I64(0x9A1019D7AB2C3FC2),I64(0x3668D42D06FE13D7),\n\t\tI64(0xDCC1FBB25606A6D0),I64(0x969490DD795A1C22),I64(0x3549B1A1BC6DD2EF),I64(0xC94F5E23A0ED770E),\n\t\tI64(0xB9F6686B5B39FDCB),I64(0xC4D4F4A6EFEAE00D),I64(0xE732851A1FFF2204),I64(0x94AAD6DE5EB869F9),\n\t\tI64(0x3F8FF2AE07206E7F),I64(0xFE38A9813B62D03A),I64(0xA7A1AD7A8BEE2466),I64(0x7B6056C8DDE882B6),\n\t\tI64(0x302A1E286FC58CA7),I64(0x8DA0FA457A259BC7),I64(0xB3302B64E074415B),I64(0x5402AE7EFF8B635F),\n\t\tI64(0x08F8050C9CAFC94B),I64(0xAE468BF98A3059CE),I64(0x88C355CCA98DC58F),I64(0xB10E6D67C7963480),\n\t\tI64(0xBAD70DE7E1AA3CF3),I64(0xBFB4A26E320262BB),I64(0xCB711820870F02D5),I64(0xCE12B7A954A75C9D),\n\t\tI64(0x563CE87DD8691684),I64(0x9F73B65E7884618A),I64(0x2B1E74B06CBA0B42),I64(0x47CEC1EA605B2DF1),\n\t\tI64(0x1C698312F735AC76),I64(0x5FDBCEFED9B76B2C),I64(0x831A354C8FB1CDFC),I64(0x820516C312C0791F),\n\t\tI64(0xB74CA762AEADABF0),I64(0xFC06EF821C80A5E1),I64(0x5723CBF24518A267),I64(0x9D4DF05D5F661451),\n\t\tI64(0x588627742DFD40BF),I64(0xDA8331B73F3D39A0),I64(0x17B0E392D109A405),I64(0xF965400BCF28FBA9),\n\t\tI64(0x7C3DBF4229A2A925),I64(0x023E460327E275DB),I64(0x6CD0B55A0CE126B3),I64(0xE62DA695828E96E7),\n\t\tI64(0x42AD6E63B3F373B9),I64(0xE50CC319381D57DF),I64(0xC5CBD729729B54EE),I64(0x46D1E265FD2A9912),\n\t\tI64(0x6428B056904EEFF8),I64(0x8BE23040131E04B7),I64(0x6709D5DA2ADD2EC0),I64(0x075DE98AF44A2B93),\n\t\tI64(0x8447DCC67BFBE66F),I64(0x6616F655B7AC9A23),I64(0xD607B8BDED4B1A40),I64(0x0563AF89D3A85E48),\n\t\tI64(0x3DB1B4AD20C21BA4),I64(0x11F22997B8323B75),I64(0x292032B34B587E99),I64(0x7F1CDACE9331681D),\n\t\tI64(0x8E819FC9C0B65AFF),I64(0xA1E3677FE2D5BB16),I64(0xCD33D225EE349DA5),I64(0xD9A2543B85AEF898),\n\t\tI64(0x795E10CBFA0AF76D),I64(0x25A4BBB9992E5D79),I64(0x78413344677B438E),I64(0xF0826688CEF68601),\n\t\tI64(0xD27B34BBA392F0EB),I64(0x551D8DF162FAD7BC),I64(0x1E57C511D0D7D9AD),I64(0xDEFFBDB171E4D30B),\n\t\tI64(0xF4FEEA8E802F6CAA),I64(0xA480C8F6317DE55E),I64(0xA0FC44F07FA40FF5),I64(0x95B5F551C3C9DD1A),\n\t\tI64(0x22F952336D6476EA),I64(0x0000000000000000),I64(0xA6BE8EF5169F9085),I64(0xCC2CF1AA73452946),\n\t\tI64(0x2E7DDB39BF12550A),I64(0xD526DD3157D8DB78),I64(0x486B2D6C08BECF29),I64(0x9B0F3A58365D8B21),\n\t\tI64(0xAC78CDFAADD22C15),I64(0xBC95C7E28891A383),I64(0x6A927F5F65DAB9C3),I64(0xC3891D2C1BA0CB9E),\n\t\tI64(0xEAA92F9F50F8B507),I64(0xCF0D9426C9D6E87E),I64(0xCA6E3BAF1A7EB636),I64(0xAB25247059980786),\n\t\tI64(0x69B31AD3DF4978FB),I64(0xE2512A93CC577C4C),I64(0xFF278A0EA61364D9),I64(0x71A615C766A53E26),\n\t\tI64(0x89DC764334FC716C),I64(0xF87A638452594F4A),I64(0xF2BC208BE914F3DA),I64(0x8766B94AC1682757),\n\t\tI64(0xBBC82E687CDB8810),I64(0x626A7A53F9757088),I64(0xA2C202F358467A2E),I64(0x4D0882E5DB169161),\n\t\tI64(0x09E7268301DE7DA8),I64(0xE897699C771AC0DC),I64(0xC8507DAC3D9CC3ED),I64(0xC0A878A0A1330AA6),\n\t\tI64(0x978BB352E42BA8C1),I64(0xE9884A13EA6B743F),I64(0x279AFDBABECC28A2),I64(0x047C8C064ED9EAAB),\n\t\tI64(0x507E2278B15289F4),I64(0x599904FBB08CF45C),I64(0xBD8AE46D15E01760),I64(0x31353DA7F2B43844),\n\t\tI64(0x8558FF49E68A528C),I64(0x76FBFC4D92EF15B5),I64(0x3456922E211C660C),I64(0x86799AC55C1993B4),\n\t\tI64(0x3E90D1219A51DA9C),I64(0x2D5CBEB505819432),I64(0x982E5FD48CCE4A19),I64(0xDB9C1238A24C8D43),\n\t\tI64(0xD439FEBECAA96F9B),I64(0x418C0BEF0960B281),I64(0x158EA591F6EBD1DE),I64(0x1F48E69E4DA66D4E),\n\t\tI64(0x8AFD13CF8E6FB054),I64(0xF5E1C9011D5ED849),I64(0xE34E091C5126C8AF),I64(0xAD67EE7530A398F6),\n\t\tI64(0x43B24DEC2E82C75A),I64(0x75DA99C1287CD48D),I64(0x92E81CDB3783F689),I64(0xA3DD217CC537CECD),\n\t\tI64(0x60543C50DE970553),I64(0x93F73F54AAF2426A),I64(0xA91B62737E7A725D),I64(0xF19D4507538732E2),\n\t\tI64(0x77E4DFC20F9EA156),I64(0x7D229CCDB4D31DC6),I64(0x1B346A98037F87E5),I64(0xEDF4C615A4B29E94),\n\t\tI64(0x4093286094110662),I64(0xB0114EE85AE78063),I64(0x6FF1D0D6B672E78B),I64(0x6DCF96D591909250),\n\t\tI64(0xDFE09E3EEC9567E8),I64(0x3214582B4827F97C),I64(0xB46DC2EE143E6AC8),I64(0xF6C0AC8DA7CD1971),\n\t\tI64(0xEBB60C10CD8901E4),I64(0xF7DF8F023ABCAD92),I64(0x9C52D3D2C217A0B2),I64(0x6B8D5CD0F8AB0D20),\n\t\tI64(0x3777F7A29B8FA734),I64(0x011F238F9D71B4E3),I64(0xC1B75B2F3C42BE45),I64(0x5DE588FDFE551EF7),\n\t\tI64(0x6EEEF3592B035368),I64(0xAA3A07FFC4E9B365),I64(0xECEBE59A39C32A77),I64(0x5BA742F8976E8187),\n\t\tI64(0x4B4A48E0B22D0E11),I64(0xDDDED83DCB771233),I64(0xA59FEB79AC0C51BD),I64(0xC7F5912A55792135)\n\t},\n\t{\n\t\tI64(0x6D6AE04668A9B08A),I64(0x3AB3F04B0BE8C743),I64(0xE51E166B54B3C908),I64(0xBE90A9EB35C2F139),\n\t\tI64(0xB2C7066637F2BEC1),I64(0xAA6945613392202C),I64(0x9A28C36F3B5201EB),I64(0xDDCE5A93AB536994),\n\t\tI64(0x0E34133EF6382827),I64(0x52A02BA1EC55048B),I64(0xA2F88F97C4B2A177),I64(0x8640E513CA2251A5),\n\t\tI64(0xCDF1D36258137622),I64(0xFE6CB708DEDF8DDB),I64(0x8A174A9EC8121E5D),I64(0x679896036B81560E),\n\t\tI64(0x59ED033395795FEE),I64(0x1DD778AB8B74EDAF),I64(0xEE533EF92D9F926D),I64(0x2A8C79BAF8A8D8F5),\n\t\tI64(0x6BCF398E69B119F6),I64(0xE20491742FAFDD95),I64(0x276488E0809C2AEC),I64(0xEA955B82D88F5CCE),\n\t\tI64(0x7102C63A99D9E0C4),I64(0xF9763017A5C39946),I64(0x429FA2501F151B3D),I64(0x4659C72BEA05D59E),\n\t\tI64(0x984B7FDCCF5A6634),I64(0xF742232953FBB161),I64(0x3041860E08C021C7),I64(0x747BFD9616CD9386),\n\t\tI64(0x4BB1367192312787),I64(0x1B72A1638A6C44D3),I64(0x4A0E68A6E8359A66),I64(0x169A5039F258B6CA),\n\t\tI64(0xB98A2EF44EDEE5A4),I64(0xD9083FE85E43A737),I64(0x967F6CE239624E13),I64(0x8874F62D3C1A7982),\n\t\tI64(0x3C1629830AF06E3F),I64(0x9165EBFD427E5A8E),I64(0xB5DD81794CEEAA5C),I64(0x0DE8F15A7834F219),\n\t\tI64(0x70BD98EDE3DD5D25),I64(0xACCC9CA9328A8950),I64(0x56664EDA1945CA28),I64(0x221DB34C0F8859AE),\n\t\tI64(0x26DBD637FA98970D),I64(0x1ACDFFB4F068F932),I64(0x4585254F64090FA0),I64(0x72DE245E17D53AFA),\n\t\tI64(0x1546B25D7C546CF4),I64(0x207E0FFFFB803E71),I64(0xFAAAD2732BCF4378),I64(0xB462DFAE36EA17BD),\n\t\tI64(0xCF926FD1AC1B11FD),I64(0xE0672DC7DBA7BA4A),I64(0xD3FA49AD5D6B41B3),I64(0x8BA81449B216A3BC),\n\t\tI64(0x14F9EC8A0650D115),I64(0x40FC1EE3EB1D7CE2),I64(0x23A2ED9B758CE44F),I64(0x782C521B14FDDC7E),\n\t\tI64(0x1C68267CF170504E),I64(0xBCF31558C1CA96E6),I64(0xA781B43B4BA6D235),I64(0xF6FD7DFE29FF0C80),\n\t\tI64(0xB0A4BAD5C3FAD91E),I64(0xD199F51EA963266C),I64(0x414340349119C103),I64(0x5405F269ED4DADF7),\n\t\tI64(0xABD61BB649969DCD),I64(0x6813DBEAE7BDC3C8),I64(0x65FB2AB09F8931D1),I64(0xF1E7FAE152E3181D),\n\t\tI64(0xC1A67CEF5A2339DA),I64(0x7A4FEEA8E0F5BBA1),I64(0x1E0B9ACF05783791),I64(0x5B8EBF8061713831),\n\t\tI64(0x80E53CDBCB3AF8D9),I64(0x7E898BD315E57502),I64(0xC6BCFBF0213F2D47),I64(0x95A38E86B76E942D),\n\t\tI64(0x092E94218D243CBA),I64(0x8339DEBF453622E7),I64(0xB11BE402B9FE64FF),I64(0x57D9100D634177C9),\n\t\tI64(0xCC4E8DB52217CBC3),I64(0x3B0CAE9C71EC7AA2),I64(0xFB158CA451CBFE99),I64(0x2B33276D82AC6514),\n\t\tI64(0x01BF5ED77A04BDE1),I64(0xC5601994AF33F779),I64(0x75C4A3416CC92E67),I64(0xF3844652A6EB7FC2),\n\t\tI64(0x3487E375FDD0EF64),I64(0x18AE430704609EED),I64(0x4D14EFB993298EFB),I64(0x815A620CB13E4538),\n\t\tI64(0x125C354207487869),I64(0x9EEEA614CE42CF48),I64(0xCE2D3106D61FAC1C),I64(0xBBE99247BAD6827B),\n\t\tI64(0x071A871F7B1C149D),I64(0x2E4A1CC10DB81656),I64(0x77A71FF298C149B8),I64(0x06A5D9C80118A97C),\n\t\tI64(0xAD73C27E488E34B1),I64(0x443A7B981E0DB241),I64(0xE3BBCFA355AB6074),I64(0x0AF276450328E684),\n\t\tI64(0x73617A896DD1871B),I64(0x58525DE4EF7DE20F),I64(0xB7BE3DCAB8E6CD83),I64(0x19111DD07E64230C),\n\t\tI64(0x842359A03E2A367A),I64(0x103F89F1F3401FB6),I64(0xDC710444D157D475),I64(0xB835702334DA5845),\n\t\tI64(0x4320FC876511A6DC),I64(0xD026ABC9D3679B8D),I64(0x17250EEE885C0B2B),I64(0x90DAB52A387AE76F),\n\t\tI64(0x31FED8D972C49C26),I64(0x89CBA8FA461EC463),I64(0x2FF5421677BCABB7),I64(0x396F122F85E41D7D),\n\t\tI64(0xA09B332430BAC6A8),I64(0xC888E8CED7070560),I64(0xAEAF201AC682EE8F),I64(0x1180D7268944A257),\n\t\tI64(0xF058A43628E7A5FC),I64(0xBD4C4B8FBBCE2B07),I64(0xA1246DF34ABE7B49),I64(0x7D5569B79BE9AF3C),\n\t\tI64(0xA9B5A705BD9EFA12),I64(0xDB6B835BAA4BC0E8),I64(0x05793BAC8F147342),I64(0x21C1512881848390),\n\t\tI64(0xFDB0556C50D357E5),I64(0x613D4FCB6A99FF72),I64(0x03DCE2648E0CDA3E),I64(0xE949B9E6568386F0),\n\t\tI64(0xFC0F0BBB2AD7EA04),I64(0x6A70675913B5A417),I64(0x7F36D5046FE1C8E3),I64(0x0C57AF8D02304FF8),\n\t\tI64(0x32223ABDFCC84618),I64(0x0891CAF6F720815B),I64(0xA63EEAEC31A26FD4),I64(0x2507345374944D33),\n\t\tI64(0x49D28AC266394058),I64(0xF5219F9AA7F3D6BE),I64(0x2D96FEA583B4CC68),I64(0x5A31E1571B7585D0),\n\t\tI64(0x8ED12FE53D02D0FE),I64(0xDFADE6205F5B0E4B),I64(0x4CABB16EE92D331A),I64(0x04C6657BF510CEA3),\n\t\tI64(0xD73C2CD6A87B8F10),I64(0xE1D87310A1A307AB),I64(0x6CD5BE9112AD0D6B),I64(0x97C032354366F3F2),\n\t\tI64(0xD4E0CEB22677552E),I64(0x0000000000000000),I64(0x29509BDE76A402CB),I64(0xC27A9E8BD42FE3E4),\n\t\tI64(0x5EF7842CEE654B73),I64(0xAF107ECDBC86536E),I64(0x3FCACBE784FCB401),I64(0xD55F90655C73E8CF),\n\t\tI64(0xE6C2F40FDABF1336),I64(0xE8F6E7312C873B11),I64(0xEB2A0555A28BE12F),I64(0xE4A148BC2EB774E9),\n\t\tI64(0x9B979DB84156BC0A),I64(0x6EB60222E6A56AB4),I64(0x87FFBBC4B026EC44),I64(0xC703A5275B3B90A6),\n\t\tI64(0x47E699FC9001687F),I64(0x9C8D1AA73A4AA897),I64(0x7CEA3760E1ED12DD),I64(0x4EC80DDD1D2554C5),\n\t\tI64(0x13E36B957D4CC588),I64(0x5D2B66486069914D),I64(0x92B90999CC7280B0),I64(0x517CC9C56259DEB5),\n\t\tI64(0xC937B619AD03B881),I64(0xEC30824AD997F5B2),I64(0xA45D565FC5AA080B),I64(0xD6837201D27F32F1),\n\t\tI64(0x635EF3789E9198AD),I64(0x531F75769651B96A),I64(0x4F77530A6721E924),I64(0x486DD4151C3DFDB9),\n\t\tI64(0x5F48DAFB9461F692),I64(0x375B011173DC355A),I64(0x3DA9775470F4D3DE),I64(0x8D0DCD81B30E0AC0),\n\t\tI64(0x36E45FC609D888BB),I64(0x55BAACBE97491016),I64(0x8CB29356C90AB721),I64(0x76184125E2C5F459),\n\t\tI64(0x99F4210BB55EDBD5),I64(0x6F095CF59CA1D755),I64(0x9F51F8C3B44672A9),I64(0x3538BDA287D45285),\n\t\tI64(0x50C39712185D6354),I64(0xF23B1885DCEFC223),I64(0x79930CCC6EF9619F),I64(0xED8FDC9DA3934853),\n\t\tI64(0xCB540AAA590BDF5E),I64(0x5C94389F1A6D2CAC),I64(0xE77DAAD8A0BBAED7),I64(0x28EFC5090CA0BF2A),\n\t\tI64(0xBF2FF73C4FC64CD8),I64(0xB37858B14DF60320),I64(0xF8C96EC0DFC724A7),I64(0x828680683F329F06),\n\t\tI64(0x941CD051CD6A29CC),I64(0xC3C5C05CAE2B5E05),I64(0xB601631DC2E27062),I64(0xC01922382027843B),\n\t\tI64(0x24B86A840E90F0D2),I64(0xD245177A276FFC52),I64(0x0F8B4DE98C3C95C6),I64(0x3E759530FEF809E0),\n\t\tI64(0x0B4D2892792C5B65),I64(0xC4DF4743D5374A98),I64(0xA5E20888BFAEB5EA),I64(0xBA56CC90C0D23F9A),\n\t\tI64(0x38D04CF8FFE0A09C),I64(0x62E1ADAFE495254C),I64(0x0263BCB3F40867DF),I64(0xCAEB547D230F62BF),\n\t\tI64(0x6082111C109D4293),I64(0xDAD4DD8CD04F7D09),I64(0xEFEC602E579B2F8C),I64(0x1FB4C4187F7C8A70),\n\t\tI64(0xFFD3E9DFA4DB303A),I64(0x7BF0B07F9AF10640),I64(0xF49EC14DDDF76B5F),I64(0x8F6E713247066D1F),\n\t\tI64(0x339D646A86CCFBF9),I64(0x64447467E58D8C30),I64(0x2C29A072F9B07189),I64(0xD8B7613F24471AD6),\n\t\tI64(0x6627C8D41185EBEF),I64(0xA347D140BEB61C96),I64(0xDE12B8F7255FB3AA),I64(0x9D324470404E1576),\n\t\tI64(0x9306574EB6763D51),I64(0xA80AF9D2C79A47F3),I64(0x859C0777442E8B9B),I64(0x69AC853D9DB97E29)\n\t},\n\t{\n\t\tI64(0xC3407DFC2DE6377E),I64(0x5B9E93EEA4256F77),I64(0xADB58FDD50C845E0),I64(0x5219FF11A75BED86),\n\t\tI64(0x356B61CFD90B1DE9),I64(0xFB8F406E25ABE037),I64(0x7A5A0231C0F60796),I64(0x9D3CD216E1F5020B),\n\t\tI64(0x0C6550FB6B48D8F3),I64(0xF57508C427FF1C62),I64(0x4AD35FFA71CB407D),I64(0x6290A2DA1666AA6D),\n\t\tI64(0xE284EC2349355F9F),I64(0xB3C307C53D7C84EC),I64(0x05E23C0468365A02),I64(0x190BAC4D6C9EBFA8),\n\t\tI64(0x94BBBEE9E28B80FA),I64(0xA34FC777529CB9B5),I64(0xCC7B39F095BCD978),I64(0x2426ADDB0CE532E3),\n\t\tI64(0x7E79329312CE4FC7),I64(0xAB09A72EEBEC2917),I64(0xF8D15499F6B9D6C2),I64(0x1A55B8BABF8C895D),\n\t\tI64(0xDB8ADD17FB769A85),I64(0xB57F2F368658E81B),I64(0x8ACD36F18F3F41F6),I64(0x5CE3B7BBA50F11D3),\n\t\tI64(0x114DCC14D5EE2F0A),I64(0xB91A7FCDED1030E8),I64(0x81D5425FE55DE7A1),I64(0xB6213BC1554ADEEE),\n\t\tI64(0x80144EF95F53F5F2),I64(0x1E7688186DB4C10C),I64(0x3B912965DB5FE1BC),I64(0xC281715A97E8252D),\n\t\tI64(0x54A5D7E21C7F8171),I64(0x4B12535CCBC5522E),I64(0x1D289CEFBEA6F7F9),I64(0x6EF5F2217D2E729E),\n\t\tI64(0xE6A7DC819B0D17CE),I64(0x1B94B41C05829B0E),I64(0x33D7493C622F711E),I64(0xDCF7F942FA5CE421),\n\t\tI64(0x600FBA8B7F7A8ECB),I64(0x46B60F011A83988E),I64(0x235B898E0DCF4C47),I64(0x957AB24F588592A9),\n\t\tI64(0x4354330572B5C28C),I64(0xA5F3EF84E9B8D542),I64(0x8C711E02341B2D01),I64(0x0B1874AE6A62A657),\n\t\tI64(0x1213D8E306FC19FF),I64(0xFE6D7C6A4D9DBA35),I64(0x65ED868F174CD4C9),I64(0x88522EA0E6236550),\n\t\tI64(0x899322065C2D7703),I64(0xC01E690BFEF4018B),I64(0x915982ED8ABDDAF8),I64(0xBE675B98EC3A4E4C),\n\t\tI64(0xA996BF7F82F00DB1),I64(0xE1DAF8D49A27696A),I64(0x2EFFD5D3DC8986E7),I64(0xD153A51F2B1A2E81),\n\t\tI64(0x18CAA0EBD690ADFB),I64(0x390E3134B243C51A),I64(0x2778B92CDFF70416),I64(0x029F1851691C24A6),\n\t\tI64(0x5E7CAFEACC133575),I64(0xFA4E4CC89FA5F264),I64(0x5A5F9F481E2B7D24),I64(0x484C47AB18D764DB),\n\t\tI64(0x400A27F2A1A7F479),I64(0xAEEB9B2A83DA7315),I64(0x721C626879869734),I64(0x042330A2D2384851),\n\t\tI64(0x85F672FD3765AFF0),I64(0xBA446B3A3E02061D),I64(0x73DD6ECEC3888567),I64(0xFFAC70CCF793A866),\n\t\tI64(0xDFA9EDB5294ED2D4),I64(0x6C6AEA7014325638),I64(0x834A5A0E8C41C307),I64(0xCDBA35562FB2CB2B),\n\t\tI64(0x0AD97808D06CB404),I64(0x0F3B440CB85AEE06),I64(0xE5F9C876481F213B),I64(0x98DEEE1289C35809),\n\t\tI64(0x59018BBFCD394BD1),I64(0xE01BF47220297B39),I64(0xDE68E1139340C087),I64(0x9FA3CA4788E926AD),\n\t\tI64(0xBB85679C840C144E),I64(0x53D8F3B71D55FFD5),I64(0x0DA45C5DD146CAA0),I64(0x6F34FE87C72060CD),\n\t\tI64(0x57FBC315CF6DB784),I64(0xCEE421A1FCA0FDDE),I64(0x3D2D0196607B8D4B),I64(0x642C8A29AD42C69A),\n\t\tI64(0x14AFF010BDD87508),I64(0xAC74837BEAC657B3),I64(0x3216459AD821634D),I64(0x3FB219C70967A9ED),\n\t\tI64(0x06BC28F3BB246CF7),I64(0xF2082C9126D562C6),I64(0x66B39278C45EE23C),I64(0xBD394F6F3F2878B9),\n\t\tI64(0xFD33689D9E8F8CC0),I64(0x37F4799EB017394F),I64(0x108CC0B26FE03D59),I64(0xDA4BD1B1417888D6),\n\t\tI64(0xB09D1332EE6EB219),I64(0x2F3ED975668794B4),I64(0x58C0871977375982),I64(0x7561463D78ACE990),\n\t\tI64(0x09876CFF037E82F1),I64(0x7FB83E35A8C05D94),I64(0x26B9B58A65F91645),I64(0xEF20B07E9873953F),\n\t\tI64(0x3148516D0B3355B8),I64(0x41CB2B541BA9E62A),I64(0x790416C613E43163),I64(0xA011D380818E8F40),\n\t\tI64(0x3A5025C36151F3EF),I64(0xD57095BDF92266D0),I64(0x498D4B0DA2D97688),I64(0x8B0C3A57353153A5),\n\t\tI64(0x21C491DF64D368E1),I64(0x8F2F0AF5E7091BF4),I64(0x2DA1C1240F9BB012),I64(0xC43D59A92CCC49DA),\n\t\tI64(0xBFA6573E56345C1F),I64(0x828B56A8364FD154),I64(0x9A41F643E0DF7CAF),I64(0xBCF843C985266AEA),\n\t\tI64(0x2B1DE9D7B4BFDCE5),I64(0x20059D79DEDD7AB2),I64(0x6DABE6D6AE3C446B),I64(0x45E81BF6C991AE7B),\n\t\tI64(0x6351AE7CAC68B83E),I64(0xA432E32253B6C711),I64(0xD092A9B991143CD2),I64(0xCAC711032E98B58F),\n\t\tI64(0xD8D4C9E02864AC70),I64(0xC5FC550F96C25B89),I64(0xD7EF8DEC903E4276),I64(0x67729EDE7E50F06F),\n\t\tI64(0xEAC28C7AF045CF3D),I64(0xB15C1F945460A04A),I64(0x9CFDDEB05BFB1058),I64(0x93C69ABCE3A1FE5E),\n\t\tI64(0xEB0380DC4A4BDD6E),I64(0xD20DB1E8F8081874),I64(0x229A8528B7C15E14),I64(0x44291750739FBC28),\n\t\tI64(0xD3CCBD4E42060A27),I64(0xF62B1C33F4ED2A97),I64(0x86A8660AE4779905),I64(0xD62E814A2A305025),\n\t\tI64(0x477703A7A08D8ADD),I64(0x7B9B0E977AF815C5),I64(0x78C51A60A9EA2330),I64(0xA6ADFB733AAAE3B7),\n\t\tI64(0x97E5AA1E3199B60F),I64(0x0000000000000000),I64(0xF4B404629DF10E31),I64(0x5564DB44A6719322),\n\t\tI64(0x9207961A59AFEC0D),I64(0x9624A6B88B97A45C),I64(0x363575380A192B1C),I64(0x2C60CD82B595A241),\n\t\tI64(0x7D272664C1DC7932),I64(0x7142769FAA94A1C1),I64(0xA1D0DF263B809D13),I64(0x1630E841D4C451AE),\n\t\tI64(0xC1DF65AD44FA13D8),I64(0x13D2D445BCF20BAC),I64(0xD915C546926ABE23),I64(0x38CF3D92084DD749),\n\t\tI64(0xE766D0272103059D),I64(0xC7634D5EFFDE7F2F),I64(0x077D2455012A7EA4),I64(0xEDBFA82FF16FB199),\n\t\tI64(0xAF2A978C39D46146),I64(0x42953FA3C8BBD0DF),I64(0xCB061DA59496A7DC),I64(0x25E7A17DB6EB20B0),\n\t\tI64(0x34AA6D6963050FBA),I64(0xA76CF7D580A4F1E4),I64(0xF7EA10954EE338C4),I64(0xFCF2643B24819E93),\n\t\tI64(0xCF252D0746AEEF8D),I64(0x4EF06F58A3F3082C),I64(0x563ACFB37563A5D7),I64(0x5086E740CE47C920),\n\t\tI64(0x2982F186DDA3F843),I64(0x87696AAC5E798B56),I64(0x5D22BB1D1F010380),I64(0x035E14F7D31236F5),\n\t\tI64(0x3CEC0D30DA759F18),I64(0xF3C920379CDB7095),I64(0xB8DB736B571E22BB),I64(0xDD36F5E44052F672),\n\t\tI64(0xAAC8AB8851E23B44),I64(0xA857B3D938FE1FE2),I64(0x17F1E4E76ECA43FD),I64(0xEC7EA4894B61A3CA),\n\t\tI64(0x9E62C6E132E734FE),I64(0xD4B1991B432C7483),I64(0x6AD6C283AF163ACF),I64(0x1CE9904904A8E5AA),\n\t\tI64(0x5FBDA34C761D2726),I64(0xF910583F4CB7C491),I64(0xC6A241F845D06D7C),I64(0x4F3163FE19FD1A7F),\n\t\tI64(0xE99C988D2357F9C8),I64(0x8EEE06535D0709A7),I64(0x0EFA48AA0254FC55),I64(0xB4BE23903C56FA48),\n\t\tI64(0x763F52CAABBEDF65),I64(0xEEE1BCD8227D876C),I64(0xE345E085F33B4DCC),I64(0x3E731561B369BBBE),\n\t\tI64(0x2843FD2067ADEA10),I64(0x2ADCE5710EB1CEB6),I64(0xB7E03767EF44CCBD),I64(0x8DB012A48E153F52),\n\t\tI64(0x61CEB62DC5749C98),I64(0xE85D942B9959EB9B),I64(0x4C6F7709CAEF2C8A),I64(0x84377E5B8D6BBDA3),\n\t\tI64(0x30895DCBB13D47EB),I64(0x74A04A9BC2A2FBC3),I64(0x6B17CE251518289C),I64(0xE438C4D0F2113368),\n\t\tI64(0x1FB784BED7BAD35F),I64(0x9B80FAE55AD16EFC),I64(0x77FE5E6C11B0CD36),I64(0xC858095247849129),\n\t\tI64(0x08466059B97090A2),I64(0x01C10CA6BA0E1253),I64(0x6988D6747C040C3A),I64(0x6849DAD2C60A1E69),\n\t\tI64(0x5147EBE67449DB73),I64(0xC99905F4FD8A837A),I64(0x991FE2B433CD4A5A),I64(0xF09734C04FC94660),\n\t\tI64(0xA28ECBD1E892ABE6),I64(0xF1563866F5C75433),I64(0x4DAE7BAF70E13ED9),I64(0x7CE62AC27BD26B61),\n\t\tI64(0x70837A39109AB392),I64(0x90988E4B30B3C8AB),I64(0xB2020B63877296BF),I64(0x156EFCB607D6675B)\n\t},\n\t{\n\t\tI64(0xE63F55CE97C331D0),I64(0x25B506B0015BBA16),I64(0xC8706E29E6AD9BA8),I64(0x5B43D3775D521F6A),\n\t\tI64(0x0BFA3D577035106E),I64(0xAB95FC172AFB0E66),I64(0xF64B63979E7A3276),I64(0xF58B4562649DAD4B),\n\t\tI64(0x48F7C3DBAE0C83F1),I64(0xFF31916642F5C8C5),I64(0xCBB048DC1C4A0495),I64(0x66B8F83CDF622989),\n\t\tI64(0x35C130E908E2B9B0),I64(0x7C761A61F0B34FA1),I64(0x3601161CF205268D),I64(0x9E54CCFE2219B7D6),\n\t\tI64(0x8B7D90A538940837),I64(0x9CD403588EA35D0B),I64(0xBC3C6FEA9CCC5B5A),I64(0xE5FF733B6D24AEED),\n\t\tI64(0xCEED22DE0F7EB8D2),I64(0xEC8581CAB1AB545E),I64(0xB96105E88FF8E71D),I64(0x8CA03501871A5EAD),\n\t\tI64(0x76CCCE65D6DB2A2F),I64(0x5883F582A7B58057),I64(0x3F7BE4ED2E8ADC3E),I64(0x0FE7BE06355CD9C9),\n\t\tI64(0xEE054E6C1D11BE83),I64(0x1074365909B903A6),I64(0x5DDE9F80B4813C10),I64(0x4A770C7D02B6692C),\n\t\tI64(0x5379C8D5D7809039),I64(0xB4067448161ED409),I64(0x5F5E5026183BD6CD),I64(0xE898029BF4C29DF9),\n\t\tI64(0x7FB63C940A54D09C),I64(0xC5171F897F4BA8BC),I64(0xA6F28DB7B31D3D72),I64(0x2E4F3BE7716EAA78),\n\t\tI64(0x0D6771A099E63314),I64(0x82076254E41BF284),I64(0x2F0FD2B42733DF98),I64(0x5C9E76D3E2DC49F0),\n\t\tI64(0x7AEB569619606CDB),I64(0x83478B07B2468764),I64(0xCFADCB8D5923CD32),I64(0x85DAC7F05B95A41E),\n\t\tI64(0xB5469D1B4043A1E9),I64(0xB821ECBBD9A592FD),I64(0x1B8E0B0E798C13C8),I64(0x62A57B6D9A0BE02E),\n\t\tI64(0xFCF1B793B81257F8),I64(0x9D94EA0BD8FE28EB),I64(0x4CEA408AEB654A56),I64(0x23284A47E888996C),\n\t\tI64(0x2D8F1D128B893545),I64(0xF4CBAC3132C0D8AB),I64(0xBD7C86B9CA912EBA),I64(0x3A268EEF3DBE6079),\n\t\tI64(0xF0D62F6077A9110C),I64(0x2735C916ADE150CB),I64(0x89FD5F03942EE2EA),I64(0x1ACEE25D2FD16628),\n\t\tI64(0x90F39BAB41181BFF),I64(0x430DFE8CDE39939F),I64(0xF70B8AC4C8274796),I64(0x1C53AEAAC6024552),\n\t\tI64(0x13B410ACF35E9C9B),I64(0xA532AB4249FAA24F),I64(0x2B1251E5625A163F),I64(0xD7E3E676DA4841C7),\n\t\tI64(0xA7B264E4E5404892),I64(0xDA8497D643AE72D3),I64(0x861AE105A1723B23),I64(0x38A6414991048AA4),\n\t\tI64(0x6578DEC92585B6B4),I64(0x0280CFA6ACBAEADD),I64(0x88BDB650C273970A),I64(0x9333BD5EBBFF84C2),\n\t\tI64(0x4E6A8F2C47DFA08B),I64(0x321C954DB76CEF2A),I64(0x418D312A72837942),I64(0xB29B38BFFFCDF773),\n\t\tI64(0x6C022C38F90A4C07),I64(0x5A033A240B0F6A8A),I64(0x1F93885F3CE5DA6F),I64(0xC38A537E96988BC6),\n\t\tI64(0x39E6A81AC759FF44),I64(0x29929E43CEE0FCE2),I64(0x40CDD87924DE0CA2),I64(0xE9D8EBC8A29FE819),\n\t\tI64(0x0C2798F3CFBB46F4),I64(0x55E484223E53B343),I64(0x4650948ECD0D2FD8),I64(0x20E86CB2126F0651),\n\t\tI64(0x6D42C56BAF5739E7),I64(0xA06FC1405ACE1E08),I64(0x7BABBFC54F3D193B),I64(0x424D17DF8864E67F),\n\t\tI64(0xD8045870EF14980E),I64(0xC6D7397C85AC3781),I64(0x21A885E1443273B1),I64(0x67F8116F893F5C69),\n\t\tI64(0x24F5EFE35706CFF6),I64(0xD56329D076F2AB1A),I64(0x5E1EB9754E66A32D),I64(0x28D2771098BD8902),\n\t\tI64(0x8F6013F47DFDC190),I64(0x17A993FDB637553C),I64(0xE0A219397E1012AA),I64(0x786B9930B5DA8606),\n\t\tI64(0x6E82E39E55B0A6DA),I64(0x875A0856F72F4EC3),I64(0x3741FF4FA458536D),I64(0xAC4859B3957558FC),\n\t\tI64(0x7EF6D5C75C09A57C),I64(0xC04A758B6C7F14FB),I64(0xF9ACDD91AB26EBBF),I64(0x7391A467C5EF9668),\n\t\tI64(0x335C7C1EE1319ACA),I64(0xA91533B18641E4BB),I64(0xE4BF9A683B79DB0D),I64(0x8E20FAA72BA0B470),\n\t\tI64(0x51F907737B3A7AE4),I64(0x2268A314BED5EC8C),I64(0xD944B123B949EDEE),I64(0x31DCB3B84D8B7017),\n\t\tI64(0xD3FE65279F218860),I64(0x097AF2F1DC8FFAB3),I64(0x9B09A6FC312D0B91),I64(0xCC6DED78A3C4520F),\n\t\tI64(0x3481D9BA5EBFCC50),I64(0x4F2A667F1182D56B),I64(0xDFD9FDD4509ACE94),I64(0x26752045FBBC252B),\n\t\tI64(0xBFFC491F662BC467),I64(0xDD593272FC202449),I64(0x3CBBC218D46D4303),I64(0x91B372F817456E1F),\n\t\tI64(0x681FAF69BC6385A0),I64(0xB686BBEEBAA43ED4),I64(0x1469B5084CD0CA01),I64(0x98C98009CBCA94AC),\n\t\tI64(0x6438379A73D8C354),I64(0xC2CABA2DC0C5FE26),I64(0x3E3B0DBE78D7A9DE),I64(0x50B9EE202D670F04),\n\t\tI64(0x4590B27B37EAB0E5),I64(0x6025B4CB36B10AF3),I64(0xFB2C1237079C0162),I64(0xA12F28130C936BE8),\n\t\tI64(0x4B37E52E54EB1CCC),I64(0x083A1BA28AD28F53),I64(0xC10A9CD83A22611B),I64(0x9F1425AD7444C236),\n\t\tI64(0x069D4CF7E9D3237A),I64(0xEDC56899E7F621BE),I64(0x778C273680865FCF),I64(0x309C5AEB1BD605F7),\n\t\tI64(0x8DE0DC52D1472B4D),I64(0xF8EC34C2FD7B9E5F),I64(0xEA18CD3D58787724),I64(0xAAD515447CA67B86),\n\t\tI64(0x9989695A9D97E14C),I64(0x0000000000000000),I64(0xF196C63321F464EC),I64(0x71116BC169557CB5),\n\t\tI64(0xAF887F466F92C7C1),I64(0x972E3E0FFE964D65),I64(0x190EC4A8D536F915),I64(0x95AEF1A9522CA7B8),\n\t\tI64(0xDC19DB21AA7D51A9),I64(0x94EE18FA0471D258),I64(0x8087ADF248A11859),I64(0xC457F6DA2916DD5C),\n\t\tI64(0xFA6CFB6451C17482),I64(0xF256E0C6DB13FBD1),I64(0x6A9F60CF10D96F7D),I64(0x4DAAA9D9BD383FB6),\n\t\tI64(0x03C026F5FAE79F3D),I64(0xDE99148706C7BB74),I64(0x2A52B8B6340763DF),I64(0x6FC20ACD03EDD33A),\n\t\tI64(0xD423C08320AFDEFA),I64(0xBBE1CA4E23420DC0),I64(0x966ED75CA8CB3885),I64(0xEB58246E0E2502C4),\n\t\tI64(0x055D6A021334BC47),I64(0xA47242111FA7D7AF),I64(0xE3623FCC84F78D97),I64(0x81C744A11EFC6DB9),\n\t\tI64(0xAEC8961539CFB221),I64(0xF31609958D4E8E31),I64(0x63E5923ECC5695CE),I64(0x47107DDD9B505A38),\n\t\tI64(0xA3AFE7B5A0298135),I64(0x792B7063E387F3E6),I64(0x0140E953565D75E0),I64(0x12F4F9FFA503E97B),\n\t\tI64(0x750CE8902C3CB512),I64(0xDBC47E8515F30733),I64(0x1ED3610C6AB8AF8F),I64(0x5239218681DDE5D9),\n\t\tI64(0xE222D69FD2AAF877),I64(0xFE71783514A8BD25),I64(0xCAF0A18F4A177175),I64(0x61655D9860EC7F13),\n\t\tI64(0xE77FBC9DC19E4430),I64(0x2CCFF441DDD440A5),I64(0x16E97AAEE06A20DC),I64(0xA855DAE2D01C915B),\n\t\tI64(0x1D1347F9905F30B2),I64(0xB7C652BDECF94B34),I64(0xD03E43D265C6175D),I64(0xFDB15EC0EE4F2218),\n\t\tI64(0x57644B8492E9599E),I64(0x07DDA5A4BF8E569A),I64(0x54A46D71680EC6A3),I64(0x5624A2D7C4B42C7E),\n\t\tI64(0xBEBCA04C3076B187),I64(0x7D36F332A6EE3A41),I64(0x3B6667BC6BE31599),I64(0x695F463AEA3EF040),\n\t\tI64(0xAD08B0E0C3282D1C),I64(0xB15B1E4A052A684E),I64(0x44D05B2861B7C505),I64(0x15295C5B1A8DBFE1),\n\t\tI64(0x744C01C37A61C0F2),I64(0x59C31CD1F1E8F5B7),I64(0xEF45A73F4B4CCB63),I64(0x6BDF899C46841A9D),\n\t\tI64(0x3DFB2B4B823036E3),I64(0xA2EF0EE6F674F4D5),I64(0x184E2DFB836B8CF5),I64(0x1134DF0A5FE47646),\n\t\tI64(0xBAA1231D751F7820),I64(0xD17EAA81339B62BD),I64(0xB01BF71953771DAE),I64(0x849A2EA30DC8D1FE),\n\t\tI64(0x705182923F080955),I64(0x0EA757556301AC29),I64(0x041D83514569C9A7),I64(0x0ABAD4042668658E),\n\t\tI64(0x49B72A88F851F611),I64(0x8A3D79F66EC97DD7),I64(0xCD2D042BF59927EF),I64(0xC930877AB0F0EE48),\n\t\tI64(0x9273540DEDA2F122),I64(0xC797D02FD3F14261),I64(0xE1E2F06A284D674A),I64(0xD2BE8C74C97CFD80),\n\t\tI64(0x9A494FAF67707E71),I64(0xB3DBD1ECA9908293),I64(0x72D14D3493B2E388),I64(0xD6A30F258C153427)\n\t}\n};\n\nstatic const uint64_t gost12_iteration_constants[12][8] =\n{\n\t{\n\t\tI64(0xdd806559f2a64507),I64(0x05767436cc744d23),I64(0xa2422a08a460d315),I64(0x4b7ce09192676901),\n\t\tI64(0x714eb88d7585c4fc),I64(0x2f6a76432e45d016),I64(0xebcb2f81c0657c1f),I64(0xb1085bda1ecadae9)\n\t},\n\t{\n\t\tI64(0xe679047021b19bb7),I64(0x55dda21bd7cbcd56),I64(0x5cb561c2db0aa7ca),I64(0x9ab5176b12d69958),\n\t\tI64(0x61d55e0f16b50131),I64(0xf3feea720a232b98),I64(0x4fe39d460f70b5d7),I64(0x6fa3b58aa99d2f1a)\n\t},\n\t{\n\t\tI64(0x991e96f50aba0ab2),I64(0xc2b6f443867adb31),I64(0xc1c93a376062db09),I64(0xd3e20fe490359eb1),\n\t\tI64(0xf2ea7514b1297b7b),I64(0x06f15e5f529c1f8b),I64(0x0a39fc286a3d8435),I64(0xf574dcac2bce2fc7)\n\t},\n\t{\n\t\tI64(0x220cbebc84e3d12e),I64(0x3453eaa193e837f1),I64(0xd8b71333935203be),I64(0xa9d72c82ed03d675),\n\t\tI64(0x9d721cad685e353f),I64(0x488e857e335c3c7d),I64(0xf948e1a05d71e4dd),I64(0xef1fdfb3e81566d2)\n\t},\n\t{\n\t\tI64(0x601758fd7c6cfe57),I64(0x7a56a27ea9ea63f5),I64(0xdfff00b723271a16),I64(0xbfcd1747253af5a3),\n\t\tI64(0x359e35d7800fffbd),I64(0x7f151c1f1686104a),I64(0x9a3f410c6ca92363),I64(0x4bea6bacad474799)\n\t},\n\t{\n\t\tI64(0xfa68407a46647d6e),I64(0xbf71c57236904f35),I64(0x0af21f66c2bec6b6),I64(0xcffaa6b71c9ab7b4),\n\t\tI64(0x187f9ab49af08ec6),I64(0x2d66c4f95142a46c),I64(0x6fa4c33b7a3039c0),I64(0xae4faeae1d3ad3d9)\n\t},\n\t{\n\t\tI64(0x8886564d3a14d493),I64(0x3517454ca23c4af3),I64(0x06476983284a0504),I64(0x0992abc52d822c37),\n\t\tI64(0xd3473e33197a93c9),I64(0x399ec6c7e6bf87c9),I64(0x51ac86febf240954),I64(0xf4c70e16eeaac5ec)\n\t},\n\t{\n\t\tI64(0xa47f0dd4bf02e71e),I64(0x36acc2355951a8d9),I64(0x69d18d2bd1a5c42f),I64(0xf4892bcb929b0690),\n\t\tI64(0x89b4443b4ddbc49a),I64(0x4eb7f8719c36de1e),I64(0x03e7aa020c6e4141),I64(0x9b1f5b424d93c9a7)\n\t},\n\t{\n\t\tI64(0x7261445183235adb),I64(0x0e38dc92cb1f2a60),I64(0x7b2b8a9aa6079c54),I64(0x800a440bdbb2ceb1),\n\t\tI64(0x3cd955b7e00d0984),I64(0x3a7d3a1b25894224),I64(0x944c9ad8ec165fde),I64(0x378f5a541631229b)\n\t},\n\t{\n\t\tI64(0x74b4c7fb98459ced),I64(0x3698fad1153bb6c3),I64(0x7a1e6c303b7652f4),I64(0x9fe76702af69334b),\n\t\tI64(0x1fffe18a1b336103),I64(0x8941e71cff8a78db),I64(0x382ae548b2e4f3f3),I64(0xabbedea680056f52)\n\t},\n\t{\n\t\tI64(0x6bcaa4cd81f32d1b),I64(0xdea2594ac06fd85d),I64(0xefbacd1d7d476e98),I64(0x8a1d71efea48b9ca),\n\t\tI64(0x2001802114846679),I64(0xd8fa6bbbebab0761),I64(0x3002c6cd635afe94),I64(0x7bcd9ed0efc889fb)\n\t},\n\t{\n\t\tI64(0x48bc924af11bd720),I64(0xfaf417d5d9b21b99),I64(0xe71da4aa88e12852),I64(0x5d80ef9d1891cc86),\n\t\tI64(0xf82012d430219f9b),I64(0xcda43c32bcdf1d77),I64(0xd21380b00449b17a),I64(0x378ee767f11631ba)\n\t}\n};\n\nstatic const uint64_t zero_512[8] = { 0,0,0,0,0,0,0,0 };\n\n/**\n * Initialize algorithm context.\n *\n * @param ctx context to initialize\n * @param hash_size the size of the digest in bytes\n */\nstatic RHASH_INLINE void rhash_gost12_init(gost12_ctx* ctx, unsigned hash_size)\n{\n\tmemset(ctx, 0, sizeof(gost12_ctx));\n\tif (hash_size != gost12_512_hash_size)\n\t\tmemset(ctx->h, 1, gost12_512_hash_size);\n\tctx->hash_size = hash_size;\n}\n\n/**\n * Initialize algorithm context for 256-bit sized digest.\n *\n * @param ctx context to initialize\n * @param hash_size the size of the digest in bytes\n */\nvoid rhash_gost12_256_init(gost12_ctx* ctx)\n{\n\trhash_gost12_init(ctx, gost12_256_hash_size);\n}\n\n/**\n * Initialize algorithm context for 512-bit sized digest.\n *\n * @param ctx context to initialize\n * @param hash_size the size of the digest in bytes\n */\nvoid rhash_gost12_512_init(gost12_ctx* ctx)\n{\n\trhash_gost12_init(ctx, gost12_512_hash_size);\n}\n\n#define xor_uint512(x, y, z) { \\\n\tz[0] = x[0] ^ y[0]; \\\n\tz[1] = x[1] ^ y[1]; \\\n\tz[2] = x[2] ^ y[2]; \\\n\tz[3] = x[3] ^ y[3]; \\\n\tz[4] = x[4] ^ y[4]; \\\n\tz[5] = x[5] ^ y[5]; \\\n\tz[6] = x[6] ^ y[6]; \\\n\tz[7] = x[7] ^ y[7]; \\\n}\n\nstatic void LPSX(const uint64_t* a, const uint64_t* b, uint64_t* result)\n{\n\tregister uint64_t r0, r1, r2, r3, r4, r5, r6, r7;\n\tint i;\n\n\t/* calculate xor_uint512(a, b) */\n\tr0 = a[0] ^ b[0];\n\tr1 = a[1] ^ b[1];\n\tr2 = a[2] ^ b[2];\n\tr3 = a[3] ^ b[3];\n\tr4 = a[4] ^ b[4];\n\tr5 = a[5] ^ b[5];\n\tr6 = a[6] ^ b[6];\n\tr7 = a[7] ^ b[7];\n\n\t/* apply L P S transformations */\n\tfor (i = 0; i <= 7; i++)\n\t{\n\t\tresult[i]  = TR[0][(r0 >> (i << 3)) & 0xFF];\n\t\tresult[i] ^= TR[1][(r1 >> (i << 3)) & 0xFF];\n\t\tresult[i] ^= TR[2][(r2 >> (i << 3)) & 0xFF];\n\t\tresult[i] ^= TR[3][(r3 >> (i << 3)) & 0xFF];\n\t\tresult[i] ^= TR[4][(r4 >> (i << 3)) & 0xFF];\n\t\tresult[i] ^= TR[5][(r5 >> (i << 3)) & 0xFF];\n\t\tresult[i] ^= TR[6][(r6 >> (i << 3)) & 0xFF];\n\t\tresult[i] ^= TR[7][(r7 >> (i << 3)) & 0xFF];\n\t}\n}\n\n/*\n * Implementaion of the function g_N(h,m) = E(LPS(h xor N),m) xor h xor m,\n * where E(K, ) = X[K1 3 ]L PSX[K12] .. . L PSX[K2]LPSX[K1](m).\n */\nstatic void g_N(const uint64_t N[], uint64_t h[], const uint64_t m[])\n{\n\tuint64_t K_i[8];\n\tuint64_t state[8];\n\tunsigned int i;\n\n\t/* the first iteration of E(K_i, m): calculate and apply K_1 */\n\tLPSX(h, N, K_i);\n\tLPSX(K_i, m, state);\n\n\t/* rounds 2,...,11 of E(K_i, m) */\n#if 0\n\tLPSX(K_i, gost12_iteration_constants[0], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[1], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[2], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[3], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[4], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[5], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[6], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[7], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[8], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[9], K_i);\n\tLPSX(K_i, state, state);\n\tLPSX(K_i, gost12_iteration_constants[10], K_i);\n\tLPSX(K_i, state, state);\n#else\n\tfor (i = 0; i < 11; i++)\n\t{\n\t\tLPSX(K_i, gost12_iteration_constants[i], K_i);\n\t\tLPSX(K_i, state, state);\n\t}\n#endif\n\n\t/* the round 12 of E(K_i, m) */\n\tLPSX(K_i, gost12_iteration_constants[11], K_i);\n\txor_uint512(K_i, state, state);\n\n\t/* the last step: calculate h = (state XOR h XOR m) */\n\txor_uint512(state, h, state);\n\txor_uint512(state, m, h);\n}\n\nstatic RHASH_INLINE void add_uint512(uint64_t sum[], const uint64_t x[])\n{\n\t/* usless but fun optimization for x86 */\n#if defined(USE_GCC_ASM_IA32)\n\t__asm(\n\t\t\"movl   (%1), %%eax\\n\\taddl %%eax,   (%0)\\n\\t\"\n\t\t\"movl  4(%1), %%ecx\\n\\tadcl %%ecx,  4(%0)\\n\\t\"\n\t\t\"movl  8(%1), %%eax\\n\\tadcl %%eax,  8(%0)\\n\\t\"\n\t\t\"movl 12(%1), %%ecx\\n\\tadcl %%ecx, 12(%0)\\n\\t\"\n\t\t\"movl 16(%1), %%eax\\n\\tadcl %%eax, 16(%0)\\n\\t\"\n\t\t\"movl 20(%1), %%ecx\\n\\tadcl %%ecx, 20(%0)\\n\\t\"\n\t\t\"movl 24(%1), %%eax\\n\\tadcl %%eax, 24(%0)\\n\\t\"\n\t\t\"movl 28(%1), %%ecx\\n\\tadcl %%ecx, 28(%0)\\n\\t\"\n\t\t\"movl 32(%1), %%eax\\n\\tadcl %%eax, 32(%0)\\n\\t\"\n\t\t\"movl 36(%1), %%ecx\\n\\tadcl %%ecx, 36(%0)\\n\\t\"\n\t\t\"movl 40(%1), %%eax\\n\\tadcl %%eax, 40(%0)\\n\\t\"\n\t\t\"movl 44(%1), %%ecx\\n\\tadcl %%ecx, 44(%0)\\n\\t\"\n\t\t\"movl 48(%1), %%eax\\n\\tadcl %%eax, 48(%0)\\n\\t\"\n\t\t\"movl 52(%1), %%ecx\\n\\tadcl %%ecx, 52(%0)\\n\\t\"\n\t\t\"movl 56(%1), %%eax\\n\\tadcl %%eax, 56(%0)\\n\\t\"\n\t\t\"movl 60(%1), %%ecx\\n\\tadcl %%ecx, 60(%0)\\n\\t\"\n\t\t: : \"r\" (sum), \"r\" (x)\n\t\t: \"eax\", \"ecx\", \"memory\", \"cc\" );\n#elif defined(USE_GCC_ASM_X64)\n\t__asm(\n\t\t\"movq (%1), %%rax\\n\\taddq %%rax, (%0)\\n\\t\"\n\t\t\"movq 8(%1), %%rax\\n\\tadcq %%rax, 8(%0)\\n\\t\"\n\t\t\"movq 16(%1), %%rax\\n\\tadcq %%rax, 16(%0)\\n\\t\"\n\t\t\"movq 24(%1), %%rax\\n\\tadcq %%rax, 24(%0)\\n\\t\"\n\t\t\"movq 32(%1), %%rax\\n\\tadcq %%rax, 32(%0)\\n\\t\"\n\t\t\"movq 40(%1), %%rax\\n\\tadcq %%rax, 40(%0)\\n\\t\"\n\t\t\"movq 48(%1), %%rax\\n\\tadcq %%rax, 48(%0)\\n\\t\"\n\t\t\"movq 56(%1), %%rax\\n\\tadcq %%rax, 56(%0)\\n\\t\"\n\t\t: : \"r\" (sum), \"r\" (x)\n\t\t: \"rax\", \"memory\", \"cc\" );\n#else /* defined(USE_GCC_ASM_IA32) */\n\tint i;\n\tuint64_t carry = 0;\n\n\t/* compute the 512-bit sum */\n\tfor (i = 0; i < 8; i++)\n\t{\n\t\tsum[i] += x[i] + carry;\n\t\tcarry = (sum[i] < x[i] ? 1 : sum[i] == x[i] ? carry : 0);\n\t}\n#endif /* USE_GCC_ASM_IA32 */\n}\n\nstatic const uint64_t stage2_constant[8] = { I64(512), 0, 0, 0, 0, 0, 0, 0 };\n\nstatic RHASH_INLINE void rhash_gost12_stage2(gost12_ctx* ctx, uint64_t m[])\n{\n\tg_N(ctx->N, ctx->h, m);\n\tadd_uint512(ctx->N, stage2_constant);\n\tadd_uint512(ctx->S, m);\n}\n\nvoid rhash_gost12_update(gost12_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tif (ctx->index)\n\t{\n\t\tsize_t rest = gost12_block_size - ctx->index;\n\n\t\tle64_copy(ctx->message, ctx->index, msg, (size < rest ? size : rest));\n\t\tctx->index += (unsigned)size;\n\t\tif (size < rest)\n\t\t\treturn;\n\n\t\t/* process partial block */\n\t\trhash_gost12_stage2(ctx, ctx->message);\n\t\tmsg  += rest;\n\t\tsize -= rest;\n\t\tctx->index = 0;\n\t}\n\tif (IS_LITTLE_ENDIAN && IS_ALIGNED_64(msg))\n\t{\n\t\twhile (size >= gost12_block_size)\n\t\t{\n\t\t\trhash_gost12_stage2(ctx, (uint64_t*)msg);\n\t\t\tmsg += gost12_block_size;\n\t\t\tsize -= gost12_block_size;\n\t\t}\n\t} else {\n\t\twhile (size >= gost12_block_size)\n\t\t{\n\t\t\tle64_copy(ctx->message, 0, msg, gost12_block_size);\n\t\t\trhash_gost12_stage2(ctx, ctx->message);\n\t\t\tmsg += gost12_block_size;\n\t\t\tsize -= gost12_block_size;\n\t\t}\n\t}\n\tif (size)\n\t{\n\t\tctx->index = (unsigned)size;\n\t\tle64_copy(ctx->message, 0, msg, size); /* save leftovers */\n\t}\n}\n\nvoid rhash_gost12_final(gost12_ctx* ctx, unsigned char* result)\n{\n\tuint64_t unprocessed_bits_count[8] = { 0,0,0,0,0,0,0,0 };\n\tsize_t index_u64 = ctx->index >> 3;\n\tunsigned shift = (ctx->index & 7) * 8;\n\n\tunprocessed_bits_count[0] = ctx->index * 8;\n\tctx->message[index_u64]   &= ~(I64(0xFFFFFFFFFFFFFFFF) << shift);\n\tctx->message[index_u64++] ^= I64(0x01) << shift;\n\tmemset(&ctx->message[index_u64], 0, gost12_block_size - index_u64 * 8);\n\n\t/* apply gost12 stage 3 */\n\tg_N(ctx->N, ctx->h, ctx->message);\n\tadd_uint512(ctx->N, unprocessed_bits_count);\n\tadd_uint512(ctx->S, ctx->message);\n\tg_N(zero_512, ctx->h, ctx->N);\n\tg_N(zero_512, ctx->h, ctx->S);\n\n\tle64_copy(result, 0, &(ctx->h[8 - ctx->hash_size / 8]), ctx->hash_size);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/gost12.h",
    "content": "﻿/* gost12.h */\n#ifndef GOST12_H\n#define GOST12_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define gost12_block_size 64\n#define gost12_256_hash_size 32\n#define gost12_512_hash_size 64\n\n/* algorithm context */\ntypedef struct gost12_ctx {\n\tuint64_t h[8];\n\tuint64_t N[8];\n\tuint64_t S[8];\n\tuint64_t message[8];\n\tunsigned index;\n\tunsigned hash_size;\n} gost12_ctx;\n\n/* hash functions */\n\nvoid rhash_gost12_256_init(gost12_ctx* ctx);\nvoid rhash_gost12_512_init(gost12_ctx* ctx);\nvoid rhash_gost12_update(gost12_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_gost12_final(gost12_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* GOST12_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/gost94.c",
    "content": "﻿/* gost94.c - an implementation of the GOST R 34.11-94 hash function,\n * the deprecated Russian cryptographic standard.\n * See also RFC 4357.\n *\n * Copyright (c) 2009, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"gost94.h\"\n#include <string.h>\n#include \"byte_order.h\"\n\n#if defined(__GNUC__) && defined(CPU_IA32) && !defined(__clang__) && !defined(RHASH_NO_ASM)\n# define USE_GCC_ASM_IA32\n#elif defined(__GNUC__) && defined(CPU_X64) && !defined(RHASH_NO_ASM)\n# define USE_GCC_ASM_X64\n#endif\n\nextern unsigned rhash_gost94_sbox[4][256];\nextern unsigned rhash_gost94_sbox_cryptpro[4][256];\n\n/**\n * Initialize algorithm context before calculating hash\n * with test parameters set.\n *\n * @param ctx context to initialize\n */\nvoid rhash_gost94_init(gost94_ctx* ctx)\n{\n\tmemset(ctx, 0, sizeof(gost94_ctx));\n}\n\n/**\n * Initialize GOST algorithm context with CryptoPro parameter set.\n *\n * @param ctx context to initialize\n */\nvoid rhash_gost94_cryptopro_init(gost94_ctx* ctx)\n{\n\trhash_gost94_init(ctx);\n\tctx->cryptpro = 1;\n}\n\n/*\n *  A macro that performs a full encryption round of GOST 28147-89.\n *  Temporary variables tmp assumed and variables r and l for left and right\n *  blocks.\n */\n#ifndef USE_GCC_ASM_IA32\n# define GOST94_ENCRYPT_ROUND(key1, key2, sbox) \\\n\ttmp = (key1) + r; \\\n\tl ^= (sbox)[tmp & 0xff] ^ ((sbox) + 256)[(tmp >> 8) & 0xff] ^ \\\n\t\t((sbox) + 512)[(tmp >> 16) & 0xff] ^ ((sbox) + 768)[tmp >> 24]; \\\n\ttmp = (key2) + l; \\\n\tr ^= (sbox)[tmp & 0xff] ^ ((sbox) + 256)[(tmp >> 8) & 0xff] ^ \\\n\t\t((sbox) + 512)[(tmp >> 16) & 0xff] ^ ((sbox) + 768)[tmp >> 24];\n\n/* encrypt a block with the given key */\n# define GOST94_ENCRYPT(result, i, key, hash, sbox) \\\n\tr = hash[i], l = hash[i + 1]; \\\n\tGOST94_ENCRYPT_ROUND(key[0], key[1], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[2], key[3], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[4], key[5], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[6], key[7], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[0], key[1], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[2], key[3], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[4], key[5], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[6], key[7], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[0], key[1], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[2], key[3], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[4], key[5], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[6], key[7], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[7], key[6], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[5], key[4], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[3], key[2], sbox) \\\n\tGOST94_ENCRYPT_ROUND(key[1], key[0], sbox) \\\n\tresult[i] = l, result[i + 1] = r;\n\n#else /* USE_GCC_ASM_IA32 */\n\n/* a faster x86 version of GOST94_ENCRYPT() */\n/* it supposes edi=r, esi=l, edx=sbox ; */\n# define ENC_ROUND_ASMx86(key, reg1, reg2) \\\n\t\"movl %\" #key \", %%eax\\n\\t\" \\\n\t\"addl %%\" #reg1 \", %%eax\\n\\t\" \\\n\t\"movzx %%al, %%ebx\\n\\t\" \\\n\t\"movzx %%ah, %%ecx\\n\\t\" \\\n\t\"xorl (%%edx, %%ebx, 4), %%\" #reg2 \"\\n\\t\" \\\n\t\"xorl 1024(%%edx, %%ecx, 4), %%\" #reg2 \"\\n\\t\" \\\n\t\"shrl $16, %%eax\\n\\t\" \\\n\t\"movzx %%al, %%ebx\\n\\t\" \\\n\t\"shrl $8, %%eax\\n\\t\" \\\n\t\"xorl 2048(%%edx, %%ebx, 4), %%\" #reg2 \"\\n\\t\" \\\n\t\"xorl 3072(%%edx, %%eax, 4), %%\" #reg2 \"\\n\\t\"\n\n# define ENC_ASM(key1, key2) ENC_ROUND_ASMx86(key1, edi, esi) ENC_ROUND_ASMx86(key2, esi, edi)\n# define GOST94_ENCRYPT_GCC_ASM_X86() \\\n\tENC_ASM( 5,  6) ENC_ASM( 7,  8) ENC_ASM( 9, 10) ENC_ASM(11, 12) \\\n\tENC_ASM( 5,  6) ENC_ASM( 7,  8) ENC_ASM( 9, 10) ENC_ASM(11, 12) \\\n\tENC_ASM( 5,  6) ENC_ASM( 7,  8) ENC_ASM( 9, 10) ENC_ASM(11, 12) \\\n\tENC_ASM(12, 11) ENC_ASM(10,  9) ENC_ASM( 8,  7) ENC_ASM( 6,  5)\n#endif /* USE_GCC_ASM_IA32 */\n\n/**\n * The core transformation. Process a 512-bit block.\n *\n * @param hash intermediate message hash\n * @param block the message block to process\n */\nstatic void rhash_gost94_block_compress(gost94_ctx* ctx, const unsigned* block)\n{\n\tunsigned i;\n\tunsigned key[8], u[8], v[8], w[8], s[8];\n\tunsigned* sbox = (ctx->cryptpro ? (unsigned*)rhash_gost94_sbox_cryptpro : (unsigned*)rhash_gost94_sbox);\n\n\t/* u := hash, v := <256-bit message block> */\n\tmemcpy(u, ctx->hash, sizeof(u));\n\tmemcpy(v, block, sizeof(v));\n\n\t/* w := u xor v */\n\tw[0] = u[0] ^ v[0], w[1] = u[1] ^ v[1];\n\tw[2] = u[2] ^ v[2], w[3] = u[3] ^ v[3];\n\tw[4] = u[4] ^ v[4], w[5] = u[5] ^ v[5];\n\tw[6] = u[6] ^ v[6], w[7] = u[7] ^ v[7];\n\n\t/* calculate keys, encrypt hash and store result to the s[] array */\n\tfor (i = 0;; i += 2) {\n\t\t/* key generation: key_i := P(w) */\n\t\tkey[0] = (w[0] & 0x000000ff) | ((w[2] & 0x000000ff) << 8) | ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24);\n\t\tkey[1] = ((w[0] & 0x0000ff00) >> 8) | (w[2] & 0x0000ff00) | ((w[4] & 0x0000ff00) << 8)  | ((w[6] & 0x0000ff00) << 16);\n\t\tkey[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) | (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8);\n\t\tkey[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) | ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000);\n\t\tkey[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) | ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24);\n\t\tkey[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3] & 0x0000ff00) | ((w[5] & 0x0000ff00) << 8)  | ((w[7] & 0x0000ff00) << 16);\n\t\tkey[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) | (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8);\n\t\tkey[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) | ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);\n\n\t\t/* encryption: s_i := E_{key_i} (h_i) */\n#ifndef USE_GCC_ASM_IA32\n\t\t{\n\t\t\tunsigned l, r, tmp;\n\t\t\tGOST94_ENCRYPT(s, i, key, ctx->hash, sbox);\n\t\t}\n#else /* USE_GCC_ASM_IA32 */\n\t\t__asm __volatile(\n\t\t\t\"movl %%ebx, %13\\n\\t\"\n\t\t\tGOST94_ENCRYPT_GCC_ASM_X86() /* optimized for x86 Intel Core 2 */\n\t\t\t\"movl %13, %%ebx\\n\\t\"\n\t\t\t: \"=S\" (s[i]), \"=D\" (s[i + 1]) /* 0,1: s[i]=esi, s[i + 1]=edi */\n\t\t\t: \"d\" (sbox), \"D\" (ctx->hash[i]), \"S\" (ctx->hash[i + 1]), /* 2,3,4: edx=sbox,edi=r,esi=l */\n\t\t\t\"m\" (key[0]), \"m\" (key[1]), \"m\" (key[2]), \"m\" (key[3]), /* 5, 6, 7, 8 */\n\t\t\t\"m\" (key[4]), \"m\" (key[5]), \"m\" (key[6]), \"m\" (key[7]), /* 9,10,11,12 */\n\t\t\t\"m\" (w[0])  /* store EBX in w[0], cause it's used for PIC on *BSD. */\n\t\t\t/* We avoid push/pop instructions incompatible with gcc -fomit-frame-pointer */\n\t\t\t: \"cc\", \"eax\", \"ecx\");\n#endif /* USE_GCC_ASM_IA32 */\n\n\t\tif (i == 0) {\n\t\t\t/* w:= A(u) ^ A^2(v) */\n\t\t\tw[0] = u[2] ^ v[4], w[1] = u[3] ^ v[5];\n\t\t\tw[2] = u[4] ^ v[6], w[3] = u[5] ^ v[7];\n\t\t\tw[4] = u[6] ^ (v[0] ^= v[2]);\n\t\t\tw[5] = u[7] ^ (v[1] ^= v[3]);\n\t\t\tw[6] = (u[0] ^= u[2]) ^ (v[2] ^= v[4]);\n\t\t\tw[7] = (u[1] ^= u[3]) ^ (v[3] ^= v[5]);\n\t\t} else if ((i & 2) != 0) {\n\t\t\tif (i == 6) break;\n\n\t\t\t/* w := A^2(u) xor A^4(v) xor C_3; u := A(u) xor C_3 */\n\t\t\t/* C_3=0xff00ffff000000ffff0000ff00ffff0000ff00ff00ff00ffff00ff00ff00ff00 */\n\t\t\tu[2] ^= u[4] ^ 0x000000ff;\n\t\t\tu[3] ^= u[5] ^ 0xff00ffff;\n\t\t\tu[4] ^= 0xff00ff00;\n\t\t\tu[5] ^= 0xff00ff00;\n\t\t\tu[6] ^= 0x00ff00ff;\n\t\t\tu[7] ^= 0x00ff00ff;\n\t\t\tu[0] ^= 0x00ffff00;\n\t\t\tu[1] ^= 0xff0000ff;\n\n\t\t\tw[0] = u[4] ^ v[0];\n\t\t\tw[2] = u[6] ^ v[2];\n\t\t\tw[4] = u[0] ^ (v[4] ^= v[6]);\n\t\t\tw[6] = u[2] ^ (v[6] ^= v[0]);\n\t\t\tw[1] = u[5] ^ v[1];\n\t\t\tw[3] = u[7] ^ v[3];\n\t\t\tw[5] = u[1] ^ (v[5] ^= v[7]);\n\t\t\tw[7] = u[3] ^ (v[7] ^= v[1]);\n\t\t} else {\n\t\t\t/* i==4 here */\n\t\t\t/* w:= A( A^2(u) xor C_3 ) xor A^6(v) */\n\t\t\tw[0] = u[6] ^ v[4], w[1] = u[7] ^ v[5];\n\t\t\tw[2] = u[0] ^ v[6], w[3] = u[1] ^ v[7];\n\t\t\tw[4] = u[2] ^ (v[0] ^= v[2]);\n\t\t\tw[5] = u[3] ^ (v[1] ^= v[3]);\n\t\t\tw[6] = (u[4] ^= u[6]) ^ (v[2] ^= v[4]);\n\t\t\tw[7] = (u[5] ^= u[7]) ^ (v[3] ^= v[5]);\n\t\t}\n\t}\n\n\t/* step hash function: x(block, hash) := psi^61(hash xor psi(block xor psi^12(S))) */\n\n\t/* 12 rounds of the LFSR and xor in <message block> */\n\tu[0] = block[0] ^ s[6];\n\tu[1] = block[1] ^ s[7];\n\tu[2] = block[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[7] & 0xffff0000) ^ (s[7] >> 16);\n\tu[3] = block[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ (s[1] << 16) ^ (s[1] >> 16) ^\n\t\t(s[2] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);\n\tu[4] = block[4] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^\n\t\t(s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);\n\tu[5] = block[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^\n\t\t(s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16);\n\tu[6] = block[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16)\n\t\t^ (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16);\n\tu[7] = block[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^\n\t\t(s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16);\n\n\t/* 1 round of the LFSR (a mixing transformation) and xor with <hash> */\n\tv[0] = ctx->hash[0] ^ (u[1] << 16) ^ (u[0] >> 16);\n\tv[1] = ctx->hash[1] ^ (u[2] << 16) ^ (u[1] >> 16);\n\tv[2] = ctx->hash[2] ^ (u[3] << 16) ^ (u[2] >> 16);\n\tv[3] = ctx->hash[3] ^ (u[4] << 16) ^ (u[3] >> 16);\n\tv[4] = ctx->hash[4] ^ (u[5] << 16) ^ (u[4] >> 16);\n\tv[5] = ctx->hash[5] ^ (u[6] << 16) ^ (u[5] >> 16);\n\tv[6] = ctx->hash[6] ^ (u[7] << 16) ^ (u[6] >> 16);\n\tv[7] = ctx->hash[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000) ^ (u[7] >> 16);\n\n\t/* 61 rounds of LFSR, mixing up hash */\n\tctx->hash[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^\n\t\t(v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^\n\t\t(v[3] >> 16) ^ (v[4] << 16) ^ (v[5] >> 16) ^ v[5] ^\n\t\t(v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff);\n\tctx->hash[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^\n\t\t(v[1] & 0xffff) ^ v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^\n\t\t(v[4] >> 16) ^ (v[5] << 16) ^ (v[6] << 16) ^ v[6] ^\n\t\t(v[7] & 0xffff0000) ^ (v[7] >> 16);\n\tctx->hash[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^\n\t\t(v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^\n\t\tv[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^\n\t\t(v[7] & 0xffff) ^ (v[7] << 16) ^ (v[7] >> 16);\n\tctx->hash[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^\n\t\t(v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^\n\t\t(v[2] >> 16) ^ v[2] ^ (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^\n\t\t(v[5] << 16) ^ (v[6] << 16) ^ (v[7] & 0xffff) ^ (v[7] >> 16);\n\tctx->hash[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^\n\t\t(v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^\n\t\t(v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16);\n\tctx->hash[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^\n\t\t(v[1] >> 16) ^ (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^\n\t\t(v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^\n\t\t(v[5] << 16) ^ (v[6] << 16) ^ (v[6] >> 16) ^ v[6] ^\n\t\t(v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000);\n\tctx->hash[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^\n\t\t(v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^\n\t\t(v[6] << 16) ^ (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7];\n\tctx->hash[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^\n\t\t(v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^\n\t\t(v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];\n}\n\n/**\n * This function calculates hash value by 256-bit blocks.\n * It updates 256-bit check sum as follows:\n *    *(uint256_t)(ctx->sum) += *(uint256_t*)block;\n * and then updates intermediate hash value ctx->hash\n * by calling rhash_gost94_block_compress().\n *\n * @param ctx algorithm context\n * @param block the 256-bit message block to process\n */\nstatic void rhash_gost94_compute_sum_and_hash(gost94_ctx* ctx, const unsigned* block)\n{\n#if IS_LITTLE_ENDIAN\n# define block_le block\n# define LOAD_BLOCK_LE(i)\n#else\n\tunsigned block_le[8]; /* tmp buffer for little endian number */\n# define LOAD_BLOCK_LE(i) (block_le[i] = le2me_32(block[i]))\n#endif\n\n\t/* This optimization doesn't improve speed much,\n\t* and saves too little memory, but it was fun to write! =)  */\n#ifdef USE_GCC_ASM_IA32\n\t__asm __volatile(\n\t\t\"addl %0, (%1)\\n\\t\"\n\t\t\"movl 4(%2), %0\\n\\t\"\n\t\t\"adcl %0, 4(%1)\\n\\t\"\n\t\t\"movl 8(%2), %0\\n\\t\"\n\t\t\"adcl %0, 8(%1)\\n\\t\"\n\t\t\"movl 12(%2), %0\\n\\t\"\n\t\t\"adcl %0, 12(%1)\\n\\t\"\n\t\t\"movl 16(%2), %0\\n\\t\"\n\t\t\"adcl %0, 16(%1)\\n\\t\"\n\t\t\"movl 20(%2), %0\\n\\t\"\n\t\t\"adcl %0, 20(%1)\\n\\t\"\n\t\t\"movl 24(%2), %0\\n\\t\"\n\t\t\"adcl %0, 24(%1)\\n\\t\"\n\t\t\"movl 28(%2), %0\\n\\t\"\n\t\t\"adcl %0, 28(%1)\\n\\t\"\n\t\t: : \"r\" (block[0]), \"r\" (ctx->sum), \"r\" (block)\n\t\t: \"0\", \"memory\", \"cc\" );\n#elif defined(USE_GCC_ASM_X64)\n\tconst uint64_t* block64 = (const uint64_t*)block;\n\tuint64_t* sum64 = (uint64_t*)ctx->sum;\n\t__asm __volatile(\n\t\t\"addq %4, %0\\n\\t\"\n\t\t\"adcq %5, %1\\n\\t\"\n\t\t\"adcq %6, %2\\n\\t\"\n\t\t\"adcq %7, %3\\n\\t\"\n\t\t: \"+m\" (sum64[0]), \"+m\" (sum64[1]), \"+m\" (sum64[2]), \"+m\" (sum64[3])\n\t\t: \"r\" (block64[0]), \"r\" (block64[1]), \"r\" (block64[2]), \"r\" (block64[3])\n\t\t: \"cc\" );\n#else /* USE_GCC_ASM_IA32 */\n\n\tunsigned i, carry = 0;\n\n\t/* compute the 256-bit sum */\n\tfor (i = 0; i < 8; i++) {\n\t\tLOAD_BLOCK_LE(i);\n\t\tctx->sum[i] += block_le[i] + carry;\n\t\tcarry = (ctx->sum[i] < block_le[i] ? 1 :\n\t\t\tctx->sum[i] == block_le[i] ? carry : 0);\n\t}\n#endif /* USE_GCC_ASM_IA32 */\n\n\t/* update message hash */\n\trhash_gost94_block_compress(ctx, block_le);\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_gost94_update(gost94_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tunsigned index = (unsigned)ctx->length & 31;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tunsigned left = gost94_block_size - index;\n\t\tmemcpy(ctx->message + index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_gost94_compute_sum_and_hash(ctx, (unsigned*)ctx->message);\n\t\tmsg += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= gost94_block_size) {\n\t\tunsigned* aligned_message_block;\n#if (defined(__GNUC__) && defined(CPU_X64))\n\t\tif (IS_ALIGNED_64(msg)) {\n#else\n\t\tif (IS_ALIGNED_32(msg)) {\n#endif\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\ton little-endian CPU without copying it */\n\t\t\taligned_message_block = (unsigned*)msg;\n\t\t} else {\n\t\t\tmemcpy(ctx->message, msg, gost94_block_size);\n\t\t\taligned_message_block = (unsigned*)ctx->message;\n\t\t}\n\n\t\trhash_gost94_compute_sum_and_hash(ctx, aligned_message_block);\n\t\tmsg += gost94_block_size;\n\t\tsize -= gost94_block_size;\n\t}\n\tif (size) {\n\t\t/* save leftovers */\n\t\tmemcpy(ctx->message, msg, size);\n\t}\n}\n\n/**\n * Finish hashing and store message digest into given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_gost94_final(gost94_ctx* ctx, unsigned char result[32])\n{\n\tunsigned  index = (unsigned)ctx->length & 31;\n\tunsigned* msg32 = (unsigned*)ctx->message;\n\n\t/* pad the last block with zeroes and hash it */\n\tif (index > 0) {\n\t\tmemset(ctx->message + index, 0, 32 - index);\n\t\trhash_gost94_compute_sum_and_hash(ctx, msg32);\n\t}\n\n\t/* hash the message length and the sum */\n\tmsg32[0] = (unsigned)(ctx->length << 3);\n\tmsg32[1] = (unsigned)(ctx->length >> 29);\n\tmemset(msg32 + 2, 0, sizeof(unsigned) * 6);\n\n\trhash_gost94_block_compress(ctx, msg32);\n\trhash_gost94_block_compress(ctx, ctx->sum);\n\n\t/* convert hash state to result bytes */\n\tle32_copy(result, 0, ctx->hash, gost94_hash_length);\n}\n\n#ifdef GENERATE_GOST94_LOOKUP_TABLE\nALIGN_ATTR(64)\nunsigned rhash_gost94_sbox[4][256];\nunsigned rhash_gost94_sbox_cryptpro[4][256];\n\n/**\n * Calculate a lookup table from S-Boxes.\n * A substitution table is used to speed up hash calculation.\n *\n * @param out pointer to the lookup table to fill\n * @param src pointer to eight S-Boxes to fill the table from\n */\nstatic void rhash_gost94_fill_sbox(unsigned out[4][256], const unsigned char src[8][16])\n{\n\tint a, b, i;\n\tunsigned long ax, bx, cx, dx;\n\n\tfor (i = 0, a = 0; a < 16; a++) {\n\t\tax = (unsigned)src[1][a] << 15;\n\t\tbx = (unsigned)src[3][a] << 23;\n\t\tcx = ROTL32((unsigned)src[5][a], 31);\n\t\tdx = (unsigned)src[7][a] << 7;\n\n\t\tfor (b = 0; b < 16; b++, i++) {\n\t\t\tout[0][i] = ax | ((unsigned)src[0][b] << 11);\n\t\t\tout[1][i] = bx | ((unsigned)src[2][b] << 19);\n\t\t\tout[2][i] = cx | ((unsigned)src[4][b] << 27);\n\t\t\tout[3][i] = dx | ((unsigned)src[6][b] << 3);\n\t\t}\n\t}\n}\n\n/**\n * Initialize the GOST lookup tables for both parameters sets.\n * Two lookup tables contain 8 KiB in total, so calculating\n * them at rine-time can save a little space in the exutable file\n * in trade of consuming some time at pogram start.\n */\nvoid rhash_gost94_init_table(void)\n{\n\t/* Test parameters set. Eight 4-bit S-Boxes defined by GOST R 34.10-94\n\t * standard for testing the hash function.\n\t * Also given by RFC 4357 section 11.2 */\n\tstatic const unsigned char sbox[8][16] = {\n\t\t{  4, 10,  9,  2, 13,  8,  0, 14,  6, 11,  1, 12,  7, 15,  5,  3 },\n\t\t{ 14, 11,  4, 12,  6, 13, 15, 10,  2,  3,  8,  1,  0,  7,  5,  9 },\n\t\t{  5,  8,  1, 13, 10,  3,  4,  2, 14, 15, 12,  7,  6,  0,  9, 11 },\n\t\t{  7, 13, 10,  1,  0,  8,  9, 15, 14,  4,  6, 12, 11,  2,  5,  3 },\n\t\t{  6, 12,  7,  1,  5, 15, 13,  8,  4, 10,  9, 14,  0,  3, 11,  2 },\n\t\t{  4, 11, 10,  0,  7,  2,  1, 13,  3,  6,  8,  5,  9, 12, 15, 14 },\n\t\t{ 13, 11,  4,  1,  3, 15,  5,  9,  0, 10, 14,  7,  6,  8,  2, 12 },\n\t\t{  1, 15, 13,  0,  5,  7, 10,  4,  9,  2,  3, 14,  6, 11,  8, 12 }\n\t};\n\n\t/* Parameter set recommended by RFC 4357.\n\t * Eight 4-bit S-Boxes as defined by RFC 4357 section 11.2 */\n\tstatic const unsigned char sbox_cryptpro[8][16] = {\n\t\t{ 10,  4,  5,  6,  8,  1,  3,  7, 13, 12, 14,  0,  9,  2, 11, 15 },\n\t\t{  5, 15,  4,  0,  2, 13, 11,  9,  1,  7,  6,  3, 12, 14, 10,  8 },\n\t\t{  7, 15, 12, 14,  9,  4,  1,  0,  3, 11,  5,  2,  6, 10,  8, 13 },\n\t\t{  4, 10,  7, 12,  0, 15,  2,  8, 14,  1,  6,  5, 13, 11,  9,  3 },\n\t\t{  7,  6,  4, 11,  9, 12,  2, 10,  1,  8,  0, 14, 15, 13,  3,  5 },\n\t\t{  7,  6,  2,  4, 13,  9, 15,  0, 10,  1,  5, 11,  8, 14, 12,  3 },\n\t\t{ 13, 14,  4,  1,  7,  0,  5, 10,  3, 12,  8, 15,  6,  2,  9, 11 },\n\t\t{  1,  3, 10,  9,  5, 11,  4, 15,  8,  6,  7, 14, 13,  0,  2, 12 }\n\t};\n\n\trhash_gost94_fill_sbox(rhash_gost94_sbox, sbox);\n\trhash_gost94_fill_sbox(rhash_gost94_sbox_cryptpro, sbox_cryptpro);\n}\n\n#else /* GENERATE_GOST94_LOOKUP_TABLE */\n\n/* pre-initialized GOST lookup tables based on rotated S-Box */\nALIGN_ATTR(64)\nunsigned rhash_gost94_sbox[4][256] = {\n\t{\n\t\t0x72000, 0x75000, 0x74800, 0x71000, 0x76800,\n\t\t0x74000, 0x70000, 0x77000, 0x73000, 0x75800,\n\t\t0x70800, 0x76000, 0x73800, 0x77800, 0x72800,\n\t\t0x71800, 0x5A000, 0x5D000, 0x5C800, 0x59000,\n\t\t0x5E800, 0x5C000, 0x58000, 0x5F000, 0x5B000,\n\t\t0x5D800, 0x58800, 0x5E000, 0x5B800, 0x5F800,\n\t\t0x5A800, 0x59800, 0x22000, 0x25000, 0x24800,\n\t\t0x21000, 0x26800, 0x24000, 0x20000, 0x27000,\n\t\t0x23000, 0x25800, 0x20800, 0x26000, 0x23800,\n\t\t0x27800, 0x22800, 0x21800, 0x62000, 0x65000,\n\t\t0x64800, 0x61000, 0x66800, 0x64000, 0x60000,\n\t\t0x67000, 0x63000, 0x65800, 0x60800, 0x66000,\n\t\t0x63800, 0x67800, 0x62800, 0x61800, 0x32000,\n\t\t0x35000, 0x34800, 0x31000, 0x36800, 0x34000,\n\t\t0x30000, 0x37000, 0x33000, 0x35800, 0x30800,\n\t\t0x36000, 0x33800, 0x37800, 0x32800, 0x31800,\n\t\t0x6A000, 0x6D000, 0x6C800, 0x69000, 0x6E800,\n\t\t0x6C000, 0x68000, 0x6F000, 0x6B000, 0x6D800,\n\t\t0x68800, 0x6E000, 0x6B800, 0x6F800, 0x6A800,\n\t\t0x69800, 0x7A000, 0x7D000, 0x7C800, 0x79000,\n\t\t0x7E800, 0x7C000, 0x78000, 0x7F000, 0x7B000,\n\t\t0x7D800, 0x78800, 0x7E000, 0x7B800, 0x7F800,\n\t\t0x7A800, 0x79800, 0x52000, 0x55000, 0x54800,\n\t\t0x51000, 0x56800, 0x54000, 0x50000, 0x57000,\n\t\t0x53000, 0x55800, 0x50800, 0x56000, 0x53800,\n\t\t0x57800, 0x52800, 0x51800, 0x12000, 0x15000,\n\t\t0x14800, 0x11000, 0x16800, 0x14000, 0x10000,\n\t\t0x17000, 0x13000, 0x15800, 0x10800, 0x16000,\n\t\t0x13800, 0x17800, 0x12800, 0x11800, 0x1A000,\n\t\t0x1D000, 0x1C800, 0x19000, 0x1E800, 0x1C000,\n\t\t0x18000, 0x1F000, 0x1B000, 0x1D800, 0x18800,\n\t\t0x1E000, 0x1B800, 0x1F800, 0x1A800, 0x19800,\n\t\t0x42000, 0x45000, 0x44800, 0x41000, 0x46800,\n\t\t0x44000, 0x40000, 0x47000, 0x43000, 0x45800,\n\t\t0x40800, 0x46000, 0x43800, 0x47800, 0x42800,\n\t\t0x41800, 0xA000,  0xD000,  0xC800,  0x9000,\n\t\t0xE800,  0xC000,  0x8000,  0xF000,  0xB000,\n\t\t0xD800,  0x8800,  0xE000,  0xB800,  0xF800,\n\t\t0xA800,  0x9800,  0x2000,  0x5000,  0x4800,\n\t\t0x1000,  0x6800,  0x4000,  0x0,     0x7000,\n\t\t0x3000,  0x5800,  0x800,   0x6000,  0x3800,\n\t\t0x7800,  0x2800,  0x1800,  0x3A000, 0x3D000,\n\t\t0x3C800, 0x39000, 0x3E800, 0x3C000, 0x38000,\n\t\t0x3F000, 0x3B000, 0x3D800, 0x38800, 0x3E000,\n\t\t0x3B800, 0x3F800, 0x3A800, 0x39800, 0x2A000,\n\t\t0x2D000, 0x2C800, 0x29000, 0x2E800, 0x2C000,\n\t\t0x28000, 0x2F000, 0x2B000, 0x2D800, 0x28800,\n\t\t0x2E000, 0x2B800, 0x2F800, 0x2A800, 0x29800,\n\t\t0x4A000, 0x4D000, 0x4C800, 0x49000, 0x4E800,\n\t\t0x4C000, 0x48000, 0x4F000, 0x4B000, 0x4D800,\n\t\t0x48800, 0x4E000, 0x4B800, 0x4F800, 0x4A800,\n\t\t0x49800\n\t}, {\n\t\t0x3A80000, 0x3C00000, 0x3880000, 0x3E80000, 0x3D00000,\n\t\t0x3980000, 0x3A00000, 0x3900000, 0x3F00000, 0x3F80000,\n\t\t0x3E00000, 0x3B80000, 0x3B00000, 0x3800000, 0x3C80000,\n\t\t0x3D80000, 0x6A80000, 0x6C00000, 0x6880000, 0x6E80000,\n\t\t0x6D00000, 0x6980000, 0x6A00000, 0x6900000, 0x6F00000,\n\t\t0x6F80000, 0x6E00000, 0x6B80000, 0x6B00000, 0x6800000,\n\t\t0x6C80000, 0x6D80000, 0x5280000, 0x5400000, 0x5080000,\n\t\t0x5680000, 0x5500000, 0x5180000, 0x5200000, 0x5100000,\n\t\t0x5700000, 0x5780000, 0x5600000, 0x5380000, 0x5300000,\n\t\t0x5000000, 0x5480000, 0x5580000, 0xA80000,  0xC00000,\n\t\t0x880000,  0xE80000,  0xD00000,  0x980000,  0xA00000,\n\t\t0x900000,  0xF00000,  0xF80000,  0xE00000,  0xB80000,\n\t\t0xB00000,  0x800000,  0xC80000,  0xD80000,  0x280000,\n\t\t0x400000,  0x80000,   0x680000,  0x500000,  0x180000,\n\t\t0x200000,  0x100000,  0x700000,  0x780000,  0x600000,\n\t\t0x380000,  0x300000,  0x0,       0x480000,  0x580000,\n\t\t0x4280000, 0x4400000, 0x4080000, 0x4680000, 0x4500000,\n\t\t0x4180000, 0x4200000, 0x4100000, 0x4700000, 0x4780000,\n\t\t0x4600000, 0x4380000, 0x4300000, 0x4000000, 0x4480000,\n\t\t0x4580000, 0x4A80000, 0x4C00000, 0x4880000, 0x4E80000,\n\t\t0x4D00000, 0x4980000, 0x4A00000, 0x4900000, 0x4F00000,\n\t\t0x4F80000, 0x4E00000, 0x4B80000, 0x4B00000, 0x4800000,\n\t\t0x4C80000, 0x4D80000, 0x7A80000, 0x7C00000, 0x7880000,\n\t\t0x7E80000, 0x7D00000, 0x7980000, 0x7A00000, 0x7900000,\n\t\t0x7F00000, 0x7F80000, 0x7E00000, 0x7B80000, 0x7B00000,\n\t\t0x7800000, 0x7C80000, 0x7D80000, 0x7280000, 0x7400000,\n\t\t0x7080000, 0x7680000, 0x7500000, 0x7180000, 0x7200000,\n\t\t0x7100000, 0x7700000, 0x7780000, 0x7600000, 0x7380000,\n\t\t0x7300000, 0x7000000, 0x7480000, 0x7580000, 0x2280000,\n\t\t0x2400000, 0x2080000, 0x2680000, 0x2500000, 0x2180000,\n\t\t0x2200000, 0x2100000, 0x2700000, 0x2780000, 0x2600000,\n\t\t0x2380000, 0x2300000, 0x2000000, 0x2480000, 0x2580000,\n\t\t0x3280000, 0x3400000, 0x3080000, 0x3680000, 0x3500000,\n\t\t0x3180000, 0x3200000, 0x3100000, 0x3700000, 0x3780000,\n\t\t0x3600000, 0x3380000, 0x3300000, 0x3000000, 0x3480000,\n\t\t0x3580000, 0x6280000, 0x6400000, 0x6080000, 0x6680000,\n\t\t0x6500000, 0x6180000, 0x6200000, 0x6100000, 0x6700000,\n\t\t0x6780000, 0x6600000, 0x6380000, 0x6300000, 0x6000000,\n\t\t0x6480000, 0x6580000, 0x5A80000, 0x5C00000, 0x5880000,\n\t\t0x5E80000, 0x5D00000, 0x5980000, 0x5A00000, 0x5900000,\n\t\t0x5F00000, 0x5F80000, 0x5E00000, 0x5B80000, 0x5B00000,\n\t\t0x5800000, 0x5C80000, 0x5D80000, 0x1280000, 0x1400000,\n\t\t0x1080000, 0x1680000, 0x1500000, 0x1180000, 0x1200000,\n\t\t0x1100000, 0x1700000, 0x1780000, 0x1600000, 0x1380000,\n\t\t0x1300000, 0x1000000, 0x1480000, 0x1580000, 0x2A80000,\n\t\t0x2C00000, 0x2880000, 0x2E80000, 0x2D00000, 0x2980000,\n\t\t0x2A00000, 0x2900000, 0x2F00000, 0x2F80000, 0x2E00000,\n\t\t0x2B80000, 0x2B00000, 0x2800000, 0x2C80000, 0x2D80000,\n\t\t0x1A80000, 0x1C00000, 0x1880000, 0x1E80000, 0x1D00000,\n\t\t0x1980000, 0x1A00000, 0x1900000, 0x1F00000, 0x1F80000,\n\t\t0x1E00000, 0x1B80000, 0x1B00000, 0x1800000, 0x1C80000,\n\t\t0x1D80000\n\t}, {\n\t\t0x30000002, 0x60000002, 0x38000002, 0x8000002,\n\t\t0x28000002, 0x78000002, 0x68000002, 0x40000002,\n\t\t0x20000002, 0x50000002, 0x48000002, 0x70000002,\n\t\t0x2,        0x18000002, 0x58000002, 0x10000002,\n\t\t0xB0000005, 0xE0000005, 0xB8000005, 0x88000005,\n\t\t0xA8000005, 0xF8000005, 0xE8000005, 0xC0000005,\n\t\t0xA0000005, 0xD0000005, 0xC8000005, 0xF0000005,\n\t\t0x80000005, 0x98000005, 0xD8000005, 0x90000005,\n\t\t0x30000005, 0x60000005, 0x38000005, 0x8000005,\n\t\t0x28000005, 0x78000005, 0x68000005, 0x40000005,\n\t\t0x20000005, 0x50000005, 0x48000005, 0x70000005,\n\t\t0x5,        0x18000005, 0x58000005, 0x10000005,\n\t\t0x30000000, 0x60000000, 0x38000000, 0x8000000,\n\t\t0x28000000, 0x78000000, 0x68000000, 0x40000000,\n\t\t0x20000000, 0x50000000, 0x48000000, 0x70000000,\n\t\t0x0,        0x18000000, 0x58000000, 0x10000000,\n\t\t0xB0000003, 0xE0000003, 0xB8000003, 0x88000003,\n\t\t0xA8000003, 0xF8000003, 0xE8000003, 0xC0000003,\n\t\t0xA0000003, 0xD0000003, 0xC8000003, 0xF0000003,\n\t\t0x80000003, 0x98000003, 0xD8000003, 0x90000003,\n\t\t0x30000001, 0x60000001, 0x38000001, 0x8000001,\n\t\t0x28000001, 0x78000001, 0x68000001, 0x40000001,\n\t\t0x20000001, 0x50000001, 0x48000001, 0x70000001,\n\t\t0x1,        0x18000001, 0x58000001, 0x10000001,\n\t\t0xB0000000, 0xE0000000, 0xB8000000, 0x88000000,\n\t\t0xA8000000, 0xF8000000, 0xE8000000, 0xC0000000,\n\t\t0xA0000000, 0xD0000000, 0xC8000000, 0xF0000000,\n\t\t0x80000000, 0x98000000, 0xD8000000, 0x90000000,\n\t\t0xB0000006, 0xE0000006, 0xB8000006, 0x88000006,\n\t\t0xA8000006, 0xF8000006, 0xE8000006, 0xC0000006,\n\t\t0xA0000006, 0xD0000006, 0xC8000006, 0xF0000006,\n\t\t0x80000006, 0x98000006, 0xD8000006, 0x90000006,\n\t\t0xB0000001, 0xE0000001, 0xB8000001, 0x88000001,\n\t\t0xA8000001, 0xF8000001, 0xE8000001, 0xC0000001,\n\t\t0xA0000001, 0xD0000001, 0xC8000001, 0xF0000001,\n\t\t0x80000001, 0x98000001, 0xD8000001, 0x90000001,\n\t\t0x30000003, 0x60000003, 0x38000003, 0x8000003,\n\t\t0x28000003, 0x78000003, 0x68000003, 0x40000003,\n\t\t0x20000003, 0x50000003, 0x48000003, 0x70000003,\n\t\t0x3,        0x18000003, 0x58000003, 0x10000003,\n\t\t0x30000004, 0x60000004, 0x38000004, 0x8000004,\n\t\t0x28000004, 0x78000004, 0x68000004, 0x40000004,\n\t\t0x20000004, 0x50000004, 0x48000004, 0x70000004,\n\t\t0x4,        0x18000004, 0x58000004, 0x10000004,\n\t\t0xB0000002, 0xE0000002, 0xB8000002, 0x88000002,\n\t\t0xA8000002, 0xF8000002, 0xE8000002, 0xC0000002,\n\t\t0xA0000002, 0xD0000002, 0xC8000002, 0xF0000002,\n\t\t0x80000002, 0x98000002, 0xD8000002, 0x90000002,\n\t\t0xB0000004, 0xE0000004, 0xB8000004, 0x88000004,\n\t\t0xA8000004, 0xF8000004, 0xE8000004, 0xC0000004,\n\t\t0xA0000004, 0xD0000004, 0xC8000004, 0xF0000004,\n\t\t0x80000004, 0x98000004, 0xD8000004, 0x90000004,\n\t\t0x30000006, 0x60000006, 0x38000006, 0x8000006,\n\t\t0x28000006, 0x78000006, 0x68000006, 0x40000006,\n\t\t0x20000006, 0x50000006, 0x48000006, 0x70000006,\n\t\t0x6,        0x18000006, 0x58000006, 0x10000006,\n\t\t0xB0000007, 0xE0000007, 0xB8000007, 0x88000007,\n\t\t0xA8000007, 0xF8000007, 0xE8000007, 0xC0000007,\n\t\t0xA0000007, 0xD0000007, 0xC8000007, 0xF0000007,\n\t\t0x80000007, 0x98000007, 0xD8000007, 0x90000007,\n\t\t0x30000007, 0x60000007, 0x38000007, 0x8000007,\n\t\t0x28000007, 0x78000007, 0x68000007, 0x40000007,\n\t\t0x20000007, 0x50000007, 0x48000007, 0x70000007,\n\t\t0x7,        0x18000007, 0x58000007, 0x10000007\n\t}, {\n\t\t0xE8,  0xD8,  0xA0,  0x88,  0x98,  0xF8,  0xA8,  0xC8,  0x80,  0xD0,\n\t\t0xF0,  0xB8,  0xB0,  0xC0,  0x90,  0xE0,  0x7E8, 0x7D8, 0x7A0, 0x788,\n\t\t0x798, 0x7F8, 0x7A8, 0x7C8, 0x780, 0x7D0, 0x7F0, 0x7B8, 0x7B0, 0x7C0,\n\t\t0x790, 0x7E0, 0x6E8, 0x6D8, 0x6A0, 0x688, 0x698, 0x6F8, 0x6A8, 0x6C8,\n\t\t0x680, 0x6D0, 0x6F0, 0x6B8, 0x6B0, 0x6C0, 0x690, 0x6E0, 0x68,  0x58,\n\t\t0x20,  0x8,   0x18,  0x78,  0x28,  0x48,  0x0,   0x50,  0x70,  0x38,\n\t\t0x30,  0x40,  0x10,  0x60,  0x2E8, 0x2D8, 0x2A0, 0x288, 0x298, 0x2F8,\n\t\t0x2A8, 0x2C8, 0x280, 0x2D0, 0x2F0, 0x2B8, 0x2B0, 0x2C0, 0x290, 0x2E0,\n\t\t0x3E8, 0x3D8, 0x3A0, 0x388, 0x398, 0x3F8, 0x3A8, 0x3C8, 0x380, 0x3D0,\n\t\t0x3F0, 0x3B8, 0x3B0, 0x3C0, 0x390, 0x3E0, 0x568, 0x558, 0x520, 0x508,\n\t\t0x518, 0x578, 0x528, 0x548, 0x500, 0x550, 0x570, 0x538, 0x530, 0x540,\n\t\t0x510, 0x560, 0x268, 0x258, 0x220, 0x208, 0x218, 0x278, 0x228, 0x248,\n\t\t0x200, 0x250, 0x270, 0x238, 0x230, 0x240, 0x210, 0x260, 0x4E8, 0x4D8,\n\t\t0x4A0, 0x488, 0x498, 0x4F8, 0x4A8, 0x4C8, 0x480, 0x4D0, 0x4F0, 0x4B8,\n\t\t0x4B0, 0x4C0, 0x490, 0x4E0, 0x168, 0x158, 0x120, 0x108, 0x118, 0x178,\n\t\t0x128, 0x148, 0x100, 0x150, 0x170, 0x138, 0x130, 0x140, 0x110, 0x160,\n\t\t0x1E8, 0x1D8, 0x1A0, 0x188, 0x198, 0x1F8, 0x1A8, 0x1C8, 0x180, 0x1D0,\n\t\t0x1F0, 0x1B8, 0x1B0, 0x1C0, 0x190, 0x1E0, 0x768, 0x758, 0x720, 0x708,\n\t\t0x718, 0x778, 0x728, 0x748, 0x700, 0x750, 0x770, 0x738, 0x730, 0x740,\n\t\t0x710, 0x760, 0x368, 0x358, 0x320, 0x308, 0x318, 0x378, 0x328, 0x348,\n\t\t0x300, 0x350, 0x370, 0x338, 0x330, 0x340, 0x310, 0x360, 0x5E8, 0x5D8,\n\t\t0x5A0, 0x588, 0x598, 0x5F8, 0x5A8, 0x5C8, 0x580, 0x5D0, 0x5F0, 0x5B8,\n\t\t0x5B0, 0x5C0, 0x590, 0x5E0, 0x468, 0x458, 0x420, 0x408, 0x418, 0x478,\n\t\t0x428, 0x448, 0x400, 0x450, 0x470, 0x438, 0x430, 0x440, 0x410, 0x460,\n\t\t0x668, 0x658, 0x620, 0x608, 0x618, 0x678, 0x628, 0x648, 0x600, 0x650,\n\t\t0x670, 0x638, 0x630, 0x640, 0x610, 0x660\n\t}\n};\n\n/* pre-initialized GOST lookup tables based on rotated S-Box */\nunsigned rhash_gost94_sbox_cryptpro[4][256] = {\n\t{\n\t\t0x2d000, 0x2a000, 0x2a800, 0x2b000, 0x2c000,\n\t\t0x28800, 0x29800, 0x2b800, 0x2e800, 0x2e000,\n\t\t0x2f000, 0x28000, 0x2c800, 0x29000, 0x2d800,\n\t\t0x2f800, 0x7d000, 0x7a000, 0x7a800, 0x7b000,\n\t\t0x7c000, 0x78800, 0x79800, 0x7b800, 0x7e800,\n\t\t0x7e000, 0x7f000, 0x78000, 0x7c800, 0x79000,\n\t\t0x7d800, 0x7f800, 0x25000, 0x22000, 0x22800,\n\t\t0x23000, 0x24000, 0x20800, 0x21800, 0x23800,\n\t\t0x26800, 0x26000, 0x27000, 0x20000, 0x24800,\n\t\t0x21000, 0x25800, 0x27800, 0x5000,  0x2000,\n\t\t0x2800,  0x3000,  0x4000,  0x800,   0x1800,\n\t\t0x3800,  0x6800,  0x6000,  0x7000,  0x0,\n\t\t0x4800,  0x1000,  0x5800,  0x7800,  0x15000,\n\t\t0x12000, 0x12800, 0x13000, 0x14000, 0x10800,\n\t\t0x11800, 0x13800, 0x16800, 0x16000, 0x17000,\n\t\t0x10000, 0x14800, 0x11000, 0x15800, 0x17800,\n\t\t0x6d000, 0x6a000, 0x6a800, 0x6b000, 0x6c000,\n\t\t0x68800, 0x69800, 0x6b800, 0x6e800, 0x6e000,\n\t\t0x6f000, 0x68000, 0x6c800, 0x69000, 0x6d800,\n\t\t0x6f800, 0x5d000, 0x5a000, 0x5a800, 0x5b000,\n\t\t0x5c000, 0x58800, 0x59800, 0x5b800, 0x5e800,\n\t\t0x5e000, 0x5f000, 0x58000, 0x5c800, 0x59000,\n\t\t0x5d800, 0x5f800, 0x4d000, 0x4a000, 0x4a800,\n\t\t0x4b000, 0x4c000, 0x48800, 0x49800, 0x4b800,\n\t\t0x4e800, 0x4e000, 0x4f000, 0x48000, 0x4c800,\n\t\t0x49000, 0x4d800, 0x4f800, 0xd000,  0xa000,\n\t\t0xa800,  0xb000,  0xc000,  0x8800,  0x9800,\n\t\t0xb800,  0xe800,  0xe000,  0xf000,  0x8000,\n\t\t0xc800,  0x9000,  0xd800,  0xf800,  0x3d000,\n\t\t0x3a000, 0x3a800, 0x3b000, 0x3c000, 0x38800,\n\t\t0x39800, 0x3b800, 0x3e800, 0x3e000, 0x3f000,\n\t\t0x38000, 0x3c800, 0x39000, 0x3d800, 0x3f800,\n\t\t0x35000, 0x32000, 0x32800, 0x33000, 0x34000,\n\t\t0x30800, 0x31800, 0x33800, 0x36800, 0x36000,\n\t\t0x37000, 0x30000, 0x34800, 0x31000, 0x35800,\n\t\t0x37800, 0x1d000, 0x1a000, 0x1a800, 0x1b000,\n\t\t0x1c000, 0x18800, 0x19800, 0x1b800, 0x1e800,\n\t\t0x1e000, 0x1f000, 0x18000, 0x1c800, 0x19000,\n\t\t0x1d800, 0x1f800, 0x65000, 0x62000, 0x62800,\n\t\t0x63000, 0x64000, 0x60800, 0x61800, 0x63800,\n\t\t0x66800, 0x66000, 0x67000, 0x60000, 0x64800,\n\t\t0x61000, 0x65800, 0x67800, 0x75000, 0x72000,\n\t\t0x72800, 0x73000, 0x74000, 0x70800, 0x71800,\n\t\t0x73800, 0x76800, 0x76000, 0x77000, 0x70000,\n\t\t0x74800, 0x71000, 0x75800, 0x77800, 0x55000,\n\t\t0x52000, 0x52800, 0x53000, 0x54000, 0x50800,\n\t\t0x51800, 0x53800, 0x56800, 0x56000, 0x57000,\n\t\t0x50000, 0x54800, 0x51000, 0x55800, 0x57800,\n\t\t0x45000, 0x42000, 0x42800, 0x43000, 0x44000,\n\t\t0x40800, 0x41800, 0x43800, 0x46800, 0x46000,\n\t\t0x47000, 0x40000, 0x44800, 0x41000, 0x45800, 0x47800\n\t}, {\n\t\t0x2380000, 0x2780000, 0x2600000, 0x2700000, 0x2480000,\n\t\t0x2200000, 0x2080000, 0x2000000, 0x2180000, 0x2580000,\n\t\t0x2280000, 0x2100000, 0x2300000, 0x2500000, 0x2400000,\n\t\t0x2680000, 0x5380000, 0x5780000, 0x5600000, 0x5700000,\n\t\t0x5480000, 0x5200000, 0x5080000, 0x5000000, 0x5180000,\n\t\t0x5580000, 0x5280000, 0x5100000, 0x5300000, 0x5500000,\n\t\t0x5400000, 0x5680000, 0x3b80000, 0x3f80000, 0x3e00000,\n\t\t0x3f00000, 0x3c80000, 0x3a00000, 0x3880000, 0x3800000,\n\t\t0x3980000, 0x3d80000, 0x3a80000, 0x3900000, 0x3b00000,\n\t\t0x3d00000, 0x3c00000, 0x3e80000, 0x6380000, 0x6780000,\n\t\t0x6600000, 0x6700000, 0x6480000, 0x6200000, 0x6080000,\n\t\t0x6000000, 0x6180000, 0x6580000, 0x6280000, 0x6100000,\n\t\t0x6300000, 0x6500000, 0x6400000, 0x6680000, 0x380000,\n\t\t0x780000,  0x600000,  0x700000,  0x480000,  0x200000,\n\t\t0x80000,   0x0,       0x180000,  0x580000,  0x280000,\n\t\t0x100000,  0x300000,  0x500000,  0x400000,  0x680000,\n\t\t0x7b80000, 0x7f80000, 0x7e00000, 0x7f00000, 0x7c80000,\n\t\t0x7a00000, 0x7880000, 0x7800000, 0x7980000, 0x7d80000,\n\t\t0x7a80000, 0x7900000, 0x7b00000, 0x7d00000, 0x7c00000,\n\t\t0x7e80000, 0x1380000, 0x1780000, 0x1600000, 0x1700000,\n\t\t0x1480000, 0x1200000, 0x1080000, 0x1000000, 0x1180000,\n\t\t0x1580000, 0x1280000, 0x1100000, 0x1300000, 0x1500000,\n\t\t0x1400000, 0x1680000, 0x4380000, 0x4780000, 0x4600000,\n\t\t0x4700000, 0x4480000, 0x4200000, 0x4080000, 0x4000000,\n\t\t0x4180000, 0x4580000, 0x4280000, 0x4100000, 0x4300000,\n\t\t0x4500000, 0x4400000, 0x4680000, 0x7380000, 0x7780000,\n\t\t0x7600000, 0x7700000, 0x7480000, 0x7200000, 0x7080000,\n\t\t0x7000000, 0x7180000, 0x7580000, 0x7280000, 0x7100000,\n\t\t0x7300000, 0x7500000, 0x7400000, 0x7680000, 0xb80000,\n\t\t0xf80000,  0xe00000,  0xf00000,  0xc80000,  0xa00000,\n\t\t0x880000,  0x800000,  0x980000,  0xd80000,  0xa80000,\n\t\t0x900000,  0xb00000,  0xd00000,  0xc00000,  0xe80000,\n\t\t0x3380000, 0x3780000, 0x3600000, 0x3700000, 0x3480000,\n\t\t0x3200000, 0x3080000, 0x3000000, 0x3180000, 0x3580000,\n\t\t0x3280000, 0x3100000, 0x3300000, 0x3500000, 0x3400000,\n\t\t0x3680000, 0x2b80000, 0x2f80000, 0x2e00000, 0x2f00000,\n\t\t0x2c80000, 0x2a00000, 0x2880000, 0x2800000, 0x2980000,\n\t\t0x2d80000, 0x2a80000, 0x2900000, 0x2b00000, 0x2d00000,\n\t\t0x2c00000, 0x2e80000, 0x6b80000, 0x6f80000, 0x6e00000,\n\t\t0x6f00000, 0x6c80000, 0x6a00000, 0x6880000, 0x6800000,\n\t\t0x6980000, 0x6d80000, 0x6a80000, 0x6900000, 0x6b00000,\n\t\t0x6d00000, 0x6c00000, 0x6e80000, 0x5b80000, 0x5f80000,\n\t\t0x5e00000, 0x5f00000, 0x5c80000, 0x5a00000, 0x5880000,\n\t\t0x5800000, 0x5980000, 0x5d80000, 0x5a80000, 0x5900000,\n\t\t0x5b00000, 0x5d00000, 0x5c00000, 0x5e80000, 0x4b80000,\n\t\t0x4f80000, 0x4e00000, 0x4f00000, 0x4c80000, 0x4a00000,\n\t\t0x4880000, 0x4800000, 0x4980000, 0x4d80000, 0x4a80000,\n\t\t0x4900000, 0x4b00000, 0x4d00000, 0x4c00000, 0x4e80000,\n\t\t0x1b80000, 0x1f80000, 0x1e00000, 0x1f00000, 0x1c80000,\n\t\t0x1a00000, 0x1880000, 0x1800000, 0x1980000, 0x1d80000,\n\t\t0x1a80000, 0x1900000, 0x1b00000, 0x1d00000, 0x1c00000,\n\t\t0x1e80000\n\t}, {\n\t\t0xb8000003, 0xb0000003, 0xa0000003, 0xd8000003, 0xc8000003,\n\t\t0xe0000003, 0x90000003, 0xd0000003, 0x88000003, 0xc0000003,\n\t\t0x80000003, 0xf0000003, 0xf8000003, 0xe8000003, 0x98000003,\n\t\t0xa8000003, 0x38000003, 0x30000003, 0x20000003, 0x58000003,\n\t\t0x48000003, 0x60000003, 0x10000003, 0x50000003, 0x8000003,\n\t\t0x40000003, 0x3,        0x70000003, 0x78000003, 0x68000003,\n\t\t0x18000003, 0x28000003, 0x38000001, 0x30000001, 0x20000001,\n\t\t0x58000001, 0x48000001, 0x60000001, 0x10000001, 0x50000001,\n\t\t0x8000001,  0x40000001, 0x1,        0x70000001, 0x78000001,\n\t\t0x68000001, 0x18000001, 0x28000001, 0x38000002, 0x30000002,\n\t\t0x20000002, 0x58000002, 0x48000002, 0x60000002, 0x10000002,\n\t\t0x50000002, 0x8000002,  0x40000002, 0x2,        0x70000002,\n\t\t0x78000002, 0x68000002, 0x18000002, 0x28000002, 0xb8000006,\n\t\t0xb0000006, 0xa0000006, 0xd8000006, 0xc8000006, 0xe0000006,\n\t\t0x90000006, 0xd0000006, 0x88000006, 0xc0000006, 0x80000006,\n\t\t0xf0000006, 0xf8000006, 0xe8000006, 0x98000006, 0xa8000006,\n\t\t0xb8000004, 0xb0000004, 0xa0000004, 0xd8000004, 0xc8000004,\n\t\t0xe0000004, 0x90000004, 0xd0000004, 0x88000004, 0xc0000004,\n\t\t0x80000004, 0xf0000004, 0xf8000004, 0xe8000004, 0x98000004,\n\t\t0xa8000004, 0xb8000007, 0xb0000007, 0xa0000007, 0xd8000007,\n\t\t0xc8000007, 0xe0000007, 0x90000007, 0xd0000007, 0x88000007,\n\t\t0xc0000007, 0x80000007, 0xf0000007, 0xf8000007, 0xe8000007,\n\t\t0x98000007, 0xa8000007, 0x38000000, 0x30000000, 0x20000000,\n\t\t0x58000000, 0x48000000, 0x60000000, 0x10000000, 0x50000000,\n\t\t0x8000000,  0x40000000, 0x0,        0x70000000, 0x78000000,\n\t\t0x68000000, 0x18000000, 0x28000000, 0x38000005, 0x30000005,\n\t\t0x20000005, 0x58000005, 0x48000005, 0x60000005, 0x10000005,\n\t\t0x50000005, 0x8000005,  0x40000005, 0x5,        0x70000005,\n\t\t0x78000005, 0x68000005, 0x18000005, 0x28000005, 0xb8000000,\n\t\t0xb0000000, 0xa0000000, 0xd8000000, 0xc8000000, 0xe0000000,\n\t\t0x90000000, 0xd0000000, 0x88000000, 0xc0000000, 0x80000000,\n\t\t0xf0000000, 0xf8000000, 0xe8000000, 0x98000000, 0xa8000000,\n\t\t0xb8000002, 0xb0000002, 0xa0000002, 0xd8000002, 0xc8000002,\n\t\t0xe0000002, 0x90000002, 0xd0000002, 0x88000002, 0xc0000002,\n\t\t0x80000002, 0xf0000002, 0xf8000002, 0xe8000002, 0x98000002,\n\t\t0xa8000002, 0xb8000005, 0xb0000005, 0xa0000005, 0xd8000005,\n\t\t0xc8000005, 0xe0000005, 0x90000005, 0xd0000005, 0x88000005,\n\t\t0xc0000005, 0x80000005, 0xf0000005, 0xf8000005, 0xe8000005,\n\t\t0x98000005, 0xa8000005, 0x38000004, 0x30000004, 0x20000004,\n\t\t0x58000004, 0x48000004, 0x60000004, 0x10000004, 0x50000004,\n\t\t0x8000004,  0x40000004, 0x4,        0x70000004, 0x78000004,\n\t\t0x68000004, 0x18000004, 0x28000004, 0x38000007, 0x30000007,\n\t\t0x20000007, 0x58000007, 0x48000007, 0x60000007, 0x10000007,\n\t\t0x50000007, 0x8000007,  0x40000007, 0x7,        0x70000007,\n\t\t0x78000007, 0x68000007, 0x18000007, 0x28000007, 0x38000006,\n\t\t0x30000006, 0x20000006, 0x58000006, 0x48000006, 0x60000006,\n\t\t0x10000006, 0x50000006, 0x8000006,  0x40000006, 0x6,\n\t\t0x70000006, 0x78000006, 0x68000006, 0x18000006, 0x28000006,\n\t\t0xb8000001, 0xb0000001, 0xa0000001, 0xd8000001, 0xc8000001,\n\t\t0xe0000001, 0x90000001, 0xd0000001, 0x88000001, 0xc0000001,\n\t\t0x80000001, 0xf0000001, 0xf8000001, 0xe8000001, 0x98000001,\n\t\t0xa8000001\n\t}, {\n\t\t0xe8,  0xf0,  0xa0,  0x88,  0xb8,  0x80,  0xa8,  0xd0,  0x98,  0xe0,\n\t\t0xc0,  0xf8,  0xb0,  0x90,  0xc8,  0xd8,  0x1e8, 0x1f0, 0x1a0, 0x188,\n\t\t0x1b8, 0x180, 0x1a8, 0x1d0, 0x198, 0x1e0, 0x1c0, 0x1f8, 0x1b0, 0x190,\n\t\t0x1c8, 0x1d8, 0x568, 0x570, 0x520, 0x508, 0x538, 0x500, 0x528, 0x550,\n\t\t0x518, 0x560, 0x540, 0x578, 0x530, 0x510, 0x548, 0x558, 0x4e8, 0x4f0,\n\t\t0x4a0, 0x488, 0x4b8, 0x480, 0x4a8, 0x4d0, 0x498, 0x4e0, 0x4c0, 0x4f8,\n\t\t0x4b0, 0x490, 0x4c8, 0x4d8, 0x2e8, 0x2f0, 0x2a0, 0x288, 0x2b8, 0x280,\n\t\t0x2a8, 0x2d0, 0x298, 0x2e0, 0x2c0, 0x2f8, 0x2b0, 0x290, 0x2c8, 0x2d8,\n\t\t0x5e8, 0x5f0, 0x5a0, 0x588, 0x5b8, 0x580, 0x5a8, 0x5d0, 0x598, 0x5e0,\n\t\t0x5c0, 0x5f8, 0x5b0, 0x590, 0x5c8, 0x5d8, 0x268, 0x270, 0x220, 0x208,\n\t\t0x238, 0x200, 0x228, 0x250, 0x218, 0x260, 0x240, 0x278, 0x230, 0x210,\n\t\t0x248, 0x258, 0x7e8, 0x7f0, 0x7a0, 0x788, 0x7b8, 0x780, 0x7a8, 0x7d0,\n\t\t0x798, 0x7e0, 0x7c0, 0x7f8, 0x7b0, 0x790, 0x7c8, 0x7d8, 0x468, 0x470,\n\t\t0x420, 0x408, 0x438, 0x400, 0x428, 0x450, 0x418, 0x460, 0x440, 0x478,\n\t\t0x430, 0x410, 0x448, 0x458, 0x368, 0x370, 0x320, 0x308, 0x338, 0x300,\n\t\t0x328, 0x350, 0x318, 0x360, 0x340, 0x378, 0x330, 0x310, 0x348, 0x358,\n\t\t0x3e8, 0x3f0, 0x3a0, 0x388, 0x3b8, 0x380, 0x3a8, 0x3d0, 0x398, 0x3e0,\n\t\t0x3c0, 0x3f8, 0x3b0, 0x390, 0x3c8, 0x3d8, 0x768, 0x770, 0x720, 0x708,\n\t\t0x738, 0x700, 0x728, 0x750, 0x718, 0x760, 0x740, 0x778, 0x730, 0x710,\n\t\t0x748, 0x758, 0x6e8, 0x6f0, 0x6a0, 0x688, 0x6b8, 0x680, 0x6a8, 0x6d0,\n\t\t0x698, 0x6e0, 0x6c0, 0x6f8, 0x6b0, 0x690, 0x6c8, 0x6d8, 0x68,  0x70,\n\t\t0x20,  0x8,   0x38,  0x0,   0x28,  0x50,  0x18,  0x60,  0x40,  0x78,\n\t\t0x30,  0x10,  0x48,  0x58,  0x168, 0x170, 0x120, 0x108, 0x138, 0x100,\n\t\t0x128, 0x150, 0x118, 0x160, 0x140, 0x178, 0x130, 0x110, 0x148, 0x158,\n\t\t0x668, 0x670, 0x620, 0x608, 0x638, 0x600, 0x628, 0x650, 0x618, 0x660,\n\t\t0x640, 0x678, 0x630, 0x610, 0x648, 0x658\n\t}\n};\n\n#endif /* GENERATE_GOST94_LOOKUP_TABLE */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/gost94.h",
    "content": "﻿/* gost94.h */\n#ifndef GOST94_H\n#define GOST94_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define gost94_block_size 32\n#define gost94_hash_length 32\n\n/* algorithm context */\ntypedef struct gost94_ctx\n{\n\tunsigned hash[8];  /* algorithm 256-bit state */\n\tunsigned sum[8];   /* sum of processed message blocks */\n\tunsigned char message[gost94_block_size]; /* 256-bit buffer for leftovers */\n\tuint64_t length;   /* number of processed bytes */\n\tunsigned cryptpro; /* boolean flag, the type of sbox to use */\n} gost94_ctx;\n\n/* hash functions */\n\nvoid rhash_gost94_init(gost94_ctx* ctx);\nvoid rhash_gost94_cryptopro_init(gost94_ctx* ctx);\nvoid rhash_gost94_update(gost94_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_gost94_final(gost94_ctx* ctx, unsigned char result[32]);\n\n#ifdef GENERATE_GOST94_LOOKUP_TABLE\nvoid rhash_gost94_init_table(void); /* initialize algorithm static data */\n#endif\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* GOST94_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/has160.c",
    "content": "﻿/* hash.c - an implementation of HAS-160 Algorithm.\n *\n * Copyright (c) 2009, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n *\n * HAS-160 is a cryptographic hash function designed for use with the\n * Korean KCDSA digital signature algorithm. It derives from SHA-1,\n * with assorted changes intended to increase its security.\n * It produces a 160-bit message digest.\n *\n * HAS-160 was developed in 1998 by KISA\n * (Korea Information Security Agency) + Academic.\n */\n\n#include <string.h>\n#include \"byte_order.h\"\n#include \"has160.h\"\n\n/**\n * Initialize algorithm context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_has160_init(has160_ctx* ctx)\n{\n\tmemset(ctx, 0, sizeof(*ctx));\n\n\t/* initialize algorithm state */\n\tctx->hash[0] = 0x67452301;\n\tctx->hash[1] = 0xefcdab89;\n\tctx->hash[2] = 0x98badcfe;\n\tctx->hash[3] = 0x10325476;\n\tctx->hash[4] = 0xc3d2e1f0;\n}\n\n/* HAS-160 boolean functions:\n * F1(x,y,z) == (x AND y) OR ((NOT x) AND z) = ((y XOR z) AND x) XOR z\n * F2(x,y,z) == x XOR y XOR z\n * F3(x,y,z) == y XOR (x OR (NOT Z))\n * F4(x,y,z) == x XOR y XOR z                 */\n#define STEP_F1(A, B, C, D, E, msg, rot) \\\n\tE += ROTL32(A, rot) + (D ^ (B & (C ^ D))) + msg; \\\n\tB  = ROTL32(B, 10);\n#define STEP_F2(A, B, C, D, E, msg, rot) \\\n\tE += ROTL32(A, rot) + (B ^ C ^ D) + msg + 0x5A827999; \\\n\tB  = ROTL32(B, 17);\n#define STEP_F3(A, B, C, D, E, msg, rot) \\\n\tE += ROTL32(A, rot) + (C ^ (B | ~D)) + msg + 0x6ED9EBA1; \\\n\tB  = ROTL32(B, 25);\n#define STEP_F4(A, B, C, D, E, msg, rot) \\\n\tE += ROTL32(A, rot) + (B ^ C ^ D) + msg + 0x8F1BBCDC; \\\n\tB  = ROTL32(B, 30);\n\n/**\n * The core transformation. Process a 512-bit block.\n *\n * @param hash algorithm state\n * @param block the message block to process\n */\nstatic void rhash_has160_process_block(unsigned* hash, const unsigned* block)\n{\n\tunsigned X[32];\n\t{\n\t\tunsigned j;\n\t\tfor (j = 0; j < 16; j++) {\n\t\t\tX[j] = le2me_32(block[j]);\n\t\t}\n\n\t\tX[16] = X[ 0] ^ X[ 1] ^ X[ 2] ^ X[ 3]; /* for rounds  1..20 */\n\t\tX[17] = X[ 4] ^ X[ 5] ^ X[ 6] ^ X[ 7];\n\t\tX[18] = X[ 8] ^ X[ 9] ^ X[10] ^ X[11];\n\t\tX[19] = X[12] ^ X[13] ^ X[14] ^ X[15];\n\t\tX[20] = X[ 3] ^ X[ 6] ^ X[ 9] ^ X[12]; /* for rounds 21..40 */\n\t\tX[21] = X[ 2] ^ X[ 5] ^ X[ 8] ^ X[15];\n\t\tX[22] = X[ 1] ^ X[ 4] ^ X[11] ^ X[14];\n\t\tX[23] = X[ 0] ^ X[ 7] ^ X[10] ^ X[13];\n\t\tX[24] = X[ 5] ^ X[ 7] ^ X[12] ^ X[14]; /* for rounds 41..60 */\n\t\tX[25] = X[ 0] ^ X[ 2] ^ X[ 9] ^ X[11];\n\t\tX[26] = X[ 4] ^ X[ 6] ^ X[13] ^ X[15];\n\t\tX[27] = X[ 1] ^ X[ 3] ^ X[ 8] ^ X[10];\n\t\tX[28] = X[ 2] ^ X[ 7] ^ X[ 8] ^ X[13]; /* for rounds 61..80 */\n\t\tX[29] = X[ 3] ^ X[ 4] ^ X[ 9] ^ X[14];\n\t\tX[30] = X[ 0] ^ X[ 5] ^ X[10] ^ X[15];\n\t\tX[31] = X[ 1] ^ X[ 6] ^ X[11] ^ X[12];\n\t}\n\n\n\t{\n\t\tunsigned A, B, C, D, E;\n\n\t\tA = hash[0];\n\t\tB = hash[1];\n\t\tC = hash[2];\n\t\tD = hash[3];\n\t\tE = hash[4];\n\n\t\tSTEP_F1(A,B,C,D,E,X[18], 5);\n\t\tSTEP_F1(E,A,B,C,D,X[ 0],11);\n\t\tSTEP_F1(D,E,A,B,C,X[ 1], 7);\n\t\tSTEP_F1(C,D,E,A,B,X[ 2],15);\n\t\tSTEP_F1(B,C,D,E,A,X[ 3], 6);\n\t\tSTEP_F1(A,B,C,D,E,X[19],13);\n\t\tSTEP_F1(E,A,B,C,D,X[ 4], 8);\n\t\tSTEP_F1(D,E,A,B,C,X[ 5],14);\n\t\tSTEP_F1(C,D,E,A,B,X[ 6], 7);\n\t\tSTEP_F1(B,C,D,E,A,X[ 7],12);\n\t\tSTEP_F1(A,B,C,D,E,X[16], 9);\n\t\tSTEP_F1(E,A,B,C,D,X[ 8],11);\n\t\tSTEP_F1(D,E,A,B,C,X[ 9], 8);\n\t\tSTEP_F1(C,D,E,A,B,X[10],15);\n\t\tSTEP_F1(B,C,D,E,A,X[11], 6);\n\t\tSTEP_F1(A,B,C,D,E,X[17],12);\n\t\tSTEP_F1(E,A,B,C,D,X[12], 9);\n\t\tSTEP_F1(D,E,A,B,C,X[13],14);\n\t\tSTEP_F1(C,D,E,A,B,X[14], 5);\n\t\tSTEP_F1(B,C,D,E,A,X[15],13);\n\n\t\tSTEP_F2(A,B,C,D,E,X[22], 5);\n\t\tSTEP_F2(E,A,B,C,D,X[ 3],11);\n\t\tSTEP_F2(D,E,A,B,C,X[ 6], 7);\n\t\tSTEP_F2(C,D,E,A,B,X[ 9],15);\n\t\tSTEP_F2(B,C,D,E,A,X[12], 6);\n\t\tSTEP_F2(A,B,C,D,E,X[23],13);\n\t\tSTEP_F2(E,A,B,C,D,X[15], 8);\n\t\tSTEP_F2(D,E,A,B,C,X[ 2],14);\n\t\tSTEP_F2(C,D,E,A,B,X[ 5], 7);\n\t\tSTEP_F2(B,C,D,E,A,X[ 8],12);\n\t\tSTEP_F2(A,B,C,D,E,X[20], 9);\n\t\tSTEP_F2(E,A,B,C,D,X[11],11);\n\t\tSTEP_F2(D,E,A,B,C,X[14], 8);\n\t\tSTEP_F2(C,D,E,A,B,X[ 1],15);\n\t\tSTEP_F2(B,C,D,E,A,X[ 4], 6);\n\t\tSTEP_F2(A,B,C,D,E,X[21],12);\n\t\tSTEP_F2(E,A,B,C,D,X[ 7], 9);\n\t\tSTEP_F2(D,E,A,B,C,X[10],14);\n\t\tSTEP_F2(C,D,E,A,B,X[13], 5);\n\t\tSTEP_F2(B,C,D,E,A,X[ 0],13);\n\n\t\tSTEP_F3(A,B,C,D,E,X[26], 5);\n\t\tSTEP_F3(E,A,B,C,D,X[12],11);\n\t\tSTEP_F3(D,E,A,B,C,X[ 5], 7);\n\t\tSTEP_F3(C,D,E,A,B,X[14],15);\n\t\tSTEP_F3(B,C,D,E,A,X[ 7], 6);\n\t\tSTEP_F3(A,B,C,D,E,X[27],13);\n\t\tSTEP_F3(E,A,B,C,D,X[ 0], 8);\n\t\tSTEP_F3(D,E,A,B,C,X[ 9],14);\n\t\tSTEP_F3(C,D,E,A,B,X[ 2], 7);\n\t\tSTEP_F3(B,C,D,E,A,X[11],12);\n\t\tSTEP_F3(A,B,C,D,E,X[24], 9);\n\t\tSTEP_F3(E,A,B,C,D,X[ 4],11);\n\t\tSTEP_F3(D,E,A,B,C,X[13], 8);\n\t\tSTEP_F3(C,D,E,A,B,X[ 6],15);\n\t\tSTEP_F3(B,C,D,E,A,X[15], 6);\n\t\tSTEP_F3(A,B,C,D,E,X[25],12);\n\t\tSTEP_F3(E,A,B,C,D,X[ 8], 9);\n\t\tSTEP_F3(D,E,A,B,C,X[ 1],14);\n\t\tSTEP_F3(C,D,E,A,B,X[10], 5);\n\t\tSTEP_F3(B,C,D,E,A,X[ 3],13);\n\n\t\tSTEP_F4(A,B,C,D,E,X[30], 5);\n\t\tSTEP_F4(E,A,B,C,D,X[ 7],11);\n\t\tSTEP_F4(D,E,A,B,C,X[ 2], 7);\n\t\tSTEP_F4(C,D,E,A,B,X[13],15);\n\t\tSTEP_F4(B,C,D,E,A,X[ 8], 6);\n\t\tSTEP_F4(A,B,C,D,E,X[31],13);\n\t\tSTEP_F4(E,A,B,C,D,X[ 3], 8);\n\t\tSTEP_F4(D,E,A,B,C,X[14],14);\n\t\tSTEP_F4(C,D,E,A,B,X[ 9], 7);\n\t\tSTEP_F4(B,C,D,E,A,X[ 4],12);\n\t\tSTEP_F4(A,B,C,D,E,X[28], 9);\n\t\tSTEP_F4(E,A,B,C,D,X[15],11);\n\t\tSTEP_F4(D,E,A,B,C,X[10], 8);\n\t\tSTEP_F4(C,D,E,A,B,X[ 5],15);\n\t\tSTEP_F4(B,C,D,E,A,X[ 0], 6);\n\t\tSTEP_F4(A,B,C,D,E,X[29],12);\n\t\tSTEP_F4(E,A,B,C,D,X[11], 9);\n\t\tSTEP_F4(D,E,A,B,C,X[ 6],14);\n\t\tSTEP_F4(C,D,E,A,B,X[ 1], 5);\n\t\tSTEP_F4(B,C,D,E,A,X[12],13);\n\n\t\thash[0] += A;\n\t\thash[1] += B;\n\t\thash[2] += C;\n\t\thash[3] += D;\n\t\thash[4] += E;\n\t}\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_has160_update(has160_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tunsigned index = (unsigned)ctx->length & 63;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tunsigned left = has160_block_size - index;\n\t\tmemcpy((char*)ctx->message + index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_has160_process_block(ctx->hash, ctx->message);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= has160_block_size) {\n\t\tunsigned* aligned_message_block;\n\t\tif (IS_ALIGNED_32(msg)) {\n\t\t\t/* the most common case is processing a 32-bit aligned message\n\t\t\twithout copying it */\n\t\t\taligned_message_block = (unsigned*)msg;\n\t\t} else {\n\t\t\tmemcpy(ctx->message, msg, has160_block_size);\n\t\t\taligned_message_block = ctx->message;\n\t\t}\n\n\t\trhash_has160_process_block(ctx->hash, aligned_message_block);\n\t\tmsg  += has160_block_size;\n\t\tsize -= has160_block_size;\n\t}\n\tif (size) {\n\t\t/* save leftovers */\n\t\tmemcpy(ctx->message, msg, size);\n\t}\n}\n\n/**\n * Compute and save calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_has160_final(has160_ctx* ctx, unsigned char* result)\n{\n\tunsigned shift = ((unsigned)ctx->length & 3) * 8;\n\tunsigned index = ((unsigned)ctx->length & 63) >> 2;\n\n\t/* pad message and run for last block */\n#if IS_LITTLE_ENDIAN\n\tctx->message[index]   &= ~(0xFFFFFFFFu << shift);\n\tctx->message[index++] ^= 0x80u << shift;\n#else\n\tctx->message[index]   &= ~(0xFFFFFFFFu >> shift);\n\tctx->message[index++] ^= 0x80000000u >> shift;\n#endif\n\n\t/* if no room left in the message to store 64-bit message length */\n\tif (index > 14) {\n\t\t/* then fill the rest with zeros and process it */\n\t\twhile (index < 16) {\n\t\t\tctx->message[index++] = 0;\n\t\t}\n\t\trhash_has160_process_block(ctx->hash, ctx->message);\n\t\tindex = 0;\n\t}\n\twhile (index < 14) {\n\t\tctx->message[index++] = 0;\n\t}\n\tctx->message[14] = le2me_32( (unsigned)(ctx->length << 3)  );\n\tctx->message[15] = le2me_32( (unsigned)(ctx->length >> 29) );\n\trhash_has160_process_block(ctx->hash, ctx->message);\n\n\tle32_copy(result, 0, &ctx->hash, has160_hash_size);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/has160.h",
    "content": "﻿/* has160.h */\n#ifndef HAS160_H\n#define HAS160_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define has160_block_size 64\n#define has160_hash_size 20\n\ntypedef struct has160_ctx\n{\n\tunsigned message[has160_block_size / 4]; /* 512-bit buffer for leftovers */\n\tuint64_t length;     /* number of processed bytes */\n\tunsigned hash[5];   /* 160-bit algorithm internal hashing state */\n} has160_ctx;\n\n/* hash functions */\n\nvoid rhash_has160_init(has160_ctx* ctx);\nvoid rhash_has160_update(has160_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_has160_final(has160_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* HAS160_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/hex.c",
    "content": "﻿/* hex.c - conversion for hexadecimal and base32 strings.\n *\n * Copyright (c) 2008, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n#include \"hex.h\"\n#include \"util.h\"\n#include <ctype.h>\n#include <string.h>\n\n/**\n * Store hexadecimal representation of a binary string to given buffer.\n *\n * @param dst the buffer to receive hexadecimal representation\n * @param src binary string\n * @param length string length\n * @param upper_case flag to print string in uppercase\n */\nvoid rhash_byte_to_hex(char* dst, const unsigned char* src, size_t length, int upper_case)\n{\n\tconst char hex_add = (upper_case ? 'A' - 10 : 'a' - 10);\n\tfor (; length > 0; src++, length--) {\n\t\tconst unsigned char hi = (*src >> 4) & 15;\n\t\tconst unsigned char lo = *src & 15;\n\t\t*dst++ = (hi > 9 ? hi + hex_add : hi + '0');\n\t\t*dst++ = (lo > 9 ? lo + hex_add : lo + '0');\n\t}\n\t*dst = '\\0';\n}\n\n/**\n * Encode a binary string to base32.\n *\n * @param dst the buffer to store result\n * @param src binary string\n * @param length string length\n * @param upper_case flag to print string in uppercase\n */\nvoid rhash_byte_to_base32(char* dst, const unsigned char* src, size_t length, int upper_case)\n{\n\tconst char a = (upper_case ? 'A' : 'a');\n\tunsigned shift = 0;\n\tunsigned char word;\n\tconst unsigned char* e = src + length;\n\twhile (src < e) {\n\t\tif (shift > 3) {\n\t\t\tword = (*src & (0xFF >> shift));\n\t\t\tshift = (shift + 5) % 8;\n\t\t\tword <<= shift;\n\t\t\tif (src + 1 < e)\n\t\t\t\tword |= *(src + 1) >> (8 - shift);\n\t\t\t++src;\n\t\t} else {\n\t\t\tshift = (shift + 5) % 8;\n\t\t\tword = ( *src >> ( (8 - shift) & 7 ) ) & 0x1F;\n\t\t\tif (shift == 0) src++;\n\t\t}\n\t\t*dst++ = ( word < 26 ? word + a : word + '2' - 26 );\n\t}\n\t*dst = '\\0';\n}\n\n/**\n * Encode a binary string to base64.\n * Encoded output length is always a multiple of 4 bytes.\n *\n * @param dst the buffer to store result\n * @param src binary string\n * @param length string length\n */\nvoid rhash_byte_to_base64(char* dst, const unsigned char* src, size_t length)\n{\n\tstatic const char* tail = \"0123456789+/\";\n\tunsigned shift = 0;\n\tunsigned char word;\n\tconst unsigned char* e = src + length;\n\twhile (src < e) {\n\t\tif (shift > 2) {\n\t\t\tword = (*src & (0xFF >> shift));\n\t\t\tshift = (shift + 6) % 8;\n\t\t\tword <<= shift;\n\t\t\tif (src + 1 < e)\n\t\t\t\tword |= *(src + 1) >> (8 - shift);\n\t\t\t++src;\n\t\t} else {\n\t\t\tshift = (shift + 6) % 8;\n\t\t\tword = ( *src >> ( (8 - shift) & 7 ) ) & 0x3F;\n\t\t\tif (shift == 0) src++;\n\t\t}\n\t\t*dst++ = ( word < 52 ? (word < 26 ? word + 'A' : word - 26 + 'a') : tail[word - 52]);\n\t}\n\tif (shift > 0) {\n\t\t*dst++ = '=';\n\t\tif (shift == 4) *dst++ = '=';\n\t}\n\t*dst = '\\0';\n}\n\nsize_t rhash_base64_url_encoded_helper(char* dst, const unsigned char* src, size_t length, int url_encode, int upper_case)\n{\n#define B64_CHUNK_SIZE 120\n\tchar buffer[164];\n\tRHASH_ASSERT((BASE64_LENGTH(B64_CHUNK_SIZE) + 4) <= sizeof(buffer));\n\tRHASH_ASSERT((B64_CHUNK_SIZE % 6) == 0);\n#ifdef __clang_analyzer__\n\tmemset(buffer, 0, sizeof(buffer));\n#endif\n\tif (url_encode) {\n\t\tsize_t result_length = 0;\n\t\tfor (; length > 0; src += B64_CHUNK_SIZE) {\n\t\t\tsize_t chunk_size = (length < B64_CHUNK_SIZE ? length : B64_CHUNK_SIZE);\n\t\t\tsize_t encoded_length;\n\t\t\trhash_byte_to_base64(buffer, src, chunk_size);\n\t\t\tencoded_length = rhash_urlencode(dst, buffer, BASE64_LENGTH(chunk_size), upper_case);\n\t\t\tresult_length += encoded_length;\n\t\t\tdst += encoded_length;\n\t\t\tlength -= chunk_size;\n\t\t}\n\t\treturn result_length;\n\t}\n\trhash_byte_to_base64(dst, src, length);\n\treturn BASE64_LENGTH(length);\n}\n\n/* RFC 3986: safe url characters are ascii alpha-numeric and \"-._~\", other characters should be percent-encoded */\nstatic unsigned url_safe_char_mask[4] = { 0, 0x03ff6000, 0x87fffffe, 0x47fffffe };\n#define IS_URL_GOOD_CHAR(c) ((unsigned)(c) < 128 && (url_safe_char_mask[c >> 5] & (1 << (c & 31))))\n\n/**\n * URL-encode specified binary string.\n *\n * @param dst (nullable) buffer to output encoded string to,\n *            NULL to just calculate the lengths of encoded string\n * @param src binary string to encode\n * @param size size of the binary string\n * @param upper_case flag to output hex-codes in uppercase\n * @return the length of the result string\n */\nsize_t rhash_urlencode(char* dst, const char* src, size_t size, int upper_case)\n{\n\tconst char* start;\n\tsize_t i;\n\tif (!dst) {\n\t\tsize_t length = size;\n\t\tfor (i = 0; i < size; i++)\n\t\t\tif (!IS_URL_GOOD_CHAR(src[i]))\n\t\t\t\tlength += 2;\n\t\treturn length;\n\t} else {\n\t\tconst char hex_add = (upper_case ? 'A' - 10 : 'a' - 10);\n\t\tstart = dst;\n\t\t/* percent-encode all but unreserved URL characters */\n\t\tfor (i = 0; i < size; i++) {\n\t\t\tif (IS_URL_GOOD_CHAR(src[i])) {\n\t\t\t\t*dst++ = src[i];\n\t\t\t} else {\n\t\t\t\tunsigned char hi = ((unsigned char)(src[i]) >> 4) & 0x0f;\n\t\t\t\tunsigned char lo = (unsigned char)(src[i]) & 0x0f;\n\t\t\t\t*dst++ = '%';\n\t\t\t\t*dst++ = (hi > 9 ? hi + hex_add : hi + '0');\n\t\t\t\t*dst++ = (lo > 9 ? lo + hex_add : lo + '0');\n\t\t\t}\n\t\t}\n\t\t*dst = 0;\n\t}\n\treturn dst - start;\n}\n\n/**\n * Print 64-bit number with trailing '\\0' to a string buffer.\n * if dst is NULL, then just return the length of the number.\n *\n * @param dst output buffer\n * @param number the number to print\n * @return length of the printed number (without trailing '\\0')\n */\nint rhash_sprintI64(char* dst, uint64_t number)\n{\n\t/* The biggest number has 20 digits: 2^64 = 18 446 744 073 709 551 616 */\n\tchar buf[24];\n\tchar* p;\n\tsize_t length;\n\n\tif (dst == NULL) {\n\t\t/* just calculate the length of the number */\n\t\tif (number == 0) return 1;\n\t\tfor (length = 0; number != 0; number /= 10) length++;\n\t\treturn (int)length;\n\t}\n\n\tp = buf + 23;\n\t*p = '\\0'; /* last symbol should be '\\0' */\n\tif (number == 0) {\n\t\t*(--p) = '0';\n\t} else {\n\t\tfor (; p >= buf && number != 0; number /= 10) {\n\t\t\t*(--p) = '0' + (char)(number % 10);\n\t\t}\n\t}\n\tlength = buf + 23 - p;\n\tmemcpy(dst, p, length + 1);\n\treturn (int)length;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/hex.h",
    "content": "﻿/* hex.h - conversion for hexadecimal and base32 strings. */\n#ifndef HEX_H\n#define HEX_H\n\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nvoid rhash_byte_to_hex(char* dest, const unsigned char* src, size_t length, int upper_case);\nvoid rhash_byte_to_base32(char* dest, const unsigned char* src, size_t length, int upper_case);\nvoid rhash_byte_to_base64(char* dest, const unsigned char* src, size_t length);\nchar* rhash_print_hex_byte(char* dest, const unsigned char byte, int upper_case);\nsize_t rhash_urlencode(char* dst, const char* str, size_t size, int upper_case);\nsize_t rhash_base64_url_encoded_helper(char* dst, const unsigned char* src, size_t length, int url_encode, int upper_case);\nint rhash_sprintI64(char* dst, uint64_t number);\n\n#define BASE32_LENGTH(bytes) (((bytes) * 8 + 4) / 5)\n#define BASE64_LENGTH(bytes) ((((bytes) + 2) / 3) * 4)\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* HEX_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/rhash_sha256.c",
    "content": "﻿/* sha256.c - an implementation of SHA-256/224 hash functions\n * based on FIPS 180-3 (Federal Information Processing Standart).\n *\n * Copyright (c) 2010, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <string.h>\n#include \"byte_order.h\"\n#include \"sha256.h\"\n\n/* SHA-224 and SHA-256 constants for 64 rounds. These words represent\n * the first 32 bits of the fractional parts of the cube\n * roots of the first 64 prime numbers. */\nstatic const unsigned rhash_k256[64] = {\n\t0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,\n\t0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n\t0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\n\t0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n\t0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,\n\t0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n\t0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,\n\t0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n\t0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\n\t0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n\t0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n};\n\n/* The SHA256/224 functions defined by FIPS 180-3, 4.1.2 */\n/* Optimized version of Ch(x,y,z)=((x & y) | (~x & z)) */\n#define Ch(x,y,z)  ((z) ^ ((x) & ((y) ^ (z))))\n/* Optimized version of Maj(x,y,z)=((x & y) ^ (x & z) ^ (y & z)) */\n#define Maj(x,y,z) (((x) & (y)) ^ ((z) & ((x) ^ (y))))\n\n#define Sigma0(x) (ROTR32((x), 2) ^ ROTR32((x), 13) ^ ROTR32((x), 22))\n#define Sigma1(x) (ROTR32((x), 6) ^ ROTR32((x), 11) ^ ROTR32((x), 25))\n#define sigma0(x) (ROTR32((x), 7) ^ ROTR32((x), 18) ^ ((x) >>  3))\n#define sigma1(x) (ROTR32((x),17) ^ ROTR32((x), 19) ^ ((x) >> 10))\n\n/* Recalculate element n-th of circular buffer W using formula\n *   W[n] = sigma1(W[n - 2]) + W[n - 7] + sigma0(W[n - 15]) + W[n - 16]; */\n#define RECALCULATE_W(W,n) (W[n] += \\\n\t(sigma1(W[(n - 2) & 15]) + W[(n - 7) & 15] + sigma0(W[(n - 15) & 15])))\n\n#define ROUND(a,b,c,d,e,f,g,h,k,data) { \\\n\tunsigned T1 = h + Sigma1(e) + Ch(e,f,g) + k + (data); \\\n\td += T1, h = T1 + Sigma0(a) + Maj(a,b,c); }\n#define ROUND_1_16(a,b,c,d,e,f,g,h,n) \\\n\tROUND(a,b,c,d,e,f,g,h, rhash_k256[n], W[n] = be2me_32(block[n]))\n#define ROUND_17_64(a,b,c,d,e,f,g,h,n) \\\n\tROUND(a,b,c,d,e,f,g,h, k[n], RECALCULATE_W(W, n))\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_sha256_init(sha256_ctx* ctx)\n{\n\t/* Initial values. These words were obtained by taking the first 32\n\t * bits of the fractional parts of the square roots of the first\n\t * eight prime numbers. */\n\tstatic const unsigned SHA256_H0[8] = {\n\t\t0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,\n\t\t0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19\n\t};\n\tmemset(ctx->message, 0, sizeof(ctx->message));\n\tctx->length = 0;\n\tctx->digest_length = sha256_hash_size;\n\n\t/* initialize algorithm state */\n\tmemcpy(ctx->hash, SHA256_H0, sizeof(ctx->hash));\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_sha224_init(struct sha256_ctx* ctx)\n{\n\t/* Initial values from FIPS 180-3. These words were obtained by taking\n\t * bits from 33th to 64th of the fractional parts of the square\n\t * roots of ninth through sixteenth prime numbers. */\n\tstatic const unsigned SHA224_H0[8] = {\n\t\t0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,\n\t\t0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4\n\t};\n\tmemset(ctx->message, 0, sizeof(ctx->message));\n\tctx->length = 0;\n\tctx->digest_length = sha224_hash_size;\n\n\tmemcpy(ctx->hash, SHA224_H0, sizeof(ctx->hash));\n}\n\n/**\n * The core transformation. Process a 512-bit block.\n *\n * @param hash algorithm state\n * @param block the message block to process\n */\nstatic void rhash_sha256_process_block(unsigned hash[8], unsigned block[16])\n{\n\tunsigned A, B, C, D, E, F, G, H;\n\tunsigned W[16];\n\tconst unsigned* k;\n\tint i;\n\n\tA = hash[0], B = hash[1], C = hash[2], D = hash[3];\n\tE = hash[4], F = hash[5], G = hash[6], H = hash[7];\n\n\t/* Compute SHA using alternate Method: FIPS 180-3 6.1.3 */\n\tROUND_1_16(A, B, C, D, E, F, G, H, 0);\n\tROUND_1_16(H, A, B, C, D, E, F, G, 1);\n\tROUND_1_16(G, H, A, B, C, D, E, F, 2);\n\tROUND_1_16(F, G, H, A, B, C, D, E, 3);\n\tROUND_1_16(E, F, G, H, A, B, C, D, 4);\n\tROUND_1_16(D, E, F, G, H, A, B, C, 5);\n\tROUND_1_16(C, D, E, F, G, H, A, B, 6);\n\tROUND_1_16(B, C, D, E, F, G, H, A, 7);\n\tROUND_1_16(A, B, C, D, E, F, G, H, 8);\n\tROUND_1_16(H, A, B, C, D, E, F, G, 9);\n\tROUND_1_16(G, H, A, B, C, D, E, F, 10);\n\tROUND_1_16(F, G, H, A, B, C, D, E, 11);\n\tROUND_1_16(E, F, G, H, A, B, C, D, 12);\n\tROUND_1_16(D, E, F, G, H, A, B, C, 13);\n\tROUND_1_16(C, D, E, F, G, H, A, B, 14);\n\tROUND_1_16(B, C, D, E, F, G, H, A, 15);\n\n\tfor (i = 16, k = &rhash_k256[16]; i < 64; i += 16, k += 16) {\n\t\tROUND_17_64(A, B, C, D, E, F, G, H,  0);\n\t\tROUND_17_64(H, A, B, C, D, E, F, G,  1);\n\t\tROUND_17_64(G, H, A, B, C, D, E, F,  2);\n\t\tROUND_17_64(F, G, H, A, B, C, D, E,  3);\n\t\tROUND_17_64(E, F, G, H, A, B, C, D,  4);\n\t\tROUND_17_64(D, E, F, G, H, A, B, C,  5);\n\t\tROUND_17_64(C, D, E, F, G, H, A, B,  6);\n\t\tROUND_17_64(B, C, D, E, F, G, H, A,  7);\n\t\tROUND_17_64(A, B, C, D, E, F, G, H,  8);\n\t\tROUND_17_64(H, A, B, C, D, E, F, G,  9);\n\t\tROUND_17_64(G, H, A, B, C, D, E, F, 10);\n\t\tROUND_17_64(F, G, H, A, B, C, D, E, 11);\n\t\tROUND_17_64(E, F, G, H, A, B, C, D, 12);\n\t\tROUND_17_64(D, E, F, G, H, A, B, C, 13);\n\t\tROUND_17_64(C, D, E, F, G, H, A, B, 14);\n\t\tROUND_17_64(B, C, D, E, F, G, H, A, 15);\n\t}\n\n\thash[0] += A, hash[1] += B, hash[2] += C, hash[3] += D;\n\thash[4] += E, hash[5] += F, hash[6] += G, hash[7] += H;\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_sha256_update(sha256_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tsize_t index = (size_t)ctx->length & 63;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tsize_t left = sha256_block_size - index;\n\t\tmemcpy((char*)ctx->message + index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_sha256_process_block(ctx->hash, (unsigned*)ctx->message);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= sha256_block_size) {\n\t\tunsigned* aligned_message_block;\n\t\tif (IS_ALIGNED_32(msg)) {\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\twithout copying it */\n\t\t\taligned_message_block = (unsigned*)msg;\n\t\t} else {\n\t\t\tmemcpy(ctx->message, msg, sha256_block_size);\n\t\t\taligned_message_block = (unsigned*)ctx->message;\n\t\t}\n\n\t\trhash_sha256_process_block(ctx->hash, aligned_message_block);\n\t\tmsg  += sha256_block_size;\n\t\tsize -= sha256_block_size;\n\t}\n\tif (size) {\n\t\tmemcpy(ctx->message, msg, size); /* save leftovers */\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_sha256_final(sha256_ctx* ctx, unsigned char* result)\n{\n\tsize_t index = ((unsigned)ctx->length & 63) >> 2;\n\tunsigned shift = ((unsigned)ctx->length & 3) * 8;\n\n\t/* pad message and run for last block */\n\n\t/* append the byte 0x80 to the message */\n\tctx->message[index]   &= le2me_32(~(0xFFFFFFFFu << shift));\n\tctx->message[index++] ^= le2me_32(0x80u << shift);\n\n\t/* if no room left in the message to store 64-bit message length */\n\tif (index > 14) {\n\t\t/* then fill the rest with zeros and process it */\n\t\twhile (index < 16) {\n\t\t\tctx->message[index++] = 0;\n\t\t}\n\t\trhash_sha256_process_block(ctx->hash, ctx->message);\n\t\tindex = 0;\n\t}\n\twhile (index < 14) {\n\t\tctx->message[index++] = 0;\n\t}\n\tctx->message[14] = be2me_32( (unsigned)(ctx->length >> 29) );\n\tctx->message[15] = be2me_32( (unsigned)(ctx->length << 3) );\n\trhash_sha256_process_block(ctx->hash, ctx->message);\n\n\tif (result) be32_copy(result, 0, ctx->hash, ctx->digest_length);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/rhash_util.c",
    "content": "﻿/* util.c - memory functions.\n *\n * Copyright (c) 2020, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n#include \"util.h\"\n\n#if defined(HAS_POSIX_ALIGNED_ALLOC)\n\n#include <errno.h>\n\nvoid* rhash_px_aalloc(size_t alignment, size_t size)\n{\n\tvoid* ptr;\n\tif ((errno = posix_memalign(&ptr, alignment, size)) != 0)\n\t\treturn NULL;\n\treturn ptr;\n}\n\n#elif defined(HAS_GENERIC_ALIGNED_ALLOC)\n\n#include <assert.h>\n#include <stdlib.h>\n\nvoid* rhash_aligned_alloc(size_t alignment, size_t size)\n{\n\tunsigned char* block = (unsigned char*)malloc(size + alignment);\n\tassert((alignment & (alignment - 1)) == 0);\n\tassert(alignment >= sizeof(void*));\n\tif (block) {\n\t\tconst size_t alignment_mask = (alignment - 1);\n\t\tunsigned char* basement = block + sizeof(void*);\n\t\tsize_t offset = ((unsigned char*)0 - basement) & alignment_mask;\n\t\tvoid** result = (void**)(basement + offset);\n\t\tassert((((unsigned char*)result - (unsigned char*)0) % alignment) == 0);\n\t\tresult[-1] = block; /* store original pointer */\n\t\treturn result;\n\t}\n\treturn NULL;\n}\n\nvoid rhash_aligned_free(void* ptr)\n{\n\tvoid** pfree = (void**)ptr;\n\tif (ptr)\n\t\tfree(pfree[-1]);\n}\n\n#else\ntypedef int dummy_declaration_required_by_strict_iso_c;\n#endif /* HAS_POSIX_ALIGNED_ALLOC / HAS_GENERIC_ALIGNED_ALLOC */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/ripemd-160.c",
    "content": "﻿/* ripemd-160.c - an implementation of RIPEMD-160 Hash function\n * based on the original aritcle:\n * H. Dobbertin, A. Bosselaers, B. Preneel, RIPEMD-160: A strengthened version\n * of RIPEMD, Lecture Notes in Computer, 1996, V.1039, pp.71-82\n *\n * Copyright (c) 2009, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <string.h>\n#include \"byte_order.h\"\n#include \"ripemd-160.h\"\n\n/**\n * Initialize algorithm context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_ripemd160_init(ripemd160_ctx* ctx)\n{\n\tmemset(ctx->message, 0, sizeof(ctx->message));\n\tctx->length = 0;\n\n\t/* initialize state */\n\tctx->hash[0] = 0x67452301;\n\tctx->hash[1] = 0xefcdab89;\n\tctx->hash[2] = 0x98badcfe;\n\tctx->hash[3] = 0x10325476;\n\tctx->hash[4] = 0xc3d2e1f0;\n}\n\n/* five boolean functions */\n#define F1(x, y, z) ((x) ^ (y) ^ (z))\n#define F2(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))\n#define F3(x, y, z) (((x) | ~(y)) ^ (z))\n#define F4(x, y, z) ((((x) ^ (y)) & (z)) ^ (y))\n#define F5(x, y, z) ((x) ^ ((y) | ~(z)))\n\n#define RMD_FUNC(FUNC, A, B, C, D, E, X, S, K) \\\n\t(A) += FUNC((B), (C), (D)) + (X) + K; \\\n\t(A) = ROTL32((A), (S)) + (E); \\\n\t(C) = ROTL32((C), 10);\n\n/* steps for the left and right half of algorithm */\n#define L1(A, B, C, D, E, X, S) RMD_FUNC(F1, A, B, C, D, E, X, S, 0)\n#define L2(A, B, C, D, E, X, S) RMD_FUNC(F2, A, B, C, D, E, X, S, 0x5a827999UL)\n#define L3(A, B, C, D, E, X, S) RMD_FUNC(F3, A, B, C, D, E, X, S, 0x6ed9eba1UL)\n#define L4(A, B, C, D, E, X, S) RMD_FUNC(F4, A, B, C, D, E, X, S, 0x8f1bbcdcUL)\n#define L5(A, B, C, D, E, X, S) RMD_FUNC(F5, A, B, C, D, E, X, S, 0xa953fd4eUL)\n#define R1(A, B, C, D, E, X, S) RMD_FUNC(F5, A, B, C, D, E, X, S, 0x50a28be6UL)\n#define R2(A, B, C, D, E, X, S) RMD_FUNC(F4, A, B, C, D, E, X, S, 0x5c4dd124UL)\n#define R3(A, B, C, D, E, X, S) RMD_FUNC(F3, A, B, C, D, E, X, S, 0x6d703ef3UL)\n#define R4(A, B, C, D, E, X, S) RMD_FUNC(F2, A, B, C, D, E, X, S, 0x7a6d76e9UL)\n#define R5(A, B, C, D, E, X, S) RMD_FUNC(F1, A, B, C, D, E, X, S, 0)\n\n/**\n * The core transformation. Process a 512-bit block.\n *\n * @param hash algorithm intermediate hash\n * @param X the message block to process\n */\nstatic void rhash_ripemd160_process_block(unsigned* hash, const unsigned* X)\n{\n\tregister unsigned A = hash[0],  B = hash[1],  C = hash[2], D = hash[3],  E = hash[4];\n\tregister unsigned a1 = hash[0], b1 = hash[1], c1 = hash[2], d1 = hash[3], e1 = hash[4];\n\n\t/* rounds of the left and right half interleaved */\n\tL1(a1, b1, c1, d1, e1, X[ 0], 11);\n\tR1(A, B, C, D, E, X[ 5],  8);\n\tL1(e1, a1, b1, c1, d1, X[ 1], 14);\n\tR1(E, A, B, C, D, X[14],  9);\n\tL1(d1, e1, a1, b1, c1, X[ 2], 15);\n\tR1(D, E, A, B, C, X[ 7],  9);\n\tL1(c1, d1, e1, a1, b1, X[ 3], 12);\n\tR1(C, D, E, A, B, X[ 0], 11);\n\tL1(b1, c1, d1, e1, a1, X[ 4],  5);\n\tR1(B, C, D, E, A, X[ 9], 13);\n\tL1(a1, b1, c1, d1, e1, X[ 5],  8);\n\tR1(A, B, C, D, E, X[ 2], 15);\n\tL1(e1, a1, b1, c1, d1, X[ 6],  7);\n\tR1(E, A, B, C, D, X[11], 15);\n\tL1(d1, e1, a1, b1, c1, X[ 7],  9);\n\tR1(D, E, A, B, C, X[ 4],  5);\n\tL1(c1, d1, e1, a1, b1, X[ 8], 11);\n\tR1(C, D, E, A, B, X[13],  7);\n\tL1(b1, c1, d1, e1, a1, X[ 9], 13);\n\tR1(B, C, D, E, A, X[ 6],  7);\n\tL1(a1, b1, c1, d1, e1, X[10], 14);\n\tR1(A, B, C, D, E, X[15],  8);\n\tL1(e1, a1, b1, c1, d1, X[11], 15);\n\tR1(E, A, B, C, D, X[ 8], 11);\n\tL1(d1, e1, a1, b1, c1, X[12],  6);\n\tR1(D, E, A, B, C, X[ 1], 14);\n\tL1(c1, d1, e1, a1, b1, X[13],  7);\n\tR1(C, D, E, A, B, X[10], 14);\n\tL1(b1, c1, d1, e1, a1, X[14],  9);\n\tR1(B, C, D, E, A, X[ 3], 12);\n\tL1(a1, b1, c1, d1, e1, X[15],  8);\n\tR1(A, B, C, D, E, X[12],  6);\n\n\tL2(e1, a1, b1, c1, d1, X[ 7],  7);\n\tR2(E, A, B, C, D, X[ 6],  9);\n\tL2(d1, e1, a1, b1, c1, X[ 4],  6);\n\tR2(D, E, A, B, C, X[11], 13);\n\tL2(c1, d1, e1, a1, b1, X[13],  8);\n\tR2(C, D, E, A, B, X[ 3], 15);\n\tL2(b1, c1, d1, e1, a1, X[ 1], 13);\n\tR2(B, C, D, E, A, X[ 7],  7);\n\tL2(a1, b1, c1, d1, e1, X[10], 11);\n\tR2(A, B, C, D, E, X[ 0], 12);\n\tL2(e1, a1, b1, c1, d1, X[ 6],  9);\n\tR2(E, A, B, C, D, X[13],  8);\n\tL2(d1, e1, a1, b1, c1, X[15],  7);\n\tR2(D, E, A, B, C, X[ 5],  9);\n\tL2(c1, d1, e1, a1, b1, X[ 3], 15);\n\tR2(C, D, E, A, B, X[10], 11);\n\tL2(b1, c1, d1, e1, a1, X[12],  7);\n\tR2(B, C, D, E, A, X[14],  7);\n\tL2(a1, b1, c1, d1, e1, X[ 0], 12);\n\tR2(A, B, C, D, E, X[15],  7);\n\tL2(e1, a1, b1, c1, d1, X[ 9], 15);\n\tR2(E, A, B, C, D, X[ 8], 12);\n\tL2(d1, e1, a1, b1, c1, X[ 5],  9);\n\tR2(D, E, A, B, C, X[12],  7);\n\tL2(c1, d1, e1, a1, b1, X[ 2], 11);\n\tR2(C, D, E, A, B, X[ 4],  6);\n\tL2(b1, c1, d1, e1, a1, X[14],  7);\n\tR2(B, C, D, E, A, X[ 9], 15);\n\tL2(a1, b1, c1, d1, e1, X[11], 13);\n\tR2(A, B, C, D, E, X[ 1], 13);\n\tL2(e1, a1, b1, c1, d1, X[ 8], 12);\n\tR2(E, A, B, C, D, X[ 2], 11);\n\n\tL3(d1, e1, a1, b1, c1, X[ 3], 11);\n\tR3(D, E, A, B, C, X[15],  9);\n\tL3(c1, d1, e1, a1, b1, X[10], 13);\n\tR3(C, D, E, A, B, X[ 5],  7);\n\tL3(b1, c1, d1, e1, a1, X[14],  6);\n\tR3(B, C, D, E, A, X[ 1], 15);\n\tL3(a1, b1, c1, d1, e1, X[ 4],  7);\n\tR3(A, B, C, D, E, X[ 3], 11);\n\tL3(e1, a1, b1, c1, d1, X[ 9], 14);\n\tR3(E, A, B, C, D, X[ 7],  8);\n\tL3(d1, e1, a1, b1, c1, X[15],  9);\n\tR3(D, E, A, B, C, X[14],  6);\n\tL3(c1, d1, e1, a1, b1, X[ 8], 13);\n\tR3(C, D, E, A, B, X[ 6],  6);\n\tL3(b1, c1, d1, e1, a1, X[ 1], 15);\n\tR3(B, C, D, E, A, X[ 9], 14);\n\tL3(a1, b1, c1, d1, e1, X[ 2], 14);\n\tR3(A, B, C, D, E, X[11], 12);\n\tL3(e1, a1, b1, c1, d1, X[ 7],  8);\n\tR3(E, A, B, C, D, X[ 8], 13);\n\tL3(d1, e1, a1, b1, c1, X[ 0], 13);\n\tR3(D, E, A, B, C, X[12],  5);\n\tL3(c1, d1, e1, a1, b1, X[ 6],  6);\n\tR3(C, D, E, A, B, X[ 2], 14);\n\tL3(b1, c1, d1, e1, a1, X[13],  5);\n\tR3(B, C, D, E, A, X[10], 13);\n\tL3(a1, b1, c1, d1, e1, X[11], 12);\n\tR3(A, B, C, D, E, X[ 0], 13);\n\tL3(e1, a1, b1, c1, d1, X[ 5],  7);\n\tR3(E, A, B, C, D, X[ 4],  7);\n\tL3(d1, e1, a1, b1, c1, X[12],  5);\n\tR3(D, E, A, B, C, X[13],  5);\n\n\tL4(c1, d1, e1, a1, b1, X[ 1], 11);\n\tR4(C, D, E, A, B, X[ 8], 15);\n\tL4(b1, c1, d1, e1, a1, X[ 9], 12);\n\tR4(B, C, D, E, A, X[ 6],  5);\n\tL4(a1, b1, c1, d1, e1, X[11], 14);\n\tR4(A, B, C, D, E, X[ 4],  8);\n\tL4(e1, a1, b1, c1, d1, X[10], 15);\n\tR4(E, A, B, C, D, X[ 1], 11);\n\tL4(d1, e1, a1, b1, c1, X[ 0], 14);\n\tR4(D, E, A, B, C, X[ 3], 14);\n\tL4(c1, d1, e1, a1, b1, X[ 8], 15);\n\tR4(C, D, E, A, B, X[11], 14);\n\tL4(b1, c1, d1, e1, a1, X[12],  9);\n\tR4(B, C, D, E, A, X[15],  6);\n\tL4(a1, b1, c1, d1, e1, X[ 4],  8);\n\tR4(A, B, C, D, E, X[ 0], 14);\n\tL4(e1, a1, b1, c1, d1, X[13],  9);\n\tR4(E, A, B, C, D, X[ 5],  6);\n\tL4(d1, e1, a1, b1, c1, X[ 3], 14);\n\tR4(D, E, A, B, C, X[12],  9);\n\tL4(c1, d1, e1, a1, b1, X[ 7],  5);\n\tR4(C, D, E, A, B, X[ 2], 12);\n\tL4(b1, c1, d1, e1, a1, X[15],  6);\n\tR4(B, C, D, E, A, X[13],  9);\n\tL4(a1, b1, c1, d1, e1, X[14],  8);\n\tR4(A, B, C, D, E, X[ 9], 12);\n\tL4(e1, a1, b1, c1, d1, X[ 5],  6);\n\tR4(E, A, B, C, D, X[ 7],  5);\n\tL4(d1, e1, a1, b1, c1, X[ 6],  5);\n\tR4(D, E, A, B, C, X[10], 15);\n\tL4(c1, d1, e1, a1, b1, X[ 2], 12);\n\tR4(C, D, E, A, B, X[14],  8);\n\n\tL5(b1, c1, d1, e1, a1, X[ 4],  9);\n\tR5(B, C, D, E, A, X[12] ,  8);\n\tL5(a1, b1, c1, d1, e1, X[ 0], 15);\n\tR5(A, B, C, D, E, X[15] ,  5);\n\tL5(e1, a1, b1, c1, d1, X[ 5],  5);\n\tR5(E, A, B, C, D, X[10] , 12);\n\tL5(d1, e1, a1, b1, c1, X[ 9], 11);\n\tR5(D, E, A, B, C, X[ 4] ,  9);\n\tL5(c1, d1, e1, a1, b1, X[ 7],  6);\n\tR5(C, D, E, A, B, X[ 1] , 12);\n\tL5(b1, c1, d1, e1, a1, X[12],  8);\n\tR5(B, C, D, E, A, X[ 5] ,  5);\n\tL5(a1, b1, c1, d1, e1, X[ 2], 13);\n\tR5(A, B, C, D, E, X[ 8] , 14);\n\tL5(e1, a1, b1, c1, d1, X[10], 12);\n\tR5(E, A, B, C, D, X[ 7] ,  6);\n\tL5(d1, e1, a1, b1, c1, X[14],  5);\n\tR5(D, E, A, B, C, X[ 6] ,  8);\n\tL5(c1, d1, e1, a1, b1, X[ 1], 12);\n\tR5(C, D, E, A, B, X[ 2] , 13);\n\tL5(b1, c1, d1, e1, a1, X[ 3], 13);\n\tR5(B, C, D, E, A, X[13] ,  6);\n\tL5(a1, b1, c1, d1, e1, X[ 8], 14);\n\tR5(A, B, C, D, E, X[14] ,  5);\n\tL5(e1, a1, b1, c1, d1, X[11], 11);\n\tR5(E, A, B, C, D, X[ 0] , 15);\n\tL5(d1, e1, a1, b1, c1, X[ 6],  8);\n\tR5(D, E, A, B, C, X[ 3] , 13);\n\tL5(c1, d1, e1, a1, b1, X[15],  5);\n\tR5(C, D, E, A, B, X[ 9] , 11);\n\tL5(b1, c1, d1, e1, a1, X[13],  6);\n\tR5(B, C, D, E, A, X[11] , 11);\n\n\t/* update intermediate hash */\n\tD += c1 + hash[1];\n\thash[1] = hash[2] + d1 + E;\n\thash[2] = hash[3] + e1 + A;\n\thash[3] = hash[4] + a1 + B;\n\thash[4] = hash[0] + b1 + C;\n\thash[0] = D;\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_ripemd160_update(ripemd160_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tunsigned index = (unsigned)ctx->length & 63;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tunsigned left = ripemd160_block_size - index;\n\t\tle32_copy(ctx->message, index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_ripemd160_process_block(ctx->hash, (unsigned*)ctx->message);\n\t\tmsg += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= ripemd160_block_size) {\n\t\tunsigned* aligned_message_block;\n\t\tif (IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg)) {\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\ton little-endian CPU without copying it */\n\t\t\taligned_message_block = (unsigned*)msg;\n\t\t} else {\n\t\t\tle32_copy(ctx->message, 0, msg, ripemd160_block_size);\n\t\t\taligned_message_block = ctx->message;\n\t\t}\n\n\t\trhash_ripemd160_process_block(ctx->hash, aligned_message_block);\n\t\tmsg += ripemd160_block_size;\n\t\tsize -= ripemd160_block_size;\n\t}\n\tif (size) {\n\t\t/* save leftovers */\n\t\tle32_copy(ctx->message, 0, msg, size);\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_ripemd160_final(ripemd160_ctx* ctx, unsigned char result[20])\n{\n\tunsigned index = ((unsigned)ctx->length & 63) >> 2;\n\tunsigned shift = ((unsigned)ctx->length & 3) * 8;\n\n\t/* pad message and run for last block */\n\n\t/* append the byte 0x80 to the message */\n\tctx->message[index]   &= ~(0xFFFFFFFFu << shift);\n\tctx->message[index++] ^= 0x80u << shift;\n\n\t/* if no room left in the message to store 64-bit message length */\n\tif (index > 14) {\n\t\t/* then fill the rest with zeros and process it */\n\t\twhile (index < 16) {\n\t\t\tctx->message[index++] = 0;\n\t\t}\n\t\trhash_ripemd160_process_block(ctx->hash, ctx->message);\n\t\tindex = 0;\n\t}\n\twhile (index < 14) {\n\t\tctx->message[index++] = 0;\n\t}\n\tctx->message[14] = (unsigned)(ctx->length << 3);\n\tctx->message[15] = (unsigned)(ctx->length >> 29);\n\trhash_ripemd160_process_block(ctx->hash, ctx->message);\n\n\tle32_copy(result, 0, &ctx->hash, 20);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/ripemd-160.h",
    "content": "﻿/* ripemd-160.h */\n#ifndef  RMD160_H\n#define  RMD160_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define ripemd160_block_size 64\n#define ripemd160_hash_size  20\n\n/* algorithm context */\ntypedef struct ripemd160_ctx\n{\n\tunsigned message[ripemd160_block_size / 4]; /* 512-bit buffer for leftovers */\n\tuint64_t length;  /* number of processed bytes */\n\tunsigned hash[5]; /* 160-bit algorithm internal hashing state */\n} ripemd160_ctx;\n\n/* hash functions */\n\nvoid rhash_ripemd160_init(ripemd160_ctx* ctx);\nvoid rhash_ripemd160_update(ripemd160_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_ripemd160_final(ripemd160_ctx* ctx, unsigned char result[20]);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* RMD160_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/sha1.h",
    "content": "﻿/* sha1.h */\n#ifndef SHA1_H\n#define SHA1_H\n#include \"ustd.h\"\n#include <K7Base.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define sha1_block_size 64\n#define sha1_hash_size  20\n\n/* algorithm context */\ntypedef struct sha1_ctx\n{\n    K7_BASE_HASH_HANDLE context; /* internal context */\n\tuint64_t length;   /* number of processed bytes */\n\tunsigned hash[5];  /* 160-bit algorithm internal hashing state */\n} sha1_ctx;\n\n/* hash functions */\n\nvoid rhash_sha1_init(sha1_ctx* ctx);\nvoid rhash_sha1_update(sha1_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_sha1_final(sha1_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* SHA1_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/sha256.h",
    "content": "﻿/* sha.h sha256 and sha224 hash functions */\n#ifndef SHA256_H\n#define SHA256_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define sha256_block_size 64\n#define sha256_hash_size  32\n#define sha224_hash_size  28\n\n/* algorithm context */\ntypedef struct sha256_ctx\n{\n\tunsigned message[16];   /* 512-bit buffer for leftovers */\n\tuint64_t length;        /* number of processed bytes */\n\tunsigned hash[8];       /* 256-bit algorithm internal hashing state */\n\tunsigned digest_length; /* length of the algorithm digest in bytes */\n} sha256_ctx;\n\nvoid rhash_sha224_init(sha256_ctx* ctx);\nvoid rhash_sha256_init(sha256_ctx* ctx);\nvoid rhash_sha256_update(sha256_ctx* ctx, const unsigned char* data, size_t length);\nvoid rhash_sha256_final(sha256_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* SHA256_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/sha3.c",
    "content": "﻿/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).\n * based on the\n * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011\n * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche\n *\n * Copyright (c) 2013, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <assert.h>\n#include <string.h>\n#include \"byte_order.h\"\n#include \"sha3.h\"\n\n/* constants */\n#define NumberOfRounds 24\n\n/* SHA3 (Keccak) constants for 24 rounds */\nstatic uint64_t keccak_round_constants[NumberOfRounds] = {\n\tI64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),\n\tI64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),\n\tI64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),\n\tI64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),\n\tI64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),\n\tI64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)\n};\n\n/* Initializing a sha3 context for given number of output bits */\nstatic void rhash_keccak_init(sha3_ctx* ctx, unsigned bits)\n{\n\t/* NB: The Keccak capacity parameter = bits * 2 */\n\tunsigned rate = 1600 - bits * 2;\n\n\tmemset(ctx, 0, sizeof(sha3_ctx));\n\tctx->block_size = rate / 8;\n\tassert(rate <= 1600 && (rate % 64) == 0);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_sha3_224_init(sha3_ctx* ctx)\n{\n\trhash_keccak_init(ctx, 224);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_sha3_256_init(sha3_ctx* ctx)\n{\n\trhash_keccak_init(ctx, 256);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_sha3_384_init(sha3_ctx* ctx)\n{\n\trhash_keccak_init(ctx, 384);\n}\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_sha3_512_init(sha3_ctx* ctx)\n{\n\trhash_keccak_init(ctx, 512);\n}\n\n#define XORED_A(i) A[(i)] ^ A[(i) + 5] ^ A[(i) + 10] ^ A[(i) + 15] ^ A[(i) + 20]\n#define THETA_STEP(i) \\\n\tA[(i)]      ^= D[(i)]; \\\n\tA[(i) + 5]  ^= D[(i)]; \\\n\tA[(i) + 10] ^= D[(i)]; \\\n\tA[(i) + 15] ^= D[(i)]; \\\n\tA[(i) + 20] ^= D[(i)] \\\n\n/* Keccak theta() transformation */\nstatic void keccak_theta(uint64_t* A)\n{\n\tuint64_t D[5];\n\tD[0] = ROTL64(XORED_A(1), 1) ^ XORED_A(4);\n\tD[1] = ROTL64(XORED_A(2), 1) ^ XORED_A(0);\n\tD[2] = ROTL64(XORED_A(3), 1) ^ XORED_A(1);\n\tD[3] = ROTL64(XORED_A(4), 1) ^ XORED_A(2);\n\tD[4] = ROTL64(XORED_A(0), 1) ^ XORED_A(3);\n\tTHETA_STEP(0);\n\tTHETA_STEP(1);\n\tTHETA_STEP(2);\n\tTHETA_STEP(3);\n\tTHETA_STEP(4);\n}\n\n/* Keccak pi() transformation */\nstatic void keccak_pi(uint64_t* A)\n{\n\tuint64_t A1;\n\tA1 = A[1];\n\tA[ 1] = A[ 6];\n\tA[ 6] = A[ 9];\n\tA[ 9] = A[22];\n\tA[22] = A[14];\n\tA[14] = A[20];\n\tA[20] = A[ 2];\n\tA[ 2] = A[12];\n\tA[12] = A[13];\n\tA[13] = A[19];\n\tA[19] = A[23];\n\tA[23] = A[15];\n\tA[15] = A[ 4];\n\tA[ 4] = A[24];\n\tA[24] = A[21];\n\tA[21] = A[ 8];\n\tA[ 8] = A[16];\n\tA[16] = A[ 5];\n\tA[ 5] = A[ 3];\n\tA[ 3] = A[18];\n\tA[18] = A[17];\n\tA[17] = A[11];\n\tA[11] = A[ 7];\n\tA[ 7] = A[10];\n\tA[10] = A1;\n\t/* note: A[ 0] is left as is */\n}\n\n#define CHI_STEP(i) \\\n\tA0 = A[0 + (i)]; \\\n\tA1 = A[1 + (i)]; \\\n\tA[0 + (i)] ^= ~A1 & A[2 + (i)]; \\\n\tA[1 + (i)] ^= ~A[2 + (i)] & A[3 + (i)]; \\\n\tA[2 + (i)] ^= ~A[3 + (i)] & A[4 + (i)]; \\\n\tA[3 + (i)] ^= ~A[4 + (i)] & A0; \\\n\tA[4 + (i)] ^= ~A0 & A1 \\\n\n/* Keccak chi() transformation */\nstatic void keccak_chi(uint64_t* A)\n{\n\tuint64_t A0, A1;\n\tCHI_STEP(0);\n\tCHI_STEP(5);\n\tCHI_STEP(10);\n\tCHI_STEP(15);\n\tCHI_STEP(20);\n}\n\nstatic void rhash_sha3_permutation(uint64_t* state)\n{\n\tint round;\n\tfor (round = 0; round < NumberOfRounds; round++)\n\t{\n\t\tkeccak_theta(state);\n\n\t\t/* apply Keccak rho() transformation */\n\t\tstate[ 1] = ROTL64(state[ 1],  1);\n\t\tstate[ 2] = ROTL64(state[ 2], 62);\n\t\tstate[ 3] = ROTL64(state[ 3], 28);\n\t\tstate[ 4] = ROTL64(state[ 4], 27);\n\t\tstate[ 5] = ROTL64(state[ 5], 36);\n\t\tstate[ 6] = ROTL64(state[ 6], 44);\n\t\tstate[ 7] = ROTL64(state[ 7],  6);\n\t\tstate[ 8] = ROTL64(state[ 8], 55);\n\t\tstate[ 9] = ROTL64(state[ 9], 20);\n\t\tstate[10] = ROTL64(state[10],  3);\n\t\tstate[11] = ROTL64(state[11], 10);\n\t\tstate[12] = ROTL64(state[12], 43);\n\t\tstate[13] = ROTL64(state[13], 25);\n\t\tstate[14] = ROTL64(state[14], 39);\n\t\tstate[15] = ROTL64(state[15], 41);\n\t\tstate[16] = ROTL64(state[16], 45);\n\t\tstate[17] = ROTL64(state[17], 15);\n\t\tstate[18] = ROTL64(state[18], 21);\n\t\tstate[19] = ROTL64(state[19],  8);\n\t\tstate[20] = ROTL64(state[20], 18);\n\t\tstate[21] = ROTL64(state[21],  2);\n\t\tstate[22] = ROTL64(state[22], 61);\n\t\tstate[23] = ROTL64(state[23], 56);\n\t\tstate[24] = ROTL64(state[24], 14);\n\n\t\tkeccak_pi(state);\n\t\tkeccak_chi(state);\n\n\t\t/* apply iota(state, round) */\n\t\t*state ^= keccak_round_constants[round];\n\t}\n}\n\n/**\n * The core transformation. Process the specified block of data.\n *\n * @param hash the algorithm state\n * @param block the message block to process\n * @param block_size the size of the processed block in bytes\n */\nstatic void rhash_sha3_process_block(uint64_t hash[25], const uint64_t* block, size_t block_size)\n{\n\t/* expanded loop */\n\thash[ 0] ^= le2me_64(block[ 0]);\n\thash[ 1] ^= le2me_64(block[ 1]);\n\thash[ 2] ^= le2me_64(block[ 2]);\n\thash[ 3] ^= le2me_64(block[ 3]);\n\thash[ 4] ^= le2me_64(block[ 4]);\n\thash[ 5] ^= le2me_64(block[ 5]);\n\thash[ 6] ^= le2me_64(block[ 6]);\n\thash[ 7] ^= le2me_64(block[ 7]);\n\thash[ 8] ^= le2me_64(block[ 8]);\n\t/* if not sha3-512 */\n\tif (block_size > 72) {\n\t\thash[ 9] ^= le2me_64(block[ 9]);\n\t\thash[10] ^= le2me_64(block[10]);\n\t\thash[11] ^= le2me_64(block[11]);\n\t\thash[12] ^= le2me_64(block[12]);\n\t\t/* if not sha3-384 */\n\t\tif (block_size > 104) {\n\t\t\thash[13] ^= le2me_64(block[13]);\n\t\t\thash[14] ^= le2me_64(block[14]);\n\t\t\thash[15] ^= le2me_64(block[15]);\n\t\t\thash[16] ^= le2me_64(block[16]);\n\t\t\t/* if not sha3-256 */\n\t\t\tif (block_size > 136) {\n\t\t\t\thash[17] ^= le2me_64(block[17]);\n#ifdef FULL_SHA3_FAMILY_SUPPORT\n\t\t\t\t/* if not sha3-224 */\n\t\t\t\tif (block_size > 144) {\n\t\t\t\t\thash[18] ^= le2me_64(block[18]);\n\t\t\t\t\thash[19] ^= le2me_64(block[19]);\n\t\t\t\t\thash[20] ^= le2me_64(block[20]);\n\t\t\t\t\thash[21] ^= le2me_64(block[21]);\n\t\t\t\t\thash[22] ^= le2me_64(block[22]);\n\t\t\t\t\thash[23] ^= le2me_64(block[23]);\n\t\t\t\t\thash[24] ^= le2me_64(block[24]);\n\t\t\t\t}\n#endif\n\t\t\t}\n\t\t}\n\t}\n\t/* make a permutation of the hash */\n\trhash_sha3_permutation(hash);\n}\n\n#define SHA3_FINALIZED 0x80000000\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_sha3_update(sha3_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tsize_t index = (size_t)ctx->rest;\n\tsize_t block_size = (size_t)ctx->block_size;\n\n\tif (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */\n\tctx->rest = (unsigned)((ctx->rest + size) % block_size);\n\n\t/* fill partial block */\n\tif (index) {\n\t\tsize_t left = block_size - index;\n\t\tmemcpy((char*)ctx->message + index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_sha3_process_block(ctx->hash, ctx->message, block_size);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= block_size) {\n\t\tuint64_t* aligned_message_block;\n\t\tif (IS_ALIGNED_64(msg)) {\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\twithout copying it */\n\t\t\taligned_message_block = (uint64_t*)msg;\n\t\t} else {\n\t\t\tmemcpy(ctx->message, msg, block_size);\n\t\t\taligned_message_block = ctx->message;\n\t\t}\n\n\t\trhash_sha3_process_block(ctx->hash, aligned_message_block, block_size);\n\t\tmsg  += block_size;\n\t\tsize -= block_size;\n\t}\n\tif (size) {\n\t\tmemcpy(ctx->message, msg, size); /* save leftovers */\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_sha3_final(sha3_ctx* ctx, unsigned char* result)\n{\n\tsize_t digest_length = 100 - ctx->block_size / 2;\n\tconst size_t block_size = ctx->block_size;\n\n\tif (!(ctx->rest & SHA3_FINALIZED))\n\t{\n\t\t/* clear the rest of the data queue */\n\t\tmemset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);\n\t\t((char*)ctx->message)[ctx->rest] |= 0x06;\n\t\t((char*)ctx->message)[block_size - 1] |= 0x80;\n\n\t\t/* process final block */\n\t\trhash_sha3_process_block(ctx->hash, ctx->message, block_size);\n\t\tctx->rest = SHA3_FINALIZED; /* mark context as finalized */\n\t}\n\n\tassert(block_size > digest_length);\n\tif (result) me64_to_le_str(result, ctx->hash, digest_length);\n}\n\n#ifdef USE_KECCAK\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_keccak_final(sha3_ctx* ctx, unsigned char* result)\n{\n\tsize_t digest_length = 100 - ctx->block_size / 2;\n\tconst size_t block_size = ctx->block_size;\n\n\tif (!(ctx->rest & SHA3_FINALIZED))\n\t{\n\t\t/* clear the rest of the data queue */\n\t\tmemset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);\n\t\t((char*)ctx->message)[ctx->rest] |= 0x01;\n\t\t((char*)ctx->message)[block_size - 1] |= 0x80;\n\n\t\t/* process final block */\n\t\trhash_sha3_process_block(ctx->hash, ctx->message, block_size);\n\t\tctx->rest = SHA3_FINALIZED; /* mark context as finalized */\n\t}\n\n\tassert(block_size > digest_length);\n\tif (result) me64_to_le_str(result, ctx->hash, digest_length);\n}\n#endif /* USE_KECCAK */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/sha3.h",
    "content": "﻿/* sha3.h */\n#ifndef RHASH_SHA3_H\n#define RHASH_SHA3_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define sha3_224_hash_size  28\n#define sha3_256_hash_size  32\n#define sha3_384_hash_size  48\n#define sha3_512_hash_size  64\n#define sha3_max_permutation_size 25\n#define sha3_max_rate_in_qwords 24\n\n/**\n * SHA3 Algorithm context.\n */\ntypedef struct sha3_ctx\n{\n\t/* 1600 bits algorithm hashing state */\n\tuint64_t hash[sha3_max_permutation_size];\n\t/* 1536-bit buffer for leftovers */\n\tuint64_t message[sha3_max_rate_in_qwords];\n\t/* count of bytes in the message[] buffer */\n\tunsigned rest;\n\t/* size of a message block processed at once */\n\tunsigned block_size;\n} sha3_ctx;\n\n/* methods for calculating the hash function */\n\nvoid rhash_sha3_224_init(sha3_ctx* ctx);\nvoid rhash_sha3_256_init(sha3_ctx* ctx);\nvoid rhash_sha3_384_init(sha3_ctx* ctx);\nvoid rhash_sha3_512_init(sha3_ctx* ctx);\nvoid rhash_sha3_update(sha3_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_sha3_final(sha3_ctx* ctx, unsigned char* result);\n\n#ifdef USE_KECCAK\n#define rhash_keccak_224_init rhash_sha3_224_init\n#define rhash_keccak_256_init rhash_sha3_256_init\n#define rhash_keccak_384_init rhash_sha3_384_init\n#define rhash_keccak_512_init rhash_sha3_512_init\n#define rhash_keccak_update rhash_sha3_update\nvoid rhash_keccak_final(sha3_ctx* ctx, unsigned char* result);\n#endif\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* RHASH_SHA3_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/snefru.c",
    "content": "﻿/* snefru.c - an implementation of Snefru-128/256 Message-Digest Algorithms\n *\n * Copyright (c) 2009, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n *\n * Specification: Ralph C. Merkle, A Fast Software One-Way Hash Function,\n *   J. Cryptology, Vol. 3, No 1, pp. 43-58, 1990\n *\n * Info from wikipedia:  Snefru is a cryptographic hash function invented\n * by Ralph Merkle in 1989 which supports 128-bit and 256-bit output.  It\n * was named after the Egyptian Pharaoh Sneferu, continuing the tradition\n * of the Khufu and Khafre block ciphers.\n *\n * The original design of Snefru was shown to be insecure by Eli Biham and\n * Adi Shamir who were able to use differential cryptanalysis to find hash\n * collisions. The design was then modified by increasing the number of\n * iterations of the main pass of the algorithm from two to eight. Although\n * differential cryptanalysis can break the revised version with less\n * complexity than brute force search (a certificational weakness), the attack\n * requires 2^88.5 operations and is thus not currently feasible in practice.\n *\n * The algorithm can also be run with a variable number of \"rounds\" of the\n * internal algorithm. However, analysis by several cryptographers has shown\n * that SNEFRU has weaknesses that can be exploited, and that you can find\n * arbitrary messages that hash to a given 128-bit value if the 4-round\n * version is used. Dr. Merkle currently recommends that only 8-round SNEFRU\n * be used, but this algorithm is significantly slower than the MD5 or HAVAL\n * algorithms.\n */\n\n#include <string.h>\n#include <assert.h>\n#include \"byte_order.h\"\n\n#include \"snefru.h\"\n\n#define SNEFRU_NUMBER_OF_ROUNDS 8\n\n/* SNEFRU lookup table (S-Box) */\nstatic const unsigned rhash_snefru_sbox[SNEFRU_NUMBER_OF_ROUNDS * 512] = {\n\t0x64f9001b, 0xfeddcdf6, 0x7c8ff1e2, 0x11d71514, 0x8b8c18d3, 0xdddf881e,\n\t0x6eab5056, 0x88ced8e1, 0x49148959, 0x69c56fd5, 0xb7994f03, 0x0fbcee3e,\n\t0x3c264940, 0x21557e58, 0xe14b3fc2, 0x2e5cf591, 0xdceff8ce, 0x092a1648,\n\t0xbe812936, 0xff7b0c6a, 0xd5251037, 0xafa448f1, 0x7dafc95a, 0x1ea69c3f,\n\t0xa417abe7, 0x5890e423, 0xb0cb70c0, 0xc85025f7, 0x244d97e3, 0x1ff3595f,\n\t0xc4ec6396, 0x59181e17, 0xe635b477, 0x354e7dbf, 0x796f7753, 0x66eb52cc,\n\t0x77c3f995, 0x32e3a927, 0x80ccaed6, 0x4e2be89d, 0x375bbd28, 0xad1a3d05,\n\t0x2b1b42b3, 0x16c44c71, 0x4d54bfa8, 0xe57ddc7a, 0xec6d8144, 0x5a71046b,\n\t0xd8229650, 0x87fc8f24, 0xcbc60e09, 0xb6390366, 0xd9f76092, 0xd393a70b,\n\t0x1d31a08a, 0x9cd971c9, 0x5c1ef445, 0x86fab694, 0xfdb44165, 0x8eaafcbe,\n\t0x4bcac6eb, 0xfb7a94e5, 0x5789d04e, 0xfa13cf35, 0x236b8da9, 0x4133f000,\n\t0x6224261c, 0xf412f23b, 0xe75e56a4, 0x30022116, 0xbaf17f1f, 0xd09872f9,\n\t0xc1a3699c, 0xf1e802aa, 0x0dd145dc, 0x4fdce093, 0x8d8412f0, 0x6cd0f376,\n\t0x3de6b73d, 0x84ba737f, 0xb43a30f2, 0x44569f69, 0x00e4eaca, 0xb58de3b0,\n\t0x959113c8, 0xd62efee9, 0x90861f83, 0xced69874, 0x2f793cee, 0xe8571c30,\n\t0x483665d1, 0xab07b031, 0x914c844f, 0x15bf3be8, 0x2c3f2a9a, 0x9eb95fd4,\n\t0x92e7472d, 0x2297cc5b, 0xee5f2782, 0x5377b562, 0xdb8ebbcf, 0xf961dedd,\n\t0xc59b5c60, 0x1bd3910d, 0x26d206ad, 0xb28514d8, 0x5ecf6b52, 0x7fea78bb,\n\t0x504879ac, 0xed34a884, 0x36e51d3c, 0x1753741d, 0x8c47caed, 0x9d0a40ef,\n\t0x3145e221, 0xda27eb70, 0xdf730ba3, 0x183c8789, 0x739ac0a6, 0x9a58dfc6,\n\t0x54b134c1, 0xac3e242e, 0xcc493902, 0x7b2dda99, 0x8f15bc01, 0x29fd38c7,\n\t0x27d5318f, 0x604aaff5, 0xf29c6818, 0xc38aa2ec, 0x1019d4c3, 0xa8fb936e,\n\t0x20ed7b39, 0x0b686119, 0x89a0906f, 0x1cc7829e, 0x9952ef4b, 0x850e9e8c,\n\t0xcd063a90, 0x67002f8e, 0xcfac8cb7, 0xeaa24b11, 0x988b4e6c, 0x46f066df,\n\t0xca7eec08, 0xc7bba664, 0x831d17bd, 0x63f575e6, 0x9764350e, 0x47870d42,\n\t0x026ca4a2, 0x8167d587, 0x61b6adab, 0xaa6564d2, 0x70da237b, 0x25e1c74a,\n\t0xa1c901a0, 0x0eb0a5da, 0x7670f741, 0x51c05aea, 0x933dfa32, 0x0759ff1a,\n\t0x56010ab8, 0x5fdecb78, 0x3f32edf8, 0xaebedbb9, 0x39f8326d, 0xd20858c5,\n\t0x9b638be4, 0xa572c80a, 0x28e0a19f, 0x432099fc, 0x3a37c3cd, 0xbf95c585,\n\t0xb392c12a, 0x6aa707d7, 0x52f66a61, 0x12d483b1, 0x96435b5e, 0x3e75802b,\n\t0x3ba52b33, 0xa99f51a5, 0xbda1e157, 0x78c2e70c, 0xfcae7ce0, 0xd1602267,\n\t0x2affac4d, 0x4a510947, 0x0ab2b83a, 0x7a04e579, 0x340dfd80, 0xb916e922,\n\t0xe29d5e9b, 0xf5624af4, 0x4ca9d9af, 0x6bbd2cfe, 0xe3b7f620, 0xc2746e07,\n\t0x5b42b9b6, 0xa06919bc, 0xf0f2c40f, 0x72217ab5, 0x14c19df3, 0xf3802dae,\n\t0xe094beb4, 0xa2101aff, 0x0529575d, 0x55cdb27c, 0xa33bddb2, 0x6528b37d,\n\t0x740c05db, 0xe96a62c4, 0x40782846, 0x6d30d706, 0xbbf48e2c, 0xbce2d3de,\n\t0x049e37fa, 0x01b5e634, 0x2d886d8d, 0x7e5a2e7e, 0xd7412013, 0x06e90f97,\n\t0xe45d3eba, 0xb8ad3386, 0x13051b25, 0x0c035354, 0x71c89b75, 0xc638fbd0,\n\t0x197f11a1, 0xef0f08fb, 0xf8448651, 0x38409563, 0x452f4443, 0x5d464d55,\n\t0x03d8764c, 0xb1b8d638, 0xa70bba2f, 0x94b3d210, 0xeb6692a7, 0xd409c2d9,\n\t0x68838526, 0xa6db8a15, 0x751f6c98, 0xde769a88, 0xc9ee4668, 0x1a82a373,\n\t0x0896aa49, 0x42233681, 0xf62c55cb, 0x9f1c5404, 0xf74fb15c, 0xc06e4312,\n\t0x6ffe5d72, 0x8aa8678b, 0x337cd129, 0x8211cefd, 0x074a1d09, 0x52a10e5a,\n\t0x9275a3f8, 0x4b82506c, 0x37df7e1b, 0x4c78b3c5, 0xcefab1da, 0xf472267e,\n\t0xb63045f6, 0xd66a1fc0, 0x400298e3, 0x27e60c94, 0x87d2f1b8, 0xdf9e56cc,\n\t0x45cd1803, 0x1d35e098, 0xcce7c736, 0x03483bf1, 0x1f7307d7, 0xc6e8f948,\n\t0xe613c111, 0x3955c6ff, 0x1170ed7c, 0x8e95da41, 0x99c31bf4, 0xa4da8021,\n\t0x7b5f94fb, 0xdd0da51f, 0x6562aa77, 0x556bcb23, 0xdb1bacc6, 0x798040b9,\n\t0xbfe5378f, 0x731d55e6, 0xdaa5bfee, 0x389bbc60, 0x1b33fba4, 0x9c567204,\n\t0x36c26c68, 0x77ee9d69, 0x8aeb3e88, 0x2d50b5ce, 0x9579e790, 0x42b13cfc,\n\t0x33fbd32b, 0xee0503a7, 0xb5862824, 0x15e41ead, 0xc8412ef7, 0x9d441275,\n\t0x2fcec582, 0x5ff483b7, 0x8f3931df, 0x2e5d2a7b, 0x49467bf9, 0x0653dea9,\n\t0x2684ce35, 0x7e655e5c, 0xf12771d8, 0xbb15cc67, 0xab097ca1, 0x983dcf52,\n\t0x10ddf026, 0x21267f57, 0x2c58f6b4, 0x31043265, 0x0bab8c01, 0xd5492099,\n\t0xacaae619, 0x944ce54a, 0xf2d13d39, 0xadd3fc32, 0xcda08a40, 0xe2b0d451,\n\t0x9efe08ae, 0xb9d50fd2, 0xea5cd7fd, 0xc9a749dd, 0x13ea2253, 0x832debaa,\n\t0x24be640f, 0xe03e926a, 0x29e01cde, 0x8bf59f18, 0x0f9d00b6, 0xe1238b46,\n\t0x1e7d8e34, 0x93619adb, 0x76b32f9f, 0xbd972cec, 0xe31fa976, 0xa68fbb10,\n\t0xfb3ba49d, 0x8587c41d, 0xa5add1d0, 0xf3cf84bf, 0xd4e11150, 0xd9ffa6bc,\n\t0xc3f6018c, 0xaef10572, 0x74a64b2f, 0xe7dc9559, 0x2aae35d5, 0x5b6f587f,\n\t0xa9e353fe, 0xca4fb674, 0x04ba24a8, 0xe5c6875f, 0xdcbc6266, 0x6bc5c03f,\n\t0x661eef02, 0xed740bab, 0x058e34e4, 0xb7e946cf, 0x88698125, 0x72ec48ed,\n\t0xb11073a3, 0xa13485eb, 0xa2a2429c, 0xfa407547, 0x50b76713, 0x5418c37d,\n\t0x96192da5, 0x170bb04b, 0x518a021e, 0xb0ac13d1, 0x0963fa2a, 0x4a6e10e1,\n\t0x58472bdc, 0xf7f8d962, 0x979139ea, 0x8d856538, 0xc0997042, 0x48324d7a,\n\t0x447623cb, 0x8cbbe364, 0x6e0c6b0e, 0xd36d63b0, 0x3f244c84, 0x3542c971,\n\t0x2b228dc1, 0xcb0325bb, 0xf8c0d6e9, 0xde11066b, 0xa8649327, 0xfc31f83e,\n\t0x7dd80406, 0xf916dd61, 0xd89f79d3, 0x615144c2, 0xebb45d31, 0x28002958,\n\t0x56890a37, 0xf05b3808, 0x123ae844, 0x86839e16, 0x914b0d83, 0xc506b43c,\n\t0xcf3cba5e, 0x7c60f5c9, 0x22deb2a0, 0x5d9c2715, 0xc77ba0ef, 0x4f45360b,\n\t0xc1017d8b, 0xe45adc29, 0xa759909b, 0x412cd293, 0xd7d796b1, 0x00c8ff30,\n\t0x23a34a80, 0x4ec15c91, 0x714e78b5, 0x47b9e42e, 0x78f3ea4d, 0x7f078f5b,\n\t0x346c593a, 0xa3a87a1a, 0x9bcbfe12, 0x3d439963, 0xb2ef6d8e, 0xb8d46028,\n\t0x6c2fd5ca, 0x62675256, 0x01f2a2f3, 0xbc96ae0a, 0x709a8920, 0xb4146e87,\n\t0x6308b9e2, 0x64bda7ba, 0xafed6892, 0x6037f2a2, 0xf52969e0, 0x0adb43a6,\n\t0x82811400, 0x90d0bdf0, 0x19c9549e, 0x203f6a73, 0x1accaf4f, 0x89714e6d,\n\t0x164d4705, 0x67665f07, 0xec206170, 0x0c2182b2, 0xa02b9c81, 0x53289722,\n\t0xf6a97686, 0x140e4179, 0x9f778849, 0x9a88e15d, 0x25cadb54, 0xd157f36f,\n\t0x32a421c3, 0xb368e98a, 0x5a92cd0d, 0x757aa8d4, 0xc20ac278, 0x08b551c7,\n\t0x849491e8, 0x4dc75ad6, 0x697c33be, 0xbaf0ca33, 0x46125b4e, 0x59d677b3,\n\t0x30d9c8f2, 0xd0af860c, 0x1c7fd0fa, 0xfe0ff72c, 0x5c8d6f43, 0x57fdec3b,\n\t0x6ab6ad97, 0xd22adf89, 0x18171785, 0x02bfe22d, 0x6db80917, 0x80b216af,\n\t0xe85e4f9a, 0x7a1c306e, 0x6fc49bf5, 0x3af7a11c, 0x81e215e7, 0x68363fcd,\n\t0x3e9357c8, 0xef52fd55, 0x3b8bab4c, 0x3c8cf495, 0xbefceebd, 0xfd25b714,\n\t0xc498d83d, 0x0d2e1a8d, 0xe9f966ac, 0x0e387445, 0x435419e5, 0x5e7ebec4,\n\t0xaa90b8d9, 0xff1a3a96, 0x4a8fe4e3, 0xf27d99cd, 0xd04a40ca, 0xcb5ff194,\n\t0x3668275a, 0xff4816be, 0xa78b394c, 0x4c6be9db, 0x4eec38d2, 0x4296ec80,\n\t0xcdce96f8, 0x888c2f38, 0xe75508f5, 0x7b916414, 0x060aa14a, 0xa214f327,\n\t0xbe608daf, 0x1ebbdec2, 0x61f98ce9, 0xe92156fe, 0x4f22d7a3, 0x3f76a8d9,\n\t0x559a4b33, 0x38ad2959, 0xf3f17e9e, 0x85e1ba91, 0xe5eba6fb, 0x73dcd48c,\n\t0xf5c3ff78, 0x481b6058, 0x8a3297f7, 0x8f1f3bf4, 0x93785ab2, 0x477a4a5b,\n\t0x6334eb5d, 0x6d251b2e, 0x74a9102d, 0x07e38ffa, 0x915c9c62, 0xccc275ea,\n\t0x6be273ec, 0x3ebddd70, 0xd895796c, 0xdc54a91b, 0xc9afdf81, 0x23633f73,\n\t0x275119b4, 0xb19f6b67, 0x50756e22, 0x2bb152e2, 0x76ea46a2, 0xa353e232,\n\t0x2f596ad6, 0x0b1edb0b, 0x02d3d9a4, 0x78b47843, 0x64893e90, 0x40f0caad,\n\t0xf68d3ad7, 0x46fd1707, 0x1c9c67ef, 0xb5e086de, 0x96ee6ca6, 0x9aa34774,\n\t0x1ba4f48a, 0x8d01abfd, 0x183ee1f6, 0x5ff8aa7a, 0x17e4faae, 0x303983b0,\n\t0x6c08668b, 0xd4ac4382, 0xe6c5849f, 0x92fefb53, 0xc1cac4ce, 0x43501388,\n\t0x441118cf, 0xec4fb308, 0x53a08e86, 0x9e0fe0c5, 0xf91c1525, 0xac45be05,\n\t0xd7987cb5, 0x49ba1487, 0x57938940, 0xd5877648, 0xa958727f, 0x58dfe3c3,\n\t0xf436cf77, 0x399e4d11, 0xf0a5bfa9, 0xef61a33b, 0xa64cac60, 0x04a8d0ba,\n\t0x030dd572, 0xb83d320f, 0xcab23045, 0xe366f2f0, 0x815d008d, 0xc897a43a,\n\t0x1d352df3, 0xb9cc571d, 0x8bf38744, 0x72209092, 0xeba124eb, 0xfb99ce5e,\n\t0x3bb94293, 0x28da549c, 0xaab8a228, 0xa4197785, 0x33c70296, 0x25f6259b,\n\t0x5c85da21, 0xdf15bdee, 0x15b7c7e8, 0xe2abef75, 0xfcc19bc1, 0x417ff868,\n\t0x14884434, 0x62825179, 0xc6d5c11c, 0x0e4705dc, 0x22700de0, 0xd3d2af18,\n\t0x9be822a0, 0x35b669f1, 0xc42bb55c, 0x0a801252, 0x115bf0fc, 0x3cd7d856,\n\t0xb43f5f9d, 0xc2306516, 0xa1231c47, 0xf149207e, 0x5209a795, 0x34b3ccd8,\n\t0x67aefe54, 0x2c83924e, 0x6662cbac, 0x5eedd161, 0x84e681aa, 0x5d57d26b,\n\t0xfa465cc4, 0x7e3ac3a8, 0xbf7c0cc6, 0xe18a9aa1, 0xc32f0a6f, 0xb22cc00d,\n\t0x3d280369, 0x994e554f, 0x68f480d3, 0xadcff5e6, 0x3a8eb265, 0x83269831,\n\t0xbd568a09, 0x4bc8ae6a, 0x69f56d2b, 0x0f17eac8, 0x772eb6c7, 0x9f41343c,\n\t0xab1d0742, 0x826a6f50, 0xfea2097c, 0x1912c283, 0xce185899, 0xe4444839,\n\t0x2d8635d5, 0x65d0b1ff, 0x865a7f17, 0x326d9fb1, 0x59e52820, 0x0090ade1,\n\t0x753c7149, 0x9ddd8b98, 0xa5a691da, 0x0d0382bb, 0x8904c930, 0x086cb000,\n\t0x6e69d3bd, 0x24d4e7a7, 0x05244fd0, 0x101a5e0c, 0x6a947dcb, 0xe840f77b,\n\t0x7d0c5003, 0x7c370f1f, 0x805245ed, 0xe05e3d3f, 0x7906880e, 0xbabfcd35,\n\t0x1a7ec697, 0x8c052324, 0x0c6ec8df, 0xd129a589, 0xc7a75b02, 0x12d81de7,\n\t0xd9be2a66, 0x1f4263ab, 0xde73fdb6, 0x2a00680a, 0x56649e36, 0x3133ed55,\n\t0x90fa0bf2, 0x2910a02a, 0x949d9d46, 0xa0d1dcdd, 0xcfc9b7d4, 0xd2677be5,\n\t0x95cb36b3, 0x13cd9410, 0xdbf73313, 0xb7c6e8c0, 0xf781414b, 0x510b016d,\n\t0xb0de1157, 0xd6b0f62c, 0xbb074ecc, 0x7f1395b7, 0xee792cf9, 0xea6fd63e,\n\t0x5bd6938e, 0xaf02fc64, 0xdab57ab8, 0x8edb3784, 0x8716318f, 0x164d1a01,\n\t0x26f26141, 0xb372e6b9, 0xf8fc2b06, 0x7ac00e04, 0x3727b89a, 0x97e9bca5,\n\t0x9c2a742f, 0xbc3b1f7d, 0x7165b471, 0x609b4c29, 0x20925351, 0x5ae72112,\n\t0x454be5d1, 0xc0ffb95f, 0xdd0ef919, 0x6f2d70c9, 0x0974c5bf, 0x98aa6263,\n\t0x01d91e4d, 0x2184bb6e, 0x70c43c1e, 0x4d435915, 0xae7b8523, 0xb6fb06bc,\n\t0x5431ee76, 0xfdbc5d26, 0xed77493d, 0xc5712ee4, 0xa8380437, 0x2eef261a,\n\t0x5a79392b, 0xb8af32c2, 0x41f7720a, 0x833a61ec, 0x13dfedac, 0xc4990bc4,\n\t0xdc0f54bc, 0xfedd5e88, 0x80da1881, 0x4dea1afd, 0xfd402cc6, 0xae67cc7a,\n\t0xc5238525, 0x8ea01254, 0xb56b9bd5, 0x862fbd6d, 0xac8575d3, 0x6fba3714,\n\t0xda7ebf46, 0x59cd5238, 0x8ac9dbfe, 0x353729fc, 0xe497d7f2, 0xc3ab84e0,\n\t0xf05a114b, 0x7b887a75, 0xedc603dd, 0x5e6fe680, 0x2c84b399, 0x884eb1da,\n\t0x1cb8c8bf, 0xaa51098a, 0xc862231c, 0x8bac2221, 0x21b387e5, 0x208a430d,\n\t0x2a3f0f8b, 0xa5ff9cd2, 0x6012a2ea, 0x147a9ee7, 0xf62a501d, 0xb4b2e51a,\n\t0x3ef3484c, 0xc0253c59, 0x2b82b536, 0x0aa9696b, 0xbe0c109b, 0xc70b7929,\n\t0xce3e8a19, 0x2f66950e, 0x459f1c2c, 0xe68fb93d, 0xa3c3ff3e, 0x62b45c62,\n\t0x300991cb, 0x01914c57, 0x7f7bc06a, 0x182831f5, 0xe7b74bca, 0xfa50f6d0,\n\t0x523caa61, 0xe3a7cf05, 0xe9e41311, 0x280a21d1, 0x6a4297e1, 0xf24dc67e,\n\t0xfc3189e6, 0xb72bf34f, 0x4b1e67af, 0x543402ce, 0x79a59867, 0x0648e02a,\n\t0x00a3ac17, 0xc6208d35, 0x6e7f5f76, 0xa45bb4be, 0xf168fa63, 0x3f4125f3,\n\t0xf311406f, 0x02706565, 0xbfe58022, 0x0cfcfdd9, 0x0735a7f7, 0x8f049092,\n\t0xd98edc27, 0xf5c5d55c, 0xe0f201db, 0x0dcafc9a, 0x7727fb79, 0xaf43abf4,\n\t0x26e938c1, 0x401b26a6, 0x900720fa, 0x2752d97b, 0xcff1d1b3, 0xa9d9e424,\n\t0x42db99ab, 0x6cf8be5f, 0xe82cebe3, 0x3afb733b, 0x6b734eb6, 0x1036414a,\n\t0x975f667c, 0x049d6377, 0xba587c60, 0xb1d10483, 0xde1aefcc, 0x1129d055,\n\t0x72051e91, 0x6946d623, 0xf9e86ea7, 0x48768c00, 0xb0166c93, 0x9956bbf0,\n\t0x1f1f6d84, 0xfb15e18e, 0x033b495d, 0x56e3362e, 0x4f44c53c, 0x747cba51,\n\t0x89d37872, 0x5d9c331b, 0xd2ef9fa8, 0x254917f8, 0x1b106f47, 0x37d75553,\n\t0xb3f053b0, 0x7dccd8ef, 0xd30eb802, 0x5889f42d, 0x610206d7, 0x1a7d34a1,\n\t0x92d87dd8, 0xe5f4a315, 0xd1cf0e71, 0xb22dfe45, 0xb901e8eb, 0x0fc0ce5e,\n\t0x2efa60c9, 0x2de74290, 0x36d0c906, 0x381c70e4, 0x4c6da5b5, 0x3d81a682,\n\t0x7e381f34, 0x396c4f52, 0x95ad5901, 0x1db50c5a, 0x29982e9e, 0x1557689f,\n\t0x3471ee42, 0xd7e2f7c0, 0x8795a1e2, 0xbc324d8d, 0xe224c3c8, 0x12837e39,\n\t0xcdee3d74, 0x7ad2143f, 0x0e13d40c, 0x78bd4a68, 0xa2eb194d, 0xdb9451f9,\n\t0x859b71dc, 0x5c4f5b89, 0xca14a8a4, 0xef92f003, 0x16741d98, 0x33aa4444,\n\t0x9e967fbb, 0x092e3020, 0xd86a35b8, 0x8cc17b10, 0xe1bf08ae, 0x55693fc5,\n\t0x7680ad13, 0x1e6546e8, 0x23b6e7b9, 0xee77a4b2, 0x08ed0533, 0x44fd2895,\n\t0xb6393b69, 0x05d6cacf, 0x9819b209, 0xecbbb72f, 0x9a75779c, 0xeaec0749,\n\t0x94a65aee, 0xbdf52dc3, 0xd6a25d04, 0x82008e4e, 0xa6de160f, 0x9b036afb,\n\t0x228b3a66, 0x5fb10a70, 0xcc338b58, 0x5378a9df, 0xc908bca9, 0x4959e25b,\n\t0x46909a97, 0x66ae8f6e, 0xdd0683e9, 0x65f994b4, 0x6426cda5, 0xc24b8840,\n\t0x32539da0, 0x63175650, 0xd0c815ff, 0x50cbc41e, 0xf7c774a3, 0x31b0c231,\n\t0x8d0d8116, 0x24bef16c, 0xd555d256, 0xdf47ea8c, 0x6d21eccd, 0xa887a012,\n\t0x84542aed, 0xa7b9c1bd, 0x914c1bb1, 0xa0d5b67d, 0x438ce937, 0x7030f873,\n\t0x71f6b0c7, 0x574576ba, 0xf8bc4541, 0x9c61d348, 0x1960579d, 0x17c4daad,\n\t0x96a4cb0b, 0xc193f2f6, 0x756eafa2, 0x7c1d2f94, 0xf4fe2b43, 0xcb86e33a,\n\t0xebd4c728, 0x9d18ae64, 0x9fe13e30, 0x3ce0f5de, 0xaba1f985, 0xaddc2718,\n\t0x68ce6278, 0xd45e241f, 0xa15c82b7, 0x3b2293d4, 0x739edd32, 0x674a6bf1,\n\t0x5b5d587f, 0x4772deaa, 0x4a63968f, 0x0be68686, 0x513d6426, 0x939a4787,\n\t0xbba89296, 0x4ec20007, 0x818d0d08, 0xff64dfd6, 0xcb2297cb, 0xdb48a144,\n\t0xa16cbe4b, 0xbbea1d6c, 0x5af6b6b7, 0x8a8110b6, 0xf9236ef9, 0xc98f83e6,\n\t0x0f9c65b8, 0x252d4a89, 0xa497f068, 0xa5d7ed2d, 0x94c22845, 0x9da1c8c4,\n\t0xe27c2e2e, 0x6e8ba2b4, 0xc3dd17fb, 0x498cd482, 0x0dfe6a9f, 0xb0705829,\n\t0x9a1e6dc1, 0xf829717c, 0x07bb8e3a, 0xda3c0b02, 0x1af82fc7, 0x73b70955,\n\t0x7a04379c, 0x5ee20a28, 0x83712ae5, 0xf4c47c6d, 0xdf72ba56, 0xd794858d,\n\t0x8c0cf709, 0x18f0f390, 0xb6c69b35, 0xbf2f01db, 0x2fa74dca, 0xd0cd9127,\n\t0xbde66cec, 0x3deebd46, 0x57c88fc3, 0xcee1406f, 0x0066385a, 0xf3c3444f,\n\t0x3a79d5d5, 0x75751eb9, 0x3e7f8185, 0x521c2605, 0xe1aaab6e, 0x38ebb80f,\n\t0xbee7e904, 0x61cb9647, 0xea54904e, 0x05ae00e4, 0x2d7ac65f, 0x087751a1,\n\t0xdcd82915, 0x0921ee16, 0xdd86d33b, 0xd6bd491a, 0x40fbadf0, 0x4232cbd2,\n\t0x33808d10, 0x39098c42, 0x193f3199, 0x0bc1e47a, 0x4a82b149, 0x02b65a8a,\n\t0x104cdc8e, 0x24a8f52c, 0x685c6077, 0xc79f95c9, 0x1d11fe50, 0xc08dafcd,\n\t0x7b1a9a03, 0x1c1f11d8, 0x84250e7f, 0x979db248, 0xebdc0501, 0xb9553395,\n\t0xe3c05ea8, 0xb1e51c4c, 0x13b0e681, 0x3b407766, 0x36db3087, 0xee17c9fc,\n\t0x6c53ecf2, 0xadccc58f, 0xc427660b, 0xefd5867d, 0x9b6d54a5, 0x6ff1aeff,\n\t0x8e787952, 0x9e2bffe0, 0x8761d034, 0xe00bdbad, 0xae99a8d3, 0xcc03f6e2,\n\t0xfd0ed807, 0x0e508ae3, 0xb74182ab, 0x4349245d, 0xd120a465, 0xb246a641,\n\t0xaf3b7ab0, 0x2a6488bb, 0x4b3a0d1f, 0xe7c7e58c, 0x3faff2eb, 0x90445ffd,\n\t0xcf38c393, 0x995d07e7, 0xf24f1b36, 0x356f6891, 0x6d6ebcbe, 0x8da9e262,\n\t0x50fd520e, 0x5bca9e1e, 0x37472cf3, 0x69075057, 0x7ec5fded, 0x0cab892a,\n\t0xfb2412ba, 0x1728debf, 0xa000a988, 0xd843ce79, 0x042e20dd, 0x4fe8f853,\n\t0x56659c3c, 0x2739d119, 0xa78a6120, 0x80960375, 0x70420611, 0x85e09f78,\n\t0xabd17e96, 0x1b513eaf, 0x1e01eb63, 0x26ad2133, 0xa890c094, 0x7613cf60,\n\t0x817e781b, 0xa39113d7, 0xe957fa58, 0x4131b99e, 0x28b1efda, 0x66acfba7,\n\t0xff68944a, 0x77a44fd1, 0x7f331522, 0x59ffb3fa, 0xa6df935b, 0xfa12d9df,\n\t0xc6bf6f3f, 0x89520cf6, 0x659edd6a, 0x544da739, 0x8b052538, 0x7c30ea21,\n\t0xc2345525, 0x15927fb2, 0x144a436b, 0xba107b8b, 0x1219ac97, 0x06730432,\n\t0x31831ab3, 0xc55a5c24, 0xaa0fcd3e, 0xe5606be8, 0x5c88f19b, 0x4c0841ee,\n\t0x1fe37267, 0x11f9c4f4, 0x9f1b9dae, 0x864e76d0, 0xe637c731, 0xd97d23a6,\n\t0x32f53d5c, 0xb8161980, 0x93fa0f84, 0xcaef0870, 0x8874487e, 0x98f2cc73,\n\t0x645fb5c6, 0xcd853659, 0x2062470d, 0x16ede8e9, 0x6b06dab5, 0x78b43900,\n\t0xfc95b786, 0x5d8e7de1, 0x465b5954, 0xfe7ba014, 0xf7d23f7b, 0x92bc8b18,\n\t0x03593592, 0x55cef4f7, 0x74b27317, 0x79de1fc2, 0xc8a0bfbd, 0x229398cc,\n\t0x62a602ce, 0xbcb94661, 0x5336d206, 0xd2a375fe, 0x6a6ab483, 0x4702a5a4,\n\t0xa2e9d73d, 0x23a2e0f1, 0x9189140a, 0x581d18dc, 0xb39a922b, 0x82356212,\n\t0xd5f432a9, 0xd356c2a3, 0x5f765b4d, 0x450afcc8, 0x4415e137, 0xe8ecdfbc,\n\t0xed0de3ea, 0x60d42b13, 0xf13df971, 0x71fc5da2, 0xc1455340, 0xf087742f,\n\t0xf55e5751, 0x67b3c1f8, 0xac6b8774, 0x7dcfaaac, 0x95983bc0, 0x489bb0b1,\n\t0x2c184223, 0x964b6726, 0x2bd3271c, 0x72266472, 0xded64530, 0x0a2aa343,\n\t0xd4f716a0, 0xb4dad6d9, 0x2184345e, 0x512c990c, 0x29d92d08, 0x2ebe709a,\n\t0x01144c69, 0x34584b9d, 0xe4634ed6, 0xecc963cf, 0x3c6984aa, 0x4ed056ef,\n\t0x9ca56976, 0x8f3e80d4, 0xb5bae7c5, 0x30b5caf5, 0x63f33a64, 0xa9e4bbde,\n\t0xf6b82298, 0x4d673c1d, 0x4b4f1121, 0xba183081, 0xc784f41f, 0xd17d0bac,\n\t0x083d2267, 0x37b1361e, 0x3581ad05, 0xfda2f6bc, 0x1e892cdd, 0xb56d3c3a,\n\t0x32140e46, 0x138d8aab, 0xe14773d4, 0x5b0e71df, 0x5d1fe055, 0x3fb991d3,\n\t0xf1f46c71, 0xa325988c, 0x10f66e80, 0xb1006348, 0x726a9f60, 0x3b67f8ba,\n\t0x4e114ef4, 0x05c52115, 0x4c5ca11c, 0x99e1efd8, 0x471b83b3, 0xcbf7e524,\n\t0x43ad82f5, 0x690ca93b, 0xfaa61bb2, 0x12a832b5, 0xb734f943, 0xbd22aea7,\n\t0x88fec626, 0x5e80c3e7, 0xbe3eaf5e, 0x44617652, 0xa5724475, 0xbb3b9695,\n\t0x7f3fee8f, 0x964e7deb, 0x518c052d, 0x2a0bbc2b, 0xc2175f5c, 0x9a7b3889,\n\t0xa70d8d0c, 0xeaccdd29, 0xcccd6658, 0x34bb25e6, 0xb8391090, 0xf651356f,\n\t0x52987c9e, 0x0c16c1cd, 0x8e372d3c, 0x2fc6ebbd, 0x6e5da3e3, 0xb0e27239,\n\t0x5f685738, 0x45411786, 0x067f65f8, 0x61778b40, 0x81ab2e65, 0x14c8f0f9,\n\t0xa6b7b4ce, 0x4036eaec, 0xbf62b00a, 0xecfd5e02, 0x045449a6, 0xb20afd28,\n\t0x2166d273, 0x0d13a863, 0x89508756, 0xd51a7530, 0x2d653f7a, 0x3cdbdbc3,\n\t0x80c9df4f, 0x3d5812d9, 0x53fbb1f3, 0xc0f185c0, 0x7a3c3d7e, 0x68646410,\n\t0x857607a0, 0x1d12622e, 0x97f33466, 0xdb4c9917, 0x6469607c, 0x566e043d,\n\t0x79ef1edb, 0x2c05898d, 0xc9578e25, 0xcd380101, 0x46e04377, 0x7d1cc7a9,\n\t0x6552b837, 0x20192608, 0xb97500c5, 0xed296b44, 0x368648b4, 0x62995cd5,\n\t0x82731400, 0xf9aebd8b, 0x3844c0c7, 0x7c2de794, 0x33a1a770, 0x8ae528c2,\n\t0x5a2be812, 0x1f8f4a07, 0x2b5ed7ca, 0x937eb564, 0x6fda7e11, 0xe49b5d6c,\n\t0xb4b3244e, 0x18aa53a4, 0x3a061334, 0x4d6067a3, 0x83ba5868, 0x9bdf4dfe,\n\t0x7449f261, 0x709f8450, 0xcad133cb, 0xde941c3f, 0xf52ae484, 0x781d77ed,\n\t0x7e4395f0, 0xae103b59, 0x922331bb, 0x42ce50c8, 0xe6f08153, 0xe7d941d0,\n\t0x5028ed6b, 0xb3d2c49b, 0xad4d9c3e, 0xd201fb6e, 0xa45bd5be, 0xffcb7f4b,\n\t0x579d7806, 0xf821bb5b, 0x59d592ad, 0xd0be0c31, 0xd4e3b676, 0x0107165a,\n\t0x0fe939d2, 0x49bcaafd, 0x55ffcfe5, 0x2ec1f783, 0xf39a09a5, 0x3eb42772,\n\t0x19b55a5d, 0x024a0679, 0x8c83b3f7, 0x8642ba1d, 0xacacd9ea, 0x87d352c4,\n\t0x60931f45, 0xa05f97d7, 0x1cecd42c, 0xe2fcc87b, 0xb60f94e2, 0x67a34b0b,\n\t0xfcdd40c9, 0x0b150a27, 0xd3ee9e04, 0x582e29e9, 0x4ac22b41, 0x6ac4e1b8,\n\t0xbccaa51a, 0x237af30e, 0xebc3b709, 0xc4a59d19, 0x284bc98a, 0xe9d41a93,\n\t0x6bfa2018, 0x73b2d651, 0x11f9a2fa, 0xce09bff1, 0x41a470aa, 0x25888f22,\n\t0x77e754e8, 0xf7330d8e, 0x158eab16, 0xc5d68842, 0xc685a6f6, 0xe5b82fde,\n\t0x09ea3a96, 0x6dde1536, 0x4fa919da, 0x26c0be9f, 0x9eed6f69, 0xf05555f2,\n\t0xe06fc285, 0x9cd76d23, 0xaf452a92, 0xefc74cb7, 0x9d6b4732, 0x8be408ee,\n\t0x22401d0d, 0xee6c459d, 0x7587cb82, 0xe8746862, 0x5cbdde87, 0x98794278,\n\t0x31afb94d, 0xc11e0f2f, 0x30e8fc2a, 0xcf3261ef, 0x1a3023e1, 0xaa2f86cf,\n\t0xf202e24a, 0x8d08dcff, 0x764837c6, 0xa26374cc, 0x9f7c3e88, 0x949cc57d,\n\t0xdd26a07f, 0xc39efab0, 0xc8f879a1, 0xdce67bb9, 0xf4b0a435, 0x912c9ae0,\n\t0xd85603e4, 0x953a9bbf, 0xfb8290d6, 0x0aebcd5f, 0x16206a9a, 0x6c787a14,\n\t0xd9a0f16a, 0x29bf4f74, 0x8f8bce91, 0x0e5a9354, 0xab038cb1, 0x1b8ad11b,\n\t0xe327ff49, 0x0053da20, 0x90cf51dc, 0xda92fe6d, 0x0390ca47, 0xa8958097,\n\t0xa9dc5baf, 0x3931e3c1, 0x840446b6, 0x63d069fb, 0xd7460299, 0x7124ecd1,\n\t0x0791e613, 0x485918fc, 0xd635d04c, 0xdf96ac33, 0x66f2d303, 0x247056ae,\n\t0xa1a7b2a8, 0x27d8cc9c, 0x17b6e998, 0x7bf5590f, 0xfe97f557, 0x5471d8a2,\n\t0x83a327a1, 0x9f379f51, 0x40a7d007, 0x11307423, 0x224587c1, 0xac27d63b,\n\t0x3b7e64ea, 0x2e1cbfa6, 0x09996000, 0x03bc0e2c, 0xd4c4478a, 0x4542e0ab,\n\t0xfeda26d4, 0xc1d10fcb, 0x8252f596, 0x4494eb5c, 0xa362f314, 0xf5ba81fd,\n\t0x75c3a376, 0x4ca214ca, 0xe164dedd, 0x5088fa97, 0x4b0930e0, 0x2fcfb7e8,\n\t0x33a6f4b2, 0xc7e94211, 0x2d66c774, 0x43be8bae, 0xc663d445, 0x908eb130,\n\t0xf4e3be15, 0x63b9d566, 0x529396b5, 0x1e1be743, 0x4d5ff63f, 0x985e4a83,\n\t0x71ab9df7, 0xc516c6f5, 0x85c19ab4, 0x1f4daee4, 0xf2973431, 0xb713dc5e,\n\t0x3f2e159a, 0xc824da16, 0x06bf376a, 0xb2fe23ec, 0xe39b1c22, 0xf1eecb5f,\n\t0x08e82d52, 0x565686c2, 0xab0aea93, 0xfd47219f, 0xebdbabd7, 0x2404a185,\n\t0x8c7312b9, 0xa8f2d828, 0x0c8902da, 0x65b42b63, 0xc0bbef62, 0x4e3e4cef,\n\t0x788f8018, 0xee1ebab7, 0x93928f9d, 0x683d2903, 0xd3b60689, 0xafcb0ddc,\n\t0x88a4c47a, 0xf6dd9c3d, 0x7ea5fca0, 0x8a6d7244, 0xbe11f120, 0x04ff91b8,\n\t0x8d2dc8c0, 0x27f97fdb, 0x7f9e1f47, 0x1734f0c7, 0x26f3ed8e, 0x0df8f2bf,\n\t0xb0833d9e, 0xe420a4e5, 0xa423cae6, 0x95616772, 0x9ae6c049, 0x075941f2,\n\t0xd8e12812, 0x000f6f4f, 0x3c0d6b05, 0x6cef921c, 0xb82bc264, 0x396cb008,\n\t0x5d608a6f, 0x6d7782c8, 0x186550aa, 0x6b6fec09, 0x28e70b13, 0x57ce5688,\n\t0xecd3af84, 0x23335a95, 0x91f40cd2, 0x7b6a3b26, 0xbd32b3b6, 0x3754a6fb,\n\t0x8ed088f0, 0xf867e87c, 0x20851746, 0x6410f9c6, 0x35380442, 0xc2ca10a7,\n\t0x1adea27f, 0x76bddd79, 0x92742cf4, 0x0e98f7ee, 0x164e931d, 0xb9c835b3,\n\t0x69060a99, 0xb44c531e, 0xfa7b66fe, 0xc98a5b53, 0x7d95aae9, 0x302f467b,\n\t0x74b811de, 0xf3866abd, 0xb5b3d32d, 0xfc3157a4, 0xd251fe19, 0x0b5d8eac,\n\t0xda71ffd5, 0x47ea05a3, 0x05c6a9e1, 0xca0ee958, 0x9939034d, 0x25dc5edf,\n\t0x79083cb1, 0x86768450, 0xcf757d6d, 0x5972b6bc, 0xa78d59c9, 0xc4ad8d41,\n\t0x2a362ad3, 0xd1179991, 0x601407ff, 0xdcf50917, 0x587069d0, 0xe0821ed6,\n\t0xdbb59427, 0x73911a4b, 0x7c904fc3, 0x844afb92, 0x6f8c955d, 0xe8c0c5bb,\n\t0xb67ab987, 0xa529d96c, 0xf91f7181, 0x618b1b06, 0xe718bb0c, 0x8bd7615b,\n\t0xd5a93a59, 0x54aef81b, 0x772136e3, 0xce44fd9c, 0x10cda57e, 0x87d66e0b,\n\t0x3d798967, 0x1b2c1804, 0x3edfbd68, 0x15f6e62b, 0xef68b854, 0x3896db35,\n\t0x12b7b5e2, 0xcb489029, 0x9e4f98a5, 0x62eb77a8, 0x217c24a2, 0x964152f6,\n\t0x49b2080a, 0x53d23ee7, 0x48fb6d69, 0x1903d190, 0x9449e494, 0xbf6e7886,\n\t0xfb356cfa, 0x3a261365, 0x424bc1eb, 0xa1192570, 0x019ca782, 0x9d3f7e0e,\n\t0x9c127575, 0xedf02039, 0xad57bcce, 0x5c153277, 0x81a84540, 0xbcaa7356,\n\t0xccd59b60, 0xa62a629b, 0xa25ccd10, 0x2b5b65cf, 0x1c535832, 0x55fd4e3a,\n\t0x31d9790d, 0xf06bc37d, 0x4afc1d71, 0xaeed5533, 0xba461634, 0xbb694b78,\n\t0x5f3a5c73, 0x6a3c764a, 0x8fb0cca9, 0xf725684c, 0x4fe5382f, 0x1d0163af,\n\t0x5aa07a8f, 0xe205a8ed, 0xc30bad38, 0xff22cf1f, 0x72432e2e, 0x32c2518b,\n\t0x3487ce4e, 0x7ae0ac02, 0x709fa098, 0x0a3b395a, 0x5b4043f8, 0xa9e48c36,\n\t0x149a8521, 0xd07dee6b, 0x46acd2f3, 0x8958dffc, 0xb3a1223c, 0xb11d31c4,\n\t0xcd7f4d3e, 0x0f28e3ad, 0xe5b100be, 0xaac54824, 0xe9c9d7ba, 0x9bd47001,\n\t0x80f149b0, 0x66022f0f, 0x020c4048, 0x6efa192a, 0x67073f8d, 0x13ec7bf9,\n\t0x3655011a, 0xe6afe157, 0xd9845f6e, 0xdecc4425, 0x511ae2cc, 0xdf81b4d8,\n\t0xd7809e55, 0xd6d883d9, 0x2cc7978c, 0x5e787cc5, 0xdd0033d1, 0xa050c937,\n\t0x97f75dcd, 0x299de580, 0x41e2b261, 0xea5a54f1, 0x7e672590, 0xbea513bb,\n\t0x2c906fe6, 0x86029c2b, 0x55dc4f74, 0x0553398e, 0x63e09647, 0xcafd0bab,\n\t0x264c37df, 0x8272210f, 0x67afa669, 0x12d98a5f, 0x8cab23c4, 0x75c68bd1,\n\t0xc3370470, 0x33f37f4e, 0x283992ff, 0xe73a3a67, 0x1032f283, 0xf5ad9fc2,\n\t0x963f0c5d, 0x664fbc45, 0x202ba41c, 0xc7c02d80, 0x54731e84, 0x8a1085f5,\n\t0x601d80fb, 0x2f968e55, 0x35e96812, 0xe45a8f78, 0xbd7de662, 0x3b6e6ead,\n\t0x8097c5ef, 0x070b6781, 0xb1e508f3, 0x24e4fae3, 0xb81a7805, 0xec0fc918,\n\t0x43c8774b, 0x9b2512a9, 0x2b05ad04, 0x32c2536f, 0xedf236e0, 0x8bc4b0cf,\n\t0xbaceb837, 0x4535b289, 0x0d0e94c3, 0xa5a371d0, 0xad695a58, 0x39e3437d,\n\t0x9186bffc, 0x21038c3b, 0x0aa9dff9, 0x5d1f06ce, 0x62def8a4, 0xf740a2b4,\n\t0xa2575868, 0x682683c1, 0xdbb30fac, 0x61fe1928, 0x468a6511, 0xc61cd5f4,\n\t0xe54d9800, 0x6b98d7f7, 0x8418b6a5, 0x5f09a5d2, 0x90b4e80b, 0x49b2c852,\n\t0x69f11c77, 0x17412b7e, 0x7f6fc0ed, 0x56838dcc, 0x6e9546a2, 0xd0758619,\n\t0x087b9b9a, 0xd231a01d, 0xaf46d415, 0x097060fd, 0xd920f657, 0x882d3f9f,\n\t0x3ae7c3c9, 0xe8a00d9b, 0x4fe67ebe, 0x2ef80eb2, 0xc1916b0c, 0xf4dffea0,\n\t0xb97eb3eb, 0xfdff84dd, 0xff8b14f1, 0xe96b0572, 0xf64b508c, 0xae220a6e,\n\t0x4423ae5a, 0xc2bece5e, 0xde27567c, 0xfc935c63, 0x47075573, 0xe65b27f0,\n\t0xe121fd22, 0xf2668753, 0x2debf5d7, 0x8347e08d, 0xac5eda03, 0x2a7cebe9,\n\t0x3fe8d92e, 0x23542fe4, 0x1fa7bd50, 0xcf9b4102, 0x9d0dba39, 0x9cb8902a,\n\t0xa7249d8b, 0x0f6d667a, 0x5ebfa9ec, 0x6a594df2, 0x79600938, 0x023b7591,\n\t0xea2c79c8, 0xc99d07ea, 0x64cb5ee1, 0x1a9cab3d, 0x76db9527, 0xc08e012f,\n\t0x3dfb481a, 0x872f22e7, 0x2948d15c, 0xa4782c79, 0x6f50d232, 0x78f0728a,\n\t0x5a87aab1, 0xc4e2c19c, 0xee767387, 0x1b2a1864, 0x7b8d10d3, 0xd1713161,\n\t0x0eeac456, 0xd8799e06, 0xb645b548, 0x4043cb65, 0xa874fb29, 0x4b12d030,\n\t0x7d687413, 0x18ef9a1f, 0xd7631d4c, 0x5829c7da, 0xcdfa30fa, 0xc5084bb0,\n\t0x92cd20e2, 0xd4c16940, 0x03283ec0, 0xa917813f, 0x9a587d01, 0x70041f8f,\n\t0xdc6ab1dc, 0xddaee3d5, 0x31829742, 0x198c022d, 0x1c9eafcb, 0x5bbc6c49,\n\t0xd3d3293a, 0x16d50007, 0x04bb8820, 0x3c5c2a41, 0x37ee7af8, 0x8eb04025,\n\t0x9313ecba, 0xbffc4799, 0x8955a744, 0xef85d633, 0x504499a7, 0xa6ca6a86,\n\t0xbb3d3297, 0xb34a8236, 0x6dccbe4f, 0x06143394, 0xce19fc7b, 0xccc3c6c6,\n\t0xe36254ae, 0x77b7eda1, 0xa133dd9e, 0xebf9356a, 0x513ccf88, 0xe2a1b417,\n\t0x972ee5bd, 0x853824cd, 0x5752f4ee, 0x6c1142e8, 0x3ea4f309, 0xb2b5934a,\n\t0xdfd628aa, 0x59acea3e, 0xa01eb92c, 0x389964bc, 0xda305dd4, 0x019a59b7,\n\t0x11d2ca93, 0xfaa6d3b9, 0x4e772eca, 0x72651776, 0xfb4e5b0e, 0xa38f91a8,\n\t0x1d0663b5, 0x30f4f192, 0xb50051b6, 0xb716ccb3, 0x4abd1b59, 0x146c5f26,\n\t0xf134e2de, 0x00f67c6c, 0xb0e1b795, 0x98aa4ec7, 0x0cc73b34, 0x654276a3,\n\t0x8d1ba871, 0x740a5216, 0xe0d01a23, 0x9ed161d6, 0x9f36a324, 0x993ebb7f,\n\t0xfeb9491b, 0x365ddcdb, 0x810cffc5, 0x71ec0382, 0x2249e7bf, 0x48817046,\n\t0xf3a24a5b, 0x4288e4d9, 0x0bf5c243, 0x257fe151, 0x95b64c0d, 0x4164f066,\n\t0xaaf7db08, 0x73b1119d, 0x8f9f7bb8, 0xd6844596, 0xf07a34a6, 0x53943d0a,\n\t0xf9dd166d, 0x7a8957af, 0xf8ba3ce5, 0x27c9621e, 0x5cdae910, 0xc8518998,\n\t0x941538fe, 0x136115d8, 0xaba8443c, 0x4d01f931, 0x34edf760, 0xb45f266b,\n\t0xd5d4de14, 0x52d8ac35, 0x15cfd885, 0xcbc5cd21, 0x4cd76d4d, 0x7c80ef54,\n\t0xbc92ee75, 0x1e56a1f6, 0xbaa20b6c, 0x9ffbad26, 0xe1f7d738, 0x794aec8d,\n\t0xc9e9cf3c, 0x8a9a7846, 0xc57c4685, 0xb9a92fed, 0x29cb141f, 0x52f9ddb7,\n\t0xf68ba6bc, 0x19ccc020, 0x4f584aaa, 0x3bf6a596, 0x003b7cf7, 0x54f0ce9a,\n\t0xa7ec4303, 0x46cf0077, 0x78d33aa1, 0x215247d9, 0x74bcdf91, 0x08381d30,\n\t0xdac43e40, 0x64872531, 0x0beffe5f, 0xb317f457, 0xaebb12da, 0xd5d0d67b,\n\t0x7d75c6b4, 0x42a6d241, 0x1502d0a9, 0x3fd97fff, 0xc6c3ed28, 0x81868d0a,\n\t0x92628bc5, 0x86679544, 0xfd1867af, 0x5ca3ea61, 0x568d5578, 0x4a2d71f4,\n\t0x43c9d549, 0x8d95de2b, 0x6e5c74a0, 0x9120ffc7, 0x0d05d14a, 0xa93049d3,\n\t0xbfa80e17, 0xf4096810, 0x043f5ef5, 0xa673b4f1, 0x6d780298, 0xa4847783,\n\t0x5ee726fb, 0x9934c281, 0x220a588c, 0x384e240f, 0x933d5c69, 0x39e5ef47,\n\t0x26e8b8f3, 0x4c1c6212, 0x8040f75d, 0x074b7093, 0x6625a8d7, 0x36298945,\n\t0x76285088, 0x651d37c3, 0x24f5274d, 0xdbca3dab, 0x186b7ee1, 0xd80f8182,\n\t0x14210c89, 0x943a3075, 0x4e6e11c4, 0x4d7e6bad, 0xf05064c8, 0x025dcd97,\n\t0x4bc10302, 0x7cede572, 0x8f90a970, 0xab88eeba, 0xb5998029, 0x5124d839,\n\t0xb0eeb6a3, 0x89ddabdc, 0xe8074d76, 0xa1465223, 0x32518cf2, 0x9d39d4eb,\n\t0xc0d84524, 0xe35e6ea8, 0x7abf3804, 0x113e2348, 0x9ae6069d, 0xb4dfdabb,\n\t0xa8c5313f, 0x23ea3f79, 0x530e36a2, 0xa5fd228b, 0x95d1d350, 0x2b14cc09,\n\t0x40042956, 0x879d05cc, 0x2064b9ca, 0xacaca40e, 0xb29c846e, 0x9676c9e3,\n\t0x752b7b8a, 0x7be2bcc2, 0x6bd58f5e, 0xd48f4c32, 0x606835e4, 0x9cd7c364,\n\t0x2c269b7a, 0x3a0d079c, 0x73b683fe, 0x45374f1e, 0x10afa242, 0x577f8666,\n\t0xddaa10f6, 0xf34f561c, 0x3d355d6b, 0xe47048ae, 0xaa13c492, 0x050344fd,\n\t0x2aab5151, 0xf5b26ae5, 0xed919a59, 0x5ac67900, 0xf1cde380, 0x0c79a11b,\n\t0x351533fc, 0xcd4d8e36, 0x1f856005, 0x690b9fdd, 0xe736dccf, 0x1d47bf6a,\n\t0x7f66c72a, 0x85f21b7f, 0x983cbdb6, 0x01ebbebf, 0x035f3b99, 0xeb111f34,\n\t0x28cefdc6, 0x5bfc9ecd, 0xf22eacb0, 0x9e41cbb2, 0xe0f8327c, 0x82e3e26f,\n\t0xfc43fc86, 0xd0ba66df, 0x489ef2a7, 0xd9e0c81d, 0x68690d52, 0xcc451367,\n\t0xc2232e16, 0xe95a7335, 0x0fdae19b, 0xff5b962c, 0x97596527, 0xc46db333,\n\t0x3ed4c562, 0xc14c9d9e, 0x5d6faa21, 0x638e940d, 0xf9316d58, 0x47b3b0ea,\n\t0x30ffcad2, 0xce1bba7d, 0x1e6108e6, 0x2e1ea33d, 0x507bf05b, 0xfafef94b,\n\t0xd17de8e2, 0x5598b214, 0x1663f813, 0x17d25a2d, 0xeefa5ff9, 0x582f4e37,\n\t0x12128773, 0xfef17ab8, 0x06005322, 0xbb32bbc9, 0x8c898508, 0x592c15f0,\n\t0xd38a4054, 0x4957b7d6, 0xd2b891db, 0x37bd2d3e, 0x34ad20cb, 0x622288e9,\n\t0x2dc7345a, 0xafb416c0, 0x1cf459b1, 0xdc7739fa, 0x0a711a25, 0x13e18a0c,\n\t0x5f72af4c, 0x6ac8db11, 0xbe53c18e, 0x1aa569b9, 0xef551ea4, 0xa02a429f,\n\t0xbd16e790, 0x7eb9171a, 0x77d693d8, 0x8e06993a, 0x9bde7560, 0xe5801987,\n\t0xc37a09be, 0xb8db76ac, 0xe2087294, 0x6c81616d, 0xb7f30fe7, 0xbc9b82bd,\n\t0xfba4e4d4, 0xc7b1012f, 0xa20c043b, 0xde9febd0, 0x2f9297ce, 0xe610aef8,\n\t0x70b06f19, 0xc86ae00b, 0x0e01988f, 0x41192ae0, 0x448c1cb5, 0xadbe92ee,\n\t0x7293a007, 0x1b54b5b3, 0xd61f63d1, 0xeae40a74, 0x61a72b55, 0xec83a7d5,\n\t0x88942806, 0x90a07da5, 0xd7424b95, 0x67745b4e, 0xa31a1853, 0xca6021ef,\n\t0xdfb56c4f, 0xcbc2d915, 0x3c48e918, 0x8bae3c63, 0x6f659c71, 0xf8b754c1,\n\t0x2782f3de, 0xf796f168, 0x71492c84, 0x33c0f5a6, 0x3144f6ec, 0x25dc412e,\n\t0xb16c5743, 0x83a1fa7e, 0x0997b101, 0xb627e6e8, 0xcf33905c, 0x8456fb65,\n\t0xb29bea74, 0xc35da605, 0x305c1ca3, 0xd2e9f5bc, 0x6fd5bff4, 0xff347703,\n\t0xfc45b163, 0xf498e068, 0xb71229fc, 0x81acc3fb, 0x78538a8b, 0x984ecf81,\n\t0xa5da47a4, 0x8f259eef, 0x6475dc65, 0x081865b9, 0x49e14a3c, 0x19e66079,\n\t0xd382e91b, 0x5b109794, 0x3f9f81e1, 0x4470a388, 0x41601abe, 0xaaf9f407,\n\t0x8e175ef6, 0xed842297, 0x893a4271, 0x1790839a, 0xd566a99e, 0x6b417dee,\n\t0x75c90d23, 0x715edb31, 0x723553f7, 0x9afb50c9, 0xfbc5f600, 0xcd3b6a4e,\n\t0x97ed0fba, 0x29689aec, 0x63135c8e, 0xf0e26c7e, 0x0692ae7f, 0xdbb208ff,\n\t0x2ede3e9b, 0x6a65bebd, 0xd40867e9, 0xc954afc5, 0x73b08201, 0x7ffdf809,\n\t0x1195c24f, 0x1ca5adca, 0x74bd6d1f, 0xb393c455, 0xcadfd3fa, 0x99f13011,\n\t0x0ebca813, 0x60e791b8, 0x6597ac7a, 0x18a7e46b, 0x09cb49d3, 0x0b27df6d,\n\t0xcfe52f87, 0xcef66837, 0xe6328035, 0xfa87c592, 0x37baff93, 0xd71fcc99,\n\t0xdcab205c, 0x4d7a5638, 0x48012510, 0x62797558, 0xb6cf1fe5, 0xbc311834,\n\t0x9c2373ac, 0x14ec6175, 0xa439cbdf, 0x54afb0ea, 0xd686960b, 0xfdd0d47b,\n\t0x7b063902, 0x8b78bac3, 0x26c6a4d5, 0x5c0055b6, 0x2376102e, 0x0411783e,\n\t0x2aa3f1cd, 0x51fc6ea8, 0x701ce243, 0x9b2a0abb, 0x0ad93733, 0x6e80d03d,\n\t0xaf6295d1, 0xf629896f, 0xa30b0648, 0x463d8dd4, 0x963f84cb, 0x01ff94f8,\n\t0x8d7fefdc, 0x553611c0, 0xa97c1719, 0xb96af759, 0xe0e3c95e, 0x0528335b,\n\t0x21fe5925, 0x821a5245, 0x807238b1, 0x67f23db5, 0xea6b4eab, 0x0da6f985,\n\t0xab1bc85a, 0xef8c90e4, 0x4526230e, 0x38eb8b1c, 0x1b91cd91, 0x9fce5f0c,\n\t0xf72cc72b, 0xc64f2617, 0xdaf7857d, 0x7d373cf1, 0x28eaedd7, 0x203887d0,\n\t0xc49a155f, 0xa251b3b0, 0xf2d47ae3, 0x3d9ef267, 0x4a94ab2f, 0x7755a222,\n\t0x0205e329, 0xc28fa7a7, 0xaec1fe51, 0x270f164c, 0x8c6d01bf, 0x53b5bc98,\n\t0xc09d3feb, 0x834986cc, 0x4309a12c, 0x578b2a96, 0x3bb74b86, 0x69561b4a,\n\t0x037e32f3, 0xde335b08, 0xc5156be0, 0xe7ef09ad, 0x93b834c7, 0xa7719352,\n\t0x59302821, 0xe3529d26, 0xf961da76, 0xcb142c44, 0xa0f3b98d, 0x76502457,\n\t0x945a414b, 0x078eeb12, 0xdff8de69, 0xeb6c8c2d, 0xbda90c4d, 0xe9c44d16,\n\t0x168dfd66, 0xad64763b, 0xa65fd764, 0x95a29c06, 0x32d7713f, 0x40f0b277,\n\t0x224af08f, 0x004cb5e8, 0x92574814, 0x8877d827, 0x3e5b2d04, 0x68c2d5f2,\n\t0x86966273, 0x1d433ada, 0x8774988a, 0x3c0e0bfe, 0xddad581d, 0x2fd654ed,\n\t0x0f4769fd, 0xc181ee9d, 0x5fd88f61, 0x341dbb3a, 0x528543f9, 0xd92235cf,\n\t0x1ea82eb4, 0xb5cd790f, 0x91d24f1e, 0xa869e6c2, 0x61f474d2, 0xcc205add,\n\t0x0c7bfba9, 0xbf2b0489, 0xb02d72d8, 0x2b46ece6, 0xe4dcd90a, 0xb8a11440,\n\t0xee8a63b7, 0x854dd1a1, 0xd1e00583, 0x42b40e24, 0x9e8964de, 0xb4b35d78,\n\t0xbec76f6e, 0x24b9c620, 0xd8d399a6, 0x5adb2190, 0x2db12730, 0x3a5866af,\n\t0x58c8fadb, 0x5d8844e7, 0x8a4bf380, 0x15a01d70, 0x79f5c028, 0x66be3b8c,\n\t0xf3e42b53, 0x56990039, 0x2c0c3182, 0x5e16407c, 0xecc04515, 0x6c440284,\n\t0x4cb6701a, 0x13bfc142, 0x9d039f6a, 0x4f6e92c8, 0xa1407c62, 0x8483a095,\n\t0xc70ae1c4, 0xe20213a2, 0xbacafc41, 0x4ecc12b3, 0x4bee3646, 0x1fe807ae,\n\t0x25217f9c, 0x35dde5f5, 0x7a7dd6ce, 0xf89cce50, 0xac07b718, 0x7e73d2c6,\n\t0xe563e76c, 0x123ca536, 0x3948ca56, 0x9019dd49, 0x10aa88d9, 0xc82451e2,\n\t0x473eb6d6, 0x506fe854, 0xe8bb03a5, 0x332f4c32, 0xfe1e1e72, 0xb1ae572a,\n\t0x7c0d7bc1, 0xe1c37eb2, 0xf542aa60, 0xf1a48ea0, 0xd067b89f, 0xbbfa195d,\n\t0x1a049b0d, 0x315946aa, 0x36d1b447, 0x6d2ebdf0, 0x0d188a6d, 0x12cea0db,\n\t0x7e63740e, 0x6a444821, 0x253d234f, 0x6ffc6597, 0x94a6bdef, 0x33ee1b2f,\n\t0x0a6c00c0, 0x3aa336b1, 0x5af55d17, 0x265fb3dc, 0x0e89cf4d, 0x0786b008,\n\t0xc80055b8, 0x6b17c3ce, 0x72b05a74, 0xd21a8d78, 0xa6b70840, 0xfe8eae77,\n\t0xed69565c, 0x55e1bcf4, 0x585c2f60, 0xe06f1a62, 0xad67c0cd, 0x7712af88,\n\t0x9cc26aca, 0x1888053d, 0x37eb853e, 0x9215abd7, 0xde30adfc, 0x1f1038e6,\n\t0x70c51c8a, 0x8d586c26, 0xf72bdd90, 0x4dc3ce15, 0x68eaeefa, 0xd0e9c8b9,\n\t0x200f9c44, 0xddd141ba, 0x024bf1d3, 0x0f64c9d4, 0xc421e9e9, 0x9d11c14c,\n\t0x9a0dd9e4, 0x5f92ec19, 0x1b980df0, 0x1dcc4542, 0xb8fe8c56, 0x0c9c9167,\n\t0x4e81eb49, 0xca368f27, 0xe3603b37, 0xea08accc, 0xac516992, 0xc34f513b,\n\t0x804d100d, 0x6edca4c4, 0xfc912939, 0x29d219b0, 0x278aaa3c, 0x4868da7d,\n\t0x54e890b7, 0xb46d735a, 0x514589aa, 0xd6c630af, 0x4980dfe8, 0xbe3ccc55,\n\t0x59d41202, 0x650c078b, 0xaf3a9e7b, 0x3ed9827a, 0x9e79fc6e, 0xaadbfbae,\n\t0xc5f7d803, 0x3daf7f50, 0x67b4f465, 0x73406e11, 0x39313f8c, 0x8a6e6686,\n\t0xd8075f1f, 0xd3cbfed1, 0x69c7e49c, 0x930581e0, 0xe4b1a5a8, 0xbbc45472,\n\t0x09ddbf58, 0xc91d687e, 0xbdbffda5, 0x88c08735, 0xe9e36bf9, 0xdb5ea9b6,\n\t0x95559404, 0x08f432fb, 0xe24ea281, 0x64663579, 0x000b8010, 0x7914e7d5,\n\t0x32fd0473, 0xd1a7f0a4, 0x445ab98e, 0xec72993f, 0xa29a4d32, 0xb77306d8,\n\t0xc7c97cf6, 0x7b6ab645, 0xf5ef7adf, 0xfb2e15f7, 0xe747f757, 0x5e944354,\n\t0x234a2669, 0x47e46359, 0x9b9d11a9, 0x40762ced, 0x56f1de98, 0x11334668,\n\t0x890a9a70, 0x1a296113, 0xb3bd4af5, 0x163b7548, 0xd51b4f84, 0xb99b2abc,\n\t0x3cc1dc30, 0xa9f0b56c, 0x812272b2, 0x0b233a5f, 0xb650dbf2, 0xf1a0771b,\n\t0x36562b76, 0xdc037b0f, 0x104c97ff, 0xc2ec98d2, 0x90596f22, 0x28b6620b,\n\t0xdf42b212, 0xfdbc4243, 0xf3fb175e, 0x4a2d8b00, 0xe8f3869b, 0x30d69bc3,\n\t0x853714c8, 0xa7751d2e, 0x31e56dea, 0xd4840b0c, 0x9685d783, 0x068c9333,\n\t0x8fba032c, 0x76d7bb47, 0x6d0ee22b, 0xb546794b, 0xd971b894, 0x8b09d253,\n\t0xa0ad5761, 0xee77ba06, 0x46359f31, 0x577cc7ec, 0x52825efd, 0xa4beed95,\n\t0x9825c52a, 0xeb48029a, 0xbaae59f8, 0xcf490ee1, 0xbc990164, 0x8ca49dfe,\n\t0x4f38a6e7, 0x2ba98389, 0x8228f538, 0x199f64ac, 0x01a1cac5, 0xa8b51641,\n\t0x5ce72d01, 0x8e5df26b, 0x60f28e1e, 0xcd5be125, 0xe5b376bf, 0x1c8d3116,\n\t0x7132cbb3, 0xcb7ae320, 0xc0fa5366, 0xd7653e34, 0x971c88c2, 0xc62c7dd0,\n\t0x34d0a3da, 0x868f6709, 0x7ae6fa8f, 0x22bbd523, 0x66cd3d5b, 0x1ef9288d,\n\t0xf9cf58c1, 0x5b784e80, 0x7439a191, 0xae134c36, 0x9116c463, 0x2e9e1396,\n\t0xf8611f3a, 0x2d2f3307, 0x247f37dd, 0xc1e2ff9d, 0x43c821e5, 0x05ed5cab,\n\t0xef74e80a, 0x4cca6028, 0xf0ac3cbd, 0x5d874b29, 0x6c62f6a6, 0x4b2a2ef3,\n\t0xb1aa2087, 0x62a5d0a3, 0x0327221c, 0xb096b4c6, 0x417ec693, 0xaba840d6,\n\t0x789725eb, 0xf4b9e02d, 0xe6e00975, 0xcc04961a, 0x63f624bb, 0x7fa21ecb,\n\t0x2c01ea7f, 0xb2415005, 0x2a8bbeb5, 0x83b2b14e, 0xa383d1a7, 0x5352f96a,\n\t0x043ecdad, 0xce1918a1, 0xfa6be6c9, 0x50def36f, 0xf6b80ce2, 0x4543ef7c,\n\t0x9953d651, 0xf257955d, 0x87244914, 0xda1e0a24, 0xffda4785, 0x14d327a2,\n\t0x3b93c29f, 0x840684b4, 0x61ab71a0, 0x9f7b784a, 0x2fd570cf, 0x15955bde,\n\t0x38f8d471, 0x3534a718, 0x133fb71d, 0x3fd80f52, 0x4290a8be, 0x75ff44c7,\n\t0xa554e546, 0xe1023499, 0xbf2652e3, 0x7d20399e, 0xa1df7e82, 0x177092ee,\n\t0x217dd3f1, 0x7c1ff8d9, 0x12113f2e, 0xbfbd0785, 0xf11793fb, 0xa5bff566,\n\t0x83c7b0e5, 0x72fb316b, 0x75526a9a, 0x41e0e612, 0x7156ba09, 0x53ce7dee,\n\t0x0aa26881, 0xa43e0d7d, 0x3da73ca3, 0x182761ed, 0xbd5077ff, 0x56db4aa0,\n\t0xe792711c, 0xf0a4eb1d, 0x7f878237, 0xec65c4e8, 0x08dc8d43, 0x0f8ce142,\n\t0x8258abda, 0xf4154e16, 0x49dec2fd, 0xcd8d5705, 0x6c2c3a0f, 0x5c12bb88,\n\t0xeff3cdb6, 0x2c89ed8c, 0x7beba967, 0x2a142157, 0xc6d0836f, 0xb4f97e96,\n\t0x6931e969, 0x514e6c7c, 0xa7792600, 0x0bbbf780, 0x59671bbd, 0x0707b676,\n\t0x37482d93, 0x80af1479, 0x3805a60d, 0xe1f4cac1, 0x580b3074, 0x30b8d6ce,\n\t0x05a304be, 0xd176626d, 0xebca97f3, 0xbb201f11, 0x6a1afe23, 0xffaa86e4,\n\t0x62b4da49, 0x1b6629f5, 0xf5d9e092, 0xf37f3dd1, 0x619bd45b, 0xa6ec8e4f,\n\t0x29c80939, 0x0c7c0c34, 0x9cfe6e48, 0xe65fd3ac, 0x73613b65, 0xb3c669f9,\n\t0xbe2e8a9e, 0x286f9678, 0x5797fd13, 0x99805d75, 0xcfb641c5, 0xa91074ba,\n\t0x6343af47, 0x6403cb46, 0x8894c8db, 0x2663034c, 0x3c40dc5e, 0x00995231,\n\t0x96789aa2, 0x2efde4b9, 0x7dc195e1, 0x547dadd5, 0x06a8ea04, 0xf2347a63,\n\t0x5e0dc6f7, 0x8462dfc2, 0x1e6b2c3c, 0x9bd275b3, 0x91d419e2, 0xbcefd17e,\n\t0xb9003924, 0xd07e7320, 0xdef0495c, 0xc36ad00e, 0x1785b1ab, 0x92e20bcf,\n\t0xb139f0e9, 0x675bb9a1, 0xaecfa4af, 0x132376cb, 0xe84589d3, 0x79a05456,\n\t0xa2f860bc, 0x1ae4f8b5, 0x20df4db4, 0xa1e1428b, 0x3bf60a1a, 0x27ff7bf1,\n\t0xcb44c0e7, 0xf7f587c4, 0x1f3b9b21, 0x94368f01, 0x856e23a4, 0x6f93de3f,\n\t0x773f5bbf, 0x8b22056e, 0xdf41f654, 0xb8246ff4, 0x8d57bff2, 0xd57167ea,\n\t0xc5699f22, 0x40734ba7, 0x5d5c2772, 0x033020a8, 0xe30a7c4d, 0xadc40fd6,\n\t0x76353441, 0x5aa5229b, 0x81516590, 0xda49f14e, 0x4fa672a5, 0x4d9fac5f,\n\t0x154be230, 0x8a7a5cc0, 0xce3d2f84, 0xcca15514, 0x5221360c, 0xaf0fb81e,\n\t0x5bdd5873, 0xf6825f8f, 0x1113d228, 0x70ad996c, 0x93320051, 0x60471c53,\n\t0xe9ba567b, 0x3a462ae3, 0x5f55e72d, 0x1d3c5ad7, 0xdcfc45ec, 0x34d812ef,\n\t0xfa96ee1b, 0x369d1ef8, 0xc9b1a189, 0x7c1d3555, 0x50845edc, 0x4bb31877,\n\t0x8764a060, 0x8c9a9415, 0x230e1a3a, 0xb05e9133, 0x242b9e03, 0xa3b99db7,\n\t0xc2d7fb0a, 0x3333849d, 0xd27278d4, 0xb5d3efa6, 0x78ac28ad, 0xc7b2c135,\n\t0x0926ecf0, 0xc1374c91, 0x74f16d98, 0x2274084a, 0x3f6d9cfa, 0x7ac0a383,\n\t0xb73aff1f, 0x3909a23d, 0x9f1653ae, 0x4e2f3e71, 0xca5ab22a, 0xe01e3858,\n\t0x90c5a7eb, 0x3e4a17df, 0xaa987fb0, 0x488bbd62, 0xb625062b, 0x2d776bb8,\n\t0x43b5fc08, 0x1490d532, 0xd6d12495, 0x44e89845, 0x2fe60118, 0x9d9ef950,\n\t0xac38133e, 0xd3864329, 0x017b255a, 0xfdc2dd26, 0x256851e6, 0x318e7086,\n\t0x2bfa4861, 0x89eac706, 0xee5940c6, 0x68c3bc2f, 0xe260334b, 0x98da90bb,\n\t0xf818f270, 0x4706d897, 0x212d3799, 0x4cf7e5d0, 0xd9c9649f, 0xa85db5cd,\n\t0x35e90e82, 0x6b881152, 0xab1c02c7, 0x46752b02, 0x664f598e, 0x45ab2e64,\n\t0xc4cdb4b2, 0xba42107f, 0xea2a808a, 0x971bf3de, 0x4a54a836, 0x4253aecc,\n\t0x1029be68, 0x6dcc9225, 0xe4bca56a, 0xc0ae50b1, 0x7e011d94, 0xe59c162c,\n\t0xd8e5c340, 0xd470fa0b, 0xb2be79dd, 0xd783889c, 0x1cede8f6, 0x8f4c817a,\n\t0xddb785c9, 0x860232d8, 0x198aaad9, 0xa0814738, 0x3219cffc, 0x169546d2,\n\t0xfc0cb759, 0x55911510, 0x04d5cec3, 0xed08cc3b, 0x0d6cf427, 0xc8e38cca,\n\t0x0eeee3fe, 0x9ee7d7c8, 0xf9f24fa9, 0xdb04b35d, 0x9ab0c9e0, 0x651f4417,\n\t0x028f8b07, 0x6e28d9aa, 0xfba96319, 0x8ed66687, 0xfecbc58d, 0x954ddb44,\n\t0x7b0bdffe, 0x865d16b1, 0x49a058c0, 0x97abaa3f, 0xcaacc75d, 0xaba6c17d,\n\t0xf8746f92, 0x6f48aeed, 0x8841d4b5, 0xf36a146a, 0x73c390ab, 0xe6fb558f,\n\t0x87b1019e, 0x26970252, 0x246377b2, 0xcbf676ae, 0xf923db06, 0xf7389116,\n\t0x14c81a90, 0x83114eb4, 0x8b137559, 0x95a86a7a, 0xd5b8da8c, 0xc4df780e,\n\t0x5a9cb3e2, 0xe44d4062, 0xe8dc8ef6, 0x9d180845, 0x817ad18b, 0xc286c85b,\n\t0x251f20de, 0xee6d5933, 0xf6edef81, 0xd4d16c1e, 0xc94a0c32, 0x8437fd22,\n\t0x3271ee43, 0x42572aee, 0x5f91962a, 0x1c522d98, 0x59b23f0c, 0xd86b8804,\n\t0x08c63531, 0x2c0d7a40, 0xb97c4729, 0x04964df9, 0x13c74a17, 0x5878362f,\n\t0x4c808cd6, 0x092cb1e0, 0x6df02885, 0xa0c2105e, 0x8aba9e68, 0x64e03057,\n\t0xe5d61325, 0x0e43a628, 0x16dbd62b, 0x2733d90b, 0x3ae57283, 0xc0c1052c,\n\t0x4b6fb620, 0x37513953, 0xfc898bb3, 0x471b179f, 0xdf6e66b8, 0xd32142f5,\n\t0x9b30fafc, 0x4ed92549, 0x105c6d99, 0x4acd69ff, 0x2b1a27d3, 0x6bfcc067,\n\t0x6301a278, 0xad36e6f2, 0xef3ff64e, 0x56b3cadb, 0x0184bb61, 0x17beb9fd,\n\t0xfaec6109, 0xa2e1ffa1, 0x2fd224f8, 0x238f5be6, 0x8f8570cf, 0xaeb5f25a,\n\t0x4f1d3e64, 0x4377eb24, 0x1fa45346, 0xb2056386, 0x52095e76, 0xbb7b5adc,\n\t0x3514e472, 0xdde81e6e, 0x7acea9c4, 0xac15cc48, 0x71c97d93, 0x767f941c,\n\t0x911052a2, 0xffea09bf, 0xfe3ddcf0, 0x15ebf3aa, 0x9235b8bc, 0x75408615,\n\t0x9a723437, 0xe1a1bd38, 0x33541b7e, 0x1bdd6856, 0xb307e13e, 0x90814bb0,\n\t0x51d7217b, 0x0bb92219, 0x689f4500, 0xc568b01f, 0x5df3d2d7, 0x3c0ecd0d,\n\t0x2a0244c8, 0x852574e8, 0xe72f23a9, 0x8e26ed02, 0x2d92cbdd, 0xdabc0458,\n\t0xcdf5feb6, 0x9e4e8dcc, 0xf4f1e344, 0x0d8c436d, 0x4427603b, 0xbdd37fda,\n\t0x80505f26, 0x8c7d2b8e, 0xb73273c5, 0x397362ea, 0x618a3811, 0x608bfb88,\n\t0x06f7d714, 0x212e4677, 0x28efcead, 0x076c0371, 0x36a3a4d9, 0x5487b455,\n\t0x3429a365, 0x65d467ac, 0x78ee7eeb, 0x99bf12b7, 0x4d129896, 0x772a5601,\n\t0xcce284c7, 0x2ed85c21, 0xd099e8a4, 0xa179158a, 0x6ac0ab1a, 0x299a4807,\n\t0xbe67a58d, 0xdc19544a, 0xb8949b54, 0x8d315779, 0xb6f849c1, 0x53c5ac34,\n\t0x66de92a5, 0xf195dd13, 0x318d3a73, 0x301ec542, 0x0cc40da6, 0xf253ade4,\n\t0x467ee566, 0xea5585ec, 0x3baf19bb, 0x7de9f480, 0x79006e7c, 0xa9b7a197,\n\t0xa44bd8f1, 0xfb2ba739, 0xec342fd4, 0xed4fd32d, 0x3d1789ba, 0x400f5d7f,\n\t0xc798f594, 0x4506a847, 0x034c0a95, 0xe2162c9d, 0x55a9cfd0, 0x692d832e,\n\t0xcf9db2ca, 0x5e2287e9, 0xd2610ef3, 0x1ae7ecc2, 0x48399ca0, 0xa7e4269b,\n\t0x6ee3a0af, 0x7065bfe1, 0xa6ffe708, 0x2256804c, 0x7476e21b, 0x41b0796c,\n\t0x7c243b05, 0x000a950f, 0x1858416b, 0xf5a53c89, 0xe9fef823, 0x3f443275,\n\t0xe0cbf091, 0x0af27b84, 0x3ebb0f27, 0x1de6f7f4, 0xc31c29f7, 0xb166de3d,\n\t0x12932ec3, 0x9c0c0674, 0x5cda81b9, 0xd1bd9d12, 0xaffd7c82, 0x8962bca7,\n\t0xa342c4a8, 0x62457151, 0x82089f03, 0xeb49c670, 0x5b5f6530, 0x7e28bad2,\n\t0x20880ba3, 0xf0faafcd, 0xce82b56f, 0x0275335c, 0xc18e8afb, 0xde601d69,\n\t0xba9b820a, 0xc8a2be4f, 0xd7cac335, 0xd9a73741, 0x115e974d, 0x7f5ac21d,\n\t0x383bf9c6, 0xbcaeb75f, 0xfd0350ce, 0xb5d06b87, 0x9820e03c, 0x72d5f163,\n\t0xe3644fc9, 0xa5464c4b, 0x57048fcb, 0x9690c9df, 0xdbf9eafa, 0xbff4649a,\n\t0x053c00e3, 0xb4b61136, 0x67593dd1, 0x503ee960, 0x9fb4993a, 0x19831810,\n\t0xc670d518, 0xb05b51d8, 0x0f3a1ce5, 0x6caa1f9c, 0xaacc31be, 0x949ed050,\n\t0x1ead07e7, 0xa8479abd, 0xd6cffcd5, 0x936993ef, 0x472e91cb, 0x5444b5b6,\n\t0x62be5861, 0x1be102c7, 0x63e4b31e, 0xe81f71b7, 0x9e2317c9, 0x39a408ae,\n\t0x518024f4, 0x1731c66f, 0x68cbc918, 0x71fb0c9e, 0xd03b7fdd, 0x7d6222eb,\n\t0x9057eda3, 0x1a34a407, 0x8cc2253d, 0xb6f6979d, 0x835675dc, 0xf319be9f,\n\t0xbe1cd743, 0x4d32fee4, 0x77e7d887, 0x37e9ebfd, 0x15f851e8, 0x23dc3706,\n\t0x19d78385, 0xbd506933, 0xa13ad4a6, 0x913f1a0e, 0xdde560b9, 0x9a5f0996,\n\t0xa65a0435, 0x48d34c4d, 0xe90839a7, 0x8abba54e, 0x6fd13ce1, 0xc7eebd3c,\n\t0x0e297602, 0x58b9bbb4, 0xef7901e6, 0x64a28a62, 0xa509875a, 0xf8834442,\n\t0x2702c709, 0x07353f31, 0x3b39f665, 0xf5b18b49, 0x4010ae37, 0x784de00b,\n\t0x7a1121e9, 0xde918ed3, 0xc8529dcd, 0x816a5d05, 0x02ed8298, 0x04e3dd84,\n\t0xfd2bc3e2, 0xaf167089, 0x96af367e, 0xa4da6232, 0x18ff7325, 0x05f9a9f1,\n\t0x4fefb9f9, 0xcd94eaa5, 0xbfaa5069, 0xa0b8c077, 0x60d86f57, 0xfe71c813,\n\t0x29ebd2c8, 0x4ca86538, 0x6bf1a030, 0xa237b88a, 0xaa8af41d, 0xe1f7b6ec,\n\t0xe214d953, 0x33057879, 0x49caa736, 0xfa45cff3, 0xc063b411, 0xba7e27d0,\n\t0x31533819, 0x2a004ac1, 0x210efc3f, 0x2646885e, 0x66727dcf, 0x9d7fbf54,\n\t0xa8dd0ea8, 0x3447cace, 0x3f0c14db, 0xb8382aac, 0x4ace3539, 0x0a518d51,\n\t0x95178981, 0x35aee2ca, 0x73f0f7e3, 0x94281140, 0x59d0e523, 0xd292cb88,\n\t0x565d1b27, 0x7ec8fbaf, 0x069af08d, 0xc127fd24, 0x0bc77b10, 0x5f03e7ef,\n\t0x453e99ba, 0xeed9ff7f, 0x87b55215, 0x7915ab4c, 0xd389a358, 0x5e75ce6d,\n\t0x28d655c0, 0xdad26c73, 0x2e2510ff, 0x9fa7eecc, 0x1d0629c3, 0xdc9c9c46,\n\t0x2d67ecd7, 0xe75e94bd, 0x3d649e2a, 0x6c413a2b, 0x706f0d7c, 0xdfb0127b,\n\t0x4e366b55, 0x2c825650, 0x24205720, 0xb5c998f7, 0x3e95462c, 0x756e5c72,\n\t0x3259488f, 0x11e8771a, 0xa7c0a617, 0x577663e5, 0x089b6401, 0x8eab1941,\n\t0xae55ef8c, 0x3aac5460, 0xd4e6262f, 0x5d979a47, 0xb19823b0, 0x7f8d6a0c,\n\t0xffa08683, 0x0170cd0f, 0x858cd5d8, 0x53961c90, 0xc4c61556, 0x41f2f226,\n\t0xcfcd062d, 0xf24c03b8, 0xea81df5b, 0x7be2fa52, 0xb361f98b, 0xc2901316,\n\t0x55ba4bbc, 0x93b234a9, 0x0fbc6603, 0x80a96822, 0x6d60491f, 0x22bd00f8,\n\t0xbcad5aad, 0x52f3f13b, 0x42fd2b28, 0xb41dd01c, 0xc52c93bf, 0xfc663094,\n\t0x8f58d100, 0x43fecc08, 0xc6331e5d, 0xe6480f66, 0xca847204, 0x4bdf1da0,\n\t0x30cc2efb, 0x13e02dea, 0xfb49ac45, 0xf9d4434f, 0xf47c5b9c, 0x148879c2,\n\t0x039fc234, 0xa3db9bfc, 0xd1a1dc5c, 0x763d7cd4, 0xed6d2f93, 0xab13af6e,\n\t0x1e8e054a, 0xd68f4f9a, 0xc30484b3, 0xd7d50afa, 0x6930855f, 0xcc07db95,\n\t0xce746db1, 0x744e967d, 0xf16cf575, 0x8643e8b5, 0xf0eae38e, 0xe52de1d1,\n\t0x6587dae0, 0x0c4b8121, 0x1c7ac567, 0xac0db20a, 0x36c3a812, 0x5b1a4514,\n\t0xa9a3f868, 0xb9263baa, 0xcb3ce9d2, 0xe44fb1a4, 0x9221bc82, 0xb29390fe,\n\t0x6ab41863, 0x974a3e2e, 0x89f531c5, 0x255ca13e, 0x8b65d348, 0xec248f78,\n\t0xd8fc16f0, 0x50ecdeee, 0x09010792, 0x3c7d1fb2, 0xeba5426b, 0x847b417a,\n\t0x468b40d9, 0x8dc4e680, 0x7cc1f391, 0x2f1eb086, 0x6e5baa6a, 0xe0b395da,\n\t0xe31b2cf6, 0xd9690b0d, 0x729ec464, 0x38403dde, 0x610b80a2, 0x5cf433ab,\n\t0xb0785fc4, 0xd512e4c6, 0xbbb7d699, 0x5a86591b, 0x10cf5376, 0x12bf9f4b,\n\t0x980fbaa1, 0x992a4e70, 0x20fa7ae7, 0xf7996ebb, 0xc918a2be, 0x82de74f2,\n\t0xad54209b, 0xf66b4d74, 0x1fc5b771, 0x169d9229, 0x887761df, 0x00b667d5,\n\t0xdb425e59, 0xb72f2844, 0x9b0ac1f5, 0x9c737e3a, 0x2b85476c, 0x6722add6,\n\t0x44a63297, 0x0d688ced, 0xabc59484, 0x4107778a, 0x8ad94c6f, 0xfe83df90,\n\t0x0f64053f, 0xd1292e9d, 0xc5744356, 0x8dd1abb4, 0x4c4e7667, 0xfb4a7fc1,\n\t0x74f402cb, 0x70f06afd, 0xa82286f2, 0x918dd076, 0x7a97c5ce, 0x48f7bde3,\n\t0x6a04d11d, 0xac243ef7, 0x33ac10ca, 0x2f7a341e, 0x5f75157a, 0xf4773381,\n\t0x591c870e, 0x78df8cc8, 0x22f3adb0, 0x251a5993, 0x09fbef66, 0x796942a8,\n\t0x97541d2e, 0x2373daa9, 0x1bd2f142, 0xb57e8eb2, 0xe1a5bfdb, 0x7d0efa92,\n\t0xb3442c94, 0xd2cb6447, 0x386ac97e, 0x66d61805, 0xbdada15e, 0x11bc1aa7,\n\t0x14e9f6ea, 0xe533a0c0, 0xf935ee0a, 0x8fee8a04, 0x810d6d85, 0x7c68b6d6,\n\t0x4edc9aa2, 0x956e897d, 0xed87581a, 0x264be9d7, 0xff4ddb29, 0x823857c2,\n\t0xe005a9a0, 0xf1cc2450, 0x6f9951e1, 0xaade2310, 0xe70c75f5, 0x83e1a31f,\n\t0x4f7dde8e, 0xf723b563, 0x368e0928, 0x86362b71, 0x21e8982d, 0xdfb3f92b,\n\t0x44676352, 0x99efba31, 0x2eab4e1c, 0xfc6ca5e7, 0x0ebe5d4e, 0xa0717d0c,\n\t0xb64f8199, 0x946b31a1, 0x5656cbc6, 0xcffec3ef, 0x622766c9, 0xfa211e35,\n\t0x52f98b89, 0x6d01674b, 0x4978a802, 0xf651f701, 0x15b0d43d, 0xd6ff4683,\n\t0x3463855f, 0x672ba29c, 0xbc128312, 0x4626a70d, 0xc8927a5a, 0xb8481cf9,\n\t0x1c962262, 0xa21196ba, 0xbaba5ee9, 0x5bb162d0, 0x69943bd1, 0x0c47e35c,\n\t0x8cc9619a, 0xe284d948, 0x271bf264, 0xc27fb398, 0x4bc70897, 0x60cf202c,\n\t0x7f42d6aa, 0xa5a13506, 0x5d3e8860, 0xcea63d3c, 0x63bf0a8f, 0xf02e9efa,\n\t0xb17b0674, 0xb072b1d3, 0x06e5723b, 0x3737e436, 0x24aa49c7, 0x0ded0d18,\n\t0xdb256b14, 0x58b27877, 0xecb49f54, 0x6c40256a, 0x6ea92ffb, 0x3906aa4c,\n\t0xc9866fd5, 0x4549323e, 0xa7b85fab, 0x1918cc27, 0x7308d7b5, 0x1e16c7ad,\n\t0x71850b37, 0x3095fd78, 0xa63b70e6, 0xd880e2ae, 0x3e282769, 0xa39ba6bc,\n\t0x98700fa3, 0xf34c53e8, 0x288af426, 0xb99d930f, 0xf5b99df1, 0xe9d0c8cf,\n\t0x5ac8405d, 0x50e7217b, 0x511fbbbe, 0x2ca2e639, 0xc020301b, 0x356dbc00,\n\t0x8e43ddb9, 0x4d327b4a, 0xf20ff3ed, 0x1dbb29bd, 0x43d44779, 0xa1b68f70,\n\t0x6114455b, 0xe63d280b, 0x6bf6ff65, 0x10fc39e5, 0x3dae126e, 0xc1d7cf11,\n\t0xcb60b795, 0x1789d5b3, 0x9bca36b7, 0x08306075, 0x84615608, 0x8b3a0186,\n\t0xe88fbecd, 0x7ba47c4d, 0x2de44dac, 0x653fe58d, 0xcca0b968, 0xd7fa0e72,\n\t0x93901780, 0x1f2c26cc, 0xae595b6b, 0xa9ecea9b, 0xe3dbf8c4, 0x319cc130,\n\t0x12981196, 0x01a3a4de, 0x32c454b6, 0x755bd817, 0x3cd871e4, 0xa48bb8da,\n\t0x02fdec09, 0xfd2dc2e2, 0x9e578088, 0x9a9f916d, 0x4065fe6c, 0x1853999e,\n\t0xc7793f23, 0xdc1016bb, 0x969355ff, 0x7ef292f6, 0xcdce4adc, 0x05e24416,\n\t0x85c16c46, 0xd441d37f, 0x57bd6855, 0x8746f54f, 0x9ca773df, 0x770bae22,\n\t0x54828413, 0xb75e4b19, 0x04c35c03, 0xbf7cca07, 0x2955c4dd, 0x721db041,\n\t0xb2394f33, 0x03f51387, 0x89b73c9f, 0x0b1737f3, 0x07e69024, 0x9231d245,\n\t0x76193861, 0x88159c15, 0xdeb552d9, 0xd9767e40, 0x20c6c0c3, 0x4281977c,\n\t0xf8afe1e0, 0xd32a0751, 0x3fc27432, 0xddf1dcc5, 0x68581f34, 0x3bcd5025,\n\t0x0091b2ee, 0x4aeb6944, 0x1602e743, 0xea09eb58, 0xef0a2a8b, 0x641e03a5,\n\t0xeb50e021, 0x5c8ccef8, 0x802ff0b8, 0xd5e3edfe, 0xc4dd1b49, 0x5334cd2a,\n\t0x13f82d2f, 0x47450c20, 0x55dafbd2, 0xbec0c6f4, 0xb45d7959, 0x3ad36e8c,\n\t0x0aa8ac57, 0x1a3c8d73, 0xe45aafb1, 0x9f664838, 0xc6880053, 0xd0039bbf,\n\t0xee5f19eb, 0xca0041d8, 0xbbea3aaf, 0xda628291, 0x9d5c95d4, 0xadd504a6,\n\t0xc39ab482, 0x5e9e14a4, 0x2be065f0, 0x2a13fc3a, 0x9052e8ec, 0xaf6f5afc,\n\t0x519aa8b5, 0xbb303da9, 0xe00e2b10, 0xdfa6c1db, 0x2e6b952e, 0xee10dc23,\n\t0x37936d09, 0x1fc42e92, 0x39b25a9f, 0x13ff89f4, 0xc8f53fea, 0x18500bc7,\n\t0x95a0379d, 0x98f751c2, 0x2289c42f, 0xa21e4098, 0x6f391f41, 0xf27e7e58,\n\t0x0d0df887, 0x4b79d540, 0x8e8409aa, 0x71fe46f8, 0x688a9b29, 0x3f08b548,\n\t0x84abe03a, 0x5e91b6c1, 0xfde4c2ae, 0x251d0e72, 0x92d4fee5, 0xf9371967,\n\t0x9175108f, 0xe6e81835, 0x8c8cb8ee, 0xb55a67b3, 0xcef138cc, 0x8b256268,\n\t0x00d815f5, 0xe8810812, 0x77826189, 0xea73267d, 0x19b90f8d, 0x45c33bb4,\n\t0x82477056, 0xe1770075, 0x09467aa6, 0xa7c6f54a, 0x79768742, 0x61b86bca,\n\t0xd6644a44, 0xe33f0171, 0xc229fbcd, 0x41b08feb, 0xd1903e30, 0x65ec9080,\n\t0x563d6fbd, 0xf56da488, 0xebf64cd8, 0x4934426b, 0x7c8592fc, 0x6aca8cf2,\n\t0x1cea111b, 0x3a57ee7a, 0xace11c0d, 0x9942d85e, 0xc4613407, 0xfa8e643b,\n\t0x327fc701, 0x4ca9be82, 0x3352526d, 0x2c047f63, 0xf3a8f7dd, 0x1a4a98a8,\n\t0x762ed4d1, 0x27c75008, 0xbdf497c0, 0x7a7b84df, 0x315c28ab, 0x801f93e3,\n\t0xf19b0ca1, 0x8f14e46a, 0xe48ba333, 0x9605e625, 0xf03ecb60, 0x60385f2d,\n\t0x902845ba, 0x7f96d66f, 0x24bff05c, 0x2820730b, 0x947133cb, 0xd444828a,\n\t0xb343f6f1, 0x0bef4705, 0x8da574f9, 0x01e25d6c, 0x1732793e, 0x4f0f7b27,\n\t0x364b7117, 0xb2d1da77, 0xa6c5f1e9, 0x574ca5b1, 0x386a3076, 0xad6894d6,\n\t0x1156d7fa, 0xa48d1d9a, 0x4794c0af, 0x150c0aa0, 0x26d348ac, 0x29fdeabe,\n\t0xa5dede53, 0x81671e8e, 0x594ee3bf, 0xa96c56e6, 0x3426a726, 0xc5976579,\n\t0xbc22e5e4, 0xc1006319, 0xdaafdd2a, 0xa1a1aa83, 0x3badd0e7, 0xc3b14981,\n\t0xd770b155, 0xccd7c693, 0x42e944c5, 0x03e0064f, 0xca95b4ef, 0x3dee81c3,\n\t0xfbbcd98c, 0x1e07e15b, 0x667ce949, 0xe7d6773f, 0x21b6124b, 0x6b2a6ef7,\n\t0xd3278a9c, 0x9a988304, 0x75d2ae9b, 0xfe49e2ff, 0x9bc24f46, 0x74cc2cf6,\n\t0xa3139f36, 0x6c9ef35a, 0x9fc1dffe, 0x9e5facdc, 0xaadc8bbb, 0x5abdbc5f,\n\t0x44b3b390, 0xf754efa7, 0x5fe3bdb7, 0x4e59c886, 0x06a4c984, 0xa0338878,\n\t0xcd513cd7, 0x63ebd27e, 0x8aba80ad, 0x50da144e, 0x5d9f4e97, 0x025b751c,\n\t0x2d580200, 0xb6c05837, 0x580aa15d, 0x54022a6e, 0xb41a5415, 0x4863fab6,\n\t0xb0b79957, 0x46d0d159, 0xdc2b8650, 0x20a7bb0c, 0x4a032974, 0xec8636a2,\n\t0x8548f24c, 0xf6a2bf16, 0x1088f4b0, 0x0c2f3a94, 0x525dc396, 0x14065785,\n\t0x2b4dca52, 0x08aeed39, 0xabedfc99, 0xb1dbcf18, 0x87f85bbc, 0xae3aff61,\n\t0x433ccd70, 0x5b23cc64, 0x7b453213, 0x5355c545, 0x9318ec0a, 0x78692d31,\n\t0x0a21693d, 0xd5666814, 0x05fb59d9, 0xc71985b2, 0x2abb8e0e, 0xcf6e6c91,\n\t0xd9cfe7c6, 0xefe7132c, 0x9711ab28, 0x3ce52732, 0x12d516d2, 0x7209a0d0,\n\t0xd278d306, 0x70fa4b7b, 0x1d407dd3, 0xdb0beba4, 0xbfd97621, 0xa8be21e1,\n\t0x1b6f1b66, 0x30650dda, 0xba7ddbb9, 0x7df953fb, 0x9d1c3902, 0xedf0e8d5,\n\t0xb8741ae0, 0x0f240565, 0x62cd438b, 0xc616a924, 0xaf7a96a3, 0x35365538,\n\t0xe583af4d, 0x73415eb8, 0x23176a47, 0xfc9ccee8, 0x7efc9de2, 0x695e03cf,\n\t0xf8ce66d4, 0x88b4781d, 0x67dd9c03, 0x3e8f9e73, 0xc0c95c51, 0xbe314d22,\n\t0x55aa0795, 0xcb1bb011, 0xe980fdc8, 0x9c62b7ce, 0xde2d239e, 0x042cadf3,\n\t0xffdf04de, 0x5ce6a60f, 0xd8c831ed, 0xb7b5b9ec, 0xb9cbf962, 0xe253b254,\n\t0x0735ba1f, 0x16ac917f, 0xdd607c2b, 0x64a335c4, 0x40159a7c, 0x869222f0,\n\t0x6ef21769, 0x839d20a5, 0xd03b24c9, 0xf412601e, 0x6d72a243, 0x0e018dfd,\n\t0x89f3721a, 0xc94f4134, 0x2f992f20, 0x4d87253c\n};\n\n/**\n * Initialize algorithm context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_snefru128_init(struct snefru_ctx* ctx)\n{\n\tmemset(ctx, 0, sizeof(snefru_ctx));\n\tctx->digest_length = snefru128_hash_length;\n}\n\n/**\n * Initialize algorithm context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_snefru256_init(struct snefru_ctx* ctx)\n{\n\tmemset(ctx, 0, sizeof(snefru_ctx));\n\tctx->digest_length = snefru256_hash_length;\n}\n\n/**\n * Core transformation, processes given 256-bit or 384-bit block.\n * The algoririthm is optimized for Intel Pentum.\n *\n * @param ctx algorithm context\n * @param block the message block to process\n */\nstatic void rhash_snefru_process_block(snefru_ctx* ctx, unsigned* block)\n{\n\tunsigned W[16];\n\tunsigned rot;\n\n\tconst unsigned* sbox;\n\tconst unsigned* const sbox_end = rhash_snefru_sbox + 512 * SNEFRU_NUMBER_OF_ROUNDS;\n\tunsigned* const hash = ctx->hash;\n\n\t{\n\t\t/* fill W[] array */\n\t\tW[0] = ctx->hash[0], W[1] = ctx->hash[1];\n\t\tW[2] = ctx->hash[2], W[3] = ctx->hash[3];\n\n\t\tif (ctx->digest_length == snefru256_hash_length) {\n\t\t\tW[4] = ctx->hash[4], W[5] = ctx->hash[5];\n\t\t\tW[6] = ctx->hash[6], W[7] = ctx->hash[7];\n\t\t} else {\n\t\t\tW[4] = be2me_32(block[0]), W[5] = be2me_32(block[1]);\n\t\t\tW[6] = be2me_32(block[2]), W[7] = be2me_32(block[3]);\n\t\t\tblock += 4;\n\t\t}\n\n\t\tW[ 8] = be2me_32(block[0]), W[ 9] = be2me_32(block[1]);\n\t\tW[10] = be2me_32(block[2]), W[11] = be2me_32(block[3]);\n\t\tW[12] = be2me_32(block[4]), W[13] = be2me_32(block[5]);\n\t\tW[14] = be2me_32(block[6]), W[15] = be2me_32(block[7]);\n\t}\n\n\t/* do algorithm rounds using S-Box */\n\tfor (sbox = rhash_snefru_sbox; sbox < sbox_end; sbox += 512)\n\t{\n\t\t/* cycle 4 times */\n\t\tfor (rot = 0x18100810; rot; rot >>= 8)\n\t\t{\n\t\t\tunsigned x;\n\n#define SNEFERU_UPDATE_W(i) \\\n\tx = sbox[(i << 7 & 0x100) + (W[i] & 0xff)]; \\\n\tW[(i - 1) & 0x0f] ^= x; \\\n\tif (i >= 2) W[(i - 1) & 0x0f] = \\\n\tROTR32(W[(i - 1) & 0x0f], (unsigned char)rot); \\\n\tW[(i + 1) & 0x0f] ^= x;\n\n\t\t\tSNEFERU_UPDATE_W(0);\n\t\t\tSNEFERU_UPDATE_W(1);\n\t\t\tSNEFERU_UPDATE_W(2);\n\t\t\tSNEFERU_UPDATE_W(3);\n\t\t\tSNEFERU_UPDATE_W(4);\n\t\t\tSNEFERU_UPDATE_W(5);\n\t\t\tSNEFERU_UPDATE_W(6);\n\t\t\tSNEFERU_UPDATE_W(7);\n\t\t\tSNEFERU_UPDATE_W(8);\n\t\t\tSNEFERU_UPDATE_W(9);\n\t\t\tSNEFERU_UPDATE_W(10);\n\t\t\tSNEFERU_UPDATE_W(11);\n\t\t\tSNEFERU_UPDATE_W(12);\n\t\t\tSNEFERU_UPDATE_W(13);\n\t\t\tSNEFERU_UPDATE_W(14);\n\t\t\tSNEFERU_UPDATE_W(15);\n\t\t\tW[( 0) & 0x0f] = ROTR32(W[( 0) & 0x0f], (unsigned char)rot);\n\t\t\tW[(15) & 0x0f] = ROTR32(W[(15) & 0x0f], (unsigned char)rot);\n\t\t}\n\t}\n\n\t/* store current hashing state */\n\thash[0] ^= W[15];\n\thash[1] ^= W[14];\n\thash[2] ^= W[13];\n\thash[3] ^= W[12];\n\tif (ctx->digest_length == snefru256_hash_length) {\n\t\thash[4] ^= W[11];\n\t\thash[5] ^= W[10];\n\t\thash[6] ^= W[ 9];\n\t\thash[7] ^= W[ 8];\n\t}\n}\n\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_snefru_update(snefru_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tconst unsigned data_block_size = 64 - ctx->digest_length;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (ctx->index) {\n\t\tunsigned left = data_block_size - ctx->index;\n\t\tmemcpy((char*)ctx->buffer + ctx->index, msg, (size < left ? size : left));\n\t\tif (size < left) {\n\t\t\tctx->index += (unsigned)size;\n\t\t\treturn;\n\t\t}\n\n\t\t/* process partial block */\n\t\trhash_snefru_process_block(ctx, (unsigned*)ctx->buffer);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= data_block_size) {\n\t\tunsigned* aligned_message_block;\n\n\t\tif (IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg)) {\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\ton a little-endian CPU without copying it */\n\t\t\taligned_message_block = (unsigned*)msg;\n\t\t} else {\n\t\t\tmemcpy(ctx->buffer, msg, data_block_size);\n\t\t\taligned_message_block = (unsigned*)ctx->buffer;\n\t\t}\n\t\trhash_snefru_process_block(ctx, aligned_message_block);\n\n\t\tmsg  += data_block_size;\n\t\tsize -= data_block_size;\n\t}\n\n\tctx->index = (unsigned)size;\n\tif (size) {\n\t\t/* save leftovers */\n\t\tmemcpy(ctx->buffer, msg, size);\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n * Finalize the hash value calculation by appending the (padded) length field.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_snefru_final(snefru_ctx* ctx, unsigned char* result)\n{\n\tconst unsigned digest_dw_len = ctx->digest_length / 4; /* length in dwords */\n\tconst unsigned data_block_size = 64 - ctx->digest_length;\n\n\tassert(ctx->index == (unsigned)(ctx->length % data_block_size));\n\tif (ctx->index) {\n\t\t/* pad the last data block if partially filled */\n\t\tmemset((char*)ctx->buffer + ctx->index, 0, data_block_size - ctx->index);\n\t\trhash_snefru_process_block(ctx, (unsigned*)ctx->buffer);\n\t}\n\n\tmemset(ctx->buffer, 0, data_block_size - 8);\n\t((unsigned*)ctx->buffer)[14 - digest_dw_len] = be2me_32((unsigned)(ctx->length >> 29));\n\t((unsigned*)ctx->buffer)[15 - digest_dw_len] = be2me_32((unsigned)(ctx->length << 3));\n\trhash_snefru_process_block(ctx, (unsigned*)ctx->buffer);\n\n\tbe32_copy(result, 0, ctx->hash, ctx->digest_length);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/snefru.h",
    "content": "﻿/* snefru.h */\n#ifndef SNEFRU_H\n#define SNEFRU_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Snefru-128 processses message by blocks of 48 bytes, */\n/* and Snefru-256 uses blocks of 32 bytes */\n\n/* here we declare the maximal block size */\n#define snefru_block_size 48\n\n#define snefru128_hash_length 16\n#define snefru256_hash_length 32\n\n/* algorithm context */\ntypedef struct snefru_ctx\n{\n\tunsigned hash[8];         /* algorithm 512-bit hashing state */\n\tunsigned char buffer[48]; /* 384-bit message block */\n\tuint64_t length;          /* processed message length */\n\tunsigned index;           /* index in the buffer of the last byte stored */\n\tunsigned digest_length;   /* length of the algorithm digest in bytes */\n} snefru_ctx;\n\n/* hash functions */\n\nvoid rhash_snefru128_init(snefru_ctx* ctx);\nvoid rhash_snefru256_init(snefru_ctx* ctx);\nvoid rhash_snefru_update(snefru_ctx* ctx, const unsigned char* data, size_t size);\nvoid rhash_snefru_final(snefru_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* SNEFRU_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/tiger.c",
    "content": "﻿/* tiger.c - an implementation of Tiger Hash Function\n * based on the article by\n * Ross Anderson and Eli Biham \"Tiger: A Fast New Hash Function\".\n *\n * Copyright (c) 2007, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include <string.h>\n#include \"byte_order.h\"\n#include \"tiger.h\"\n\n#ifdef NO_TIGER2\n# define TIGER2_FLAG I64(0)\n#else\n# define TIGER2_FLAG I64(0x8000000000000000)\n#endif /* NO_TIGER2 */\n\n#define LENGTH_MASK (~TIGER2_FLAG)\n#define INITIALIZE_TIGER_STATE(state) \\\n\tstate[0] = I64(0x0123456789ABCDEF); \\\n\tstate[1] = I64(0xFEDCBA9876543210); \\\n\tstate[2] = I64(0xF096A5B4C3B2E187);\n\n/**\n * Initialize Tiger context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_tiger_init(tiger_ctx* ctx)\n{\n\tctx->length = 0;\n\tINITIALIZE_TIGER_STATE(ctx->hash);\n}\n\n#ifndef NO_TIGER2\n/**\n * Initialize Tiger2 context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_tiger2_init(tiger_ctx* ctx)\n{\n\tctx->length = TIGER2_FLAG;\n\tINITIALIZE_TIGER_STATE(ctx->hash);\n}\n#endif /* NO_TIGER2 */\n\n/* lookup tables */\nextern uint64_t rhash_tiger_sboxes[4][256];\n#define t1 rhash_tiger_sboxes[0]\n#define t2 rhash_tiger_sboxes[1]\n#define t3 rhash_tiger_sboxes[2]\n#define t4 rhash_tiger_sboxes[3]\n\n#ifdef CPU_X64 /* for x86-64 */\n#define round(a,b,c,x,mul) \\\n\tc ^= x; \\\n\ta -= t1[(uint8_t)(c)] ^ \\\n\t\tt2[(uint8_t)((c) >> (2 * 8))] ^ \\\n\t\tt3[(uint8_t)((c) >> (4 * 8))] ^ \\\n\t\tt4[(uint8_t)((c) >> (6 * 8))] ; \\\n\tb += t4[(uint8_t)((c) >> (1 * 8))] ^ \\\n\t\tt3[(uint8_t)((c) >> (3 * 8))] ^ \\\n\t\tt2[(uint8_t)((c) >> (5 * 8))] ^ \\\n\t\tt1[(uint8_t)((c) >> (7 * 8))]; \\\n\tb *= mul;\n\n#else /* for IA32 */\n\n#define round(a,b,c,x,mul) \\\n\tc ^= x; \\\n\ta -= t1[(uint8_t)(c)] ^ \\\n\t\tt2[(uint8_t)(((uint32_t)(c)) >> (2 * 8))] ^ \\\n\t\tt3[(uint8_t)((c) >> (4 * 8))] ^ \\\n\t\tt4[(uint8_t)(((uint32_t)((c) >> (4 * 8))) >> (2 * 8))] ; \\\n\tb += t4[(uint8_t)(((uint32_t)(c)) >> (1 * 8))] ^ \\\n\t\tt3[(uint8_t)(((uint32_t)(c)) >> (3 * 8))] ^ \\\n\t\tt2[(uint8_t)(((uint32_t)((c) >> (4 * 8))) >> (1 * 8))] ^ \\\n\t\tt1[(uint8_t)(((uint32_t)((c) >> (4 * 8))) >> (3 * 8))]; \\\n\tb *= mul;\n#endif /* CPU_X64 */\n\n#define pass(a,b,c,mul) \\\n\tround(a,b,c,x0,mul) \\\n\tround(b,c,a,x1,mul) \\\n\tround(c,a,b,x2,mul) \\\n\tround(a,b,c,x3,mul) \\\n\tround(b,c,a,x4,mul) \\\n\tround(c,a,b,x5,mul) \\\n\tround(a,b,c,x6,mul) \\\n\tround(b,c,a,x7,mul)\n\n#define key_schedule { \\\n\tx0 -= x7 ^ I64(0xA5A5A5A5A5A5A5A5); \\\n\tx1 ^= x0; \\\n\tx2 += x1; \\\n\tx3 -= x2 ^ ((~x1)<<19); \\\n\tx4 ^= x3; \\\n\tx5 += x4; \\\n\tx6 -= x5 ^ ((~x4)>>23); \\\n\tx7 ^= x6; \\\n\tx0 += x7; \\\n\tx1 -= x0 ^ ((~x7)<<19); \\\n\tx2 ^= x1; \\\n\tx3 += x2; \\\n\tx4 -= x3 ^ ((~x2)>>23); \\\n\tx5 ^= x4; \\\n\tx6 += x5; \\\n\tx7 -= x6 ^ I64(0x0123456789ABCDEF); \\\n}\n\n/**\n * The core transformation. Process a 512-bit block.\n *\n * @param state the algorithm state\n * @param block the message block to process\n */\nstatic void rhash_tiger_process_block(uint64_t state[3], uint64_t* block)\n{\n\t/* Optimized for GCC IA32.\n\t   The order of declarations is important for compiler. */\n\tuint64_t a, b, c;\n\tuint64_t x0, x1, x2, x3, x4, x5, x6, x7;\n#ifndef CPU_X64\n\tuint64_t tmp;\n\tchar i;\n#endif\n\n\tx0 = le2me_64(block[0]); x1 = le2me_64(block[1]);\n\tx2 = le2me_64(block[2]); x3 = le2me_64(block[3]);\n\tx4 = le2me_64(block[4]); x5 = le2me_64(block[5]);\n\tx6 = le2me_64(block[6]); x7 = le2me_64(block[7]);\n\n\ta = state[0];\n\tb = state[1];\n\tc = state[2];\n\n\t/* passes and key shedules */\n#ifndef CPU_X64\n\tfor (i = 0; i < 3; i++) {\n\t\tif (i != 0) key_schedule;\n\t\tpass(a, b, c, (i == 0 ? 5 : i == 1 ? 7 : 9));\n\t\ttmp = a;\n\t\ta = c;\n\t\tc = b;\n\t\tb = tmp;\n\t}\n#else\n\tpass(a, b, c, 5);\n\tkey_schedule;\n\tpass(c, a, b, 7);\n\tkey_schedule;\n\tpass(b, c, a, 9);\n#endif\n\n\t/* feedforward operation */\n\tstate[0] = a ^ state[0];\n\tstate[1] = b - state[1];\n\tstate[2] = c + state[2];\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_tiger_update(tiger_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tsize_t index = (size_t)ctx->length & 63;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tsize_t left = tiger_block_size - index;\n\t\tif (size < left) {\n\t\t\tif (size > 0)\n\t\t\t\tmemcpy(ctx->message + index, msg, size);\n\t\t\treturn;\n\t\t} else {\n\t\t\tmemcpy(ctx->message + index, msg, left);\n\t\t\trhash_tiger_process_block(ctx->hash, (uint64_t*)ctx->message);\n\t\t\tmsg += left;\n\t\t\tsize -= left;\n\t\t}\n\t}\n\twhile (size >= tiger_block_size) {\n\t\tif (IS_ALIGNED_64(msg)) {\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\twithout copying it */\n\t\t\trhash_tiger_process_block(ctx->hash, (uint64_t*)msg);\n\t\t} else {\n\t\t\tmemcpy(ctx->message, msg, tiger_block_size);\n\t\t\trhash_tiger_process_block(ctx->hash, (uint64_t*)ctx->message);\n\t\t}\n\n\t\tmsg += tiger_block_size;\n\t\tsize -= tiger_block_size;\n\t}\n\tif (size) {\n\t\t/* save leftovers */\n\t\tmemcpy(ctx->message, msg, size);\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_tiger_final(tiger_ctx* ctx, unsigned char result[24])\n{\n\tunsigned index = (unsigned)ctx->length & 63;\n\tuint64_t* msg64 = (uint64_t*)ctx->message;\n\n\t/* pad message and run for last block */\n\n\t/* append the byte 0x01 to the message */\n\tctx->message[index++] = (ctx->length & TIGER2_FLAG ? 0x80 : 0x01);\n\n\t/* if no room left in the message to store 64-bit message length */\n\tif (index > 56) {\n\t\t/* then fill the rest with zeros and process it */\n\t\twhile (index < 64) {\n\t\t\tctx->message[index++] = 0;\n\t\t}\n\t\trhash_tiger_process_block(ctx->hash, msg64);\n\t\tindex = 0;\n\t}\n\twhile (index < 56) {\n\t\tctx->message[index++] = 0;\n\t}\n\tmsg64[7] = le2me_64((ctx->length & LENGTH_MASK) << 3);\n\trhash_tiger_process_block(ctx->hash, msg64);\n\n\t/* save result hash */\n\tle64_copy(result, 0, &ctx->hash, 24);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/tiger.h",
    "content": "﻿/* tiger.h */\n#ifndef TIGER_H\n#define TIGER_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define tiger_block_size 64\n#define tiger_hash_length 24\n\n/* algorithm context */\ntypedef struct tiger_ctx\n{\n\t/* the order of the fields slightly influence the algorithm speed */\n\tuint64_t hash[3]; /* algorithm 192-bit state */\n\tunsigned char message[tiger_block_size]; /* 512-bit buffer for leftovers */\n\tuint64_t length;  /* processed message length */\n} tiger_ctx;\n\n/* hash functions */\n\n#ifndef NO_TIGER2\nvoid rhash_tiger2_init(tiger_ctx* ctx);\n#endif /* NO_TIGER2 */\n\nvoid rhash_tiger_init(tiger_ctx* ctx);\nvoid rhash_tiger_update(tiger_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_tiger_final(tiger_ctx* ctx, unsigned char result[24]);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* TIGER_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/tiger_sbox.c",
    "content": "﻿/* tiger_sbox.c - S-Box for Tiger hash function\n *\n * Copyright (c) 2007, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n#include \"byte_order.h\"\n\n/* Four S-boxes used for table lookups by Tiger hash function. 8Kb in total. */\nuint64_t rhash_tiger_sboxes[4][256] = {\n\t{\n\t\tI64(0x02AAB17CF7E90C5E),  I64(0xAC424B03E243A8EC),\n\t\tI64(0x72CD5BE30DD5FCD3),  I64(0x6D019B93F6F97F3A),\n\t\tI64(0xCD9978FFD21F9193),  I64(0x7573A1C9708029E2),\n\t\tI64(0xB164326B922A83C3),  I64(0x46883EEE04915870),\n\t\tI64(0xEAACE3057103ECE6),  I64(0xC54169B808A3535C),\n\t\tI64(0x4CE754918DDEC47C),  I64(0x0AA2F4DFDC0DF40C),\n\t\tI64(0x10B76F18A74DBEFA),  I64(0xC6CCB6235AD1AB6A),\n\t\tI64(0x13726121572FE2FF),  I64(0x1A488C6F199D921E),\n\t\tI64(0x4BC9F9F4DA0007CA),  I64(0x26F5E6F6E85241C7),\n\t\tI64(0x859079DBEA5947B6),  I64(0x4F1885C5C99E8C92),\n\t\tI64(0xD78E761EA96F864B),  I64(0x8E36428C52B5C17D),\n\t\tI64(0x69CF6827373063C1),  I64(0xB607C93D9BB4C56E),\n\t\tI64(0x7D820E760E76B5EA),  I64(0x645C9CC6F07FDC42),\n\t\tI64(0xBF38A078243342E0),  I64(0x5F6B343C9D2E7D04),\n\t\tI64(0xF2C28AEB600B0EC6),  I64(0x6C0ED85F7254BCAC),\n\t\tI64(0x71592281A4DB4FE5),  I64(0x1967FA69CE0FED9F),\n\t\tI64(0xFD5293F8B96545DB),  I64(0xC879E9D7F2A7600B),\n\t\tI64(0x860248920193194E),  I64(0xA4F9533B2D9CC0B3),\n\t\tI64(0x9053836C15957613),  I64(0xDB6DCF8AFC357BF1),\n\t\tI64(0x18BEEA7A7A370F57),  I64(0x037117CA50B99066),\n\t\tI64(0x6AB30A9774424A35),  I64(0xF4E92F02E325249B),\n\t\tI64(0x7739DB07061CCAE1),  I64(0xD8F3B49CECA42A05),\n\t\tI64(0xBD56BE3F51382F73),  I64(0x45FAED5843B0BB28),\n\t\tI64(0x1C813D5C11BF1F83),  I64(0x8AF0E4B6D75FA169),\n\t\tI64(0x33EE18A487AD9999),  I64(0x3C26E8EAB1C94410),\n\t\tI64(0xB510102BC0A822F9),  I64(0x141EEF310CE6123B),\n\t\tI64(0xFC65B90059DDB154),  I64(0xE0158640C5E0E607),\n\t\tI64(0x884E079826C3A3CF),  I64(0x930D0D9523C535FD),\n\t\tI64(0x35638D754E9A2B00),  I64(0x4085FCCF40469DD5),\n\t\tI64(0xC4B17AD28BE23A4C),  I64(0xCAB2F0FC6A3E6A2E),\n\t\tI64(0x2860971A6B943FCD),  I64(0x3DDE6EE212E30446),\n\t\tI64(0x6222F32AE01765AE),  I64(0x5D550BB5478308FE),\n\t\tI64(0xA9EFA98DA0EDA22A),  I64(0xC351A71686C40DA7),\n\t\tI64(0x1105586D9C867C84),  I64(0xDCFFEE85FDA22853),\n\t\tI64(0xCCFBD0262C5EEF76),  I64(0xBAF294CB8990D201),\n\t\tI64(0xE69464F52AFAD975),  I64(0x94B013AFDF133E14),\n\t\tI64(0x06A7D1A32823C958),  I64(0x6F95FE5130F61119),\n\t\tI64(0xD92AB34E462C06C0),  I64(0xED7BDE33887C71D2),\n\t\tI64(0x79746D6E6518393E),  I64(0x5BA419385D713329),\n\t\tI64(0x7C1BA6B948A97564),  I64(0x31987C197BFDAC67),\n\t\tI64(0xDE6C23C44B053D02),  I64(0x581C49FED002D64D),\n\t\tI64(0xDD474D6338261571),  I64(0xAA4546C3E473D062),\n\t\tI64(0x928FCE349455F860),  I64(0x48161BBACAAB94D9),\n\t\tI64(0x63912430770E6F68),  I64(0x6EC8A5E602C6641C),\n\t\tI64(0x87282515337DDD2B),  I64(0x2CDA6B42034B701B),\n\t\tI64(0xB03D37C181CB096D),  I64(0xE108438266C71C6F),\n\t\tI64(0x2B3180C7EB51B255),  I64(0xDF92B82F96C08BBC),\n\t\tI64(0x5C68C8C0A632F3BA),  I64(0x5504CC861C3D0556),\n\t\tI64(0xABBFA4E55FB26B8F),  I64(0x41848B0AB3BACEB4),\n\t\tI64(0xB334A273AA445D32),  I64(0xBCA696F0A85AD881),\n\t\tI64(0x24F6EC65B528D56C),  I64(0x0CE1512E90F4524A),\n\t\tI64(0x4E9DD79D5506D35A),  I64(0x258905FAC6CE9779),\n\t\tI64(0x2019295B3E109B33),  I64(0xF8A9478B73A054CC),\n\t\tI64(0x2924F2F934417EB0),  I64(0x3993357D536D1BC4),\n\t\tI64(0x38A81AC21DB6FF8B),  I64(0x47C4FBF17D6016BF),\n\t\tI64(0x1E0FAADD7667E3F5),  I64(0x7ABCFF62938BEB96),\n\t\tI64(0xA78DAD948FC179C9),  I64(0x8F1F98B72911E50D),\n\t\tI64(0x61E48EAE27121A91),  I64(0x4D62F7AD31859808),\n\t\tI64(0xECEBA345EF5CEAEB),  I64(0xF5CEB25EBC9684CE),\n\t\tI64(0xF633E20CB7F76221),  I64(0xA32CDF06AB8293E4),\n\t\tI64(0x985A202CA5EE2CA4),  I64(0xCF0B8447CC8A8FB1),\n\t\tI64(0x9F765244979859A3),  I64(0xA8D516B1A1240017),\n\t\tI64(0x0BD7BA3EBB5DC726),  I64(0xE54BCA55B86ADB39),\n\t\tI64(0x1D7A3AFD6C478063),  I64(0x519EC608E7669EDD),\n\t\tI64(0x0E5715A2D149AA23),  I64(0x177D4571848FF194),\n\t\tI64(0xEEB55F3241014C22),  I64(0x0F5E5CA13A6E2EC2),\n\t\tI64(0x8029927B75F5C361),  I64(0xAD139FABC3D6E436),\n\t\tI64(0x0D5DF1A94CCF402F),  I64(0x3E8BD948BEA5DFC8),\n\t\tI64(0xA5A0D357BD3FF77E),  I64(0xA2D12E251F74F645),\n\t\tI64(0x66FD9E525E81A082),  I64(0x2E0C90CE7F687A49),\n\t\tI64(0xC2E8BCBEBA973BC5),  I64(0x000001BCE509745F),\n\t\tI64(0x423777BBE6DAB3D6),  I64(0xD1661C7EAEF06EB5),\n\t\tI64(0xA1781F354DAACFD8),  I64(0x2D11284A2B16AFFC),\n\t\tI64(0xF1FC4F67FA891D1F),  I64(0x73ECC25DCB920ADA),\n\t\tI64(0xAE610C22C2A12651),  I64(0x96E0A810D356B78A),\n\t\tI64(0x5A9A381F2FE7870F),  I64(0xD5AD62EDE94E5530),\n\t\tI64(0xD225E5E8368D1427),  I64(0x65977B70C7AF4631),\n\t\tI64(0x99F889B2DE39D74F),  I64(0x233F30BF54E1D143),\n\t\tI64(0x9A9675D3D9A63C97),  I64(0x5470554FF334F9A8),\n\t\tI64(0x166ACB744A4F5688),  I64(0x70C74CAAB2E4AEAD),\n\t\tI64(0xF0D091646F294D12),  I64(0x57B82A89684031D1),\n\t\tI64(0xEFD95A5A61BE0B6B),  I64(0x2FBD12E969F2F29A),\n\t\tI64(0x9BD37013FEFF9FE8),  I64(0x3F9B0404D6085A06),\n\t\tI64(0x4940C1F3166CFE15),  I64(0x09542C4DCDF3DEFB),\n\t\tI64(0xB4C5218385CD5CE3),  I64(0xC935B7DC4462A641),\n\t\tI64(0x3417F8A68ED3B63F),  I64(0xB80959295B215B40),\n\t\tI64(0xF99CDAEF3B8C8572),  I64(0x018C0614F8FCB95D),\n\t\tI64(0x1B14ACCD1A3ACDF3),  I64(0x84D471F200BB732D),\n\t\tI64(0xC1A3110E95E8DA16),  I64(0x430A7220BF1A82B8),\n\t\tI64(0xB77E090D39DF210E),  I64(0x5EF4BD9F3CD05E9D),\n\t\tI64(0x9D4FF6DA7E57A444),  I64(0xDA1D60E183D4A5F8),\n\t\tI64(0xB287C38417998E47),  I64(0xFE3EDC121BB31886),\n\t\tI64(0xC7FE3CCC980CCBEF),  I64(0xE46FB590189BFD03),\n\t\tI64(0x3732FD469A4C57DC),  I64(0x7EF700A07CF1AD65),\n\t\tI64(0x59C64468A31D8859),  I64(0x762FB0B4D45B61F6),\n\t\tI64(0x155BAED099047718),  I64(0x68755E4C3D50BAA6),\n\t\tI64(0xE9214E7F22D8B4DF),  I64(0x2ADDBF532EAC95F4),\n\t\tI64(0x32AE3909B4BD0109),  I64(0x834DF537B08E3450),\n\t\tI64(0xFA209DA84220728D),  I64(0x9E691D9B9EFE23F7),\n\t\tI64(0x0446D288C4AE8D7F),  I64(0x7B4CC524E169785B),\n\t\tI64(0x21D87F0135CA1385),  I64(0xCEBB400F137B8AA5),\n\t\tI64(0x272E2B66580796BE),  I64(0x3612264125C2B0DE),\n\t\tI64(0x057702BDAD1EFBB2),  I64(0xD4BABB8EACF84BE9),\n\t\tI64(0x91583139641BC67B),  I64(0x8BDC2DE08036E024),\n\t\tI64(0x603C8156F49F68ED),  I64(0xF7D236F7DBEF5111),\n\t\tI64(0x9727C4598AD21E80),  I64(0xA08A0896670A5FD7),\n\t\tI64(0xCB4A8F4309EBA9CB),  I64(0x81AF564B0F7036A1),\n\t\tI64(0xC0B99AA778199ABD),  I64(0x959F1EC83FC8E952),\n\t\tI64(0x8C505077794A81B9),  I64(0x3ACAAF8F056338F0),\n\t\tI64(0x07B43F50627A6778),  I64(0x4A44AB49F5ECCC77),\n\t\tI64(0x3BC3D6E4B679EE98),  I64(0x9CC0D4D1CF14108C),\n\t\tI64(0x4406C00B206BC8A0),  I64(0x82A18854C8D72D89),\n\t\tI64(0x67E366B35C3C432C),  I64(0xB923DD61102B37F2),\n\t\tI64(0x56AB2779D884271D),  I64(0xBE83E1B0FF1525AF),\n\t\tI64(0xFB7C65D4217E49A9),  I64(0x6BDBE0E76D48E7D4),\n\t\tI64(0x08DF828745D9179E),  I64(0x22EA6A9ADD53BD34),\n\t\tI64(0xE36E141C5622200A),  I64(0x7F805D1B8CB750EE),\n\t\tI64(0xAFE5C7A59F58E837),  I64(0xE27F996A4FB1C23C),\n\t\tI64(0xD3867DFB0775F0D0),  I64(0xD0E673DE6E88891A),\n\t\tI64(0x123AEB9EAFB86C25),  I64(0x30F1D5D5C145B895),\n\t\tI64(0xBB434A2DEE7269E7),  I64(0x78CB67ECF931FA38),\n\t\tI64(0xF33B0372323BBF9C),  I64(0x52D66336FB279C74),\n\t\tI64(0x505F33AC0AFB4EAA),  I64(0xE8A5CD99A2CCE187),\n\t\tI64(0x534974801E2D30BB),  I64(0x8D2D5711D5876D90),\n\t\tI64(0x1F1A412891BC038E),  I64(0xD6E2E71D82E56648),\n\t\tI64(0x74036C3A497732B7),  I64(0x89B67ED96361F5AB),\n\t\tI64(0xFFED95D8F1EA02A2),  I64(0xE72B3BD61464D43D),\n\t\tI64(0xA6300F170BDC4820),  I64(0xEBC18760ED78A77A)\n\t}, {\n\t\tI64(0xE6A6BE5A05A12138),  I64(0xB5A122A5B4F87C98),\n\t\tI64(0x563C6089140B6990),  I64(0x4C46CB2E391F5DD5),\n\t\tI64(0xD932ADDBC9B79434),  I64(0x08EA70E42015AFF5),\n\t\tI64(0xD765A6673E478CF1),  I64(0xC4FB757EAB278D99),\n\t\tI64(0xDF11C6862D6E0692),  I64(0xDDEB84F10D7F3B16),\n\t\tI64(0x6F2EF604A665EA04),  I64(0x4A8E0F0FF0E0DFB3),\n\t\tI64(0xA5EDEEF83DBCBA51),  I64(0xFC4F0A2A0EA4371E),\n\t\tI64(0xE83E1DA85CB38429),  I64(0xDC8FF882BA1B1CE2),\n\t\tI64(0xCD45505E8353E80D),  I64(0x18D19A00D4DB0717),\n\t\tI64(0x34A0CFEDA5F38101),  I64(0x0BE77E518887CAF2),\n\t\tI64(0x1E341438B3C45136),  I64(0xE05797F49089CCF9),\n\t\tI64(0xFFD23F9DF2591D14),  I64(0x543DDA228595C5CD),\n\t\tI64(0x661F81FD99052A33),  I64(0x8736E641DB0F7B76),\n\t\tI64(0x15227725418E5307),  I64(0xE25F7F46162EB2FA),\n\t\tI64(0x48A8B2126C13D9FE),  I64(0xAFDC541792E76EEA),\n\t\tI64(0x03D912BFC6D1898F),  I64(0x31B1AAFA1B83F51B),\n\t\tI64(0xF1AC2796E42AB7D9),  I64(0x40A3A7D7FCD2EBAC),\n\t\tI64(0x1056136D0AFBBCC5),  I64(0x7889E1DD9A6D0C85),\n\t\tI64(0xD33525782A7974AA),  I64(0xA7E25D09078AC09B),\n\t\tI64(0xBD4138B3EAC6EDD0),  I64(0x920ABFBE71EB9E70),\n\t\tI64(0xA2A5D0F54FC2625C),  I64(0xC054E36B0B1290A3),\n\t\tI64(0xF6DD59FF62FE932B),  I64(0x3537354511A8AC7D),\n\t\tI64(0xCA845E9172FADCD4),  I64(0x84F82B60329D20DC),\n\t\tI64(0x79C62CE1CD672F18),  I64(0x8B09A2ADD124642C),\n\t\tI64(0xD0C1E96A19D9E726),  I64(0x5A786A9B4BA9500C),\n\t\tI64(0x0E020336634C43F3),  I64(0xC17B474AEB66D822),\n\t\tI64(0x6A731AE3EC9BAAC2),  I64(0x8226667AE0840258),\n\t\tI64(0x67D4567691CAECA5),  I64(0x1D94155C4875ADB5),\n\t\tI64(0x6D00FD985B813FDF),  I64(0x51286EFCB774CD06),\n\t\tI64(0x5E8834471FA744AF),  I64(0xF72CA0AEE761AE2E),\n\t\tI64(0xBE40E4CDAEE8E09A),  I64(0xE9970BBB5118F665),\n\t\tI64(0x726E4BEB33DF1964),  I64(0x703B000729199762),\n\t\tI64(0x4631D816F5EF30A7),  I64(0xB880B5B51504A6BE),\n\t\tI64(0x641793C37ED84B6C),  I64(0x7B21ED77F6E97D96),\n\t\tI64(0x776306312EF96B73),  I64(0xAE528948E86FF3F4),\n\t\tI64(0x53DBD7F286A3F8F8),  I64(0x16CADCE74CFC1063),\n\t\tI64(0x005C19BDFA52C6DD),  I64(0x68868F5D64D46AD3),\n\t\tI64(0x3A9D512CCF1E186A),  I64(0x367E62C2385660AE),\n\t\tI64(0xE359E7EA77DCB1D7),  I64(0x526C0773749ABE6E),\n\t\tI64(0x735AE5F9D09F734B),  I64(0x493FC7CC8A558BA8),\n\t\tI64(0xB0B9C1533041AB45),  I64(0x321958BA470A59BD),\n\t\tI64(0x852DB00B5F46C393),  I64(0x91209B2BD336B0E5),\n\t\tI64(0x6E604F7D659EF19F),  I64(0xB99A8AE2782CCB24),\n\t\tI64(0xCCF52AB6C814C4C7),  I64(0x4727D9AFBE11727B),\n\t\tI64(0x7E950D0C0121B34D),  I64(0x756F435670AD471F),\n\t\tI64(0xF5ADD442615A6849),  I64(0x4E87E09980B9957A),\n\t\tI64(0x2ACFA1DF50AEE355),  I64(0xD898263AFD2FD556),\n\t\tI64(0xC8F4924DD80C8FD6),  I64(0xCF99CA3D754A173A),\n\t\tI64(0xFE477BACAF91BF3C),  I64(0xED5371F6D690C12D),\n\t\tI64(0x831A5C285E687094),  I64(0xC5D3C90A3708A0A4),\n\t\tI64(0x0F7F903717D06580),  I64(0x19F9BB13B8FDF27F),\n\t\tI64(0xB1BD6F1B4D502843),  I64(0x1C761BA38FFF4012),\n\t\tI64(0x0D1530C4E2E21F3B),  I64(0x8943CE69A7372C8A),\n\t\tI64(0xE5184E11FEB5CE66),  I64(0x618BDB80BD736621),\n\t\tI64(0x7D29BAD68B574D0B),  I64(0x81BB613E25E6FE5B),\n\t\tI64(0x071C9C10BC07913F),  I64(0xC7BEEB7909AC2D97),\n\t\tI64(0xC3E58D353BC5D757),  I64(0xEB017892F38F61E8),\n\t\tI64(0xD4EFFB9C9B1CC21A),  I64(0x99727D26F494F7AB),\n\t\tI64(0xA3E063A2956B3E03),  I64(0x9D4A8B9A4AA09C30),\n\t\tI64(0x3F6AB7D500090FB4),  I64(0x9CC0F2A057268AC0),\n\t\tI64(0x3DEE9D2DEDBF42D1),  I64(0x330F49C87960A972),\n\t\tI64(0xC6B2720287421B41),  I64(0x0AC59EC07C00369C),\n\t\tI64(0xEF4EAC49CB353425),  I64(0xF450244EEF0129D8),\n\t\tI64(0x8ACC46E5CAF4DEB6),  I64(0x2FFEAB63989263F7),\n\t\tI64(0x8F7CB9FE5D7A4578),  I64(0x5BD8F7644E634635),\n\t\tI64(0x427A7315BF2DC900),  I64(0x17D0C4AA2125261C),\n\t\tI64(0x3992486C93518E50),  I64(0xB4CBFEE0A2D7D4C3),\n\t\tI64(0x7C75D6202C5DDD8D),  I64(0xDBC295D8E35B6C61),\n\t\tI64(0x60B369D302032B19),  I64(0xCE42685FDCE44132),\n\t\tI64(0x06F3DDB9DDF65610),  I64(0x8EA4D21DB5E148F0),\n\t\tI64(0x20B0FCE62FCD496F),  I64(0x2C1B912358B0EE31),\n\t\tI64(0xB28317B818F5A308),  I64(0xA89C1E189CA6D2CF),\n\t\tI64(0x0C6B18576AAADBC8),  I64(0xB65DEAA91299FAE3),\n\t\tI64(0xFB2B794B7F1027E7),  I64(0x04E4317F443B5BEB),\n\t\tI64(0x4B852D325939D0A6),  I64(0xD5AE6BEEFB207FFC),\n\t\tI64(0x309682B281C7D374),  I64(0xBAE309A194C3B475),\n\t\tI64(0x8CC3F97B13B49F05),  I64(0x98A9422FF8293967),\n\t\tI64(0x244B16B01076FF7C),  I64(0xF8BF571C663D67EE),\n\t\tI64(0x1F0D6758EEE30DA1),  I64(0xC9B611D97ADEB9B7),\n\t\tI64(0xB7AFD5887B6C57A2),  I64(0x6290AE846B984FE1),\n\t\tI64(0x94DF4CDEACC1A5FD),  I64(0x058A5BD1C5483AFF),\n\t\tI64(0x63166CC142BA3C37),  I64(0x8DB8526EB2F76F40),\n\t\tI64(0xE10880036F0D6D4E),  I64(0x9E0523C9971D311D),\n\t\tI64(0x45EC2824CC7CD691),  I64(0x575B8359E62382C9),\n\t\tI64(0xFA9E400DC4889995),  I64(0xD1823ECB45721568),\n\t\tI64(0xDAFD983B8206082F),  I64(0xAA7D29082386A8CB),\n\t\tI64(0x269FCD4403B87588),  I64(0x1B91F5F728BDD1E0),\n\t\tI64(0xE4669F39040201F6),  I64(0x7A1D7C218CF04ADE),\n\t\tI64(0x65623C29D79CE5CE),  I64(0x2368449096C00BB1),\n\t\tI64(0xAB9BF1879DA503BA),  I64(0xBC23ECB1A458058E),\n\t\tI64(0x9A58DF01BB401ECC),  I64(0xA070E868A85F143D),\n\t\tI64(0x4FF188307DF2239E),  I64(0x14D565B41A641183),\n\t\tI64(0xEE13337452701602),  I64(0x950E3DCF3F285E09),\n\t\tI64(0x59930254B9C80953),  I64(0x3BF299408930DA6D),\n\t\tI64(0xA955943F53691387),  I64(0xA15EDECAA9CB8784),\n\t\tI64(0x29142127352BE9A0),  I64(0x76F0371FFF4E7AFB),\n\t\tI64(0x0239F450274F2228),  I64(0xBB073AF01D5E868B),\n\t\tI64(0xBFC80571C10E96C1),  I64(0xD267088568222E23),\n\t\tI64(0x9671A3D48E80B5B0),  I64(0x55B5D38AE193BB81),\n\t\tI64(0x693AE2D0A18B04B8),  I64(0x5C48B4ECADD5335F),\n\t\tI64(0xFD743B194916A1CA),  I64(0x2577018134BE98C4),\n\t\tI64(0xE77987E83C54A4AD),  I64(0x28E11014DA33E1B9),\n\t\tI64(0x270CC59E226AA213),  I64(0x71495F756D1A5F60),\n\t\tI64(0x9BE853FB60AFEF77),  I64(0xADC786A7F7443DBF),\n\t\tI64(0x0904456173B29A82),  I64(0x58BC7A66C232BD5E),\n\t\tI64(0xF306558C673AC8B2),  I64(0x41F639C6B6C9772A),\n\t\tI64(0x216DEFE99FDA35DA),  I64(0x11640CC71C7BE615),\n\t\tI64(0x93C43694565C5527),  I64(0xEA038E6246777839),\n\t\tI64(0xF9ABF3CE5A3E2469),  I64(0x741E768D0FD312D2),\n\t\tI64(0x0144B883CED652C6),  I64(0xC20B5A5BA33F8552),\n\t\tI64(0x1AE69633C3435A9D),  I64(0x97A28CA4088CFDEC),\n\t\tI64(0x8824A43C1E96F420),  I64(0x37612FA66EEEA746),\n\t\tI64(0x6B4CB165F9CF0E5A),  I64(0x43AA1C06A0ABFB4A),\n\t\tI64(0x7F4DC26FF162796B),  I64(0x6CBACC8E54ED9B0F),\n\t\tI64(0xA6B7FFEFD2BB253E),  I64(0x2E25BC95B0A29D4F),\n\t\tI64(0x86D6A58BDEF1388C),  I64(0xDED74AC576B6F054),\n\t\tI64(0x8030BDBC2B45805D),  I64(0x3C81AF70E94D9289),\n\t\tI64(0x3EFF6DDA9E3100DB),  I64(0xB38DC39FDFCC8847),\n\t\tI64(0x123885528D17B87E),  I64(0xF2DA0ED240B1B642),\n\t\tI64(0x44CEFADCD54BF9A9),  I64(0x1312200E433C7EE6),\n\t\tI64(0x9FFCC84F3A78C748),  I64(0xF0CD1F72248576BB),\n\t\tI64(0xEC6974053638CFE4),  I64(0x2BA7B67C0CEC4E4C),\n\t\tI64(0xAC2F4DF3E5CE32ED),  I64(0xCB33D14326EA4C11),\n\t\tI64(0xA4E9044CC77E58BC),  I64(0x5F513293D934FCEF),\n\t\tI64(0x5DC9645506E55444),  I64(0x50DE418F317DE40A),\n\t\tI64(0x388CB31A69DDE259),  I64(0x2DB4A83455820A86),\n\t\tI64(0x9010A91E84711AE9),  I64(0x4DF7F0B7B1498371),\n\t\tI64(0xD62A2EABC0977179),  I64(0x22FAC097AA8D5C0E)\n\t}, {\n\t\tI64(0xF49FCC2FF1DAF39B),  I64(0x487FD5C66FF29281),\n\t\tI64(0xE8A30667FCDCA83F),  I64(0x2C9B4BE3D2FCCE63),\n\t\tI64(0xDA3FF74B93FBBBC2),  I64(0x2FA165D2FE70BA66),\n\t\tI64(0xA103E279970E93D4),  I64(0xBECDEC77B0E45E71),\n\t\tI64(0xCFB41E723985E497),  I64(0xB70AAA025EF75017),\n\t\tI64(0xD42309F03840B8E0),  I64(0x8EFC1AD035898579),\n\t\tI64(0x96C6920BE2B2ABC5),  I64(0x66AF4163375A9172),\n\t\tI64(0x2174ABDCCA7127FB),  I64(0xB33CCEA64A72FF41),\n\t\tI64(0xF04A4933083066A5),  I64(0x8D970ACDD7289AF5),\n\t\tI64(0x8F96E8E031C8C25E),  I64(0xF3FEC02276875D47),\n\t\tI64(0xEC7BF310056190DD),  I64(0xF5ADB0AEBB0F1491),\n\t\tI64(0x9B50F8850FD58892),  I64(0x4975488358B74DE8),\n\t\tI64(0xA3354FF691531C61),  I64(0x0702BBE481D2C6EE),\n\t\tI64(0x89FB24057DEDED98),  I64(0xAC3075138596E902),\n\t\tI64(0x1D2D3580172772ED),  I64(0xEB738FC28E6BC30D),\n\t\tI64(0x5854EF8F63044326),  I64(0x9E5C52325ADD3BBE),\n\t\tI64(0x90AA53CF325C4623),  I64(0xC1D24D51349DD067),\n\t\tI64(0x2051CFEEA69EA624),  I64(0x13220F0A862E7E4F),\n\t\tI64(0xCE39399404E04864),  I64(0xD9C42CA47086FCB7),\n\t\tI64(0x685AD2238A03E7CC),  I64(0x066484B2AB2FF1DB),\n\t\tI64(0xFE9D5D70EFBF79EC),  I64(0x5B13B9DD9C481854),\n\t\tI64(0x15F0D475ED1509AD),  I64(0x0BEBCD060EC79851),\n\t\tI64(0xD58C6791183AB7F8),  I64(0xD1187C5052F3EEE4),\n\t\tI64(0xC95D1192E54E82FF),  I64(0x86EEA14CB9AC6CA2),\n\t\tI64(0x3485BEB153677D5D),  I64(0xDD191D781F8C492A),\n\t\tI64(0xF60866BAA784EBF9),  I64(0x518F643BA2D08C74),\n\t\tI64(0x8852E956E1087C22),  I64(0xA768CB8DC410AE8D),\n\t\tI64(0x38047726BFEC8E1A),  I64(0xA67738B4CD3B45AA),\n\t\tI64(0xAD16691CEC0DDE19),  I64(0xC6D4319380462E07),\n\t\tI64(0xC5A5876D0BA61938),  I64(0x16B9FA1FA58FD840),\n\t\tI64(0x188AB1173CA74F18),  I64(0xABDA2F98C99C021F),\n\t\tI64(0x3E0580AB134AE816),  I64(0x5F3B05B773645ABB),\n\t\tI64(0x2501A2BE5575F2F6),  I64(0x1B2F74004E7E8BA9),\n\t\tI64(0x1CD7580371E8D953),  I64(0x7F6ED89562764E30),\n\t\tI64(0xB15926FF596F003D),  I64(0x9F65293DA8C5D6B9),\n\t\tI64(0x6ECEF04DD690F84C),  I64(0x4782275FFF33AF88),\n\t\tI64(0xE41433083F820801),  I64(0xFD0DFE409A1AF9B5),\n\t\tI64(0x4325A3342CDB396B),  I64(0x8AE77E62B301B252),\n\t\tI64(0xC36F9E9F6655615A),  I64(0x85455A2D92D32C09),\n\t\tI64(0xF2C7DEA949477485),  I64(0x63CFB4C133A39EBA),\n\t\tI64(0x83B040CC6EBC5462),  I64(0x3B9454C8FDB326B0),\n\t\tI64(0x56F56A9E87FFD78C),  I64(0x2DC2940D99F42BC6),\n\t\tI64(0x98F7DF096B096E2D),  I64(0x19A6E01E3AD852BF),\n\t\tI64(0x42A99CCBDBD4B40B),  I64(0xA59998AF45E9C559),\n\t\tI64(0x366295E807D93186),  I64(0x6B48181BFAA1F773),\n\t\tI64(0x1FEC57E2157A0A1D),  I64(0x4667446AF6201AD5),\n\t\tI64(0xE615EBCACFB0F075),  I64(0xB8F31F4F68290778),\n\t\tI64(0x22713ED6CE22D11E),  I64(0x3057C1A72EC3C93B),\n\t\tI64(0xCB46ACC37C3F1F2F),  I64(0xDBB893FD02AAF50E),\n\t\tI64(0x331FD92E600B9FCF),  I64(0xA498F96148EA3AD6),\n\t\tI64(0xA8D8426E8B6A83EA),  I64(0xA089B274B7735CDC),\n\t\tI64(0x87F6B3731E524A11),  I64(0x118808E5CBC96749),\n\t\tI64(0x9906E4C7B19BD394),  I64(0xAFED7F7E9B24A20C),\n\t\tI64(0x6509EADEEB3644A7),  I64(0x6C1EF1D3E8EF0EDE),\n\t\tI64(0xB9C97D43E9798FB4),  I64(0xA2F2D784740C28A3),\n\t\tI64(0x7B8496476197566F),  I64(0x7A5BE3E6B65F069D),\n\t\tI64(0xF96330ED78BE6F10),  I64(0xEEE60DE77A076A15),\n\t\tI64(0x2B4BEE4AA08B9BD0),  I64(0x6A56A63EC7B8894E),\n\t\tI64(0x02121359BA34FEF4),  I64(0x4CBF99F8283703FC),\n\t\tI64(0x398071350CAF30C8),  I64(0xD0A77A89F017687A),\n\t\tI64(0xF1C1A9EB9E423569),  I64(0x8C7976282DEE8199),\n\t\tI64(0x5D1737A5DD1F7ABD),  I64(0x4F53433C09A9FA80),\n\t\tI64(0xFA8B0C53DF7CA1D9),  I64(0x3FD9DCBC886CCB77),\n\t\tI64(0xC040917CA91B4720),  I64(0x7DD00142F9D1DCDF),\n\t\tI64(0x8476FC1D4F387B58),  I64(0x23F8E7C5F3316503),\n\t\tI64(0x032A2244E7E37339),  I64(0x5C87A5D750F5A74B),\n\t\tI64(0x082B4CC43698992E),  I64(0xDF917BECB858F63C),\n\t\tI64(0x3270B8FC5BF86DDA),  I64(0x10AE72BB29B5DD76),\n\t\tI64(0x576AC94E7700362B),  I64(0x1AD112DAC61EFB8F),\n\t\tI64(0x691BC30EC5FAA427),  I64(0xFF246311CC327143),\n\t\tI64(0x3142368E30E53206),  I64(0x71380E31E02CA396),\n\t\tI64(0x958D5C960AAD76F1),  I64(0xF8D6F430C16DA536),\n\t\tI64(0xC8FFD13F1BE7E1D2),  I64(0x7578AE66004DDBE1),\n\t\tI64(0x05833F01067BE646),  I64(0xBB34B5AD3BFE586D),\n\t\tI64(0x095F34C9A12B97F0),  I64(0x247AB64525D60CA8),\n\t\tI64(0xDCDBC6F3017477D1),  I64(0x4A2E14D4DECAD24D),\n\t\tI64(0xBDB5E6D9BE0A1EEB),  I64(0x2A7E70F7794301AB),\n\t\tI64(0xDEF42D8A270540FD),  I64(0x01078EC0A34C22C1),\n\t\tI64(0xE5DE511AF4C16387),  I64(0x7EBB3A52BD9A330A),\n\t\tI64(0x77697857AA7D6435),  I64(0x004E831603AE4C32),\n\t\tI64(0xE7A21020AD78E312),  I64(0x9D41A70C6AB420F2),\n\t\tI64(0x28E06C18EA1141E6),  I64(0xD2B28CBD984F6B28),\n\t\tI64(0x26B75F6C446E9D83),  I64(0xBA47568C4D418D7F),\n\t\tI64(0xD80BADBFE6183D8E),  I64(0x0E206D7F5F166044),\n\t\tI64(0xE258A43911CBCA3E),  I64(0x723A1746B21DC0BC),\n\t\tI64(0xC7CAA854F5D7CDD3),  I64(0x7CAC32883D261D9C),\n\t\tI64(0x7690C26423BA942C),  I64(0x17E55524478042B8),\n\t\tI64(0xE0BE477656A2389F),  I64(0x4D289B5E67AB2DA0),\n\t\tI64(0x44862B9C8FBBFD31),  I64(0xB47CC8049D141365),\n\t\tI64(0x822C1B362B91C793),  I64(0x4EB14655FB13DFD8),\n\t\tI64(0x1ECBBA0714E2A97B),  I64(0x6143459D5CDE5F14),\n\t\tI64(0x53A8FBF1D5F0AC89),  I64(0x97EA04D81C5E5B00),\n\t\tI64(0x622181A8D4FDB3F3),  I64(0xE9BCD341572A1208),\n\t\tI64(0x1411258643CCE58A),  I64(0x9144C5FEA4C6E0A4),\n\t\tI64(0x0D33D06565CF620F),  I64(0x54A48D489F219CA1),\n\t\tI64(0xC43E5EAC6D63C821),  I64(0xA9728B3A72770DAF),\n\t\tI64(0xD7934E7B20DF87EF),  I64(0xE35503B61A3E86E5),\n\t\tI64(0xCAE321FBC819D504),  I64(0x129A50B3AC60BFA6),\n\t\tI64(0xCD5E68EA7E9FB6C3),  I64(0xB01C90199483B1C7),\n\t\tI64(0x3DE93CD5C295376C),  I64(0xAED52EDF2AB9AD13),\n\t\tI64(0x2E60F512C0A07884),  I64(0xBC3D86A3E36210C9),\n\t\tI64(0x35269D9B163951CE),  I64(0x0C7D6E2AD0CDB5FA),\n\t\tI64(0x59E86297D87F5733),  I64(0x298EF221898DB0E7),\n\t\tI64(0x55000029D1A5AA7E),  I64(0x8BC08AE1B5061B45),\n\t\tI64(0xC2C31C2B6C92703A),  I64(0x94CC596BAF25EF42),\n\t\tI64(0x0A1D73DB22540456),  I64(0x04B6A0F9D9C4179A),\n\t\tI64(0xEFFDAFA2AE3D3C60),  I64(0xF7C8075BB49496C4),\n\t\tI64(0x9CC5C7141D1CD4E3),  I64(0x78BD1638218E5534),\n\t\tI64(0xB2F11568F850246A),  I64(0xEDFABCFA9502BC29),\n\t\tI64(0x796CE5F2DA23051B),  I64(0xAAE128B0DC93537C),\n\t\tI64(0x3A493DA0EE4B29AE),  I64(0xB5DF6B2C416895D7),\n\t\tI64(0xFCABBD25122D7F37),  I64(0x70810B58105DC4B1),\n\t\tI64(0xE10FDD37F7882A90),  I64(0x524DCAB5518A3F5C),\n\t\tI64(0x3C9E85878451255B),  I64(0x4029828119BD34E2),\n\t\tI64(0x74A05B6F5D3CECCB),  I64(0xB610021542E13ECA),\n\t\tI64(0x0FF979D12F59E2AC),  I64(0x6037DA27E4F9CC50),\n\t\tI64(0x5E92975A0DF1847D),  I64(0xD66DE190D3E623FE),\n\t\tI64(0x5032D6B87B568048),  I64(0x9A36B7CE8235216E),\n\t\tI64(0x80272A7A24F64B4A),  I64(0x93EFED8B8C6916F7),\n\t\tI64(0x37DDBFF44CCE1555),  I64(0x4B95DB5D4B99BD25),\n\t\tI64(0x92D3FDA169812FC0),  I64(0xFB1A4A9A90660BB6),\n\t\tI64(0x730C196946A4B9B2),  I64(0x81E289AA7F49DA68),\n\t\tI64(0x64669A0F83B1A05F),  I64(0x27B3FF7D9644F48B),\n\t\tI64(0xCC6B615C8DB675B3),  I64(0x674F20B9BCEBBE95),\n\t\tI64(0x6F31238275655982),  I64(0x5AE488713E45CF05),\n\t\tI64(0xBF619F9954C21157),  I64(0xEABAC46040A8EAE9),\n\t\tI64(0x454C6FE9F2C0C1CD),  I64(0x419CF6496412691C),\n\t\tI64(0xD3DC3BEF265B0F70),  I64(0x6D0E60F5C3578A9E)\n\t}, {\n\t\tI64(0x5B0E608526323C55),  I64(0x1A46C1A9FA1B59F5),\n\t\tI64(0xA9E245A17C4C8FFA),  I64(0x65CA5159DB2955D7),\n\t\tI64(0x05DB0A76CE35AFC2),  I64(0x81EAC77EA9113D45),\n\t\tI64(0x528EF88AB6AC0A0D),  I64(0xA09EA253597BE3FF),\n\t\tI64(0x430DDFB3AC48CD56),  I64(0xC4B3A67AF45CE46F),\n\t\tI64(0x4ECECFD8FBE2D05E),  I64(0x3EF56F10B39935F0),\n\t\tI64(0x0B22D6829CD619C6),  I64(0x17FD460A74DF2069),\n\t\tI64(0x6CF8CC8E8510ED40),  I64(0xD6C824BF3A6ECAA7),\n\t\tI64(0x61243D581A817049),  I64(0x048BACB6BBC163A2),\n\t\tI64(0xD9A38AC27D44CC32),  I64(0x7FDDFF5BAAF410AB),\n\t\tI64(0xAD6D495AA804824B),  I64(0xE1A6A74F2D8C9F94),\n\t\tI64(0xD4F7851235DEE8E3),  I64(0xFD4B7F886540D893),\n\t\tI64(0x247C20042AA4BFDA),  I64(0x096EA1C517D1327C),\n\t\tI64(0xD56966B4361A6685),  I64(0x277DA5C31221057D),\n\t\tI64(0x94D59893A43ACFF7),  I64(0x64F0C51CCDC02281),\n\t\tI64(0x3D33BCC4FF6189DB),  I64(0xE005CB184CE66AF1),\n\t\tI64(0xFF5CCD1D1DB99BEA),  I64(0xB0B854A7FE42980F),\n\t\tI64(0x7BD46A6A718D4B9F),  I64(0xD10FA8CC22A5FD8C),\n\t\tI64(0xD31484952BE4BD31),  I64(0xC7FA975FCB243847),\n\t\tI64(0x4886ED1E5846C407),  I64(0x28CDDB791EB70B04),\n\t\tI64(0xC2B00BE2F573417F),  I64(0x5C9590452180F877),\n\t\tI64(0x7A6BDDFFF370EB00),  I64(0xCE509E38D6D9D6A4),\n\t\tI64(0xEBEB0F00647FA702),  I64(0x1DCC06CF76606F06),\n\t\tI64(0xE4D9F28BA286FF0A),  I64(0xD85A305DC918C262),\n\t\tI64(0x475B1D8732225F54),  I64(0x2D4FB51668CCB5FE),\n\t\tI64(0xA679B9D9D72BBA20),  I64(0x53841C0D912D43A5),\n\t\tI64(0x3B7EAA48BF12A4E8),  I64(0x781E0E47F22F1DDF),\n\t\tI64(0xEFF20CE60AB50973),  I64(0x20D261D19DFFB742),\n\t\tI64(0x16A12B03062A2E39),  I64(0x1960EB2239650495),\n\t\tI64(0x251C16FED50EB8B8),  I64(0x9AC0C330F826016E),\n\t\tI64(0xED152665953E7671),  I64(0x02D63194A6369570),\n\t\tI64(0x5074F08394B1C987),  I64(0x70BA598C90B25CE1),\n\t\tI64(0x794A15810B9742F6),  I64(0x0D5925E9FCAF8C6C),\n\t\tI64(0x3067716CD868744E),  I64(0x910AB077E8D7731B),\n\t\tI64(0x6A61BBDB5AC42F61),  I64(0x93513EFBF0851567),\n\t\tI64(0xF494724B9E83E9D5),  I64(0xE887E1985C09648D),\n\t\tI64(0x34B1D3C675370CFD),  I64(0xDC35E433BC0D255D),\n\t\tI64(0xD0AAB84234131BE0),  I64(0x08042A50B48B7EAF),\n\t\tI64(0x9997C4EE44A3AB35),  I64(0x829A7B49201799D0),\n\t\tI64(0x263B8307B7C54441),  I64(0x752F95F4FD6A6CA6),\n\t\tI64(0x927217402C08C6E5),  I64(0x2A8AB754A795D9EE),\n\t\tI64(0xA442F7552F72943D),  I64(0x2C31334E19781208),\n\t\tI64(0x4FA98D7CEAEE6291),  I64(0x55C3862F665DB309),\n\t\tI64(0xBD0610175D53B1F3),  I64(0x46FE6CB840413F27),\n\t\tI64(0x3FE03792DF0CFA59),  I64(0xCFE700372EB85E8F),\n\t\tI64(0xA7BE29E7ADBCE118),  I64(0xE544EE5CDE8431DD),\n\t\tI64(0x8A781B1B41F1873E),  I64(0xA5C94C78A0D2F0E7),\n\t\tI64(0x39412E2877B60728),  I64(0xA1265EF3AFC9A62C),\n\t\tI64(0xBCC2770C6A2506C5),  I64(0x3AB66DD5DCE1CE12),\n\t\tI64(0xE65499D04A675B37),  I64(0x7D8F523481BFD216),\n\t\tI64(0x0F6F64FCEC15F389),  I64(0x74EFBE618B5B13C8),\n\t\tI64(0xACDC82B714273E1D),  I64(0xDD40BFE003199D17),\n\t\tI64(0x37E99257E7E061F8),  I64(0xFA52626904775AAA),\n\t\tI64(0x8BBBF63A463D56F9),  I64(0xF0013F1543A26E64),\n\t\tI64(0xA8307E9F879EC898),  I64(0xCC4C27A4150177CC),\n\t\tI64(0x1B432F2CCA1D3348),  I64(0xDE1D1F8F9F6FA013),\n\t\tI64(0x606602A047A7DDD6),  I64(0xD237AB64CC1CB2C7),\n\t\tI64(0x9B938E7225FCD1D3),  I64(0xEC4E03708E0FF476),\n\t\tI64(0xFEB2FBDA3D03C12D),  I64(0xAE0BCED2EE43889A),\n\t\tI64(0x22CB8923EBFB4F43),  I64(0x69360D013CF7396D),\n\t\tI64(0x855E3602D2D4E022),  I64(0x073805BAD01F784C),\n\t\tI64(0x33E17A133852F546),  I64(0xDF4874058AC7B638),\n\t\tI64(0xBA92B29C678AA14A),  I64(0x0CE89FC76CFAADCD),\n\t\tI64(0x5F9D4E0908339E34),  I64(0xF1AFE9291F5923B9),\n\t\tI64(0x6E3480F60F4A265F),  I64(0xEEBF3A2AB29B841C),\n\t\tI64(0xE21938A88F91B4AD),  I64(0x57DFEFF845C6D3C3),\n\t\tI64(0x2F006B0BF62CAAF2),  I64(0x62F479EF6F75EE78),\n\t\tI64(0x11A55AD41C8916A9),  I64(0xF229D29084FED453),\n\t\tI64(0x42F1C27B16B000E6),  I64(0x2B1F76749823C074),\n\t\tI64(0x4B76ECA3C2745360),  I64(0x8C98F463B91691BD),\n\t\tI64(0x14BCC93CF1ADE66A),  I64(0x8885213E6D458397),\n\t\tI64(0x8E177DF0274D4711),  I64(0xB49B73B5503F2951),\n\t\tI64(0x10168168C3F96B6B),  I64(0x0E3D963B63CAB0AE),\n\t\tI64(0x8DFC4B5655A1DB14),  I64(0xF789F1356E14DE5C),\n\t\tI64(0x683E68AF4E51DAC1),  I64(0xC9A84F9D8D4B0FD9),\n\t\tI64(0x3691E03F52A0F9D1),  I64(0x5ED86E46E1878E80),\n\t\tI64(0x3C711A0E99D07150),  I64(0x5A0865B20C4E9310),\n\t\tI64(0x56FBFC1FE4F0682E),  I64(0xEA8D5DE3105EDF9B),\n\t\tI64(0x71ABFDB12379187A),  I64(0x2EB99DE1BEE77B9C),\n\t\tI64(0x21ECC0EA33CF4523),  I64(0x59A4D7521805C7A1),\n\t\tI64(0x3896F5EB56AE7C72),  I64(0xAA638F3DB18F75DC),\n\t\tI64(0x9F39358DABE9808E),  I64(0xB7DEFA91C00B72AC),\n\t\tI64(0x6B5541FD62492D92),  I64(0x6DC6DEE8F92E4D5B),\n\t\tI64(0x353F57ABC4BEEA7E),  I64(0x735769D6DA5690CE),\n\t\tI64(0x0A234AA642391484),  I64(0xF6F9508028F80D9D),\n\t\tI64(0xB8E319A27AB3F215),  I64(0x31AD9C1151341A4D),\n\t\tI64(0x773C22A57BEF5805),  I64(0x45C7561A07968633),\n\t\tI64(0xF913DA9E249DBE36),  I64(0xDA652D9B78A64C68),\n\t\tI64(0x4C27A97F3BC334EF),  I64(0x76621220E66B17F4),\n\t\tI64(0x967743899ACD7D0B),  I64(0xF3EE5BCAE0ED6782),\n\t\tI64(0x409F753600C879FC),  I64(0x06D09A39B5926DB6),\n\t\tI64(0x6F83AEB0317AC588),  I64(0x01E6CA4A86381F21),\n\t\tI64(0x66FF3462D19F3025),  I64(0x72207C24DDFD3BFB),\n\t\tI64(0x4AF6B6D3E2ECE2EB),  I64(0x9C994DBEC7EA08DE),\n\t\tI64(0x49ACE597B09A8BC4),  I64(0xB38C4766CF0797BA),\n\t\tI64(0x131B9373C57C2A75),  I64(0xB1822CCE61931E58),\n\t\tI64(0x9D7555B909BA1C0C),  I64(0x127FAFDD937D11D2),\n\t\tI64(0x29DA3BADC66D92E4),  I64(0xA2C1D57154C2ECBC),\n\t\tI64(0x58C5134D82F6FE24),  I64(0x1C3AE3515B62274F),\n\t\tI64(0xE907C82E01CB8126),  I64(0xF8ED091913E37FCB),\n\t\tI64(0x3249D8F9C80046C9),  I64(0x80CF9BEDE388FB63),\n\t\tI64(0x1881539A116CF19E),  I64(0x5103F3F76BD52457),\n\t\tI64(0x15B7E6F5AE47F7A8),  I64(0xDBD7C6DED47E9CCF),\n\t\tI64(0x44E55C410228BB1A),  I64(0xB647D4255EDB4E99),\n\t\tI64(0x5D11882BB8AAFC30),  I64(0xF5098BBB29D3212A),\n\t\tI64(0x8FB5EA14E90296B3),  I64(0x677B942157DD025A),\n\t\tI64(0xFB58E7C0A390ACB5),  I64(0x89D3674C83BD4A01),\n\t\tI64(0x9E2DA4DF4BF3B93B),  I64(0xFCC41E328CAB4829),\n\t\tI64(0x03F38C96BA582C52),  I64(0xCAD1BDBD7FD85DB2),\n\t\tI64(0xBBB442C16082AE83),  I64(0xB95FE86BA5DA9AB0),\n\t\tI64(0xB22E04673771A93F),  I64(0x845358C9493152D8),\n\t\tI64(0xBE2A488697B4541E),  I64(0x95A2DC2DD38E6966),\n\t\tI64(0xC02C11AC923C852B),  I64(0x2388B1990DF2A87B),\n\t\tI64(0x7C8008FA1B4F37BE),  I64(0x1F70D0C84D54E503),\n\t\tI64(0x5490ADEC7ECE57D4),  I64(0x002B3C27D9063A3A),\n\t\tI64(0x7EAEA3848030A2BF),  I64(0xC602326DED2003C0),\n\t\tI64(0x83A7287D69A94086),  I64(0xC57A5FCB30F57A8A),\n\t\tI64(0xB56844E479EBE779),  I64(0xA373B40F05DCBCE9),\n\t\tI64(0xD71A786E88570EE2),  I64(0x879CBACDBDE8F6A0),\n\t\tI64(0x976AD1BCC164A32F),  I64(0xAB21E25E9666D78B),\n\t\tI64(0x901063AAE5E5C33C),  I64(0x9818B34448698D90),\n\t\tI64(0xE36487AE3E1E8ABB),  I64(0xAFBDF931893BDCB4),\n\t\tI64(0x6345A0DC5FBBD519),  I64(0x8628FE269B9465CA),\n\t\tI64(0x1E5D01603F9C51EC),  I64(0x4DE44006A15049B7),\n\t\tI64(0xBF6C70E5F776CBB1),  I64(0x411218F2EF552BED),\n\t\tI64(0xCB0C0708705A36A3),  I64(0xE74D14754F986044),\n\t\tI64(0xCD56D9430EA8280E),  I64(0xC12591D7535F5065),\n\t\tI64(0xC83223F1720AEF96),  I64(0xC3A0396F7363A51F)\n\t}\n};\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/torrent.c",
    "content": "﻿/* torrent.c - create BitTorrent files and calculate BitTorrent  InfoHash (BTIH).\n *\n * Copyright (c) 2010, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"torrent.h\"\n#include \"hex.h\"\n#include \"util.h\"\n#include <assert.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>  /* time() */\n#include \"byte_order.h\"\n\n#ifdef USE_OPENSSL\n#define SHA1_INIT(ctx) ((pinit_t)ctx->sha1_methods.init)(&ctx->sha1_context)\n#define SHA1_UPDATE(ctx, msg, size) ((pupdate_t)ctx->sha1_methods.update)(&ctx->sha1_context, (msg), (size))\n#define SHA1_FINAL(ctx, result) ((pfinal_t)ctx->sha1_methods.final)(&ctx->sha1_context, (result))\n#else\n#define SHA1_INIT(ctx) rhash_sha1_init(&ctx->sha1_context)\n#define SHA1_UPDATE(ctx, msg, size) rhash_sha1_update(&ctx->sha1_context, (msg), (size))\n#define SHA1_FINAL(ctx, result) rhash_sha1_final(&ctx->sha1_context, (result))\n#endif\n\n#define BT_MIN_PIECE_LENGTH 16384\n/** size of a SHA1 hash in bytes */\n#define BT_HASH_SIZE 20\n/** number of SHA1 hashes to store together in one block */\n#define BT_BLOCK_SIZE 256\n#define BT_BLOCK_SIZE_IN_BYTES (BT_BLOCK_SIZE * BT_HASH_SIZE)\n\n/**\n * Initialize torrent context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid bt_init(torrent_ctx* ctx)\n{\n\tmemset(ctx, 0, sizeof(torrent_ctx));\n\tctx->piece_length = BT_MIN_PIECE_LENGTH;\n\tassert(BT_MIN_PIECE_LENGTH == bt_default_piece_length(0, 0));\n\n#ifdef USE_OPENSSL\n\t/* get the methods of the selected SHA1 algorithm */\n\tassert(rhash_info_table[3].info->hash_id == EXTENDED_SHA1);\n\tassert(rhash_info_table[3].context_size <= (sizeof(sha1_ctx) + sizeof(unsigned long)));\n\trhash_load_sha1_methods(&ctx->sha1_methods, METHODS_SELECTED);\n#endif\n\n\tSHA1_INIT(ctx);\n}\n\n/**\n * Free memory allocated by properties of torrent_vect structure.\n *\n * @param vect vector to clean\n */\nstatic void bt_vector_clean(torrent_vect* vect)\n{\n\tsize_t i;\n\tfor (i = 0; i < vect->size; i++) {\n\t\tfree(vect->array[i]);\n\t}\n\tfree(vect->array);\n}\n\n/**\n * Clean up torrent context by freeing all dynamically\n * allocated memory.\n *\n * @param ctx torrent algorithm context\n */\nvoid bt_cleanup(torrent_ctx* ctx)\n{\n\tassert(ctx != NULL);\n\n\t/* destroy arrays */\n\tbt_vector_clean(&ctx->hash_blocks);\n\tbt_vector_clean(&ctx->files);\n\tbt_vector_clean(&ctx->announce);\n\n\tfree(ctx->program_name);\n\tfree(ctx->content.str);\n\tctx->program_name = 0;\n\tctx->content.str = 0;\n}\n\nstatic void bt_generate_torrent(torrent_ctx* ctx);\n\n/**\n * Add an item to vector.\n *\n * @param vect vector to add item to\n * @param item the item to add\n * @return non-zero on success, zero on fail\n */\nstatic int bt_vector_add_ptr(torrent_vect* vect, void* item)\n{\n\t/* check if vector contains enough space for the next item */\n\tif (vect->size >= vect->allocated) {\n\t\tsize_t size = (vect->allocated == 0 ? 128 : vect->allocated * 2);\n\t\tvoid* new_array = realloc(vect->array, size * sizeof(void*));\n\t\tif (new_array == NULL) return 0; /* failed: no memory */\n\t\tvect->array = (void**)new_array;\n\t\tvect->allocated = size;\n\t}\n\t/* add new item to the vector */\n\tvect->array[vect->size] = item;\n\tvect->size++;\n\treturn 1;\n}\n\n/**\n * Store a SHA1 hash of a processed file piece.\n *\n * @param ctx torrent algorithm context\n * @return non-zero on success, zero on fail\n */\nstatic int bt_store_piece_sha1(torrent_ctx* ctx)\n{\n\tunsigned char* block;\n\tunsigned char* hash;\n\n\tif ((ctx->piece_count % BT_BLOCK_SIZE) == 0) {\n\t\tblock = (unsigned char*)malloc(BT_BLOCK_SIZE_IN_BYTES);\n\t\tif (!block)\n\t\t\treturn 0;\n\t\tif (!bt_vector_add_ptr(&ctx->hash_blocks, block)) {\n\t\t\tfree(block);\n\t\t\treturn 0;\n\t\t}\n\t} else {\n\t\tblock = (unsigned char*)(ctx->hash_blocks.array[ctx->piece_count / BT_BLOCK_SIZE]);\n\t}\n\n\thash = &block[BT_HASH_SIZE * (ctx->piece_count % BT_BLOCK_SIZE)];\n\tSHA1_FINAL(ctx, hash); /* write the hash */\n\tctx->piece_count++;\n\treturn 1;\n}\n\n/**\n * A filepath and filesize information.\n */\ntypedef struct bt_file_info\n{\n\tuint64_t size;\n\tchar path[];\n} bt_file_info;\n\n/**\n * Add a file info into the batch of files of given torrent.\n *\n * @param ctx torrent algorithm context\n * @param path file path\n * @param filesize file size\n * @return non-zero on success, zero on fail\n */\nint bt_add_file(torrent_ctx* ctx, const char* path, uint64_t filesize)\n{\n\tsize_t len = strlen(path);\n\tbt_file_info* info = (bt_file_info*)malloc(sizeof(uint64_t) + len + 1);\n\tif (info == NULL) {\n\t\tctx->error = 1;\n\t\treturn 0;\n\t}\n\n\tinfo->size = filesize;\n\tmemcpy(info->path, path, len + 1);\n\tif (!bt_vector_add_ptr(&ctx->files, info)) {\n\t\tfree(info);\n\t\treturn 0;\n\t}\n\n\t/* recalculate piece length (but only if hashing not started yet) */\n\tif (ctx->piece_count == 0 && ctx->index == 0) {\n\t\t/* note: in case of batch of files should use a total batch size */\n\t\tctx->piece_length = bt_default_piece_length(filesize, ctx->options & BT_OPT_TRANSMISSION);\n\t}\n\treturn 1;\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid bt_update(torrent_ctx* ctx, const void* msg, size_t size)\n{\n\tconst unsigned char* pmsg = (const unsigned char*)msg;\n\tsize_t rest = (size_t)(ctx->piece_length - ctx->index);\n\tassert(ctx->index < ctx->piece_length);\n\n\twhile (size > 0) {\n\t\tsize_t left = (size < rest ? size : rest);\n\t\tSHA1_UPDATE(ctx, pmsg, left);\n\t\tif (size < rest) {\n\t\t\tctx->index += left;\n\t\t\tbreak;\n\t\t}\n\t\tbt_store_piece_sha1(ctx);\n\t\tSHA1_INIT(ctx);\n\t\tctx->index = 0;\n\n\t\tpmsg += rest;\n\t\tsize -= rest;\n\t\trest = ctx->piece_length;\n\t}\n}\n\n/**\n * Finalize hashing and optionally store calculated hash into the given array.\n * If the result parameter is NULL, the hash is not stored, but it is\n * accessible by bt_get_btih().\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result pointer to the array store message hash into\n */\nvoid bt_final(torrent_ctx* ctx, unsigned char result[20])\n{\n\tif (ctx->index > 0) {\n\t\tbt_store_piece_sha1(ctx); /* flush buffered data */\n\t}\n\n\tbt_generate_torrent(ctx);\n\tif (result) memcpy(result, ctx->btih, btih_hash_size);\n}\n\n/* BitTorrent functions */\n\n/**\n * Grow, if needed, the torrent_str buffer to ensure it contains\n * at least (length + 1) characters.\n *\n * @param ctx the torrent algorithm context\n * @param length length of the string, the allocated buffer must contain\n * @return 1 on success, 0 on error\n */\nstatic int bt_str_ensure_length(torrent_ctx* ctx, size_t length)\n{\n\tchar* new_str;\n\tif (ctx->error)\n\t\treturn 0;\n\tif (length >= ctx->content.allocated) {\n\t\tlength++; /* allocate one character more */\n\t\tif (length < 64) length = 64;\n\t\telse length = (length + 255) & ~255;\n\t\tnew_str = (char*)realloc(ctx->content.str, length);\n\t\tif (new_str == NULL) {\n\t\t\tctx->error = 1;\n\t\t\tctx->content.allocated = 0;\n\t\t\treturn 0;\n\t\t}\n\t\tctx->content.str = new_str;\n\t\tctx->content.allocated = length;\n\t}\n\treturn 1;\n}\n\n/**\n * Append a null-terminated string to the string string buffer.\n *\n * @param ctx the torrent algorithm context\n * @param text the null-terminated string to append\n */\nstatic void bt_str_append(torrent_ctx* ctx, const char* text)\n{\n\tsize_t length = strlen(text);\n\tif (!bt_str_ensure_length(ctx, ctx->content.length + length + 1))\n\t\treturn;\n\tassert(ctx->content.str != 0);\n\tmemcpy(ctx->content.str + ctx->content.length, text, length + 1);\n\tctx->content.length += length;\n}\n\n/**\n * B-encode given integer.\n *\n * @param ctx the torrent algorithm context\n * @param name B-encoded string to prepend the number or NULL\n * @param number the integer to output\n */\nstatic void bt_bencode_int(torrent_ctx* ctx, const char* name, uint64_t number)\n{\n\tchar* p;\n\tif (name)\n\t\tbt_str_append(ctx, name);\n\n\t/* add up to 20 digits and 2 letters */\n\tif (!bt_str_ensure_length(ctx, ctx->content.length + 22))\n\t\treturn;\n\tp = ctx->content.str + ctx->content.length;\n\t*(p++) = 'i';\n\tp += rhash_sprintI64(p, number);\n\t*(p++) = 'e';\n\t*p = '\\0'; /* terminate string with \\0 */\n\n\tctx->content.length = (p - ctx->content.str);\n}\n\n/**\n * B-encode a string.\n *\n * @param ctx the torrent algorithm context\n * @param name B-encoded string to prepend or NULL\n * @param str the string to encode\n */\nstatic void bt_bencode_str(torrent_ctx* ctx, const char* name, const char* str)\n{\n\tconst size_t string_length = strlen(str);\n\tint number_length;\n\tchar* p;\n\n\tif (name)\n\t\tbt_str_append(ctx, name);\n\tif (!bt_str_ensure_length(ctx, ctx->content.length + string_length + 21))\n\t\treturn;\n\tp = ctx->content.str + ctx->content.length;\n\tp += (number_length = rhash_sprintI64(p, string_length));\n\tctx->content.length += string_length + number_length + 1;\n\n\t*(p++) = ':';\n\tmemcpy(p, str, string_length + 1); /* copy with trailing '\\0' */\n}\n\n/**\n * B-encode array of SHA1 hashes of file pieces.\n *\n * @param ctx pointer to the torrent structure containing SHA1 hashes\n */\nstatic void bt_bencode_pieces(torrent_ctx* ctx)\n{\n\tconst size_t pieces_length = ctx->piece_count * BT_HASH_SIZE;\n\tsize_t bytes_left, i;\n\tint number_length;\n\tchar* p;\n\n\tif (!bt_str_ensure_length(ctx, ctx->content.length + pieces_length + 21))\n\t\treturn;\n\tp = ctx->content.str + ctx->content.length;\n\tp += (number_length = rhash_sprintI64(p, pieces_length));\n\tctx->content.length += pieces_length + number_length + 1;\n\n\t*(p++) = ':';\n\tp[pieces_length] = '\\0'; /* terminate with \\0 just in case */\n\n\tfor (bytes_left = pieces_length, i = 0; bytes_left > 0; i++)\n\t{\n\t\tsize_t size = (bytes_left < BT_BLOCK_SIZE_IN_BYTES ? bytes_left : BT_BLOCK_SIZE_IN_BYTES);\n\t\tmemcpy(p, ctx->hash_blocks.array[i], size);\n\t\tbytes_left -= size;\n\t\tp += size;\n\t}\n}\n\n/**\n * Calculate default torrent piece length, using uTorrent algorithm.\n * Algorithm:\n *   piece_length = 16K for total_size < 16M,\n *   piece_length = 8M for total_size >= 4G,\n *   piece_length = top_bit(total_size) / 512 otherwise.\n *\n * @param total_size total torrent batch size\n * @return piece length used by torrent file\n */\nstatic size_t utorr_piece_length(uint64_t total_size)\n{\n\tsize_t size = (size_t)(total_size >> 9) | 16384;\n\tsize_t hi_bit;\n\tfor (hi_bit = 8388608; hi_bit > size; hi_bit >>= 1);\n\treturn hi_bit;\n}\n\n#define MB I64(1048576)\n\n/**\n * Calculate default torrent piece length, using transmission algorithm.\n * Algorithm:\n *   piece_length = (size >= 2G ? 2M : size >= 1G ? 1M :\n *       size >= 512M ? 512K : size >= 350M ? 256K :\n *       size >= 150M ? 128K : size >= 50M ? 64K : 32K);\n *\n * @param total_size total torrent batch size\n * @return piece length used by torrent file\n */\nstatic size_t transmission_piece_length(uint64_t total_size)\n{\n\tstatic const uint64_t sizes[6] = { 50 * MB, 150 * MB, 350 * MB, 512 * MB, 1024 * MB, 2048 * MB };\n\tint i;\n\tfor (i = 0; i < 6 && total_size >= sizes[i]; i++);\n\treturn (32 * 1024) << i;\n}\n\nsize_t bt_default_piece_length(uint64_t total_size, int transmission)\n{\n\treturn (transmission ?\n\t\ttransmission_piece_length(total_size) : utorr_piece_length(total_size));\n}\n\n/* get file basename */\nstatic const char* bt_get_basename(const char* path)\n{\n\tconst char* p = strchr(path, '\\0') - 1;\n\tfor (; p >= path && *p != '/' && *p != '\\\\'; p--);\n\treturn (p + 1);\n}\n\n/* extract batchname from the path, modifies the path buffer */\nstatic const char* get_batch_name(char* path)\n{\n\tchar* p = (char*)bt_get_basename(path) - 1;\n\tfor (; p > path && (*p == '/' || *p == '\\\\'); p--) *p = 0;\n\tif (p <= path) return \"BATCH_DIR\";\n\treturn bt_get_basename(path);\n}\n\n/* write file size and path */\nstatic void bt_file_info_append(torrent_ctx* ctx, const char* length_name,\n\tconst char* path_name, bt_file_info* info)\n{\n\tbt_bencode_int(ctx, length_name, info->size);\n\t/* store the file basename */\n\tbt_bencode_str(ctx, path_name, bt_get_basename(info->path));\n}\n\n/**\n * Generate torrent file content\n * @see http://wiki.theory.org/BitTorrentSpecification\n *\n * @param ctx the torrent algorithm context\n */\nstatic void bt_generate_torrent(torrent_ctx* ctx)\n{\n\tuint64_t total_size = 0;\n\tsize_t info_start_pos;\n\n\tassert(ctx->content.str == NULL);\n\n\tif (ctx->piece_length == 0) {\n\t\tif (ctx->files.size == 1) {\n\t\t\ttotal_size = ((bt_file_info*)ctx->files.array[0])->size;\n\t\t}\n\t\tctx->piece_length = bt_default_piece_length(total_size, ctx->options & BT_OPT_TRANSMISSION);\n\t}\n\n\tif ((ctx->options & BT_OPT_INFOHASH_ONLY) == 0) {\n\t\t/* write the torrent header */\n\t\tbt_str_append(ctx, \"d\");\n\t\tif (ctx->announce.array && ctx->announce.size > 0) {\n\t\t\tbt_bencode_str(ctx, \"8:announce\", ctx->announce.array[0]);\n\n\t\t\t/* if more than one announce url */\n\t\t\tif (ctx->announce.size > 1) {\n\t\t\t\t/* add the announce-list key-value pair */\n\t\t\t\tsize_t i;\n\t\t\t\tbt_str_append(ctx, \"13:announce-listll\");\n\n\t\t\t\tfor (i = 0; i < ctx->announce.size; i++) {\n\t\t\t\t\tif (i > 0) {\n\t\t\t\t\t\tbt_str_append(ctx, \"el\");\n\t\t\t\t\t}\n\t\t\t\t\tbt_bencode_str(ctx, 0, ctx->announce.array[i]);\n\t\t\t\t}\n\t\t\t\tbt_str_append(ctx, \"ee\");\n\t\t\t}\n\t\t}\n\n\t\tif (ctx->program_name) {\n\t\t\tbt_bencode_str(ctx, \"10:created by\", ctx->program_name);\n\t\t}\n\t\tbt_bencode_int(ctx, \"13:creation date\", (uint64_t)time(NULL));\n\n\t\tbt_str_append(ctx, \"8:encoding5:UTF-8\");\n\t}\n\n\t/* write the essential for BTIH part of the torrent file */\n\n\tbt_str_append(ctx, \"4:infod\"); /* start the info dictionary */\n\tinfo_start_pos = ctx->content.length - 1;\n\n\tif (ctx->files.size > 1) {\n\t\tsize_t i;\n\n\t\t/* process batch torrent */\n\t\tbt_str_append(ctx, \"5:filesl\"); /* start list of files */\n\n\t\t/* write length and path for each file in the batch */\n\t\tfor (i = 0; i < ctx->files.size; i++) {\n\t\t\tbt_file_info_append(ctx, \"d6:length\", \"4:pathl\",\n\t\t\t\t(bt_file_info*)ctx->files.array[i]);\n\t\t\tbt_str_append(ctx, \"ee\");\n\t\t}\n\t\t/* note: get_batch_name modifies path, so should be called here */\n\t\tbt_bencode_str(ctx, \"e4:name\", get_batch_name(\n\t\t\t((bt_file_info*)ctx->files.array[0])->path));\n\t}\n\telse if (ctx->files.size > 0) {\n\t\t/* write size and basename of the first file */\n\t\t/* in the non-batch mode other files are ignored */\n\t\tbt_file_info_append(ctx, \"6:length\", \"4:name\",\n\t\t\t(bt_file_info*)ctx->files.array[0]);\n\t}\n\n\tbt_bencode_int(ctx, \"12:piece length\", ctx->piece_length);\n\tbt_str_append(ctx, \"6:pieces\");\n\tbt_bencode_pieces(ctx);\n\n\tif (ctx->options & BT_OPT_PRIVATE) {\n\t\tbt_str_append(ctx, \"7:privatei1e\");\n\t} else if (ctx->options & BT_OPT_TRANSMISSION) {\n\t\tbt_str_append(ctx, \"7:privatei0e\");\n\t}\n\tbt_str_append(ctx, \"ee\");\n\n\t/* calculate BTIH */\n\tSHA1_INIT(ctx);\n\tif (ctx->content.str) {\n\t\tSHA1_UPDATE(ctx, (unsigned char*)ctx->content.str + info_start_pos,\n\t\t\tctx->content.length - info_start_pos - 1);\n\t}\n\tSHA1_FINAL(ctx, ctx->btih);\n}\n\n/* Getters/Setters */\n\n/**\n * Get BTIH (BitTorrent Info Hash) value.\n *\n * @param ctx the torrent algorithm context\n * @return the 20-bytes long BTIH value\n */\nunsigned char* bt_get_btih(torrent_ctx* ctx)\n{\n\treturn ctx->btih;\n}\n\n/**\n * Set the torrent algorithm options.\n *\n * @param ctx the torrent algorithm context\n * @param options the options to set\n */\nvoid bt_set_options(torrent_ctx* ctx, unsigned options)\n{\n\tctx->options = options;\n}\n\n#if defined(__STRICT_ANSI__)\n/* define strdup for gcc -ansi */\nstatic char* bt_strdup(const char* str)\n{\n\tsize_t len = strlen(str);\n\tchar* res = (char*)malloc(len + 1);\n\tif (res) memcpy(res, str, len + 1);\n\treturn res;\n}\n#define strdup bt_strdup\n#endif /* __STRICT_ANSI__ */\n\n/**\n * Set optional name of the program generating the torrent\n * for storing into torrent file.\n *\n * @param ctx the torrent algorithm context\n * @param name the program name\n * @return non-zero on success, zero on error\n */\nint bt_set_program_name(torrent_ctx* ctx, const char* name)\n{\n\tctx->program_name = strdup(name);\n\treturn (ctx->program_name != NULL);\n}\n\n/**\n * Set length of a file piece.\n *\n * @param ctx the torrent algorithm context\n * @param piece_length the piece length in bytes\n */\nvoid bt_set_piece_length(torrent_ctx* ctx, size_t piece_length)\n{\n\tctx->piece_length = piece_length;\n}\n\n/**\n * Set length of a file piece by the total batch size.\n *\n * @param ctx the torrent algorithm context\n * @param total_size total batch size\n */\nvoid bt_set_total_batch_size(torrent_ctx* ctx, uint64_t total_size)\n{\n\tctx->piece_length = bt_default_piece_length(total_size, ctx->options & BT_OPT_TRANSMISSION);\n}\n\n/**\n * Add a tracker announce-URL to the torrent file.\n *\n * @param ctx the torrent algorithm context\n * @param announce_url the announce URL of the tracker\n * @return non-zero on success, zero on error\n */\nint bt_add_announce(torrent_ctx* ctx, const char* announce_url)\n{\n\tchar* url_copy;\n\tif (!announce_url || announce_url[0] == '\\0') return 0;\n\turl_copy = strdup(announce_url);\n\tif (!url_copy) return 0;\n\tif (bt_vector_add_ptr(&ctx->announce, url_copy))\n\t\treturn 1;\n\tfree(url_copy);\n\treturn 0;\n}\n\n/**\n * Get the content of generated torrent file.\n *\n * @param ctx the torrent algorithm context\n * @param pstr pointer to pointer receiving the buffer with file content\n * @return length of the torrent file content\n */\nsize_t bt_get_text(torrent_ctx* ctx, char** pstr)\n{\n\tassert(ctx->content.str);\n\t*pstr = ctx->content.str;\n\treturn ctx->content.length;\n}\n\n#if !defined(NO_IMPORT_EXPORT)\n\n# define EXPORT_ALIGNER 7\n# define GET_EXPORT_ALIGNED(size) (((size) + EXPORT_ALIGNER) & ~EXPORT_ALIGNER)\n# define GET_EXPORT_PADDING(size) (-(size) & EXPORT_ALIGNER)\n# define GET_EXPORT_STR_LEN(length) GET_EXPORT_ALIGNED((length) + 1)\n# define GET_EXPORT_SIZED_STR_LEN(length) GET_EXPORT_STR_LEN((length) + sizeof(size_t))\n# define IS_EXPORT_ALIGNED(size) (((size) & EXPORT_ALIGNER) == 0)\n# define BT_CTX_OSSL_FLAG 0x10\n\nstatic void bt_export_str(char* out, const char* str, size_t length)\n{\n\tassert(!!out);\n\t*(size_t*)(out) = length;\n\tout += sizeof(size_t);\n\tmemcpy(out, str, length + 1);\n}\n\ntypedef struct bt_export_header {\n\tsize_t torrent_ctx_size;\n\tsize_t files_size;\n\tsize_t announce_size;\n\tsize_t program_name_length;\n\tsize_t content_length;\n} bt_export_header;\n\n/**\n * Export algorithm context to a memory region, or calculate the\n * size required for context export.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param out pointer to the memory region or NULL\n * @param size size of memory region\n * @return the size of the exported data on success, 0 on fail.\n */\nsize_t bt_export(const torrent_ctx* ctx, void* out, size_t size)\n{\n\tconst size_t head_size = sizeof(bt_export_header);\n\tconst size_t ctx_head_size = offsetof(torrent_ctx, hash_blocks);\n\tconst size_t hashes_size = ctx->piece_count * BT_HASH_SIZE;\n\tsize_t exported_size = head_size + ctx_head_size + hashes_size;\n\tconst size_t padding_size = GET_EXPORT_PADDING(exported_size);\n\tconst size_t program_name_length = (ctx->program_name ? strlen(ctx->program_name) : 0);\n\tchar* out_ptr = (char*)out;\n\tsize_t i;\n\tassert((exported_size + padding_size) == GET_EXPORT_ALIGNED(exported_size));\n\tif (out_ptr) {\n\t\tbt_export_header* header = (bt_export_header*)out_ptr;\n\t\tsize_t hash_data_left = hashes_size;\n\t\tif (size < exported_size)\n\t\t\treturn 0;\n\t\theader->torrent_ctx_size = sizeof(torrent_ctx);\n\t\theader->files_size = ctx->files.size;\n\t\theader->announce_size = ctx->announce.size;\n\t\theader->program_name_length = program_name_length;\n\t\theader->content_length = ctx->content.length;\n\t\tout_ptr += head_size;\n\n\t\tmemcpy(out_ptr, ctx, ctx_head_size);\n\t\tout_ptr += ctx_head_size;\n\n\t\tfor (i = 0; i < ctx->hash_blocks.size && hash_data_left; i++) {\n\t\t\tsize_t left = (hash_data_left < BT_BLOCK_SIZE_IN_BYTES ? hash_data_left : BT_BLOCK_SIZE_IN_BYTES);\n\t\t\tmemcpy(out_ptr, ctx->hash_blocks.array[i], left);\n\t\t\tout_ptr += left;\n\t\t\thash_data_left -= left;\n\t\t}\n\t\tout_ptr += padding_size;\n\t}\n\texported_size += padding_size;\n\tassert(IS_EXPORT_ALIGNED(exported_size));\n\n\tfor (i = 0; i < ctx->files.size; i++) {\n\t\tbt_file_info* info = (bt_file_info*)(ctx->files.array[i]);\n\t\tsize_t length = strlen(info->path);\n\t\tconst size_t aligned_length = GET_EXPORT_SIZED_STR_LEN(length);\n\t\tif (!length)\n\t\t\tcontinue;\n\t\texported_size += sizeof(uint64_t) + aligned_length;\n\t\tif (out_ptr) {\n\t\t\tif (size < exported_size)\n\t\t\t\treturn 0;\n\t\t\t*(uint64_t*)out_ptr = info->size;\n\t\t\tout_ptr += sizeof(uint64_t);\n\t\t\tbt_export_str(out_ptr, info->path, length);\n\t\t\tout_ptr += aligned_length;\n\t\t}\n\t}\n\tassert(IS_EXPORT_ALIGNED(exported_size));\n\n\tfor (i = 0; i < ctx->announce.size; i++) {\n\t\tsize_t length = strlen(ctx->announce.array[i]);\n\t\tconst size_t aligned_length = GET_EXPORT_SIZED_STR_LEN(length);\n\t\tif (!length)\n\t\t\tcontinue;\n\t\texported_size += aligned_length;\n\t\tif (out_ptr) {\n\t\t\tif (size < exported_size)\n\t\t\t\treturn 0;\n\t\t\tbt_export_str(out_ptr, ctx->announce.array[i], length);\n\t\t\tout_ptr += aligned_length;\n\t\t}\n\t}\n\tassert(IS_EXPORT_ALIGNED(exported_size));\n\n\tif (program_name_length > 0) {\n\t\tconst size_t aligned_length = GET_EXPORT_STR_LEN(program_name_length);\n\t\texported_size += aligned_length;\n\t\tif (out_ptr) {\n\t\t\tif (size < exported_size)\n\t\t\t\treturn 0;\n\t\t\tstrcpy(out_ptr, ctx->program_name);\n\t\t\tout_ptr += aligned_length;\n\t\t}\n\t\tassert(IS_EXPORT_ALIGNED(exported_size));\n\t}\n\n\tif (ctx->content.length > 0) {\n\t\tconst size_t aligned_length = GET_EXPORT_STR_LEN(ctx->content.length);\n\t\texported_size += aligned_length;\n\t\tif (out_ptr) {\n\t\t\tif (size < exported_size)\n\t\t\t\treturn 0;\n\t\t\tassert(ctx->content.str != NULL);\n\t\t\tmemcpy(out_ptr, ctx->content.str, ctx->content.length + 1);\n\t\t\tout_ptr += aligned_length;\n\t\t}\n\t\tassert(IS_EXPORT_ALIGNED(exported_size));\n\t}\n\tassert(!out || (size_t)(out_ptr - (char*)out) == exported_size);\n\n#if defined(USE_OPENSSL)\n\tif (out_ptr && ARE_OPENSSL_METHODS(ctx->sha1_methods)) {\n\t\tsize_t* error_ptr = (size_t*)((char*)out + head_size + offsetof(torrent_ctx, error));\n\t\t*error_ptr |= BT_CTX_OSSL_FLAG;\n\t\tRHASH_ASSERT(sizeof(*error_ptr) == sizeof(ctx->error));\n\t}\n#endif\n\treturn exported_size;\n}\n\n/**\n * Import algorithm context from a memory region.\n *\n * @param ctx pointer to the algorithm context\n * @param in pointer to the data to import\n * @param size size of data to import\n * @return the size of the imported data on success, 0 on fail.\n */\nsize_t bt_import(torrent_ctx* ctx, const void* in, size_t size)\n{\n\tconst size_t head_size = sizeof(bt_export_header);\n\tconst size_t ctx_head_size = offsetof(torrent_ctx, hash_blocks);\n\tsize_t imported_size = head_size + ctx_head_size;\n\tconst char* in_ptr = (const char*)in;\n\tsize_t padding_size;\n\tsize_t hash_data_left;\n\tsize_t length;\n\tsize_t i;\n\tconst bt_export_header* header = (const bt_export_header*)in_ptr;\n\tif (size < imported_size)\n\t\treturn 0;\n\tif (header->torrent_ctx_size != sizeof(torrent_ctx))\n\t\treturn 0;\n\tin_ptr += sizeof(bt_export_header);\n\n\tmemset(ctx, 0, sizeof(torrent_ctx));\n\tmemcpy(ctx, in_ptr, ctx_head_size);\n\tin_ptr += ctx_head_size;\n\n\thash_data_left = ctx->piece_count * BT_HASH_SIZE;\n\timported_size += hash_data_left;\n\tpadding_size = GET_EXPORT_PADDING(imported_size);\n\timported_size += padding_size;\n\tassert(IS_EXPORT_ALIGNED(imported_size));\n\tif (size < imported_size)\n\t\treturn 0;\n\n\twhile (hash_data_left) {\n\t\tsize_t left = (hash_data_left < BT_BLOCK_SIZE_IN_BYTES ? hash_data_left : BT_BLOCK_SIZE_IN_BYTES);\n\t\tunsigned char* block = (unsigned char*)malloc(BT_BLOCK_SIZE_IN_BYTES);\n\t\tif (!block)\n\t\t\treturn 0;\n\t\tif (!bt_vector_add_ptr(&ctx->hash_blocks, block)) {\n\t\t\tfree(block);\n\t\t\treturn 0;\n\t\t}\n\t\tmemcpy(block, in_ptr, left);\n\t\tin_ptr += left;\n\t\thash_data_left -= left;\n\t}\n\tin_ptr += padding_size;\n\tassert((size_t)(in_ptr - (char*)in) == imported_size);\n\tassert(IS_EXPORT_ALIGNED(imported_size));\n\n\tfor (i = 0; i < header->files_size; i++) {\n\t\tuint64_t filesize;\n\t\timported_size += sizeof(uint64_t);\n\t\tif (size < (imported_size + sizeof(size_t)))\n\t\t\treturn 0;\n\t\tfilesize = *(uint64_t*)in_ptr;\n\t\tin_ptr += sizeof(uint64_t);\n\t\tlength = *(size_t*)in_ptr;\n\t\timported_size += GET_EXPORT_SIZED_STR_LEN(length);\n\t\tif (!length || size < imported_size)\n\t\t\treturn 0;\n\t\tif (!bt_add_file(ctx, in_ptr + sizeof(size_t), filesize))\n\t\t\treturn 0;\n\t\tin_ptr += GET_EXPORT_SIZED_STR_LEN(length);\n\t}\n\tassert((size_t)(in_ptr - (char*)in) == imported_size);\n\tassert(IS_EXPORT_ALIGNED(imported_size));\n\n\tfor (i = 0; i < header->announce_size; i++) {\n\t\tif (size < (imported_size + sizeof(size_t)))\n\t\t\treturn 0;\n\t\tlength = *(size_t*)in_ptr;\n\t\timported_size += GET_EXPORT_SIZED_STR_LEN(length);\n\t\tif (!length || size < imported_size)\n\t\t\treturn 0;\n\t\tif (!bt_add_announce(ctx, in_ptr + sizeof(size_t)))\n\t\t\treturn 0;\n\t\tin_ptr += GET_EXPORT_SIZED_STR_LEN(length);\n\t}\n\tassert((size_t)(in_ptr - (char*)in) == imported_size);\n\tassert(IS_EXPORT_ALIGNED(imported_size));\n\n\tlength = header->program_name_length;\n\tif (length) {\n\t\timported_size += GET_EXPORT_STR_LEN(length);\n\t\tif (size < imported_size)\n\t\t\treturn 0;\n\t\tif (!bt_set_program_name(ctx, in_ptr))\n\t\t\treturn 0;\n\t\tin_ptr += GET_EXPORT_STR_LEN(length);\n\t\tassert((size_t)(in_ptr - (char*)in) == imported_size);\n\t\tassert(IS_EXPORT_ALIGNED(imported_size));\n\t}\n\n#if defined(USE_OPENSSL)\n\t/* must restore ctx->error flag before calling bt_str_ensure_length() */\n\tif ((ctx->error & BT_CTX_OSSL_FLAG) != 0) {\n\t\tctx->error &= ~BT_CTX_OSSL_FLAG;\n\t\trhash_load_sha1_methods(&ctx->sha1_methods, METHODS_OPENSSL);\n\t} else {\n\t\trhash_load_sha1_methods(&ctx->sha1_methods, METHODS_RHASH);\n\t}\n#endif\n\n\tlength = header->content_length;\n\tif (length) {\n\t\timported_size += GET_EXPORT_STR_LEN(length);\n\t\tif (size < imported_size)\n\t\t\treturn 0;\n\t\tif (!bt_str_ensure_length(ctx, length))\n\t\t\treturn 0;\n\t\tmemcpy(ctx->content.str, in_ptr, length);\n\t\tin_ptr += GET_EXPORT_STR_LEN(length);\n\t\tassert((size_t)(in_ptr - (char*)in) == imported_size);\n\t\tassert(IS_EXPORT_ALIGNED(imported_size));\n\t}\n\treturn imported_size;\n}\n#endif /* !defined(NO_IMPORT_EXPORT) */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/torrent.h",
    "content": "﻿/* torrent.h */\n#ifndef TORRENT_H\n#define TORRENT_H\n#include \"sha1.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define btih_hash_size  20\n\n/* vector structure */\ntypedef struct torrent_vect\n{\n\tvoid** array;     /* array of elements of the vector */\n\tsize_t size;      /* vector size */\n\tsize_t allocated; /* number of allocated elements */\n} torrent_vect;\n\n/* a binary string */\ntypedef struct torrent_str\n{\n\tchar* str;\n\tsize_t length;\n\tsize_t allocated;\n} torrent_str;\n\n/* BitTorrent algorithm context */\ntypedef struct torrent_ctx\n{\n\tunsigned char btih[20]; /* resulting BTIH hash sum */\n\tunsigned options;       /* algorithm options */\n\tsha1_ctx sha1_context;  /* context for hashing current file piece */\n#if defined(USE_OPENSSL) || defined(OPENSSL_RUNTIME)\n\tunsigned long reserved; /* need more space for OpenSSL SHA1 context */\n#endif\n\tsize_t index;             /* byte index in the current piece */\n\tsize_t piece_length;      /* length of a torrent file piece */\n\tsize_t piece_count;       /* the number of pieces processed */\n\tsize_t error;             /* non-zero if error occurred, zero otherwise */\n\ttorrent_vect hash_blocks; /* array of blocks storing SHA1 hashes */\n\ttorrent_vect files;       /* names of files in a torrent batch */\n\ttorrent_vect announce;    /* announce URLs */\n\tchar* program_name;       /* the name of the program */\n\n\ttorrent_str content;      /* the content of generated torrent file */\n#if defined(USE_OPENSSL) || defined(OPENSSL_RUNTIME)\n\trhash_hashing_methods sha1_methods;\n#endif\n} torrent_ctx;\n\nvoid bt_init(torrent_ctx* ctx);\nvoid bt_update(torrent_ctx* ctx, const void* msg, size_t size);\nvoid bt_final(torrent_ctx* ctx, unsigned char result[20]);\nvoid bt_cleanup(torrent_ctx* ctx);\n\n#if !defined(NO_IMPORT_EXPORT)\nsize_t bt_export(const torrent_ctx* ctx, void* out, size_t size);\nsize_t bt_import(torrent_ctx* ctx, const void* in, size_t size);\n#endif /* !defined(NO_IMPORT_EXPORT) */\n\nunsigned char* bt_get_btih(torrent_ctx* ctx);\nsize_t bt_get_text(torrent_ctx* ctx, char** pstr);\n\n/* possible options */\n#define BT_OPT_PRIVATE 1\n#define BT_OPT_INFOHASH_ONLY 2\n#define BT_OPT_TRANSMISSION 4\n\nvoid bt_set_options(torrent_ctx* ctx, unsigned options);\nint  bt_add_file(torrent_ctx* ctx, const char* path, uint64_t filesize);\nint  bt_add_announce(torrent_ctx* ctx, const char* announce_url);\nint  bt_set_program_name(torrent_ctx* ctx, const char* name);\nvoid bt_set_piece_length(torrent_ctx* ctx, size_t piece_length);\nvoid bt_set_total_batch_size(torrent_ctx* ctx, uint64_t total_size);\nsize_t bt_default_piece_length(uint64_t total_size, int transmission);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* TORRENT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/tth.c",
    "content": "﻿/* tth.c - calculate TTH (Tiger Tree Hash) function.\n *\n * Copyright (c) 2007, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"tth.h\"\n#include \"byte_order.h\"\n#include <stddef.h>\n#include <string.h>\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_tth_init(tth_ctx* ctx)\n{\n\trhash_tiger_init(&ctx->tiger);\n\tctx->tiger.message[ ctx->tiger.length++ ] = 0x00;\n\tctx->block_count = 0;\n}\n\n/**\n * The core transformation.\n *\n * @param ctx algorithm state\n */\nstatic void rhash_tth_process_block(tth_ctx* ctx)\n{\n\tuint64_t it;\n\tunsigned pos = 0;\n\tunsigned char msg[24];\n\n\tfor (it = 1; it & ctx->block_count; it <<= 1) {\n\t\trhash_tiger_final(&ctx->tiger, msg);\n\t\trhash_tiger_init(&ctx->tiger);\n\t\tctx->tiger.message[ctx->tiger.length++] = 0x01;\n\t\trhash_tiger_update(&ctx->tiger, (unsigned char*)(ctx->stack + pos), 24);\n\t\t/* note: we can cut this step, if the previous rhash_tiger_final saves directly to ctx->tiger.message+25; */\n\t\trhash_tiger_update(&ctx->tiger, msg, 24);\n\t\tpos += 3;\n\t}\n\trhash_tiger_final(&ctx->tiger, (unsigned char*)(ctx->stack + pos));\n\tctx->block_count++;\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_tth_update(tth_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tsize_t rest = 1025 - (size_t)ctx->tiger.length;\n\tfor (;;) {\n\t\tif (size < rest) rest = size;\n\t\trhash_tiger_update(&ctx->tiger, msg, rest);\n\t\tmsg += rest;\n\t\tsize -= rest;\n\t\tif (ctx->tiger.length < 1025) {\n\t\t\treturn;\n\t\t}\n\n\t\t/* process block hash */\n\t\trhash_tth_process_block(ctx);\n\n\t\t/* init block hash */\n\t\trhash_tiger_init(&ctx->tiger);\n\t\tctx->tiger.message[ ctx->tiger.length++ ] = 0x00;\n\t\trest = 1024;\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_tth_final(tth_ctx* ctx, unsigned char result[24])\n{\n\tuint64_t it = 1;\n\tunsigned pos = 0;\n\tunsigned char msg[24];\n\tconst unsigned char* last_message;\n\n\t/* process the bytes left in the context buffer */\n\tif (ctx->tiger.length > 1 || ctx->block_count == 0) {\n\t\trhash_tth_process_block(ctx);\n\t}\n\n\tfor (; it < ctx->block_count && (it & ctx->block_count) == 0; it <<= 1) pos += 3;\n\tlast_message = (unsigned char*)(ctx->stack + pos);\n\n\tfor (it <<= 1; it <= ctx->block_count; it <<= 1) {\n\t\t/* merge TTH sums in the tree */\n\t\tpos += 3;\n\t\tif (it & ctx->block_count) {\n\t\t\trhash_tiger_init(&ctx->tiger);\n\t\t\tctx->tiger.message[ ctx->tiger.length++ ] = 0x01;\n\t\t\trhash_tiger_update(&ctx->tiger, (unsigned char*)(ctx->stack + pos), 24);\n\t\t\trhash_tiger_update(&ctx->tiger, last_message, 24);\n\n\t\t\trhash_tiger_final(&ctx->tiger, msg);\n\t\t\tlast_message = msg;\n\t\t}\n\t}\n\n\t/* save result hash */\n\tmemcpy(ctx->tiger.hash, last_message, tiger_hash_length);\n\tif (result) memcpy(result, last_message, tiger_hash_length);\n}\n\n#if !defined(NO_IMPORT_EXPORT)\nstatic size_t tth_get_stack_size(uint64_t block_count)\n{\n\tsize_t stack_size = 0;\n\tfor (; block_count; block_count >>= 1)\n\t\tstack_size += 24;\n\treturn stack_size;\n}\n\n/**\n * Export tth context to a memory region, or calculate the\n * size required for context export.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param out pointer to the memory region or NULL\n * @param size size of memory region\n * @return the size of the exported data on success, 0 on fail.\n */\nsize_t rhash_tth_export(const tth_ctx* ctx, void* out, size_t size)\n{\n\tsize_t export_size = offsetof(tth_ctx, stack) +\n\t\ttth_get_stack_size(ctx->block_count);\n\tif (out != NULL) {\n\t\tif (size < export_size)\n\t\t\treturn 0;\n\t\tmemcpy(out, ctx, export_size);\n\t}\n\treturn export_size;\n}\n\n/**\n * Import tth context from a memory region.\n *\n * @param ctx pointer to the algorithm context\n * @param in pointer to the data to import\n * @param size size of data to import\n * @return the size of the imported data on success, 0 on fail.\n */\nsize_t rhash_tth_import(tth_ctx* ctx, const void* in, size_t size)\n{\n\tconst size_t head_size = offsetof(tth_ctx, stack);\n\tsize_t stack_size;\n\tif (size < head_size)\n\t\treturn 0;\n\tmemset(ctx, 0, sizeof(tth_ctx));\n\tmemcpy(ctx, in, head_size);\n\tstack_size = tth_get_stack_size(ctx->block_count);\n\tif (size < (head_size + stack_size))\n\t\treturn 0;\n\tmemcpy(ctx->stack, (const char*)in + head_size, stack_size);\n\treturn head_size + stack_size;\n}\n#endif /* !defined(NO_IMPORT_EXPORT) */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/tth.h",
    "content": "﻿#ifndef TTH_H\n#define TTH_H\n#include \"ustd.h\"\n#include \"tiger.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* algorithm context */\ntypedef struct tth_ctx\n{\n\ttiger_ctx tiger;       /* context used to hash tree leaves */\n\tuint64_t block_count;  /* number of processed blocks */\n\tuint64_t stack[64 * 3];\n} tth_ctx;\n\n/* hash functions */\n\nvoid rhash_tth_init(tth_ctx* ctx);\nvoid rhash_tth_update(tth_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_tth_final(tth_ctx* ctx, unsigned char result[24]);\n\n#if !defined(NO_IMPORT_EXPORT)\nsize_t rhash_tth_export(const tth_ctx* ctx, void* out, size_t size);\nsize_t rhash_tth_import(tth_ctx* ctx, const void* in, size_t size);\n#endif /* !defined(NO_IMPORT_EXPORT) */\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* TTH_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/ustd.h",
    "content": "﻿/* ustd.h common macros and includes */\n#ifndef LIBRHASH_USTD_H\n#define LIBRHASH_USTD_H\n\n#if _MSC_VER > 1000\n# include <stddef.h> /* size_t for vc6.0 */\n\n# if _MSC_VER >= 1600\n/* Visual Studio >= 2010 has stdint.h */\n#  include <stdint.h>\n# else\n  /* vc6.0 has bug with __int8, so using char instead */\n  typedef signed char       int8_t;\n  typedef signed __int16    int16_t;\n  typedef signed __int32    int32_t;\n  typedef signed __int64    int64_t;\n  typedef unsigned char     uint8_t;\n  typedef unsigned __int16  uint16_t;\n  typedef unsigned __int32  uint32_t;\n  typedef unsigned __int64  uint64_t;\n# endif /* _MSC_VER >= 1600 */\n\n/* disable warnings: The POSIX name for this item is deprecated. Use the ISO C++ conformant name. */\n# pragma warning(disable : 4996)\n\n#else /* _MSC_VER > 1000 */\n\n# include <stdint.h>\n# include <unistd.h>\n\n#endif /* _MSC_VER > 1000 */\n\n#endif /* LIBRHASH_USTD_H */\n\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/util.h",
    "content": "﻿/* util.h */\n#ifndef UTIL_H\n#define UTIL_H\n\n#include <stdlib.h> /* for aligned_alloc and __GLIBC__ version macros */\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* compile-time assert */\n#define RHASH_ASSERT(condition) (void)sizeof(char[1 - 2 * !(condition)])\n#define RHASH_COUNTOF(array) (sizeof(array) /  sizeof(*array))\n\n/* define atomic_compare_and_swap() */\n#if (defined(__GNUC__) && __GNUC__ >= 4 && (__GNUC__ > 4 || __GNUC_MINOR__ >= 1) \\\n\t&& defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) \\\n\t|| (defined(__INTEL_COMPILER) && !defined(_WIN32))\n/* atomic operations are defined by ICC and GCC >= 4.1, but by the later one supposedly not for ARM */\n/* note: ICC on ia64 platform possibly require ia64intrin.h, need testing */\n# define atomic_compare_and_swap(ptr, oldval, newval) __sync_val_compare_and_swap(ptr, oldval, newval)\n#elif defined(_MSC_VER)\n# define WIN32_LEAN_AND_MEAN\n# include <windows.h>\n# define atomic_compare_and_swap(ptr, oldval, newval) InterlockedCompareExchange(ptr, newval, oldval)\n#elif defined(__sun)\n# include <atomic.h>\n# define atomic_compare_and_swap(ptr, oldval, newval) atomic_cas_32(ptr, oldval, newval)\n#else\n/* fallback case */\n# define atomic_compare_and_swap(ptr, oldval, newval) { if (*(ptr) == (oldval)) *(ptr) = (newval); }\n# define NO_ATOMIC_BUILTINS\n#endif\n\n/* alignment macros */\n#define DEFAULT_ALIGNMENT 64\n#define ALIGN_SIZE_BY(size, align) (((size) + ((align) - 1)) & ~((align) - 1))\n#define IS_SIZE_ALIGNED_BY(size, align) (((size) & ((align) - 1)) == 0)\n#define IS_PTR_ALIGNED_BY(ptr, align) IS_SIZE_ALIGNED_BY((uintptr_t)(ptr), (align))\n\n/* define rhash_aligned_alloc() and rhash_aligned_free() */\n#if !defined(NO_WIN32_ALIGNED_ALLOC) && defined(_WIN32)\n\n# define HAS_WIN32_ALIGNED_ALLOC\n# include <malloc.h>\n# define rhash_aligned_alloc(alignment, size) _aligned_malloc((size), (alignment))\n# define rhash_aligned_free(ptr) _aligned_free(ptr)\n\n#elif !defined(NO_STDC_ALIGNED_ALLOC) && (__STDC_VERSION__ >= 201112L || defined(_ISOC11_SOURCE)) \\\n\t&& !defined(__APPLE__) && !defined(__HAIKU__) && !defined(__sun) \\\n\t&& (!defined(__GLIBC__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 15)) \\\n\t&& (!defined(__ANDROID_API__) || __ANDROID_API__ >= 28)\n\n# define HAS_STDC_ALIGNED_ALLOC\n# define rhash_aligned_alloc(alignment, size) aligned_alloc((alignment), ALIGN_SIZE_BY(size, alignment))\n# define rhash_aligned_free(ptr) free(ptr)\n\n#else /* defined(_WIN32) ... */\n\n# include \"ustd.h\" /* for _POSIX_VERSION macro */\n\n# if !defined(NO_POSIX_ALIGNED_ALLOC) && (_POSIX_VERSION >= 200112L || _XOPEN_SOURCE >= 600)\n\n#  define HAS_POSIX_ALIGNED_ALLOC\n#  define rhash_aligned_alloc(alignment, size) rhash_px_aalloc((alignment), ALIGN_SIZE_BY(size, sizeof(void*)))\n#  define rhash_aligned_free(ptr) free(ptr)\nvoid* rhash_px_aalloc(size_t size, size_t alignment);\n\n# else\n\n#  define HAS_GENERIC_ALIGNED_ALLOC\nvoid* rhash_aligned_alloc(size_t alignment, size_t size);\nvoid rhash_aligned_free(void* ptr);\n\n# endif /* !defined(NO_POSIX_ALIGNED_ALLOC) ... */\n#endif /* defined(_WIN32) ... */\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* UTIL_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/whirlpool.c",
    "content": "﻿/* whirlpool.c - an implementation of the Whirlpool Hash Function.\n *\n * Copyright (c) 2009, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n *\n * Documentation:\n * P. S. L. M. Barreto, V. Rijmen, ``The Whirlpool hashing function,''\n * NESSIE submission, 2000 (tweaked version, 2001)\n *\n * The algorithm is named after the Whirlpool Galaxy in Canes Venatici.\n */\n\n#include <string.h>\n#include \"byte_order.h\"\n#include \"whirlpool.h\"\n\n/**\n * Initialize context before calculating hash.\n *\n * @param ctx context to initialize\n */\nvoid rhash_whirlpool_init(struct whirlpool_ctx* ctx)\n{\n\tctx->length = 0;\n\tmemset(ctx->hash, 0, sizeof(ctx->hash));\n}\n\n/* Algorithm S-Box */\nextern uint64_t rhash_whirlpool_sbox[8][256];\n\n#define WHIRLPOOL_OP(src, shift) ( \\\n\trhash_whirlpool_sbox[0][(int)(src[ shift      & 7] >> 56)       ] ^ \\\n\trhash_whirlpool_sbox[1][(int)(src[(shift + 7) & 7] >> 48) & 0xff] ^ \\\n\trhash_whirlpool_sbox[2][(int)(src[(shift + 6) & 7] >> 40) & 0xff] ^ \\\n\trhash_whirlpool_sbox[3][(int)(src[(shift + 5) & 7] >> 32) & 0xff] ^ \\\n\trhash_whirlpool_sbox[4][(int)(src[(shift + 4) & 7] >> 24) & 0xff] ^ \\\n\trhash_whirlpool_sbox[5][(int)(src[(shift + 3) & 7] >> 16) & 0xff] ^ \\\n\trhash_whirlpool_sbox[6][(int)(src[(shift + 2) & 7] >>  8) & 0xff] ^ \\\n\trhash_whirlpool_sbox[7][(int)(src[(shift + 1) & 7]      ) & 0xff])\n\n/**\n * The core transformation. Process a 512-bit block.\n *\n * @param hash algorithm state\n * @param block the message block to process\n */\nstatic void rhash_whirlpool_process_block(uint64_t* hash, uint64_t* p_block)\n{\n\tint i;                /* loop counter */\n\tuint64_t K[2][8];       /* key */\n\tuint64_t state[2][8];   /* state */\n\n\t/* alternating binary flags */\n\tunsigned int m = 0;\n\n\t/* the number of rounds of the internal dedicated block cipher */\n\tconst int number_of_rounds = 10;\n\n\t/* array used in the rounds */\n\tstatic const uint64_t rc[10] = {\n\t\tI64(0x1823c6e887b8014f),\n\t\tI64(0x36a6d2f5796f9152),\n\t\tI64(0x60bc9b8ea30c7b35),\n\t\tI64(0x1de0d7c22e4bfe57),\n\t\tI64(0x157737e59ff04ada),\n\t\tI64(0x58c9290ab1a06b85),\n\t\tI64(0xbd5d10f4cb3e0567),\n\t\tI64(0xe427418ba77d95d8),\n\t\tI64(0xfbee7c66dd17479e),\n\t\tI64(0xca2dbf07ad5a8333)\n\t};\n\n\t/* map the message buffer to a block */\n\tfor (i = 0; i < 8; i++) {\n\t\t/* store K^0 and xor it with the intermediate hash state */\n\t\tK[0][i] = hash[i];\n\t\tstate[0][i] = be2me_64(p_block[i]) ^ hash[i];\n\t\thash[i] = state[0][i];\n\t}\n\n\t/* iterate over algorithm rounds */\n\tfor (i = 0; i < number_of_rounds; i++)\n\t{\n\t\t/* compute K^i from K^{i-1} */\n\t\tK[m ^ 1][0] = WHIRLPOOL_OP(K[m], 0) ^ rc[i];\n\t\tK[m ^ 1][1] = WHIRLPOOL_OP(K[m], 1);\n\t\tK[m ^ 1][2] = WHIRLPOOL_OP(K[m], 2);\n\t\tK[m ^ 1][3] = WHIRLPOOL_OP(K[m], 3);\n\t\tK[m ^ 1][4] = WHIRLPOOL_OP(K[m], 4);\n\t\tK[m ^ 1][5] = WHIRLPOOL_OP(K[m], 5);\n\t\tK[m ^ 1][6] = WHIRLPOOL_OP(K[m], 6);\n\t\tK[m ^ 1][7] = WHIRLPOOL_OP(K[m], 7);\n\n\t\t/* apply the i-th round transformation */\n\t\tstate[m ^ 1][0] = WHIRLPOOL_OP(state[m], 0) ^ K[m ^ 1][0];\n\t\tstate[m ^ 1][1] = WHIRLPOOL_OP(state[m], 1) ^ K[m ^ 1][1];\n\t\tstate[m ^ 1][2] = WHIRLPOOL_OP(state[m], 2) ^ K[m ^ 1][2];\n\t\tstate[m ^ 1][3] = WHIRLPOOL_OP(state[m], 3) ^ K[m ^ 1][3];\n\t\tstate[m ^ 1][4] = WHIRLPOOL_OP(state[m], 4) ^ K[m ^ 1][4];\n\t\tstate[m ^ 1][5] = WHIRLPOOL_OP(state[m], 5) ^ K[m ^ 1][5];\n\t\tstate[m ^ 1][6] = WHIRLPOOL_OP(state[m], 6) ^ K[m ^ 1][6];\n\t\tstate[m ^ 1][7] = WHIRLPOOL_OP(state[m], 7) ^ K[m ^ 1][7];\n\n\t\tm = m ^ 1;\n\t}\n\n\t/* apply the Miyaguchi-Preneel compression function */\n\thash[0] ^= state[0][0];\n\thash[1] ^= state[0][1];\n\thash[2] ^= state[0][2];\n\thash[3] ^= state[0][3];\n\thash[4] ^= state[0][4];\n\thash[5] ^= state[0][5];\n\thash[6] ^= state[0][6];\n\thash[7] ^= state[0][7];\n}\n\n/**\n * Calculate message hash.\n * Can be called repeatedly with chunks of the message to be hashed.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param msg message chunk\n * @param size length of the message chunk\n */\nvoid rhash_whirlpool_update(whirlpool_ctx* ctx, const unsigned char* msg, size_t size)\n{\n\tunsigned index = (unsigned)ctx->length & 63;\n\tunsigned left;\n\tctx->length += size;\n\n\t/* fill partial block */\n\tif (index) {\n\t\tleft = whirlpool_block_size - index;\n\t\tmemcpy(ctx->message + index, msg, (size < left ? size : left));\n\t\tif (size < left) return;\n\n\t\t/* process partial block */\n\t\trhash_whirlpool_process_block(ctx->hash, (uint64_t*)ctx->message);\n\t\tmsg  += left;\n\t\tsize -= left;\n\t}\n\twhile (size >= whirlpool_block_size) {\n\t\tuint64_t* aligned_message_block;\n\t\tif (IS_ALIGNED_64(msg)) {\n\t\t\t/* the most common case is processing of an already aligned message\n\t\t\twithout copying it */\n\t\t\taligned_message_block = (uint64_t*)msg;\n\t\t} else {\n\t\t\tmemcpy(ctx->message, msg, whirlpool_block_size);\n\t\t\taligned_message_block = (uint64_t*)ctx->message;\n\t\t}\n\n\t\trhash_whirlpool_process_block(ctx->hash, aligned_message_block);\n\t\tmsg += whirlpool_block_size;\n\t\tsize -= whirlpool_block_size;\n\t}\n\tif (size) {\n\t\t/* save leftovers */\n\t\tmemcpy(ctx->message, msg, size);\n\t}\n}\n\n/**\n * Store calculated hash into the given array.\n *\n * @param ctx the algorithm context containing current hashing state\n * @param result calculated hash in binary form\n */\nvoid rhash_whirlpool_final(whirlpool_ctx* ctx, unsigned char* result)\n{\n\tunsigned index = (unsigned)ctx->length & 63;\n\tuint64_t* msg64 = (uint64_t*)ctx->message;\n\n\t/* pad message and run for last block */\n\tctx->message[index++] = 0x80;\n\n\t/* if no room left in the message to store 256-bit message length */\n\tif (index > 32) {\n\t\t/* then pad the rest with zeros and process it */\n\t\twhile (index < 64) {\n\t\t\tctx->message[index++] = 0;\n\t\t}\n\t\trhash_whirlpool_process_block(ctx->hash, msg64);\n\t\tindex = 0;\n\t}\n\t/* due to optimization actually only 64-bit of message length are stored */\n\twhile (index < 56) {\n\t\tctx->message[index++] = 0;\n\t}\n\tmsg64[7] = be2me_64(ctx->length << 3);\n\trhash_whirlpool_process_block(ctx->hash, msg64);\n\n\t/* save result hash */\n\tbe64_copy(result, 0, ctx->hash, 64);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/whirlpool.h",
    "content": "﻿/* whirlpool.h */\n#ifndef WHIRLPOOL_H\n#define WHIRLPOOL_H\n#include \"ustd.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define whirlpool_block_size 64\n\n/* algorithm context */\ntypedef struct whirlpool_ctx\n{\n\tuint64_t hash[8];    /* 512-bit algorithm internal hashing state */\n\tunsigned char message[whirlpool_block_size]; /* 512-bit buffer to hash */\n\n\t/* Note: original algorith uses 256-bit counter, allowing to hash up to\n\t   2^256 bits sized message. For optimization we use here 64-bit counter,\n\t   thus reducing maximal message size to 2^64 bits = 2 Exbibytes = 2^21 TiB) */\n\tuint64_t length;     /* number of processed bytes */\n} whirlpool_ctx;\n\n/* hash functions */\n\nvoid rhash_whirlpool_init(whirlpool_ctx* ctx);\nvoid rhash_whirlpool_update(whirlpool_ctx* ctx, const unsigned char* msg, size_t size);\nvoid rhash_whirlpool_final(whirlpool_ctx* ctx, unsigned char* result);\n\n#ifdef __cplusplus\n} /* extern \"C\" */\n#endif /* __cplusplus */\n\n#endif /* WHIRLPOOL_H */\n"
  },
  {
    "path": "NanaZip.Codecs/RHash/whirlpool_sbox.c",
    "content": "﻿/* whirlpool_sbox.c - S-Box for the Whirlpool hash function\n *\n * Copyright (c) 2009, Aleksey Kravchenko <rhash.admin@gmail.com>\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\n * REGARD TO THIS SOFTWARE  INCLUDING ALL IMPLIED WARRANTIES OF  MERCHANTABILITY\n * AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\n * INDIRECT,  OR CONSEQUENTIAL DAMAGES  OR ANY DAMAGES WHATSOEVER RESULTING FROM\n * LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION OF CONTRACT,  NEGLIGENCE\n * OR OTHER TORTIOUS ACTION,  ARISING OUT OF  OR IN CONNECTION  WITH THE USE  OR\n * PERFORMANCE OF THIS SOFTWARE.\n */\n\n#include \"byte_order.h\"\n\nuint64_t rhash_whirlpool_sbox[8][256] = {\n\t{\n\t\t/* C0 vectors */\n\t\tI64(0x18186018c07830d8), I64(0x23238c2305af4626), I64(0xc6c63fc67ef991b8), I64(0xe8e887e8136fcdfb),\n\t\tI64(0x878726874ca113cb), I64(0xb8b8dab8a9626d11), I64(0x0101040108050209), I64(0x4f4f214f426e9e0d),\n\t\tI64(0x3636d836adee6c9b), I64(0xa6a6a2a6590451ff), I64(0xd2d26fd2debdb90c), I64(0xf5f5f3f5fb06f70e),\n\t\tI64(0x7979f979ef80f296), I64(0x6f6fa16f5fcede30), I64(0x91917e91fcef3f6d), I64(0x52525552aa07a4f8),\n\t\tI64(0x60609d6027fdc047), I64(0xbcbccabc89766535), I64(0x9b9b569baccd2b37), I64(0x8e8e028e048c018a),\n\t\tI64(0xa3a3b6a371155bd2), I64(0x0c0c300c603c186c), I64(0x7b7bf17bff8af684), I64(0x3535d435b5e16a80),\n\t\tI64(0x1d1d741de8693af5), I64(0xe0e0a7e05347ddb3), I64(0xd7d77bd7f6acb321), I64(0xc2c22fc25eed999c),\n\t\tI64(0x2e2eb82e6d965c43), I64(0x4b4b314b627a9629), I64(0xfefedffea321e15d), I64(0x575741578216aed5),\n\t\tI64(0x15155415a8412abd), I64(0x7777c1779fb6eee8), I64(0x3737dc37a5eb6e92), I64(0xe5e5b3e57b56d79e),\n\t\tI64(0x9f9f469f8cd92313), I64(0xf0f0e7f0d317fd23), I64(0x4a4a354a6a7f9420), I64(0xdada4fda9e95a944),\n\t\tI64(0x58587d58fa25b0a2), I64(0xc9c903c906ca8fcf), I64(0x2929a429558d527c), I64(0x0a0a280a5022145a),\n\t\tI64(0xb1b1feb1e14f7f50), I64(0xa0a0baa0691a5dc9), I64(0x6b6bb16b7fdad614), I64(0x85852e855cab17d9),\n\t\tI64(0xbdbdcebd8173673c), I64(0x5d5d695dd234ba8f), I64(0x1010401080502090), I64(0xf4f4f7f4f303f507),\n\t\tI64(0xcbcb0bcb16c08bdd), I64(0x3e3ef83eedc67cd3), I64(0x0505140528110a2d), I64(0x676781671fe6ce78),\n\t\tI64(0xe4e4b7e47353d597), I64(0x27279c2725bb4e02), I64(0x4141194132588273), I64(0x8b8b168b2c9d0ba7),\n\t\tI64(0xa7a7a6a7510153f6), I64(0x7d7de97dcf94fab2), I64(0x95956e95dcfb3749), I64(0xd8d847d88e9fad56),\n\t\tI64(0xfbfbcbfb8b30eb70), I64(0xeeee9fee2371c1cd), I64(0x7c7ced7cc791f8bb), I64(0x6666856617e3cc71),\n\t\tI64(0xdddd53dda68ea77b), I64(0x17175c17b84b2eaf), I64(0x4747014702468e45), I64(0x9e9e429e84dc211a),\n\t\tI64(0xcaca0fca1ec589d4), I64(0x2d2db42d75995a58), I64(0xbfbfc6bf9179632e), I64(0x07071c07381b0e3f),\n\t\tI64(0xadad8ead012347ac), I64(0x5a5a755aea2fb4b0), I64(0x838336836cb51bef), I64(0x3333cc3385ff66b6),\n\t\tI64(0x636391633ff2c65c), I64(0x02020802100a0412), I64(0xaaaa92aa39384993), I64(0x7171d971afa8e2de),\n\t\tI64(0xc8c807c80ecf8dc6), I64(0x19196419c87d32d1), I64(0x494939497270923b), I64(0xd9d943d9869aaf5f),\n\t\tI64(0xf2f2eff2c31df931), I64(0xe3e3abe34b48dba8), I64(0x5b5b715be22ab6b9), I64(0x88881a8834920dbc),\n\t\tI64(0x9a9a529aa4c8293e), I64(0x262698262dbe4c0b), I64(0x3232c8328dfa64bf), I64(0xb0b0fab0e94a7d59),\n\t\tI64(0xe9e983e91b6acff2), I64(0x0f0f3c0f78331e77), I64(0xd5d573d5e6a6b733), I64(0x80803a8074ba1df4),\n\t\tI64(0xbebec2be997c6127), I64(0xcdcd13cd26de87eb), I64(0x3434d034bde46889), I64(0x48483d487a759032),\n\t\tI64(0xffffdbffab24e354), I64(0x7a7af57af78ff48d), I64(0x90907a90f4ea3d64), I64(0x5f5f615fc23ebe9d),\n\t\tI64(0x202080201da0403d), I64(0x6868bd6867d5d00f), I64(0x1a1a681ad07234ca), I64(0xaeae82ae192c41b7),\n\t\tI64(0xb4b4eab4c95e757d), I64(0x54544d549a19a8ce), I64(0x93937693ece53b7f), I64(0x222288220daa442f),\n\t\tI64(0x64648d6407e9c863), I64(0xf1f1e3f1db12ff2a), I64(0x7373d173bfa2e6cc), I64(0x12124812905a2482),\n\t\tI64(0x40401d403a5d807a), I64(0x0808200840281048), I64(0xc3c32bc356e89b95), I64(0xecec97ec337bc5df),\n\t\tI64(0xdbdb4bdb9690ab4d), I64(0xa1a1bea1611f5fc0), I64(0x8d8d0e8d1c830791), I64(0x3d3df43df5c97ac8),\n\t\tI64(0x97976697ccf1335b), I64(0x0000000000000000), I64(0xcfcf1bcf36d483f9), I64(0x2b2bac2b4587566e),\n\t\tI64(0x7676c57697b3ece1), I64(0x8282328264b019e6), I64(0xd6d67fd6fea9b128), I64(0x1b1b6c1bd87736c3),\n\t\tI64(0xb5b5eeb5c15b7774), I64(0xafaf86af112943be), I64(0x6a6ab56a77dfd41d), I64(0x50505d50ba0da0ea),\n\t\tI64(0x45450945124c8a57), I64(0xf3f3ebf3cb18fb38), I64(0x3030c0309df060ad), I64(0xefef9bef2b74c3c4),\n\t\tI64(0x3f3ffc3fe5c37eda), I64(0x55554955921caac7), I64(0xa2a2b2a2791059db), I64(0xeaea8fea0365c9e9),\n\t\tI64(0x656589650fecca6a), I64(0xbabad2bab9686903), I64(0x2f2fbc2f65935e4a), I64(0xc0c027c04ee79d8e),\n\t\tI64(0xdede5fdebe81a160), I64(0x1c1c701ce06c38fc), I64(0xfdfdd3fdbb2ee746), I64(0x4d4d294d52649a1f),\n\t\tI64(0x92927292e4e03976), I64(0x7575c9758fbceafa), I64(0x06061806301e0c36), I64(0x8a8a128a249809ae),\n\t\tI64(0xb2b2f2b2f940794b), I64(0xe6e6bfe66359d185), I64(0x0e0e380e70361c7e), I64(0x1f1f7c1ff8633ee7),\n\t\tI64(0x6262956237f7c455), I64(0xd4d477d4eea3b53a), I64(0xa8a89aa829324d81), I64(0x96966296c4f43152),\n\t\tI64(0xf9f9c3f99b3aef62), I64(0xc5c533c566f697a3), I64(0x2525942535b14a10), I64(0x59597959f220b2ab),\n\t\tI64(0x84842a8454ae15d0), I64(0x7272d572b7a7e4c5), I64(0x3939e439d5dd72ec), I64(0x4c4c2d4c5a619816),\n\t\tI64(0x5e5e655eca3bbc94), I64(0x7878fd78e785f09f), I64(0x3838e038ddd870e5), I64(0x8c8c0a8c14860598),\n\t\tI64(0xd1d163d1c6b2bf17), I64(0xa5a5aea5410b57e4), I64(0xe2e2afe2434dd9a1), I64(0x616199612ff8c24e),\n\t\tI64(0xb3b3f6b3f1457b42), I64(0x2121842115a54234), I64(0x9c9c4a9c94d62508), I64(0x1e1e781ef0663cee),\n\t\tI64(0x4343114322528661), I64(0xc7c73bc776fc93b1), I64(0xfcfcd7fcb32be54f), I64(0x0404100420140824),\n\t\tI64(0x51515951b208a2e3), I64(0x99995e99bcc72f25), I64(0x6d6da96d4fc4da22), I64(0x0d0d340d68391a65),\n\t\tI64(0xfafacffa8335e979), I64(0xdfdf5bdfb684a369), I64(0x7e7ee57ed79bfca9), I64(0x242490243db44819),\n\t\tI64(0x3b3bec3bc5d776fe), I64(0xabab96ab313d4b9a), I64(0xcece1fce3ed181f0), I64(0x1111441188552299),\n\t\tI64(0x8f8f068f0c890383), I64(0x4e4e254e4a6b9c04), I64(0xb7b7e6b7d1517366), I64(0xebeb8beb0b60cbe0),\n\t\tI64(0x3c3cf03cfdcc78c1), I64(0x81813e817cbf1ffd), I64(0x94946a94d4fe3540), I64(0xf7f7fbf7eb0cf31c),\n\t\tI64(0xb9b9deb9a1676f18), I64(0x13134c13985f268b), I64(0x2c2cb02c7d9c5851), I64(0xd3d36bd3d6b8bb05),\n\t\tI64(0xe7e7bbe76b5cd38c), I64(0x6e6ea56e57cbdc39), I64(0xc4c437c46ef395aa), I64(0x03030c03180f061b),\n\t\tI64(0x565645568a13acdc), I64(0x44440d441a49885e), I64(0x7f7fe17fdf9efea0), I64(0xa9a99ea921374f88),\n\t\tI64(0x2a2aa82a4d825467), I64(0xbbbbd6bbb16d6b0a), I64(0xc1c123c146e29f87), I64(0x53535153a202a6f1),\n\t\tI64(0xdcdc57dcae8ba572), I64(0x0b0b2c0b58271653), I64(0x9d9d4e9d9cd32701), I64(0x6c6cad6c47c1d82b),\n\t\tI64(0x3131c43195f562a4), I64(0x7474cd7487b9e8f3), I64(0xf6f6fff6e309f115), I64(0x464605460a438c4c),\n\t\tI64(0xacac8aac092645a5), I64(0x89891e893c970fb5), I64(0x14145014a04428b4), I64(0xe1e1a3e15b42dfba),\n\t\tI64(0x16165816b04e2ca6), I64(0x3a3ae83acdd274f7), I64(0x6969b9696fd0d206), I64(0x09092409482d1241),\n\t\tI64(0x7070dd70a7ade0d7), I64(0xb6b6e2b6d954716f), I64(0xd0d067d0ceb7bd1e), I64(0xeded93ed3b7ec7d6),\n\t\tI64(0xcccc17cc2edb85e2), I64(0x424215422a578468), I64(0x98985a98b4c22d2c), I64(0xa4a4aaa4490e55ed),\n\t\tI64(0x2828a0285d885075), I64(0x5c5c6d5cda31b886), I64(0xf8f8c7f8933fed6b), I64(0x8686228644a411c2),\n\t\t}, {\n\t\t/* C1 vectors */\n\t\tI64(0xd818186018c07830), I64(0x2623238c2305af46), I64(0xb8c6c63fc67ef991), I64(0xfbe8e887e8136fcd),\n\t\tI64(0xcb878726874ca113), I64(0x11b8b8dab8a9626d), I64(0x0901010401080502), I64(0x0d4f4f214f426e9e),\n\t\tI64(0x9b3636d836adee6c), I64(0xffa6a6a2a6590451), I64(0x0cd2d26fd2debdb9), I64(0x0ef5f5f3f5fb06f7),\n\t\tI64(0x967979f979ef80f2), I64(0x306f6fa16f5fcede), I64(0x6d91917e91fcef3f), I64(0xf852525552aa07a4),\n\t\tI64(0x4760609d6027fdc0), I64(0x35bcbccabc897665), I64(0x379b9b569baccd2b), I64(0x8a8e8e028e048c01),\n\t\tI64(0xd2a3a3b6a371155b), I64(0x6c0c0c300c603c18), I64(0x847b7bf17bff8af6), I64(0x803535d435b5e16a),\n\t\tI64(0xf51d1d741de8693a), I64(0xb3e0e0a7e05347dd), I64(0x21d7d77bd7f6acb3), I64(0x9cc2c22fc25eed99),\n\t\tI64(0x432e2eb82e6d965c), I64(0x294b4b314b627a96), I64(0x5dfefedffea321e1), I64(0xd5575741578216ae),\n\t\tI64(0xbd15155415a8412a), I64(0xe87777c1779fb6ee), I64(0x923737dc37a5eb6e), I64(0x9ee5e5b3e57b56d7),\n\t\tI64(0x139f9f469f8cd923), I64(0x23f0f0e7f0d317fd), I64(0x204a4a354a6a7f94), I64(0x44dada4fda9e95a9),\n\t\tI64(0xa258587d58fa25b0), I64(0xcfc9c903c906ca8f), I64(0x7c2929a429558d52), I64(0x5a0a0a280a502214),\n\t\tI64(0x50b1b1feb1e14f7f), I64(0xc9a0a0baa0691a5d), I64(0x146b6bb16b7fdad6), I64(0xd985852e855cab17),\n\t\tI64(0x3cbdbdcebd817367), I64(0x8f5d5d695dd234ba), I64(0x9010104010805020), I64(0x07f4f4f7f4f303f5),\n\t\tI64(0xddcbcb0bcb16c08b), I64(0xd33e3ef83eedc67c), I64(0x2d0505140528110a), I64(0x78676781671fe6ce),\n\t\tI64(0x97e4e4b7e47353d5), I64(0x0227279c2725bb4e), I64(0x7341411941325882), I64(0xa78b8b168b2c9d0b),\n\t\tI64(0xf6a7a7a6a7510153), I64(0xb27d7de97dcf94fa), I64(0x4995956e95dcfb37), I64(0x56d8d847d88e9fad),\n\t\tI64(0x70fbfbcbfb8b30eb), I64(0xcdeeee9fee2371c1), I64(0xbb7c7ced7cc791f8), I64(0x716666856617e3cc),\n\t\tI64(0x7bdddd53dda68ea7), I64(0xaf17175c17b84b2e), I64(0x454747014702468e), I64(0x1a9e9e429e84dc21),\n\t\tI64(0xd4caca0fca1ec589), I64(0x582d2db42d75995a), I64(0x2ebfbfc6bf917963), I64(0x3f07071c07381b0e),\n\t\tI64(0xacadad8ead012347), I64(0xb05a5a755aea2fb4), I64(0xef838336836cb51b), I64(0xb63333cc3385ff66),\n\t\tI64(0x5c636391633ff2c6), I64(0x1202020802100a04), I64(0x93aaaa92aa393849), I64(0xde7171d971afa8e2),\n\t\tI64(0xc6c8c807c80ecf8d), I64(0xd119196419c87d32), I64(0x3b49493949727092), I64(0x5fd9d943d9869aaf),\n\t\tI64(0x31f2f2eff2c31df9), I64(0xa8e3e3abe34b48db), I64(0xb95b5b715be22ab6), I64(0xbc88881a8834920d),\n\t\tI64(0x3e9a9a529aa4c829), I64(0x0b262698262dbe4c), I64(0xbf3232c8328dfa64), I64(0x59b0b0fab0e94a7d),\n\t\tI64(0xf2e9e983e91b6acf), I64(0x770f0f3c0f78331e), I64(0x33d5d573d5e6a6b7), I64(0xf480803a8074ba1d),\n\t\tI64(0x27bebec2be997c61), I64(0xebcdcd13cd26de87), I64(0x893434d034bde468), I64(0x3248483d487a7590),\n\t\tI64(0x54ffffdbffab24e3), I64(0x8d7a7af57af78ff4), I64(0x6490907a90f4ea3d), I64(0x9d5f5f615fc23ebe),\n\t\tI64(0x3d202080201da040), I64(0x0f6868bd6867d5d0), I64(0xca1a1a681ad07234), I64(0xb7aeae82ae192c41),\n\t\tI64(0x7db4b4eab4c95e75), I64(0xce54544d549a19a8), I64(0x7f93937693ece53b), I64(0x2f222288220daa44),\n\t\tI64(0x6364648d6407e9c8), I64(0x2af1f1e3f1db12ff), I64(0xcc7373d173bfa2e6), I64(0x8212124812905a24),\n\t\tI64(0x7a40401d403a5d80), I64(0x4808082008402810), I64(0x95c3c32bc356e89b), I64(0xdfecec97ec337bc5),\n\t\tI64(0x4ddbdb4bdb9690ab), I64(0xc0a1a1bea1611f5f), I64(0x918d8d0e8d1c8307), I64(0xc83d3df43df5c97a),\n\t\tI64(0x5b97976697ccf133), I64(0x0000000000000000), I64(0xf9cfcf1bcf36d483), I64(0x6e2b2bac2b458756),\n\t\tI64(0xe17676c57697b3ec), I64(0xe68282328264b019), I64(0x28d6d67fd6fea9b1), I64(0xc31b1b6c1bd87736),\n\t\tI64(0x74b5b5eeb5c15b77), I64(0xbeafaf86af112943), I64(0x1d6a6ab56a77dfd4), I64(0xea50505d50ba0da0),\n\t\tI64(0x5745450945124c8a), I64(0x38f3f3ebf3cb18fb), I64(0xad3030c0309df060), I64(0xc4efef9bef2b74c3),\n\t\tI64(0xda3f3ffc3fe5c37e), I64(0xc755554955921caa), I64(0xdba2a2b2a2791059), I64(0xe9eaea8fea0365c9),\n\t\tI64(0x6a656589650fecca), I64(0x03babad2bab96869), I64(0x4a2f2fbc2f65935e), I64(0x8ec0c027c04ee79d),\n\t\tI64(0x60dede5fdebe81a1), I64(0xfc1c1c701ce06c38), I64(0x46fdfdd3fdbb2ee7), I64(0x1f4d4d294d52649a),\n\t\tI64(0x7692927292e4e039), I64(0xfa7575c9758fbcea), I64(0x3606061806301e0c), I64(0xae8a8a128a249809),\n\t\tI64(0x4bb2b2f2b2f94079), I64(0x85e6e6bfe66359d1), I64(0x7e0e0e380e70361c), I64(0xe71f1f7c1ff8633e),\n\t\tI64(0x556262956237f7c4), I64(0x3ad4d477d4eea3b5), I64(0x81a8a89aa829324d), I64(0x5296966296c4f431),\n\t\tI64(0x62f9f9c3f99b3aef), I64(0xa3c5c533c566f697), I64(0x102525942535b14a), I64(0xab59597959f220b2),\n\t\tI64(0xd084842a8454ae15), I64(0xc57272d572b7a7e4), I64(0xec3939e439d5dd72), I64(0x164c4c2d4c5a6198),\n\t\tI64(0x945e5e655eca3bbc), I64(0x9f7878fd78e785f0), I64(0xe53838e038ddd870), I64(0x988c8c0a8c148605),\n\t\tI64(0x17d1d163d1c6b2bf), I64(0xe4a5a5aea5410b57), I64(0xa1e2e2afe2434dd9), I64(0x4e616199612ff8c2),\n\t\tI64(0x42b3b3f6b3f1457b), I64(0x342121842115a542), I64(0x089c9c4a9c94d625), I64(0xee1e1e781ef0663c),\n\t\tI64(0x6143431143225286), I64(0xb1c7c73bc776fc93), I64(0x4ffcfcd7fcb32be5), I64(0x2404041004201408),\n\t\tI64(0xe351515951b208a2), I64(0x2599995e99bcc72f), I64(0x226d6da96d4fc4da), I64(0x650d0d340d68391a),\n\t\tI64(0x79fafacffa8335e9), I64(0x69dfdf5bdfb684a3), I64(0xa97e7ee57ed79bfc), I64(0x19242490243db448),\n\t\tI64(0xfe3b3bec3bc5d776), I64(0x9aabab96ab313d4b), I64(0xf0cece1fce3ed181), I64(0x9911114411885522),\n\t\tI64(0x838f8f068f0c8903), I64(0x044e4e254e4a6b9c), I64(0x66b7b7e6b7d15173), I64(0xe0ebeb8beb0b60cb),\n\t\tI64(0xc13c3cf03cfdcc78), I64(0xfd81813e817cbf1f), I64(0x4094946a94d4fe35), I64(0x1cf7f7fbf7eb0cf3),\n\t\tI64(0x18b9b9deb9a1676f), I64(0x8b13134c13985f26), I64(0x512c2cb02c7d9c58), I64(0x05d3d36bd3d6b8bb),\n\t\tI64(0x8ce7e7bbe76b5cd3), I64(0x396e6ea56e57cbdc), I64(0xaac4c437c46ef395), I64(0x1b03030c03180f06),\n\t\tI64(0xdc565645568a13ac), I64(0x5e44440d441a4988), I64(0xa07f7fe17fdf9efe), I64(0x88a9a99ea921374f),\n\t\tI64(0x672a2aa82a4d8254), I64(0x0abbbbd6bbb16d6b), I64(0x87c1c123c146e29f), I64(0xf153535153a202a6),\n\t\tI64(0x72dcdc57dcae8ba5), I64(0x530b0b2c0b582716), I64(0x019d9d4e9d9cd327), I64(0x2b6c6cad6c47c1d8),\n\t\tI64(0xa43131c43195f562), I64(0xf37474cd7487b9e8), I64(0x15f6f6fff6e309f1), I64(0x4c464605460a438c),\n\t\tI64(0xa5acac8aac092645), I64(0xb589891e893c970f), I64(0xb414145014a04428), I64(0xbae1e1a3e15b42df),\n\t\tI64(0xa616165816b04e2c), I64(0xf73a3ae83acdd274), I64(0x066969b9696fd0d2), I64(0x4109092409482d12),\n\t\tI64(0xd77070dd70a7ade0), I64(0x6fb6b6e2b6d95471), I64(0x1ed0d067d0ceb7bd), I64(0xd6eded93ed3b7ec7),\n\t\tI64(0xe2cccc17cc2edb85), I64(0x68424215422a5784), I64(0x2c98985a98b4c22d), I64(0xeda4a4aaa4490e55),\n\t\tI64(0x752828a0285d8850), I64(0x865c5c6d5cda31b8), I64(0x6bf8f8c7f8933fed), I64(0xc28686228644a411),\n\t\t}, {\n\t\t/* C2 vectors */\n\t\tI64(0x30d818186018c078), I64(0x462623238c2305af), I64(0x91b8c6c63fc67ef9), I64(0xcdfbe8e887e8136f),\n\t\tI64(0x13cb878726874ca1), I64(0x6d11b8b8dab8a962), I64(0x0209010104010805), I64(0x9e0d4f4f214f426e),\n\t\tI64(0x6c9b3636d836adee), I64(0x51ffa6a6a2a65904), I64(0xb90cd2d26fd2debd), I64(0xf70ef5f5f3f5fb06),\n\t\tI64(0xf2967979f979ef80), I64(0xde306f6fa16f5fce), I64(0x3f6d91917e91fcef), I64(0xa4f852525552aa07),\n\t\tI64(0xc04760609d6027fd), I64(0x6535bcbccabc8976), I64(0x2b379b9b569baccd), I64(0x018a8e8e028e048c),\n\t\tI64(0x5bd2a3a3b6a37115), I64(0x186c0c0c300c603c), I64(0xf6847b7bf17bff8a), I64(0x6a803535d435b5e1),\n\t\tI64(0x3af51d1d741de869), I64(0xddb3e0e0a7e05347), I64(0xb321d7d77bd7f6ac), I64(0x999cc2c22fc25eed),\n\t\tI64(0x5c432e2eb82e6d96), I64(0x96294b4b314b627a), I64(0xe15dfefedffea321), I64(0xaed5575741578216),\n\t\tI64(0x2abd15155415a841), I64(0xeee87777c1779fb6), I64(0x6e923737dc37a5eb), I64(0xd79ee5e5b3e57b56),\n\t\tI64(0x23139f9f469f8cd9), I64(0xfd23f0f0e7f0d317), I64(0x94204a4a354a6a7f), I64(0xa944dada4fda9e95),\n\t\tI64(0xb0a258587d58fa25), I64(0x8fcfc9c903c906ca), I64(0x527c2929a429558d), I64(0x145a0a0a280a5022),\n\t\tI64(0x7f50b1b1feb1e14f), I64(0x5dc9a0a0baa0691a), I64(0xd6146b6bb16b7fda), I64(0x17d985852e855cab),\n\t\tI64(0x673cbdbdcebd8173), I64(0xba8f5d5d695dd234), I64(0x2090101040108050), I64(0xf507f4f4f7f4f303),\n\t\tI64(0x8bddcbcb0bcb16c0), I64(0x7cd33e3ef83eedc6), I64(0x0a2d050514052811), I64(0xce78676781671fe6),\n\t\tI64(0xd597e4e4b7e47353), I64(0x4e0227279c2725bb), I64(0x8273414119413258), I64(0x0ba78b8b168b2c9d),\n\t\tI64(0x53f6a7a7a6a75101), I64(0xfab27d7de97dcf94), I64(0x374995956e95dcfb), I64(0xad56d8d847d88e9f),\n\t\tI64(0xeb70fbfbcbfb8b30), I64(0xc1cdeeee9fee2371), I64(0xf8bb7c7ced7cc791), I64(0xcc716666856617e3),\n\t\tI64(0xa77bdddd53dda68e), I64(0x2eaf17175c17b84b), I64(0x8e45474701470246), I64(0x211a9e9e429e84dc),\n\t\tI64(0x89d4caca0fca1ec5), I64(0x5a582d2db42d7599), I64(0x632ebfbfc6bf9179), I64(0x0e3f07071c07381b),\n\t\tI64(0x47acadad8ead0123), I64(0xb4b05a5a755aea2f), I64(0x1bef838336836cb5), I64(0x66b63333cc3385ff),\n\t\tI64(0xc65c636391633ff2), I64(0x041202020802100a), I64(0x4993aaaa92aa3938), I64(0xe2de7171d971afa8),\n\t\tI64(0x8dc6c8c807c80ecf), I64(0x32d119196419c87d), I64(0x923b494939497270), I64(0xaf5fd9d943d9869a),\n\t\tI64(0xf931f2f2eff2c31d), I64(0xdba8e3e3abe34b48), I64(0xb6b95b5b715be22a), I64(0x0dbc88881a883492),\n\t\tI64(0x293e9a9a529aa4c8), I64(0x4c0b262698262dbe), I64(0x64bf3232c8328dfa), I64(0x7d59b0b0fab0e94a),\n\t\tI64(0xcff2e9e983e91b6a), I64(0x1e770f0f3c0f7833), I64(0xb733d5d573d5e6a6), I64(0x1df480803a8074ba),\n\t\tI64(0x6127bebec2be997c), I64(0x87ebcdcd13cd26de), I64(0x68893434d034bde4), I64(0x903248483d487a75),\n\t\tI64(0xe354ffffdbffab24), I64(0xf48d7a7af57af78f), I64(0x3d6490907a90f4ea), I64(0xbe9d5f5f615fc23e),\n\t\tI64(0x403d202080201da0), I64(0xd00f6868bd6867d5), I64(0x34ca1a1a681ad072), I64(0x41b7aeae82ae192c),\n\t\tI64(0x757db4b4eab4c95e), I64(0xa8ce54544d549a19), I64(0x3b7f93937693ece5), I64(0x442f222288220daa),\n\t\tI64(0xc86364648d6407e9), I64(0xff2af1f1e3f1db12), I64(0xe6cc7373d173bfa2), I64(0x248212124812905a),\n\t\tI64(0x807a40401d403a5d), I64(0x1048080820084028), I64(0x9b95c3c32bc356e8), I64(0xc5dfecec97ec337b),\n\t\tI64(0xab4ddbdb4bdb9690), I64(0x5fc0a1a1bea1611f), I64(0x07918d8d0e8d1c83), I64(0x7ac83d3df43df5c9),\n\t\tI64(0x335b97976697ccf1), I64(0x0000000000000000), I64(0x83f9cfcf1bcf36d4), I64(0x566e2b2bac2b4587),\n\t\tI64(0xece17676c57697b3), I64(0x19e68282328264b0), I64(0xb128d6d67fd6fea9), I64(0x36c31b1b6c1bd877),\n\t\tI64(0x7774b5b5eeb5c15b), I64(0x43beafaf86af1129), I64(0xd41d6a6ab56a77df), I64(0xa0ea50505d50ba0d),\n\t\tI64(0x8a5745450945124c), I64(0xfb38f3f3ebf3cb18), I64(0x60ad3030c0309df0), I64(0xc3c4efef9bef2b74),\n\t\tI64(0x7eda3f3ffc3fe5c3), I64(0xaac755554955921c), I64(0x59dba2a2b2a27910), I64(0xc9e9eaea8fea0365),\n\t\tI64(0xca6a656589650fec), I64(0x6903babad2bab968), I64(0x5e4a2f2fbc2f6593), I64(0x9d8ec0c027c04ee7),\n\t\tI64(0xa160dede5fdebe81), I64(0x38fc1c1c701ce06c), I64(0xe746fdfdd3fdbb2e), I64(0x9a1f4d4d294d5264),\n\t\tI64(0x397692927292e4e0), I64(0xeafa7575c9758fbc), I64(0x0c3606061806301e), I64(0x09ae8a8a128a2498),\n\t\tI64(0x794bb2b2f2b2f940), I64(0xd185e6e6bfe66359), I64(0x1c7e0e0e380e7036), I64(0x3ee71f1f7c1ff863),\n\t\tI64(0xc4556262956237f7), I64(0xb53ad4d477d4eea3), I64(0x4d81a8a89aa82932), I64(0x315296966296c4f4),\n\t\tI64(0xef62f9f9c3f99b3a), I64(0x97a3c5c533c566f6), I64(0x4a102525942535b1), I64(0xb2ab59597959f220),\n\t\tI64(0x15d084842a8454ae), I64(0xe4c57272d572b7a7), I64(0x72ec3939e439d5dd), I64(0x98164c4c2d4c5a61),\n\t\tI64(0xbc945e5e655eca3b), I64(0xf09f7878fd78e785), I64(0x70e53838e038ddd8), I64(0x05988c8c0a8c1486),\n\t\tI64(0xbf17d1d163d1c6b2), I64(0x57e4a5a5aea5410b), I64(0xd9a1e2e2afe2434d), I64(0xc24e616199612ff8),\n\t\tI64(0x7b42b3b3f6b3f145), I64(0x42342121842115a5), I64(0x25089c9c4a9c94d6), I64(0x3cee1e1e781ef066),\n\t\tI64(0x8661434311432252), I64(0x93b1c7c73bc776fc), I64(0xe54ffcfcd7fcb32b), I64(0x0824040410042014),\n\t\tI64(0xa2e351515951b208), I64(0x2f2599995e99bcc7), I64(0xda226d6da96d4fc4), I64(0x1a650d0d340d6839),\n\t\tI64(0xe979fafacffa8335), I64(0xa369dfdf5bdfb684), I64(0xfca97e7ee57ed79b), I64(0x4819242490243db4),\n\t\tI64(0x76fe3b3bec3bc5d7), I64(0x4b9aabab96ab313d), I64(0x81f0cece1fce3ed1), I64(0x2299111144118855),\n\t\tI64(0x03838f8f068f0c89), I64(0x9c044e4e254e4a6b), I64(0x7366b7b7e6b7d151), I64(0xcbe0ebeb8beb0b60),\n\t\tI64(0x78c13c3cf03cfdcc), I64(0x1ffd81813e817cbf), I64(0x354094946a94d4fe), I64(0xf31cf7f7fbf7eb0c),\n\t\tI64(0x6f18b9b9deb9a167), I64(0x268b13134c13985f), I64(0x58512c2cb02c7d9c), I64(0xbb05d3d36bd3d6b8),\n\t\tI64(0xd38ce7e7bbe76b5c), I64(0xdc396e6ea56e57cb), I64(0x95aac4c437c46ef3), I64(0x061b03030c03180f),\n\t\tI64(0xacdc565645568a13), I64(0x885e44440d441a49), I64(0xfea07f7fe17fdf9e), I64(0x4f88a9a99ea92137),\n\t\tI64(0x54672a2aa82a4d82), I64(0x6b0abbbbd6bbb16d), I64(0x9f87c1c123c146e2), I64(0xa6f153535153a202),\n\t\tI64(0xa572dcdc57dcae8b), I64(0x16530b0b2c0b5827), I64(0x27019d9d4e9d9cd3), I64(0xd82b6c6cad6c47c1),\n\t\tI64(0x62a43131c43195f5), I64(0xe8f37474cd7487b9), I64(0xf115f6f6fff6e309), I64(0x8c4c464605460a43),\n\t\tI64(0x45a5acac8aac0926), I64(0x0fb589891e893c97), I64(0x28b414145014a044), I64(0xdfbae1e1a3e15b42),\n\t\tI64(0x2ca616165816b04e), I64(0x74f73a3ae83acdd2), I64(0xd2066969b9696fd0), I64(0x124109092409482d),\n\t\tI64(0xe0d77070dd70a7ad), I64(0x716fb6b6e2b6d954), I64(0xbd1ed0d067d0ceb7), I64(0xc7d6eded93ed3b7e),\n\t\tI64(0x85e2cccc17cc2edb), I64(0x8468424215422a57), I64(0x2d2c98985a98b4c2), I64(0x55eda4a4aaa4490e),\n\t\tI64(0x50752828a0285d88), I64(0xb8865c5c6d5cda31), I64(0xed6bf8f8c7f8933f), I64(0x11c28686228644a4),\n\t\t}, {\n\t\t/* C3 vectors */\n\t\tI64(0x7830d818186018c0), I64(0xaf462623238c2305), I64(0xf991b8c6c63fc67e), I64(0x6fcdfbe8e887e813),\n\t\tI64(0xa113cb878726874c), I64(0x626d11b8b8dab8a9), I64(0x0502090101040108), I64(0x6e9e0d4f4f214f42),\n\t\tI64(0xee6c9b3636d836ad), I64(0x0451ffa6a6a2a659), I64(0xbdb90cd2d26fd2de), I64(0x06f70ef5f5f3f5fb),\n\t\tI64(0x80f2967979f979ef), I64(0xcede306f6fa16f5f), I64(0xef3f6d91917e91fc), I64(0x07a4f852525552aa),\n\t\tI64(0xfdc04760609d6027), I64(0x766535bcbccabc89), I64(0xcd2b379b9b569bac), I64(0x8c018a8e8e028e04),\n\t\tI64(0x155bd2a3a3b6a371), I64(0x3c186c0c0c300c60), I64(0x8af6847b7bf17bff), I64(0xe16a803535d435b5),\n\t\tI64(0x693af51d1d741de8), I64(0x47ddb3e0e0a7e053), I64(0xacb321d7d77bd7f6), I64(0xed999cc2c22fc25e),\n\t\tI64(0x965c432e2eb82e6d), I64(0x7a96294b4b314b62), I64(0x21e15dfefedffea3), I64(0x16aed55757415782),\n\t\tI64(0x412abd15155415a8), I64(0xb6eee87777c1779f), I64(0xeb6e923737dc37a5), I64(0x56d79ee5e5b3e57b),\n\t\tI64(0xd923139f9f469f8c), I64(0x17fd23f0f0e7f0d3), I64(0x7f94204a4a354a6a), I64(0x95a944dada4fda9e),\n\t\tI64(0x25b0a258587d58fa), I64(0xca8fcfc9c903c906), I64(0x8d527c2929a42955), I64(0x22145a0a0a280a50),\n\t\tI64(0x4f7f50b1b1feb1e1), I64(0x1a5dc9a0a0baa069), I64(0xdad6146b6bb16b7f), I64(0xab17d985852e855c),\n\t\tI64(0x73673cbdbdcebd81), I64(0x34ba8f5d5d695dd2), I64(0x5020901010401080), I64(0x03f507f4f4f7f4f3),\n\t\tI64(0xc08bddcbcb0bcb16), I64(0xc67cd33e3ef83eed), I64(0x110a2d0505140528), I64(0xe6ce78676781671f),\n\t\tI64(0x53d597e4e4b7e473), I64(0xbb4e0227279c2725), I64(0x5882734141194132), I64(0x9d0ba78b8b168b2c),\n\t\tI64(0x0153f6a7a7a6a751), I64(0x94fab27d7de97dcf), I64(0xfb374995956e95dc), I64(0x9fad56d8d847d88e),\n\t\tI64(0x30eb70fbfbcbfb8b), I64(0x71c1cdeeee9fee23), I64(0x91f8bb7c7ced7cc7), I64(0xe3cc716666856617),\n\t\tI64(0x8ea77bdddd53dda6), I64(0x4b2eaf17175c17b8), I64(0x468e454747014702), I64(0xdc211a9e9e429e84),\n\t\tI64(0xc589d4caca0fca1e), I64(0x995a582d2db42d75), I64(0x79632ebfbfc6bf91), I64(0x1b0e3f07071c0738),\n\t\tI64(0x2347acadad8ead01), I64(0x2fb4b05a5a755aea), I64(0xb51bef838336836c), I64(0xff66b63333cc3385),\n\t\tI64(0xf2c65c636391633f), I64(0x0a04120202080210), I64(0x384993aaaa92aa39), I64(0xa8e2de7171d971af),\n\t\tI64(0xcf8dc6c8c807c80e), I64(0x7d32d119196419c8), I64(0x70923b4949394972), I64(0x9aaf5fd9d943d986),\n\t\tI64(0x1df931f2f2eff2c3), I64(0x48dba8e3e3abe34b), I64(0x2ab6b95b5b715be2), I64(0x920dbc88881a8834),\n\t\tI64(0xc8293e9a9a529aa4), I64(0xbe4c0b262698262d), I64(0xfa64bf3232c8328d), I64(0x4a7d59b0b0fab0e9),\n\t\tI64(0x6acff2e9e983e91b), I64(0x331e770f0f3c0f78), I64(0xa6b733d5d573d5e6), I64(0xba1df480803a8074),\n\t\tI64(0x7c6127bebec2be99), I64(0xde87ebcdcd13cd26), I64(0xe468893434d034bd), I64(0x75903248483d487a),\n\t\tI64(0x24e354ffffdbffab), I64(0x8ff48d7a7af57af7), I64(0xea3d6490907a90f4), I64(0x3ebe9d5f5f615fc2),\n\t\tI64(0xa0403d202080201d), I64(0xd5d00f6868bd6867), I64(0x7234ca1a1a681ad0), I64(0x2c41b7aeae82ae19),\n\t\tI64(0x5e757db4b4eab4c9), I64(0x19a8ce54544d549a), I64(0xe53b7f93937693ec), I64(0xaa442f222288220d),\n\t\tI64(0xe9c86364648d6407), I64(0x12ff2af1f1e3f1db), I64(0xa2e6cc7373d173bf), I64(0x5a24821212481290),\n\t\tI64(0x5d807a40401d403a), I64(0x2810480808200840), I64(0xe89b95c3c32bc356), I64(0x7bc5dfecec97ec33),\n\t\tI64(0x90ab4ddbdb4bdb96), I64(0x1f5fc0a1a1bea161), I64(0x8307918d8d0e8d1c), I64(0xc97ac83d3df43df5),\n\t\tI64(0xf1335b97976697cc), I64(0x0000000000000000), I64(0xd483f9cfcf1bcf36), I64(0x87566e2b2bac2b45),\n\t\tI64(0xb3ece17676c57697), I64(0xb019e68282328264), I64(0xa9b128d6d67fd6fe), I64(0x7736c31b1b6c1bd8),\n\t\tI64(0x5b7774b5b5eeb5c1), I64(0x2943beafaf86af11), I64(0xdfd41d6a6ab56a77), I64(0x0da0ea50505d50ba),\n\t\tI64(0x4c8a574545094512), I64(0x18fb38f3f3ebf3cb), I64(0xf060ad3030c0309d), I64(0x74c3c4efef9bef2b),\n\t\tI64(0xc37eda3f3ffc3fe5), I64(0x1caac75555495592), I64(0x1059dba2a2b2a279), I64(0x65c9e9eaea8fea03),\n\t\tI64(0xecca6a656589650f), I64(0x686903babad2bab9), I64(0x935e4a2f2fbc2f65), I64(0xe79d8ec0c027c04e),\n\t\tI64(0x81a160dede5fdebe), I64(0x6c38fc1c1c701ce0), I64(0x2ee746fdfdd3fdbb), I64(0x649a1f4d4d294d52),\n\t\tI64(0xe0397692927292e4), I64(0xbceafa7575c9758f), I64(0x1e0c360606180630), I64(0x9809ae8a8a128a24),\n\t\tI64(0x40794bb2b2f2b2f9), I64(0x59d185e6e6bfe663), I64(0x361c7e0e0e380e70), I64(0x633ee71f1f7c1ff8),\n\t\tI64(0xf7c4556262956237), I64(0xa3b53ad4d477d4ee), I64(0x324d81a8a89aa829), I64(0xf4315296966296c4),\n\t\tI64(0x3aef62f9f9c3f99b), I64(0xf697a3c5c533c566), I64(0xb14a102525942535), I64(0x20b2ab59597959f2),\n\t\tI64(0xae15d084842a8454), I64(0xa7e4c57272d572b7), I64(0xdd72ec3939e439d5), I64(0x6198164c4c2d4c5a),\n\t\tI64(0x3bbc945e5e655eca), I64(0x85f09f7878fd78e7), I64(0xd870e53838e038dd), I64(0x8605988c8c0a8c14),\n\t\tI64(0xb2bf17d1d163d1c6), I64(0x0b57e4a5a5aea541), I64(0x4dd9a1e2e2afe243), I64(0xf8c24e616199612f),\n\t\tI64(0x457b42b3b3f6b3f1), I64(0xa542342121842115), I64(0xd625089c9c4a9c94), I64(0x663cee1e1e781ef0),\n\t\tI64(0x5286614343114322), I64(0xfc93b1c7c73bc776), I64(0x2be54ffcfcd7fcb3), I64(0x1408240404100420),\n\t\tI64(0x08a2e351515951b2), I64(0xc72f2599995e99bc), I64(0xc4da226d6da96d4f), I64(0x391a650d0d340d68),\n\t\tI64(0x35e979fafacffa83), I64(0x84a369dfdf5bdfb6), I64(0x9bfca97e7ee57ed7), I64(0xb44819242490243d),\n\t\tI64(0xd776fe3b3bec3bc5), I64(0x3d4b9aabab96ab31), I64(0xd181f0cece1fce3e), I64(0x5522991111441188),\n\t\tI64(0x8903838f8f068f0c), I64(0x6b9c044e4e254e4a), I64(0x517366b7b7e6b7d1), I64(0x60cbe0ebeb8beb0b),\n\t\tI64(0xcc78c13c3cf03cfd), I64(0xbf1ffd81813e817c), I64(0xfe354094946a94d4), I64(0x0cf31cf7f7fbf7eb),\n\t\tI64(0x676f18b9b9deb9a1), I64(0x5f268b13134c1398), I64(0x9c58512c2cb02c7d), I64(0xb8bb05d3d36bd3d6),\n\t\tI64(0x5cd38ce7e7bbe76b), I64(0xcbdc396e6ea56e57), I64(0xf395aac4c437c46e), I64(0x0f061b03030c0318),\n\t\tI64(0x13acdc565645568a), I64(0x49885e44440d441a), I64(0x9efea07f7fe17fdf), I64(0x374f88a9a99ea921),\n\t\tI64(0x8254672a2aa82a4d), I64(0x6d6b0abbbbd6bbb1), I64(0xe29f87c1c123c146), I64(0x02a6f153535153a2),\n\t\tI64(0x8ba572dcdc57dcae), I64(0x2716530b0b2c0b58), I64(0xd327019d9d4e9d9c), I64(0xc1d82b6c6cad6c47),\n\t\tI64(0xf562a43131c43195), I64(0xb9e8f37474cd7487), I64(0x09f115f6f6fff6e3), I64(0x438c4c464605460a),\n\t\tI64(0x2645a5acac8aac09), I64(0x970fb589891e893c), I64(0x4428b414145014a0), I64(0x42dfbae1e1a3e15b),\n\t\tI64(0x4e2ca616165816b0), I64(0xd274f73a3ae83acd), I64(0xd0d2066969b9696f), I64(0x2d12410909240948),\n\t\tI64(0xade0d77070dd70a7), I64(0x54716fb6b6e2b6d9), I64(0xb7bd1ed0d067d0ce), I64(0x7ec7d6eded93ed3b),\n\t\tI64(0xdb85e2cccc17cc2e), I64(0x578468424215422a), I64(0xc22d2c98985a98b4), I64(0x0e55eda4a4aaa449),\n\t\tI64(0x8850752828a0285d), I64(0x31b8865c5c6d5cda), I64(0x3fed6bf8f8c7f893), I64(0xa411c28686228644),\n\t\t}, {\n\t\t/* C4 vectors */\n\t\tI64(0xc07830d818186018), I64(0x05af462623238c23), I64(0x7ef991b8c6c63fc6), I64(0x136fcdfbe8e887e8),\n\t\tI64(0x4ca113cb87872687), I64(0xa9626d11b8b8dab8), I64(0x0805020901010401), I64(0x426e9e0d4f4f214f),\n\t\tI64(0xadee6c9b3636d836), I64(0x590451ffa6a6a2a6), I64(0xdebdb90cd2d26fd2), I64(0xfb06f70ef5f5f3f5),\n\t\tI64(0xef80f2967979f979), I64(0x5fcede306f6fa16f), I64(0xfcef3f6d91917e91), I64(0xaa07a4f852525552),\n\t\tI64(0x27fdc04760609d60), I64(0x89766535bcbccabc), I64(0xaccd2b379b9b569b), I64(0x048c018a8e8e028e),\n\t\tI64(0x71155bd2a3a3b6a3), I64(0x603c186c0c0c300c), I64(0xff8af6847b7bf17b), I64(0xb5e16a803535d435),\n\t\tI64(0xe8693af51d1d741d), I64(0x5347ddb3e0e0a7e0), I64(0xf6acb321d7d77bd7), I64(0x5eed999cc2c22fc2),\n\t\tI64(0x6d965c432e2eb82e), I64(0x627a96294b4b314b), I64(0xa321e15dfefedffe), I64(0x8216aed557574157),\n\t\tI64(0xa8412abd15155415), I64(0x9fb6eee87777c177), I64(0xa5eb6e923737dc37), I64(0x7b56d79ee5e5b3e5),\n\t\tI64(0x8cd923139f9f469f), I64(0xd317fd23f0f0e7f0), I64(0x6a7f94204a4a354a), I64(0x9e95a944dada4fda),\n\t\tI64(0xfa25b0a258587d58), I64(0x06ca8fcfc9c903c9), I64(0x558d527c2929a429), I64(0x5022145a0a0a280a),\n\t\tI64(0xe14f7f50b1b1feb1), I64(0x691a5dc9a0a0baa0), I64(0x7fdad6146b6bb16b), I64(0x5cab17d985852e85),\n\t\tI64(0x8173673cbdbdcebd), I64(0xd234ba8f5d5d695d), I64(0x8050209010104010), I64(0xf303f507f4f4f7f4),\n\t\tI64(0x16c08bddcbcb0bcb), I64(0xedc67cd33e3ef83e), I64(0x28110a2d05051405), I64(0x1fe6ce7867678167),\n\t\tI64(0x7353d597e4e4b7e4), I64(0x25bb4e0227279c27), I64(0x3258827341411941), I64(0x2c9d0ba78b8b168b),\n\t\tI64(0x510153f6a7a7a6a7), I64(0xcf94fab27d7de97d), I64(0xdcfb374995956e95), I64(0x8e9fad56d8d847d8),\n\t\tI64(0x8b30eb70fbfbcbfb), I64(0x2371c1cdeeee9fee), I64(0xc791f8bb7c7ced7c), I64(0x17e3cc7166668566),\n\t\tI64(0xa68ea77bdddd53dd), I64(0xb84b2eaf17175c17), I64(0x02468e4547470147), I64(0x84dc211a9e9e429e),\n\t\tI64(0x1ec589d4caca0fca), I64(0x75995a582d2db42d), I64(0x9179632ebfbfc6bf), I64(0x381b0e3f07071c07),\n\t\tI64(0x012347acadad8ead), I64(0xea2fb4b05a5a755a), I64(0x6cb51bef83833683), I64(0x85ff66b63333cc33),\n\t\tI64(0x3ff2c65c63639163), I64(0x100a041202020802), I64(0x39384993aaaa92aa), I64(0xafa8e2de7171d971),\n\t\tI64(0x0ecf8dc6c8c807c8), I64(0xc87d32d119196419), I64(0x7270923b49493949), I64(0x869aaf5fd9d943d9),\n\t\tI64(0xc31df931f2f2eff2), I64(0x4b48dba8e3e3abe3), I64(0xe22ab6b95b5b715b), I64(0x34920dbc88881a88),\n\t\tI64(0xa4c8293e9a9a529a), I64(0x2dbe4c0b26269826), I64(0x8dfa64bf3232c832), I64(0xe94a7d59b0b0fab0),\n\t\tI64(0x1b6acff2e9e983e9), I64(0x78331e770f0f3c0f), I64(0xe6a6b733d5d573d5), I64(0x74ba1df480803a80),\n\t\tI64(0x997c6127bebec2be), I64(0x26de87ebcdcd13cd), I64(0xbde468893434d034), I64(0x7a75903248483d48),\n\t\tI64(0xab24e354ffffdbff), I64(0xf78ff48d7a7af57a), I64(0xf4ea3d6490907a90), I64(0xc23ebe9d5f5f615f),\n\t\tI64(0x1da0403d20208020), I64(0x67d5d00f6868bd68), I64(0xd07234ca1a1a681a), I64(0x192c41b7aeae82ae),\n\t\tI64(0xc95e757db4b4eab4), I64(0x9a19a8ce54544d54), I64(0xece53b7f93937693), I64(0x0daa442f22228822),\n\t\tI64(0x07e9c86364648d64), I64(0xdb12ff2af1f1e3f1), I64(0xbfa2e6cc7373d173), I64(0x905a248212124812),\n\t\tI64(0x3a5d807a40401d40), I64(0x4028104808082008), I64(0x56e89b95c3c32bc3), I64(0x337bc5dfecec97ec),\n\t\tI64(0x9690ab4ddbdb4bdb), I64(0x611f5fc0a1a1bea1), I64(0x1c8307918d8d0e8d), I64(0xf5c97ac83d3df43d),\n\t\tI64(0xccf1335b97976697), I64(0x0000000000000000), I64(0x36d483f9cfcf1bcf), I64(0x4587566e2b2bac2b),\n\t\tI64(0x97b3ece17676c576), I64(0x64b019e682823282), I64(0xfea9b128d6d67fd6), I64(0xd87736c31b1b6c1b),\n\t\tI64(0xc15b7774b5b5eeb5), I64(0x112943beafaf86af), I64(0x77dfd41d6a6ab56a), I64(0xba0da0ea50505d50),\n\t\tI64(0x124c8a5745450945), I64(0xcb18fb38f3f3ebf3), I64(0x9df060ad3030c030), I64(0x2b74c3c4efef9bef),\n\t\tI64(0xe5c37eda3f3ffc3f), I64(0x921caac755554955), I64(0x791059dba2a2b2a2), I64(0x0365c9e9eaea8fea),\n\t\tI64(0x0fecca6a65658965), I64(0xb9686903babad2ba), I64(0x65935e4a2f2fbc2f), I64(0x4ee79d8ec0c027c0),\n\t\tI64(0xbe81a160dede5fde), I64(0xe06c38fc1c1c701c), I64(0xbb2ee746fdfdd3fd), I64(0x52649a1f4d4d294d),\n\t\tI64(0xe4e0397692927292), I64(0x8fbceafa7575c975), I64(0x301e0c3606061806), I64(0x249809ae8a8a128a),\n\t\tI64(0xf940794bb2b2f2b2), I64(0x6359d185e6e6bfe6), I64(0x70361c7e0e0e380e), I64(0xf8633ee71f1f7c1f),\n\t\tI64(0x37f7c45562629562), I64(0xeea3b53ad4d477d4), I64(0x29324d81a8a89aa8), I64(0xc4f4315296966296),\n\t\tI64(0x9b3aef62f9f9c3f9), I64(0x66f697a3c5c533c5), I64(0x35b14a1025259425), I64(0xf220b2ab59597959),\n\t\tI64(0x54ae15d084842a84), I64(0xb7a7e4c57272d572), I64(0xd5dd72ec3939e439), I64(0x5a6198164c4c2d4c),\n\t\tI64(0xca3bbc945e5e655e), I64(0xe785f09f7878fd78), I64(0xddd870e53838e038), I64(0x148605988c8c0a8c),\n\t\tI64(0xc6b2bf17d1d163d1), I64(0x410b57e4a5a5aea5), I64(0x434dd9a1e2e2afe2), I64(0x2ff8c24e61619961),\n\t\tI64(0xf1457b42b3b3f6b3), I64(0x15a5423421218421), I64(0x94d625089c9c4a9c), I64(0xf0663cee1e1e781e),\n\t\tI64(0x2252866143431143), I64(0x76fc93b1c7c73bc7), I64(0xb32be54ffcfcd7fc), I64(0x2014082404041004),\n\t\tI64(0xb208a2e351515951), I64(0xbcc72f2599995e99), I64(0x4fc4da226d6da96d), I64(0x68391a650d0d340d),\n\t\tI64(0x8335e979fafacffa), I64(0xb684a369dfdf5bdf), I64(0xd79bfca97e7ee57e), I64(0x3db4481924249024),\n\t\tI64(0xc5d776fe3b3bec3b), I64(0x313d4b9aabab96ab), I64(0x3ed181f0cece1fce), I64(0x8855229911114411),\n\t\tI64(0x0c8903838f8f068f), I64(0x4a6b9c044e4e254e), I64(0xd1517366b7b7e6b7), I64(0x0b60cbe0ebeb8beb),\n\t\tI64(0xfdcc78c13c3cf03c), I64(0x7cbf1ffd81813e81), I64(0xd4fe354094946a94), I64(0xeb0cf31cf7f7fbf7),\n\t\tI64(0xa1676f18b9b9deb9), I64(0x985f268b13134c13), I64(0x7d9c58512c2cb02c), I64(0xd6b8bb05d3d36bd3),\n\t\tI64(0x6b5cd38ce7e7bbe7), I64(0x57cbdc396e6ea56e), I64(0x6ef395aac4c437c4), I64(0x180f061b03030c03),\n\t\tI64(0x8a13acdc56564556), I64(0x1a49885e44440d44), I64(0xdf9efea07f7fe17f), I64(0x21374f88a9a99ea9),\n\t\tI64(0x4d8254672a2aa82a), I64(0xb16d6b0abbbbd6bb), I64(0x46e29f87c1c123c1), I64(0xa202a6f153535153),\n\t\tI64(0xae8ba572dcdc57dc), I64(0x582716530b0b2c0b), I64(0x9cd327019d9d4e9d), I64(0x47c1d82b6c6cad6c),\n\t\tI64(0x95f562a43131c431), I64(0x87b9e8f37474cd74), I64(0xe309f115f6f6fff6), I64(0x0a438c4c46460546),\n\t\tI64(0x092645a5acac8aac), I64(0x3c970fb589891e89), I64(0xa04428b414145014), I64(0x5b42dfbae1e1a3e1),\n\t\tI64(0xb04e2ca616165816), I64(0xcdd274f73a3ae83a), I64(0x6fd0d2066969b969), I64(0x482d124109092409),\n\t\tI64(0xa7ade0d77070dd70), I64(0xd954716fb6b6e2b6), I64(0xceb7bd1ed0d067d0), I64(0x3b7ec7d6eded93ed),\n\t\tI64(0x2edb85e2cccc17cc), I64(0x2a57846842421542), I64(0xb4c22d2c98985a98), I64(0x490e55eda4a4aaa4),\n\t\tI64(0x5d8850752828a028), I64(0xda31b8865c5c6d5c), I64(0x933fed6bf8f8c7f8), I64(0x44a411c286862286),\n\t\t}, {\n\t\t/* C5 vectors */\n\t\tI64(0x18c07830d8181860), I64(0x2305af462623238c), I64(0xc67ef991b8c6c63f), I64(0xe8136fcdfbe8e887),\n\t\tI64(0x874ca113cb878726), I64(0xb8a9626d11b8b8da), I64(0x0108050209010104), I64(0x4f426e9e0d4f4f21),\n\t\tI64(0x36adee6c9b3636d8), I64(0xa6590451ffa6a6a2), I64(0xd2debdb90cd2d26f), I64(0xf5fb06f70ef5f5f3),\n\t\tI64(0x79ef80f2967979f9), I64(0x6f5fcede306f6fa1), I64(0x91fcef3f6d91917e), I64(0x52aa07a4f8525255),\n\t\tI64(0x6027fdc04760609d), I64(0xbc89766535bcbcca), I64(0x9baccd2b379b9b56), I64(0x8e048c018a8e8e02),\n\t\tI64(0xa371155bd2a3a3b6), I64(0x0c603c186c0c0c30), I64(0x7bff8af6847b7bf1), I64(0x35b5e16a803535d4),\n\t\tI64(0x1de8693af51d1d74), I64(0xe05347ddb3e0e0a7), I64(0xd7f6acb321d7d77b), I64(0xc25eed999cc2c22f),\n\t\tI64(0x2e6d965c432e2eb8), I64(0x4b627a96294b4b31), I64(0xfea321e15dfefedf), I64(0x578216aed5575741),\n\t\tI64(0x15a8412abd151554), I64(0x779fb6eee87777c1), I64(0x37a5eb6e923737dc), I64(0xe57b56d79ee5e5b3),\n\t\tI64(0x9f8cd923139f9f46), I64(0xf0d317fd23f0f0e7), I64(0x4a6a7f94204a4a35), I64(0xda9e95a944dada4f),\n\t\tI64(0x58fa25b0a258587d), I64(0xc906ca8fcfc9c903), I64(0x29558d527c2929a4), I64(0x0a5022145a0a0a28),\n\t\tI64(0xb1e14f7f50b1b1fe), I64(0xa0691a5dc9a0a0ba), I64(0x6b7fdad6146b6bb1), I64(0x855cab17d985852e),\n\t\tI64(0xbd8173673cbdbdce), I64(0x5dd234ba8f5d5d69), I64(0x1080502090101040), I64(0xf4f303f507f4f4f7),\n\t\tI64(0xcb16c08bddcbcb0b), I64(0x3eedc67cd33e3ef8), I64(0x0528110a2d050514), I64(0x671fe6ce78676781),\n\t\tI64(0xe47353d597e4e4b7), I64(0x2725bb4e0227279c), I64(0x4132588273414119), I64(0x8b2c9d0ba78b8b16),\n\t\tI64(0xa7510153f6a7a7a6), I64(0x7dcf94fab27d7de9), I64(0x95dcfb374995956e), I64(0xd88e9fad56d8d847),\n\t\tI64(0xfb8b30eb70fbfbcb), I64(0xee2371c1cdeeee9f), I64(0x7cc791f8bb7c7ced), I64(0x6617e3cc71666685),\n\t\tI64(0xdda68ea77bdddd53), I64(0x17b84b2eaf17175c), I64(0x4702468e45474701), I64(0x9e84dc211a9e9e42),\n\t\tI64(0xca1ec589d4caca0f), I64(0x2d75995a582d2db4), I64(0xbf9179632ebfbfc6), I64(0x07381b0e3f07071c),\n\t\tI64(0xad012347acadad8e), I64(0x5aea2fb4b05a5a75), I64(0x836cb51bef838336), I64(0x3385ff66b63333cc),\n\t\tI64(0x633ff2c65c636391), I64(0x02100a0412020208), I64(0xaa39384993aaaa92), I64(0x71afa8e2de7171d9),\n\t\tI64(0xc80ecf8dc6c8c807), I64(0x19c87d32d1191964), I64(0x497270923b494939), I64(0xd9869aaf5fd9d943),\n\t\tI64(0xf2c31df931f2f2ef), I64(0xe34b48dba8e3e3ab), I64(0x5be22ab6b95b5b71), I64(0x8834920dbc88881a),\n\t\tI64(0x9aa4c8293e9a9a52), I64(0x262dbe4c0b262698), I64(0x328dfa64bf3232c8), I64(0xb0e94a7d59b0b0fa),\n\t\tI64(0xe91b6acff2e9e983), I64(0x0f78331e770f0f3c), I64(0xd5e6a6b733d5d573), I64(0x8074ba1df480803a),\n\t\tI64(0xbe997c6127bebec2), I64(0xcd26de87ebcdcd13), I64(0x34bde468893434d0), I64(0x487a75903248483d),\n\t\tI64(0xffab24e354ffffdb), I64(0x7af78ff48d7a7af5), I64(0x90f4ea3d6490907a), I64(0x5fc23ebe9d5f5f61),\n\t\tI64(0x201da0403d202080), I64(0x6867d5d00f6868bd), I64(0x1ad07234ca1a1a68), I64(0xae192c41b7aeae82),\n\t\tI64(0xb4c95e757db4b4ea), I64(0x549a19a8ce54544d), I64(0x93ece53b7f939376), I64(0x220daa442f222288),\n\t\tI64(0x6407e9c86364648d), I64(0xf1db12ff2af1f1e3), I64(0x73bfa2e6cc7373d1), I64(0x12905a2482121248),\n\t\tI64(0x403a5d807a40401d), I64(0x0840281048080820), I64(0xc356e89b95c3c32b), I64(0xec337bc5dfecec97),\n\t\tI64(0xdb9690ab4ddbdb4b), I64(0xa1611f5fc0a1a1be), I64(0x8d1c8307918d8d0e), I64(0x3df5c97ac83d3df4),\n\t\tI64(0x97ccf1335b979766), I64(0x0000000000000000), I64(0xcf36d483f9cfcf1b), I64(0x2b4587566e2b2bac),\n\t\tI64(0x7697b3ece17676c5), I64(0x8264b019e6828232), I64(0xd6fea9b128d6d67f), I64(0x1bd87736c31b1b6c),\n\t\tI64(0xb5c15b7774b5b5ee), I64(0xaf112943beafaf86), I64(0x6a77dfd41d6a6ab5), I64(0x50ba0da0ea50505d),\n\t\tI64(0x45124c8a57454509), I64(0xf3cb18fb38f3f3eb), I64(0x309df060ad3030c0), I64(0xef2b74c3c4efef9b),\n\t\tI64(0x3fe5c37eda3f3ffc), I64(0x55921caac7555549), I64(0xa2791059dba2a2b2), I64(0xea0365c9e9eaea8f),\n\t\tI64(0x650fecca6a656589), I64(0xbab9686903babad2), I64(0x2f65935e4a2f2fbc), I64(0xc04ee79d8ec0c027),\n\t\tI64(0xdebe81a160dede5f), I64(0x1ce06c38fc1c1c70), I64(0xfdbb2ee746fdfdd3), I64(0x4d52649a1f4d4d29),\n\t\tI64(0x92e4e03976929272), I64(0x758fbceafa7575c9), I64(0x06301e0c36060618), I64(0x8a249809ae8a8a12),\n\t\tI64(0xb2f940794bb2b2f2), I64(0xe66359d185e6e6bf), I64(0x0e70361c7e0e0e38), I64(0x1ff8633ee71f1f7c),\n\t\tI64(0x6237f7c455626295), I64(0xd4eea3b53ad4d477), I64(0xa829324d81a8a89a), I64(0x96c4f43152969662),\n\t\tI64(0xf99b3aef62f9f9c3), I64(0xc566f697a3c5c533), I64(0x2535b14a10252594), I64(0x59f220b2ab595979),\n\t\tI64(0x8454ae15d084842a), I64(0x72b7a7e4c57272d5), I64(0x39d5dd72ec3939e4), I64(0x4c5a6198164c4c2d),\n\t\tI64(0x5eca3bbc945e5e65), I64(0x78e785f09f7878fd), I64(0x38ddd870e53838e0), I64(0x8c148605988c8c0a),\n\t\tI64(0xd1c6b2bf17d1d163), I64(0xa5410b57e4a5a5ae), I64(0xe2434dd9a1e2e2af), I64(0x612ff8c24e616199),\n\t\tI64(0xb3f1457b42b3b3f6), I64(0x2115a54234212184), I64(0x9c94d625089c9c4a), I64(0x1ef0663cee1e1e78),\n\t\tI64(0x4322528661434311), I64(0xc776fc93b1c7c73b), I64(0xfcb32be54ffcfcd7), I64(0x0420140824040410),\n\t\tI64(0x51b208a2e3515159), I64(0x99bcc72f2599995e), I64(0x6d4fc4da226d6da9), I64(0x0d68391a650d0d34),\n\t\tI64(0xfa8335e979fafacf), I64(0xdfb684a369dfdf5b), I64(0x7ed79bfca97e7ee5), I64(0x243db44819242490),\n\t\tI64(0x3bc5d776fe3b3bec), I64(0xab313d4b9aabab96), I64(0xce3ed181f0cece1f), I64(0x1188552299111144),\n\t\tI64(0x8f0c8903838f8f06), I64(0x4e4a6b9c044e4e25), I64(0xb7d1517366b7b7e6), I64(0xeb0b60cbe0ebeb8b),\n\t\tI64(0x3cfdcc78c13c3cf0), I64(0x817cbf1ffd81813e), I64(0x94d4fe354094946a), I64(0xf7eb0cf31cf7f7fb),\n\t\tI64(0xb9a1676f18b9b9de), I64(0x13985f268b13134c), I64(0x2c7d9c58512c2cb0), I64(0xd3d6b8bb05d3d36b),\n\t\tI64(0xe76b5cd38ce7e7bb), I64(0x6e57cbdc396e6ea5), I64(0xc46ef395aac4c437), I64(0x03180f061b03030c),\n\t\tI64(0x568a13acdc565645), I64(0x441a49885e44440d), I64(0x7fdf9efea07f7fe1), I64(0xa921374f88a9a99e),\n\t\tI64(0x2a4d8254672a2aa8), I64(0xbbb16d6b0abbbbd6), I64(0xc146e29f87c1c123), I64(0x53a202a6f1535351),\n\t\tI64(0xdcae8ba572dcdc57), I64(0x0b582716530b0b2c), I64(0x9d9cd327019d9d4e), I64(0x6c47c1d82b6c6cad),\n\t\tI64(0x3195f562a43131c4), I64(0x7487b9e8f37474cd), I64(0xf6e309f115f6f6ff), I64(0x460a438c4c464605),\n\t\tI64(0xac092645a5acac8a), I64(0x893c970fb589891e), I64(0x14a04428b4141450), I64(0xe15b42dfbae1e1a3),\n\t\tI64(0x16b04e2ca6161658), I64(0x3acdd274f73a3ae8), I64(0x696fd0d2066969b9), I64(0x09482d1241090924),\n\t\tI64(0x70a7ade0d77070dd), I64(0xb6d954716fb6b6e2), I64(0xd0ceb7bd1ed0d067), I64(0xed3b7ec7d6eded93),\n\t\tI64(0xcc2edb85e2cccc17), I64(0x422a578468424215), I64(0x98b4c22d2c98985a), I64(0xa4490e55eda4a4aa),\n\t\tI64(0x285d8850752828a0), I64(0x5cda31b8865c5c6d), I64(0xf8933fed6bf8f8c7), I64(0x8644a411c2868622),\n\t\t}, {\n\t\t/* C6 vectors */\n\t\tI64(0x6018c07830d81818), I64(0x8c2305af46262323), I64(0x3fc67ef991b8c6c6), I64(0x87e8136fcdfbe8e8),\n\t\tI64(0x26874ca113cb8787), I64(0xdab8a9626d11b8b8), I64(0x0401080502090101), I64(0x214f426e9e0d4f4f),\n\t\tI64(0xd836adee6c9b3636), I64(0xa2a6590451ffa6a6), I64(0x6fd2debdb90cd2d2), I64(0xf3f5fb06f70ef5f5),\n\t\tI64(0xf979ef80f2967979), I64(0xa16f5fcede306f6f), I64(0x7e91fcef3f6d9191), I64(0x5552aa07a4f85252),\n\t\tI64(0x9d6027fdc0476060), I64(0xcabc89766535bcbc), I64(0x569baccd2b379b9b), I64(0x028e048c018a8e8e),\n\t\tI64(0xb6a371155bd2a3a3), I64(0x300c603c186c0c0c), I64(0xf17bff8af6847b7b), I64(0xd435b5e16a803535),\n\t\tI64(0x741de8693af51d1d), I64(0xa7e05347ddb3e0e0), I64(0x7bd7f6acb321d7d7), I64(0x2fc25eed999cc2c2),\n\t\tI64(0xb82e6d965c432e2e), I64(0x314b627a96294b4b), I64(0xdffea321e15dfefe), I64(0x41578216aed55757),\n\t\tI64(0x5415a8412abd1515), I64(0xc1779fb6eee87777), I64(0xdc37a5eb6e923737), I64(0xb3e57b56d79ee5e5),\n\t\tI64(0x469f8cd923139f9f), I64(0xe7f0d317fd23f0f0), I64(0x354a6a7f94204a4a), I64(0x4fda9e95a944dada),\n\t\tI64(0x7d58fa25b0a25858), I64(0x03c906ca8fcfc9c9), I64(0xa429558d527c2929), I64(0x280a5022145a0a0a),\n\t\tI64(0xfeb1e14f7f50b1b1), I64(0xbaa0691a5dc9a0a0), I64(0xb16b7fdad6146b6b), I64(0x2e855cab17d98585),\n\t\tI64(0xcebd8173673cbdbd), I64(0x695dd234ba8f5d5d), I64(0x4010805020901010), I64(0xf7f4f303f507f4f4),\n\t\tI64(0x0bcb16c08bddcbcb), I64(0xf83eedc67cd33e3e), I64(0x140528110a2d0505), I64(0x81671fe6ce786767),\n\t\tI64(0xb7e47353d597e4e4), I64(0x9c2725bb4e022727), I64(0x1941325882734141), I64(0x168b2c9d0ba78b8b),\n\t\tI64(0xa6a7510153f6a7a7), I64(0xe97dcf94fab27d7d), I64(0x6e95dcfb37499595), I64(0x47d88e9fad56d8d8),\n\t\tI64(0xcbfb8b30eb70fbfb), I64(0x9fee2371c1cdeeee), I64(0xed7cc791f8bb7c7c), I64(0x856617e3cc716666),\n\t\tI64(0x53dda68ea77bdddd), I64(0x5c17b84b2eaf1717), I64(0x014702468e454747), I64(0x429e84dc211a9e9e),\n\t\tI64(0x0fca1ec589d4caca), I64(0xb42d75995a582d2d), I64(0xc6bf9179632ebfbf), I64(0x1c07381b0e3f0707),\n\t\tI64(0x8ead012347acadad), I64(0x755aea2fb4b05a5a), I64(0x36836cb51bef8383), I64(0xcc3385ff66b63333),\n\t\tI64(0x91633ff2c65c6363), I64(0x0802100a04120202), I64(0x92aa39384993aaaa), I64(0xd971afa8e2de7171),\n\t\tI64(0x07c80ecf8dc6c8c8), I64(0x6419c87d32d11919), I64(0x39497270923b4949), I64(0x43d9869aaf5fd9d9),\n\t\tI64(0xeff2c31df931f2f2), I64(0xabe34b48dba8e3e3), I64(0x715be22ab6b95b5b), I64(0x1a8834920dbc8888),\n\t\tI64(0x529aa4c8293e9a9a), I64(0x98262dbe4c0b2626), I64(0xc8328dfa64bf3232), I64(0xfab0e94a7d59b0b0),\n\t\tI64(0x83e91b6acff2e9e9), I64(0x3c0f78331e770f0f), I64(0x73d5e6a6b733d5d5), I64(0x3a8074ba1df48080),\n\t\tI64(0xc2be997c6127bebe), I64(0x13cd26de87ebcdcd), I64(0xd034bde468893434), I64(0x3d487a7590324848),\n\t\tI64(0xdbffab24e354ffff), I64(0xf57af78ff48d7a7a), I64(0x7a90f4ea3d649090), I64(0x615fc23ebe9d5f5f),\n\t\tI64(0x80201da0403d2020), I64(0xbd6867d5d00f6868), I64(0x681ad07234ca1a1a), I64(0x82ae192c41b7aeae),\n\t\tI64(0xeab4c95e757db4b4), I64(0x4d549a19a8ce5454), I64(0x7693ece53b7f9393), I64(0x88220daa442f2222),\n\t\tI64(0x8d6407e9c8636464), I64(0xe3f1db12ff2af1f1), I64(0xd173bfa2e6cc7373), I64(0x4812905a24821212),\n\t\tI64(0x1d403a5d807a4040), I64(0x2008402810480808), I64(0x2bc356e89b95c3c3), I64(0x97ec337bc5dfecec),\n\t\tI64(0x4bdb9690ab4ddbdb), I64(0xbea1611f5fc0a1a1), I64(0x0e8d1c8307918d8d), I64(0xf43df5c97ac83d3d),\n\t\tI64(0x6697ccf1335b9797), I64(0x0000000000000000), I64(0x1bcf36d483f9cfcf), I64(0xac2b4587566e2b2b),\n\t\tI64(0xc57697b3ece17676), I64(0x328264b019e68282), I64(0x7fd6fea9b128d6d6), I64(0x6c1bd87736c31b1b),\n\t\tI64(0xeeb5c15b7774b5b5), I64(0x86af112943beafaf), I64(0xb56a77dfd41d6a6a), I64(0x5d50ba0da0ea5050),\n\t\tI64(0x0945124c8a574545), I64(0xebf3cb18fb38f3f3), I64(0xc0309df060ad3030), I64(0x9bef2b74c3c4efef),\n\t\tI64(0xfc3fe5c37eda3f3f), I64(0x4955921caac75555), I64(0xb2a2791059dba2a2), I64(0x8fea0365c9e9eaea),\n\t\tI64(0x89650fecca6a6565), I64(0xd2bab9686903baba), I64(0xbc2f65935e4a2f2f), I64(0x27c04ee79d8ec0c0),\n\t\tI64(0x5fdebe81a160dede), I64(0x701ce06c38fc1c1c), I64(0xd3fdbb2ee746fdfd), I64(0x294d52649a1f4d4d),\n\t\tI64(0x7292e4e039769292), I64(0xc9758fbceafa7575), I64(0x1806301e0c360606), I64(0x128a249809ae8a8a),\n\t\tI64(0xf2b2f940794bb2b2), I64(0xbfe66359d185e6e6), I64(0x380e70361c7e0e0e), I64(0x7c1ff8633ee71f1f),\n\t\tI64(0x956237f7c4556262), I64(0x77d4eea3b53ad4d4), I64(0x9aa829324d81a8a8), I64(0x6296c4f431529696),\n\t\tI64(0xc3f99b3aef62f9f9), I64(0x33c566f697a3c5c5), I64(0x942535b14a102525), I64(0x7959f220b2ab5959),\n\t\tI64(0x2a8454ae15d08484), I64(0xd572b7a7e4c57272), I64(0xe439d5dd72ec3939), I64(0x2d4c5a6198164c4c),\n\t\tI64(0x655eca3bbc945e5e), I64(0xfd78e785f09f7878), I64(0xe038ddd870e53838), I64(0x0a8c148605988c8c),\n\t\tI64(0x63d1c6b2bf17d1d1), I64(0xaea5410b57e4a5a5), I64(0xafe2434dd9a1e2e2), I64(0x99612ff8c24e6161),\n\t\tI64(0xf6b3f1457b42b3b3), I64(0x842115a542342121), I64(0x4a9c94d625089c9c), I64(0x781ef0663cee1e1e),\n\t\tI64(0x1143225286614343), I64(0x3bc776fc93b1c7c7), I64(0xd7fcb32be54ffcfc), I64(0x1004201408240404),\n\t\tI64(0x5951b208a2e35151), I64(0x5e99bcc72f259999), I64(0xa96d4fc4da226d6d), I64(0x340d68391a650d0d),\n\t\tI64(0xcffa8335e979fafa), I64(0x5bdfb684a369dfdf), I64(0xe57ed79bfca97e7e), I64(0x90243db448192424),\n\t\tI64(0xec3bc5d776fe3b3b), I64(0x96ab313d4b9aabab), I64(0x1fce3ed181f0cece), I64(0x4411885522991111),\n\t\tI64(0x068f0c8903838f8f), I64(0x254e4a6b9c044e4e), I64(0xe6b7d1517366b7b7), I64(0x8beb0b60cbe0ebeb),\n\t\tI64(0xf03cfdcc78c13c3c), I64(0x3e817cbf1ffd8181), I64(0x6a94d4fe35409494), I64(0xfbf7eb0cf31cf7f7),\n\t\tI64(0xdeb9a1676f18b9b9), I64(0x4c13985f268b1313), I64(0xb02c7d9c58512c2c), I64(0x6bd3d6b8bb05d3d3),\n\t\tI64(0xbbe76b5cd38ce7e7), I64(0xa56e57cbdc396e6e), I64(0x37c46ef395aac4c4), I64(0x0c03180f061b0303),\n\t\tI64(0x45568a13acdc5656), I64(0x0d441a49885e4444), I64(0xe17fdf9efea07f7f), I64(0x9ea921374f88a9a9),\n\t\tI64(0xa82a4d8254672a2a), I64(0xd6bbb16d6b0abbbb), I64(0x23c146e29f87c1c1), I64(0x5153a202a6f15353),\n\t\tI64(0x57dcae8ba572dcdc), I64(0x2c0b582716530b0b), I64(0x4e9d9cd327019d9d), I64(0xad6c47c1d82b6c6c),\n\t\tI64(0xc43195f562a43131), I64(0xcd7487b9e8f37474), I64(0xfff6e309f115f6f6), I64(0x05460a438c4c4646),\n\t\tI64(0x8aac092645a5acac), I64(0x1e893c970fb58989), I64(0x5014a04428b41414), I64(0xa3e15b42dfbae1e1),\n\t\tI64(0x5816b04e2ca61616), I64(0xe83acdd274f73a3a), I64(0xb9696fd0d2066969), I64(0x2409482d12410909),\n\t\tI64(0xdd70a7ade0d77070), I64(0xe2b6d954716fb6b6), I64(0x67d0ceb7bd1ed0d0), I64(0x93ed3b7ec7d6eded),\n\t\tI64(0x17cc2edb85e2cccc), I64(0x15422a5784684242), I64(0x5a98b4c22d2c9898), I64(0xaaa4490e55eda4a4),\n\t\tI64(0xa0285d8850752828), I64(0x6d5cda31b8865c5c), I64(0xc7f8933fed6bf8f8), I64(0x228644a411c28686),\n\t\t}, {\n\t\t/* C7 vectors */\n\t\tI64(0x186018c07830d818), I64(0x238c2305af462623), I64(0xc63fc67ef991b8c6), I64(0xe887e8136fcdfbe8),\n\t\tI64(0x8726874ca113cb87), I64(0xb8dab8a9626d11b8), I64(0x0104010805020901), I64(0x4f214f426e9e0d4f),\n\t\tI64(0x36d836adee6c9b36), I64(0xa6a2a6590451ffa6), I64(0xd26fd2debdb90cd2), I64(0xf5f3f5fb06f70ef5),\n\t\tI64(0x79f979ef80f29679), I64(0x6fa16f5fcede306f), I64(0x917e91fcef3f6d91), I64(0x525552aa07a4f852),\n\t\tI64(0x609d6027fdc04760), I64(0xbccabc89766535bc), I64(0x9b569baccd2b379b), I64(0x8e028e048c018a8e),\n\t\tI64(0xa3b6a371155bd2a3), I64(0x0c300c603c186c0c), I64(0x7bf17bff8af6847b), I64(0x35d435b5e16a8035),\n\t\tI64(0x1d741de8693af51d), I64(0xe0a7e05347ddb3e0), I64(0xd77bd7f6acb321d7), I64(0xc22fc25eed999cc2),\n\t\tI64(0x2eb82e6d965c432e), I64(0x4b314b627a96294b), I64(0xfedffea321e15dfe), I64(0x5741578216aed557),\n\t\tI64(0x155415a8412abd15), I64(0x77c1779fb6eee877), I64(0x37dc37a5eb6e9237), I64(0xe5b3e57b56d79ee5),\n\t\tI64(0x9f469f8cd923139f), I64(0xf0e7f0d317fd23f0), I64(0x4a354a6a7f94204a), I64(0xda4fda9e95a944da),\n\t\tI64(0x587d58fa25b0a258), I64(0xc903c906ca8fcfc9), I64(0x29a429558d527c29), I64(0x0a280a5022145a0a),\n\t\tI64(0xb1feb1e14f7f50b1), I64(0xa0baa0691a5dc9a0), I64(0x6bb16b7fdad6146b), I64(0x852e855cab17d985),\n\t\tI64(0xbdcebd8173673cbd), I64(0x5d695dd234ba8f5d), I64(0x1040108050209010), I64(0xf4f7f4f303f507f4),\n\t\tI64(0xcb0bcb16c08bddcb), I64(0x3ef83eedc67cd33e), I64(0x05140528110a2d05), I64(0x6781671fe6ce7867),\n\t\tI64(0xe4b7e47353d597e4), I64(0x279c2725bb4e0227), I64(0x4119413258827341), I64(0x8b168b2c9d0ba78b),\n\t\tI64(0xa7a6a7510153f6a7), I64(0x7de97dcf94fab27d), I64(0x956e95dcfb374995), I64(0xd847d88e9fad56d8),\n\t\tI64(0xfbcbfb8b30eb70fb), I64(0xee9fee2371c1cdee), I64(0x7ced7cc791f8bb7c), I64(0x66856617e3cc7166),\n\t\tI64(0xdd53dda68ea77bdd), I64(0x175c17b84b2eaf17), I64(0x47014702468e4547), I64(0x9e429e84dc211a9e),\n\t\tI64(0xca0fca1ec589d4ca), I64(0x2db42d75995a582d), I64(0xbfc6bf9179632ebf), I64(0x071c07381b0e3f07),\n\t\tI64(0xad8ead012347acad), I64(0x5a755aea2fb4b05a), I64(0x8336836cb51bef83), I64(0x33cc3385ff66b633),\n\t\tI64(0x6391633ff2c65c63), I64(0x020802100a041202), I64(0xaa92aa39384993aa), I64(0x71d971afa8e2de71),\n\t\tI64(0xc807c80ecf8dc6c8), I64(0x196419c87d32d119), I64(0x4939497270923b49), I64(0xd943d9869aaf5fd9),\n\t\tI64(0xf2eff2c31df931f2), I64(0xe3abe34b48dba8e3), I64(0x5b715be22ab6b95b), I64(0x881a8834920dbc88),\n\t\tI64(0x9a529aa4c8293e9a), I64(0x2698262dbe4c0b26), I64(0x32c8328dfa64bf32), I64(0xb0fab0e94a7d59b0),\n\t\tI64(0xe983e91b6acff2e9), I64(0x0f3c0f78331e770f), I64(0xd573d5e6a6b733d5), I64(0x803a8074ba1df480),\n\t\tI64(0xbec2be997c6127be), I64(0xcd13cd26de87ebcd), I64(0x34d034bde4688934), I64(0x483d487a75903248),\n\t\tI64(0xffdbffab24e354ff), I64(0x7af57af78ff48d7a), I64(0x907a90f4ea3d6490), I64(0x5f615fc23ebe9d5f),\n\t\tI64(0x2080201da0403d20), I64(0x68bd6867d5d00f68), I64(0x1a681ad07234ca1a), I64(0xae82ae192c41b7ae),\n\t\tI64(0xb4eab4c95e757db4), I64(0x544d549a19a8ce54), I64(0x937693ece53b7f93), I64(0x2288220daa442f22),\n\t\tI64(0x648d6407e9c86364), I64(0xf1e3f1db12ff2af1), I64(0x73d173bfa2e6cc73), I64(0x124812905a248212),\n\t\tI64(0x401d403a5d807a40), I64(0x0820084028104808), I64(0xc32bc356e89b95c3), I64(0xec97ec337bc5dfec),\n\t\tI64(0xdb4bdb9690ab4ddb), I64(0xa1bea1611f5fc0a1), I64(0x8d0e8d1c8307918d), I64(0x3df43df5c97ac83d),\n\t\tI64(0x976697ccf1335b97), I64(0x0000000000000000), I64(0xcf1bcf36d483f9cf), I64(0x2bac2b4587566e2b),\n\t\tI64(0x76c57697b3ece176), I64(0x82328264b019e682), I64(0xd67fd6fea9b128d6), I64(0x1b6c1bd87736c31b),\n\t\tI64(0xb5eeb5c15b7774b5), I64(0xaf86af112943beaf), I64(0x6ab56a77dfd41d6a), I64(0x505d50ba0da0ea50),\n\t\tI64(0x450945124c8a5745), I64(0xf3ebf3cb18fb38f3), I64(0x30c0309df060ad30), I64(0xef9bef2b74c3c4ef),\n\t\tI64(0x3ffc3fe5c37eda3f), I64(0x554955921caac755), I64(0xa2b2a2791059dba2), I64(0xea8fea0365c9e9ea),\n\t\tI64(0x6589650fecca6a65), I64(0xbad2bab9686903ba), I64(0x2fbc2f65935e4a2f), I64(0xc027c04ee79d8ec0),\n\t\tI64(0xde5fdebe81a160de), I64(0x1c701ce06c38fc1c), I64(0xfdd3fdbb2ee746fd), I64(0x4d294d52649a1f4d),\n\t\tI64(0x927292e4e0397692), I64(0x75c9758fbceafa75), I64(0x061806301e0c3606), I64(0x8a128a249809ae8a),\n\t\tI64(0xb2f2b2f940794bb2), I64(0xe6bfe66359d185e6), I64(0x0e380e70361c7e0e), I64(0x1f7c1ff8633ee71f),\n\t\tI64(0x62956237f7c45562), I64(0xd477d4eea3b53ad4), I64(0xa89aa829324d81a8), I64(0x966296c4f4315296),\n\t\tI64(0xf9c3f99b3aef62f9), I64(0xc533c566f697a3c5), I64(0x25942535b14a1025), I64(0x597959f220b2ab59),\n\t\tI64(0x842a8454ae15d084), I64(0x72d572b7a7e4c572), I64(0x39e439d5dd72ec39), I64(0x4c2d4c5a6198164c),\n\t\tI64(0x5e655eca3bbc945e), I64(0x78fd78e785f09f78), I64(0x38e038ddd870e538), I64(0x8c0a8c148605988c),\n\t\tI64(0xd163d1c6b2bf17d1), I64(0xa5aea5410b57e4a5), I64(0xe2afe2434dd9a1e2), I64(0x6199612ff8c24e61),\n\t\tI64(0xb3f6b3f1457b42b3), I64(0x21842115a5423421), I64(0x9c4a9c94d625089c), I64(0x1e781ef0663cee1e),\n\t\tI64(0x4311432252866143), I64(0xc73bc776fc93b1c7), I64(0xfcd7fcb32be54ffc), I64(0x0410042014082404),\n\t\tI64(0x515951b208a2e351), I64(0x995e99bcc72f2599), I64(0x6da96d4fc4da226d), I64(0x0d340d68391a650d),\n\t\tI64(0xfacffa8335e979fa), I64(0xdf5bdfb684a369df), I64(0x7ee57ed79bfca97e), I64(0x2490243db4481924),\n\t\tI64(0x3bec3bc5d776fe3b), I64(0xab96ab313d4b9aab), I64(0xce1fce3ed181f0ce), I64(0x1144118855229911),\n\t\tI64(0x8f068f0c8903838f), I64(0x4e254e4a6b9c044e), I64(0xb7e6b7d1517366b7), I64(0xeb8beb0b60cbe0eb),\n\t\tI64(0x3cf03cfdcc78c13c), I64(0x813e817cbf1ffd81), I64(0x946a94d4fe354094), I64(0xf7fbf7eb0cf31cf7),\n\t\tI64(0xb9deb9a1676f18b9), I64(0x134c13985f268b13), I64(0x2cb02c7d9c58512c), I64(0xd36bd3d6b8bb05d3),\n\t\tI64(0xe7bbe76b5cd38ce7), I64(0x6ea56e57cbdc396e), I64(0xc437c46ef395aac4), I64(0x030c03180f061b03),\n\t\tI64(0x5645568a13acdc56), I64(0x440d441a49885e44), I64(0x7fe17fdf9efea07f), I64(0xa99ea921374f88a9),\n\t\tI64(0x2aa82a4d8254672a), I64(0xbbd6bbb16d6b0abb), I64(0xc123c146e29f87c1), I64(0x535153a202a6f153),\n\t\tI64(0xdc57dcae8ba572dc), I64(0x0b2c0b582716530b), I64(0x9d4e9d9cd327019d), I64(0x6cad6c47c1d82b6c),\n\t\tI64(0x31c43195f562a431), I64(0x74cd7487b9e8f374), I64(0xf6fff6e309f115f6), I64(0x4605460a438c4c46),\n\t\tI64(0xac8aac092645a5ac), I64(0x891e893c970fb589), I64(0x145014a04428b414), I64(0xe1a3e15b42dfbae1),\n\t\tI64(0x165816b04e2ca616), I64(0x3ae83acdd274f73a), I64(0x69b9696fd0d20669), I64(0x092409482d124109),\n\t\tI64(0x70dd70a7ade0d770), I64(0xb6e2b6d954716fb6), I64(0xd067d0ceb7bd1ed0), I64(0xed93ed3b7ec7d6ed),\n\t\tI64(0xcc17cc2edb85e2cc), I64(0x4215422a57846842), I64(0x985a98b4c22d2c98), I64(0xa4aaa4490e55eda4),\n\t\tI64(0x28a0285d88507528), I64(0x5c6d5cda31b8865c), I64(0xf8c7f8933fed6bf8), I64(0x86228644a411c286),\n\t}\n};\n/* end of whirlpool_sbox array */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/brotli-mt.h",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n/* ***************************************\n * Defines\n ****************************************/\n\n#ifndef BROTLIMT_H\n#define BROTLIMT_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#include <stddef.h>   /* size_t */\n\n/* current maximum the library will accept */\n#define BROTLIMT_THREAD_MAX 128\n#define BROTLIMT_LEVEL_MIN    0\n#define BROTLIMT_LEVEL_MAX   11\n\n#define BROTLIMT_MAGICNUMBER     0x5242U /* BR */\n#define BROTLIMT_MAGIC_SKIPPABLE 0x184D2A50U\n\n#define BROTLI_VERSION_MAJOR 1\n#define BROTLI_VERSION_MINOR 0\n\n/* **************************************\n * Error Handling\n ****************************************/\n\ntypedef enum {\n  BROTLIMT_error_no_error,\n  BROTLIMT_error_memory_allocation,\n  BROTLIMT_error_read_fail,\n  BROTLIMT_error_write_fail,\n  BROTLIMT_error_data_error,\n  BROTLIMT_error_frame_compress,\n  BROTLIMT_error_frame_decompress,\n  BROTLIMT_error_compressionParameter_unsupported,\n  BROTLIMT_error_compression_library,\n  BROTLIMT_error_canceled,\n  BROTLIMT_error_maxCode\n} BROTLIMT_ErrorCode;\n\n#define PREFIX(name) BROTLIMT_error_##name\n#define MT_ERROR(name)  ((size_t)-PREFIX(name))\nextern unsigned BROTLIMT_isError(size_t code);\nextern const char* BROTLIMT_getErrorString(size_t code);\n\n/* **************************************\n * Structures\n ****************************************/\n\ntypedef struct {\n\tvoid *buf;\t\t/* ptr to data */\n\tsize_t size;\t\t/* current filled in buf */\n\tsize_t allocated;\t/* length of buf */\n} BROTLIMT_Buffer;\n\n/**\n * reading and writing functions\n * - you can use stdio functions or plain read/write\n * - just write some wrapper on your own\n * - a sample is given in 7-Zip ZS or bromt.c\n * - the function should return -1 on error and zero on success\n * - the read or written bytes will go to in->size or out->size\n */\ntypedef int (fn_read) (void *args, BROTLIMT_Buffer * in);\ntypedef int (fn_write) (void *args, BROTLIMT_Buffer * out);\n\ntypedef struct {\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n} BROTLIMT_RdWr_t;\n\n/* **************************************\n * Compression\n ****************************************/\n\ntypedef struct BROTLIMT_CCtx_s BROTLIMT_CCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @level   - 1 .. 9\n * @threads - 1 .. BROTLIMT_THREAD_MAX\n * @inputsize - if zero, becomes some optimal value for the level\n *            - if nonzero, the given value is taken\n */\nBROTLIMT_CCtx *BROTLIMT_createCCtx(int threads, uint64_t unpackSize, int level, int inputsize, int lgwin);\n\n/**\n * 2) threaded compression\n * - errorcheck via \n */\nsize_t BROTLIMT_compressCCtx(BROTLIMT_CCtx * ctx, BROTLIMT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t BROTLIMT_GetFramesCCtx(BROTLIMT_CCtx * ctx);\nsize_t BROTLIMT_GetInsizeCCtx(BROTLIMT_CCtx * ctx);\nsize_t BROTLIMT_GetOutsizeCCtx(BROTLIMT_CCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid BROTLIMT_freeCCtx(BROTLIMT_CCtx * ctx);\n\n/* **************************************\n * Decompression\n ****************************************/\n\ntypedef struct BROTLIMT_DCtx_s BROTLIMT_DCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @threads - 1 .. BROTLIMT_THREAD_MAX\n * @ inputsize - used for single threaded standard bro format without skippable frames\n */\nBROTLIMT_DCtx *BROTLIMT_createDCtx(int threads, int inputsize);\n\n/**\n * 2) threaded compression\n * - return -1 on error\n */\nsize_t BROTLIMT_decompressDCtx(BROTLIMT_DCtx * ctx, BROTLIMT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t BROTLIMT_GetFramesDCtx(BROTLIMT_DCtx * ctx);\nsize_t BROTLIMT_GetInsizeDCtx(BROTLIMT_DCtx * ctx);\nsize_t BROTLIMT_GetOutsizeDCtx(BROTLIMT_DCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid BROTLIMT_freeDCtx(BROTLIMT_DCtx * ctx);\n\n#if defined (__cplusplus)\n}\n#endif\n#endif\t\t\t\t/* BROTLIMT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/brotli-mt_common.c",
    "content": "﻿\n/**\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#include <brotli/encode.h>\n#include <brotli/decode.h>\n\n#include \"brotli-mt.h\"\n\n/* ****************************************\n * BROMT Error Management\n ******************************************/\n\n/**\n * BROTLIMT_isError() - tells if a return value is an error code\n */\nunsigned BROTLIMT_isError(size_t code)\n{\n\treturn (code > MT_ERROR(maxCode));\n}\n\n/**\n * BROTLIMT_getErrorString() - give our error code string of result\n */\nconst char *BROTLIMT_getErrorString(size_t code)\n{\n\tstatic const char *noErrorCode = \"Unspecified brotli error code\";\n\n\tswitch ((BROTLIMT_ErrorCode) (0 - code)) {\n\tcase PREFIX(no_error):\n\t\treturn \"No error detected\";\n\tcase PREFIX(memory_allocation):\n\t\treturn \"Allocation error : not enough memory\";\n\tcase PREFIX(read_fail):\n\t\treturn \"Read failure\";\n\tcase PREFIX(write_fail):\n\t\treturn \"Write failure\";\n\tcase PREFIX(data_error):\n\t\treturn \"Malformed input\";\n\tcase PREFIX(frame_compress):\n\t\treturn \"Could not compress frame at once\";\n\tcase PREFIX(frame_decompress):\n\t\treturn \"Could not decompress frame at once\";\n\tcase PREFIX(compressionParameter_unsupported):\n\t\treturn \"Compression parameter is out of bound\";\n\tcase PREFIX(maxCode):\n\tdefault:\n\t\treturn noErrorCode;\n\t}\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/brotli-mt_compress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <brotli/encode.h>\n#include <brotli/../../common/constants.h>\n\n#include \"brotli-mt.h\"\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n\n/**\n * multi threaded brotli - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tBROTLIMT_CCtx *ctx;\n\tpthread_t pthread;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tBROTLIMT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct BROTLIMT_CCtx_s {\n\n\t/* levels: 1..BROTLIMT_LEVEL_MAX */\n\tint level;\n\n\t/* threads: 0..BROTLIMT_THREAD_MAX */\n\tint threads;\n\n\t/* size of file/stream to compress if known */\n\tuint64_t unpackSize;\n\n\t/* should be used for read from input */\n\tint inputsize;\n\n\tint lgwin;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Compression\n ****************************************/\n\nBROTLIMT_CCtx *BROTLIMT_createCCtx(int threads, uint64_t unpackSize, int level, int inputsize, int lgwin)\n{\n\tBROTLIMT_CCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (BROTLIMT_CCtx *) malloc(sizeof(BROTLIMT_CCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 0 || threads > BROTLIMT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* check level */\n\tif (level < BROTLIMT_LEVEL_MIN || level > BROTLIMT_LEVEL_MAX)\n\t\treturn 0;\n\n\t/* calculate chunksize for one thread */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 * 1024 * (level ? level : 1);\n\n\tctx->lgwin = lgwin;\n\n\t/* setup ctx */\n\tctx->level = level;\n\tctx->threads = threads;\n\tctx->unpackSize = unpackSize;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\tif (threads) {\n\t\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\t\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\t\t/* free -> busy -> out -> free -> ... */\n\t\tINIT_LIST_HEAD(&ctx->writelist_free);\t/* free, can be used */\n\t\tINIT_LIST_HEAD(&ctx->writelist_busy);\t/* busy */\n\t\tINIT_LIST_HEAD(&ctx->writelist_done);\t/* can be written */\n\n\t\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\t\tif (!ctx->cwork)\n\t\t\tgoto err_cwork;\n\n\t\tfor (t = 0; t < threads; t++) {\n\t\t\tcwork_t *w = &ctx->cwork[t];\n\t\t\tw->ctx = ctx;\n\t\t}\n\t} else {\n\t\tctx->cwork = NULL;\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn MT_ERROR(read_fail);\n\tcase -2:\n\t\treturn MT_ERROR(canceled);\n\tcase -3:\n\t\treturn MT_ERROR(memory_allocation);\n\t}\n\n\treturn MT_ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for compressed output\n */\nstatic size_t pt_write(BROTLIMT_CCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n\n\t/* the entry isn't the currently needed, return...  */\n\tif (wl->frame != ctx->curframe)\n\t\treturn 0;\n\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic void *pt_compress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tBROTLIMT_CCtx *ctx = w->ctx;\n\tsize_t result;\n\tBROTLIMT_Buffer in;\n\n\t/* inbuf is constant */\n\tin.size = ctx->inputsize;\n\tin.buf = malloc(in.size);\n\tif (!in.buf)\n\t\treturn (void *)MT_ERROR(memory_allocation);\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tstruct writelist *wl;\n\t\tint rv;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\twl->out.size =\n\t\t\t    BrotliEncoderMaxCompressedSize(ctx->inputsize) + 16;\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)MT_ERROR(memory_allocation);\n\t\t\t}\n\t\t\twl->out.size =\n\t\t\t    BrotliEncoderMaxCompressedSize(ctx->inputsize) + 16;\n\t\t\twl->out.buf = malloc(wl->out.size);\n\t\t\tif (!wl->out.buf) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)MT_ERROR(memory_allocation);\n\t\t\t}\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t/* read new input */\n\t\tpthread_mutex_lock(&ctx->read_mutex);\n\t\tin.size = ctx->inputsize;\n\t\trv = ctx->fn_read(ctx->arg_read, &in);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn (void *)mt_error(rv);\n\t\t}\n\n\t\t/* eof */\n\t\tif (in.size == 0 && ctx->frames > 0) {\n\t\t\tfree(in.buf);\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t\tgoto okay;\n\t\t}\n\t\tctx->insize += in.size;\n\t\twl->frame = ctx->frames++;\n\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t/* compress whole frame */\n\t\t{\n\t\t\tconst uint8_t *ibuf = in.buf;\n\t\t\tuint8_t *obuf = (uint8_t*)wl->out.buf + 16;\n\t\t\twl->out.size -= 16;\n\t\t\trv = BrotliEncoderCompress(ctx->level,\n\t\t\t\t\t\t   ctx->lgwin,\n\t\t\t\t\t\t   BROTLI_MODE_GENERIC, in.size,\n\t\t\t\t\t\t   ibuf, &wl->out.size, obuf);\n\n\t\t\t/* printf(\"BrotliEncoderCompress() rv=%d in=%zu out=%zu\\n\", rv, in.size, wl->out.size); */\n\n\t\t\tif (rv == BROTLI_FALSE) {\n\t\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)MT_ERROR(frame_compress);\n\t\t\t}\n\t\t}\n\n\t\t/* write skippable frame */\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 0,\n\t\t\t      BROTLIMT_MAGIC_SKIPPABLE);\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 4, 8);\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 8,\n\t\t\t      (U32) wl->out.size);\n\t\t/* BR */\n\t\tMEM_writeLE16((unsigned char *)wl->out.buf + 12,\n\t\t\t      (U16) BROTLIMT_MAGICNUMBER);\n\n\t\t/* number of 64KB blocks needed for decompression */\n\t\t{\n\t\tU16 hintsize;\n\t\tif (ctx->inputsize > (int)in.size) {\n\t\t\thintsize = (U16)(in.size >> 16);\n\t\t\thintsize += 1;\n\t\t} else\n\t\t\thintsize = ctx->inputsize >> 16;\n\t\tMEM_writeLE16((unsigned char *)wl->out.buf + 14,\n\t\t\t      hintsize);\n\t\t}\n\n\t\twl->out.size += 16;\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tif (BROTLIMT_isError(result))\n\t\t\treturn (void *)result;\n\t}\n\n okay:\n\treturn 0;\n}\n\n/* single threaded (standard brotli stream, without header/mt-frames) */\nstatic size_t st_compress(void *arg)\n{\n\tBROTLIMT_CCtx *ctx = (BROTLIMT_CCtx *) arg;\n\tBrotliEncoderOperation brop = BROTLI_OPERATION_PROCESS;\n\tBROTLIMT_Buffer Out;\n\tBROTLIMT_Buffer *out = &Out;\n\tBROTLIMT_Buffer In;\n\tBROTLIMT_Buffer *in = &In;\n\tBrotliEncoderState *state;\n\tconst uint8_t* next_in;\n\tuint8_t* next_out;\n\tint rv;\n\tsize_t retval = 0;\n\n\t/* allocate space for input buffer (default 1M * level) */\n\tin->allocated = ctx->inputsize;\n\tin->buf = malloc(in->allocated);\n\tif (!in->buf)\n\t\treturn MT_ERROR(memory_allocation);\n\tnext_in = in->buf;\n\tin->size = 0;\n\n\t/* allocate space for output buffer */\n\tout->allocated = out->size = ctx->inputsize / 4;\n\tout->buf = malloc(out->size);\n\tif (!out->buf) {\n\t\tfree(in->buf);\n\t\treturn MT_ERROR(memory_allocation);\n\t}\n\tnext_out = out->buf;\n\n\tstate = BrotliEncoderCreateInstance(NULL, NULL, NULL);\n\tif (!state) {\n\t\tfree(in->buf);\n\t\tfree(out->buf);\n\t\treturn MT_ERROR(memory_allocation);\n\t}\n\n\tBrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, (uint32_t)ctx->level);\n\tif (ctx->lgwin > 0) {\n\t\t/* Specified by user. */\n\t\t/* Do not enable \"large-window\" extension, if not required. */\n\t\tif (ctx->lgwin > BROTLI_MAX_WINDOW_BITS) {\n\t\t\tBrotliEncoderSetParameter(state, BROTLI_PARAM_LARGE_WINDOW, 1u);\n\t\t}\n\t\tBrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN, (uint32_t)ctx->lgwin);\n\t} else {\n\t  /* 0, or not specified by user; could be chosen by compressor. */\n\t  uint32_t lgwin = 24 /* DEFAULT_LGWIN */;\n\t  /* Use file size to limit lgwin. */\n\t  if (ctx->unpackSize != (uint64_t)(int64_t)-1) {\n\t    lgwin = BROTLI_MIN_WINDOW_BITS;\n\t    while (BROTLI_MAX_BACKWARD_LIMIT(lgwin) <\n\t           (uint64_t)ctx->unpackSize) {\n\t      lgwin++;\n\t      if (lgwin == BROTLI_MAX_WINDOW_BITS) break;\n\t    }\n\t  }\n\t  BrotliEncoderSetParameter(state, BROTLI_PARAM_LGWIN, lgwin);\n\t}\n\tif (ctx->unpackSize > 0 && ctx->unpackSize != (uint64_t)(int64_t)-1) {\n\t\tuint32_t size_hint = ctx->unpackSize < (1 << 30) ?\n\t    (uint32_t)ctx->unpackSize : (1u << 30);\n\t\tBrotliEncoderSetParameter(state, BROTLI_PARAM_SIZE_HINT, size_hint);\n\t}\n\n\twhile (1) {\n\t\tif (in->size == 0 && brop != BROTLI_OPERATION_FINISH) {\n\t\t\tin->size = in->allocated;\n\t\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\t\tif (rv != 0) {\n\t\t\t\tretval = mt_error(rv);\n\t\t\t\tgoto done;\n\t\t\t}\n\t\t\tif (in->size == 0) {\n\t\t\t\tbrop = BROTLI_OPERATION_FINISH; // eof\n\t\t\t}\n\t\t\tnext_in = in->buf;\n\t\t}\n\n\t\tif (!BrotliEncoderCompressStream(state, brop, &in->size, &next_in, &out->size, &next_out, 0)) {\n\t\t\tretval = MT_ERROR(frame_compress);\n\t\t\tgoto done;\n\t\t}\n\t\tif (out->size == 0) {\n\t\t\tout->size = next_out - (uint8_t*)out->buf;\n\t\t\trv = ctx->fn_write(ctx->arg_write, out);\n\t\t\tif (rv != 0) {\n\t\t\t\tretval = mt_error(rv);\n\t\t\t\tgoto done;\n\t\t\t}\n\t\t\tnext_out = out->buf;\n\t\t\tout->size = out->allocated;\n\t\t}\n\t\tif (BrotliEncoderIsFinished(state)) {\n\t\t\tout->size = next_out - (uint8_t*)out->buf;\n\t\t\trv = ctx->fn_write(ctx->arg_write, out);\n\t\t\tif (rv != 0) {\n\t\t\t\tretval = mt_error(rv);\n\t\t\t\tgoto done;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n done:\n\t\tfree(in->buf);\n\t\tfree(out->buf);\n\t\tBrotliEncoderDestroyInstance(state);\n\t\treturn retval;\n}\n\nsize_t BROTLIMT_compressCCtx(BROTLIMT_CCtx * ctx, BROTLIMT_RdWr_t * rdwr)\n{\n\tint t;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn MT_ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* single threaded brotli (no header, no mt-frames) */\n\tif (ctx->threads == 0) {\n\t\t/* decompress single threaded */\n\t\treturn st_compress(ctx);\n\t}\n\n\t/* start all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tpthread_create(&w->pthread, NULL, pt_compress, w);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(w->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\n    /* move remaining done/busy entries to free list */\n    while (!list_empty(&ctx->writelist_done)) {\n        struct list_head* entry = list_first(&ctx->writelist_done);\n        list_move(entry, &ctx->writelist_free);\n    }\n    while (!list_empty(&ctx->writelist_busy)) {\n        struct list_head* entry = list_first(&ctx->writelist_busy);\n        list_move(entry, &ctx->writelist_free);\n    }\n\t/* clean up lists */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t) retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t BROTLIMT_GetInsizeCCtx(BROTLIMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t BROTLIMT_GetOutsizeCCtx(BROTLIMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t BROTLIMT_GetFramesCCtx(BROTLIMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid BROTLIMT_freeCCtx(BROTLIMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn;\n\n\tif (ctx->threads) {\n\t\tpthread_mutex_destroy(&ctx->read_mutex);\n\t\tpthread_mutex_destroy(&ctx->write_mutex);\n\t\tfree(ctx->cwork);\n\t}\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/brotli-mt_decompress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <brotli/decode.h>\n\n#include \"brotli-mt.h\"\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n\n/**\n * multi threaded brotli - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tBROTLIMT_DCtx *ctx;\n\tpthread_t pthread;\n\tBROTLIMT_Buffer in;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tBROTLIMT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct BROTLIMT_DCtx_s {\n\n\t/* threads: 0, 1..BROTLIMT_THREAD_MAX */\n\tint threads;\n\n\t/* should be used for read from input */\n\tsize_t inputsize;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Decompression\n ****************************************/\n\nBROTLIMT_DCtx *BROTLIMT_createDCtx(int threads, int inputsize)\n{\n\tBROTLIMT_DCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (BROTLIMT_DCtx *) malloc(sizeof(BROTLIMT_DCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 0 || threads > BROTLIMT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* setup ctx */\n\tctx->threads = threads;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\t/* will be used for single stream only */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 * 256; /* 256K buffer */\n\n\tif (threads) {\n\t\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\t\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\t\tINIT_LIST_HEAD(&ctx->writelist_free);\n\t\tINIT_LIST_HEAD(&ctx->writelist_busy);\n\t\tINIT_LIST_HEAD(&ctx->writelist_done);\n\t} else {\n\t\tthreads = 1;\n\t}\t\t\n\n\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\tif (!ctx->cwork)\n\t\tgoto err_cwork;\n\n\tfor (t = 0; t < threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tw->ctx = ctx;\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn MT_ERROR(read_fail);\n\tcase -2:\n\t\treturn MT_ERROR(canceled);\n\tcase -3:\n\t\treturn MT_ERROR(memory_allocation);\n\t}\n\n\t/* XXX, some catch all other errors */\n\treturn MT_ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for decompressed output\n */\nstatic size_t pt_write(BROTLIMT_DCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/**\n * pt_read - read compressed output\n */\nstatic size_t pt_read(BROTLIMT_DCtx * ctx, BROTLIMT_Buffer * in, size_t * frame, size_t * uncompressed)\n{\n\tunsigned char hdrbuf[16];\n\tBROTLIMT_Buffer hdr;\n\tint rv;\n\n\t/* read skippable frame (12 or 16 bytes) */\n\tpthread_mutex_lock(&ctx->read_mutex);\n\n\t/* special case, first 4 bytes already read */\n\tif (ctx->frames == 0) {\n\t\thdr.buf = hdrbuf + 4;\n\t\thdr.size = 12;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\tif (hdr.size != 12)\n\t\t\tgoto error_read;\n\t\thdr.buf = hdrbuf;\n\t} else {\n\t\thdr.buf = hdrbuf;\n\t\thdr.size = 16;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* eof reached ? */\n\t\tif (hdr.size == 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\tin->size = 0;\n\t\t\treturn 0;\n\t\t}\n\t\tif (hdr.size != 16)\n\t\t\tgoto error_read;\n\t\tif (MEM_readLE32((unsigned char *)hdr.buf + 0) !=\n\t\t    BROTLIMT_MAGIC_SKIPPABLE)\n\t\t\tgoto error_data;\n\t}\n\n\t/* check header data */\n\tif (MEM_readLE32((unsigned char *)hdr.buf + 4) != 8)\n\t\tgoto error_data;\n\tif (MEM_readLE16((unsigned char *)hdr.buf + 12) != BROTLIMT_MAGICNUMBER)\n\t\tgoto error_data;\n\n\t/* get uncompressed size for output buffer */\n\t{\n\t\tU16 hintsize = MEM_readLE16((unsigned char *)hdr.buf + 14);\n\t\t*uncompressed = hintsize << 16;\n\t}\n\n\tctx->insize += 16;\n\t/* read new inputsize */\n\t{\n\t\tsize_t toRead = MEM_readLE32((unsigned char *)hdr.buf + 8);\n\t\tif (in->allocated < toRead) {\n\t\t\t/* need bigger input buffer */\n\t\t\tif (in->allocated)\n\t\t\t\tin->buf = realloc(in->buf, toRead);\n\t\t\telse\n\t\t\t\tin->buf = malloc(toRead);\n\t\t\tif (!in->buf)\n\t\t\t\tgoto error_nomem;\n\t\t\tin->allocated = toRead;\n\t\t}\n\n\t\tin->size = toRead;\n\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\t/* generic read failure! */\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* needed more bytes! */\n\t\tif (in->size != toRead)\n\t\t\tgoto error_data;\n\n\t\tctx->insize += in->size;\n\t}\n\t*frame = ctx->frames++;\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t/* done, no error */\n\treturn 0;\n\n error_data:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn MT_ERROR(data_error);\n error_read:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn MT_ERROR(read_fail);\n error_nomem:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn MT_ERROR(memory_allocation);\n}\n\nstatic void *pt_decompress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tBROTLIMT_Buffer *in = &w->in;\n\tBROTLIMT_DCtx *ctx = w->ctx;\n\tsize_t result = 0;\n\tstruct writelist *wl;\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tBROTLIMT_Buffer *out;\n\t\tint rv;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tresult = MT_ERROR(memory_allocation);\n\t\t\t\tgoto error_unlock;\n\t\t\t}\n\t\t\twl->out.buf = 0;\n\t\t\twl->out.size = 0;\n\t\t\twl->out.allocated = 0;\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tout = &wl->out;\n\n\t\t/* zero should not happen here! */\n\t\tresult = pt_read(ctx, in, &wl->frame, &wl->out.size);\n\t\tif (BROTLIMT_isError(result)) {\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\tif (in->size == 0)\n\t\t\tbreak;\n\n\t\tif (out->allocated < out->size) {\n\t\t\tif (out->allocated)\n\t\t\t\tout->buf = realloc(out->buf, out->size);\n\t\t\telse\n\t\t\t\tout->buf = malloc(out->size);\n\t\t\tif (!out->buf) {\n\t\t\t\tresult = MT_ERROR(memory_allocation);\n\t\t\t\tgoto error_lock;\n\t\t\t}\n\t\t\tout->allocated = out->size;\n\t\t}\n\n\t\trv =\n\t\t    BrotliDecoderDecompress(in->size, in->buf, &out->size,\n\t\t\t\t\t    out->buf);\n\n\t\tif (rv != BROTLI_DECODER_RESULT_SUCCESS) {\n\t\t\tresult = MT_ERROR(frame_decompress);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tif (BROTLIMT_isError(result))\n\t\t\tgoto error_unlock;\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t}\n\n\t/* everything is okay */\n    result = 0;\n\n error_lock:\n\tpthread_mutex_lock(&ctx->write_mutex);\n error_unlock:\n\tlist_move(&wl->node, &ctx->writelist_free);\n\tpthread_mutex_unlock(&ctx->write_mutex);\n\tif (in->allocated)\n\t\tfree(in->buf);\n\treturn (void *)result;\n}\n\n/* single threaded (standard brotli stream, without header/mt-frames) */\nstatic size_t st_decompress(void *arg)\n{\n\tBROTLIMT_DCtx *ctx = (BROTLIMT_DCtx *) arg;\n\tBrotliDecoderResult bres = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;\n\tcwork_t *w = &ctx->cwork[0];\n\tBROTLIMT_Buffer Out;\n\tBROTLIMT_Buffer *out = &Out;\n\tBROTLIMT_Buffer *in = &w->in;\n\tBrotliDecoderState *state;\n\tconst uint8_t* next_in;\n\tuint8_t* next_out;\n\tint rv;\n\tsize_t retval = 0;\n\n\t/* allocate space for input buffer */\n\tin->allocated = in->size = ctx->inputsize;\n\tin->buf = malloc(in->size);\n\tif (!in->buf)\n\t\treturn MT_ERROR(memory_allocation);\n\tnext_in = in->buf;\n\n\t/* allocate space for output buffer */\n\tout->allocated = out->size = ctx->inputsize * 4;\n\tout->buf = malloc(out->size);\n\tif (!out->buf) {\n\t\tfree(in->buf);\n\t\treturn MT_ERROR(memory_allocation);\n\t}\n\tnext_out = out->buf;\n\n\tstate = BrotliDecoderCreateInstance(NULL, NULL, NULL);\n\tif (!state) {\n\t\tfree(in->buf);\n\t\tfree(out->buf);\n\t  return MT_ERROR(memory_allocation);\n\t}\n\tBrotliDecoderSetParameter(state, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1);\n\n\twhile (1) {\n\t\tif (bres == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {\n\t\t\tin->size = in->allocated;\n\t\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\t\tif (in->size == 0) break;\n\t\t\tif (rv != 0) {\n\t\t\t\tretval = mt_error(rv);\n\t\t\t\tgoto done;\n\t\t\t}\n\t\t\tnext_in = in->buf;\n\t\t} else if (bres == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {\n\t\t\tout->size = next_out - (uint8_t*)out->buf;\n\t\t\trv = ctx->fn_write(ctx->arg_write, out);\n\t\t\tif (rv != 0) {\n\t\t\t\tretval = mt_error(rv);\n\t\t\t\tgoto done;\n\t\t\t}\n\t\t\tnext_out = out->buf;\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\n\t\tbres = BrotliDecoderDecompressStream(state, &in->size, &next_in, &out->size, &next_out, 0);\n\t}\n\n\tif (bres != BROTLI_DECODER_RESULT_SUCCESS) {\n\t\tretval = MT_ERROR(data_error); // corrupt input\n\t\tgoto done;\n\t}\n\tout->size = next_out - (uint8_t*)out->buf;\n\tif (out->size != 0) {\n\t\trv = ctx->fn_write(ctx->arg_write, out);\n\t\tif (rv != 0) {\n\t\t\tretval = mt_error(rv);\n\t\t\tgoto done;\n\t\t}\n\t}\n\n done:\n\t\tfree(in->buf);\n\t\tfree(out->buf);\n\t\tBrotliDecoderDestroyInstance(state);\n\t\treturn retval;\n}\n\nsize_t BROTLIMT_decompressDCtx(BROTLIMT_DCtx * ctx, BROTLIMT_RdWr_t * rdwr)\n{\n\tunsigned char buf[4];\n\tint t, rv;\n\tcwork_t *w = &ctx->cwork[0];\n\tBROTLIMT_Buffer *in = &w->in;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn MT_ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* For single threaded brotli (no header, no mt-frames), don't check for \n\t   BROTLIMT_MAGIC_SKIPPABLE here, because stdandard brotli stream may also\n\t   start with it, so will be mistakenly considered as brotli-mt stream. */\n\tif (ctx->threads == 0) {\n\t\t/* decompress single threaded */\n\t\treturn st_decompress(ctx);\n\t}\n\n\t/* check for BROTLIMT_MAGIC_SKIPPABLE */\n\tin->buf = buf;\n\tin->size = 4;\n\trv = ctx->fn_read(ctx->arg_read, in);\n\tif (rv != 0)\n\t\treturn mt_error(rv);\n\tif (in->size != 4)\n\t\treturn MT_ERROR(data_error);\n\n\t/* mark unused */\n\tin->buf = 0;\n\tin->size = 0;\n\tin->allocated = 0;\n\n\t/* single threaded, but with known sizes */\n\tif (ctx->threads == 1) {\n\t\t/* no pthread_create() needed! */\n\t\tvoid *p = pt_decompress(w);\n\t\tif (p)\n            retval_of_thread = p;\n        goto done;\n\t}\n\n\t/* multi threaded */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\twt->in.buf = 0;\n\t\twt->in.size = 0;\n\t\twt->in.allocated = 0;\n\t\tpthread_create(&wt->pthread, NULL, pt_decompress, wt);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(wt->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\ndone:\n    /* move remaining done/busy entries to free list */\n    while (!list_empty(&ctx->writelist_done)) {\n        struct list_head* entry = list_first(&ctx->writelist_done);\n        list_move(entry, &ctx->writelist_free);\n    }\n    while (!list_empty(&ctx->writelist_busy)) {\n        struct list_head* entry = list_first(&ctx->writelist_busy);\n        list_move(entry, &ctx->writelist_free);\n    }\n\t/* clean up the buffers */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t) retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t BROTLIMT_GetInsizeDCtx(BROTLIMT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t BROTLIMT_GetOutsizeDCtx(BROTLIMT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t BROTLIMT_GetFramesDCtx(BROTLIMT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid BROTLIMT_freeDCtx(BROTLIMT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn;\n\n\tif (ctx->threads) {\n\t\tpthread_mutex_destroy(&ctx->read_mutex);\n\t\tpthread_mutex_destroy(&ctx->write_mutex);\n\t}\n\tfree(ctx->cwork);\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/list.h",
    "content": "﻿\n/**\n * Copyright (c) 2016 Tino Reichardt\n * - removed unneeded stuff\n * - added win32 compatibility\n *\n * Copyright (c) 2013 The NetBSD Foundation, Inc.\n * All rights reserved.\n *\n * This code is derived from software contributed to The NetBSD Foundation\n * by Taylor R. Campbell.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS\n * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\n * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS\n * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n * POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef LIST_H\n#define LIST_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#include \"memmt.h\"\n\nstruct list_head {\n\tstruct list_head *prev;\n\tstruct list_head *next;\n};\n\nMEM_STATIC void INIT_LIST_HEAD(struct list_head *head)\n{\n\thead->prev = head;\n\thead->next = head;\n}\n\nMEM_STATIC struct list_head *list_first(const struct list_head *head)\n{\n\treturn head->next;\n}\n\nMEM_STATIC struct list_head *list_last(const struct list_head *head)\n{\n\treturn head->prev;\n}\n\nMEM_STATIC struct list_head *list_next(const struct list_head *node)\n{\n\treturn node->next;\n}\n\nMEM_STATIC struct list_head *list_prev(const struct list_head *node)\n{\n\treturn node->prev;\n}\n\nMEM_STATIC void __list_add_between(struct list_head *prev,\n\tstruct list_head *node, struct list_head *next)\n{\n\tprev->next = node;\n\tnode->prev = prev;\n\tnode->next = next;\n\tnext->prev = node;\n}\n\nMEM_STATIC void list_add(struct list_head *node, struct list_head *head)\n{\n\t__list_add_between(head, node, head->next);\n}\n\nMEM_STATIC void list_add_tail(struct list_head *node, struct list_head *head)\n{\n\t__list_add_between(head->prev, node, head);\n}\n\nMEM_STATIC void list_del(struct list_head *entry)\n{\n\tentry->prev->next = entry->next;\n\tentry->next->prev = entry->prev;\n}\n\nMEM_STATIC int list_empty(const struct list_head *head)\n{\n\treturn (head->next == head);\n}\n\nMEM_STATIC void list_move(struct list_head *node, struct list_head *head)\n{\n\tlist_del(node);\n\tlist_add(node, head);\n}\n\nMEM_STATIC void list_move_tail(struct list_head *node, struct list_head *head)\n{\n\tlist_del(node);\n\tlist_add_tail(node, head);\n}\n\n#ifndef CONTAINING_RECORD\n#define CONTAINING_RECORD(ptr, type, field) \\\n\t((type*)((char*)(ptr) - (char*)(&((type*)0)->field)))\n#endif\n\n#define list_entry(ptr, type, member)\tCONTAINING_RECORD(ptr, type, member)\n#define\tlist_for_each(var, head) \\\n\tfor ((var) = list_first((head)); (var) != (head); (var) = list_next((var)))\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\t\t\t\t/* LIST_H */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lizard-mt.h",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n/* ***************************************\n * Defines\n ****************************************/\n\n#ifndef LIZARDMT_H\n#define LIZARDMT_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#include <stddef.h>   /* size_t */\n\n/* current maximum the library will accept */\n#define LIZARDMT_THREAD_MAX 128\n#define LIZARDMT_LEVEL_MIN   10\n#define LIZARDMT_LEVEL_MAX   49\n\n#define LIZARDFMT_MAGICNUMBER     0x184D2206U\n#define LIZARDFMT_MAGIC_SKIPPABLE 0x184D2A50U\n\n/* **************************************\n * Error Handling\n ****************************************/\n\nextern size_t lizardmt_errcode;\n\ntypedef enum {\n  LIZARDMT_error_no_error,\n  LIZARDMT_error_memory_allocation,\n  LIZARDMT_error_read_fail,\n  LIZARDMT_error_write_fail,\n  LIZARDMT_error_data_error,\n  LIZARDMT_error_frame_compress,\n  LIZARDMT_error_frame_decompress,\n  LIZARDMT_error_compressionParameter_unsupported,\n  LIZARDMT_error_compression_library,\n  LIZARDMT_error_canceled,\n  LIZARDMT_error_maxCode\n} LIZARDMT_ErrorCode;\n\n#ifdef ERROR\n#  undef ERROR   /* reported already defined on VS 2015 (Rich Geldreich) */\n#endif\n#define PREFIX(name) LIZARDMT_error_##name\n#define ERROR(name)  ((size_t)-PREFIX(name))\nextern unsigned LIZARDMT_isError(size_t code);\nextern const char* LIZARDMT_getErrorString(size_t code);\n\n/* **************************************\n * Structures\n ****************************************/\n\ntypedef struct {\n\tvoid *buf;\t\t/* ptr to data */\n\tsize_t size;\t\t/* current filled in buf */\n\tsize_t allocated;\t/* length of buf */\n} LIZARDMT_Buffer;\n\n/**\n * reading and writing functions\n * - you can use stdio functions or plain read/write\n * - just write some wrapper on your own\n * - a sample is given in 7-Zip ZS or lizardmt.c\n * - the function should return -1 on error and zero on success\n * - the read or written bytes will go to in->size or out->size\n */\ntypedef int (fn_read) (void *args, LIZARDMT_Buffer * in);\ntypedef int (fn_write) (void *args, LIZARDMT_Buffer * out);\n\ntypedef struct {\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n} LIZARDMT_RdWr_t;\n\n/* **************************************\n * Compression\n ****************************************/\n\ntypedef struct LIZARDMT_CCtx_s LIZARDMT_CCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @level   - 1 .. 9\n * @threads - 1 .. LIZARDMT_THREAD_MAX\n * @inputsize - if zero, becomes some optimal value for the level\n *            - if nonzero, the given value is taken\n */\nLIZARDMT_CCtx *LIZARDMT_createCCtx(int threads, int level, int inputsize);\n\n/**\n * 2) threaded compression\n * - errorcheck via \n */\nsize_t LIZARDMT_compressCCtx(LIZARDMT_CCtx * ctx, LIZARDMT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t LIZARDMT_GetFramesCCtx(LIZARDMT_CCtx * ctx);\nsize_t LIZARDMT_GetInsizeCCtx(LIZARDMT_CCtx * ctx);\nsize_t LIZARDMT_GetOutsizeCCtx(LIZARDMT_CCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid LIZARDMT_freeCCtx(LIZARDMT_CCtx * ctx);\n\n/* **************************************\n * Decompression\n ****************************************/\n\ntypedef struct LIZARDMT_DCtx_s LIZARDMT_DCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @threads - 1 .. LIZARDMT_THREAD_MAX\n * @ inputsize - used for single threaded standard lizard format without skippable frames\n */\nLIZARDMT_DCtx *LIZARDMT_createDCtx(int threads, int inputsize);\n\n/**\n * 2) threaded compression\n * - return -1 on error\n */\nsize_t LIZARDMT_decompressDCtx(LIZARDMT_DCtx * ctx, LIZARDMT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t LIZARDMT_GetFramesDCtx(LIZARDMT_DCtx * ctx);\nsize_t LIZARDMT_GetInsizeDCtx(LIZARDMT_DCtx * ctx);\nsize_t LIZARDMT_GetOutsizeDCtx(LIZARDMT_DCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid LIZARDMT_freeDCtx(LIZARDMT_DCtx * ctx);\n\n#if defined (__cplusplus)\n}\n#endif\n#endif\t\t\t\t/* LIZARDMT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lizard-mt_common.c",
    "content": "﻿\n/**\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#include \"lizard_frame.h\"\n#include \"lizard-mt.h\"\n\n/* will be used for lib errors */\nsize_t lizardmt_errcode;\n\n/* ****************************************\n * LIZARDMT Error Management\n ******************************************/\n\n/**\n * LIZARDMT_isError() - tells if a return value is an error code\n */\nunsigned LIZARDMT_isError(size_t code)\n{\n\treturn (code > ERROR(maxCode));\n}\n\n/**\n * LIZARDMT_getErrorString() - give error code string from function result\n */\nconst char *LIZARDMT_getErrorString(size_t code)\n{\n\tstatic const char *noErrorCode = \"Unspecified lizardmt error code\";\n\n\tif (LizardF_isError(lizardmt_errcode))\n\t\treturn LizardF_getErrorName(lizardmt_errcode);\n\n\tswitch ((LIZARDMT_ErrorCode) (0 - code)) {\n\tcase PREFIX(no_error):\n\t\treturn \"No error detected\";\n\tcase PREFIX(memory_allocation):\n\t\treturn \"Allocation error : not enough memory\";\n\tcase PREFIX(read_fail):\n\t\treturn \"Read failure\";\n\tcase PREFIX(write_fail):\n\t\treturn \"Write failure\";\n\tcase PREFIX(data_error):\n\t\treturn \"Malformed input\";\n\tcase PREFIX(frame_compress):\n\t\treturn \"Could not compress frame at once\";\n\tcase PREFIX(frame_decompress):\n\t\treturn \"Could not decompress frame at once\";\n\tcase PREFIX(compressionParameter_unsupported):\n\t\treturn \"Compression parameter is out of bound\";\n\tcase PREFIX(compression_library):\n\t\treturn \"Compression library reports failure\";\n\tcase PREFIX(maxCode):\n\tdefault:\n\t\treturn noErrorCode;\n\t}\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lizard-mt_compress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#define LizardF_DISABLE_OBSOLETE_ENUMS\n#include \"lizard_frame.h\"\n\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n#include \"lizard-mt.h\"\n\n/**\n * multi threaded lizard - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tLIZARDMT_CCtx *ctx;\n\tLizardF_preferences_t zpref;\n\tpthread_t pthread;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tLIZARDMT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct LIZARDMT_CCtx_s {\n\n\t/* level: 1..LIZARDMT_LEVEL_MAX */\n\tint level;\n\n\t/* threads: 1..LIZARDMT_THREAD_MAX */\n\tint threads;\n\n\t/* should be used for read from input */\n\tint inputsize;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Compression\n ****************************************/\n\nLIZARDMT_CCtx *LIZARDMT_createCCtx(int threads, int level, int inputsize)\n{\n\tLIZARDMT_CCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (LIZARDMT_CCtx *) malloc(sizeof(LIZARDMT_CCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 1 || threads > LIZARDMT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* check level */\n\tif (level < LIZARDMT_LEVEL_MIN || level > LIZARDMT_LEVEL_MAX)\n\t\treturn 0;\n\n\t/* calculate chunksize for one thread */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 * 1024 * 4;\n\n\t/* setup ctx */\n\tctx->level = level;\n\tctx->threads = threads;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\t/* free -> busy -> out -> free -> ... */\n\tINIT_LIST_HEAD(&ctx->writelist_free);\t/* free, can be used */\n\tINIT_LIST_HEAD(&ctx->writelist_busy);\t/* busy */\n\tINIT_LIST_HEAD(&ctx->writelist_done);\t/* can be written */\n\n\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\tif (!ctx->cwork)\n\t\tgoto err_cwork;\n\n\tfor (t = 0; t < threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tw->ctx = ctx;\n\n\t\t/* setup preferences for that thread */\n\t\tmemset(&w->zpref, 0, sizeof(LizardF_preferences_t));\n\t\tw->zpref.compressionLevel = level;\n\t\tw->zpref.frameInfo.blockMode = LizardF_blockLinked;\n\t\tw->zpref.frameInfo.contentSize = 1;\n\t\tw->zpref.frameInfo.contentChecksumFlag =\n\t\t    LizardF_contentChecksumEnabled;\n\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn ERROR(read_fail);\n\tcase -2:\n\t\treturn ERROR(canceled);\n\tcase -3:\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\treturn ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for compressed output\n */\nstatic size_t pt_write(LIZARDMT_CCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n\n\t/* the entry isn't the currently needed, return...  */\n\tif (wl->frame != ctx->curframe)\n\t\treturn 0;\n\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic void *pt_compress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tLIZARDMT_CCtx *ctx = w->ctx;\n\tsize_t result;\n\tLIZARDMT_Buffer in;\n\n\t/* inbuf is constant */\n\tin.size = ctx->inputsize;\n\tin.buf = malloc(in.size);\n\tif (!in.buf)\n\t\treturn (void *)ERROR(memory_allocation);\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tstruct writelist *wl;\n\t\tint rv;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\twl->out.size =\n\t\t\t    LizardF_compressFrameBound(ctx->inputsize,\n\t\t\t\t\t\t    &w->zpref) + 12;\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)ERROR(memory_allocation);\n\t\t\t}\n\t\t\twl->out.size =\n\t\t\t    LizardF_compressFrameBound(ctx->inputsize,\n\t\t\t\t\t\t    &w->zpref) + 12;;\n\t\t\twl->out.buf = malloc(wl->out.size);\n\t\t\tif (!wl->out.buf) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)ERROR(memory_allocation);\n\t\t\t}\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t/* read new input */\n\t\tpthread_mutex_lock(&ctx->read_mutex);\n\t\tin.size = ctx->inputsize;\n\t\trv = ctx->fn_read(ctx->arg_read, &in);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn (void *)mt_error(rv);\n\t\t}\n\n\t\t/* eof */\n\t\tif (in.size == 0 && ctx->frames > 0) {\n\t\t\tfree(in.buf);\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t\tgoto okay;\n\t\t}\n\t\tctx->insize += in.size;\n\t\twl->frame = ctx->frames++;\n\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t/* compress whole frame */\n\t\tresult =\n\t\t    LizardF_compressFrame((unsigned char *)wl->out.buf + 12,\n\t\t\t\t       wl->out.size - 12, in.buf, in.size,\n\t\t\t\t       &w->zpref);\n\t\tif (LizardF_isError(result)) {\n\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t/* user can lookup that code */\n\t\t\tlizardmt_errcode = result;\n\t\t\treturn (void *)ERROR(compression_library);\n\t\t}\n\n\t\t/* write skippable frame */\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 0,\n\t\t\t      LIZARDFMT_MAGIC_SKIPPABLE);\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 4, 4);\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 8, (U32) result);\n\t\twl->out.size = result + 12;\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tif (LIZARDMT_isError(result))\n\t\t\treturn (void *)result;\n\t}\n\n okay:\n\treturn 0;\n}\n\nsize_t LIZARDMT_compressCCtx(LIZARDMT_CCtx * ctx, LIZARDMT_RdWr_t * rdwr)\n{\n\tint t;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* start all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tpthread_create(&w->pthread, NULL, pt_compress, w);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(w->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\n\t/* clean up lists */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t) retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t LIZARDMT_GetInsizeCCtx(LIZARDMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t LIZARDMT_GetOutsizeCCtx(LIZARDMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t LIZARDMT_GetFramesCCtx(LIZARDMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid LIZARDMT_freeCCtx(LIZARDMT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn;\n\n\tpthread_mutex_destroy(&ctx->read_mutex);\n\tpthread_mutex_destroy(&ctx->write_mutex);\n\tfree(ctx->cwork);\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lizard-mt_decompress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#define LizardF_DISABLE_OBSOLETE_ENUMS\n#include \"lizard_frame.h\"\n\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n#include \"lizard-mt.h\"\n\n/**\n * multi threaded lizard - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tLIZARDMT_DCtx *ctx;\n\tpthread_t pthread;\n\tLIZARDMT_Buffer in;\n\tLizardF_decompressionContext_t dctx;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tLIZARDMT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct LIZARDMT_DCtx_s {\n\n\t/* threads: 1..LIZARDMT_THREAD_MAX */\n\tint threads;\n\n\t/* should be used for read from input */\n\tsize_t inputsize;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Decompression\n ****************************************/\n\nLIZARDMT_DCtx *LIZARDMT_createDCtx(int threads, int inputsize)\n{\n\tLIZARDMT_DCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (LIZARDMT_DCtx *) malloc(sizeof(LIZARDMT_DCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 1 || threads > LIZARDMT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* setup ctx */\n\tctx->threads = threads;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\t/* will be used for single stream only */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 * 64;\t/* 64K buffer */\n\n\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\tINIT_LIST_HEAD(&ctx->writelist_free);\n\tINIT_LIST_HEAD(&ctx->writelist_busy);\n\tINIT_LIST_HEAD(&ctx->writelist_done);\n\n\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\tif (!ctx->cwork)\n\t\tgoto err_cwork;\n\n\tfor (t = 0; t < threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tw->ctx = ctx;\n\n\t\t/* setup thread work */\n\t\tLizardF_createDecompressionContext(&w->dctx, LIZARDF_VERSION);\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn ERROR(read_fail);\n\tcase -2:\n\t\treturn ERROR(canceled);\n\tcase -3:\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\t/* XXX, some catch all other errors */\n\treturn ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for decompressed output\n */\nstatic size_t pt_write(LIZARDMT_DCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/**\n * pt_read - read compressed output\n */\nstatic size_t pt_read(LIZARDMT_DCtx * ctx, LIZARDMT_Buffer * in, size_t * frame)\n{\n\tunsigned char hdrbuf[12];\n\tLIZARDMT_Buffer hdr;\n\tint rv;\n\n\t/* read skippable frame (8 or 12 bytes) */\n\tpthread_mutex_lock(&ctx->read_mutex);\n\n\t/* special case, first 4 bytes already read */\n\tif (ctx->frames == 0) {\n\t\thdr.buf = hdrbuf + 4;\n\t\thdr.size = 8;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\tif (hdr.size != 8)\n\t\t\tgoto error_read;\n\t\thdr.buf = hdrbuf;\n\t} else {\n\t\thdr.buf = hdrbuf;\n\t\thdr.size = 12;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* eof reached ? */\n\t\tif (hdr.size == 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\tin->size = 0;\n\t\t\treturn 0;\n\t\t}\n\t\tif (hdr.size != 12)\n\t\t\tgoto error_read;\n\t\tif (MEM_readLE32((unsigned char *)hdr.buf + 0) !=\n\t\t    LIZARDFMT_MAGIC_SKIPPABLE)\n\t\t\tgoto error_data;\n\t}\n\n\t/* check header data */\n\tif (MEM_readLE32((unsigned char *)hdr.buf + 4) != 4)\n\t\tgoto error_data;\n\n\tctx->insize += 12;\n\t/* read new inputsize */\n\t{\n\t\tsize_t toRead = MEM_readLE32((unsigned char *)hdr.buf + 8);\n\t\tif (in->allocated < toRead) {\n\t\t\t/* need bigger input buffer */\n\t\t\tif (in->allocated)\n\t\t\t\tin->buf = realloc(in->buf, toRead);\n\t\t\telse\n\t\t\t\tin->buf = malloc(toRead);\n\t\t\tif (!in->buf)\n\t\t\t\tgoto error_nomem;\n\t\t\tin->allocated = toRead;\n\t\t}\n\n\t\tin->size = toRead;\n\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\t/* generic read failure! */\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* needed more bytes! */\n\t\tif (in->size != toRead)\n\t\t\tgoto error_data;\n\n\t\tctx->insize += in->size;\n\t}\n\t*frame = ctx->frames++;\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t/* done, no error */\n\treturn 0;\n\n error_data:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(data_error);\n error_read:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(read_fail);\n error_nomem:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(memory_allocation);\n}\n\nstatic void *pt_decompress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tLIZARDMT_Buffer *in = &w->in;\n\tLIZARDMT_DCtx *ctx = w->ctx;\n\tsize_t result = 0;\n\tstruct writelist *wl;\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tLIZARDMT_Buffer *out;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tresult = ERROR(memory_allocation);\n\t\t\t\tgoto error_unlock;\n\t\t\t}\n\t\t\twl->out.buf = 0;\n\t\t\twl->out.size = 0;\n\t\t\twl->out.allocated = 0;\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tout = &wl->out;\n\n\t\t/* zero should not happen here! */\n\t\tresult = pt_read(ctx, in, &wl->frame);\n\t\tif (LIZARDMT_isError(result)) {\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\tif (in->size == 0)\n\t\t\tbreak;\n\n\t\t/* mininmal frame */\n\t\tif (in->size < 40 && ctx->frames == 1) {\n\t\t\tout->size = 1024 * 64;\n\t\t} else {\n\t\t\t/* get frame size for output buffer */\n\t\t\tunsigned char *src = (unsigned char *)in->buf + 6;\n\t\t\tout->size = (size_t) MEM_readLE64(src);\n\t\t}\n\n\n\t\tif (out->allocated < out->size) {\n\t\t\tif (out->allocated)\n\t\t\t\tout->buf = realloc(out->buf, out->size);\n\t\t\telse\n\t\t\t\tout->buf = malloc(out->size);\n\t\t\tif (!out->buf) {\n\t\t\t\tresult = ERROR(memory_allocation);\n\t\t\t\tgoto error_lock;\n\t\t\t}\n\t\t\tout->allocated = out->size;\n\t\t}\n\n\t\tresult =\n\t\t    LizardF_decompress(w->dctx, out->buf, &out->size,\n\t\t\t\t    in->buf, &in->size, 0);\n\n\t\tif (LizardF_isError(result)) {\n\t\t\tlizardmt_errcode = result;\n\t\t\tresult = ERROR(compression_library);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\tif (result != 0) {\n\t\t\tresult = ERROR(frame_decompress);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tif (LIZARDMT_isError(result))\n\t\t\tgoto error_unlock;\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t}\n\n\t/* everything is okay */\n\tpthread_mutex_lock(&ctx->write_mutex);\n\tlist_move(&wl->node, &ctx->writelist_free);\n\tpthread_mutex_unlock(&ctx->write_mutex);\n\tif (in->allocated)\n\t\tfree(in->buf);\n\treturn 0;\n\n error_lock:\n\tpthread_mutex_lock(&ctx->write_mutex);\n error_unlock:\n\tlist_move(&wl->node, &ctx->writelist_free);\n\tpthread_mutex_unlock(&ctx->write_mutex);\n\tif (in->allocated)\n\t\tfree(in->buf);\n\treturn (void *)result;\n}\n\n/* single threaded */\nstatic size_t st_decompress(void *arg)\n{\n\tLIZARDMT_DCtx *ctx = (LIZARDMT_DCtx *) arg;\n\tLizardF_errorCode_t nextToLoad = 0;\n\tcwork_t *w = &ctx->cwork[0];\n\tLIZARDMT_Buffer Out;\n\tLIZARDMT_Buffer *out = &Out;\n\tLIZARDMT_Buffer *in = &w->in;\n\tvoid *magic = in->buf;\n\tsize_t pos = 0;\n\tint rv;\n\n\t/* allocate space for input buffer */\n\tin->size = ctx->inputsize;\n\tin->buf = malloc(in->size);\n\tif (!in->buf)\n\t\treturn ERROR(memory_allocation);\n\n\t/* allocate space for output buffer */\n\tout->size = ctx->inputsize;\n\tout->buf = malloc(out->size);\n\tif (!out->buf) {\n\t\tfree(in->buf);\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\t/* we have read already 4 bytes */\n\tin->size = 4;\n\tmemcpy(in->buf, magic, in->size);\n\n\tnextToLoad =\n\t    LizardF_decompress(w->dctx, out->buf, &pos, in->buf, &in->size, 0);\n\tif (LizardF_isError(nextToLoad)) {\n\t\tfree(in->buf);\n\t\tfree(out->buf);\n\t\treturn ERROR(compression_library);\n\t}\n\n\tfor (; nextToLoad; pos = 0) {\n\t\tif (nextToLoad > ctx->inputsize)\n\t\t\tnextToLoad = ctx->inputsize;\n\n\t\t/* read new input */\n\t\tin->size = nextToLoad;\n\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\tif (rv != 0) {\n\t\t\tfree(in->buf);\n\t\t\tfree(out->buf);\n\t\t\treturn mt_error(rv);\n\t\t}\n\n\t\t/* done, eof reached */\n\t\tif (in->size == 0)\n\t\t\tbreak;\n\n\t\t/* still to read, or still to flush */\n\t\twhile ((pos < in->size) || (out->size == ctx->inputsize)) {\n\t\t\tsize_t remaining = in->size - pos;\n\t\t\tout->size = ctx->inputsize;\n\n\t\t\t/* decompress */\n\t\t\tnextToLoad =\n\t\t\t    LizardF_decompress(w->dctx, out->buf, &out->size,\n\t\t\t\t\t    (unsigned char *)in->buf + pos,\n\t\t\t\t\t    &remaining, NULL);\n\t\t\tif (LizardF_isError(nextToLoad)) {\n\t\t\t\tfree(in->buf);\n\t\t\t\tfree(out->buf);\n\t\t\t\treturn ERROR(compression_library);\n\t\t\t}\n\n\t\t\t/* have some output */\n\t\t\tif (out->size) {\n\t\t\t\trv = ctx->fn_write(ctx->arg_write, out);\n\t\t\t\tif (rv != 0) {\n\t\t\t\t\tfree(in->buf);\n\t\t\t\t\tfree(out->buf);\n\t\t\t\t\treturn mt_error(rv);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (nextToLoad == 0)\n\t\t\t\tbreak;\n\n\t\t\tpos += remaining;\n\t\t}\n\t}\n\n\t/* no error */\n\tfree(out->buf);\n\tfree(in->buf);\n\treturn 0;\n}\n\nsize_t LIZARDMT_decompressDCtx(LIZARDMT_DCtx * ctx, LIZARDMT_RdWr_t * rdwr)\n{\n\tunsigned char buf[4];\n\tint t, rv;\n\tcwork_t *w = &ctx->cwork[0];\n\tLIZARDMT_Buffer *in = &w->in;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* check for LIZARDFMT_MAGIC_SKIPPABLE */\n\tin->buf = buf;\n\tin->size = 4;\n\trv = ctx->fn_read(ctx->arg_read, in);\n\tif (rv != 0)\n\t\treturn mt_error(rv);\n\tif (in->size != 4)\n\t\treturn ERROR(data_error);\n\n\t/* single threaded with unknown sizes */\n\tif (MEM_readLE32(buf) != LIZARDFMT_MAGIC_SKIPPABLE) {\n\n\t\t/* look for correct magic */\n\t\tif (MEM_readLE32(buf) != LIZARDFMT_MAGICNUMBER)\n\t\t\treturn ERROR(data_error);\n\n\t\t/* decompress single threaded */\n\t\treturn st_decompress(ctx);\n\t}\n\n\t/* mark unused */\n\tin->buf = 0;\n\tin->size = 0;\n\tin->allocated = 0;\n\n\t/* single threaded, but with known sizes */\n\tif (ctx->threads == 1) {\n\t\t/* no pthread_create() needed! */\n\t\tvoid *p = pt_decompress(w);\n\t\tif (p)\n\t\t\treturn (size_t) p;\n\t\tgoto okay;\n\t}\n\n\t/* multi threaded */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\twt->in.buf = 0;\n\t\twt->in.size = 0;\n\t\twt->in.allocated = 0;\n\t\tpthread_create(&wt->pthread, NULL, pt_decompress, wt);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(wt->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\n okay:\n\t/* clean up the buffers */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t) retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t LIZARDMT_GetInsizeDCtx(LIZARDMT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t LIZARDMT_GetOutsizeDCtx(LIZARDMT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t LIZARDMT_GetFramesDCtx(LIZARDMT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid LIZARDMT_freeDCtx(LIZARDMT_DCtx * ctx)\n{\n\tint t;\n\n\tif (!ctx)\n\t\treturn;\n\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tLizardF_freeDecompressionContext(w->dctx);\n\t}\n\n\tpthread_mutex_destroy(&ctx->read_mutex);\n\tpthread_mutex_destroy(&ctx->write_mutex);\n\tfree(ctx->cwork);\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz4-mt.h",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n/* ***************************************\n * Defines\n ****************************************/\n\n#ifndef LZ4MT_H\n#define LZ4MT_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#include <stddef.h>   /* size_t */\n\n/* current maximum the library will accept */\n#define LZ4MT_THREAD_MAX 128\n#define LZ4MT_LEVEL_MIN    1\n#define LZ4MT_LEVEL_MAX   12\n\n#define LZ4FMT_MAGICNUMBER     0x184D2204U\n#define LZ4FMT_MAGIC_SKIPPABLE 0x184D2A50U\n\n/* **************************************\n * Error Handling\n ****************************************/\n\nextern size_t lz4mt_errcode;\n\ntypedef enum {\n  LZ4MT_error_no_error,\n  LZ4MT_error_memory_allocation,\n  LZ4MT_error_read_fail,\n  LZ4MT_error_write_fail,\n  LZ4MT_error_data_error,\n  LZ4MT_error_frame_compress,\n  LZ4MT_error_frame_decompress,\n  LZ4MT_error_compressionParameter_unsupported,\n  LZ4MT_error_compression_library,\n  LZ4MT_error_canceled,\n  LZ4MT_error_maxCode\n} LZ4MT_ErrorCode;\n\n#ifdef ERROR\n#  undef ERROR   /* reported already defined on VS 2015 (Rich Geldreich) */\n#endif\n#define PREFIX(name) LZ4MT_error_##name\n#define ERROR(name)  ((size_t)-PREFIX(name))\nextern unsigned LZ4MT_isError(size_t code);\nextern const char* LZ4MT_getErrorString(size_t code);\n\n/* **************************************\n * Structures\n ****************************************/\n\ntypedef struct {\n\tvoid *buf;\t\t/* ptr to data */\n\tsize_t size;\t\t/* current filled in buf */\n\tsize_t allocated;\t/* length of buf */\n} LZ4MT_Buffer;\n\n/**\n * reading and writing functions\n * - you can use stdio functions or plain read/write\n * - just write some wrapper on your own\n * - a sample is given in 7-Zip ZS or lz4mt.c\n * - the function should return -1 on error and zero on success\n * - the read or written bytes will go to in->size or out->size\n */\ntypedef int (fn_read) (void *args, LZ4MT_Buffer * in);\ntypedef int (fn_write) (void *args, LZ4MT_Buffer * out);\n\ntypedef struct {\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n} LZ4MT_RdWr_t;\n\n/* **************************************\n * Compression\n ****************************************/\n\ntypedef struct LZ4MT_CCtx_s LZ4MT_CCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @level   - 1 .. 9\n * @threads - 1 .. LZ4MT_THREAD_MAX\n * @inputsize - if zero, becomes some optimal value for the level\n *            - if nonzero, the given value is taken\n */\nLZ4MT_CCtx *LZ4MT_createCCtx(int threads, int level, int inputsize);\n\n/**\n * 2) threaded compression\n * - errorcheck via \n */\nsize_t LZ4MT_compressCCtx(LZ4MT_CCtx * ctx, LZ4MT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t LZ4MT_GetFramesCCtx(LZ4MT_CCtx * ctx);\nsize_t LZ4MT_GetInsizeCCtx(LZ4MT_CCtx * ctx);\nsize_t LZ4MT_GetOutsizeCCtx(LZ4MT_CCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid LZ4MT_freeCCtx(LZ4MT_CCtx * ctx);\n\n/* **************************************\n * Decompression\n ****************************************/\n\ntypedef struct LZ4MT_DCtx_s LZ4MT_DCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @threads - 1 .. LZ4MT_THREAD_MAX\n * @ inputsize - used for single threaded standard lz4 format without skippable frames\n */\nLZ4MT_DCtx *LZ4MT_createDCtx(int threads, int inputsize);\n\n/**\n * 2) threaded compression\n * - return -1 on error\n */\nsize_t LZ4MT_decompressDCtx(LZ4MT_DCtx * ctx, LZ4MT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t LZ4MT_GetFramesDCtx(LZ4MT_DCtx * ctx);\nsize_t LZ4MT_GetInsizeDCtx(LZ4MT_DCtx * ctx);\nsize_t LZ4MT_GetOutsizeDCtx(LZ4MT_DCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid LZ4MT_freeDCtx(LZ4MT_DCtx * ctx);\n\n#if defined (__cplusplus)\n}\n#endif\n#endif\t\t\t\t/* LZ4MT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz4-mt_common.c",
    "content": "﻿\n/**\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#include \"lz4frame.h\"\n#include \"lz4-mt.h\"\n\n/* will be used for lib errors */\nsize_t lz4mt_errcode;\n\n/* ****************************************\n * LZ4MT Error Management\n ******************************************/\n\n/**\n * LZ4MT_isError() - tells if a return value is an error code\n */\nunsigned LZ4MT_isError(size_t code)\n{\n\treturn (code > ERROR(maxCode));\n}\n\n/**\n * LZ4MT_getErrorString() - give error code string from function result\n */\nconst char *LZ4MT_getErrorString(size_t code)\n{\n\tstatic const char *noErrorCode = \"Unspecified lz4mt error code\";\n\n\tif (LZ4F_isError(lz4mt_errcode))\n\t\treturn LZ4F_getErrorName(lz4mt_errcode);\n\n\tswitch ((LZ4MT_ErrorCode) (0 - code)) {\n\tcase PREFIX(no_error):\n\t\treturn \"No error detected\";\n\tcase PREFIX(memory_allocation):\n\t\treturn \"Allocation error : not enough memory\";\n\tcase PREFIX(read_fail):\n\t\treturn \"Read failure\";\n\tcase PREFIX(write_fail):\n\t\treturn \"Write failure\";\n\tcase PREFIX(data_error):\n\t\treturn \"Malformed input\";\n\tcase PREFIX(frame_compress):\n\t\treturn \"Could not compress frame at once\";\n\tcase PREFIX(frame_decompress):\n\t\treturn \"Could not decompress frame at once\";\n\tcase PREFIX(compressionParameter_unsupported):\n\t\treturn \"Compression parameter is out of bound\";\n\tcase PREFIX(compression_library):\n\t\treturn \"Compression library reports failure\";\n\tcase PREFIX(maxCode):\n\tdefault:\n\t\treturn noErrorCode;\n\t}\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz4-mt_compress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#define LZ4F_DISABLE_OBSOLETE_ENUMS\n#include \"lz4frame.h\"\n\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n#include \"lz4-mt.h\"\n\n/**\n * multi threaded lz4 - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tLZ4MT_CCtx *ctx;\n\tLZ4F_preferences_t zpref;\n\tpthread_t pthread;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tLZ4MT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct LZ4MT_CCtx_s {\n\n\t/* level: 1..LZ4MT_LEVEL_MAX */\n\tint level;\n\n\t/* threads: 1..LZ4MT_THREAD_MAX */\n\tint threads;\n\n\t/* should be used for read from input */\n\tint inputsize;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Compression\n ****************************************/\n\nLZ4MT_CCtx *LZ4MT_createCCtx(int threads, int level, int inputsize)\n{\n\tLZ4MT_CCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (LZ4MT_CCtx *) malloc(sizeof(LZ4MT_CCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 1 || threads > LZ4MT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* check level */\n\tif (level < LZ4MT_LEVEL_MIN || level > LZ4MT_LEVEL_MAX)\n\t\treturn 0;\n\n\t/* calculate chunksize for one thread */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 * 1024 * 4;\n\n\t/* printf(\"XX level=%d threads=%d inputsize=%d\\n\", level, threads, inputsize); */\n\n\t/* setup ctx */\n\tctx->level = level;\n\tctx->threads = threads;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\t/* free -> busy -> out -> free -> ... */\n\tINIT_LIST_HEAD(&ctx->writelist_free);\t/* free, can be used */\n\tINIT_LIST_HEAD(&ctx->writelist_busy);\t/* busy */\n\tINIT_LIST_HEAD(&ctx->writelist_done);\t/* can be written */\n\n\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\tif (!ctx->cwork)\n\t\tgoto err_cwork;\n\n\tfor (t = 0; t < threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tw->ctx = ctx;\n\n\t\t/* setup preferences for that thread */\n\t\tmemset(&w->zpref, 0, sizeof(LZ4F_preferences_t));\n\t\tw->zpref.compressionLevel = level;\n\t\tw->zpref.frameInfo.blockMode = LZ4F_blockLinked;\n\t\tw->zpref.frameInfo.contentSize = 1;\n\t\tw->zpref.frameInfo.contentChecksumFlag =\n\t\t    LZ4F_contentChecksumEnabled;\n\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn ERROR(read_fail);\n\tcase -2:\n\t\treturn ERROR(canceled);\n\tcase -3:\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\treturn ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for compressed output\n */\nstatic size_t pt_write(LZ4MT_CCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n\n\t/* the entry isn't the currently needed, return...  */\n\tif (wl->frame != ctx->curframe)\n\t\treturn 0;\n\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic void *pt_compress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tLZ4MT_CCtx *ctx = w->ctx;\n\tsize_t result;\n\tLZ4MT_Buffer in;\n\n\t/* inbuf is constant */\n\tin.size = ctx->inputsize;\n\tin.buf = malloc(in.size);\n\tif (!in.buf)\n\t\treturn (void *)ERROR(memory_allocation);\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tstruct writelist *wl;\n\t\tint rv;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\twl->out.size =\n\t\t\t    LZ4F_compressFrameBound(ctx->inputsize,\n\t\t\t\t\t\t    &w->zpref) + 12;\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)ERROR(memory_allocation);\n\t\t\t}\n\t\t\twl->out.size =\n\t\t\t    LZ4F_compressFrameBound(ctx->inputsize,\n\t\t\t\t\t\t    &w->zpref) + 12;;\n\t\t\twl->out.buf = malloc(wl->out.size);\n\t\t\tif (!wl->out.buf) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)ERROR(memory_allocation);\n\t\t\t}\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t/* read new input */\n\t\tpthread_mutex_lock(&ctx->read_mutex);\n\t\tin.size = ctx->inputsize;\n\t\trv = ctx->fn_read(ctx->arg_read, &in);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn (void *)mt_error(rv);\n\t\t}\n\n\t\t/* eof */\n\t\tif (in.size == 0 && ctx->frames > 0) {\n\t\t\tfree(in.buf);\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t\tgoto okay;\n\t\t}\n\t\tctx->insize += in.size;\n\t\twl->frame = ctx->frames++;\n\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t/* compress whole frame */\n\t\tif (ctx->threads != 1) {\n\t\t\t/* with SKIPPABLE frame info */\n\t\t\tresult =\n\t\t\t    LZ4F_compressFrame((unsigned char *)wl->out.buf +\n\t\t\t\t\t       12, wl->out.size - 12, in.buf,\n\t\t\t\t\t       in.size, &w->zpref);\n\n\t\t\tif (LZ4F_isError(result)) {\n\t\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t\t\t/* user can lookup that code */\n\t\t\t\tlz4mt_errcode = result;\n\t\t\t\treturn (void *)ERROR(compression_library);\n\t\t\t}\n\n\t\t\t/* write skippable frame */\n\t\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 0,\n\t\t\t\t      LZ4FMT_MAGIC_SKIPPABLE);\n\t\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 4, 4);\n\t\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 8,\n\t\t\t\t      (U32) result);\n\t\t\twl->out.size = result + 12;\n\t\t} else {\n\t\t\t/* WITHOUT SKIPPABLE frame info */\n\t\t\tresult =\n\t\t\t    LZ4F_compressFrame((unsigned char *)wl->out.buf,\n\t\t\t\t\t       wl->out.size, in.buf, in.size,\n\t\t\t\t\t       &w->zpref);\n\n\t\t\tif (LZ4F_isError(result)) {\n\t\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t\t\t/* user can lookup that code */\n\t\t\t\tlz4mt_errcode = result;\n\t\t\t\treturn (void *)ERROR(compression_library);\n\t\t\t}\n\n\t\t\twl->out.size = result;\n\t\t}\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tif (LZ4MT_isError(result))\n\t\t\treturn (void *)result;\n\t}\n\n okay:\n\treturn 0;\n}\n\nsize_t LZ4MT_compressCCtx(LZ4MT_CCtx * ctx, LZ4MT_RdWr_t * rdwr)\n{\n\tint t;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* start all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tpthread_create(&w->pthread, NULL, pt_compress, w);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(w->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\n\t/* clean up lists */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t)retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t LZ4MT_GetInsizeCCtx(LZ4MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t LZ4MT_GetOutsizeCCtx(LZ4MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t LZ4MT_GetFramesCCtx(LZ4MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid LZ4MT_freeCCtx(LZ4MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn;\n\n\tpthread_mutex_destroy(&ctx->read_mutex);\n\tpthread_mutex_destroy(&ctx->write_mutex);\n\tfree(ctx->cwork);\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz4-mt_decompress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2020 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#define LZ4F_DISABLE_OBSOLETE_ENUMS\n#include \"lz4frame.h\"\n\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n#include \"lz4-mt.h\"\n\n/**\n * multi threaded lz4 - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tLZ4MT_DCtx *ctx;\n\tpthread_t pthread;\n\tLZ4MT_Buffer in;\n\tLZ4F_decompressionContext_t dctx;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tLZ4MT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct LZ4MT_DCtx_s {\n\n\t/* threads: 1..LZ4MT_THREAD_MAX */\n\tint threads;\n\n\t/* should be used for read from input */\n\tsize_t inputsize;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Decompression\n ****************************************/\n\nLZ4MT_DCtx *LZ4MT_createDCtx(int threads, int inputsize)\n{\n\tLZ4MT_DCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (LZ4MT_DCtx *) malloc(sizeof(LZ4MT_DCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 1 || threads > LZ4MT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* setup ctx */\n\tctx->threads = threads;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\t/* will be used for single stream only */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 + 1024 * 4;\n\n\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\tINIT_LIST_HEAD(&ctx->writelist_free);\n\tINIT_LIST_HEAD(&ctx->writelist_busy);\n\tINIT_LIST_HEAD(&ctx->writelist_done);\n\n\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\tif (!ctx->cwork)\n\t\tgoto err_cwork;\n\n\tfor (t = 0; t < threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tw->ctx = ctx;\n\n\t\t/* setup thread work */\n\t\tLZ4F_createDecompressionContext(&w->dctx, LZ4F_VERSION);\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn ERROR(read_fail);\n\tcase -2:\n\t\treturn ERROR(canceled);\n\tcase -3:\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\t/* XXX, some catch all other errors */\n\treturn ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for decompressed output\n */\nstatic size_t pt_write(LZ4MT_DCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/**\n * pt_read - read compressed output\n */\nstatic size_t pt_read(LZ4MT_DCtx * ctx, LZ4MT_Buffer * in, size_t * frame)\n{\n\tunsigned char hdrbuf[12];\n\tLZ4MT_Buffer hdr;\n\tint rv;\n\n\t/* read skippable frame (8 or 12 bytes) */\n\tpthread_mutex_lock(&ctx->read_mutex);\n\n\t/* special case, first 4 bytes already read */\n\tif (ctx->frames == 0) {\n\t\thdr.buf = hdrbuf + 4;\n\t\thdr.size = 8;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\tif (hdr.size != 8)\n\t\t\tgoto error_read;\n\t\thdr.buf = hdrbuf;\n\t} else {\n\t\thdr.buf = hdrbuf;\n\t\thdr.size = 12;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* eof reached ? */\n\t\tif (hdr.size == 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\tin->size = 0;\n\t\t\treturn 0;\n\t\t}\n\t\tif (hdr.size != 12)\n\t\t\tgoto error_read;\n\t\tif (MEM_readLE32((unsigned char *)hdr.buf + 0) !=\n\t\t    LZ4FMT_MAGIC_SKIPPABLE)\n\t\t\tgoto error_data;\n\t}\n\n\t/* check header data */\n\tif (MEM_readLE32((unsigned char *)hdr.buf + 4) != 4)\n\t\tgoto error_data;\n\n\tctx->insize += 12;\n\t/* read new inputsize */\n\t{\n\t\tsize_t toRead = MEM_readLE32((unsigned char *)hdr.buf + 8);\n\t\tif (in->allocated < toRead) {\n\t\t\t/* need bigger input buffer */\n\t\t\tif (in->allocated)\n\t\t\t\tin->buf = realloc(in->buf, toRead);\n\t\t\telse\n\t\t\t\tin->buf = malloc(toRead);\n\t\t\tif (!in->buf)\n\t\t\t\tgoto error_nomem;\n\t\t\tin->allocated = toRead;\n\t\t}\n\n\t\tin->size = toRead;\n\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\t/* generic read failure! */\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* needed more bytes! */\n\t\tif (in->size != toRead)\n\t\t\tgoto error_data;\n\n\t\tctx->insize += in->size;\n\t}\n\t*frame = ctx->frames++;\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t/* done, no error */\n\treturn 0;\n\n error_data:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(data_error);\n error_read:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(read_fail);\n error_nomem:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(memory_allocation);\n}\n\nstatic void *pt_decompress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tLZ4MT_Buffer *in = &w->in;\n\tLZ4MT_DCtx *ctx = w->ctx;\n\tsize_t result = 0;\n\tstruct writelist *wl;\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tLZ4MT_Buffer *out;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tresult = ERROR(memory_allocation);\n\t\t\t\tgoto error_unlock;\n\t\t\t}\n\t\t\twl->out.buf = 0;\n\t\t\twl->out.size = 0;\n\t\t\twl->out.allocated = 0;\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tout = &wl->out;\n\n\t\t/* zero should not happen here! */\n\t\tresult = pt_read(ctx, in, &wl->frame);\n\t\tif (LZ4MT_isError(result)) {\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\tif (in->size == 0)\n\t\t\tbreak;\n\n\t\t/* mininmal frame */\n\t\tif (in->size < 40 && ctx->frames == 1) {\n\t\t\tout->size = 1024 * 64;\n\t\t} else {\n\t\t\t/* get frame size for output buffer */\n\t\t\tunsigned char *src = (unsigned char *)in->buf + 6;\n\t\t\tout->size = (size_t) MEM_readLE64(src);\n\t\t}\n\n\t\tif (out->allocated < out->size) {\n\t\t\tif (out->allocated)\n\t\t\t\tout->buf = realloc(out->buf, out->size);\n\t\t\telse\n\t\t\t\tout->buf = malloc(out->size);\n\t\t\tif (!out->buf) {\n\t\t\t\tresult = ERROR(memory_allocation);\n\t\t\t\tgoto error_lock;\n\t\t\t}\n\t\t\tout->allocated = out->size;\n\t\t}\n\n\t\tresult =\n\t\t    LZ4F_decompress(w->dctx, out->buf, &out->size,\n\t\t\t\t    in->buf, &in->size, 0);\n\n\t\tif (LZ4F_isError(result)) {\n\t\t\tlz4mt_errcode = result;\n\t\t\tresult = ERROR(compression_library);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\tif (result != 0) {\n\t\t\tresult = ERROR(frame_decompress);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tif (LZ4MT_isError(result))\n\t\t\tgoto error_unlock;\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t}\n\n\t/* everything is okay */\n\tpthread_mutex_lock(&ctx->write_mutex);\n\tlist_move(&wl->node, &ctx->writelist_free);\n\tpthread_mutex_unlock(&ctx->write_mutex);\n\tif (in->allocated)\n\t\tfree(in->buf);\n\treturn 0;\n\n error_lock:\n\tpthread_mutex_lock(&ctx->write_mutex);\n error_unlock:\n\tlist_move(&wl->node, &ctx->writelist_free);\n\tpthread_mutex_unlock(&ctx->write_mutex);\n\tif (in->allocated)\n\t\tfree(in->buf);\n\treturn (void *)result;\n}\n\n/* single threaded */\nstatic size_t st_decompress(void *arg)\n{\n\tLZ4MT_DCtx *ctx = (LZ4MT_DCtx *) arg;\n\tLZ4F_errorCode_t result = 0;\n\tcwork_t *w = &ctx->cwork[0];\n\tLZ4MT_Buffer Out;\n\tLZ4MT_Buffer *out = &Out;\n\tLZ4MT_Buffer *in = &w->in;\n\tvoid *magic = in->buf;\n\tint rv;\n\n\t/* allocate space for input buffer */\n\tin->size = ctx->inputsize;\n\tin->buf = malloc(in->size);\n\tif (!in->buf)\n\t\treturn ERROR(memory_allocation);\n\n\t/* allocate space for output buffer */\n\tout->size = ctx->inputsize;\n\tout->buf = malloc(out->size);\n\tif (!out->buf) {\n\t\tfree(in->buf);\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\t/* we have read already 4 bytes */\n\tin->size = 4;\n\tmemcpy(in->buf, magic, in->size);\n\n\t/* stats */\n\tctx->insize = 4;\n\tctx->outsize = 0;\n\n\t/* decompress loop */\n\tfor (;;) {\n\t\tsize_t srcPos = 0;\n\t\tfor (;;) {\n\t\t\tsize_t srcSize = in->size - srcPos;\n\t\t\tout->size = ctx->inputsize;\n\n\t\t\tresult = LZ4F_decompress(w->dctx, out->buf, &out->size, (unsigned char *)in->buf + srcPos, &srcSize, NULL);\n\t\t\tif (LZ4F_isError(result)) {\n\t\t\t\tfree(in->buf);\n\t\t\t\tfree(out->buf);\n\t\t\t\treturn ERROR(compression_library);\n\t\t\t}\n\n\t\t\t/* update stats */\n\t\t\tsrcPos += srcSize;\n\t\t\tctx->insize += srcSize;\n\t\t\tctx->outsize += out->size;\n\n\t\t\t/* have some output */\n\t\t\tif (out->size) {\n\t\t\t\trv = ctx->fn_write(ctx->arg_write, out);\n\t\t\t\tif (rv != 0) {\n\t\t\t\t\tfree(in->buf);\n\t\t\t\t\tfree(out->buf);\n\t\t\t\t\treturn mt_error(rv);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* consumed all input */\n\t\t\tif (srcPos == in->size)\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* read new input */\n\t\tif (result)\n\t\t\tin->size = result;\n\t\telse\n\t\t\tin->size = ctx->inputsize;\n\n\t\tif (in->size > ctx->inputsize)\n\t\t\tin->size = ctx->inputsize;\n\n\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\tctx->insize += in->size;\n\t\tif (rv != 0) {\n\t\t\tfree(in->buf);\n\t\t\tfree(out->buf);\n\t\t\treturn mt_error(rv);\n\t\t}\n\n\t\tif (in->size == 0)\n\t\t\tbreak;\n\t}\n\n\t/* no error */\n\tfree(out->buf);\n\tfree(in->buf);\n\treturn 0;\n}\n\nsize_t LZ4MT_decompressDCtx(LZ4MT_DCtx * ctx, LZ4MT_RdWr_t * rdwr)\n{\n\tunsigned char buf[4];\n\tint t, rv;\n\tcwork_t *w = &ctx->cwork[0];\n\tLZ4MT_Buffer *in = &w->in;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* check for LZ4FMT_MAGIC_SKIPPABLE */\n\tin->buf = buf;\n\tin->size = 4;\n\trv = ctx->fn_read(ctx->arg_read, in);\n\tif (rv != 0)\n\t\treturn mt_error(rv);\n\tif (in->size != 4)\n\t\treturn ERROR(data_error);\n\n\t/* single threaded with unknown sizes */\n\tif (MEM_readLE32(buf) != LZ4FMT_MAGIC_SKIPPABLE) {\n\n\t\t/* look for correct magic */\n\t\tif (MEM_readLE32(buf) != LZ4FMT_MAGICNUMBER)\n\t\t\treturn ERROR(data_error);\n\n\t\t/* decompress single threaded */\n\t\treturn st_decompress(ctx);\n\t}\n\n\t/* mark unused */\n\tin->buf = 0;\n\tin->size = 0;\n\tin->allocated = 0;\n\n\t/* single threaded, but with known sizes */\n\tif (ctx->threads == 1) {\n\t\t/* no pthread_create() needed! */\n\t\tvoid *p = pt_decompress(w);\n\t\tif (p)\n\t\t\treturn (size_t) p;\n\t\tgoto okay;\n\t}\n\n\t/* multi threaded */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\twt->in.buf = 0;\n\t\twt->in.size = 0;\n\t\twt->in.allocated = 0;\n\t\tpthread_create(&wt->pthread, NULL, pt_decompress, wt);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(wt->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\n okay:\n\t/* clean up the buffers */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t) retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t LZ4MT_GetInsizeDCtx(LZ4MT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t LZ4MT_GetOutsizeDCtx(LZ4MT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t LZ4MT_GetFramesDCtx(LZ4MT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid LZ4MT_freeDCtx(LZ4MT_DCtx * ctx)\n{\n\tint t;\n\n\tif (!ctx)\n\t\treturn;\n\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tLZ4F_freeDecompressionContext(w->dctx);\n\t}\n\n\tpthread_mutex_destroy(&ctx->read_mutex);\n\tpthread_mutex_destroy(&ctx->write_mutex);\n\tfree(ctx->cwork);\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz5-mt.h",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n/* ***************************************\n * Defines\n ****************************************/\n\n#ifndef LZ5MT_H\n#define LZ5MT_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#include <stddef.h>   /* size_t */\n\n/* current maximum the library will accept */\n#define LZ5MT_THREAD_MAX 128\n#define LZ5MT_LEVEL_MIN    1\n#define LZ5MT_LEVEL_MAX   15\n\n#define LZ5FMT_MAGICNUMBER     0x184D2205U\n#define LZ5FMT_MAGIC_SKIPPABLE 0x184D2A50U\n\n/* **************************************\n * Error Handling\n ****************************************/\n\nextern size_t lz5mt_errcode;\n\ntypedef enum {\n  LZ5MT_error_no_error,\n  LZ5MT_error_memory_allocation,\n  LZ5MT_error_read_fail,\n  LZ5MT_error_write_fail,\n  LZ5MT_error_data_error,\n  LZ5MT_error_frame_compress,\n  LZ5MT_error_frame_decompress,\n  LZ5MT_error_compressionParameter_unsupported,\n  LZ5MT_error_compression_library,\n  LZ5MT_error_canceled,\n  LZ5MT_error_maxCode\n} LZ5MT_ErrorCode;\n\n#ifdef ERROR\n#  undef ERROR   /* reported already defined on VS 2015 (Rich Geldreich) */\n#endif\n#define PREFIX(name) LZ5MT_error_##name\n#define ERROR(name)  ((size_t)-PREFIX(name))\nextern unsigned LZ5MT_isError(size_t code);\nextern const char* LZ5MT_getErrorString(size_t code);\n\n/* **************************************\n * Structures\n ****************************************/\n\ntypedef struct {\n\tvoid *buf;\t\t/* ptr to data */\n\tsize_t size;\t\t/* current filled in buf */\n\tsize_t allocated;\t/* length of buf */\n} LZ5MT_Buffer;\n\n/**\n * reading and writing functions\n * - you can use stdio functions or plain read/write\n * - just write some wrapper on your own\n * - a sample is given in 7-Zip ZS or lz5mt.c\n * - the function should return -1 on error and zero on success\n * - the read or written bytes will go to in->size or out->size\n */\ntypedef int (fn_read) (void *args, LZ5MT_Buffer * in);\ntypedef int (fn_write) (void *args, LZ5MT_Buffer * out);\n\ntypedef struct {\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n} LZ5MT_RdWr_t;\n\n/* **************************************\n * Compression\n ****************************************/\n\ntypedef struct LZ5MT_CCtx_s LZ5MT_CCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @level   - 1 .. 9\n * @threads - 1 .. LZ5MT_THREAD_MAX\n * @inputsize - if zero, becomes some optimal value for the level\n *            - if nonzero, the given value is taken\n */\nLZ5MT_CCtx *LZ5MT_createCCtx(int threads, int level, int inputsize);\n\n/**\n * 2) threaded compression\n * - errorcheck via \n */\nsize_t LZ5MT_compressCCtx(LZ5MT_CCtx * ctx, LZ5MT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t LZ5MT_GetFramesCCtx(LZ5MT_CCtx * ctx);\nsize_t LZ5MT_GetInsizeCCtx(LZ5MT_CCtx * ctx);\nsize_t LZ5MT_GetOutsizeCCtx(LZ5MT_CCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid LZ5MT_freeCCtx(LZ5MT_CCtx * ctx);\n\n/* **************************************\n * Decompression\n ****************************************/\n\ntypedef struct LZ5MT_DCtx_s LZ5MT_DCtx;\n\n/**\n * 1) allocate new cctx\n * - return cctx or zero on error\n *\n * @threads - 1 .. LZ5MT_THREAD_MAX\n * @ inputsize - used for single threaded standard lz5 format without skippable frames\n */\nLZ5MT_DCtx *LZ5MT_createDCtx(int threads, int inputsize);\n\n/**\n * 2) threaded compression\n * - return -1 on error\n */\nsize_t LZ5MT_decompressDCtx(LZ5MT_DCtx * ctx, LZ5MT_RdWr_t * rdwr);\n\n/**\n * 3) get some statistic\n */\nsize_t LZ5MT_GetFramesDCtx(LZ5MT_DCtx * ctx);\nsize_t LZ5MT_GetInsizeDCtx(LZ5MT_DCtx * ctx);\nsize_t LZ5MT_GetOutsizeDCtx(LZ5MT_DCtx * ctx);\n\n/**\n * 4) free cctx\n * - no special return value\n */\nvoid LZ5MT_freeDCtx(LZ5MT_DCtx * ctx);\n\n#if defined (__cplusplus)\n}\n#endif\n#endif\t\t\t\t/* LZ5MT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz5-mt_common.c",
    "content": "﻿\n/**\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#include \"lz5frame.h\"\n#include \"lz5-mt.h\"\n\n/* will be used for lib errors */\nsize_t lz5mt_errcode;\n\n/* ****************************************\n * LZ5MT Error Management\n ******************************************/\n\n/**\n * LZ5MT_isError() - tells if a return value is an error code\n */\nunsigned LZ5MT_isError(size_t code)\n{\n\treturn (code > ERROR(maxCode));\n}\n\n/**\n * LZ5MT_getErrorString() - give error code string from function result\n */\nconst char *LZ5MT_getErrorString(size_t code)\n{\n\tstatic const char *noErrorCode = \"Unspecified lz5mt error code\";\n\n\tif (LZ5F_isError(lz5mt_errcode))\n\t\treturn LZ5F_getErrorName(lz5mt_errcode);\n\n\tswitch ((LZ5MT_ErrorCode) (0 - code)) {\n\tcase PREFIX(no_error):\n\t\treturn \"No error detected\";\n\tcase PREFIX(memory_allocation):\n\t\treturn \"Allocation error : not enough memory\";\n\tcase PREFIX(read_fail):\n\t\treturn \"Read failure\";\n\tcase PREFIX(write_fail):\n\t\treturn \"Write failure\";\n\tcase PREFIX(data_error):\n\t\treturn \"Malformed input\";\n\tcase PREFIX(frame_compress):\n\t\treturn \"Could not compress frame at once\";\n\tcase PREFIX(frame_decompress):\n\t\treturn \"Could not decompress frame at once\";\n\tcase PREFIX(compressionParameter_unsupported):\n\t\treturn \"Compression parameter is out of bound\";\n\tcase PREFIX(compression_library):\n\t\treturn \"Compression library reports failure\";\n\tcase PREFIX(maxCode):\n\tdefault:\n\t\treturn noErrorCode;\n\t}\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz5-mt_compress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#define LZ5F_DISABLE_OBSOLETE_ENUMS\n#include \"lz5frame.h\"\n\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n#include \"lz5-mt.h\"\n\n/**\n * multi threaded lz5 - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tLZ5MT_CCtx *ctx;\n\tLZ5F_preferences_t zpref;\n\tpthread_t pthread;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tLZ5MT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct LZ5MT_CCtx_s {\n\n\t/* level: 1..LZ5MT_LEVEL_MAX */\n\tint level;\n\n\t/* threads: 1..LZ5MT_THREAD_MAX */\n\tint threads;\n\n\t/* should be used for read from input */\n\tint inputsize;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Compression\n ****************************************/\n\nLZ5MT_CCtx *LZ5MT_createCCtx(int threads, int level, int inputsize)\n{\n\tLZ5MT_CCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (LZ5MT_CCtx *) malloc(sizeof(LZ5MT_CCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 1 || threads > LZ5MT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* check level */\n\tif (level < LZ5MT_LEVEL_MIN || level > LZ5MT_LEVEL_MAX)\n\t\treturn 0;\n\n\t/* calculate chunksize for one thread */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 * 1024 * 4;\n\n\t/* setup ctx */\n\tctx->level = level;\n\tctx->threads = threads;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\t/* free -> busy -> out -> free -> ... */\n\tINIT_LIST_HEAD(&ctx->writelist_free);\t/* free, can be used */\n\tINIT_LIST_HEAD(&ctx->writelist_busy);\t/* busy */\n\tINIT_LIST_HEAD(&ctx->writelist_done);\t/* can be written */\n\n\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\tif (!ctx->cwork)\n\t\tgoto err_cwork;\n\n\tfor (t = 0; t < threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tw->ctx = ctx;\n\n\t\t/* setup preferences for that thread */\n\t\tmemset(&w->zpref, 0, sizeof(LZ5F_preferences_t));\n\t\tw->zpref.compressionLevel = level;\n\t\tw->zpref.frameInfo.blockMode = LZ5F_blockLinked;\n\t\tw->zpref.frameInfo.contentSize = 1;\n\t\tw->zpref.frameInfo.contentChecksumFlag =\n\t\t    LZ5F_contentChecksumEnabled;\n\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn ERROR(read_fail);\n\tcase -2:\n\t\treturn ERROR(canceled);\n\tcase -3:\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\treturn ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for compressed output\n */\nstatic size_t pt_write(LZ5MT_CCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n\n\t/* the entry isn't the currently needed, return...  */\n\tif (wl->frame != ctx->curframe)\n\t\treturn 0;\n\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nstatic void *pt_compress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tLZ5MT_CCtx *ctx = w->ctx;\n\tsize_t result;\n\tLZ5MT_Buffer in;\n\n\t/* inbuf is constant */\n\tin.size = ctx->inputsize;\n\tin.buf = malloc(in.size);\n\tif (!in.buf)\n\t\treturn (void *)ERROR(memory_allocation);\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tstruct writelist *wl;\n\t\tint rv;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\twl->out.size =\n\t\t\t    LZ5F_compressFrameBound(ctx->inputsize,\n\t\t\t\t\t\t    &w->zpref) + 12;\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)ERROR(memory_allocation);\n\t\t\t}\n\t\t\twl->out.size =\n\t\t\t    LZ5F_compressFrameBound(ctx->inputsize,\n\t\t\t\t\t\t    &w->zpref) + 12;;\n\t\t\twl->out.buf = malloc(wl->out.size);\n\t\t\tif (!wl->out.buf) {\n\t\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t\treturn (void *)ERROR(memory_allocation);\n\t\t\t}\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t/* read new input */\n\t\tpthread_mutex_lock(&ctx->read_mutex);\n\t\tin.size = ctx->inputsize;\n\t\trv = ctx->fn_read(ctx->arg_read, &in);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn (void *)mt_error(rv);\n\t\t}\n\n\t\t/* eof */\n\t\tif (in.size == 0 && ctx->frames > 0) {\n\t\t\tfree(in.buf);\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\n\t\t\tgoto okay;\n\t\t}\n\t\tctx->insize += in.size;\n\t\twl->frame = ctx->frames++;\n\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t\t/* compress whole frame */\n\t\tresult =\n\t\t    LZ5F_compressFrame((unsigned char *)wl->out.buf + 12,\n\t\t\t\t       wl->out.size - 12, in.buf, in.size,\n\t\t\t\t       &w->zpref);\n\t\tif (LZ5F_isError(result)) {\n\t\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\t\t/* user can lookup that code */\n\t\t\tlz5mt_errcode = result;\n\t\t\treturn (void *)ERROR(compression_library);\n\t\t}\n\n\t\t/* write skippable frame */\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 0,\n\t\t\t      LZ5FMT_MAGIC_SKIPPABLE);\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 4, 4);\n\t\tMEM_writeLE32((unsigned char *)wl->out.buf + 8, (U32) result);\n\t\twl->out.size = result + 12;\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tif (LZ5MT_isError(result))\n\t\t\treturn (void *)result;\n\t}\n\n okay:\n\treturn 0;\n}\n\nsize_t LZ5MT_compressCCtx(LZ5MT_CCtx * ctx, LZ5MT_RdWr_t * rdwr)\n{\n\tint t;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* start all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tpthread_create(&w->pthread, NULL, pt_compress, w);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(w->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\n\t/* clean up lists */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t) retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t LZ5MT_GetInsizeCCtx(LZ5MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t LZ5MT_GetOutsizeCCtx(LZ5MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t LZ5MT_GetFramesCCtx(LZ5MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid LZ5MT_freeCCtx(LZ5MT_CCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn;\n\n\tpthread_mutex_destroy(&ctx->read_mutex);\n\tpthread_mutex_destroy(&ctx->write_mutex);\n\tfree(ctx->cwork);\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/lz5-mt_decompress.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 - 2017 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#include <stdlib.h>\n#include <string.h>\n\n#define LZ5F_DISABLE_OBSOLETE_ENUMS\n#include \"lz5frame.h\"\n\n#include \"memmt.h\"\n#include \"threading.h\"\n#include \"list.h\"\n#include \"lz5-mt.h\"\n\n/**\n * multi threaded lz5 - multiple workers version\n *\n * - each thread works on his own\n * - no main thread which does reading and then starting the work\n * - needs a callback for reading / writing\n * - each worker does his:\n *   1) get read mutex and read some input\n *   2) release read mutex and do compression\n *   3) get write mutex and write result\n *   4) begin with step 1 again, until no input\n */\n\n/* worker for compression */\ntypedef struct {\n\tLZ5MT_DCtx *ctx;\n\tpthread_t pthread;\n\tLZ5MT_Buffer in;\n\tLZ5F_decompressionContext_t dctx;\n} cwork_t;\n\nstruct writelist;\nstruct writelist {\n\tsize_t frame;\n\tLZ5MT_Buffer out;\n\tstruct list_head node;\n};\n\nstruct LZ5MT_DCtx_s {\n\n\t/* threads: 1..LZ5MT_THREAD_MAX */\n\tint threads;\n\n\t/* should be used for read from input */\n\tsize_t inputsize;\n\n\t/* statistic */\n\tsize_t insize;\n\tsize_t outsize;\n\tsize_t curframe;\n\tsize_t frames;\n\n\t/* threading */\n\tcwork_t *cwork;\n\n\t/* reading input */\n\tpthread_mutex_t read_mutex;\n\tfn_read *fn_read;\n\tvoid *arg_read;\n\n\t/* writing output */\n\tpthread_mutex_t write_mutex;\n\tfn_write *fn_write;\n\tvoid *arg_write;\n\n\t/* lists for writing queue */\n\tstruct list_head writelist_free;\n\tstruct list_head writelist_busy;\n\tstruct list_head writelist_done;\n};\n\n/* **************************************\n * Decompression\n ****************************************/\n\nLZ5MT_DCtx *LZ5MT_createDCtx(int threads, int inputsize)\n{\n\tLZ5MT_DCtx *ctx;\n\tint t;\n\n\t/* allocate ctx */\n\tctx = (LZ5MT_DCtx *) malloc(sizeof(LZ5MT_DCtx));\n\tif (!ctx)\n\t\treturn 0;\n\n\t/* check threads value */\n\tif (threads < 1 || threads > LZ5MT_THREAD_MAX)\n\t\treturn 0;\n\n\t/* setup ctx */\n\tctx->threads = threads;\n\tctx->insize = 0;\n\tctx->outsize = 0;\n\tctx->frames = 0;\n\tctx->curframe = 0;\n\n\t/* will be used for single stream only */\n\tif (inputsize)\n\t\tctx->inputsize = inputsize;\n\telse\n\t\tctx->inputsize = 1024 * 64;\t/* 64K buffer */\n\n\tpthread_mutex_init(&ctx->read_mutex, NULL);\n\tpthread_mutex_init(&ctx->write_mutex, NULL);\n\n\tINIT_LIST_HEAD(&ctx->writelist_free);\n\tINIT_LIST_HEAD(&ctx->writelist_busy);\n\tINIT_LIST_HEAD(&ctx->writelist_done);\n\n\tctx->cwork = (cwork_t *) malloc(sizeof(cwork_t) * threads);\n\tif (!ctx->cwork)\n\t\tgoto err_cwork;\n\n\tfor (t = 0; t < threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tw->ctx = ctx;\n\n\t\t/* setup thread work */\n\t\tLZ5F_createDecompressionContext(&w->dctx, LZ5F_VERSION);\n\t}\n\n\treturn ctx;\n\n err_cwork:\n\tfree(ctx);\n\n\treturn 0;\n}\n\n/**\n * mt_error - return mt lib specific error code\n */\nstatic size_t mt_error(int rv)\n{\n\tswitch (rv) {\n\tcase -1:\n\t\treturn ERROR(read_fail);\n\tcase -2:\n\t\treturn ERROR(canceled);\n\tcase -3:\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\t/* XXX, some catch all other errors */\n\treturn ERROR(read_fail);\n}\n\n/**\n * pt_write - queue for decompressed output\n */\nstatic size_t pt_write(LZ5MT_DCtx * ctx, struct writelist *wl)\n{\n\tstruct list_head *entry;\n\n\t/* move the entry to the done list */\n\tlist_move(&wl->node, &ctx->writelist_done);\n again:\n\t/* check, what can be written ... */\n\tlist_for_each(entry, &ctx->writelist_done) {\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tif (wl->frame == ctx->curframe) {\n\t\t\tint rv = ctx->fn_write(ctx->arg_write, &wl->out);\n\t\t\tif (rv != 0)\n\t\t\t\treturn mt_error(rv);\n\t\t\tctx->outsize += wl->out.size;\n\t\t\tctx->curframe++;\n\t\t\tlist_move(entry, &ctx->writelist_free);\n\t\t\tgoto again;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\n/**\n * pt_read - read compressed output\n */\nstatic size_t pt_read(LZ5MT_DCtx * ctx, LZ5MT_Buffer * in, size_t * frame)\n{\n\tunsigned char hdrbuf[12];\n\tLZ5MT_Buffer hdr;\n\tint rv;\n\n\t/* read skippable frame (8 or 12 bytes) */\n\tpthread_mutex_lock(&ctx->read_mutex);\n\n\t/* special case, first 4 bytes already read */\n\tif (ctx->frames == 0) {\n\t\thdr.buf = hdrbuf + 4;\n\t\thdr.size = 8;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\tif (hdr.size != 8)\n\t\t\tgoto error_read;\n\t\thdr.buf = hdrbuf;\n\t} else {\n\t\thdr.buf = hdrbuf;\n\t\thdr.size = 12;\n\t\trv = ctx->fn_read(ctx->arg_read, &hdr);\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* eof reached ? */\n\t\tif (hdr.size == 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\tin->size = 0;\n\t\t\treturn 0;\n\t\t}\n\t\tif (hdr.size != 12)\n\t\t\tgoto error_read;\n\t\tif (MEM_readLE32((unsigned char *)hdr.buf + 0) !=\n\t\t    LZ5FMT_MAGIC_SKIPPABLE)\n\t\t\tgoto error_data;\n\t}\n\n\t/* check header data */\n\tif (MEM_readLE32((unsigned char *)hdr.buf + 4) != 4)\n\t\tgoto error_data;\n\n\tctx->insize += 12;\n\t/* read new inputsize */\n\t{\n\t\tsize_t toRead = MEM_readLE32((unsigned char *)hdr.buf + 8);\n\t\tif (in->allocated < toRead) {\n\t\t\t/* need bigger input buffer */\n\t\t\tif (in->allocated)\n\t\t\t\tin->buf = realloc(in->buf, toRead);\n\t\t\telse\n\t\t\t\tin->buf = malloc(toRead);\n\t\t\tif (!in->buf)\n\t\t\t\tgoto error_nomem;\n\t\t\tin->allocated = toRead;\n\t\t}\n\n\t\tin->size = toRead;\n\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\t/* generic read failure! */\n\t\tif (rv != 0) {\n\t\t\tpthread_mutex_unlock(&ctx->read_mutex);\n\t\t\treturn mt_error(rv);\n\t\t}\n\t\t/* needed more bytes! */\n\t\tif (in->size != toRead)\n\t\t\tgoto error_data;\n\n\t\tctx->insize += in->size;\n\t}\n\t*frame = ctx->frames++;\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\n\t/* done, no error */\n\treturn 0;\n\n error_data:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(data_error);\n error_read:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(read_fail);\n error_nomem:\n\tpthread_mutex_unlock(&ctx->read_mutex);\n\treturn ERROR(memory_allocation);\n}\n\nstatic void *pt_decompress(void *arg)\n{\n\tcwork_t *w = (cwork_t *) arg;\n\tLZ5MT_Buffer *in = &w->in;\n\tLZ5MT_DCtx *ctx = w->ctx;\n\tsize_t result = 0;\n\tstruct writelist *wl;\n\n\tfor (;;) {\n\t\tstruct list_head *entry;\n\t\tLZ5MT_Buffer *out;\n\n\t\t/* allocate space for new output */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tif (!list_empty(&ctx->writelist_free)) {\n\t\t\t/* take unused entry */\n\t\t\tentry = list_first(&ctx->writelist_free);\n\t\t\twl = list_entry(entry, struct writelist, node);\n\t\t\tlist_move(entry, &ctx->writelist_busy);\n\t\t} else {\n\t\t\t/* allocate new one */\n\t\t\twl = (struct writelist *)\n\t\t\t    malloc(sizeof(struct writelist));\n\t\t\tif (!wl) {\n\t\t\t\tresult = ERROR(memory_allocation);\n\t\t\t\tgoto error_unlock;\n\t\t\t}\n\t\t\twl->out.buf = 0;\n\t\t\twl->out.size = 0;\n\t\t\twl->out.allocated = 0;\n\t\t\tlist_add(&wl->node, &ctx->writelist_busy);\n\t\t}\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t\tout = &wl->out;\n\n\t\t/* zero should not happen here! */\n\t\tresult = pt_read(ctx, in, &wl->frame);\n\t\tif (LZ5MT_isError(result)) {\n\t\t\tlist_move(&wl->node, &ctx->writelist_free);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\tif (in->size == 0)\n\t\t\tbreak;\n\n\t\t/* mininmal frame */\n\t\tif (in->size < 40 && ctx->frames == 1) {\n\t\t\tout->size = 1024 * 64;\n\t\t} else {\n\t\t\t/* get frame size for output buffer */\n\t\t\tunsigned char *src = (unsigned char *)in->buf + 6;\n\t\t\tout->size = (size_t) MEM_readLE64(src);\n\t\t}\n\n\t\tif (out->allocated < out->size) {\n\t\t\tif (out->allocated)\n\t\t\t\tout->buf = realloc(out->buf, out->size);\n\t\t\telse\n\t\t\t\tout->buf = malloc(out->size);\n\t\t\tif (!out->buf) {\n\t\t\t\tresult = ERROR(memory_allocation);\n\t\t\t\tgoto error_lock;\n\t\t\t}\n\t\t\tout->allocated = out->size;\n\t\t}\n\n\t\tresult =\n\t\t    LZ5F_decompress(w->dctx, out->buf, &out->size,\n\t\t\t\t    in->buf, &in->size, 0);\n\n\t\tif (LZ5F_isError(result)) {\n\t\t\tlz5mt_errcode = result;\n\t\t\tresult = ERROR(compression_library);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\tif (result != 0) {\n\t\t\tresult = ERROR(frame_decompress);\n\t\t\tgoto error_lock;\n\t\t}\n\n\t\t/* write result */\n\t\tpthread_mutex_lock(&ctx->write_mutex);\n\t\tresult = pt_write(ctx, wl);\n\t\tif (LZ5MT_isError(result))\n\t\t\tgoto error_unlock;\n\t\tpthread_mutex_unlock(&ctx->write_mutex);\n\t}\n\n\t/* everything is okay */\n\tpthread_mutex_lock(&ctx->write_mutex);\n\tlist_move(&wl->node, &ctx->writelist_free);\n\tpthread_mutex_unlock(&ctx->write_mutex);\n\tif (in->allocated)\n\t\tfree(in->buf);\n\treturn 0;\n\n error_lock:\n\tpthread_mutex_lock(&ctx->write_mutex);\n error_unlock:\n\tlist_move(&wl->node, &ctx->writelist_free);\n\tpthread_mutex_unlock(&ctx->write_mutex);\n\tif (in->allocated)\n\t\tfree(in->buf);\n\treturn (void *)result;\n}\n\n/* single threaded */\nstatic size_t st_decompress(void *arg)\n{\n\tLZ5MT_DCtx *ctx = (LZ5MT_DCtx *) arg;\n\tLZ5F_errorCode_t nextToLoad = 0;\n\tcwork_t *w = &ctx->cwork[0];\n\tLZ5MT_Buffer Out;\n\tLZ5MT_Buffer *out = &Out;\n\tLZ5MT_Buffer *in = &w->in;\n\tvoid *magic = in->buf;\n\tsize_t pos = 0;\n\tint rv;\n\n\t/* allocate space for input buffer */\n\tin->size = ctx->inputsize;\n\tin->buf = malloc(in->size);\n\tif (!in->buf)\n\t\treturn ERROR(memory_allocation);\n\n\t/* allocate space for output buffer */\n\tout->size = ctx->inputsize;\n\tout->buf = malloc(out->size);\n\tif (!out->buf) {\n\t\tfree(in->buf);\n\t\treturn ERROR(memory_allocation);\n\t}\n\n\t/* we have read already 4 bytes */\n\tin->size = 4;\n\tmemcpy(in->buf, magic, in->size);\n\n\tnextToLoad =\n\t    LZ5F_decompress(w->dctx, out->buf, &pos, in->buf, &in->size, 0);\n\tif (LZ5F_isError(nextToLoad)) {\n\t\tfree(in->buf);\n\t\tfree(out->buf);\n\t\treturn ERROR(compression_library);\n\t}\n\n\tfor (; nextToLoad; pos = 0) {\n\t\tif (nextToLoad > ctx->inputsize)\n\t\t\tnextToLoad = ctx->inputsize;\n\n\t\t/* read new input */\n\t\tin->size = nextToLoad;\n\t\trv = ctx->fn_read(ctx->arg_read, in);\n\t\tif (rv != 0) {\n\t\t\tfree(in->buf);\n\t\t\tfree(out->buf);\n\t\t\treturn mt_error(rv);\n\t\t}\n\n\t\t/* done, eof reached */\n\t\tif (in->size == 0)\n\t\t\tbreak;\n\n\t\t/* still to read, or still to flush */\n\t\twhile ((pos < in->size) || (out->size == ctx->inputsize)) {\n\t\t\tsize_t remaining = in->size - pos;\n\t\t\tout->size = ctx->inputsize;\n\n\t\t\t/* decompress */\n\t\t\tnextToLoad =\n\t\t\t    LZ5F_decompress(w->dctx, out->buf, &out->size,\n\t\t\t\t\t    (unsigned char *)in->buf + pos,\n\t\t\t\t\t    &remaining, NULL);\n\t\t\tif (LZ5F_isError(nextToLoad)) {\n\t\t\t\tfree(in->buf);\n\t\t\t\tfree(out->buf);\n\t\t\t\treturn ERROR(compression_library);\n\t\t\t}\n\n\t\t\t/* have some output */\n\t\t\tif (out->size) {\n\t\t\t\trv = ctx->fn_write(ctx->arg_write, out);\n\t\t\t\tif (rv != 0) {\n\t\t\t\t\tfree(in->buf);\n\t\t\t\t\tfree(out->buf);\n\t\t\t\t\treturn mt_error(rv);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (nextToLoad == 0)\n\t\t\t\tbreak;\n\n\t\t\tpos += remaining;\n\t\t}\n\t}\n\n\t/* no error */\n\tfree(out->buf);\n\tfree(in->buf);\n\treturn 0;\n}\n\nsize_t LZ5MT_decompressDCtx(LZ5MT_DCtx * ctx, LZ5MT_RdWr_t * rdwr)\n{\n\tunsigned char buf[4];\n\tint t, rv;\n\tcwork_t *w = &ctx->cwork[0];\n\tLZ5MT_Buffer *in = &w->in;\n\tvoid *retval_of_thread = 0;\n\n\tif (!ctx)\n\t\treturn ERROR(compressionParameter_unsupported);\n\n\t/* init reading and writing functions */\n\tctx->fn_read = rdwr->fn_read;\n\tctx->fn_write = rdwr->fn_write;\n\tctx->arg_read = rdwr->arg_read;\n\tctx->arg_write = rdwr->arg_write;\n\n\t/* check for LZ5FMT_MAGIC_SKIPPABLE */\n\tin->buf = buf;\n\tin->size = 4;\n\trv = ctx->fn_read(ctx->arg_read, in);\n\tif (rv != 0)\n\t\treturn mt_error(rv);\n\tif (in->size != 4)\n\t\treturn ERROR(data_error);\n\n\t/* single threaded with unknown sizes */\n\tif (MEM_readLE32(buf) != LZ5FMT_MAGIC_SKIPPABLE) {\n\n\t\t/* look for correct magic */\n\t\tif (MEM_readLE32(buf) != LZ5FMT_MAGICNUMBER)\n\t\t\treturn ERROR(data_error);\n\n\t\t/* decompress single threaded */\n\t\treturn st_decompress(ctx);\n\t}\n\n\t/* mark unused */\n\tin->buf = 0;\n\tin->size = 0;\n\tin->allocated = 0;\n\n\t/* single threaded, but with known sizes */\n\tif (ctx->threads == 1) {\n\t\t/* no pthread_create() needed! */\n\t\tvoid *p = pt_decompress(w);\n\t\tif (p)\n\t\t\treturn (size_t) p;\n\t\tgoto okay;\n\t}\n\n\t/* multi threaded */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\twt->in.buf = 0;\n\t\twt->in.size = 0;\n\t\twt->in.allocated = 0;\n\t\tpthread_create(&wt->pthread, NULL, pt_decompress, wt);\n\t}\n\n\t/* wait for all workers */\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *wt = &ctx->cwork[t];\n\t\tvoid *p = 0;\n\t\tpthread_join(wt->pthread, &p);\n\t\tif (p)\n\t\t\tretval_of_thread = p;\n\t}\n\n okay:\n\t/* clean up the buffers */\n\twhile (!list_empty(&ctx->writelist_free)) {\n\t\tstruct writelist *wl;\n\t\tstruct list_head *entry;\n\t\tentry = list_first(&ctx->writelist_free);\n\t\twl = list_entry(entry, struct writelist, node);\n\t\tfree(wl->out.buf);\n\t\tlist_del(&wl->node);\n\t\tfree(wl);\n\t}\n\n\treturn (size_t) retval_of_thread;\n}\n\n/* returns current uncompressed data size */\nsize_t LZ5MT_GetInsizeDCtx(LZ5MT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->insize;\n}\n\n/* returns the current compressed data size */\nsize_t LZ5MT_GetOutsizeDCtx(LZ5MT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->outsize;\n}\n\n/* returns the current compressed frames */\nsize_t LZ5MT_GetFramesDCtx(LZ5MT_DCtx * ctx)\n{\n\tif (!ctx)\n\t\treturn 0;\n\n\treturn ctx->curframe;\n}\n\nvoid LZ5MT_freeDCtx(LZ5MT_DCtx * ctx)\n{\n\tint t;\n\n\tif (!ctx)\n\t\treturn;\n\n\tfor (t = 0; t < ctx->threads; t++) {\n\t\tcwork_t *w = &ctx->cwork[t];\n\t\tLZ5F_freeDecompressionContext(w->dctx);\n\t}\n\n\tpthread_mutex_destroy(&ctx->read_mutex);\n\tpthread_mutex_destroy(&ctx->write_mutex);\n\tfree(ctx->cwork);\n\tfree(ctx);\n\tctx = 0;\n\n\treturn;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/memmt.h",
    "content": "﻿\n/**\n * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include <stddef.h>     /* size_t, ptrdiff_t */\n#include <string.h>     /* memcpy */\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n#if defined(__GNUC__)\n#  define MEM_STATIC static __inline __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define MEM_STATIC static inline\n#elif defined(_MSC_VER)\n#  define MEM_STATIC static __inline\n#else\n#  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n/* code only tested on 32 and 64 bits systems */\n#define MEM_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(int)(!!(c)) }; }\nMEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }\n\n/* define likely() and unlikely() */\n#if defined(__GNUC__) || (__INTEL_COMPILER >= 800) || defined(__clang__)\n#  define expect(expr,value)    (__builtin_expect ((expr),(value)) )\n#else\n#  define expect(expr,value)    (expr)\n#endif\n#define likely(expr)     expect((expr) != 0, 1)\n#define unlikely(expr)   expect((expr) != 0, 0)\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# include <stdint.h>\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-**************************************************************\n*  Memory I/O\n*****************************************************************/\n/* MEM_FORCE_MEMORY_ACCESS :\n * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.\n * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.\n * The below switch allow to select different access method for improved performance.\n * Method 0 (default) : use `memcpy()`. Safe and portable.\n * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).\n *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.\n * Method 2 : direct access. This method is portable but violate C standard.\n *            It can generate buggy code on targets depending on alignment.\n *            In some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)\n * See http://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details.\n * Prefer these methods in priority order (0 > 1 > 2)\n */\n#ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */\n#  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )\n#    define MEM_FORCE_MEMORY_ACCESS 2\n#  elif defined(__INTEL_COMPILER) /*|| defined(_MSC_VER)*/ || \\\n  (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) ))\n#    define MEM_FORCE_MEMORY_ACCESS 1\n#  endif\n#endif\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\n#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)\n\n/* violates C standard, by lying on structure alignment.\nOnly use if no other choice to achieve best performance on target platform */\nMEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }\nMEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }\nMEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }\nMEM_STATIC U64 MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }\n\n#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)\n\n/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */\n/* currently only defined for gcc and icc */\n#if defined(_MSC_VER) || (defined(__INTEL_COMPILER) && defined(WIN32))\n\t__pragma( pack(push, 1) )\n    typedef union { U16 u16; U32 u32; U64 u64; size_t st; } unalign;\n    __pragma( pack(pop) )\n#else\n    typedef union { U16 u16; U32 u32; U64 u64; size_t st; } __attribute__((packed)) unalign;\n#endif\n\nMEM_STATIC U16 MEM_read16(const void* ptr) { return ((const unalign*)ptr)->u16; }\nMEM_STATIC U32 MEM_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }\nMEM_STATIC U64 MEM_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }\nMEM_STATIC U64 MEM_readST(const void* ptr) { return ((const unalign*)ptr)->st; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign*)memPtr)->u64 = value; }\n\n#else\n\n/* default method, safe and standard.\n   can sometimes prove slower */\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC size_t MEM_readST(const void* memPtr)\n{\n    size_t val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write32(void* memPtr, U32 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write64(void* memPtr, U64 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\n#endif /* MEM_FORCE_MEMORY_ACCESS */\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif defined (__GNUC__)\n    return __builtin_bswap32(in);\n#else\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n#endif\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_uint64(in);\n#elif defined (__GNUC__)\n    return __builtin_bswap64(in);\n#else\n    return  ((in << 56) & 0xff00000000000000ULL) |\n            ((in << 40) & 0x00ff000000000000ULL) |\n            ((in << 24) & 0x0000ff0000000000ULL) |\n            ((in << 8)  & 0x000000ff00000000ULL) |\n            ((in >> 8)  & 0x00000000ff000000ULL) |\n            ((in >> 24) & 0x0000000000ff0000ULL) |\n            ((in >> 40) & 0x000000000000ff00ULL) |\n            ((in >> 56) & 0x00000000000000ffULL);\n#endif\n}\n\nMEM_STATIC size_t MEM_swapST(size_t in)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_swap32((U32)in);\n    else\n        return (size_t)MEM_swap64((U64)in);\n}\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nMEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)\n{\n    MEM_writeLE16(memPtr, (U16)val);\n    ((BYTE*)memPtr)[2] = (BYTE)(val>>16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n        return MEM_swap32(MEM_read32(memPtr));\n}\n\nMEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)\n{\n    if (MEM_isLittleEndian())\n        MEM_write32(memPtr, val32);\n    else\n        MEM_write32(memPtr, MEM_swap32(val32));\n}\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n        return MEM_swap64(MEM_read64(memPtr));\n}\n\nMEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)\n{\n    if (MEM_isLittleEndian())\n        MEM_write64(memPtr, val64);\n    else\n        MEM_write64(memPtr, MEM_swap64(val64));\n}\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)\n{\n    if (MEM_32bits())\n        MEM_writeLE32(memPtr, (U32)val);\n    else\n        MEM_writeLE64(memPtr, (U64)val);\n}\n\n/*=== Big endian r/w ===*/\n\nMEM_STATIC U32 MEM_readBE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_swap32(MEM_read32(memPtr));\n    else\n        return MEM_read32(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32)\n{\n    if (MEM_isLittleEndian())\n        MEM_write32(memPtr, MEM_swap32(val32));\n    else\n        MEM_write32(memPtr, val32);\n}\n\nMEM_STATIC U64 MEM_readBE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_swap64(MEM_read64(memPtr));\n    else\n        return MEM_read64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64)\n{\n    if (MEM_isLittleEndian())\n        MEM_write64(memPtr, MEM_swap64(val64));\n    else\n        MEM_write64(memPtr, val64);\n}\n\nMEM_STATIC size_t MEM_readBEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readBE32(memPtr);\n    else\n        return (size_t)MEM_readBE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)\n{\n    if (MEM_32bits())\n        MEM_writeBE32(memPtr, (U32)val);\n    else\n        MEM_writeBE64(memPtr, (U64)val);\n}\n\n\n/* function safe only for comparisons */\nMEM_STATIC U32 MEM_readMINMATCH(const void* memPtr, U32 length)\n{\n    switch (length)\n    {\n    default :\n    case 4 : return MEM_read32(memPtr);\n    case 3 : if (MEM_isLittleEndian())\n                return MEM_read32(memPtr)<<8;\n             else\n                return MEM_read32(memPtr)>>8;\n    }\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/threading.h",
    "content": "﻿\n/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n#ifndef THREADING_H\n#define THREADING_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n#ifdef _WIN32\n\n/**\n * Windows Pthread Wrapper, based on this site:\n * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html\n */\n\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#include <windows.h>\n\n/* mutex */\n#define pthread_mutex_t CRITICAL_SECTION\n#define pthread_mutex_init(a,b)   InitializeCriticalSection((a))\n#define pthread_mutex_destroy(a)  DeleteCriticalSection((a))\n#define pthread_mutex_lock        EnterCriticalSection\n#define pthread_mutex_unlock      LeaveCriticalSection\n\n/* pthread_create() and pthread_join() */\ntypedef struct {\n\tHANDLE handle;\n\tvoid *(*start_routine) (void *);\n\tvoid *arg;\n} pthread_t;\n\nextern int pthread_create(pthread_t * thread, const void *unused,\n\t\t\t  void *(*start_routine) (void *), void *arg);\n\n#define pthread_join(a, b) _pthread_join(&(a), (b))\nextern int _pthread_join(pthread_t * thread, void **value_ptr);\n\n/**\n * add here more systems as required\n */\n\n#else\n\n/* POSIX Systems */\n#include <pthread.h>\n\n#endif /* POSIX Systems */\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif\t\t\t\t/* PTHREAD_H */\n"
  },
  {
    "path": "NanaZip.Codecs/ZSTDMT/zstd-mt_threading.c",
    "content": "﻿\n/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n */\n\n/**\n * This file will hold wrapper for systems, which do not support Pthreads\n */\n\n#ifdef _WIN32\n\n/**\n * Windows Pthread Wrapper, based on this site:\n * http://www.cse.wustl.edu/~schmidt/win32-cv-1.html\n */\n\n#include \"threading.h\"\n\n#include <process.h>\n#include <errno.h>\n\nstatic unsigned __stdcall worker(void *arg)\n{\n\tpthread_t *thread = (pthread_t *) arg;\n\tthread->arg = thread->start_routine(thread->arg);\n\treturn 0;\n}\n\nint\npthread_create(pthread_t * thread, const void *unused,\n\t       void *(*start_routine) (void *), void *arg)\n{\n\t(void)unused;\n\tthread->arg = arg;\n\tthread->start_routine = start_routine;\n\tthread->handle =\n\t    (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL);\n\n\tif (!thread->handle)\n\t\treturn errno;\n\telse\n\t\treturn 0;\n}\n\nint _pthread_join(pthread_t * thread, void **value_ptr)\n{\n\tDWORD result;\n\n\tif (!thread->handle)\n\t\treturn 0;\n\n\tresult = WaitForSingleObject(thread->handle, INFINITE);\n\tswitch (result) {\n\tcase WAIT_OBJECT_0:\n\t\tif (value_ptr)\n\t\t\t*value_ptr = thread->arg;\n\t\treturn 0;\n\tcase WAIT_ABANDONED:\n\t\treturn EINVAL;\n\tdefault:\n\t\treturn GetLastError();\n\t}\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/allocations.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This file provides custom allocation primitives\n */\n\n#define ZSTD_DEPS_NEED_MALLOC\n#include \"zstd_deps.h\"   /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */\n\n#include \"compiler.h\" /* MEM_STATIC */\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"../zstd.h\" /* ZSTD_customMem */\n\n#ifndef ZSTD_ALLOCATIONS_H\n#define ZSTD_ALLOCATIONS_H\n\n/* custom memory allocation functions */\n\nMEM_STATIC void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem)\n{\n    if (customMem.customAlloc)\n        return customMem.customAlloc(customMem.opaque, size);\n    return ZSTD_malloc(size);\n}\n\nMEM_STATIC void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem)\n{\n    if (customMem.customAlloc) {\n        /* calloc implemented as malloc+memset;\n         * not as efficient as calloc, but next best guess for custom malloc */\n        void* const ptr = customMem.customAlloc(customMem.opaque, size);\n        ZSTD_memset(ptr, 0, size);\n        return ptr;\n    }\n    return ZSTD_calloc(1, size);\n}\n\nMEM_STATIC void ZSTD_customFree(void* ptr, ZSTD_customMem customMem)\n{\n    if (ptr!=NULL) {\n        if (customMem.customFree)\n            customMem.customFree(customMem.opaque, ptr);\n        else\n            ZSTD_free(ptr);\n    }\n}\n\n#endif /* ZSTD_ALLOCATIONS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/bits.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_BITS_H\n#define ZSTD_BITS_H\n\n#include \"mem.h\"\n\nMEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)\n{\n    assert(val != 0);\n    {\n        static const U32 DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3,\n                                                30, 22, 20, 15, 25, 17, 4, 8,\n                                                31, 27, 13, 23, 21, 19, 16, 7,\n                                                26, 12, 18, 6, 11, 5, 10, 9};\n        return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];\n    }\n}\n\nMEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER)\n#  if STATIC_BMI2\n    return (unsigned)_tzcnt_u32(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanForward(&r, val);\n        return (unsigned)r;\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4)\n    return (unsigned)__builtin_ctz(val);\n#elif defined(__ICCARM__)\n    return (unsigned)__builtin_ctz(val);\n#else\n    return ZSTD_countTrailingZeros32_fallback(val);\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val)\n{\n    assert(val != 0);\n    {\n        static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29,\n                                            11, 14, 16, 18, 22, 25, 3, 30,\n                                            8, 12, 20, 28, 15, 17, 24, 7,\n                                            19, 27, 23, 6, 26, 5, 4, 31};\n        val |= val >> 1;\n        val |= val >> 2;\n        val |= val >> 4;\n        val |= val >> 8;\n        val |= val >> 16;\n        return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27];\n    }\n}\n\nMEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER)\n#  if STATIC_BMI2\n    return (unsigned)_lzcnt_u32(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanReverse(&r, val);\n        return (unsigned)(31 - r);\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4)\n    return (unsigned)__builtin_clz(val);\n#elif defined(__ICCARM__)\n    return (unsigned)__builtin_clz(val);\n#else\n    return ZSTD_countLeadingZeros32_fallback(val);\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER) && defined(_WIN64)\n#  if STATIC_BMI2\n    return (unsigned)_tzcnt_u64(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanForward64(&r, val);\n        return (unsigned)r;\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__)\n    return (unsigned)__builtin_ctzll(val);\n#elif defined(__ICCARM__)\n    return (unsigned)__builtin_ctzll(val);\n#else\n    {\n        U32 mostSignificantWord = (U32)(val >> 32);\n        U32 leastSignificantWord = (U32)val;\n        if (leastSignificantWord == 0) {\n            return 32 + ZSTD_countTrailingZeros32(mostSignificantWord);\n        } else {\n            return ZSTD_countTrailingZeros32(leastSignificantWord);\n        }\n    }\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val)\n{\n    assert(val != 0);\n#if defined(_MSC_VER) && defined(_WIN64)\n#  if STATIC_BMI2\n    return (unsigned)_lzcnt_u64(val);\n#  else\n    if (val != 0) {\n        unsigned long r;\n        _BitScanReverse64(&r, val);\n        return (unsigned)(63 - r);\n    } else {\n        __assume(0); /* Should not reach this code path */\n    }\n#  endif\n#elif defined(__GNUC__) && (__GNUC__ >= 4)\n    return (unsigned)(__builtin_clzll(val));\n#elif defined(__ICCARM__)\n    return (unsigned)(__builtin_clzll(val));\n#else\n    {\n        U32 mostSignificantWord = (U32)(val >> 32);\n        U32 leastSignificantWord = (U32)val;\n        if (mostSignificantWord == 0) {\n            return 32 + ZSTD_countLeadingZeros32(leastSignificantWord);\n        } else {\n            return ZSTD_countLeadingZeros32(mostSignificantWord);\n        }\n    }\n#endif\n}\n\nMEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val)\n{\n    if (MEM_isLittleEndian()) {\n        if (MEM_64bits()) {\n            return ZSTD_countTrailingZeros64((U64)val) >> 3;\n        } else {\n            return ZSTD_countTrailingZeros32((U32)val) >> 3;\n        }\n    } else {  /* Big Endian CPU */\n        if (MEM_64bits()) {\n            return ZSTD_countLeadingZeros64((U64)val) >> 3;\n        } else {\n            return ZSTD_countLeadingZeros32((U32)val) >> 3;\n        }\n    }\n}\n\nMEM_STATIC unsigned ZSTD_highbit32(U32 val)   /* compress, dictBuilder, decodeCorpus */\n{\n    assert(val != 0);\n    return 31 - ZSTD_countLeadingZeros32(val);\n}\n\n/* ZSTD_rotateRight_*():\n * Rotates a bitfield to the right by \"count\" bits.\n * https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts\n */\nMEM_STATIC\nU64 ZSTD_rotateRight_U64(U64 const value, U32 count) {\n    assert(count < 64);\n    count &= 0x3F; /* for fickle pattern recognition */\n    return (value >> count) | (U64)(value << ((0U - count) & 0x3F));\n}\n\nMEM_STATIC\nU32 ZSTD_rotateRight_U32(U32 const value, U32 count) {\n    assert(count < 32);\n    count &= 0x1F; /* for fickle pattern recognition */\n    return (value >> count) | (U32)(value << ((0U - count) & 0x1F));\n}\n\nMEM_STATIC\nU16 ZSTD_rotateRight_U16(U16 const value, U32 count) {\n    assert(count < 16);\n    count &= 0x0F; /* for fickle pattern recognition */\n    return (value >> count) | (U16)(value << ((0U - count) & 0x0F));\n}\n\n#endif /* ZSTD_BITS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/bitstream.h",
    "content": "﻿/* ******************************************************************\n * bitstream\n * Part of FSE library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n/*\n*  This API consists of small unitary functions, which must be inlined for best performance.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include \"mem.h\"            /* unaligned access routines */\n#include \"compiler.h\"       /* UNLIKELY() */\n#include \"debug.h\"          /* assert(), DEBUGLOG(), RAWLOG() */\n#include \"error_private.h\"  /* error codes and messages */\n#include \"bits.h\"           /* ZSTD_highbit32 */\n\n/*=========================================\n*  Target specific\n=========================================*/\n#ifndef ZSTD_NO_INTRINSICS\n#  if (defined(__BMI__) || defined(__BMI2__)) && defined(__GNUC__)\n#    include <immintrin.h>   /* support for bextr (experimental)/bzhi */\n#  elif defined(__ICCARM__)\n#    include <intrinsics.h>\n#  endif\n#endif\n\n#define STREAM_ACCUMULATOR_MIN_32  25\n#define STREAM_ACCUMULATOR_MIN_64  57\n#define STREAM_ACCUMULATOR_MIN    ((U32)(MEM_32bits() ? STREAM_ACCUMULATOR_MIN_32 : STREAM_ACCUMULATOR_MIN_64))\n\n\n/*-******************************************\n*  bitStream encoding API (write forward)\n********************************************/\ntypedef size_t BitContainerType;\n/* bitStream can mix input from multiple sources.\n * A critical property of these streams is that they encode and decode in **reverse** direction.\n * So the first bit sequence you add will be the last to be read, like a LIFO stack.\n */\ntypedef struct {\n    BitContainerType bitContainer;\n    unsigned bitPos;\n    char*  startPtr;\n    char*  ptr;\n    char*  endPtr;\n} BIT_CStream_t;\n\nMEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, void* dstBuffer, size_t dstCapacity);\nMEM_STATIC void   BIT_addBits(BIT_CStream_t* bitC, BitContainerType value, unsigned nbBits);\nMEM_STATIC void   BIT_flushBits(BIT_CStream_t* bitC);\nMEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC);\n\n/* Start with initCStream, providing the size of buffer to write into.\n*  bitStream will never write outside of this buffer.\n*  `dstCapacity` must be >= sizeof(bitD->bitContainer), otherwise @return will be an error code.\n*\n*  bits are first added to a local register.\n*  Local register is BitContainerType, 64-bits on 64-bits systems, or 32-bits on 32-bits systems.\n*  Writing data into memory is an explicit operation, performed by the flushBits function.\n*  Hence keep track how many bits are potentially stored into local register to avoid register overflow.\n*  After a flushBits, a maximum of 7 bits might still be stored into local register.\n*\n*  Avoid storing elements of more than 24 bits if you want compatibility with 32-bits bitstream readers.\n*\n*  Last operation is to close the bitStream.\n*  The function returns the final size of CStream in bytes.\n*  If data couldn't fit into `dstBuffer`, it will return a 0 ( == not storable)\n*/\n\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct {\n    BitContainerType bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n    const char* limitPtr;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,  /* fully refilled */\n               BIT_DStream_endOfBuffer = 1, /* still some bits left in bitstream */\n               BIT_DStream_completed = 2,   /* bitstream entirely consumed, bit-exact */\n               BIT_DStream_overflow = 3     /* user requested more bits than present in bitstream */\n    } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n/* Start by invoking BIT_initDStream().\n*  A chunk of the bitStream is then stored into a local register.\n*  Local register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (BitContainerType).\n*  You can then retrieve bitFields stored into the local register, **in reverse order**.\n*  Local register is explicitly reloaded from memory by the BIT_reloadDStream() method.\n*  A reload guarantee a minimum of ((8*sizeof(bitD->bitContainer))-7) bits when its result is BIT_DStream_unfinished.\n*  Otherwise, it can be less than that, so proceed accordingly.\n*  Checking if DStream has reached its end can be performed with BIT_endOfDStream().\n*/\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC, BitContainerType value, unsigned nbBits);\n/* faster, but works only if value is \"clean\", meaning all high bits above nbBits are 0 */\n\nMEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC);\n/* unsafe version; does not check buffer overflow */\n\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n/*=====    Local Constants   =====*/\nstatic const unsigned BIT_mask[] = {\n    0,          1,         3,         7,         0xF,       0x1F,\n    0x3F,       0x7F,      0xFF,      0x1FF,     0x3FF,     0x7FF,\n    0xFFF,      0x1FFF,    0x3FFF,    0x7FFF,    0xFFFF,    0x1FFFF,\n    0x3FFFF,    0x7FFFF,   0xFFFFF,   0x1FFFFF,  0x3FFFFF,  0x7FFFFF,\n    0xFFFFFF,   0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF,\n    0x3FFFFFFF, 0x7FFFFFFF}; /* up to 31 bits */\n#define BIT_MASK_SIZE (sizeof(BIT_mask) / sizeof(BIT_mask[0]))\n\n/*-**************************************************************\n*  bitStream encoding\n****************************************************************/\n/*! BIT_initCStream() :\n *  `dstCapacity` must be > sizeof(size_t)\n *  @return : 0 if success,\n *            otherwise an error code (can be tested using ERR_isError()) */\nMEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC,\n                                  void* startPtr, size_t dstCapacity)\n{\n    bitC->bitContainer = 0;\n    bitC->bitPos = 0;\n    bitC->startPtr = (char*)startPtr;\n    bitC->ptr = bitC->startPtr;\n    bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer);\n    if (dstCapacity <= sizeof(bitC->bitContainer)) return ERROR(dstSize_tooSmall);\n    return 0;\n}\n\nFORCE_INLINE_TEMPLATE BitContainerType BIT_getLowerBits(BitContainerType bitContainer, U32 const nbBits)\n{\n#if STATIC_BMI2 && !defined(ZSTD_NO_INTRINSICS)\n#  if (defined(__x86_64__) || defined(_M_X64)) && !defined(__ILP32__)\n    return _bzhi_u64(bitContainer, nbBits);\n#  else\n    DEBUG_STATIC_ASSERT(sizeof(bitContainer) == sizeof(U32));\n    return _bzhi_u32(bitContainer, nbBits);\n#  endif\n#else\n    assert(nbBits < BIT_MASK_SIZE);\n    return bitContainer & BIT_mask[nbBits];\n#endif\n}\n\n/*! BIT_addBits() :\n *  can add up to 31 bits into `bitC`.\n *  Note : does not check for register overflow ! */\nMEM_STATIC void BIT_addBits(BIT_CStream_t* bitC,\n                            BitContainerType value, unsigned nbBits)\n{\n    DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32);\n    assert(nbBits < BIT_MASK_SIZE);\n    assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    bitC->bitContainer |= BIT_getLowerBits(value, nbBits) << bitC->bitPos;\n    bitC->bitPos += nbBits;\n}\n\n/*! BIT_addBitsFast() :\n *  works only if `value` is _clean_,\n *  meaning all high bits above nbBits are 0 */\nMEM_STATIC void BIT_addBitsFast(BIT_CStream_t* bitC,\n                                BitContainerType value, unsigned nbBits)\n{\n    assert((value>>nbBits) == 0);\n    assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    bitC->bitContainer |= value << bitC->bitPos;\n    bitC->bitPos += nbBits;\n}\n\n/*! BIT_flushBitsFast() :\n *  assumption : bitContainer has not overflowed\n *  unsafe version; does not check buffer overflow */\nMEM_STATIC void BIT_flushBitsFast(BIT_CStream_t* bitC)\n{\n    size_t const nbBytes = bitC->bitPos >> 3;\n    assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    assert(bitC->ptr <= bitC->endPtr);\n    MEM_writeLEST(bitC->ptr, bitC->bitContainer);\n    bitC->ptr += nbBytes;\n    bitC->bitPos &= 7;\n    bitC->bitContainer >>= nbBytes*8;\n}\n\n/*! BIT_flushBits() :\n *  assumption : bitContainer has not overflowed\n *  safe version; check for buffer overflow, and prevents it.\n *  note : does not signal buffer overflow.\n *  overflow will be revealed later on using BIT_closeCStream() */\nMEM_STATIC void BIT_flushBits(BIT_CStream_t* bitC)\n{\n    size_t const nbBytes = bitC->bitPos >> 3;\n    assert(bitC->bitPos < sizeof(bitC->bitContainer) * 8);\n    assert(bitC->ptr <= bitC->endPtr);\n    MEM_writeLEST(bitC->ptr, bitC->bitContainer);\n    bitC->ptr += nbBytes;\n    if (bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;\n    bitC->bitPos &= 7;\n    bitC->bitContainer >>= nbBytes*8;\n}\n\n/*! BIT_closeCStream() :\n *  @return : size of CStream, in bytes,\n *            or 0 if it could not fit into dstBuffer */\nMEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC)\n{\n    BIT_addBitsFast(bitC, 1, 1);   /* endMark */\n    BIT_flushBits(bitC);\n    if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */\n    return (size_t)(bitC->ptr - bitC->startPtr) + (bitC->bitPos > 0);\n}\n\n\n/*-********************************************************\n*  bitStream decoding\n**********************************************************/\n/*! BIT_initDStream() :\n *  Initialize a BIT_DStream_t.\n * `bitD` : a pointer to an already allocated BIT_DStream_t structure.\n * `srcSize` must be the *exact* size of the bitStream, in bytes.\n * @return : size of stream (== srcSize), or an errorCode if a problem is detected\n */\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    bitD->start = (const char*)srcBuffer;\n    bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer);\n\n    if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;  /* ensures bitsConsumed is always set */\n          if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }\n    } else {\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n        case 7: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);\n                ZSTD_FALLTHROUGH;\n\n        case 6: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);\n                ZSTD_FALLTHROUGH;\n\n        case 5: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);\n                ZSTD_FALLTHROUGH;\n\n        case 4: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[3]) << 24;\n                ZSTD_FALLTHROUGH;\n\n        case 3: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[2]) << 16;\n                ZSTD_FALLTHROUGH;\n\n        case 2: bitD->bitContainer += (BitContainerType)(((const BYTE*)(srcBuffer))[1]) <<  8;\n                ZSTD_FALLTHROUGH;\n\n        default: break;\n        }\n        {   BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n            bitD->bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;\n            if (lastByte == 0) return ERROR(corruption_detected);  /* endMark not present */\n        }\n        bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nFORCE_INLINE_TEMPLATE BitContainerType BIT_getUpperBits(BitContainerType bitContainer, U32 const start)\n{\n    return bitContainer >> start;\n}\n\nFORCE_INLINE_TEMPLATE BitContainerType BIT_getMiddleBits(BitContainerType bitContainer, U32 const start, U32 const nbBits)\n{\n    U32 const regMask = sizeof(bitContainer)*8 - 1;\n    /* if start > regMask, bitstream is corrupted, and result is undefined */\n    assert(nbBits < BIT_MASK_SIZE);\n    /* x86 transform & ((1 << nbBits) - 1) to bzhi instruction, it is better\n     * than accessing memory. When bmi2 instruction is not present, we consider\n     * such cpus old (pre-Haswell, 2013) and their performance is not of that\n     * importance.\n     */\n#if defined(__x86_64__) || defined(_M_X64)\n    return (bitContainer >> (start & regMask)) & ((((U64)1) << nbBits) - 1);\n#else\n    return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];\n#endif\n}\n\n/*! BIT_lookBits() :\n *  Provides next n bits from local register.\n *  local register is not modified.\n *  On 32-bits, maxNbBits==24.\n *  On 64-bits, maxNbBits==56.\n * @return : value extracted */\nFORCE_INLINE_TEMPLATE BitContainerType BIT_lookBits(const BIT_DStream_t*  bitD, U32 nbBits)\n{\n    /* arbitrate between double-shift and shift+mask */\n#if 1\n    /* if bitD->bitsConsumed + nbBits > sizeof(bitD->bitContainer)*8,\n     * bitstream is likely corrupted, and result is undefined */\n    return BIT_getMiddleBits(bitD->bitContainer, (sizeof(bitD->bitContainer)*8) - bitD->bitsConsumed - nbBits, nbBits);\n#else\n    /* this code path is slower on my os-x laptop */\n    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> 1) >> ((regMask-nbBits) & regMask);\n#endif\n}\n\n/*! BIT_lookBitsFast() :\n *  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC BitContainerType BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits)\n{\n    U32 const regMask = sizeof(bitD->bitContainer)*8 - 1;\n    assert(nbBits >= 1);\n    return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask);\n}\n\nFORCE_INLINE_TEMPLATE void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\n/*! BIT_readBits() :\n *  Read (consume) next n bits from local register and update.\n *  Pay attention to not read more than nbBits contained into local register.\n * @return : extracted value. */\nFORCE_INLINE_TEMPLATE BitContainerType BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits)\n{\n    BitContainerType const value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BIT_readBitsFast() :\n *  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC BitContainerType BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits)\n{\n    BitContainerType const value = BIT_lookBitsFast(bitD, nbBits);\n    assert(nbBits >= 1);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BIT_reloadDStream_internal() :\n *  Simple variant of BIT_reloadDStream(), with two conditions:\n *  1. bitstream is valid : bitsConsumed <= sizeof(bitD->bitContainer)*8\n *  2. look window is valid after shifted down : bitD->ptr >= bitD->start\n */\nMEM_STATIC BIT_DStream_status BIT_reloadDStream_internal(BIT_DStream_t* bitD)\n{\n    assert(bitD->bitsConsumed <= sizeof(bitD->bitContainer)*8);\n    bitD->ptr -= bitD->bitsConsumed >> 3;\n    assert(bitD->ptr >= bitD->start);\n    bitD->bitsConsumed &= 7;\n    bitD->bitContainer = MEM_readLEST(bitD->ptr);\n    return BIT_DStream_unfinished;\n}\n\n/*! BIT_reloadDStreamFast() :\n *  Similar to BIT_reloadDStream(), but with two differences:\n *  1. bitsConsumed <= sizeof(bitD->bitContainer)*8 must hold!\n *  2. Returns BIT_DStream_overflow when bitD->ptr < bitD->limitPtr, at this\n *     point you must use BIT_reloadDStream() to reload.\n */\nMEM_STATIC BIT_DStream_status BIT_reloadDStreamFast(BIT_DStream_t* bitD)\n{\n    if (UNLIKELY(bitD->ptr < bitD->limitPtr))\n        return BIT_DStream_overflow;\n    return BIT_reloadDStream_internal(bitD);\n}\n\n/*! BIT_reloadDStream() :\n *  Refill `bitD` from buffer previously set in BIT_initDStream() .\n *  This function is safe, it guarantees it will not never beyond src buffer.\n * @return : status of `BIT_DStream_t` internal register.\n *           when status == BIT_DStream_unfinished, internal register is filled with at least 25 or 57 bits */\nFORCE_INLINE_TEMPLATE BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    /* note : once in overflow mode, a bitstream remains in this mode until it's reset */\n    if (UNLIKELY(bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))) {\n        static const BitContainerType zeroFilled = 0;\n        bitD->ptr = (const char*)&zeroFilled; /* aliasing is allowed for char */\n        /* overflow detected, erroneous scenario or end of stream: no update */\n        return BIT_DStream_overflow;\n    }\n\n    assert(bitD->ptr >= bitD->start);\n\n    if (bitD->ptr >= bitD->limitPtr) {\n        return BIT_reloadDStream_internal(bitD);\n    }\n    if (bitD->ptr == bitD->start) {\n        /* reached end of bitStream => no update */\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    /* start < ptr < limitPtr => cautious update */\n    {   U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD->bitContainer), otherwise bitD->ptr == bitD->start */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream() :\n * @return : 1 if DStream has _exactly_ reached its end (all bits consumed).\n */\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#endif /* BITSTREAM_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/compiler.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPILER_H\n#define ZSTD_COMPILER_H\n\n#include <stddef.h>\n\n#include \"portability_macros.h\"\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n/* force inlining */\n\n#if !defined(ZSTD_NO_INLINE)\n#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#  define INLINE_KEYWORD inline\n#else\n#  define INLINE_KEYWORD\n#endif\n\n#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#  define FORCE_INLINE_ATTR __attribute__((always_inline))\n#elif defined(_MSC_VER)\n#  define FORCE_INLINE_ATTR __forceinline\n#else\n#  define FORCE_INLINE_ATTR\n#endif\n\n#else\n\n#define INLINE_KEYWORD\n#define FORCE_INLINE_ATTR\n\n#endif\n\n/**\n  On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).\n  This explicitly marks such functions as __cdecl so that the code will still compile\n  if a CC other than __cdecl has been made the default.\n*/\n#if  defined(_MSC_VER)\n#  define WIN_CDECL __cdecl\n#else\n#  define WIN_CDECL\n#endif\n\n/* UNUSED_ATTR tells the compiler it is okay if the function is unused. */\n#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#  define UNUSED_ATTR __attribute__((unused))\n#else\n#  define UNUSED_ATTR\n#endif\n\n/**\n * FORCE_INLINE_TEMPLATE is used to define C \"templates\", which take constant\n * parameters. They must be inlined for the compiler to eliminate the constant\n * branches.\n */\n#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR UNUSED_ATTR\n/**\n * HINT_INLINE is used to help the compiler generate better code. It is *not*\n * used for \"templates\", so it can be tweaked based on the compilers\n * performance.\n *\n * gcc-4.8 and gcc-4.9 have been shown to benefit from leaving off the\n * always_inline attribute.\n *\n * clang up to 5.0.0 (trunk) benefit tremendously from the always_inline\n * attribute.\n */\n#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 8 && __GNUC__ < 5\n#  define HINT_INLINE static INLINE_KEYWORD\n#else\n#  define HINT_INLINE FORCE_INLINE_TEMPLATE\n#endif\n\n/* \"soft\" inline :\n * The compiler is free to select if it's a good idea to inline or not.\n * The main objective is to silence compiler warnings\n * when a defined function in included but not used.\n *\n * Note : this macro is prefixed `MEM_` because it used to be provided by `mem.h` unit.\n * Updating the prefix is probably preferable, but requires a fairly large codemod,\n * since this name is used everywhere.\n */\n#ifndef MEM_STATIC  /* already defined in Linux Kernel mem.h */\n#if defined(__GNUC__)\n#  define MEM_STATIC static __inline UNUSED_ATTR\n#elif defined(__IAR_SYSTEMS_ICC__)\n#  define MEM_STATIC static inline UNUSED_ATTR\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define MEM_STATIC static inline\n#elif defined(_MSC_VER)\n#  define MEM_STATIC static __inline\n#else\n#  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n#endif\n\n/* force no inlining */\n#ifdef _MSC_VER\n#  define FORCE_NOINLINE static __declspec(noinline)\n#else\n#  if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#    define FORCE_NOINLINE static __attribute__((__noinline__))\n#  else\n#    define FORCE_NOINLINE static\n#  endif\n#endif\n\n\n/* target attribute */\n#if defined(__GNUC__) || defined(__IAR_SYSTEMS_ICC__)\n#  define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))\n#else\n#  define TARGET_ATTRIBUTE(target)\n#endif\n\n/* Target attribute for BMI2 dynamic dispatch.\n * Enable lzcnt, bmi, and bmi2.\n * We test for bmi1 & bmi2. lzcnt is included in bmi1.\n */\n#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE(\"lzcnt,bmi,bmi2\")\n\n/* prefetch\n * can be disabled, by declaring NO_PREFETCH build macro */\n#if defined(NO_PREFETCH)\n#  define PREFETCH_L1(ptr)  do { (void)(ptr); } while (0)  /* disabled */\n#  define PREFETCH_L2(ptr)  do { (void)(ptr); } while (0)  /* disabled */\n#else\n#  if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) && !defined(_M_ARM64EC)  /* _mm_prefetch() is not defined outside of x86/x64 */\n#    include <mmintrin.h>   /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */\n#    define PREFETCH_L1(ptr)  _mm_prefetch((const char*)(ptr), _MM_HINT_T0)\n#    define PREFETCH_L2(ptr)  _mm_prefetch((const char*)(ptr), _MM_HINT_T1)\n#  elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )\n#    define PREFETCH_L1(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)\n#    define PREFETCH_L2(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */)\n#  elif defined(__aarch64__)\n#    define PREFETCH_L1(ptr)  do { __asm__ __volatile__(\"prfm pldl1keep, %0\" ::\"Q\"(*(ptr))); } while (0)\n#    define PREFETCH_L2(ptr)  do { __asm__ __volatile__(\"prfm pldl2keep, %0\" ::\"Q\"(*(ptr))); } while (0)\n#  else\n#    define PREFETCH_L1(ptr) do { (void)(ptr); } while (0)  /* disabled */\n#    define PREFETCH_L2(ptr) do { (void)(ptr); } while (0)  /* disabled */\n#  endif\n#endif  /* NO_PREFETCH */\n\n#define CACHELINE_SIZE 64\n\n#define PREFETCH_AREA(p, s)                              \\\n    do {                                                 \\\n        const char* const _ptr = (const char*)(p);       \\\n        size_t const _size = (size_t)(s);                \\\n        size_t _pos;                                     \\\n        for (_pos=0; _pos<_size; _pos+=CACHELINE_SIZE) { \\\n            PREFETCH_L2(_ptr + _pos);                    \\\n        }                                                \\\n    } while (0)\n\n/* vectorization\n * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,\n * and some compilers, like Intel ICC and MCST LCC, do not support it at all. */\n#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__)\n#  if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)\n#    define DONT_VECTORIZE __attribute__((optimize(\"no-tree-vectorize\")))\n#  else\n#    define DONT_VECTORIZE _Pragma(\"GCC optimize(\\\"no-tree-vectorize\\\")\")\n#  endif\n#else\n#  define DONT_VECTORIZE\n#endif\n\n/* Tell the compiler that a branch is likely or unlikely.\n * Only use these macros if it causes the compiler to generate better code.\n * If you can remove a LIKELY/UNLIKELY annotation without speed changes in gcc\n * and clang, please do.\n */\n#if defined(__GNUC__)\n#define LIKELY(x) (__builtin_expect((x), 1))\n#define UNLIKELY(x) (__builtin_expect((x), 0))\n#else\n#define LIKELY(x) (x)\n#define UNLIKELY(x) (x)\n#endif\n\n#if __has_builtin(__builtin_unreachable) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))\n#  define ZSTD_UNREACHABLE do { assert(0), __builtin_unreachable(); } while (0)\n#else\n#  define ZSTD_UNREACHABLE do { assert(0); } while (0)\n#endif\n\n/* disable warnings */\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4100)        /* disable: C4100: unreferenced formal parameter */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4204)        /* disable: C4204: non-constant aggregate initializer */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n/* compile time determination of SIMD support */\n#if !defined(ZSTD_NO_INTRINSICS)\n#  if defined(__AVX2__)\n#    define ZSTD_ARCH_X86_AVX2\n#  endif\n#  if defined(__SSE2__) || defined(_M_X64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))\n#    define ZSTD_ARCH_X86_SSE2\n#  endif\n#  if defined(__ARM_NEON) || defined(_M_ARM64)\n#    define ZSTD_ARCH_ARM_NEON\n#  endif\n#\n#  if defined(ZSTD_ARCH_X86_AVX2)\n#    include <immintrin.h>\n#  endif\n#  if defined(ZSTD_ARCH_X86_SSE2)\n#    include <emmintrin.h>\n#  elif defined(ZSTD_ARCH_ARM_NEON)\n#    include <arm_neon.h>\n#  endif\n#endif\n\n/* C-language Attributes are added in C23. */\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)\n# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)\n#else\n# define ZSTD_HAS_C_ATTRIBUTE(x) 0\n#endif\n\n/* Only use C++ attributes in C++. Some compilers report support for C++\n * attributes when compiling with C.\n */\n#if defined(__cplusplus) && defined(__has_cpp_attribute)\n# define ZSTD_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)\n#else\n# define ZSTD_HAS_CPP_ATTRIBUTE(x) 0\n#endif\n\n/* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute.\n * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough\n * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough\n * - Else: __attribute__((__fallthrough__))\n */\n#ifndef ZSTD_FALLTHROUGH\n# if ZSTD_HAS_C_ATTRIBUTE(fallthrough)\n#  define ZSTD_FALLTHROUGH [[fallthrough]]\n# elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough)\n#  define ZSTD_FALLTHROUGH [[fallthrough]]\n# elif __has_attribute(__fallthrough__)\n/* Leading semicolon is to satisfy gcc-11 with -pedantic. Without the semicolon\n * gcc complains about: a label can only be part of a statement and a declaration is not a statement.\n */\n#  define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__))\n# else\n#  define ZSTD_FALLTHROUGH\n# endif\n#endif\n\n/*-**************************************************************\n*  Alignment\n*****************************************************************/\n\n/* @return 1 if @u is a 2^n value, 0 otherwise\n * useful to check a value is valid for alignment restrictions */\nMEM_STATIC int ZSTD_isPower2(size_t u) {\n    return (u & (u-1)) == 0;\n}\n\n/* this test was initially positioned in mem.h,\n * but this file is removed (or replaced) for linux kernel\n * so it's now hosted in compiler.h,\n * which remains valid for both user & kernel spaces.\n */\n\n#ifndef ZSTD_ALIGNOF\n# if defined(__GNUC__) || defined(_MSC_VER)\n/* covers gcc, clang & MSVC */\n/* note : this section must come first, before C11,\n * due to a limitation in the kernel source generator */\n#  define ZSTD_ALIGNOF(T) __alignof(T)\n\n# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)\n/* C11 support */\n#  include <stdalign.h>\n#  define ZSTD_ALIGNOF(T) alignof(T)\n\n# else\n/* No known support for alignof() - imperfect backup */\n#  define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T))\n\n# endif\n#endif /* ZSTD_ALIGNOF */\n\n#ifndef ZSTD_ALIGNED\n/* C90-compatible alignment macro (GCC/Clang). Adjust for other compilers if needed. */\n# if defined(__GNUC__) || defined(__clang__)\n#  define ZSTD_ALIGNED(a) __attribute__((aligned(a)))\n# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */\n#  define ZSTD_ALIGNED(a) _Alignas(a)\n#elif defined(_MSC_VER)\n#  define ZSTD_ALIGNED(n) __declspec(align(n))\n# else\n   /* this compiler will require its own alignment instruction */\n#  define ZSTD_ALIGNED(...)\n# endif\n#endif /* ZSTD_ALIGNED */\n\n\n/*-**************************************************************\n*  Sanitizer\n*****************************************************************/\n\n/**\n * Zstd relies on pointer overflow in its decompressor.\n * We add this attribute to functions that rely on pointer overflow.\n */\n#ifndef ZSTD_ALLOW_POINTER_OVERFLOW_ATTR\n#  if __has_attribute(no_sanitize)\n#    if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 8\n       /* gcc < 8 only has signed-integer-overlow which triggers on pointer overflow */\n#      define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize(\"signed-integer-overflow\")))\n#    else\n       /* older versions of clang [3.7, 5.0) will warn that pointer-overflow is ignored. */\n#      define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR __attribute__((no_sanitize(\"pointer-overflow\")))\n#    endif\n#  else\n#    define ZSTD_ALLOW_POINTER_OVERFLOW_ATTR\n#  endif\n#endif\n\n/**\n * Helper function to perform a wrapped pointer difference without triggering\n * UBSAN.\n *\n * @returns lhs - rhs with wrapping\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nptrdiff_t ZSTD_wrappedPtrDiff(unsigned char const* lhs, unsigned char const* rhs)\n{\n    return lhs - rhs;\n}\n\n/**\n * Helper function to perform a wrapped pointer add without triggering UBSAN.\n *\n * @return ptr + add with wrapping\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nunsigned char const* ZSTD_wrappedPtrAdd(unsigned char const* ptr, ptrdiff_t add)\n{\n    return ptr + add;\n}\n\n/**\n * Helper function to perform a wrapped pointer subtraction without triggering\n * UBSAN.\n *\n * @return ptr - sub with wrapping\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nunsigned char const* ZSTD_wrappedPtrSub(unsigned char const* ptr, ptrdiff_t sub)\n{\n    return ptr - sub;\n}\n\n/**\n * Helper function to add to a pointer that works around C's undefined behavior\n * of adding 0 to NULL.\n *\n * @returns `ptr + add` except it defines `NULL + 0 == NULL`.\n */\nMEM_STATIC\nunsigned char* ZSTD_maybeNullPtrAdd(unsigned char* ptr, ptrdiff_t add)\n{\n    return add > 0 ? ptr + add : ptr;\n}\n\n/* Issue #3240 reports an ASAN failure on an llvm-mingw build. Out of an\n * abundance of caution, disable our custom poisoning on mingw. */\n#ifdef __MINGW32__\n#ifndef ZSTD_ASAN_DONT_POISON_WORKSPACE\n#define ZSTD_ASAN_DONT_POISON_WORKSPACE 1\n#endif\n#ifndef ZSTD_MSAN_DONT_POISON_WORKSPACE\n#define ZSTD_MSAN_DONT_POISON_WORKSPACE 1\n#endif\n#endif\n\n#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE)\n/* Not all platforms that support msan provide sanitizers/msan_interface.h.\n * We therefore declare the functions we need ourselves, rather than trying to\n * include the header file... */\n#include <stddef.h>  /* size_t */\n#define ZSTD_DEPS_NEED_STDINT\n#include \"zstd_deps.h\"  /* intptr_t */\n\n/* Make memory region fully initialized (without changing its contents). */\nvoid __msan_unpoison(const volatile void *a, size_t size);\n\n/* Make memory region fully uninitialized (without changing its contents).\n   This is a legacy interface that does not update origin information. Use\n   __msan_allocated_memory() instead. */\nvoid __msan_poison(const volatile void *a, size_t size);\n\n/* Returns the offset of the first (at least partially) poisoned byte in the\n   memory range, or -1 if the whole range is good. */\nintptr_t __msan_test_shadow(const volatile void *x, size_t size);\n\n/* Print shadow and origin for the memory range to stderr in a human-readable\n   format. */\nvoid __msan_print_shadow(const volatile void *x, size_t size);\n#endif\n\n#if ZSTD_ADDRESS_SANITIZER && !defined(ZSTD_ASAN_DONT_POISON_WORKSPACE)\n/* Not all platforms that support asan provide sanitizers/asan_interface.h.\n * We therefore declare the functions we need ourselves, rather than trying to\n * include the header file... */\n#include <stddef.h>  /* size_t */\n\n/**\n * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable.\n *\n * This memory must be previously allocated by your program. Instrumented\n * code is forbidden from accessing addresses in this region until it is\n * unpoisoned. This function is not guaranteed to poison the entire region -\n * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan\n * alignment restrictions.\n *\n * \\note This function is not thread-safe because no two threads can poison or\n * unpoison memory in the same memory region simultaneously.\n *\n * \\param addr Start of memory region.\n * \\param size Size of memory region. */\nvoid __asan_poison_memory_region(void const volatile *addr, size_t size);\n\n/**\n * Marks a memory region (<c>[addr, addr+size)</c>) as addressable.\n *\n * This memory must be previously allocated by your program. Accessing\n * addresses in this region is allowed until this region is poisoned again.\n * This function could unpoison a super-region of <c>[addr, addr+size)</c> due\n * to ASan alignment restrictions.\n *\n * \\note This function is not thread-safe because no two threads can\n * poison or unpoison memory in the same memory region simultaneously.\n *\n * \\param addr Start of memory region.\n * \\param size Size of memory region. */\nvoid __asan_unpoison_memory_region(void const volatile *addr, size_t size);\n#endif\n\n#endif /* ZSTD_COMPILER_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/cpu.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMMON_CPU_H\n#define ZSTD_COMMON_CPU_H\n\n/**\n * Implementation taken from folly/CpuId.h\n * https://github.com/facebook/folly/blob/master/folly/CpuId.h\n */\n\n#include \"mem.h\"\n\n#ifdef _MSC_VER\n#include <intrin.h>\n#endif\n\ntypedef struct {\n    U32 f1c;\n    U32 f1d;\n    U32 f7b;\n    U32 f7c;\n} ZSTD_cpuid_t;\n\nMEM_STATIC ZSTD_cpuid_t ZSTD_cpuid(void) {\n    U32 f1c = 0;\n    U32 f1d = 0;\n    U32 f7b = 0;\n    U32 f7c = 0;\n#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))\n#if !defined(_M_X64) || !defined(__clang__) || __clang_major__ >= 16\n    int reg[4];\n    __cpuid((int*)reg, 0);\n    {\n        int const n = reg[0];\n        if (n >= 1) {\n            __cpuid((int*)reg, 1);\n            f1c = (U32)reg[2];\n            f1d = (U32)reg[3];\n        }\n        if (n >= 7) {\n            __cpuidex((int*)reg, 7, 0);\n            f7b = (U32)reg[1];\n            f7c = (U32)reg[2];\n        }\n    }\n#else\n    /* Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in\n     * which the `__cpuid` intrinsic does not save and restore `rbx` as it needs\n     * to due to being a reserved register. So in that case, do the `cpuid`\n     * ourselves. Clang supports inline assembly anyway.\n     */\n    U32 n;\n    __asm__(\n        \"pushq %%rbx\\n\\t\"\n        \"cpuid\\n\\t\"\n        \"popq %%rbx\\n\\t\"\n        : \"=a\"(n)\n        : \"a\"(0)\n        : \"rcx\", \"rdx\");\n    if (n >= 1) {\n      U32 f1a;\n      __asm__(\n          \"pushq %%rbx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"popq %%rbx\\n\\t\"\n          : \"=a\"(f1a), \"=c\"(f1c), \"=d\"(f1d)\n          : \"a\"(1)\n          :);\n    }\n    if (n >= 7) {\n      __asm__(\n          \"pushq %%rbx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"movq %%rbx, %%rax\\n\\t\"\n          \"popq %%rbx\"\n          : \"=a\"(f7b), \"=c\"(f7c)\n          : \"a\"(7), \"c\"(0)\n          : \"rdx\");\n    }\n#endif\n#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && defined(__GNUC__)\n    /* The following block like the normal cpuid branch below, but gcc\n     * reserves ebx for use of its pic register so we must specially\n     * handle the save and restore to avoid clobbering the register\n     */\n    U32 n;\n    __asm__(\n        \"pushl %%ebx\\n\\t\"\n        \"cpuid\\n\\t\"\n        \"popl %%ebx\\n\\t\"\n        : \"=a\"(n)\n        : \"a\"(0)\n        : \"ecx\", \"edx\");\n    if (n >= 1) {\n      U32 f1a;\n      __asm__(\n          \"pushl %%ebx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"popl %%ebx\\n\\t\"\n          : \"=a\"(f1a), \"=c\"(f1c), \"=d\"(f1d)\n          : \"a\"(1));\n    }\n    if (n >= 7) {\n      __asm__(\n          \"pushl %%ebx\\n\\t\"\n          \"cpuid\\n\\t\"\n          \"movl %%ebx, %%eax\\n\\t\"\n          \"popl %%ebx\"\n          : \"=a\"(f7b), \"=c\"(f7c)\n          : \"a\"(7), \"c\"(0)\n          : \"edx\");\n    }\n#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386__)\n    U32 n;\n    __asm__(\"cpuid\" : \"=a\"(n) : \"a\"(0) : \"ebx\", \"ecx\", \"edx\");\n    if (n >= 1) {\n      U32 f1a;\n      __asm__(\"cpuid\" : \"=a\"(f1a), \"=c\"(f1c), \"=d\"(f1d) : \"a\"(1) : \"ebx\");\n    }\n    if (n >= 7) {\n      U32 f7a;\n      __asm__(\"cpuid\"\n              : \"=a\"(f7a), \"=b\"(f7b), \"=c\"(f7c)\n              : \"a\"(7), \"c\"(0)\n              : \"edx\");\n    }\n#endif\n    {\n        ZSTD_cpuid_t cpuid;\n        cpuid.f1c = f1c;\n        cpuid.f1d = f1d;\n        cpuid.f7b = f7b;\n        cpuid.f7c = f7c;\n        return cpuid;\n    }\n}\n\n#define X(name, r, bit)                                                        \\\n  MEM_STATIC int ZSTD_cpuid_##name(ZSTD_cpuid_t const cpuid) {                 \\\n    return ((cpuid.r) & (1U << bit)) != 0;                                     \\\n  }\n\n/* cpuid(1): Processor Info and Feature Bits. */\n#define C(name, bit) X(name, f1c, bit)\n  C(sse3, 0)\n  C(pclmuldq, 1)\n  C(dtes64, 2)\n  C(monitor, 3)\n  C(dscpl, 4)\n  C(vmx, 5)\n  C(smx, 6)\n  C(eist, 7)\n  C(tm2, 8)\n  C(ssse3, 9)\n  C(cnxtid, 10)\n  C(fma, 12)\n  C(cx16, 13)\n  C(xtpr, 14)\n  C(pdcm, 15)\n  C(pcid, 17)\n  C(dca, 18)\n  C(sse41, 19)\n  C(sse42, 20)\n  C(x2apic, 21)\n  C(movbe, 22)\n  C(popcnt, 23)\n  C(tscdeadline, 24)\n  C(aes, 25)\n  C(xsave, 26)\n  C(osxsave, 27)\n  C(avx, 28)\n  C(f16c, 29)\n  C(rdrand, 30)\n#undef C\n#define D(name, bit) X(name, f1d, bit)\n  D(fpu, 0)\n  D(vme, 1)\n  D(de, 2)\n  D(pse, 3)\n  D(tsc, 4)\n  D(msr, 5)\n  D(pae, 6)\n  D(mce, 7)\n  D(cx8, 8)\n  D(apic, 9)\n  D(sep, 11)\n  D(mtrr, 12)\n  D(pge, 13)\n  D(mca, 14)\n  D(cmov, 15)\n  D(pat, 16)\n  D(pse36, 17)\n  D(psn, 18)\n  D(clfsh, 19)\n  D(ds, 21)\n  D(acpi, 22)\n  D(mmx, 23)\n  D(fxsr, 24)\n  D(sse, 25)\n  D(sse2, 26)\n  D(ss, 27)\n  D(htt, 28)\n  D(tm, 29)\n  D(pbe, 31)\n#undef D\n\n/* cpuid(7): Extended Features. */\n#define B(name, bit) X(name, f7b, bit)\n  B(bmi1, 3)\n  B(hle, 4)\n  B(avx2, 5)\n  B(smep, 7)\n  B(bmi2, 8)\n  B(erms, 9)\n  B(invpcid, 10)\n  B(rtm, 11)\n  B(mpx, 14)\n  B(avx512f, 16)\n  B(avx512dq, 17)\n  B(rdseed, 18)\n  B(adx, 19)\n  B(smap, 20)\n  B(avx512ifma, 21)\n  B(pcommit, 22)\n  B(clflushopt, 23)\n  B(clwb, 24)\n  B(avx512pf, 26)\n  B(avx512er, 27)\n  B(avx512cd, 28)\n  B(sha, 29)\n  B(avx512bw, 30)\n  B(avx512vl, 31)\n#undef B\n#define C(name, bit) X(name, f7c, bit)\n  C(prefetchwt1, 0)\n  C(avx512vbmi, 1)\n#undef C\n\n#undef X\n\n#endif /* ZSTD_COMMON_CPU_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/debug.c",
    "content": "﻿/* ******************************************************************\n * debug\n * Part of FSE library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n\n/*\n * This module only hosts one global variable\n * which can be used to dynamically influence the verbosity of traces,\n * such as DEBUGLOG and RAWLOG\n */\n\n#include \"debug.h\"\n\n#if !defined(ZSTD_LINUX_KERNEL) || (DEBUGLEVEL>=2)\n/* We only use this when DEBUGLEVEL>=2, but we get -Werror=pedantic errors if a\n * translation unit is empty. So remove this from Linux kernel builds, but\n * otherwise just leave it in.\n */\nint g_debuglevel = DEBUGLEVEL;\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/debug.h",
    "content": "﻿/* ******************************************************************\n * debug\n * Part of FSE library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n\n/*\n * The purpose of this header is to enable debug functions.\n * They regroup assert(), DEBUGLOG() and RAWLOG() for run-time,\n * and DEBUG_STATIC_ASSERT() for compile-time.\n *\n * By default, DEBUGLEVEL==0, which means run-time debug is disabled.\n *\n * Level 1 enables assert() only.\n * Starting level 2, traces can be generated and pushed to stderr.\n * The higher the level, the more verbose the traces.\n *\n * It's possible to dynamically adjust level using variable g_debug_level,\n * which is only declared if DEBUGLEVEL>=2,\n * and is a global variable, not multi-thread protected (use with care)\n */\n\n#ifndef DEBUG_H_12987983217\n#define DEBUG_H_12987983217\n\n\n/* static assert is triggered at compile time, leaving no runtime artefact.\n * static assert only works with compile-time constants.\n * Also, this variant can only be used inside a function. */\n#define DEBUG_STATIC_ASSERT(c) (void)sizeof(char[(c) ? 1 : -1])\n\n\n/* DEBUGLEVEL is expected to be defined externally,\n * typically through compiler command line.\n * Value must be a number. */\n#ifndef DEBUGLEVEL\n#  define DEBUGLEVEL 0\n#endif\n\n\n/* recommended values for DEBUGLEVEL :\n * 0 : release mode, no debug, all run-time checks disabled\n * 1 : enables assert() only, no display\n * 2 : reserved, for currently active debug path\n * 3 : events once per object lifetime (CCtx, CDict, etc.)\n * 4 : events once per frame\n * 5 : events once per block\n * 6 : events once per sequence (verbose)\n * 7+: events at every position (*very* verbose)\n *\n * It's generally inconvenient to output traces > 5.\n * In which case, it's possible to selectively trigger high verbosity levels\n * by modifying g_debug_level.\n */\n\n#if (DEBUGLEVEL>=1)\n#  define ZSTD_DEPS_NEED_ASSERT\n#  include \"zstd_deps.h\"\n#else\n#  ifndef assert   /* assert may be already defined, due to prior #include <assert.h> */\n#    define assert(condition) ((void)0)   /* disable assert (default) */\n#  endif\n#endif\n\n#if (DEBUGLEVEL>=2)\n#  define ZSTD_DEPS_NEED_IO\n#  include \"zstd_deps.h\"\nextern int g_debuglevel; /* the variable is only declared,\n                            it actually lives in debug.c,\n                            and is shared by the whole process.\n                            It's not thread-safe.\n                            It's useful when enabling very verbose levels\n                            on selective conditions (such as position in src) */\n\n#  define RAWLOG(l, ...)                   \\\n    do {                                   \\\n        if (l<=g_debuglevel) {             \\\n            ZSTD_DEBUG_PRINT(__VA_ARGS__); \\\n        }                                  \\\n    } while (0)\n\n#define STRINGIFY(x) #x\n#define TOSTRING(x) STRINGIFY(x)\n#define LINE_AS_STRING TOSTRING(__LINE__)\n\n#  define DEBUGLOG(l, ...)                               \\\n    do {                                                 \\\n        if (l<=g_debuglevel) {                           \\\n            ZSTD_DEBUG_PRINT(__FILE__ \":\" LINE_AS_STRING \": \" __VA_ARGS__); \\\n            ZSTD_DEBUG_PRINT(\" \\n\");                     \\\n        }                                                \\\n    } while (0)\n#else\n#  define RAWLOG(l, ...)   do { } while (0)    /* disabled */\n#  define DEBUGLOG(l, ...) do { } while (0)    /* disabled */\n#endif\n\n#endif /* DEBUG_H_12987983217 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/entropy_common.c",
    "content": "﻿/* ******************************************************************\n * Common functions of New Generation Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* *************************************\n*  Dependencies\n***************************************/\n#include \"mem.h\"\n#include \"error_private.h\"       /* ERR_*, ERROR */\n#define FSE_STATIC_LINKING_ONLY  /* FSE_MIN_TABLELOG */\n#include \"fse.h\"\n#include \"huf.h\"\n#include \"bits.h\"                /* ZSDT_highbit32, ZSTD_countTrailingZeros32 */\n\n\n/*===   Version   ===*/\nunsigned FSE_versionNumber(void) { return FSE_VERSION_NUMBER; }\n\n\n/*===   Error Management   ===*/\nunsigned FSE_isError(size_t code) { return ERR_isError(code); }\nconst char* FSE_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\nunsigned HUF_isError(size_t code) { return ERR_isError(code); }\nconst char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/*-**************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nFORCE_INLINE_TEMPLATE\nsize_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                           const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    unsigned const maxSV1 = *maxSVPtr + 1;\n    int previous0 = 0;\n\n    if (hbSize < 8) {\n        /* This function only works when hbSize >= 8 */\n        char buffer[8] = {0};\n        ZSTD_memcpy(buffer, headerBuffer, hbSize);\n        {   size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr,\n                                                    buffer, sizeof(buffer));\n            if (FSE_isError(countSize)) return countSize;\n            if (countSize > hbSize) return ERROR(corruption_detected);\n            return countSize;\n    }   }\n    assert(hbSize >= 8);\n\n    /* init */\n    ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0]));   /* all symbols not present in NCount have a frequency of 0 */\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    for (;;) {\n        if (previous0) {\n            /* Count the number of repeats. Each time the\n             * 2-bit repeat code is 0b11 there is another\n             * repeat.\n             * Avoid UB by setting the high bit to 1.\n             */\n            int repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;\n            while (repeats >= 12) {\n                charnum += 3 * 12;\n                if (LIKELY(ip <= iend-7)) {\n                    ip += 3;\n                } else {\n                    bitCount -= (int)(8 * (iend - 7 - ip));\n                    bitCount &= 31;\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> bitCount;\n                repeats = ZSTD_countTrailingZeros32(~bitStream | 0x80000000) >> 1;\n            }\n            charnum += 3 * repeats;\n            bitStream >>= 2 * repeats;\n            bitCount += 2 * repeats;\n\n            /* Add the final repeat which isn't 0b11. */\n            assert((bitStream & 3) < 3);\n            charnum += bitStream & 3;\n            bitCount += 2;\n\n            /* This is an error, but break and return an error\n             * at the end, because returning out of a loop makes\n             * it harder for the compiler to optimize.\n             */\n            if (charnum >= maxSV1) break;\n\n            /* We don't need to set the normalized count to 0\n             * because we already memset the whole buffer to 0.\n             */\n\n            if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                assert((bitCount >> 3) <= 3); /* For first condition to work */\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                bitCount &= 31;\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> bitCount;\n        }\n        {\n            int const max = (2*threshold-1) - remaining;\n            int count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = bitStream & (threshold-1);\n                bitCount += nbBits-1;\n            } else {\n                count = bitStream & (2*threshold-1);\n                if (count >= threshold) count -= max;\n                bitCount += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            /* When it matters (small blocks), this is a\n             * predictable branch, because we don't use -1.\n             */\n            if (count >= 0) {\n                remaining -= count;\n            } else {\n                assert(count == -1);\n                remaining += count;\n            }\n            normalizedCounter[charnum++] = (short)count;\n            previous0 = !count;\n\n            assert(threshold > 1);\n            if (remaining < threshold) {\n                /* This branch can be folded into the\n                 * threshold update condition because we\n                 * know that threshold > 1.\n                 */\n                if (remaining <= 1) break;\n                nbBits = ZSTD_highbit32(remaining) + 1;\n                threshold = 1 << (nbBits - 1);\n            }\n            if (charnum >= maxSV1) break;\n\n            if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                bitCount &= 31;\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> bitCount;\n    }   }\n    if (remaining != 1) return ERROR(corruption_detected);\n    /* Only possible when there are too many zeros. */\n    if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall);\n    if (bitCount > 32) return ERROR(corruption_detected);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    return ip-istart;\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic size_t FSE_readNCount_body_default(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize)\n{\n    return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n}\n\n#if DYNAMIC_BMI2\nBMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize)\n{\n    return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n}\n#endif\n\nsize_t FSE_readNCount_bmi2(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize, int bmi2)\n{\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n    }\n#endif\n    (void)bmi2;\n    return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize);\n}\n\nsize_t FSE_readNCount(\n        short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n        const void* headerBuffer, size_t hbSize)\n{\n    return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0);\n}\n\n\n/*! HUF_readStats() :\n    Read compact Huffman tree, saved by HUF_writeCTable().\n    `huffWeight` is destination buffer.\n    `rankStats` is assumed to be a table of at least HUF_TABLELOG_MAX U32.\n    @return : size read from `src` , or an error Code .\n    Note : Needed by HUF_readCTable() and HUF_readDTableX?() .\n*/\nsize_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize)\n{\n    U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];\n    return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* flags */ 0);\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                   U32* nbSymbolsPtr, U32* tableLogPtr,\n                   const void* src, size_t srcSize,\n                   void* workSpace, size_t wkspSize,\n                   int bmi2)\n{\n    U32 weightTotal;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* ZSTD_memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128) {  /* special header */\n        oSize = iSize - 127;\n        iSize = ((oSize+1)/2);\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        if (oSize >= hwSize) return ERROR(corruption_detected);\n        ip += 1;\n        {   U32 n;\n            for (n=0; n<oSize; n+=2) {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }\n    else  {   /* header compressed with FSE (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        /* max (hwSize-1) values decoded, as last one is implied */\n        oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2);\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));\n    weightTotal = 0;\n    {   U32 n; for (n=0; n<oSize; n++) {\n            if (huffWeight[n] > HUF_TABLELOG_MAX) return ERROR(corruption_detected);\n            rankStats[huffWeight[n]]++;\n            weightTotal += (1 << huffWeight[n]) >> 1;\n    }   }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    {   U32 const tableLog = ZSTD_highbit32(weightTotal) + 1;\n        if (tableLog > HUF_TABLELOG_MAX) return ERROR(corruption_detected);\n        *tableLogPtr = tableLog;\n        /* determine last weight */\n        {   U32 const total = 1 << tableLog;\n            U32 const rest = total - weightTotal;\n            U32 const verif = 1 << ZSTD_highbit32(rest);\n            U32 const lastWeight = ZSTD_highbit32(rest) + 1;\n            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n            huffWeight[oSize] = (BYTE)lastWeight;\n            rankStats[lastWeight]++;\n    }   }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    return iSize+1;\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize,\n                     void* workSpace, size_t wkspSize)\n{\n    return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0);\n}\n\n#if DYNAMIC_BMI2\nstatic BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize,\n                     void* workSpace, size_t wkspSize)\n{\n    return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1);\n}\n#endif\n\nsize_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize,\n                     void* workSpace, size_t wkspSize,\n                     int flags)\n{\n#if DYNAMIC_BMI2\n    if (flags & HUF_flags_bmi2) {\n        return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);\n    }\n#endif\n    (void)flags;\n    return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/error_private.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* The purpose of this file is to have a single list of error strings embedded in binary */\n\n#include \"error_private.h\"\n\nconst char* ERR_getErrorString(ERR_enum code)\n{\n#ifdef ZSTD_STRIP_ERROR_STRINGS\n    (void)code;\n    return \"Error strings stripped\";\n#else\n    static const char* const notErrorCode = \"Unspecified error code\";\n    switch( code )\n    {\n    case PREFIX(no_error): return \"No error detected\";\n    case PREFIX(GENERIC):  return \"Error (generic)\";\n    case PREFIX(prefix_unknown): return \"Unknown frame descriptor\";\n    case PREFIX(version_unsupported): return \"Version not supported\";\n    case PREFIX(frameParameter_unsupported): return \"Unsupported frame parameter\";\n    case PREFIX(frameParameter_windowTooLarge): return \"Frame requires too much memory for decoding\";\n    case PREFIX(corruption_detected): return \"Data corruption detected\";\n    case PREFIX(checksum_wrong): return \"Restored data doesn't match checksum\";\n    case PREFIX(literals_headerWrong): return \"Header of Literals' block doesn't respect format specification\";\n    case PREFIX(parameter_unsupported): return \"Unsupported parameter\";\n    case PREFIX(parameter_combination_unsupported): return \"Unsupported combination of parameters\";\n    case PREFIX(parameter_outOfBound): return \"Parameter is out of bound\";\n    case PREFIX(init_missing): return \"Context should be init first\";\n    case PREFIX(memory_allocation): return \"Allocation error : not enough memory\";\n    case PREFIX(workSpace_tooSmall): return \"workSpace buffer is not large enough\";\n    case PREFIX(stage_wrong): return \"Operation not authorized at current processing stage\";\n    case PREFIX(tableLog_tooLarge): return \"tableLog requires too much memory : unsupported\";\n    case PREFIX(maxSymbolValue_tooLarge): return \"Unsupported max Symbol Value : too large\";\n    case PREFIX(maxSymbolValue_tooSmall): return \"Specified maxSymbolValue is too small\";\n    case PREFIX(cannotProduce_uncompressedBlock): return \"This mode cannot generate an uncompressed block\";\n    case PREFIX(stabilityCondition_notRespected): return \"pledged buffer stability condition is not respected\";\n    case PREFIX(dictionary_corrupted): return \"Dictionary is corrupted\";\n    case PREFIX(dictionary_wrong): return \"Dictionary mismatch\";\n    case PREFIX(dictionaryCreation_failed): return \"Cannot create Dictionary from provided samples\";\n    case PREFIX(dstSize_tooSmall): return \"Destination buffer is too small\";\n    case PREFIX(srcSize_wrong): return \"Src size is incorrect\";\n    case PREFIX(dstBuffer_null): return \"Operation on NULL destination buffer\";\n    case PREFIX(noForwardProgress_destFull): return \"Operation made no progress over multiple calls, due to output buffer being full\";\n    case PREFIX(noForwardProgress_inputEmpty): return \"Operation made no progress over multiple calls, due to input being empty\";\n        /* following error codes are not stable and may be removed or changed in a future version */\n    case PREFIX(frameIndex_tooLarge): return \"Frame index is too large\";\n    case PREFIX(seekableIO): return \"An I/O error occurred when reading/seeking\";\n    case PREFIX(dstBuffer_wrong): return \"Destination buffer is wrong\";\n    case PREFIX(srcBuffer_wrong): return \"Source buffer is wrong\";\n    case PREFIX(sequenceProducer_failed): return \"Block-level external sequence producer returned an error code\";\n    case PREFIX(externalSequences_invalid): return \"External sequences are not valid\";\n    case PREFIX(maxCode):\n    default: return notErrorCode;\n    }\n#endif\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/error_private.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* Note : this module is expected to remain private, do not expose it */\n\n#ifndef ERROR_H_MODULE\n#define ERROR_H_MODULE\n\n/* ****************************************\n*  Dependencies\n******************************************/\n#include \"../zstd_errors.h\"  /* enum list */\n#include \"compiler.h\"\n#include \"debug.h\"\n#include \"zstd_deps.h\"       /* size_t */\n\n/* ****************************************\n*  Compiler-specific\n******************************************/\n#if defined(__GNUC__)\n#  define ERR_STATIC static __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define ERR_STATIC static inline\n#elif defined(_MSC_VER)\n#  define ERR_STATIC static __inline\n#else\n#  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/*-****************************************\n*  Customization (error_public.h)\n******************************************/\ntypedef ZSTD_ErrorCode ERR_enum;\n#define PREFIX(name) ZSTD_error_##name\n\n\n/*-****************************************\n*  Error codes handling\n******************************************/\n#undef ERROR   /* already defined on Visual Studio */\n#define ERROR(name) ZSTD_ERROR(name)\n#define ZSTD_ERROR(name) ((size_t)-PREFIX(name))\n\nERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }\n\nERR_STATIC ERR_enum ERR_getErrorCode(size_t code) { if (!ERR_isError(code)) return (ERR_enum)0; return (ERR_enum) (0-code); }\n\n/* check and forward error code */\n#define CHECK_V_F(e, f)     \\\n    size_t const e = f;     \\\n    do {                    \\\n        if (ERR_isError(e)) \\\n            return e;       \\\n    } while (0)\n#define CHECK_F(f)   do { CHECK_V_F(_var_err__, f); } while (0)\n\n\n/*-****************************************\n*  Error Strings\n******************************************/\n\nconst char* ERR_getErrorString(ERR_enum code);   /* error_private.c */\n\nERR_STATIC const char* ERR_getErrorName(size_t code)\n{\n    return ERR_getErrorString(ERR_getErrorCode(code));\n}\n\n/**\n * Ignore: this is an internal helper.\n *\n * This is a helper function to help force C99-correctness during compilation.\n * Under strict compilation modes, variadic macro arguments can't be empty.\n * However, variadic function arguments can be. Using a function therefore lets\n * us statically check that at least one (string) argument was passed,\n * independent of the compilation flags.\n */\nstatic INLINE_KEYWORD UNUSED_ATTR\nvoid _force_has_format_string(const char *format, ...) {\n  (void)format;\n}\n\n/**\n * Ignore: this is an internal helper.\n *\n * We want to force this function invocation to be syntactically correct, but\n * we don't want to force runtime evaluation of its arguments.\n */\n#define _FORCE_HAS_FORMAT_STRING(...)              \\\n    do {                                           \\\n        if (0) {                                   \\\n            _force_has_format_string(__VA_ARGS__); \\\n        }                                          \\\n    } while (0)\n\n#define ERR_QUOTE(str) #str\n\n/**\n * Return the specified error if the condition evaluates to true.\n *\n * In debug modes, prints additional information.\n * In order to do that (particularly, printing the conditional that failed),\n * this can't just wrap RETURN_ERROR().\n */\n#define RETURN_ERROR_IF(cond, err, ...)                                        \\\n    do {                                                                       \\\n        if (cond) {                                                            \\\n            RAWLOG(3, \"%s:%d: ERROR!: check %s failed, returning %s\",          \\\n                  __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \\\n            _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                             \\\n            RAWLOG(3, \": \" __VA_ARGS__);                                       \\\n            RAWLOG(3, \"\\n\");                                                   \\\n            return ERROR(err);                                                 \\\n        }                                                                      \\\n    } while (0)\n\n/**\n * Unconditionally return the specified error.\n *\n * In debug modes, prints additional information.\n */\n#define RETURN_ERROR(err, ...)                                               \\\n    do {                                                                     \\\n        RAWLOG(3, \"%s:%d: ERROR!: unconditional check failed, returning %s\", \\\n              __FILE__, __LINE__, ERR_QUOTE(ERROR(err)));                    \\\n        _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                               \\\n        RAWLOG(3, \": \" __VA_ARGS__);                                         \\\n        RAWLOG(3, \"\\n\");                                                     \\\n        return ERROR(err);                                                   \\\n    } while(0)\n\n/**\n * If the provided expression evaluates to an error code, returns that error code.\n *\n * In debug modes, prints additional information.\n */\n#define FORWARD_IF_ERROR(err, ...)                                                 \\\n    do {                                                                           \\\n        size_t const err_code = (err);                                             \\\n        if (ERR_isError(err_code)) {                                               \\\n            RAWLOG(3, \"%s:%d: ERROR!: forwarding error in %s: %s\",                 \\\n                  __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \\\n            _FORCE_HAS_FORMAT_STRING(__VA_ARGS__);                                 \\\n            RAWLOG(3, \": \" __VA_ARGS__);                                           \\\n            RAWLOG(3, \"\\n\");                                                       \\\n            return err_code;                                                       \\\n        }                                                                          \\\n    } while(0)\n\n#endif /* ERROR_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/fse.h",
    "content": "﻿/* ******************************************************************\n * FSE : Finite State Entropy codec\n * Public Prototypes declaration\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n#ifndef FSE_H\n#define FSE_H\n\n\n/*-*****************************************\n*  Dependencies\n******************************************/\n#include \"zstd_deps.h\"    /* size_t, ptrdiff_t */\n\n/*-*****************************************\n*  FSE_PUBLIC_API : control library symbols visibility\n******************************************/\n#if defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1) && defined(__GNUC__) && (__GNUC__ >= 4)\n#  define FSE_PUBLIC_API __attribute__ ((visibility (\"default\")))\n#elif defined(FSE_DLL_EXPORT) && (FSE_DLL_EXPORT==1)   /* Visual expected */\n#  define FSE_PUBLIC_API __declspec(dllexport)\n#elif defined(FSE_DLL_IMPORT) && (FSE_DLL_IMPORT==1)\n#  define FSE_PUBLIC_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define FSE_PUBLIC_API\n#endif\n\n/*------   Version   ------*/\n#define FSE_VERSION_MAJOR    0\n#define FSE_VERSION_MINOR    9\n#define FSE_VERSION_RELEASE  0\n\n#define FSE_LIB_VERSION FSE_VERSION_MAJOR.FSE_VERSION_MINOR.FSE_VERSION_RELEASE\n#define FSE_QUOTE(str) #str\n#define FSE_EXPAND_AND_QUOTE(str) FSE_QUOTE(str)\n#define FSE_VERSION_STRING FSE_EXPAND_AND_QUOTE(FSE_LIB_VERSION)\n\n#define FSE_VERSION_NUMBER  (FSE_VERSION_MAJOR *100*100 + FSE_VERSION_MINOR *100 + FSE_VERSION_RELEASE)\nFSE_PUBLIC_API unsigned FSE_versionNumber(void);   /**< library version number; to be used when checking dll version */\n\n\n/*-*****************************************\n*  Tool functions\n******************************************/\nFSE_PUBLIC_API size_t FSE_compressBound(size_t size);       /* maximum compressed size */\n\n/* Error Management */\nFSE_PUBLIC_API unsigned    FSE_isError(size_t code);        /* tells if a return value is an error code */\nFSE_PUBLIC_API const char* FSE_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n/*-*****************************************\n*  FSE detailed API\n******************************************/\n/*!\nFSE_compress() does the following:\n1. count symbol occurrence from source[] into table count[] (see hist.h)\n2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)\n3. save normalized counters to memory buffer using writeNCount()\n4. build encoding table 'CTable' from normalized counters\n5. encode the data stream using encoding table 'CTable'\n\nFSE_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n/* *** COMPRESSION *** */\n\n/*! FSE_optimalTableLog():\n    dynamically downsize 'tableLog' when conditions are met.\n    It saves CPU time, by using smaller tables, while preserving or even improving compression ratio.\n    @return : recommended tableLog (necessarily <= 'maxTableLog') */\nFSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue);\n\n/*! FSE_normalizeCount():\n    normalize counts so that sum(count[]) == Power_of_2 (2^tableLog)\n    'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1).\n    useLowProbCount is a boolean parameter which trades off compressed size for\n    faster header decoding. When it is set to 1, the compressed data will be slightly\n    smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be\n    faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0\n    is a good default, since header deserialization makes a big speed difference.\n    Otherwise, useLowProbCount=1 is a good default, since the speed difference is small.\n    @return : tableLog,\n              or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog,\n                    const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount);\n\n/*! FSE_NCountWriteBound():\n    Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'.\n    Typically useful for allocation purpose. */\nFSE_PUBLIC_API size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSE_writeNCount():\n    Compactly save 'normalizedCounter' into 'buffer'.\n    @return : size of the compressed table,\n              or an errorCode, which can be tested using FSE_isError(). */\nFSE_PUBLIC_API size_t FSE_writeNCount (void* buffer, size_t bufferSize,\n                                 const short* normalizedCounter,\n                                 unsigned maxSymbolValue, unsigned tableLog);\n\n/*! Constructor and Destructor of FSE_CTable.\n    Note that FSE_CTable size depends on 'tableLog' and 'maxSymbolValue' */\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's only meant to be more restrictive than void* */\n\n/*! FSE_buildCTable():\n    Builds `ct`, which must be already allocated, using FSE_createCTable().\n    @return : 0, or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSE_compress_usingCTable():\n    Compress `src` using `ct` into `dst` which must be already allocated.\n    @return : size of compressed data (<= `dstCapacity`),\n              or 0 if compressed data could not fit into `dst`,\n              or an errorCode, which can be tested using FSE_isError() */\nFSE_PUBLIC_API size_t FSE_compress_usingCTable (void* dst, size_t dstCapacity, const void* src, size_t srcSize, const FSE_CTable* ct);\n\n/*!\nTutorial :\n----------\nThe first step is to count all symbols. FSE_count() does this job very fast.\nResult will be saved into 'count', a table of unsigned int, which must be already allocated, and have 'maxSymbolValuePtr[0]+1' cells.\n'src' is a table of bytes of size 'srcSize'. All values within 'src' MUST be <= maxSymbolValuePtr[0]\nmaxSymbolValuePtr[0] will be updated, with its real value (necessarily <= original value)\nFSE_count() will return the number of occurrence of the most frequent symbol.\nThis can be used to know if there is a single symbol within 'src', and to quickly evaluate its compressibility.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).\n\nThe next step is to normalize the frequencies.\nFSE_normalizeCount() will ensure that sum of frequencies is == 2 ^'tableLog'.\nIt also guarantees a minimum of 1 to any Symbol with frequency >= 1.\nYou can use 'tableLog'==0 to mean \"use default tableLog value\".\nIf you are unsure of which tableLog value to use, you can ask FSE_optimalTableLog(),\nwhich will provide the optimal valid tableLog given sourceSize, maxSymbolValue, and a user-defined maximum (0 means \"default\").\n\nThe result of FSE_normalizeCount() will be saved into a table,\ncalled 'normalizedCounter', which is a table of signed short.\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValue+1' cells.\nThe return value is tableLog if everything proceeded as expected.\nIt is 0 if there is a single symbol within distribution.\nIf there is an error (ex: invalid tableLog value), the function will return an ErrorCode (which can be tested using FSE_isError()).\n\n'normalizedCounter' can be saved in a compact manner to a memory area using FSE_writeNCount().\n'buffer' must be already allocated.\nFor guaranteed success, buffer size must be at least FSE_headerBound().\nThe result of the function is the number of bytes written into 'buffer'.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError(); ex : buffer size too small).\n\n'normalizedCounter' can then be used to create the compression table 'CTable'.\nThe space required by 'CTable' must be already allocated, using FSE_createCTable().\nYou can then use FSE_buildCTable() to fill 'CTable'.\nIf there is an error, both functions will return an ErrorCode (which can be tested using FSE_isError()).\n\n'CTable' can then be used to compress 'src', with FSE_compress_usingCTable().\nSimilar to FSE_count(), the convention is that 'src' is assumed to be a table of char of size 'srcSize'\nThe function returns the size of compressed data (without header), necessarily <= `dstCapacity`.\nIf it returns '0', compressed data could not fit into 'dst'.\nIf there is an error, the function will return an ErrorCode (which can be tested using FSE_isError()).\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*! FSE_readNCount():\n    Read compactly saved 'normalizedCounter' from 'rBuffer'.\n    @return : size read from 'rBuffer',\n              or an errorCode, which can be tested using FSE_isError().\n              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nFSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter,\n                           unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,\n                           const void* rBuffer, size_t rBuffSize);\n\n/*! FSE_readNCount_bmi2():\n * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise.\n */\nFSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter,\n                           unsigned* maxSymbolValuePtr, unsigned* tableLogPtr,\n                           const void* rBuffer, size_t rBuffSize, int bmi2);\n\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSE_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\nThe next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.\nThis is performed by the function FSE_buildDTable().\nThe space required by 'FSE_DTable' must be already allocated using FSE_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\n`FSE_DTable` can then be used to decompress `cSrc`, with FSE_decompress_usingDTable().\n`cSrcSize` must be strictly correct, otherwise decompression will fail.\nFSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).\nIf there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)\n*/\n\n#endif  /* FSE_H */\n\n\n#if defined(FSE_STATIC_LINKING_ONLY) && !defined(FSE_H_FSE_STATIC_LINKING_ONLY)\n#define FSE_H_FSE_STATIC_LINKING_ONLY\n#include \"bitstream.h\"\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */)\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<(maxTableLog)))\n\n/* or use the size to malloc() space directly. Pay attention to alignment restrictions though */\n#define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue)   (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable))\n#define FSE_DTABLE_SIZE(maxTableLog)                   (FSE_DTABLE_SIZE_U32(maxTableLog) * sizeof(FSE_DTable))\n\n\n/* *****************************************\n *  FSE advanced API\n ***************************************** */\n\nunsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);\n/**< same as FSE_optimalTableLog(), which used `minus==2` */\n\nsize_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);\n/**< build a fake FSE_CTable, designed to compress always the same symbolValue */\n\n/* FSE_buildCTable_wksp() :\n * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).\n * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.\n * See FSE_buildCTable_wksp() for breakdown of workspace usage.\n */\n#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */)\n#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))\nsize_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);\n\n#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8)\n#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned))\nFSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);\n/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */\n\n#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + 1 + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) + (FSE_MAX_SYMBOL_VALUE + 1) / 2 + 1)\n#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned))\nsize_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2);\n/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)`.\n * Set bmi2 to 1 if your CPU supports BMI2 or 0 if it doesn't */\n\ntypedef enum {\n   FSE_repeat_none,  /**< Cannot use the previous table */\n   FSE_repeat_check, /**< Can use the previous table but it must be checked */\n   FSE_repeat_valid  /**< Can use the previous table and it is assumed to be valid */\n } FSE_repeat;\n\n/* *****************************************\n*  FSE symbol compression API\n*******************************************/\n/*!\n   This API consists of small unitary functions, which highly benefit from being inlined.\n   Hence their body are included in next section.\n*/\ntypedef struct {\n    ptrdiff_t   value;\n    const void* stateTable;\n    const void* symbolTT;\n    unsigned    stateLog;\n} FSE_CState_t;\n\nstatic void FSE_initCState(FSE_CState_t* CStatePtr, const FSE_CTable* ct);\n\nstatic void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* CStatePtr, unsigned symbol);\n\nstatic void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* CStatePtr);\n\n/**<\nThese functions are inner components of FSE_compress_usingCTable().\nThey allow the creation of custom streams, mixing multiple tables and bit sources.\n\nA key property to keep in mind is that encoding and decoding are done **in reverse direction**.\nSo the first symbol you will encode is the last you will decode, like a LIFO stack.\n\nYou will need a few variables to track your CStream. They are :\n\nFSE_CTable    ct;         // Provided by FSE_buildCTable()\nBIT_CStream_t bitStream;  // bitStream tracking structure\nFSE_CState_t  state;      // State tracking structure (can have several)\n\n\nThe first thing to do is to init bitStream and state.\n    size_t errorCode = BIT_initCStream(&bitStream, dstBuffer, maxDstSize);\n    FSE_initCState(&state, ct);\n\nNote that BIT_initCStream() can produce an error code, so its result should be tested, using FSE_isError();\nYou can then encode your input data, byte after byte.\nFSE_encodeSymbol() outputs a maximum of 'tableLog' bits at a time.\nRemember decoding will be done in reverse direction.\n    FSE_encodeByte(&bitStream, &state, symbol);\n\nAt any time, you can also add any bit sequence.\nNote : maximum allowed nbBits is 25, for compatibility with 32-bits decoders\n    BIT_addBits(&bitStream, bitField, nbBits);\n\nThe above methods don't commit data to memory, they just store it into local register, for speed.\nLocal register size is 64-bits on 64-bits systems, 32-bits on 32-bits systems (size_t).\nWriting data to memory is a manual operation, performed by the flushBits function.\n    BIT_flushBits(&bitStream);\n\nYour last FSE encoding operation shall be to flush your last state value(s).\n    FSE_flushState(&bitStream, &state);\n\nFinally, you must close the bitStream.\nThe function returns the size of CStream in bytes.\nIf data couldn't fit into dstBuffer, it will return a 0 ( == not compressible)\nIf there is an error, it returns an errorCode (which can be tested using FSE_isError()).\n    size_t size = BIT_closeCStream(&bitStream);\n*/\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct {\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n/**<\nLet's now decompose FSE_decompress_usingDTable() into its unitary components.\nYou will decode FSE-encoded symbols from the bitStream,\nand also any other bitFields you put in, **in reverse order**.\n\nYou will need a few variables to track your bitStream. They are :\n\nBIT_DStream_t DStream;    // Stream context\nFSE_DState_t  DState;     // State context. Multiple ones are possible\nFSE_DTable*   DTablePtr;  // Decoding table, provided by FSE_buildDTable()\n\nThe first thing to do is to init the bitStream.\n    errorCode = BIT_initDStream(&DStream, srcBuffer, srcSize);\n\nYou should then retrieve your initial state(s)\n(in reverse flushing order if you have several ones) :\n    errorCode = FSE_initDState(&DState, &DStream, DTablePtr);\n\nYou can then decode your data, symbol after symbol.\nFor information the maximum number of bits read by FSE_decodeSymbol() is 'tableLog'.\nKeep in mind that symbols are decoded in reverse order, like a LIFO stack (last in, first out).\n    unsigned char symbol = FSE_decodeSymbol(&DState, &DStream);\n\nYou can retrieve any bitfield you eventually stored into the bitStream (in reverse order)\nNote : maximum allowed nbBits is 25, for 32-bits compatibility\n    size_t bitField = BIT_readBits(&DStream, nbBits);\n\nAll above operations only read from local register (which size depends on size_t).\nRefueling the register from memory is manually performed by the reload method.\n    endSignal = FSE_reloadDStream(&DStream);\n\nBIT_reloadDStream() result tells if there is still some more data to read from DStream.\nBIT_DStream_unfinished : there is still some data left into the DStream.\nBIT_DStream_endOfBuffer : Dstream reached end of buffer. Its container may no longer be completely filled.\nBIT_DStream_completed : Dstream reached its exact end, corresponding in general to decompression completed.\nBIT_DStream_tooFar : Dstream went too far. Decompression result is corrupted.\n\nWhen reaching end of buffer (BIT_DStream_endOfBuffer), progress slowly, notably if you decode multiple symbols per loop,\nto properly detect the exact end of stream.\nAfter each decoded symbol, check if DStream is fully consumed using this simple test :\n    BIT_reloadDStream(&DStream) >= BIT_DStream_completed\n\nWhen it's done, verify decompression is fully completed, by checking both DStream and the relevant states.\nChecking if DStream has reached its end is performed by :\n    BIT_endOfDStream(&DStream);\nCheck also the states. There might be some symbols left there, if some high probability ones (>50%) are possible.\n    FSE_endOfDState(&DState);\n*/\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\ntypedef struct {\n    int deltaFindState;\n    U32 deltaNbBits;\n} FSE_symbolCompressionTransform; /* total 8 bytes */\n\nMEM_STATIC void FSE_initCState(FSE_CState_t* statePtr, const FSE_CTable* ct)\n{\n    const void* ptr = ct;\n    const U16* u16ptr = (const U16*) ptr;\n    const U32 tableLog = MEM_read16(ptr);\n    statePtr->value = (ptrdiff_t)1<<tableLog;\n    statePtr->stateTable = u16ptr+2;\n    statePtr->symbolTT = ct + 1 + (tableLog ? (1<<(tableLog-1)) : 1);\n    statePtr->stateLog = tableLog;\n}\n\n\n/*! FSE_initCState2() :\n*   Same as FSE_initCState(), but the first symbol to include (which will be the last to be read)\n*   uses the smallest state value possible, saving the cost of this symbol */\nMEM_STATIC void FSE_initCState2(FSE_CState_t* statePtr, const FSE_CTable* ct, U32 symbol)\n{\n    FSE_initCState(statePtr, ct);\n    {   const FSE_symbolCompressionTransform symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];\n        const U16* stateTable = (const U16*)(statePtr->stateTable);\n        U32 nbBitsOut  = (U32)((symbolTT.deltaNbBits + (1<<15)) >> 16);\n        statePtr->value = (nbBitsOut << 16) - symbolTT.deltaNbBits;\n        statePtr->value = stateTable[(statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];\n    }\n}\n\nMEM_STATIC void FSE_encodeSymbol(BIT_CStream_t* bitC, FSE_CState_t* statePtr, unsigned symbol)\n{\n    FSE_symbolCompressionTransform const symbolTT = ((const FSE_symbolCompressionTransform*)(statePtr->symbolTT))[symbol];\n    const U16* const stateTable = (const U16*)(statePtr->stateTable);\n    U32 const nbBitsOut  = (U32)((statePtr->value + symbolTT.deltaNbBits) >> 16);\n    BIT_addBits(bitC, (BitContainerType)statePtr->value, nbBitsOut);\n    statePtr->value = stateTable[ (statePtr->value >> nbBitsOut) + symbolTT.deltaFindState];\n}\n\nMEM_STATIC void FSE_flushCState(BIT_CStream_t* bitC, const FSE_CState_t* statePtr)\n{\n    BIT_addBits(bitC, (BitContainerType)statePtr->value, statePtr->stateLog);\n    BIT_flushBits(bitC);\n}\n\n\n/* FSE_getMaxNbBits() :\n * Approximate maximum cost of a symbol, in bits.\n * Fractional get rounded up (i.e. a symbol with a normalized frequency of 3 gives the same result as a frequency of 2)\n * note 1 : assume symbolValue is valid (<= maxSymbolValue)\n * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */\nMEM_STATIC U32 FSE_getMaxNbBits(const void* symbolTTPtr, U32 symbolValue)\n{\n    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;\n    return (symbolTT[symbolValue].deltaNbBits + ((1<<16)-1)) >> 16;\n}\n\n/* FSE_bitCost() :\n * Approximate symbol cost, as fractional value, using fixed-point format (accuracyLog fractional bits)\n * note 1 : assume symbolValue is valid (<= maxSymbolValue)\n * note 2 : if freq[symbolValue]==0, @return a fake cost of tableLog+1 bits */\nMEM_STATIC U32 FSE_bitCost(const void* symbolTTPtr, U32 tableLog, U32 symbolValue, U32 accuracyLog)\n{\n    const FSE_symbolCompressionTransform* symbolTT = (const FSE_symbolCompressionTransform*) symbolTTPtr;\n    U32 const minNbBits = symbolTT[symbolValue].deltaNbBits >> 16;\n    U32 const threshold = (minNbBits+1) << 16;\n    assert(tableLog < 16);\n    assert(accuracyLog < 31-tableLog);  /* ensure enough room for renormalization double shift */\n    {   U32 const tableSize = 1 << tableLog;\n        U32 const deltaFromThreshold = threshold - (symbolTT[symbolValue].deltaNbBits + tableSize);\n        U32 const normalizedDeltaFromThreshold = (deltaFromThreshold << accuracyLog) >> tableLog;   /* linear interpolation (very approximate) */\n        U32 const bitMultiplier = 1 << accuracyLog;\n        assert(symbolTT[symbolValue].deltaNbBits + tableSize <= threshold);\n        assert(normalizedDeltaFromThreshold <= bitMultiplier);\n        return (minNbBits+1)*bitMultiplier - normalizedDeltaFromThreshold;\n    }\n}\n\n\n/* ======    Decompression    ====== */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;\n    DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_peekSymbol(const FSE_DState_t* DStatePtr)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC void FSE_updateState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n    DStatePtr->state = DInfo.newState + lowBits;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/*! FSE_decodeSymbolFast() :\n    unsafe, only works if no symbol has a probability > 50% */\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    FSE_decode_t const DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#ifndef FSE_MAX_MEMORY_USAGE\n#  define FSE_MAX_MEMORY_USAGE 14\n#endif\n#ifndef FSE_DEFAULT_MEMORY_USAGE\n#  define FSE_DEFAULT_MEMORY_USAGE 13\n#endif\n#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE)\n#  error \"FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE\"\n#endif\n\n/*!FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#ifndef FSE_MAX_SYMBOL_VALUE\n#  define FSE_MAX_SYMBOL_VALUE 255\n#endif\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n#define FSE_DECODE_TYPE FSE_decode_t\n\n\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#  error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3)\n\n#endif /* FSE_STATIC_LINKING_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/fse_decompress.c",
    "content": "﻿/* ******************************************************************\n * FSE : Finite State Entropy decoder\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include \"debug.h\"      /* assert */\n#include \"bitstream.h\"\n#include \"compiler.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n#include \"error_private.h\"\n#include \"zstd_deps.h\"  /* ZSTD_memcpy */\n#include \"bits.h\"       /* ZSTD_highbit32 */\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_isError ERR_isError\n#define FSE_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\nstatic size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)\n{\n    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);\n    U16* symbolNext = (U16*)workSpace;\n    BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1);\n\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n    U32 highThreshold = tableSize-1;\n\n    /* Sanity Checks */\n    if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge);\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    {   FSE_DTableHeader DTableH;\n        DTableH.tableLog = (U16)tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    symbolNext[s] = (U16)normalizedCounter[s];\n        }   }   }\n        ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    if (highThreshold == tableSize - 1) {\n        size_t const tableMask = tableSize-1;\n        size_t const step = FSE_TABLESTEP(tableSize);\n        /* First lay down the symbols in order.\n         * We use a uint64_t to lay down 8 bytes at a time. This reduces branch\n         * misses since small blocks generally have small table logs, so nearly\n         * all symbols have counts <= 8. We ensure we have 8 bytes at the end of\n         * our buffer to handle the over-write.\n         */\n        {   U64 const add = 0x0101010101010101ull;\n            size_t pos = 0;\n            U64 sv = 0;\n            U32 s;\n            for (s=0; s<maxSV1; ++s, sv += add) {\n                int i;\n                int const n = normalizedCounter[s];\n                MEM_write64(spread + pos, sv);\n                for (i = 8; i < n; i += 8) {\n                    MEM_write64(spread + pos + i, sv);\n                }\n                pos += (size_t)n;\n        }   }\n        /* Now we spread those positions across the table.\n         * The benefit of doing it in two stages is that we avoid the\n         * variable size inner loop, which caused lots of branch misses.\n         * Now we can run through all the positions without any branch misses.\n         * We unroll the loop twice, since that is what empirically worked best.\n         */\n        {\n            size_t position = 0;\n            size_t s;\n            size_t const unroll = 2;\n            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */\n            for (s = 0; s < (size_t)tableSize; s += unroll) {\n                size_t u;\n                for (u = 0; u < unroll; ++u) {\n                    size_t const uPosition = (position + (u * step)) & tableMask;\n                    tableDecode[uPosition].symbol = spread[s + u];\n                }\n                position = (position + (unroll * step)) & tableMask;\n            }\n            assert(position == 0);\n        }\n    } else {\n        U32 const tableMask = tableSize-1;\n        U32 const step = FSE_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            for (i=0; i<normalizedCounter[s]; i++) {\n                tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n                position = (position + step) & tableMask;\n                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {   U32 u;\n        for (u=0; u<tableSize; u++) {\n            FSE_FUNCTION_TYPE const symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);\n            U32 const nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - ZSTD_highbit32(nextState) );\n            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n    }   }\n\n    return 0;\n}\n\nsize_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize)\n{\n    return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize);\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\n\nFORCE_INLINE_TEMPLATE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n\n    /* Init */\n    CHECK_F(BIT_initDStream(&bitD, cSrc, cSrcSize));\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n    RETURN_ERROR_IF(BIT_reloadDStream(&bitD)==BIT_DStream_overflow, corruption_detected, \"\");\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) & (op<olimit) ; op+=4) {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1) {\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n        *op++ = FSE_GETSYMBOL(&state1);\n        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {\n            *op++ = FSE_GETSYMBOL(&state2);\n            break;\n        }\n\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n        *op++ = FSE_GETSYMBOL(&state2);\n        if (BIT_reloadDStream(&bitD)==BIT_DStream_overflow) {\n            *op++ = FSE_GETSYMBOL(&state1);\n            break;\n    }   }\n\n    assert(op >= ostart);\n    return (size_t)(op-ostart);\n}\n\ntypedef struct {\n    short ncount[FSE_MAX_SYMBOL_VALUE + 1];\n} FSE_DecompressWksp;\n\n\nFORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body(\n        void* dst, size_t dstCapacity,\n        const void* cSrc, size_t cSrcSize,\n        unsigned maxLog, void* workSpace, size_t wkspSize,\n        int bmi2)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    FSE_DecompressWksp* const wksp = (FSE_DecompressWksp*)workSpace;\n    size_t const dtablePos = sizeof(FSE_DecompressWksp) / sizeof(FSE_DTable);\n    FSE_DTable* const dtable = (FSE_DTable*)workSpace + dtablePos;\n\n    FSE_STATIC_ASSERT((FSE_MAX_SYMBOL_VALUE + 1) % 2 == 0);\n    if (wkspSize < sizeof(*wksp)) return ERROR(GENERIC);\n\n    /* correct offset to dtable depends on this property */\n    FSE_STATIC_ASSERT(sizeof(FSE_DecompressWksp) % sizeof(FSE_DTable) == 0);\n\n    /* normal FSE decoding mode */\n    {   size_t const NCountLength =\n            FSE_readNCount_bmi2(wksp->ncount, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2);\n        if (FSE_isError(NCountLength)) return NCountLength;\n        if (tableLog > maxLog) return ERROR(tableLog_tooLarge);\n        assert(NCountLength <= cSrcSize);\n        ip += NCountLength;\n        cSrcSize -= NCountLength;\n    }\n\n    if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge);\n    assert(sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog) <= wkspSize);\n    workSpace = (BYTE*)workSpace + sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);\n    wkspSize -= sizeof(*wksp) + FSE_DTABLE_SIZE(tableLog);\n\n    CHECK_F( FSE_buildDTable_internal(dtable, wksp->ncount, maxSymbolValue, tableLog, workSpace, wkspSize) );\n\n    {\n        const void* ptr = dtable;\n        const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr;\n        const U32 fastMode = DTableH->fastMode;\n\n        /* select fast mode (static) */\n        if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 1);\n        return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 0);\n    }\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)\n{\n    return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0);\n}\n\n#if DYNAMIC_BMI2\nBMI2_TARGET_ATTRIBUTE static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)\n{\n    return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);\n}\n#endif\n\nsize_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2)\n{\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);\n    }\n#endif\n    (void)bmi2;\n    return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize);\n}\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/huf.h",
    "content": "﻿/* ******************************************************************\n * huff0 huffman codec,\n * part of Finite State Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * You can contact the author at :\n * - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n#ifndef HUF_H_298734234\n#define HUF_H_298734234\n\n/* *** Dependencies *** */\n#include \"zstd_deps.h\"    /* size_t */\n#include \"mem.h\"          /* U32 */\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n\n/* ***   Tool functions *** */\n#define HUF_BLOCKSIZE_MAX (128 * 1024)   /**< maximum input size for a single block compressed with HUF_compress */\nsize_t HUF_compressBound(size_t size);   /**< maximum compressed size (worst case) */\n\n/* Error Management */\nunsigned    HUF_isError(size_t code);       /**< tells if a return value is an error code */\nconst char* HUF_getErrorName(size_t code);  /**< provides error code string (useful for debugging) */\n\n\n#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */)\n#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64))\n\n/* *** Constants *** */\n#define HUF_TABLELOG_MAX      12      /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_TABLELOG_ABSOLUTEMAX */\n#define HUF_TABLELOG_DEFAULT  11      /* default tableLog value when none specified */\n#define HUF_SYMBOLVALUE_MAX  255\n\n#define HUF_TABLELOG_ABSOLUTEMAX  12  /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)\n#  error \"HUF_TABLELOG_MAX is too large !\"\n#endif\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* HUF buffer bounds */\n#define HUF_CTABLEBOUND 129\n#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true when incompressible is pre-filtered with fast heuristic */\n#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of HUF's Compression Table */\n/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */\ntypedef size_t HUF_CElt;   /* consider it an incomplete type */\n#define HUF_CTABLE_SIZE_ST(maxSymbolValue)   ((maxSymbolValue)+2)   /* Use tables of size_t, for proper alignment */\n#define HUF_CTABLE_SIZE(maxSymbolValue)       (HUF_CTABLE_SIZE_ST(maxSymbolValue) * sizeof(size_t))\n#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \\\n    HUF_CElt name[HUF_CTABLE_SIZE_ST(maxSymbolValue)] /* no final ; */\n\n/* static allocation of HUF's DTable */\ntypedef U32 HUF_DTable;\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<(maxTableLog)))\n#define HUF_CREATE_STATIC_DTABLEX1(DTable, maxTableLog) \\\n        HUF_DTable DTable[HUF_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1) * 0x01000001) }\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        HUF_DTable DTable[HUF_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog) * 0x01000001) }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\n\n/**\n * Huffman flags bitset.\n * For all flags, 0 is the default value.\n */\ntypedef enum {\n    /**\n     * If compiled with DYNAMIC_BMI2: Set flag only if the CPU supports BMI2 at runtime.\n     * Otherwise: Ignored.\n     */\n    HUF_flags_bmi2 = (1 << 0),\n    /**\n     * If set: Test possible table depths to find the one that produces the smallest header + encoded size.\n     * If unset: Use heuristic to find the table depth.\n     */\n    HUF_flags_optimalDepth = (1 << 1),\n    /**\n     * If set: If the previous table can encode the input, always reuse the previous table.\n     * If unset: If the previous table can encode the input, reuse the previous table if it results in a smaller output.\n     */\n    HUF_flags_preferRepeat = (1 << 2),\n    /**\n     * If set: Sample the input and check if the sample is uncompressible, if it is then don't attempt to compress.\n     * If unset: Always histogram the entire input.\n     */\n    HUF_flags_suspectUncompressible = (1 << 3),\n    /**\n     * If set: Don't use assembly implementations\n     * If unset: Allow using assembly implementations\n     */\n    HUF_flags_disableAsm = (1 << 4),\n    /**\n     * If set: Don't use the fast decoding loop, always use the fallback decoding loop.\n     * If unset: Use the fast decoding loop when possible.\n     */\n    HUF_flags_disableFast = (1 << 5)\n} HUF_flags_e;\n\n\n/* ****************************************\n *  HUF detailed API\n * ****************************************/\n#define HUF_OPTIMAL_DEPTH_THRESHOLD ZSTD_btultra\n\n/*! HUF_compress() does the following:\n *  1. count symbol occurrence from source[] into table count[] using FSE_count() (exposed within \"fse.h\")\n *  2. (optional) refine tableLog using HUF_optimalTableLog()\n *  3. build Huffman table from count using HUF_buildCTable()\n *  4. save Huffman table to memory buffer using HUF_writeCTable()\n *  5. encode the data stream using HUF_compress4X_usingCTable()\n *\n *  The following API allows targeting specific sub-functions for advanced tasks.\n *  For example, it's possible to compress several blocks using the same 'CTable',\n *  or to save and regenerate 'CTable' using external methods.\n */\nunsigned HUF_minTableLog(unsigned symbolCardinality);\nunsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue);\nunsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, void* workSpace,\n size_t wkspSize, HUF_CElt* table, const unsigned* count, int flags); /* table is used as scratch space for building and testing tables, not a return value */\nsize_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);\nsize_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags);\nsize_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);\nint HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);\n\ntypedef enum {\n   HUF_repeat_none,  /**< Cannot use the previous table */\n   HUF_repeat_check, /**< Can use the previous table but it must be checked. Note : The previous table must have been constructed by HUF_compress{1, 4}X_repeat */\n   HUF_repeat_valid  /**< Can use the previous table and it is assumed to be valid */\n } HUF_repeat;\n\n/** HUF_compress4X_repeat() :\n *  Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.\n *  If it uses hufTable it does not modify hufTable or repeat.\n *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.\n *  If preferRepeat then the old table will always be used if valid.\n *  If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */\nsize_t HUF_compress4X_repeat(void* dst, size_t dstSize,\n                       const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned tableLog,\n                       void* workSpace, size_t wkspSize,    /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */\n                       HUF_CElt* hufTable, HUF_repeat* repeat, int flags);\n\n/** HUF_buildCTable_wksp() :\n *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.\n * `workSpace` must be aligned on 4-bytes boundaries, and its size must be >= HUF_CTABLE_WORKSPACE_SIZE.\n */\n#define HUF_CTABLE_WORKSPACE_SIZE_U32 ((4 * (HUF_SYMBOLVALUE_MAX + 1)) + 192)\n#define HUF_CTABLE_WORKSPACE_SIZE (HUF_CTABLE_WORKSPACE_SIZE_U32 * sizeof(unsigned))\nsize_t HUF_buildCTable_wksp (HUF_CElt* tree,\n                       const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,\n                             void* workSpace, size_t wkspSize);\n\n/*! HUF_readStats() :\n *  Read compact Huffman tree, saved by HUF_writeCTable().\n * `huffWeight` is destination buffer.\n * @return : size read from `src` , or an error Code .\n *  Note : Needed by HUF_readCTable() and HUF_readDTableXn() . */\nsize_t HUF_readStats(BYTE* huffWeight, size_t hwSize,\n                     U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize);\n\n/*! HUF_readStats_wksp() :\n * Same as HUF_readStats() but takes an external workspace which must be\n * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE.\n * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.\n */\n#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1)\n#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned))\nsize_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,\n                          U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr,\n                          const void* src, size_t srcSize,\n                          void* workspace, size_t wkspSize,\n                          int flags);\n\n/** HUF_readCTable() :\n *  Loading a CTable saved with HUF_writeCTable() */\nsize_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);\n\n/** HUF_getNbBitsFromCTable() :\n *  Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX\n *  Note 1 : If symbolValue > HUF_readCTableHeader(symbolTable).maxSymbolValue, returns 0\n *  Note 2 : is not inlined, as HUF_CElt definition is private\n */\nU32 HUF_getNbBitsFromCTable(const HUF_CElt* symbolTable, U32 symbolValue);\n\ntypedef struct {\n    BYTE tableLog;\n    BYTE maxSymbolValue;\n    BYTE unused[sizeof(size_t) - 2];\n} HUF_CTableHeader;\n\n/** HUF_readCTableHeader() :\n *  @returns The header from the CTable specifying the tableLog and the maxSymbolValue.\n */\nHUF_CTableHeader HUF_readCTableHeader(HUF_CElt const* ctable);\n\n/*\n * HUF_decompress() does the following:\n * 1. select the decompression algorithm (X1, X2) based on pre-computed heuristics\n * 2. build Huffman table from save, using HUF_readDTableX?()\n * 3. decode 1 or 4 segments in parallel using HUF_decompress?X?_usingDTable()\n */\n\n/** HUF_selectDecoder() :\n *  Tells which decoder is likely to decode faster,\n *  based on a set of pre-computed metrics.\n * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .\n *  Assumption : 0 < dstSize <= 128 KB */\nU32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize);\n\n/**\n *  The minimum workspace size for the `workSpace` used in\n *  HUF_readDTableX1_wksp() and HUF_readDTableX2_wksp().\n *\n *  The space used depends on HUF_TABLELOG_MAX, ranging from ~1500 bytes when\n *  HUF_TABLE_LOG_MAX=12 to ~1850 bytes when HUF_TABLE_LOG_MAX=15.\n *  Buffer overflow errors may potentially occur if code modifications result in\n *  a required workspace size greater than that specified in the following\n *  macro.\n */\n#define HUF_DECOMPRESS_WORKSPACE_SIZE ((2 << 10) + (1 << 9))\n#define HUF_DECOMPRESS_WORKSPACE_SIZE_U32 (HUF_DECOMPRESS_WORKSPACE_SIZE / sizeof(U32))\n\n\n/* ====================== */\n/* single stream variants */\n/* ====================== */\n\nsize_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags);\n/** HUF_compress1X_repeat() :\n *  Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.\n *  If it uses hufTable it does not modify hufTable or repeat.\n *  If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.\n *  If preferRepeat then the old table will always be used if valid.\n *  If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */\nsize_t HUF_compress1X_repeat(void* dst, size_t dstSize,\n                       const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned tableLog,\n                       void* workSpace, size_t wkspSize,   /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */\n                       HUF_CElt* hufTable, HUF_repeat* repeat, int flags);\n\nsize_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);   /**< double-symbols decoder */\n#endif\n\n/* BMI2 variants.\n * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0.\n */\nsize_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags);\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);\n#endif\nsize_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags);\nsize_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags);\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);\n#endif\n#ifndef HUF_FORCE_DECOMPRESS_X1\nsize_t HUF_readDTableX2_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags);\n#endif\n\n#endif   /* HUF_H_298734234 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/mem.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include <stddef.h>  /* size_t, ptrdiff_t */\n#include \"compiler.h\"  /* __has_builtin */\n#include \"debug.h\"  /* DEBUG_STATIC_ASSERT */\n#include \"zstd_deps.h\"  /* ZSTD_memcpy */\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#elif defined(__ICCARM__)\n#   include <intrinsics.h>\n#endif\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n#  if defined(_AIX)\n#    include <inttypes.h>\n#  else\n#    include <stdint.h> /* intptr_t */\n#  endif\n  typedef   uint8_t BYTE;\n  typedef   uint8_t U8;\n  typedef    int8_t S8;\n  typedef  uint16_t U16;\n  typedef   int16_t S16;\n  typedef  uint32_t U32;\n  typedef   int32_t S32;\n  typedef  uint64_t U64;\n  typedef   int64_t S64;\n#else\n# include <limits.h>\n#if CHAR_BIT != 8\n#  error \"this implementation requires char to be exactly 8-bit type\"\n#endif\n  typedef unsigned char      BYTE;\n  typedef unsigned char      U8;\n  typedef   signed char      S8;\n#if USHRT_MAX != 65535\n#  error \"this implementation requires short to be exactly 16-bit type\"\n#endif\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n#if UINT_MAX != 4294967295\n#  error \"this implementation requires int to be exactly 32-bit type\"\n#endif\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n/* note : there are no limits defined for long long type in C90.\n * limits exist in C99, however, in such case, <stdint.h> is preferred */\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n/*-**************************************************************\n*  Memory I/O API\n*****************************************************************/\n/*=== Static platform detection ===*/\nMEM_STATIC unsigned MEM_32bits(void);\nMEM_STATIC unsigned MEM_64bits(void);\nMEM_STATIC unsigned MEM_isLittleEndian(void);\n\n/*=== Native unaligned read/write ===*/\nMEM_STATIC U16 MEM_read16(const void* memPtr);\nMEM_STATIC U32 MEM_read32(const void* memPtr);\nMEM_STATIC U64 MEM_read64(const void* memPtr);\nMEM_STATIC size_t MEM_readST(const void* memPtr);\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value);\nMEM_STATIC void MEM_write32(void* memPtr, U32 value);\nMEM_STATIC void MEM_write64(void* memPtr, U64 value);\n\n/*=== Little endian unaligned read/write ===*/\nMEM_STATIC U16 MEM_readLE16(const void* memPtr);\nMEM_STATIC U32 MEM_readLE24(const void* memPtr);\nMEM_STATIC U32 MEM_readLE32(const void* memPtr);\nMEM_STATIC U64 MEM_readLE64(const void* memPtr);\nMEM_STATIC size_t MEM_readLEST(const void* memPtr);\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val);\nMEM_STATIC void MEM_writeLE24(void* memPtr, U32 val);\nMEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32);\nMEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64);\nMEM_STATIC void MEM_writeLEST(void* memPtr, size_t val);\n\n/*=== Big endian unaligned read/write ===*/\nMEM_STATIC U32 MEM_readBE32(const void* memPtr);\nMEM_STATIC U64 MEM_readBE64(const void* memPtr);\nMEM_STATIC size_t MEM_readBEST(const void* memPtr);\n\nMEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32);\nMEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64);\nMEM_STATIC void MEM_writeBEST(void* memPtr, size_t val);\n\n/*=== Byteswap ===*/\nMEM_STATIC U32 MEM_swap32(U32 in);\nMEM_STATIC U64 MEM_swap64(U64 in);\nMEM_STATIC size_t MEM_swapST(size_t in);\n\n\n/*-**************************************************************\n*  Memory I/O Implementation\n*****************************************************************/\n/* MEM_FORCE_MEMORY_ACCESS : For accessing unaligned memory:\n * Method 0 : always use `memcpy()`. Safe and portable.\n * Method 1 : Use compiler extension to set unaligned access.\n * Method 2 : direct access. This method is portable but violate C standard.\n *            It can generate buggy code on targets depending on alignment.\n * Default  : method 1 if supported, else method 0\n */\n#ifndef MEM_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */\n#  ifdef __GNUC__\n#    define MEM_FORCE_MEMORY_ACCESS 1\n#  endif\n#endif\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n    return 1;\n#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n    return 0;\n#elif defined(__clang__) && __LITTLE_ENDIAN__\n    return 1;\n#elif defined(__clang__) && __BIG_ENDIAN__\n    return 0;\n#elif defined(_MSC_VER) && (_M_X64 || _M_IX86)\n    return 1;\n#elif defined(__DMC__) && defined(_M_IX86)\n    return 1;\n#elif defined(__IAR_SYSTEMS_ICC__) && __LITTLE_ENDIAN__\n    return 1;\n#else\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n#endif\n}\n\n#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)\n\n/* violates C standard, by lying on structure alignment.\nOnly use if no other choice to achieve best performance on target platform */\nMEM_STATIC U16 MEM_read16(const void* memPtr) { return *(const U16*) memPtr; }\nMEM_STATIC U32 MEM_read32(const void* memPtr) { return *(const U32*) memPtr; }\nMEM_STATIC U64 MEM_read64(const void* memPtr) { return *(const U64*) memPtr; }\nMEM_STATIC size_t MEM_readST(const void* memPtr) { return *(const size_t*) memPtr; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(U64*)memPtr = value; }\n\n#elif defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==1)\n\ntypedef __attribute__((aligned(1))) U16 unalign16;\ntypedef __attribute__((aligned(1))) U32 unalign32;\ntypedef __attribute__((aligned(1))) U64 unalign64;\ntypedef __attribute__((aligned(1))) size_t unalignArch;\n\nMEM_STATIC U16 MEM_read16(const void* ptr) { return *(const unalign16*)ptr; }\nMEM_STATIC U32 MEM_read32(const void* ptr) { return *(const unalign32*)ptr; }\nMEM_STATIC U64 MEM_read64(const void* ptr) { return *(const unalign64*)ptr; }\nMEM_STATIC size_t MEM_readST(const void* ptr) { return *(const unalignArch*)ptr; }\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value) { *(unalign16*)memPtr = value; }\nMEM_STATIC void MEM_write32(void* memPtr, U32 value) { *(unalign32*)memPtr = value; }\nMEM_STATIC void MEM_write64(void* memPtr, U64 value) { *(unalign64*)memPtr = value; }\n\n#else\n\n/* default method, safe and standard.\n   can sometimes prove slower */\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC size_t MEM_readST(const void* memPtr)\n{\n    size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    ZSTD_memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write32(void* memPtr, U32 value)\n{\n    ZSTD_memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write64(void* memPtr, U64 value)\n{\n    ZSTD_memcpy(memPtr, &value, sizeof(value));\n}\n\n#endif /* MEM_FORCE_MEMORY_ACCESS */\n\nMEM_STATIC U32 MEM_swap32_fallback(U32 in)\n{\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n}\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \\\n  || (defined(__clang__) && __has_builtin(__builtin_bswap32))\n    return __builtin_bswap32(in);\n#elif defined(__ICCARM__)\n    return __REV(in);\n#else\n    return MEM_swap32_fallback(in);\n#endif\n}\n\nMEM_STATIC U64 MEM_swap64_fallback(U64 in)\n{\n     return  ((in << 56) & 0xff00000000000000ULL) |\n            ((in << 40) & 0x00ff000000000000ULL) |\n            ((in << 24) & 0x0000ff0000000000ULL) |\n            ((in << 8)  & 0x000000ff00000000ULL) |\n            ((in >> 8)  & 0x00000000ff000000ULL) |\n            ((in >> 24) & 0x0000000000ff0000ULL) |\n            ((in >> 40) & 0x000000000000ff00ULL) |\n            ((in >> 56) & 0x00000000000000ffULL);\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_uint64(in);\n#elif (defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) \\\n  || (defined(__clang__) && __has_builtin(__builtin_bswap64))\n    return __builtin_bswap64(in);\n#else\n    return MEM_swap64_fallback(in);\n#endif\n}\n\nMEM_STATIC size_t MEM_swapST(size_t in)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_swap32((U32)in);\n    else\n        return (size_t)MEM_swap64((U64)in);\n}\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return (U32)MEM_readLE16(memPtr) + ((U32)(((const BYTE*)memPtr)[2]) << 16);\n}\n\nMEM_STATIC void MEM_writeLE24(void* memPtr, U32 val)\n{\n    MEM_writeLE16(memPtr, (U16)val);\n    ((BYTE*)memPtr)[2] = (BYTE)(val>>16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n        return MEM_swap32(MEM_read32(memPtr));\n}\n\nMEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32)\n{\n    if (MEM_isLittleEndian())\n        MEM_write32(memPtr, val32);\n    else\n        MEM_write32(memPtr, MEM_swap32(val32));\n}\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n        return MEM_swap64(MEM_read64(memPtr));\n}\n\nMEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64)\n{\n    if (MEM_isLittleEndian())\n        MEM_write64(memPtr, val64);\n    else\n        MEM_write64(memPtr, MEM_swap64(val64));\n}\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeLEST(void* memPtr, size_t val)\n{\n    if (MEM_32bits())\n        MEM_writeLE32(memPtr, (U32)val);\n    else\n        MEM_writeLE64(memPtr, (U64)val);\n}\n\n/*=== Big endian r/w ===*/\n\nMEM_STATIC U32 MEM_readBE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_swap32(MEM_read32(memPtr));\n    else\n        return MEM_read32(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32)\n{\n    if (MEM_isLittleEndian())\n        MEM_write32(memPtr, MEM_swap32(val32));\n    else\n        MEM_write32(memPtr, val32);\n}\n\nMEM_STATIC U64 MEM_readBE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_swap64(MEM_read64(memPtr));\n    else\n        return MEM_read64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64)\n{\n    if (MEM_isLittleEndian())\n        MEM_write64(memPtr, MEM_swap64(val64));\n    else\n        MEM_write64(memPtr, val64);\n}\n\nMEM_STATIC size_t MEM_readBEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readBE32(memPtr);\n    else\n        return (size_t)MEM_readBE64(memPtr);\n}\n\nMEM_STATIC void MEM_writeBEST(void* memPtr, size_t val)\n{\n    if (MEM_32bits())\n        MEM_writeBE32(memPtr, (U32)val);\n    else\n        MEM_writeBE64(memPtr, (U64)val);\n}\n\n/* code only tested on 32 and 64 bits systems */\nMEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); }\n\n#endif /* MEM_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/pool.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ======   Dependencies   ======= */\n#include \"../common/allocations.h\"  /* ZSTD_customCalloc, ZSTD_customFree */\n#include \"zstd_deps.h\" /* size_t */\n#include \"debug.h\"     /* assert */\n#include \"pool.h\"\n\n/* ======   Compiler specifics   ====== */\n#if defined(_MSC_VER)\n#  pragma warning(disable : 4204)        /* disable: C4204: non-constant aggregate initializer */\n#endif\n\n\n#ifdef ZSTD_MULTITHREAD\n\n#include \"threading.h\"   /* pthread adaptation */\n\n/* A job is a function and an opaque argument */\ntypedef struct POOL_job_s {\n    POOL_function function;\n    void *opaque;\n} POOL_job;\n\nstruct POOL_ctx_s {\n    ZSTD_customMem customMem;\n    /* Keep track of the threads */\n    ZSTD_pthread_t* threads;\n    size_t threadCapacity;\n    size_t threadLimit;\n\n    /* The queue is a circular buffer */\n    POOL_job *queue;\n    size_t queueHead;\n    size_t queueTail;\n    size_t queueSize;\n\n    /* The number of threads working on jobs */\n    size_t numThreadsBusy;\n    /* Indicates if the queue is empty */\n    int queueEmpty;\n\n    /* The mutex protects the queue */\n    ZSTD_pthread_mutex_t queueMutex;\n    /* Condition variable for pushers to wait on when the queue is full */\n    ZSTD_pthread_cond_t queuePushCond;\n    /* Condition variables for poppers to wait on when the queue is empty */\n    ZSTD_pthread_cond_t queuePopCond;\n    /* Indicates if the queue is shutting down */\n    int shutdown;\n};\n\n/* POOL_thread() :\n * Work thread for the thread pool.\n * Waits for jobs and executes them.\n * @returns : NULL on failure else non-null.\n */\nstatic void* POOL_thread(void* opaque) {\n    POOL_ctx* const ctx = (POOL_ctx*)opaque;\n    if (!ctx) { return NULL; }\n    for (;;) {\n        /* Lock the mutex and wait for a non-empty queue or until shutdown */\n        ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n\n        while ( ctx->queueEmpty\n            || (ctx->numThreadsBusy >= ctx->threadLimit) ) {\n            if (ctx->shutdown) {\n                /* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit),\n                 * a few threads will be shutdown while !queueEmpty,\n                 * but enough threads will remain active to finish the queue */\n                ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n                return opaque;\n            }\n            ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex);\n        }\n        /* Pop a job off the queue */\n        {   POOL_job const job = ctx->queue[ctx->queueHead];\n            ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;\n            ctx->numThreadsBusy++;\n            ctx->queueEmpty = (ctx->queueHead == ctx->queueTail);\n            /* Unlock the mutex, signal a pusher, and run the job */\n            ZSTD_pthread_cond_signal(&ctx->queuePushCond);\n            ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n\n            job.function(job.opaque);\n\n            /* If the intended queue size was 0, signal after finishing job */\n            ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n            ctx->numThreadsBusy--;\n            ZSTD_pthread_cond_signal(&ctx->queuePushCond);\n            ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n        }\n    }  /* for (;;) */\n    assert(0);  /* Unreachable */\n}\n\n/* ZSTD_createThreadPool() : public access point */\nPOOL_ctx* ZSTD_createThreadPool(size_t numThreads) {\n    return POOL_create (numThreads, 0);\n}\n\nPOOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {\n    return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);\n}\n\nPOOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,\n                               ZSTD_customMem customMem)\n{\n    POOL_ctx* ctx;\n    /* Check parameters */\n    if (!numThreads) { return NULL; }\n    /* Allocate the context and zero initialize */\n    ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem);\n    if (!ctx) { return NULL; }\n    /* Initialize the job queue.\n     * It needs one extra space since one space is wasted to differentiate\n     * empty and full queues.\n     */\n    ctx->queueSize = queueSize + 1;\n    ctx->queue = (POOL_job*)ZSTD_customCalloc(ctx->queueSize * sizeof(POOL_job), customMem);\n    ctx->queueHead = 0;\n    ctx->queueTail = 0;\n    ctx->numThreadsBusy = 0;\n    ctx->queueEmpty = 1;\n    {\n        int error = 0;\n        error |= ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL);\n        error |= ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL);\n        error |= ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL);\n        if (error) { POOL_free(ctx); return NULL; }\n    }\n    ctx->shutdown = 0;\n    /* Allocate space for the thread handles */\n    ctx->threads = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), customMem);\n    ctx->threadCapacity = 0;\n    ctx->customMem = customMem;\n    /* Check for errors */\n    if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; }\n    /* Initialize the threads */\n    {   size_t i;\n        for (i = 0; i < numThreads; ++i) {\n            if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) {\n                ctx->threadCapacity = i;\n                POOL_free(ctx);\n                return NULL;\n        }   }\n        ctx->threadCapacity = numThreads;\n        ctx->threadLimit = numThreads;\n    }\n    return ctx;\n}\n\n/*! POOL_join() :\n    Shutdown the queue, wake any sleeping threads, and join all of the threads.\n*/\nstatic void POOL_join(POOL_ctx* ctx) {\n    /* Shut down the queue */\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    ctx->shutdown = 1;\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n    /* Wake up sleeping threads */\n    ZSTD_pthread_cond_broadcast(&ctx->queuePushCond);\n    ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);\n    /* Join all of the threads */\n    {   size_t i;\n        for (i = 0; i < ctx->threadCapacity; ++i) {\n            ZSTD_pthread_join(ctx->threads[i]);  /* note : could fail */\n    }   }\n}\n\nvoid POOL_free(POOL_ctx *ctx) {\n    if (!ctx) { return; }\n    POOL_join(ctx);\n    ZSTD_pthread_mutex_destroy(&ctx->queueMutex);\n    ZSTD_pthread_cond_destroy(&ctx->queuePushCond);\n    ZSTD_pthread_cond_destroy(&ctx->queuePopCond);\n    ZSTD_customFree(ctx->queue, ctx->customMem);\n    ZSTD_customFree(ctx->threads, ctx->customMem);\n    ZSTD_customFree(ctx, ctx->customMem);\n}\n\n/*! POOL_joinJobs() :\n *  Waits for all queued jobs to finish executing.\n */\nvoid POOL_joinJobs(POOL_ctx* ctx) {\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    while(!ctx->queueEmpty || ctx->numThreadsBusy > 0) {\n        ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);\n    }\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n}\n\nvoid ZSTD_freeThreadPool (ZSTD_threadPool* pool) {\n  POOL_free (pool);\n}\n\nsize_t POOL_sizeof(const POOL_ctx* ctx) {\n    if (ctx==NULL) return 0;  /* supports sizeof NULL */\n    return sizeof(*ctx)\n        + ctx->queueSize * sizeof(POOL_job)\n        + ctx->threadCapacity * sizeof(ZSTD_pthread_t);\n}\n\n\n/* @return : 0 on success, 1 on error */\nstatic int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads)\n{\n    if (numThreads <= ctx->threadCapacity) {\n        if (!numThreads) return 1;\n        ctx->threadLimit = numThreads;\n        return 0;\n    }\n    /* numThreads > threadCapacity */\n    {   ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customCalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem);\n        if (!threadPool) return 1;\n        /* replace existing thread pool */\n        ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(ZSTD_pthread_t));\n        ZSTD_customFree(ctx->threads, ctx->customMem);\n        ctx->threads = threadPool;\n        /* Initialize additional threads */\n        {   size_t threadId;\n            for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) {\n                if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) {\n                    ctx->threadCapacity = threadId;\n                    return 1;\n            }   }\n    }   }\n    /* successfully expanded */\n    ctx->threadCapacity = numThreads;\n    ctx->threadLimit = numThreads;\n    return 0;\n}\n\n/* @return : 0 on success, 1 on error */\nint POOL_resize(POOL_ctx* ctx, size_t numThreads)\n{\n    int result;\n    if (ctx==NULL) return 1;\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    result = POOL_resize_internal(ctx, numThreads);\n    ZSTD_pthread_cond_broadcast(&ctx->queuePopCond);\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n    return result;\n}\n\n/**\n * Returns 1 if the queue is full and 0 otherwise.\n *\n * When queueSize is 1 (pool was created with an intended queueSize of 0),\n * then a queue is empty if there is a thread free _and_ no job is waiting.\n */\nstatic int isQueueFull(POOL_ctx const* ctx) {\n    if (ctx->queueSize > 1) {\n        return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize);\n    } else {\n        return (ctx->numThreadsBusy == ctx->threadLimit) ||\n               !ctx->queueEmpty;\n    }\n}\n\n\nstatic void\nPOOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)\n{\n    POOL_job job;\n    job.function = function;\n    job.opaque = opaque;\n    assert(ctx != NULL);\n    if (ctx->shutdown) return;\n\n    ctx->queueEmpty = 0;\n    ctx->queue[ctx->queueTail] = job;\n    ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize;\n    ZSTD_pthread_cond_signal(&ctx->queuePopCond);\n}\n\nvoid POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque)\n{\n    assert(ctx != NULL);\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    /* Wait until there is space in the queue for the new job */\n    while (isQueueFull(ctx) && (!ctx->shutdown)) {\n        ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex);\n    }\n    POOL_add_internal(ctx, function, opaque);\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n}\n\n\nint POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque)\n{\n    assert(ctx != NULL);\n    ZSTD_pthread_mutex_lock(&ctx->queueMutex);\n    if (isQueueFull(ctx)) {\n        ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n        return 0;\n    }\n    POOL_add_internal(ctx, function, opaque);\n    ZSTD_pthread_mutex_unlock(&ctx->queueMutex);\n    return 1;\n}\n\n\n#else  /* ZSTD_MULTITHREAD  not defined */\n\n/* ========================== */\n/* No multi-threading support */\n/* ========================== */\n\n\n/* We don't need any data, but if it is empty, malloc() might return NULL. */\nstruct POOL_ctx_s {\n    int dummy;\n};\nstatic POOL_ctx g_poolCtx;\n\nPOOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {\n    return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);\n}\n\nPOOL_ctx*\nPOOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem)\n{\n    (void)numThreads;\n    (void)queueSize;\n    (void)customMem;\n    return &g_poolCtx;\n}\n\nvoid POOL_free(POOL_ctx* ctx) {\n    assert(!ctx || ctx == &g_poolCtx);\n    (void)ctx;\n}\n\nvoid POOL_joinJobs(POOL_ctx* ctx){\n    assert(!ctx || ctx == &g_poolCtx);\n    (void)ctx;\n}\n\nint POOL_resize(POOL_ctx* ctx, size_t numThreads) {\n    (void)ctx; (void)numThreads;\n    return 0;\n}\n\nvoid POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) {\n    (void)ctx;\n    function(opaque);\n}\n\nint POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {\n    (void)ctx;\n    function(opaque);\n    return 1;\n}\n\nsize_t POOL_sizeof(const POOL_ctx* ctx) {\n    if (ctx==NULL) return 0;  /* supports sizeof NULL */\n    assert(ctx == &g_poolCtx);\n    return sizeof(*ctx);\n}\n\n#endif  /* ZSTD_MULTITHREAD */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/pool.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef POOL_H\n#define POOL_H\n\n\n#include \"zstd_deps.h\"\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_customMem */\n#include \"../zstd.h\"\n\ntypedef struct POOL_ctx_s POOL_ctx;\n\n/*! POOL_create() :\n *  Create a thread pool with at most `numThreads` threads.\n * `numThreads` must be at least 1.\n *  The maximum number of queued jobs before blocking is `queueSize`.\n * @return : POOL_ctx pointer on success, else NULL.\n*/\nPOOL_ctx* POOL_create(size_t numThreads, size_t queueSize);\n\nPOOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,\n                               ZSTD_customMem customMem);\n\n/*! POOL_free() :\n *  Free a thread pool returned by POOL_create().\n */\nvoid POOL_free(POOL_ctx* ctx);\n\n\n/*! POOL_joinJobs() :\n *  Waits for all queued jobs to finish executing.\n */\nvoid POOL_joinJobs(POOL_ctx* ctx);\n\n/*! POOL_resize() :\n *  Expands or shrinks pool's number of threads.\n *  This is more efficient than releasing + creating a new context,\n *  since it tries to preserve and reuse existing threads.\n * `numThreads` must be at least 1.\n * @return : 0 when resize was successful,\n *           !0 (typically 1) if there is an error.\n *    note : only numThreads can be resized, queueSize remains unchanged.\n */\nint POOL_resize(POOL_ctx* ctx, size_t numThreads);\n\n/*! POOL_sizeof() :\n * @return threadpool memory usage\n *  note : compatible with NULL (returns 0 in this case)\n */\nsize_t POOL_sizeof(const POOL_ctx* ctx);\n\n/*! POOL_function :\n *  The function type that can be added to a thread pool.\n */\ntypedef void (*POOL_function)(void*);\n\n/*! POOL_add() :\n *  Add the job `function(opaque)` to the thread pool. `ctx` must be valid.\n *  Possibly blocks until there is room in the queue.\n *  Note : The function may be executed asynchronously,\n *         therefore, `opaque` must live until function has been completed.\n */\nvoid POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);\n\n\n/*! POOL_tryAdd() :\n *  Add the job `function(opaque)` to thread pool _if_ a queue slot is available.\n *  Returns immediately even if not (does not block).\n * @return : 1 if successful, 0 if not.\n */\nint POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/portability_macros.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_PORTABILITY_MACROS_H\n#define ZSTD_PORTABILITY_MACROS_H\n\n/**\n * This header file contains macro definitions to support portability.\n * This header is shared between C and ASM code, so it MUST only\n * contain macro definitions. It MUST not contain any C code.\n *\n * This header ONLY defines macros to detect platforms/feature support.\n *\n */\n\n\n/* compat. with non-clang compilers */\n#ifndef __has_attribute\n  #define __has_attribute(x) 0\n#endif\n\n/* compat. with non-clang compilers */\n#ifndef __has_builtin\n#  define __has_builtin(x) 0\n#endif\n\n/* compat. with non-clang compilers */\n#ifndef __has_feature\n#  define __has_feature(x) 0\n#endif\n\n/* detects whether we are being compiled under msan */\n#ifndef ZSTD_MEMORY_SANITIZER\n#  if __has_feature(memory_sanitizer)\n#    define ZSTD_MEMORY_SANITIZER 1\n#  else\n#    define ZSTD_MEMORY_SANITIZER 0\n#  endif\n#endif\n\n/* detects whether we are being compiled under asan */\n#ifndef ZSTD_ADDRESS_SANITIZER\n#  if __has_feature(address_sanitizer)\n#    define ZSTD_ADDRESS_SANITIZER 1\n#  elif defined(__SANITIZE_ADDRESS__)\n#    define ZSTD_ADDRESS_SANITIZER 1\n#  else\n#    define ZSTD_ADDRESS_SANITIZER 0\n#  endif\n#endif\n\n/* detects whether we are being compiled under dfsan */\n#ifndef ZSTD_DATAFLOW_SANITIZER\n# if __has_feature(dataflow_sanitizer)\n#  define ZSTD_DATAFLOW_SANITIZER 1\n# else\n#  define ZSTD_DATAFLOW_SANITIZER 0\n# endif\n#endif\n\n/* Mark the internal assembly functions as hidden  */\n#ifdef __ELF__\n# define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func\n#elif defined(__APPLE__)\n# define ZSTD_HIDE_ASM_FUNCTION(func) .private_extern func\n#else\n# define ZSTD_HIDE_ASM_FUNCTION(func)\n#endif\n\n/* Compile time determination of BMI2 support */\n#ifndef STATIC_BMI2\n#  if defined(__BMI2__)\n#    define STATIC_BMI2 1\n#  elif defined(_MSC_VER) && defined(__AVX2__)\n#    define STATIC_BMI2 1 /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */\n#  endif\n#endif\n\n#ifndef STATIC_BMI2\n#  define STATIC_BMI2 0\n#endif\n\n/* Enable runtime BMI2 dispatch based on the CPU.\n * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.\n */\n#ifndef DYNAMIC_BMI2\n#  if ((defined(__clang__) && __has_attribute(__target__)) \\\n      || (defined(__GNUC__) \\\n          && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \\\n      && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)) \\\n      && !defined(__BMI2__)\n#    define DYNAMIC_BMI2 1\n#  else\n#    define DYNAMIC_BMI2 0\n#  endif\n#endif\n\n/**\n * Only enable assembly for GNU C compatible compilers,\n * because other platforms may not support GAS assembly syntax.\n *\n * Only enable assembly for Linux / MacOS / Win32, other platforms may\n * work, but they haven't been tested. This could likely be\n * extended to BSD systems.\n *\n * Disable assembly when MSAN is enabled, because MSAN requires\n * 100% of code to be instrumented to work.\n */\n#if defined(__GNUC__)\n#  if defined(__linux__) || defined(__linux) || defined(__APPLE__) || defined(_WIN32)\n#    if ZSTD_MEMORY_SANITIZER\n#      define ZSTD_ASM_SUPPORTED 0\n#    elif ZSTD_DATAFLOW_SANITIZER\n#      define ZSTD_ASM_SUPPORTED 0\n#    else\n#      define ZSTD_ASM_SUPPORTED 1\n#    endif\n#  else\n#    define ZSTD_ASM_SUPPORTED 0\n#  endif\n#else\n#  define ZSTD_ASM_SUPPORTED 0\n#endif\n\n/**\n * Determines whether we should enable assembly for x86-64\n * with BMI2.\n *\n * Enable if all of the following conditions hold:\n * - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM\n * - Assembly is supported\n * - We are compiling for x86-64 and either:\n *   - DYNAMIC_BMI2 is enabled\n *   - BMI2 is supported at compile time\n */\n#if !defined(ZSTD_DISABLE_ASM) &&                                 \\\n    ZSTD_ASM_SUPPORTED &&                                         \\\n    defined(__x86_64__) &&                                        \\\n    (DYNAMIC_BMI2 || defined(__BMI2__))\n# define ZSTD_ENABLE_ASM_X86_64_BMI2 1\n#else\n# define ZSTD_ENABLE_ASM_X86_64_BMI2 0\n#endif\n\n/*\n * For x86 ELF targets, add .note.gnu.property section for Intel CET in\n * assembly sources when CET is enabled.\n *\n * Additionally, any function that may be called indirectly must begin\n * with ZSTD_CET_ENDBRANCH.\n */\n#if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__)) \\\n    && defined(__has_include)\n# if __has_include(<cet.h>)\n#  include <cet.h>\n#  define ZSTD_CET_ENDBRANCH _CET_ENDBR\n# endif\n#endif\n\n#ifndef ZSTD_CET_ENDBRANCH\n# define ZSTD_CET_ENDBRANCH\n#endif\n\n#endif /* ZSTD_PORTABILITY_MACROS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/threading.c",
    "content": "﻿/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/**\n * This file will hold wrapper for systems, which do not support pthreads\n */\n\n#include \"threading.h\"\n\n/* create fake symbol to avoid empty translation unit warning */\nint g_ZSTD_threading_useless_symbol;\n\n#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)\n\n/**\n * Windows minimalist Pthread Wrapper\n */\n\n\n/* ===  Dependencies  === */\n#include <process.h>\n#include <errno.h>\n\n\n/* ===  Implementation  === */\n\ntypedef struct {\n    void* (*start_routine)(void*);\n    void* arg;\n    int initialized;\n    ZSTD_pthread_cond_t initialized_cond;\n    ZSTD_pthread_mutex_t initialized_mutex;\n} ZSTD_thread_params_t;\n\nstatic unsigned __stdcall worker(void *arg)\n{\n    void* (*start_routine)(void*);\n    void* thread_arg;\n\n    /* Initialized thread_arg and start_routine and signal main thread that we don't need it\n     * to wait any longer.\n     */\n    {\n        ZSTD_thread_params_t*  thread_param = (ZSTD_thread_params_t*)arg;\n        thread_arg = thread_param->arg;\n        start_routine = thread_param->start_routine;\n\n        /* Signal main thread that we are running and do not depend on its memory anymore */\n        ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex);\n        thread_param->initialized = 1;\n        ZSTD_pthread_cond_signal(&thread_param->initialized_cond);\n        ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex);\n    }\n\n    start_routine(thread_arg);\n\n    return 0;\n}\n\nint ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,\n            void* (*start_routine) (void*), void* arg)\n{\n    ZSTD_thread_params_t thread_param;\n    (void)unused;\n\n    if (thread==NULL) return -1;\n    *thread = NULL;\n\n    thread_param.start_routine = start_routine;\n    thread_param.arg = arg;\n    thread_param.initialized = 0;\n\n    /* Setup thread initialization synchronization */\n    if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) {\n        /* Should never happen on Windows */\n        return -1;\n    }\n    if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) {\n        /* Should never happen on Windows */\n        ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);\n        return -1;\n    }\n\n    /* Spawn thread */\n    *thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL);\n    if (*thread==NULL) {\n        ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);\n        ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);\n        return errno;\n    }\n\n    /* Wait for thread to be initialized */\n    ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex);\n    while(!thread_param.initialized) {\n        ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex);\n    }\n    ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex);\n    ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);\n    ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);\n\n    return 0;\n}\n\nint ZSTD_pthread_join(ZSTD_pthread_t thread)\n{\n    DWORD result;\n\n    if (!thread) return 0;\n\n    result = WaitForSingleObject(thread, INFINITE);\n    CloseHandle(thread);\n\n    switch (result) {\n    case WAIT_OBJECT_0:\n        return 0;\n    case WAIT_ABANDONED:\n        return EINVAL;\n    default:\n        return GetLastError();\n    }\n}\n\n#endif   /* ZSTD_MULTITHREAD */\n\n#if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)\n\n#define ZSTD_DEPS_NEED_MALLOC\n#include \"zstd_deps.h\"\n\nint ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)\n{\n    assert(mutex != NULL);\n    *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));\n    if (!*mutex)\n        return 1;\n    return pthread_mutex_init(*mutex, attr);\n}\n\nint ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)\n{\n    assert(mutex != NULL);\n    if (!*mutex)\n        return 0;\n    {\n        int const ret = pthread_mutex_destroy(*mutex);\n        ZSTD_free(*mutex);\n        return ret;\n    }\n}\n\nint ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)\n{\n    assert(cond != NULL);\n    *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));\n    if (!*cond)\n        return 1;\n    return pthread_cond_init(*cond, attr);\n}\n\nint ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)\n{\n    assert(cond != NULL);\n    if (!*cond)\n        return 0;\n    {\n        int const ret = pthread_cond_destroy(*cond);\n        ZSTD_free(*cond);\n        return ret;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/threading.h",
    "content": "﻿/**\n * Copyright (c) 2016 Tino Reichardt\n * All rights reserved.\n *\n * You can contact the author at:\n * - zstdmt source repository: https://github.com/mcmilk/zstdmt\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef THREADING_H_938743\n#define THREADING_H_938743\n\n#include \"debug.h\"\n\n#if defined(ZSTD_MULTITHREAD) && defined(_WIN32)\n\n/**\n * Windows minimalist Pthread Wrapper\n */\n#ifdef WINVER\n#  undef WINVER\n#endif\n#define WINVER       0x0600\n\n#ifdef _WIN32_WINNT\n#  undef _WIN32_WINNT\n#endif\n#define _WIN32_WINNT 0x0600\n\n#ifndef WIN32_LEAN_AND_MEAN\n#  define WIN32_LEAN_AND_MEAN\n#endif\n\n#undef ERROR   /* reported already defined on VS 2015 (Rich Geldreich) */\n#include <windows.h>\n#undef ERROR\n#define ERROR(name) ZSTD_ERROR(name)\n\n\n/* mutex */\n#define ZSTD_pthread_mutex_t           CRITICAL_SECTION\n#define ZSTD_pthread_mutex_init(a, b)  ((void)(b), InitializeCriticalSection((a)), 0)\n#define ZSTD_pthread_mutex_destroy(a)  DeleteCriticalSection((a))\n#define ZSTD_pthread_mutex_lock(a)     EnterCriticalSection((a))\n#define ZSTD_pthread_mutex_unlock(a)   LeaveCriticalSection((a))\n\n/* condition variable */\n#define ZSTD_pthread_cond_t             CONDITION_VARIABLE\n#define ZSTD_pthread_cond_init(a, b)    ((void)(b), InitializeConditionVariable((a)), 0)\n#define ZSTD_pthread_cond_destroy(a)    ((void)(a))\n#define ZSTD_pthread_cond_wait(a, b)    SleepConditionVariableCS((a), (b), INFINITE)\n#define ZSTD_pthread_cond_signal(a)     WakeConditionVariable((a))\n#define ZSTD_pthread_cond_broadcast(a)  WakeAllConditionVariable((a))\n\n/* ZSTD_pthread_create() and ZSTD_pthread_join() */\ntypedef HANDLE ZSTD_pthread_t;\n\nint ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,\n                   void* (*start_routine) (void*), void* arg);\n\nint ZSTD_pthread_join(ZSTD_pthread_t thread);\n\n/**\n * add here more wrappers as required\n */\n\n#elif defined(ZSTD_MULTITHREAD)    /* posix assumed ; need a better detection method */\n/* ===   POSIX Systems   === */\n#  include <pthread.h>\n\n#if DEBUGLEVEL < 1\n\n#define ZSTD_pthread_mutex_t            pthread_mutex_t\n#define ZSTD_pthread_mutex_init(a, b)   pthread_mutex_init((a), (b))\n#define ZSTD_pthread_mutex_destroy(a)   pthread_mutex_destroy((a))\n#define ZSTD_pthread_mutex_lock(a)      pthread_mutex_lock((a))\n#define ZSTD_pthread_mutex_unlock(a)    pthread_mutex_unlock((a))\n\n#define ZSTD_pthread_cond_t             pthread_cond_t\n#define ZSTD_pthread_cond_init(a, b)    pthread_cond_init((a), (b))\n#define ZSTD_pthread_cond_destroy(a)    pthread_cond_destroy((a))\n#define ZSTD_pthread_cond_wait(a, b)    pthread_cond_wait((a), (b))\n#define ZSTD_pthread_cond_signal(a)     pthread_cond_signal((a))\n#define ZSTD_pthread_cond_broadcast(a)  pthread_cond_broadcast((a))\n\n#define ZSTD_pthread_t                  pthread_t\n#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))\n#define ZSTD_pthread_join(a)         pthread_join((a),NULL)\n\n#else /* DEBUGLEVEL >= 1 */\n\n/* Debug implementation of threading.\n * In this implementation we use pointers for mutexes and condition variables.\n * This way, if we forget to init/destroy them the program will crash or ASAN\n * will report leaks.\n */\n\n#define ZSTD_pthread_mutex_t            pthread_mutex_t*\nint ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr);\nint ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex);\n#define ZSTD_pthread_mutex_lock(a)      pthread_mutex_lock(*(a))\n#define ZSTD_pthread_mutex_unlock(a)    pthread_mutex_unlock(*(a))\n\n#define ZSTD_pthread_cond_t             pthread_cond_t*\nint ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr);\nint ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond);\n#define ZSTD_pthread_cond_wait(a, b)    pthread_cond_wait(*(a), *(b))\n#define ZSTD_pthread_cond_signal(a)     pthread_cond_signal(*(a))\n#define ZSTD_pthread_cond_broadcast(a)  pthread_cond_broadcast(*(a))\n\n#define ZSTD_pthread_t                  pthread_t\n#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d))\n#define ZSTD_pthread_join(a)         pthread_join((a),NULL)\n\n#endif\n\n#else  /* ZSTD_MULTITHREAD not defined */\n/* No multithreading support */\n\ntypedef int ZSTD_pthread_mutex_t;\n#define ZSTD_pthread_mutex_init(a, b)   ((void)(a), (void)(b), 0)\n#define ZSTD_pthread_mutex_destroy(a)   ((void)(a))\n#define ZSTD_pthread_mutex_lock(a)      ((void)(a))\n#define ZSTD_pthread_mutex_unlock(a)    ((void)(a))\n\ntypedef int ZSTD_pthread_cond_t;\n#define ZSTD_pthread_cond_init(a, b)    ((void)(a), (void)(b), 0)\n#define ZSTD_pthread_cond_destroy(a)    ((void)(a))\n#define ZSTD_pthread_cond_wait(a, b)    ((void)(a), (void)(b))\n#define ZSTD_pthread_cond_signal(a)     ((void)(a))\n#define ZSTD_pthread_cond_broadcast(a)  ((void)(a))\n\n/* do not use ZSTD_pthread_t */\n\n#endif /* ZSTD_MULTITHREAD */\n\n\n#endif /* THREADING_H_938743 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/zstd_common.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#define ZSTD_DEPS_NEED_MALLOC\n#include \"error_private.h\"\n#include \"zstd_internal.h\"\n\n\n/*-****************************************\n*  Version\n******************************************/\nunsigned ZSTD_versionNumber(void) { return ZSTD_VERSION_NUMBER; }\n\nconst char* ZSTD_versionString(void) { return ZSTD_VERSION_STRING; }\n\n\n/*-****************************************\n*  ZSTD Error Management\n******************************************/\n#undef ZSTD_isError   /* defined within zstd_internal.h */\n/*! ZSTD_isError() :\n *  tells if a return value is an error code\n *  symbol is required for external callers */\nunsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n/*! ZSTD_getErrorName() :\n *  provides error code string from function result (useful for debugging) */\nconst char* ZSTD_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n/*! ZSTD_getError() :\n *  convert a `size_t` function result into a proper ZSTD_errorCode enum */\nZSTD_ErrorCode ZSTD_getErrorCode(size_t code) { return ERR_getErrorCode(code); }\n\n/*! ZSTD_getErrorString() :\n *  provides error code string from enum */\nconst char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString(code); }\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/zstd_deps.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This file provides common libc dependencies that zstd requires.\n * The purpose is to allow replacing this file with a custom implementation\n * to compile zstd without libc support.\n */\n\n/* Need:\n * NULL\n * INT_MAX\n * UINT_MAX\n * ZSTD_memcpy()\n * ZSTD_memset()\n * ZSTD_memmove()\n */\n#ifndef ZSTD_DEPS_COMMON\n#define ZSTD_DEPS_COMMON\n\n/* Even though we use qsort_r only for the dictionary builder, the macro\n * _GNU_SOURCE has to be declared *before* the inclusion of any standard\n * header and the script 'combine.sh' combines the whole zstd source code\n * in a single file.\n */\n#if defined(__linux) || defined(__linux__) || defined(linux) || defined(__gnu_linux__) || \\\n    defined(__CYGWIN__) || defined(__MSYS__)\n#if !defined(_GNU_SOURCE) && !defined(__ANDROID__) /* NDK doesn't ship qsort_r(). */\n#define _GNU_SOURCE\n#endif\n#endif\n\n#include <limits.h>\n#include <stddef.h>\n#include <string.h>\n\n#if defined(__GNUC__) && __GNUC__ >= 4\n# define ZSTD_memcpy(d,s,l) __builtin_memcpy((d),(s),(l))\n# define ZSTD_memmove(d,s,l) __builtin_memmove((d),(s),(l))\n# define ZSTD_memset(p,v,l) __builtin_memset((p),(v),(l))\n#else\n# define ZSTD_memcpy(d,s,l) memcpy((d),(s),(l))\n# define ZSTD_memmove(d,s,l) memmove((d),(s),(l))\n# define ZSTD_memset(p,v,l) memset((p),(v),(l))\n#endif\n\n#endif /* ZSTD_DEPS_COMMON */\n\n/* Need:\n * ZSTD_malloc()\n * ZSTD_free()\n * ZSTD_calloc()\n */\n#ifdef ZSTD_DEPS_NEED_MALLOC\n#ifndef ZSTD_DEPS_MALLOC\n#define ZSTD_DEPS_MALLOC\n\n#include <stdlib.h>\n\n#define ZSTD_malloc(s) malloc(s)\n#define ZSTD_calloc(n,s) calloc((n), (s))\n#define ZSTD_free(p) free((p))\n\n#endif /* ZSTD_DEPS_MALLOC */\n#endif /* ZSTD_DEPS_NEED_MALLOC */\n\n/*\n * Provides 64-bit math support.\n * Need:\n * U64 ZSTD_div64(U64 dividend, U32 divisor)\n */\n#ifdef ZSTD_DEPS_NEED_MATH64\n#ifndef ZSTD_DEPS_MATH64\n#define ZSTD_DEPS_MATH64\n\n#define ZSTD_div64(dividend, divisor) ((dividend) / (divisor))\n\n#endif /* ZSTD_DEPS_MATH64 */\n#endif /* ZSTD_DEPS_NEED_MATH64 */\n\n/* Need:\n * assert()\n */\n#ifdef ZSTD_DEPS_NEED_ASSERT\n#ifndef ZSTD_DEPS_ASSERT\n#define ZSTD_DEPS_ASSERT\n\n#include <assert.h>\n\n#endif /* ZSTD_DEPS_ASSERT */\n#endif /* ZSTD_DEPS_NEED_ASSERT */\n\n/* Need:\n * ZSTD_DEBUG_PRINT()\n */\n#ifdef ZSTD_DEPS_NEED_IO\n#ifndef ZSTD_DEPS_IO\n#define ZSTD_DEPS_IO\n\n#include <stdio.h>\n#define ZSTD_DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__)\n\n#endif /* ZSTD_DEPS_IO */\n#endif /* ZSTD_DEPS_NEED_IO */\n\n/* Only requested when <stdint.h> is known to be present.\n * Need:\n * intptr_t\n */\n#ifdef ZSTD_DEPS_NEED_STDINT\n#ifndef ZSTD_DEPS_STDINT\n#define ZSTD_DEPS_STDINT\n\n#include <stdint.h>\n\n#endif /* ZSTD_DEPS_STDINT */\n#endif /* ZSTD_DEPS_NEED_STDINT */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/zstd_internal.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_CCOMMON_H_MODULE\n#define ZSTD_CCOMMON_H_MODULE\n\n/* this module contains definitions which must be identical\n * across compression, decompression and dictBuilder.\n * It also contains a few functions useful to at least 2 of them\n * and which benefit from being inlined */\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"compiler.h\"\n#include \"cpu.h\"\n#include \"mem.h\"\n#include \"debug.h\"                 /* assert, DEBUGLOG, RAWLOG, g_debuglevel */\n#include \"error_private.h\"\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"../zstd.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"fse.h\"\n#include \"huf.h\"\n#ifndef XXH_STATIC_LINKING_ONLY\n#  define XXH_STATIC_LINKING_ONLY  /* XXH64_state_t */\n#endif\n#include \"xxhash.h\"                /* XXH_reset, update, digest */\n#ifndef ZSTD_NO_TRACE\n#  include \"zstd_trace.h\"\n#else\n#  define ZSTD_TRACE 0\n#endif\n\n/* ---- static assert (debug) --- */\n#define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)\n#define ZSTD_isError ERR_isError   /* for inlining */\n#define FSE_isError  ERR_isError\n#define HUF_isError  ERR_isError\n\n\n/*-*************************************\n*  shared macros\n***************************************/\n#undef MIN\n#undef MAX\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n#define BOUNDED(min,val,max) (MAX(min,MIN(val,max)))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTD_OPT_NUM    (1<<12)\n\n#define ZSTD_REP_NUM      3                 /* number of repcodes */\nstatic UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define ZSTD_WINDOWLOG_ABSOLUTEMIN 10\nstatic UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };\nstatic UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };\n\n#define ZSTD_FRAMEIDSIZE 4   /* magic number size */\n\n#define ZSTD_BLOCKHEADERSIZE 3   /* C standard doesn't allow `static const` variable to be init using another `static const` variable */\nstatic UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;\ntypedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;\n\n#define ZSTD_FRAMECHECKSUMSIZE 4\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */)   /* for a non-null block */\n#define MIN_LITERALS_FOR_4_STREAMS 6\n\ntypedef enum { set_basic, set_rle, set_compressed, set_repeat } SymbolEncodingType_e;\n\n#define LONGNBSEQ 0x7F00\n\n#define MINMATCH 3\n\n#define Litbits  8\n#define LitHufLog 11\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML   52\n#define MaxLL   35\n#define DefaultMaxOff 28\n#define MaxOff  31\n#define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */\n#define MLFSELog    9\n#define LLFSELog    9\n#define OffFSELog   8\n#define MaxFSELog  MAX(MAX(MLFSELog, LLFSELog), OffFSELog)\n#define MaxMLBits 16\n#define MaxLLBits 16\n\n#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */\n/* Each table cannot take more than #symbols * FSELog bits */\n#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)\n\nstatic UNUSED_ATTR const U8 LL_bits[MaxLL+1] = {\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     1, 1, 1, 1, 2, 2, 3, 3,\n     4, 6, 7, 8, 9,10,11,12,\n    13,14,15,16\n};\nstatic UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {\n     4, 3, 2, 2, 2, 2, 2, 2,\n     2, 2, 2, 2, 2, 1, 1, 1,\n     2, 2, 2, 2, 2, 2, 2, 2,\n     2, 3, 2, 1, 1, 1, 1, 1,\n    -1,-1,-1,-1\n};\n#define LL_DEFAULTNORMLOG 6  /* for static allocation */\nstatic UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;\n\nstatic UNUSED_ATTR const U8 ML_bits[MaxML+1] = {\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     0, 0, 0, 0, 0, 0, 0, 0,\n     1, 1, 1, 1, 2, 2, 3, 3,\n     4, 4, 5, 7, 8, 9,10,11,\n    12,13,14,15,16\n};\nstatic UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = {\n     1, 4, 3, 2, 2, 2, 2, 2,\n     2, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1,-1,-1,\n    -1,-1,-1,-1,-1\n};\n#define ML_DEFAULTNORMLOG 6  /* for static allocation */\nstatic UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;\n\nstatic UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = {\n     1, 1, 1, 1, 1, 1, 2, 2,\n     2, 1, 1, 1, 1, 1, 1, 1,\n     1, 1, 1, 1, 1, 1, 1, 1,\n    -1,-1,-1,-1,-1\n};\n#define OF_DEFAULTNORMLOG 5  /* for static allocation */\nstatic UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTD_copy8(void* dst, const void* src) {\n#if defined(ZSTD_ARCH_ARM_NEON)\n    vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src));\n#else\n    ZSTD_memcpy(dst, src, 8);\n#endif\n}\n#define COPY8(d,s) do { ZSTD_copy8(d,s); d+=8; s+=8; } while (0)\n\n/* Need to use memmove here since the literal buffer can now be located within\n   the dst buffer. In circumstances where the op \"catches up\" to where the\n   literal buffer is, there can be partial overlaps in this call on the final\n   copy if the literal is being shifted by less than 16 bytes. */\nstatic void ZSTD_copy16(void* dst, const void* src) {\n#if defined(ZSTD_ARCH_ARM_NEON)\n    vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));\n#elif defined(ZSTD_ARCH_X86_SSE2)\n    _mm_storeu_si128((__m128i*)dst, _mm_loadu_si128((const __m128i*)src));\n#elif defined(__clang__)\n    ZSTD_memmove(dst, src, 16);\n#else\n    /* ZSTD_memmove is not inlined properly by gcc */\n    BYTE copy16_buf[16];\n    ZSTD_memcpy(copy16_buf, src, 16);\n    ZSTD_memcpy(dst, copy16_buf, 16);\n#endif\n}\n#define COPY16(d,s) do { ZSTD_copy16(d,s); d+=16; s+=16; } while (0)\n\n#define WILDCOPY_OVERLENGTH 32\n#define WILDCOPY_VECLEN 16\n\ntypedef enum {\n    ZSTD_no_overlap,\n    ZSTD_overlap_src_before_dst\n    /*  ZSTD_overlap_dst_before_src, */\n} ZSTD_overlap_e;\n\n/*! ZSTD_wildcopy() :\n *  Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0)\n *  @param ovtype controls the overlap detection\n *         - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.\n *         - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart.\n *           The src buffer must be before the dst buffer.\n */\nMEM_STATIC FORCE_INLINE_ATTR\nvoid ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype)\n{\n    ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n\n    if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {\n        /* Handle short offset copies. */\n        do {\n            COPY8(op, ip);\n        } while (op < oend);\n    } else {\n        assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN);\n        /* Separate out the first COPY16() call because the copy length is\n         * almost certain to be short, so the branches have different\n         * probabilities. Since it is almost certain to be short, only do\n         * one COPY16() in the first call. Then, do two calls per loop since\n         * at that point it is more likely to have a high trip count.\n         */\n        ZSTD_copy16(op, ip);\n        if (16 >= length) return;\n        op += 16;\n        ip += 16;\n        do {\n            COPY16(op, ip);\n            COPY16(op, ip);\n        }\n        while (op < oend);\n    }\n}\n\nMEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    size_t const length = MIN(dstCapacity, srcSize);\n    if (length > 0) {\n        ZSTD_memcpy(dst, src, length);\n    }\n    return length;\n}\n\n/* define \"workspace is too large\" as this number of times larger than needed */\n#define ZSTD_WORKSPACETOOLARGE_FACTOR 3\n\n/* when workspace is continuously too large\n * during at least this number of times,\n * context's memory usage is considered wasteful,\n * because it's sized to handle a worst case scenario which rarely happens.\n * In which case, resize it down to free some memory */\n#define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128\n\n/* Controls whether the input/output buffer is buffered or stable. */\ntypedef enum {\n    ZSTD_bm_buffered = 0,  /* Buffer the input/output */\n    ZSTD_bm_stable = 1     /* ZSTD_inBuffer/ZSTD_outBuffer is stable */\n} ZSTD_bufferMode_e;\n\n\n/*-*******************************************\n*  Private declarations\n*********************************************/\n\n/**\n * Contains the compressed frame size and an upper-bound for the decompressed frame size.\n * Note: before using `compressedSize`, check for errors using ZSTD_isError().\n *       similarly, before using `decompressedBound`, check for errors using:\n *          `decompressedBound != ZSTD_CONTENTSIZE_ERROR`\n */\ntypedef struct {\n    size_t nbBlocks;\n    size_t compressedSize;\n    unsigned long long decompressedBound;\n} ZSTD_frameSizeInfo;   /* decompress & legacy */\n\n/* ZSTD_invalidateRepCodes() :\n * ensures next compression will not use repcodes from previous block.\n * Note : only works with regular variant;\n *        do not use with extDict variant ! */\nvoid ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);   /* zstdmt, adaptive_compression (shouldn't get this definition from here) */\n\n\ntypedef struct {\n    blockType_e blockType;\n    U32 lastBlock;\n    U32 origSize;\n} blockProperties_t;   /* declared here for decompress and fullbench */\n\n/*! ZSTD_getcBlockSize() :\n *  Provides the size of compressed block from block header `src` */\n/*  Used by: decompress, fullbench */\nsize_t ZSTD_getcBlockSize(const void* src, size_t srcSize,\n                          blockProperties_t* bpPtr);\n\n/*! ZSTD_decodeSeqHeaders() :\n *  decode sequence header from src */\n/*  Used by: zstd_decompress_block, fullbench */\nsize_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,\n                       const void* src, size_t srcSize);\n\n/**\n * @returns true iff the CPU supports dynamic BMI2 dispatch.\n */\nMEM_STATIC int ZSTD_cpuSupportsBmi2(void)\n{\n    ZSTD_cpuid_t cpuid = ZSTD_cpuid();\n    return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);\n}\n\n#endif   /* ZSTD_CCOMMON_H_MODULE */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/common/zstd_trace.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_TRACE_H\n#define ZSTD_TRACE_H\n\n#include <stddef.h>\n\n/* weak symbol support\n * For now, enable conservatively:\n * - Only GNUC\n * - Only ELF\n * - Only x86-64, i386, aarch64 and risc-v.\n * Also, explicitly disable on platforms known not to work so they aren't\n * forgotten in the future.\n */\n#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && \\\n    defined(__GNUC__) && defined(__ELF__) && \\\n    (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \\\n     defined(_M_IX86) || defined(__aarch64__) || defined(__riscv)) && \\\n    !defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \\\n    !defined(__CYGWIN__) && !defined(_AIX)\n#  define ZSTD_HAVE_WEAK_SYMBOLS 1\n#else\n#  define ZSTD_HAVE_WEAK_SYMBOLS 0\n#endif\n#if ZSTD_HAVE_WEAK_SYMBOLS\n#  define ZSTD_WEAK_ATTR __attribute__((__weak__))\n#else\n#  define ZSTD_WEAK_ATTR\n#endif\n\n/* Only enable tracing when weak symbols are available. */\n#ifndef ZSTD_TRACE\n#  define ZSTD_TRACE ZSTD_HAVE_WEAK_SYMBOLS\n#endif\n\n#if ZSTD_TRACE\n\nstruct ZSTD_CCtx_s;\nstruct ZSTD_DCtx_s;\nstruct ZSTD_CCtx_params_s;\n\ntypedef struct {\n    /**\n     * ZSTD_VERSION_NUMBER\n     *\n     * This is guaranteed to be the first member of ZSTD_trace.\n     * Otherwise, this struct is not stable between versions. If\n     * the version number does not match your expectation, you\n     * should not interpret the rest of the struct.\n     */\n    unsigned version;\n    /**\n     * Non-zero if streaming (de)compression is used.\n     */\n    int streaming;\n    /**\n     * The dictionary ID.\n     */\n    unsigned dictionaryID;\n    /**\n     * Is the dictionary cold?\n     * Only set on decompression.\n     */\n    int dictionaryIsCold;\n    /**\n     * The dictionary size or zero if no dictionary.\n     */\n    size_t dictionarySize;\n    /**\n     * The uncompressed size of the data.\n     */\n    size_t uncompressedSize;\n    /**\n     * The compressed size of the data.\n     */\n    size_t compressedSize;\n    /**\n     * The fully resolved CCtx parameters (NULL on decompression).\n     */\n    struct ZSTD_CCtx_params_s const* params;\n    /**\n     * The ZSTD_CCtx pointer (NULL on decompression).\n     */\n    struct ZSTD_CCtx_s const* cctx;\n    /**\n     * The ZSTD_DCtx pointer (NULL on compression).\n     */\n    struct ZSTD_DCtx_s const* dctx;\n} ZSTD_Trace;\n\n/**\n * A tracing context. It must be 0 when tracing is disabled.\n * Otherwise, any non-zero value returned by a tracing begin()\n * function is presented to any subsequent calls to end().\n *\n * Any non-zero value is treated as tracing is enabled and not\n * interpreted by the library.\n *\n * Two possible uses are:\n * * A timestamp for when the begin() function was called.\n * * A unique key identifying the (de)compression, like the\n *   address of the [dc]ctx pointer if you need to track\n *   more information than just a timestamp.\n */\ntypedef unsigned long long ZSTD_TraceCtx;\n\n/**\n * Trace the beginning of a compression call.\n * @param cctx The dctx pointer for the compression.\n *             It can be used as a key to map begin() to end().\n * @returns Non-zero if tracing is enabled. The return value is\n *          passed to ZSTD_trace_compress_end().\n */\nZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_compress_begin(\n    struct ZSTD_CCtx_s const* cctx);\n\n/**\n * Trace the end of a compression call.\n * @param ctx The return value of ZSTD_trace_compress_begin().\n * @param trace The zstd tracing info.\n */\nZSTD_WEAK_ATTR void ZSTD_trace_compress_end(\n    ZSTD_TraceCtx ctx,\n    ZSTD_Trace const* trace);\n\n/**\n * Trace the beginning of a decompression call.\n * @param dctx The dctx pointer for the decompression.\n *             It can be used as a key to map begin() to end().\n * @returns Non-zero if tracing is enabled. The return value is\n *          passed to ZSTD_trace_compress_end().\n */\nZSTD_WEAK_ATTR ZSTD_TraceCtx ZSTD_trace_decompress_begin(\n    struct ZSTD_DCtx_s const* dctx);\n\n/**\n * Trace the end of a decompression call.\n * @param ctx The return value of ZSTD_trace_decompress_begin().\n * @param trace The zstd tracing info.\n */\nZSTD_WEAK_ATTR void ZSTD_trace_decompress_end(\n    ZSTD_TraceCtx ctx,\n    ZSTD_Trace const* trace);\n\n#endif /* ZSTD_TRACE */\n\n#endif /* ZSTD_TRACE_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/clevels.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_CLEVELS_H\n#define ZSTD_CLEVELS_H\n\n#define ZSTD_STATIC_LINKING_ONLY  /* ZSTD_compressionParameters  */\n#include \"../zstd.h\"\n\n/*-=====  Pre-defined compression levels  =====-*/\n\n#define ZSTD_MAX_CLEVEL     22\n\n#ifdef __GNUC__\n__attribute__((__unused__))\n#endif\n\nstatic const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {\n{   /* \"default\" - for any srcSize > 256 KB */\n    /* W,  C,  H,  S,  L, TL, strat */\n    { 19, 12, 13,  1,  6,  1, ZSTD_fast    },  /* base for negative levels */\n    { 19, 13, 14,  1,  7,  0, ZSTD_fast    },  /* level  1 */\n    { 20, 15, 16,  1,  6,  0, ZSTD_fast    },  /* level  2 */\n    { 21, 16, 17,  1,  5,  0, ZSTD_dfast   },  /* level  3 */\n    { 21, 18, 18,  1,  5,  0, ZSTD_dfast   },  /* level  4 */\n    { 21, 18, 19,  3,  5,  2, ZSTD_greedy  },  /* level  5 */\n    { 21, 18, 19,  3,  5,  4, ZSTD_lazy    },  /* level  6 */\n    { 21, 19, 20,  4,  5,  8, ZSTD_lazy    },  /* level  7 */\n    { 21, 19, 20,  4,  5, 16, ZSTD_lazy2   },  /* level  8 */\n    { 22, 20, 21,  4,  5, 16, ZSTD_lazy2   },  /* level  9 */\n    { 22, 21, 22,  5,  5, 16, ZSTD_lazy2   },  /* level 10 */\n    { 22, 21, 22,  6,  5, 16, ZSTD_lazy2   },  /* level 11 */\n    { 22, 22, 23,  6,  5, 32, ZSTD_lazy2   },  /* level 12 */\n    { 22, 22, 22,  4,  5, 32, ZSTD_btlazy2 },  /* level 13 */\n    { 22, 22, 23,  5,  5, 32, ZSTD_btlazy2 },  /* level 14 */\n    { 22, 23, 23,  6,  5, 32, ZSTD_btlazy2 },  /* level 15 */\n    { 22, 22, 22,  5,  5, 48, ZSTD_btopt   },  /* level 16 */\n    { 23, 23, 22,  5,  4, 64, ZSTD_btopt   },  /* level 17 */\n    { 23, 23, 22,  6,  3, 64, ZSTD_btultra },  /* level 18 */\n    { 23, 24, 22,  7,  3,256, ZSTD_btultra2},  /* level 19 */\n    { 25, 25, 23,  7,  3,256, ZSTD_btultra2},  /* level 20 */\n    { 26, 26, 24,  7,  3,512, ZSTD_btultra2},  /* level 21 */\n    { 27, 27, 25,  9,  3,999, ZSTD_btultra2},  /* level 22 */\n},\n{   /* for srcSize <= 256 KB */\n    /* W,  C,  H,  S,  L,  T, strat */\n    { 18, 12, 13,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */\n    { 18, 13, 14,  1,  6,  0, ZSTD_fast    },  /* level  1 */\n    { 18, 14, 14,  1,  5,  0, ZSTD_dfast   },  /* level  2 */\n    { 18, 16, 16,  1,  4,  0, ZSTD_dfast   },  /* level  3 */\n    { 18, 16, 17,  3,  5,  2, ZSTD_greedy  },  /* level  4.*/\n    { 18, 17, 18,  5,  5,  2, ZSTD_greedy  },  /* level  5.*/\n    { 18, 18, 19,  3,  5,  4, ZSTD_lazy    },  /* level  6.*/\n    { 18, 18, 19,  4,  4,  4, ZSTD_lazy    },  /* level  7 */\n    { 18, 18, 19,  4,  4,  8, ZSTD_lazy2   },  /* level  8 */\n    { 18, 18, 19,  5,  4,  8, ZSTD_lazy2   },  /* level  9 */\n    { 18, 18, 19,  6,  4,  8, ZSTD_lazy2   },  /* level 10 */\n    { 18, 18, 19,  5,  4, 12, ZSTD_btlazy2 },  /* level 11.*/\n    { 18, 19, 19,  7,  4, 12, ZSTD_btlazy2 },  /* level 12.*/\n    { 18, 18, 19,  4,  4, 16, ZSTD_btopt   },  /* level 13 */\n    { 18, 18, 19,  4,  3, 32, ZSTD_btopt   },  /* level 14.*/\n    { 18, 18, 19,  6,  3,128, ZSTD_btopt   },  /* level 15.*/\n    { 18, 19, 19,  6,  3,128, ZSTD_btultra },  /* level 16.*/\n    { 18, 19, 19,  8,  3,256, ZSTD_btultra },  /* level 17.*/\n    { 18, 19, 19,  6,  3,128, ZSTD_btultra2},  /* level 18.*/\n    { 18, 19, 19,  8,  3,256, ZSTD_btultra2},  /* level 19.*/\n    { 18, 19, 19, 10,  3,512, ZSTD_btultra2},  /* level 20.*/\n    { 18, 19, 19, 12,  3,512, ZSTD_btultra2},  /* level 21.*/\n    { 18, 19, 19, 13,  3,999, ZSTD_btultra2},  /* level 22.*/\n},\n{   /* for srcSize <= 128 KB */\n    /* W,  C,  H,  S,  L,  T, strat */\n    { 17, 12, 12,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */\n    { 17, 12, 13,  1,  6,  0, ZSTD_fast    },  /* level  1 */\n    { 17, 13, 15,  1,  5,  0, ZSTD_fast    },  /* level  2 */\n    { 17, 15, 16,  2,  5,  0, ZSTD_dfast   },  /* level  3 */\n    { 17, 17, 17,  2,  4,  0, ZSTD_dfast   },  /* level  4 */\n    { 17, 16, 17,  3,  4,  2, ZSTD_greedy  },  /* level  5 */\n    { 17, 16, 17,  3,  4,  4, ZSTD_lazy    },  /* level  6 */\n    { 17, 16, 17,  3,  4,  8, ZSTD_lazy2   },  /* level  7 */\n    { 17, 16, 17,  4,  4,  8, ZSTD_lazy2   },  /* level  8 */\n    { 17, 16, 17,  5,  4,  8, ZSTD_lazy2   },  /* level  9 */\n    { 17, 16, 17,  6,  4,  8, ZSTD_lazy2   },  /* level 10 */\n    { 17, 17, 17,  5,  4,  8, ZSTD_btlazy2 },  /* level 11 */\n    { 17, 18, 17,  7,  4, 12, ZSTD_btlazy2 },  /* level 12 */\n    { 17, 18, 17,  3,  4, 12, ZSTD_btopt   },  /* level 13.*/\n    { 17, 18, 17,  4,  3, 32, ZSTD_btopt   },  /* level 14.*/\n    { 17, 18, 17,  6,  3,256, ZSTD_btopt   },  /* level 15.*/\n    { 17, 18, 17,  6,  3,128, ZSTD_btultra },  /* level 16.*/\n    { 17, 18, 17,  8,  3,256, ZSTD_btultra },  /* level 17.*/\n    { 17, 18, 17, 10,  3,512, ZSTD_btultra },  /* level 18.*/\n    { 17, 18, 17,  5,  3,256, ZSTD_btultra2},  /* level 19.*/\n    { 17, 18, 17,  7,  3,512, ZSTD_btultra2},  /* level 20.*/\n    { 17, 18, 17,  9,  3,512, ZSTD_btultra2},  /* level 21.*/\n    { 17, 18, 17, 11,  3,999, ZSTD_btultra2},  /* level 22.*/\n},\n{   /* for srcSize <= 16 KB */\n    /* W,  C,  H,  S,  L,  T, strat */\n    { 14, 12, 13,  1,  5,  1, ZSTD_fast    },  /* base for negative levels */\n    { 14, 14, 15,  1,  5,  0, ZSTD_fast    },  /* level  1 */\n    { 14, 14, 15,  1,  4,  0, ZSTD_fast    },  /* level  2 */\n    { 14, 14, 15,  2,  4,  0, ZSTD_dfast   },  /* level  3 */\n    { 14, 14, 14,  4,  4,  2, ZSTD_greedy  },  /* level  4 */\n    { 14, 14, 14,  3,  4,  4, ZSTD_lazy    },  /* level  5.*/\n    { 14, 14, 14,  4,  4,  8, ZSTD_lazy2   },  /* level  6 */\n    { 14, 14, 14,  6,  4,  8, ZSTD_lazy2   },  /* level  7 */\n    { 14, 14, 14,  8,  4,  8, ZSTD_lazy2   },  /* level  8.*/\n    { 14, 15, 14,  5,  4,  8, ZSTD_btlazy2 },  /* level  9.*/\n    { 14, 15, 14,  9,  4,  8, ZSTD_btlazy2 },  /* level 10.*/\n    { 14, 15, 14,  3,  4, 12, ZSTD_btopt   },  /* level 11.*/\n    { 14, 15, 14,  4,  3, 24, ZSTD_btopt   },  /* level 12.*/\n    { 14, 15, 14,  5,  3, 32, ZSTD_btultra },  /* level 13.*/\n    { 14, 15, 15,  6,  3, 64, ZSTD_btultra },  /* level 14.*/\n    { 14, 15, 15,  7,  3,256, ZSTD_btultra },  /* level 15.*/\n    { 14, 15, 15,  5,  3, 48, ZSTD_btultra2},  /* level 16.*/\n    { 14, 15, 15,  6,  3,128, ZSTD_btultra2},  /* level 17.*/\n    { 14, 15, 15,  7,  3,256, ZSTD_btultra2},  /* level 18.*/\n    { 14, 15, 15,  8,  3,256, ZSTD_btultra2},  /* level 19.*/\n    { 14, 15, 15,  8,  3,512, ZSTD_btultra2},  /* level 20.*/\n    { 14, 15, 15,  9,  3,512, ZSTD_btultra2},  /* level 21.*/\n    { 14, 15, 15, 10,  3,999, ZSTD_btultra2},  /* level 22.*/\n},\n};\n\n\n\n#endif  /* ZSTD_CLEVELS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/fse_compress.c",
    "content": "﻿/* ******************************************************************\n * FSE : Finite State Entropy encoder\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include \"../common/compiler.h\"\n#include \"../common/mem.h\"        /* U32, U16, etc. */\n#include \"../common/debug.h\"      /* assert, DEBUGLOG */\n#include \"hist.h\"       /* HIST_count_wksp */\n#include \"../common/bitstream.h\"\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/error_private.h\"\n#define ZSTD_DEPS_NEED_MALLOC\n#define ZSTD_DEPS_NEED_MATH64\n#include \"../common/zstd_deps.h\"  /* ZSTD_memset */\n#include \"../common/bits.h\" /* ZSTD_highbit32 */\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_isError ERR_isError\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\n\n/* FSE_buildCTable_wksp() :\n * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).\n * wkspSize should be sized to handle worst case situation, which is `1<<max_tableLog * sizeof(FSE_FUNCTION_TYPE)`\n * workSpace must also be properly aligned with FSE_FUNCTION_TYPE requirements\n */\nsize_t FSE_buildCTable_wksp(FSE_CTable* ct,\n                      const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,\n                            void* workSpace, size_t wkspSize)\n{\n    U32 const tableSize = 1 << tableLog;\n    U32 const tableMask = tableSize - 1;\n    void* const ptr = ct;\n    U16* const tableU16 = ( (U16*) ptr) + 2;\n    void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;\n    FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);\n    U32 const step = FSE_TABLESTEP(tableSize);\n    U32 const maxSV1 = maxSymbolValue+1;\n\n    U16* cumul = (U16*)workSpace;   /* size = maxSV1 */\n    FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSV1+1));  /* size = tableSize */\n\n    U32 highThreshold = tableSize-1;\n\n    assert(((size_t)workSpace & 1) == 0);  /* Must be 2 bytes-aligned */\n    if (FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) > wkspSize) return ERROR(tableLog_tooLarge);\n    /* CTable header */\n    tableU16[-2] = (U16) tableLog;\n    tableU16[-1] = (U16) maxSymbolValue;\n    assert(tableLog < 16);   /* required for threshold strategy to work */\n\n    /* For explanations on how to distribute symbol values over the table :\n     * https://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */\n\n     #ifdef __clang_analyzer__\n     ZSTD_memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize);   /* useless initialization, just to keep scan-build happy */\n     #endif\n\n    /* symbol start positions */\n    {   U32 u;\n        cumul[0] = 0;\n        for (u=1; u <= maxSV1; u++) {\n            if (normalizedCounter[u-1]==-1) {  /* Low proba symbol */\n                cumul[u] = cumul[u-1] + 1;\n                tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1);\n            } else {\n                assert(normalizedCounter[u-1] >= 0);\n                cumul[u] = cumul[u-1] + (U16)normalizedCounter[u-1];\n                assert(cumul[u] >= cumul[u-1]);  /* no overflow */\n        }   }\n        cumul[maxSV1] = (U16)(tableSize+1);\n    }\n\n    /* Spread symbols */\n    if (highThreshold == tableSize - 1) {\n        /* Case for no low prob count symbols. Lay down 8 bytes at a time\n         * to reduce branch misses since we are operating on a small block\n         */\n        BYTE* const spread = tableSymbol + tableSize; /* size = tableSize + 8 (may write beyond tableSize) */\n        {   U64 const add = 0x0101010101010101ull;\n            size_t pos = 0;\n            U64 sv = 0;\n            U32 s;\n            for (s=0; s<maxSV1; ++s, sv += add) {\n                int i;\n                int const n = normalizedCounter[s];\n                MEM_write64(spread + pos, sv);\n                for (i = 8; i < n; i += 8) {\n                    MEM_write64(spread + pos + i, sv);\n                }\n                assert(n>=0);\n                pos += (size_t)n;\n            }\n        }\n        /* Spread symbols across the table. Lack of lowprob symbols means that\n         * we don't need variable sized inner loop, so we can unroll the loop and\n         * reduce branch misses.\n         */\n        {   size_t position = 0;\n            size_t s;\n            size_t const unroll = 2; /* Experimentally determined optimal unroll */\n            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */\n            for (s = 0; s < (size_t)tableSize; s += unroll) {\n                size_t u;\n                for (u = 0; u < unroll; ++u) {\n                    size_t const uPosition = (position + (u * step)) & tableMask;\n                    tableSymbol[uPosition] = spread[s + u];\n                }\n                position = (position + (unroll * step)) & tableMask;\n            }\n            assert(position == 0);   /* Must have initialized all positions */\n        }\n    } else {\n        U32 position = 0;\n        U32 symbol;\n        for (symbol=0; symbol<maxSV1; symbol++) {\n            int nbOccurrences;\n            int const freq = normalizedCounter[symbol];\n            for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {\n                tableSymbol[position] = (FSE_FUNCTION_TYPE)symbol;\n                position = (position + step) & tableMask;\n                while (position > highThreshold)\n                    position = (position + step) & tableMask;   /* Low proba area */\n        }   }\n        assert(position==0);  /* Must have initialized all positions */\n    }\n\n    /* Build table */\n    {   U32 u; for (u=0; u<tableSize; u++) {\n        FSE_FUNCTION_TYPE s = tableSymbol[u];   /* note : static analyzer may not understand tableSymbol is properly initialized */\n        tableU16[cumul[s]++] = (U16) (tableSize+u);   /* TableU16 : sorted by symbol order; gives next state value */\n    }   }\n\n    /* Build Symbol Transformation Table */\n    {   unsigned total = 0;\n        unsigned s;\n        for (s=0; s<=maxSymbolValue; s++) {\n            switch (normalizedCounter[s])\n            {\n            case  0:\n                /* filling nonetheless, for compatibility with FSE_getMaxNbBits() */\n                symbolTT[s].deltaNbBits = ((tableLog+1) << 16) - (1<<tableLog);\n                break;\n\n            case -1:\n            case  1:\n                symbolTT[s].deltaNbBits = (tableLog << 16) - (1<<tableLog);\n                assert(total <= INT_MAX);\n                symbolTT[s].deltaFindState = (int)(total - 1);\n                total ++;\n                break;\n            default :\n                assert(normalizedCounter[s] > 1);\n                {   U32 const maxBitsOut = tableLog - ZSTD_highbit32 ((U32)normalizedCounter[s]-1);\n                    U32 const minStatePlus = (U32)normalizedCounter[s] << maxBitsOut;\n                    symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;\n                    symbolTT[s].deltaFindState = (int)(total - (unsigned)normalizedCounter[s]);\n                    total +=  (unsigned)normalizedCounter[s];\n    }   }   }   }\n\n#if 0  /* debug : symbol costs */\n    DEBUGLOG(5, \"\\n --- table statistics : \");\n    {   U32 symbol;\n        for (symbol=0; symbol<=maxSymbolValue; symbol++) {\n            DEBUGLOG(5, \"%3u: w=%3i,   maxBits=%u, fracBits=%.2f\",\n                symbol, normalizedCounter[symbol],\n                FSE_getMaxNbBits(symbolTT, symbol),\n                (double)FSE_bitCost(symbolTT, tableLog, symbol, 8) / 256);\n    }   }\n#endif\n\n    return 0;\n}\n\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/*-**************************************************************\n*  FSE NCount encoding\n****************************************************************/\nsize_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)\n{\n    size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog\n                                   + 4 /* bitCount initialized at 4 */\n                                   + 2 /* first two symbols may use one additional bit each */) / 8)\n                                   + 1 /* round up to whole nb bytes */\n                                   + 2 /* additional two bytes for bitstream flush */;\n    return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND;  /* maxSymbolValue==0 ? use default */\n}\n\nstatic size_t\nFSE_writeNCount_generic (void* header, size_t headerBufferSize,\n                   const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,\n                         unsigned writeIsSafe)\n{\n    BYTE* const ostart = (BYTE*) header;\n    BYTE* out = ostart;\n    BYTE* const oend = ostart + headerBufferSize;\n    int nbBits;\n    const int tableSize = 1 << tableLog;\n    int remaining;\n    int threshold;\n    U32 bitStream = 0;\n    int bitCount = 0;\n    unsigned symbol = 0;\n    unsigned const alphabetSize = maxSymbolValue + 1;\n    int previousIs0 = 0;\n\n    /* Table Size */\n    bitStream += (tableLog-FSE_MIN_TABLELOG) << bitCount;\n    bitCount  += 4;\n\n    /* Init */\n    remaining = tableSize+1;   /* +1 for extra accuracy */\n    threshold = tableSize;\n    nbBits = (int)tableLog+1;\n\n    while ((symbol < alphabetSize) && (remaining>1)) {  /* stops at 1 */\n        if (previousIs0) {\n            unsigned start = symbol;\n            while ((symbol < alphabetSize) && !normalizedCounter[symbol]) symbol++;\n            if (symbol == alphabetSize) break;   /* incorrect distribution */\n            while (symbol >= start+24) {\n                start+=24;\n                bitStream += 0xFFFFU << bitCount;\n                if ((!writeIsSafe) && (out > oend-2))\n                    return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n                out[0] = (BYTE) bitStream;\n                out[1] = (BYTE)(bitStream>>8);\n                out+=2;\n                bitStream>>=16;\n            }\n            while (symbol >= start+3) {\n                start+=3;\n                bitStream += 3U << bitCount;\n                bitCount += 2;\n            }\n            bitStream += (symbol-start) << bitCount;\n            bitCount += 2;\n            if (bitCount>16) {\n                if ((!writeIsSafe) && (out > oend - 2))\n                    return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n                out[0] = (BYTE)bitStream;\n                out[1] = (BYTE)(bitStream>>8);\n                out += 2;\n                bitStream >>= 16;\n                bitCount -= 16;\n        }   }\n        {   int count = normalizedCounter[symbol++];\n            int const max = (2*threshold-1) - remaining;\n            remaining -= count < 0 ? -count : count;\n            count++;   /* +1 for extra accuracy */\n            if (count>=threshold)\n                count += max;   /* [0..max[ [max..threshold[ (...) [threshold+max 2*threshold[ */\n            bitStream += (U32)count << bitCount;\n            bitCount  += nbBits;\n            bitCount  -= (count<max);\n            previousIs0  = (count==1);\n            if (remaining<1) return ERROR(GENERIC);\n            while (remaining<threshold) { nbBits--; threshold>>=1; }\n        }\n        if (bitCount>16) {\n            if ((!writeIsSafe) && (out > oend - 2))\n                return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n            out[0] = (BYTE)bitStream;\n            out[1] = (BYTE)(bitStream>>8);\n            out += 2;\n            bitStream >>= 16;\n            bitCount -= 16;\n    }   }\n\n    if (remaining != 1)\n        return ERROR(GENERIC);  /* incorrect normalized distribution */\n    assert(symbol <= alphabetSize);\n\n    /* flush remaining bitStream */\n    if ((!writeIsSafe) && (out > oend - 2))\n        return ERROR(dstSize_tooSmall);   /* Buffer overflow */\n    out[0] = (BYTE)bitStream;\n    out[1] = (BYTE)(bitStream>>8);\n    out+= (bitCount+7) /8;\n\n    assert(out >= ostart);\n    return (size_t)(out-ostart);\n}\n\n\nsize_t FSE_writeNCount (void* buffer, size_t bufferSize,\n                  const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);   /* Unsupported */\n    if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC);   /* Unsupported */\n\n    if (bufferSize < FSE_NCountWriteBound(maxSymbolValue, tableLog))\n        return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 0);\n\n    return FSE_writeNCount_generic(buffer, bufferSize, normalizedCounter, maxSymbolValue, tableLog, 1 /* write in buffer is safe */);\n}\n\n\n/*-**************************************************************\n*  FSE Compression Code\n****************************************************************/\n\n/* provides the minimum logSize to safely represent a distribution */\nstatic unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue)\n{\n    U32 minBitsSrc = ZSTD_highbit32((U32)(srcSize)) + 1;\n    U32 minBitsSymbols = ZSTD_highbit32(maxSymbolValue) + 2;\n    U32 minBits = minBitsSrc < minBitsSymbols ? minBitsSrc : minBitsSymbols;\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    return minBits;\n}\n\nunsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus)\n{\n    U32 maxBitsSrc = ZSTD_highbit32((U32)(srcSize - 1)) - minus;\n    U32 tableLog = maxTableLog;\n    U32 minBits = FSE_minTableLog(srcSize, maxSymbolValue);\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;\n    if (maxBitsSrc < tableLog) tableLog = maxBitsSrc;   /* Accuracy can be reduced */\n    if (minBits > tableLog) tableLog = minBits;   /* Need a minimum to safely represent all symbol values */\n    if (tableLog < FSE_MIN_TABLELOG) tableLog = FSE_MIN_TABLELOG;\n    if (tableLog > FSE_MAX_TABLELOG) tableLog = FSE_MAX_TABLELOG;\n    return tableLog;\n}\n\nunsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue)\n{\n    return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2);\n}\n\n/* Secondary normalization method.\n   To be used when primary method fails. */\n\nstatic size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue, short lowProbCount)\n{\n    short const NOT_YET_ASSIGNED = -2;\n    U32 s;\n    U32 distributed = 0;\n    U32 ToDistribute;\n\n    /* Init */\n    U32 const lowThreshold = (U32)(total >> tableLog);\n    U32 lowOne = (U32)((total * 3) >> (tableLog + 1));\n\n    for (s=0; s<=maxSymbolValue; s++) {\n        if (count[s] == 0) {\n            norm[s]=0;\n            continue;\n        }\n        if (count[s] <= lowThreshold) {\n            norm[s] = lowProbCount;\n            distributed++;\n            total -= count[s];\n            continue;\n        }\n        if (count[s] <= lowOne) {\n            norm[s] = 1;\n            distributed++;\n            total -= count[s];\n            continue;\n        }\n\n        norm[s]=NOT_YET_ASSIGNED;\n    }\n    ToDistribute = (1 << tableLog) - distributed;\n\n    if (ToDistribute == 0)\n        return 0;\n\n    if ((total / ToDistribute) > lowOne) {\n        /* risk of rounding to zero */\n        lowOne = (U32)((total * 3) / (ToDistribute * 2));\n        for (s=0; s<=maxSymbolValue; s++) {\n            if ((norm[s] == NOT_YET_ASSIGNED) && (count[s] <= lowOne)) {\n                norm[s] = 1;\n                distributed++;\n                total -= count[s];\n                continue;\n        }   }\n        ToDistribute = (1 << tableLog) - distributed;\n    }\n\n    if (distributed == maxSymbolValue+1) {\n        /* all values are pretty poor;\n           probably incompressible data (should have already been detected);\n           find max, then give all remaining points to max */\n        U32 maxV = 0, maxC = 0;\n        for (s=0; s<=maxSymbolValue; s++)\n            if (count[s] > maxC) { maxV=s; maxC=count[s]; }\n        norm[maxV] += (short)ToDistribute;\n        return 0;\n    }\n\n    if (total == 0) {\n        /* all of the symbols were low enough for the lowOne or lowThreshold */\n        for (s=0; ToDistribute > 0; s = (s+1)%(maxSymbolValue+1))\n            if (norm[s] > 0) { ToDistribute--; norm[s]++; }\n        return 0;\n    }\n\n    {   U64 const vStepLog = 62 - tableLog;\n        U64 const mid = (1ULL << (vStepLog-1)) - 1;\n        U64 const rStep = ZSTD_div64((((U64)1<<vStepLog) * ToDistribute) + mid, (U32)total);   /* scale on remaining */\n        U64 tmpTotal = mid;\n        for (s=0; s<=maxSymbolValue; s++) {\n            if (norm[s]==NOT_YET_ASSIGNED) {\n                U64 const end = tmpTotal + (count[s] * rStep);\n                U32 const sStart = (U32)(tmpTotal >> vStepLog);\n                U32 const sEnd = (U32)(end >> vStepLog);\n                U32 const weight = sEnd - sStart;\n                if (weight < 1)\n                    return ERROR(GENERIC);\n                norm[s] = (short)weight;\n                tmpTotal = end;\n    }   }   }\n\n    return 0;\n}\n\nsize_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog,\n                           const unsigned* count, size_t total,\n                           unsigned maxSymbolValue, unsigned useLowProbCount)\n{\n    /* Sanity checks */\n    if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG;\n    if (tableLog < FSE_MIN_TABLELOG) return ERROR(GENERIC);   /* Unsupported size */\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);   /* Unsupported size */\n    if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC);   /* Too small tableLog, compression potentially impossible */\n\n    {   static U32 const rtbTable[] = {     0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 };\n        short const lowProbCount = useLowProbCount ? -1 : 1;\n        U64 const scale = 62 - tableLog;\n        U64 const step = ZSTD_div64((U64)1<<62, (U32)total);   /* <== here, one division ! */\n        U64 const vStep = 1ULL<<(scale-20);\n        int stillToDistribute = 1<<tableLog;\n        unsigned s;\n        unsigned largest=0;\n        short largestP=0;\n        U32 lowThreshold = (U32)(total >> tableLog);\n\n        for (s=0; s<=maxSymbolValue; s++) {\n            if (count[s] == total) return 0;   /* rle special case */\n            if (count[s] == 0) { normalizedCounter[s]=0; continue; }\n            if (count[s] <= lowThreshold) {\n                normalizedCounter[s] = lowProbCount;\n                stillToDistribute--;\n            } else {\n                short proba = (short)((count[s]*step) >> scale);\n                if (proba<8) {\n                    U64 restToBeat = vStep * rtbTable[proba];\n                    proba += (count[s]*step) - ((U64)proba<<scale) > restToBeat;\n                }\n                if (proba > largestP) { largestP=proba; largest=s; }\n                normalizedCounter[s] = proba;\n                stillToDistribute -= proba;\n        }   }\n        if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) {\n            /* corner case, need another normalization method */\n            size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue, lowProbCount);\n            if (FSE_isError(errorCode)) return errorCode;\n        }\n        else normalizedCounter[largest] += (short)stillToDistribute;\n    }\n\n#if 0\n    {   /* Print Table (debug) */\n        U32 s;\n        U32 nTotal = 0;\n        for (s=0; s<=maxSymbolValue; s++)\n            RAWLOG(2, \"%3i: %4i \\n\", s, normalizedCounter[s]);\n        for (s=0; s<=maxSymbolValue; s++)\n            nTotal += abs(normalizedCounter[s]);\n        if (nTotal != (1U<<tableLog))\n            RAWLOG(2, \"Warning !!! Total == %u != %u !!!\", nTotal, 1U<<tableLog);\n        getchar();\n    }\n#endif\n\n    return tableLog;\n}\n\n/* fake FSE_CTable, for rle input (always same symbol) */\nsize_t FSE_buildCTable_rle (FSE_CTable* ct, BYTE symbolValue)\n{\n    void* ptr = ct;\n    U16* tableU16 = ( (U16*) ptr) + 2;\n    void* FSCTptr = (U32*)ptr + 2;\n    FSE_symbolCompressionTransform* symbolTT = (FSE_symbolCompressionTransform*) FSCTptr;\n\n    /* header */\n    tableU16[-2] = (U16) 0;\n    tableU16[-1] = (U16) symbolValue;\n\n    /* Build table */\n    tableU16[0] = 0;\n    tableU16[1] = 0;   /* just in case */\n\n    /* Build Symbol Transformation Table */\n    symbolTT[symbolValue].deltaNbBits = 0;\n    symbolTT[symbolValue].deltaFindState = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_compress_usingCTable_generic (void* dst, size_t dstSize,\n                           const void* src, size_t srcSize,\n                           const FSE_CTable* ct, const unsigned fast)\n{\n    const BYTE* const istart = (const BYTE*) src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip=iend;\n\n    BIT_CStream_t bitC;\n    FSE_CState_t CState1, CState2;\n\n    /* init */\n    if (srcSize <= 2) return 0;\n    { size_t const initError = BIT_initCStream(&bitC, dst, dstSize);\n      if (FSE_isError(initError)) return 0; /* not enough space available to write a bitstream */ }\n\n#define FSE_FLUSHBITS(s)  (fast ? BIT_flushBitsFast(s) : BIT_flushBits(s))\n\n    if (srcSize & 1) {\n        FSE_initCState2(&CState1, ct, *--ip);\n        FSE_initCState2(&CState2, ct, *--ip);\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        FSE_FLUSHBITS(&bitC);\n    } else {\n        FSE_initCState2(&CState2, ct, *--ip);\n        FSE_initCState2(&CState1, ct, *--ip);\n    }\n\n    /* join to mod 4 */\n    srcSize -= 2;\n    if ((sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) && (srcSize & 2)) {  /* test bit 2 */\n        FSE_encodeSymbol(&bitC, &CState2, *--ip);\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        FSE_FLUSHBITS(&bitC);\n    }\n\n    /* 2 or 4 encoding per loop */\n    while ( ip>istart ) {\n\n        FSE_encodeSymbol(&bitC, &CState2, *--ip);\n\n        if (sizeof(bitC.bitContainer)*8 < FSE_MAX_TABLELOG*2+7 )   /* this test must be static */\n            FSE_FLUSHBITS(&bitC);\n\n        FSE_encodeSymbol(&bitC, &CState1, *--ip);\n\n        if (sizeof(bitC.bitContainer)*8 > FSE_MAX_TABLELOG*4+7 ) {  /* this test must be static */\n            FSE_encodeSymbol(&bitC, &CState2, *--ip);\n            FSE_encodeSymbol(&bitC, &CState1, *--ip);\n        }\n\n        FSE_FLUSHBITS(&bitC);\n    }\n\n    FSE_flushCState(&bitC, &CState2);\n    FSE_flushCState(&bitC, &CState1);\n    return BIT_closeCStream(&bitC);\n}\n\nsize_t FSE_compress_usingCTable (void* dst, size_t dstSize,\n                           const void* src, size_t srcSize,\n                           const FSE_CTable* ct)\n{\n    unsigned const fast = (dstSize >= FSE_BLOCKBOUND(srcSize));\n\n    if (fast)\n        return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 1);\n    else\n        return FSE_compress_usingCTable_generic(dst, dstSize, src, srcSize, ct, 0);\n}\n\n\nsize_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); }\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/hist.c",
    "content": "﻿/* ******************************************************************\n * hist : Histogram functions\n * part of Finite State Entropy project\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* --- dependencies --- */\n#include \"../common/mem.h\"             /* U32, BYTE, etc. */\n#include \"../common/debug.h\"           /* assert, DEBUGLOG */\n#include \"../common/error_private.h\"   /* ERROR */\n#include \"hist.h\"\n\n\n/* --- Error management --- */\nunsigned HIST_isError(size_t code) { return ERR_isError(code); }\n\n/*-**************************************************************\n *  Histogram functions\n ****************************************************************/\nvoid HIST_add(unsigned* count, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const end = ip + srcSize;\n\n    while (ip<end) {\n        count[*ip++]++;\n    }\n}\n\nunsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,\n                           const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const end = ip + srcSize;\n    unsigned maxSymbolValue = *maxSymbolValuePtr;\n    unsigned largestCount=0;\n\n    ZSTD_memset(count, 0, (maxSymbolValue+1) * sizeof(*count));\n    if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; }\n\n    while (ip<end) {\n        assert(*ip <= maxSymbolValue);\n        count[*ip++]++;\n    }\n\n    while (!count[maxSymbolValue]) maxSymbolValue--;\n    *maxSymbolValuePtr = maxSymbolValue;\n\n    {   U32 s;\n        for (s=0; s<=maxSymbolValue; s++)\n            if (count[s] > largestCount) largestCount = count[s];\n    }\n\n    return largestCount;\n}\n\ntypedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e;\n\n/* HIST_count_parallel_wksp() :\n * store histogram into 4 intermediate tables, recombined at the end.\n * this design makes better use of OoO cpus,\n * and is noticeably faster when some values are heavily repeated.\n * But it needs some additional workspace for intermediate tables.\n * `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32.\n * @return : largest histogram frequency,\n *           or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */\nstatic size_t HIST_count_parallel_wksp(\n                                unsigned* count, unsigned* maxSymbolValuePtr,\n                                const void* source, size_t sourceSize,\n                                HIST_checkInput_e check,\n                                U32* const workSpace)\n{\n    const BYTE* ip = (const BYTE*)source;\n    const BYTE* const iend = ip+sourceSize;\n    size_t const countSize = (*maxSymbolValuePtr + 1) * sizeof(*count);\n    unsigned max=0;\n    U32* const Counting1 = workSpace;\n    U32* const Counting2 = Counting1 + 256;\n    U32* const Counting3 = Counting2 + 256;\n    U32* const Counting4 = Counting3 + 256;\n\n    /* safety checks */\n    assert(*maxSymbolValuePtr <= 255);\n    if (!sourceSize) {\n        ZSTD_memset(count, 0, countSize);\n        *maxSymbolValuePtr = 0;\n        return 0;\n    }\n    ZSTD_memset(workSpace, 0, 4*256*sizeof(unsigned));\n\n    /* by stripes of 16 bytes */\n    {   U32 cached = MEM_read32(ip); ip += 4;\n        while (ip < iend-15) {\n            U32 c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n            c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n            c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n            c = cached; cached = MEM_read32(ip); ip += 4;\n            Counting1[(BYTE) c     ]++;\n            Counting2[(BYTE)(c>>8) ]++;\n            Counting3[(BYTE)(c>>16)]++;\n            Counting4[       c>>24 ]++;\n        }\n        ip-=4;\n    }\n\n    /* finish last symbols */\n    while (ip<iend) Counting1[*ip++]++;\n\n    {   U32 s;\n        for (s=0; s<256; s++) {\n            Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s];\n            if (Counting1[s] > max) max = Counting1[s];\n    }   }\n\n    {   unsigned maxSymbolValue = 255;\n        while (!Counting1[maxSymbolValue]) maxSymbolValue--;\n        if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall);\n        *maxSymbolValuePtr = maxSymbolValue;\n        ZSTD_memmove(count, Counting1, countSize);   /* in case count & Counting1 are overlapping */\n    }\n    return (size_t)max;\n}\n\n/* HIST_countFast_wksp() :\n * Same as HIST_countFast(), but using an externally provided scratch buffer.\n * `workSpace` is a writable buffer which must be 4-bytes aligned,\n * `workSpaceSize` must be >= HIST_WKSP_SIZE\n */\nsize_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                          const void* source, size_t sourceSize,\n                          void* workSpace, size_t workSpaceSize)\n{\n    if (sourceSize < 1500) /* heuristic threshold */\n        return HIST_count_simple(count, maxSymbolValuePtr, source, sourceSize);\n    if ((size_t)workSpace & 3) return ERROR(GENERIC);  /* must be aligned on 4-bytes boundaries */\n    if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);\n    return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace);\n}\n\n/* HIST_count_wksp() :\n * Same as HIST_count(), but using an externally provided scratch buffer.\n * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */\nsize_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                       const void* source, size_t sourceSize,\n                       void* workSpace, size_t workSpaceSize)\n{\n    if ((size_t)workSpace & 3) return ERROR(GENERIC);  /* must be aligned on 4-bytes boundaries */\n    if (workSpaceSize < HIST_WKSP_SIZE) return ERROR(workSpace_tooSmall);\n    if (*maxSymbolValuePtr < 255)\n        return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, checkMaxSymbolValue, (U32*)workSpace);\n    *maxSymbolValuePtr = 255;\n    return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize);\n}\n\n#ifndef ZSTD_NO_UNUSED_FUNCTIONS\n/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */\nsize_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,\n                     const void* source, size_t sourceSize)\n{\n    unsigned tmpCounters[HIST_WKSP_SIZE_U32];\n    return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters));\n}\n\nsize_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,\n                 const void* src, size_t srcSize)\n{\n    unsigned tmpCounters[HIST_WKSP_SIZE_U32];\n    return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters));\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/hist.h",
    "content": "﻿/* ******************************************************************\n * hist : Histogram functions\n * part of Finite State Entropy project\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* --- dependencies --- */\n#include \"../common/zstd_deps.h\"   /* size_t */\n\n\n/* --- simple histogram functions --- */\n\n/*! HIST_count():\n *  Provides the precise count of each byte within a table 'count'.\n * 'count' is a table of unsigned int, of minimum size (*maxSymbolValuePtr+1).\n *  Updates *maxSymbolValuePtr with actual largest symbol value detected.\n * @return : count of the most frequent symbol (which isn't identified).\n *           or an error code, which can be tested using HIST_isError().\n *           note : if return == srcSize, there is only one symbol.\n */\nsize_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr,\n                  const void* src, size_t srcSize);\n\nunsigned HIST_isError(size_t code);  /**< tells if a return value is an error code */\n\n\n/* --- advanced histogram functions --- */\n\n#define HIST_WKSP_SIZE_U32 1024\n#define HIST_WKSP_SIZE    (HIST_WKSP_SIZE_U32 * sizeof(unsigned))\n/** HIST_count_wksp() :\n *  Same as HIST_count(), but using an externally provided scratch buffer.\n *  Benefit is this function will use very little stack space.\n * `workSpace` is a writable buffer which must be 4-bytes aligned,\n * `workSpaceSize` must be >= HIST_WKSP_SIZE\n */\nsize_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                       const void* src, size_t srcSize,\n                       void* workSpace, size_t workSpaceSize);\n\n/** HIST_countFast() :\n *  same as HIST_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr.\n *  This function is unsafe, and will segfault if any value within `src` is `> *maxSymbolValuePtr`\n */\nsize_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr,\n                      const void* src, size_t srcSize);\n\n/** HIST_countFast_wksp() :\n *  Same as HIST_countFast(), but using an externally provided scratch buffer.\n * `workSpace` is a writable buffer which must be 4-bytes aligned,\n * `workSpaceSize` must be >= HIST_WKSP_SIZE\n */\nsize_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr,\n                           const void* src, size_t srcSize,\n                           void* workSpace, size_t workSpaceSize);\n\n/*! HIST_count_simple() :\n *  Same as HIST_countFast(), this function is unsafe,\n *  and will segfault if any value within `src` is `> *maxSymbolValuePtr`.\n *  It is also a bit slower for large inputs.\n *  However, it does not need any additional memory (not even on stack).\n * @return : count of the most frequent symbol.\n *  Note this function doesn't produce any error (i.e. it must succeed).\n */\nunsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr,\n                           const void* src, size_t srcSize);\n\n/*! HIST_add() :\n *  Lowest level: just add nb of occurrences of characters from @src into @count.\n *  @count is not reset. @count array is presumed large enough (i.e. 1 KB).\n @  This function does not need any additional stack memory.\n */\nvoid HIST_add(unsigned* count, const void* src, size_t srcSize);\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/huf_compress.c",
    "content": "﻿/* ******************************************************************\n * Huffman encoder, part of New Generation Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *  - Public forum : https://groups.google.com/forum/#!forum/lz4c\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include \"../common/zstd_deps.h\"     /* ZSTD_memcpy, ZSTD_memset */\n#include \"../common/compiler.h\"\n#include \"../common/bitstream.h\"\n#include \"hist.h\"\n#define FSE_STATIC_LINKING_ONLY   /* FSE_optimalTableLog_internal */\n#include \"../common/fse.h\"        /* header compression */\n#include \"../common/huf.h\"\n#include \"../common/error_private.h\"\n#include \"../common/bits.h\"       /* ZSTD_highbit32 */\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_isError ERR_isError\n#define HUF_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Required declarations\n****************************************************************/\ntypedef struct nodeElt_s {\n    U32 count;\n    U16 parent;\n    BYTE byte;\n    BYTE nbBits;\n} nodeElt;\n\n\n/* **************************************************************\n*  Debug Traces\n****************************************************************/\n\n#if DEBUGLEVEL >= 2\n\nstatic size_t showU32(const U32* arr, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %u\", arr[u]); (void)arr;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n}\n\nstatic size_t HUF_getNbBits(HUF_CElt elt);\n\nstatic size_t showCTableBits(const HUF_CElt* ctable, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %zu\", HUF_getNbBits(ctable[u])); (void)ctable;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n\n}\n\nstatic size_t showHNodeSymbols(const nodeElt* hnode, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %u\", hnode[u].byte); (void)hnode;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n}\n\nstatic size_t showHNodeBits(const nodeElt* hnode, size_t size)\n{\n    size_t u;\n    for (u=0; u<size; u++) {\n        RAWLOG(6, \" %u\", hnode[u].nbBits); (void)hnode;\n    }\n    RAWLOG(6, \" \\n\");\n    return size;\n}\n\n#endif\n\n\n/* *******************************************************\n*  HUF : Huffman block compression\n*********************************************************/\n#define HUF_WORKSPACE_MAX_ALIGNMENT 8\n\nstatic void* HUF_alignUpWorkspace(void* workspace, size_t* workspaceSizePtr, size_t align)\n{\n    size_t const mask = align - 1;\n    size_t const rem = (size_t)workspace & mask;\n    size_t const add = (align - rem) & mask;\n    BYTE* const aligned = (BYTE*)workspace + add;\n    assert((align & (align - 1)) == 0); /* pow 2 */\n    assert(align <= HUF_WORKSPACE_MAX_ALIGNMENT);\n    if (*workspaceSizePtr >= add) {\n        assert(add < align);\n        assert(((size_t)aligned & mask) == 0);\n        *workspaceSizePtr -= add;\n        return aligned;\n    } else {\n        *workspaceSizePtr = 0;\n        return NULL;\n    }\n}\n\n\n/* HUF_compressWeights() :\n * Same as FSE_compress(), but dedicated to huff0's weights compression.\n * The use case needs much less stack memory.\n * Note : all elements within weightTable are supposed to be <= HUF_TABLELOG_MAX.\n */\n#define MAX_FSE_TABLELOG_FOR_HUFF_HEADER 6\n\ntypedef struct {\n    FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)];\n    U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)];\n    unsigned count[HUF_TABLELOG_MAX+1];\n    S16 norm[HUF_TABLELOG_MAX+1];\n} HUF_CompressWeightsWksp;\n\nstatic size_t\nHUF_compressWeights(void* dst, size_t dstSize,\n              const void* weightTable, size_t wtSize,\n                    void* workspace, size_t workspaceSize)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + dstSize;\n\n    unsigned maxSymbolValue = HUF_TABLELOG_MAX;\n    U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;\n    HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));\n\n    if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC);\n\n    /* init conditions */\n    if (wtSize <= 1) return 0;  /* Not compressible */\n\n    /* Scan input and build symbol stats */\n    {   unsigned const maxCount = HIST_count_simple(wksp->count, &maxSymbolValue, weightTable, wtSize);   /* never fails */\n        if (maxCount == wtSize) return 1;   /* only a single symbol in src : rle */\n        if (maxCount == 1) return 0;        /* each symbol present maximum once => not compressible */\n    }\n\n    tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue);\n    CHECK_F( FSE_normalizeCount(wksp->norm, tableLog, wksp->count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) );\n\n    /* Write table description header */\n    {   CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), wksp->norm, maxSymbolValue, tableLog) );\n        op += hSize;\n    }\n\n    /* Compress */\n    CHECK_F( FSE_buildCTable_wksp(wksp->CTable, wksp->norm, maxSymbolValue, tableLog, wksp->scratchBuffer, sizeof(wksp->scratchBuffer)) );\n    {   CHECK_V_F(cSize, FSE_compress_usingCTable(op, (size_t)(oend - op), weightTable, wtSize, wksp->CTable) );\n        if (cSize == 0) return 0;   /* not enough space for compressed data */\n        op += cSize;\n    }\n\n    return (size_t)(op-ostart);\n}\n\nstatic size_t HUF_getNbBits(HUF_CElt elt)\n{\n    return elt & 0xFF;\n}\n\nstatic size_t HUF_getNbBitsFast(HUF_CElt elt)\n{\n    return elt;\n}\n\nstatic size_t HUF_getValue(HUF_CElt elt)\n{\n    return elt & ~(size_t)0xFF;\n}\n\nstatic size_t HUF_getValueFast(HUF_CElt elt)\n{\n    return elt;\n}\n\nstatic void HUF_setNbBits(HUF_CElt* elt, size_t nbBits)\n{\n    assert(nbBits <= HUF_TABLELOG_ABSOLUTEMAX);\n    *elt = nbBits;\n}\n\nstatic void HUF_setValue(HUF_CElt* elt, size_t value)\n{\n    size_t const nbBits = HUF_getNbBits(*elt);\n    if (nbBits > 0) {\n        assert((value >> nbBits) == 0);\n        *elt |= value << (sizeof(HUF_CElt) * 8 - nbBits);\n    }\n}\n\nHUF_CTableHeader HUF_readCTableHeader(HUF_CElt const* ctable)\n{\n    HUF_CTableHeader header;\n    ZSTD_memcpy(&header, ctable, sizeof(header));\n    return header;\n}\n\nstatic void HUF_writeCTableHeader(HUF_CElt* ctable, U32 tableLog, U32 maxSymbolValue)\n{\n    HUF_CTableHeader header;\n    HUF_STATIC_ASSERT(sizeof(ctable[0]) == sizeof(header));\n    ZSTD_memset(&header, 0, sizeof(header));\n    assert(tableLog < 256);\n    header.tableLog = (BYTE)tableLog;\n    assert(maxSymbolValue < 256);\n    header.maxSymbolValue = (BYTE)maxSymbolValue;\n    ZSTD_memcpy(ctable, &header, sizeof(header));\n}\n\ntypedef struct {\n    HUF_CompressWeightsWksp wksp;\n    BYTE bitsToWeight[HUF_TABLELOG_MAX + 1];   /* precomputed conversion table */\n    BYTE huffWeight[HUF_SYMBOLVALUE_MAX];\n} HUF_WriteCTableWksp;\n\nsize_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,\n                            const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog,\n                            void* workspace, size_t workspaceSize)\n{\n    HUF_CElt const* const ct = CTable + 1;\n    BYTE* op = (BYTE*)dst;\n    U32 n;\n    HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));\n\n    HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE >= sizeof(HUF_WriteCTableWksp));\n\n    assert(HUF_readCTableHeader(CTable).maxSymbolValue == maxSymbolValue);\n    assert(HUF_readCTableHeader(CTable).tableLog == huffLog);\n\n    /* check conditions */\n    if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC);\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);\n\n    /* convert to weight */\n    wksp->bitsToWeight[0] = 0;\n    for (n=1; n<huffLog+1; n++)\n        wksp->bitsToWeight[n] = (BYTE)(huffLog + 1 - n);\n    for (n=0; n<maxSymbolValue; n++)\n        wksp->huffWeight[n] = wksp->bitsToWeight[HUF_getNbBits(ct[n])];\n\n    /* attempt weights compression by FSE */\n    if (maxDstSize < 1) return ERROR(dstSize_tooSmall);\n    {   CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, wksp->huffWeight, maxSymbolValue, &wksp->wksp, sizeof(wksp->wksp)) );\n        if ((hSize>1) & (hSize < maxSymbolValue/2)) {   /* FSE compressed */\n            op[0] = (BYTE)hSize;\n            return hSize+1;\n    }   }\n\n    /* write raw values as 4-bits (max : 15) */\n    if (maxSymbolValue > (256-128)) return ERROR(GENERIC);   /* should not happen : likely means source cannot be compressed */\n    if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall);   /* not enough space within dst buffer */\n    op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));\n    wksp->huffWeight[maxSymbolValue] = 0;   /* to be sure it doesn't cause msan issue in final combination */\n    for (n=0; n<maxSymbolValue; n+=2)\n        op[(n/2)+1] = (BYTE)((wksp->huffWeight[n] << 4) + wksp->huffWeight[n+1]);\n    return ((maxSymbolValue+1)/2) + 1;\n}\n\n\nsize_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned* hasZeroWeights)\n{\n    BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];   /* init not required, even though some static analyzer may complain */\n    U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n    HUF_CElt* const ct = CTable + 1;\n\n    /* get symbol weights */\n    CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));\n    *hasZeroWeights = (rankVal[0] > 0);\n\n    /* check result */\n    if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);\n\n    *maxSymbolValuePtr = nbSymbols - 1;\n\n    HUF_writeCTableHeader(CTable, tableLog, *maxSymbolValuePtr);\n\n    /* Prepare base value per rank */\n    {   U32 n, nextRankStart = 0;\n        for (n=1; n<=tableLog; n++) {\n            U32 curr = nextRankStart;\n            nextRankStart += (rankVal[n] << (n-1));\n            rankVal[n] = curr;\n    }   }\n\n    /* fill nbBits */\n    {   U32 n; for (n=0; n<nbSymbols; n++) {\n            const U32 w = huffWeight[n];\n            HUF_setNbBits(ct + n, (BYTE)(tableLog + 1 - w) & -(w != 0));\n    }   }\n\n    /* fill val */\n    {   U16 nbPerRank[HUF_TABLELOG_MAX+2]  = {0};  /* support w=0=>n=tableLog+1 */\n        U16 valPerRank[HUF_TABLELOG_MAX+2] = {0};\n        { U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[HUF_getNbBits(ct[n])]++; }\n        /* determine stating value per rank */\n        valPerRank[tableLog+1] = 0;   /* for w==0 */\n        {   U16 min = 0;\n            U32 n; for (n=tableLog; n>0; n--) {  /* start at n=tablelog <-> w=1 */\n                valPerRank[n] = min;     /* get starting value within each rank */\n                min += nbPerRank[n];\n                min >>= 1;\n        }   }\n        /* assign value within rank, symbol order */\n        { U32 n; for (n=0; n<nbSymbols; n++) HUF_setValue(ct + n, valPerRank[HUF_getNbBits(ct[n])]++); }\n    }\n\n    return readSize;\n}\n\nU32 HUF_getNbBitsFromCTable(HUF_CElt const* CTable, U32 symbolValue)\n{\n    const HUF_CElt* const ct = CTable + 1;\n    assert(symbolValue <= HUF_SYMBOLVALUE_MAX);\n    if (symbolValue > HUF_readCTableHeader(CTable).maxSymbolValue)\n        return 0;\n    return (U32)HUF_getNbBits(ct[symbolValue]);\n}\n\n\n/**\n * HUF_setMaxHeight():\n * Try to enforce @targetNbBits on the Huffman tree described in @huffNode.\n *\n * It attempts to convert all nodes with nbBits > @targetNbBits\n * to employ @targetNbBits instead. Then it adjusts the tree\n * so that it remains a valid canonical Huffman tree.\n *\n * @pre               The sum of the ranks of each symbol == 2^largestBits,\n *                    where largestBits == huffNode[lastNonNull].nbBits.\n * @post              The sum of the ranks of each symbol == 2^largestBits,\n *                    where largestBits is the return value (expected <= targetNbBits).\n *\n * @param huffNode    The Huffman tree modified in place to enforce targetNbBits.\n *                    It's presumed sorted, from most frequent to rarest symbol.\n * @param lastNonNull The symbol with the lowest count in the Huffman tree.\n * @param targetNbBits  The allowed number of bits, which the Huffman tree\n *                    may not respect. After this function the Huffman tree will\n *                    respect targetNbBits.\n * @return            The maximum number of bits of the Huffman tree after adjustment.\n */\nstatic U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 targetNbBits)\n{\n    const U32 largestBits = huffNode[lastNonNull].nbBits;\n    /* early exit : no elt > targetNbBits, so the tree is already valid. */\n    if (largestBits <= targetNbBits) return largestBits;\n\n    DEBUGLOG(5, \"HUF_setMaxHeight (targetNbBits = %u)\", targetNbBits);\n\n    /* there are several too large elements (at least >= 2) */\n    {   int totalCost = 0;\n        const U32 baseCost = 1 << (largestBits - targetNbBits);\n        int n = (int)lastNonNull;\n\n        /* Adjust any ranks > targetNbBits to targetNbBits.\n         * Compute totalCost, which is how far the sum of the ranks is\n         * we are over 2^largestBits after adjust the offending ranks.\n         */\n        while (huffNode[n].nbBits > targetNbBits) {\n            totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits));\n            huffNode[n].nbBits = (BYTE)targetNbBits;\n            n--;\n        }\n        /* n stops at huffNode[n].nbBits <= targetNbBits */\n        assert(huffNode[n].nbBits <= targetNbBits);\n        /* n end at index of smallest symbol using < targetNbBits */\n        while (huffNode[n].nbBits == targetNbBits) --n;\n\n        /* renorm totalCost from 2^largestBits to 2^targetNbBits\n         * note : totalCost is necessarily a multiple of baseCost */\n        assert(((U32)totalCost & (baseCost - 1)) == 0);\n        totalCost >>= (largestBits - targetNbBits);\n        assert(totalCost > 0);\n\n        /* repay normalized cost */\n        {   U32 const noSymbol = 0xF0F0F0F0;\n            U32 rankLast[HUF_TABLELOG_MAX+2];\n\n            /* Get pos of last (smallest = lowest cum. count) symbol per rank */\n            ZSTD_memset(rankLast, 0xF0, sizeof(rankLast));\n            {   U32 currentNbBits = targetNbBits;\n                int pos;\n                for (pos=n ; pos >= 0; pos--) {\n                    if (huffNode[pos].nbBits >= currentNbBits) continue;\n                    currentNbBits = huffNode[pos].nbBits;   /* < targetNbBits */\n                    rankLast[targetNbBits-currentNbBits] = (U32)pos;\n            }   }\n\n            while (totalCost > 0) {\n                /* Try to reduce the next power of 2 above totalCost because we\n                 * gain back half the rank.\n                 */\n                U32 nBitsToDecrease = ZSTD_highbit32((U32)totalCost) + 1;\n                for ( ; nBitsToDecrease > 1; nBitsToDecrease--) {\n                    U32 const highPos = rankLast[nBitsToDecrease];\n                    U32 const lowPos = rankLast[nBitsToDecrease-1];\n                    if (highPos == noSymbol) continue;\n                    /* Decrease highPos if no symbols of lowPos or if it is\n                     * not cheaper to remove 2 lowPos than highPos.\n                     */\n                    if (lowPos == noSymbol) break;\n                    {   U32 const highTotal = huffNode[highPos].count;\n                        U32 const lowTotal = 2 * huffNode[lowPos].count;\n                        if (highTotal <= lowTotal) break;\n                }   }\n                /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */\n                assert(rankLast[nBitsToDecrease] != noSymbol || nBitsToDecrease == 1);\n                /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */\n                while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol))\n                    nBitsToDecrease++;\n                assert(rankLast[nBitsToDecrease] != noSymbol);\n                /* Increase the number of bits to gain back half the rank cost. */\n                totalCost -= 1 << (nBitsToDecrease-1);\n                huffNode[rankLast[nBitsToDecrease]].nbBits++;\n\n                /* Fix up the new rank.\n                 * If the new rank was empty, this symbol is now its smallest.\n                 * Otherwise, this symbol will be the largest in the new rank so no adjustment.\n                 */\n                if (rankLast[nBitsToDecrease-1] == noSymbol)\n                    rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease];\n                /* Fix up the old rank.\n                 * If the symbol was at position 0, meaning it was the highest weight symbol in the tree,\n                 * it must be the only symbol in its rank, so the old rank now has no symbols.\n                 * Otherwise, since the Huffman nodes are sorted by count, the previous position is now\n                 * the smallest node in the rank. If the previous position belongs to a different rank,\n                 * then the rank is now empty.\n                 */\n                if (rankLast[nBitsToDecrease] == 0)    /* special case, reached largest symbol */\n                    rankLast[nBitsToDecrease] = noSymbol;\n                else {\n                    rankLast[nBitsToDecrease]--;\n                    if (huffNode[rankLast[nBitsToDecrease]].nbBits != targetNbBits-nBitsToDecrease)\n                        rankLast[nBitsToDecrease] = noSymbol;   /* this rank is now empty */\n                }\n            }   /* while (totalCost > 0) */\n\n            /* If we've removed too much weight, then we have to add it back.\n             * To avoid overshooting again, we only adjust the smallest rank.\n             * We take the largest nodes from the lowest rank 0 and move them\n             * to rank 1. There's guaranteed to be enough rank 0 symbols because\n             * TODO.\n             */\n            while (totalCost < 0) {  /* Sometimes, cost correction overshoot */\n                /* special case : no rank 1 symbol (using targetNbBits-1);\n                 * let's create one from largest rank 0 (using targetNbBits).\n                 */\n                if (rankLast[1] == noSymbol) {\n                    while (huffNode[n].nbBits == targetNbBits) n--;\n                    huffNode[n+1].nbBits--;\n                    assert(n >= 0);\n                    rankLast[1] = (U32)(n+1);\n                    totalCost++;\n                    continue;\n                }\n                huffNode[ rankLast[1] + 1 ].nbBits--;\n                rankLast[1]++;\n                totalCost ++;\n            }\n        }   /* repay normalized cost */\n    }   /* there are several too large elements (at least >= 2) */\n\n    return targetNbBits;\n}\n\ntypedef struct {\n    U16 base;\n    U16 curr;\n} rankPos;\n\ntypedef nodeElt huffNodeTable[2 * (HUF_SYMBOLVALUE_MAX + 1)];\n\n/* Number of buckets available for HUF_sort() */\n#define RANK_POSITION_TABLE_SIZE 192\n\ntypedef struct {\n  huffNodeTable huffNodeTbl;\n  rankPos rankPosition[RANK_POSITION_TABLE_SIZE];\n} HUF_buildCTable_wksp_tables;\n\n/* RANK_POSITION_DISTINCT_COUNT_CUTOFF == Cutoff point in HUF_sort() buckets for which we use log2 bucketing.\n * Strategy is to use as many buckets as possible for representing distinct\n * counts while using the remainder to represent all \"large\" counts.\n *\n * To satisfy this requirement for 192 buckets, we can do the following:\n * Let buckets 0-166 represent distinct counts of [0, 166]\n * Let buckets 166 to 192 represent all remaining counts up to RANK_POSITION_MAX_COUNT_LOG using log2 bucketing.\n */\n#define RANK_POSITION_MAX_COUNT_LOG 32\n#define RANK_POSITION_LOG_BUCKETS_BEGIN ((RANK_POSITION_TABLE_SIZE - 1) - RANK_POSITION_MAX_COUNT_LOG - 1 /* == 158 */)\n#define RANK_POSITION_DISTINCT_COUNT_CUTOFF (RANK_POSITION_LOG_BUCKETS_BEGIN + ZSTD_highbit32(RANK_POSITION_LOG_BUCKETS_BEGIN) /* == 166 */)\n\n/* Return the appropriate bucket index for a given count. See definition of\n * RANK_POSITION_DISTINCT_COUNT_CUTOFF for explanation of bucketing strategy.\n */\nstatic U32 HUF_getIndex(U32 const count) {\n    return (count < RANK_POSITION_DISTINCT_COUNT_CUTOFF)\n        ? count\n        : ZSTD_highbit32(count) + RANK_POSITION_LOG_BUCKETS_BEGIN;\n}\n\n/* Helper swap function for HUF_quickSortPartition() */\nstatic void HUF_swapNodes(nodeElt* a, nodeElt* b) {\n\tnodeElt tmp = *a;\n\t*a = *b;\n\t*b = tmp;\n}\n\n/* Returns 0 if the huffNode array is not sorted by descending count */\nMEM_STATIC int HUF_isSorted(nodeElt huffNode[], U32 const maxSymbolValue1) {\n    U32 i;\n    for (i = 1; i < maxSymbolValue1; ++i) {\n        if (huffNode[i].count > huffNode[i-1].count) {\n            return 0;\n        }\n    }\n    return 1;\n}\n\n/* Insertion sort by descending order */\nHINT_INLINE void HUF_insertionSort(nodeElt huffNode[], int const low, int const high) {\n    int i;\n    int const size = high-low+1;\n    huffNode += low;\n    for (i = 1; i < size; ++i) {\n        nodeElt const key = huffNode[i];\n        int j = i - 1;\n        while (j >= 0 && huffNode[j].count < key.count) {\n            huffNode[j + 1] = huffNode[j];\n            j--;\n        }\n        huffNode[j + 1] = key;\n    }\n}\n\n/* Pivot helper function for quicksort. */\nstatic int HUF_quickSortPartition(nodeElt arr[], int const low, int const high) {\n    /* Simply select rightmost element as pivot. \"Better\" selectors like\n     * median-of-three don't experimentally appear to have any benefit.\n     */\n    U32 const pivot = arr[high].count;\n    int i = low - 1;\n    int j = low;\n    for ( ; j < high; j++) {\n        if (arr[j].count > pivot) {\n            i++;\n            HUF_swapNodes(&arr[i], &arr[j]);\n        }\n    }\n    HUF_swapNodes(&arr[i + 1], &arr[high]);\n    return i + 1;\n}\n\n/* Classic quicksort by descending with partially iterative calls\n * to reduce worst case callstack size.\n */\nstatic void HUF_simpleQuickSort(nodeElt arr[], int low, int high) {\n    int const kInsertionSortThreshold = 8;\n    if (high - low < kInsertionSortThreshold) {\n        HUF_insertionSort(arr, low, high);\n        return;\n    }\n    while (low < high) {\n        int const idx = HUF_quickSortPartition(arr, low, high);\n        if (idx - low < high - idx) {\n            HUF_simpleQuickSort(arr, low, idx - 1);\n            low = idx + 1;\n        } else {\n            HUF_simpleQuickSort(arr, idx + 1, high);\n            high = idx - 1;\n        }\n    }\n}\n\n/**\n * HUF_sort():\n * Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order.\n * This is a typical bucket sorting strategy that uses either quicksort or insertion sort to sort each bucket.\n *\n * @param[out] huffNode       Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled.\n *                            Must have (maxSymbolValue + 1) entries.\n * @param[in]  count          Histogram of the symbols.\n * @param[in]  maxSymbolValue Maximum symbol value.\n * @param      rankPosition   This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries.\n */\nstatic void HUF_sort(nodeElt huffNode[], const unsigned count[], U32 const maxSymbolValue, rankPos rankPosition[]) {\n    U32 n;\n    U32 const maxSymbolValue1 = maxSymbolValue+1;\n\n    /* Compute base and set curr to base.\n     * For symbol s let lowerRank = HUF_getIndex(count[n]) and rank = lowerRank + 1.\n     * See HUF_getIndex to see bucketing strategy.\n     * We attribute each symbol to lowerRank's base value, because we want to know where\n     * each rank begins in the output, so for rank R we want to count ranks R+1 and above.\n     */\n    ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE);\n    for (n = 0; n < maxSymbolValue1; ++n) {\n        U32 lowerRank = HUF_getIndex(count[n]);\n        assert(lowerRank < RANK_POSITION_TABLE_SIZE - 1);\n        rankPosition[lowerRank].base++;\n    }\n\n    assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0);\n    /* Set up the rankPosition table */\n    for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) {\n        rankPosition[n-1].base += rankPosition[n].base;\n        rankPosition[n-1].curr = rankPosition[n-1].base;\n    }\n\n    /* Insert each symbol into their appropriate bucket, setting up rankPosition table. */\n    for (n = 0; n < maxSymbolValue1; ++n) {\n        U32 const c = count[n];\n        U32 const r = HUF_getIndex(c) + 1;\n        U32 const pos = rankPosition[r].curr++;\n        assert(pos < maxSymbolValue1);\n        huffNode[pos].count = c;\n        huffNode[pos].byte  = (BYTE)n;\n    }\n\n    /* Sort each bucket. */\n    for (n = RANK_POSITION_DISTINCT_COUNT_CUTOFF; n < RANK_POSITION_TABLE_SIZE - 1; ++n) {\n        int const bucketSize = rankPosition[n].curr - rankPosition[n].base;\n        U32 const bucketStartIdx = rankPosition[n].base;\n        if (bucketSize > 1) {\n            assert(bucketStartIdx < maxSymbolValue1);\n            HUF_simpleQuickSort(huffNode + bucketStartIdx, 0, bucketSize-1);\n        }\n    }\n\n    assert(HUF_isSorted(huffNode, maxSymbolValue1));\n}\n\n\n/** HUF_buildCTable_wksp() :\n *  Same as HUF_buildCTable(), but using externally allocated scratch buffer.\n *  `workSpace` must be aligned on 4-bytes boundaries, and be at least as large as sizeof(HUF_buildCTable_wksp_tables).\n */\n#define STARTNODE (HUF_SYMBOLVALUE_MAX+1)\n\n/* HUF_buildTree():\n * Takes the huffNode array sorted by HUF_sort() and builds an unlimited-depth Huffman tree.\n *\n * @param huffNode        The array sorted by HUF_sort(). Builds the Huffman tree in this array.\n * @param maxSymbolValue  The maximum symbol value.\n * @return                The smallest node in the Huffman tree (by count).\n */\nstatic int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue)\n{\n    nodeElt* const huffNode0 = huffNode - 1;\n    int nonNullRank;\n    int lowS, lowN;\n    int nodeNb = STARTNODE;\n    int n, nodeRoot;\n    DEBUGLOG(5, \"HUF_buildTree (alphabet size = %u)\", maxSymbolValue + 1);\n    /* init for parents */\n    nonNullRank = (int)maxSymbolValue;\n    while(huffNode[nonNullRank].count == 0) nonNullRank--;\n    lowS = nonNullRank; nodeRoot = nodeNb + lowS - 1; lowN = nodeNb;\n    huffNode[nodeNb].count = huffNode[lowS].count + huffNode[lowS-1].count;\n    huffNode[lowS].parent = huffNode[lowS-1].parent = (U16)nodeNb;\n    nodeNb++; lowS-=2;\n    for (n=nodeNb; n<=nodeRoot; n++) huffNode[n].count = (U32)(1U<<30);\n    huffNode0[0].count = (U32)(1U<<31);  /* fake entry, strong barrier */\n\n    /* create parents */\n    while (nodeNb <= nodeRoot) {\n        int const n1 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;\n        int const n2 = (huffNode[lowS].count < huffNode[lowN].count) ? lowS-- : lowN++;\n        huffNode[nodeNb].count = huffNode[n1].count + huffNode[n2].count;\n        huffNode[n1].parent = huffNode[n2].parent = (U16)nodeNb;\n        nodeNb++;\n    }\n\n    /* distribute weights (unlimited tree height) */\n    huffNode[nodeRoot].nbBits = 0;\n    for (n=nodeRoot-1; n>=STARTNODE; n--)\n        huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;\n    for (n=0; n<=nonNullRank; n++)\n        huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1;\n\n    DEBUGLOG(6, \"Initial distribution of bits completed (%zu sorted symbols)\", showHNodeBits(huffNode, maxSymbolValue+1));\n\n    return nonNullRank;\n}\n\n/**\n * HUF_buildCTableFromTree():\n * Build the CTable given the Huffman tree in huffNode.\n *\n * @param[out] CTable         The output Huffman CTable.\n * @param      huffNode       The Huffman tree.\n * @param      nonNullRank    The last and smallest node in the Huffman tree.\n * @param      maxSymbolValue The maximum symbol value.\n * @param      maxNbBits      The exact maximum number of bits used in the Huffman tree.\n */\nstatic void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits)\n{\n    HUF_CElt* const ct = CTable + 1;\n    /* fill result into ctable (val, nbBits) */\n    int n;\n    U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};\n    U16 valPerRank[HUF_TABLELOG_MAX+1] = {0};\n    int const alphabetSize = (int)(maxSymbolValue + 1);\n    for (n=0; n<=nonNullRank; n++)\n        nbPerRank[huffNode[n].nbBits]++;\n    /* determine starting value per rank */\n    {   U16 min = 0;\n        for (n=(int)maxNbBits; n>0; n--) {\n            valPerRank[n] = min;      /* get starting value within each rank */\n            min += nbPerRank[n];\n            min >>= 1;\n    }   }\n    for (n=0; n<alphabetSize; n++)\n        HUF_setNbBits(ct + huffNode[n].byte, huffNode[n].nbBits);   /* push nbBits per symbol, symbol order */\n    for (n=0; n<alphabetSize; n++)\n        HUF_setValue(ct + n, valPerRank[HUF_getNbBits(ct[n])]++);   /* assign value within rank, symbol order */\n\n    HUF_writeCTableHeader(CTable, maxNbBits, maxSymbolValue);\n}\n\nsize_t\nHUF_buildCTable_wksp(HUF_CElt* CTable, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits,\n                     void* workSpace, size_t wkspSize)\n{\n    HUF_buildCTable_wksp_tables* const wksp_tables =\n        (HUF_buildCTable_wksp_tables*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(U32));\n    nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;\n    nodeElt* const huffNode = huffNode0+1;\n    int nonNullRank;\n\n    HUF_STATIC_ASSERT(HUF_CTABLE_WORKSPACE_SIZE == sizeof(HUF_buildCTable_wksp_tables));\n\n    DEBUGLOG(5, \"HUF_buildCTable_wksp (alphabet size = %u)\", maxSymbolValue+1);\n\n    /* safety checks */\n    if (wkspSize < sizeof(HUF_buildCTable_wksp_tables))\n        return ERROR(workSpace_tooSmall);\n    if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX)\n        return ERROR(maxSymbolValue_tooLarge);\n    ZSTD_memset(huffNode0, 0, sizeof(huffNodeTable));\n\n    /* sort, decreasing order */\n    HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition);\n    DEBUGLOG(6, \"sorted symbols completed (%zu symbols)\", showHNodeSymbols(huffNode, maxSymbolValue+1));\n\n    /* build tree */\n    nonNullRank = HUF_buildTree(huffNode, maxSymbolValue);\n\n    /* determine and enforce maxTableLog */\n    maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits);\n    if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC);   /* check fit into table */\n\n    HUF_buildCTableFromTree(CTable, huffNode, nonNullRank, maxSymbolValue, maxNbBits);\n\n    return maxNbBits;\n}\n\nsize_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)\n{\n    HUF_CElt const* ct = CTable + 1;\n    size_t nbBits = 0;\n    int s;\n    for (s = 0; s <= (int)maxSymbolValue; ++s) {\n        nbBits += HUF_getNbBits(ct[s]) * count[s];\n    }\n    return nbBits >> 3;\n}\n\nint HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) {\n    HUF_CTableHeader header = HUF_readCTableHeader(CTable);\n    HUF_CElt const* ct = CTable + 1;\n    int bad = 0;\n    int s;\n\n    assert(header.tableLog <= HUF_TABLELOG_ABSOLUTEMAX);\n\n    if (header.maxSymbolValue < maxSymbolValue)\n        return 0;\n\n    for (s = 0; s <= (int)maxSymbolValue; ++s) {\n        bad |= (count[s] != 0) & (HUF_getNbBits(ct[s]) == 0);\n    }\n    return !bad;\n}\n\nsize_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }\n\n/** HUF_CStream_t:\n * Huffman uses its own BIT_CStream_t implementation.\n * There are three major differences from BIT_CStream_t:\n *   1. HUF_addBits() takes a HUF_CElt (size_t) which is\n *      the pair (nbBits, value) in the format:\n *      format:\n *        - Bits [0, 4)            = nbBits\n *        - Bits [4, 64 - nbBits)  = 0\n *        - Bits [64 - nbBits, 64) = value\n *   2. The bitContainer is built from the upper bits and\n *      right shifted. E.g. to add a new value of N bits\n *      you right shift the bitContainer by N, then or in\n *      the new value into the N upper bits.\n *   3. The bitstream has two bit containers. You can add\n *      bits to the second container and merge them into\n *      the first container.\n */\n\n#define HUF_BITS_IN_CONTAINER (sizeof(size_t) * 8)\n\ntypedef struct {\n    size_t bitContainer[2];\n    size_t bitPos[2];\n\n    BYTE* startPtr;\n    BYTE* ptr;\n    BYTE* endPtr;\n} HUF_CStream_t;\n\n/**! HUF_initCStream():\n * Initializes the bitstream.\n * @returns 0 or an error code.\n */\nstatic size_t HUF_initCStream(HUF_CStream_t* bitC,\n                                  void* startPtr, size_t dstCapacity)\n{\n    ZSTD_memset(bitC, 0, sizeof(*bitC));\n    bitC->startPtr = (BYTE*)startPtr;\n    bitC->ptr = bitC->startPtr;\n    bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer[0]);\n    if (dstCapacity <= sizeof(bitC->bitContainer[0])) return ERROR(dstSize_tooSmall);\n    return 0;\n}\n\n/*! HUF_addBits():\n * Adds the symbol stored in HUF_CElt elt to the bitstream.\n *\n * @param elt   The element we're adding. This is a (nbBits, value) pair.\n *              See the HUF_CStream_t docs for the format.\n * @param idx   Insert into the bitstream at this idx.\n * @param kFast This is a template parameter. If the bitstream is guaranteed\n *              to have at least 4 unused bits after this call it may be 1,\n *              otherwise it must be 0. HUF_addBits() is faster when fast is set.\n */\nFORCE_INLINE_TEMPLATE void HUF_addBits(HUF_CStream_t* bitC, HUF_CElt elt, int idx, int kFast)\n{\n    assert(idx <= 1);\n    assert(HUF_getNbBits(elt) <= HUF_TABLELOG_ABSOLUTEMAX);\n    /* This is efficient on x86-64 with BMI2 because shrx\n     * only reads the low 6 bits of the register. The compiler\n     * knows this and elides the mask. When fast is set,\n     * every operation can use the same value loaded from elt.\n     */\n    bitC->bitContainer[idx] >>= HUF_getNbBits(elt);\n    bitC->bitContainer[idx] |= kFast ? HUF_getValueFast(elt) : HUF_getValue(elt);\n    /* We only read the low 8 bits of bitC->bitPos[idx] so it\n     * doesn't matter that the high bits have noise from the value.\n     */\n    bitC->bitPos[idx] += HUF_getNbBitsFast(elt);\n    assert((bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER);\n    /* The last 4-bits of elt are dirty if fast is set,\n     * so we must not be overwriting bits that have already been\n     * inserted into the bit container.\n     */\n#if DEBUGLEVEL >= 1\n    {\n        size_t const nbBits = HUF_getNbBits(elt);\n        size_t const dirtyBits = nbBits == 0 ? 0 : ZSTD_highbit32((U32)nbBits) + 1;\n        (void)dirtyBits;\n        /* Middle bits are 0. */\n        assert(((elt >> dirtyBits) << (dirtyBits + nbBits)) == 0);\n        /* We didn't overwrite any bits in the bit container. */\n        assert(!kFast || (bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER);\n        (void)dirtyBits;\n    }\n#endif\n}\n\nFORCE_INLINE_TEMPLATE void HUF_zeroIndex1(HUF_CStream_t* bitC)\n{\n    bitC->bitContainer[1] = 0;\n    bitC->bitPos[1] = 0;\n}\n\n/*! HUF_mergeIndex1() :\n * Merges the bit container @ index 1 into the bit container @ index 0\n * and zeros the bit container @ index 1.\n */\nFORCE_INLINE_TEMPLATE void HUF_mergeIndex1(HUF_CStream_t* bitC)\n{\n    assert((bitC->bitPos[1] & 0xFF) < HUF_BITS_IN_CONTAINER);\n    bitC->bitContainer[0] >>= (bitC->bitPos[1] & 0xFF);\n    bitC->bitContainer[0] |= bitC->bitContainer[1];\n    bitC->bitPos[0] += bitC->bitPos[1];\n    assert((bitC->bitPos[0] & 0xFF) <= HUF_BITS_IN_CONTAINER);\n}\n\n/*! HUF_flushBits() :\n* Flushes the bits in the bit container @ index 0.\n*\n* @post bitPos will be < 8.\n* @param kFast If kFast is set then we must know a-priori that\n*              the bit container will not overflow.\n*/\nFORCE_INLINE_TEMPLATE void HUF_flushBits(HUF_CStream_t* bitC, int kFast)\n{\n    /* The upper bits of bitPos are noisy, so we must mask by 0xFF. */\n    size_t const nbBits = bitC->bitPos[0] & 0xFF;\n    size_t const nbBytes = nbBits >> 3;\n    /* The top nbBits bits of bitContainer are the ones we need. */\n    size_t const bitContainer = bitC->bitContainer[0] >> (HUF_BITS_IN_CONTAINER - nbBits);\n    /* Mask bitPos to account for the bytes we consumed. */\n    bitC->bitPos[0] &= 7;\n    assert(nbBits > 0);\n    assert(nbBits <= sizeof(bitC->bitContainer[0]) * 8);\n    assert(bitC->ptr <= bitC->endPtr);\n    MEM_writeLEST(bitC->ptr, bitContainer);\n    bitC->ptr += nbBytes;\n    assert(!kFast || bitC->ptr <= bitC->endPtr);\n    if (!kFast && bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;\n    /* bitContainer doesn't need to be modified because the leftover\n     * bits are already the top bitPos bits. And we don't care about\n     * noise in the lower values.\n     */\n}\n\n/*! HUF_endMark()\n * @returns The Huffman stream end mark: A 1-bit value = 1.\n */\nstatic HUF_CElt HUF_endMark(void)\n{\n    HUF_CElt endMark;\n    HUF_setNbBits(&endMark, 1);\n    HUF_setValue(&endMark, 1);\n    return endMark;\n}\n\n/*! HUF_closeCStream() :\n *  @return Size of CStream, in bytes,\n *          or 0 if it could not fit into dstBuffer */\nstatic size_t HUF_closeCStream(HUF_CStream_t* bitC)\n{\n    HUF_addBits(bitC, HUF_endMark(), /* idx */ 0, /* kFast */ 0);\n    HUF_flushBits(bitC, /* kFast */ 0);\n    {\n        size_t const nbBits = bitC->bitPos[0] & 0xFF;\n        if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */\n        return (size_t)(bitC->ptr - bitC->startPtr) + (nbBits > 0);\n    }\n}\n\nFORCE_INLINE_TEMPLATE void\nHUF_encodeSymbol(HUF_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable, int idx, int fast)\n{\n    HUF_addBits(bitCPtr, CTable[symbol], idx, fast);\n}\n\nFORCE_INLINE_TEMPLATE void\nHUF_compress1X_usingCTable_internal_body_loop(HUF_CStream_t* bitC,\n                                   const BYTE* ip, size_t srcSize,\n                                   const HUF_CElt* ct,\n                                   int kUnroll, int kFastFlush, int kLastFast)\n{\n    /* Join to kUnroll */\n    int n = (int)srcSize;\n    int rem = n % kUnroll;\n    if (rem > 0) {\n        for (; rem > 0; --rem) {\n            HUF_encodeSymbol(bitC, ip[--n], ct, 0, /* fast */ 0);\n        }\n        HUF_flushBits(bitC, kFastFlush);\n    }\n    assert(n % kUnroll == 0);\n\n    /* Join to 2 * kUnroll */\n    if (n % (2 * kUnroll)) {\n        int u;\n        for (u = 1; u < kUnroll; ++u) {\n            HUF_encodeSymbol(bitC, ip[n - u], ct, 0, 1);\n        }\n        HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, 0, kLastFast);\n        HUF_flushBits(bitC, kFastFlush);\n        n -= kUnroll;\n    }\n    assert(n % (2 * kUnroll) == 0);\n\n    for (; n>0; n-= 2 * kUnroll) {\n        /* Encode kUnroll symbols into the bitstream @ index 0. */\n        int u;\n        for (u = 1; u < kUnroll; ++u) {\n            HUF_encodeSymbol(bitC, ip[n - u], ct, /* idx */ 0, /* fast */ 1);\n        }\n        HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, /* idx */ 0, /* fast */ kLastFast);\n        HUF_flushBits(bitC, kFastFlush);\n        /* Encode kUnroll symbols into the bitstream @ index 1.\n         * This allows us to start filling the bit container\n         * without any data dependencies.\n         */\n        HUF_zeroIndex1(bitC);\n        for (u = 1; u < kUnroll; ++u) {\n            HUF_encodeSymbol(bitC, ip[n - kUnroll - u], ct, /* idx */ 1, /* fast */ 1);\n        }\n        HUF_encodeSymbol(bitC, ip[n - kUnroll - kUnroll], ct, /* idx */ 1, /* fast */ kLastFast);\n        /* Merge bitstream @ index 1 into the bitstream @ index 0 */\n        HUF_mergeIndex1(bitC);\n        HUF_flushBits(bitC, kFastFlush);\n    }\n    assert(n == 0);\n\n}\n\n/**\n * Returns a tight upper bound on the output space needed by Huffman\n * with 8 bytes buffer to handle over-writes. If the output is at least\n * this large we don't need to do bounds checks during Huffman encoding.\n */\nstatic size_t HUF_tightCompressBound(size_t srcSize, size_t tableLog)\n{\n    return ((srcSize * tableLog) >> 3) + 8;\n}\n\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,\n                                   const void* src, size_t srcSize,\n                                   const HUF_CElt* CTable)\n{\n    U32 const tableLog = HUF_readCTableHeader(CTable).tableLog;\n    HUF_CElt const* ct = CTable + 1;\n    const BYTE* ip = (const BYTE*) src;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    HUF_CStream_t bitC;\n\n    /* init */\n    if (dstSize < 8) return 0;   /* not enough space to compress */\n    { BYTE* op = ostart;\n      size_t const initErr = HUF_initCStream(&bitC, op, (size_t)(oend-op));\n      if (HUF_isError(initErr)) return 0; }\n\n    if (dstSize < HUF_tightCompressBound(srcSize, (size_t)tableLog) || tableLog > 11)\n        HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ MEM_32bits() ? 2 : 4, /* kFast */ 0, /* kLastFast */ 0);\n    else {\n        if (MEM_32bits()) {\n            switch (tableLog) {\n            case 11:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 10: ZSTD_FALLTHROUGH;\n            case 9: ZSTD_FALLTHROUGH;\n            case 8:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            case 7: ZSTD_FALLTHROUGH;\n            default:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 3, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            }\n        } else {\n            switch (tableLog) {\n            case 11:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 10:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            case 9:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 6, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 8:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 7, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 7:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 8, /* kFastFlush */ 1, /* kLastFast */ 0);\n                break;\n            case 6: ZSTD_FALLTHROUGH;\n            default:\n                HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 9, /* kFastFlush */ 1, /* kLastFast */ 1);\n                break;\n            }\n        }\n    }\n    assert(bitC.ptr <= bitC.endPtr);\n\n    return HUF_closeCStream(&bitC);\n}\n\n#if DYNAMIC_BMI2\n\nstatic BMI2_TARGET_ATTRIBUTE size_t\nHUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,\n                                   const void* src, size_t srcSize,\n                                   const HUF_CElt* CTable)\n{\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\nstatic size_t\nHUF_compress1X_usingCTable_internal_default(void* dst, size_t dstSize,\n                                      const void* src, size_t srcSize,\n                                      const HUF_CElt* CTable)\n{\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\nstatic size_t\nHUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, const int flags)\n{\n    if (flags & HUF_flags_bmi2) {\n        return HUF_compress1X_usingCTable_internal_bmi2(dst, dstSize, src, srcSize, CTable);\n    }\n    return HUF_compress1X_usingCTable_internal_default(dst, dstSize, src, srcSize, CTable);\n}\n\n#else\n\nstatic size_t\nHUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, const int flags)\n{\n    (void)flags;\n    return HUF_compress1X_usingCTable_internal_body(dst, dstSize, src, srcSize, CTable);\n}\n\n#endif\n\nsize_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags)\n{\n    return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags);\n}\n\nstatic size_t\nHUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,\n                              const void* src, size_t srcSize,\n                              const HUF_CElt* CTable, int flags)\n{\n    size_t const segmentSize = (srcSize+3)/4;   /* first 3 segments */\n    const BYTE* ip = (const BYTE*) src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart;\n\n    if (dstSize < 6 + 1 + 1 + 1 + 8) return 0;   /* minimum space to compress successfully */\n    if (srcSize < 12) return 0;   /* no saving possible : too small input */\n    op += 6;   /* jumpTable */\n\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        MEM_writeLE16(ostart, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        MEM_writeLE16(ostart+2, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        MEM_writeLE16(ostart+4, (U16)cSize);\n        op += cSize;\n    }\n\n    ip += segmentSize;\n    assert(op <= oend);\n    assert(ip <= iend);\n    {   CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, flags) );\n        if (cSize == 0 || cSize > 65535) return 0;\n        op += cSize;\n    }\n\n    return (size_t)(op-ostart);\n}\n\nsize_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int flags)\n{\n    return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, flags);\n}\n\ntypedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;\n\nstatic size_t HUF_compressCTable_internal(\n                BYTE* const ostart, BYTE* op, BYTE* const oend,\n                const void* src, size_t srcSize,\n                HUF_nbStreams_e nbStreams, const HUF_CElt* CTable, const int flags)\n{\n    size_t const cSize = (nbStreams==HUF_singleStream) ?\n                         HUF_compress1X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags) :\n                         HUF_compress4X_usingCTable_internal(op, (size_t)(oend - op), src, srcSize, CTable, flags);\n    if (HUF_isError(cSize)) { return cSize; }\n    if (cSize==0) { return 0; }   /* uncompressible */\n    op += cSize;\n    /* check compressibility */\n    assert(op >= ostart);\n    if ((size_t)(op-ostart) >= srcSize-1) { return 0; }\n    return (size_t)(op-ostart);\n}\n\ntypedef struct {\n    unsigned count[HUF_SYMBOLVALUE_MAX + 1];\n    HUF_CElt CTable[HUF_CTABLE_SIZE_ST(HUF_SYMBOLVALUE_MAX)];\n    union {\n        HUF_buildCTable_wksp_tables buildCTable_wksp;\n        HUF_WriteCTableWksp writeCTable_wksp;\n        U32 hist_wksp[HIST_WKSP_SIZE_U32];\n    } wksps;\n} HUF_compress_tables_t;\n\n#define SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE 4096\n#define SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO 10  /* Must be >= 2 */\n\nunsigned HUF_cardinality(const unsigned* count, unsigned maxSymbolValue)\n{\n    unsigned cardinality = 0;\n    unsigned i;\n\n    for (i = 0; i < maxSymbolValue + 1; i++) {\n        if (count[i] != 0) cardinality += 1;\n    }\n\n    return cardinality;\n}\n\nunsigned HUF_minTableLog(unsigned symbolCardinality)\n{\n    U32 minBitsSymbols = ZSTD_highbit32(symbolCardinality) + 1;\n    return minBitsSymbols;\n}\n\nunsigned HUF_optimalTableLog(\n            unsigned maxTableLog,\n            size_t srcSize,\n            unsigned maxSymbolValue,\n            void* workSpace, size_t wkspSize,\n            HUF_CElt* table,\n      const unsigned* count,\n            int flags)\n{\n    assert(srcSize > 1); /* Not supported, RLE should be used instead */\n    assert(wkspSize >= sizeof(HUF_buildCTable_wksp_tables));\n\n    if (!(flags & HUF_flags_optimalDepth)) {\n        /* cheap evaluation, based on FSE */\n        return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 1);\n    }\n\n    {   BYTE* dst = (BYTE*)workSpace + sizeof(HUF_WriteCTableWksp);\n        size_t dstSize = wkspSize - sizeof(HUF_WriteCTableWksp);\n        size_t hSize, newSize;\n        const unsigned symbolCardinality = HUF_cardinality(count, maxSymbolValue);\n        const unsigned minTableLog = HUF_minTableLog(symbolCardinality);\n        size_t optSize = ((size_t) ~0) - 1;\n        unsigned optLog = maxTableLog, optLogGuess;\n\n        DEBUGLOG(6, \"HUF_optimalTableLog: probing huf depth (srcSize=%zu)\", srcSize);\n\n        /* Search until size increases */\n        for (optLogGuess = minTableLog; optLogGuess <= maxTableLog; optLogGuess++) {\n            DEBUGLOG(7, \"checking for huffLog=%u\", optLogGuess);\n\n            {   size_t maxBits = HUF_buildCTable_wksp(table, count, maxSymbolValue, optLogGuess, workSpace, wkspSize);\n                if (ERR_isError(maxBits)) continue;\n\n                if (maxBits < optLogGuess && optLogGuess > minTableLog) break;\n\n                hSize = HUF_writeCTable_wksp(dst, dstSize, table, maxSymbolValue, (U32)maxBits, workSpace, wkspSize);\n            }\n\n            if (ERR_isError(hSize)) continue;\n\n            newSize = HUF_estimateCompressedSize(table, count, maxSymbolValue) + hSize;\n\n            if (newSize > optSize + 1) {\n                break;\n            }\n\n            if (newSize < optSize) {\n                optSize = newSize;\n                optLog = optLogGuess;\n            }\n        }\n        assert(optLog <= HUF_TABLELOG_MAX);\n        return optLog;\n    }\n}\n\n/* HUF_compress_internal() :\n * `workSpace_align4` must be aligned on 4-bytes boundaries,\n * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U64 unsigned */\nstatic size_t\nHUF_compress_internal (void* dst, size_t dstSize,\n                 const void* src, size_t srcSize,\n                       unsigned maxSymbolValue, unsigned huffLog,\n                       HUF_nbStreams_e nbStreams,\n                       void* workSpace, size_t wkspSize,\n                       HUF_CElt* oldHufTable, HUF_repeat* repeat, int flags)\n{\n    HUF_compress_tables_t* const table = (HUF_compress_tables_t*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(size_t));\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart;\n\n    DEBUGLOG(5, \"HUF_compress_internal (srcSize=%zu)\", srcSize);\n    HUF_STATIC_ASSERT(sizeof(*table) + HUF_WORKSPACE_MAX_ALIGNMENT <= HUF_WORKSPACE_SIZE);\n\n    /* checks & inits */\n    if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall);\n    if (!srcSize) return 0;  /* Uncompressed */\n    if (!dstSize) return 0;  /* cannot fit anything within dst budget */\n    if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);   /* current block size limit */\n    if (huffLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(maxSymbolValue_tooLarge);\n    if (!maxSymbolValue) maxSymbolValue = HUF_SYMBOLVALUE_MAX;\n    if (!huffLog) huffLog = HUF_TABLELOG_DEFAULT;\n\n    /* Heuristic : If old table is valid, use it for small inputs */\n    if ((flags & HUF_flags_preferRepeat) && repeat && *repeat == HUF_repeat_valid) {\n        return HUF_compressCTable_internal(ostart, op, oend,\n                                           src, srcSize,\n                                           nbStreams, oldHufTable, flags);\n    }\n\n    /* If uncompressible data is suspected, do a smaller sampling first */\n    DEBUG_STATIC_ASSERT(SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO >= 2);\n    if ((flags & HUF_flags_suspectUncompressible) && srcSize >= (SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE * SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO)) {\n        size_t largestTotal = 0;\n        DEBUGLOG(5, \"input suspected incompressible : sampling to check\");\n        {   unsigned maxSymbolValueBegin = maxSymbolValue;\n            CHECK_V_F(largestBegin, HIST_count_simple (table->count, &maxSymbolValueBegin, (const BYTE*)src, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) );\n            largestTotal += largestBegin;\n        }\n        {   unsigned maxSymbolValueEnd = maxSymbolValue;\n            CHECK_V_F(largestEnd, HIST_count_simple (table->count, &maxSymbolValueEnd, (const BYTE*)src + srcSize - SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) );\n            largestTotal += largestEnd;\n        }\n        if (largestTotal <= ((2 * SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) >> 7)+4) return 0;   /* heuristic : probably not compressible enough */\n    }\n\n    /* Scan input and build symbol stats */\n    {   CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->wksps.hist_wksp, sizeof(table->wksps.hist_wksp)) );\n        if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; }   /* single symbol, rle */\n        if (largest <= (srcSize >> 7)+4) return 0;   /* heuristic : probably not compressible enough */\n    }\n    DEBUGLOG(6, \"histogram detail completed (%zu symbols)\", showU32(table->count, maxSymbolValue+1));\n\n    /* Check validity of previous table */\n    if ( repeat\n      && *repeat == HUF_repeat_check\n      && !HUF_validateCTable(oldHufTable, table->count, maxSymbolValue)) {\n        *repeat = HUF_repeat_none;\n    }\n    /* Heuristic : use existing table for small inputs */\n    if ((flags & HUF_flags_preferRepeat) && repeat && *repeat != HUF_repeat_none) {\n        return HUF_compressCTable_internal(ostart, op, oend,\n                                           src, srcSize,\n                                           nbStreams, oldHufTable, flags);\n    }\n\n    /* Build Huffman Tree */\n    huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, &table->wksps, sizeof(table->wksps), table->CTable, table->count, flags);\n    {   size_t const maxBits = HUF_buildCTable_wksp(table->CTable, table->count,\n                                            maxSymbolValue, huffLog,\n                                            &table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp));\n        CHECK_F(maxBits);\n        huffLog = (U32)maxBits;\n        DEBUGLOG(6, \"bit distribution completed (%zu symbols)\", showCTableBits(table->CTable + 1, maxSymbolValue+1));\n    }\n\n    /* Write table description header */\n    {   CHECK_V_F(hSize, HUF_writeCTable_wksp(op, dstSize, table->CTable, maxSymbolValue, huffLog,\n                                              &table->wksps.writeCTable_wksp, sizeof(table->wksps.writeCTable_wksp)) );\n        /* Check if using previous huffman table is beneficial */\n        if (repeat && *repeat != HUF_repeat_none) {\n            size_t const oldSize = HUF_estimateCompressedSize(oldHufTable, table->count, maxSymbolValue);\n            size_t const newSize = HUF_estimateCompressedSize(table->CTable, table->count, maxSymbolValue);\n            if (oldSize <= hSize + newSize || hSize + 12 >= srcSize) {\n                return HUF_compressCTable_internal(ostart, op, oend,\n                                                   src, srcSize,\n                                                   nbStreams, oldHufTable, flags);\n        }   }\n\n        /* Use the new huffman table */\n        if (hSize + 12ul >= srcSize) { return 0; }\n        op += hSize;\n        if (repeat) { *repeat = HUF_repeat_none; }\n        if (oldHufTable)\n            ZSTD_memcpy(oldHufTable, table->CTable, sizeof(table->CTable));  /* Save new table */\n    }\n    return HUF_compressCTable_internal(ostart, op, oend,\n                                       src, srcSize,\n                                       nbStreams, table->CTable, flags);\n}\n\nsize_t HUF_compress1X_repeat (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize,\n                      HUF_CElt* hufTable, HUF_repeat* repeat, int flags)\n{\n    DEBUGLOG(5, \"HUF_compress1X_repeat (srcSize = %zu)\", srcSize);\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_singleStream,\n                                 workSpace, wkspSize, hufTable,\n                                 repeat, flags);\n}\n\n/* HUF_compress4X_repeat():\n * compress input using 4 streams.\n * consider skipping quickly\n * reuse an existing huffman compression table */\nsize_t HUF_compress4X_repeat (void* dst, size_t dstSize,\n                      const void* src, size_t srcSize,\n                      unsigned maxSymbolValue, unsigned huffLog,\n                      void* workSpace, size_t wkspSize,\n                      HUF_CElt* hufTable, HUF_repeat* repeat, int flags)\n{\n    DEBUGLOG(5, \"HUF_compress4X_repeat (srcSize = %zu)\", srcSize);\n    return HUF_compress_internal(dst, dstSize, src, srcSize,\n                                 maxSymbolValue, huffLog, HUF_fourStreams,\n                                 workSpace, wkspSize,\n                                 hufTable, repeat, flags);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */\n#include \"../common/zstd_deps.h\"  /* INT_MAX, ZSTD_memset, ZSTD_memcpy */\n#include \"../common/mem.h\"\n#include \"../common/error_private.h\"\n#include \"hist.h\"           /* HIST_countFast_wksp */\n#define FSE_STATIC_LINKING_ONLY   /* FSE_encodeSymbol */\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include \"zstd_compress_internal.h\"\n#include \"zstd_compress_sequences.h\"\n#include \"zstd_compress_literals.h\"\n#include \"zstd_fast.h\"\n#include \"zstd_double_fast.h\"\n#include \"zstd_lazy.h\"\n#include \"zstd_opt.h\"\n#include \"zstd_ldm.h\"\n#include \"zstd_compress_superblock.h\"\n#include  \"../common/bits.h\"      /* ZSTD_highbit32, ZSTD_rotateRight_U64 */\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * COMPRESS_HEAPMODE :\n * Select how default decompression function ZSTD_compress() allocates its context,\n * on stack (0, default), or into heap (1).\n * Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected.\n */\n#ifndef ZSTD_COMPRESS_HEAPMODE\n#  define ZSTD_COMPRESS_HEAPMODE 0\n#endif\n\n/*!\n * ZSTD_HASHLOG3_MAX :\n * Maximum size of the hash table dedicated to find 3-bytes matches,\n * in log format, aka 17 => 1 << 17 == 128Ki positions.\n * This structure is only used in zstd_opt.\n * Since allocation is centralized for all strategies, it has to be known here.\n * The actual (selected) size of the hash table is then stored in ZSTD_MatchState_t.hashLog3,\n * so that zstd_opt.c doesn't need to know about this constant.\n */\n#ifndef ZSTD_HASHLOG3_MAX\n#  define ZSTD_HASHLOG3_MAX 17\n#endif\n\n/*-*************************************\n*  Helper functions\n***************************************/\n/* ZSTD_compressBound()\n * Note that the result from this function is only valid for\n * the one-pass compression functions.\n * When employing the streaming mode,\n * if flushes are frequently altering the size of blocks,\n * the overhead from block headers can make the compressed data larger\n * than the return value of ZSTD_compressBound().\n */\nsize_t ZSTD_compressBound(size_t srcSize) {\n    size_t const r = ZSTD_COMPRESSBOUND(srcSize);\n    if (r==0) return ERROR(srcSize_wrong);\n    return r;\n}\n\n\n/*-*************************************\n*  Context memory management\n***************************************/\nstruct ZSTD_CDict_s {\n    const void* dictContent;\n    size_t dictContentSize;\n    ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */\n    U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */\n    ZSTD_cwksp workspace;\n    ZSTD_MatchState_t matchState;\n    ZSTD_compressedBlockState_t cBlockState;\n    ZSTD_customMem customMem;\n    U32 dictID;\n    int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */\n    ZSTD_ParamSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use\n                                           * row-based matchfinder. Unless the cdict is reloaded, we will use\n                                           * the same greedy/lazy matchfinder at compression time.\n                                           */\n};  /* typedef'd to ZSTD_CDict within \"zstd.h\" */\n\nZSTD_CCtx* ZSTD_createCCtx(void)\n{\n    return ZSTD_createCCtx_advanced(ZSTD_defaultCMem);\n}\n\nstatic void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)\n{\n    assert(cctx != NULL);\n    ZSTD_memset(cctx, 0, sizeof(*cctx));\n    cctx->customMem = memManager;\n    cctx->bmi2 = ZSTD_cpuSupportsBmi2();\n    {   size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);\n        assert(!ZSTD_isError(err));\n        (void)err;\n    }\n}\n\nZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem)\n{\n    ZSTD_STATIC_ASSERT(zcss_init==0);\n    ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1));\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n    {   ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem);\n        if (!cctx) return NULL;\n        ZSTD_initCCtx(cctx, customMem);\n        return cctx;\n    }\n}\n\nZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize)\n{\n    ZSTD_cwksp ws;\n    ZSTD_CCtx* cctx;\n    if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL;  /* minimum size */\n    if ((size_t)workspace & 7) return NULL;  /* must be 8-aligned */\n    ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);\n\n    cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx));\n    if (cctx == NULL) return NULL;\n\n    ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx));\n    ZSTD_cwksp_move(&cctx->workspace, &ws);\n    cctx->staticSize = workspaceSize;\n\n    /* statically sized space. tmpWorkspace never moves (but prev/next block swap places) */\n    if (!ZSTD_cwksp_check_available(&cctx->workspace, TMP_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL;\n    cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));\n    cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t));\n    cctx->tmpWorkspace = ZSTD_cwksp_reserve_object(&cctx->workspace, TMP_WORKSPACE_SIZE);\n    cctx->tmpWkspSize = TMP_WORKSPACE_SIZE;\n    cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());\n    return cctx;\n}\n\n/**\n * Clears and frees all of the dictionaries in the CCtx.\n */\nstatic void ZSTD_clearAllDicts(ZSTD_CCtx* cctx)\n{\n    ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem);\n    ZSTD_freeCDict(cctx->localDict.cdict);\n    ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict));\n    ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));\n    cctx->cdict = NULL;\n}\n\nstatic size_t ZSTD_sizeof_localDict(ZSTD_localDict dict)\n{\n    size_t const bufferSize = dict.dictBuffer != NULL ? dict.dictSize : 0;\n    size_t const cdictSize = ZSTD_sizeof_CDict(dict.cdict);\n    return bufferSize + cdictSize;\n}\n\nstatic void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)\n{\n    assert(cctx != NULL);\n    assert(cctx->staticSize == 0);\n    ZSTD_clearAllDicts(cctx);\n#ifdef ZSTD_MULTITHREAD\n    ZSTDMT_freeCCtx(cctx->mtctx); cctx->mtctx = NULL;\n#endif\n    ZSTD_cwksp_free(&cctx->workspace, cctx->customMem);\n}\n\nsize_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)\n{\n    DEBUGLOG(3, \"ZSTD_freeCCtx (address: %p)\", (void*)cctx);\n    if (cctx==NULL) return 0;   /* support free on NULL */\n    RETURN_ERROR_IF(cctx->staticSize, memory_allocation,\n                    \"not compatible with static CCtx\");\n    {   int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx);\n        ZSTD_freeCCtxContent(cctx);\n        if (!cctxInWorkspace) ZSTD_customFree(cctx, cctx->customMem);\n    }\n    return 0;\n}\n\n\nstatic size_t ZSTD_sizeof_mtctx(const ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    return ZSTDMT_sizeof_CCtx(cctx->mtctx);\n#else\n    (void)cctx;\n    return 0;\n#endif\n}\n\n\nsize_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx)\n{\n    if (cctx==NULL) return 0;   /* support sizeof on NULL */\n    /* cctx may be in the workspace */\n    return (cctx->workspace.workspace == cctx ? 0 : sizeof(*cctx))\n           + ZSTD_cwksp_sizeof(&cctx->workspace)\n           + ZSTD_sizeof_localDict(cctx->localDict)\n           + ZSTD_sizeof_mtctx(cctx);\n}\n\nsize_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs)\n{\n    return ZSTD_sizeof_CCtx(zcs);  /* same object */\n}\n\n/* private API call, for dictBuilder only */\nconst SeqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); }\n\n/* Returns true if the strategy supports using a row based matchfinder */\nstatic int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) {\n    return (strategy >= ZSTD_greedy && strategy <= ZSTD_lazy2);\n}\n\n/* Returns true if the strategy and useRowMatchFinder mode indicate that we will use the row based matchfinder\n * for this compression.\n */\nstatic int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_ParamSwitch_e mode) {\n    assert(mode != ZSTD_ps_auto);\n    return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_ps_enable);\n}\n\n/* Returns row matchfinder usage given an initial mode and cParams */\nstatic ZSTD_ParamSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_ParamSwitch_e mode,\n                                                         const ZSTD_compressionParameters* const cParams) {\n    if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */\n    mode = ZSTD_ps_disable;\n    if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode;\n    if (cParams->windowLog > 14) mode = ZSTD_ps_enable;\n    return mode;\n}\n\n/* Returns block splitter usage (generally speaking, when using slower/stronger compression modes) */\nstatic ZSTD_ParamSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_ParamSwitch_e mode,\n                                                        const ZSTD_compressionParameters* const cParams) {\n    if (mode != ZSTD_ps_auto) return mode;\n    return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17) ? ZSTD_ps_enable : ZSTD_ps_disable;\n}\n\n/* Returns 1 if the arguments indicate that we should allocate a chainTable, 0 otherwise */\nstatic int ZSTD_allocateChainTable(const ZSTD_strategy strategy,\n                                   const ZSTD_ParamSwitch_e useRowMatchFinder,\n                                   const U32 forDDSDict) {\n    assert(useRowMatchFinder != ZSTD_ps_auto);\n    /* We always should allocate a chaintable if we are allocating a matchstate for a DDS dictionary matchstate.\n     * We do not allocate a chaintable if we are using ZSTD_fast, or are using the row-based matchfinder.\n     */\n    return forDDSDict || ((strategy != ZSTD_fast) && !ZSTD_rowMatchFinderUsed(strategy, useRowMatchFinder));\n}\n\n/* Returns ZSTD_ps_enable if compression parameters are such that we should\n * enable long distance matching (wlog >= 27, strategy >= btopt).\n * Returns ZSTD_ps_disable otherwise.\n */\nstatic ZSTD_ParamSwitch_e ZSTD_resolveEnableLdm(ZSTD_ParamSwitch_e mode,\n                                 const ZSTD_compressionParameters* const cParams) {\n    if (mode != ZSTD_ps_auto) return mode;\n    return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable;\n}\n\nstatic int ZSTD_resolveExternalSequenceValidation(int mode) {\n    return mode;\n}\n\n/* Resolves maxBlockSize to the default if no value is present. */\nstatic size_t ZSTD_resolveMaxBlockSize(size_t maxBlockSize) {\n    if (maxBlockSize == 0) {\n        return ZSTD_BLOCKSIZE_MAX;\n    } else {\n        return maxBlockSize;\n    }\n}\n\nstatic ZSTD_ParamSwitch_e ZSTD_resolveExternalRepcodeSearch(ZSTD_ParamSwitch_e value, int cLevel) {\n    if (value != ZSTD_ps_auto) return value;\n    if (cLevel < 10) {\n        return ZSTD_ps_disable;\n    } else {\n        return ZSTD_ps_enable;\n    }\n}\n\n/* Returns 1 if compression parameters are such that CDict hashtable and chaintable indices are tagged.\n * If so, the tags need to be removed in ZSTD_resetCCtx_byCopyingCDict. */\nstatic int ZSTD_CDictIndicesAreTagged(const ZSTD_compressionParameters* const cParams) {\n    return cParams->strategy == ZSTD_fast || cParams->strategy == ZSTD_dfast;\n}\n\nstatic ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(\n        ZSTD_compressionParameters cParams)\n{\n    ZSTD_CCtx_params cctxParams;\n    /* should not matter, as all cParams are presumed properly defined */\n    ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT);\n    cctxParams.cParams = cParams;\n\n    /* Adjust advanced params according to cParams */\n    cctxParams.ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams.ldmParams.enableLdm, &cParams);\n    if (cctxParams.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams);\n        assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog);\n        assert(cctxParams.ldmParams.hashRateLog < 32);\n    }\n    cctxParams.postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams.postBlockSplitter, &cParams);\n    cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);\n    cctxParams.validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams.validateSequences);\n    cctxParams.maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams.maxBlockSize);\n    cctxParams.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams.searchForExternalRepcodes,\n                                                                             cctxParams.compressionLevel);\n    assert(!ZSTD_checkCParams(cParams));\n    return cctxParams;\n}\n\nstatic ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced(\n        ZSTD_customMem customMem)\n{\n    ZSTD_CCtx_params* params;\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n    params = (ZSTD_CCtx_params*)ZSTD_customCalloc(\n            sizeof(ZSTD_CCtx_params), customMem);\n    if (!params) { return NULL; }\n    ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);\n    params->customMem = customMem;\n    return params;\n}\n\nZSTD_CCtx_params* ZSTD_createCCtxParams(void)\n{\n    return ZSTD_createCCtxParams_advanced(ZSTD_defaultCMem);\n}\n\nsize_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params)\n{\n    if (params == NULL) { return 0; }\n    ZSTD_customFree(params, params->customMem);\n    return 0;\n}\n\nsize_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params)\n{\n    return ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT);\n}\n\nsize_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) {\n    RETURN_ERROR_IF(!cctxParams, GENERIC, \"NULL pointer!\");\n    ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));\n    cctxParams->compressionLevel = compressionLevel;\n    cctxParams->fParams.contentSizeFlag = 1;\n    return 0;\n}\n\n#define ZSTD_NO_CLEVEL 0\n\n/**\n * Initializes `cctxParams` from `params` and `compressionLevel`.\n * @param compressionLevel If params are derived from a compression level then that compression level, otherwise ZSTD_NO_CLEVEL.\n */\nstatic void\nZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams,\n                        const ZSTD_parameters* params,\n                              int compressionLevel)\n{\n    assert(!ZSTD_checkCParams(params->cParams));\n    ZSTD_memset(cctxParams, 0, sizeof(*cctxParams));\n    cctxParams->cParams = params->cParams;\n    cctxParams->fParams = params->fParams;\n    /* Should not matter, as all cParams are presumed properly defined.\n     * But, set it for tracing anyway.\n     */\n    cctxParams->compressionLevel = compressionLevel;\n    cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, &params->cParams);\n    cctxParams->postBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->postBlockSplitter, &params->cParams);\n    cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, &params->cParams);\n    cctxParams->validateSequences = ZSTD_resolveExternalSequenceValidation(cctxParams->validateSequences);\n    cctxParams->maxBlockSize = ZSTD_resolveMaxBlockSize(cctxParams->maxBlockSize);\n    cctxParams->searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(cctxParams->searchForExternalRepcodes, compressionLevel);\n    DEBUGLOG(4, \"ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d, useBlockSplitter=%d ldm=%d\",\n                cctxParams->useRowMatchFinder, cctxParams->postBlockSplitter, cctxParams->ldmParams.enableLdm);\n}\n\nsize_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)\n{\n    RETURN_ERROR_IF(!cctxParams, GENERIC, \"NULL pointer!\");\n    FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , \"\");\n    ZSTD_CCtxParams_init_internal(cctxParams, &params, ZSTD_NO_CLEVEL);\n    return 0;\n}\n\n/**\n * Sets cctxParams' cParams and fParams from params, but otherwise leaves them alone.\n * @param params Validated zstd parameters.\n */\nstatic void ZSTD_CCtxParams_setZstdParams(\n        ZSTD_CCtx_params* cctxParams, const ZSTD_parameters* params)\n{\n    assert(!ZSTD_checkCParams(params->cParams));\n    cctxParams->cParams = params->cParams;\n    cctxParams->fParams = params->fParams;\n    /* Should not matter, as all cParams are presumed properly defined.\n     * But, set it for tracing anyway.\n     */\n    cctxParams->compressionLevel = ZSTD_NO_CLEVEL;\n}\n\nZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)\n{\n    ZSTD_bounds bounds = { 0, 0, 0 };\n\n    switch(param)\n    {\n    case ZSTD_c_compressionLevel:\n        bounds.lowerBound = ZSTD_minCLevel();\n        bounds.upperBound = ZSTD_maxCLevel();\n        return bounds;\n\n    case ZSTD_c_windowLog:\n        bounds.lowerBound = ZSTD_WINDOWLOG_MIN;\n        bounds.upperBound = ZSTD_WINDOWLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_hashLog:\n        bounds.lowerBound = ZSTD_HASHLOG_MIN;\n        bounds.upperBound = ZSTD_HASHLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_chainLog:\n        bounds.lowerBound = ZSTD_CHAINLOG_MIN;\n        bounds.upperBound = ZSTD_CHAINLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_searchLog:\n        bounds.lowerBound = ZSTD_SEARCHLOG_MIN;\n        bounds.upperBound = ZSTD_SEARCHLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_minMatch:\n        bounds.lowerBound = ZSTD_MINMATCH_MIN;\n        bounds.upperBound = ZSTD_MINMATCH_MAX;\n        return bounds;\n\n    case ZSTD_c_targetLength:\n        bounds.lowerBound = ZSTD_TARGETLENGTH_MIN;\n        bounds.upperBound = ZSTD_TARGETLENGTH_MAX;\n        return bounds;\n\n    case ZSTD_c_strategy:\n        bounds.lowerBound = ZSTD_STRATEGY_MIN;\n        bounds.upperBound = ZSTD_STRATEGY_MAX;\n        return bounds;\n\n    case ZSTD_c_contentSizeFlag:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_checksumFlag:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_dictIDFlag:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_nbWorkers:\n        bounds.lowerBound = 0;\n#ifdef ZSTD_MULTITHREAD\n        bounds.upperBound = ZSTDMT_NBWORKERS_MAX;\n#else\n        bounds.upperBound = 0;\n#endif\n        return bounds;\n\n    case ZSTD_c_jobSize:\n        bounds.lowerBound = 0;\n#ifdef ZSTD_MULTITHREAD\n        bounds.upperBound = ZSTDMT_JOBSIZE_MAX;\n#else\n        bounds.upperBound = 0;\n#endif\n        return bounds;\n\n    case ZSTD_c_overlapLog:\n#ifdef ZSTD_MULTITHREAD\n        bounds.lowerBound = ZSTD_OVERLAPLOG_MIN;\n        bounds.upperBound = ZSTD_OVERLAPLOG_MAX;\n#else\n        bounds.lowerBound = 0;\n        bounds.upperBound = 0;\n#endif\n        return bounds;\n\n    case ZSTD_c_enableDedicatedDictSearch:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_enableLongDistanceMatching:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_ldmHashLog:\n        bounds.lowerBound = ZSTD_LDM_HASHLOG_MIN;\n        bounds.upperBound = ZSTD_LDM_HASHLOG_MAX;\n        return bounds;\n\n    case ZSTD_c_ldmMinMatch:\n        bounds.lowerBound = ZSTD_LDM_MINMATCH_MIN;\n        bounds.upperBound = ZSTD_LDM_MINMATCH_MAX;\n        return bounds;\n\n    case ZSTD_c_ldmBucketSizeLog:\n        bounds.lowerBound = ZSTD_LDM_BUCKETSIZELOG_MIN;\n        bounds.upperBound = ZSTD_LDM_BUCKETSIZELOG_MAX;\n        return bounds;\n\n    case ZSTD_c_ldmHashRateLog:\n        bounds.lowerBound = ZSTD_LDM_HASHRATELOG_MIN;\n        bounds.upperBound = ZSTD_LDM_HASHRATELOG_MAX;\n        return bounds;\n\n    /* experimental parameters */\n    case ZSTD_c_rsyncable:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_forceMaxWindow :\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_format:\n        ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);\n        bounds.lowerBound = ZSTD_f_zstd1;\n        bounds.upperBound = ZSTD_f_zstd1_magicless;   /* note : how to ensure at compile time that this is the highest value enum ? */\n        return bounds;\n\n    case ZSTD_c_forceAttachDict:\n        ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad);\n        bounds.lowerBound = ZSTD_dictDefaultAttach;\n        bounds.upperBound = ZSTD_dictForceLoad;       /* note : how to ensure at compile time that this is the highest value enum ? */\n        return bounds;\n\n    case ZSTD_c_literalCompressionMode:\n        ZSTD_STATIC_ASSERT(ZSTD_ps_auto < ZSTD_ps_enable && ZSTD_ps_enable < ZSTD_ps_disable);\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_targetCBlockSize:\n        bounds.lowerBound = ZSTD_TARGETCBLOCKSIZE_MIN;\n        bounds.upperBound = ZSTD_TARGETCBLOCKSIZE_MAX;\n        return bounds;\n\n    case ZSTD_c_srcSizeHint:\n        bounds.lowerBound = ZSTD_SRCSIZEHINT_MIN;\n        bounds.upperBound = ZSTD_SRCSIZEHINT_MAX;\n        return bounds;\n\n    case ZSTD_c_stableInBuffer:\n    case ZSTD_c_stableOutBuffer:\n        bounds.lowerBound = (int)ZSTD_bm_buffered;\n        bounds.upperBound = (int)ZSTD_bm_stable;\n        return bounds;\n\n    case ZSTD_c_blockDelimiters:\n        bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters;\n        bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters;\n        return bounds;\n\n    case ZSTD_c_validateSequences:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_splitAfterSequences:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_blockSplitterLevel:\n        bounds.lowerBound = 0;\n        bounds.upperBound = ZSTD_BLOCKSPLITTER_LEVEL_MAX;\n        return bounds;\n\n    case ZSTD_c_useRowMatchFinder:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_deterministicRefPrefix:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_prefetchCDictTables:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    case ZSTD_c_enableSeqProducerFallback:\n        bounds.lowerBound = 0;\n        bounds.upperBound = 1;\n        return bounds;\n\n    case ZSTD_c_maxBlockSize:\n        bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;\n        bounds.upperBound = ZSTD_BLOCKSIZE_MAX;\n        return bounds;\n\n    case ZSTD_c_repcodeResolution:\n        bounds.lowerBound = (int)ZSTD_ps_auto;\n        bounds.upperBound = (int)ZSTD_ps_disable;\n        return bounds;\n\n    default:\n        bounds.error = ERROR(parameter_unsupported);\n        return bounds;\n    }\n}\n\n/* ZSTD_cParam_clampBounds:\n * Clamps the value into the bounded range.\n */\nstatic size_t ZSTD_cParam_clampBounds(ZSTD_cParameter cParam, int* value)\n{\n    ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);\n    if (ZSTD_isError(bounds.error)) return bounds.error;\n    if (*value < bounds.lowerBound) *value = bounds.lowerBound;\n    if (*value > bounds.upperBound) *value = bounds.upperBound;\n    return 0;\n}\n\n#define BOUNDCHECK(cParam, val)                                       \\\n    do {                                                              \\\n        RETURN_ERROR_IF(!ZSTD_cParam_withinBounds(cParam,val),        \\\n                        parameter_outOfBound, \"Param out of bounds\"); \\\n    } while (0)\n\n\nstatic int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)\n{\n    switch(param)\n    {\n    case ZSTD_c_compressionLevel:\n    case ZSTD_c_hashLog:\n    case ZSTD_c_chainLog:\n    case ZSTD_c_searchLog:\n    case ZSTD_c_minMatch:\n    case ZSTD_c_targetLength:\n    case ZSTD_c_strategy:\n    case ZSTD_c_blockSplitterLevel:\n        return 1;\n\n    case ZSTD_c_format:\n    case ZSTD_c_windowLog:\n    case ZSTD_c_contentSizeFlag:\n    case ZSTD_c_checksumFlag:\n    case ZSTD_c_dictIDFlag:\n    case ZSTD_c_forceMaxWindow :\n    case ZSTD_c_nbWorkers:\n    case ZSTD_c_jobSize:\n    case ZSTD_c_overlapLog:\n    case ZSTD_c_rsyncable:\n    case ZSTD_c_enableDedicatedDictSearch:\n    case ZSTD_c_enableLongDistanceMatching:\n    case ZSTD_c_ldmHashLog:\n    case ZSTD_c_ldmMinMatch:\n    case ZSTD_c_ldmBucketSizeLog:\n    case ZSTD_c_ldmHashRateLog:\n    case ZSTD_c_forceAttachDict:\n    case ZSTD_c_literalCompressionMode:\n    case ZSTD_c_targetCBlockSize:\n    case ZSTD_c_srcSizeHint:\n    case ZSTD_c_stableInBuffer:\n    case ZSTD_c_stableOutBuffer:\n    case ZSTD_c_blockDelimiters:\n    case ZSTD_c_validateSequences:\n    case ZSTD_c_splitAfterSequences:\n    case ZSTD_c_useRowMatchFinder:\n    case ZSTD_c_deterministicRefPrefix:\n    case ZSTD_c_prefetchCDictTables:\n    case ZSTD_c_enableSeqProducerFallback:\n    case ZSTD_c_maxBlockSize:\n    case ZSTD_c_repcodeResolution:\n    default:\n        return 0;\n    }\n}\n\nsize_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setParameter (%i, %i)\", (int)param, value);\n    if (cctx->streamStage != zcss_init) {\n        if (ZSTD_isUpdateAuthorized(param)) {\n            cctx->cParamsChanged = 1;\n        } else {\n            RETURN_ERROR(stage_wrong, \"can only set params in cctx init stage\");\n    }   }\n\n    switch(param)\n    {\n    case ZSTD_c_nbWorkers:\n        RETURN_ERROR_IF((value!=0) && cctx->staticSize, parameter_unsupported,\n                        \"MT not compatible with static alloc\");\n        break;\n\n    case ZSTD_c_compressionLevel:\n    case ZSTD_c_windowLog:\n    case ZSTD_c_hashLog:\n    case ZSTD_c_chainLog:\n    case ZSTD_c_searchLog:\n    case ZSTD_c_minMatch:\n    case ZSTD_c_targetLength:\n    case ZSTD_c_strategy:\n    case ZSTD_c_ldmHashRateLog:\n    case ZSTD_c_format:\n    case ZSTD_c_contentSizeFlag:\n    case ZSTD_c_checksumFlag:\n    case ZSTD_c_dictIDFlag:\n    case ZSTD_c_forceMaxWindow:\n    case ZSTD_c_forceAttachDict:\n    case ZSTD_c_literalCompressionMode:\n    case ZSTD_c_jobSize:\n    case ZSTD_c_overlapLog:\n    case ZSTD_c_rsyncable:\n    case ZSTD_c_enableDedicatedDictSearch:\n    case ZSTD_c_enableLongDistanceMatching:\n    case ZSTD_c_ldmHashLog:\n    case ZSTD_c_ldmMinMatch:\n    case ZSTD_c_ldmBucketSizeLog:\n    case ZSTD_c_targetCBlockSize:\n    case ZSTD_c_srcSizeHint:\n    case ZSTD_c_stableInBuffer:\n    case ZSTD_c_stableOutBuffer:\n    case ZSTD_c_blockDelimiters:\n    case ZSTD_c_validateSequences:\n    case ZSTD_c_splitAfterSequences:\n    case ZSTD_c_blockSplitterLevel:\n    case ZSTD_c_useRowMatchFinder:\n    case ZSTD_c_deterministicRefPrefix:\n    case ZSTD_c_prefetchCDictTables:\n    case ZSTD_c_enableSeqProducerFallback:\n    case ZSTD_c_maxBlockSize:\n    case ZSTD_c_repcodeResolution:\n        break;\n\n    default: RETURN_ERROR(parameter_unsupported, \"unknown parameter\");\n    }\n    return ZSTD_CCtxParams_setParameter(&cctx->requestedParams, param, value);\n}\n\nsize_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,\n                                    ZSTD_cParameter param, int value)\n{\n    DEBUGLOG(4, \"ZSTD_CCtxParams_setParameter (%i, %i)\", (int)param, value);\n    switch(param)\n    {\n    case ZSTD_c_format :\n        BOUNDCHECK(ZSTD_c_format, value);\n        CCtxParams->format = (ZSTD_format_e)value;\n        return (size_t)CCtxParams->format;\n\n    case ZSTD_c_compressionLevel : {\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), \"\");\n        if (value == 0)\n            CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */\n        else\n            CCtxParams->compressionLevel = value;\n        if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel;\n        return 0;  /* return type (size_t) cannot represent negative values */\n    }\n\n    case ZSTD_c_windowLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_windowLog, value);\n        CCtxParams->cParams.windowLog = (U32)value;\n        return CCtxParams->cParams.windowLog;\n\n    case ZSTD_c_hashLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_hashLog, value);\n        CCtxParams->cParams.hashLog = (U32)value;\n        return CCtxParams->cParams.hashLog;\n\n    case ZSTD_c_chainLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_chainLog, value);\n        CCtxParams->cParams.chainLog = (U32)value;\n        return CCtxParams->cParams.chainLog;\n\n    case ZSTD_c_searchLog :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_searchLog, value);\n        CCtxParams->cParams.searchLog = (U32)value;\n        return (size_t)value;\n\n    case ZSTD_c_minMatch :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_minMatch, value);\n        CCtxParams->cParams.minMatch = (U32)value;\n        return CCtxParams->cParams.minMatch;\n\n    case ZSTD_c_targetLength :\n        BOUNDCHECK(ZSTD_c_targetLength, value);\n        CCtxParams->cParams.targetLength = (U32)value;\n        return CCtxParams->cParams.targetLength;\n\n    case ZSTD_c_strategy :\n        if (value!=0)   /* 0 => use default */\n            BOUNDCHECK(ZSTD_c_strategy, value);\n        CCtxParams->cParams.strategy = (ZSTD_strategy)value;\n        return (size_t)CCtxParams->cParams.strategy;\n\n    case ZSTD_c_contentSizeFlag :\n        /* Content size written in frame header _when known_ (default:1) */\n        DEBUGLOG(4, \"set content size flag = %u\", (value!=0));\n        CCtxParams->fParams.contentSizeFlag = value != 0;\n        return (size_t)CCtxParams->fParams.contentSizeFlag;\n\n    case ZSTD_c_checksumFlag :\n        /* A 32-bits content checksum will be calculated and written at end of frame (default:0) */\n        CCtxParams->fParams.checksumFlag = value != 0;\n        return (size_t)CCtxParams->fParams.checksumFlag;\n\n    case ZSTD_c_dictIDFlag : /* When applicable, dictionary's dictID is provided in frame header (default:1) */\n        DEBUGLOG(4, \"set dictIDFlag = %u\", (value!=0));\n        CCtxParams->fParams.noDictIDFlag = !value;\n        return !CCtxParams->fParams.noDictIDFlag;\n\n    case ZSTD_c_forceMaxWindow :\n        CCtxParams->forceWindow = (value != 0);\n        return (size_t)CCtxParams->forceWindow;\n\n    case ZSTD_c_forceAttachDict : {\n        const ZSTD_dictAttachPref_e pref = (ZSTD_dictAttachPref_e)value;\n        BOUNDCHECK(ZSTD_c_forceAttachDict, (int)pref);\n        CCtxParams->attachDictPref = pref;\n        return CCtxParams->attachDictPref;\n    }\n\n    case ZSTD_c_literalCompressionMode : {\n        const ZSTD_ParamSwitch_e lcm = (ZSTD_ParamSwitch_e)value;\n        BOUNDCHECK(ZSTD_c_literalCompressionMode, (int)lcm);\n        CCtxParams->literalCompressionMode = lcm;\n        return CCtxParams->literalCompressionMode;\n    }\n\n    case ZSTD_c_nbWorkers :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), \"\");\n        CCtxParams->nbWorkers = value;\n        return (size_t)(CCtxParams->nbWorkers);\n#endif\n\n    case ZSTD_c_jobSize :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        /* Adjust to the minimum non-default value. */\n        if (value != 0 && value < ZSTDMT_JOBSIZE_MIN)\n            value = ZSTDMT_JOBSIZE_MIN;\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), \"\");\n        assert(value >= 0);\n        CCtxParams->jobSize = (size_t)value;\n        return CCtxParams->jobSize;\n#endif\n\n    case ZSTD_c_overlapLog :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), \"\");\n        CCtxParams->overlapLog = value;\n        return (size_t)CCtxParams->overlapLog;\n#endif\n\n    case ZSTD_c_rsyncable :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR_IF(value!=0, parameter_unsupported, \"not compiled with multithreading\");\n        return 0;\n#else\n        FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(ZSTD_c_overlapLog, &value), \"\");\n        CCtxParams->rsyncable = value;\n        return (size_t)CCtxParams->rsyncable;\n#endif\n\n    case ZSTD_c_enableDedicatedDictSearch :\n        CCtxParams->enableDedicatedDictSearch = (value!=0);\n        return (size_t)CCtxParams->enableDedicatedDictSearch;\n\n    case ZSTD_c_enableLongDistanceMatching :\n        BOUNDCHECK(ZSTD_c_enableLongDistanceMatching, value);\n        CCtxParams->ldmParams.enableLdm = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->ldmParams.enableLdm;\n\n    case ZSTD_c_ldmHashLog :\n        if (value!=0)   /* 0 ==> auto */\n            BOUNDCHECK(ZSTD_c_ldmHashLog, value);\n        CCtxParams->ldmParams.hashLog = (U32)value;\n        return CCtxParams->ldmParams.hashLog;\n\n    case ZSTD_c_ldmMinMatch :\n        if (value!=0)   /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_ldmMinMatch, value);\n        CCtxParams->ldmParams.minMatchLength = (U32)value;\n        return CCtxParams->ldmParams.minMatchLength;\n\n    case ZSTD_c_ldmBucketSizeLog :\n        if (value!=0)   /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_ldmBucketSizeLog, value);\n        CCtxParams->ldmParams.bucketSizeLog = (U32)value;\n        return CCtxParams->ldmParams.bucketSizeLog;\n\n    case ZSTD_c_ldmHashRateLog :\n        if (value!=0)   /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_ldmHashRateLog, value);\n        CCtxParams->ldmParams.hashRateLog = (U32)value;\n        return CCtxParams->ldmParams.hashRateLog;\n\n    case ZSTD_c_targetCBlockSize :\n        if (value!=0) {  /* 0 ==> default */\n            value = MAX(value, ZSTD_TARGETCBLOCKSIZE_MIN);\n            BOUNDCHECK(ZSTD_c_targetCBlockSize, value);\n        }\n        CCtxParams->targetCBlockSize = (U32)value;\n        return CCtxParams->targetCBlockSize;\n\n    case ZSTD_c_srcSizeHint :\n        if (value!=0)    /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_srcSizeHint, value);\n        CCtxParams->srcSizeHint = value;\n        return (size_t)CCtxParams->srcSizeHint;\n\n    case ZSTD_c_stableInBuffer:\n        BOUNDCHECK(ZSTD_c_stableInBuffer, value);\n        CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value;\n        return CCtxParams->inBufferMode;\n\n    case ZSTD_c_stableOutBuffer:\n        BOUNDCHECK(ZSTD_c_stableOutBuffer, value);\n        CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value;\n        return CCtxParams->outBufferMode;\n\n    case ZSTD_c_blockDelimiters:\n        BOUNDCHECK(ZSTD_c_blockDelimiters, value);\n        CCtxParams->blockDelimiters = (ZSTD_SequenceFormat_e)value;\n        return CCtxParams->blockDelimiters;\n\n    case ZSTD_c_validateSequences:\n        BOUNDCHECK(ZSTD_c_validateSequences, value);\n        CCtxParams->validateSequences = value;\n        return (size_t)CCtxParams->validateSequences;\n\n    case ZSTD_c_splitAfterSequences:\n        BOUNDCHECK(ZSTD_c_splitAfterSequences, value);\n        CCtxParams->postBlockSplitter = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->postBlockSplitter;\n\n    case ZSTD_c_blockSplitterLevel:\n        BOUNDCHECK(ZSTD_c_blockSplitterLevel, value);\n        CCtxParams->preBlockSplitter_level = value;\n        return (size_t)CCtxParams->preBlockSplitter_level;\n\n    case ZSTD_c_useRowMatchFinder:\n        BOUNDCHECK(ZSTD_c_useRowMatchFinder, value);\n        CCtxParams->useRowMatchFinder = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->useRowMatchFinder;\n\n    case ZSTD_c_deterministicRefPrefix:\n        BOUNDCHECK(ZSTD_c_deterministicRefPrefix, value);\n        CCtxParams->deterministicRefPrefix = !!value;\n        return (size_t)CCtxParams->deterministicRefPrefix;\n\n    case ZSTD_c_prefetchCDictTables:\n        BOUNDCHECK(ZSTD_c_prefetchCDictTables, value);\n        CCtxParams->prefetchCDictTables = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->prefetchCDictTables;\n\n    case ZSTD_c_enableSeqProducerFallback:\n        BOUNDCHECK(ZSTD_c_enableSeqProducerFallback, value);\n        CCtxParams->enableMatchFinderFallback = value;\n        return (size_t)CCtxParams->enableMatchFinderFallback;\n\n    case ZSTD_c_maxBlockSize:\n        if (value!=0)    /* 0 ==> default */\n            BOUNDCHECK(ZSTD_c_maxBlockSize, value);\n        assert(value>=0);\n        CCtxParams->maxBlockSize = (size_t)value;\n        return CCtxParams->maxBlockSize;\n\n    case ZSTD_c_repcodeResolution:\n        BOUNDCHECK(ZSTD_c_repcodeResolution, value);\n        CCtxParams->searchForExternalRepcodes = (ZSTD_ParamSwitch_e)value;\n        return CCtxParams->searchForExternalRepcodes;\n\n    default: RETURN_ERROR(parameter_unsupported, \"unknown parameter\");\n    }\n}\n\nsize_t ZSTD_CCtx_getParameter(ZSTD_CCtx const* cctx, ZSTD_cParameter param, int* value)\n{\n    return ZSTD_CCtxParams_getParameter(&cctx->requestedParams, param, value);\n}\n\nsize_t ZSTD_CCtxParams_getParameter(\n        ZSTD_CCtx_params const* CCtxParams, ZSTD_cParameter param, int* value)\n{\n    switch(param)\n    {\n    case ZSTD_c_format :\n        *value = (int)CCtxParams->format;\n        break;\n    case ZSTD_c_compressionLevel :\n        *value = CCtxParams->compressionLevel;\n        break;\n    case ZSTD_c_windowLog :\n        *value = (int)CCtxParams->cParams.windowLog;\n        break;\n    case ZSTD_c_hashLog :\n        *value = (int)CCtxParams->cParams.hashLog;\n        break;\n    case ZSTD_c_chainLog :\n        *value = (int)CCtxParams->cParams.chainLog;\n        break;\n    case ZSTD_c_searchLog :\n        *value = (int)CCtxParams->cParams.searchLog;\n        break;\n    case ZSTD_c_minMatch :\n        *value = (int)CCtxParams->cParams.minMatch;\n        break;\n    case ZSTD_c_targetLength :\n        *value = (int)CCtxParams->cParams.targetLength;\n        break;\n    case ZSTD_c_strategy :\n        *value = (int)CCtxParams->cParams.strategy;\n        break;\n    case ZSTD_c_contentSizeFlag :\n        *value = CCtxParams->fParams.contentSizeFlag;\n        break;\n    case ZSTD_c_checksumFlag :\n        *value = CCtxParams->fParams.checksumFlag;\n        break;\n    case ZSTD_c_dictIDFlag :\n        *value = !CCtxParams->fParams.noDictIDFlag;\n        break;\n    case ZSTD_c_forceMaxWindow :\n        *value = CCtxParams->forceWindow;\n        break;\n    case ZSTD_c_forceAttachDict :\n        *value = (int)CCtxParams->attachDictPref;\n        break;\n    case ZSTD_c_literalCompressionMode :\n        *value = (int)CCtxParams->literalCompressionMode;\n        break;\n    case ZSTD_c_nbWorkers :\n#ifndef ZSTD_MULTITHREAD\n        assert(CCtxParams->nbWorkers == 0);\n#endif\n        *value = CCtxParams->nbWorkers;\n        break;\n    case ZSTD_c_jobSize :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR(parameter_unsupported, \"not compiled with multithreading\");\n#else\n        assert(CCtxParams->jobSize <= INT_MAX);\n        *value = (int)CCtxParams->jobSize;\n        break;\n#endif\n    case ZSTD_c_overlapLog :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR(parameter_unsupported, \"not compiled with multithreading\");\n#else\n        *value = CCtxParams->overlapLog;\n        break;\n#endif\n    case ZSTD_c_rsyncable :\n#ifndef ZSTD_MULTITHREAD\n        RETURN_ERROR(parameter_unsupported, \"not compiled with multithreading\");\n#else\n        *value = CCtxParams->rsyncable;\n        break;\n#endif\n    case ZSTD_c_enableDedicatedDictSearch :\n        *value = CCtxParams->enableDedicatedDictSearch;\n        break;\n    case ZSTD_c_enableLongDistanceMatching :\n        *value = (int)CCtxParams->ldmParams.enableLdm;\n        break;\n    case ZSTD_c_ldmHashLog :\n        *value = (int)CCtxParams->ldmParams.hashLog;\n        break;\n    case ZSTD_c_ldmMinMatch :\n        *value = (int)CCtxParams->ldmParams.minMatchLength;\n        break;\n    case ZSTD_c_ldmBucketSizeLog :\n        *value = (int)CCtxParams->ldmParams.bucketSizeLog;\n        break;\n    case ZSTD_c_ldmHashRateLog :\n        *value = (int)CCtxParams->ldmParams.hashRateLog;\n        break;\n    case ZSTD_c_targetCBlockSize :\n        *value = (int)CCtxParams->targetCBlockSize;\n        break;\n    case ZSTD_c_srcSizeHint :\n        *value = (int)CCtxParams->srcSizeHint;\n        break;\n    case ZSTD_c_stableInBuffer :\n        *value = (int)CCtxParams->inBufferMode;\n        break;\n    case ZSTD_c_stableOutBuffer :\n        *value = (int)CCtxParams->outBufferMode;\n        break;\n    case ZSTD_c_blockDelimiters :\n        *value = (int)CCtxParams->blockDelimiters;\n        break;\n    case ZSTD_c_validateSequences :\n        *value = (int)CCtxParams->validateSequences;\n        break;\n    case ZSTD_c_splitAfterSequences :\n        *value = (int)CCtxParams->postBlockSplitter;\n        break;\n    case ZSTD_c_blockSplitterLevel :\n        *value = CCtxParams->preBlockSplitter_level;\n        break;\n    case ZSTD_c_useRowMatchFinder :\n        *value = (int)CCtxParams->useRowMatchFinder;\n        break;\n    case ZSTD_c_deterministicRefPrefix:\n        *value = (int)CCtxParams->deterministicRefPrefix;\n        break;\n    case ZSTD_c_prefetchCDictTables:\n        *value = (int)CCtxParams->prefetchCDictTables;\n        break;\n    case ZSTD_c_enableSeqProducerFallback:\n        *value = CCtxParams->enableMatchFinderFallback;\n        break;\n    case ZSTD_c_maxBlockSize:\n        *value = (int)CCtxParams->maxBlockSize;\n        break;\n    case ZSTD_c_repcodeResolution:\n        *value = (int)CCtxParams->searchForExternalRepcodes;\n        break;\n    default: RETURN_ERROR(parameter_unsupported, \"unknown parameter\");\n    }\n    return 0;\n}\n\n/** ZSTD_CCtx_setParametersUsingCCtxParams() :\n *  just applies `params` into `cctx`\n *  no action is performed, parameters are merely stored.\n *  If ZSTDMT is enabled, parameters are pushed to cctx->mtctx.\n *    This is possible even if a compression is ongoing.\n *    In which case, new parameters will be applied on the fly, starting with next compression job.\n */\nsize_t ZSTD_CCtx_setParametersUsingCCtxParams(\n        ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setParametersUsingCCtxParams\");\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"The context is in the wrong stage!\");\n    RETURN_ERROR_IF(cctx->cdict, stage_wrong,\n                    \"Can't override parameters with cdict attached (some must \"\n                    \"be inherited from the cdict).\");\n\n    cctx->requestedParams = *params;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams)\n{\n    ZSTD_STATIC_ASSERT(sizeof(cparams) == 7 * 4 /* all params are listed below */);\n    DEBUGLOG(4, \"ZSTD_CCtx_setCParams\");\n    /* only update if all parameters are valid */\n    FORWARD_IF_ERROR(ZSTD_checkCParams(cparams), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_windowLog, (int)cparams.windowLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_chainLog, (int)cparams.chainLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_hashLog, (int)cparams.hashLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_searchLog, (int)cparams.searchLog), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_minMatch, (int)cparams.minMatch), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_targetLength, (int)cparams.targetLength), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_strategy, (int)cparams.strategy), \"\");\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams)\n{\n    ZSTD_STATIC_ASSERT(sizeof(fparams) == 3 * 4 /* all params are listed below */);\n    DEBUGLOG(4, \"ZSTD_CCtx_setFParams\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_contentSizeFlag, fparams.contentSizeFlag != 0), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, fparams.checksumFlag != 0), \"\");\n    FORWARD_IF_ERROR(ZSTD_CCtx_setParameter(cctx, ZSTD_c_dictIDFlag, fparams.noDictIDFlag == 0), \"\");\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setParams\");\n    /* First check cParams, because we want to update all or none. */\n    FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), \"\");\n    /* Next set fParams, because this could fail if the cctx isn't in init stage. */\n    FORWARD_IF_ERROR(ZSTD_CCtx_setFParams(cctx, params.fParams), \"\");\n    /* Finally set cParams, which should succeed. */\n    FORWARD_IF_ERROR(ZSTD_CCtx_setCParams(cctx, params.cParams), \"\");\n    return 0;\n}\n\nsize_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_setPledgedSrcSize to %llu bytes\", pledgedSrcSize);\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't set pledgedSrcSize when not in init stage.\");\n    cctx->pledgedSrcSizePlusOne = pledgedSrcSize+1;\n    return 0;\n}\n\nstatic ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(\n        int const compressionLevel,\n        size_t const dictSize);\nstatic int ZSTD_dedicatedDictSearch_isSupported(\n        const ZSTD_compressionParameters* cParams);\nstatic void ZSTD_dedicatedDictSearch_revertCParams(\n        ZSTD_compressionParameters* cParams);\n\n/**\n * Initializes the local dictionary using requested parameters.\n * NOTE: Initialization does not employ the pledged src size,\n * because the dictionary may be used for multiple compressions.\n */\nstatic size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx)\n{\n    ZSTD_localDict* const dl = &cctx->localDict;\n    if (dl->dict == NULL) {\n        /* No local dictionary. */\n        assert(dl->dictBuffer == NULL);\n        assert(dl->cdict == NULL);\n        assert(dl->dictSize == 0);\n        return 0;\n    }\n    if (dl->cdict != NULL) {\n        /* Local dictionary already initialized. */\n        assert(cctx->cdict == dl->cdict);\n        return 0;\n    }\n    assert(dl->dictSize > 0);\n    assert(cctx->cdict == NULL);\n    assert(cctx->prefixDict.dict == NULL);\n\n    dl->cdict = ZSTD_createCDict_advanced2(\n            dl->dict,\n            dl->dictSize,\n            ZSTD_dlm_byRef,\n            dl->dictContentType,\n            &cctx->requestedParams,\n            cctx->customMem);\n    RETURN_ERROR_IF(!dl->cdict, memory_allocation, \"ZSTD_createCDict_advanced failed\");\n    cctx->cdict = dl->cdict;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_loadDictionary_advanced(\n        ZSTD_CCtx* cctx,\n        const void* dict, size_t dictSize,\n        ZSTD_dictLoadMethod_e dictLoadMethod,\n        ZSTD_dictContentType_e dictContentType)\n{\n    DEBUGLOG(4, \"ZSTD_CCtx_loadDictionary_advanced (size: %u)\", (U32)dictSize);\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't load a dictionary when cctx is not in init stage.\");\n    ZSTD_clearAllDicts(cctx);  /* erase any previously set dictionary */\n    if (dict == NULL || dictSize == 0)  /* no dictionary */\n        return 0;\n    if (dictLoadMethod == ZSTD_dlm_byRef) {\n        cctx->localDict.dict = dict;\n    } else {\n        /* copy dictionary content inside CCtx to own its lifetime */\n        void* dictBuffer;\n        RETURN_ERROR_IF(cctx->staticSize, memory_allocation,\n                        \"static CCtx can't allocate for an internal copy of dictionary\");\n        dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem);\n        RETURN_ERROR_IF(dictBuffer==NULL, memory_allocation,\n                        \"allocation failed for dictionary content\");\n        ZSTD_memcpy(dictBuffer, dict, dictSize);\n        cctx->localDict.dictBuffer = dictBuffer;  /* owned ptr to free */\n        cctx->localDict.dict = dictBuffer;        /* read-only reference */\n    }\n    cctx->localDict.dictSize = dictSize;\n    cctx->localDict.dictContentType = dictContentType;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_loadDictionary_byReference(\n      ZSTD_CCtx* cctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_CCtx_loadDictionary_advanced(\n            cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);\n}\n\nsize_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_CCtx_loadDictionary_advanced(\n            cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);\n}\n\n\nsize_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)\n{\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't ref a dict when ctx not in init stage.\");\n    /* Free the existing local cdict (if any) to save memory. */\n    ZSTD_clearAllDicts(cctx);\n    cctx->cdict = cdict;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool)\n{\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't ref a pool when ctx not in init stage.\");\n    cctx->pool = pool;\n    return 0;\n}\n\nsize_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize)\n{\n    return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent);\n}\n\nsize_t ZSTD_CCtx_refPrefix_advanced(\n        ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)\n{\n    RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                    \"Can't ref a prefix when ctx not in init stage.\");\n    ZSTD_clearAllDicts(cctx);\n    if (prefix != NULL && prefixSize > 0) {\n        cctx->prefixDict.dict = prefix;\n        cctx->prefixDict.dictSize = prefixSize;\n        cctx->prefixDict.dictContentType = dictContentType;\n    }\n    return 0;\n}\n\n/*! ZSTD_CCtx_reset() :\n *  Also dumps dictionary */\nsize_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset)\n{\n    if ( (reset == ZSTD_reset_session_only)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        cctx->streamStage = zcss_init;\n        cctx->pledgedSrcSizePlusOne = 0;\n    }\n    if ( (reset == ZSTD_reset_parameters)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,\n                        \"Reset parameters is only possible during init stage.\");\n        ZSTD_clearAllDicts(cctx);\n        return ZSTD_CCtxParams_reset(&cctx->requestedParams);\n    }\n    return 0;\n}\n\n\n/** ZSTD_checkCParams() :\n    control CParam values remain within authorized range.\n    @return : 0, or an error code if one value is beyond authorized range */\nsize_t ZSTD_checkCParams(ZSTD_compressionParameters cParams)\n{\n    BOUNDCHECK(ZSTD_c_windowLog, (int)cParams.windowLog);\n    BOUNDCHECK(ZSTD_c_chainLog,  (int)cParams.chainLog);\n    BOUNDCHECK(ZSTD_c_hashLog,   (int)cParams.hashLog);\n    BOUNDCHECK(ZSTD_c_searchLog, (int)cParams.searchLog);\n    BOUNDCHECK(ZSTD_c_minMatch,  (int)cParams.minMatch);\n    BOUNDCHECK(ZSTD_c_targetLength,(int)cParams.targetLength);\n    BOUNDCHECK(ZSTD_c_strategy,  (int)cParams.strategy);\n    return 0;\n}\n\n/** ZSTD_clampCParams() :\n *  make CParam values within valid range.\n *  @return : valid CParams */\nstatic ZSTD_compressionParameters\nZSTD_clampCParams(ZSTD_compressionParameters cParams)\n{\n#   define CLAMP_TYPE(cParam, val, type)                                      \\\n        do {                                                                  \\\n            ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);         \\\n            if ((int)val<bounds.lowerBound) val=(type)bounds.lowerBound;      \\\n            else if ((int)val>bounds.upperBound) val=(type)bounds.upperBound; \\\n        } while (0)\n#   define CLAMP(cParam, val) CLAMP_TYPE(cParam, val, unsigned)\n    CLAMP(ZSTD_c_windowLog, cParams.windowLog);\n    CLAMP(ZSTD_c_chainLog,  cParams.chainLog);\n    CLAMP(ZSTD_c_hashLog,   cParams.hashLog);\n    CLAMP(ZSTD_c_searchLog, cParams.searchLog);\n    CLAMP(ZSTD_c_minMatch,  cParams.minMatch);\n    CLAMP(ZSTD_c_targetLength,cParams.targetLength);\n    CLAMP_TYPE(ZSTD_c_strategy,cParams.strategy, ZSTD_strategy);\n    return cParams;\n}\n\n/** ZSTD_cycleLog() :\n *  condition for correct operation : hashLog > 1 */\nU32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat)\n{\n    U32 const btScale = ((U32)strat >= (U32)ZSTD_btlazy2);\n    return hashLog - btScale;\n}\n\n/** ZSTD_dictAndWindowLog() :\n * Returns an adjusted window log that is large enough to fit the source and the dictionary.\n * The zstd format says that the entire dictionary is valid if one byte of the dictionary\n * is within the window. So the hashLog and chainLog should be large enough to reference both\n * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing\n * the hashLog and windowLog.\n * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN.\n */\nstatic U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize)\n{\n    const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX;\n    /* No dictionary ==> No change */\n    if (dictSize == 0) {\n        return windowLog;\n    }\n    assert(windowLog <= ZSTD_WINDOWLOG_MAX);\n    assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */\n    {\n        U64 const windowSize = 1ULL << windowLog;\n        U64 const dictAndWindowSize = dictSize + windowSize;\n        /* If the window size is already large enough to fit both the source and the dictionary\n         * then just use the window size. Otherwise adjust so that it fits the dictionary and\n         * the window.\n         */\n        if (windowSize >= dictSize + srcSize) {\n            return windowLog; /* Window size large enough already */\n        } else if (dictAndWindowSize >= maxWindowSize) {\n            return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */\n        } else  {\n            return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1;\n        }\n    }\n}\n\n/** ZSTD_adjustCParams_internal() :\n *  optimize `cPar` for a specified input (`srcSize` and `dictSize`).\n *  mostly downsize to reduce memory consumption and initialization latency.\n * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known.\n * `mode` is the mode for parameter adjustment. See docs for `ZSTD_CParamMode_e`.\n *  note : `srcSize==0` means 0!\n *  condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */\nstatic ZSTD_compressionParameters\nZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,\n                            unsigned long long srcSize,\n                            size_t dictSize,\n                            ZSTD_CParamMode_e mode,\n                            ZSTD_ParamSwitch_e useRowMatchFinder)\n{\n    const U64 minSrcSize = 513; /* (1<<9) + 1 */\n    const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1);\n    assert(ZSTD_checkCParams(cPar)==0);\n\n    /* Cascade the selected strategy down to the next-highest one built into\n     * this binary. */\n#ifdef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_btultra2) {\n        cPar.strategy = ZSTD_btultra;\n    }\n    if (cPar.strategy == ZSTD_btultra) {\n        cPar.strategy = ZSTD_btopt;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_btopt) {\n        cPar.strategy = ZSTD_btlazy2;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_btlazy2) {\n        cPar.strategy = ZSTD_lazy2;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_lazy2) {\n        cPar.strategy = ZSTD_lazy;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_lazy) {\n        cPar.strategy = ZSTD_greedy;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_greedy) {\n        cPar.strategy = ZSTD_dfast;\n    }\n#endif\n#ifdef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n    if (cPar.strategy == ZSTD_dfast) {\n        cPar.strategy = ZSTD_fast;\n        cPar.targetLength = 0;\n    }\n#endif\n\n    switch (mode) {\n    case ZSTD_cpm_unknown:\n    case ZSTD_cpm_noAttachDict:\n        /* If we don't know the source size, don't make any\n         * assumptions about it. We will already have selected\n         * smaller parameters if a dictionary is in use.\n         */\n        break;\n    case ZSTD_cpm_createCDict:\n        /* Assume a small source size when creating a dictionary\n         * with an unknown source size.\n         */\n        if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)\n            srcSize = minSrcSize;\n        break;\n    case ZSTD_cpm_attachDict:\n        /* Dictionary has its own dedicated parameters which have\n         * already been selected. We are selecting parameters\n         * for only the source.\n         */\n        dictSize = 0;\n        break;\n    default:\n        assert(0);\n        break;\n    }\n\n    /* resize windowLog if input is small enough, to use less memory */\n    if ( (srcSize <= maxWindowResize)\n      && (dictSize <= maxWindowResize) )  {\n        U32 const tSize = (U32)(srcSize + dictSize);\n        static U32 const hashSizeMin = 1 << ZSTD_HASHLOG_MIN;\n        U32 const srcLog = (tSize < hashSizeMin) ? ZSTD_HASHLOG_MIN :\n                            ZSTD_highbit32(tSize-1) + 1;\n        if (cPar.windowLog > srcLog) cPar.windowLog = srcLog;\n    }\n    if (srcSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n        U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize);\n        U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy);\n        if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1;\n        if (cycleLog > dictAndWindowLog)\n            cPar.chainLog -= (cycleLog - dictAndWindowLog);\n    }\n\n    if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN)\n        cPar.windowLog = ZSTD_WINDOWLOG_ABSOLUTEMIN;  /* minimum wlog required for valid frame header */\n\n    /* We can't use more than 32 bits of hash in total, so that means that we require:\n     * (hashLog + 8) <= 32 && (chainLog + 8) <= 32\n     */\n    if (mode == ZSTD_cpm_createCDict && ZSTD_CDictIndicesAreTagged(&cPar)) {\n        U32 const maxShortCacheHashLog = 32 - ZSTD_SHORT_CACHE_TAG_BITS;\n        if (cPar.hashLog > maxShortCacheHashLog) {\n            cPar.hashLog = maxShortCacheHashLog;\n        }\n        if (cPar.chainLog > maxShortCacheHashLog) {\n            cPar.chainLog = maxShortCacheHashLog;\n        }\n    }\n\n\n    /* At this point, we aren't 100% sure if we are using the row match finder.\n     * Unless it is explicitly disabled, conservatively assume that it is enabled.\n     * In this case it will only be disabled for small sources, so shrinking the\n     * hash log a little bit shouldn't result in any ratio loss.\n     */\n    if (useRowMatchFinder == ZSTD_ps_auto)\n        useRowMatchFinder = ZSTD_ps_enable;\n\n    /* We can't hash more than 32-bits in total. So that means that we require:\n     * (hashLog - rowLog + 8) <= 32\n     */\n    if (ZSTD_rowMatchFinderUsed(cPar.strategy, useRowMatchFinder)) {\n        /* Switch to 32-entry rows if searchLog is 5 (or more) */\n        U32 const rowLog = BOUNDED(4, cPar.searchLog, 6);\n        U32 const maxRowHashLog = 32 - ZSTD_ROW_HASH_TAG_BITS;\n        U32 const maxHashLog = maxRowHashLog + rowLog;\n        assert(cPar.hashLog >= rowLog);\n        if (cPar.hashLog > maxHashLog) {\n            cPar.hashLog = maxHashLog;\n        }\n    }\n\n    return cPar;\n}\n\nZSTD_compressionParameters\nZSTD_adjustCParams(ZSTD_compressionParameters cPar,\n                   unsigned long long srcSize,\n                   size_t dictSize)\n{\n    cPar = ZSTD_clampCParams(cPar);   /* resulting cPar is necessarily valid (all parameters within range) */\n    if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN;\n    return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown, ZSTD_ps_auto);\n}\n\nstatic ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);\nstatic ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);\n\nstatic void ZSTD_overrideCParams(\n              ZSTD_compressionParameters* cParams,\n        const ZSTD_compressionParameters* overrides)\n{\n    if (overrides->windowLog)    cParams->windowLog    = overrides->windowLog;\n    if (overrides->hashLog)      cParams->hashLog      = overrides->hashLog;\n    if (overrides->chainLog)     cParams->chainLog     = overrides->chainLog;\n    if (overrides->searchLog)    cParams->searchLog    = overrides->searchLog;\n    if (overrides->minMatch)     cParams->minMatch     = overrides->minMatch;\n    if (overrides->targetLength) cParams->targetLength = overrides->targetLength;\n    if (overrides->strategy)     cParams->strategy     = overrides->strategy;\n}\n\nZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(\n        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    ZSTD_compressionParameters cParams;\n    if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) {\n        assert(CCtxParams->srcSizeHint>=0);\n        srcSizeHint = (U64)CCtxParams->srcSizeHint;\n    }\n    cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode);\n    if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;\n    ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);\n    assert(!ZSTD_checkCParams(cParams));\n    /* srcSizeHint == 0 means 0 */\n    return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode, CCtxParams->useRowMatchFinder);\n}\n\nstatic size_t\nZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,\n                       const ZSTD_ParamSwitch_e useRowMatchFinder,\n                       const int enableDedicatedDictSearch,\n                       const U32 forCCtx)\n{\n    /* chain table size should be 0 for fast or row-hash strategies */\n    size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder, enableDedicatedDictSearch && !forCCtx)\n                                ? ((size_t)1 << cParams->chainLog)\n                                : 0;\n    size_t const hSize = ((size_t)1) << cParams->hashLog;\n    U32    const hashLog3 = (forCCtx && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;\n    size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;\n    /* We don't use ZSTD_cwksp_alloc_size() here because the tables aren't\n     * surrounded by redzones in ASAN. */\n    size_t const tableSpace = chainSize * sizeof(U32)\n                            + hSize * sizeof(U32)\n                            + h3Size * sizeof(U32);\n    size_t const optPotentialSpace =\n        ZSTD_cwksp_aligned64_alloc_size((MaxML+1) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size((MaxLL+1) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size((MaxOff+1) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size((1<<Litbits) * sizeof(U32))\n      + ZSTD_cwksp_aligned64_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_match_t))\n      + ZSTD_cwksp_aligned64_alloc_size(ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));\n    size_t const lazyAdditionalSpace = ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)\n                                            ? ZSTD_cwksp_aligned64_alloc_size(hSize)\n                                            : 0;\n    size_t const optSpace = (forCCtx && (cParams->strategy >= ZSTD_btopt))\n                                ? optPotentialSpace\n                                : 0;\n    size_t const slackSpace = ZSTD_cwksp_slack_space_required();\n\n    /* tables are guaranteed to be sized in multiples of 64 bytes (or 16 uint32_t) */\n    ZSTD_STATIC_ASSERT(ZSTD_HASHLOG_MIN >= 4 && ZSTD_WINDOWLOG_MIN >= 4 && ZSTD_CHAINLOG_MIN >= 4);\n    assert(useRowMatchFinder != ZSTD_ps_auto);\n\n    DEBUGLOG(4, \"chainSize: %u - hSize: %u - h3Size: %u\",\n                (U32)chainSize, (U32)hSize, (U32)h3Size);\n    return tableSpace + optSpace + slackSpace + lazyAdditionalSpace;\n}\n\n/* Helper function for calculating memory requirements.\n * Gives a tighter bound than ZSTD_sequenceBound() by taking minMatch into account. */\nstatic size_t ZSTD_maxNbSeq(size_t blockSize, unsigned minMatch, int useSequenceProducer) {\n    U32 const divider = (minMatch==3 || useSequenceProducer) ? 3 : 4;\n    return blockSize / divider;\n}\n\nstatic size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n        const ZSTD_compressionParameters* cParams,\n        const ldmParams_t* ldmParams,\n        const int isStatic,\n        const ZSTD_ParamSwitch_e useRowMatchFinder,\n        const size_t buffInSize,\n        const size_t buffOutSize,\n        const U64 pledgedSrcSize,\n        int useSequenceProducer,\n        size_t maxBlockSize)\n{\n    size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize);\n    size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(maxBlockSize), windowSize);\n    size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, cParams->minMatch, useSequenceProducer);\n    size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize)\n                            + ZSTD_cwksp_aligned64_alloc_size(maxNbSeq * sizeof(SeqDef))\n                            + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE));\n    size_t const tmpWorkSpace = ZSTD_cwksp_alloc_size(TMP_WORKSPACE_SIZE);\n    size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t));\n    size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 0, /* forCCtx */ 1);\n\n    size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams);\n    size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize);\n    size_t const ldmSeqSpace = ldmParams->enableLdm == ZSTD_ps_enable ?\n        ZSTD_cwksp_aligned64_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0;\n\n\n    size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize)\n                             + ZSTD_cwksp_alloc_size(buffOutSize);\n\n    size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0;\n\n    size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);\n    size_t const externalSeqSpace = useSequenceProducer\n        ? ZSTD_cwksp_aligned64_alloc_size(maxNbExternalSeq * sizeof(ZSTD_Sequence))\n        : 0;\n\n    size_t const neededSpace =\n        cctxSpace +\n        tmpWorkSpace +\n        blockStateSpace +\n        ldmSpace +\n        ldmSeqSpace +\n        matchStateSize +\n        tokenSpace +\n        bufferSpace +\n        externalSeqSpace;\n\n    DEBUGLOG(5, \"estimate workspace : %u\", (U32)neededSpace);\n    return neededSpace;\n}\n\nsize_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)\n{\n    ZSTD_compressionParameters const cParams =\n                ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n    ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,\n                                                                               &cParams);\n\n    RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, \"Estimate CCtx size is supported for single-threaded compression only.\");\n    /* estimateCCtxSize is for one-shot compression. So no buffers should\n     * be needed. However, we still allocate two 0-sized buffers, which can\n     * take space under ASAN. */\n    return ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n        &cParams, &params->ldmParams, 1, useRowMatchFinder, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);\n}\n\nsize_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)\n{\n    ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams);\n    if (ZSTD_rowMatchFinderSupported(cParams.strategy)) {\n        /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */\n        size_t noRowCCtxSize;\n        size_t rowCCtxSize;\n        initialParams.useRowMatchFinder = ZSTD_ps_disable;\n        noRowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);\n        initialParams.useRowMatchFinder = ZSTD_ps_enable;\n        rowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);\n        return MAX(noRowCCtxSize, rowCCtxSize);\n    } else {\n        return ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);\n    }\n}\n\nstatic size_t ZSTD_estimateCCtxSize_internal(int compressionLevel)\n{\n    int tier = 0;\n    size_t largestSize = 0;\n    static const unsigned long long srcSizeTiers[4] = {16 KB, 128 KB, 256 KB, ZSTD_CONTENTSIZE_UNKNOWN};\n    for (; tier < 4; ++tier) {\n        /* Choose the set of cParams for a given level across all srcSizes that give the largest cctxSize */\n        ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeTiers[tier], 0, ZSTD_cpm_noAttachDict);\n        largestSize = MAX(ZSTD_estimateCCtxSize_usingCParams(cParams), largestSize);\n    }\n    return largestSize;\n}\n\nsize_t ZSTD_estimateCCtxSize(int compressionLevel)\n{\n    int level;\n    size_t memBudget = 0;\n    for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {\n        /* Ensure monotonically increasing memory usage as compression level increases */\n        size_t const newMB = ZSTD_estimateCCtxSize_internal(level);\n        if (newMB > memBudget) memBudget = newMB;\n    }\n    return memBudget;\n}\n\nsize_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)\n{\n    RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, \"Estimate CCtx size is supported for single-threaded compression only.\");\n    {   ZSTD_compressionParameters const cParams =\n                ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n        size_t const blockSize = MIN(ZSTD_resolveMaxBlockSize(params->maxBlockSize), (size_t)1 << cParams.windowLog);\n        size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered)\n                ? ((size_t)1 << cParams.windowLog) + blockSize\n                : 0;\n        size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)\n                ? ZSTD_compressBound(blockSize) + 1\n                : 0;\n        ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, &params->cParams);\n\n        return ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n            &cParams, &params->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,\n            ZSTD_CONTENTSIZE_UNKNOWN, ZSTD_hasExtSeqProd(params), params->maxBlockSize);\n    }\n}\n\nsize_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)\n{\n    ZSTD_CCtx_params initialParams = ZSTD_makeCCtxParamsFromCParams(cParams);\n    if (ZSTD_rowMatchFinderSupported(cParams.strategy)) {\n        /* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */\n        size_t noRowCCtxSize;\n        size_t rowCCtxSize;\n        initialParams.useRowMatchFinder = ZSTD_ps_disable;\n        noRowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);\n        initialParams.useRowMatchFinder = ZSTD_ps_enable;\n        rowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);\n        return MAX(noRowCCtxSize, rowCCtxSize);\n    } else {\n        return ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);\n    }\n}\n\nstatic size_t ZSTD_estimateCStreamSize_internal(int compressionLevel)\n{\n    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n    return ZSTD_estimateCStreamSize_usingCParams(cParams);\n}\n\nsize_t ZSTD_estimateCStreamSize(int compressionLevel)\n{\n    int level;\n    size_t memBudget = 0;\n    for (level=MIN(compressionLevel, 1); level<=compressionLevel; level++) {\n        size_t const newMB = ZSTD_estimateCStreamSize_internal(level);\n        if (newMB > memBudget) memBudget = newMB;\n    }\n    return memBudget;\n}\n\n/* ZSTD_getFrameProgression():\n * tells how much data has been consumed (input) and produced (output) for current frame.\n * able to count progression inside worker threads (non-blocking mode).\n */\nZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers > 0) {\n        return ZSTDMT_getFrameProgression(cctx->mtctx);\n    }\n#endif\n    {   ZSTD_frameProgression fp;\n        size_t const buffered = (cctx->inBuff == NULL) ? 0 :\n                                cctx->inBuffPos - cctx->inToCompress;\n        if (buffered) assert(cctx->inBuffPos >= cctx->inToCompress);\n        assert(buffered <= ZSTD_BLOCKSIZE_MAX);\n        fp.ingested = cctx->consumedSrcSize + buffered;\n        fp.consumed = cctx->consumedSrcSize;\n        fp.produced = cctx->producedCSize;\n        fp.flushed  = cctx->producedCSize;   /* simplified; some data might still be left within streaming output buffer */\n        fp.currentJobID = 0;\n        fp.nbActiveWorkers = 0;\n        return fp;\n}   }\n\n/*! ZSTD_toFlushNow()\n *  Only useful for multithreading scenarios currently (nbWorkers >= 1).\n */\nsize_t ZSTD_toFlushNow(ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers > 0) {\n        return ZSTDMT_toFlushNow(cctx->mtctx);\n    }\n#endif\n    (void)cctx;\n    return 0;   /* over-simplification; could also check if context is currently running in streaming mode, and in which case, report how many bytes are left to be flushed within output buffer */\n}\n\nstatic void ZSTD_assertEqualCParams(ZSTD_compressionParameters cParams1,\n                                    ZSTD_compressionParameters cParams2)\n{\n    (void)cParams1;\n    (void)cParams2;\n    assert(cParams1.windowLog    == cParams2.windowLog);\n    assert(cParams1.chainLog     == cParams2.chainLog);\n    assert(cParams1.hashLog      == cParams2.hashLog);\n    assert(cParams1.searchLog    == cParams2.searchLog);\n    assert(cParams1.minMatch     == cParams2.minMatch);\n    assert(cParams1.targetLength == cParams2.targetLength);\n    assert(cParams1.strategy     == cParams2.strategy);\n}\n\nvoid ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs)\n{\n    int i;\n    for (i = 0; i < ZSTD_REP_NUM; ++i)\n        bs->rep[i] = repStartValue[i];\n    bs->entropy.huf.repeatMode = HUF_repeat_none;\n    bs->entropy.fse.offcode_repeatMode = FSE_repeat_none;\n    bs->entropy.fse.matchlength_repeatMode = FSE_repeat_none;\n    bs->entropy.fse.litlength_repeatMode = FSE_repeat_none;\n}\n\n/*! ZSTD_invalidateMatchState()\n *  Invalidate all the matches in the match finder tables.\n *  Requires nextSrc and base to be set (can be NULL).\n */\nstatic void ZSTD_invalidateMatchState(ZSTD_MatchState_t* ms)\n{\n    ZSTD_window_clear(&ms->window);\n\n    ms->nextToUpdate = ms->window.dictLimit;\n    ms->loadedDictEnd = 0;\n    ms->opt.litLengthSum = 0;  /* force reset of btopt stats */\n    ms->dictMatchState = NULL;\n}\n\n/**\n * Controls, for this matchState reset, whether the tables need to be cleared /\n * prepared for the coming compression (ZSTDcrp_makeClean), or whether the\n * tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a\n * subsequent operation will overwrite the table space anyways (e.g., copying\n * the matchState contents in from a CDict).\n */\ntypedef enum {\n    ZSTDcrp_makeClean,\n    ZSTDcrp_leaveDirty\n} ZSTD_compResetPolicy_e;\n\n/**\n * Controls, for this matchState reset, whether indexing can continue where it\n * left off (ZSTDirp_continue), or whether it needs to be restarted from zero\n * (ZSTDirp_reset).\n */\ntypedef enum {\n    ZSTDirp_continue,\n    ZSTDirp_reset\n} ZSTD_indexResetPolicy_e;\n\ntypedef enum {\n    ZSTD_resetTarget_CDict,\n    ZSTD_resetTarget_CCtx\n} ZSTD_resetTarget_e;\n\n/* Mixes bits in a 64 bits in a value, based on XXH3_rrmxmx */\nstatic U64 ZSTD_bitmix(U64 val, U64 len) {\n    val ^= ZSTD_rotateRight_U64(val, 49) ^ ZSTD_rotateRight_U64(val, 24);\n    val *= 0x9FB21C651E98DF25ULL;\n    val ^= (val >> 35) + len ;\n    val *= 0x9FB21C651E98DF25ULL;\n    return val ^ (val >> 28);\n}\n\n/* Mixes in the hashSalt and hashSaltEntropy to create a new hashSalt */\nstatic void ZSTD_advanceHashSalt(ZSTD_MatchState_t* ms) {\n    ms->hashSalt = ZSTD_bitmix(ms->hashSalt, 8) ^ ZSTD_bitmix((U64) ms->hashSaltEntropy, 4);\n}\n\nstatic size_t\nZSTD_reset_matchState(ZSTD_MatchState_t* ms,\n                      ZSTD_cwksp* ws,\n                const ZSTD_compressionParameters* cParams,\n                const ZSTD_ParamSwitch_e useRowMatchFinder,\n                const ZSTD_compResetPolicy_e crp,\n                const ZSTD_indexResetPolicy_e forceResetIndex,\n                const ZSTD_resetTarget_e forWho)\n{\n    /* disable chain table allocation for fast or row-based strategies */\n    size_t const chainSize = ZSTD_allocateChainTable(cParams->strategy, useRowMatchFinder,\n                                                     ms->dedicatedDictSearch && (forWho == ZSTD_resetTarget_CDict))\n                                ? ((size_t)1 << cParams->chainLog)\n                                : 0;\n    size_t const hSize = ((size_t)1) << cParams->hashLog;\n    U32    const hashLog3 = ((forWho == ZSTD_resetTarget_CCtx) && cParams->minMatch==3) ? MIN(ZSTD_HASHLOG3_MAX, cParams->windowLog) : 0;\n    size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;\n\n    DEBUGLOG(4, \"reset indices : %u\", forceResetIndex == ZSTDirp_reset);\n    assert(useRowMatchFinder != ZSTD_ps_auto);\n    if (forceResetIndex == ZSTDirp_reset) {\n        ZSTD_window_init(&ms->window);\n        ZSTD_cwksp_mark_tables_dirty(ws);\n    }\n\n    ms->hashLog3 = hashLog3;\n    ms->lazySkipping = 0;\n\n    ZSTD_invalidateMatchState(ms);\n\n    assert(!ZSTD_cwksp_reserve_failed(ws)); /* check that allocation hasn't already failed */\n\n    ZSTD_cwksp_clear_tables(ws);\n\n    DEBUGLOG(5, \"reserving table space\");\n    /* table Space */\n    ms->hashTable = (U32*)ZSTD_cwksp_reserve_table(ws, hSize * sizeof(U32));\n    ms->chainTable = (U32*)ZSTD_cwksp_reserve_table(ws, chainSize * sizeof(U32));\n    ms->hashTable3 = (U32*)ZSTD_cwksp_reserve_table(ws, h3Size * sizeof(U32));\n    RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,\n                    \"failed a workspace allocation in ZSTD_reset_matchState\");\n\n    DEBUGLOG(4, \"reset table : %u\", crp!=ZSTDcrp_leaveDirty);\n    if (crp!=ZSTDcrp_leaveDirty) {\n        /* reset tables only */\n        ZSTD_cwksp_clean_tables(ws);\n    }\n\n    if (ZSTD_rowMatchFinderUsed(cParams->strategy, useRowMatchFinder)) {\n        /* Row match finder needs an additional table of hashes (\"tags\") */\n        size_t const tagTableSize = hSize;\n        /* We want to generate a new salt in case we reset a Cctx, but we always want to use\n         * 0 when we reset a Cdict */\n        if(forWho == ZSTD_resetTarget_CCtx) {\n            ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned_init_once(ws, tagTableSize);\n            ZSTD_advanceHashSalt(ms);\n        } else {\n            /* When we are not salting we want to always memset the memory */\n            ms->tagTable = (BYTE*) ZSTD_cwksp_reserve_aligned64(ws, tagTableSize);\n            ZSTD_memset(ms->tagTable, 0, tagTableSize);\n            ms->hashSalt = 0;\n        }\n        {   /* Switch to 32-entry rows if searchLog is 5 (or more) */\n            U32 const rowLog = BOUNDED(4, cParams->searchLog, 6);\n            assert(cParams->hashLog >= rowLog);\n            ms->rowHashLog = cParams->hashLog - rowLog;\n        }\n    }\n\n    /* opt parser space */\n    if ((forWho == ZSTD_resetTarget_CCtx) && (cParams->strategy >= ZSTD_btopt)) {\n        DEBUGLOG(4, \"reserving optimal parser space\");\n        ms->opt.litFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (1<<Litbits) * sizeof(unsigned));\n        ms->opt.litLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxLL+1) * sizeof(unsigned));\n        ms->opt.matchLengthFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxML+1) * sizeof(unsigned));\n        ms->opt.offCodeFreq = (unsigned*)ZSTD_cwksp_reserve_aligned64(ws, (MaxOff+1) * sizeof(unsigned));\n        ms->opt.matchTable = (ZSTD_match_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_match_t));\n        ms->opt.priceTable = (ZSTD_optimal_t*)ZSTD_cwksp_reserve_aligned64(ws, ZSTD_OPT_SIZE * sizeof(ZSTD_optimal_t));\n    }\n\n    ms->cParams = *cParams;\n\n    RETURN_ERROR_IF(ZSTD_cwksp_reserve_failed(ws), memory_allocation,\n                    \"failed a workspace allocation in ZSTD_reset_matchState\");\n    return 0;\n}\n\n/* ZSTD_indexTooCloseToMax() :\n * minor optimization : prefer memset() rather than reduceIndex()\n * which is measurably slow in some circumstances (reported for Visual Studio).\n * Works when re-using a context for a lot of smallish inputs :\n * if all inputs are smaller than ZSTD_INDEXOVERFLOW_MARGIN,\n * memset() will be triggered before reduceIndex().\n */\n#define ZSTD_INDEXOVERFLOW_MARGIN (16 MB)\nstatic int ZSTD_indexTooCloseToMax(ZSTD_window_t w)\n{\n    return (size_t)(w.nextSrc - w.base) > (ZSTD_CURRENT_MAX - ZSTD_INDEXOVERFLOW_MARGIN);\n}\n\n/** ZSTD_dictTooBig():\n * When dictionaries are larger than ZSTD_CHUNKSIZE_MAX they can't be loaded in\n * one go generically. So we ensure that in that case we reset the tables to zero,\n * so that we can load as much of the dictionary as possible.\n */\nstatic int ZSTD_dictTooBig(size_t const loadedDictSize)\n{\n    return loadedDictSize > ZSTD_CHUNKSIZE_MAX;\n}\n\n/*! ZSTD_resetCCtx_internal() :\n * @param loadedDictSize The size of the dictionary to be loaded\n * into the context, if any. If no dictionary is used, or the\n * dictionary is being attached / copied, then pass 0.\n * note : `params` are assumed fully validated at this stage.\n */\nstatic size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,\n                                      ZSTD_CCtx_params const* params,\n                                      U64 const pledgedSrcSize,\n                                      size_t const loadedDictSize,\n                                      ZSTD_compResetPolicy_e const crp,\n                                      ZSTD_buffered_policy_e const zbuff)\n{\n    ZSTD_cwksp* const ws = &zc->workspace;\n    DEBUGLOG(4, \"ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d useBlockSplitter=%d\",\n                (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->postBlockSplitter);\n    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));\n\n    zc->isFirstBlock = 1;\n\n    /* Set applied params early so we can modify them for LDM,\n     * and point params at the applied params.\n     */\n    zc->appliedParams = *params;\n    params = &zc->appliedParams;\n\n    assert(params->useRowMatchFinder != ZSTD_ps_auto);\n    assert(params->postBlockSplitter != ZSTD_ps_auto);\n    assert(params->ldmParams.enableLdm != ZSTD_ps_auto);\n    assert(params->maxBlockSize != 0);\n    if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n        /* Adjust long distance matching parameters */\n        ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, &params->cParams);\n        assert(params->ldmParams.hashLog >= params->ldmParams.bucketSizeLog);\n        assert(params->ldmParams.hashRateLog < 32);\n    }\n\n    {   size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << params->cParams.windowLog), pledgedSrcSize));\n        size_t const blockSize = MIN(params->maxBlockSize, windowSize);\n        size_t const maxNbSeq = ZSTD_maxNbSeq(blockSize, params->cParams.minMatch, ZSTD_hasExtSeqProd(params));\n        size_t const buffOutSize = (zbuff == ZSTDb_buffered && params->outBufferMode == ZSTD_bm_buffered)\n                ? ZSTD_compressBound(blockSize) + 1\n                : 0;\n        size_t const buffInSize = (zbuff == ZSTDb_buffered && params->inBufferMode == ZSTD_bm_buffered)\n                ? windowSize + blockSize\n                : 0;\n        size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize);\n\n        int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window);\n        int const dictTooBig = ZSTD_dictTooBig(loadedDictSize);\n        ZSTD_indexResetPolicy_e needsIndexReset =\n            (indexTooClose || dictTooBig || !zc->initialized) ? ZSTDirp_reset : ZSTDirp_continue;\n\n        size_t const neededSpace =\n            ZSTD_estimateCCtxSize_usingCCtxParams_internal(\n                &params->cParams, &params->ldmParams, zc->staticSize != 0, params->useRowMatchFinder,\n                buffInSize, buffOutSize, pledgedSrcSize, ZSTD_hasExtSeqProd(params), params->maxBlockSize);\n\n        FORWARD_IF_ERROR(neededSpace, \"cctx size estimate failed!\");\n\n        if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0);\n\n        {   /* Check if workspace is large enough, alloc a new one if needed */\n            int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace;\n            int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace);\n            int resizeWorkspace = workspaceTooSmall || workspaceWasteful;\n            DEBUGLOG(4, \"Need %zu B workspace\", neededSpace);\n            DEBUGLOG(4, \"windowSize: %zu - blockSize: %zu\", windowSize, blockSize);\n\n            if (resizeWorkspace) {\n                DEBUGLOG(4, \"Resize workspaceSize from %zuKB to %zuKB\",\n                            ZSTD_cwksp_sizeof(ws) >> 10,\n                            neededSpace >> 10);\n\n                RETURN_ERROR_IF(zc->staticSize, memory_allocation, \"static cctx : no resize\");\n\n                needsIndexReset = ZSTDirp_reset;\n\n                ZSTD_cwksp_free(ws, zc->customMem);\n                FORWARD_IF_ERROR(ZSTD_cwksp_create(ws, neededSpace, zc->customMem), \"\");\n\n                DEBUGLOG(5, \"reserving object space\");\n                /* Statically sized space.\n                 * tmpWorkspace never moves,\n                 * though prev/next block swap places */\n                assert(ZSTD_cwksp_check_available(ws, 2 * sizeof(ZSTD_compressedBlockState_t)));\n                zc->blockState.prevCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));\n                RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, \"couldn't allocate prevCBlock\");\n                zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));\n                RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, \"couldn't allocate nextCBlock\");\n                zc->tmpWorkspace = ZSTD_cwksp_reserve_object(ws, TMP_WORKSPACE_SIZE);\n                RETURN_ERROR_IF(zc->tmpWorkspace == NULL, memory_allocation, \"couldn't allocate tmpWorkspace\");\n                zc->tmpWkspSize = TMP_WORKSPACE_SIZE;\n        }   }\n\n        ZSTD_cwksp_clear(ws);\n\n        /* init params */\n        zc->blockState.matchState.cParams = params->cParams;\n        zc->blockState.matchState.prefetchCDictTables = params->prefetchCDictTables == ZSTD_ps_enable;\n        zc->pledgedSrcSizePlusOne = pledgedSrcSize+1;\n        zc->consumedSrcSize = 0;\n        zc->producedCSize = 0;\n        if (pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN)\n            zc->appliedParams.fParams.contentSizeFlag = 0;\n        DEBUGLOG(4, \"pledged content size : %u ; flag : %u\",\n            (unsigned)pledgedSrcSize, zc->appliedParams.fParams.contentSizeFlag);\n        zc->blockSizeMax = blockSize;\n\n        XXH64_reset(&zc->xxhState, 0);\n        zc->stage = ZSTDcs_init;\n        zc->dictID = 0;\n        zc->dictContentSize = 0;\n\n        ZSTD_reset_compressedBlockState(zc->blockState.prevCBlock);\n\n        FORWARD_IF_ERROR(ZSTD_reset_matchState(\n                &zc->blockState.matchState,\n                ws,\n                &params->cParams,\n                params->useRowMatchFinder,\n                crp,\n                needsIndexReset,\n                ZSTD_resetTarget_CCtx), \"\");\n\n        zc->seqStore.sequencesStart = (SeqDef*)ZSTD_cwksp_reserve_aligned64(ws, maxNbSeq * sizeof(SeqDef));\n\n        /* ldm hash table */\n        if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n            /* TODO: avoid memset? */\n            size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog;\n            zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned64(ws, ldmHSize * sizeof(ldmEntry_t));\n            ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t));\n            zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned64(ws, maxNbLdmSeq * sizeof(rawSeq));\n            zc->maxNbLdmSequences = maxNbLdmSeq;\n\n            ZSTD_window_init(&zc->ldmState.window);\n            zc->ldmState.loadedDictEnd = 0;\n        }\n\n        /* reserve space for block-level external sequences */\n        if (ZSTD_hasExtSeqProd(params)) {\n            size_t const maxNbExternalSeq = ZSTD_sequenceBound(blockSize);\n            zc->extSeqBufCapacity = maxNbExternalSeq;\n            zc->extSeqBuf =\n                (ZSTD_Sequence*)ZSTD_cwksp_reserve_aligned64(ws, maxNbExternalSeq * sizeof(ZSTD_Sequence));\n        }\n\n        /* buffers */\n\n        /* ZSTD_wildcopy() is used to copy into the literals buffer,\n         * so we have to oversize the buffer by WILDCOPY_OVERLENGTH bytes.\n         */\n        zc->seqStore.litStart = ZSTD_cwksp_reserve_buffer(ws, blockSize + WILDCOPY_OVERLENGTH);\n        zc->seqStore.maxNbLit = blockSize;\n\n        zc->bufferedPolicy = zbuff;\n        zc->inBuffSize = buffInSize;\n        zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize);\n        zc->outBuffSize = buffOutSize;\n        zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);\n\n        /* ldm bucketOffsets table */\n        if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n            /* TODO: avoid memset? */\n            size_t const numBuckets =\n                  ((size_t)1) << (params->ldmParams.hashLog -\n                                  params->ldmParams.bucketSizeLog);\n            zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, numBuckets);\n            ZSTD_memset(zc->ldmState.bucketOffsets, 0, numBuckets);\n        }\n\n        /* sequences storage */\n        ZSTD_referenceExternalSequences(zc, NULL, 0);\n        zc->seqStore.maxNbSeq = maxNbSeq;\n        zc->seqStore.llCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));\n        zc->seqStore.mlCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));\n        zc->seqStore.ofCode = ZSTD_cwksp_reserve_buffer(ws, maxNbSeq * sizeof(BYTE));\n\n        DEBUGLOG(3, \"wksp: finished allocating, %zd bytes remain available\", ZSTD_cwksp_available_space(ws));\n        assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace));\n\n        zc->initialized = 1;\n\n        return 0;\n    }\n}\n\n/* ZSTD_invalidateRepCodes() :\n * ensures next compression will not use repcodes from previous block.\n * Note : only works with regular variant;\n *        do not use with extDict variant ! */\nvoid ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx) {\n    int i;\n    for (i=0; i<ZSTD_REP_NUM; i++) cctx->blockState.prevCBlock->rep[i] = 0;\n    assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));\n}\n\n/* These are the approximate sizes for each strategy past which copying the\n * dictionary tables into the working context is faster than using them\n * in-place.\n */\nstatic const size_t attachDictSizeCutoffs[ZSTD_STRATEGY_MAX+1] = {\n    8 KB,  /* unused */\n    8 KB,  /* ZSTD_fast */\n    16 KB, /* ZSTD_dfast */\n    32 KB, /* ZSTD_greedy */\n    32 KB, /* ZSTD_lazy */\n    32 KB, /* ZSTD_lazy2 */\n    32 KB, /* ZSTD_btlazy2 */\n    32 KB, /* ZSTD_btopt */\n    8 KB,  /* ZSTD_btultra */\n    8 KB   /* ZSTD_btultra2 */\n};\n\nstatic int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict,\n                                 const ZSTD_CCtx_params* params,\n                                 U64 pledgedSrcSize)\n{\n    size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy];\n    int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch;\n    return dedicatedDictSearch\n        || ( ( pledgedSrcSize <= cutoff\n            || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN\n            || params->attachDictPref == ZSTD_dictForceAttach )\n          && params->attachDictPref != ZSTD_dictForceCopy\n          && !params->forceWindow ); /* dictMatchState isn't correctly\n                                      * handled in _enforceMaxDist */\n}\n\nstatic size_t\nZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx,\n                        const ZSTD_CDict* cdict,\n                        ZSTD_CCtx_params params,\n                        U64 pledgedSrcSize,\n                        ZSTD_buffered_policy_e zbuff)\n{\n    DEBUGLOG(4, \"ZSTD_resetCCtx_byAttachingCDict() pledgedSrcSize=%llu\",\n                (unsigned long long)pledgedSrcSize);\n    {\n        ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams;\n        unsigned const windowLog = params.cParams.windowLog;\n        assert(windowLog != 0);\n        /* Resize working context table params for input only, since the dict\n         * has its own tables. */\n        /* pledgedSrcSize == 0 means 0! */\n\n        if (cdict->matchState.dedicatedDictSearch) {\n            ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams);\n        }\n\n        params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize,\n                                                     cdict->dictContentSize, ZSTD_cpm_attachDict,\n                                                     params.useRowMatchFinder);\n        params.cParams.windowLog = windowLog;\n        params.useRowMatchFinder = cdict->useRowMatchFinder;    /* cdict overrides */\n        FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, &params, pledgedSrcSize,\n                                                 /* loadedDictSize */ 0,\n                                                 ZSTDcrp_makeClean, zbuff), \"\");\n        assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy);\n    }\n\n    {   const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc\n                                  - cdict->matchState.window.base);\n        const U32 cdictLen = cdictEnd - cdict->matchState.window.dictLimit;\n        if (cdictLen == 0) {\n            /* don't even attach dictionaries with no contents */\n            DEBUGLOG(4, \"skipping attaching empty dictionary\");\n        } else {\n            DEBUGLOG(4, \"attaching dictionary into context\");\n            cctx->blockState.matchState.dictMatchState = &cdict->matchState;\n\n            /* prep working match state so dict matches never have negative indices\n             * when they are translated to the working context's index space. */\n            if (cctx->blockState.matchState.window.dictLimit < cdictEnd) {\n                cctx->blockState.matchState.window.nextSrc =\n                    cctx->blockState.matchState.window.base + cdictEnd;\n                ZSTD_window_clear(&cctx->blockState.matchState.window);\n            }\n            /* loadedDictEnd is expressed within the referential of the active context */\n            cctx->blockState.matchState.loadedDictEnd = cctx->blockState.matchState.window.dictLimit;\n    }   }\n\n    cctx->dictID = cdict->dictID;\n    cctx->dictContentSize = cdict->dictContentSize;\n\n    /* copy block state */\n    ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));\n\n    return 0;\n}\n\nstatic void ZSTD_copyCDictTableIntoCCtx(U32* dst, U32 const* src, size_t tableSize,\n                                        ZSTD_compressionParameters const* cParams) {\n    if (ZSTD_CDictIndicesAreTagged(cParams)){\n        /* Remove tags from the CDict table if they are present.\n         * See docs on \"short cache\" in zstd_compress_internal.h for context. */\n        size_t i;\n        for (i = 0; i < tableSize; i++) {\n            U32 const taggedIndex = src[i];\n            U32 const index = taggedIndex >> ZSTD_SHORT_CACHE_TAG_BITS;\n            dst[i] = index;\n        }\n    } else {\n        ZSTD_memcpy(dst, src, tableSize * sizeof(U32));\n    }\n}\n\nstatic size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,\n                            const ZSTD_CDict* cdict,\n                            ZSTD_CCtx_params params,\n                            U64 pledgedSrcSize,\n                            ZSTD_buffered_policy_e zbuff)\n{\n    const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams;\n\n    assert(!cdict->matchState.dedicatedDictSearch);\n    DEBUGLOG(4, \"ZSTD_resetCCtx_byCopyingCDict() pledgedSrcSize=%llu\",\n                (unsigned long long)pledgedSrcSize);\n\n    {   unsigned const windowLog = params.cParams.windowLog;\n        assert(windowLog != 0);\n        /* Copy only compression parameters related to tables. */\n        params.cParams = *cdict_cParams;\n        params.cParams.windowLog = windowLog;\n        params.useRowMatchFinder = cdict->useRowMatchFinder;\n        FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, &params, pledgedSrcSize,\n                                                 /* loadedDictSize */ 0,\n                                                 ZSTDcrp_leaveDirty, zbuff), \"\");\n        assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy);\n        assert(cctx->appliedParams.cParams.hashLog == cdict_cParams->hashLog);\n        assert(cctx->appliedParams.cParams.chainLog == cdict_cParams->chainLog);\n    }\n\n    ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);\n    assert(params.useRowMatchFinder != ZSTD_ps_auto);\n\n    /* copy tables */\n    {   size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->useRowMatchFinder, 0 /* DDS guaranteed disabled */)\n                                                            ? ((size_t)1 << cdict_cParams->chainLog)\n                                                            : 0;\n        size_t const hSize =  (size_t)1 << cdict_cParams->hashLog;\n\n        ZSTD_copyCDictTableIntoCCtx(cctx->blockState.matchState.hashTable,\n                                cdict->matchState.hashTable,\n                                hSize, cdict_cParams);\n\n        /* Do not copy cdict's chainTable if cctx has parameters such that it would not use chainTable */\n        if (ZSTD_allocateChainTable(cctx->appliedParams.cParams.strategy, cctx->appliedParams.useRowMatchFinder, 0 /* forDDSDict */)) {\n            ZSTD_copyCDictTableIntoCCtx(cctx->blockState.matchState.chainTable,\n                                    cdict->matchState.chainTable,\n                                    chainSize, cdict_cParams);\n        }\n        /* copy tag table */\n        if (ZSTD_rowMatchFinderUsed(cdict_cParams->strategy, cdict->useRowMatchFinder)) {\n            size_t const tagTableSize = hSize;\n            ZSTD_memcpy(cctx->blockState.matchState.tagTable,\n                        cdict->matchState.tagTable,\n                        tagTableSize);\n            cctx->blockState.matchState.hashSalt = cdict->matchState.hashSalt;\n        }\n    }\n\n    /* Zero the hashTable3, since the cdict never fills it */\n    assert(cctx->blockState.matchState.hashLog3 <= 31);\n    {   U32 const h3log = cctx->blockState.matchState.hashLog3;\n        size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;\n        assert(cdict->matchState.hashLog3 == 0);\n        ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32));\n    }\n\n    ZSTD_cwksp_mark_tables_clean(&cctx->workspace);\n\n    /* copy dictionary offsets */\n    {   ZSTD_MatchState_t const* srcMatchState = &cdict->matchState;\n        ZSTD_MatchState_t* dstMatchState = &cctx->blockState.matchState;\n        dstMatchState->window       = srcMatchState->window;\n        dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;\n        dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;\n    }\n\n    cctx->dictID = cdict->dictID;\n    cctx->dictContentSize = cdict->dictContentSize;\n\n    /* copy block state */\n    ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState));\n\n    return 0;\n}\n\n/* We have a choice between copying the dictionary context into the working\n * context, or referencing the dictionary context from the working context\n * in-place. We decide here which strategy to use. */\nstatic size_t ZSTD_resetCCtx_usingCDict(ZSTD_CCtx* cctx,\n                            const ZSTD_CDict* cdict,\n                            const ZSTD_CCtx_params* params,\n                            U64 pledgedSrcSize,\n                            ZSTD_buffered_policy_e zbuff)\n{\n\n    DEBUGLOG(4, \"ZSTD_resetCCtx_usingCDict (pledgedSrcSize=%u)\",\n                (unsigned)pledgedSrcSize);\n\n    if (ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) {\n        return ZSTD_resetCCtx_byAttachingCDict(\n            cctx, cdict, *params, pledgedSrcSize, zbuff);\n    } else {\n        return ZSTD_resetCCtx_byCopyingCDict(\n            cctx, cdict, *params, pledgedSrcSize, zbuff);\n    }\n}\n\n/*! ZSTD_copyCCtx_internal() :\n *  Duplicate an existing context `srcCCtx` into another one `dstCCtx`.\n *  Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).\n *  The \"context\", in this case, refers to the hash and chain tables,\n *  entropy tables, and dictionary references.\n * `windowLog` value is enforced if != 0, otherwise value is copied from srcCCtx.\n * @return : 0, or an error code */\nstatic size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,\n                            const ZSTD_CCtx* srcCCtx,\n                            ZSTD_frameParameters fParams,\n                            U64 pledgedSrcSize,\n                            ZSTD_buffered_policy_e zbuff)\n{\n    RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong,\n                    \"Can't copy a ctx that's not in init stage.\");\n    DEBUGLOG(5, \"ZSTD_copyCCtx_internal\");\n    ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem));\n    {   ZSTD_CCtx_params params = dstCCtx->requestedParams;\n        /* Copy only compression parameters related to tables. */\n        params.cParams = srcCCtx->appliedParams.cParams;\n        assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_ps_auto);\n        assert(srcCCtx->appliedParams.postBlockSplitter != ZSTD_ps_auto);\n        assert(srcCCtx->appliedParams.ldmParams.enableLdm != ZSTD_ps_auto);\n        params.useRowMatchFinder = srcCCtx->appliedParams.useRowMatchFinder;\n        params.postBlockSplitter = srcCCtx->appliedParams.postBlockSplitter;\n        params.ldmParams = srcCCtx->appliedParams.ldmParams;\n        params.fParams = fParams;\n        params.maxBlockSize = srcCCtx->appliedParams.maxBlockSize;\n        ZSTD_resetCCtx_internal(dstCCtx, &params, pledgedSrcSize,\n                                /* loadedDictSize */ 0,\n                                ZSTDcrp_leaveDirty, zbuff);\n        assert(dstCCtx->appliedParams.cParams.windowLog == srcCCtx->appliedParams.cParams.windowLog);\n        assert(dstCCtx->appliedParams.cParams.strategy == srcCCtx->appliedParams.cParams.strategy);\n        assert(dstCCtx->appliedParams.cParams.hashLog == srcCCtx->appliedParams.cParams.hashLog);\n        assert(dstCCtx->appliedParams.cParams.chainLog == srcCCtx->appliedParams.cParams.chainLog);\n        assert(dstCCtx->blockState.matchState.hashLog3 == srcCCtx->blockState.matchState.hashLog3);\n    }\n\n    ZSTD_cwksp_mark_tables_dirty(&dstCCtx->workspace);\n\n    /* copy tables */\n    {   size_t const chainSize = ZSTD_allocateChainTable(srcCCtx->appliedParams.cParams.strategy,\n                                                         srcCCtx->appliedParams.useRowMatchFinder,\n                                                         0 /* forDDSDict */)\n                                    ? ((size_t)1 << srcCCtx->appliedParams.cParams.chainLog)\n                                    : 0;\n        size_t const hSize =  (size_t)1 << srcCCtx->appliedParams.cParams.hashLog;\n        U32 const h3log = srcCCtx->blockState.matchState.hashLog3;\n        size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0;\n\n        ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable,\n               srcCCtx->blockState.matchState.hashTable,\n               hSize * sizeof(U32));\n        ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable,\n               srcCCtx->blockState.matchState.chainTable,\n               chainSize * sizeof(U32));\n        ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3,\n               srcCCtx->blockState.matchState.hashTable3,\n               h3Size * sizeof(U32));\n    }\n\n    ZSTD_cwksp_mark_tables_clean(&dstCCtx->workspace);\n\n    /* copy dictionary offsets */\n    {\n        const ZSTD_MatchState_t* srcMatchState = &srcCCtx->blockState.matchState;\n        ZSTD_MatchState_t* dstMatchState = &dstCCtx->blockState.matchState;\n        dstMatchState->window       = srcMatchState->window;\n        dstMatchState->nextToUpdate = srcMatchState->nextToUpdate;\n        dstMatchState->loadedDictEnd= srcMatchState->loadedDictEnd;\n    }\n    dstCCtx->dictID = srcCCtx->dictID;\n    dstCCtx->dictContentSize = srcCCtx->dictContentSize;\n\n    /* copy block state */\n    ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock));\n\n    return 0;\n}\n\n/*! ZSTD_copyCCtx() :\n *  Duplicate an existing context `srcCCtx` into another one `dstCCtx`.\n *  Only works during stage ZSTDcs_init (i.e. after creation, but before first call to ZSTD_compressContinue()).\n *  pledgedSrcSize==0 means \"unknown\".\n*   @return : 0, or an error code */\nsize_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize)\n{\n    ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };\n    ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy;\n    ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1);\n    if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN;\n    fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN);\n\n    return ZSTD_copyCCtx_internal(dstCCtx, srcCCtx,\n                                fParams, pledgedSrcSize,\n                                zbuff);\n}\n\n\n#define ZSTD_ROWSIZE 16\n/*! ZSTD_reduceTable() :\n *  reduce table indexes by `reducerValue`, or squash to zero.\n *  PreserveMark preserves \"unsorted mark\" for btlazy2 strategy.\n *  It must be set to a clear 0/1 value, to remove branch during inlining.\n *  Presume table size is a multiple of ZSTD_ROWSIZE\n *  to help auto-vectorization */\nFORCE_INLINE_TEMPLATE void\nZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark)\n{\n    int const nbRows = (int)size / ZSTD_ROWSIZE;\n    int cellNb = 0;\n    int rowNb;\n    /* Protect special index values < ZSTD_WINDOW_START_INDEX. */\n    U32 const reducerThreshold = reducerValue + ZSTD_WINDOW_START_INDEX;\n    assert((size & (ZSTD_ROWSIZE-1)) == 0);  /* multiple of ZSTD_ROWSIZE */\n    assert(size < (1U<<31));   /* can be cast to int */\n\n#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    /* To validate that the table reuse logic is sound, and that we don't\n     * access table space that we haven't cleaned, we re-\"poison\" the table\n     * space every time we mark it dirty.\n     *\n     * This function however is intended to operate on those dirty tables and\n     * re-clean them. So when this function is used correctly, we can unpoison\n     * the memory it operated on. This introduces a blind spot though, since\n     * if we now try to operate on __actually__ poisoned memory, we will not\n     * detect that. */\n    __msan_unpoison(table, size * sizeof(U32));\n#endif\n\n    for (rowNb=0 ; rowNb < nbRows ; rowNb++) {\n        int column;\n        for (column=0; column<ZSTD_ROWSIZE; column++) {\n            U32 newVal;\n            if (preserveMark && table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) {\n                /* This write is pointless, but is required(?) for the compiler\n                 * to auto-vectorize the loop. */\n                newVal = ZSTD_DUBT_UNSORTED_MARK;\n            } else if (table[cellNb] < reducerThreshold) {\n                newVal = 0;\n            } else {\n                newVal = table[cellNb] - reducerValue;\n            }\n            table[cellNb] = newVal;\n            cellNb++;\n    }   }\n}\n\nstatic void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)\n{\n    ZSTD_reduceTable_internal(table, size, reducerValue, 0);\n}\n\nstatic void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)\n{\n    ZSTD_reduceTable_internal(table, size, reducerValue, 1);\n}\n\n/*! ZSTD_reduceIndex() :\n*   rescale all indexes to avoid future overflow (indexes are U32) */\nstatic void ZSTD_reduceIndex (ZSTD_MatchState_t* ms, ZSTD_CCtx_params const* params, const U32 reducerValue)\n{\n    {   U32 const hSize = (U32)1 << params->cParams.hashLog;\n        ZSTD_reduceTable(ms->hashTable, hSize, reducerValue);\n    }\n\n    if (ZSTD_allocateChainTable(params->cParams.strategy, params->useRowMatchFinder, (U32)ms->dedicatedDictSearch)) {\n        U32 const chainSize = (U32)1 << params->cParams.chainLog;\n        if (params->cParams.strategy == ZSTD_btlazy2)\n            ZSTD_reduceTable_btlazy2(ms->chainTable, chainSize, reducerValue);\n        else\n            ZSTD_reduceTable(ms->chainTable, chainSize, reducerValue);\n    }\n\n    if (ms->hashLog3) {\n        U32 const h3Size = (U32)1 << ms->hashLog3;\n        ZSTD_reduceTable(ms->hashTable3, h3Size, reducerValue);\n    }\n}\n\n\n/*-*******************************************************\n*  Block entropic compression\n*********************************************************/\n\n/* See doc/zstd_compression_format.md for detailed format description */\n\nint ZSTD_seqToCodes(const SeqStore_t* seqStorePtr)\n{\n    const SeqDef* const sequences = seqStorePtr->sequencesStart;\n    BYTE* const llCodeTable = seqStorePtr->llCode;\n    BYTE* const ofCodeTable = seqStorePtr->ofCode;\n    BYTE* const mlCodeTable = seqStorePtr->mlCode;\n    U32 const nbSeq = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    U32 u;\n    int longOffsets = 0;\n    assert(nbSeq <= seqStorePtr->maxNbSeq);\n    for (u=0; u<nbSeq; u++) {\n        U32 const llv = sequences[u].litLength;\n        U32 const ofCode = ZSTD_highbit32(sequences[u].offBase);\n        U32 const mlv = sequences[u].mlBase;\n        llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);\n        ofCodeTable[u] = (BYTE)ofCode;\n        mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);\n        assert(!(MEM_64bits() && ofCode >= STREAM_ACCUMULATOR_MIN));\n        if (MEM_32bits() && ofCode >= STREAM_ACCUMULATOR_MIN)\n            longOffsets = 1;\n    }\n    if (seqStorePtr->longLengthType==ZSTD_llt_literalLength)\n        llCodeTable[seqStorePtr->longLengthPos] = MaxLL;\n    if (seqStorePtr->longLengthType==ZSTD_llt_matchLength)\n        mlCodeTable[seqStorePtr->longLengthPos] = MaxML;\n    return longOffsets;\n}\n\n/* ZSTD_useTargetCBlockSize():\n * Returns if target compressed block size param is being used.\n * If used, compression will do best effort to make a compressed block size to be around targetCBlockSize.\n * Returns 1 if true, 0 otherwise. */\nstatic int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)\n{\n    DEBUGLOG(5, \"ZSTD_useTargetCBlockSize (targetCBlockSize=%zu)\", cctxParams->targetCBlockSize);\n    return (cctxParams->targetCBlockSize != 0);\n}\n\n/* ZSTD_blockSplitterEnabled():\n * Returns if block splitting param is being used\n * If used, compression will do best effort to split a block in order to improve compression ratio.\n * At the time this function is called, the parameter must be finalized.\n * Returns 1 if true, 0 otherwise. */\nstatic int ZSTD_blockSplitterEnabled(ZSTD_CCtx_params* cctxParams)\n{\n    DEBUGLOG(5, \"ZSTD_blockSplitterEnabled (postBlockSplitter=%d)\", cctxParams->postBlockSplitter);\n    assert(cctxParams->postBlockSplitter != ZSTD_ps_auto);\n    return (cctxParams->postBlockSplitter == ZSTD_ps_enable);\n}\n\n/* Type returned by ZSTD_buildSequencesStatistics containing finalized symbol encoding types\n * and size of the sequences statistics\n */\ntypedef struct {\n    U32 LLtype;\n    U32 Offtype;\n    U32 MLtype;\n    size_t size;\n    size_t lastCountSize; /* Accounts for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */\n    int longOffsets;\n} ZSTD_symbolEncodingTypeStats_t;\n\n/* ZSTD_buildSequencesStatistics():\n * Returns a ZSTD_symbolEncodingTypeStats_t, or a zstd error code in the `size` field.\n * Modifies `nextEntropy` to have the appropriate values as a side effect.\n * nbSeq must be greater than 0.\n *\n * entropyWkspSize must be of size at least ENTROPY_WORKSPACE_SIZE - (MaxSeq + 1)*sizeof(U32)\n */\nstatic ZSTD_symbolEncodingTypeStats_t\nZSTD_buildSequencesStatistics(\n                const SeqStore_t* seqStorePtr, size_t nbSeq,\n                const ZSTD_fseCTables_t* prevEntropy, ZSTD_fseCTables_t* nextEntropy,\n                      BYTE* dst, const BYTE* const dstEnd,\n                      ZSTD_strategy strategy, unsigned* countWorkspace,\n                      void* entropyWorkspace, size_t entropyWkspSize)\n{\n    BYTE* const ostart = dst;\n    const BYTE* const oend = dstEnd;\n    BYTE* op = ostart;\n    FSE_CTable* CTable_LitLength = nextEntropy->litlengthCTable;\n    FSE_CTable* CTable_OffsetBits = nextEntropy->offcodeCTable;\n    FSE_CTable* CTable_MatchLength = nextEntropy->matchlengthCTable;\n    const BYTE* const ofCodeTable = seqStorePtr->ofCode;\n    const BYTE* const llCodeTable = seqStorePtr->llCode;\n    const BYTE* const mlCodeTable = seqStorePtr->mlCode;\n    ZSTD_symbolEncodingTypeStats_t stats;\n\n    stats.lastCountSize = 0;\n    /* convert length/distances into codes */\n    stats.longOffsets = ZSTD_seqToCodes(seqStorePtr);\n    assert(op <= oend);\n    assert(nbSeq != 0); /* ZSTD_selectEncodingType() divides by nbSeq */\n    /* build CTable for Literal Lengths */\n    {   unsigned max = MaxLL;\n        size_t const mostFrequent = HIST_countFast_wksp(countWorkspace, &max, llCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */\n        DEBUGLOG(5, \"Building LL table\");\n        nextEntropy->litlength_repeatMode = prevEntropy->litlength_repeatMode;\n        stats.LLtype = ZSTD_selectEncodingType(&nextEntropy->litlength_repeatMode,\n                                        countWorkspace, max, mostFrequent, nbSeq,\n                                        LLFSELog, prevEntropy->litlengthCTable,\n                                        LL_defaultNorm, LL_defaultNormLog,\n                                        ZSTD_defaultAllowed, strategy);\n        assert(set_basic < set_compressed && set_rle < set_compressed);\n        assert(!(stats.LLtype < set_compressed && nextEntropy->litlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */\n        {   size_t const countSize = ZSTD_buildCTable(\n                op, (size_t)(oend - op),\n                CTable_LitLength, LLFSELog, (SymbolEncodingType_e)stats.LLtype,\n                countWorkspace, max, llCodeTable, nbSeq,\n                LL_defaultNorm, LL_defaultNormLog, MaxLL,\n                prevEntropy->litlengthCTable,\n                sizeof(prevEntropy->litlengthCTable),\n                entropyWorkspace, entropyWkspSize);\n            if (ZSTD_isError(countSize)) {\n                DEBUGLOG(3, \"ZSTD_buildCTable for LitLens failed\");\n                stats.size = countSize;\n                return stats;\n            }\n            if (stats.LLtype == set_compressed)\n                stats.lastCountSize = countSize;\n            op += countSize;\n            assert(op <= oend);\n    }   }\n    /* build CTable for Offsets */\n    {   unsigned max = MaxOff;\n        size_t const mostFrequent = HIST_countFast_wksp(\n            countWorkspace, &max, ofCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);  /* can't fail */\n        /* We can only use the basic table if max <= DefaultMaxOff, otherwise the offsets are too large */\n        ZSTD_DefaultPolicy_e const defaultPolicy = (max <= DefaultMaxOff) ? ZSTD_defaultAllowed : ZSTD_defaultDisallowed;\n        DEBUGLOG(5, \"Building OF table\");\n        nextEntropy->offcode_repeatMode = prevEntropy->offcode_repeatMode;\n        stats.Offtype = ZSTD_selectEncodingType(&nextEntropy->offcode_repeatMode,\n                                        countWorkspace, max, mostFrequent, nbSeq,\n                                        OffFSELog, prevEntropy->offcodeCTable,\n                                        OF_defaultNorm, OF_defaultNormLog,\n                                        defaultPolicy, strategy);\n        assert(!(stats.Offtype < set_compressed && nextEntropy->offcode_repeatMode != FSE_repeat_none)); /* We don't copy tables */\n        {   size_t const countSize = ZSTD_buildCTable(\n                op, (size_t)(oend - op),\n                CTable_OffsetBits, OffFSELog, (SymbolEncodingType_e)stats.Offtype,\n                countWorkspace, max, ofCodeTable, nbSeq,\n                OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,\n                prevEntropy->offcodeCTable,\n                sizeof(prevEntropy->offcodeCTable),\n                entropyWorkspace, entropyWkspSize);\n            if (ZSTD_isError(countSize)) {\n                DEBUGLOG(3, \"ZSTD_buildCTable for Offsets failed\");\n                stats.size = countSize;\n                return stats;\n            }\n            if (stats.Offtype == set_compressed)\n                stats.lastCountSize = countSize;\n            op += countSize;\n            assert(op <= oend);\n    }   }\n    /* build CTable for MatchLengths */\n    {   unsigned max = MaxML;\n        size_t const mostFrequent = HIST_countFast_wksp(\n            countWorkspace, &max, mlCodeTable, nbSeq, entropyWorkspace, entropyWkspSize);   /* can't fail */\n        DEBUGLOG(5, \"Building ML table (remaining space : %i)\", (int)(oend-op));\n        nextEntropy->matchlength_repeatMode = prevEntropy->matchlength_repeatMode;\n        stats.MLtype = ZSTD_selectEncodingType(&nextEntropy->matchlength_repeatMode,\n                                        countWorkspace, max, mostFrequent, nbSeq,\n                                        MLFSELog, prevEntropy->matchlengthCTable,\n                                        ML_defaultNorm, ML_defaultNormLog,\n                                        ZSTD_defaultAllowed, strategy);\n        assert(!(stats.MLtype < set_compressed && nextEntropy->matchlength_repeatMode != FSE_repeat_none)); /* We don't copy tables */\n        {   size_t const countSize = ZSTD_buildCTable(\n                op, (size_t)(oend - op),\n                CTable_MatchLength, MLFSELog, (SymbolEncodingType_e)stats.MLtype,\n                countWorkspace, max, mlCodeTable, nbSeq,\n                ML_defaultNorm, ML_defaultNormLog, MaxML,\n                prevEntropy->matchlengthCTable,\n                sizeof(prevEntropy->matchlengthCTable),\n                entropyWorkspace, entropyWkspSize);\n            if (ZSTD_isError(countSize)) {\n                DEBUGLOG(3, \"ZSTD_buildCTable for MatchLengths failed\");\n                stats.size = countSize;\n                return stats;\n            }\n            if (stats.MLtype == set_compressed)\n                stats.lastCountSize = countSize;\n            op += countSize;\n            assert(op <= oend);\n    }   }\n    stats.size = (size_t)(op-ostart);\n    return stats;\n}\n\n/* ZSTD_entropyCompressSeqStore_internal():\n * compresses both literals and sequences\n * Returns compressed size of block, or a zstd error.\n */\n#define SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO 20\nMEM_STATIC size_t\nZSTD_entropyCompressSeqStore_internal(\n                              void* dst, size_t dstCapacity,\n                        const void* literals, size_t litSize,\n                        const SeqStore_t* seqStorePtr,\n                        const ZSTD_entropyCTables_t* prevEntropy,\n                              ZSTD_entropyCTables_t* nextEntropy,\n                        const ZSTD_CCtx_params* cctxParams,\n                              void* entropyWorkspace, size_t entropyWkspSize,\n                        const int bmi2)\n{\n    ZSTD_strategy const strategy = cctxParams->cParams.strategy;\n    unsigned* count = (unsigned*)entropyWorkspace;\n    FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable;\n    FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable;\n    FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable;\n    const SeqDef* const sequences = seqStorePtr->sequencesStart;\n    const size_t nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    const BYTE* const ofCodeTable = seqStorePtr->ofCode;\n    const BYTE* const llCodeTable = seqStorePtr->llCode;\n    const BYTE* const mlCodeTable = seqStorePtr->mlCode;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    size_t lastCountSize;\n    int longOffsets = 0;\n\n    entropyWorkspace = count + (MaxSeq + 1);\n    entropyWkspSize -= (MaxSeq + 1) * sizeof(*count);\n\n    DEBUGLOG(5, \"ZSTD_entropyCompressSeqStore_internal (nbSeq=%zu, dstCapacity=%zu)\", nbSeq, dstCapacity);\n    ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));\n    assert(entropyWkspSize >= HUF_WORKSPACE_SIZE);\n\n    /* Compress literals */\n    {   size_t const numSequences = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n        /* Base suspicion of uncompressibility on ratio of literals to sequences */\n        int const suspectUncompressible = (numSequences == 0) || (litSize / numSequences >= SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO);\n\n        size_t const cSize = ZSTD_compressLiterals(\n                                    op, dstCapacity,\n                                    literals, litSize,\n                                    entropyWorkspace, entropyWkspSize,\n                                    &prevEntropy->huf, &nextEntropy->huf,\n                                    cctxParams->cParams.strategy,\n                                    ZSTD_literalsCompressionIsDisabled(cctxParams),\n                                    suspectUncompressible, bmi2);\n        FORWARD_IF_ERROR(cSize, \"ZSTD_compressLiterals failed\");\n        assert(cSize <= dstCapacity);\n        op += cSize;\n    }\n\n    /* Sequences Header */\n    RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,\n                    dstSize_tooSmall, \"Can't fit seq hdr in output buf!\");\n    if (nbSeq < 128) {\n        *op++ = (BYTE)nbSeq;\n    } else if (nbSeq < LONGNBSEQ) {\n        op[0] = (BYTE)((nbSeq>>8) + 0x80);\n        op[1] = (BYTE)nbSeq;\n        op+=2;\n    } else {\n        op[0]=0xFF;\n        MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ));\n        op+=3;\n    }\n    assert(op <= oend);\n    if (nbSeq==0) {\n        /* Copy the old tables over as if we repeated them */\n        ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse));\n        return (size_t)(op - ostart);\n    }\n    {   BYTE* const seqHead = op++;\n        /* build stats for sequences */\n        const ZSTD_symbolEncodingTypeStats_t stats =\n                ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,\n                                             &prevEntropy->fse, &nextEntropy->fse,\n                                              op, oend,\n                                              strategy, count,\n                                              entropyWorkspace, entropyWkspSize);\n        FORWARD_IF_ERROR(stats.size, \"ZSTD_buildSequencesStatistics failed!\");\n        *seqHead = (BYTE)((stats.LLtype<<6) + (stats.Offtype<<4) + (stats.MLtype<<2));\n        lastCountSize = stats.lastCountSize;\n        op += stats.size;\n        longOffsets = stats.longOffsets;\n    }\n\n    {   size_t const bitstreamSize = ZSTD_encodeSequences(\n                                        op, (size_t)(oend - op),\n                                        CTable_MatchLength, mlCodeTable,\n                                        CTable_OffsetBits, ofCodeTable,\n                                        CTable_LitLength, llCodeTable,\n                                        sequences, nbSeq,\n                                        longOffsets, bmi2);\n        FORWARD_IF_ERROR(bitstreamSize, \"ZSTD_encodeSequences failed\");\n        op += bitstreamSize;\n        assert(op <= oend);\n        /* zstd versions <= 1.3.4 mistakenly report corruption when\n         * FSE_readNCount() receives a buffer < 4 bytes.\n         * Fixed by https://github.com/facebook/zstd/pull/1146.\n         * This can happen when the last set_compressed table present is 2\n         * bytes and the bitstream is only one byte.\n         * In this exceedingly rare case, we will simply emit an uncompressed\n         * block, since it isn't worth optimizing.\n         */\n        if (lastCountSize && (lastCountSize + bitstreamSize) < 4) {\n            /* lastCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */\n            assert(lastCountSize + bitstreamSize == 3);\n            DEBUGLOG(5, \"Avoiding bug in zstd decoder in versions <= 1.3.4 by \"\n                        \"emitting an uncompressed block.\");\n            return 0;\n        }\n    }\n\n    DEBUGLOG(5, \"compressed block size : %u\", (unsigned)(op - ostart));\n    return (size_t)(op - ostart);\n}\n\nstatic size_t\nZSTD_entropyCompressSeqStore_wExtLitBuffer(\n                          void* dst, size_t dstCapacity,\n                    const void* literals, size_t litSize,\n                          size_t blockSize,\n                    const SeqStore_t* seqStorePtr,\n                    const ZSTD_entropyCTables_t* prevEntropy,\n                          ZSTD_entropyCTables_t* nextEntropy,\n                    const ZSTD_CCtx_params* cctxParams,\n                          void* entropyWorkspace, size_t entropyWkspSize,\n                          int bmi2)\n{\n    size_t const cSize = ZSTD_entropyCompressSeqStore_internal(\n                            dst, dstCapacity,\n                            literals, litSize,\n                            seqStorePtr, prevEntropy, nextEntropy, cctxParams,\n                            entropyWorkspace, entropyWkspSize, bmi2);\n    if (cSize == 0) return 0;\n    /* When srcSize <= dstCapacity, there is enough space to write a raw uncompressed block.\n     * Since we ran out of space, block must be not compressible, so fall back to raw uncompressed block.\n     */\n    if ((cSize == ERROR(dstSize_tooSmall)) & (blockSize <= dstCapacity)) {\n        DEBUGLOG(4, \"not enough dstCapacity (%zu) for ZSTD_entropyCompressSeqStore_internal()=> do not compress block\", dstCapacity);\n        return 0;  /* block not compressed */\n    }\n    FORWARD_IF_ERROR(cSize, \"ZSTD_entropyCompressSeqStore_internal failed\");\n\n    /* Check compressibility */\n    {   size_t const maxCSize = blockSize - ZSTD_minGain(blockSize, cctxParams->cParams.strategy);\n        if (cSize >= maxCSize) return 0;  /* block not compressed */\n    }\n    DEBUGLOG(5, \"ZSTD_entropyCompressSeqStore() cSize: %zu\", cSize);\n    /* libzstd decoder before  > v1.5.4 is not compatible with compressed blocks of size ZSTD_BLOCKSIZE_MAX exactly.\n     * This restriction is indirectly already fulfilled by respecting ZSTD_minGain() condition above.\n     */\n    assert(cSize < ZSTD_BLOCKSIZE_MAX);\n    return cSize;\n}\n\nstatic size_t\nZSTD_entropyCompressSeqStore(\n                    const SeqStore_t* seqStorePtr,\n                    const ZSTD_entropyCTables_t* prevEntropy,\n                          ZSTD_entropyCTables_t* nextEntropy,\n                    const ZSTD_CCtx_params* cctxParams,\n                          void* dst, size_t dstCapacity,\n                          size_t srcSize,\n                          void* entropyWorkspace, size_t entropyWkspSize,\n                          int bmi2)\n{\n    return ZSTD_entropyCompressSeqStore_wExtLitBuffer(\n                dst, dstCapacity,\n                seqStorePtr->litStart, (size_t)(seqStorePtr->lit - seqStorePtr->litStart),\n                srcSize,\n                seqStorePtr,\n                prevEntropy, nextEntropy,\n                cctxParams,\n                entropyWorkspace, entropyWkspSize,\n                bmi2);\n}\n\n/* ZSTD_selectBlockCompressor() :\n * Not static, but internal use only (used by long distance matcher)\n * assumption : strat is a valid strategy */\nZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode)\n{\n    static const ZSTD_BlockCompressor_f blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {\n        { ZSTD_compressBlock_fast  /* default for 0 */,\n          ZSTD_compressBlock_fast,\n          ZSTD_COMPRESSBLOCK_DOUBLEFAST,\n          ZSTD_COMPRESSBLOCK_GREEDY,\n          ZSTD_COMPRESSBLOCK_LAZY,\n          ZSTD_COMPRESSBLOCK_LAZY2,\n          ZSTD_COMPRESSBLOCK_BTLAZY2,\n          ZSTD_COMPRESSBLOCK_BTOPT,\n          ZSTD_COMPRESSBLOCK_BTULTRA,\n          ZSTD_COMPRESSBLOCK_BTULTRA2\n        },\n        { ZSTD_compressBlock_fast_extDict  /* default for 0 */,\n          ZSTD_compressBlock_fast_extDict,\n          ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT,\n          ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT,\n          ZSTD_COMPRESSBLOCK_LAZY_EXTDICT,\n          ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT,\n          ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT\n        },\n        { ZSTD_compressBlock_fast_dictMatchState  /* default for 0 */,\n          ZSTD_compressBlock_fast_dictMatchState,\n          ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE,\n          ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE\n        },\n        { NULL  /* default for 0 */,\n          NULL,\n          NULL,\n          ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH,\n          ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH,\n          ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH,\n          NULL,\n          NULL,\n          NULL,\n          NULL }\n    };\n    ZSTD_BlockCompressor_f selectedCompressor;\n    ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1);\n\n    assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat));\n    DEBUGLOG(5, \"Selected block compressor: dictMode=%d strat=%d rowMatchfinder=%d\", (int)dictMode, (int)strat, (int)useRowMatchFinder);\n    if (ZSTD_rowMatchFinderUsed(strat, useRowMatchFinder)) {\n        static const ZSTD_BlockCompressor_f rowBasedBlockCompressors[4][3] = {\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_ROW\n            },\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW\n            },\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW\n            },\n            {\n                ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW,\n                ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW\n            }\n        };\n        DEBUGLOG(5, \"Selecting a row-based matchfinder\");\n        assert(useRowMatchFinder != ZSTD_ps_auto);\n        selectedCompressor = rowBasedBlockCompressors[(int)dictMode][(int)strat - (int)ZSTD_greedy];\n    } else {\n        selectedCompressor = blockCompressor[(int)dictMode][(int)strat];\n    }\n    assert(selectedCompressor != NULL);\n    return selectedCompressor;\n}\n\nstatic void ZSTD_storeLastLiterals(SeqStore_t* seqStorePtr,\n                                   const BYTE* anchor, size_t lastLLSize)\n{\n    ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize);\n    seqStorePtr->lit += lastLLSize;\n}\n\nvoid ZSTD_resetSeqStore(SeqStore_t* ssPtr)\n{\n    ssPtr->lit = ssPtr->litStart;\n    ssPtr->sequences = ssPtr->sequencesStart;\n    ssPtr->longLengthType = ZSTD_llt_none;\n}\n\n/* ZSTD_postProcessSequenceProducerResult() :\n * Validates and post-processes sequences obtained through the external matchfinder API:\n *   - Checks whether nbExternalSeqs represents an error condition.\n *   - Appends a block delimiter to outSeqs if one is not already present.\n *     See zstd.h for context regarding block delimiters.\n * Returns the number of sequences after post-processing, or an error code. */\nstatic size_t ZSTD_postProcessSequenceProducerResult(\n    ZSTD_Sequence* outSeqs, size_t nbExternalSeqs, size_t outSeqsCapacity, size_t srcSize\n) {\n    RETURN_ERROR_IF(\n        nbExternalSeqs > outSeqsCapacity,\n        sequenceProducer_failed,\n        \"External sequence producer returned error code %lu\",\n        (unsigned long)nbExternalSeqs\n    );\n\n    RETURN_ERROR_IF(\n        nbExternalSeqs == 0 && srcSize > 0,\n        sequenceProducer_failed,\n        \"Got zero sequences from external sequence producer for a non-empty src buffer!\"\n    );\n\n    if (srcSize == 0) {\n        ZSTD_memset(&outSeqs[0], 0, sizeof(ZSTD_Sequence));\n        return 1;\n    }\n\n    {\n        ZSTD_Sequence const lastSeq = outSeqs[nbExternalSeqs - 1];\n\n        /* We can return early if lastSeq is already a block delimiter. */\n        if (lastSeq.offset == 0 && lastSeq.matchLength == 0) {\n            return nbExternalSeqs;\n        }\n\n        /* This error condition is only possible if the external matchfinder\n         * produced an invalid parse, by definition of ZSTD_sequenceBound(). */\n        RETURN_ERROR_IF(\n            nbExternalSeqs == outSeqsCapacity,\n            sequenceProducer_failed,\n            \"nbExternalSeqs == outSeqsCapacity but lastSeq is not a block delimiter!\"\n        );\n\n        /* lastSeq is not a block delimiter, so we need to append one. */\n        ZSTD_memset(&outSeqs[nbExternalSeqs], 0, sizeof(ZSTD_Sequence));\n        return nbExternalSeqs + 1;\n    }\n}\n\n/* ZSTD_fastSequenceLengthSum() :\n * Returns sum(litLen) + sum(matchLen) + lastLits for *seqBuf*.\n * Similar to another function in zstd_compress.c (determine_blockSize),\n * except it doesn't check for a block delimiter to end summation.\n * Removing the early exit allows the compiler to auto-vectorize (https://godbolt.org/z/cY1cajz9P).\n * This function can be deleted and replaced by determine_blockSize after we resolve issue #3456. */\nstatic size_t ZSTD_fastSequenceLengthSum(ZSTD_Sequence const* seqBuf, size_t seqBufSize) {\n    size_t matchLenSum, litLenSum, i;\n    matchLenSum = 0;\n    litLenSum = 0;\n    for (i = 0; i < seqBufSize; i++) {\n        litLenSum += seqBuf[i].litLength;\n        matchLenSum += seqBuf[i].matchLength;\n    }\n    return litLenSum + matchLenSum;\n}\n\n/**\n * Function to validate sequences produced by a block compressor.\n */\nstatic void ZSTD_validateSeqStore(const SeqStore_t* seqStore, const ZSTD_compressionParameters* cParams)\n{\n#if DEBUGLEVEL >= 1\n    const SeqDef* seq = seqStore->sequencesStart;\n    const SeqDef* const seqEnd = seqStore->sequences;\n    size_t const matchLenLowerBound = cParams->minMatch == 3 ? 3 : 4;\n    for (; seq < seqEnd; ++seq) {\n        const ZSTD_SequenceLength seqLength = ZSTD_getSequenceLength(seqStore, seq);\n        assert(seqLength.matchLength >= matchLenLowerBound);\n        (void)seqLength;\n        (void)matchLenLowerBound;\n    }\n#else\n    (void)seqStore;\n    (void)cParams;\n#endif\n}\n\nstatic size_t\nZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,\n                                   ZSTD_SequencePosition* seqPos,\n                             const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                             const void* src, size_t blockSize,\n                                   ZSTD_ParamSwitch_e externalRepSearch);\n\ntypedef enum { ZSTDbss_compress, ZSTDbss_noCompress } ZSTD_BuildSeqStore_e;\n\nstatic size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)\n{\n    ZSTD_MatchState_t* const ms = &zc->blockState.matchState;\n    DEBUGLOG(5, \"ZSTD_buildSeqStore (srcSize=%zu)\", srcSize);\n    assert(srcSize <= ZSTD_BLOCKSIZE_MAX);\n    /* Assert that we have correctly flushed the ctx params into the ms's copy */\n    ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams);\n    /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding\n     * additional 1. We need to revisit and change this logic to be more consistent */\n    if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) {\n        if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) {\n            ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize);\n        } else {\n            ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch);\n        }\n        return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */\n    }\n    ZSTD_resetSeqStore(&(zc->seqStore));\n    /* required for optimal parser to read stats from dictionary */\n    ms->opt.symbolCosts = &zc->blockState.prevCBlock->entropy;\n    /* tell the optimal parser how we expect to compress literals */\n    ms->opt.literalCompressionMode = zc->appliedParams.literalCompressionMode;\n    /* a gap between an attached dict and the current window is not safe,\n     * they must remain adjacent,\n     * and when that stops being the case, the dict must be unset */\n    assert(ms->dictMatchState == NULL || ms->loadedDictEnd == ms->window.dictLimit);\n\n    /* limited update after a very long match */\n    {   const BYTE* const base = ms->window.base;\n        const BYTE* const istart = (const BYTE*)src;\n        const U32 curr = (U32)(istart-base);\n        if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1));   /* ensure no overflow */\n        if (curr > ms->nextToUpdate + 384)\n            ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384));\n    }\n\n    /* select and store sequences */\n    {   ZSTD_dictMode_e const dictMode = ZSTD_matchState_dictMode(ms);\n        size_t lastLLSize;\n        {   int i;\n            for (i = 0; i < ZSTD_REP_NUM; ++i)\n                zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];\n        }\n        if (zc->externSeqStore.pos < zc->externSeqStore.size) {\n            assert(zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_disable);\n\n            /* External matchfinder + LDM is technically possible, just not implemented yet.\n             * We need to revisit soon and implement it. */\n            RETURN_ERROR_IF(\n                ZSTD_hasExtSeqProd(&zc->appliedParams),\n                parameter_combination_unsupported,\n                \"Long-distance matching with external sequence producer enabled is not currently supported.\"\n            );\n\n            /* Updates ldmSeqStore.pos */\n            lastLLSize =\n                ZSTD_ldm_blockCompress(&zc->externSeqStore,\n                                       ms, &zc->seqStore,\n                                       zc->blockState.nextCBlock->rep,\n                                       zc->appliedParams.useRowMatchFinder,\n                                       src, srcSize);\n            assert(zc->externSeqStore.pos <= zc->externSeqStore.size);\n        } else if (zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {\n            RawSeqStore_t ldmSeqStore = kNullRawSeqStore;\n\n            /* External matchfinder + LDM is technically possible, just not implemented yet.\n             * We need to revisit soon and implement it. */\n            RETURN_ERROR_IF(\n                ZSTD_hasExtSeqProd(&zc->appliedParams),\n                parameter_combination_unsupported,\n                \"Long-distance matching with external sequence producer enabled is not currently supported.\"\n            );\n\n            ldmSeqStore.seq = zc->ldmSequences;\n            ldmSeqStore.capacity = zc->maxNbLdmSequences;\n            /* Updates ldmSeqStore.size */\n            FORWARD_IF_ERROR(ZSTD_ldm_generateSequences(&zc->ldmState, &ldmSeqStore,\n                                               &zc->appliedParams.ldmParams,\n                                               src, srcSize), \"\");\n            /* Updates ldmSeqStore.pos */\n            lastLLSize =\n                ZSTD_ldm_blockCompress(&ldmSeqStore,\n                                       ms, &zc->seqStore,\n                                       zc->blockState.nextCBlock->rep,\n                                       zc->appliedParams.useRowMatchFinder,\n                                       src, srcSize);\n            assert(ldmSeqStore.pos == ldmSeqStore.size);\n        } else if (ZSTD_hasExtSeqProd(&zc->appliedParams)) {\n            assert(\n                zc->extSeqBufCapacity >= ZSTD_sequenceBound(srcSize)\n            );\n            assert(zc->appliedParams.extSeqProdFunc != NULL);\n\n            {   U32 const windowSize = (U32)1 << zc->appliedParams.cParams.windowLog;\n\n                size_t const nbExternalSeqs = (zc->appliedParams.extSeqProdFunc)(\n                    zc->appliedParams.extSeqProdState,\n                    zc->extSeqBuf,\n                    zc->extSeqBufCapacity,\n                    src, srcSize,\n                    NULL, 0,  /* dict and dictSize, currently not supported */\n                    zc->appliedParams.compressionLevel,\n                    windowSize\n                );\n\n                size_t const nbPostProcessedSeqs = ZSTD_postProcessSequenceProducerResult(\n                    zc->extSeqBuf,\n                    nbExternalSeqs,\n                    zc->extSeqBufCapacity,\n                    srcSize\n                );\n\n                /* Return early if there is no error, since we don't need to worry about last literals */\n                if (!ZSTD_isError(nbPostProcessedSeqs)) {\n                    ZSTD_SequencePosition seqPos = {0,0,0};\n                    size_t const seqLenSum = ZSTD_fastSequenceLengthSum(zc->extSeqBuf, nbPostProcessedSeqs);\n                    RETURN_ERROR_IF(seqLenSum > srcSize, externalSequences_invalid, \"External sequences imply too large a block!\");\n                    FORWARD_IF_ERROR(\n                        ZSTD_transferSequences_wBlockDelim(\n                            zc, &seqPos,\n                            zc->extSeqBuf, nbPostProcessedSeqs,\n                            src, srcSize,\n                            zc->appliedParams.searchForExternalRepcodes\n                        ),\n                        \"Failed to copy external sequences to seqStore!\"\n                    );\n                    ms->ldmSeqStore = NULL;\n                    DEBUGLOG(5, \"Copied %lu sequences from external sequence producer to internal seqStore.\", (unsigned long)nbExternalSeqs);\n                    return ZSTDbss_compress;\n                }\n\n                /* Propagate the error if fallback is disabled */\n                if (!zc->appliedParams.enableMatchFinderFallback) {\n                    return nbPostProcessedSeqs;\n                }\n\n                /* Fallback to software matchfinder */\n                {   ZSTD_BlockCompressor_f const blockCompressor =\n                        ZSTD_selectBlockCompressor(\n                            zc->appliedParams.cParams.strategy,\n                            zc->appliedParams.useRowMatchFinder,\n                            dictMode);\n                    ms->ldmSeqStore = NULL;\n                    DEBUGLOG(\n                        5,\n                        \"External sequence producer returned error code %lu. Falling back to internal parser.\",\n                        (unsigned long)nbExternalSeqs\n                    );\n                    lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);\n            }   }\n        } else {   /* not long range mode and no external matchfinder */\n            ZSTD_BlockCompressor_f const blockCompressor = ZSTD_selectBlockCompressor(\n                    zc->appliedParams.cParams.strategy,\n                    zc->appliedParams.useRowMatchFinder,\n                    dictMode);\n            ms->ldmSeqStore = NULL;\n            lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize);\n        }\n        {   const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize;\n            ZSTD_storeLastLiterals(&zc->seqStore, lastLiterals, lastLLSize);\n    }   }\n    ZSTD_validateSeqStore(&zc->seqStore, &zc->appliedParams.cParams);\n    return ZSTDbss_compress;\n}\n\nstatic size_t ZSTD_copyBlockSequences(SeqCollector* seqCollector, const SeqStore_t* seqStore, const U32 prevRepcodes[ZSTD_REP_NUM])\n{\n    const SeqDef* inSeqs = seqStore->sequencesStart;\n    const size_t nbInSequences = (size_t)(seqStore->sequences - inSeqs);\n    const size_t nbInLiterals = (size_t)(seqStore->lit - seqStore->litStart);\n\n    ZSTD_Sequence* outSeqs = seqCollector->seqIndex == 0 ? seqCollector->seqStart : seqCollector->seqStart + seqCollector->seqIndex;\n    const size_t nbOutSequences = nbInSequences + 1;\n    size_t nbOutLiterals = 0;\n    Repcodes_t repcodes;\n    size_t i;\n\n    /* Bounds check that we have enough space for every input sequence\n     * and the block delimiter\n     */\n    assert(seqCollector->seqIndex <= seqCollector->maxSequences);\n    RETURN_ERROR_IF(\n        nbOutSequences > (size_t)(seqCollector->maxSequences - seqCollector->seqIndex),\n        dstSize_tooSmall,\n        \"Not enough space to copy sequences\");\n\n    ZSTD_memcpy(&repcodes, prevRepcodes, sizeof(repcodes));\n    for (i = 0; i < nbInSequences; ++i) {\n        U32 rawOffset;\n        outSeqs[i].litLength = inSeqs[i].litLength;\n        outSeqs[i].matchLength = inSeqs[i].mlBase + MINMATCH;\n        outSeqs[i].rep = 0;\n\n        /* Handle the possible single length >= 64K\n         * There can only be one because we add MINMATCH to every match length,\n         * and blocks are at most 128K.\n         */\n        if (i == seqStore->longLengthPos) {\n            if (seqStore->longLengthType == ZSTD_llt_literalLength) {\n                outSeqs[i].litLength += 0x10000;\n            } else if (seqStore->longLengthType == ZSTD_llt_matchLength) {\n                outSeqs[i].matchLength += 0x10000;\n            }\n        }\n\n        /* Determine the raw offset given the offBase, which may be a repcode. */\n        if (OFFBASE_IS_REPCODE(inSeqs[i].offBase)) {\n            const U32 repcode = OFFBASE_TO_REPCODE(inSeqs[i].offBase);\n            assert(repcode > 0);\n            outSeqs[i].rep = repcode;\n            if (outSeqs[i].litLength != 0) {\n                rawOffset = repcodes.rep[repcode - 1];\n            } else {\n                if (repcode == 3) {\n                    assert(repcodes.rep[0] > 1);\n                    rawOffset = repcodes.rep[0] - 1;\n                } else {\n                    rawOffset = repcodes.rep[repcode];\n                }\n            }\n        } else {\n            rawOffset = OFFBASE_TO_OFFSET(inSeqs[i].offBase);\n        }\n        outSeqs[i].offset = rawOffset;\n\n        /* Update repcode history for the sequence */\n        ZSTD_updateRep(repcodes.rep,\n                       inSeqs[i].offBase,\n                       inSeqs[i].litLength == 0);\n\n        nbOutLiterals += outSeqs[i].litLength;\n    }\n    /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.\n     * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker\n     * for the block boundary, according to the API.\n     */\n    assert(nbInLiterals >= nbOutLiterals);\n    {\n        const size_t lastLLSize = nbInLiterals - nbOutLiterals;\n        outSeqs[nbInSequences].litLength = (U32)lastLLSize;\n        outSeqs[nbInSequences].matchLength = 0;\n        outSeqs[nbInSequences].offset = 0;\n        assert(nbOutSequences == nbInSequences + 1);\n    }\n    seqCollector->seqIndex += nbOutSequences;\n    assert(seqCollector->seqIndex <= seqCollector->maxSequences);\n\n    return 0;\n}\n\nsize_t ZSTD_sequenceBound(size_t srcSize) {\n    const size_t maxNbSeq = (srcSize / ZSTD_MINMATCH_MIN) + 1;\n    const size_t maxNbDelims = (srcSize / ZSTD_BLOCKSIZE_MAX_MIN) + 1;\n    return maxNbSeq + maxNbDelims;\n}\n\nsize_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,\n                              size_t outSeqsSize, const void* src, size_t srcSize)\n{\n    const size_t dstCapacity = ZSTD_compressBound(srcSize);\n    void* dst; /* Make C90 happy. */\n    SeqCollector seqCollector;\n    {\n        int targetCBlockSize;\n        FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_targetCBlockSize, &targetCBlockSize), \"\");\n        RETURN_ERROR_IF(targetCBlockSize != 0, parameter_unsupported, \"targetCBlockSize != 0\");\n    }\n    {\n        int nbWorkers;\n        FORWARD_IF_ERROR(ZSTD_CCtx_getParameter(zc, ZSTD_c_nbWorkers, &nbWorkers), \"\");\n        RETURN_ERROR_IF(nbWorkers != 0, parameter_unsupported, \"nbWorkers != 0\");\n    }\n\n    dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem);\n    RETURN_ERROR_IF(dst == NULL, memory_allocation, \"NULL pointer!\");\n\n    seqCollector.collectSequences = 1;\n    seqCollector.seqStart = outSeqs;\n    seqCollector.seqIndex = 0;\n    seqCollector.maxSequences = outSeqsSize;\n    zc->seqCollector = seqCollector;\n\n    {\n        const size_t ret = ZSTD_compress2(zc, dst, dstCapacity, src, srcSize);\n        ZSTD_customFree(dst, ZSTD_defaultCMem);\n        FORWARD_IF_ERROR(ret, \"ZSTD_compress2 failed\");\n    }\n    assert(zc->seqCollector.seqIndex <= ZSTD_sequenceBound(srcSize));\n    return zc->seqCollector.seqIndex;\n}\n\nsize_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) {\n    size_t in = 0;\n    size_t out = 0;\n    for (; in < seqsSize; ++in) {\n        if (sequences[in].offset == 0 && sequences[in].matchLength == 0) {\n            if (in != seqsSize - 1) {\n                sequences[in+1].litLength += sequences[in].litLength;\n            }\n        } else {\n            sequences[out] = sequences[in];\n            ++out;\n        }\n    }\n    return out;\n}\n\n/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */\nstatic int ZSTD_isRLE(const BYTE* src, size_t length) {\n    const BYTE* ip = src;\n    const BYTE value = ip[0];\n    const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL);\n    const size_t unrollSize = sizeof(size_t) * 4;\n    const size_t unrollMask = unrollSize - 1;\n    const size_t prefixLength = length & unrollMask;\n    size_t i;\n    if (length == 1) return 1;\n    /* Check if prefix is RLE first before using unrolled loop */\n    if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) {\n        return 0;\n    }\n    for (i = prefixLength; i != length; i += unrollSize) {\n        size_t u;\n        for (u = 0; u < unrollSize; u += sizeof(size_t)) {\n            if (MEM_readST(ip + i + u) != valueST) {\n                return 0;\n    }   }   }\n    return 1;\n}\n\n/* Returns true if the given block may be RLE.\n * This is just a heuristic based on the compressibility.\n * It may return both false positives and false negatives.\n */\nstatic int ZSTD_maybeRLE(SeqStore_t const* seqStore)\n{\n    size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);\n    size_t const nbLits = (size_t)(seqStore->lit - seqStore->litStart);\n\n    return nbSeqs < 4 && nbLits < 10;\n}\n\nstatic void\nZSTD_blockState_confirmRepcodesAndEntropyTables(ZSTD_blockState_t* const bs)\n{\n    ZSTD_compressedBlockState_t* const tmp = bs->prevCBlock;\n    bs->prevCBlock = bs->nextCBlock;\n    bs->nextCBlock = tmp;\n}\n\n/* Writes the block header */\nstatic void\nwriteBlockHeader(void* op, size_t cSize, size_t blockSize, U32 lastBlock)\n{\n    U32 const cBlockHeader = cSize == 1 ?\n                        lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :\n                        lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);\n    MEM_writeLE24(op, cBlockHeader);\n    DEBUGLOG(5, \"writeBlockHeader: cSize: %zu blockSize: %zu lastBlock: %u\", cSize, blockSize, lastBlock);\n}\n\n/** ZSTD_buildBlockEntropyStats_literals() :\n *  Builds entropy for the literals.\n *  Stores literals block type (raw, rle, compressed, repeat) and\n *  huffman description table to hufMetadata.\n *  Requires ENTROPY_WORKSPACE_SIZE workspace\n * @return : size of huffman description table, or an error code\n */\nstatic size_t\nZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSize,\n                               const ZSTD_hufCTables_t* prevHuf,\n                                     ZSTD_hufCTables_t* nextHuf,\n                                     ZSTD_hufCTablesMetadata_t* hufMetadata,\n                               const int literalsCompressionIsDisabled,\n                                     void* workspace, size_t wkspSize,\n                                     int hufFlags)\n{\n    BYTE* const wkspStart = (BYTE*)workspace;\n    BYTE* const wkspEnd = wkspStart + wkspSize;\n    BYTE* const countWkspStart = wkspStart;\n    unsigned* const countWksp = (unsigned*)workspace;\n    const size_t countWkspSize = (HUF_SYMBOLVALUE_MAX + 1) * sizeof(unsigned);\n    BYTE* const nodeWksp = countWkspStart + countWkspSize;\n    const size_t nodeWkspSize = (size_t)(wkspEnd - nodeWksp);\n    unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX;\n    unsigned huffLog = LitHufLog;\n    HUF_repeat repeat = prevHuf->repeatMode;\n    DEBUGLOG(5, \"ZSTD_buildBlockEntropyStats_literals (srcSize=%zu)\", srcSize);\n\n    /* Prepare nextEntropy assuming reusing the existing table */\n    ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n\n    if (literalsCompressionIsDisabled) {\n        DEBUGLOG(5, \"set_basic - disabled\");\n        hufMetadata->hType = set_basic;\n        return 0;\n    }\n\n    /* small ? don't even attempt compression (speed opt) */\n#ifndef COMPRESS_LITERALS_SIZE_MIN\n# define COMPRESS_LITERALS_SIZE_MIN 63  /* heuristic */\n#endif\n    {   size_t const minLitSize = (prevHuf->repeatMode == HUF_repeat_valid) ? 6 : COMPRESS_LITERALS_SIZE_MIN;\n        if (srcSize <= minLitSize) {\n            DEBUGLOG(5, \"set_basic - too small\");\n            hufMetadata->hType = set_basic;\n            return 0;\n    }   }\n\n    /* Scan input and build symbol stats */\n    {   size_t const largest =\n            HIST_count_wksp (countWksp, &maxSymbolValue,\n                            (const BYTE*)src, srcSize,\n                            workspace, wkspSize);\n        FORWARD_IF_ERROR(largest, \"HIST_count_wksp failed\");\n        if (largest == srcSize) {\n            /* only one literal symbol */\n            DEBUGLOG(5, \"set_rle\");\n            hufMetadata->hType = set_rle;\n            return 0;\n        }\n        if (largest <= (srcSize >> 7)+4) {\n            /* heuristic: likely not compressible */\n            DEBUGLOG(5, \"set_basic - no gain\");\n            hufMetadata->hType = set_basic;\n            return 0;\n    }   }\n\n    /* Validate the previous Huffman table */\n    if (repeat == HUF_repeat_check\n      && !HUF_validateCTable((HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue)) {\n        repeat = HUF_repeat_none;\n    }\n\n    /* Build Huffman Tree */\n    ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable));\n    huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue, nodeWksp, nodeWkspSize, nextHuf->CTable, countWksp, hufFlags);\n    assert(huffLog <= LitHufLog);\n    {   size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp,\n                                                    maxSymbolValue, huffLog,\n                                                    nodeWksp, nodeWkspSize);\n        FORWARD_IF_ERROR(maxBits, \"HUF_buildCTable_wksp\");\n        huffLog = (U32)maxBits;\n    }\n    {   /* Build and write the CTable */\n        size_t const newCSize = HUF_estimateCompressedSize(\n                (HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue);\n        size_t const hSize = HUF_writeCTable_wksp(\n                hufMetadata->hufDesBuffer, sizeof(hufMetadata->hufDesBuffer),\n                (HUF_CElt*)nextHuf->CTable, maxSymbolValue, huffLog,\n                nodeWksp, nodeWkspSize);\n        /* Check against repeating the previous CTable */\n        if (repeat != HUF_repeat_none) {\n            size_t const oldCSize = HUF_estimateCompressedSize(\n                    (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue);\n            if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) {\n                DEBUGLOG(5, \"set_repeat - smaller\");\n                ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n                hufMetadata->hType = set_repeat;\n                return 0;\n        }   }\n        if (newCSize + hSize >= srcSize) {\n            DEBUGLOG(5, \"set_basic - no gains\");\n            ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n            hufMetadata->hType = set_basic;\n            return 0;\n        }\n        DEBUGLOG(5, \"set_compressed (hSize=%u)\", (U32)hSize);\n        hufMetadata->hType = set_compressed;\n        nextHuf->repeatMode = HUF_repeat_check;\n        return hSize;\n    }\n}\n\n\n/* ZSTD_buildDummySequencesStatistics():\n * Returns a ZSTD_symbolEncodingTypeStats_t with all encoding types as set_basic,\n * and updates nextEntropy to the appropriate repeatMode.\n */\nstatic ZSTD_symbolEncodingTypeStats_t\nZSTD_buildDummySequencesStatistics(ZSTD_fseCTables_t* nextEntropy)\n{\n    ZSTD_symbolEncodingTypeStats_t stats = {set_basic, set_basic, set_basic, 0, 0, 0};\n    nextEntropy->litlength_repeatMode = FSE_repeat_none;\n    nextEntropy->offcode_repeatMode = FSE_repeat_none;\n    nextEntropy->matchlength_repeatMode = FSE_repeat_none;\n    return stats;\n}\n\n/** ZSTD_buildBlockEntropyStats_sequences() :\n *  Builds entropy for the sequences.\n *  Stores symbol compression modes and fse table to fseMetadata.\n *  Requires ENTROPY_WORKSPACE_SIZE wksp.\n * @return : size of fse tables or error code */\nstatic size_t\nZSTD_buildBlockEntropyStats_sequences(\n                const SeqStore_t* seqStorePtr,\n                const ZSTD_fseCTables_t* prevEntropy,\n                      ZSTD_fseCTables_t* nextEntropy,\n                const ZSTD_CCtx_params* cctxParams,\n                      ZSTD_fseCTablesMetadata_t* fseMetadata,\n                      void* workspace, size_t wkspSize)\n{\n    ZSTD_strategy const strategy = cctxParams->cParams.strategy;\n    size_t const nbSeq = (size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    BYTE* const ostart = fseMetadata->fseTablesBuffer;\n    BYTE* const oend = ostart + sizeof(fseMetadata->fseTablesBuffer);\n    BYTE* op = ostart;\n    unsigned* countWorkspace = (unsigned*)workspace;\n    unsigned* entropyWorkspace = countWorkspace + (MaxSeq + 1);\n    size_t entropyWorkspaceSize = wkspSize - (MaxSeq + 1) * sizeof(*countWorkspace);\n    ZSTD_symbolEncodingTypeStats_t stats;\n\n    DEBUGLOG(5, \"ZSTD_buildBlockEntropyStats_sequences (nbSeq=%zu)\", nbSeq);\n    stats = nbSeq != 0 ? ZSTD_buildSequencesStatistics(seqStorePtr, nbSeq,\n                                          prevEntropy, nextEntropy, op, oend,\n                                          strategy, countWorkspace,\n                                          entropyWorkspace, entropyWorkspaceSize)\n                       : ZSTD_buildDummySequencesStatistics(nextEntropy);\n    FORWARD_IF_ERROR(stats.size, \"ZSTD_buildSequencesStatistics failed!\");\n    fseMetadata->llType = (SymbolEncodingType_e) stats.LLtype;\n    fseMetadata->ofType = (SymbolEncodingType_e) stats.Offtype;\n    fseMetadata->mlType = (SymbolEncodingType_e) stats.MLtype;\n    fseMetadata->lastCountSize = stats.lastCountSize;\n    return stats.size;\n}\n\n\n/** ZSTD_buildBlockEntropyStats() :\n *  Builds entropy for the block.\n *  Requires workspace size ENTROPY_WORKSPACE_SIZE\n * @return : 0 on success, or an error code\n *  Note : also employed in superblock\n */\nsize_t ZSTD_buildBlockEntropyStats(\n            const SeqStore_t* seqStorePtr,\n            const ZSTD_entropyCTables_t* prevEntropy,\n                  ZSTD_entropyCTables_t* nextEntropy,\n            const ZSTD_CCtx_params* cctxParams,\n                  ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                  void* workspace, size_t wkspSize)\n{\n    size_t const litSize = (size_t)(seqStorePtr->lit - seqStorePtr->litStart);\n    int const huf_useOptDepth = (cctxParams->cParams.strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD);\n    int const hufFlags = huf_useOptDepth ? HUF_flags_optimalDepth : 0;\n\n    entropyMetadata->hufMetadata.hufDesSize =\n        ZSTD_buildBlockEntropyStats_literals(seqStorePtr->litStart, litSize,\n                                            &prevEntropy->huf, &nextEntropy->huf,\n                                            &entropyMetadata->hufMetadata,\n                                            ZSTD_literalsCompressionIsDisabled(cctxParams),\n                                            workspace, wkspSize, hufFlags);\n\n    FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, \"ZSTD_buildBlockEntropyStats_literals failed\");\n    entropyMetadata->fseMetadata.fseTablesSize =\n        ZSTD_buildBlockEntropyStats_sequences(seqStorePtr,\n                                              &prevEntropy->fse, &nextEntropy->fse,\n                                              cctxParams,\n                                              &entropyMetadata->fseMetadata,\n                                              workspace, wkspSize);\n    FORWARD_IF_ERROR(entropyMetadata->fseMetadata.fseTablesSize, \"ZSTD_buildBlockEntropyStats_sequences failed\");\n    return 0;\n}\n\n/* Returns the size estimate for the literals section (header + content) of a block */\nstatic size_t\nZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSize,\n                               const ZSTD_hufCTables_t* huf,\n                               const ZSTD_hufCTablesMetadata_t* hufMetadata,\n                               void* workspace, size_t wkspSize,\n                               int writeEntropy)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    unsigned maxSymbolValue = HUF_SYMBOLVALUE_MAX;\n    size_t literalSectionHeaderSize = 3 + (litSize >= 1 KB) + (litSize >= 16 KB);\n    U32 singleStream = litSize < 256;\n\n    if (hufMetadata->hType == set_basic) return litSize;\n    else if (hufMetadata->hType == set_rle) return 1;\n    else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) {\n        size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);\n        if (ZSTD_isError(largest)) return litSize;\n        {   size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);\n            if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;\n            if (!singleStream) cLitSizeEstimate += 6; /* multi-stream huffman uses 6-byte jump table */\n            return cLitSizeEstimate + literalSectionHeaderSize;\n    }   }\n    assert(0); /* impossible */\n    return 0;\n}\n\n/* Returns the size estimate for the FSE-compressed symbols (of, ml, ll) of a block */\nstatic size_t\nZSTD_estimateBlockSize_symbolType(SymbolEncodingType_e type,\n                    const BYTE* codeTable, size_t nbSeq, unsigned maxCode,\n                    const FSE_CTable* fseCTable,\n                    const U8* additionalBits,\n                    short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                    void* workspace, size_t wkspSize)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    const BYTE* ctp = codeTable;\n    const BYTE* const ctStart = ctp;\n    const BYTE* const ctEnd = ctStart + nbSeq;\n    size_t cSymbolTypeSizeEstimateInBits = 0;\n    unsigned max = maxCode;\n\n    HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize);  /* can't fail */\n    if (type == set_basic) {\n        /* We selected this encoding type, so it must be valid. */\n        assert(max <= defaultMax);\n        (void)defaultMax;\n        cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max);\n    } else if (type == set_rle) {\n        cSymbolTypeSizeEstimateInBits = 0;\n    } else if (type == set_compressed || type == set_repeat) {\n        cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);\n    }\n    if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) {\n        return nbSeq * 10;\n    }\n    while (ctp < ctEnd) {\n        if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];\n        else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */\n        ctp++;\n    }\n    return cSymbolTypeSizeEstimateInBits >> 3;\n}\n\n/* Returns the size estimate for the sequences section (header + content) of a block */\nstatic size_t\nZSTD_estimateBlockSize_sequences(const BYTE* ofCodeTable,\n                                 const BYTE* llCodeTable,\n                                 const BYTE* mlCodeTable,\n                                 size_t nbSeq,\n                                 const ZSTD_fseCTables_t* fseTables,\n                                 const ZSTD_fseCTablesMetadata_t* fseMetadata,\n                                 void* workspace, size_t wkspSize,\n                                 int writeEntropy)\n{\n    size_t sequencesSectionHeaderSize = 1 /* seqHead */ + 1 /* min seqSize size */ + (nbSeq >= 128) + (nbSeq >= LONGNBSEQ);\n    size_t cSeqSizeEstimate = 0;\n    cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, nbSeq, MaxOff,\n                                    fseTables->offcodeCTable, NULL,\n                                    OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,\n                                    workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->llType, llCodeTable, nbSeq, MaxLL,\n                                    fseTables->litlengthCTable, LL_bits,\n                                    LL_defaultNorm, LL_defaultNormLog, MaxLL,\n                                    workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, nbSeq, MaxML,\n                                    fseTables->matchlengthCTable, ML_bits,\n                                    ML_defaultNorm, ML_defaultNormLog, MaxML,\n                                    workspace, wkspSize);\n    if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;\n    return cSeqSizeEstimate + sequencesSectionHeaderSize;\n}\n\n/* Returns the size estimate for a given stream of literals, of, ll, ml */\nstatic size_t\nZSTD_estimateBlockSize(const BYTE* literals, size_t litSize,\n                       const BYTE* ofCodeTable,\n                       const BYTE* llCodeTable,\n                       const BYTE* mlCodeTable,\n                       size_t nbSeq,\n                       const ZSTD_entropyCTables_t* entropy,\n                       const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                       void* workspace, size_t wkspSize,\n                       int writeLitEntropy, int writeSeqEntropy)\n{\n    size_t const literalsSize = ZSTD_estimateBlockSize_literal(literals, litSize,\n                                    &entropy->huf, &entropyMetadata->hufMetadata,\n                                    workspace, wkspSize, writeLitEntropy);\n    size_t const seqSize = ZSTD_estimateBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,\n                                    nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,\n                                    workspace, wkspSize, writeSeqEntropy);\n    return seqSize + literalsSize + ZSTD_blockHeaderSize;\n}\n\n/* Builds entropy statistics and uses them for blocksize estimation.\n *\n * @return: estimated compressed size of the seqStore, or a zstd error.\n */\nstatic size_t\nZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(SeqStore_t* seqStore, ZSTD_CCtx* zc)\n{\n    ZSTD_entropyCTablesMetadata_t* const entropyMetadata = &zc->blockSplitCtx.entropyMetadata;\n    DEBUGLOG(6, \"ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize()\");\n    FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(seqStore,\n                    &zc->blockState.prevCBlock->entropy,\n                    &zc->blockState.nextCBlock->entropy,\n                    &zc->appliedParams,\n                    entropyMetadata,\n                    zc->tmpWorkspace, zc->tmpWkspSize), \"\");\n    return ZSTD_estimateBlockSize(\n                    seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart),\n                    seqStore->ofCode, seqStore->llCode, seqStore->mlCode,\n                    (size_t)(seqStore->sequences - seqStore->sequencesStart),\n                    &zc->blockState.nextCBlock->entropy,\n                    entropyMetadata,\n                    zc->tmpWorkspace, zc->tmpWkspSize,\n                    (int)(entropyMetadata->hufMetadata.hType == set_compressed), 1);\n}\n\n/* Returns literals bytes represented in a seqStore */\nstatic size_t ZSTD_countSeqStoreLiteralsBytes(const SeqStore_t* const seqStore)\n{\n    size_t literalsBytes = 0;\n    size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);\n    size_t i;\n    for (i = 0; i < nbSeqs; ++i) {\n        SeqDef const seq = seqStore->sequencesStart[i];\n        literalsBytes += seq.litLength;\n        if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_literalLength) {\n            literalsBytes += 0x10000;\n    }   }\n    return literalsBytes;\n}\n\n/* Returns match bytes represented in a seqStore */\nstatic size_t ZSTD_countSeqStoreMatchBytes(const SeqStore_t* const seqStore)\n{\n    size_t matchBytes = 0;\n    size_t const nbSeqs = (size_t)(seqStore->sequences - seqStore->sequencesStart);\n    size_t i;\n    for (i = 0; i < nbSeqs; ++i) {\n        SeqDef seq = seqStore->sequencesStart[i];\n        matchBytes += seq.mlBase + MINMATCH;\n        if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) {\n            matchBytes += 0x10000;\n    }   }\n    return matchBytes;\n}\n\n/* Derives the seqStore that is a chunk of the originalSeqStore from [startIdx, endIdx).\n * Stores the result in resultSeqStore.\n */\nstatic void ZSTD_deriveSeqStoreChunk(SeqStore_t* resultSeqStore,\n                               const SeqStore_t* originalSeqStore,\n                                     size_t startIdx, size_t endIdx)\n{\n    *resultSeqStore = *originalSeqStore;\n    if (startIdx > 0) {\n        resultSeqStore->sequences = originalSeqStore->sequencesStart + startIdx;\n        resultSeqStore->litStart += ZSTD_countSeqStoreLiteralsBytes(resultSeqStore);\n    }\n\n    /* Move longLengthPos into the correct position if necessary */\n    if (originalSeqStore->longLengthType != ZSTD_llt_none) {\n        if (originalSeqStore->longLengthPos < startIdx || originalSeqStore->longLengthPos > endIdx) {\n            resultSeqStore->longLengthType = ZSTD_llt_none;\n        } else {\n            resultSeqStore->longLengthPos -= (U32)startIdx;\n        }\n    }\n    resultSeqStore->sequencesStart = originalSeqStore->sequencesStart + startIdx;\n    resultSeqStore->sequences = originalSeqStore->sequencesStart + endIdx;\n    if (endIdx == (size_t)(originalSeqStore->sequences - originalSeqStore->sequencesStart)) {\n        /* This accounts for possible last literals if the derived chunk reaches the end of the block */\n        assert(resultSeqStore->lit == originalSeqStore->lit);\n    } else {\n        size_t const literalsBytes = ZSTD_countSeqStoreLiteralsBytes(resultSeqStore);\n        resultSeqStore->lit = resultSeqStore->litStart + literalsBytes;\n    }\n    resultSeqStore->llCode += startIdx;\n    resultSeqStore->mlCode += startIdx;\n    resultSeqStore->ofCode += startIdx;\n}\n\n/**\n * Returns the raw offset represented by the combination of offBase, ll0, and repcode history.\n * offBase must represent a repcode in the numeric representation of ZSTD_storeSeq().\n */\nstatic U32\nZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offBase, const U32 ll0)\n{\n    U32 const adjustedRepCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0;  /* [ 0 - 3 ] */\n    assert(OFFBASE_IS_REPCODE(offBase));\n    if (adjustedRepCode == ZSTD_REP_NUM) {\n        assert(ll0);\n        /* litlength == 0 and offCode == 2 implies selection of first repcode - 1\n         * This is only valid if it results in a valid offset value, aka > 0.\n         * Note : it may happen that `rep[0]==1` in exceptional circumstances.\n         * In which case this function will return 0, which is an invalid offset.\n         * It's not an issue though, since this value will be\n         * compared and discarded within ZSTD_seqStore_resolveOffCodes().\n         */\n        return rep[0] - 1;\n    }\n    return rep[adjustedRepCode];\n}\n\n/**\n * ZSTD_seqStore_resolveOffCodes() reconciles any possible divergences in offset history that may arise\n * due to emission of RLE/raw blocks that disturb the offset history,\n * and replaces any repcodes within the seqStore that may be invalid.\n *\n * dRepcodes are updated as would be on the decompression side.\n * cRepcodes are updated exactly in accordance with the seqStore.\n *\n * Note : this function assumes seq->offBase respects the following numbering scheme :\n *        0 : invalid\n *        1-3 : repcode 1-3\n *        4+ : real_offset+3\n */\nstatic void\nZSTD_seqStore_resolveOffCodes(Repcodes_t* const dRepcodes, Repcodes_t* const cRepcodes,\n                        const SeqStore_t* const seqStore, U32 const nbSeq)\n{\n    U32 idx = 0;\n    U32 const longLitLenIdx = seqStore->longLengthType == ZSTD_llt_literalLength ? seqStore->longLengthPos : nbSeq;\n    for (; idx < nbSeq; ++idx) {\n        SeqDef* const seq = seqStore->sequencesStart + idx;\n        U32 const ll0 = (seq->litLength == 0) && (idx != longLitLenIdx);\n        U32 const offBase = seq->offBase;\n        assert(offBase > 0);\n        if (OFFBASE_IS_REPCODE(offBase)) {\n            U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offBase, ll0);\n            U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offBase, ll0);\n            /* Adjust simulated decompression repcode history if we come across a mismatch. Replace\n             * the repcode with the offset it actually references, determined by the compression\n             * repcode history.\n             */\n            if (dRawOffset != cRawOffset) {\n                seq->offBase = OFFSET_TO_OFFBASE(cRawOffset);\n            }\n        }\n        /* Compression repcode history is always updated with values directly from the unmodified seqStore.\n         * Decompression repcode history may use modified seq->offset value taken from compression repcode history.\n         */\n        ZSTD_updateRep(dRepcodes->rep, seq->offBase, ll0);\n        ZSTD_updateRep(cRepcodes->rep, offBase, ll0);\n    }\n}\n\n/* ZSTD_compressSeqStore_singleBlock():\n * Compresses a seqStore into a block with a block header, into the buffer dst.\n *\n * Returns the total size of that block (including header) or a ZSTD error code.\n */\nstatic size_t\nZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc,\n                            const SeqStore_t* const seqStore,\n                                  Repcodes_t* const dRep, Repcodes_t* const cRep,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                                  U32 lastBlock, U32 isPartition)\n{\n    const U32 rleMaxLength = 25;\n    BYTE* op = (BYTE*)dst;\n    const BYTE* ip = (const BYTE*)src;\n    size_t cSize;\n    size_t cSeqsSize;\n\n    /* In case of an RLE or raw block, the simulated decompression repcode history must be reset */\n    Repcodes_t const dRepOriginal = *dRep;\n    DEBUGLOG(5, \"ZSTD_compressSeqStore_singleBlock\");\n    if (isPartition)\n        ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart));\n\n    RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, \"Block header doesn't fit\");\n    cSeqsSize = ZSTD_entropyCompressSeqStore(seqStore,\n                &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,\n                &zc->appliedParams,\n                op + ZSTD_blockHeaderSize, dstCapacity - ZSTD_blockHeaderSize,\n                srcSize,\n                zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */,\n                zc->bmi2);\n    FORWARD_IF_ERROR(cSeqsSize, \"ZSTD_entropyCompressSeqStore failed!\");\n\n    if (!zc->isFirstBlock &&\n        cSeqsSize < rleMaxLength &&\n        ZSTD_isRLE((BYTE const*)src, srcSize)) {\n        /* We don't want to emit our first block as a RLE even if it qualifies because\n        * doing so will cause the decoder (cli only) to throw a \"should consume all input error.\"\n        * This is only an issue for zstd <= v1.4.3\n        */\n        cSeqsSize = 1;\n    }\n\n    /* Sequence collection not supported when block splitting */\n    if (zc->seqCollector.collectSequences) {\n        FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, seqStore, dRepOriginal.rep), \"copyBlockSequences failed\");\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n        return 0;\n    }\n\n    if (cSeqsSize == 0) {\n        cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock);\n        FORWARD_IF_ERROR(cSize, \"Nocompress block failed\");\n        DEBUGLOG(5, \"Writing out nocompress block, size: %zu\", cSize);\n        *dRep = dRepOriginal; /* reset simulated decompression repcode history */\n    } else if (cSeqsSize == 1) {\n        cSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, srcSize, lastBlock);\n        FORWARD_IF_ERROR(cSize, \"RLE compress block failed\");\n        DEBUGLOG(5, \"Writing out RLE block, size: %zu\", cSize);\n        *dRep = dRepOriginal; /* reset simulated decompression repcode history */\n    } else {\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n        writeBlockHeader(op, cSeqsSize, srcSize, lastBlock);\n        cSize = ZSTD_blockHeaderSize + cSeqsSize;\n        DEBUGLOG(5, \"Writing out compressed block, size: %zu\", cSize);\n    }\n\n    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n    return cSize;\n}\n\n/* Struct to keep track of where we are in our recursive calls. */\ntypedef struct {\n    U32* splitLocations;    /* Array of split indices */\n    size_t idx;             /* The current index within splitLocations being worked on */\n} seqStoreSplits;\n\n#define MIN_SEQUENCES_BLOCK_SPLITTING 300\n\n/* Helper function to perform the recursive search for block splits.\n * Estimates the cost of seqStore prior to split, and estimates the cost of splitting the sequences in half.\n * If advantageous to split, then we recurse down the two sub-blocks.\n * If not, or if an error occurred in estimation, then we do not recurse.\n *\n * Note: The recursion depth is capped by a heuristic minimum number of sequences,\n * defined by MIN_SEQUENCES_BLOCK_SPLITTING.\n * In theory, this means the absolute largest recursion depth is 10 == log2(maxNbSeqInBlock/MIN_SEQUENCES_BLOCK_SPLITTING).\n * In practice, recursion depth usually doesn't go beyond 4.\n *\n * Furthermore, the number of splits is capped by ZSTD_MAX_NB_BLOCK_SPLITS.\n * At ZSTD_MAX_NB_BLOCK_SPLITS == 196 with the current existing blockSize\n * maximum of 128 KB, this value is actually impossible to reach.\n */\nstatic void\nZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,\n                             ZSTD_CCtx* zc, const SeqStore_t* origSeqStore)\n{\n    SeqStore_t* const fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk;\n    SeqStore_t* const firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore;\n    SeqStore_t* const secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore;\n    size_t estimatedOriginalSize;\n    size_t estimatedFirstHalfSize;\n    size_t estimatedSecondHalfSize;\n    size_t midIdx = (startIdx + endIdx)/2;\n\n    DEBUGLOG(5, \"ZSTD_deriveBlockSplitsHelper: startIdx=%zu endIdx=%zu\", startIdx, endIdx);\n    assert(endIdx >= startIdx);\n    if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= ZSTD_MAX_NB_BLOCK_SPLITS) {\n        DEBUGLOG(6, \"ZSTD_deriveBlockSplitsHelper: Too few sequences (%zu)\", endIdx - startIdx);\n        return;\n    }\n    ZSTD_deriveSeqStoreChunk(fullSeqStoreChunk, origSeqStore, startIdx, endIdx);\n    ZSTD_deriveSeqStoreChunk(firstHalfSeqStore, origSeqStore, startIdx, midIdx);\n    ZSTD_deriveSeqStoreChunk(secondHalfSeqStore, origSeqStore, midIdx, endIdx);\n    estimatedOriginalSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(fullSeqStoreChunk, zc);\n    estimatedFirstHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(firstHalfSeqStore, zc);\n    estimatedSecondHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(secondHalfSeqStore, zc);\n    DEBUGLOG(5, \"Estimated original block size: %zu -- First half split: %zu -- Second half split: %zu\",\n             estimatedOriginalSize, estimatedFirstHalfSize, estimatedSecondHalfSize);\n    if (ZSTD_isError(estimatedOriginalSize) || ZSTD_isError(estimatedFirstHalfSize) || ZSTD_isError(estimatedSecondHalfSize)) {\n        return;\n    }\n    if (estimatedFirstHalfSize + estimatedSecondHalfSize < estimatedOriginalSize) {\n        DEBUGLOG(5, \"split decided at seqNb:%zu\", midIdx);\n        ZSTD_deriveBlockSplitsHelper(splits, startIdx, midIdx, zc, origSeqStore);\n        splits->splitLocations[splits->idx] = (U32)midIdx;\n        splits->idx++;\n        ZSTD_deriveBlockSplitsHelper(splits, midIdx, endIdx, zc, origSeqStore);\n    }\n}\n\n/* Base recursive function.\n * Populates a table with intra-block partition indices that can improve compression ratio.\n *\n * @return: number of splits made (which equals the size of the partition table - 1).\n */\nstatic size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq)\n{\n    seqStoreSplits splits;\n    splits.splitLocations = partitions;\n    splits.idx = 0;\n    if (nbSeq <= 4) {\n        DEBUGLOG(5, \"ZSTD_deriveBlockSplits: Too few sequences to split (%u <= 4)\", nbSeq);\n        /* Refuse to try and split anything with less than 4 sequences */\n        return 0;\n    }\n    ZSTD_deriveBlockSplitsHelper(&splits, 0, nbSeq, zc, &zc->seqStore);\n    splits.splitLocations[splits.idx] = nbSeq;\n    DEBUGLOG(5, \"ZSTD_deriveBlockSplits: final nb partitions: %zu\", splits.idx+1);\n    return splits.idx;\n}\n\n/* ZSTD_compressBlock_splitBlock():\n * Attempts to split a given block into multiple blocks to improve compression ratio.\n *\n * Returns combined size of all blocks (which includes headers), or a ZSTD error code.\n */\nstatic size_t\nZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc,\n                                    void* dst, size_t dstCapacity,\n                              const void* src, size_t blockSize,\n                                    U32 lastBlock, U32 nbSeq)\n{\n    size_t cSize = 0;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    size_t i = 0;\n    size_t srcBytesTotal = 0;\n    U32* const partitions = zc->blockSplitCtx.partitions; /* size == ZSTD_MAX_NB_BLOCK_SPLITS */\n    SeqStore_t* const nextSeqStore = &zc->blockSplitCtx.nextSeqStore;\n    SeqStore_t* const currSeqStore = &zc->blockSplitCtx.currSeqStore;\n    size_t const numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq);\n\n    /* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history\n     * may become invalid. In order to reconcile potentially invalid repcodes, we keep track of two\n     * separate repcode histories that simulate repcode history on compression and decompression side,\n     * and use the histories to determine whether we must replace a particular repcode with its raw offset.\n     *\n     * 1) cRep gets updated for each partition, regardless of whether the block was emitted as uncompressed\n     *    or RLE. This allows us to retrieve the offset value that an invalid repcode references within\n     *    a nocompress/RLE block.\n     * 2) dRep gets updated only for compressed partitions, and when a repcode gets replaced, will use\n     *    the replacement offset value rather than the original repcode to update the repcode history.\n     *    dRep also will be the final repcode history sent to the next block.\n     *\n     * See ZSTD_seqStore_resolveOffCodes() for more details.\n     */\n    Repcodes_t dRep;\n    Repcodes_t cRep;\n    ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    ZSTD_memset(nextSeqStore, 0, sizeof(SeqStore_t));\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)\",\n                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,\n                (unsigned)zc->blockState.matchState.nextToUpdate);\n\n    if (numSplits == 0) {\n        size_t cSizeSingleBlock =\n            ZSTD_compressSeqStore_singleBlock(zc, &zc->seqStore,\n                                            &dRep, &cRep,\n                                            op, dstCapacity,\n                                            ip, blockSize,\n                                            lastBlock, 0 /* isPartition */);\n        FORWARD_IF_ERROR(cSizeSingleBlock, \"Compressing single block from splitBlock_internal() failed!\");\n        DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock_internal: No splits\");\n        assert(zc->blockSizeMax <= ZSTD_BLOCKSIZE_MAX);\n        assert(cSizeSingleBlock <= zc->blockSizeMax + ZSTD_blockHeaderSize);\n        return cSizeSingleBlock;\n    }\n\n    ZSTD_deriveSeqStoreChunk(currSeqStore, &zc->seqStore, 0, partitions[0]);\n    for (i = 0; i <= numSplits; ++i) {\n        size_t cSizeChunk;\n        U32 const lastPartition = (i == numSplits);\n        U32 lastBlockEntireSrc = 0;\n\n        size_t srcBytes = ZSTD_countSeqStoreLiteralsBytes(currSeqStore) + ZSTD_countSeqStoreMatchBytes(currSeqStore);\n        srcBytesTotal += srcBytes;\n        if (lastPartition) {\n            /* This is the final partition, need to account for possible last literals */\n            srcBytes += blockSize - srcBytesTotal;\n            lastBlockEntireSrc = lastBlock;\n        } else {\n            ZSTD_deriveSeqStoreChunk(nextSeqStore, &zc->seqStore, partitions[i], partitions[i+1]);\n        }\n\n        cSizeChunk = ZSTD_compressSeqStore_singleBlock(zc, currSeqStore,\n                                                      &dRep, &cRep,\n                                                       op, dstCapacity,\n                                                       ip, srcBytes,\n                                                       lastBlockEntireSrc, 1 /* isPartition */);\n        DEBUGLOG(5, \"Estimated size: %zu vs %zu : actual size\",\n                    ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(currSeqStore, zc), cSizeChunk);\n        FORWARD_IF_ERROR(cSizeChunk, \"Compressing chunk failed!\");\n\n        ip += srcBytes;\n        op += cSizeChunk;\n        dstCapacity -= cSizeChunk;\n        cSize += cSizeChunk;\n        *currSeqStore = *nextSeqStore;\n        assert(cSizeChunk <= zc->blockSizeMax + ZSTD_blockHeaderSize);\n    }\n    /* cRep and dRep may have diverged during the compression.\n     * If so, we use the dRep repcodes for the next block.\n     */\n    ZSTD_memcpy(zc->blockState.prevCBlock->rep, dRep.rep, sizeof(Repcodes_t));\n    return cSize;\n}\n\nstatic size_t\nZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,\n                              void* dst, size_t dstCapacity,\n                              const void* src, size_t srcSize, U32 lastBlock)\n{\n    U32 nbSeq;\n    size_t cSize;\n    DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock\");\n    assert(zc->appliedParams.postBlockSplitter == ZSTD_ps_enable);\n\n    {   const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);\n        FORWARD_IF_ERROR(bss, \"ZSTD_buildSeqStore failed\");\n        if (bss == ZSTDbss_noCompress) {\n            if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n                zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n            RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, \"Uncompressible block\");\n            cSize = ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);\n            FORWARD_IF_ERROR(cSize, \"ZSTD_noCompressBlock failed\");\n            DEBUGLOG(5, \"ZSTD_compressBlock_splitBlock: Nocompress block\");\n            return cSize;\n        }\n        nbSeq = (U32)(zc->seqStore.sequences - zc->seqStore.sequencesStart);\n    }\n\n    cSize = ZSTD_compressBlock_splitBlock_internal(zc, dst, dstCapacity, src, srcSize, lastBlock, nbSeq);\n    FORWARD_IF_ERROR(cSize, \"Splitting blocks failed!\");\n    return cSize;\n}\n\nstatic size_t\nZSTD_compressBlock_internal(ZSTD_CCtx* zc,\n                            void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize, U32 frame)\n{\n    /* This is an estimated upper bound for the length of an rle block.\n     * This isn't the actual upper bound.\n     * Finding the real threshold needs further investigation.\n     */\n    const U32 rleMaxLength = 25;\n    size_t cSize;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    DEBUGLOG(5, \"ZSTD_compressBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)\",\n                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,\n                (unsigned)zc->blockState.matchState.nextToUpdate);\n\n    {   const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);\n        FORWARD_IF_ERROR(bss, \"ZSTD_buildSeqStore failed\");\n        if (bss == ZSTDbss_noCompress) {\n            RETURN_ERROR_IF(zc->seqCollector.collectSequences, sequenceProducer_failed, \"Uncompressible block\");\n            cSize = 0;\n            goto out;\n        }\n    }\n\n    if (zc->seqCollector.collectSequences) {\n        FORWARD_IF_ERROR(ZSTD_copyBlockSequences(&zc->seqCollector, ZSTD_getSeqStore(zc), zc->blockState.prevCBlock->rep), \"copyBlockSequences failed\");\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n        return 0;\n    }\n\n    /* encode sequences and literals */\n    cSize = ZSTD_entropyCompressSeqStore(&zc->seqStore,\n            &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,\n            &zc->appliedParams,\n            dst, dstCapacity,\n            srcSize,\n            zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */,\n            zc->bmi2);\n\n    if (frame &&\n        /* We don't want to emit our first block as a RLE even if it qualifies because\n         * doing so will cause the decoder (cli only) to throw a \"should consume all input error.\"\n         * This is only an issue for zstd <= v1.4.3\n         */\n        !zc->isFirstBlock &&\n        cSize < rleMaxLength &&\n        ZSTD_isRLE(ip, srcSize))\n    {\n        cSize = 1;\n        op[0] = ip[0];\n    }\n\nout:\n    if (!ZSTD_isError(cSize) && cSize > 1) {\n        ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n    }\n    /* We check that dictionaries have offset codes available for the first\n     * block. After the first block, the offcode table might not have large\n     * enough codes to represent the offsets in the data.\n     */\n    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n    return cSize;\n}\n\nstatic size_t ZSTD_compressBlock_targetCBlockSize_body(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                               const size_t bss, U32 lastBlock)\n{\n    DEBUGLOG(6, \"Attempting ZSTD_compressSuperBlock()\");\n    if (bss == ZSTDbss_compress) {\n        if (/* We don't want to emit our first block as a RLE even if it qualifies because\n            * doing so will cause the decoder (cli only) to throw a \"should consume all input error.\"\n            * This is only an issue for zstd <= v1.4.3\n            */\n            !zc->isFirstBlock &&\n            ZSTD_maybeRLE(&zc->seqStore) &&\n            ZSTD_isRLE((BYTE const*)src, srcSize))\n        {\n            return ZSTD_rleCompressBlock(dst, dstCapacity, *(BYTE const*)src, srcSize, lastBlock);\n        }\n        /* Attempt superblock compression.\n         *\n         * Note that compressed size of ZSTD_compressSuperBlock() is not bound by the\n         * standard ZSTD_compressBound(). This is a problem, because even if we have\n         * space now, taking an extra byte now could cause us to run out of space later\n         * and violate ZSTD_compressBound().\n         *\n         * Define blockBound(blockSize) = blockSize + ZSTD_blockHeaderSize.\n         *\n         * In order to respect ZSTD_compressBound() we must attempt to emit a raw\n         * uncompressed block in these cases:\n         *   * cSize == 0: Return code for an uncompressed block.\n         *   * cSize == dstSize_tooSmall: We may have expanded beyond blockBound(srcSize).\n         *     ZSTD_noCompressBlock() will return dstSize_tooSmall if we are really out of\n         *     output space.\n         *   * cSize >= blockBound(srcSize): We have expanded the block too much so\n         *     emit an uncompressed block.\n         */\n        {   size_t const cSize =\n                ZSTD_compressSuperBlock(zc, dst, dstCapacity, src, srcSize, lastBlock);\n            if (cSize != ERROR(dstSize_tooSmall)) {\n                size_t const maxCSize =\n                    srcSize - ZSTD_minGain(srcSize, zc->appliedParams.cParams.strategy);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressSuperBlock failed\");\n                if (cSize != 0 && cSize < maxCSize + ZSTD_blockHeaderSize) {\n                    ZSTD_blockState_confirmRepcodesAndEntropyTables(&zc->blockState);\n                    return cSize;\n                }\n            }\n        }\n    } /* if (bss == ZSTDbss_compress)*/\n\n    DEBUGLOG(6, \"Resorting to ZSTD_noCompressBlock()\");\n    /* Superblock compression failed, attempt to emit a single no compress block.\n     * The decoder will be able to stream this block since it is uncompressed.\n     */\n    return ZSTD_noCompressBlock(dst, dstCapacity, src, srcSize, lastBlock);\n}\n\nstatic size_t ZSTD_compressBlock_targetCBlockSize(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                               U32 lastBlock)\n{\n    size_t cSize = 0;\n    const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);\n    DEBUGLOG(5, \"ZSTD_compressBlock_targetCBlockSize (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u, srcSize=%zu)\",\n                (unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit, (unsigned)zc->blockState.matchState.nextToUpdate, srcSize);\n    FORWARD_IF_ERROR(bss, \"ZSTD_buildSeqStore failed\");\n\n    cSize = ZSTD_compressBlock_targetCBlockSize_body(zc, dst, dstCapacity, src, srcSize, bss, lastBlock);\n    FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_targetCBlockSize_body failed\");\n\n    if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n        zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n    return cSize;\n}\n\nstatic void ZSTD_overflowCorrectIfNeeded(ZSTD_MatchState_t* ms,\n                                         ZSTD_cwksp* ws,\n                                         ZSTD_CCtx_params const* params,\n                                         void const* ip,\n                                         void const* iend)\n{\n    U32 const cycleLog = ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy);\n    U32 const maxDist = (U32)1 << params->cParams.windowLog;\n    if (ZSTD_window_needOverflowCorrection(ms->window, cycleLog, maxDist, ms->loadedDictEnd, ip, iend)) {\n        U32 const correction = ZSTD_window_correctOverflow(&ms->window, cycleLog, maxDist, ip);\n        ZSTD_STATIC_ASSERT(ZSTD_CHAINLOG_MAX <= 30);\n        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX_32 <= 30);\n        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);\n        ZSTD_cwksp_mark_tables_dirty(ws);\n        ZSTD_reduceIndex(ms, params, correction);\n        ZSTD_cwksp_mark_tables_clean(ws);\n        if (ms->nextToUpdate < correction) ms->nextToUpdate = 0;\n        else ms->nextToUpdate -= correction;\n        /* invalidate dictionaries on overflow correction */\n        ms->loadedDictEnd = 0;\n        ms->dictMatchState = NULL;\n    }\n}\n\n#include \"zstd_preSplit.h\"\n\nstatic size_t ZSTD_optimalBlockSize(ZSTD_CCtx* cctx, const void* src, size_t srcSize, size_t blockSizeMax, int splitLevel, ZSTD_strategy strat, S64 savings)\n{\n    /* split level based on compression strategy, from `fast` to `btultra2` */\n    static const int splitLevels[] = { 0, 0, 1, 2, 2, 3, 3, 4, 4, 4 };\n    /* note: conservatively only split full blocks (128 KB) currently.\n     * While it's possible to go lower, let's keep it simple for a first implementation.\n     * Besides, benefits of splitting are reduced when blocks are already small.\n     */\n    if (srcSize < 128 KB || blockSizeMax < 128 KB)\n        return MIN(srcSize, blockSizeMax);\n    /* do not split incompressible data though:\n     * require verified savings to allow pre-splitting.\n     * Note: as a consequence, the first full block is not split.\n     */\n    if (savings < 3) {\n        DEBUGLOG(6, \"don't attempt splitting: savings (%i) too low\", (int)savings);\n        return 128 KB;\n    }\n    /* apply @splitLevel, or use default value (which depends on @strat).\n     * note that splitting heuristic is still conditioned by @savings >= 3,\n     * so the first block will not reach this code path */\n    if (splitLevel == 1) return 128 KB;\n    if (splitLevel == 0) {\n        assert(ZSTD_fast <= strat && strat <= ZSTD_btultra2);\n        splitLevel = splitLevels[strat];\n    } else {\n        assert(2 <= splitLevel && splitLevel <= 6);\n        splitLevel -= 2;\n    }\n    return ZSTD_splitBlock(src, blockSizeMax, splitLevel, cctx->tmpWorkspace, cctx->tmpWkspSize);\n}\n\n/*! ZSTD_compress_frameChunk() :\n*   Compress a chunk of data into one or multiple blocks.\n*   All blocks will be terminated, all input will be consumed.\n*   Function will issue an error if there is not enough `dstCapacity` to hold the compressed content.\n*   Frame is supposed already started (header already produced)\n*  @return : compressed size, or an error code\n*/\nstatic size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,\n                                     void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                                     U32 lastFrameChunk)\n{\n    size_t blockSizeMax = cctx->blockSizeMax;\n    size_t remaining = srcSize;\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    U32 const maxDist = (U32)1 << cctx->appliedParams.cParams.windowLog;\n    S64 savings = (S64)cctx->consumedSrcSize - (S64)cctx->producedCSize;\n\n    assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX);\n\n    DEBUGLOG(5, \"ZSTD_compress_frameChunk (srcSize=%u, blockSizeMax=%u)\", (unsigned)srcSize, (unsigned)blockSizeMax);\n    if (cctx->appliedParams.fParams.checksumFlag && srcSize)\n        XXH64_update(&cctx->xxhState, src, srcSize);\n\n    while (remaining) {\n        ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;\n        size_t const blockSize = ZSTD_optimalBlockSize(cctx,\n                                ip, remaining,\n                                blockSizeMax,\n                                cctx->appliedParams.preBlockSplitter_level,\n                                cctx->appliedParams.cParams.strategy,\n                                savings);\n        U32 const lastBlock = lastFrameChunk & (blockSize == remaining);\n        assert(blockSize <= remaining);\n\n        /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding\n         * additional 1. We need to revisit and change this logic to be more consistent */\n        RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize + MIN_CBLOCK_SIZE + 1,\n                        dstSize_tooSmall,\n                        \"not enough space to store compressed block\");\n\n        ZSTD_overflowCorrectIfNeeded(\n            ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize);\n        ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);\n        ZSTD_window_enforceMaxDist(&ms->window, ip, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);\n\n        /* Ensure hash/chain table insertion resumes no sooner than lowlimit */\n        if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;\n\n        {   size_t cSize;\n            if (ZSTD_useTargetCBlockSize(&cctx->appliedParams)) {\n                cSize = ZSTD_compressBlock_targetCBlockSize(cctx, op, dstCapacity, ip, blockSize, lastBlock);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_targetCBlockSize failed\");\n                assert(cSize > 0);\n                assert(cSize <= blockSize + ZSTD_blockHeaderSize);\n            } else if (ZSTD_blockSplitterEnabled(&cctx->appliedParams)) {\n                cSize = ZSTD_compressBlock_splitBlock(cctx, op, dstCapacity, ip, blockSize, lastBlock);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_splitBlock failed\");\n                assert(cSize > 0 || cctx->seqCollector.collectSequences == 1);\n            } else {\n                cSize = ZSTD_compressBlock_internal(cctx,\n                                        op+ZSTD_blockHeaderSize, dstCapacity-ZSTD_blockHeaderSize,\n                                        ip, blockSize, 1 /* frame */);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressBlock_internal failed\");\n\n                if (cSize == 0) {  /* block is not compressible */\n                    cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);\n                    FORWARD_IF_ERROR(cSize, \"ZSTD_noCompressBlock failed\");\n                } else {\n                    U32 const cBlockHeader = cSize == 1 ?\n                        lastBlock + (((U32)bt_rle)<<1) + (U32)(blockSize << 3) :\n                        lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);\n                    MEM_writeLE24(op, cBlockHeader);\n                    cSize += ZSTD_blockHeaderSize;\n                }\n            }  /* if (ZSTD_useTargetCBlockSize(&cctx->appliedParams))*/\n\n            /* @savings is employed to ensure that splitting doesn't worsen expansion of incompressible data.\n             * Without splitting, the maximum expansion is 3 bytes per full block.\n             * An adversarial input could attempt to fudge the split detector,\n             * and make it split incompressible data, resulting in more block headers.\n             * Note that, since ZSTD_COMPRESSBOUND() assumes a worst case scenario of 1KB per block,\n             * and the splitter never creates blocks that small (current lower limit is 8 KB),\n             * there is already no risk to expand beyond ZSTD_COMPRESSBOUND() limit.\n             * But if the goal is to not expand by more than 3-bytes per 128 KB full block,\n             * then yes, it becomes possible to make the block splitter oversplit incompressible data.\n             * Using @savings, we enforce an even more conservative condition,\n             * requiring the presence of enough savings (at least 3 bytes) to authorize splitting,\n             * otherwise only full blocks are used.\n             * But being conservative is fine,\n             * since splitting barely compressible blocks is not fruitful anyway */\n            savings += (S64)blockSize - (S64)cSize;\n\n            ip += blockSize;\n            assert(remaining >= blockSize);\n            remaining -= blockSize;\n            op += cSize;\n            assert(dstCapacity >= cSize);\n            dstCapacity -= cSize;\n            cctx->isFirstBlock = 0;\n            DEBUGLOG(5, \"ZSTD_compress_frameChunk: adding a block of size %u\",\n                        (unsigned)cSize);\n    }   }\n\n    if (lastFrameChunk && (op>ostart)) cctx->stage = ZSTDcs_ending;\n    return (size_t)(op-ostart);\n}\n\n\nstatic size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,\n                                    const ZSTD_CCtx_params* params,\n                                    U64 pledgedSrcSize, U32 dictID)\n{\n    BYTE* const op = (BYTE*)dst;\n    U32   const dictIDSizeCodeLength = (dictID>0) + (dictID>=256) + (dictID>=65536);   /* 0-3 */\n    U32   const dictIDSizeCode = params->fParams.noDictIDFlag ? 0 : dictIDSizeCodeLength;   /* 0-3 */\n    U32   const checksumFlag = params->fParams.checksumFlag>0;\n    U32   const windowSize = (U32)1 << params->cParams.windowLog;\n    U32   const singleSegment = params->fParams.contentSizeFlag && (windowSize >= pledgedSrcSize);\n    BYTE  const windowLogByte = (BYTE)((params->cParams.windowLog - ZSTD_WINDOWLOG_ABSOLUTEMIN) << 3);\n    U32   const fcsCode = params->fParams.contentSizeFlag ?\n                     (pledgedSrcSize>=256) + (pledgedSrcSize>=65536+256) + (pledgedSrcSize>=0xFFFFFFFFU) : 0;  /* 0-3 */\n    BYTE  const frameHeaderDescriptionByte = (BYTE)(dictIDSizeCode + (checksumFlag<<2) + (singleSegment<<5) + (fcsCode<<6) );\n    size_t pos=0;\n\n    assert(!(params->fParams.contentSizeFlag && pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN));\n    RETURN_ERROR_IF(dstCapacity < ZSTD_FRAMEHEADERSIZE_MAX, dstSize_tooSmall,\n                    \"dst buf is too small to fit worst-case frame header size.\");\n    DEBUGLOG(4, \"ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u\",\n                !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode);\n    if (params->format == ZSTD_f_zstd1) {\n        MEM_writeLE32(dst, ZSTD_MAGICNUMBER);\n        pos = 4;\n    }\n    op[pos++] = frameHeaderDescriptionByte;\n    if (!singleSegment) op[pos++] = windowLogByte;\n    switch(dictIDSizeCode)\n    {\n        default:\n            assert(0); /* impossible */\n            ZSTD_FALLTHROUGH;\n        case 0 : break;\n        case 1 : op[pos] = (BYTE)(dictID); pos++; break;\n        case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break;\n        case 3 : MEM_writeLE32(op+pos, dictID); pos+=4; break;\n    }\n    switch(fcsCode)\n    {\n        default:\n            assert(0); /* impossible */\n            ZSTD_FALLTHROUGH;\n        case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break;\n        case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;\n        case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;\n        case 3 : MEM_writeLE64(op+pos, (U64)(pledgedSrcSize)); pos+=8; break;\n    }\n    return pos;\n}\n\n/* ZSTD_writeSkippableFrame_advanced() :\n * Writes out a skippable frame with the specified magic number variant (16 are supported),\n * from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15, and the desired source data.\n *\n * Returns the total number of bytes written, or a ZSTD error code.\n */\nsize_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize, unsigned magicVariant) {\n    BYTE* op = (BYTE*)dst;\n    RETURN_ERROR_IF(dstCapacity < srcSize + ZSTD_SKIPPABLEHEADERSIZE /* Skippable frame overhead */,\n                    dstSize_tooSmall, \"Not enough room for skippable frame\");\n    RETURN_ERROR_IF(srcSize > (unsigned)0xFFFFFFFF, srcSize_wrong, \"Src size too large for skippable frame\");\n    RETURN_ERROR_IF(magicVariant > 15, parameter_outOfBound, \"Skippable frame magic number variant not supported\");\n\n    MEM_writeLE32(op, (U32)(ZSTD_MAGIC_SKIPPABLE_START + magicVariant));\n    MEM_writeLE32(op+4, (U32)srcSize);\n    ZSTD_memcpy(op+8, src, srcSize);\n    return srcSize + ZSTD_SKIPPABLEHEADERSIZE;\n}\n\n/* ZSTD_writeLastEmptyBlock() :\n * output an empty Block with end-of-frame mark to complete a frame\n * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))\n *           or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)\n */\nsize_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity)\n{\n    RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall,\n                    \"dst buf is too small to write frame trailer empty block.\");\n    {   U32 const cBlockHeader24 = 1 /*lastBlock*/ + (((U32)bt_raw)<<1);  /* 0 size */\n        MEM_writeLE24(dst, cBlockHeader24);\n        return ZSTD_blockHeaderSize;\n    }\n}\n\nvoid ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq)\n{\n    assert(cctx->stage == ZSTDcs_init);\n    assert(nbSeq == 0 || cctx->appliedParams.ldmParams.enableLdm != ZSTD_ps_enable);\n    cctx->externSeqStore.seq = seq;\n    cctx->externSeqStore.size = nbSeq;\n    cctx->externSeqStore.capacity = nbSeq;\n    cctx->externSeqStore.pos = 0;\n    cctx->externSeqStore.posInSequence = 0;\n}\n\n\nstatic size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,\n                              void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize,\n                               U32 frame, U32 lastFrameChunk)\n{\n    ZSTD_MatchState_t* const ms = &cctx->blockState.matchState;\n    size_t fhSize = 0;\n\n    DEBUGLOG(5, \"ZSTD_compressContinue_internal, stage: %u, srcSize: %u\",\n                cctx->stage, (unsigned)srcSize);\n    RETURN_ERROR_IF(cctx->stage==ZSTDcs_created, stage_wrong,\n                    \"missing init (ZSTD_compressBegin)\");\n\n    if (frame && (cctx->stage==ZSTDcs_init)) {\n        fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams,\n                                       cctx->pledgedSrcSizePlusOne-1, cctx->dictID);\n        FORWARD_IF_ERROR(fhSize, \"ZSTD_writeFrameHeader failed\");\n        assert(fhSize <= dstCapacity);\n        dstCapacity -= fhSize;\n        dst = (char*)dst + fhSize;\n        cctx->stage = ZSTDcs_ongoing;\n    }\n\n    if (!srcSize) return fhSize;  /* do not generate an empty block if no input */\n\n    if (!ZSTD_window_update(&ms->window, src, srcSize, ms->forceNonContiguous)) {\n        ms->forceNonContiguous = 0;\n        ms->nextToUpdate = ms->window.dictLimit;\n    }\n    if (cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_window_update(&cctx->ldmState.window, src, srcSize, /* forceNonContiguous */ 0);\n    }\n\n    if (!frame) {\n        /* overflow check and correction for block mode */\n        ZSTD_overflowCorrectIfNeeded(\n            ms, &cctx->workspace, &cctx->appliedParams,\n            src, (BYTE const*)src + srcSize);\n    }\n\n    DEBUGLOG(5, \"ZSTD_compressContinue_internal (blockSize=%u)\", (unsigned)cctx->blockSizeMax);\n    {   size_t const cSize = frame ?\n                             ZSTD_compress_frameChunk (cctx, dst, dstCapacity, src, srcSize, lastFrameChunk) :\n                             ZSTD_compressBlock_internal (cctx, dst, dstCapacity, src, srcSize, 0 /* frame */);\n        FORWARD_IF_ERROR(cSize, \"%s\", frame ? \"ZSTD_compress_frameChunk failed\" : \"ZSTD_compressBlock_internal failed\");\n        cctx->consumedSrcSize += srcSize;\n        cctx->producedCSize += (cSize + fhSize);\n        assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));\n        if (cctx->pledgedSrcSizePlusOne != 0) {  /* control src size */\n            ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);\n            RETURN_ERROR_IF(\n                cctx->consumedSrcSize+1 > cctx->pledgedSrcSizePlusOne,\n                srcSize_wrong,\n                \"error : pledgedSrcSize = %u, while realSrcSize >= %u\",\n                (unsigned)cctx->pledgedSrcSizePlusOne-1,\n                (unsigned)cctx->consumedSrcSize);\n        }\n        return cSize + fhSize;\n    }\n}\n\nsize_t ZSTD_compressContinue_public(ZSTD_CCtx* cctx,\n                                        void* dst, size_t dstCapacity,\n                                  const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressContinue (srcSize=%u)\", (unsigned)srcSize);\n    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 1 /* frame mode */, 0 /* last chunk */);\n}\n\n/* NOTE: Must just wrap ZSTD_compressContinue_public() */\nsize_t ZSTD_compressContinue(ZSTD_CCtx* cctx,\n                             void* dst, size_t dstCapacity,\n                       const void* src, size_t srcSize)\n{\n    return ZSTD_compressContinue_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\nstatic size_t ZSTD_getBlockSize_deprecated(const ZSTD_CCtx* cctx)\n{\n    ZSTD_compressionParameters const cParams = cctx->appliedParams.cParams;\n    assert(!ZSTD_checkCParams(cParams));\n    return MIN(cctx->appliedParams.maxBlockSize, (size_t)1 << cParams.windowLog);\n}\n\n/* NOTE: Must just wrap ZSTD_getBlockSize_deprecated() */\nsize_t ZSTD_getBlockSize(const ZSTD_CCtx* cctx)\n{\n    return ZSTD_getBlockSize_deprecated(cctx);\n}\n\n/* NOTE: Must just wrap ZSTD_compressBlock_deprecated() */\nsize_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressBlock: srcSize = %u\", (unsigned)srcSize);\n    { size_t const blockSizeMax = ZSTD_getBlockSize_deprecated(cctx);\n      RETURN_ERROR_IF(srcSize > blockSizeMax, srcSize_wrong, \"input is larger than a block\"); }\n\n    return ZSTD_compressContinue_internal(cctx, dst, dstCapacity, src, srcSize, 0 /* frame mode */, 0 /* last chunk */);\n}\n\n/* NOTE: Must just wrap ZSTD_compressBlock_deprecated() */\nsize_t ZSTD_compressBlock(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_deprecated(cctx, dst, dstCapacity, src, srcSize);\n}\n\n/*! ZSTD_loadDictionaryContent() :\n *  @return : 0, or an error code\n */\nstatic size_t\nZSTD_loadDictionaryContent(ZSTD_MatchState_t* ms,\n                        ldmState_t* ls,\n                        ZSTD_cwksp* ws,\n                        ZSTD_CCtx_params const* params,\n                        const void* src, size_t srcSize,\n                        ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp)\n{\n    const BYTE* ip = (const BYTE*) src;\n    const BYTE* const iend = ip + srcSize;\n    int const loadLdmDict = params->ldmParams.enableLdm == ZSTD_ps_enable && ls != NULL;\n\n    /* Assert that the ms params match the params we're being given */\n    ZSTD_assertEqualCParams(params->cParams, ms->cParams);\n\n    {   /* Ensure large dictionaries can't cause index overflow */\n\n        /* Allow the dictionary to set indices up to exactly ZSTD_CURRENT_MAX.\n         * Dictionaries right at the edge will immediately trigger overflow\n         * correction, but I don't want to insert extra constraints here.\n         */\n        U32 maxDictSize = ZSTD_CURRENT_MAX - ZSTD_WINDOW_START_INDEX;\n\n        int const CDictTaggedIndices = ZSTD_CDictIndicesAreTagged(&params->cParams);\n        if (CDictTaggedIndices && tfp == ZSTD_tfp_forCDict) {\n            /* Some dictionary matchfinders in zstd use \"short cache\",\n             * which treats the lower ZSTD_SHORT_CACHE_TAG_BITS of each\n             * CDict hashtable entry as a tag rather than as part of an index.\n             * When short cache is used, we need to truncate the dictionary\n             * so that its indices don't overlap with the tag. */\n            U32 const shortCacheMaxDictSize = (1u << (32 - ZSTD_SHORT_CACHE_TAG_BITS)) - ZSTD_WINDOW_START_INDEX;\n            maxDictSize = MIN(maxDictSize, shortCacheMaxDictSize);\n            assert(!loadLdmDict);\n        }\n\n        /* If the dictionary is too large, only load the suffix of the dictionary. */\n        if (srcSize > maxDictSize) {\n            ip = iend - maxDictSize;\n            src = ip;\n            srcSize = maxDictSize;\n        }\n    }\n\n    if (srcSize > ZSTD_CHUNKSIZE_MAX) {\n        /* We must have cleared our windows when our source is this large. */\n        assert(ZSTD_window_isEmpty(ms->window));\n        if (loadLdmDict) assert(ZSTD_window_isEmpty(ls->window));\n    }\n    ZSTD_window_update(&ms->window, src, srcSize, /* forceNonContiguous */ 0);\n\n    DEBUGLOG(4, \"ZSTD_loadDictionaryContent: useRowMatchFinder=%d\", (int)params->useRowMatchFinder);\n\n    if (loadLdmDict) { /* Load the entire dict into LDM matchfinders. */\n        DEBUGLOG(4, \"ZSTD_loadDictionaryContent: Trigger loadLdmDict\");\n        ZSTD_window_update(&ls->window, src, srcSize, /* forceNonContiguous */ 0);\n        ls->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ls->window.base);\n        ZSTD_ldm_fillHashTable(ls, ip, iend, &params->ldmParams);\n        DEBUGLOG(4, \"ZSTD_loadDictionaryContent: ZSTD_ldm_fillHashTable completes\");\n    }\n\n    /* If the dict is larger than we can reasonably index in our tables, only load the suffix. */\n    {   U32 maxDictSize = 1U << MIN(MAX(params->cParams.hashLog + 3, params->cParams.chainLog + 1), 31);\n        if (srcSize > maxDictSize) {\n            ip = iend - maxDictSize;\n            src = ip;\n            srcSize = maxDictSize;\n        }\n    }\n\n    ms->nextToUpdate = (U32)(ip - ms->window.base);\n    ms->loadedDictEnd = params->forceWindow ? 0 : (U32)(iend - ms->window.base);\n    ms->forceNonContiguous = params->deterministicRefPrefix;\n\n    if (srcSize <= HASH_READ_SIZE) return 0;\n\n    ZSTD_overflowCorrectIfNeeded(ms, ws, params, ip, iend);\n\n    switch(params->cParams.strategy)\n    {\n    case ZSTD_fast:\n        ZSTD_fillHashTable(ms, iend, dtlm, tfp);\n        break;\n    case ZSTD_dfast:\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n        ZSTD_fillDoubleHashTable(ms, iend, dtlm, tfp);\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    case ZSTD_greedy:\n    case ZSTD_lazy:\n    case ZSTD_lazy2:\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR)\n        assert(srcSize >= HASH_READ_SIZE);\n        if (ms->dedicatedDictSearch) {\n            assert(ms->chainTable != NULL);\n            ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, iend-HASH_READ_SIZE);\n        } else {\n            assert(params->useRowMatchFinder != ZSTD_ps_auto);\n            if (params->useRowMatchFinder == ZSTD_ps_enable) {\n                size_t const tagTableSize = ((size_t)1 << params->cParams.hashLog);\n                ZSTD_memset(ms->tagTable, 0, tagTableSize);\n                ZSTD_row_update(ms, iend-HASH_READ_SIZE);\n                DEBUGLOG(4, \"Using row-based hash table for lazy dict\");\n            } else {\n                ZSTD_insertAndFindFirstIndex(ms, iend-HASH_READ_SIZE);\n                DEBUGLOG(4, \"Using chain-based hash table for lazy dict\");\n            }\n        }\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    case ZSTD_btlazy2:   /* we want the dictionary table fully sorted */\n    case ZSTD_btopt:\n    case ZSTD_btultra:\n    case ZSTD_btultra2:\n#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n        assert(srcSize >= HASH_READ_SIZE);\n        DEBUGLOG(4, \"Fill %u bytes into the Binary Tree\", (unsigned)srcSize);\n        ZSTD_updateTree(ms, iend-HASH_READ_SIZE, iend);\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    default:\n        assert(0);  /* not possible : not a valid strategy id */\n    }\n\n    ms->nextToUpdate = (U32)(iend - ms->window.base);\n    return 0;\n}\n\n\n/* Dictionaries that assign zero probability to symbols that show up causes problems\n * when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check\n * and only dictionaries with 100% valid symbols can be assumed valid.\n */\nstatic FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue)\n{\n    U32 s;\n    if (dictMaxSymbolValue < maxSymbolValue) {\n        return FSE_repeat_check;\n    }\n    for (s = 0; s <= maxSymbolValue; ++s) {\n        if (normalizedCounter[s] == 0) {\n            return FSE_repeat_check;\n        }\n    }\n    return FSE_repeat_valid;\n}\n\nsize_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,\n                         const void* const dict, size_t dictSize)\n{\n    short offcodeNCount[MaxOff+1];\n    unsigned offcodeMaxValue = MaxOff;\n    const BYTE* dictPtr = (const BYTE*)dict;    /* skip magic num and dict ID */\n    const BYTE* const dictEnd = dictPtr + dictSize;\n    dictPtr += 8;\n    bs->entropy.huf.repeatMode = HUF_repeat_check;\n\n    {   unsigned maxSymbolValue = 255;\n        unsigned hasZeroWeights = 1;\n        size_t const hufHeaderSize = HUF_readCTable((HUF_CElt*)bs->entropy.huf.CTable, &maxSymbolValue, dictPtr,\n            (size_t)(dictEnd-dictPtr), &hasZeroWeights);\n\n        /* We only set the loaded table as valid if it contains all non-zero\n         * weights. Otherwise, we set it to check */\n        if (!hasZeroWeights && maxSymbolValue == 255)\n            bs->entropy.huf.repeatMode = HUF_repeat_valid;\n\n        RETURN_ERROR_IF(HUF_isError(hufHeaderSize), dictionary_corrupted, \"\");\n        dictPtr += hufHeaderSize;\n    }\n\n    {   unsigned offcodeLog;\n        size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, \"\");\n        /* fill all offset symbols to avoid garbage at end of table */\n        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(\n                bs->entropy.fse.offcodeCTable,\n                offcodeNCount, MaxOff, offcodeLog,\n                workspace, HUF_WORKSPACE_SIZE)),\n            dictionary_corrupted, \"\");\n        /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */\n        dictPtr += offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(\n                bs->entropy.fse.matchlengthCTable,\n                matchlengthNCount, matchlengthMaxValue, matchlengthLog,\n                workspace, HUF_WORKSPACE_SIZE)),\n            dictionary_corrupted, \"\");\n        bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML);\n        dictPtr += matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp(\n                bs->entropy.fse.litlengthCTable,\n                litlengthNCount, litlengthMaxValue, litlengthLog,\n                workspace, HUF_WORKSPACE_SIZE)),\n            dictionary_corrupted, \"\");\n        bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL);\n        dictPtr += litlengthHeaderSize;\n    }\n\n    RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, \"\");\n    bs->rep[0] = MEM_readLE32(dictPtr+0);\n    bs->rep[1] = MEM_readLE32(dictPtr+4);\n    bs->rep[2] = MEM_readLE32(dictPtr+8);\n    dictPtr += 12;\n\n    {   size_t const dictContentSize = (size_t)(dictEnd - dictPtr);\n        U32 offcodeMax = MaxOff;\n        if (dictContentSize <= ((U32)-1) - 128 KB) {\n            U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */\n            offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */\n        }\n        /* All offset values <= dictContentSize + 128 KB must be representable for a valid table */\n        bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff));\n\n        /* All repCodes must be <= dictContentSize and != 0 */\n        {   U32 u;\n            for (u=0; u<3; u++) {\n                RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, \"\");\n                RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, \"\");\n    }   }   }\n\n    return (size_t)(dictPtr - (const BYTE*)dict);\n}\n\n/* Dictionary format :\n * See :\n * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format\n */\n/*! ZSTD_loadZstdDictionary() :\n * @return : dictID, or an error code\n *  assumptions : magic number supposed already checked\n *                dictSize supposed >= 8\n */\nstatic size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs,\n                                      ZSTD_MatchState_t* ms,\n                                      ZSTD_cwksp* ws,\n                                      ZSTD_CCtx_params const* params,\n                                      const void* dict, size_t dictSize,\n                                      ZSTD_dictTableLoadMethod_e dtlm,\n                                      ZSTD_tableFillPurpose_e tfp,\n                                      void* workspace)\n{\n    const BYTE* dictPtr = (const BYTE*)dict;\n    const BYTE* const dictEnd = dictPtr + dictSize;\n    size_t dictID;\n    size_t eSize;\n    ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog)));\n    assert(dictSize >= 8);\n    assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY);\n\n    dictID = params->fParams.noDictIDFlag ? 0 :  MEM_readLE32(dictPtr + 4 /* skip magic number */ );\n    eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize);\n    FORWARD_IF_ERROR(eSize, \"ZSTD_loadCEntropy failed\");\n    dictPtr += eSize;\n\n    {\n        size_t const dictContentSize = (size_t)(dictEnd - dictPtr);\n        FORWARD_IF_ERROR(ZSTD_loadDictionaryContent(\n            ms, NULL, ws, params, dictPtr, dictContentSize, dtlm, tfp), \"\");\n    }\n    return dictID;\n}\n\n/** ZSTD_compress_insertDictionary() :\n*   @return : dictID, or an error code */\nstatic size_t\nZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs,\n                               ZSTD_MatchState_t* ms,\n                               ldmState_t* ls,\n                               ZSTD_cwksp* ws,\n                         const ZSTD_CCtx_params* params,\n                         const void* dict, size_t dictSize,\n                               ZSTD_dictContentType_e dictContentType,\n                               ZSTD_dictTableLoadMethod_e dtlm,\n                               ZSTD_tableFillPurpose_e tfp,\n                               void* workspace)\n{\n    DEBUGLOG(4, \"ZSTD_compress_insertDictionary (dictSize=%u)\", (U32)dictSize);\n    if ((dict==NULL) || (dictSize<8)) {\n        RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, \"\");\n        return 0;\n    }\n\n    ZSTD_reset_compressedBlockState(bs);\n\n    /* dict restricted modes */\n    if (dictContentType == ZSTD_dct_rawContent)\n        return ZSTD_loadDictionaryContent(ms, ls, ws, params, dict, dictSize, dtlm, tfp);\n\n    if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) {\n        if (dictContentType == ZSTD_dct_auto) {\n            DEBUGLOG(4, \"raw content dictionary detected\");\n            return ZSTD_loadDictionaryContent(\n                ms, ls, ws, params, dict, dictSize, dtlm, tfp);\n        }\n        RETURN_ERROR_IF(dictContentType == ZSTD_dct_fullDict, dictionary_wrong, \"\");\n        assert(0);   /* impossible */\n    }\n\n    /* dict as full zstd dictionary */\n    return ZSTD_loadZstdDictionary(\n        bs, ms, ws, params, dict, dictSize, dtlm, tfp, workspace);\n}\n\n#define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB)\n#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL)\n\n/*! ZSTD_compressBegin_internal() :\n * Assumption : either @dict OR @cdict (or none) is non-NULL, never both\n * @return : 0, or an error code */\nstatic size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx,\n                                    const void* dict, size_t dictSize,\n                                    ZSTD_dictContentType_e dictContentType,\n                                    ZSTD_dictTableLoadMethod_e dtlm,\n                                    const ZSTD_CDict* cdict,\n                                    const ZSTD_CCtx_params* params, U64 pledgedSrcSize,\n                                    ZSTD_buffered_policy_e zbuff)\n{\n    size_t const dictContentSize = cdict ? cdict->dictContentSize : dictSize;\n#if ZSTD_TRACE\n    cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0;\n#endif\n    DEBUGLOG(4, \"ZSTD_compressBegin_internal: wlog=%u\", params->cParams.windowLog);\n    /* params are supposed to be fully validated at this point */\n    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));\n    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */\n    if ( (cdict)\n      && (cdict->dictContentSize > 0)\n      && ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF\n        || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER\n        || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN\n        || cdict->compressionLevel == 0)\n      && (params->attachDictPref != ZSTD_dictForceLoad) ) {\n        return ZSTD_resetCCtx_usingCDict(cctx, cdict, params, pledgedSrcSize, zbuff);\n    }\n\n    FORWARD_IF_ERROR( ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize,\n                                     dictContentSize,\n                                     ZSTDcrp_makeClean, zbuff) , \"\");\n    {   size_t const dictID = cdict ?\n                ZSTD_compress_insertDictionary(\n                        cctx->blockState.prevCBlock, &cctx->blockState.matchState,\n                        &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent,\n                        cdict->dictContentSize, cdict->dictContentType, dtlm,\n                        ZSTD_tfp_forCCtx, cctx->tmpWorkspace)\n              : ZSTD_compress_insertDictionary(\n                        cctx->blockState.prevCBlock, &cctx->blockState.matchState,\n                        &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, dict, dictSize,\n                        dictContentType, dtlm, ZSTD_tfp_forCCtx, cctx->tmpWorkspace);\n        FORWARD_IF_ERROR(dictID, \"ZSTD_compress_insertDictionary failed\");\n        assert(dictID <= UINT_MAX);\n        cctx->dictID = (U32)dictID;\n        cctx->dictContentSize = dictContentSize;\n    }\n    return 0;\n}\n\nsize_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,\n                                    const void* dict, size_t dictSize,\n                                    ZSTD_dictContentType_e dictContentType,\n                                    ZSTD_dictTableLoadMethod_e dtlm,\n                                    const ZSTD_CDict* cdict,\n                                    const ZSTD_CCtx_params* params,\n                                    unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_compressBegin_advanced_internal: wlog=%u\", params->cParams.windowLog);\n    /* compression parameters verification and optimization */\n    FORWARD_IF_ERROR( ZSTD_checkCParams(params->cParams) , \"\");\n    return ZSTD_compressBegin_internal(cctx,\n                                       dict, dictSize, dictContentType, dtlm,\n                                       cdict,\n                                       params, pledgedSrcSize,\n                                       ZSTDb_not_buffered);\n}\n\n/*! ZSTD_compressBegin_advanced() :\n*   @return : 0, or an error code */\nsize_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx,\n                             const void* dict, size_t dictSize,\n                                   ZSTD_parameters params, unsigned long long pledgedSrcSize)\n{\n    ZSTD_CCtx_params cctxParams;\n    ZSTD_CCtxParams_init_internal(&cctxParams, &params, ZSTD_NO_CLEVEL);\n    return ZSTD_compressBegin_advanced_internal(cctx,\n                                            dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast,\n                                            NULL /*cdict*/,\n                                            &cctxParams, pledgedSrcSize);\n}\n\nstatic size_t\nZSTD_compressBegin_usingDict_deprecated(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)\n{\n    ZSTD_CCtx_params cctxParams;\n    {   ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict);\n        ZSTD_CCtxParams_init_internal(&cctxParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel);\n    }\n    DEBUGLOG(4, \"ZSTD_compressBegin_usingDict (dictSize=%u)\", (unsigned)dictSize);\n    return ZSTD_compressBegin_internal(cctx, dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,\n                                       &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, ZSTDb_not_buffered);\n}\n\nsize_t\nZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel)\n{\n    return ZSTD_compressBegin_usingDict_deprecated(cctx, dict, dictSize, compressionLevel);\n}\n\nsize_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel)\n{\n    return ZSTD_compressBegin_usingDict_deprecated(cctx, NULL, 0, compressionLevel);\n}\n\n\n/*! ZSTD_writeEpilogue() :\n*   Ends a frame.\n*   @return : nb of bytes written into dst (or an error code) */\nstatic size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n\n    DEBUGLOG(4, \"ZSTD_writeEpilogue\");\n    RETURN_ERROR_IF(cctx->stage == ZSTDcs_created, stage_wrong, \"init missing\");\n\n    /* special case : empty frame */\n    if (cctx->stage == ZSTDcs_init) {\n        size_t fhSize = ZSTD_writeFrameHeader(dst, dstCapacity, &cctx->appliedParams, 0, 0);\n        FORWARD_IF_ERROR(fhSize, \"ZSTD_writeFrameHeader failed\");\n        dstCapacity -= fhSize;\n        op += fhSize;\n        cctx->stage = ZSTDcs_ongoing;\n    }\n\n    if (cctx->stage != ZSTDcs_ending) {\n        /* write one last empty block, make it the \"last\" block */\n        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1) + 0;\n        ZSTD_STATIC_ASSERT(ZSTD_BLOCKHEADERSIZE == 3);\n        RETURN_ERROR_IF(dstCapacity<3, dstSize_tooSmall, \"no room for epilogue\");\n        MEM_writeLE24(op, cBlockHeader24);\n        op += ZSTD_blockHeaderSize;\n        dstCapacity -= ZSTD_blockHeaderSize;\n    }\n\n    if (cctx->appliedParams.fParams.checksumFlag) {\n        U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);\n        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, \"no room for checksum\");\n        DEBUGLOG(4, \"ZSTD_writeEpilogue: write checksum : %08X\", (unsigned)checksum);\n        MEM_writeLE32(op, checksum);\n        op += 4;\n    }\n\n    cctx->stage = ZSTDcs_created;  /* return to \"created but no init\" status */\n    return (size_t)(op-ostart);\n}\n\nvoid ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize)\n{\n#if ZSTD_TRACE\n    if (cctx->traceCtx && ZSTD_trace_compress_end != NULL) {\n        int const streaming = cctx->inBuffSize > 0 || cctx->outBuffSize > 0 || cctx->appliedParams.nbWorkers > 0;\n        ZSTD_Trace trace;\n        ZSTD_memset(&trace, 0, sizeof(trace));\n        trace.version = ZSTD_VERSION_NUMBER;\n        trace.streaming = streaming;\n        trace.dictionaryID = cctx->dictID;\n        trace.dictionarySize = cctx->dictContentSize;\n        trace.uncompressedSize = cctx->consumedSrcSize;\n        trace.compressedSize = cctx->producedCSize + extraCSize;\n        trace.params = &cctx->appliedParams;\n        trace.cctx = cctx;\n        ZSTD_trace_compress_end(cctx->traceCtx, &trace);\n    }\n    cctx->traceCtx = 0;\n#else\n    (void)cctx;\n    (void)extraCSize;\n#endif\n}\n\nsize_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize)\n{\n    size_t endResult;\n    size_t const cSize = ZSTD_compressContinue_internal(cctx,\n                                dst, dstCapacity, src, srcSize,\n                                1 /* frame mode */, 1 /* last chunk */);\n    FORWARD_IF_ERROR(cSize, \"ZSTD_compressContinue_internal failed\");\n    endResult = ZSTD_writeEpilogue(cctx, (char*)dst + cSize, dstCapacity-cSize);\n    FORWARD_IF_ERROR(endResult, \"ZSTD_writeEpilogue failed\");\n    assert(!(cctx->appliedParams.fParams.contentSizeFlag && cctx->pledgedSrcSizePlusOne == 0));\n    if (cctx->pledgedSrcSizePlusOne != 0) {  /* control src size */\n        ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN == (unsigned long long)-1);\n        DEBUGLOG(4, \"end of frame : controlling src size\");\n        RETURN_ERROR_IF(\n            cctx->pledgedSrcSizePlusOne != cctx->consumedSrcSize+1,\n            srcSize_wrong,\n             \"error : pledgedSrcSize = %u, while realSrcSize = %u\",\n            (unsigned)cctx->pledgedSrcSizePlusOne-1,\n            (unsigned)cctx->consumedSrcSize);\n    }\n    ZSTD_CCtx_trace(cctx, endResult);\n    return cSize + endResult;\n}\n\n/* NOTE: Must just wrap ZSTD_compressEnd_public() */\nsize_t ZSTD_compressEnd(ZSTD_CCtx* cctx,\n                        void* dst, size_t dstCapacity,\n                  const void* src, size_t srcSize)\n{\n    return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\nsize_t ZSTD_compress_advanced (ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize,\n                         const void* dict,size_t dictSize,\n                               ZSTD_parameters params)\n{\n    DEBUGLOG(4, \"ZSTD_compress_advanced\");\n    FORWARD_IF_ERROR(ZSTD_checkCParams(params.cParams), \"\");\n    ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, &params, ZSTD_NO_CLEVEL);\n    return ZSTD_compress_advanced_internal(cctx,\n                                           dst, dstCapacity,\n                                           src, srcSize,\n                                           dict, dictSize,\n                                           &cctx->simpleApiParams);\n}\n\n/* Internal */\nsize_t ZSTD_compress_advanced_internal(\n        ZSTD_CCtx* cctx,\n        void* dst, size_t dstCapacity,\n        const void* src, size_t srcSize,\n        const void* dict,size_t dictSize,\n        const ZSTD_CCtx_params* params)\n{\n    DEBUGLOG(4, \"ZSTD_compress_advanced_internal (srcSize:%u)\", (unsigned)srcSize);\n    FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,\n                         dict, dictSize, ZSTD_dct_auto, ZSTD_dtlm_fast, NULL,\n                         params, srcSize, ZSTDb_not_buffered) , \"\");\n    return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\nsize_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize,\n                         const void* dict, size_t dictSize,\n                               int compressionLevel)\n{\n    {\n        ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict);\n        assert(params.fParams.contentSizeFlag == 1);\n        ZSTD_CCtxParams_init_internal(&cctx->simpleApiParams, &params, (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT: compressionLevel);\n    }\n    DEBUGLOG(4, \"ZSTD_compress_usingDict (srcSize=%u)\", (unsigned)srcSize);\n    return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, dict, dictSize, &cctx->simpleApiParams);\n}\n\nsize_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,\n                         void* dst, size_t dstCapacity,\n                   const void* src, size_t srcSize,\n                         int compressionLevel)\n{\n    DEBUGLOG(4, \"ZSTD_compressCCtx (srcSize=%u)\", (unsigned)srcSize);\n    assert(cctx != NULL);\n    return ZSTD_compress_usingDict(cctx, dst, dstCapacity, src, srcSize, NULL, 0, compressionLevel);\n}\n\nsize_t ZSTD_compress(void* dst, size_t dstCapacity,\n               const void* src, size_t srcSize,\n                     int compressionLevel)\n{\n    size_t result;\n#if ZSTD_COMPRESS_HEAPMODE\n    ZSTD_CCtx* cctx = ZSTD_createCCtx();\n    RETURN_ERROR_IF(!cctx, memory_allocation, \"ZSTD_createCCtx failed\");\n    result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel);\n    ZSTD_freeCCtx(cctx);\n#else\n    ZSTD_CCtx ctxBody;\n    ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem);\n    result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel);\n    ZSTD_freeCCtxContent(&ctxBody);   /* can't free ctxBody itself, as it's on stack; free only heap content */\n#endif\n    return result;\n}\n\n\n/* =====  Dictionary API  ===== */\n\n/*! ZSTD_estimateCDictSize_advanced() :\n *  Estimate amount of memory that will be needed to create a dictionary with following arguments */\nsize_t ZSTD_estimateCDictSize_advanced(\n        size_t dictSize, ZSTD_compressionParameters cParams,\n        ZSTD_dictLoadMethod_e dictLoadMethod)\n{\n    DEBUGLOG(5, \"sizeof(ZSTD_CDict) : %u\", (unsigned)sizeof(ZSTD_CDict));\n    return ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))\n         + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)\n         /* enableDedicatedDictSearch == 1 ensures that CDict estimation will not be too small\n          * in case we are using DDS with row-hash. */\n         + ZSTD_sizeof_matchState(&cParams, ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams),\n                                  /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0)\n         + (dictLoadMethod == ZSTD_dlm_byRef ? 0\n            : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));\n}\n\nsize_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel)\n{\n    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy);\n}\n\nsize_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict)\n{\n    if (cdict==NULL) return 0;   /* support sizeof on NULL */\n    DEBUGLOG(5, \"sizeof(*cdict) : %u\", (unsigned)sizeof(*cdict));\n    /* cdict may be in the workspace */\n    return (cdict->workspace.workspace == cdict ? 0 : sizeof(*cdict))\n        + ZSTD_cwksp_sizeof(&cdict->workspace);\n}\n\nstatic size_t ZSTD_initCDict_internal(\n                    ZSTD_CDict* cdict,\n              const void* dictBuffer, size_t dictSize,\n                    ZSTD_dictLoadMethod_e dictLoadMethod,\n                    ZSTD_dictContentType_e dictContentType,\n                    ZSTD_CCtx_params params)\n{\n    DEBUGLOG(3, \"ZSTD_initCDict_internal (dictContentType:%u)\", (unsigned)dictContentType);\n    assert(!ZSTD_checkCParams(params.cParams));\n    cdict->matchState.cParams = params.cParams;\n    cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch;\n    if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) {\n        cdict->dictContent = dictBuffer;\n    } else {\n         void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*)));\n        RETURN_ERROR_IF(!internalBuffer, memory_allocation, \"NULL pointer!\");\n        cdict->dictContent = internalBuffer;\n        ZSTD_memcpy(internalBuffer, dictBuffer, dictSize);\n    }\n    cdict->dictContentSize = dictSize;\n    cdict->dictContentType = dictContentType;\n\n    cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE);\n\n\n    /* Reset the state to no dictionary */\n    ZSTD_reset_compressedBlockState(&cdict->cBlockState);\n    FORWARD_IF_ERROR(ZSTD_reset_matchState(\n        &cdict->matchState,\n        &cdict->workspace,\n        &params.cParams,\n        params.useRowMatchFinder,\n        ZSTDcrp_makeClean,\n        ZSTDirp_reset,\n        ZSTD_resetTarget_CDict), \"\");\n    /* (Maybe) load the dictionary\n     * Skips loading the dictionary if it is < 8 bytes.\n     */\n    {   params.compressionLevel = ZSTD_CLEVEL_DEFAULT;\n        params.fParams.contentSizeFlag = 1;\n        {   size_t const dictID = ZSTD_compress_insertDictionary(\n                    &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace,\n                    &params, cdict->dictContent, cdict->dictContentSize,\n                    dictContentType, ZSTD_dtlm_full, ZSTD_tfp_forCDict, cdict->entropyWorkspace);\n            FORWARD_IF_ERROR(dictID, \"ZSTD_compress_insertDictionary failed\");\n            assert(dictID <= (size_t)(U32)-1);\n            cdict->dictID = (U32)dictID;\n        }\n    }\n\n    return 0;\n}\n\nstatic ZSTD_CDict*\nZSTD_createCDict_advanced_internal(size_t dictSize,\n                                ZSTD_dictLoadMethod_e dictLoadMethod,\n                                ZSTD_compressionParameters cParams,\n                                ZSTD_ParamSwitch_e useRowMatchFinder,\n                                int enableDedicatedDictSearch,\n                                ZSTD_customMem customMem)\n{\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced_internal (dictSize=%u)\", (unsigned)dictSize);\n\n    {   size_t const workspaceSize =\n            ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) +\n            ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) +\n            ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, enableDedicatedDictSearch, /* forCCtx */ 0) +\n            (dictLoadMethod == ZSTD_dlm_byRef ? 0\n             : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))));\n        void* const workspace = ZSTD_customMalloc(workspaceSize, customMem);\n        ZSTD_cwksp ws;\n        ZSTD_CDict* cdict;\n\n        if (!workspace) {\n            ZSTD_customFree(workspace, customMem);\n            return NULL;\n        }\n\n        ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc);\n\n        cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));\n        assert(cdict != NULL);\n        ZSTD_cwksp_move(&cdict->workspace, &ws);\n        cdict->customMem = customMem;\n        cdict->compressionLevel = ZSTD_NO_CLEVEL; /* signals advanced API usage */\n        cdict->useRowMatchFinder = useRowMatchFinder;\n        return cdict;\n    }\n}\n\nZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,\n                                      ZSTD_dictLoadMethod_e dictLoadMethod,\n                                      ZSTD_dictContentType_e dictContentType,\n                                      ZSTD_compressionParameters cParams,\n                                      ZSTD_customMem customMem)\n{\n    ZSTD_CCtx_params cctxParams;\n    ZSTD_memset(&cctxParams, 0, sizeof(cctxParams));\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced, dictSize=%u, mode=%u\", (unsigned)dictSize, (unsigned)dictContentType);\n    ZSTD_CCtxParams_init(&cctxParams, 0);\n    cctxParams.cParams = cParams;\n    cctxParams.customMem = customMem;\n    return ZSTD_createCDict_advanced2(\n        dictBuffer, dictSize,\n        dictLoadMethod, dictContentType,\n        &cctxParams, customMem);\n}\n\nZSTD_CDict* ZSTD_createCDict_advanced2(\n        const void* dict, size_t dictSize,\n        ZSTD_dictLoadMethod_e dictLoadMethod,\n        ZSTD_dictContentType_e dictContentType,\n        const ZSTD_CCtx_params* originalCctxParams,\n        ZSTD_customMem customMem)\n{\n    ZSTD_CCtx_params cctxParams = *originalCctxParams;\n    ZSTD_compressionParameters cParams;\n    ZSTD_CDict* cdict;\n\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced2, dictSize=%u, mode=%u\", (unsigned)dictSize, (unsigned)dictContentType);\n    if (!customMem.customAlloc ^ !customMem.customFree) return NULL;\n\n    if (cctxParams.enableDedicatedDictSearch) {\n        cParams = ZSTD_dedicatedDictSearch_getCParams(\n            cctxParams.compressionLevel, dictSize);\n        ZSTD_overrideCParams(&cParams, &cctxParams.cParams);\n    } else {\n        cParams = ZSTD_getCParamsFromCCtxParams(\n            &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    }\n\n    if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) {\n        /* Fall back to non-DDSS params */\n        cctxParams.enableDedicatedDictSearch = 0;\n        cParams = ZSTD_getCParamsFromCCtxParams(\n            &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    }\n\n    DEBUGLOG(3, \"ZSTD_createCDict_advanced2: DedicatedDictSearch=%u\", cctxParams.enableDedicatedDictSearch);\n    cctxParams.cParams = cParams;\n    cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);\n\n    cdict = ZSTD_createCDict_advanced_internal(dictSize,\n                        dictLoadMethod, cctxParams.cParams,\n                        cctxParams.useRowMatchFinder, cctxParams.enableDedicatedDictSearch,\n                        customMem);\n\n    if (!cdict || ZSTD_isError( ZSTD_initCDict_internal(cdict,\n                                    dict, dictSize,\n                                    dictLoadMethod, dictContentType,\n                                    cctxParams) )) {\n        ZSTD_freeCDict(cdict);\n        return NULL;\n    }\n\n    return cdict;\n}\n\nZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel)\n{\n    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,\n                                                  ZSTD_dlm_byCopy, ZSTD_dct_auto,\n                                                  cParams, ZSTD_defaultCMem);\n    if (cdict)\n        cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;\n    return cdict;\n}\n\nZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel)\n{\n    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict);\n    ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize,\n                                     ZSTD_dlm_byRef, ZSTD_dct_auto,\n                                     cParams, ZSTD_defaultCMem);\n    if (cdict)\n        cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel;\n    return cdict;\n}\n\nsize_t ZSTD_freeCDict(ZSTD_CDict* cdict)\n{\n    if (cdict==NULL) return 0;   /* support free on NULL */\n    {   ZSTD_customMem const cMem = cdict->customMem;\n        int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict);\n        ZSTD_cwksp_free(&cdict->workspace, cMem);\n        if (!cdictInWorkspace) {\n            ZSTD_customFree(cdict, cMem);\n        }\n        return 0;\n    }\n}\n\n/*! ZSTD_initStaticCDict_advanced() :\n *  Generate a digested dictionary in provided memory area.\n *  workspace: The memory area to emplace the dictionary into.\n *             Provided pointer must 8-bytes aligned.\n *             It must outlive dictionary usage.\n *  workspaceSize: Use ZSTD_estimateCDictSize()\n *                 to determine how large workspace must be.\n *  cParams : use ZSTD_getCParams() to transform a compression level\n *            into its relevant cParams.\n * @return : pointer to ZSTD_CDict*, or NULL if error (size too small)\n *  Note : there is no corresponding \"free\" function.\n *         Since workspace was allocated externally, it must be freed externally.\n */\nconst ZSTD_CDict* ZSTD_initStaticCDict(\n                                 void* workspace, size_t workspaceSize,\n                           const void* dict, size_t dictSize,\n                                 ZSTD_dictLoadMethod_e dictLoadMethod,\n                                 ZSTD_dictContentType_e dictContentType,\n                                 ZSTD_compressionParameters cParams)\n{\n    ZSTD_ParamSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams);\n    /* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */\n    size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0);\n    size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))\n                            + (dictLoadMethod == ZSTD_dlm_byRef ? 0\n                               : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*))))\n                            + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)\n                            + matchStateSize;\n    ZSTD_CDict* cdict;\n    ZSTD_CCtx_params params;\n\n    DEBUGLOG(4, \"ZSTD_initStaticCDict (dictSize==%u)\", (unsigned)dictSize);\n    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */\n\n    {\n        ZSTD_cwksp ws;\n        ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc);\n        cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict));\n        if (cdict == NULL) return NULL;\n        ZSTD_cwksp_move(&cdict->workspace, &ws);\n    }\n\n    if (workspaceSize < neededSize) return NULL;\n\n    ZSTD_CCtxParams_init(&params, 0);\n    params.cParams = cParams;\n    params.useRowMatchFinder = useRowMatchFinder;\n    cdict->useRowMatchFinder = useRowMatchFinder;\n    cdict->compressionLevel = ZSTD_NO_CLEVEL;\n\n    if (ZSTD_isError( ZSTD_initCDict_internal(cdict,\n                                              dict, dictSize,\n                                              dictLoadMethod, dictContentType,\n                                              params) ))\n        return NULL;\n\n    return cdict;\n}\n\nZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict)\n{\n    assert(cdict != NULL);\n    return cdict->matchState.cParams;\n}\n\n/*! ZSTD_getDictID_fromCDict() :\n *  Provides the dictID of the dictionary loaded into `cdict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nunsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict)\n{\n    if (cdict==NULL) return 0;\n    return cdict->dictID;\n}\n\n/* ZSTD_compressBegin_usingCDict_internal() :\n * Implementation of various ZSTD_compressBegin_usingCDict* functions.\n */\nstatic size_t ZSTD_compressBegin_usingCDict_internal(\n    ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,\n    ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)\n{\n    ZSTD_CCtx_params cctxParams;\n    DEBUGLOG(4, \"ZSTD_compressBegin_usingCDict_internal\");\n    RETURN_ERROR_IF(cdict==NULL, dictionary_wrong, \"NULL pointer!\");\n    /* Initialize the cctxParams from the cdict */\n    {\n        ZSTD_parameters params;\n        params.fParams = fParams;\n        params.cParams = ( pledgedSrcSize < ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF\n                        || pledgedSrcSize < cdict->dictContentSize * ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER\n                        || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN\n                        || cdict->compressionLevel == 0 ) ?\n                ZSTD_getCParamsFromCDict(cdict)\n              : ZSTD_getCParams(cdict->compressionLevel,\n                                pledgedSrcSize,\n                                cdict->dictContentSize);\n        ZSTD_CCtxParams_init_internal(&cctxParams, &params, cdict->compressionLevel);\n    }\n    /* Increase window log to fit the entire dictionary and source if the\n     * source size is known. Limit the increase to 19, which is the\n     * window log for compression level 1 with the largest source size.\n     */\n    if (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n        U32 const limitedSrcSize = (U32)MIN(pledgedSrcSize, 1U << 19);\n        U32 const limitedSrcLog = limitedSrcSize > 1 ? ZSTD_highbit32(limitedSrcSize - 1) + 1 : 1;\n        cctxParams.cParams.windowLog = MAX(cctxParams.cParams.windowLog, limitedSrcLog);\n    }\n    return ZSTD_compressBegin_internal(cctx,\n                                        NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast,\n                                        cdict,\n                                        &cctxParams, pledgedSrcSize,\n                                        ZSTDb_not_buffered);\n}\n\n\n/* ZSTD_compressBegin_usingCDict_advanced() :\n * This function is DEPRECATED.\n * cdict must be != NULL */\nsize_t ZSTD_compressBegin_usingCDict_advanced(\n    ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict,\n    ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize)\n{\n    return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, pledgedSrcSize);\n}\n\n/* ZSTD_compressBegin_usingCDict() :\n * cdict must be != NULL */\nsize_t ZSTD_compressBegin_usingCDict_deprecated(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)\n{\n    ZSTD_frameParameters const fParams = { 0 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };\n    return ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, ZSTD_CONTENTSIZE_UNKNOWN);\n}\n\nsize_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict)\n{\n    return ZSTD_compressBegin_usingCDict_deprecated(cctx, cdict);\n}\n\n/*! ZSTD_compress_usingCDict_internal():\n * Implementation of various ZSTD_compress_usingCDict* functions.\n */\nstatic size_t ZSTD_compress_usingCDict_internal(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize,\n                                const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)\n{\n    FORWARD_IF_ERROR(ZSTD_compressBegin_usingCDict_internal(cctx, cdict, fParams, srcSize), \"\"); /* will check if cdict != NULL */\n    return ZSTD_compressEnd_public(cctx, dst, dstCapacity, src, srcSize);\n}\n\n/*! ZSTD_compress_usingCDict_advanced():\n * This function is DEPRECATED.\n */\nsize_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize,\n                                const ZSTD_CDict* cdict, ZSTD_frameParameters fParams)\n{\n    return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);\n}\n\n/*! ZSTD_compress_usingCDict() :\n *  Compression using a digested Dictionary.\n *  Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.\n *  Note that compression parameters are decided at CDict creation time\n *  while frame parameters are hardcoded */\nsize_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                                const void* src, size_t srcSize,\n                                const ZSTD_CDict* cdict)\n{\n    ZSTD_frameParameters const fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ };\n    return ZSTD_compress_usingCDict_internal(cctx, dst, dstCapacity, src, srcSize, cdict, fParams);\n}\n\n\n\n/* ******************************************************************\n*  Streaming\n********************************************************************/\n\nZSTD_CStream* ZSTD_createCStream(void)\n{\n    DEBUGLOG(3, \"ZSTD_createCStream\");\n    return ZSTD_createCStream_advanced(ZSTD_defaultCMem);\n}\n\nZSTD_CStream* ZSTD_initStaticCStream(void *workspace, size_t workspaceSize)\n{\n    return ZSTD_initStaticCCtx(workspace, workspaceSize);\n}\n\nZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem)\n{   /* CStream and CCtx are now same object */\n    return ZSTD_createCCtx_advanced(customMem);\n}\n\nsize_t ZSTD_freeCStream(ZSTD_CStream* zcs)\n{\n    return ZSTD_freeCCtx(zcs);   /* same object */\n}\n\n\n\n/*======   Initialization   ======*/\n\nsize_t ZSTD_CStreamInSize(void)  { return ZSTD_BLOCKSIZE_MAX; }\n\nsize_t ZSTD_CStreamOutSize(void)\n{\n    return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ;\n}\n\nstatic ZSTD_CParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize)\n{\n    if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize))\n        return ZSTD_cpm_attachDict;\n    else\n        return ZSTD_cpm_noAttachDict;\n}\n\n/* ZSTD_resetCStream():\n * pledgedSrcSize == 0 means \"unknown\" */\nsize_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pss)\n{\n    /* temporary : 0 interpreted as \"unknown\" during transition period.\n     * Users willing to specify \"unknown\" **must** use ZSTD_CONTENTSIZE_UNKNOWN.\n     * 0 will be interpreted as \"empty\" in the future.\n     */\n    U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;\n    DEBUGLOG(4, \"ZSTD_resetCStream: pledgedSrcSize = %u\", (unsigned)pledgedSrcSize);\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    return 0;\n}\n\n/*! ZSTD_initCStream_internal() :\n *  Note : for lib/compress only. Used by zstdmt_compress.c.\n *  Assumption 1 : params are valid\n *  Assumption 2 : either dict, or cdict, is defined, not both */\nsize_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,\n                    const void* dict, size_t dictSize, const ZSTD_CDict* cdict,\n                    const ZSTD_CCtx_params* params,\n                    unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_internal\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));\n    zcs->requestedParams = *params;\n    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */\n    if (dict) {\n        FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , \"\");\n    } else {\n        /* Dictionary is cleared if !cdict */\n        FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , \"\");\n    }\n    return 0;\n}\n\n/* ZSTD_initCStream_usingCDict_advanced() :\n * same as ZSTD_initCStream_usingCDict(), with control over frame parameters */\nsize_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,\n                                            const ZSTD_CDict* cdict,\n                                            ZSTD_frameParameters fParams,\n                                            unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_usingCDict_advanced\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    zcs->requestedParams.fParams = fParams;\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , \"\");\n    return 0;\n}\n\n/* note : cdict must outlive compression session */\nsize_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_usingCDict\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, cdict) , \"\");\n    return 0;\n}\n\n\n/* ZSTD_initCStream_advanced() :\n * pledgedSrcSize must be exact.\n * if srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.\n * dict is loaded with default parameters ZSTD_dct_auto and ZSTD_dlm_byCopy. */\nsize_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,\n                                 const void* dict, size_t dictSize,\n                                 ZSTD_parameters params, unsigned long long pss)\n{\n    /* for compatibility with older programs relying on this behavior.\n     * Users should now specify ZSTD_CONTENTSIZE_UNKNOWN.\n     * This line will be removed in the future.\n     */\n    U64 const pledgedSrcSize = (pss==0 && params.fParams.contentSizeFlag==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;\n    DEBUGLOG(4, \"ZSTD_initCStream_advanced\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , \"\");\n    ZSTD_CCtxParams_setZstdParams(&zcs->requestedParams, &params);\n    FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , \"\");\n    return 0;\n}\n\nsize_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream_usingDict\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_loadDictionary(zcs, dict, dictSize) , \"\");\n    return 0;\n}\n\nsize_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pss)\n{\n    /* temporary : 0 interpreted as \"unknown\" during transition period.\n     * Users willing to specify \"unknown\" **must** use ZSTD_CONTENTSIZE_UNKNOWN.\n     * 0 will be interpreted as \"empty\" in the future.\n     */\n    U64 const pledgedSrcSize = (pss==0) ? ZSTD_CONTENTSIZE_UNKNOWN : pss;\n    DEBUGLOG(4, \"ZSTD_initCStream_srcSize\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize) , \"\");\n    return 0;\n}\n\nsize_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel)\n{\n    DEBUGLOG(4, \"ZSTD_initCStream\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_refCDict(zcs, NULL) , \"\");\n    FORWARD_IF_ERROR( ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel) , \"\");\n    return 0;\n}\n\n/*======   Compression   ======*/\n\nstatic size_t ZSTD_nextInputSizeHint(const ZSTD_CCtx* cctx)\n{\n    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        return cctx->blockSizeMax - cctx->stableIn_notConsumed;\n    }\n    assert(cctx->appliedParams.inBufferMode == ZSTD_bm_buffered);\n    {   size_t hintInSize = cctx->inBuffTarget - cctx->inBuffPos;\n        if (hintInSize==0) hintInSize = cctx->blockSizeMax;\n        return hintInSize;\n    }\n}\n\n/** ZSTD_compressStream_generic():\n *  internal function for all *compressStream*() variants\n * @return : hint size for next input to complete ongoing block */\nstatic size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,\n                                          ZSTD_outBuffer* output,\n                                          ZSTD_inBuffer* input,\n                                          ZSTD_EndDirective const flushMode)\n{\n    const char* const istart = (assert(input != NULL), (const char*)input->src);\n    const char* const iend = (istart != NULL) ? istart + input->size : istart;\n    const char* ip = (istart != NULL) ? istart + input->pos : istart;\n    char* const ostart = (assert(output != NULL), (char*)output->dst);\n    char* const oend = (ostart != NULL) ? ostart + output->size : ostart;\n    char* op = (ostart != NULL) ? ostart + output->pos : ostart;\n    U32 someMoreWork = 1;\n\n    /* check expectations */\n    DEBUGLOG(5, \"ZSTD_compressStream_generic, flush=%i, srcSize = %zu\", (int)flushMode, input->size - input->pos);\n    assert(zcs != NULL);\n    if (zcs->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        assert(input->pos >= zcs->stableIn_notConsumed);\n        input->pos -= zcs->stableIn_notConsumed;\n        if (ip) ip -= zcs->stableIn_notConsumed;\n        zcs->stableIn_notConsumed = 0;\n    }\n    if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {\n        assert(zcs->inBuff != NULL);\n        assert(zcs->inBuffSize > 0);\n    }\n    if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) {\n        assert(zcs->outBuff !=  NULL);\n        assert(zcs->outBuffSize > 0);\n    }\n    if (input->src == NULL) assert(input->size == 0);\n    assert(input->pos <= input->size);\n    if (output->dst == NULL) assert(output->size == 0);\n    assert(output->pos <= output->size);\n    assert((U32)flushMode <= (U32)ZSTD_e_end);\n\n    while (someMoreWork) {\n        switch(zcs->streamStage)\n        {\n        case zcss_init:\n            RETURN_ERROR(init_missing, \"call ZSTD_initCStream() first!\");\n\n        case zcss_load:\n            if ( (flushMode == ZSTD_e_end)\n              && ( (size_t)(oend-op) >= ZSTD_compressBound((size_t)(iend-ip))     /* Enough output space */\n                || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)  /* OR we are allowed to return dstSizeTooSmall */\n              && (zcs->inBuffPos == 0) ) {\n                /* shortcut to compression pass directly into output buffer */\n                size_t const cSize = ZSTD_compressEnd_public(zcs,\n                                                op, (size_t)(oend-op),\n                                                ip, (size_t)(iend-ip));\n                DEBUGLOG(4, \"ZSTD_compressEnd : cSize=%u\", (unsigned)cSize);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressEnd failed\");\n                ip = iend;\n                op += cSize;\n                zcs->frameEnded = 1;\n                ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n                someMoreWork = 0; break;\n            }\n            /* complete loading into inBuffer in buffered mode */\n            if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) {\n                size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos;\n                size_t const loaded = ZSTD_limitCopy(\n                                        zcs->inBuff + zcs->inBuffPos, toLoad,\n                                        ip, (size_t)(iend-ip));\n                zcs->inBuffPos += loaded;\n                if (ip) ip += loaded;\n                if ( (flushMode == ZSTD_e_continue)\n                  && (zcs->inBuffPos < zcs->inBuffTarget) ) {\n                    /* not enough input to fill full block : stop here */\n                    someMoreWork = 0; break;\n                }\n                if ( (flushMode == ZSTD_e_flush)\n                  && (zcs->inBuffPos == zcs->inToCompress) ) {\n                    /* empty */\n                    someMoreWork = 0; break;\n                }\n            } else {\n                assert(zcs->appliedParams.inBufferMode == ZSTD_bm_stable);\n                if ( (flushMode == ZSTD_e_continue)\n                  && ( (size_t)(iend - ip) < zcs->blockSizeMax) ) {\n                    /* can't compress a full block : stop here */\n                    zcs->stableIn_notConsumed = (size_t)(iend - ip);\n                    ip = iend;  /* pretend to have consumed input */\n                    someMoreWork = 0; break;\n                }\n                if ( (flushMode == ZSTD_e_flush)\n                  && (ip == iend) ) {\n                    /* empty */\n                    someMoreWork = 0; break;\n                }\n            }\n            /* compress current block (note : this stage cannot be stopped in the middle) */\n            DEBUGLOG(5, \"stream compression stage (flushMode==%u)\", flushMode);\n            {   int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered);\n                void* cDst;\n                size_t cSize;\n                size_t oSize = (size_t)(oend-op);\n                size_t const iSize = inputBuffered ? zcs->inBuffPos - zcs->inToCompress\n                                                   : MIN((size_t)(iend - ip), zcs->blockSizeMax);\n                if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable)\n                    cDst = op;   /* compress into output buffer, to skip flush stage */\n                else\n                    cDst = zcs->outBuff, oSize = zcs->outBuffSize;\n                if (inputBuffered) {\n                    unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend);\n                    cSize = lastBlock ?\n                            ZSTD_compressEnd_public(zcs, cDst, oSize,\n                                        zcs->inBuff + zcs->inToCompress, iSize) :\n                            ZSTD_compressContinue_public(zcs, cDst, oSize,\n                                        zcs->inBuff + zcs->inToCompress, iSize);\n                    FORWARD_IF_ERROR(cSize, \"%s\", lastBlock ? \"ZSTD_compressEnd failed\" : \"ZSTD_compressContinue failed\");\n                    zcs->frameEnded = lastBlock;\n                    /* prepare next block */\n                    zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSizeMax;\n                    if (zcs->inBuffTarget > zcs->inBuffSize)\n                        zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSizeMax;\n                    DEBUGLOG(5, \"inBuffTarget:%u / inBuffSize:%u\",\n                            (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize);\n                    if (!lastBlock)\n                        assert(zcs->inBuffTarget <= zcs->inBuffSize);\n                    zcs->inToCompress = zcs->inBuffPos;\n                } else { /* !inputBuffered, hence ZSTD_bm_stable */\n                    unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip + iSize == iend);\n                    cSize = lastBlock ?\n                            ZSTD_compressEnd_public(zcs, cDst, oSize, ip, iSize) :\n                            ZSTD_compressContinue_public(zcs, cDst, oSize, ip, iSize);\n                    /* Consume the input prior to error checking to mirror buffered mode. */\n                    if (ip) ip += iSize;\n                    FORWARD_IF_ERROR(cSize, \"%s\", lastBlock ? \"ZSTD_compressEnd failed\" : \"ZSTD_compressContinue failed\");\n                    zcs->frameEnded = lastBlock;\n                    if (lastBlock) assert(ip == iend);\n                }\n                if (cDst == op) {  /* no need to flush */\n                    op += cSize;\n                    if (zcs->frameEnded) {\n                        DEBUGLOG(5, \"Frame completed directly in outBuffer\");\n                        someMoreWork = 0;\n                        ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n                    }\n                    break;\n                }\n                zcs->outBuffContentSize = cSize;\n                zcs->outBuffFlushedSize = 0;\n                zcs->streamStage = zcss_flush; /* pass-through to flush stage */\n            }\n\t    ZSTD_FALLTHROUGH;\n        case zcss_flush:\n            DEBUGLOG(5, \"flush stage\");\n            assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered);\n            {   size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize;\n                size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op),\n                            zcs->outBuff + zcs->outBuffFlushedSize, toFlush);\n                DEBUGLOG(5, \"toFlush: %u into %u ==> flushed: %u\",\n                            (unsigned)toFlush, (unsigned)(oend-op), (unsigned)flushed);\n                if (flushed)\n                    op += flushed;\n                zcs->outBuffFlushedSize += flushed;\n                if (toFlush!=flushed) {\n                    /* flush not fully completed, presumably because dst is too small */\n                    assert(op==oend);\n                    someMoreWork = 0;\n                    break;\n                }\n                zcs->outBuffContentSize = zcs->outBuffFlushedSize = 0;\n                if (zcs->frameEnded) {\n                    DEBUGLOG(5, \"Frame completed on flush\");\n                    someMoreWork = 0;\n                    ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n                    break;\n                }\n                zcs->streamStage = zcss_load;\n                break;\n            }\n\n        default: /* impossible */\n            assert(0);\n        }\n    }\n\n    input->pos = (size_t)(ip - istart);\n    output->pos = (size_t)(op - ostart);\n    if (zcs->frameEnded) return 0;\n    return ZSTD_nextInputSizeHint(zcs);\n}\n\nstatic size_t ZSTD_nextInputSizeHint_MTorST(const ZSTD_CCtx* cctx)\n{\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers >= 1) {\n        assert(cctx->mtctx != NULL);\n        return ZSTDMT_nextInputSizeHint(cctx->mtctx);\n    }\n#endif\n    return ZSTD_nextInputSizeHint(cctx);\n\n}\n\nsize_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input)\n{\n    FORWARD_IF_ERROR( ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue) , \"\");\n    return ZSTD_nextInputSizeHint_MTorST(zcs);\n}\n\n/* After a compression call set the expected input/output buffer.\n * This is validated at the start of the next compression call.\n */\nstatic void\nZSTD_setBufferExpectations(ZSTD_CCtx* cctx, const ZSTD_outBuffer* output, const ZSTD_inBuffer* input)\n{\n    DEBUGLOG(5, \"ZSTD_setBufferExpectations (for advanced stable in/out modes)\");\n    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        cctx->expectedInBuffer = *input;\n    }\n    if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {\n        cctx->expectedOutBufferSize = output->size - output->pos;\n    }\n}\n\n/* Validate that the input/output buffers match the expectations set by\n * ZSTD_setBufferExpectations.\n */\nstatic size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx,\n                                        ZSTD_outBuffer const* output,\n                                        ZSTD_inBuffer const* input,\n                                        ZSTD_EndDirective endOp)\n{\n    if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) {\n        ZSTD_inBuffer const expect = cctx->expectedInBuffer;\n        if (expect.src != input->src || expect.pos != input->pos)\n            RETURN_ERROR(stabilityCondition_notRespected, \"ZSTD_c_stableInBuffer enabled but input differs!\");\n    }\n    (void)endOp;\n    if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) {\n        size_t const outBufferSize = output->size - output->pos;\n        if (cctx->expectedOutBufferSize != outBufferSize)\n            RETURN_ERROR(stabilityCondition_notRespected, \"ZSTD_c_stableOutBuffer enabled but output size differs!\");\n    }\n    return 0;\n}\n\n/*\n * If @endOp == ZSTD_e_end, @inSize becomes pledgedSrcSize.\n * Otherwise, it's ignored.\n * @return: 0 on success, or a ZSTD_error code otherwise.\n */\nstatic size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,\n                                             ZSTD_EndDirective endOp,\n                                             size_t inSize)\n{\n    ZSTD_CCtx_params params = cctx->requestedParams;\n    ZSTD_prefixDict const prefixDict = cctx->prefixDict;\n    FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , \"\"); /* Init the local dict if present. */\n    ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict));   /* single usage */\n    assert(prefixDict.dict==NULL || cctx->cdict==NULL);    /* only one can be set */\n    if (cctx->cdict && !cctx->localDict.cdict) {\n        /* Let the cdict's compression level take priority over the requested params.\n         * But do not take the cdict's compression level if the \"cdict\" is actually a localDict\n         * generated from ZSTD_initLocalDict().\n         */\n        params.compressionLevel = cctx->cdict->compressionLevel;\n    }\n    DEBUGLOG(4, \"ZSTD_CCtx_init_compressStream2 : transparent init stage\");\n    if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1;  /* auto-determine pledgedSrcSize */\n\n    {   size_t const dictSize = prefixDict.dict\n                ? prefixDict.dictSize\n                : (cctx->cdict ? cctx->cdict->dictContentSize : 0);\n        ZSTD_CParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, &params, cctx->pledgedSrcSizePlusOne - 1);\n        params.cParams = ZSTD_getCParamsFromCCtxParams(\n                &params, cctx->pledgedSrcSizePlusOne-1,\n                dictSize, mode);\n    }\n\n    params.postBlockSplitter = ZSTD_resolveBlockSplitterMode(params.postBlockSplitter, &params.cParams);\n    params.ldmParams.enableLdm = ZSTD_resolveEnableLdm(params.ldmParams.enableLdm, &params.cParams);\n    params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, &params.cParams);\n    params.validateSequences = ZSTD_resolveExternalSequenceValidation(params.validateSequences);\n    params.maxBlockSize = ZSTD_resolveMaxBlockSize(params.maxBlockSize);\n    params.searchForExternalRepcodes = ZSTD_resolveExternalRepcodeSearch(params.searchForExternalRepcodes, params.compressionLevel);\n\n#ifdef ZSTD_MULTITHREAD\n    /* If external matchfinder is enabled, make sure to fail before checking job size (for consistency) */\n    RETURN_ERROR_IF(\n        ZSTD_hasExtSeqProd(&params) && params.nbWorkers >= 1,\n        parameter_combination_unsupported,\n        \"External sequence producer isn't supported with nbWorkers >= 1\"\n    );\n\n    if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) {\n        params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */\n    }\n    if (params.nbWorkers > 0) {\n# if ZSTD_TRACE\n        cctx->traceCtx = (ZSTD_trace_compress_begin != NULL) ? ZSTD_trace_compress_begin(cctx) : 0;\n# endif\n        /* mt context creation */\n        if (cctx->mtctx == NULL) {\n            DEBUGLOG(4, \"ZSTD_compressStream2: creating new mtctx for nbWorkers=%u\",\n                        params.nbWorkers);\n            cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem, cctx->pool);\n            RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, \"NULL pointer!\");\n        }\n        /* mt compression */\n        DEBUGLOG(4, \"call ZSTDMT_initCStream_internal as nbWorkers=%u\", params.nbWorkers);\n        FORWARD_IF_ERROR( ZSTDMT_initCStream_internal(\n                    cctx->mtctx,\n                    prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType,\n                    cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , \"\");\n        cctx->dictID = cctx->cdict ? cctx->cdict->dictID : 0;\n        cctx->dictContentSize = cctx->cdict ? cctx->cdict->dictContentSize : prefixDict.dictSize;\n        cctx->consumedSrcSize = 0;\n        cctx->producedCSize = 0;\n        cctx->streamStage = zcss_load;\n        cctx->appliedParams = params;\n    } else\n#endif  /* ZSTD_MULTITHREAD */\n    {   U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1;\n        assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));\n        FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx,\n                prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast,\n                cctx->cdict,\n                &params, pledgedSrcSize,\n                ZSTDb_buffered) , \"\");\n        assert(cctx->appliedParams.nbWorkers == 0);\n        cctx->inToCompress = 0;\n        cctx->inBuffPos = 0;\n        if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) {\n            /* for small input: avoid automatic flush on reaching end of block, since\n            * it would require to add a 3-bytes null block to end frame\n            */\n            cctx->inBuffTarget = cctx->blockSizeMax + (cctx->blockSizeMax == pledgedSrcSize);\n        } else {\n            cctx->inBuffTarget = 0;\n        }\n        cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0;\n        cctx->streamStage = zcss_load;\n        cctx->frameEnded = 0;\n    }\n    return 0;\n}\n\n/* @return provides a minimum amount of data remaining to be flushed from internal buffers\n */\nsize_t ZSTD_compressStream2( ZSTD_CCtx* cctx,\n                             ZSTD_outBuffer* output,\n                             ZSTD_inBuffer* input,\n                             ZSTD_EndDirective endOp)\n{\n    DEBUGLOG(5, \"ZSTD_compressStream2, endOp=%u \", (unsigned)endOp);\n    /* check conditions */\n    RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, \"invalid output buffer\");\n    RETURN_ERROR_IF(input->pos  > input->size, srcSize_wrong, \"invalid input buffer\");\n    RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, \"invalid endDirective\");\n    assert(cctx != NULL);\n\n    /* transparent initialization stage */\n    if (cctx->streamStage == zcss_init) {\n        size_t const inputSize = input->size - input->pos;  /* no obligation to start from pos==0 */\n        size_t const totalInputSize = inputSize + cctx->stableIn_notConsumed;\n        if ( (cctx->requestedParams.inBufferMode == ZSTD_bm_stable) /* input is presumed stable, across invocations */\n          && (endOp == ZSTD_e_continue)                             /* no flush requested, more input to come */\n          && (totalInputSize < ZSTD_BLOCKSIZE_MAX) ) {              /* not even reached one block yet */\n            if (cctx->stableIn_notConsumed) {  /* not the first time */\n                /* check stable source guarantees */\n                RETURN_ERROR_IF(input->src != cctx->expectedInBuffer.src, stabilityCondition_notRespected, \"stableInBuffer condition not respected: wrong src pointer\");\n                RETURN_ERROR_IF(input->pos != cctx->expectedInBuffer.size, stabilityCondition_notRespected, \"stableInBuffer condition not respected: externally modified pos\");\n            }\n            /* pretend input was consumed, to give a sense forward progress */\n            input->pos = input->size;\n            /* save stable inBuffer, for later control, and flush/end */\n            cctx->expectedInBuffer = *input;\n            /* but actually input wasn't consumed, so keep track of position from where compression shall resume */\n            cctx->stableIn_notConsumed += inputSize;\n            /* don't initialize yet, wait for the first block of flush() order, for better parameters adaptation */\n            return ZSTD_FRAMEHEADERSIZE_MIN(cctx->requestedParams.format);  /* at least some header to produce */\n        }\n        FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, totalInputSize), \"compressStream2 initialization failed\");\n        ZSTD_setBufferExpectations(cctx, output, input);   /* Set initial buffer expectations now that we've initialized */\n    }\n    /* end of transparent initialization stage */\n\n    FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), \"invalid buffers\");\n    /* compression stage */\n#ifdef ZSTD_MULTITHREAD\n    if (cctx->appliedParams.nbWorkers > 0) {\n        size_t flushMin;\n        if (cctx->cParamsChanged) {\n            ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams);\n            cctx->cParamsChanged = 0;\n        }\n        if (cctx->stableIn_notConsumed) {\n            assert(cctx->appliedParams.inBufferMode == ZSTD_bm_stable);\n            /* some early data was skipped - make it available for consumption */\n            assert(input->pos >= cctx->stableIn_notConsumed);\n            input->pos -= cctx->stableIn_notConsumed;\n            cctx->stableIn_notConsumed = 0;\n        }\n        for (;;) {\n            size_t const ipos = input->pos;\n            size_t const opos = output->pos;\n            flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp);\n            cctx->consumedSrcSize += (U64)(input->pos - ipos);\n            cctx->producedCSize += (U64)(output->pos - opos);\n            if ( ZSTD_isError(flushMin)\n              || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */\n                if (flushMin == 0)\n                    ZSTD_CCtx_trace(cctx, 0);\n                ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n            }\n            FORWARD_IF_ERROR(flushMin, \"ZSTDMT_compressStream_generic failed\");\n\n            if (endOp == ZSTD_e_continue) {\n                /* We only require some progress with ZSTD_e_continue, not maximal progress.\n                 * We're done if we've consumed or produced any bytes, or either buffer is\n                 * full.\n                 */\n                if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size)\n                    break;\n            } else {\n                assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end);\n                /* We require maximal progress. We're done when the flush is complete or the\n                 * output buffer is full.\n                 */\n                if (flushMin == 0 || output->pos == output->size)\n                    break;\n            }\n        }\n        DEBUGLOG(5, \"completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic\");\n        /* Either we don't require maximum forward progress, we've finished the\n         * flush, or we are out of output space.\n         */\n        assert(endOp == ZSTD_e_continue || flushMin == 0 || output->pos == output->size);\n        ZSTD_setBufferExpectations(cctx, output, input);\n        return flushMin;\n    }\n#endif /* ZSTD_MULTITHREAD */\n    FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , \"\");\n    DEBUGLOG(5, \"completed ZSTD_compressStream2\");\n    ZSTD_setBufferExpectations(cctx, output, input);\n    return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */\n}\n\nsize_t ZSTD_compressStream2_simpleArgs (\n                            ZSTD_CCtx* cctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos,\n                            ZSTD_EndDirective endOp)\n{\n    ZSTD_outBuffer output;\n    ZSTD_inBuffer  input;\n    output.dst = dst;\n    output.size = dstCapacity;\n    output.pos = *dstPos;\n    input.src = src;\n    input.size = srcSize;\n    input.pos = *srcPos;\n    /* ZSTD_compressStream2() will check validity of dstPos and srcPos */\n    {   size_t const cErr = ZSTD_compressStream2(cctx, &output, &input, endOp);\n        *dstPos = output.pos;\n        *srcPos = input.pos;\n        return cErr;\n    }\n}\n\nsize_t ZSTD_compress2(ZSTD_CCtx* cctx,\n                      void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode;\n    ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode;\n    DEBUGLOG(4, \"ZSTD_compress2 (srcSize=%u)\", (unsigned)srcSize);\n    ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only);\n    /* Enable stable input/output buffers. */\n    cctx->requestedParams.inBufferMode = ZSTD_bm_stable;\n    cctx->requestedParams.outBufferMode = ZSTD_bm_stable;\n    {   size_t oPos = 0;\n        size_t iPos = 0;\n        size_t const result = ZSTD_compressStream2_simpleArgs(cctx,\n                                        dst, dstCapacity, &oPos,\n                                        src, srcSize, &iPos,\n                                        ZSTD_e_end);\n        /* Reset to the original values. */\n        cctx->requestedParams.inBufferMode = originalInBufferMode;\n        cctx->requestedParams.outBufferMode = originalOutBufferMode;\n\n        FORWARD_IF_ERROR(result, \"ZSTD_compressStream2_simpleArgs failed\");\n        if (result != 0) {  /* compression not completed, due to lack of output space */\n            assert(oPos == dstCapacity);\n            RETURN_ERROR(dstSize_tooSmall, \"\");\n        }\n        assert(iPos == srcSize);   /* all input is expected consumed */\n        return oPos;\n    }\n}\n\n/* ZSTD_validateSequence() :\n * @offBase : must use the format required by ZSTD_storeSeq()\n * @returns a ZSTD error code if sequence is not valid\n */\nstatic size_t\nZSTD_validateSequence(U32 offBase, U32 matchLength, U32 minMatch,\n                      size_t posInSrc, U32 windowLog, size_t dictSize, int useSequenceProducer)\n{\n    U32 const windowSize = 1u << windowLog;\n    /* posInSrc represents the amount of data the decoder would decode up to this point.\n     * As long as the amount of data decoded is less than or equal to window size, offsets may be\n     * larger than the total length of output decoded in order to reference the dict, even larger than\n     * window size. After output surpasses windowSize, we're limited to windowSize offsets again.\n     */\n    size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;\n    size_t const matchLenLowerBound = (minMatch == 3 || useSequenceProducer) ? 3 : 4;\n    RETURN_ERROR_IF(offBase > OFFSET_TO_OFFBASE(offsetBound), externalSequences_invalid, \"Offset too large!\");\n    /* Validate maxNbSeq is large enough for the given matchLength and minMatch */\n    RETURN_ERROR_IF(matchLength < matchLenLowerBound, externalSequences_invalid, \"Matchlength too small for the minMatch\");\n    return 0;\n}\n\n/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */\nstatic U32 ZSTD_finalizeOffBase(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0)\n{\n    U32 offBase = OFFSET_TO_OFFBASE(rawOffset);\n\n    if (!ll0 && rawOffset == rep[0]) {\n        offBase = REPCODE1_TO_OFFBASE;\n    } else if (rawOffset == rep[1]) {\n        offBase = REPCODE_TO_OFFBASE(2 - ll0);\n    } else if (rawOffset == rep[2]) {\n        offBase = REPCODE_TO_OFFBASE(3 - ll0);\n    } else if (ll0 && rawOffset == rep[0] - 1) {\n        offBase = REPCODE3_TO_OFFBASE;\n    }\n    return offBase;\n}\n\n/* This function scans through an array of ZSTD_Sequence,\n * storing the sequences it reads, until it reaches a block delimiter.\n * Note that the block delimiter includes the last literals of the block.\n * @blockSize must be == sum(sequence_lengths).\n * @returns @blockSize on success, and a ZSTD_error otherwise.\n */\nstatic size_t\nZSTD_transferSequences_wBlockDelim(ZSTD_CCtx* cctx,\n                                   ZSTD_SequencePosition* seqPos,\n                             const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                             const void* src, size_t blockSize,\n                                   ZSTD_ParamSwitch_e externalRepSearch)\n{\n    U32 idx = seqPos->idx;\n    U32 const startIdx = idx;\n    BYTE const* ip = (BYTE const*)(src);\n    const BYTE* const iend = ip + blockSize;\n    Repcodes_t updatedRepcodes;\n    U32 dictSize;\n\n    DEBUGLOG(5, \"ZSTD_transferSequences_wBlockDelim (blockSize = %zu)\", blockSize);\n\n    if (cctx->cdict) {\n        dictSize = (U32)cctx->cdict->dictContentSize;\n    } else if (cctx->prefixDict.dict) {\n        dictSize = (U32)cctx->prefixDict.dictSize;\n    } else {\n        dictSize = 0;\n    }\n    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    for (; idx < inSeqsSize && (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0); ++idx) {\n        U32 const litLength = inSeqs[idx].litLength;\n        U32 const matchLength = inSeqs[idx].matchLength;\n        U32 offBase;\n\n        if (externalRepSearch == ZSTD_ps_disable) {\n            offBase = OFFSET_TO_OFFBASE(inSeqs[idx].offset);\n        } else {\n            U32 const ll0 = (litLength == 0);\n            offBase = ZSTD_finalizeOffBase(inSeqs[idx].offset, updatedRepcodes.rep, ll0);\n            ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);\n        }\n\n        DEBUGLOG(6, \"Storing sequence: (of: %u, ml: %u, ll: %u)\", offBase, matchLength, litLength);\n        if (cctx->appliedParams.validateSequences) {\n            seqPos->posInSrc += litLength + matchLength;\n            FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch,\n                                                seqPos->posInSrc,\n                                                cctx->appliedParams.cParams.windowLog, dictSize,\n                                                ZSTD_hasExtSeqProd(&cctx->appliedParams)),\n                                                \"Sequence validation failed\");\n        }\n        RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,\n                        \"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.\");\n        ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength);\n        ip += matchLength + litLength;\n    }\n    RETURN_ERROR_IF(idx == inSeqsSize, externalSequences_invalid, \"Block delimiter not found.\");\n\n    /* If we skipped repcode search while parsing, we need to update repcodes now */\n    assert(externalRepSearch != ZSTD_ps_auto);\n    assert(idx >= startIdx);\n    if (externalRepSearch == ZSTD_ps_disable && idx != startIdx) {\n        U32* const rep = updatedRepcodes.rep;\n        U32 lastSeqIdx = idx - 1; /* index of last non-block-delimiter sequence */\n\n        if (lastSeqIdx >= startIdx + 2) {\n            rep[2] = inSeqs[lastSeqIdx - 2].offset;\n            rep[1] = inSeqs[lastSeqIdx - 1].offset;\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        } else if (lastSeqIdx == startIdx + 1) {\n            rep[2] = rep[0];\n            rep[1] = inSeqs[lastSeqIdx - 1].offset;\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        } else {\n            assert(lastSeqIdx == startIdx);\n            rep[2] = rep[1];\n            rep[1] = rep[0];\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        }\n    }\n\n    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t));\n\n    if (inSeqs[idx].litLength) {\n        DEBUGLOG(6, \"Storing last literals of size: %u\", inSeqs[idx].litLength);\n        ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength);\n        ip += inSeqs[idx].litLength;\n        seqPos->posInSrc += inSeqs[idx].litLength;\n    }\n    RETURN_ERROR_IF(ip != iend, externalSequences_invalid, \"Blocksize doesn't agree with block delimiter!\");\n    seqPos->idx = idx+1;\n    return blockSize;\n}\n\n/*\n * This function attempts to scan through @blockSize bytes in @src\n * represented by the sequences in @inSeqs,\n * storing any (partial) sequences.\n *\n * Occasionally, we may want to reduce the actual number of bytes consumed from @src\n * to avoid splitting a match, notably if it would produce a match smaller than MINMATCH.\n *\n * @returns the number of bytes consumed from @src, necessarily <= @blockSize.\n * Otherwise, it may return a ZSTD error if something went wrong.\n */\nstatic size_t\nZSTD_transferSequences_noDelim(ZSTD_CCtx* cctx,\n                               ZSTD_SequencePosition* seqPos,\n                         const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                         const void* src, size_t blockSize,\n                               ZSTD_ParamSwitch_e externalRepSearch)\n{\n    U32 idx = seqPos->idx;\n    U32 startPosInSequence = seqPos->posInSequence;\n    U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;\n    size_t dictSize;\n    const BYTE* const istart = (const BYTE*)(src);\n    const BYTE* ip = istart;\n    const BYTE* iend = istart + blockSize;  /* May be adjusted if we decide to process fewer than blockSize bytes */\n    Repcodes_t updatedRepcodes;\n    U32 bytesAdjustment = 0;\n    U32 finalMatchSplit = 0;\n\n    /* TODO(embg) support fast parsing mode in noBlockDelim mode */\n    (void)externalRepSearch;\n\n    if (cctx->cdict) {\n        dictSize = cctx->cdict->dictContentSize;\n    } else if (cctx->prefixDict.dict) {\n        dictSize = cctx->prefixDict.dictSize;\n    } else {\n        dictSize = 0;\n    }\n    DEBUGLOG(5, \"ZSTD_transferSequences_noDelim: idx: %u PIS: %u blockSize: %zu\", idx, startPosInSequence, blockSize);\n    DEBUGLOG(5, \"Start seq: idx: %u (of: %u ml: %u ll: %u)\", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);\n    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n    while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {\n        const ZSTD_Sequence currSeq = inSeqs[idx];\n        U32 litLength = currSeq.litLength;\n        U32 matchLength = currSeq.matchLength;\n        U32 const rawOffset = currSeq.offset;\n        U32 offBase;\n\n        /* Modify the sequence depending on where endPosInSequence lies */\n        if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {\n            if (startPosInSequence >= litLength) {\n                startPosInSequence -= litLength;\n                litLength = 0;\n                matchLength -= startPosInSequence;\n            } else {\n                litLength -= startPosInSequence;\n            }\n            /* Move to the next sequence */\n            endPosInSequence -= currSeq.litLength + currSeq.matchLength;\n            startPosInSequence = 0;\n        } else {\n            /* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence\n               does not reach the end of the match. So, we have to split the sequence */\n            DEBUGLOG(6, \"Require a split: diff: %u, idx: %u PIS: %u\",\n                     currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence);\n            if (endPosInSequence > litLength) {\n                U32 firstHalfMatchLength;\n                litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence;\n                firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength;\n                if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) {\n                    /* Only ever split the match if it is larger than the block size */\n                    U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence;\n                    if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) {\n                        /* Move the endPosInSequence backward so that it creates match of minMatch length */\n                        endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;\n                        bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength;\n                        firstHalfMatchLength -= bytesAdjustment;\n                    }\n                    matchLength = firstHalfMatchLength;\n                    /* Flag that we split the last match - after storing the sequence, exit the loop,\n                       but keep the value of endPosInSequence */\n                    finalMatchSplit = 1;\n                } else {\n                    /* Move the position in sequence backwards so that we don't split match, and break to store\n                     * the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence\n                     * should go. We prefer to do this whenever it is not necessary to split the match, or if doing so\n                     * would cause the first half of the match to be too small\n                     */\n                    bytesAdjustment = endPosInSequence - currSeq.litLength;\n                    endPosInSequence = currSeq.litLength;\n                    break;\n                }\n            } else {\n                /* This sequence ends inside the literals, break to store the last literals */\n                break;\n            }\n        }\n        /* Check if this offset can be represented with a repcode */\n        {   U32 const ll0 = (litLength == 0);\n            offBase = ZSTD_finalizeOffBase(rawOffset, updatedRepcodes.rep, ll0);\n            ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);\n        }\n\n        if (cctx->appliedParams.validateSequences) {\n            seqPos->posInSrc += litLength + matchLength;\n            FORWARD_IF_ERROR(ZSTD_validateSequence(offBase, matchLength, cctx->appliedParams.cParams.minMatch, seqPos->posInSrc,\n                                                   cctx->appliedParams.cParams.windowLog, dictSize, ZSTD_hasExtSeqProd(&cctx->appliedParams)),\n                                                   \"Sequence validation failed\");\n        }\n        DEBUGLOG(6, \"Storing sequence: (of: %u, ml: %u, ll: %u)\", offBase, matchLength, litLength);\n        RETURN_ERROR_IF(idx - seqPos->idx >= cctx->seqStore.maxNbSeq, externalSequences_invalid,\n                        \"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.\");\n        ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offBase, matchLength);\n        ip += matchLength + litLength;\n        if (!finalMatchSplit)\n            idx++; /* Next Sequence */\n    }\n    DEBUGLOG(5, \"Ending seq: idx: %u (of: %u ml: %u ll: %u)\", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);\n    assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength);\n    seqPos->idx = idx;\n    seqPos->posInSequence = endPosInSequence;\n    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t));\n\n    iend -= bytesAdjustment;\n    if (ip != iend) {\n        /* Store any last literals */\n        U32 const lastLLSize = (U32)(iend - ip);\n        assert(ip <= iend);\n        DEBUGLOG(6, \"Storing last literals of size: %u\", lastLLSize);\n        ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize);\n        seqPos->posInSrc += lastLLSize;\n    }\n\n    return (size_t)(iend-istart);\n}\n\n/* @seqPos represents a position within @inSeqs,\n * it is read and updated by this function,\n * once the goal to produce a block of size @blockSize is reached.\n * @return: nb of bytes consumed from @src, necessarily <= @blockSize.\n */\ntypedef size_t (*ZSTD_SequenceCopier_f)(ZSTD_CCtx* cctx,\n                                        ZSTD_SequencePosition* seqPos,\n                                  const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,\n                                  const void* src, size_t blockSize,\n                                        ZSTD_ParamSwitch_e externalRepSearch);\n\nstatic ZSTD_SequenceCopier_f ZSTD_selectSequenceCopier(ZSTD_SequenceFormat_e mode)\n{\n    assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, (int)mode));\n    if (mode == ZSTD_sf_explicitBlockDelimiters) {\n        return ZSTD_transferSequences_wBlockDelim;\n    }\n    assert(mode == ZSTD_sf_noBlockDelimiters);\n    return ZSTD_transferSequences_noDelim;\n}\n\n/* Discover the size of next block by searching for the delimiter.\n * Note that a block delimiter **must** exist in this mode,\n * otherwise it's an input error.\n * The block size retrieved will be later compared to ensure it remains within bounds */\nstatic size_t\nblockSize_explicitDelimiter(const ZSTD_Sequence* inSeqs, size_t inSeqsSize, ZSTD_SequencePosition seqPos)\n{\n    int end = 0;\n    size_t blockSize = 0;\n    size_t spos = seqPos.idx;\n    DEBUGLOG(6, \"blockSize_explicitDelimiter : seq %zu / %zu\", spos, inSeqsSize);\n    assert(spos <= inSeqsSize);\n    while (spos < inSeqsSize) {\n        end = (inSeqs[spos].offset == 0);\n        blockSize += inSeqs[spos].litLength + inSeqs[spos].matchLength;\n        if (end) {\n            if (inSeqs[spos].matchLength != 0)\n                RETURN_ERROR(externalSequences_invalid, \"delimiter format error : both matchlength and offset must be == 0\");\n            break;\n        }\n        spos++;\n    }\n    if (!end)\n        RETURN_ERROR(externalSequences_invalid, \"Reached end of sequences without finding a block delimiter\");\n    return blockSize;\n}\n\nstatic size_t determine_blockSize(ZSTD_SequenceFormat_e mode,\n                           size_t blockSize, size_t remaining,\n                     const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                           ZSTD_SequencePosition seqPos)\n{\n    DEBUGLOG(6, \"determine_blockSize : remainingSize = %zu\", remaining);\n    if (mode == ZSTD_sf_noBlockDelimiters) {\n        /* Note: more a \"target\" block size */\n        return MIN(remaining, blockSize);\n    }\n    assert(mode == ZSTD_sf_explicitBlockDelimiters);\n    {   size_t const explicitBlockSize = blockSize_explicitDelimiter(inSeqs, inSeqsSize, seqPos);\n        FORWARD_IF_ERROR(explicitBlockSize, \"Error while determining block size with explicit delimiters\");\n        if (explicitBlockSize > blockSize)\n            RETURN_ERROR(externalSequences_invalid, \"sequences incorrectly define a too large block\");\n        if (explicitBlockSize > remaining)\n            RETURN_ERROR(externalSequences_invalid, \"sequences define a frame longer than source\");\n        return explicitBlockSize;\n    }\n}\n\n/* Compress all provided sequences, block-by-block.\n *\n * Returns the cumulative size of all compressed blocks (including their headers),\n * otherwise a ZSTD error.\n */\nstatic size_t\nZSTD_compressSequences_internal(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                          const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                          const void* src, size_t srcSize)\n{\n    size_t cSize = 0;\n    size_t remaining = srcSize;\n    ZSTD_SequencePosition seqPos = {0, 0, 0};\n\n    const BYTE* ip = (BYTE const*)src;\n    BYTE* op = (BYTE*)dst;\n    ZSTD_SequenceCopier_f const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);\n\n    DEBUGLOG(4, \"ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu\", srcSize, inSeqsSize);\n    /* Special case: empty frame */\n    if (remaining == 0) {\n        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1);\n        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, \"No room for empty frame block header\");\n        MEM_writeLE32(op, cBlockHeader24);\n        op += ZSTD_blockHeaderSize;\n        dstCapacity -= ZSTD_blockHeaderSize;\n        cSize += ZSTD_blockHeaderSize;\n    }\n\n    while (remaining) {\n        size_t compressedSeqsSize;\n        size_t cBlockSize;\n        size_t blockSize = determine_blockSize(cctx->appliedParams.blockDelimiters,\n                                        cctx->blockSizeMax, remaining,\n                                        inSeqs, inSeqsSize, seqPos);\n        U32 const lastBlock = (blockSize == remaining);\n        FORWARD_IF_ERROR(blockSize, \"Error while trying to determine block size\");\n        assert(blockSize <= remaining);\n        ZSTD_resetSeqStore(&cctx->seqStore);\n\n        blockSize = sequenceCopier(cctx,\n                                   &seqPos, inSeqs, inSeqsSize,\n                                   ip, blockSize,\n                                   cctx->appliedParams.searchForExternalRepcodes);\n        FORWARD_IF_ERROR(blockSize, \"Bad sequence copy\");\n\n        /* If blocks are too small, emit as a nocompress block */\n        /* TODO: See 3090. We reduced MIN_CBLOCK_SIZE from 3 to 2 so to compensate we are adding\n         * additional 1. We need to revisit and change this logic to be more consistent */\n        if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1+1) {\n            cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);\n            FORWARD_IF_ERROR(cBlockSize, \"Nocompress block failed\");\n            DEBUGLOG(5, \"Block too small (%zu): data remains uncompressed: cSize=%zu\", blockSize, cBlockSize);\n            cSize += cBlockSize;\n            ip += blockSize;\n            op += cBlockSize;\n            remaining -= blockSize;\n            dstCapacity -= cBlockSize;\n            continue;\n        }\n\n        RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, \"not enough dstCapacity to write a new compressed block\");\n        compressedSeqsSize = ZSTD_entropyCompressSeqStore(&cctx->seqStore,\n                                &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,\n                                &cctx->appliedParams,\n                                op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize,\n                                blockSize,\n                                cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */,\n                                cctx->bmi2);\n        FORWARD_IF_ERROR(compressedSeqsSize, \"Compressing sequences of block failed\");\n        DEBUGLOG(5, \"Compressed sequences size: %zu\", compressedSeqsSize);\n\n        if (!cctx->isFirstBlock &&\n            ZSTD_maybeRLE(&cctx->seqStore) &&\n            ZSTD_isRLE(ip, blockSize)) {\n            /* Note: don't emit the first block as RLE even if it qualifies because\n             * doing so will cause the decoder (cli <= v1.4.3 only) to throw an (invalid) error\n             * \"should consume all input error.\"\n             */\n            compressedSeqsSize = 1;\n        }\n\n        if (compressedSeqsSize == 0) {\n            /* ZSTD_noCompressBlock writes the block header as well */\n            cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock);\n            FORWARD_IF_ERROR(cBlockSize, \"ZSTD_noCompressBlock failed\");\n            DEBUGLOG(5, \"Writing out nocompress block, size: %zu\", cBlockSize);\n        } else if (compressedSeqsSize == 1) {\n            cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock);\n            FORWARD_IF_ERROR(cBlockSize, \"ZSTD_rleCompressBlock failed\");\n            DEBUGLOG(5, \"Writing out RLE block, size: %zu\", cBlockSize);\n        } else {\n            U32 cBlockHeader;\n            /* Error checking and repcodes update */\n            ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState);\n            if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n                cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n            /* Write block header into beginning of block*/\n            cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);\n            MEM_writeLE24(op, cBlockHeader);\n            cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;\n            DEBUGLOG(5, \"Writing out compressed block, size: %zu\", cBlockSize);\n        }\n\n        cSize += cBlockSize;\n\n        if (lastBlock) {\n            break;\n        } else {\n            ip += blockSize;\n            op += cBlockSize;\n            remaining -= blockSize;\n            dstCapacity -= cBlockSize;\n            cctx->isFirstBlock = 0;\n        }\n        DEBUGLOG(5, \"cSize running total: %zu (remaining dstCapacity=%zu)\", cSize, dstCapacity);\n    }\n\n    DEBUGLOG(4, \"cSize final total: %zu\", cSize);\n    return cSize;\n}\n\nsize_t ZSTD_compressSequences(ZSTD_CCtx* cctx,\n                              void* dst, size_t dstCapacity,\n                              const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                              const void* src, size_t srcSize)\n{\n    BYTE* op = (BYTE*)dst;\n    size_t cSize = 0;\n\n    /* Transparent initialization stage, same as compressStream2() */\n    DEBUGLOG(4, \"ZSTD_compressSequences (nbSeqs=%zu,dstCapacity=%zu)\", inSeqsSize, dstCapacity);\n    assert(cctx != NULL);\n    FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), \"CCtx initialization failed\");\n\n    /* Begin writing output, starting with frame header */\n    {   size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity,\n                    &cctx->appliedParams, srcSize, cctx->dictID);\n        op += frameHeaderSize;\n        assert(frameHeaderSize <= dstCapacity);\n        dstCapacity -= frameHeaderSize;\n        cSize += frameHeaderSize;\n    }\n    if (cctx->appliedParams.fParams.checksumFlag && srcSize) {\n        XXH64_update(&cctx->xxhState, src, srcSize);\n    }\n\n    /* Now generate compressed blocks */\n    {   size_t const cBlocksSize = ZSTD_compressSequences_internal(cctx,\n                                                           op, dstCapacity,\n                                                           inSeqs, inSeqsSize,\n                                                           src, srcSize);\n        FORWARD_IF_ERROR(cBlocksSize, \"Compressing blocks failed!\");\n        cSize += cBlocksSize;\n        assert(cBlocksSize <= dstCapacity);\n        dstCapacity -= cBlocksSize;\n    }\n\n    /* Complete with frame checksum, if needed */\n    if (cctx->appliedParams.fParams.checksumFlag) {\n        U32 const checksum = (U32) XXH64_digest(&cctx->xxhState);\n        RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, \"no room for checksum\");\n        DEBUGLOG(4, \"Write checksum : %08X\", (unsigned)checksum);\n        MEM_writeLE32((char*)dst + cSize, checksum);\n        cSize += 4;\n    }\n\n    DEBUGLOG(4, \"Final compressed size: %zu\", cSize);\n    return cSize;\n}\n\n\n#if defined(__AVX2__)\n\n#include <immintrin.h>  /* AVX2 intrinsics */\n\n/*\n * Convert 2 sequences per iteration, using AVX2 intrinsics:\n *   - offset -> offBase = offset + 2\n *   - litLength -> (U16) litLength\n *   - matchLength -> (U16)(matchLength - 3)\n *   - rep is ignored\n * Store only 8 bytes per SeqDef (offBase[4], litLength[2], mlBase[2]).\n *\n * At the end, instead of extracting two __m128i,\n * we use _mm256_permute4x64_epi64(..., 0xE8) to move lane2 into lane1,\n * then store the lower 16 bytes in one go.\n *\n * @returns 0 on succes, with no long length detected\n * @returns > 0 if there is one long length (> 65535),\n * indicating the position, and type.\n */\nstatic size_t convertSequences_noRepcodes(\n    SeqDef* dstSeqs,\n    const ZSTD_Sequence* inSeqs,\n    size_t nbSequences)\n{\n    /*\n     * addition:\n     *   For each 128-bit half: (offset+2, litLength+0, matchLength-3, rep+0)\n     */\n    const __m256i addition = _mm256_setr_epi32(\n        ZSTD_REP_NUM, 0, -MINMATCH, 0,    /* for sequence i */\n        ZSTD_REP_NUM, 0, -MINMATCH, 0     /* for sequence i+1 */\n    );\n\n    /* limit: check if there is a long length */\n    const __m256i limit = _mm256_set1_epi32(65535);\n\n    /*\n     * shuffle mask for byte-level rearrangement in each 128-bit half:\n     *\n     * Input layout (after addition) per 128-bit half:\n     *   [ offset+2 (4 bytes) | litLength (4 bytes) | matchLength (4 bytes) | rep (4 bytes) ]\n     * We only need:\n     *   offBase (4 bytes) = offset+2\n     *   litLength (2 bytes) = low 2 bytes of litLength\n     *   mlBase (2 bytes) = low 2 bytes of (matchLength)\n     * => Bytes [0..3, 4..5, 8..9], zero the rest.\n     */\n    const __m256i mask = _mm256_setr_epi8(\n        /* For the lower 128 bits => sequence i */\n         0, 1, 2, 3,       /* offset+2 */\n         4, 5,             /* litLength (16 bits) */\n         8, 9,             /* matchLength (16 bits) */\n         (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80,\n         (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80,\n\n        /* For the upper 128 bits => sequence i+1 */\n        16,17,18,19,       /* offset+2 */\n        20,21,             /* litLength */\n        24,25,             /* matchLength */\n        (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80,\n        (BYTE)0x80, (BYTE)0x80, (BYTE)0x80, (BYTE)0x80\n    );\n\n    /*\n     * Next, we'll use _mm256_permute4x64_epi64(vshf, 0xE8).\n     * Explanation of 0xE8 = 11101000b => [lane0, lane2, lane2, lane3].\n     * So the lower 128 bits become [lane0, lane2] => combining seq0 and seq1.\n     */\n#define PERM_LANE_0X_E8 0xE8  /* [0,2,2,3] in lane indices */\n\n    size_t longLen = 0, i = 0;\n\n    /* AVX permutation depends on the specific definition of target structures */\n    ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, offset) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);\n    ZSTD_STATIC_ASSERT(sizeof(SeqDef) == 8);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, offBase) == 0);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, litLength) == 4);\n    ZSTD_STATIC_ASSERT(offsetof(SeqDef, mlBase) == 6);\n\n    /* Process 2 sequences per loop iteration */\n    for (; i + 1 < nbSequences; i += 2) {\n        /* Load 2 ZSTD_Sequence (32 bytes) */\n        __m256i vin  = _mm256_loadu_si256((const __m256i*)(const void*)&inSeqs[i]);\n\n        /* Add {2, 0, -3, 0} in each 128-bit half */\n        __m256i vadd = _mm256_add_epi32(vin, addition);\n\n        /* Check for long length */\n        __m256i ll_cmp  = _mm256_cmpgt_epi32(vadd, limit);  /* 0xFFFFFFFF for element > 65535 */\n        int ll_res  = _mm256_movemask_epi8(ll_cmp);\n\n        /* Shuffle bytes so each half gives us the 8 bytes we need */\n        __m256i vshf = _mm256_shuffle_epi8(vadd, mask);\n        /*\n         * Now:\n         *   Lane0 = seq0's 8 bytes\n         *   Lane1 = 0\n         *   Lane2 = seq1's 8 bytes\n         *   Lane3 = 0\n         */\n\n        /* Permute 64-bit lanes => move Lane2 down into Lane1. */\n        __m256i vperm = _mm256_permute4x64_epi64(vshf, PERM_LANE_0X_E8);\n        /*\n         * Now the lower 16 bytes (Lane0+Lane1) = [seq0, seq1].\n         * The upper 16 bytes are [Lane2, Lane3] = [seq1, 0], but we won't use them.\n         */\n\n        /* Store only the lower 16 bytes => 2 SeqDef (8 bytes each) */\n        _mm_storeu_si128((__m128i *)(void*)&dstSeqs[i], _mm256_castsi256_si128(vperm));\n        /*\n         * This writes out 16 bytes total:\n         *   - offset 0..7  => seq0 (offBase, litLength, mlBase)\n         *   - offset 8..15 => seq1 (offBase, litLength, mlBase)\n         */\n\n        /* check (unlikely) long lengths > 65535\n         * indices for lengths correspond to bits [4..7], [8..11], [20..23], [24..27]\n         * => combined mask = 0x0FF00FF0\n         */\n        if (UNLIKELY((ll_res & 0x0FF00FF0) != 0)) {\n            /* long length detected: let's figure out which one*/\n            if (inSeqs[i].matchLength > 65535+MINMATCH) {\n                assert(longLen == 0);\n                longLen = i + 1;\n            }\n            if (inSeqs[i].litLength > 65535) {\n                assert(longLen == 0);\n                longLen = i + nbSequences + 1;\n            }\n            if (inSeqs[i+1].matchLength > 65535+MINMATCH) {\n                assert(longLen == 0);\n                longLen = i + 1 + 1;\n            }\n            if (inSeqs[i+1].litLength > 65535) {\n                assert(longLen == 0);\n                longLen = i + 1 + nbSequences + 1;\n            }\n        }\n    }\n\n    /* Handle leftover if @nbSequences is odd */\n    if (i < nbSequences) {\n        /* process last sequence */\n        assert(i == nbSequences - 1);\n        dstSeqs[i].offBase = OFFSET_TO_OFFBASE(inSeqs[i].offset);\n        dstSeqs[i].litLength = (U16)inSeqs[i].litLength;\n        dstSeqs[i].mlBase = (U16)(inSeqs[i].matchLength - MINMATCH);\n        /* check (unlikely) long lengths > 65535 */\n        if (UNLIKELY(inSeqs[i].matchLength > 65535+MINMATCH)) {\n            assert(longLen == 0);\n            longLen = i + 1;\n        }\n        if (UNLIKELY(inSeqs[i].litLength > 65535)) {\n            assert(longLen == 0);\n            longLen = i + nbSequences + 1;\n        }\n    }\n\n    return longLen;\n}\n\n/* the vector implementation could also be ported to SSSE3,\n * but since this implementation is targeting modern systems (>= Sapphire Rapid),\n * it's not useful to develop and maintain code for older pre-AVX2 platforms */\n\n#else /* no AVX2 */\n\nstatic size_t convertSequences_noRepcodes(\n    SeqDef* dstSeqs,\n    const ZSTD_Sequence* inSeqs,\n    size_t nbSequences)\n{\n    size_t longLen = 0;\n    size_t n;\n    for (n=0; n<nbSequences; n++) {\n        dstSeqs[n].offBase = OFFSET_TO_OFFBASE(inSeqs[n].offset);\n        dstSeqs[n].litLength = (U16)inSeqs[n].litLength;\n        dstSeqs[n].mlBase = (U16)(inSeqs[n].matchLength - MINMATCH);\n        /* check for long length > 65535 */\n        if (UNLIKELY(inSeqs[n].matchLength > 65535+MINMATCH)) {\n            assert(longLen == 0);\n            longLen = n + 1;\n        }\n        if (UNLIKELY(inSeqs[n].litLength > 65535)) {\n            assert(longLen == 0);\n            longLen = n + nbSequences + 1;\n        }\n    }\n    return longLen;\n}\n\n#endif\n\n/*\n * Precondition: Sequences must end on an explicit Block Delimiter\n * @return: 0 on success, or an error code.\n * Note: Sequence validation functionality has been disabled (removed).\n * This is helpful to generate a lean main pipeline, improving performance.\n * It may be re-inserted later.\n */\nsize_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx,\n                const ZSTD_Sequence* const inSeqs, size_t nbSequences,\n                int repcodeResolution)\n{\n    Repcodes_t updatedRepcodes;\n    size_t seqNb = 0;\n\n    DEBUGLOG(5, \"ZSTD_convertBlockSequences (nbSequences = %zu)\", nbSequences);\n\n    RETURN_ERROR_IF(nbSequences >= cctx->seqStore.maxNbSeq, externalSequences_invalid,\n                    \"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.\");\n\n    ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(Repcodes_t));\n\n    /* check end condition */\n    assert(nbSequences >= 1);\n    assert(inSeqs[nbSequences-1].matchLength == 0);\n    assert(inSeqs[nbSequences-1].offset == 0);\n\n    /* Convert Sequences from public format to internal format */\n    if (!repcodeResolution) {\n        size_t const longl = convertSequences_noRepcodes(cctx->seqStore.sequencesStart, inSeqs, nbSequences-1);\n        cctx->seqStore.sequences = cctx->seqStore.sequencesStart + nbSequences-1;\n        if (longl) {\n            DEBUGLOG(5, \"long length\");\n            assert(cctx->seqStore.longLengthType == ZSTD_llt_none);\n            if (longl <= nbSequences-1) {\n                DEBUGLOG(5, \"long match length detected at pos %zu\", longl-1);\n                cctx->seqStore.longLengthType = ZSTD_llt_matchLength;\n                cctx->seqStore.longLengthPos = (U32)(longl-1);\n            } else {\n                DEBUGLOG(5, \"long literals length detected at pos %zu\", longl-nbSequences);\n                assert(longl <= 2* (nbSequences-1));\n                cctx->seqStore.longLengthType = ZSTD_llt_literalLength;\n                cctx->seqStore.longLengthPos = (U32)(longl-(nbSequences-1)-1);\n            }\n        }\n    } else {\n        for (seqNb = 0; seqNb < nbSequences - 1 ; seqNb++) {\n            U32 const litLength = inSeqs[seqNb].litLength;\n            U32 const matchLength = inSeqs[seqNb].matchLength;\n            U32 const ll0 = (litLength == 0);\n            U32 const offBase = ZSTD_finalizeOffBase(inSeqs[seqNb].offset, updatedRepcodes.rep, ll0);\n\n            DEBUGLOG(6, \"Storing sequence: (of: %u, ml: %u, ll: %u)\", offBase, matchLength, litLength);\n            ZSTD_storeSeqOnly(&cctx->seqStore, litLength, offBase, matchLength);\n            ZSTD_updateRep(updatedRepcodes.rep, offBase, ll0);\n        }\n    }\n\n    /* If we skipped repcode search while parsing, we need to update repcodes now */\n    if (!repcodeResolution && nbSequences > 1) {\n        U32* const rep = updatedRepcodes.rep;\n\n        if (nbSequences >= 4) {\n            U32 lastSeqIdx = (U32)nbSequences - 2; /* index of last full sequence */\n            rep[2] = inSeqs[lastSeqIdx - 2].offset;\n            rep[1] = inSeqs[lastSeqIdx - 1].offset;\n            rep[0] = inSeqs[lastSeqIdx].offset;\n        } else if (nbSequences == 3) {\n            rep[2] = rep[0];\n            rep[1] = inSeqs[0].offset;\n            rep[0] = inSeqs[1].offset;\n        } else {\n            assert(nbSequences == 2);\n            rep[2] = rep[1];\n            rep[1] = rep[0];\n            rep[0] = inSeqs[0].offset;\n        }\n    }\n\n    ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(Repcodes_t));\n\n    return 0;\n}\n\n#if defined(ZSTD_ARCH_X86_AVX2)\n\nBlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    size_t i;\n    __m256i const zeroVec = _mm256_setzero_si256();\n    __m256i sumVec = zeroVec;  /* accumulates match+lit in 32-bit lanes */\n    ZSTD_ALIGNED(32) U32 tmp[8];      /* temporary buffer for reduction */\n    size_t mSum = 0, lSum = 0;\n    ZSTD_STATIC_ASSERT(sizeof(ZSTD_Sequence) == 16);\n\n    /* Process 2 structs (32 bytes) at a time */\n    for (i = 0; i + 2 <= nbSeqs; i += 2) {\n        /* Load two consecutive ZSTD_Sequence (8×4 = 32 bytes) */\n        __m256i data     = _mm256_loadu_si256((const __m256i*)(const void*)&seqs[i]);\n        /* check end of block signal */\n        __m256i cmp      = _mm256_cmpeq_epi32(data, zeroVec);\n        int cmp_res      = _mm256_movemask_epi8(cmp);\n        /* indices for match lengths correspond to bits [8..11], [24..27]\n         * => combined mask = 0x0F000F00 */\n        ZSTD_STATIC_ASSERT(offsetof(ZSTD_Sequence, matchLength) == 8);\n        if (cmp_res & 0x0F000F00) break;\n        /* Accumulate in sumVec */\n        sumVec           = _mm256_add_epi32(sumVec, data);\n    }\n\n    /* Horizontal reduction */\n    _mm256_store_si256((__m256i*)tmp, sumVec);\n    lSum = tmp[1] + tmp[5];\n    mSum = tmp[2] + tmp[6];\n\n    /* Handle the leftover */\n    for (; i < nbSeqs; i++) {\n        lSum += seqs[i].litLength;\n        mSum += seqs[i].matchLength;\n        if (seqs[i].matchLength == 0) break; /* end of block */\n    }\n\n    if (i==nbSeqs) {\n        /* reaching end of sequences: end of block signal was not present */\n        BlockSummary bs;\n        bs.nbSequences = ERROR(externalSequences_invalid);\n        return bs;\n    }\n    {   BlockSummary bs;\n        bs.nbSequences = i+1;\n        bs.blockSize = lSum + mSum;\n        bs.litSize = lSum;\n        return bs;\n    }\n}\n\n#else\n\nBlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs)\n{\n    size_t totalMatchSize = 0;\n    size_t litSize = 0;\n    size_t n;\n    assert(seqs);\n    for (n=0; n<nbSeqs; n++) {\n        totalMatchSize += seqs[n].matchLength;\n        litSize += seqs[n].litLength;\n        if (seqs[n].matchLength == 0) {\n            assert(seqs[n].offset == 0);\n            break;\n        }\n    }\n    if (n==nbSeqs) {\n        BlockSummary bs;\n        bs.nbSequences = ERROR(externalSequences_invalid);\n        return bs;\n    }\n    {   BlockSummary bs;\n        bs.nbSequences = n+1;\n        bs.blockSize = litSize + totalMatchSize;\n        bs.litSize = litSize;\n        return bs;\n    }\n}\n#endif\n\n\nstatic size_t\nZSTD_compressSequencesAndLiterals_internal(ZSTD_CCtx* cctx,\n                                void* dst, size_t dstCapacity,\n                          const ZSTD_Sequence* inSeqs, size_t nbSequences,\n                          const void* literals, size_t litSize, size_t srcSize)\n{\n    size_t remaining = srcSize;\n    size_t cSize = 0;\n    BYTE* op = (BYTE*)dst;\n    int const repcodeResolution = (cctx->appliedParams.searchForExternalRepcodes == ZSTD_ps_enable);\n    assert(cctx->appliedParams.searchForExternalRepcodes != ZSTD_ps_auto);\n\n    DEBUGLOG(4, \"ZSTD_compressSequencesAndLiterals_internal: nbSeqs=%zu, litSize=%zu\", nbSequences, litSize);\n    RETURN_ERROR_IF(nbSequences == 0, externalSequences_invalid, \"Requires at least 1 end-of-block\");\n\n    /* Special case: empty frame */\n    if ((nbSequences == 1) && (inSeqs[0].litLength == 0)) {\n        U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1);\n        RETURN_ERROR_IF(dstCapacity<3, dstSize_tooSmall, \"No room for empty frame block header\");\n        MEM_writeLE24(op, cBlockHeader24);\n        op += ZSTD_blockHeaderSize;\n        dstCapacity -= ZSTD_blockHeaderSize;\n        cSize += ZSTD_blockHeaderSize;\n    }\n\n    while (nbSequences) {\n        size_t compressedSeqsSize, cBlockSize, conversionStatus;\n        BlockSummary const block = ZSTD_get1BlockSummary(inSeqs, nbSequences);\n        U32 const lastBlock = (block.nbSequences == nbSequences);\n        FORWARD_IF_ERROR(block.nbSequences, \"Error while trying to determine nb of sequences for a block\");\n        assert(block.nbSequences <= nbSequences);\n        RETURN_ERROR_IF(block.litSize > litSize, externalSequences_invalid, \"discrepancy: Sequences require more literals than present in buffer\");\n        ZSTD_resetSeqStore(&cctx->seqStore);\n\n        conversionStatus = ZSTD_convertBlockSequences(cctx,\n                            inSeqs, block.nbSequences,\n                            repcodeResolution);\n        FORWARD_IF_ERROR(conversionStatus, \"Bad sequence conversion\");\n        inSeqs += block.nbSequences;\n        nbSequences -= block.nbSequences;\n        remaining -= block.blockSize;\n\n        /* Note: when blockSize is very small, other variant send it uncompressed.\n         * Here, we still send the sequences, because we don't have the original source to send it uncompressed.\n         * One could imagine in theory reproducing the source from the sequences,\n         * but that's complex and costly memory intensive, and goes against the objectives of this variant. */\n\n        RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, \"not enough dstCapacity to write a new compressed block\");\n\n        compressedSeqsSize = ZSTD_entropyCompressSeqStore_internal(\n                                op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize,\n                                literals, block.litSize,\n                                &cctx->seqStore,\n                                &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy,\n                                &cctx->appliedParams,\n                                cctx->tmpWorkspace, cctx->tmpWkspSize /* statically allocated in resetCCtx */,\n                                cctx->bmi2);\n        FORWARD_IF_ERROR(compressedSeqsSize, \"Compressing sequences of block failed\");\n        /* note: the spec forbids for any compressed block to be larger than maximum block size */\n        if (compressedSeqsSize > cctx->blockSizeMax) compressedSeqsSize = 0;\n        DEBUGLOG(5, \"Compressed sequences size: %zu\", compressedSeqsSize);\n        litSize -= block.litSize;\n        literals = (const char*)literals + block.litSize;\n\n        /* Note: difficult to check source for RLE block when only Literals are provided,\n         * but it could be considered from analyzing the sequence directly */\n\n        if (compressedSeqsSize == 0) {\n            /* Sending uncompressed blocks is out of reach, because the source is not provided.\n             * In theory, one could use the sequences to regenerate the source, like a decompressor,\n             * but it's complex, and memory hungry, killing the purpose of this variant.\n             * Current outcome: generate an error code.\n             */\n            RETURN_ERROR(cannotProduce_uncompressedBlock, \"ZSTD_compressSequencesAndLiterals cannot generate an uncompressed block\");\n        } else {\n            U32 cBlockHeader;\n            assert(compressedSeqsSize > 1); /* no RLE */\n            /* Error checking and repcodes update */\n            ZSTD_blockState_confirmRepcodesAndEntropyTables(&cctx->blockState);\n            if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)\n                cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;\n\n            /* Write block header into beginning of block*/\n            cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3);\n            MEM_writeLE24(op, cBlockHeader);\n            cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize;\n            DEBUGLOG(5, \"Writing out compressed block, size: %zu\", cBlockSize);\n        }\n\n        cSize += cBlockSize;\n        op += cBlockSize;\n        dstCapacity -= cBlockSize;\n        cctx->isFirstBlock = 0;\n        DEBUGLOG(5, \"cSize running total: %zu (remaining dstCapacity=%zu)\", cSize, dstCapacity);\n\n        if (lastBlock) {\n            assert(nbSequences == 0);\n            break;\n        }\n    }\n\n    RETURN_ERROR_IF(litSize != 0, externalSequences_invalid, \"literals must be entirely and exactly consumed\");\n    RETURN_ERROR_IF(remaining != 0, externalSequences_invalid, \"Sequences must represent a total of exactly srcSize=%zu\", srcSize);\n    DEBUGLOG(4, \"cSize final total: %zu\", cSize);\n    return cSize;\n}\n\nsize_t\nZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,\n                    void* dst, size_t dstCapacity,\n                    const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                    const void* literals, size_t litSize, size_t litCapacity,\n                    size_t decompressedSize)\n{\n    BYTE* op = (BYTE*)dst;\n    size_t cSize = 0;\n\n    /* Transparent initialization stage, same as compressStream2() */\n    DEBUGLOG(4, \"ZSTD_compressSequencesAndLiterals (dstCapacity=%zu)\", dstCapacity);\n    assert(cctx != NULL);\n    if (litCapacity < litSize) {\n        RETURN_ERROR(workSpace_tooSmall, \"literals buffer is not large enough: must be at least 8 bytes larger than litSize (risk of read out-of-bound)\");\n    }\n    FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, decompressedSize), \"CCtx initialization failed\");\n\n    if (cctx->appliedParams.blockDelimiters == ZSTD_sf_noBlockDelimiters) {\n        RETURN_ERROR(frameParameter_unsupported, \"This mode is only compatible with explicit delimiters\");\n    }\n    if (cctx->appliedParams.validateSequences) {\n        RETURN_ERROR(parameter_unsupported, \"This mode is not compatible with Sequence validation\");\n    }\n    if (cctx->appliedParams.fParams.checksumFlag) {\n        RETURN_ERROR(frameParameter_unsupported, \"this mode is not compatible with frame checksum\");\n    }\n\n    /* Begin writing output, starting with frame header */\n    {   size_t const frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity,\n                    &cctx->appliedParams, decompressedSize, cctx->dictID);\n        op += frameHeaderSize;\n        assert(frameHeaderSize <= dstCapacity);\n        dstCapacity -= frameHeaderSize;\n        cSize += frameHeaderSize;\n    }\n\n    /* Now generate compressed blocks */\n    {   size_t const cBlocksSize = ZSTD_compressSequencesAndLiterals_internal(cctx,\n                                            op, dstCapacity,\n                                            inSeqs, inSeqsSize,\n                                            literals, litSize, decompressedSize);\n        FORWARD_IF_ERROR(cBlocksSize, \"Compressing blocks failed!\");\n        cSize += cBlocksSize;\n        assert(cBlocksSize <= dstCapacity);\n        dstCapacity -= cBlocksSize;\n    }\n\n    DEBUGLOG(4, \"Final compressed size: %zu\", cSize);\n    return cSize;\n}\n\n/*======   Finalize   ======*/\n\nstatic ZSTD_inBuffer inBuffer_forEndFlush(const ZSTD_CStream* zcs)\n{\n    const ZSTD_inBuffer nullInput = { NULL, 0, 0 };\n    const int stableInput = (zcs->appliedParams.inBufferMode == ZSTD_bm_stable);\n    return stableInput ? zcs->expectedInBuffer : nullInput;\n}\n\n/*! ZSTD_flushStream() :\n * @return : amount of data remaining to flush */\nsize_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)\n{\n    ZSTD_inBuffer input = inBuffer_forEndFlush(zcs);\n    input.size = input.pos; /* do not ingest more input during flush */\n    return ZSTD_compressStream2(zcs, output, &input, ZSTD_e_flush);\n}\n\nsize_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)\n{\n    ZSTD_inBuffer input = inBuffer_forEndFlush(zcs);\n    size_t const remainingToFlush = ZSTD_compressStream2(zcs, output, &input, ZSTD_e_end);\n    FORWARD_IF_ERROR(remainingToFlush , \"ZSTD_compressStream2(,,ZSTD_e_end) failed\");\n    if (zcs->appliedParams.nbWorkers > 0) return remainingToFlush;   /* minimal estimation */\n    /* single thread mode : attempt to calculate remaining to flush more precisely */\n    {   size_t const lastBlockSize = zcs->frameEnded ? 0 : ZSTD_BLOCKHEADERSIZE;\n        size_t const checksumSize = (size_t)(zcs->frameEnded ? 0 : zcs->appliedParams.fParams.checksumFlag * 4);\n        size_t const toFlush = remainingToFlush + lastBlockSize + checksumSize;\n        DEBUGLOG(4, \"ZSTD_endStream : remaining to flush : %u\", (unsigned)toFlush);\n        return toFlush;\n    }\n}\n\n\n/*-=====  Pre-defined compression levels  =====-*/\n#include \"clevels.h\"\n\nint ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }\nint ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }\nint ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; }\n\nstatic ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)\n{\n    ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);\n    switch (cParams.strategy) {\n        case ZSTD_fast:\n        case ZSTD_dfast:\n            break;\n        case ZSTD_greedy:\n        case ZSTD_lazy:\n        case ZSTD_lazy2:\n            cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG;\n            break;\n        case ZSTD_btlazy2:\n        case ZSTD_btopt:\n        case ZSTD_btultra:\n        case ZSTD_btultra2:\n            break;\n    }\n    return cParams;\n}\n\nstatic int ZSTD_dedicatedDictSearch_isSupported(\n        ZSTD_compressionParameters const* cParams)\n{\n    return (cParams->strategy >= ZSTD_greedy)\n        && (cParams->strategy <= ZSTD_lazy2)\n        && (cParams->hashLog > cParams->chainLog)\n        && (cParams->chainLog <= 24);\n}\n\n/**\n * Reverses the adjustment applied to cparams when enabling dedicated dict\n * search. This is used to recover the params set to be used in the working\n * context. (Otherwise, those tables would also grow.)\n */\nstatic void ZSTD_dedicatedDictSearch_revertCParams(\n        ZSTD_compressionParameters* cParams) {\n    switch (cParams->strategy) {\n        case ZSTD_fast:\n        case ZSTD_dfast:\n            break;\n        case ZSTD_greedy:\n        case ZSTD_lazy:\n        case ZSTD_lazy2:\n            cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG;\n            if (cParams->hashLog < ZSTD_HASHLOG_MIN) {\n                cParams->hashLog = ZSTD_HASHLOG_MIN;\n            }\n            break;\n        case ZSTD_btlazy2:\n        case ZSTD_btopt:\n        case ZSTD_btultra:\n        case ZSTD_btultra2:\n            break;\n    }\n}\n\nstatic U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    switch (mode) {\n    case ZSTD_cpm_unknown:\n    case ZSTD_cpm_noAttachDict:\n    case ZSTD_cpm_createCDict:\n        break;\n    case ZSTD_cpm_attachDict:\n        dictSize = 0;\n        break;\n    default:\n        assert(0);\n        break;\n    }\n    {   int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN;\n        size_t const addedSize = unknown && dictSize > 0 ? 500 : 0;\n        return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize;\n    }\n}\n\n/*! ZSTD_getCParams_internal() :\n * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.\n *  Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown.\n *        Use dictSize == 0 for unknown or unused.\n *  Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_CParamMode_e`. */\nstatic ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode);\n    U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB);\n    int row;\n    DEBUGLOG(5, \"ZSTD_getCParams_internal (cLevel=%i)\", compressionLevel);\n\n    /* row */\n    if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT;   /* 0 == default */\n    else if (compressionLevel < 0) row = 0;   /* entry 0 is baseline for fast mode */\n    else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL;\n    else row = compressionLevel;\n\n    {   ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row];\n        DEBUGLOG(5, \"ZSTD_getCParams_internal selected tableID: %u row: %u strat: %u\", tableID, row, (U32)cp.strategy);\n        /* acceleration factor */\n        if (compressionLevel < 0) {\n            int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel);\n            cp.targetLength = (unsigned)(-clampedCompressionLevel);\n        }\n        /* refine parameters based on srcSize & dictSize */\n        return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode, ZSTD_ps_auto);\n    }\n}\n\n/*! ZSTD_getCParams() :\n * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize.\n *  Size values are optional, provide 0 if not known or unused */\nZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)\n{\n    if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;\n    return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);\n}\n\n/*! ZSTD_getParams() :\n *  same idea as ZSTD_getCParams()\n * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).\n *  Fields of `ZSTD_frameParameters` are set to default values */\nstatic ZSTD_parameters\nZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode)\n{\n    ZSTD_parameters params;\n    ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode);\n    DEBUGLOG(5, \"ZSTD_getParams (cLevel=%i)\", compressionLevel);\n    ZSTD_memset(&params, 0, sizeof(params));\n    params.cParams = cParams;\n    params.fParams.contentSizeFlag = 1;\n    return params;\n}\n\n/*! ZSTD_getParams() :\n *  same idea as ZSTD_getCParams()\n * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`).\n *  Fields of `ZSTD_frameParameters` are set to default values */\nZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize)\n{\n    if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN;\n    return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown);\n}\n\nvoid ZSTD_registerSequenceProducer(\n    ZSTD_CCtx* zc,\n    void* extSeqProdState,\n    ZSTD_sequenceProducer_F extSeqProdFunc)\n{\n    assert(zc != NULL);\n    ZSTD_CCtxParams_registerSequenceProducer(\n        &zc->requestedParams, extSeqProdState, extSeqProdFunc\n    );\n}\n\nvoid ZSTD_CCtxParams_registerSequenceProducer(\n  ZSTD_CCtx_params* params,\n  void* extSeqProdState,\n  ZSTD_sequenceProducer_F extSeqProdFunc)\n{\n    assert(params != NULL);\n    if (extSeqProdFunc != NULL) {\n        params->extSeqProdFunc = extSeqProdFunc;\n        params->extSeqProdState = extSeqProdState;\n    } else {\n        params->extSeqProdFunc = NULL;\n        params->extSeqProdState = NULL;\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress_internal.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* This header contains definitions\n * that shall **only** be used by modules within lib/compress.\n */\n\n#ifndef ZSTD_COMPRESS_H\n#define ZSTD_COMPRESS_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"../common/zstd_internal.h\"\n#include \"zstd_cwksp.h\"\n#ifdef ZSTD_MULTITHREAD\n#  include \"zstdmt_compress.h\"\n#endif\n#include \"../common/bits.h\" /* ZSTD_highbit32, ZSTD_NbCommonBytes */\n#include \"zstd_preSplit.h\" /* ZSTD_SLIPBLOCK_WORKSPACESIZE */\n\n/*-*************************************\n*  Constants\n***************************************/\n#define kSearchStrength      8\n#define HASH_READ_SIZE       8\n#define ZSTD_DUBT_UNSORTED_MARK 1   /* For btlazy2 strategy, index ZSTD_DUBT_UNSORTED_MARK==1 means \"unsorted\".\n                                       It could be confused for a real successor at index \"1\", if sorted as larger than its predecessor.\n                                       It's not a big deal though : candidate will just be sorted again.\n                                       Additionally, candidate position 1 will be lost.\n                                       But candidate 1 cannot hide a large tree of candidates, so it's a minimal loss.\n                                       The benefit is that ZSTD_DUBT_UNSORTED_MARK cannot be mishandled after table reuse with a different strategy.\n                                       This constant is required by ZSTD_compressBlock_btlazy2() and ZSTD_reduceTable_internal() */\n\n\n/*-*************************************\n*  Context memory management\n***************************************/\ntypedef enum { ZSTDcs_created=0, ZSTDcs_init, ZSTDcs_ongoing, ZSTDcs_ending } ZSTD_compressionStage_e;\ntypedef enum { zcss_init=0, zcss_load, zcss_flush } ZSTD_cStreamStage;\n\ntypedef struct ZSTD_prefixDict_s {\n    const void* dict;\n    size_t dictSize;\n    ZSTD_dictContentType_e dictContentType;\n} ZSTD_prefixDict;\n\ntypedef struct {\n    void* dictBuffer;\n    void const* dict;\n    size_t dictSize;\n    ZSTD_dictContentType_e dictContentType;\n    ZSTD_CDict* cdict;\n} ZSTD_localDict;\n\ntypedef struct {\n    HUF_CElt CTable[HUF_CTABLE_SIZE_ST(255)];\n    HUF_repeat repeatMode;\n} ZSTD_hufCTables_t;\n\ntypedef struct {\n    FSE_CTable offcodeCTable[FSE_CTABLE_SIZE_U32(OffFSELog, MaxOff)];\n    FSE_CTable matchlengthCTable[FSE_CTABLE_SIZE_U32(MLFSELog, MaxML)];\n    FSE_CTable litlengthCTable[FSE_CTABLE_SIZE_U32(LLFSELog, MaxLL)];\n    FSE_repeat offcode_repeatMode;\n    FSE_repeat matchlength_repeatMode;\n    FSE_repeat litlength_repeatMode;\n} ZSTD_fseCTables_t;\n\ntypedef struct {\n    ZSTD_hufCTables_t huf;\n    ZSTD_fseCTables_t fse;\n} ZSTD_entropyCTables_t;\n\n/***********************************************\n*  Sequences *\n***********************************************/\ntypedef struct SeqDef_s {\n    U32 offBase;   /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */\n    U16 litLength;\n    U16 mlBase;    /* mlBase == matchLength - MINMATCH */\n} SeqDef;\n\n/* Controls whether seqStore has a single \"long\" litLength or matchLength. See SeqStore_t. */\ntypedef enum {\n    ZSTD_llt_none = 0,             /* no longLengthType */\n    ZSTD_llt_literalLength = 1,    /* represents a long literal */\n    ZSTD_llt_matchLength = 2       /* represents a long match */\n} ZSTD_longLengthType_e;\n\ntypedef struct {\n    SeqDef* sequencesStart;\n    SeqDef* sequences;      /* ptr to end of sequences */\n    BYTE*  litStart;\n    BYTE*  lit;             /* ptr to end of literals */\n    BYTE*  llCode;\n    BYTE*  mlCode;\n    BYTE*  ofCode;\n    size_t maxNbSeq;\n    size_t maxNbLit;\n\n    /* longLengthPos and longLengthType to allow us to represent either a single litLength or matchLength\n     * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment\n     * the existing value of the litLength or matchLength by 0x10000.\n     */\n    ZSTD_longLengthType_e longLengthType;\n    U32                   longLengthPos;  /* Index of the sequence to apply long length modification to */\n} SeqStore_t;\n\ntypedef struct {\n    U32 litLength;\n    U32 matchLength;\n} ZSTD_SequenceLength;\n\n/**\n * Returns the ZSTD_SequenceLength for the given sequences. It handles the decoding of long sequences\n * indicated by longLengthPos and longLengthType, and adds MINMATCH back to matchLength.\n */\nMEM_STATIC ZSTD_SequenceLength ZSTD_getSequenceLength(SeqStore_t const* seqStore, SeqDef const* seq)\n{\n    ZSTD_SequenceLength seqLen;\n    seqLen.litLength = seq->litLength;\n    seqLen.matchLength = seq->mlBase + MINMATCH;\n    if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {\n        if (seqStore->longLengthType == ZSTD_llt_literalLength) {\n            seqLen.litLength += 0x10000;\n        }\n        if (seqStore->longLengthType == ZSTD_llt_matchLength) {\n            seqLen.matchLength += 0x10000;\n        }\n    }\n    return seqLen;\n}\n\nconst SeqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx);   /* compress & dictBuilder */\nint ZSTD_seqToCodes(const SeqStore_t* seqStorePtr);   /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */\n\n\n/***********************************************\n*  Entropy buffer statistics structs and funcs *\n***********************************************/\n/** ZSTD_hufCTablesMetadata_t :\n *  Stores Literals Block Type for a super-block in hType, and\n *  huffman tree description in hufDesBuffer.\n *  hufDesSize refers to the size of huffman tree description in bytes.\n *  This metadata is populated in ZSTD_buildBlockEntropyStats_literals() */\ntypedef struct {\n    SymbolEncodingType_e hType;\n    BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE];\n    size_t hufDesSize;\n} ZSTD_hufCTablesMetadata_t;\n\n/** ZSTD_fseCTablesMetadata_t :\n *  Stores symbol compression modes for a super-block in {ll, ol, ml}Type, and\n *  fse tables in fseTablesBuffer.\n *  fseTablesSize refers to the size of fse tables in bytes.\n *  This metadata is populated in ZSTD_buildBlockEntropyStats_sequences() */\ntypedef struct {\n    SymbolEncodingType_e llType;\n    SymbolEncodingType_e ofType;\n    SymbolEncodingType_e mlType;\n    BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE];\n    size_t fseTablesSize;\n    size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_entropyCompressSeqStore_internal() */\n} ZSTD_fseCTablesMetadata_t;\n\ntypedef struct {\n    ZSTD_hufCTablesMetadata_t hufMetadata;\n    ZSTD_fseCTablesMetadata_t fseMetadata;\n} ZSTD_entropyCTablesMetadata_t;\n\n/** ZSTD_buildBlockEntropyStats() :\n *  Builds entropy for the block.\n *  @return : 0 on success or error code */\nsize_t ZSTD_buildBlockEntropyStats(\n                    const SeqStore_t* seqStorePtr,\n                    const ZSTD_entropyCTables_t* prevEntropy,\n                          ZSTD_entropyCTables_t* nextEntropy,\n                    const ZSTD_CCtx_params* cctxParams,\n                          ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                          void* workspace, size_t wkspSize);\n\n/*********************************\n*  Compression internals structs *\n*********************************/\n\ntypedef struct {\n    U32 off;            /* Offset sumtype code for the match, using ZSTD_storeSeq() format */\n    U32 len;            /* Raw length of match */\n} ZSTD_match_t;\n\ntypedef struct {\n    U32 offset;         /* Offset of sequence */\n    U32 litLength;      /* Length of literals prior to match */\n    U32 matchLength;    /* Raw length of match */\n} rawSeq;\n\ntypedef struct {\n  rawSeq* seq;          /* The start of the sequences */\n  size_t pos;           /* The index in seq where reading stopped. pos <= size. */\n  size_t posInSequence; /* The position within the sequence at seq[pos] where reading\n                           stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */\n  size_t size;          /* The number of sequences. <= capacity. */\n  size_t capacity;      /* The capacity starting from `seq` pointer */\n} RawSeqStore_t;\n\nUNUSED_ATTR static const RawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0};\n\ntypedef struct {\n    int price;  /* price from beginning of segment to this position */\n    U32 off;    /* offset of previous match */\n    U32 mlen;   /* length of previous match */\n    U32 litlen; /* nb of literals since previous match */\n    U32 rep[ZSTD_REP_NUM];  /* offset history after previous match */\n} ZSTD_optimal_t;\n\ntypedef enum { zop_dynamic=0, zop_predef } ZSTD_OptPrice_e;\n\n#define ZSTD_OPT_SIZE (ZSTD_OPT_NUM+3)\ntypedef struct {\n    /* All tables are allocated inside cctx->workspace by ZSTD_resetCCtx_internal() */\n    unsigned* litFreq;           /* table of literals statistics, of size 256 */\n    unsigned* litLengthFreq;     /* table of litLength statistics, of size (MaxLL+1) */\n    unsigned* matchLengthFreq;   /* table of matchLength statistics, of size (MaxML+1) */\n    unsigned* offCodeFreq;       /* table of offCode statistics, of size (MaxOff+1) */\n    ZSTD_match_t* matchTable;    /* list of found matches, of size ZSTD_OPT_SIZE */\n    ZSTD_optimal_t* priceTable;  /* All positions tracked by optimal parser, of size ZSTD_OPT_SIZE */\n\n    U32  litSum;                 /* nb of literals */\n    U32  litLengthSum;           /* nb of litLength codes */\n    U32  matchLengthSum;         /* nb of matchLength codes */\n    U32  offCodeSum;             /* nb of offset codes */\n    U32  litSumBasePrice;        /* to compare to log2(litfreq) */\n    U32  litLengthSumBasePrice;  /* to compare to log2(llfreq)  */\n    U32  matchLengthSumBasePrice;/* to compare to log2(mlfreq)  */\n    U32  offCodeSumBasePrice;    /* to compare to log2(offreq)  */\n    ZSTD_OptPrice_e priceType;   /* prices can be determined dynamically, or follow a pre-defined cost structure */\n    const ZSTD_entropyCTables_t* symbolCosts;  /* pre-calculated dictionary statistics */\n    ZSTD_ParamSwitch_e literalCompressionMode;\n} optState_t;\n\ntypedef struct {\n  ZSTD_entropyCTables_t entropy;\n  U32 rep[ZSTD_REP_NUM];\n} ZSTD_compressedBlockState_t;\n\ntypedef struct {\n    BYTE const* nextSrc;       /* next block here to continue on current prefix */\n    BYTE const* base;          /* All regular indexes relative to this position */\n    BYTE const* dictBase;      /* extDict indexes relative to this position */\n    U32 dictLimit;             /* below that point, need extDict */\n    U32 lowLimit;              /* below that point, no more valid data */\n    U32 nbOverflowCorrections; /* Number of times overflow correction has run since\n                                * ZSTD_window_init(). Useful for debugging coredumps\n                                * and for ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY.\n                                */\n} ZSTD_window_t;\n\n#define ZSTD_WINDOW_START_INDEX 2\n\ntypedef struct ZSTD_MatchState_t ZSTD_MatchState_t;\n\n#define ZSTD_ROW_HASH_CACHE_SIZE 8       /* Size of prefetching hash cache for row-based matchfinder */\n\nstruct ZSTD_MatchState_t {\n    ZSTD_window_t window;   /* State for window round buffer management */\n    U32 loadedDictEnd;      /* index of end of dictionary, within context's referential.\n                             * When loadedDictEnd != 0, a dictionary is in use, and still valid.\n                             * This relies on a mechanism to set loadedDictEnd=0 when dictionary is no longer within distance.\n                             * Such mechanism is provided within ZSTD_window_enforceMaxDist() and ZSTD_checkDictValidity().\n                             * When dict referential is copied into active context (i.e. not attached),\n                             * loadedDictEnd == dictSize, since referential starts from zero.\n                             */\n    U32 nextToUpdate;       /* index from which to continue table update */\n    U32 hashLog3;           /* dispatch table for matches of len==3 : larger == faster, more memory */\n\n    U32 rowHashLog;                          /* For row-based matchfinder: Hashlog based on nb of rows in the hashTable.*/\n    BYTE* tagTable;                          /* For row-based matchFinder: A row-based table containing the hashes and head index. */\n    U32 hashCache[ZSTD_ROW_HASH_CACHE_SIZE]; /* For row-based matchFinder: a cache of hashes to improve speed */\n    U64 hashSalt;                            /* For row-based matchFinder: salts the hash for reuse of tag table */\n    U32 hashSaltEntropy;                     /* For row-based matchFinder: collects entropy for salt generation */\n\n    U32* hashTable;\n    U32* hashTable3;\n    U32* chainTable;\n\n    int forceNonContiguous; /* Non-zero if we should force non-contiguous load for the next window update. */\n\n    int dedicatedDictSearch;  /* Indicates whether this matchState is using the\n                               * dedicated dictionary search structure.\n                               */\n    optState_t opt;         /* optimal parser state */\n    const ZSTD_MatchState_t* dictMatchState;\n    ZSTD_compressionParameters cParams;\n    const RawSeqStore_t* ldmSeqStore;\n\n    /* Controls prefetching in some dictMatchState matchfinders.\n     * This behavior is controlled from the cctx ms.\n     * This parameter has no effect in the cdict ms. */\n    int prefetchCDictTables;\n\n    /* When == 0, lazy match finders insert every position.\n     * When != 0, lazy match finders only insert positions they search.\n     * This allows them to skip much faster over incompressible data,\n     * at a small cost to compression ratio.\n     */\n    int lazySkipping;\n};\n\ntypedef struct {\n    ZSTD_compressedBlockState_t* prevCBlock;\n    ZSTD_compressedBlockState_t* nextCBlock;\n    ZSTD_MatchState_t matchState;\n} ZSTD_blockState_t;\n\ntypedef struct {\n    U32 offset;\n    U32 checksum;\n} ldmEntry_t;\n\ntypedef struct {\n    BYTE const* split;\n    U32 hash;\n    U32 checksum;\n    ldmEntry_t* bucket;\n} ldmMatchCandidate_t;\n\n#define LDM_BATCH_SIZE 64\n\ntypedef struct {\n    ZSTD_window_t window;   /* State for the window round buffer management */\n    ldmEntry_t* hashTable;\n    U32 loadedDictEnd;\n    BYTE* bucketOffsets;    /* Next position in bucket to insert entry */\n    size_t splitIndices[LDM_BATCH_SIZE];\n    ldmMatchCandidate_t matchCandidates[LDM_BATCH_SIZE];\n} ldmState_t;\n\ntypedef struct {\n    ZSTD_ParamSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */\n    U32 hashLog;            /* Log size of hashTable */\n    U32 bucketSizeLog;      /* Log bucket size for collision resolution, at most 8 */\n    U32 minMatchLength;     /* Minimum match length */\n    U32 hashRateLog;       /* Log number of entries to skip */\n    U32 windowLog;          /* Window log for the LDM */\n} ldmParams_t;\n\ntypedef struct {\n    int collectSequences;\n    ZSTD_Sequence* seqStart;\n    size_t seqIndex;\n    size_t maxSequences;\n} SeqCollector;\n\nstruct ZSTD_CCtx_params_s {\n    ZSTD_format_e format;\n    ZSTD_compressionParameters cParams;\n    ZSTD_frameParameters fParams;\n\n    int compressionLevel;\n    int forceWindow;           /* force back-references to respect limit of\n                                * 1<<wLog, even for dictionary */\n    size_t targetCBlockSize;   /* Tries to fit compressed block size to be around targetCBlockSize.\n                                * No target when targetCBlockSize == 0.\n                                * There is no guarantee on compressed block size */\n    int srcSizeHint;           /* User's best guess of source size.\n                                * Hint is not valid when srcSizeHint == 0.\n                                * There is no guarantee that hint is close to actual source size */\n\n    ZSTD_dictAttachPref_e attachDictPref;\n    ZSTD_ParamSwitch_e literalCompressionMode;\n\n    /* Multithreading: used to pass parameters to mtctx */\n    int nbWorkers;\n    size_t jobSize;\n    int overlapLog;\n    int rsyncable;\n\n    /* Long distance matching parameters */\n    ldmParams_t ldmParams;\n\n    /* Dedicated dict search algorithm trigger */\n    int enableDedicatedDictSearch;\n\n    /* Input/output buffer modes */\n    ZSTD_bufferMode_e inBufferMode;\n    ZSTD_bufferMode_e outBufferMode;\n\n    /* Sequence compression API */\n    ZSTD_SequenceFormat_e blockDelimiters;\n    int validateSequences;\n\n    /* Block splitting\n     * @postBlockSplitter executes split analysis after sequences are produced,\n     * it's more accurate but consumes more resources.\n     * @preBlockSplitter_level splits before knowing sequences,\n     * it's more approximative but also cheaper.\n     * Valid @preBlockSplitter_level values range from 0 to 6 (included).\n     * 0 means auto, 1 means do not split,\n     * then levels are sorted in increasing cpu budget, from 2 (fastest) to 6 (slowest).\n     * Highest @preBlockSplitter_level combines well with @postBlockSplitter.\n     */\n    ZSTD_ParamSwitch_e postBlockSplitter;\n    int preBlockSplitter_level;\n\n    /* Adjust the max block size*/\n    size_t maxBlockSize;\n\n    /* Param for deciding whether to use row-based matchfinder */\n    ZSTD_ParamSwitch_e useRowMatchFinder;\n\n    /* Always load a dictionary in ext-dict mode (not prefix mode)? */\n    int deterministicRefPrefix;\n\n    /* Internal use, for createCCtxParams() and freeCCtxParams() only */\n    ZSTD_customMem customMem;\n\n    /* Controls prefetching in some dictMatchState matchfinders */\n    ZSTD_ParamSwitch_e prefetchCDictTables;\n\n    /* Controls whether zstd will fall back to an internal matchfinder\n     * if the external matchfinder returns an error code. */\n    int enableMatchFinderFallback;\n\n    /* Parameters for the external sequence producer API.\n     * Users set these parameters through ZSTD_registerSequenceProducer().\n     * It is not possible to set these parameters individually through the public API. */\n    void* extSeqProdState;\n    ZSTD_sequenceProducer_F extSeqProdFunc;\n\n    /* Controls repcode search in external sequence parsing */\n    ZSTD_ParamSwitch_e searchForExternalRepcodes;\n};  /* typedef'd to ZSTD_CCtx_params within \"zstd.h\" */\n\n#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2))\n#define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE)\n#define TMP_WORKSPACE_SIZE (MAX(ENTROPY_WORKSPACE_SIZE, ZSTD_SLIPBLOCK_WORKSPACESIZE))\n\n/**\n * Indicates whether this compression proceeds directly from user-provided\n * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or\n * whether the context needs to buffer the input/output (ZSTDb_buffered).\n */\ntypedef enum {\n    ZSTDb_not_buffered,\n    ZSTDb_buffered\n} ZSTD_buffered_policy_e;\n\n/**\n * Struct that contains all elements of block splitter that should be allocated\n * in a wksp.\n */\n#define ZSTD_MAX_NB_BLOCK_SPLITS 196\ntypedef struct {\n    SeqStore_t fullSeqStoreChunk;\n    SeqStore_t firstHalfSeqStore;\n    SeqStore_t secondHalfSeqStore;\n    SeqStore_t currSeqStore;\n    SeqStore_t nextSeqStore;\n\n    U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS];\n    ZSTD_entropyCTablesMetadata_t entropyMetadata;\n} ZSTD_blockSplitCtx;\n\nstruct ZSTD_CCtx_s {\n    ZSTD_compressionStage_e stage;\n    int cParamsChanged;                  /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */\n    int bmi2;                            /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */\n    ZSTD_CCtx_params requestedParams;\n    ZSTD_CCtx_params appliedParams;\n    ZSTD_CCtx_params simpleApiParams;    /* Param storage used by the simple API - not sticky. Must only be used in top-level simple API functions for storage. */\n    U32   dictID;\n    size_t dictContentSize;\n\n    ZSTD_cwksp workspace; /* manages buffer for dynamic allocations */\n    size_t blockSizeMax;\n    unsigned long long pledgedSrcSizePlusOne;  /* this way, 0 (default) == unknown */\n    unsigned long long consumedSrcSize;\n    unsigned long long producedCSize;\n    XXH64_state_t xxhState;\n    ZSTD_customMem customMem;\n    ZSTD_threadPool* pool;\n    size_t staticSize;\n    SeqCollector seqCollector;\n    int isFirstBlock;\n    int initialized;\n\n    SeqStore_t seqStore;      /* sequences storage ptrs */\n    ldmState_t ldmState;      /* long distance matching state */\n    rawSeq* ldmSequences;     /* Storage for the ldm output sequences */\n    size_t maxNbLdmSequences;\n    RawSeqStore_t externSeqStore; /* Mutable reference to external sequences */\n    ZSTD_blockState_t blockState;\n    void* tmpWorkspace;  /* used as substitute of stack space - must be aligned for S64 type */\n    size_t tmpWkspSize;\n\n    /* Whether we are streaming or not */\n    ZSTD_buffered_policy_e bufferedPolicy;\n\n    /* streaming */\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inToCompress;\n    size_t inBuffPos;\n    size_t inBuffTarget;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outBuffContentSize;\n    size_t outBuffFlushedSize;\n    ZSTD_cStreamStage streamStage;\n    U32    frameEnded;\n\n    /* Stable in/out buffer verification */\n    ZSTD_inBuffer expectedInBuffer;\n    size_t stableIn_notConsumed; /* nb bytes within stable input buffer that are said to be consumed but are not */\n    size_t expectedOutBufferSize;\n\n    /* Dictionary */\n    ZSTD_localDict localDict;\n    const ZSTD_CDict* cdict;\n    ZSTD_prefixDict prefixDict;   /* single-usage dictionary */\n\n    /* Multi-threading */\n#ifdef ZSTD_MULTITHREAD\n    ZSTDMT_CCtx* mtctx;\n#endif\n\n    /* Tracing */\n#if ZSTD_TRACE\n    ZSTD_TraceCtx traceCtx;\n#endif\n\n    /* Workspace for block splitter */\n    ZSTD_blockSplitCtx blockSplitCtx;\n\n    /* Buffer for output from external sequence producer */\n    ZSTD_Sequence* extSeqBuf;\n    size_t extSeqBufCapacity;\n};\n\ntypedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;\ntypedef enum { ZSTD_tfp_forCCtx, ZSTD_tfp_forCDict } ZSTD_tableFillPurpose_e;\n\ntypedef enum {\n    ZSTD_noDict = 0,\n    ZSTD_extDict = 1,\n    ZSTD_dictMatchState = 2,\n    ZSTD_dedicatedDictSearch = 3\n} ZSTD_dictMode_e;\n\ntypedef enum {\n    ZSTD_cpm_noAttachDict = 0,  /* Compression with ZSTD_noDict or ZSTD_extDict.\n                                 * In this mode we use both the srcSize and the dictSize\n                                 * when selecting and adjusting parameters.\n                                 */\n    ZSTD_cpm_attachDict = 1,    /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch.\n                                 * In this mode we only take the srcSize into account when selecting\n                                 * and adjusting parameters.\n                                 */\n    ZSTD_cpm_createCDict = 2,   /* Creating a CDict.\n                                 * In this mode we take both the source size and the dictionary size\n                                 * into account when selecting and adjusting the parameters.\n                                 */\n    ZSTD_cpm_unknown = 3        /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams.\n                                 * We don't know what these parameters are for. We default to the legacy\n                                 * behavior of taking both the source size and the dict size into account\n                                 * when selecting and adjusting parameters.\n                                 */\n} ZSTD_CParamMode_e;\n\ntypedef size_t (*ZSTD_BlockCompressor_f) (\n        ZSTD_MatchState_t* bs, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nZSTD_BlockCompressor_f ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_ParamSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);\n\n\nMEM_STATIC U32 ZSTD_LLcode(U32 litLength)\n{\n    static const BYTE LL_Code[64] = {  0,  1,  2,  3,  4,  5,  6,  7,\n                                       8,  9, 10, 11, 12, 13, 14, 15,\n                                      16, 16, 17, 17, 18, 18, 19, 19,\n                                      20, 20, 20, 20, 21, 21, 21, 21,\n                                      22, 22, 22, 22, 22, 22, 22, 22,\n                                      23, 23, 23, 23, 23, 23, 23, 23,\n                                      24, 24, 24, 24, 24, 24, 24, 24,\n                                      24, 24, 24, 24, 24, 24, 24, 24 };\n    static const U32 LL_deltaCode = 19;\n    return (litLength > 63) ? ZSTD_highbit32(litLength) + LL_deltaCode : LL_Code[litLength];\n}\n\n/* ZSTD_MLcode() :\n * note : mlBase = matchLength - MINMATCH;\n *        because it's the format it's stored in seqStore->sequences */\nMEM_STATIC U32 ZSTD_MLcode(U32 mlBase)\n{\n    static const BYTE ML_Code[128] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n                                      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n                                      32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37,\n                                      38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39,\n                                      40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n                                      41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,\n                                      42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,\n                                      42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };\n    static const U32 ML_deltaCode = 36;\n    return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];\n}\n\n/* ZSTD_cParam_withinBounds:\n * @return 1 if value is within cParam bounds,\n * 0 otherwise */\nMEM_STATIC int ZSTD_cParam_withinBounds(ZSTD_cParameter cParam, int value)\n{\n    ZSTD_bounds const bounds = ZSTD_cParam_getBounds(cParam);\n    if (ZSTD_isError(bounds.error)) return 0;\n    if (value < bounds.lowerBound) return 0;\n    if (value > bounds.upperBound) return 0;\n    return 1;\n}\n\n/* ZSTD_selectAddr:\n * @return index >= lowLimit ? candidate : backup,\n * tries to force branchless codegen. */\nMEM_STATIC const BYTE*\nZSTD_selectAddr(U32 index, U32 lowLimit, const BYTE* candidate, const BYTE* backup)\n{\n#if defined(__GNUC__) && defined(__x86_64__)\n    __asm__ (\n        \"cmp %1, %2\\n\"\n        \"cmova %3, %0\\n\"\n        : \"+r\"(candidate)\n        : \"r\"(index), \"r\"(lowLimit), \"r\"(backup)\n        );\n    return candidate;\n#else\n    return index >= lowLimit ? candidate : backup;\n#endif\n}\n\n/* ZSTD_noCompressBlock() :\n * Writes uncompressed block to dst buffer from given src.\n * Returns the size of the block */\nMEM_STATIC size_t\nZSTD_noCompressBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize, U32 lastBlock)\n{\n    U32 const cBlockHeader24 = lastBlock + (((U32)bt_raw)<<1) + (U32)(srcSize << 3);\n    DEBUGLOG(5, \"ZSTD_noCompressBlock (srcSize=%zu, dstCapacity=%zu)\", srcSize, dstCapacity);\n    RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity,\n                    dstSize_tooSmall, \"dst buf too small for uncompressed block\");\n    MEM_writeLE24(dst, cBlockHeader24);\n    ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize);\n    return ZSTD_blockHeaderSize + srcSize;\n}\n\nMEM_STATIC size_t\nZSTD_rleCompressBlock(void* dst, size_t dstCapacity, BYTE src, size_t srcSize, U32 lastBlock)\n{\n    BYTE* const op = (BYTE*)dst;\n    U32 const cBlockHeader = lastBlock + (((U32)bt_rle)<<1) + (U32)(srcSize << 3);\n    RETURN_ERROR_IF(dstCapacity < 4, dstSize_tooSmall, \"\");\n    MEM_writeLE24(op, cBlockHeader);\n    op[3] = src;\n    return 4;\n}\n\n\n/* ZSTD_minGain() :\n * minimum compression required\n * to generate a compress block or a compressed literals section.\n * note : use same formula for both situations */\nMEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)\n{\n    U32 const minlog = (strat>=ZSTD_btultra) ? (U32)(strat) - 1 : 6;\n    ZSTD_STATIC_ASSERT(ZSTD_btultra == 8);\n    assert(ZSTD_cParam_withinBounds(ZSTD_c_strategy, (int)strat));\n    return (srcSize >> minlog) + 2;\n}\n\nMEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams)\n{\n    switch (cctxParams->literalCompressionMode) {\n    case ZSTD_ps_enable:\n        return 0;\n    case ZSTD_ps_disable:\n        return 1;\n    default:\n        assert(0 /* impossible: pre-validated */);\n        ZSTD_FALLTHROUGH;\n    case ZSTD_ps_auto:\n        return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);\n    }\n}\n\n/*! ZSTD_safecopyLiterals() :\n *  memcpy() function that won't read beyond more than WILDCOPY_OVERLENGTH bytes past ilimit_w.\n *  Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single\n *  large copies.\n */\nstatic void\nZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w)\n{\n    assert(iend > ilimit_w);\n    if (ip <= ilimit_w) {\n        ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);\n        op += ilimit_w - ip;\n        ip = ilimit_w;\n    }\n    while (ip < iend) *op++ = *ip++;\n}\n\n\n#define REPCODE1_TO_OFFBASE REPCODE_TO_OFFBASE(1)\n#define REPCODE2_TO_OFFBASE REPCODE_TO_OFFBASE(2)\n#define REPCODE3_TO_OFFBASE REPCODE_TO_OFFBASE(3)\n#define REPCODE_TO_OFFBASE(r) (assert((r)>=1), assert((r)<=ZSTD_REP_NUM), (r)) /* accepts IDs 1,2,3 */\n#define OFFSET_TO_OFFBASE(o)  (assert((o)>0), o + ZSTD_REP_NUM)\n#define OFFBASE_IS_OFFSET(o)  ((o) > ZSTD_REP_NUM)\n#define OFFBASE_IS_REPCODE(o) ( 1 <= (o) && (o) <= ZSTD_REP_NUM)\n#define OFFBASE_TO_OFFSET(o)  (assert(OFFBASE_IS_OFFSET(o)), (o) - ZSTD_REP_NUM)\n#define OFFBASE_TO_REPCODE(o) (assert(OFFBASE_IS_REPCODE(o)), (o))  /* returns ID 1,2,3 */\n\n/*! ZSTD_storeSeqOnly() :\n *  Store a sequence (litlen, litPtr, offBase and matchLength) into SeqStore_t.\n *  Literals themselves are not copied, but @litPtr is updated.\n *  @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE().\n *  @matchLength : must be >= MINMATCH\n*/\nHINT_INLINE UNUSED_ATTR void\nZSTD_storeSeqOnly(SeqStore_t* seqStorePtr,\n              size_t litLength,\n              U32 offBase,\n              size_t matchLength)\n{\n    assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);\n\n    /* literal Length */\n    assert(litLength <= ZSTD_BLOCKSIZE_MAX);\n    if (UNLIKELY(litLength>0xFFFF)) {\n        assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */\n        seqStorePtr->longLengthType = ZSTD_llt_literalLength;\n        seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n    }\n    seqStorePtr->sequences[0].litLength = (U16)litLength;\n\n    /* match offset */\n    seqStorePtr->sequences[0].offBase = offBase;\n\n    /* match Length */\n    assert(matchLength <= ZSTD_BLOCKSIZE_MAX);\n    assert(matchLength >= MINMATCH);\n    {   size_t const mlBase = matchLength - MINMATCH;\n        if (UNLIKELY(mlBase>0xFFFF)) {\n            assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */\n            seqStorePtr->longLengthType = ZSTD_llt_matchLength;\n            seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);\n        }\n        seqStorePtr->sequences[0].mlBase = (U16)mlBase;\n    }\n\n    seqStorePtr->sequences++;\n}\n\n/*! ZSTD_storeSeq() :\n *  Store a sequence (litlen, litPtr, offBase and matchLength) into SeqStore_t.\n *  @offBase : Users should employ macros REPCODE_TO_OFFBASE() and OFFSET_TO_OFFBASE().\n *  @matchLength : must be >= MINMATCH\n *  Allowed to over-read literals up to litLimit.\n*/\nHINT_INLINE UNUSED_ATTR void\nZSTD_storeSeq(SeqStore_t* seqStorePtr,\n              size_t litLength, const BYTE* literals, const BYTE* litLimit,\n              U32 offBase,\n              size_t matchLength)\n{\n    BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;\n    BYTE const* const litEnd = literals + litLength;\n#if defined(DEBUGLEVEL) && (DEBUGLEVEL >= 6)\n    static const BYTE* g_start = NULL;\n    if (g_start==NULL) g_start = (const BYTE*)literals;  /* note : index only works for compression within a single segment */\n    {   U32 const pos = (U32)((const BYTE*)literals - g_start);\n        DEBUGLOG(6, \"Cpos%7u :%3u literals, match%4u bytes at offBase%7u\",\n               pos, (U32)litLength, (U32)matchLength, (U32)offBase);\n    }\n#endif\n    assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);\n    /* copy Literals */\n    assert(seqStorePtr->maxNbLit <= 128 KB);\n    assert(seqStorePtr->lit + litLength <= seqStorePtr->litStart + seqStorePtr->maxNbLit);\n    assert(literals + litLength <= litLimit);\n    if (litEnd <= litLimit_w) {\n        /* Common case we can use wildcopy.\n         * First copy 16 bytes, because literals are likely short.\n         */\n        ZSTD_STATIC_ASSERT(WILDCOPY_OVERLENGTH >= 16);\n        ZSTD_copy16(seqStorePtr->lit, literals);\n        if (litLength > 16) {\n            ZSTD_wildcopy(seqStorePtr->lit+16, literals+16, (ptrdiff_t)litLength-16, ZSTD_no_overlap);\n        }\n    } else {\n        ZSTD_safecopyLiterals(seqStorePtr->lit, literals, litEnd, litLimit_w);\n    }\n    seqStorePtr->lit += litLength;\n\n    ZSTD_storeSeqOnly(seqStorePtr, litLength, offBase, matchLength);\n}\n\n/* ZSTD_updateRep() :\n * updates in-place @rep (array of repeat offsets)\n * @offBase : sum-type, using numeric representation of ZSTD_storeSeq()\n */\nMEM_STATIC void\nZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0)\n{\n    if (OFFBASE_IS_OFFSET(offBase)) {  /* full offset */\n        rep[2] = rep[1];\n        rep[1] = rep[0];\n        rep[0] = OFFBASE_TO_OFFSET(offBase);\n    } else {   /* repcode */\n        U32 const repCode = OFFBASE_TO_REPCODE(offBase) - 1 + ll0;\n        if (repCode > 0) {  /* note : if repCode==0, no change */\n            U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];\n            rep[2] = (repCode >= 2) ? rep[1] : rep[2];\n            rep[1] = rep[0];\n            rep[0] = currentOffset;\n        } else {   /* repCode == 0 */\n            /* nothing to do */\n        }\n    }\n}\n\ntypedef struct repcodes_s {\n    U32 rep[3];\n} Repcodes_t;\n\nMEM_STATIC Repcodes_t\nZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase, U32 const ll0)\n{\n    Repcodes_t newReps;\n    ZSTD_memcpy(&newReps, rep, sizeof(newReps));\n    ZSTD_updateRep(newReps.rep, offBase, ll0);\n    return newReps;\n}\n\n\n/*-*************************************\n*  Match length counter\n***************************************/\nMEM_STATIC size_t ZSTD_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* const pInLimit)\n{\n    const BYTE* const pStart = pIn;\n    const BYTE* const pInLoopLimit = pInLimit - (sizeof(size_t)-1);\n\n    if (pIn < pInLoopLimit) {\n        { size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n          if (diff) return ZSTD_NbCommonBytes(diff); }\n        pIn+=sizeof(size_t); pMatch+=sizeof(size_t);\n        while (pIn < pInLoopLimit) {\n            size_t const diff = MEM_readST(pMatch) ^ MEM_readST(pIn);\n            if (!diff) { pIn+=sizeof(size_t); pMatch+=sizeof(size_t); continue; }\n            pIn += ZSTD_NbCommonBytes(diff);\n            return (size_t)(pIn - pStart);\n    }   }\n    if (MEM_64bits() && (pIn<(pInLimit-3)) && (MEM_read32(pMatch) == MEM_read32(pIn))) { pIn+=4; pMatch+=4; }\n    if ((pIn<(pInLimit-1)) && (MEM_read16(pMatch) == MEM_read16(pIn))) { pIn+=2; pMatch+=2; }\n    if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;\n    return (size_t)(pIn - pStart);\n}\n\n/** ZSTD_count_2segments() :\n *  can count match length with `ip` & `match` in 2 different segments.\n *  convention : on reaching mEnd, match count continue starting from iStart\n */\nMEM_STATIC size_t\nZSTD_count_2segments(const BYTE* ip, const BYTE* match,\n                     const BYTE* iEnd, const BYTE* mEnd, const BYTE* iStart)\n{\n    const BYTE* const vEnd = MIN( ip + (mEnd - match), iEnd);\n    size_t const matchLength = ZSTD_count(ip, match, vEnd);\n    if (match + matchLength != mEnd) return matchLength;\n    DEBUGLOG(7, \"ZSTD_count_2segments: found a 2-parts match (current length==%zu)\", matchLength);\n    DEBUGLOG(7, \"distance from match beginning to end dictionary = %i\", (int)(mEnd - match));\n    DEBUGLOG(7, \"distance from current pos to end buffer = %i\", (int)(iEnd - ip));\n    DEBUGLOG(7, \"next byte : ip==%02X, istart==%02X\", ip[matchLength], *iStart);\n    DEBUGLOG(7, \"final match length = %zu\", matchLength + ZSTD_count(ip+matchLength, iStart, iEnd));\n    return matchLength + ZSTD_count(ip+matchLength, iStart, iEnd);\n}\n\n\n/*-*************************************\n *  Hashes\n ***************************************/\nstatic const U32 prime3bytes = 506832829U;\nstatic U32    ZSTD_hash3(U32 u, U32 h, U32 s) { assert(h <= 32); return (((u << (32-24)) * prime3bytes) ^ s)  >> (32-h) ; }\nMEM_STATIC size_t ZSTD_hash3Ptr(const void* ptr, U32 h) { return ZSTD_hash3(MEM_readLE32(ptr), h, 0); } /* only in zstd_opt.h */\nMEM_STATIC size_t ZSTD_hash3PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash3(MEM_readLE32(ptr), h, s); }\n\nstatic const U32 prime4bytes = 2654435761U;\nstatic U32    ZSTD_hash4(U32 u, U32 h, U32 s) { assert(h <= 32); return ((u * prime4bytes) ^ s) >> (32-h) ; }\nstatic size_t ZSTD_hash4Ptr(const void* ptr, U32 h) { return ZSTD_hash4(MEM_readLE32(ptr), h, 0); }\nstatic size_t ZSTD_hash4PtrS(const void* ptr, U32 h, U32 s) { return ZSTD_hash4(MEM_readLE32(ptr), h, s); }\n\nstatic const U64 prime5bytes = 889523592379ULL;\nstatic size_t ZSTD_hash5(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u  << (64-40)) * prime5bytes) ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash5Ptr(const void* p, U32 h) { return ZSTD_hash5(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash5PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash5(MEM_readLE64(p), h, s); }\n\nstatic const U64 prime6bytes = 227718039650203ULL;\nstatic size_t ZSTD_hash6(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u  << (64-48)) * prime6bytes) ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash6Ptr(const void* p, U32 h) { return ZSTD_hash6(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash6PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash6(MEM_readLE64(p), h, s); }\n\nstatic const U64 prime7bytes = 58295818150454627ULL;\nstatic size_t ZSTD_hash7(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u  << (64-56)) * prime7bytes) ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash7Ptr(const void* p, U32 h) { return ZSTD_hash7(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash7PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash7(MEM_readLE64(p), h, s); }\n\nstatic const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL;\nstatic size_t ZSTD_hash8(U64 u, U32 h, U64 s) { assert(h <= 64); return (size_t)((((u) * prime8bytes)  ^ s) >> (64-h)) ; }\nstatic size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h, 0); }\nstatic size_t ZSTD_hash8PtrS(const void* p, U32 h, U64 s) { return ZSTD_hash8(MEM_readLE64(p), h, s); }\n\n\nMEM_STATIC FORCE_INLINE_ATTR\nsize_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls)\n{\n    /* Although some of these hashes do support hBits up to 64, some do not.\n     * To be on the safe side, always avoid hBits > 32. */\n    assert(hBits <= 32);\n\n    switch(mls)\n    {\n    default:\n    case 4: return ZSTD_hash4Ptr(p, hBits);\n    case 5: return ZSTD_hash5Ptr(p, hBits);\n    case 6: return ZSTD_hash6Ptr(p, hBits);\n    case 7: return ZSTD_hash7Ptr(p, hBits);\n    case 8: return ZSTD_hash8Ptr(p, hBits);\n    }\n}\n\nMEM_STATIC FORCE_INLINE_ATTR\nsize_t ZSTD_hashPtrSalted(const void* p, U32 hBits, U32 mls, const U64 hashSalt) {\n    /* Although some of these hashes do support hBits up to 64, some do not.\n     * To be on the safe side, always avoid hBits > 32. */\n    assert(hBits <= 32);\n\n    switch(mls)\n    {\n        default:\n        case 4: return ZSTD_hash4PtrS(p, hBits, (U32)hashSalt);\n        case 5: return ZSTD_hash5PtrS(p, hBits, hashSalt);\n        case 6: return ZSTD_hash6PtrS(p, hBits, hashSalt);\n        case 7: return ZSTD_hash7PtrS(p, hBits, hashSalt);\n        case 8: return ZSTD_hash8PtrS(p, hBits, hashSalt);\n    }\n}\n\n\n/** ZSTD_ipow() :\n * Return base^exponent.\n */\nstatic U64 ZSTD_ipow(U64 base, U64 exponent)\n{\n    U64 power = 1;\n    while (exponent) {\n      if (exponent & 1) power *= base;\n      exponent >>= 1;\n      base *= base;\n    }\n    return power;\n}\n\n#define ZSTD_ROLL_HASH_CHAR_OFFSET 10\n\n/** ZSTD_rollingHash_append() :\n * Add the buffer to the hash value.\n */\nstatic U64 ZSTD_rollingHash_append(U64 hash, void const* buf, size_t size)\n{\n    BYTE const* istart = (BYTE const*)buf;\n    size_t pos;\n    for (pos = 0; pos < size; ++pos) {\n        hash *= prime8bytes;\n        hash += istart[pos] + ZSTD_ROLL_HASH_CHAR_OFFSET;\n    }\n    return hash;\n}\n\n/** ZSTD_rollingHash_compute() :\n * Compute the rolling hash value of the buffer.\n */\nMEM_STATIC U64 ZSTD_rollingHash_compute(void const* buf, size_t size)\n{\n    return ZSTD_rollingHash_append(0, buf, size);\n}\n\n/** ZSTD_rollingHash_primePower() :\n * Compute the primePower to be passed to ZSTD_rollingHash_rotate() for a hash\n * over a window of length bytes.\n */\nMEM_STATIC U64 ZSTD_rollingHash_primePower(U32 length)\n{\n    return ZSTD_ipow(prime8bytes, length - 1);\n}\n\n/** ZSTD_rollingHash_rotate() :\n * Rotate the rolling hash by one byte.\n */\nMEM_STATIC U64 ZSTD_rollingHash_rotate(U64 hash, BYTE toRemove, BYTE toAdd, U64 primePower)\n{\n    hash -= (toRemove + ZSTD_ROLL_HASH_CHAR_OFFSET) * primePower;\n    hash *= prime8bytes;\n    hash += toAdd + ZSTD_ROLL_HASH_CHAR_OFFSET;\n    return hash;\n}\n\n/*-*************************************\n*  Round buffer management\n***************************************/\n/* Max @current value allowed:\n * In 32-bit mode: we want to avoid crossing the 2 GB limit,\n *                 reducing risks of side effects in case of signed operations on indexes.\n * In 64-bit mode: we want to ensure that adding the maximum job size (512 MB)\n *                 doesn't overflow U32 index capacity (4 GB) */\n#define ZSTD_CURRENT_MAX (MEM_64bits() ? 3500U MB : 2000U MB)\n/* Maximum chunk size before overflow correction needs to be called again */\n#define ZSTD_CHUNKSIZE_MAX                                                     \\\n    ( ((U32)-1)                  /* Maximum ending current index */            \\\n    - ZSTD_CURRENT_MAX)          /* Maximum beginning lowLimit */\n\n/**\n * ZSTD_window_clear():\n * Clears the window containing the history by simply setting it to empty.\n */\nMEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)\n{\n    size_t const endT = (size_t)(window->nextSrc - window->base);\n    U32 const end = (U32)endT;\n\n    window->lowLimit = end;\n    window->dictLimit = end;\n}\n\nMEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)\n{\n    return window.dictLimit == ZSTD_WINDOW_START_INDEX &&\n           window.lowLimit == ZSTD_WINDOW_START_INDEX &&\n           (window.nextSrc - window.base) == ZSTD_WINDOW_START_INDEX;\n}\n\n/**\n * ZSTD_window_hasExtDict():\n * Returns non-zero if the window has a non-empty extDict.\n */\nMEM_STATIC U32 ZSTD_window_hasExtDict(ZSTD_window_t const window)\n{\n    return window.lowLimit < window.dictLimit;\n}\n\n/**\n * ZSTD_matchState_dictMode():\n * Inspects the provided matchState and figures out what dictMode should be\n * passed to the compressor.\n */\nMEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_MatchState_t *ms)\n{\n    return ZSTD_window_hasExtDict(ms->window) ?\n        ZSTD_extDict :\n        ms->dictMatchState != NULL ?\n            (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) :\n            ZSTD_noDict;\n}\n\n/* Defining this macro to non-zero tells zstd to run the overflow correction\n * code much more frequently. This is very inefficient, and should only be\n * used for tests and fuzzers.\n */\n#ifndef ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY\n#  ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n#    define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 1\n#  else\n#    define ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY 0\n#  endif\n#endif\n\n/**\n * ZSTD_window_canOverflowCorrect():\n * Returns non-zero if the indices are large enough for overflow correction\n * to work correctly without impacting compression ratio.\n */\nMEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,\n                                              U32 cycleLog,\n                                              U32 maxDist,\n                                              U32 loadedDictEnd,\n                                              void const* src)\n{\n    U32 const cycleSize = 1u << cycleLog;\n    U32 const curr = (U32)((BYTE const*)src - window.base);\n    U32 const minIndexToOverflowCorrect = cycleSize\n                                        + MAX(maxDist, cycleSize)\n                                        + ZSTD_WINDOW_START_INDEX;\n\n    /* Adjust the min index to backoff the overflow correction frequency,\n     * so we don't waste too much CPU in overflow correction. If this\n     * computation overflows we don't really care, we just need to make\n     * sure it is at least minIndexToOverflowCorrect.\n     */\n    U32 const adjustment = window.nbOverflowCorrections + 1;\n    U32 const adjustedIndex = MAX(minIndexToOverflowCorrect * adjustment,\n                                  minIndexToOverflowCorrect);\n    U32 const indexLargeEnough = curr > adjustedIndex;\n\n    /* Only overflow correct early if the dictionary is invalidated already,\n     * so we don't hurt compression ratio.\n     */\n    U32 const dictionaryInvalidated = curr > maxDist + loadedDictEnd;\n\n    return indexLargeEnough && dictionaryInvalidated;\n}\n\n/**\n * ZSTD_window_needOverflowCorrection():\n * Returns non-zero if the indices are getting too large and need overflow\n * protection.\n */\nMEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window,\n                                                  U32 cycleLog,\n                                                  U32 maxDist,\n                                                  U32 loadedDictEnd,\n                                                  void const* src,\n                                                  void const* srcEnd)\n{\n    U32 const curr = (U32)((BYTE const*)srcEnd - window.base);\n    if (ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {\n        if (ZSTD_window_canOverflowCorrect(window, cycleLog, maxDist, loadedDictEnd, src)) {\n            return 1;\n        }\n    }\n    return curr > ZSTD_CURRENT_MAX;\n}\n\n/**\n * ZSTD_window_correctOverflow():\n * Reduces the indices to protect from index overflow.\n * Returns the correction made to the indices, which must be applied to every\n * stored index.\n *\n * The least significant cycleLog bits of the indices must remain the same,\n * which may be 0. Every index up to maxDist in the past must be valid.\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,\n                                           U32 maxDist, void const* src)\n{\n    /* preemptive overflow correction:\n     * 1. correction is large enough:\n     *    lowLimit > (3<<29) ==> current > 3<<29 + 1<<windowLog\n     *    1<<windowLog <= newCurrent < 1<<chainLog + 1<<windowLog\n     *\n     *    current - newCurrent\n     *    > (3<<29 + 1<<windowLog) - (1<<windowLog + 1<<chainLog)\n     *    > (3<<29) - (1<<chainLog)\n     *    > (3<<29) - (1<<30)             (NOTE: chainLog <= 30)\n     *    > 1<<29\n     *\n     * 2. (ip+ZSTD_CHUNKSIZE_MAX - cctx->base) doesn't overflow:\n     *    After correction, current is less than (1<<chainLog + 1<<windowLog).\n     *    In 64-bit mode we are safe, because we have 64-bit ptrdiff_t.\n     *    In 32-bit mode we are safe, because (chainLog <= 29), so\n     *    ip+ZSTD_CHUNKSIZE_MAX - cctx->base < 1<<32.\n     * 3. (cctx->lowLimit + 1<<windowLog) < 1<<32:\n     *    windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32.\n     */\n    U32 const cycleSize = 1u << cycleLog;\n    U32 const cycleMask = cycleSize - 1;\n    U32 const curr = (U32)((BYTE const*)src - window->base);\n    U32 const currentCycle = curr & cycleMask;\n    /* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */\n    U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX\n                                     ? MAX(cycleSize, ZSTD_WINDOW_START_INDEX)\n                                     : 0;\n    U32 const newCurrent = currentCycle\n                         + currentCycleCorrection\n                         + MAX(maxDist, cycleSize);\n    U32 const correction = curr - newCurrent;\n    /* maxDist must be a power of two so that:\n     *   (newCurrent & cycleMask) == (curr & cycleMask)\n     * This is required to not corrupt the chains / binary tree.\n     */\n    assert((maxDist & (maxDist - 1)) == 0);\n    assert((curr & cycleMask) == (newCurrent & cycleMask));\n    assert(curr > newCurrent);\n    if (!ZSTD_WINDOW_OVERFLOW_CORRECT_FREQUENTLY) {\n        /* Loose bound, should be around 1<<29 (see above) */\n        assert(correction > 1<<28);\n    }\n\n    window->base += correction;\n    window->dictBase += correction;\n    if (window->lowLimit < correction + ZSTD_WINDOW_START_INDEX) {\n        window->lowLimit = ZSTD_WINDOW_START_INDEX;\n    } else {\n        window->lowLimit -= correction;\n    }\n    if (window->dictLimit < correction + ZSTD_WINDOW_START_INDEX) {\n        window->dictLimit = ZSTD_WINDOW_START_INDEX;\n    } else {\n        window->dictLimit -= correction;\n    }\n\n    /* Ensure we can still reference the full window. */\n    assert(newCurrent >= maxDist);\n    assert(newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX);\n    /* Ensure that lowLimit and dictLimit didn't underflow. */\n    assert(window->lowLimit <= newCurrent);\n    assert(window->dictLimit <= newCurrent);\n\n    ++window->nbOverflowCorrections;\n\n    DEBUGLOG(4, \"Correction of 0x%x bytes to lowLimit=0x%x\", correction,\n             window->lowLimit);\n    return correction;\n}\n\n/**\n * ZSTD_window_enforceMaxDist():\n * Updates lowLimit so that:\n *    (srcEnd - base) - lowLimit == maxDist + loadedDictEnd\n *\n * It ensures index is valid as long as index >= lowLimit.\n * This must be called before a block compression call.\n *\n * loadedDictEnd is only defined if a dictionary is in use for current compression.\n * As the name implies, loadedDictEnd represents the index at end of dictionary.\n * The value lies within context's referential, it can be directly compared to blockEndIdx.\n *\n * If loadedDictEndPtr is NULL, no dictionary is in use, and we use loadedDictEnd == 0.\n * If loadedDictEndPtr is not NULL, we set it to zero after updating lowLimit.\n * This is because dictionaries are allowed to be referenced fully\n * as long as the last byte of the dictionary is in the window.\n * Once input has progressed beyond window size, dictionary cannot be referenced anymore.\n *\n * In normal dict mode, the dictionary lies between lowLimit and dictLimit.\n * In dictMatchState mode, lowLimit and dictLimit are the same,\n * and the dictionary is below them.\n * forceWindow and dictMatchState are therefore incompatible.\n */\nMEM_STATIC void\nZSTD_window_enforceMaxDist(ZSTD_window_t* window,\n                     const void* blockEnd,\n                           U32   maxDist,\n                           U32*  loadedDictEndPtr,\n                     const ZSTD_MatchState_t** dictMatchStatePtr)\n{\n    U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);\n    U32 const loadedDictEnd = (loadedDictEndPtr != NULL) ? *loadedDictEndPtr : 0;\n    DEBUGLOG(5, \"ZSTD_window_enforceMaxDist: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u\",\n                (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);\n\n    /* - When there is no dictionary : loadedDictEnd == 0.\n         In which case, the test (blockEndIdx > maxDist) is merely to avoid\n         overflowing next operation `newLowLimit = blockEndIdx - maxDist`.\n       - When there is a standard dictionary :\n         Index referential is copied from the dictionary,\n         which means it starts from 0.\n         In which case, loadedDictEnd == dictSize,\n         and it makes sense to compare `blockEndIdx > maxDist + dictSize`\n         since `blockEndIdx` also starts from zero.\n       - When there is an attached dictionary :\n         loadedDictEnd is expressed within the referential of the context,\n         so it can be directly compared against blockEndIdx.\n    */\n    if (blockEndIdx > maxDist + loadedDictEnd) {\n        U32 const newLowLimit = blockEndIdx - maxDist;\n        if (window->lowLimit < newLowLimit) window->lowLimit = newLowLimit;\n        if (window->dictLimit < window->lowLimit) {\n            DEBUGLOG(5, \"Update dictLimit to match lowLimit, from %u to %u\",\n                        (unsigned)window->dictLimit, (unsigned)window->lowLimit);\n            window->dictLimit = window->lowLimit;\n        }\n        /* On reaching window size, dictionaries are invalidated */\n        if (loadedDictEndPtr) *loadedDictEndPtr = 0;\n        if (dictMatchStatePtr) *dictMatchStatePtr = NULL;\n    }\n}\n\n/* Similar to ZSTD_window_enforceMaxDist(),\n * but only invalidates dictionary\n * when input progresses beyond window size.\n * assumption : loadedDictEndPtr and dictMatchStatePtr are valid (non NULL)\n *              loadedDictEnd uses same referential as window->base\n *              maxDist is the window size */\nMEM_STATIC void\nZSTD_checkDictValidity(const ZSTD_window_t* window,\n                       const void* blockEnd,\n                             U32   maxDist,\n                             U32*  loadedDictEndPtr,\n                       const ZSTD_MatchState_t** dictMatchStatePtr)\n{\n    assert(loadedDictEndPtr != NULL);\n    assert(dictMatchStatePtr != NULL);\n    {   U32 const blockEndIdx = (U32)((BYTE const*)blockEnd - window->base);\n        U32 const loadedDictEnd = *loadedDictEndPtr;\n        DEBUGLOG(5, \"ZSTD_checkDictValidity: blockEndIdx=%u, maxDist=%u, loadedDictEnd=%u\",\n                    (unsigned)blockEndIdx, (unsigned)maxDist, (unsigned)loadedDictEnd);\n        assert(blockEndIdx >= loadedDictEnd);\n\n        if (blockEndIdx > loadedDictEnd + maxDist || loadedDictEnd != window->dictLimit) {\n            /* On reaching window size, dictionaries are invalidated.\n             * For simplification, if window size is reached anywhere within next block,\n             * the dictionary is invalidated for the full block.\n             *\n             * We also have to invalidate the dictionary if ZSTD_window_update() has detected\n             * non-contiguous segments, which means that loadedDictEnd != window->dictLimit.\n             * loadedDictEnd may be 0, if forceWindow is true, but in that case we never use\n             * dictMatchState, so setting it to NULL is not a problem.\n             */\n            DEBUGLOG(6, \"invalidating dictionary for current block (distance > windowSize)\");\n            *loadedDictEndPtr = 0;\n            *dictMatchStatePtr = NULL;\n        } else {\n            if (*loadedDictEndPtr != 0) {\n                DEBUGLOG(6, \"dictionary considered valid for current block\");\n    }   }   }\n}\n\nMEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {\n    ZSTD_memset(window, 0, sizeof(*window));\n    window->base = (BYTE const*)\" \";\n    window->dictBase = (BYTE const*)\" \";\n    ZSTD_STATIC_ASSERT(ZSTD_DUBT_UNSORTED_MARK < ZSTD_WINDOW_START_INDEX); /* Start above ZSTD_DUBT_UNSORTED_MARK */\n    window->dictLimit = ZSTD_WINDOW_START_INDEX;    /* start from >0, so that 1st position is valid */\n    window->lowLimit = ZSTD_WINDOW_START_INDEX;     /* it ensures first and later CCtx usages compress the same */\n    window->nextSrc = window->base + ZSTD_WINDOW_START_INDEX;   /* see issue #1241 */\n    window->nbOverflowCorrections = 0;\n}\n\n/**\n * ZSTD_window_update():\n * Updates the window by appending [src, src + srcSize) to the window.\n * If it is not contiguous, the current prefix becomes the extDict, and we\n * forget about the extDict. Handles overlap of the prefix and extDict.\n * Returns non-zero if the segment is contiguous.\n */\nMEM_STATIC\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_window_update(ZSTD_window_t* window,\n                 const void* src, size_t srcSize,\n                       int forceNonContiguous)\n{\n    BYTE const* const ip = (BYTE const*)src;\n    U32 contiguous = 1;\n    DEBUGLOG(5, \"ZSTD_window_update\");\n    if (srcSize == 0)\n        return contiguous;\n    assert(window->base != NULL);\n    assert(window->dictBase != NULL);\n    /* Check if blocks follow each other */\n    if (src != window->nextSrc || forceNonContiguous) {\n        /* not contiguous */\n        size_t const distanceFromBase = (size_t)(window->nextSrc - window->base);\n        DEBUGLOG(5, \"Non contiguous blocks, new segment starts at %u\", window->dictLimit);\n        window->lowLimit = window->dictLimit;\n        assert(distanceFromBase == (size_t)(U32)distanceFromBase);  /* should never overflow */\n        window->dictLimit = (U32)distanceFromBase;\n        window->dictBase = window->base;\n        window->base = ip - distanceFromBase;\n        /* ms->nextToUpdate = window->dictLimit; */\n        if (window->dictLimit - window->lowLimit < HASH_READ_SIZE) window->lowLimit = window->dictLimit;   /* too small extDict */\n        contiguous = 0;\n    }\n    window->nextSrc = ip + srcSize;\n    /* if input and dictionary overlap : reduce dictionary (area presumed modified by input) */\n    if ( (ip+srcSize > window->dictBase + window->lowLimit)\n       & (ip < window->dictBase + window->dictLimit)) {\n        size_t const highInputIdx = (size_t)((ip + srcSize) - window->dictBase);\n        U32 const lowLimitMax = (highInputIdx > (size_t)window->dictLimit) ? window->dictLimit : (U32)highInputIdx;\n        assert(highInputIdx < UINT_MAX);\n        window->lowLimit = lowLimitMax;\n        DEBUGLOG(5, \"Overlapping extDict and input : new lowLimit = %u\", window->lowLimit);\n    }\n    return contiguous;\n}\n\n/**\n * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix.\n */\nMEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog)\n{\n    U32 const maxDistance = 1U << windowLog;\n    U32 const lowestValid = ms->window.lowLimit;\n    U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    U32 const isDictionary = (ms->loadedDictEnd != 0);\n    /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary\n     * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't\n     * valid for the entire block. So this check is sufficient to find the lowest valid match index.\n     */\n    U32 const matchLowest = isDictionary ? lowestValid : withinWindow;\n    return matchLowest;\n}\n\n/**\n * Returns the lowest allowed match index in the prefix.\n */\nMEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_MatchState_t* ms, U32 curr, unsigned windowLog)\n{\n    U32    const maxDistance = 1U << windowLog;\n    U32    const lowestValid = ms->window.dictLimit;\n    U32    const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    U32    const isDictionary = (ms->loadedDictEnd != 0);\n    /* When computing the lowest prefix index we need to take the dictionary into account to handle\n     * the edge case where the dictionary and the source are contiguous in memory.\n     */\n    U32    const matchLowest = isDictionary ? lowestValid : withinWindow;\n    return matchLowest;\n}\n\n/* index_safety_check:\n * intentional underflow : ensure repIndex isn't overlapping dict + prefix\n * @return 1 if values are not overlapping,\n * 0 otherwise */\nMEM_STATIC int ZSTD_index_overlap_check(const U32 prefixLowestIndex, const U32 repIndex) {\n    return ((U32)((prefixLowestIndex-1)  - repIndex) >= 3);\n}\n\n\n/* debug functions */\n#if (DEBUGLEVEL>=2)\n\nMEM_STATIC double ZSTD_fWeight(U32 rawStat)\n{\n    U32 const fp_accuracy = 8;\n    U32 const fp_multiplier = (1 << fp_accuracy);\n    U32 const newStat = rawStat + 1;\n    U32 const hb = ZSTD_highbit32(newStat);\n    U32 const BWeight = hb * fp_multiplier;\n    U32 const FWeight = (newStat << fp_accuracy) >> hb;\n    U32 const weight = BWeight + FWeight;\n    assert(hb + fp_accuracy < 31);\n    return (double)weight / fp_multiplier;\n}\n\n/* display a table content,\n * listing each element, its frequency, and its predicted bit cost */\nMEM_STATIC void ZSTD_debugTable(const U32* table, U32 max)\n{\n    unsigned u, sum;\n    for (u=0, sum=0; u<=max; u++) sum += table[u];\n    DEBUGLOG(2, \"total nb elts: %u\", sum);\n    for (u=0; u<=max; u++) {\n        DEBUGLOG(2, \"%2u: %5u  (%.2f)\",\n                u, table[u], ZSTD_fWeight(sum) - ZSTD_fWeight(table[u]) );\n    }\n}\n\n#endif\n\n/* Short Cache */\n\n/* Normally, zstd matchfinders follow this flow:\n *     1. Compute hash at ip\n *     2. Load index from hashTable[hash]\n *     3. Check if *ip == *(base + index)\n * In dictionary compression, loading *(base + index) is often an L2 or even L3 miss.\n *\n * Short cache is an optimization which allows us to avoid step 3 most of the time\n * when the data doesn't actually match. With short cache, the flow becomes:\n *     1. Compute (hash, currentTag) at ip. currentTag is an 8-bit independent hash at ip.\n *     2. Load (index, matchTag) from hashTable[hash]. See ZSTD_writeTaggedIndex to understand how this works.\n *     3. Only if currentTag == matchTag, check *ip == *(base + index). Otherwise, continue.\n *\n * Currently, short cache is only implemented in CDict hashtables. Thus, its use is limited to\n * dictMatchState matchfinders.\n */\n#define ZSTD_SHORT_CACHE_TAG_BITS 8\n#define ZSTD_SHORT_CACHE_TAG_MASK ((1u << ZSTD_SHORT_CACHE_TAG_BITS) - 1)\n\n/* Helper function for ZSTD_fillHashTable and ZSTD_fillDoubleHashTable.\n * Unpacks hashAndTag into (hash, tag), then packs (index, tag) into hashTable[hash]. */\nMEM_STATIC void ZSTD_writeTaggedIndex(U32* const hashTable, size_t hashAndTag, U32 index) {\n    size_t const hash = hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS;\n    U32 const tag = (U32)(hashAndTag & ZSTD_SHORT_CACHE_TAG_MASK);\n    assert(index >> (32 - ZSTD_SHORT_CACHE_TAG_BITS) == 0);\n    hashTable[hash] = (index << ZSTD_SHORT_CACHE_TAG_BITS) | tag;\n}\n\n/* Helper function for short cache matchfinders.\n * Unpacks tag1 and tag2 from lower bits of packedTag1 and packedTag2, then checks if the tags match. */\nMEM_STATIC int ZSTD_comparePackedTags(size_t packedTag1, size_t packedTag2) {\n    U32 const tag1 = packedTag1 & ZSTD_SHORT_CACHE_TAG_MASK;\n    U32 const tag2 = packedTag2 & ZSTD_SHORT_CACHE_TAG_MASK;\n    return tag1 == tag2;\n}\n\n/* ===============================================================\n * Shared internal declarations\n * These prototypes may be called from sources not in lib/compress\n * =============================================================== */\n\n/* ZSTD_loadCEntropy() :\n * dict : must point at beginning of a valid zstd dictionary.\n * return : size of dictionary header (size of magic number + dict ID + entropy tables)\n * assumptions : magic number supposed already checked\n *               and dictSize >= 8 */\nsize_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace,\n                         const void* const dict, size_t dictSize);\n\nvoid ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs);\n\ntypedef struct {\n    U32 idx;            /* Index in array of ZSTD_Sequence */\n    U32 posInSequence;  /* Position within sequence at idx */\n    size_t posInSrc;    /* Number of bytes given by sequences provided so far */\n} ZSTD_SequencePosition;\n\n/* for benchmark */\nsize_t ZSTD_convertBlockSequences(ZSTD_CCtx* cctx,\n                        const ZSTD_Sequence* const inSeqs, size_t nbSequences,\n                        int const repcodeResolution);\n\ntypedef struct {\n    size_t nbSequences;\n    size_t blockSize;\n    size_t litSize;\n} BlockSummary;\n\nBlockSummary ZSTD_get1BlockSummary(const ZSTD_Sequence* seqs, size_t nbSeqs);\n\n/* ==============================================================\n * Private declarations\n * These prototypes shall only be called from within lib/compress\n * ============================================================== */\n\n/* ZSTD_getCParamsFromCCtxParams() :\n * cParams are built depending on compressionLevel, src size hints,\n * LDM and manually set compression parameters.\n * Note: srcSizeHint == 0 means 0!\n */\nZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(\n        const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_CParamMode_e mode);\n\n/*! ZSTD_initCStream_internal() :\n *  Private use only. Init streaming operation.\n *  expects params to be valid.\n *  must receive dict, or cdict, or none, but not both.\n *  @return : 0, or an error code */\nsize_t ZSTD_initCStream_internal(ZSTD_CStream* zcs,\n                     const void* dict, size_t dictSize,\n                     const ZSTD_CDict* cdict,\n                     const ZSTD_CCtx_params* params, unsigned long long pledgedSrcSize);\n\nvoid ZSTD_resetSeqStore(SeqStore_t* ssPtr);\n\n/*! ZSTD_getCParamsFromCDict() :\n *  as the name implies */\nZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict);\n\n/* ZSTD_compressBegin_advanced_internal() :\n * Private use only. To be called from zstdmt_compress.c. */\nsize_t ZSTD_compressBegin_advanced_internal(ZSTD_CCtx* cctx,\n                                    const void* dict, size_t dictSize,\n                                    ZSTD_dictContentType_e dictContentType,\n                                    ZSTD_dictTableLoadMethod_e dtlm,\n                                    const ZSTD_CDict* cdict,\n                                    const ZSTD_CCtx_params* params,\n                                    unsigned long long pledgedSrcSize);\n\n/* ZSTD_compress_advanced_internal() :\n * Private use only. To be called from zstdmt_compress.c. */\nsize_t ZSTD_compress_advanced_internal(ZSTD_CCtx* cctx,\n                                       void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize,\n                                 const void* dict,size_t dictSize,\n                                 const ZSTD_CCtx_params* params);\n\n\n/* ZSTD_writeLastEmptyBlock() :\n * output an empty Block with end-of-frame mark to complete a frame\n * @return : size of data written into `dst` (== ZSTD_blockHeaderSize (defined in zstd_internal.h))\n *           or an error code if `dstCapacity` is too small (<ZSTD_blockHeaderSize)\n */\nsize_t ZSTD_writeLastEmptyBlock(void* dst, size_t dstCapacity);\n\n\n/* ZSTD_referenceExternalSequences() :\n * Must be called before starting a compression operation.\n * seqs must parse a prefix of the source.\n * This cannot be used when long range matching is enabled.\n * Zstd will use these sequences, and pass the literals to a secondary block\n * compressor.\n * NOTE: seqs are not verified! Invalid sequences can cause out-of-bounds memory\n * access and data corruption.\n */\nvoid ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSeq);\n\n/** ZSTD_cycleLog() :\n *  condition for correct operation : hashLog > 1 */\nU32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat);\n\n/** ZSTD_CCtx_trace() :\n *  Trace the end of a compression call.\n */\nvoid ZSTD_CCtx_trace(ZSTD_CCtx* cctx, size_t extraCSize);\n\n/* Returns 1 if an external sequence producer is registered, otherwise returns 0. */\nMEM_STATIC int ZSTD_hasExtSeqProd(const ZSTD_CCtx_params* params) {\n    return params->extSeqProdFunc != NULL;\n}\n\n/* ===============================================================\n * Deprecated definitions that are still used internally to avoid\n * deprecation warnings. These functions are exactly equivalent to\n * their public variants, but avoid the deprecation warnings.\n * =============================================================== */\n\nsize_t ZSTD_compressBegin_usingCDict_deprecated(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);\n\nsize_t ZSTD_compressContinue_public(ZSTD_CCtx* cctx,\n                                    void* dst, size_t dstCapacity,\n                              const void* src, size_t srcSize);\n\nsize_t ZSTD_compressEnd_public(ZSTD_CCtx* cctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize);\n\nsize_t ZSTD_compressBlock_deprecated(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n#endif /* ZSTD_COMPRESS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress_literals.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /*-*************************************\n *  Dependencies\n ***************************************/\n#include \"zstd_compress_literals.h\"\n\n\n/* **************************************************************\n*  Debug Traces\n****************************************************************/\n#if DEBUGLEVEL >= 2\n\nstatic size_t showHexa(const void* src, size_t srcSize)\n{\n    const BYTE* const ip = (const BYTE*)src;\n    size_t u;\n    for (u=0; u<srcSize; u++) {\n        RAWLOG(5, \" %02X\", ip[u]); (void)ip;\n    }\n    RAWLOG(5, \" \\n\");\n    return srcSize;\n}\n\n#endif\n\n\n/* **************************************************************\n*  Literals compression - special cases\n****************************************************************/\nsize_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    U32   const flSize = 1 + (srcSize>31) + (srcSize>4095);\n\n    DEBUGLOG(5, \"ZSTD_noCompressLiterals: srcSize=%zu, dstCapacity=%zu\", srcSize, dstCapacity);\n\n    RETURN_ERROR_IF(srcSize + flSize > dstCapacity, dstSize_tooSmall, \"\");\n\n    switch(flSize)\n    {\n        case 1: /* 2 - 1 - 5 */\n            ostart[0] = (BYTE)((U32)set_basic + (srcSize<<3));\n            break;\n        case 2: /* 2 - 2 - 12 */\n            MEM_writeLE16(ostart, (U16)((U32)set_basic + (1<<2) + (srcSize<<4)));\n            break;\n        case 3: /* 2 - 2 - 20 */\n            MEM_writeLE32(ostart, (U32)((U32)set_basic + (3<<2) + (srcSize<<4)));\n            break;\n        default:   /* not necessary : flSize is {1,2,3} */\n            assert(0);\n    }\n\n    ZSTD_memcpy(ostart + flSize, src, srcSize);\n    DEBUGLOG(5, \"Raw (uncompressed) literals: %u -> %u\", (U32)srcSize, (U32)(srcSize + flSize));\n    return srcSize + flSize;\n}\n\nstatic int allBytesIdentical(const void* src, size_t srcSize)\n{\n    assert(srcSize >= 1);\n    assert(src != NULL);\n    {   const BYTE b = ((const BYTE*)src)[0];\n        size_t p;\n        for (p=1; p<srcSize; p++) {\n            if (((const BYTE*)src)[p] != b) return 0;\n        }\n        return 1;\n    }\n}\n\nsize_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    U32   const flSize = 1 + (srcSize>31) + (srcSize>4095);\n\n    assert(dstCapacity >= 4); (void)dstCapacity;\n    assert(allBytesIdentical(src, srcSize));\n\n    switch(flSize)\n    {\n        case 1: /* 2 - 1 - 5 */\n            ostart[0] = (BYTE)((U32)set_rle + (srcSize<<3));\n            break;\n        case 2: /* 2 - 2 - 12 */\n            MEM_writeLE16(ostart, (U16)((U32)set_rle + (1<<2) + (srcSize<<4)));\n            break;\n        case 3: /* 2 - 2 - 20 */\n            MEM_writeLE32(ostart, (U32)((U32)set_rle + (3<<2) + (srcSize<<4)));\n            break;\n        default:   /* not necessary : flSize is {1,2,3} */\n            assert(0);\n    }\n\n    ostart[flSize] = *(const BYTE*)src;\n    DEBUGLOG(5, \"RLE : Repeated Literal (%02X: %u times) -> %u bytes encoded\", ((const BYTE*)src)[0], (U32)srcSize, (U32)flSize + 1);\n    return flSize+1;\n}\n\n/* ZSTD_minLiteralsToCompress() :\n * returns minimal amount of literals\n * for literal compression to even be attempted.\n * Minimum is made tighter as compression strategy increases.\n */\nstatic size_t\nZSTD_minLiteralsToCompress(ZSTD_strategy strategy, HUF_repeat huf_repeat)\n{\n    assert((int)strategy >= 0);\n    assert((int)strategy <= 9);\n    /* btultra2 : min 8 bytes;\n     * then 2x larger for each successive compression strategy\n     * max threshold 64 bytes */\n    {   int const shift = MIN(9-(int)strategy, 3);\n        size_t const mintc = (huf_repeat == HUF_repeat_valid) ? 6 : (size_t)8 << shift;\n        DEBUGLOG(7, \"minLiteralsToCompress = %zu\", mintc);\n        return mintc;\n    }\n}\n\nsize_t ZSTD_compressLiterals (\n                  void* dst, size_t dstCapacity,\n            const void* src, size_t srcSize,\n                  void* entropyWorkspace, size_t entropyWorkspaceSize,\n            const ZSTD_hufCTables_t* prevHuf,\n                  ZSTD_hufCTables_t* nextHuf,\n                  ZSTD_strategy strategy,\n                  int disableLiteralCompression,\n                  int suspectUncompressible,\n                  int bmi2)\n{\n    size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);\n    BYTE*  const ostart = (BYTE*)dst;\n    U32 singleStream = srcSize < 256;\n    SymbolEncodingType_e hType = set_compressed;\n    size_t cLitSize;\n\n    DEBUGLOG(5,\"ZSTD_compressLiterals (disableLiteralCompression=%i, srcSize=%u, dstCapacity=%zu)\",\n                disableLiteralCompression, (U32)srcSize, dstCapacity);\n\n    DEBUGLOG(6, \"Completed literals listing (%zu bytes)\", showHexa(src, srcSize));\n\n    /* Prepare nextEntropy assuming reusing the existing table */\n    ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n\n    if (disableLiteralCompression)\n        return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);\n\n    /* if too small, don't even attempt compression (speed opt) */\n    if (srcSize < ZSTD_minLiteralsToCompress(strategy, prevHuf->repeatMode))\n        return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);\n\n    RETURN_ERROR_IF(dstCapacity < lhSize+1, dstSize_tooSmall, \"not enough space for compression\");\n    {   HUF_repeat repeat = prevHuf->repeatMode;\n        int const flags = 0\n            | (bmi2 ? HUF_flags_bmi2 : 0)\n            | (strategy < ZSTD_lazy && srcSize <= 1024 ? HUF_flags_preferRepeat : 0)\n            | (strategy >= HUF_OPTIMAL_DEPTH_THRESHOLD ? HUF_flags_optimalDepth : 0)\n            | (suspectUncompressible ? HUF_flags_suspectUncompressible : 0);\n\n        typedef size_t (*huf_compress_f)(void*, size_t, const void*, size_t, unsigned, unsigned, void*, size_t, HUF_CElt*, HUF_repeat*, int);\n        huf_compress_f huf_compress;\n        if (repeat == HUF_repeat_valid && lhSize == 3) singleStream = 1;\n        huf_compress = singleStream ? HUF_compress1X_repeat : HUF_compress4X_repeat;\n        cLitSize = huf_compress(ostart+lhSize, dstCapacity-lhSize,\n                                src, srcSize,\n                                HUF_SYMBOLVALUE_MAX, LitHufLog,\n                                entropyWorkspace, entropyWorkspaceSize,\n                                (HUF_CElt*)nextHuf->CTable,\n                                &repeat, flags);\n        DEBUGLOG(5, \"%zu literals compressed into %zu bytes (before header)\", srcSize, cLitSize);\n        if (repeat != HUF_repeat_none) {\n            /* reused the existing table */\n            DEBUGLOG(5, \"reusing statistics from previous huffman block\");\n            hType = set_repeat;\n        }\n    }\n\n    {   size_t const minGain = ZSTD_minGain(srcSize, strategy);\n        if ((cLitSize==0) || (cLitSize >= srcSize - minGain) || ERR_isError(cLitSize)) {\n            ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n            return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);\n    }   }\n    if (cLitSize==1) {\n        /* A return value of 1 signals that the alphabet consists of a single symbol.\n         * However, in some rare circumstances, it could be the compressed size (a single byte).\n         * For that outcome to have a chance to happen, it's necessary that `srcSize < 8`.\n         * (it's also necessary to not generate statistics).\n         * Therefore, in such a case, actively check that all bytes are identical. */\n        if ((srcSize >= 8) || allBytesIdentical(src, srcSize)) {\n            ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));\n            return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);\n    }   }\n\n    if (hType == set_compressed) {\n        /* using a newly constructed table */\n        nextHuf->repeatMode = HUF_repeat_check;\n    }\n\n    /* Build header */\n    switch(lhSize)\n    {\n    case 3: /* 2 - 2 - 10 - 10 */\n        if (!singleStream) assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);\n        {   U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<14);\n            MEM_writeLE24(ostart, lhc);\n            break;\n        }\n    case 4: /* 2 - 2 - 14 - 14 */\n        assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);\n        {   U32 const lhc = hType + (2 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<18);\n            MEM_writeLE32(ostart, lhc);\n            break;\n        }\n    case 5: /* 2 - 2 - 18 - 18 */\n        assert(srcSize >= MIN_LITERALS_FOR_4_STREAMS);\n        {   U32 const lhc = hType + (3 << 2) + ((U32)srcSize<<4) + ((U32)cLitSize<<22);\n            MEM_writeLE32(ostart, lhc);\n            ostart[4] = (BYTE)(cLitSize >> 10);\n            break;\n        }\n    default:  /* not possible : lhSize is {3,4,5} */\n        assert(0);\n    }\n    DEBUGLOG(5, \"Compressed literals: %u -> %u\", (U32)srcSize, (U32)(lhSize+cLitSize));\n    return lhSize+cLitSize;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress_literals.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPRESS_LITERALS_H\n#define ZSTD_COMPRESS_LITERALS_H\n\n#include \"zstd_compress_internal.h\" /* ZSTD_hufCTables_t, ZSTD_minGain() */\n\n\nsize_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* ZSTD_compressRleLiteralsBlock() :\n * Conditions :\n * - All bytes in @src are identical\n * - dstCapacity >= 4 */\nsize_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* ZSTD_compressLiterals():\n * @entropyWorkspace: must be aligned on 4-bytes boundaries\n * @entropyWorkspaceSize : must be >= HUF_WORKSPACE_SIZE\n * @suspectUncompressible: sampling checks, to potentially skip huffman coding\n */\nsize_t ZSTD_compressLiterals (void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize,\n                              void* entropyWorkspace, size_t entropyWorkspaceSize,\n                        const ZSTD_hufCTables_t* prevHuf,\n                              ZSTD_hufCTables_t* nextHuf,\n                              ZSTD_strategy strategy, int disableLiteralCompression,\n                              int suspectUncompressible,\n                              int bmi2);\n\n#endif /* ZSTD_COMPRESS_LITERALS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress_sequences.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /*-*************************************\n *  Dependencies\n ***************************************/\n#include \"zstd_compress_sequences.h\"\n\n/**\n * -log2(x / 256) lookup table for x in [0, 256).\n * If x == 0: Return 0\n * Else: Return floor(-log2(x / 256) * 256)\n */\nstatic unsigned const kInverseProbabilityLog256[256] = {\n    0,    2048, 1792, 1642, 1536, 1453, 1386, 1329, 1280, 1236, 1197, 1162,\n    1130, 1100, 1073, 1047, 1024, 1001, 980,  960,  941,  923,  906,  889,\n    874,  859,  844,  830,  817,  804,  791,  779,  768,  756,  745,  734,\n    724,  714,  704,  694,  685,  676,  667,  658,  650,  642,  633,  626,\n    618,  610,  603,  595,  588,  581,  574,  567,  561,  554,  548,  542,\n    535,  529,  523,  517,  512,  506,  500,  495,  489,  484,  478,  473,\n    468,  463,  458,  453,  448,  443,  438,  434,  429,  424,  420,  415,\n    411,  407,  402,  398,  394,  390,  386,  382,  377,  373,  370,  366,\n    362,  358,  354,  350,  347,  343,  339,  336,  332,  329,  325,  322,\n    318,  315,  311,  308,  305,  302,  298,  295,  292,  289,  286,  282,\n    279,  276,  273,  270,  267,  264,  261,  258,  256,  253,  250,  247,\n    244,  241,  239,  236,  233,  230,  228,  225,  222,  220,  217,  215,\n    212,  209,  207,  204,  202,  199,  197,  194,  192,  190,  187,  185,\n    182,  180,  178,  175,  173,  171,  168,  166,  164,  162,  159,  157,\n    155,  153,  151,  149,  146,  144,  142,  140,  138,  136,  134,  132,\n    130,  128,  126,  123,  121,  119,  117,  115,  114,  112,  110,  108,\n    106,  104,  102,  100,  98,   96,   94,   93,   91,   89,   87,   85,\n    83,   82,   80,   78,   76,   74,   73,   71,   69,   67,   66,   64,\n    62,   61,   59,   57,   55,   54,   52,   50,   49,   47,   46,   44,\n    42,   41,   39,   37,   36,   34,   33,   31,   30,   28,   26,   25,\n    23,   22,   20,   19,   17,   16,   14,   13,   11,   10,   8,    7,\n    5,    4,    2,    1,\n};\n\nstatic unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) {\n  void const* ptr = ctable;\n  U16 const* u16ptr = (U16 const*)ptr;\n  U32 const maxSymbolValue = MEM_read16(u16ptr + 1);\n  return maxSymbolValue;\n}\n\n/**\n * Returns true if we should use ncount=-1 else we should\n * use ncount=1 for low probability symbols instead.\n */\nstatic unsigned ZSTD_useLowProbCount(size_t const nbSeq)\n{\n    /* Heuristic: This should cover most blocks <= 16K and\n     * start to fade out after 16K to about 32K depending on\n     * compressibility.\n     */\n    return nbSeq >= 2048;\n}\n\n/**\n * Returns the cost in bytes of encoding the normalized count header.\n * Returns an error if any of the helper functions return an error.\n */\nstatic size_t ZSTD_NCountCost(unsigned const* count, unsigned const max,\n                              size_t const nbSeq, unsigned const FSELog)\n{\n    BYTE wksp[FSE_NCOUNTBOUND];\n    S16 norm[MaxSeq + 1];\n    const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);\n    FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), \"\");\n    return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog);\n}\n\n/**\n * Returns the cost in bits of encoding the distribution described by count\n * using the entropy bound.\n */\nstatic size_t ZSTD_entropyCost(unsigned const* count, unsigned const max, size_t const total)\n{\n    unsigned cost = 0;\n    unsigned s;\n\n    assert(total > 0);\n    for (s = 0; s <= max; ++s) {\n        unsigned norm = (unsigned)((256 * count[s]) / total);\n        if (count[s] != 0 && norm == 0)\n            norm = 1;\n        assert(count[s] < total);\n        cost += count[s] * kInverseProbabilityLog256[norm];\n    }\n    return cost >> 8;\n}\n\n/**\n * Returns the cost in bits of encoding the distribution in count using ctable.\n * Returns an error if ctable cannot represent all the symbols in count.\n */\nsize_t ZSTD_fseBitCost(\n    FSE_CTable const* ctable,\n    unsigned const* count,\n    unsigned const max)\n{\n    unsigned const kAccuracyLog = 8;\n    size_t cost = 0;\n    unsigned s;\n    FSE_CState_t cstate;\n    FSE_initCState(&cstate, ctable);\n    if (ZSTD_getFSEMaxSymbolValue(ctable) < max) {\n        DEBUGLOG(5, \"Repeat FSE_CTable has maxSymbolValue %u < %u\",\n                    ZSTD_getFSEMaxSymbolValue(ctable), max);\n        return ERROR(GENERIC);\n    }\n    for (s = 0; s <= max; ++s) {\n        unsigned const tableLog = cstate.stateLog;\n        unsigned const badCost = (tableLog + 1) << kAccuracyLog;\n        unsigned const bitCost = FSE_bitCost(cstate.symbolTT, tableLog, s, kAccuracyLog);\n        if (count[s] == 0)\n            continue;\n        if (bitCost >= badCost) {\n            DEBUGLOG(5, \"Repeat FSE_CTable has Prob[%u] == 0\", s);\n            return ERROR(GENERIC);\n        }\n        cost += (size_t)count[s] * bitCost;\n    }\n    return cost >> kAccuracyLog;\n}\n\n/**\n * Returns the cost in bits of encoding the distribution in count using the\n * table described by norm. The max symbol support by norm is assumed >= max.\n * norm must be valid for every symbol with non-zero probability in count.\n */\nsize_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,\n                             unsigned const* count, unsigned const max)\n{\n    unsigned const shift = 8 - accuracyLog;\n    size_t cost = 0;\n    unsigned s;\n    assert(accuracyLog <= 8);\n    for (s = 0; s <= max; ++s) {\n        unsigned const normAcc = (norm[s] != -1) ? (unsigned)norm[s] : 1;\n        unsigned const norm256 = normAcc << shift;\n        assert(norm256 > 0);\n        assert(norm256 < 256);\n        cost += count[s] * kInverseProbabilityLog256[norm256];\n    }\n    return cost >> 8;\n}\n\nSymbolEncodingType_e\nZSTD_selectEncodingType(\n        FSE_repeat* repeatMode, unsigned const* count, unsigned const max,\n        size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,\n        FSE_CTable const* prevCTable,\n        short const* defaultNorm, U32 defaultNormLog,\n        ZSTD_DefaultPolicy_e const isDefaultAllowed,\n        ZSTD_strategy const strategy)\n{\n    ZSTD_STATIC_ASSERT(ZSTD_defaultDisallowed == 0 && ZSTD_defaultAllowed != 0);\n    if (mostFrequent == nbSeq) {\n        *repeatMode = FSE_repeat_none;\n        if (isDefaultAllowed && nbSeq <= 2) {\n            /* Prefer set_basic over set_rle when there are 2 or fewer symbols,\n             * since RLE uses 1 byte, but set_basic uses 5-6 bits per symbol.\n             * If basic encoding isn't possible, always choose RLE.\n             */\n            DEBUGLOG(5, \"Selected set_basic\");\n            return set_basic;\n        }\n        DEBUGLOG(5, \"Selected set_rle\");\n        return set_rle;\n    }\n    if (strategy < ZSTD_lazy) {\n        if (isDefaultAllowed) {\n            size_t const staticFse_nbSeq_max = 1000;\n            size_t const mult = 10 - strategy;\n            size_t const baseLog = 3;\n            size_t const dynamicFse_nbSeq_min = (((size_t)1 << defaultNormLog) * mult) >> baseLog;  /* 28-36 for offset, 56-72 for lengths */\n            assert(defaultNormLog >= 5 && defaultNormLog <= 6);  /* xx_DEFAULTNORMLOG */\n            assert(mult <= 9 && mult >= 7);\n            if ( (*repeatMode == FSE_repeat_valid)\n              && (nbSeq < staticFse_nbSeq_max) ) {\n                DEBUGLOG(5, \"Selected set_repeat\");\n                return set_repeat;\n            }\n            if ( (nbSeq < dynamicFse_nbSeq_min)\n              || (mostFrequent < (nbSeq >> (defaultNormLog-1))) ) {\n                DEBUGLOG(5, \"Selected set_basic\");\n                /* The format allows default tables to be repeated, but it isn't useful.\n                 * When using simple heuristics to select encoding type, we don't want\n                 * to confuse these tables with dictionaries. When running more careful\n                 * analysis, we don't need to waste time checking both repeating tables\n                 * and default tables.\n                 */\n                *repeatMode = FSE_repeat_none;\n                return set_basic;\n            }\n        }\n    } else {\n        size_t const basicCost = isDefaultAllowed ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, count, max) : ERROR(GENERIC);\n        size_t const repeatCost = *repeatMode != FSE_repeat_none ? ZSTD_fseBitCost(prevCTable, count, max) : ERROR(GENERIC);\n        size_t const NCountCost = ZSTD_NCountCost(count, max, nbSeq, FSELog);\n        size_t const compressedCost = (NCountCost << 3) + ZSTD_entropyCost(count, max, nbSeq);\n\n        if (isDefaultAllowed) {\n            assert(!ZSTD_isError(basicCost));\n            assert(!(*repeatMode == FSE_repeat_valid && ZSTD_isError(repeatCost)));\n        }\n        assert(!ZSTD_isError(NCountCost));\n        assert(compressedCost < ERROR(maxCode));\n        DEBUGLOG(5, \"Estimated bit costs: basic=%u\\trepeat=%u\\tcompressed=%u\",\n                    (unsigned)basicCost, (unsigned)repeatCost, (unsigned)compressedCost);\n        if (basicCost <= repeatCost && basicCost <= compressedCost) {\n            DEBUGLOG(5, \"Selected set_basic\");\n            assert(isDefaultAllowed);\n            *repeatMode = FSE_repeat_none;\n            return set_basic;\n        }\n        if (repeatCost <= compressedCost) {\n            DEBUGLOG(5, \"Selected set_repeat\");\n            assert(!ZSTD_isError(repeatCost));\n            return set_repeat;\n        }\n        assert(compressedCost < basicCost && compressedCost < repeatCost);\n    }\n    DEBUGLOG(5, \"Selected set_compressed\");\n    *repeatMode = FSE_repeat_check;\n    return set_compressed;\n}\n\ntypedef struct {\n    S16 norm[MaxSeq + 1];\n    U32 wksp[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(MaxSeq, MaxFSELog)];\n} ZSTD_BuildCTableWksp;\n\nsize_t\nZSTD_buildCTable(void* dst, size_t dstCapacity,\n                FSE_CTable* nextCTable, U32 FSELog, SymbolEncodingType_e type,\n                unsigned* count, U32 max,\n                const BYTE* codeTable, size_t nbSeq,\n                const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                const FSE_CTable* prevCTable, size_t prevCTableSize,\n                void* entropyWorkspace, size_t entropyWorkspaceSize)\n{\n    BYTE* op = (BYTE*)dst;\n    const BYTE* const oend = op + dstCapacity;\n    DEBUGLOG(6, \"ZSTD_buildCTable (dstCapacity=%u)\", (unsigned)dstCapacity);\n\n    switch (type) {\n    case set_rle:\n        FORWARD_IF_ERROR(FSE_buildCTable_rle(nextCTable, (BYTE)max), \"\");\n        RETURN_ERROR_IF(dstCapacity==0, dstSize_tooSmall, \"not enough space\");\n        *op = codeTable[0];\n        return 1;\n    case set_repeat:\n        ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize);\n        return 0;\n    case set_basic:\n        FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), \"\");  /* note : could be pre-calculated */\n        return 0;\n    case set_compressed: {\n        ZSTD_BuildCTableWksp* wksp = (ZSTD_BuildCTableWksp*)entropyWorkspace;\n        size_t nbSeq_1 = nbSeq;\n        const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max);\n        if (count[codeTable[nbSeq-1]] > 1) {\n            count[codeTable[nbSeq-1]]--;\n            nbSeq_1--;\n        }\n        assert(nbSeq_1 > 1);\n        assert(entropyWorkspaceSize >= sizeof(ZSTD_BuildCTableWksp));\n        (void)entropyWorkspaceSize;\n        FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), \"FSE_normalizeCount failed\");\n        assert(oend >= op);\n        {   size_t const NCountSize = FSE_writeNCount(op, (size_t)(oend - op), wksp->norm, max, tableLog);   /* overflow protected */\n            FORWARD_IF_ERROR(NCountSize, \"FSE_writeNCount failed\");\n            FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), \"FSE_buildCTable_wksp failed\");\n            return NCountSize;\n        }\n    }\n    default: assert(0); RETURN_ERROR(GENERIC, \"impossible to reach\");\n    }\n}\n\nFORCE_INLINE_TEMPLATE size_t\nZSTD_encodeSequences_body(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets)\n{\n    BIT_CStream_t blockStream;\n    FSE_CState_t  stateMatchLength;\n    FSE_CState_t  stateOffsetBits;\n    FSE_CState_t  stateLitLength;\n\n    RETURN_ERROR_IF(\n        ERR_isError(BIT_initCStream(&blockStream, dst, dstCapacity)),\n        dstSize_tooSmall, \"not enough space remaining\");\n    DEBUGLOG(6, \"available space for bitstream : %i  (dstCapacity=%u)\",\n                (int)(blockStream.endPtr - blockStream.startPtr),\n                (unsigned)dstCapacity);\n\n    /* first symbols */\n    FSE_initCState2(&stateMatchLength, CTable_MatchLength, mlCodeTable[nbSeq-1]);\n    FSE_initCState2(&stateOffsetBits,  CTable_OffsetBits,  ofCodeTable[nbSeq-1]);\n    FSE_initCState2(&stateLitLength,   CTable_LitLength,   llCodeTable[nbSeq-1]);\n    BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);\n    if (MEM_32bits()) BIT_flushBits(&blockStream);\n    BIT_addBits(&blockStream, sequences[nbSeq-1].mlBase, ML_bits[mlCodeTable[nbSeq-1]]);\n    if (MEM_32bits()) BIT_flushBits(&blockStream);\n    if (longOffsets) {\n        U32 const ofBits = ofCodeTable[nbSeq-1];\n        unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);\n        if (extraBits) {\n            BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, extraBits);\n            BIT_flushBits(&blockStream);\n        }\n        BIT_addBits(&blockStream, sequences[nbSeq-1].offBase >> extraBits,\n                    ofBits - extraBits);\n    } else {\n        BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]);\n    }\n    BIT_flushBits(&blockStream);\n\n    {   size_t n;\n        for (n=nbSeq-2 ; n<nbSeq ; n--) {      /* intentional underflow */\n            BYTE const llCode = llCodeTable[n];\n            BYTE const ofCode = ofCodeTable[n];\n            BYTE const mlCode = mlCodeTable[n];\n            U32  const llBits = LL_bits[llCode];\n            U32  const ofBits = ofCode;\n            U32  const mlBits = ML_bits[mlCode];\n            DEBUGLOG(6, \"encoding: litlen:%2u - matchlen:%2u - offCode:%7u\",\n                        (unsigned)sequences[n].litLength,\n                        (unsigned)sequences[n].mlBase + MINMATCH,\n                        (unsigned)sequences[n].offBase);\n                                                                            /* 32b*/  /* 64b*/\n                                                                            /* (7)*/  /* (7)*/\n            FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode);       /* 15 */  /* 15 */\n            FSE_encodeSymbol(&blockStream, &stateMatchLength, mlCode);      /* 24 */  /* 24 */\n            if (MEM_32bits()) BIT_flushBits(&blockStream);                  /* (7)*/\n            FSE_encodeSymbol(&blockStream, &stateLitLength, llCode);        /* 16 */  /* 33 */\n            if (MEM_32bits() || (ofBits+mlBits+llBits >= 64-7-(LLFSELog+MLFSELog+OffFSELog)))\n                BIT_flushBits(&blockStream);                                /* (7)*/\n            BIT_addBits(&blockStream, sequences[n].litLength, llBits);\n            if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);\n            BIT_addBits(&blockStream, sequences[n].mlBase, mlBits);\n            if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);\n            if (longOffsets) {\n                unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);\n                if (extraBits) {\n                    BIT_addBits(&blockStream, sequences[n].offBase, extraBits);\n                    BIT_flushBits(&blockStream);                            /* (7)*/\n                }\n                BIT_addBits(&blockStream, sequences[n].offBase >> extraBits,\n                            ofBits - extraBits);                            /* 31 */\n            } else {\n                BIT_addBits(&blockStream, sequences[n].offBase, ofBits);     /* 31 */\n            }\n            BIT_flushBits(&blockStream);                                    /* (7)*/\n            DEBUGLOG(7, \"remaining space : %i\", (int)(blockStream.endPtr - blockStream.ptr));\n    }   }\n\n    DEBUGLOG(6, \"ZSTD_encodeSequences: flushing ML state with %u bits\", stateMatchLength.stateLog);\n    FSE_flushCState(&blockStream, &stateMatchLength);\n    DEBUGLOG(6, \"ZSTD_encodeSequences: flushing Off state with %u bits\", stateOffsetBits.stateLog);\n    FSE_flushCState(&blockStream, &stateOffsetBits);\n    DEBUGLOG(6, \"ZSTD_encodeSequences: flushing LL state with %u bits\", stateLitLength.stateLog);\n    FSE_flushCState(&blockStream, &stateLitLength);\n\n    {   size_t const streamSize = BIT_closeCStream(&blockStream);\n        RETURN_ERROR_IF(streamSize==0, dstSize_tooSmall, \"not enough space\");\n        return streamSize;\n    }\n}\n\nstatic size_t\nZSTD_encodeSequences_default(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets)\n{\n    return ZSTD_encodeSequences_body(dst, dstCapacity,\n                                    CTable_MatchLength, mlCodeTable,\n                                    CTable_OffsetBits, ofCodeTable,\n                                    CTable_LitLength, llCodeTable,\n                                    sequences, nbSeq, longOffsets);\n}\n\n\n#if DYNAMIC_BMI2\n\nstatic BMI2_TARGET_ATTRIBUTE size_t\nZSTD_encodeSequences_bmi2(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets)\n{\n    return ZSTD_encodeSequences_body(dst, dstCapacity,\n                                    CTable_MatchLength, mlCodeTable,\n                                    CTable_OffsetBits, ofCodeTable,\n                                    CTable_LitLength, llCodeTable,\n                                    sequences, nbSeq, longOffsets);\n}\n\n#endif\n\nsize_t ZSTD_encodeSequences(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2)\n{\n    DEBUGLOG(5, \"ZSTD_encodeSequences: dstCapacity = %u\", (unsigned)dstCapacity);\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        return ZSTD_encodeSequences_bmi2(dst, dstCapacity,\n                                         CTable_MatchLength, mlCodeTable,\n                                         CTable_OffsetBits, ofCodeTable,\n                                         CTable_LitLength, llCodeTable,\n                                         sequences, nbSeq, longOffsets);\n    }\n#endif\n    (void)bmi2;\n    return ZSTD_encodeSequences_default(dst, dstCapacity,\n                                        CTable_MatchLength, mlCodeTable,\n                                        CTable_OffsetBits, ofCodeTable,\n                                        CTable_LitLength, llCodeTable,\n                                        sequences, nbSeq, longOffsets);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress_sequences.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPRESS_SEQUENCES_H\n#define ZSTD_COMPRESS_SEQUENCES_H\n\n#include \"zstd_compress_internal.h\" /* SeqDef */\n#include \"../common/fse.h\" /* FSE_repeat, FSE_CTable */\n#include \"../common/zstd_internal.h\" /* SymbolEncodingType_e, ZSTD_strategy */\n\ntypedef enum {\n    ZSTD_defaultDisallowed = 0,\n    ZSTD_defaultAllowed = 1\n} ZSTD_DefaultPolicy_e;\n\nSymbolEncodingType_e\nZSTD_selectEncodingType(\n        FSE_repeat* repeatMode, unsigned const* count, unsigned const max,\n        size_t const mostFrequent, size_t nbSeq, unsigned const FSELog,\n        FSE_CTable const* prevCTable,\n        short const* defaultNorm, U32 defaultNormLog,\n        ZSTD_DefaultPolicy_e const isDefaultAllowed,\n        ZSTD_strategy const strategy);\n\nsize_t\nZSTD_buildCTable(void* dst, size_t dstCapacity,\n                FSE_CTable* nextCTable, U32 FSELog, SymbolEncodingType_e type,\n                unsigned* count, U32 max,\n                const BYTE* codeTable, size_t nbSeq,\n                const S16* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                const FSE_CTable* prevCTable, size_t prevCTableSize,\n                void* entropyWorkspace, size_t entropyWorkspaceSize);\n\nsize_t ZSTD_encodeSequences(\n            void* dst, size_t dstCapacity,\n            FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,\n            FSE_CTable const* CTable_OffsetBits, BYTE const* ofCodeTable,\n            FSE_CTable const* CTable_LitLength, BYTE const* llCodeTable,\n            SeqDef const* sequences, size_t nbSeq, int longOffsets, int bmi2);\n\nsize_t ZSTD_fseBitCost(\n    FSE_CTable const* ctable,\n    unsigned const* count,\n    unsigned const max);\n\nsize_t ZSTD_crossEntropyCost(short const* norm, unsigned accuracyLog,\n                             unsigned const* count, unsigned const max);\n#endif /* ZSTD_COMPRESS_SEQUENCES_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress_superblock.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n /*-*************************************\n *  Dependencies\n ***************************************/\n#include \"zstd_compress_superblock.h\"\n\n#include \"../common/zstd_internal.h\"  /* ZSTD_getSequenceLength */\n#include \"hist.h\"                     /* HIST_countFast_wksp */\n#include \"zstd_compress_internal.h\"   /* ZSTD_[huf|fse|entropy]CTablesMetadata_t */\n#include \"zstd_compress_sequences.h\"\n#include \"zstd_compress_literals.h\"\n\n/** ZSTD_compressSubBlock_literal() :\n *  Compresses literals section for a sub-block.\n *  When we have to write the Huffman table we will sometimes choose a header\n *  size larger than necessary. This is because we have to pick the header size\n *  before we know the table size + compressed size, so we have a bound on the\n *  table size. If we guessed incorrectly, we fall back to uncompressed literals.\n *\n *  We write the header when writeEntropy=1 and set entropyWritten=1 when we succeeded\n *  in writing the header, otherwise it is set to 0.\n *\n *  hufMetadata->hType has literals block type info.\n *      If it is set_basic, all sub-blocks literals section will be Raw_Literals_Block.\n *      If it is set_rle, all sub-blocks literals section will be RLE_Literals_Block.\n *      If it is set_compressed, first sub-block's literals section will be Compressed_Literals_Block\n *      If it is set_compressed, first sub-block's literals section will be Treeless_Literals_Block\n *      and the following sub-blocks' literals sections will be Treeless_Literals_Block.\n *  @return : compressed size of literals section of a sub-block\n *            Or 0 if unable to compress.\n *            Or error code */\nstatic size_t\nZSTD_compressSubBlock_literal(const HUF_CElt* hufTable,\n                              const ZSTD_hufCTablesMetadata_t* hufMetadata,\n                              const BYTE* literals, size_t litSize,\n                              void* dst, size_t dstSize,\n                              const int bmi2, int writeEntropy, int* entropyWritten)\n{\n    size_t const header = writeEntropy ? 200 : 0;\n    size_t const lhSize = 3 + (litSize >= (1 KB - header)) + (litSize >= (16 KB - header));\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstSize;\n    BYTE* op = ostart + lhSize;\n    U32 const singleStream = lhSize == 3;\n    SymbolEncodingType_e hType = writeEntropy ? hufMetadata->hType : set_repeat;\n    size_t cLitSize = 0;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_literal (litSize=%zu, lhSize=%zu, writeEntropy=%d)\", litSize, lhSize, writeEntropy);\n\n    *entropyWritten = 0;\n    if (litSize == 0 || hufMetadata->hType == set_basic) {\n      DEBUGLOG(5, \"ZSTD_compressSubBlock_literal using raw literal\");\n      return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);\n    } else if (hufMetadata->hType == set_rle) {\n      DEBUGLOG(5, \"ZSTD_compressSubBlock_literal using rle literal\");\n      return ZSTD_compressRleLiteralsBlock(dst, dstSize, literals, litSize);\n    }\n\n    assert(litSize > 0);\n    assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat);\n\n    if (writeEntropy && hufMetadata->hType == set_compressed) {\n        ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize);\n        op += hufMetadata->hufDesSize;\n        cLitSize += hufMetadata->hufDesSize;\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_literal (hSize=%zu)\", hufMetadata->hufDesSize);\n    }\n\n    {   int const flags = bmi2 ? HUF_flags_bmi2 : 0;\n        const size_t cSize = singleStream ? HUF_compress1X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags)\n                                          : HUF_compress4X_usingCTable(op, (size_t)(oend-op), literals, litSize, hufTable, flags);\n        op += cSize;\n        cLitSize += cSize;\n        if (cSize == 0 || ERR_isError(cSize)) {\n            DEBUGLOG(5, \"Failed to write entropy tables %s\", ZSTD_getErrorName(cSize));\n            return 0;\n        }\n        /* If we expand and we aren't writing a header then emit uncompressed */\n        if (!writeEntropy && cLitSize >= litSize) {\n            DEBUGLOG(5, \"ZSTD_compressSubBlock_literal using raw literal because uncompressible\");\n            return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);\n        }\n        /* If we are writing headers then allow expansion that doesn't change our header size. */\n        if (lhSize < (size_t)(3 + (cLitSize >= 1 KB) + (cLitSize >= 16 KB))) {\n            assert(cLitSize > litSize);\n            DEBUGLOG(5, \"Literals expanded beyond allowed header size\");\n            return ZSTD_noCompressLiterals(dst, dstSize, literals, litSize);\n        }\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_literal (cSize=%zu)\", cSize);\n    }\n\n    /* Build header */\n    switch(lhSize)\n    {\n    case 3: /* 2 - 2 - 10 - 10 */\n        {   U32 const lhc = hType + ((U32)(!singleStream) << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<14);\n            MEM_writeLE24(ostart, lhc);\n            break;\n        }\n    case 4: /* 2 - 2 - 14 - 14 */\n        {   U32 const lhc = hType + (2 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<18);\n            MEM_writeLE32(ostart, lhc);\n            break;\n        }\n    case 5: /* 2 - 2 - 18 - 18 */\n        {   U32 const lhc = hType + (3 << 2) + ((U32)litSize<<4) + ((U32)cLitSize<<22);\n            MEM_writeLE32(ostart, lhc);\n            ostart[4] = (BYTE)(cLitSize >> 10);\n            break;\n        }\n    default:  /* not possible : lhSize is {3,4,5} */\n        assert(0);\n    }\n    *entropyWritten = 1;\n    DEBUGLOG(5, \"Compressed literals: %u -> %u\", (U32)litSize, (U32)(op-ostart));\n    return (size_t)(op-ostart);\n}\n\nstatic size_t\nZSTD_seqDecompressedSize(SeqStore_t const* seqStore,\n                   const SeqDef* sequences, size_t nbSeqs,\n                         size_t litSize, int lastSubBlock)\n{\n    size_t matchLengthSum = 0;\n    size_t litLengthSum = 0;\n    size_t n;\n    for (n=0; n<nbSeqs; n++) {\n        const ZSTD_SequenceLength seqLen = ZSTD_getSequenceLength(seqStore, sequences+n);\n        litLengthSum += seqLen.litLength;\n        matchLengthSum += seqLen.matchLength;\n    }\n    DEBUGLOG(5, \"ZSTD_seqDecompressedSize: %u sequences from %p: %u literals + %u matchlength\",\n                (unsigned)nbSeqs, (const void*)sequences,\n                (unsigned)litLengthSum, (unsigned)matchLengthSum);\n    if (!lastSubBlock)\n        assert(litLengthSum == litSize);\n    else\n        assert(litLengthSum <= litSize);\n    (void)litLengthSum;\n    return matchLengthSum + litSize;\n}\n\n/** ZSTD_compressSubBlock_sequences() :\n *  Compresses sequences section for a sub-block.\n *  fseMetadata->llType, fseMetadata->ofType, and fseMetadata->mlType have\n *  symbol compression modes for the super-block.\n *  The first successfully compressed block will have these in its header.\n *  We set entropyWritten=1 when we succeed in compressing the sequences.\n *  The following sub-blocks will always have repeat mode.\n *  @return : compressed size of sequences section of a sub-block\n *            Or 0 if it is unable to compress\n *            Or error code. */\nstatic size_t\nZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables,\n                                const ZSTD_fseCTablesMetadata_t* fseMetadata,\n                                const SeqDef* sequences, size_t nbSeq,\n                                const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,\n                                const ZSTD_CCtx_params* cctxParams,\n                                void* dst, size_t dstCapacity,\n                                const int bmi2, int writeEntropy, int* entropyWritten)\n{\n    const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    BYTE* seqHead;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (nbSeq=%zu, writeEntropy=%d, longOffsets=%d)\", nbSeq, writeEntropy, longOffsets);\n\n    *entropyWritten = 0;\n    /* Sequences Header */\n    RETURN_ERROR_IF((oend-op) < 3 /*max nbSeq Size*/ + 1 /*seqHead*/,\n                    dstSize_tooSmall, \"\");\n    if (nbSeq < 128)\n        *op++ = (BYTE)nbSeq;\n    else if (nbSeq < LONGNBSEQ)\n        op[0] = (BYTE)((nbSeq>>8) + 0x80), op[1] = (BYTE)nbSeq, op+=2;\n    else\n        op[0]=0xFF, MEM_writeLE16(op+1, (U16)(nbSeq - LONGNBSEQ)), op+=3;\n    if (nbSeq==0) {\n        return (size_t)(op - ostart);\n    }\n\n    /* seqHead : flags for FSE encoding type */\n    seqHead = op++;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (seqHeadSize=%u)\", (unsigned)(op-ostart));\n\n    if (writeEntropy) {\n        const U32 LLtype = fseMetadata->llType;\n        const U32 Offtype = fseMetadata->ofType;\n        const U32 MLtype = fseMetadata->mlType;\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)\", fseMetadata->fseTablesSize);\n        *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2));\n        ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize);\n        op += fseMetadata->fseTablesSize;\n    } else {\n        const U32 repeat = set_repeat;\n        *seqHead = (BYTE)((repeat<<6) + (repeat<<4) + (repeat<<2));\n    }\n\n    {   size_t const bitstreamSize = ZSTD_encodeSequences(\n                                        op, (size_t)(oend - op),\n                                        fseTables->matchlengthCTable, mlCode,\n                                        fseTables->offcodeCTable, ofCode,\n                                        fseTables->litlengthCTable, llCode,\n                                        sequences, nbSeq,\n                                        longOffsets, bmi2);\n        FORWARD_IF_ERROR(bitstreamSize, \"ZSTD_encodeSequences failed\");\n        op += bitstreamSize;\n        /* zstd versions <= 1.3.4 mistakenly report corruption when\n         * FSE_readNCount() receives a buffer < 4 bytes.\n         * Fixed by https://github.com/facebook/zstd/pull/1146.\n         * This can happen when the last set_compressed table present is 2\n         * bytes and the bitstream is only one byte.\n         * In this exceedingly rare case, we will simply emit an uncompressed\n         * block, since it isn't worth optimizing.\n         */\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n        if (writeEntropy && fseMetadata->lastCountSize && fseMetadata->lastCountSize + bitstreamSize < 4) {\n            /* NCountSize >= 2 && bitstreamSize > 0 ==> lastCountSize == 3 */\n            assert(fseMetadata->lastCountSize + bitstreamSize == 3);\n            DEBUGLOG(5, \"Avoiding bug in zstd decoder in versions <= 1.3.4 by \"\n                        \"emitting an uncompressed block.\");\n            return 0;\n        }\n#endif\n        DEBUGLOG(5, \"ZSTD_compressSubBlock_sequences (bitstreamSize=%zu)\", bitstreamSize);\n    }\n\n    /* zstd versions <= 1.4.0 mistakenly report error when\n     * sequences section body size is less than 3 bytes.\n     * Fixed by https://github.com/facebook/zstd/pull/1664.\n     * This can happen when the previous sequences section block is compressed\n     * with rle mode and the current block's sequences section is compressed\n     * with repeat mode where sequences section body size can be 1 byte.\n     */\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    if (op-seqHead < 4) {\n        DEBUGLOG(5, \"Avoiding bug in zstd decoder in versions <= 1.4.0 by emitting \"\n                    \"an uncompressed block when sequences are < 4 bytes\");\n        return 0;\n    }\n#endif\n\n    *entropyWritten = 1;\n    return (size_t)(op - ostart);\n}\n\n/** ZSTD_compressSubBlock() :\n *  Compresses a single sub-block.\n *  @return : compressed size of the sub-block\n *            Or 0 if it failed to compress. */\nstatic size_t ZSTD_compressSubBlock(const ZSTD_entropyCTables_t* entropy,\n                                    const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                                    const SeqDef* sequences, size_t nbSeq,\n                                    const BYTE* literals, size_t litSize,\n                                    const BYTE* llCode, const BYTE* mlCode, const BYTE* ofCode,\n                                    const ZSTD_CCtx_params* cctxParams,\n                                    void* dst, size_t dstCapacity,\n                                    const int bmi2,\n                                    int writeLitEntropy, int writeSeqEntropy,\n                                    int* litEntropyWritten, int* seqEntropyWritten,\n                                    U32 lastBlock)\n{\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart + ZSTD_blockHeaderSize;\n    DEBUGLOG(5, \"ZSTD_compressSubBlock (litSize=%zu, nbSeq=%zu, writeLitEntropy=%d, writeSeqEntropy=%d, lastBlock=%d)\",\n                litSize, nbSeq, writeLitEntropy, writeSeqEntropy, lastBlock);\n    {   size_t cLitSize = ZSTD_compressSubBlock_literal((const HUF_CElt*)entropy->huf.CTable,\n                                                        &entropyMetadata->hufMetadata, literals, litSize,\n                                                        op, (size_t)(oend-op),\n                                                        bmi2, writeLitEntropy, litEntropyWritten);\n        FORWARD_IF_ERROR(cLitSize, \"ZSTD_compressSubBlock_literal failed\");\n        if (cLitSize == 0) return 0;\n        op += cLitSize;\n    }\n    {   size_t cSeqSize = ZSTD_compressSubBlock_sequences(&entropy->fse,\n                                                  &entropyMetadata->fseMetadata,\n                                                  sequences, nbSeq,\n                                                  llCode, mlCode, ofCode,\n                                                  cctxParams,\n                                                  op, (size_t)(oend-op),\n                                                  bmi2, writeSeqEntropy, seqEntropyWritten);\n        FORWARD_IF_ERROR(cSeqSize, \"ZSTD_compressSubBlock_sequences failed\");\n        if (cSeqSize == 0) return 0;\n        op += cSeqSize;\n    }\n    /* Write block header */\n    {   size_t cSize = (size_t)(op-ostart) - ZSTD_blockHeaderSize;\n        U32 const cBlockHeader24 = lastBlock + (((U32)bt_compressed)<<1) + (U32)(cSize << 3);\n        MEM_writeLE24(ostart, cBlockHeader24);\n    }\n    return (size_t)(op-ostart);\n}\n\nstatic size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t litSize,\n                                                const ZSTD_hufCTables_t* huf,\n                                                const ZSTD_hufCTablesMetadata_t* hufMetadata,\n                                                void* workspace, size_t wkspSize,\n                                                int writeEntropy)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    unsigned maxSymbolValue = 255;\n    size_t literalSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */\n\n    if (hufMetadata->hType == set_basic) return litSize;\n    else if (hufMetadata->hType == set_rle) return 1;\n    else if (hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat) {\n        size_t const largest = HIST_count_wksp (countWksp, &maxSymbolValue, (const BYTE*)literals, litSize, workspace, wkspSize);\n        if (ZSTD_isError(largest)) return litSize;\n        {   size_t cLitSizeEstimate = HUF_estimateCompressedSize((const HUF_CElt*)huf->CTable, countWksp, maxSymbolValue);\n            if (writeEntropy) cLitSizeEstimate += hufMetadata->hufDesSize;\n            return cLitSizeEstimate + literalSectionHeaderSize;\n    }   }\n    assert(0); /* impossible */\n    return 0;\n}\n\nstatic size_t ZSTD_estimateSubBlockSize_symbolType(SymbolEncodingType_e type,\n                        const BYTE* codeTable, unsigned maxCode,\n                        size_t nbSeq, const FSE_CTable* fseCTable,\n                        const U8* additionalBits,\n                        short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,\n                        void* workspace, size_t wkspSize)\n{\n    unsigned* const countWksp = (unsigned*)workspace;\n    const BYTE* ctp = codeTable;\n    const BYTE* const ctStart = ctp;\n    const BYTE* const ctEnd = ctStart + nbSeq;\n    size_t cSymbolTypeSizeEstimateInBits = 0;\n    unsigned max = maxCode;\n\n    HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize);  /* can't fail */\n    if (type == set_basic) {\n        /* We selected this encoding type, so it must be valid. */\n        assert(max <= defaultMax);\n        cSymbolTypeSizeEstimateInBits = max <= defaultMax\n                ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max)\n                : ERROR(GENERIC);\n    } else if (type == set_rle) {\n        cSymbolTypeSizeEstimateInBits = 0;\n    } else if (type == set_compressed || type == set_repeat) {\n        cSymbolTypeSizeEstimateInBits = ZSTD_fseBitCost(fseCTable, countWksp, max);\n    }\n    if (ZSTD_isError(cSymbolTypeSizeEstimateInBits)) return nbSeq * 10;\n    while (ctp < ctEnd) {\n        if (additionalBits) cSymbolTypeSizeEstimateInBits += additionalBits[*ctp];\n        else cSymbolTypeSizeEstimateInBits += *ctp; /* for offset, offset code is also the number of additional bits */\n        ctp++;\n    }\n    return cSymbolTypeSizeEstimateInBits / 8;\n}\n\nstatic size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable,\n                                                  const BYTE* llCodeTable,\n                                                  const BYTE* mlCodeTable,\n                                                  size_t nbSeq,\n                                                  const ZSTD_fseCTables_t* fseTables,\n                                                  const ZSTD_fseCTablesMetadata_t* fseMetadata,\n                                                  void* workspace, size_t wkspSize,\n                                                  int writeEntropy)\n{\n    size_t const sequencesSectionHeaderSize = 3; /* Use hard coded size of 3 bytes */\n    size_t cSeqSizeEstimate = 0;\n    if (nbSeq == 0) return sequencesSectionHeaderSize;\n    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff,\n                                         nbSeq, fseTables->offcodeCTable, NULL,\n                                         OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff,\n                                         workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL,\n                                         nbSeq, fseTables->litlengthCTable, LL_bits,\n                                         LL_defaultNorm, LL_defaultNormLog, MaxLL,\n                                         workspace, wkspSize);\n    cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML,\n                                         nbSeq, fseTables->matchlengthCTable, ML_bits,\n                                         ML_defaultNorm, ML_defaultNormLog, MaxML,\n                                         workspace, wkspSize);\n    if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize;\n    return cSeqSizeEstimate + sequencesSectionHeaderSize;\n}\n\ntypedef struct {\n    size_t estLitSize;\n    size_t estBlockSize;\n} EstimatedBlockSize;\nstatic EstimatedBlockSize ZSTD_estimateSubBlockSize(const BYTE* literals, size_t litSize,\n                                        const BYTE* ofCodeTable,\n                                        const BYTE* llCodeTable,\n                                        const BYTE* mlCodeTable,\n                                        size_t nbSeq,\n                                        const ZSTD_entropyCTables_t* entropy,\n                                        const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                                        void* workspace, size_t wkspSize,\n                                        int writeLitEntropy, int writeSeqEntropy)\n{\n    EstimatedBlockSize ebs;\n    ebs.estLitSize = ZSTD_estimateSubBlockSize_literal(literals, litSize,\n                                                        &entropy->huf, &entropyMetadata->hufMetadata,\n                                                        workspace, wkspSize, writeLitEntropy);\n    ebs.estBlockSize = ZSTD_estimateSubBlockSize_sequences(ofCodeTable, llCodeTable, mlCodeTable,\n                                                         nbSeq, &entropy->fse, &entropyMetadata->fseMetadata,\n                                                         workspace, wkspSize, writeSeqEntropy);\n    ebs.estBlockSize += ebs.estLitSize + ZSTD_blockHeaderSize;\n    return ebs;\n}\n\nstatic int ZSTD_needSequenceEntropyTables(ZSTD_fseCTablesMetadata_t const* fseMetadata)\n{\n    if (fseMetadata->llType == set_compressed || fseMetadata->llType == set_rle)\n        return 1;\n    if (fseMetadata->mlType == set_compressed || fseMetadata->mlType == set_rle)\n        return 1;\n    if (fseMetadata->ofType == set_compressed || fseMetadata->ofType == set_rle)\n        return 1;\n    return 0;\n}\n\nstatic size_t countLiterals(SeqStore_t const* seqStore, const SeqDef* sp, size_t seqCount)\n{\n    size_t n, total = 0;\n    assert(sp != NULL);\n    for (n=0; n<seqCount; n++) {\n        total += ZSTD_getSequenceLength(seqStore, sp+n).litLength;\n    }\n    DEBUGLOG(6, \"countLiterals for %zu sequences from %p => %zu bytes\", seqCount, (const void*)sp, total);\n    return total;\n}\n\n#define BYTESCALE 256\n\nstatic size_t sizeBlockSequences(const SeqDef* sp, size_t nbSeqs,\n                size_t targetBudget, size_t avgLitCost, size_t avgSeqCost,\n                int firstSubBlock)\n{\n    size_t n, budget = 0, inSize=0;\n    /* entropy headers */\n    size_t const headerSize = (size_t)firstSubBlock * 120 * BYTESCALE; /* generous estimate */\n    assert(firstSubBlock==0 || firstSubBlock==1);\n    budget += headerSize;\n\n    /* first sequence => at least one sequence*/\n    budget += sp[0].litLength * avgLitCost + avgSeqCost;\n    if (budget > targetBudget) return 1;\n    inSize = sp[0].litLength + (sp[0].mlBase+MINMATCH);\n\n    /* loop over sequences */\n    for (n=1; n<nbSeqs; n++) {\n        size_t currentCost = sp[n].litLength * avgLitCost + avgSeqCost;\n        budget += currentCost;\n        inSize += sp[n].litLength + (sp[n].mlBase+MINMATCH);\n        /* stop when sub-block budget is reached */\n        if ( (budget > targetBudget)\n            /* though continue to expand until the sub-block is deemed compressible */\n          && (budget < inSize * BYTESCALE) )\n            break;\n    }\n\n    return n;\n}\n\n/** ZSTD_compressSubBlock_multi() :\n *  Breaks super-block into multiple sub-blocks and compresses them.\n *  Entropy will be written into the first block.\n *  The following blocks use repeat_mode to compress.\n *  Sub-blocks are all compressed, except the last one when beneficial.\n *  @return : compressed size of the super block (which features multiple ZSTD blocks)\n *            or 0 if it failed to compress. */\nstatic size_t ZSTD_compressSubBlock_multi(const SeqStore_t* seqStorePtr,\n                            const ZSTD_compressedBlockState_t* prevCBlock,\n                            ZSTD_compressedBlockState_t* nextCBlock,\n                            const ZSTD_entropyCTablesMetadata_t* entropyMetadata,\n                            const ZSTD_CCtx_params* cctxParams,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                            const int bmi2, U32 lastBlock,\n                            void* workspace, size_t wkspSize)\n{\n    const SeqDef* const sstart = seqStorePtr->sequencesStart;\n    const SeqDef* const send = seqStorePtr->sequences;\n    const SeqDef* sp = sstart; /* tracks progresses within seqStorePtr->sequences */\n    size_t const nbSeqs = (size_t)(send - sstart);\n    const BYTE* const lstart = seqStorePtr->litStart;\n    const BYTE* const lend = seqStorePtr->lit;\n    const BYTE* lp = lstart;\n    size_t const nbLiterals = (size_t)(lend - lstart);\n    BYTE const* ip = (BYTE const*)src;\n    BYTE const* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    const BYTE* llCodePtr = seqStorePtr->llCode;\n    const BYTE* mlCodePtr = seqStorePtr->mlCode;\n    const BYTE* ofCodePtr = seqStorePtr->ofCode;\n    size_t const minTarget = ZSTD_TARGETCBLOCKSIZE_MIN; /* enforce minimum size, to reduce undesirable side effects */\n    size_t const targetCBlockSize = MAX(minTarget, cctxParams->targetCBlockSize);\n    int writeLitEntropy = (entropyMetadata->hufMetadata.hType == set_compressed);\n    int writeSeqEntropy = 1;\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_multi (srcSize=%u, litSize=%u, nbSeq=%u)\",\n               (unsigned)srcSize, (unsigned)(lend-lstart), (unsigned)(send-sstart));\n\n        /* let's start by a general estimation for the full block */\n    if (nbSeqs > 0) {\n        EstimatedBlockSize const ebs =\n                ZSTD_estimateSubBlockSize(lp, nbLiterals,\n                                        ofCodePtr, llCodePtr, mlCodePtr, nbSeqs,\n                                        &nextCBlock->entropy, entropyMetadata,\n                                        workspace, wkspSize,\n                                        writeLitEntropy, writeSeqEntropy);\n        /* quick estimation */\n        size_t const avgLitCost = nbLiterals ? (ebs.estLitSize * BYTESCALE) / nbLiterals : BYTESCALE;\n        size_t const avgSeqCost = ((ebs.estBlockSize - ebs.estLitSize) * BYTESCALE) / nbSeqs;\n        const size_t nbSubBlocks = MAX((ebs.estBlockSize + (targetCBlockSize/2)) / targetCBlockSize, 1);\n        size_t n, avgBlockBudget, blockBudgetSupp=0;\n        avgBlockBudget = (ebs.estBlockSize * BYTESCALE) / nbSubBlocks;\n        DEBUGLOG(5, \"estimated fullblock size=%u bytes ; avgLitCost=%.2f ; avgSeqCost=%.2f ; targetCBlockSize=%u, nbSubBlocks=%u ; avgBlockBudget=%.0f bytes\",\n                    (unsigned)ebs.estBlockSize, (double)avgLitCost/BYTESCALE, (double)avgSeqCost/BYTESCALE,\n                    (unsigned)targetCBlockSize, (unsigned)nbSubBlocks, (double)avgBlockBudget/BYTESCALE);\n        /* simplification: if estimates states that the full superblock doesn't compress, just bail out immediately\n         * this will result in the production of a single uncompressed block covering @srcSize.*/\n        if (ebs.estBlockSize > srcSize) return 0;\n\n        /* compress and write sub-blocks */\n        assert(nbSubBlocks>0);\n        for (n=0; n < nbSubBlocks-1; n++) {\n            /* determine nb of sequences for current sub-block + nbLiterals from next sequence */\n            size_t const seqCount = sizeBlockSequences(sp, (size_t)(send-sp),\n                                        avgBlockBudget + blockBudgetSupp, avgLitCost, avgSeqCost, n==0);\n            /* if reached last sequence : break to last sub-block (simplification) */\n            assert(seqCount <= (size_t)(send-sp));\n            if (sp + seqCount == send) break;\n            assert(seqCount > 0);\n            /* compress sub-block */\n            {   int litEntropyWritten = 0;\n                int seqEntropyWritten = 0;\n                size_t litSize = countLiterals(seqStorePtr, sp, seqCount);\n                const size_t decompressedSize =\n                        ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 0);\n                size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,\n                                                sp, seqCount,\n                                                lp, litSize,\n                                                llCodePtr, mlCodePtr, ofCodePtr,\n                                                cctxParams,\n                                                op, (size_t)(oend-op),\n                                                bmi2, writeLitEntropy, writeSeqEntropy,\n                                                &litEntropyWritten, &seqEntropyWritten,\n                                                0);\n                FORWARD_IF_ERROR(cSize, \"ZSTD_compressSubBlock failed\");\n\n                /* check compressibility, update state components */\n                if (cSize > 0 && cSize < decompressedSize) {\n                    DEBUGLOG(5, \"Committed sub-block compressing %u bytes => %u bytes\",\n                                (unsigned)decompressedSize, (unsigned)cSize);\n                    assert(ip + decompressedSize <= iend);\n                    ip += decompressedSize;\n                    lp += litSize;\n                    op += cSize;\n                    llCodePtr += seqCount;\n                    mlCodePtr += seqCount;\n                    ofCodePtr += seqCount;\n                    /* Entropy only needs to be written once */\n                    if (litEntropyWritten) {\n                        writeLitEntropy = 0;\n                    }\n                    if (seqEntropyWritten) {\n                        writeSeqEntropy = 0;\n                    }\n                    sp += seqCount;\n                    blockBudgetSupp = 0;\n            }   }\n            /* otherwise : do not compress yet, coalesce current sub-block with following one */\n        }\n    } /* if (nbSeqs > 0) */\n\n    /* write last block */\n    DEBUGLOG(5, \"Generate last sub-block: %u sequences remaining\", (unsigned)(send - sp));\n    {   int litEntropyWritten = 0;\n        int seqEntropyWritten = 0;\n        size_t litSize = (size_t)(lend - lp);\n        size_t seqCount = (size_t)(send - sp);\n        const size_t decompressedSize =\n                ZSTD_seqDecompressedSize(seqStorePtr, sp, seqCount, litSize, 1);\n        size_t const cSize = ZSTD_compressSubBlock(&nextCBlock->entropy, entropyMetadata,\n                                            sp, seqCount,\n                                            lp, litSize,\n                                            llCodePtr, mlCodePtr, ofCodePtr,\n                                            cctxParams,\n                                            op, (size_t)(oend-op),\n                                            bmi2, writeLitEntropy, writeSeqEntropy,\n                                            &litEntropyWritten, &seqEntropyWritten,\n                                            lastBlock);\n        FORWARD_IF_ERROR(cSize, \"ZSTD_compressSubBlock failed\");\n\n        /* update pointers, the nb of literals borrowed from next sequence must be preserved */\n        if (cSize > 0 && cSize < decompressedSize) {\n            DEBUGLOG(5, \"Last sub-block compressed %u bytes => %u bytes\",\n                        (unsigned)decompressedSize, (unsigned)cSize);\n            assert(ip + decompressedSize <= iend);\n            ip += decompressedSize;\n            lp += litSize;\n            op += cSize;\n            llCodePtr += seqCount;\n            mlCodePtr += seqCount;\n            ofCodePtr += seqCount;\n            /* Entropy only needs to be written once */\n            if (litEntropyWritten) {\n                writeLitEntropy = 0;\n            }\n            if (seqEntropyWritten) {\n                writeSeqEntropy = 0;\n            }\n            sp += seqCount;\n        }\n    }\n\n\n    if (writeLitEntropy) {\n        DEBUGLOG(5, \"Literal entropy tables were never written\");\n        ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf));\n    }\n    if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) {\n        /* If we haven't written our entropy tables, then we've violated our contract and\n         * must emit an uncompressed block.\n         */\n        DEBUGLOG(5, \"Sequence entropy tables were never written => cancel, emit an uncompressed block\");\n        return 0;\n    }\n\n    if (ip < iend) {\n        /* some data left : last part of the block sent uncompressed */\n        size_t const rSize = (size_t)((iend - ip));\n        size_t const cSize = ZSTD_noCompressBlock(op, (size_t)(oend - op), ip, rSize, lastBlock);\n        DEBUGLOG(5, \"Generate last uncompressed sub-block of %u bytes\", (unsigned)(rSize));\n        FORWARD_IF_ERROR(cSize, \"ZSTD_noCompressBlock failed\");\n        assert(cSize != 0);\n        op += cSize;\n        /* We have to regenerate the repcodes because we've skipped some sequences */\n        if (sp < send) {\n            const SeqDef* seq;\n            Repcodes_t rep;\n            ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));\n            for (seq = sstart; seq < sp; ++seq) {\n                ZSTD_updateRep(rep.rep, seq->offBase, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);\n            }\n            ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));\n        }\n    }\n\n    DEBUGLOG(5, \"ZSTD_compressSubBlock_multi compressed all subBlocks: total compressed size = %u\",\n                (unsigned)(op-ostart));\n    return (size_t)(op-ostart);\n}\n\nsize_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                               unsigned lastBlock)\n{\n    ZSTD_entropyCTablesMetadata_t entropyMetadata;\n\n    FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(&zc->seqStore,\n          &zc->blockState.prevCBlock->entropy,\n          &zc->blockState.nextCBlock->entropy,\n          &zc->appliedParams,\n          &entropyMetadata,\n          zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */), \"\");\n\n    return ZSTD_compressSubBlock_multi(&zc->seqStore,\n            zc->blockState.prevCBlock,\n            zc->blockState.nextCBlock,\n            &entropyMetadata,\n            &zc->appliedParams,\n            dst, dstCapacity,\n            src, srcSize,\n            zc->bmi2, lastBlock,\n            zc->tmpWorkspace, zc->tmpWkspSize /* statically allocated in resetCCtx */);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_compress_superblock.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_COMPRESS_ADVANCED_H\n#define ZSTD_COMPRESS_ADVANCED_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n\n#include \"../zstd.h\" /* ZSTD_CCtx */\n\n/*-*************************************\n*  Target Compressed Block Size\n***************************************/\n\n/* ZSTD_compressSuperBlock() :\n * Used to compress a super block when targetCBlockSize is being used.\n * The given block will be compressed into multiple sub blocks that are around targetCBlockSize. */\nsize_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc,\n                               void* dst, size_t dstCapacity,\n                               void const* src, size_t srcSize,\n                               unsigned lastBlock);\n\n#endif /* ZSTD_COMPRESS_ADVANCED_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_cwksp.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_CWKSP_H\n#define ZSTD_CWKSP_H\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customFree */\n#include \"../common/zstd_internal.h\"\n#include \"../common/portability_macros.h\"\n#include \"../common/compiler.h\" /* ZS2_isPower2 */\n\n/*-*************************************\n*  Constants\n***************************************/\n\n/* Since the workspace is effectively its own little malloc implementation /\n * arena, when we run under ASAN, we should similarly insert redzones between\n * each internal element of the workspace, so ASAN will catch overruns that\n * reach outside an object but that stay inside the workspace.\n *\n * This defines the size of that redzone.\n */\n#ifndef ZSTD_CWKSP_ASAN_REDZONE_SIZE\n#define ZSTD_CWKSP_ASAN_REDZONE_SIZE 128\n#endif\n\n\n/* Set our tables and aligneds to align by 64 bytes */\n#define ZSTD_CWKSP_ALIGNMENT_BYTES 64\n\n/*-*************************************\n*  Structures\n***************************************/\ntypedef enum {\n    ZSTD_cwksp_alloc_objects,\n    ZSTD_cwksp_alloc_aligned_init_once,\n    ZSTD_cwksp_alloc_aligned,\n    ZSTD_cwksp_alloc_buffers\n} ZSTD_cwksp_alloc_phase_e;\n\n/**\n * Used to describe whether the workspace is statically allocated (and will not\n * necessarily ever be freed), or if it's dynamically allocated and we can\n * expect a well-formed caller to free this.\n */\ntypedef enum {\n    ZSTD_cwksp_dynamic_alloc,\n    ZSTD_cwksp_static_alloc\n} ZSTD_cwksp_static_alloc_e;\n\n/**\n * Zstd fits all its internal datastructures into a single continuous buffer,\n * so that it only needs to perform a single OS allocation (or so that a buffer\n * can be provided to it and it can perform no allocations at all). This buffer\n * is called the workspace.\n *\n * Several optimizations complicate that process of allocating memory ranges\n * from this workspace for each internal datastructure:\n *\n * - These different internal datastructures have different setup requirements:\n *\n *   - The static objects need to be cleared once and can then be trivially\n *     reused for each compression.\n *\n *   - Various buffers don't need to be initialized at all--they are always\n *     written into before they're read.\n *\n *   - The matchstate tables have a unique requirement that they don't need\n *     their memory to be totally cleared, but they do need the memory to have\n *     some bound, i.e., a guarantee that all values in the memory they've been\n *     allocated is less than some maximum value (which is the starting value\n *     for the indices that they will then use for compression). When this\n *     guarantee is provided to them, they can use the memory without any setup\n *     work. When it can't, they have to clear the area.\n *\n * - These buffers also have different alignment requirements.\n *\n * - We would like to reuse the objects in the workspace for multiple\n *   compressions without having to perform any expensive reallocation or\n *   reinitialization work.\n *\n * - We would like to be able to efficiently reuse the workspace across\n *   multiple compressions **even when the compression parameters change** and\n *   we need to resize some of the objects (where possible).\n *\n * To attempt to manage this buffer, given these constraints, the ZSTD_cwksp\n * abstraction was created. It works as follows:\n *\n * Workspace Layout:\n *\n * [                        ... workspace ...                           ]\n * [objects][tables ->] free space [<- buffers][<- aligned][<- init once]\n *\n * The various objects that live in the workspace are divided into the\n * following categories, and are allocated separately:\n *\n * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict,\n *   so that literally everything fits in a single buffer. Note: if present,\n *   this must be the first object in the workspace, since ZSTD_customFree{CCtx,\n *   CDict}() rely on a pointer comparison to see whether one or two frees are\n *   required.\n *\n * - Fixed size objects: these are fixed-size, fixed-count objects that are\n *   nonetheless \"dynamically\" allocated in the workspace so that we can\n *   control how they're initialized separately from the broader ZSTD_CCtx.\n *   Examples:\n *   - Entropy Workspace\n *   - 2 x ZSTD_compressedBlockState_t\n *   - CDict dictionary contents\n *\n * - Tables: these are any of several different datastructures (hash tables,\n *   chain tables, binary trees) that all respect a common format: they are\n *   uint32_t arrays, all of whose values are between 0 and (nextSrc - base).\n *   Their sizes depend on the cparams. These tables are 64-byte aligned.\n *\n * - Init once: these buffers require to be initialized at least once before\n *   use. They should be used when we want to skip memory initialization\n *   while not triggering memory checkers (like Valgrind) when reading from\n *   from this memory without writing to it first.\n *   These buffers should be used carefully as they might contain data\n *   from previous compressions.\n *   Buffers are aligned to 64 bytes.\n *\n * - Aligned: these buffers don't require any initialization before they're\n *   used. The user of the buffer should make sure they write into a buffer\n *   location before reading from it.\n *   Buffers are aligned to 64 bytes.\n *\n * - Buffers: these buffers are used for various purposes that don't require\n *   any alignment or initialization before they're used. This means they can\n *   be moved around at no cost for a new compression.\n *\n * Allocating Memory:\n *\n * The various types of objects must be allocated in order, so they can be\n * correctly packed into the workspace buffer. That order is:\n *\n * 1. Objects\n * 2. Init once / Tables\n * 3. Aligned / Tables\n * 4. Buffers / Tables\n *\n * Attempts to reserve objects of different types out of order will fail.\n */\ntypedef struct {\n    void* workspace;\n    void* workspaceEnd;\n\n    void* objectEnd;\n    void* tableEnd;\n    void* tableValidEnd;\n    void* allocStart;\n    void* initOnceStart;\n\n    BYTE allocFailed;\n    int workspaceOversizedDuration;\n    ZSTD_cwksp_alloc_phase_e phase;\n    ZSTD_cwksp_static_alloc_e isStatic;\n} ZSTD_cwksp;\n\n/*-*************************************\n*  Functions\n***************************************/\n\nMEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws);\nMEM_STATIC void*  ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws);\n\nMEM_STATIC void ZSTD_cwksp_assert_internal_consistency(ZSTD_cwksp* ws) {\n    (void)ws;\n    assert(ws->workspace <= ws->objectEnd);\n    assert(ws->objectEnd <= ws->tableEnd);\n    assert(ws->objectEnd <= ws->tableValidEnd);\n    assert(ws->tableEnd <= ws->allocStart);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    assert(ws->allocStart <= ws->workspaceEnd);\n    assert(ws->initOnceStart <= ZSTD_cwksp_initialAllocStart(ws));\n    assert(ws->workspace <= ws->initOnceStart);\n#if ZSTD_MEMORY_SANITIZER\n    {\n        intptr_t const offset = __msan_test_shadow(ws->initOnceStart,\n            (U8*)ZSTD_cwksp_initialAllocStart(ws) - (U8*)ws->initOnceStart);\n        (void)offset;\n#if defined(ZSTD_MSAN_PRINT)\n        if(offset!=-1) {\n            __msan_print_shadow((U8*)ws->initOnceStart + offset - 8, 32);\n        }\n#endif\n        assert(offset==-1);\n    };\n#endif\n}\n\n/**\n * Align must be a power of 2.\n */\nMEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t align) {\n    size_t const mask = align - 1;\n    assert(ZSTD_isPower2(align));\n    return (size + mask) & ~mask;\n}\n\n/**\n * Use this to determine how much space in the workspace we will consume to\n * allocate this object. (Normally it should be exactly the size of the object,\n * but under special conditions, like ASAN, where we pad each object, it might\n * be larger.)\n *\n * Since tables aren't currently redzoned, you don't need to call through this\n * to figure out how much space you need for the matchState tables. Everything\n * else is though.\n *\n * Do not use for sizing aligned buffers. Instead, use ZSTD_cwksp_aligned64_alloc_size().\n */\nMEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) {\n    if (size == 0)\n        return 0;\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n#else\n    return size;\n#endif\n}\n\nMEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size, size_t alignment) {\n    return ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(size, alignment));\n}\n\n/**\n * Returns an adjusted alloc size that is the nearest larger multiple of 64 bytes.\n * Used to determine the number of bytes required for a given \"aligned\".\n */\nMEM_STATIC size_t ZSTD_cwksp_aligned64_alloc_size(size_t size) {\n    return ZSTD_cwksp_aligned_alloc_size(size, ZSTD_CWKSP_ALIGNMENT_BYTES);\n}\n\n/**\n * Returns the amount of additional space the cwksp must allocate\n * for internal purposes (currently only alignment).\n */\nMEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {\n    /* For alignment, the wksp will always allocate an additional 2*ZSTD_CWKSP_ALIGNMENT_BYTES\n     * bytes to align the beginning of tables section and end of buffers;\n     */\n    size_t const slackSpace = ZSTD_CWKSP_ALIGNMENT_BYTES * 2;\n    return slackSpace;\n}\n\n\n/**\n * Return the number of additional bytes required to align a pointer to the given number of bytes.\n * alignBytes must be a power of two.\n */\nMEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignBytes) {\n    size_t const alignBytesMask = alignBytes - 1;\n    size_t const bytes = (alignBytes - ((size_t)ptr & (alignBytesMask))) & alignBytesMask;\n    assert(ZSTD_isPower2(alignBytes));\n    assert(bytes < alignBytes);\n    return bytes;\n}\n\n/**\n * Returns the initial value for allocStart which is used to determine the position from\n * which we can allocate from the end of the workspace.\n */\nMEM_STATIC void*  ZSTD_cwksp_initialAllocStart(ZSTD_cwksp* ws)\n{\n    char* endPtr = (char*)ws->workspaceEnd;\n    assert(ZSTD_isPower2(ZSTD_CWKSP_ALIGNMENT_BYTES));\n    endPtr = endPtr - ((size_t)endPtr % ZSTD_CWKSP_ALIGNMENT_BYTES);\n    return (void*)endPtr;\n}\n\n/**\n * Internal function. Do not use directly.\n * Reserves the given number of bytes within the aligned/buffer segment of the wksp,\n * which counts from the end of the wksp (as opposed to the object/table segment).\n *\n * Returns a pointer to the beginning of that space.\n */\nMEM_STATIC void*\nZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes)\n{\n    void* const alloc = (BYTE*)ws->allocStart - bytes;\n    void* const bottom = ws->tableEnd;\n    DEBUGLOG(5, \"cwksp: reserving [0x%p]:%zd bytes; %zd bytes remaining\",\n        alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);\n    ZSTD_cwksp_assert_internal_consistency(ws);\n    assert(alloc >= bottom);\n    if (alloc < bottom) {\n        DEBUGLOG(4, \"cwksp: alloc failed!\");\n        ws->allocFailed = 1;\n        return NULL;\n    }\n    /* the area is reserved from the end of wksp.\n     * If it overlaps with tableValidEnd, it voids guarantees on values' range */\n    if (alloc < ws->tableValidEnd) {\n        ws->tableValidEnd = alloc;\n    }\n    ws->allocStart = alloc;\n    return alloc;\n}\n\n/**\n * Moves the cwksp to the next phase, and does any necessary allocations.\n * cwksp initialization must necessarily go through each phase in order.\n * Returns a 0 on success, or zstd error\n */\nMEM_STATIC size_t\nZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase)\n{\n    assert(phase >= ws->phase);\n    if (phase > ws->phase) {\n        /* Going from allocating objects to allocating initOnce / tables */\n        if (ws->phase < ZSTD_cwksp_alloc_aligned_init_once &&\n            phase >= ZSTD_cwksp_alloc_aligned_init_once) {\n            ws->tableValidEnd = ws->objectEnd;\n            ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws);\n\n            {   /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */\n                void *const alloc = ws->objectEnd;\n                size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES);\n                void *const objectEnd = (BYTE *) alloc + bytesToAlign;\n                DEBUGLOG(5, \"reserving table alignment addtl space: %zu\", bytesToAlign);\n                RETURN_ERROR_IF(objectEnd > ws->workspaceEnd, memory_allocation,\n                                \"table phase - alignment initial allocation failed!\");\n                ws->objectEnd = objectEnd;\n                ws->tableEnd = objectEnd;  /* table area starts being empty */\n                if (ws->tableValidEnd < ws->tableEnd) {\n                    ws->tableValidEnd = ws->tableEnd;\n                }\n            }\n        }\n        ws->phase = phase;\n        ZSTD_cwksp_assert_internal_consistency(ws);\n    }\n    return 0;\n}\n\n/**\n * Returns whether this object/buffer/etc was allocated in this workspace.\n */\nMEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr)\n{\n    return (ptr != NULL) && (ws->workspace <= ptr) && (ptr < ws->workspaceEnd);\n}\n\n/**\n * Internal function. Do not use directly.\n */\nMEM_STATIC void*\nZSTD_cwksp_reserve_internal(ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase)\n{\n    void* alloc;\n    if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) {\n        return NULL;\n    }\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* over-reserve space */\n    bytes += 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n#endif\n\n    alloc = ZSTD_cwksp_reserve_internal_buffer_space(ws, bytes);\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on\n     * either size. */\n    if (alloc) {\n        alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n        if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n            /* We need to keep the redzone poisoned while unpoisoning the bytes that\n             * are actually allocated. */\n            __asan_unpoison_memory_region(alloc, bytes - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE);\n        }\n    }\n#endif\n\n    return alloc;\n}\n\n/**\n * Reserves and returns unaligned memory.\n */\nMEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes)\n{\n    return (BYTE*)ZSTD_cwksp_reserve_internal(ws, bytes, ZSTD_cwksp_alloc_buffers);\n}\n\n/**\n * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).\n * This memory has been initialized at least once in the past.\n * This doesn't mean it has been initialized this time, and it might contain data from previous\n * operations.\n * The main usage is for algorithms that might need read access into uninitialized memory.\n * The algorithm must maintain safety under these conditions and must make sure it doesn't\n * leak any of the past data (directly or in side channels).\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_aligned_init_once(ZSTD_cwksp* ws, size_t bytes)\n{\n    size_t const alignedBytes = ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES);\n    void* ptr = ZSTD_cwksp_reserve_internal(ws, alignedBytes, ZSTD_cwksp_alloc_aligned_init_once);\n    assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    if(ptr && ptr < ws->initOnceStart) {\n        /* We assume the memory following the current allocation is either:\n         * 1. Not usable as initOnce memory (end of workspace)\n         * 2. Another initOnce buffer that has been allocated before (and so was previously memset)\n         * 3. An ASAN redzone, in which case we don't want to write on it\n         * For these reasons it should be fine to not explicitly zero every byte up to ws->initOnceStart.\n         * Note that we assume here that MSAN and ASAN cannot run in the same time. */\n        ZSTD_memset(ptr, 0, MIN((size_t)((U8*)ws->initOnceStart - (U8*)ptr), alignedBytes));\n        ws->initOnceStart = ptr;\n    }\n#if ZSTD_MEMORY_SANITIZER\n    assert(__msan_test_shadow(ptr, bytes) == -1);\n#endif\n    return ptr;\n}\n\n/**\n * Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_aligned64(ZSTD_cwksp* ws, size_t bytes)\n{\n    void* const ptr = ZSTD_cwksp_reserve_internal(ws,\n                        ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),\n                        ZSTD_cwksp_alloc_aligned);\n    assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    return ptr;\n}\n\n/**\n * Aligned on 64 bytes. These buffers have the special property that\n * their values remain constrained, allowing us to reuse them without\n * memset()-ing them.\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes)\n{\n    const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned_init_once;\n    void* alloc;\n    void* end;\n    void* top;\n\n    /* We can only start allocating tables after we are done reserving space for objects at the\n     * start of the workspace */\n    if(ws->phase < phase) {\n        if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase))) {\n            return NULL;\n        }\n    }\n    alloc = ws->tableEnd;\n    end = (BYTE *)alloc + bytes;\n    top = ws->allocStart;\n\n    DEBUGLOG(5, \"cwksp: reserving %p table %zd bytes, %zd bytes remaining\",\n        alloc, bytes, ZSTD_cwksp_available_space(ws) - bytes);\n    assert((bytes & (sizeof(U32)-1)) == 0);\n    ZSTD_cwksp_assert_internal_consistency(ws);\n    assert(end <= top);\n    if (end > top) {\n        DEBUGLOG(4, \"cwksp: table alloc failed!\");\n        ws->allocFailed = 1;\n        return NULL;\n    }\n    ws->tableEnd = end;\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        __asan_unpoison_memory_region(alloc, bytes);\n    }\n#endif\n\n    assert((bytes & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    assert(((size_t)alloc & (ZSTD_CWKSP_ALIGNMENT_BYTES-1)) == 0);\n    return alloc;\n}\n\n/**\n * Aligned on sizeof(void*).\n * Note : should happen only once, at workspace first initialization\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes)\n{\n    size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*));\n    void* alloc = ws->objectEnd;\n    void* end = (BYTE*)alloc + roundedBytes;\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* over-reserve space */\n    end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n#endif\n\n    DEBUGLOG(4,\n        \"cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining\",\n        alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes);\n    assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0);\n    assert(bytes % ZSTD_ALIGNOF(void*) == 0);\n    ZSTD_cwksp_assert_internal_consistency(ws);\n    /* we must be in the first phase, no advance is possible */\n    if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) {\n        DEBUGLOG(3, \"cwksp: object alloc failed!\");\n        ws->allocFailed = 1;\n        return NULL;\n    }\n    ws->objectEnd = end;\n    ws->tableEnd = end;\n    ws->tableValidEnd = end;\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on\n     * either size. */\n    alloc = (BYTE*)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        __asan_unpoison_memory_region(alloc, bytes);\n    }\n#endif\n\n    return alloc;\n}\n/**\n * with alignment control\n * Note : should happen only once, at workspace first initialization\n */\nMEM_STATIC void* ZSTD_cwksp_reserve_object_aligned(ZSTD_cwksp* ws, size_t byteSize, size_t alignment)\n{\n    size_t const mask = alignment - 1;\n    size_t const surplus = (alignment > sizeof(void*)) ? alignment - sizeof(void*) : 0;\n    void* const start = ZSTD_cwksp_reserve_object(ws, byteSize + surplus);\n    if (start == NULL) return NULL;\n    if (surplus == 0) return start;\n    assert(ZSTD_isPower2(alignment));\n    return (void*)(((size_t)start + surplus) & ~mask);\n}\n\nMEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws)\n{\n    DEBUGLOG(4, \"cwksp: ZSTD_cwksp_mark_tables_dirty\");\n\n#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    /* To validate that the table reuse logic is sound, and that we don't\n     * access table space that we haven't cleaned, we re-\"poison\" the table\n     * space every time we mark it dirty.\n     * Since tableValidEnd space and initOnce space may overlap we don't poison\n     * the initOnce portion as it break its promise. This means that this poisoning\n     * check isn't always applied fully. */\n    {\n        size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;\n        assert(__msan_test_shadow(ws->objectEnd, size) == -1);\n        if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) {\n            __msan_poison(ws->objectEnd, size);\n        } else {\n            assert(ws->initOnceStart >= ws->objectEnd);\n            __msan_poison(ws->objectEnd, (BYTE*)ws->initOnceStart - (BYTE*)ws->objectEnd);\n        }\n    }\n#endif\n\n    assert(ws->tableValidEnd >= ws->objectEnd);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    ws->tableValidEnd = ws->objectEnd;\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\nMEM_STATIC void ZSTD_cwksp_mark_tables_clean(ZSTD_cwksp* ws) {\n    DEBUGLOG(4, \"cwksp: ZSTD_cwksp_mark_tables_clean\");\n    assert(ws->tableValidEnd >= ws->objectEnd);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    if (ws->tableValidEnd < ws->tableEnd) {\n        ws->tableValidEnd = ws->tableEnd;\n    }\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\n/**\n * Zero the part of the allocated tables not already marked clean.\n */\nMEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) {\n    DEBUGLOG(4, \"cwksp: ZSTD_cwksp_clean_tables\");\n    assert(ws->tableValidEnd >= ws->objectEnd);\n    assert(ws->tableValidEnd <= ws->allocStart);\n    if (ws->tableValidEnd < ws->tableEnd) {\n        ZSTD_memset(ws->tableValidEnd, 0, (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd));\n    }\n    ZSTD_cwksp_mark_tables_clean(ws);\n}\n\n/**\n * Invalidates table allocations.\n * All other allocations remain valid.\n */\nMEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws)\n{\n    DEBUGLOG(4, \"cwksp: clearing tables!\");\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* We don't do this when the workspace is statically allocated, because\n     * when that is the case, we have no capability to hook into the end of the\n     * workspace's lifecycle to unpoison the memory.\n     */\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd;\n        __asan_poison_memory_region(ws->objectEnd, size);\n    }\n#endif\n\n    ws->tableEnd = ws->objectEnd;\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\n/**\n * Invalidates all buffer, aligned, and table allocations.\n * Object allocations remain valid.\n */\nMEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) {\n    DEBUGLOG(4, \"cwksp: clearing!\");\n\n#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    /* To validate that the context reuse logic is sound, and that we don't\n     * access stuff that this compression hasn't initialized, we re-\"poison\"\n     * the workspace except for the areas in which we expect memory reuse\n     * without initialization (objects, valid tables area and init once\n     * memory). */\n    {\n        if((BYTE*)ws->tableValidEnd < (BYTE*)ws->initOnceStart) {\n            size_t size = (BYTE*)ws->initOnceStart - (BYTE*)ws->tableValidEnd;\n            __msan_poison(ws->tableValidEnd, size);\n        }\n    }\n#endif\n\n#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)\n    /* We don't do this when the workspace is statically allocated, because\n     * when that is the case, we have no capability to hook into the end of the\n     * workspace's lifecycle to unpoison the memory.\n     */\n    if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {\n        size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd;\n        __asan_poison_memory_region(ws->objectEnd, size);\n    }\n#endif\n\n    ws->tableEnd = ws->objectEnd;\n    ws->allocStart = ZSTD_cwksp_initialAllocStart(ws);\n    ws->allocFailed = 0;\n    if (ws->phase > ZSTD_cwksp_alloc_aligned_init_once) {\n        ws->phase = ZSTD_cwksp_alloc_aligned_init_once;\n    }\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\nMEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) {\n    return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace);\n}\n\nMEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) {\n    return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace)\n         + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart);\n}\n\n/**\n * The provided workspace takes ownership of the buffer [start, start+size).\n * Any existing values in the workspace are ignored (the previously managed\n * buffer, if present, must be separately freed).\n */\nMEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) {\n    DEBUGLOG(4, \"cwksp: init'ing workspace with %zd bytes\", size);\n    assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */\n    ws->workspace = start;\n    ws->workspaceEnd = (BYTE*)start + size;\n    ws->objectEnd = ws->workspace;\n    ws->tableValidEnd = ws->objectEnd;\n    ws->initOnceStart = ZSTD_cwksp_initialAllocStart(ws);\n    ws->phase = ZSTD_cwksp_alloc_objects;\n    ws->isStatic = isStatic;\n    ZSTD_cwksp_clear(ws);\n    ws->workspaceOversizedDuration = 0;\n    ZSTD_cwksp_assert_internal_consistency(ws);\n}\n\nMEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) {\n    void* workspace = ZSTD_customMalloc(size, customMem);\n    DEBUGLOG(4, \"cwksp: creating new workspace with %zd bytes\", size);\n    RETURN_ERROR_IF(workspace == NULL, memory_allocation, \"NULL pointer!\");\n    ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc);\n    return 0;\n}\n\nMEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) {\n    void *ptr = ws->workspace;\n    DEBUGLOG(4, \"cwksp: freeing workspace\");\n#if ZSTD_MEMORY_SANITIZER && !defined(ZSTD_MSAN_DONT_POISON_WORKSPACE)\n    if (ptr != NULL && customMem.customFree != NULL) {\n        __msan_unpoison(ptr, ZSTD_cwksp_sizeof(ws));\n    }\n#endif\n    ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp));\n    ZSTD_customFree(ptr, customMem);\n}\n\n/**\n * Moves the management of a workspace from one cwksp to another. The src cwksp\n * is left in an invalid state (src must be re-init()'ed before it's used again).\n */\nMEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) {\n    *dst = *src;\n    ZSTD_memset(src, 0, sizeof(ZSTD_cwksp));\n}\n\nMEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) {\n    return ws->allocFailed;\n}\n\n/*-*************************************\n*  Functions Checking Free Space\n***************************************/\n\n/* ZSTD_alignmentSpaceWithinBounds() :\n * Returns if the estimated space needed for a wksp is within an acceptable limit of the\n * actual amount of space used.\n */\nMEM_STATIC int ZSTD_cwksp_estimated_space_within_bounds(const ZSTD_cwksp *const ws, size_t const estimatedSpace) {\n    /* We have an alignment space between objects and tables between tables and buffers, so we can have up to twice\n     * the alignment bytes difference between estimation and actual usage */\n    return (estimatedSpace - ZSTD_cwksp_slack_space_required()) <= ZSTD_cwksp_used(ws) &&\n           ZSTD_cwksp_used(ws) <= estimatedSpace;\n}\n\n\nMEM_STATIC size_t ZSTD_cwksp_available_space(ZSTD_cwksp* ws) {\n    return (size_t)((BYTE*)ws->allocStart - (BYTE*)ws->tableEnd);\n}\n\nMEM_STATIC int ZSTD_cwksp_check_available(ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    return ZSTD_cwksp_available_space(ws) >= additionalNeededSpace;\n}\n\nMEM_STATIC int ZSTD_cwksp_check_too_large(ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    return ZSTD_cwksp_check_available(\n        ws, additionalNeededSpace * ZSTD_WORKSPACETOOLARGE_FACTOR);\n}\n\nMEM_STATIC int ZSTD_cwksp_check_wasteful(ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    return ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)\n        && ws->workspaceOversizedDuration > ZSTD_WORKSPACETOOLARGE_MAXDURATION;\n}\n\nMEM_STATIC void ZSTD_cwksp_bump_oversized_duration(\n        ZSTD_cwksp* ws, size_t additionalNeededSpace) {\n    if (ZSTD_cwksp_check_too_large(ws, additionalNeededSpace)) {\n        ws->workspaceOversizedDuration++;\n    } else {\n        ws->workspaceOversizedDuration = 0;\n    }\n}\n\n#endif /* ZSTD_CWKSP_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_double_fast.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"\n#include \"zstd_double_fast.h\"\n\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillDoubleHashTableForCDict(ZSTD_MatchState_t* ms,\n                              void const* end, ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashLarge = ms->hashTable;\n    U32  const hBitsL = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    U32  const mls = cParams->minMatch;\n    U32* const hashSmall = ms->chainTable;\n    U32  const hBitsS = cParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Always insert every fastHashFillStep position into the hash tables.\n     * Insert the other positions into the large hash table if their entry\n     * is empty.\n     */\n    for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        U32 i;\n        for (i = 0; i < fastHashFillStep; ++i) {\n            size_t const smHashAndTag = ZSTD_hashPtr(ip + i, hBitsS, mls);\n            size_t const lgHashAndTag = ZSTD_hashPtr(ip + i, hBitsL, 8);\n            if (i == 0) {\n                ZSTD_writeTaggedIndex(hashSmall, smHashAndTag, curr + i);\n            }\n            if (i == 0 || hashLarge[lgHashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) {\n                ZSTD_writeTaggedIndex(hashLarge, lgHashAndTag, curr + i);\n            }\n            /* Only load extra positions for ZSTD_dtlm_full */\n            if (dtlm == ZSTD_dtlm_fast)\n                break;\n    }   }\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillDoubleHashTableForCCtx(ZSTD_MatchState_t* ms,\n                              void const* end, ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashLarge = ms->hashTable;\n    U32  const hBitsL = cParams->hashLog;\n    U32  const mls = cParams->minMatch;\n    U32* const hashSmall = ms->chainTable;\n    U32  const hBitsS = cParams->chainLog;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Always insert every fastHashFillStep position into the hash tables.\n     * Insert the other positions into the large hash table if their entry\n     * is empty.\n     */\n    for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        U32 i;\n        for (i = 0; i < fastHashFillStep; ++i) {\n            size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls);\n            size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8);\n            if (i == 0)\n                hashSmall[smHash] = curr + i;\n            if (i == 0 || hashLarge[lgHash] == 0)\n                hashLarge[lgHash] = curr + i;\n            /* Only load extra positions for ZSTD_dtlm_full */\n            if (dtlm == ZSTD_dtlm_fast)\n                break;\n        }   }\n}\n\nvoid ZSTD_fillDoubleHashTable(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp)\n{\n    if (tfp == ZSTD_tfp_forCDict) {\n        ZSTD_fillDoubleHashTableForCDict(ms, end, dtlm);\n    } else {\n        ZSTD_fillDoubleHashTableForCCtx(ms, end, dtlm);\n    }\n}\n\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_doubleFast_noDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize, U32 const mls /* template */)\n{\n    ZSTD_compressionParameters const* cParams = &ms->cParams;\n    U32* const hashLong = ms->hashTable;\n    const U32 hBitsL = cParams->hashLog;\n    U32* const hashSmall = ms->chainTable;\n    const U32 hBitsS = cParams->chainLog;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* anchor = istart;\n    const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);\n    /* presumes that, if there is a dictionary, it must be using Attach mode */\n    const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);\n    const BYTE* const prefixLowest = base + prefixLowestIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n    U32 offset_1=rep[0], offset_2=rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    size_t mLength;\n    U32 offset;\n    U32 curr;\n\n    /* how many positions to search before increasing step size */\n    const size_t kStepIncr = 1 << kSearchStrength;\n    /* the position at which to increment the step size if no match is found */\n    const BYTE* nextStep;\n    size_t step; /* the current step size */\n\n    size_t hl0; /* the long hash at ip */\n    size_t hl1; /* the long hash at ip1 */\n\n    U32 idxl0; /* the long match index for ip */\n    U32 idxl1; /* the long match index for ip1 */\n\n    const BYTE* matchl0; /* the long match for ip */\n    const BYTE* matchs0; /* the short match for ip */\n    const BYTE* matchl1; /* the long match for ip1 */\n    const BYTE* matchs0_safe; /* matchs0 or safe address */\n\n    const BYTE* ip = istart; /* the current position */\n    const BYTE* ip1; /* the next position */\n    /* Array of ~random data, should have low probability of matching data\n     * we load from here instead of from tables, if matchl0/matchl1 are\n     * invalid indices. Used to avoid unpredictable branches. */\n    const BYTE dummy[] = {0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0,0xe2,0xb4};\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_doubleFast_noDict_generic\");\n\n    /* init */\n    ip += ((ip - prefixLowest) == 0);\n    {\n        U32 const current = (U32)(ip - base);\n        U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog);\n        U32 const maxRep = current - windowLow;\n        if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0;\n        if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0;\n    }\n\n    /* Outer Loop: one iteration per match found and stored */\n    while (1) {\n        step = 1;\n        nextStep = ip + kStepIncr;\n        ip1 = ip + step;\n\n        if (ip1 > ilimit) {\n            goto _cleanup;\n        }\n\n        hl0 = ZSTD_hashPtr(ip, hBitsL, 8);\n        idxl0 = hashLong[hl0];\n        matchl0 = base + idxl0;\n\n        /* Inner Loop: one iteration per search / position */\n        do {\n            const size_t hs0 = ZSTD_hashPtr(ip, hBitsS, mls);\n            const U32 idxs0 = hashSmall[hs0];\n            curr = (U32)(ip-base);\n            matchs0 = base + idxs0;\n\n            hashLong[hl0] = hashSmall[hs0] = curr;   /* update hash tables */\n\n            /* check noDict repcode */\n            if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {\n                mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;\n                ip++;\n                ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n                goto _match_stored;\n            }\n\n            hl1 = ZSTD_hashPtr(ip1, hBitsL, 8);\n\n            /* idxl0 > prefixLowestIndex is a (somewhat) unpredictable branch.\n             * However expression below complies into conditional move. Since\n             * match is unlikely and we only *branch* on idxl0 > prefixLowestIndex\n             * if there is a match, all branches become predictable. */\n            {   const BYTE*  const matchl0_safe = ZSTD_selectAddr(idxl0, prefixLowestIndex, matchl0, &dummy[0]);\n\n                /* check prefix long match */\n                if (MEM_read64(matchl0_safe) == MEM_read64(ip) && matchl0_safe == matchl0) {\n                    mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8;\n                    offset = (U32)(ip-matchl0);\n                    while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */\n                    goto _match_found;\n            }   }\n\n            idxl1 = hashLong[hl1];\n            matchl1 = base + idxl1;\n\n            /* Same optimization as matchl0 above */\n            matchs0_safe = ZSTD_selectAddr(idxs0, prefixLowestIndex, matchs0, &dummy[0]);\n\n            /* check prefix short match */\n            if(MEM_read32(matchs0_safe) == MEM_read32(ip) && matchs0_safe == matchs0) {\n                  goto _search_next_long;\n            }\n\n            if (ip1 >= nextStep) {\n                PREFETCH_L1(ip1 + 64);\n                PREFETCH_L1(ip1 + 128);\n                step++;\n                nextStep += kStepIncr;\n            }\n            ip = ip1;\n            ip1 += step;\n\n            hl0 = hl1;\n            idxl0 = idxl1;\n            matchl0 = matchl1;\n    #if defined(__aarch64__)\n            PREFETCH_L1(ip+256);\n    #endif\n        } while (ip1 <= ilimit);\n\n_cleanup:\n        /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0),\n         * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */\n        offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n        /* save reps for next block */\n        rep[0] = offset_1 ? offset_1 : offsetSaved1;\n        rep[1] = offset_2 ? offset_2 : offsetSaved2;\n\n        /* Return the last literals size */\n        return (size_t)(iend - anchor);\n\n_search_next_long:\n\n        /* short match found: let's check for a longer one */\n        mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4;\n        offset = (U32)(ip - matchs0);\n\n        /* check long match at +1 position */\n        if ((idxl1 > prefixLowestIndex) && (MEM_read64(matchl1) == MEM_read64(ip1))) {\n            size_t const l1len = ZSTD_count(ip1+8, matchl1+8, iend) + 8;\n            if (l1len > mLength) {\n                /* use the long match instead */\n                ip = ip1;\n                mLength = l1len;\n                offset = (U32)(ip-matchl1);\n                matchs0 = matchl1;\n            }\n        }\n\n        while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* complete backward */\n\n        /* fall-through */\n\n_match_found: /* requires ip, offset, mLength */\n        offset_2 = offset_1;\n        offset_1 = offset;\n\n        if (step < 4) {\n            /* It is unsafe to write this value back to the hashtable when ip1 is\n             * greater than or equal to the new ip we will have after we're done\n             * processing this match. Rather than perform that test directly\n             * (ip1 >= ip + mLength), which costs speed in practice, we do a simpler\n             * more predictable test. The minmatch even if we take a short match is\n             * 4 bytes, so as long as step, the distance between ip and ip1\n             * (initially) is less than 4, we know ip1 < new ip. */\n            hashLong[hl1] = (U32)(ip1 - base);\n        }\n\n        ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n_match_stored:\n        /* match found */\n        ip += mLength;\n        anchor = ip;\n\n        if (ip <= ilimit) {\n            /* Complementary insertion */\n            /* done after iLimit test, as candidates could be > iend-8 */\n            {   U32 const indexToInsert = curr+2;\n                hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;\n                hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);\n                hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;\n                hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);\n            }\n\n            /* check immediate repcode */\n            while ( (ip <= ilimit)\n                 && ( (offset_2>0)\n                    & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {\n                /* store sequence */\n                size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;\n                U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff;  /* swap offset_2 <=> offset_1 */\n                hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);\n                hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);\n                ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, rLength);\n                ip += rLength;\n                anchor = ip;\n                continue;   /* faster when present ... (?) */\n            }\n        }\n    }\n}\n\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize,\n        U32 const mls /* template */)\n{\n    ZSTD_compressionParameters const* cParams = &ms->cParams;\n    U32* const hashLong = ms->hashTable;\n    const U32 hBitsL = cParams->hashLog;\n    U32* const hashSmall = ms->chainTable;\n    const U32 hBitsS = cParams->chainLog;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);\n    /* presumes that, if there is a dictionary, it must be using Attach mode */\n    const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);\n    const BYTE* const prefixLowest = base + prefixLowestIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n    U32 offset_1=rep[0], offset_2=rep[1];\n\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const ZSTD_compressionParameters* const dictCParams = &dms->cParams;\n    const U32* const dictHashLong  = dms->hashTable;\n    const U32* const dictHashSmall = dms->chainTable;\n    const U32 dictStartIndex       = dms->window.dictLimit;\n    const BYTE* const dictBase     = dms->window.base;\n    const BYTE* const dictStart    = dictBase + dictStartIndex;\n    const BYTE* const dictEnd      = dms->window.nextSrc;\n    const U32 dictIndexDelta       = prefixLowestIndex - (U32)(dictEnd - dictBase);\n    const U32 dictHBitsL           = dictCParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    const U32 dictHBitsS           = dictCParams->chainLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    const U32 dictAndPrefixLength  = (U32)((ip - prefixLowest) + (dictEnd - dictStart));\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_doubleFast_dictMatchState_generic\");\n\n    /* if a dictionary is attached, it must be within window range */\n    assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);\n\n    if (ms->prefetchCDictTables) {\n        size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32);\n        size_t const chainTableBytes = (((size_t)1) << dictCParams->chainLog) * sizeof(U32);\n        PREFETCH_AREA(dictHashLong, hashTableBytes);\n        PREFETCH_AREA(dictHashSmall, chainTableBytes);\n    }\n\n    /* init */\n    ip += (dictAndPrefixLength == 0);\n\n    /* dictMatchState repCode checks don't currently handle repCode == 0\n     * disabling. */\n    assert(offset_1 <= dictAndPrefixLength);\n    assert(offset_2 <= dictAndPrefixLength);\n\n    /* Main Search Loop */\n    while (ip < ilimit) {   /* < instead of <=, because repcode check at (ip+1) */\n        size_t mLength;\n        U32 offset;\n        size_t const h2 = ZSTD_hashPtr(ip, hBitsL, 8);\n        size_t const h = ZSTD_hashPtr(ip, hBitsS, mls);\n        size_t const dictHashAndTagL = ZSTD_hashPtr(ip, dictHBitsL, 8);\n        size_t const dictHashAndTagS = ZSTD_hashPtr(ip, dictHBitsS, mls);\n        U32 const dictMatchIndexAndTagL = dictHashLong[dictHashAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS];\n        U32 const dictMatchIndexAndTagS = dictHashSmall[dictHashAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS];\n        int const dictTagsMatchL = ZSTD_comparePackedTags(dictMatchIndexAndTagL, dictHashAndTagL);\n        int const dictTagsMatchS = ZSTD_comparePackedTags(dictMatchIndexAndTagS, dictHashAndTagS);\n        U32 const curr = (U32)(ip-base);\n        U32 const matchIndexL = hashLong[h2];\n        U32 matchIndexS = hashSmall[h];\n        const BYTE* matchLong = base + matchIndexL;\n        const BYTE* match = base + matchIndexS;\n        const U32 repIndex = curr + 1 - offset_1;\n        const BYTE* repMatch = (repIndex < prefixLowestIndex) ?\n                               dictBase + (repIndex - dictIndexDelta) :\n                               base + repIndex;\n        hashLong[h2] = hashSmall[h] = curr;   /* update hash tables */\n\n        /* check repcode */\n        if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n            && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {\n            const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n            mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n            ip++;\n            ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n            goto _match_stored;\n        }\n\n        if ((matchIndexL >= prefixLowestIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {\n            /* check prefix long match */\n            mLength = ZSTD_count(ip+8, matchLong+8, iend) + 8;\n            offset = (U32)(ip-matchLong);\n            while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */\n            goto _match_found;\n        } else if (dictTagsMatchL) {\n            /* check dictMatchState long match */\n            U32 const dictMatchIndexL = dictMatchIndexAndTagL >> ZSTD_SHORT_CACHE_TAG_BITS;\n            const BYTE* dictMatchL = dictBase + dictMatchIndexL;\n            assert(dictMatchL < dictEnd);\n\n            if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) {\n                mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8;\n                offset = (U32)(curr - dictMatchIndexL - dictIndexDelta);\n                while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */\n                goto _match_found;\n        }   }\n\n        if (matchIndexS > prefixLowestIndex) {\n            /* short match  candidate */\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                goto _search_next_long;\n            }\n        } else if (dictTagsMatchS) {\n            /* check dictMatchState short match */\n            U32 const dictMatchIndexS = dictMatchIndexAndTagS >> ZSTD_SHORT_CACHE_TAG_BITS;\n            match = dictBase + dictMatchIndexS;\n            matchIndexS = dictMatchIndexS + dictIndexDelta;\n\n            if (match > dictStart && MEM_read32(match) == MEM_read32(ip)) {\n                goto _search_next_long;\n        }   }\n\n        ip += ((ip-anchor) >> kSearchStrength) + 1;\n#if defined(__aarch64__)\n        PREFETCH_L1(ip+256);\n#endif\n        continue;\n\n_search_next_long:\n        {   size_t const hl3 = ZSTD_hashPtr(ip+1, hBitsL, 8);\n            size_t const dictHashAndTagL3 = ZSTD_hashPtr(ip+1, dictHBitsL, 8);\n            U32 const matchIndexL3 = hashLong[hl3];\n            U32 const dictMatchIndexAndTagL3 = dictHashLong[dictHashAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS];\n            int const dictTagsMatchL3 = ZSTD_comparePackedTags(dictMatchIndexAndTagL3, dictHashAndTagL3);\n            const BYTE* matchL3 = base + matchIndexL3;\n            hashLong[hl3] = curr + 1;\n\n            /* check prefix long +1 match */\n            if ((matchIndexL3 >= prefixLowestIndex) && (MEM_read64(matchL3) == MEM_read64(ip+1))) {\n                mLength = ZSTD_count(ip+9, matchL3+8, iend) + 8;\n                ip++;\n                offset = (U32)(ip-matchL3);\n                while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */\n                goto _match_found;\n            } else if (dictTagsMatchL3) {\n                /* check dict long +1 match */\n                U32 const dictMatchIndexL3 = dictMatchIndexAndTagL3 >> ZSTD_SHORT_CACHE_TAG_BITS;\n                const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3;\n                assert(dictMatchL3 < dictEnd);\n                if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) {\n                    mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8;\n                    ip++;\n                    offset = (U32)(curr + 1 - dictMatchIndexL3 - dictIndexDelta);\n                    while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */\n                    goto _match_found;\n        }   }   }\n\n        /* if no long +1 match, explore the short match we found */\n        if (matchIndexS < prefixLowestIndex) {\n            mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;\n            offset = (U32)(curr - matchIndexS);\n            while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */\n        } else {\n            mLength = ZSTD_count(ip+4, match+4, iend) + 4;\n            offset = (U32)(ip - match);\n            while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */\n        }\n\n_match_found:\n        offset_2 = offset_1;\n        offset_1 = offset;\n\n        ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n_match_stored:\n        /* match found */\n        ip += mLength;\n        anchor = ip;\n\n        if (ip <= ilimit) {\n            /* Complementary insertion */\n            /* done after iLimit test, as candidates could be > iend-8 */\n            {   U32 const indexToInsert = curr+2;\n                hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;\n                hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);\n                hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;\n                hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);\n            }\n\n            /* check immediate repcode */\n            while (ip <= ilimit) {\n                U32 const current2 = (U32)(ip-base);\n                U32 const repIndex2 = current2 - offset_2;\n                const BYTE* repMatch2 = repIndex2 < prefixLowestIndex ?\n                        dictBase + repIndex2 - dictIndexDelta :\n                        base + repIndex2;\n                if ( (ZSTD_index_overlap_check(prefixLowestIndex, repIndex2))\n                   && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {\n                    const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;\n                    size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;\n                    U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                    hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;\n                    hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;\n                    ip += repLength2;\n                    anchor = ip;\n                    continue;\n                }\n                break;\n            }\n        }\n    }   /* while (ip < ilimit) */\n\n    /* save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n\n#define ZSTD_GEN_DFAST_FN(dictMode, mls)                                                                 \\\n    static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls(                                      \\\n            ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],                          \\\n            void const* src, size_t srcSize)                                                             \\\n    {                                                                                                    \\\n        return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \\\n    }\n\nZSTD_GEN_DFAST_FN(noDict, 4)\nZSTD_GEN_DFAST_FN(noDict, 5)\nZSTD_GEN_DFAST_FN(noDict, 6)\nZSTD_GEN_DFAST_FN(noDict, 7)\n\nZSTD_GEN_DFAST_FN(dictMatchState, 4)\nZSTD_GEN_DFAST_FN(dictMatchState, 5)\nZSTD_GEN_DFAST_FN(dictMatchState, 6)\nZSTD_GEN_DFAST_FN(dictMatchState, 7)\n\n\nsize_t ZSTD_compressBlock_doubleFast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    const U32 mls = ms->cParams.minMatch;\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_doubleFast_noDict_4(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_doubleFast_noDict_5(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_doubleFast_noDict_6(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_doubleFast_noDict_7(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n\nsize_t ZSTD_compressBlock_doubleFast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    const U32 mls = ms->cParams.minMatch;\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_4(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_5(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_6(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_doubleFast_dictMatchState_7(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_doubleFast_extDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize,\n        U32 const mls /* template */)\n{\n    ZSTD_compressionParameters const* cParams = &ms->cParams;\n    U32* const hashLong = ms->hashTable;\n    U32  const hBitsL = cParams->hashLog;\n    U32* const hashSmall = ms->chainTable;\n    U32  const hBitsS = cParams->chainLog;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - 8;\n    const BYTE* const base = ms->window.base;\n    const U32   endIndex = (U32)((size_t)(istart - base) + srcSize);\n    const U32   lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog);\n    const U32   dictStartIndex = lowLimit;\n    const U32   dictLimit = ms->window.dictLimit;\n    const U32   prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit;\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const BYTE* const dictStart = dictBase + dictStartIndex;\n    const BYTE* const dictEnd = dictBase + prefixStartIndex;\n    U32 offset_1=rep[0], offset_2=rep[1];\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_doubleFast_extDict_generic (srcSize=%zu)\", srcSize);\n\n    /* if extDict is invalidated due to maxDistance, switch to \"regular\" variant */\n    if (prefixStartIndex == dictStartIndex)\n        return ZSTD_compressBlock_doubleFast(ms, seqStore, rep, src, srcSize);\n\n    /* Search Loop */\n    while (ip < ilimit) {  /* < instead of <=, because (ip+1) */\n        const size_t hSmall = ZSTD_hashPtr(ip, hBitsS, mls);\n        const U32 matchIndex = hashSmall[hSmall];\n        const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base;\n        const BYTE* match = matchBase + matchIndex;\n\n        const size_t hLong = ZSTD_hashPtr(ip, hBitsL, 8);\n        const U32 matchLongIndex = hashLong[hLong];\n        const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base;\n        const BYTE* matchLong = matchLongBase + matchLongIndex;\n\n        const U32 curr = (U32)(ip-base);\n        const U32 repIndex = curr + 1 - offset_1;   /* offset_1 expected <= curr +1 */\n        const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;\n        const BYTE* const repMatch = repBase + repIndex;\n        size_t mLength;\n        hashSmall[hSmall] = hashLong[hLong] = curr;   /* update hash table */\n\n        if (((ZSTD_index_overlap_check(prefixStartIndex, repIndex))\n            & (offset_1 <= curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */\n          && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {\n            const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;\n            mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;\n            ip++;\n            ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n        } else {\n            if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {\n                const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;\n                const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart;\n                U32 offset;\n                mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8;\n                offset = curr - matchLongIndex;\n                while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; }   /* catch up */\n                offset_2 = offset_1;\n                offset_1 = offset;\n                ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n            } else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {\n                size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);\n                U32 const matchIndex3 = hashLong[h3];\n                const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base;\n                const BYTE* match3 = match3Base + matchIndex3;\n                U32 offset;\n                hashLong[h3] = curr + 1;\n                if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) {\n                    const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend;\n                    const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart;\n                    mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8;\n                    ip++;\n                    offset = curr+1 - matchIndex3;\n                    while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */\n                } else {\n                    const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend;\n                    const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart;\n                    mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;\n                    offset = curr - matchIndex;\n                    while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; }   /* catch up */\n                }\n                offset_2 = offset_1;\n                offset_1 = offset;\n                ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n\n            } else {\n                ip += ((ip-anchor) >> kSearchStrength) + 1;\n                continue;\n        }   }\n\n        /* move to next sequence start */\n        ip += mLength;\n        anchor = ip;\n\n        if (ip <= ilimit) {\n            /* Complementary insertion */\n            /* done after iLimit test, as candidates could be > iend-8 */\n            {   U32 const indexToInsert = curr+2;\n                hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;\n                hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);\n                hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;\n                hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);\n            }\n\n            /* check immediate repcode */\n            while (ip <= ilimit) {\n                U32 const current2 = (U32)(ip-base);\n                U32 const repIndex2 = current2 - offset_2;\n                const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;\n                if ( ((ZSTD_index_overlap_check(prefixStartIndex, repIndex2))\n                    & (offset_2 <= current2 - dictStartIndex))\n                  && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {\n                    const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;\n                    size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;\n                    U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                    hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;\n                    hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;\n                    ip += repLength2;\n                    anchor = ip;\n                    continue;\n                }\n                break;\n    }   }   }\n\n    /* save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n\nZSTD_GEN_DFAST_FN(extDict, 4)\nZSTD_GEN_DFAST_FN(extDict, 5)\nZSTD_GEN_DFAST_FN(extDict, 6)\nZSTD_GEN_DFAST_FN(extDict, 7)\n\nsize_t ZSTD_compressBlock_doubleFast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mls = ms->cParams.minMatch;\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_doubleFast_extDict_4(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_doubleFast_extDict_5(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_doubleFast_extDict_6(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_doubleFast_extDict_7(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n#endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_double_fast.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_DOUBLE_FAST_H\n#define ZSTD_DOUBLE_FAST_H\n\n#include \"../common/mem.h\"      /* U32 */\n#include \"zstd_compress_internal.h\"     /* ZSTD_CCtx, size_t */\n\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n\nvoid ZSTD_fillDoubleHashTable(ZSTD_MatchState_t* ms,\n                              void const* end, ZSTD_dictTableLoadMethod_e dtlm,\n                              ZSTD_tableFillPurpose_e tfp);\n\nsize_t ZSTD_compressBlock_doubleFast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_doubleFast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_doubleFast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST ZSTD_compressBlock_doubleFast\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE ZSTD_compressBlock_doubleFast_dictMatchState\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT ZSTD_compressBlock_doubleFast_extDict\n#else\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST NULL\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_DOUBLEFAST_EXTDICT NULL\n#endif /* ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR */\n\n#endif /* ZSTD_DOUBLE_FAST_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_fast.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"  /* ZSTD_hashPtr, ZSTD_count, ZSTD_storeSeq */\n#include \"zstd_fast.h\"\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillHashTableForCDict(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32  const hBits = cParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n    U32  const mls = cParams->minMatch;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Currently, we always use ZSTD_dtlm_full for filling CDict tables.\n     * Feel free to remove this assert if there's a good reason! */\n    assert(dtlm == ZSTD_dtlm_full);\n\n    /* Always insert every fastHashFillStep position into the hash table.\n     * Insert the other positions if their hash entry is empty.\n     */\n    for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        {   size_t const hashAndTag = ZSTD_hashPtr(ip, hBits, mls);\n            ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr);   }\n\n        if (dtlm == ZSTD_dtlm_fast) continue;\n        /* Only load extra positions for ZSTD_dtlm_full */\n        {   U32 p;\n            for (p = 1; p < fastHashFillStep; ++p) {\n                size_t const hashAndTag = ZSTD_hashPtr(ip + p, hBits, mls);\n                if (hashTable[hashAndTag >> ZSTD_SHORT_CACHE_TAG_BITS] == 0) {  /* not yet filled */\n                    ZSTD_writeTaggedIndex(hashTable, hashAndTag, curr + p);\n    }   }   }   }\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_fillHashTableForCCtx(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32  const hBits = cParams->hashLog;\n    U32  const mls = cParams->minMatch;\n    const BYTE* const base = ms->window.base;\n    const BYTE* ip = base + ms->nextToUpdate;\n    const BYTE* const iend = ((const BYTE*)end) - HASH_READ_SIZE;\n    const U32 fastHashFillStep = 3;\n\n    /* Currently, we always use ZSTD_dtlm_fast for filling CCtx tables.\n     * Feel free to remove this assert if there's a good reason! */\n    assert(dtlm == ZSTD_dtlm_fast);\n\n    /* Always insert every fastHashFillStep position into the hash table.\n     * Insert the other positions if their hash entry is empty.\n     */\n    for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) {\n        U32 const curr = (U32)(ip - base);\n        size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls);\n        hashTable[hash0] = curr;\n        if (dtlm == ZSTD_dtlm_fast) continue;\n        /* Only load extra positions for ZSTD_dtlm_full */\n        {   U32 p;\n            for (p = 1; p < fastHashFillStep; ++p) {\n                size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls);\n                if (hashTable[hash] == 0) {  /* not yet filled */\n                    hashTable[hash] = curr + p;\n    }   }   }   }\n}\n\nvoid ZSTD_fillHashTable(ZSTD_MatchState_t* ms,\n                        const void* const end,\n                        ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp)\n{\n    if (tfp == ZSTD_tfp_forCDict) {\n        ZSTD_fillHashTableForCDict(ms, end, dtlm);\n    } else {\n        ZSTD_fillHashTableForCCtx(ms, end, dtlm);\n    }\n}\n\n\ntypedef int (*ZSTD_match4Found) (const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit);\n\nstatic int\nZSTD_match4Found_cmov(const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit)\n{\n    /* Array of ~random data, should have low probability of matching data.\n     * Load from here if the index is invalid.\n     * Used to avoid unpredictable branches. */\n    static const BYTE dummy[] = {0x12,0x34,0x56,0x78};\n\n    /* currentIdx >= lowLimit is a (somewhat) unpredictable branch.\n     * However expression below compiles into conditional move.\n     */\n    const BYTE* mvalAddr = ZSTD_selectAddr(matchIdx, idxLowLimit, matchAddress, dummy);\n    /* Note: this used to be written as : return test1 && test2;\n     * Unfortunately, once inlined, these tests become branches,\n     * in which case it becomes critical that they are executed in the right order (test1 then test2).\n     * So we have to write these tests in a specific manner to ensure their ordering.\n     */\n    if (MEM_read32(currentPtr) != MEM_read32(mvalAddr)) return 0;\n    /* force ordering of these tests, which matters once the function is inlined, as they become branches */\n#if defined(__GNUC__)\n    __asm__(\"\");\n#endif\n    return matchIdx >= idxLowLimit;\n}\n\nstatic int\nZSTD_match4Found_branch(const BYTE* currentPtr, const BYTE* matchAddress, U32 matchIdx, U32 idxLowLimit)\n{\n    /* using a branch instead of a cmov,\n     * because it's faster in scenarios where matchIdx >= idxLowLimit is generally true,\n     * aka almost all candidates are within range */\n    U32 mval;\n    if (matchIdx >= idxLowLimit) {\n        mval = MEM_read32(matchAddress);\n    } else {\n        mval = MEM_read32(currentPtr) ^ 1; /* guaranteed to not match. */\n    }\n\n    return (MEM_read32(currentPtr) == mval);\n}\n\n\n/**\n * If you squint hard enough (and ignore repcodes), the search operation at any\n * given position is broken into 4 stages:\n *\n * 1. Hash   (map position to hash value via input read)\n * 2. Lookup (map hash val to index via hashtable read)\n * 3. Load   (map index to value at that position via input read)\n * 4. Compare\n *\n * Each of these steps involves a memory read at an address which is computed\n * from the previous step. This means these steps must be sequenced and their\n * latencies are cumulative.\n *\n * Rather than do 1->2->3->4 sequentially for a single position before moving\n * onto the next, this implementation interleaves these operations across the\n * next few positions:\n *\n * R = Repcode Read & Compare\n * H = Hash\n * T = Table Lookup\n * M = Match Read & Compare\n *\n * Pos | Time -->\n * ----+-------------------\n * N   | ... M\n * N+1 | ...   TM\n * N+2 |    R H   T M\n * N+3 |         H    TM\n * N+4 |           R H   T M\n * N+5 |                H   ...\n * N+6 |                  R ...\n *\n * This is very much analogous to the pipelining of execution in a CPU. And just\n * like a CPU, we have to dump the pipeline when we find a match (i.e., take a\n * branch).\n *\n * When this happens, we throw away our current state, and do the following prep\n * to re-enter the loop:\n *\n * Pos | Time -->\n * ----+-------------------\n * N   | H T\n * N+1 |  H\n *\n * This is also the work we do at the beginning to enter the loop initially.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_fast_noDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize,\n        U32 const mls, int useCmov)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32 const hlog = cParams->hashLog;\n    size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1; /* min 2 */\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const U32   endIndex = (U32)((size_t)(istart - base) + srcSize);\n    const U32   prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n\n    const BYTE* anchor = istart;\n    const BYTE* ip0 = istart;\n    const BYTE* ip1;\n    const BYTE* ip2;\n    const BYTE* ip3;\n    U32 current0;\n\n    U32 rep_offset1 = rep[0];\n    U32 rep_offset2 = rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    size_t hash0; /* hash for ip0 */\n    size_t hash1; /* hash for ip1 */\n    U32 matchIdx; /* match idx for ip0 */\n\n    U32 offcode;\n    const BYTE* match0;\n    size_t mLength;\n\n    /* ip0 and ip1 are always adjacent. The targetLength skipping and\n     * uncompressibility acceleration is applied to every other position,\n     * matching the behavior of #1562. step therefore represents the gap\n     * between pairs of positions, from ip0 to ip2 or ip1 to ip3. */\n    size_t step;\n    const BYTE* nextStep;\n    const size_t kStepIncr = (1 << (kSearchStrength - 1));\n    const ZSTD_match4Found matchFound = useCmov ? ZSTD_match4Found_cmov : ZSTD_match4Found_branch;\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_fast_generic\");\n    ip0 += (ip0 == prefixStart);\n    {   U32 const curr = (U32)(ip0 - base);\n        U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);\n        U32 const maxRep = curr - windowLow;\n        if (rep_offset2 > maxRep) offsetSaved2 = rep_offset2, rep_offset2 = 0;\n        if (rep_offset1 > maxRep) offsetSaved1 = rep_offset1, rep_offset1 = 0;\n    }\n\n    /* start each op */\n_start: /* Requires: ip0 */\n\n    step = stepSize;\n    nextStep = ip0 + kStepIncr;\n\n    /* calculate positions, ip0 - anchor == 0, so we skip step calc */\n    ip1 = ip0 + 1;\n    ip2 = ip0 + step;\n    ip3 = ip2 + 1;\n\n    if (ip3 >= ilimit) {\n        goto _cleanup;\n    }\n\n    hash0 = ZSTD_hashPtr(ip0, hlog, mls);\n    hash1 = ZSTD_hashPtr(ip1, hlog, mls);\n\n    matchIdx = hashTable[hash0];\n\n    do {\n        /* load repcode match for ip[2]*/\n        const U32 rval = MEM_read32(ip2 - rep_offset1);\n\n        /* write back hash table entry */\n        current0 = (U32)(ip0 - base);\n        hashTable[hash0] = current0;\n\n        /* check repcode at ip[2] */\n        if ((MEM_read32(ip2) == rval) & (rep_offset1 > 0)) {\n            ip0 = ip2;\n            match0 = ip0 - rep_offset1;\n            mLength = ip0[-1] == match0[-1];\n            ip0 -= mLength;\n            match0 -= mLength;\n            offcode = REPCODE1_TO_OFFBASE;\n            mLength += 4;\n\n            /* Write next hash table entry: it's already calculated.\n             * This write is known to be safe because ip1 is before the\n             * repcode (ip2). */\n            hashTable[hash1] = (U32)(ip1 - base);\n\n            goto _match;\n        }\n\n         if (matchFound(ip0, base + matchIdx, matchIdx, prefixStartIndex)) {\n            /* Write next hash table entry (it's already calculated).\n            * This write is known to be safe because the ip1 == ip0 + 1,\n            * so searching will resume after ip1 */\n            hashTable[hash1] = (U32)(ip1 - base);\n\n            goto _offset;\n        }\n\n        /* lookup ip[1] */\n        matchIdx = hashTable[hash1];\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip3;\n\n        /* write back hash table entry */\n        current0 = (U32)(ip0 - base);\n        hashTable[hash0] = current0;\n\n         if (matchFound(ip0, base + matchIdx, matchIdx, prefixStartIndex)) {\n            /* Write next hash table entry, since it's already calculated */\n            if (step <= 4) {\n                /* Avoid writing an index if it's >= position where search will resume.\n                * The minimum possible match has length 4, so search can resume at ip0 + 4.\n                */\n                hashTable[hash1] = (U32)(ip1 - base);\n            }\n            goto _offset;\n        }\n\n        /* lookup ip[1] */\n        matchIdx = hashTable[hash1];\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip0 + step;\n        ip3 = ip1 + step;\n\n        /* calculate step */\n        if (ip2 >= nextStep) {\n            step++;\n            PREFETCH_L1(ip1 + 64);\n            PREFETCH_L1(ip1 + 128);\n            nextStep += kStepIncr;\n        }\n    } while (ip3 < ilimit);\n\n_cleanup:\n    /* Note that there are probably still a couple positions one could search.\n     * However, it seems to be a meaningful performance hit to try to search\n     * them. So let's not. */\n\n    /* When the repcodes are outside of the prefix, we set them to zero before the loop.\n     * When the offsets are still zero, we need to restore them after the block to have a correct\n     * repcode history. If only one offset was invalid, it is easy. The tricky case is when both\n     * offsets were invalid. We need to figure out which offset to refill with.\n     *     - If both offsets are zero they are in the same order.\n     *     - If both offsets are non-zero, we won't restore the offsets from `offsetSaved[12]`.\n     *     - If only one is zero, we need to decide which offset to restore.\n     *         - If rep_offset1 is non-zero, then rep_offset2 must be offsetSaved1.\n     *         - It is impossible for rep_offset2 to be non-zero.\n     *\n     * So if rep_offset1 started invalid (offsetSaved1 != 0) and became valid (rep_offset1 != 0), then\n     * set rep[0] = rep_offset1 and rep[1] = offsetSaved1.\n     */\n    offsetSaved2 = ((offsetSaved1 != 0) && (rep_offset1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n    /* save reps for next block */\n    rep[0] = rep_offset1 ? rep_offset1 : offsetSaved1;\n    rep[1] = rep_offset2 ? rep_offset2 : offsetSaved2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n\n_offset: /* Requires: ip0, idx */\n\n    /* Compute the offset code. */\n    match0 = base + matchIdx;\n    rep_offset2 = rep_offset1;\n    rep_offset1 = (U32)(ip0-match0);\n    offcode = OFFSET_TO_OFFBASE(rep_offset1);\n    mLength = 4;\n\n    /* Count the backwards match length. */\n    while (((ip0>anchor) & (match0>prefixStart)) && (ip0[-1] == match0[-1])) {\n        ip0--;\n        match0--;\n        mLength++;\n    }\n\n_match: /* Requires: ip0, match0, offcode */\n\n    /* Count the forward length. */\n    mLength += ZSTD_count(ip0 + mLength, match0 + mLength, iend);\n\n    ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength);\n\n    ip0 += mLength;\n    anchor = ip0;\n\n    /* Fill table and check for immediate repcode. */\n    if (ip0 <= ilimit) {\n        /* Fill Table */\n        assert(base+current0+2 > istart);  /* check base overflow */\n        hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2;  /* here because current+2 could be > iend-8 */\n        hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);\n\n        if (rep_offset2 > 0) { /* rep_offset2==0 means rep_offset2 is invalidated */\n            while ( (ip0 <= ilimit) && (MEM_read32(ip0) == MEM_read32(ip0 - rep_offset2)) ) {\n                /* store sequence */\n                size_t const rLength = ZSTD_count(ip0+4, ip0+4-rep_offset2, iend) + 4;\n                { U32 const tmpOff = rep_offset2; rep_offset2 = rep_offset1; rep_offset1 = tmpOff; } /* swap rep_offset2 <=> rep_offset1 */\n                hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);\n                ip0 += rLength;\n                ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, REPCODE1_TO_OFFBASE, rLength);\n                anchor = ip0;\n                continue;   /* faster when present (confirmed on gcc-8) ... (?) */\n    }   }   }\n\n    goto _start;\n}\n\n#define ZSTD_GEN_FAST_FN(dictMode, mml, cmov)                                                       \\\n    static size_t ZSTD_compressBlock_fast_##dictMode##_##mml##_##cmov(                              \\\n            ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],                    \\\n            void const* src, size_t srcSize)                                                       \\\n    {                                                                                              \\\n        return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mml, cmov); \\\n    }\n\nZSTD_GEN_FAST_FN(noDict, 4, 1)\nZSTD_GEN_FAST_FN(noDict, 5, 1)\nZSTD_GEN_FAST_FN(noDict, 6, 1)\nZSTD_GEN_FAST_FN(noDict, 7, 1)\n\nZSTD_GEN_FAST_FN(noDict, 4, 0)\nZSTD_GEN_FAST_FN(noDict, 5, 0)\nZSTD_GEN_FAST_FN(noDict, 6, 0)\nZSTD_GEN_FAST_FN(noDict, 7, 0)\n\nsize_t ZSTD_compressBlock_fast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mml = ms->cParams.minMatch;\n    /* use cmov when \"candidate in range\" branch is likely unpredictable */\n    int const useCmov = ms->cParams.windowLog < 19;\n    assert(ms->dictMatchState == NULL);\n    if (useCmov) {\n        switch(mml)\n        {\n        default: /* includes case 3 */\n        case 4 :\n            return ZSTD_compressBlock_fast_noDict_4_1(ms, seqStore, rep, src, srcSize);\n        case 5 :\n            return ZSTD_compressBlock_fast_noDict_5_1(ms, seqStore, rep, src, srcSize);\n        case 6 :\n            return ZSTD_compressBlock_fast_noDict_6_1(ms, seqStore, rep, src, srcSize);\n        case 7 :\n            return ZSTD_compressBlock_fast_noDict_7_1(ms, seqStore, rep, src, srcSize);\n        }\n    } else {\n        /* use a branch instead */\n        switch(mml)\n        {\n        default: /* includes case 3 */\n        case 4 :\n            return ZSTD_compressBlock_fast_noDict_4_0(ms, seqStore, rep, src, srcSize);\n        case 5 :\n            return ZSTD_compressBlock_fast_noDict_5_0(ms, seqStore, rep, src, srcSize);\n        case 6 :\n            return ZSTD_compressBlock_fast_noDict_6_0(ms, seqStore, rep, src, srcSize);\n        case 7 :\n            return ZSTD_compressBlock_fast_noDict_7_0(ms, seqStore, rep, src, srcSize);\n        }\n    }\n}\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_fast_dictMatchState_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize, U32 const mls, U32 const hasStep)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32 const hlog = cParams->hashLog;\n    /* support stepSize of 0 */\n    U32 const stepSize = cParams->targetLength + !(cParams->targetLength);\n    const BYTE* const base = ms->window.base;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip0 = istart;\n    const BYTE* ip1 = ip0 + stepSize; /* we assert below that stepSize >= 1 */\n    const BYTE* anchor = istart;\n    const U32   prefixStartIndex = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - HASH_READ_SIZE;\n    U32 offset_1=rep[0], offset_2=rep[1];\n\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const ZSTD_compressionParameters* const dictCParams = &dms->cParams ;\n    const U32* const dictHashTable = dms->hashTable;\n    const U32 dictStartIndex       = dms->window.dictLimit;\n    const BYTE* const dictBase     = dms->window.base;\n    const BYTE* const dictStart    = dictBase + dictStartIndex;\n    const BYTE* const dictEnd      = dms->window.nextSrc;\n    const U32 dictIndexDelta       = prefixStartIndex - (U32)(dictEnd - dictBase);\n    const U32 dictAndPrefixLength  = (U32)(istart - prefixStart + dictEnd - dictStart);\n    const U32 dictHBits            = dictCParams->hashLog + ZSTD_SHORT_CACHE_TAG_BITS;\n\n    /* if a dictionary is still attached, it necessarily means that\n     * it is within window size. So we just check it. */\n    const U32 maxDistance = 1U << cParams->windowLog;\n    const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);\n    assert(endIndex - prefixStartIndex <= maxDistance);\n    (void)maxDistance; (void)endIndex;   /* these variables are not used when assert() is disabled */\n\n    (void)hasStep; /* not currently specialized on whether it's accelerated */\n\n    /* ensure there will be no underflow\n     * when translating a dict index into a local index */\n    assert(prefixStartIndex >= (U32)(dictEnd - dictBase));\n\n    if (ms->prefetchCDictTables) {\n        size_t const hashTableBytes = (((size_t)1) << dictCParams->hashLog) * sizeof(U32);\n        PREFETCH_AREA(dictHashTable, hashTableBytes);\n    }\n\n    /* init */\n    DEBUGLOG(5, \"ZSTD_compressBlock_fast_dictMatchState_generic\");\n    ip0 += (dictAndPrefixLength == 0);\n    /* dictMatchState repCode checks don't currently handle repCode == 0\n     * disabling. */\n    assert(offset_1 <= dictAndPrefixLength);\n    assert(offset_2 <= dictAndPrefixLength);\n\n    /* Outer search loop */\n    assert(stepSize >= 1);\n    while (ip1 <= ilimit) {   /* repcode check at (ip0 + 1) is safe because ip0 < ip1 */\n        size_t mLength;\n        size_t hash0 = ZSTD_hashPtr(ip0, hlog, mls);\n\n        size_t const dictHashAndTag0 = ZSTD_hashPtr(ip0, dictHBits, mls);\n        U32 dictMatchIndexAndTag = dictHashTable[dictHashAndTag0 >> ZSTD_SHORT_CACHE_TAG_BITS];\n        int dictTagsMatch = ZSTD_comparePackedTags(dictMatchIndexAndTag, dictHashAndTag0);\n\n        U32 matchIndex = hashTable[hash0];\n        U32 curr = (U32)(ip0 - base);\n        size_t step = stepSize;\n        const size_t kStepIncr = 1 << kSearchStrength;\n        const BYTE* nextStep = ip0 + kStepIncr;\n\n        /* Inner search loop */\n        while (1) {\n            const BYTE* match = base + matchIndex;\n            const U32 repIndex = curr + 1 - offset_1;\n            const BYTE* repMatch = (repIndex < prefixStartIndex) ?\n                                   dictBase + (repIndex - dictIndexDelta) :\n                                   base + repIndex;\n            const size_t hash1 = ZSTD_hashPtr(ip1, hlog, mls);\n            size_t const dictHashAndTag1 = ZSTD_hashPtr(ip1, dictHBits, mls);\n            hashTable[hash0] = curr;   /* update hash table */\n\n            if ((ZSTD_index_overlap_check(prefixStartIndex, repIndex))\n                && (MEM_read32(repMatch) == MEM_read32(ip0 + 1))) {\n                const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;\n                mLength = ZSTD_count_2segments(ip0 + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4;\n                ip0++;\n                ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, REPCODE1_TO_OFFBASE, mLength);\n                break;\n            }\n\n            if (dictTagsMatch) {\n                /* Found a possible dict match */\n                const U32 dictMatchIndex = dictMatchIndexAndTag >> ZSTD_SHORT_CACHE_TAG_BITS;\n                const BYTE* dictMatch = dictBase + dictMatchIndex;\n                if (dictMatchIndex > dictStartIndex &&\n                    MEM_read32(dictMatch) == MEM_read32(ip0)) {\n                    /* To replicate extDict parse behavior, we only use dict matches when the normal matchIndex is invalid */\n                    if (matchIndex <= prefixStartIndex) {\n                        U32 const offset = (U32) (curr - dictMatchIndex - dictIndexDelta);\n                        mLength = ZSTD_count_2segments(ip0 + 4, dictMatch + 4, iend, dictEnd, prefixStart) + 4;\n                        while (((ip0 > anchor) & (dictMatch > dictStart))\n                            && (ip0[-1] == dictMatch[-1])) {\n                            ip0--;\n                            dictMatch--;\n                            mLength++;\n                        } /* catch up */\n                        offset_2 = offset_1;\n                        offset_1 = offset;\n                        ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n                        break;\n                    }\n                }\n            }\n\n            if (ZSTD_match4Found_cmov(ip0, match, matchIndex, prefixStartIndex)) {\n                /* found a regular match of size >= 4 */\n                U32 const offset = (U32) (ip0 - match);\n                mLength = ZSTD_count(ip0 + 4, match + 4, iend) + 4;\n                while (((ip0 > anchor) & (match > prefixStart))\n                       && (ip0[-1] == match[-1])) {\n                    ip0--;\n                    match--;\n                    mLength++;\n                } /* catch up */\n                offset_2 = offset_1;\n                offset_1 = offset;\n                ZSTD_storeSeq(seqStore, (size_t) (ip0 - anchor), anchor, iend, OFFSET_TO_OFFBASE(offset), mLength);\n                break;\n            }\n\n            /* Prepare for next iteration */\n            dictMatchIndexAndTag = dictHashTable[dictHashAndTag1 >> ZSTD_SHORT_CACHE_TAG_BITS];\n            dictTagsMatch = ZSTD_comparePackedTags(dictMatchIndexAndTag, dictHashAndTag1);\n            matchIndex = hashTable[hash1];\n\n            if (ip1 >= nextStep) {\n                step++;\n                nextStep += kStepIncr;\n            }\n            ip0 = ip1;\n            ip1 = ip1 + step;\n            if (ip1 > ilimit) goto _cleanup;\n\n            curr = (U32)(ip0 - base);\n            hash0 = hash1;\n        }   /* end inner search loop */\n\n        /* match found */\n        assert(mLength);\n        ip0 += mLength;\n        anchor = ip0;\n\n        if (ip0 <= ilimit) {\n            /* Fill Table */\n            assert(base+curr+2 > istart);  /* check base overflow */\n            hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2;  /* here because curr+2 could be > iend-8 */\n            hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);\n\n            /* check immediate repcode */\n            while (ip0 <= ilimit) {\n                U32 const current2 = (U32)(ip0-base);\n                U32 const repIndex2 = current2 - offset_2;\n                const BYTE* repMatch2 = repIndex2 < prefixStartIndex ?\n                        dictBase - dictIndexDelta + repIndex2 :\n                        base + repIndex2;\n                if ( (ZSTD_index_overlap_check(prefixStartIndex, repIndex2))\n                   && (MEM_read32(repMatch2) == MEM_read32(ip0))) {\n                    const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;\n                    size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;\n                    U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                    hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = current2;\n                    ip0 += repLength2;\n                    anchor = ip0;\n                    continue;\n                }\n                break;\n            }\n        }\n\n        /* Prepare for next iteration */\n        assert(ip0 == anchor);\n        ip1 = ip0 + stepSize;\n    }\n\n_cleanup:\n    /* save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n\n\nZSTD_GEN_FAST_FN(dictMatchState, 4, 0)\nZSTD_GEN_FAST_FN(dictMatchState, 5, 0)\nZSTD_GEN_FAST_FN(dictMatchState, 6, 0)\nZSTD_GEN_FAST_FN(dictMatchState, 7, 0)\n\nsize_t ZSTD_compressBlock_fast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mls = ms->cParams.minMatch;\n    assert(ms->dictMatchState != NULL);\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_fast_dictMatchState_4_0(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_fast_dictMatchState_5_0(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_fast_dictMatchState_6_0(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_fast_dictMatchState_7_0(ms, seqStore, rep, src, srcSize);\n    }\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_fast_extDict_generic(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize, U32 const mls, U32 const hasStep)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32 const hlog = cParams->hashLog;\n    /* support stepSize of 0 */\n    size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* anchor = istart;\n    const U32   endIndex = (U32)((size_t)(istart - base) + srcSize);\n    const U32   lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog);\n    const U32   dictStartIndex = lowLimit;\n    const BYTE* const dictStart = dictBase + dictStartIndex;\n    const U32   dictLimit = ms->window.dictLimit;\n    const U32   prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit;\n    const BYTE* const prefixStart = base + prefixStartIndex;\n    const BYTE* const dictEnd = dictBase + prefixStartIndex;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - 8;\n    U32 offset_1=rep[0], offset_2=rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    const BYTE* ip0 = istart;\n    const BYTE* ip1;\n    const BYTE* ip2;\n    const BYTE* ip3;\n    U32 current0;\n\n\n    size_t hash0; /* hash for ip0 */\n    size_t hash1; /* hash for ip1 */\n    U32 idx; /* match idx for ip0 */\n    const BYTE* idxBase; /* base pointer for idx */\n\n    U32 offcode;\n    const BYTE* match0;\n    size_t mLength;\n    const BYTE* matchEnd = 0; /* initialize to avoid warning, assert != 0 later */\n\n    size_t step;\n    const BYTE* nextStep;\n    const size_t kStepIncr = (1 << (kSearchStrength - 1));\n\n    (void)hasStep; /* not currently specialized on whether it's accelerated */\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_fast_extDict_generic (offset_1=%u)\", offset_1);\n\n    /* switch to \"regular\" variant if extDict is invalidated due to maxDistance */\n    if (prefixStartIndex == dictStartIndex)\n        return ZSTD_compressBlock_fast(ms, seqStore, rep, src, srcSize);\n\n    {   U32 const curr = (U32)(ip0 - base);\n        U32 const maxRep = curr - dictStartIndex;\n        if (offset_2 >= maxRep) offsetSaved2 = offset_2, offset_2 = 0;\n        if (offset_1 >= maxRep) offsetSaved1 = offset_1, offset_1 = 0;\n    }\n\n    /* start each op */\n_start: /* Requires: ip0 */\n\n    step = stepSize;\n    nextStep = ip0 + kStepIncr;\n\n    /* calculate positions, ip0 - anchor == 0, so we skip step calc */\n    ip1 = ip0 + 1;\n    ip2 = ip0 + step;\n    ip3 = ip2 + 1;\n\n    if (ip3 >= ilimit) {\n        goto _cleanup;\n    }\n\n    hash0 = ZSTD_hashPtr(ip0, hlog, mls);\n    hash1 = ZSTD_hashPtr(ip1, hlog, mls);\n\n    idx = hashTable[hash0];\n    idxBase = idx < prefixStartIndex ? dictBase : base;\n\n    do {\n        {   /* load repcode match for ip[2] */\n            U32 const current2 = (U32)(ip2 - base);\n            U32 const repIndex = current2 - offset_1;\n            const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base;\n            U32 rval;\n            if ( ((U32)(prefixStartIndex - repIndex) >= 4) /* intentional underflow */\n                 & (offset_1 > 0) ) {\n                rval = MEM_read32(repBase + repIndex);\n            } else {\n                rval = MEM_read32(ip2) ^ 1; /* guaranteed to not match. */\n            }\n\n            /* write back hash table entry */\n            current0 = (U32)(ip0 - base);\n            hashTable[hash0] = current0;\n\n            /* check repcode at ip[2] */\n            if (MEM_read32(ip2) == rval) {\n                ip0 = ip2;\n                match0 = repBase + repIndex;\n                matchEnd = repIndex < prefixStartIndex ? dictEnd : iend;\n                assert((match0 != prefixStart) & (match0 != dictStart));\n                mLength = ip0[-1] == match0[-1];\n                ip0 -= mLength;\n                match0 -= mLength;\n                offcode = REPCODE1_TO_OFFBASE;\n                mLength += 4;\n                goto _match;\n        }   }\n\n        {   /* load match for ip[0] */\n            U32 const mval = idx >= dictStartIndex ?\n                    MEM_read32(idxBase + idx) :\n                    MEM_read32(ip0) ^ 1; /* guaranteed not to match */\n\n            /* check match at ip[0] */\n            if (MEM_read32(ip0) == mval) {\n                /* found a match! */\n                goto _offset;\n        }   }\n\n        /* lookup ip[1] */\n        idx = hashTable[hash1];\n        idxBase = idx < prefixStartIndex ? dictBase : base;\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip3;\n\n        /* write back hash table entry */\n        current0 = (U32)(ip0 - base);\n        hashTable[hash0] = current0;\n\n        {   /* load match for ip[0] */\n            U32 const mval = idx >= dictStartIndex ?\n                    MEM_read32(idxBase + idx) :\n                    MEM_read32(ip0) ^ 1; /* guaranteed not to match */\n\n            /* check match at ip[0] */\n            if (MEM_read32(ip0) == mval) {\n                /* found a match! */\n                goto _offset;\n        }   }\n\n        /* lookup ip[1] */\n        idx = hashTable[hash1];\n        idxBase = idx < prefixStartIndex ? dictBase : base;\n\n        /* hash ip[2] */\n        hash0 = hash1;\n        hash1 = ZSTD_hashPtr(ip2, hlog, mls);\n\n        /* advance to next positions */\n        ip0 = ip1;\n        ip1 = ip2;\n        ip2 = ip0 + step;\n        ip3 = ip1 + step;\n\n        /* calculate step */\n        if (ip2 >= nextStep) {\n            step++;\n            PREFETCH_L1(ip1 + 64);\n            PREFETCH_L1(ip1 + 128);\n            nextStep += kStepIncr;\n        }\n    } while (ip3 < ilimit);\n\n_cleanup:\n    /* Note that there are probably still a couple positions we could search.\n     * However, it seems to be a meaningful performance hit to try to search\n     * them. So let's not. */\n\n    /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0),\n     * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */\n    offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n    /* save reps for next block */\n    rep[0] = offset_1 ? offset_1 : offsetSaved1;\n    rep[1] = offset_2 ? offset_2 : offsetSaved2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n\n_offset: /* Requires: ip0, idx, idxBase */\n\n    /* Compute the offset code. */\n    {   U32 const offset = current0 - idx;\n        const BYTE* const lowMatchPtr = idx < prefixStartIndex ? dictStart : prefixStart;\n        matchEnd = idx < prefixStartIndex ? dictEnd : iend;\n        match0 = idxBase + idx;\n        offset_2 = offset_1;\n        offset_1 = offset;\n        offcode = OFFSET_TO_OFFBASE(offset);\n        mLength = 4;\n\n        /* Count the backwards match length. */\n        while (((ip0>anchor) & (match0>lowMatchPtr)) && (ip0[-1] == match0[-1])) {\n            ip0--;\n            match0--;\n            mLength++;\n    }   }\n\n_match: /* Requires: ip0, match0, offcode, matchEnd */\n\n    /* Count the forward length. */\n    assert(matchEnd != 0);\n    mLength += ZSTD_count_2segments(ip0 + mLength, match0 + mLength, iend, matchEnd, prefixStart);\n\n    ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength);\n\n    ip0 += mLength;\n    anchor = ip0;\n\n    /* write next hash table entry */\n    if (ip1 < ip0) {\n        hashTable[hash1] = (U32)(ip1 - base);\n    }\n\n    /* Fill table and check for immediate repcode. */\n    if (ip0 <= ilimit) {\n        /* Fill Table */\n        assert(base+current0+2 > istart);  /* check base overflow */\n        hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2;  /* here because current+2 could be > iend-8 */\n        hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);\n\n        while (ip0 <= ilimit) {\n            U32 const repIndex2 = (U32)(ip0-base) - offset_2;\n            const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;\n            if ( ((ZSTD_index_overlap_check(prefixStartIndex, repIndex2)) & (offset_2 > 0))\n                 && (MEM_read32(repMatch2) == MEM_read32(ip0)) ) {\n                const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;\n                size_t const repLength2 = ZSTD_count_2segments(ip0+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;\n                { U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; }  /* swap offset_2 <=> offset_1 */\n                ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, REPCODE1_TO_OFFBASE, repLength2);\n                hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);\n                ip0 += repLength2;\n                anchor = ip0;\n                continue;\n            }\n            break;\n    }   }\n\n    goto _start;\n}\n\nZSTD_GEN_FAST_FN(extDict, 4, 0)\nZSTD_GEN_FAST_FN(extDict, 5, 0)\nZSTD_GEN_FAST_FN(extDict, 6, 0)\nZSTD_GEN_FAST_FN(extDict, 7, 0)\n\nsize_t ZSTD_compressBlock_fast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    U32 const mls = ms->cParams.minMatch;\n    assert(ms->dictMatchState == NULL);\n    switch(mls)\n    {\n    default: /* includes case 3 */\n    case 4 :\n        return ZSTD_compressBlock_fast_extDict_4_0(ms, seqStore, rep, src, srcSize);\n    case 5 :\n        return ZSTD_compressBlock_fast_extDict_5_0(ms, seqStore, rep, src, srcSize);\n    case 6 :\n        return ZSTD_compressBlock_fast_extDict_6_0(ms, seqStore, rep, src, srcSize);\n    case 7 :\n        return ZSTD_compressBlock_fast_extDict_7_0(ms, seqStore, rep, src, srcSize);\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_fast.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_FAST_H\n#define ZSTD_FAST_H\n\n#include \"../common/mem.h\"      /* U32 */\n#include \"zstd_compress_internal.h\"\n\nvoid ZSTD_fillHashTable(ZSTD_MatchState_t* ms,\n                        void const* end, ZSTD_dictTableLoadMethod_e dtlm,\n                        ZSTD_tableFillPurpose_e tfp);\nsize_t ZSTD_compressBlock_fast(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_fast_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_fast_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#endif /* ZSTD_FAST_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_lazy.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"\n#include \"zstd_lazy.h\"\n#include \"../common/bits.h\" /* ZSTD_countTrailingZeros64 */\n\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)\n\n#define kLazySkippingStep 8\n\n\n/*-*************************************\n*  Binary Tree search\n***************************************/\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_updateDUBT(ZSTD_MatchState_t* ms,\n                const BYTE* ip, const BYTE* iend,\n                U32 mls)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const hashTable = ms->hashTable;\n    U32  const hashLog = cParams->hashLog;\n\n    U32* const bt = ms->chainTable;\n    U32  const btLog  = cParams->chainLog - 1;\n    U32  const btMask = (1 << btLog) - 1;\n\n    const BYTE* const base = ms->window.base;\n    U32 const target = (U32)(ip - base);\n    U32 idx = ms->nextToUpdate;\n\n    if (idx != target)\n        DEBUGLOG(7, \"ZSTD_updateDUBT, from %u to %u (dictLimit:%u)\",\n                    idx, target, ms->window.dictLimit);\n    assert(ip + 8 <= iend);   /* condition for ZSTD_hashPtr */\n    (void)iend;\n\n    assert(idx >= ms->window.dictLimit);   /* condition for valid base+idx */\n    for ( ; idx < target ; idx++) {\n        size_t const h  = ZSTD_hashPtr(base + idx, hashLog, mls);   /* assumption : ip + 8 <= iend */\n        U32    const matchIndex = hashTable[h];\n\n        U32*   const nextCandidatePtr = bt + 2*(idx&btMask);\n        U32*   const sortMarkPtr  = nextCandidatePtr + 1;\n\n        DEBUGLOG(8, \"ZSTD_updateDUBT: insert %u\", idx);\n        hashTable[h] = idx;   /* Update Hash Table */\n        *nextCandidatePtr = matchIndex;   /* update BT like a chain */\n        *sortMarkPtr = ZSTD_DUBT_UNSORTED_MARK;\n    }\n    ms->nextToUpdate = target;\n}\n\n\n/** ZSTD_insertDUBT1() :\n *  sort one already inserted but unsorted position\n *  assumption : curr >= btlow == (curr - btmask)\n *  doesn't fail */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_insertDUBT1(const ZSTD_MatchState_t* ms,\n                 U32 curr, const BYTE* inputEnd,\n                 U32 nbCompares, U32 btLow,\n                 const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const bt = ms->chainTable;\n    U32  const btLog  = cParams->chainLog - 1;\n    U32  const btMask = (1 << btLog) - 1;\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const ip = (curr>=dictLimit) ? base + curr : dictBase + curr;\n    const BYTE* const iend = (curr>=dictLimit) ? inputEnd : dictBase + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* match;\n    U32* smallerPtr = bt + 2*(curr&btMask);\n    U32* largerPtr  = smallerPtr + 1;\n    U32 matchIndex = *smallerPtr;   /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */\n    U32 dummy32;   /* to be nullified at the end */\n    U32 const windowValid = ms->window.lowLimit;\n    U32 const maxDistance = 1U << cParams->windowLog;\n    U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid;\n\n\n    DEBUGLOG(8, \"ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)\",\n                curr, dictLimit, windowLow);\n    assert(curr >= btLow);\n    assert(ip < iend);   /* condition for ZSTD_count */\n\n    for (; nbCompares && (matchIndex > windowLow); --nbCompares) {\n        U32* const nextPtr = bt + 2*(matchIndex & btMask);\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        assert(matchIndex < curr);\n        /* note : all candidates are now supposed sorted,\n         * but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK\n         * when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */\n\n        if ( (dictMode != ZSTD_extDict)\n          || (matchIndex+matchLength >= dictLimit)  /* both in current segment*/\n          || (curr < dictLimit) /* both in extDict */) {\n            const BYTE* const mBase = ( (dictMode != ZSTD_extDict)\n                                     || (matchIndex+matchLength >= dictLimit)) ?\n                                        base : dictBase;\n            assert( (matchIndex+matchLength >= dictLimit)   /* might be wrong if extDict is incorrectly set to 0 */\n                 || (curr < dictLimit) );\n            match = mBase + matchIndex;\n            matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);\n        } else {\n            match = dictBase + matchIndex;\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n            if (matchIndex+matchLength >= dictLimit)\n                match = base + matchIndex;   /* preparation for next read of match[matchLength] */\n        }\n\n        DEBUGLOG(8, \"ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes \",\n                    curr, matchIndex, (U32)matchLength);\n\n        if (ip+matchLength == iend) {   /* equal : no way to know if inf or sup */\n            break;   /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */\n        }\n\n        if (match[matchLength] < ip[matchLength]) {  /* necessarily within buffer */\n            /* match is smaller than current */\n            *smallerPtr = matchIndex;             /* update smaller idx */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            DEBUGLOG(8, \"ZSTD_insertDUBT1: %u (>btLow=%u) is smaller : next => %u\",\n                        matchIndex, btLow, nextPtr[1]);\n            smallerPtr = nextPtr+1;               /* new \"candidate\" => larger than match, which was smaller than target */\n            matchIndex = nextPtr[1];              /* new matchIndex, larger than previous and closer to current */\n        } else {\n            /* match is larger than current */\n            *largerPtr = matchIndex;\n            commonLengthLarger = matchLength;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            DEBUGLOG(8, \"ZSTD_insertDUBT1: %u (>btLow=%u) is larger => %u\",\n                        matchIndex, btLow, nextPtr[0]);\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n    }   }\n\n    *smallerPtr = *largerPtr = 0;\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_DUBT_findBetterDictMatch (\n        const ZSTD_MatchState_t* ms,\n        const BYTE* const ip, const BYTE* const iend,\n        size_t* offsetPtr,\n        size_t bestLength,\n        U32 nbCompares,\n        U32 const mls,\n        const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_MatchState_t * const dms = ms->dictMatchState;\n    const ZSTD_compressionParameters* const dmsCParams = &dms->cParams;\n    const U32 * const dictHashTable = dms->hashTable;\n    U32         const hashLog = dmsCParams->hashLog;\n    size_t      const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32               dictMatchIndex = dictHashTable[h];\n\n    const BYTE* const base = ms->window.base;\n    const BYTE* const prefixStart = base + ms->window.dictLimit;\n    U32         const curr = (U32)(ip-base);\n    const BYTE* const dictBase = dms->window.base;\n    const BYTE* const dictEnd = dms->window.nextSrc;\n    U32         const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base);\n    U32         const dictLowLimit = dms->window.lowLimit;\n    U32         const dictIndexDelta = ms->window.lowLimit - dictHighLimit;\n\n    U32*        const dictBt = dms->chainTable;\n    U32         const btLog  = dmsCParams->chainLog - 1;\n    U32         const btMask = (1 << btLog) - 1;\n    U32         const btLow = (btMask >= dictHighLimit - dictLowLimit) ? dictLowLimit : dictHighLimit - btMask;\n\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n\n    (void)dictMode;\n    assert(dictMode == ZSTD_dictMatchState);\n\n    for (; nbCompares && (dictMatchIndex > dictLowLimit); --nbCompares) {\n        U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask);\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        const BYTE* match = dictBase + dictMatchIndex;\n        matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n        if (dictMatchIndex+matchLength >= dictHighLimit)\n            match = base + dictMatchIndex + dictIndexDelta;   /* to prepare for next usage of match[matchLength] */\n\n        if (matchLength > bestLength) {\n            U32 matchIndex = dictMatchIndex + dictIndexDelta;\n            if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {\n                DEBUGLOG(9, \"ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)\",\n                    curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, OFFSET_TO_OFFBASE(curr - matchIndex), dictMatchIndex, matchIndex);\n                bestLength = matchLength, *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n            }\n            if (ip+matchLength == iend) {   /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */\n                break;   /* drop, to guarantee consistency (miss a little bit of compression) */\n            }\n        }\n\n        if (match[matchLength] < ip[matchLength]) {\n            if (dictMatchIndex <= btLow) { break; }   /* beyond tree size, stop the search */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            dictMatchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n        } else {\n            /* match is larger than current */\n            if (dictMatchIndex <= btLow) { break; }   /* beyond tree size, stop the search */\n            commonLengthLarger = matchLength;\n            dictMatchIndex = nextPtr[0];\n        }\n    }\n\n    if (bestLength >= MINMATCH) {\n        U32 const mIndex = curr - (U32)OFFBASE_TO_OFFSET(*offsetPtr); (void)mIndex;\n        DEBUGLOG(8, \"ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)\",\n                    curr, (U32)bestLength, (U32)*offsetPtr, mIndex);\n    }\n    return bestLength;\n\n}\n\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_DUBT_findBestMatch(ZSTD_MatchState_t* ms,\n                        const BYTE* const ip, const BYTE* const iend,\n                        size_t* offBasePtr,\n                        U32 const mls,\n                        const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32*   const hashTable = ms->hashTable;\n    U32    const hashLog = cParams->hashLog;\n    size_t const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32          matchIndex  = hashTable[h];\n\n    const BYTE* const base = ms->window.base;\n    U32    const curr = (U32)(ip-base);\n    U32    const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog);\n\n    U32*   const bt = ms->chainTable;\n    U32    const btLog  = cParams->chainLog - 1;\n    U32    const btMask = (1 << btLog) - 1;\n    U32    const btLow = (btMask >= curr) ? 0 : curr - btMask;\n    U32    const unsortLimit = MAX(btLow, windowLow);\n\n    U32*         nextCandidate = bt + 2*(matchIndex&btMask);\n    U32*         unsortedMark = bt + 2*(matchIndex&btMask) + 1;\n    U32          nbCompares = 1U << cParams->searchLog;\n    U32          nbCandidates = nbCompares;\n    U32          previousCandidate = 0;\n\n    DEBUGLOG(7, \"ZSTD_DUBT_findBestMatch (%u) \", curr);\n    assert(ip <= iend-8);   /* required for h calculation */\n    assert(dictMode != ZSTD_dedicatedDictSearch);\n\n    /* reach end of unsorted candidates list */\n    while ( (matchIndex > unsortLimit)\n         && (*unsortedMark == ZSTD_DUBT_UNSORTED_MARK)\n         && (nbCandidates > 1) ) {\n        DEBUGLOG(8, \"ZSTD_DUBT_findBestMatch: candidate %u is unsorted\",\n                    matchIndex);\n        *unsortedMark = previousCandidate;  /* the unsortedMark becomes a reversed chain, to move up back to original position */\n        previousCandidate = matchIndex;\n        matchIndex = *nextCandidate;\n        nextCandidate = bt + 2*(matchIndex&btMask);\n        unsortedMark = bt + 2*(matchIndex&btMask) + 1;\n        nbCandidates --;\n    }\n\n    /* nullify last candidate if it's still unsorted\n     * simplification, detrimental to compression ratio, beneficial for speed */\n    if ( (matchIndex > unsortLimit)\n      && (*unsortedMark==ZSTD_DUBT_UNSORTED_MARK) ) {\n        DEBUGLOG(7, \"ZSTD_DUBT_findBestMatch: nullify last unsorted candidate %u\",\n                    matchIndex);\n        *nextCandidate = *unsortedMark = 0;\n    }\n\n    /* batch sort stacked candidates */\n    matchIndex = previousCandidate;\n    while (matchIndex) {  /* will end on matchIndex == 0 */\n        U32* const nextCandidateIdxPtr = bt + 2*(matchIndex&btMask) + 1;\n        U32 const nextCandidateIdx = *nextCandidateIdxPtr;\n        ZSTD_insertDUBT1(ms, matchIndex, iend,\n                         nbCandidates, unsortLimit, dictMode);\n        matchIndex = nextCandidateIdx;\n        nbCandidates++;\n    }\n\n    /* find longest match */\n    {   size_t commonLengthSmaller = 0, commonLengthLarger = 0;\n        const BYTE* const dictBase = ms->window.dictBase;\n        const U32 dictLimit = ms->window.dictLimit;\n        const BYTE* const dictEnd = dictBase + dictLimit;\n        const BYTE* const prefixStart = base + dictLimit;\n        U32* smallerPtr = bt + 2*(curr&btMask);\n        U32* largerPtr  = bt + 2*(curr&btMask) + 1;\n        U32 matchEndIdx = curr + 8 + 1;\n        U32 dummy32;   /* to be nullified at the end */\n        size_t bestLength = 0;\n\n        matchIndex  = hashTable[h];\n        hashTable[h] = curr;   /* Update Hash Table */\n\n        for (; nbCompares && (matchIndex > windowLow); --nbCompares) {\n            U32* const nextPtr = bt + 2*(matchIndex & btMask);\n            size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n            const BYTE* match;\n\n            if ((dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) {\n                match = base + matchIndex;\n                matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);\n            } else {\n                match = dictBase + matchIndex;\n                matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n                if (matchIndex+matchLength >= dictLimit)\n                    match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */\n            }\n\n            if (matchLength > bestLength) {\n                if (matchLength > matchEndIdx - matchIndex)\n                    matchEndIdx = matchIndex + (U32)matchLength;\n                if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr - matchIndex + 1) - ZSTD_highbit32((U32)*offBasePtr)) )\n                    bestLength = matchLength, *offBasePtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n                if (ip+matchLength == iend) {   /* equal : no way to know if inf or sup */\n                    if (dictMode == ZSTD_dictMatchState) {\n                        nbCompares = 0; /* in addition to avoiding checking any\n                                         * further in this loop, make sure we\n                                         * skip checking in the dictionary. */\n                    }\n                    break;   /* drop, to guarantee consistency (miss a little bit of compression) */\n                }\n            }\n\n            if (match[matchLength] < ip[matchLength]) {\n                /* match is smaller than current */\n                *smallerPtr = matchIndex;             /* update smaller idx */\n                commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n                if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n                smallerPtr = nextPtr+1;               /* new \"smaller\" => larger of match */\n                matchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n            } else {\n                /* match is larger than current */\n                *largerPtr = matchIndex;\n                commonLengthLarger = matchLength;\n                if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n                largerPtr = nextPtr;\n                matchIndex = nextPtr[0];\n        }   }\n\n        *smallerPtr = *largerPtr = 0;\n\n        assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n        if (dictMode == ZSTD_dictMatchState && nbCompares) {\n            bestLength = ZSTD_DUBT_findBetterDictMatch(\n                    ms, ip, iend,\n                    offBasePtr, bestLength, nbCompares,\n                    mls, dictMode);\n        }\n\n        assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */\n        ms->nextToUpdate = matchEndIdx - 8;   /* skip repetitive patterns */\n        if (bestLength >= MINMATCH) {\n            U32 const mIndex = curr - (U32)OFFBASE_TO_OFFSET(*offBasePtr); (void)mIndex;\n            DEBUGLOG(8, \"ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)\",\n                        curr, (U32)bestLength, (U32)*offBasePtr, mIndex);\n        }\n        return bestLength;\n    }\n}\n\n\n/** ZSTD_BtFindBestMatch() : Tree updater, providing best match */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_BtFindBestMatch( ZSTD_MatchState_t* ms,\n                const BYTE* const ip, const BYTE* const iLimit,\n                      size_t* offBasePtr,\n                const U32 mls /* template */,\n                const ZSTD_dictMode_e dictMode)\n{\n    DEBUGLOG(7, \"ZSTD_BtFindBestMatch\");\n    if (ip < ms->window.base + ms->nextToUpdate) return 0;   /* skipped area */\n    ZSTD_updateDUBT(ms, ip, iLimit, mls);\n    return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offBasePtr, mls, dictMode);\n}\n\n/***********************************\n* Dedicated dict search\n***********************************/\n\nvoid ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip)\n{\n    const BYTE* const base = ms->window.base;\n    U32 const target = (U32)(ip - base);\n    U32* const hashTable = ms->hashTable;\n    U32* const chainTable = ms->chainTable;\n    U32 const chainSize = 1 << ms->cParams.chainLog;\n    U32 idx = ms->nextToUpdate;\n    U32 const minChain = chainSize < target - idx ? target - chainSize : idx;\n    U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG;\n    U32 const cacheSize = bucketSize - 1;\n    U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize;\n    U32 const chainLimit = chainAttempts > 255 ? 255 : chainAttempts;\n\n    /* We know the hashtable is oversized by a factor of `bucketSize`.\n     * We are going to temporarily pretend `bucketSize == 1`, keeping only a\n     * single entry. We will use the rest of the space to construct a temporary\n     * chaintable.\n     */\n    U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;\n    U32* const tmpHashTable = hashTable;\n    U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog);\n    U32 const tmpChainSize = (U32)((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog;\n    U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx;\n    U32 hashIdx;\n\n    assert(ms->cParams.chainLog <= 24);\n    assert(ms->cParams.hashLog > ms->cParams.chainLog);\n    assert(idx != 0);\n    assert(tmpMinChain <= minChain);\n\n    /* fill conventional hash table and conventional chain table */\n    for ( ; idx < target; idx++) {\n        U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch);\n        if (idx >= tmpMinChain) {\n            tmpChainTable[idx - tmpMinChain] = hashTable[h];\n        }\n        tmpHashTable[h] = idx;\n    }\n\n    /* sort chains into ddss chain table */\n    {\n        U32 chainPos = 0;\n        for (hashIdx = 0; hashIdx < (1U << hashLog); hashIdx++) {\n            U32 count;\n            U32 countBeyondMinChain = 0;\n            U32 i = tmpHashTable[hashIdx];\n            for (count = 0; i >= tmpMinChain && count < cacheSize; count++) {\n                /* skip through the chain to the first position that won't be\n                 * in the hash cache bucket */\n                if (i < minChain) {\n                    countBeyondMinChain++;\n                }\n                i = tmpChainTable[i - tmpMinChain];\n            }\n            if (count == cacheSize) {\n                for (count = 0; count < chainLimit;) {\n                    if (i < minChain) {\n                        if (!i || ++countBeyondMinChain > cacheSize) {\n                            /* only allow pulling `cacheSize` number of entries\n                             * into the cache or chainTable beyond `minChain`,\n                             * to replace the entries pulled out of the\n                             * chainTable into the cache. This lets us reach\n                             * back further without increasing the total number\n                             * of entries in the chainTable, guaranteeing the\n                             * DDSS chain table will fit into the space\n                             * allocated for the regular one. */\n                            break;\n                        }\n                    }\n                    chainTable[chainPos++] = i;\n                    count++;\n                    if (i < tmpMinChain) {\n                        break;\n                    }\n                    i = tmpChainTable[i - tmpMinChain];\n                }\n            } else {\n                count = 0;\n            }\n            if (count) {\n                tmpHashTable[hashIdx] = ((chainPos - count) << 8) + count;\n            } else {\n                tmpHashTable[hashIdx] = 0;\n            }\n        }\n        assert(chainPos <= chainSize); /* I believe this is guaranteed... */\n    }\n\n    /* move chain pointers into the last entry of each hash bucket */\n    for (hashIdx = (1 << hashLog); hashIdx; ) {\n        U32 const bucketIdx = --hashIdx << ZSTD_LAZY_DDSS_BUCKET_LOG;\n        U32 const chainPackedPointer = tmpHashTable[hashIdx];\n        U32 i;\n        for (i = 0; i < cacheSize; i++) {\n            hashTable[bucketIdx + i] = 0;\n        }\n        hashTable[bucketIdx + bucketSize - 1] = chainPackedPointer;\n    }\n\n    /* fill the buckets of the hash table */\n    for (idx = ms->nextToUpdate; idx < target; idx++) {\n        U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch)\n                   << ZSTD_LAZY_DDSS_BUCKET_LOG;\n        U32 i;\n        /* Shift hash cache down 1. */\n        for (i = cacheSize - 1; i; i--)\n            hashTable[h + i] = hashTable[h + i - 1];\n        hashTable[h] = idx;\n    }\n\n    ms->nextToUpdate = target;\n}\n\n/* Returns the longest match length found in the dedicated dict search structure.\n * If none are longer than the argument ml, then ml will be returned.\n */\nFORCE_INLINE_TEMPLATE\nsize_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nbAttempts,\n                                            const ZSTD_MatchState_t* const dms,\n                                            const BYTE* const ip, const BYTE* const iLimit,\n                                            const BYTE* const prefixStart, const U32 curr,\n                                            const U32 dictLimit, const size_t ddsIdx) {\n    const U32 ddsLowestIndex  = dms->window.dictLimit;\n    const BYTE* const ddsBase = dms->window.base;\n    const BYTE* const ddsEnd  = dms->window.nextSrc;\n    const U32 ddsSize         = (U32)(ddsEnd - ddsBase);\n    const U32 ddsIndexDelta   = dictLimit - ddsSize;\n    const U32 bucketSize      = (1 << ZSTD_LAZY_DDSS_BUCKET_LOG);\n    const U32 bucketLimit     = nbAttempts < bucketSize - 1 ? nbAttempts : bucketSize - 1;\n    U32 ddsAttempt;\n    U32 matchIndex;\n\n    for (ddsAttempt = 0; ddsAttempt < bucketSize - 1; ddsAttempt++) {\n        PREFETCH_L1(ddsBase + dms->hashTable[ddsIdx + ddsAttempt]);\n    }\n\n    {\n        U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1];\n        U32 const chainIndex = chainPackedPointer >> 8;\n\n        PREFETCH_L1(&dms->chainTable[chainIndex]);\n    }\n\n    for (ddsAttempt = 0; ddsAttempt < bucketLimit; ddsAttempt++) {\n        size_t currentMl=0;\n        const BYTE* match;\n        matchIndex = dms->hashTable[ddsIdx + ddsAttempt];\n        match = ddsBase + matchIndex;\n\n        if (!matchIndex) {\n            return ml;\n        }\n\n        /* guaranteed by table construction */\n        (void)ddsLowestIndex;\n        assert(matchIndex >= ddsLowestIndex);\n        assert(match+4 <= ddsEnd);\n        if (MEM_read32(match) == MEM_read32(ip)) {\n            /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n            currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4;\n        }\n\n        /* save best solution */\n        if (currentMl > ml) {\n            ml = currentMl;\n            *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + ddsIndexDelta));\n            if (ip+currentMl == iLimit) {\n                /* best possible, avoids read overflow on next attempt */\n                return ml;\n            }\n        }\n    }\n\n    {\n        U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1];\n        U32 chainIndex = chainPackedPointer >> 8;\n        U32 const chainLength = chainPackedPointer & 0xFF;\n        U32 const chainAttempts = nbAttempts - ddsAttempt;\n        U32 const chainLimit = chainAttempts > chainLength ? chainLength : chainAttempts;\n        U32 chainAttempt;\n\n        for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++) {\n            PREFETCH_L1(ddsBase + dms->chainTable[chainIndex + chainAttempt]);\n        }\n\n        for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++, chainIndex++) {\n            size_t currentMl=0;\n            const BYTE* match;\n            matchIndex = dms->chainTable[chainIndex];\n            match = ddsBase + matchIndex;\n\n            /* guaranteed by table construction */\n            assert(matchIndex >= ddsLowestIndex);\n            assert(match+4 <= ddsEnd);\n            if (MEM_read32(match) == MEM_read32(ip)) {\n                /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4;\n            }\n\n            /* save best solution */\n            if (currentMl > ml) {\n                ml = currentMl;\n                *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + ddsIndexDelta));\n                if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n            }\n        }\n    }\n    return ml;\n}\n\n\n/* *********************************\n*  Hash Chain\n***********************************/\n#define NEXT_IN_CHAIN(d, mask)   chainTable[(d) & (mask)]\n\n/* Update chains up to ip (excluded)\n   Assumption : always within prefix (i.e. not within extDict) */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_insertAndFindFirstIndex_internal(\n                        ZSTD_MatchState_t* ms,\n                        const ZSTD_compressionParameters* const cParams,\n                        const BYTE* ip, U32 const mls, U32 const lazySkipping)\n{\n    U32* const hashTable  = ms->hashTable;\n    const U32 hashLog = cParams->hashLog;\n    U32* const chainTable = ms->chainTable;\n    const U32 chainMask = (1 << cParams->chainLog) - 1;\n    const BYTE* const base = ms->window.base;\n    const U32 target = (U32)(ip - base);\n    U32 idx = ms->nextToUpdate;\n\n    while(idx < target) { /* catch up */\n        size_t const h = ZSTD_hashPtr(base+idx, hashLog, mls);\n        NEXT_IN_CHAIN(idx, chainMask) = hashTable[h];\n        hashTable[h] = idx;\n        idx++;\n        /* Stop inserting every position when in the lazy skipping mode. */\n        if (lazySkipping)\n            break;\n    }\n\n    ms->nextToUpdate = target;\n    return hashTable[ZSTD_hashPtr(ip, hashLog, mls)];\n}\n\nU32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip) {\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch, /* lazySkipping*/ 0);\n}\n\n/* inlining is important to hardwire a hot branch (template emulation) */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_HcFindBestMatch(\n                        ZSTD_MatchState_t* ms,\n                        const BYTE* const ip, const BYTE* const iLimit,\n                        size_t* offsetPtr,\n                        const U32 mls, const ZSTD_dictMode_e dictMode)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32* const chainTable = ms->chainTable;\n    const U32 chainSize = (1 << cParams->chainLog);\n    const U32 chainMask = chainSize-1;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const U32 curr = (U32)(ip-base);\n    const U32 maxDistance = 1U << cParams->windowLog;\n    const U32 lowestValid = ms->window.lowLimit;\n    const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    const U32 isDictionary = (ms->loadedDictEnd != 0);\n    const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance;\n    const U32 minChain = curr > chainSize ? curr - chainSize : 0;\n    U32 nbAttempts = 1U << cParams->searchLog;\n    size_t ml=4-1;\n\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch\n                         ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0;\n    const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch\n                        ? ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG : 0;\n\n    U32 matchIndex;\n\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        const U32* entry = &dms->hashTable[ddsIdx];\n        PREFETCH_L1(entry);\n    }\n\n    /* HC4 match finder */\n    matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls, ms->lazySkipping);\n\n    for ( ; (matchIndex>=lowLimit) & (nbAttempts>0) ; nbAttempts--) {\n        size_t currentMl=0;\n        if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {\n            const BYTE* const match = base + matchIndex;\n            assert(matchIndex >= dictLimit);   /* ensures this is true if dictMode != ZSTD_extDict */\n            /* read 4B starting from (match + ml + 1 - sizeof(U32)) */\n            if (MEM_read32(match + ml - 3) == MEM_read32(ip + ml - 3))   /* potentially better */\n                currentMl = ZSTD_count(ip, match, iLimit);\n        } else {\n            const BYTE* const match = dictBase + matchIndex;\n            assert(match+4 <= dictEnd);\n            if (MEM_read32(match) == MEM_read32(ip))   /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;\n        }\n\n        /* save best solution */\n        if (currentMl > ml) {\n            ml = currentMl;\n            *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n            if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n        }\n\n        if (matchIndex <= minChain) break;\n        matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);\n    }\n\n    assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts, dms,\n                                                  ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);\n    } else if (dictMode == ZSTD_dictMatchState) {\n        const U32* const dmsChainTable = dms->chainTable;\n        const U32 dmsChainSize         = (1 << dms->cParams.chainLog);\n        const U32 dmsChainMask         = dmsChainSize - 1;\n        const U32 dmsLowestIndex       = dms->window.dictLimit;\n        const BYTE* const dmsBase      = dms->window.base;\n        const BYTE* const dmsEnd       = dms->window.nextSrc;\n        const U32 dmsSize              = (U32)(dmsEnd - dmsBase);\n        const U32 dmsIndexDelta        = dictLimit - dmsSize;\n        const U32 dmsMinChain = dmsSize > dmsChainSize ? dmsSize - dmsChainSize : 0;\n\n        matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)];\n\n        for ( ; (matchIndex>=dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) {\n            size_t currentMl=0;\n            const BYTE* const match = dmsBase + matchIndex;\n            assert(match+4 <= dmsEnd);\n            if (MEM_read32(match) == MEM_read32(ip))   /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4;\n\n            /* save best solution */\n            if (currentMl > ml) {\n                ml = currentMl;\n                assert(curr > matchIndex + dmsIndexDelta);\n                *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + dmsIndexDelta));\n                if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n            }\n\n            if (matchIndex <= dmsMinChain) break;\n\n            matchIndex = dmsChainTable[matchIndex & dmsChainMask];\n        }\n    }\n\n    return ml;\n}\n\n/* *********************************\n* (SIMD) Row-based matchfinder\n***********************************/\n/* Constants for row-based hash */\n#define ZSTD_ROW_HASH_TAG_MASK ((1u << ZSTD_ROW_HASH_TAG_BITS) - 1)\n#define ZSTD_ROW_HASH_MAX_ENTRIES 64    /* absolute maximum number of entries per row, for all configurations */\n\n#define ZSTD_ROW_HASH_CACHE_MASK (ZSTD_ROW_HASH_CACHE_SIZE - 1)\n\ntypedef U64 ZSTD_VecMask;   /* Clarifies when we are interacting with a U64 representing a mask of matches */\n\n/* ZSTD_VecMask_next():\n * Starting from the LSB, returns the idx of the next non-zero bit.\n * Basically counting the nb of trailing zeroes.\n */\nMEM_STATIC U32 ZSTD_VecMask_next(ZSTD_VecMask val) {\n    return ZSTD_countTrailingZeros64(val);\n}\n\n/* ZSTD_row_nextIndex():\n * Returns the next index to insert at within a tagTable row, and updates the \"head\"\n * value to reflect the update. Essentially cycles backwards from [1, {entries per row})\n */\nFORCE_INLINE_TEMPLATE U32 ZSTD_row_nextIndex(BYTE* const tagRow, U32 const rowMask) {\n    U32 next = (*tagRow-1) & rowMask;\n    next += (next == 0) ? rowMask : 0; /* skip first position */\n    *tagRow = (BYTE)next;\n    return next;\n}\n\n/* ZSTD_isAligned():\n * Checks that a pointer is aligned to \"align\" bytes which must be a power of 2.\n */\nMEM_STATIC int ZSTD_isAligned(void const* ptr, size_t align) {\n    assert((align & (align - 1)) == 0);\n    return (((size_t)ptr) & (align - 1)) == 0;\n}\n\n/* ZSTD_row_prefetch():\n * Performs prefetching for the hashTable and tagTable at a given row.\n */\nFORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, BYTE const* tagTable, U32 const relRow, U32 const rowLog) {\n    PREFETCH_L1(hashTable + relRow);\n    if (rowLog >= 5) {\n        PREFETCH_L1(hashTable + relRow + 16);\n        /* Note: prefetching more of the hash table does not appear to be beneficial for 128-entry rows */\n    }\n    PREFETCH_L1(tagTable + relRow);\n    if (rowLog == 6) {\n        PREFETCH_L1(tagTable + relRow + 32);\n    }\n    assert(rowLog == 4 || rowLog == 5 || rowLog == 6);\n    assert(ZSTD_isAligned(hashTable + relRow, 64));                 /* prefetched hash row always 64-byte aligned */\n    assert(ZSTD_isAligned(tagTable + relRow, (size_t)1 << rowLog)); /* prefetched tagRow sits on correct multiple of bytes (32,64,128) */\n}\n\n/* ZSTD_row_fillHashCache():\n * Fill up the hash cache starting at idx, prefetching up to ZSTD_ROW_HASH_CACHE_SIZE entries,\n * but not beyond iLimit.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_row_fillHashCache(ZSTD_MatchState_t* ms, const BYTE* base,\n                                   U32 const rowLog, U32 const mls,\n                                   U32 idx, const BYTE* const iLimit)\n{\n    U32 const* const hashTable = ms->hashTable;\n    BYTE const* const tagTable = ms->tagTable;\n    U32 const hashLog = ms->rowHashLog;\n    U32 const maxElemsToPrefetch = (base + idx) > iLimit ? 0 : (U32)(iLimit - (base + idx) + 1);\n    U32 const lim = idx + MIN(ZSTD_ROW_HASH_CACHE_SIZE, maxElemsToPrefetch);\n\n    for (; idx < lim; ++idx) {\n        U32 const hash = (U32)ZSTD_hashPtrSalted(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt);\n        U32 const row = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        ZSTD_row_prefetch(hashTable, tagTable, row, rowLog);\n        ms->hashCache[idx & ZSTD_ROW_HASH_CACHE_MASK] = hash;\n    }\n\n    DEBUGLOG(6, \"ZSTD_row_fillHashCache(): [%u %u %u %u %u %u %u %u]\", ms->hashCache[0], ms->hashCache[1],\n                                                     ms->hashCache[2], ms->hashCache[3], ms->hashCache[4],\n                                                     ms->hashCache[5], ms->hashCache[6], ms->hashCache[7]);\n}\n\n/* ZSTD_row_nextCachedHash():\n * Returns the hash of base + idx, and replaces the hash in the hash cache with the byte at\n * base + idx + ZSTD_ROW_HASH_CACHE_SIZE. Also prefetches the appropriate rows from hashTable and tagTable.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTable,\n                                                  BYTE const* tagTable, BYTE const* base,\n                                                  U32 idx, U32 const hashLog,\n                                                  U32 const rowLog, U32 const mls,\n                                                  U64 const hashSalt)\n{\n    U32 const newHash = (U32)ZSTD_hashPtrSalted(base+idx+ZSTD_ROW_HASH_CACHE_SIZE, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, hashSalt);\n    U32 const row = (newHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n    ZSTD_row_prefetch(hashTable, tagTable, row, rowLog);\n    {   U32 const hash = cache[idx & ZSTD_ROW_HASH_CACHE_MASK];\n        cache[idx & ZSTD_ROW_HASH_CACHE_MASK] = newHash;\n        return hash;\n    }\n}\n\n/* ZSTD_row_update_internalImpl():\n * Updates the hash table with positions starting from updateStartIdx until updateEndIdx.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_row_update_internalImpl(ZSTD_MatchState_t* ms,\n                                  U32 updateStartIdx, U32 const updateEndIdx,\n                                  U32 const mls, U32 const rowLog,\n                                  U32 const rowMask, U32 const useCache)\n{\n    U32* const hashTable = ms->hashTable;\n    BYTE* const tagTable = ms->tagTable;\n    U32 const hashLog = ms->rowHashLog;\n    const BYTE* const base = ms->window.base;\n\n    DEBUGLOG(6, \"ZSTD_row_update_internalImpl(): updateStartIdx=%u, updateEndIdx=%u\", updateStartIdx, updateEndIdx);\n    for (; updateStartIdx < updateEndIdx; ++updateStartIdx) {\n        U32 const hash = useCache ? ZSTD_row_nextCachedHash(ms->hashCache, hashTable, tagTable, base, updateStartIdx, hashLog, rowLog, mls, ms->hashSalt)\n                                  : (U32)ZSTD_hashPtrSalted(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt);\n        U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        U32* const row = hashTable + relRow;\n        BYTE* tagRow = tagTable + relRow;\n        U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask);\n\n        assert(hash == ZSTD_hashPtrSalted(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, ms->hashSalt));\n        tagRow[pos] = hash & ZSTD_ROW_HASH_TAG_MASK;\n        row[pos] = updateStartIdx;\n    }\n}\n\n/* ZSTD_row_update_internal():\n * Inserts the byte at ip into the appropriate position in the hash table, and updates ms->nextToUpdate.\n * Skips sections of long matches as is necessary.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_row_update_internal(ZSTD_MatchState_t* ms, const BYTE* ip,\n                              U32 const mls, U32 const rowLog,\n                              U32 const rowMask, U32 const useCache)\n{\n    U32 idx = ms->nextToUpdate;\n    const BYTE* const base = ms->window.base;\n    const U32 target = (U32)(ip - base);\n    const U32 kSkipThreshold = 384;\n    const U32 kMaxMatchStartPositionsToUpdate = 96;\n    const U32 kMaxMatchEndPositionsToUpdate = 32;\n\n    if (useCache) {\n        /* Only skip positions when using hash cache, i.e.\n         * if we are loading a dict, don't skip anything.\n         * If we decide to skip, then we only update a set number\n         * of positions at the beginning and end of the match.\n         */\n        if (UNLIKELY(target - idx > kSkipThreshold)) {\n            U32 const bound = idx + kMaxMatchStartPositionsToUpdate;\n            ZSTD_row_update_internalImpl(ms, idx, bound, mls, rowLog, rowMask, useCache);\n            idx = target - kMaxMatchEndPositionsToUpdate;\n            ZSTD_row_fillHashCache(ms, base, rowLog, mls, idx, ip+1);\n        }\n    }\n    assert(target >= idx);\n    ZSTD_row_update_internalImpl(ms, idx, target, mls, rowLog, rowMask, useCache);\n    ms->nextToUpdate = target;\n}\n\n/* ZSTD_row_update():\n * External wrapper for ZSTD_row_update_internal(). Used for filling the hashtable during dictionary\n * processing.\n */\nvoid ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* ip) {\n    const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);\n    const U32 rowMask = (1u << rowLog) - 1;\n    const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */);\n\n    DEBUGLOG(5, \"ZSTD_row_update(), rowLog=%u\", rowLog);\n    ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* don't use cache */);\n}\n\n/* Returns the mask width of bits group of which will be set to 1. Given not all\n * architectures have easy movemask instruction, this helps to iterate over\n * groups of bits easier and faster.\n */\nFORCE_INLINE_TEMPLATE U32\nZSTD_row_matchMaskGroupWidth(const U32 rowEntries)\n{\n    assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);\n    assert(rowEntries <= ZSTD_ROW_HASH_MAX_ENTRIES);\n    (void)rowEntries;\n#if defined(ZSTD_ARCH_ARM_NEON)\n    /* NEON path only works for little endian */\n    if (!MEM_isLittleEndian()) {\n        return 1;\n    }\n    if (rowEntries == 16) {\n        return 4;\n    }\n    if (rowEntries == 32) {\n        return 2;\n    }\n    if (rowEntries == 64) {\n        return 1;\n    }\n#endif\n    return 1;\n}\n\n#if defined(ZSTD_ARCH_X86_SSE2)\nFORCE_INLINE_TEMPLATE ZSTD_VecMask\nZSTD_row_getSSEMask(int nbChunks, const BYTE* const src, const BYTE tag, const U32 head)\n{\n    const __m128i comparisonMask = _mm_set1_epi8((char)tag);\n    int matches[4] = {0};\n    int i;\n    assert(nbChunks == 1 || nbChunks == 2 || nbChunks == 4);\n    for (i=0; i<nbChunks; i++) {\n        const __m128i chunk = _mm_loadu_si128((const __m128i*)(const void*)(src + 16*i));\n        const __m128i equalMask = _mm_cmpeq_epi8(chunk, comparisonMask);\n        matches[i] = _mm_movemask_epi8(equalMask);\n    }\n    if (nbChunks == 1) return ZSTD_rotateRight_U16((U16)matches[0], head);\n    if (nbChunks == 2) return ZSTD_rotateRight_U32((U32)matches[1] << 16 | (U32)matches[0], head);\n    assert(nbChunks == 4);\n    return ZSTD_rotateRight_U64((U64)matches[3] << 48 | (U64)matches[2] << 32 | (U64)matches[1] << 16 | (U64)matches[0], head);\n}\n#endif\n\n#if defined(ZSTD_ARCH_ARM_NEON)\nFORCE_INLINE_TEMPLATE ZSTD_VecMask\nZSTD_row_getNEONMask(const U32 rowEntries, const BYTE* const src, const BYTE tag, const U32 headGrouped)\n{\n    assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);\n    if (rowEntries == 16) {\n        /* vshrn_n_u16 shifts by 4 every u16 and narrows to 8 lower bits.\n         * After that groups of 4 bits represent the equalMask. We lower\n         * all bits except the highest in these groups by doing AND with\n         * 0x88 = 0b10001000.\n         */\n        const uint8x16_t chunk = vld1q_u8(src);\n        const uint16x8_t equalMask = vreinterpretq_u16_u8(vceqq_u8(chunk, vdupq_n_u8(tag)));\n        const uint8x8_t res = vshrn_n_u16(equalMask, 4);\n        const U64 matches = vget_lane_u64(vreinterpret_u64_u8(res), 0);\n        return ZSTD_rotateRight_U64(matches, headGrouped) & 0x8888888888888888ull;\n    } else if (rowEntries == 32) {\n        /* Same idea as with rowEntries == 16 but doing AND with\n         * 0x55 = 0b01010101.\n         */\n        const uint16x8x2_t chunk = vld2q_u16((const uint16_t*)(const void*)src);\n        const uint8x16_t chunk0 = vreinterpretq_u8_u16(chunk.val[0]);\n        const uint8x16_t chunk1 = vreinterpretq_u8_u16(chunk.val[1]);\n        const uint8x16_t dup = vdupq_n_u8(tag);\n        const uint8x8_t t0 = vshrn_n_u16(vreinterpretq_u16_u8(vceqq_u8(chunk0, dup)), 6);\n        const uint8x8_t t1 = vshrn_n_u16(vreinterpretq_u16_u8(vceqq_u8(chunk1, dup)), 6);\n        const uint8x8_t res = vsli_n_u8(t0, t1, 4);\n        const U64 matches = vget_lane_u64(vreinterpret_u64_u8(res), 0) ;\n        return ZSTD_rotateRight_U64(matches, headGrouped) & 0x5555555555555555ull;\n    } else { /* rowEntries == 64 */\n        const uint8x16x4_t chunk = vld4q_u8(src);\n        const uint8x16_t dup = vdupq_n_u8(tag);\n        const uint8x16_t cmp0 = vceqq_u8(chunk.val[0], dup);\n        const uint8x16_t cmp1 = vceqq_u8(chunk.val[1], dup);\n        const uint8x16_t cmp2 = vceqq_u8(chunk.val[2], dup);\n        const uint8x16_t cmp3 = vceqq_u8(chunk.val[3], dup);\n\n        const uint8x16_t t0 = vsriq_n_u8(cmp1, cmp0, 1);\n        const uint8x16_t t1 = vsriq_n_u8(cmp3, cmp2, 1);\n        const uint8x16_t t2 = vsriq_n_u8(t1, t0, 2);\n        const uint8x16_t t3 = vsriq_n_u8(t2, t2, 4);\n        const uint8x8_t t4 = vshrn_n_u16(vreinterpretq_u16_u8(t3), 4);\n        const U64 matches = vget_lane_u64(vreinterpret_u64_u8(t4), 0);\n        return ZSTD_rotateRight_U64(matches, headGrouped);\n    }\n}\n#endif\n\n/* Returns a ZSTD_VecMask (U64) that has the nth group (determined by\n * ZSTD_row_matchMaskGroupWidth) of bits set to 1 if the newly-computed \"tag\"\n * matches the hash at the nth position in a row of the tagTable.\n * Each row is a circular buffer beginning at the value of \"headGrouped\". So we\n * must rotate the \"matches\" bitfield to match up with the actual layout of the\n * entries within the hashTable */\nFORCE_INLINE_TEMPLATE ZSTD_VecMask\nZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 headGrouped, const U32 rowEntries)\n{\n    const BYTE* const src = tagRow;\n    assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);\n    assert(rowEntries <= ZSTD_ROW_HASH_MAX_ENTRIES);\n    assert(ZSTD_row_matchMaskGroupWidth(rowEntries) * rowEntries <= sizeof(ZSTD_VecMask) * 8);\n\n#if defined(ZSTD_ARCH_X86_SSE2)\n\n    return ZSTD_row_getSSEMask(rowEntries / 16, src, tag, headGrouped);\n\n#else /* SW or NEON-LE */\n\n# if defined(ZSTD_ARCH_ARM_NEON)\n  /* This NEON path only works for little endian - otherwise use SWAR below */\n    if (MEM_isLittleEndian()) {\n        return ZSTD_row_getNEONMask(rowEntries, src, tag, headGrouped);\n    }\n# endif /* ZSTD_ARCH_ARM_NEON */\n    /* SWAR */\n    {   const int chunkSize = sizeof(size_t);\n        const size_t shiftAmount = ((chunkSize * 8) - chunkSize);\n        const size_t xFF = ~((size_t)0);\n        const size_t x01 = xFF / 0xFF;\n        const size_t x80 = x01 << 7;\n        const size_t splatChar = tag * x01;\n        ZSTD_VecMask matches = 0;\n        int i = rowEntries - chunkSize;\n        assert((sizeof(size_t) == 4) || (sizeof(size_t) == 8));\n        if (MEM_isLittleEndian()) { /* runtime check so have two loops */\n            const size_t extractMagic = (xFF / 0x7F) >> chunkSize;\n            do {\n                size_t chunk = MEM_readST(&src[i]);\n                chunk ^= splatChar;\n                chunk = (((chunk | x80) - x01) | chunk) & x80;\n                matches <<= chunkSize;\n                matches |= (chunk * extractMagic) >> shiftAmount;\n                i -= chunkSize;\n            } while (i >= 0);\n        } else { /* big endian: reverse bits during extraction */\n            const size_t msb = xFF ^ (xFF >> 1);\n            const size_t extractMagic = (msb / 0x1FF) | msb;\n            do {\n                size_t chunk = MEM_readST(&src[i]);\n                chunk ^= splatChar;\n                chunk = (((chunk | x80) - x01) | chunk) & x80;\n                matches <<= chunkSize;\n                matches |= ((chunk >> 7) * extractMagic) >> shiftAmount;\n                i -= chunkSize;\n            } while (i >= 0);\n        }\n        matches = ~matches;\n        if (rowEntries == 16) {\n            return ZSTD_rotateRight_U16((U16)matches, headGrouped);\n        } else if (rowEntries == 32) {\n            return ZSTD_rotateRight_U32((U32)matches, headGrouped);\n        } else {\n            return ZSTD_rotateRight_U64((U64)matches, headGrouped);\n        }\n    }\n#endif\n}\n\n/* The high-level approach of the SIMD row based match finder is as follows:\n * - Figure out where to insert the new entry:\n *      - Generate a hash for current input position and split it into a one byte of tag and `rowHashLog` bits of index.\n *           - The hash is salted by a value that changes on every context reset, so when the same table is used\n *             we will avoid collisions that would otherwise slow us down by introducing phantom matches.\n *      - The hashTable is effectively split into groups or \"rows\" of 15 or 31 entries of U32, and the index determines\n *        which row to insert into.\n *      - Determine the correct position within the row to insert the entry into. Each row of 15 or 31 can\n *        be considered as a circular buffer with a \"head\" index that resides in the tagTable (overall 16 or 32 bytes\n *        per row).\n * - Use SIMD to efficiently compare the tags in the tagTable to the 1-byte tag calculated for the position and\n *   generate a bitfield that we can cycle through to check the collisions in the hash table.\n * - Pick the longest match.\n * - Insert the tag into the equivalent row and position in the tagTable.\n */\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_RowFindBestMatch(\n                        ZSTD_MatchState_t* ms,\n                        const BYTE* const ip, const BYTE* const iLimit,\n                        size_t* offsetPtr,\n                        const U32 mls, const ZSTD_dictMode_e dictMode,\n                        const U32 rowLog)\n{\n    U32* const hashTable = ms->hashTable;\n    BYTE* const tagTable = ms->tagTable;\n    U32* const hashCache = ms->hashCache;\n    const U32 hashLog = ms->rowHashLog;\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const U32 curr = (U32)(ip-base);\n    const U32 maxDistance = 1U << cParams->windowLog;\n    const U32 lowestValid = ms->window.lowLimit;\n    const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;\n    const U32 isDictionary = (ms->loadedDictEnd != 0);\n    const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance;\n    const U32 rowEntries = (1U << rowLog);\n    const U32 rowMask = rowEntries - 1;\n    const U32 cappedSearchLog = MIN(cParams->searchLog, rowLog); /* nb of searches is capped at nb entries per row */\n    const U32 groupWidth = ZSTD_row_matchMaskGroupWidth(rowEntries);\n    const U64 hashSalt = ms->hashSalt;\n    U32 nbAttempts = 1U << cappedSearchLog;\n    size_t ml=4-1;\n    U32 hash;\n\n    /* DMS/DDS variables that may be referenced laster */\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n\n    /* Initialize the following variables to satisfy static analyzer */\n    size_t ddsIdx = 0;\n    U32 ddsExtraAttempts = 0; /* cctx hash tables are limited in searches, but allow extra searches into DDS */\n    U32 dmsTag = 0;\n    U32* dmsRow = NULL;\n    BYTE* dmsTagRow = NULL;\n\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        const U32 ddsHashLog = dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;\n        {   /* Prefetch DDS hashtable entry */\n            ddsIdx = ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG;\n            PREFETCH_L1(&dms->hashTable[ddsIdx]);\n        }\n        ddsExtraAttempts = cParams->searchLog > rowLog ? 1U << (cParams->searchLog - rowLog) : 0;\n    }\n\n    if (dictMode == ZSTD_dictMatchState) {\n        /* Prefetch DMS rows */\n        U32* const dmsHashTable = dms->hashTable;\n        BYTE* const dmsTagTable = dms->tagTable;\n        U32 const dmsHash = (U32)ZSTD_hashPtr(ip, dms->rowHashLog + ZSTD_ROW_HASH_TAG_BITS, mls);\n        U32 const dmsRelRow = (dmsHash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        dmsTag = dmsHash & ZSTD_ROW_HASH_TAG_MASK;\n        dmsTagRow = (BYTE*)(dmsTagTable + dmsRelRow);\n        dmsRow = dmsHashTable + dmsRelRow;\n        ZSTD_row_prefetch(dmsHashTable, dmsTagTable, dmsRelRow, rowLog);\n    }\n\n    /* Update the hashTable and tagTable up to (but not including) ip */\n    if (!ms->lazySkipping) {\n        ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 1 /* useCache */);\n        hash = ZSTD_row_nextCachedHash(hashCache, hashTable, tagTable, base, curr, hashLog, rowLog, mls, hashSalt);\n    } else {\n        /* Stop inserting every position when in the lazy skipping mode.\n         * The hash cache is also not kept up to date in this mode.\n         */\n        hash = (U32)ZSTD_hashPtrSalted(ip, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls, hashSalt);\n        ms->nextToUpdate = curr;\n    }\n    ms->hashSaltEntropy += hash; /* collect salt entropy */\n\n    {   /* Get the hash for ip, compute the appropriate row */\n        U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;\n        U32 const tag = hash & ZSTD_ROW_HASH_TAG_MASK;\n        U32* const row = hashTable + relRow;\n        BYTE* tagRow = (BYTE*)(tagTable + relRow);\n        U32 const headGrouped = (*tagRow & rowMask) * groupWidth;\n        U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES];\n        size_t numMatches = 0;\n        size_t currMatch = 0;\n        ZSTD_VecMask matches = ZSTD_row_getMatchMask(tagRow, (BYTE)tag, headGrouped, rowEntries);\n\n        /* Cycle through the matches and prefetch */\n        for (; (matches > 0) && (nbAttempts > 0); matches &= (matches - 1)) {\n            U32 const matchPos = ((headGrouped + ZSTD_VecMask_next(matches)) / groupWidth) & rowMask;\n            U32 const matchIndex = row[matchPos];\n            if(matchPos == 0) continue;\n            assert(numMatches < rowEntries);\n            if (matchIndex < lowLimit)\n                break;\n            if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {\n                PREFETCH_L1(base + matchIndex);\n            } else {\n                PREFETCH_L1(dictBase + matchIndex);\n            }\n            matchBuffer[numMatches++] = matchIndex;\n            --nbAttempts;\n        }\n\n        /* Speed opt: insert current byte into hashtable too. This allows us to avoid one iteration of the loop\n           in ZSTD_row_update_internal() at the next search. */\n        {\n            U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask);\n            tagRow[pos] = (BYTE)tag;\n            row[pos] = ms->nextToUpdate++;\n        }\n\n        /* Return the longest match */\n        for (; currMatch < numMatches; ++currMatch) {\n            U32 const matchIndex = matchBuffer[currMatch];\n            size_t currentMl=0;\n            assert(matchIndex < curr);\n            assert(matchIndex >= lowLimit);\n\n            if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) {\n                const BYTE* const match = base + matchIndex;\n                assert(matchIndex >= dictLimit);   /* ensures this is true if dictMode != ZSTD_extDict */\n                /* read 4B starting from (match + ml + 1 - sizeof(U32)) */\n                if (MEM_read32(match + ml - 3) == MEM_read32(ip + ml - 3))   /* potentially better */\n                    currentMl = ZSTD_count(ip, match, iLimit);\n            } else {\n                const BYTE* const match = dictBase + matchIndex;\n                assert(match+4 <= dictEnd);\n                if (MEM_read32(match) == MEM_read32(ip))   /* assumption : matchIndex <= dictLimit-4 (by table construction) */\n                    currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dictEnd, prefixStart) + 4;\n            }\n\n            /* Save best solution */\n            if (currentMl > ml) {\n                ml = currentMl;\n                *offsetPtr = OFFSET_TO_OFFBASE(curr - matchIndex);\n                if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */\n            }\n        }\n    }\n\n    assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n    if (dictMode == ZSTD_dedicatedDictSearch) {\n        ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts + ddsExtraAttempts, dms,\n                                                  ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);\n    } else if (dictMode == ZSTD_dictMatchState) {\n        /* TODO: Measure and potentially add prefetching to DMS */\n        const U32 dmsLowestIndex       = dms->window.dictLimit;\n        const BYTE* const dmsBase      = dms->window.base;\n        const BYTE* const dmsEnd       = dms->window.nextSrc;\n        const U32 dmsSize              = (U32)(dmsEnd - dmsBase);\n        const U32 dmsIndexDelta        = dictLimit - dmsSize;\n\n        {   U32 const headGrouped = (*dmsTagRow & rowMask) * groupWidth;\n            U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES];\n            size_t numMatches = 0;\n            size_t currMatch = 0;\n            ZSTD_VecMask matches = ZSTD_row_getMatchMask(dmsTagRow, (BYTE)dmsTag, headGrouped, rowEntries);\n\n            for (; (matches > 0) && (nbAttempts > 0); matches &= (matches - 1)) {\n                U32 const matchPos = ((headGrouped + ZSTD_VecMask_next(matches)) / groupWidth) & rowMask;\n                U32 const matchIndex = dmsRow[matchPos];\n                if(matchPos == 0) continue;\n                if (matchIndex < dmsLowestIndex)\n                    break;\n                PREFETCH_L1(dmsBase + matchIndex);\n                matchBuffer[numMatches++] = matchIndex;\n                --nbAttempts;\n            }\n\n            /* Return the longest match */\n            for (; currMatch < numMatches; ++currMatch) {\n                U32 const matchIndex = matchBuffer[currMatch];\n                size_t currentMl=0;\n                assert(matchIndex >= dmsLowestIndex);\n                assert(matchIndex < curr);\n\n                {   const BYTE* const match = dmsBase + matchIndex;\n                    assert(match+4 <= dmsEnd);\n                    if (MEM_read32(match) == MEM_read32(ip))\n                        currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, dmsEnd, prefixStart) + 4;\n                }\n\n                if (currentMl > ml) {\n                    ml = currentMl;\n                    assert(curr > matchIndex + dmsIndexDelta);\n                    *offsetPtr = OFFSET_TO_OFFBASE(curr - (matchIndex + dmsIndexDelta));\n                    if (ip+currentMl == iLimit) break;\n                }\n            }\n        }\n    }\n    return ml;\n}\n\n\n/**\n * Generate search functions templated on (dictMode, mls, rowLog).\n * These functions are outlined for code size & compilation time.\n * ZSTD_searchMax() dispatches to the correct implementation function.\n *\n * TODO: The start of the search function involves loading and calculating a\n * bunch of constants from the ZSTD_MatchState_t. These computations could be\n * done in an initialization function, and saved somewhere in the match state.\n * Then we could pass a pointer to the saved state instead of the match state,\n * and avoid duplicate computations.\n *\n * TODO: Move the match re-winding into searchMax. This improves compression\n * ratio, and unlocks further simplifications with the next TODO.\n *\n * TODO: Try moving the repcode search into searchMax. After the re-winding\n * and repcode search are in searchMax, there is no more logic in the match\n * finder loop that requires knowledge about the dictMode. So we should be\n * able to avoid force inlining it, and we can join the extDict loop with\n * the single segment loop. It should go in searchMax instead of its own\n * function to avoid having multiple virtual function calls per search.\n */\n\n#define ZSTD_BT_SEARCH_FN(dictMode, mls) ZSTD_BtFindBestMatch_##dictMode##_##mls\n#define ZSTD_HC_SEARCH_FN(dictMode, mls) ZSTD_HcFindBestMatch_##dictMode##_##mls\n#define ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog) ZSTD_RowFindBestMatch_##dictMode##_##mls##_##rowLog\n\n#define ZSTD_SEARCH_FN_ATTRS FORCE_NOINLINE\n\n#define GEN_ZSTD_BT_SEARCH_FN(dictMode, mls)                                           \\\n    ZSTD_SEARCH_FN_ATTRS size_t ZSTD_BT_SEARCH_FN(dictMode, mls)(                      \\\n            ZSTD_MatchState_t* ms,                                                     \\\n            const BYTE* ip, const BYTE* const iLimit,                                  \\\n            size_t* offBasePtr)                                                        \\\n    {                                                                                  \\\n        assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls);                           \\\n        return ZSTD_BtFindBestMatch(ms, ip, iLimit, offBasePtr, mls, ZSTD_##dictMode); \\\n    }                                                                                  \\\n\n#define GEN_ZSTD_HC_SEARCH_FN(dictMode, mls)                                          \\\n    ZSTD_SEARCH_FN_ATTRS size_t ZSTD_HC_SEARCH_FN(dictMode, mls)(                     \\\n            ZSTD_MatchState_t* ms,                                                    \\\n            const BYTE* ip, const BYTE* const iLimit,                                 \\\n            size_t* offsetPtr)                                                        \\\n    {                                                                                 \\\n        assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls);                          \\\n        return ZSTD_HcFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \\\n    }                                                                                 \\\n\n#define GEN_ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)                                          \\\n    ZSTD_SEARCH_FN_ATTRS size_t ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)(                     \\\n            ZSTD_MatchState_t* ms,                                                             \\\n            const BYTE* ip, const BYTE* const iLimit,                                          \\\n            size_t* offsetPtr)                                                                 \\\n    {                                                                                          \\\n        assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls);                                   \\\n        assert(MAX(4, MIN(6, ms->cParams.searchLog)) == rowLog);                               \\\n        return ZSTD_RowFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode, rowLog); \\\n    }                                                                                          \\\n\n#define ZSTD_FOR_EACH_ROWLOG(X, dictMode, mls) \\\n    X(dictMode, mls, 4)                        \\\n    X(dictMode, mls, 5)                        \\\n    X(dictMode, mls, 6)\n\n#define ZSTD_FOR_EACH_MLS_ROWLOG(X, dictMode) \\\n    ZSTD_FOR_EACH_ROWLOG(X, dictMode, 4)      \\\n    ZSTD_FOR_EACH_ROWLOG(X, dictMode, 5)      \\\n    ZSTD_FOR_EACH_ROWLOG(X, dictMode, 6)\n\n#define ZSTD_FOR_EACH_MLS(X, dictMode) \\\n    X(dictMode, 4)                     \\\n    X(dictMode, 5)                     \\\n    X(dictMode, 6)\n\n#define ZSTD_FOR_EACH_DICT_MODE(X, ...) \\\n    X(__VA_ARGS__, noDict)              \\\n    X(__VA_ARGS__, extDict)             \\\n    X(__VA_ARGS__, dictMatchState)      \\\n    X(__VA_ARGS__, dedicatedDictSearch)\n\n/* Generate row search fns for each combination of (dictMode, mls, rowLog) */\nZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS_ROWLOG, GEN_ZSTD_ROW_SEARCH_FN)\n/* Generate binary Tree search fns for each combination of (dictMode, mls) */\nZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_BT_SEARCH_FN)\n/* Generate hash chain search fns for each combination of (dictMode, mls) */\nZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_HC_SEARCH_FN)\n\ntypedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searchMethod_e;\n\n#define GEN_ZSTD_CALL_BT_SEARCH_FN(dictMode, mls)                         \\\n    case mls:                                                             \\\n        return ZSTD_BT_SEARCH_FN(dictMode, mls)(ms, ip, iend, offsetPtr);\n#define GEN_ZSTD_CALL_HC_SEARCH_FN(dictMode, mls)                         \\\n    case mls:                                                             \\\n        return ZSTD_HC_SEARCH_FN(dictMode, mls)(ms, ip, iend, offsetPtr);\n#define GEN_ZSTD_CALL_ROW_SEARCH_FN(dictMode, mls, rowLog)                         \\\n    case rowLog:                                                                   \\\n        return ZSTD_ROW_SEARCH_FN(dictMode, mls, rowLog)(ms, ip, iend, offsetPtr);\n\n#define ZSTD_SWITCH_MLS(X, dictMode)   \\\n    switch (mls) {                     \\\n        ZSTD_FOR_EACH_MLS(X, dictMode) \\\n    }\n\n#define ZSTD_SWITCH_ROWLOG(dictMode, mls)                                    \\\n    case mls:                                                                \\\n        switch (rowLog) {                                                    \\\n            ZSTD_FOR_EACH_ROWLOG(GEN_ZSTD_CALL_ROW_SEARCH_FN, dictMode, mls) \\\n        }                                                                    \\\n        ZSTD_UNREACHABLE;                                                    \\\n        break;\n\n#define ZSTD_SWITCH_SEARCH_METHOD(dictMode)                       \\\n    switch (searchMethod) {                                       \\\n        case search_hashChain:                                    \\\n            ZSTD_SWITCH_MLS(GEN_ZSTD_CALL_HC_SEARCH_FN, dictMode) \\\n            break;                                                \\\n        case search_binaryTree:                                   \\\n            ZSTD_SWITCH_MLS(GEN_ZSTD_CALL_BT_SEARCH_FN, dictMode) \\\n            break;                                                \\\n        case search_rowHash:                                      \\\n            ZSTD_SWITCH_MLS(ZSTD_SWITCH_ROWLOG, dictMode)         \\\n            break;                                                \\\n    }                                                             \\\n    ZSTD_UNREACHABLE;\n\n/**\n * Searches for the longest match at @p ip.\n * Dispatches to the correct implementation function based on the\n * (searchMethod, dictMode, mls, rowLog). We use switch statements\n * here instead of using an indirect function call through a function\n * pointer because after Spectre and Meltdown mitigations, indirect\n * function calls can be very costly, especially in the kernel.\n *\n * NOTE: dictMode and searchMethod should be templated, so those switch\n * statements should be optimized out. Only the mls & rowLog switches\n * should be left.\n *\n * @param ms The match state.\n * @param ip The position to search at.\n * @param iend The end of the input data.\n * @param[out] offsetPtr Stores the match offset into this pointer.\n * @param mls The minimum search length, in the range [4, 6].\n * @param rowLog The row log (if applicable), in the range [4, 6].\n * @param searchMethod The search method to use (templated).\n * @param dictMode The dictMode (templated).\n *\n * @returns The length of the longest match found, or < mls if no match is found.\n * If a match is found its offset is stored in @p offsetPtr.\n */\nFORCE_INLINE_TEMPLATE size_t ZSTD_searchMax(\n    ZSTD_MatchState_t* ms,\n    const BYTE* ip,\n    const BYTE* iend,\n    size_t* offsetPtr,\n    U32 const mls,\n    U32 const rowLog,\n    searchMethod_e const searchMethod,\n    ZSTD_dictMode_e const dictMode)\n{\n    if (dictMode == ZSTD_noDict) {\n        ZSTD_SWITCH_SEARCH_METHOD(noDict)\n    } else if (dictMode == ZSTD_extDict) {\n        ZSTD_SWITCH_SEARCH_METHOD(extDict)\n    } else if (dictMode == ZSTD_dictMatchState) {\n        ZSTD_SWITCH_SEARCH_METHOD(dictMatchState)\n    } else if (dictMode == ZSTD_dedicatedDictSearch) {\n        ZSTD_SWITCH_SEARCH_METHOD(dedicatedDictSearch)\n    }\n    ZSTD_UNREACHABLE;\n    return 0;\n}\n\n/* *******************************\n*  Common parser - lazy strategy\n*********************************/\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_lazy_generic(\n                        ZSTD_MatchState_t* ms, SeqStore_t* seqStore,\n                        U32 rep[ZSTD_REP_NUM],\n                        const void* src, size_t srcSize,\n                        const searchMethod_e searchMethod, const U32 depth,\n                        ZSTD_dictMode_e const dictMode)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = (searchMethod == search_rowHash) ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;\n    const BYTE* const base = ms->window.base;\n    const U32 prefixLowestIndex = ms->window.dictLimit;\n    const BYTE* const prefixLowest = base + prefixLowestIndex;\n    const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6);\n    const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);\n\n    U32 offset_1 = rep[0], offset_2 = rep[1];\n    U32 offsetSaved1 = 0, offsetSaved2 = 0;\n\n    const int isDMS = dictMode == ZSTD_dictMatchState;\n    const int isDDS = dictMode == ZSTD_dedicatedDictSearch;\n    const int isDxS = isDMS || isDDS;\n    const ZSTD_MatchState_t* const dms = ms->dictMatchState;\n    const U32 dictLowestIndex      = isDxS ? dms->window.dictLimit : 0;\n    const BYTE* const dictBase     = isDxS ? dms->window.base : NULL;\n    const BYTE* const dictLowest   = isDxS ? dictBase + dictLowestIndex : NULL;\n    const BYTE* const dictEnd      = isDxS ? dms->window.nextSrc : NULL;\n    const U32 dictIndexDelta       = isDxS ?\n                                     prefixLowestIndex - (U32)(dictEnd - dictBase) :\n                                     0;\n    const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest));\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_lazy_generic (dictMode=%u) (searchFunc=%u)\", (U32)dictMode, (U32)searchMethod);\n    ip += (dictAndPrefixLength == 0);\n    if (dictMode == ZSTD_noDict) {\n        U32 const curr = (U32)(ip - base);\n        U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, ms->cParams.windowLog);\n        U32 const maxRep = curr - windowLow;\n        if (offset_2 > maxRep) offsetSaved2 = offset_2, offset_2 = 0;\n        if (offset_1 > maxRep) offsetSaved1 = offset_1, offset_1 = 0;\n    }\n    if (isDxS) {\n        /* dictMatchState repCode checks don't currently handle repCode == 0\n         * disabling. */\n        assert(offset_1 <= dictAndPrefixLength);\n        assert(offset_2 <= dictAndPrefixLength);\n    }\n\n    /* Reset the lazy skipping state */\n    ms->lazySkipping = 0;\n\n    if (searchMethod == search_rowHash) {\n        ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n    }\n\n    /* Match Loop */\n#if defined(__GNUC__) && defined(__x86_64__)\n    /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the\n     * code alignment is perturbed. To fix the instability align the loop on 32-bytes.\n     */\n    __asm__(\".p2align 5\");\n#endif\n    while (ip < ilimit) {\n        size_t matchLength=0;\n        size_t offBase = REPCODE1_TO_OFFBASE;\n        const BYTE* start=ip+1;\n        DEBUGLOG(7, \"search baseline (depth 0)\");\n\n        /* check repCode */\n        if (isDxS) {\n            const U32 repIndex = (U32)(ip - base) + 1 - offset_1;\n            const BYTE* repMatch = ((dictMode == ZSTD_dictMatchState || dictMode == ZSTD_dedicatedDictSearch)\n                                && repIndex < prefixLowestIndex) ?\n                                   dictBase + (repIndex - dictIndexDelta) :\n                                   base + repIndex;\n            if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {\n                const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n                matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n                if (depth==0) goto _storeSequence;\n            }\n        }\n        if ( dictMode == ZSTD_noDict\n          && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {\n            matchLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;\n            if (depth==0) goto _storeSequence;\n        }\n\n        /* first search (depth 0) */\n        {   size_t offbaseFound = 999999999;\n            size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &offbaseFound, mls, rowLog, searchMethod, dictMode);\n            if (ml2 > matchLength)\n                matchLength = ml2, start = ip, offBase = offbaseFound;\n        }\n\n        if (matchLength < 4) {\n            size_t const step = ((size_t)(ip-anchor) >> kSearchStrength) + 1;   /* jump faster over incompressible sections */;\n            ip += step;\n            /* Enter the lazy skipping mode once we are skipping more than 8 bytes at a time.\n             * In this mode we stop inserting every position into our tables, and only insert\n             * positions that we search, which is one in step positions.\n             * The exact cutoff is flexible, I've just chosen a number that is reasonably high,\n             * so we minimize the compression ratio loss in \"normal\" scenarios. This mode gets\n             * triggered once we've gone 2KB without finding any matches.\n             */\n            ms->lazySkipping = step > kLazySkippingStep;\n            continue;\n        }\n\n        /* let's try to find a better solution */\n        if (depth>=1)\n        while (ip<ilimit) {\n            DEBUGLOG(7, \"search depth 1\");\n            ip ++;\n            if ( (dictMode == ZSTD_noDict)\n              && (offBase) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {\n                size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;\n                int const gain2 = (int)(mlRep * 3);\n                int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1);\n                if ((mlRep >= 4) && (gain2 > gain1))\n                    matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n            }\n            if (isDxS) {\n                const U32 repIndex = (U32)(ip - base) - offset_1;\n                const BYTE* repMatch = repIndex < prefixLowestIndex ?\n                               dictBase + (repIndex - dictIndexDelta) :\n                               base + repIndex;\n                if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                    && (MEM_read32(repMatch) == MEM_read32(ip)) ) {\n                    const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n                    size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n                    int const gain2 = (int)(mlRep * 3);\n                    int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1);\n                    if ((mlRep >= 4) && (gain2 > gain1))\n                        matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                }\n            }\n            {   size_t ofbCandidate=999999999;\n                size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, dictMode);\n                int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 4);\n                if ((ml2 >= 4) && (gain2 > gain1)) {\n                    matchLength = ml2, offBase = ofbCandidate, start = ip;\n                    continue;   /* search a better one */\n            }   }\n\n            /* let's find an even better one */\n            if ((depth==2) && (ip<ilimit)) {\n                DEBUGLOG(7, \"search depth 2\");\n                ip ++;\n                if ( (dictMode == ZSTD_noDict)\n                  && (offBase) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {\n                    size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;\n                    int const gain2 = (int)(mlRep * 4);\n                    int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1);\n                    if ((mlRep >= 4) && (gain2 > gain1))\n                        matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                }\n                if (isDxS) {\n                    const U32 repIndex = (U32)(ip - base) - offset_1;\n                    const BYTE* repMatch = repIndex < prefixLowestIndex ?\n                                   dictBase + (repIndex - dictIndexDelta) :\n                                   base + repIndex;\n                    if ((ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                        && (MEM_read32(repMatch) == MEM_read32(ip)) ) {\n                        const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;\n                        size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;\n                        int const gain2 = (int)(mlRep * 4);\n                        int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1);\n                        if ((mlRep >= 4) && (gain2 > gain1))\n                            matchLength = mlRep, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                    }\n                }\n                {   size_t ofbCandidate=999999999;\n                    size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, dictMode);\n                    int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                    int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 7);\n                    if ((ml2 >= 4) && (gain2 > gain1)) {\n                        matchLength = ml2, offBase = ofbCandidate, start = ip;\n                        continue;\n            }   }   }\n            break;  /* nothing found : store previous solution */\n        }\n\n        /* NOTE:\n         * Pay attention that `start[-value]` can lead to strange undefined behavior\n         * notably if `value` is unsigned, resulting in a large positive `-value`.\n         */\n        /* catch up */\n        if (OFFBASE_IS_OFFSET(offBase)) {\n            if (dictMode == ZSTD_noDict) {\n                while ( ((start > anchor) & (start - OFFBASE_TO_OFFSET(offBase) > prefixLowest))\n                     && (start[-1] == (start-OFFBASE_TO_OFFSET(offBase))[-1]) )  /* only search for offset within prefix */\n                    { start--; matchLength++; }\n            }\n            if (isDxS) {\n                U32 const matchIndex = (U32)((size_t)(start-base) - OFFBASE_TO_OFFSET(offBase));\n                const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex;\n                const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest;\n                while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; }  /* catch up */\n            }\n            offset_2 = offset_1; offset_1 = (U32)OFFBASE_TO_OFFSET(offBase);\n        }\n        /* store sequence */\n_storeSequence:\n        {   size_t const litLength = (size_t)(start - anchor);\n            ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offBase, matchLength);\n            anchor = ip = start + matchLength;\n        }\n        if (ms->lazySkipping) {\n            /* We've found a match, disable lazy skipping mode, and refill the hash cache. */\n            if (searchMethod == search_rowHash) {\n                ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n            }\n            ms->lazySkipping = 0;\n        }\n\n        /* check immediate repcode */\n        if (isDxS) {\n            while (ip <= ilimit) {\n                U32 const current2 = (U32)(ip-base);\n                U32 const repIndex = current2 - offset_2;\n                const BYTE* repMatch = repIndex < prefixLowestIndex ?\n                        dictBase - dictIndexDelta + repIndex :\n                        base + repIndex;\n                if ( (ZSTD_index_overlap_check(prefixLowestIndex, repIndex))\n                   && (MEM_read32(repMatch) == MEM_read32(ip)) ) {\n                    const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend;\n                    matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4;\n                    offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase;   /* swap offset_2 <=> offset_1 */\n                    ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength);\n                    ip += matchLength;\n                    anchor = ip;\n                    continue;\n                }\n                break;\n            }\n        }\n\n        if (dictMode == ZSTD_noDict) {\n            while ( ((ip <= ilimit) & (offset_2>0))\n                 && (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {\n                /* store sequence */\n                matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;\n                offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase; /* swap repcodes */\n                ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength);\n                ip += matchLength;\n                anchor = ip;\n                continue;   /* faster when present ... (?) */\n    }   }   }\n\n    /* If offset_1 started invalid (offsetSaved1 != 0) and became valid (offset_1 != 0),\n     * rotate saved offsets. See comment in ZSTD_compressBlock_fast_noDict for more context. */\n    offsetSaved2 = ((offsetSaved1 != 0) && (offset_1 != 0)) ? offsetSaved1 : offsetSaved2;\n\n    /* save reps for next block */\n    rep[0] = offset_1 ? offset_1 : offsetSaved1;\n    rep[1] = offset_2 ? offset_2 : offsetSaved2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n#endif /* build exclusions */\n\n\n#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_greedy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_greedy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch);\n}\n\nsize_t ZSTD_compressBlock_greedy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_greedy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0, ZSTD_dedicatedDictSearch);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch);\n}\n\nsize_t ZSTD_compressBlock_lazy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1, ZSTD_dedicatedDictSearch);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch);\n}\n\nsize_t ZSTD_compressBlock_lazy2_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2, ZSTD_dedicatedDictSearch);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btlazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_btlazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2, ZSTD_dictMatchState);\n}\n#endif\n\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_compressBlock_lazy_extDict_generic(\n                        ZSTD_MatchState_t* ms, SeqStore_t* seqStore,\n                        U32 rep[ZSTD_REP_NUM],\n                        const void* src, size_t srcSize,\n                        const searchMethod_e searchMethod, const U32 depth)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;\n    const BYTE* const base = ms->window.base;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const BYTE* const dictEnd  = dictBase + dictLimit;\n    const BYTE* const dictStart  = dictBase + ms->window.lowLimit;\n    const U32 windowLog = ms->cParams.windowLog;\n    const U32 mls = BOUNDED(4, ms->cParams.minMatch, 6);\n    const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);\n\n    U32 offset_1 = rep[0], offset_2 = rep[1];\n\n    DEBUGLOG(5, \"ZSTD_compressBlock_lazy_extDict_generic (searchFunc=%u)\", (U32)searchMethod);\n\n    /* Reset the lazy skipping state */\n    ms->lazySkipping = 0;\n\n    /* init */\n    ip += (ip == prefixStart);\n    if (searchMethod == search_rowHash) {\n        ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n    }\n\n    /* Match Loop */\n#if defined(__GNUC__) && defined(__x86_64__)\n    /* I've measured random a 5% speed loss on levels 5 & 6 (greedy) when the\n     * code alignment is perturbed. To fix the instability align the loop on 32-bytes.\n     */\n    __asm__(\".p2align 5\");\n#endif\n    while (ip < ilimit) {\n        size_t matchLength=0;\n        size_t offBase = REPCODE1_TO_OFFBASE;\n        const BYTE* start=ip+1;\n        U32 curr = (U32)(ip-base);\n\n        /* check repCode */\n        {   const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1, windowLog);\n            const U32 repIndex = (U32)(curr+1 - offset_1);\n            const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n            const BYTE* const repMatch = repBase + repIndex;\n            if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n               & (offset_1 <= curr+1 - windowLow) ) /* note: we are searching at curr+1 */\n            if (MEM_read32(ip+1) == MEM_read32(repMatch)) {\n                /* repcode detected we should take it */\n                const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                matchLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                if (depth==0) goto _storeSequence;\n        }   }\n\n        /* first search (depth 0) */\n        {   size_t ofbCandidate = 999999999;\n            size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict);\n            if (ml2 > matchLength)\n                matchLength = ml2, start = ip, offBase = ofbCandidate;\n        }\n\n        if (matchLength < 4) {\n            size_t const step = ((size_t)(ip-anchor) >> kSearchStrength);\n            ip += step + 1;   /* jump faster over incompressible sections */\n            /* Enter the lazy skipping mode once we are skipping more than 8 bytes at a time.\n             * In this mode we stop inserting every position into our tables, and only insert\n             * positions that we search, which is one in step positions.\n             * The exact cutoff is flexible, I've just chosen a number that is reasonably high,\n             * so we minimize the compression ratio loss in \"normal\" scenarios. This mode gets\n             * triggered once we've gone 2KB without finding any matches.\n             */\n            ms->lazySkipping = step > kLazySkippingStep;\n            continue;\n        }\n\n        /* let's try to find a better solution */\n        if (depth>=1)\n        while (ip<ilimit) {\n            ip ++;\n            curr++;\n            /* check repCode */\n            if (offBase) {\n                const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);\n                const U32 repIndex = (U32)(curr - offset_1);\n                const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n                const BYTE* const repMatch = repBase + repIndex;\n                if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n                   & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */\n                if (MEM_read32(ip) == MEM_read32(repMatch)) {\n                    /* repcode detected */\n                    const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                    size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                    int const gain2 = (int)(repLength * 3);\n                    int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offBase) + 1);\n                    if ((repLength >= 4) && (gain2 > gain1))\n                        matchLength = repLength, offBase = REPCODE1_TO_OFFBASE, start = ip;\n            }   }\n\n            /* search match, depth 1 */\n            {   size_t ofbCandidate = 999999999;\n                size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict);\n                int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 4);\n                if ((ml2 >= 4) && (gain2 > gain1)) {\n                    matchLength = ml2, offBase = ofbCandidate, start = ip;\n                    continue;   /* search a better one */\n            }   }\n\n            /* let's find an even better one */\n            if ((depth==2) && (ip<ilimit)) {\n                ip ++;\n                curr++;\n                /* check repCode */\n                if (offBase) {\n                    const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);\n                    const U32 repIndex = (U32)(curr - offset_1);\n                    const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n                    const BYTE* const repMatch = repBase + repIndex;\n                    if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n                       & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */\n                    if (MEM_read32(ip) == MEM_read32(repMatch)) {\n                        /* repcode detected */\n                        const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                        size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                        int const gain2 = (int)(repLength * 4);\n                        int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 1);\n                        if ((repLength >= 4) && (gain2 > gain1))\n                            matchLength = repLength, offBase = REPCODE1_TO_OFFBASE, start = ip;\n                }   }\n\n                /* search match, depth 2 */\n                {   size_t ofbCandidate = 999999999;\n                    size_t const ml2 = ZSTD_searchMax(ms, ip, iend, &ofbCandidate, mls, rowLog, searchMethod, ZSTD_extDict);\n                    int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)ofbCandidate));   /* raw approx */\n                    int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offBase) + 7);\n                    if ((ml2 >= 4) && (gain2 > gain1)) {\n                        matchLength = ml2, offBase = ofbCandidate, start = ip;\n                        continue;\n            }   }   }\n            break;  /* nothing found : store previous solution */\n        }\n\n        /* catch up */\n        if (OFFBASE_IS_OFFSET(offBase)) {\n            U32 const matchIndex = (U32)((size_t)(start-base) - OFFBASE_TO_OFFSET(offBase));\n            const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;\n            const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;\n            while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; }  /* catch up */\n            offset_2 = offset_1; offset_1 = (U32)OFFBASE_TO_OFFSET(offBase);\n        }\n\n        /* store sequence */\n_storeSequence:\n        {   size_t const litLength = (size_t)(start - anchor);\n            ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offBase, matchLength);\n            anchor = ip = start + matchLength;\n        }\n        if (ms->lazySkipping) {\n            /* We've found a match, disable lazy skipping mode, and refill the hash cache. */\n            if (searchMethod == search_rowHash) {\n                ZSTD_row_fillHashCache(ms, base, rowLog, mls, ms->nextToUpdate, ilimit);\n            }\n            ms->lazySkipping = 0;\n        }\n\n        /* check immediate repcode */\n        while (ip <= ilimit) {\n            const U32 repCurrent = (U32)(ip-base);\n            const U32 windowLow = ZSTD_getLowestMatchIndex(ms, repCurrent, windowLog);\n            const U32 repIndex = repCurrent - offset_2;\n            const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;\n            const BYTE* const repMatch = repBase + repIndex;\n            if ( (ZSTD_index_overlap_check(dictLimit, repIndex))\n               & (offset_2 <= repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */\n            if (MEM_read32(ip) == MEM_read32(repMatch)) {\n                /* repcode detected we should take it */\n                const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;\n                matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;\n                offBase = offset_2; offset_2 = offset_1; offset_1 = (U32)offBase;   /* swap offset history */\n                ZSTD_storeSeq(seqStore, 0, anchor, iend, REPCODE1_TO_OFFBASE, matchLength);\n                ip += matchLength;\n                anchor = ip;\n                continue;   /* faster when present ... (?) */\n            }\n            break;\n    }   }\n\n    /* Save reps for next block */\n    rep[0] = offset_1;\n    rep[1] = offset_2;\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n#endif /* build exclusions */\n\n#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_greedy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0);\n}\n\nsize_t ZSTD_compressBlock_greedy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 0);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1);\n}\n\nsize_t ZSTD_compressBlock_lazy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 1);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2);\n}\n\nsize_t ZSTD_compressBlock_lazy2_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_rowHash, 2);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btlazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize)\n\n{\n    return ZSTD_compressBlock_lazy_extDict_generic(ms, seqStore, rep, src, srcSize, search_binaryTree, 2);\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_lazy.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LAZY_H\n#define ZSTD_LAZY_H\n\n#include \"zstd_compress_internal.h\"\n\n/**\n * Dedicated Dictionary Search Structure bucket log. In the\n * ZSTD_dedicatedDictSearch mode, the hashTable has\n * 2 ** ZSTD_LAZY_DDSS_BUCKET_LOG entries in each bucket, rather than just\n * one.\n */\n#define ZSTD_LAZY_DDSS_BUCKET_LOG 2\n\n#define ZSTD_ROW_HASH_TAG_BITS 8        /* nb bits to use for the tag */\n\n#if !defined(ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR)\nU32 ZSTD_insertAndFindFirstIndex(ZSTD_MatchState_t* ms, const BYTE* ip);\nvoid ZSTD_row_update(ZSTD_MatchState_t* const ms, const BYTE* ip);\n\nvoid ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_MatchState_t* ms, const BYTE* const ip);\n\nvoid ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue);  /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */\n#endif\n\n#ifndef ZSTD_EXCLUDE_GREEDY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_greedy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_greedy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_GREEDY ZSTD_compressBlock_greedy\n#define ZSTD_COMPRESSBLOCK_GREEDY_ROW ZSTD_compressBlock_greedy_row\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE ZSTD_compressBlock_greedy_dictMatchState\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW ZSTD_compressBlock_greedy_dictMatchState_row\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH ZSTD_compressBlock_greedy_dedicatedDictSearch\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_greedy_dedicatedDictSearch_row\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT ZSTD_compressBlock_greedy_extDict\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW ZSTD_compressBlock_greedy_extDict_row\n#else\n#define ZSTD_COMPRESSBLOCK_GREEDY NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_ROW NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DICTMATCHSTATE_ROW NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_DEDICATEDDICTSEARCH_ROW NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_GREEDY_EXTDICT_ROW NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_LAZY ZSTD_compressBlock_lazy\n#define ZSTD_COMPRESSBLOCK_LAZY_ROW ZSTD_compressBlock_lazy_row\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE ZSTD_compressBlock_lazy_dictMatchState\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW ZSTD_compressBlock_lazy_dictMatchState_row\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH ZSTD_compressBlock_lazy_dedicatedDictSearch\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_lazy_dedicatedDictSearch_row\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT ZSTD_compressBlock_lazy_extDict\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW ZSTD_compressBlock_lazy_extDict_row\n#else\n#define ZSTD_COMPRESSBLOCK_LAZY NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DICTMATCHSTATE_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_DEDICATEDDICTSEARCH_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_LAZY_EXTDICT_ROW NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_LAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_lazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dictMatchState_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_dedicatedDictSearch_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_lazy2_extDict_row(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_LAZY2 ZSTD_compressBlock_lazy2\n#define ZSTD_COMPRESSBLOCK_LAZY2_ROW ZSTD_compressBlock_lazy2_row\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE ZSTD_compressBlock_lazy2_dictMatchState\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW ZSTD_compressBlock_lazy2_dictMatchState_row\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH ZSTD_compressBlock_lazy2_dedicatedDictSearch\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW ZSTD_compressBlock_lazy2_dedicatedDictSearch_row\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT ZSTD_compressBlock_lazy2_extDict\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW ZSTD_compressBlock_lazy2_extDict_row\n#else\n#define ZSTD_COMPRESSBLOCK_LAZY2 NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DICTMATCHSTATE_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_DEDICATEDDICTSEARCH_ROW NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_LAZY2_EXTDICT_ROW NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btlazy2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btlazy2_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btlazy2_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_BTLAZY2 ZSTD_compressBlock_btlazy2\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE ZSTD_compressBlock_btlazy2_dictMatchState\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT ZSTD_compressBlock_btlazy2_extDict\n#else\n#define ZSTD_COMPRESSBLOCK_BTLAZY2 NULL\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_BTLAZY2_EXTDICT NULL\n#endif\n\n#endif /* ZSTD_LAZY_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_ldm.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_ldm.h\"\n\n#include \"../common/debug.h\"\n#include <xxhash.h>\n#include \"zstd_fast.h\"          /* ZSTD_fillHashTable() */\n#include \"zstd_double_fast.h\"   /* ZSTD_fillDoubleHashTable() */\n#include \"zstd_ldm_geartab.h\"\n\n#define LDM_BUCKET_SIZE_LOG 4\n#define LDM_MIN_MATCH_LENGTH 64\n#define LDM_HASH_RLOG 7\n\ntypedef struct {\n    U64 rolling;\n    U64 stopMask;\n} ldmRollingHashState_t;\n\n/** ZSTD_ldm_gear_init():\n *\n * Initializes the rolling hash state such that it will honor the\n * settings in params. */\nstatic void ZSTD_ldm_gear_init(ldmRollingHashState_t* state, ldmParams_t const* params)\n{\n    unsigned maxBitsInMask = MIN(params->minMatchLength, 64);\n    unsigned hashRateLog = params->hashRateLog;\n\n    state->rolling = ~(U32)0;\n\n    /* The choice of the splitting criterion is subject to two conditions:\n     *   1. it has to trigger on average every 2^(hashRateLog) bytes;\n     *   2. ideally, it has to depend on a window of minMatchLength bytes.\n     *\n     * In the gear hash algorithm, bit n depends on the last n bytes;\n     * so in order to obtain a good quality splitting criterion it is\n     * preferable to use bits with high weight.\n     *\n     * To match condition 1 we use a mask with hashRateLog bits set\n     * and, because of the previous remark, we make sure these bits\n     * have the highest possible weight while still respecting\n     * condition 2.\n     */\n    if (hashRateLog > 0 && hashRateLog <= maxBitsInMask) {\n        state->stopMask = (((U64)1 << hashRateLog) - 1) << (maxBitsInMask - hashRateLog);\n    } else {\n        /* In this degenerate case we simply honor the hash rate. */\n        state->stopMask = ((U64)1 << hashRateLog) - 1;\n    }\n}\n\n/** ZSTD_ldm_gear_reset()\n * Feeds [data, data + minMatchLength) into the hash without registering any\n * splits. This effectively resets the hash state. This is used when skipping\n * over data, either at the beginning of a block, or skipping sections.\n */\nstatic void ZSTD_ldm_gear_reset(ldmRollingHashState_t* state,\n                                BYTE const* data, size_t minMatchLength)\n{\n    U64 hash = state->rolling;\n    size_t n = 0;\n\n#define GEAR_ITER_ONCE() do {                                  \\\n        hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \\\n        n += 1;                                                \\\n    } while (0)\n    while (n + 3 < minMatchLength) {\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n    }\n    while (n < minMatchLength) {\n        GEAR_ITER_ONCE();\n    }\n#undef GEAR_ITER_ONCE\n}\n\n/** ZSTD_ldm_gear_feed():\n *\n * Registers in the splits array all the split points found in the first\n * size bytes following the data pointer. This function terminates when\n * either all the data has been processed or LDM_BATCH_SIZE splits are\n * present in the splits array.\n *\n * Precondition: The splits array must not be full.\n * Returns: The number of bytes processed. */\nstatic size_t ZSTD_ldm_gear_feed(ldmRollingHashState_t* state,\n                                 BYTE const* data, size_t size,\n                                 size_t* splits, unsigned* numSplits)\n{\n    size_t n;\n    U64 hash, mask;\n\n    hash = state->rolling;\n    mask = state->stopMask;\n    n = 0;\n\n#define GEAR_ITER_ONCE() do { \\\n        hash = (hash << 1) + ZSTD_ldm_gearTab[data[n] & 0xff]; \\\n        n += 1; \\\n        if (UNLIKELY((hash & mask) == 0)) { \\\n            splits[*numSplits] = n; \\\n            *numSplits += 1; \\\n            if (*numSplits == LDM_BATCH_SIZE) \\\n                goto done; \\\n        } \\\n    } while (0)\n\n    while (n + 3 < size) {\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n        GEAR_ITER_ONCE();\n    }\n    while (n < size) {\n        GEAR_ITER_ONCE();\n    }\n\n#undef GEAR_ITER_ONCE\n\ndone:\n    state->rolling = hash;\n    return n;\n}\n\nvoid ZSTD_ldm_adjustParameters(ldmParams_t* params,\n                        const ZSTD_compressionParameters* cParams)\n{\n    params->windowLog = cParams->windowLog;\n    ZSTD_STATIC_ASSERT(LDM_BUCKET_SIZE_LOG <= ZSTD_LDM_BUCKETSIZELOG_MAX);\n    DEBUGLOG(4, \"ZSTD_ldm_adjustParameters\");\n    if (params->hashRateLog == 0) {\n        if (params->hashLog > 0) {\n            /* if params->hashLog is set, derive hashRateLog from it */\n            assert(params->hashLog <= ZSTD_HASHLOG_MAX);\n            if (params->windowLog > params->hashLog) {\n                params->hashRateLog = params->windowLog - params->hashLog;\n            }\n        } else {\n            assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9);\n            /* mapping from [fast, rate7] to [btultra2, rate4] */\n            params->hashRateLog = 7 - (cParams->strategy/3);\n        }\n    }\n    if (params->hashLog == 0) {\n        params->hashLog = BOUNDED(ZSTD_HASHLOG_MIN, params->windowLog - params->hashRateLog, ZSTD_HASHLOG_MAX);\n    }\n    if (params->minMatchLength == 0) {\n        params->minMatchLength = LDM_MIN_MATCH_LENGTH;\n        if (cParams->strategy >= ZSTD_btultra)\n            params->minMatchLength /= 2;\n    }\n    if (params->bucketSizeLog==0) {\n        assert(1 <= (int)cParams->strategy && (int)cParams->strategy <= 9);\n        params->bucketSizeLog = BOUNDED(LDM_BUCKET_SIZE_LOG, (U32)cParams->strategy, ZSTD_LDM_BUCKETSIZELOG_MAX);\n    }\n    params->bucketSizeLog = MIN(params->bucketSizeLog, params->hashLog);\n}\n\nsize_t ZSTD_ldm_getTableSize(ldmParams_t params)\n{\n    size_t const ldmHSize = ((size_t)1) << params.hashLog;\n    size_t const ldmBucketSizeLog = MIN(params.bucketSizeLog, params.hashLog);\n    size_t const ldmBucketSize = ((size_t)1) << (params.hashLog - ldmBucketSizeLog);\n    size_t const totalSize = ZSTD_cwksp_alloc_size(ldmBucketSize)\n                           + ZSTD_cwksp_alloc_size(ldmHSize * sizeof(ldmEntry_t));\n    return params.enableLdm == ZSTD_ps_enable ? totalSize : 0;\n}\n\nsize_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)\n{\n    return params.enableLdm == ZSTD_ps_enable ? (maxChunkSize / params.minMatchLength) : 0;\n}\n\n/** ZSTD_ldm_getBucket() :\n *  Returns a pointer to the start of the bucket associated with hash. */\nstatic ldmEntry_t* ZSTD_ldm_getBucket(\n        const ldmState_t* ldmState, size_t hash, U32 const bucketSizeLog)\n{\n    return ldmState->hashTable + (hash << bucketSizeLog);\n}\n\n/** ZSTD_ldm_insertEntry() :\n *  Insert the entry with corresponding hash into the hash table */\nstatic void ZSTD_ldm_insertEntry(ldmState_t* ldmState,\n                                 size_t const hash, const ldmEntry_t entry,\n                                 U32 const bucketSizeLog)\n{\n    BYTE* const pOffset = ldmState->bucketOffsets + hash;\n    unsigned const offset = *pOffset;\n\n    *(ZSTD_ldm_getBucket(ldmState, hash, bucketSizeLog) + offset) = entry;\n    *pOffset = (BYTE)((offset + 1) & ((1u << bucketSizeLog) - 1));\n\n}\n\n/** ZSTD_ldm_countBackwardsMatch() :\n *  Returns the number of bytes that match backwards before pIn and pMatch.\n *\n *  We count only bytes where pMatch >= pBase and pIn >= pAnchor. */\nstatic size_t ZSTD_ldm_countBackwardsMatch(\n            const BYTE* pIn, const BYTE* pAnchor,\n            const BYTE* pMatch, const BYTE* pMatchBase)\n{\n    size_t matchLength = 0;\n    while (pIn > pAnchor && pMatch > pMatchBase && pIn[-1] == pMatch[-1]) {\n        pIn--;\n        pMatch--;\n        matchLength++;\n    }\n    return matchLength;\n}\n\n/** ZSTD_ldm_countBackwardsMatch_2segments() :\n *  Returns the number of bytes that match backwards from pMatch,\n *  even with the backwards match spanning 2 different segments.\n *\n *  On reaching `pMatchBase`, start counting from mEnd */\nstatic size_t ZSTD_ldm_countBackwardsMatch_2segments(\n                    const BYTE* pIn, const BYTE* pAnchor,\n                    const BYTE* pMatch, const BYTE* pMatchBase,\n                    const BYTE* pExtDictStart, const BYTE* pExtDictEnd)\n{\n    size_t matchLength = ZSTD_ldm_countBackwardsMatch(pIn, pAnchor, pMatch, pMatchBase);\n    if (pMatch - matchLength != pMatchBase || pMatchBase == pExtDictStart) {\n        /* If backwards match is entirely in the extDict or prefix, immediately return */\n        return matchLength;\n    }\n    DEBUGLOG(7, \"ZSTD_ldm_countBackwardsMatch_2segments: found 2-parts backwards match (length in prefix==%zu)\", matchLength);\n    matchLength += ZSTD_ldm_countBackwardsMatch(pIn - matchLength, pAnchor, pExtDictEnd, pExtDictStart);\n    DEBUGLOG(7, \"final backwards match length = %zu\", matchLength);\n    return matchLength;\n}\n\n/** ZSTD_ldm_fillFastTables() :\n *\n *  Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies.\n *  This is similar to ZSTD_loadDictionaryContent.\n *\n *  The tables for the other strategies are filled within their\n *  block compressors. */\nstatic size_t ZSTD_ldm_fillFastTables(ZSTD_MatchState_t* ms,\n                                      void const* end)\n{\n    const BYTE* const iend = (const BYTE*)end;\n\n    switch(ms->cParams.strategy)\n    {\n    case ZSTD_fast:\n        ZSTD_fillHashTable(ms, iend, ZSTD_dtlm_fast, ZSTD_tfp_forCCtx);\n        break;\n\n    case ZSTD_dfast:\n#ifndef ZSTD_EXCLUDE_DFAST_BLOCK_COMPRESSOR\n        ZSTD_fillDoubleHashTable(ms, iend, ZSTD_dtlm_fast, ZSTD_tfp_forCCtx);\n#else\n        assert(0); /* shouldn't be called: cparams should've been adjusted. */\n#endif\n        break;\n\n    case ZSTD_greedy:\n    case ZSTD_lazy:\n    case ZSTD_lazy2:\n    case ZSTD_btlazy2:\n    case ZSTD_btopt:\n    case ZSTD_btultra:\n    case ZSTD_btultra2:\n        break;\n    default:\n        assert(0);  /* not possible : not a valid strategy id */\n    }\n\n    return 0;\n}\n\nvoid ZSTD_ldm_fillHashTable(\n            ldmState_t* ldmState, const BYTE* ip,\n            const BYTE* iend, ldmParams_t const* params)\n{\n    U32 const minMatchLength = params->minMatchLength;\n    U32 const bucketSizeLog = params->bucketSizeLog;\n    U32 const hBits = params->hashLog - bucketSizeLog;\n    BYTE const* const base = ldmState->window.base;\n    BYTE const* const istart = ip;\n    ldmRollingHashState_t hashState;\n    size_t* const splits = ldmState->splitIndices;\n    unsigned numSplits;\n\n    DEBUGLOG(5, \"ZSTD_ldm_fillHashTable\");\n\n    ZSTD_ldm_gear_init(&hashState, params);\n    while (ip < iend) {\n        size_t hashed;\n        unsigned n;\n\n        numSplits = 0;\n        hashed = ZSTD_ldm_gear_feed(&hashState, ip, (size_t)(iend - ip), splits, &numSplits);\n\n        for (n = 0; n < numSplits; n++) {\n            if (ip + splits[n] >= istart + minMatchLength) {\n                BYTE const* const split = ip + splits[n] - minMatchLength;\n                U64 const xxhash = XXH64(split, minMatchLength, 0);\n                U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));\n                ldmEntry_t entry;\n\n                entry.offset = (U32)(split - base);\n                entry.checksum = (U32)(xxhash >> 32);\n                ZSTD_ldm_insertEntry(ldmState, hash, entry, params->bucketSizeLog);\n            }\n        }\n\n        ip += hashed;\n    }\n}\n\n\n/** ZSTD_ldm_limitTableUpdate() :\n *\n *  Sets cctx->nextToUpdate to a position corresponding closer to anchor\n *  if it is far way\n *  (after a long match, only update tables a limited amount). */\nstatic void ZSTD_ldm_limitTableUpdate(ZSTD_MatchState_t* ms, const BYTE* anchor)\n{\n    U32 const curr = (U32)(anchor - ms->window.base);\n    if (curr > ms->nextToUpdate + 1024) {\n        ms->nextToUpdate =\n            curr - MIN(512, curr - ms->nextToUpdate - 1024);\n    }\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_ldm_generateSequences_internal(\n        ldmState_t* ldmState, RawSeqStore_t* rawSeqStore,\n        ldmParams_t const* params, void const* src, size_t srcSize)\n{\n    /* LDM parameters */\n    int const extDict = ZSTD_window_hasExtDict(ldmState->window);\n    U32 const minMatchLength = params->minMatchLength;\n    U32 const entsPerBucket = 1U << params->bucketSizeLog;\n    U32 const hBits = params->hashLog - params->bucketSizeLog;\n    /* Prefix and extDict parameters */\n    U32 const dictLimit = ldmState->window.dictLimit;\n    U32 const lowestIndex = extDict ? ldmState->window.lowLimit : dictLimit;\n    BYTE const* const base = ldmState->window.base;\n    BYTE const* const dictBase = extDict ? ldmState->window.dictBase : NULL;\n    BYTE const* const dictStart = extDict ? dictBase + lowestIndex : NULL;\n    BYTE const* const dictEnd = extDict ? dictBase + dictLimit : NULL;\n    BYTE const* const lowPrefixPtr = base + dictLimit;\n    /* Input bounds */\n    BYTE const* const istart = (BYTE const*)src;\n    BYTE const* const iend = istart + srcSize;\n    BYTE const* const ilimit = iend - HASH_READ_SIZE;\n    /* Input positions */\n    BYTE const* anchor = istart;\n    BYTE const* ip = istart;\n    /* Rolling hash state */\n    ldmRollingHashState_t hashState;\n    /* Arrays for staged-processing */\n    size_t* const splits = ldmState->splitIndices;\n    ldmMatchCandidate_t* const candidates = ldmState->matchCandidates;\n    unsigned numSplits;\n\n    if (srcSize < minMatchLength)\n        return iend - anchor;\n\n    /* Initialize the rolling hash state with the first minMatchLength bytes */\n    ZSTD_ldm_gear_init(&hashState, params);\n    ZSTD_ldm_gear_reset(&hashState, ip, minMatchLength);\n    ip += minMatchLength;\n\n    while (ip < ilimit) {\n        size_t hashed;\n        unsigned n;\n\n        numSplits = 0;\n        hashed = ZSTD_ldm_gear_feed(&hashState, ip, ilimit - ip,\n                                    splits, &numSplits);\n\n        for (n = 0; n < numSplits; n++) {\n            BYTE const* const split = ip + splits[n] - minMatchLength;\n            U64 const xxhash = XXH64(split, minMatchLength, 0);\n            U32 const hash = (U32)(xxhash & (((U32)1 << hBits) - 1));\n\n            candidates[n].split = split;\n            candidates[n].hash = hash;\n            candidates[n].checksum = (U32)(xxhash >> 32);\n            candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, params->bucketSizeLog);\n            PREFETCH_L1(candidates[n].bucket);\n        }\n\n        for (n = 0; n < numSplits; n++) {\n            size_t forwardMatchLength = 0, backwardMatchLength = 0,\n                   bestMatchLength = 0, mLength;\n            U32 offset;\n            BYTE const* const split = candidates[n].split;\n            U32 const checksum = candidates[n].checksum;\n            U32 const hash = candidates[n].hash;\n            ldmEntry_t* const bucket = candidates[n].bucket;\n            ldmEntry_t const* cur;\n            ldmEntry_t const* bestEntry = NULL;\n            ldmEntry_t newEntry;\n\n            newEntry.offset = (U32)(split - base);\n            newEntry.checksum = checksum;\n\n            /* If a split point would generate a sequence overlapping with\n             * the previous one, we merely register it in the hash table and\n             * move on */\n            if (split < anchor) {\n                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);\n                continue;\n            }\n\n            for (cur = bucket; cur < bucket + entsPerBucket; cur++) {\n                size_t curForwardMatchLength, curBackwardMatchLength,\n                       curTotalMatchLength;\n                if (cur->checksum != checksum || cur->offset <= lowestIndex) {\n                    continue;\n                }\n                if (extDict) {\n                    BYTE const* const curMatchBase =\n                        cur->offset < dictLimit ? dictBase : base;\n                    BYTE const* const pMatch = curMatchBase + cur->offset;\n                    BYTE const* const matchEnd =\n                        cur->offset < dictLimit ? dictEnd : iend;\n                    BYTE const* const lowMatchPtr =\n                        cur->offset < dictLimit ? dictStart : lowPrefixPtr;\n                    curForwardMatchLength =\n                        ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr);\n                    if (curForwardMatchLength < minMatchLength) {\n                        continue;\n                    }\n                    curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments(\n                            split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd);\n                } else { /* !extDict */\n                    BYTE const* const pMatch = base + cur->offset;\n                    curForwardMatchLength = ZSTD_count(split, pMatch, iend);\n                    if (curForwardMatchLength < minMatchLength) {\n                        continue;\n                    }\n                    curBackwardMatchLength =\n                        ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr);\n                }\n                curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength;\n\n                if (curTotalMatchLength > bestMatchLength) {\n                    bestMatchLength = curTotalMatchLength;\n                    forwardMatchLength = curForwardMatchLength;\n                    backwardMatchLength = curBackwardMatchLength;\n                    bestEntry = cur;\n                }\n            }\n\n            /* No match found -- insert an entry into the hash table\n             * and process the next candidate match */\n            if (bestEntry == NULL) {\n                ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);\n                continue;\n            }\n\n            /* Match found */\n            offset = (U32)(split - base) - bestEntry->offset;\n            mLength = forwardMatchLength + backwardMatchLength;\n            {\n                rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size;\n\n                /* Out of sequence storage */\n                if (rawSeqStore->size == rawSeqStore->capacity)\n                    return ERROR(dstSize_tooSmall);\n                seq->litLength = (U32)(split - backwardMatchLength - anchor);\n                seq->matchLength = (U32)mLength;\n                seq->offset = offset;\n                rawSeqStore->size++;\n            }\n\n            /* Insert the current entry into the hash table --- it must be\n             * done after the previous block to avoid clobbering bestEntry */\n            ZSTD_ldm_insertEntry(ldmState, hash, newEntry, params->bucketSizeLog);\n\n            anchor = split + forwardMatchLength;\n\n            /* If we find a match that ends after the data that we've hashed\n             * then we have a repeating, overlapping, pattern. E.g. all zeros.\n             * If one repetition of the pattern matches our `stopMask` then all\n             * repetitions will. We don't need to insert them all into out table,\n             * only the first one. So skip over overlapping matches.\n             * This is a major speed boost (20x) for compressing a single byte\n             * repeated, when that byte ends up in the table.\n             */\n            if (anchor > ip + hashed) {\n                ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength);\n                /* Continue the outer loop at anchor (ip + hashed == anchor). */\n                ip = anchor - hashed;\n                break;\n            }\n        }\n\n        ip += hashed;\n    }\n\n    return iend - anchor;\n}\n\n/*! ZSTD_ldm_reduceTable() :\n *  reduce table indexes by `reducerValue` */\nstatic void ZSTD_ldm_reduceTable(ldmEntry_t* const table, U32 const size,\n                                 U32 const reducerValue)\n{\n    U32 u;\n    for (u = 0; u < size; u++) {\n        if (table[u].offset < reducerValue) table[u].offset = 0;\n        else table[u].offset -= reducerValue;\n    }\n}\n\nsize_t ZSTD_ldm_generateSequences(\n        ldmState_t* ldmState, RawSeqStore_t* sequences,\n        ldmParams_t const* params, void const* src, size_t srcSize)\n{\n    U32 const maxDist = 1U << params->windowLog;\n    BYTE const* const istart = (BYTE const*)src;\n    BYTE const* const iend = istart + srcSize;\n    size_t const kMaxChunkSize = 1 << 20;\n    size_t const nbChunks = (srcSize / kMaxChunkSize) + ((srcSize % kMaxChunkSize) != 0);\n    size_t chunk;\n    size_t leftoverSize = 0;\n\n    assert(ZSTD_CHUNKSIZE_MAX >= kMaxChunkSize);\n    /* Check that ZSTD_window_update() has been called for this chunk prior\n     * to passing it to this function.\n     */\n    assert(ldmState->window.nextSrc >= (BYTE const*)src + srcSize);\n    /* The input could be very large (in zstdmt), so it must be broken up into\n     * chunks to enforce the maximum distance and handle overflow correction.\n     */\n    assert(sequences->pos <= sequences->size);\n    assert(sequences->size <= sequences->capacity);\n    for (chunk = 0; chunk < nbChunks && sequences->size < sequences->capacity; ++chunk) {\n        BYTE const* const chunkStart = istart + chunk * kMaxChunkSize;\n        size_t const remaining = (size_t)(iend - chunkStart);\n        BYTE const *const chunkEnd =\n            (remaining < kMaxChunkSize) ? iend : chunkStart + kMaxChunkSize;\n        size_t const chunkSize = chunkEnd - chunkStart;\n        size_t newLeftoverSize;\n        size_t const prevSize = sequences->size;\n\n        assert(chunkStart < iend);\n        /* 1. Perform overflow correction if necessary. */\n        if (ZSTD_window_needOverflowCorrection(ldmState->window, 0, maxDist, ldmState->loadedDictEnd, chunkStart, chunkEnd)) {\n            U32 const ldmHSize = 1U << params->hashLog;\n            U32 const correction = ZSTD_window_correctOverflow(\n                &ldmState->window, /* cycleLog */ 0, maxDist, chunkStart);\n            ZSTD_ldm_reduceTable(ldmState->hashTable, ldmHSize, correction);\n            /* invalidate dictionaries on overflow correction */\n            ldmState->loadedDictEnd = 0;\n        }\n        /* 2. We enforce the maximum offset allowed.\n         *\n         * kMaxChunkSize should be small enough that we don't lose too much of\n         * the window through early invalidation.\n         * TODO: * Test the chunk size.\n         *       * Try invalidation after the sequence generation and test the\n         *         offset against maxDist directly.\n         *\n         * NOTE: Because of dictionaries + sequence splitting we MUST make sure\n         * that any offset used is valid at the END of the sequence, since it may\n         * be split into two sequences. This condition holds when using\n         * ZSTD_window_enforceMaxDist(), but if we move to checking offsets\n         * against maxDist directly, we'll have to carefully handle that case.\n         */\n        ZSTD_window_enforceMaxDist(&ldmState->window, chunkEnd, maxDist, &ldmState->loadedDictEnd, NULL);\n        /* 3. Generate the sequences for the chunk, and get newLeftoverSize. */\n        newLeftoverSize = ZSTD_ldm_generateSequences_internal(\n            ldmState, sequences, params, chunkStart, chunkSize);\n        if (ZSTD_isError(newLeftoverSize))\n            return newLeftoverSize;\n        /* 4. We add the leftover literals from previous iterations to the first\n         *    newly generated sequence, or add the `newLeftoverSize` if none are\n         *    generated.\n         */\n        /* Prepend the leftover literals from the last call */\n        if (prevSize < sequences->size) {\n            sequences->seq[prevSize].litLength += (U32)leftoverSize;\n            leftoverSize = newLeftoverSize;\n        } else {\n            assert(newLeftoverSize == chunkSize);\n            leftoverSize += chunkSize;\n        }\n    }\n    return 0;\n}\n\nvoid\nZSTD_ldm_skipSequences(RawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch)\n{\n    while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {\n        rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;\n        if (srcSize <= seq->litLength) {\n            /* Skip past srcSize literals */\n            seq->litLength -= (U32)srcSize;\n            return;\n        }\n        srcSize -= seq->litLength;\n        seq->litLength = 0;\n        if (srcSize < seq->matchLength) {\n            /* Skip past the first srcSize of the match */\n            seq->matchLength -= (U32)srcSize;\n            if (seq->matchLength < minMatch) {\n                /* The match is too short, omit it */\n                if (rawSeqStore->pos + 1 < rawSeqStore->size) {\n                    seq[1].litLength += seq[0].matchLength;\n                }\n                rawSeqStore->pos++;\n            }\n            return;\n        }\n        srcSize -= seq->matchLength;\n        seq->matchLength = 0;\n        rawSeqStore->pos++;\n    }\n}\n\n/**\n * If the sequence length is longer than remaining then the sequence is split\n * between this block and the next.\n *\n * Returns the current sequence to handle, or if the rest of the block should\n * be literals, it returns a sequence with offset == 0.\n */\nstatic rawSeq maybeSplitSequence(RawSeqStore_t* rawSeqStore,\n                                 U32 const remaining, U32 const minMatch)\n{\n    rawSeq sequence = rawSeqStore->seq[rawSeqStore->pos];\n    assert(sequence.offset > 0);\n    /* Likely: No partial sequence */\n    if (remaining >= sequence.litLength + sequence.matchLength) {\n        rawSeqStore->pos++;\n        return sequence;\n    }\n    /* Cut the sequence short (offset == 0 ==> rest is literals). */\n    if (remaining <= sequence.litLength) {\n        sequence.offset = 0;\n    } else if (remaining < sequence.litLength + sequence.matchLength) {\n        sequence.matchLength = remaining - sequence.litLength;\n        if (sequence.matchLength < minMatch) {\n            sequence.offset = 0;\n        }\n    }\n    /* Skip past `remaining` bytes for the future sequences. */\n    ZSTD_ldm_skipSequences(rawSeqStore, remaining, minMatch);\n    return sequence;\n}\n\nvoid ZSTD_ldm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes) {\n    U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);\n    while (currPos && rawSeqStore->pos < rawSeqStore->size) {\n        rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];\n        if (currPos >= currSeq.litLength + currSeq.matchLength) {\n            currPos -= currSeq.litLength + currSeq.matchLength;\n            rawSeqStore->pos++;\n        } else {\n            rawSeqStore->posInSequence = currPos;\n            break;\n        }\n    }\n    if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {\n        rawSeqStore->posInSequence = 0;\n    }\n}\n\nsize_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore,\n    ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n    ZSTD_ParamSwitch_e useRowMatchFinder,\n    void const* src, size_t srcSize)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    unsigned const minMatch = cParams->minMatch;\n    ZSTD_BlockCompressor_f const blockCompressor =\n        ZSTD_selectBlockCompressor(cParams->strategy, useRowMatchFinder, ZSTD_matchState_dictMode(ms));\n    /* Input bounds */\n    BYTE const* const istart = (BYTE const*)src;\n    BYTE const* const iend = istart + srcSize;\n    /* Input positions */\n    BYTE const* ip = istart;\n\n    DEBUGLOG(5, \"ZSTD_ldm_blockCompress: srcSize=%zu\", srcSize);\n    /* If using opt parser, use LDMs only as candidates rather than always accepting them */\n    if (cParams->strategy >= ZSTD_btopt) {\n        size_t lastLLSize;\n        ms->ldmSeqStore = rawSeqStore;\n        lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize);\n        ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize);\n        return lastLLSize;\n    }\n\n    assert(rawSeqStore->pos <= rawSeqStore->size);\n    assert(rawSeqStore->size <= rawSeqStore->capacity);\n    /* Loop through each sequence and apply the block compressor to the literals */\n    while (rawSeqStore->pos < rawSeqStore->size && ip < iend) {\n        /* maybeSplitSequence updates rawSeqStore->pos */\n        rawSeq const sequence = maybeSplitSequence(rawSeqStore,\n                                                   (U32)(iend - ip), minMatch);\n        /* End signal */\n        if (sequence.offset == 0)\n            break;\n\n        assert(ip + sequence.litLength + sequence.matchLength <= iend);\n\n        /* Fill tables for block compressor */\n        ZSTD_ldm_limitTableUpdate(ms, ip);\n        ZSTD_ldm_fillFastTables(ms, ip);\n        /* Run the block compressor */\n        DEBUGLOG(5, \"pos %u : calling block compressor on segment of size %u\", (unsigned)(ip-istart), sequence.litLength);\n        {\n            int i;\n            size_t const newLitLength =\n                blockCompressor(ms, seqStore, rep, ip, sequence.litLength);\n            ip += sequence.litLength;\n            /* Update the repcodes */\n            for (i = ZSTD_REP_NUM - 1; i > 0; i--)\n                rep[i] = rep[i-1];\n            rep[0] = sequence.offset;\n            /* Store the sequence */\n            ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength, iend,\n                          OFFSET_TO_OFFBASE(sequence.offset),\n                          sequence.matchLength);\n            ip += sequence.matchLength;\n        }\n    }\n    /* Fill the tables for the block compressor */\n    ZSTD_ldm_limitTableUpdate(ms, ip);\n    ZSTD_ldm_fillFastTables(ms, ip);\n    /* Compress the last literals */\n    return blockCompressor(ms, seqStore, rep, ip, iend - ip);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_ldm.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LDM_H\n#define ZSTD_LDM_H\n\n#include \"zstd_compress_internal.h\"   /* ldmParams_t, U32 */\n#include \"../zstd.h\"   /* ZSTD_CCtx, size_t */\n\n/*-*************************************\n*  Long distance matching\n***************************************/\n\n#define ZSTD_LDM_DEFAULT_WINDOW_LOG ZSTD_WINDOWLOG_LIMIT_DEFAULT\n\nvoid ZSTD_ldm_fillHashTable(\n            ldmState_t* state, const BYTE* ip,\n            const BYTE* iend, ldmParams_t const* params);\n\n/**\n * ZSTD_ldm_generateSequences():\n *\n * Generates the sequences using the long distance match finder.\n * Generates long range matching sequences in `sequences`, which parse a prefix\n * of the source. `sequences` must be large enough to store every sequence,\n * which can be checked with `ZSTD_ldm_getMaxNbSeq()`.\n * @returns 0 or an error code.\n *\n * NOTE: The user must have called ZSTD_window_update() for all of the input\n * they have, even if they pass it to ZSTD_ldm_generateSequences() in chunks.\n * NOTE: This function returns an error if it runs out of space to store\n *       sequences.\n */\nsize_t ZSTD_ldm_generateSequences(\n            ldmState_t* ldms, RawSeqStore_t* sequences,\n            ldmParams_t const* params, void const* src, size_t srcSize);\n\n/**\n * ZSTD_ldm_blockCompress():\n *\n * Compresses a block using the predefined sequences, along with a secondary\n * block compressor. The literals section of every sequence is passed to the\n * secondary block compressor, and those sequences are interspersed with the\n * predefined sequences. Returns the length of the last literals.\n * Updates `rawSeqStore.pos` to indicate how many sequences have been consumed.\n * `rawSeqStore.seq` may also be updated to split the last sequence between two\n * blocks.\n * @return The length of the last literals.\n *\n * NOTE: The source must be at most the maximum block size, but the predefined\n * sequences can be any size, and may be longer than the block. In the case that\n * they are longer than the block, the last sequences may need to be split into\n * two. We handle that case correctly, and update `rawSeqStore` appropriately.\n * NOTE: This function does not return any errors.\n */\nsize_t ZSTD_ldm_blockCompress(RawSeqStore_t* rawSeqStore,\n            ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n            ZSTD_ParamSwitch_e useRowMatchFinder,\n            void const* src, size_t srcSize);\n\n/**\n * ZSTD_ldm_skipSequences():\n *\n * Skip past `srcSize` bytes worth of sequences in `rawSeqStore`.\n * Avoids emitting matches less than `minMatch` bytes.\n * Must be called for data that is not passed to ZSTD_ldm_blockCompress().\n */\nvoid ZSTD_ldm_skipSequences(RawSeqStore_t* rawSeqStore, size_t srcSize,\n    U32 const minMatch);\n\n/* ZSTD_ldm_skipRawSeqStoreBytes():\n * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'.\n * Not to be used in conjunction with ZSTD_ldm_skipSequences().\n * Must be called for data with is not passed to ZSTD_ldm_blockCompress().\n */\nvoid ZSTD_ldm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes);\n\n/** ZSTD_ldm_getTableSize() :\n *  Estimate the space needed for long distance matching tables or 0 if LDM is\n *  disabled.\n */\nsize_t ZSTD_ldm_getTableSize(ldmParams_t params);\n\n/** ZSTD_ldm_getSeqSpace() :\n *  Return an upper bound on the number of sequences that can be produced by\n *  the long distance matcher, or 0 if LDM is disabled.\n */\nsize_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize);\n\n/** ZSTD_ldm_adjustParameters() :\n *  If the params->hashRateLog is not set, set it to its default value based on\n *  windowLog and params->hashLog.\n *\n *  Ensures that params->bucketSizeLog is <= params->hashLog (setting it to\n *  params->hashLog if it is not).\n *\n *  Ensures that the minMatchLength >= targetLength during optimal parsing.\n */\nvoid ZSTD_ldm_adjustParameters(ldmParams_t* params,\n                               ZSTD_compressionParameters const* cParams);\n\n#endif /* ZSTD_FAST_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_ldm_geartab.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LDM_GEARTAB_H\n#define ZSTD_LDM_GEARTAB_H\n\n#include \"../common/compiler.h\" /* UNUSED_ATTR */\n#include \"../common/mem.h\"      /* U64 */\n\nstatic UNUSED_ATTR const U64 ZSTD_ldm_gearTab[256] = {\n    0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc,\n    0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05,\n    0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e,\n    0x9c8528f65badeaca, 0x86563706e2097529, 0x2902475fa375d889,\n    0xafb32a9739a5ebe6, 0xce2714da3883e639, 0x21eaf821722e69e,\n    0x37b628620b628,    0x49a8d455d88caf5,  0x8556d711e6958140,\n    0x4f7ae74fc605c1f,  0x829f0c3468bd3a20, 0x4ffdc885c625179e,\n    0x8473de048a3daf1b, 0x51008822b05646b2, 0x69d75d12b2d1cc5f,\n    0x8c9d4a19159154bc, 0xc3cc10f4abbd4003, 0xd06ddc1cecb97391,\n    0xbe48e6e7ed80302e, 0x3481db31cee03547, 0xacc3f67cdaa1d210,\n    0x65cb771d8c7f96cc, 0x8eb27177055723dd, 0xc789950d44cd94be,\n    0x934feadc3700b12b, 0x5e485f11edbdf182, 0x1e2e2a46fd64767a,\n    0x2969ca71d82efa7c, 0x9d46e9935ebbba2e, 0xe056b67e05e6822b,\n    0x94d73f55739d03a0, 0xcd7010bdb69b5a03, 0x455ef9fcd79b82f4,\n    0x869cb54a8749c161, 0x38d1a4fa6185d225, 0xb475166f94bbe9bb,\n    0xa4143548720959f1, 0x7aed4780ba6b26ba, 0xd0ce264439e02312,\n    0x84366d746078d508, 0xa8ce973c72ed17be, 0x21c323a29a430b01,\n    0x9962d617e3af80ee, 0xab0ce91d9c8cf75b, 0x530e8ee6d19a4dbc,\n    0x2ef68c0cf53f5d72, 0xc03a681640a85506, 0x496e4e9f9c310967,\n    0x78580472b59b14a0, 0x273824c23b388577, 0x66bf923ad45cb553,\n    0x47ae1a5a2492ba86, 0x35e304569e229659, 0x4765182a46870b6f,\n    0x6cbab625e9099412, 0xddac9a2e598522c1, 0x7172086e666624f2,\n    0xdf5003ca503b7837, 0x88c0c1db78563d09, 0x58d51865acfc289d,\n    0x177671aec65224f1, 0xfb79d8a241e967d7, 0x2be1e101cad9a49a,\n    0x6625682f6e29186b, 0x399553457ac06e50, 0x35dffb4c23abb74,\n    0x429db2591f54aade, 0xc52802a8037d1009, 0x6acb27381f0b25f3,\n    0xf45e2551ee4f823b, 0x8b0ea2d99580c2f7, 0x3bed519cbcb4e1e1,\n    0xff452823dbb010a,  0x9d42ed614f3dd267, 0x5b9313c06257c57b,\n    0xa114b8008b5e1442, 0xc1fe311c11c13d4b, 0x66e8763ea34c5568,\n    0x8b982af1c262f05d, 0xee8876faaa75fbb7, 0x8a62a4d0d172bb2a,\n    0xc13d94a3b7449a97, 0x6dbbba9dc15d037c, 0xc786101f1d92e0f1,\n    0xd78681a907a0b79b, 0xf61aaf2962c9abb9, 0x2cfd16fcd3cb7ad9,\n    0x868c5b6744624d21, 0x25e650899c74ddd7, 0xba042af4a7c37463,\n    0x4eb1a539465a3eca, 0xbe09dbf03b05d5ca, 0x774e5a362b5472ba,\n    0x47a1221229d183cd, 0x504b0ca18ef5a2df, 0xdffbdfbde2456eb9,\n    0x46cd2b2fbee34634, 0xf2aef8fe819d98c3, 0x357f5276d4599d61,\n    0x24a5483879c453e3, 0x88026889192b4b9,  0x28da96671782dbec,\n    0x4ef37c40588e9aaa, 0x8837b90651bc9fb3, 0xc164f741d3f0e5d6,\n    0xbc135a0a704b70ba, 0x69cd868f7622ada,  0xbc37ba89e0b9c0ab,\n    0x47c14a01323552f6, 0x4f00794bacee98bb, 0x7107de7d637a69d5,\n    0x88af793bb6f2255e, 0xf3c6466b8799b598, 0xc288c616aa7f3b59,\n    0x81ca63cf42fca3fd, 0x88d85ace36a2674b, 0xd056bd3792389e7,\n    0xe55c396c4e9dd32d, 0xbefb504571e6c0a6, 0x96ab32115e91e8cc,\n    0xbf8acb18de8f38d1, 0x66dae58801672606, 0x833b6017872317fb,\n    0xb87c16f2d1c92864, 0xdb766a74e58b669c, 0x89659f85c61417be,\n    0xc8daad856011ea0c, 0x76a4b565b6fe7eae, 0xa469d085f6237312,\n    0xaaf0365683a3e96c, 0x4dbb746f8424f7b8, 0x638755af4e4acc1,\n    0x3d7807f5bde64486, 0x17be6d8f5bbb7639, 0x903f0cd44dc35dc,\n    0x67b672eafdf1196c, 0xa676ff93ed4c82f1, 0x521d1004c5053d9d,\n    0x37ba9ad09ccc9202, 0x84e54d297aacfb51, 0xa0b4b776a143445,\n    0x820d471e20b348e,  0x1874383cb83d46dc, 0x97edeec7a1efe11c,\n    0xb330e50b1bdc42aa, 0x1dd91955ce70e032, 0xa514cdb88f2939d5,\n    0x2791233fd90db9d3, 0x7b670a4cc50f7a9b, 0x77c07d2a05c6dfa5,\n    0xe3778b6646d0a6fa, 0xb39c8eda47b56749, 0x933ed448addbef28,\n    0xaf846af6ab7d0bf4, 0xe5af208eb666e49,  0x5e6622f73534cd6a,\n    0x297daeca42ef5b6e, 0x862daef3d35539a6, 0xe68722498f8e1ea9,\n    0x981c53093dc0d572, 0xfa09b0bfbf86fbf5, 0x30b1e96166219f15,\n    0x70e7d466bdc4fb83, 0x5a66736e35f2a8e9, 0xcddb59d2b7c1baef,\n    0xd6c7d247d26d8996, 0xea4e39eac8de1ba3, 0x539c8bb19fa3aff2,\n    0x9f90e4c5fd508d8,  0xa34e5956fbaf3385, 0x2e2f8e151d3ef375,\n    0x173691e9b83faec1, 0xb85a8d56bf016379, 0x8382381267408ae3,\n    0xb90f901bbdc0096d, 0x7c6ad32933bcec65, 0x76bb5e2f2c8ad595,\n    0x390f851a6cf46d28, 0xc3e6064da1c2da72, 0xc52a0c101cfa5389,\n    0xd78eaf84a3fbc530, 0x3781b9e2288b997e, 0x73c2f6dea83d05c4,\n    0x4228e364c5b5ed7,  0x9d7a3edf0da43911, 0x8edcfeda24686756,\n    0x5e7667a7b7a9b3a1, 0x4c4f389fa143791d, 0xb08bc1023da7cddc,\n    0x7ab4be3ae529b1cc, 0x754e6132dbe74ff9, 0x71635442a839df45,\n    0x2f6fb1643fbe52de, 0x961e0a42cf7a8177, 0xf3b45d83d89ef2ea,\n    0xee3de4cf4a6e3e9b, 0xcd6848542c3295e7, 0xe4cee1664c78662f,\n    0x9947548b474c68c4, 0x25d73777a5ed8b0b, 0xc915b1d636b7fc,\n    0x21c2ba75d9b0d2da, 0x5f6b5dcf608a64a1, 0xdcf333255ff9570c,\n    0x633b922418ced4ee, 0xc136dde0b004b34a, 0x58cc83b05d4b2f5a,\n    0x5eb424dda28e42d2, 0x62df47369739cd98, 0xb4e0b42485e4ce17,\n    0x16e1f0c1f9a8d1e7, 0x8ec3916707560ebf, 0x62ba6e2df2cc9db3,\n    0xcbf9f4ff77d83a16, 0x78d9d7d07d2bbcc4, 0xef554ce1e02c41f4,\n    0x8d7581127eccf94d, 0xa9b53336cb3c8a05, 0x38c42c0bf45c4f91,\n    0x640893cdf4488863, 0x80ec34bc575ea568, 0x39f324f5b48eaa40,\n    0xe9d9ed1f8eff527f, 0x9224fc058cc5a214, 0xbaba00b04cfe7741,\n    0x309a9f120fcf52af, 0xa558f3ec65626212, 0x424bec8b7adabe2f,\n    0x41622513a6aea433, 0xb88da2d5324ca798, 0xd287733b245528a4,\n    0x9a44697e6d68aec3, 0x7b1093be2f49bb28, 0x50bbec632e3d8aad,\n    0x6cd90723e1ea8283, 0x897b9e7431b02bf3, 0x219efdcb338a7047,\n    0x3b0311f0a27c0656, 0xdb17bf91c0db96e7, 0x8cd4fd6b4e85a5b2,\n    0xfab071054ba6409d, 0x40d6fe831fa9dfd9, 0xaf358debad7d791e,\n    0xeb8d0e25a65e3e58, 0xbbcbd3df14e08580, 0xcf751f27ecdab2b,\n    0x2b4da14f2613d8f4\n};\n\n#endif /* ZSTD_LDM_GEARTAB_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_opt.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"zstd_compress_internal.h\"\n#include \"hist.h\"\n#include \"zstd_opt.h\"\n\n#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n\n#define ZSTD_LITFREQ_ADD    2   /* scaling factor for litFreq, so that frequencies adapt faster to new stats */\n#define ZSTD_MAX_PRICE     (1<<30)\n\n#define ZSTD_PREDEF_THRESHOLD 8   /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */\n\n\n/*-*************************************\n*  Price functions for optimal parser\n***************************************/\n\n#if 0    /* approximation at bit level (for tests) */\n#  define BITCOST_ACCURACY 0\n#  define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)\n#  define WEIGHT(stat, opt) ((void)(opt), ZSTD_bitWeight(stat))\n#elif 0  /* fractional bit accuracy (for tests) */\n#  define BITCOST_ACCURACY 8\n#  define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)\n#  define WEIGHT(stat,opt) ((void)(opt), ZSTD_fracWeight(stat))\n#else    /* opt==approx, ultra==accurate */\n#  define BITCOST_ACCURACY 8\n#  define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)\n#  define WEIGHT(stat,opt) ((opt) ? ZSTD_fracWeight(stat) : ZSTD_bitWeight(stat))\n#endif\n\n/* ZSTD_bitWeight() :\n * provide estimated \"cost\" of a stat in full bits only */\nMEM_STATIC U32 ZSTD_bitWeight(U32 stat)\n{\n    return (ZSTD_highbit32(stat+1) * BITCOST_MULTIPLIER);\n}\n\n/* ZSTD_fracWeight() :\n * provide fractional-bit \"cost\" of a stat,\n * using linear interpolation approximation */\nMEM_STATIC U32 ZSTD_fracWeight(U32 rawStat)\n{\n    U32 const stat = rawStat + 1;\n    U32 const hb = ZSTD_highbit32(stat);\n    U32 const BWeight = hb * BITCOST_MULTIPLIER;\n    /* Fweight was meant for \"Fractional weight\"\n     * but it's effectively a value between 1 and 2\n     * using fixed point arithmetic */\n    U32 const FWeight = (stat << BITCOST_ACCURACY) >> hb;\n    U32 const weight = BWeight + FWeight;\n    assert(hb + BITCOST_ACCURACY < 31);\n    return weight;\n}\n\n#if (DEBUGLEVEL>=2)\n/* debugging function,\n * @return price in bytes as fractional value\n * for debug messages only */\nMEM_STATIC double ZSTD_fCost(int price)\n{\n    return (double)price / (BITCOST_MULTIPLIER*8);\n}\n#endif\n\nstatic int ZSTD_compressedLiterals(optState_t const* const optPtr)\n{\n    return optPtr->literalCompressionMode != ZSTD_ps_disable;\n}\n\nstatic void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)\n{\n    if (ZSTD_compressedLiterals(optPtr))\n        optPtr->litSumBasePrice = WEIGHT(optPtr->litSum, optLevel);\n    optPtr->litLengthSumBasePrice = WEIGHT(optPtr->litLengthSum, optLevel);\n    optPtr->matchLengthSumBasePrice = WEIGHT(optPtr->matchLengthSum, optLevel);\n    optPtr->offCodeSumBasePrice = WEIGHT(optPtr->offCodeSum, optLevel);\n}\n\n\nstatic U32 sum_u32(const unsigned table[], size_t nbElts)\n{\n    size_t n;\n    U32 total = 0;\n    for (n=0; n<nbElts; n++) {\n        total += table[n];\n    }\n    return total;\n}\n\ntypedef enum { base_0possible=0, base_1guaranteed=1 } base_directive_e;\n\nstatic U32\nZSTD_downscaleStats(unsigned* table, U32 lastEltIndex, U32 shift, base_directive_e base1)\n{\n    U32 s, sum=0;\n    DEBUGLOG(5, \"ZSTD_downscaleStats (nbElts=%u, shift=%u)\",\n            (unsigned)lastEltIndex+1, (unsigned)shift );\n    assert(shift < 30);\n    for (s=0; s<lastEltIndex+1; s++) {\n        unsigned const base = base1 ? 1 : (table[s]>0);\n        unsigned const newStat = base + (table[s] >> shift);\n        sum += newStat;\n        table[s] = newStat;\n    }\n    return sum;\n}\n\n/* ZSTD_scaleStats() :\n * reduce all elt frequencies in table if sum too large\n * return the resulting sum of elements */\nstatic U32 ZSTD_scaleStats(unsigned* table, U32 lastEltIndex, U32 logTarget)\n{\n    U32 const prevsum = sum_u32(table, lastEltIndex+1);\n    U32 const factor = prevsum >> logTarget;\n    DEBUGLOG(5, \"ZSTD_scaleStats (nbElts=%u, target=%u)\", (unsigned)lastEltIndex+1, (unsigned)logTarget);\n    assert(logTarget < 30);\n    if (factor <= 1) return prevsum;\n    return ZSTD_downscaleStats(table, lastEltIndex, ZSTD_highbit32(factor), base_1guaranteed);\n}\n\n/* ZSTD_rescaleFreqs() :\n * if first block (detected by optPtr->litLengthSum == 0) : init statistics\n *    take hints from dictionary if there is one\n *    and init from zero if there is none,\n *    using src for literals stats, and baseline stats for sequence symbols\n * otherwise downscale existing stats, to be used as seed for next block.\n */\nstatic void\nZSTD_rescaleFreqs(optState_t* const optPtr,\n            const BYTE* const src, size_t const srcSize,\n                  int const optLevel)\n{\n    int const compressedLiterals = ZSTD_compressedLiterals(optPtr);\n    DEBUGLOG(5, \"ZSTD_rescaleFreqs (srcSize=%u)\", (unsigned)srcSize);\n    optPtr->priceType = zop_dynamic;\n\n    if (optPtr->litLengthSum == 0) {  /* no literals stats collected -> first block assumed -> init */\n\n        /* heuristic: use pre-defined stats for too small inputs */\n        if (srcSize <= ZSTD_PREDEF_THRESHOLD) {\n            DEBUGLOG(5, \"srcSize <= %i : use predefined stats\", ZSTD_PREDEF_THRESHOLD);\n            optPtr->priceType = zop_predef;\n        }\n\n        assert(optPtr->symbolCosts != NULL);\n        if (optPtr->symbolCosts->huf.repeatMode == HUF_repeat_valid) {\n\n            /* huffman stats covering the full value set : table presumed generated by dictionary */\n            optPtr->priceType = zop_dynamic;\n\n            if (compressedLiterals) {\n                /* generate literals statistics from huffman table */\n                unsigned lit;\n                assert(optPtr->litFreq != NULL);\n                optPtr->litSum = 0;\n                for (lit=0; lit<=MaxLit; lit++) {\n                    U32 const scaleLog = 11;   /* scale to 2K */\n                    U32 const bitCost = HUF_getNbBitsFromCTable(optPtr->symbolCosts->huf.CTable, lit);\n                    assert(bitCost <= scaleLog);\n                    optPtr->litFreq[lit] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->litSum += optPtr->litFreq[lit];\n            }   }\n\n            {   unsigned ll;\n                FSE_CState_t llstate;\n                FSE_initCState(&llstate, optPtr->symbolCosts->fse.litlengthCTable);\n                optPtr->litLengthSum = 0;\n                for (ll=0; ll<=MaxLL; ll++) {\n                    U32 const scaleLog = 10;   /* scale to 1K */\n                    U32 const bitCost = FSE_getMaxNbBits(llstate.symbolTT, ll);\n                    assert(bitCost < scaleLog);\n                    optPtr->litLengthFreq[ll] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->litLengthSum += optPtr->litLengthFreq[ll];\n            }   }\n\n            {   unsigned ml;\n                FSE_CState_t mlstate;\n                FSE_initCState(&mlstate, optPtr->symbolCosts->fse.matchlengthCTable);\n                optPtr->matchLengthSum = 0;\n                for (ml=0; ml<=MaxML; ml++) {\n                    U32 const scaleLog = 10;\n                    U32 const bitCost = FSE_getMaxNbBits(mlstate.symbolTT, ml);\n                    assert(bitCost < scaleLog);\n                    optPtr->matchLengthFreq[ml] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->matchLengthSum += optPtr->matchLengthFreq[ml];\n            }   }\n\n            {   unsigned of;\n                FSE_CState_t ofstate;\n                FSE_initCState(&ofstate, optPtr->symbolCosts->fse.offcodeCTable);\n                optPtr->offCodeSum = 0;\n                for (of=0; of<=MaxOff; of++) {\n                    U32 const scaleLog = 10;\n                    U32 const bitCost = FSE_getMaxNbBits(ofstate.symbolTT, of);\n                    assert(bitCost < scaleLog);\n                    optPtr->offCodeFreq[of] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;\n                    optPtr->offCodeSum += optPtr->offCodeFreq[of];\n            }   }\n\n        } else {  /* first block, no dictionary */\n\n            assert(optPtr->litFreq != NULL);\n            if (compressedLiterals) {\n                /* base initial cost of literals on direct frequency within src */\n                unsigned lit = MaxLit;\n                HIST_count_simple(optPtr->litFreq, &lit, src, srcSize);   /* use raw first block to init statistics */\n                optPtr->litSum = ZSTD_downscaleStats(optPtr->litFreq, MaxLit, 8, base_0possible);\n            }\n\n            {   unsigned const baseLLfreqs[MaxLL+1] = {\n                    4, 2, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1\n                };\n                ZSTD_memcpy(optPtr->litLengthFreq, baseLLfreqs, sizeof(baseLLfreqs));\n                optPtr->litLengthSum = sum_u32(baseLLfreqs, MaxLL+1);\n            }\n\n            {   unsigned ml;\n                for (ml=0; ml<=MaxML; ml++)\n                    optPtr->matchLengthFreq[ml] = 1;\n            }\n            optPtr->matchLengthSum = MaxML+1;\n\n            {   unsigned const baseOFCfreqs[MaxOff+1] = {\n                    6, 2, 1, 1, 2, 3, 4, 4,\n                    4, 3, 2, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1,\n                    1, 1, 1, 1, 1, 1, 1, 1\n                };\n                ZSTD_memcpy(optPtr->offCodeFreq, baseOFCfreqs, sizeof(baseOFCfreqs));\n                optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1);\n            }\n\n        }\n\n    } else {   /* new block : scale down accumulated statistics */\n\n        if (compressedLiterals)\n            optPtr->litSum = ZSTD_scaleStats(optPtr->litFreq, MaxLit, 12);\n        optPtr->litLengthSum = ZSTD_scaleStats(optPtr->litLengthFreq, MaxLL, 11);\n        optPtr->matchLengthSum = ZSTD_scaleStats(optPtr->matchLengthFreq, MaxML, 11);\n        optPtr->offCodeSum = ZSTD_scaleStats(optPtr->offCodeFreq, MaxOff, 11);\n    }\n\n    ZSTD_setBasePrices(optPtr, optLevel);\n}\n\n/* ZSTD_rawLiteralsCost() :\n * price of literals (only) in specified segment (which length can be 0).\n * does not include price of literalLength symbol */\nstatic U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,\n                                const optState_t* const optPtr,\n                                int optLevel)\n{\n    DEBUGLOG(8, \"ZSTD_rawLiteralsCost (%u literals)\", litLength);\n    if (litLength == 0) return 0;\n\n    if (!ZSTD_compressedLiterals(optPtr))\n        return (litLength << 3) * BITCOST_MULTIPLIER;  /* Uncompressed - 8 bytes per literal. */\n\n    if (optPtr->priceType == zop_predef)\n        return (litLength*6) * BITCOST_MULTIPLIER;  /* 6 bit per literal - no statistic used */\n\n    /* dynamic statistics */\n    {   U32 price = optPtr->litSumBasePrice * litLength;\n        U32 const litPriceMax = optPtr->litSumBasePrice - BITCOST_MULTIPLIER;\n        U32 u;\n        assert(optPtr->litSumBasePrice >= BITCOST_MULTIPLIER);\n        for (u=0; u < litLength; u++) {\n            U32 litPrice = WEIGHT(optPtr->litFreq[literals[u]], optLevel);\n            if (UNLIKELY(litPrice > litPriceMax)) litPrice = litPriceMax;\n            price -= litPrice;\n        }\n        return price;\n    }\n}\n\n/* ZSTD_litLengthPrice() :\n * cost of literalLength symbol */\nstatic U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr, int optLevel)\n{\n    assert(litLength <= ZSTD_BLOCKSIZE_MAX);\n    if (optPtr->priceType == zop_predef)\n        return WEIGHT(litLength, optLevel);\n\n    /* ZSTD_LLcode() can't compute litLength price for sizes >= ZSTD_BLOCKSIZE_MAX\n     * because it isn't representable in the zstd format.\n     * So instead just pretend it would cost 1 bit more than ZSTD_BLOCKSIZE_MAX - 1.\n     * In such a case, the block would be all literals.\n     */\n    if (litLength == ZSTD_BLOCKSIZE_MAX)\n        return BITCOST_MULTIPLIER + ZSTD_litLengthPrice(ZSTD_BLOCKSIZE_MAX - 1, optPtr, optLevel);\n\n    /* dynamic statistics */\n    {   U32 const llCode = ZSTD_LLcode(litLength);\n        return (LL_bits[llCode] * BITCOST_MULTIPLIER)\n             + optPtr->litLengthSumBasePrice\n             - WEIGHT(optPtr->litLengthFreq[llCode], optLevel);\n    }\n}\n\n/* ZSTD_getMatchPrice() :\n * Provides the cost of the match part (offset + matchLength) of a sequence.\n * Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.\n * @offBase : sumtype, representing an offset or a repcode, and using numeric representation of ZSTD_storeSeq()\n * @optLevel: when <2, favors small offset for decompression speed (improved cache efficiency)\n */\nFORCE_INLINE_TEMPLATE U32\nZSTD_getMatchPrice(U32 const offBase,\n                   U32 const matchLength,\n             const optState_t* const optPtr,\n                   int const optLevel)\n{\n    U32 price;\n    U32 const offCode = ZSTD_highbit32(offBase);\n    U32 const mlBase = matchLength - MINMATCH;\n    assert(matchLength >= MINMATCH);\n\n    if (optPtr->priceType == zop_predef)  /* fixed scheme, does not use statistics */\n        return WEIGHT(mlBase, optLevel)\n             + ((16 + offCode) * BITCOST_MULTIPLIER); /* emulated offset cost */\n\n    /* dynamic statistics */\n    price = (offCode * BITCOST_MULTIPLIER) + (optPtr->offCodeSumBasePrice - WEIGHT(optPtr->offCodeFreq[offCode], optLevel));\n    if ((optLevel<2) /*static*/ && offCode >= 20)\n        price += (offCode-19)*2 * BITCOST_MULTIPLIER; /* handicap for long distance offsets, favor decompression speed */\n\n    /* match Length */\n    {   U32 const mlCode = ZSTD_MLcode(mlBase);\n        price += (ML_bits[mlCode] * BITCOST_MULTIPLIER) + (optPtr->matchLengthSumBasePrice - WEIGHT(optPtr->matchLengthFreq[mlCode], optLevel));\n    }\n\n    price += BITCOST_MULTIPLIER / 5;   /* heuristic : make matches a bit more costly to favor less sequences -> faster decompression speed */\n\n    DEBUGLOG(8, \"ZSTD_getMatchPrice(ml:%u) = %u\", matchLength, price);\n    return price;\n}\n\n/* ZSTD_updateStats() :\n * assumption : literals + litLength <= iend */\nstatic void ZSTD_updateStats(optState_t* const optPtr,\n                             U32 litLength, const BYTE* literals,\n                             U32 offBase, U32 matchLength)\n{\n    /* literals */\n    if (ZSTD_compressedLiterals(optPtr)) {\n        U32 u;\n        for (u=0; u < litLength; u++)\n            optPtr->litFreq[literals[u]] += ZSTD_LITFREQ_ADD;\n        optPtr->litSum += litLength*ZSTD_LITFREQ_ADD;\n    }\n\n    /* literal Length */\n    {   U32 const llCode = ZSTD_LLcode(litLength);\n        optPtr->litLengthFreq[llCode]++;\n        optPtr->litLengthSum++;\n    }\n\n    /* offset code : follows storeSeq() numeric representation */\n    {   U32 const offCode = ZSTD_highbit32(offBase);\n        assert(offCode <= MaxOff);\n        optPtr->offCodeFreq[offCode]++;\n        optPtr->offCodeSum++;\n    }\n\n    /* match Length */\n    {   U32 const mlBase = matchLength - MINMATCH;\n        U32 const mlCode = ZSTD_MLcode(mlBase);\n        optPtr->matchLengthFreq[mlCode]++;\n        optPtr->matchLengthSum++;\n    }\n}\n\n\n/* ZSTD_readMINMATCH() :\n * function safe only for comparisons\n * assumption : memPtr must be at least 4 bytes before end of buffer */\nMEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)\n{\n    switch (length)\n    {\n    default :\n    case 4 : return MEM_read32(memPtr);\n    case 3 : if (MEM_isLittleEndian())\n                return MEM_read32(memPtr)<<8;\n             else\n                return MEM_read32(memPtr)>>8;\n    }\n}\n\n\n/* Update hashTable3 up to ip (excluded)\n   Assumption : always within prefix (i.e. not within extDict) */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_MatchState_t* ms,\n                                       U32* nextToUpdate3,\n                                       const BYTE* const ip)\n{\n    U32* const hashTable3 = ms->hashTable3;\n    U32 const hashLog3 = ms->hashLog3;\n    const BYTE* const base = ms->window.base;\n    U32 idx = *nextToUpdate3;\n    U32 const target = (U32)(ip - base);\n    size_t const hash3 = ZSTD_hash3Ptr(ip, hashLog3);\n    assert(hashLog3 > 0);\n\n    while(idx < target) {\n        hashTable3[ZSTD_hash3Ptr(base+idx, hashLog3)] = idx;\n        idx++;\n    }\n\n    *nextToUpdate3 = target;\n    return hashTable3[hash3];\n}\n\n\n/*-*************************************\n*  Binary Tree search\n***************************************/\n/** ZSTD_insertBt1() : add one or multiple positions to tree.\n * @param ip assumed <= iend-8 .\n * @param target The target of ZSTD_updateTree_internal() - we are filling to this position\n * @return : nb of positions added */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_insertBt1(\n                const ZSTD_MatchState_t* ms,\n                const BYTE* const ip, const BYTE* const iend,\n                U32 const target,\n                U32 const mls, const int extDict)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32*   const hashTable = ms->hashTable;\n    U32    const hashLog = cParams->hashLog;\n    size_t const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32*   const bt = ms->chainTable;\n    U32    const btLog  = cParams->chainLog - 1;\n    U32    const btMask = (1 << btLog) - 1;\n    U32 matchIndex = hashTable[h];\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const dictBase = ms->window.dictBase;\n    const U32 dictLimit = ms->window.dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    const BYTE* match;\n    const U32 curr = (U32)(ip-base);\n    const U32 btLow = btMask >= curr ? 0 : curr - btMask;\n    U32* smallerPtr = bt + 2*(curr&btMask);\n    U32* largerPtr  = smallerPtr + 1;\n    U32 dummy32;   /* to be nullified at the end */\n    /* windowLow is based on target because\n     * we only need positions that will be in the window at the end of the tree update.\n     */\n    U32 const windowLow = ZSTD_getLowestMatchIndex(ms, target, cParams->windowLog);\n    U32 matchEndIdx = curr+8+1;\n    size_t bestLength = 8;\n    U32 nbCompares = 1U << cParams->searchLog;\n#ifdef ZSTD_C_PREDICT\n    U32 predictedSmall = *(bt + 2*((curr-1)&btMask) + 0);\n    U32 predictedLarge = *(bt + 2*((curr-1)&btMask) + 1);\n    predictedSmall += (predictedSmall>0);\n    predictedLarge += (predictedLarge>0);\n#endif /* ZSTD_C_PREDICT */\n\n    DEBUGLOG(8, \"ZSTD_insertBt1 (%u)\", curr);\n\n    assert(curr <= target);\n    assert(ip <= iend-8);   /* required for h calculation */\n    hashTable[h] = curr;   /* Update Hash Table */\n\n    assert(windowLow > 0);\n    for (; nbCompares && (matchIndex >= windowLow); --nbCompares) {\n        U32* const nextPtr = bt + 2*(matchIndex & btMask);\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        assert(matchIndex < curr);\n\n#ifdef ZSTD_C_PREDICT   /* note : can create issues when hlog small <= 11 */\n        const U32* predictPtr = bt + 2*((matchIndex-1) & btMask);   /* written this way, as bt is a roll buffer */\n        if (matchIndex == predictedSmall) {\n            /* no need to check length, result known */\n            *smallerPtr = matchIndex;\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            smallerPtr = nextPtr+1;               /* new \"smaller\" => larger of match */\n            matchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n            predictedSmall = predictPtr[1] + (predictPtr[1]>0);\n            continue;\n        }\n        if (matchIndex == predictedLarge) {\n            *largerPtr = matchIndex;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n            predictedLarge = predictPtr[0] + (predictPtr[0]>0);\n            continue;\n        }\n#endif\n\n        if (!extDict || (matchIndex+matchLength >= dictLimit)) {\n            assert(matchIndex+matchLength >= dictLimit);   /* might be wrong if actually extDict */\n            match = base + matchIndex;\n            matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend);\n        } else {\n            match = dictBase + matchIndex;\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iend, dictEnd, prefixStart);\n            if (matchIndex+matchLength >= dictLimit)\n                match = base + matchIndex;   /* to prepare for next usage of match[matchLength] */\n        }\n\n        if (matchLength > bestLength) {\n            bestLength = matchLength;\n            if (matchLength > matchEndIdx - matchIndex)\n                matchEndIdx = matchIndex + (U32)matchLength;\n        }\n\n        if (ip+matchLength == iend) {   /* equal : no way to know if inf or sup */\n            break;   /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */\n        }\n\n        if (match[matchLength] < ip[matchLength]) {  /* necessarily within buffer */\n            /* match is smaller than current */\n            *smallerPtr = matchIndex;             /* update smaller idx */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            smallerPtr = nextPtr+1;               /* new \"candidate\" => larger than match, which was smaller than target */\n            matchIndex = nextPtr[1];              /* new matchIndex, larger than previous and closer to current */\n        } else {\n            /* match is larger than current */\n            *largerPtr = matchIndex;\n            commonLengthLarger = matchLength;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop searching */\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n    }   }\n\n    *smallerPtr = *largerPtr = 0;\n    {   U32 positions = 0;\n        if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384));   /* speed optimization */\n        assert(matchEndIdx > curr + 8);\n        return MAX(positions, matchEndIdx - (curr + 8));\n    }\n}\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_updateTree_internal(\n                ZSTD_MatchState_t* ms,\n                const BYTE* const ip, const BYTE* const iend,\n                const U32 mls, const ZSTD_dictMode_e dictMode)\n{\n    const BYTE* const base = ms->window.base;\n    U32 const target = (U32)(ip - base);\n    U32 idx = ms->nextToUpdate;\n    DEBUGLOG(7, \"ZSTD_updateTree_internal, from %u to %u  (dictMode:%u)\",\n                idx, target, dictMode);\n\n    while(idx < target) {\n        U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, target, mls, dictMode == ZSTD_extDict);\n        assert(idx < (U32)(idx + forward));\n        idx += forward;\n    }\n    assert((size_t)(ip - base) <= (size_t)(U32)(-1));\n    assert((size_t)(iend - base) <= (size_t)(U32)(-1));\n    ms->nextToUpdate = target;\n}\n\nvoid ZSTD_updateTree(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend) {\n    ZSTD_updateTree_internal(ms, ip, iend, ms->cParams.minMatch, ZSTD_noDict);\n}\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32\nZSTD_insertBtAndGetAllMatches (\n                ZSTD_match_t* matches,  /* store result (found matches) in this table (presumed large enough) */\n                ZSTD_MatchState_t* ms,\n                U32* nextToUpdate3,\n                const BYTE* const ip, const BYTE* const iLimit,\n                const ZSTD_dictMode_e dictMode,\n                const U32 rep[ZSTD_REP_NUM],\n                const U32 ll0,  /* tells if associated literal length is 0 or not. This value must be 0 or 1 */\n                const U32 lengthToBeat,\n                const U32 mls /* template */)\n{\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n    U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);\n    const BYTE* const base = ms->window.base;\n    U32 const curr = (U32)(ip-base);\n    U32 const hashLog = cParams->hashLog;\n    U32 const minMatch = (mls==3) ? 3 : 4;\n    U32* const hashTable = ms->hashTable;\n    size_t const h  = ZSTD_hashPtr(ip, hashLog, mls);\n    U32 matchIndex  = hashTable[h];\n    U32* const bt   = ms->chainTable;\n    U32 const btLog = cParams->chainLog - 1;\n    U32 const btMask= (1U << btLog) - 1;\n    size_t commonLengthSmaller=0, commonLengthLarger=0;\n    const BYTE* const dictBase = ms->window.dictBase;\n    U32 const dictLimit = ms->window.dictLimit;\n    const BYTE* const dictEnd = dictBase + dictLimit;\n    const BYTE* const prefixStart = base + dictLimit;\n    U32 const btLow = (btMask >= curr) ? 0 : curr - btMask;\n    U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog);\n    U32 const matchLow = windowLow ? windowLow : 1;\n    U32* smallerPtr = bt + 2*(curr&btMask);\n    U32* largerPtr  = bt + 2*(curr&btMask) + 1;\n    U32 matchEndIdx = curr+8+1;   /* farthest referenced position of any match => detects repetitive patterns */\n    U32 dummy32;   /* to be nullified at the end */\n    U32 mnum = 0;\n    U32 nbCompares = 1U << cParams->searchLog;\n\n    const ZSTD_MatchState_t* dms    = dictMode == ZSTD_dictMatchState ? ms->dictMatchState : NULL;\n    const ZSTD_compressionParameters* const dmsCParams =\n                                      dictMode == ZSTD_dictMatchState ? &dms->cParams : NULL;\n    const BYTE* const dmsBase       = dictMode == ZSTD_dictMatchState ? dms->window.base : NULL;\n    const BYTE* const dmsEnd        = dictMode == ZSTD_dictMatchState ? dms->window.nextSrc : NULL;\n    U32         const dmsHighLimit  = dictMode == ZSTD_dictMatchState ? (U32)(dmsEnd - dmsBase) : 0;\n    U32         const dmsLowLimit   = dictMode == ZSTD_dictMatchState ? dms->window.lowLimit : 0;\n    U32         const dmsIndexDelta = dictMode == ZSTD_dictMatchState ? windowLow - dmsHighLimit : 0;\n    U32         const dmsHashLog    = dictMode == ZSTD_dictMatchState ? dmsCParams->hashLog : hashLog;\n    U32         const dmsBtLog      = dictMode == ZSTD_dictMatchState ? dmsCParams->chainLog - 1 : btLog;\n    U32         const dmsBtMask     = dictMode == ZSTD_dictMatchState ? (1U << dmsBtLog) - 1 : 0;\n    U32         const dmsBtLow      = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit;\n\n    size_t bestLength = lengthToBeat-1;\n    DEBUGLOG(8, \"ZSTD_insertBtAndGetAllMatches: current=%u\", curr);\n\n    /* check repCode */\n    assert(ll0 <= 1);   /* necessarily 1 or 0 */\n    {   U32 const lastR = ZSTD_REP_NUM + ll0;\n        U32 repCode;\n        for (repCode = ll0; repCode < lastR; repCode++) {\n            U32 const repOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];\n            U32 const repIndex = curr - repOffset;\n            U32 repLen = 0;\n            assert(curr >= dictLimit);\n            if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < curr-dictLimit) {  /* equivalent to `curr > repIndex >= dictLimit` */\n                /* We must validate the repcode offset because when we're using a dictionary the\n                 * valid offset range shrinks when the dictionary goes out of bounds.\n                 */\n                if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) {\n                    repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch;\n                }\n            } else {  /* repIndex < dictLimit || repIndex >= curr */\n                const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ?\n                                             dmsBase + repIndex - dmsIndexDelta :\n                                             dictBase + repIndex;\n                assert(curr >= windowLow);\n                if ( dictMode == ZSTD_extDict\n                  && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow)  /* equivalent to `curr > repIndex >= windowLow` */\n                     & (ZSTD_index_overlap_check(dictLimit, repIndex)) )\n                  && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {\n                    repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch;\n                }\n                if (dictMode == ZSTD_dictMatchState\n                  && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta))  /* equivalent to `curr > repIndex >= dmsLowLimit` */\n                     & (ZSTD_index_overlap_check(dictLimit, repIndex)) )\n                  && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) {\n                    repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch;\n            }   }\n            /* save longer solution */\n            if (repLen > bestLength) {\n                DEBUGLOG(8, \"found repCode %u (ll0:%u, offset:%u) of length %u\",\n                            repCode, ll0, repOffset, repLen);\n                bestLength = repLen;\n                matches[mnum].off = REPCODE_TO_OFFBASE(repCode - ll0 + 1);  /* expect value between 1 and 3 */\n                matches[mnum].len = (U32)repLen;\n                mnum++;\n                if ( (repLen > sufficient_len)\n                   | (ip+repLen == iLimit) ) {  /* best possible */\n                    return mnum;\n    }   }   }   }\n\n    /* HC3 match finder */\n    if ((mls == 3) /*static*/ && (bestLength < mls)) {\n        U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip);\n        if ((matchIndex3 >= matchLow)\n          & (curr - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) {\n            size_t mlen;\n            if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) {\n                const BYTE* const match = base + matchIndex3;\n                mlen = ZSTD_count(ip, match, iLimit);\n            } else {\n                const BYTE* const match = dictBase + matchIndex3;\n                mlen = ZSTD_count_2segments(ip, match, iLimit, dictEnd, prefixStart);\n            }\n\n            /* save best solution */\n            if (mlen >= mls /* == 3 > bestLength */) {\n                DEBUGLOG(8, \"found small match with hlog3, of length %u\",\n                            (U32)mlen);\n                bestLength = mlen;\n                assert(curr > matchIndex3);\n                assert(mnum==0);  /* no prior solution */\n                matches[0].off = OFFSET_TO_OFFBASE(curr - matchIndex3);\n                matches[0].len = (U32)mlen;\n                mnum = 1;\n                if ( (mlen > sufficient_len) |\n                     (ip+mlen == iLimit) ) {  /* best possible length */\n                    ms->nextToUpdate = curr+1;  /* skip insertion */\n                    return 1;\n        }   }   }\n        /* no dictMatchState lookup: dicts don't have a populated HC3 table */\n    }  /* if (mls == 3) */\n\n    hashTable[h] = curr;   /* Update Hash Table */\n\n    for (; nbCompares && (matchIndex >= matchLow); --nbCompares) {\n        U32* const nextPtr = bt + 2*(matchIndex & btMask);\n        const BYTE* match;\n        size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n        assert(curr > matchIndex);\n\n        if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) {\n            assert(matchIndex+matchLength >= dictLimit);  /* ensure the condition is correct when !extDict */\n            match = base + matchIndex;\n            if (matchIndex >= dictLimit) assert(memcmp(match, ip, matchLength) == 0);  /* ensure early section of match is equal as expected */\n            matchLength += ZSTD_count(ip+matchLength, match+matchLength, iLimit);\n        } else {\n            match = dictBase + matchIndex;\n            assert(memcmp(match, ip, matchLength) == 0);  /* ensure early section of match is equal as expected */\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dictEnd, prefixStart);\n            if (matchIndex+matchLength >= dictLimit)\n                match = base + matchIndex;   /* prepare for match[matchLength] read */\n        }\n\n        if (matchLength > bestLength) {\n            DEBUGLOG(8, \"found match of length %u at distance %u (offBase=%u)\",\n                    (U32)matchLength, curr - matchIndex, OFFSET_TO_OFFBASE(curr - matchIndex));\n            assert(matchEndIdx > matchIndex);\n            if (matchLength > matchEndIdx - matchIndex)\n                matchEndIdx = matchIndex + (U32)matchLength;\n            bestLength = matchLength;\n            matches[mnum].off = OFFSET_TO_OFFBASE(curr - matchIndex);\n            matches[mnum].len = (U32)matchLength;\n            mnum++;\n            if ( (matchLength > ZSTD_OPT_NUM)\n               | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {\n                if (dictMode == ZSTD_dictMatchState) nbCompares = 0; /* break should also skip searching dms */\n                break; /* drop, to preserve bt consistency (miss a little bit of compression) */\n        }   }\n\n        if (match[matchLength] < ip[matchLength]) {\n            /* match smaller than current */\n            *smallerPtr = matchIndex;             /* update smaller idx */\n            commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n            if (matchIndex <= btLow) { smallerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            smallerPtr = nextPtr+1;               /* new candidate => larger than match, which was smaller than current */\n            matchIndex = nextPtr[1];              /* new matchIndex, larger than previous, closer to current */\n        } else {\n            *largerPtr = matchIndex;\n            commonLengthLarger = matchLength;\n            if (matchIndex <= btLow) { largerPtr=&dummy32; break; }   /* beyond tree size, stop the search */\n            largerPtr = nextPtr;\n            matchIndex = nextPtr[0];\n    }   }\n\n    *smallerPtr = *largerPtr = 0;\n\n    assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */\n    if (dictMode == ZSTD_dictMatchState && nbCompares) {\n        size_t const dmsH = ZSTD_hashPtr(ip, dmsHashLog, mls);\n        U32 dictMatchIndex = dms->hashTable[dmsH];\n        const U32* const dmsBt = dms->chainTable;\n        commonLengthSmaller = commonLengthLarger = 0;\n        for (; nbCompares && (dictMatchIndex > dmsLowLimit); --nbCompares) {\n            const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & dmsBtMask);\n            size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger);   /* guaranteed minimum nb of common bytes */\n            const BYTE* match = dmsBase + dictMatchIndex;\n            matchLength += ZSTD_count_2segments(ip+matchLength, match+matchLength, iLimit, dmsEnd, prefixStart);\n            if (dictMatchIndex+matchLength >= dmsHighLimit)\n                match = base + dictMatchIndex + dmsIndexDelta;   /* to prepare for next usage of match[matchLength] */\n\n            if (matchLength > bestLength) {\n                matchIndex = dictMatchIndex + dmsIndexDelta;\n                DEBUGLOG(8, \"found dms match of length %u at distance %u (offBase=%u)\",\n                        (U32)matchLength, curr - matchIndex, OFFSET_TO_OFFBASE(curr - matchIndex));\n                if (matchLength > matchEndIdx - matchIndex)\n                    matchEndIdx = matchIndex + (U32)matchLength;\n                bestLength = matchLength;\n                matches[mnum].off = OFFSET_TO_OFFBASE(curr - matchIndex);\n                matches[mnum].len = (U32)matchLength;\n                mnum++;\n                if ( (matchLength > ZSTD_OPT_NUM)\n                   | (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {\n                    break;   /* drop, to guarantee consistency (miss a little bit of compression) */\n            }   }\n\n            if (dictMatchIndex <= dmsBtLow) { break; }   /* beyond tree size, stop the search */\n            if (match[matchLength] < ip[matchLength]) {\n                commonLengthSmaller = matchLength;    /* all smaller will now have at least this guaranteed common length */\n                dictMatchIndex = nextPtr[1];              /* new matchIndex larger than previous (closer to current) */\n            } else {\n                /* match is larger than current */\n                commonLengthLarger = matchLength;\n                dictMatchIndex = nextPtr[0];\n    }   }   }  /* if (dictMode == ZSTD_dictMatchState) */\n\n    assert(matchEndIdx > curr+8);\n    ms->nextToUpdate = matchEndIdx - 8;  /* skip repetitive patterns */\n    return mnum;\n}\n\ntypedef U32 (*ZSTD_getAllMatchesFn)(\n    ZSTD_match_t*,\n    ZSTD_MatchState_t*,\n    U32*,\n    const BYTE*,\n    const BYTE*,\n    const U32 rep[ZSTD_REP_NUM],\n    U32 const ll0,\n    U32 const lengthToBeat);\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nU32 ZSTD_btGetAllMatches_internal(\n        ZSTD_match_t* matches,\n        ZSTD_MatchState_t* ms,\n        U32* nextToUpdate3,\n        const BYTE* ip,\n        const BYTE* const iHighLimit,\n        const U32 rep[ZSTD_REP_NUM],\n        U32 const ll0,\n        U32 const lengthToBeat,\n        const ZSTD_dictMode_e dictMode,\n        const U32 mls)\n{\n    assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls);\n    DEBUGLOG(8, \"ZSTD_BtGetAllMatches(dictMode=%d, mls=%u)\", (int)dictMode, mls);\n    if (ip < ms->window.base + ms->nextToUpdate)\n        return 0;   /* skipped area */\n    ZSTD_updateTree_internal(ms, ip, iHighLimit, mls, dictMode);\n    return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, mls);\n}\n\n#define ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls) ZSTD_btGetAllMatches_##dictMode##_##mls\n\n#define GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, mls)            \\\n    static U32 ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls)(      \\\n            ZSTD_match_t* matches,                             \\\n            ZSTD_MatchState_t* ms,                             \\\n            U32* nextToUpdate3,                                \\\n            const BYTE* ip,                                    \\\n            const BYTE* const iHighLimit,                      \\\n            const U32 rep[ZSTD_REP_NUM],                       \\\n            U32 const ll0,                                     \\\n            U32 const lengthToBeat)                            \\\n    {                                                          \\\n        return ZSTD_btGetAllMatches_internal(                  \\\n                matches, ms, nextToUpdate3, ip, iHighLimit,    \\\n                rep, ll0, lengthToBeat, ZSTD_##dictMode, mls); \\\n    }\n\n#define GEN_ZSTD_BT_GET_ALL_MATCHES(dictMode)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 3)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 4)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 5)  \\\n    GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 6)\n\nGEN_ZSTD_BT_GET_ALL_MATCHES(noDict)\nGEN_ZSTD_BT_GET_ALL_MATCHES(extDict)\nGEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState)\n\n#define ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMode)  \\\n    {                                            \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 3), \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 4), \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 5), \\\n        ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 6)  \\\n    }\n\nstatic ZSTD_getAllMatchesFn\nZSTD_selectBtGetAllMatches(ZSTD_MatchState_t const* ms, ZSTD_dictMode_e const dictMode)\n{\n    ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = {\n        ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict),\n        ZSTD_BT_GET_ALL_MATCHES_ARRAY(extDict),\n        ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMatchState)\n    };\n    U32 const mls = BOUNDED(3, ms->cParams.minMatch, 6);\n    assert((U32)dictMode < 3);\n    assert(mls - 3 < 4);\n    return getAllMatchesFns[(int)dictMode][mls - 3];\n}\n\n/*************************\n*  LDM helper functions  *\n*************************/\n\n/* Struct containing info needed to make decision about ldm inclusion */\ntypedef struct {\n    RawSeqStore_t seqStore;   /* External match candidates store for this block */\n    U32 startPosInBlock;      /* Start position of the current match candidate */\n    U32 endPosInBlock;        /* End position of the current match candidate */\n    U32 offset;               /* Offset of the match candidate */\n} ZSTD_optLdm_t;\n\n/* ZSTD_optLdm_skipRawSeqStoreBytes():\n * Moves forward in @rawSeqStore by @nbBytes,\n * which will update the fields 'pos' and 'posInSequence'.\n */\nstatic void ZSTD_optLdm_skipRawSeqStoreBytes(RawSeqStore_t* rawSeqStore, size_t nbBytes)\n{\n    U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);\n    while (currPos && rawSeqStore->pos < rawSeqStore->size) {\n        rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];\n        if (currPos >= currSeq.litLength + currSeq.matchLength) {\n            currPos -= currSeq.litLength + currSeq.matchLength;\n            rawSeqStore->pos++;\n        } else {\n            rawSeqStore->posInSequence = currPos;\n            break;\n        }\n    }\n    if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) {\n        rawSeqStore->posInSequence = 0;\n    }\n}\n\n/* ZSTD_opt_getNextMatchAndUpdateSeqStore():\n * Calculates the beginning and end of the next match in the current block.\n * Updates 'pos' and 'posInSequence' of the ldmSeqStore.\n */\nstatic void\nZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,\n                                       U32 blockBytesRemaining)\n{\n    rawSeq currSeq;\n    U32 currBlockEndPos;\n    U32 literalsBytesRemaining;\n    U32 matchBytesRemaining;\n\n    /* Setting match end position to MAX to ensure we never use an LDM during this block */\n    if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {\n        optLdm->startPosInBlock = UINT_MAX;\n        optLdm->endPosInBlock = UINT_MAX;\n        return;\n    }\n    /* Calculate appropriate bytes left in matchLength and litLength\n     * after adjusting based on ldmSeqStore->posInSequence */\n    currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];\n    assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);\n    currBlockEndPos = currPosInBlock + blockBytesRemaining;\n    literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ?\n            currSeq.litLength - (U32)optLdm->seqStore.posInSequence :\n            0;\n    matchBytesRemaining = (literalsBytesRemaining == 0) ?\n            currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) :\n            currSeq.matchLength;\n\n    /* If there are more literal bytes than bytes remaining in block, no ldm is possible */\n    if (literalsBytesRemaining >= blockBytesRemaining) {\n        optLdm->startPosInBlock = UINT_MAX;\n        optLdm->endPosInBlock = UINT_MAX;\n        ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining);\n        return;\n    }\n\n    /* Matches may be < minMatch by this process. In that case, we will reject them\n       when we are deciding whether or not to add the ldm */\n    optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining;\n    optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining;\n    optLdm->offset = currSeq.offset;\n\n    if (optLdm->endPosInBlock > currBlockEndPos) {\n        /* Match ends after the block ends, we can't use the whole match */\n        optLdm->endPosInBlock = currBlockEndPos;\n        ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock);\n    } else {\n        /* Consume nb of bytes equal to size of sequence left */\n        ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining);\n    }\n}\n\n/* ZSTD_optLdm_maybeAddMatch():\n * Adds a match if it's long enough,\n * based on it's 'matchStartPosInBlock' and 'matchEndPosInBlock',\n * into 'matches'. Maintains the correct ordering of 'matches'.\n */\nstatic void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,\n                                      const ZSTD_optLdm_t* optLdm, U32 currPosInBlock,\n                                      U32 minMatch)\n{\n    U32 const posDiff = currPosInBlock - optLdm->startPosInBlock;\n    /* Note: ZSTD_match_t actually contains offBase and matchLength (before subtracting MINMATCH) */\n    U32 const candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;\n\n    /* Ensure that current block position is not outside of the match */\n    if (currPosInBlock < optLdm->startPosInBlock\n      || currPosInBlock >= optLdm->endPosInBlock\n      || candidateMatchLength < minMatch) {\n        return;\n    }\n\n    if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {\n        U32 const candidateOffBase = OFFSET_TO_OFFBASE(optLdm->offset);\n        DEBUGLOG(6, \"ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offBase: %u matchLength %u) at block position=%u\",\n                 candidateOffBase, candidateMatchLength, currPosInBlock);\n        matches[*nbMatches].len = candidateMatchLength;\n        matches[*nbMatches].off = candidateOffBase;\n        (*nbMatches)++;\n    }\n}\n\n/* ZSTD_optLdm_processMatchCandidate():\n * Wrapper function to update ldm seq store and call ldm functions as necessary.\n */\nstatic void\nZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm,\n                                  ZSTD_match_t* matches, U32* nbMatches,\n                                  U32 currPosInBlock, U32 remainingBytes,\n                                  U32 minMatch)\n{\n    if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {\n        return;\n    }\n\n    if (currPosInBlock >= optLdm->endPosInBlock) {\n        if (currPosInBlock > optLdm->endPosInBlock) {\n            /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily\n             * at the end of a match from the ldm seq store, and will often be some bytes\n             * over beyond matchEndPosInBlock. As such, we need to correct for these \"overshoots\"\n             */\n            U32 const posOvershoot = currPosInBlock - optLdm->endPosInBlock;\n            ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);\n        }\n        ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);\n    }\n    ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock, minMatch);\n}\n\n\n/*-*******************************\n*  Optimal parser\n*********************************/\n\n#if 0 /* debug */\n\nstatic void\nlistStats(const U32* table, int lastEltID)\n{\n    int const nbElts = lastEltID + 1;\n    int enb;\n    for (enb=0; enb < nbElts; enb++) {\n        (void)table;\n        /* RAWLOG(2, \"%3i:%3i,  \", enb, table[enb]); */\n        RAWLOG(2, \"%4i,\", table[enb]);\n    }\n    RAWLOG(2, \" \\n\");\n}\n\n#endif\n\n#define LIT_PRICE(_p) (int)ZSTD_rawLiteralsCost(_p, 1, optStatePtr, optLevel)\n#define LL_PRICE(_l) (int)ZSTD_litLengthPrice(_l, optStatePtr, optLevel)\n#define LL_INCPRICE(_l) (LL_PRICE(_l) - LL_PRICE(_l-1))\n\nFORCE_INLINE_TEMPLATE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t\nZSTD_compressBlock_opt_generic(ZSTD_MatchState_t* ms,\n                               SeqStore_t* seqStore,\n                               U32 rep[ZSTD_REP_NUM],\n                         const void* src, size_t srcSize,\n                         const int optLevel,\n                         const ZSTD_dictMode_e dictMode)\n{\n    optState_t* const optStatePtr = &ms->opt;\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* anchor = istart;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* const ilimit = iend - 8;\n    const BYTE* const base = ms->window.base;\n    const BYTE* const prefixStart = base + ms->window.dictLimit;\n    const ZSTD_compressionParameters* const cParams = &ms->cParams;\n\n    ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode);\n\n    U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);\n    U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;\n    U32 nextToUpdate3 = ms->nextToUpdate;\n\n    ZSTD_optimal_t* const opt = optStatePtr->priceTable;\n    ZSTD_match_t* const matches = optStatePtr->matchTable;\n    ZSTD_optimal_t lastStretch;\n    ZSTD_optLdm_t optLdm;\n\n    ZSTD_memset(&lastStretch, 0, sizeof(ZSTD_optimal_t));\n\n    optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore;\n    optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0;\n    ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip));\n\n    /* init */\n    DEBUGLOG(5, \"ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u\",\n                (U32)(ip - base), ms->window.dictLimit, ms->nextToUpdate);\n    assert(optLevel <= 2);\n    ZSTD_rescaleFreqs(optStatePtr, (const BYTE*)src, srcSize, optLevel);\n    ip += (ip==prefixStart);\n\n    /* Match Loop */\n    while (ip < ilimit) {\n        U32 cur, last_pos = 0;\n\n        /* find first match */\n        {   U32 const litlen = (U32)(ip - anchor);\n            U32 const ll0 = !litlen;\n            U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, ip, iend, rep, ll0, minMatch);\n            ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,\n                                              (U32)(ip-istart), (U32)(iend-ip),\n                                              minMatch);\n            if (!nbMatches) {\n                DEBUGLOG(8, \"no match found at cPos %u\", (unsigned)(ip-istart));\n                ip++;\n                continue;\n            }\n\n            /* Match found: let's store this solution, and eventually find more candidates.\n             * During this forward pass, @opt is used to store stretches,\n             * defined as \"a match followed by N literals\".\n             * Note how this is different from a Sequence, which is \"N literals followed by a match\".\n             * Storing stretches allows us to store different match predecessors\n             * for each literal position part of a literals run. */\n\n            /* initialize opt[0] */\n            opt[0].mlen = 0;  /* there are only literals so far */\n            opt[0].litlen = litlen;\n            /* No need to include the actual price of the literals before the first match\n             * because it is static for the duration of the forward pass, and is included\n             * in every subsequent price. But, we include the literal length because\n             * the cost variation of litlen depends on the value of litlen.\n             */\n            opt[0].price = LL_PRICE(litlen);\n            ZSTD_STATIC_ASSERT(sizeof(opt[0].rep[0]) == sizeof(rep[0]));\n            ZSTD_memcpy(&opt[0].rep, rep, sizeof(opt[0].rep));\n\n            /* large match -> immediate encoding */\n            {   U32 const maxML = matches[nbMatches-1].len;\n                U32 const maxOffBase = matches[nbMatches-1].off;\n                DEBUGLOG(6, \"found %u matches of maxLength=%u and maxOffBase=%u at cPos=%u => start new series\",\n                            nbMatches, maxML, maxOffBase, (U32)(ip-prefixStart));\n\n                if (maxML > sufficient_len) {\n                    lastStretch.litlen = 0;\n                    lastStretch.mlen = maxML;\n                    lastStretch.off = maxOffBase;\n                    DEBUGLOG(6, \"large match (%u>%u) => immediate encoding\",\n                                maxML, sufficient_len);\n                    cur = 0;\n                    last_pos = maxML;\n                    goto _shortestPath;\n            }   }\n\n            /* set prices for first matches starting position == 0 */\n            assert(opt[0].price >= 0);\n            {   U32 pos;\n                U32 matchNb;\n                for (pos = 1; pos < minMatch; pos++) {\n                    opt[pos].price = ZSTD_MAX_PRICE;\n                    opt[pos].mlen = 0;\n                    opt[pos].litlen = litlen + pos;\n                }\n                for (matchNb = 0; matchNb < nbMatches; matchNb++) {\n                    U32 const offBase = matches[matchNb].off;\n                    U32 const end = matches[matchNb].len;\n                    for ( ; pos <= end ; pos++ ) {\n                        int const matchPrice = (int)ZSTD_getMatchPrice(offBase, pos, optStatePtr, optLevel);\n                        int const sequencePrice = opt[0].price + matchPrice;\n                        DEBUGLOG(7, \"rPos:%u => set initial price : %.2f\",\n                                    pos, ZSTD_fCost(sequencePrice));\n                        opt[pos].mlen = pos;\n                        opt[pos].off = offBase;\n                        opt[pos].litlen = 0; /* end of match */\n                        opt[pos].price = sequencePrice + LL_PRICE(0);\n                    }\n                }\n                last_pos = pos-1;\n                opt[pos].price = ZSTD_MAX_PRICE;\n            }\n        }\n\n        /* check further positions */\n        for (cur = 1; cur <= last_pos; cur++) {\n            const BYTE* const inr = ip + cur;\n            assert(cur <= ZSTD_OPT_NUM);\n            DEBUGLOG(7, \"cPos:%i==rPos:%u\", (int)(inr-istart), cur);\n\n            /* Fix current position with one literal if cheaper */\n            {   U32 const litlen = opt[cur-1].litlen + 1;\n                int const price = opt[cur-1].price\n                                + LIT_PRICE(ip+cur-1)\n                                + LL_INCPRICE(litlen);\n                assert(price < 1000000000); /* overflow check */\n                if (price <= opt[cur].price) {\n                    ZSTD_optimal_t const prevMatch = opt[cur];\n                    DEBUGLOG(7, \"cPos:%i==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)\",\n                                (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price), litlen,\n                                opt[cur-1].rep[0], opt[cur-1].rep[1], opt[cur-1].rep[2]);\n                    opt[cur] = opt[cur-1];\n                    opt[cur].litlen = litlen;\n                    opt[cur].price = price;\n                    if ( (optLevel >= 1) /* additional check only for higher modes */\n                      && (prevMatch.litlen == 0) /* replace a match */\n                      && (LL_INCPRICE(1) < 0) /* ll1 is cheaper than ll0 */\n                      && LIKELY(ip + cur < iend)\n                    ) {\n                        /* check next position, in case it would be cheaper */\n                        int with1literal = prevMatch.price + LIT_PRICE(ip+cur) + LL_INCPRICE(1);\n                        int withMoreLiterals = price + LIT_PRICE(ip+cur) + LL_INCPRICE(litlen+1);\n                        DEBUGLOG(7, \"then at next rPos %u : match+1lit %.2f vs %ulits %.2f\",\n                                cur+1, ZSTD_fCost(with1literal), litlen+1, ZSTD_fCost(withMoreLiterals));\n                        if ( (with1literal < withMoreLiterals)\n                          && (with1literal < opt[cur+1].price) ) {\n                            /* update offset history - before it disappears */\n                            U32 const prev = cur - prevMatch.mlen;\n                            Repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, prevMatch.off, opt[prev].litlen==0);\n                            assert(cur >= prevMatch.mlen);\n                            DEBUGLOG(7, \"==> match+1lit is cheaper (%.2f < %.2f) (hist:%u,%u,%u) !\",\n                                        ZSTD_fCost(with1literal), ZSTD_fCost(withMoreLiterals),\n                                        newReps.rep[0], newReps.rep[1], newReps.rep[2] );\n                            opt[cur+1] = prevMatch;  /* mlen & offbase */\n                            ZSTD_memcpy(opt[cur+1].rep, &newReps, sizeof(Repcodes_t));\n                            opt[cur+1].litlen = 1;\n                            opt[cur+1].price = with1literal;\n                            if (last_pos < cur+1) last_pos = cur+1;\n                        }\n                    }\n                } else {\n                    DEBUGLOG(7, \"cPos:%i==rPos:%u : literal would cost more (%.2f>%.2f)\",\n                                (int)(inr-istart), cur, ZSTD_fCost(price), ZSTD_fCost(opt[cur].price));\n                }\n            }\n\n            /* Offset history is not updated during match comparison.\n             * Do it here, now that the match is selected and confirmed.\n             */\n            ZSTD_STATIC_ASSERT(sizeof(opt[cur].rep) == sizeof(Repcodes_t));\n            assert(cur >= opt[cur].mlen);\n            if (opt[cur].litlen == 0) {\n                /* just finished a match => alter offset history */\n                U32 const prev = cur - opt[cur].mlen;\n                Repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[prev].litlen==0);\n                ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(Repcodes_t));\n            }\n\n            /* last match must start at a minimum distance of 8 from oend */\n            if (inr > ilimit) continue;\n\n            if (cur == last_pos) break;\n\n            if ( (optLevel==0) /*static_test*/\n              && (opt[cur+1].price <= opt[cur].price + (BITCOST_MULTIPLIER/2)) ) {\n                DEBUGLOG(7, \"skip current position : next rPos(%u) price is cheaper\", cur+1);\n                continue;  /* skip unpromising positions; about ~+6% speed, -0.01 ratio */\n            }\n\n            assert(opt[cur].price >= 0);\n            {   U32 const ll0 = (opt[cur].litlen == 0);\n                int const previousPrice = opt[cur].price;\n                int const basePrice = previousPrice + LL_PRICE(0);\n                U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, inr, iend, opt[cur].rep, ll0, minMatch);\n                U32 matchNb;\n\n                ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,\n                                                  (U32)(inr-istart), (U32)(iend-inr),\n                                                  minMatch);\n\n                if (!nbMatches) {\n                    DEBUGLOG(7, \"rPos:%u : no match found\", cur);\n                    continue;\n                }\n\n                {   U32 const longestML = matches[nbMatches-1].len;\n                    DEBUGLOG(7, \"cPos:%i==rPos:%u, found %u matches, of longest ML=%u\",\n                                (int)(inr-istart), cur, nbMatches, longestML);\n\n                    if ( (longestML > sufficient_len)\n                      || (cur + longestML >= ZSTD_OPT_NUM)\n                      || (ip + cur + longestML >= iend) ) {\n                        lastStretch.mlen = longestML;\n                        lastStretch.off = matches[nbMatches-1].off;\n                        lastStretch.litlen = 0;\n                        last_pos = cur + longestML;\n                        goto _shortestPath;\n                }   }\n\n                /* set prices using matches found at position == cur */\n                for (matchNb = 0; matchNb < nbMatches; matchNb++) {\n                    U32 const offset = matches[matchNb].off;\n                    U32 const lastML = matches[matchNb].len;\n                    U32 const startML = (matchNb>0) ? matches[matchNb-1].len+1 : minMatch;\n                    U32 mlen;\n\n                    DEBUGLOG(7, \"testing match %u => offBase=%4u, mlen=%2u, llen=%2u\",\n                                matchNb, matches[matchNb].off, lastML, opt[cur].litlen);\n\n                    for (mlen = lastML; mlen >= startML; mlen--) {  /* scan downward */\n                        U32 const pos = cur + mlen;\n                        int const price = basePrice + (int)ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);\n\n                        if ((pos > last_pos) || (price < opt[pos].price)) {\n                            DEBUGLOG(7, \"rPos:%u (ml=%2u) => new better price (%.2f<%.2f)\",\n                                        pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));\n                            while (last_pos < pos) {\n                                /* fill empty positions, for future comparisons */\n                                last_pos++;\n                                opt[last_pos].price = ZSTD_MAX_PRICE;\n                                opt[last_pos].litlen = !0;  /* just needs to be != 0, to mean \"not an end of match\" */\n                            }\n                            opt[pos].mlen = mlen;\n                            opt[pos].off = offset;\n                            opt[pos].litlen = 0;\n                            opt[pos].price = price;\n                        } else {\n                            DEBUGLOG(7, \"rPos:%u (ml=%2u) => new price is worse (%.2f>=%.2f)\",\n                                        pos, mlen, ZSTD_fCost(price), ZSTD_fCost(opt[pos].price));\n                            if (optLevel==0) break;  /* early update abort; gets ~+10% speed for about -0.01 ratio loss */\n                        }\n            }   }   }\n            opt[last_pos+1].price = ZSTD_MAX_PRICE;\n        }  /* for (cur = 1; cur <= last_pos; cur++) */\n\n        lastStretch = opt[last_pos];\n        assert(cur >= lastStretch.mlen);\n        cur = last_pos - lastStretch.mlen;\n\n_shortestPath:   /* cur, last_pos, best_mlen, best_off have to be set */\n        assert(opt[0].mlen == 0);\n        assert(last_pos >= lastStretch.mlen);\n        assert(cur == last_pos - lastStretch.mlen);\n\n        if (lastStretch.mlen==0) {\n            /* no solution : all matches have been converted into literals */\n            assert(lastStretch.litlen == (ip - anchor) + last_pos);\n            ip += last_pos;\n            continue;\n        }\n        assert(lastStretch.off > 0);\n\n        /* Update offset history */\n        if (lastStretch.litlen == 0) {\n            /* finishing on a match : update offset history */\n            Repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastStretch.off, opt[cur].litlen==0);\n            ZSTD_memcpy(rep, &reps, sizeof(Repcodes_t));\n        } else {\n            ZSTD_memcpy(rep, lastStretch.rep, sizeof(Repcodes_t));\n            assert(cur >= lastStretch.litlen);\n            cur -= lastStretch.litlen;\n        }\n\n        /* Let's write the shortest path solution.\n         * It is stored in @opt in reverse order,\n         * starting from @storeEnd (==cur+2),\n         * effectively partially @opt overwriting.\n         * Content is changed too:\n         * - So far, @opt stored stretches, aka a match followed by literals\n         * - Now, it will store sequences, aka literals followed by a match\n         */\n        {   U32 const storeEnd = cur + 2;\n            U32 storeStart = storeEnd;\n            U32 stretchPos = cur;\n\n            DEBUGLOG(6, \"start reverse traversal (last_pos:%u, cur:%u)\",\n                        last_pos, cur); (void)last_pos;\n            assert(storeEnd < ZSTD_OPT_SIZE);\n            DEBUGLOG(6, \"last stretch copied into pos=%u (llen=%u,mlen=%u,ofc=%u)\",\n                        storeEnd, lastStretch.litlen, lastStretch.mlen, lastStretch.off);\n            if (lastStretch.litlen > 0) {\n                /* last \"sequence\" is unfinished: just a bunch of literals */\n                opt[storeEnd].litlen = lastStretch.litlen;\n                opt[storeEnd].mlen = 0;\n                storeStart = storeEnd-1;\n                opt[storeStart] = lastStretch;\n            } {\n                opt[storeEnd] = lastStretch;  /* note: litlen will be fixed */\n                storeStart = storeEnd;\n            }\n            while (1) {\n                ZSTD_optimal_t nextStretch = opt[stretchPos];\n                opt[storeStart].litlen = nextStretch.litlen;\n                DEBUGLOG(6, \"selected sequence (llen=%u,mlen=%u,ofc=%u)\",\n                            opt[storeStart].litlen, opt[storeStart].mlen, opt[storeStart].off);\n                if (nextStretch.mlen == 0) {\n                    /* reaching beginning of segment */\n                    break;\n                }\n                storeStart--;\n                opt[storeStart] = nextStretch; /* note: litlen will be fixed */\n                assert(nextStretch.litlen + nextStretch.mlen <= stretchPos);\n                stretchPos -= nextStretch.litlen + nextStretch.mlen;\n            }\n\n            /* save sequences */\n            DEBUGLOG(6, \"sending selected sequences into seqStore\");\n            {   U32 storePos;\n                for (storePos=storeStart; storePos <= storeEnd; storePos++) {\n                    U32 const llen = opt[storePos].litlen;\n                    U32 const mlen = opt[storePos].mlen;\n                    U32 const offBase = opt[storePos].off;\n                    U32 const advance = llen + mlen;\n                    DEBUGLOG(6, \"considering seq starting at %i, llen=%u, mlen=%u\",\n                                (int)(anchor - istart), (unsigned)llen, (unsigned)mlen);\n\n                    if (mlen==0) {  /* only literals => must be last \"sequence\", actually starting a new stream of sequences */\n                        assert(storePos == storeEnd);   /* must be last sequence */\n                        ip = anchor + llen;     /* last \"sequence\" is a bunch of literals => don't progress anchor */\n                        continue;   /* will finish */\n                    }\n\n                    assert(anchor + llen <= iend);\n                    ZSTD_updateStats(optStatePtr, llen, anchor, offBase, mlen);\n                    ZSTD_storeSeq(seqStore, llen, anchor, iend, offBase, mlen);\n                    anchor += advance;\n                    ip = anchor;\n            }   }\n            DEBUGLOG(7, \"new offset history : %u, %u, %u\", rep[0], rep[1], rep[2]);\n\n            /* update all costs */\n            ZSTD_setBasePrices(optStatePtr, optLevel);\n        }\n    }   /* while (ip < ilimit) */\n\n    /* Return the last literals size */\n    return (size_t)(iend - anchor);\n}\n#endif /* build exclusions */\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nstatic size_t ZSTD_compressBlock_opt0(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)\n{\n    return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nstatic size_t ZSTD_compressBlock_opt2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)\n{\n    return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btopt(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressBlock_btopt\");\n    return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_noDict);\n}\n#endif\n\n\n\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\n/* ZSTD_initStats_ultra():\n * make a first compression pass, just to seed stats with more accurate starting values.\n * only works on first block, with no dictionary and no ldm.\n * this function cannot error out, its narrow contract must be respected.\n */\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_initStats_ultra(ZSTD_MatchState_t* ms,\n                          SeqStore_t* seqStore,\n                          U32 rep[ZSTD_REP_NUM],\n                    const void* src, size_t srcSize)\n{\n    U32 tmpRep[ZSTD_REP_NUM];  /* updated rep codes will sink here */\n    ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep));\n\n    DEBUGLOG(4, \"ZSTD_initStats_ultra (srcSize=%zu)\", srcSize);\n    assert(ms->opt.litLengthSum == 0);    /* first block */\n    assert(seqStore->sequences == seqStore->sequencesStart);   /* no ldm */\n    assert(ms->window.dictLimit == ms->window.lowLimit);   /* no dictionary */\n    assert(ms->window.dictLimit - ms->nextToUpdate <= 1);  /* no prefix (note: intentional overflow, defined as 2-complement) */\n\n    ZSTD_compressBlock_opt2(ms, seqStore, tmpRep, src, srcSize, ZSTD_noDict);   /* generate stats into ms->opt*/\n\n    /* invalidate first scan from history, only keep entropy stats */\n    ZSTD_resetSeqStore(seqStore);\n    ms->window.base -= srcSize;\n    ms->window.dictLimit += (U32)srcSize;\n    ms->window.lowLimit = ms->window.dictLimit;\n    ms->nextToUpdate = ms->window.dictLimit;\n\n}\n\nsize_t ZSTD_compressBlock_btultra(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_compressBlock_btultra (srcSize=%zu)\", srcSize);\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);\n}\n\nsize_t ZSTD_compressBlock_btultra2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    U32 const curr = (U32)((const BYTE*)src - ms->window.base);\n    DEBUGLOG(5, \"ZSTD_compressBlock_btultra2 (srcSize=%zu)\", srcSize);\n\n    /* 2-passes strategy:\n     * this strategy makes a first pass over first block to collect statistics\n     * in order to seed next round's statistics with it.\n     * After 1st pass, function forgets history, and starts a new block.\n     * Consequently, this can only work if no data has been previously loaded in tables,\n     * aka, no dictionary, no prefix, no ldm preprocessing.\n     * The compression ratio gain is generally small (~0.5% on first block),\n     * the cost is 2x cpu time on first block. */\n    assert(srcSize <= ZSTD_BLOCKSIZE_MAX);\n    if ( (ms->opt.litLengthSum==0)   /* first block */\n      && (seqStore->sequences == seqStore->sequencesStart)  /* no ldm */\n      && (ms->window.dictLimit == ms->window.lowLimit)   /* no dictionary */\n      && (curr == ms->window.dictLimit)    /* start of frame, nothing already loaded nor skipped */\n      && (srcSize > ZSTD_PREDEF_THRESHOLD) /* input large enough to not employ default stats */\n      ) {\n        ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);\n    }\n\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btopt_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_btopt_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_extDict);\n}\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btultra_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);\n}\n\nsize_t ZSTD_compressBlock_btultra_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        const void* src, size_t srcSize)\n{\n    return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_extDict);\n}\n#endif\n\n/* note : no btultra2 variant for extDict nor dictMatchState,\n * because btultra2 is not meant to work with dictionaries\n * and is only specific for the first block (no prefix) */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_opt.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_OPT_H\n#define ZSTD_OPT_H\n\n#include \"zstd_compress_internal.h\"\n\n#if !defined(ZSTD_EXCLUDE_BTLAZY2_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR) \\\n || !defined(ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR)\n/* used in ZSTD_loadDictionaryContent() */\nvoid ZSTD_updateTree(ZSTD_MatchState_t* ms, const BYTE* ip, const BYTE* iend);\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTOPT_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btopt(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btopt_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btopt_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_BTOPT ZSTD_compressBlock_btopt\n#define ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE ZSTD_compressBlock_btopt_dictMatchState\n#define ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT ZSTD_compressBlock_btopt_extDict\n#else\n#define ZSTD_COMPRESSBLOCK_BTOPT NULL\n#define ZSTD_COMPRESSBLOCK_BTOPT_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_BTOPT_EXTDICT NULL\n#endif\n\n#ifndef ZSTD_EXCLUDE_BTULTRA_BLOCK_COMPRESSOR\nsize_t ZSTD_compressBlock_btultra(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btultra_dictMatchState(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\nsize_t ZSTD_compressBlock_btultra_extDict(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n        /* note : no btultra2 variant for extDict nor dictMatchState,\n         * because btultra2 is not meant to work with dictionaries\n         * and is only specific for the first block (no prefix) */\nsize_t ZSTD_compressBlock_btultra2(\n        ZSTD_MatchState_t* ms, SeqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],\n        void const* src, size_t srcSize);\n\n#define ZSTD_COMPRESSBLOCK_BTULTRA ZSTD_compressBlock_btultra\n#define ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE ZSTD_compressBlock_btultra_dictMatchState\n#define ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT ZSTD_compressBlock_btultra_extDict\n#define ZSTD_COMPRESSBLOCK_BTULTRA2 ZSTD_compressBlock_btultra2\n#else\n#define ZSTD_COMPRESSBLOCK_BTULTRA NULL\n#define ZSTD_COMPRESSBLOCK_BTULTRA_DICTMATCHSTATE NULL\n#define ZSTD_COMPRESSBLOCK_BTULTRA_EXTDICT NULL\n#define ZSTD_COMPRESSBLOCK_BTULTRA2 NULL\n#endif\n\n#endif /* ZSTD_OPT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_preSplit.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#include \"../common/compiler.h\" /* ZSTD_ALIGNOF */\n#include \"../common/mem.h\" /* S64 */\n#include \"../common/zstd_deps.h\" /* ZSTD_memset */\n#include \"../common/zstd_internal.h\" /* ZSTD_STATIC_ASSERT */\n#include \"hist.h\" /* HIST_add */\n#include \"zstd_preSplit.h\"\n\n\n#define BLOCKSIZE_MIN 3500\n#define THRESHOLD_PENALTY_RATE 16\n#define THRESHOLD_BASE (THRESHOLD_PENALTY_RATE - 2)\n#define THRESHOLD_PENALTY 3\n\n#define HASHLENGTH 2\n#define HASHLOG_MAX 10\n#define HASHTABLESIZE (1 << HASHLOG_MAX)\n#define HASHMASK (HASHTABLESIZE - 1)\n#define KNUTH 0x9e3779b9\n\n/* for hashLog > 8, hash 2 bytes.\n * for hashLog == 8, just take the byte, no hashing.\n * The speed of this method relies on compile-time constant propagation */\nFORCE_INLINE_TEMPLATE unsigned hash2(const void *p, unsigned hashLog)\n{\n    assert(hashLog >= 8);\n    if (hashLog == 8) return (U32)((const BYTE*)p)[0];\n    assert(hashLog <= HASHLOG_MAX);\n    return (U32)(MEM_read16(p)) * KNUTH >> (32 - hashLog);\n}\n\n\ntypedef struct {\n  unsigned events[HASHTABLESIZE];\n  size_t nbEvents;\n} Fingerprint;\ntypedef struct {\n    Fingerprint pastEvents;\n    Fingerprint newEvents;\n} FPStats;\n\nstatic void initStats(FPStats* fpstats)\n{\n    ZSTD_memset(fpstats, 0, sizeof(FPStats));\n}\n\nFORCE_INLINE_TEMPLATE void\naddEvents_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate, unsigned hashLog)\n{\n    const char* p = (const char*)src;\n    size_t limit = srcSize - HASHLENGTH + 1;\n    size_t n;\n    assert(srcSize >= HASHLENGTH);\n    for (n = 0; n < limit; n+=samplingRate) {\n        fp->events[hash2(p+n, hashLog)]++;\n    }\n    fp->nbEvents += limit/samplingRate;\n}\n\nFORCE_INLINE_TEMPLATE void\nrecordFingerprint_generic(Fingerprint* fp, const void* src, size_t srcSize, size_t samplingRate, unsigned hashLog)\n{\n    ZSTD_memset(fp, 0, sizeof(unsigned) * ((size_t)1 << hashLog));\n    fp->nbEvents = 0;\n    addEvents_generic(fp, src, srcSize, samplingRate, hashLog);\n}\n\ntypedef void (*RecordEvents_f)(Fingerprint* fp, const void* src, size_t srcSize);\n\n#define FP_RECORD(_rate) ZSTD_recordFingerprint_##_rate\n\n#define ZSTD_GEN_RECORD_FINGERPRINT(_rate, _hSize)                                 \\\n    static void FP_RECORD(_rate)(Fingerprint* fp, const void* src, size_t srcSize) \\\n    {                                                                              \\\n        recordFingerprint_generic(fp, src, srcSize, _rate, _hSize);                \\\n    }\n\nZSTD_GEN_RECORD_FINGERPRINT(1, 10)\nZSTD_GEN_RECORD_FINGERPRINT(5, 10)\nZSTD_GEN_RECORD_FINGERPRINT(11, 9)\nZSTD_GEN_RECORD_FINGERPRINT(43, 8)\n\n\nstatic U64 abs64(S64 s64) { return (U64)((s64 < 0) ? -s64 : s64); }\n\nstatic U64 fpDistance(const Fingerprint* fp1, const Fingerprint* fp2, unsigned hashLog)\n{\n    U64 distance = 0;\n    size_t n;\n    assert(hashLog <= HASHLOG_MAX);\n    for (n = 0; n < ((size_t)1 << hashLog); n++) {\n        distance +=\n            abs64((S64)fp1->events[n] * (S64)fp2->nbEvents - (S64)fp2->events[n] * (S64)fp1->nbEvents);\n    }\n    return distance;\n}\n\n/* Compare newEvents with pastEvents\n * return 1 when considered \"too different\"\n */\nstatic int compareFingerprints(const Fingerprint* ref,\n                            const Fingerprint* newfp,\n                            int penalty,\n                            unsigned hashLog)\n{\n    assert(ref->nbEvents > 0);\n    assert(newfp->nbEvents > 0);\n    {   U64 p50 = (U64)ref->nbEvents * (U64)newfp->nbEvents;\n        U64 deviation = fpDistance(ref, newfp, hashLog);\n        U64 threshold = p50 * (U64)(THRESHOLD_BASE + penalty) / THRESHOLD_PENALTY_RATE;\n        return deviation >= threshold;\n    }\n}\n\nstatic void mergeEvents(Fingerprint* acc, const Fingerprint* newfp)\n{\n    size_t n;\n    for (n = 0; n < HASHTABLESIZE; n++) {\n        acc->events[n] += newfp->events[n];\n    }\n    acc->nbEvents += newfp->nbEvents;\n}\n\nstatic void flushEvents(FPStats* fpstats)\n{\n    size_t n;\n    for (n = 0; n < HASHTABLESIZE; n++) {\n        fpstats->pastEvents.events[n] = fpstats->newEvents.events[n];\n    }\n    fpstats->pastEvents.nbEvents = fpstats->newEvents.nbEvents;\n    ZSTD_memset(&fpstats->newEvents, 0, sizeof(fpstats->newEvents));\n}\n\nstatic void removeEvents(Fingerprint* acc, const Fingerprint* slice)\n{\n    size_t n;\n    for (n = 0; n < HASHTABLESIZE; n++) {\n        assert(acc->events[n] >= slice->events[n]);\n        acc->events[n] -= slice->events[n];\n    }\n    acc->nbEvents -= slice->nbEvents;\n}\n\n#define CHUNKSIZE (8 << 10)\nstatic size_t ZSTD_splitBlock_byChunks(const void* blockStart, size_t blockSize,\n                        int level,\n                        void* workspace, size_t wkspSize)\n{\n    static const RecordEvents_f records_fs[] = {\n        FP_RECORD(43), FP_RECORD(11), FP_RECORD(5), FP_RECORD(1)\n    };\n    static const unsigned hashParams[] = { 8, 9, 10, 10 };\n    const RecordEvents_f record_f = (assert(0<=level && level<=3), records_fs[level]);\n    FPStats* const fpstats = (FPStats*)workspace;\n    const char* p = (const char*)blockStart;\n    int penalty = THRESHOLD_PENALTY;\n    size_t pos = 0;\n    assert(blockSize == (128 << 10));\n    assert(workspace != NULL);\n    assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0);\n    ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats));\n    assert(wkspSize >= sizeof(FPStats)); (void)wkspSize;\n\n    initStats(fpstats);\n    record_f(&fpstats->pastEvents, p, CHUNKSIZE);\n    for (pos = CHUNKSIZE; pos <= blockSize - CHUNKSIZE; pos += CHUNKSIZE) {\n        record_f(&fpstats->newEvents, p + pos, CHUNKSIZE);\n        if (compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, penalty, hashParams[level])) {\n            return pos;\n        } else {\n            mergeEvents(&fpstats->pastEvents, &fpstats->newEvents);\n            if (penalty > 0) penalty--;\n        }\n    }\n    assert(pos == blockSize);\n    return blockSize;\n    (void)flushEvents; (void)removeEvents;\n}\n\n/* ZSTD_splitBlock_fromBorders(): very fast strategy :\n * compare fingerprint from beginning and end of the block,\n * derive from their difference if it's preferable to split in the middle,\n * repeat the process a second time, for finer grained decision.\n * 3 times did not brought improvements, so I stopped at 2.\n * Benefits are good enough for a cheap heuristic.\n * More accurate splitting saves more, but speed impact is also more perceptible.\n * For better accuracy, use more elaborate variant *_byChunks.\n */\nstatic size_t ZSTD_splitBlock_fromBorders(const void* blockStart, size_t blockSize,\n                        void* workspace, size_t wkspSize)\n{\n#define SEGMENT_SIZE 512\n    FPStats* const fpstats = (FPStats*)workspace;\n    Fingerprint* middleEvents = (Fingerprint*)(void*)((char*)workspace + 512 * sizeof(unsigned));\n    assert(blockSize == (128 << 10));\n    assert(workspace != NULL);\n    assert((size_t)workspace % ZSTD_ALIGNOF(FPStats) == 0);\n    ZSTD_STATIC_ASSERT(ZSTD_SLIPBLOCK_WORKSPACESIZE >= sizeof(FPStats));\n    assert(wkspSize >= sizeof(FPStats)); (void)wkspSize;\n\n    initStats(fpstats);\n    HIST_add(fpstats->pastEvents.events, blockStart, SEGMENT_SIZE);\n    HIST_add(fpstats->newEvents.events, (const char*)blockStart + blockSize - SEGMENT_SIZE, SEGMENT_SIZE);\n    fpstats->pastEvents.nbEvents = fpstats->newEvents.nbEvents = SEGMENT_SIZE;\n    if (!compareFingerprints(&fpstats->pastEvents, &fpstats->newEvents, 0, 8))\n        return blockSize;\n\n    HIST_add(middleEvents->events, (const char*)blockStart + blockSize/2 - SEGMENT_SIZE/2, SEGMENT_SIZE);\n    middleEvents->nbEvents = SEGMENT_SIZE;\n    {   U64 const distFromBegin = fpDistance(&fpstats->pastEvents, middleEvents, 8);\n        U64 const distFromEnd = fpDistance(&fpstats->newEvents, middleEvents, 8);\n        U64 const minDistance = SEGMENT_SIZE * SEGMENT_SIZE / 3;\n        if (abs64((S64)distFromBegin - (S64)distFromEnd) < minDistance)\n            return 64 KB;\n        return (distFromBegin > distFromEnd) ? 32 KB : 96 KB;\n    }\n}\n\nsize_t ZSTD_splitBlock(const void* blockStart, size_t blockSize,\n                    int level,\n                    void* workspace, size_t wkspSize)\n{\n    DEBUGLOG(6, \"ZSTD_splitBlock (level=%i)\", level);\n    assert(0<=level && level<=4);\n    if (level == 0)\n        return ZSTD_splitBlock_fromBorders(blockStart, blockSize, workspace, wkspSize);\n    /* level >= 1*/\n    return ZSTD_splitBlock_byChunks(blockStart, blockSize, level-1, workspace, wkspSize);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstd_preSplit.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_PRESPLIT_H\n#define ZSTD_PRESPLIT_H\n\n#include <stddef.h>  /* size_t */\n\n#define ZSTD_SLIPBLOCK_WORKSPACESIZE 8208\n\n/* ZSTD_splitBlock():\n * @level must be a value between 0 and 4.\n *        higher levels spend more energy to detect block boundaries.\n * @workspace must be aligned for size_t.\n * @wkspSize must be at least >= ZSTD_SLIPBLOCK_WORKSPACESIZE\n * note:\n * For the time being, this function only accepts full 128 KB blocks.\n * Therefore, @blockSize must be == 128 KB.\n * While this could be extended to smaller sizes in the future,\n * it is not yet clear if this would be useful. TBD.\n */\nsize_t ZSTD_splitBlock(const void* blockStart, size_t blockSize,\n                    int level,\n                    void* workspace, size_t wkspSize);\n\n#endif /* ZSTD_PRESPLIT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstdmt_compress.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ======   Compiler specifics   ====== */\n#if defined(_MSC_VER)\n#  pragma warning(disable : 4204)   /* disable: C4204: non-constant aggregate initializer */\n#endif\n\n\n/* ======   Dependencies   ====== */\n#include \"../common/allocations.h\" /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */\n#include \"../common/mem.h\"         /* MEM_STATIC */\n#include \"../common/pool.h\"        /* threadpool */\n#include \"../common/threading.h\"   /* mutex */\n#include \"zstd_compress_internal.h\" /* MIN, ERROR, ZSTD_*, ZSTD_highbit32 */\n#include \"zstd_ldm.h\"\n#include \"zstdmt_compress.h\"\n\n/* Guards code to support resizing the SeqPool.\n * We will want to resize the SeqPool to save memory in the future.\n * Until then, comment the code out since it is unused.\n */\n#define ZSTD_RESIZE_SEQPOOL 0\n\n/* ======   Debug   ====== */\n#if defined(DEBUGLEVEL) && (DEBUGLEVEL>=2) \\\n    && !defined(_MSC_VER) \\\n    && !defined(__MINGW32__)\n\n#  include <stdio.h>\n#  include <unistd.h>\n#  include <sys/times.h>\n\n#  define DEBUG_PRINTHEX(l,p,n)                                       \\\n    do {                                                              \\\n        unsigned debug_u;                                             \\\n        for (debug_u=0; debug_u<(n); debug_u++)                       \\\n            RAWLOG(l, \"%02X \", ((const unsigned char*)(p))[debug_u]); \\\n        RAWLOG(l, \" \\n\");                                             \\\n    } while (0)\n\nstatic unsigned long long GetCurrentClockTimeMicroseconds(void)\n{\n   static clock_t _ticksPerSecond = 0;\n   if (_ticksPerSecond <= 0) _ticksPerSecond = sysconf(_SC_CLK_TCK);\n\n   {   struct tms junk; clock_t newTicks = (clock_t) times(&junk);\n       return ((((unsigned long long)newTicks)*(1000000))/_ticksPerSecond);\n}  }\n\n#define MUTEX_WAIT_TIME_DLEVEL 6\n#define ZSTD_PTHREAD_MUTEX_LOCK(mutex)                                                  \\\n    do {                                                                                \\\n        if (DEBUGLEVEL >= MUTEX_WAIT_TIME_DLEVEL) {                                     \\\n            unsigned long long const beforeTime = GetCurrentClockTimeMicroseconds();    \\\n            ZSTD_pthread_mutex_lock(mutex);                                             \\\n            {   unsigned long long const afterTime = GetCurrentClockTimeMicroseconds(); \\\n                unsigned long long const elapsedTime = (afterTime-beforeTime);          \\\n                if (elapsedTime > 1000) {                                               \\\n                    /* or whatever threshold you like; I'm using 1 millisecond here */  \\\n                    DEBUGLOG(MUTEX_WAIT_TIME_DLEVEL,                                    \\\n                        \"Thread took %llu microseconds to acquire mutex %s \\n\",         \\\n                        elapsedTime, #mutex);                                           \\\n            }   }                                                                       \\\n        } else {                                                                        \\\n            ZSTD_pthread_mutex_lock(mutex);                                             \\\n        }                                                                               \\\n    } while (0)\n\n#else\n\n#  define ZSTD_PTHREAD_MUTEX_LOCK(m) ZSTD_pthread_mutex_lock(m)\n#  define DEBUG_PRINTHEX(l,p,n) do { } while (0)\n\n#endif\n\n\n/* =====   Buffer Pool   ===== */\n/* a single Buffer Pool can be invoked from multiple threads in parallel */\n\ntypedef struct buffer_s {\n    void* start;\n    size_t capacity;\n} Buffer;\n\nstatic const Buffer g_nullBuffer = { NULL, 0 };\n\ntypedef struct ZSTDMT_bufferPool_s {\n    ZSTD_pthread_mutex_t poolMutex;\n    size_t bufferSize;\n    unsigned totalBuffers;\n    unsigned nbBuffers;\n    ZSTD_customMem cMem;\n    Buffer* buffers;\n} ZSTDMT_bufferPool;\n\nstatic void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool)\n{\n    DEBUGLOG(3, \"ZSTDMT_freeBufferPool (address:%08X)\", (U32)(size_t)bufPool);\n    if (!bufPool) return;   /* compatibility with free on NULL */\n    if (bufPool->buffers) {\n        unsigned u;\n        for (u=0; u<bufPool->totalBuffers; u++) {\n            DEBUGLOG(4, \"free buffer %2u (address:%08X)\", u, (U32)(size_t)bufPool->buffers[u].start);\n            ZSTD_customFree(bufPool->buffers[u].start, bufPool->cMem);\n        }\n        ZSTD_customFree(bufPool->buffers, bufPool->cMem);\n    }\n    ZSTD_pthread_mutex_destroy(&bufPool->poolMutex);\n    ZSTD_customFree(bufPool, bufPool->cMem);\n}\n\nstatic ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_customMem cMem)\n{\n    ZSTDMT_bufferPool* const bufPool =\n        (ZSTDMT_bufferPool*)ZSTD_customCalloc(sizeof(ZSTDMT_bufferPool), cMem);\n    if (bufPool==NULL) return NULL;\n    if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) {\n        ZSTD_customFree(bufPool, cMem);\n        return NULL;\n    }\n    bufPool->buffers = (Buffer*)ZSTD_customCalloc(maxNbBuffers * sizeof(Buffer), cMem);\n    if (bufPool->buffers==NULL) {\n        ZSTDMT_freeBufferPool(bufPool);\n        return NULL;\n    }\n    bufPool->bufferSize = 64 KB;\n    bufPool->totalBuffers = maxNbBuffers;\n    bufPool->nbBuffers = 0;\n    bufPool->cMem = cMem;\n    return bufPool;\n}\n\n/* only works at initialization, not during compression */\nstatic size_t ZSTDMT_sizeof_bufferPool(ZSTDMT_bufferPool* bufPool)\n{\n    size_t const poolSize = sizeof(*bufPool);\n    size_t const arraySize = bufPool->totalBuffers * sizeof(Buffer);\n    unsigned u;\n    size_t totalBufferSize = 0;\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    for (u=0; u<bufPool->totalBuffers; u++)\n        totalBufferSize += bufPool->buffers[u].capacity;\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n\n    return poolSize + arraySize + totalBufferSize;\n}\n\n/* ZSTDMT_setBufferSize() :\n * all future buffers provided by this buffer pool will have _at least_ this size\n * note : it's better for all buffers to have same size,\n * as they become freely interchangeable, reducing malloc/free usages and memory fragmentation */\nstatic void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const bSize)\n{\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    DEBUGLOG(4, \"ZSTDMT_setBufferSize: bSize = %u\", (U32)bSize);\n    bufPool->bufferSize = bSize;\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n}\n\n\nstatic ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, unsigned maxNbBuffers)\n{\n    if (srcBufPool==NULL) return NULL;\n    if (srcBufPool->totalBuffers >= maxNbBuffers) /* good enough */\n        return srcBufPool;\n    /* need a larger buffer pool */\n    {   ZSTD_customMem const cMem = srcBufPool->cMem;\n        size_t const bSize = srcBufPool->bufferSize;   /* forward parameters */\n        ZSTDMT_bufferPool* newBufPool;\n        ZSTDMT_freeBufferPool(srcBufPool);\n        newBufPool = ZSTDMT_createBufferPool(maxNbBuffers, cMem);\n        if (newBufPool==NULL) return newBufPool;\n        ZSTDMT_setBufferSize(newBufPool, bSize);\n        return newBufPool;\n    }\n}\n\n/** ZSTDMT_getBuffer() :\n *  assumption : bufPool must be valid\n * @return : a buffer, with start pointer and size\n *  note: allocation may fail, in this case, start==NULL and size==0 */\nstatic Buffer ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool)\n{\n    size_t const bSize = bufPool->bufferSize;\n    DEBUGLOG(5, \"ZSTDMT_getBuffer: bSize = %u\", (U32)bufPool->bufferSize);\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    if (bufPool->nbBuffers) {   /* try to use an existing buffer */\n        Buffer const buf = bufPool->buffers[--(bufPool->nbBuffers)];\n        size_t const availBufferSize = buf.capacity;\n        bufPool->buffers[bufPool->nbBuffers] = g_nullBuffer;\n        if ((availBufferSize >= bSize) & ((availBufferSize>>3) <= bSize)) {\n            /* large enough, but not too much */\n            DEBUGLOG(5, \"ZSTDMT_getBuffer: provide buffer %u of size %u\",\n                        bufPool->nbBuffers, (U32)buf.capacity);\n            ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n            return buf;\n        }\n        /* size conditions not respected : scratch this buffer, create new one */\n        DEBUGLOG(5, \"ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing\");\n        ZSTD_customFree(buf.start, bufPool->cMem);\n    }\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n    /* create new buffer */\n    DEBUGLOG(5, \"ZSTDMT_getBuffer: create a new buffer\");\n    {   Buffer buffer;\n        void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);\n        buffer.start = start;   /* note : start can be NULL if malloc fails ! */\n        buffer.capacity = (start==NULL) ? 0 : bSize;\n        if (start==NULL) {\n            DEBUGLOG(5, \"ZSTDMT_getBuffer: buffer allocation failure !!\");\n        } else {\n            DEBUGLOG(5, \"ZSTDMT_getBuffer: created buffer of size %u\", (U32)bSize);\n        }\n        return buffer;\n    }\n}\n\n#if ZSTD_RESIZE_SEQPOOL\n/** ZSTDMT_resizeBuffer() :\n * assumption : bufPool must be valid\n * @return : a buffer that is at least the buffer pool buffer size.\n *           If a reallocation happens, the data in the input buffer is copied.\n */\nstatic Buffer ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, Buffer buffer)\n{\n    size_t const bSize = bufPool->bufferSize;\n    if (buffer.capacity < bSize) {\n        void* const start = ZSTD_customMalloc(bSize, bufPool->cMem);\n        Buffer newBuffer;\n        newBuffer.start = start;\n        newBuffer.capacity = start == NULL ? 0 : bSize;\n        if (start != NULL) {\n            assert(newBuffer.capacity >= buffer.capacity);\n            ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity);\n            DEBUGLOG(5, \"ZSTDMT_resizeBuffer: created buffer of size %u\", (U32)bSize);\n            return newBuffer;\n        }\n        DEBUGLOG(5, \"ZSTDMT_resizeBuffer: buffer allocation failure !!\");\n    }\n    return buffer;\n}\n#endif\n\n/* store buffer for later re-use, up to pool capacity */\nstatic void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, Buffer buf)\n{\n    DEBUGLOG(5, \"ZSTDMT_releaseBuffer\");\n    if (buf.start == NULL) return;   /* compatible with release on NULL */\n    ZSTD_pthread_mutex_lock(&bufPool->poolMutex);\n    if (bufPool->nbBuffers < bufPool->totalBuffers) {\n        bufPool->buffers[bufPool->nbBuffers++] = buf;  /* stored for later use */\n        DEBUGLOG(5, \"ZSTDMT_releaseBuffer: stored buffer of size %u in slot %u\",\n                    (U32)buf.capacity, (U32)(bufPool->nbBuffers-1));\n        ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n        return;\n    }\n    ZSTD_pthread_mutex_unlock(&bufPool->poolMutex);\n    /* Reached bufferPool capacity (note: should not happen) */\n    DEBUGLOG(5, \"ZSTDMT_releaseBuffer: pool capacity reached => freeing \");\n    ZSTD_customFree(buf.start, bufPool->cMem);\n}\n\n/* We need 2 output buffers per worker since each dstBuff must be flushed after it is released.\n * The 3 additional buffers are as follows:\n *   1 buffer for input loading\n *   1 buffer for \"next input\" when submitting current one\n *   1 buffer stuck in queue */\n#define BUF_POOL_MAX_NB_BUFFERS(nbWorkers) (2*(nbWorkers) + 3)\n\n/* After a worker releases its rawSeqStore, it is immediately ready for reuse.\n * So we only need one seq buffer per worker. */\n#define SEQ_POOL_MAX_NB_BUFFERS(nbWorkers) (nbWorkers)\n\n/* =====   Seq Pool Wrapper   ====== */\n\ntypedef ZSTDMT_bufferPool ZSTDMT_seqPool;\n\nstatic size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool)\n{\n    return ZSTDMT_sizeof_bufferPool(seqPool);\n}\n\nstatic RawSeqStore_t bufferToSeq(Buffer buffer)\n{\n    RawSeqStore_t seq = kNullRawSeqStore;\n    seq.seq = (rawSeq*)buffer.start;\n    seq.capacity = buffer.capacity / sizeof(rawSeq);\n    return seq;\n}\n\nstatic Buffer seqToBuffer(RawSeqStore_t seq)\n{\n    Buffer buffer;\n    buffer.start = seq.seq;\n    buffer.capacity = seq.capacity * sizeof(rawSeq);\n    return buffer;\n}\n\nstatic RawSeqStore_t ZSTDMT_getSeq(ZSTDMT_seqPool* seqPool)\n{\n    if (seqPool->bufferSize == 0) {\n        return kNullRawSeqStore;\n    }\n    return bufferToSeq(ZSTDMT_getBuffer(seqPool));\n}\n\n#if ZSTD_RESIZE_SEQPOOL\nstatic RawSeqStore_t ZSTDMT_resizeSeq(ZSTDMT_seqPool* seqPool, RawSeqStore_t seq)\n{\n  return bufferToSeq(ZSTDMT_resizeBuffer(seqPool, seqToBuffer(seq)));\n}\n#endif\n\nstatic void ZSTDMT_releaseSeq(ZSTDMT_seqPool* seqPool, RawSeqStore_t seq)\n{\n  ZSTDMT_releaseBuffer(seqPool, seqToBuffer(seq));\n}\n\nstatic void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)\n{\n  ZSTDMT_setBufferSize(seqPool, nbSeq * sizeof(rawSeq));\n}\n\nstatic ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)\n{\n    ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(SEQ_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);\n    if (seqPool == NULL) return NULL;\n    ZSTDMT_setNbSeq(seqPool, 0);\n    return seqPool;\n}\n\nstatic void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)\n{\n    ZSTDMT_freeBufferPool(seqPool);\n}\n\nstatic ZSTDMT_seqPool* ZSTDMT_expandSeqPool(ZSTDMT_seqPool* pool, U32 nbWorkers)\n{\n    return ZSTDMT_expandBufferPool(pool, SEQ_POOL_MAX_NB_BUFFERS(nbWorkers));\n}\n\n\n/* =====   CCtx Pool   ===== */\n/* a single CCtx Pool can be invoked from multiple threads in parallel */\n\ntypedef struct {\n    ZSTD_pthread_mutex_t poolMutex;\n    int totalCCtx;\n    int availCCtx;\n    ZSTD_customMem cMem;\n    ZSTD_CCtx** cctxs;\n} ZSTDMT_CCtxPool;\n\n/* note : all CCtx borrowed from the pool must be reverted back to the pool _before_ freeing the pool */\nstatic void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)\n{\n    if (!pool) return;\n    ZSTD_pthread_mutex_destroy(&pool->poolMutex);\n    if (pool->cctxs) {\n        int cid;\n        for (cid=0; cid<pool->totalCCtx; cid++)\n            ZSTD_freeCCtx(pool->cctxs[cid]);  /* free compatible with NULL */\n        ZSTD_customFree(pool->cctxs, pool->cMem);\n    }\n    ZSTD_customFree(pool, pool->cMem);\n}\n\n/* ZSTDMT_createCCtxPool() :\n * implies nbWorkers >= 1 , checked by caller ZSTDMT_createCCtx() */\nstatic ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,\n                                              ZSTD_customMem cMem)\n{\n    ZSTDMT_CCtxPool* const cctxPool =\n        (ZSTDMT_CCtxPool*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtxPool), cMem);\n    assert(nbWorkers > 0);\n    if (!cctxPool) return NULL;\n    if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {\n        ZSTD_customFree(cctxPool, cMem);\n        return NULL;\n    }\n    cctxPool->totalCCtx = nbWorkers;\n    cctxPool->cctxs = (ZSTD_CCtx**)ZSTD_customCalloc(nbWorkers * sizeof(ZSTD_CCtx*), cMem);\n    if (!cctxPool->cctxs) {\n        ZSTDMT_freeCCtxPool(cctxPool);\n        return NULL;\n    }\n    cctxPool->cMem = cMem;\n    cctxPool->cctxs[0] = ZSTD_createCCtx_advanced(cMem);\n    if (!cctxPool->cctxs[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }\n    cctxPool->availCCtx = 1;   /* at least one cctx for single-thread mode */\n    DEBUGLOG(3, \"cctxPool created, with %u workers\", nbWorkers);\n    return cctxPool;\n}\n\nstatic ZSTDMT_CCtxPool* ZSTDMT_expandCCtxPool(ZSTDMT_CCtxPool* srcPool,\n                                              int nbWorkers)\n{\n    if (srcPool==NULL) return NULL;\n    if (nbWorkers <= srcPool->totalCCtx) return srcPool;   /* good enough */\n    /* need a larger cctx pool */\n    {   ZSTD_customMem const cMem = srcPool->cMem;\n        ZSTDMT_freeCCtxPool(srcPool);\n        return ZSTDMT_createCCtxPool(nbWorkers, cMem);\n    }\n}\n\n/* only works during initialization phase, not during compression */\nstatic size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)\n{\n    ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);\n    {   unsigned const nbWorkers = cctxPool->totalCCtx;\n        size_t const poolSize = sizeof(*cctxPool);\n        size_t const arraySize = cctxPool->totalCCtx * sizeof(ZSTD_CCtx*);\n        size_t totalCCtxSize = 0;\n        unsigned u;\n        for (u=0; u<nbWorkers; u++) {\n            totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctxs[u]);\n        }\n        ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);\n        assert(nbWorkers > 0);\n        return poolSize + arraySize + totalCCtxSize;\n    }\n}\n\nstatic ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)\n{\n    DEBUGLOG(5, \"ZSTDMT_getCCtx\");\n    ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);\n    if (cctxPool->availCCtx) {\n        cctxPool->availCCtx--;\n        {   ZSTD_CCtx* const cctx = cctxPool->cctxs[cctxPool->availCCtx];\n            ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);\n            return cctx;\n    }   }\n    ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);\n    DEBUGLOG(5, \"create one more CCtx\");\n    return ZSTD_createCCtx_advanced(cctxPool->cMem);   /* note : can be NULL, when creation fails ! */\n}\n\nstatic void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)\n{\n    if (cctx==NULL) return;   /* compatibility with release on NULL */\n    ZSTD_pthread_mutex_lock(&pool->poolMutex);\n    if (pool->availCCtx < pool->totalCCtx)\n        pool->cctxs[pool->availCCtx++] = cctx;\n    else {\n        /* pool overflow : should not happen, since totalCCtx==nbWorkers */\n        DEBUGLOG(4, \"CCtx pool overflow : free cctx\");\n        ZSTD_freeCCtx(cctx);\n    }\n    ZSTD_pthread_mutex_unlock(&pool->poolMutex);\n}\n\n/* ====   Serial State   ==== */\n\ntypedef struct {\n    void const* start;\n    size_t size;\n} Range;\n\ntypedef struct {\n    /* All variables in the struct are protected by mutex. */\n    ZSTD_pthread_mutex_t mutex;\n    ZSTD_pthread_cond_t cond;\n    ZSTD_CCtx_params params;\n    ldmState_t ldmState;\n    XXH64_state_t xxhState;\n    unsigned nextJobID;\n    /* Protects ldmWindow.\n     * Must be acquired after the main mutex when acquiring both.\n     */\n    ZSTD_pthread_mutex_t ldmWindowMutex;\n    ZSTD_pthread_cond_t ldmWindowCond;  /* Signaled when ldmWindow is updated */\n    ZSTD_window_t ldmWindow;  /* A thread-safe copy of ldmState.window */\n} SerialState;\n\nstatic int\nZSTDMT_serialState_reset(SerialState* serialState,\n                         ZSTDMT_seqPool* seqPool,\n                         ZSTD_CCtx_params params,\n                         size_t jobSize,\n                         const void* dict, size_t const dictSize,\n                         ZSTD_dictContentType_e dictContentType)\n{\n    /* Adjust parameters */\n    if (params.ldmParams.enableLdm == ZSTD_ps_enable) {\n        DEBUGLOG(4, \"LDM window size = %u KB\", (1U << params.cParams.windowLog) >> 10);\n        ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);\n        assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);\n        assert(params.ldmParams.hashRateLog < 32);\n    } else {\n        ZSTD_memset(&params.ldmParams, 0, sizeof(params.ldmParams));\n    }\n    serialState->nextJobID = 0;\n    if (params.fParams.checksumFlag)\n        XXH64_reset(&serialState->xxhState, 0);\n    if (params.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_customMem cMem = params.customMem;\n        unsigned const hashLog = params.ldmParams.hashLog;\n        size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);\n        unsigned const bucketLog =\n            params.ldmParams.hashLog - params.ldmParams.bucketSizeLog;\n        unsigned const prevBucketLog =\n            serialState->params.ldmParams.hashLog -\n            serialState->params.ldmParams.bucketSizeLog;\n        size_t const numBuckets = (size_t)1 << bucketLog;\n        /* Size the seq pool tables */\n        ZSTDMT_setNbSeq(seqPool, ZSTD_ldm_getMaxNbSeq(params.ldmParams, jobSize));\n        /* Reset the window */\n        ZSTD_window_init(&serialState->ldmState.window);\n        /* Resize tables and output space if necessary. */\n        if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) {\n            ZSTD_customFree(serialState->ldmState.hashTable, cMem);\n            serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem);\n        }\n        if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) {\n            ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);\n            serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(numBuckets, cMem);\n        }\n        if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets)\n            return 1;\n        /* Zero the tables */\n        ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize);\n        ZSTD_memset(serialState->ldmState.bucketOffsets, 0, numBuckets);\n\n        /* Update window state and fill hash table with dict */\n        serialState->ldmState.loadedDictEnd = 0;\n        if (dictSize > 0) {\n            if (dictContentType == ZSTD_dct_rawContent) {\n                BYTE const* const dictEnd = (const BYTE*)dict + dictSize;\n                ZSTD_window_update(&serialState->ldmState.window, dict, dictSize, /* forceNonContiguous */ 0);\n                ZSTD_ldm_fillHashTable(&serialState->ldmState, (const BYTE*)dict, dictEnd, &params.ldmParams);\n                serialState->ldmState.loadedDictEnd = params.forceWindow ? 0 : (U32)(dictEnd - serialState->ldmState.window.base);\n            } else {\n                /* don't even load anything */\n            }\n        }\n\n        /* Initialize serialState's copy of ldmWindow. */\n        serialState->ldmWindow = serialState->ldmState.window;\n    }\n\n    serialState->params = params;\n    serialState->params.jobSize = (U32)jobSize;\n    return 0;\n}\n\nstatic int ZSTDMT_serialState_init(SerialState* serialState)\n{\n    int initError = 0;\n    ZSTD_memset(serialState, 0, sizeof(*serialState));\n    initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL);\n    initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL);\n    initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL);\n    initError |= ZSTD_pthread_cond_init(&serialState->ldmWindowCond, NULL);\n    return initError;\n}\n\nstatic void ZSTDMT_serialState_free(SerialState* serialState)\n{\n    ZSTD_customMem cMem = serialState->params.customMem;\n    ZSTD_pthread_mutex_destroy(&serialState->mutex);\n    ZSTD_pthread_cond_destroy(&serialState->cond);\n    ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex);\n    ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond);\n    ZSTD_customFree(serialState->ldmState.hashTable, cMem);\n    ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem);\n}\n\nstatic void\nZSTDMT_serialState_genSequences(SerialState* serialState,\n                                RawSeqStore_t* seqStore,\n                                Range src, unsigned jobID)\n{\n    /* Wait for our turn */\n    ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);\n    while (serialState->nextJobID < jobID) {\n        DEBUGLOG(5, \"wait for serialState->cond\");\n        ZSTD_pthread_cond_wait(&serialState->cond, &serialState->mutex);\n    }\n    /* A future job may error and skip our job */\n    if (serialState->nextJobID == jobID) {\n        /* It is now our turn, do any processing necessary */\n        if (serialState->params.ldmParams.enableLdm == ZSTD_ps_enable) {\n            size_t error;\n            DEBUGLOG(6, \"ZSTDMT_serialState_genSequences: LDM update\");\n            assert(seqStore->seq != NULL && seqStore->pos == 0 &&\n                   seqStore->size == 0 && seqStore->capacity > 0);\n            assert(src.size <= serialState->params.jobSize);\n            ZSTD_window_update(&serialState->ldmState.window, src.start, src.size, /* forceNonContiguous */ 0);\n            error = ZSTD_ldm_generateSequences(\n                &serialState->ldmState, seqStore,\n                &serialState->params.ldmParams, src.start, src.size);\n            /* We provide a large enough buffer to never fail. */\n            assert(!ZSTD_isError(error)); (void)error;\n            /* Update ldmWindow to match the ldmState.window and signal the main\n             * thread if it is waiting for a buffer.\n             */\n            ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex);\n            serialState->ldmWindow = serialState->ldmState.window;\n            ZSTD_pthread_cond_signal(&serialState->ldmWindowCond);\n            ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex);\n        }\n        if (serialState->params.fParams.checksumFlag && src.size > 0)\n            XXH64_update(&serialState->xxhState, src.start, src.size);\n    }\n    /* Now it is the next jobs turn */\n    serialState->nextJobID++;\n    ZSTD_pthread_cond_broadcast(&serialState->cond);\n    ZSTD_pthread_mutex_unlock(&serialState->mutex);\n}\n\nstatic void\nZSTDMT_serialState_applySequences(const SerialState* serialState, /* just for an assert() check */\n                                  ZSTD_CCtx* jobCCtx,\n                                  const RawSeqStore_t* seqStore)\n{\n    if (seqStore->size > 0) {\n        DEBUGLOG(5, \"ZSTDMT_serialState_applySequences: uploading %u external sequences\", (unsigned)seqStore->size);\n        assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable); (void)serialState;\n        assert(jobCCtx);\n        ZSTD_referenceExternalSequences(jobCCtx, seqStore->seq, seqStore->size);\n    }\n}\n\nstatic void ZSTDMT_serialState_ensureFinished(SerialState* serialState,\n                                              unsigned jobID, size_t cSize)\n{\n    ZSTD_PTHREAD_MUTEX_LOCK(&serialState->mutex);\n    if (serialState->nextJobID <= jobID) {\n        assert(ZSTD_isError(cSize)); (void)cSize;\n        DEBUGLOG(5, \"Skipping past job %u because of error\", jobID);\n        serialState->nextJobID = jobID + 1;\n        ZSTD_pthread_cond_broadcast(&serialState->cond);\n\n        ZSTD_PTHREAD_MUTEX_LOCK(&serialState->ldmWindowMutex);\n        ZSTD_window_clear(&serialState->ldmWindow);\n        ZSTD_pthread_cond_signal(&serialState->ldmWindowCond);\n        ZSTD_pthread_mutex_unlock(&serialState->ldmWindowMutex);\n    }\n    ZSTD_pthread_mutex_unlock(&serialState->mutex);\n\n}\n\n\n/* ------------------------------------------ */\n/* =====          Worker thread         ===== */\n/* ------------------------------------------ */\n\nstatic const Range kNullRange = { NULL, 0 };\n\ntypedef struct {\n    size_t   consumed;                 /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx */\n    size_t   cSize;                    /* SHARED - set0 by mtctx, then modified by worker AND read by mtctx, then set0 by mtctx */\n    ZSTD_pthread_mutex_t job_mutex;    /* Thread-safe - used by mtctx and worker */\n    ZSTD_pthread_cond_t job_cond;      /* Thread-safe - used by mtctx and worker */\n    ZSTDMT_CCtxPool* cctxPool;         /* Thread-safe - used by mtctx and (all) workers */\n    ZSTDMT_bufferPool* bufPool;        /* Thread-safe - used by mtctx and (all) workers */\n    ZSTDMT_seqPool* seqPool;           /* Thread-safe - used by mtctx and (all) workers */\n    SerialState* serial;               /* Thread-safe - used by mtctx and (all) workers */\n    Buffer dstBuff;                    /* set by worker (or mtctx), then read by worker & mtctx, then modified by mtctx => no barrier */\n    Range prefix;                      /* set by mtctx, then read by worker & mtctx => no barrier */\n    Range src;                         /* set by mtctx, then read by worker & mtctx => no barrier */\n    unsigned jobID;                    /* set by mtctx, then read by worker => no barrier */\n    unsigned firstJob;                 /* set by mtctx, then read by worker => no barrier */\n    unsigned lastJob;                  /* set by mtctx, then read by worker => no barrier */\n    ZSTD_CCtx_params params;           /* set by mtctx, then read by worker => no barrier */\n    const ZSTD_CDict* cdict;           /* set by mtctx, then read by worker => no barrier */\n    unsigned long long fullFrameSize;  /* set by mtctx, then read by worker => no barrier */\n    size_t   dstFlushed;               /* used only by mtctx */\n    unsigned frameChecksumNeeded;      /* used only by mtctx */\n} ZSTDMT_jobDescription;\n\n#define JOB_ERROR(e)                                \\\n    do {                                            \\\n        ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);   \\\n        job->cSize = e;                             \\\n        ZSTD_pthread_mutex_unlock(&job->job_mutex); \\\n        goto _endJob;                               \\\n    } while (0)\n\n/* ZSTDMT_compressionJob() is a POOL_function type */\nstatic void ZSTDMT_compressionJob(void* jobDescription)\n{\n    ZSTDMT_jobDescription* const job = (ZSTDMT_jobDescription*)jobDescription;\n    ZSTD_CCtx_params jobParams = job->params;   /* do not modify job->params ! copy it, modify the copy */\n    ZSTD_CCtx* const cctx = ZSTDMT_getCCtx(job->cctxPool);\n    RawSeqStore_t rawSeqStore = ZSTDMT_getSeq(job->seqPool);\n    Buffer dstBuff = job->dstBuff;\n    size_t lastCBlockSize = 0;\n\n    DEBUGLOG(5, \"ZSTDMT_compressionJob: job %u\", job->jobID);\n    /* resources */\n    if (cctx==NULL) JOB_ERROR(ERROR(memory_allocation));\n    if (dstBuff.start == NULL) {   /* streaming job : doesn't provide a dstBuffer */\n        dstBuff = ZSTDMT_getBuffer(job->bufPool);\n        if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation));\n        job->dstBuff = dstBuff;   /* this value can be read in ZSTDMT_flush, when it copies the whole job */\n    }\n    if (jobParams.ldmParams.enableLdm == ZSTD_ps_enable && rawSeqStore.seq == NULL)\n        JOB_ERROR(ERROR(memory_allocation));\n\n    /* Don't compute the checksum for chunks, since we compute it externally,\n     * but write it in the header.\n     */\n    if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;\n    /* Don't run LDM for the chunks, since we handle it externally */\n    jobParams.ldmParams.enableLdm = ZSTD_ps_disable;\n    /* Correct nbWorkers to 0. */\n    jobParams.nbWorkers = 0;\n\n\n    /* init */\n\n    /* Perform serial step as early as possible */\n    ZSTDMT_serialState_genSequences(job->serial, &rawSeqStore, job->src, job->jobID);\n\n    if (job->cdict) {\n        size_t const initError = ZSTD_compressBegin_advanced_internal(cctx, NULL, 0, ZSTD_dct_auto, ZSTD_dtlm_fast, job->cdict, &jobParams, job->fullFrameSize);\n        assert(job->firstJob);  /* only allowed for first job */\n        if (ZSTD_isError(initError)) JOB_ERROR(initError);\n    } else {\n        U64 const pledgedSrcSize = job->firstJob ? job->fullFrameSize : job->src.size;\n        {   size_t const forceWindowError = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_forceMaxWindow, !job->firstJob);\n            if (ZSTD_isError(forceWindowError)) JOB_ERROR(forceWindowError);\n        }\n        if (!job->firstJob) {\n            size_t const err = ZSTD_CCtxParams_setParameter(&jobParams, ZSTD_c_deterministicRefPrefix, 0);\n            if (ZSTD_isError(err)) JOB_ERROR(err);\n        }\n        DEBUGLOG(6, \"ZSTDMT_compressionJob: job %u: loading prefix of size %zu\", job->jobID, job->prefix.size);\n        {   size_t const initError = ZSTD_compressBegin_advanced_internal(cctx,\n                                        job->prefix.start, job->prefix.size, ZSTD_dct_rawContent,\n                                        ZSTD_dtlm_fast,\n                                        NULL, /*cdict*/\n                                        &jobParams, pledgedSrcSize);\n            if (ZSTD_isError(initError)) JOB_ERROR(initError);\n    }   }\n\n    /* External Sequences can only be applied after CCtx initialization */\n    ZSTDMT_serialState_applySequences(job->serial, cctx, &rawSeqStore);\n\n    if (!job->firstJob) {  /* flush and overwrite frame header when it's not first job */\n        size_t const hSize = ZSTD_compressContinue_public(cctx, dstBuff.start, dstBuff.capacity, job->src.start, 0);\n        if (ZSTD_isError(hSize)) JOB_ERROR(hSize);\n        DEBUGLOG(5, \"ZSTDMT_compressionJob: flush and overwrite %u bytes of frame header (not first job)\", (U32)hSize);\n        ZSTD_invalidateRepCodes(cctx);\n    }\n\n    /* compress the entire job by smaller chunks, for better granularity */\n    {   size_t const chunkSize = 4*ZSTD_BLOCKSIZE_MAX;\n        int const nbChunks = (int)((job->src.size + (chunkSize-1)) / chunkSize);\n        const BYTE* ip = (const BYTE*) job->src.start;\n        BYTE* const ostart = (BYTE*)dstBuff.start;\n        BYTE* op = ostart;\n        BYTE* oend = op + dstBuff.capacity;\n        int chunkNb;\n        if (sizeof(size_t) > sizeof(int)) assert(job->src.size < ((size_t)INT_MAX) * chunkSize);   /* check overflow */\n        DEBUGLOG(5, \"ZSTDMT_compressionJob: compress %u bytes in %i blocks\", (U32)job->src.size, nbChunks);\n        assert(job->cSize == 0);\n        for (chunkNb = 1; chunkNb < nbChunks; chunkNb++) {\n            size_t const cSize = ZSTD_compressContinue_public(cctx, op, oend-op, ip, chunkSize);\n            if (ZSTD_isError(cSize)) JOB_ERROR(cSize);\n            ip += chunkSize;\n            op += cSize; assert(op < oend);\n            /* stats */\n            ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);\n            job->cSize += cSize;\n            job->consumed = chunkSize * chunkNb;\n            DEBUGLOG(5, \"ZSTDMT_compressionJob: compress new block : cSize==%u bytes (total: %u)\",\n                        (U32)cSize, (U32)job->cSize);\n            ZSTD_pthread_cond_signal(&job->job_cond);   /* warns some more data is ready to be flushed */\n            ZSTD_pthread_mutex_unlock(&job->job_mutex);\n        }\n        /* last block */\n        assert(chunkSize > 0);\n        assert((chunkSize & (chunkSize - 1)) == 0);  /* chunkSize must be power of 2 for mask==(chunkSize-1) to work */\n        if ((nbChunks > 0) | job->lastJob /*must output a \"last block\" flag*/ ) {\n            size_t const lastBlockSize1 = job->src.size & (chunkSize-1);\n            size_t const lastBlockSize = ((lastBlockSize1==0) & (job->src.size>=chunkSize)) ? chunkSize : lastBlockSize1;\n            size_t const cSize = (job->lastJob) ?\n                 ZSTD_compressEnd_public(cctx, op, oend-op, ip, lastBlockSize) :\n                 ZSTD_compressContinue_public(cctx, op, oend-op, ip, lastBlockSize);\n            if (ZSTD_isError(cSize)) JOB_ERROR(cSize);\n            lastCBlockSize = cSize;\n    }   }\n    if (!job->firstJob) {\n        /* Double check that we don't have an ext-dict, because then our\n         * repcode invalidation doesn't work.\n         */\n        assert(!ZSTD_window_hasExtDict(cctx->blockState.matchState.window));\n    }\n    ZSTD_CCtx_trace(cctx, 0);\n\n_endJob:\n    ZSTDMT_serialState_ensureFinished(job->serial, job->jobID, job->cSize);\n    if (job->prefix.size > 0)\n        DEBUGLOG(5, \"Finished with prefix: %zx\", (size_t)job->prefix.start);\n    DEBUGLOG(5, \"Finished with source: %zx\", (size_t)job->src.start);\n    /* release resources */\n    ZSTDMT_releaseSeq(job->seqPool, rawSeqStore);\n    ZSTDMT_releaseCCtx(job->cctxPool, cctx);\n    /* report */\n    ZSTD_PTHREAD_MUTEX_LOCK(&job->job_mutex);\n    if (ZSTD_isError(job->cSize)) assert(lastCBlockSize == 0);\n    job->cSize += lastCBlockSize;\n    job->consumed = job->src.size;  /* when job->consumed == job->src.size , compression job is presumed completed */\n    ZSTD_pthread_cond_signal(&job->job_cond);\n    ZSTD_pthread_mutex_unlock(&job->job_mutex);\n}\n\n\n/* ------------------------------------------ */\n/* =====   Multi-threaded compression   ===== */\n/* ------------------------------------------ */\n\ntypedef struct {\n    Range prefix;         /* read-only non-owned prefix buffer */\n    Buffer buffer;\n    size_t filled;\n} InBuff_t;\n\ntypedef struct {\n  BYTE* buffer;     /* The round input buffer. All jobs get references\n                     * to pieces of the buffer. ZSTDMT_tryGetInputRange()\n                     * handles handing out job input buffers, and makes\n                     * sure it doesn't overlap with any pieces still in use.\n                     */\n  size_t capacity;  /* The capacity of buffer. */\n  size_t pos;       /* The position of the current inBuff in the round\n                     * buffer. Updated past the end if the inBuff once\n                     * the inBuff is sent to the worker thread.\n                     * pos <= capacity.\n                     */\n} RoundBuff_t;\n\nstatic const RoundBuff_t kNullRoundBuff = {NULL, 0, 0};\n\n#define RSYNC_LENGTH 32\n/* Don't create chunks smaller than the zstd block size.\n * This stops us from regressing compression ratio too much,\n * and ensures our output fits in ZSTD_compressBound().\n *\n * If this is shrunk < ZSTD_BLOCKSIZELOG_MIN then\n * ZSTD_COMPRESSBOUND() will need to be updated.\n */\n#define RSYNC_MIN_BLOCK_LOG ZSTD_BLOCKSIZELOG_MAX\n#define RSYNC_MIN_BLOCK_SIZE (1<<RSYNC_MIN_BLOCK_LOG)\n\ntypedef struct {\n  U64 hash;\n  U64 hitMask;\n  U64 primePower;\n} RSyncState_t;\n\nstruct ZSTDMT_CCtx_s {\n    POOL_ctx* factory;\n    ZSTDMT_jobDescription* jobs;\n    ZSTDMT_bufferPool* bufPool;\n    ZSTDMT_CCtxPool* cctxPool;\n    ZSTDMT_seqPool* seqPool;\n    ZSTD_CCtx_params params;\n    size_t targetSectionSize;\n    size_t targetPrefixSize;\n    int jobReady;        /* 1 => one job is already prepared, but pool has shortage of workers. Don't create a new job. */\n    InBuff_t inBuff;\n    RoundBuff_t roundBuff;\n    SerialState serial;\n    RSyncState_t rsync;\n    unsigned jobIDMask;\n    unsigned doneJobID;\n    unsigned nextJobID;\n    unsigned frameEnded;\n    unsigned allJobsCompleted;\n    unsigned long long frameContentSize;\n    unsigned long long consumed;\n    unsigned long long produced;\n    ZSTD_customMem cMem;\n    ZSTD_CDict* cdictLocal;\n    const ZSTD_CDict* cdict;\n    unsigned providedFactory: 1;\n};\n\nstatic void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem)\n{\n    U32 jobNb;\n    if (jobTable == NULL) return;\n    for (jobNb=0; jobNb<nbJobs; jobNb++) {\n        ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex);\n        ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond);\n    }\n    ZSTD_customFree(jobTable, cMem);\n}\n\n/* ZSTDMT_allocJobsTable()\n * allocate and init a job table.\n * update *nbJobsPtr to next power of 2 value, as size of table */\nstatic ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_customMem cMem)\n{\n    U32 const nbJobsLog2 = ZSTD_highbit32(*nbJobsPtr) + 1;\n    U32 const nbJobs = 1 << nbJobsLog2;\n    U32 jobNb;\n    ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*)\n                ZSTD_customCalloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem);\n    int initError = 0;\n    if (jobTable==NULL) return NULL;\n    *nbJobsPtr = nbJobs;\n    for (jobNb=0; jobNb<nbJobs; jobNb++) {\n        initError |= ZSTD_pthread_mutex_init(&jobTable[jobNb].job_mutex, NULL);\n        initError |= ZSTD_pthread_cond_init(&jobTable[jobNb].job_cond, NULL);\n    }\n    if (initError != 0) {\n        ZSTDMT_freeJobsTable(jobTable, nbJobs, cMem);\n        return NULL;\n    }\n    return jobTable;\n}\n\nstatic size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) {\n    U32 nbJobs = nbWorkers + 2;\n    if (nbJobs > mtctx->jobIDMask+1) {  /* need more job capacity */\n        ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);\n        mtctx->jobIDMask = 0;\n        mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, mtctx->cMem);\n        if (mtctx->jobs==NULL) return ERROR(memory_allocation);\n        assert((nbJobs != 0) && ((nbJobs & (nbJobs - 1)) == 0));  /* ensure nbJobs is a power of 2 */\n        mtctx->jobIDMask = nbJobs - 1;\n    }\n    return 0;\n}\n\n\n/* ZSTDMT_CCtxParam_setNbWorkers():\n * Internal use only */\nstatic size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers)\n{\n    return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers);\n}\n\nMEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)\n{\n    ZSTDMT_CCtx* mtctx;\n    U32 nbJobs = nbWorkers + 2;\n    int initError;\n    DEBUGLOG(3, \"ZSTDMT_createCCtx_advanced (nbWorkers = %u)\", nbWorkers);\n\n    if (nbWorkers < 1) return NULL;\n    nbWorkers = MIN(nbWorkers , ZSTDMT_NBWORKERS_MAX);\n    if ((cMem.customAlloc!=NULL) ^ (cMem.customFree!=NULL))\n        /* invalid custom allocator */\n        return NULL;\n\n    mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem);\n    if (!mtctx) return NULL;\n    ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);\n    mtctx->cMem = cMem;\n    mtctx->allJobsCompleted = 1;\n    if (pool != NULL) {\n      mtctx->factory = pool;\n      mtctx->providedFactory = 1;\n    }\n    else {\n      mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem);\n      mtctx->providedFactory = 0;\n    }\n    mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);\n    assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0);  /* ensure nbJobs is a power of 2 */\n    mtctx->jobIDMask = nbJobs - 1;\n    mtctx->bufPool = ZSTDMT_createBufferPool(BUF_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);\n    mtctx->cctxPool = ZSTDMT_createCCtxPool(nbWorkers, cMem);\n    mtctx->seqPool = ZSTDMT_createSeqPool(nbWorkers, cMem);\n    initError = ZSTDMT_serialState_init(&mtctx->serial);\n    mtctx->roundBuff = kNullRoundBuff;\n    if (!mtctx->factory | !mtctx->jobs | !mtctx->bufPool | !mtctx->cctxPool | !mtctx->seqPool | initError) {\n        ZSTDMT_freeCCtx(mtctx);\n        return NULL;\n    }\n    DEBUGLOG(3, \"mt_cctx created, for %u threads\", nbWorkers);\n    return mtctx;\n}\n\nZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool)\n{\n#ifdef ZSTD_MULTITHREAD\n    return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool);\n#else\n    (void)nbWorkers;\n    (void)cMem;\n    (void)pool;\n    return NULL;\n#endif\n}\n\n\n/* ZSTDMT_releaseAllJobResources() :\n * note : ensure all workers are killed first ! */\nstatic void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx)\n{\n    unsigned jobID;\n    DEBUGLOG(3, \"ZSTDMT_releaseAllJobResources\");\n    for (jobID=0; jobID <= mtctx->jobIDMask; jobID++) {\n        /* Copy the mutex/cond out */\n        ZSTD_pthread_mutex_t const mutex = mtctx->jobs[jobID].job_mutex;\n        ZSTD_pthread_cond_t const cond = mtctx->jobs[jobID].job_cond;\n\n        DEBUGLOG(4, \"job%02u: release dst address %08X\", jobID, (U32)(size_t)mtctx->jobs[jobID].dstBuff.start);\n        ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff);\n\n        /* Clear the job description, but keep the mutex/cond */\n        ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID]));\n        mtctx->jobs[jobID].job_mutex = mutex;\n        mtctx->jobs[jobID].job_cond = cond;\n    }\n    mtctx->inBuff.buffer = g_nullBuffer;\n    mtctx->inBuff.filled = 0;\n    mtctx->allJobsCompleted = 1;\n}\n\nstatic void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx)\n{\n    DEBUGLOG(4, \"ZSTDMT_waitForAllJobsCompleted\");\n    while (mtctx->doneJobID < mtctx->nextJobID) {\n        unsigned const jobID = mtctx->doneJobID & mtctx->jobIDMask;\n        ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex);\n        while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) {\n            DEBUGLOG(4, \"waiting for jobCompleted signal from job %u\", mtctx->doneJobID);   /* we want to block when waiting for data to flush */\n            ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex);\n        }\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex);\n        mtctx->doneJobID++;\n    }\n}\n\nsize_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx)\n{\n    if (mtctx==NULL) return 0;   /* compatible with free on NULL */\n    if (!mtctx->providedFactory)\n        POOL_free(mtctx->factory);   /* stop and free worker threads */\n    ZSTDMT_releaseAllJobResources(mtctx);  /* release job resources into pools first */\n    ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem);\n    ZSTDMT_freeBufferPool(mtctx->bufPool);\n    ZSTDMT_freeCCtxPool(mtctx->cctxPool);\n    ZSTDMT_freeSeqPool(mtctx->seqPool);\n    ZSTDMT_serialState_free(&mtctx->serial);\n    ZSTD_freeCDict(mtctx->cdictLocal);\n    if (mtctx->roundBuff.buffer)\n        ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);\n    ZSTD_customFree(mtctx, mtctx->cMem);\n    return 0;\n}\n\nsize_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx)\n{\n    if (mtctx == NULL) return 0;   /* supports sizeof NULL */\n    return sizeof(*mtctx)\n            + POOL_sizeof(mtctx->factory)\n            + ZSTDMT_sizeof_bufferPool(mtctx->bufPool)\n            + (mtctx->jobIDMask+1) * sizeof(ZSTDMT_jobDescription)\n            + ZSTDMT_sizeof_CCtxPool(mtctx->cctxPool)\n            + ZSTDMT_sizeof_seqPool(mtctx->seqPool)\n            + ZSTD_sizeof_CDict(mtctx->cdictLocal)\n            + mtctx->roundBuff.capacity;\n}\n\n\n/* ZSTDMT_resize() :\n * @return : error code if fails, 0 on success */\nstatic size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)\n{\n    if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);\n    FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , \"\");\n    mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, BUF_POOL_MAX_NB_BUFFERS(nbWorkers));\n    if (mtctx->bufPool == NULL) return ERROR(memory_allocation);\n    mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);\n    if (mtctx->cctxPool == NULL) return ERROR(memory_allocation);\n    mtctx->seqPool = ZSTDMT_expandSeqPool(mtctx->seqPool, nbWorkers);\n    if (mtctx->seqPool == NULL) return ERROR(memory_allocation);\n    ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers);\n    return 0;\n}\n\n\n/*! ZSTDMT_updateCParams_whileCompressing() :\n *  Updates a selected set of compression parameters, remaining compatible with currently active frame.\n *  New parameters will be applied to next compression job. */\nvoid ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams)\n{\n    U32 const saved_wlog = mtctx->params.cParams.windowLog;   /* Do not modify windowLog while compressing */\n    int const compressionLevel = cctxParams->compressionLevel;\n    DEBUGLOG(5, \"ZSTDMT_updateCParams_whileCompressing (level:%i)\",\n                compressionLevel);\n    mtctx->params.compressionLevel = compressionLevel;\n    {   ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);\n        cParams.windowLog = saved_wlog;\n        mtctx->params.cParams = cParams;\n    }\n}\n\n/* ZSTDMT_getFrameProgression():\n * tells how much data has been consumed (input) and produced (output) for current frame.\n * able to count progression inside worker threads.\n * Note : mutex will be acquired during statistics collection inside workers. */\nZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx)\n{\n    ZSTD_frameProgression fps;\n    DEBUGLOG(5, \"ZSTDMT_getFrameProgression\");\n    fps.ingested = mtctx->consumed + mtctx->inBuff.filled;\n    fps.consumed = mtctx->consumed;\n    fps.produced = fps.flushed = mtctx->produced;\n    fps.currentJobID = mtctx->nextJobID;\n    fps.nbActiveWorkers = 0;\n    {   unsigned jobNb;\n        unsigned lastJobNb = mtctx->nextJobID + mtctx->jobReady; assert(mtctx->jobReady <= 1);\n        DEBUGLOG(6, \"ZSTDMT_getFrameProgression: jobs: from %u to <%u (jobReady:%u)\",\n                    mtctx->doneJobID, lastJobNb, mtctx->jobReady);\n        for (jobNb = mtctx->doneJobID ; jobNb < lastJobNb ; jobNb++) {\n            unsigned const wJobID = jobNb & mtctx->jobIDMask;\n            ZSTDMT_jobDescription* jobPtr = &mtctx->jobs[wJobID];\n            ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);\n            {   size_t const cResult = jobPtr->cSize;\n                size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;\n                size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;\n                assert(flushed <= produced);\n                fps.ingested += jobPtr->src.size;\n                fps.consumed += jobPtr->consumed;\n                fps.produced += produced;\n                fps.flushed  += flushed;\n                fps.nbActiveWorkers += (jobPtr->consumed < jobPtr->src.size);\n            }\n            ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n        }\n    }\n    return fps;\n}\n\n\nsize_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)\n{\n    size_t toFlush;\n    unsigned const jobID = mtctx->doneJobID;\n    assert(jobID <= mtctx->nextJobID);\n    if (jobID == mtctx->nextJobID) return 0;   /* no active job => nothing to flush */\n\n    /* look into oldest non-fully-flushed job */\n    {   unsigned const wJobID = jobID & mtctx->jobIDMask;\n        ZSTDMT_jobDescription* const jobPtr = &mtctx->jobs[wJobID];\n        ZSTD_pthread_mutex_lock(&jobPtr->job_mutex);\n        {   size_t const cResult = jobPtr->cSize;\n            size_t const produced = ZSTD_isError(cResult) ? 0 : cResult;\n            size_t const flushed = ZSTD_isError(cResult) ? 0 : jobPtr->dstFlushed;\n            assert(flushed <= produced);\n            assert(jobPtr->consumed <= jobPtr->src.size);\n            toFlush = produced - flushed;\n            /* if toFlush==0, nothing is available to flush.\n             * However, jobID is expected to still be active:\n             * if jobID was already completed and fully flushed,\n             * ZSTDMT_flushProduced() should have already moved onto next job.\n             * Therefore, some input has not yet been consumed. */\n            if (toFlush==0) {\n                assert(jobPtr->consumed < jobPtr->src.size);\n            }\n        }\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n    }\n\n    return toFlush;\n}\n\n\n/* ------------------------------------------ */\n/* =====   Multi-threaded compression   ===== */\n/* ------------------------------------------ */\n\nstatic unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params)\n{\n    unsigned jobLog;\n    if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n        /* In Long Range Mode, the windowLog is typically oversized.\n         * In which case, it's preferable to determine the jobSize\n         * based on cycleLog instead. */\n        jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3);\n    } else {\n        jobLog = MAX(20, params->cParams.windowLog + 2);\n    }\n    return MIN(jobLog, (unsigned)ZSTDMT_JOBLOG_MAX);\n}\n\nstatic int ZSTDMT_overlapLog_default(ZSTD_strategy strat)\n{\n    switch(strat)\n    {\n        case ZSTD_btultra2:\n            return 9;\n        case ZSTD_btultra:\n        case ZSTD_btopt:\n            return 8;\n        case ZSTD_btlazy2:\n        case ZSTD_lazy2:\n            return 7;\n        case ZSTD_lazy:\n        case ZSTD_greedy:\n        case ZSTD_dfast:\n        case ZSTD_fast:\n        default:;\n    }\n    return 6;\n}\n\nstatic int ZSTDMT_overlapLog(int ovlog, ZSTD_strategy strat)\n{\n    assert(0 <= ovlog && ovlog <= 9);\n    if (ovlog == 0) return ZSTDMT_overlapLog_default(strat);\n    return ovlog;\n}\n\nstatic size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)\n{\n    int const overlapRLog = 9 - ZSTDMT_overlapLog(params->overlapLog, params->cParams.strategy);\n    int ovLog = (overlapRLog >= 8) ? 0 : (params->cParams.windowLog - overlapRLog);\n    assert(0 <= overlapRLog && overlapRLog <= 8);\n    if (params->ldmParams.enableLdm == ZSTD_ps_enable) {\n        /* In Long Range Mode, the windowLog is typically oversized.\n         * In which case, it's preferable to determine the jobSize\n         * based on chainLog instead.\n         * Then, ovLog becomes a fraction of the jobSize, rather than windowSize */\n        ovLog = MIN(params->cParams.windowLog, ZSTDMT_computeTargetJobLog(params) - 2)\n                - overlapRLog;\n    }\n    assert(0 <= ovLog && ovLog <= ZSTD_WINDOWLOG_MAX);\n    DEBUGLOG(4, \"overlapLog : %i\", params->overlapLog);\n    DEBUGLOG(4, \"overlap size : %i\", 1 << ovLog);\n    return (ovLog==0) ? 0 : (size_t)1 << ovLog;\n}\n\n/* ====================================== */\n/* =======      Streaming API     ======= */\n/* ====================================== */\n\nsize_t ZSTDMT_initCStream_internal(\n        ZSTDMT_CCtx* mtctx,\n        const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,\n        const ZSTD_CDict* cdict, ZSTD_CCtx_params params,\n        unsigned long long pledgedSrcSize)\n{\n    DEBUGLOG(4, \"ZSTDMT_initCStream_internal (pledgedSrcSize=%u, nbWorkers=%u, cctxPool=%u)\",\n                (U32)pledgedSrcSize, params.nbWorkers, mtctx->cctxPool->totalCCtx);\n\n    /* params supposed partially fully validated at this point */\n    assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams)));\n    assert(!((dict) && (cdict)));  /* either dict or cdict, not both */\n\n    /* init */\n    if (params.nbWorkers != mtctx->params.nbWorkers)\n        FORWARD_IF_ERROR( ZSTDMT_resize(mtctx, (unsigned)params.nbWorkers) , \"\");\n\n    if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN;\n    if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX;\n\n    if (mtctx->allJobsCompleted == 0) {   /* previous compression not correctly finished */\n        ZSTDMT_waitForAllJobsCompleted(mtctx);\n        ZSTDMT_releaseAllJobResources(mtctx);\n        mtctx->allJobsCompleted = 1;\n    }\n\n    mtctx->params = params;\n    mtctx->frameContentSize = pledgedSrcSize;\n    ZSTD_freeCDict(mtctx->cdictLocal);\n    if (dict) {\n        mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,\n                                                    ZSTD_dlm_byCopy, dictContentType, /* note : a loadPrefix becomes an internal CDict */\n                                                    params.cParams, mtctx->cMem);\n        mtctx->cdict = mtctx->cdictLocal;\n        if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation);\n    } else {\n        mtctx->cdictLocal = NULL;\n        mtctx->cdict = cdict;\n    }\n\n    mtctx->targetPrefixSize = ZSTDMT_computeOverlapSize(&params);\n    DEBUGLOG(4, \"overlapLog=%i => %u KB\", params.overlapLog, (U32)(mtctx->targetPrefixSize>>10));\n    mtctx->targetSectionSize = params.jobSize;\n    if (mtctx->targetSectionSize == 0) {\n        mtctx->targetSectionSize = 1ULL << ZSTDMT_computeTargetJobLog(&params);\n    }\n    assert(mtctx->targetSectionSize <= (size_t)ZSTDMT_JOBSIZE_MAX);\n\n    if (params.rsyncable) {\n        /* Aim for the targetsectionSize as the average job size. */\n        U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10);\n        U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10);\n        /* We refuse to create jobs < RSYNC_MIN_BLOCK_SIZE bytes, so make sure our\n         * expected job size is at least 4x larger. */\n        assert(rsyncBits >= RSYNC_MIN_BLOCK_LOG + 2);\n        DEBUGLOG(4, \"rsyncLog = %u\", rsyncBits);\n        mtctx->rsync.hash = 0;\n        mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;\n        mtctx->rsync.primePower = ZSTD_rollingHash_primePower(RSYNC_LENGTH);\n    }\n    if (mtctx->targetSectionSize < mtctx->targetPrefixSize) mtctx->targetSectionSize = mtctx->targetPrefixSize;  /* job size must be >= overlap size */\n    DEBUGLOG(4, \"Job Size : %u KB (note : set to %u)\", (U32)(mtctx->targetSectionSize>>10), (U32)params.jobSize);\n    DEBUGLOG(4, \"inBuff Size : %u KB\", (U32)(mtctx->targetSectionSize>>10));\n    ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize));\n    {\n        /* If ldm is enabled we need windowSize space. */\n        size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? (1U << mtctx->params.cParams.windowLog) : 0;\n        /* Two buffers of slack, plus extra space for the overlap\n         * This is the minimum slack that LDM works with. One extra because\n         * flush might waste up to targetSectionSize-1 bytes. Another extra\n         * for the overlap (if > 0), then one to fill which doesn't overlap\n         * with the LDM window.\n         */\n        size_t const nbSlackBuffers = 2 + (mtctx->targetPrefixSize > 0);\n        size_t const slackSize = mtctx->targetSectionSize * nbSlackBuffers;\n        /* Compute the total size, and always have enough slack */\n        size_t const nbWorkers = MAX(mtctx->params.nbWorkers, 1);\n        size_t const sectionsSize = mtctx->targetSectionSize * nbWorkers;\n        size_t const capacity = MAX(windowSize, sectionsSize) + slackSize;\n        if (mtctx->roundBuff.capacity < capacity) {\n            if (mtctx->roundBuff.buffer)\n                ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem);\n            mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem);\n            if (mtctx->roundBuff.buffer == NULL) {\n                mtctx->roundBuff.capacity = 0;\n                return ERROR(memory_allocation);\n            }\n            mtctx->roundBuff.capacity = capacity;\n        }\n    }\n    DEBUGLOG(4, \"roundBuff capacity : %u KB\", (U32)(mtctx->roundBuff.capacity>>10));\n    mtctx->roundBuff.pos = 0;\n    mtctx->inBuff.buffer = g_nullBuffer;\n    mtctx->inBuff.filled = 0;\n    mtctx->inBuff.prefix = kNullRange;\n    mtctx->doneJobID = 0;\n    mtctx->nextJobID = 0;\n    mtctx->frameEnded = 0;\n    mtctx->allJobsCompleted = 0;\n    mtctx->consumed = 0;\n    mtctx->produced = 0;\n\n    /* update dictionary */\n    ZSTD_freeCDict(mtctx->cdictLocal);\n    mtctx->cdictLocal = NULL;\n    mtctx->cdict = NULL;\n    if (dict) {\n        if (dictContentType == ZSTD_dct_rawContent) {\n            mtctx->inBuff.prefix.start = (const BYTE*)dict;\n            mtctx->inBuff.prefix.size = dictSize;\n        } else {\n            /* note : a loadPrefix becomes an internal CDict */\n            mtctx->cdictLocal = ZSTD_createCDict_advanced(dict, dictSize,\n                                                        ZSTD_dlm_byRef, dictContentType,\n                                                        params.cParams, mtctx->cMem);\n            mtctx->cdict = mtctx->cdictLocal;\n            if (mtctx->cdictLocal == NULL) return ERROR(memory_allocation);\n        }\n    } else {\n        mtctx->cdict = cdict;\n    }\n\n    if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, mtctx->targetSectionSize,\n                                 dict, dictSize, dictContentType))\n        return ERROR(memory_allocation);\n\n\n    return 0;\n}\n\n\n/* ZSTDMT_writeLastEmptyBlock()\n * Write a single empty block with an end-of-frame to finish a frame.\n * Job must be created from streaming variant.\n * This function is always successful if expected conditions are fulfilled.\n */\nstatic void ZSTDMT_writeLastEmptyBlock(ZSTDMT_jobDescription* job)\n{\n    assert(job->lastJob == 1);\n    assert(job->src.size == 0);   /* last job is empty -> will be simplified into a last empty block */\n    assert(job->firstJob == 0);   /* cannot be first job, as it also needs to create frame header */\n    assert(job->dstBuff.start == NULL);   /* invoked from streaming variant only (otherwise, dstBuff might be user's output) */\n    job->dstBuff = ZSTDMT_getBuffer(job->bufPool);\n    if (job->dstBuff.start == NULL) {\n      job->cSize = ERROR(memory_allocation);\n      return;\n    }\n    assert(job->dstBuff.capacity >= ZSTD_blockHeaderSize);   /* no buffer should ever be that small */\n    job->src = kNullRange;\n    job->cSize = ZSTD_writeLastEmptyBlock(job->dstBuff.start, job->dstBuff.capacity);\n    assert(!ZSTD_isError(job->cSize));\n    assert(job->consumed == 0);\n}\n\nstatic size_t ZSTDMT_createCompressionJob(ZSTDMT_CCtx* mtctx, size_t srcSize, ZSTD_EndDirective endOp)\n{\n    unsigned const jobID = mtctx->nextJobID & mtctx->jobIDMask;\n    int const endFrame = (endOp == ZSTD_e_end);\n\n    if (mtctx->nextJobID > mtctx->doneJobID + mtctx->jobIDMask) {\n        DEBUGLOG(5, \"ZSTDMT_createCompressionJob: will not create new job : table is full\");\n        assert((mtctx->nextJobID & mtctx->jobIDMask) == (mtctx->doneJobID & mtctx->jobIDMask));\n        return 0;\n    }\n\n    if (!mtctx->jobReady) {\n        BYTE const* src = (BYTE const*)mtctx->inBuff.buffer.start;\n        DEBUGLOG(5, \"ZSTDMT_createCompressionJob: preparing job %u to compress %u bytes with %u preload \",\n                    mtctx->nextJobID, (U32)srcSize, (U32)mtctx->inBuff.prefix.size);\n        mtctx->jobs[jobID].src.start = src;\n        mtctx->jobs[jobID].src.size = srcSize;\n        assert(mtctx->inBuff.filled >= srcSize);\n        mtctx->jobs[jobID].prefix = mtctx->inBuff.prefix;\n        mtctx->jobs[jobID].consumed = 0;\n        mtctx->jobs[jobID].cSize = 0;\n        mtctx->jobs[jobID].params = mtctx->params;\n        mtctx->jobs[jobID].cdict = mtctx->nextJobID==0 ? mtctx->cdict : NULL;\n        mtctx->jobs[jobID].fullFrameSize = mtctx->frameContentSize;\n        mtctx->jobs[jobID].dstBuff = g_nullBuffer;\n        mtctx->jobs[jobID].cctxPool = mtctx->cctxPool;\n        mtctx->jobs[jobID].bufPool = mtctx->bufPool;\n        mtctx->jobs[jobID].seqPool = mtctx->seqPool;\n        mtctx->jobs[jobID].serial = &mtctx->serial;\n        mtctx->jobs[jobID].jobID = mtctx->nextJobID;\n        mtctx->jobs[jobID].firstJob = (mtctx->nextJobID==0);\n        mtctx->jobs[jobID].lastJob = endFrame;\n        mtctx->jobs[jobID].frameChecksumNeeded = mtctx->params.fParams.checksumFlag && endFrame && (mtctx->nextJobID>0);\n        mtctx->jobs[jobID].dstFlushed = 0;\n\n        /* Update the round buffer pos and clear the input buffer to be reset */\n        mtctx->roundBuff.pos += srcSize;\n        mtctx->inBuff.buffer = g_nullBuffer;\n        mtctx->inBuff.filled = 0;\n        /* Set the prefix for next job */\n        if (!endFrame) {\n            size_t const newPrefixSize = MIN(srcSize, mtctx->targetPrefixSize);\n            mtctx->inBuff.prefix.start = src + srcSize - newPrefixSize;\n            mtctx->inBuff.prefix.size = newPrefixSize;\n        } else {   /* endFrame==1 => no need for another input buffer */\n            mtctx->inBuff.prefix = kNullRange;\n            mtctx->frameEnded = endFrame;\n            if (mtctx->nextJobID == 0) {\n                /* single job exception : checksum is already calculated directly within worker thread */\n                mtctx->params.fParams.checksumFlag = 0;\n        }   }\n\n        if ( (srcSize == 0)\n          && (mtctx->nextJobID>0)/*single job must also write frame header*/ ) {\n            DEBUGLOG(5, \"ZSTDMT_createCompressionJob: creating a last empty block to end frame\");\n            assert(endOp == ZSTD_e_end);  /* only possible case : need to end the frame with an empty last block */\n            ZSTDMT_writeLastEmptyBlock(mtctx->jobs + jobID);\n            mtctx->nextJobID++;\n            return 0;\n        }\n    }\n\n    DEBUGLOG(5, \"ZSTDMT_createCompressionJob: posting job %u : %u bytes  (end:%u, jobNb == %u (mod:%u))\",\n                mtctx->nextJobID,\n                (U32)mtctx->jobs[jobID].src.size,\n                mtctx->jobs[jobID].lastJob,\n                mtctx->nextJobID,\n                jobID);\n    if (POOL_tryAdd(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[jobID])) {\n        mtctx->nextJobID++;\n        mtctx->jobReady = 0;\n    } else {\n        DEBUGLOG(5, \"ZSTDMT_createCompressionJob: no worker available for job %u\", mtctx->nextJobID);\n        mtctx->jobReady = 1;\n    }\n    return 0;\n}\n\n\n/*! ZSTDMT_flushProduced() :\n *  flush whatever data has been produced but not yet flushed in current job.\n *  move to next job if current one is fully flushed.\n * `output` : `pos` will be updated with amount of data flushed .\n * `blockToFlush` : if >0, the function will block and wait if there is no data available to flush .\n * @return : amount of data remaining within internal buffer, 0 if no more, 1 if unknown but > 0, or an error code */\nstatic size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, unsigned blockToFlush, ZSTD_EndDirective end)\n{\n    unsigned const wJobID = mtctx->doneJobID & mtctx->jobIDMask;\n    DEBUGLOG(5, \"ZSTDMT_flushProduced (blocking:%u , job %u <= %u)\",\n                blockToFlush, mtctx->doneJobID, mtctx->nextJobID);\n    assert(output->size >= output->pos);\n\n    ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex);\n    if (  blockToFlush\n      && (mtctx->doneJobID < mtctx->nextJobID) ) {\n        assert(mtctx->jobs[wJobID].dstFlushed <= mtctx->jobs[wJobID].cSize);\n        while (mtctx->jobs[wJobID].dstFlushed == mtctx->jobs[wJobID].cSize) {  /* nothing to flush */\n            if (mtctx->jobs[wJobID].consumed == mtctx->jobs[wJobID].src.size) {\n                DEBUGLOG(5, \"job %u is completely consumed (%u == %u) => don't wait for cond, there will be none\",\n                            mtctx->doneJobID, (U32)mtctx->jobs[wJobID].consumed, (U32)mtctx->jobs[wJobID].src.size);\n                break;\n            }\n            DEBUGLOG(5, \"waiting for something to flush from job %u (currently flushed: %u bytes)\",\n                        mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);\n            ZSTD_pthread_cond_wait(&mtctx->jobs[wJobID].job_cond, &mtctx->jobs[wJobID].job_mutex);  /* block when nothing to flush but some to come */\n    }   }\n\n    /* try to flush something */\n    {   size_t cSize = mtctx->jobs[wJobID].cSize;                  /* shared */\n        size_t const srcConsumed = mtctx->jobs[wJobID].consumed;   /* shared */\n        size_t const srcSize = mtctx->jobs[wJobID].src.size;       /* read-only, could be done after mutex lock, but no-declaration-after-statement */\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n        if (ZSTD_isError(cSize)) {\n            DEBUGLOG(5, \"ZSTDMT_flushProduced: job %u : compression error detected : %s\",\n                        mtctx->doneJobID, ZSTD_getErrorName(cSize));\n            ZSTDMT_waitForAllJobsCompleted(mtctx);\n            ZSTDMT_releaseAllJobResources(mtctx);\n            return cSize;\n        }\n        /* add frame checksum if necessary (can only happen once) */\n        assert(srcConsumed <= srcSize);\n        if ( (srcConsumed == srcSize)   /* job completed -> worker no longer active */\n          && mtctx->jobs[wJobID].frameChecksumNeeded ) {\n            U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState);\n            DEBUGLOG(4, \"ZSTDMT_flushProduced: writing checksum : %08X \\n\", checksum);\n            MEM_writeLE32((char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].cSize, checksum);\n            cSize += 4;\n            mtctx->jobs[wJobID].cSize += 4;  /* can write this shared value, as worker is no longer active */\n            mtctx->jobs[wJobID].frameChecksumNeeded = 0;\n        }\n\n        if (cSize > 0) {   /* compression is ongoing or completed */\n            size_t const toFlush = MIN(cSize - mtctx->jobs[wJobID].dstFlushed, output->size - output->pos);\n            DEBUGLOG(5, \"ZSTDMT_flushProduced: Flushing %u bytes from job %u (completion:%u/%u, generated:%u)\",\n                        (U32)toFlush, mtctx->doneJobID, (U32)srcConsumed, (U32)srcSize, (U32)cSize);\n            assert(mtctx->doneJobID < mtctx->nextJobID);\n            assert(cSize >= mtctx->jobs[wJobID].dstFlushed);\n            assert(mtctx->jobs[wJobID].dstBuff.start != NULL);\n            if (toFlush > 0) {\n                ZSTD_memcpy((char*)output->dst + output->pos,\n                    (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed,\n                    toFlush);\n            }\n            output->pos += toFlush;\n            mtctx->jobs[wJobID].dstFlushed += toFlush;  /* can write : this value is only used by mtctx */\n\n            if ( (srcConsumed == srcSize)    /* job is completed */\n              && (mtctx->jobs[wJobID].dstFlushed == cSize) ) {   /* output buffer fully flushed => free this job position */\n                DEBUGLOG(5, \"Job %u completed (%u bytes), moving to next one\",\n                        mtctx->doneJobID, (U32)mtctx->jobs[wJobID].dstFlushed);\n                ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[wJobID].dstBuff);\n                DEBUGLOG(5, \"dstBuffer released\");\n                mtctx->jobs[wJobID].dstBuff = g_nullBuffer;\n                mtctx->jobs[wJobID].cSize = 0;   /* ensure this job slot is considered \"not started\" in future check */\n                mtctx->consumed += srcSize;\n                mtctx->produced += cSize;\n                mtctx->doneJobID++;\n        }   }\n\n        /* return value : how many bytes left in buffer ; fake it to 1 when unknown but >0 */\n        if (cSize > mtctx->jobs[wJobID].dstFlushed) return (cSize - mtctx->jobs[wJobID].dstFlushed);\n        if (srcSize > srcConsumed) return 1;   /* current job not completely compressed */\n    }\n    if (mtctx->doneJobID < mtctx->nextJobID) return 1;   /* some more jobs ongoing */\n    if (mtctx->jobReady) return 1;      /* one job is ready to push, just not yet in the list */\n    if (mtctx->inBuff.filled > 0) return 1;   /* input is not empty, and still needs to be converted into a job */\n    mtctx->allJobsCompleted = mtctx->frameEnded;   /* all jobs are entirely flushed => if this one is last one, frame is completed */\n    if (end == ZSTD_e_end) return !mtctx->frameEnded;  /* for ZSTD_e_end, question becomes : is frame completed ? instead of : are internal buffers fully flushed ? */\n    return 0;   /* internal buffers fully flushed */\n}\n\n/**\n * Returns the range of data used by the earliest job that is not yet complete.\n * If the data of the first job is broken up into two segments, we cover both\n * sections.\n */\nstatic Range ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)\n{\n    unsigned const firstJobID = mtctx->doneJobID;\n    unsigned const lastJobID = mtctx->nextJobID;\n    unsigned jobID;\n\n    /* no need to check during first round */\n    size_t roundBuffCapacity = mtctx->roundBuff.capacity;\n    size_t nbJobs1stRoundMin = roundBuffCapacity / mtctx->targetSectionSize;\n    if (lastJobID < nbJobs1stRoundMin) return kNullRange;\n\n    for (jobID = firstJobID; jobID < lastJobID; ++jobID) {\n        unsigned const wJobID = jobID & mtctx->jobIDMask;\n        size_t consumed;\n\n        ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[wJobID].job_mutex);\n        consumed = mtctx->jobs[wJobID].consumed;\n        ZSTD_pthread_mutex_unlock(&mtctx->jobs[wJobID].job_mutex);\n\n        if (consumed < mtctx->jobs[wJobID].src.size) {\n            Range range = mtctx->jobs[wJobID].prefix;\n            if (range.size == 0) {\n                /* Empty prefix */\n                range = mtctx->jobs[wJobID].src;\n            }\n            /* Job source in multiple segments not supported yet */\n            assert(range.start <= mtctx->jobs[wJobID].src.start);\n            return range;\n        }\n    }\n    return kNullRange;\n}\n\n/**\n * Returns non-zero iff buffer and range overlap.\n */\nstatic int ZSTDMT_isOverlapped(Buffer buffer, Range range)\n{\n    BYTE const* const bufferStart = (BYTE const*)buffer.start;\n    BYTE const* const rangeStart = (BYTE const*)range.start;\n\n    if (rangeStart == NULL || bufferStart == NULL)\n        return 0;\n\n    {\n        BYTE const* const bufferEnd = bufferStart + buffer.capacity;\n        BYTE const* const rangeEnd = rangeStart + range.size;\n\n        /* Empty ranges cannot overlap */\n        if (bufferStart == bufferEnd || rangeStart == rangeEnd)\n            return 0;\n\n        return bufferStart < rangeEnd && rangeStart < bufferEnd;\n    }\n}\n\nstatic int ZSTDMT_doesOverlapWindow(Buffer buffer, ZSTD_window_t window)\n{\n    Range extDict;\n    Range prefix;\n\n    DEBUGLOG(5, \"ZSTDMT_doesOverlapWindow\");\n    extDict.start = window.dictBase + window.lowLimit;\n    extDict.size = window.dictLimit - window.lowLimit;\n\n    prefix.start = window.base + window.dictLimit;\n    prefix.size = window.nextSrc - (window.base + window.dictLimit);\n    DEBUGLOG(5, \"extDict [0x%zx, 0x%zx)\",\n                (size_t)extDict.start,\n                (size_t)extDict.start + extDict.size);\n    DEBUGLOG(5, \"prefix  [0x%zx, 0x%zx)\",\n                (size_t)prefix.start,\n                (size_t)prefix.start + prefix.size);\n\n    return ZSTDMT_isOverlapped(buffer, extDict)\n        || ZSTDMT_isOverlapped(buffer, prefix);\n}\n\nstatic void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, Buffer buffer)\n{\n    if (mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable) {\n        ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;\n        DEBUGLOG(5, \"ZSTDMT_waitForLdmComplete\");\n        DEBUGLOG(5, \"source  [0x%zx, 0x%zx)\",\n                    (size_t)buffer.start,\n                    (size_t)buffer.start + buffer.capacity);\n        ZSTD_PTHREAD_MUTEX_LOCK(mutex);\n        while (ZSTDMT_doesOverlapWindow(buffer, mtctx->serial.ldmWindow)) {\n            DEBUGLOG(5, \"Waiting for LDM to finish...\");\n            ZSTD_pthread_cond_wait(&mtctx->serial.ldmWindowCond, mutex);\n        }\n        DEBUGLOG(6, \"Done waiting for LDM to finish\");\n        ZSTD_pthread_mutex_unlock(mutex);\n    }\n}\n\n/**\n * Attempts to set the inBuff to the next section to fill.\n * If any part of the new section is still in use we give up.\n * Returns non-zero if the buffer is filled.\n */\nstatic int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx)\n{\n    Range const inUse = ZSTDMT_getInputDataInUse(mtctx);\n    size_t const spaceLeft = mtctx->roundBuff.capacity - mtctx->roundBuff.pos;\n    size_t const spaceNeeded = mtctx->targetSectionSize;\n    Buffer buffer;\n\n    DEBUGLOG(5, \"ZSTDMT_tryGetInputRange\");\n    assert(mtctx->inBuff.buffer.start == NULL);\n    assert(mtctx->roundBuff.capacity >= spaceNeeded);\n\n    if (spaceLeft < spaceNeeded) {\n        /* ZSTD_invalidateRepCodes() doesn't work for extDict variants.\n         * Simply copy the prefix to the beginning in that case.\n         */\n        BYTE* const start = (BYTE*)mtctx->roundBuff.buffer;\n        size_t const prefixSize = mtctx->inBuff.prefix.size;\n\n        buffer.start = start;\n        buffer.capacity = prefixSize;\n        if (ZSTDMT_isOverlapped(buffer, inUse)) {\n            DEBUGLOG(5, \"Waiting for buffer...\");\n            return 0;\n        }\n        ZSTDMT_waitForLdmComplete(mtctx, buffer);\n        ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize);\n        mtctx->inBuff.prefix.start = start;\n        mtctx->roundBuff.pos = prefixSize;\n    }\n    buffer.start = mtctx->roundBuff.buffer + mtctx->roundBuff.pos;\n    buffer.capacity = spaceNeeded;\n\n    if (ZSTDMT_isOverlapped(buffer, inUse)) {\n        DEBUGLOG(5, \"Waiting for buffer...\");\n        return 0;\n    }\n    assert(!ZSTDMT_isOverlapped(buffer, mtctx->inBuff.prefix));\n\n    ZSTDMT_waitForLdmComplete(mtctx, buffer);\n\n    DEBUGLOG(5, \"Using prefix range [%zx, %zx)\",\n                (size_t)mtctx->inBuff.prefix.start,\n                (size_t)mtctx->inBuff.prefix.start + mtctx->inBuff.prefix.size);\n    DEBUGLOG(5, \"Using source range [%zx, %zx)\",\n                (size_t)buffer.start,\n                (size_t)buffer.start + buffer.capacity);\n\n\n    mtctx->inBuff.buffer = buffer;\n    mtctx->inBuff.filled = 0;\n    assert(mtctx->roundBuff.pos + buffer.capacity <= mtctx->roundBuff.capacity);\n    return 1;\n}\n\ntypedef struct {\n  size_t toLoad;  /* The number of bytes to load from the input. */\n  int flush;      /* Boolean declaring if we must flush because we found a synchronization point. */\n} SyncPoint;\n\n/**\n * Searches through the input for a synchronization point. If one is found, we\n * will instruct the caller to flush, and return the number of bytes to load.\n * Otherwise, we will load as many bytes as possible and instruct the caller\n * to continue as normal.\n */\nstatic SyncPoint\nfindSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)\n{\n    BYTE const* const istart = (BYTE const*)input.src + input.pos;\n    U64 const primePower = mtctx->rsync.primePower;\n    U64 const hitMask = mtctx->rsync.hitMask;\n\n    SyncPoint syncPoint;\n    U64 hash;\n    BYTE const* prev;\n    size_t pos;\n\n    syncPoint.toLoad = MIN(input.size - input.pos, mtctx->targetSectionSize - mtctx->inBuff.filled);\n    syncPoint.flush = 0;\n    if (!mtctx->params.rsyncable)\n        /* Rsync is disabled. */\n        return syncPoint;\n    if (mtctx->inBuff.filled + input.size - input.pos < RSYNC_MIN_BLOCK_SIZE)\n        /* We don't emit synchronization points if it would produce too small blocks.\n         * We don't have enough input to find a synchronization point, so don't look.\n         */\n        return syncPoint;\n    if (mtctx->inBuff.filled + syncPoint.toLoad < RSYNC_LENGTH)\n        /* Not enough to compute the hash.\n         * We will miss any synchronization points in this RSYNC_LENGTH byte\n         * window. However, since it depends only in the internal buffers, if the\n         * state is already synchronized, we will remain synchronized.\n         * Additionally, the probability that we miss a synchronization point is\n         * low: RSYNC_LENGTH / targetSectionSize.\n         */\n        return syncPoint;\n    /* Initialize the loop variables. */\n    if (mtctx->inBuff.filled < RSYNC_MIN_BLOCK_SIZE) {\n        /* We don't need to scan the first RSYNC_MIN_BLOCK_SIZE positions\n         * because they can't possibly be a sync point. So we can start\n         * part way through the input buffer.\n         */\n        pos = RSYNC_MIN_BLOCK_SIZE - mtctx->inBuff.filled;\n        if (pos >= RSYNC_LENGTH) {\n            prev = istart + pos - RSYNC_LENGTH;\n            hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);\n        } else {\n            assert(mtctx->inBuff.filled >= RSYNC_LENGTH);\n            prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;\n            hash = ZSTD_rollingHash_compute(prev + pos, (RSYNC_LENGTH - pos));\n            hash = ZSTD_rollingHash_append(hash, istart, pos);\n        }\n    } else {\n        /* We have enough bytes buffered to initialize the hash,\n         * and have processed enough bytes to find a sync point.\n         * Start scanning at the beginning of the input.\n         */\n        assert(mtctx->inBuff.filled >= RSYNC_MIN_BLOCK_SIZE);\n        assert(RSYNC_MIN_BLOCK_SIZE >= RSYNC_LENGTH);\n        pos = 0;\n        prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;\n        hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);\n        if ((hash & hitMask) == hitMask) {\n            /* We're already at a sync point so don't load any more until\n             * we're able to flush this sync point.\n             * This likely happened because the job table was full so we\n             * couldn't add our job.\n             */\n            syncPoint.toLoad = 0;\n            syncPoint.flush = 1;\n            return syncPoint;\n        }\n    }\n    /* Starting with the hash of the previous RSYNC_LENGTH bytes, roll\n     * through the input. If we hit a synchronization point, then cut the\n     * job off, and tell the compressor to flush the job. Otherwise, load\n     * all the bytes and continue as normal.\n     * If we go too long without a synchronization point (targetSectionSize)\n     * then a block will be emitted anyways, but this is okay, since if we\n     * are already synchronized we will remain synchronized.\n     */\n    assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);\n    for (; pos < syncPoint.toLoad; ++pos) {\n        BYTE const toRemove = pos < RSYNC_LENGTH ? prev[pos] : istart[pos - RSYNC_LENGTH];\n        /* This assert is very expensive, and Debian compiles with asserts enabled.\n         * So disable it for now. We can get similar coverage by checking it at the\n         * beginning & end of the loop.\n         * assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);\n         */\n        hash = ZSTD_rollingHash_rotate(hash, toRemove, istart[pos], primePower);\n        assert(mtctx->inBuff.filled + pos >= RSYNC_MIN_BLOCK_SIZE);\n        if ((hash & hitMask) == hitMask) {\n            syncPoint.toLoad = pos + 1;\n            syncPoint.flush = 1;\n            ++pos; /* for assert */\n            break;\n        }\n    }\n    assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);\n    return syncPoint;\n}\n\nsize_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx)\n{\n    size_t hintInSize = mtctx->targetSectionSize - mtctx->inBuff.filled;\n    if (hintInSize==0) hintInSize = mtctx->targetSectionSize;\n    return hintInSize;\n}\n\n/** ZSTDMT_compressStream_generic() :\n *  internal use only - exposed to be invoked from zstd_compress.c\n *  assumption : output and input are valid (pos <= size)\n * @return : minimum amount of data remaining to flush, 0 if none */\nsize_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,\n                                     ZSTD_outBuffer* output,\n                                     ZSTD_inBuffer* input,\n                                     ZSTD_EndDirective endOp)\n{\n    unsigned forwardInputProgress = 0;\n    DEBUGLOG(5, \"ZSTDMT_compressStream_generic (endOp=%u, srcSize=%u)\",\n                (U32)endOp, (U32)(input->size - input->pos));\n    assert(output->pos <= output->size);\n    assert(input->pos  <= input->size);\n\n    if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) {\n        /* current frame being ended. Only flush/end are allowed */\n        return ERROR(stage_wrong);\n    }\n\n    /* fill input buffer */\n    if ( (!mtctx->jobReady)\n      && (input->size > input->pos) ) {   /* support NULL input */\n        if (mtctx->inBuff.buffer.start == NULL) {\n            assert(mtctx->inBuff.filled == 0); /* Can't fill an empty buffer */\n            if (!ZSTDMT_tryGetInputRange(mtctx)) {\n                /* It is only possible for this operation to fail if there are\n                 * still compression jobs ongoing.\n                 */\n                DEBUGLOG(5, \"ZSTDMT_tryGetInputRange failed\");\n                assert(mtctx->doneJobID != mtctx->nextJobID);\n            } else\n                DEBUGLOG(5, \"ZSTDMT_tryGetInputRange completed successfully : mtctx->inBuff.buffer.start = %p\", mtctx->inBuff.buffer.start);\n        }\n        if (mtctx->inBuff.buffer.start != NULL) {\n            SyncPoint const syncPoint = findSynchronizationPoint(mtctx, *input);\n            if (syncPoint.flush && endOp == ZSTD_e_continue) {\n                endOp = ZSTD_e_flush;\n            }\n            assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize);\n            DEBUGLOG(5, \"ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u\",\n                        (U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize);\n            ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad);\n            input->pos += syncPoint.toLoad;\n            mtctx->inBuff.filled += syncPoint.toLoad;\n            forwardInputProgress = syncPoint.toLoad>0;\n        }\n    }\n    if ((input->pos < input->size) && (endOp == ZSTD_e_end)) {\n        /* Can't end yet because the input is not fully consumed.\n            * We are in one of these cases:\n            * - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job.\n            * - We filled the input buffer: flush this job but don't end the frame.\n            * - We hit a synchronization point: flush this job but don't end the frame.\n            */\n        assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable);\n        endOp = ZSTD_e_flush;\n    }\n\n    if ( (mtctx->jobReady)\n      || (mtctx->inBuff.filled >= mtctx->targetSectionSize)  /* filled enough : let's compress */\n      || ((endOp != ZSTD_e_continue) && (mtctx->inBuff.filled > 0))  /* something to flush : let's go */\n      || ((endOp == ZSTD_e_end) && (!mtctx->frameEnded)) ) {   /* must finish the frame with a zero-size block */\n        size_t const jobSize = mtctx->inBuff.filled;\n        assert(mtctx->inBuff.filled <= mtctx->targetSectionSize);\n        FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, jobSize, endOp) , \"\");\n    }\n\n    /* check for potential compressed data ready to be flushed */\n    {   size_t const remainingToFlush = ZSTDMT_flushProduced(mtctx, output, !forwardInputProgress, endOp); /* block if there was no forward input progress */\n        if (input->pos < input->size) return MAX(remainingToFlush, 1);  /* input not consumed : do not end flush yet */\n        DEBUGLOG(5, \"end of ZSTDMT_compressStream_generic: remainingToFlush = %u\", (U32)remainingToFlush);\n        return remainingToFlush;\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/compress/zstdmt_compress.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n #ifndef ZSTDMT_COMPRESS_H\n #define ZSTDMT_COMPRESS_H\n\n/* ===   Dependencies   === */\n#include \"../common/zstd_deps.h\"   /* size_t */\n#define ZSTD_STATIC_LINKING_ONLY   /* ZSTD_parameters */\n#include \"../zstd.h\"            /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */\n\n/* Note : This is an internal API.\n *        These APIs used to be exposed with ZSTDLIB_API,\n *        because it used to be the only way to invoke MT compression.\n *        Now, you must use ZSTD_compress2 and ZSTD_compressStream2() instead.\n *\n *        This API requires ZSTD_MULTITHREAD to be defined during compilation,\n *        otherwise ZSTDMT_createCCtx*() will fail.\n */\n\n/* ===   Constants   === */\n#ifndef ZSTDMT_NBWORKERS_MAX /* a different value can be selected at compile time */\n#  define ZSTDMT_NBWORKERS_MAX ((sizeof(void*)==4) /*32-bit*/ ? 64 : 256)\n#endif\n#ifndef ZSTDMT_JOBSIZE_MIN   /* a different value can be selected at compile time */\n#  define ZSTDMT_JOBSIZE_MIN (512 KB)\n#endif\n#define ZSTDMT_JOBLOG_MAX   (MEM_32bits() ? 29 : 30)\n#define ZSTDMT_JOBSIZE_MAX  (MEM_32bits() ? (512 MB) : (1024 MB))\n\n\n/* ========================================================\n * ===  Private interface, for use by ZSTD_compress.c   ===\n * ===  Not exposed in libzstd. Never invoke directly   ===\n * ======================================================== */\n\n/* ===   Memory management   === */\ntypedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx;\n/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */\nZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers,\n                                        ZSTD_customMem cMem,\n\t\t\t\t\tZSTD_threadPool *pool);\nsize_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx);\n\nsize_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx);\n\n/* ===   Streaming functions   === */\n\nsize_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);\n\n/*! ZSTDMT_initCStream_internal() :\n *  Private use only. Init streaming operation.\n *  expects params to be valid.\n *  must receive dict, or cdict, or none, but not both.\n *  mtctx can be freshly constructed or reused from a prior compression.\n *  If mtctx is reused, memory allocations from the prior compression may not be freed,\n *  even if they are not needed for the current compression.\n *  @return : 0, or an error code */\nsize_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* mtctx,\n                    const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,\n                    const ZSTD_CDict* cdict,\n                    ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);\n\n/*! ZSTDMT_compressStream_generic() :\n *  Combines ZSTDMT_compressStream() with optional ZSTDMT_flushStream() or ZSTDMT_endStream()\n *  depending on flush directive.\n * @return : minimum amount of data still to be flushed\n *           0 if fully flushed\n *           or an error code\n *  note : needs to be init using any ZSTD_initCStream*() variant */\nsize_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx,\n                                     ZSTD_outBuffer* output,\n                                     ZSTD_inBuffer* input,\n                                     ZSTD_EndDirective endOp);\n\n /*! ZSTDMT_toFlushNow()\n  *  Tell how many bytes are ready to be flushed immediately.\n  *  Probe the oldest active job (not yet entirely flushed) and check its output buffer.\n  *  If return 0, it means there is no active job,\n  *  or, it means oldest job is still active, but everything produced has been flushed so far,\n  *  therefore flushing is limited by speed of oldest job. */\nsize_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx);\n\n/*! ZSTDMT_updateCParams_whileCompressing() :\n *  Updates only a selected set of compression parameters, to remain compatible with current frame.\n *  New parameters will be applied to next compression job. */\nvoid ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_params* cctxParams);\n\n/*! ZSTDMT_getFrameProgression():\n *  tells how much data has been consumed (input) and produced (output) for current frame.\n *  able to count progression inside worker threads.\n */\nZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx);\n\n#endif   /* ZSTDMT_COMPRESS_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/decompress/huf_decompress.c",
    "content": "﻿/* ******************************************************************\n * huff0 huffman decoder,\n * part of Finite State Entropy library\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n *  You can contact the author at :\n *  - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n****************************************************************** */\n\n/* **************************************************************\n*  Dependencies\n****************************************************************/\n#include \"../common/zstd_deps.h\"  /* ZSTD_memcpy, ZSTD_memset */\n#include \"../common/compiler.h\"\n#include \"../common/bitstream.h\"  /* BIT_* */\n#include \"../common/fse.h\"        /* to compress headers */\n#include \"../common/huf.h\"\n#include \"../common/error_private.h\"\n#include \"../common/zstd_internal.h\"\n#include \"../common/bits.h\"       /* ZSTD_highbit32, ZSTD_countTrailingZeros64 */\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n\n#define HUF_DECODER_FAST_TABLELOG 11\n\n/* **************************************************************\n*  Macros\n****************************************************************/\n\n#ifdef HUF_DISABLE_FAST_DECODE\n# define HUF_ENABLE_FAST_DECODE 0\n#else\n# define HUF_ENABLE_FAST_DECODE 1\n#endif\n\n/* These two optional macros force the use one way or another of the two\n * Huffman decompression implementations. You can't force in both directions\n * at the same time.\n */\n#if defined(HUF_FORCE_DECOMPRESS_X1) && \\\n    defined(HUF_FORCE_DECOMPRESS_X2)\n#error \"Cannot force the use of the X1 and X2 decoders at the same time!\"\n#endif\n\n/* When DYNAMIC_BMI2 is enabled, fast decoders are only called when bmi2 is\n * supported at runtime, so we can add the BMI2 target attribute.\n * When it is disabled, we will still get BMI2 if it is enabled statically.\n */\n#if DYNAMIC_BMI2\n# define HUF_FAST_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE\n#else\n# define HUF_FAST_BMI2_ATTRS\n#endif\n\n#ifdef __cplusplus\n# define HUF_EXTERN_C extern \"C\"\n#else\n# define HUF_EXTERN_C\n#endif\n#define HUF_ASM_DECL HUF_EXTERN_C\n\n#if DYNAMIC_BMI2\n# define HUF_NEED_BMI2_FUNCTION 1\n#else\n# define HUF_NEED_BMI2_FUNCTION 0\n#endif\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_isError ERR_isError\n\n\n/* **************************************************************\n*  Byte alignment for workSpace management\n****************************************************************/\n#define HUF_ALIGN(x, a)         HUF_ALIGN_MASK((x), (a) - 1)\n#define HUF_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))\n\n\n/* **************************************************************\n*  BMI2 Variant Wrappers\n****************************************************************/\ntypedef size_t (*HUF_DecompressUsingDTableFn)(void *dst, size_t dstSize,\n                                              const void *cSrc,\n                                              size_t cSrcSize,\n                                              const HUF_DTable *DTable);\n\n#if DYNAMIC_BMI2\n\n#define HUF_DGEN(fn)                                                        \\\n                                                                            \\\n    static size_t fn##_default(                                             \\\n                  void* dst,  size_t dstSize,                               \\\n            const void* cSrc, size_t cSrcSize,                              \\\n            const HUF_DTable* DTable)                                       \\\n    {                                                                       \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }                                                                       \\\n                                                                            \\\n    static BMI2_TARGET_ATTRIBUTE size_t fn##_bmi2(                          \\\n                  void* dst,  size_t dstSize,                               \\\n            const void* cSrc, size_t cSrcSize,                              \\\n            const HUF_DTable* DTable)                                       \\\n    {                                                                       \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }                                                                       \\\n                                                                            \\\n    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \\\n                     size_t cSrcSize, HUF_DTable const* DTable, int flags)  \\\n    {                                                                       \\\n        if (flags & HUF_flags_bmi2) {                                       \\\n            return fn##_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);         \\\n        }                                                                   \\\n        return fn##_default(dst, dstSize, cSrc, cSrcSize, DTable);          \\\n    }\n\n#else\n\n#define HUF_DGEN(fn)                                                        \\\n    static size_t fn(void* dst, size_t dstSize, void const* cSrc,           \\\n                     size_t cSrcSize, HUF_DTable const* DTable, int flags)  \\\n    {                                                                       \\\n        (void)flags;                                                        \\\n        return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable);             \\\n    }\n\n#endif\n\n\n/*-***************************/\n/*  generic DTableDesc       */\n/*-***************************/\ntypedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;\n\nstatic DTableDesc HUF_getDTableDesc(const HUF_DTable* table)\n{\n    DTableDesc dtd;\n    ZSTD_memcpy(&dtd, table, sizeof(dtd));\n    return dtd;\n}\n\nstatic size_t HUF_initFastDStream(BYTE const* ip) {\n    BYTE const lastByte = ip[7];\n    size_t const bitsConsumed = lastByte ? 8 - ZSTD_highbit32(lastByte) : 0;\n    size_t const value = MEM_readLEST(ip) | 1;\n    assert(bitsConsumed <= 8);\n    assert(sizeof(size_t) == 8);\n    return value << bitsConsumed;\n}\n\n\n/**\n * The input/output arguments to the Huffman fast decoding loop:\n *\n * ip [in/out] - The input pointers, must be updated to reflect what is consumed.\n * op [in/out] - The output pointers, must be updated to reflect what is written.\n * bits [in/out] - The bitstream containers, must be updated to reflect the current state.\n * dt [in] - The decoding table.\n * ilowest [in] - The beginning of the valid range of the input. Decoders may read\n *                down to this pointer. It may be below iend[0].\n * oend [in] - The end of the output stream. op[3] must not cross oend.\n * iend [in] - The end of each input stream. ip[i] may cross iend[i],\n *             as long as it is above ilowest, but that indicates corruption.\n */\ntypedef struct {\n    BYTE const* ip[4];\n    BYTE* op[4];\n    U64 bits[4];\n    void const* dt;\n    BYTE const* ilowest;\n    BYTE* oend;\n    BYTE const* iend[4];\n} HUF_DecompressFastArgs;\n\ntypedef void (*HUF_DecompressFastLoopFn)(HUF_DecompressFastArgs*);\n\n/**\n * Initializes args for the fast decoding loop.\n * @returns 1 on success\n *          0 if the fallback implementation should be used.\n *          Or an error code on failure.\n */\nstatic size_t HUF_DecompressFastArgs_init(HUF_DecompressFastArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable)\n{\n    void const* dt = DTable + 1;\n    U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;\n\n    const BYTE* const istart = (const BYTE*)src;\n\n    BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);\n\n    /* The fast decoding loop assumes 64-bit little-endian.\n     * This condition is false on x32.\n     */\n    if (!MEM_isLittleEndian() || MEM_32bits())\n        return 0;\n\n    /* Avoid nullptr addition */\n    if (dstSize == 0)\n        return 0;\n    assert(dst != NULL);\n\n    /* strict minimum : jump table + 1 byte per stream */\n    if (srcSize < 10)\n        return ERROR(corruption_detected);\n\n    /* Must have at least 8 bytes per stream because we don't handle initializing smaller bit containers.\n     * If table log is not correct at this point, fallback to the old decoder.\n     * On small inputs we don't have enough data to trigger the fast loop, so use the old decoder.\n     */\n    if (dtLog != HUF_DECODER_FAST_TABLELOG)\n        return 0;\n\n    /* Read the jump table. */\n    {\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = srcSize - (length1 + length2 + length3 + 6);\n        args->iend[0] = istart + 6;  /* jumpTable */\n        args->iend[1] = args->iend[0] + length1;\n        args->iend[2] = args->iend[1] + length2;\n        args->iend[3] = args->iend[2] + length3;\n\n        /* HUF_initFastDStream() requires this, and this small of an input\n         * won't benefit from the ASM loop anyways.\n         */\n        if (length1 < 8 || length2 < 8 || length3 < 8 || length4 < 8)\n            return 0;\n        if (length4 > srcSize) return ERROR(corruption_detected);   /* overflow */\n    }\n    /* ip[] contains the position that is currently loaded into bits[]. */\n    args->ip[0] = args->iend[1] - sizeof(U64);\n    args->ip[1] = args->iend[2] - sizeof(U64);\n    args->ip[2] = args->iend[3] - sizeof(U64);\n    args->ip[3] = (BYTE const*)src + srcSize - sizeof(U64);\n\n    /* op[] contains the output pointers. */\n    args->op[0] = (BYTE*)dst;\n    args->op[1] = args->op[0] + (dstSize+3)/4;\n    args->op[2] = args->op[1] + (dstSize+3)/4;\n    args->op[3] = args->op[2] + (dstSize+3)/4;\n\n    /* No point to call the ASM loop for tiny outputs. */\n    if (args->op[3] >= oend)\n        return 0;\n\n    /* bits[] is the bit container.\n        * It is read from the MSB down to the LSB.\n        * It is shifted left as it is read, and zeros are\n        * shifted in. After the lowest valid bit a 1 is\n        * set, so that CountTrailingZeros(bits[]) can be used\n        * to count how many bits we've consumed.\n        */\n    args->bits[0] = HUF_initFastDStream(args->ip[0]);\n    args->bits[1] = HUF_initFastDStream(args->ip[1]);\n    args->bits[2] = HUF_initFastDStream(args->ip[2]);\n    args->bits[3] = HUF_initFastDStream(args->ip[3]);\n\n    /* The decoders must be sure to never read beyond ilowest.\n     * This is lower than iend[0], but allowing decoders to read\n     * down to ilowest can allow an extra iteration or two in the\n     * fast loop.\n     */\n    args->ilowest = istart;\n\n    args->oend = oend;\n    args->dt = dt;\n\n    return 1;\n}\n\nstatic size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressFastArgs const* args, int stream, BYTE* segmentEnd)\n{\n    /* Validate that we haven't overwritten. */\n    if (args->op[stream] > segmentEnd)\n        return ERROR(corruption_detected);\n    /* Validate that we haven't read beyond iend[].\n        * Note that ip[] may be < iend[] because the MSB is\n        * the next bit to read, and we may have consumed 100%\n        * of the stream, so down to iend[i] - 8 is valid.\n        */\n    if (args->ip[stream] < args->iend[stream] - 8)\n        return ERROR(corruption_detected);\n\n    /* Construct the BIT_DStream_t. */\n    assert(sizeof(size_t) == 8);\n    bit->bitContainer = MEM_readLEST(args->ip[stream]);\n    bit->bitsConsumed = ZSTD_countTrailingZeros64(args->bits[stream]);\n    bit->start = (const char*)args->ilowest;\n    bit->limitPtr = bit->start + sizeof(size_t);\n    bit->ptr = (const char*)args->ip[stream];\n\n    return 0;\n}\n\n/* Calls X(N) for each stream 0, 1, 2, 3. */\n#define HUF_4X_FOR_EACH_STREAM(X) \\\n    do {                          \\\n        X(0);                     \\\n        X(1);                     \\\n        X(2);                     \\\n        X(3);                     \\\n    } while (0)\n\n/* Calls X(N, var) for each stream 0, 1, 2, 3. */\n#define HUF_4X_FOR_EACH_STREAM_WITH_VAR(X, var) \\\n    do {                                        \\\n        X(0, (var));                            \\\n        X(1, (var));                            \\\n        X(2, (var));                            \\\n        X(3, (var));                            \\\n    } while (0)\n\n\n#ifndef HUF_FORCE_DECOMPRESS_X2\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\ntypedef struct { BYTE nbBits; BYTE byte; } HUF_DEltX1;   /* single-symbol decoding */\n\n/**\n * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at\n * a time.\n */\nstatic U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {\n    U64 D4;\n    if (MEM_isLittleEndian()) {\n        D4 = (U64)((symbol << 8) + nbBits);\n    } else {\n        D4 = (U64)(symbol + (nbBits << 8));\n    }\n    assert(D4 < (1U << 16));\n    D4 *= 0x0001000100010001ULL;\n    return D4;\n}\n\n/**\n * Increase the tableLog to targetTableLog and rescales the stats.\n * If tableLog > targetTableLog this is a no-op.\n * @returns New tableLog\n */\nstatic U32 HUF_rescaleStats(BYTE* huffWeight, U32* rankVal, U32 nbSymbols, U32 tableLog, U32 targetTableLog)\n{\n    if (tableLog > targetTableLog)\n        return tableLog;\n    if (tableLog < targetTableLog) {\n        U32 const scale = targetTableLog - tableLog;\n        U32 s;\n        /* Increase the weight for all non-zero probability symbols by scale. */\n        for (s = 0; s < nbSymbols; ++s) {\n            huffWeight[s] += (BYTE)((huffWeight[s] == 0) ? 0 : scale);\n        }\n        /* Update rankVal to reflect the new weights.\n         * All weights except 0 get moved to weight + scale.\n         * Weights [1, scale] are empty.\n         */\n        for (s = targetTableLog; s > scale; --s) {\n            rankVal[s] = rankVal[s - scale];\n        }\n        for (s = scale; s > 0; --s) {\n            rankVal[s] = 0;\n        }\n    }\n    return targetTableLog;\n}\n\ntypedef struct {\n        U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];\n        U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1];\n        U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];\n        BYTE symbols[HUF_SYMBOLVALUE_MAX + 1];\n        BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];\n} HUF_ReadDTableX1_Workspace;\n\nsize_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int flags)\n{\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n    size_t iSize;\n    void* const dtPtr = DTable + 1;\n    HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr;\n    HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace;\n\n    DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp));\n    if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge);\n\n    DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable));\n    /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), flags);\n    if (HUF_isError(iSize)) return iSize;\n\n\n    /* Table header */\n    {   DTableDesc dtd = HUF_getDTableDesc(DTable);\n        U32 const maxTableLog = dtd.maxTableLog + 1;\n        U32 const targetTableLog = MIN(maxTableLog, HUF_DECODER_FAST_TABLELOG);\n        tableLog = HUF_rescaleStats(wksp->huffWeight, wksp->rankVal, nbSymbols, tableLog, targetTableLog);\n        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, Huffman tree cannot fit in */\n        dtd.tableType = 0;\n        dtd.tableLog = (BYTE)tableLog;\n        ZSTD_memcpy(DTable, &dtd, sizeof(dtd));\n    }\n\n    /* Compute symbols and rankStart given rankVal:\n     *\n     * rankVal already contains the number of values of each weight.\n     *\n     * symbols contains the symbols ordered by weight. First are the rankVal[0]\n     * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on.\n     * symbols[0] is filled (but unused) to avoid a branch.\n     *\n     * rankStart contains the offset where each rank belongs in the DTable.\n     * rankStart[0] is not filled because there are no entries in the table for\n     * weight 0.\n     */\n    {   int n;\n        U32 nextRankStart = 0;\n        int const unroll = 4;\n        int const nLimit = (int)nbSymbols - unroll + 1;\n        for (n=0; n<(int)tableLog+1; n++) {\n            U32 const curr = nextRankStart;\n            nextRankStart += wksp->rankVal[n];\n            wksp->rankStart[n] = curr;\n        }\n        for (n=0; n < nLimit; n += unroll) {\n            int u;\n            for (u=0; u < unroll; ++u) {\n                size_t const w = wksp->huffWeight[n+u];\n                wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u);\n            }\n        }\n        for (; n < (int)nbSymbols; ++n) {\n            size_t const w = wksp->huffWeight[n];\n            wksp->symbols[wksp->rankStart[w]++] = (BYTE)n;\n        }\n    }\n\n    /* fill DTable\n     * We fill all entries of each weight in order.\n     * That way length is a constant for each iteration of the outer loop.\n     * We can switch based on the length to a different inner loop which is\n     * optimized for that particular case.\n     */\n    {   U32 w;\n        int symbol = wksp->rankVal[0];\n        int rankStart = 0;\n        for (w=1; w<tableLog+1; ++w) {\n            int const symbolCount = wksp->rankVal[w];\n            int const length = (1 << w) >> 1;\n            int uStart = rankStart;\n            BYTE const nbBits = (BYTE)(tableLog + 1 - w);\n            int s;\n            int u;\n            switch (length) {\n            case 1:\n                for (s=0; s<symbolCount; ++s) {\n                    HUF_DEltX1 D;\n                    D.byte = wksp->symbols[symbol + s];\n                    D.nbBits = nbBits;\n                    dt[uStart] = D;\n                    uStart += 1;\n                }\n                break;\n            case 2:\n                for (s=0; s<symbolCount; ++s) {\n                    HUF_DEltX1 D;\n                    D.byte = wksp->symbols[symbol + s];\n                    D.nbBits = nbBits;\n                    dt[uStart+0] = D;\n                    dt[uStart+1] = D;\n                    uStart += 2;\n                }\n                break;\n            case 4:\n                for (s=0; s<symbolCount; ++s) {\n                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);\n                    MEM_write64(dt + uStart, D4);\n                    uStart += 4;\n                }\n                break;\n            case 8:\n                for (s=0; s<symbolCount; ++s) {\n                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);\n                    MEM_write64(dt + uStart, D4);\n                    MEM_write64(dt + uStart + 4, D4);\n                    uStart += 8;\n                }\n                break;\n            default:\n                for (s=0; s<symbolCount; ++s) {\n                    U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits);\n                    for (u=0; u < length; u += 16) {\n                        MEM_write64(dt + uStart + u + 0, D4);\n                        MEM_write64(dt + uStart + u + 4, D4);\n                        MEM_write64(dt + uStart + u + 8, D4);\n                        MEM_write64(dt + uStart + u + 12, D4);\n                    }\n                    assert(u == length);\n                    uStart += length;\n                }\n                break;\n            }\n            symbol += symbolCount;\n            rankStart += symbolCount * length;\n        }\n    }\n    return iSize;\n}\n\nFORCE_INLINE_TEMPLATE BYTE\nHUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n    BYTE const c = dt[val].byte;\n    BIT_skipBits(Dstream, dt[val].nbBits);\n    return c;\n}\n\n#define HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr) \\\n    do { *ptr++ = HUF_decodeSymbolX1(DStreamPtr, dt, dtLog); } while (0)\n\n#define HUF_DECODE_SYMBOLX1_1(ptr, DStreamPtr)      \\\n    do {                                            \\\n        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12)) \\\n            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \\\n    } while (0)\n\n#define HUF_DECODE_SYMBOLX1_2(ptr, DStreamPtr)      \\\n    do {                                            \\\n        if (MEM_64bits())                           \\\n            HUF_DECODE_SYMBOLX1_0(ptr, DStreamPtr); \\\n    } while (0)\n\nHINT_INLINE size_t\nHUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX1* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    if ((pEnd - p) > 3) {\n        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {\n            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);\n            HUF_DECODE_SYMBOLX1_1(p, bitDPtr);\n            HUF_DECODE_SYMBOLX1_2(p, bitDPtr);\n            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n        }\n    } else {\n        BIT_reloadDStream(bitDPtr);\n    }\n\n    /* [0-3] symbols remaining */\n    if (MEM_32bits())\n        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd))\n            HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX1_0(p, bitDPtr);\n\n    return (size_t)(pEnd-pStart);\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress1X1_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = ZSTD_maybeNullPtrAdd(op, dstSize);\n    const void* dtPtr = DTable + 1;\n    const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;\n    BIT_DStream_t bitD;\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n    U32 const dtLog = dtd.tableLog;\n\n    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );\n\n    HUF_decodeStreamX1(op, &bitD, oend, dt, dtLog);\n\n    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\n/* HUF_decompress4X1_usingDTable_internal_body():\n * Conditions :\n * @dstSize >= 6\n */\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress4X1_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */\n    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        BYTE* const olimit = oend - 3;\n        const void* const dtPtr = DTable + 1;\n        const HUF_DEltX1* const dt = (const HUF_DEltX1*)dtPtr;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n        U32 endSignal = 1;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        if (opStart4 > oend) return ERROR(corruption_detected);      /* overflow */\n        assert(dstSize >= 6); /* validated above */\n        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );\n        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );\n        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );\n        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );\n\n        /* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */\n        if ((size_t)(oend - op4) >= sizeof(size_t)) {\n            for ( ; (endSignal) & (op4 < olimit) ; ) {\n                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX1_1(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_1(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_1(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_1(op4, &bitD4);\n                HUF_DECODE_SYMBOLX1_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX1_0(op1, &bitD1);\n                HUF_DECODE_SYMBOLX1_0(op2, &bitD2);\n                HUF_DECODE_SYMBOLX1_0(op3, &bitD3);\n                HUF_DECODE_SYMBOLX1_0(op4, &bitD4);\n                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;\n            }\n        }\n\n        /* check corruption */\n        /* note : should not be necessary : op# advance in lock step, and we control op4.\n         *        but curiously, binary generated by gcc 7.2 & 7.3 with -mbmi2 runs faster when >=1 test is present */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX1(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX1(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX1(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX1(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n#if HUF_NEED_BMI2_FUNCTION\nstatic BMI2_TARGET_ATTRIBUTE\nsize_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n#endif\n\nstatic\nsize_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2\n\nHUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;\n\n#endif\n\nstatic HUF_FAST_BMI2_ATTRS\nvoid HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)\n{\n    U64 bits[4];\n    BYTE const* ip[4];\n    BYTE* op[4];\n    U16 const* const dtable = (U16 const*)args->dt;\n    BYTE* const oend = args->oend;\n    BYTE const* const ilowest = args->ilowest;\n\n    /* Copy the arguments to local variables */\n    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));\n    ZSTD_memcpy(&op, &args->op, sizeof(op));\n\n    assert(MEM_isLittleEndian());\n    assert(!MEM_32bits());\n\n    for (;;) {\n        BYTE* olimit;\n        int stream;\n\n        /* Assert loop preconditions */\n#ifndef NDEBUG\n        for (stream = 0; stream < 4; ++stream) {\n            assert(op[stream] <= (stream == 3 ? oend : op[stream + 1]));\n            assert(ip[stream] >= ilowest);\n        }\n#endif\n        /* Compute olimit */\n        {\n            /* Each iteration produces 5 output symbols per stream */\n            size_t const oiters = (size_t)(oend - op[3]) / 5;\n            /* Each iteration consumes up to 11 bits * 5 = 55 bits < 7 bytes\n             * per stream.\n             */\n            size_t const iiters = (size_t)(ip[0] - ilowest) / 7;\n            /* We can safely run iters iterations before running bounds checks */\n            size_t const iters = MIN(oiters, iiters);\n            size_t const symbols = iters * 5;\n\n            /* We can simply check that op[3] < olimit, instead of checking all\n             * of our bounds, since we can't hit the other bounds until we've run\n             * iters iterations, which only happens when op[3] == olimit.\n             */\n            olimit = op[3] + symbols;\n\n            /* Exit fast decoding loop once we reach the end. */\n            if (op[3] == olimit)\n                break;\n\n            /* Exit the decoding loop if any input pointer has crossed the\n             * previous one. This indicates corruption, and a precondition\n             * to our loop is that ip[i] >= ip[0].\n             */\n            for (stream = 1; stream < 4; ++stream) {\n                if (ip[stream] < ip[stream - 1])\n                    goto _out;\n            }\n        }\n\n#ifndef NDEBUG\n        for (stream = 1; stream < 4; ++stream) {\n            assert(ip[stream] >= ip[stream - 1]);\n        }\n#endif\n\n#define HUF_4X1_DECODE_SYMBOL(_stream, _symbol)                 \\\n    do {                                                        \\\n        int const index = (int)(bits[(_stream)] >> 53);         \\\n        int const entry = (int)dtable[index];                   \\\n        bits[(_stream)] <<= (entry & 0x3F);                     \\\n        op[(_stream)][(_symbol)] = (BYTE)((entry >> 8) & 0xFF); \\\n    } while (0)\n\n#define HUF_4X1_RELOAD_STREAM(_stream)                              \\\n    do {                                                            \\\n        int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \\\n        int const nbBits = ctz & 7;                                 \\\n        int const nbBytes = ctz >> 3;                               \\\n        op[(_stream)] += 5;                                         \\\n        ip[(_stream)] -= nbBytes;                                   \\\n        bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \\\n        bits[(_stream)] <<= nbBits;                                 \\\n    } while (0)\n\n        /* Manually unroll the loop because compilers don't consistently\n         * unroll the inner loops, which destroys performance.\n         */\n        do {\n            /* Decode 5 symbols in each of the 4 streams */\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 0);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 1);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 2);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 3);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X1_DECODE_SYMBOL, 4);\n\n            /* Reload each of the 4 the bitstreams */\n            HUF_4X_FOR_EACH_STREAM(HUF_4X1_RELOAD_STREAM);\n        } while (op[3] < olimit);\n\n#undef HUF_4X1_DECODE_SYMBOL\n#undef HUF_4X1_RELOAD_STREAM\n    }\n\n_out:\n\n    /* Save the final values of each of the state variables back to args. */\n    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));\n    ZSTD_memcpy(&args->op, &op, sizeof(op));\n}\n\n/**\n * @returns @p dstSize on success (>= 6)\n *          0 if the fallback implementation should be used\n *          An error if an error occurred\n */\nstatic HUF_FAST_BMI2_ATTRS\nsize_t\nHUF_decompress4X1_usingDTable_internal_fast(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable,\n    HUF_DecompressFastLoopFn loopFn)\n{\n    void const* dt = DTable + 1;\n    BYTE const* const ilowest = (BYTE const*)cSrc;\n    BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);\n    HUF_DecompressFastArgs args;\n    {   size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);\n        FORWARD_IF_ERROR(ret, \"Failed to init fast loop args\");\n        if (ret == 0)\n            return 0;\n    }\n\n    assert(args.ip[0] >= args.ilowest);\n    loopFn(&args);\n\n    /* Our loop guarantees that ip[] >= ilowest and that we haven't\n    * overwritten any op[].\n    */\n    assert(args.ip[0] >= ilowest);\n    assert(args.ip[0] >= ilowest);\n    assert(args.ip[1] >= ilowest);\n    assert(args.ip[2] >= ilowest);\n    assert(args.ip[3] >= ilowest);\n    assert(args.op[3] <= oend);\n\n    assert(ilowest == args.ilowest);\n    assert(ilowest + 6 == args.iend[0]);\n    (void)ilowest;\n\n    /* finish bit streams one by one. */\n    {   size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* segmentEnd = (BYTE*)dst;\n        int i;\n        for (i = 0; i < 4; ++i) {\n            BIT_DStream_t bit;\n            if (segmentSize <= (size_t)(oend - segmentEnd))\n                segmentEnd += segmentSize;\n            else\n                segmentEnd = oend;\n            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), \"corruption\");\n            /* Decompress and validate that we've produced exactly the expected length. */\n            args.op[i] += HUF_decodeStreamX1(args.op[i], &bit, segmentEnd, (HUF_DEltX1 const*)dt, HUF_DECODER_FAST_TABLELOG);\n            if (args.op[i] != segmentEnd) return ERROR(corruption_detected);\n        }\n    }\n\n    /* decoded size */\n    assert(dstSize != 0);\n    return dstSize;\n}\n\nHUF_DGEN(HUF_decompress1X1_usingDTable_internal)\n\nstatic size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable, int flags)\n{\n    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X1_usingDTable_internal_default;\n    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop;\n\n#if DYNAMIC_BMI2\n    if (flags & HUF_flags_bmi2) {\n        fallbackFn = HUF_decompress4X1_usingDTable_internal_bmi2;\n# if ZSTD_ENABLE_ASM_X86_64_BMI2\n        if (!(flags & HUF_flags_disableAsm)) {\n            loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;\n        }\n# endif\n    } else {\n        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n    }\n#endif\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)\n    if (!(flags & HUF_flags_disableAsm)) {\n        loopFn = HUF_decompress4X1_usingDTable_internal_fast_asm_loop;\n    }\n#endif\n\n    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {\n        size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);\n        if (ret != 0)\n            return ret;\n    }\n    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nstatic size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress4X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);\n}\n\n#endif /* HUF_FORCE_DECOMPRESS_X2 */\n\n\n#ifndef HUF_FORCE_DECOMPRESS_X1\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2;  /* double-symbols decoding */\ntypedef struct { BYTE symbol; } sortedSymbol_t;\ntypedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];\ntypedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];\n\n/**\n * Constructs a HUF_DEltX2 in a U32.\n */\nstatic U32 HUF_buildDEltX2U32(U32 symbol, U32 nbBits, U32 baseSeq, int level)\n{\n    U32 seq;\n    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, sequence) == 0);\n    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, nbBits) == 2);\n    DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, length) == 3);\n    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U32));\n    if (MEM_isLittleEndian()) {\n        seq = level == 1 ? symbol : (baseSeq + (symbol << 8));\n        return seq + (nbBits << 16) + ((U32)level << 24);\n    } else {\n        seq = level == 1 ? (symbol << 8) : ((baseSeq << 8) + symbol);\n        return (seq << 16) + (nbBits << 8) + (U32)level;\n    }\n}\n\n/**\n * Constructs a HUF_DEltX2.\n */\nstatic HUF_DEltX2 HUF_buildDEltX2(U32 symbol, U32 nbBits, U32 baseSeq, int level)\n{\n    HUF_DEltX2 DElt;\n    U32 const val = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);\n    DEBUG_STATIC_ASSERT(sizeof(DElt) == sizeof(val));\n    ZSTD_memcpy(&DElt, &val, sizeof(val));\n    return DElt;\n}\n\n/**\n * Constructs 2 HUF_DEltX2s and packs them into a U64.\n */\nstatic U64 HUF_buildDEltX2U64(U32 symbol, U32 nbBits, U16 baseSeq, int level)\n{\n    U32 DElt = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);\n    return (U64)DElt + ((U64)DElt << 32);\n}\n\n/**\n * Fills the DTable rank with all the symbols from [begin, end) that are each\n * nbBits long.\n *\n * @param DTableRank The start of the rank in the DTable.\n * @param begin The first symbol to fill (inclusive).\n * @param end The last symbol to fill (exclusive).\n * @param nbBits Each symbol is nbBits long.\n * @param tableLog The table log.\n * @param baseSeq If level == 1 { 0 } else { the first level symbol }\n * @param level The level in the table. Must be 1 or 2.\n */\nstatic void HUF_fillDTableX2ForWeight(\n    HUF_DEltX2* DTableRank,\n    sortedSymbol_t const* begin, sortedSymbol_t const* end,\n    U32 nbBits, U32 tableLog,\n    U16 baseSeq, int const level)\n{\n    U32 const length = 1U << ((tableLog - nbBits) & 0x1F /* quiet static-analyzer */);\n    const sortedSymbol_t* ptr;\n    assert(level >= 1 && level <= 2);\n    switch (length) {\n    case 1:\n        for (ptr = begin; ptr != end; ++ptr) {\n            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);\n            *DTableRank++ = DElt;\n        }\n        break;\n    case 2:\n        for (ptr = begin; ptr != end; ++ptr) {\n            HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);\n            DTableRank[0] = DElt;\n            DTableRank[1] = DElt;\n            DTableRank += 2;\n        }\n        break;\n    case 4:\n        for (ptr = begin; ptr != end; ++ptr) {\n            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);\n            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));\n            DTableRank += 4;\n        }\n        break;\n    case 8:\n        for (ptr = begin; ptr != end; ++ptr) {\n            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);\n            ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));\n            DTableRank += 8;\n        }\n        break;\n    default:\n        for (ptr = begin; ptr != end; ++ptr) {\n            U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);\n            HUF_DEltX2* const DTableRankEnd = DTableRank + length;\n            for (; DTableRank != DTableRankEnd; DTableRank += 8) {\n                ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));\n                ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));\n                ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));\n                ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));\n            }\n        }\n        break;\n    }\n}\n\n/* HUF_fillDTableX2Level2() :\n * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */\nstatic void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32 consumedBits,\n                           const U32* rankVal, const int minWeight, const int maxWeight1,\n                           const sortedSymbol_t* sortedSymbols, U32 const* rankStart,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    /* Fill skipped values (all positions up to rankVal[minWeight]).\n     * These are positions only get a single symbol because the combined weight\n     * is too large.\n     */\n    if (minWeight>1) {\n        U32 const length = 1U << ((targetLog - consumedBits) & 0x1F /* quiet static-analyzer */);\n        U64 const DEltX2 = HUF_buildDEltX2U64(baseSeq, consumedBits, /* baseSeq */ 0, /* level */ 1);\n        int const skipSize = rankVal[minWeight];\n        assert(length > 1);\n        assert((U32)skipSize < length);\n        switch (length) {\n        case 2:\n            assert(skipSize == 1);\n            ZSTD_memcpy(DTable, &DEltX2, sizeof(DEltX2));\n            break;\n        case 4:\n            assert(skipSize <= 4);\n            ZSTD_memcpy(DTable + 0, &DEltX2, sizeof(DEltX2));\n            ZSTD_memcpy(DTable + 2, &DEltX2, sizeof(DEltX2));\n            break;\n        default:\n            {\n                int i;\n                for (i = 0; i < skipSize; i += 8) {\n                    ZSTD_memcpy(DTable + i + 0, &DEltX2, sizeof(DEltX2));\n                    ZSTD_memcpy(DTable + i + 2, &DEltX2, sizeof(DEltX2));\n                    ZSTD_memcpy(DTable + i + 4, &DEltX2, sizeof(DEltX2));\n                    ZSTD_memcpy(DTable + i + 6, &DEltX2, sizeof(DEltX2));\n                }\n            }\n        }\n    }\n\n    /* Fill each of the second level symbols by weight. */\n    {\n        int w;\n        for (w = minWeight; w < maxWeight1; ++w) {\n            int const begin = rankStart[w];\n            int const end = rankStart[w+1];\n            U32 const nbBits = nbBitsBaseline - w;\n            U32 const totalBits = nbBits + consumedBits;\n            HUF_fillDTableX2ForWeight(\n                DTable + rankVal[w],\n                sortedSymbols + begin, sortedSymbols + end,\n                totalBits, targetLog,\n                baseSeq, /* level */ 2);\n        }\n    }\n}\n\nstatic void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList,\n                           const U32* rankStart, rankValCol_t* rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32* const rankVal = rankValOrigin[0];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    int w;\n    int const wEnd = (int)maxWeight + 1;\n\n    /* Fill DTable in order of weight. */\n    for (w = 1; w < wEnd; ++w) {\n        int const begin = (int)rankStart[w];\n        int const end = (int)rankStart[w+1];\n        U32 const nbBits = nbBitsBaseline - w;\n\n        if (targetLog-nbBits >= minBits) {\n            /* Enough room for a second symbol. */\n            int start = rankVal[w];\n            U32 const length = 1U << ((targetLog - nbBits) & 0x1F /* quiet static-analyzer */);\n            int minWeight = nbBits + scaleLog;\n            int s;\n            if (minWeight < 1) minWeight = 1;\n            /* Fill the DTable for every symbol of weight w.\n             * These symbols get at least 1 second symbol.\n             */\n            for (s = begin; s != end; ++s) {\n                HUF_fillDTableX2Level2(\n                    DTable + start, targetLog, nbBits,\n                    rankValOrigin[nbBits], minWeight, wEnd,\n                    sortedList, rankStart,\n                    nbBitsBaseline, sortedList[s].symbol);\n                start += length;\n            }\n        } else {\n            /* Only a single symbol. */\n            HUF_fillDTableX2ForWeight(\n                DTable + rankVal[w],\n                sortedList + begin, sortedList + end,\n                nbBits, targetLog,\n                /* baseSeq */ 0, /* level */ 1);\n        }\n    }\n}\n\ntypedef struct {\n    rankValCol_t rankVal[HUF_TABLELOG_MAX];\n    U32 rankStats[HUF_TABLELOG_MAX + 1];\n    U32 rankStart0[HUF_TABLELOG_MAX + 3];\n    sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];\n    BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];\n    U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];\n} HUF_ReadDTableX2_Workspace;\n\nsize_t HUF_readDTableX2_wksp(HUF_DTable* DTable,\n                       const void* src, size_t srcSize,\n                             void* workSpace, size_t wkspSize, int flags)\n{\n    U32 tableLog, maxW, nbSymbols;\n    DTableDesc dtd = HUF_getDTableDesc(DTable);\n    U32 maxTableLog = dtd.maxTableLog;\n    size_t iSize;\n    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */\n    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;\n    U32 *rankStart;\n\n    HUF_ReadDTableX2_Workspace* const wksp = (HUF_ReadDTableX2_Workspace*)workSpace;\n\n    if (sizeof(*wksp) > wkspSize) return ERROR(GENERIC);\n\n    rankStart = wksp->rankStart0 + 1;\n    ZSTD_memset(wksp->rankStats, 0, sizeof(wksp->rankStats));\n    ZSTD_memset(wksp->rankStart0, 0, sizeof(wksp->rankStart0));\n\n    DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable));   /* if compiler fails here, assertion is wrong */\n    if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);\n    /* ZSTD_memset(weightList, 0, sizeof(weightList)); */  /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), flags);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n    if (tableLog <= HUF_DECODER_FAST_TABLELOG && maxTableLog > HUF_DECODER_FAST_TABLELOG) maxTableLog = HUF_DECODER_FAST_TABLELOG;\n\n    /* find maxWeight */\n    for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {   U32 w, nextRankStart = 0;\n        for (w=1; w<maxW+1; w++) {\n            U32 curr = nextRankStart;\n            nextRankStart += wksp->rankStats[w];\n            rankStart[w] = curr;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        rankStart[maxW+1] = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {   U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 const w = wksp->weightList[s];\n            U32 const r = rankStart[w]++;\n            wksp->sortedSymbol[r].symbol = (BYTE)s;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {   U32* const rankVal0 = wksp->rankVal[0];\n        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */\n            U32 nextRankVal = 0;\n            U32 w;\n            for (w=1; w<maxW+1; w++) {\n                U32 curr = nextRankVal;\n                nextRankVal += wksp->rankStats[w] << (w+rescale);\n                rankVal0[w] = curr;\n        }   }\n        {   U32 const minBits = tableLog+1 - maxW;\n            U32 consumed;\n            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {\n                U32* const rankValPtr = wksp->rankVal[consumed];\n                U32 w;\n                for (w = 1; w < maxW+1; w++) {\n                    rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }   }\n\n    HUF_fillDTableX2(dt, maxTableLog,\n                   wksp->sortedSymbol,\n                   wksp->rankStart0, wksp->rankVal, maxW,\n                   tableLog+1);\n\n    dtd.tableLog = (BYTE)maxTableLog;\n    dtd.tableType = 1;\n    ZSTD_memcpy(DTable, &dtd, sizeof(dtd));\n    return iSize;\n}\n\n\nFORCE_INLINE_TEMPLATE U32\nHUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    ZSTD_memcpy(op, &dt[val].sequence, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nFORCE_INLINE_TEMPLATE U32\nHUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    ZSTD_memcpy(op, &dt[val].sequence, 1);\n    if (dt[val].length==1) {\n        BIT_skipBits(DStream, dt[val].nbBits);\n    } else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);\n        }\n    }\n    return 1;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    do { ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); } while (0)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr)                     \\\n    do {                                                           \\\n        if (MEM_64bits() || (HUF_TABLELOG_MAX<=12))                \\\n            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \\\n    } while (0)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr)                     \\\n    do {                                                           \\\n        if (MEM_64bits())                                          \\\n            ptr += HUF_decodeSymbolX2(ptr, DStreamPtr, dt, dtLog); \\\n    } while (0)\n\nHINT_INLINE size_t\nHUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,\n                const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    if ((size_t)(pEnd - p) >= sizeof(bitDPtr->bitContainer)) {\n        if (dtLog <= 11 && MEM_64bits()) {\n            /* up to 10 symbols at a time */\n            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-9)) {\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n            }\n        } else {\n            /* up to 8 symbols at a time */\n            while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {\n                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n                HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n            }\n        }\n    } else {\n        BIT_reloadDStream(bitDPtr);\n    }\n\n    /* closer to end : up to 2 symbols at a time */\n    if ((size_t)(pEnd - p) >= 2) {\n        while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))\n            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n        while (p <= pEnd-2)\n            HUF_DECODE_SYMBOLX2_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n    }\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress1X2_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    BIT_DStream_t bitD;\n\n    /* Init */\n    CHECK_F( BIT_initDStream(&bitD, cSrc, cSrcSize) );\n\n    /* decode */\n    {   BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, dstSize);\n        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */\n        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        HUF_decodeStreamX2(ostart, &bitD, oend, dt, dtd.tableLog);\n    }\n\n    /* check */\n    if (!BIT_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\n/* HUF_decompress4X2_usingDTable_internal_body():\n * Conditions:\n * @dstSize >= 6\n */\nFORCE_INLINE_TEMPLATE size_t\nHUF_decompress4X2_usingDTable_internal_body(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n    if (dstSize < 6) return ERROR(corruption_detected);         /* stream 4-split doesn't work */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        BYTE* const olimit = oend - (sizeof(size_t)-1);\n        const void* const dtPtr = DTable+1;\n        const HUF_DEltX2* const dt = (const HUF_DEltX2*)dtPtr;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal = 1;\n        DTableDesc const dtd = HUF_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);  /* overflow */\n        if (opStart4 > oend) return ERROR(corruption_detected);     /* overflow */\n        assert(dstSize >= 6 /* validated above */);\n        CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );\n        CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );\n        CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );\n        CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        if ((size_t)(oend - op4) >= sizeof(size_t)) {\n            for ( ; (endSignal) & (op4 < olimit); ) {\n#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n                endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n                endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;\n                endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;\n#else\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n                HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n                HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n                HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n                HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n                endSignal = (U32)LIKELY((U32)\n                            (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)\n                        & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)\n                        & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)\n                        & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));\n#endif\n            }\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n#if HUF_NEED_BMI2_FUNCTION\nstatic BMI2_TARGET_ATTRIBUTE\nsize_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n#endif\n\nstatic\nsize_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable) {\n    return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2\n\nHUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_fast_asm_loop(HUF_DecompressFastArgs* args) ZSTDLIB_HIDDEN;\n\n#endif\n\nstatic HUF_FAST_BMI2_ATTRS\nvoid HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)\n{\n    U64 bits[4];\n    BYTE const* ip[4];\n    BYTE* op[4];\n    BYTE* oend[4];\n    HUF_DEltX2 const* const dtable = (HUF_DEltX2 const*)args->dt;\n    BYTE const* const ilowest = args->ilowest;\n\n    /* Copy the arguments to local registers. */\n    ZSTD_memcpy(&bits, &args->bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&ip), &args->ip, sizeof(ip));\n    ZSTD_memcpy(&op, &args->op, sizeof(op));\n\n    oend[0] = op[1];\n    oend[1] = op[2];\n    oend[2] = op[3];\n    oend[3] = args->oend;\n\n    assert(MEM_isLittleEndian());\n    assert(!MEM_32bits());\n\n    for (;;) {\n        BYTE* olimit;\n        int stream;\n\n        /* Assert loop preconditions */\n#ifndef NDEBUG\n        for (stream = 0; stream < 4; ++stream) {\n            assert(op[stream] <= oend[stream]);\n            assert(ip[stream] >= ilowest);\n        }\n#endif\n        /* Compute olimit */\n        {\n            /* Each loop does 5 table lookups for each of the 4 streams.\n             * Each table lookup consumes up to 11 bits of input, and produces\n             * up to 2 bytes of output.\n             */\n            /* We can consume up to 7 bytes of input per iteration per stream.\n             * We also know that each input pointer is >= ip[0]. So we can run\n             * iters loops before running out of input.\n             */\n            size_t iters = (size_t)(ip[0] - ilowest) / 7;\n            /* Each iteration can produce up to 10 bytes of output per stream.\n             * Each output stream my advance at different rates. So take the\n             * minimum number of safe iterations among all the output streams.\n             */\n            for (stream = 0; stream < 4; ++stream) {\n                size_t const oiters = (size_t)(oend[stream] - op[stream]) / 10;\n                iters = MIN(iters, oiters);\n            }\n\n            /* Each iteration produces at least 5 output symbols. So until\n             * op[3] crosses olimit, we know we haven't executed iters\n             * iterations yet. This saves us maintaining an iters counter,\n             * at the expense of computing the remaining # of iterations\n             * more frequently.\n             */\n            olimit = op[3] + (iters * 5);\n\n            /* Exit the fast decoding loop once we reach the end. */\n            if (op[3] == olimit)\n                break;\n\n            /* Exit the decoding loop if any input pointer has crossed the\n             * previous one. This indicates corruption, and a precondition\n             * to our loop is that ip[i] >= ip[0].\n             */\n            for (stream = 1; stream < 4; ++stream) {\n                if (ip[stream] < ip[stream - 1])\n                    goto _out;\n            }\n        }\n\n#ifndef NDEBUG\n        for (stream = 1; stream < 4; ++stream) {\n            assert(ip[stream] >= ip[stream - 1]);\n        }\n#endif\n\n#define HUF_4X2_DECODE_SYMBOL(_stream, _decode3)                      \\\n    do {                                                              \\\n        if ((_decode3) || (_stream) != 3) {                           \\\n            int const index = (int)(bits[(_stream)] >> 53);           \\\n            HUF_DEltX2 const entry = dtable[index];                   \\\n            MEM_write16(op[(_stream)], entry.sequence); \\\n            bits[(_stream)] <<= (entry.nbBits) & 0x3F;                \\\n            op[(_stream)] += (entry.length);                          \\\n        }                                                             \\\n    } while (0)\n\n#define HUF_4X2_RELOAD_STREAM(_stream)                                  \\\n    do {                                                                \\\n        HUF_4X2_DECODE_SYMBOL(3, 1);                                    \\\n        {                                                               \\\n            int const ctz = ZSTD_countTrailingZeros64(bits[(_stream)]); \\\n            int const nbBits = ctz & 7;                                 \\\n            int const nbBytes = ctz >> 3;                               \\\n            ip[(_stream)] -= nbBytes;                                   \\\n            bits[(_stream)] = MEM_read64(ip[(_stream)]) | 1;            \\\n            bits[(_stream)] <<= nbBits;                                 \\\n        }                                                               \\\n    } while (0)\n\n        /* Manually unroll the loop because compilers don't consistently\n         * unroll the inner loops, which destroys performance.\n         */\n        do {\n            /* Decode 5 symbols from each of the first 3 streams.\n             * The final stream will be decoded during the reload phase\n             * to reduce register pressure.\n             */\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);\n            HUF_4X_FOR_EACH_STREAM_WITH_VAR(HUF_4X2_DECODE_SYMBOL, 0);\n\n            /* Decode one symbol from the final stream */\n            HUF_4X2_DECODE_SYMBOL(3, 1);\n\n            /* Decode 4 symbols from the final stream & reload bitstreams.\n             * The final stream is reloaded last, meaning that all 5 symbols\n             * are decoded from the final stream before it is reloaded.\n             */\n            HUF_4X_FOR_EACH_STREAM(HUF_4X2_RELOAD_STREAM);\n        } while (op[3] < olimit);\n    }\n\n#undef HUF_4X2_DECODE_SYMBOL\n#undef HUF_4X2_RELOAD_STREAM\n\n_out:\n\n    /* Save the final values of each of the state variables back to args. */\n    ZSTD_memcpy(&args->bits, &bits, sizeof(bits));\n    ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));\n    ZSTD_memcpy(&args->op, &op, sizeof(op));\n}\n\n\nstatic HUF_FAST_BMI2_ATTRS size_t\nHUF_decompress4X2_usingDTable_internal_fast(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUF_DTable* DTable,\n    HUF_DecompressFastLoopFn loopFn) {\n    void const* dt = DTable + 1;\n    const BYTE* const ilowest = (const BYTE*)cSrc;\n    BYTE* const oend = ZSTD_maybeNullPtrAdd((BYTE*)dst, dstSize);\n    HUF_DecompressFastArgs args;\n    {\n        size_t const ret = HUF_DecompressFastArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);\n        FORWARD_IF_ERROR(ret, \"Failed to init asm args\");\n        if (ret == 0)\n            return 0;\n    }\n\n    assert(args.ip[0] >= args.ilowest);\n    loopFn(&args);\n\n    /* note : op4 already verified within main loop */\n    assert(args.ip[0] >= ilowest);\n    assert(args.ip[1] >= ilowest);\n    assert(args.ip[2] >= ilowest);\n    assert(args.ip[3] >= ilowest);\n    assert(args.op[3] <= oend);\n\n    assert(ilowest == args.ilowest);\n    assert(ilowest + 6 == args.iend[0]);\n    (void)ilowest;\n\n    /* finish bitStreams one by one */\n    {\n        size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* segmentEnd = (BYTE*)dst;\n        int i;\n        for (i = 0; i < 4; ++i) {\n            BIT_DStream_t bit;\n            if (segmentSize <= (size_t)(oend - segmentEnd))\n                segmentEnd += segmentSize;\n            else\n                segmentEnd = oend;\n            FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), \"corruption\");\n            args.op[i] += HUF_decodeStreamX2(args.op[i], &bit, segmentEnd, (HUF_DEltX2 const*)dt, HUF_DECODER_FAST_TABLELOG);\n            if (args.op[i] != segmentEnd)\n                return ERROR(corruption_detected);\n        }\n    }\n\n    /* decoded size */\n    return dstSize;\n}\n\nstatic size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,\n                    size_t cSrcSize, HUF_DTable const* DTable, int flags)\n{\n    HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X2_usingDTable_internal_default;\n    HUF_DecompressFastLoopFn loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop;\n\n#if DYNAMIC_BMI2\n    if (flags & HUF_flags_bmi2) {\n        fallbackFn = HUF_decompress4X2_usingDTable_internal_bmi2;\n# if ZSTD_ENABLE_ASM_X86_64_BMI2\n        if (!(flags & HUF_flags_disableAsm)) {\n            loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;\n        }\n# endif\n    } else {\n        return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n    }\n#endif\n\n#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)\n    if (!(flags & HUF_flags_disableAsm)) {\n        loopFn = HUF_decompress4X2_usingDTable_internal_fast_asm_loop;\n    }\n#endif\n\n    if (HUF_ENABLE_FAST_DECODE && !(flags & HUF_flags_disableFast)) {\n        size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);\n        if (ret != 0)\n            return ret;\n    }\n    return fallbackFn(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nHUF_DGEN(HUF_decompress1X2_usingDTable_internal)\n\nsize_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX2_wksp(DCtx, cSrc, cSrcSize,\n                                               workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress1X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, DCtx, flags);\n}\n\nstatic size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                   const void* cSrc, size_t cSrcSize,\n                                   void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX2_wksp(dctx, cSrc, cSrcSize,\n                                         workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress4X2_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);\n}\n\n#endif /* HUF_FORCE_DECOMPRESS_X1 */\n\n\n/* ***********************************/\n/* Universal decompression selectors */\n/* ***********************************/\n\n\n#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][2 /* single, double */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}},  /* Q==1 : impossible */\n    {{ 150,216}, { 381,119}},   /* Q == 2 : 12-18% */\n    {{ 170,205}, { 514,112}},   /* Q == 3 : 18-25% */\n    {{ 177,199}, { 539,110}},   /* Q == 4 : 25-32% */\n    {{ 197,194}, { 644,107}},   /* Q == 5 : 32-38% */\n    {{ 221,192}, { 735,107}},   /* Q == 6 : 38-44% */\n    {{ 256,189}, { 881,106}},   /* Q == 7 : 44-50% */\n    {{ 359,188}, {1167,109}},   /* Q == 8 : 50-56% */\n    {{ 582,187}, {1570,114}},   /* Q == 9 : 56-62% */\n    {{ 688,187}, {1712,122}},   /* Q ==10 : 62-69% */\n    {{ 825,186}, {1965,136}},   /* Q ==11 : 69-75% */\n    {{ 976,185}, {2131,150}},   /* Q ==12 : 75-81% */\n    {{1180,186}, {2070,175}},   /* Q ==13 : 81-87% */\n    {{1377,185}, {1731,202}},   /* Q ==14 : 87-93% */\n    {{1412,185}, {1695,202}},   /* Q ==15 : 93-99% */\n};\n#endif\n\n/** HUF_selectDecoder() :\n *  Tells which decoder is likely to decode faster,\n *  based on a set of pre-computed metrics.\n * @return : 0==HUF_decompress4X1, 1==HUF_decompress4X2 .\n *  Assumption : 0 < dstSize <= 128 KB */\nU32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)\n{\n    assert(dstSize > 0);\n    assert(dstSize <= 128*1024);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dstSize;\n    (void)cSrcSize;\n    return 0;\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dstSize;\n    (void)cSrcSize;\n    return 1;\n#else\n    /* decoder timing evaluation */\n    {   U32 const Q = (cSrcSize >= dstSize) ? 15 : (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 */\n        U32 const D256 = (U32)(dstSize >> 8);\n        U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);\n        U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);\n        DTime1 += DTime1 >> 5;  /* small advantage to algorithm using less memory, to reduce cache eviction */\n        return DTime1 < DTime0;\n    }\n#endif\n}\n\nsize_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,\n                                  const void* cSrc, size_t cSrcSize,\n                                  void* workSpace, size_t wkspSize, int flags)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags);\n#else\n        return algoNb ? HUF_decompress1X2_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags):\n                        HUF_decompress1X1_DCtx_wksp(dctx, dst, dstSize, cSrc,\n                                cSrcSize, workSpace, wkspSize, flags);\n#endif\n    }\n}\n\n\nsize_t HUF_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#else\n    return dtd.tableType ? HUF_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :\n                           HUF_decompress1X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#endif\n}\n\n#ifndef HUF_FORCE_DECOMPRESS_X2\nsize_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize, flags);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUF_decompress1X1_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx, flags);\n}\n#endif\n\nsize_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int flags)\n{\n    DTableDesc const dtd = HUF_getDTableDesc(DTable);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n    (void)dtd;\n    assert(dtd.tableType == 0);\n    return HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n    (void)dtd;\n    assert(dtd.tableType == 1);\n    return HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#else\n    return dtd.tableType ? HUF_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags) :\n                           HUF_decompress4X1_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable, flags);\n#endif\n}\n\nsize_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int flags)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize == 0) return ERROR(corruption_detected);\n\n    {   U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize);\n#if defined(HUF_FORCE_DECOMPRESS_X1)\n        (void)algoNb;\n        assert(algoNb == 0);\n        return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);\n#elif defined(HUF_FORCE_DECOMPRESS_X2)\n        (void)algoNb;\n        assert(algoNb == 1);\n        return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);\n#else\n        return algoNb ? HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags) :\n                        HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, workSpace, wkspSize, flags);\n#endif\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/decompress/zstd_ddict.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* zstd_ddict.c :\n * concentrates all logic that needs to know the internals of ZSTD_DDict object */\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customFree */\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */\n#include \"../common/cpu.h\"         /* bmi2 */\n#include \"../common/mem.h\"         /* low level memory routines */\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include \"zstd_decompress_internal.h\"\n#include \"zstd_ddict.h\"\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n#  include \"../legacy/zstd_legacy.h\"\n#endif\n\n\n\n/*-*******************************************************\n*  Types\n*********************************************************/\nstruct ZSTD_DDict_s {\n    void* dictBuffer;\n    const void* dictContent;\n    size_t dictSize;\n    ZSTD_entropyDTables_t entropy;\n    U32 dictID;\n    U32 entropyPresent;\n    ZSTD_customMem cMem;\n};  /* typedef'd to ZSTD_DDict within \"zstd.h\" */\n\nconst void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict)\n{\n    assert(ddict != NULL);\n    return ddict->dictContent;\n}\n\nsize_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict)\n{\n    assert(ddict != NULL);\n    return ddict->dictSize;\n}\n\nvoid ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)\n{\n    DEBUGLOG(4, \"ZSTD_copyDDictParameters\");\n    assert(dctx != NULL);\n    assert(ddict != NULL);\n    dctx->dictID = ddict->dictID;\n    dctx->prefixStart = ddict->dictContent;\n    dctx->virtualStart = ddict->dictContent;\n    dctx->dictEnd = (const BYTE*)ddict->dictContent + ddict->dictSize;\n    dctx->previousDstEnd = dctx->dictEnd;\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    dctx->dictContentBeginForFuzzing = dctx->prefixStart;\n    dctx->dictContentEndForFuzzing = dctx->previousDstEnd;\n#endif\n    if (ddict->entropyPresent) {\n        dctx->litEntropy = 1;\n        dctx->fseEntropy = 1;\n        dctx->LLTptr = ddict->entropy.LLTable;\n        dctx->MLTptr = ddict->entropy.MLTable;\n        dctx->OFTptr = ddict->entropy.OFTable;\n        dctx->HUFptr = ddict->entropy.hufTable;\n        dctx->entropy.rep[0] = ddict->entropy.rep[0];\n        dctx->entropy.rep[1] = ddict->entropy.rep[1];\n        dctx->entropy.rep[2] = ddict->entropy.rep[2];\n    } else {\n        dctx->litEntropy = 0;\n        dctx->fseEntropy = 0;\n    }\n}\n\n\nstatic size_t\nZSTD_loadEntropy_intoDDict(ZSTD_DDict* ddict,\n                           ZSTD_dictContentType_e dictContentType)\n{\n    ddict->dictID = 0;\n    ddict->entropyPresent = 0;\n    if (dictContentType == ZSTD_dct_rawContent) return 0;\n\n    if (ddict->dictSize < 8) {\n        if (dictContentType == ZSTD_dct_fullDict)\n            return ERROR(dictionary_corrupted);   /* only accept specified dictionaries */\n        return 0;   /* pure content mode */\n    }\n    {   U32 const magic = MEM_readLE32(ddict->dictContent);\n        if (magic != ZSTD_MAGIC_DICTIONARY) {\n            if (dictContentType == ZSTD_dct_fullDict)\n                return ERROR(dictionary_corrupted);   /* only accept specified dictionaries */\n            return 0;   /* pure content mode */\n        }\n    }\n    ddict->dictID = MEM_readLE32((const char*)ddict->dictContent + ZSTD_FRAMEIDSIZE);\n\n    /* load entropy tables */\n    RETURN_ERROR_IF(ZSTD_isError(ZSTD_loadDEntropy(\n            &ddict->entropy, ddict->dictContent, ddict->dictSize)),\n        dictionary_corrupted, \"\");\n    ddict->entropyPresent = 1;\n    return 0;\n}\n\n\nstatic size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict,\n                                      const void* dict, size_t dictSize,\n                                      ZSTD_dictLoadMethod_e dictLoadMethod,\n                                      ZSTD_dictContentType_e dictContentType)\n{\n    if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dict) || (!dictSize)) {\n        ddict->dictBuffer = NULL;\n        ddict->dictContent = dict;\n        if (!dict) dictSize = 0;\n    } else {\n        void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem);\n        ddict->dictBuffer = internalBuffer;\n        ddict->dictContent = internalBuffer;\n        if (!internalBuffer) return ERROR(memory_allocation);\n        ZSTD_memcpy(internalBuffer, dict, dictSize);\n    }\n    ddict->dictSize = dictSize;\n    ddict->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001);  /* cover both little and big endian */\n\n    /* parse dictionary content */\n    FORWARD_IF_ERROR( ZSTD_loadEntropy_intoDDict(ddict, dictContentType) , \"\");\n\n    return 0;\n}\n\nZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,\n                                      ZSTD_dictLoadMethod_e dictLoadMethod,\n                                      ZSTD_dictContentType_e dictContentType,\n                                      ZSTD_customMem customMem)\n{\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n\n    {   ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem);\n        if (ddict == NULL) return NULL;\n        ddict->cMem = customMem;\n        {   size_t const initResult = ZSTD_initDDict_internal(ddict,\n                                            dict, dictSize,\n                                            dictLoadMethod, dictContentType);\n            if (ZSTD_isError(initResult)) {\n                ZSTD_freeDDict(ddict);\n                return NULL;\n        }   }\n        return ddict;\n    }\n}\n\n/*! ZSTD_createDDict() :\n*   Create a digested dictionary, to start decompression without startup delay.\n*   `dict` content is copied inside DDict.\n*   Consequently, `dict` can be released after `ZSTD_DDict` creation */\nZSTD_DDict* ZSTD_createDDict(const void* dict, size_t dictSize)\n{\n    ZSTD_customMem const allocator = { NULL, NULL, NULL };\n    return ZSTD_createDDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, allocator);\n}\n\n/*! ZSTD_createDDict_byReference() :\n *  Create a digested dictionary, to start decompression without startup delay.\n *  Dictionary content is simply referenced, it will be accessed during decompression.\n *  Warning : dictBuffer must outlive DDict (DDict must be freed before dictBuffer) */\nZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize)\n{\n    ZSTD_customMem const allocator = { NULL, NULL, NULL };\n    return ZSTD_createDDict_advanced(dictBuffer, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, allocator);\n}\n\n\nconst ZSTD_DDict* ZSTD_initStaticDDict(\n                                void* sBuffer, size_t sBufferSize,\n                                const void* dict, size_t dictSize,\n                                ZSTD_dictLoadMethod_e dictLoadMethod,\n                                ZSTD_dictContentType_e dictContentType)\n{\n    size_t const neededSpace = sizeof(ZSTD_DDict)\n                             + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);\n    ZSTD_DDict* const ddict = (ZSTD_DDict*)sBuffer;\n    assert(sBuffer != NULL);\n    assert(dict != NULL);\n    if ((size_t)sBuffer & 7) return NULL;   /* 8-aligned */\n    if (sBufferSize < neededSpace) return NULL;\n    if (dictLoadMethod == ZSTD_dlm_byCopy) {\n        ZSTD_memcpy(ddict+1, dict, dictSize);  /* local copy */\n        dict = ddict+1;\n    }\n    if (ZSTD_isError( ZSTD_initDDict_internal(ddict,\n                                              dict, dictSize,\n                                              ZSTD_dlm_byRef, dictContentType) ))\n        return NULL;\n    return ddict;\n}\n\n\nsize_t ZSTD_freeDDict(ZSTD_DDict* ddict)\n{\n    if (ddict==NULL) return 0;   /* support free on NULL */\n    {   ZSTD_customMem const cMem = ddict->cMem;\n        ZSTD_customFree(ddict->dictBuffer, cMem);\n        ZSTD_customFree(ddict, cMem);\n        return 0;\n    }\n}\n\n/*! ZSTD_estimateDDictSize() :\n *  Estimate amount of memory that will be needed to create a dictionary for decompression.\n *  Note : dictionary created by reference using ZSTD_dlm_byRef are smaller */\nsize_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod)\n{\n    return sizeof(ZSTD_DDict) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : dictSize);\n}\n\nsize_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict)\n{\n    if (ddict==NULL) return 0;   /* support sizeof on NULL */\n    return sizeof(*ddict) + (ddict->dictBuffer ? ddict->dictSize : 0) ;\n}\n\n/*! ZSTD_getDictID_fromDDict() :\n *  Provides the dictID of the dictionary loaded into `ddict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nunsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict)\n{\n    if (ddict==NULL) return 0;\n    return ddict->dictID;\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/decompress/zstd_ddict.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#ifndef ZSTD_DDICT_H\n#define ZSTD_DDICT_H\n\n/*-*******************************************************\n *  Dependencies\n *********************************************************/\n#include \"../common/zstd_deps.h\"   /* size_t */\n#include \"../zstd.h\"     /* ZSTD_DDict, and several public functions */\n\n\n/*-*******************************************************\n *  Interface\n *********************************************************/\n\n/* note: several prototypes are already published in `zstd.h` :\n * ZSTD_createDDict()\n * ZSTD_createDDict_byReference()\n * ZSTD_createDDict_advanced()\n * ZSTD_freeDDict()\n * ZSTD_initStaticDDict()\n * ZSTD_sizeof_DDict()\n * ZSTD_estimateDDictSize()\n * ZSTD_getDictID_fromDict()\n */\n\nconst void* ZSTD_DDict_dictContent(const ZSTD_DDict* ddict);\nsize_t ZSTD_DDict_dictSize(const ZSTD_DDict* ddict);\n\nvoid ZSTD_copyDDictParameters(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);\n\n\n\n#endif /* ZSTD_DDICT_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/decompress/zstd_decompress.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTD_decompress() allocates its context,\n * on stack (0), or into heap (1, default; requires malloc()).\n * Note that functions with explicit context such as ZSTD_decompressDCtx() are unaffected.\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif\n\n/*!\n*  LEGACY_SUPPORT :\n*  if set to 1+, ZSTD_decompress() can decode older formats (v0.1+)\n*/\n#ifndef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 0\n#endif\n\n/*!\n *  MAXWINDOWSIZE_DEFAULT :\n *  maximum window size accepted by DStream __by default__.\n *  Frames requiring more memory will be rejected.\n *  It's possible to set a different limit using ZSTD_DCtx_setMaxWindowSize().\n */\n#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT\n#  define ZSTD_MAXWINDOWSIZE_DEFAULT (((U32)1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT) + 1)\n#endif\n\n/*!\n *  NO_FORWARD_PROGRESS_MAX :\n *  maximum allowed nb of calls to ZSTD_decompressStream()\n *  without any forward progress\n *  (defined as: no byte read from input, and no byte flushed to output)\n *  before triggering an error.\n */\n#ifndef ZSTD_NO_FORWARD_PROGRESS_MAX\n#  define ZSTD_NO_FORWARD_PROGRESS_MAX 16\n#endif\n\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */\n#include \"../common/allocations.h\"  /* ZSTD_customMalloc, ZSTD_customCalloc, ZSTD_customFree */\n#include \"../common/error_private.h\"\n#include \"../common/zstd_internal.h\"  /* blockProperties_t */\n#include \"../common/mem.h\"         /* low level memory routines */\n#include \"../common/bits.h\"  /* ZSTD_highbit32 */\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include <xxhash.h> /* XXH64_reset, XXH64_update, XXH64_digest, XXH64 */\n#include \"zstd_decompress_internal.h\"   /* ZSTD_DCtx */\n#include \"zstd_ddict.h\"  /* ZSTD_DDictDictContent */\n#include \"zstd_decompress_block.h\"   /* ZSTD_decompressBlock_internal */\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n#  include \"../legacy/zstd_legacy.h\"\n#endif\n\n\n\n/*************************************\n * Multiple DDicts Hashset internals *\n *************************************/\n\n#define DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT 4\n#define DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT 3  /* These two constants represent SIZE_MULT/COUNT_MULT load factor without using a float.\n                                                    * Currently, that means a 0.75 load factor.\n                                                    * So, if count * COUNT_MULT / size * SIZE_MULT != 0, then we've exceeded\n                                                    * the load factor of the ddict hash set.\n                                                    */\n\n#define DDICT_HASHSET_TABLE_BASE_SIZE 64\n#define DDICT_HASHSET_RESIZE_FACTOR 2\n\n/* Hash function to determine starting position of dict insertion within the table\n * Returns an index between [0, hashSet->ddictPtrTableSize]\n */\nstatic size_t ZSTD_DDictHashSet_getIndex(const ZSTD_DDictHashSet* hashSet, U32 dictID) {\n    const U64 hash = XXH64(&dictID, sizeof(U32), 0);\n    /* DDict ptr table size is a multiple of 2, use size - 1 as mask to get index within [0, hashSet->ddictPtrTableSize) */\n    return hash & (hashSet->ddictPtrTableSize - 1);\n}\n\n/* Adds DDict to a hashset without resizing it.\n * If inserting a DDict with a dictID that already exists in the set, replaces the one in the set.\n * Returns 0 if successful, or a zstd error code if something went wrong.\n */\nstatic size_t ZSTD_DDictHashSet_emplaceDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict) {\n    const U32 dictID = ZSTD_getDictID_fromDDict(ddict);\n    size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);\n    const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;\n    RETURN_ERROR_IF(hashSet->ddictPtrCount == hashSet->ddictPtrTableSize, GENERIC, \"Hash set is full!\");\n    DEBUGLOG(4, \"Hashed index: for dictID: %u is %zu\", dictID, idx);\n    while (hashSet->ddictPtrTable[idx] != NULL) {\n        /* Replace existing ddict if inserting ddict with same dictID */\n        if (ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]) == dictID) {\n            DEBUGLOG(4, \"DictID already exists, replacing rather than adding\");\n            hashSet->ddictPtrTable[idx] = ddict;\n            return 0;\n        }\n        idx &= idxRangeMask;\n        idx++;\n    }\n    DEBUGLOG(4, \"Final idx after probing for dictID %u is: %zu\", dictID, idx);\n    hashSet->ddictPtrTable[idx] = ddict;\n    hashSet->ddictPtrCount++;\n    return 0;\n}\n\n/* Expands hash table by factor of DDICT_HASHSET_RESIZE_FACTOR and\n * rehashes all values, allocates new table, frees old table.\n * Returns 0 on success, otherwise a zstd error code.\n */\nstatic size_t ZSTD_DDictHashSet_expand(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {\n    size_t newTableSize = hashSet->ddictPtrTableSize * DDICT_HASHSET_RESIZE_FACTOR;\n    const ZSTD_DDict** newTable = (const ZSTD_DDict**)ZSTD_customCalloc(sizeof(ZSTD_DDict*) * newTableSize, customMem);\n    const ZSTD_DDict** oldTable = hashSet->ddictPtrTable;\n    size_t oldTableSize = hashSet->ddictPtrTableSize;\n    size_t i;\n\n    DEBUGLOG(4, \"Expanding DDict hash table! Old size: %zu new size: %zu\", oldTableSize, newTableSize);\n    RETURN_ERROR_IF(!newTable, memory_allocation, \"Expanded hashset allocation failed!\");\n    hashSet->ddictPtrTable = newTable;\n    hashSet->ddictPtrTableSize = newTableSize;\n    hashSet->ddictPtrCount = 0;\n    for (i = 0; i < oldTableSize; ++i) {\n        if (oldTable[i] != NULL) {\n            FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, oldTable[i]), \"\");\n        }\n    }\n    ZSTD_customFree((void*)oldTable, customMem);\n    DEBUGLOG(4, \"Finished re-hash\");\n    return 0;\n}\n\n/* Fetches a DDict with the given dictID\n * Returns the ZSTD_DDict* with the requested dictID. If it doesn't exist, then returns NULL.\n */\nstatic const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet, U32 dictID) {\n    size_t idx = ZSTD_DDictHashSet_getIndex(hashSet, dictID);\n    const size_t idxRangeMask = hashSet->ddictPtrTableSize - 1;\n    DEBUGLOG(4, \"Hashed index: for dictID: %u is %zu\", dictID, idx);\n    for (;;) {\n        size_t currDictID = ZSTD_getDictID_fromDDict(hashSet->ddictPtrTable[idx]);\n        if (currDictID == dictID || currDictID == 0) {\n            /* currDictID == 0 implies a NULL ddict entry */\n            break;\n        } else {\n            idx &= idxRangeMask;    /* Goes to start of table when we reach the end */\n            idx++;\n        }\n    }\n    DEBUGLOG(4, \"Final idx after probing for dictID %u is: %zu\", dictID, idx);\n    return hashSet->ddictPtrTable[idx];\n}\n\n/* Allocates space for and returns a ddict hash set\n * The hash set's ZSTD_DDict* table has all values automatically set to NULL to begin with.\n * Returns NULL if allocation failed.\n */\nstatic ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {\n    ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);\n    DEBUGLOG(4, \"Allocating new hash set\");\n    if (!ret)\n        return NULL;\n    ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);\n    if (!ret->ddictPtrTable) {\n        ZSTD_customFree(ret, customMem);\n        return NULL;\n    }\n    ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;\n    ret->ddictPtrCount = 0;\n    return ret;\n}\n\n/* Frees the table of ZSTD_DDict* within a hashset, then frees the hashset itself.\n * Note: The ZSTD_DDict* within the table are NOT freed.\n */\nstatic void ZSTD_freeDDictHashSet(ZSTD_DDictHashSet* hashSet, ZSTD_customMem customMem) {\n    DEBUGLOG(4, \"Freeing ddict hash set\");\n    if (hashSet && hashSet->ddictPtrTable) {\n        ZSTD_customFree((void*)hashSet->ddictPtrTable, customMem);\n    }\n    if (hashSet) {\n        ZSTD_customFree(hashSet, customMem);\n    }\n}\n\n/* Public function: Adds a DDict into the ZSTD_DDictHashSet, possibly triggering a resize of the hash set.\n * Returns 0 on success, or a ZSTD error.\n */\nstatic size_t ZSTD_DDictHashSet_addDDict(ZSTD_DDictHashSet* hashSet, const ZSTD_DDict* ddict, ZSTD_customMem customMem) {\n    DEBUGLOG(4, \"Adding dict ID: %u to hashset with - Count: %zu Tablesize: %zu\", ZSTD_getDictID_fromDDict(ddict), hashSet->ddictPtrCount, hashSet->ddictPtrTableSize);\n    if (hashSet->ddictPtrCount * DDICT_HASHSET_MAX_LOAD_FACTOR_COUNT_MULT / hashSet->ddictPtrTableSize * DDICT_HASHSET_MAX_LOAD_FACTOR_SIZE_MULT != 0) {\n        FORWARD_IF_ERROR(ZSTD_DDictHashSet_expand(hashSet, customMem), \"\");\n    }\n    FORWARD_IF_ERROR(ZSTD_DDictHashSet_emplaceDDict(hashSet, ddict), \"\");\n    return 0;\n}\n\n/*-*************************************************************\n*   Context management\n***************************************************************/\nsize_t ZSTD_sizeof_DCtx (const ZSTD_DCtx* dctx)\n{\n    if (dctx==NULL) return 0;   /* support sizeof NULL */\n    return sizeof(*dctx)\n           + ZSTD_sizeof_DDict(dctx->ddictLocal)\n           + dctx->inBuffSize + dctx->outBuffSize;\n}\n\nsize_t ZSTD_estimateDCtxSize(void) { return sizeof(ZSTD_DCtx); }\n\n\nstatic size_t ZSTD_startingInputLength(ZSTD_format_e format)\n{\n    size_t const startingInputLength = ZSTD_FRAMEHEADERSIZE_PREFIX(format);\n    /* only supports formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless */\n    assert( (format == ZSTD_f_zstd1) || (format == ZSTD_f_zstd1_magicless) );\n    return startingInputLength;\n}\n\nstatic void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)\n{\n    assert(dctx->streamStage == zdss_init);\n    dctx->format = ZSTD_f_zstd1;\n    dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;\n    dctx->outBufferMode = ZSTD_bm_buffered;\n    dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;\n    dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;\n    dctx->disableHufAsm = 0;\n    dctx->maxBlockSizeParam = 0;\n}\n\nstatic void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)\n{\n    dctx->staticSize  = 0;\n    dctx->ddict       = NULL;\n    dctx->ddictLocal  = NULL;\n    dctx->dictEnd     = NULL;\n    dctx->ddictIsCold = 0;\n    dctx->dictUses = ZSTD_dont_use;\n    dctx->inBuff      = NULL;\n    dctx->inBuffSize  = 0;\n    dctx->outBuffSize = 0;\n    dctx->streamStage = zdss_init;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n    dctx->legacyContext = NULL;\n    dctx->previousLegacyVersion = 0;\n#endif\n    dctx->noForwardProgress = 0;\n    dctx->oversizedDuration = 0;\n    dctx->isFrameDecompression = 1;\n#if DYNAMIC_BMI2\n    dctx->bmi2 = ZSTD_cpuSupportsBmi2();\n#endif\n    dctx->ddictSet = NULL;\n    ZSTD_DCtx_resetParameters(dctx);\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    dctx->dictContentEndForFuzzing = NULL;\n#endif\n}\n\nZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)\n{\n    ZSTD_DCtx* const dctx = (ZSTD_DCtx*) workspace;\n\n    if ((size_t)workspace & 7) return NULL;  /* 8-aligned */\n    if (workspaceSize < sizeof(ZSTD_DCtx)) return NULL;  /* minimum size */\n\n    ZSTD_initDCtx_internal(dctx);\n    dctx->staticSize = workspaceSize;\n    dctx->inBuff = (char*)(dctx+1);\n    return dctx;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {\n    if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;\n\n    {   ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);\n        if (!dctx) return NULL;\n        dctx->customMem = customMem;\n        ZSTD_initDCtx_internal(dctx);\n        return dctx;\n    }\n}\n\nZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)\n{\n    return ZSTD_createDCtx_internal(customMem);\n}\n\nZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    DEBUGLOG(3, \"ZSTD_createDCtx\");\n    return ZSTD_createDCtx_internal(ZSTD_defaultCMem);\n}\n\nstatic void ZSTD_clearDict(ZSTD_DCtx* dctx)\n{\n    ZSTD_freeDDict(dctx->ddictLocal);\n    dctx->ddictLocal = NULL;\n    dctx->ddict = NULL;\n    dctx->dictUses = ZSTD_dont_use;\n}\n\nsize_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    if (dctx==NULL) return 0;   /* support free on NULL */\n    RETURN_ERROR_IF(dctx->staticSize, memory_allocation, \"not compatible with static DCtx\");\n    {   ZSTD_customMem const cMem = dctx->customMem;\n        ZSTD_clearDict(dctx);\n        ZSTD_customFree(dctx->inBuff, cMem);\n        dctx->inBuff = NULL;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n        if (dctx->legacyContext)\n            ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion);\n#endif\n        if (dctx->ddictSet) {\n            ZSTD_freeDDictHashSet(dctx->ddictSet, cMem);\n            dctx->ddictSet = NULL;\n        }\n        ZSTD_customFree(dctx, cMem);\n        return 0;\n    }\n}\n\n/* no longer useful */\nvoid ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx)\n{\n    size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx);\n    ZSTD_memcpy(dstDCtx, srcDCtx, toCopy);  /* no need to copy workspace */\n}\n\n/* Given a dctx with a digested frame params, re-selects the correct ZSTD_DDict based on\n * the requested dict ID from the frame. If there exists a reference to the correct ZSTD_DDict, then\n * accordingly sets the ddict to be used to decompress the frame.\n *\n * If no DDict is found, then no action is taken, and the ZSTD_DCtx::ddict remains as-is.\n *\n * ZSTD_d_refMultipleDDicts must be enabled for this function to be called.\n */\nstatic void ZSTD_DCtx_selectFrameDDict(ZSTD_DCtx* dctx) {\n    assert(dctx->refMultipleDDicts && dctx->ddictSet);\n    DEBUGLOG(4, \"Adjusting DDict based on requested dict ID from frame\");\n    if (dctx->ddict) {\n        const ZSTD_DDict* frameDDict = ZSTD_DDictHashSet_getDDict(dctx->ddictSet, dctx->fParams.dictID);\n        if (frameDDict) {\n            DEBUGLOG(4, \"DDict found!\");\n            ZSTD_clearDict(dctx);\n            dctx->dictID = dctx->fParams.dictID;\n            dctx->ddict = frameDDict;\n            dctx->dictUses = ZSTD_use_indefinitely;\n        }\n    }\n}\n\n\n/*-*************************************************************\n *   Frame header decoding\n ***************************************************************/\n\n/*! ZSTD_isFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier.\n *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.\n *  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.\n *  Note 3 : Skippable Frame Identifiers are considered valid. */\nunsigned ZSTD_isFrame(const void* buffer, size_t size)\n{\n    if (size < ZSTD_FRAMEIDSIZE) return 0;\n    {   U32 const magic = MEM_readLE32(buffer);\n        if (magic == ZSTD_MAGICNUMBER) return 1;\n        if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;\n    }\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n    if (ZSTD_isLegacy(buffer, size)) return 1;\n#endif\n    return 0;\n}\n\n/*! ZSTD_isSkippableFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.\n *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.\n */\nunsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)\n{\n    if (size < ZSTD_FRAMEIDSIZE) return 0;\n    {   U32 const magic = MEM_readLE32(buffer);\n        if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;\n    }\n    return 0;\n}\n\n/** ZSTD_frameHeaderSize_internal() :\n *  srcSize must be large enough to reach header size fields.\n *  note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.\n * @return : size of the Frame Header\n *           or an error code, which can be tested with ZSTD_isError() */\nstatic size_t ZSTD_frameHeaderSize_internal(const void* src, size_t srcSize, ZSTD_format_e format)\n{\n    size_t const minInputSize = ZSTD_startingInputLength(format);\n    RETURN_ERROR_IF(srcSize < minInputSize, srcSize_wrong, \"\");\n\n    {   BYTE const fhd = ((const BYTE*)src)[minInputSize-1];\n        U32 const dictID= fhd & 3;\n        U32 const singleSegment = (fhd >> 5) & 1;\n        U32 const fcsId = fhd >> 6;\n        return minInputSize + !singleSegment\n             + ZSTD_did_fieldSize[dictID] + ZSTD_fcs_fieldSize[fcsId]\n             + (singleSegment && !fcsId);\n    }\n}\n\n/** ZSTD_frameHeaderSize() :\n *  srcSize must be >= ZSTD_frameHeaderSize_prefix.\n * @return : size of the Frame Header,\n *           or an error code (if srcSize is too small) */\nsize_t ZSTD_frameHeaderSize(const void* src, size_t srcSize)\n{\n    return ZSTD_frameHeaderSize_internal(src, srcSize, ZSTD_f_zstd1);\n}\n\n\n/** ZSTD_getFrameHeader_advanced() :\n *  decode Frame Header, or require larger `srcSize`.\n *  note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless\n * @return : 0, `zfhPtr` is correctly filled,\n *          >0, `srcSize` is too small, value is wanted `srcSize` amount,\n**           or an error code, which can be tested using ZSTD_isError() */\nsize_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t const minInputSize = ZSTD_startingInputLength(format);\n\n    DEBUGLOG(5, \"ZSTD_getFrameHeader_advanced: minInputSize = %zu, srcSize = %zu\", minInputSize, srcSize);\n\n    if (srcSize > 0) {\n        /* note : technically could be considered an assert(), since it's an invalid entry */\n        RETURN_ERROR_IF(src==NULL, GENERIC, \"invalid parameter : src==NULL, but srcSize>0\");\n    }\n    if (srcSize < minInputSize) {\n        if (srcSize > 0 && format != ZSTD_f_zstd1_magicless) {\n            /* when receiving less than @minInputSize bytes,\n             * control these bytes at least correspond to a supported magic number\n             * in order to error out early if they don't.\n            **/\n            size_t const toCopy = MIN(4, srcSize);\n            unsigned char hbuf[4]; MEM_writeLE32(hbuf, ZSTD_MAGICNUMBER);\n            assert(src != NULL);\n            ZSTD_memcpy(hbuf, src, toCopy);\n            if ( MEM_readLE32(hbuf) != ZSTD_MAGICNUMBER ) {\n                /* not a zstd frame : let's check if it's a skippable frame */\n                MEM_writeLE32(hbuf, ZSTD_MAGIC_SKIPPABLE_START);\n                ZSTD_memcpy(hbuf, src, toCopy);\n                if ((MEM_readLE32(hbuf) & ZSTD_MAGIC_SKIPPABLE_MASK) != ZSTD_MAGIC_SKIPPABLE_START) {\n                    RETURN_ERROR(prefix_unknown,\n                                \"first bytes don't correspond to any supported magic number\");\n        }   }   }\n        return minInputSize;\n    }\n\n    ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));   /* not strictly necessary, but static analyzers may not understand that zfhPtr will be read only if return value is zero, since they are 2 different signals */\n    if ( (format != ZSTD_f_zstd1_magicless)\n      && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) {\n        if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n            /* skippable frame */\n            if (srcSize < ZSTD_SKIPPABLEHEADERSIZE)\n                return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */\n            ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr));\n            zfhPtr->frameType = ZSTD_skippableFrame;\n            zfhPtr->dictID = MEM_readLE32(src) - ZSTD_MAGIC_SKIPPABLE_START;\n            zfhPtr->headerSize = ZSTD_SKIPPABLEHEADERSIZE;\n            zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE);\n            return 0;\n        }\n        RETURN_ERROR(prefix_unknown, \"\");\n    }\n\n    /* ensure there is enough `srcSize` to fully read/decode frame header */\n    {   size_t const fhsize = ZSTD_frameHeaderSize_internal(src, srcSize, format);\n        if (srcSize < fhsize) return fhsize;\n        zfhPtr->headerSize = (U32)fhsize;\n    }\n\n    {   BYTE const fhdByte = ip[minInputSize-1];\n        size_t pos = minInputSize;\n        U32 const dictIDSizeCode = fhdByte&3;\n        U32 const checksumFlag = (fhdByte>>2)&1;\n        U32 const singleSegment = (fhdByte>>5)&1;\n        U32 const fcsID = fhdByte>>6;\n        U64 windowSize = 0;\n        U32 dictID = 0;\n        U64 frameContentSize = ZSTD_CONTENTSIZE_UNKNOWN;\n        RETURN_ERROR_IF((fhdByte & 0x08) != 0, frameParameter_unsupported,\n                        \"reserved bits, must be zero\");\n\n        if (!singleSegment) {\n            BYTE const wlByte = ip[pos++];\n            U32 const windowLog = (wlByte >> 3) + ZSTD_WINDOWLOG_ABSOLUTEMIN;\n            RETURN_ERROR_IF(windowLog > ZSTD_WINDOWLOG_MAX, frameParameter_windowTooLarge, \"\");\n            windowSize = (1ULL << windowLog);\n            windowSize += (windowSize >> 3) * (wlByte&7);\n        }\n        switch(dictIDSizeCode)\n        {\n            default:\n                assert(0);  /* impossible */\n                ZSTD_FALLTHROUGH;\n            case 0 : break;\n            case 1 : dictID = ip[pos]; pos++; break;\n            case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;\n            case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;\n        }\n        switch(fcsID)\n        {\n            default:\n                assert(0);  /* impossible */\n                ZSTD_FALLTHROUGH;\n            case 0 : if (singleSegment) frameContentSize = ip[pos]; break;\n            case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;\n            case 2 : frameContentSize = MEM_readLE32(ip+pos); break;\n            case 3 : frameContentSize = MEM_readLE64(ip+pos); break;\n        }\n        if (singleSegment) windowSize = frameContentSize;\n\n        zfhPtr->frameType = ZSTD_frame;\n        zfhPtr->frameContentSize = frameContentSize;\n        zfhPtr->windowSize = windowSize;\n        zfhPtr->blockSizeMax = (unsigned) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);\n        zfhPtr->dictID = dictID;\n        zfhPtr->checksumFlag = checksumFlag;\n    }\n    return 0;\n}\n\n/** ZSTD_getFrameHeader() :\n *  decode Frame Header, or require larger `srcSize`.\n *  note : this function does not consume input, it only reads it.\n * @return : 0, `zfhPtr` is correctly filled,\n *          >0, `srcSize` is too small, value is wanted `srcSize` amount,\n *           or an error code, which can be tested using ZSTD_isError() */\nsize_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize)\n{\n    return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);\n}\n\n/** ZSTD_getFrameContentSize() :\n *  compatible with legacy mode\n * @return : decompressed size of the single frame pointed to be `src` if known, otherwise\n *         - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined\n *         - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small) */\nunsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize)\n{\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n    if (ZSTD_isLegacy(src, srcSize)) {\n        unsigned long long const ret = ZSTD_getDecompressedSize_legacy(src, srcSize);\n        return ret == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : ret;\n    }\n#endif\n    {   ZSTD_FrameHeader zfh;\n        if (ZSTD_getFrameHeader(&zfh, src, srcSize) != 0)\n            return ZSTD_CONTENTSIZE_ERROR;\n        if (zfh.frameType == ZSTD_skippableFrame) {\n            return 0;\n        } else {\n            return zfh.frameContentSize;\n    }   }\n}\n\nstatic size_t readSkippableFrameSize(void const* src, size_t srcSize)\n{\n    size_t const skippableHeaderSize = ZSTD_SKIPPABLEHEADERSIZE;\n    U32 sizeU32;\n\n    RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, \"\");\n\n    sizeU32 = MEM_readLE32((BYTE const*)src + ZSTD_FRAMEIDSIZE);\n    RETURN_ERROR_IF((U32)(sizeU32 + ZSTD_SKIPPABLEHEADERSIZE) < sizeU32,\n                    frameParameter_unsupported, \"\");\n    {   size_t const skippableSize = skippableHeaderSize + sizeU32;\n        RETURN_ERROR_IF(skippableSize > srcSize, srcSize_wrong, \"\");\n        return skippableSize;\n    }\n}\n\n/*! ZSTD_readSkippableFrame() :\n * Retrieves content of a skippable frame, and writes it to dst buffer.\n *\n * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,\n * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START.  This can be NULL if the caller is not interested\n * in the magicVariant.\n *\n * Returns an error if destination buffer is not large enough, or if this is not a valid skippable frame.\n *\n * @return : number of bytes written or a ZSTD error.\n */\nsize_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,\n                               unsigned* magicVariant,  /* optional, can be NULL */\n                         const void* src, size_t srcSize)\n{\n    RETURN_ERROR_IF(srcSize < ZSTD_SKIPPABLEHEADERSIZE, srcSize_wrong, \"\");\n\n    {   U32 const magicNumber = MEM_readLE32(src);\n        size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);\n        size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;\n\n        /* check input validity */\n        RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, \"\");\n        RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, \"\");\n        RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, \"\");\n\n        /* deliver payload */\n        if (skippableContentSize > 0  && dst != NULL)\n            ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);\n        if (magicVariant != NULL)\n            *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;\n        return skippableContentSize;\n    }\n}\n\n/** ZSTD_findDecompressedSize() :\n *  `srcSize` must be the exact length of some number of ZSTD compressed and/or\n *      skippable frames\n *  note: compatible with legacy mode\n * @return : decompressed size of the frames contained */\nunsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)\n{\n    unsigned long long totalDstSize = 0;\n\n    while (srcSize >= ZSTD_startingInputLength(ZSTD_f_zstd1)) {\n        U32 const magicNumber = MEM_readLE32(src);\n\n        if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n            size_t const skippableSize = readSkippableFrameSize(src, srcSize);\n            if (ZSTD_isError(skippableSize)) return ZSTD_CONTENTSIZE_ERROR;\n            assert(skippableSize <= srcSize);\n\n            src = (const BYTE *)src + skippableSize;\n            srcSize -= skippableSize;\n            continue;\n        }\n\n        {   unsigned long long const fcs = ZSTD_getFrameContentSize(src, srcSize);\n            if (fcs >= ZSTD_CONTENTSIZE_ERROR) return fcs;\n\n            if (totalDstSize + fcs < totalDstSize)\n                return ZSTD_CONTENTSIZE_ERROR; /* check for overflow */\n            totalDstSize += fcs;\n        }\n        /* skip to next frame */\n        {   size_t const frameSrcSize = ZSTD_findFrameCompressedSize(src, srcSize);\n            if (ZSTD_isError(frameSrcSize)) return ZSTD_CONTENTSIZE_ERROR;\n            assert(frameSrcSize <= srcSize);\n\n            src = (const BYTE *)src + frameSrcSize;\n            srcSize -= frameSrcSize;\n        }\n    }  /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */\n\n    if (srcSize) return ZSTD_CONTENTSIZE_ERROR;\n\n    return totalDstSize;\n}\n\n/** ZSTD_getDecompressedSize() :\n *  compatible with legacy mode\n * @return : decompressed size if known, 0 otherwise\n             note : 0 can mean any of the following :\n                   - frame content is empty\n                   - decompressed size field is not present in frame header\n                   - frame header unknown / not supported\n                   - frame header not complete (`srcSize` too small) */\nunsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize)\n{\n    unsigned long long const ret = ZSTD_getFrameContentSize(src, srcSize);\n    ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_ERROR < ZSTD_CONTENTSIZE_UNKNOWN);\n    return (ret >= ZSTD_CONTENTSIZE_ERROR) ? 0 : ret;\n}\n\n\n/** ZSTD_decodeFrameHeader() :\n * `headerSize` must be the size provided by ZSTD_frameHeaderSize().\n * If multiple DDict references are enabled, also will choose the correct DDict to use.\n * @return : 0 if success, or an error code, which can be tested using ZSTD_isError() */\nstatic size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t headerSize)\n{\n    size_t const result = ZSTD_getFrameHeader_advanced(&(dctx->fParams), src, headerSize, dctx->format);\n    if (ZSTD_isError(result)) return result;    /* invalid header */\n    RETURN_ERROR_IF(result>0, srcSize_wrong, \"headerSize too small\");\n\n    /* Reference DDict requested by frame if dctx references multiple ddicts */\n    if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts && dctx->ddictSet) {\n        ZSTD_DCtx_selectFrameDDict(dctx);\n    }\n\n#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    /* Skip the dictID check in fuzzing mode, because it makes the search\n     * harder.\n     */\n    RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID),\n                    dictionary_wrong, \"\");\n#endif\n    dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0;\n    if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0);\n    dctx->processedCSize += headerSize;\n    return 0;\n}\n\nstatic ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret)\n{\n    ZSTD_frameSizeInfo frameSizeInfo;\n    frameSizeInfo.compressedSize = ret;\n    frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;\n    return frameSizeInfo;\n}\n\nstatic ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize, ZSTD_format_e format)\n{\n    ZSTD_frameSizeInfo frameSizeInfo;\n    ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo));\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n    if (format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize))\n        return ZSTD_findFrameSizeInfoLegacy(src, srcSize);\n#endif\n\n    if (format == ZSTD_f_zstd1 && (srcSize >= ZSTD_SKIPPABLEHEADERSIZE)\n        && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n        frameSizeInfo.compressedSize = readSkippableFrameSize(src, srcSize);\n        assert(ZSTD_isError(frameSizeInfo.compressedSize) ||\n               frameSizeInfo.compressedSize <= srcSize);\n        return frameSizeInfo;\n    } else {\n        const BYTE* ip = (const BYTE*)src;\n        const BYTE* const ipstart = ip;\n        size_t remainingSize = srcSize;\n        size_t nbBlocks = 0;\n        ZSTD_FrameHeader zfh;\n\n        /* Extract Frame Header */\n        {   size_t const ret = ZSTD_getFrameHeader_advanced(&zfh, src, srcSize, format);\n            if (ZSTD_isError(ret))\n                return ZSTD_errorFrameSizeInfo(ret);\n            if (ret > 0)\n                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));\n        }\n\n        ip += zfh.headerSize;\n        remainingSize -= zfh.headerSize;\n\n        /* Iterate over each block */\n        while (1) {\n            blockProperties_t blockProperties;\n            size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n            if (ZSTD_isError(cBlockSize))\n                return ZSTD_errorFrameSizeInfo(cBlockSize);\n\n            if (ZSTD_blockHeaderSize + cBlockSize > remainingSize)\n                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));\n\n            ip += ZSTD_blockHeaderSize + cBlockSize;\n            remainingSize -= ZSTD_blockHeaderSize + cBlockSize;\n            nbBlocks++;\n\n            if (blockProperties.lastBlock) break;\n        }\n\n        /* Final frame content checksum */\n        if (zfh.checksumFlag) {\n            if (remainingSize < 4)\n                return ZSTD_errorFrameSizeInfo(ERROR(srcSize_wrong));\n            ip += 4;\n        }\n\n        frameSizeInfo.nbBlocks = nbBlocks;\n        frameSizeInfo.compressedSize = (size_t)(ip - ipstart);\n        frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN)\n                                        ? zfh.frameContentSize\n                                        : (unsigned long long)nbBlocks * zfh.blockSizeMax;\n        return frameSizeInfo;\n    }\n}\n\nstatic size_t ZSTD_findFrameCompressedSize_advanced(const void *src, size_t srcSize, ZSTD_format_e format) {\n    ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, format);\n    return frameSizeInfo.compressedSize;\n}\n\n/** ZSTD_findFrameCompressedSize() :\n * See docs in zstd.h\n * Note: compatible with legacy mode */\nsize_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize)\n{\n    return ZSTD_findFrameCompressedSize_advanced(src, srcSize, ZSTD_f_zstd1);\n}\n\n/** ZSTD_decompressBound() :\n *  compatible with legacy mode\n *  `src` must point to the start of a ZSTD frame or a skippable frame\n *  `srcSize` must be at least as large as the frame contained\n *  @return : the maximum decompressed size of the compressed source\n */\nunsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)\n{\n    unsigned long long bound = 0;\n    /* Iterate over each frame */\n    while (srcSize > 0) {\n        ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);\n        size_t const compressedSize = frameSizeInfo.compressedSize;\n        unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;\n        if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)\n            return ZSTD_CONTENTSIZE_ERROR;\n        assert(srcSize >= compressedSize);\n        src = (const BYTE*)src + compressedSize;\n        srcSize -= compressedSize;\n        bound += decompressedBound;\n    }\n    return bound;\n}\n\nsize_t ZSTD_decompressionMargin(void const* src, size_t srcSize)\n{\n    size_t margin = 0;\n    unsigned maxBlockSize = 0;\n\n    /* Iterate over each frame */\n    while (srcSize > 0) {\n        ZSTD_frameSizeInfo const frameSizeInfo = ZSTD_findFrameSizeInfo(src, srcSize, ZSTD_f_zstd1);\n        size_t const compressedSize = frameSizeInfo.compressedSize;\n        unsigned long long const decompressedBound = frameSizeInfo.decompressedBound;\n        ZSTD_FrameHeader zfh;\n\n        FORWARD_IF_ERROR(ZSTD_getFrameHeader(&zfh, src, srcSize), \"\");\n        if (ZSTD_isError(compressedSize) || decompressedBound == ZSTD_CONTENTSIZE_ERROR)\n            return ERROR(corruption_detected);\n\n        if (zfh.frameType == ZSTD_frame) {\n            /* Add the frame header to our margin */\n            margin += zfh.headerSize;\n            /* Add the checksum to our margin */\n            margin += zfh.checksumFlag ? 4 : 0;\n            /* Add 3 bytes per block */\n            margin += 3 * frameSizeInfo.nbBlocks;\n\n            /* Compute the max block size */\n            maxBlockSize = MAX(maxBlockSize, zfh.blockSizeMax);\n        } else {\n            assert(zfh.frameType == ZSTD_skippableFrame);\n            /* Add the entire skippable frame size to our margin. */\n            margin += compressedSize;\n        }\n\n        assert(srcSize >= compressedSize);\n        src = (const BYTE*)src + compressedSize;\n        srcSize -= compressedSize;\n    }\n\n    /* Add the max block size back to the margin. */\n    margin += maxBlockSize;\n\n    return margin;\n}\n\n/*-*************************************************************\n *   Frame decoding\n ***************************************************************/\n\n/** ZSTD_insertBlock() :\n *  insert `src` block into `dctx` history. Useful to track uncompressed blocks. */\nsize_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize)\n{\n    DEBUGLOG(5, \"ZSTD_insertBlock: %u bytes\", (unsigned)blockSize);\n    ZSTD_checkContinuity(dctx, blockStart, blockSize);\n    dctx->previousDstEnd = (const char*)blockStart + blockSize;\n    return blockSize;\n}\n\n\nstatic size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity,\n                          const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_copyRawBlock\");\n    RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, \"\");\n    if (dst == NULL) {\n        if (srcSize == 0) return 0;\n        RETURN_ERROR(dstBuffer_null, \"\");\n    }\n    ZSTD_memmove(dst, src, srcSize);\n    return srcSize;\n}\n\nstatic size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity,\n                               BYTE b,\n                               size_t regenSize)\n{\n    RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, \"\");\n    if (dst == NULL) {\n        if (regenSize == 0) return 0;\n        RETURN_ERROR(dstBuffer_null, \"\");\n    }\n    ZSTD_memset(dst, b, regenSize);\n    return regenSize;\n}\n\nstatic void ZSTD_DCtx_trace_end(ZSTD_DCtx const* dctx, U64 uncompressedSize, U64 compressedSize, int streaming)\n{\n#if ZSTD_TRACE\n    if (dctx->traceCtx && ZSTD_trace_decompress_end != NULL) {\n        ZSTD_Trace trace;\n        ZSTD_memset(&trace, 0, sizeof(trace));\n        trace.version = ZSTD_VERSION_NUMBER;\n        trace.streaming = streaming;\n        if (dctx->ddict) {\n            trace.dictionaryID = ZSTD_getDictID_fromDDict(dctx->ddict);\n            trace.dictionarySize = ZSTD_DDict_dictSize(dctx->ddict);\n            trace.dictionaryIsCold = dctx->ddictIsCold;\n        }\n        trace.uncompressedSize = (size_t)uncompressedSize;\n        trace.compressedSize = (size_t)compressedSize;\n        trace.dctx = dctx;\n        ZSTD_trace_decompress_end(dctx->traceCtx, &trace);\n    }\n#else\n    (void)dctx;\n    (void)uncompressedSize;\n    (void)compressedSize;\n    (void)streaming;\n#endif\n}\n\n\n/*! ZSTD_decompressFrame() :\n * @dctx must be properly initialized\n *  will update *srcPtr and *srcSizePtr,\n *  to make *srcPtr progress by one frame. */\nstatic size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,\n                                   void* dst, size_t dstCapacity,\n                             const void** srcPtr, size_t *srcSizePtr)\n{\n    const BYTE* const istart = (const BYTE*)(*srcPtr);\n    const BYTE* ip = istart;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = dstCapacity != 0 ? ostart + dstCapacity : ostart;\n    BYTE* op = ostart;\n    size_t remainingSrcSize = *srcSizePtr;\n\n    DEBUGLOG(4, \"ZSTD_decompressFrame (srcSize:%i)\", (int)*srcSizePtr);\n\n    /* check */\n    RETURN_ERROR_IF(\n        remainingSrcSize < ZSTD_FRAMEHEADERSIZE_MIN(dctx->format)+ZSTD_blockHeaderSize,\n        srcSize_wrong, \"\");\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTD_frameHeaderSize_internal(\n                ip, ZSTD_FRAMEHEADERSIZE_PREFIX(dctx->format), dctx->format);\n        if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;\n        RETURN_ERROR_IF(remainingSrcSize < frameHeaderSize+ZSTD_blockHeaderSize,\n                        srcSize_wrong, \"\");\n        FORWARD_IF_ERROR( ZSTD_decodeFrameHeader(dctx, ip, frameHeaderSize) , \"\");\n        ip += frameHeaderSize; remainingSrcSize -= frameHeaderSize;\n    }\n\n    /* Shrink the blockSizeMax if enabled */\n    if (dctx->maxBlockSizeParam != 0)\n        dctx->fParams.blockSizeMax = MIN(dctx->fParams.blockSizeMax, (unsigned)dctx->maxBlockSizeParam);\n\n    /* Loop on each block */\n    while (1) {\n        BYTE* oBlockEnd = oend;\n        size_t decodedSize;\n        blockProperties_t blockProperties;\n        size_t const cBlockSize = ZSTD_getcBlockSize(ip, remainingSrcSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSrcSize -= ZSTD_blockHeaderSize;\n        RETURN_ERROR_IF(cBlockSize > remainingSrcSize, srcSize_wrong, \"\");\n\n        if (ip >= op && ip < oBlockEnd) {\n            /* We are decompressing in-place. Limit the output pointer so that we\n             * don't overwrite the block that we are currently reading. This will\n             * fail decompression if the input & output pointers aren't spaced\n             * far enough apart.\n             *\n             * This is important to set, even when the pointers are far enough\n             * apart, because ZSTD_decompressBlock_internal() can decide to store\n             * literals in the output buffer, after the block it is decompressing.\n             * Since we don't want anything to overwrite our input, we have to tell\n             * ZSTD_decompressBlock_internal to never write past ip.\n             *\n             * See ZSTD_allocateLiteralsBuffer() for reference.\n             */\n            oBlockEnd = op + (ip - op);\n        }\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            assert(dctx->isFrameDecompression == 1);\n            decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oBlockEnd-op), ip, cBlockSize, not_streaming);\n            break;\n        case bt_raw :\n            /* Use oend instead of oBlockEnd because this function is safe to overlap. It uses memmove. */\n            decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);\n            break;\n        case bt_rle :\n            decodedSize = ZSTD_setRleBlock(op, (size_t)(oBlockEnd-op), *ip, blockProperties.origSize);\n            break;\n        case bt_reserved :\n        default:\n            RETURN_ERROR(corruption_detected, \"invalid block type\");\n        }\n        FORWARD_IF_ERROR(decodedSize, \"Block decompression failure\");\n        DEBUGLOG(5, \"Decompressed block of dSize = %u\", (unsigned)decodedSize);\n        if (dctx->validateChecksum) {\n            XXH64_update(&dctx->xxhState, op, decodedSize);\n        }\n        if (decodedSize) /* support dst = NULL,0 */ {\n            op += decodedSize;\n        }\n        assert(ip != NULL);\n        ip += cBlockSize;\n        remainingSrcSize -= cBlockSize;\n        if (blockProperties.lastBlock) break;\n    }\n\n    if (dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n        RETURN_ERROR_IF((U64)(op-ostart) != dctx->fParams.frameContentSize,\n                        corruption_detected, \"\");\n    }\n    if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */\n        RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, \"\");\n        if (!dctx->forceIgnoreChecksum) {\n            U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState);\n            U32 checkRead;\n            checkRead = MEM_readLE32(ip);\n            RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, \"\");\n        }\n        ip += 4;\n        remainingSrcSize -= 4;\n    }\n    ZSTD_DCtx_trace_end(dctx, (U64)(op-ostart), (U64)(ip-istart), /* streaming */ 0);\n    /* Allow caller to get size read */\n    DEBUGLOG(4, \"ZSTD_decompressFrame: decompressed frame of size %i, consuming %i bytes of input\", (int)(op-ostart), (int)(ip - (const BYTE*)*srcPtr));\n    *srcPtr = ip;\n    *srcSizePtr = remainingSrcSize;\n    return (size_t)(op-ostart);\n}\n\nstatic\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx,\n                                        void* dst, size_t dstCapacity,\n                                  const void* src, size_t srcSize,\n                                  const void* dict, size_t dictSize,\n                                  const ZSTD_DDict* ddict)\n{\n    void* const dststart = dst;\n    int moreThan1Frame = 0;\n\n    DEBUGLOG(5, \"ZSTD_decompressMultiFrame\");\n    assert(dict==NULL || ddict==NULL);  /* either dict or ddict set, not both */\n\n    if (ddict) {\n        dict = ZSTD_DDict_dictContent(ddict);\n        dictSize = ZSTD_DDict_dictSize(ddict);\n    }\n\n    while (srcSize >= ZSTD_startingInputLength(dctx->format)) {\n\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1)\n        if (dctx->format == ZSTD_f_zstd1 && ZSTD_isLegacy(src, srcSize)) {\n            size_t decodedSize;\n            size_t const frameSize = ZSTD_findFrameCompressedSizeLegacy(src, srcSize);\n            if (ZSTD_isError(frameSize)) return frameSize;\n            RETURN_ERROR_IF(dctx->staticSize, memory_allocation,\n                \"legacy support is not compatible with static dctx\");\n\n            decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize);\n            if (ZSTD_isError(decodedSize)) return decodedSize;\n\n            {\n                unsigned long long const expectedSize = ZSTD_getFrameContentSize(src, srcSize);\n                RETURN_ERROR_IF(expectedSize == ZSTD_CONTENTSIZE_ERROR, corruption_detected, \"Corrupted frame header!\");\n                if (expectedSize != ZSTD_CONTENTSIZE_UNKNOWN) {\n                    RETURN_ERROR_IF(expectedSize != decodedSize, corruption_detected,\n                        \"Frame header size does not match decoded size!\");\n                }\n            }\n\n            assert(decodedSize <= dstCapacity);\n            dst = (BYTE*)dst + decodedSize;\n            dstCapacity -= decodedSize;\n\n            src = (const BYTE*)src + frameSize;\n            srcSize -= frameSize;\n\n            continue;\n        }\n#endif\n\n        if (dctx->format == ZSTD_f_zstd1 && srcSize >= 4) {\n            U32 const magicNumber = MEM_readLE32(src);\n            DEBUGLOG(5, \"reading magic number %08X\", (unsigned)magicNumber);\n            if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {\n                /* skippable frame detected : skip it */\n                size_t const skippableSize = readSkippableFrameSize(src, srcSize);\n                FORWARD_IF_ERROR(skippableSize, \"invalid skippable frame\");\n                assert(skippableSize <= srcSize);\n\n                src = (const BYTE *)src + skippableSize;\n                srcSize -= skippableSize;\n                continue; /* check next frame */\n        }   }\n\n        if (ddict) {\n            /* we were called from ZSTD_decompress_usingDDict */\n            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(dctx, ddict), \"\");\n        } else {\n            /* this will initialize correctly with no dict if dict == NULL, so\n             * use this in all cases but ddict */\n            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDict(dctx, dict, dictSize), \"\");\n        }\n        ZSTD_checkContinuity(dctx, dst, dstCapacity);\n\n        {   const size_t res = ZSTD_decompressFrame(dctx, dst, dstCapacity,\n                                                    &src, &srcSize);\n            RETURN_ERROR_IF(\n                (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown)\n             && (moreThan1Frame==1),\n                srcSize_wrong,\n                \"At least one frame successfully completed, \"\n                \"but following bytes are garbage: \"\n                \"it's more likely to be a srcSize error, \"\n                \"specifying more input bytes than size of frame(s). \"\n                \"Note: one could be unlucky, it might be a corruption error instead, \"\n                \"happening right at the place where we expect zstd magic bytes. \"\n                \"But this is _much_ less likely than a srcSize field error.\");\n            if (ZSTD_isError(res)) return res;\n            assert(res <= dstCapacity);\n            if (res != 0)\n                dst = (BYTE*)dst + res;\n            dstCapacity -= res;\n        }\n        moreThan1Frame = 1;\n    }  /* while (srcSize >= ZSTD_frameHeaderSize_prefix) */\n\n    RETURN_ERROR_IF(srcSize, srcSize_wrong, \"input not entirely consumed\");\n\n    return (size_t)((BYTE*)dst - (BYTE*)dststart);\n}\n\nsize_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                           const void* src, size_t srcSize,\n                           const void* dict, size_t dictSize)\n{\n    return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize, dict, dictSize, NULL);\n}\n\n\nstatic ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)\n{\n    switch (dctx->dictUses) {\n    default:\n        assert(0 /* Impossible */);\n        ZSTD_FALLTHROUGH;\n    case ZSTD_dont_use:\n        ZSTD_clearDict(dctx);\n        return NULL;\n    case ZSTD_use_indefinitely:\n        return dctx->ddict;\n    case ZSTD_use_once:\n        dctx->dictUses = ZSTD_dont_use;\n        return dctx->ddict;\n    }\n}\n\nsize_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTD_decompress_usingDDict(dctx, dst, dstCapacity, src, srcSize, ZSTD_getDDict(dctx));\n}\n\n\nsize_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)\n    size_t regenSize;\n    ZSTD_DCtx* const dctx =  ZSTD_createDCtx_internal(ZSTD_defaultCMem);\n    RETURN_ERROR_IF(dctx==NULL, memory_allocation, \"NULL pointer!\");\n    regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);\n    ZSTD_freeDCtx(dctx);\n    return regenSize;\n#else   /* stack mode */\n    ZSTD_DCtx dctx;\n    ZSTD_initDCtx_internal(&dctx);\n    return ZSTD_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);\n#endif\n}\n\n\n/*-**************************************\n*   Advanced Streaming Decompression API\n*   Bufferless and synchronous\n****************************************/\nsize_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx) { return dctx->expected; }\n\n/**\n * Similar to ZSTD_nextSrcSizeToDecompress(), but when a block input can be streamed, we\n * allow taking a partial block as the input. Currently only raw uncompressed blocks can\n * be streamed.\n *\n * For blocks that can be streamed, this allows us to reduce the latency until we produce\n * output, and avoid copying the input.\n *\n * @param inputSize - The total amount of input that the caller currently has.\n */\nstatic size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t inputSize) {\n    if (!(dctx->stage == ZSTDds_decompressBlock || dctx->stage == ZSTDds_decompressLastBlock))\n        return dctx->expected;\n    if (dctx->bType != bt_raw)\n        return dctx->expected;\n    return BOUNDED(1, inputSize, dctx->expected);\n}\n\nZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {\n    switch(dctx->stage)\n    {\n    default:   /* should not happen */\n        assert(0);\n        ZSTD_FALLTHROUGH;\n    case ZSTDds_getFrameHeaderSize:\n        ZSTD_FALLTHROUGH;\n    case ZSTDds_decodeFrameHeader:\n        return ZSTDnit_frameHeader;\n    case ZSTDds_decodeBlockHeader:\n        return ZSTDnit_blockHeader;\n    case ZSTDds_decompressBlock:\n        return ZSTDnit_block;\n    case ZSTDds_decompressLastBlock:\n        return ZSTDnit_lastBlock;\n    case ZSTDds_checkChecksum:\n        return ZSTDnit_checksum;\n    case ZSTDds_decodeSkippableHeader:\n        ZSTD_FALLTHROUGH;\n    case ZSTDds_skipFrame:\n        return ZSTDnit_skippableFrame;\n    }\n}\n\nstatic int ZSTD_isSkipFrame(ZSTD_DCtx* dctx) { return dctx->stage == ZSTDds_skipFrame; }\n\n/** ZSTD_decompressContinue() :\n *  srcSize : must be the exact nb of bytes expected (see ZSTD_nextSrcSizeToDecompress())\n *  @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)\n *            or an error code, which can be tested using ZSTD_isError() */\nsize_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    DEBUGLOG(5, \"ZSTD_decompressContinue (srcSize:%u)\", (unsigned)srcSize);\n    /* Sanity check */\n    RETURN_ERROR_IF(srcSize != ZSTD_nextSrcSizeToDecompressWithInputSize(dctx, srcSize), srcSize_wrong, \"not allowed\");\n    ZSTD_checkContinuity(dctx, dst, dstCapacity);\n\n    dctx->processedCSize += srcSize;\n\n    switch (dctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        assert(src != NULL);\n        if (dctx->format == ZSTD_f_zstd1) {  /* allows header */\n            assert(srcSize >= ZSTD_FRAMEIDSIZE);  /* to read skippable magic number */\n            if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {        /* skippable frame */\n                ZSTD_memcpy(dctx->headerBuffer, src, srcSize);\n                dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize;  /* remaining to load to get full skippable frame header */\n                dctx->stage = ZSTDds_decodeSkippableHeader;\n                return 0;\n        }   }\n        dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format);\n        if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize;\n        ZSTD_memcpy(dctx->headerBuffer, src, srcSize);\n        dctx->expected = dctx->headerSize - srcSize;\n        dctx->stage = ZSTDds_decodeFrameHeader;\n        return 0;\n\n    case ZSTDds_decodeFrameHeader:\n        assert(src != NULL);\n        ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize);\n        FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), \"\");\n        dctx->expected = ZSTD_blockHeaderSize;\n        dctx->stage = ZSTDds_decodeBlockHeader;\n        return 0;\n\n    case ZSTDds_decodeBlockHeader:\n        {   blockProperties_t bp;\n            size_t const cBlockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n            if (ZSTD_isError(cBlockSize)) return cBlockSize;\n            RETURN_ERROR_IF(cBlockSize > dctx->fParams.blockSizeMax, corruption_detected, \"Block Size Exceeds Maximum\");\n            dctx->expected = cBlockSize;\n            dctx->bType = bp.blockType;\n            dctx->rleSize = bp.origSize;\n            if (cBlockSize) {\n                dctx->stage = bp.lastBlock ? ZSTDds_decompressLastBlock : ZSTDds_decompressBlock;\n                return 0;\n            }\n            /* empty block */\n            if (bp.lastBlock) {\n                if (dctx->fParams.checksumFlag) {\n                    dctx->expected = 4;\n                    dctx->stage = ZSTDds_checkChecksum;\n                } else {\n                    dctx->expected = 0; /* end of frame */\n                    dctx->stage = ZSTDds_getFrameHeaderSize;\n                }\n            } else {\n                dctx->expected = ZSTD_blockHeaderSize;  /* jump to next header */\n                dctx->stage = ZSTDds_decodeBlockHeader;\n            }\n            return 0;\n        }\n\n    case ZSTDds_decompressLastBlock:\n    case ZSTDds_decompressBlock:\n        DEBUGLOG(5, \"ZSTD_decompressContinue: case ZSTDds_decompressBlock\");\n        {   size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                DEBUGLOG(5, \"ZSTD_decompressContinue: case bt_compressed\");\n                assert(dctx->isFrameDecompression == 1);\n                rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, is_streaming);\n                dctx->expected = 0;  /* Streaming not supported */\n                break;\n            case bt_raw :\n                assert(srcSize <= dctx->expected);\n                rSize = ZSTD_copyRawBlock(dst, dstCapacity, src, srcSize);\n                FORWARD_IF_ERROR(rSize, \"ZSTD_copyRawBlock failed\");\n                assert(rSize == srcSize);\n                dctx->expected -= rSize;\n                break;\n            case bt_rle :\n                rSize = ZSTD_setRleBlock(dst, dstCapacity, *(const BYTE*)src, dctx->rleSize);\n                dctx->expected = 0;  /* Streaming not supported */\n                break;\n            case bt_reserved :   /* should never happen */\n            default:\n                RETURN_ERROR(corruption_detected, \"invalid block type\");\n            }\n            FORWARD_IF_ERROR(rSize, \"\");\n            RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, \"Decompressed Block Size Exceeds Maximum\");\n            DEBUGLOG(5, \"ZSTD_decompressContinue: decoded size from block : %u\", (unsigned)rSize);\n            dctx->decodedSize += rSize;\n            if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize);\n            dctx->previousDstEnd = (char*)dst + rSize;\n\n            /* Stay on the same stage until we are finished streaming the block. */\n            if (dctx->expected > 0) {\n                return rSize;\n            }\n\n            if (dctx->stage == ZSTDds_decompressLastBlock) {   /* end of frame */\n                DEBUGLOG(4, \"ZSTD_decompressContinue: decoded size from frame : %u\", (unsigned)dctx->decodedSize);\n                RETURN_ERROR_IF(\n                    dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN\n                 && dctx->decodedSize != dctx->fParams.frameContentSize,\n                    corruption_detected, \"\");\n                if (dctx->fParams.checksumFlag) {  /* another round for frame checksum */\n                    dctx->expected = 4;\n                    dctx->stage = ZSTDds_checkChecksum;\n                } else {\n                    ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);\n                    dctx->expected = 0;   /* ends here */\n                    dctx->stage = ZSTDds_getFrameHeaderSize;\n                }\n            } else {\n                dctx->stage = ZSTDds_decodeBlockHeader;\n                dctx->expected = ZSTD_blockHeaderSize;\n            }\n            return rSize;\n        }\n\n    case ZSTDds_checkChecksum:\n        assert(srcSize == 4);  /* guaranteed by dctx->expected */\n        {\n            if (dctx->validateChecksum) {\n                U32 const h32 = (U32)XXH64_digest(&dctx->xxhState);\n                U32 const check32 = MEM_readLE32(src);\n                DEBUGLOG(4, \"ZSTD_decompressContinue: checksum : calculated %08X :: %08X read\", (unsigned)h32, (unsigned)check32);\n                RETURN_ERROR_IF(check32 != h32, checksum_wrong, \"\");\n            }\n            ZSTD_DCtx_trace_end(dctx, dctx->decodedSize, dctx->processedCSize, /* streaming */ 1);\n            dctx->expected = 0;\n            dctx->stage = ZSTDds_getFrameHeaderSize;\n            return 0;\n        }\n\n    case ZSTDds_decodeSkippableHeader:\n        assert(src != NULL);\n        assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE);\n        assert(dctx->format != ZSTD_f_zstd1_magicless);\n        ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize);   /* complete skippable header */\n        dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE);   /* note : dctx->expected can grow seriously large, beyond local buffer size */\n        dctx->stage = ZSTDds_skipFrame;\n        return 0;\n\n    case ZSTDds_skipFrame:\n        dctx->expected = 0;\n        dctx->stage = ZSTDds_getFrameHeaderSize;\n        return 0;\n\n    default:\n        assert(0);   /* impossible */\n        RETURN_ERROR(GENERIC, \"impossible to reach\");   /* some compilers require default to do something */\n    }\n}\n\n\nstatic size_t ZSTD_refDictContent(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->virtualStart = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));\n    dctx->prefixStart = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    dctx->dictContentBeginForFuzzing = dctx->prefixStart;\n    dctx->dictContentEndForFuzzing = dctx->previousDstEnd;\n#endif\n    return 0;\n}\n\n/*! ZSTD_loadDEntropy() :\n *  dict : must point at beginning of a valid zstd dictionary.\n * @return : size of entropy tables read */\nsize_t\nZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,\n                  const void* const dict, size_t const dictSize)\n{\n    const BYTE* dictPtr = (const BYTE*)dict;\n    const BYTE* const dictEnd = dictPtr + dictSize;\n\n    RETURN_ERROR_IF(dictSize <= 8, dictionary_corrupted, \"dict is too small\");\n    assert(MEM_readLE32(dict) == ZSTD_MAGIC_DICTIONARY);   /* dict must be valid */\n    dictPtr += 8;   /* skip header = magic + dictID */\n\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, OFTable) == offsetof(ZSTD_entropyDTables_t, LLTable) + sizeof(entropy->LLTable));\n    ZSTD_STATIC_ASSERT(offsetof(ZSTD_entropyDTables_t, MLTable) == offsetof(ZSTD_entropyDTables_t, OFTable) + sizeof(entropy->OFTable));\n    ZSTD_STATIC_ASSERT(sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable) >= HUF_DECOMPRESS_WORKSPACE_SIZE);\n    {   void* const workspace = &entropy->LLTable;   /* use fse tables as temporary workspace; implies fse tables are grouped together */\n        size_t const workspaceSize = sizeof(entropy->LLTable) + sizeof(entropy->OFTable) + sizeof(entropy->MLTable);\n#ifdef HUF_FORCE_DECOMPRESS_X1\n        /* in minimal huffman, we always use X1 variants */\n        size_t const hSize = HUF_readDTableX1_wksp(entropy->hufTable,\n                                                dictPtr, dictEnd - dictPtr,\n                                                workspace, workspaceSize, /* flags */ 0);\n#else\n        size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable,\n                                                dictPtr, (size_t)(dictEnd - dictPtr),\n                                                workspace, workspaceSize, /* flags */ 0);\n#endif\n        RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, \"\");\n        dictPtr += hSize;\n    }\n\n    {   short offcodeNCount[MaxOff+1];\n        unsigned offcodeMaxValue = MaxOff, offcodeLog;\n        size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, \"\");\n        ZSTD_buildFSETable( entropy->OFTable,\n                            offcodeNCount, offcodeMaxValue,\n                            OF_base, OF_bits,\n                            offcodeLog,\n                            entropy->workspace, sizeof(entropy->workspace),\n                            /* bmi2 */0);\n        dictPtr += offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, \"\");\n        ZSTD_buildFSETable( entropy->MLTable,\n                            matchlengthNCount, matchlengthMaxValue,\n                            ML_base, ML_bits,\n                            matchlengthLog,\n                            entropy->workspace, sizeof(entropy->workspace),\n                            /* bmi2 */ 0);\n        dictPtr += matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr));\n        RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, \"\");\n        RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, \"\");\n        ZSTD_buildFSETable( entropy->LLTable,\n                            litlengthNCount, litlengthMaxValue,\n                            LL_base, LL_bits,\n                            litlengthLog,\n                            entropy->workspace, sizeof(entropy->workspace),\n                            /* bmi2 */ 0);\n        dictPtr += litlengthHeaderSize;\n    }\n\n    RETURN_ERROR_IF(dictPtr+12 > dictEnd, dictionary_corrupted, \"\");\n    {   int i;\n        size_t const dictContentSize = (size_t)(dictEnd - (dictPtr+12));\n        for (i=0; i<3; i++) {\n            U32 const rep = MEM_readLE32(dictPtr); dictPtr += 4;\n            RETURN_ERROR_IF(rep==0 || rep > dictContentSize,\n                            dictionary_corrupted, \"\");\n            entropy->rep[i] = rep;\n    }   }\n\n    return (size_t)(dictPtr - (const BYTE*)dict);\n}\n\nstatic size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    if (dictSize < 8) return ZSTD_refDictContent(dctx, dict, dictSize);\n    {   U32 const magic = MEM_readLE32(dict);\n        if (magic != ZSTD_MAGIC_DICTIONARY) {\n            return ZSTD_refDictContent(dctx, dict, dictSize);   /* pure content mode */\n    }   }\n    dctx->dictID = MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);\n\n    /* load entropy tables */\n    {   size_t const eSize = ZSTD_loadDEntropy(&dctx->entropy, dict, dictSize);\n        RETURN_ERROR_IF(ZSTD_isError(eSize), dictionary_corrupted, \"\");\n        dict = (const char*)dict + eSize;\n        dictSize -= eSize;\n    }\n    dctx->litEntropy = dctx->fseEntropy = 1;\n\n    /* reference dictionary content */\n    return ZSTD_refDictContent(dctx, dict, dictSize);\n}\n\nsize_t ZSTD_decompressBegin(ZSTD_DCtx* dctx)\n{\n    assert(dctx != NULL);\n#if ZSTD_TRACE\n    dctx->traceCtx = (ZSTD_trace_decompress_begin != NULL) ? ZSTD_trace_decompress_begin(dctx) : 0;\n#endif\n    dctx->expected = ZSTD_startingInputLength(dctx->format);  /* dctx->format must be properly set */\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->processedCSize = 0;\n    dctx->decodedSize = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->prefixStart = NULL;\n    dctx->virtualStart = NULL;\n    dctx->dictEnd = NULL;\n    dctx->entropy.hufTable[0] = (HUF_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001);  /* cover both little and big endian */\n    dctx->litEntropy = dctx->fseEntropy = 0;\n    dctx->dictID = 0;\n    dctx->bType = bt_reserved;\n    dctx->isFrameDecompression = 1;\n    ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue));\n    ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue));  /* initial repcodes */\n    dctx->LLTptr = dctx->entropy.LLTable;\n    dctx->MLTptr = dctx->entropy.MLTable;\n    dctx->OFTptr = dctx->entropy.OFTable;\n    dctx->HUFptr = dctx->entropy.hufTable;\n    return 0;\n}\n\nsize_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , \"\");\n    if (dict && dictSize)\n        RETURN_ERROR_IF(\n            ZSTD_isError(ZSTD_decompress_insertDictionary(dctx, dict, dictSize)),\n            dictionary_corrupted, \"\");\n    return 0;\n}\n\n\n/* ======   ZSTD_DDict   ====== */\n\nsize_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)\n{\n    DEBUGLOG(4, \"ZSTD_decompressBegin_usingDDict\");\n    assert(dctx != NULL);\n    if (ddict) {\n        const char* const dictStart = (const char*)ZSTD_DDict_dictContent(ddict);\n        size_t const dictSize = ZSTD_DDict_dictSize(ddict);\n        const void* const dictEnd = dictStart + dictSize;\n        dctx->ddictIsCold = (dctx->dictEnd != dictEnd);\n        DEBUGLOG(4, \"DDict is %s\",\n                    dctx->ddictIsCold ? \"~cold~\" : \"hot!\");\n    }\n    FORWARD_IF_ERROR( ZSTD_decompressBegin(dctx) , \"\");\n    if (ddict) {   /* NULL ddict is equivalent to no dictionary */\n        ZSTD_copyDDictParameters(dctx, ddict);\n    }\n    return 0;\n}\n\n/*! ZSTD_getDictID_fromDict() :\n *  Provides the dictID stored within dictionary.\n *  if @return == 0, the dictionary is not conformant with Zstandard specification.\n *  It can still be loaded, but as a content-only dictionary. */\nunsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize)\n{\n    if (dictSize < 8) return 0;\n    if (MEM_readLE32(dict) != ZSTD_MAGIC_DICTIONARY) return 0;\n    return MEM_readLE32((const char*)dict + ZSTD_FRAMEIDSIZE);\n}\n\n/*! ZSTD_getDictID_fromFrame() :\n *  Provides the dictID required to decompress frame stored within `src`.\n *  If @return == 0, the dictID could not be decoded.\n *  This could for one of the following reasons :\n *  - The frame does not require a dictionary (most common case).\n *  - The frame was built with dictID intentionally removed.\n *    Needed dictionary is a hidden piece of information.\n *    Note : this use case also happens when using a non-conformant dictionary.\n *  - `srcSize` is too small, and as a result, frame header could not be decoded.\n *    Note : possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`.\n *  - This is not a Zstandard frame.\n *  When identifying the exact failure cause, it's possible to use\n *  ZSTD_getFrameHeader(), which will provide a more precise error code. */\nunsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)\n{\n    ZSTD_FrameHeader zfp = { 0, 0, 0, ZSTD_frame, 0, 0, 0, 0, 0 };\n    size_t const hError = ZSTD_getFrameHeader(&zfp, src, srcSize);\n    if (ZSTD_isError(hError)) return 0;\n    return zfp.dictID;\n}\n\n\n/*! ZSTD_decompress_usingDDict() :\n*   Decompression using a pre-digested Dictionary\n*   Use dictionary without significant overhead. */\nsize_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,\n                                  void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                            const ZSTD_DDict* ddict)\n{\n    /* pass content and size in case legacy frames are encountered */\n    return ZSTD_decompressMultiFrame(dctx, dst, dstCapacity, src, srcSize,\n                                     NULL, 0,\n                                     ddict);\n}\n\n\n/*=====================================\n*   Streaming decompression\n*====================================*/\n\nZSTD_DStream* ZSTD_createDStream(void)\n{\n    DEBUGLOG(3, \"ZSTD_createDStream\");\n    return ZSTD_createDCtx_internal(ZSTD_defaultCMem);\n}\n\nZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)\n{\n    return ZSTD_initStaticDCtx(workspace, workspaceSize);\n}\n\nZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)\n{\n    return ZSTD_createDCtx_internal(customMem);\n}\n\nsize_t ZSTD_freeDStream(ZSTD_DStream* zds)\n{\n    return ZSTD_freeDCtx(zds);\n}\n\n\n/* ***  Initialization  *** */\n\nsize_t ZSTD_DStreamInSize(void)  { return ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize; }\nsize_t ZSTD_DStreamOutSize(void) { return ZSTD_BLOCKSIZE_MAX; }\n\nsize_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx,\n                                   const void* dict, size_t dictSize,\n                                         ZSTD_dictLoadMethod_e dictLoadMethod,\n                                         ZSTD_dictContentType_e dictContentType)\n{\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    ZSTD_clearDict(dctx);\n    if (dict && dictSize != 0) {\n        dctx->ddictLocal = ZSTD_createDDict_advanced(dict, dictSize, dictLoadMethod, dictContentType, dctx->customMem);\n        RETURN_ERROR_IF(dctx->ddictLocal == NULL, memory_allocation, \"NULL pointer!\");\n        dctx->ddict = dctx->ddictLocal;\n        dctx->dictUses = ZSTD_use_indefinitely;\n    }\n    return 0;\n}\n\nsize_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);\n}\n\nsize_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    return ZSTD_DCtx_loadDictionary_advanced(dctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);\n}\n\nsize_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType)\n{\n    FORWARD_IF_ERROR(ZSTD_DCtx_loadDictionary_advanced(dctx, prefix, prefixSize, ZSTD_dlm_byRef, dictContentType), \"\");\n    dctx->dictUses = ZSTD_use_once;\n    return 0;\n}\n\nsize_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize)\n{\n    return ZSTD_DCtx_refPrefix_advanced(dctx, prefix, prefixSize, ZSTD_dct_rawContent);\n}\n\n\n/* ZSTD_initDStream_usingDict() :\n * return : expected size, aka ZSTD_startingInputLength().\n * this function cannot fail */\nsize_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize)\n{\n    DEBUGLOG(4, \"ZSTD_initDStream_usingDict\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_reset(zds, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_loadDictionary(zds, dict, dictSize) , \"\");\n    return ZSTD_startingInputLength(zds->format);\n}\n\n/* note : this variant can't fail */\nsize_t ZSTD_initDStream(ZSTD_DStream* zds)\n{\n    DEBUGLOG(4, \"ZSTD_initDStream\");\n    FORWARD_IF_ERROR(ZSTD_DCtx_reset(zds, ZSTD_reset_session_only), \"\");\n    FORWARD_IF_ERROR(ZSTD_DCtx_refDDict(zds, NULL), \"\");\n    return ZSTD_startingInputLength(zds->format);\n}\n\n/* ZSTD_initDStream_usingDDict() :\n * ddict will just be referenced, and must outlive decompression session\n * this function cannot fail */\nsize_t ZSTD_initDStream_usingDDict(ZSTD_DStream* dctx, const ZSTD_DDict* ddict)\n{\n    DEBUGLOG(4, \"ZSTD_initDStream_usingDDict\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only) , \"\");\n    FORWARD_IF_ERROR( ZSTD_DCtx_refDDict(dctx, ddict) , \"\");\n    return ZSTD_startingInputLength(dctx->format);\n}\n\n/* ZSTD_resetDStream() :\n * return : expected size, aka ZSTD_startingInputLength().\n * this function cannot fail */\nsize_t ZSTD_resetDStream(ZSTD_DStream* dctx)\n{\n    DEBUGLOG(4, \"ZSTD_resetDStream\");\n    FORWARD_IF_ERROR(ZSTD_DCtx_reset(dctx, ZSTD_reset_session_only), \"\");\n    return ZSTD_startingInputLength(dctx->format);\n}\n\n\nsize_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict)\n{\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    ZSTD_clearDict(dctx);\n    if (ddict) {\n        dctx->ddict = ddict;\n        dctx->dictUses = ZSTD_use_indefinitely;\n        if (dctx->refMultipleDDicts == ZSTD_rmd_refMultipleDDicts) {\n            if (dctx->ddictSet == NULL) {\n                dctx->ddictSet = ZSTD_createDDictHashSet(dctx->customMem);\n                if (!dctx->ddictSet) {\n                    RETURN_ERROR(memory_allocation, \"Failed to allocate memory for hash set!\");\n                }\n            }\n            assert(!dctx->staticSize);  /* Impossible: ddictSet cannot have been allocated if static dctx */\n            FORWARD_IF_ERROR(ZSTD_DDictHashSet_addDDict(dctx->ddictSet, ddict, dctx->customMem), \"\");\n        }\n    }\n    return 0;\n}\n\n/* ZSTD_DCtx_setMaxWindowSize() :\n * note : no direct equivalence in ZSTD_DCtx_setParameter,\n * since this version sets windowSize, and the other sets windowLog */\nsize_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize)\n{\n    ZSTD_bounds const bounds = ZSTD_dParam_getBounds(ZSTD_d_windowLogMax);\n    size_t const min = (size_t)1 << bounds.lowerBound;\n    size_t const max = (size_t)1 << bounds.upperBound;\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    RETURN_ERROR_IF(maxWindowSize < min, parameter_outOfBound, \"\");\n    RETURN_ERROR_IF(maxWindowSize > max, parameter_outOfBound, \"\");\n    dctx->maxWindowSize = maxWindowSize;\n    return 0;\n}\n\nsize_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format)\n{\n    return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format);\n}\n\nZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)\n{\n    ZSTD_bounds bounds = { 0, 0, 0 };\n    switch(dParam) {\n        case ZSTD_d_windowLogMax:\n            bounds.lowerBound = ZSTD_WINDOWLOG_ABSOLUTEMIN;\n            bounds.upperBound = ZSTD_WINDOWLOG_MAX;\n            return bounds;\n        case ZSTD_d_format:\n            bounds.lowerBound = (int)ZSTD_f_zstd1;\n            bounds.upperBound = (int)ZSTD_f_zstd1_magicless;\n            ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless);\n            return bounds;\n        case ZSTD_d_stableOutBuffer:\n            bounds.lowerBound = (int)ZSTD_bm_buffered;\n            bounds.upperBound = (int)ZSTD_bm_stable;\n            return bounds;\n        case ZSTD_d_forceIgnoreChecksum:\n            bounds.lowerBound = (int)ZSTD_d_validateChecksum;\n            bounds.upperBound = (int)ZSTD_d_ignoreChecksum;\n            return bounds;\n        case ZSTD_d_refMultipleDDicts:\n            bounds.lowerBound = (int)ZSTD_rmd_refSingleDDict;\n            bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;\n            return bounds;\n        case ZSTD_d_disableHuffmanAssembly:\n            bounds.lowerBound = 0;\n            bounds.upperBound = 1;\n            return bounds;\n        case ZSTD_d_maxBlockSize:\n            bounds.lowerBound = ZSTD_BLOCKSIZE_MAX_MIN;\n            bounds.upperBound = ZSTD_BLOCKSIZE_MAX;\n            return bounds;\n\n        default:;\n    }\n    bounds.error = ERROR(parameter_unsupported);\n    return bounds;\n}\n\n/* ZSTD_dParam_withinBounds:\n * @return 1 if value is within dParam bounds,\n * 0 otherwise */\nstatic int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value)\n{\n    ZSTD_bounds const bounds = ZSTD_dParam_getBounds(dParam);\n    if (ZSTD_isError(bounds.error)) return 0;\n    if (value < bounds.lowerBound) return 0;\n    if (value > bounds.upperBound) return 0;\n    return 1;\n}\n\n#define CHECK_DBOUNDS(p,v) {                \\\n    RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, \"\"); \\\n}\n\nsize_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value)\n{\n    switch (param) {\n        case ZSTD_d_windowLogMax:\n            *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize);\n            return 0;\n        case ZSTD_d_format:\n            *value = (int)dctx->format;\n            return 0;\n        case ZSTD_d_stableOutBuffer:\n            *value = (int)dctx->outBufferMode;\n            return 0;\n        case ZSTD_d_forceIgnoreChecksum:\n            *value = (int)dctx->forceIgnoreChecksum;\n            return 0;\n        case ZSTD_d_refMultipleDDicts:\n            *value = (int)dctx->refMultipleDDicts;\n            return 0;\n        case ZSTD_d_disableHuffmanAssembly:\n            *value = (int)dctx->disableHufAsm;\n            return 0;\n        case ZSTD_d_maxBlockSize:\n            *value = dctx->maxBlockSizeParam;\n            return 0;\n        default:;\n    }\n    RETURN_ERROR(parameter_unsupported, \"\");\n}\n\nsize_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value)\n{\n    RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n    switch(dParam) {\n        case ZSTD_d_windowLogMax:\n            if (value == 0) value = ZSTD_WINDOWLOG_LIMIT_DEFAULT;\n            CHECK_DBOUNDS(ZSTD_d_windowLogMax, value);\n            dctx->maxWindowSize = ((size_t)1) << value;\n            return 0;\n        case ZSTD_d_format:\n            CHECK_DBOUNDS(ZSTD_d_format, value);\n            dctx->format = (ZSTD_format_e)value;\n            return 0;\n        case ZSTD_d_stableOutBuffer:\n            CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value);\n            dctx->outBufferMode = (ZSTD_bufferMode_e)value;\n            return 0;\n        case ZSTD_d_forceIgnoreChecksum:\n            CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value);\n            dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value;\n            return 0;\n        case ZSTD_d_refMultipleDDicts:\n            CHECK_DBOUNDS(ZSTD_d_refMultipleDDicts, value);\n            if (dctx->staticSize != 0) {\n                RETURN_ERROR(parameter_unsupported, \"Static dctx does not support multiple DDicts!\");\n            }\n            dctx->refMultipleDDicts = (ZSTD_refMultipleDDicts_e)value;\n            return 0;\n        case ZSTD_d_disableHuffmanAssembly:\n            CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);\n            dctx->disableHufAsm = value != 0;\n            return 0;\n        case ZSTD_d_maxBlockSize:\n            if (value != 0) CHECK_DBOUNDS(ZSTD_d_maxBlockSize, value);\n            dctx->maxBlockSizeParam = value;\n            return 0;\n        default:;\n    }\n    RETURN_ERROR(parameter_unsupported, \"\");\n}\n\nsize_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset)\n{\n    if ( (reset == ZSTD_reset_session_only)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        dctx->streamStage = zdss_init;\n        dctx->noForwardProgress = 0;\n        dctx->isFrameDecompression = 1;\n    }\n    if ( (reset == ZSTD_reset_parameters)\n      || (reset == ZSTD_reset_session_and_parameters) ) {\n        RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, \"\");\n        ZSTD_clearDict(dctx);\n        ZSTD_DCtx_resetParameters(dctx);\n    }\n    return 0;\n}\n\n\nsize_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)\n{\n    return ZSTD_sizeof_DCtx(dctx);\n}\n\nstatic size_t ZSTD_decodingBufferSize_internal(unsigned long long windowSize, unsigned long long frameContentSize, size_t blockSizeMax)\n{\n    size_t const blockSize = MIN((size_t)MIN(windowSize, ZSTD_BLOCKSIZE_MAX), blockSizeMax);\n    /* We need blockSize + WILDCOPY_OVERLENGTH worth of buffer so that if a block\n     * ends at windowSize + WILDCOPY_OVERLENGTH + 1 bytes, we can start writing\n     * the block at the beginning of the output buffer, and maintain a full window.\n     *\n     * We need another blockSize worth of buffer so that we can store split\n     * literals at the end of the block without overwriting the extDict window.\n     */\n    unsigned long long const neededRBSize = windowSize + (blockSize * 2) + (WILDCOPY_OVERLENGTH * 2);\n    unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);\n    size_t const minRBSize = (size_t) neededSize;\n    RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,\n                    frameParameter_windowTooLarge, \"\");\n    return minRBSize;\n}\n\nsize_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)\n{\n    return ZSTD_decodingBufferSize_internal(windowSize, frameContentSize, ZSTD_BLOCKSIZE_MAX);\n}\n\nsize_t ZSTD_estimateDStreamSize(size_t windowSize)\n{\n    size_t const blockSize = MIN(windowSize, ZSTD_BLOCKSIZE_MAX);\n    size_t const inBuffSize = blockSize;  /* no block can be larger */\n    size_t const outBuffSize = ZSTD_decodingBufferSize_min(windowSize, ZSTD_CONTENTSIZE_UNKNOWN);\n    return ZSTD_estimateDCtxSize() + inBuffSize + outBuffSize;\n}\n\nsize_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize)\n{\n    U32 const windowSizeMax = 1U << ZSTD_WINDOWLOG_MAX;   /* note : should be user-selectable, but requires an additional parameter (or a dctx) */\n    ZSTD_FrameHeader zfh;\n    size_t const err = ZSTD_getFrameHeader(&zfh, src, srcSize);\n    if (ZSTD_isError(err)) return err;\n    RETURN_ERROR_IF(err>0, srcSize_wrong, \"\");\n    RETURN_ERROR_IF(zfh.windowSize > windowSizeMax,\n                    frameParameter_windowTooLarge, \"\");\n    return ZSTD_estimateDStreamSize((size_t)zfh.windowSize);\n}\n\n\n/* *****   Decompression   ***** */\n\nstatic int ZSTD_DCtx_isOverflow(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)\n{\n    return (zds->inBuffSize + zds->outBuffSize) >= (neededInBuffSize + neededOutBuffSize) * ZSTD_WORKSPACETOOLARGE_FACTOR;\n}\n\nstatic void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const neededInBuffSize, size_t const neededOutBuffSize)\n{\n    if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize))\n        zds->oversizedDuration++;\n    else\n        zds->oversizedDuration = 0;\n}\n\nstatic int ZSTD_DCtx_isOversizedTooLong(ZSTD_DStream* zds)\n{\n    return zds->oversizedDuration >= ZSTD_WORKSPACETOOLARGE_MAXDURATION;\n}\n\n/* Checks that the output buffer hasn't changed if ZSTD_obm_stable is used. */\nstatic size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* output)\n{\n    ZSTD_outBuffer const expect = zds->expectedOutBuffer;\n    /* No requirement when ZSTD_obm_stable is not enabled. */\n    if (zds->outBufferMode != ZSTD_bm_stable)\n        return 0;\n    /* Any buffer is allowed in zdss_init, this must be the same for every other call until\n     * the context is reset.\n     */\n    if (zds->streamStage == zdss_init)\n        return 0;\n    /* The buffer must match our expectation exactly. */\n    if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size)\n        return 0;\n    RETURN_ERROR(dstBuffer_wrong, \"ZSTD_d_stableOutBuffer enabled but output differs!\");\n}\n\n/* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream()\n * and updates the stage and the output buffer state. This call is extracted so it can be\n * used both when reading directly from the ZSTD_inBuffer, and in buffered input mode.\n * NOTE: You must break after calling this function since the streamStage is modified.\n */\nstatic size_t ZSTD_decompressContinueStream(\n            ZSTD_DStream* zds, char** op, char* oend,\n            void const* src, size_t srcSize) {\n    int const isSkipFrame = ZSTD_isSkipFrame(zds);\n    if (zds->outBufferMode == ZSTD_bm_buffered) {\n        size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart;\n        size_t const decodedSize = ZSTD_decompressContinue(zds,\n                zds->outBuff + zds->outStart, dstSize, src, srcSize);\n        FORWARD_IF_ERROR(decodedSize, \"\");\n        if (!decodedSize && !isSkipFrame) {\n            zds->streamStage = zdss_read;\n        } else {\n            zds->outEnd = zds->outStart + decodedSize;\n            zds->streamStage = zdss_flush;\n        }\n    } else {\n        /* Write directly into the output buffer */\n        size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op);\n        size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize);\n        FORWARD_IF_ERROR(decodedSize, \"\");\n        *op += decodedSize;\n        /* Flushing is not needed. */\n        zds->streamStage = zdss_read;\n        assert(*op <= oend);\n        assert(zds->outBufferMode == ZSTD_bm_stable);\n    }\n    return 0;\n}\n\nsize_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input)\n{\n    const char* const src = (const char*)input->src;\n    const char* const istart = input->pos != 0 ? src + input->pos : src;\n    const char* const iend = input->size != 0 ? src + input->size : src;\n    const char* ip = istart;\n    char* const dst = (char*)output->dst;\n    char* const ostart = output->pos != 0 ? dst + output->pos : dst;\n    char* const oend = output->size != 0 ? dst + output->size : dst;\n    char* op = ostart;\n    U32 someMoreWork = 1;\n\n    DEBUGLOG(5, \"ZSTD_decompressStream\");\n    assert(zds != NULL);\n    RETURN_ERROR_IF(\n        input->pos > input->size,\n        srcSize_wrong,\n        \"forbidden. in: pos: %u   vs size: %u\",\n        (U32)input->pos, (U32)input->size);\n    RETURN_ERROR_IF(\n        output->pos > output->size,\n        dstSize_tooSmall,\n        \"forbidden. out: pos: %u   vs size: %u\",\n        (U32)output->pos, (U32)output->size);\n    DEBUGLOG(5, \"input size : %u\", (U32)(input->size - input->pos));\n    FORWARD_IF_ERROR(ZSTD_checkOutBuffer(zds, output), \"\");\n\n    while (someMoreWork) {\n        switch(zds->streamStage)\n        {\n        case zdss_init :\n            DEBUGLOG(5, \"stage zdss_init => transparent reset \");\n            zds->streamStage = zdss_loadHeader;\n            zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n            zds->legacyVersion = 0;\n#endif\n            zds->hostageByte = 0;\n            zds->expectedOutBuffer = *output;\n            ZSTD_FALLTHROUGH;\n\n        case zdss_loadHeader :\n            DEBUGLOG(5, \"stage zdss_loadHeader (srcSize : %u)\", (U32)(iend - ip));\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n            if (zds->legacyVersion) {\n                RETURN_ERROR_IF(zds->staticSize, memory_allocation,\n                    \"legacy support is incompatible with static dctx\");\n                {   size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, zds->legacyVersion, output, input);\n                    if (hint==0) zds->streamStage = zdss_init;\n                    return hint;\n            }   }\n#endif\n            {   size_t const hSize = ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format);\n                if (zds->refMultipleDDicts && zds->ddictSet) {\n                    ZSTD_DCtx_selectFrameDDict(zds);\n                }\n                if (ZSTD_isError(hSize)) {\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n                    U32 const legacyVersion = ZSTD_isLegacy(istart, iend-istart);\n                    if (legacyVersion) {\n                        ZSTD_DDict const* const ddict = ZSTD_getDDict(zds);\n                        const void* const dict = ddict ? ZSTD_DDict_dictContent(ddict) : NULL;\n                        size_t const dictSize = ddict ? ZSTD_DDict_dictSize(ddict) : 0;\n                        DEBUGLOG(5, \"ZSTD_decompressStream: detected legacy version v0.%u\", legacyVersion);\n                        RETURN_ERROR_IF(zds->staticSize, memory_allocation,\n                            \"legacy support is incompatible with static dctx\");\n                        FORWARD_IF_ERROR(ZSTD_initLegacyStream(&zds->legacyContext,\n                                    zds->previousLegacyVersion, legacyVersion,\n                                    dict, dictSize), \"\");\n                        zds->legacyVersion = zds->previousLegacyVersion = legacyVersion;\n                        {   size_t const hint = ZSTD_decompressLegacyStream(zds->legacyContext, legacyVersion, output, input);\n                            if (hint==0) zds->streamStage = zdss_init;   /* or stay in stage zdss_loadHeader */\n                            return hint;\n                    }   }\n#endif\n                    return hSize;   /* error */\n                }\n                if (hSize != 0) {   /* need more input */\n                    size_t const toLoad = hSize - zds->lhSize;   /* if hSize!=0, hSize > zds->lhSize */\n                    size_t const remainingInput = (size_t)(iend-ip);\n                    assert(iend >= ip);\n                    if (toLoad > remainingInput) {   /* not enough input to load full header */\n                        if (remainingInput > 0) {\n                            ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput);\n                            zds->lhSize += remainingInput;\n                        }\n                        input->pos = input->size;\n                        /* check first few bytes */\n                        FORWARD_IF_ERROR(\n                            ZSTD_getFrameHeader_advanced(&zds->fParams, zds->headerBuffer, zds->lhSize, zds->format),\n                            \"First few bytes detected incorrect\" );\n                        /* return hint input size */\n                        return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize;   /* remaining header bytes + next block header */\n                    }\n                    assert(ip != NULL);\n                    ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad;\n                    break;\n            }   }\n\n            /* check for single-pass mode opportunity */\n            if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN\n                && zds->fParams.frameType != ZSTD_skippableFrame\n                && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) {\n                size_t const cSize = ZSTD_findFrameCompressedSize_advanced(istart, (size_t)(iend-istart), zds->format);\n                if (cSize <= (size_t)(iend-istart)) {\n                    /* shortcut : using single-pass mode */\n                    size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds));\n                    if (ZSTD_isError(decompressedSize)) return decompressedSize;\n                    DEBUGLOG(4, \"shortcut to single-pass ZSTD_decompress_usingDDict()\");\n                    assert(istart != NULL);\n                    ip = istart + cSize;\n                    op = op ? op + decompressedSize : op; /* can occur if frameContentSize = 0 (empty frame) */\n                    zds->expected = 0;\n                    zds->streamStage = zdss_init;\n                    someMoreWork = 0;\n                    break;\n            }   }\n\n            /* Check output buffer is large enough for ZSTD_odm_stable. */\n            if (zds->outBufferMode == ZSTD_bm_stable\n                && zds->fParams.frameType != ZSTD_skippableFrame\n                && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN\n                && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) {\n                RETURN_ERROR(dstSize_tooSmall, \"ZSTD_obm_stable passed but ZSTD_outBuffer is too small\");\n            }\n\n            /* Consume header (see ZSTDds_decodeFrameHeader) */\n            DEBUGLOG(4, \"Consume header\");\n            FORWARD_IF_ERROR(ZSTD_decompressBegin_usingDDict(zds, ZSTD_getDDict(zds)), \"\");\n\n            if (zds->format == ZSTD_f_zstd1\n                && (MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) {  /* skippable frame */\n                zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE);\n                zds->stage = ZSTDds_skipFrame;\n            } else {\n                FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(zds, zds->headerBuffer, zds->lhSize), \"\");\n                zds->expected = ZSTD_blockHeaderSize;\n                zds->stage = ZSTDds_decodeBlockHeader;\n            }\n\n            /* control buffer memory usage */\n            DEBUGLOG(4, \"Control max memory usage (%u KB <= max %u KB)\",\n                        (U32)(zds->fParams.windowSize >>10),\n                        (U32)(zds->maxWindowSize >> 10) );\n            zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);\n            RETURN_ERROR_IF(zds->fParams.windowSize > zds->maxWindowSize,\n                            frameParameter_windowTooLarge, \"\");\n            if (zds->maxBlockSizeParam != 0)\n                zds->fParams.blockSizeMax = MIN(zds->fParams.blockSizeMax, (unsigned)zds->maxBlockSizeParam);\n\n            /* Adapt buffer sizes to frame header instructions */\n            {   size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */);\n                size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered\n                        ? ZSTD_decodingBufferSize_internal(zds->fParams.windowSize, zds->fParams.frameContentSize, zds->fParams.blockSizeMax)\n                        : 0;\n\n                ZSTD_DCtx_updateOversizedDuration(zds, neededInBuffSize, neededOutBuffSize);\n\n                {   int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize);\n                    int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds);\n\n                    if (tooSmall || tooLarge) {\n                        size_t const bufferSize = neededInBuffSize + neededOutBuffSize;\n                        DEBUGLOG(4, \"inBuff  : from %u to %u\",\n                                    (U32)zds->inBuffSize, (U32)neededInBuffSize);\n                        DEBUGLOG(4, \"outBuff : from %u to %u\",\n                                    (U32)zds->outBuffSize, (U32)neededOutBuffSize);\n                        if (zds->staticSize) {  /* static DCtx */\n                            DEBUGLOG(4, \"staticSize : %u\", (U32)zds->staticSize);\n                            assert(zds->staticSize >= sizeof(ZSTD_DCtx));  /* controlled at init */\n                            RETURN_ERROR_IF(\n                                bufferSize > zds->staticSize - sizeof(ZSTD_DCtx),\n                                memory_allocation, \"\");\n                        } else {\n                            ZSTD_customFree(zds->inBuff, zds->customMem);\n                            zds->inBuffSize = 0;\n                            zds->outBuffSize = 0;\n                            zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem);\n                            RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, \"\");\n                        }\n                        zds->inBuffSize = neededInBuffSize;\n                        zds->outBuff = zds->inBuff + zds->inBuffSize;\n                        zds->outBuffSize = neededOutBuffSize;\n            }   }   }\n            zds->streamStage = zdss_read;\n            ZSTD_FALLTHROUGH;\n\n        case zdss_read:\n            DEBUGLOG(5, \"stage zdss_read\");\n            {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip));\n                DEBUGLOG(5, \"neededInSize = %u\", (U32)neededInSize);\n                if (neededInSize==0) {  /* end of frame */\n                    zds->streamStage = zdss_init;\n                    someMoreWork = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */\n                    FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, ip, neededInSize), \"\");\n                    assert(ip != NULL);\n                    ip += neededInSize;\n                    /* Function modifies the stage so we must break */\n                    break;\n            }   }\n            if (ip==iend) { someMoreWork = 0; break; }   /* no more input */\n            zds->streamStage = zdss_load;\n            ZSTD_FALLTHROUGH;\n\n        case zdss_load:\n            {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);\n                size_t const toLoad = neededInSize - zds->inPos;\n                int const isSkipFrame = ZSTD_isSkipFrame(zds);\n                size_t loadedSize;\n                /* At this point we shouldn't be decompressing a block that we can stream. */\n                assert(neededInSize == ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)));\n                if (isSkipFrame) {\n                    loadedSize = MIN(toLoad, (size_t)(iend-ip));\n                } else {\n                    RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos,\n                                    corruption_detected,\n                                    \"should never happen\");\n                    loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip));\n                }\n                if (loadedSize != 0) {\n                    /* ip may be NULL */\n                    ip += loadedSize;\n                    zds->inPos += loadedSize;\n                }\n                if (loadedSize < toLoad) { someMoreWork = 0; break; }   /* not enough input, wait for more */\n\n                /* decode loaded input */\n                zds->inPos = 0;   /* input is consumed */\n                FORWARD_IF_ERROR(ZSTD_decompressContinueStream(zds, &op, oend, zds->inBuff, neededInSize), \"\");\n                /* Function modifies the stage so we must break */\n                break;\n            }\n        case zdss_flush:\n            {\n                size_t const toFlushSize = zds->outEnd - zds->outStart;\n                size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize);\n\n                op = op ? op + flushedSize : op;\n\n                zds->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {  /* flush completed */\n                    zds->streamStage = zdss_read;\n                    if ( (zds->outBuffSize < zds->fParams.frameContentSize)\n                        && (zds->outStart + zds->fParams.blockSizeMax > zds->outBuffSize) ) {\n                        DEBUGLOG(5, \"restart filling outBuff from beginning (left:%i, needed:%u)\",\n                                (int)(zds->outBuffSize - zds->outStart),\n                                (U32)zds->fParams.blockSizeMax);\n                        zds->outStart = zds->outEnd = 0;\n                    }\n                    break;\n            }   }\n            /* cannot complete flush */\n            someMoreWork = 0;\n            break;\n\n        default:\n            assert(0);    /* impossible */\n            RETURN_ERROR(GENERIC, \"impossible to reach\");   /* some compilers require default to do something */\n    }   }\n\n    /* result */\n    input->pos = (size_t)(ip - (const char*)(input->src));\n    output->pos = (size_t)(op - (char*)(output->dst));\n\n    /* Update the expected output buffer for ZSTD_obm_stable. */\n    zds->expectedOutBuffer = *output;\n\n    if ((ip==istart) && (op==ostart)) {  /* no forward progress */\n        zds->noForwardProgress ++;\n        if (zds->noForwardProgress >= ZSTD_NO_FORWARD_PROGRESS_MAX) {\n            RETURN_ERROR_IF(op==oend, noForwardProgress_destFull, \"\");\n            RETURN_ERROR_IF(ip==iend, noForwardProgress_inputEmpty, \"\");\n            assert(0);\n        }\n    } else {\n        zds->noForwardProgress = 0;\n    }\n    {   size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zds);\n        if (!nextSrcSizeHint) {   /* frame fully decoded */\n            if (zds->outEnd == zds->outStart) {  /* output fully flushed */\n                if (zds->hostageByte) {\n                    if (input->pos >= input->size) {\n                        /* can't release hostage (not present) */\n                        zds->streamStage = zdss_read;\n                        return 1;\n                    }\n                    input->pos++;  /* release hostage */\n                }   /* zds->hostageByte */\n                return 0;\n            }  /* zds->outEnd == zds->outStart */\n            if (!zds->hostageByte) { /* output not fully flushed; keep last byte as hostage; will be released when all output is flushed */\n                input->pos--;   /* note : pos > 0, otherwise, impossible to finish reading last block */\n                zds->hostageByte=1;\n            }\n            return 1;\n        }  /* nextSrcSizeHint==0 */\n        nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zds) == ZSTDnit_block);   /* preload header of next block */\n        assert(zds->inPos <= nextSrcSizeHint);\n        nextSrcSizeHint -= zds->inPos;   /* part already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\nsize_t ZSTD_decompressStream_simpleArgs (\n                            ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos)\n{\n    ZSTD_outBuffer output;\n    ZSTD_inBuffer  input;\n    output.dst = dst;\n    output.size = dstCapacity;\n    output.pos = *dstPos;\n    input.src = src;\n    input.size = srcSize;\n    input.pos = *srcPos;\n    {   size_t const cErr = ZSTD_decompressStream(dctx, &output, &input);\n        *dstPos = output.pos;\n        *srcPos = input.pos;\n        return cErr;\n    }\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/decompress/zstd_decompress_block.c",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n/* zstd_decompress_block :\n * this module takes care of decompressing _compressed_ block */\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include \"../common/zstd_deps.h\"   /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */\n#include \"../common/compiler.h\"    /* prefetch */\n#include \"../common/cpu.h\"         /* bmi2 */\n#include \"../common/mem.h\"         /* low level memory routines */\n#define FSE_STATIC_LINKING_ONLY\n#include \"../common/fse.h\"\n#include \"../common/huf.h\"\n#include \"../common/zstd_internal.h\"\n#include \"zstd_decompress_internal.h\"   /* ZSTD_DCtx */\n#include \"zstd_ddict.h\"  /* ZSTD_DDictDictContent */\n#include \"zstd_decompress_block.h\"\n#include \"../common/bits.h\"  /* ZSTD_highbit32 */\n\n/*_*******************************************************\n*  Macros\n**********************************************************/\n\n/* These two optional macros force the use one way or another of the two\n * ZSTD_decompressSequences implementations. You can't force in both directions\n * at the same time.\n */\n#if defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \\\n    defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)\n#error \"Cannot force the use of the short and the long ZSTD_decompressSequences variants!\"\n#endif\n\n\n/*_*******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); }\n\n\n/*-*************************************************************\n *   Block decoding\n ***************************************************************/\n\nstatic size_t ZSTD_blockSizeMax(ZSTD_DCtx const* dctx)\n{\n    size_t const blockSizeMax = dctx->isFrameDecompression ? dctx->fParams.blockSizeMax : ZSTD_BLOCKSIZE_MAX;\n    assert(blockSizeMax <= ZSTD_BLOCKSIZE_MAX);\n    return blockSizeMax;\n}\n\n/*! ZSTD_getcBlockSize() :\n *  Provides the size of compressed block from block header `src` */\nsize_t ZSTD_getcBlockSize(const void* src, size_t srcSize,\n                          blockProperties_t* bpPtr)\n{\n    RETURN_ERROR_IF(srcSize < ZSTD_blockHeaderSize, srcSize_wrong, \"\");\n\n    {   U32 const cBlockHeader = MEM_readLE24(src);\n        U32 const cSize = cBlockHeader >> 3;\n        bpPtr->lastBlock = cBlockHeader & 1;\n        bpPtr->blockType = (blockType_e)((cBlockHeader >> 1) & 3);\n        bpPtr->origSize = cSize;   /* only useful for RLE */\n        if (bpPtr->blockType == bt_rle) return 1;\n        RETURN_ERROR_IF(bpPtr->blockType == bt_reserved, corruption_detected, \"\");\n        return cSize;\n    }\n}\n\n/* Allocate buffer for literals, either overlapping current dst, or split between dst and litExtraBuffer, or stored entirely within litExtraBuffer */\nstatic void ZSTD_allocateLiteralsBuffer(ZSTD_DCtx* dctx, void* const dst, const size_t dstCapacity, const size_t litSize,\n    const streaming_operation streaming, const size_t expectedWriteSize, const unsigned splitImmediately)\n{\n    size_t const blockSizeMax = ZSTD_blockSizeMax(dctx);\n    assert(litSize <= blockSizeMax);\n    assert(dctx->isFrameDecompression || streaming == not_streaming);\n    assert(expectedWriteSize <= blockSizeMax);\n    if (streaming == not_streaming && dstCapacity > blockSizeMax + WILDCOPY_OVERLENGTH + litSize + WILDCOPY_OVERLENGTH) {\n        /* If we aren't streaming, we can just put the literals after the output\n         * of the current block. We don't need to worry about overwriting the\n         * extDict of our window, because it doesn't exist.\n         * So if we have space after the end of the block, just put it there.\n         */\n        dctx->litBuffer = (BYTE*)dst + blockSizeMax + WILDCOPY_OVERLENGTH;\n        dctx->litBufferEnd = dctx->litBuffer + litSize;\n        dctx->litBufferLocation = ZSTD_in_dst;\n    } else if (litSize <= ZSTD_LITBUFFEREXTRASIZE) {\n        /* Literals fit entirely within the extra buffer, put them there to avoid\n         * having to split the literals.\n         */\n        dctx->litBuffer = dctx->litExtraBuffer;\n        dctx->litBufferEnd = dctx->litBuffer + litSize;\n        dctx->litBufferLocation = ZSTD_not_in_dst;\n    } else {\n        assert(blockSizeMax > ZSTD_LITBUFFEREXTRASIZE);\n        /* Literals must be split between the output block and the extra lit\n         * buffer. We fill the extra lit buffer with the tail of the literals,\n         * and put the rest of the literals at the end of the block, with\n         * WILDCOPY_OVERLENGTH of buffer room to allow for overreads.\n         * This MUST not write more than our maxBlockSize beyond dst, because in\n         * streaming mode, that could overwrite part of our extDict window.\n         */\n        if (splitImmediately) {\n            /* won't fit in litExtraBuffer, so it will be split between end of dst and extra buffer */\n            dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;\n            dctx->litBufferEnd = dctx->litBuffer + litSize - ZSTD_LITBUFFEREXTRASIZE;\n        } else {\n            /* initially this will be stored entirely in dst during huffman decoding, it will partially be shifted to litExtraBuffer after */\n            dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize;\n            dctx->litBufferEnd = (BYTE*)dst + expectedWriteSize;\n        }\n        dctx->litBufferLocation = ZSTD_split;\n        assert(dctx->litBufferEnd <= (BYTE*)dst + expectedWriteSize);\n    }\n}\n\n/*! ZSTD_decodeLiteralsBlock() :\n * Where it is possible to do so without being stomped by the output during decompression, the literals block will be stored\n * in the dstBuffer.  If there is room to do so, it will be stored in full in the excess dst space after where the current\n * block will be output.  Otherwise it will be stored at the end of the current dst blockspace, with a small portion being\n * stored in dctx->litExtraBuffer to help keep it \"ahead\" of the current output write.\n *\n * @return : nb of bytes read from src (< srcSize )\n *  note : symbol not declared but exposed for fullbench */\nstatic size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize,   /* note : srcSize < BLOCKSIZE */\n                          void* dst, size_t dstCapacity, const streaming_operation streaming)\n{\n    DEBUGLOG(5, \"ZSTD_decodeLiteralsBlock\");\n    RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, \"\");\n\n    {   const BYTE* const istart = (const BYTE*) src;\n        SymbolEncodingType_e const litEncType = (SymbolEncodingType_e)(istart[0] & 3);\n        size_t const blockSizeMax = ZSTD_blockSizeMax(dctx);\n\n        switch(litEncType)\n        {\n        case set_repeat:\n            DEBUGLOG(5, \"set_repeat flag : re-using stats from previous compressed literals block\");\n            RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, \"\");\n            ZSTD_FALLTHROUGH;\n\n        case set_compressed:\n            RETURN_ERROR_IF(srcSize < 5, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need up to 5 for case 3\");\n            {   size_t lhSize, litSize, litCSize;\n                U32 singleStream=0;\n                U32 const lhlCode = (istart[0] >> 2) & 3;\n                U32 const lhc = MEM_readLE32(istart);\n                size_t hufSuccess;\n                size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity);\n                int const flags = 0\n                    | (ZSTD_DCtx_get_bmi2(dctx) ? HUF_flags_bmi2 : 0)\n                    | (dctx->disableHufAsm ? HUF_flags_disableAsm : 0);\n                switch(lhlCode)\n                {\n                case 0: case 1: default:   /* note : default is impossible, since lhlCode into [0..3] */\n                    /* 2 - 2 - 10 - 10 */\n                    singleStream = !lhlCode;\n                    lhSize = 3;\n                    litSize  = (lhc >> 4) & 0x3FF;\n                    litCSize = (lhc >> 14) & 0x3FF;\n                    break;\n                case 2:\n                    /* 2 - 2 - 14 - 14 */\n                    lhSize = 4;\n                    litSize  = (lhc >> 4) & 0x3FFF;\n                    litCSize = lhc >> 18;\n                    break;\n                case 3:\n                    /* 2 - 2 - 18 - 18 */\n                    lhSize = 5;\n                    litSize  = (lhc >> 4) & 0x3FFFF;\n                    litCSize = (lhc >> 22) + ((size_t)istart[4] << 10);\n                    break;\n                }\n                RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, \"NULL not handled\");\n                RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, \"\");\n                if (!singleStream)\n                    RETURN_ERROR_IF(litSize < MIN_LITERALS_FOR_4_STREAMS, literals_headerWrong,\n                        \"Not enough literals (%zu) for the 4-streams mode (min %u)\",\n                        litSize, MIN_LITERALS_FOR_4_STREAMS);\n                RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, \"\");\n                RETURN_ERROR_IF(expectedWriteSize < litSize , dstSize_tooSmall, \"\");\n                ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 0);\n\n                /* prefetch huffman table if cold */\n                if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {\n                    PREFETCH_AREA(dctx->HUFptr, sizeof(dctx->entropy.hufTable));\n                }\n\n                if (litEncType==set_repeat) {\n                    if (singleStream) {\n                        hufSuccess = HUF_decompress1X_usingDTable(\n                            dctx->litBuffer, litSize, istart+lhSize, litCSize,\n                            dctx->HUFptr, flags);\n                    } else {\n                        assert(litSize >= MIN_LITERALS_FOR_4_STREAMS);\n                        hufSuccess = HUF_decompress4X_usingDTable(\n                            dctx->litBuffer, litSize, istart+lhSize, litCSize,\n                            dctx->HUFptr, flags);\n                    }\n                } else {\n                    if (singleStream) {\n#if defined(HUF_FORCE_DECOMPRESS_X2)\n                        hufSuccess = HUF_decompress1X_DCtx_wksp(\n                            dctx->entropy.hufTable, dctx->litBuffer, litSize,\n                            istart+lhSize, litCSize, dctx->workspace,\n                            sizeof(dctx->workspace), flags);\n#else\n                        hufSuccess = HUF_decompress1X1_DCtx_wksp(\n                            dctx->entropy.hufTable, dctx->litBuffer, litSize,\n                            istart+lhSize, litCSize, dctx->workspace,\n                            sizeof(dctx->workspace), flags);\n#endif\n                    } else {\n                        hufSuccess = HUF_decompress4X_hufOnly_wksp(\n                            dctx->entropy.hufTable, dctx->litBuffer, litSize,\n                            istart+lhSize, litCSize, dctx->workspace,\n                            sizeof(dctx->workspace), flags);\n                    }\n                }\n                if (dctx->litBufferLocation == ZSTD_split)\n                {\n                    assert(litSize > ZSTD_LITBUFFEREXTRASIZE);\n                    ZSTD_memcpy(dctx->litExtraBuffer, dctx->litBufferEnd - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);\n                    ZSTD_memmove(dctx->litBuffer + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH, dctx->litBuffer, litSize - ZSTD_LITBUFFEREXTRASIZE);\n                    dctx->litBuffer += ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;\n                    dctx->litBufferEnd -= WILDCOPY_OVERLENGTH;\n                    assert(dctx->litBufferEnd <= (BYTE*)dst + blockSizeMax);\n                }\n\n                RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, \"\");\n\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                dctx->litEntropy = 1;\n                if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;\n                return litCSize + lhSize;\n            }\n\n        case set_basic:\n            {   size_t litSize, lhSize;\n                U32 const lhlCode = ((istart[0]) >> 2) & 3;\n                size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity);\n                switch(lhlCode)\n                {\n                case 0: case 2: default:   /* note : default is impossible, since lhlCode into [0..3] */\n                    lhSize = 1;\n                    litSize = istart[0] >> 3;\n                    break;\n                case 1:\n                    lhSize = 2;\n                    litSize = MEM_readLE16(istart) >> 4;\n                    break;\n                case 3:\n                    lhSize = 3;\n                    RETURN_ERROR_IF(srcSize<3, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize = 3\");\n                    litSize = MEM_readLE24(istart) >> 4;\n                    break;\n                }\n\n                RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, \"NULL not handled\");\n                RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, \"\");\n                RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, \"\");\n                ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);\n                if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                    RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, \"\");\n                    if (dctx->litBufferLocation == ZSTD_split)\n                    {\n                        ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize - ZSTD_LITBUFFEREXTRASIZE);\n                        ZSTD_memcpy(dctx->litExtraBuffer, istart + lhSize + litSize - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);\n                    }\n                    else\n                    {\n                        ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize);\n                    }\n                    dctx->litPtr = dctx->litBuffer;\n                    dctx->litSize = litSize;\n                    return lhSize+litSize;\n                }\n                /* direct reference into compressed stream */\n                dctx->litPtr = istart+lhSize;\n                dctx->litSize = litSize;\n                dctx->litBufferEnd = dctx->litPtr + litSize;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                return lhSize+litSize;\n            }\n\n        case set_rle:\n            {   U32 const lhlCode = ((istart[0]) >> 2) & 3;\n                size_t litSize, lhSize;\n                size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity);\n                switch(lhlCode)\n                {\n                case 0: case 2: default:   /* note : default is impossible, since lhlCode into [0..3] */\n                    lhSize = 1;\n                    litSize = istart[0] >> 3;\n                    break;\n                case 1:\n                    lhSize = 2;\n                    RETURN_ERROR_IF(srcSize<3, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize+1 = 3\");\n                    litSize = MEM_readLE16(istart) >> 4;\n                    break;\n                case 3:\n                    lhSize = 3;\n                    RETURN_ERROR_IF(srcSize<4, corruption_detected, \"srcSize >= MIN_CBLOCK_SIZE == 2; here we need lhSize+1 = 4\");\n                    litSize = MEM_readLE24(istart) >> 4;\n                    break;\n                }\n                RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, \"NULL not handled\");\n                RETURN_ERROR_IF(litSize > blockSizeMax, corruption_detected, \"\");\n                RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, \"\");\n                ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);\n                if (dctx->litBufferLocation == ZSTD_split)\n                {\n                    ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize - ZSTD_LITBUFFEREXTRASIZE);\n                    ZSTD_memset(dctx->litExtraBuffer, istart[lhSize], ZSTD_LITBUFFEREXTRASIZE);\n                }\n                else\n                {\n                    ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize);\n                }\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                return lhSize+1;\n            }\n        default:\n            RETURN_ERROR(corruption_detected, \"impossible\");\n        }\n    }\n}\n\n/* Hidden declaration for fullbench */\nsize_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize,\n                          void* dst, size_t dstCapacity);\nsize_t ZSTD_decodeLiteralsBlock_wrapper(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize,\n                          void* dst, size_t dstCapacity)\n{\n    dctx->isFrameDecompression = 0;\n    return ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, not_streaming);\n}\n\n/* Default FSE distribution tables.\n * These are pre-calculated FSE decoding tables using default distributions as defined in specification :\n * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions\n * They were generated programmatically with following method :\n * - start from default distributions, present in /lib/common/zstd_internal.h\n * - generate tables normally, using ZSTD_buildFSETable()\n * - printout the content of tables\n * - prettify output, report below, test with fuzzer to ensure it's correct */\n\n/* Default FSE distribution table for Literal Lengths */\nstatic const ZSTD_seqSymbol LL_defaultDTable[(1<<LL_DEFAULTNORMLOG)+1] = {\n     {  1,  1,  1, LL_DEFAULTNORMLOG},  /* header : fastMode, tableLog */\n     /* nextState, nbAddBits, nbBits, baseVal */\n     {  0,  0,  4,    0},  { 16,  0,  4,    0},\n     { 32,  0,  5,    1},  {  0,  0,  5,    3},\n     {  0,  0,  5,    4},  {  0,  0,  5,    6},\n     {  0,  0,  5,    7},  {  0,  0,  5,    9},\n     {  0,  0,  5,   10},  {  0,  0,  5,   12},\n     {  0,  0,  6,   14},  {  0,  1,  5,   16},\n     {  0,  1,  5,   20},  {  0,  1,  5,   22},\n     {  0,  2,  5,   28},  {  0,  3,  5,   32},\n     {  0,  4,  5,   48},  { 32,  6,  5,   64},\n     {  0,  7,  5,  128},  {  0,  8,  6,  256},\n     {  0, 10,  6, 1024},  {  0, 12,  6, 4096},\n     { 32,  0,  4,    0},  {  0,  0,  4,    1},\n     {  0,  0,  5,    2},  { 32,  0,  5,    4},\n     {  0,  0,  5,    5},  { 32,  0,  5,    7},\n     {  0,  0,  5,    8},  { 32,  0,  5,   10},\n     {  0,  0,  5,   11},  {  0,  0,  6,   13},\n     { 32,  1,  5,   16},  {  0,  1,  5,   18},\n     { 32,  1,  5,   22},  {  0,  2,  5,   24},\n     { 32,  3,  5,   32},  {  0,  3,  5,   40},\n     {  0,  6,  4,   64},  { 16,  6,  4,   64},\n     { 32,  7,  5,  128},  {  0,  9,  6,  512},\n     {  0, 11,  6, 2048},  { 48,  0,  4,    0},\n     { 16,  0,  4,    1},  { 32,  0,  5,    2},\n     { 32,  0,  5,    3},  { 32,  0,  5,    5},\n     { 32,  0,  5,    6},  { 32,  0,  5,    8},\n     { 32,  0,  5,    9},  { 32,  0,  5,   11},\n     { 32,  0,  5,   12},  {  0,  0,  6,   15},\n     { 32,  1,  5,   18},  { 32,  1,  5,   20},\n     { 32,  2,  5,   24},  { 32,  2,  5,   28},\n     { 32,  3,  5,   40},  { 32,  4,  5,   48},\n     {  0, 16,  6,65536},  {  0, 15,  6,32768},\n     {  0, 14,  6,16384},  {  0, 13,  6, 8192},\n};   /* LL_defaultDTable */\n\n/* Default FSE distribution table for Offset Codes */\nstatic const ZSTD_seqSymbol OF_defaultDTable[(1<<OF_DEFAULTNORMLOG)+1] = {\n    {  1,  1,  1, OF_DEFAULTNORMLOG},  /* header : fastMode, tableLog */\n    /* nextState, nbAddBits, nbBits, baseVal */\n    {  0,  0,  5,    0},     {  0,  6,  4,   61},\n    {  0,  9,  5,  509},     {  0, 15,  5,32765},\n    {  0, 21,  5,2097149},   {  0,  3,  5,    5},\n    {  0,  7,  4,  125},     {  0, 12,  5, 4093},\n    {  0, 18,  5,262141},    {  0, 23,  5,8388605},\n    {  0,  5,  5,   29},     {  0,  8,  4,  253},\n    {  0, 14,  5,16381},     {  0, 20,  5,1048573},\n    {  0,  2,  5,    1},     { 16,  7,  4,  125},\n    {  0, 11,  5, 2045},     {  0, 17,  5,131069},\n    {  0, 22,  5,4194301},   {  0,  4,  5,   13},\n    { 16,  8,  4,  253},     {  0, 13,  5, 8189},\n    {  0, 19,  5,524285},    {  0,  1,  5,    1},\n    { 16,  6,  4,   61},     {  0, 10,  5, 1021},\n    {  0, 16,  5,65533},     {  0, 28,  5,268435453},\n    {  0, 27,  5,134217725}, {  0, 26,  5,67108861},\n    {  0, 25,  5,33554429},  {  0, 24,  5,16777213},\n};   /* OF_defaultDTable */\n\n\n/* Default FSE distribution table for Match Lengths */\nstatic const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {\n    {  1,  1,  1, ML_DEFAULTNORMLOG},  /* header : fastMode, tableLog */\n    /* nextState, nbAddBits, nbBits, baseVal */\n    {  0,  0,  6,    3},  {  0,  0,  4,    4},\n    { 32,  0,  5,    5},  {  0,  0,  5,    6},\n    {  0,  0,  5,    8},  {  0,  0,  5,    9},\n    {  0,  0,  5,   11},  {  0,  0,  6,   13},\n    {  0,  0,  6,   16},  {  0,  0,  6,   19},\n    {  0,  0,  6,   22},  {  0,  0,  6,   25},\n    {  0,  0,  6,   28},  {  0,  0,  6,   31},\n    {  0,  0,  6,   34},  {  0,  1,  6,   37},\n    {  0,  1,  6,   41},  {  0,  2,  6,   47},\n    {  0,  3,  6,   59},  {  0,  4,  6,   83},\n    {  0,  7,  6,  131},  {  0,  9,  6,  515},\n    { 16,  0,  4,    4},  {  0,  0,  4,    5},\n    { 32,  0,  5,    6},  {  0,  0,  5,    7},\n    { 32,  0,  5,    9},  {  0,  0,  5,   10},\n    {  0,  0,  6,   12},  {  0,  0,  6,   15},\n    {  0,  0,  6,   18},  {  0,  0,  6,   21},\n    {  0,  0,  6,   24},  {  0,  0,  6,   27},\n    {  0,  0,  6,   30},  {  0,  0,  6,   33},\n    {  0,  1,  6,   35},  {  0,  1,  6,   39},\n    {  0,  2,  6,   43},  {  0,  3,  6,   51},\n    {  0,  4,  6,   67},  {  0,  5,  6,   99},\n    {  0,  8,  6,  259},  { 32,  0,  4,    4},\n    { 48,  0,  4,    4},  { 16,  0,  4,    5},\n    { 32,  0,  5,    7},  { 32,  0,  5,    8},\n    { 32,  0,  5,   10},  { 32,  0,  5,   11},\n    {  0,  0,  6,   14},  {  0,  0,  6,   17},\n    {  0,  0,  6,   20},  {  0,  0,  6,   23},\n    {  0,  0,  6,   26},  {  0,  0,  6,   29},\n    {  0,  0,  6,   32},  {  0, 16,  6,65539},\n    {  0, 15,  6,32771},  {  0, 14,  6,16387},\n    {  0, 13,  6, 8195},  {  0, 12,  6, 4099},\n    {  0, 11,  6, 2051},  {  0, 10,  6, 1027},\n};   /* ML_defaultDTable */\n\n\nstatic void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U8 nbAddBits)\n{\n    void* ptr = dt;\n    ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;\n    ZSTD_seqSymbol* const cell = dt + 1;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->nbBits = 0;\n    cell->nextState = 0;\n    assert(nbAddBits < 255);\n    cell->nbAdditionalBits = nbAddBits;\n    cell->baseValue = baseValue;\n}\n\n\n/* ZSTD_buildFSETable() :\n * generate FSE decoding table for one symbol (ll, ml or off)\n * cannot fail if input is valid =>\n * all inputs are presumed validated at this stage */\nFORCE_INLINE_TEMPLATE\nvoid ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize)\n{\n    ZSTD_seqSymbol* const tableDecode = dt+1;\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n\n    U16* symbolNext = (U16*)wksp;\n    BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1);\n    U32 highThreshold = tableSize - 1;\n\n\n    /* Sanity Checks */\n    assert(maxSymbolValue <= MaxSeq);\n    assert(tableLog <= MaxFSELog);\n    assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE);\n    (void)wkspSize;\n    /* Init, lay down lowprob symbols */\n    {   ZSTD_seqSymbol_header DTableH;\n        DTableH.tableLog = tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].baseValue = s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    assert(normalizedCounter[s]>=0);\n                    symbolNext[s] = (U16)normalizedCounter[s];\n        }   }   }\n        ZSTD_memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    assert(tableSize <= 512);\n    /* Specialized symbol spreading for the case when there are\n     * no low probability (-1 count) symbols. When compressing\n     * small blocks we avoid low probability symbols to hit this\n     * case, since header decoding speed matters more.\n     */\n    if (highThreshold == tableSize - 1) {\n        size_t const tableMask = tableSize-1;\n        size_t const step = FSE_TABLESTEP(tableSize);\n        /* First lay down the symbols in order.\n         * We use a uint64_t to lay down 8 bytes at a time. This reduces branch\n         * misses since small blocks generally have small table logs, so nearly\n         * all symbols have counts <= 8. We ensure we have 8 bytes at the end of\n         * our buffer to handle the over-write.\n         */\n        {\n            U64 const add = 0x0101010101010101ull;\n            size_t pos = 0;\n            U64 sv = 0;\n            U32 s;\n            for (s=0; s<maxSV1; ++s, sv += add) {\n                int i;\n                int const n = normalizedCounter[s];\n                MEM_write64(spread + pos, sv);\n                for (i = 8; i < n; i += 8) {\n                    MEM_write64(spread + pos + i, sv);\n                }\n                assert(n>=0);\n                pos += (size_t)n;\n            }\n        }\n        /* Now we spread those positions across the table.\n         * The benefit of doing it in two stages is that we avoid the\n         * variable size inner loop, which caused lots of branch misses.\n         * Now we can run through all the positions without any branch misses.\n         * We unroll the loop twice, since that is what empirically worked best.\n         */\n        {\n            size_t position = 0;\n            size_t s;\n            size_t const unroll = 2;\n            assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */\n            for (s = 0; s < (size_t)tableSize; s += unroll) {\n                size_t u;\n                for (u = 0; u < unroll; ++u) {\n                    size_t const uPosition = (position + (u * step)) & tableMask;\n                    tableDecode[uPosition].baseValue = spread[s + u];\n                }\n                position = (position + (unroll * step)) & tableMask;\n            }\n            assert(position == 0);\n        }\n    } else {\n        U32 const tableMask = tableSize-1;\n        U32 const step = FSE_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            int const n = normalizedCounter[s];\n            for (i=0; i<n; i++) {\n                tableDecode[position].baseValue = s;\n                position = (position + step) & tableMask;\n                while (UNLIKELY(position > highThreshold)) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n        assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {\n        U32 u;\n        for (u=0; u<tableSize; u++) {\n            U32 const symbol = tableDecode[u].baseValue;\n            U32 const nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - ZSTD_highbit32(nextState) );\n            tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n            assert(nbAdditionalBits[symbol] < 255);\n            tableDecode[u].nbAdditionalBits = nbAdditionalBits[symbol];\n            tableDecode[u].baseValue = baseValue[symbol];\n        }\n    }\n}\n\n/* Avoids the FORCE_INLINE of the _body() function. */\nstatic void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize)\n{\n    ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,\n            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n}\n\n#if DYNAMIC_BMI2\nBMI2_TARGET_ATTRIBUTE static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize)\n{\n    ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,\n            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n}\n#endif\n\nvoid ZSTD_buildFSETable(ZSTD_seqSymbol* dt,\n            const short* normalizedCounter, unsigned maxSymbolValue,\n            const U32* baseValue, const U8* nbAdditionalBits,\n            unsigned tableLog, void* wksp, size_t wkspSize, int bmi2)\n{\n#if DYNAMIC_BMI2\n    if (bmi2) {\n        ZSTD_buildFSETable_body_bmi2(dt, normalizedCounter, maxSymbolValue,\n                baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n        return;\n    }\n#endif\n    (void)bmi2;\n    ZSTD_buildFSETable_body_default(dt, normalizedCounter, maxSymbolValue,\n            baseValue, nbAdditionalBits, tableLog, wksp, wkspSize);\n}\n\n\n/*! ZSTD_buildSeqTable() :\n * @return : nb bytes read from src,\n *           or an error code if it fails */\nstatic size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,\n                                 SymbolEncodingType_e type, unsigned max, U32 maxLog,\n                                 const void* src, size_t srcSize,\n                                 const U32* baseValue, const U8* nbAdditionalBits,\n                                 const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable,\n                                 int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize,\n                                 int bmi2)\n{\n    switch(type)\n    {\n    case set_rle :\n        RETURN_ERROR_IF(!srcSize, srcSize_wrong, \"\");\n        RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected, \"\");\n        {   U32 const symbol = *(const BYTE*)src;\n            U32 const baseline = baseValue[symbol];\n            U8 const nbBits = nbAdditionalBits[symbol];\n            ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);\n        }\n        *DTablePtr = DTableSpace;\n        return 1;\n    case set_basic :\n        *DTablePtr = defaultTable;\n        return 0;\n    case set_repeat:\n        RETURN_ERROR_IF(!flagRepeatTable, corruption_detected, \"\");\n        /* prefetch FSE table if used */\n        if (ddictIsCold && (nbSeq > 24 /* heuristic */)) {\n            const void* const pStart = *DTablePtr;\n            size_t const pSize = sizeof(ZSTD_seqSymbol) * (SEQSYMBOL_TABLE_SIZE(maxLog));\n            PREFETCH_AREA(pStart, pSize);\n        }\n        return 0;\n    case set_compressed :\n        {   unsigned tableLog;\n            S16 norm[MaxSeq+1];\n            size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize);\n            RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, \"\");\n            RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, \"\");\n            ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2);\n            *DTablePtr = DTableSpace;\n            return headerSize;\n        }\n    default :\n        assert(0);\n        RETURN_ERROR(GENERIC, \"impossible\");\n    }\n}\n\nsize_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,\n                             const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip = istart;\n    int nbSeq;\n    DEBUGLOG(5, \"ZSTD_decodeSeqHeaders\");\n\n    /* check */\n    RETURN_ERROR_IF(srcSize < MIN_SEQUENCES_SIZE, srcSize_wrong, \"\");\n\n    /* SeqHead */\n    nbSeq = *ip++;\n    if (nbSeq > 0x7F) {\n        if (nbSeq == 0xFF) {\n            RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, \"\");\n            nbSeq = MEM_readLE16(ip) + LONGNBSEQ;\n            ip+=2;\n        } else {\n            RETURN_ERROR_IF(ip >= iend, srcSize_wrong, \"\");\n            nbSeq = ((nbSeq-0x80)<<8) + *ip++;\n        }\n    }\n    *nbSeqPtr = nbSeq;\n\n    if (nbSeq == 0) {\n        /* No sequence : section ends immediately */\n        RETURN_ERROR_IF(ip != iend, corruption_detected,\n            \"extraneous data present in the Sequences section\");\n        return (size_t)(ip - istart);\n    }\n\n    /* FSE table descriptors */\n    RETURN_ERROR_IF(ip+1 > iend, srcSize_wrong, \"\"); /* minimum possible size: 1 byte for symbol encoding types */\n    RETURN_ERROR_IF(*ip & 3, corruption_detected, \"\"); /* The last field, Reserved, must be all-zeroes. */\n    {   SymbolEncodingType_e const LLtype = (SymbolEncodingType_e)(*ip >> 6);\n        SymbolEncodingType_e const OFtype = (SymbolEncodingType_e)((*ip >> 4) & 3);\n        SymbolEncodingType_e const MLtype = (SymbolEncodingType_e)((*ip >> 2) & 3);\n        ip++;\n\n        /* Build DTables */\n        {   size_t const llhSize = ZSTD_buildSeqTable(dctx->entropy.LLTable, &dctx->LLTptr,\n                                                      LLtype, MaxLL, LLFSELog,\n                                                      ip, iend-ip,\n                                                      LL_base, LL_bits,\n                                                      LL_defaultDTable, dctx->fseEntropy,\n                                                      dctx->ddictIsCold, nbSeq,\n                                                      dctx->workspace, sizeof(dctx->workspace),\n                                                      ZSTD_DCtx_get_bmi2(dctx));\n            RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, \"ZSTD_buildSeqTable failed\");\n            ip += llhSize;\n        }\n\n        {   size_t const ofhSize = ZSTD_buildSeqTable(dctx->entropy.OFTable, &dctx->OFTptr,\n                                                      OFtype, MaxOff, OffFSELog,\n                                                      ip, iend-ip,\n                                                      OF_base, OF_bits,\n                                                      OF_defaultDTable, dctx->fseEntropy,\n                                                      dctx->ddictIsCold, nbSeq,\n                                                      dctx->workspace, sizeof(dctx->workspace),\n                                                      ZSTD_DCtx_get_bmi2(dctx));\n            RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, \"ZSTD_buildSeqTable failed\");\n            ip += ofhSize;\n        }\n\n        {   size_t const mlhSize = ZSTD_buildSeqTable(dctx->entropy.MLTable, &dctx->MLTptr,\n                                                      MLtype, MaxML, MLFSELog,\n                                                      ip, iend-ip,\n                                                      ML_base, ML_bits,\n                                                      ML_defaultDTable, dctx->fseEntropy,\n                                                      dctx->ddictIsCold, nbSeq,\n                                                      dctx->workspace, sizeof(dctx->workspace),\n                                                      ZSTD_DCtx_get_bmi2(dctx));\n            RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, \"ZSTD_buildSeqTable failed\");\n            ip += mlhSize;\n        }\n    }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    size_t state;\n    const ZSTD_seqSymbol* table;\n} ZSTD_fseState;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    ZSTD_fseState stateLL;\n    ZSTD_fseState stateOffb;\n    ZSTD_fseState stateML;\n    size_t prevOffset[ZSTD_REP_NUM];\n} seqState_t;\n\n/*! ZSTD_overlapCopy8() :\n *  Copies 8 bytes from ip to op and updates op and ip where ip <= op.\n *  If the offset is < 8 then the offset is spread to at least 8 bytes.\n *\n *  Precondition: *ip <= *op\n *  Postcondition: *op - *op >= 8\n */\nHINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) {\n    assert(*ip <= *op);\n    if (offset < 8) {\n        /* close range match, overlap */\n        static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n        static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n        int const sub2 = dec64table[offset];\n        (*op)[0] = (*ip)[0];\n        (*op)[1] = (*ip)[1];\n        (*op)[2] = (*ip)[2];\n        (*op)[3] = (*ip)[3];\n        *ip += dec32table[offset];\n        ZSTD_copy4(*op+4, *ip);\n        *ip -= sub2;\n    } else {\n        ZSTD_copy8(*op, *ip);\n    }\n    *ip += 8;\n    *op += 8;\n    assert(*op - *ip >= 8);\n}\n\n/*! ZSTD_safecopy() :\n *  Specialized version of memcpy() that is allowed to READ up to WILDCOPY_OVERLENGTH past the input buffer\n *  and write up to 16 bytes past oend_w (op >= oend_w is allowed).\n *  This function is only called in the uncommon case where the sequence is near the end of the block. It\n *  should be fast for a single long sequence, but can be slow for several short sequences.\n *\n *  @param ovtype controls the overlap detection\n *         - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.\n *         - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart.\n *           The src buffer must be before the dst buffer.\n */\nstatic void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) {\n    ptrdiff_t const diff = op - ip;\n    BYTE* const oend = op + length;\n\n    assert((ovtype == ZSTD_no_overlap && (diff <= -8 || diff >= 8 || op >= oend_w)) ||\n           (ovtype == ZSTD_overlap_src_before_dst && diff >= 0));\n\n    if (length < 8) {\n        /* Handle short lengths. */\n        while (op < oend) *op++ = *ip++;\n        return;\n    }\n    if (ovtype == ZSTD_overlap_src_before_dst) {\n        /* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */\n        assert(length >= 8);\n        ZSTD_overlapCopy8(&op, &ip, diff);\n        length -= 8;\n        assert(op - ip >= 8);\n        assert(op <= oend);\n    }\n\n    if (oend <= oend_w) {\n        /* No risk of overwrite. */\n        ZSTD_wildcopy(op, ip, length, ovtype);\n        return;\n    }\n    if (op <= oend_w) {\n        /* Wildcopy until we get close to the end. */\n        assert(oend > oend_w);\n        ZSTD_wildcopy(op, ip, oend_w - op, ovtype);\n        ip += oend_w - op;\n        op += oend_w - op;\n    }\n    /* Handle the leftovers. */\n    while (op < oend) *op++ = *ip++;\n}\n\n/* ZSTD_safecopyDstBeforeSrc():\n * This version allows overlap with dst before src, or handles the non-overlap case with dst after src\n * Kept separate from more common ZSTD_safecopy case to avoid performance impact to the safecopy common case */\nstatic void ZSTD_safecopyDstBeforeSrc(BYTE* op, const BYTE* ip, ptrdiff_t length) {\n    ptrdiff_t const diff = op - ip;\n    BYTE* const oend = op + length;\n\n    if (length < 8 || diff > -8) {\n        /* Handle short lengths, close overlaps, and dst not before src. */\n        while (op < oend) *op++ = *ip++;\n        return;\n    }\n\n    if (op <= oend - WILDCOPY_OVERLENGTH && diff < -WILDCOPY_VECLEN) {\n        ZSTD_wildcopy(op, ip, oend - WILDCOPY_OVERLENGTH - op, ZSTD_no_overlap);\n        ip += oend - WILDCOPY_OVERLENGTH - op;\n        op += oend - WILDCOPY_OVERLENGTH - op;\n    }\n\n    /* Handle the leftovers. */\n    while (op < oend) *op++ = *ip++;\n}\n\n/* ZSTD_execSequenceEnd():\n * This version handles cases that are near the end of the output buffer. It requires\n * more careful checks to make sure there is no overflow. By separating out these hard\n * and unlikely cases, we can speed up the common cases.\n *\n * NOTE: This function needs to be fast for a single long sequence, but doesn't need\n * to be optimized for many small sequences, since those fall into ZSTD_execSequence().\n */\nFORCE_NOINLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequenceEnd(BYTE* op,\n    BYTE* const oend, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n    BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;\n\n    /* bounds checks : careful of address space overflow in 32-bit mode */\n    RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, \"last match must fit within dstBuffer\");\n    RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, \"try to read beyond literal buffer\");\n    assert(op < op + sequenceLength);\n    assert(oLitEnd < op + sequenceLength);\n\n    /* copy literals */\n    ZSTD_safecopy(op, oend_w, *litPtr, sequence.litLength, ZSTD_no_overlap);\n    op = oLitEnd;\n    *litPtr = iLitEnd;\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix */\n        RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, \"\");\n        match = dictEnd - (prefixStart - match);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = dictEnd - match;\n        ZSTD_memmove(oLitEnd, match, length1);\n        op = oLitEnd + length1;\n        sequence.matchLength -= length1;\n        match = prefixStart;\n        }\n    }\n    ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);\n    return sequenceLength;\n}\n\n/* ZSTD_execSequenceEndSplitLitBuffer():\n * This version is intended to be used during instances where the litBuffer is still split.  It is kept separate to avoid performance impact for the good case.\n */\nFORCE_NOINLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op,\n    BYTE* const oend, const BYTE* const oend_w, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n\n    /* bounds checks : careful of address space overflow in 32-bit mode */\n    RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, \"last match must fit within dstBuffer\");\n    RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, \"try to read beyond literal buffer\");\n    assert(op < op + sequenceLength);\n    assert(oLitEnd < op + sequenceLength);\n\n    /* copy literals */\n    RETURN_ERROR_IF(op > *litPtr && op < *litPtr + sequence.litLength, dstSize_tooSmall, \"output should not catch up to and overwrite literal buffer\");\n    ZSTD_safecopyDstBeforeSrc(op, *litPtr, sequence.litLength);\n    op = oLitEnd;\n    *litPtr = iLitEnd;\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix */\n        RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, \"\");\n        match = dictEnd - (prefixStart - match);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = dictEnd - match;\n        ZSTD_memmove(oLitEnd, match, length1);\n        op = oLitEnd + length1;\n        sequence.matchLength -= length1;\n        match = prefixStart;\n        }\n    }\n    ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);\n    return sequenceLength;\n}\n\nHINT_INLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequence(BYTE* op,\n    BYTE* const oend, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_w = oend - WILDCOPY_OVERLENGTH;   /* risk : address space underflow on oend=NULL */\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    assert(op != NULL /* Precondition */);\n    assert(oend_w < oend /* No underflow */);\n\n#if defined(__aarch64__)\n    /* prefetch sequence starting from match that will be used for copy later */\n    PREFETCH_L1(match);\n#endif\n    /* Handle edge cases in a slow path:\n     *   - Read beyond end of literals\n     *   - Match end is within WILDCOPY_OVERLIMIT of oend\n     *   - 32-bit mode and the match length overflows\n     */\n    if (UNLIKELY(\n        iLitEnd > litLimit ||\n        oMatchEnd > oend_w ||\n        (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))\n        return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);\n\n    /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */\n    assert(op <= oLitEnd /* No overflow */);\n    assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);\n    assert(oMatchEnd <= oend /* No underflow */);\n    assert(iLitEnd <= litLimit /* Literal length is in bounds */);\n    assert(oLitEnd <= oend_w /* Can wildcopy literals */);\n    assert(oMatchEnd <= oend_w /* Can wildcopy matches */);\n\n    /* Copy Literals:\n     * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.\n     * We likely don't need the full 32-byte wildcopy.\n     */\n    assert(WILDCOPY_OVERLENGTH >= 16);\n    ZSTD_copy16(op, (*litPtr));\n    if (UNLIKELY(sequence.litLength > 16)) {\n        ZSTD_wildcopy(op + 16, (*litPtr) + 16, sequence.litLength - 16, ZSTD_no_overlap);\n    }\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* Copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix -> go into extDict */\n        RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, \"\");\n        match = dictEnd + (match - prefixStart);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = dictEnd - match;\n        ZSTD_memmove(oLitEnd, match, length1);\n        op = oLitEnd + length1;\n        sequence.matchLength -= length1;\n        match = prefixStart;\n        }\n    }\n    /* Match within prefix of 1 or more bytes */\n    assert(op <= oMatchEnd);\n    assert(oMatchEnd <= oend_w);\n    assert(match >= prefixStart);\n    assert(sequence.matchLength >= 1);\n\n    /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy\n     * without overlap checking.\n     */\n    if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {\n        /* We bet on a full wildcopy for matches, since we expect matches to be\n         * longer than literals (in general). In silesia, ~10% of matches are longer\n         * than 16 bytes.\n         */\n        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);\n        return sequenceLength;\n    }\n    assert(sequence.offset < WILDCOPY_VECLEN);\n\n    /* Copy 8 bytes and spread the offset to be >= 8. */\n    ZSTD_overlapCopy8(&op, &match, sequence.offset);\n\n    /* If the match length is > 8 bytes, then continue with the wildcopy. */\n    if (sequence.matchLength > 8) {\n        assert(op < oMatchEnd);\n        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8, ZSTD_overlap_src_before_dst);\n    }\n    return sequenceLength;\n}\n\nHINT_INLINE\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nsize_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,\n    BYTE* const oend, const BYTE* const oend_w, seq_t sequence,\n    const BYTE** litPtr, const BYTE* const litLimit,\n    const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    assert(op != NULL /* Precondition */);\n    assert(oend_w < oend /* No underflow */);\n    /* Handle edge cases in a slow path:\n     *   - Read beyond end of literals\n     *   - Match end is within WILDCOPY_OVERLIMIT of oend\n     *   - 32-bit mode and the match length overflows\n     */\n    if (UNLIKELY(\n            iLitEnd > litLimit ||\n            oMatchEnd > oend_w ||\n            (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))\n        return ZSTD_execSequenceEndSplitLitBuffer(op, oend, oend_w, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);\n\n    /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */\n    assert(op <= oLitEnd /* No overflow */);\n    assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);\n    assert(oMatchEnd <= oend /* No underflow */);\n    assert(iLitEnd <= litLimit /* Literal length is in bounds */);\n    assert(oLitEnd <= oend_w /* Can wildcopy literals */);\n    assert(oMatchEnd <= oend_w /* Can wildcopy matches */);\n\n    /* Copy Literals:\n     * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.\n     * We likely don't need the full 32-byte wildcopy.\n     */\n    assert(WILDCOPY_OVERLENGTH >= 16);\n    ZSTD_copy16(op, (*litPtr));\n    if (UNLIKELY(sequence.litLength > 16)) {\n        ZSTD_wildcopy(op+16, (*litPtr)+16, sequence.litLength-16, ZSTD_no_overlap);\n    }\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* Copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {\n        /* offset beyond prefix -> go into extDict */\n        RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, \"\");\n        match = dictEnd + (match - prefixStart);\n        if (match + sequence.matchLength <= dictEnd) {\n            ZSTD_memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = dictEnd - match;\n            ZSTD_memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = prefixStart;\n    }   }\n    /* Match within prefix of 1 or more bytes */\n    assert(op <= oMatchEnd);\n    assert(oMatchEnd <= oend_w);\n    assert(match >= prefixStart);\n    assert(sequence.matchLength >= 1);\n\n    /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy\n     * without overlap checking.\n     */\n    if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {\n        /* We bet on a full wildcopy for matches, since we expect matches to be\n         * longer than literals (in general). In silesia, ~10% of matches are longer\n         * than 16 bytes.\n         */\n        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);\n        return sequenceLength;\n    }\n    assert(sequence.offset < WILDCOPY_VECLEN);\n\n    /* Copy 8 bytes and spread the offset to be >= 8. */\n    ZSTD_overlapCopy8(&op, &match, sequence.offset);\n\n    /* If the match length is > 8 bytes, then continue with the wildcopy. */\n    if (sequence.matchLength > 8) {\n        assert(op < oMatchEnd);\n        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8, ZSTD_overlap_src_before_dst);\n    }\n    return sequenceLength;\n}\n\n\nstatic void\nZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)\n{\n    const void* ptr = dt;\n    const ZSTD_seqSymbol_header* const DTableH = (const ZSTD_seqSymbol_header*)ptr;\n    DStatePtr->state = BIT_readBits(bitD, DTableH->tableLog);\n    DEBUGLOG(6, \"ZSTD_initFseState : val=%u using %u bits\",\n                (U32)DStatePtr->state, DTableH->tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nFORCE_INLINE_TEMPLATE void\nZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, U16 nextState, U32 nbBits)\n{\n    size_t const lowBits = BIT_readBits(bitD, nbBits);\n    DStatePtr->state = nextState + lowBits;\n}\n\n/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum\n * offset bits. But we can only read at most STREAM_ACCUMULATOR_MIN_32\n * bits before reloading. This value is the maximum number of bytes we read\n * after reloading when we are decoding long offsets.\n */\n#define LONG_OFFSETS_MAX_EXTRA_BITS_32                       \\\n    (ZSTD_WINDOWLOG_MAX_32 > STREAM_ACCUMULATOR_MIN_32       \\\n        ? ZSTD_WINDOWLOG_MAX_32 - STREAM_ACCUMULATOR_MIN_32  \\\n        : 0)\n\ntypedef enum { ZSTD_lo_isRegularOffset, ZSTD_lo_isLongOffset=1 } ZSTD_longOffset_e;\n\n/**\n * ZSTD_decodeSequence():\n * @p longOffsets : tells the decoder to reload more bit while decoding large offsets\n *                  only used in 32-bit mode\n * @return : Sequence (litL + matchL + offset)\n */\nFORCE_INLINE_TEMPLATE seq_t\nZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, const int isLastSeq)\n{\n    seq_t seq;\n    /*\n     * ZSTD_seqSymbol is a 64 bits wide structure.\n     * It can be loaded in one operation\n     * and its fields extracted by simply shifting or bit-extracting on aarch64.\n     * GCC doesn't recognize this and generates more unnecessary ldr/ldrb/ldrh\n     * operations that cause performance drop. This can be avoided by using this\n     * ZSTD_memcpy hack.\n     */\n#if defined(__aarch64__) && (defined(__GNUC__) && !defined(__clang__))\n    ZSTD_seqSymbol llDInfoS, mlDInfoS, ofDInfoS;\n    ZSTD_seqSymbol* const llDInfo = &llDInfoS;\n    ZSTD_seqSymbol* const mlDInfo = &mlDInfoS;\n    ZSTD_seqSymbol* const ofDInfo = &ofDInfoS;\n    ZSTD_memcpy(llDInfo, seqState->stateLL.table + seqState->stateLL.state, sizeof(ZSTD_seqSymbol));\n    ZSTD_memcpy(mlDInfo, seqState->stateML.table + seqState->stateML.state, sizeof(ZSTD_seqSymbol));\n    ZSTD_memcpy(ofDInfo, seqState->stateOffb.table + seqState->stateOffb.state, sizeof(ZSTD_seqSymbol));\n#else\n    const ZSTD_seqSymbol* const llDInfo = seqState->stateLL.table + seqState->stateLL.state;\n    const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state;\n    const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state;\n#endif\n    seq.matchLength = mlDInfo->baseValue;\n    seq.litLength = llDInfo->baseValue;\n    {   U32 const ofBase = ofDInfo->baseValue;\n        BYTE const llBits = llDInfo->nbAdditionalBits;\n        BYTE const mlBits = mlDInfo->nbAdditionalBits;\n        BYTE const ofBits = ofDInfo->nbAdditionalBits;\n        BYTE const totalBits = llBits+mlBits+ofBits;\n\n        U16 const llNext = llDInfo->nextState;\n        U16 const mlNext = mlDInfo->nextState;\n        U16 const ofNext = ofDInfo->nextState;\n        U32 const llnbBits = llDInfo->nbBits;\n        U32 const mlnbBits = mlDInfo->nbBits;\n        U32 const ofnbBits = ofDInfo->nbBits;\n\n        assert(llBits <= MaxLLBits);\n        assert(mlBits <= MaxMLBits);\n        assert(ofBits <= MaxOff);\n        /*\n         * As gcc has better branch and block analyzers, sometimes it is only\n         * valuable to mark likeliness for clang, it gives around 3-4% of\n         * performance.\n         */\n\n        /* sequence */\n        {   size_t offset;\n            if (ofBits > 1) {\n                ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);\n                ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);\n                ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 > LONG_OFFSETS_MAX_EXTRA_BITS_32);\n                ZSTD_STATIC_ASSERT(STREAM_ACCUMULATOR_MIN_32 - LONG_OFFSETS_MAX_EXTRA_BITS_32 >= MaxMLBits);\n                if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {\n                    /* Always read extra bits, this keeps the logic simple,\n                     * avoids branches, and avoids accidentally reading 0 bits.\n                     */\n                    U32 const extraBits = LONG_OFFSETS_MAX_EXTRA_BITS_32;\n                    offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);\n                    BIT_reloadDStream(&seqState->DStream);\n                    offset += BIT_readBitsFast(&seqState->DStream, extraBits);\n                } else {\n                    offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/);   /* <=  (ZSTD_WINDOWLOG_MAX-1) bits */\n                    if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);\n                }\n                seqState->prevOffset[2] = seqState->prevOffset[1];\n                seqState->prevOffset[1] = seqState->prevOffset[0];\n                seqState->prevOffset[0] = offset;\n            } else {\n                U32 const ll0 = (llDInfo->baseValue == 0);\n                if (LIKELY((ofBits == 0))) {\n                    offset = seqState->prevOffset[ll0];\n                    seqState->prevOffset[1] = seqState->prevOffset[!ll0];\n                    seqState->prevOffset[0] = offset;\n                } else {\n                    offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);\n                    {   size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];\n                        temp -= !temp; /* 0 is not valid: input corrupted => force offset to -1 => corruption detected at execSequence */\n                        if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];\n                        seqState->prevOffset[1] = seqState->prevOffset[0];\n                        seqState->prevOffset[0] = offset = temp;\n            }   }   }\n            seq.offset = offset;\n        }\n\n        if (mlBits > 0)\n            seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);\n\n        if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))\n            BIT_reloadDStream(&seqState->DStream);\n        if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))\n            BIT_reloadDStream(&seqState->DStream);\n        /* Ensure there are enough bits to read the rest of data in 64-bit mode. */\n        ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);\n\n        if (llBits > 0)\n            seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);\n\n        if (MEM_32bits())\n            BIT_reloadDStream(&seqState->DStream);\n\n        DEBUGLOG(6, \"seq: litL=%u, matchL=%u, offset=%u\",\n                    (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);\n\n        if (!isLastSeq) {\n            /* don't update FSE state for last Sequence */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits);    /* <=  9 bits */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits);    /* <=  9 bits */\n            if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);    /* <= 18 bits */\n            ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofNext, ofnbBits);  /* <=  8 bits */\n            BIT_reloadDStream(&seqState->DStream);\n        }\n    }\n\n    return seq;\n}\n\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n#if DEBUGLEVEL >= 1\nstatic int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd)\n{\n    size_t const windowSize = dctx->fParams.windowSize;\n    /* No dictionary used. */\n    if (dctx->dictContentEndForFuzzing == NULL) return 0;\n    /* Dictionary is our prefix. */\n    if (prefixStart == dctx->dictContentBeginForFuzzing) return 1;\n    /* Dictionary is not our ext-dict. */\n    if (dctx->dictEnd != dctx->dictContentEndForFuzzing) return 0;\n    /* Dictionary is not within our window size. */\n    if ((size_t)(oLitEnd - prefixStart) >= windowSize) return 0;\n    /* Dictionary is active. */\n    return 1;\n}\n#endif\n\nstatic void ZSTD_assertValidSequence(\n        ZSTD_DCtx const* dctx,\n        BYTE const* op, BYTE const* oend,\n        seq_t const seq,\n        BYTE const* prefixStart, BYTE const* virtualStart)\n{\n#if DEBUGLEVEL >= 1\n    if (dctx->isFrameDecompression) {\n        size_t const windowSize = dctx->fParams.windowSize;\n        size_t const sequenceSize = seq.litLength + seq.matchLength;\n        BYTE const* const oLitEnd = op + seq.litLength;\n        DEBUGLOG(6, \"Checking sequence: litL=%u matchL=%u offset=%u\",\n                (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);\n        assert(op <= oend);\n        assert((size_t)(oend - op) >= sequenceSize);\n        assert(sequenceSize <= ZSTD_blockSizeMax(dctx));\n        if (ZSTD_dictionaryIsActive(dctx, prefixStart, oLitEnd)) {\n            size_t const dictSize = (size_t)((char const*)dctx->dictContentEndForFuzzing - (char const*)dctx->dictContentBeginForFuzzing);\n            /* Offset must be within the dictionary. */\n            assert(seq.offset <= (size_t)(oLitEnd - virtualStart));\n            assert(seq.offset <= windowSize + dictSize);\n        } else {\n            /* Offset must be within our window. */\n            assert(seq.offset <= windowSize);\n        }\n    }\n#else\n    (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart;\n#endif\n}\n#endif\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\n\n\nFORCE_INLINE_TEMPLATE size_t\nDONT_VECTORIZE\nZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize, int nbSeq,\n                         const ZSTD_longOffset_e isLongOffset)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ZSTD_maybeNullPtrAdd(ostart, maxDstSize);\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* litBufferEnd = dctx->litBufferEnd;\n    const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);\n    const BYTE* const vBase = (const BYTE*) (dctx->virtualStart);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n    DEBUGLOG(5, \"ZSTD_decompressSequences_bodySplitLitBuffer (%i seqs)\", nbSeq);\n\n    /* Literals are split between internal buffer & output buffer */\n    if (nbSeq) {\n        seqState_t seqState;\n        dctx->fseEntropy = 1;\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }\n        RETURN_ERROR_IF(\n            ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),\n            corruption_detected, \"\");\n        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);\n        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);\n        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);\n        assert(dst != NULL);\n\n        ZSTD_STATIC_ASSERT(\n                BIT_DStream_unfinished < BIT_DStream_completed &&\n                BIT_DStream_endOfBuffer < BIT_DStream_completed &&\n                BIT_DStream_completed < BIT_DStream_overflow);\n\n        /* decompress without overrunning litPtr begins */\n        {   seq_t sequence = {0,0,0};  /* some static analyzer believe that @sequence is not initialized (it necessarily is, since for(;;) loop as at least one iteration) */\n            /* Align the decompression loop to 32 + 16 bytes.\n                *\n                * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression\n                * speed swings based on the alignment of the decompression loop. This\n                * performance swing is caused by parts of the decompression loop falling\n                * out of the DSB. The entire decompression loop should fit in the DSB,\n                * when it can't we get much worse performance. You can measure if you've\n                * hit the good case or the bad case with this perf command for some\n                * compressed file test.zst:\n                *\n                *   perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \\\n                *             -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst\n                *\n                * If you see most cycles served out of the MITE you've hit the bad case.\n                * If you see most cycles served out of the DSB you've hit the good case.\n                * If it is pretty even then you may be in an okay case.\n                *\n                * This issue has been reproduced on the following CPUs:\n                *   - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9\n                *               Use Instruments->Counters to get DSB/MITE cycles.\n                *               I never got performance swings, but I was able to\n                *               go from the good case of mostly DSB to half of the\n                *               cycles served from MITE.\n                *   - Coffeelake: Intel i9-9900k\n                *   - Coffeelake: Intel i7-9700k\n                *\n                * I haven't been able to reproduce the instability or DSB misses on any\n                * of the following CPUS:\n                *   - Haswell\n                *   - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH\n                *   - Skylake\n                *\n                * Alignment is done for each of the three major decompression loops:\n                *   - ZSTD_decompressSequences_bodySplitLitBuffer - presplit section of the literal buffer\n                *   - ZSTD_decompressSequences_bodySplitLitBuffer - postsplit section of the literal buffer\n                *   - ZSTD_decompressSequences_body\n                * Alignment choices are made to minimize large swings on bad cases and influence on performance\n                * from changes external to this code, rather than to overoptimize on the current commit.\n                *\n                * If you are seeing performance stability this script can help test.\n                * It tests on 4 commits in zstd where I saw performance change.\n                *\n                *   https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4\n                */\n#if defined(__GNUC__) && defined(__x86_64__)\n            __asm__(\".p2align 6\");\n#  if __GNUC__ >= 7\n\t    /* good for gcc-7, gcc-9, and gcc-11 */\n            __asm__(\"nop\");\n            __asm__(\".p2align 5\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 4\");\n#    if __GNUC__ == 8 || __GNUC__ == 10\n\t    /* good for gcc-8 and gcc-10 */\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#    endif\n#  endif\n#endif\n\n            /* Handle the initial state where litBuffer is currently split between dst and litExtraBuffer */\n            for ( ; nbSeq; nbSeq--) {\n                sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1);\n                if (litPtr + sequence.litLength > dctx->litBufferEnd) break;\n                {   size_t const oneSeqSize = ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence.litLength - WILDCOPY_OVERLENGTH, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n                    if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                        return oneSeqSize;\n                    DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n                    op += oneSeqSize;\n            }   }\n            DEBUGLOG(6, \"reached: (litPtr + sequence.litLength > dctx->litBufferEnd)\");\n\n            /* If there are more sequences, they will need to read literals from litExtraBuffer; copy over the remainder from dst and update litPtr and litEnd */\n            if (nbSeq > 0) {\n                const size_t leftoverLit = dctx->litBufferEnd - litPtr;\n                DEBUGLOG(6, \"There are %i sequences left, and %zu/%zu literals left in buffer\", nbSeq, leftoverLit, sequence.litLength);\n                if (leftoverLit) {\n                    RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, \"remaining lit must fit within dstBuffer\");\n                    ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);\n                    sequence.litLength -= leftoverLit;\n                    op += leftoverLit;\n                }\n                litPtr = dctx->litExtraBuffer;\n                litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                {   size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n                    if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                        return oneSeqSize;\n                    DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n                    op += oneSeqSize;\n                }\n                nbSeq--;\n            }\n        }\n\n        if (nbSeq > 0) {\n            /* there is remaining lit from extra buffer */\n\n#if defined(__GNUC__) && defined(__x86_64__)\n            __asm__(\".p2align 6\");\n            __asm__(\"nop\");\n#  if __GNUC__ != 7\n            /* worse for gcc-7 better for gcc-8, gcc-9, and gcc-10 and clang */\n            __asm__(\".p2align 4\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  elif __GNUC__ >= 11\n            __asm__(\".p2align 3\");\n#  else\n            __asm__(\".p2align 5\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  endif\n#endif\n\n            for ( ; nbSeq ; nbSeq--) {\n                seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1);\n                size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                assert(!ZSTD_isError(oneSeqSize));\n                ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n                if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                    return oneSeqSize;\n                DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n                op += oneSeqSize;\n            }\n        }\n\n        /* check if reached exact end */\n        DEBUGLOG(5, \"ZSTD_decompressSequences_bodySplitLitBuffer: after decode loop, remaining nbSeq : %i\", nbSeq);\n        RETURN_ERROR_IF(nbSeq, corruption_detected, \"\");\n        DEBUGLOG(5, \"bitStream : start=%p, ptr=%p, bitsConsumed=%u\", seqState.DStream.start, seqState.DStream.ptr, seqState.DStream.bitsConsumed);\n        RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, \"\");\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    if (dctx->litBufferLocation == ZSTD_split) {\n        /* split hasn't been reached yet, first get dst then copy litExtraBuffer */\n        size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);\n        DEBUGLOG(6, \"copy last literals from segment : %u\", (U32)lastLLSize);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memmove(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n        litPtr = dctx->litExtraBuffer;\n        litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n        dctx->litBufferLocation = ZSTD_not_in_dst;\n    }\n    /* copy last literals from internal buffer */\n    {   size_t const lastLLSize = (size_t)(litBufferEnd - litPtr);\n        DEBUGLOG(6, \"copy last literals from internal buffer : %u\", (U32)lastLLSize);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n    }   }\n\n    DEBUGLOG(6, \"decoded block of size %u bytes\", (U32)(op - ostart));\n    return (size_t)(op - ostart);\n}\n\nFORCE_INLINE_TEMPLATE size_t\nDONT_VECTORIZE\nZSTD_decompressSequences_body(ZSTD_DCtx* dctx,\n    void* dst, size_t maxDstSize,\n    const void* seqStart, size_t seqSize, int nbSeq,\n    const ZSTD_longOffset_e isLongOffset)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = dctx->litBufferLocation == ZSTD_not_in_dst ? ZSTD_maybeNullPtrAdd(ostart, maxDstSize) : dctx->litBuffer;\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    const BYTE* const prefixStart = (const BYTE*)(dctx->prefixStart);\n    const BYTE* const vBase = (const BYTE*)(dctx->virtualStart);\n    const BYTE* const dictEnd = (const BYTE*)(dctx->dictEnd);\n    DEBUGLOG(5, \"ZSTD_decompressSequences_body: nbSeq = %d\", nbSeq);\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seqState_t seqState;\n        dctx->fseEntropy = 1;\n        { U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }\n        RETURN_ERROR_IF(\n            ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend - ip)),\n            corruption_detected, \"\");\n        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);\n        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);\n        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);\n        assert(dst != NULL);\n\n#if defined(__GNUC__) && defined(__x86_64__)\n            __asm__(\".p2align 6\");\n            __asm__(\"nop\");\n#  if __GNUC__ >= 7\n            __asm__(\".p2align 5\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  else\n            __asm__(\".p2align 4\");\n            __asm__(\"nop\");\n            __asm__(\".p2align 3\");\n#  endif\n#endif\n\n        for ( ; nbSeq ; nbSeq--) {\n            seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, nbSeq==1);\n            size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n            assert(!ZSTD_isError(oneSeqSize));\n            ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);\n#endif\n            if (UNLIKELY(ZSTD_isError(oneSeqSize)))\n                return oneSeqSize;\n            DEBUGLOG(6, \"regenerated sequence size : %u\", (U32)oneSeqSize);\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        assert(nbSeq == 0);\n        RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, \"\");\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    {   size_t const lastLLSize = (size_t)(litEnd - litPtr);\n        DEBUGLOG(6, \"copy last literals : %u\", (U32)lastLLSize);\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n    }   }\n\n    DEBUGLOG(6, \"decoded block of size %u bytes\", (U32)(op - ostart));\n    return (size_t)(op - ostart);\n}\n\nstatic size_t\nZSTD_decompressSequences_default(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n\nstatic size_t\nZSTD_decompressSequencesSplitLitBuffer_default(ZSTD_DCtx* dctx,\n                                               void* dst, size_t maxDstSize,\n                                         const void* seqStart, size_t seqSize, int nbSeq,\n                                         const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\n\nFORCE_INLINE_TEMPLATE\n\nsize_t ZSTD_prefetchMatch(size_t prefetchPos, seq_t const sequence,\n                   const BYTE* const prefixStart, const BYTE* const dictEnd)\n{\n    prefetchPos += sequence.litLength;\n    {   const BYTE* const matchBase = (sequence.offset > prefetchPos) ? dictEnd : prefixStart;\n        /* note : this operation can overflow when seq.offset is really too large, which can only happen when input is corrupted.\n         * No consequence though : memory address is only used for prefetching, not for dereferencing */\n        const BYTE* const match = ZSTD_wrappedPtrSub(ZSTD_wrappedPtrAdd(matchBase, prefetchPos), sequence.offset);\n        PREFETCH_L1(match); PREFETCH_L1(match+CACHELINE_SIZE);   /* note : it's safe to invoke PREFETCH() on any memory address, including invalid ones */\n    }\n    return prefetchPos + sequence.matchLength;\n}\n\n/* This decoding function employs prefetching\n * to reduce latency impact of cache misses.\n * It's generally employed when block contains a significant portion of long-distance matches\n * or when coupled with a \"cold\" dictionary */\nFORCE_INLINE_TEMPLATE size_t\nZSTD_decompressSequencesLong_body(\n                               ZSTD_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize, int nbSeq,\n                         const ZSTD_longOffset_e isLongOffset)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = dctx->litBufferLocation == ZSTD_in_dst ? dctx->litBuffer : ZSTD_maybeNullPtrAdd(ostart, maxDstSize);\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* litBufferEnd = dctx->litBufferEnd;\n    const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);\n    const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n\n    /* Regen sequences */\n    if (nbSeq) {\n#define STORED_SEQS 8\n#define STORED_SEQS_MASK (STORED_SEQS-1)\n#define ADVANCED_SEQS STORED_SEQS\n        seq_t sequences[STORED_SEQS];\n        int const seqAdvance = MIN(nbSeq, ADVANCED_SEQS);\n        seqState_t seqState;\n        int seqNb;\n        size_t prefetchPos = (size_t)(op-prefixStart); /* track position relative to prefixStart */\n\n        dctx->fseEntropy = 1;\n        { int i; for (i=0; i<ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }\n        assert(dst != NULL);\n        assert(iend >= ip);\n        RETURN_ERROR_IF(\n            ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend-ip)),\n            corruption_detected, \"\");\n        ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);\n        ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);\n        ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);\n\n        /* prepare in advance */\n        for (seqNb=0; seqNb<seqAdvance; seqNb++) {\n            seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset, seqNb == nbSeq-1);\n            prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);\n            sequences[seqNb] = sequence;\n        }\n\n        /* decompress without stomping litBuffer */\n        for (; seqNb < nbSeq; seqNb++) {\n            seq_t sequence = ZSTD_decodeSequence(&seqState, isLongOffset, seqNb == nbSeq-1);\n\n            if (dctx->litBufferLocation == ZSTD_split && litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength > dctx->litBufferEnd) {\n                /* lit buffer is reaching split point, empty out the first buffer and transition to litExtraBuffer */\n                const size_t leftoverLit = dctx->litBufferEnd - litPtr;\n                if (leftoverLit)\n                {\n                    RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, \"remaining lit must fit within dstBuffer\");\n                    ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);\n                    sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength -= leftoverLit;\n                    op += leftoverLit;\n                }\n                litPtr = dctx->litExtraBuffer;\n                litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                {   size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                    if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n\n                    prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);\n                    sequences[seqNb & STORED_SEQS_MASK] = sequence;\n                    op += oneSeqSize;\n            }   }\n            else\n            {\n                /* lit buffer is either wholly contained in first or second split, or not split at all*/\n                size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ?\n                    ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength - WILDCOPY_OVERLENGTH, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :\n                    ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                assert(!ZSTD_isError(oneSeqSize));\n                ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n\n                prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);\n                sequences[seqNb & STORED_SEQS_MASK] = sequence;\n                op += oneSeqSize;\n            }\n        }\n        RETURN_ERROR_IF(!BIT_endOfDStream(&seqState.DStream), corruption_detected, \"\");\n\n        /* finish queue */\n        seqNb -= seqAdvance;\n        for ( ; seqNb<nbSeq ; seqNb++) {\n            seq_t *sequence = &(sequences[seqNb&STORED_SEQS_MASK]);\n            if (dctx->litBufferLocation == ZSTD_split && litPtr + sequence->litLength > dctx->litBufferEnd) {\n                const size_t leftoverLit = dctx->litBufferEnd - litPtr;\n                if (leftoverLit) {\n                    RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, \"remaining lit must fit within dstBuffer\");\n                    ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);\n                    sequence->litLength -= leftoverLit;\n                    op += leftoverLit;\n                }\n                litPtr = dctx->litExtraBuffer;\n                litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n                dctx->litBufferLocation = ZSTD_not_in_dst;\n                {   size_t const oneSeqSize = ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                    assert(!ZSTD_isError(oneSeqSize));\n                    ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                    if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n                    op += oneSeqSize;\n                }\n            }\n            else\n            {\n                size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ?\n                    ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence->litLength - WILDCOPY_OVERLENGTH, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :\n                    ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);\n#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)\n                assert(!ZSTD_isError(oneSeqSize));\n                ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);\n#endif\n                if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n                op += oneSeqSize;\n            }\n        }\n\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    if (dctx->litBufferLocation == ZSTD_split) { /* first deplete literal buffer in dst, then copy litExtraBuffer */\n        size_t const lastLLSize = litBufferEnd - litPtr;\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memmove(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n        litPtr = dctx->litExtraBuffer;\n        litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;\n    }\n    {   size_t const lastLLSize = litBufferEnd - litPtr;\n        RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, \"\");\n        if (op != NULL) {\n            ZSTD_memmove(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return (size_t)(op - ostart);\n}\n\nstatic size_t\nZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */\n\n\n\n#if DYNAMIC_BMI2\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\nstatic BMI2_TARGET_ATTRIBUTE size_t\nDONT_VECTORIZE\nZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\nstatic BMI2_TARGET_ATTRIBUTE size_t\nDONT_VECTORIZE\nZSTD_decompressSequencesSplitLitBuffer_bmi2(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\nstatic BMI2_TARGET_ATTRIBUTE size_t\nZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                           const void* seqStart, size_t seqSize, int nbSeq,\n                           const ZSTD_longOffset_e isLongOffset)\n{\n    return ZSTD_decompressSequencesLong_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */\n\n#endif /* DYNAMIC_BMI2 */\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\nstatic size_t\nZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,\n                   const void* seqStart, size_t seqSize, int nbSeq,\n                   const ZSTD_longOffset_e isLongOffset)\n{\n    DEBUGLOG(5, \"ZSTD_decompressSequences\");\n#if DYNAMIC_BMI2\n    if (ZSTD_DCtx_get_bmi2(dctx)) {\n        return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n    }\n#endif\n    return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\nstatic size_t\nZSTD_decompressSequencesSplitLitBuffer(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,\n                                 const void* seqStart, size_t seqSize, int nbSeq,\n                                 const ZSTD_longOffset_e isLongOffset)\n{\n    DEBUGLOG(5, \"ZSTD_decompressSequencesSplitLitBuffer\");\n#if DYNAMIC_BMI2\n    if (ZSTD_DCtx_get_bmi2(dctx)) {\n        return ZSTD_decompressSequencesSplitLitBuffer_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n    }\n#endif\n    return ZSTD_decompressSequencesSplitLitBuffer_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */\n\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\n/* ZSTD_decompressSequencesLong() :\n * decompression function triggered when a minimum share of offsets is considered \"long\",\n * aka out of cache.\n * note : \"long\" definition seems overloaded here, sometimes meaning \"wider than bitstream register\", and sometimes meaning \"farther than memory cache distance\".\n * This function will try to mitigate main memory latency through the use of prefetching */\nstatic size_t\nZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,\n                             void* dst, size_t maxDstSize,\n                             const void* seqStart, size_t seqSize, int nbSeq,\n                             const ZSTD_longOffset_e isLongOffset)\n{\n    DEBUGLOG(5, \"ZSTD_decompressSequencesLong\");\n#if DYNAMIC_BMI2\n    if (ZSTD_DCtx_get_bmi2(dctx)) {\n        return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n    }\n#endif\n  return ZSTD_decompressSequencesLong_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset);\n}\n#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT */\n\n\n/**\n * @returns The total size of the history referenceable by zstd, including\n * both the prefix and the extDict. At @p op any offset larger than this\n * is invalid.\n */\nstatic size_t ZSTD_totalHistorySize(BYTE* op, BYTE const* virtualStart)\n{\n    return (size_t)(op - virtualStart);\n}\n\ntypedef struct {\n    unsigned longOffsetShare;\n    unsigned maxNbAdditionalBits;\n} ZSTD_OffsetInfo;\n\n/* ZSTD_getOffsetInfo() :\n * condition : offTable must be valid\n * @return : \"share\" of long offsets (arbitrarily defined as > (1<<23))\n *           compared to maximum possible of (1<<OffFSELog),\n *           as well as the maximum number additional bits required.\n */\nstatic ZSTD_OffsetInfo\nZSTD_getOffsetInfo(const ZSTD_seqSymbol* offTable, int nbSeq)\n{\n    ZSTD_OffsetInfo info = {0, 0};\n    /* If nbSeq == 0, then the offTable is uninitialized, but we have\n     * no sequences, so both values should be 0.\n     */\n    if (nbSeq != 0) {\n        const void* ptr = offTable;\n        U32 const tableLog = ((const ZSTD_seqSymbol_header*)ptr)[0].tableLog;\n        const ZSTD_seqSymbol* table = offTable + 1;\n        U32 const max = 1 << tableLog;\n        U32 u;\n        DEBUGLOG(5, \"ZSTD_getLongOffsetsShare: (tableLog=%u)\", tableLog);\n\n        assert(max <= (1 << OffFSELog));  /* max not too large */\n        for (u=0; u<max; u++) {\n            info.maxNbAdditionalBits = MAX(info.maxNbAdditionalBits, table[u].nbAdditionalBits);\n            if (table[u].nbAdditionalBits > 22) info.longOffsetShare += 1;\n        }\n\n        assert(tableLog <= OffFSELog);\n        info.longOffsetShare <<= (OffFSELog - tableLog);  /* scale to OffFSELog */\n    }\n\n    return info;\n}\n\n/**\n * @returns The maximum offset we can decode in one read of our bitstream, without\n * reloading more bits in the middle of the offset bits read. Any offsets larger\n * than this must use the long offset decoder.\n */\nstatic size_t ZSTD_maxShortOffset(void)\n{\n    if (MEM_64bits()) {\n        /* We can decode any offset without reloading bits.\n         * This might change if the max window size grows.\n         */\n        ZSTD_STATIC_ASSERT(ZSTD_WINDOWLOG_MAX <= 31);\n        return (size_t)-1;\n    } else {\n        /* The maximum offBase is (1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1.\n         * This offBase would require STREAM_ACCUMULATOR_MIN extra bits.\n         * Then we have to subtract ZSTD_REP_NUM to get the maximum possible offset.\n         */\n        size_t const maxOffbase = ((size_t)1 << (STREAM_ACCUMULATOR_MIN + 1)) - 1;\n        size_t const maxOffset = maxOffbase - ZSTD_REP_NUM;\n        assert(ZSTD_highbit32((U32)maxOffbase) == STREAM_ACCUMULATOR_MIN);\n        return maxOffset;\n    }\n}\n\nsize_t\nZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,\n                              void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize, const streaming_operation streaming)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n    DEBUGLOG(5, \"ZSTD_decompressBlock_internal (cSize : %u)\", (unsigned)srcSize);\n\n    /* Note : the wording of the specification\n     * allows compressed block to be sized exactly ZSTD_blockSizeMax(dctx).\n     * This generally does not happen, as it makes little sense,\n     * since an uncompressed block would feature same size and have no decompression cost.\n     * Also, note that decoder from reference libzstd before < v1.5.4\n     * would consider this edge case as an error.\n     * As a consequence, avoid generating compressed blocks of size ZSTD_blockSizeMax(dctx)\n     * for broader compatibility with the deployed ecosystem of zstd decoders */\n    RETURN_ERROR_IF(srcSize > ZSTD_blockSizeMax(dctx), srcSize_wrong, \"\");\n\n    /* Decode literals section */\n    {   size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, streaming);\n        DEBUGLOG(5, \"ZSTD_decodeLiteralsBlock : cSize=%u, nbLiterals=%zu\", (U32)litCSize, dctx->litSize);\n        if (ZSTD_isError(litCSize)) return litCSize;\n        ip += litCSize;\n        srcSize -= litCSize;\n    }\n\n    /* Build Decoding Tables */\n    {\n        /* Compute the maximum block size, which must also work when !frame and fParams are unset.\n         * Additionally, take the min with dstCapacity to ensure that the totalHistorySize fits in a size_t.\n         */\n        size_t const blockSizeMax = MIN(dstCapacity, ZSTD_blockSizeMax(dctx));\n        size_t const totalHistorySize = ZSTD_totalHistorySize(ZSTD_maybeNullPtrAdd((BYTE*)dst, blockSizeMax), (BYTE const*)dctx->virtualStart);\n        /* isLongOffset must be true if there are long offsets.\n         * Offsets are long if they are larger than ZSTD_maxShortOffset().\n         * We don't expect that to be the case in 64-bit mode.\n         *\n         * We check here to see if our history is large enough to allow long offsets.\n         * If it isn't, then we can't possible have (valid) long offsets. If the offset\n         * is invalid, then it is okay to read it incorrectly.\n         *\n         * If isLongOffsets is true, then we will later check our decoding table to see\n         * if it is even possible to generate long offsets.\n         */\n        ZSTD_longOffset_e isLongOffset = (ZSTD_longOffset_e)(MEM_32bits() && (totalHistorySize > ZSTD_maxShortOffset()));\n        /* These macros control at build-time which decompressor implementation\n         * we use. If neither is defined, we do some inspection and dispatch at\n         * runtime.\n         */\n#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \\\n    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)\n        int usePrefetchDecoder = dctx->ddictIsCold;\n#else\n        /* Set to 1 to avoid computing offset info if we don't need to.\n         * Otherwise this value is ignored.\n         */\n        int usePrefetchDecoder = 1;\n#endif\n        int nbSeq;\n        size_t const seqHSize = ZSTD_decodeSeqHeaders(dctx, &nbSeq, ip, srcSize);\n        if (ZSTD_isError(seqHSize)) return seqHSize;\n        ip += seqHSize;\n        srcSize -= seqHSize;\n\n        RETURN_ERROR_IF((dst == NULL || dstCapacity == 0) && nbSeq > 0, dstSize_tooSmall, \"NULL not handled\");\n        RETURN_ERROR_IF(MEM_64bits() && sizeof(size_t) == sizeof(void*) && (size_t)(-1) - (size_t)dst < (size_t)(1 << 20), dstSize_tooSmall,\n                \"invalid dst\");\n\n        /* If we could potentially have long offsets, or we might want to use the prefetch decoder,\n         * compute information about the share of long offsets, and the maximum nbAdditionalBits.\n         * NOTE: could probably use a larger nbSeq limit\n         */\n        if (isLongOffset || (!usePrefetchDecoder && (totalHistorySize > (1u << 24)) && (nbSeq > 8))) {\n            ZSTD_OffsetInfo const info = ZSTD_getOffsetInfo(dctx->OFTptr, nbSeq);\n            if (isLongOffset && info.maxNbAdditionalBits <= STREAM_ACCUMULATOR_MIN) {\n                /* If isLongOffset, but the maximum number of additional bits that we see in our table is small\n                 * enough, then we know it is impossible to have too long an offset in this block, so we can\n                 * use the regular offset decoder.\n                 */\n                isLongOffset = ZSTD_lo_isRegularOffset;\n            }\n            if (!usePrefetchDecoder) {\n                U32 const minShare = MEM_64bits() ? 7 : 20; /* heuristic values, correspond to 2.73% and 7.81% */\n                usePrefetchDecoder = (info.longOffsetShare >= minShare);\n            }\n        }\n\n        dctx->ddictIsCold = 0;\n\n#if !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT) && \\\n    !defined(ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG)\n        if (usePrefetchDecoder) {\n#else\n        (void)usePrefetchDecoder;\n        {\n#endif\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT\n            return ZSTD_decompressSequencesLong(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);\n#endif\n        }\n\n#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG\n        /* else */\n        if (dctx->litBufferLocation == ZSTD_split)\n            return ZSTD_decompressSequencesSplitLitBuffer(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);\n        else\n            return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset);\n#endif\n    }\n}\n\n\nZSTD_ALLOW_POINTER_OVERFLOW_ATTR\nvoid ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize)\n{\n    if (dst != dctx->previousDstEnd && dstSize > 0) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->virtualStart = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->prefixStart));\n        dctx->prefixStart = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nsize_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx,\n                                       void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize)\n{\n    size_t dSize;\n    dctx->isFrameDecompression = 0;\n    ZSTD_checkContinuity(dctx, dst, dstCapacity);\n    dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, not_streaming);\n    FORWARD_IF_ERROR(dSize, \"\");\n    dctx->previousDstEnd = (char*)dst + dSize;\n    return dSize;\n}\n\n\n/* NOTE: Must just wrap ZSTD_decompressBlock_deprecated() */\nsize_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    return ZSTD_decompressBlock_deprecated(dctx, dst, dstCapacity, src, srcSize);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/decompress/zstd_decompress_block.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#ifndef ZSTD_DEC_BLOCK_H\n#define ZSTD_DEC_BLOCK_H\n\n/*-*******************************************************\n *  Dependencies\n *********************************************************/\n#include \"../common/zstd_deps.h\"   /* size_t */\n#include \"../zstd.h\"    /* DCtx, and some public functions */\n#include \"../common/zstd_internal.h\"  /* blockProperties_t, and some public functions */\n#include \"zstd_decompress_internal.h\"  /* ZSTD_seqSymbol */\n\n\n/* ===   Prototypes   === */\n\n/* note: prototypes already published within `zstd.h` :\n * ZSTD_decompressBlock()\n */\n\n/* note: prototypes already published within `zstd_internal.h` :\n * ZSTD_getcBlockSize()\n * ZSTD_decodeSeqHeaders()\n */\n\n\n /* Streaming state is used to inform allocation of the literal buffer */\ntypedef enum {\n    not_streaming = 0,\n    is_streaming = 1\n} streaming_operation;\n\n/* ZSTD_decompressBlock_internal() :\n * decompress block, starting at `src`,\n * into destination buffer `dst`.\n * @return : decompressed block size,\n *           or an error code (which can be tested using ZSTD_isError())\n */\nsize_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,\n                               void* dst, size_t dstCapacity,\n                         const void* src, size_t srcSize, const streaming_operation streaming);\n\n/* ZSTD_buildFSETable() :\n * generate FSE decoding table for one symbol (ll, ml or off)\n * this function must be called with valid parameters only\n * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.)\n * in which case it cannot fail.\n * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is\n * defined in zstd_decompress_internal.h.\n * Internal use only.\n */\nvoid ZSTD_buildFSETable(ZSTD_seqSymbol* dt,\n             const short* normalizedCounter, unsigned maxSymbolValue,\n             const U32* baseValue, const U8* nbAdditionalBits,\n                   unsigned tableLog, void* wksp, size_t wkspSize,\n                   int bmi2);\n\n/* Internal definition of ZSTD_decompressBlock() to avoid deprecation warnings. */\nsize_t ZSTD_decompressBlock_deprecated(ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize);\n\n\n#endif /* ZSTD_DEC_BLOCK_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/decompress/zstd_decompress_internal.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/* zstd_decompress_internal:\n * objects and definitions shared within lib/decompress modules */\n\n #ifndef ZSTD_DECOMPRESS_INTERNAL_H\n #define ZSTD_DECOMPRESS_INTERNAL_H\n\n\n/*-*******************************************************\n *  Dependencies\n *********************************************************/\n#include \"../common/mem.h\"             /* BYTE, U16, U32 */\n#include \"../common/zstd_internal.h\"   /* constants : MaxLL, MaxML, MaxOff, LLFSELog, etc. */\n\n\n\n/*-*******************************************************\n *  Constants\n *********************************************************/\nstatic UNUSED_ATTR const U32 LL_base[MaxLL+1] = {\n                 0,    1,    2,     3,     4,     5,     6,      7,\n                 8,    9,   10,    11,    12,    13,    14,     15,\n                16,   18,   20,    22,    24,    28,    32,     40,\n                48,   64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,\n                0x2000, 0x4000, 0x8000, 0x10000 };\n\nstatic UNUSED_ATTR const U32 OF_base[MaxOff+1] = {\n                 0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,\n                 0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,\n                 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,\n                 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };\n\nstatic UNUSED_ATTR const U8 OF_bits[MaxOff+1] = {\n                     0,  1,  2,  3,  4,  5,  6,  7,\n                     8,  9, 10, 11, 12, 13, 14, 15,\n                    16, 17, 18, 19, 20, 21, 22, 23,\n                    24, 25, 26, 27, 28, 29, 30, 31 };\n\nstatic UNUSED_ATTR const U32 ML_base[MaxML+1] = {\n                     3,  4,  5,    6,     7,     8,     9,    10,\n                    11, 12, 13,   14,    15,    16,    17,    18,\n                    19, 20, 21,   22,    23,    24,    25,    26,\n                    27, 28, 29,   30,    31,    32,    33,    34,\n                    35, 37, 39,   41,    43,    47,    51,    59,\n                    67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,\n                    0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };\n\n\n/*-*******************************************************\n *  Decompression types\n *********************************************************/\n typedef struct {\n     U32 fastMode;\n     U32 tableLog;\n } ZSTD_seqSymbol_header;\n\n typedef struct {\n     U16  nextState;\n     BYTE nbAdditionalBits;\n     BYTE nbBits;\n     U32  baseValue;\n } ZSTD_seqSymbol;\n\n #define SEQSYMBOL_TABLE_SIZE(log)   (1 + (1 << (log)))\n\n#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64))\n#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32))\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\n\ntypedef struct {\n    ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)];    /* Note : Space reserved for FSE Tables */\n    ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)];   /* is also used as temporary workspace while building hufTable during DDict creation */\n    ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)];    /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */\n    HUF_DTable hufTable[HUF_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];  /* can accommodate HUF_decompress4X */\n    U32 rep[ZSTD_REP_NUM];\n    U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32];\n} ZSTD_entropyDTables_t;\n\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,\n               ZSTDds_decompressLastBlock, ZSTDds_checkChecksum,\n               ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTD_dStage;\n\ntypedef enum { zdss_init=0, zdss_loadHeader,\n               zdss_read, zdss_load, zdss_flush } ZSTD_dStreamStage;\n\ntypedef enum {\n    ZSTD_use_indefinitely = -1,  /* Use the dictionary indefinitely */\n    ZSTD_dont_use = 0,           /* Do not use the dictionary (if one exists free it) */\n    ZSTD_use_once = 1            /* Use the dictionary once and set to ZSTD_dont_use */\n} ZSTD_dictUses_e;\n\n/* Hashset for storing references to multiple ZSTD_DDict within ZSTD_DCtx */\ntypedef struct {\n    const ZSTD_DDict** ddictPtrTable;\n    size_t ddictPtrTableSize;\n    size_t ddictPtrCount;\n} ZSTD_DDictHashSet;\n\n#ifndef ZSTD_DECODER_INTERNAL_BUFFER\n#  define ZSTD_DECODER_INTERNAL_BUFFER  (1 << 16)\n#endif\n\n#define ZSTD_LBMIN 64\n#define ZSTD_LBMAX (128 << 10)\n\n/* extra buffer, compensates when dst is not large enough to store litBuffer */\n#define ZSTD_LITBUFFEREXTRASIZE  BOUNDED(ZSTD_LBMIN, ZSTD_DECODER_INTERNAL_BUFFER, ZSTD_LBMAX)\n\ntypedef enum {\n    ZSTD_not_in_dst = 0,  /* Stored entirely within litExtraBuffer */\n    ZSTD_in_dst = 1,           /* Stored entirely within dst (in memory after current output write) */\n    ZSTD_split = 2            /* Split between litExtraBuffer and dst */\n} ZSTD_litLocation_e;\n\nstruct ZSTD_DCtx_s\n{\n    const ZSTD_seqSymbol* LLTptr;\n    const ZSTD_seqSymbol* MLTptr;\n    const ZSTD_seqSymbol* OFTptr;\n    const HUF_DTable* HUFptr;\n    ZSTD_entropyDTables_t entropy;\n    U32 workspace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32];   /* space needed when building huffman tables */\n    const void* previousDstEnd;   /* detect continuity */\n    const void* prefixStart;      /* start of current segment */\n    const void* virtualStart;     /* virtual start of previous segment if it was just before current one */\n    const void* dictEnd;          /* end of previous segment */\n    size_t expected;\n    ZSTD_FrameHeader fParams;\n    U64 processedCSize;\n    U64 decodedSize;\n    blockType_e bType;            /* used in ZSTD_decompressContinue(), store blockType between block header decoding and block decompression stages */\n    ZSTD_dStage stage;\n    U32 litEntropy;\n    U32 fseEntropy;\n    XXH64_state_t xxhState;\n    size_t headerSize;\n    ZSTD_format_e format;\n    ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum;   /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */\n    U32 validateChecksum;         /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */\n    const BYTE* litPtr;\n    ZSTD_customMem customMem;\n    size_t litSize;\n    size_t rleSize;\n    size_t staticSize;\n    int isFrameDecompression;\n#if DYNAMIC_BMI2\n    int bmi2;                     /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */\n#endif\n\n    /* dictionary */\n    ZSTD_DDict* ddictLocal;\n    const ZSTD_DDict* ddict;     /* set by ZSTD_initDStream_usingDDict(), or ZSTD_DCtx_refDDict() */\n    U32 dictID;\n    int ddictIsCold;             /* if == 1 : dictionary is \"new\" for working context, and presumed \"cold\" (not in cpu cache) */\n    ZSTD_dictUses_e dictUses;\n    ZSTD_DDictHashSet* ddictSet;                    /* Hash set for multiple ddicts */\n    ZSTD_refMultipleDDicts_e refMultipleDDicts;     /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */\n    int disableHufAsm;\n    int maxBlockSizeParam;\n\n    /* streaming */\n    ZSTD_dStreamStage streamStage;\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    size_t maxWindowSize;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t lhSize;\n#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)\n    void* legacyContext;\n    U32 previousLegacyVersion;\n    U32 legacyVersion;\n#endif\n    U32 hostageByte;\n    int noForwardProgress;\n    ZSTD_bufferMode_e outBufferMode;\n    ZSTD_outBuffer expectedOutBuffer;\n\n    /* workspace */\n    BYTE* litBuffer;\n    const BYTE* litBufferEnd;\n    ZSTD_litLocation_e litBufferLocation;\n    BYTE litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE + WILDCOPY_OVERLENGTH]; /* literal buffer can be split between storage within dst and within this scratch buffer */\n    BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];\n\n    size_t oversizedDuration;\n\n#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION\n    void const* dictContentBeginForFuzzing;\n    void const* dictContentEndForFuzzing;\n#endif\n\n    /* Tracing */\n#if ZSTD_TRACE\n    ZSTD_TraceCtx traceCtx;\n#endif\n};  /* typedef'd to ZSTD_DCtx within \"zstd.h\" */\n\nMEM_STATIC int ZSTD_DCtx_get_bmi2(const struct ZSTD_DCtx_s *dctx) {\n#if DYNAMIC_BMI2\n    return dctx->bmi2;\n#else\n    (void)dctx;\n    return 0;\n#endif\n}\n\n/*-*******************************************************\n *  Shared internal functions\n *********************************************************/\n\n/*! ZSTD_loadDEntropy() :\n *  dict : must point at beginning of a valid zstd dictionary.\n * @return : size of dictionary header (size of magic number + dict ID + entropy tables) */\nsize_t ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy,\n                   const void* const dict, size_t const dictSize);\n\n/*! ZSTD_checkContinuity() :\n *  check if next `dst` follows previous position, where decompression ended.\n *  If yes, do nothing (continue on current segment).\n *  If not, classify previous segment as \"external dictionary\", and start a new segment.\n *  This function cannot fail. */\nvoid ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst, size_t dstSize);\n\n\n#endif /* ZSTD_DECOMPRESS_INTERNAL_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_legacy.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_LEGACY_H\n#define ZSTD_LEGACY_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include \"../common/mem.h\"            /* MEM_STATIC */\n#include \"../common/error_private.h\"  /* ERROR */\n#include \"../common/zstd_internal.h\"  /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTD_frameSizeInfo */\n\n#if !defined (ZSTD_LEGACY_SUPPORT) || (ZSTD_LEGACY_SUPPORT == 0)\n#  undef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 8\n#endif\n\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n#  include \"zstd_v01.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n#  include \"zstd_v02.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n#  include \"zstd_v03.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n#  include \"zstd_v04.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n#  include \"zstd_v05.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n#  include \"zstd_v06.h\"\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n#  include \"zstd_v07.h\"\n#endif\n\n/** ZSTD_isLegacy() :\n    @return : > 0 if supported by legacy decoder. 0 otherwise.\n              return value is the version.\n*/\nMEM_STATIC unsigned ZSTD_isLegacy(const void* src, size_t srcSize)\n{\n    U32 magicNumberLE;\n    if (srcSize<4) return 0;\n    magicNumberLE = MEM_readLE32(src);\n    switch(magicNumberLE)\n    {\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n        case ZSTDv01_magicNumberLE:return 1;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n        case ZSTDv02_magicNumber : return 2;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n        case ZSTDv03_magicNumber : return 3;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case ZSTDv04_magicNumber : return 4;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case ZSTDv05_MAGICNUMBER : return 5;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case ZSTDv06_MAGICNUMBER : return 6;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case ZSTDv07_MAGICNUMBER : return 7;\n#endif\n        default : return 0;\n    }\n}\n\n\nMEM_STATIC unsigned long long ZSTD_getDecompressedSize_legacy(const void* src, size_t srcSize)\n{\n    U32 const version = ZSTD_isLegacy(src, srcSize);\n    if (version < 5) return 0;  /* no decompressed size in frame header, or not a legacy format */\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n    if (version==5) {\n        ZSTDv05_parameters fParams;\n        size_t const frResult = ZSTDv05_getFrameParams(&fParams, src, srcSize);\n        if (frResult != 0) return 0;\n        return fParams.srcSize;\n    }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n    if (version==6) {\n        ZSTDv06_frameParams fParams;\n        size_t const frResult = ZSTDv06_getFrameParams(&fParams, src, srcSize);\n        if (frResult != 0) return 0;\n        return fParams.frameContentSize;\n    }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n    if (version==7) {\n        ZSTDv07_frameParams fParams;\n        size_t const frResult = ZSTDv07_getFrameParams(&fParams, src, srcSize);\n        if (frResult != 0) return 0;\n        return fParams.frameContentSize;\n    }\n#endif\n    return 0;   /* should not be possible */\n}\n\n\nMEM_STATIC size_t ZSTD_decompressLegacy(\n                     void* dst, size_t dstCapacity,\n               const void* src, size_t compressedSize,\n               const void* dict,size_t dictSize)\n{\n    U32 const version = ZSTD_isLegacy(src, compressedSize);\n    char x;\n    /* Avoid passing NULL to legacy decoding. */\n    if (dst == NULL) {\n        assert(dstCapacity == 0);\n        dst = &x;\n    }\n    if (src == NULL) {\n        assert(compressedSize == 0);\n        src = &x;\n    }\n    if (dict == NULL) {\n        assert(dictSize == 0);\n        dict = &x;\n    }\n    (void)dst; (void)dstCapacity; (void)dict; (void)dictSize;  /* unused when ZSTD_LEGACY_SUPPORT >= 8 */\n    switch(version)\n    {\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n        case 1 :\n            return ZSTDv01_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n        case 2 :\n            return ZSTDv02_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n        case 3 :\n            return ZSTDv03_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n            return ZSTDv04_decompress(dst, dstCapacity, src, compressedSize);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n            {   size_t result;\n                ZSTDv05_DCtx* const zd = ZSTDv05_createDCtx();\n                if (zd==NULL) return ERROR(memory_allocation);\n                result = ZSTDv05_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);\n                ZSTDv05_freeDCtx(zd);\n                return result;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n            {   size_t result;\n                ZSTDv06_DCtx* const zd = ZSTDv06_createDCtx();\n                if (zd==NULL) return ERROR(memory_allocation);\n                result = ZSTDv06_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);\n                ZSTDv06_freeDCtx(zd);\n                return result;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n            {   size_t result;\n                ZSTDv07_DCtx* const zd = ZSTDv07_createDCtx();\n                if (zd==NULL) return ERROR(memory_allocation);\n                result = ZSTDv07_decompress_usingDict(zd, dst, dstCapacity, src, compressedSize, dict, dictSize);\n                ZSTDv07_freeDCtx(zd);\n                return result;\n            }\n#endif\n        default :\n            return ERROR(prefix_unknown);\n    }\n}\n\nMEM_STATIC ZSTD_frameSizeInfo ZSTD_findFrameSizeInfoLegacy(const void *src, size_t srcSize)\n{\n    ZSTD_frameSizeInfo frameSizeInfo;\n    U32 const version = ZSTD_isLegacy(src, srcSize);\n    switch(version)\n    {\n#if (ZSTD_LEGACY_SUPPORT <= 1)\n        case 1 :\n            ZSTDv01_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 2)\n        case 2 :\n            ZSTDv02_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 3)\n        case 3 :\n            ZSTDv03_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n            ZSTDv04_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n            ZSTDv05_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n            ZSTDv06_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n            ZSTDv07_findFrameSizeInfoLegacy(src, srcSize,\n                &frameSizeInfo.compressedSize,\n                &frameSizeInfo.decompressedBound);\n            break;\n#endif\n        default :\n            frameSizeInfo.compressedSize = ERROR(prefix_unknown);\n            frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;\n            break;\n    }\n    if (!ZSTD_isError(frameSizeInfo.compressedSize) && frameSizeInfo.compressedSize > srcSize) {\n        frameSizeInfo.compressedSize = ERROR(srcSize_wrong);\n        frameSizeInfo.decompressedBound = ZSTD_CONTENTSIZE_ERROR;\n    }\n    /* In all cases, decompressedBound == nbBlocks * ZSTD_BLOCKSIZE_MAX.\n     * So we can compute nbBlocks without having to change every function.\n     */\n    if (frameSizeInfo.decompressedBound != ZSTD_CONTENTSIZE_ERROR) {\n        assert((frameSizeInfo.decompressedBound & (ZSTD_BLOCKSIZE_MAX - 1)) == 0);\n        frameSizeInfo.nbBlocks = (size_t)(frameSizeInfo.decompressedBound / ZSTD_BLOCKSIZE_MAX);\n    }\n    return frameSizeInfo;\n}\n\nMEM_STATIC size_t ZSTD_findFrameCompressedSizeLegacy(const void *src, size_t srcSize)\n{\n    ZSTD_frameSizeInfo frameSizeInfo = ZSTD_findFrameSizeInfoLegacy(src, srcSize);\n    return frameSizeInfo.compressedSize;\n}\n\nMEM_STATIC size_t ZSTD_freeLegacyStreamContext(void* legacyContext, U32 version)\n{\n    switch(version)\n    {\n        default :\n        case 1 :\n        case 2 :\n        case 3 :\n            (void)legacyContext;\n            return ERROR(version_unsupported);\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 : return ZBUFFv04_freeDCtx((ZBUFFv04_DCtx*)legacyContext);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 : return ZBUFFv05_freeDCtx((ZBUFFv05_DCtx*)legacyContext);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 : return ZBUFFv06_freeDCtx((ZBUFFv06_DCtx*)legacyContext);\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 : return ZBUFFv07_freeDCtx((ZBUFFv07_DCtx*)legacyContext);\n#endif\n    }\n}\n\n\nMEM_STATIC size_t ZSTD_initLegacyStream(void** legacyContext, U32 prevVersion, U32 newVersion,\n                                        const void* dict, size_t dictSize)\n{\n    char x;\n    /* Avoid passing NULL to legacy decoding. */\n    if (dict == NULL) {\n        assert(dictSize == 0);\n        dict = &x;\n    }\n    DEBUGLOG(5, \"ZSTD_initLegacyStream for v0.%u\", newVersion);\n    if (prevVersion != newVersion) ZSTD_freeLegacyStreamContext(*legacyContext, prevVersion);\n    switch(newVersion)\n    {\n        default :\n        case 1 :\n        case 2 :\n        case 3 :\n            (void)dict; (void)dictSize;\n            return 0;\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n        {\n            ZBUFFv04_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv04_createDCtx() : (ZBUFFv04_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv04_decompressInit(dctx);\n            ZBUFFv04_decompressWithDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n        {\n            ZBUFFv05_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv05_createDCtx() : (ZBUFFv05_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv05_decompressInitDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n        {\n            ZBUFFv06_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv06_createDCtx() : (ZBUFFv06_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv06_decompressInitDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n        {\n            ZBUFFv07_DCtx* dctx = (prevVersion != newVersion) ? ZBUFFv07_createDCtx() : (ZBUFFv07_DCtx*)*legacyContext;\n            if (dctx==NULL) return ERROR(memory_allocation);\n            ZBUFFv07_decompressInitDictionary(dctx, dict, dictSize);\n            *legacyContext = dctx;\n            return 0;\n        }\n#endif\n    }\n}\n\n\n\nMEM_STATIC size_t ZSTD_decompressLegacyStream(void* legacyContext, U32 version,\n                                              ZSTD_outBuffer* output, ZSTD_inBuffer* input)\n{\n    static char x;\n    /* Avoid passing NULL to legacy decoding. */\n    if (output->dst == NULL) {\n        assert(output->size == 0);\n        output->dst = &x;\n    }\n    if (input->src == NULL) {\n        assert(input->size == 0);\n        input->src = &x;\n    }\n    DEBUGLOG(5, \"ZSTD_decompressLegacyStream for v0.%u\", version);\n    switch(version)\n    {\n        default :\n        case 1 :\n        case 2 :\n        case 3 :\n            (void)legacyContext; (void)output; (void)input;\n            return ERROR(version_unsupported);\n#if (ZSTD_LEGACY_SUPPORT <= 4)\n        case 4 :\n            {\n                ZBUFFv04_DCtx* dctx = (ZBUFFv04_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv04_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 5)\n        case 5 :\n            {\n                ZBUFFv05_DCtx* dctx = (ZBUFFv05_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv05_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 6)\n        case 6 :\n            {\n                ZBUFFv06_DCtx* dctx = (ZBUFFv06_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv06_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n#if (ZSTD_LEGACY_SUPPORT <= 7)\n        case 7 :\n            {\n                ZBUFFv07_DCtx* dctx = (ZBUFFv07_DCtx*) legacyContext;\n                const void* src = (const char*)input->src + input->pos;\n                size_t readSize = input->size - input->pos;\n                void* dst = (char*)output->dst + output->pos;\n                size_t decodedSize = output->size - output->pos;\n                size_t const hintSize = ZBUFFv07_decompressContinue(dctx, dst, &decodedSize, src, &readSize);\n                output->pos += decodedSize;\n                input->pos += readSize;\n                return hintSize;\n            }\n#endif\n    }\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* ZSTD_LEGACY_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v01.c",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/******************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include \"zstd_v01.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/******************************************\n*  Static allocation\n******************************************/\n/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n/* You can statically allocate Huff0 DTable as a table of unsigned short using below macro */\n#define HUF_DTABLE_SIZE_U16(maxTableLog)   (1 + (1<<maxTableLog))\n#define HUF_CREATE_STATIC_DTABLE(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE_U16(maxTableLog)] = { maxTableLog }\n\n\n/******************************************\n*  Error Management\n******************************************/\n#define FSE_LIST_ERRORS(ITEM) \\\n        ITEM(FSE_OK_NoError) ITEM(FSE_ERROR_GENERIC) \\\n        ITEM(FSE_ERROR_tableLog_tooLarge) ITEM(FSE_ERROR_maxSymbolValue_tooLarge) ITEM(FSE_ERROR_maxSymbolValue_tooSmall) \\\n        ITEM(FSE_ERROR_dstSize_tooSmall) ITEM(FSE_ERROR_srcSize_wrong)\\\n        ITEM(FSE_ERROR_corruptionDetected) \\\n        ITEM(FSE_ERROR_maxCode)\n\n#define FSE_GENERATE_ENUM(ENUM) ENUM,\ntypedef enum { FSE_LIST_ERRORS(FSE_GENERATE_ENUM) } FSE_errorCodes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */\n\n\n/******************************************\n*  FSE symbol compression API\n******************************************/\n/*\n   This API consists of small unitary functions, which highly benefit from being inlined.\n   You will want to enable link-time-optimization to ensure these functions are properly inlined in your binary.\n   Visual seems to do it automatically.\n   For gcc or clang, you'll need to add -flto flag at compilation and linking stages.\n   If none of these solutions is applicable, include \"fse.c\" directly.\n*/\n\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\ntypedef struct\n{\n    size_t bitContainer;\n    int    bitPos;\n    char*  startPtr;\n    char*  ptr;\n    char*  endPtr;\n} FSE_CStream_t;\n\ntypedef struct\n{\n    ptrdiff_t   value;\n    const void* stateTable;\n    const void* symbolTT;\n    unsigned    stateLog;\n} FSE_CState_t;\n\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} FSE_DStream_t;\n\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\ntypedef enum { FSE_DStream_unfinished = 0,\n               FSE_DStream_endOfBuffer = 1,\n               FSE_DStream_completed = 2,\n               FSE_DStream_tooFar = 3 } FSE_DStream_status;  /* result of FSE_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... ?! */\n\n\n/****************************************************************\n*  Tuning parameters\n****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/* FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/****************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n\n\n/****************************************************************\n*  Byte symbol type\n****************************************************************/\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\n\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n#ifndef MEM_ACCESS_MODULE\n#define MEM_ACCESS_MODULE\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n# include <stdint.h>\ntypedef  uint8_t BYTE;\ntypedef uint16_t U16;\ntypedef  int16_t S16;\ntypedef uint32_t U32;\ntypedef  int32_t S32;\ntypedef uint64_t U64;\ntypedef  int64_t S64;\n#else\ntypedef unsigned char       BYTE;\ntypedef unsigned short      U16;\ntypedef   signed short      S16;\ntypedef unsigned int        U32;\ntypedef   signed int        S32;\ntypedef unsigned long long  U64;\ntypedef   signed long long  S64;\n#endif\n\n#endif   /* MEM_ACCESS_MODULE */\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nstatic unsigned FSE_32bits(void)\n{\n    return sizeof(void*)==4;\n}\n\nstatic unsigned FSE_isLittleEndian(void)\n{\n    const union { U32 i; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nstatic U16 FSE_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic U32 FSE_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic U64 FSE_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nstatic U16 FSE_readLE16(const void* memPtr)\n{\n    if (FSE_isLittleEndian())\n        return FSE_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nstatic U32 FSE_readLE32(const void* memPtr)\n{\n    if (FSE_isLittleEndian())\n        return FSE_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nstatic U64 FSE_readLE64(const void* memPtr)\n{\n    if (FSE_isLittleEndian())\n        return FSE_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\nstatic size_t FSE_readLEST(const void* memPtr)\n{\n    if (FSE_32bits())\n        return (size_t)FSE_readLE32(memPtr);\n    else\n        return (size_t)FSE_readLE64(memPtr);\n}\n\n\n\n/****************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/****************************************************************\n*  Complex types\n****************************************************************/\ntypedef struct\n{\n    int deltaFindState;\n    U32 deltaNbBits;\n} FSE_symbolCompressionTransform; /* total 8 bytes */\n\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n/****************************************************************\n*  Internal functions\n****************************************************************/\nFORCE_INLINE unsigned FSE_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (GCC_VERSION >= 304)   /* GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n/****************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\n#define FSE_DECODE_TYPE FSE_decode_t\n\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\nstatic size_t FSE_buildDTable\n(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)(ptr) + 1;   /* because dt is unsigned, 32-bits aligned on 32-bits */\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return (size_t)-FSE_ERROR_maxSymbolValue_tooLarge;\n    if (tableLog > FSE_MAX_TABLELOG) return (size_t)-FSE_ERROR_tableLog_tooLarge;\n\n    /* Init, lay down lowprob symbols */\n    DTableH[0].tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return (size_t)-FSE_ERROR_GENERIC;   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - FSE_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH->fastMode = (U16)noLarge;\n    return 0;\n}\n\n\n/******************************************\n*  FSE byte symbol\n******************************************/\n#ifndef FSE_COMMONDEFS_ONLY\n\nstatic unsigned FSE_isError(size_t code) { return (code > (size_t)(-FSE_ERROR_maxCode)); }\n\nstatic short FSE_abs(short a)\n{\n    return a<0? -a : a;\n}\n\n\n/****************************************************************\n*  Header bitstream management\n****************************************************************/\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return (size_t)-FSE_ERROR_srcSize_wrong;\n    bitStream = FSE_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return (size_t)-FSE_ERROR_tableLog_tooLarge;\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = FSE_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return (size_t)-FSE_ERROR_maxSymbolValue_tooSmall;\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = FSE_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = FSE_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return (size_t)-FSE_ERROR_GENERIC;\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return (size_t)-FSE_ERROR_GENERIC;             /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\n\n/* FSE_initDStream\n * Initialize a FSE_DStream_t.\n * srcBuffer must point at the beginning of an FSE block.\n * The function result is the size of the FSE_block (== srcSize).\n * If srcSize is too small, the function will return an errorCode;\n */\nstatic size_t FSE_initDStream(FSE_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) return (size_t)-FSE_ERROR_srcSize_wrong;\n\n    if (srcSize >=  sizeof(size_t))\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = FSE_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC;   /* stop bit not present */\n        bitD->bitsConsumed = 8 - FSE_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);\n                    /* fallthrough */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);\n                    /* fallthrough */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);\n                    /* fallthrough */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;\n                    /* fallthrough */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;\n                    /* fallthrough */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;\n                    /* fallthrough */\n            default:;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return (size_t)-FSE_ERROR_GENERIC;   /* stop bit not present */\n        bitD->bitsConsumed = 8 - FSE_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\n\n/*!FSE_lookBits\n * Provides next n bits from the bitContainer.\n * bitContainer is not modified (bits are still present for next read/look)\n * On 32-bits, maxNbBits==25\n * On 64-bits, maxNbBits==57\n * return : value extracted.\n */\nstatic size_t FSE_lookBits(FSE_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\nstatic size_t FSE_lookBitsFast(FSE_DStream_t* bitD, U32 nbBits)   /* only if nbBits >= 1 !! */\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nstatic void FSE_skipBits(FSE_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\n\n/*!FSE_readBits\n * Read next n bits from the bitContainer.\n * On 32-bits, don't read more than maxNbBits==25\n * On 64-bits, don't read more than maxNbBits==57\n * Use the fast variant *only* if n >= 1.\n * return : value extracted.\n */\nstatic size_t FSE_readBits(FSE_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = FSE_lookBits(bitD, nbBits);\n    FSE_skipBits(bitD, nbBits);\n    return value;\n}\n\nstatic size_t FSE_readBitsFast(FSE_DStream_t* bitD, U32 nbBits)   /* only if nbBits >= 1 !! */\n{\n    size_t value = FSE_lookBitsFast(bitD, nbBits);\n    FSE_skipBits(bitD, nbBits);\n    return value;\n}\n\nstatic unsigned FSE_reloadDStream(FSE_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return FSE_DStream_tooFar;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = FSE_readLEST(bitD->ptr);\n        return FSE_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return FSE_DStream_endOfBuffer;\n        return FSE_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        U32 result = FSE_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = FSE_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = FSE_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n\nstatic void FSE_initDState(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD, const FSE_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSE_DTableHeader* const DTableH = (const FSE_DTableHeader*)ptr;\n    DStatePtr->state = FSE_readBits(bitD, DTableH->tableLog);\n    FSE_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nstatic BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = FSE_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nstatic BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, FSE_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = FSE_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/* FSE_endOfDStream\n   Tells if bitD has reached end of bitStream or not */\n\nstatic unsigned FSE_endOfDStream(const FSE_DStream_t* bitD)\n{\n    return ((bitD->ptr == bitD->start) && (bitD->bitsConsumed == sizeof(bitD->bitContainer)*8));\n}\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    FSE_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = FSE_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (FSE_reloadDStream(&bitD)==FSE_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            FSE_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (FSE_reloadDStream(&bitD) > FSE_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            FSE_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : FSE_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly FSE_DStream_completed */\n    while (1)\n    {\n        if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (FSE_reloadDStream(&bitD)>FSE_DStream_completed) || (op==omax) || (FSE_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (FSE_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */\n\n    return (size_t)-FSE_ERROR_corruptionDetected;\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));   /* memcpy() into local variable, to avoid strict aliasing warning */\n\n    /* select fast mode (static) */\n    if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return (size_t)-FSE_ERROR_srcSize_wrong;   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n/* *******************************************************\n*  Huff0 : Huffman block compression\n*********************************************************/\n#define HUF_MAX_SYMBOL_VALUE 255\n#define HUF_DEFAULT_TABLELOG  12       /* used by default, when not specified */\n#define HUF_MAX_TABLELOG  12           /* max possible tableLog; for allocation purpose; can be modified */\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\ntypedef struct HUF_CElt_s {\n  U16  val;\n  BYTE nbBits;\n} HUF_CElt ;\n\ntypedef struct nodeElt_s {\n    U32 count;\n    U16 parent;\n    BYTE byte;\n    BYTE nbBits;\n} nodeElt;\n\n\n/* *******************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct {\n    BYTE byte;\n    BYTE nbBits;\n} HUF_DElt;\n\nstatic size_t HUF_readDTable (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];  /* large enough for values from 0 to 16 */\n    U32 weightTotal;\n    U32 maxBits;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n    U32 nextRankStart;\n    void* ptr = DTable+1;\n    HUF_DElt* const dt = (HUF_DElt*)ptr;\n\n    if (!srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n    iSize = ip[0];\n\n    FSE_STATIC_ASSERT(sizeof(HUF_DElt) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* should not be necessary, but some analyzer complain ... */\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, sizeof(huffWeight));\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n        oSize = FSE_decompress(huffWeight, HUF_MAX_SYMBOL_VALUE, ip+1, iSize);   /* max 255 values decoded, last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankVal, 0, sizeof(rankVal));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return (size_t)-FSE_ERROR_corruptionDetected;\n        rankVal[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return (size_t)-FSE_ERROR_corruptionDetected;\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    maxBits = FSE_highbit32(weightTotal) + 1;\n    if (maxBits > DTable[0]) return (size_t)-FSE_ERROR_tableLog_tooLarge;   /* DTable is too small */\n    DTable[0] = (U16)maxBits;\n    {\n        U32 total = 1 << maxBits;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << FSE_highbit32(rest);\n        U32 lastWeight = FSE_highbit32(rest) + 1;\n        if (verif != rest) return (size_t)-FSE_ERROR_corruptionDetected;    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankVal[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankVal[1] < 2) || (rankVal[1] & 1)) return (size_t)-FSE_ERROR_corruptionDetected;   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=maxBits; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<=oSize; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DElt D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(maxBits + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize+1;\n}\n\n\nstatic BYTE HUF_decodeSymbol(FSE_DStream_t* Dstream, const HUF_DElt* dt, const U32 dtLog)\n{\n        const size_t val = FSE_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        FSE_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\nstatic size_t HUF_decompress_usingDTable(   /* -3% slower when non static */\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 6) return (size_t)-FSE_ERROR_srcSize_wrong;\n    {\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* op = ostart;\n        BYTE* const omax = op + maxDstSize;\n        BYTE* const olimit = maxDstSize < 15 ? op : omax-15;\n\n        const void* ptr = DTable;\n        const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n        U32 reloadStatus;\n\n        /* Init */\n\n        const U16* jumpTable = (const U16*)cSrc;\n        const size_t length1 = FSE_readLE16(jumpTable);\n        const size_t length2 = FSE_readLE16(jumpTable+1);\n        const size_t length3 = FSE_readLE16(jumpTable+2);\n        const size_t length4 = cSrcSize - 6 - length1 - length2 - length3;   /* check coherency !! */\n        const char* const start1 = (const char*)(cSrc) + 6;\n        const char* const start2 = start1 + length1;\n        const char* const start3 = start2 + length2;\n        const char* const start4 = start3 + length3;\n        FSE_DStream_t bitD1, bitD2, bitD3, bitD4;\n\n        if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n\n        errorCode = FSE_initDStream(&bitD1, start1, length1);\n        if (FSE_isError(errorCode)) return errorCode;\n        errorCode = FSE_initDStream(&bitD2, start2, length2);\n        if (FSE_isError(errorCode)) return errorCode;\n        errorCode = FSE_initDStream(&bitD3, start3, length3);\n        if (FSE_isError(errorCode)) return errorCode;\n        errorCode = FSE_initDStream(&bitD4, start4, length4);\n        if (FSE_isError(errorCode)) return errorCode;\n\n        reloadStatus=FSE_reloadDStream(&bitD2);\n\n        /* 16 symbols per loop */\n        for ( ; (reloadStatus<FSE_DStream_completed) && (op<olimit);  /* D2-3-4 are supposed to be synchronized and finish together */\n            op+=16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1))\n        {\n    #define HUF_DECODE_SYMBOL_0(n, Dstream) \\\n            op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog);\n\n    #define HUF_DECODE_SYMBOL_1(n, Dstream) \\\n            op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \\\n            if (FSE_32bits() && (HUF_MAX_TABLELOG>12)) FSE_reloadDStream(&Dstream)\n\n    #define HUF_DECODE_SYMBOL_2(n, Dstream) \\\n            op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \\\n            if (FSE_32bits()) FSE_reloadDStream(&Dstream)\n\n            HUF_DECODE_SYMBOL_1( 0, bitD1);\n            HUF_DECODE_SYMBOL_1( 1, bitD2);\n            HUF_DECODE_SYMBOL_1( 2, bitD3);\n            HUF_DECODE_SYMBOL_1( 3, bitD4);\n            HUF_DECODE_SYMBOL_2( 4, bitD1);\n            HUF_DECODE_SYMBOL_2( 5, bitD2);\n            HUF_DECODE_SYMBOL_2( 6, bitD3);\n            HUF_DECODE_SYMBOL_2( 7, bitD4);\n            HUF_DECODE_SYMBOL_1( 8, bitD1);\n            HUF_DECODE_SYMBOL_1( 9, bitD2);\n            HUF_DECODE_SYMBOL_1(10, bitD3);\n            HUF_DECODE_SYMBOL_1(11, bitD4);\n            HUF_DECODE_SYMBOL_0(12, bitD1);\n            HUF_DECODE_SYMBOL_0(13, bitD2);\n            HUF_DECODE_SYMBOL_0(14, bitD3);\n            HUF_DECODE_SYMBOL_0(15, bitD4);\n        }\n\n        if (reloadStatus!=FSE_DStream_completed)   /* not complete : some bitStream might be FSE_DStream_unfinished */\n            return (size_t)-FSE_ERROR_corruptionDetected;\n\n        /* tail */\n        {\n            /* bitTail = bitD1; */   /* *much* slower : -20% !??! */\n            FSE_DStream_t bitTail;\n            bitTail.ptr = bitD1.ptr;\n            bitTail.bitsConsumed = bitD1.bitsConsumed;\n            bitTail.bitContainer = bitD1.bitContainer;   /* required in case of FSE_DStream_endOfBuffer */\n            bitTail.start = start1;\n            for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op<omax) ; op++)\n            {\n                HUF_DECODE_SYMBOL_0(0, bitTail);\n            }\n\n            if (FSE_endOfDStream(&bitTail))\n                return op-ostart;\n        }\n\n        if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */\n\n        return (size_t)-FSE_ERROR_corruptionDetected;\n    }\n}\n\n\nstatic size_t HUF_decompress (void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLE(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTable (DTable, cSrc, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong;\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, DTable);\n}\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/****************************************************************\n*  Tuning parameters\n*****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect */\n#define ZSTD_MEMORY_USAGE 17\n\n\n/**************************************\n   CPU Feature Detection\n**************************************/\n/*\n * Automated efficient unaligned memory access detection\n * Based on known hardware architectures\n * This list will be updated thanks to feedbacks\n */\n#if defined(CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS) \\\n    || defined(__ARM_FEATURE_UNALIGNED) \\\n    || defined(__i386__) || defined(__x86_64__) \\\n    || defined(_M_IX86) || defined(_M_X64) \\\n    || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_8__) \\\n    || (defined(_M_ARM) && (_M_ARM >= 7))\n#  define ZSTD_UNALIGNED_ACCESS 1\n#else\n#  define ZSTD_UNALIGNED_ACCESS 0\n#endif\n\n\n/********************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/********************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef __AVX2__\n#  include <immintrin.h>   /* AVX2 intrinsics */\n#endif\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n#ifndef MEM_ACCESS_MODULE\n#define MEM_ACCESS_MODULE\n/********************************************************\n*  Basic Types\n*********************************************************/\n#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\ntypedef  uint8_t BYTE;\ntypedef uint16_t U16;\ntypedef  int16_t S16;\ntypedef uint32_t U32;\ntypedef  int32_t S32;\ntypedef uint64_t U64;\n#else\ntypedef unsigned char       BYTE;\ntypedef unsigned short      U16;\ntypedef   signed short      S16;\ntypedef unsigned int        U32;\ntypedef   signed int        S32;\ntypedef unsigned long long  U64;\n#endif\n\n#endif   /* MEM_ACCESS_MODULE */\n\n\n/********************************************************\n*  Constants\n*********************************************************/\nstatic const U32 ZSTD_magicNumber = 0xFD2FB51E;   /* 3rd version : seqNb header */\n\n#define HASH_LOG (ZSTD_MEMORY_USAGE - 2)\n#define HASH_TABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASH_TABLESIZE - 1)\n\n#define KNUTH 2654435761\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n\n#define WORKPLACESIZE (BLOCKSIZE*3)\n#define MINMATCH 4\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits )-1)\n#define MaxLL  ((1<<LLbits )-1)\n#define MaxOff ((1<<Offbits)-1)\n#define LitFSELog  11\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MAX(a,b) ((a)<(b)?(b):(a))\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define LITERAL_NOENTROPY 63\n#define COMMAND_NOENTROPY 7   /* to remove */\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize = 4;\n\n\n/********************************************************\n*  Memory operations\n*********************************************************/\nstatic unsigned ZSTD_32bits(void) { return sizeof(void*)==4; }\n\nstatic unsigned ZSTD_isLittleEndian(void)\n{\n    const union { U32 i; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nstatic U16    ZSTD_read16(const void* p) { U16 r; memcpy(&r, p, sizeof(r)); return r; }\n\nstatic void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\nstatic void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s)    { ZSTD_copy8(d,s); d+=8; s+=8; }\n\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    while (op < oend) COPY8(op, ip);\n}\n\nstatic U16 ZSTD_readLE16(const void* memPtr)\n{\n    if (ZSTD_isLittleEndian()) return ZSTD_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)((U16)p[0] + ((U16)p[1]<<8));\n    }\n}\n\nstatic U32 ZSTD_readLE24(const void* memPtr)\n{\n    return ZSTD_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nstatic U32 ZSTD_readBE32(const void* memPtr)\n{\n    const BYTE* p = (const BYTE*)memPtr;\n    return (U32)(((U32)p[0]<<24) + ((U32)p[1]<<16) + ((U32)p[2]<<8) + ((U32)p[3]<<0));\n}\n\n\n/**************************************\n*  Local structures\n***************************************/\ntypedef struct ZSTD_Cctx_s ZSTD_Cctx;\n\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n} SeqStore_t;\n\n\ntypedef struct ZSTD_Cctx_s\n{\n    const BYTE* base;\n    U32 current;\n    U32 nextUpdate;\n    SeqStore_t seqStore;\n#ifdef __AVX2__\n    __m256i hashTable[HASH_TABLESIZE>>3];\n#else\n    U32 hashTable[HASH_TABLESIZE];\n#endif\n    BYTE buffer[WORKPLACESIZE];\n} cctxi_t;\n\n\n\n\n/**************************************\n*  Error Management\n**************************************/\n/* published entry point */\nunsigned ZSTDv01_isError(size_t code) { return ERR_isError(code); }\n\n\n/**************************************\n*  Tool functions\n**************************************/\n#define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */\n#define ZSTD_VERSION_MINOR    1    /* for new (non-breaking) interface capabilities */\n#define ZSTD_VERSION_RELEASE  3    /* for tweaks, bug-fixes, or development */\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n/**************************************************************\n*   Decompression code\n**************************************************************/\n\nstatic size_t ZSTDv01_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\nstatic size_t ZSTD_decompressLiterals(void* ctx,\n                                      void* dst, size_t maxDstSize,\n                                const void* src, size_t srcSize)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + maxDstSize;\n    const BYTE* ip = (const BYTE*)src;\n    size_t errorCode;\n    size_t litSize;\n\n    /* check : minimum 2, for litSize, +1, for content */\n    if (srcSize <= 3) return ERROR(corruption_detected);\n\n    litSize = ip[1] + (ip[0]<<8);\n    litSize += ((ip[-3] >> 3) & 7) << 16;   /* mmmmh.... */\n    op = oend - litSize;\n\n    (void)ctx;\n    if (litSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    errorCode = HUF_decompress(op, litSize, ip+2, srcSize-2);\n    if (FSE_isError(errorCode)) return ERROR(GENERIC);\n    return litSize;\n}\n\n\nstatic size_t ZSTDv01_decodeLiteralsBlock(void* ctx,\n                                void* dst, size_t maxDstSize,\n                          const BYTE** litStart, size_t* litSize,\n                          const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* const oend = ostart + maxDstSize;\n    blockProperties_t litbp;\n\n    size_t litcSize = ZSTDv01_getcBlockSize(src, srcSize, &litbp);\n    if (ZSTDv01_isError(litcSize)) return litcSize;\n    if (litcSize > srcSize - ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    ip += ZSTD_blockHeaderSize;\n\n    switch(litbp.blockType)\n    {\n    case bt_raw:\n        *litStart = ip;\n        ip += litcSize;\n        *litSize = litcSize;\n        break;\n    case bt_rle:\n        {\n            size_t rleSize = litbp.origSize;\n            if (rleSize>maxDstSize) return ERROR(dstSize_tooSmall);\n            if (!srcSize) return ERROR(srcSize_wrong);\n            if (rleSize > 0) {\n                memset(oend - rleSize, *ip, rleSize);\n            }\n            *litStart = oend - rleSize;\n            *litSize = rleSize;\n            ip++;\n            break;\n        }\n    case bt_compressed:\n        {\n            size_t decodedLitSize = ZSTD_decompressLiterals(ctx, dst, maxDstSize, ip, litcSize);\n            if (ZSTDv01_isError(decodedLitSize)) return decodedLitSize;\n            *litStart = oend - decodedLitSize;\n            *litSize = decodedLitSize;\n            ip += litcSize;\n            break;\n        }\n    case bt_end:\n    default:\n        return ERROR(GENERIC);\n    }\n\n    return ip-istart;\n}\n\n\nstatic size_t ZSTDv01_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = ZSTD_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++); break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    FSE_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    seqState->prevOffset = seq->offset;\n    if (litLength == MaxLL)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else\n        {\n            if (dumps<=(de-3))\n            {\n                litLength = ZSTD_readLE24(dumps);\n                dumps += 3;\n            }\n        }\n    }\n\n    /* Offset */\n    {\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));\n        if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = ((size_t)1 << (nbBits & ((sizeof(offset)*8)-1))) + FSE_readBits(&(seqState->DStream), nbBits);\n        if (ZSTD_32bits()) FSE_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else\n        {\n            if (dumps<=(de-3))\n            {\n                matchLength = ZSTD_readLE24(dumps);\n                dumps += 3;\n            }\n        }\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                BYTE* const base, BYTE* const oend)\n{\n    static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */\n    static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */\n    const BYTE* const ostart = op;\n    BYTE* const oLitEnd = op + sequence.litLength;\n    const size_t litLength = sequence.litLength;\n    BYTE* const endMatch = op + litLength + sequence.matchLength;    /* risk : address space overflow (32-bits) */\n    const BYTE* const litEnd = *litPtr + litLength;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);\n\n    if (endMatch > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n    if (sequence.matchLength > (size_t)(*litPtr-op)) return ERROR(dstSize_tooSmall);  /* overwrite literal segment */\n\n    /* copy Literals */\n    ZSTD_memmove(op, *litPtr, sequence.litLength);   /* note : v0.1 seems to allow scenarios where output or input are close to end of buffer */\n\n    op += litLength;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* check : last match must be at a minimum distance of 8 from end of dest buffer */\n    if (oend-op < 8) return ERROR(dstSize_tooSmall);\n\n    /* copy Match */\n    {\n        const U32 overlapRisk = (((size_t)(litEnd - endMatch)) < 12);\n        const BYTE* match = op - sequence.offset;            /* possible underflow at op - offset ? */\n        size_t qutt = 12;\n        U64 saved[2];\n\n        /* check */\n        if (match < base) return ERROR(corruption_detected);\n        if (sequence.offset > (size_t)base) return ERROR(corruption_detected);\n\n        /* save beginning of literal sequence, in case of write overlap */\n        if (overlapRisk)\n        {\n            if ((endMatch + qutt) > oend) qutt = oend-endMatch;\n            memcpy(saved, endMatch, qutt);\n        }\n\n        if (sequence.offset < 8)\n        {\n            const int dec64 = dec64table[sequence.offset];\n            op[0] = match[0];\n            op[1] = match[1];\n            op[2] = match[2];\n            op[3] = match[3];\n            match += dec32table[sequence.offset];\n            ZSTD_copy4(op+4, match);\n            match -= dec64;\n        } else { ZSTD_copy8(op, match); }\n        op += 8; match += 8;\n\n        if (endMatch > oend-(16-MINMATCH))\n        {\n            if (op < oend-8)\n            {\n                ZSTD_wildcopy(op, match, (oend-8) - op);\n                match += (oend-8) - op;\n                op = oend-8;\n            }\n            while (op<endMatch) *op++ = *match++;\n        }\n        else\n            ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n\n        /* restore, in case of overlap */\n        if (overlapRisk) memcpy(endMatch, saved, qutt);\n    }\n\n    return endMatch-ostart;\n}\n\ntypedef struct ZSTDv01_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    void* previousDstEnd;\n    void* base;\n    size_t expected;\n    blockType_t bType;\n    U32 phase;\n} dctx_t;\n\n\nstatic size_t ZSTD_decompressSequences(\n                               void* ctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize,\n                         const BYTE* litStart, size_t litSize)\n{\n    dctx_t* dctx = (dctx_t*)ctx;\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength;\n    const BYTE* litPtr = litStart;\n    const BYTE* const litEnd = litStart + litSize;\n    int nbSeq;\n    const BYTE* dumps;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    BYTE* const base = (BYTE*) (dctx->base);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTDv01_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTDv01_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = 1;\n        errorCode = FSE_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (FSE_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (FSE_reloadDStream(&(seqState.DStream)) <= FSE_DStream_completed) && (nbSeq>0) ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);\n            if (ZSTDv01_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !FSE_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */\n        if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memmove(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic size_t ZSTD_decompressBlock(\n                            void* ctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed, srcSize is trusted */\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* litPtr = NULL;\n    size_t litSize = 0;\n    size_t errorCode;\n\n    /* Decode literals sub-block */\n    errorCode = ZSTDv01_decodeLiteralsBlock(ctx, dst, maxDstSize, &litPtr, &litSize, src, srcSize);\n    if (ZSTDv01_isError(errorCode)) return errorCode;\n    ip += errorCode;\n    srcSize -= errorCode;\n\n    return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize, litPtr, litSize);\n}\n\n\nsize_t ZSTDv01_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    U32 magicNumber;\n    size_t errorCode=0;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    magicNumber = ZSTD_readBE32(src);\n    if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t blockSize = ZSTDv01_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv01_isError(blockSize)) return blockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (blockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            errorCode = ZSTD_decompressBlock(ctx, op, oend-op, ip, blockSize);\n            break;\n        case bt_raw :\n            errorCode = ZSTD_copyUncompressedBlock(op, oend-op, ip, blockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        if (blockSize == 0) break;   /* bt_end */\n\n        if (ZSTDv01_isError(errorCode)) return errorCode;\n        op += errorCode;\n        ip += blockSize;\n        remainingSize -= blockSize;\n    }\n\n    return op-ostart;\n}\n\nsize_t ZSTDv01_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    dctx_t ctx;\n    ctx.base = dst;\n    return ZSTDv01_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    magicNumber = ZSTD_readBE32(src);\n    if (magicNumber != ZSTD_magicNumber) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t blockSize = ZSTDv01_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv01_isError(blockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, blockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (blockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (blockSize == 0) break;   /* bt_end */\n\n        ip += blockSize;\n        remainingSize -= blockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/*******************************\n*  Streaming Decompression API\n*******************************/\n\nsize_t ZSTDv01_resetDCtx(ZSTDv01_Dctx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize;\n    dctx->phase = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    return 0;\n}\n\nZSTDv01_Dctx* ZSTDv01_createDCtx(void)\n{\n    ZSTDv01_Dctx* dctx = (ZSTDv01_Dctx*)malloc(sizeof(ZSTDv01_Dctx));\n    if (dctx==NULL) return NULL;\n    ZSTDv01_resetDCtx(dctx);\n    return dctx;\n}\n\nsize_t ZSTDv01_freeDCtx(ZSTDv01_Dctx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\nsize_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx* dctx)\n{\n    return ((dctx_t*)dctx)->expected;\n}\n\nsize_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    dctx_t* ctx = (dctx_t*)dctx;\n\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    if (dst != ctx->previousDstEnd)  /* not contiguous */\n        ctx->base = dst;\n\n    /* Decompress : frame header */\n    if (ctx->phase == 0)\n    {\n        /* Check frame magic header */\n        U32 magicNumber = ZSTD_readBE32(src);\n        if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        return 0;\n    }\n\n    /* Decompress : block header */\n    if (ctx->phase == 1)\n    {\n        blockProperties_t bp;\n        size_t blockSize = ZSTDv01_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n        if (ZSTDv01_isError(blockSize)) return blockSize;\n        if (bp.blockType == bt_end)\n        {\n            ctx->expected = 0;\n            ctx->phase = 0;\n        }\n        else\n        {\n            ctx->expected = blockSize;\n            ctx->bType = bp.blockType;\n            ctx->phase = 2;\n        }\n\n        return 0;\n    }\n\n    /* Decompress : block content */\n    {\n        size_t rSize;\n        switch(ctx->bType)\n        {\n        case bt_compressed:\n            rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);\n            break;\n        case bt_raw :\n            rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet handled */\n            break;\n        case bt_end :   /* should never happen (filtered at phase 1) */\n            rSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        if (ZSTDv01_isError(rSize)) return rSize;\n        ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);\n        return rSize;\n    }\n\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v01.h",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V01_H_28739879432\n#define ZSTD_V01_H_28739879432\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv01_decompress() : decompress ZSTD frames compliant with v0.1.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv01_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv01_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.1.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n     note : assumes `cSize` and `dBound` are _not_ NULL.\n */\nvoid ZSTDv01_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/**\nZSTDv01_isError() : tells if the result of ZSTDv01_decompress() is an error\n*/\nunsigned ZSTDv01_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv01_Dctx_s ZSTDv01_Dctx;\nZSTDv01_Dctx* ZSTDv01_createDCtx(void);\nsize_t ZSTDv01_freeDCtx(ZSTDv01_Dctx* dctx);\n\nsize_t ZSTDv01_decompressDCtx(void* ctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n/* *************************************\n*  Streaming functions\n***************************************/\nsize_t ZSTDv01_resetDCtx(ZSTDv01_Dctx* dctx);\n\nsize_t ZSTDv01_nextSrcSizeToDecompress(ZSTDv01_Dctx* dctx);\nsize_t ZSTDv01_decompressContinue(ZSTDv01_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv01_magicNumber   0xFD2FB51E   /* Big Endian version */\n#define ZSTDv01_magicNumberLE 0x1EB52FFD   /* Little Endian version */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V01_H_28739879432 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v02.c",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include \"zstd_v02.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write16(memPtr, val);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n\n/* ******************************************************************\n   bitstream\n   Part of NewGen Entropy library\n   header file (to include)\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/**********************************************\n*  bitStream decompression API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,\n               BIT_DStream_endOfBuffer = 1,\n               BIT_DStream_completed = 2,\n               BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n/******************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/****************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BIT_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/**********************************************************\n* bitStream decoding\n**********************************************************/\n\n/*!BIT_initDStream\n*  Initialize a BIT_DStream_t.\n*  @bitD : a pointer to an already allocated BIT_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t))   /* normal case */\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);\n                    /* fallthrough */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);\n                    /* fallthrough */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);\n                    /* fallthrough */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;\n                    /* fallthrough */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;\n                    /* fallthrough */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;\n                    /* fallthrough */\n            default:;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nMEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BIT_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BIT_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBitsFast(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BIT_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BIT_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   Error codes and messages\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef ERROR_H_MODULE\n#define ERROR_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define ERR_STATIC static inline\n#elif defined(_MSC_VER)\n#  define ERR_STATIC static __inline\n#elif defined(__GNUC__)\n#  define ERR_STATIC static __attribute__((unused))\n#else\n#  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/******************************************\n*  Error Management\n******************************************/\n#define PREFIX(name) ZSTD_error_##name\n\n#define ERROR(name) (size_t)-PREFIX(name)\n\n#define ERROR_LIST(ITEM) \\\n        ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \\\n        ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \\\n        ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \\\n        ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \\\n        ITEM(PREFIX(maxCode))\n\n#define ERROR_GENERATE_ENUM(ENUM) ENUM,\ntypedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */\n\n#define ERROR_CONVERTTOSTRING(STRING) #STRING,\n#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR)\nstatic const char* ERR_strings[] = { ERROR_LIST(ERROR_GENERATE_STRING) };\n\nERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }\n\nERR_STATIC const char* ERR_getErrorName(size_t code)\n{\n    static const char* codeError = \"Unspecified error code\";\n    if (ERR_isError(code)) return ERR_strings[-(int)(code)];\n    return codeError;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ERROR_H_MODULE */\n/*\nConstructor and Destructor of type FSE_CTable\n    Note that its size depends on 'tableLog' and 'maxSymbolValue' */\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Static allocation\n******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) (size + (size>>7))\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/******************************************\n*  FSE advanced API\n******************************************/\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);\n/* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);\n/* build a fake FSE_DTable, designed to always generate the same symbolValue */\n\n\n/******************************************\n*  FSE symbol decompression API\n******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n\n/******************************************\n*  FSE unsafe API\n******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/******************************************\n*  Implementation of inline functions\n******************************************/\n\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Static allocation macros\n******************************************/\n/* Huff0 buffer bounds */\n#define HUF_CTABLEBOUND 129\n#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of Huff0's DTable */\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))  /* nb Cells; use unsigned short for X2, unsigned int for X4 */\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/******************************************\n*  Advanced functions\n******************************************/\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\nstatic size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* quad-symbols decoder */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n/*\n    zstd - standard compression library\n    Header File\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Version\n***************************************/\n#define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */\n#define ZSTD_VERSION_MINOR    2    /* for new (non-breaking) interface capabilities */\n#define ZSTD_VERSION_RELEASE  2    /* for tweaks, bug-fixes, or development */\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTD_CCtx_s ZSTD_CCtx;   /* incomplete type */\n\n#if defined (__cplusplus)\n}\n#endif\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Streaming functions\n***************************************/\n\ntypedef struct ZSTDv02_Dctx_s ZSTD_DCtx;\n\n/*\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTD_magicNumber 0xFD2FB522   /* v0.2 (current)*/\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/****************************************************************\n*  Tuning parameters\n****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/* FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/****************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n\n\n/****************************************************************\n*  Byte symbol type\n****************************************************************/\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/****************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n\n/****************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\n\n#define FSE_DECODE_TYPE FSE_decode_t\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\nstatic size_t FSE_buildDTable\n(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* ptr = dt+1;\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)ptr;\n    FSE_DTableHeader DTableH;\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));   /* memcpy(), to avoid strict aliasing warnings */\n    return 0;\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n/******************************************\n*  FSE helper functions\n******************************************/\nstatic unsigned FSE_isError(size_t code) { return ERR_isError(code); }\n\n\n/****************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSE_abs(short a)\n{\n    return (short)(a<0 ? -a : a);\n}\n\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;   /* because dt is unsigned */\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1)\n    {\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n\n    /* select fast mode (static) */\n    if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/******************************************\n*  Helper functions\n******************************************/\nstatic unsigned HUF_isError(size_t code) { return ERR_isError(code); }\n\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUF_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */\n#define HUF_DEFAULT_TABLELOG  HUF_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUF_MAX_SYMBOL_VALUE 255\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\n\n\n/*********************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUF_readStats\n    Read compact Huffman tree, saved by HUF_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    //memset(huffWeight, 0, hwSize);   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BIT_highbit32(weightTotal) + 1;\n    if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BIT_highbit32(rest);\n        U32 lastWeight = BIT_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/**************************/\n/* single-symbol decoding */\n/**************************/\n\nstatic size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* ptr = DTable+1;\n    HUF_DEltX2* const dt = (HUF_DEltX2*)ptr;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BIT_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n    {\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\n\nstatic size_t HUF_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX2* const dt = ((const HUF_DEltX2*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/***************************/\n/* double-symbols decoding */\n/***************************/\n\nstatic void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUF_DEltX4 DElt;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)   /* note : sortedSymbols already skipped */\n    {\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)\n    {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits)   /* enough room for a second symbol */\n        {\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            HUF_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nstatic size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    void* ptr = DTable;\n    HUF_DEltX4* const dt = ((HUF_DEltX4*)ptr) + 1;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        {if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n    HUF_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);\n    else\n    {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n        {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n        }\n    }\n    return 1;\n}\n\n\n#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7))\n    {\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2))\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\n\nstatic size_t HUF_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX4* const dt = ((const HUF_DEltX4*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* quad-symbol decoding           */\n/**********************************/\ntypedef struct { BYTE nbBits; BYTE nbBytes; } HUF_DDescX6;\ntypedef union { BYTE byte[4]; U32 sequence; } HUF_DSeqX6;\n\n/* recursive, up to level 3; may benefit from <template>-like strategy to nest each level inline */\nstatic void HUF_fillDTableX6LevelN(HUF_DDescX6* DDescription, HUF_DSeqX6* DSequence, int sizeLog,\n                           const rankVal_t rankValOrigin, const U32 consumed, const int minWeight, const U32 maxWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize, const U32* rankStart,\n                           const U32 nbBitsBaseline, HUF_DSeqX6 baseSeq, HUF_DDescX6 DDesc)\n{\n    const int scaleLog = nbBitsBaseline - sizeLog;   /* note : targetLog >= (nbBitsBaseline-1), hence scaleLog <= 1 */\n    const int minBits  = nbBitsBaseline - maxWeight;\n    const U32 level = DDesc.nbBytes;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 symbolStartPos, s;\n\n    /* local rankVal, will be modified */\n    memcpy(rankVal, rankValOrigin[consumed], sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i;\n        const U32 skipSize = rankVal[minWeight];\n        for (i = 0; i < skipSize; i++)\n        {\n            DSequence[i] = baseSeq;\n            DDescription[i] = DDesc;\n        }\n    }\n\n    /* fill DTable */\n    DDesc.nbBytes++;\n    symbolStartPos = rankStart[minWeight];\n    for (s=symbolStartPos; s<sortedListSize; s++)\n    {\n        const BYTE symbol = sortedSymbols[s].symbol;\n        const U32  weight = sortedSymbols[s].weight;   /* >= 1 (sorted) */\n        const int  nbBits = nbBitsBaseline - weight;   /* >= 1 (by construction) */\n        const int  totalBits = consumed+nbBits;\n        const U32  start  = rankVal[weight];\n        const U32  length = 1 << (sizeLog-nbBits);\n        baseSeq.byte[level] = symbol;\n        DDesc.nbBits = (BYTE)totalBits;\n\n        if ((level<3) && (sizeLog-totalBits >= minBits))   /* enough room for another symbol */\n        {\n            int nextMinWeight = totalBits + scaleLog;\n            if (nextMinWeight < 1) nextMinWeight = 1;\n            HUF_fillDTableX6LevelN(DDescription+start, DSequence+start, sizeLog-nbBits,\n                           rankValOrigin, totalBits, nextMinWeight, maxWeight,\n                           sortedSymbols, sortedListSize, rankStart,\n                           nbBitsBaseline, baseSeq, DDesc);   /* recursive (max : level 3) */\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            for (i = start; i < end; i++)\n            {\n                DDescription[i] = DDesc;\n                DSequence[i] = baseSeq;\n            }\n        }\n        rankVal[weight] += length;\n    }\n}\n\n\n/* note : same preparation as X4 */\nstatic size_t HUF_readDTableX6 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    rankVal_t rankVal;\n    const U32 memLog = DTable[0];\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n\n    /* fill tables */\n    {\n        void* ptr = DTable+1;\n        HUF_DDescX6* DDescription = (HUF_DDescX6*)(ptr);\n        void* dSeqStart = DTable + 1 + ((size_t)1<<(memLog-1));\n        HUF_DSeqX6* DSequence = (HUF_DSeqX6*)(dSeqStart);\n        HUF_DSeqX6 DSeq;\n        HUF_DDescX6 DDesc;\n        DSeq.sequence = 0;\n        DDesc.nbBits = 0;\n        DDesc.nbBytes = 0;\n        HUF_fillDTableX6LevelN(DDescription, DSequence, memLog,\n                       (const U32 (*)[HUF_ABSOLUTEMAX_TABLELOG + 1])rankVal, 0, 1, maxW,\n                       sortedSymbol, sizeOfSort, rankStart0,\n                       tableLog+1, DSeq, DDesc);\n    }\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX6(void* op, BIT_DStream_t* DStream, const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, ds+val, sizeof(HUF_DSeqX6));\n    BIT_skipBits(DStream, dd[val].nbBits);\n    return dd[val].nbBytes;\n}\n\nstatic U32 HUF_decodeLastSymbolsX6(void* op, const U32 maxL, BIT_DStream_t* DStream,\n                                  const HUF_DDescX6* dd, const HUF_DSeqX6* ds, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    U32 length = dd[val].nbBytes;\n    if (length <= maxL)\n    {\n        memcpy(op, ds+val, length);\n        BIT_skipBits(DStream, dd[val].nbBits);\n        return length;\n    }\n    memcpy(op, ds+val, maxL);\n    if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n    {\n        BIT_skipBits(DStream, dd[val].nbBits);\n        if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n            DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }\n    return maxL;\n}\n\n\n#define HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX6(ptr, DStreamPtr, dd, ds, dtLog)\n\n#define HUF_DECODE_SYMBOLX6_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX6_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX6_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX6(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const U32* DTable, const U32 dtLog)\n{\n    const void* ddPtr = DTable+1;\n    const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr);\n    const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1));\n    const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr);\n    BYTE* const pStart = p;\n\n    /* up to 16 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-16))\n    {\n        HUF_DECODE_SYMBOLX6_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX6_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX6_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX6_0(p, bitDPtr);\n    }\n\n    /* closer to the end, up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n        HUF_DECODE_SYMBOLX6_0(p, bitDPtr);\n\n    while (p <= pEnd-4)\n        HUF_DECODE_SYMBOLX6_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    while (p < pEnd)\n        p += HUF_decodeLastSymbolsX6(p, (U32)(pEnd-p), bitDPtr, dd, ds, dtLog);\n\n    return p-pStart;\n}\n\n\n\nstatic size_t HUF_decompress4X6_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const U32 dtLog = DTable[0];\n        const void* ddPtr = DTable+1;\n        const HUF_DDescX6* dd = (const HUF_DDescX6*)(ddPtr);\n        const void* dsPtr = DTable + 1 + ((size_t)1<<(dtLog-1));\n        const HUF_DSeqX6* ds = (const HUF_DSeqX6*)(dsPtr);\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-64 symbols per loop (4-16 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (op3 <= opStart4) && (endSignal==BIT_DStream_unfinished) && (op4<=(oend-16)) ; )\n        {\n            HUF_DECODE_SYMBOLX6_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX6_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX6_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX6_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX6_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX6_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX6_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX6(op1, &bitD1, opStart2, DTable, dtLog);\n        HUF_decodeStreamX6(op2, &bitD2, opStart3, DTable, dtLog);\n        HUF_decodeStreamX6(op3, &bitD3, opStart4, DTable, dtLog);\n        HUF_decodeStreamX6(op4, &bitD4, oend,     DTable, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X6 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX6(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX6 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X6_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* Generic decompression selector */\n/**********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nstatic size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, HUF_decompress4X6 };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n    if (Dtime[2] < Dtime[algoNb]) algoNb = 2;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);   /* multi-streams single-symbol decoding */\n    //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize);   /* multi-streams double-symbols decoding */\n    //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize);   /* multi-streams quad-symbols decoding */\n}\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n*  MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*/\n#define ZSTD_MEMORY_USAGE 17\n\n/*!\n * HEAPMODE :\n * Select how default compression functions will allocate memory for their hash table,\n * in memory stack (0, fastest), or in memory heap (1, requires malloc())\n * Note that compression context is fairly large, as a consequence heap memory is recommended.\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif /* ZSTD_HEAPMODE */\n\n/*!\n*  LEGACY_SUPPORT :\n*  decompressor can decode older formats (starting from Zstd 0.1+)\n*/\n#ifndef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 1\n#endif\n\n\n/* *******************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/* *******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef __AVX2__\n#  include <immintrin.h>   /* AVX2 intrinsics */\n#endif\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/* *******************************************************\n*  Constants\n*********************************************************/\n#define HASH_LOG (ZSTD_MEMORY_USAGE - 2)\n#define HASH_TABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASH_TABLESIZE - 1)\n\n#define KNUTH 2654435761\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)\n#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)\n#define IS_RAW BIT0\n#define IS_RLE BIT1\n\n#define WORKPLACESIZE (BLOCKSIZE*3)\n#define MINMATCH 4\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits )-1)\n#define MaxLL  ((1<<LLbits )-1)\n#define MaxOff   31\n#define LitFSELog  11\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MAX(a,b) ((a)<(b)?(b):(a))\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define LITERAL_NOENTROPY 63\n#define COMMAND_NOENTROPY 7   /* to remove */\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize = 4;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\nstatic void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do COPY8(op, ip) while (op < oend);\n}\n\n\n/* **************************************\n*  Local structures\n****************************************/\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n} SeqStore_t;\n\n\n/* *************************************\n*  Error Management\n***************************************/\n/*! ZSTD_isError\n*   tells if a return value is an error code */\nstatic unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\nstruct ZSTDv02_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    void* previousDstEnd;\n    void* base;\n    size_t expected;\n    blockType_t bType;\n    U32 phase;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];\n};   /* typedef'd to ZSTD_Dctx within \"zstd_static.h\" */\n\n\nstatic size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\nstatic size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/** ZSTD_decompressLiterals\n    @return : nb of bytes read from src, or an error code*/\nstatic size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,\n                                const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n    const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n\n    if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);\n    if (litCSize + 5 > srcSize) return ERROR(corruption_detected);\n\n    if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);\n\n    *maxDstSizePtr = litSize;\n    return litCSize + 5;\n}\n\n\n/** ZSTD_decodeLiteralsBlock\n    @return : nb of bytes read from src (< srcSize )*/\nstatic size_t ZSTD_decodeLiteralsBlock(void* ctx,\n                          const void* src, size_t srcSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* const istart = (const BYTE* const)src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(*istart & 3)\n    {\n    default:\n    case 0:\n        {\n            size_t litSize = BLOCKSIZE;\n            const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, 8);\n            return readSize;   /* works if it's an error too */\n        }\n    case IS_RAW:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */\n            {\n                if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n                if (litSize > srcSize-3) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, 8);\n                return litSize+3;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+3;\n            dctx->litSize = litSize;\n            return litSize+3;\n        }\n    case IS_RLE:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[3], litSize + 8);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return 4;\n        }\n    }\n}\n\n\nstatic size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = MEM_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    seqState->prevOffset = seq->offset;\n    if (litLength == MaxLL)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else if (dumps + 3 <= de)\n        {\n            litLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {\n        static const size_t offsetPrefix[MaxOff+1] = {  /* note : size_t faster than U32 */\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));   /* <= maxOff, by table construction */\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* cmove */\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 3 <= de)\n        {\n            matchLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                BYTE* const base, BYTE* const oend)\n{\n    static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */\n    static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */\n    const BYTE* const ostart = op;\n    BYTE* const oLitEnd = op + sequence.litLength;\n    BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use the pointer check */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n    if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    {\n        const BYTE* match = op - sequence.offset;\n\n        /* check */\n        if (sequence.offset > (size_t)op) return ERROR(corruption_detected);   /* address space overflow test (this test seems kept by clang optimizer) */\n        //if (match > op) return ERROR(corruption_detected);   /* address space overflow test (is clang optimizer removing this test ?) */\n        if (match < base) return ERROR(corruption_detected);\n\n        /* close range match, overlap */\n        if (sequence.offset < 8)\n        {\n            const int dec64 = dec64table[sequence.offset];\n            op[0] = match[0];\n            op[1] = match[1];\n            op[2] = match[2];\n            op[3] = match[3];\n            match += dec32table[sequence.offset];\n            ZSTD_copy4(op+4, match);\n            match -= dec64;\n        }\n        else\n        {\n            ZSTD_copy8(op, match);\n        }\n        op += 8; match += 8;\n\n        if (oMatchEnd > oend-(16-MINMATCH))\n        {\n            if (op < oend_8)\n            {\n                ZSTD_wildcopy(op, match, oend_8 - op);\n                match += oend_8 - op;\n                op = oend_8;\n            }\n            while (op < oMatchEnd) *op++ = *match++;\n        }\n        else\n        {\n            ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n        }\n    }\n\n    return oMatchEnd - ostart;\n}\n\nstatic size_t ZSTD_decompressSequences(\n                               void* ctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq;\n    const BYTE* dumps;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    BYTE* const base = (BYTE*) (dctx->base);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTD_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = 1;\n        errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (nbSeq>0) ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);\n            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */\n        if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (litPtr > litEnd) return ERROR(corruption_detected);\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memmove(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic size_t ZSTD_decompressBlock(\n                            void* ctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    /* Decode literals sub-block */\n    size_t litCSize = ZSTD_decodeLiteralsBlock(ctx, src, srcSize);\n    if (ZSTD_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize);\n}\n\n\nstatic size_t ZSTD_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTD_decompressBlock(ctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTD_copyUncompressedBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTD_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\nstatic size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    ZSTD_DCtx ctx;\n    ctx.base = dst;\n    return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/*******************************\n*  Streaming Decompression API\n*******************************/\n\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize;\n    dctx->phase = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    return 0;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTD_resetDCtx(dctx);\n    return dctx;\n}\n\nstatic size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    if (dst != ctx->previousDstEnd)  /* not contiguous */\n        ctx->base = dst;\n\n    /* Decompress : frame header */\n    if (ctx->phase == 0)\n    {\n        /* Check frame magic header */\n        U32 magicNumber = MEM_readLE32(src);\n        if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        return 0;\n    }\n\n    /* Decompress : block header */\n    if (ctx->phase == 1)\n    {\n        blockProperties_t bp;\n        size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n        if (ZSTD_isError(blockSize)) return blockSize;\n        if (bp.blockType == bt_end)\n        {\n            ctx->expected = 0;\n            ctx->phase = 0;\n        }\n        else\n        {\n            ctx->expected = blockSize;\n            ctx->bType = bp.blockType;\n            ctx->phase = 2;\n        }\n\n        return 0;\n    }\n\n    /* Decompress : block content */\n    {\n        size_t rSize;\n        switch(ctx->bType)\n        {\n        case bt_compressed:\n            rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);\n            break;\n        case bt_raw :\n            rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet handled */\n            break;\n        case bt_end :   /* should never happen (filtered at phase 1) */\n            rSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        if (ZSTD_isError(rSize)) return rSize;\n        ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);\n        return rSize;\n    }\n\n}\n\n\n/* wrapper layer */\n\nunsigned ZSTDv02_isError(size_t code)\n{\n    return ZSTD_isError(code);\n}\n\nsize_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize)\n{\n    return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);\n}\n\nZSTDv02_Dctx* ZSTDv02_createDCtx(void)\n{\n    return (ZSTDv02_Dctx*)ZSTD_createDCtx();\n}\n\nsize_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx)\n{\n    return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx)\n{\n    return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx)\n{\n    return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v02.h",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V02_H_4174539423\n#define ZSTD_V02_H_4174539423\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv02_decompress() : decompress ZSTD frames compliant with v0.2.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv02_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv02_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.2.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\nvoid ZSTDv02_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/**\nZSTDv02_isError() : tells if the result of ZSTDv02_decompress() is an error\n*/\nunsigned ZSTDv02_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv02_Dctx_s ZSTDv02_Dctx;\nZSTDv02_Dctx* ZSTDv02_createDCtx(void);\nsize_t ZSTDv02_freeDCtx(ZSTDv02_Dctx* dctx);\n\nsize_t ZSTDv02_decompressDCtx(void* ctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n/* *************************************\n*  Streaming functions\n***************************************/\nsize_t ZSTDv02_resetDCtx(ZSTDv02_Dctx* dctx);\n\nsize_t ZSTDv02_nextSrcSizeToDecompress(ZSTDv02_Dctx* dctx);\nsize_t ZSTDv02_decompressContinue(ZSTDv02_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv02_magicNumber 0xFD2FB522   /* v0.2 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V02_H_4174539423 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v03.c",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include \"zstd_v03.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write16(memPtr, val);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n\n/* ******************************************************************\n   bitstream\n   Part of NewGen Entropy library\n   header file (to include)\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/**********************************************\n*  bitStream decompression API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,\n               BIT_DStream_endOfBuffer = 1,\n               BIT_DStream_completed = 2,\n               BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n\n/******************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/****************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BIT_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/**********************************************************\n* bitStream decoding\n**********************************************************/\n\n/*!BIT_initDStream\n*  Initialize a BIT_DStream_t.\n*  @bitD : a pointer to an already allocated BIT_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t))   /* normal case */\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);\n                    /* fallthrough */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);\n                    /* fallthrough */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);\n                    /* fallthrough */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24;\n                    /* fallthrough */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16;\n                    /* fallthrough */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8;\n                    /* fallthrough */\n            default:;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\nMEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BIT_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BIT_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBitsFast(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BIT_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BIT_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   Error codes and messages\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef ERROR_H_MODULE\n#define ERROR_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define ERR_STATIC static inline\n#elif defined(_MSC_VER)\n#  define ERR_STATIC static __inline\n#elif defined(__GNUC__)\n#  define ERR_STATIC static __attribute__((unused))\n#else\n#  define ERR_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/******************************************\n*  Error Management\n******************************************/\n#define PREFIX(name) ZSTD_error_##name\n\n#define ERROR(name) (size_t)-PREFIX(name)\n\n#define ERROR_LIST(ITEM) \\\n        ITEM(PREFIX(No_Error)) ITEM(PREFIX(GENERIC)) \\\n        ITEM(PREFIX(dstSize_tooSmall)) ITEM(PREFIX(srcSize_wrong)) \\\n        ITEM(PREFIX(prefix_unknown)) ITEM(PREFIX(corruption_detected)) \\\n        ITEM(PREFIX(tableLog_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooLarge)) ITEM(PREFIX(maxSymbolValue_tooSmall)) \\\n        ITEM(PREFIX(maxCode))\n\n#define ERROR_GENERATE_ENUM(ENUM) ENUM,\ntypedef enum { ERROR_LIST(ERROR_GENERATE_ENUM) } ERR_codes;  /* enum is exposed, to detect & handle specific errors; compare function result to -enum value */\n\n#define ERROR_CONVERTTOSTRING(STRING) #STRING,\n#define ERROR_GENERATE_STRING(EXPR) ERROR_CONVERTTOSTRING(EXPR)\nstatic const char* ERR_strings[] = { ERROR_LIST(ERROR_GENERATE_STRING) };\n\nERR_STATIC unsigned ERR_isError(size_t code) { return (code > ERROR(maxCode)); }\n\nERR_STATIC const char* ERR_getErrorName(size_t code)\n{\n    static const char* codeError = \"Unspecified error code\";\n    if (ERR_isError(code)) return ERR_strings[-(int)(code)];\n    return codeError;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ERROR_H_MODULE */\n/*\nConstructor and Destructor of type FSE_CTable\n    Note that its size depends on 'tableLog' and 'maxSymbolValue' */\ntypedef unsigned FSE_CTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Static allocation\n******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) (size + (size>>7))\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* You can statically allocate FSE CTable/DTable as a table of unsigned using below macro */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/******************************************\n*  FSE advanced API\n******************************************/\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);\n/* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);\n/* build a fake FSE_DTable, designed to always generate the same symbolValue */\n\n\n/******************************************\n*  FSE symbol decompression API\n******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n\n/******************************************\n*  FSE unsafe API\n******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/******************************************\n*  Implementation of inline functions\n******************************************/\n\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/******************************************\n*  Static allocation macros\n******************************************/\n/* Huff0 buffer bounds */\n#define HUF_CTABLEBOUND 129\n#define HUF_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n#define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of Huff0's DTable */\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))  /* nb Cells; use unsigned short for X2, unsigned int for X4 */\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/******************************************\n*  Advanced functions\n******************************************/\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n/*\n    zstd - standard compression library\n    Header File\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Version\n***************************************/\n#define ZSTD_VERSION_MAJOR    0    /* for breaking interface changes  */\n#define ZSTD_VERSION_MINOR    2    /* for new (non-breaking) interface capabilities */\n#define ZSTD_VERSION_RELEASE  2    /* for tweaks, bug-fixes, or development */\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTD_CCtx_s ZSTD_CCtx;   /* incomplete type */\n\n#if defined (__cplusplus)\n}\n#endif\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Streaming functions\n***************************************/\n\ntypedef struct ZSTDv03_Dctx_s ZSTD_DCtx;\n\n/*\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTD_magicNumber 0xFD2FB523   /* v0.3 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/****************************************************************\n*  Tuning parameters\n****************************************************************/\n/* MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/* FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/****************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n\n\n/****************************************************************\n*  Byte symbol type\n****************************************************************/\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/****************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n\n/****************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\n\n/* Function templates */\n\n#define FSE_DECODE_TYPE FSE_decode_t\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\nstatic size_t FSE_buildDTable\n(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* ptr = dt+1;\n    FSE_DTableHeader DTableH;\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*)ptr;\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));\n    return 0;\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n/******************************************\n*  FSE helper functions\n******************************************/\nstatic unsigned FSE_isError(size_t code) { return ERR_isError(code); }\n\n\n/****************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSE_abs(short a)\n{\n    return a<0 ? -a : a;\n}\n\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const cell = (FSE_decode_t*)(ptr) + 1;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)(ptr) + 1;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1)\n    {\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n\n    /* select fast mode (static) */\n    if (DTableH.fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/****************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n/****************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n/****************************************************************\n*  Error Management\n****************************************************************/\n#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/******************************************\n*  Helper functions\n******************************************/\nstatic unsigned HUF_isError(size_t code) { return ERR_isError(code); }\n\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUF_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */\n#define HUF_DEFAULT_TABLELOG  HUF_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUF_MAX_SYMBOL_VALUE 255\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\n\n\n/*********************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUF_readStats\n    Read compact Huffman tree, saved by HUF_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    //memset(huffWeight, 0, hwSize);   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BIT_highbit32(weightTotal) + 1;\n    if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BIT_highbit32(rest);\n        U32 lastWeight = BIT_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/**************************/\n/* single-symbol decoding */\n/**************************/\n\nstatic size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* ptr = DTable+1;\n    HUF_DEltX2* const dt = (HUF_DEltX2*)(ptr);\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BIT_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n    {\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\n\nstatic size_t HUF_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX2* const dt = ((const HUF_DEltX2*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/***************************/\n/* double-symbols decoding */\n/***************************/\n\nstatic void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUF_DEltX4 DElt;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)   /* note : sortedSymbols already skipped */\n    {\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)\n    {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits)   /* enough room for a second symbol */\n        {\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            HUF_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nstatic size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize = ip[0];\n    void* ptr = DTable;\n    HUF_DEltX4* const dt = ((HUF_DEltX4*)ptr) + 1;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n    HUF_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);\n    else\n    {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n        {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n        }\n    }\n    return 1;\n}\n\n\n#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7))\n    {\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2))\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\n\nstatic size_t HUF_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n\n        const void* ptr = DTable;\n        const HUF_DEltX4* const dt = ((const HUF_DEltX4*)ptr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* Generic decompression selector */\n/**********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nstatic size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, NULL };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);   /* multi-streams single-symbol decoding */\n    //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize);   /* multi-streams double-symbols decoding */\n    //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize);   /* multi-streams quad-symbols decoding */\n}\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n*  MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*/\n#define ZSTD_MEMORY_USAGE 17\n\n/*!\n * HEAPMODE :\n * Select how default compression functions will allocate memory for their hash table,\n * in memory stack (0, fastest), or in memory heap (1, requires malloc())\n * Note that compression context is fairly large, as a consequence heap memory is recommended.\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif /* ZSTD_HEAPMODE */\n\n/*!\n*  LEGACY_SUPPORT :\n*  decompressor can decode older formats (starting from Zstd 0.1+)\n*/\n#ifndef ZSTD_LEGACY_SUPPORT\n#  define ZSTD_LEGACY_SUPPORT 1\n#endif\n\n\n/* *******************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/* *******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef __AVX2__\n#  include <immintrin.h>   /* AVX2 intrinsics */\n#endif\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#else\n#  define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n#endif\n\n\n/* *******************************************************\n*  Constants\n*********************************************************/\n#define HASH_LOG (ZSTD_MEMORY_USAGE - 2)\n#define HASH_TABLESIZE (1 << HASH_LOG)\n#define HASH_MASK (HASH_TABLESIZE - 1)\n\n#define KNUTH 2654435761\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)\n#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)\n#define IS_RAW BIT0\n#define IS_RLE BIT1\n\n#define WORKPLACESIZE (BLOCKSIZE*3)\n#define MINMATCH 4\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits )-1)\n#define MaxLL  ((1<<LLbits )-1)\n#define MaxOff   31\n#define LitFSELog  11\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MAX(a,b) ((a)<(b)?(b):(a))\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define LITERAL_NOENTROPY 63\n#define COMMAND_NOENTROPY 7   /* to remove */\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize = 4;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void   ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\nstatic void   ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do COPY8(op, ip) while (op < oend);\n}\n\n\n/* **************************************\n*  Local structures\n****************************************/\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n} SeqStore_t;\n\n\n/* *************************************\n*  Error Management\n***************************************/\n/*! ZSTD_isError\n*   tells if a return value is an error code */\nstatic unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\nstruct ZSTDv03_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    void* previousDstEnd;\n    void* base;\n    size_t expected;\n    blockType_t bType;\n    U32 phase;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];\n};   /* typedef'd to ZSTD_Dctx within \"zstd_static.h\" */\n\n\nstatic size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\nstatic size_t ZSTD_copyUncompressedBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/** ZSTD_decompressLiterals\n    @return : nb of bytes read from src, or an error code*/\nstatic size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,\n                                const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n    const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n\n    if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);\n    if (litCSize + 5 > srcSize) return ERROR(corruption_detected);\n\n    if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);\n\n    *maxDstSizePtr = litSize;\n    return litCSize + 5;\n}\n\n\n/** ZSTD_decodeLiteralsBlock\n    @return : nb of bytes read from src (< srcSize )*/\nstatic size_t ZSTD_decodeLiteralsBlock(void* ctx,\n                          const void* src, size_t srcSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* const istart = (const BYTE* const)src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(*istart & 3)\n    {\n    default:\n    case 0:\n        {\n            size_t litSize = BLOCKSIZE;\n            const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, 8);\n            return readSize;   /* works if it's an error too */\n        }\n    case IS_RAW:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */\n            {\n                if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n                if (litSize > srcSize-3) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, 8);\n                return litSize+3;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+3;\n            dctx->litSize = litSize;\n            return litSize+3;\n        }\n    case IS_RLE:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[3], litSize + 8);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return 4;\n        }\n    }\n}\n\n\nstatic size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = MEM_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL and MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    seqState->prevOffset = seq->offset;\n    if (litLength == MaxLL)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else if (dumps + 3 <= de)\n        {\n            litLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {\n        static const size_t offsetPrefix[MaxOff+1] = {  /* note : size_t faster than U32 */\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));   /* <= maxOff, by table construction */\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* cmove */\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML)\n    {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 3 <= de)\n        {\n            matchLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) dumps = de-1;   /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                BYTE* const base, BYTE* const oend)\n{\n    static const int dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4};   /* added */\n    static const int dec64table[] = {8, 8, 8, 7, 8, 9,10,11};   /* subtracted */\n    const BYTE* const ostart = op;\n    BYTE* const oLitEnd = op + sequence.litLength;\n    BYTE* const oMatchEnd = op + sequence.litLength + sequence.matchLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n    if (sequence.offset > (U32)(oLitEnd - base)) return ERROR(corruption_detected);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    {   const BYTE* match = op - sequence.offset;\n\n        /* check */\n        if (sequence.offset > (size_t)op) return ERROR(corruption_detected);   /* address space overflow test (this test seems kept by clang optimizer) */\n        //if (match > op) return ERROR(corruption_detected);   /* address space overflow test (is clang optimizer removing this test ?) */\n        if (match < base) return ERROR(corruption_detected);\n\n        /* close range match, overlap */\n        if (sequence.offset < 8)\n        {\n            const int dec64 = dec64table[sequence.offset];\n            op[0] = match[0];\n            op[1] = match[1];\n            op[2] = match[2];\n            op[3] = match[3];\n            match += dec32table[sequence.offset];\n            ZSTD_copy4(op+4, match);\n            match -= dec64;\n        }\n        else\n        {\n            ZSTD_copy8(op, match);\n        }\n        op += 8; match += 8;\n\n        if (oMatchEnd > oend-(16-MINMATCH))\n        {\n            if (op < oend_8)\n            {\n                ZSTD_wildcopy(op, match, oend_8 - op);\n                match += oend_8 - op;\n                op = oend_8;\n            }\n            while (op < oMatchEnd) *op++ = *match++;\n        }\n        else\n        {\n            ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n        }\n    }\n\n    return oMatchEnd - ostart;\n}\n\nstatic size_t ZSTD_decompressSequences(\n                               void* ctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)ctx;\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq;\n    const BYTE* dumps;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    BYTE* const base = (BYTE*) (dctx->base);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTD_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = sequence.offset = 4;\n        errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (nbSeq>0) ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, sequence, &litPtr, litEnd, base, oend);\n            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* requested too much : data is corrupted */\n        if (nbSeq<0) return ERROR(corruption_detected);   /* requested too many sequences : data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (litPtr > litEnd) return ERROR(corruption_detected);\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memmove(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic size_t ZSTD_decompressBlock(\n                            void* ctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    /* Decode literals sub-block */\n    size_t litCSize = ZSTD_decodeLiteralsBlock(ctx, src, srcSize);\n    if (ZSTD_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTD_decompressSequences(ctx, dst, maxDstSize, ip, srcSize);\n}\n\n\nstatic size_t ZSTD_decompressDCtx(void* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTD_decompressBlock(ctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTD_copyUncompressedBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTD_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\nstatic size_t ZSTD_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    ZSTD_DCtx ctx;\n    ctx.base = dst;\n    return ZSTD_decompressDCtx(&ctx, dst, maxDstSize, src, srcSize);\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nMEM_STATIC void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    U32 magicNumber;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize+ZSTD_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_magicNumber) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize; remainingSize -= ZSTD_frameHeaderSize;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n\n/*******************************\n*  Streaming Decompression API\n*******************************/\n\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize;\n    dctx->phase = 0;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    return 0;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTD_resetDCtx(dctx);\n    return dctx;\n}\n\nstatic size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    if (dst != ctx->previousDstEnd)  /* not contiguous */\n        ctx->base = dst;\n\n    /* Decompress : frame header */\n    if (ctx->phase == 0)\n    {\n        /* Check frame magic header */\n        U32 magicNumber = MEM_readLE32(src);\n        if (magicNumber != ZSTD_magicNumber) return ERROR(prefix_unknown);\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        return 0;\n    }\n\n    /* Decompress : block header */\n    if (ctx->phase == 1)\n    {\n        blockProperties_t bp;\n        size_t blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n        if (ZSTD_isError(blockSize)) return blockSize;\n        if (bp.blockType == bt_end)\n        {\n            ctx->expected = 0;\n            ctx->phase = 0;\n        }\n        else\n        {\n            ctx->expected = blockSize;\n            ctx->bType = bp.blockType;\n            ctx->phase = 2;\n        }\n\n        return 0;\n    }\n\n    /* Decompress : block content */\n    {\n        size_t rSize;\n        switch(ctx->bType)\n        {\n        case bt_compressed:\n            rSize = ZSTD_decompressBlock(ctx, dst, maxDstSize, src, srcSize);\n            break;\n        case bt_raw :\n            rSize = ZSTD_copyUncompressedBlock(dst, maxDstSize, src, srcSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet handled */\n            break;\n        case bt_end :   /* should never happen (filtered at phase 1) */\n            rSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);\n        }\n        ctx->phase = 1;\n        ctx->expected = ZSTD_blockHeaderSize;\n        if (ZSTD_isError(rSize)) return rSize;\n        ctx->previousDstEnd = (void*)( ((char*)dst) + rSize);\n        return rSize;\n    }\n\n}\n\n\n/* wrapper layer */\n\nunsigned ZSTDv03_isError(size_t code)\n{\n    return ZSTD_isError(code);\n}\n\nsize_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize)\n{\n    return ZSTD_decompress(dst, maxOriginalSize, src, compressedSize);\n}\n\nZSTDv03_Dctx* ZSTDv03_createDCtx(void)\n{\n    return (ZSTDv03_Dctx*)ZSTD_createDCtx();\n}\n\nsize_t ZSTDv03_freeDCtx(ZSTDv03_Dctx* dctx)\n{\n    return ZSTD_freeDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv03_resetDCtx(ZSTDv03_Dctx* dctx)\n{\n    return ZSTD_resetDCtx((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv03_nextSrcSizeToDecompress(ZSTDv03_Dctx* dctx)\n{\n    return ZSTD_nextSrcSizeToDecompress((ZSTD_DCtx*)dctx);\n}\n\nsize_t ZSTDv03_decompressContinue(ZSTDv03_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompressContinue((ZSTD_DCtx*)dctx, dst, maxDstSize, src, srcSize);\n}\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v03.h",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V03_H_298734209782\n#define ZSTD_V03_H_298734209782\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv03_decompress() : decompress ZSTD frames compliant with v0.3.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv03_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv03_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.3.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\n void ZSTDv03_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                      size_t* cSize, unsigned long long* dBound);\n\n    /**\nZSTDv03_isError() : tells if the result of ZSTDv03_decompress() is an error\n*/\nunsigned ZSTDv03_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv03_Dctx_s ZSTDv03_Dctx;\nZSTDv03_Dctx* ZSTDv03_createDCtx(void);\nsize_t ZSTDv03_freeDCtx(ZSTDv03_Dctx* dctx);\n\nsize_t ZSTDv03_decompressDCtx(void* ctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n/* *************************************\n*  Streaming functions\n***************************************/\nsize_t ZSTDv03_resetDCtx(ZSTDv03_Dctx* dctx);\n\nsize_t ZSTDv03_nextSrcSizeToDecompress(ZSTDv03_Dctx* dctx);\nsize_t ZSTDv03_decompressContinue(ZSTDv03_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv03_magicNumber 0xFD2FB523   /* v0.3 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V03_H_298734209782 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v04.c",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n /******************************************\n *  Includes\n ******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n#include \"zstd_v04.h\"\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n/* ******************************************************************\n *   mem.h\n *******************************************************************/\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/******************************************\n*  Compiler-specific\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/****************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-*************************************\n*  Debug\n***************************************/\n#include \"../common/debug.h\"\n#ifndef assert\n#  define assert(condition) ((void)0)\n#endif\n\n\n/****************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian())\n    {\n        MEM_write16(memPtr, val);\n    }\n    else\n    {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE24(const void* memPtr)\n{\n    return MEM_readLE16(memPtr) + (((const BYTE*)memPtr)[2] << 16);\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n    {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n/*\n    zstd - standard compression library\n    Header File for static linking only\n*/\n#ifndef ZSTD_STATIC_H\n#define ZSTD_STATIC_H\n\n\n/* *************************************\n*  Types\n***************************************/\n#define ZSTD_WINDOWLOG_ABSOLUTEMIN 11\n\n/** from faster to stronger */\ntypedef enum { ZSTD_fast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2 } ZSTD_strategy;\n\ntypedef struct\n{\n    U64 srcSize;       /* optional : tells how much bytes are present in the frame. Use 0 if not known. */\n    U32 windowLog;     /* largest match distance : larger == more compression, more memory needed during decompression */\n    U32 contentLog;    /* full search segment : larger == more compression, slower, more memory (useless for fast) */\n    U32 hashLog;       /* dispatch table : larger == more memory, faster */\n    U32 searchLog;     /* nb of searches : larger == more compression, slower */\n    U32 searchLength;  /* size of matches : larger == faster decompression, sometimes less compression */\n    ZSTD_strategy strategy;\n} ZSTD_parameters;\n\ntypedef ZSTDv04_Dctx ZSTD_DCtx;\n\n/* *************************************\n*  Advanced functions\n***************************************/\n/** ZSTD_decompress_usingDict\n*   Same as ZSTD_decompressDCtx, using a Dictionary content as prefix\n*   Note : dict can be NULL, in which case, it's equivalent to ZSTD_decompressDCtx() */\nstatic size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx,\n                                             void* dst, size_t maxDstSize,\n                                       const void* src, size_t srcSize,\n                                       const void* dict,size_t dictSize);\n\n\n/* **************************************\n*  Streaming functions (direct mode)\n****************************************/\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx);\nstatic size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize);\nstatic void   ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* src, size_t srcSize);\n\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n\n/**\n  Streaming decompression, bufferless mode\n\n  A ZSTD_DCtx object is required to track streaming operations.\n  Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.\n  A ZSTD_DCtx object can be re-used multiple times. Use ZSTD_resetDCtx() to return to fresh status.\n\n  First operation is to retrieve frame parameters, using ZSTD_getFrameParams().\n  This function doesn't consume its input. It needs enough input data to properly decode the frame header.\n  Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.\n  Result : 0 when successful, it means the ZSTD_parameters structure has been filled.\n           >0 : means there is not enough data into src. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTD_isError() (For example, if it's not a ZSTD header)\n\n  Then, you can optionally insert a dictionary.\n  This operation must mimic the compressor behavior, otherwise decompression will fail or be corrupted.\n\n  Then it's possible to start decompression.\n  Use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() requires this exact amount of bytes, or it will fail.\n  ZSTD_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).\n  They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.\n\n  @result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n\n  A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n*/\n\n\n\n\n#endif  /* ZSTD_STATIC_H */\n\n\n/*\n    zstd_internal - common functions to include\n    Header File for include\n*/\n#ifndef ZSTD_CCOMMON_H_MODULE\n#define ZSTD_CCOMMON_H_MODULE\n\n/* *************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/* *************************************\n*  Common constants\n***************************************/\n#define ZSTD_MAGICNUMBER 0xFD2FB524   /* v0.4 */\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n\nstatic const size_t ZSTD_blockHeaderSize = 3;\nstatic const size_t ZSTD_frameHeaderSize_min = 5;\n#define ZSTD_frameHeaderSize_max 5         /* define, for static allocation */\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define IS_RAW BIT0\n#define IS_RLE BIT1\n\n#define MINMATCH 4\n#define REPCODE_STARTVALUE 4\n\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxML  ((1<<MLbits) - 1)\n#define MaxLL  ((1<<LLbits) - 1)\n#define MaxOff ((1<<Offbits)- 1)\n#define MLFSELog   10\n#define LLFSELog   10\n#define OffFSELog   9\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define MIN_SEQUENCES_SIZE (2 /*seqNb*/ + 2 /*dumps*/ + 3 /*seqTables*/ + 1 /*bitStream*/)\n#define MIN_CBLOCK_SIZE (3 /*litCSize*/ + MIN_SEQUENCES_SIZE)\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n\n/* ******************************************\n*  Shared functions to include for inlining\n********************************************/\nstatic void ZSTD_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTD_wildcopy : custom version of memcpy(), can copy up to 7-8 bytes too many */\nstatic void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file\n****************************************************************** */\n#ifndef FSE_H\n#define FSE_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n\n\n/* *****************************************\n*  FSE simple functions\n******************************************/\nstatic size_t FSE_decompress(void* dst,  size_t maxDstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nFSE_decompress():\n    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'maxDstSize'.\n    return : size of regenerated data (<= maxDstSize)\n             or an error code, which can be tested using FSE_isError()\n\n    ** Important ** : FSE_decompress() doesn't decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\n\n\n/* *****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nstatic unsigned    FSE_isError(size_t code);        /* tells if a return value is an error code */\n\n\n\n/* *****************************************\n*  FSE detailed API\n******************************************/\n/*!\nFSE_compress() does the following:\n1. count symbol occurrence from source[] into table count[]\n2. normalize counters so that sum(count[]) == Power_of_2 (2^tableLog)\n3. save normalized counters to memory buffer using writeNCount()\n4. build encoding table 'CTable' from normalized counters\n5. encode the data stream using encoding table 'CTable'\n\nFSE_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*!\nFSE_readNCount():\n   Read compactly saved 'normalizedCounter' from 'rBuffer'.\n   return : size read from 'rBuffer'\n            or an errorCode, which can be tested using FSE_isError()\n            maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nstatic  size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*!\nConstructor and Destructor of type FSE_DTable\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSE_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\n\n/*!\nFSE_buildDTable():\n   Builds 'dt', which must be already allocated, using FSE_createDTable()\n   return : 0,\n            or an errorCode, which can be tested using FSE_isError() */\nstatic size_t FSE_buildDTable ( FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*!\nFSE_decompress_usingDTable():\n   Decompress compressed source 'cSrc' of size 'cSrcSize' using 'dt'\n   into 'dst' which must be already allocated.\n   return : size of regenerated data (necessarily <= maxDstSize)\n            or an errorCode, which can be tested using FSE_isError() */\nstatic  size_t FSE_decompress_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const FSE_DTable* dt);\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSE_readNCount() if it was saved using FSE_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSE_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSE_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\nThe next step is to build the decompression tables 'FSE_DTable' from 'normalizedCounter'.\nThis is performed by the function FSE_buildDTable().\nThe space required by 'FSE_DTable' must be already allocated using FSE_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSE_isError().\n\n'FSE_DTable' can then be used to decompress 'cSrc', with FSE_decompress_usingDTable().\n'cSrcSize' must be strictly correct, otherwise decompression will fail.\nFSE_decompress_usingDTable() result will tell how many bytes were regenerated (<=maxDstSize).\nIf there is an error, the function will return an error code, which can be tested using FSE_isError(). (ex: dst buffer too small)\n*/\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSE_H */\n\n\n/* ******************************************************************\n   bitstream\n   Part of NewGen Entropy library\n   header file (to include)\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n/**********************************************\n*  bitStream decompression API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BIT_DStream_t;\n\ntypedef enum { BIT_DStream_unfinished = 0,\n               BIT_DStream_endOfBuffer = 1,\n               BIT_DStream_completed = 2,\n               BIT_DStream_overflow = 3 } BIT_DStream_status;  /* result of BIT_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD);\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* bitD);\n\n\n\n\n/******************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/****************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BIT_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n/**********************************************************\n* bitStream decoding\n**********************************************************/\n\n/*!BIT_initDStream\n*  Initialize a BIT_DStream_t.\n*  @bitD : a pointer to an already allocated BIT_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t))   /* normal case */\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n    }\n    else\n    {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BIT_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nMEM_STATIC size_t BIT_lookBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BIT_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_lookBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBits(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BIT_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BIT_readBitsFast(BIT_DStream_t* bitD, U32 nbBits)\n{\n    size_t value = BIT_lookBitsFast(bitD, nbBits);\n    BIT_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BIT_DStream_status BIT_reloadDStream(BIT_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BIT_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer))\n    {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BIT_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start)\n    {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BIT_DStream_endOfBuffer;\n        return BIT_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BIT_DStream_status result = BIT_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start)\n        {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BIT_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BIT_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BIT_endOfDStream(const BIT_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n\n\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSE_STATIC_H\n#define FSE_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSE_NCOUNTBOUND 512\n#define FSE_BLOCKBOUND(size) (size + (size>>7))\n#define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */\n#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue)   (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2))\n#define FSE_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSE advanced API\n*******************************************/\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits);\n/* build a fake FSE_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue);\n/* build a fake FSE_DTable, designed to always generate the same symbolValue */\n\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSE_DState_t;\n\n\nstatic void     FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt);\n\nstatic unsigned char FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n\nstatic unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr);\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSE_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSE_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSE_initDState(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD, const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    DStatePtr->state = BIT_readBits(bitD, DTableH.tableLog);\n    BIT_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbol(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSE_decodeSymbolFast(FSE_DState_t* DStatePtr, BIT_DStream_t* bitD)\n{\n    const FSE_decode_t DInfo = ((const FSE_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BIT_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSE_STATIC_H */\n\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSE_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSE_MAX_MEMORY_USAGE 14\n#define FSE_DEFAULT_MEMORY_USAGE 13\n\n/*!FSE_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSE_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSE_FUNCTION_TYPE BYTE\n#define FSE_FUNCTION_EXTENSION\n#define FSE_DECODE_TYPE FSE_decode_t\n\n\n#endif   /* !FSE_COMMONDEFS_ONLY */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Dependencies\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSE_MAX_TABLELOG  (FSE_MAX_MEMORY_USAGE-2)\n#define FSE_MAX_TABLESIZE (1U<<FSE_MAX_TABLELOG)\n#define FSE_MAXTABLESIZE_MASK (FSE_MAX_TABLESIZE-1)\n#define FSE_DEFAULT_TABLELOG (FSE_DEFAULT_MEMORY_USAGE-2)\n#define FSE_MIN_TABLELOG 5\n\n#define FSE_TABLELOG_ABSOLUTE_MAX 15\n#if FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX\n#error \"FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSE_STATIC_ASSERT(c) { enum { FSE_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)];\n\n\n/*-**************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSE_FUNCTION_EXTENSION\n#  error \"FSE_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSE_FUNCTION_TYPE\n#  error \"FSE_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSE_CAT(X,Y) X##Y\n#define FSE_FUNCTION_NAME(X,Y) FSE_CAT(X,Y)\n#define FSE_TYPE_NAME(X,Y) FSE_CAT(X,Y)\n\nstatic U32 FSE_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\n\nstatic size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    FSE_DTableHeader DTableH;\n    void* const tdPtr = dt+1;   /* because dt is unsigned, 32-bits aligned on 32-bits */\n    FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr);\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSE_tableStep(tableSize);\n    U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    memset(tableDecode, 0, sizeof(FSE_DECODE_TYPE) * (maxSymbolValue+1) );   /* useless init, but keep static analyzer happy, and we don't need to performance optimize legacy decoders */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        if (normalizedCounter[s]==-1)\n        {\n            tableDecode[highThreshold--].symbol = (FSE_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        }\n        else\n        {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n        }\n    }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++)\n        {\n            tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }\n    }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++)\n        {\n            FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BIT_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n        }\n    }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));\n    return 0;\n}\n\n\n#ifndef FSE_COMMONDEFS_ONLY\n/******************************************\n*  FSE helper functions\n******************************************/\nstatic unsigned FSE_isError(size_t code) { return ERR_isError(code); }\n\n\n/****************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSE_abs(short a)\n{\n    return a<0 ? -a : a;\n}\n\nstatic size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr))\n    {\n        if (previous0)\n        {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF)\n            {\n                n0+=24;\n                if (ip < iend-5)\n                {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                }\n                else\n                {\n                    bitStream >>= 16;\n                    bitCount+=16;\n                }\n            }\n            while ((bitStream & 3) == 3)\n            {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n            {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max)\n            {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            }\n            else\n            {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSE_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold)\n            {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            {\n                if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4))\n                {\n                    ip += bitCount>>3;\n                    bitCount &= 7;\n                }\n                else\n                {\n                    bitCount -= (int)(8 * (iend - 4 - ip));\n                    ip = iend - 4;\n                }\n                bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n            }\n        }\n    }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*********************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nstatic size_t FSE_buildDTable_rle (FSE_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSE_decode_t* const cell = (FSE_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nstatic size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSE_DTableHeader* const DTableH = (FSE_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSE_decode_t* const dinfo = (FSE_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++)\n    {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSE_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSE_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BIT_DStream_t bitD;\n    FSE_DState_t state1;\n    FSE_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BIT_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSE_isError(errorCode)) return errorCode;\n\n    FSE_initDState(&state1, &bitD, dt);\n    FSE_initDState(&state2, &bitD, dt);\n\n#define FSE_GETSYMBOL(statePtr) fast ? FSE_decodeSymbolFast(statePtr, &bitD) : FSE_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BIT_reloadDStream(&bitD)==BIT_DStream_unfinished) && (op<olimit) ; op+=4)\n    {\n        op[0] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[1] = FSE_GETSYMBOL(&state2);\n\n        if (FSE_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BIT_reloadDStream(&bitD) > BIT_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSE_GETSYMBOL(&state1);\n\n        if (FSE_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BIT_reloadDStream(&bitD);\n\n        op[3] = FSE_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BIT_reloadDStream(&bitD) >= FSE_DStream_partiallyFilled; Ends at exactly BIT_DStream_completed */\n    while (1)\n    {\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state1);\n\n        if ( (BIT_reloadDStream(&bitD)>BIT_DStream_completed) || (op==omax) || (BIT_endOfDStream(&bitD) && (fast || FSE_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSE_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BIT_endOfDStream(&bitD) && FSE_endOfDState(&state1) && FSE_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nstatic size_t FSE_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSE_DTable* dt)\n{\n    FSE_DTableHeader DTableH;\n    U32 fastMode;\n\n    memcpy(&DTableH, dt, sizeof(DTableH));\n    fastMode = DTableH.fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSE_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nstatic size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSE_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    errorCode = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSE_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSE_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSE_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSE_COMMONDEFS_ONLY */\n\n\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef HUFF0_H\n#define HUFF0_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* ****************************************\n*  Dependency\n******************************************/\n#include <stddef.h>    /* size_t */\n\n\n/* ****************************************\n*  Huff0 simple functions\n******************************************/\nstatic size_t HUF_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nHUF_decompress():\n    Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstSize'.\n    'dstSize' must be the exact size of original (uncompressed) data.\n    Note : in contrast with FSE, HUF_decompress can regenerate RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data, because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize)\n              or an error code, which can be tested using HUF_isError()\n*/\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nstatic unsigned    HUF_isError(size_t code);        /* tells if a return value is an error code */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUFF0_H */\n\n\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef HUFF0_STATIC_H\n#define HUFF0_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* ****************************************\n*  Static allocation macros\n******************************************/\n/* static allocation of Huff0's DTable */\n#define HUF_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))  /* nb Cells; use unsigned short for X2, unsigned int for X4 */\n#define HUF_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUF_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUF_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n/* ****************************************\n*  Huff0 detailed API\n******************************************/\n/*!\nHUF_decompress() does the following:\n1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics\n2. build Huffman table from save, using HUF_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUF_decompressSXn_usingDTable\n\n*/\nstatic size_t HUF_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);\nstatic size_t HUF_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);\n\nstatic size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nstatic size_t HUF_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* HUFF0_STATIC_H */\n\n\n\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n#define HUF_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUF_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */\n#define HUF_DEFAULT_TABLELOG  HUF_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUF_MAX_SYMBOL_VALUE 255\n#if (HUF_MAX_TABLELOG > HUF_ABSOLUTEMAX_TABLELOG)\n#  error \"HUF_MAX_TABLELOG is too large !\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\nstatic unsigned HUF_isError(size_t code) { return ERR_isError(code); }\n#define HUF_STATIC_ASSERT(c) { enum { HUF_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n\n/*-*******************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUF_readStats\n    Read compact Huffman tree, saved by HUF_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    //memset(huffWeight, 0, hwSize);   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  /* special header */\n    {\n        if (iSize >= (242))   /* RLE */\n        {\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else   /* Incompressible */\n        {\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2)\n            {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n            }\n        }\n    }\n    else  /* header compressed with FSE (normal case) */\n    {\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSE_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUF_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++)\n    {\n        if (huffWeight[n] >= HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BIT_highbit32(weightTotal) + 1;\n    if (tableLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BIT_highbit32(rest);\n        U32 lastWeight = BIT_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/**************************/\n/* single-symbol decoding */\n/**************************/\n\nstatic size_t HUF_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    size_t iSize;\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* const dtPtr = DTable + 1;\n    HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    //memset(huffWeight, 0, sizeof(huffWeight));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(huffWeight, HUF_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof DTable, as allocated, from used size of DTable, in case of DTable re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++)\n    {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++)\n    {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUF_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUF_decodeSymbolX2(BIT_DStream_t* Dstream, const HUF_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BIT_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BIT_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUF_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUF_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUF_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, const HUF_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-4))\n    {\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd))\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUF_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\n\nstatic size_t HUF_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUF_DEltX2* const dt = ((const HUF_DEltX2*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX2_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUF_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUF_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/***************************/\n/* double-symbols decoding */\n/***************************/\n\nstatic void HUF_fillDTableX4Level2(HUF_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUF_DEltX4 DElt;\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1)\n    {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)   /* note : sortedSymbols already skipped */\n    {\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUF_ABSOLUTEMAX_TABLELOG][HUF_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUF_fillDTableX4(HUF_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUF_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++)\n    {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits)   /* enough room for a second symbol */\n        {\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUF_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        }\n        else\n        {\n            U32 i;\n            const U32 end = start + length;\n            HUF_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nstatic size_t HUF_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUF_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUF_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUF_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUF_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    size_t iSize;\n    void* dtPtr = DTable;\n    HUF_DEltX4* const dt = ((HUF_DEltX4*)dtPtr) + 1;\n\n    HUF_STATIC_ASSERT(sizeof(HUF_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUF_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    //memset(weightList, 0, sizeof(weightList));   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUF_readStats(weightList, HUF_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUF_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--)\n        { if (!maxW) return ERROR(GENERIC); }  /* necessarily finds a solution before maxW==0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++)\n        {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++)\n        {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++)\n        {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++)\n            {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n            }\n        }\n    }\n\n    HUF_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUF_decodeSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BIT_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUF_decodeLastSymbolX4(void* op, BIT_DStream_t* DStream, const HUF_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BIT_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);\n    else\n    {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8))\n        {\n            BIT_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n        }\n    }\n    return 1;\n}\n\n\n#define HUF_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUF_MAX_TABLELOG<=12)) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUF_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUF_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUF_decodeStreamX4(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd, const HUF_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p < pEnd-7))\n    {\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) && (p <= pEnd-2))\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUF_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUF_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\nstatic size_t HUF_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUF_DEltX4* const dt = ((const HUF_DEltX4*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BIT_DStream_t bitD1;\n        BIT_DStream_t bitD2;\n        BIT_DStream_t bitD3;\n        BIT_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BIT_initDStream(&bitD1, istart1, length1);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD2, istart2, length2);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD3, istart3, length3);\n        if (HUF_isError(errorCode)) return errorCode;\n        errorCode = BIT_initDStream(&bitD4, istart4, length4);\n        if (HUF_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        for ( ; (endSignal==BIT_DStream_unfinished) && (op4<(oend-7)) ; )\n        {\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUF_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUF_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUF_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUF_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BIT_reloadDStream(&bitD1) | BIT_reloadDStream(&bitD2) | BIT_reloadDStream(&bitD3) | BIT_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUF_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUF_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUF_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUF_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BIT_endOfDStream(&bitD1) & BIT_endOfDStream(&bitD2) & BIT_endOfDStream(&bitD3) & BIT_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nstatic size_t HUF_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUF_CREATE_STATIC_DTABLEX4(DTable, HUF_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUF_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUF_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUF_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/**********************************/\n/* Generic decompression selector */\n/**********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nstatic size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUF_decompress4X2, HUF_decompress4X4, NULL };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    //return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize);   /* multi-streams single-symbol decoding */\n    //return HUF_decompress4X4(dst, dstSize, cSrc, cSrcSize);   /* multi-streams double-symbols decoding */\n    //return HUF_decompress4X6(dst, dstSize, cSrc, cSrcSize);   /* multi-streams quad-symbols decoding */\n}\n\n\n\n#endif   /* ZSTD_CCOMMON_H_MODULE */\n\n\n/*\n    zstd - decompression module fo v0.4 legacy format\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTD_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTD_HEAPMODE\n#  define ZSTD_HEAPMODE 1\n#endif\n\n\n/* *******************************************************\n*  Includes\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug : printf */\n\n\n/* *******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/* *************************************\n*  Local types\n***************************************/\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/* *************************************\n*  Error Management\n***************************************/\n\n/*! ZSTD_isError\n*   tells if a return value is an error code */\nstatic unsigned ZSTD_isError(size_t code) { return ERR_isError(code); }\n\n\n/* *************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTD_dStage;\n\nstruct ZSTDv04_Dctx_s\n{\n    U32 LLTable[FSE_DTABLE_SIZE_U32(LLFSELog)];\n    U32 OffTable[FSE_DTABLE_SIZE_U32(OffFSELog)];\n    U32 MLTable[FSE_DTABLE_SIZE_U32(MLFSELog)];\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    size_t headerSize;\n    ZSTD_parameters params;\n    blockType_t bType;\n    ZSTD_dStage stage;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + 8 /* margin for wildcopy */];\n    BYTE headerBuffer[ZSTD_frameHeaderSize_max];\n};  /* typedef'd to ZSTD_DCtx within \"zstd_static.h\" */\n\nstatic size_t ZSTD_resetDCtx(ZSTD_DCtx* dctx)\n{\n    dctx->expected = ZSTD_frameHeaderSize_min;\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    return 0;\n}\n\nstatic ZSTD_DCtx* ZSTD_createDCtx(void)\n{\n    ZSTD_DCtx* dctx = (ZSTD_DCtx*)malloc(sizeof(ZSTD_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTD_resetDCtx(dctx);\n    return dctx;\n}\n\nstatic size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx)\n{\n    free(dctx);\n    return 0;\n}\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\n/** ZSTD_decodeFrameHeader_Part1\n*   decode the 1st part of the Frame Header, which tells Frame Header size.\n*   srcSize must be == ZSTD_frameHeaderSize_min\n*   @return : the full size of the Frame Header */\nstatic size_t ZSTD_decodeFrameHeader_Part1(ZSTD_DCtx* zc, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);\n    zc->headerSize = ZSTD_frameHeaderSize_min;\n    return zc->headerSize;\n}\n\n\nstatic size_t ZSTD_getFrameParams(ZSTD_parameters* params, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize < ZSTD_frameHeaderSize_min) return ZSTD_frameHeaderSize_max;\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTD_MAGICNUMBER) return ERROR(prefix_unknown);\n    memset(params, 0, sizeof(*params));\n    params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTD_WINDOWLOG_ABSOLUTEMIN;\n    if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported);   /* reserved bits */\n    return 0;\n}\n\n/** ZSTD_decodeFrameHeader_Part2\n*   decode the full Frame Header\n*   srcSize must be the size provided by ZSTD_decodeFrameHeader_Part1\n*   @return : 0, or an error code, which can be tested using ZSTD_isError() */\nstatic size_t ZSTD_decodeFrameHeader_Part2(ZSTD_DCtx* zc, const void* src, size_t srcSize)\n{\n    size_t result;\n    if (srcSize != zc->headerSize) return ERROR(srcSize_wrong);\n    result = ZSTD_getFrameParams(&(zc->params), src, srcSize);\n    if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupported);\n    return result;\n}\n\n\nstatic size_t ZSTD_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE* const)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3) return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\nstatic size_t ZSTD_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/** ZSTD_decompressLiterals\n    @return : nb of bytes read from src, or an error code*/\nstatic size_t ZSTD_decompressLiterals(void* dst, size_t* maxDstSizePtr,\n                                const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    const size_t litSize = (MEM_readLE32(src) & 0x1FFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n    const size_t litCSize = (MEM_readLE32(ip+2) & 0xFFFFFF) >> 5;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n\n    if (litSize > *maxDstSizePtr) return ERROR(corruption_detected);\n    if (litCSize + 5 > srcSize) return ERROR(corruption_detected);\n\n    if (HUF_isError(HUF_decompress(dst, litSize, ip+5, litCSize))) return ERROR(corruption_detected);\n\n    *maxDstSizePtr = litSize;\n    return litCSize + 5;\n}\n\n\n/** ZSTD_decodeLiteralsBlock\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,\n                          const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(*istart & 3)\n    {\n    /* compressed */\n    case 0:\n        {\n            size_t litSize = BLOCKSIZE;\n            const size_t readSize = ZSTD_decompressLiterals(dctx->litBuffer, &litSize, src, srcSize);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, 8);\n            return readSize;   /* works if it's an error too */\n        }\n    case IS_RAW:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > srcSize-11)   /* risk of reading too far with wildcopy */\n            {\n                if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n                if (litSize > srcSize-3) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, 8);\n                return litSize+3;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+3;\n            dctx->litSize = litSize;\n            return litSize+3;        }\n    case IS_RLE:\n        {\n            const size_t litSize = (MEM_readLE32(istart) & 0xFFFFFF) >> 2;   /* no buffer issue : srcSize >= MIN_CBLOCK_SIZE */\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[3], litSize + 8);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return 4;\n        }\n    default:\n        return ERROR(corruption_detected);   /* forbidden nominal case */\n    }\n}\n\n\nstatic size_t ZSTD_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSE_DTable* DTableLL, FSE_DTable* DTableML, FSE_DTable* DTableOffb,\n                         const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE* const)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    U32 LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < 5) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = MEM_readLE16(ip); ip+=2;\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2)\n    {\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    }\n    else\n    {\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL >= MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case bt_rle :\n            LLlog = 0;\n            FSE_buildDTable_rle(DTableLL, *ip++); break;\n        case bt_raw :\n            LLlog = LLbits;\n            FSE_buildDTable_raw(DTableLL, LLbits); break;\n        default :\n            {   U32 max = MaxLL;\n                headerSize = FSE_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case bt_rle :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case bt_raw :\n            Offlog = Offbits;\n            FSE_buildDTable_raw(DTableOffb, Offbits); break;\n        default :\n            {   U32 max = MaxOff;\n                headerSize = FSE_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case bt_rle :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSE_buildDTable_rle(DTableML, *ip++); break;\n        case bt_raw :\n            MLlog = MLbits;\n            FSE_buildDTable_raw(DTableML, MLbits); break;\n        default :\n            {   U32 max = MaxML;\n                headerSize = FSE_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSE_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSELog) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSE_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t offset;\n    size_t matchLength;\n} seq_t;\n\ntypedef struct {\n    BIT_DStream_t DStream;\n    FSE_DState_t stateLL;\n    FSE_DState_t stateOffb;\n    FSE_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\nstatic void ZSTD_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSE_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    if (litLength == MaxLL) {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) litLength += add;\n        else if (dumps + 3 <= de) {\n            litLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {   static const U32 offsetPrefix[MaxOff+1] = {\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode, nbBits;\n        offsetCode = FSE_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));   /* <= maxOff, by table construction */\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BIT_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BIT_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* cmove */\n        if (offsetCode | !litLength) seqState->prevOffset = seq->offset;   /* cmove */\n    }\n\n    /* MatchLength */\n    matchLength = FSE_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML) {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 3 <= de){\n            matchLength = MEM_readLE24(dumps);\n            dumps += 3;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n}\n\n\nstatic size_t ZSTD_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n    static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n    BYTE* const oLitEnd = op + sequence.litLength;\n    const size_t sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTD_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base))\n    {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase))\n            return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd)\n        {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {\n            size_t length1 = dictEnd - match;\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_8 || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n        }\n    }\n    /* Requirement: op <= oend_8 */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        const int sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTD_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTD_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH))\n    {\n        if (op < oend_8)\n        {\n            ZSTD_wildcopy(op, match, oend_8 - op);\n            match += oend_8 - op;\n            op = oend_8;\n        }\n        while (op < oMatchEnd) *op++ = *match++;\n    }\n    else\n    {\n        ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8, but must be signed */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTD_decompressSequences(\n                               ZSTD_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq;\n    const BYTE* dumps;\n    U32* DTableLL = dctx->LLTable;\n    U32* DTableML = dctx->MLTable;\n    U32* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTD_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, iend-ip);\n    if (ZSTD_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        sequence.offset = 4;\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = 4;\n        errorCode = BIT_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSE_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSE_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSE_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && nbSeq ; )\n        {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTD_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n            if (ZSTD_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if ( !BIT_endOfDStream(&(seqState.DStream)) ) return ERROR(corruption_detected);   /* DStream should be entirely and exactly consumed; otherwise data is corrupted */\n\n        /* last literal segment */\n        {\n            size_t lastLLSize = litEnd - litPtr;\n            if (litPtr > litEnd) return ERROR(corruption_detected);\n            if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n            if (lastLLSize > 0) {\n                if (op != litPtr) memcpy(op, litPtr, lastLLSize);\n                op += lastLLSize;\n            }\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTD_checkContinuity(ZSTD_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd)   /* not contiguous */\n    {\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,\n                            void* dst, size_t maxDstSize,\n                      const void* src, size_t srcSize)\n{\n    /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n    size_t litCSize;\n\n    if (srcSize > BLOCKSIZE) return ERROR(corruption_detected);\n\n    /* Decode literals sub-block */\n    litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);\n    if (ZSTD_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTD_decompressSequences(dctx, dst, maxDstSize, ip, srcSize);\n}\n\n\nstatic size_t ZSTD_decompress_usingDict(ZSTD_DCtx* ctx,\n                                 void* dst, size_t maxDstSize,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE* const)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    blockProperties_t blockProperties;\n\n    /* init */\n    ZSTD_resetDCtx(ctx);\n    if (dict)\n    {\n        ZSTD_decompress_insertDictionary(ctx, dict, dictSize);\n        ctx->dictEnd = ctx->previousDstEnd;\n        ctx->vBase = (const char*)dst - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base));\n        ctx->base = dst;\n    }\n    else\n    {\n        ctx->vBase = ctx->base = ctx->dictEnd = dst;\n    }\n\n    /* Frame Header */\n    {\n        size_t frameHeaderSize;\n        if (srcSize < ZSTD_frameHeaderSize_min+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n        frameHeaderSize = ZSTD_decodeFrameHeader_Part1(ctx, src, ZSTD_frameHeaderSize_min);\n        if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTD_blockHeaderSize) return ERROR(srcSize_wrong);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n        frameHeaderSize = ZSTD_decodeFrameHeader_Part2(ctx, src, frameHeaderSize);\n        if (ZSTD_isError(frameHeaderSize)) return frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTD_decompressBlock_internal(ctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTD_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTD_frameHeaderSize_min) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    if (MEM_readLE32(src) != ZSTD_MAGICNUMBER) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTD_frameHeaderSize_min; remainingSize -= ZSTD_frameHeaderSize_min;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTD_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTD_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTD_blockHeaderSize;\n        remainingSize -= ZSTD_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/* ******************************\n*  Streaming Decompression API\n********************************/\nstatic size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nstatic size_t ZSTD_decompressContinue(ZSTD_DCtx* ctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != ctx->expected) return ERROR(srcSize_wrong);\n    ZSTD_checkContinuity(ctx, dst);\n\n    /* Decompress : frame header; part 1 */\n    switch (ctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        /* get frame header size */\n        if (srcSize != ZSTD_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        ctx->headerSize = ZSTD_decodeFrameHeader_Part1(ctx, src, ZSTD_frameHeaderSize_min);\n        if (ZSTD_isError(ctx->headerSize)) return ctx->headerSize;\n        memcpy(ctx->headerBuffer, src, ZSTD_frameHeaderSize_min);\n        if (ctx->headerSize > ZSTD_frameHeaderSize_min) return ERROR(GENERIC);   /* impossible */\n        ctx->expected = 0;   /* not necessary to copy more */\n        /* fallthrough */\n    case ZSTDds_decodeFrameHeader:\n        /* get frame header */\n        {   size_t const result = ZSTD_decodeFrameHeader_Part2(ctx, ctx->headerBuffer, ctx->headerSize);\n            if (ZSTD_isError(result)) return result;\n            ctx->expected = ZSTD_blockHeaderSize;\n            ctx->stage = ZSTDds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDds_decodeBlockHeader:\n        /* Decode block header */\n        {   blockProperties_t bp;\n            size_t const blockSize = ZSTD_getcBlockSize(src, ZSTD_blockHeaderSize, &bp);\n            if (ZSTD_isError(blockSize)) return blockSize;\n            if (bp.blockType == bt_end)\n            {\n                ctx->expected = 0;\n                ctx->stage = ZSTDds_getFrameHeaderSize;\n            }\n            else\n            {\n                ctx->expected = blockSize;\n                ctx->bType = bp.blockType;\n                ctx->stage = ZSTDds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDds_decompressBlock:\n        {\n            /* Decompress : block content */\n            size_t rSize;\n            switch(ctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTD_decompressBlock_internal(ctx, dst, maxDstSize, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTD_copyRawBlock(dst, maxDstSize, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);\n            }\n            ctx->stage = ZSTDds_decodeBlockHeader;\n            ctx->expected = ZSTD_blockHeaderSize;\n            if (ZSTD_isError(rSize)) return rSize;\n            ctx->previousDstEnd = (char*)dst + rSize;\n            return rSize;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic void ZSTD_decompress_insertDictionary(ZSTD_DCtx* ctx, const void* dict, size_t dictSize)\n{\n    ctx->dictEnd = ctx->previousDstEnd;\n    ctx->vBase = (const char*)dict - ((const char*)(ctx->previousDstEnd) - (const char*)(ctx->base));\n    ctx->base = dict;\n    ctx->previousDstEnd = (const char*)dict + dictSize;\n}\n\n\n\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stdlib.h>\n\n\n/** ************************************************\n*  Streaming decompression\n*\n*  A ZBUFF_DCtx object is required to track streaming operation.\n*  Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources.\n*  Use ZBUFF_decompressInit() to start a new decompression operation.\n*  ZBUFF_DCtx objects can be reused multiple times.\n*\n*  Use ZBUFF_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *maxDstSizePtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.\n*  The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst .\n*  return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory)\n*  output : 128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.\n*  input : just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* **************************************************/\n\ntypedef enum { ZBUFFds_init, ZBUFFds_readHeader, ZBUFFds_loadHeader, ZBUFFds_decodeHeader,\n               ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFF_dStage;\n\n/* *** Resource management *** */\n\n#define ZSTD_frameHeaderSize_max 5   /* too magical, should come from reference */\nstruct ZBUFFv04_DCtx_s {\n    ZSTD_DCtx* zc;\n    ZSTD_parameters params;\n    char* inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char* outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t hPos;\n    const char* dict;\n    size_t dictSize;\n    ZBUFF_dStage stage;\n    unsigned char headerBuffer[ZSTD_frameHeaderSize_max];\n};   /* typedef'd to ZBUFF_DCtx within \"zstd_buffered.h\" */\n\ntypedef ZBUFFv04_DCtx ZBUFF_DCtx;\n\n\nstatic ZBUFF_DCtx* ZBUFF_createDCtx(void)\n{\n    ZBUFF_DCtx* zbc = (ZBUFF_DCtx*)malloc(sizeof(ZBUFF_DCtx));\n    if (zbc==NULL) return NULL;\n    memset(zbc, 0, sizeof(*zbc));\n    zbc->zc = ZSTD_createDCtx();\n    zbc->stage = ZBUFFds_init;\n    return zbc;\n}\n\nstatic size_t ZBUFF_freeDCtx(ZBUFF_DCtx* zbc)\n{\n    if (zbc==NULL) return 0;   /* support free on null */\n    ZSTD_freeDCtx(zbc->zc);\n    free(zbc->inBuff);\n    free(zbc->outBuff);\n    free(zbc);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nstatic size_t ZBUFF_decompressInit(ZBUFF_DCtx* zbc)\n{\n    zbc->stage = ZBUFFds_readHeader;\n    zbc->hPos = zbc->inPos = zbc->outStart = zbc->outEnd = zbc->dictSize = 0;\n    return ZSTD_resetDCtx(zbc->zc);\n}\n\n\nstatic size_t ZBUFF_decompressWithDictionary(ZBUFF_DCtx* zbc, const void* src, size_t srcSize)\n{\n    zbc->dict = (const char*)src;\n    zbc->dictSize = srcSize;\n    return 0;\n}\n\nstatic size_t ZBUFF_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    size_t length = MIN(maxDstSize, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n/* *** Decompression *** */\n\nstatic size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbc, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* ip = istart;\n    const char* const iend = istart + *srcSizePtr;\n    char* const ostart = (char*)dst;\n    char* op = ostart;\n    char* const oend = ostart + *maxDstSizePtr;\n    U32 notDone = 1;\n\n    DEBUGLOG(5, \"ZBUFF_decompressContinue\");\n    while (notDone)\n    {\n        switch(zbc->stage)\n        {\n\n        case ZBUFFds_init :\n            DEBUGLOG(5, \"ZBUFF_decompressContinue: stage==ZBUFFds_init => ERROR(init_missing)\");\n            return ERROR(init_missing);\n\n        case ZBUFFds_readHeader :\n            /* read header from src */\n            {   size_t const headerSize = ZSTD_getFrameParams(&(zbc->params), src, *srcSizePtr);\n                if (ZSTD_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    memcpy(zbc->headerBuffer+zbc->hPos, src, *srcSizePtr);\n                    zbc->hPos += *srcSizePtr;\n                    *maxDstSizePtr = 0;\n                    zbc->stage = ZBUFFds_loadHeader;\n                    return headerSize - zbc->hPos;\n                }\n                zbc->stage = ZBUFFds_decodeHeader;\n                break;\n            }\n\n        case ZBUFFds_loadHeader:\n            /* complete header from src */\n            {   size_t headerSize = ZBUFF_limitCopy(\n                    zbc->headerBuffer + zbc->hPos, ZSTD_frameHeaderSize_max - zbc->hPos,\n                    src, *srcSizePtr);\n                zbc->hPos += headerSize;\n                ip += headerSize;\n                headerSize = ZSTD_getFrameParams(&(zbc->params), zbc->headerBuffer, zbc->hPos);\n                if (ZSTD_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    *maxDstSizePtr = 0;\n                    return headerSize - zbc->hPos;\n            }   }\n            /* intentional fallthrough */\n\n        case ZBUFFds_decodeHeader:\n                /* apply header to create / resize buffers */\n                {   size_t const neededOutSize = (size_t)1 << zbc->params.windowLog;\n                    size_t const neededInSize = BLOCKSIZE;   /* a block is never > BLOCKSIZE */\n                    if (zbc->inBuffSize < neededInSize) {\n                        free(zbc->inBuff);\n                        zbc->inBuffSize = neededInSize;\n                        zbc->inBuff = (char*)malloc(neededInSize);\n                        if (zbc->inBuff == NULL) return ERROR(memory_allocation);\n                    }\n                    if (zbc->outBuffSize < neededOutSize) {\n                        free(zbc->outBuff);\n                        zbc->outBuffSize = neededOutSize;\n                        zbc->outBuff = (char*)malloc(neededOutSize);\n                        if (zbc->outBuff == NULL) return ERROR(memory_allocation);\n                }   }\n                if (zbc->dictSize)\n                    ZSTD_decompress_insertDictionary(zbc->zc, zbc->dict, zbc->dictSize);\n                if (zbc->hPos) {\n                    /* some data already loaded into headerBuffer : transfer into inBuff */\n                    memcpy(zbc->inBuff, zbc->headerBuffer, zbc->hPos);\n                    zbc->inPos = zbc->hPos;\n                    zbc->hPos = 0;\n                    zbc->stage = ZBUFFds_load;\n                    break;\n                }\n                zbc->stage = ZBUFFds_read;\n\t\t/* fall-through */\n        case ZBUFFds_read:\n            {\n                size_t neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);\n                if (neededInSize==0)   /* end of frame */\n                {\n                    zbc->stage = ZBUFFds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize)\n                {\n                    /* directly decode from src */\n                    size_t decodedSize = ZSTD_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        ip, neededInSize);\n                    if (ZSTD_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize) break;   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbc->stage = ZBUFFds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFds_load:\n            {\n                size_t neededInSize = ZSTD_nextSrcSizeToDecompress(zbc->zc);\n                size_t toLoad = neededInSize - zbc->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFF_limitCopy(zbc->inBuff + zbc->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbc->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n                {\n                    size_t decodedSize = ZSTD_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        zbc->inBuff, neededInSize);\n                    if (ZSTD_isError(decodedSize)) return decodedSize;\n                    zbc->inPos = 0;   /* input is consumed */\n                    if (!decodedSize) { zbc->stage = ZBUFFds_read; break; }   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFds_flush;\n                    /* ZBUFFds_flush follows */\n                }\n            }\n\t    /* fall-through */\n        case ZBUFFds_flush:\n            {\n                size_t toFlushSize = zbc->outEnd - zbc->outStart;\n                size_t flushedSize = ZBUFF_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize);\n                op += flushedSize;\n                zbc->outStart += flushedSize;\n                if (flushedSize == toFlushSize)\n                {\n                    zbc->stage = ZBUFFds_read;\n                    if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize)\n                        zbc->outStart = zbc->outEnd = 0;\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n        }\n    }\n\n    *srcSizePtr = ip-istart;\n    *maxDstSizePtr = op-ostart;\n\n    {\n        size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbc->zc);\n        if (nextSrcSizeHint > 3) nextSrcSizeHint+= 3;   /* get the next block header while at it */\n        nextSrcSizeHint -= zbc->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nunsigned ZBUFFv04_isError(size_t errorCode) { return ERR_isError(errorCode); }\nconst char* ZBUFFv04_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n\nsize_t ZBUFFv04_recommendedDInSize(void)  { return BLOCKSIZE + 3; }\nsize_t ZBUFFv04_recommendedDOutSize(void) { return BLOCKSIZE; }\n\n\n\n/*- ========================================================================= -*/\n\n/* final wrapping stage */\n\nsize_t ZSTDv04_decompressDCtx(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);\n}\n\nsize_t ZSTDv04_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE==1)\n    size_t regenSize;\n    ZSTD_DCtx* dctx = ZSTD_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv04_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);\n    ZSTD_freeDCtx(dctx);\n    return regenSize;\n#else\n    ZSTD_DCtx dctx;\n    return ZSTDv04_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);\n#endif\n}\n\nsize_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx) { return ZSTD_resetDCtx(dctx); }\n\nsize_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx)\n{\n    return ZSTD_nextSrcSizeToDecompress(dctx);\n}\n\nsize_t ZSTDv04_decompressContinue(ZSTDv04_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTD_decompressContinue(dctx, dst, maxDstSize, src, srcSize);\n}\n\n\n\nZBUFFv04_DCtx* ZBUFFv04_createDCtx(void) { return ZBUFF_createDCtx(); }\nsize_t ZBUFFv04_freeDCtx(ZBUFFv04_DCtx* dctx) { return ZBUFF_freeDCtx(dctx); }\n\nsize_t ZBUFFv04_decompressInit(ZBUFFv04_DCtx* dctx) { return ZBUFF_decompressInit(dctx); }\nsize_t ZBUFFv04_decompressWithDictionary(ZBUFFv04_DCtx* dctx, const void* src, size_t srcSize)\n{ return ZBUFF_decompressWithDictionary(dctx, src, srcSize); }\n\nsize_t ZBUFFv04_decompressContinue(ZBUFFv04_DCtx* dctx, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)\n{\n    DEBUGLOG(5, \"ZBUFFv04_decompressContinue\");\n    return ZBUFF_decompressContinue(dctx, dst, maxDstSizePtr, src, srcSizePtr);\n}\n\nZSTD_DCtx* ZSTDv04_createDCtx(void) { return ZSTD_createDCtx(); }\nsize_t ZSTDv04_freeDCtx(ZSTD_DCtx* dctx) { return ZSTD_freeDCtx(dctx); }\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v04.h",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_V04_H_91868324769238\n#define ZSTD_V04_H_91868324769238\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* *************************************\n*  Includes\n***************************************/\n#include <stddef.h>   /* size_t */\n\n\n/* *************************************\n*  Simple one-step function\n***************************************/\n/**\nZSTDv04_decompress() : decompress ZSTD frames compliant with v0.4.x format\n    compressedSize : is the exact source size\n    maxOriginalSize : is the size of the 'dst' buffer, which must be already allocated.\n                      It must be equal or larger than originalSize, otherwise decompression will fail.\n    return : the number of bytes decompressed into destination buffer (originalSize)\n             or an errorCode if it fails (which can be tested using ZSTDv01_isError())\n*/\nsize_t ZSTDv04_decompress( void* dst, size_t maxOriginalSize,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv04_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.4.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\n void ZSTDv04_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                      size_t* cSize, unsigned long long* dBound);\n\n/**\nZSTDv04_isError() : tells if the result of ZSTDv04_decompress() is an error\n*/\nunsigned ZSTDv04_isError(size_t code);\n\n\n/* *************************************\n*  Advanced functions\n***************************************/\ntypedef struct ZSTDv04_Dctx_s ZSTDv04_Dctx;\nZSTDv04_Dctx* ZSTDv04_createDCtx(void);\nsize_t ZSTDv04_freeDCtx(ZSTDv04_Dctx* dctx);\n\nsize_t ZSTDv04_decompressDCtx(ZSTDv04_Dctx* dctx,\n                              void* dst, size_t maxOriginalSize,\n                        const void* src, size_t compressedSize);\n\n\n/* *************************************\n*  Direct Streaming\n***************************************/\nsize_t ZSTDv04_resetDCtx(ZSTDv04_Dctx* dctx);\n\nsize_t ZSTDv04_nextSrcSizeToDecompress(ZSTDv04_Dctx* dctx);\nsize_t ZSTDv04_decompressContinue(ZSTDv04_Dctx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize);\n/**\n  Use above functions alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() will use previous data blocks to improve compression if they are located prior to current block.\n  Result is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some header.\n*/\n\n\n/* *************************************\n*  Buffered Streaming\n***************************************/\ntypedef struct ZBUFFv04_DCtx_s ZBUFFv04_DCtx;\nZBUFFv04_DCtx* ZBUFFv04_createDCtx(void);\nsize_t         ZBUFFv04_freeDCtx(ZBUFFv04_DCtx* dctx);\n\nsize_t ZBUFFv04_decompressInit(ZBUFFv04_DCtx* dctx);\nsize_t ZBUFFv04_decompressWithDictionary(ZBUFFv04_DCtx* dctx, const void* dict, size_t dictSize);\n\nsize_t ZBUFFv04_decompressContinue(ZBUFFv04_DCtx* dctx, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr);\n\n/** ************************************************\n*  Streaming decompression\n*\n*  A ZBUFF_DCtx object is required to track streaming operation.\n*  Use ZBUFF_createDCtx() and ZBUFF_freeDCtx() to create/release resources.\n*  Use ZBUFF_decompressInit() to start a new decompression operation.\n*  ZBUFF_DCtx objects can be reused multiple times.\n*\n*  Optionally, a reference to a static dictionary can be set, using ZBUFF_decompressWithDictionary()\n*  It must be the same content as the one set during compression phase.\n*  Dictionary content must remain accessible during the decompression process.\n*\n*  Use ZBUFF_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *maxDstSizePtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFF_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFF_recommendedDInSize / ZBUFF_recommendedDOutSize\n*  output : ZBUFF_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.\n*  input : ZBUFF_recommendedDInSize==128Kb+3; just follow indications from ZBUFF_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* **************************************************/\nunsigned ZBUFFv04_isError(size_t errorCode);\nconst char* ZBUFFv04_getErrorName(size_t errorCode);\n\n\n/** The below functions provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are not compulsory, they just tend to offer better latency */\nsize_t ZBUFFv04_recommendedDInSize(void);\nsize_t ZBUFFv04_recommendedDOutSize(void);\n\n\n/* *************************************\n*  Prefix - version detection\n***************************************/\n#define ZSTDv04_magicNumber 0xFD2FB524   /* v0.4 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_V04_H_91868324769238 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v05.c",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*- Dependencies -*/\n#include \"zstd_v05.h\"\n#include \"../common/error_private.h\"\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-****************************************\n*  Dependencies\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(__GNUC__)\n#  define MEM_STATIC static __attribute__((unused))\n#elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#  define MEM_STATIC static inline\n#elif defined(_MSC_VER)\n#  define MEM_STATIC static __inline\n#else\n#  define MEM_STATIC static  /* this version may generate warnings for unused static functions; disable the relevant warning */\n#endif\n\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-**************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(void*)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(void*)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write32(void* memPtr, U32 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC void MEM_write64(void* memPtr, U64 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U32)((U32)p[0] + ((U32)p[1]<<8) + ((U32)p[2]<<16) + ((U32)p[3]<<24));\n    }\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U64)((U64)p[0] + ((U64)p[1]<<8) + ((U64)p[2]<<16) + ((U64)p[3]<<24)\n                     + ((U64)p[4]<<32) + ((U64)p[5]<<40) + ((U64)p[6]<<48) + ((U64)p[7]<<56));\n    }\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n#ifndef ZSTD_STATIC_H\n#define ZSTD_STATIC_H\n\n/* The prototypes defined within this file are considered experimental.\n * They should not be used in the context DLL as they may change in the future.\n * Prefer static linking if you need them, to control breaking version changes issues.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*-*************************************\n*  Types\n***************************************/\n#define ZSTDv05_WINDOWLOG_ABSOLUTEMIN 11\n\n\n/*-*************************************\n*  Advanced functions\n***************************************/\n/*- Advanced Decompression functions -*/\n\n/*! ZSTDv05_decompress_usingPreparedDCtx() :\n*   Same as ZSTDv05_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.\n*   It avoids reloading the dictionary each time.\n*   `preparedDCtx` must have been properly initialized using ZSTDv05_decompressBegin_usingDict().\n*   Requires 2 contexts : 1 for reference, which will not be modified, and 1 to run the decompression operation */\nsize_t ZSTDv05_decompress_usingPreparedDCtx(\n                                             ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* preparedDCtx,\n                                             void* dst, size_t dstCapacity,\n                                       const void* src, size_t srcSize);\n\n\n/* **************************************\n*  Streaming functions (direct mode)\n****************************************/\nsize_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx);\n\n/*\n  Streaming decompression, direct mode (bufferless)\n\n  A ZSTDv05_DCtx object is required to track streaming operations.\n  Use ZSTDv05_createDCtx() / ZSTDv05_freeDCtx() to manage it.\n  A ZSTDv05_DCtx object can be re-used multiple times.\n\n  First typical operation is to retrieve frame parameters, using ZSTDv05_getFrameParams().\n  This operation is independent, and just needs enough input data to properly decode the frame header.\n  Objective is to retrieve *params.windowlog, to know minimum amount of memory required during decoding.\n  Result : 0 when successful, it means the ZSTDv05_parameters structure has been filled.\n           >0 : means there is not enough data into src. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTDv05_isError()\n\n  Start decompression, with ZSTDv05_decompressBegin() or ZSTDv05_decompressBegin_usingDict()\n  Alternatively, you can copy a prepared context, using ZSTDv05_copyDCtx()\n\n  Then use ZSTDv05_nextSrcSizeToDecompress() and ZSTDv05_decompressContinue() alternatively.\n  ZSTDv05_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv05_decompressContinue().\n  ZSTDv05_decompressContinue() requires this exact amount of bytes, or it will fail.\n  ZSTDv05_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).\n  They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.\n\n  @result of ZSTDv05_decompressContinue() is the number of bytes regenerated within 'dst'.\n  It can be zero, which is not an error; it just means ZSTDv05_decompressContinue() has decoded some header.\n\n  A frame is fully decoded when ZSTDv05_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n*/\n\n\n/* **************************************\n*  Block functions\n****************************************/\n/*! Block functions produce and decode raw zstd blocks, without frame metadata.\n    User will have to take in charge required information to regenerate data, such as block sizes.\n\n    A few rules to respect :\n    - Uncompressed block size must be <= 128 KB\n    - Compressing or decompressing requires a context structure\n      + Use ZSTDv05_createCCtx() and ZSTDv05_createDCtx()\n    - It is necessary to init context before starting\n      + compression : ZSTDv05_compressBegin()\n      + decompression : ZSTDv05_decompressBegin()\n      + variants _usingDict() are also allowed\n      + copyCCtx() and copyDCtx() work too\n    - When a block is considered not compressible enough, ZSTDv05_compressBlock() result will be zero.\n      In which case, nothing is produced into `dst`.\n      + User must test for such outcome and deal directly with uncompressed data\n      + ZSTDv05_decompressBlock() doesn't accept uncompressed data as input !!\n*/\n\nsize_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv05_STATIC_H */\n\n\n/*\n    zstd_internal - common functions to include\n    Header File for include\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n*/\n#ifndef ZSTD_CCOMMON_H_MODULE\n#define ZSTD_CCOMMON_H_MODULE\n\n\n\n/*-*************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTDv05_DICT_MAGIC  0xEC30A435\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BLOCKSIZE (128 KB)                 /* define, for static allocation */\n\nstatic const size_t ZSTDv05_blockHeaderSize = 3;\nstatic const size_t ZSTDv05_frameHeaderSize_min = 5;\n#define ZSTDv05_frameHeaderSize_max 5         /* define, for static allocation */\n\n#define BITv057 128\n#define BITv056  64\n#define BITv055  32\n#define BITv054  16\n#define BITv051   2\n#define BITv050   1\n\n#define IS_HUFv05 0\n#define IS_PCH 1\n#define IS_RAW 2\n#define IS_RLE 3\n\n#define MINMATCH 4\n#define REPCODE_STARTVALUE 1\n\n#define Litbits  8\n#define MLbits   7\n#define LLbits   6\n#define Offbits  5\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML  ((1<<MLbits) - 1)\n#define MaxLL  ((1<<LLbits) - 1)\n#define MaxOff ((1<<Offbits)- 1)\n#define MLFSEv05Log   10\n#define LLFSEv05Log   10\n#define OffFSEv05Log   9\n#define MaxSeq MAX(MaxLL, MaxML)\n\n#define FSEv05_ENCODING_RAW     0\n#define FSEv05_ENCODING_RLE     1\n#define FSEv05_ENCODING_STATIC  2\n#define FSEv05_ENCODING_DYNAMIC 3\n\n\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */\n\n#define WILDCOPY_OVERLENGTH 8\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTDv05_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n\n#define COPY8(d,s) { ZSTDv05_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTDv05_wildcopy() :\n*   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */\nMEM_STATIC void ZSTDv05_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n/*-*******************************************\n*  Private interfaces\n*********************************************/\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* offCode;\n    BYTE* litStart;\n    BYTE* lit;\n    BYTE* litLengthStart;\n    BYTE* litLength;\n    BYTE* matchLengthStart;\n    BYTE* matchLength;\n    BYTE* dumpsStart;\n    BYTE* dumps;\n    /* opt */\n    U32* matchLengthFreq;\n    U32* litLengthFreq;\n    U32* litFreq;\n    U32* offCodeFreq;\n    U32  matchLengthSum;\n    U32  litLengthSum;\n    U32  litSum;\n    U32  offCodeSum;\n} SeqStore_t;\n\n\n\n#endif   /* ZSTDv05_CCOMMON_H_MODULE */\n/* ******************************************************************\n   FSEv05 : Finite State Entropy coder\n   header file\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSEv05_H\n#define FSEv05_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Includes\n******************************************/\n#include <stddef.h>    /* size_t, ptrdiff_t */\n\n\n/*-****************************************\n*  FSEv05 simple functions\n******************************************/\nsize_t FSEv05_decompress(void* dst,  size_t maxDstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nFSEv05_decompress():\n    Decompress FSEv05 data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'maxDstSize'.\n    return : size of regenerated data (<= maxDstSize)\n             or an error code, which can be tested using FSEv05_isError()\n\n    ** Important ** : FSEv05_decompress() doesn't decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\n\n\n/* *****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nunsigned    FSEv05_isError(size_t code);        /* tells if a return value is an error code */\nconst char* FSEv05_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n\n\n/* *****************************************\n*  FSEv05 detailed API\n******************************************/\n/* *** DECOMPRESSION *** */\n\n/*!\nFSEv05_readNCount():\n   Read compactly saved 'normalizedCounter' from 'rBuffer'.\n   return : size read from 'rBuffer'\n            or an errorCode, which can be tested using FSEv05_isError()\n            maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nsize_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*!\nConstructor and Destructor of type FSEv05_DTable\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSEv05_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\nFSEv05_DTable* FSEv05_createDTable(unsigned tableLog);\nvoid        FSEv05_freeDTable(FSEv05_DTable* dt);\n\n/*!\nFSEv05_buildDTable():\n   Builds 'dt', which must be already allocated, using FSEv05_createDTable()\n   @return : 0,\n             or an errorCode, which can be tested using FSEv05_isError() */\nsize_t FSEv05_buildDTable (FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*!\nFSEv05_decompress_usingDTable():\n   Decompress compressed source @cSrc of size @cSrcSize using `dt`\n   into `dst` which must be already allocated.\n   @return : size of regenerated data (necessarily <= @dstCapacity)\n             or an errorCode, which can be tested using FSEv05_isError() */\nsize_t FSEv05_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv05_DTable* dt);\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv05_H */\n/* ******************************************************************\n   bitstream\n   Part of FSEv05 library\n   header file (to include)\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef BITv05STREAM_H_MODULE\n#define BITv05STREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which highly benefit from being inlined.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BITv05_DStream_t;\n\ntypedef enum { BITv05_DStream_unfinished = 0,\n               BITv05_DStream_endOfBuffer = 1,\n               BITv05_DStream_completed = 2,\n               BITv05_DStream_overflow = 3 } BITv05_DStream_status;  /* result of BITv05_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD);\nMEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* bitD);\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/*-**************************************************************\n*  Helper functions\n****************************************************************/\nMEM_STATIC unsigned BITv05_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/*-********************************************************\n* bitStream decoding\n**********************************************************/\n/*!BITv05_initDStream\n*  Initialize a BITv05_DStream_t.\n*  @bitD : a pointer to an already allocated BITv05_DStream_t structure\n*  @srcBuffer must point at the beginning of a bitStream\n*  @srcSize must be the exact size of the bitStream\n*  @result : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BITv05_initDStream(BITv05_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(size_t)) {  /* normal case */\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(size_t);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);\n    } else {\n        U32 contain32;\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[6]) << (sizeof(size_t)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[5]) << (sizeof(size_t)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[4]) << (sizeof(size_t)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(bitD->start))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        contain32 = ((const BYTE*)srcBuffer)[srcSize-1];\n        if (contain32 == 0) return ERROR(GENERIC);   /* endMark not present */\n        bitD->bitsConsumed = 8 - BITv05_highbit32(contain32);\n        bitD->bitsConsumed += (U32)(sizeof(size_t) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\nMEM_STATIC size_t BITv05_lookBits(BITv05_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BITv05_lookBitsFast :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv05_lookBitsFast(BITv05_DStream_t* bitD, U32 nbBits)\n{\n    const U32 bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BITv05_skipBits(BITv05_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BITv05_readBits(BITv05_DStream_t* bitD, unsigned nbBits)\n{\n    size_t value = BITv05_lookBits(bitD, nbBits);\n    BITv05_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*!BITv05_readBitsFast :\n*  unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv05_readBitsFast(BITv05_DStream_t* bitD, unsigned nbBits)\n{\n    size_t value = BITv05_lookBitsFast(bitD, nbBits);\n    BITv05_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BITv05_DStream_status BITv05_reloadDStream(BITv05_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BITv05_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BITv05_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start) {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv05_DStream_endOfBuffer;\n        return BITv05_DStream_completed;\n    }\n    {\n        U32 nbBytes = bitD->bitsConsumed >> 3;\n        BITv05_DStream_status result = BITv05_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BITv05_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BITv05_endOfDStream\n*   @return Tells if DStream has reached its exact end\n*/\nMEM_STATIC unsigned BITv05_endOfDStream(const BITv05_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITv05STREAM_H_MODULE */\n/* ******************************************************************\n   FSEv05 : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSEv05_STATIC_H\n#define FSEv05_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* It is possible to statically allocate FSEv05 CTable/DTable as a table of unsigned using below macros */\n#define FSEv05_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSEv05 advanced API\n*******************************************/\nsize_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits);\n/* build a fake FSEv05_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nsize_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, unsigned char symbolValue);\n/* build a fake FSEv05_DTable, designed to always generate the same symbolValue */\n\n\n\n/* *****************************************\n*  FSEv05 symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSEv05_DState_t;\n\n\nstatic void     FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt);\n\nstatic unsigned char FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);\n\nstatic unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr);\n\n\n\n/* *****************************************\n*  FSEv05 unsafe API\n*******************************************/\nstatic unsigned char FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\n/* decompression */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSEv05_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSEv05_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSEv05_initDState(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD, const FSEv05_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv05_DTableHeader* const DTableH = (const FSEv05_DTableHeader*)ptr;\n    DStatePtr->state = BITv05_readBits(bitD, DTableH->tableLog);\n    BITv05_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSEv05_peakSymbol(FSEv05_DState_t* DStatePtr)\n{\n    const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC BYTE FSEv05_decodeSymbol(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)\n{\n    const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32  nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BITv05_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC BYTE FSEv05_decodeSymbolFast(FSEv05_DState_t* DStatePtr, BITv05_DStream_t* bitD)\n{\n    const FSEv05_decode_t DInfo = ((const FSEv05_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    const U32 nbBits = DInfo.nbBits;\n    BYTE symbol = DInfo.symbol;\n    size_t lowBits = BITv05_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\nMEM_STATIC unsigned FSEv05_endOfDState(const FSEv05_DState_t* DStatePtr)\n{\n    return DStatePtr->state == 0;\n}\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv05_STATIC_H */\n/* ******************************************************************\n   FSEv05 : Finite State Entropy coder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSEv05 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n#ifndef FSEv05_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSEv05_MAX_MEMORY_USAGE 14\n#define FSEv05_DEFAULT_MEMORY_USAGE 13\n\n/*!FSEv05_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSEv05_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSEv05_FUNCTION_TYPE BYTE\n#define FSEv05_FUNCTION_EXTENSION\n#define FSEv05_DECODE_TYPE FSEv05_decode_t\n\n\n#endif   /* !FSEv05_COMMONDEFS_ONLY */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSEv05_MAX_TABLELOG  (FSEv05_MAX_MEMORY_USAGE-2)\n#define FSEv05_MAX_TABLESIZE (1U<<FSEv05_MAX_TABLELOG)\n#define FSEv05_MAXTABLESIZE_MASK (FSEv05_MAX_TABLESIZE-1)\n#define FSEv05_DEFAULT_TABLELOG (FSEv05_DEFAULT_MEMORY_USAGE-2)\n#define FSEv05_MIN_TABLELOG 5\n\n#define FSEv05_TABLELOG_ABSOLUTE_MAX 15\n#if FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX\n#error \"FSEv05_MAX_TABLELOG > FSEv05_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSEv05_STATIC_ASSERT(c) { enum { FSEv05_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef unsigned DTable_max_t[FSEv05_DTABLE_SIZE_U32(FSEv05_MAX_TABLELOG)];\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSEv05_FUNCTION_EXTENSION\n#  error \"FSEv05_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSEv05_FUNCTION_TYPE\n#  error \"FSEv05_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSEv05_CAT(X,Y) X##Y\n#define FSEv05_FUNCTION_NAME(X,Y) FSEv05_CAT(X,Y)\n#define FSEv05_TYPE_NAME(X,Y) FSEv05_CAT(X,Y)\n\n\n/* Function templates */\nstatic U32 FSEv05_tableStep(U32 tableSize) { return (tableSize>>1) + (tableSize>>3) + 3; }\n\n\n\nFSEv05_DTable* FSEv05_createDTable (unsigned tableLog)\n{\n    if (tableLog > FSEv05_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv05_TABLELOG_ABSOLUTE_MAX;\n    return (FSEv05_DTable*)malloc( FSEv05_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );\n}\n\nvoid FSEv05_freeDTable (FSEv05_DTable* dt)\n{\n    free(dt);\n}\n\nsize_t FSEv05_buildDTable(FSEv05_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    FSEv05_DTableHeader DTableH;\n    void* const tdPtr = dt+1;   /* because dt is unsigned, 32-bits aligned on 32-bits */\n    FSEv05_DECODE_TYPE* const tableDecode = (FSEv05_DECODE_TYPE*) (tdPtr);\n    const U32 tableSize = 1 << tableLog;\n    const U32 tableMask = tableSize-1;\n    const U32 step = FSEv05_tableStep(tableSize);\n    U16 symbolNext[FSEv05_MAX_SYMBOL_VALUE+1];\n    U32 position = 0;\n    U32 highThreshold = tableSize-1;\n    const S16 largeLimit= (S16)(1 << (tableLog-1));\n    U32 noLarge = 1;\n    U32 s;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSEv05_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSEv05_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    memset(tableDecode, 0, sizeof(FSEv05_FUNCTION_TYPE) * (maxSymbolValue+1) );   /* useless init, but keep static analyzer happy, and we don't need to performance optimize legacy decoders */\n    DTableH.tableLog = (U16)tableLog;\n    for (s=0; s<=maxSymbolValue; s++) {\n        if (normalizedCounter[s]==-1) {\n            tableDecode[highThreshold--].symbol = (FSEv05_FUNCTION_TYPE)s;\n            symbolNext[s] = 1;\n        } else {\n            if (normalizedCounter[s] >= largeLimit) noLarge=0;\n            symbolNext[s] = normalizedCounter[s];\n    }   }\n\n    /* Spread symbols */\n    for (s=0; s<=maxSymbolValue; s++) {\n        int i;\n        for (i=0; i<normalizedCounter[s]; i++) {\n            tableDecode[position].symbol = (FSEv05_FUNCTION_TYPE)s;\n            position = (position + step) & tableMask;\n            while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n    }   }\n\n    if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n\n    /* Build Decoding table */\n    {\n        U32 i;\n        for (i=0; i<tableSize; i++) {\n            FSEv05_FUNCTION_TYPE symbol = (FSEv05_FUNCTION_TYPE)(tableDecode[i].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[i].nbBits = (BYTE) (tableLog - BITv05_highbit32 ((U32)nextState) );\n            tableDecode[i].newState = (U16) ( (nextState << tableDecode[i].nbBits) - tableSize);\n    }   }\n\n    DTableH.fastMode = (U16)noLarge;\n    memcpy(dt, &DTableH, sizeof(DTableH));\n    return 0;\n}\n\n\n#ifndef FSEv05_COMMONDEFS_ONLY\n/*-****************************************\n*  FSEv05 helper functions\n******************************************/\nunsigned FSEv05_isError(size_t code) { return ERR_isError(code); }\n\nconst char* FSEv05_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/*-**************************************************************\n*  FSEv05 NCount encoding-decoding\n****************************************************************/\nstatic short FSEv05_abs(short a) { return a<0 ? -a : a; }\n\n\nsize_t FSEv05_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSEv05_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSEv05_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr)) {\n        if (previous0) {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF) {\n                n0+=24;\n                if (ip < iend-5) {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                } else {\n                    bitStream >>= 16;\n                    bitCount+=16;\n            }   }\n            while ((bitStream & 3) == 3) {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {\n            const short max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            } else {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSEv05_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold) {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n    }   }\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nsize_t FSEv05_buildDTable_rle (FSEv05_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv05_decode_t* const cell = (FSEv05_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nsize_t FSEv05_buildDTable_raw (FSEv05_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSEv05_DTableHeader* const DTableH = (FSEv05_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv05_decode_t* const dinfo = (FSEv05_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSymbolValue = tableMask;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<=maxSymbolValue; s++) {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSEv05_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSEv05_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BITv05_DStream_t bitD;\n    FSEv05_DState_t state1;\n    FSEv05_DState_t state2;\n    size_t errorCode;\n\n    /* Init */\n    errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n    if (FSEv05_isError(errorCode)) return errorCode;\n\n    FSEv05_initDState(&state1, &bitD, dt);\n    FSEv05_initDState(&state2, &bitD, dt);\n\n#define FSEv05_GETSYMBOL(statePtr) fast ? FSEv05_decodeSymbolFast(statePtr, &bitD) : FSEv05_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BITv05_reloadDStream(&bitD)==BITv05_DStream_unfinished) && (op<olimit) ; op+=4) {\n        op[0] = FSEv05_GETSYMBOL(&state1);\n\n        if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv05_reloadDStream(&bitD);\n\n        op[1] = FSEv05_GETSYMBOL(&state2);\n\n        if (FSEv05_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BITv05_reloadDStream(&bitD) > BITv05_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSEv05_GETSYMBOL(&state1);\n\n        if (FSEv05_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv05_reloadDStream(&bitD);\n\n        op[3] = FSEv05_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BITv05_reloadDStream(&bitD) >= FSEv05_DStream_partiallyFilled; Ends at exactly BITv05_DStream_completed */\n    while (1) {\n        if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state1))) )\n            break;\n\n        *op++ = FSEv05_GETSYMBOL(&state1);\n\n        if ( (BITv05_reloadDStream(&bitD)>BITv05_DStream_completed) || (op==omax) || (BITv05_endOfDStream(&bitD) && (fast || FSEv05_endOfDState(&state2))) )\n            break;\n\n        *op++ = FSEv05_GETSYMBOL(&state2);\n    }\n\n    /* end ? */\n    if (BITv05_endOfDStream(&bitD) && FSEv05_endOfDState(&state1) && FSEv05_endOfDState(&state2))\n        return op-ostart;\n\n    if (op==omax) return ERROR(dstSize_tooSmall);   /* dst buffer is full, but cSrc unfinished */\n\n    return ERROR(corruption_detected);\n}\n\n\nsize_t FSEv05_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSEv05_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv05_DTableHeader* DTableH = (const FSEv05_DTableHeader*)ptr;\n    const U32 fastMode = DTableH->fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSEv05_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nsize_t FSEv05_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSEv05_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSEv05_MAX_SYMBOL_VALUE;\n    size_t errorCode;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSEv05 decoding mode */\n    errorCode = FSEv05_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n    if (FSEv05_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    errorCode = FSEv05_buildDTable (dt, counting, maxSymbolValue, tableLog);\n    if (FSEv05_isError(errorCode)) return errorCode;\n\n    /* always return, even if it is an error code */\n    return FSEv05_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);\n}\n\n\n\n#endif   /* FSEv05_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFF0_H\n#define HUFF0_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* ****************************************\n*  Huff0 simple functions\n******************************************/\nsize_t HUFv05_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n/*!\nHUFv05_decompress():\n    Decompress Huff0 data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstSize'.\n    @dstSize : must be the **exact** size of original (uncompressed) data.\n    Note : in contrast with FSEv05, HUFv05_decompress can regenerate\n           RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,\n           because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize)\n              or an error code, which can be tested using HUFv05_isError()\n*/\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\n/* Error Management */\nunsigned    HUFv05_isError(size_t code);        /* tells if a return value is an error code */\nconst char* HUFv05_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUF0_H */\n/* ******************************************************************\n   Huff0 : Huffman codec, part of New Generation Entropy library\n   header file, for static linking only\n   Copyright (C) 2013-2016, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUF0_STATIC_H\n#define HUF0_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* static allocation of Huff0's DTable */\n#define HUFv05_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))\n#define HUFv05_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv05_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv05_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv05_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nsize_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n/* ****************************************\n*  Huff0 detailed API\n******************************************/\n/*!\nHUFv05_decompress() does the following:\n1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics\n2. build Huffman table from save, using HUFv05_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUFv05_decompressSXn_usingDTable\n*/\nsize_t HUFv05_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);\nsize_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);\n\nsize_t HUFv05_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv05_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n/* single stream variants */\n\nsize_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */\n\nsize_t HUFv05_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv05_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* HUF0_STATIC_H */\n/* ******************************************************************\n   Huff0 : Huffman coder, part of New Generation Entropy library\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSEv05+Huff0 source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n/* **************************************************************\n*  Includes\n****************************************************************/\n#include <stdlib.h>     /* malloc, free, qsort */\n#include <string.h>     /* memcpy, memset */\n#include <stdio.h>      /* printf (debug) */\n\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n#define HUFv05_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUFv05_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUFv05_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUFv05_ABSOLUTEMAX_TABLELOG */\n#define HUFv05_DEFAULT_TABLELOG  HUFv05_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUFv05_MAX_SYMBOL_VALUE 255\n#if (HUFv05_MAX_TABLELOG > HUFv05_ABSOLUTEMAX_TABLELOG)\n#  error \"HUFv05_MAX_TABLELOG is too large !\"\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\nunsigned HUFv05_isError(size_t code) { return ERR_isError(code); }\nconst char* HUFv05_getErrorName(size_t code) { return ERR_getErrorName(code); }\n#define HUFv05_STATIC_ASSERT(c) { enum { HUFv05_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* *******************************************************\n*  Huff0 : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUFv05_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv05_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n/*! HUFv05_readStats\n    Read compact Huffman tree, saved by HUFv05_writeCTable\n    @huffWeight : destination buffer\n    @return : size read from `src`\n*/\nstatic size_t HUFv05_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    U32 tableLog;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n    U32 n;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* memset(huffWeight, 0, hwSize); */   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  { /* special header */\n        if (iSize >= (242)) {  /* RLE */\n            static int l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else {   /* Incompressible */\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            for (n=0; n<oSize; n+=2) {\n                huffWeight[n]   = ip[n/2] >> 4;\n                huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }\n    else  {   /* header compressed with FSEv05 (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSEv05_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSEv05_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUFv05_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    for (n=0; n<oSize; n++) {\n        if (huffWeight[n] >= HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        rankStats[huffWeight[n]]++;\n        weightTotal += (1 << huffWeight[n]) >> 1;\n    }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    tableLog = BITv05_highbit32(weightTotal) + 1;\n    if (tableLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n    {   /* determine last weight */\n        U32 total = 1 << tableLog;\n        U32 rest = total - weightTotal;\n        U32 verif = 1 << BITv05_highbit32(rest);\n        U32 lastWeight = BITv05_highbit32(rest) + 1;\n        if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n        huffWeight[oSize] = (BYTE)lastWeight;\n        rankStats[lastWeight]++;\n    }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    *tableLogPtr = tableLog;\n    return iSize+1;\n}\n\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\n\nsize_t HUFv05_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUFv05_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    size_t iSize;\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* const dtPtr = DTable + 1;\n    HUFv05_DEltX2* const dt = (HUFv05_DEltX2*)dtPtr;\n\n    HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv05_readStats(huffWeight, HUFv05_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv05_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<=tableLog; n++) {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++) {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUFv05_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\nstatic BYTE HUFv05_decodeSymbolX2(BITv05_DStream_t* Dstream, const HUFv05_DEltX2* dt, const U32 dtLog)\n{\n        const size_t val = BITv05_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n        const BYTE c = dt[val].byte;\n        BITv05_skipBits(Dstream, dt[val].nbBits);\n        return c;\n}\n\n#define HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUFv05_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUFv05_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \\\n        HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUFv05_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUFv05_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUFv05_decodeStreamX2(BYTE* p, BITv05_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv05_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-4)) {\n        HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd))\n        HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUFv05_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\nsize_t HUFv05_decompress1X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + dstSize;\n    const U32 dtLog = DTable[0];\n    const void* dtPtr = DTable;\n    const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr)+1;\n    BITv05_DStream_t bitD;\n\n    if (dstSize <= cSrcSize) return ERROR(dstSize_tooSmall);\n    { size_t const errorCode = BITv05_initDStream(&bitD, cSrc, cSrcSize);\n      if (HUFv05_isError(errorCode)) return errorCode; }\n\n    HUFv05_decodeStreamX2(op, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\nsize_t HUFv05_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv05_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\nsize_t HUFv05_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv05_DStream_t bitD1;\n        BITv05_DStream_t bitD2;\n        BITv05_DStream_t bitD3;\n        BITv05_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv05_initDStream(&bitD1, istart1, length1);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD2, istart2, length2);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD3, istart3, length3);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD4, istart4, length4);\n        if (HUFv05_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv05_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv05_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX2(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n    size_t errorCode;\n\n    errorCode = HUFv05_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv05_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\n\nstatic void HUFv05_fillDTableX4Level2(HUFv05_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUFv05_DEltX4 DElt;\n    U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];\n    U32 s;\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1) {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }\n}\n\ntypedef U32 rankVal_t[HUFv05_ABSOLUTEMAX_TABLELOG][HUFv05_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUFv05_fillDTableX4(HUFv05_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUFv05_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUFv05_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        } else {\n            U32 i;\n            const U32 end = start + length;\n            HUFv05_DEltX4 DElt;\n\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits   = (BYTE)(nbBits);\n            DElt.length   = 1;\n            for (i = start; i < end; i++)\n                DTable[i] = DElt;\n        }\n        rankVal[weight] += length;\n    }\n}\n\nsize_t HUFv05_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUFv05_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUFv05_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUFv05_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUFv05_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    size_t iSize;\n    void* dtPtr = DTable;\n    HUFv05_DEltX4* const dt = ((HUFv05_DEltX4*)dtPtr) + 1;\n\n    HUFv05_STATIC_ASSERT(sizeof(HUFv05_DEltX4) == sizeof(unsigned));   /* if compilation fails here, assertion is false */\n    if (memLog > HUFv05_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    /* memset(weightList, 0, sizeof(weightList)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv05_readStats(weightList, HUFv05_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv05_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {\n        U32 w, nextRankStart = 0;\n        for (w=1; w<=maxW; w++) {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {\n        U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 w = weightList[s];\n            U32 r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {\n        const U32 minBits = tableLog+1 - maxW;\n        U32 nextRankVal = 0;\n        U32 w, consumed;\n        const int rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n        U32* rankVal0 = rankVal[0];\n        for (w=1; w<=maxW; w++) {\n            U32 current = nextRankVal;\n            nextRankVal += rankStats[w] << (w+rescale);\n            rankVal0[w] = current;\n        }\n        for (consumed = minBits; consumed <= memLog - minBits; consumed++) {\n            U32* rankValPtr = rankVal[consumed];\n            for (w = 1; w <= maxW; w++) {\n                rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }\n\n    HUFv05_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUFv05_decodeSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv05_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BITv05_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUFv05_decodeLastSymbolX4(void* op, BITv05_DStream_t* DStream, const HUFv05_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv05_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BITv05_skipBits(DStream, dt[val].nbBits);\n    else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BITv05_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }   }\n    return 1;\n}\n\n\n#define HUFv05_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv05_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv05_MAX_TABLELOG<=12)) \\\n        ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv05_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUFv05_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUFv05_decodeStreamX4(BYTE* p, BITv05_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv05_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p < pEnd-7)) {\n        HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv05_reloadDStream(bitDPtr) == BITv05_DStream_unfinished) && (p <= pEnd-2))\n        HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUFv05_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUFv05_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\nsize_t HUFv05_decompress1X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const unsigned* DTable)\n{\n    const BYTE* const istart = (const BYTE*) cSrc;\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* const oend = ostart + dstSize;\n\n    const U32 dtLog = DTable[0];\n    const void* const dtPtr = DTable;\n    const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;\n    size_t errorCode;\n\n    /* Init */\n    BITv05_DStream_t bitD;\n    errorCode = BITv05_initDStream(&bitD, istart, cSrcSize);\n    if (HUFv05_isError(errorCode)) return errorCode;\n\n    /* finish bitStreams one by one */\n    HUFv05_decodeStreamX4(ostart, &bitD, oend,     dt, dtLog);\n\n    /* check */\n    if (!BITv05_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\nsize_t HUFv05_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv05_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\nsize_t HUFv05_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const unsigned* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {\n        const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv05_DEltX4* const dt = ((const HUFv05_DEltX4*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv05_DStream_t bitD1;\n        BITv05_DStream_t bitD2;\n        BITv05_DStream_t bitD3;\n        BITv05_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv05_initDStream(&bitD1, istart1, length1);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD2, istart2, length2);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD3, istart3, length3);\n        if (HUFv05_isError(errorCode)) return errorCode;\n        errorCode = BITv05_initDStream(&bitD4, istart4, length4);\n        if (HUFv05_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv05_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUFv05_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUFv05_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUFv05_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv05_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv05_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv05_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv05_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv05_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv05_CREATE_STATIC_DTABLEX4(DTable, HUFv05_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv05_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv05_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv05_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/* ********************************/\n/* Generic decompression selector */\n/* ********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nsize_t HUFv05_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUFv05_decompress4X2, HUFv05_decompress4X4, NULL };\n    /* estimate decompression time */\n    U32 Q;\n    const U32 D256 = (U32)(dstSize >> 8);\n    U32 Dtime[3];\n    U32 algoNb = 0;\n    int n;\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize >= dstSize) return ERROR(corruption_detected);   /* invalid, or not compressed, but not compressed already dealt with */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    for (n=0; n<3; n++)\n        Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    if (Dtime[1] < Dtime[0]) algoNb = 1;\n\n    return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n\n    /* return HUFv05_decompress4X2(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams single-symbol decoding */\n    /* return HUFv05_decompress4X4(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams double-symbols decoding */\n    /* return HUFv05_decompress4X6(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams quad-symbols decoding */\n}\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTDv05_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTDv05_HEAPMODE\n#  define ZSTDv05_HEAPMODE 1\n#endif\n\n\n/*-*******************************************************\n*  Dependencies\n*********************************************************/\n#include <stdlib.h>      /* calloc */\n#include <string.h>      /* memcpy, memmove */\n#include <stdio.h>       /* debug only : printf */\n\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/*-*************************************\n*  Local types\n***************************************/\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n\n/* *******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTDv05_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/* *************************************\n*  Error Management\n***************************************/\n/*! ZSTDv05_isError() :\n*   tells if a return value is an error code */\nunsigned ZSTDv05_isError(size_t code) { return ERR_isError(code); }\n\n\n/*! ZSTDv05_getErrorName() :\n*   provides error code string (useful for debugging) */\nconst char* ZSTDv05_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* *************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDv05ds_getFrameHeaderSize, ZSTDv05ds_decodeFrameHeader,\n               ZSTDv05ds_decodeBlockHeader, ZSTDv05ds_decompressBlock } ZSTDv05_dStage;\n\nstruct ZSTDv05_DCtx_s\n{\n    FSEv05_DTable LLTable[FSEv05_DTABLE_SIZE_U32(LLFSEv05Log)];\n    FSEv05_DTable OffTable[FSEv05_DTABLE_SIZE_U32(OffFSEv05Log)];\n    FSEv05_DTable MLTable[FSEv05_DTABLE_SIZE_U32(MLFSEv05Log)];\n    unsigned   hufTableX4[HUFv05_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    size_t headerSize;\n    ZSTDv05_parameters params;\n    blockType_t bType;   /* used in ZSTDv05_decompressContinue(), to transfer blockType between header decoding and block decoding stages */\n    ZSTDv05_dStage stage;\n    U32 flagStaticTables;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[BLOCKSIZE + WILDCOPY_OVERLENGTH];\n    BYTE headerBuffer[ZSTDv05_frameHeaderSize_max];\n};  /* typedef'd to ZSTDv05_DCtx within \"zstd_static.h\" */\n\nsize_t ZSTDv05_sizeofDCtx (void); /* Hidden declaration */\nsize_t ZSTDv05_sizeofDCtx (void) { return sizeof(ZSTDv05_DCtx); }\n\nsize_t ZSTDv05_decompressBegin(ZSTDv05_DCtx* dctx)\n{\n    dctx->expected = ZSTDv05_frameHeaderSize_min;\n    dctx->stage = ZSTDv05ds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    dctx->hufTableX4[0] = ZSTD_HUFFDTABLE_CAPACITY_LOG;\n    dctx->flagStaticTables = 0;\n    return 0;\n}\n\nZSTDv05_DCtx* ZSTDv05_createDCtx(void)\n{\n    ZSTDv05_DCtx* dctx = (ZSTDv05_DCtx*)malloc(sizeof(ZSTDv05_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTDv05_decompressBegin(dctx);\n    return dctx;\n}\n\nsize_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx)\n{\n    free(dctx);\n    return 0;   /* reserved as a potential error code in the future */\n}\n\nvoid ZSTDv05_copyDCtx(ZSTDv05_DCtx* dstDCtx, const ZSTDv05_DCtx* srcDCtx)\n{\n    memcpy(dstDCtx, srcDCtx,\n           sizeof(ZSTDv05_DCtx) - (BLOCKSIZE+WILDCOPY_OVERLENGTH + ZSTDv05_frameHeaderSize_max));  /* no need to copy workspace */\n}\n\n\n/* *************************************************************\n*   Decompression section\n***************************************************************/\n\n/* Frame format description\n   Frame Header -  [ Block Header - Block ] - Frame End\n   1) Frame Header\n      - 4 bytes - Magic Number : ZSTDv05_MAGICNUMBER (defined within zstd_internal.h)\n      - 1 byte  - Window Descriptor\n   2) Block Header\n      - 3 bytes, starting with a 2-bits descriptor\n                 Uncompressed, Compressed, Frame End, unused\n   3) Block\n      See Block Format Description\n   4) Frame End\n      - 3 bytes, compatible with Block Header\n*/\n\n/* Block format description\n\n   Block = Literal Section - Sequences Section\n   Prerequisite : size of (compressed) block, maximum size of regenerated data\n\n   1) Literal Section\n\n   1.1) Header : 1-5 bytes\n        flags: 2 bits\n            00 compressed by Huff0\n            01 unused\n            10 is Raw (uncompressed)\n            11 is Rle\n            Note : using 01 => Huff0 with precomputed table ?\n            Note : delta map ? => compressed ?\n\n   1.1.1) Huff0-compressed literal block : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n   1.1.2) Raw (uncompressed) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RAW<<6) + (0<<4) + size\n               12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RLE<<6) + (0<<4) + size\n               12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n        1- CTable available (stored into workspace ?)\n        2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)\n\n\n   1.2) Literal block content\n\n   1.2.1) Huff0 block, using sizes from header\n        See Huff0 format\n\n   1.2.2) Huff0 block, using prepared table\n\n   1.2.3) Raw content\n\n   1.2.4) single byte\n\n\n   2) Sequences section\n      TO DO\n*/\n\n\n/** ZSTDv05_decodeFrameHeader_Part1() :\n*   decode the 1st part of the Frame Header, which tells Frame Header size.\n*   srcSize must be == ZSTDv05_frameHeaderSize_min.\n*   @return : the full size of the Frame Header */\nstatic size_t ZSTDv05_decodeFrameHeader_Part1(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize != ZSTDv05_frameHeaderSize_min)\n        return ERROR(srcSize_wrong);\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);\n    zc->headerSize = ZSTDv05_frameHeaderSize_min;\n    return zc->headerSize;\n}\n\n\nsize_t ZSTDv05_getFrameParams(ZSTDv05_parameters* params, const void* src, size_t srcSize)\n{\n    U32 magicNumber;\n    if (srcSize < ZSTDv05_frameHeaderSize_min) return ZSTDv05_frameHeaderSize_max;\n    magicNumber = MEM_readLE32(src);\n    if (magicNumber != ZSTDv05_MAGICNUMBER) return ERROR(prefix_unknown);\n    memset(params, 0, sizeof(*params));\n    params->windowLog = (((const BYTE*)src)[4] & 15) + ZSTDv05_WINDOWLOG_ABSOLUTEMIN;\n    if ((((const BYTE*)src)[4] >> 4) != 0) return ERROR(frameParameter_unsupported);   /* reserved bits */\n    return 0;\n}\n\n/** ZSTDv05_decodeFrameHeader_Part2() :\n*   decode the full Frame Header.\n*   srcSize must be the size provided by ZSTDv05_decodeFrameHeader_Part1().\n*   @return : 0, or an error code, which can be tested using ZSTDv05_isError() */\nstatic size_t ZSTDv05_decodeFrameHeader_Part2(ZSTDv05_DCtx* zc, const void* src, size_t srcSize)\n{\n    size_t result;\n    if (srcSize != zc->headerSize)\n        return ERROR(srcSize_wrong);\n    result = ZSTDv05_getFrameParams(&(zc->params), src, srcSize);\n    if ((MEM_32bits()) && (zc->params.windowLog > 25)) return ERROR(frameParameter_unsupported);\n    return result;\n}\n\n\nstatic size_t ZSTDv05_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE*)src;\n    BYTE headerFlags;\n    U32 cSize;\n\n    if (srcSize < 3)\n        return ERROR(srcSize_wrong);\n\n    headerFlags = *in;\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n\n    bpPtr->blockType = (blockType_t)(headerFlags >> 6);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTDv05_copyRawBlock(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    if (dst==NULL) return ERROR(dstSize_tooSmall);\n    if (srcSize > maxDstSize) return ERROR(dstSize_tooSmall);\n    memcpy(dst, src, srcSize);\n    return srcSize;\n}\n\n\n/*! ZSTDv05_decodeLiteralsBlock() :\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTDv05_decodeLiteralsBlock(ZSTDv05_DCtx* dctx,\n                                    const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(istart[0]>> 6)\n    {\n    case IS_HUFv05:\n        {\n            size_t litSize, litCSize, singleStream=0;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (srcSize < 5) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                /* 2 - 2 - 10 - 10 */\n                lhSize=3;\n                singleStream = istart[0] & 16;\n                litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n                litCSize = ((istart[1] &  3) << 8) + istart[2];\n                break;\n            case 2:\n                /* 2 - 2 - 14 - 14 */\n                lhSize=4;\n                litSize  = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);\n                litCSize = ((istart[2] & 63) <<  8) + istart[3];\n                break;\n            case 3:\n                /* 2 - 2 - 18 - 18 */\n                lhSize=5;\n                litSize  = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);\n                litCSize = ((istart[2] &  3) << 16) + (istart[3] << 8) + istart[4];\n                break;\n            }\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            if (HUFv05_isError(singleStream ?\n                            HUFv05_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :\n                            HUFv05_decompress   (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))\n                return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_PCH:\n        {\n            size_t errorCode;\n            size_t litSize, litCSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (lhSize != 1)  /* only case supported for now : small litSize, single stream */\n                return ERROR(corruption_detected);\n            if (!dctx->flagStaticTables)\n                return ERROR(dictionary_corrupted);\n\n            /* 2 - 2 - 10 - 10 */\n            lhSize=3;\n            litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n            litCSize = ((istart[1] &  3) << 8) + istart[2];\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            errorCode = HUFv05_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);\n            if (HUFv05_isError(errorCode)) return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_RAW:\n        {\n            size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize=1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                break;\n            }\n\n            if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                if (litSize+lhSize > srcSize) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart+lhSize, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n                return lhSize+litSize;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+lhSize;\n            dctx->litSize = litSize;\n            return lhSize+litSize;\n        }\n    case IS_RLE:\n        {\n            size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize = 1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                if (srcSize<4) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */\n                break;\n            }\n            if (litSize > BLOCKSIZE) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return lhSize+1;\n        }\n    default:\n        return ERROR(corruption_detected);   /* impossible */\n    }\n}\n\n\nstatic size_t ZSTDv05_decodeSeqHeaders(int* nbSeq, const BYTE** dumpsPtr, size_t* dumpsLengthPtr,\n                         FSEv05_DTable* DTableLL, FSEv05_DTable* DTableML, FSEv05_DTable* DTableOffb,\n                         const void* src, size_t srcSize, U32 flagStaticTable)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* ip = istart;\n    const BYTE* const iend = istart + srcSize;\n    U32 LLtype, Offtype, MLtype;\n    unsigned LLlog, Offlog, MLlog;\n    size_t dumpsLength;\n\n    /* check */\n    if (srcSize < MIN_SEQUENCES_SIZE)\n        return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    *nbSeq = *ip++;\n    if (*nbSeq==0) return 1;\n    if (*nbSeq >= 128) {\n        if (ip >= iend) return ERROR(srcSize_wrong);\n        *nbSeq = ((nbSeq[0]-128)<<8) + *ip++;\n    }\n\n    if (ip >= iend) return ERROR(srcSize_wrong);\n    LLtype  = *ip >> 6;\n    Offtype = (*ip >> 4) & 3;\n    MLtype  = (*ip >> 2) & 3;\n    if (*ip & 2) {\n        if (ip+3 > iend) return ERROR(srcSize_wrong);\n        dumpsLength  = ip[2];\n        dumpsLength += ip[1] << 8;\n        ip += 3;\n    } else {\n        if (ip+2 > iend) return ERROR(srcSize_wrong);\n        dumpsLength  = ip[1];\n        dumpsLength += (ip[0] & 1) << 8;\n        ip += 2;\n    }\n    *dumpsPtr = ip;\n    ip += dumpsLength;\n    *dumpsLengthPtr = dumpsLength;\n\n    /* check */\n    if (ip > iend-3) return ERROR(srcSize_wrong); /* min : all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n\n    /* sequences */\n    {\n        S16 norm[MaxML+1];    /* assumption : MaxML >= MaxLL >= MaxOff */\n        size_t headerSize;\n\n        /* Build DTables */\n        switch(LLtype)\n        {\n        case FSEv05_ENCODING_RLE :\n            LLlog = 0;\n            FSEv05_buildDTable_rle(DTableLL, *ip++);\n            break;\n        case FSEv05_ENCODING_RAW :\n            LLlog = LLbits;\n            FSEv05_buildDTable_raw(DTableLL, LLbits);\n            break;\n        case FSEv05_ENCODING_STATIC:\n            if (!flagStaticTable) return ERROR(corruption_detected);\n            break;\n        case FSEv05_ENCODING_DYNAMIC :\n        default :   /* impossible */\n            {   unsigned max = MaxLL;\n                headerSize = FSEv05_readNCount(norm, &max, &LLlog, ip, iend-ip);\n                if (FSEv05_isError(headerSize)) return ERROR(GENERIC);\n                if (LLlog > LLFSEv05Log) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSEv05_buildDTable(DTableLL, norm, max, LLlog);\n        }   }\n\n        switch(Offtype)\n        {\n        case FSEv05_ENCODING_RLE :\n            Offlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong);   /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSEv05_buildDTable_rle(DTableOffb, *ip++ & MaxOff); /* if *ip > MaxOff, data is corrupted */\n            break;\n        case FSEv05_ENCODING_RAW :\n            Offlog = Offbits;\n            FSEv05_buildDTable_raw(DTableOffb, Offbits);\n            break;\n        case FSEv05_ENCODING_STATIC:\n            if (!flagStaticTable) return ERROR(corruption_detected);\n            break;\n        case FSEv05_ENCODING_DYNAMIC :\n        default :   /* impossible */\n            {   unsigned max = MaxOff;\n                headerSize = FSEv05_readNCount(norm, &max, &Offlog, ip, iend-ip);\n                if (FSEv05_isError(headerSize)) return ERROR(GENERIC);\n                if (Offlog > OffFSEv05Log) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSEv05_buildDTable(DTableOffb, norm, max, Offlog);\n        }   }\n\n        switch(MLtype)\n        {\n        case FSEv05_ENCODING_RLE :\n            MLlog = 0;\n            if (ip > iend-2) return ERROR(srcSize_wrong); /* min : \"raw\", hence no header, but at least xxLog bits */\n            FSEv05_buildDTable_rle(DTableML, *ip++);\n            break;\n        case FSEv05_ENCODING_RAW :\n            MLlog = MLbits;\n            FSEv05_buildDTable_raw(DTableML, MLbits);\n            break;\n        case FSEv05_ENCODING_STATIC:\n            if (!flagStaticTable) return ERROR(corruption_detected);\n            break;\n        case FSEv05_ENCODING_DYNAMIC :\n        default :   /* impossible */\n            {   unsigned max = MaxML;\n                headerSize = FSEv05_readNCount(norm, &max, &MLlog, ip, iend-ip);\n                if (FSEv05_isError(headerSize)) return ERROR(GENERIC);\n                if (MLlog > MLFSEv05Log) return ERROR(corruption_detected);\n                ip += headerSize;\n                FSEv05_buildDTable(DTableML, norm, max, MLlog);\n    }   }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    BITv05_DStream_t DStream;\n    FSEv05_DState_t stateLL;\n    FSEv05_DState_t stateOffb;\n    FSEv05_DState_t stateML;\n    size_t prevOffset;\n    const BYTE* dumps;\n    const BYTE* dumpsEnd;\n} seqState_t;\n\n\n\nstatic void ZSTDv05_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    size_t litLength;\n    size_t prevOffset;\n    size_t offset;\n    size_t matchLength;\n    const BYTE* dumps = seqState->dumps;\n    const BYTE* const de = seqState->dumpsEnd;\n\n    /* Literal length */\n    litLength = FSEv05_peakSymbol(&(seqState->stateLL));\n    prevOffset = litLength ? seq->offset : seqState->prevOffset;\n    if (litLength == MaxLL) {\n        const U32 add = *dumps++;\n        if (add < 255) litLength += add;\n        else if (dumps + 2 <= de) {\n            litLength = MEM_readLE16(dumps);\n            dumps += 2;\n            if ((litLength & 1) && dumps < de) {\n                litLength += *dumps << 16;\n                dumps += 1;\n            }\n            litLength>>=1;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n\n    /* Offset */\n    {\n        static const U32 offsetPrefix[MaxOff+1] = {\n                1 /*fake*/, 1, 2, 4, 8, 16, 32, 64, 128, 256,\n                512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144,\n                524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, /*fake*/ 1, 1, 1, 1, 1 };\n        U32 offsetCode = FSEv05_peakSymbol(&(seqState->stateOffb));   /* <= maxOff, by table construction */\n        U32 nbBits = offsetCode - 1;\n        if (offsetCode==0) nbBits = 0;   /* cmove */\n        offset = offsetPrefix[offsetCode] + BITv05_readBits(&(seqState->DStream), nbBits);\n        if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));\n        if (offsetCode==0) offset = prevOffset;   /* repcode, cmove */\n        if (offsetCode | !litLength) seqState->prevOffset = seq->offset;   /* cmove */\n        FSEv05_decodeSymbol(&(seqState->stateOffb), &(seqState->DStream));    /* update */\n    }\n\n    /* Literal length update */\n    FSEv05_decodeSymbol(&(seqState->stateLL), &(seqState->DStream));   /* update */\n    if (MEM_32bits()) BITv05_reloadDStream(&(seqState->DStream));\n\n    /* MatchLength */\n    matchLength = FSEv05_decodeSymbol(&(seqState->stateML), &(seqState->DStream));\n    if (matchLength == MaxML) {\n        const U32 add = dumps<de ? *dumps++ : 0;\n        if (add < 255) matchLength += add;\n        else if (dumps + 2 <= de) {\n            matchLength = MEM_readLE16(dumps);\n            dumps += 2;\n            if ((matchLength & 1) && dumps < de) {\n                matchLength += *dumps << 16;\n                dumps += 1;\n            }\n            matchLength >>= 1;\n        }\n        if (dumps >= de) { dumps = de-1; }  /* late correction, to avoid read overflow (data is now corrupted anyway) */\n    }\n    matchLength += MINMATCH;\n\n    /* save result */\n    seq->litLength = litLength;\n    seq->offset = offset;\n    seq->matchLength = matchLength;\n    seqState->dumps = dumps;\n\n#if 0   /* debug */\n    {\n        static U64 totalDecoded = 0;\n        printf(\"pos %6u : %3u literals & match %3u bytes at distance %6u \\n\",\n           (U32)(totalDecoded), (U32)litLength, (U32)matchLength, (U32)offset);\n        totalDecoded += litLength + matchLength;\n    }\n#endif\n}\n\n\nstatic size_t ZSTDv05_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    static const int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n    static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n    BYTE* const oLitEnd = op + sequence.litLength;\n    const size_t sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const litEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (litEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTDv05_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = litEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base)) {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase))\n            return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd) {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {\n            size_t length1 = dictEnd - match;\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_8 || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n    }   }\n    /* Requirement: op <= oend_8 */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        const int sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTDv05_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTDv05_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH)) {\n        if (op < oend_8) {\n            ZSTDv05_wildcopy(op, match, oend_8 - op);\n            match += oend_8 - op;\n            op = oend_8;\n        }\n        while (op < oMatchEnd)\n            *op++ = *match++;\n    } else {\n        ZSTDv05_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTDv05_decompressSequences(\n                               ZSTDv05_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t errorCode, dumpsLength=0;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    int nbSeq=0;\n    const BYTE* dumps = NULL;\n    unsigned* DTableLL = dctx->LLTable;\n    unsigned* DTableML = dctx->MLTable;\n    unsigned* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n\n    /* Build Decoding Tables */\n    errorCode = ZSTDv05_decodeSeqHeaders(&nbSeq, &dumps, &dumpsLength,\n                                      DTableLL, DTableML, DTableOffb,\n                                      ip, seqSize, dctx->flagStaticTables);\n    if (ZSTDv05_isError(errorCode)) return errorCode;\n    ip += errorCode;\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        sequence.offset = REPCODE_STARTVALUE;\n        seqState.dumps = dumps;\n        seqState.dumpsEnd = dumps + dumpsLength;\n        seqState.prevOffset = REPCODE_STARTVALUE;\n        errorCode = BITv05_initDStream(&(seqState.DStream), ip, iend-ip);\n        if (ERR_isError(errorCode)) return ERROR(corruption_detected);\n        FSEv05_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSEv05_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSEv05_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BITv05_reloadDStream(&(seqState.DStream)) <= BITv05_DStream_completed) && nbSeq ; ) {\n            size_t oneSeqSize;\n            nbSeq--;\n            ZSTDv05_decodeSequence(&sequence, &seqState);\n            oneSeqSize = ZSTDv05_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n            if (ZSTDv05_isError(oneSeqSize)) return oneSeqSize;\n            op += oneSeqSize;\n        }\n\n        /* check if reached exact end */\n        if (nbSeq) return ERROR(corruption_detected);\n    }\n\n    /* last literal segment */\n    {\n        size_t lastLLSize = litEnd - litPtr;\n        if (litPtr > litEnd) return ERROR(corruption_detected);   /* too many literals already used */\n        if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n        if (lastLLSize > 0) {\n            memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTDv05_checkContinuity(ZSTDv05_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTDv05_decompressBlock_internal(ZSTDv05_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n    size_t litCSize;\n\n    if (srcSize >= BLOCKSIZE) return ERROR(srcSize_wrong);\n\n    /* Decode literals sub-block */\n    litCSize = ZSTDv05_decodeLiteralsBlock(dctx, src, srcSize);\n    if (ZSTDv05_isError(litCSize)) return litCSize;\n    ip += litCSize;\n    srcSize -= litCSize;\n\n    return ZSTDv05_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);\n}\n\n\nsize_t ZSTDv05_decompressBlock(ZSTDv05_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    ZSTDv05_checkContinuity(dctx, dst);\n    return ZSTDv05_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\n/*! ZSTDv05_decompress_continueDCtx\n*   dctx must have been properly initialized */\nstatic size_t ZSTDv05_decompress_continueDCtx(ZSTDv05_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                                 const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + maxDstSize;\n    size_t remainingSize = srcSize;\n    blockProperties_t blockProperties;\n    memset(&blockProperties, 0, sizeof(blockProperties));\n\n    /* Frame Header */\n    {   size_t frameHeaderSize;\n        if (srcSize < ZSTDv05_frameHeaderSize_min+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);\n        frameHeaderSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);\n        if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTDv05_blockHeaderSize) return ERROR(srcSize_wrong);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n        frameHeaderSize = ZSTDv05_decodeFrameHeader_Part2(dctx, src, frameHeaderSize);\n        if (ZSTDv05_isError(frameHeaderSize)) return frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t decodedSize=0;\n        size_t cBlockSize = ZSTDv05_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv05_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTDv05_blockHeaderSize;\n        remainingSize -= ZSTDv05_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTDv05_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTDv05_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTDv05_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n\nsize_t ZSTDv05_decompress_usingPreparedDCtx(ZSTDv05_DCtx* dctx, const ZSTDv05_DCtx* refDCtx,\n                                         void* dst, size_t maxDstSize,\n                                   const void* src, size_t srcSize)\n{\n    ZSTDv05_copyDCtx(dctx, refDCtx);\n    ZSTDv05_checkContinuity(dctx, dst);\n    return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);\n}\n\n\nsize_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx,\n                                 void* dst, size_t maxDstSize,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    ZSTDv05_decompressBegin_usingDict(dctx, dict, dictSize);\n    ZSTDv05_checkContinuity(dctx, dst);\n    return ZSTDv05_decompress_continueDCtx(dctx, dst, maxDstSize, src, srcSize);\n}\n\n\nsize_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    return ZSTDv05_decompress_usingDict(dctx, dst, maxDstSize, src, srcSize, NULL, 0);\n}\n\nsize_t ZSTDv05_decompress(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n#if defined(ZSTDv05_HEAPMODE) && (ZSTDv05_HEAPMODE==1)\n    size_t regenSize;\n    ZSTDv05_DCtx* dctx = ZSTDv05_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv05_decompressDCtx(dctx, dst, maxDstSize, src, srcSize);\n    ZSTDv05_freeDCtx(dctx);\n    return regenSize;\n#else\n    ZSTDv05_DCtx dctx;\n    return ZSTDv05_decompressDCtx(&dctx, dst, maxDstSize, src, srcSize);\n#endif\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    blockProperties_t blockProperties;\n\n    /* Frame Header */\n    if (srcSize < ZSTDv05_frameHeaderSize_min) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n    if (MEM_readLE32(src) != ZSTDv05_MAGICNUMBER) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n        return;\n    }\n    ip += ZSTDv05_frameHeaderSize_min; remainingSize -= ZSTDv05_frameHeaderSize_min;\n\n    /* Loop on each block */\n    while (1)\n    {\n        size_t cBlockSize = ZSTDv05_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv05_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTDv05_blockHeaderSize;\n        remainingSize -= ZSTDv05_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * BLOCKSIZE;\n}\n\n/* ******************************\n*  Streaming Decompression API\n********************************/\nsize_t ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nsize_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != dctx->expected) return ERROR(srcSize_wrong);\n    ZSTDv05_checkContinuity(dctx, dst);\n\n    /* Decompress : frame header; part 1 */\n    switch (dctx->stage)\n    {\n    case ZSTDv05ds_getFrameHeaderSize :\n        /* get frame header size */\n        if (srcSize != ZSTDv05_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        dctx->headerSize = ZSTDv05_decodeFrameHeader_Part1(dctx, src, ZSTDv05_frameHeaderSize_min);\n        if (ZSTDv05_isError(dctx->headerSize)) return dctx->headerSize;\n        memcpy(dctx->headerBuffer, src, ZSTDv05_frameHeaderSize_min);\n        if (dctx->headerSize > ZSTDv05_frameHeaderSize_min) return ERROR(GENERIC); /* should never happen */\n        dctx->expected = 0;   /* not necessary to copy more */\n        /* fallthrough */\n    case ZSTDv05ds_decodeFrameHeader:\n        /* get frame header */\n        {   size_t const result = ZSTDv05_decodeFrameHeader_Part2(dctx, dctx->headerBuffer, dctx->headerSize);\n            if (ZSTDv05_isError(result)) return result;\n            dctx->expected = ZSTDv05_blockHeaderSize;\n            dctx->stage = ZSTDv05ds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDv05ds_decodeBlockHeader:\n        {\n            /* Decode block header */\n            blockProperties_t bp;\n            size_t blockSize = ZSTDv05_getcBlockSize(src, ZSTDv05_blockHeaderSize, &bp);\n            if (ZSTDv05_isError(blockSize)) return blockSize;\n            if (bp.blockType == bt_end) {\n                dctx->expected = 0;\n                dctx->stage = ZSTDv05ds_getFrameHeaderSize;\n            }\n            else {\n                dctx->expected = blockSize;\n                dctx->bType = bp.blockType;\n                dctx->stage = ZSTDv05ds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDv05ds_decompressBlock:\n        {\n            /* Decompress : block content */\n            size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTDv05_decompressBlock_internal(dctx, dst, maxDstSize, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTDv05_copyRawBlock(dst, maxDstSize, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);   /* impossible */\n            }\n            dctx->stage = ZSTDv05ds_decodeBlockHeader;\n            dctx->expected = ZSTDv05_blockHeaderSize;\n            if (ZSTDv05_isError(rSize)) return rSize;\n            dctx->previousDstEnd = (char*)dst + rSize;\n            return rSize;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic void ZSTDv05_refDictContent(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n    dctx->base = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n}\n\nstatic size_t ZSTDv05_loadEntropy(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, errorCode, litlengthHeaderSize;\n    short offcodeNCount[MaxOff+1];\n    unsigned offcodeMaxValue=MaxOff, offcodeLog;\n    short matchlengthNCount[MaxML+1];\n    unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n    short litlengthNCount[MaxLL+1];\n    unsigned litlengthMaxValue = MaxLL, litlengthLog;\n\n    hSize = HUFv05_readDTableX4(dctx->hufTableX4, dict, dictSize);\n    if (HUFv05_isError(hSize)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + hSize;\n    dictSize -= hSize;\n\n    offcodeHeaderSize = FSEv05_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);\n    if (FSEv05_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);\n    if (offcodeLog > OffFSEv05Log) return ERROR(dictionary_corrupted);\n    errorCode = FSEv05_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);\n    if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + offcodeHeaderSize;\n    dictSize -= offcodeHeaderSize;\n\n    matchlengthHeaderSize = FSEv05_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);\n    if (FSEv05_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);\n    if (matchlengthLog > MLFSEv05Log) return ERROR(dictionary_corrupted);\n    errorCode = FSEv05_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);\n    if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + matchlengthHeaderSize;\n    dictSize -= matchlengthHeaderSize;\n\n    litlengthHeaderSize = FSEv05_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);\n    if (litlengthLog > LLFSEv05Log) return ERROR(dictionary_corrupted);\n    if (FSEv05_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);\n    errorCode = FSEv05_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);\n    if (FSEv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n\n    dctx->flagStaticTables = 1;\n    return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;\n}\n\nstatic size_t ZSTDv05_decompress_insertDictionary(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t eSize;\n    U32 magic = MEM_readLE32(dict);\n    if (magic != ZSTDv05_DICT_MAGIC) {\n        /* pure content mode */\n        ZSTDv05_refDictContent(dctx, dict, dictSize);\n        return 0;\n    }\n    /* load entropy tables */\n    dict = (const char*)dict + 4;\n    dictSize -= 4;\n    eSize = ZSTDv05_loadEntropy(dctx, dict, dictSize);\n    if (ZSTDv05_isError(eSize)) return ERROR(dictionary_corrupted);\n\n    /* reference dictionary content */\n    dict = (const char*)dict + eSize;\n    dictSize -= eSize;\n    ZSTDv05_refDictContent(dctx, dict, dictSize);\n\n    return 0;\n}\n\n\nsize_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t errorCode;\n    errorCode = ZSTDv05_decompressBegin(dctx);\n    if (ZSTDv05_isError(errorCode)) return errorCode;\n\n    if (dict && dictSize) {\n        errorCode = ZSTDv05_decompress_insertDictionary(dctx, dict, dictSize);\n        if (ZSTDv05_isError(errorCode)) return ERROR(dictionary_corrupted);\n    }\n\n    return 0;\n}\n\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd source repository : https://github.com/Cyan4973/zstd\n    - ztsd public forum : https://groups.google.com/forum/#!forum/lz4c\n*/\n\n/* The objects defined into this file should be considered experimental.\n * They are not labelled stable, as their prototype may change in the future.\n * You can use them for tests, provide feedback, or if you can endure risk of future changes.\n */\n\n\n\n/* *************************************\n*  Constants\n***************************************/\nstatic size_t ZBUFFv05_blockHeaderSize = 3;\n\n\n\n/* *** Compression *** */\n\nstatic size_t ZBUFFv05_limitCopy(void* dst, size_t maxDstSize, const void* src, size_t srcSize)\n{\n    size_t length = MIN(maxDstSize, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n\n\n\n/** ************************************************\n*  Streaming decompression\n*\n*  A ZBUFFv05_DCtx object is required to track streaming operation.\n*  Use ZBUFFv05_createDCtx() and ZBUFFv05_freeDCtx() to create/release resources.\n*  Use ZBUFFv05_decompressInit() to start a new decompression operation.\n*  ZBUFFv05_DCtx objects can be reused multiple times.\n*\n*  Use ZBUFFv05_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *maxDstSizePtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *maxDstSizePtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to call again the function with remaining input.\n*  The content of dst will be overwritten (up to *maxDstSizePtr) at each function call, so save its content if it matters or change dst .\n*  return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to improve latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFFv05_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory)\n*  output : 128 KB block size is the internal unit, it ensures it's always possible to write a full block when it's decoded.\n*  input : just follow indications from ZBUFFv05_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* **************************************************/\n\ntypedef enum { ZBUFFv05ds_init, ZBUFFv05ds_readHeader, ZBUFFv05ds_loadHeader, ZBUFFv05ds_decodeHeader,\n               ZBUFFv05ds_read, ZBUFFv05ds_load, ZBUFFv05ds_flush } ZBUFFv05_dStage;\n\n/* *** Resource management *** */\n\n#define ZSTDv05_frameHeaderSize_max 5   /* too magical, should come from reference */\nstruct ZBUFFv05_DCtx_s {\n    ZSTDv05_DCtx* zc;\n    ZSTDv05_parameters params;\n    char* inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char* outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t hPos;\n    ZBUFFv05_dStage stage;\n    unsigned char headerBuffer[ZSTDv05_frameHeaderSize_max];\n};   /* typedef'd to ZBUFFv05_DCtx within \"zstd_buffered.h\" */\n\n\nZBUFFv05_DCtx* ZBUFFv05_createDCtx(void)\n{\n    ZBUFFv05_DCtx* zbc = (ZBUFFv05_DCtx*)malloc(sizeof(ZBUFFv05_DCtx));\n    if (zbc==NULL) return NULL;\n    memset(zbc, 0, sizeof(*zbc));\n    zbc->zc = ZSTDv05_createDCtx();\n    zbc->stage = ZBUFFv05ds_init;\n    return zbc;\n}\n\nsize_t ZBUFFv05_freeDCtx(ZBUFFv05_DCtx* zbc)\n{\n    if (zbc==NULL) return 0;   /* support free on null */\n    ZSTDv05_freeDCtx(zbc->zc);\n    free(zbc->inBuff);\n    free(zbc->outBuff);\n    free(zbc);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nsize_t ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx* zbc, const void* dict, size_t dictSize)\n{\n    zbc->stage = ZBUFFv05ds_readHeader;\n    zbc->hPos = zbc->inPos = zbc->outStart = zbc->outEnd = 0;\n    return ZSTDv05_decompressBegin_usingDict(zbc->zc, dict, dictSize);\n}\n\nsize_t ZBUFFv05_decompressInit(ZBUFFv05_DCtx* zbc)\n{\n    return ZBUFFv05_decompressInitDictionary(zbc, NULL, 0);\n}\n\n\n/* *** Decompression *** */\n\nsize_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* zbc, void* dst, size_t* maxDstSizePtr, const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* ip = istart;\n    const char* const iend = istart + *srcSizePtr;\n    char* const ostart = (char*)dst;\n    char* op = ostart;\n    char* const oend = ostart + *maxDstSizePtr;\n    U32 notDone = 1;\n\n    while (notDone) {\n        switch(zbc->stage)\n        {\n        case ZBUFFv05ds_init :\n            return ERROR(init_missing);\n\n        case ZBUFFv05ds_readHeader :\n            /* read header from src */\n            {\n                size_t headerSize = ZSTDv05_getFrameParams(&(zbc->params), src, *srcSizePtr);\n                if (ZSTDv05_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    memcpy(zbc->headerBuffer+zbc->hPos, src, *srcSizePtr);\n                    zbc->hPos += *srcSizePtr;\n                    *maxDstSizePtr = 0;\n                    zbc->stage = ZBUFFv05ds_loadHeader;\n                    return headerSize - zbc->hPos;\n                }\n                zbc->stage = ZBUFFv05ds_decodeHeader;\n                break;\n            }\n\t    /* fall-through */\n        case ZBUFFv05ds_loadHeader:\n            /* complete header from src */\n            {\n                size_t headerSize = ZBUFFv05_limitCopy(\n                    zbc->headerBuffer + zbc->hPos, ZSTDv05_frameHeaderSize_max - zbc->hPos,\n                    src, *srcSizePtr);\n                zbc->hPos += headerSize;\n                ip += headerSize;\n                headerSize = ZSTDv05_getFrameParams(&(zbc->params), zbc->headerBuffer, zbc->hPos);\n                if (ZSTDv05_isError(headerSize)) return headerSize;\n                if (headerSize) {\n                    /* not enough input to decode header : tell how many bytes would be necessary */\n                    *maxDstSizePtr = 0;\n                    return headerSize - zbc->hPos;\n                }\n                /* zbc->stage = ZBUFFv05ds_decodeHeader; break; */   /* useless : stage follows */\n            }\n\t    /* fall-through */\n        case ZBUFFv05ds_decodeHeader:\n                /* apply header to create / resize buffers */\n                {\n                    size_t neededOutSize = (size_t)1 << zbc->params.windowLog;\n                    size_t neededInSize = BLOCKSIZE;   /* a block is never > BLOCKSIZE */\n                    if (zbc->inBuffSize < neededInSize) {\n                        free(zbc->inBuff);\n                        zbc->inBuffSize = neededInSize;\n                        zbc->inBuff = (char*)malloc(neededInSize);\n                        if (zbc->inBuff == NULL) return ERROR(memory_allocation);\n                    }\n                    if (zbc->outBuffSize < neededOutSize) {\n                        free(zbc->outBuff);\n                        zbc->outBuffSize = neededOutSize;\n                        zbc->outBuff = (char*)malloc(neededOutSize);\n                        if (zbc->outBuff == NULL) return ERROR(memory_allocation);\n                }   }\n                if (zbc->hPos) {\n                    /* some data already loaded into headerBuffer : transfer into inBuff */\n                    memcpy(zbc->inBuff, zbc->headerBuffer, zbc->hPos);\n                    zbc->inPos = zbc->hPos;\n                    zbc->hPos = 0;\n                    zbc->stage = ZBUFFv05ds_load;\n                    break;\n                }\n                zbc->stage = ZBUFFv05ds_read;\n\t\t/* fall-through */\n        case ZBUFFv05ds_read:\n            {\n                size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);\n                if (neededInSize==0) {  /* end of frame */\n                    zbc->stage = ZBUFFv05ds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {\n                    /* directly decode from src */\n                    size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        ip, neededInSize);\n                    if (ZSTDv05_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize) break;   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFv05ds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbc->stage = ZBUFFv05ds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFv05ds_load:\n            {\n                size_t neededInSize = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);\n                size_t toLoad = neededInSize - zbc->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbc->inBuffSize - zbc->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFFv05_limitCopy(zbc->inBuff + zbc->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbc->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n                {\n                    size_t decodedSize = ZSTDv05_decompressContinue(zbc->zc,\n                        zbc->outBuff + zbc->outStart, zbc->outBuffSize - zbc->outStart,\n                        zbc->inBuff, neededInSize);\n                    if (ZSTDv05_isError(decodedSize)) return decodedSize;\n                    zbc->inPos = 0;   /* input is consumed */\n                    if (!decodedSize) { zbc->stage = ZBUFFv05ds_read; break; }   /* this was just a header */\n                    zbc->outEnd = zbc->outStart +  decodedSize;\n                    zbc->stage = ZBUFFv05ds_flush;\n                    /* break; */  /* ZBUFFv05ds_flush follows */\n                }\n\t    }\n\t    /* fall-through */\n        case ZBUFFv05ds_flush:\n            {\n                size_t toFlushSize = zbc->outEnd - zbc->outStart;\n                size_t flushedSize = ZBUFFv05_limitCopy(op, oend-op, zbc->outBuff + zbc->outStart, toFlushSize);\n                op += flushedSize;\n                zbc->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {\n                    zbc->stage = ZBUFFv05ds_read;\n                    if (zbc->outStart + BLOCKSIZE > zbc->outBuffSize)\n                        zbc->outStart = zbc->outEnd = 0;\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n    }   }\n\n    *srcSizePtr = ip-istart;\n    *maxDstSizePtr = op-ostart;\n\n    {   size_t nextSrcSizeHint = ZSTDv05_nextSrcSizeToDecompress(zbc->zc);\n        if (nextSrcSizeHint > ZBUFFv05_blockHeaderSize) nextSrcSizeHint+= ZBUFFv05_blockHeaderSize;   /* get next block header too */\n        nextSrcSizeHint -= zbc->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nunsigned ZBUFFv05_isError(size_t errorCode) { return ERR_isError(errorCode); }\nconst char* ZBUFFv05_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n\nsize_t ZBUFFv05_recommendedDInSize(void)  { return BLOCKSIZE + ZBUFFv05_blockHeaderSize /* block header size*/ ; }\nsize_t ZBUFFv05_recommendedDOutSize(void) { return BLOCKSIZE; }\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v05.h",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTDv05_H\n#define ZSTDv05_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-*************************************\n*  Dependencies\n***************************************/\n#include <stddef.h>   /* size_t */\n#include \"../common/mem.h\"      /* U64, U32 */\n\n\n/* *************************************\n*  Simple functions\n***************************************/\n/*! ZSTDv05_decompress() :\n    `compressedSize` : is the _exact_ size of the compressed blob, otherwise decompression will fail.\n    `dstCapacity` must be large enough, equal or larger than originalSize.\n    @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n              or an errorCode if it fails (which can be tested using ZSTDv05_isError()) */\nsize_t ZSTDv05_decompress( void* dst, size_t dstCapacity,\n                     const void* src, size_t compressedSize);\n\n /**\n ZSTDv05_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.5.x format\n     srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n     cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                 or an error code if it fails (which can be tested using ZSTDv01_isError())\n     dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                 or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n */\nvoid ZSTDv05_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/* *************************************\n*  Helper functions\n***************************************/\n/* Error Management */\nunsigned    ZSTDv05_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */\nconst char* ZSTDv05_getErrorName(size_t code);     /*!< provides readable string for an error code */\n\n\n/* *************************************\n*  Explicit memory management\n***************************************/\n/** Decompression context */\ntypedef struct ZSTDv05_DCtx_s ZSTDv05_DCtx;\nZSTDv05_DCtx* ZSTDv05_createDCtx(void);\nsize_t ZSTDv05_freeDCtx(ZSTDv05_DCtx* dctx);      /*!< @return : errorCode */\n\n/** ZSTDv05_decompressDCtx() :\n*   Same as ZSTDv05_decompress(), but requires an already allocated ZSTDv05_DCtx (see ZSTDv05_createDCtx()) */\nsize_t ZSTDv05_decompressDCtx(ZSTDv05_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-***********************\n*  Simple Dictionary API\n*************************/\n/*! ZSTDv05_decompress_usingDict() :\n*   Decompression using a pre-defined Dictionary content (see dictBuilder).\n*   Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted.\n*   Note : dict can be NULL, in which case, it's equivalent to ZSTDv05_decompressDCtx() */\nsize_t ZSTDv05_decompress_usingDict(ZSTDv05_DCtx* dctx,\n                                            void* dst, size_t dstCapacity,\n                                      const void* src, size_t srcSize,\n                                      const void* dict,size_t dictSize);\n\n/*-************************\n*  Advanced Streaming API\n***************************/\ntypedef enum { ZSTDv05_fast, ZSTDv05_greedy, ZSTDv05_lazy, ZSTDv05_lazy2, ZSTDv05_btlazy2, ZSTDv05_opt, ZSTDv05_btopt } ZSTDv05_strategy;\ntypedef struct {\n    U64 srcSize;\n    U32 windowLog;     /* the only useful information to retrieve */\n    U32 contentLog; U32 hashLog; U32 searchLog; U32 searchLength; U32 targetLength; ZSTDv05_strategy strategy;\n} ZSTDv05_parameters;\nsize_t ZSTDv05_getFrameParams(ZSTDv05_parameters* params, const void* src, size_t srcSize);\n\nsize_t ZSTDv05_decompressBegin_usingDict(ZSTDv05_DCtx* dctx, const void* dict, size_t dictSize);\nvoid   ZSTDv05_copyDCtx(ZSTDv05_DCtx* dstDCtx, const ZSTDv05_DCtx* srcDCtx);\nsize_t ZSTDv05_nextSrcSizeToDecompress(ZSTDv05_DCtx* dctx);\nsize_t ZSTDv05_decompressContinue(ZSTDv05_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-***********************\n*  ZBUFF API\n*************************/\ntypedef struct ZBUFFv05_DCtx_s ZBUFFv05_DCtx;\nZBUFFv05_DCtx* ZBUFFv05_createDCtx(void);\nsize_t         ZBUFFv05_freeDCtx(ZBUFFv05_DCtx* dctx);\n\nsize_t ZBUFFv05_decompressInit(ZBUFFv05_DCtx* dctx);\nsize_t ZBUFFv05_decompressInitDictionary(ZBUFFv05_DCtx* dctx, const void* dict, size_t dictSize);\n\nsize_t ZBUFFv05_decompressContinue(ZBUFFv05_DCtx* dctx,\n                                            void* dst, size_t* dstCapacityPtr,\n                                      const void* src, size_t* srcSizePtr);\n\n/*-***************************************************************************\n*  Streaming decompression\n*\n*  A ZBUFFv05_DCtx object is required to track streaming operations.\n*  Use ZBUFFv05_createDCtx() and ZBUFFv05_freeDCtx() to create/release resources.\n*  Use ZBUFFv05_decompressInit() to start a new decompression operation,\n*   or ZBUFFv05_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv05_DCtx objects can be reused multiple times.\n*\n*  Use ZBUFFv05_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters or change @dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency)\n*            or 0 when a frame is completely decoded\n*            or an error code, which can be tested using ZBUFFv05_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv05_recommendedDInSize() / ZBUFFv05_recommendedDOutSize()\n*  output : ZBUFFv05_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv05_recommendedDInSize==128Kb+3; just follow indications from ZBUFFv05_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nunsigned ZBUFFv05_isError(size_t errorCode);\nconst char* ZBUFFv05_getErrorName(size_t errorCode);\n\n/** Functions below provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are just hints, and tend to offer better latency */\nsize_t ZBUFFv05_recommendedDInSize(void);\nsize_t ZBUFFv05_recommendedDOutSize(void);\n\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define ZSTDv05_MAGICNUMBER 0xFD2FB525   /* v0.5 */\n\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv0505_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v06.c",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*- Dependencies -*/\n#include \"zstd_v06.h\"\n#include <stddef.h>    /* size_t, ptrdiff_t */\n#include <string.h>    /* memcpy */\n#include <stdlib.h>    /* malloc, free, qsort */\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-**************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap32(in);\n#else\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n#endif\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_uint64(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap64(in);\n#else\n    return  ((in << 56) & 0xff00000000000000ULL) |\n            ((in << 40) & 0x00ff000000000000ULL) |\n            ((in << 24) & 0x0000ff0000000000ULL) |\n            ((in << 8)  & 0x000000ff00000000ULL) |\n            ((in >> 8)  & 0x00000000ff000000ULL) |\n            ((in >> 24) & 0x0000000000ff0000ULL) |\n            ((in >> 40) & 0x000000000000ff00ULL) |\n            ((in >> 56) & 0x00000000000000ffULL);\n#endif\n}\n\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n        return MEM_swap32(MEM_read32(memPtr));\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n        return MEM_swap64(MEM_read64(memPtr));\n}\n\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n\n/*\n    zstd - standard compression library\n    Header File for static linking only\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n#ifndef ZSTDv06_STATIC_H\n#define ZSTDv06_STATIC_H\n\n/* The prototypes defined within this file are considered experimental.\n * They should not be used in the context DLL as they may change in the future.\n * Prefer static linking if you need them, to control breaking version changes issues.\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*- Advanced Decompression functions -*/\n\n/*! ZSTDv06_decompress_usingPreparedDCtx() :\n*   Same as ZSTDv06_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.\n*   It avoids reloading the dictionary each time.\n*   `preparedDCtx` must have been properly initialized using ZSTDv06_decompressBegin_usingDict().\n*   Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */\nZSTDLIBv06_API size_t ZSTDv06_decompress_usingPreparedDCtx(\n                                           ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx,\n                                           void* dst, size_t dstCapacity,\n                                     const void* src, size_t srcSize);\n\n\n\n#define ZSTDv06_FRAMEHEADERSIZE_MAX 13    /* for static allocation */\nstatic const size_t ZSTDv06_frameHeaderSize_min = 5;\nstatic const size_t ZSTDv06_frameHeaderSize_max = ZSTDv06_FRAMEHEADERSIZE_MAX;\n\nZSTDLIBv06_API size_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx);\n\n/*\n  Streaming decompression, direct mode (bufferless)\n\n  A ZSTDv06_DCtx object is required to track streaming operations.\n  Use ZSTDv06_createDCtx() / ZSTDv06_freeDCtx() to manage it.\n  A ZSTDv06_DCtx object can be re-used multiple times.\n\n  First optional operation is to retrieve frame parameters, using ZSTDv06_getFrameParams(), which doesn't consume the input.\n  It can provide the minimum size of rolling buffer required to properly decompress data,\n  and optionally the final size of uncompressed content.\n  (Note : content size is an optional info that may not be present. 0 means : content size unknown)\n  Frame parameters are extracted from the beginning of compressed frame.\n  The amount of data to read is variable, from ZSTDv06_frameHeaderSize_min to ZSTDv06_frameHeaderSize_max (so if `srcSize` >= ZSTDv06_frameHeaderSize_max, it will always work)\n  If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.\n  Result : 0 when successful, it means the ZSTDv06_frameParams structure has been filled.\n          >0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTDv06_isError()\n\n  Start decompression, with ZSTDv06_decompressBegin() or ZSTDv06_decompressBegin_usingDict().\n  Alternatively, you can copy a prepared context, using ZSTDv06_copyDCtx().\n\n  Then use ZSTDv06_nextSrcSizeToDecompress() and ZSTDv06_decompressContinue() alternatively.\n  ZSTDv06_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv06_decompressContinue().\n  ZSTDv06_decompressContinue() requires this exact amount of bytes, or it will fail.\n  ZSTDv06_decompressContinue() needs previous data blocks during decompression, up to (1 << windowlog).\n  They should preferably be located contiguously, prior to current block. Alternatively, a round buffer is also possible.\n\n  @result of ZSTDv06_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity)\n  It can be zero, which is not an error; it just means ZSTDv06_decompressContinue() has decoded some header.\n\n  A frame is fully decoded when ZSTDv06_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n*/\n\n\n/* **************************************\n*  Block functions\n****************************************/\n/*! Block functions produce and decode raw zstd blocks, without frame metadata.\n    User will have to take in charge required information to regenerate data, such as compressed and content sizes.\n\n    A few rules to respect :\n    - Uncompressed block size must be <= ZSTDv06_BLOCKSIZE_MAX (128 KB)\n    - Compressing or decompressing requires a context structure\n      + Use ZSTDv06_createCCtx() and ZSTDv06_createDCtx()\n    - It is necessary to init context before starting\n      + compression : ZSTDv06_compressBegin()\n      + decompression : ZSTDv06_decompressBegin()\n      + variants _usingDict() are also allowed\n      + copyCCtx() and copyDCtx() work too\n    - When a block is considered not compressible enough, ZSTDv06_compressBlock() result will be zero.\n      In which case, nothing is produced into `dst`.\n      + User must test for such outcome and deal directly with uncompressed data\n      + ZSTDv06_decompressBlock() doesn't accept uncompressed data as input !!\n*/\n\n#define ZSTDv06_BLOCKSIZE_MAX (128 * 1024)   /* define, for static allocation */\nZSTDLIBv06_API size_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv06_STATIC_H */\n/*\n    zstd_internal - common functions to include\n    Header File for include\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://www.zstd.net\n*/\n#ifndef ZSTDv06_CCOMMON_H_MODULE\n#define ZSTDv06_CCOMMON_H_MODULE\n\n\n/*-*************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTDv06_DICT_MAGIC  0xEC30A436\n\n#define ZSTDv06_REP_NUM    3\n#define ZSTDv06_REP_INIT   ZSTDv06_REP_NUM\n#define ZSTDv06_REP_MOVE   (ZSTDv06_REP_NUM-1)\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define ZSTDv06_WINDOWLOG_ABSOLUTEMIN 12\nstatic const size_t ZSTDv06_fcs_fieldSize[4] = { 0, 1, 2, 8 };\n\n#define ZSTDv06_BLOCKHEADERSIZE 3   /* because C standard does not allow a static const value to be defined using another static const value .... :( */\nstatic const size_t ZSTDv06_blockHeaderSize = ZSTDv06_BLOCKHEADERSIZE;\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */\n\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\n\n#define IS_HUF 0\n#define IS_PCH 1\n#define IS_RAW 2\n#define IS_RLE 3\n\n#define LONGNBSEQ 0x7F00\n\n#define MINMATCH 3\n#define EQUAL_READ32 4\n#define REPCODE_STARTVALUE 1\n\n#define Litbits  8\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML  52\n#define MaxLL  35\n#define MaxOff 28\n#define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */\n#define MLFSELog    9\n#define LLFSELog    9\n#define OffFSELog   8\n\n#define FSEv06_ENCODING_RAW     0\n#define FSEv06_ENCODING_RLE     1\n#define FSEv06_ENCODING_STATIC  2\n#define FSEv06_ENCODING_DYNAMIC 3\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,\n                                     13,14,15,16 };\nstatic const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,\n                                             2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,\n                                            -1,-1,-1,-1 };\nstatic const U32 LL_defaultNormLog = 6;\n\nstatic const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,\n                                     12,13,14,15,16 };\nstatic const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,\n                                            -1,-1,-1,-1,-1 };\nstatic const U32 ML_defaultNormLog = 6;\n\nstatic const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                              1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };\nstatic const U32 OF_defaultNormLog = 5;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTDv06_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n#define COPY8(d,s) { ZSTDv06_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTDv06_wildcopy() :\n*   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */\n#define WILDCOPY_OVERLENGTH 8\nMEM_STATIC void ZSTDv06_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n\n/*-*******************************************\n*  Private interfaces\n*********************************************/\ntypedef struct {\n    U32 off;\n    U32 len;\n} ZSTDv06_match_t;\n\ntypedef struct {\n    U32 price;\n    U32 off;\n    U32 mlen;\n    U32 litlen;\n    U32 rep[ZSTDv06_REP_INIT];\n} ZSTDv06_optimal_t;\n\ntypedef struct { U32  unused; } ZSTDv06_stats_t;\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* litStart;\n    BYTE* lit;\n    U16*  litLengthStart;\n    U16*  litLength;\n    BYTE* llCodeStart;\n    U16*  matchLengthStart;\n    U16*  matchLength;\n    BYTE* mlCodeStart;\n    U32   longLengthID;   /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */\n    U32   longLengthPos;\n    /* opt */\n    ZSTDv06_optimal_t* priceTable;\n    ZSTDv06_match_t* matchTable;\n    U32* matchLengthFreq;\n    U32* litLengthFreq;\n    U32* litFreq;\n    U32* offCodeFreq;\n    U32  matchLengthSum;\n    U32  matchSum;\n    U32  litLengthSum;\n    U32  litSum;\n    U32  offCodeSum;\n    U32  log2matchLengthSum;\n    U32  log2matchSum;\n    U32  log2litLengthSum;\n    U32  log2litSum;\n    U32  log2offCodeSum;\n    U32  factor;\n    U32  cachedPrice;\n    U32  cachedLitLength;\n    const BYTE* cachedLiterals;\n    ZSTDv06_stats_t stats;\n} SeqStore_t;\n\nvoid ZSTDv06_seqToCodes(const SeqStore_t* seqStorePtr, size_t const nbSeq);\n\n\n#endif   /* ZSTDv06_CCOMMON_H_MODULE */\n/* ******************************************************************\n   FSE : Finite State Entropy codec\n   Public Prototypes declaration\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef FSEv06_H\n#define FSEv06_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*-****************************************\n*  FSE simple functions\n******************************************/\n/*! FSEv06_decompress():\n    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstCapacity'.\n    @return : size of regenerated data (<= maxDstSize),\n              or an error code, which can be tested using FSEv06_isError() .\n\n    ** Important ** : FSEv06_decompress() does not decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\nsize_t FSEv06_decompress(void* dst,  size_t dstCapacity,\n                const void* cSrc, size_t cSrcSize);\n\n\n/*-*****************************************\n*  Tool functions\n******************************************/\nsize_t FSEv06_compressBound(size_t size);       /* maximum compressed size */\n\n/* Error Management */\nunsigned    FSEv06_isError(size_t code);        /* tells if a return value is an error code */\nconst char* FSEv06_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n\n/*-*****************************************\n*  FSE detailed API\n******************************************/\n/*!\n\nFSEv06_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*! FSEv06_readNCount():\n    Read compactly saved 'normalizedCounter' from 'rBuffer'.\n    @return : size read from 'rBuffer',\n              or an errorCode, which can be tested using FSEv06_isError().\n              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nsize_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*! Constructor and Destructor of FSEv06_DTable.\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSEv06_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\nFSEv06_DTable* FSEv06_createDTable(unsigned tableLog);\nvoid        FSEv06_freeDTable(FSEv06_DTable* dt);\n\n/*! FSEv06_buildDTable():\n    Builds 'dt', which must be already allocated, using FSEv06_createDTable().\n    return : 0, or an errorCode, which can be tested using FSEv06_isError() */\nsize_t FSEv06_buildDTable (FSEv06_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSEv06_decompress_usingDTable():\n    Decompress compressed source `cSrc` of size `cSrcSize` using `dt`\n    into `dst` which must be already allocated.\n    @return : size of regenerated data (necessarily <= `dstCapacity`),\n              or an errorCode, which can be tested using FSEv06_isError() */\nsize_t FSEv06_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv06_DTable* dt);\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSEv06_readNCount() if it was saved using FSEv06_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSEv06_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSEv06_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSEv06_isError().\n\nThe next step is to build the decompression tables 'FSEv06_DTable' from 'normalizedCounter'.\nThis is performed by the function FSEv06_buildDTable().\nThe space required by 'FSEv06_DTable' must be already allocated using FSEv06_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSEv06_isError().\n\n`FSEv06_DTable` can then be used to decompress `cSrc`, with FSEv06_decompress_usingDTable().\n`cSrcSize` must be strictly correct, otherwise decompression will fail.\nFSEv06_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).\nIf there is an error, the function will return an error code, which can be tested using FSEv06_isError(). (ex: dst buffer too small)\n*/\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv06_H */\n/* ******************************************************************\n   bitstream\n   Part of FSE library\n   header file (to include)\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which must be inlined for best performance.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/*=========================================\n*  Target specific\n=========================================*/\n#if defined(__BMI__) && defined(__GNUC__)\n#  include <immintrin.h>   /* support for bextr (experimental) */\n#endif\n\n\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BITv06_DStream_t;\n\ntypedef enum { BITv06_DStream_unfinished = 0,\n               BITv06_DStream_endOfBuffer = 1,\n               BITv06_DStream_completed = 2,\n               BITv06_DStream_overflow = 3 } BITv06_DStream_status;  /* result of BITv06_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BITv06_initDStream(BITv06_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BITv06_readBits(BITv06_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD);\nMEM_STATIC unsigned BITv06_endOfDStream(const BITv06_DStream_t* bitD);\n\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/*-**************************************************************\n*  Internal functions\n****************************************************************/\nMEM_STATIC unsigned BITv06_highbit32 ( U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    unsigned r;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    r = DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n    return r;\n#   endif\n}\n\n\n\n/*-********************************************************\n* bitStream decoding\n**********************************************************/\n/*! BITv06_initDStream() :\n*   Initialize a BITv06_DStream_t.\n*   `bitD` : a pointer to an already allocated BITv06_DStream_t structure.\n*   `srcSize` must be the *exact* size of the bitStream, in bytes.\n*   @return : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BITv06_initDStream(BITv06_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          if (lastByte == 0) return ERROR(GENERIC);   /* endMark not present */\n          bitD->bitsConsumed = 8 - BITv06_highbit32(lastByte); }\n    } else {\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          if (lastByte == 0) return ERROR(GENERIC);   /* endMark not present */\n          bitD->bitsConsumed = 8 - BITv06_highbit32(lastByte); }\n        bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\n\n MEM_STATIC size_t BITv06_lookBits(const BITv06_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BITv06_lookBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv06_lookBitsFast(const BITv06_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BITv06_skipBits(BITv06_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BITv06_readBits(BITv06_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv06_lookBits(bitD, nbBits);\n    BITv06_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BITv06_readBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv06_readBitsFast(BITv06_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv06_lookBitsFast(bitD, nbBits);\n    BITv06_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BITv06_DStream_status BITv06_reloadDStream(BITv06_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should never happen */\n        return BITv06_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BITv06_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start) {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv06_DStream_endOfBuffer;\n        return BITv06_DStream_completed;\n    }\n    {   U32 nbBytes = bitD->bitsConsumed >> 3;\n        BITv06_DStream_status result = BITv06_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BITv06_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BITv06_endOfDStream() :\n*   @return Tells if DStream has exactly reached its end (all bits consumed).\n*/\nMEM_STATIC unsigned BITv06_endOfDStream(const BITv06_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   FSE : Finite State Entropy coder\n   header file for static linking (only)\n   Copyright (C) 2013-2015, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n   - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef FSEv06_STATIC_H\n#define FSEv06_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSEv06_NCOUNTBOUND 512\n#define FSEv06_BLOCKBOUND(size) (size + (size>>7))\n#define FSEv06_COMPRESSBOUND(size) (FSEv06_NCOUNTBOUND + FSEv06_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */\n#define FSEv06_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSE advanced API\n*******************************************/\nsize_t FSEv06_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);\n/* same as FSEv06_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr  */\n\nsize_t FSEv06_buildDTable_raw (FSEv06_DTable* dt, unsigned nbBits);\n/* build a fake FSEv06_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nsize_t FSEv06_buildDTable_rle (FSEv06_DTable* dt, unsigned char symbolValue);\n/* build a fake FSEv06_DTable, designed to always generate the same symbolValue */\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSEv06_DState_t;\n\n\nstatic void     FSEv06_initDState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD, const FSEv06_DTable* dt);\n\nstatic unsigned char FSEv06_decodeSymbol(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD);\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSEv06_decodeSymbolFast(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* *****************************************\n*  Implementation of inlined functions\n*******************************************/\n\n\n/* ======    Decompression    ====== */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSEv06_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSEv06_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSEv06_initDState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD, const FSEv06_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv06_DTableHeader* const DTableH = (const FSEv06_DTableHeader*)ptr;\n    DStatePtr->state = BITv06_readBits(bitD, DTableH->tableLog);\n    BITv06_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSEv06_peekSymbol(const FSEv06_DState_t* DStatePtr)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC void FSEv06_updateState(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    size_t const lowBits = BITv06_readBits(bitD, nbBits);\n    DStatePtr->state = DInfo.newState + lowBits;\n}\n\nMEM_STATIC BYTE FSEv06_decodeSymbol(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv06_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/*! FSEv06_decodeSymbolFast() :\n    unsafe, only works if no symbol has a probability > 50% */\nMEM_STATIC BYTE FSEv06_decodeSymbolFast(FSEv06_DState_t* DStatePtr, BITv06_DStream_t* bitD)\n{\n    FSEv06_decode_t const DInfo = ((const FSEv06_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv06_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n\n\n#ifndef FSEv06_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSEv06_MAX_MEMORY_USAGE 14\n#define FSEv06_DEFAULT_MEMORY_USAGE 13\n\n/*!FSEv06_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSEv06_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSEv06_FUNCTION_TYPE BYTE\n#define FSEv06_FUNCTION_EXTENSION\n#define FSEv06_DECODE_TYPE FSEv06_decode_t\n\n\n#endif   /* !FSEv06_COMMONDEFS_ONLY */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSEv06_MAX_TABLELOG  (FSEv06_MAX_MEMORY_USAGE-2)\n#define FSEv06_MAX_TABLESIZE (1U<<FSEv06_MAX_TABLELOG)\n#define FSEv06_MAXTABLESIZE_MASK (FSEv06_MAX_TABLESIZE-1)\n#define FSEv06_DEFAULT_TABLELOG (FSEv06_DEFAULT_MEMORY_USAGE-2)\n#define FSEv06_MIN_TABLELOG 5\n\n#define FSEv06_TABLELOG_ABSOLUTE_MAX 15\n#if FSEv06_MAX_TABLELOG > FSEv06_TABLELOG_ABSOLUTE_MAX\n#error \"FSEv06_MAX_TABLELOG > FSEv06_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n#define FSEv06_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv06_STATIC_H */\n/*\n   Common functions of New Generation Entropy library\n   Copyright (C) 2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n*************************************************************************** */\n\n\n/*-****************************************\n*  FSE Error Management\n******************************************/\nunsigned FSEv06_isError(size_t code) { return ERR_isError(code); }\n\nconst char* FSEv06_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* **************************************************************\n*  HUF Error Management\n****************************************************************/\nstatic unsigned HUFv06_isError(size_t code) { return ERR_isError(code); }\n\n\n/*-**************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSEv06_abs(short a) { return a<0 ? -a : a; }\n\nsize_t FSEv06_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSEv06_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSEv06_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr)) {\n        if (previous0) {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF) {\n                n0+=24;\n                if (ip < iend-5) {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                } else {\n                    bitStream >>= 16;\n                    bitCount+=16;\n            }   }\n            while ((bitStream & 3) == 3) {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {   short const max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            } else {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSEv06_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold) {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n    }   }   /* while ((remaining>1) && (charnum<=*maxSVPtr)) */\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n/* ******************************************************************\n   FSE : Finite State Entropy decoder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSEv06_isError ERR_isError\n#define FSEv06_STATIC_ASSERT(c) { enum { FSEv06_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSEv06_DTABLE_SIZE_U32(FSEv06_MAX_TABLELOG)];\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSEv06_FUNCTION_EXTENSION\n#  error \"FSEv06_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSEv06_FUNCTION_TYPE\n#  error \"FSEv06_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSEv06_CAT(X,Y) X##Y\n#define FSEv06_FUNCTION_NAME(X,Y) FSEv06_CAT(X,Y)\n#define FSEv06_TYPE_NAME(X,Y) FSEv06_CAT(X,Y)\n\n\n/* Function templates */\nFSEv06_DTable* FSEv06_createDTable (unsigned tableLog)\n{\n    if (tableLog > FSEv06_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv06_TABLELOG_ABSOLUTE_MAX;\n    return (FSEv06_DTable*)malloc( FSEv06_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );\n}\n\nvoid FSEv06_freeDTable (FSEv06_DTable* dt)\n{\n    free(dt);\n}\n\nsize_t FSEv06_buildDTable(FSEv06_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */\n    FSEv06_DECODE_TYPE* const tableDecode = (FSEv06_DECODE_TYPE*) (tdPtr);\n    U16 symbolNext[FSEv06_MAX_SYMBOL_VALUE+1];\n\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n    U32 highThreshold = tableSize-1;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSEv06_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSEv06_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    {   FSEv06_DTableHeader DTableH;\n        DTableH.tableLog = (U16)tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].symbol = (FSEv06_FUNCTION_TYPE)s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    symbolNext[s] = normalizedCounter[s];\n        }   }   }\n        memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    {   U32 const tableMask = tableSize-1;\n        U32 const step = FSEv06_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            for (i=0; i<normalizedCounter[s]; i++) {\n                tableDecode[position].symbol = (FSEv06_FUNCTION_TYPE)s;\n                position = (position + step) & tableMask;\n                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n\n        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {   U32 u;\n        for (u=0; u<tableSize; u++) {\n            FSEv06_FUNCTION_TYPE const symbol = (FSEv06_FUNCTION_TYPE)(tableDecode[u].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - BITv06_highbit32 ((U32)nextState) );\n            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n    }   }\n\n    return 0;\n}\n\n\n\n#ifndef FSEv06_COMMONDEFS_ONLY\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nsize_t FSEv06_buildDTable_rle (FSEv06_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSEv06_DTableHeader* const DTableH = (FSEv06_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv06_decode_t* const cell = (FSEv06_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nsize_t FSEv06_buildDTable_raw (FSEv06_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSEv06_DTableHeader* const DTableH = (FSEv06_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv06_decode_t* const dinfo = (FSEv06_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSV1 = tableMask+1;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<maxSV1; s++) {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSEv06_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSEv06_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BITv06_DStream_t bitD;\n    FSEv06_DState_t state1;\n    FSEv06_DState_t state2;\n\n    /* Init */\n    { size_t const errorCode = BITv06_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n      if (FSEv06_isError(errorCode)) return errorCode; }\n\n    FSEv06_initDState(&state1, &bitD, dt);\n    FSEv06_initDState(&state2, &bitD, dt);\n\n#define FSEv06_GETSYMBOL(statePtr) fast ? FSEv06_decodeSymbolFast(statePtr, &bitD) : FSEv06_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BITv06_reloadDStream(&bitD)==BITv06_DStream_unfinished) && (op<olimit) ; op+=4) {\n        op[0] = FSEv06_GETSYMBOL(&state1);\n\n        if (FSEv06_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv06_reloadDStream(&bitD);\n\n        op[1] = FSEv06_GETSYMBOL(&state2);\n\n        if (FSEv06_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BITv06_reloadDStream(&bitD) > BITv06_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSEv06_GETSYMBOL(&state1);\n\n        if (FSEv06_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv06_reloadDStream(&bitD);\n\n        op[3] = FSEv06_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BITv06_reloadDStream(&bitD) >= FSEv06_DStream_partiallyFilled; Ends at exactly BITv06_DStream_completed */\n    while (1) {\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv06_GETSYMBOL(&state1);\n\n        if (BITv06_reloadDStream(&bitD)==BITv06_DStream_overflow) {\n            *op++ = FSEv06_GETSYMBOL(&state2);\n            break;\n        }\n\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv06_GETSYMBOL(&state2);\n\n        if (BITv06_reloadDStream(&bitD)==BITv06_DStream_overflow) {\n            *op++ = FSEv06_GETSYMBOL(&state1);\n            break;\n    }   }\n\n    return op-ostart;\n}\n\n\nsize_t FSEv06_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSEv06_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv06_DTableHeader* DTableH = (const FSEv06_DTableHeader*)ptr;\n    const U32 fastMode = DTableH->fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSEv06_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSEv06_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nsize_t FSEv06_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSEv06_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSEv06_MAX_SYMBOL_VALUE;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    {   size_t const NCountLength = FSEv06_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n        if (FSEv06_isError(NCountLength)) return NCountLength;\n        if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n        ip += NCountLength;\n        cSrcSize -= NCountLength;\n    }\n\n    { size_t const errorCode = FSEv06_buildDTable (dt, counting, maxSymbolValue, tableLog);\n      if (FSEv06_isError(errorCode)) return errorCode; }\n\n    return FSEv06_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);   /* always return, even if it is an error code */\n}\n\n\n\n#endif   /* FSEv06_COMMONDEFS_ONLY */\n/* ******************************************************************\n   Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFv06_H\n#define HUFv06_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* ****************************************\n*  HUF simple functions\n******************************************/\nsize_t HUFv06_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n/*\nHUFv06_decompress() :\n    Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstSize'.\n    `dstSize` : must be the **exact** size of original (uncompressed) data.\n    Note : in contrast with FSE, HUFv06_decompress can regenerate\n           RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,\n           because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize)\n              or an error code, which can be tested using HUFv06_isError()\n*/\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\nsize_t HUFv06_compressBound(size_t size);       /**< maximum compressed size */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUFv06_H */\n/* ******************************************************************\n   Huffman codec, part of New Generation Entropy library\n   header file, for static linking only\n   Copyright (C) 2013-2016, Yann Collet\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFv06_STATIC_H\n#define HUFv06_STATIC_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* HUF buffer bounds */\n#define HUFv06_CTABLEBOUND 129\n#define HUFv06_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n#define HUFv06_COMPRESSBOUND(size) (HUFv06_CTABLEBOUND + HUFv06_BLOCKBOUND(size))   /* Macro version, useful for static allocation */\n\n/* static allocation of HUF's DTable */\n#define HUFv06_DTABLE_SIZE(maxTableLog)   (1 + (1<<maxTableLog))\n#define HUFv06_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        unsigned short DTable[HUFv06_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv06_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv06_DTABLE_SIZE(maxTableLog)] = { maxTableLog }\n#define HUFv06_CREATE_STATIC_DTABLEX6(DTable, maxTableLog) \\\n        unsigned int DTable[HUFv06_DTABLE_SIZE(maxTableLog) * 3 / 2] = { maxTableLog }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nsize_t HUFv06_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv06_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbols decoder */\n\n\n\n/*!\nHUFv06_decompress() does the following:\n1. select the decompression algorithm (X2, X4, X6) based on pre-computed heuristics\n2. build Huffman table from save, using HUFv06_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUFv06_decompressSXn_usingDTable\n*/\nsize_t HUFv06_readDTableX2 (unsigned short* DTable, const void* src, size_t srcSize);\nsize_t HUFv06_readDTableX4 (unsigned* DTable, const void* src, size_t srcSize);\n\nsize_t HUFv06_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv06_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n/* single stream variants */\nsize_t HUFv06_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv06_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */\n\nsize_t HUFv06_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned short* DTable);\nsize_t HUFv06_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const unsigned* DTable);\n\n\n\n/* **************************************************************\n*  Constants\n****************************************************************/\n#define HUFv06_ABSOLUTEMAX_TABLELOG  16   /* absolute limit of HUFv06_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUFv06_MAX_TABLELOG  12           /* max configured tableLog (for static allocation); can be modified up to HUFv06_ABSOLUTEMAX_TABLELOG */\n#define HUFv06_DEFAULT_TABLELOG  HUFv06_MAX_TABLELOG   /* tableLog by default, when not specified */\n#define HUFv06_MAX_SYMBOL_VALUE 255\n#if (HUFv06_MAX_TABLELOG > HUFv06_ABSOLUTEMAX_TABLELOG)\n#  error \"HUFv06_MAX_TABLELOG is too large !\"\n#endif\n\n\n\n/*! HUFv06_readStats() :\n    Read compact Huffman tree, saved by HUFv06_writeCTable().\n    `huffWeight` is destination buffer.\n    @return : size read from `src`\n*/\nMEM_STATIC size_t HUFv06_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                            U32* nbSymbolsPtr, U32* tableLogPtr,\n                            const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* memset(huffWeight, 0, hwSize); */   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  { /* special header */\n        if (iSize >= (242)) {  /* RLE */\n            static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else {   /* Incompressible */\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            {   U32 n;\n                for (n=0; n<oSize; n+=2) {\n                    huffWeight[n]   = ip[n/2] >> 4;\n                    huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }   }\n    else  {   /* header compressed with FSE (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSEv06_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSEv06_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUFv06_ABSOLUTEMAX_TABLELOG + 1) * sizeof(U32));\n    weightTotal = 0;\n    {   U32 n; for (n=0; n<oSize; n++) {\n            if (huffWeight[n] >= HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n            rankStats[huffWeight[n]]++;\n            weightTotal += (1 << huffWeight[n]) >> 1;\n    }   }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    {   U32 const tableLog = BITv06_highbit32(weightTotal) + 1;\n        if (tableLog > HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(corruption_detected);\n        *tableLogPtr = tableLog;\n        /* determine last weight */\n        {   U32 const total = 1 << tableLog;\n            U32 const rest = total - weightTotal;\n            U32 const verif = 1 << BITv06_highbit32(rest);\n            U32 const lastWeight = BITv06_highbit32(rest) + 1;\n            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n            huffWeight[oSize] = (BYTE)lastWeight;\n            rankStats[lastWeight]++;\n    }   }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    return iSize+1;\n}\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* HUFv06_STATIC_H */\n/* ******************************************************************\n   Huffman decoder, part of New Generation Entropy library\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUFv06_STATIC_ASSERT(c) { enum { HUFv06_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n\n/* *******************************************************\n*  HUF : Huffman block decompression\n*********************************************************/\ntypedef struct { BYTE byte; BYTE nbBits; } HUFv06_DEltX2;   /* single-symbol decoding */\n\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv06_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\n\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\n\nsize_t HUFv06_readDTableX2 (U16* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUFv06_MAX_SYMBOL_VALUE + 1];\n    U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    size_t iSize;\n    U32 nbSymbols = 0;\n    U32 n;\n    U32 nextRankStart;\n    void* const dtPtr = DTable + 1;\n    HUFv06_DEltX2* const dt = (HUFv06_DEltX2*)dtPtr;\n\n    HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX2) == sizeof(U16));   /* if compilation fails here, assertion is false */\n    /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv06_readStats(huffWeight, HUFv06_MAX_SYMBOL_VALUE + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv06_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > DTable[0]) return ERROR(tableLog_tooLarge);   /* DTable is too small */\n    DTable[0] = (U16)tableLog;   /* maybe should separate sizeof allocated DTable, from used size of DTable, in case of re-use */\n\n    /* Prepare ranks */\n    nextRankStart = 0;\n    for (n=1; n<tableLog+1; n++) {\n        U32 current = nextRankStart;\n        nextRankStart += (rankVal[n] << (n-1));\n        rankVal[n] = current;\n    }\n\n    /* fill DTable */\n    for (n=0; n<nbSymbols; n++) {\n        const U32 w = huffWeight[n];\n        const U32 length = (1 << w) >> 1;\n        U32 i;\n        HUFv06_DEltX2 D;\n        D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n        for (i = rankVal[w]; i < rankVal[w] + length; i++)\n            dt[i] = D;\n        rankVal[w] += length;\n    }\n\n    return iSize;\n}\n\n\nstatic BYTE HUFv06_decodeSymbolX2(BITv06_DStream_t* Dstream, const HUFv06_DEltX2* dt, const U32 dtLog)\n{\n    const size_t val = BITv06_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n    const BYTE c = dt[val].byte;\n    BITv06_skipBits(Dstream, dt[val].nbBits);\n    return c;\n}\n\n#define HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUFv06_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUFv06_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv06_MAX_TABLELOG<=12)) \\\n        HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUFv06_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUFv06_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUFv06_decodeStreamX2(BYTE* p, BITv06_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv06_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p <= pEnd-4)) {\n        HUFv06_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p < pEnd))\n        HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUFv06_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\nsize_t HUFv06_decompress1X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + dstSize;\n    const U32 dtLog = DTable[0];\n    const void* dtPtr = DTable;\n    const HUFv06_DEltX2* const dt = ((const HUFv06_DEltX2*)dtPtr)+1;\n    BITv06_DStream_t bitD;\n\n    { size_t const errorCode = BITv06_initDStream(&bitD, cSrc, cSrcSize);\n      if (HUFv06_isError(errorCode)) return errorCode; }\n\n    HUFv06_decodeStreamX2(op, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv06_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\nsize_t HUFv06_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX2(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const errorCode = HUFv06_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv06_decompress1X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\nsize_t HUFv06_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U16* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv06_DEltX2* const dt = ((const HUFv06_DEltX2*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv06_DStream_t bitD1;\n        BITv06_DStream_t bitD2;\n        BITv06_DStream_t bitD3;\n        BITv06_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv06_initDStream(&bitD1, istart1, length1);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD2, istart2, length2);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD3, istart3, length3);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD4, istart4, length4);\n        if (HUFv06_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv06_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv06_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv06_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv06_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv06_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv06_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv06_endOfDStream(&bitD1) & BITv06_endOfDStream(&bitD2) & BITv06_endOfDStream(&bitD3) & BITv06_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv06_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX2(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const errorCode = HUFv06_readDTableX2 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(errorCode)) return errorCode;\n    if (errorCode >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += errorCode;\n    cSrcSize -= errorCode;\n\n    return HUFv06_decompress4X2_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\n\nstatic void HUFv06_fillDTableX4Level2(HUFv06_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUFv06_DEltX4 DElt;\n    U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1) {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    { U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }}\n}\n\ntypedef U32 rankVal_t[HUFv06_ABSOLUTEMAX_TABLELOG][HUFv06_ABSOLUTEMAX_TABLELOG + 1];\n\nstatic void HUFv06_fillDTableX4(HUFv06_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUFv06_ABSOLUTEMAX_TABLELOG + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUFv06_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        } else {\n            HUFv06_DEltX4 DElt;\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits = (BYTE)(nbBits);\n            DElt.length = 1;\n            {   U32 u;\n                const U32 end = start + length;\n                for (u = start; u < end; u++) DTable[u] = DElt;\n        }   }\n        rankVal[weight] += length;\n    }\n}\n\nsize_t HUFv06_readDTableX4 (U32* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUFv06_MAX_SYMBOL_VALUE + 1];\n    sortedSymbol_t sortedSymbol[HUFv06_MAX_SYMBOL_VALUE + 1];\n    U32 rankStats[HUFv06_ABSOLUTEMAX_TABLELOG + 1] = { 0 };\n    U32 rankStart0[HUFv06_ABSOLUTEMAX_TABLELOG + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    const U32 memLog = DTable[0];\n    size_t iSize;\n    void* dtPtr = DTable;\n    HUFv06_DEltX4* const dt = ((HUFv06_DEltX4*)dtPtr) + 1;\n\n    HUFv06_STATIC_ASSERT(sizeof(HUFv06_DEltX4) == sizeof(U32));   /* if compilation fails here, assertion is false */\n    if (memLog > HUFv06_ABSOLUTEMAX_TABLELOG) return ERROR(tableLog_tooLarge);\n    /* memset(weightList, 0, sizeof(weightList)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv06_readStats(weightList, HUFv06_MAX_SYMBOL_VALUE + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv06_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > memLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {   U32 w, nextRankStart = 0;\n        for (w=1; w<maxW+1; w++) {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {   U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 const w = weightList[s];\n            U32 const r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {   U32* const rankVal0 = rankVal[0];\n        {   int const rescale = (memLog-tableLog) - 1;   /* tableLog <= memLog */\n            U32 nextRankVal = 0;\n            U32 w;\n            for (w=1; w<maxW+1; w++) {\n                U32 current = nextRankVal;\n                nextRankVal += rankStats[w] << (w+rescale);\n                rankVal0[w] = current;\n        }   }\n        {   U32 const minBits = tableLog+1 - maxW;\n            U32 consumed;\n            for (consumed = minBits; consumed < memLog - minBits + 1; consumed++) {\n                U32* const rankValPtr = rankVal[consumed];\n                U32 w;\n                for (w = 1; w < maxW+1; w++) {\n                    rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }   }\n\n    HUFv06_fillDTableX4(dt, memLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    return iSize;\n}\n\n\nstatic U32 HUFv06_decodeSymbolX4(void* op, BITv06_DStream_t* DStream, const HUFv06_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv06_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BITv06_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUFv06_decodeLastSymbolX4(void* op, BITv06_DStream_t* DStream, const HUFv06_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv06_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BITv06_skipBits(DStream, dt[val].nbBits);\n    else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BITv06_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }   }\n    return 1;\n}\n\n\n#define HUFv06_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv06_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv06_MAX_TABLELOG<=12)) \\\n        ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv06_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUFv06_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUFv06_decodeStreamX4(BYTE* p, BITv06_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv06_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p < pEnd-7)) {\n        HUFv06_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv06_reloadDStream(bitDPtr) == BITv06_DStream_unfinished) && (p <= pEnd-2))\n        HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUFv06_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUFv06_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\nsize_t HUFv06_decompress1X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    const BYTE* const istart = (const BYTE*) cSrc;\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* const oend = ostart + dstSize;\n\n    const U32 dtLog = DTable[0];\n    const void* const dtPtr = DTable;\n    const HUFv06_DEltX4* const dt = ((const HUFv06_DEltX4*)dtPtr) +1;\n\n    /* Init */\n    BITv06_DStream_t bitD;\n    { size_t const errorCode = BITv06_initDStream(&bitD, istart, cSrcSize);\n      if (HUFv06_isError(errorCode)) return errorCode; }\n\n    /* decode */\n    HUFv06_decodeStreamX4(ostart, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv06_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\nsize_t HUFv06_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX4(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv06_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv06_decompress1X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\nsize_t HUFv06_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const U32* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable;\n        const HUFv06_DEltX4* const dt = ((const HUFv06_DEltX4*)dtPtr) +1;\n        const U32 dtLog = DTable[0];\n        size_t errorCode;\n\n        /* Init */\n        BITv06_DStream_t bitD1;\n        BITv06_DStream_t bitD2;\n        BITv06_DStream_t bitD3;\n        BITv06_DStream_t bitD4;\n        const size_t length1 = MEM_readLE16(istart);\n        const size_t length2 = MEM_readLE16(istart+2);\n        const size_t length3 = MEM_readLE16(istart+4);\n        size_t length4;\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n\n        length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        errorCode = BITv06_initDStream(&bitD1, istart1, length1);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD2, istart2, length2);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD3, istart3, length3);\n        if (HUFv06_isError(errorCode)) return errorCode;\n        errorCode = BITv06_initDStream(&bitD4, istart4, length4);\n        if (HUFv06_isError(errorCode)) return errorCode;\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv06_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv06_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv06_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUFv06_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUFv06_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUFv06_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BITv06_reloadDStream(&bitD1) | BITv06_reloadDStream(&bitD2) | BITv06_reloadDStream(&bitD3) | BITv06_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv06_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv06_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv06_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv06_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv06_endOfDStream(&bitD1) & BITv06_endOfDStream(&bitD2) & BITv06_endOfDStream(&bitD3) & BITv06_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv06_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv06_CREATE_STATIC_DTABLEX4(DTable, HUFv06_MAX_TABLELOG);\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv06_readDTableX4 (DTable, cSrc, cSrcSize);\n    if (HUFv06_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize;\n    cSrcSize -= hSize;\n\n    return HUFv06_decompress4X4_usingDTable (dst, dstSize, ip, cSrcSize, DTable);\n}\n\n\n\n\n/* ********************************/\n/* Generic decompression selector */\n/* ********************************/\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nsize_t HUFv06_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[3] = { HUFv06_decompress4X2, HUFv06_decompress4X4, NULL };\n    U32 Dtime[3];   /* decompression time estimation */\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    /* decoder timing evaluation */\n    {   U32 const Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n        U32 const D256 = (U32)(dstSize >> 8);\n        U32 n; for (n=0; n<3; n++)\n            Dtime[n] = algoTime[Q][n].tableTime + (algoTime[Q][n].decode256Time * D256);\n    }\n\n    Dtime[1] += Dtime[1] >> 4; Dtime[2] += Dtime[2] >> 3; /* advantage to algorithms using less memory, for cache eviction */\n\n    {   U32 algoNb = 0;\n        if (Dtime[1] < Dtime[0]) algoNb = 1;\n        /* if (Dtime[2] < Dtime[algoNb]) algoNb = 2; */   /* current speed of HUFv06_decompress4X6 is not good */\n        return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n    }\n\n    /* return HUFv06_decompress4X2(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams single-symbol decoding */\n    /* return HUFv06_decompress4X4(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams double-symbols decoding */\n    /* return HUFv06_decompress4X6(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams quad-symbols decoding */\n}\n/*\n    Common functions of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n/*-****************************************\n*  Version\n******************************************/\n\n/*-****************************************\n*  ZSTD Error Management\n******************************************/\n/*! ZSTDv06_isError() :\n*   tells if a return value is an error code */\nunsigned ZSTDv06_isError(size_t code) { return ERR_isError(code); }\n\n/*! ZSTDv06_getErrorName() :\n*   provides error code string from function result (useful for debugging) */\nconst char* ZSTDv06_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* **************************************************************\n*  ZBUFF Error Management\n****************************************************************/\nunsigned ZBUFFv06_isError(size_t errorCode) { return ERR_isError(errorCode); }\n\nconst char* ZBUFFv06_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTDv06_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTDv06_HEAPMODE\n#  define ZSTDv06_HEAPMODE 1\n#endif\n\n\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#endif\n\n\n/*-*************************************\n*  Macros\n***************************************/\n#define ZSTDv06_isError ERR_isError   /* for inlining */\n#define FSEv06_isError  ERR_isError\n#define HUFv06_isError  ERR_isError\n\n\n/*_*******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTDv06_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/*-*************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock } ZSTDv06_dStage;\n\nstruct ZSTDv06_DCtx_s\n{\n    FSEv06_DTable LLTable[FSEv06_DTABLE_SIZE_U32(LLFSELog)];\n    FSEv06_DTable OffTable[FSEv06_DTABLE_SIZE_U32(OffFSELog)];\n    FSEv06_DTable MLTable[FSEv06_DTABLE_SIZE_U32(MLFSELog)];\n    unsigned   hufTableX4[HUFv06_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    size_t headerSize;\n    ZSTDv06_frameParams fParams;\n    blockType_t bType;   /* used in ZSTDv06_decompressContinue(), to transfer blockType between header decoding and block decoding stages */\n    ZSTDv06_dStage stage;\n    U32 flagRepeatTable;\n    const BYTE* litPtr;\n    size_t litSize;\n    BYTE litBuffer[ZSTDv06_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];\n    BYTE headerBuffer[ZSTDv06_FRAMEHEADERSIZE_MAX];\n};  /* typedef'd to ZSTDv06_DCtx within \"zstd_static.h\" */\n\nsize_t ZSTDv06_sizeofDCtx (void); /* Hidden declaration */\nsize_t ZSTDv06_sizeofDCtx (void) { return sizeof(ZSTDv06_DCtx); }\n\nsize_t ZSTDv06_decompressBegin(ZSTDv06_DCtx* dctx)\n{\n    dctx->expected = ZSTDv06_frameHeaderSize_min;\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    dctx->hufTableX4[0] = ZSTD_HUFFDTABLE_CAPACITY_LOG;\n    dctx->flagRepeatTable = 0;\n    return 0;\n}\n\nZSTDv06_DCtx* ZSTDv06_createDCtx(void)\n{\n    ZSTDv06_DCtx* dctx = (ZSTDv06_DCtx*)malloc(sizeof(ZSTDv06_DCtx));\n    if (dctx==NULL) return NULL;\n    ZSTDv06_decompressBegin(dctx);\n    return dctx;\n}\n\nsize_t ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx)\n{\n    free(dctx);\n    return 0;   /* reserved as a potential error code in the future */\n}\n\nvoid ZSTDv06_copyDCtx(ZSTDv06_DCtx* dstDCtx, const ZSTDv06_DCtx* srcDCtx)\n{\n    memcpy(dstDCtx, srcDCtx,\n           sizeof(ZSTDv06_DCtx) - (ZSTDv06_BLOCKSIZE_MAX+WILDCOPY_OVERLENGTH + ZSTDv06_frameHeaderSize_max));  /* no need to copy workspace */\n}\n\n\n/*-*************************************************************\n*   Decompression section\n***************************************************************/\n\n/* Frame format description\n   Frame Header -  [ Block Header - Block ] - Frame End\n   1) Frame Header\n      - 4 bytes - Magic Number : ZSTDv06_MAGICNUMBER (defined within zstd_static.h)\n      - 1 byte  - Frame Descriptor\n   2) Block Header\n      - 3 bytes, starting with a 2-bits descriptor\n                 Uncompressed, Compressed, Frame End, unused\n   3) Block\n      See Block Format Description\n   4) Frame End\n      - 3 bytes, compatible with Block Header\n*/\n\n\n/* Frame descriptor\n\n   1 byte, using :\n   bit 0-3 : windowLog - ZSTDv06_WINDOWLOG_ABSOLUTEMIN   (see zstd_internal.h)\n   bit 4   : minmatch 4(0) or 3(1)\n   bit 5   : reserved (must be zero)\n   bit 6-7 : Frame content size : unknown, 1 byte, 2 bytes, 8 bytes\n\n   Optional : content size (0, 1, 2 or 8 bytes)\n   0 : unknown\n   1 : 0-255 bytes\n   2 : 256 - 65535+256\n   8 : up to 16 exa\n*/\n\n\n/* Compressed Block, format description\n\n   Block = Literal Section - Sequences Section\n   Prerequisite : size of (compressed) block, maximum size of regenerated data\n\n   1) Literal Section\n\n   1.1) Header : 1-5 bytes\n        flags: 2 bits\n            00 compressed by Huff0\n            01 unused\n            10 is Raw (uncompressed)\n            11 is Rle\n            Note : using 01 => Huff0 with precomputed table ?\n            Note : delta map ? => compressed ?\n\n   1.1.1) Huff0-compressed literal block : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n   1.1.2) Raw (uncompressed) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RAW<<6) + (0<<4) + size\n               12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RLE<<6) + (0<<4) + size\n               12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n        1- CTable available (stored into workspace ?)\n        2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)\n\n\n   1.2) Literal block content\n\n   1.2.1) Huff0 block, using sizes from header\n        See Huff0 format\n\n   1.2.2) Huff0 block, using prepared table\n\n   1.2.3) Raw content\n\n   1.2.4) single byte\n\n\n   2) Sequences section\n      TO DO\n*/\n\n/** ZSTDv06_frameHeaderSize() :\n*   srcSize must be >= ZSTDv06_frameHeaderSize_min.\n*   @return : size of the Frame Header */\nstatic size_t ZSTDv06_frameHeaderSize(const void* src, size_t srcSize)\n{\n    if (srcSize < ZSTDv06_frameHeaderSize_min) return ERROR(srcSize_wrong);\n    { U32 const fcsId = (((const BYTE*)src)[4]) >> 6;\n      return ZSTDv06_frameHeaderSize_min + ZSTDv06_fcs_fieldSize[fcsId]; }\n}\n\n\n/** ZSTDv06_getFrameParams() :\n*   decode Frame Header, or provide expected `srcSize`.\n*   @return : 0, `fparamsPtr` is correctly filled,\n*            >0, `srcSize` is too small, result is expected `srcSize`,\n*             or an error code, which can be tested using ZSTDv06_isError() */\nsize_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize < ZSTDv06_frameHeaderSize_min) return ZSTDv06_frameHeaderSize_min;\n    if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) return ERROR(prefix_unknown);\n\n    /* ensure there is enough `srcSize` to fully read/decode frame header */\n    { size_t const fhsize = ZSTDv06_frameHeaderSize(src, srcSize);\n      if (srcSize < fhsize) return fhsize; }\n\n    memset(fparamsPtr, 0, sizeof(*fparamsPtr));\n    {   BYTE const frameDesc = ip[4];\n        fparamsPtr->windowLog = (frameDesc & 0xF) + ZSTDv06_WINDOWLOG_ABSOLUTEMIN;\n        if ((frameDesc & 0x20) != 0) return ERROR(frameParameter_unsupported);   /* reserved 1 bit */\n        switch(frameDesc >> 6)  /* fcsId */\n        {\n            default:   /* impossible */\n            case 0 : fparamsPtr->frameContentSize = 0; break;\n            case 1 : fparamsPtr->frameContentSize = ip[5]; break;\n            case 2 : fparamsPtr->frameContentSize = MEM_readLE16(ip+5)+256; break;\n            case 3 : fparamsPtr->frameContentSize = MEM_readLE64(ip+5); break;\n    }   }\n    return 0;\n}\n\n\n/** ZSTDv06_decodeFrameHeader() :\n*   `srcSize` must be the size provided by ZSTDv06_frameHeaderSize().\n*   @return : 0 if success, or an error code, which can be tested using ZSTDv06_isError() */\nstatic size_t ZSTDv06_decodeFrameHeader(ZSTDv06_DCtx* zc, const void* src, size_t srcSize)\n{\n    size_t const result = ZSTDv06_getFrameParams(&(zc->fParams), src, srcSize);\n    if ((MEM_32bits()) && (zc->fParams.windowLog > 25)) return ERROR(frameParameter_unsupported);\n    return result;\n}\n\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n/*! ZSTDv06_getcBlockSize() :\n*   Provides the size of compressed block from block header `src` */\nstatic size_t ZSTDv06_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE*)src;\n    U32 cSize;\n\n    if (srcSize < ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    bpPtr->blockType = (blockType_t)((*in) >> 6);\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTDv06_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    if (dst==NULL) return ERROR(dstSize_tooSmall);\n    if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);\n    memcpy(dst, src, srcSize);\n    return srcSize;\n}\n\n\n/*! ZSTDv06_decodeLiteralsBlock() :\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTDv06_decodeLiteralsBlock(ZSTDv06_DCtx* dctx,\n                          const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    /* any compressed block with literals segment must be at least this size */\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch(istart[0]>> 6)\n    {\n    case IS_HUF:\n        {   size_t litSize, litCSize, singleStream=0;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (srcSize < 5) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                /* 2 - 2 - 10 - 10 */\n                lhSize=3;\n                singleStream = istart[0] & 16;\n                litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n                litCSize = ((istart[1] &  3) << 8) + istart[2];\n                break;\n            case 2:\n                /* 2 - 2 - 14 - 14 */\n                lhSize=4;\n                litSize  = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);\n                litCSize = ((istart[2] & 63) <<  8) + istart[3];\n                break;\n            case 3:\n                /* 2 - 2 - 18 - 18 */\n                lhSize=5;\n                litSize  = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);\n                litCSize = ((istart[2] &  3) << 16) + (istart[3] << 8) + istart[4];\n                break;\n            }\n            if (litSize > ZSTDv06_BLOCKSIZE_MAX) return ERROR(corruption_detected);\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            if (HUFv06_isError(singleStream ?\n                            HUFv06_decompress1X2(dctx->litBuffer, litSize, istart+lhSize, litCSize) :\n                            HUFv06_decompress   (dctx->litBuffer, litSize, istart+lhSize, litCSize) ))\n                return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_PCH:\n        {   size_t litSize, litCSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (lhSize != 1)  /* only case supported for now : small litSize, single stream */\n                return ERROR(corruption_detected);\n            if (!dctx->flagRepeatTable)\n                return ERROR(dictionary_corrupted);\n\n            /* 2 - 2 - 10 - 10 */\n            lhSize=3;\n            litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n            litCSize = ((istart[1] &  3) << 8) + istart[2];\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            {   size_t const errorCode = HUFv06_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTableX4);\n                if (HUFv06_isError(errorCode)) return ERROR(corruption_detected);\n            }\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case IS_RAW:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize=1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                break;\n            }\n\n            if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                if (litSize+lhSize > srcSize) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart+lhSize, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n                return lhSize+litSize;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+lhSize;\n            dctx->litSize = litSize;\n            return lhSize+litSize;\n        }\n    case IS_RLE:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize = 1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                if (srcSize<4) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */\n                break;\n            }\n            if (litSize > ZSTDv06_BLOCKSIZE_MAX) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return lhSize+1;\n        }\n    default:\n        return ERROR(corruption_detected);   /* impossible */\n    }\n}\n\n\n/*! ZSTDv06_buildSeqTable() :\n    @return : nb bytes read from src,\n              or an error code if it fails, testable with ZSTDv06_isError()\n*/\nstatic size_t ZSTDv06_buildSeqTable(FSEv06_DTable* DTable, U32 type, U32 max, U32 maxLog,\n                                 const void* src, size_t srcSize,\n                                 const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)\n{\n    switch(type)\n    {\n    case FSEv06_ENCODING_RLE :\n        if (!srcSize) return ERROR(srcSize_wrong);\n        if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);\n        FSEv06_buildDTable_rle(DTable, *(const BYTE*)src);   /* if *src > max, data is corrupted */\n        return 1;\n    case FSEv06_ENCODING_RAW :\n        FSEv06_buildDTable(DTable, defaultNorm, max, defaultLog);\n        return 0;\n    case FSEv06_ENCODING_STATIC:\n        if (!flagRepeatTable) return ERROR(corruption_detected);\n        return 0;\n    default :   /* impossible */\n    case FSEv06_ENCODING_DYNAMIC :\n        {   U32 tableLog;\n            S16 norm[MaxSeq+1];\n            size_t const headerSize = FSEv06_readNCount(norm, &max, &tableLog, src, srcSize);\n            if (FSEv06_isError(headerSize)) return ERROR(corruption_detected);\n            if (tableLog > maxLog) return ERROR(corruption_detected);\n            FSEv06_buildDTable(DTable, norm, max, tableLog);\n            return headerSize;\n    }   }\n}\n\n\nstatic size_t ZSTDv06_decodeSeqHeaders(int* nbSeqPtr,\n                             FSEv06_DTable* DTableLL, FSEv06_DTable* DTableML, FSEv06_DTable* DTableOffb, U32 flagRepeatTable,\n                             const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip = istart;\n\n    /* check */\n    if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    {   int nbSeq = *ip++;\n        if (!nbSeq) { *nbSeqPtr=0; return 1; }\n        if (nbSeq > 0x7F) {\n            if (nbSeq == 0xFF) {\n                if (ip+2 > iend) return ERROR(srcSize_wrong);\n                nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;\n            } else {\n                if (ip >= iend) return ERROR(srcSize_wrong);\n                nbSeq = ((nbSeq-0x80)<<8) + *ip++;\n            }\n        }\n        *nbSeqPtr = nbSeq;\n    }\n\n    /* FSE table descriptors */\n    if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n    {   U32 const LLtype  = *ip >> 6;\n        U32 const Offtype = (*ip >> 4) & 3;\n        U32 const MLtype  = (*ip >> 2) & 3;\n        ip++;\n\n        /* Build DTables */\n        {   size_t const bhSize = ZSTDv06_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);\n            if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);\n            ip += bhSize;\n        }\n        {   size_t const bhSize = ZSTDv06_buildSeqTable(DTableOffb, Offtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);\n            if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);\n            ip += bhSize;\n        }\n        {   size_t const bhSize = ZSTDv06_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);\n            if (ZSTDv06_isError(bhSize)) return ERROR(corruption_detected);\n            ip += bhSize;\n    }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    BITv06_DStream_t DStream;\n    FSEv06_DState_t stateLL;\n    FSEv06_DState_t stateOffb;\n    FSEv06_DState_t stateML;\n    size_t prevOffset[ZSTDv06_REP_INIT];\n} seqState_t;\n\n\n\nstatic void ZSTDv06_decodeSequence(seq_t* seq, seqState_t* seqState)\n{\n    /* Literal length */\n    U32 const llCode = FSEv06_peekSymbol(&(seqState->stateLL));\n    U32 const mlCode = FSEv06_peekSymbol(&(seqState->stateML));\n    U32 const ofCode = FSEv06_peekSymbol(&(seqState->stateOffb));   /* <= maxOff, by table construction */\n\n    U32 const llBits = LL_bits[llCode];\n    U32 const mlBits = ML_bits[mlCode];\n    U32 const ofBits = ofCode;\n    U32 const totalBits = llBits+mlBits+ofBits;\n\n    static const U32 LL_base[MaxLL+1] = {\n                             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,   10,    11,    12,    13,    14,     15,\n                            16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,\n                            0x2000, 0x4000, 0x8000, 0x10000 };\n\n    static const U32 ML_base[MaxML+1] = {\n                             0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10,   11,    12,    13,    14,    15,\n                            16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,   27,    28,    29,    30,    31,\n                            32, 34, 36, 38, 40, 44, 48, 56, 64, 80, 96, 0x80, 0x100, 0x200, 0x400, 0x800,\n                            0x1000, 0x2000, 0x4000, 0x8000, 0x10000 };\n\n    static const U32 OF_base[MaxOff+1] = {\n                 0,        1,       3,       7,     0xF,     0x1F,     0x3F,     0x7F,\n                 0xFF,   0x1FF,   0x3FF,   0x7FF,   0xFFF,   0x1FFF,   0x3FFF,   0x7FFF,\n                 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF,\n                 0xFFFFFF, 0x1FFFFFF, 0x3FFFFFF, /*fake*/ 1, 1 };\n\n    /* sequence */\n    {   size_t offset;\n        if (!ofCode)\n            offset = 0;\n        else {\n            offset = OF_base[ofCode] + BITv06_readBits(&(seqState->DStream), ofBits);   /* <=  26 bits */\n            if (MEM_32bits()) BITv06_reloadDStream(&(seqState->DStream));\n        }\n\n        if (offset < ZSTDv06_REP_NUM) {\n            if (llCode == 0 && offset <= 1) offset = 1-offset;\n\n            if (offset != 0) {\n                size_t temp = seqState->prevOffset[offset];\n                if (offset != 1) {\n                    seqState->prevOffset[2] = seqState->prevOffset[1];\n                }\n                seqState->prevOffset[1] = seqState->prevOffset[0];\n                seqState->prevOffset[0] = offset = temp;\n\n            } else {\n                offset = seqState->prevOffset[0];\n            }\n        } else {\n            offset -= ZSTDv06_REP_MOVE;\n            seqState->prevOffset[2] = seqState->prevOffset[1];\n            seqState->prevOffset[1] = seqState->prevOffset[0];\n            seqState->prevOffset[0] = offset;\n        }\n        seq->offset = offset;\n    }\n\n    seq->matchLength = ML_base[mlCode] + MINMATCH + ((mlCode>31) ? BITv06_readBits(&(seqState->DStream), mlBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() && (mlBits+llBits>24)) BITv06_reloadDStream(&(seqState->DStream));\n\n    seq->litLength = LL_base[llCode] + ((llCode>15) ? BITv06_readBits(&(seqState->DStream), llBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() ||\n       (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv06_reloadDStream(&(seqState->DStream));\n\n    /* ANS state update */\n    FSEv06_updateState(&(seqState->stateLL), &(seqState->DStream));   /* <=  9 bits */\n    FSEv06_updateState(&(seqState->stateML), &(seqState->DStream));   /* <=  9 bits */\n    if (MEM_32bits()) BITv06_reloadDStream(&(seqState->DStream));     /* <= 18 bits */\n    FSEv06_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <=  8 bits */\n}\n\n\nstatic size_t ZSTDv06_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_8 = oend-8;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* checks */\n    size_t const seqLength = sequence.litLength + sequence.matchLength;\n\n    if (seqLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);\n    /* Now we know there are no overflow in literal nor match lengths, can use pointer checks */\n    if (oLitEnd > oend_8) return ERROR(dstSize_tooSmall);\n\n    if (oMatchEnd > oend) return ERROR(dstSize_tooSmall);   /* overwrite beyond dst buffer */\n    if (iLitEnd > litLimit) return ERROR(corruption_detected);   /* overRead beyond lit buffer */\n\n    /* copy Literals */\n    ZSTDv06_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : oLitEnd <= oend-8 : no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base)) {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd) {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = dictEnd - match;\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_8 || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n    }   }\n    /* Requirement: op <= oend_8 */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n        static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n        int const sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTDv06_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTDv06_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH)) {\n        if (op < oend_8) {\n            ZSTDv06_wildcopy(op, match, oend_8 - op);\n            match += oend_8 - op;\n            op = oend_8;\n        }\n        while (op < oMatchEnd) *op++ = *match++;\n    } else {\n        ZSTDv06_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTDv06_decompressSequences(\n                               ZSTDv06_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + maxDstSize;\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    FSEv06_DTable* DTableLL = dctx->LLTable;\n    FSEv06_DTable* DTableML = dctx->MLTable;\n    FSEv06_DTable* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n    int nbSeq;\n\n    /* Build Decoding Tables */\n    {   size_t const seqHSize = ZSTDv06_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->flagRepeatTable, ip, seqSize);\n        if (ZSTDv06_isError(seqHSize)) return seqHSize;\n        ip += seqHSize;\n        dctx->flagRepeatTable = 0;\n    }\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seq_t sequence;\n        seqState_t seqState;\n\n        memset(&sequence, 0, sizeof(sequence));\n        sequence.offset = REPCODE_STARTVALUE;\n        { U32 i; for (i=0; i<ZSTDv06_REP_INIT; i++) seqState.prevOffset[i] = REPCODE_STARTVALUE; }\n        { size_t const errorCode = BITv06_initDStream(&(seqState.DStream), ip, iend-ip);\n          if (ERR_isError(errorCode)) return ERROR(corruption_detected); }\n        FSEv06_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSEv06_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSEv06_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BITv06_reloadDStream(&(seqState.DStream)) <= BITv06_DStream_completed) && nbSeq ; ) {\n            nbSeq--;\n            ZSTDv06_decodeSequence(&sequence, &seqState);\n\n#if 0  /* debug */\n            static BYTE* start = NULL;\n            if (start==NULL) start = op;\n            size_t pos = (size_t)(op-start);\n            if ((pos >= 5810037) && (pos < 5810400))\n                printf(\"Dpos %6u :%5u literals & match %3u bytes at distance %6u \\n\",\n                       pos, (U32)sequence.litLength, (U32)sequence.matchLength, (U32)sequence.offset);\n#endif\n\n            {   size_t const oneSeqSize = ZSTDv06_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n                if (ZSTDv06_isError(oneSeqSize)) return oneSeqSize;\n                op += oneSeqSize;\n        }   }\n\n        /* check if reached exact end */\n        if (nbSeq) return ERROR(corruption_detected);\n    }\n\n    /* last literal segment */\n    {   size_t const lastLLSize = litEnd - litPtr;\n        if (litPtr > litEnd) return ERROR(corruption_detected);   /* too many literals already used */\n        if (op+lastLLSize > oend) return ERROR(dstSize_tooSmall);\n        if (lastLLSize > 0) {\n            memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTDv06_checkContinuity(ZSTDv06_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTDv06_decompressBlock_internal(ZSTDv06_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize >= ZSTDv06_BLOCKSIZE_MAX) return ERROR(srcSize_wrong);\n\n    /* Decode literals sub-block */\n    {   size_t const litCSize = ZSTDv06_decodeLiteralsBlock(dctx, src, srcSize);\n        if (ZSTDv06_isError(litCSize)) return litCSize;\n        ip += litCSize;\n        srcSize -= litCSize;\n    }\n    return ZSTDv06_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);\n}\n\n\nsize_t ZSTDv06_decompressBlock(ZSTDv06_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    ZSTDv06_checkContinuity(dctx, dst);\n    return ZSTDv06_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\n/*! ZSTDv06_decompressFrame() :\n*   `dctx` must be properly initialized */\nstatic size_t ZSTDv06_decompressFrame(ZSTDv06_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* op = ostart;\n    BYTE* const oend = ostart + dstCapacity;\n    size_t remainingSize = srcSize;\n    blockProperties_t blockProperties = { bt_compressed, 0 };\n\n    /* check */\n    if (srcSize < ZSTDv06_frameHeaderSize_min+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);\n        if (ZSTDv06_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) return ERROR(srcSize_wrong);\n        if (ZSTDv06_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        size_t decodedSize=0;\n        size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv06_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTDv06_blockHeaderSize;\n        remainingSize -= ZSTDv06_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTDv06_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTDv06_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            return ERROR(GENERIC);   /* not yet supported */\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        if (ZSTDv06_isError(decodedSize)) return decodedSize;\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n\nsize_t ZSTDv06_decompress_usingPreparedDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* refDCtx,\n                                         void* dst, size_t dstCapacity,\n                                   const void* src, size_t srcSize)\n{\n    ZSTDv06_copyDCtx(dctx, refDCtx);\n    ZSTDv06_checkContinuity(dctx, dst);\n    return ZSTDv06_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    ZSTDv06_decompressBegin_usingDict(dctx, dict, dictSize);\n    ZSTDv06_checkContinuity(dctx, dst);\n    return ZSTDv06_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTDv06_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);\n}\n\n\nsize_t ZSTDv06_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n#if defined(ZSTDv06_HEAPMODE) && (ZSTDv06_HEAPMODE==1)\n    size_t regenSize;\n    ZSTDv06_DCtx* dctx = ZSTDv06_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv06_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);\n    ZSTDv06_freeDCtx(dctx);\n    return regenSize;\n#else   /* stack mode */\n    ZSTDv06_DCtx dctx;\n    return ZSTDv06_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);\n#endif\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n    blockProperties_t blockProperties = { bt_compressed, 0 };\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv06_frameHeaderSize(src, srcSize);\n        if (ZSTDv06_isError(frameHeaderSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);\n            return;\n        }\n        if (MEM_readLE32(src) != ZSTDv06_MAGICNUMBER) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n            return;\n        }\n        if (srcSize < frameHeaderSize+ZSTDv06_blockHeaderSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        size_t const cBlockSize = ZSTDv06_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv06_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTDv06_blockHeaderSize;\n        remainingSize -= ZSTDv06_blockHeaderSize;\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        if (cBlockSize == 0) break;   /* bt_end */\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * ZSTDv06_BLOCKSIZE_MAX;\n}\n\n/*_******************************\n*  Streaming Decompression API\n********************************/\nsize_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nsize_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != dctx->expected) return ERROR(srcSize_wrong);\n    if (dstCapacity) ZSTDv06_checkContinuity(dctx, dst);\n\n    /* Decompress : frame header; part 1 */\n    switch (dctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        if (srcSize != ZSTDv06_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        dctx->headerSize = ZSTDv06_frameHeaderSize(src, ZSTDv06_frameHeaderSize_min);\n        if (ZSTDv06_isError(dctx->headerSize)) return dctx->headerSize;\n        memcpy(dctx->headerBuffer, src, ZSTDv06_frameHeaderSize_min);\n        if (dctx->headerSize > ZSTDv06_frameHeaderSize_min) {\n            dctx->expected = dctx->headerSize - ZSTDv06_frameHeaderSize_min;\n            dctx->stage = ZSTDds_decodeFrameHeader;\n            return 0;\n        }\n        dctx->expected = 0;   /* not necessary to copy more */\n\t/* fall-through */\n    case ZSTDds_decodeFrameHeader:\n        {   size_t result;\n            memcpy(dctx->headerBuffer + ZSTDv06_frameHeaderSize_min, src, dctx->expected);\n            result = ZSTDv06_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);\n            if (ZSTDv06_isError(result)) return result;\n            dctx->expected = ZSTDv06_blockHeaderSize;\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDds_decodeBlockHeader:\n        {   blockProperties_t bp;\n            size_t const cBlockSize = ZSTDv06_getcBlockSize(src, ZSTDv06_blockHeaderSize, &bp);\n            if (ZSTDv06_isError(cBlockSize)) return cBlockSize;\n            if (bp.blockType == bt_end) {\n                dctx->expected = 0;\n                dctx->stage = ZSTDds_getFrameHeaderSize;\n            } else {\n                dctx->expected = cBlockSize;\n                dctx->bType = bp.blockType;\n                dctx->stage = ZSTDds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDds_decompressBlock:\n        {   size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTDv06_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTDv06_copyRawBlock(dst, dstCapacity, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);   /* impossible */\n            }\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            dctx->expected = ZSTDv06_blockHeaderSize;\n            if (ZSTDv06_isError(rSize)) return rSize;\n            dctx->previousDstEnd = (char*)dst + rSize;\n            return rSize;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic void ZSTDv06_refDictContent(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n    dctx->base = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n}\n\nstatic size_t ZSTDv06_loadEntropy(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t hSize, offcodeHeaderSize, matchlengthHeaderSize, litlengthHeaderSize;\n\n    hSize = HUFv06_readDTableX4(dctx->hufTableX4, dict, dictSize);\n    if (HUFv06_isError(hSize)) return ERROR(dictionary_corrupted);\n    dict = (const char*)dict + hSize;\n    dictSize -= hSize;\n\n    {   short offcodeNCount[MaxOff+1];\n        U32 offcodeMaxValue=MaxOff, offcodeLog;\n        offcodeHeaderSize = FSEv06_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dict, dictSize);\n        if (FSEv06_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);\n        if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv06_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);\n          if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dict = (const char*)dict + offcodeHeaderSize;\n        dictSize -= offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        matchlengthHeaderSize = FSEv06_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dict, dictSize);\n        if (FSEv06_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv06_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);\n          if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dict = (const char*)dict + matchlengthHeaderSize;\n        dictSize -= matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        litlengthHeaderSize = FSEv06_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dict, dictSize);\n        if (FSEv06_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv06_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);\n          if (FSEv06_isError(errorCode)) return ERROR(dictionary_corrupted); }\n    }\n\n    dctx->flagRepeatTable = 1;\n    return hSize + offcodeHeaderSize + matchlengthHeaderSize + litlengthHeaderSize;\n}\n\nstatic size_t ZSTDv06_decompress_insertDictionary(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    size_t eSize;\n    U32 const magic = MEM_readLE32(dict);\n    if (magic != ZSTDv06_DICT_MAGIC) {\n        /* pure content mode */\n        ZSTDv06_refDictContent(dctx, dict, dictSize);\n        return 0;\n    }\n    /* load entropy tables */\n    dict = (const char*)dict + 4;\n    dictSize -= 4;\n    eSize = ZSTDv06_loadEntropy(dctx, dict, dictSize);\n    if (ZSTDv06_isError(eSize)) return ERROR(dictionary_corrupted);\n\n    /* reference dictionary content */\n    dict = (const char*)dict + eSize;\n    dictSize -= eSize;\n    ZSTDv06_refDictContent(dctx, dict, dictSize);\n\n    return 0;\n}\n\n\nsize_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    { size_t const errorCode = ZSTDv06_decompressBegin(dctx);\n      if (ZSTDv06_isError(errorCode)) return errorCode; }\n\n    if (dict && dictSize) {\n        size_t const errorCode = ZSTDv06_decompress_insertDictionary(dctx, dict, dictSize);\n        if (ZSTDv06_isError(errorCode)) return ERROR(dictionary_corrupted);\n    }\n\n    return 0;\n}\n\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv06_DCtx object is required to track streaming operations.\n*  Use ZBUFFv06_createDCtx() and ZBUFFv06_freeDCtx() to create/release resources.\n*  Use ZBUFFv06_decompressInit() to start a new decompression operation,\n*   or ZBUFFv06_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv06_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv06_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv06_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv06_recommendedDInSize() and ZBUFFv06_recommendedDOutSize()\n*  output : ZBUFFv06_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv06_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv06_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\ntypedef enum { ZBUFFds_init, ZBUFFds_loadHeader,\n               ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv06_dStage;\n\n/* *** Resource management *** */\nstruct ZBUFFv06_DCtx_s {\n    ZSTDv06_DCtx* zd;\n    ZSTDv06_frameParams fParams;\n    ZBUFFv06_dStage stage;\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t blockSize;\n    BYTE headerBuffer[ZSTDv06_FRAMEHEADERSIZE_MAX];\n    size_t lhSize;\n};   /* typedef'd to ZBUFFv06_DCtx within \"zstd_buffered.h\" */\n\n\nZBUFFv06_DCtx* ZBUFFv06_createDCtx(void)\n{\n    ZBUFFv06_DCtx* zbd = (ZBUFFv06_DCtx*)malloc(sizeof(ZBUFFv06_DCtx));\n    if (zbd==NULL) return NULL;\n    memset(zbd, 0, sizeof(*zbd));\n    zbd->zd = ZSTDv06_createDCtx();\n    if (zbd->zd==NULL) {\n        ZBUFFv06_freeDCtx(zbd); /* avoid leaking the context */\n        return NULL;\n    }\n    zbd->stage = ZBUFFds_init;\n    return zbd;\n}\n\nsize_t ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* zbd)\n{\n    if (zbd==NULL) return 0;   /* support free on null */\n    ZSTDv06_freeDCtx(zbd->zd);\n    free(zbd->inBuff);\n    free(zbd->outBuff);\n    free(zbd);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nsize_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* zbd, const void* dict, size_t dictSize)\n{\n    zbd->stage = ZBUFFds_loadHeader;\n    zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;\n    return ZSTDv06_decompressBegin_usingDict(zbd->zd, dict, dictSize);\n}\n\nsize_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* zbd)\n{\n    return ZBUFFv06_decompressInitDictionary(zbd, NULL, 0);\n}\n\n\n\nMEM_STATIC size_t ZBUFFv06_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    size_t length = MIN(dstCapacity, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n\n/* *** Decompression *** */\n\nsize_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* zbd,\n                                void* dst, size_t* dstCapacityPtr,\n                          const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* const iend = istart + *srcSizePtr;\n    const char* ip = istart;\n    char* const ostart = (char*)dst;\n    char* const oend = ostart + *dstCapacityPtr;\n    char* op = ostart;\n    U32 notDone = 1;\n\n    while (notDone) {\n        switch(zbd->stage)\n        {\n        case ZBUFFds_init :\n            return ERROR(init_missing);\n\n        case ZBUFFds_loadHeader :\n            {   size_t const hSize = ZSTDv06_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);\n                if (hSize != 0) {\n                    size_t const toLoad = hSize - zbd->lhSize;   /* if hSize!=0, hSize > zbd->lhSize */\n                    if (ZSTDv06_isError(hSize)) return hSize;\n                    if (toLoad > (size_t)(iend-ip)) {   /* not enough input to load full header */\n                        if (ip != NULL)\n                            memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);\n                        zbd->lhSize += iend-ip;\n                        *dstCapacityPtr = 0;\n                        return (hSize - zbd->lhSize) + ZSTDv06_blockHeaderSize;   /* remaining header bytes + next block header */\n                    }\n                    memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;\n                    break;\n            }   }\n\n            /* Consume header */\n            {   size_t const h1Size = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);  /* == ZSTDv06_frameHeaderSize_min */\n                size_t const h1Result = ZSTDv06_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);\n                if (ZSTDv06_isError(h1Result)) return h1Result;\n                if (h1Size < zbd->lhSize) {   /* long header */\n                    size_t const h2Size = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n                    size_t const h2Result = ZSTDv06_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);\n                    if (ZSTDv06_isError(h2Result)) return h2Result;\n            }   }\n\n            /* Frame header instruct buffer sizes */\n            {   size_t const blockSize = MIN(1 << zbd->fParams.windowLog, ZSTDv06_BLOCKSIZE_MAX);\n                zbd->blockSize = blockSize;\n                if (zbd->inBuffSize < blockSize) {\n                    free(zbd->inBuff);\n                    zbd->inBuffSize = blockSize;\n                    zbd->inBuff = (char*)malloc(blockSize);\n                    if (zbd->inBuff == NULL) return ERROR(memory_allocation);\n                }\n                {   size_t const neededOutSize = ((size_t)1 << zbd->fParams.windowLog) + blockSize + WILDCOPY_OVERLENGTH * 2;\n                    if (zbd->outBuffSize < neededOutSize) {\n                        free(zbd->outBuff);\n                        zbd->outBuffSize = neededOutSize;\n                        zbd->outBuff = (char*)malloc(neededOutSize);\n                        if (zbd->outBuff == NULL) return ERROR(memory_allocation);\n            }   }   }\n            zbd->stage = ZBUFFds_read;\n\t    /* fall-through */\n        case ZBUFFds_read:\n            {   size_t const neededInSize = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n                if (neededInSize==0) {  /* end of frame */\n                    zbd->stage = ZBUFFds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */\n                    size_t const decodedSize = ZSTDv06_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,\n                        ip, neededInSize);\n                    if (ZSTDv06_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize) break;   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbd->stage = ZBUFFds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFds_load:\n            {   size_t const neededInSize = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n                size_t const toLoad = neededInSize - zbd->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFFv06_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbd->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n\n                /* decode loaded input */\n                {   size_t const decodedSize = ZSTDv06_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,\n                        zbd->inBuff, neededInSize);\n                    if (ZSTDv06_isError(decodedSize)) return decodedSize;\n                    zbd->inPos = 0;   /* input is consumed */\n                    if (!decodedSize) { zbd->stage = ZBUFFds_read; break; }   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    /* break; */ /* ZBUFFds_flush follows */\n                }\n\t    }\n\t    /* fall-through */\n        case ZBUFFds_flush:\n            {   size_t const toFlushSize = zbd->outEnd - zbd->outStart;\n                size_t const flushedSize = ZBUFFv06_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);\n                op += flushedSize;\n                zbd->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {\n                    zbd->stage = ZBUFFds_read;\n                    if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)\n                        zbd->outStart = zbd->outEnd = 0;\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n    }   }\n\n    /* result */\n    *srcSizePtr = ip-istart;\n    *dstCapacityPtr = op-ostart;\n    {   size_t nextSrcSizeHint = ZSTDv06_nextSrcSizeToDecompress(zbd->zd);\n        if (nextSrcSizeHint > ZSTDv06_blockHeaderSize) nextSrcSizeHint+= ZSTDv06_blockHeaderSize;   /* get following block header too */\n        nextSrcSizeHint -= zbd->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nsize_t ZBUFFv06_recommendedDInSize(void)  { return ZSTDv06_BLOCKSIZE_MAX + ZSTDv06_blockHeaderSize /* block header size*/ ; }\nsize_t ZBUFFv06_recommendedDOutSize(void) { return ZSTDv06_BLOCKSIZE_MAX; }\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v06.h",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTDv06_H\n#define ZSTDv06_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*======  Dependency  ======*/\n#include <stddef.h>   /* size_t */\n\n\n/*======  Export for Windows  ======*/\n/*!\n*  ZSTDv06_DLL_EXPORT :\n*  Enable exporting of functions when building a Windows DLL\n*/\n#if defined(_WIN32) && defined(ZSTDv06_DLL_EXPORT) && (ZSTDv06_DLL_EXPORT==1)\n#  define ZSTDLIBv06_API __declspec(dllexport)\n#else\n#  define ZSTDLIBv06_API\n#endif\n\n\n/* *************************************\n*  Simple functions\n***************************************/\n/*! ZSTDv06_decompress() :\n    `compressedSize` : is the _exact_ size of the compressed blob, otherwise decompression will fail.\n    `dstCapacity` must be large enough, equal or larger than originalSize.\n    @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n              or an errorCode if it fails (which can be tested using ZSTDv06_isError()) */\nZSTDLIBv06_API size_t ZSTDv06_decompress( void* dst, size_t dstCapacity,\n                                    const void* src, size_t compressedSize);\n\n/**\nZSTDv06_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.6.x format\n    srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n    cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                or an error code if it fails (which can be tested using ZSTDv01_isError())\n    dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n*/\nvoid ZSTDv06_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/* *************************************\n*  Helper functions\n***************************************/\nZSTDLIBv06_API size_t      ZSTDv06_compressBound(size_t srcSize); /*!< maximum compressed size (worst case scenario) */\n\n/* Error Management */\nZSTDLIBv06_API unsigned    ZSTDv06_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */\nZSTDLIBv06_API const char* ZSTDv06_getErrorName(size_t code);     /*!< provides readable string for an error code */\n\n\n/* *************************************\n*  Explicit memory management\n***************************************/\n/** Decompression context */\ntypedef struct ZSTDv06_DCtx_s ZSTDv06_DCtx;\nZSTDLIBv06_API ZSTDv06_DCtx* ZSTDv06_createDCtx(void);\nZSTDLIBv06_API size_t     ZSTDv06_freeDCtx(ZSTDv06_DCtx* dctx);      /*!< @return : errorCode */\n\n/** ZSTDv06_decompressDCtx() :\n*   Same as ZSTDv06_decompress(), but requires an already allocated ZSTDv06_DCtx (see ZSTDv06_createDCtx()) */\nZSTDLIBv06_API size_t ZSTDv06_decompressDCtx(ZSTDv06_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-***********************\n*  Dictionary API\n*************************/\n/*! ZSTDv06_decompress_usingDict() :\n*   Decompression using a pre-defined Dictionary content (see dictBuilder).\n*   Dictionary must be identical to the one used during compression, otherwise regenerated data will be corrupted.\n*   Note : dict can be NULL, in which case, it's equivalent to ZSTDv06_decompressDCtx() */\nZSTDLIBv06_API size_t ZSTDv06_decompress_usingDict(ZSTDv06_DCtx* dctx,\n                                                   void* dst, size_t dstCapacity,\n                                             const void* src, size_t srcSize,\n                                             const void* dict,size_t dictSize);\n\n\n/*-************************\n*  Advanced Streaming API\n***************************/\nstruct ZSTDv06_frameParams_s { unsigned long long frameContentSize; unsigned windowLog; };\ntypedef struct ZSTDv06_frameParams_s ZSTDv06_frameParams;\n\nZSTDLIBv06_API size_t ZSTDv06_getFrameParams(ZSTDv06_frameParams* fparamsPtr, const void* src, size_t srcSize);   /**< doesn't consume input */\nZSTDLIBv06_API size_t ZSTDv06_decompressBegin_usingDict(ZSTDv06_DCtx* dctx, const void* dict, size_t dictSize);\nZSTDLIBv06_API void   ZSTDv06_copyDCtx(ZSTDv06_DCtx* dctx, const ZSTDv06_DCtx* preparedDCtx);\n\nZSTDLIBv06_API size_t ZSTDv06_nextSrcSizeToDecompress(ZSTDv06_DCtx* dctx);\nZSTDLIBv06_API size_t ZSTDv06_decompressContinue(ZSTDv06_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n\n/* *************************************\n*  ZBUFF API\n***************************************/\n\ntypedef struct ZBUFFv06_DCtx_s ZBUFFv06_DCtx;\nZSTDLIBv06_API ZBUFFv06_DCtx* ZBUFFv06_createDCtx(void);\nZSTDLIBv06_API size_t         ZBUFFv06_freeDCtx(ZBUFFv06_DCtx* dctx);\n\nZSTDLIBv06_API size_t ZBUFFv06_decompressInit(ZBUFFv06_DCtx* dctx);\nZSTDLIBv06_API size_t ZBUFFv06_decompressInitDictionary(ZBUFFv06_DCtx* dctx, const void* dict, size_t dictSize);\n\nZSTDLIBv06_API size_t ZBUFFv06_decompressContinue(ZBUFFv06_DCtx* dctx,\n                                                  void* dst, size_t* dstCapacityPtr,\n                                            const void* src, size_t* srcSizePtr);\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv06_DCtx object is required to track streaming operations.\n*  Use ZBUFFv06_createDCtx() and ZBUFFv06_freeDCtx() to create/release resources.\n*  Use ZBUFFv06_decompressInit() to start a new decompression operation,\n*   or ZBUFFv06_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv06_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv06_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv06_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv06_recommendedDInSize() and ZBUFFv06_recommendedDOutSize()\n*  output : ZBUFFv06_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv06_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv06_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nZSTDLIBv06_API unsigned ZBUFFv06_isError(size_t errorCode);\nZSTDLIBv06_API const char* ZBUFFv06_getErrorName(size_t errorCode);\n\n/** Functions below provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are just hints, they tend to offer better latency */\nZSTDLIBv06_API size_t ZBUFFv06_recommendedDInSize(void);\nZSTDLIBv06_API size_t ZBUFFv06_recommendedDOutSize(void);\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define ZSTDv06_MAGICNUMBER 0xFD2FB526   /* v0.6 */\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv06_BUFFERED_H */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v07.c",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n\n/*- Dependencies -*/\n#include <stddef.h>     /* size_t, ptrdiff_t */\n#include <string.h>     /* memcpy */\n#include <stdlib.h>     /* malloc, free, qsort */\n\n#ifndef XXH_STATIC_LINKING_ONLY\n#  define XXH_STATIC_LINKING_ONLY    /* XXH64_state_t */\n#endif\n#include <xxhash.h>                  /* XXH64_* */\n#include \"zstd_v07.h\"\n\n#define FSEv07_STATIC_LINKING_ONLY   /* FSEv07_MIN_TABLELOG */\n#define HUFv07_STATIC_LINKING_ONLY   /* HUFv07_TABLELOG_ABSOLUTEMAX */\n#define ZSTDv07_STATIC_LINKING_ONLY\n\n#include \"../common/compiler.h\"\n#include \"../common/error_private.h\"\n\n\n#ifdef ZSTDv07_STATIC_LINKING_ONLY\n\n/* ====================================================================================\n * The definitions in this section are considered experimental.\n * They should never be used with a dynamic library, as they may change in the future.\n * They are provided for advanced usages.\n * Use them only in association with static linking.\n * ==================================================================================== */\n\n/*--- Constants ---*/\n#define ZSTDv07_MAGIC_SKIPPABLE_START  0x184D2A50U\n\n#define ZSTDv07_WINDOWLOG_MAX_32  25\n#define ZSTDv07_WINDOWLOG_MAX_64  27\n#define ZSTDv07_WINDOWLOG_MAX    ((U32)(MEM_32bits() ? ZSTDv07_WINDOWLOG_MAX_32 : ZSTDv07_WINDOWLOG_MAX_64))\n#define ZSTDv07_WINDOWLOG_MIN     18\n#define ZSTDv07_CHAINLOG_MAX     (ZSTDv07_WINDOWLOG_MAX+1)\n#define ZSTDv07_CHAINLOG_MIN       4\n#define ZSTDv07_HASHLOG_MAX       ZSTDv07_WINDOWLOG_MAX\n#define ZSTDv07_HASHLOG_MIN       12\n#define ZSTDv07_HASHLOG3_MAX      17\n#define ZSTDv07_SEARCHLOG_MAX    (ZSTDv07_WINDOWLOG_MAX-1)\n#define ZSTDv07_SEARCHLOG_MIN      1\n#define ZSTDv07_SEARCHLENGTH_MAX   7\n#define ZSTDv07_SEARCHLENGTH_MIN   3\n#define ZSTDv07_TARGETLENGTH_MIN   4\n#define ZSTDv07_TARGETLENGTH_MAX 999\n\n#define ZSTDv07_FRAMEHEADERSIZE_MAX 18    /* for static allocation */\nstatic const size_t ZSTDv07_frameHeaderSize_min = 5;\nstatic const size_t ZSTDv07_frameHeaderSize_max = ZSTDv07_FRAMEHEADERSIZE_MAX;\nstatic const size_t ZSTDv07_skippableHeaderSize = 8;  /* magic number + skippable frame length */\n\n\n/* custom memory allocation functions */\ntypedef void* (*ZSTDv07_allocFunction) (void* opaque, size_t size);\ntypedef void  (*ZSTDv07_freeFunction) (void* opaque, void* address);\ntypedef struct { ZSTDv07_allocFunction customAlloc; ZSTDv07_freeFunction customFree; void* opaque; } ZSTDv07_customMem;\n\n\n/*--- Advanced Decompression functions ---*/\n\n/*! ZSTDv07_estimateDCtxSize() :\n *  Gives the potential amount of memory allocated to create a ZSTDv07_DCtx */\nZSTDLIBv07_API size_t ZSTDv07_estimateDCtxSize(void);\n\n/*! ZSTDv07_createDCtx_advanced() :\n *  Create a ZSTD decompression context using external alloc and free functions */\nZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem);\n\n/*! ZSTDv07_sizeofDCtx() :\n *  Gives the amount of memory used by a given ZSTDv07_DCtx */\nZSTDLIBv07_API size_t ZSTDv07_sizeofDCtx(const ZSTDv07_DCtx* dctx);\n\n\n/* ******************************************************************\n*  Buffer-less streaming functions (synchronous mode)\n********************************************************************/\n\nZSTDLIBv07_API size_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx);\nZSTDLIBv07_API size_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize);\nZSTDLIBv07_API void   ZSTDv07_copyDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* preparedDCtx);\n\nZSTDLIBv07_API size_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx);\nZSTDLIBv07_API size_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/*\n  Buffer-less streaming decompression (synchronous mode)\n\n  A ZSTDv07_DCtx object is required to track streaming operations.\n  Use ZSTDv07_createDCtx() / ZSTDv07_freeDCtx() to manage it.\n  A ZSTDv07_DCtx object can be re-used multiple times.\n\n  First optional operation is to retrieve frame parameters, using ZSTDv07_getFrameParams(), which doesn't consume the input.\n  It can provide the minimum size of rolling buffer required to properly decompress data (`windowSize`),\n  and optionally the final size of uncompressed content.\n  (Note : content size is an optional info that may not be present. 0 means : content size unknown)\n  Frame parameters are extracted from the beginning of compressed frame.\n  The amount of data to read is variable, from ZSTDv07_frameHeaderSize_min to ZSTDv07_frameHeaderSize_max (so if `srcSize` >= ZSTDv07_frameHeaderSize_max, it will always work)\n  If `srcSize` is too small for operation to succeed, function will return the minimum size it requires to produce a result.\n  Result : 0 when successful, it means the ZSTDv07_frameParams structure has been filled.\n          >0 : means there is not enough data into `src`. Provides the expected size to successfully decode header.\n           errorCode, which can be tested using ZSTDv07_isError()\n\n  Start decompression, with ZSTDv07_decompressBegin() or ZSTDv07_decompressBegin_usingDict().\n  Alternatively, you can copy a prepared context, using ZSTDv07_copyDCtx().\n\n  Then use ZSTDv07_nextSrcSizeToDecompress() and ZSTDv07_decompressContinue() alternatively.\n  ZSTDv07_nextSrcSizeToDecompress() tells how much bytes to provide as 'srcSize' to ZSTDv07_decompressContinue().\n  ZSTDv07_decompressContinue() requires this exact amount of bytes, or it will fail.\n\n  @result of ZSTDv07_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).\n  It can be zero, which is not an error; it just means ZSTDv07_decompressContinue() has decoded some header.\n\n  ZSTDv07_decompressContinue() needs previous data blocks during decompression, up to `windowSize`.\n  They should preferably be located contiguously, prior to current block.\n  Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters.\n  ZSTDv07_decompressContinue() is very sensitive to contiguity,\n  if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,\n    or that previous contiguous segment is large enough to properly handle maximum back-reference.\n\n  A frame is fully decoded when ZSTDv07_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n\n\n  == Special case : skippable frames ==\n\n  Skippable frames allow the integration of user-defined data into a flow of concatenated frames.\n  Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frame is following:\n  a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F\n  b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits\n  c) Frame Content - any content (User Data) of length equal to Frame Size\n  For skippable frames ZSTDv07_decompressContinue() always returns 0.\n  For skippable frames ZSTDv07_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable.\n  It also returns Frame Size as fparamsPtr->frameContentSize.\n*/\n\n\n/* **************************************\n*  Block functions\n****************************************/\n/*! Block functions produce and decode raw zstd blocks, without frame metadata.\n    Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).\n    User will have to take in charge required information to regenerate data, such as compressed and content sizes.\n\n    A few rules to respect :\n    - Compressing and decompressing require a context structure\n      + Use ZSTDv07_createCCtx() and ZSTDv07_createDCtx()\n    - It is necessary to init context before starting\n      + compression : ZSTDv07_compressBegin()\n      + decompression : ZSTDv07_decompressBegin()\n      + variants _usingDict() are also allowed\n      + copyCCtx() and copyDCtx() work too\n    - Block size is limited, it must be <= ZSTDv07_getBlockSizeMax()\n      + If you need to compress more, cut data into multiple blocks\n      + Consider using the regular ZSTDv07_compress() instead, as frame metadata costs become negligible when source size is large.\n    - When a block is considered not compressible enough, ZSTDv07_compressBlock() result will be zero.\n      In which case, nothing is produced into `dst`.\n      + User must test for such outcome and deal directly with uncompressed data\n      + ZSTDv07_decompressBlock() doesn't accept uncompressed data as input !!!\n      + In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.\n        Use ZSTDv07_insertBlock() in such a case.\n*/\n\n#define ZSTDv07_BLOCKSIZE_ABSOLUTEMAX (128 * 1024)   /* define, for static allocation */\nZSTDLIBv07_API size_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize);  /**< insert block into `dctx` history. Useful for uncompressed blocks */\n\n\n#endif   /* ZSTDv07_STATIC_LINKING_ONLY */\n\n\n/* ******************************************************************\n   mem.h\n   low-level memory access routines\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n#ifndef MEM_H_MODULE\n#define MEM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*-****************************************\n*  Compiler specifics\n******************************************/\n#if defined(_MSC_VER)   /* Visual Studio */\n#   include <stdlib.h>  /* _byteswap_ulong */\n#   include <intrin.h>  /* _byteswap_* */\n#endif\n\n\n/*-**************************************************************\n*  Basic Types\n*****************************************************************/\n#if  !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n# if defined(_AIX)\n#  include <inttypes.h>\n# else\n#  include <stdint.h> /* intptr_t */\n# endif\n  typedef  uint8_t BYTE;\n  typedef uint16_t U16;\n  typedef  int16_t S16;\n  typedef uint32_t U32;\n  typedef  int32_t S32;\n  typedef uint64_t U64;\n  typedef  int64_t S64;\n#else\n  typedef unsigned char       BYTE;\n  typedef unsigned short      U16;\n  typedef   signed short      S16;\n  typedef unsigned int        U32;\n  typedef   signed int        S32;\n  typedef unsigned long long  U64;\n  typedef   signed long long  S64;\n#endif\n\n\n/*-**************************************************************\n*  Memory I/O\n*****************************************************************/\n\nMEM_STATIC unsigned MEM_32bits(void) { return sizeof(size_t)==4; }\nMEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }\n\nMEM_STATIC unsigned MEM_isLittleEndian(void)\n{\n    const union { U32 u; BYTE c[4]; } one = { 1 };   /* don't use static : performance detrimental  */\n    return one.c[0];\n}\n\nMEM_STATIC U16 MEM_read16(const void* memPtr)\n{\n    U16 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U32 MEM_read32(const void* memPtr)\n{\n    U32 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC U64 MEM_read64(const void* memPtr)\n{\n    U64 val; memcpy(&val, memPtr, sizeof(val)); return val;\n}\n\nMEM_STATIC void MEM_write16(void* memPtr, U16 value)\n{\n    memcpy(memPtr, &value, sizeof(value));\n}\n\nMEM_STATIC U32 MEM_swap32(U32 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_ulong(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap32(in);\n#else\n    return  ((in << 24) & 0xff000000 ) |\n            ((in <<  8) & 0x00ff0000 ) |\n            ((in >>  8) & 0x0000ff00 ) |\n            ((in >> 24) & 0x000000ff );\n#endif\n}\n\nMEM_STATIC U64 MEM_swap64(U64 in)\n{\n#if defined(_MSC_VER)     /* Visual Studio */\n    return _byteswap_uint64(in);\n#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)\n    return __builtin_bswap64(in);\n#else\n    return  ((in << 56) & 0xff00000000000000ULL) |\n            ((in << 40) & 0x00ff000000000000ULL) |\n            ((in << 24) & 0x0000ff0000000000ULL) |\n            ((in << 8)  & 0x000000ff00000000ULL) |\n            ((in >> 8)  & 0x00000000ff000000ULL) |\n            ((in >> 24) & 0x0000000000ff0000ULL) |\n            ((in >> 40) & 0x000000000000ff00ULL) |\n            ((in >> 56) & 0x00000000000000ffULL);\n#endif\n}\n\n\n/*=== Little endian r/w ===*/\n\nMEM_STATIC U16 MEM_readLE16(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read16(memPtr);\n    else {\n        const BYTE* p = (const BYTE*)memPtr;\n        return (U16)(p[0] + (p[1]<<8));\n    }\n}\n\nMEM_STATIC void MEM_writeLE16(void* memPtr, U16 val)\n{\n    if (MEM_isLittleEndian()) {\n        MEM_write16(memPtr, val);\n    } else {\n        BYTE* p = (BYTE*)memPtr;\n        p[0] = (BYTE)val;\n        p[1] = (BYTE)(val>>8);\n    }\n}\n\nMEM_STATIC U32 MEM_readLE32(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read32(memPtr);\n    else\n        return MEM_swap32(MEM_read32(memPtr));\n}\n\n\nMEM_STATIC U64 MEM_readLE64(const void* memPtr)\n{\n    if (MEM_isLittleEndian())\n        return MEM_read64(memPtr);\n    else\n        return MEM_swap64(MEM_read64(memPtr));\n}\n\nMEM_STATIC size_t MEM_readLEST(const void* memPtr)\n{\n    if (MEM_32bits())\n        return (size_t)MEM_readLE32(memPtr);\n    else\n        return (size_t)MEM_readLE64(memPtr);\n}\n\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* MEM_H_MODULE */\n/* ******************************************************************\n   bitstream\n   Part of FSE library\n   header file (to include)\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef BITSTREAM_H_MODULE\n#define BITSTREAM_H_MODULE\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n/*\n*  This API consists of small unitary functions, which must be inlined for best performance.\n*  Since link-time-optimization is not available for all compilers,\n*  these functions are defined into a .h to be included.\n*/\n\n\n/*=========================================\n*  Target specific\n=========================================*/\n#if defined(__BMI__) && defined(__GNUC__)\n#  include <immintrin.h>   /* support for bextr (experimental) */\n#endif\n\n/*-********************************************\n*  bitStream decoding API (read backward)\n**********************************************/\ntypedef struct\n{\n    size_t   bitContainer;\n    unsigned bitsConsumed;\n    const char* ptr;\n    const char* start;\n} BITv07_DStream_t;\n\ntypedef enum { BITv07_DStream_unfinished = 0,\n               BITv07_DStream_endOfBuffer = 1,\n               BITv07_DStream_completed = 2,\n               BITv07_DStream_overflow = 3 } BITv07_DStream_status;  /* result of BITv07_reloadDStream() */\n               /* 1,2,4,8 would be better for bitmap combinations, but slows down performance a bit ... :( */\n\nMEM_STATIC size_t   BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize);\nMEM_STATIC size_t   BITv07_readBits(BITv07_DStream_t* bitD, unsigned nbBits);\nMEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD);\nMEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* bitD);\n\n\n\n/*-****************************************\n*  unsafe API\n******************************************/\nMEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, unsigned nbBits);\n/* faster, but works only if nbBits >= 1 */\n\n\n\n/*-**************************************************************\n*  Internal functions\n****************************************************************/\nMEM_STATIC unsigned BITv07_highbit32 (U32 val)\n{\n#   if defined(_MSC_VER)   /* Visual */\n    unsigned long r;\n    return _BitScanReverse(&r, val) ? (unsigned)r : 0;\n#   elif defined(__GNUC__) && (__GNUC__ >= 3)   /* Use GCC Intrinsic */\n    return __builtin_clz (val) ^ 31;\n#   else   /* Software version */\n    static const unsigned DeBruijnClz[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };\n    U32 v = val;\n    v |= v >> 1;\n    v |= v >> 2;\n    v |= v >> 4;\n    v |= v >> 8;\n    v |= v >> 16;\n    return DeBruijnClz[ (U32) (v * 0x07C4ACDDU) >> 27];\n#   endif\n}\n\n\n\n/*-********************************************************\n* bitStream decoding\n**********************************************************/\n/*! BITv07_initDStream() :\n*   Initialize a BITv07_DStream_t.\n*   `bitD` : a pointer to an already allocated BITv07_DStream_t structure.\n*   `srcSize` must be the *exact* size of the bitStream, in bytes.\n*   @return : size of stream (== srcSize) or an errorCode if a problem is detected\n*/\nMEM_STATIC size_t BITv07_initDStream(BITv07_DStream_t* bitD, const void* srcBuffer, size_t srcSize)\n{\n    if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); }\n\n    if (srcSize >=  sizeof(bitD->bitContainer)) {  /* normal case */\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = (const char*)srcBuffer + srcSize - sizeof(bitD->bitContainer);\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;\n          if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }\n    } else {\n        bitD->start = (const char*)srcBuffer;\n        bitD->ptr   = bitD->start;\n        bitD->bitContainer = *(const BYTE*)(bitD->start);\n        switch(srcSize)\n        {\n            case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);/* fall-through */\n            case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);/* fall-through */\n            case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);/* fall-through */\n            case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24; /* fall-through */\n            case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16; /* fall-through */\n            case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) <<  8; /* fall-through */\n            default: break;\n        }\n        { BYTE const lastByte = ((const BYTE*)srcBuffer)[srcSize-1];\n          bitD->bitsConsumed = lastByte ? 8 - BITv07_highbit32(lastByte) : 0;\n          if (lastByte == 0) return ERROR(GENERIC); /* endMark not present */ }\n        bitD->bitsConsumed += (U32)(sizeof(bitD->bitContainer) - srcSize)*8;\n    }\n\n    return srcSize;\n}\n\n\n MEM_STATIC size_t BITv07_lookBits(const BITv07_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return ((bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> 1) >> ((bitMask-nbBits) & bitMask);\n}\n\n/*! BITv07_lookBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv07_lookBitsFast(const BITv07_DStream_t* bitD, U32 nbBits)\n{\n    U32 const bitMask = sizeof(bitD->bitContainer)*8 - 1;\n    return (bitD->bitContainer << (bitD->bitsConsumed & bitMask)) >> (((bitMask+1)-nbBits) & bitMask);\n}\n\nMEM_STATIC void BITv07_skipBits(BITv07_DStream_t* bitD, U32 nbBits)\n{\n    bitD->bitsConsumed += nbBits;\n}\n\nMEM_STATIC size_t BITv07_readBits(BITv07_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv07_lookBits(bitD, nbBits);\n    BITv07_skipBits(bitD, nbBits);\n    return value;\n}\n\n/*! BITv07_readBitsFast() :\n*   unsafe version; only works if nbBits >= 1 */\nMEM_STATIC size_t BITv07_readBitsFast(BITv07_DStream_t* bitD, U32 nbBits)\n{\n    size_t const value = BITv07_lookBitsFast(bitD, nbBits);\n    BITv07_skipBits(bitD, nbBits);\n    return value;\n}\n\nMEM_STATIC BITv07_DStream_status BITv07_reloadDStream(BITv07_DStream_t* bitD)\n{\n    if (bitD->bitsConsumed > (sizeof(bitD->bitContainer)*8))  /* should not happen => corruption detected */\n        return BITv07_DStream_overflow;\n\n    if (bitD->ptr >= bitD->start + sizeof(bitD->bitContainer)) {\n        bitD->ptr -= bitD->bitsConsumed >> 3;\n        bitD->bitsConsumed &= 7;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);\n        return BITv07_DStream_unfinished;\n    }\n    if (bitD->ptr == bitD->start) {\n        if (bitD->bitsConsumed < sizeof(bitD->bitContainer)*8) return BITv07_DStream_endOfBuffer;\n        return BITv07_DStream_completed;\n    }\n    {   U32 nbBytes = bitD->bitsConsumed >> 3;\n        BITv07_DStream_status result = BITv07_DStream_unfinished;\n        if (bitD->ptr - nbBytes < bitD->start) {\n            nbBytes = (U32)(bitD->ptr - bitD->start);  /* ptr > start */\n            result = BITv07_DStream_endOfBuffer;\n        }\n        bitD->ptr -= nbBytes;\n        bitD->bitsConsumed -= nbBytes*8;\n        bitD->bitContainer = MEM_readLEST(bitD->ptr);   /* reminder : srcSize > sizeof(bitD) */\n        return result;\n    }\n}\n\n/*! BITv07_endOfDStream() :\n*   @return Tells if DStream has exactly reached its end (all bits consumed).\n*/\nMEM_STATIC unsigned BITv07_endOfDStream(const BITv07_DStream_t* DStream)\n{\n    return ((DStream->ptr == DStream->start) && (DStream->bitsConsumed == sizeof(DStream->bitContainer)*8));\n}\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* BITSTREAM_H_MODULE */\n/* ******************************************************************\n   FSE : Finite State Entropy codec\n   Public Prototypes declaration\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef FSEv07_H\n#define FSEv07_H\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/*-****************************************\n*  FSE simple functions\n******************************************/\n\n/*! FSEv07_decompress():\n    Decompress FSE data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated destination buffer 'dst', of size 'dstCapacity'.\n    @return : size of regenerated data (<= maxDstSize),\n              or an error code, which can be tested using FSEv07_isError() .\n\n    ** Important ** : FSEv07_decompress() does not decompress non-compressible nor RLE data !!!\n    Why ? : making this distinction requires a header.\n    Header management is intentionally delegated to the user layer, which can better manage special cases.\n*/\nsize_t FSEv07_decompress(void* dst,  size_t dstCapacity,\n                const void* cSrc, size_t cSrcSize);\n\n\n/* Error Management */\nunsigned    FSEv07_isError(size_t code);        /* tells if a return value is an error code */\nconst char* FSEv07_getErrorName(size_t code);   /* provides error code string (useful for debugging) */\n\n\n/*-*****************************************\n*  FSE detailed API\n******************************************/\n/*!\nFSEv07_decompress() does the following:\n1. read normalized counters with readNCount()\n2. build decoding table 'DTable' from normalized counters\n3. decode the data stream using decoding table 'DTable'\n\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and provide normalized distribution using external method.\n*/\n\n\n/* *** DECOMPRESSION *** */\n\n/*! FSEv07_readNCount():\n    Read compactly saved 'normalizedCounter' from 'rBuffer'.\n    @return : size read from 'rBuffer',\n              or an errorCode, which can be tested using FSEv07_isError().\n              maxSymbolValuePtr[0] and tableLogPtr[0] will also be updated with their respective values */\nsize_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize);\n\n/*! Constructor and Destructor of FSEv07_DTable.\n    Note that its size depends on 'tableLog' */\ntypedef unsigned FSEv07_DTable;   /* don't allocate that. It's just a way to be more restrictive than void* */\nFSEv07_DTable* FSEv07_createDTable(unsigned tableLog);\nvoid        FSEv07_freeDTable(FSEv07_DTable* dt);\n\n/*! FSEv07_buildDTable():\n    Builds 'dt', which must be already allocated, using FSEv07_createDTable().\n    return : 0, or an errorCode, which can be tested using FSEv07_isError() */\nsize_t FSEv07_buildDTable (FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog);\n\n/*! FSEv07_decompress_usingDTable():\n    Decompress compressed source `cSrc` of size `cSrcSize` using `dt`\n    into `dst` which must be already allocated.\n    @return : size of regenerated data (necessarily <= `dstCapacity`),\n              or an errorCode, which can be tested using FSEv07_isError() */\nsize_t FSEv07_decompress_usingDTable(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, const FSEv07_DTable* dt);\n\n/*!\nTutorial :\n----------\n(Note : these functions only decompress FSE-compressed blocks.\n If block is uncompressed, use memcpy() instead\n If block is a single repeated byte, use memset() instead )\n\nThe first step is to obtain the normalized frequencies of symbols.\nThis can be performed by FSEv07_readNCount() if it was saved using FSEv07_writeNCount().\n'normalizedCounter' must be already allocated, and have at least 'maxSymbolValuePtr[0]+1' cells of signed short.\nIn practice, that means it's necessary to know 'maxSymbolValue' beforehand,\nor size the table to handle worst case situations (typically 256).\nFSEv07_readNCount() will provide 'tableLog' and 'maxSymbolValue'.\nThe result of FSEv07_readNCount() is the number of bytes read from 'rBuffer'.\nNote that 'rBufferSize' must be at least 4 bytes, even if useful information is less than that.\nIf there is an error, the function will return an error code, which can be tested using FSEv07_isError().\n\nThe next step is to build the decompression tables 'FSEv07_DTable' from 'normalizedCounter'.\nThis is performed by the function FSEv07_buildDTable().\nThe space required by 'FSEv07_DTable' must be already allocated using FSEv07_createDTable().\nIf there is an error, the function will return an error code, which can be tested using FSEv07_isError().\n\n`FSEv07_DTable` can then be used to decompress `cSrc`, with FSEv07_decompress_usingDTable().\n`cSrcSize` must be strictly correct, otherwise decompression will fail.\nFSEv07_decompress_usingDTable() result will tell how many bytes were regenerated (<=`dstCapacity`).\nIf there is an error, the function will return an error code, which can be tested using FSEv07_isError(). (ex: dst buffer too small)\n*/\n\n\n#ifdef FSEv07_STATIC_LINKING_ONLY\n\n\n/* *****************************************\n*  Static allocation\n*******************************************/\n/* FSE buffer bounds */\n#define FSEv07_NCOUNTBOUND 512\n#define FSEv07_BLOCKBOUND(size) (size + (size>>7))\n\n/* It is possible to statically allocate FSE CTable/DTable as a table of unsigned using below macros */\n#define FSEv07_DTABLE_SIZE_U32(maxTableLog)                   (1 + (1<<maxTableLog))\n\n\n/* *****************************************\n*  FSE advanced API\n*******************************************/\nsize_t FSEv07_countFast(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize);\n/**< same as FSEv07_count(), but blindly trusts that all byte values within src are <= *maxSymbolValuePtr  */\n\nunsigned FSEv07_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue, unsigned minus);\n/**< same as FSEv07_optimalTableLog(), which used `minus==2` */\n\nsize_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits);\n/**< build a fake FSEv07_DTable, designed to read an uncompressed bitstream where each symbol uses nbBits */\n\nsize_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, unsigned char symbolValue);\n/**< build a fake FSEv07_DTable, designed to always generate the same symbolValue */\n\n\n\n/* *****************************************\n*  FSE symbol decompression API\n*******************************************/\ntypedef struct\n{\n    size_t      state;\n    const void* table;   /* precise table may vary, depending on U16 */\n} FSEv07_DState_t;\n\n\nstatic void     FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt);\n\nstatic unsigned char FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);\n\n\n\n/* *****************************************\n*  FSE unsafe API\n*******************************************/\nstatic unsigned char FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD);\n/* faster, but works only if nbBits is always >= 1 (otherwise, result will be corrupted) */\n\n\n/* ======    Decompression    ====== */\n\ntypedef struct {\n    U16 tableLog;\n    U16 fastMode;\n} FSEv07_DTableHeader;   /* sizeof U32 */\n\ntypedef struct\n{\n    unsigned short newState;\n    unsigned char  symbol;\n    unsigned char  nbBits;\n} FSEv07_decode_t;   /* size == U32 */\n\nMEM_STATIC void FSEv07_initDState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD, const FSEv07_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv07_DTableHeader* const DTableH = (const FSEv07_DTableHeader*)ptr;\n    DStatePtr->state = BITv07_readBits(bitD, DTableH->tableLog);\n    BITv07_reloadDStream(bitD);\n    DStatePtr->table = dt + 1;\n}\n\nMEM_STATIC BYTE FSEv07_peekSymbol(const FSEv07_DState_t* DStatePtr)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    return DInfo.symbol;\n}\n\nMEM_STATIC void FSEv07_updateState(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    size_t const lowBits = BITv07_readBits(bitD, nbBits);\n    DStatePtr->state = DInfo.newState + lowBits;\n}\n\nMEM_STATIC BYTE FSEv07_decodeSymbol(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv07_readBits(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n/*! FSEv07_decodeSymbolFast() :\n    unsafe, only works if no symbol has a probability > 50% */\nMEM_STATIC BYTE FSEv07_decodeSymbolFast(FSEv07_DState_t* DStatePtr, BITv07_DStream_t* bitD)\n{\n    FSEv07_decode_t const DInfo = ((const FSEv07_decode_t*)(DStatePtr->table))[DStatePtr->state];\n    U32 const nbBits = DInfo.nbBits;\n    BYTE const symbol = DInfo.symbol;\n    size_t const lowBits = BITv07_readBitsFast(bitD, nbBits);\n\n    DStatePtr->state = DInfo.newState + lowBits;\n    return symbol;\n}\n\n\n\n#ifndef FSEv07_COMMONDEFS_ONLY\n\n/* **************************************************************\n*  Tuning parameters\n****************************************************************/\n/*!MEMORY_USAGE :\n*  Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)\n*  Increasing memory usage improves compression ratio\n*  Reduced memory usage can improve speed, due to cache effect\n*  Recommended max value is 14, for 16KB, which nicely fits into Intel x86 L1 cache */\n#define FSEv07_MAX_MEMORY_USAGE 14\n#define FSEv07_DEFAULT_MEMORY_USAGE 13\n\n/*!FSEv07_MAX_SYMBOL_VALUE :\n*  Maximum symbol value authorized.\n*  Required for proper stack allocation */\n#define FSEv07_MAX_SYMBOL_VALUE 255\n\n\n/* **************************************************************\n*  template functions type & suffix\n****************************************************************/\n#define FSEv07_FUNCTION_TYPE BYTE\n#define FSEv07_FUNCTION_EXTENSION\n#define FSEv07_DECODE_TYPE FSEv07_decode_t\n\n\n#endif   /* !FSEv07_COMMONDEFS_ONLY */\n\n\n/* ***************************************************************\n*  Constants\n*****************************************************************/\n#define FSEv07_MAX_TABLELOG  (FSEv07_MAX_MEMORY_USAGE-2)\n#define FSEv07_MAX_TABLESIZE (1U<<FSEv07_MAX_TABLELOG)\n#define FSEv07_MAXTABLESIZE_MASK (FSEv07_MAX_TABLESIZE-1)\n#define FSEv07_DEFAULT_TABLELOG (FSEv07_DEFAULT_MEMORY_USAGE-2)\n#define FSEv07_MIN_TABLELOG 5\n\n#define FSEv07_TABLELOG_ABSOLUTE_MAX 15\n#if FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX\n#  error \"FSEv07_MAX_TABLELOG > FSEv07_TABLELOG_ABSOLUTE_MAX is not supported\"\n#endif\n\n#define FSEv07_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3)\n\n\n#endif /* FSEv07_STATIC_LINKING_ONLY */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* FSEv07_H */\n/* ******************************************************************\n   Huffman coder, part of New Generation Entropy library\n   header file\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n   You can contact the author at :\n   - Source repository : https://github.com/Cyan4973/FiniteStateEntropy\n****************************************************************** */\n#ifndef HUFv07_H_298734234\n#define HUFv07_H_298734234\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n\n\n/* *** simple functions *** */\n/**\nHUFv07_decompress() :\n    Decompress HUF data from buffer 'cSrc', of size 'cSrcSize',\n    into already allocated buffer 'dst', of minimum size 'dstSize'.\n    `dstSize` : **must** be the ***exact*** size of original (uncompressed) data.\n    Note : in contrast with FSE, HUFv07_decompress can regenerate\n           RLE (cSrcSize==1) and uncompressed (cSrcSize==dstSize) data,\n           because it knows size to regenerate.\n    @return : size of regenerated data (== dstSize),\n              or an error code, which can be tested using HUFv07_isError()\n*/\nsize_t HUFv07_decompress(void* dst,  size_t dstSize,\n                const void* cSrc, size_t cSrcSize);\n\n\n/* ****************************************\n*  Tool functions\n******************************************/\n#define HUFv07_BLOCKSIZE_MAX (128 * 1024)\n\n/* Error Management */\nunsigned    HUFv07_isError(size_t code);        /**< tells if a return value is an error code */\nconst char* HUFv07_getErrorName(size_t code);   /**< provides error code string (useful for debugging) */\n\n\n/* *** Advanced function *** */\n\n\n#ifdef HUFv07_STATIC_LINKING_ONLY\n\n\n/* *** Constants *** */\n#define HUFv07_TABLELOG_ABSOLUTEMAX  16   /* absolute limit of HUFv07_MAX_TABLELOG. Beyond that value, code does not work */\n#define HUFv07_TABLELOG_MAX  12           /* max configured tableLog (for static allocation); can be modified up to HUFv07_ABSOLUTEMAX_TABLELOG */\n#define HUFv07_TABLELOG_DEFAULT  11       /* tableLog by default, when not specified */\n#define HUFv07_SYMBOLVALUE_MAX 255\n#if (HUFv07_TABLELOG_MAX > HUFv07_TABLELOG_ABSOLUTEMAX)\n#  error \"HUFv07_TABLELOG_MAX is too large !\"\n#endif\n\n\n/* ****************************************\n*  Static allocation\n******************************************/\n/* HUF buffer bounds */\n#define HUFv07_BLOCKBOUND(size) (size + (size>>8) + 8)   /* only true if incompressible pre-filtered with fast heuristic */\n\n/* static allocation of HUF's DTable */\ntypedef U32 HUFv07_DTable;\n#define HUFv07_DTABLE_SIZE(maxTableLog)   (1 + (1<<(maxTableLog)))\n#define HUFv07_CREATE_STATIC_DTABLEX2(DTable, maxTableLog) \\\n        HUFv07_DTable DTable[HUFv07_DTABLE_SIZE((maxTableLog)-1)] = { ((U32)((maxTableLog)-1)*0x1000001) }\n#define HUFv07_CREATE_STATIC_DTABLEX4(DTable, maxTableLog) \\\n        HUFv07_DTable DTable[HUFv07_DTABLE_SIZE(maxTableLog)] = { ((U32)(maxTableLog)*0x1000001) }\n\n\n/* ****************************************\n*  Advanced decompression functions\n******************************************/\nsize_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\n\nsize_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< decodes RLE and uncompressed */\nsize_t HUFv07_decompress4X_hufOnly(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /**< considers RLE and uncompressed as errors */\nsize_t HUFv07_decompress4X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUFv07_decompress4X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\n\nsize_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\nsize_t HUFv07_decompress1X2_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< single-symbol decoder */\nsize_t HUFv07_decompress1X4_DCtx(HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /**< double-symbols decoder */\n\n\n/* ****************************************\n*  HUF detailed API\n******************************************/\n/*!\nThe following API allows targeting specific sub-functions for advanced tasks.\nFor example, it's possible to compress several blocks using the same 'CTable',\nor to save and regenerate 'CTable' using external methods.\n*/\n/* FSEv07_count() : find it within \"fse.h\" */\n\n/*! HUFv07_readStats() :\n    Read compact Huffman tree, saved by HUFv07_writeCTable().\n    `huffWeight` is destination buffer.\n    @return : size read from `src` , or an error Code .\n    Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() . */\nsize_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize);\n\n\n/*\nHUFv07_decompress() does the following:\n1. select the decompression algorithm (X2, X4) based on pre-computed heuristics\n2. build Huffman table from save, using HUFv07_readDTableXn()\n3. decode 1 or 4 segments in parallel using HUFv07_decompressSXn_usingDTable\n*/\n\n/** HUFv07_selectDecoder() :\n*   Tells which decoder is likely to decode faster,\n*   based on a set of pre-determined metrics.\n*   @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .\n*   Assumption : 0 < cSrcSize < dstSize <= 128 KB */\nU32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize);\n\nsize_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize);\nsize_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize);\n\nsize_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress4X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\n\n\n/* single stream variants */\nsize_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* single-symbol decoder */\nsize_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);   /* double-symbol decoder */\n\nsize_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress1X2_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\nsize_t HUFv07_decompress1X4_usingDTable(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUFv07_DTable* DTable);\n\n\n#endif /* HUFv07_STATIC_LINKING_ONLY */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* HUFv07_H_298734234 */\n/*\n   Common functions of New Generation Entropy library\n   Copyright (C) 2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n*************************************************************************** */\n\n\n\n/*-****************************************\n*  FSE Error Management\n******************************************/\nunsigned FSEv07_isError(size_t code) { return ERR_isError(code); }\n\nconst char* FSEv07_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/* **************************************************************\n*  HUF Error Management\n****************************************************************/\nunsigned HUFv07_isError(size_t code) { return ERR_isError(code); }\n\nconst char* HUFv07_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n/*-**************************************************************\n*  FSE NCount encoding-decoding\n****************************************************************/\nstatic short FSEv07_abs(short a) { return (short)(a<0 ? -a : a); }\n\nsize_t FSEv07_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,\n                 const void* headerBuffer, size_t hbSize)\n{\n    const BYTE* const istart = (const BYTE*) headerBuffer;\n    const BYTE* const iend = istart + hbSize;\n    const BYTE* ip = istart;\n    int nbBits;\n    int remaining;\n    int threshold;\n    U32 bitStream;\n    int bitCount;\n    unsigned charnum = 0;\n    int previous0 = 0;\n\n    if (hbSize < 4) return ERROR(srcSize_wrong);\n    bitStream = MEM_readLE32(ip);\n    nbBits = (bitStream & 0xF) + FSEv07_MIN_TABLELOG;   /* extract tableLog */\n    if (nbBits > FSEv07_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge);\n    bitStream >>= 4;\n    bitCount = 4;\n    *tableLogPtr = nbBits;\n    remaining = (1<<nbBits)+1;\n    threshold = 1<<nbBits;\n    nbBits++;\n\n    while ((remaining>1) && (charnum<=*maxSVPtr)) {\n        if (previous0) {\n            unsigned n0 = charnum;\n            while ((bitStream & 0xFFFF) == 0xFFFF) {\n                n0+=24;\n                if (ip < iend-5) {\n                    ip+=2;\n                    bitStream = MEM_readLE32(ip) >> bitCount;\n                } else {\n                    bitStream >>= 16;\n                    bitCount+=16;\n            }   }\n            while ((bitStream & 3) == 3) {\n                n0+=3;\n                bitStream>>=2;\n                bitCount+=2;\n            }\n            n0 += bitStream & 3;\n            bitCount += 2;\n            if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall);\n            while (charnum < n0) normalizedCounter[charnum++] = 0;\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n                bitStream = MEM_readLE32(ip) >> bitCount;\n            }\n            else\n                bitStream >>= 2;\n        }\n        {   short const max = (short)((2*threshold-1)-remaining);\n            short count;\n\n            if ((bitStream & (threshold-1)) < (U32)max) {\n                count = (short)(bitStream & (threshold-1));\n                bitCount   += nbBits-1;\n            } else {\n                count = (short)(bitStream & (2*threshold-1));\n                if (count >= threshold) count -= max;\n                bitCount   += nbBits;\n            }\n\n            count--;   /* extra accuracy */\n            remaining -= FSEv07_abs(count);\n            normalizedCounter[charnum++] = count;\n            previous0 = !count;\n            while (remaining < threshold) {\n                nbBits--;\n                threshold >>= 1;\n            }\n\n            if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) {\n                ip += bitCount>>3;\n                bitCount &= 7;\n            } else {\n                bitCount -= (int)(8 * (iend - 4 - ip));\n                ip = iend - 4;\n            }\n            bitStream = MEM_readLE32(ip) >> (bitCount & 31);\n    }   }   /* while ((remaining>1) && (charnum<=*maxSVPtr)) */\n    if (remaining != 1) return ERROR(GENERIC);\n    *maxSVPtr = charnum-1;\n\n    ip += (bitCount+7)>>3;\n    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);\n    return ip-istart;\n}\n\n\n/*! HUFv07_readStats() :\n    Read compact Huffman tree, saved by HUFv07_writeCTable().\n    `huffWeight` is destination buffer.\n    @return : size read from `src` , or an error Code .\n    Note : Needed by HUFv07_readCTable() and HUFv07_readDTableXn() .\n*/\nsize_t HUFv07_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,\n                     U32* nbSymbolsPtr, U32* tableLogPtr,\n                     const void* src, size_t srcSize)\n{\n    U32 weightTotal;\n    const BYTE* ip = (const BYTE*) src;\n    size_t iSize;\n    size_t oSize;\n\n    if (!srcSize) return ERROR(srcSize_wrong);\n    iSize = ip[0];\n    /* memset(huffWeight, 0, hwSize); */   /* is not necessary, even though some analyzer complain ... */\n\n    if (iSize >= 128)  { /* special header */\n        if (iSize >= (242)) {  /* RLE */\n            static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };\n            oSize = l[iSize-242];\n            memset(huffWeight, 1, hwSize);\n            iSize = 0;\n        }\n        else {   /* Incompressible */\n            oSize = iSize - 127;\n            iSize = ((oSize+1)/2);\n            if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n            if (oSize >= hwSize) return ERROR(corruption_detected);\n            ip += 1;\n            {   U32 n;\n                for (n=0; n<oSize; n+=2) {\n                    huffWeight[n]   = ip[n/2] >> 4;\n                    huffWeight[n+1] = ip[n/2] & 15;\n    }   }   }   }\n    else  {   /* header compressed with FSE (normal case) */\n        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);\n        oSize = FSEv07_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */\n        if (FSEv07_isError(oSize)) return oSize;\n    }\n\n    /* collect weight stats */\n    memset(rankStats, 0, (HUFv07_TABLELOG_ABSOLUTEMAX + 1) * sizeof(U32));\n    weightTotal = 0;\n    {   U32 n; for (n=0; n<oSize; n++) {\n            if (huffWeight[n] >= HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);\n            rankStats[huffWeight[n]]++;\n            weightTotal += (1 << huffWeight[n]) >> 1;\n    }   }\n    if (weightTotal == 0) return ERROR(corruption_detected);\n\n    /* get last non-null symbol weight (implied, total must be 2^n) */\n    {   U32 const tableLog = BITv07_highbit32(weightTotal) + 1;\n        if (tableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(corruption_detected);\n        *tableLogPtr = tableLog;\n        /* determine last weight */\n        {   U32 const total = 1 << tableLog;\n            U32 const rest = total - weightTotal;\n            U32 const verif = 1 << BITv07_highbit32(rest);\n            U32 const lastWeight = BITv07_highbit32(rest) + 1;\n            if (verif != rest) return ERROR(corruption_detected);    /* last value must be a clean power of 2 */\n            huffWeight[oSize] = (BYTE)lastWeight;\n            rankStats[lastWeight]++;\n    }   }\n\n    /* check tree construction validity */\n    if ((rankStats[1] < 2) || (rankStats[1] & 1)) return ERROR(corruption_detected);   /* by construction : at least 2 elts of rank 1, must be even */\n\n    /* results */\n    *nbSymbolsPtr = (U32)(oSize+1);\n    return iSize+1;\n}\n/* ******************************************************************\n   FSE : Finite State Entropy decoder\n   Copyright (C) 2013-2015, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  define FORCE_INLINE static __forceinline\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4214)        /* disable: C4214: non-int bitfields */\n#else\n#  if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */\n#    ifdef __GNUC__\n#      define FORCE_INLINE static inline __attribute__((always_inline))\n#    else\n#      define FORCE_INLINE static inline\n#    endif\n#  else\n#    define FORCE_INLINE static\n#  endif /* __STDC_VERSION__ */\n#endif\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define FSEv07_isError ERR_isError\n#define FSEv07_STATIC_ASSERT(c) { enum { FSEv07_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/* **************************************************************\n*  Complex types\n****************************************************************/\ntypedef U32 DTable_max_t[FSEv07_DTABLE_SIZE_U32(FSEv07_MAX_TABLELOG)];\n\n\n/* **************************************************************\n*  Templates\n****************************************************************/\n/*\n  designed to be included\n  for type-specific functions (template emulation in C)\n  Objective is to write these functions only once, for improved maintenance\n*/\n\n/* safety checks */\n#ifndef FSEv07_FUNCTION_EXTENSION\n#  error \"FSEv07_FUNCTION_EXTENSION must be defined\"\n#endif\n#ifndef FSEv07_FUNCTION_TYPE\n#  error \"FSEv07_FUNCTION_TYPE must be defined\"\n#endif\n\n/* Function names */\n#define FSEv07_CAT(X,Y) X##Y\n#define FSEv07_FUNCTION_NAME(X,Y) FSEv07_CAT(X,Y)\n#define FSEv07_TYPE_NAME(X,Y) FSEv07_CAT(X,Y)\n\n\n/* Function templates */\nFSEv07_DTable* FSEv07_createDTable (unsigned tableLog)\n{\n    if (tableLog > FSEv07_TABLELOG_ABSOLUTE_MAX) tableLog = FSEv07_TABLELOG_ABSOLUTE_MAX;\n    return (FSEv07_DTable*)malloc( FSEv07_DTABLE_SIZE_U32(tableLog) * sizeof (U32) );\n}\n\nvoid FSEv07_freeDTable (FSEv07_DTable* dt)\n{\n    free(dt);\n}\n\nsize_t FSEv07_buildDTable(FSEv07_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)\n{\n    void* const tdPtr = dt+1;   /* because *dt is unsigned, 32-bits aligned on 32-bits */\n    FSEv07_DECODE_TYPE* const tableDecode = (FSEv07_DECODE_TYPE*) (tdPtr);\n    U16 symbolNext[FSEv07_MAX_SYMBOL_VALUE+1];\n\n    U32 const maxSV1 = maxSymbolValue + 1;\n    U32 const tableSize = 1 << tableLog;\n    U32 highThreshold = tableSize-1;\n\n    /* Sanity Checks */\n    if (maxSymbolValue > FSEv07_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge);\n    if (tableLog > FSEv07_MAX_TABLELOG) return ERROR(tableLog_tooLarge);\n\n    /* Init, lay down lowprob symbols */\n    {   FSEv07_DTableHeader DTableH;\n        DTableH.tableLog = (U16)tableLog;\n        DTableH.fastMode = 1;\n        {   S16 const largeLimit= (S16)(1 << (tableLog-1));\n            U32 s;\n            for (s=0; s<maxSV1; s++) {\n                if (normalizedCounter[s]==-1) {\n                    tableDecode[highThreshold--].symbol = (FSEv07_FUNCTION_TYPE)s;\n                    symbolNext[s] = 1;\n                } else {\n                    if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0;\n                    symbolNext[s] = normalizedCounter[s];\n        }   }   }\n        memcpy(dt, &DTableH, sizeof(DTableH));\n    }\n\n    /* Spread symbols */\n    {   U32 const tableMask = tableSize-1;\n        U32 const step = FSEv07_TABLESTEP(tableSize);\n        U32 s, position = 0;\n        for (s=0; s<maxSV1; s++) {\n            int i;\n            for (i=0; i<normalizedCounter[s]; i++) {\n                tableDecode[position].symbol = (FSEv07_FUNCTION_TYPE)s;\n                position = (position + step) & tableMask;\n                while (position > highThreshold) position = (position + step) & tableMask;   /* lowprob area */\n        }   }\n\n        if (position!=0) return ERROR(GENERIC);   /* position must reach all cells once, otherwise normalizedCounter is incorrect */\n    }\n\n    /* Build Decoding table */\n    {   U32 u;\n        for (u=0; u<tableSize; u++) {\n            FSEv07_FUNCTION_TYPE const symbol = (FSEv07_FUNCTION_TYPE)(tableDecode[u].symbol);\n            U16 nextState = symbolNext[symbol]++;\n            tableDecode[u].nbBits = (BYTE) (tableLog - BITv07_highbit32 ((U32)nextState) );\n            tableDecode[u].newState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);\n    }   }\n\n    return 0;\n}\n\n\n\n#ifndef FSEv07_COMMONDEFS_ONLY\n\n/*-*******************************************************\n*  Decompression (Byte symbols)\n*********************************************************/\nsize_t FSEv07_buildDTable_rle (FSEv07_DTable* dt, BYTE symbolValue)\n{\n    void* ptr = dt;\n    FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv07_decode_t* const cell = (FSEv07_decode_t*)dPtr;\n\n    DTableH->tableLog = 0;\n    DTableH->fastMode = 0;\n\n    cell->newState = 0;\n    cell->symbol = symbolValue;\n    cell->nbBits = 0;\n\n    return 0;\n}\n\n\nsize_t FSEv07_buildDTable_raw (FSEv07_DTable* dt, unsigned nbBits)\n{\n    void* ptr = dt;\n    FSEv07_DTableHeader* const DTableH = (FSEv07_DTableHeader*)ptr;\n    void* dPtr = dt + 1;\n    FSEv07_decode_t* const dinfo = (FSEv07_decode_t*)dPtr;\n    const unsigned tableSize = 1 << nbBits;\n    const unsigned tableMask = tableSize - 1;\n    const unsigned maxSV1 = tableMask+1;\n    unsigned s;\n\n    /* Sanity checks */\n    if (nbBits < 1) return ERROR(GENERIC);         /* min size */\n\n    /* Build Decoding Table */\n    DTableH->tableLog = (U16)nbBits;\n    DTableH->fastMode = 1;\n    for (s=0; s<maxSV1; s++) {\n        dinfo[s].newState = 0;\n        dinfo[s].symbol = (BYTE)s;\n        dinfo[s].nbBits = (BYTE)nbBits;\n    }\n\n    return 0;\n}\n\nFORCE_INLINE size_t FSEv07_decompress_usingDTable_generic(\n          void* dst, size_t maxDstSize,\n    const void* cSrc, size_t cSrcSize,\n    const FSEv07_DTable* dt, const unsigned fast)\n{\n    BYTE* const ostart = (BYTE*) dst;\n    BYTE* op = ostart;\n    BYTE* const omax = op + maxDstSize;\n    BYTE* const olimit = omax-3;\n\n    BITv07_DStream_t bitD;\n    FSEv07_DState_t state1;\n    FSEv07_DState_t state2;\n\n    /* Init */\n    { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);   /* replaced last arg by maxCompressed Size */\n      if (FSEv07_isError(errorCode)) return errorCode; }\n\n    FSEv07_initDState(&state1, &bitD, dt);\n    FSEv07_initDState(&state2, &bitD, dt);\n\n#define FSEv07_GETSYMBOL(statePtr) fast ? FSEv07_decodeSymbolFast(statePtr, &bitD) : FSEv07_decodeSymbol(statePtr, &bitD)\n\n    /* 4 symbols per loop */\n    for ( ; (BITv07_reloadDStream(&bitD)==BITv07_DStream_unfinished) && (op<olimit) ; op+=4) {\n        op[0] = FSEv07_GETSYMBOL(&state1);\n\n        if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv07_reloadDStream(&bitD);\n\n        op[1] = FSEv07_GETSYMBOL(&state2);\n\n        if (FSEv07_MAX_TABLELOG*4+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            { if (BITv07_reloadDStream(&bitD) > BITv07_DStream_unfinished) { op+=2; break; } }\n\n        op[2] = FSEv07_GETSYMBOL(&state1);\n\n        if (FSEv07_MAX_TABLELOG*2+7 > sizeof(bitD.bitContainer)*8)    /* This test must be static */\n            BITv07_reloadDStream(&bitD);\n\n        op[3] = FSEv07_GETSYMBOL(&state2);\n    }\n\n    /* tail */\n    /* note : BITv07_reloadDStream(&bitD) >= FSEv07_DStream_partiallyFilled; Ends at exactly BITv07_DStream_completed */\n    while (1) {\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv07_GETSYMBOL(&state1);\n\n        if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {\n            *op++ = FSEv07_GETSYMBOL(&state2);\n            break;\n        }\n\n        if (op>(omax-2)) return ERROR(dstSize_tooSmall);\n\n        *op++ = FSEv07_GETSYMBOL(&state2);\n\n        if (BITv07_reloadDStream(&bitD)==BITv07_DStream_overflow) {\n            *op++ = FSEv07_GETSYMBOL(&state1);\n            break;\n    }   }\n\n    return op-ostart;\n}\n\n\nsize_t FSEv07_decompress_usingDTable(void* dst, size_t originalSize,\n                            const void* cSrc, size_t cSrcSize,\n                            const FSEv07_DTable* dt)\n{\n    const void* ptr = dt;\n    const FSEv07_DTableHeader* DTableH = (const FSEv07_DTableHeader*)ptr;\n    const U32 fastMode = DTableH->fastMode;\n\n    /* select fast mode (static) */\n    if (fastMode) return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 1);\n    return FSEv07_decompress_usingDTable_generic(dst, originalSize, cSrc, cSrcSize, dt, 0);\n}\n\n\nsize_t FSEv07_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* const istart = (const BYTE*)cSrc;\n    const BYTE* ip = istart;\n    short counting[FSEv07_MAX_SYMBOL_VALUE+1];\n    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */\n    unsigned tableLog;\n    unsigned maxSymbolValue = FSEv07_MAX_SYMBOL_VALUE;\n\n    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */\n\n    /* normal FSE decoding mode */\n    {   size_t const NCountLength = FSEv07_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);\n        if (FSEv07_isError(NCountLength)) return NCountLength;\n        if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */\n        ip += NCountLength;\n        cSrcSize -= NCountLength;\n    }\n\n    { size_t const errorCode = FSEv07_buildDTable (dt, counting, maxSymbolValue, tableLog);\n      if (FSEv07_isError(errorCode)) return errorCode; }\n\n    return FSEv07_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);   /* always return, even if it is an error code */\n}\n\n\n\n#endif   /* FSEv07_COMMONDEFS_ONLY */\n\n/* ******************************************************************\n   Huffman decoder, part of New Generation Entropy library\n   Copyright (C) 2013-2016, Yann Collet.\n\n   BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are\n   met:\n\n       * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n       * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following disclaimer\n   in the documentation and/or other materials provided with the\n   distribution.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - FSE+HUF source repository : https://github.com/Cyan4973/FiniteStateEntropy\n    - Public forum : https://groups.google.com/forum/#!forum/lz4c\n****************************************************************** */\n\n/* **************************************************************\n*  Compiler specifics\n****************************************************************/\n#if defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n/* inline is defined */\n#elif defined(_MSC_VER)\n#  define inline __inline\n#else\n#  define inline /* disable inline */\n#endif\n\n\n#ifdef _MSC_VER    /* Visual Studio */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#endif\n\n\n\n/* **************************************************************\n*  Error Management\n****************************************************************/\n#define HUFv07_STATIC_ASSERT(c) { enum { HUFv07_static_assert = 1/(int)(!!(c)) }; }   /* use only *after* variable declarations */\n\n\n/*-***************************/\n/*  generic DTableDesc       */\n/*-***************************/\n\ntypedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; } DTableDesc;\n\nstatic DTableDesc HUFv07_getDTableDesc(const HUFv07_DTable* table)\n{\n    DTableDesc dtd;\n    memcpy(&dtd, table, sizeof(dtd));\n    return dtd;\n}\n\n\n/*-***************************/\n/*  single-symbol decoding   */\n/*-***************************/\n\ntypedef struct { BYTE byte; BYTE nbBits; } HUFv07_DEltX2;   /* single-symbol decoding */\n\nsize_t HUFv07_readDTableX2 (HUFv07_DTable* DTable, const void* src, size_t srcSize)\n{\n    BYTE huffWeight[HUFv07_SYMBOLVALUE_MAX + 1];\n    U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];   /* large enough for values from 0 to 16 */\n    U32 tableLog = 0;\n    U32 nbSymbols = 0;\n    size_t iSize;\n    void* const dtPtr = DTable + 1;\n    HUFv07_DEltX2* const dt = (HUFv07_DEltX2*)dtPtr;\n\n    HUFv07_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUFv07_DTable));\n    /* memset(huffWeight, 0, sizeof(huffWeight)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv07_readStats(huffWeight, HUFv07_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv07_isError(iSize)) return iSize;\n\n    /* Table header */\n    {   DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n        if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge);   /* DTable too small, huffman tree cannot fit in */\n        dtd.tableType = 0;\n        dtd.tableLog = (BYTE)tableLog;\n        memcpy(DTable, &dtd, sizeof(dtd));\n    }\n\n    /* Prepare ranks */\n    {   U32 n, nextRankStart = 0;\n        for (n=1; n<tableLog+1; n++) {\n            U32 current = nextRankStart;\n            nextRankStart += (rankVal[n] << (n-1));\n            rankVal[n] = current;\n    }   }\n\n    /* fill DTable */\n    {   U32 n;\n        for (n=0; n<nbSymbols; n++) {\n            U32 const w = huffWeight[n];\n            U32 const length = (1 << w) >> 1;\n            U32 i;\n            HUFv07_DEltX2 D;\n            D.byte = (BYTE)n; D.nbBits = (BYTE)(tableLog + 1 - w);\n            for (i = rankVal[w]; i < rankVal[w] + length; i++)\n                dt[i] = D;\n            rankVal[w] += length;\n    }   }\n\n    return iSize;\n}\n\n\nstatic BYTE HUFv07_decodeSymbolX2(BITv07_DStream_t* Dstream, const HUFv07_DEltX2* dt, const U32 dtLog)\n{\n    size_t const val = BITv07_lookBitsFast(Dstream, dtLog); /* note : dtLog >= 1 */\n    BYTE const c = dt[val].byte;\n    BITv07_skipBits(Dstream, dt[val].nbBits);\n    return c;\n}\n\n#define HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr) \\\n    *ptr++ = HUFv07_decodeSymbolX2(DStreamPtr, dt, dtLog)\n\n#define HUFv07_DECODE_SYMBOLX2_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \\\n        HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\n#define HUFv07_DECODE_SYMBOLX2_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        HUFv07_DECODE_SYMBOLX2_0(ptr, DStreamPtr)\n\nstatic inline size_t HUFv07_decodeStreamX2(BYTE* p, BITv07_DStream_t* const bitDPtr, BYTE* const pEnd, const HUFv07_DEltX2* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 4 symbols at a time */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-4)) {\n        HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX2_1(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX2_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);\n    }\n\n    /* closer to the end */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd))\n        HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    /* no more data to retrieve from bitstream, hence no need to reload */\n    while (p < pEnd)\n        HUFv07_DECODE_SYMBOLX2_0(p, bitDPtr);\n\n    return pEnd-pStart;\n}\n\nstatic size_t HUFv07_decompress1X2_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + dstSize;\n    const void* dtPtr = DTable + 1;\n    const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;\n    BITv07_DStream_t bitD;\n    DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n    U32 const dtLog = dtd.tableLog;\n\n    { size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);\n      if (HUFv07_isError(errorCode)) return errorCode; }\n\n    HUFv07_decodeStreamX2(op, &bitD, oend, dt, dtLog);\n\n    /* check */\n    if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    return dstSize;\n}\n\nsize_t HUFv07_decompress1X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 0) return ERROR(GENERIC);\n    return HUFv07_decompress1X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nsize_t HUFv07_decompress1X2_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv07_readDTableX2 (DCtx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress1X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);\n}\n\nsize_t HUFv07_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress1X2_DCtx (DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n\nstatic size_t HUFv07_decompress4X2_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    /* Check */\n    if (cSrcSize < 10) return ERROR(corruption_detected);  /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable + 1;\n        const HUFv07_DEltX2* const dt = (const HUFv07_DEltX2*)dtPtr;\n\n        /* Init */\n        BITv07_DStream_t bitD1;\n        BITv07_DStream_t bitD2;\n        BITv07_DStream_t bitD3;\n        BITv07_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        const size_t segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n        DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX2_1(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_1(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_1(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_1(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX2_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX2_0(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX2_0(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX2_0(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX2_0(op4, &bitD4);\n            endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv07_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv07_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv07_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv07_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        endSignal = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);\n        if (!endSignal) return ERROR(corruption_detected);\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv07_decompress4X2_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 0) return ERROR(GENERIC);\n    return HUFv07_decompress4X2_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n\nsize_t HUFv07_decompress4X2_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv07_readDTableX2 (dctx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress4X2_usingDTable_internal (dst, dstSize, ip, cSrcSize, dctx);\n}\n\nsize_t HUFv07_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX2(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n\n/* *************************/\n/* double-symbols decoding */\n/* *************************/\ntypedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUFv07_DEltX4;  /* double-symbols decoding */\n\ntypedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;\n\nstatic void HUFv07_fillDTableX4Level2(HUFv07_DEltX4* DTable, U32 sizeLog, const U32 consumed,\n                           const U32* rankValOrigin, const int minWeight,\n                           const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,\n                           U32 nbBitsBaseline, U16 baseSeq)\n{\n    HUFv07_DEltX4 DElt;\n    U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];\n\n    /* get pre-calculated rankVal */\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill skipped values */\n    if (minWeight>1) {\n        U32 i, skipSize = rankVal[minWeight];\n        MEM_writeLE16(&(DElt.sequence), baseSeq);\n        DElt.nbBits   = (BYTE)(consumed);\n        DElt.length   = 1;\n        for (i = 0; i < skipSize; i++)\n            DTable[i] = DElt;\n    }\n\n    /* fill DTable */\n    { U32 s; for (s=0; s<sortedListSize; s++) {   /* note : sortedSymbols already skipped */\n        const U32 symbol = sortedSymbols[s].symbol;\n        const U32 weight = sortedSymbols[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 length = 1 << (sizeLog-nbBits);\n        const U32 start = rankVal[weight];\n        U32 i = start;\n        const U32 end = start + length;\n\n        MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));\n        DElt.nbBits = (BYTE)(nbBits + consumed);\n        DElt.length = 2;\n        do { DTable[i++] = DElt; } while (i<end);   /* since length >= 1 */\n\n        rankVal[weight] += length;\n    }}\n}\n\ntypedef U32 rankVal_t[HUFv07_TABLELOG_ABSOLUTEMAX][HUFv07_TABLELOG_ABSOLUTEMAX + 1];\n\nstatic void HUFv07_fillDTableX4(HUFv07_DEltX4* DTable, const U32 targetLog,\n                           const sortedSymbol_t* sortedList, const U32 sortedListSize,\n                           const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,\n                           const U32 nbBitsBaseline)\n{\n    U32 rankVal[HUFv07_TABLELOG_ABSOLUTEMAX + 1];\n    const int scaleLog = nbBitsBaseline - targetLog;   /* note : targetLog >= srcLog, hence scaleLog <= 1 */\n    const U32 minBits  = nbBitsBaseline - maxWeight;\n    U32 s;\n\n    memcpy(rankVal, rankValOrigin, sizeof(rankVal));\n\n    /* fill DTable */\n    for (s=0; s<sortedListSize; s++) {\n        const U16 symbol = sortedList[s].symbol;\n        const U32 weight = sortedList[s].weight;\n        const U32 nbBits = nbBitsBaseline - weight;\n        const U32 start = rankVal[weight];\n        const U32 length = 1 << (targetLog-nbBits);\n\n        if (targetLog-nbBits >= minBits) {   /* enough room for a second symbol */\n            U32 sortedRank;\n            int minWeight = nbBits + scaleLog;\n            if (minWeight < 1) minWeight = 1;\n            sortedRank = rankStart[minWeight];\n            HUFv07_fillDTableX4Level2(DTable+start, targetLog-nbBits, nbBits,\n                           rankValOrigin[nbBits], minWeight,\n                           sortedList+sortedRank, sortedListSize-sortedRank,\n                           nbBitsBaseline, symbol);\n        } else {\n            HUFv07_DEltX4 DElt;\n            MEM_writeLE16(&(DElt.sequence), symbol);\n            DElt.nbBits = (BYTE)(nbBits);\n            DElt.length = 1;\n            {   U32 u;\n                const U32 end = start + length;\n                for (u = start; u < end; u++) DTable[u] = DElt;\n        }   }\n        rankVal[weight] += length;\n    }\n}\n\nsize_t HUFv07_readDTableX4 (HUFv07_DTable* DTable, const void* src, size_t srcSize)\n{\n    BYTE weightList[HUFv07_SYMBOLVALUE_MAX + 1];\n    sortedSymbol_t sortedSymbol[HUFv07_SYMBOLVALUE_MAX + 1];\n    U32 rankStats[HUFv07_TABLELOG_ABSOLUTEMAX + 1] = { 0 };\n    U32 rankStart0[HUFv07_TABLELOG_ABSOLUTEMAX + 2] = { 0 };\n    U32* const rankStart = rankStart0+1;\n    rankVal_t rankVal;\n    U32 tableLog, maxW, sizeOfSort, nbSymbols;\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    U32 const maxTableLog = dtd.maxTableLog;\n    size_t iSize;\n    void* dtPtr = DTable+1;   /* force compiler to avoid strict-aliasing */\n    HUFv07_DEltX4* const dt = (HUFv07_DEltX4*)dtPtr;\n\n    HUFv07_STATIC_ASSERT(sizeof(HUFv07_DEltX4) == sizeof(HUFv07_DTable));   /* if compilation fails here, assertion is false */\n    if (maxTableLog > HUFv07_TABLELOG_ABSOLUTEMAX) return ERROR(tableLog_tooLarge);\n    /* memset(weightList, 0, sizeof(weightList)); */   /* is not necessary, even though some analyzer complain ... */\n\n    iSize = HUFv07_readStats(weightList, HUFv07_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize);\n    if (HUFv07_isError(iSize)) return iSize;\n\n    /* check result */\n    if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge);   /* DTable can't fit code depth */\n\n    /* find maxWeight */\n    for (maxW = tableLog; rankStats[maxW]==0; maxW--) {}  /* necessarily finds a solution before 0 */\n\n    /* Get start index of each weight */\n    {   U32 w, nextRankStart = 0;\n        for (w=1; w<maxW+1; w++) {\n            U32 current = nextRankStart;\n            nextRankStart += rankStats[w];\n            rankStart[w] = current;\n        }\n        rankStart[0] = nextRankStart;   /* put all 0w symbols at the end of sorted list*/\n        sizeOfSort = nextRankStart;\n    }\n\n    /* sort symbols by weight */\n    {   U32 s;\n        for (s=0; s<nbSymbols; s++) {\n            U32 const w = weightList[s];\n            U32 const r = rankStart[w]++;\n            sortedSymbol[r].symbol = (BYTE)s;\n            sortedSymbol[r].weight = (BYTE)w;\n        }\n        rankStart[0] = 0;   /* forget 0w symbols; this is beginning of weight(1) */\n    }\n\n    /* Build rankVal */\n    {   U32* const rankVal0 = rankVal[0];\n        {   int const rescale = (maxTableLog-tableLog) - 1;   /* tableLog <= maxTableLog */\n            U32 nextRankVal = 0;\n            U32 w;\n            for (w=1; w<maxW+1; w++) {\n                U32 current = nextRankVal;\n                nextRankVal += rankStats[w] << (w+rescale);\n                rankVal0[w] = current;\n        }   }\n        {   U32 const minBits = tableLog+1 - maxW;\n            U32 consumed;\n            for (consumed = minBits; consumed < maxTableLog - minBits + 1; consumed++) {\n                U32* const rankValPtr = rankVal[consumed];\n                U32 w;\n                for (w = 1; w < maxW+1; w++) {\n                    rankValPtr[w] = rankVal0[w] >> consumed;\n    }   }   }   }\n\n    HUFv07_fillDTableX4(dt, maxTableLog,\n                   sortedSymbol, sizeOfSort,\n                   rankStart0, rankVal, maxW,\n                   tableLog+1);\n\n    dtd.tableLog = (BYTE)maxTableLog;\n    dtd.tableType = 1;\n    memcpy(DTable, &dtd, sizeof(dtd));\n    return iSize;\n}\n\n\nstatic U32 HUFv07_decodeSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv07_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 2);\n    BITv07_skipBits(DStream, dt[val].nbBits);\n    return dt[val].length;\n}\n\nstatic U32 HUFv07_decodeLastSymbolX4(void* op, BITv07_DStream_t* DStream, const HUFv07_DEltX4* dt, const U32 dtLog)\n{\n    const size_t val = BITv07_lookBitsFast(DStream, dtLog);   /* note : dtLog >= 1 */\n    memcpy(op, dt+val, 1);\n    if (dt[val].length==1) BITv07_skipBits(DStream, dt[val].nbBits);\n    else {\n        if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {\n            BITv07_skipBits(DStream, dt[val].nbBits);\n            if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))\n                DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);   /* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */\n    }   }\n    return 1;\n}\n\n\n#define HUFv07_DECODE_SYMBOLX4_0(ptr, DStreamPtr) \\\n    ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv07_DECODE_SYMBOLX4_1(ptr, DStreamPtr) \\\n    if (MEM_64bits() || (HUFv07_TABLELOG_MAX<=12)) \\\n        ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\n#define HUFv07_DECODE_SYMBOLX4_2(ptr, DStreamPtr) \\\n    if (MEM_64bits()) \\\n        ptr += HUFv07_decodeSymbolX4(ptr, DStreamPtr, dt, dtLog)\n\nstatic inline size_t HUFv07_decodeStreamX4(BYTE* p, BITv07_DStream_t* bitDPtr, BYTE* const pEnd, const HUFv07_DEltX4* const dt, const U32 dtLog)\n{\n    BYTE* const pStart = p;\n\n    /* up to 8 symbols at a time */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p < pEnd-7)) {\n        HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX4_1(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX4_2(p, bitDPtr);\n        HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);\n    }\n\n    /* closer to end : up to 2 symbols at a time */\n    while ((BITv07_reloadDStream(bitDPtr) == BITv07_DStream_unfinished) && (p <= pEnd-2))\n        HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);\n\n    while (p <= pEnd-2)\n        HUFv07_DECODE_SYMBOLX4_0(p, bitDPtr);   /* no need to reload : reached the end of DStream */\n\n    if (p < pEnd)\n        p += HUFv07_decodeLastSymbolX4(p, bitDPtr, dt, dtLog);\n\n    return p-pStart;\n}\n\n\nstatic size_t HUFv07_decompress1X4_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    BITv07_DStream_t bitD;\n\n    /* Init */\n    {   size_t const errorCode = BITv07_initDStream(&bitD, cSrc, cSrcSize);\n        if (HUFv07_isError(errorCode)) return errorCode;\n    }\n\n    /* decode */\n    {   BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable+1;   /* force compiler to not use strict-aliasing */\n        const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;\n        DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n        HUFv07_decodeStreamX4(ostart, &bitD, oend, dt, dtd.tableLog);\n    }\n\n    /* check */\n    if (!BITv07_endOfDStream(&bitD)) return ERROR(corruption_detected);\n\n    /* decoded size */\n    return dstSize;\n}\n\nsize_t HUFv07_decompress1X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 1) return ERROR(GENERIC);\n    return HUFv07_decompress1X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\nsize_t HUFv07_decompress1X4_DCtx (HUFv07_DTable* DCtx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t const hSize = HUFv07_readDTableX4 (DCtx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress1X4_usingDTable_internal (dst, dstSize, ip, cSrcSize, DCtx);\n}\n\nsize_t HUFv07_decompress1X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress1X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\nstatic size_t HUFv07_decompress4X4_usingDTable_internal(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */\n\n    {   const BYTE* const istart = (const BYTE*) cSrc;\n        BYTE* const ostart = (BYTE*) dst;\n        BYTE* const oend = ostart + dstSize;\n        const void* const dtPtr = DTable+1;\n        const HUFv07_DEltX4* const dt = (const HUFv07_DEltX4*)dtPtr;\n\n        /* Init */\n        BITv07_DStream_t bitD1;\n        BITv07_DStream_t bitD2;\n        BITv07_DStream_t bitD3;\n        BITv07_DStream_t bitD4;\n        size_t const length1 = MEM_readLE16(istart);\n        size_t const length2 = MEM_readLE16(istart+2);\n        size_t const length3 = MEM_readLE16(istart+4);\n        size_t const length4 = cSrcSize - (length1 + length2 + length3 + 6);\n        const BYTE* const istart1 = istart + 6;  /* jumpTable */\n        const BYTE* const istart2 = istart1 + length1;\n        const BYTE* const istart3 = istart2 + length2;\n        const BYTE* const istart4 = istart3 + length3;\n        size_t const segmentSize = (dstSize+3) / 4;\n        BYTE* const opStart2 = ostart + segmentSize;\n        BYTE* const opStart3 = opStart2 + segmentSize;\n        BYTE* const opStart4 = opStart3 + segmentSize;\n        BYTE* op1 = ostart;\n        BYTE* op2 = opStart2;\n        BYTE* op3 = opStart3;\n        BYTE* op4 = opStart4;\n        U32 endSignal;\n        DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n        U32 const dtLog = dtd.tableLog;\n\n        if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */\n        { size_t const errorCode = BITv07_initDStream(&bitD1, istart1, length1);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD2, istart2, length2);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD3, istart3, length3);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n        { size_t const errorCode = BITv07_initDStream(&bitD4, istart4, length4);\n          if (HUFv07_isError(errorCode)) return errorCode; }\n\n        /* 16-32 symbols per loop (4-8 symbols per stream) */\n        endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        for ( ; (endSignal==BITv07_DStream_unfinished) && (op4<(oend-7)) ; ) {\n            HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX4_1(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_1(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_1(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_1(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX4_2(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_2(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_2(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_2(op4, &bitD4);\n            HUFv07_DECODE_SYMBOLX4_0(op1, &bitD1);\n            HUFv07_DECODE_SYMBOLX4_0(op2, &bitD2);\n            HUFv07_DECODE_SYMBOLX4_0(op3, &bitD3);\n            HUFv07_DECODE_SYMBOLX4_0(op4, &bitD4);\n\n            endSignal = BITv07_reloadDStream(&bitD1) | BITv07_reloadDStream(&bitD2) | BITv07_reloadDStream(&bitD3) | BITv07_reloadDStream(&bitD4);\n        }\n\n        /* check corruption */\n        if (op1 > opStart2) return ERROR(corruption_detected);\n        if (op2 > opStart3) return ERROR(corruption_detected);\n        if (op3 > opStart4) return ERROR(corruption_detected);\n        /* note : op4 supposed already verified within main loop */\n\n        /* finish bitStreams one by one */\n        HUFv07_decodeStreamX4(op1, &bitD1, opStart2, dt, dtLog);\n        HUFv07_decodeStreamX4(op2, &bitD2, opStart3, dt, dtLog);\n        HUFv07_decodeStreamX4(op3, &bitD3, opStart4, dt, dtLog);\n        HUFv07_decodeStreamX4(op4, &bitD4, oend,     dt, dtLog);\n\n        /* check */\n        { U32 const endCheck = BITv07_endOfDStream(&bitD1) & BITv07_endOfDStream(&bitD2) & BITv07_endOfDStream(&bitD3) & BITv07_endOfDStream(&bitD4);\n          if (!endCheck) return ERROR(corruption_detected); }\n\n        /* decoded size */\n        return dstSize;\n    }\n}\n\n\nsize_t HUFv07_decompress4X4_usingDTable(\n          void* dst,  size_t dstSize,\n    const void* cSrc, size_t cSrcSize,\n    const HUFv07_DTable* DTable)\n{\n    DTableDesc dtd = HUFv07_getDTableDesc(DTable);\n    if (dtd.tableType != 1) return ERROR(GENERIC);\n    return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, cSrc, cSrcSize, DTable);\n}\n\n\nsize_t HUFv07_decompress4X4_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    const BYTE* ip = (const BYTE*) cSrc;\n\n    size_t hSize = HUFv07_readDTableX4 (dctx, cSrc, cSrcSize);\n    if (HUFv07_isError(hSize)) return hSize;\n    if (hSize >= cSrcSize) return ERROR(srcSize_wrong);\n    ip += hSize; cSrcSize -= hSize;\n\n    return HUFv07_decompress4X4_usingDTable_internal(dst, dstSize, ip, cSrcSize, dctx);\n}\n\nsize_t HUFv07_decompress4X4 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    HUFv07_CREATE_STATIC_DTABLEX4(DTable, HUFv07_TABLELOG_MAX);\n    return HUFv07_decompress4X4_DCtx(DTable, dst, dstSize, cSrc, cSrcSize);\n}\n\n\n/* ********************************/\n/* Generic decompression selector */\n/* ********************************/\n\nsize_t HUFv07_decompress1X_usingDTable(void* dst, size_t maxDstSize,\n                                    const void* cSrc, size_t cSrcSize,\n                                    const HUFv07_DTable* DTable)\n{\n    DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n    return dtd.tableType ? HUFv07_decompress1X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :\n                           HUFv07_decompress1X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);\n}\n\nsize_t HUFv07_decompress4X_usingDTable(void* dst, size_t maxDstSize,\n                                    const void* cSrc, size_t cSrcSize,\n                                    const HUFv07_DTable* DTable)\n{\n    DTableDesc const dtd = HUFv07_getDTableDesc(DTable);\n    return dtd.tableType ? HUFv07_decompress4X4_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable) :\n                           HUFv07_decompress4X2_usingDTable_internal(dst, maxDstSize, cSrc, cSrcSize, DTable);\n}\n\n\ntypedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;\nstatic const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =\n{\n    /* single, double, quad */\n    {{0,0}, {1,1}, {2,2}},  /* Q==0 : impossible */\n    {{0,0}, {1,1}, {2,2}},  /* Q==1 : impossible */\n    {{  38,130}, {1313, 74}, {2151, 38}},   /* Q == 2 : 12-18% */\n    {{ 448,128}, {1353, 74}, {2238, 41}},   /* Q == 3 : 18-25% */\n    {{ 556,128}, {1353, 74}, {2238, 47}},   /* Q == 4 : 25-32% */\n    {{ 714,128}, {1418, 74}, {2436, 53}},   /* Q == 5 : 32-38% */\n    {{ 883,128}, {1437, 74}, {2464, 61}},   /* Q == 6 : 38-44% */\n    {{ 897,128}, {1515, 75}, {2622, 68}},   /* Q == 7 : 44-50% */\n    {{ 926,128}, {1613, 75}, {2730, 75}},   /* Q == 8 : 50-56% */\n    {{ 947,128}, {1729, 77}, {3359, 77}},   /* Q == 9 : 56-62% */\n    {{1107,128}, {2083, 81}, {4006, 84}},   /* Q ==10 : 62-69% */\n    {{1177,128}, {2379, 87}, {4785, 88}},   /* Q ==11 : 69-75% */\n    {{1242,128}, {2415, 93}, {5155, 84}},   /* Q ==12 : 75-81% */\n    {{1349,128}, {2644,106}, {5260,106}},   /* Q ==13 : 81-87% */\n    {{1455,128}, {2422,124}, {4174,124}},   /* Q ==14 : 87-93% */\n    {{ 722,128}, {1891,145}, {1936,146}},   /* Q ==15 : 93-99% */\n};\n\n/** HUFv07_selectDecoder() :\n*   Tells which decoder is likely to decode faster,\n*   based on a set of pre-determined metrics.\n*   @return : 0==HUFv07_decompress4X2, 1==HUFv07_decompress4X4 .\n*   Assumption : 0 < cSrcSize < dstSize <= 128 KB */\nU32 HUFv07_selectDecoder (size_t dstSize, size_t cSrcSize)\n{\n    /* decoder timing evaluation */\n    U32 const Q = (U32)(cSrcSize * 16 / dstSize);   /* Q < 16 since dstSize > cSrcSize */\n    U32 const D256 = (U32)(dstSize >> 8);\n    U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);\n    U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);\n    DTime1 += DTime1 >> 3;  /* advantage to algorithm using less memory, for cache eviction */\n\n    return DTime1 < DTime0;\n}\n\n\ntypedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize);\n\nsize_t HUFv07_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    static const decompressionAlgo decompress[2] = { HUFv07_decompress4X2, HUFv07_decompress4X4 };\n\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return decompress[algoNb](dst, dstSize, cSrc, cSrcSize);\n    }\n\n    /* return HUFv07_decompress4X2(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams single-symbol decoding */\n    /* return HUFv07_decompress4X4(dst, dstSize, cSrc, cSrcSize); */   /* multi-streams double-symbols decoding */\n}\n\nsize_t HUFv07_decompress4X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :\n                        HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;\n    }\n}\n\nsize_t HUFv07_decompress4X_hufOnly (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if ((cSrcSize >= dstSize) || (cSrcSize <= 1)) return ERROR(corruption_detected);   /* invalid */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return algoNb ? HUFv07_decompress4X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :\n                        HUFv07_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;\n    }\n}\n\nsize_t HUFv07_decompress1X_DCtx (HUFv07_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize)\n{\n    /* validation checks */\n    if (dstSize == 0) return ERROR(dstSize_tooSmall);\n    if (cSrcSize > dstSize) return ERROR(corruption_detected);   /* invalid */\n    if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; }   /* not compressed */\n    if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; }   /* RLE */\n\n    {   U32 const algoNb = HUFv07_selectDecoder(dstSize, cSrcSize);\n        return algoNb ? HUFv07_decompress1X4_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) :\n                        HUFv07_decompress1X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ;\n    }\n}\n/*\n    Common functions of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n\n/*-****************************************\n*  ZSTD Error Management\n******************************************/\n/*! ZSTDv07_isError() :\n*   tells if a return value is an error code */\nunsigned ZSTDv07_isError(size_t code) { return ERR_isError(code); }\n\n/*! ZSTDv07_getErrorName() :\n*   provides error code string from function result (useful for debugging) */\nconst char* ZSTDv07_getErrorName(size_t code) { return ERR_getErrorName(code); }\n\n\n\n/* **************************************************************\n*  ZBUFF Error Management\n****************************************************************/\nunsigned ZBUFFv07_isError(size_t errorCode) { return ERR_isError(errorCode); }\n\nconst char* ZBUFFv07_getErrorName(size_t errorCode) { return ERR_getErrorName(errorCode); }\n\n\n\nstatic void* ZSTDv07_defaultAllocFunction(void* opaque, size_t size)\n{\n    void* address = malloc(size);\n    (void)opaque;\n    /* printf(\"alloc %p, %d opaque=%p \\n\", address, (int)size, opaque); */\n    return address;\n}\n\nstatic void ZSTDv07_defaultFreeFunction(void* opaque, void* address)\n{\n    (void)opaque;\n    /* if (address) printf(\"free %p opaque=%p \\n\", address, opaque); */\n    free(address);\n}\n/*\n    zstd_internal - common functions to include\n    Header File for include\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://www.zstd.net\n*/\n#ifndef ZSTDv07_CCOMMON_H_MODULE\n#define ZSTDv07_CCOMMON_H_MODULE\n\n\n/*-*************************************\n*  Common macros\n***************************************/\n#define MIN(a,b) ((a)<(b) ? (a) : (b))\n#define MAX(a,b) ((a)>(b) ? (a) : (b))\n\n\n/*-*************************************\n*  Common constants\n***************************************/\n#define ZSTDv07_OPT_NUM    (1<<12)\n#define ZSTDv07_DICT_MAGIC  0xEC30A437   /* v0.7 */\n\n#define ZSTDv07_REP_NUM    3\n#define ZSTDv07_REP_INIT   ZSTDv07_REP_NUM\n#define ZSTDv07_REP_MOVE   (ZSTDv07_REP_NUM-1)\nstatic const U32 repStartValue[ZSTDv07_REP_NUM] = { 1, 4, 8 };\n\n#define KB *(1 <<10)\n#define MB *(1 <<20)\n#define GB *(1U<<30)\n\n#define BIT7 128\n#define BIT6  64\n#define BIT5  32\n#define BIT4  16\n#define BIT1   2\n#define BIT0   1\n\n#define ZSTDv07_WINDOWLOG_ABSOLUTEMIN 10\nstatic const size_t ZSTDv07_fcs_fieldSize[4] = { 0, 2, 4, 8 };\nstatic const size_t ZSTDv07_did_fieldSize[4] = { 0, 1, 2, 4 };\n\n#define ZSTDv07_BLOCKHEADERSIZE 3   /* C standard doesn't allow `static const` variable to be init using another `static const` variable */\nstatic const size_t ZSTDv07_blockHeaderSize = ZSTDv07_BLOCKHEADERSIZE;\ntypedef enum { bt_compressed, bt_raw, bt_rle, bt_end } blockType_t;\n\n#define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */\n#define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */ + MIN_SEQUENCES_SIZE /* nbSeq==0 */)   /* for a non-null block */\n\n#define ZSTD_HUFFDTABLE_CAPACITY_LOG 12\ntypedef enum { lbt_huffman, lbt_repeat, lbt_raw, lbt_rle } litBlockType_t;\n\n#define LONGNBSEQ 0x7F00\n\n#define MINMATCH 3\n#define EQUAL_READ32 4\n\n#define Litbits  8\n#define MaxLit ((1<<Litbits) - 1)\n#define MaxML  52\n#define MaxLL  35\n#define MaxOff 28\n#define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */\n#define MLFSELog    9\n#define LLFSELog    9\n#define OffFSELog   8\n\n#define FSEv07_ENCODING_RAW     0\n#define FSEv07_ENCODING_RLE     1\n#define FSEv07_ENCODING_STATIC  2\n#define FSEv07_ENCODING_DYNAMIC 3\n\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\n\nstatic const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 6, 7, 8, 9,10,11,12,\n                                     13,14,15,16 };\nstatic const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,\n                                             2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1,\n                                            -1,-1,-1,-1 };\nstatic const U32 LL_defaultNormLog = 6;\n\nstatic const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                                      1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 7, 8, 9,10,11,\n                                     12,13,14,15,16 };\nstatic const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,-1,-1,\n                                            -1,-1,-1,-1,-1 };\nstatic const U32 ML_defaultNormLog = 6;\n\nstatic const S16 OF_defaultNorm[MaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,\n                                              1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1 };\nstatic const U32 OF_defaultNormLog = 5;\n\n\n/*-*******************************************\n*  Shared functions to include for inlining\n*********************************************/\nstatic void ZSTDv07_copy8(void* dst, const void* src) { memcpy(dst, src, 8); }\n#define COPY8(d,s) { ZSTDv07_copy8(d,s); d+=8; s+=8; }\n\n/*! ZSTDv07_wildcopy() :\n*   custom version of memcpy(), can copy up to 7 bytes too many (8 bytes if length==0) */\n#define WILDCOPY_OVERLENGTH 8\nMEM_STATIC void ZSTDv07_wildcopy(void* dst, const void* src, ptrdiff_t length)\n{\n    const BYTE* ip = (const BYTE*)src;\n    BYTE* op = (BYTE*)dst;\n    BYTE* const oend = op + length;\n    do\n        COPY8(op, ip)\n    while (op < oend);\n}\n\n\n/*-*******************************************\n*  Private interfaces\n*********************************************/\ntypedef struct ZSTDv07_stats_s ZSTDv07_stats_t;\n\ntypedef struct {\n    U32 off;\n    U32 len;\n} ZSTDv07_match_t;\n\ntypedef struct {\n    U32 price;\n    U32 off;\n    U32 mlen;\n    U32 litlen;\n    U32 rep[ZSTDv07_REP_INIT];\n} ZSTDv07_optimal_t;\n\nstruct ZSTDv07_stats_s { U32 unused; };\n\ntypedef struct {\n    void* buffer;\n    U32*  offsetStart;\n    U32*  offset;\n    BYTE* offCodeStart;\n    BYTE* litStart;\n    BYTE* lit;\n    U16*  litLengthStart;\n    U16*  litLength;\n    BYTE* llCodeStart;\n    U16*  matchLengthStart;\n    U16*  matchLength;\n    BYTE* mlCodeStart;\n    U32   longLengthID;   /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */\n    U32   longLengthPos;\n    /* opt */\n    ZSTDv07_optimal_t* priceTable;\n    ZSTDv07_match_t* matchTable;\n    U32* matchLengthFreq;\n    U32* litLengthFreq;\n    U32* litFreq;\n    U32* offCodeFreq;\n    U32  matchLengthSum;\n    U32  matchSum;\n    U32  litLengthSum;\n    U32  litSum;\n    U32  offCodeSum;\n    U32  log2matchLengthSum;\n    U32  log2matchSum;\n    U32  log2litLengthSum;\n    U32  log2litSum;\n    U32  log2offCodeSum;\n    U32  factor;\n    U32  cachedPrice;\n    U32  cachedLitLength;\n    const BYTE* cachedLiterals;\n    ZSTDv07_stats_t stats;\n} SeqStore_t;\n\nvoid ZSTDv07_seqToCodes(const SeqStore_t* seqStorePtr, size_t const nbSeq);\n\n/* custom memory allocation functions */\nstatic const ZSTDv07_customMem defaultCustomMem = { ZSTDv07_defaultAllocFunction, ZSTDv07_defaultFreeFunction, NULL };\n\n#endif   /* ZSTDv07_CCOMMON_H_MODULE */\n/*\n    zstd - standard compression library\n    Copyright (C) 2014-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd\n*/\n\n/* ***************************************************************\n*  Tuning parameters\n*****************************************************************/\n/*!\n * HEAPMODE :\n * Select how default decompression function ZSTDv07_decompress() will allocate memory,\n * in memory stack (0), or in memory heap (1, requires malloc())\n */\n#ifndef ZSTDv07_HEAPMODE\n#  define ZSTDv07_HEAPMODE 1\n#endif\n\n\n/*-*******************************************************\n*  Compiler specifics\n*********************************************************/\n#ifdef _MSC_VER    /* Visual Studio */\n#  include <intrin.h>                    /* For Visual 2005 */\n#  pragma warning(disable : 4127)        /* disable: C4127: conditional expression is constant */\n#  pragma warning(disable : 4324)        /* disable: C4324: padded structure */\n#  pragma warning(disable : 4100)        /* disable: C4100: unreferenced formal parameter */\n#endif\n\n\n/*-*************************************\n*  Macros\n***************************************/\n#define ZSTDv07_isError ERR_isError   /* for inlining */\n#define FSEv07_isError  ERR_isError\n#define HUFv07_isError  ERR_isError\n\n\n/*_*******************************************************\n*  Memory operations\n**********************************************************/\nstatic void ZSTDv07_copy4(void* dst, const void* src) { memcpy(dst, src, 4); }\n\n\n/*-*************************************************************\n*   Context management\n***************************************************************/\ntypedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader,\n               ZSTDds_decodeBlockHeader, ZSTDds_decompressBlock,\n               ZSTDds_decodeSkippableHeader, ZSTDds_skipFrame } ZSTDv07_dStage;\n\nstruct ZSTDv07_DCtx_s\n{\n    FSEv07_DTable LLTable[FSEv07_DTABLE_SIZE_U32(LLFSELog)];\n    FSEv07_DTable OffTable[FSEv07_DTABLE_SIZE_U32(OffFSELog)];\n    FSEv07_DTable MLTable[FSEv07_DTABLE_SIZE_U32(MLFSELog)];\n    HUFv07_DTable hufTable[HUFv07_DTABLE_SIZE(ZSTD_HUFFDTABLE_CAPACITY_LOG)];  /* can accommodate HUFv07_decompress4X */\n    const void* previousDstEnd;\n    const void* base;\n    const void* vBase;\n    const void* dictEnd;\n    size_t expected;\n    U32 rep[3];\n    ZSTDv07_frameParams fParams;\n    blockType_t bType;   /* used in ZSTDv07_decompressContinue(), to transfer blockType between header decoding and block decoding stages */\n    ZSTDv07_dStage stage;\n    U32 litEntropy;\n    U32 fseEntropy;\n    XXH64_state_t xxhState;\n    size_t headerSize;\n    U32 dictID;\n    const BYTE* litPtr;\n    ZSTDv07_customMem customMem;\n    size_t litSize;\n    BYTE litBuffer[ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + WILDCOPY_OVERLENGTH];\n    BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];\n};  /* typedef'd to ZSTDv07_DCtx within \"zstd_static.h\" */\n\nint ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx);\n\nsize_t ZSTDv07_sizeofDCtx (const ZSTDv07_DCtx* dctx) { return sizeof(*dctx); }\n\nsize_t ZSTDv07_estimateDCtxSize(void) { return sizeof(ZSTDv07_DCtx); }\n\nsize_t ZSTDv07_decompressBegin(ZSTDv07_DCtx* dctx)\n{\n    dctx->expected = ZSTDv07_frameHeaderSize_min;\n    dctx->stage = ZSTDds_getFrameHeaderSize;\n    dctx->previousDstEnd = NULL;\n    dctx->base = NULL;\n    dctx->vBase = NULL;\n    dctx->dictEnd = NULL;\n    dctx->hufTable[0] = (HUFv07_DTable)((ZSTD_HUFFDTABLE_CAPACITY_LOG)*0x1000001);\n    dctx->litEntropy = dctx->fseEntropy = 0;\n    dctx->dictID = 0;\n    { int i; for (i=0; i<ZSTDv07_REP_NUM; i++) dctx->rep[i] = repStartValue[i]; }\n    return 0;\n}\n\nZSTDv07_DCtx* ZSTDv07_createDCtx_advanced(ZSTDv07_customMem customMem)\n{\n    ZSTDv07_DCtx* dctx;\n\n    if (!customMem.customAlloc && !customMem.customFree)\n        customMem = defaultCustomMem;\n\n    if (!customMem.customAlloc || !customMem.customFree)\n        return NULL;\n\n    dctx = (ZSTDv07_DCtx*) customMem.customAlloc(customMem.opaque, sizeof(ZSTDv07_DCtx));\n    if (!dctx) return NULL;\n    memcpy(&dctx->customMem, &customMem, sizeof(ZSTDv07_customMem));\n    ZSTDv07_decompressBegin(dctx);\n    return dctx;\n}\n\nZSTDv07_DCtx* ZSTDv07_createDCtx(void)\n{\n    return ZSTDv07_createDCtx_advanced(defaultCustomMem);\n}\n\nsize_t ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx)\n{\n    if (dctx==NULL) return 0;   /* support free on NULL */\n    dctx->customMem.customFree(dctx->customMem.opaque, dctx);\n    return 0;   /* reserved as a potential error code in the future */\n}\n\nvoid ZSTDv07_copyDCtx(ZSTDv07_DCtx* dstDCtx, const ZSTDv07_DCtx* srcDCtx)\n{\n    memcpy(dstDCtx, srcDCtx,\n           sizeof(ZSTDv07_DCtx) - (ZSTDv07_BLOCKSIZE_ABSOLUTEMAX+WILDCOPY_OVERLENGTH + ZSTDv07_frameHeaderSize_max));  /* no need to copy workspace */\n}\n\n\n/*-*************************************************************\n*   Decompression section\n***************************************************************/\n\n/* Frame format description\n   Frame Header -  [ Block Header - Block ] - Frame End\n   1) Frame Header\n      - 4 bytes - Magic Number : ZSTDv07_MAGICNUMBER (defined within zstd.h)\n      - 1 byte  - Frame Descriptor\n   2) Block Header\n      - 3 bytes, starting with a 2-bits descriptor\n                 Uncompressed, Compressed, Frame End, unused\n   3) Block\n      See Block Format Description\n   4) Frame End\n      - 3 bytes, compatible with Block Header\n*/\n\n\n/* Frame Header :\n\n   1 byte - FrameHeaderDescription :\n   bit 0-1 : dictID (0, 1, 2 or 4 bytes)\n   bit 2   : checksumFlag\n   bit 3   : reserved (must be zero)\n   bit 4   : reserved (unused, can be any value)\n   bit 5   : Single Segment (if 1, WindowLog byte is not present)\n   bit 6-7 : FrameContentFieldSize (0, 2, 4, or 8)\n             if (SkippedWindowLog && !FrameContentFieldsize) FrameContentFieldsize=1;\n\n   Optional : WindowLog (0 or 1 byte)\n   bit 0-2 : octal Fractional (1/8th)\n   bit 3-7 : Power of 2, with 0 = 1 KB (up to 2 TB)\n\n   Optional : dictID (0, 1, 2 or 4 bytes)\n   Automatic adaptation\n   0 : no dictID\n   1 : 1 - 255\n   2 : 256 - 65535\n   4 : all other values\n\n   Optional : content size (0, 1, 2, 4 or 8 bytes)\n   0 : unknown          (fcfs==0 and swl==0)\n   1 : 0-255 bytes      (fcfs==0 and swl==1)\n   2 : 256 - 65535+256  (fcfs==1)\n   4 : 0 - 4GB-1        (fcfs==2)\n   8 : 0 - 16EB-1       (fcfs==3)\n*/\n\n\n/* Compressed Block, format description\n\n   Block = Literal Section - Sequences Section\n   Prerequisite : size of (compressed) block, maximum size of regenerated data\n\n   1) Literal Section\n\n   1.1) Header : 1-5 bytes\n        flags: 2 bits\n            00 compressed by Huff0\n            01 unused\n            10 is Raw (uncompressed)\n            11 is Rle\n            Note : using 01 => Huff0 with precomputed table ?\n            Note : delta map ? => compressed ?\n\n   1.1.1) Huff0-compressed literal block : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n   1.1.2) Raw (uncompressed) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RAW<<6) + (0<<4) + size\n               12 bits: (IS_RAW<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RAW<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.3) Rle (repeated single byte) literal block header : 1-3 bytes\n        size :  5 bits: (IS_RLE<<6) + (0<<4) + size\n               12 bits: (IS_RLE<<6) + (2<<4) + (size>>8)\n                        size&255\n               20 bits: (IS_RLE<<6) + (3<<4) + (size>>16)\n                        size>>8&255\n                        size&255\n\n   1.1.4) Huff0-compressed literal block, using precomputed CTables : 3-5 bytes\n            srcSize < 1 KB => 3 bytes (2-2-10-10) => single stream\n            srcSize < 1 KB => 3 bytes (2-2-10-10)\n            srcSize < 16KB => 4 bytes (2-2-14-14)\n            else           => 5 bytes (2-2-18-18)\n            big endian convention\n\n        1- CTable available (stored into workspace ?)\n        2- Small input (fast heuristic ? Full comparison ? depend on clevel ?)\n\n\n   1.2) Literal block content\n\n   1.2.1) Huff0 block, using sizes from header\n        See Huff0 format\n\n   1.2.2) Huff0 block, using prepared table\n\n   1.2.3) Raw content\n\n   1.2.4) single byte\n\n\n   2) Sequences section\n      TO DO\n*/\n\n/** ZSTDv07_frameHeaderSize() :\n*   srcSize must be >= ZSTDv07_frameHeaderSize_min.\n*   @return : size of the Frame Header */\nstatic size_t ZSTDv07_frameHeaderSize(const void* src, size_t srcSize)\n{\n    if (srcSize < ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);\n    {   BYTE const fhd = ((const BYTE*)src)[4];\n        U32 const dictID= fhd & 3;\n        U32 const directMode = (fhd >> 5) & 1;\n        U32 const fcsId = fhd >> 6;\n        return ZSTDv07_frameHeaderSize_min + !directMode + ZSTDv07_did_fieldSize[dictID] + ZSTDv07_fcs_fieldSize[fcsId]\n                + (directMode && !ZSTDv07_fcs_fieldSize[fcsId]);\n    }\n}\n\n\n/** ZSTDv07_getFrameParams() :\n*   decode Frame Header, or require larger `srcSize`.\n*   @return : 0, `fparamsPtr` is correctly filled,\n*            >0, `srcSize` is too small, result is expected `srcSize`,\n*             or an error code, which can be tested using ZSTDv07_isError() */\nsize_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize < ZSTDv07_frameHeaderSize_min) return ZSTDv07_frameHeaderSize_min;\n    memset(fparamsPtr, 0, sizeof(*fparamsPtr));\n    if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {\n        if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {\n            if (srcSize < ZSTDv07_skippableHeaderSize) return ZSTDv07_skippableHeaderSize; /* magic number + skippable frame length */\n            fparamsPtr->frameContentSize = MEM_readLE32((const char *)src + 4);\n            fparamsPtr->windowSize = 0; /* windowSize==0 means a frame is skippable */\n            return 0;\n        }\n        return ERROR(prefix_unknown);\n    }\n\n    /* ensure there is enough `srcSize` to fully read/decode frame header */\n    { size_t const fhsize = ZSTDv07_frameHeaderSize(src, srcSize);\n      if (srcSize < fhsize) return fhsize; }\n\n    {   BYTE const fhdByte = ip[4];\n        size_t pos = 5;\n        U32 const dictIDSizeCode = fhdByte&3;\n        U32 const checksumFlag = (fhdByte>>2)&1;\n        U32 const directMode = (fhdByte>>5)&1;\n        U32 const fcsID = fhdByte>>6;\n        U32 const windowSizeMax = 1U << ZSTDv07_WINDOWLOG_MAX;\n        U32 windowSize = 0;\n        U32 dictID = 0;\n        U64 frameContentSize = 0;\n        if ((fhdByte & 0x08) != 0)   /* reserved bits, which must be zero */\n            return ERROR(frameParameter_unsupported);\n        if (!directMode) {\n            BYTE const wlByte = ip[pos++];\n            U32 const windowLog = (wlByte >> 3) + ZSTDv07_WINDOWLOG_ABSOLUTEMIN;\n            if (windowLog > ZSTDv07_WINDOWLOG_MAX)\n                return ERROR(frameParameter_unsupported);\n            windowSize = (1U << windowLog);\n            windowSize += (windowSize >> 3) * (wlByte&7);\n        }\n\n        switch(dictIDSizeCode)\n        {\n            default:   /* impossible */\n            case 0 : break;\n            case 1 : dictID = ip[pos]; pos++; break;\n            case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;\n            case 3 : dictID = MEM_readLE32(ip+pos); pos+=4; break;\n        }\n        switch(fcsID)\n        {\n            default:   /* impossible */\n            case 0 : if (directMode) frameContentSize = ip[pos]; break;\n            case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;\n            case 2 : frameContentSize = MEM_readLE32(ip+pos); break;\n            case 3 : frameContentSize = MEM_readLE64(ip+pos); break;\n        }\n        if (!windowSize) windowSize = (U32)frameContentSize;\n        if (windowSize > windowSizeMax)\n            return ERROR(frameParameter_unsupported);\n        fparamsPtr->frameContentSize = frameContentSize;\n        fparamsPtr->windowSize = windowSize;\n        fparamsPtr->dictID = dictID;\n        fparamsPtr->checksumFlag = checksumFlag;\n    }\n    return 0;\n}\n\n\n/** ZSTDv07_getDecompressedSize() :\n*   compatible with legacy mode\n*   @return : decompressed size if known, 0 otherwise\n              note : 0 can mean any of the following :\n                   - decompressed size is not provided within frame header\n                   - frame header unknown / not supported\n                   - frame header not completely provided (`srcSize` too small) */\nunsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize)\n{\n    ZSTDv07_frameParams fparams;\n    size_t const frResult = ZSTDv07_getFrameParams(&fparams, src, srcSize);\n    if (frResult!=0) return 0;\n    return fparams.frameContentSize;\n}\n\n\n/** ZSTDv07_decodeFrameHeader() :\n*   `srcSize` must be the size provided by ZSTDv07_frameHeaderSize().\n*   @return : 0 if success, or an error code, which can be tested using ZSTDv07_isError() */\nstatic size_t ZSTDv07_decodeFrameHeader(ZSTDv07_DCtx* dctx, const void* src, size_t srcSize)\n{\n    size_t const result = ZSTDv07_getFrameParams(&(dctx->fParams), src, srcSize);\n    if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong);\n    if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0);\n    return result;\n}\n\n\ntypedef struct\n{\n    blockType_t blockType;\n    U32 origSize;\n} blockProperties_t;\n\n/*! ZSTDv07_getcBlockSize() :\n*   Provides the size of compressed block from block header `src` */\nstatic size_t ZSTDv07_getcBlockSize(const void* src, size_t srcSize, blockProperties_t* bpPtr)\n{\n    const BYTE* const in = (const BYTE*)src;\n    U32 cSize;\n\n    if (srcSize < ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    bpPtr->blockType = (blockType_t)((*in) >> 6);\n    cSize = in[2] + (in[1]<<8) + ((in[0] & 7)<<16);\n    bpPtr->origSize = (bpPtr->blockType == bt_rle) ? cSize : 0;\n\n    if (bpPtr->blockType == bt_end) return 0;\n    if (bpPtr->blockType == bt_rle) return 1;\n    return cSize;\n}\n\n\nstatic size_t ZSTDv07_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    if (srcSize > dstCapacity) return ERROR(dstSize_tooSmall);\n    if (srcSize > 0) {\n        memcpy(dst, src, srcSize);\n    }\n    return srcSize;\n}\n\n\n/*! ZSTDv07_decodeLiteralsBlock() :\n    @return : nb of bytes read from src (< srcSize ) */\nstatic size_t ZSTDv07_decodeLiteralsBlock(ZSTDv07_DCtx* dctx,\n                          const void* src, size_t srcSize)   /* note : srcSize < BLOCKSIZE */\n{\n    const BYTE* const istart = (const BYTE*) src;\n\n    if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected);\n\n    switch((litBlockType_t)(istart[0]>> 6))\n    {\n    case lbt_huffman:\n        {   size_t litSize, litCSize, singleStream=0;\n            U32 lhSize = (istart[0] >> 4) & 3;\n            if (srcSize < 5) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for lhSize, + cSize (+nbSeq) */\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                /* 2 - 2 - 10 - 10 */\n                lhSize=3;\n                singleStream = istart[0] & 16;\n                litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n                litCSize = ((istart[1] &  3) << 8) + istart[2];\n                break;\n            case 2:\n                /* 2 - 2 - 14 - 14 */\n                lhSize=4;\n                litSize  = ((istart[0] & 15) << 10) + (istart[1] << 2) + (istart[2] >> 6);\n                litCSize = ((istart[2] & 63) <<  8) + istart[3];\n                break;\n            case 3:\n                /* 2 - 2 - 18 - 18 */\n                lhSize=5;\n                litSize  = ((istart[0] & 15) << 14) + (istart[1] << 6) + (istart[2] >> 2);\n                litCSize = ((istart[2] &  3) << 16) + (istart[3] << 8) + istart[4];\n                break;\n            }\n            if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            if (HUFv07_isError(singleStream ?\n                            HUFv07_decompress1X2_DCtx(dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) :\n                            HUFv07_decompress4X_hufOnly (dctx->hufTable, dctx->litBuffer, litSize, istart+lhSize, litCSize) ))\n                return ERROR(corruption_detected);\n\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            dctx->litEntropy = 1;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case lbt_repeat:\n        {   size_t litSize, litCSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            if (lhSize != 1)  /* only case supported for now : small litSize, single stream */\n                return ERROR(corruption_detected);\n            if (dctx->litEntropy==0)\n                return ERROR(dictionary_corrupted);\n\n            /* 2 - 2 - 10 - 10 */\n            lhSize=3;\n            litSize  = ((istart[0] & 15) << 6) + (istart[1] >> 2);\n            litCSize = ((istart[1] &  3) << 8) + istart[2];\n            if (litCSize + lhSize > srcSize) return ERROR(corruption_detected);\n\n            {   size_t const errorCode = HUFv07_decompress1X4_usingDTable(dctx->litBuffer, litSize, istart+lhSize, litCSize, dctx->hufTable);\n                if (HUFv07_isError(errorCode)) return ERROR(corruption_detected);\n            }\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n            return litCSize + lhSize;\n        }\n    case lbt_raw:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize=1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                break;\n            }\n\n            if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) {  /* risk reading beyond src buffer with wildcopy */\n                if (litSize+lhSize > srcSize) return ERROR(corruption_detected);\n                memcpy(dctx->litBuffer, istart+lhSize, litSize);\n                dctx->litPtr = dctx->litBuffer;\n                dctx->litSize = litSize;\n                memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);\n                return lhSize+litSize;\n            }\n            /* direct reference into compressed stream */\n            dctx->litPtr = istart+lhSize;\n            dctx->litSize = litSize;\n            return lhSize+litSize;\n        }\n    case lbt_rle:\n        {   size_t litSize;\n            U32 lhSize = ((istart[0]) >> 4) & 3;\n            switch(lhSize)\n            {\n            case 0: case 1: default:   /* note : default is impossible, since lhSize into [0..3] */\n                lhSize = 1;\n                litSize = istart[0] & 31;\n                break;\n            case 2:\n                litSize = ((istart[0] & 15) << 8) + istart[1];\n                break;\n            case 3:\n                litSize = ((istart[0] & 15) << 16) + (istart[1] << 8) + istart[2];\n                if (srcSize<4) return ERROR(corruption_detected);   /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4 */\n                break;\n            }\n            if (litSize > ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(corruption_detected);\n            memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);\n            dctx->litPtr = dctx->litBuffer;\n            dctx->litSize = litSize;\n            return lhSize+1;\n        }\n    default:\n        return ERROR(corruption_detected);   /* impossible */\n    }\n}\n\n\n/*! ZSTDv07_buildSeqTable() :\n    @return : nb bytes read from src,\n              or an error code if it fails, testable with ZSTDv07_isError()\n*/\nstatic size_t ZSTDv07_buildSeqTable(FSEv07_DTable* DTable, U32 type, U32 max, U32 maxLog,\n                                 const void* src, size_t srcSize,\n                                 const S16* defaultNorm, U32 defaultLog, U32 flagRepeatTable)\n{\n    switch(type)\n    {\n    case FSEv07_ENCODING_RLE :\n        if (!srcSize) return ERROR(srcSize_wrong);\n        if ( (*(const BYTE*)src) > max) return ERROR(corruption_detected);\n        FSEv07_buildDTable_rle(DTable, *(const BYTE*)src);   /* if *src > max, data is corrupted */\n        return 1;\n    case FSEv07_ENCODING_RAW :\n        FSEv07_buildDTable(DTable, defaultNorm, max, defaultLog);\n        return 0;\n    case FSEv07_ENCODING_STATIC:\n        if (!flagRepeatTable) return ERROR(corruption_detected);\n        return 0;\n    default :   /* impossible */\n    case FSEv07_ENCODING_DYNAMIC :\n        {   U32 tableLog;\n            S16 norm[MaxSeq+1];\n            size_t const headerSize = FSEv07_readNCount(norm, &max, &tableLog, src, srcSize);\n            if (FSEv07_isError(headerSize)) return ERROR(corruption_detected);\n            if (tableLog > maxLog) return ERROR(corruption_detected);\n            FSEv07_buildDTable(DTable, norm, max, tableLog);\n            return headerSize;\n    }   }\n}\n\n\nstatic size_t ZSTDv07_decodeSeqHeaders(int* nbSeqPtr,\n                             FSEv07_DTable* DTableLL, FSEv07_DTable* DTableML, FSEv07_DTable* DTableOffb, U32 flagRepeatTable,\n                             const void* src, size_t srcSize)\n{\n    const BYTE* const istart = (const BYTE*)src;\n    const BYTE* const iend = istart + srcSize;\n    const BYTE* ip = istart;\n\n    /* check */\n    if (srcSize < MIN_SEQUENCES_SIZE) return ERROR(srcSize_wrong);\n\n    /* SeqHead */\n    {   int nbSeq = *ip++;\n        if (!nbSeq) { *nbSeqPtr=0; return 1; }\n        if (nbSeq > 0x7F) {\n            if (nbSeq == 0xFF) {\n                if (ip+2 > iend) return ERROR(srcSize_wrong);\n                nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2;\n            } else {\n                if (ip >= iend) return ERROR(srcSize_wrong);\n                nbSeq = ((nbSeq-0x80)<<8) + *ip++;\n            }\n        }\n        *nbSeqPtr = nbSeq;\n    }\n\n    /* FSE table descriptors */\n    if (ip + 4 > iend) return ERROR(srcSize_wrong); /* min : header byte + all 3 are \"raw\", hence no header, but at least xxLog bits per type */\n    {   U32 const LLtype  = *ip >> 6;\n        U32 const OFtype = (*ip >> 4) & 3;\n        U32 const MLtype  = (*ip >> 2) & 3;\n        ip++;\n\n        /* Build DTables */\n        {   size_t const llhSize = ZSTDv07_buildSeqTable(DTableLL, LLtype, MaxLL, LLFSELog, ip, iend-ip, LL_defaultNorm, LL_defaultNormLog, flagRepeatTable);\n            if (ZSTDv07_isError(llhSize)) return ERROR(corruption_detected);\n            ip += llhSize;\n        }\n        {   size_t const ofhSize = ZSTDv07_buildSeqTable(DTableOffb, OFtype, MaxOff, OffFSELog, ip, iend-ip, OF_defaultNorm, OF_defaultNormLog, flagRepeatTable);\n            if (ZSTDv07_isError(ofhSize)) return ERROR(corruption_detected);\n            ip += ofhSize;\n        }\n        {   size_t const mlhSize = ZSTDv07_buildSeqTable(DTableML, MLtype, MaxML, MLFSELog, ip, iend-ip, ML_defaultNorm, ML_defaultNormLog, flagRepeatTable);\n            if (ZSTDv07_isError(mlhSize)) return ERROR(corruption_detected);\n            ip += mlhSize;\n    }   }\n\n    return ip-istart;\n}\n\n\ntypedef struct {\n    size_t litLength;\n    size_t matchLength;\n    size_t offset;\n} seq_t;\n\ntypedef struct {\n    BITv07_DStream_t DStream;\n    FSEv07_DState_t stateLL;\n    FSEv07_DState_t stateOffb;\n    FSEv07_DState_t stateML;\n    size_t prevOffset[ZSTDv07_REP_INIT];\n} seqState_t;\n\n\nstatic seq_t ZSTDv07_decodeSequence(seqState_t* seqState)\n{\n    seq_t seq;\n\n    U32 const llCode = FSEv07_peekSymbol(&(seqState->stateLL));\n    U32 const mlCode = FSEv07_peekSymbol(&(seqState->stateML));\n    U32 const ofCode = FSEv07_peekSymbol(&(seqState->stateOffb));   /* <= maxOff, by table construction */\n\n    U32 const llBits = LL_bits[llCode];\n    U32 const mlBits = ML_bits[mlCode];\n    U32 const ofBits = ofCode;\n    U32 const totalBits = llBits+mlBits+ofBits;\n\n    static const U32 LL_base[MaxLL+1] = {\n                             0,  1,  2,  3,  4,  5,  6,  7,  8,  9,   10,    11,    12,    13,    14,     15,\n                            16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000,\n                            0x2000, 0x4000, 0x8000, 0x10000 };\n\n    static const U32 ML_base[MaxML+1] = {\n                             3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,   14,    15,    16,    17,    18,\n                            19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,   30,    31,    32,    33,    34,\n                            35, 37, 39, 41, 43, 47, 51, 59, 67, 83, 99, 0x83, 0x103, 0x203, 0x403, 0x803,\n                            0x1003, 0x2003, 0x4003, 0x8003, 0x10003 };\n\n    static const U32 OF_base[MaxOff+1] = {\n                 0,        1,       1,       5,     0xD,     0x1D,     0x3D,     0x7D,\n                 0xFD,   0x1FD,   0x3FD,   0x7FD,   0xFFD,   0x1FFD,   0x3FFD,   0x7FFD,\n                 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,\n                 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD };\n\n    /* sequence */\n    {   size_t offset;\n        if (!ofCode)\n            offset = 0;\n        else {\n            offset = OF_base[ofCode] + BITv07_readBits(&(seqState->DStream), ofBits);   /* <=  (ZSTDv07_WINDOWLOG_MAX-1) bits */\n            if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));\n        }\n\n        if (ofCode <= 1) {\n            if ((llCode == 0) & (offset <= 1)) offset = 1-offset;\n            if (offset) {\n                size_t const temp = seqState->prevOffset[offset];\n                if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];\n                seqState->prevOffset[1] = seqState->prevOffset[0];\n                seqState->prevOffset[0] = offset = temp;\n            } else {\n                offset = seqState->prevOffset[0];\n            }\n        } else {\n            seqState->prevOffset[2] = seqState->prevOffset[1];\n            seqState->prevOffset[1] = seqState->prevOffset[0];\n            seqState->prevOffset[0] = offset;\n        }\n        seq.offset = offset;\n    }\n\n    seq.matchLength = ML_base[mlCode] + ((mlCode>31) ? BITv07_readBits(&(seqState->DStream), mlBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() && (mlBits+llBits>24)) BITv07_reloadDStream(&(seqState->DStream));\n\n    seq.litLength = LL_base[llCode] + ((llCode>15) ? BITv07_readBits(&(seqState->DStream), llBits) : 0);   /* <=  16 bits */\n    if (MEM_32bits() ||\n       (totalBits > 64 - 7 - (LLFSELog+MLFSELog+OffFSELog)) ) BITv07_reloadDStream(&(seqState->DStream));\n\n    /* ANS state update */\n    FSEv07_updateState(&(seqState->stateLL), &(seqState->DStream));   /* <=  9 bits */\n    FSEv07_updateState(&(seqState->stateML), &(seqState->DStream));   /* <=  9 bits */\n    if (MEM_32bits()) BITv07_reloadDStream(&(seqState->DStream));     /* <= 18 bits */\n    FSEv07_updateState(&(seqState->stateOffb), &(seqState->DStream)); /* <=  8 bits */\n\n    return seq;\n}\n\n\nstatic\nsize_t ZSTDv07_execSequence(BYTE* op,\n                                BYTE* const oend, seq_t sequence,\n                                const BYTE** litPtr, const BYTE* const litLimit,\n                                const BYTE* const base, const BYTE* const vBase, const BYTE* const dictEnd)\n{\n    BYTE* const oLitEnd = op + sequence.litLength;\n    size_t const sequenceLength = sequence.litLength + sequence.matchLength;\n    BYTE* const oMatchEnd = op + sequenceLength;   /* risk : address space overflow (32-bits) */\n    BYTE* const oend_w = oend-WILDCOPY_OVERLENGTH;\n    const BYTE* const iLitEnd = *litPtr + sequence.litLength;\n    const BYTE* match = oLitEnd - sequence.offset;\n\n    /* check */\n    assert(oend >= op);\n    if (sequence.litLength + WILDCOPY_OVERLENGTH > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    if (sequenceLength > (size_t)(oend - op)) return ERROR(dstSize_tooSmall);\n    assert(litLimit >= *litPtr);\n    if (sequence.litLength > (size_t)(litLimit - *litPtr)) return ERROR(corruption_detected);;\n\n    /* copy Literals */\n    ZSTDv07_wildcopy(op, *litPtr, (ptrdiff_t)sequence.litLength);   /* note : since oLitEnd <= oend-WILDCOPY_OVERLENGTH, no risk of overwrite beyond oend */\n    op = oLitEnd;\n    *litPtr = iLitEnd;   /* update for next sequence */\n\n    /* copy Match */\n    if (sequence.offset > (size_t)(oLitEnd - base)) {\n        /* offset beyond prefix */\n        if (sequence.offset > (size_t)(oLitEnd - vBase)) return ERROR(corruption_detected);\n        match = dictEnd - (base-match);\n        if (match + sequence.matchLength <= dictEnd) {\n            memmove(oLitEnd, match, sequence.matchLength);\n            return sequenceLength;\n        }\n        /* span extDict & currentPrefixSegment */\n        {   size_t const length1 = (size_t)(dictEnd - match);\n            memmove(oLitEnd, match, length1);\n            op = oLitEnd + length1;\n            sequence.matchLength -= length1;\n            match = base;\n            if (op > oend_w || sequence.matchLength < MINMATCH) {\n              while (op < oMatchEnd) *op++ = *match++;\n              return sequenceLength;\n            }\n    }   }\n    /* Requirement: op <= oend_w */\n\n    /* match within prefix */\n    if (sequence.offset < 8) {\n        /* close range match, overlap */\n        static const U32 dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };   /* added */\n        static const int dec64table[] = { 8, 8, 8, 7, 8, 9,10,11 };   /* subtracted */\n        int const sub2 = dec64table[sequence.offset];\n        op[0] = match[0];\n        op[1] = match[1];\n        op[2] = match[2];\n        op[3] = match[3];\n        match += dec32table[sequence.offset];\n        ZSTDv07_copy4(op+4, match);\n        match -= sub2;\n    } else {\n        ZSTDv07_copy8(op, match);\n    }\n    op += 8; match += 8;\n\n    if (oMatchEnd > oend-(16-MINMATCH)) {\n        if (op < oend_w) {\n            ZSTDv07_wildcopy(op, match, oend_w - op);\n            match += oend_w - op;\n            op = oend_w;\n        }\n        while (op < oMatchEnd) *op++ = *match++;\n    } else {\n        ZSTDv07_wildcopy(op, match, (ptrdiff_t)sequence.matchLength-8);   /* works even if matchLength < 8 */\n    }\n    return sequenceLength;\n}\n\n\nstatic size_t ZSTDv07_decompressSequences(\n                               ZSTDv07_DCtx* dctx,\n                               void* dst, size_t maxDstSize,\n                         const void* seqStart, size_t seqSize)\n{\n    const BYTE* ip = (const BYTE*)seqStart;\n    const BYTE* const iend = ip + seqSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + maxDstSize;\n    BYTE* op = ostart;\n    const BYTE* litPtr = dctx->litPtr;\n    const BYTE* const litEnd = litPtr + dctx->litSize;\n    FSEv07_DTable* DTableLL = dctx->LLTable;\n    FSEv07_DTable* DTableML = dctx->MLTable;\n    FSEv07_DTable* DTableOffb = dctx->OffTable;\n    const BYTE* const base = (const BYTE*) (dctx->base);\n    const BYTE* const vBase = (const BYTE*) (dctx->vBase);\n    const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);\n    int nbSeq;\n\n    /* Build Decoding Tables */\n    {   size_t const seqHSize = ZSTDv07_decodeSeqHeaders(&nbSeq, DTableLL, DTableML, DTableOffb, dctx->fseEntropy, ip, seqSize);\n        if (ZSTDv07_isError(seqHSize)) return seqHSize;\n        ip += seqHSize;\n    }\n\n    /* Regen sequences */\n    if (nbSeq) {\n        seqState_t seqState;\n        dctx->fseEntropy = 1;\n        { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) seqState.prevOffset[i] = dctx->rep[i]; }\n        { size_t const errorCode = BITv07_initDStream(&(seqState.DStream), ip, iend-ip);\n          if (ERR_isError(errorCode)) return ERROR(corruption_detected); }\n        FSEv07_initDState(&(seqState.stateLL), &(seqState.DStream), DTableLL);\n        FSEv07_initDState(&(seqState.stateOffb), &(seqState.DStream), DTableOffb);\n        FSEv07_initDState(&(seqState.stateML), &(seqState.DStream), DTableML);\n\n        for ( ; (BITv07_reloadDStream(&(seqState.DStream)) <= BITv07_DStream_completed) && nbSeq ; ) {\n            nbSeq--;\n            {   seq_t const sequence = ZSTDv07_decodeSequence(&seqState);\n                size_t const oneSeqSize = ZSTDv07_execSequence(op, oend, sequence, &litPtr, litEnd, base, vBase, dictEnd);\n                if (ZSTDv07_isError(oneSeqSize)) return oneSeqSize;\n                op += oneSeqSize;\n        }   }\n\n        /* check if reached exact end */\n        if (nbSeq) return ERROR(corruption_detected);\n        /* save reps for next block */\n        { U32 i; for (i=0; i<ZSTDv07_REP_INIT; i++) dctx->rep[i] = (U32)(seqState.prevOffset[i]); }\n    }\n\n    /* last literal segment */\n    {   size_t const lastLLSize = litEnd - litPtr;\n        /* if (litPtr > litEnd) return ERROR(corruption_detected); */   /* too many literals already used */\n        if (lastLLSize > (size_t)(oend-op)) return ERROR(dstSize_tooSmall);\n        if (lastLLSize > 0) {\n            memcpy(op, litPtr, lastLLSize);\n            op += lastLLSize;\n        }\n    }\n\n    return op-ostart;\n}\n\n\nstatic void ZSTDv07_checkContinuity(ZSTDv07_DCtx* dctx, const void* dst)\n{\n    if (dst != dctx->previousDstEnd) {   /* not contiguous */\n        dctx->dictEnd = dctx->previousDstEnd;\n        dctx->vBase = (const char*)dst - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n        dctx->base = dst;\n        dctx->previousDstEnd = dst;\n    }\n}\n\n\nstatic size_t ZSTDv07_decompressBlock_internal(ZSTDv07_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{   /* blockType == blockCompressed */\n    const BYTE* ip = (const BYTE*)src;\n\n    if (srcSize >= ZSTDv07_BLOCKSIZE_ABSOLUTEMAX) return ERROR(srcSize_wrong);\n\n    /* Decode literals sub-block */\n    {   size_t const litCSize = ZSTDv07_decodeLiteralsBlock(dctx, src, srcSize);\n        if (ZSTDv07_isError(litCSize)) return litCSize;\n        ip += litCSize;\n        srcSize -= litCSize;\n    }\n    return ZSTDv07_decompressSequences(dctx, dst, dstCapacity, ip, srcSize);\n}\n\n\nsize_t ZSTDv07_decompressBlock(ZSTDv07_DCtx* dctx,\n                            void* dst, size_t dstCapacity,\n                      const void* src, size_t srcSize)\n{\n    size_t dSize;\n    ZSTDv07_checkContinuity(dctx, dst);\n    dSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n    dctx->previousDstEnd = (char*)dst + dSize;\n    return dSize;\n}\n\n\n/** ZSTDv07_insertBlock() :\n    insert `src` block into `dctx` history. Useful to track uncompressed blocks. */\nZSTDLIBv07_API size_t ZSTDv07_insertBlock(ZSTDv07_DCtx* dctx, const void* blockStart, size_t blockSize)\n{\n    ZSTDv07_checkContinuity(dctx, blockStart);\n    dctx->previousDstEnd = (const char*)blockStart + blockSize;\n    return blockSize;\n}\n\n\nstatic size_t ZSTDv07_generateNxBytes(void* dst, size_t dstCapacity, BYTE byte, size_t length)\n{\n    if (length > dstCapacity) return ERROR(dstSize_tooSmall);\n    if (length > 0) {\n        memset(dst, byte, length);\n    }\n    return length;\n}\n\n\n/*! ZSTDv07_decompressFrame() :\n*   `dctx` must be properly initialized */\nstatic size_t ZSTDv07_decompressFrame(ZSTDv07_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize)\n{\n    const BYTE* ip = (const BYTE*)src;\n    const BYTE* const iend = ip + srcSize;\n    BYTE* const ostart = (BYTE*)dst;\n    BYTE* const oend = ostart + dstCapacity;\n    BYTE* op = ostart;\n    size_t remainingSize = srcSize;\n\n    /* check */\n    if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);\n        if (ZSTDv07_isError(frameHeaderSize)) return frameHeaderSize;\n        if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) return ERROR(srcSize_wrong);\n        if (ZSTDv07_decodeFrameHeader(dctx, src, frameHeaderSize)) return ERROR(corruption_detected);\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        size_t decodedSize;\n        blockProperties_t blockProperties;\n        size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, iend-ip, &blockProperties);\n        if (ZSTDv07_isError(cBlockSize)) return cBlockSize;\n\n        ip += ZSTDv07_blockHeaderSize;\n        remainingSize -= ZSTDv07_blockHeaderSize;\n        if (cBlockSize > remainingSize) return ERROR(srcSize_wrong);\n\n        switch(blockProperties.blockType)\n        {\n        case bt_compressed:\n            decodedSize = ZSTDv07_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize);\n            break;\n        case bt_raw :\n            decodedSize = ZSTDv07_copyRawBlock(op, oend-op, ip, cBlockSize);\n            break;\n        case bt_rle :\n            decodedSize = ZSTDv07_generateNxBytes(op, oend-op, *ip, blockProperties.origSize);\n            break;\n        case bt_end :\n            /* end of frame */\n            if (remainingSize) return ERROR(srcSize_wrong);\n            decodedSize = 0;\n            break;\n        default:\n            return ERROR(GENERIC);   /* impossible */\n        }\n        if (blockProperties.blockType == bt_end) break;   /* bt_end */\n\n        if (ZSTDv07_isError(decodedSize)) return decodedSize;\n        if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize);\n        op += decodedSize;\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n    }\n\n    return op-ostart;\n}\n\n\n/*! ZSTDv07_decompress_usingPreparedDCtx() :\n*   Same as ZSTDv07_decompress_usingDict, but using a reference context `preparedDCtx`, where dictionary has been loaded.\n*   It avoids reloading the dictionary each time.\n*   `preparedDCtx` must have been properly initialized using ZSTDv07_decompressBegin_usingDict().\n*   Requires 2 contexts : 1 for reference (preparedDCtx), which will not be modified, and 1 to run the decompression operation (dctx) */\nstatic size_t ZSTDv07_decompress_usingPreparedDCtx(ZSTDv07_DCtx* dctx, const ZSTDv07_DCtx* refDCtx,\n                                         void* dst, size_t dstCapacity,\n                                   const void* src, size_t srcSize)\n{\n    ZSTDv07_copyDCtx(dctx, refDCtx);\n    ZSTDv07_checkContinuity(dctx, dst);\n    return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,\n                                 void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize,\n                                 const void* dict, size_t dictSize)\n{\n    ZSTDv07_decompressBegin_usingDict(dctx, dict, dictSize);\n    ZSTDv07_checkContinuity(dctx, dst);\n    return ZSTDv07_decompressFrame(dctx, dst, dstCapacity, src, srcSize);\n}\n\n\nsize_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    return ZSTDv07_decompress_usingDict(dctx, dst, dstCapacity, src, srcSize, NULL, 0);\n}\n\n\nsize_t ZSTDv07_decompress(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n#if defined(ZSTDv07_HEAPMODE) && (ZSTDv07_HEAPMODE==1)\n    size_t regenSize;\n    ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx();\n    if (dctx==NULL) return ERROR(memory_allocation);\n    regenSize = ZSTDv07_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);\n    ZSTDv07_freeDCtx(dctx);\n    return regenSize;\n#else   /* stack mode */\n    ZSTDv07_DCtx dctx;\n    return ZSTDv07_decompressDCtx(&dctx, dst, dstCapacity, src, srcSize);\n#endif\n}\n\n/* ZSTD_errorFrameSizeInfoLegacy() :\n   assumes `cSize` and `dBound` are _not_ NULL */\nstatic void ZSTD_errorFrameSizeInfoLegacy(size_t* cSize, unsigned long long* dBound, size_t ret)\n{\n    *cSize = ret;\n    *dBound = ZSTD_CONTENTSIZE_ERROR;\n}\n\nvoid ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize, size_t* cSize, unsigned long long* dBound)\n{\n    const BYTE* ip = (const BYTE*)src;\n    size_t remainingSize = srcSize;\n    size_t nbBlocks = 0;\n\n    /* check */\n    if (srcSize < ZSTDv07_frameHeaderSize_min+ZSTDv07_blockHeaderSize) {\n        ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n        return;\n    }\n\n    /* Frame Header */\n    {   size_t const frameHeaderSize = ZSTDv07_frameHeaderSize(src, srcSize);\n        if (ZSTDv07_isError(frameHeaderSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, frameHeaderSize);\n            return;\n        }\n        if (MEM_readLE32(src) != ZSTDv07_MAGICNUMBER) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(prefix_unknown));\n            return;\n        }\n        if (srcSize < frameHeaderSize+ZSTDv07_blockHeaderSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n        ip += frameHeaderSize; remainingSize -= frameHeaderSize;\n    }\n\n    /* Loop on each block */\n    while (1) {\n        blockProperties_t blockProperties;\n        size_t const cBlockSize = ZSTDv07_getcBlockSize(ip, remainingSize, &blockProperties);\n        if (ZSTDv07_isError(cBlockSize)) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, cBlockSize);\n            return;\n        }\n\n        ip += ZSTDv07_blockHeaderSize;\n        remainingSize -= ZSTDv07_blockHeaderSize;\n\n        if (blockProperties.blockType == bt_end) break;\n\n        if (cBlockSize > remainingSize) {\n            ZSTD_errorFrameSizeInfoLegacy(cSize, dBound, ERROR(srcSize_wrong));\n            return;\n        }\n\n        ip += cBlockSize;\n        remainingSize -= cBlockSize;\n        nbBlocks++;\n    }\n\n    *cSize = ip - (const BYTE*)src;\n    *dBound = nbBlocks * ZSTDv07_BLOCKSIZE_ABSOLUTEMAX;\n}\n\n/*_******************************\n*  Streaming Decompression API\n********************************/\nsize_t ZSTDv07_nextSrcSizeToDecompress(ZSTDv07_DCtx* dctx)\n{\n    return dctx->expected;\n}\n\nint ZSTDv07_isSkipFrame(ZSTDv07_DCtx* dctx)\n{\n    return dctx->stage == ZSTDds_skipFrame;\n}\n\n/** ZSTDv07_decompressContinue() :\n*   @return : nb of bytes generated into `dst` (necessarily <= `dstCapacity)\n*             or an error code, which can be tested using ZSTDv07_isError() */\nsize_t ZSTDv07_decompressContinue(ZSTDv07_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    /* Sanity check */\n    if (srcSize != dctx->expected) return ERROR(srcSize_wrong);\n    if (dstCapacity) ZSTDv07_checkContinuity(dctx, dst);\n\n    switch (dctx->stage)\n    {\n    case ZSTDds_getFrameHeaderSize :\n        if (srcSize != ZSTDv07_frameHeaderSize_min) return ERROR(srcSize_wrong);   /* impossible */\n        if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTDv07_MAGIC_SKIPPABLE_START) {\n            memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);\n            dctx->expected = ZSTDv07_skippableHeaderSize - ZSTDv07_frameHeaderSize_min; /* magic number + skippable frame length */\n            dctx->stage = ZSTDds_decodeSkippableHeader;\n            return 0;\n        }\n        dctx->headerSize = ZSTDv07_frameHeaderSize(src, ZSTDv07_frameHeaderSize_min);\n        if (ZSTDv07_isError(dctx->headerSize)) return dctx->headerSize;\n        memcpy(dctx->headerBuffer, src, ZSTDv07_frameHeaderSize_min);\n        if (dctx->headerSize > ZSTDv07_frameHeaderSize_min) {\n            dctx->expected = dctx->headerSize - ZSTDv07_frameHeaderSize_min;\n            dctx->stage = ZSTDds_decodeFrameHeader;\n            return 0;\n        }\n        dctx->expected = 0;   /* not necessary to copy more */\n\t/* fall-through */\n    case ZSTDds_decodeFrameHeader:\n        {   size_t result;\n            memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);\n            result = ZSTDv07_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize);\n            if (ZSTDv07_isError(result)) return result;\n            dctx->expected = ZSTDv07_blockHeaderSize;\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            return 0;\n        }\n    case ZSTDds_decodeBlockHeader:\n        {   blockProperties_t bp;\n            size_t const cBlockSize = ZSTDv07_getcBlockSize(src, ZSTDv07_blockHeaderSize, &bp);\n            if (ZSTDv07_isError(cBlockSize)) return cBlockSize;\n            if (bp.blockType == bt_end) {\n                if (dctx->fParams.checksumFlag) {\n                    U64 const h64 = XXH64_digest(&dctx->xxhState);\n                    U32 const h32 = (U32)(h64>>11) & ((1<<22)-1);\n                    const BYTE* const ip = (const BYTE*)src;\n                    U32 const check32 = ip[2] + (ip[1] << 8) + ((ip[0] & 0x3F) << 16);\n                    if (check32 != h32) return ERROR(checksum_wrong);\n                }\n                dctx->expected = 0;\n                dctx->stage = ZSTDds_getFrameHeaderSize;\n            } else {\n                dctx->expected = cBlockSize;\n                dctx->bType = bp.blockType;\n                dctx->stage = ZSTDds_decompressBlock;\n            }\n            return 0;\n        }\n    case ZSTDds_decompressBlock:\n        {   size_t rSize;\n            switch(dctx->bType)\n            {\n            case bt_compressed:\n                rSize = ZSTDv07_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize);\n                break;\n            case bt_raw :\n                rSize = ZSTDv07_copyRawBlock(dst, dstCapacity, src, srcSize);\n                break;\n            case bt_rle :\n                return ERROR(GENERIC);   /* not yet handled */\n                break;\n            case bt_end :   /* should never happen (filtered at phase 1) */\n                rSize = 0;\n                break;\n            default:\n                return ERROR(GENERIC);   /* impossible */\n            }\n            dctx->stage = ZSTDds_decodeBlockHeader;\n            dctx->expected = ZSTDv07_blockHeaderSize;\n            if (ZSTDv07_isError(rSize)) return rSize;\n            dctx->previousDstEnd = (char*)dst + rSize;\n            if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize);\n            return rSize;\n        }\n    case ZSTDds_decodeSkippableHeader:\n        {   memcpy(dctx->headerBuffer + ZSTDv07_frameHeaderSize_min, src, dctx->expected);\n            dctx->expected = MEM_readLE32(dctx->headerBuffer + 4);\n            dctx->stage = ZSTDds_skipFrame;\n            return 0;\n        }\n    case ZSTDds_skipFrame:\n        {   dctx->expected = 0;\n            dctx->stage = ZSTDds_getFrameHeaderSize;\n            return 0;\n        }\n    default:\n        return ERROR(GENERIC);   /* impossible */\n    }\n}\n\n\nstatic size_t ZSTDv07_refDictContent(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    dctx->dictEnd = dctx->previousDstEnd;\n    dctx->vBase = (const char*)dict - ((const char*)(dctx->previousDstEnd) - (const char*)(dctx->base));\n    dctx->base = dict;\n    dctx->previousDstEnd = (const char*)dict + dictSize;\n    return 0;\n}\n\nstatic size_t ZSTDv07_loadEntropy(ZSTDv07_DCtx* dctx, const void* const dict, size_t const dictSize)\n{\n    const BYTE* dictPtr = (const BYTE*)dict;\n    const BYTE* const dictEnd = dictPtr + dictSize;\n\n    {   size_t const hSize = HUFv07_readDTableX4(dctx->hufTable, dict, dictSize);\n        if (HUFv07_isError(hSize)) return ERROR(dictionary_corrupted);\n        dictPtr += hSize;\n    }\n\n    {   short offcodeNCount[MaxOff+1];\n        U32 offcodeMaxValue=MaxOff, offcodeLog;\n        size_t const offcodeHeaderSize = FSEv07_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr);\n        if (FSEv07_isError(offcodeHeaderSize)) return ERROR(dictionary_corrupted);\n        if (offcodeLog > OffFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv07_buildDTable(dctx->OffTable, offcodeNCount, offcodeMaxValue, offcodeLog);\n          if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dictPtr += offcodeHeaderSize;\n    }\n\n    {   short matchlengthNCount[MaxML+1];\n        unsigned matchlengthMaxValue = MaxML, matchlengthLog;\n        size_t const matchlengthHeaderSize = FSEv07_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr);\n        if (FSEv07_isError(matchlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (matchlengthLog > MLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv07_buildDTable(dctx->MLTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog);\n          if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dictPtr += matchlengthHeaderSize;\n    }\n\n    {   short litlengthNCount[MaxLL+1];\n        unsigned litlengthMaxValue = MaxLL, litlengthLog;\n        size_t const litlengthHeaderSize = FSEv07_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr);\n        if (FSEv07_isError(litlengthHeaderSize)) return ERROR(dictionary_corrupted);\n        if (litlengthLog > LLFSELog) return ERROR(dictionary_corrupted);\n        { size_t const errorCode = FSEv07_buildDTable(dctx->LLTable, litlengthNCount, litlengthMaxValue, litlengthLog);\n          if (FSEv07_isError(errorCode)) return ERROR(dictionary_corrupted); }\n        dictPtr += litlengthHeaderSize;\n    }\n\n    if (dictPtr+12 > dictEnd) return ERROR(dictionary_corrupted);\n    dctx->rep[0] = MEM_readLE32(dictPtr+0); if (dctx->rep[0] == 0 || dctx->rep[0] >= dictSize) return ERROR(dictionary_corrupted);\n    dctx->rep[1] = MEM_readLE32(dictPtr+4); if (dctx->rep[1] == 0 || dctx->rep[1] >= dictSize) return ERROR(dictionary_corrupted);\n    dctx->rep[2] = MEM_readLE32(dictPtr+8); if (dctx->rep[2] == 0 || dctx->rep[2] >= dictSize) return ERROR(dictionary_corrupted);\n    dictPtr += 12;\n\n    dctx->litEntropy = dctx->fseEntropy = 1;\n    return dictPtr - (const BYTE*)dict;\n}\n\nstatic size_t ZSTDv07_decompress_insertDictionary(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    if (dictSize < 8) return ZSTDv07_refDictContent(dctx, dict, dictSize);\n    {   U32 const magic = MEM_readLE32(dict);\n        if (magic != ZSTDv07_DICT_MAGIC) {\n            return ZSTDv07_refDictContent(dctx, dict, dictSize);   /* pure content mode */\n    }   }\n    dctx->dictID = MEM_readLE32((const char*)dict + 4);\n\n    /* load entropy tables */\n    dict = (const char*)dict + 8;\n    dictSize -= 8;\n    {   size_t const eSize = ZSTDv07_loadEntropy(dctx, dict, dictSize);\n        if (ZSTDv07_isError(eSize)) return ERROR(dictionary_corrupted);\n        dict = (const char*)dict + eSize;\n        dictSize -= eSize;\n    }\n\n    /* reference dictionary content */\n    return ZSTDv07_refDictContent(dctx, dict, dictSize);\n}\n\n\nsize_t ZSTDv07_decompressBegin_usingDict(ZSTDv07_DCtx* dctx, const void* dict, size_t dictSize)\n{\n    { size_t const errorCode = ZSTDv07_decompressBegin(dctx);\n      if (ZSTDv07_isError(errorCode)) return errorCode; }\n\n    if (dict && dictSize) {\n        size_t const errorCode = ZSTDv07_decompress_insertDictionary(dctx, dict, dictSize);\n        if (ZSTDv07_isError(errorCode)) return ERROR(dictionary_corrupted);\n    }\n\n    return 0;\n}\n\n\nstruct ZSTDv07_DDict_s {\n    void* dict;\n    size_t dictSize;\n    ZSTDv07_DCtx* refContext;\n};  /* typedef'd tp ZSTDv07_CDict within zstd.h */\n\nstatic ZSTDv07_DDict* ZSTDv07_createDDict_advanced(const void* dict, size_t dictSize, ZSTDv07_customMem customMem)\n{\n    if (!customMem.customAlloc && !customMem.customFree)\n        customMem = defaultCustomMem;\n\n    if (!customMem.customAlloc || !customMem.customFree)\n        return NULL;\n\n    {   ZSTDv07_DDict* const ddict = (ZSTDv07_DDict*) customMem.customAlloc(customMem.opaque, sizeof(*ddict));\n        void* const dictContent = customMem.customAlloc(customMem.opaque, dictSize);\n        ZSTDv07_DCtx* const dctx = ZSTDv07_createDCtx_advanced(customMem);\n\n        if (!dictContent || !ddict || !dctx) {\n            customMem.customFree(customMem.opaque, dictContent);\n            customMem.customFree(customMem.opaque, ddict);\n            customMem.customFree(customMem.opaque, dctx);\n            return NULL;\n        }\n\n        memcpy(dictContent, dict, dictSize);\n        {   size_t const errorCode = ZSTDv07_decompressBegin_usingDict(dctx, dictContent, dictSize);\n            if (ZSTDv07_isError(errorCode)) {\n                customMem.customFree(customMem.opaque, dictContent);\n                customMem.customFree(customMem.opaque, ddict);\n                customMem.customFree(customMem.opaque, dctx);\n                return NULL;\n        }   }\n\n        ddict->dict = dictContent;\n        ddict->dictSize = dictSize;\n        ddict->refContext = dctx;\n        return ddict;\n    }\n}\n\n/*! ZSTDv07_createDDict() :\n*   Create a digested dictionary, ready to start decompression without startup delay.\n*   `dict` can be released after `ZSTDv07_DDict` creation */\nZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize)\n{\n    ZSTDv07_customMem const allocator = { NULL, NULL, NULL };\n    return ZSTDv07_createDDict_advanced(dict, dictSize, allocator);\n}\n\nsize_t ZSTDv07_freeDDict(ZSTDv07_DDict* ddict)\n{\n    ZSTDv07_freeFunction const cFree = ddict->refContext->customMem.customFree;\n    void* const opaque = ddict->refContext->customMem.opaque;\n    ZSTDv07_freeDCtx(ddict->refContext);\n    cFree(opaque, ddict->dict);\n    cFree(opaque, ddict);\n    return 0;\n}\n\n/*! ZSTDv07_decompress_usingDDict() :\n*   Decompression using a pre-digested Dictionary\n*   Use dictionary without significant overhead. */\nZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,\n                                           void* dst, size_t dstCapacity,\n                                     const void* src, size_t srcSize,\n                                     const ZSTDv07_DDict* ddict)\n{\n    return ZSTDv07_decompress_usingPreparedDCtx(dctx, ddict->refContext,\n                                           dst, dstCapacity,\n                                           src, srcSize);\n}\n/*\n    Buffered version of Zstd compression library\n    Copyright (C) 2015-2016, Yann Collet.\n\n    BSD 2-Clause License (https://opensource.org/licenses/bsd-license.php)\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions are\n    met:\n    * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above\n    copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the\n    distribution.\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n    \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n    You can contact the author at :\n    - zstd homepage : https://facebook.github.io/zstd/\n*/\n\n\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv07_DCtx object is required to track streaming operations.\n*  Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources.\n*  Use ZBUFFv07_decompressInit() to start a new decompression operation,\n*   or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv07_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv07_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of @dst will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change @dst.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv07_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize()\n*  output : ZBUFFv07_recommendedDOutSize==128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv07_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\ntypedef enum { ZBUFFds_init, ZBUFFds_loadHeader,\n               ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFFv07_dStage;\n\n/* *** Resource management *** */\nstruct ZBUFFv07_DCtx_s {\n    ZSTDv07_DCtx* zd;\n    ZSTDv07_frameParams fParams;\n    ZBUFFv07_dStage stage;\n    char*  inBuff;\n    size_t inBuffSize;\n    size_t inPos;\n    char*  outBuff;\n    size_t outBuffSize;\n    size_t outStart;\n    size_t outEnd;\n    size_t blockSize;\n    BYTE headerBuffer[ZSTDv07_FRAMEHEADERSIZE_MAX];\n    size_t lhSize;\n    ZSTDv07_customMem customMem;\n};   /* typedef'd to ZBUFFv07_DCtx within \"zstd_buffered.h\" */\n\nZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem);\n\nZBUFFv07_DCtx* ZBUFFv07_createDCtx(void)\n{\n    return ZBUFFv07_createDCtx_advanced(defaultCustomMem);\n}\n\nZBUFFv07_DCtx* ZBUFFv07_createDCtx_advanced(ZSTDv07_customMem customMem)\n{\n    ZBUFFv07_DCtx* zbd;\n\n    if (!customMem.customAlloc && !customMem.customFree)\n        customMem = defaultCustomMem;\n\n    if (!customMem.customAlloc || !customMem.customFree)\n        return NULL;\n\n    zbd = (ZBUFFv07_DCtx*)customMem.customAlloc(customMem.opaque, sizeof(ZBUFFv07_DCtx));\n    if (zbd==NULL) return NULL;\n    memset(zbd, 0, sizeof(ZBUFFv07_DCtx));\n    memcpy(&zbd->customMem, &customMem, sizeof(ZSTDv07_customMem));\n    zbd->zd = ZSTDv07_createDCtx_advanced(customMem);\n    if (zbd->zd == NULL) { ZBUFFv07_freeDCtx(zbd); return NULL; }\n    zbd->stage = ZBUFFds_init;\n    return zbd;\n}\n\nsize_t ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* zbd)\n{\n    if (zbd==NULL) return 0;   /* support free on null */\n    ZSTDv07_freeDCtx(zbd->zd);\n    if (zbd->inBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);\n    if (zbd->outBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);\n    zbd->customMem.customFree(zbd->customMem.opaque, zbd);\n    return 0;\n}\n\n\n/* *** Initialization *** */\n\nsize_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* zbd, const void* dict, size_t dictSize)\n{\n    zbd->stage = ZBUFFds_loadHeader;\n    zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;\n    return ZSTDv07_decompressBegin_usingDict(zbd->zd, dict, dictSize);\n}\n\nsize_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* zbd)\n{\n    return ZBUFFv07_decompressInitDictionary(zbd, NULL, 0);\n}\n\n\n/* internal util function */\nMEM_STATIC size_t ZBUFFv07_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)\n{\n    size_t const length = MIN(dstCapacity, srcSize);\n    if (length > 0) {\n        memcpy(dst, src, length);\n    }\n    return length;\n}\n\n\n/* *** Decompression *** */\n\nsize_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* zbd,\n                                void* dst, size_t* dstCapacityPtr,\n                          const void* src, size_t* srcSizePtr)\n{\n    const char* const istart = (const char*)src;\n    const char* const iend = istart + *srcSizePtr;\n    const char* ip = istart;\n    char* const ostart = (char*)dst;\n    char* const oend = ostart + *dstCapacityPtr;\n    char* op = ostart;\n    U32 notDone = 1;\n\n    while (notDone) {\n        switch(zbd->stage)\n        {\n        case ZBUFFds_init :\n            return ERROR(init_missing);\n\n        case ZBUFFds_loadHeader :\n            {   size_t const hSize = ZSTDv07_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);\n                if (ZSTDv07_isError(hSize)) return hSize;\n                if (hSize != 0) {\n                    size_t const toLoad = hSize - zbd->lhSize;   /* if hSize!=0, hSize > zbd->lhSize */\n                    if (toLoad > (size_t)(iend-ip)) {   /* not enough input to load full header */\n                        if (ip != NULL)\n                            memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);\n                        zbd->lhSize += iend-ip;\n                        *dstCapacityPtr = 0;\n                        return (hSize - zbd->lhSize) + ZSTDv07_blockHeaderSize;   /* remaining header bytes + next block header */\n                    }\n                    memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;\n                    break;\n            }   }\n\n            /* Consume header */\n            {   size_t const h1Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);  /* == ZSTDv07_frameHeaderSize_min */\n                size_t const h1Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);\n                if (ZSTDv07_isError(h1Result)) return h1Result;\n                if (h1Size < zbd->lhSize) {   /* long header */\n                    size_t const h2Size = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n                    size_t const h2Result = ZSTDv07_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);\n                    if (ZSTDv07_isError(h2Result)) return h2Result;\n            }   }\n\n            zbd->fParams.windowSize = MAX(zbd->fParams.windowSize, 1U << ZSTDv07_WINDOWLOG_ABSOLUTEMIN);\n\n            /* Frame header instruct buffer sizes */\n            {   size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTDv07_BLOCKSIZE_ABSOLUTEMAX);\n                zbd->blockSize = blockSize;\n                if (zbd->inBuffSize < blockSize) {\n                    zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);\n                    zbd->inBuffSize = blockSize;\n                    zbd->inBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, blockSize);\n                    if (zbd->inBuff == NULL) return ERROR(memory_allocation);\n                }\n                {   size_t const neededOutSize = zbd->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;\n                    if (zbd->outBuffSize < neededOutSize) {\n                        zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);\n                        zbd->outBuffSize = neededOutSize;\n                        zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize);\n                        if (zbd->outBuff == NULL) return ERROR(memory_allocation);\n            }   }   }\n            zbd->stage = ZBUFFds_read;\n            /* pass-through */\n\t    /* fall-through */\n        case ZBUFFds_read:\n            {   size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n                if (neededInSize==0) {  /* end of frame */\n                    zbd->stage = ZBUFFds_init;\n                    notDone = 0;\n                    break;\n                }\n                if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */\n                    const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);\n                    size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, (isSkipFrame ? 0 : zbd->outBuffSize - zbd->outStart),\n                        ip, neededInSize);\n                    if (ZSTDv07_isError(decodedSize)) return decodedSize;\n                    ip += neededInSize;\n                    if (!decodedSize && !isSkipFrame) break;   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    break;\n                }\n                if (ip==iend) { notDone = 0; break; }   /* no more input */\n                zbd->stage = ZBUFFds_load;\n            }\n\t    /* fall-through */\n        case ZBUFFds_load:\n            {   size_t const neededInSize = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n                size_t const toLoad = neededInSize - zbd->inPos;   /* should always be <= remaining space within inBuff */\n                size_t loadedSize;\n                if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected);   /* should never happen */\n                loadedSize = ZBUFFv07_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);\n                ip += loadedSize;\n                zbd->inPos += loadedSize;\n                if (loadedSize < toLoad) { notDone = 0; break; }   /* not enough input, wait for more */\n\n                /* decode loaded input */\n                {  const int isSkipFrame = ZSTDv07_isSkipFrame(zbd->zd);\n                   size_t const decodedSize = ZSTDv07_decompressContinue(zbd->zd,\n                        zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,\n                        zbd->inBuff, neededInSize);\n                    if (ZSTDv07_isError(decodedSize)) return decodedSize;\n                    zbd->inPos = 0;   /* input is consumed */\n                    if (!decodedSize && !isSkipFrame) { zbd->stage = ZBUFFds_read; break; }   /* this was just a header */\n                    zbd->outEnd = zbd->outStart +  decodedSize;\n                    zbd->stage = ZBUFFds_flush;\n                    /* break; */\n                    /* pass-through */\n                }\n\t    }\n\t    /* fall-through */\n        case ZBUFFds_flush:\n            {   size_t const toFlushSize = zbd->outEnd - zbd->outStart;\n                size_t const flushedSize = ZBUFFv07_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);\n                op += flushedSize;\n                zbd->outStart += flushedSize;\n                if (flushedSize == toFlushSize) {\n                    zbd->stage = ZBUFFds_read;\n                    if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)\n                        zbd->outStart = zbd->outEnd = 0;\n                    break;\n                }\n                /* cannot flush everything */\n                notDone = 0;\n                break;\n            }\n        default: return ERROR(GENERIC);   /* impossible */\n    }   }\n\n    /* result */\n    *srcSizePtr = ip-istart;\n    *dstCapacityPtr = op-ostart;\n    {   size_t nextSrcSizeHint = ZSTDv07_nextSrcSizeToDecompress(zbd->zd);\n        nextSrcSizeHint -= zbd->inPos;   /* already loaded*/\n        return nextSrcSizeHint;\n    }\n}\n\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nsize_t ZBUFFv07_recommendedDInSize(void)  { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX + ZSTDv07_blockHeaderSize /* block header size*/ ; }\nsize_t ZBUFFv07_recommendedDOutSize(void) { return ZSTDv07_BLOCKSIZE_ABSOLUTEMAX; }\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/legacy/zstd_v07.h",
    "content": "﻿/*\n * Copyright (c) Yann Collet, Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTDv07_H_235446\n#define ZSTDv07_H_235446\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/*======  Dependency  ======*/\n#include <stddef.h>   /* size_t */\n\n\n/*======  Export for Windows  ======*/\n/*!\n*  ZSTDv07_DLL_EXPORT :\n*  Enable exporting of functions when building a Windows DLL\n*/\n#if defined(_WIN32) && defined(ZSTDv07_DLL_EXPORT) && (ZSTDv07_DLL_EXPORT==1)\n#  define ZSTDLIBv07_API __declspec(dllexport)\n#else\n#  define ZSTDLIBv07_API\n#endif\n\n\n/* *************************************\n*  Simple API\n***************************************/\n/*! ZSTDv07_getDecompressedSize() :\n*   @return : decompressed size if known, 0 otherwise.\n       note 1 : if `0`, follow up with ZSTDv07_getFrameParams() to know precise failure cause.\n       note 2 : decompressed size could be wrong or intentionally modified !\n                always ensure results fit within application's authorized limits */\nunsigned long long ZSTDv07_getDecompressedSize(const void* src, size_t srcSize);\n\n/*! ZSTDv07_decompress() :\n    `compressedSize` : must be _exact_ size of compressed input, otherwise decompression will fail.\n    `dstCapacity` must be equal or larger than originalSize.\n    @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n              or an errorCode if it fails (which can be tested using ZSTDv07_isError()) */\nZSTDLIBv07_API size_t ZSTDv07_decompress( void* dst, size_t dstCapacity,\n                                    const void* src, size_t compressedSize);\n\n/**\nZSTDv07_findFrameSizeInfoLegacy() : get the source length and decompressed bound of a ZSTD frame compliant with v0.7.x format\n    srcSize : The size of the 'src' buffer, at least as large as the frame pointed to by 'src'\n    cSize (output parameter)  : the number of bytes that would be read to decompress this frame\n                                or an error code if it fails (which can be tested using ZSTDv01_isError())\n    dBound (output parameter) : an upper-bound for the decompressed size of the data in the frame\n                                or ZSTD_CONTENTSIZE_ERROR if an error occurs\n\n    note : assumes `cSize` and `dBound` are _not_ NULL.\n*/\nvoid ZSTDv07_findFrameSizeInfoLegacy(const void *src, size_t srcSize,\n                                     size_t* cSize, unsigned long long* dBound);\n\n/*======  Helper functions  ======*/\nZSTDLIBv07_API unsigned    ZSTDv07_isError(size_t code);          /*!< tells if a `size_t` function result is an error code */\nZSTDLIBv07_API const char* ZSTDv07_getErrorName(size_t code);     /*!< provides readable string from an error code */\n\n\n/*-*************************************\n*  Explicit memory management\n***************************************/\n/** Decompression context */\ntypedef struct ZSTDv07_DCtx_s ZSTDv07_DCtx;\nZSTDLIBv07_API ZSTDv07_DCtx* ZSTDv07_createDCtx(void);\nZSTDLIBv07_API size_t     ZSTDv07_freeDCtx(ZSTDv07_DCtx* dctx);      /*!< @return : errorCode */\n\n/** ZSTDv07_decompressDCtx() :\n*   Same as ZSTDv07_decompress(), requires an allocated ZSTDv07_DCtx (see ZSTDv07_createDCtx()) */\nZSTDLIBv07_API size_t ZSTDv07_decompressDCtx(ZSTDv07_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n\n/*-************************\n*  Simple dictionary API\n***************************/\n/*! ZSTDv07_decompress_usingDict() :\n*   Decompression using a pre-defined Dictionary content (see dictBuilder).\n*   Dictionary must be identical to the one used during compression.\n*   Note : This function load the dictionary, resulting in a significant startup time */\nZSTDLIBv07_API size_t ZSTDv07_decompress_usingDict(ZSTDv07_DCtx* dctx,\n                                                   void* dst, size_t dstCapacity,\n                                             const void* src, size_t srcSize,\n                                             const void* dict,size_t dictSize);\n\n\n/*-**************************\n*  Advanced Dictionary API\n****************************/\n/*! ZSTDv07_createDDict() :\n*   Create a digested dictionary, ready to start decompression operation without startup delay.\n*   `dict` can be released after creation */\ntypedef struct ZSTDv07_DDict_s ZSTDv07_DDict;\nZSTDLIBv07_API ZSTDv07_DDict* ZSTDv07_createDDict(const void* dict, size_t dictSize);\nZSTDLIBv07_API size_t      ZSTDv07_freeDDict(ZSTDv07_DDict* ddict);\n\n/*! ZSTDv07_decompress_usingDDict() :\n*   Decompression using a pre-digested Dictionary\n*   Faster startup than ZSTDv07_decompress_usingDict(), recommended when same dictionary is used multiple times. */\nZSTDLIBv07_API size_t ZSTDv07_decompress_usingDDict(ZSTDv07_DCtx* dctx,\n                                                    void* dst, size_t dstCapacity,\n                                              const void* src, size_t srcSize,\n                                              const ZSTDv07_DDict* ddict);\n\ntypedef struct {\n    unsigned long long frameContentSize;\n    unsigned windowSize;\n    unsigned dictID;\n    unsigned checksumFlag;\n} ZSTDv07_frameParams;\n\nZSTDLIBv07_API size_t ZSTDv07_getFrameParams(ZSTDv07_frameParams* fparamsPtr, const void* src, size_t srcSize);   /**< doesn't consume input */\n\n\n\n\n/* *************************************\n*  Streaming functions\n***************************************/\ntypedef struct ZBUFFv07_DCtx_s ZBUFFv07_DCtx;\nZSTDLIBv07_API ZBUFFv07_DCtx* ZBUFFv07_createDCtx(void);\nZSTDLIBv07_API size_t      ZBUFFv07_freeDCtx(ZBUFFv07_DCtx* dctx);\n\nZSTDLIBv07_API size_t ZBUFFv07_decompressInit(ZBUFFv07_DCtx* dctx);\nZSTDLIBv07_API size_t ZBUFFv07_decompressInitDictionary(ZBUFFv07_DCtx* dctx, const void* dict, size_t dictSize);\n\nZSTDLIBv07_API size_t ZBUFFv07_decompressContinue(ZBUFFv07_DCtx* dctx,\n                                            void* dst, size_t* dstCapacityPtr,\n                                      const void* src, size_t* srcSizePtr);\n\n/*-***************************************************************************\n*  Streaming decompression howto\n*\n*  A ZBUFFv07_DCtx object is required to track streaming operations.\n*  Use ZBUFFv07_createDCtx() and ZBUFFv07_freeDCtx() to create/release resources.\n*  Use ZBUFFv07_decompressInit() to start a new decompression operation,\n*   or ZBUFFv07_decompressInitDictionary() if decompression requires a dictionary.\n*  Note that ZBUFFv07_DCtx objects can be re-init multiple times.\n*\n*  Use ZBUFFv07_decompressContinue() repetitively to consume your input.\n*  *srcSizePtr and *dstCapacityPtr can be any size.\n*  The function will report how many bytes were read or written by modifying *srcSizePtr and *dstCapacityPtr.\n*  Note that it may not consume the entire input, in which case it's up to the caller to present remaining input again.\n*  The content of `dst` will be overwritten (up to *dstCapacityPtr) at each function call, so save its content if it matters, or change `dst`.\n*  @return : a hint to preferred nb of bytes to use as input for next function call (it's only a hint, to help latency),\n*            or 0 when a frame is completely decoded,\n*            or an error code, which can be tested using ZBUFFv07_isError().\n*\n*  Hint : recommended buffer sizes (not compulsory) : ZBUFFv07_recommendedDInSize() and ZBUFFv07_recommendedDOutSize()\n*  output : ZBUFFv07_recommendedDOutSize== 128 KB block size is the internal unit, it ensures it's always possible to write a full block when decoded.\n*  input  : ZBUFFv07_recommendedDInSize == 128KB + 3;\n*           just follow indications from ZBUFFv07_decompressContinue() to minimize latency. It should always be <= 128 KB + 3 .\n* *******************************************************************************/\n\n\n/* *************************************\n*  Tool functions\n***************************************/\nZSTDLIBv07_API unsigned ZBUFFv07_isError(size_t errorCode);\nZSTDLIBv07_API const char* ZBUFFv07_getErrorName(size_t errorCode);\n\n/** Functions below provide recommended buffer sizes for Compression or Decompression operations.\n*   These sizes are just hints, they tend to offer better latency */\nZSTDLIBv07_API size_t ZBUFFv07_recommendedDInSize(void);\nZSTDLIBv07_API size_t ZBUFFv07_recommendedDOutSize(void);\n\n\n/*-*************************************\n*  Constants\n***************************************/\n#define ZSTDv07_MAGICNUMBER            0xFD2FB527   /* v0.7 */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTDv07_H_235446 */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/zstd.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_H_235446\n#define ZSTD_H_235446\n\n\n/* ======   Dependencies   ======*/\n#include <stddef.h>   /* size_t */\n\n#include \"zstd_errors.h\" /* list of errors */\n#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)\n#include <limits.h>   /* INT_MAX */\n#endif /* ZSTD_STATIC_LINKING_ONLY */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* =====   ZSTDLIB_API : control library symbols visibility   ===== */\n#ifndef ZSTDLIB_VISIBLE\n   /* Backwards compatibility with old macro name */\n#  ifdef ZSTDLIB_VISIBILITY\n#    define ZSTDLIB_VISIBLE ZSTDLIB_VISIBILITY\n#  elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDLIB_VISIBLE __attribute__ ((visibility (\"default\")))\n#  else\n#    define ZSTDLIB_VISIBLE\n#  endif\n#endif\n\n#ifndef ZSTDLIB_HIDDEN\n#  if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDLIB_HIDDEN __attribute__ ((visibility (\"hidden\")))\n#  else\n#    define ZSTDLIB_HIDDEN\n#  endif\n#endif\n\n#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#  define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBLE\n#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#  define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define ZSTDLIB_API ZSTDLIB_VISIBLE\n#endif\n\n/* Deprecation warnings :\n * Should these warnings be a problem, it is generally possible to disable them,\n * typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual.\n * Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS.\n */\n#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS\n#  define ZSTD_DEPRECATED(message) /* disable deprecation warnings */\n#else\n#  if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */\n#    define ZSTD_DEPRECATED(message) [[deprecated(message)]]\n#  elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__) || defined(__IAR_SYSTEMS_ICC__)\n#    define ZSTD_DEPRECATED(message) __attribute__((deprecated(message)))\n#  elif defined(__GNUC__) && (__GNUC__ >= 3)\n#    define ZSTD_DEPRECATED(message) __attribute__((deprecated))\n#  elif defined(_MSC_VER)\n#    define ZSTD_DEPRECATED(message) __declspec(deprecated(message))\n#  else\n#    pragma message(\"WARNING: You need to implement ZSTD_DEPRECATED for this compiler\")\n#    define ZSTD_DEPRECATED(message)\n#  endif\n#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */\n\n\n/*******************************************************************************\n  Introduction\n\n  zstd, short for Zstandard, is a fast lossless compression algorithm, targeting\n  real-time compression scenarios at zlib-level and better compression ratios.\n  The zstd compression library provides in-memory compression and decompression\n  functions.\n\n  The library supports regular compression levels from 1 up to ZSTD_maxCLevel(),\n  which is currently 22. Levels >= 20, labeled `--ultra`, should be used with\n  caution, as they require more memory. The library also offers negative\n  compression levels, which extend the range of speed vs. ratio preferences.\n  The lower the level, the faster the speed (at the cost of compression).\n\n  Compression can be done in:\n    - a single step (described as Simple API)\n    - a single step, reusing a context (described as Explicit context)\n    - unbounded multiple steps (described as Streaming compression)\n\n  The compression ratio achievable on small data can be highly improved using\n  a dictionary. Dictionary compression can be performed in:\n    - a single step (described as Simple dictionary API)\n    - a single step, reusing a dictionary (described as Bulk-processing\n      dictionary API)\n\n  Advanced experimental functions can be accessed using\n  `#define ZSTD_STATIC_LINKING_ONLY` before including zstd.h.\n\n  Advanced experimental APIs should never be used with a dynamically-linked\n  library. They are not \"stable\"; their definitions or signatures may change in\n  the future. Only static linking is allowed.\n*******************************************************************************/\n\n/*------   Version   ------*/\n#define ZSTD_VERSION_MAJOR    1\n#define ZSTD_VERSION_MINOR    5\n#define ZSTD_VERSION_RELEASE  7\n#define ZSTD_VERSION_NUMBER  (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)\n\n/*! ZSTD_versionNumber() :\n *  Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */\nZSTDLIB_API unsigned ZSTD_versionNumber(void);\n\n#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE\n#define ZSTD_QUOTE(str) #str\n#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)\n#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)\n\n/*! ZSTD_versionString() :\n *  Return runtime library version, like \"1.4.5\". Requires v1.3.0+. */\nZSTDLIB_API const char* ZSTD_versionString(void);\n\n/* *************************************\n *  Default constant\n ***************************************/\n#ifndef ZSTD_CLEVEL_DEFAULT\n#  define ZSTD_CLEVEL_DEFAULT 3\n#endif\n\n/* *************************************\n *  Constants\n ***************************************/\n\n/* All magic numbers are supposed read/written to/from files/memory using little-endian convention */\n#define ZSTD_MAGICNUMBER            0xFD2FB528    /* valid since v0.8.0 */\n#define ZSTD_MAGIC_DICTIONARY       0xEC30A437    /* valid since v0.7.0 */\n#define ZSTD_MAGIC_SKIPPABLE_START  0x184D2A50    /* all 16 values, from 0x184D2A50 to 0x184D2A5F, signal the beginning of a skippable frame */\n#define ZSTD_MAGIC_SKIPPABLE_MASK   0xFFFFFFF0\n\n#define ZSTD_BLOCKSIZELOG_MAX  17\n#define ZSTD_BLOCKSIZE_MAX     (1<<ZSTD_BLOCKSIZELOG_MAX)\n\n\n/***************************************\n*  Simple Core API\n***************************************/\n/*! ZSTD_compress() :\n *  Compresses `src` content as a single zstd compressed frame into already allocated `dst`.\n *  NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have\n *        enough space to successfully compress the data.\n *  @return : compressed size written into `dst` (<= `dstCapacity),\n *            or an error code if it fails (which can be tested using ZSTD_isError()). */\nZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,\n                            const void* src, size_t srcSize,\n                                  int compressionLevel);\n\n/*! ZSTD_decompress() :\n * `compressedSize` : must be the _exact_ size of some number of compressed and/or skippable frames.\n *  Multiple compressed frames can be decompressed at once with this method.\n *  The result will be the concatenation of all decompressed frames, back to back.\n * `dstCapacity` is an upper bound of originalSize to regenerate.\n *  First frame's decompressed size can be extracted using ZSTD_getFrameContentSize().\n *  If maximum upper bound isn't known, prefer using streaming mode to decompress data.\n * @return : the number of bytes decompressed into `dst` (<= `dstCapacity`),\n *           or an errorCode if it fails (which can be tested using ZSTD_isError()). */\nZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,\n                              const void* src, size_t compressedSize);\n\n\n/*======  Decompression helper functions  ======*/\n\n/*! ZSTD_getFrameContentSize() : requires v1.3.0+\n * `src` should point to the start of a ZSTD encoded frame.\n * `srcSize` must be at least as large as the frame header.\n *           hint : any size >= `ZSTD_frameHeaderSize_max` is large enough.\n * @return : - decompressed size of `src` frame content, if known\n *           - ZSTD_CONTENTSIZE_UNKNOWN if the size cannot be determined\n *           - ZSTD_CONTENTSIZE_ERROR if an error occurred (e.g. invalid magic number, srcSize too small)\n *  note 1 : a 0 return value means the frame is valid but \"empty\".\n *           When invoking this method on a skippable frame, it will return 0.\n *  note 2 : decompressed size is an optional field, it may not be present (typically in streaming mode).\n *           When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.\n *           In which case, it's necessary to use streaming mode to decompress data.\n *           Optionally, application can rely on some implicit limit,\n *           as ZSTD_decompress() only needs an upper bound of decompressed size.\n *           (For example, data could be necessarily cut into blocks <= 16 KB).\n *  note 3 : decompressed size is always present when compression is completed using single-pass functions,\n *           such as ZSTD_compress(), ZSTD_compressCCtx() ZSTD_compress_usingDict() or ZSTD_compress_usingCDict().\n *  note 4 : decompressed size can be very large (64-bits value),\n *           potentially larger than what local system can handle as a single memory segment.\n *           In which case, it's necessary to use streaming mode to decompress data.\n *  note 5 : If source is untrusted, decompressed size could be wrong or intentionally modified.\n *           Always ensure return value fits within application's authorized limits.\n *           Each application can set its own limits.\n *  note 6 : This function replaces ZSTD_getDecompressedSize() */\n#define ZSTD_CONTENTSIZE_UNKNOWN (0ULL - 1)\n#define ZSTD_CONTENTSIZE_ERROR   (0ULL - 2)\nZSTDLIB_API unsigned long long ZSTD_getFrameContentSize(const void *src, size_t srcSize);\n\n/*! ZSTD_getDecompressedSize() (obsolete):\n *  This function is now obsolete, in favor of ZSTD_getFrameContentSize().\n *  Both functions work the same way, but ZSTD_getDecompressedSize() blends\n *  \"empty\", \"unknown\" and \"error\" results to the same return value (0),\n *  while ZSTD_getFrameContentSize() gives them separate return values.\n * @return : decompressed size of `src` frame content _if known and not empty_, 0 otherwise. */\nZSTD_DEPRECATED(\"Replaced by ZSTD_getFrameContentSize\")\nZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);\n\n/*! ZSTD_findFrameCompressedSize() : Requires v1.4.0+\n * `src` should point to the start of a ZSTD frame or skippable frame.\n * `srcSize` must be >= first frame size\n * @return : the compressed size of the first frame starting at `src`,\n *           suitable to pass as `srcSize` to `ZSTD_decompress` or similar,\n *           or an error code if input is invalid\n *  Note 1: this method is called _find*() because it's not enough to read the header,\n *          it may have to scan through the frame's content, to reach its end.\n *  Note 2: this method also works with Skippable Frames. In which case,\n *          it returns the size of the complete skippable frame,\n *          which is always equal to its content size + 8 bytes for headers. */\nZSTDLIB_API size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);\n\n\n/*======  Compression helper functions  ======*/\n\n/*! ZSTD_compressBound() :\n * maximum compressed size in worst case single-pass scenario.\n * When invoking `ZSTD_compress()`, or any other one-pass compression function,\n * it's recommended to provide @dstCapacity >= ZSTD_compressBound(srcSize)\n * as it eliminates one potential failure scenario,\n * aka not enough room in dst buffer to write the compressed frame.\n * Note : ZSTD_compressBound() itself can fail, if @srcSize >= ZSTD_MAX_INPUT_SIZE .\n *        In which case, ZSTD_compressBound() will return an error code\n *        which can be tested using ZSTD_isError().\n *\n * ZSTD_COMPRESSBOUND() :\n * same as ZSTD_compressBound(), but as a macro.\n * It can be used to produce constants, which can be useful for static allocation,\n * for example to size a static array on stack.\n * Will produce constant value 0 if srcSize is too large.\n */\n#define ZSTD_MAX_INPUT_SIZE ((sizeof(size_t)==8) ? 0xFF00FF00FF00FF00ULL : 0xFF00FF00U)\n#define ZSTD_COMPRESSBOUND(srcSize)   (((size_t)(srcSize) >= ZSTD_MAX_INPUT_SIZE) ? 0 : (srcSize) + ((srcSize)>>8) + (((srcSize) < (128<<10)) ? (((128<<10) - (srcSize)) >> 11) /* margin, from 64 to 0 */ : 0))  /* this formula ensures that bound(A) + bound(B) <= bound(A+B) as long as A and B >= 128 KB */\nZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case single-pass scenario */\n\n\n/*======  Error helper functions  ======*/\n/* ZSTD_isError() :\n * Most ZSTD_* functions returning a size_t value can be tested for error,\n * using ZSTD_isError().\n * @return 1 if error, 0 otherwise\n */\nZSTDLIB_API unsigned     ZSTD_isError(size_t result);      /*!< tells if a `size_t` function result is an error code */\nZSTDLIB_API ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult); /* convert a result into an error code, which can be compared to error enum list */\nZSTDLIB_API const char*  ZSTD_getErrorName(size_t result); /*!< provides readable string from a function result */\nZSTDLIB_API int          ZSTD_minCLevel(void);             /*!< minimum negative compression level allowed, requires v1.4.0+ */\nZSTDLIB_API int          ZSTD_maxCLevel(void);             /*!< maximum compression level available */\nZSTDLIB_API int          ZSTD_defaultCLevel(void);         /*!< default compression level, specified by ZSTD_CLEVEL_DEFAULT, requires v1.5.0+ */\n\n\n/***************************************\n*  Explicit context\n***************************************/\n/*= Compression context\n *  When compressing many times,\n *  it is recommended to allocate a compression context just once,\n *  and reuse it for each successive compression operation.\n *  This will make the workload easier for system's memory.\n *  Note : re-using context is just a speed / resource optimization.\n *         It doesn't change the compression ratio, which remains identical.\n *  Note 2: For parallel execution in multi-threaded environments,\n *         use one different context per thread .\n */\ntypedef struct ZSTD_CCtx_s ZSTD_CCtx;\nZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);\nZSTDLIB_API size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* compatible with NULL pointer */\n\n/*! ZSTD_compressCCtx() :\n *  Same as ZSTD_compress(), using an explicit ZSTD_CCtx.\n *  Important : in order to mirror `ZSTD_compress()` behavior,\n *  this function compresses at the requested compression level,\n *  __ignoring any other advanced parameter__ .\n *  If any advanced parameter was set using the advanced API,\n *  they will all be reset. Only @compressionLevel remains.\n */\nZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* cctx,\n                                     void* dst, size_t dstCapacity,\n                               const void* src, size_t srcSize,\n                                     int compressionLevel);\n\n/*= Decompression context\n *  When decompressing many times,\n *  it is recommended to allocate a context only once,\n *  and reuse it for each successive compression operation.\n *  This will make workload friendlier for system's memory.\n *  Use one context per thread for parallel execution. */\ntypedef struct ZSTD_DCtx_s ZSTD_DCtx;\nZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);\nZSTDLIB_API size_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);  /* accept NULL pointer */\n\n/*! ZSTD_decompressDCtx() :\n *  Same as ZSTD_decompress(),\n *  requires an allocated ZSTD_DCtx.\n *  Compatible with sticky parameters (see below).\n */\nZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,\n                                       void* dst, size_t dstCapacity,\n                                 const void* src, size_t srcSize);\n\n\n/*********************************************\n*  Advanced compression API (Requires v1.4.0+)\n**********************************************/\n\n/* API design :\n *   Parameters are pushed one by one into an existing context,\n *   using ZSTD_CCtx_set*() functions.\n *   Pushed parameters are sticky : they are valid for next compressed frame, and any subsequent frame.\n *   \"sticky\" parameters are applicable to `ZSTD_compress2()` and `ZSTD_compressStream*()` !\n *   __They do not apply to one-shot variants such as ZSTD_compressCCtx()__ .\n *\n *   It's possible to reset all parameters to \"default\" using ZSTD_CCtx_reset().\n *\n *   This API supersedes all other \"advanced\" API entry points in the experimental section.\n *   In the future, we expect to remove API entry points from experimental which are redundant with this API.\n */\n\n\n/* Compression strategies, listed from fastest to strongest */\ntypedef enum { ZSTD_fast=1,\n               ZSTD_dfast=2,\n               ZSTD_greedy=3,\n               ZSTD_lazy=4,\n               ZSTD_lazy2=5,\n               ZSTD_btlazy2=6,\n               ZSTD_btopt=7,\n               ZSTD_btultra=8,\n               ZSTD_btultra2=9\n               /* note : new strategies _might_ be added in the future.\n                         Only the order (from fast to strong) is guaranteed */\n} ZSTD_strategy;\n\ntypedef enum {\n\n    /* compression parameters\n     * Note: When compressing with a ZSTD_CDict these parameters are superseded\n     * by the parameters used to construct the ZSTD_CDict.\n     * See ZSTD_CCtx_refCDict() for more info (superseded-by-cdict). */\n    ZSTD_c_compressionLevel=100, /* Set compression parameters according to pre-defined cLevel table.\n                              * Note that exact compression parameters are dynamically determined,\n                              * depending on both compression level and srcSize (when known).\n                              * Default level is ZSTD_CLEVEL_DEFAULT==3.\n                              * Special: value 0 means default, which is controlled by ZSTD_CLEVEL_DEFAULT.\n                              * Note 1 : it's possible to pass a negative compression level.\n                              * Note 2 : setting a level does not automatically set all other compression parameters\n                              *   to default. Setting this will however eventually dynamically impact the compression\n                              *   parameters which have not been manually set. The manually set\n                              *   ones will 'stick'. */\n    /* Advanced compression parameters :\n     * It's possible to pin down compression parameters to some specific values.\n     * In which case, these values are no longer dynamically selected by the compressor */\n    ZSTD_c_windowLog=101,    /* Maximum allowed back-reference distance, expressed as power of 2.\n                              * This will set a memory budget for streaming decompression,\n                              * with larger values requiring more memory\n                              * and typically compressing more.\n                              * Must be clamped between ZSTD_WINDOWLOG_MIN and ZSTD_WINDOWLOG_MAX.\n                              * Special: value 0 means \"use default windowLog\".\n                              * Note: Using a windowLog greater than ZSTD_WINDOWLOG_LIMIT_DEFAULT\n                              *       requires explicitly allowing such size at streaming decompression stage. */\n    ZSTD_c_hashLog=102,      /* Size of the initial probe table, as a power of 2.\n                              * Resulting memory usage is (1 << (hashLog+2)).\n                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX.\n                              * Larger tables improve compression ratio of strategies <= dFast,\n                              * and improve speed of strategies > dFast.\n                              * Special: value 0 means \"use default hashLog\". */\n    ZSTD_c_chainLog=103,     /* Size of the multi-probe search table, as a power of 2.\n                              * Resulting memory usage is (1 << (chainLog+2)).\n                              * Must be clamped between ZSTD_CHAINLOG_MIN and ZSTD_CHAINLOG_MAX.\n                              * Larger tables result in better and slower compression.\n                              * This parameter is useless for \"fast\" strategy.\n                              * It's still useful when using \"dfast\" strategy,\n                              * in which case it defines a secondary probe table.\n                              * Special: value 0 means \"use default chainLog\". */\n    ZSTD_c_searchLog=104,    /* Number of search attempts, as a power of 2.\n                              * More attempts result in better and slower compression.\n                              * This parameter is useless for \"fast\" and \"dFast\" strategies.\n                              * Special: value 0 means \"use default searchLog\". */\n    ZSTD_c_minMatch=105,     /* Minimum size of searched matches.\n                              * Note that Zstandard can still find matches of smaller size,\n                              * it just tweaks its search algorithm to look for this size and larger.\n                              * Larger values increase compression and decompression speed, but decrease ratio.\n                              * Must be clamped between ZSTD_MINMATCH_MIN and ZSTD_MINMATCH_MAX.\n                              * Note that currently, for all strategies < btopt, effective minimum is 4.\n                              *                    , for all strategies > fast, effective maximum is 6.\n                              * Special: value 0 means \"use default minMatchLength\". */\n    ZSTD_c_targetLength=106, /* Impact of this field depends on strategy.\n                              * For strategies btopt, btultra & btultra2:\n                              *     Length of Match considered \"good enough\" to stop search.\n                              *     Larger values make compression stronger, and slower.\n                              * For strategy fast:\n                              *     Distance between match sampling.\n                              *     Larger values make compression faster, and weaker.\n                              * Special: value 0 means \"use default targetLength\". */\n    ZSTD_c_strategy=107,     /* See ZSTD_strategy enum definition.\n                              * The higher the value of selected strategy, the more complex it is,\n                              * resulting in stronger and slower compression.\n                              * Special: value 0 means \"use default strategy\". */\n\n    ZSTD_c_targetCBlockSize=130, /* v1.5.6+\n                                  * Attempts to fit compressed block size into approximately targetCBlockSize.\n                                  * Bound by ZSTD_TARGETCBLOCKSIZE_MIN and ZSTD_TARGETCBLOCKSIZE_MAX.\n                                  * Note that it's not a guarantee, just a convergence target (default:0).\n                                  * No target when targetCBlockSize == 0.\n                                  * This is helpful in low bandwidth streaming environments to improve end-to-end latency,\n                                  * when a client can make use of partial documents (a prominent example being Chrome).\n                                  * Note: this parameter is stable since v1.5.6.\n                                  * It was present as an experimental parameter in earlier versions,\n                                  * but it's not recommended using it with earlier library versions\n                                  * due to massive performance regressions.\n                                  */\n    /* LDM mode parameters */\n    ZSTD_c_enableLongDistanceMatching=160, /* Enable long distance matching.\n                                     * This parameter is designed to improve compression ratio\n                                     * for large inputs, by finding large matches at long distance.\n                                     * It increases memory usage and window size.\n                                     * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB\n                                     * except when expressly set to a different value.\n                                     * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and\n                                     * compression strategy >= ZSTD_btopt (== compression level 16+) */\n    ZSTD_c_ldmHashLog=161,   /* Size of the table for long distance matching, as a power of 2.\n                              * Larger values increase memory usage and compression ratio,\n                              * but decrease compression speed.\n                              * Must be clamped between ZSTD_HASHLOG_MIN and ZSTD_HASHLOG_MAX\n                              * default: windowlog - 7.\n                              * Special: value 0 means \"automatically determine hashlog\". */\n    ZSTD_c_ldmMinMatch=162,  /* Minimum match size for long distance matcher.\n                              * Larger/too small values usually decrease compression ratio.\n                              * Must be clamped between ZSTD_LDM_MINMATCH_MIN and ZSTD_LDM_MINMATCH_MAX.\n                              * Special: value 0 means \"use default value\" (default: 64). */\n    ZSTD_c_ldmBucketSizeLog=163, /* Log size of each bucket in the LDM hash table for collision resolution.\n                              * Larger values improve collision resolution but decrease compression speed.\n                              * The maximum value is ZSTD_LDM_BUCKETSIZELOG_MAX.\n                              * Special: value 0 means \"use default value\" (default: 3). */\n    ZSTD_c_ldmHashRateLog=164, /* Frequency of inserting/looking up entries into the LDM hash table.\n                              * Must be clamped between 0 and (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN).\n                              * Default is MAX(0, (windowLog - ldmHashLog)), optimizing hash table usage.\n                              * Larger values improve compression speed.\n                              * Deviating far from default value will likely result in a compression ratio decrease.\n                              * Special: value 0 means \"automatically determine hashRateLog\". */\n\n    /* frame parameters */\n    ZSTD_c_contentSizeFlag=200, /* Content size will be written into frame header _whenever known_ (default:1)\n                              * Content size must be known at the beginning of compression.\n                              * This is automatically the case when using ZSTD_compress2(),\n                              * For streaming scenarios, content size must be provided with ZSTD_CCtx_setPledgedSrcSize() */\n    ZSTD_c_checksumFlag=201, /* A 32-bits checksum of content is written at end of frame (default:0) */\n    ZSTD_c_dictIDFlag=202,   /* When applicable, dictionary's ID is written into frame header (default:1) */\n\n    /* multi-threading parameters */\n    /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD).\n     * Otherwise, trying to set any other value than default (0) will be a no-op and return an error.\n     * In a situation where it's unknown if the linked library supports multi-threading or not,\n     * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property.\n     */\n    ZSTD_c_nbWorkers=400,    /* Select how many threads will be spawned to compress in parallel.\n                              * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() :\n                              * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller,\n                              * while compression is performed in parallel, within worker thread(s).\n                              * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end :\n                              *  in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call).\n                              * More workers improve speed, but also increase memory usage.\n                              * Default value is `0`, aka \"single-threaded mode\" : no worker is spawned,\n                              * compression is performed inside Caller's thread, and all invocations are blocking */\n    ZSTD_c_jobSize=401,      /* Size of a compression job. This value is enforced only when nbWorkers >= 1.\n                              * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads.\n                              * 0 means default, which is dynamically determined based on compression parameters.\n                              * Job size must be a minimum of overlap size, or ZSTDMT_JOBSIZE_MIN (= 512 KB), whichever is largest.\n                              * The minimum size is automatically and transparently enforced. */\n    ZSTD_c_overlapLog=402,   /* Control the overlap size, as a fraction of window size.\n                              * The overlap size is an amount of data reloaded from previous job at the beginning of a new job.\n                              * It helps preserve compression ratio, while each job is compressed in parallel.\n                              * This value is enforced only when nbWorkers >= 1.\n                              * Larger values increase compression ratio, but decrease speed.\n                              * Possible values range from 0 to 9 :\n                              * - 0 means \"default\" : value will be determined by the library, depending on strategy\n                              * - 1 means \"no overlap\"\n                              * - 9 means \"full overlap\", using a full window size.\n                              * Each intermediate rank increases/decreases load size by a factor 2 :\n                              * 9: full window;  8: w/2;  7: w/4;  6: w/8;  5:w/16;  4: w/32;  3:w/64;  2:w/128;  1:no overlap;  0:default\n                              * default value varies between 6 and 9, depending on strategy */\n\n    /* note : additional experimental parameters are also available\n     * within the experimental section of the API.\n     * At the time of this writing, they include :\n     * ZSTD_c_rsyncable\n     * ZSTD_c_format\n     * ZSTD_c_forceMaxWindow\n     * ZSTD_c_forceAttachDict\n     * ZSTD_c_literalCompressionMode\n     * ZSTD_c_srcSizeHint\n     * ZSTD_c_enableDedicatedDictSearch\n     * ZSTD_c_stableInBuffer\n     * ZSTD_c_stableOutBuffer\n     * ZSTD_c_blockDelimiters\n     * ZSTD_c_validateSequences\n     * ZSTD_c_blockSplitterLevel\n     * ZSTD_c_splitAfterSequences\n     * ZSTD_c_useRowMatchFinder\n     * ZSTD_c_prefetchCDictTables\n     * ZSTD_c_enableSeqProducerFallback\n     * ZSTD_c_maxBlockSize\n     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.\n     * note : never ever use experimentalParam? names directly;\n     *        also, the enums values themselves are unstable and can still change.\n     */\n     ZSTD_c_experimentalParam1=500,\n     ZSTD_c_experimentalParam2=10,\n     ZSTD_c_experimentalParam3=1000,\n     ZSTD_c_experimentalParam4=1001,\n     ZSTD_c_experimentalParam5=1002,\n     /* was ZSTD_c_experimentalParam6=1003; is now ZSTD_c_targetCBlockSize */\n     ZSTD_c_experimentalParam7=1004,\n     ZSTD_c_experimentalParam8=1005,\n     ZSTD_c_experimentalParam9=1006,\n     ZSTD_c_experimentalParam10=1007,\n     ZSTD_c_experimentalParam11=1008,\n     ZSTD_c_experimentalParam12=1009,\n     ZSTD_c_experimentalParam13=1010,\n     ZSTD_c_experimentalParam14=1011,\n     ZSTD_c_experimentalParam15=1012,\n     ZSTD_c_experimentalParam16=1013,\n     ZSTD_c_experimentalParam17=1014,\n     ZSTD_c_experimentalParam18=1015,\n     ZSTD_c_experimentalParam19=1016,\n     ZSTD_c_experimentalParam20=1017\n} ZSTD_cParameter;\n\ntypedef struct {\n    size_t error;\n    int lowerBound;\n    int upperBound;\n} ZSTD_bounds;\n\n/*! ZSTD_cParam_getBounds() :\n *  All parameters must belong to an interval with lower and upper bounds,\n *  otherwise they will either trigger an error or be automatically clamped.\n * @return : a structure, ZSTD_bounds, which contains\n *         - an error status field, which must be tested using ZSTD_isError()\n *         - lower and upper bounds, both inclusive\n */\nZSTDLIB_API ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter cParam);\n\n/*! ZSTD_CCtx_setParameter() :\n *  Set one compression parameter, selected by enum ZSTD_cParameter.\n *  All parameters have valid bounds. Bounds can be queried using ZSTD_cParam_getBounds().\n *  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).\n *  Setting a parameter is generally only possible during frame initialization (before starting compression).\n *  Exception : when using multi-threading mode (nbWorkers >= 1),\n *              the following parameters can be updated _during_ compression (within same frame):\n *              => compressionLevel, hashLog, chainLog, searchLog, minMatch, targetLength and strategy.\n *              new parameters will be active for next job only (after a flush()).\n * @return : an error code (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_API size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value);\n\n/*! ZSTD_CCtx_setPledgedSrcSize() :\n *  Total input data size to be compressed as a single frame.\n *  Value will be written in frame header, unless if explicitly forbidden using ZSTD_c_contentSizeFlag.\n *  This value will also be controlled at end of frame, and trigger an error if not respected.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Note 1 : pledgedSrcSize==0 actually means zero, aka an empty frame.\n *           In order to mean \"unknown content size\", pass constant ZSTD_CONTENTSIZE_UNKNOWN.\n *           ZSTD_CONTENTSIZE_UNKNOWN is default value for any new frame.\n *  Note 2 : pledgedSrcSize is only valid once, for the next frame.\n *           It's discarded at the end of the frame, and replaced by ZSTD_CONTENTSIZE_UNKNOWN.\n *  Note 3 : Whenever all input data is provided and consumed in a single round,\n *           for example with ZSTD_compress2(),\n *           or invoking immediately ZSTD_compressStream2(,,,ZSTD_e_end),\n *           this value is automatically overridden by srcSize instead.\n */\nZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize);\n\ntypedef enum {\n    ZSTD_reset_session_only = 1,\n    ZSTD_reset_parameters = 2,\n    ZSTD_reset_session_and_parameters = 3\n} ZSTD_ResetDirective;\n\n/*! ZSTD_CCtx_reset() :\n *  There are 2 different things that can be reset, independently or jointly :\n *  - The session : will stop compressing current frame, and make CCtx ready to start a new one.\n *                  Useful after an error, or to interrupt any ongoing compression.\n *                  Any internal data not yet flushed is cancelled.\n *                  Compression parameters and dictionary remain unchanged.\n *                  They will be used to compress next frame.\n *                  Resetting session never fails.\n *  - The parameters : changes all parameters back to \"default\".\n *                  This also removes any reference to any dictionary or external sequence producer.\n *                  Parameters can only be changed between 2 sessions (i.e. no compression is currently ongoing)\n *                  otherwise the reset fails, and function returns an error value (which can be tested using ZSTD_isError())\n *  - Both : similar to resetting the session, followed by resetting parameters.\n */\nZSTDLIB_API size_t ZSTD_CCtx_reset(ZSTD_CCtx* cctx, ZSTD_ResetDirective reset);\n\n/*! ZSTD_compress2() :\n *  Behave the same as ZSTD_compressCCtx(), but compression parameters are set using the advanced API.\n *  (note that this entry point doesn't even expose a compression level parameter).\n *  ZSTD_compress2() always starts a new frame.\n *  Should cctx hold data from a previously unfinished frame, everything about it is forgotten.\n *  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()\n *  - The function is always blocking, returns when compression is completed.\n *  NOTE: Providing `dstCapacity >= ZSTD_compressBound(srcSize)` guarantees that zstd will have\n *        enough space to successfully compress the data, though it is possible it fails for other reasons.\n * @return : compressed size written into `dst` (<= `dstCapacity),\n *           or an error code if it fails (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_API size_t ZSTD_compress2( ZSTD_CCtx* cctx,\n                                   void* dst, size_t dstCapacity,\n                             const void* src, size_t srcSize);\n\n\n/***********************************************\n*  Advanced decompression API (Requires v1.4.0+)\n************************************************/\n\n/* The advanced API pushes parameters one by one into an existing DCtx context.\n * Parameters are sticky, and remain valid for all following frames\n * using the same DCtx context.\n * It's possible to reset parameters to default values using ZSTD_DCtx_reset().\n * Note : This API is compatible with existing ZSTD_decompressDCtx() and ZSTD_decompressStream().\n *        Therefore, no new decompression function is necessary.\n */\n\ntypedef enum {\n\n    ZSTD_d_windowLogMax=100, /* Select a size limit (in power of 2) beyond which\n                              * the streaming API will refuse to allocate memory buffer\n                              * in order to protect the host from unreasonable memory requirements.\n                              * This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.\n                              * By default, a decompression context accepts window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT).\n                              * Special: value 0 means \"use default maximum windowLog\". */\n\n    /* note : additional experimental parameters are also available\n     * within the experimental section of the API.\n     * At the time of this writing, they include :\n     * ZSTD_d_format\n     * ZSTD_d_stableOutBuffer\n     * ZSTD_d_forceIgnoreChecksum\n     * ZSTD_d_refMultipleDDicts\n     * ZSTD_d_disableHuffmanAssembly\n     * ZSTD_d_maxBlockSize\n     * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.\n     * note : never ever use experimentalParam? names directly\n     */\n     ZSTD_d_experimentalParam1=1000,\n     ZSTD_d_experimentalParam2=1001,\n     ZSTD_d_experimentalParam3=1002,\n     ZSTD_d_experimentalParam4=1003,\n     ZSTD_d_experimentalParam5=1004,\n     ZSTD_d_experimentalParam6=1005\n\n} ZSTD_dParameter;\n\n/*! ZSTD_dParam_getBounds() :\n *  All parameters must belong to an interval with lower and upper bounds,\n *  otherwise they will either trigger an error or be automatically clamped.\n * @return : a structure, ZSTD_bounds, which contains\n *         - an error status field, which must be tested using ZSTD_isError()\n *         - both lower and upper bounds, inclusive\n */\nZSTDLIB_API ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam);\n\n/*! ZSTD_DCtx_setParameter() :\n *  Set one compression parameter, selected by enum ZSTD_dParameter.\n *  All parameters have valid bounds. Bounds can be queried using ZSTD_dParam_getBounds().\n *  Providing a value beyond bound will either clamp it, or trigger an error (depending on parameter).\n *  Setting a parameter is only possible during frame initialization (before starting decompression).\n * @return : 0, or an error code (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_API size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int value);\n\n/*! ZSTD_DCtx_reset() :\n *  Return a DCtx to clean state.\n *  Session and parameters can be reset jointly or separately.\n *  Parameters can only be reset when no active frame is being decompressed.\n * @return : 0, or an error code, which can be tested with ZSTD_isError()\n */\nZSTDLIB_API size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset);\n\n\n/****************************\n*  Streaming\n****************************/\n\ntypedef struct ZSTD_inBuffer_s {\n  const void* src;    /**< start of input buffer */\n  size_t size;        /**< size of input buffer */\n  size_t pos;         /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */\n} ZSTD_inBuffer;\n\ntypedef struct ZSTD_outBuffer_s {\n  void*  dst;         /**< start of output buffer */\n  size_t size;        /**< size of output buffer */\n  size_t pos;         /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */\n} ZSTD_outBuffer;\n\n\n\n/*-***********************************************************************\n*  Streaming compression - HowTo\n*\n*  A ZSTD_CStream object is required to track streaming operation.\n*  Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.\n*  ZSTD_CStream objects can be reused multiple times on consecutive compression operations.\n*  It is recommended to reuse ZSTD_CStream since it will play nicer with system's memory, by re-using already allocated memory.\n*\n*  For parallel execution, use one separate ZSTD_CStream per thread.\n*\n*  note : since v1.3.0, ZSTD_CStream and ZSTD_CCtx are the same thing.\n*\n*  Parameters are sticky : when starting a new compression on the same context,\n*  it will reuse the same sticky parameters as previous compression session.\n*  When in doubt, it's recommended to fully initialize the context before usage.\n*  Use ZSTD_CCtx_reset() to reset the context and ZSTD_CCtx_setParameter(),\n*  ZSTD_CCtx_setPledgedSrcSize(), or ZSTD_CCtx_loadDictionary() and friends to\n*  set more specific parameters, the pledged source size, or load a dictionary.\n*\n*  Use ZSTD_compressStream2() with ZSTD_e_continue as many times as necessary to\n*  consume input stream. The function will automatically update both `pos`\n*  fields within `input` and `output`.\n*  Note that the function may not consume the entire input, for example, because\n*  the output buffer is already full, in which case `input.pos < input.size`.\n*  The caller must check if input has been entirely consumed.\n*  If not, the caller must make some room to receive more compressed data,\n*  and then present again remaining input data.\n*  note: ZSTD_e_continue is guaranteed to make some forward progress when called,\n*        but doesn't guarantee maximal forward progress. This is especially relevant\n*        when compressing with multiple threads. The call won't block if it can\n*        consume some input, but if it can't it will wait for some, but not all,\n*        output to be flushed.\n* @return : provides a minimum amount of data remaining to be flushed from internal buffers\n*           or an error code, which can be tested using ZSTD_isError().\n*\n*  At any moment, it's possible to flush whatever data might remain stuck within internal buffer,\n*  using ZSTD_compressStream2() with ZSTD_e_flush. `output->pos` will be updated.\n*  Note that, if `output->size` is too small, a single invocation with ZSTD_e_flush might not be enough (return code > 0).\n*  In which case, make some room to receive more compressed data, and call again ZSTD_compressStream2() with ZSTD_e_flush.\n*  You must continue calling ZSTD_compressStream2() with ZSTD_e_flush until it returns 0, at which point you can change the\n*  operation.\n*  note: ZSTD_e_flush will flush as much output as possible, meaning when compressing with multiple threads, it will\n*        block until the flush is complete or the output buffer is full.\n*  @return : 0 if internal buffers are entirely flushed,\n*            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),\n*            or an error code, which can be tested using ZSTD_isError().\n*\n*  Calling ZSTD_compressStream2() with ZSTD_e_end instructs to finish a frame.\n*  It will perform a flush and write frame epilogue.\n*  The epilogue is required for decoders to consider a frame completed.\n*  flush operation is the same, and follows same rules as calling ZSTD_compressStream2() with ZSTD_e_flush.\n*  You must continue calling ZSTD_compressStream2() with ZSTD_e_end until it returns 0, at which point you are free to\n*  start a new frame.\n*  note: ZSTD_e_end will flush as much output as possible, meaning when compressing with multiple threads, it will\n*        block until the flush is complete or the output buffer is full.\n*  @return : 0 if frame fully completed and fully flushed,\n*            >0 if some data still present within internal buffer (the value is minimal estimation of remaining size),\n*            or an error code, which can be tested using ZSTD_isError().\n*\n* *******************************************************************/\n\ntypedef ZSTD_CCtx ZSTD_CStream;  /**< CCtx and CStream are now effectively same object (>= v1.3.0) */\n                                 /* Continue to distinguish them for compatibility with older versions <= v1.2.0 */\n/*===== ZSTD_CStream management functions =====*/\nZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);\nZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);  /* accept NULL pointer */\n\n/*===== Streaming compression functions =====*/\ntypedef enum {\n    ZSTD_e_continue=0, /* collect more data, encoder decides when to output compressed result, for optimal compression ratio */\n    ZSTD_e_flush=1,    /* flush any data provided so far,\n                        * it creates (at least) one new block, that can be decoded immediately on reception;\n                        * frame will continue: any future data can still reference previously compressed data, improving compression.\n                        * note : multithreaded compression will block to flush as much output as possible. */\n    ZSTD_e_end=2       /* flush any remaining data _and_ close current frame.\n                        * note that frame is only closed after compressed data is fully flushed (return value == 0).\n                        * After that point, any additional data starts a new frame.\n                        * note : each frame is independent (does not reference any content from previous frame).\n                        : note : multithreaded compression will block to flush as much output as possible. */\n} ZSTD_EndDirective;\n\n/*! ZSTD_compressStream2() : Requires v1.4.0+\n *  Behaves about the same as ZSTD_compressStream, with additional control on end directive.\n *  - Compression parameters are pushed into CCtx before starting compression, using ZSTD_CCtx_set*()\n *  - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode)\n *  - output->pos must be <= dstCapacity, input->pos must be <= srcSize\n *  - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit.\n *  - endOp must be a valid directive\n *  - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller.\n *  - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available,\n *                                                  and then immediately returns, just indicating that there is some data remaining to be flushed.\n *                                                  The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte.\n *  - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking.\n *  - @return provides a minimum amount of data remaining to be flushed from internal buffers\n *            or an error code, which can be tested using ZSTD_isError().\n *            if @return != 0, flush is not fully completed, there is still some data left within internal buffers.\n *            This is useful for ZSTD_e_flush, since in this case more flushes are necessary to empty all buffers.\n *            For ZSTD_e_end, @return == 0 when internal buffers are fully flushed and frame is completed.\n *  - after a ZSTD_e_end directive, if internal buffer is not fully flushed (@return != 0),\n *            only ZSTD_e_end or ZSTD_e_flush operations are allowed.\n *            Before starting a new compression job, or changing compression parameters,\n *            it is required to fully flush internal buffers.\n *  - note: if an operation ends with an error, it may leave @cctx in an undefined state.\n *          Therefore, it's UB to invoke ZSTD_compressStream2() of ZSTD_compressStream() on such a state.\n *          In order to be re-employed after an error, a state must be reset,\n *          which can be done explicitly (ZSTD_CCtx_reset()),\n *          or is sometimes implied by methods starting a new compression job (ZSTD_initCStream(), ZSTD_compressCCtx())\n */\nZSTDLIB_API size_t ZSTD_compressStream2( ZSTD_CCtx* cctx,\n                                         ZSTD_outBuffer* output,\n                                         ZSTD_inBuffer* input,\n                                         ZSTD_EndDirective endOp);\n\n\n/* These buffer sizes are softly recommended.\n * They are not required : ZSTD_compressStream*() happily accepts any buffer size, for both input and output.\n * Respecting the recommended size just makes it a bit easier for ZSTD_compressStream*(),\n * reducing the amount of memory shuffling and buffering, resulting in minor performance savings.\n *\n * However, note that these recommendations are from the perspective of a C caller program.\n * If the streaming interface is invoked from some other language,\n * especially managed ones such as Java or Go, through a foreign function interface such as jni or cgo,\n * a major performance rule is to reduce crossing such interface to an absolute minimum.\n * It's not rare that performance ends being spent more into the interface, rather than compression itself.\n * In which cases, prefer using large buffers, as large as practical,\n * for both input and output, to reduce the nb of roundtrips.\n */\nZSTDLIB_API size_t ZSTD_CStreamInSize(void);    /**< recommended size for input buffer */\nZSTDLIB_API size_t ZSTD_CStreamOutSize(void);   /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block. */\n\n\n/* *****************************************************************************\n * This following is a legacy streaming API, available since v1.0+ .\n * It can be replaced by ZSTD_CCtx_reset() and ZSTD_compressStream2().\n * It is redundant, but remains fully supported.\n ******************************************************************************/\n\n/*!\n * Equivalent to:\n *\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)\n *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n *\n * Note that ZSTD_initCStream() clears any previously set dictionary. Use the new API\n * to compress with a dictionary.\n */\nZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);\n/*!\n * Alternative for ZSTD_compressStream2(zcs, output, input, ZSTD_e_continue).\n * NOTE: The return value is different. ZSTD_compressStream() returns a hint for\n * the next read size (if non-zero and not an error). ZSTD_compressStream2()\n * returns the minimum nb of bytes left to flush (if non-zero and not an error).\n */\nZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);\n/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_flush). */\nZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);\n/*! Equivalent to ZSTD_compressStream2(zcs, output, &emptyInput, ZSTD_e_end). */\nZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);\n\n\n/*-***************************************************************************\n*  Streaming decompression - HowTo\n*\n*  A ZSTD_DStream object is required to track streaming operations.\n*  Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.\n*  ZSTD_DStream objects can be re-employed multiple times.\n*\n*  Use ZSTD_initDStream() to start a new decompression operation.\n* @return : recommended first input size\n*  Alternatively, use advanced API to set specific properties.\n*\n*  Use ZSTD_decompressStream() repetitively to consume your input.\n*  The function will update both `pos` fields.\n*  If `input.pos < input.size`, some input has not been consumed.\n*  It's up to the caller to present again remaining data.\n*\n*  The function tries to flush all data decoded immediately, respecting output buffer size.\n*  If `output.pos < output.size`, decoder has flushed everything it could.\n*\n*  However, when `output.pos == output.size`, it's more difficult to know.\n*  If @return > 0, the frame is not complete, meaning\n*  either there is still some data left to flush within internal buffers,\n*  or there is more input to read to complete the frame (or both).\n*  In which case, call ZSTD_decompressStream() again to flush whatever remains in the buffer.\n*  Note : with no additional input provided, amount of data flushed is necessarily <= ZSTD_BLOCKSIZE_MAX.\n* @return : 0 when a frame is completely decoded and fully flushed,\n*        or an error code, which can be tested using ZSTD_isError(),\n*        or any other value > 0, which means there is still some decoding or flushing to do to complete current frame :\n*                                the return value is a suggested next input size (just a hint for better latency)\n*                                that will never request more than the remaining content of the compressed frame.\n* *******************************************************************************/\n\ntypedef ZSTD_DCtx ZSTD_DStream;  /**< DCtx and DStream are now effectively same object (>= v1.3.0) */\n                                 /* For compatibility with versions <= v1.2.0, prefer differentiating them. */\n/*===== ZSTD_DStream management functions =====*/\nZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);\nZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);  /* accept NULL pointer */\n\n/*===== Streaming decompression functions =====*/\n\n/*! ZSTD_initDStream() :\n * Initialize/reset DStream state for new decompression operation.\n * Call before new decompression operation using same DStream.\n *\n * Note : This function is redundant with the advanced API and equivalent to:\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *     ZSTD_DCtx_refDDict(zds, NULL);\n */\nZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);\n\n/*! ZSTD_decompressStream() :\n * Streaming decompression function.\n * Call repetitively to consume full input updating it as necessary.\n * Function will update both input and output `pos` fields exposing current state via these fields:\n * - `input.pos < input.size`, some input remaining and caller should provide remaining input\n *   on the next call.\n * - `output.pos < output.size`, decoder flushed internal output buffer.\n * - `output.pos == output.size`, unflushed data potentially present in the internal buffers,\n *   check ZSTD_decompressStream() @return value,\n *   if > 0, invoke it again to flush remaining data to output.\n * Note : with no additional input, amount of data flushed <= ZSTD_BLOCKSIZE_MAX.\n *\n * @return : 0 when a frame is completely decoded and fully flushed,\n *           or an error code, which can be tested using ZSTD_isError(),\n *           or any other value > 0, which means there is some decoding or flushing to do to complete current frame.\n *\n * Note: when an operation returns with an error code, the @zds state may be left in undefined state.\n *       It's UB to invoke `ZSTD_decompressStream()` on such a state.\n *       In order to re-use such a state, it must be first reset,\n *       which can be done explicitly (`ZSTD_DCtx_reset()`),\n *       or is implied for operations starting some new decompression job (`ZSTD_initDStream`, `ZSTD_decompressDCtx()`, `ZSTD_decompress_usingDict()`)\n */\nZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);\n\nZSTDLIB_API size_t ZSTD_DStreamInSize(void);    /*!< recommended size for input buffer */\nZSTDLIB_API size_t ZSTD_DStreamOutSize(void);   /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */\n\n\n/**************************\n*  Simple dictionary API\n***************************/\n/*! ZSTD_compress_usingDict() :\n *  Compression at an explicit compression level using a Dictionary.\n *  A dictionary can be any arbitrary data segment (also called a prefix),\n *  or a buffer with specified information (see zdict.h).\n *  Note : This function loads the dictionary, resulting in significant startup delay.\n *         It's intended for a dictionary used only once.\n *  Note 2 : When `dict == NULL || dictSize < 8` no dictionary is used. */\nZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,\n                                           void* dst, size_t dstCapacity,\n                                     const void* src, size_t srcSize,\n                                     const void* dict,size_t dictSize,\n                                           int compressionLevel);\n\n/*! ZSTD_decompress_usingDict() :\n *  Decompression using a known Dictionary.\n *  Dictionary must be identical to the one used during compression.\n *  Note : This function loads the dictionary, resulting in significant startup delay.\n *         It's intended for a dictionary used only once.\n *  Note : When `dict == NULL || dictSize < 8` no dictionary is used. */\nZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,\n                                             void* dst, size_t dstCapacity,\n                                       const void* src, size_t srcSize,\n                                       const void* dict,size_t dictSize);\n\n\n/***********************************\n *  Bulk processing dictionary API\n **********************************/\ntypedef struct ZSTD_CDict_s ZSTD_CDict;\n\n/*! ZSTD_createCDict() :\n *  When compressing multiple messages or blocks using the same dictionary,\n *  it's recommended to digest the dictionary only once, since it's a costly operation.\n *  ZSTD_createCDict() will create a state from digesting a dictionary.\n *  The resulting state can be used for future compression operations with very limited startup cost.\n *  ZSTD_CDict can be created once and shared by multiple threads concurrently, since its usage is read-only.\n * @dictBuffer can be released after ZSTD_CDict creation, because its content is copied within CDict.\n *  Note 1 : Consider experimental function `ZSTD_createCDict_byReference()` if you prefer to not duplicate @dictBuffer content.\n *  Note 2 : A ZSTD_CDict can be created from an empty @dictBuffer,\n *      in which case the only thing that it transports is the @compressionLevel.\n *      This can be useful in a pipeline featuring ZSTD_compress_usingCDict() exclusively,\n *      expecting a ZSTD_CDict parameter with any data, including those without a known dictionary. */\nZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize,\n                                         int compressionLevel);\n\n/*! ZSTD_freeCDict() :\n *  Function frees memory allocated by ZSTD_createCDict().\n *  If a NULL pointer is passed, no operation is performed. */\nZSTDLIB_API size_t      ZSTD_freeCDict(ZSTD_CDict* CDict);\n\n/*! ZSTD_compress_usingCDict() :\n *  Compression using a digested Dictionary.\n *  Recommended when same dictionary is used multiple times.\n *  Note : compression level is _decided at dictionary creation time_,\n *     and frame parameters are hardcoded (dictID=yes, contentSize=yes, checksum=no) */\nZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,\n                                            void* dst, size_t dstCapacity,\n                                      const void* src, size_t srcSize,\n                                      const ZSTD_CDict* cdict);\n\n\ntypedef struct ZSTD_DDict_s ZSTD_DDict;\n\n/*! ZSTD_createDDict() :\n *  Create a digested dictionary, ready to start decompression operation without startup delay.\n *  dictBuffer can be released after DDict creation, as its content is copied inside DDict. */\nZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);\n\n/*! ZSTD_freeDDict() :\n *  Function frees memory allocated with ZSTD_createDDict()\n *  If a NULL pointer is passed, no operation is performed. */\nZSTDLIB_API size_t      ZSTD_freeDDict(ZSTD_DDict* ddict);\n\n/*! ZSTD_decompress_usingDDict() :\n *  Decompression using a digested Dictionary.\n *  Recommended when same dictionary is used multiple times. */\nZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,\n                                              void* dst, size_t dstCapacity,\n                                        const void* src, size_t srcSize,\n                                        const ZSTD_DDict* ddict);\n\n\n/********************************\n *  Dictionary helper functions\n *******************************/\n\n/*! ZSTD_getDictID_fromDict() : Requires v1.4.0+\n *  Provides the dictID stored within dictionary.\n *  if @return == 0, the dictionary is not conformant with Zstandard specification.\n *  It can still be loaded, but as a content-only dictionary. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);\n\n/*! ZSTD_getDictID_fromCDict() : Requires v1.5.0+\n *  Provides the dictID of the dictionary loaded into `cdict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict);\n\n/*! ZSTD_getDictID_fromDDict() : Requires v1.4.0+\n *  Provides the dictID of the dictionary loaded into `ddict`.\n *  If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.\n *  Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);\n\n/*! ZSTD_getDictID_fromFrame() : Requires v1.4.0+\n *  Provides the dictID required to decompressed the frame stored within `src`.\n *  If @return == 0, the dictID could not be decoded.\n *  This could for one of the following reasons :\n *  - The frame does not require a dictionary to be decoded (most common case).\n *  - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden piece of information.\n *    Note : this use case also happens when using a non-conformant dictionary.\n *  - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).\n *  - This is not a Zstandard frame.\n *  When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code. */\nZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);\n\n\n/*******************************************************************************\n * Advanced dictionary and prefix API (Requires v1.4.0+)\n *\n * This API allows dictionaries to be used with ZSTD_compress2(),\n * ZSTD_compressStream2(), and ZSTD_decompressDCtx().\n * Dictionaries are sticky, they remain valid when same context is reused,\n * they only reset when the context is reset\n * with ZSTD_reset_parameters or ZSTD_reset_session_and_parameters.\n * In contrast, Prefixes are single-use.\n ******************************************************************************/\n\n\n/*! ZSTD_CCtx_loadDictionary() : Requires v1.4.0+\n *  Create an internal CDict from `dict` buffer.\n *  Decompression will have to use same dictionary.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special: Loading a NULL (or 0-size) dictionary invalidates previous dictionary,\n *           meaning \"return to no-dictionary mode\".\n *  Note 1 : Dictionary is sticky, it will be used for all future compressed frames,\n *           until parameters are reset, a new dictionary is loaded, or the dictionary\n *           is explicitly invalidated by loading a NULL dictionary.\n *  Note 2 : Loading a dictionary involves building tables.\n *           It's also a CPU consuming operation, with non-negligible impact on latency.\n *           Tables are dependent on compression parameters, and for this reason,\n *           compression parameters can no longer be changed after loading a dictionary.\n *  Note 3 :`dict` content will be copied internally.\n *           Use experimental ZSTD_CCtx_loadDictionary_byReference() to reference content instead.\n *           In such a case, dictionary buffer must outlive its users.\n *  Note 4 : Use ZSTD_CCtx_loadDictionary_advanced()\n *           to precisely select how dictionary content must be interpreted.\n *  Note 5 : This method does not benefit from LDM (long distance mode).\n *           If you want to employ LDM on some large dictionary content,\n *           prefer employing ZSTD_CCtx_refPrefix() described below.\n */\nZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_CCtx_refCDict() : Requires v1.4.0+\n *  Reference a prepared dictionary, to be used for all future compressed frames.\n *  Note that compression parameters are enforced from within CDict,\n *  and supersede any compression parameter previously set within CCtx.\n *  The parameters ignored are labelled as \"superseded-by-cdict\" in the ZSTD_cParameter enum docs.\n *  The ignored parameters will be used again if the CCtx is returned to no-dictionary mode.\n *  The dictionary will remain valid for future compressed frames using same CCtx.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special : Referencing a NULL CDict means \"return to no-dictionary mode\".\n *  Note 1 : Currently, only one dictionary can be managed.\n *           Referencing a new dictionary effectively \"discards\" any previous one.\n *  Note 2 : CDict is just referenced, its lifetime must outlive its usage within CCtx. */\nZSTDLIB_API size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);\n\n/*! ZSTD_CCtx_refPrefix() : Requires v1.4.0+\n *  Reference a prefix (single-usage dictionary) for next compressed frame.\n *  A prefix is **only used once**. Tables are discarded at end of frame (ZSTD_e_end).\n *  Decompression will need same prefix to properly regenerate data.\n *  Compressing with a prefix is similar in outcome as performing a diff and compressing it,\n *  but performs much faster, especially during decompression (compression speed is tunable with compression level).\n *  This method is compatible with LDM (long distance mode).\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special: Adding any prefix (including NULL) invalidates any previous prefix or dictionary\n *  Note 1 : Prefix buffer is referenced. It **must** outlive compression.\n *           Its content must remain unmodified during compression.\n *  Note 2 : If the intention is to diff some large src data blob with some prior version of itself,\n *           ensure that the window size is large enough to contain the entire source.\n *           See ZSTD_c_windowLog.\n *  Note 3 : Referencing a prefix involves building tables, which are dependent on compression parameters.\n *           It's a CPU consuming operation, with non-negligible impact on latency.\n *           If there is a need to use the same prefix multiple times, consider loadDictionary instead.\n *  Note 4 : By default, the prefix is interpreted as raw content (ZSTD_dct_rawContent).\n *           Use experimental ZSTD_CCtx_refPrefix_advanced() to alter dictionary interpretation. */\nZSTDLIB_API size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx,\n                                 const void* prefix, size_t prefixSize);\n\n/*! ZSTD_DCtx_loadDictionary() : Requires v1.4.0+\n *  Create an internal DDict from dict buffer, to be used to decompress all future frames.\n *  The dictionary remains valid for all future frames, until explicitly invalidated, or\n *  a new dictionary is loaded.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special : Adding a NULL (or 0-size) dictionary invalidates any previous dictionary,\n *            meaning \"return to no-dictionary mode\".\n *  Note 1 : Loading a dictionary involves building tables,\n *           which has a non-negligible impact on CPU usage and latency.\n *           It's recommended to \"load once, use many times\", to amortize the cost\n *  Note 2 :`dict` content will be copied internally, so `dict` can be released after loading.\n *           Use ZSTD_DCtx_loadDictionary_byReference() to reference dictionary content instead.\n *  Note 3 : Use ZSTD_DCtx_loadDictionary_advanced() to take control of\n *           how dictionary content is loaded and interpreted.\n */\nZSTDLIB_API size_t ZSTD_DCtx_loadDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_DCtx_refDDict() : Requires v1.4.0+\n *  Reference a prepared dictionary, to be used to decompress next frames.\n *  The dictionary remains active for decompression of future frames using same DCtx.\n *\n *  If called with ZSTD_d_refMultipleDDicts enabled, repeated calls of this function\n *  will store the DDict references in a table, and the DDict used for decompression\n *  will be determined at decompression time, as per the dict ID in the frame.\n *  The memory for the table is allocated on the first call to refDDict, and can be\n *  freed with ZSTD_freeDCtx().\n *\n *  If called with ZSTD_d_refMultipleDDicts disabled (the default), only one dictionary\n *  will be managed, and referencing a dictionary effectively \"discards\" any previous one.\n *\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Special: referencing a NULL DDict means \"return to no-dictionary mode\".\n *  Note 2 : DDict is just referenced, its lifetime must outlive its usage from DCtx.\n */\nZSTDLIB_API size_t ZSTD_DCtx_refDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);\n\n/*! ZSTD_DCtx_refPrefix() : Requires v1.4.0+\n *  Reference a prefix (single-usage dictionary) to decompress next frame.\n *  This is the reverse operation of ZSTD_CCtx_refPrefix(),\n *  and must use the same prefix as the one used during compression.\n *  Prefix is **only used once**. Reference is discarded at end of frame.\n *  End of frame is reached when ZSTD_decompressStream() returns 0.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n *  Note 1 : Adding any prefix (including NULL) invalidates any previously set prefix or dictionary\n *  Note 2 : Prefix buffer is referenced. It **must** outlive decompression.\n *           Prefix buffer must remain unmodified up to the end of frame,\n *           reached when ZSTD_decompressStream() returns 0.\n *  Note 3 : By default, the prefix is treated as raw content (ZSTD_dct_rawContent).\n *           Use ZSTD_CCtx_refPrefix_advanced() to alter dictMode (Experimental section)\n *  Note 4 : Referencing a raw content prefix has almost no cpu nor memory cost.\n *           A full dictionary is more costly, as it requires building tables.\n */\nZSTDLIB_API size_t ZSTD_DCtx_refPrefix(ZSTD_DCtx* dctx,\n                                 const void* prefix, size_t prefixSize);\n\n/* ===   Memory management   === */\n\n/*! ZSTD_sizeof_*() : Requires v1.4.0+\n *  These functions give the _current_ memory usage of selected object.\n *  Note that object memory usage can evolve (increase or decrease) over time. */\nZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);\nZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);\nZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);\nZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);\nZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);\nZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif  /* ZSTD_H_235446 */\n\n\n/* **************************************************************************************\n *   ADVANCED AND EXPERIMENTAL FUNCTIONS\n ****************************************************************************************\n * The definitions in the following section are considered experimental.\n * They are provided for advanced scenarios.\n * They should never be used with a dynamic library, as prototypes may change in the future.\n * Use them only in association with static linking.\n * ***************************************************************************************/\n\n#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)\n#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* This can be overridden externally to hide static symbols. */\n#ifndef ZSTDLIB_STATIC_API\n#  if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#    define ZSTDLIB_STATIC_API __declspec(dllexport) ZSTDLIB_VISIBLE\n#  elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#    define ZSTDLIB_STATIC_API __declspec(dllimport) ZSTDLIB_VISIBLE\n#  else\n#    define ZSTDLIB_STATIC_API ZSTDLIB_VISIBLE\n#  endif\n#endif\n\n/****************************************************************************************\n *   experimental API (static linking only)\n ****************************************************************************************\n * The following symbols and constants\n * are not planned to join \"stable API\" status in the near future.\n * They can still change in future versions.\n * Some of them are planned to remain in the static_only section indefinitely.\n * Some of them might be removed in the future (especially when redundant with existing stable functions)\n * ***************************************************************************************/\n\n#define ZSTD_FRAMEHEADERSIZE_PREFIX(format) ((format) == ZSTD_f_zstd1 ? 5 : 1)   /* minimum input size required to query frame header size */\n#define ZSTD_FRAMEHEADERSIZE_MIN(format)    ((format) == ZSTD_f_zstd1 ? 6 : 2)\n#define ZSTD_FRAMEHEADERSIZE_MAX   18   /* can be useful for static allocation */\n#define ZSTD_SKIPPABLEHEADERSIZE    8\n\n/* compression parameter bounds */\n#define ZSTD_WINDOWLOG_MAX_32    30\n#define ZSTD_WINDOWLOG_MAX_64    31\n#define ZSTD_WINDOWLOG_MAX     ((int)(sizeof(size_t) == 4 ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))\n#define ZSTD_WINDOWLOG_MIN       10\n#define ZSTD_HASHLOG_MAX       ((ZSTD_WINDOWLOG_MAX < 30) ? ZSTD_WINDOWLOG_MAX : 30)\n#define ZSTD_HASHLOG_MIN          6\n#define ZSTD_CHAINLOG_MAX_32     29\n#define ZSTD_CHAINLOG_MAX_64     30\n#define ZSTD_CHAINLOG_MAX      ((int)(sizeof(size_t) == 4 ? ZSTD_CHAINLOG_MAX_32 : ZSTD_CHAINLOG_MAX_64))\n#define ZSTD_CHAINLOG_MIN        ZSTD_HASHLOG_MIN\n#define ZSTD_SEARCHLOG_MAX      (ZSTD_WINDOWLOG_MAX-1)\n#define ZSTD_SEARCHLOG_MIN        1\n#define ZSTD_MINMATCH_MAX         7   /* only for ZSTD_fast, other strategies are limited to 6 */\n#define ZSTD_MINMATCH_MIN         3   /* only for ZSTD_btopt+, faster strategies are limited to 4 */\n#define ZSTD_TARGETLENGTH_MAX    ZSTD_BLOCKSIZE_MAX\n#define ZSTD_TARGETLENGTH_MIN     0   /* note : comparing this constant to an unsigned results in a tautological test */\n#define ZSTD_STRATEGY_MIN        ZSTD_fast\n#define ZSTD_STRATEGY_MAX        ZSTD_btultra2\n#define ZSTD_BLOCKSIZE_MAX_MIN (1 << 10) /* The minimum valid max blocksize. Maximum blocksizes smaller than this make compressBound() inaccurate. */\n\n\n#define ZSTD_OVERLAPLOG_MIN       0\n#define ZSTD_OVERLAPLOG_MAX       9\n\n#define ZSTD_WINDOWLOG_LIMIT_DEFAULT 27   /* by default, the streaming decoder will refuse any frame\n                                           * requiring larger than (1<<ZSTD_WINDOWLOG_LIMIT_DEFAULT) window size,\n                                           * to preserve host's memory from unreasonable requirements.\n                                           * This limit can be overridden using ZSTD_DCtx_setParameter(,ZSTD_d_windowLogMax,).\n                                           * The limit does not apply for one-pass decoders (such as ZSTD_decompress()), since no additional memory is allocated */\n\n\n/* LDM parameter bounds */\n#define ZSTD_LDM_HASHLOG_MIN      ZSTD_HASHLOG_MIN\n#define ZSTD_LDM_HASHLOG_MAX      ZSTD_HASHLOG_MAX\n#define ZSTD_LDM_MINMATCH_MIN        4\n#define ZSTD_LDM_MINMATCH_MAX     4096\n#define ZSTD_LDM_BUCKETSIZELOG_MIN   1\n#define ZSTD_LDM_BUCKETSIZELOG_MAX   8\n#define ZSTD_LDM_HASHRATELOG_MIN     0\n#define ZSTD_LDM_HASHRATELOG_MAX (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)\n\n/* Advanced parameter bounds */\n#define ZSTD_TARGETCBLOCKSIZE_MIN   1340 /* suitable to fit into an ethernet / wifi / 4G transport frame */\n#define ZSTD_TARGETCBLOCKSIZE_MAX   ZSTD_BLOCKSIZE_MAX\n#define ZSTD_SRCSIZEHINT_MIN        0\n#define ZSTD_SRCSIZEHINT_MAX        INT_MAX\n\n\n/* ---  Advanced types  --- */\n\ntypedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params;\n\ntypedef struct {\n    unsigned int offset;      /* The offset of the match. (NOT the same as the offset code)\n                               * If offset == 0 and matchLength == 0, this sequence represents the last\n                               * literals in the block of litLength size.\n                               */\n\n    unsigned int litLength;   /* Literal length of the sequence. */\n    unsigned int matchLength; /* Match length of the sequence. */\n\n                              /* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0.\n                               * In this case, we will treat the sequence as a marker for a block boundary.\n                               */\n\n    unsigned int rep;         /* Represents which repeat offset is represented by the field 'offset'.\n                               * Ranges from [0, 3].\n                               *\n                               * Repeat offsets are essentially previous offsets from previous sequences sorted in\n                               * recency order. For more detail, see doc/zstd_compression_format.md\n                               *\n                               * If rep == 0, then 'offset' does not contain a repeat offset.\n                               * If rep > 0:\n                               *  If litLength != 0:\n                               *      rep == 1 --> offset == repeat_offset_1\n                               *      rep == 2 --> offset == repeat_offset_2\n                               *      rep == 3 --> offset == repeat_offset_3\n                               *  If litLength == 0:\n                               *      rep == 1 --> offset == repeat_offset_2\n                               *      rep == 2 --> offset == repeat_offset_3\n                               *      rep == 3 --> offset == repeat_offset_1 - 1\n                               *\n                               * Note: This field is optional. ZSTD_generateSequences() will calculate the value of\n                               * 'rep', but repeat offsets do not necessarily need to be calculated from an external\n                               * sequence provider perspective. For example, ZSTD_compressSequences() does not\n                               * use this 'rep' field at all (as of now).\n                               */\n} ZSTD_Sequence;\n\ntypedef struct {\n    unsigned windowLog;       /**< largest match distance : larger == more compression, more memory needed during decompression */\n    unsigned chainLog;        /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */\n    unsigned hashLog;         /**< dispatch table : larger == faster, more memory */\n    unsigned searchLog;       /**< nb of searches : larger == more compression, slower */\n    unsigned minMatch;        /**< match length searched : larger == faster decompression, sometimes less compression */\n    unsigned targetLength;    /**< acceptable match size for optimal parser (only) : larger == more compression, slower */\n    ZSTD_strategy strategy;   /**< see ZSTD_strategy definition above */\n} ZSTD_compressionParameters;\n\ntypedef struct {\n    int contentSizeFlag; /**< 1: content size will be in frame header (when known) */\n    int checksumFlag;    /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */\n    int noDictIDFlag;    /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */\n} ZSTD_frameParameters;\n\ntypedef struct {\n    ZSTD_compressionParameters cParams;\n    ZSTD_frameParameters fParams;\n} ZSTD_parameters;\n\ntypedef enum {\n    ZSTD_dct_auto = 0,       /* dictionary is \"full\" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is \"rawContent\" */\n    ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */\n    ZSTD_dct_fullDict = 2    /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */\n} ZSTD_dictContentType_e;\n\ntypedef enum {\n    ZSTD_dlm_byCopy = 0,  /**< Copy dictionary content internally */\n    ZSTD_dlm_byRef = 1    /**< Reference dictionary content -- the dictionary buffer must outlive its users. */\n} ZSTD_dictLoadMethod_e;\n\ntypedef enum {\n    ZSTD_f_zstd1 = 0,           /* zstd frame format, specified in zstd_compression_format.md (default) */\n    ZSTD_f_zstd1_magicless = 1  /* Variant of zstd frame format, without initial 4-bytes magic number.\n                                 * Useful to save 4 bytes per generated frame.\n                                 * Decoder cannot recognise automatically this format, requiring this instruction. */\n} ZSTD_format_e;\n\ntypedef enum {\n    /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */\n    ZSTD_d_validateChecksum = 0,\n    ZSTD_d_ignoreChecksum = 1\n} ZSTD_forceIgnoreChecksum_e;\n\ntypedef enum {\n    /* Note: this enum controls ZSTD_d_refMultipleDDicts */\n    ZSTD_rmd_refSingleDDict = 0,\n    ZSTD_rmd_refMultipleDDicts = 1\n} ZSTD_refMultipleDDicts_e;\n\ntypedef enum {\n    /* Note: this enum and the behavior it controls are effectively internal\n     * implementation details of the compressor. They are expected to continue\n     * to evolve and should be considered only in the context of extremely\n     * advanced performance tuning.\n     *\n     * Zstd currently supports the use of a CDict in three ways:\n     *\n     * - The contents of the CDict can be copied into the working context. This\n     *   means that the compression can search both the dictionary and input\n     *   while operating on a single set of internal tables. This makes\n     *   the compression faster per-byte of input. However, the initial copy of\n     *   the CDict's tables incurs a fixed cost at the beginning of the\n     *   compression. For small compressions (< 8 KB), that copy can dominate\n     *   the cost of the compression.\n     *\n     * - The CDict's tables can be used in-place. In this model, compression is\n     *   slower per input byte, because the compressor has to search two sets of\n     *   tables. However, this model incurs no start-up cost (as long as the\n     *   working context's tables can be reused). For small inputs, this can be\n     *   faster than copying the CDict's tables.\n     *\n     * - The CDict's tables are not used at all, and instead we use the working\n     *   context alone to reload the dictionary and use params based on the source\n     *   size. See ZSTD_compress_insertDictionary() and ZSTD_compress_usingDict().\n     *   This method is effective when the dictionary sizes are very small relative\n     *   to the input size, and the input size is fairly large to begin with.\n     *\n     * Zstd has a simple internal heuristic that selects which strategy to use\n     * at the beginning of a compression. However, if experimentation shows that\n     * Zstd is making poor choices, it is possible to override that choice with\n     * this enum.\n     */\n    ZSTD_dictDefaultAttach = 0, /* Use the default heuristic. */\n    ZSTD_dictForceAttach   = 1, /* Never copy the dictionary. */\n    ZSTD_dictForceCopy     = 2, /* Always copy the dictionary. */\n    ZSTD_dictForceLoad     = 3  /* Always reload the dictionary */\n} ZSTD_dictAttachPref_e;\n\ntypedef enum {\n  ZSTD_lcm_auto = 0,          /**< Automatically determine the compression mode based on the compression level.\n                               *   Negative compression levels will be uncompressed, and positive compression\n                               *   levels will be compressed. */\n  ZSTD_lcm_huffman = 1,       /**< Always attempt Huffman compression. Uncompressed literals will still be\n                               *   emitted if Huffman compression is not profitable. */\n  ZSTD_lcm_uncompressed = 2   /**< Always emit uncompressed literals. */\n} ZSTD_literalCompressionMode_e;\n\ntypedef enum {\n  /* Note: This enum controls features which are conditionally beneficial.\n   * Zstd can take a decision on whether or not to enable the feature (ZSTD_ps_auto),\n   * but setting the switch to ZSTD_ps_enable or ZSTD_ps_disable force enable/disable the feature.\n   */\n  ZSTD_ps_auto = 0,         /* Let the library automatically determine whether the feature shall be enabled */\n  ZSTD_ps_enable = 1,       /* Force-enable the feature */\n  ZSTD_ps_disable = 2       /* Do not use the feature */\n} ZSTD_ParamSwitch_e;\n#define ZSTD_paramSwitch_e ZSTD_ParamSwitch_e  /* old name */\n\n/***************************************\n*  Frame header and size functions\n***************************************/\n\n/*! ZSTD_findDecompressedSize() :\n *  `src` should point to the start of a series of ZSTD encoded and/or skippable frames\n *  `srcSize` must be the _exact_ size of this series\n *       (i.e. there should be a frame boundary at `src + srcSize`)\n *  @return : - decompressed size of all data in all successive frames\n *            - if the decompressed size cannot be determined: ZSTD_CONTENTSIZE_UNKNOWN\n *            - if an error occurred: ZSTD_CONTENTSIZE_ERROR\n *\n *   note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.\n *            When `return==ZSTD_CONTENTSIZE_UNKNOWN`, data to decompress could be any size.\n *            In which case, it's necessary to use streaming mode to decompress data.\n *   note 2 : decompressed size is always present when compression is done with ZSTD_compress()\n *   note 3 : decompressed size can be very large (64-bits value),\n *            potentially larger than what local system can handle as a single memory segment.\n *            In which case, it's necessary to use streaming mode to decompress data.\n *   note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.\n *            Always ensure result fits within application's authorized limits.\n *            Each application can set its own limits.\n *   note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to\n *            read each contained frame header.  This is fast as most of the data is skipped,\n *            however it does mean that all frame data must be present and valid. */\nZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);\n\n/*! ZSTD_decompressBound() :\n *  `src` should point to the start of a series of ZSTD encoded and/or skippable frames\n *  `srcSize` must be the _exact_ size of this series\n *       (i.e. there should be a frame boundary at `src + srcSize`)\n *  @return : - upper-bound for the decompressed size of all data in all successive frames\n *            - if an error occurred: ZSTD_CONTENTSIZE_ERROR\n *\n *  note 1  : an error can occur if `src` contains an invalid or incorrectly formatted frame.\n *  note 2  : the upper-bound is exact when the decompressed size field is available in every ZSTD encoded frame of `src`.\n *            in this case, `ZSTD_findDecompressedSize` and `ZSTD_decompressBound` return the same value.\n *  note 3  : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:\n *              upper-bound = # blocks * min(128 KB, Window_Size)\n */\nZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);\n\n/*! ZSTD_frameHeaderSize() :\n *  srcSize must be large enough, aka >= ZSTD_FRAMEHEADERSIZE_PREFIX.\n * @return : size of the Frame Header,\n *           or an error code (if srcSize is too small) */\nZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);\n\ntypedef enum { ZSTD_frame, ZSTD_skippableFrame } ZSTD_FrameType_e;\n#define ZSTD_frameType_e ZSTD_FrameType_e /* old name */\ntypedef struct {\n    unsigned long long frameContentSize; /* if == ZSTD_CONTENTSIZE_UNKNOWN, it means this field is not available. 0 means \"empty\" */\n    unsigned long long windowSize;       /* can be very large, up to <= frameContentSize */\n    unsigned blockSizeMax;\n    ZSTD_FrameType_e frameType;          /* if == ZSTD_skippableFrame, frameContentSize is the size of skippable content */\n    unsigned headerSize;\n    unsigned dictID;                     /* for ZSTD_skippableFrame, contains the skippable magic variant [0-15] */\n    unsigned checksumFlag;\n    unsigned _reserved1;\n    unsigned _reserved2;\n} ZSTD_FrameHeader;\n#define ZSTD_frameHeader ZSTD_FrameHeader /* old name */\n\n/*! ZSTD_getFrameHeader() :\n *  decode Frame Header into `zfhPtr`, or requires larger `srcSize`.\n * @return : 0 => header is complete, `zfhPtr` is correctly filled,\n *          >0 => `srcSize` is too small, @return value is the wanted `srcSize` amount, `zfhPtr` is not filled,\n *           or an error code, which can be tested using ZSTD_isError() */\nZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize);\n/*! ZSTD_getFrameHeader_advanced() :\n *  same as ZSTD_getFrameHeader(),\n *  with added capability to select a format (like ZSTD_f_zstd1_magicless) */\nZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_FrameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);\n\n/*! ZSTD_decompressionMargin() :\n * Zstd supports in-place decompression, where the input and output buffers overlap.\n * In this case, the output buffer must be at least (Margin + Output_Size) bytes large,\n * and the input buffer must be at the end of the output buffer.\n *\n *  _______________________ Output Buffer ________________________\n * |                                                              |\n * |                                        ____ Input Buffer ____|\n * |                                       |                      |\n * v                                       v                      v\n * |---------------------------------------|-----------|----------|\n * ^                                                   ^          ^\n * |___________________ Output_Size ___________________|_ Margin _|\n *\n * NOTE: See also ZSTD_DECOMPRESSION_MARGIN().\n * NOTE: This applies only to single-pass decompression through ZSTD_decompress() or\n * ZSTD_decompressDCtx().\n * NOTE: This function supports multi-frame input.\n *\n * @param src The compressed frame(s)\n * @param srcSize The size of the compressed frame(s)\n * @returns The decompression margin or an error that can be checked with ZSTD_isError().\n */\nZSTDLIB_STATIC_API size_t ZSTD_decompressionMargin(const void* src, size_t srcSize);\n\n/*! ZSTD_DECOMPRESS_MARGIN() :\n * Similar to ZSTD_decompressionMargin(), but instead of computing the margin from\n * the compressed frame, compute it from the original size and the blockSizeLog.\n * See ZSTD_decompressionMargin() for details.\n *\n * WARNING: This macro does not support multi-frame input, the input must be a single\n * zstd frame. If you need that support use the function, or implement it yourself.\n *\n * @param originalSize The original uncompressed size of the data.\n * @param blockSize    The block size == MIN(windowSize, ZSTD_BLOCKSIZE_MAX).\n *                     Unless you explicitly set the windowLog smaller than\n *                     ZSTD_BLOCKSIZELOG_MAX you can just use ZSTD_BLOCKSIZE_MAX.\n */\n#define ZSTD_DECOMPRESSION_MARGIN(originalSize, blockSize) ((size_t)(                                              \\\n        ZSTD_FRAMEHEADERSIZE_MAX                                                              /* Frame header */ + \\\n        4                                                                                         /* checksum */ + \\\n        ((originalSize) == 0 ? 0 : 3 * (((originalSize) + (blockSize) - 1) / blockSize)) /* 3 bytes per block */ + \\\n        (blockSize)                                                                    /* One block of margin */   \\\n    ))\n\ntypedef enum {\n  ZSTD_sf_noBlockDelimiters = 0,         /* ZSTD_Sequence[] has no block delimiters, just sequences */\n  ZSTD_sf_explicitBlockDelimiters = 1    /* ZSTD_Sequence[] contains explicit block delimiters */\n} ZSTD_SequenceFormat_e;\n#define ZSTD_sequenceFormat_e ZSTD_SequenceFormat_e /* old name */\n\n/*! ZSTD_sequenceBound() :\n * `srcSize` : size of the input buffer\n *  @return : upper-bound for the number of sequences that can be generated\n *            from a buffer of srcSize bytes\n *\n *  note : returns number of sequences - to get bytes, multiply by sizeof(ZSTD_Sequence).\n */\nZSTDLIB_STATIC_API size_t ZSTD_sequenceBound(size_t srcSize);\n\n/*! ZSTD_generateSequences() :\n * WARNING: This function is meant for debugging and informational purposes ONLY!\n * Its implementation is flawed, and it will be deleted in a future version.\n * It is not guaranteed to succeed, as there are several cases where it will give\n * up and fail. You should NOT use this function in production code.\n *\n * This function is deprecated, and will be removed in a future version.\n *\n * Generate sequences using ZSTD_compress2(), given a source buffer.\n *\n * @param zc The compression context to be used for ZSTD_compress2(). Set any\n *           compression parameters you need on this context.\n * @param outSeqs The output sequences buffer of size @p outSeqsSize\n * @param outSeqsCapacity The size of the output sequences buffer.\n *                    ZSTD_sequenceBound(srcSize) is an upper bound on the number\n *                    of sequences that can be generated.\n * @param src The source buffer to generate sequences from of size @p srcSize.\n * @param srcSize The size of the source buffer.\n *\n * Each block will end with a dummy sequence\n * with offset == 0, matchLength == 0, and litLength == length of last literals.\n * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0)\n * simply acts as a block delimiter.\n *\n * @returns The number of sequences generated, necessarily less than\n *          ZSTD_sequenceBound(srcSize), or an error code that can be checked\n *          with ZSTD_isError().\n */\nZSTD_DEPRECATED(\"For debugging only, will be replaced by ZSTD_extractSequences()\")\nZSTDLIB_STATIC_API size_t\nZSTD_generateSequences(ZSTD_CCtx* zc,\n                       ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n                       const void* src, size_t srcSize);\n\n/*! ZSTD_mergeBlockDelimiters() :\n * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals\n * by merging them into the literals of the next sequence.\n *\n * As such, the final generated result has no explicit representation of block boundaries,\n * and the final last literals segment is not represented in the sequences.\n *\n * The output of this function can be fed into ZSTD_compressSequences() with CCtx\n * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters\n * @return : number of sequences left after merging\n */\nZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);\n\n/*! ZSTD_compressSequences() :\n * Compress an array of ZSTD_Sequence, associated with @src buffer, into dst.\n * @src contains the entire input (not just the literals).\n * If @srcSize > sum(sequence.length), the remaining bytes are considered all literals\n * If a dictionary is included, then the cctx should reference the dict (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.).\n * The entire source is compressed into a single frame.\n *\n * The compression behavior changes based on cctx params. In particular:\n *    If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain\n *    no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on\n *    the block size derived from the cctx, and sequences may be split. This is the default setting.\n *\n *    If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain\n *    valid block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided.\n *\n *    When ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, it's possible to decide generating repcodes\n *    using the advanced parameter ZSTD_c_repcodeResolution. Repcodes will improve compression ratio, though the benefit\n *    can vary greatly depending on Sequences. On the other hand, repcode resolution is an expensive operation.\n *    By default, it's disabled at low (<10) compression levels, and enabled above the threshold (>=10).\n *    ZSTD_c_repcodeResolution makes it possible to directly manage this processing in either direction.\n *\n *    If ZSTD_c_validateSequences == 0, this function blindly accepts the Sequences provided. Invalid Sequences cause undefined\n *    behavior. If ZSTD_c_validateSequences == 1, then the function will detect invalid Sequences (see doc/zstd_compression_format.md for\n *    specifics regarding offset/matchlength requirements) and then bail out and return an error.\n *\n *    In addition to the two adjustable experimental params, there are other important cctx params.\n *    - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN.\n *    - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression.\n *    - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset\n *      is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md\n *\n * Note: Repcodes are, as of now, always re-calculated within this function, ZSTD_Sequence.rep is effectively unused.\n * Dev Note: Once ability to ingest repcodes become available, the explicit block delims mode must respect those repcodes exactly,\n *         and cannot emit an RLE block that disagrees with the repcode history.\n * @return : final compressed size, or a ZSTD error code.\n */\nZSTDLIB_STATIC_API size_t\nZSTD_compressSequences(ZSTD_CCtx* cctx,\n                       void* dst, size_t dstCapacity,\n                 const ZSTD_Sequence* inSeqs, size_t inSeqsSize,\n                 const void* src, size_t srcSize);\n\n\n/*! ZSTD_compressSequencesAndLiterals() :\n * This is a variant of ZSTD_compressSequences() which,\n * instead of receiving (src,srcSize) as input parameter, receives (literals,litSize),\n * aka all the literals, already extracted and laid out into a single continuous buffer.\n * This can be useful if the process generating the sequences also happens to generate the buffer of literals,\n * thus skipping an extraction + caching stage.\n * It's a speed optimization, useful when the right conditions are met,\n * but it also features the following limitations:\n * - Only supports explicit delimiter mode\n * - Currently does not support Sequences validation (so input Sequences are trusted)\n * - Not compatible with frame checksum, which must be disabled\n * - If any block is incompressible, will fail and return an error\n * - @litSize must be == sum of all @.litLength fields in @inSeqs. Any discrepancy will generate an error.\n * - @litBufCapacity is the size of the underlying buffer into which literals are written, starting at address @literals.\n *   @litBufCapacity must be at least 8 bytes larger than @litSize.\n * - @decompressedSize must be correct, and correspond to the sum of all Sequences. Any discrepancy will generate an error.\n * @return : final compressed size, or a ZSTD error code.\n */\nZSTDLIB_STATIC_API size_t\nZSTD_compressSequencesAndLiterals(ZSTD_CCtx* cctx,\n                                  void* dst, size_t dstCapacity,\n                            const ZSTD_Sequence* inSeqs, size_t nbSequences,\n                            const void* literals, size_t litSize, size_t litBufCapacity,\n                            size_t decompressedSize);\n\n\n/*! ZSTD_writeSkippableFrame() :\n * Generates a zstd skippable frame containing data given by src, and writes it to dst buffer.\n *\n * Skippable frames begin with a 4-byte magic number. There are 16 possible choices of magic number,\n * ranging from ZSTD_MAGIC_SKIPPABLE_START to ZSTD_MAGIC_SKIPPABLE_START+15.\n * As such, the parameter magicVariant controls the exact skippable frame magic number variant used,\n * so the magic number used will be ZSTD_MAGIC_SKIPPABLE_START + magicVariant.\n *\n * Returns an error if destination buffer is not large enough, if the source size is not representable\n * with a 4-byte unsigned int, or if the parameter magicVariant is greater than 15 (and therefore invalid).\n *\n * @return : number of bytes written or a ZSTD error.\n */\nZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,\n                                             const void* src, size_t srcSize,\n                                                   unsigned magicVariant);\n\n/*! ZSTD_readSkippableFrame() :\n * Retrieves the content of a zstd skippable frame starting at @src, and writes it to @dst buffer.\n *\n * The parameter @magicVariant will receive the magicVariant that was supplied when the frame was written,\n * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START.\n * This can be NULL if the caller is not interested in the magicVariant.\n *\n * Returns an error if destination buffer is not large enough, or if the frame is not skippable.\n *\n * @return : number of bytes written or a ZSTD error.\n */\nZSTDLIB_STATIC_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity,\n                                                  unsigned* magicVariant,\n                                                  const void* src, size_t srcSize);\n\n/*! ZSTD_isSkippableFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.\n */\nZSTDLIB_STATIC_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);\n\n\n\n/***************************************\n*  Memory management\n***************************************/\n\n/*! ZSTD_estimate*() :\n *  These functions make it possible to estimate memory usage\n *  of a future {D,C}Ctx, before its creation.\n *  This is useful in combination with ZSTD_initStatic(),\n *  which makes it possible to employ a static buffer for ZSTD_CCtx* state.\n *\n *  ZSTD_estimateCCtxSize() will provide a memory budget large enough\n *  to compress data of any size using one-shot compression ZSTD_compressCCtx() or ZSTD_compress2()\n *  associated with any compression level up to max specified one.\n *  The estimate will assume the input may be arbitrarily large,\n *  which is the worst case.\n *\n *  Note that the size estimation is specific for one-shot compression,\n *  it is not valid for streaming (see ZSTD_estimateCStreamSize*())\n *  nor other potential ways of using a ZSTD_CCtx* state.\n *\n *  When srcSize can be bound by a known and rather \"small\" value,\n *  this knowledge can be used to provide a tighter budget estimation\n *  because the ZSTD_CCtx* state will need less memory for small inputs.\n *  This tighter estimation can be provided by employing more advanced functions\n *  ZSTD_estimateCCtxSize_usingCParams(), which can be used in tandem with ZSTD_getCParams(),\n *  and ZSTD_estimateCCtxSize_usingCCtxParams(), which can be used in tandem with ZSTD_CCtxParams_setParameter().\n *  Both can be used to estimate memory using custom compression parameters and arbitrary srcSize limits.\n *\n *  Note : only single-threaded compression is supported.\n *  ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.\n */\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int maxCompressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);\n\n/*! ZSTD_estimateCStreamSize() :\n *  ZSTD_estimateCStreamSize() will provide a memory budget large enough for streaming compression\n *  using any compression level up to the max specified one.\n *  It will also consider src size to be arbitrarily \"large\", which is a worst case scenario.\n *  If srcSize is known to always be small, ZSTD_estimateCStreamSize_usingCParams() can provide a tighter estimation.\n *  ZSTD_estimateCStreamSize_usingCParams() can be used in tandem with ZSTD_getCParams() to create cParams from compressionLevel.\n *  ZSTD_estimateCStreamSize_usingCCtxParams() can be used in tandem with ZSTD_CCtxParams_setParameter(). Only single-threaded compression is supported. This function will return an error code if ZSTD_c_nbWorkers is >= 1.\n *  Note : CStream size estimation is only correct for single-threaded compression.\n *  ZSTD_estimateCStreamSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.\n *  Note 2 : ZSTD_estimateCStreamSize* functions are not compatible with the Block-Level Sequence Producer API at this time.\n *  Size estimates assume that no external sequence producer is registered.\n *\n *  ZSTD_DStream memory budget depends on frame's window Size.\n *  This information can be passed manually, using ZSTD_estimateDStreamSize,\n *  or deducted from a valid frame Header, using ZSTD_estimateDStreamSize_fromFrame();\n *  Any frame requesting a window size larger than max specified one will be rejected.\n *  Note : if streaming is init with function ZSTD_init?Stream_usingDict(),\n *         an internal ?Dict will be created, which additional size is not estimated here.\n *         In this case, get total size by adding ZSTD_estimate?DictSize\n */\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int maxCompressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t maxWindowSize);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);\n\n/*! ZSTD_estimate?DictSize() :\n *  ZSTD_estimateCDictSize() will bet that src size is relatively \"small\", and content is copied, like ZSTD_createCDict().\n *  ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().\n *  Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.\n */\nZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);\nZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);\nZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);\n\n/*! ZSTD_initStatic*() :\n *  Initialize an object using a pre-allocated fixed-size buffer.\n *  workspace: The memory area to emplace the object into.\n *             Provided pointer *must be 8-bytes aligned*.\n *             Buffer must outlive object.\n *  workspaceSize: Use ZSTD_estimate*Size() to determine\n *                 how large workspace must be to support target scenario.\n * @return : pointer to object (same address as workspace, just different type),\n *           or NULL if error (size too small, incorrect alignment, etc.)\n *  Note : zstd will never resize nor malloc() when using a static buffer.\n *         If the object requires more memory than available,\n *         zstd will just error out (typically ZSTD_error_memory_allocation).\n *  Note 2 : there is no corresponding \"free\" function.\n *           Since workspace is allocated externally, it must be freed externally too.\n *  Note 3 : cParams : use ZSTD_getCParams() to convert a compression level\n *           into its associated cParams.\n *  Limitation 1 : currently not compatible with internal dictionary creation, triggered by\n *                 ZSTD_CCtx_loadDictionary(), ZSTD_initCStream_usingDict() or ZSTD_initDStream_usingDict().\n *  Limitation 2 : static cctx currently not compatible with multi-threading.\n *  Limitation 3 : static dctx is incompatible with legacy support.\n */\nZSTDLIB_STATIC_API ZSTD_CCtx*    ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);\nZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize);    /**< same as ZSTD_initStaticCCtx() */\n\nZSTDLIB_STATIC_API ZSTD_DCtx*    ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);\nZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize);    /**< same as ZSTD_initStaticDCtx() */\n\nZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict(\n                                        void* workspace, size_t workspaceSize,\n                                        const void* dict, size_t dictSize,\n                                        ZSTD_dictLoadMethod_e dictLoadMethod,\n                                        ZSTD_dictContentType_e dictContentType,\n                                        ZSTD_compressionParameters cParams);\n\nZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict(\n                                        void* workspace, size_t workspaceSize,\n                                        const void* dict, size_t dictSize,\n                                        ZSTD_dictLoadMethod_e dictLoadMethod,\n                                        ZSTD_dictContentType_e dictContentType);\n\n\n/*! Custom memory allocation :\n *  These prototypes make it possible to pass your own allocation/free functions.\n *  ZSTD_customMem is provided at creation time, using ZSTD_create*_advanced() variants listed below.\n *  All allocation/free operations will be completed using these custom variants instead of regular <stdlib.h> ones.\n */\ntypedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);\ntypedef void  (*ZSTD_freeFunction) (void* opaque, void* address);\ntypedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;\nstatic\n#ifdef __GNUC__\n__attribute__((__unused__))\n#endif\n\n#if defined(__clang__) && __clang_major__ >= 5\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wzero-as-null-pointer-constant\"\n#endif\nZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };  /**< this constant defers to stdlib's functions */\n#if defined(__clang__) && __clang_major__ >= 5\n#pragma clang diagnostic pop\n#endif\n\nZSTDLIB_STATIC_API ZSTD_CCtx*    ZSTD_createCCtx_advanced(ZSTD_customMem customMem);\nZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);\nZSTDLIB_STATIC_API ZSTD_DCtx*    ZSTD_createDCtx_advanced(ZSTD_customMem customMem);\nZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);\n\nZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,\n                                                  ZSTD_dictLoadMethod_e dictLoadMethod,\n                                                  ZSTD_dictContentType_e dictContentType,\n                                                  ZSTD_compressionParameters cParams,\n                                                  ZSTD_customMem customMem);\n\n/*! Thread pool :\n *  These prototypes make it possible to share a thread pool among multiple compression contexts.\n *  This can limit resources for applications with multiple threads where each one uses\n *  a threaded compression mode (via ZSTD_c_nbWorkers parameter).\n *  ZSTD_createThreadPool creates a new thread pool with a given number of threads.\n *  Note that the lifetime of such pool must exist while being used.\n *  ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value\n *  to use an internal thread pool).\n *  ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.\n */\ntypedef struct POOL_ctx_s ZSTD_threadPool;\nZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);\nZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool);  /* accept NULL pointer */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);\n\n\n/*\n * This API is temporary and is expected to change or disappear in the future!\n */\nZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2(\n    const void* dict, size_t dictSize,\n    ZSTD_dictLoadMethod_e dictLoadMethod,\n    ZSTD_dictContentType_e dictContentType,\n    const ZSTD_CCtx_params* cctxParams,\n    ZSTD_customMem customMem);\n\nZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced(\n    const void* dict, size_t dictSize,\n    ZSTD_dictLoadMethod_e dictLoadMethod,\n    ZSTD_dictContentType_e dictContentType,\n    ZSTD_customMem customMem);\n\n\n/***************************************\n*  Advanced compression functions\n***************************************/\n\n/*! ZSTD_createCDict_byReference() :\n *  Create a digested dictionary for compression\n *  Dictionary content is just referenced, not duplicated.\n *  As a consequence, `dictBuffer` **must** outlive CDict,\n *  and its content must remain unmodified throughout the lifetime of CDict.\n *  note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */\nZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);\n\n/*! ZSTD_getCParams() :\n * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.\n * `estimatedSrcSize` value is optional, select 0 if not known */\nZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);\n\n/*! ZSTD_getParams() :\n *  same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.\n *  All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */\nZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);\n\n/*! ZSTD_checkCParams() :\n *  Ensure param values remain within authorized range.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()) */\nZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);\n\n/*! ZSTD_adjustCParams() :\n *  optimize params for a given `srcSize` and `dictSize`.\n * `srcSize` can be unknown, in which case use ZSTD_CONTENTSIZE_UNKNOWN.\n * `dictSize` must be `0` when there is no dictionary.\n *  cPar can be invalid : all parameters will be clamped within valid range in the @return struct.\n *  This function never fails (wide contract) */\nZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);\n\n/*! ZSTD_CCtx_setCParams() :\n *  Set all parameters provided within @p cparams into the working @p cctx.\n *  Note : if modifying parameters during compression (MT mode only),\n *         note that changes to the .windowLog parameter will be ignored.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n *         On failure, no parameters are updated.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setCParams(ZSTD_CCtx* cctx, ZSTD_compressionParameters cparams);\n\n/*! ZSTD_CCtx_setFParams() :\n *  Set all parameters provided within @p fparams into the working @p cctx.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setFParams(ZSTD_CCtx* cctx, ZSTD_frameParameters fparams);\n\n/*! ZSTD_CCtx_setParams() :\n *  Set all parameters provided within @p params into the working @p cctx.\n * @return 0 on success, or an error code (can be checked with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParams(ZSTD_CCtx* cctx, ZSTD_parameters params);\n\n/*! ZSTD_compress_advanced() :\n *  Note : this function is now DEPRECATED.\n *         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_setParameter() and other parameter setters.\n *  This prototype will generate compilation warnings. */\nZSTD_DEPRECATED(\"use ZSTD_compress2\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compress_advanced(ZSTD_CCtx* cctx,\n                              void* dst, size_t dstCapacity,\n                        const void* src, size_t srcSize,\n                        const void* dict,size_t dictSize,\n                              ZSTD_parameters params);\n\n/*! ZSTD_compress_usingCDict_advanced() :\n *  Note : this function is now DEPRECATED.\n *         It can be replaced by ZSTD_compress2(), in combination with ZSTD_CCtx_loadDictionary() and other parameter setters.\n *  This prototype will generate compilation warnings. */\nZSTD_DEPRECATED(\"use ZSTD_compress2 with ZSTD_CCtx_loadDictionary\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,\n                                              void* dst, size_t dstCapacity,\n                                        const void* src, size_t srcSize,\n                                        const ZSTD_CDict* cdict,\n                                              ZSTD_frameParameters fParams);\n\n\n/*! ZSTD_CCtx_loadDictionary_byReference() :\n *  Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.\n *  It saves some memory, but also requires that `dict` outlives its usage within `cctx` */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_CCtx_loadDictionary_advanced() :\n *  Same as ZSTD_CCtx_loadDictionary(), but gives finer control over\n *  how to load the dictionary (by copy ? by reference ?)\n *  and how to interpret it (automatic ? force raw mode ? full mode only ?) */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);\n\n/*! ZSTD_CCtx_refPrefix_advanced() :\n *  Same as ZSTD_CCtx_refPrefix(), but gives finer control over\n *  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);\n\n/* ===   experimental parameters   === */\n/* these parameters can be used with ZSTD_setParameter()\n * they are not guaranteed to remain supported in the future */\n\n /* Enables rsyncable mode,\n  * which makes compressed files more rsync friendly\n  * by adding periodic synchronization points to the compressed data.\n  * The target average block size is ZSTD_c_jobSize / 2.\n  * It's possible to modify the job size to increase or decrease\n  * the granularity of the synchronization point.\n  * Once the jobSize is smaller than the window size,\n  * it will result in compression ratio degradation.\n  * NOTE 1: rsyncable mode only works when multithreading is enabled.\n  * NOTE 2: rsyncable performs poorly in combination with long range mode,\n  * since it will decrease the effectiveness of synchronization points,\n  * though mileage may vary.\n  * NOTE 3: Rsyncable mode limits maximum compression speed to ~400 MB/s.\n  * If the selected compression level is already running significantly slower,\n  * the overall speed won't be significantly impacted.\n  */\n #define ZSTD_c_rsyncable ZSTD_c_experimentalParam1\n\n/* Select a compression format.\n * The value must be of type ZSTD_format_e.\n * See ZSTD_format_e enum definition for details */\n#define ZSTD_c_format ZSTD_c_experimentalParam2\n\n/* Force back-reference distances to remain < windowSize,\n * even when referencing into Dictionary content (default:0) */\n#define ZSTD_c_forceMaxWindow ZSTD_c_experimentalParam3\n\n/* Controls whether the contents of a CDict\n * are used in place, or copied into the working context.\n * Accepts values from the ZSTD_dictAttachPref_e enum.\n * See the comments on that enum for an explanation of the feature. */\n#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4\n\n/* Controlled with ZSTD_ParamSwitch_e enum.\n * Default is ZSTD_ps_auto.\n * Set to ZSTD_ps_disable to never compress literals.\n * Set to ZSTD_ps_enable to always compress literals. (Note: uncompressed literals\n * may still be emitted if huffman is not beneficial to use.)\n *\n * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use\n * literals compression based on the compression parameters - specifically,\n * negative compression levels do not use literal compression.\n */\n#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5\n\n/* User's best guess of source size.\n * Hint is not valid when srcSizeHint == 0.\n * There is no guarantee that hint is close to actual source size,\n * but compression ratio may regress significantly if guess considerably underestimates */\n#define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7\n\n/* Controls whether the new and experimental \"dedicated dictionary search\n * structure\" can be used. This feature is still rough around the edges, be\n * prepared for surprising behavior!\n *\n * How to use it:\n *\n * When using a CDict, whether to use this feature or not is controlled at\n * CDict creation, and it must be set in a CCtxParams set passed into that\n * construction (via ZSTD_createCDict_advanced2()). A compression will then\n * use the feature or not based on how the CDict was constructed; the value of\n * this param, set in the CCtx, will have no effect.\n *\n * However, when a dictionary buffer is passed into a CCtx, such as via\n * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control\n * whether the CDict that is created internally can use the feature or not.\n *\n * What it does:\n *\n * Normally, the internal data structures of the CDict are analogous to what\n * would be stored in a CCtx after compressing the contents of a dictionary.\n * To an approximation, a compression using a dictionary can then use those\n * data structures to simply continue what is effectively a streaming\n * compression where the simulated compression of the dictionary left off.\n * Which is to say, the search structures in the CDict are normally the same\n * format as in the CCtx.\n *\n * It is possible to do better, since the CDict is not like a CCtx: the search\n * structures are written once during CDict creation, and then are only read\n * after that, while the search structures in the CCtx are both read and\n * written as the compression goes along. This means we can choose a search\n * structure for the dictionary that is read-optimized.\n *\n * This feature enables the use of that different structure.\n *\n * Note that some of the members of the ZSTD_compressionParameters struct have\n * different semantics and constraints in the dedicated search structure. It is\n * highly recommended that you simply set a compression level in the CCtxParams\n * you pass into the CDict creation call, and avoid messing with the cParams\n * directly.\n *\n * Effects:\n *\n * This will only have any effect when the selected ZSTD_strategy\n * implementation supports this feature. Currently, that's limited to\n * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2.\n *\n * Note that this means that the CDict tables can no longer be copied into the\n * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be\n * usable. The dictionary can only be attached or reloaded.\n *\n * In general, you should expect compression to be faster--sometimes very much\n * so--and CDict creation to be slightly slower. Eventually, we will probably\n * make this mode the default.\n */\n#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8\n\n/* ZSTD_c_stableInBuffer\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Tells the compressor that input data presented with ZSTD_inBuffer\n * will ALWAYS be the same between calls.\n * Technically, the @src pointer must never be changed,\n * and the @pos field can only be updated by zstd.\n * However, it's possible to increase the @size field,\n * allowing scenarios where more data can be appended after compressions starts.\n * These conditions are checked by the compressor,\n * and compression will fail if they are not respected.\n * Also, data in the ZSTD_inBuffer within the range [src, src + pos)\n * MUST not be modified during compression or it will result in data corruption.\n *\n * When this flag is enabled zstd won't allocate an input window buffer,\n * because the user guarantees it can reference the ZSTD_inBuffer until\n * the frame is complete. But, it will still allocate an output buffer\n * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also\n * avoid the memcpy() from the input buffer to the input window buffer.\n *\n * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using\n * this flag is ALWAYS memory safe, and will never access out-of-bounds\n * memory. However, compression WILL fail if conditions are not respected.\n *\n * WARNING: The data in the ZSTD_inBuffer in the range [src, src + pos) MUST\n * not be modified during compression or it will result in data corruption.\n * This is because zstd needs to reference data in the ZSTD_inBuffer to find\n * matches. Normally zstd maintains its own window buffer for this purpose,\n * but passing this flag tells zstd to rely on user provided buffer instead.\n */\n#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9\n\n/* ZSTD_c_stableOutBuffer\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Tells he compressor that the ZSTD_outBuffer will not be resized between\n * calls. Specifically: (out.size - out.pos) will never grow. This gives the\n * compressor the freedom to say: If the compressed data doesn't fit in the\n * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to\n * always decompress directly into the output buffer, instead of decompressing\n * into an internal buffer and copying to the output buffer.\n *\n * When this flag is enabled zstd won't allocate an output buffer, because\n * it can write directly to the ZSTD_outBuffer. It will still allocate the\n * input window buffer (see ZSTD_c_stableInBuffer).\n *\n * Zstd will check that (out.size - out.pos) never grows and return an error\n * if it does. While not strictly necessary, this should prevent surprises.\n */\n#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10\n\n/* ZSTD_c_blockDelimiters\n * Default is 0 == ZSTD_sf_noBlockDelimiters.\n *\n * For use with sequence compression API: ZSTD_compressSequences().\n *\n * Designates whether or not the given array of ZSTD_Sequence contains block delimiters\n * and last literals, which are defined as sequences with offset == 0 and matchLength == 0.\n * See the definition of ZSTD_Sequence for more specifics.\n */\n#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11\n\n/* ZSTD_c_validateSequences\n * Default is 0 == disabled. Set to 1 to enable sequence validation.\n *\n * For use with sequence compression API: ZSTD_compressSequences*().\n * Designates whether or not provided sequences are validated within ZSTD_compressSequences*()\n * during function execution.\n *\n * When Sequence validation is disabled (default), Sequences are compressed as-is,\n * so they must correct, otherwise it would result in a corruption error.\n *\n * Sequence validation adds some protection, by ensuring that all values respect boundary conditions.\n * If a Sequence is detected invalid (see doc/zstd_compression_format.md for\n * specifics regarding offset/matchlength requirements) then the function will bail out and\n * return an error.\n */\n#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12\n\n/* ZSTD_c_blockSplitterLevel\n * note: this parameter only influences the first splitter stage,\n *       which is active before producing the sequences.\n *       ZSTD_c_splitAfterSequences controls the next splitter stage,\n *       which is active after sequence production.\n *       Note that both can be combined.\n * Allowed values are between 0 and ZSTD_BLOCKSPLITTER_LEVEL_MAX included.\n * 0 means \"auto\", which will select a value depending on current ZSTD_c_strategy.\n * 1 means no splitting.\n * Then, values from 2 to 6 are sorted in increasing cpu load order.\n *\n * Note that currently the first block is never split,\n * to ensure expansion guarantees in presence of incompressible data.\n */\n#define ZSTD_BLOCKSPLITTER_LEVEL_MAX 6\n#define ZSTD_c_blockSplitterLevel ZSTD_c_experimentalParam20\n\n/* ZSTD_c_splitAfterSequences\n * This is a stronger splitter algorithm,\n * based on actual sequences previously produced by the selected parser.\n * It's also slower, and as a consequence, mostly used for high compression levels.\n * While the post-splitter does overlap with the pre-splitter,\n * both can nonetheless be combined,\n * notably with ZSTD_c_blockSplitterLevel at ZSTD_BLOCKSPLITTER_LEVEL_MAX,\n * resulting in higher compression ratio than just one of them.\n *\n * Default is ZSTD_ps_auto.\n * Set to ZSTD_ps_disable to never use block splitter.\n * Set to ZSTD_ps_enable to always use block splitter.\n *\n * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use\n * block splitting based on the compression parameters.\n */\n#define ZSTD_c_splitAfterSequences ZSTD_c_experimentalParam13\n\n/* ZSTD_c_useRowMatchFinder\n * Controlled with ZSTD_ParamSwitch_e enum.\n * Default is ZSTD_ps_auto.\n * Set to ZSTD_ps_disable to never use row-based matchfinder.\n * Set to ZSTD_ps_enable to force usage of row-based matchfinder.\n *\n * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use\n * the row-based matchfinder based on support for SIMD instructions and the window log.\n * Note that this only pertains to compression strategies: greedy, lazy, and lazy2\n */\n#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14\n\n/* ZSTD_c_deterministicRefPrefix\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Zstd produces different results for prefix compression when the prefix is\n * directly adjacent to the data about to be compressed vs. when it isn't.\n * This is because zstd detects that the two buffers are contiguous and it can\n * use a more efficient match finding algorithm. However, this produces different\n * results than when the two buffers are non-contiguous. This flag forces zstd\n * to always load the prefix in non-contiguous mode, even if it happens to be\n * adjacent to the data, to guarantee determinism.\n *\n * If you really care about determinism when using a dictionary or prefix,\n * like when doing delta compression, you should select this option. It comes\n * at a speed penalty of about ~2.5% if the dictionary and data happened to be\n * contiguous, and is free if they weren't contiguous. We don't expect that\n * intentionally making the dictionary and data contiguous will be worth the\n * cost to memcpy() the data.\n */\n#define ZSTD_c_deterministicRefPrefix ZSTD_c_experimentalParam15\n\n/* ZSTD_c_prefetchCDictTables\n * Controlled with ZSTD_ParamSwitch_e enum. Default is ZSTD_ps_auto.\n *\n * In some situations, zstd uses CDict tables in-place rather than copying them\n * into the working context. (See docs on ZSTD_dictAttachPref_e above for details).\n * In such situations, compression speed is seriously impacted when CDict tables are\n * \"cold\" (outside CPU cache). This parameter instructs zstd to prefetch CDict tables\n * when they are used in-place.\n *\n * For sufficiently small inputs, the cost of the prefetch will outweigh the benefit.\n * For sufficiently large inputs, zstd will by default memcpy() CDict tables\n * into the working context, so there is no need to prefetch. This parameter is\n * targeted at a middle range of input sizes, where a prefetch is cheap enough to be\n * useful but memcpy() is too expensive. The exact range of input sizes where this\n * makes sense is best determined by careful experimentation.\n *\n * Note: for this parameter, ZSTD_ps_auto is currently equivalent to ZSTD_ps_disable,\n * but in the future zstd may conditionally enable this feature via an auto-detection\n * heuristic for cold CDicts.\n * Use ZSTD_ps_disable to opt out of prefetching under any circumstances.\n */\n#define ZSTD_c_prefetchCDictTables ZSTD_c_experimentalParam16\n\n/* ZSTD_c_enableSeqProducerFallback\n * Allowed values are 0 (disable) and 1 (enable). The default setting is 0.\n *\n * Controls whether zstd will fall back to an internal sequence producer if an\n * external sequence producer is registered and returns an error code. This fallback\n * is block-by-block: the internal sequence producer will only be called for blocks\n * where the external sequence producer returns an error code. Fallback parsing will\n * follow any other cParam settings, such as compression level, the same as in a\n * normal (fully-internal) compression operation.\n *\n * The user is strongly encouraged to read the full Block-Level Sequence Producer API\n * documentation (below) before setting this parameter. */\n#define ZSTD_c_enableSeqProducerFallback ZSTD_c_experimentalParam17\n\n/* ZSTD_c_maxBlockSize\n * Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB).\n * The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default.\n *\n * This parameter can be used to set an upper bound on the blocksize\n * that overrides the default ZSTD_BLOCKSIZE_MAX. It cannot be used to set upper\n * bounds greater than ZSTD_BLOCKSIZE_MAX or bounds lower than 1KB (will make\n * compressBound() inaccurate). Only currently meant to be used for testing.\n */\n#define ZSTD_c_maxBlockSize ZSTD_c_experimentalParam18\n\n/* ZSTD_c_repcodeResolution\n * This parameter only has an effect if ZSTD_c_blockDelimiters is\n * set to ZSTD_sf_explicitBlockDelimiters (may change in the future).\n *\n * This parameter affects how zstd parses external sequences,\n * provided via the ZSTD_compressSequences*() API\n * or from an external block-level sequence producer.\n *\n * If set to ZSTD_ps_enable, the library will check for repeated offsets within\n * external sequences, even if those repcodes are not explicitly indicated in\n * the \"rep\" field. Note that this is the only way to exploit repcode matches\n * while using compressSequences*() or an external sequence producer, since zstd\n * currently ignores the \"rep\" field of external sequences.\n *\n * If set to ZSTD_ps_disable, the library will not exploit repeated offsets in\n * external sequences, regardless of whether the \"rep\" field has been set. This\n * reduces sequence compression overhead by about 25% while sacrificing some\n * compression ratio.\n *\n * The default value is ZSTD_ps_auto, for which the library will enable/disable\n * based on compression level (currently: level<10 disables, level>=10 enables).\n */\n#define ZSTD_c_repcodeResolution ZSTD_c_experimentalParam19\n#define ZSTD_c_searchForExternalRepcodes ZSTD_c_experimentalParam19 /* older name */\n\n\n/*! ZSTD_CCtx_getParameter() :\n *  Get the requested compression parameter value, selected by enum ZSTD_cParameter,\n *  and store it into int* value.\n * @return : 0, or an error code (which can be tested with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);\n\n\n/*! ZSTD_CCtx_params :\n *  Quick howto :\n *  - ZSTD_createCCtxParams() : Create a ZSTD_CCtx_params structure\n *  - ZSTD_CCtxParams_setParameter() : Push parameters one by one into\n *                                     an existing ZSTD_CCtx_params structure.\n *                                     This is similar to\n *                                     ZSTD_CCtx_setParameter().\n *  - ZSTD_CCtx_setParametersUsingCCtxParams() : Apply parameters to\n *                                    an existing CCtx.\n *                                    These parameters will be applied to\n *                                    all subsequent frames.\n *  - ZSTD_compressStream2() : Do compression using the CCtx.\n *  - ZSTD_freeCCtxParams() : Free the memory, accept NULL pointer.\n *\n *  This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()\n *  for static allocation of CCtx for single-threaded compression.\n */\nZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);\nZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params);  /* accept NULL pointer */\n\n/*! ZSTD_CCtxParams_reset() :\n *  Reset params to default values.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);\n\n/*! ZSTD_CCtxParams_init() :\n *  Initializes the compression parameters of cctxParams according to\n *  compression level. All other parameters are reset to their default values.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);\n\n/*! ZSTD_CCtxParams_init_advanced() :\n *  Initializes the compression and frame parameters of cctxParams according to\n *  params. All other parameters are reset to their default values.\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);\n\n/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+\n *  Similar to ZSTD_CCtx_setParameter.\n *  Set one compression parameter, selected by enum ZSTD_cParameter.\n *  Parameters must be applied to a ZSTD_CCtx using\n *  ZSTD_CCtx_setParametersUsingCCtxParams().\n * @result : a code representing success or failure (which can be tested with\n *           ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);\n\n/*! ZSTD_CCtxParams_getParameter() :\n * Similar to ZSTD_CCtx_getParameter.\n * Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.\n * @result : 0, or an error code (which can be tested with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);\n\n/*! ZSTD_CCtx_setParametersUsingCCtxParams() :\n *  Apply a set of ZSTD_CCtx_params to the compression context.\n *  This can be done even after compression is started,\n *    if nbWorkers==0, this will have no impact until a new compression is started.\n *    if nbWorkers>=1, new parameters will be picked up at next job,\n *       with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).\n */\nZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(\n        ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);\n\n/*! ZSTD_compressStream2_simpleArgs() :\n *  Same as ZSTD_compressStream2(),\n *  but using only integral types as arguments.\n *  This variant might be helpful for binders from dynamic languages\n *  which have troubles handling structures containing memory pointers.\n */\nZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs (\n                            ZSTD_CCtx* cctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos,\n                            ZSTD_EndDirective endOp);\n\n\n/***************************************\n*  Advanced decompression functions\n***************************************/\n\n/*! ZSTD_isFrame() :\n *  Tells if the content of `buffer` starts with a valid Frame Identifier.\n *  Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.\n *  Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.\n *  Note 3 : Skippable Frame Identifiers are considered valid. */\nZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size);\n\n/*! ZSTD_createDDict_byReference() :\n *  Create a digested dictionary, ready to start decompression operation without startup delay.\n *  Dictionary content is referenced, and therefore stays in dictBuffer.\n *  It is important that dictBuffer outlives DDict,\n *  it must remain read accessible throughout the lifetime of DDict */\nZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);\n\n/*! ZSTD_DCtx_loadDictionary_byReference() :\n *  Same as ZSTD_DCtx_loadDictionary(),\n *  but references `dict` content instead of copying it into `dctx`.\n *  This saves memory if `dict` remains around.,\n *  However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\n\n/*! ZSTD_DCtx_loadDictionary_advanced() :\n *  Same as ZSTD_DCtx_loadDictionary(),\n *  but gives direct control over\n *  how to load the dictionary (by copy ? by reference ?)\n *  and how to interpret it (automatic ? force raw mode ? full mode only ?). */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);\n\n/*! ZSTD_DCtx_refPrefix_advanced() :\n *  Same as ZSTD_DCtx_refPrefix(), but gives finer control over\n *  how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);\n\n/*! ZSTD_DCtx_setMaxWindowSize() :\n *  Refuses allocating internal buffers for frames requiring a window size larger than provided limit.\n *  This protects a decoder context from reserving too much memory for itself (potential attack scenario).\n *  This parameter is only useful in streaming mode, since no internal buffer is allocated in single-pass mode.\n *  By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)\n * @return : 0, or an error code (which can be tested using ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);\n\n/*! ZSTD_DCtx_getParameter() :\n *  Get the requested decompression parameter value, selected by enum ZSTD_dParameter,\n *  and store it into int* value.\n * @return : 0, or an error code (which can be tested with ZSTD_isError()).\n */\nZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);\n\n/* ZSTD_d_format\n * experimental parameter,\n * allowing selection between ZSTD_format_e input compression formats\n */\n#define ZSTD_d_format ZSTD_d_experimentalParam1\n/* ZSTD_d_stableOutBuffer\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable.\n *\n * Tells the decompressor that the ZSTD_outBuffer will ALWAYS be the same\n * between calls, except for the modifications that zstd makes to pos (the\n * caller must not modify pos). This is checked by the decompressor, and\n * decompression will fail if it ever changes. Therefore the ZSTD_outBuffer\n * MUST be large enough to fit the entire decompressed frame. This will be\n * checked when the frame content size is known. The data in the ZSTD_outBuffer\n * in the range [dst, dst + pos) MUST not be modified during decompression\n * or you will get data corruption.\n *\n * When this flag is enabled zstd won't allocate an output buffer, because\n * it can write directly to the ZSTD_outBuffer, but it will still allocate\n * an input buffer large enough to fit any compressed block. This will also\n * avoid the memcpy() from the internal output buffer to the ZSTD_outBuffer.\n * If you need to avoid the input buffer allocation use the buffer-less\n * streaming API.\n *\n * NOTE: So long as the ZSTD_outBuffer always points to valid memory, using\n * this flag is ALWAYS memory safe, and will never access out-of-bounds\n * memory. However, decompression WILL fail if you violate the preconditions.\n *\n * WARNING: The data in the ZSTD_outBuffer in the range [dst, dst + pos) MUST\n * not be modified during decompression or you will get data corruption. This\n * is because zstd needs to reference data in the ZSTD_outBuffer to regenerate\n * matches. Normally zstd maintains its own buffer for this purpose, but passing\n * this flag tells zstd to use the user provided buffer.\n */\n#define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2\n\n/* ZSTD_d_forceIgnoreChecksum\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable\n *\n * Tells the decompressor to skip checksum validation during decompression, regardless\n * of whether checksumming was specified during compression. This offers some\n * slight performance benefits, and may be useful for debugging.\n * Param has values of type ZSTD_forceIgnoreChecksum_e\n */\n#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3\n\n/* ZSTD_d_refMultipleDDicts\n * Experimental parameter.\n * Default is 0 == disabled. Set to 1 to enable\n *\n * If enabled and dctx is allocated on the heap, then additional memory will be allocated\n * to store references to multiple ZSTD_DDict. That is, multiple calls of ZSTD_refDDict()\n * using a given ZSTD_DCtx, rather than overwriting the previous DDict reference, will instead\n * store all references. At decompression time, the appropriate dictID is selected\n * from the set of DDicts based on the dictID in the frame.\n *\n * Usage is simply calling ZSTD_refDDict() on multiple dict buffers.\n *\n * Param has values of byte ZSTD_refMultipleDDicts_e\n *\n * WARNING: Enabling this parameter and calling ZSTD_DCtx_refDDict(), will trigger memory\n * allocation for the hash table. ZSTD_freeDCtx() also frees this memory.\n * Memory is allocated as per ZSTD_DCtx::customMem.\n *\n * Although this function allocates memory for the table, the user is still responsible for\n * memory management of the underlying ZSTD_DDict* themselves.\n */\n#define ZSTD_d_refMultipleDDicts ZSTD_d_experimentalParam4\n\n/* ZSTD_d_disableHuffmanAssembly\n * Set to 1 to disable the Huffman assembly implementation.\n * The default value is 0, which allows zstd to use the Huffman assembly\n * implementation if available.\n *\n * This parameter can be used to disable Huffman assembly at runtime.\n * If you want to disable it at compile time you can define the macro\n * ZSTD_DISABLE_ASM.\n */\n#define ZSTD_d_disableHuffmanAssembly ZSTD_d_experimentalParam5\n\n/* ZSTD_d_maxBlockSize\n * Allowed values are between 1KB and ZSTD_BLOCKSIZE_MAX (128KB).\n * The default is ZSTD_BLOCKSIZE_MAX, and setting to 0 will set to the default.\n *\n * Forces the decompressor to reject blocks whose content size is\n * larger than the configured maxBlockSize. When maxBlockSize is\n * larger than the windowSize, the windowSize is used instead.\n * This saves memory on the decoder when you know all blocks are small.\n *\n * This option is typically used in conjunction with ZSTD_c_maxBlockSize.\n *\n * WARNING: This causes the decoder to reject otherwise valid frames\n * that have block sizes larger than the configured maxBlockSize.\n */\n#define ZSTD_d_maxBlockSize ZSTD_d_experimentalParam6\n\n\n/*! ZSTD_DCtx_setFormat() :\n *  This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().\n *  Instruct the decoder context about what kind of data to decode next.\n *  This instruction is mandatory to decode data without a fully-formed header,\n *  such ZSTD_f_zstd1_magicless for example.\n * @return : 0, or an error code (which can be tested using ZSTD_isError()). */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_setParameter() instead\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);\n\n/*! ZSTD_decompressStream_simpleArgs() :\n *  Same as ZSTD_decompressStream(),\n *  but using only integral types as arguments.\n *  This can be helpful for binders from dynamic languages\n *  which have troubles handling structures containing memory pointers.\n */\nZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs (\n                            ZSTD_DCtx* dctx,\n                            void* dst, size_t dstCapacity, size_t* dstPos,\n                      const void* src, size_t srcSize, size_t* srcPos);\n\n\n/********************************************************************\n*  Advanced streaming functions\n*  Warning : most of these functions are now redundant with the Advanced API.\n*  Once Advanced API reaches \"stable\" status,\n*  redundant functions will be deprecated, and then at some point removed.\n********************************************************************/\n\n/*=====   Advanced Streaming compression functions  =====*/\n\n/*! ZSTD_initCStream_srcSize() :\n * This function is DEPRECATED, and equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any)\n *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n *\n * pledgedSrcSize must be correct. If it is not known at init time, use\n * ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs,\n * \"0\" also disables frame content size field. It may be enabled in the future.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs,\n                         int compressionLevel,\n                         unsigned long long pledgedSrcSize);\n\n/*! ZSTD_initCStream_usingDict() :\n * This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel);\n *     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);\n *\n * Creates of an internal CDict (incompatible with static CCtx), except if\n * dict == NULL or dictSize < 8, in which case no dict is used.\n * Note: dict is loaded with ZSTD_dct_auto (treated as a full zstd dictionary if\n * it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs,\n                     const void* dict, size_t dictSize,\n                           int compressionLevel);\n\n/*! ZSTD_initCStream_advanced() :\n * This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setParams(zcs, params);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n *     ZSTD_CCtx_loadDictionary(zcs, dict, dictSize);\n *\n * dict is loaded with ZSTD_dct_auto and ZSTD_dlm_byCopy.\n * pledgedSrcSize must be correct.\n * If srcSize is not known at init time, use value ZSTD_CONTENTSIZE_UNKNOWN.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,\n                    const void* dict, size_t dictSize,\n                          ZSTD_parameters params,\n                          unsigned long long pledgedSrcSize);\n\n/*! ZSTD_initCStream_usingCDict() :\n * This function is DEPRECATED, and equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_refCDict(zcs, cdict);\n *\n * note : cdict will just be referenced, and must outlive compression session\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict);\n\n/*! ZSTD_initCStream_usingCDict_advanced() :\n *   This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setFParams(zcs, fParams);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n *     ZSTD_CCtx_refCDict(zcs, cdict);\n *\n * same as ZSTD_initCStream_usingCDict(), with control over frame parameters.\n * pledgedSrcSize must be correct. If srcSize is not known at init time, use\n * value ZSTD_CONTENTSIZE_UNKNOWN.\n * This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset and ZSTD_CCtx_refCDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_initCStream_usingCDict_advanced(ZSTD_CStream* zcs,\n                               const ZSTD_CDict* cdict,\n                                     ZSTD_frameParameters fParams,\n                                     unsigned long long pledgedSrcSize);\n\n/*! ZSTD_resetCStream() :\n * This function is DEPRECATED, and is equivalent to:\n *     ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);\n *     ZSTD_CCtx_setPledgedSrcSize(zcs, pledgedSrcSize);\n * Note: ZSTD_resetCStream() interprets pledgedSrcSize == 0 as ZSTD_CONTENTSIZE_UNKNOWN, but\n *       ZSTD_CCtx_setPledgedSrcSize() does not do the same, so ZSTD_CONTENTSIZE_UNKNOWN must be\n *       explicitly specified.\n *\n *  start a new frame, using same parameters from previous frame.\n *  This is typically useful to skip dictionary loading stage, since it will reuse it in-place.\n *  Note that zcs must be init at least once before using ZSTD_resetCStream().\n *  If pledgedSrcSize is not known at reset time, use macro ZSTD_CONTENTSIZE_UNKNOWN.\n *  If pledgedSrcSize > 0, its value must be correct, as it will be written in header, and controlled at the end.\n *  For the time being, pledgedSrcSize==0 is interpreted as \"srcSize unknown\" for compatibility with older programs,\n *  but it will change to mean \"empty\" in future version, so use macro ZSTD_CONTENTSIZE_UNKNOWN instead.\n * @return : 0, or an error code (which can be tested using ZSTD_isError())\n *  This prototype will generate compilation warnings.\n */\nZSTD_DEPRECATED(\"use ZSTD_CCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize);\n\n\ntypedef struct {\n    unsigned long long ingested;   /* nb input bytes read and buffered */\n    unsigned long long consumed;   /* nb input bytes actually compressed */\n    unsigned long long produced;   /* nb of compressed bytes generated and buffered */\n    unsigned long long flushed;    /* nb of compressed bytes flushed : not provided; can be tracked from caller side */\n    unsigned currentJobID;         /* MT only : latest started job nb */\n    unsigned nbActiveWorkers;      /* MT only : nb of workers actively compressing at probe time */\n} ZSTD_frameProgression;\n\n/* ZSTD_getFrameProgression() :\n * tells how much data has been ingested (read from input)\n * consumed (input actually compressed) and produced (output) for current frame.\n * Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed.\n * Aggregates progression inside active worker threads.\n */\nZSTDLIB_STATIC_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);\n\n/*! ZSTD_toFlushNow() :\n *  Tell how many bytes are ready to be flushed immediately.\n *  Useful for multithreading scenarios (nbWorkers >= 1).\n *  Probe the oldest active job, defined as oldest job not yet entirely flushed,\n *  and check its output buffer.\n * @return : amount of data stored in oldest job and ready to be flushed immediately.\n *  if @return == 0, it means either :\n *  + there is no active job (could be checked with ZSTD_frameProgression()), or\n *  + oldest job is still actively compressing data,\n *    but everything it has produced has also been flushed so far,\n *    therefore flush speed is limited by production speed of oldest job\n *    irrespective of the speed of concurrent (and newer) jobs.\n */\nZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);\n\n\n/*=====   Advanced Streaming decompression functions  =====*/\n\n/*!\n * This function is deprecated, and is equivalent to:\n *\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *     ZSTD_DCtx_loadDictionary(zds, dict, dictSize);\n *\n * note: no dictionary will be used if dict == NULL or dictSize < 8\n */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_reset + ZSTD_DCtx_loadDictionary, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);\n\n/*!\n * This function is deprecated, and is equivalent to:\n *\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *     ZSTD_DCtx_refDDict(zds, ddict);\n *\n * note : ddict is referenced, it must outlive decompression session\n */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_reset + ZSTD_DCtx_refDDict, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);\n\n/*!\n * This function is deprecated, and is equivalent to:\n *\n *     ZSTD_DCtx_reset(zds, ZSTD_reset_session_only);\n *\n * reuse decompression parameters from previous init; saves dictionary loading\n */\nZSTD_DEPRECATED(\"use ZSTD_DCtx_reset, see zstd.h for detailed instructions\")\nZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);\n\n\n/* ********************* BLOCK-LEVEL SEQUENCE PRODUCER API *********************\n *\n * *** OVERVIEW ***\n * The Block-Level Sequence Producer API allows users to provide their own custom\n * sequence producer which libzstd invokes to process each block. The produced list\n * of sequences (literals and matches) is then post-processed by libzstd to produce\n * valid compressed blocks.\n *\n * This block-level offload API is a more granular complement of the existing\n * frame-level offload API compressSequences() (introduced in v1.5.1). It offers\n * an easier migration story for applications already integrated with libzstd: the\n * user application continues to invoke the same compression functions\n * ZSTD_compress2() or ZSTD_compressStream2() as usual, and transparently benefits\n * from the specific advantages of the external sequence producer. For example,\n * the sequence producer could be tuned to take advantage of known characteristics\n * of the input, to offer better speed / ratio, or could leverage hardware\n * acceleration not available within libzstd itself.\n *\n * See contrib/externalSequenceProducer for an example program employing the\n * Block-Level Sequence Producer API.\n *\n * *** USAGE ***\n * The user is responsible for implementing a function of type\n * ZSTD_sequenceProducer_F. For each block, zstd will pass the following\n * arguments to the user-provided function:\n *\n *   - sequenceProducerState: a pointer to a user-managed state for the sequence\n *     producer.\n *\n *   - outSeqs, outSeqsCapacity: an output buffer for the sequence producer.\n *     outSeqsCapacity is guaranteed >= ZSTD_sequenceBound(srcSize). The memory\n *     backing outSeqs is managed by the CCtx.\n *\n *   - src, srcSize: an input buffer for the sequence producer to parse.\n *     srcSize is guaranteed to be <= ZSTD_BLOCKSIZE_MAX.\n *\n *   - dict, dictSize: a history buffer, which may be empty, which the sequence\n *     producer may reference as it parses the src buffer. Currently, zstd will\n *     always pass dictSize == 0 into external sequence producers, but this will\n *     change in the future.\n *\n *   - compressionLevel: a signed integer representing the zstd compression level\n *     set by the user for the current operation. The sequence producer may choose\n *     to use this information to change its compression strategy and speed/ratio\n *     tradeoff. Note: the compression level does not reflect zstd parameters set\n *     through the advanced API.\n *\n *   - windowSize: a size_t representing the maximum allowed offset for external\n *     sequences. Note that sequence offsets are sometimes allowed to exceed the\n *     windowSize if a dictionary is present, see doc/zstd_compression_format.md\n *     for details.\n *\n * The user-provided function shall return a size_t representing the number of\n * sequences written to outSeqs. This return value will be treated as an error\n * code if it is greater than outSeqsCapacity. The return value must be non-zero\n * if srcSize is non-zero. The ZSTD_SEQUENCE_PRODUCER_ERROR macro is provided\n * for convenience, but any value greater than outSeqsCapacity will be treated as\n * an error code.\n *\n * If the user-provided function does not return an error code, the sequences\n * written to outSeqs must be a valid parse of the src buffer. Data corruption may\n * occur if the parse is not valid. A parse is defined to be valid if the\n * following conditions hold:\n *   - The sum of matchLengths and literalLengths must equal srcSize.\n *   - All sequences in the parse, except for the final sequence, must have\n *     matchLength >= ZSTD_MINMATCH_MIN. The final sequence must have\n *     matchLength >= ZSTD_MINMATCH_MIN or matchLength == 0.\n *   - All offsets must respect the windowSize parameter as specified in\n *     doc/zstd_compression_format.md.\n *   - If the final sequence has matchLength == 0, it must also have offset == 0.\n *\n * zstd will only validate these conditions (and fail compression if they do not\n * hold) if the ZSTD_c_validateSequences cParam is enabled. Note that sequence\n * validation has a performance cost.\n *\n * If the user-provided function returns an error, zstd will either fall back\n * to an internal sequence producer or fail the compression operation. The user can\n * choose between the two behaviors by setting the ZSTD_c_enableSeqProducerFallback\n * cParam. Fallback compression will follow any other cParam settings, such as\n * compression level, the same as in a normal compression operation.\n *\n * The user shall instruct zstd to use a particular ZSTD_sequenceProducer_F\n * function by calling\n *         ZSTD_registerSequenceProducer(cctx,\n *                                       sequenceProducerState,\n *                                       sequenceProducer)\n * This setting will persist until the next parameter reset of the CCtx.\n *\n * The sequenceProducerState must be initialized by the user before calling\n * ZSTD_registerSequenceProducer(). The user is responsible for destroying the\n * sequenceProducerState.\n *\n * *** LIMITATIONS ***\n * This API is compatible with all zstd compression APIs which respect advanced parameters.\n * However, there are three limitations:\n *\n * First, the ZSTD_c_enableLongDistanceMatching cParam is not currently supported.\n * COMPRESSION WILL FAIL if it is enabled and the user tries to compress with a block-level\n * external sequence producer.\n *   - Note that ZSTD_c_enableLongDistanceMatching is auto-enabled by default in some\n *     cases (see its documentation for details). Users must explicitly set\n *     ZSTD_c_enableLongDistanceMatching to ZSTD_ps_disable in such cases if an external\n *     sequence producer is registered.\n *   - As of this writing, ZSTD_c_enableLongDistanceMatching is disabled by default\n *     whenever ZSTD_c_windowLog < 128MB, but that's subject to change. Users should\n *     check the docs on ZSTD_c_enableLongDistanceMatching whenever the Block-Level Sequence\n *     Producer API is used in conjunction with advanced settings (like ZSTD_c_windowLog).\n *\n * Second, history buffers are not currently supported. Concretely, zstd will always pass\n * dictSize == 0 to the external sequence producer (for now). This has two implications:\n *   - Dictionaries are not currently supported. Compression will *not* fail if the user\n *     references a dictionary, but the dictionary won't have any effect.\n *   - Stream history is not currently supported. All advanced compression APIs, including\n *     streaming APIs, work with external sequence producers, but each block is treated as\n *     an independent chunk without history from previous blocks.\n *\n * Third, multi-threading within a single compression is not currently supported. In other words,\n * COMPRESSION WILL FAIL if ZSTD_c_nbWorkers > 0 and an external sequence producer is registered.\n * Multi-threading across compressions is fine: simply create one CCtx per thread.\n *\n * Long-term, we plan to overcome all three limitations. There is no technical blocker to\n * overcoming them. It is purely a question of engineering effort.\n */\n\n#define ZSTD_SEQUENCE_PRODUCER_ERROR ((size_t)(-1))\n\ntypedef size_t (*ZSTD_sequenceProducer_F) (\n  void* sequenceProducerState,\n  ZSTD_Sequence* outSeqs, size_t outSeqsCapacity,\n  const void* src, size_t srcSize,\n  const void* dict, size_t dictSize,\n  int compressionLevel,\n  size_t windowSize\n);\n\n/*! ZSTD_registerSequenceProducer() :\n * Instruct zstd to use a block-level external sequence producer function.\n *\n * The sequenceProducerState must be initialized by the caller, and the caller is\n * responsible for managing its lifetime. This parameter is sticky across\n * compressions. It will remain set until the user explicitly resets compression\n * parameters.\n *\n * Sequence producer registration is considered to be an \"advanced parameter\",\n * part of the \"advanced API\". This means it will only have an effect on compression\n * APIs which respect advanced parameters, such as compress2() and compressStream2().\n * Older compression APIs such as compressCCtx(), which predate the introduction of\n * \"advanced parameters\", will ignore any external sequence producer setting.\n *\n * The sequence producer can be \"cleared\" by registering a NULL function pointer. This\n * removes all limitations described above in the \"LIMITATIONS\" section of the API docs.\n *\n * The user is strongly encouraged to read the full API documentation (above) before\n * calling this function. */\nZSTDLIB_STATIC_API void\nZSTD_registerSequenceProducer(\n  ZSTD_CCtx* cctx,\n  void* sequenceProducerState,\n  ZSTD_sequenceProducer_F sequenceProducer\n);\n\n/*! ZSTD_CCtxParams_registerSequenceProducer() :\n * Same as ZSTD_registerSequenceProducer(), but operates on ZSTD_CCtx_params.\n * This is used for accurate size estimation with ZSTD_estimateCCtxSize_usingCCtxParams(),\n * which is needed when creating a ZSTD_CCtx with ZSTD_initStaticCCtx().\n *\n * If you are using the external sequence producer API in a scenario where ZSTD_initStaticCCtx()\n * is required, then this function is for you. Otherwise, you probably don't need it.\n *\n * See tests/zstreamtest.c for example usage. */\nZSTDLIB_STATIC_API void\nZSTD_CCtxParams_registerSequenceProducer(\n  ZSTD_CCtx_params* params,\n  void* sequenceProducerState,\n  ZSTD_sequenceProducer_F sequenceProducer\n);\n\n\n/*********************************************************************\n*  Buffer-less and synchronous inner streaming functions (DEPRECATED)\n*\n*  This API is deprecated, and will be removed in a future version.\n*  It allows streaming (de)compression with user allocated buffers.\n*  However, it is hard to use, and not as well tested as the rest of\n*  our API.\n*\n*  Please use the normal streaming API instead: ZSTD_compressStream2,\n*  and ZSTD_decompressStream.\n*  If there is functionality that you need, but it doesn't provide,\n*  please open an issue on our GitHub.\n********************************************************************* */\n\n/**\n  Buffer-less streaming compression (synchronous mode)\n\n  A ZSTD_CCtx object is required to track streaming operations.\n  Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.\n  ZSTD_CCtx object can be reused multiple times within successive compression operations.\n\n  Start by initializing a context.\n  Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression.\n\n  Then, consume your input using ZSTD_compressContinue().\n  There are some important considerations to keep in mind when using this advanced function :\n  - ZSTD_compressContinue() has no internal buffer. It uses externally provided buffers only.\n  - Interface is synchronous : input is consumed entirely and produces 1+ compressed blocks.\n  - Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario.\n    Worst case evaluation is provided by ZSTD_compressBound().\n    ZSTD_compressContinue() doesn't guarantee recover after a failed compression.\n  - ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog).\n    It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks)\n  - ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps.\n    In which case, it will \"discard\" the relevant memory section from its history.\n\n  Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.\n  It's possible to use srcSize==0, in which case, it will write a final empty block to end the frame.\n  Without last block mark, frames are considered unfinished (hence corrupted) by compliant decoders.\n\n  `ZSTD_CCtx` object can be reused (ZSTD_compressBegin()) to compress again.\n*/\n\n/*=====   Buffer-less streaming compression functions  =====*/\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */\n\nZSTD_DEPRECATED(\"This function will likely be removed in a future release. It is misleading and has very limited utility.\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**<  note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */\n\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The buffer-less API is deprecated in favor of the normal streaming API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */\nZSTD_DEPRECATED(\"use advanced API to access custom parameters\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize : If srcSize is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN */\nZSTD_DEPRECATED(\"use advanced API to access custom parameters\")\nZSTDLIB_STATIC_API\nsize_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize);   /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */\n/**\n  Buffer-less streaming decompression (synchronous mode)\n\n  A ZSTD_DCtx object is required to track streaming operations.\n  Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.\n  A ZSTD_DCtx object can be reused multiple times.\n\n  First typical operation is to retrieve frame parameters, using ZSTD_getFrameHeader().\n  Frame header is extracted from the beginning of compressed frame, so providing only the frame's beginning is enough.\n  Data fragment must be large enough to ensure successful decoding.\n `ZSTD_frameHeaderSize_max` bytes is guaranteed to always be large enough.\n  result  : 0 : successful decoding, the `ZSTD_frameHeader` structure is correctly filled.\n           >0 : `srcSize` is too small, please provide at least result bytes on next attempt.\n           errorCode, which can be tested using ZSTD_isError().\n\n  It fills a ZSTD_FrameHeader structure with important information to correctly decode the frame,\n  such as the dictionary ID, content size, or maximum back-reference distance (`windowSize`).\n  Note that these values could be wrong, either because of data corruption, or because a 3rd party deliberately spoofs false information.\n  As a consequence, check that values remain within valid application range.\n  For example, do not allocate memory blindly, check that `windowSize` is within expectation.\n  Each application can set its own limits, depending on local restrictions.\n  For extended interoperability, it is recommended to support `windowSize` of at least 8 MB.\n\n  ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize` bytes.\n  ZSTD_decompressContinue() is very sensitive to contiguity,\n  if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,\n  or that previous contiguous segment is large enough to properly handle maximum back-reference distance.\n  There are multiple ways to guarantee this condition.\n\n  The most memory efficient way is to use a round buffer of sufficient size.\n  Sufficient size is determined by invoking ZSTD_decodingBufferSize_min(),\n  which can return an error code if required value is too large for current system (in 32-bits mode).\n  In a round buffer methodology, ZSTD_decompressContinue() decompresses each block next to previous one,\n  up to the moment there is not enough room left in the buffer to guarantee decoding another full block,\n  which maximum size is provided in `ZSTD_frameHeader` structure, field `blockSizeMax`.\n  At which point, decoding can resume from the beginning of the buffer.\n  Note that already decoded data stored in the buffer should be flushed before being overwritten.\n\n  There are alternatives possible, for example using two or more buffers of size `windowSize` each, though they consume more memory.\n\n  Finally, if you control the compression process, you can also ignore all buffer size rules,\n  as long as the encoder and decoder progress in \"lock-step\",\n  aka use exactly the same buffer sizes, break contiguity at the same place, etc.\n\n  Once buffers are setup, start decompression, with ZSTD_decompressBegin().\n  If decompression requires a dictionary, use ZSTD_decompressBegin_usingDict() or ZSTD_decompressBegin_usingDDict().\n\n  Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.\n  ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().\n  ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.\n\n  result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).\n  It can be zero : it just means ZSTD_decompressContinue() has decoded some metadata item.\n  It can also be an error code, which can be tested with ZSTD_isError().\n\n  A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.\n  Context can then be reset to start a new decompression.\n\n  Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType().\n  This information is not required to properly decode a frame.\n\n  == Special case : skippable frames ==\n\n  Skippable frames allow integration of user-defined data into a flow of concatenated frames.\n  Skippable frames will be ignored (skipped) by decompressor.\n  The format of skippable frames is as follows :\n  a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F\n  b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits\n  c) Frame Content - any content (User Data) of length equal to Frame Size\n  For skippable frames ZSTD_getFrameHeader() returns zfhPtr->frameType==ZSTD_skippableFrame.\n  For skippable frames ZSTD_decompressContinue() always returns 0 : it only skips the content.\n*/\n\n/*=====   Buffer-less streaming decompression functions  =====*/\n\nZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize);  /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */\n\nZSTDLIB_STATIC_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);\nZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);\nZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);\n\nZSTDLIB_STATIC_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);\nZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\n\n/* misc */\nZSTD_DEPRECATED(\"This function will likely be removed in the next minor release. It is misleading and has very limited utility.\")\nZSTDLIB_STATIC_API void   ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);\ntypedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;\nZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);\n\n\n\n\n/* ========================================= */\n/**       Block level API (DEPRECATED)       */\n/* ========================================= */\n\n/*!\n\n    This API is deprecated in favor of the regular compression API.\n    You can get the frame header down to 2 bytes by setting:\n      - ZSTD_c_format = ZSTD_f_zstd1_magicless\n      - ZSTD_c_contentSizeFlag = 0\n      - ZSTD_c_checksumFlag = 0\n      - ZSTD_c_dictIDFlag = 0\n\n    This API is not as well tested as our normal API, so we recommend not using it.\n    We will be removing it in a future version. If the normal API doesn't provide\n    the functionality you need, please open a GitHub issue.\n\n    Block functions produce and decode raw zstd blocks, without frame metadata.\n    Frame metadata cost is typically ~12 bytes, which can be non-negligible for very small blocks (< 100 bytes).\n    But users will have to take in charge needed metadata to regenerate data, such as compressed and content sizes.\n\n    A few rules to respect :\n    - Compressing and decompressing require a context structure\n      + Use ZSTD_createCCtx() and ZSTD_createDCtx()\n    - It is necessary to init context before starting\n      + compression : any ZSTD_compressBegin*() variant, including with dictionary\n      + decompression : any ZSTD_decompressBegin*() variant, including with dictionary\n    - Block size is limited, it must be <= ZSTD_getBlockSize() <= ZSTD_BLOCKSIZE_MAX == 128 KB\n      + If input is larger than a block size, it's necessary to split input data into multiple blocks\n      + For inputs larger than a single block, consider using regular ZSTD_compress() instead.\n        Frame metadata is not that costly, and quickly becomes negligible as source size grows larger than a block.\n    - When a block is considered not compressible enough, ZSTD_compressBlock() result will be 0 (zero) !\n      ===> In which case, nothing is produced into `dst` !\n      + User __must__ test for such outcome and deal directly with uncompressed data\n      + A block cannot be declared incompressible if ZSTD_compressBlock() return value was != 0.\n        Doing so would mess up with statistics history, leading to potential data corruption.\n      + ZSTD_decompressBlock() _doesn't accept uncompressed data as input_ !!\n      + In case of multiple successive blocks, should some of them be uncompressed,\n        decoder must be informed of their existence in order to follow proper history.\n        Use ZSTD_insertBlock() for such a case.\n*/\n\n/*=====   Raw zstd block functions  =====*/\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_getBlockSize   (const ZSTD_CCtx* cctx);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_compressBlock  (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);\nZSTD_DEPRECATED(\"The block API is deprecated in favor of the normal compression API. See docs.\")\nZSTDLIB_STATIC_API size_t ZSTD_insertBlock    (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize);  /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif   /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */\n"
  },
  {
    "path": "NanaZip.Codecs/Zstandard/zstd_errors.h",
    "content": "﻿/*\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n * All rights reserved.\n *\n * This source code is licensed under both the BSD-style license (found in the\n * LICENSE file in the root directory of this source tree) and the GPLv2 (found\n * in the COPYING file in the root directory of this source tree).\n * You may select, at your option, one of the above-listed licenses.\n */\n\n#ifndef ZSTD_ERRORS_H_398273423\n#define ZSTD_ERRORS_H_398273423\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* =====   ZSTDERRORLIB_API : control library symbols visibility   ===== */\n#ifndef ZSTDERRORLIB_VISIBLE\n   /* Backwards compatibility with old macro name */\n#  ifdef ZSTDERRORLIB_VISIBILITY\n#    define ZSTDERRORLIB_VISIBLE ZSTDERRORLIB_VISIBILITY\n#  elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDERRORLIB_VISIBLE __attribute__ ((visibility (\"default\")))\n#  else\n#    define ZSTDERRORLIB_VISIBLE\n#  endif\n#endif\n\n#ifndef ZSTDERRORLIB_HIDDEN\n#  if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)\n#    define ZSTDERRORLIB_HIDDEN __attribute__ ((visibility (\"hidden\")))\n#  else\n#    define ZSTDERRORLIB_HIDDEN\n#  endif\n#endif\n\n#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)\n#  define ZSTDERRORLIB_API __declspec(dllexport) ZSTDERRORLIB_VISIBLE\n#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)\n#  define ZSTDERRORLIB_API __declspec(dllimport) ZSTDERRORLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/\n#else\n#  define ZSTDERRORLIB_API ZSTDERRORLIB_VISIBLE\n#endif\n\n/*-*********************************************\n *  Error codes list\n *-*********************************************\n *  Error codes _values_ are pinned down since v1.3.1 only.\n *  Therefore, don't rely on values if you may link to any version < v1.3.1.\n *\n *  Only values < 100 are considered stable.\n *\n *  note 1 : this API shall be used with static linking only.\n *           dynamic linking is not yet officially supported.\n *  note 2 : Prefer relying on the enum than on its value whenever possible\n *           This is the only supported way to use the error list < v1.3.1\n *  note 3 : ZSTD_isError() is always correct, whatever the library version.\n **********************************************/\ntypedef enum {\n  ZSTD_error_no_error = 0,\n  ZSTD_error_GENERIC  = 1,\n  ZSTD_error_prefix_unknown                = 10,\n  ZSTD_error_version_unsupported           = 12,\n  ZSTD_error_frameParameter_unsupported    = 14,\n  ZSTD_error_frameParameter_windowTooLarge = 16,\n  ZSTD_error_corruption_detected = 20,\n  ZSTD_error_checksum_wrong      = 22,\n  ZSTD_error_literals_headerWrong = 24,\n  ZSTD_error_dictionary_corrupted      = 30,\n  ZSTD_error_dictionary_wrong          = 32,\n  ZSTD_error_dictionaryCreation_failed = 34,\n  ZSTD_error_parameter_unsupported   = 40,\n  ZSTD_error_parameter_combination_unsupported = 41,\n  ZSTD_error_parameter_outOfBound    = 42,\n  ZSTD_error_tableLog_tooLarge       = 44,\n  ZSTD_error_maxSymbolValue_tooLarge = 46,\n  ZSTD_error_maxSymbolValue_tooSmall = 48,\n  ZSTD_error_cannotProduce_uncompressedBlock = 49,\n  ZSTD_error_stabilityCondition_notRespected = 50,\n  ZSTD_error_stage_wrong       = 60,\n  ZSTD_error_init_missing      = 62,\n  ZSTD_error_memory_allocation = 64,\n  ZSTD_error_workSpace_tooSmall= 66,\n  ZSTD_error_dstSize_tooSmall = 70,\n  ZSTD_error_srcSize_wrong    = 72,\n  ZSTD_error_dstBuffer_null   = 74,\n  ZSTD_error_noForwardProgress_destFull = 80,\n  ZSTD_error_noForwardProgress_inputEmpty = 82,\n  /* following error codes are __NOT STABLE__, they can be removed or changed in future versions */\n  ZSTD_error_frameIndex_tooLarge = 100,\n  ZSTD_error_seekableIO          = 102,\n  ZSTD_error_dstBuffer_wrong     = 104,\n  ZSTD_error_srcBuffer_wrong     = 105,\n  ZSTD_error_sequenceProducer_failed = 106,\n  ZSTD_error_externalSequences_invalid = 107,\n  ZSTD_error_maxCode = 120  /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */\n} ZSTD_ErrorCode;\n\nZSTDERRORLIB_API const char* ZSTD_getErrorString(ZSTD_ErrorCode code);   /**< Same as ZSTD_getErrorName, but using a `ZSTD_ErrorCode` enum argument */\n\n\n#if defined (__cplusplus)\n}\n#endif\n\n#endif /* ZSTD_ERRORS_H_398273423 */\n"
  },
  {
    "path": "NanaZip.Codecs/xxHash/xxhash.c",
    "content": "﻿/*\n * xxHash - Extremely Fast Hash algorithm\n * Copyright (C) 2012-2023 Yann Collet\n *\n * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *    * Redistributions of source code must retain the above copyright\n *      notice, this list of conditions and the following disclaimer.\n *    * Redistributions in binary form must reproduce the above\n *      copyright notice, this list of conditions and the following disclaimer\n *      in the documentation and/or other materials provided with the\n *      distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * You can contact the author at:\n *   - xxHash homepage: https://www.xxhash.com\n *   - xxHash source repository: https://github.com/Cyan4973/xxHash\n */\n\n/*\n * xxhash.c instantiates functions defined in xxhash.h\n */\n\n#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */\n#define XXH_IMPLEMENTATION      /* access definitions */\n\n#include \"xxhash.h\"\n"
  },
  {
    "path": "NanaZip.Codecs/xxHash/xxhash.h",
    "content": "﻿/*\n * xxHash - Extremely Fast Hash algorithm\n * Header File\n * Copyright (C) 2012-2023 Yann Collet\n *\n * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n *    * Redistributions of source code must retain the above copyright\n *      notice, this list of conditions and the following disclaimer.\n *    * Redistributions in binary form must reproduce the above\n *      copyright notice, this list of conditions and the following disclaimer\n *      in the documentation and/or other materials provided with the\n *      distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * You can contact the author at:\n *   - xxHash homepage: https://www.xxhash.com\n *   - xxHash source repository: https://github.com/Cyan4973/xxHash\n */\n\n/*!\n * @mainpage xxHash\n *\n * xxHash is an extremely fast non-cryptographic hash algorithm, working at RAM speed\n * limits.\n *\n * It is proposed in four flavors, in three families:\n * 1. @ref XXH32_family\n *   - Classic 32-bit hash function. Simple, compact, and runs on almost all\n *     32-bit and 64-bit systems.\n * 2. @ref XXH64_family\n *   - Classic 64-bit adaptation of XXH32. Just as simple, and runs well on most\n *     64-bit systems (but _not_ 32-bit systems).\n * 3. @ref XXH3_family\n *   - Modern 64-bit and 128-bit hash function family which features improved\n *     strength and performance across the board, especially on smaller data.\n *     It benefits greatly from SIMD and 64-bit without requiring it.\n *\n * Benchmarks\n * ---\n * The reference system uses an Intel i7-9700K CPU, and runs Ubuntu x64 20.04.\n * The open source benchmark program is compiled with clang v10.0 using -O3 flag.\n *\n * | Hash Name            | ISA ext | Width | Large Data Speed | Small Data Velocity |\n * | -------------------- | ------- | ----: | ---------------: | ------------------: |\n * | XXH3_64bits()        | @b AVX2 |    64 |        59.4 GB/s |               133.1 |\n * | MeowHash             | AES-NI  |   128 |        58.2 GB/s |                52.5 |\n * | XXH3_128bits()       | @b AVX2 |   128 |        57.9 GB/s |               118.1 |\n * | CLHash               | PCLMUL  |    64 |        37.1 GB/s |                58.1 |\n * | XXH3_64bits()        | @b SSE2 |    64 |        31.5 GB/s |               133.1 |\n * | XXH3_128bits()       | @b SSE2 |   128 |        29.6 GB/s |               118.1 |\n * | RAM sequential read  |         |   N/A |        28.0 GB/s |                 N/A |\n * | ahash                | AES-NI  |    64 |        22.5 GB/s |               107.2 |\n * | City64               |         |    64 |        22.0 GB/s |                76.6 |\n * | T1ha2                |         |    64 |        22.0 GB/s |                99.0 |\n * | City128              |         |   128 |        21.7 GB/s |                57.7 |\n * | FarmHash             | AES-NI  |    64 |        21.3 GB/s |                71.9 |\n * | XXH64()              |         |    64 |        19.4 GB/s |                71.0 |\n * | SpookyHash           |         |    64 |        19.3 GB/s |                53.2 |\n * | Mum                  |         |    64 |        18.0 GB/s |                67.0 |\n * | CRC32C               | SSE4.2  |    32 |        13.0 GB/s |                57.9 |\n * | XXH32()              |         |    32 |         9.7 GB/s |                71.9 |\n * | City32               |         |    32 |         9.1 GB/s |                66.0 |\n * | Blake3*              | @b AVX2 |   256 |         4.4 GB/s |                 8.1 |\n * | Murmur3              |         |    32 |         3.9 GB/s |                56.1 |\n * | SipHash*             |         |    64 |         3.0 GB/s |                43.2 |\n * | Blake3*              | @b SSE2 |   256 |         2.4 GB/s |                 8.1 |\n * | HighwayHash          |         |    64 |         1.4 GB/s |                 6.0 |\n * | FNV64                |         |    64 |         1.2 GB/s |                62.7 |\n * | Blake2*              |         |   256 |         1.1 GB/s |                 5.1 |\n * | SHA1*                |         |   160 |         0.8 GB/s |                 5.6 |\n * | MD5*                 |         |   128 |         0.6 GB/s |                 7.8 |\n * @note\n *   - Hashes which require a specific ISA extension are noted. SSE2 is also noted,\n *     even though it is mandatory on x64.\n *   - Hashes with an asterisk are cryptographic. Note that MD5 is non-cryptographic\n *     by modern standards.\n *   - Small data velocity is a rough average of algorithm's efficiency for small\n *     data. For more accurate information, see the wiki.\n *   - More benchmarks and strength tests are found on the wiki:\n *         https://github.com/Cyan4973/xxHash/wiki\n *\n * Usage\n * ------\n * All xxHash variants use a similar API. Changing the algorithm is a trivial\n * substitution.\n *\n * @pre\n *    For functions which take an input and length parameter, the following\n *    requirements are assumed:\n *    - The range from [`input`, `input + length`) is valid, readable memory.\n *      - The only exception is if the `length` is `0`, `input` may be `NULL`.\n *    - For C++, the objects must have the *TriviallyCopyable* property, as the\n *      functions access bytes directly as if it was an array of `unsigned char`.\n *\n * @anchor single_shot_example\n * **Single Shot**\n *\n * These functions are stateless functions which hash a contiguous block of memory,\n * immediately returning the result. They are the easiest and usually the fastest\n * option.\n *\n * XXH32(), XXH64(), XXH3_64bits(), XXH3_128bits()\n *\n * @code{.c}\n *   #include <string.h>\n *   #include \"xxhash.h\"\n *\n *   // Example for a function which hashes a null terminated string with XXH32().\n *   XXH32_hash_t hash_string(const char* string, XXH32_hash_t seed)\n *   {\n *       // NULL pointers are only valid if the length is zero\n *       size_t length = (string == NULL) ? 0 : strlen(string);\n *       return XXH32(string, length, seed);\n *   }\n * @endcode\n *\n *\n * @anchor streaming_example\n * **Streaming**\n *\n * These groups of functions allow incremental hashing of unknown size, even\n * more than what would fit in a size_t.\n *\n * XXH32_reset(), XXH64_reset(), XXH3_64bits_reset(), XXH3_128bits_reset()\n *\n * @code{.c}\n *   #include <stdio.h>\n *   #include <assert.h>\n *   #include \"xxhash.h\"\n *   // Example for a function which hashes a FILE incrementally with XXH3_64bits().\n *   XXH64_hash_t hashFile(FILE* f)\n *   {\n *       // Allocate a state struct. Do not just use malloc() or new.\n *       XXH3_state_t* state = XXH3_createState();\n *       assert(state != NULL && \"Out of memory!\");\n *       // Reset the state to start a new hashing session.\n *       XXH3_64bits_reset(state);\n *       char buffer[4096];\n *       size_t count;\n *       // Read the file in chunks\n *       while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0) {\n *           // Run update() as many times as necessary to process the data\n *           XXH3_64bits_update(state, buffer, count);\n *       }\n *       // Retrieve the finalized hash. This will not change the state.\n *       XXH64_hash_t result = XXH3_64bits_digest(state);\n *       // Free the state. Do not use free().\n *       XXH3_freeState(state);\n *       return result;\n *   }\n * @endcode\n *\n * Streaming functions generate the xxHash value from an incremental input.\n * This method is slower than single-call functions, due to state management.\n * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized.\n *\n * An XXH state must first be allocated using `XXH*_createState()`.\n *\n * Start a new hash by initializing the state with a seed using `XXH*_reset()`.\n *\n * Then, feed the hash state by calling `XXH*_update()` as many times as necessary.\n *\n * The function returns an error code, with 0 meaning OK, and any other value\n * meaning there is an error.\n *\n * Finally, a hash value can be produced anytime, by using `XXH*_digest()`.\n * This function returns the nn-bits hash as an int or long long.\n *\n * It's still possible to continue inserting input into the hash state after a\n * digest, and generate new hash values later on by invoking `XXH*_digest()`.\n *\n * When done, release the state using `XXH*_freeState()`.\n *\n *\n * @anchor canonical_representation_example\n * **Canonical Representation**\n *\n * The default return values from XXH functions are unsigned 32, 64 and 128 bit\n * integers.\n * This the simplest and fastest format for further post-processing.\n *\n * However, this leaves open the question of what is the order on the byte level,\n * since little and big endian conventions will store the same number differently.\n *\n * The canonical representation settles this issue by mandating big-endian\n * convention, the same convention as human-readable numbers (large digits first).\n *\n * When writing hash values to storage, sending them over a network, or printing\n * them, it's highly recommended to use the canonical representation to ensure\n * portability across a wider range of systems, present and future.\n *\n * The following functions allow transformation of hash values to and from\n * canonical format.\n *\n * XXH32_canonicalFromHash(), XXH32_hashFromCanonical(),\n * XXH64_canonicalFromHash(), XXH64_hashFromCanonical(),\n * XXH128_canonicalFromHash(), XXH128_hashFromCanonical(),\n *\n * @code{.c}\n *   #include <stdio.h>\n *   #include \"xxhash.h\"\n *\n *   // Example for a function which prints XXH32_hash_t in human readable format\n *   void printXxh32(XXH32_hash_t hash)\n *   {\n *       XXH32_canonical_t cano;\n *       XXH32_canonicalFromHash(&cano, hash);\n *       size_t i;\n *       for(i = 0; i < sizeof(cano.digest); ++i) {\n *           printf(\"%02x\", cano.digest[i]);\n *       }\n *       printf(\"\\n\");\n *   }\n *\n *   // Example for a function which converts XXH32_canonical_t to XXH32_hash_t\n *   XXH32_hash_t convertCanonicalToXxh32(XXH32_canonical_t cano)\n *   {\n *       XXH32_hash_t hash = XXH32_hashFromCanonical(&cano);\n *       return hash;\n *   }\n * @endcode\n *\n *\n * @file xxhash.h\n * xxHash prototypes and implementation\n */\n\n#if defined (__cplusplus)\nextern \"C\" {\n#endif\n\n/* ****************************\n *  INLINE mode\n ******************************/\n/*!\n * @defgroup public Public API\n * Contains details on the public xxHash functions.\n * @{\n */\n#ifdef XXH_DOXYGEN\n/*!\n * @brief Gives access to internal state declaration, required for static allocation.\n *\n * Incompatible with dynamic linking, due to risks of ABI changes.\n *\n * Usage:\n * @code{.c}\n *     #define XXH_STATIC_LINKING_ONLY\n *     #include \"xxhash.h\"\n * @endcode\n */\n#  define XXH_STATIC_LINKING_ONLY\n/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */\n\n/*!\n * @brief Gives access to internal definitions.\n *\n * Usage:\n * @code{.c}\n *     #define XXH_STATIC_LINKING_ONLY\n *     #define XXH_IMPLEMENTATION\n *     #include \"xxhash.h\"\n * @endcode\n */\n#  define XXH_IMPLEMENTATION\n/* Do not undef XXH_IMPLEMENTATION for Doxygen */\n\n/*!\n * @brief Exposes the implementation and marks all functions as `inline`.\n *\n * Use these build macros to inline xxhash into the target unit.\n * Inlining improves performance on small inputs, especially when the length is\n * expressed as a compile-time constant:\n *\n *  https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html\n *\n * It also keeps xxHash symbols private to the unit, so they are not exported.\n *\n * Usage:\n * @code{.c}\n *     #define XXH_INLINE_ALL\n *     #include \"xxhash.h\"\n * @endcode\n * Do not compile and link xxhash.o as a separate object, as it is not useful.\n */\n#  define XXH_INLINE_ALL\n#  undef XXH_INLINE_ALL\n/*!\n * @brief Exposes the implementation without marking functions as inline.\n */\n#  define XXH_PRIVATE_API\n#  undef XXH_PRIVATE_API\n/*!\n * @brief Emulate a namespace by transparently prefixing all symbols.\n *\n * If you want to include _and expose_ xxHash functions from within your own\n * library, but also want to avoid symbol collisions with other libraries which\n * may also include xxHash, you can use @ref XXH_NAMESPACE to automatically prefix\n * any public symbol from xxhash library with the value of @ref XXH_NAMESPACE\n * (therefore, avoid empty or numeric values).\n *\n * Note that no change is required within the calling program as long as it\n * includes `xxhash.h`: Regular symbol names will be automatically translated\n * by this header.\n */\n#  define XXH_NAMESPACE /* YOUR NAME HERE */\n#  undef XXH_NAMESPACE\n#endif\n\n#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \\\n    && !defined(XXH_INLINE_ALL_31684351384)\n   /* this section should be traversed only once */\n#  define XXH_INLINE_ALL_31684351384\n   /* give access to the advanced API, required to compile implementations */\n#  undef XXH_STATIC_LINKING_ONLY   /* avoid macro redef */\n#  define XXH_STATIC_LINKING_ONLY\n   /* make all functions private */\n#  undef XXH_PUBLIC_API\n#  if defined(__GNUC__)\n#    define XXH_PUBLIC_API static __inline __attribute__((__unused__))\n#  elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)\n#    define XXH_PUBLIC_API static inline\n#  elif defined(_MSC_VER)\n#    define XXH_PUBLIC_API static __inline\n#  else\n     /* note: this version may generate warnings for unused static functions */\n#    define XXH_PUBLIC_API static\n#  endif\n\n   /*\n    * This part deals with the special case where a unit wants to inline xxHash,\n    * but \"xxhash.h\" has previously been included without XXH_INLINE_ALL,\n    * such as part of some previously included *.h header file.\n    * Without further action, the new include would just be ignored,\n    * and functions would effectively _not_ be inlined (silent failure).\n    * The following macros solve this situation by prefixing all inlined names,\n    * avoiding naming collision with previous inclusions.\n    */\n   /* Before that, we unconditionally #undef all symbols,\n    * in case they were already defined with XXH_NAMESPACE.\n    * They will then be redefined for XXH_INLINE_ALL\n    */\n#  undef XXH_versionNumber\n    /* XXH32 */\n#  undef XXH32\n#  undef XXH32_createState\n#  undef XXH32_freeState\n#  undef XXH32_reset\n#  undef XXH32_update\n#  undef XXH32_digest\n#  undef XXH32_copyState\n#  undef XXH32_canonicalFromHash\n#  undef XXH32_hashFromCanonical\n    /* XXH64 */\n#  undef XXH64\n#  undef XXH64_createState\n#  undef XXH64_freeState\n#  undef XXH64_reset\n#  undef XXH64_update\n#  undef XXH64_digest\n#  undef XXH64_copyState\n#  undef XXH64_canonicalFromHash\n#  undef XXH64_hashFromCanonical\n    /* XXH3_64bits */\n#  undef XXH3_64bits\n#  undef XXH3_64bits_withSecret\n#  undef XXH3_64bits_withSeed\n#  undef XXH3_64bits_withSecretandSeed\n#  undef XXH3_createState\n#  undef XXH3_freeState\n#  undef XXH3_copyState\n#  undef XXH3_64bits_reset\n#  undef XXH3_64bits_reset_withSeed\n#  undef XXH3_64bits_reset_withSecret\n#  undef XXH3_64bits_update\n#  undef XXH3_64bits_digest\n#  undef XXH3_generateSecret\n    /* XXH3_128bits */\n#  undef XXH128\n#  undef XXH3_128bits\n#  undef XXH3_128bits_withSeed\n#  undef XXH3_128bits_withSecret\n#  undef XXH3_128bits_reset\n#  undef XXH3_128bits_reset_withSeed\n#  undef XXH3_128bits_reset_withSecret\n#  undef XXH3_128bits_reset_withSecretandSeed\n#  undef XXH3_128bits_update\n#  undef XXH3_128bits_digest\n#  undef XXH128_isEqual\n#  undef XXH128_cmp\n#  undef XXH128_canonicalFromHash\n#  undef XXH128_hashFromCanonical\n    /* Finally, free the namespace itself */\n#  undef XXH_NAMESPACE\n\n    /* employ the namespace for XXH_INLINE_ALL */\n#  define XXH_NAMESPACE XXH_INLINE_\n   /*\n    * Some identifiers (enums, type names) are not symbols,\n    * but they must nonetheless be renamed to avoid redeclaration.\n    * Alternative solution: do not redeclare them.\n    * However, this requires some #ifdefs, and has a more dispersed impact.\n    * Meanwhile, renaming can be achieved in a single place.\n    */\n#  define XXH_IPREF(Id)   XXH_NAMESPACE ## Id\n#  define XXH_OK XXH_IPREF(XXH_OK)\n#  define XXH_ERROR XXH_IPREF(XXH_ERROR)\n#  define XXH_errorcode XXH_IPREF(XXH_errorcode)\n#  define XXH32_canonical_t  XXH_IPREF(XXH32_canonical_t)\n#  define XXH64_canonical_t  XXH_IPREF(XXH64_canonical_t)\n#  define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t)\n#  define XXH32_state_s XXH_IPREF(XXH32_state_s)\n#  define XXH32_state_t XXH_IPREF(XXH32_state_t)\n#  define XXH64_state_s XXH_IPREF(XXH64_state_s)\n#  define XXH64_state_t XXH_IPREF(XXH64_state_t)\n#  define XXH3_state_s  XXH_IPREF(XXH3_state_s)\n#  define XXH3_state_t  XXH_IPREF(XXH3_state_t)\n#  define XXH128_hash_t XXH_IPREF(XXH128_hash_t)\n   /* Ensure the header is parsed again, even if it was previously included */\n#  undef XXHASH_H_5627135585666179\n#  undef XXHASH_H_STATIC_13879238742\n#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */\n\n/* ****************************************************************\n *  Stable API\n *****************************************************************/\n#ifndef XXHASH_H_5627135585666179\n#define XXHASH_H_5627135585666179 1\n\n/*! @brief Marks a global symbol. */\n#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)\n#  if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))\n#    ifdef XXH_EXPORT\n#      define XXH_PUBLIC_API __declspec(dllexport)\n#    elif XXH_IMPORT\n#      define XXH_PUBLIC_API __declspec(dllimport)\n#    endif\n#  else\n#    define XXH_PUBLIC_API   /* do nothing */\n#  endif\n#endif\n\n#ifdef XXH_NAMESPACE\n#  define XXH_CAT(A,B) A##B\n#  define XXH_NAME2(A,B) XXH_CAT(A,B)\n#  define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)\n/* XXH32 */\n#  define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)\n#  define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)\n#  define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)\n#  define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)\n#  define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)\n#  define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)\n#  define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)\n#  define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)\n#  define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)\n/* XXH64 */\n#  define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)\n#  define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)\n#  define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)\n#  define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)\n#  define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)\n#  define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)\n#  define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)\n#  define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)\n#  define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)\n/* XXH3_64bits */\n#  define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits)\n#  define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret)\n#  define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed)\n#  define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed)\n#  define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState)\n#  define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState)\n#  define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState)\n#  define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset)\n#  define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed)\n#  define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret)\n#  define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed)\n#  define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update)\n#  define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest)\n#  define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret)\n#  define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed)\n/* XXH3_128bits */\n#  define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128)\n#  define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits)\n#  define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed)\n#  define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret)\n#  define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed)\n#  define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset)\n#  define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed)\n#  define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret)\n#  define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed)\n#  define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update)\n#  define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest)\n#  define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual)\n#  define XXH128_cmp     XXH_NAME2(XXH_NAMESPACE, XXH128_cmp)\n#  define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash)\n#  define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical)\n#endif\n\n\n/* *************************************\n*  Compiler specifics\n***************************************/\n\n/* specific declaration modes for Windows */\n#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)\n#  if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))\n#    ifdef XXH_EXPORT\n#      define XXH_PUBLIC_API __declspec(dllexport)\n#    elif XXH_IMPORT\n#      define XXH_PUBLIC_API __declspec(dllimport)\n#    endif\n#  else\n#    define XXH_PUBLIC_API   /* do nothing */\n#  endif\n#endif\n\n#if defined (__GNUC__)\n# define XXH_CONSTF  __attribute__((__const__))\n# define XXH_PUREF   __attribute__((__pure__))\n# define XXH_MALLOCF __attribute__((__malloc__))\n#else\n# define XXH_CONSTF  /* disable */\n# define XXH_PUREF\n# define XXH_MALLOCF\n#endif\n\n/* *************************************\n*  Version\n***************************************/\n#define XXH_VERSION_MAJOR    0\n#define XXH_VERSION_MINOR    8\n#define XXH_VERSION_RELEASE  3\n/*! @brief Version number, encoded as two digits each */\n#define XXH_VERSION_NUMBER  (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)\n\n/*!\n * @brief Obtains the xxHash version.\n *\n * This is mostly useful when xxHash is compiled as a shared library,\n * since the returned value comes from the library, as opposed to header file.\n *\n * @return @ref XXH_VERSION_NUMBER of the invoked library.\n */\nXXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber (void);\n\n\n/* ****************************\n*  Common basic types\n******************************/\n#include <stddef.h>   /* size_t */\n/*!\n * @brief Exit code for the streaming API.\n */\ntypedef enum {\n    XXH_OK = 0, /*!< OK */\n    XXH_ERROR   /*!< Error */\n} XXH_errorcode;\n\n\n/*-**********************************************************************\n*  32-bit hash\n************************************************************************/\n#if defined(XXH_DOXYGEN) /* Don't show <stdint.h> include */\n/*!\n * @brief An unsigned 32-bit integer.\n *\n * Not necessarily defined to `uint32_t` but functionally equivalent.\n */\ntypedef uint32_t XXH32_hash_t;\n\n#elif !defined (__VMS) \\\n  && (defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n#   ifdef _AIX\n#     include <inttypes.h>\n#   else\n#     include <stdint.h>\n#   endif\n    typedef uint32_t XXH32_hash_t;\n\n#else\n#   include <limits.h>\n#   if UINT_MAX == 0xFFFFFFFFUL\n      typedef unsigned int XXH32_hash_t;\n#   elif ULONG_MAX == 0xFFFFFFFFUL\n      typedef unsigned long XXH32_hash_t;\n#   else\n#     error \"unsupported platform: need a 32-bit type\"\n#   endif\n#endif\n\n/*!\n * @}\n *\n * @defgroup XXH32_family XXH32 family\n * @ingroup public\n * Contains functions used in the classic 32-bit xxHash algorithm.\n *\n * @note\n *   XXH32 is useful for older platforms, with no or poor 64-bit performance.\n *   Note that the @ref XXH3_family provides competitive speed for both 32-bit\n *   and 64-bit systems, and offers true 64/128 bit hash results.\n *\n * @see @ref XXH64_family, @ref XXH3_family : Other xxHash families\n * @see @ref XXH32_impl for implementation details\n * @{\n */\n\n/*!\n * @brief Calculates the 32-bit hash of @p input using xxHash32.\n *\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n * @param seed The 32-bit seed to alter the hash's output predictably.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 32-bit xxHash32 value.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed);\n\n#ifndef XXH_NO_STREAM\n/*!\n * @typedef struct XXH32_state_s XXH32_state_t\n * @brief The opaque state struct for the XXH32 streaming API.\n *\n * @see XXH32_state_s for details.\n * @see @ref streaming_example \"Streaming Example\"\n */\ntypedef struct XXH32_state_s XXH32_state_t;\n\n/*!\n * @brief Allocates an @ref XXH32_state_t.\n *\n * @return An allocated pointer of @ref XXH32_state_t on success.\n * @return `NULL` on failure.\n *\n * @note Must be freed with XXH32_freeState().\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_MALLOCF XXH32_state_t* XXH32_createState(void);\n/*!\n * @brief Frees an @ref XXH32_state_t.\n *\n * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState().\n *\n * @return @ref XXH_OK.\n *\n * @note @p statePtr must be allocated with XXH32_createState().\n *\n * @see @ref streaming_example \"Streaming Example\"\n *\n */\nXXH_PUBLIC_API XXH_errorcode  XXH32_freeState(XXH32_state_t* statePtr);\n/*!\n * @brief Copies one @ref XXH32_state_t to another.\n *\n * @param dst_state The state to copy to.\n * @param src_state The state to copy from.\n * @pre\n *   @p dst_state and @p src_state must not be `NULL` and must not overlap.\n */\nXXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state);\n\n/*!\n * @brief Resets an @ref XXH32_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed The 32-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note This function resets and seeds a state. Call it before @ref XXH32_update().\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH32_reset  (XXH32_state_t* statePtr, XXH32_hash_t seed);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH32_state_t.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note Call this to incrementally consume blocks of data.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated hash value from an @ref XXH32_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated 32-bit xxHash32 value from that state.\n *\n * @note\n *   Calling XXH32_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n\n/*******   Canonical representation   *******/\n\n/*!\n * @brief Canonical (big endian) representation of @ref XXH32_hash_t.\n */\ntypedef struct {\n    unsigned char digest[4]; /*!< Hash bytes, big endian */\n} XXH32_canonical_t;\n\n/*!\n * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t.\n *\n * @param dst  The @ref XXH32_canonical_t pointer to be stored to.\n * @param hash The @ref XXH32_hash_t to be converted.\n *\n * @pre\n *   @p dst must not be `NULL`.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);\n\n/*!\n * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t.\n *\n * @param src The @ref XXH32_canonical_t to convert.\n *\n * @pre\n *   @p src must not be `NULL`.\n *\n * @return The converted hash.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);\n\n\n/*! @cond Doxygen ignores this part */\n#ifdef __has_attribute\n# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x)\n#else\n# define XXH_HAS_ATTRIBUTE(x) 0\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/*\n * C23 __STDC_VERSION__ number hasn't been specified yet. For now\n * leave as `201711L` (C17 + 1).\n * TODO: Update to correct value when its been specified.\n */\n#define XXH_C23_VN 201711L\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/* C-language Attributes are added in C23. */\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute)\n# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)\n#else\n# define XXH_HAS_C_ATTRIBUTE(x) 0\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n#if defined(__cplusplus) && defined(__has_cpp_attribute)\n# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)\n#else\n# define XXH_HAS_CPP_ATTRIBUTE(x) 0\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/*\n * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute\n * introduced in CPP17 and C23.\n * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough\n * C23   : https://en.cppreference.com/w/c/language/attributes/fallthrough\n */\n#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough)\n# define XXH_FALLTHROUGH [[fallthrough]]\n#elif XXH_HAS_ATTRIBUTE(__fallthrough__)\n# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__))\n#else\n# define XXH_FALLTHROUGH /* fallthrough */\n#endif\n/*! @endcond */\n\n/*! @cond Doxygen ignores this part */\n/*\n * Define XXH_NOESCAPE for annotated pointers in public API.\n * https://clang.llvm.org/docs/AttributeReference.html#noescape\n * As of writing this, only supported by clang.\n */\n#if XXH_HAS_ATTRIBUTE(noescape)\n# define XXH_NOESCAPE __attribute__((__noescape__))\n#else\n# define XXH_NOESCAPE\n#endif\n/*! @endcond */\n\n\n/*!\n * @}\n * @ingroup public\n * @{\n */\n\n#ifndef XXH_NO_LONG_LONG\n/*-**********************************************************************\n*  64-bit hash\n************************************************************************/\n#if defined(XXH_DOXYGEN) /* don't include <stdint.h> */\n/*!\n * @brief An unsigned 64-bit integer.\n *\n * Not necessarily defined to `uint64_t` but functionally equivalent.\n */\ntypedef uint64_t XXH64_hash_t;\n#elif !defined (__VMS) \\\n  && (defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n#   ifdef _AIX\n#     include <inttypes.h>\n#   else\n#     include <stdint.h>\n#   endif\n   typedef uint64_t XXH64_hash_t;\n#else\n#  include <limits.h>\n#  if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL\n     /* LP64 ABI says uint64_t is unsigned long */\n     typedef unsigned long XXH64_hash_t;\n#  else\n     /* the following type must have a width of 64-bit */\n     typedef unsigned long long XXH64_hash_t;\n#  endif\n#endif\n\n/*!\n * @}\n *\n * @defgroup XXH64_family XXH64 family\n * @ingroup public\n * @{\n * Contains functions used in the classic 64-bit xxHash algorithm.\n *\n * @note\n *   XXH3 provides competitive speed for both 32-bit and 64-bit systems,\n *   and offers true 64/128 bit hash results.\n *   It provides better speed for systems with vector processing capabilities.\n */\n\n/*!\n * @brief Calculates the 64-bit hash of @p input using xxHash64.\n *\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n * @param seed The 64-bit seed to alter the hash's output predictably.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 64-bit xxHash64 value.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed);\n\n/*******   Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*!\n * @brief The opaque state struct for the XXH64 streaming API.\n *\n * @see XXH64_state_s for details.\n * @see @ref streaming_example \"Streaming Example\"\n */\ntypedef struct XXH64_state_s XXH64_state_t;   /* incomplete type */\n\n/*!\n * @brief Allocates an @ref XXH64_state_t.\n *\n * @return An allocated pointer of @ref XXH64_state_t on success.\n * @return `NULL` on failure.\n *\n * @note Must be freed with XXH64_freeState().\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void);\n\n/*!\n * @brief Frees an @ref XXH64_state_t.\n *\n * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState().\n *\n * @return @ref XXH_OK.\n *\n * @note @p statePtr must be allocated with XXH64_createState().\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode  XXH64_freeState(XXH64_state_t* statePtr);\n\n/*!\n * @brief Copies one @ref XXH64_state_t to another.\n *\n * @param dst_state The state to copy to.\n * @param src_state The state to copy from.\n * @pre\n *   @p dst_state and @p src_state must not be `NULL` and must not overlap.\n */\nXXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state);\n\n/*!\n * @brief Resets an @ref XXH64_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note This function resets and seeds a state. Call it before @ref XXH64_update().\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH64_reset  (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH64_state_t.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note Call this to incrementally consume blocks of data.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated hash value from an @ref XXH64_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated 64-bit xxHash64 value from that state.\n *\n * @note\n *   Calling XXH64_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n/*******   Canonical representation   *******/\n\n/*!\n * @brief Canonical (big endian) representation of @ref XXH64_hash_t.\n */\ntypedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t;\n\n/*!\n * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t.\n *\n * @param dst The @ref XXH64_canonical_t pointer to be stored to.\n * @param hash The @ref XXH64_hash_t to be converted.\n *\n * @pre\n *   @p dst must not be `NULL`.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash);\n\n/*!\n * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t.\n *\n * @param src The @ref XXH64_canonical_t to convert.\n *\n * @pre\n *   @p src must not be `NULL`.\n *\n * @return The converted hash.\n *\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src);\n\n#ifndef XXH_NO_XXH3\n\n/*!\n * @}\n * ************************************************************************\n * @defgroup XXH3_family XXH3 family\n * @ingroup public\n * @{\n *\n * XXH3 is a more recent hash algorithm featuring:\n *  - Improved speed for both small and large inputs\n *  - True 64-bit and 128-bit outputs\n *  - SIMD acceleration\n *  - Improved 32-bit viability\n *\n * Speed analysis methodology is explained here:\n *\n *    https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html\n *\n * Compared to XXH64, expect XXH3 to run approximately\n * ~2x faster on large inputs and >3x faster on small ones,\n * exact differences vary depending on platform.\n *\n * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic,\n * but does not require it.\n * Most 32-bit and 64-bit targets that can run XXH32 smoothly can run XXH3\n * at competitive speeds, even without vector support. Further details are\n * explained in the implementation.\n *\n * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD\n * implementations for many common platforms:\n *   - AVX512\n *   - AVX2\n *   - SSE2\n *   - ARM NEON\n *   - WebAssembly SIMD128\n *   - POWER8 VSX\n *   - s390x ZVector\n * This can be controlled via the @ref XXH_VECTOR macro, but it automatically\n * selects the best version according to predefined macros. For the x86 family, an\n * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c.\n *\n * XXH3 implementation is portable:\n * it has a generic C90 formulation that can be compiled on any platform,\n * all implementations generate exactly the same hash value on all platforms.\n * Starting from v0.8.0, it's also labelled \"stable\", meaning that\n * any future version will also generate the same hash value.\n *\n * XXH3 offers 2 variants, _64bits and _128bits.\n *\n * When only 64 bits are needed, prefer invoking the _64bits variant, as it\n * reduces the amount of mixing, resulting in faster speed on small inputs.\n * It's also generally simpler to manipulate a scalar return type than a struct.\n *\n * The API supports one-shot hashing, streaming mode, and custom secrets.\n */\n\n/*!\n * @ingroup tuning\n * @brief Possible values for @ref XXH_VECTOR.\n *\n * Unless set explicitly, determined automatically.\n */\n#  define XXH_SCALAR 0 /*!< Portable scalar version */\n#  define XXH_SSE2   1 /*!< SSE2 for Pentium 4, Opteron, all x86_64. */\n#  define XXH_AVX2   2 /*!< AVX2 for Haswell and Bulldozer */\n#  define XXH_AVX512 3 /*!< AVX512 for Skylake and Icelake */\n#  define XXH_NEON   4 /*!< NEON for most ARMv7-A, all AArch64, and WASM SIMD128 */\n#  define XXH_VSX    5 /*!< VSX and ZVector for POWER8/z13 (64-bit) */\n#  define XXH_SVE    6 /*!< SVE for some ARMv8-A and ARMv9-A */\n#  define XXH_LSX    7 /*!< LSX (128-bit SIMD) for LoongArch64 */\n\n\n/*-**********************************************************************\n*  XXH3 64-bit variant\n************************************************************************/\n\n/*!\n * @brief Calculates 64-bit unseeded variant of XXH3 hash of @p input.\n *\n * @param input  The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 64-bit XXH3 hash value.\n *\n * @note\n *   This is equivalent to @ref XXH3_64bits_withSeed() with a seed of `0`, however\n *   it may have slightly better performance due to constant propagation of the\n *   defaults.\n *\n * @see\n *    XXH3_64bits_withSeed(), XXH3_64bits_withSecret(): other seeding variants\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Calculates 64-bit seeded variant of XXH3 hash of @p input.\n *\n * @param input  The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n * @param seed   The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 64-bit XXH3 hash value.\n *\n * @note\n *    seed == 0 produces the same results as @ref XXH3_64bits().\n *\n * This variant generates a custom secret on the fly based on default secret\n * altered using the @p seed value.\n *\n * While this operation is decently fast, note that it's not completely free.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed);\n\n/*!\n * The bare minimum size for a custom secret.\n *\n * @see\n *  XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(),\n *  XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret().\n */\n#define XXH3_SECRET_SIZE_MIN 136\n\n/*!\n * @brief Calculates 64-bit variant of XXH3 with a custom \"secret\".\n *\n * @param data       The block of data to be hashed, at least @p len bytes in size.\n * @param len        The length of @p data, in bytes.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @return The calculated 64-bit XXH3 hash value.\n *\n * @pre\n *   The memory between @p data and @p data + @p len must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p data may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * It's possible to provide any blob of bytes as a \"secret\" to generate the hash.\n * This makes it more difficult for an external actor to prepare an intentional collision.\n * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN).\n * However, the quality of the secret impacts the dispersion of the hash algorithm.\n * Therefore, the secret _must_ look like a bunch of random bytes.\n * Avoid \"trivial\" or structured data such as repeated sequences or a text document.\n * Whenever in doubt about the \"randomness\" of the blob of bytes,\n * consider employing @ref XXH3_generateSecret() instead (see below).\n * It will generate a proper high entropy secret derived from the blob of bytes.\n * Another advantage of using XXH3_generateSecret() is that\n * it guarantees that all bits within the initial blob of bytes\n * will impact every bit of the output.\n * This is not necessarily the case when using the blob of bytes directly\n * because, when hashing _small_ inputs, only a portion of the secret is employed.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n\n/*******   Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*\n * Streaming requires state maintenance.\n * This operation costs memory and CPU.\n * As a consequence, streaming is slower than one-shot hashing.\n * For better performance, prefer one-shot functions whenever applicable.\n */\n\n/*!\n * @brief The opaque state struct for the XXH3 streaming API.\n *\n * @see XXH3_state_s for details.\n * @see @ref streaming_example \"Streaming Example\"\n */\ntypedef struct XXH3_state_s XXH3_state_t;\nXXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void);\nXXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr);\n\n/*!\n * @brief Copies one @ref XXH3_state_t to another.\n *\n * @param dst_state The state to copy to.\n * @param src_state The state to copy from.\n * @pre\n *   @p dst_state and @p src_state must not be `NULL` and must not overlap.\n */\nXXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state);\n\n/*!\n * @brief Resets an @ref XXH3_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret with default parameters.\n *   - Call this function before @ref XXH3_64bits_update().\n *   - Digest will be equivalent to `XXH3_64bits()`.\n *\n * @see @ref streaming_example \"Streaming Example\"\n *\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);\n\n/*!\n * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed     The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret from `seed`.\n *   - Call this function before @ref XXH3_64bits_update().\n *   - Digest will be equivalent to `XXH3_64bits_withSeed()`.\n *\n * @see @ref streaming_example \"Streaming Example\"\n *\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed);\n\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   `secret` is referenced, it _must outlive_ the hash streaming session.\n *\n * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN,\n * and the quality of produced hash values depends on secret's entropy\n * (secret's content should look like a bunch of random bytes).\n * When in doubt about the randomness of a candidate `secret`,\n * consider employing `XXH3_generateSecret()` instead (see below).\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH3_state_t.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n * @pre\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note Call this to incrementally consume blocks of data.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated XXH3 64-bit hash value from that state.\n *\n * @note\n *   Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t  XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n\n/* note : canonical representation of XXH3 is the same as XXH64\n * since they both produce XXH64_hash_t values */\n\n\n/*-**********************************************************************\n*  XXH3 128-bit variant\n************************************************************************/\n\n/*!\n * @brief The return value from 128-bit hashes.\n *\n * Stored in little endian order, although the fields themselves are in native\n * endianness.\n */\ntypedef struct {\n    XXH64_hash_t low64;   /*!< `value & 0xFFFFFFFFFFFFFFFF` */\n    XXH64_hash_t high64;  /*!< `value >> 64` */\n} XXH128_hash_t;\n\n/*!\n * @brief Calculates 128-bit unseeded variant of XXH3 of @p data.\n *\n * @param data The block of data to be hashed, at least @p length bytes in size.\n * @param len  The length of @p data, in bytes.\n *\n * @return The calculated 128-bit variant of XXH3 value.\n *\n * The 128-bit variant of XXH3 has more strength, but it has a bit of overhead\n * for shorter inputs.\n *\n * This is equivalent to @ref XXH3_128bits_withSeed() with a seed of `0`, however\n * it may have slightly better performance due to constant propagation of the\n * defaults.\n *\n * @see XXH3_128bits_withSeed(), XXH3_128bits_withSecret(): other seeding variants\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len);\n/*! @brief Calculates 128-bit seeded variant of XXH3 hash of @p data.\n *\n * @param data The block of data to be hashed, at least @p length bytes in size.\n * @param len  The length of @p data, in bytes.\n * @param seed The 64-bit seed to alter the hash result predictably.\n *\n * @return The calculated 128-bit variant of XXH3 value.\n *\n * @note\n *    seed == 0 produces the same results as @ref XXH3_64bits().\n *\n * This variant generates a custom secret on the fly based on default secret\n * altered using the @p seed value.\n *\n * While this operation is decently fast, note that it's not completely free.\n *\n * @see XXH3_128bits(), XXH3_128bits_withSecret(): other seeding variants\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed);\n/*!\n * @brief Calculates 128-bit variant of XXH3 with a custom \"secret\".\n *\n * @param data       The block of data to be hashed, at least @p len bytes in size.\n * @param len        The length of @p data, in bytes.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @return The calculated 128-bit variant of XXH3 value.\n *\n * It's possible to provide any blob of bytes as a \"secret\" to generate the hash.\n * This makes it more difficult for an external actor to prepare an intentional collision.\n * The main condition is that @p secretSize *must* be large enough (>= @ref XXH3_SECRET_SIZE_MIN).\n * However, the quality of the secret impacts the dispersion of the hash algorithm.\n * Therefore, the secret _must_ look like a bunch of random bytes.\n * Avoid \"trivial\" or structured data such as repeated sequences or a text document.\n * Whenever in doubt about the \"randomness\" of the blob of bytes,\n * consider employing @ref XXH3_generateSecret() instead (see below).\n * It will generate a proper high entropy secret derived from the blob of bytes.\n * Another advantage of using XXH3_generateSecret() is that\n * it guarantees that all bits within the initial blob of bytes\n * will impact every bit of the output.\n * This is not necessarily the case when using the blob of bytes directly\n * because, when hashing _small_ inputs, only a portion of the secret is employed.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n/*******   Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*\n * Streaming requires state maintenance.\n * This operation costs memory and CPU.\n * As a consequence, streaming is slower than one-shot hashing.\n * For better performance, prefer one-shot functions whenever applicable.\n *\n * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits().\n * Use already declared XXH3_createState() and XXH3_freeState().\n *\n * All reset and streaming functions have same meaning as their 64-bit counterpart.\n */\n\n/*!\n * @brief Resets an @ref XXH3_state_t to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret with default parameters.\n *   - Call it before @ref XXH3_128bits_update().\n *   - Digest will be equivalent to `XXH3_128bits()`.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);\n\n/*!\n * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.\n *\n * @param statePtr The state struct to reset.\n * @param seed     The 64-bit seed to alter the hash result predictably.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   - This function resets `statePtr` and generate a secret from `seed`.\n *   - Call it before @ref XXH3_128bits_update().\n *   - Digest will be equivalent to `XXH3_128bits_withSeed()`.\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed);\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr   The state struct to reset.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * `secret` is referenced, it _must outlive_ the hash streaming session.\n * Similar to one-shot API, `secretSize` must be >= @ref XXH3_SECRET_SIZE_MIN,\n * and the quality of produced hash values depends on secret's entropy\n * (secret's content should look like a bunch of random bytes).\n * When in doubt about the randomness of a candidate `secret`,\n * consider employing `XXH3_generateSecret()` instead (see below).\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);\n\n/*!\n * @brief Consumes a block of @p input to an @ref XXH3_state_t.\n *\n * Call this to incrementally consume blocks of data.\n *\n * @param statePtr The state struct to update.\n * @param input The block of data to be hashed, at least @p length bytes in size.\n * @param length The length of @p input, in bytes.\n *\n * @pre\n *   @p statePtr must not be `NULL`.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @note\n *   The memory between @p input and @p input + @p length must be valid,\n *   readable, contiguous memory. However, if @p length is `0`, @p input may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);\n\n/*!\n * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t.\n *\n * @param statePtr The state struct to calculate the hash from.\n *\n * @pre\n *  @p statePtr must not be `NULL`.\n *\n * @return The calculated XXH3 128-bit hash value from that state.\n *\n * @note\n *   Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update,\n *   digest, and update again.\n *\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);\n#endif /* !XXH_NO_STREAM */\n\n/* Following helper functions make it possible to compare XXH128_hast_t values.\n * Since XXH128_hash_t is a structure, this capability is not offered by the language.\n * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */\n\n/*!\n * @brief Check equality of two XXH128_hash_t values\n *\n * @param h1 The 128-bit hash value.\n * @param h2 Another 128-bit hash value.\n *\n * @return `1` if `h1` and `h2` are equal.\n * @return `0` if they are not.\n */\nXXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2);\n\n/*!\n * @brief Compares two @ref XXH128_hash_t\n *\n * This comparator is compatible with stdlib's `qsort()`/`bsearch()`.\n *\n * @param h128_1 Left-hand side value\n * @param h128_2 Right-hand side value\n *\n * @return >0 if @p h128_1  > @p h128_2\n * @return =0 if @p h128_1 == @p h128_2\n * @return <0 if @p h128_1  < @p h128_2\n */\nXXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2);\n\n\n/*******   Canonical representation   *******/\ntypedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t;\n\n\n/*!\n * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t.\n *\n * @param dst  The @ref XXH128_canonical_t pointer to be stored to.\n * @param hash The @ref XXH128_hash_t to be converted.\n *\n * @pre\n *   @p dst must not be `NULL`.\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash);\n\n/*!\n * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t.\n *\n * @param src The @ref XXH128_canonical_t to convert.\n *\n * @pre\n *   @p src must not be `NULL`.\n *\n * @return The converted hash.\n * @see @ref canonical_representation_example \"Canonical Representation Example\"\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src);\n\n\n#endif  /* !XXH_NO_XXH3 */\n#endif  /* XXH_NO_LONG_LONG */\n\n/*!\n * @}\n */\n#endif /* XXHASH_H_5627135585666179 */\n\n\n\n#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742)\n#define XXHASH_H_STATIC_13879238742\n/* ****************************************************************************\n * This section contains declarations which are not guaranteed to remain stable.\n * They may change in future versions, becoming incompatible with a different\n * version of the library.\n * These declarations should only be used with static linking.\n * Never use them in association with dynamic linking!\n ***************************************************************************** */\n\n/*\n * These definitions are only present to allow static allocation\n * of XXH states, on stack or in a struct, for example.\n * Never **ever** access their members directly.\n */\n\n/*!\n * @internal\n * @brief Structure for XXH32 streaming API.\n *\n * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,\n * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is\n * an opaque type. This allows fields to safely be changed.\n *\n * Typedef'd to @ref XXH32_state_t.\n * Do not access the members of this struct directly.\n * @see XXH64_state_s, XXH3_state_s\n */\nstruct XXH32_state_s {\n   XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */\n   XXH32_hash_t large_len;    /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */\n   XXH32_hash_t acc[4];       /*!< Accumulator lanes */\n   unsigned char buffer[16];  /*!< Internal buffer for partial reads. */\n   XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */\n   XXH32_hash_t reserved;     /*!< Reserved field. Do not read nor write to it. */\n};   /* typedef'd to XXH32_state_t */\n\n\n#ifndef XXH_NO_LONG_LONG  /* defined when there is no 64-bit support */\n\n/*!\n * @internal\n * @brief Structure for XXH64 streaming API.\n *\n * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,\n * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is\n * an opaque type. This allows fields to safely be changed.\n *\n * Typedef'd to @ref XXH64_state_t.\n * Do not access the members of this struct directly.\n * @see XXH32_state_s, XXH3_state_s\n */\nstruct XXH64_state_s {\n   XXH64_hash_t total_len;    /*!< Total length hashed. This is always 64-bit. */\n   XXH64_hash_t acc[4];       /*!< Accumulator lanes */\n   unsigned char buffer[32];  /*!< Internal buffer for partial reads.. */\n   XXH32_hash_t bufferedSize; /*!< Amount of data in @ref buffer */\n   XXH32_hash_t reserved32;   /*!< Reserved field, needed for padding anyways*/\n   XXH64_hash_t reserved64;   /*!< Reserved field. Do not read or write to it. */\n};   /* typedef'd to XXH64_state_t */\n\n#ifndef XXH_NO_XXH3\n\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */\n#  define XXH_ALIGN(n)      _Alignas(n)\n#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */\n/* In C++ alignas() is a keyword */\n#  define XXH_ALIGN(n)      alignas(n)\n#elif defined(__GNUC__)\n#  define XXH_ALIGN(n)      __attribute__ ((aligned(n)))\n#elif defined(_MSC_VER)\n#  define XXH_ALIGN(n)      __declspec(align(n))\n#else\n#  define XXH_ALIGN(n)   /* disabled */\n#endif\n\n/* Old GCC versions only accept the attribute after the type in structures. */\n#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L))   /* C11+ */ \\\n    && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \\\n    && defined(__GNUC__)\n#   define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align)\n#else\n#   define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type\n#endif\n\n/*!\n * @brief The size of the internal XXH3 buffer.\n *\n * This is the optimal update size for incremental hashing.\n *\n * @see XXH3_64b_update(), XXH3_128b_update().\n */\n#define XXH3_INTERNALBUFFER_SIZE 256\n\n/*!\n * @internal\n * @brief Default size of the secret buffer (and @ref XXH3_kSecret).\n *\n * This is the size used in @ref XXH3_kSecret and the seeded functions.\n *\n * Not to be confused with @ref XXH3_SECRET_SIZE_MIN.\n */\n#define XXH3_SECRET_DEFAULT_SIZE 192\n\n/*!\n * @internal\n * @brief Structure for XXH3 streaming API.\n *\n * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,\n * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined.\n * Otherwise it is an opaque type.\n * Never use this definition in combination with dynamic library.\n * This allows fields to safely be changed in the future.\n *\n * @note ** This structure has a strict alignment requirement of 64 bytes!! **\n * Do not allocate this with `malloc()` or `new`,\n * it will not be sufficiently aligned.\n * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation.\n *\n * Typedef'd to @ref XXH3_state_t.\n * Do never access the members of this struct directly.\n *\n * @see XXH3_INITSTATE() for stack initialization.\n * @see XXH3_createState(), XXH3_freeState().\n * @see XXH32_state_s, XXH64_state_s\n */\nstruct XXH3_state_s {\n   XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]);\n       /*!< The 8 accumulators. See @ref XXH32_state_s::v and @ref XXH64_state_s::v */\n   XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]);\n       /*!< Used to store a custom secret generated from a seed. */\n   XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]);\n       /*!< The internal buffer. @see XXH32_state_s::mem32 */\n   XXH32_hash_t bufferedSize;\n       /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */\n   XXH32_hash_t useSeed;\n       /*!< Reserved field. Needed for padding on 64-bit. */\n   size_t nbStripesSoFar;\n       /*!< Number or stripes processed. */\n   XXH64_hash_t totalLen;\n       /*!< Total length hashed. 64-bit even on 32-bit targets. */\n   size_t nbStripesPerBlock;\n       /*!< Number of stripes per block. */\n   size_t secretLimit;\n       /*!< Size of @ref customSecret or @ref extSecret */\n   XXH64_hash_t seed;\n       /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */\n   XXH64_hash_t reserved64;\n       /*!< Reserved field. */\n   const unsigned char* extSecret;\n       /*!< Reference to an external secret for the _withSecret variants, NULL\n        *   for other variants. */\n   /* note: there may be some padding at the end due to alignment on 64 bytes */\n}; /* typedef'd to XXH3_state_t */\n\n#undef XXH_ALIGN_MEMBER\n\n/*!\n * @brief Initializes a stack-allocated `XXH3_state_s`.\n *\n * When the @ref XXH3_state_t structure is merely emplaced on stack,\n * it should be initialized with XXH3_INITSTATE() or a memset()\n * in case its first reset uses XXH3_NNbits_reset_withSeed().\n * This init can be omitted if the first reset uses default or _withSecret mode.\n * This operation isn't necessary when the state is created with XXH3_createState().\n * Note that this doesn't prepare the state for a streaming operation,\n * it's still necessary to use XXH3_NNbits_reset*() afterwards.\n */\n#define XXH3_INITSTATE(XXH3_state_ptr)                       \\\n    do {                                                     \\\n        XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \\\n        tmp_xxh3_state_ptr->seed = 0;                        \\\n        tmp_xxh3_state_ptr->extSecret = NULL;                \\\n    } while(0)\n\n\n/*!\n * @brief Calculates the 128-bit hash of @p data using XXH3.\n *\n * @param data The block of data to be hashed, at least @p len bytes in size.\n * @param len  The length of @p data, in bytes.\n * @param seed The 64-bit seed to alter the hash's output predictably.\n *\n * @pre\n *   The memory between @p data and @p data + @p len must be valid,\n *   readable, contiguous memory. However, if @p len is `0`, @p data may be\n *   `NULL`. In C++, this also must be *TriviallyCopyable*.\n *\n * @return The calculated 128-bit XXH3 value.\n *\n * @see @ref single_shot_example \"Single Shot Example\" for an example.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed);\n\n\n/* ===   Experimental API   === */\n/* Symbols defined below must be considered tied to a specific library version. */\n\n/*!\n * @brief Derive a high-entropy secret from any user-defined content, named customSeed.\n *\n * @param secretBuffer    A writable buffer for derived high-entropy secret data.\n * @param secretSize      Size of secretBuffer, in bytes.  Must be >= XXH3_SECRET_SIZE_MIN.\n * @param customSeed      A user-defined content.\n * @param customSeedSize  Size of customSeed, in bytes.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * The generated secret can be used in combination with `*_withSecret()` functions.\n * The `_withSecret()` variants are useful to provide a higher level of protection\n * than 64-bit seed, as it becomes much more difficult for an external actor to\n * guess how to impact the calculation logic.\n *\n * The function accepts as input a custom seed of any length and any content,\n * and derives from it a high-entropy secret of length @p secretSize into an\n * already allocated buffer @p secretBuffer.\n *\n * The generated secret can then be used with any `*_withSecret()` variant.\n * The functions @ref XXH3_128bits_withSecret(), @ref XXH3_64bits_withSecret(),\n * @ref XXH3_128bits_reset_withSecret() and @ref XXH3_64bits_reset_withSecret()\n * are part of this list. They all accept a `secret` parameter\n * which must be large enough for implementation reasons (>= @ref XXH3_SECRET_SIZE_MIN)\n * _and_ feature very high entropy (consist of random-looking bytes).\n * These conditions can be a high bar to meet, so @ref XXH3_generateSecret() can\n * be employed to ensure proper quality.\n *\n * @p customSeed can be anything. It can have any size, even small ones,\n * and its content can be anything, even \"poor entropy\" sources such as a bunch\n * of zeroes. The resulting `secret` will nonetheless provide all required qualities.\n *\n * @pre\n *   - @p secretSize must be >= @ref XXH3_SECRET_SIZE_MIN\n *   - When @p customSeedSize > 0, supplying NULL as customSeed is undefined behavior.\n *\n * Example code:\n * @code{.c}\n *    #include <stdio.h>\n *    #include <stdlib.h>\n *    #include <string.h>\n *    #define XXH_STATIC_LINKING_ONLY // expose unstable API\n *    #include \"xxhash.h\"\n *    // Hashes argv[2] using the entropy from argv[1].\n *    int main(int argc, char* argv[])\n *    {\n *        char secret[XXH3_SECRET_SIZE_MIN];\n *        if (argv != 3) { return 1; }\n *        XXH3_generateSecret(secret, sizeof(secret), argv[1], strlen(argv[1]));\n *        XXH64_hash_t h = XXH3_64bits_withSecret(\n *             argv[2], strlen(argv[2]),\n *             secret, sizeof(secret)\n *        );\n *        printf(\"%016llx\\n\", (unsigned long long) h);\n *    }\n * @endcode\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize);\n\n/*!\n * @brief Generate the same secret as the _withSeed() variants.\n *\n * @param secretBuffer A writable buffer of @ref XXH3_SECRET_DEFAULT_SIZE bytes\n * @param seed         The 64-bit seed to alter the hash result predictably.\n *\n * The generated secret can be used in combination with\n *`*_withSecret()` and `_withSecretandSeed()` variants.\n *\n * Example C++ `std::string` hash class:\n * @code{.cpp}\n *    #include <string>\n *    #define XXH_STATIC_LINKING_ONLY // expose unstable API\n *    #include \"xxhash.h\"\n *    // Slow, seeds each time\n *    class HashSlow {\n *        XXH64_hash_t seed;\n *    public:\n *        HashSlow(XXH64_hash_t s) : seed{s} {}\n *        size_t operator()(const std::string& x) const {\n *            return size_t{XXH3_64bits_withSeed(x.c_str(), x.length(), seed)};\n *        }\n *    };\n *    // Fast, caches the seeded secret for future uses.\n *    class HashFast {\n *        unsigned char secret[XXH3_SECRET_DEFAULT_SIZE];\n *    public:\n *        HashFast(XXH64_hash_t s) {\n *            XXH3_generateSecret_fromSeed(secret, seed);\n *        }\n *        size_t operator()(const std::string& x) const {\n *            return size_t{\n *                XXH3_64bits_withSecret(x.c_str(), x.length(), secret, sizeof(secret))\n *            };\n *        }\n *    };\n * @endcode\n */\nXXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed);\n\n/*!\n * @brief Maximum size of \"short\" key in bytes.\n */\n#define XXH3_MIDSIZE_MAX 240\n\n/*!\n * @brief Calculates 64/128-bit seeded variant of XXH3 hash of @p data.\n *\n * @param data       The block of data to be hashed, at least @p len bytes in size.\n * @param len        The length of @p data, in bytes.\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n * @param seed       The 64-bit seed to alter the hash result predictably.\n *\n * These variants generate hash values using either:\n * - @p seed for \"short\" keys (< @ref XXH3_MIDSIZE_MAX = 240 bytes)\n * - @p secret for \"large\" keys (>= @ref XXH3_MIDSIZE_MAX).\n *\n * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`.\n * `_withSeed()` has to generate the secret on the fly for \"large\" keys.\n * It's fast, but can be perceptible for \"not so large\" keys (< 1 KB).\n * `_withSecret()` has to generate the masks on the fly for \"small\" keys,\n * which requires more instructions than _withSeed() variants.\n * Therefore, _withSecretandSeed variant combines the best of both worlds.\n *\n * When @p secret has been generated by XXH3_generateSecret_fromSeed(),\n * this variant produces *exactly* the same results as `_withSeed()` variant,\n * hence offering only a pure speed benefit on \"large\" input,\n * by skipping the need to regenerate the secret for every large input.\n *\n * Another usage scenario is to hash the secret to a 64-bit hash value,\n * for example with XXH3_64bits(), which then becomes the seed,\n * and then employ both the seed and the secret in _withSecretandSeed().\n * On top of speed, an added benefit is that each bit in the secret\n * has a 50% chance to swap each bit in the output, via its impact to the seed.\n *\n * This is not guaranteed when using the secret directly in \"small data\" scenarios,\n * because only portions of the secret are employed for small data.\n */\nXXH_PUBLIC_API XXH_PUREF XXH64_hash_t\nXXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len,\n                              XXH_NOESCAPE const void* secret, size_t secretSize,\n                              XXH64_hash_t seed);\n\n/*!\n * @brief Calculates 128-bit seeded variant of XXH3 hash of @p data.\n *\n * @param data       The memory segment to be hashed, at least @p len bytes in size.\n * @param length     The length of @p data, in bytes.\n * @param secret     The secret used to alter hash result predictably.\n * @param secretSize The length of @p secret, in bytes (must be >= XXH3_SECRET_SIZE_MIN)\n * @param seed64     The 64-bit seed to alter the hash result predictably.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @see XXH3_64bits_withSecretandSeed(): contract is the same.\n */\nXXH_PUBLIC_API XXH_PUREF XXH128_hash_t\nXXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length,\n                               XXH_NOESCAPE const void* secret, size_t secretSize,\n                               XXH64_hash_t seed64);\n\n#ifndef XXH_NO_STREAM\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr   A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n * @param seed64     The 64-bit seed to alter the hash result predictably.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @see XXH3_64bits_withSecretandSeed(). Contract is identical.\n */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,\n                                    XXH_NOESCAPE const void* secret, size_t secretSize,\n                                    XXH64_hash_t seed64);\n\n/*!\n * @brief Resets an @ref XXH3_state_t with secret data to begin a new hash.\n *\n * @param statePtr   A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().\n * @param secret     The secret data.\n * @param secretSize The length of @p secret, in bytes.\n * @param seed64     The 64-bit seed to alter the hash result predictably.\n *\n * @return @ref XXH_OK on success.\n * @return @ref XXH_ERROR on failure.\n *\n * @see XXH3_64bits_withSecretandSeed(). Contract is identical.\n *\n * Note: there was a bug in an earlier version of this function (<= v0.8.2)\n * that would make it generate an incorrect hash value\n * when @p seed == 0 and @p length < XXH3_MIDSIZE_MAX\n * and @p secret is different from XXH3_generateSecret_fromSeed().\n * As stated in the contract, the correct hash result must be\n * the same as XXH3_128bits_withSeed() when @p length <= XXH3_MIDSIZE_MAX.\n * Results generated by this older version are wrong, hence not comparable.\n */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,\n                                     XXH_NOESCAPE const void* secret, size_t secretSize,\n                                     XXH64_hash_t seed64);\n\n#endif /* !XXH_NO_STREAM */\n\n#endif  /* !XXH_NO_XXH3 */\n#endif  /* XXH_NO_LONG_LONG */\n#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)\n#  define XXH_IMPLEMENTATION\n#endif\n\n#endif  /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */\n\n\n/* ======================================================================== */\n/* ======================================================================== */\n/* ======================================================================== */\n\n\n/*-**********************************************************************\n * xxHash implementation\n *-**********************************************************************\n * xxHash's implementation used to be hosted inside xxhash.c.\n *\n * However, inlining requires implementation to be visible to the compiler,\n * hence be included alongside the header.\n * Previously, implementation was hosted inside xxhash.c,\n * which was then #included when inlining was activated.\n * This construction created issues with a few build and install systems,\n * as it required xxhash.c to be stored in /include directory.\n *\n * xxHash implementation is now directly integrated within xxhash.h.\n * As a consequence, xxhash.c is no longer needed in /include.\n *\n * xxhash.c is still available and is still useful.\n * In a \"normal\" setup, when xxhash is not inlined,\n * xxhash.h only exposes the prototypes and public symbols,\n * while xxhash.c can be built into an object file xxhash.o\n * which can then be linked into the final binary.\n ************************************************************************/\n\n#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \\\n   || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387)\n#  define XXH_IMPLEM_13a8737387\n\n/* *************************************\n*  Tuning parameters\n***************************************/\n\n/*!\n * @defgroup tuning Tuning parameters\n * @{\n *\n * Various macros to control xxHash's behavior.\n */\n#ifdef XXH_DOXYGEN\n/*!\n * @brief Define this to disable 64-bit code.\n *\n * Useful if only using the @ref XXH32_family and you have a strict C90 compiler.\n */\n#  define XXH_NO_LONG_LONG\n#  undef XXH_NO_LONG_LONG /* don't actually */\n/*!\n * @brief Controls how unaligned memory is accessed.\n *\n * By default, access to unaligned memory is controlled by `memcpy()`, which is\n * safe and portable.\n *\n * Unfortunately, on some target/compiler combinations, the generated assembly\n * is sub-optimal.\n *\n * The below switch allow selection of a different access method\n * in the search for improved performance.\n *\n * @par Possible options:\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy`\n *   @par\n *     Use `memcpy()`. Safe and portable. Note that most modern compilers will\n *     eliminate the function call and treat it as an unaligned access.\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((aligned(1)))`\n *   @par\n *     Depends on compiler extensions and is therefore not portable.\n *     This method is safe _if_ your compiler supports it,\n *     and *generally* as fast or faster than `memcpy`.\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast\n *  @par\n *     Casts directly and dereferences. This method doesn't depend on the\n *     compiler, but it violates the C standard as it directly dereferences an\n *     unaligned pointer. It can generate buggy code on targets which do not\n *     support unaligned memory accesses, but in some circumstances, it's the\n *     only known way to get the most performance.\n *\n *  - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift\n *  @par\n *     Also portable. This can generate the best code on old compilers which don't\n *     inline small `memcpy()` calls, and it might also be faster on big-endian\n *     systems which lack a native byteswap instruction. However, some compilers\n *     will emit literal byteshifts even if the target supports unaligned access.\n *\n *\n * @warning\n *   Methods 1 and 2 rely on implementation-defined behavior. Use these with\n *   care, as what works on one compiler/platform/optimization level may cause\n *   another to read garbage data or even crash.\n *\n * See https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details.\n *\n * Prefer these methods in priority order (0 > 3 > 1 > 2)\n */\n#  define XXH_FORCE_MEMORY_ACCESS 0\n\n/*!\n * @def XXH_SIZE_OPT\n * @brief Controls how much xxHash optimizes for size.\n *\n * xxHash, when compiled, tends to result in a rather large binary size. This\n * is mostly due to heavy usage to forced inlining and constant folding of the\n * @ref XXH3_family to increase performance.\n *\n * However, some developers prefer size over speed. This option can\n * significantly reduce the size of the generated code. When using the `-Os`\n * or `-Oz` options on GCC or Clang, this is defined to 1 by default,\n * otherwise it is defined to 0.\n *\n * Most of these size optimizations can be controlled manually.\n *\n * This is a number from 0-2.\n *  - `XXH_SIZE_OPT` == 0: Default. xxHash makes no size optimizations. Speed\n *    comes first.\n *  - `XXH_SIZE_OPT` == 1: Default for `-Os` and `-Oz`. xxHash is more\n *    conservative and disables hacks that increase code size. It implies the\n *    options @ref XXH_NO_INLINE_HINTS == 1, @ref XXH_FORCE_ALIGN_CHECK == 0,\n *    and @ref XXH3_NEON_LANES == 8 if they are not already defined.\n *  - `XXH_SIZE_OPT` == 2: xxHash tries to make itself as small as possible.\n *    Performance may cry. For example, the single shot functions just use the\n *    streaming API.\n */\n#  define XXH_SIZE_OPT 0\n\n/*!\n * @def XXH_FORCE_ALIGN_CHECK\n * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32()\n * and XXH64() only).\n *\n * This is an important performance trick for architectures without decent\n * unaligned memory access performance.\n *\n * It checks for input alignment, and when conditions are met, uses a \"fast\n * path\" employing direct 32-bit/64-bit reads, resulting in _dramatically\n * faster_ read speed.\n *\n * The check costs one initial branch per hash, which is generally negligible,\n * but not zero.\n *\n * Moreover, it's not useful to generate an additional code path if memory\n * access uses the same instruction for both aligned and unaligned\n * addresses (e.g. x86 and aarch64).\n *\n * In these cases, the alignment check can be removed by setting this macro to 0.\n * Then the code will always use unaligned memory access.\n * Align check is automatically disabled on x86, x64, ARM64, and some ARM chips\n * which are platforms known to offer good unaligned memory accesses performance.\n *\n * It is also disabled by default when @ref XXH_SIZE_OPT >= 1.\n *\n * This option does not affect XXH3 (only XXH32 and XXH64).\n */\n#  define XXH_FORCE_ALIGN_CHECK 0\n\n/*!\n * @def XXH_NO_INLINE_HINTS\n * @brief When non-zero, sets all functions to `static`.\n *\n * By default, xxHash tries to force the compiler to inline almost all internal\n * functions.\n *\n * This can usually improve performance due to reduced jumping and improved\n * constant folding, but significantly increases the size of the binary which\n * might not be favorable.\n *\n * Additionally, sometimes the forced inlining can be detrimental to performance,\n * depending on the architecture.\n *\n * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the\n * compiler full control on whether to inline or not.\n *\n * When not optimizing (-O0), using `-fno-inline` with GCC or Clang, or if\n * @ref XXH_SIZE_OPT >= 1, this will automatically be defined.\n */\n#  define XXH_NO_INLINE_HINTS 0\n\n/*!\n * @def XXH3_INLINE_SECRET\n * @brief Determines whether to inline the XXH3 withSecret code.\n *\n * When the secret size is known, the compiler can improve the performance\n * of XXH3_64bits_withSecret() and XXH3_128bits_withSecret().\n *\n * However, if the secret size is not known, it doesn't have any benefit. This\n * happens when xxHash is compiled into a global symbol. Therefore, if\n * @ref XXH_INLINE_ALL is *not* defined, this will be defined to 0.\n *\n * Additionally, this defaults to 0 on GCC 12+, which has an issue with function pointers\n * that are *sometimes* force inline on -Og, and it is impossible to automatically\n * detect this optimization level.\n */\n#  define XXH3_INLINE_SECRET 0\n\n/*!\n * @def XXH32_ENDJMP\n * @brief Whether to use a jump for `XXH32_finalize`.\n *\n * For performance, `XXH32_finalize` uses multiple branches in the finalizer.\n * This is generally preferable for performance,\n * but depending on exact architecture, a jmp may be preferable.\n *\n * This setting is only possibly making a difference for very small inputs.\n */\n#  define XXH32_ENDJMP 0\n\n/*!\n * @internal\n * @brief Redefines old internal names.\n *\n * For compatibility with code that uses xxHash's internals before the names\n * were changed to improve namespacing. There is no other reason to use this.\n */\n#  define XXH_OLD_NAMES\n#  undef XXH_OLD_NAMES /* don't actually use, it is ugly. */\n\n/*!\n * @def XXH_NO_STREAM\n * @brief Disables the streaming API.\n *\n * When xxHash is not inlined and the streaming functions are not used, disabling\n * the streaming functions can improve code size significantly, especially with\n * the @ref XXH3_family which tends to make constant folded copies of itself.\n */\n#  define XXH_NO_STREAM\n#  undef XXH_NO_STREAM /* don't actually */\n#endif /* XXH_DOXYGEN */\n/*!\n * @}\n */\n\n#ifndef XXH_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */\n   /* prefer __packed__ structures (method 1) for GCC\n    * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy\n    * which for some reason does unaligned loads. */\n#  if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED))\n#    define XXH_FORCE_MEMORY_ACCESS 1\n#  endif\n#endif\n\n#ifndef XXH_SIZE_OPT\n   /* default to 1 for -Os or -Oz */\n#  if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__)\n#    define XXH_SIZE_OPT 1\n#  else\n#    define XXH_SIZE_OPT 0\n#  endif\n#endif\n\n#ifndef XXH_FORCE_ALIGN_CHECK  /* can be defined externally */\n   /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */\n#  if XXH_SIZE_OPT >= 1 || \\\n      defined(__i386)  || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \\\n   || defined(_M_IX86) || defined(_M_X64)     || defined(_M_ARM64)    || defined(_M_ARM) /* visual */\n#    define XXH_FORCE_ALIGN_CHECK 0\n#  else\n#    define XXH_FORCE_ALIGN_CHECK 1\n#  endif\n#endif\n\n#ifndef XXH_NO_INLINE_HINTS\n#  if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__)  /* -O0, -fno-inline */\n#    define XXH_NO_INLINE_HINTS 1\n#  else\n#    define XXH_NO_INLINE_HINTS 0\n#  endif\n#endif\n\n#ifndef XXH3_INLINE_SECRET\n#  if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \\\n     || !defined(XXH_INLINE_ALL)\n#    define XXH3_INLINE_SECRET 0\n#  else\n#    define XXH3_INLINE_SECRET 1\n#  endif\n#endif\n\n#ifndef XXH32_ENDJMP\n/* generally preferable for performance */\n#  define XXH32_ENDJMP 0\n#endif\n\n/*!\n * @defgroup impl Implementation\n * @{\n */\n\n\n/* *************************************\n*  Includes & Memory related functions\n***************************************/\n#if defined(XXH_NO_STREAM)\n/* nothing */\n#elif defined(XXH_NO_STDLIB)\n\n/* When requesting to disable any mention of stdlib,\n * the library loses the ability to invoked malloc / free.\n * In practice, it means that functions like `XXH*_createState()`\n * will always fail, and return NULL.\n * This flag is useful in situations where\n * xxhash.h is integrated into some kernel, embedded or limited environment\n * without access to dynamic allocation.\n */\n\nstatic XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; }\nstatic void XXH_free(void* p) { (void)p; }\n\n#else\n\n/*\n * Modify the local functions below should you wish to use\n * different memory routines for malloc() and free()\n */\n#include <stdlib.h>\n\n/*!\n * @internal\n * @brief Modify this function to use a different routine than malloc().\n */\nstatic XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); }\n\n/*!\n * @internal\n * @brief Modify this function to use a different routine than free().\n */\nstatic void XXH_free(void* p) { free(p); }\n\n#endif  /* XXH_NO_STDLIB */\n\n#include <string.h>\n\n/*!\n * @internal\n * @brief Modify this function to use a different routine than memcpy().\n */\nstatic void* XXH_memcpy(void* dest, const void* src, size_t size)\n{\n    return memcpy(dest,src,size);\n}\n\n#include <limits.h>   /* ULLONG_MAX */\n\n\n/* *************************************\n*  Compiler Specific Options\n***************************************/\n#ifdef _MSC_VER /* Visual Studio warning fix */\n#  pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */\n#endif\n\n#if XXH_NO_INLINE_HINTS  /* disable inlining hints */\n#  if defined(__GNUC__) || defined(__clang__)\n#    define XXH_FORCE_INLINE static __attribute__((__unused__))\n#  else\n#    define XXH_FORCE_INLINE static\n#  endif\n#  define XXH_NO_INLINE static\n/* enable inlining hints */\n#elif defined(__GNUC__) || defined(__clang__)\n#  define XXH_FORCE_INLINE static __inline__ __attribute__((__always_inline__, __unused__))\n#  define XXH_NO_INLINE static __attribute__((__noinline__))\n#elif defined(_MSC_VER)  /* Visual Studio */\n#  define XXH_FORCE_INLINE static __forceinline\n#  define XXH_NO_INLINE static __declspec(noinline)\n#elif defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L))   /* C99 */\n#  define XXH_FORCE_INLINE static inline\n#  define XXH_NO_INLINE static\n#else\n#  define XXH_FORCE_INLINE static\n#  define XXH_NO_INLINE static\n#endif\n\n#if defined(XXH_INLINE_ALL)\n#  define XXH_STATIC XXH_FORCE_INLINE\n#else\n#  define XXH_STATIC static\n#endif\n\n#if XXH3_INLINE_SECRET\n#  define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE\n#else\n#  define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE\n#endif\n\n#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */\n#  define XXH_RESTRICT   /* disable */\n#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* >= C99 */\n#  define XXH_RESTRICT   restrict\n#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \\\n   || (defined (__clang__)) \\\n   || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \\\n   || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300))\n/*\n * There are a LOT more compilers that recognize __restrict but this\n * covers the major ones.\n */\n#  define XXH_RESTRICT   __restrict\n#else\n#  define XXH_RESTRICT   /* disable */\n#endif\n\n/* *************************************\n*  Debug\n***************************************/\n/*!\n * @ingroup tuning\n * @def XXH_DEBUGLEVEL\n * @brief Sets the debugging level.\n *\n * XXH_DEBUGLEVEL is expected to be defined externally, typically via the\n * compiler's command line options. The value must be a number.\n */\n#ifndef XXH_DEBUGLEVEL\n#  ifdef DEBUGLEVEL /* backwards compat */\n#    define XXH_DEBUGLEVEL DEBUGLEVEL\n#  else\n#    define XXH_DEBUGLEVEL 0\n#  endif\n#endif\n\n#if (XXH_DEBUGLEVEL>=1)\n#  include <assert.h>   /* note: can still be disabled with NDEBUG */\n#  define XXH_ASSERT(c)   assert(c)\n#else\n#  if defined(__INTEL_COMPILER)\n#    define XXH_ASSERT(c)   XXH_ASSUME((unsigned char) (c))\n#  else\n#    define XXH_ASSERT(c)   XXH_ASSUME(c)\n#  endif\n#endif\n\n/* note: use after variable declarations */\n#ifndef XXH_STATIC_ASSERT\n#  if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)    /* C11 */\n#    define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0)\n#  elif defined(__cplusplus) && (__cplusplus >= 201103L)            /* C++11 */\n#    define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0)\n#  else\n#    define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0)\n#  endif\n#  define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c)\n#endif\n\n/*!\n * @internal\n * @def XXH_COMPILER_GUARD(var)\n * @brief Used to prevent unwanted optimizations for @p var.\n *\n * It uses an empty GCC inline assembly statement with a register constraint\n * which forces @p var into a general purpose register (eg eax, ebx, ecx\n * on x86) and marks it as modified.\n *\n * This is used in a few places to avoid unwanted autovectorization (e.g.\n * XXH32_round()). All vectorization we want is explicit via intrinsics,\n * and _usually_ isn't wanted elsewhere.\n *\n * We also use it to prevent unwanted constant folding for AArch64 in\n * XXH3_initCustomSecret_scalar().\n */\n#if defined(__GNUC__) || defined(__clang__)\n#  define XXH_COMPILER_GUARD(var) __asm__(\"\" : \"+r\" (var))\n#else\n#  define XXH_COMPILER_GUARD(var) ((void)0)\n#endif\n\n/* Specifically for NEON vectors which use the \"w\" constraint, on\n * Clang. */\n#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__)\n#  define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__(\"\" : \"+w\" (var))\n#else\n#  define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0)\n#endif\n\n/* *************************************\n*  Basic Types\n***************************************/\n#if !defined (__VMS) \\\n && (defined (__cplusplus) \\\n || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n#   ifdef _AIX\n#     include <inttypes.h>\n#   else\n#     include <stdint.h>\n#   endif\n    typedef uint8_t xxh_u8;\n#else\n    typedef unsigned char xxh_u8;\n#endif\ntypedef XXH32_hash_t xxh_u32;\n\n#ifdef XXH_OLD_NAMES\n#  warning \"XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly\"\n#  define BYTE xxh_u8\n#  define U8   xxh_u8\n#  define U32  xxh_u32\n#endif\n\n/* ***   Memory access   *** */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_read32(const void* ptr)\n * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n *\n * @param ptr The pointer to read from.\n * @return The 32-bit native endian integer from the bytes at @p ptr.\n */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_readLE32(const void* ptr)\n * @brief Reads an unaligned 32-bit little endian integer from @p ptr.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n *\n * @param ptr The pointer to read from.\n * @return The 32-bit little endian integer from the bytes at @p ptr.\n */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_readBE32(const void* ptr)\n * @brief Reads an unaligned 32-bit big endian integer from @p ptr.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n *\n * @param ptr The pointer to read from.\n * @return The 32-bit big endian integer from the bytes at @p ptr.\n */\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align)\n * @brief Like @ref XXH_readLE32(), but has an option for aligned reads.\n *\n * Affected by @ref XXH_FORCE_MEMORY_ACCESS.\n * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is\n * always @ref XXH_alignment::XXH_unaligned.\n *\n * @param ptr The pointer to read from.\n * @param align Whether @p ptr is aligned.\n * @pre\n *   If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte\n *   aligned.\n * @return The 32-bit little endian integer from the bytes at @p ptr.\n */\n\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n/*\n * Manual byteshift. Best for old compilers which don't inline memcpy.\n * We actually directly use XXH_readLE32 and XXH_readBE32.\n */\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))\n\n/*\n * Force direct memory access. Only works on CPU which support unaligned memory\n * access in hardware.\n */\nstatic xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; }\n\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))\n\n/*\n * __attribute__((aligned(1))) is supported by gcc and clang. Originally the\n * documentation claimed that it only increased the alignment, but actually it\n * can decrease it on gcc, clang, and icc:\n * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,\n * https://gcc.godbolt.org/z/xYez1j67Y.\n */\n#ifdef XXH_OLD_NAMES\ntypedef union { xxh_u32 u32; } __attribute__((__packed__)) unalign;\n#endif\nstatic xxh_u32 XXH_read32(const void* ptr)\n{\n    typedef __attribute__((__aligned__(1))) xxh_u32 xxh_unalign32;\n    return *((const xxh_unalign32*)ptr);\n}\n\n#else\n\n/*\n * Portable and safe solution. Generally efficient.\n * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html\n */\nstatic xxh_u32 XXH_read32(const void* memPtr)\n{\n    xxh_u32 val;\n    XXH_memcpy(&val, memPtr, sizeof(val));\n    return val;\n}\n\n#endif   /* XXH_FORCE_DIRECT_MEMORY_ACCESS */\n\n\n/* ***   Endianness   *** */\n\n/*!\n * @ingroup tuning\n * @def XXH_CPU_LITTLE_ENDIAN\n * @brief Whether the target is little endian.\n *\n * Defined to 1 if the target is little endian, or 0 if it is big endian.\n * It can be defined externally, for example on the compiler command line.\n *\n * If it is not defined,\n * a runtime check (which is usually constant folded) is used instead.\n *\n * @note\n *   This is not necessarily defined to an integer constant.\n *\n * @see XXH_isLittleEndian() for the runtime check.\n */\n#ifndef XXH_CPU_LITTLE_ENDIAN\n/*\n * Try to detect endianness automatically, to avoid the nonstandard behavior\n * in `XXH_isLittleEndian()`\n */\n#  if defined(_WIN32) /* Windows is always little endian */ \\\n     || defined(__LITTLE_ENDIAN__) \\\n     || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#    define XXH_CPU_LITTLE_ENDIAN 1\n#  elif defined(__BIG_ENDIAN__) \\\n     || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#    define XXH_CPU_LITTLE_ENDIAN 0\n#  else\n/*!\n * @internal\n * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN.\n *\n * Most compilers will constant fold this.\n */\nstatic int XXH_isLittleEndian(void)\n{\n    /*\n     * Portable and well-defined behavior.\n     * Don't use static: it is detrimental to performance.\n     */\n    const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 };\n    return one.c[0];\n}\n#   define XXH_CPU_LITTLE_ENDIAN   XXH_isLittleEndian()\n#  endif\n#endif\n\n\n\n\n/* ****************************************\n*  Compiler-specific Functions and Macros\n******************************************/\n#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)\n\n#ifdef __has_builtin\n#  define XXH_HAS_BUILTIN(x) __has_builtin(x)\n#else\n#  define XXH_HAS_BUILTIN(x) 0\n#endif\n\n\n\n/*\n * C23 and future versions have standard \"unreachable()\".\n * Once it has been implemented reliably we can add it as an\n * additional case:\n *\n * ```\n * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN)\n * #  include <stddef.h>\n * #  ifdef unreachable\n * #    define XXH_UNREACHABLE() unreachable()\n * #  endif\n * #endif\n * ```\n *\n * Note C++23 also has std::unreachable() which can be detected\n * as follows:\n * ```\n * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L)\n * #  include <utility>\n * #  define XXH_UNREACHABLE() std::unreachable()\n * #endif\n * ```\n * NB: `__cpp_lib_unreachable` is defined in the `<version>` header.\n * We don't use that as including `<utility>` in `extern \"C\"` blocks\n * doesn't work on GCC12\n */\n\n#if XXH_HAS_BUILTIN(__builtin_unreachable)\n#  define XXH_UNREACHABLE() __builtin_unreachable()\n\n#elif defined(_MSC_VER)\n#  define XXH_UNREACHABLE() __assume(0)\n\n#else\n#  define XXH_UNREACHABLE()\n#endif\n\n#if XXH_HAS_BUILTIN(__builtin_assume)\n#  define XXH_ASSUME(c) __builtin_assume(c)\n#else\n#  define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); }\n#endif\n\n/*!\n * @internal\n * @def XXH_rotl32(x,r)\n * @brief 32-bit rotate left.\n *\n * @param x The 32-bit integer to be rotated.\n * @param r The number of bits to rotate.\n * @pre\n *   @p r > 0 && @p r < 32\n * @note\n *   @p x and @p r may be evaluated multiple times.\n * @return The rotated result.\n */\n#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \\\n                               && XXH_HAS_BUILTIN(__builtin_rotateleft64)\n#  define XXH_rotl32 __builtin_rotateleft32\n#  define XXH_rotl64 __builtin_rotateleft64\n#elif XXH_HAS_BUILTIN(__builtin_stdc_rotate_left)\n#  define XXH_rotl32 __builtin_stdc_rotate_left\n#  define XXH_rotl64 __builtin_stdc_rotate_left\n/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */\n#elif defined(_MSC_VER)\n#  define XXH_rotl32(x,r) _rotl(x,r)\n#  define XXH_rotl64(x,r) _rotl64(x,r)\n#else\n#  define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))\n#  define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))\n#endif\n\n/*!\n * @internal\n * @fn xxh_u32 XXH_swap32(xxh_u32 x)\n * @brief A 32-bit byteswap.\n *\n * @param x The 32-bit integer to byteswap.\n * @return @p x, byteswapped.\n */\n#if defined(_MSC_VER)     /* Visual Studio */\n#  define XXH_swap32 _byteswap_ulong\n#elif XXH_GCC_VERSION >= 403\n#  define XXH_swap32 __builtin_bswap32\n#else\nstatic xxh_u32 XXH_swap32 (xxh_u32 x)\n{\n    return  ((x << 24) & 0xff000000 ) |\n            ((x <<  8) & 0x00ff0000 ) |\n            ((x >>  8) & 0x0000ff00 ) |\n            ((x >> 24) & 0x000000ff );\n}\n#endif\n\n\n/* ***************************\n*  Memory reads\n*****************************/\n\n/*!\n * @internal\n * @brief Enum to indicate whether a pointer is aligned.\n */\ntypedef enum {\n    XXH_aligned,  /*!< Aligned */\n    XXH_unaligned /*!< Possibly unaligned */\n} XXH_alignment;\n\n/*\n * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load.\n *\n * This is ideal for older compilers which don't inline memcpy.\n */\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n\nXXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[0]\n         | ((xxh_u32)bytePtr[1] << 8)\n         | ((xxh_u32)bytePtr[2] << 16)\n         | ((xxh_u32)bytePtr[3] << 24);\n}\n\nXXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[3]\n         | ((xxh_u32)bytePtr[2] << 8)\n         | ((xxh_u32)bytePtr[1] << 16)\n         | ((xxh_u32)bytePtr[0] << 24);\n}\n\n#else\nXXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));\n}\n\nstatic xxh_u32 XXH_readBE32(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);\n}\n#endif\n\nXXH_FORCE_INLINE xxh_u32\nXXH_readLE32_align(const void* ptr, XXH_alignment align)\n{\n    if (align==XXH_unaligned) {\n        return XXH_readLE32(ptr);\n    } else {\n        return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr);\n    }\n}\n\n\n/* *************************************\n*  Misc\n***************************************/\n/*! @ingroup public */\nXXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }\n\n\n/* *******************************************************************\n*  32-bit hash functions\n*********************************************************************/\n/*!\n * @}\n * @defgroup XXH32_impl XXH32 implementation\n * @ingroup impl\n *\n * Details on the XXH32 implementation.\n * @{\n */\n /* #define instead of static const, to be used as initializers */\n#define XXH_PRIME32_1  0x9E3779B1U  /*!< 0b10011110001101110111100110110001 */\n#define XXH_PRIME32_2  0x85EBCA77U  /*!< 0b10000101111010111100101001110111 */\n#define XXH_PRIME32_3  0xC2B2AE3DU  /*!< 0b11000010101100101010111000111101 */\n#define XXH_PRIME32_4  0x27D4EB2FU  /*!< 0b00100111110101001110101100101111 */\n#define XXH_PRIME32_5  0x165667B1U  /*!< 0b00010110010101100110011110110001 */\n\n#ifdef XXH_OLD_NAMES\n#  define PRIME32_1 XXH_PRIME32_1\n#  define PRIME32_2 XXH_PRIME32_2\n#  define PRIME32_3 XXH_PRIME32_3\n#  define PRIME32_4 XXH_PRIME32_4\n#  define PRIME32_5 XXH_PRIME32_5\n#endif\n\n/*!\n * @internal\n * @brief Normal stripe processing routine.\n *\n * This shuffles the bits so that any bit from @p input impacts several bits in\n * @p acc.\n *\n * @param acc The accumulator lane.\n * @param input The stripe of input to mix.\n * @return The mixed accumulator lane.\n */\nstatic xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input)\n{\n    acc += input * XXH_PRIME32_2;\n    acc  = XXH_rotl32(acc, 13);\n    acc *= XXH_PRIME32_1;\n#if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)\n    /*\n     * UGLY HACK:\n     * A compiler fence is used to prevent GCC and Clang from\n     * autovectorizing the XXH32 loop (pragmas and attributes don't work for some\n     * reason) without globally disabling SSE4.1.\n     *\n     * The reason we want to avoid vectorization is because despite working on\n     * 4 integers at a time, there are multiple factors slowing XXH32 down on\n     * SSE4:\n     * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on\n     *   newer chips!) making it slightly slower to multiply four integers at\n     *   once compared to four integers independently. Even when pmulld was\n     *   fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE\n     *   just to multiply unless doing a long operation.\n     *\n     * - Four instructions are required to rotate,\n     *      movqda tmp,  v // not required with VEX encoding\n     *      pslld  tmp, 13 // tmp <<= 13\n     *      psrld  v,   19 // x >>= 19\n     *      por    v,  tmp // x |= tmp\n     *   compared to one for scalar:\n     *      roll   v, 13    // reliably fast across the board\n     *      shldl  v, v, 13 // Sandy Bridge and later prefer this for some reason\n     *\n     * - Instruction level parallelism is actually more beneficial here because\n     *   the SIMD actually serializes this operation: While v1 is rotating, v2\n     *   can load data, while v3 can multiply. SSE forces them to operate\n     *   together.\n     *\n     * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing\n     * the loop. NEON is only faster on the A53, and with the newer cores, it is less\n     * than half the speed.\n     *\n     * Additionally, this is used on WASM SIMD128 because it JITs to the same\n     * SIMD instructions and has the same issue.\n     */\n    XXH_COMPILER_GUARD(acc);\n#endif\n    return acc;\n}\n\n/*!\n * @internal\n * @brief Mixes all bits to finalize the hash.\n *\n * The final mix ensures that all input bits have a chance to impact any bit in\n * the output digest, resulting in an unbiased distribution.\n *\n * @param hash The hash to avalanche.\n * @return The avalanched hash.\n */\nstatic xxh_u32 XXH32_avalanche(xxh_u32 hash)\n{\n    hash ^= hash >> 15;\n    hash *= XXH_PRIME32_2;\n    hash ^= hash >> 13;\n    hash *= XXH_PRIME32_3;\n    hash ^= hash >> 16;\n    return hash;\n}\n\n#define XXH_get32bits(p) XXH_readLE32_align(p, align)\n\n/*!\n * @internal\n * @brief Sets up the initial accumulator state for XXH32().\n */\nXXH_FORCE_INLINE void\nXXH32_initAccs(xxh_u32 *acc, xxh_u32 seed)\n{\n    XXH_ASSERT(acc != NULL);\n    acc[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2;\n    acc[1] = seed + XXH_PRIME32_2;\n    acc[2] = seed + 0;\n    acc[3] = seed - XXH_PRIME32_1;\n}\n\n/*!\n * @internal\n * @brief Consumes a block of data for XXH32().\n *\n * @return the end input pointer.\n */\nXXH_FORCE_INLINE const xxh_u8 *\nXXH32_consumeLong(\n    xxh_u32 *XXH_RESTRICT acc,\n    xxh_u8 const *XXH_RESTRICT input,\n    size_t len,\n    XXH_alignment align\n)\n{\n    const xxh_u8* const bEnd = input + len;\n    const xxh_u8* const limit = bEnd - 15;\n    XXH_ASSERT(acc != NULL);\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(len >= 16);\n    do {\n        acc[0] = XXH32_round(acc[0], XXH_get32bits(input)); input += 4;\n        acc[1] = XXH32_round(acc[1], XXH_get32bits(input)); input += 4;\n        acc[2] = XXH32_round(acc[2], XXH_get32bits(input)); input += 4;\n        acc[3] = XXH32_round(acc[3], XXH_get32bits(input)); input += 4;\n    } while (input < limit);\n\n    return input;\n}\n\n/*!\n * @internal\n * @brief Merges the accumulator lanes together for XXH32()\n */\nXXH_FORCE_INLINE XXH_PUREF xxh_u32\nXXH32_mergeAccs(const xxh_u32 *acc)\n{\n    XXH_ASSERT(acc != NULL);\n    return XXH_rotl32(acc[0], 1)  + XXH_rotl32(acc[1], 7)\n         + XXH_rotl32(acc[2], 12) + XXH_rotl32(acc[3], 18);\n}\n\n/*!\n * @internal\n * @brief Processes the last 0-15 bytes of @p ptr.\n *\n * There may be up to 15 bytes remaining to consume from the input.\n * This final stage will digest them to ensure that all input bytes are present\n * in the final mix.\n *\n * @param hash The hash to finalize.\n * @param ptr The pointer to the remaining input.\n * @param len The remaining length, modulo 16.\n * @param align Whether @p ptr is aligned.\n * @return The finalized hash.\n * @see XXH64_finalize().\n */\nstatic XXH_PUREF xxh_u32\nXXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align)\n{\n#define XXH_PROCESS1 do {                             \\\n    hash += (*ptr++) * XXH_PRIME32_5;                 \\\n    hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1;      \\\n} while (0)\n\n#define XXH_PROCESS4 do {                             \\\n    hash += XXH_get32bits(ptr) * XXH_PRIME32_3;       \\\n    ptr += 4;                                         \\\n    hash  = XXH_rotl32(hash, 17) * XXH_PRIME32_4;     \\\n} while (0)\n\n    if (ptr==NULL) XXH_ASSERT(len == 0);\n\n    /* Compact rerolled version; generally faster */\n    if (!XXH32_ENDJMP) {\n        len &= 15;\n        while (len >= 4) {\n            XXH_PROCESS4;\n            len -= 4;\n        }\n        while (len > 0) {\n            XXH_PROCESS1;\n            --len;\n        }\n        return XXH32_avalanche(hash);\n    } else {\n         switch(len&15) /* or switch(bEnd - p) */ {\n           case 12:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 8:       XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 4:       XXH_PROCESS4;\n                         return XXH32_avalanche(hash);\n\n           case 13:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 9:       XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 5:       XXH_PROCESS4;\n                         XXH_PROCESS1;\n                         return XXH32_avalanche(hash);\n\n           case 14:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 10:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 6:       XXH_PROCESS4;\n                         XXH_PROCESS1;\n                         XXH_PROCESS1;\n                         return XXH32_avalanche(hash);\n\n           case 15:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 11:      XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 7:       XXH_PROCESS4;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 3:       XXH_PROCESS1;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 2:       XXH_PROCESS1;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 1:       XXH_PROCESS1;\n                         XXH_FALLTHROUGH;  /* fallthrough */\n           case 0:       return XXH32_avalanche(hash);\n        }\n        XXH_ASSERT(0);\n        return hash;   /* reaching this point is deemed impossible */\n    }\n}\n\n#ifdef XXH_OLD_NAMES\n#  define PROCESS1 XXH_PROCESS1\n#  define PROCESS4 XXH_PROCESS4\n#else\n#  undef XXH_PROCESS1\n#  undef XXH_PROCESS4\n#endif\n\n/*!\n * @internal\n * @brief The implementation for @ref XXH32().\n *\n * @param input , len , seed Directly passed from @ref XXH32().\n * @param align Whether @p input is aligned.\n * @return The calculated hash.\n */\nXXH_FORCE_INLINE XXH_PUREF xxh_u32\nXXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align)\n{\n    xxh_u32 h32;\n\n    if (input==NULL) XXH_ASSERT(len == 0);\n\n    if (len>=16) {\n        xxh_u32 acc[4];\n        XXH32_initAccs(acc, seed);\n\n        input = XXH32_consumeLong(acc, input, len, align);\n\n        h32 = XXH32_mergeAccs(acc);\n    } else {\n        h32  = seed + XXH_PRIME32_5;\n    }\n\n    h32 += (xxh_u32)len;\n\n    return XXH32_finalize(h32, input, len&15, align);\n}\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed)\n{\n#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2\n    /* Simple version, good for code maintenance, but unfortunately slow for small inputs */\n    XXH32_state_t state;\n    XXH32_reset(&state, seed);\n    XXH32_update(&state, (const xxh_u8*)input, len);\n    return XXH32_digest(&state);\n#else\n    if (XXH_FORCE_ALIGN_CHECK) {\n        if ((((size_t)input) & 3) == 0) {   /* Input is 4-bytes aligned, leverage the speed benefit */\n            return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);\n    }   }\n\n    return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);\n#endif\n}\n\n\n\n/*******   Hash streaming   *******/\n#ifndef XXH_NO_STREAM\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)\n{\n    return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));\n}\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)\n{\n    XXH_free(statePtr);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)\n{\n    XXH_memcpy(dstState, srcState, sizeof(*dstState));\n}\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed)\n{\n    XXH_ASSERT(statePtr != NULL);\n    memset(statePtr, 0, sizeof(*statePtr));\n    XXH32_initAccs(statePtr->acc, seed);\n    return XXH_OK;\n}\n\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH32_update(XXH32_state_t* state, const void* input, size_t len)\n{\n    if (input==NULL) {\n        XXH_ASSERT(len == 0);\n        return XXH_OK;\n    }\n\n    state->total_len_32 += (XXH32_hash_t)len;\n    state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16));\n\n    XXH_ASSERT(state->bufferedSize < sizeof(state->buffer));\n    if (len < sizeof(state->buffer) - state->bufferedSize)  {   /* fill in tmp buffer */\n        XXH_memcpy(state->buffer + state->bufferedSize, input, len);\n        state->bufferedSize += (XXH32_hash_t)len;\n        return XXH_OK;\n    }\n\n    {   const xxh_u8* xinput = (const xxh_u8*)input;\n        const xxh_u8* const bEnd = xinput + len;\n\n        if (state->bufferedSize) {   /* non-empty buffer: complete first */\n            XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize);\n            xinput += sizeof(state->buffer) - state->bufferedSize;\n            /* then process one round */\n            (void)XXH32_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned);\n            state->bufferedSize = 0;\n        }\n\n        XXH_ASSERT(xinput <= bEnd);\n        if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) {\n            /* Process the remaining data */\n            xinput = XXH32_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned);\n        }\n\n        if (xinput < bEnd) {\n            /* Copy the leftover to the tmp buffer */\n            XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput));\n            state->bufferedSize = (unsigned)(bEnd-xinput);\n        }\n    }\n\n    return XXH_OK;\n}\n\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state)\n{\n    xxh_u32 h32;\n\n    if (state->large_len) {\n        h32 = XXH32_mergeAccs(state->acc);\n    } else {\n        h32 = state->acc[2] /* == seed */ + XXH_PRIME32_5;\n    }\n\n    h32 += state->total_len_32;\n\n    return XXH32_finalize(h32, state->buffer, state->bufferedSize, XXH_aligned);\n}\n#endif /* !XXH_NO_STREAM */\n\n/*******   Canonical representation   *******/\n\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)\n{\n    XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));\n    if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);\n    XXH_memcpy(dst, &hash, sizeof(*dst));\n}\n/*! @ingroup XXH32_family */\nXXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)\n{\n    return XXH_readBE32(src);\n}\n\n\n#ifndef XXH_NO_LONG_LONG\n\n/* *******************************************************************\n*  64-bit hash functions\n*********************************************************************/\n/*!\n * @}\n * @ingroup impl\n * @{\n */\n/*******   Memory access   *******/\n\ntypedef XXH64_hash_t xxh_u64;\n\n#ifdef XXH_OLD_NAMES\n#  define U64 xxh_u64\n#endif\n\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n/*\n * Manual byteshift. Best for old compilers which don't inline memcpy.\n * We actually directly use XXH_readLE64 and XXH_readBE64.\n */\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))\n\n/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */\nstatic xxh_u64 XXH_read64(const void* memPtr)\n{\n    return *(const xxh_u64*) memPtr;\n}\n\n#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))\n\n/*\n * __attribute__((aligned(1))) is supported by gcc and clang. Originally the\n * documentation claimed that it only increased the alignment, but actually it\n * can decrease it on gcc, clang, and icc:\n * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,\n * https://gcc.godbolt.org/z/xYez1j67Y.\n */\n#ifdef XXH_OLD_NAMES\ntypedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((__packed__)) unalign64;\n#endif\nstatic xxh_u64 XXH_read64(const void* ptr)\n{\n    typedef __attribute__((__aligned__(1))) xxh_u64 xxh_unalign64;\n    return *((const xxh_unalign64*)ptr);\n}\n\n#else\n\n/*\n * Portable and safe solution. Generally efficient.\n * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html\n */\nstatic xxh_u64 XXH_read64(const void* memPtr)\n{\n    xxh_u64 val;\n    XXH_memcpy(&val, memPtr, sizeof(val));\n    return val;\n}\n\n#endif   /* XXH_FORCE_DIRECT_MEMORY_ACCESS */\n\n#if defined(_MSC_VER)     /* Visual Studio */\n#  define XXH_swap64 _byteswap_uint64\n#elif XXH_GCC_VERSION >= 403\n#  define XXH_swap64 __builtin_bswap64\n#else\nstatic xxh_u64 XXH_swap64(xxh_u64 x)\n{\n    return  ((x << 56) & 0xff00000000000000ULL) |\n            ((x << 40) & 0x00ff000000000000ULL) |\n            ((x << 24) & 0x0000ff0000000000ULL) |\n            ((x << 8)  & 0x000000ff00000000ULL) |\n            ((x >> 8)  & 0x00000000ff000000ULL) |\n            ((x >> 24) & 0x0000000000ff0000ULL) |\n            ((x >> 40) & 0x000000000000ff00ULL) |\n            ((x >> 56) & 0x00000000000000ffULL);\n}\n#endif\n\n\n/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */\n#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))\n\nXXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[0]\n         | ((xxh_u64)bytePtr[1] << 8)\n         | ((xxh_u64)bytePtr[2] << 16)\n         | ((xxh_u64)bytePtr[3] << 24)\n         | ((xxh_u64)bytePtr[4] << 32)\n         | ((xxh_u64)bytePtr[5] << 40)\n         | ((xxh_u64)bytePtr[6] << 48)\n         | ((xxh_u64)bytePtr[7] << 56);\n}\n\nXXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr)\n{\n    const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;\n    return bytePtr[7]\n         | ((xxh_u64)bytePtr[6] << 8)\n         | ((xxh_u64)bytePtr[5] << 16)\n         | ((xxh_u64)bytePtr[4] << 24)\n         | ((xxh_u64)bytePtr[3] << 32)\n         | ((xxh_u64)bytePtr[2] << 40)\n         | ((xxh_u64)bytePtr[1] << 48)\n         | ((xxh_u64)bytePtr[0] << 56);\n}\n\n#else\nXXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));\n}\n\nstatic xxh_u64 XXH_readBE64(const void* ptr)\n{\n    return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);\n}\n#endif\n\nXXH_FORCE_INLINE xxh_u64\nXXH_readLE64_align(const void* ptr, XXH_alignment align)\n{\n    if (align==XXH_unaligned)\n        return XXH_readLE64(ptr);\n    else\n        return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr);\n}\n\n\n/*******   xxh64   *******/\n/*!\n * @}\n * @defgroup XXH64_impl XXH64 implementation\n * @ingroup impl\n *\n * Details on the XXH64 implementation.\n * @{\n */\n/* #define rather that static const, to be used as initializers */\n#define XXH_PRIME64_1  0x9E3779B185EBCA87ULL  /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */\n#define XXH_PRIME64_2  0xC2B2AE3D27D4EB4FULL  /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */\n#define XXH_PRIME64_3  0x165667B19E3779F9ULL  /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */\n#define XXH_PRIME64_4  0x85EBCA77C2B2AE63ULL  /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */\n#define XXH_PRIME64_5  0x27D4EB2F165667C5ULL  /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */\n\n#ifdef XXH_OLD_NAMES\n#  define PRIME64_1 XXH_PRIME64_1\n#  define PRIME64_2 XXH_PRIME64_2\n#  define PRIME64_3 XXH_PRIME64_3\n#  define PRIME64_4 XXH_PRIME64_4\n#  define PRIME64_5 XXH_PRIME64_5\n#endif\n\n/*! @copydoc XXH32_round */\nstatic xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input)\n{\n    acc += input * XXH_PRIME64_2;\n    acc  = XXH_rotl64(acc, 31);\n    acc *= XXH_PRIME64_1;\n#if (defined(__AVX512F__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)\n    /*\n     * DISABLE AUTOVECTORIZATION:\n     * A compiler fence is used to prevent GCC and Clang from\n     * autovectorizing the XXH64 loop (pragmas and attributes don't work for some\n     * reason) without globally disabling AVX512.\n     *\n     * Autovectorization of XXH64 tends to be detrimental,\n     * though the exact outcome may change depending on exact cpu and compiler version.\n     * For information, it has been reported as detrimental for Skylake-X,\n     * but possibly beneficial for Zen4.\n     *\n     * The default is to disable auto-vectorization,\n     * but you can select to enable it instead using `XXH_ENABLE_AUTOVECTORIZE` build variable.\n     */\n    XXH_COMPILER_GUARD(acc);\n#endif\n    return acc;\n}\n\nstatic xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val)\n{\n    val  = XXH64_round(0, val);\n    acc ^= val;\n    acc  = acc * XXH_PRIME64_1 + XXH_PRIME64_4;\n    return acc;\n}\n\n/*! @copydoc XXH32_avalanche */\nstatic xxh_u64 XXH64_avalanche(xxh_u64 hash)\n{\n    hash ^= hash >> 33;\n    hash *= XXH_PRIME64_2;\n    hash ^= hash >> 29;\n    hash *= XXH_PRIME64_3;\n    hash ^= hash >> 32;\n    return hash;\n}\n\n\n#define XXH_get64bits(p) XXH_readLE64_align(p, align)\n\n/*!\n * @internal\n * @brief Sets up the initial accumulator state for XXH64().\n */\nXXH_FORCE_INLINE void\nXXH64_initAccs(xxh_u64 *acc, xxh_u64 seed)\n{\n    XXH_ASSERT(acc != NULL);\n    acc[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2;\n    acc[1] = seed + XXH_PRIME64_2;\n    acc[2] = seed + 0;\n    acc[3] = seed - XXH_PRIME64_1;\n}\n\n/*!\n * @internal\n * @brief Consumes a block of data for XXH64().\n *\n * @return the end input pointer.\n */\nXXH_FORCE_INLINE const xxh_u8 *\nXXH64_consumeLong(\n    xxh_u64 *XXH_RESTRICT acc,\n    xxh_u8 const *XXH_RESTRICT input,\n    size_t len,\n    XXH_alignment align\n)\n{\n    const xxh_u8* const bEnd = input + len;\n    const xxh_u8* const limit = bEnd - 31;\n    XXH_ASSERT(acc != NULL);\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(len >= 32);\n    do {\n        /* reroll on 32-bit */\n        if (sizeof(void *) < sizeof(xxh_u64)) {\n            size_t i;\n            for (i = 0; i < 4; i++) {\n                acc[i] = XXH64_round(acc[i], XXH_get64bits(input));\n                input += 8;\n            }\n        } else {\n            acc[0] = XXH64_round(acc[0], XXH_get64bits(input)); input += 8;\n            acc[1] = XXH64_round(acc[1], XXH_get64bits(input)); input += 8;\n            acc[2] = XXH64_round(acc[2], XXH_get64bits(input)); input += 8;\n            acc[3] = XXH64_round(acc[3], XXH_get64bits(input)); input += 8;\n        }\n    } while (input < limit);\n\n    return input;\n}\n\n/*!\n * @internal\n * @brief Merges the accumulator lanes together for XXH64()\n */\nXXH_FORCE_INLINE XXH_PUREF xxh_u64\nXXH64_mergeAccs(const xxh_u64 *acc)\n{\n    XXH_ASSERT(acc != NULL);\n    {\n        xxh_u64 h64 = XXH_rotl64(acc[0], 1) + XXH_rotl64(acc[1], 7)\n                    + XXH_rotl64(acc[2], 12) + XXH_rotl64(acc[3], 18);\n        /* reroll on 32-bit */\n        if (sizeof(void *) < sizeof(xxh_u64)) {\n            size_t i;\n            for (i = 0; i < 4; i++) {\n                h64 = XXH64_mergeRound(h64, acc[i]);\n            }\n        } else {\n            h64 = XXH64_mergeRound(h64, acc[0]);\n            h64 = XXH64_mergeRound(h64, acc[1]);\n            h64 = XXH64_mergeRound(h64, acc[2]);\n            h64 = XXH64_mergeRound(h64, acc[3]);\n        }\n        return h64;\n    }\n}\n\n/*!\n * @internal\n * @brief Processes the last 0-31 bytes of @p ptr.\n *\n * There may be up to 31 bytes remaining to consume from the input.\n * This final stage will digest them to ensure that all input bytes are present\n * in the final mix.\n *\n * @param hash The hash to finalize.\n * @param ptr The pointer to the remaining input.\n * @param len The remaining length, modulo 32.\n * @param align Whether @p ptr is aligned.\n * @return The finalized hash\n * @see XXH32_finalize().\n */\nXXH_STATIC XXH_PUREF xxh_u64\nXXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align)\n{\n    if (ptr==NULL) XXH_ASSERT(len == 0);\n    len &= 31;\n    while (len >= 8) {\n        xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr));\n        ptr += 8;\n        hash ^= k1;\n        hash  = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4;\n        len -= 8;\n    }\n    if (len >= 4) {\n        hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1;\n        ptr += 4;\n        hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;\n        len -= 4;\n    }\n    while (len > 0) {\n        hash ^= (*ptr++) * XXH_PRIME64_5;\n        hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1;\n        --len;\n    }\n    return  XXH64_avalanche(hash);\n}\n\n#ifdef XXH_OLD_NAMES\n#  define PROCESS1_64 XXH_PROCESS1_64\n#  define PROCESS4_64 XXH_PROCESS4_64\n#  define PROCESS8_64 XXH_PROCESS8_64\n#else\n#  undef XXH_PROCESS1_64\n#  undef XXH_PROCESS4_64\n#  undef XXH_PROCESS8_64\n#endif\n\n/*!\n * @internal\n * @brief The implementation for @ref XXH64().\n *\n * @param input , len , seed Directly passed from @ref XXH64().\n * @param align Whether @p input is aligned.\n * @return The calculated hash.\n */\nXXH_FORCE_INLINE XXH_PUREF xxh_u64\nXXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align)\n{\n    xxh_u64 h64;\n    if (input==NULL) XXH_ASSERT(len == 0);\n\n    if (len>=32) {  /* Process a large block of data */\n        xxh_u64 acc[4];\n        XXH64_initAccs(acc, seed);\n\n        input = XXH64_consumeLong(acc, input, len, align);\n\n        h64 = XXH64_mergeAccs(acc);\n    } else {\n        h64  = seed + XXH_PRIME64_5;\n    }\n\n    h64 += (xxh_u64) len;\n\n    return XXH64_finalize(h64, input, len, align);\n}\n\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH64_hash_t XXH64 (XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)\n{\n#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2\n    /* Simple version, good for code maintenance, but unfortunately slow for small inputs */\n    XXH64_state_t state;\n    XXH64_reset(&state, seed);\n    XXH64_update(&state, (const xxh_u8*)input, len);\n    return XXH64_digest(&state);\n#else\n    if (XXH_FORCE_ALIGN_CHECK) {\n        if ((((size_t)input) & 7)==0) {  /* Input is aligned, let's leverage the speed advantage */\n            return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);\n    }   }\n\n    return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);\n\n#endif\n}\n\n/*******   Hash Streaming   *******/\n#ifndef XXH_NO_STREAM\n/*! @ingroup XXH64_family*/\nXXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)\n{\n    return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));\n}\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)\n{\n    XXH_free(statePtr);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState)\n{\n    XXH_memcpy(dstState, srcState, sizeof(*dstState));\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed)\n{\n    XXH_ASSERT(statePtr != NULL);\n    memset(statePtr, 0, sizeof(*statePtr));\n    XXH64_initAccs(statePtr->acc, seed);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len)\n{\n    if (input==NULL) {\n        XXH_ASSERT(len == 0);\n        return XXH_OK;\n    }\n\n    state->total_len += len;\n\n    XXH_ASSERT(state->bufferedSize <= sizeof(state->buffer));\n    if (len < sizeof(state->buffer) - state->bufferedSize)  {   /* fill in tmp buffer */\n        XXH_memcpy(state->buffer + state->bufferedSize, input, len);\n        state->bufferedSize += (XXH32_hash_t)len;\n        return XXH_OK;\n    }\n\n    {   const xxh_u8* xinput = (const xxh_u8*)input;\n        const xxh_u8* const bEnd = xinput + len;\n\n        if (state->bufferedSize) {   /* non-empty buffer => complete first */\n            XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize);\n            xinput += sizeof(state->buffer) - state->bufferedSize;\n            /* and process one round */\n            (void)XXH64_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned);\n            state->bufferedSize = 0;\n        }\n\n        XXH_ASSERT(xinput <= bEnd);\n        if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) {\n            /* Process the remaining data */\n            xinput = XXH64_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned);\n        }\n\n        if (xinput < bEnd) {\n            /* Copy the leftover to the tmp buffer */\n            XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput));\n            state->bufferedSize = (unsigned)(bEnd-xinput);\n        }\n    }\n\n    return XXH_OK;\n}\n\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state)\n{\n    xxh_u64 h64;\n\n    if (state->total_len >= 32) {\n        h64 = XXH64_mergeAccs(state->acc);\n    } else {\n        h64  = state->acc[2] /*seed*/ + XXH_PRIME64_5;\n    }\n\n    h64 += (xxh_u64) state->total_len;\n\n    return XXH64_finalize(h64, state->buffer, (size_t)state->total_len, XXH_aligned);\n}\n#endif /* !XXH_NO_STREAM */\n\n/******* Canonical representation   *******/\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash)\n{\n    XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));\n    if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);\n    XXH_memcpy(dst, &hash, sizeof(*dst));\n}\n\n/*! @ingroup XXH64_family */\nXXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src)\n{\n    return XXH_readBE64(src);\n}\n\n#ifndef XXH_NO_XXH3\n\n/* *********************************************************************\n*  XXH3\n*  New generation hash designed for speed on small keys and vectorization\n************************************************************************ */\n/*!\n * @}\n * @defgroup XXH3_impl XXH3 implementation\n * @ingroup impl\n * @{\n */\n\n/* ===   Compiler specifics   === */\n\n\n#if (defined(__GNUC__) && (__GNUC__ >= 3))  \\\n  || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \\\n  || defined(__clang__)\n#    define XXH_likely(x) __builtin_expect(x, 1)\n#    define XXH_unlikely(x) __builtin_expect(x, 0)\n#else\n#    define XXH_likely(x) (x)\n#    define XXH_unlikely(x) (x)\n#endif\n\n#ifndef XXH_HAS_INCLUDE\n#  ifdef __has_include\n/*\n * Not defined as XXH_HAS_INCLUDE(x) (function-like) because\n * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion)\n */\n#    define XXH_HAS_INCLUDE __has_include\n#  else\n#    define XXH_HAS_INCLUDE(x) 0\n#  endif\n#endif\n\n#if defined(__GNUC__) || defined(__clang__)\n#  if defined(__ARM_FEATURE_SVE)\n#    include <arm_sve.h>\n#  endif\n#  if defined(__ARM_NEON__) || defined(__ARM_NEON) \\\n   || (defined(_M_ARM) && _M_ARM >= 7) \\\n   || defined(_M_ARM64) || defined(_M_ARM64EC) \\\n   || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* WASM SIMD128 via SIMDe */\n#    define inline __inline__  /* circumvent a clang bug */\n#    include <arm_neon.h>\n#    undef inline\n#  elif defined(__AVX2__)\n#    include <immintrin.h>\n#  elif defined(__SSE2__)\n#    include <emmintrin.h>\n#  elif defined(__loongarch_sx)\n#    include <lsxintrin.h>\n#  endif\n#endif\n\n#if defined(_MSC_VER)\n#  include <intrin.h>\n#endif\n\n/*\n * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while\n * remaining a true 64-bit/128-bit hash function.\n *\n * This is done by prioritizing a subset of 64-bit operations that can be\n * emulated without too many steps on the average 32-bit machine.\n *\n * For example, these two lines seem similar, and run equally fast on 64-bit:\n *\n *   xxh_u64 x;\n *   x ^= (x >> 47); // good\n *   x ^= (x >> 13); // bad\n *\n * However, to a 32-bit machine, there is a major difference.\n *\n * x ^= (x >> 47) looks like this:\n *\n *   x.lo ^= (x.hi >> (47 - 32));\n *\n * while x ^= (x >> 13) looks like this:\n *\n *   // note: funnel shifts are not usually cheap.\n *   x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13));\n *   x.hi ^= (x.hi >> 13);\n *\n * The first one is significantly faster than the second, simply because the\n * shift is larger than 32. This means:\n *  - All the bits we need are in the upper 32 bits, so we can ignore the lower\n *    32 bits in the shift.\n *  - The shift result will always fit in the lower 32 bits, and therefore,\n *    we can ignore the upper 32 bits in the xor.\n *\n * Thanks to this optimization, XXH3 only requires these features to be efficient:\n *\n *  - Usable unaligned access\n *  - A 32-bit or 64-bit ALU\n *      - If 32-bit, a decent ADC instruction\n *  - A 32 or 64-bit multiply with a 64-bit result\n *  - For the 128-bit variant, a decent byteswap helps short inputs.\n *\n * The first two are already required by XXH32, and almost all 32-bit and 64-bit\n * platforms which can run XXH32 can run XXH3 efficiently.\n *\n * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one\n * notable exception.\n *\n * First of all, Thumb-1 lacks support for the UMULL instruction which\n * performs the important long multiply. This means numerous __aeabi_lmul\n * calls.\n *\n * Second of all, the 8 functional registers are just not enough.\n * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need\n * Lo registers, and this shuffling results in thousands more MOVs than A32.\n *\n * A32 and T32 don't have this limitation. They can access all 14 registers,\n * do a 32->64 multiply with UMULL, and the flexible operand allowing free\n * shifts is helpful, too.\n *\n * Therefore, we do a quick sanity check.\n *\n * If compiling Thumb-1 for a target which supports ARM instructions, we will\n * emit a warning, as it is not a \"sane\" platform to compile for.\n *\n * Usually, if this happens, it is because of an accident and you probably need\n * to specify -march, as you likely meant to compile for a newer architecture.\n *\n * Credit: large sections of the vectorial and asm source code paths\n *         have been contributed by @easyaspi314\n */\n#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM)\n#   warning \"XXH3 is highly inefficient without ARM or Thumb-2.\"\n#endif\n\n/* ==========================================\n * Vectorization detection\n * ========================================== */\n\n#ifdef XXH_DOXYGEN\n/*!\n * @ingroup tuning\n * @brief Overrides the vectorization implementation chosen for XXH3.\n *\n * Can be defined to 0 to disable SIMD or any of the values mentioned in\n * @ref XXH_VECTOR_TYPE.\n *\n * If this is not defined, it uses predefined macros to determine the best\n * implementation.\n */\n#  define XXH_VECTOR XXH_SCALAR\n/*!\n * @ingroup tuning\n * @brief Selects the minimum alignment for XXH3's accumulators.\n *\n * When using SIMD, this should match the alignment required for said vector\n * type, so, for example, 32 for AVX2.\n *\n * Default: Auto detected.\n */\n#  define XXH_ACC_ALIGN 8\n#endif\n\n/* Actual definition */\n#ifndef XXH_DOXYGEN\n#endif\n\n#ifndef XXH_VECTOR    /* can be defined on command line */\n#  if defined(__ARM_FEATURE_SVE)\n#    define XXH_VECTOR XXH_SVE\n#  elif ( \\\n        defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \\\n     || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \\\n     || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* wasm simd128 via SIMDe */ \\\n   ) && ( \\\n        defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \\\n    || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \\\n   )\n#    define XXH_VECTOR XXH_NEON\n#  elif defined(__AVX512F__)\n#    define XXH_VECTOR XXH_AVX512\n#  elif defined(__AVX2__)\n#    define XXH_VECTOR XXH_AVX2\n#  elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2))\n#    define XXH_VECTOR XXH_SSE2\n#  elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \\\n     || (defined(__s390x__) && defined(__VEC__)) \\\n     && defined(__GNUC__) /* TODO: IBM XL */\n#    define XXH_VECTOR XXH_VSX\n#  elif defined(__loongarch_sx)\n#    define XXH_VECTOR XXH_LSX\n#  else\n#    define XXH_VECTOR XXH_SCALAR\n#  endif\n#endif\n\n/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */\n#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE)\n#  ifdef _MSC_VER\n#    pragma warning(once : 4606)\n#  else\n#    warning \"__ARM_FEATURE_SVE isn't supported. Use SCALAR instead.\"\n#  endif\n#  undef XXH_VECTOR\n#  define XXH_VECTOR XXH_SCALAR\n#endif\n\n/*\n * Controls the alignment of the accumulator,\n * for compatibility with aligned vector loads, which are usually faster.\n */\n#ifndef XXH_ACC_ALIGN\n#  if defined(XXH_X86DISPATCH)\n#     define XXH_ACC_ALIGN 64  /* for compatibility with avx512 */\n#  elif XXH_VECTOR == XXH_SCALAR  /* scalar */\n#     define XXH_ACC_ALIGN 8\n#  elif XXH_VECTOR == XXH_SSE2  /* sse2 */\n#     define XXH_ACC_ALIGN 16\n#  elif XXH_VECTOR == XXH_AVX2  /* avx2 */\n#     define XXH_ACC_ALIGN 32\n#  elif XXH_VECTOR == XXH_NEON  /* neon */\n#     define XXH_ACC_ALIGN 16\n#  elif XXH_VECTOR == XXH_VSX   /* vsx */\n#     define XXH_ACC_ALIGN 16\n#  elif XXH_VECTOR == XXH_AVX512  /* avx512 */\n#     define XXH_ACC_ALIGN 64\n#  elif XXH_VECTOR == XXH_SVE   /* sve */\n#     define XXH_ACC_ALIGN 64\n#  elif XXH_VECTOR == XXH_LSX   /* lsx */\n#     define XXH_ACC_ALIGN 64\n#  endif\n#endif\n\n#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \\\n    || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512\n#  define XXH_SEC_ALIGN XXH_ACC_ALIGN\n#elif XXH_VECTOR == XXH_SVE\n#  define XXH_SEC_ALIGN XXH_ACC_ALIGN\n#else\n#  define XXH_SEC_ALIGN 8\n#endif\n\n#if defined(__GNUC__) || defined(__clang__)\n#  define XXH_ALIASING __attribute__((__may_alias__))\n#else\n#  define XXH_ALIASING /* nothing */\n#endif\n\n/*\n * UGLY HACK:\n * GCC usually generates the best code with -O3 for xxHash.\n *\n * However, when targeting AVX2, it is overzealous in its unrolling resulting\n * in code roughly 3/4 the speed of Clang.\n *\n * There are other issues, such as GCC splitting _mm256_loadu_si256 into\n * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which\n * only applies to Sandy and Ivy Bridge... which don't even support AVX2.\n *\n * That is why when compiling the AVX2 version, it is recommended to use either\n *   -O2 -mavx2 -march=haswell\n * or\n *   -O2 -mavx2 -mno-avx256-split-unaligned-load\n * for decent performance, or to use Clang instead.\n *\n * Fortunately, we can control the first one with a pragma that forces GCC into\n * -O2, but the other one we can't control without \"failed to inline always\n * inline function due to target mismatch\" warnings.\n */\n#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \\\n  && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \\\n  && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */\n#  pragma GCC push_options\n#  pragma GCC optimize(\"-O2\")\n#endif\n\n#if XXH_VECTOR == XXH_NEON\n\n/*\n * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3\n * optimizes out the entire hashLong loop because of the aliasing violation.\n *\n * However, GCC is also inefficient at load-store optimization with vld1q/vst1q,\n * so the only option is to mark it as aliasing.\n */\ntypedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING;\n\n/*!\n * @internal\n * @brief `vld1q_u64` but faster and alignment-safe.\n *\n * On AArch64, unaligned access is always safe, but on ARMv7-a, it is only\n * *conditionally* safe (`vld1` has an alignment bit like `movdq[ua]` in x86).\n *\n * GCC for AArch64 sees `vld1q_u8` as an intrinsic instead of a load, so it\n * prohibits load-store optimizations. Therefore, a direct dereference is used.\n *\n * Otherwise, `vld1q_u8` is used with `vreinterpretq_u8_u64` to do a safe\n * unaligned load.\n */\n#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__)\nXXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */\n{\n    return *(xxh_aliasing_uint64x2_t const *)ptr;\n}\n#else\nXXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr)\n{\n    return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr));\n}\n#endif\n\n/*!\n * @internal\n * @brief `vmlal_u32` on low and high halves of a vector.\n *\n * This is a workaround for AArch64 GCC < 11 which implemented arm_neon.h with\n * inline assembly and were therefore incapable of merging the `vget_{low, high}_u32`\n * with `vmlal_u32`.\n */\n#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    /* Inline assembly is the only way */\n    __asm__(\"umlal   %0.2d, %1.2s, %2.2s\" : \"+w\" (acc) : \"w\" (lhs), \"w\" (rhs));\n    return acc;\n}\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    /* This intrinsic works as expected */\n    return vmlal_high_u32(acc, lhs, rhs);\n}\n#else\n/* Portable intrinsic versions */\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs));\n}\n/*! @copydoc XXH_vmlal_low_u32\n * Assume the compiler converts this to vmlal_high_u32 on aarch64 */\nXXH_FORCE_INLINE uint64x2_t\nXXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)\n{\n    return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs));\n}\n#endif\n\n/*!\n * @ingroup tuning\n * @brief Controls the NEON to scalar ratio for XXH3\n *\n * This can be set to 2, 4, 6, or 8.\n *\n * ARM Cortex CPUs are _very_ sensitive to how their pipelines are used.\n *\n * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but only 2 of those\n * can be NEON. If you are only using NEON instructions, you are only using 2/3 of the CPU\n * bandwidth.\n *\n * This is even more noticeable on the more advanced cores like the Cortex-A76 which\n * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once.\n *\n * Therefore, to make the most out of the pipeline, it is beneficial to run 6 NEON lanes\n * and 2 scalar lanes, which is chosen by default.\n *\n * This does not apply to Apple processors or 32-bit processors, which run better with\n * full NEON. These will default to 8. Additionally, size-optimized builds run 8 lanes.\n *\n * This change benefits CPUs with large micro-op buffers without negatively affecting\n * most other CPUs:\n *\n *  | Chipset               | Dispatch type       | NEON only | 6:2 hybrid | Diff. |\n *  |:----------------------|:--------------------|----------:|-----------:|------:|\n *  | Snapdragon 730 (A76)  | 2 NEON/8 micro-ops  |  8.8 GB/s |  10.1 GB/s |  ~16% |\n *  | Snapdragon 835 (A73)  | 2 NEON/3 micro-ops  |  5.1 GB/s |   5.3 GB/s |   ~5% |\n *  | Marvell PXA1928 (A53) | In-order dual-issue |  1.9 GB/s |   1.9 GB/s |    0% |\n *  | Apple M1              | 4 NEON/8 micro-ops  | 37.3 GB/s |  36.1 GB/s |  ~-3% |\n *\n * It also seems to fix some bad codegen on GCC, making it almost as fast as clang.\n *\n * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning\n * it effectively becomes worse 4.\n *\n * @see XXH3_accumulate_512_neon()\n */\n# ifndef XXH3_NEON_LANES\n#  if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \\\n   && !defined(__APPLE__) && XXH_SIZE_OPT <= 0\n#   define XXH3_NEON_LANES 6\n#  else\n#   define XXH3_NEON_LANES XXH_ACC_NB\n#  endif\n# endif\n#endif  /* XXH_VECTOR == XXH_NEON */\n\n/*\n * VSX and Z Vector helpers.\n *\n * This is very messy, and any pull requests to clean this up are welcome.\n *\n * There are a lot of problems with supporting VSX and s390x, due to\n * inconsistent intrinsics, spotty coverage, and multiple endiannesses.\n */\n#if XXH_VECTOR == XXH_VSX\n/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`,\n * and `pixel`. This is a problem for obvious reasons.\n *\n * These keywords are unnecessary; the spec literally says they are\n * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd\n * after including the header.\n *\n * We use pragma push_macro/pop_macro to keep the namespace clean. */\n#  pragma push_macro(\"bool\")\n#  pragma push_macro(\"vector\")\n#  pragma push_macro(\"pixel\")\n/* silence potential macro redefined warnings */\n#  undef bool\n#  undef vector\n#  undef pixel\n\n#  if defined(__s390x__)\n#    include <s390intrin.h>\n#  else\n#    include <altivec.h>\n#  endif\n\n/* Restore the original macro values, if applicable. */\n#  pragma pop_macro(\"pixel\")\n#  pragma pop_macro(\"vector\")\n#  pragma pop_macro(\"bool\")\n\ntypedef __vector unsigned long long xxh_u64x2;\ntypedef __vector unsigned char xxh_u8x16;\ntypedef __vector unsigned xxh_u32x4;\n\n/*\n * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue.\n */\ntypedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING;\n\n# ifndef XXH_VSX_BE\n#  if defined(__BIG_ENDIAN__) \\\n  || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#    define XXH_VSX_BE 1\n#  elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__\n#    warning \"-maltivec=be is not recommended. Please use native endianness.\"\n#    define XXH_VSX_BE 1\n#  else\n#    define XXH_VSX_BE 0\n#  endif\n# endif /* !defined(XXH_VSX_BE) */\n\n# if XXH_VSX_BE\n#  if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__))\n#    define XXH_vec_revb vec_revb\n#  else\n/*!\n * A polyfill for POWER9's vec_revb().\n */\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val)\n{\n    xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,\n                                  0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 };\n    return vec_perm(val, val, vByteSwap);\n}\n#  endif\n# endif /* XXH_VSX_BE */\n\n/*!\n * Performs an unaligned vector load and byte swaps it on big endian.\n */\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr)\n{\n    xxh_u64x2 ret;\n    XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2));\n# if XXH_VSX_BE\n    ret = XXH_vec_revb(ret);\n# endif\n    return ret;\n}\n\n/*\n * vec_mulo and vec_mule are very problematic intrinsics on PowerPC\n *\n * These intrinsics weren't added until GCC 8, despite existing for a while,\n * and they are endian dependent. Also, their meaning swap depending on version.\n * */\n# if defined(__s390x__)\n /* s390x is always big endian, no issue on this platform */\n#  define XXH_vec_mulo vec_mulo\n#  define XXH_vec_mule vec_mule\n# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__)\n/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */\n /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */\n#  define XXH_vec_mulo __builtin_altivec_vmulouw\n#  define XXH_vec_mule __builtin_altivec_vmuleuw\n# else\n/* gcc needs inline assembly */\n/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b)\n{\n    xxh_u64x2 result;\n    __asm__(\"vmulouw %0, %1, %2\" : \"=v\" (result) : \"v\" (a), \"v\" (b));\n    return result;\n}\nXXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b)\n{\n    xxh_u64x2 result;\n    __asm__(\"vmuleuw %0, %1, %2\" : \"=v\" (result) : \"v\" (a), \"v\" (b));\n    return result;\n}\n# endif /* XXH_vec_mulo, XXH_vec_mule */\n#endif /* XXH_VECTOR == XXH_VSX */\n\n#if XXH_VECTOR == XXH_SVE\n#define ACCRND(acc, offset) \\\ndo { \\\n    svuint64_t input_vec = svld1_u64(mask, xinput + offset);         \\\n    svuint64_t secret_vec = svld1_u64(mask, xsecret + offset);       \\\n    svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec);     \\\n    svuint64_t swapped = svtbl_u64(input_vec, kSwap);                \\\n    svuint64_t mixed_lo = svextw_u64_x(mask, mixed);                 \\\n    svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32);            \\\n    svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \\\n    acc = svadd_u64_x(mask, acc, mul);                               \\\n} while (0)\n#endif /* XXH_VECTOR == XXH_SVE */\n\n/* prefetch\n * can be disabled, by declaring XXH_NO_PREFETCH build macro */\n#if defined(XXH_NO_PREFETCH)\n#  define XXH_PREFETCH(ptr)  (void)(ptr)  /* disabled */\n#else\n#  if XXH_SIZE_OPT >= 1\n#    define XXH_PREFETCH(ptr) (void)(ptr)\n#  elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))  /* _mm_prefetch() not defined outside of x86/x64 */\n#    include <mmintrin.h>   /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */\n#    define XXH_PREFETCH(ptr)  _mm_prefetch((const char*)(ptr), _MM_HINT_T0)\n#  elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )\n#    define XXH_PREFETCH(ptr)  __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)\n#  else\n#    define XXH_PREFETCH(ptr) (void)(ptr)  /* disabled */\n#  endif\n#endif  /* XXH_NO_PREFETCH */\n\n\n/* ==========================================\n * XXH3 default settings\n * ========================================== */\n\n#define XXH_SECRET_DEFAULT_SIZE 192   /* minimum XXH3_SECRET_SIZE_MIN */\n\n#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN)\n#  error \"default keyset is not large enough\"\n#endif\n\n/*! Pseudorandom secret taken directly from FARSH. */\nXXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = {\n    0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,\n    0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,\n    0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,\n    0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,\n    0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,\n    0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,\n    0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,\n    0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,\n    0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,\n    0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,\n    0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,\n    0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,\n};\n\nstatic const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL;  /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */\nstatic const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL;  /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */\n\n#ifdef XXH_OLD_NAMES\n#  define kSecret XXH3_kSecret\n#endif\n\n#ifdef XXH_DOXYGEN\n/*!\n * @brief Calculates a 32-bit to 64-bit long multiply.\n *\n * Implemented as a macro.\n *\n * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't\n * need to (but it shouldn't need to anyways, it is about 7 instructions to do\n * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we\n * use that instead of the normal method.\n *\n * If you are compiling for platforms like Thumb-1 and don't have a better option,\n * you may also want to write your own long multiply routine here.\n *\n * @param x, y Numbers to be multiplied\n * @return 64-bit product of the low 32 bits of @p x and @p y.\n */\nXXH_FORCE_INLINE xxh_u64\nXXH_mult32to64(xxh_u64 x, xxh_u64 y)\n{\n   return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF);\n}\n#elif defined(_MSC_VER) && defined(_M_IX86)\n#    define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y))\n#else\n/*\n * Downcast + upcast is usually better than masking on older compilers like\n * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers.\n *\n * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands\n * and perform a full 64x64 multiply -- entirely redundant on 32-bit.\n */\n#    define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y))\n#endif\n\n/*!\n * @brief Calculates a 64->128-bit long multiply.\n *\n * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar\n * version.\n *\n * @param lhs , rhs The 64-bit integers to be multiplied\n * @return The 128-bit result represented in an @ref XXH128_hash_t.\n */\nstatic XXH128_hash_t\nXXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs)\n{\n    /*\n     * GCC/Clang __uint128_t method.\n     *\n     * On most 64-bit targets, GCC and Clang define a __uint128_t type.\n     * This is usually the best way as it usually uses a native long 64-bit\n     * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64.\n     *\n     * Usually.\n     *\n     * Despite being a 32-bit platform, Clang (and emscripten) define this type\n     * despite not having the arithmetic for it. This results in a laggy\n     * compiler builtin call which calculates a full 128-bit multiply.\n     * In that case it is best to use the portable one.\n     * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677\n     */\n#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \\\n    && defined(__SIZEOF_INT128__) \\\n    || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128)\n\n    __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs;\n    XXH128_hash_t r128;\n    r128.low64  = (xxh_u64)(product);\n    r128.high64 = (xxh_u64)(product >> 64);\n    return r128;\n\n    /*\n     * MSVC for x64's _umul128 method.\n     *\n     * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct);\n     *\n     * This compiles to single operand MUL on x64.\n     */\n#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC)\n\n#ifndef _MSC_VER\n#   pragma intrinsic(_umul128)\n#endif\n    xxh_u64 product_high;\n    xxh_u64 const product_low = _umul128(lhs, rhs, &product_high);\n    XXH128_hash_t r128;\n    r128.low64  = product_low;\n    r128.high64 = product_high;\n    return r128;\n\n    /*\n     * MSVC for ARM64's __umulh method.\n     *\n     * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method.\n     */\n#elif defined(_M_ARM64) || defined(_M_ARM64EC)\n\n#ifndef _MSC_VER\n#   pragma intrinsic(__umulh)\n#endif\n    XXH128_hash_t r128;\n    r128.low64  = lhs * rhs;\n    r128.high64 = __umulh(lhs, rhs);\n    return r128;\n\n#else\n    /*\n     * Portable scalar method. Optimized for 32-bit and 64-bit ALUs.\n     *\n     * This is a fast and simple grade school multiply, which is shown below\n     * with base 10 arithmetic instead of base 0x100000000.\n     *\n     *           9 3 // D2 lhs = 93\n     *         x 7 5 // D2 rhs = 75\n     *     ----------\n     *           1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15\n     *         4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45\n     *         2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21\n     *     + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63\n     *     ---------\n     *         2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27\n     *     + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67\n     *     ---------\n     *       6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975\n     *\n     * The reasons for adding the products like this are:\n     *  1. It avoids manual carry tracking. Just like how\n     *     (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX.\n     *     This avoids a lot of complexity.\n     *\n     *  2. It hints for, and on Clang, compiles to, the powerful UMAAL\n     *     instruction available in ARM's Digital Signal Processing extension\n     *     in 32-bit ARMv6 and later, which is shown below:\n     *\n     *         void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm)\n     *         {\n     *             xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm;\n     *             *RdLo = (xxh_u32)(product & 0xFFFFFFFF);\n     *             *RdHi = (xxh_u32)(product >> 32);\n     *         }\n     *\n     *     This instruction was designed for efficient long multiplication, and\n     *     allows this to be calculated in only 4 instructions at speeds\n     *     comparable to some 64-bit ALUs.\n     *\n     *  3. It isn't terrible on other platforms. Usually this will be a couple\n     *     of 32-bit ADD/ADCs.\n     */\n\n    /* First calculate all of the cross products. */\n    xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);\n    xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32,        rhs & 0xFFFFFFFF);\n    xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32);\n    xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32,        rhs >> 32);\n\n    /* Now add the products together. These will never overflow. */\n    xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;\n    xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32)        + hi_hi;\n    xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);\n\n    XXH128_hash_t r128;\n    r128.low64  = lower;\n    r128.high64 = upper;\n    return r128;\n#endif\n}\n\n/*!\n * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it.\n *\n * The reason for the separate function is to prevent passing too many structs\n * around by value. This will hopefully inline the multiply, but we don't force it.\n *\n * @param lhs , rhs The 64-bit integers to multiply\n * @return The low 64 bits of the product XOR'd by the high 64 bits.\n * @see XXH_mult64to128()\n */\nstatic xxh_u64\nXXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs)\n{\n    XXH128_hash_t product = XXH_mult64to128(lhs, rhs);\n    return product.low64 ^ product.high64;\n}\n\n/*! Seems to produce slightly better code on GCC for some reason. */\nXXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift)\n{\n    XXH_ASSERT(0 <= shift && shift < 64);\n    return v64 ^ (v64 >> shift);\n}\n\n/*\n * This is a fast avalanche stage,\n * suitable when input bits are already partially mixed\n */\nstatic XXH64_hash_t XXH3_avalanche(xxh_u64 h64)\n{\n    h64 = XXH_xorshift64(h64, 37);\n    h64 *= PRIME_MX1;\n    h64 = XXH_xorshift64(h64, 32);\n    return h64;\n}\n\n/*\n * This is a stronger avalanche,\n * inspired by Pelle Evensen's rrmxmx\n * preferable when input has not been previously mixed\n */\nstatic XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len)\n{\n    /* this mix is inspired by Pelle Evensen's rrmxmx */\n    h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24);\n    h64 *= PRIME_MX2;\n    h64 ^= (h64 >> 35) + len ;\n    h64 *= PRIME_MX2;\n    return XXH_xorshift64(h64, 28);\n}\n\n\n/* ==========================================\n * Short keys\n * ==========================================\n * One of the shortcomings of XXH32 and XXH64 was that their performance was\n * sub-optimal on short lengths. It used an iterative algorithm which strongly\n * favored lengths that were a multiple of 4 or 8.\n *\n * Instead of iterating over individual inputs, we use a set of single shot\n * functions which piece together a range of lengths and operate in constant time.\n *\n * Additionally, the number of multiplies has been significantly reduced. This\n * reduces latency, especially when emulating 64-bit multiplies on 32-bit.\n *\n * Depending on the platform, this may or may not be faster than XXH32, but it\n * is almost guaranteed to be faster than XXH64.\n */\n\n/*\n * At very short lengths, there isn't enough input to fully hide secrets, or use\n * the entire secret.\n *\n * There is also only a limited amount of mixing we can do before significantly\n * impacting performance.\n *\n * Therefore, we use different sections of the secret and always mix two secret\n * samples with an XOR. This should have no effect on performance on the\n * seedless or withSeed variants because everything _should_ be constant folded\n * by modern compilers.\n *\n * The XOR mixing hides individual parts of the secret and increases entropy.\n *\n * This adds an extra layer of strength for custom secrets.\n */\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(1 <= len && len <= 3);\n    XXH_ASSERT(secret != NULL);\n    /*\n     * len = 1: combined = { input[0], 0x01, input[0], input[0] }\n     * len = 2: combined = { input[1], 0x02, input[0], input[1] }\n     * len = 3: combined = { input[2], 0x03, input[0], input[1] }\n     */\n    {   xxh_u8  const c1 = input[0];\n        xxh_u8  const c2 = input[len >> 1];\n        xxh_u8  const c3 = input[len - 1];\n        xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2  << 24)\n                               | ((xxh_u32)c3 <<  0) | ((xxh_u32)len << 8);\n        xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;\n        xxh_u64 const keyed = (xxh_u64)combined ^ bitflip;\n        return XXH64_avalanche(keyed);\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(4 <= len && len <= 8);\n    seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;\n    {   xxh_u32 const input1 = XXH_readLE32(input);\n        xxh_u32 const input2 = XXH_readLE32(input + len - 4);\n        xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed;\n        xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32);\n        xxh_u64 const keyed = input64 ^ bitflip;\n        return XXH3_rrmxmx(keyed, len);\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(9 <= len && len <= 16);\n    {   xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed;\n        xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed;\n        xxh_u64 const input_lo = XXH_readLE64(input)           ^ bitflip1;\n        xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2;\n        xxh_u64 const acc = len\n                          + XXH_swap64(input_lo) + input_hi\n                          + XXH3_mul128_fold64(input_lo, input_hi);\n        return XXH3_avalanche(acc);\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(len <= 16);\n    {   if (XXH_likely(len >  8)) return XXH3_len_9to16_64b(input, len, secret, seed);\n        if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed);\n        if (len) return XXH3_len_1to3_64b(input, len, secret, seed);\n        return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64)));\n    }\n}\n\n/*\n * DISCLAIMER: There are known *seed-dependent* multicollisions here due to\n * multiplication by zero, affecting hashes of lengths 17 to 240.\n *\n * However, they are very unlikely.\n *\n * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all\n * unseeded non-cryptographic hashes, it does not attempt to defend itself\n * against specially crafted inputs, only random inputs.\n *\n * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes\n * cancelling out the secret is taken an arbitrary number of times (addressed\n * in XXH3_accumulate_512), this collision is very unlikely with random inputs\n * and/or proper seeding:\n *\n * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a\n * function that is only called up to 16 times per hash with up to 240 bytes of\n * input.\n *\n * This is not too bad for a non-cryptographic hash function, especially with\n * only 64 bit outputs.\n *\n * The 128-bit variant (which trades some speed for strength) is NOT affected\n * by this, although it is always a good idea to use a proper seed if you care\n * about strength.\n */\nXXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input,\n                                     const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64)\n{\n#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \\\n  && defined(__i386__) && defined(__SSE2__)  /* x86 + SSE2 */ \\\n  && !defined(XXH_ENABLE_AUTOVECTORIZE)      /* Define to disable like XXH32 hack */\n    /*\n     * UGLY HACK:\n     * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in\n     * slower code.\n     *\n     * By forcing seed64 into a register, we disrupt the cost model and\n     * cause it to scalarize. See `XXH32_round()`\n     *\n     * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600,\n     * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on\n     * GCC 9.2, despite both emitting scalar code.\n     *\n     * GCC generates much better scalar code than Clang for the rest of XXH3,\n     * which is why finding a more optimal codepath is an interest.\n     */\n    XXH_COMPILER_GUARD(seed64);\n#endif\n    {   xxh_u64 const input_lo = XXH_readLE64(input);\n        xxh_u64 const input_hi = XXH_readLE64(input+8);\n        return XXH3_mul128_fold64(\n            input_lo ^ (XXH_readLE64(secret)   + seed64),\n            input_hi ^ (XXH_readLE64(secret+8) - seed64)\n        );\n    }\n}\n\n/* For mid range keys, XXH3 uses a Mum-hash variant. */\nXXH_FORCE_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                     const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                     XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(16 < len && len <= 128);\n\n    {   xxh_u64 acc = len * XXH_PRIME64_1;\n#if XXH_SIZE_OPT >= 1\n        /* Smaller and cleaner, but slightly slower. */\n        unsigned int i = (unsigned int)(len - 1) / 32;\n        do {\n            acc += XXH3_mix16B(input+16 * i, secret+32*i, seed);\n            acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed);\n        } while (i-- != 0);\n#else\n        if (len > 32) {\n            if (len > 64) {\n                if (len > 96) {\n                    acc += XXH3_mix16B(input+48, secret+96, seed);\n                    acc += XXH3_mix16B(input+len-64, secret+112, seed);\n                }\n                acc += XXH3_mix16B(input+32, secret+64, seed);\n                acc += XXH3_mix16B(input+len-48, secret+80, seed);\n            }\n            acc += XXH3_mix16B(input+16, secret+32, seed);\n            acc += XXH3_mix16B(input+len-32, secret+48, seed);\n        }\n        acc += XXH3_mix16B(input+0, secret+0, seed);\n        acc += XXH3_mix16B(input+len-16, secret+16, seed);\n#endif\n        return XXH3_avalanche(acc);\n    }\n}\n\nXXH_NO_INLINE XXH_PUREF XXH64_hash_t\nXXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                      const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                      XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);\n\n    #define XXH3_MIDSIZE_STARTOFFSET 3\n    #define XXH3_MIDSIZE_LASTOFFSET  17\n\n    {   xxh_u64 acc = len * XXH_PRIME64_1;\n        xxh_u64 acc_end;\n        unsigned int const nbRounds = (unsigned int)len / 16;\n        unsigned int i;\n        XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);\n        for (i=0; i<8; i++) {\n            acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed);\n        }\n        /* last bytes */\n        acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);\n        XXH_ASSERT(nbRounds >= 8);\n        acc = XXH3_avalanche(acc);\n#if defined(__clang__)                                /* Clang */ \\\n    && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \\\n    && !defined(XXH_ENABLE_AUTOVECTORIZE)             /* Define to disable */\n        /*\n         * UGLY HACK:\n         * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86.\n         * In everywhere else, it uses scalar code.\n         *\n         * For 64->128-bit multiplies, even if the NEON was 100% optimal, it\n         * would still be slower than UMAAL (see XXH_mult64to128).\n         *\n         * Unfortunately, Clang doesn't handle the long multiplies properly and\n         * converts them to the nonexistent \"vmulq_u64\" intrinsic, which is then\n         * scalarized into an ugly mess of VMOV.32 instructions.\n         *\n         * This mess is difficult to avoid without turning autovectorization\n         * off completely, but they are usually relatively minor and/or not\n         * worth it to fix.\n         *\n         * This loop is the easiest to fix, as unlike XXH32, this pragma\n         * _actually works_ because it is a loop vectorization instead of an\n         * SLP vectorization.\n         */\n        #pragma clang loop vectorize(disable)\n#endif\n        for (i=8 ; i < nbRounds; i++) {\n            /*\n             * Prevents clang for unrolling the acc loop and interleaving with this one.\n             */\n            XXH_COMPILER_GUARD(acc);\n            acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed);\n        }\n        return XXH3_avalanche(acc + acc_end);\n    }\n}\n\n\n/* =======     Long Keys     ======= */\n\n#define XXH_STRIPE_LEN 64\n#define XXH_SECRET_CONSUME_RATE 8   /* nb of secret bytes consumed at each accumulation */\n#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64))\n\n#ifdef XXH_OLD_NAMES\n#  define STRIPE_LEN XXH_STRIPE_LEN\n#  define ACC_NB XXH_ACC_NB\n#endif\n\n#ifndef XXH_PREFETCH_DIST\n#  ifdef __clang__\n#    define XXH_PREFETCH_DIST 320\n#  else\n#    if (XXH_VECTOR == XXH_AVX512)\n#      define XXH_PREFETCH_DIST 512\n#    else\n#      define XXH_PREFETCH_DIST 384\n#    endif\n#  endif  /* __clang__ */\n#endif  /* XXH_PREFETCH_DIST */\n\n/*\n * These macros are to generate an XXH3_accumulate() function.\n * The two arguments select the name suffix and target attribute.\n *\n * The name of this symbol is XXH3_accumulate_<name>() and it calls\n * XXH3_accumulate_512_<name>().\n *\n * It may be useful to hand implement this function if the compiler fails to\n * optimize the inline function.\n */\n#define XXH3_ACCUMULATE_TEMPLATE(name)                      \\\nvoid                                                        \\\nXXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc,           \\\n                       const xxh_u8* XXH_RESTRICT input,    \\\n                       const xxh_u8* XXH_RESTRICT secret,   \\\n                       size_t nbStripes)                    \\\n{                                                           \\\n    size_t n;                                               \\\n    for (n = 0; n < nbStripes; n++ ) {                      \\\n        const xxh_u8* const in = input + n*XXH_STRIPE_LEN;  \\\n        XXH_PREFETCH(in + XXH_PREFETCH_DIST);               \\\n        XXH3_accumulate_512_##name(                         \\\n                 acc,                                       \\\n                 in,                                        \\\n                 secret + n*XXH_SECRET_CONSUME_RATE);       \\\n    }                                                       \\\n}\n\n\nXXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64)\n{\n    if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64);\n    XXH_memcpy(dst, &v64, sizeof(v64));\n}\n\n/* Several intrinsic functions below are supposed to accept __int64 as argument,\n * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ .\n * However, several environments do not define __int64 type,\n * requiring a workaround.\n */\n#if !defined (__VMS) \\\n  && (defined (__cplusplus) \\\n  || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )\n    typedef int64_t xxh_i64;\n#else\n    /* the following type must have a width of 64-bit */\n    typedef long long xxh_i64;\n#endif\n\n\n/*\n * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized.\n *\n * It is a hardened version of UMAC, based off of FARSH's implementation.\n *\n * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD\n * implementations, and it is ridiculously fast.\n *\n * We harden it by mixing the original input to the accumulators as well as the product.\n *\n * This means that in the (relatively likely) case of a multiply by zero, the\n * original input is preserved.\n *\n * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve\n * cross-pollination, as otherwise the upper and lower halves would be\n * essentially independent.\n *\n * This doesn't matter on 64-bit hashes since they all get merged together in\n * the end, so we skip the extra step.\n *\n * Both XXH3_64bits and XXH3_128bits use this subroutine.\n */\n\n#if (XXH_VECTOR == XXH_AVX512) \\\n     || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0)\n\n#ifndef XXH_TARGET_AVX512\n# define XXH_TARGET_AVX512  /* disable attribute target */\n#endif\n\nXXH_FORCE_INLINE XXH_TARGET_AVX512 void\nXXH3_accumulate_512_avx512(void* XXH_RESTRICT acc,\n                     const void* XXH_RESTRICT input,\n                     const void* XXH_RESTRICT secret)\n{\n    __m512i* const xacc = (__m512i *) acc;\n    XXH_ASSERT((((size_t)acc) & 63) == 0);\n    XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));\n\n    {\n        /* data_vec    = input[0]; */\n        __m512i const data_vec    = _mm512_loadu_si512   (input);\n        /* key_vec     = secret[0]; */\n        __m512i const key_vec     = _mm512_loadu_si512   (secret);\n        /* data_key    = data_vec ^ key_vec; */\n        __m512i const data_key    = _mm512_xor_si512     (data_vec, key_vec);\n        /* data_key_lo = data_key >> 32; */\n        __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32);\n        /* product     = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */\n        __m512i const product     = _mm512_mul_epu32     (data_key, data_key_lo);\n        /* xacc[0] += swap(data_vec); */\n        __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2));\n        __m512i const sum       = _mm512_add_epi64(*xacc, data_swap);\n        /* xacc[0] += product; */\n        *xacc = _mm512_add_epi64(product, sum);\n    }\n}\nXXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512)\n\n/*\n * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing.\n *\n * Multiplication isn't perfect, as explained by Google in HighwayHash:\n *\n *  // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to\n *  // varying degrees. In descending order of goodness, bytes\n *  // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32.\n *  // As expected, the upper and lower bytes are much worse.\n *\n * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291\n *\n * Since our algorithm uses a pseudorandom secret to add some variance into the\n * mix, we don't need to (or want to) mix as often or as much as HighwayHash does.\n *\n * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid\n * extraction.\n *\n * Both XXH3_64bits and XXH3_128bits use this subroutine.\n */\n\nXXH_FORCE_INLINE XXH_TARGET_AVX512 void\nXXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 63) == 0);\n    XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));\n    {   __m512i* const xacc = (__m512i*) acc;\n        const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1);\n\n        /* xacc[0] ^= (xacc[0] >> 47) */\n        __m512i const acc_vec     = *xacc;\n        __m512i const shifted     = _mm512_srli_epi64    (acc_vec, 47);\n        /* xacc[0] ^= secret; */\n        __m512i const key_vec     = _mm512_loadu_si512   (secret);\n        __m512i const data_key    = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */);\n\n        /* xacc[0] *= XXH_PRIME32_1; */\n        __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32);\n        __m512i const prod_lo     = _mm512_mul_epu32     (data_key, prime32);\n        __m512i const prod_hi     = _mm512_mul_epu32     (data_key_hi, prime32);\n        *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32));\n    }\n}\n\nXXH_FORCE_INLINE XXH_TARGET_AVX512 void\nXXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0);\n    XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64);\n    XXH_ASSERT(((size_t)customSecret & 63) == 0);\n    (void)(&XXH_writeLE64);\n    {   int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i);\n        __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64);\n        __m512i const seed     = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos);\n\n        const __m512i* const src  = (const __m512i*) ((const void*) XXH3_kSecret);\n              __m512i* const dest = (      __m512i*) customSecret;\n        int i;\n        XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */\n        XXH_ASSERT(((size_t)dest & 63) == 0);\n        for (i=0; i < nbRounds; ++i) {\n            dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed);\n    }   }\n}\n\n#endif\n\n#if (XXH_VECTOR == XXH_AVX2) \\\n    || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0)\n\n#ifndef XXH_TARGET_AVX2\n# define XXH_TARGET_AVX2  /* disable attribute target */\n#endif\n\nXXH_FORCE_INLINE XXH_TARGET_AVX2 void\nXXH3_accumulate_512_avx2( void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 31) == 0);\n    {   __m256i* const xacc    =       (__m256i *) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm256_loadu_si256 requires  a const __m256i * pointer for some reason. */\n        const         __m256i* const xinput  = (const __m256i *) input;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */\n        const         __m256i* const xsecret = (const __m256i *) secret;\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {\n            /* data_vec    = xinput[i]; */\n            __m256i const data_vec    = _mm256_loadu_si256    (xinput+i);\n            /* key_vec     = xsecret[i]; */\n            __m256i const key_vec     = _mm256_loadu_si256   (xsecret+i);\n            /* data_key    = data_vec ^ key_vec; */\n            __m256i const data_key    = _mm256_xor_si256     (data_vec, key_vec);\n            /* data_key_lo = data_key >> 32; */\n            __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32);\n            /* product     = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */\n            __m256i const product     = _mm256_mul_epu32     (data_key, data_key_lo);\n            /* xacc[i] += swap(data_vec); */\n            __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2));\n            __m256i const sum       = _mm256_add_epi64(xacc[i], data_swap);\n            /* xacc[i] += product; */\n            xacc[i] = _mm256_add_epi64(product, sum);\n    }   }\n}\nXXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2)\n\nXXH_FORCE_INLINE XXH_TARGET_AVX2 void\nXXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 31) == 0);\n    {   __m256i* const xacc = (__m256i*) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */\n        const         __m256i* const xsecret = (const __m256i *) secret;\n        const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1);\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {\n            /* xacc[i] ^= (xacc[i] >> 47) */\n            __m256i const acc_vec     = xacc[i];\n            __m256i const shifted     = _mm256_srli_epi64    (acc_vec, 47);\n            __m256i const data_vec    = _mm256_xor_si256     (acc_vec, shifted);\n            /* xacc[i] ^= xsecret; */\n            __m256i const key_vec     = _mm256_loadu_si256   (xsecret+i);\n            __m256i const data_key    = _mm256_xor_si256     (data_vec, key_vec);\n\n            /* xacc[i] *= XXH_PRIME32_1; */\n            __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32);\n            __m256i const prod_lo     = _mm256_mul_epu32     (data_key, prime32);\n            __m256i const prod_hi     = _mm256_mul_epu32     (data_key_hi, prime32);\n            xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32));\n        }\n    }\n}\n\nXXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0);\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6);\n    XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64);\n    (void)(&XXH_writeLE64);\n    XXH_PREFETCH(customSecret);\n    {   __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64);\n\n        const __m256i* const src  = (const __m256i*) ((const void*) XXH3_kSecret);\n              __m256i*       dest = (      __m256i*) customSecret;\n\n#       if defined(__GNUC__) || defined(__clang__)\n        /*\n         * On GCC & Clang, marking 'dest' as modified will cause the compiler:\n         *   - do not extract the secret from sse registers in the internal loop\n         *   - use less common registers, and avoid pushing these reg into stack\n         */\n        XXH_COMPILER_GUARD(dest);\n#       endif\n        XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */\n        XXH_ASSERT(((size_t)dest & 31) == 0);\n\n        /* GCC -O2 need unroll loop manually */\n        dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed);\n        dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed);\n        dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed);\n        dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed);\n        dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed);\n        dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed);\n    }\n}\n\n#endif\n\n/* x86dispatch always generates SSE2 */\n#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH)\n\n#ifndef XXH_TARGET_SSE2\n# define XXH_TARGET_SSE2  /* disable attribute target */\n#endif\n\nXXH_FORCE_INLINE XXH_TARGET_SSE2 void\nXXH3_accumulate_512_sse2( void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    /* SSE2 is just a half-scale version of the AVX2 version. */\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    {   __m128i* const xacc    =       (__m128i *) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */\n        const         __m128i* const xinput  = (const __m128i *) input;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */\n        const         __m128i* const xsecret = (const __m128i *) secret;\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {\n            /* data_vec    = xinput[i]; */\n            __m128i const data_vec    = _mm_loadu_si128   (xinput+i);\n            /* key_vec     = xsecret[i]; */\n            __m128i const key_vec     = _mm_loadu_si128   (xsecret+i);\n            /* data_key    = data_vec ^ key_vec; */\n            __m128i const data_key    = _mm_xor_si128     (data_vec, key_vec);\n            /* data_key_lo = data_key >> 32; */\n            __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));\n            /* product     = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */\n            __m128i const product     = _mm_mul_epu32     (data_key, data_key_lo);\n            /* xacc[i] += swap(data_vec); */\n            __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2));\n            __m128i const sum       = _mm_add_epi64(xacc[i], data_swap);\n            /* xacc[i] += product; */\n            xacc[i] = _mm_add_epi64(product, sum);\n    }   }\n}\nXXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2)\n\nXXH_FORCE_INLINE XXH_TARGET_SSE2 void\nXXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    {   __m128i* const xacc = (__m128i*) acc;\n        /* Unaligned. This is mainly for pointer arithmetic, and because\n         * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */\n        const         __m128i* const xsecret = (const __m128i *) secret;\n        const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1);\n\n        size_t i;\n        for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {\n            /* xacc[i] ^= (xacc[i] >> 47) */\n            __m128i const acc_vec     = xacc[i];\n            __m128i const shifted     = _mm_srli_epi64    (acc_vec, 47);\n            __m128i const data_vec    = _mm_xor_si128     (acc_vec, shifted);\n            /* xacc[i] ^= xsecret[i]; */\n            __m128i const key_vec     = _mm_loadu_si128   (xsecret+i);\n            __m128i const data_key    = _mm_xor_si128     (data_vec, key_vec);\n\n            /* xacc[i] *= XXH_PRIME32_1; */\n            __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));\n            __m128i const prod_lo     = _mm_mul_epu32     (data_key, prime32);\n            __m128i const prod_hi     = _mm_mul_epu32     (data_key_hi, prime32);\n            xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32));\n        }\n    }\n}\n\nXXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);\n    (void)(&XXH_writeLE64);\n    {   int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i);\n\n#       if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900\n        /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */\n        XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) };\n        __m128i const seed = _mm_load_si128((__m128i const*)seed64x2);\n#       else\n        __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64);\n#       endif\n        int i;\n\n        const void* const src16 = XXH3_kSecret;\n        __m128i* dst16 = (__m128i*) customSecret;\n#       if defined(__GNUC__) || defined(__clang__)\n        /*\n         * On GCC & Clang, marking 'dest' as modified will cause the compiler:\n         *   - do not extract the secret from sse registers in the internal loop\n         *   - use less common registers, and avoid pushing these reg into stack\n         */\n        XXH_COMPILER_GUARD(dst16);\n#       endif\n        XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */\n        XXH_ASSERT(((size_t)dst16 & 15) == 0);\n\n        for (i=0; i < nbRounds; ++i) {\n            dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed);\n    }   }\n}\n\n#endif\n\n#if (XXH_VECTOR == XXH_NEON)\n\n/* forward declarations for the scalar routines */\nXXH_FORCE_INLINE void\nXXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input,\n                 void const* XXH_RESTRICT secret, size_t lane);\n\nXXH_FORCE_INLINE void\nXXH3_scalarScrambleRound(void* XXH_RESTRICT acc,\n                         void const* XXH_RESTRICT secret, size_t lane);\n\n/*!\n * @internal\n * @brief The bulk processing loop for NEON and WASM SIMD128.\n *\n * The NEON code path is actually partially scalar when running on AArch64. This\n * is to optimize the pipelining and can have up to 15% speedup depending on the\n * CPU, and it also mitigates some GCC codegen issues.\n *\n * @see XXH3_NEON_LANES for configuring this and details about this optimization.\n *\n * NEON's 32-bit to 64-bit long multiply takes a half vector of 32-bit\n * integers instead of the other platforms which mask full 64-bit vectors,\n * so the setup is more complicated than just shifting right.\n *\n * Additionally, there is an optimization for 4 lanes at once noted below.\n *\n * Since, as stated, the most optimal amount of lanes for Cortexes is 6,\n * there needs to be *three* versions of the accumulate operation used\n * for the remaining 2 lanes.\n *\n * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap\n * nearly perfectly.\n */\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_neon( void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0);\n    {   /* GCC for darwin arm64 does not like aliasing here */\n        xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc;\n        /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */\n        uint8_t const* xinput = (const uint8_t *) input;\n        uint8_t const* xsecret  = (const uint8_t *) secret;\n\n        size_t i;\n#ifdef __wasm_simd128__\n        /*\n         * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret\n         * is constant propagated, which results in it converting it to this\n         * inside the loop:\n         *\n         *    a = v128.load(XXH3_kSecret +  0 + $secret_offset, offset = 0)\n         *    b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0)\n         *    ...\n         *\n         * This requires a full 32-bit address immediate (and therefore a 6 byte\n         * instruction) as well as an add for each offset.\n         *\n         * Putting an asm guard prevents it from folding (at the cost of losing\n         * the alignment hint), and uses the free offset in `v128.load` instead\n         * of adding secret_offset each time which overall reduces code size by\n         * about a kilobyte and improves performance.\n         */\n        XXH_COMPILER_GUARD(xsecret);\n#endif\n        /* Scalar lanes use the normal scalarRound routine */\n        for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {\n            XXH3_scalarRound(acc, input, secret, i);\n        }\n        i = 0;\n        /* 4 NEON lanes at a time. */\n        for (; i+1 < XXH3_NEON_LANES / 2; i+=2) {\n            /* data_vec = xinput[i]; */\n            uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput  + (i * 16));\n            uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput  + ((i+1) * 16));\n            /* key_vec  = xsecret[i];  */\n            uint64x2_t key_vec_1  = XXH_vld1q_u64(xsecret + (i * 16));\n            uint64x2_t key_vec_2  = XXH_vld1q_u64(xsecret + ((i+1) * 16));\n            /* data_swap = swap(data_vec) */\n            uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1);\n            uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1);\n            /* data_key = data_vec ^ key_vec; */\n            uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1);\n            uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2);\n\n            /*\n             * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a\n             * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to\n             * get one vector with the low 32 bits of each lane, and one vector\n             * with the high 32 bits of each lane.\n             *\n             * The intrinsic returns a double vector because the original ARMv7-a\n             * instruction modified both arguments in place. AArch64 and SIMD128 emit\n             * two instructions from this intrinsic.\n             *\n             *  [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ]\n             *  [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ]\n             */\n            uint32x4x2_t unzipped = vuzpq_u32(\n                vreinterpretq_u32_u64(data_key_1),\n                vreinterpretq_u32_u64(data_key_2)\n            );\n            /* data_key_lo = data_key & 0xFFFFFFFF */\n            uint32x4_t data_key_lo = unzipped.val[0];\n            /* data_key_hi = data_key >> 32 */\n            uint32x4_t data_key_hi = unzipped.val[1];\n            /*\n             * Then, we can split the vectors horizontally and multiply which, as for most\n             * widening intrinsics, have a variant that works on both high half vectors\n             * for free on AArch64. A similar instruction is available on SIMD128.\n             *\n             * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi\n             */\n            uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi);\n            uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi);\n            /*\n             * Clang reorders\n             *    a += b * c;     // umlal   swap.2d, dkl.2s, dkh.2s\n             *    c += a;         // add     acc.2d, acc.2d, swap.2d\n             * to\n             *    c += a;         // add     acc.2d, acc.2d, swap.2d\n             *    c += b * c;     // umlal   acc.2d, dkl.2s, dkh.2s\n             *\n             * While it would make sense in theory since the addition is faster,\n             * for reasons likely related to umlal being limited to certain NEON\n             * pipelines, this is worse. A compiler guard fixes this.\n             */\n            XXH_COMPILER_GUARD_CLANG_NEON(sum_1);\n            XXH_COMPILER_GUARD_CLANG_NEON(sum_2);\n            /* xacc[i] = acc_vec + sum; */\n            xacc[i]   = vaddq_u64(xacc[i], sum_1);\n            xacc[i+1] = vaddq_u64(xacc[i+1], sum_2);\n        }\n        /* Operate on the remaining NEON lanes 2 at a time. */\n        for (; i < XXH3_NEON_LANES / 2; i++) {\n            /* data_vec = xinput[i]; */\n            uint64x2_t data_vec = XXH_vld1q_u64(xinput  + (i * 16));\n            /* key_vec  = xsecret[i];  */\n            uint64x2_t key_vec  = XXH_vld1q_u64(xsecret + (i * 16));\n            /* acc_vec_2 = swap(data_vec) */\n            uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1);\n            /* data_key = data_vec ^ key_vec; */\n            uint64x2_t data_key = veorq_u64(data_vec, key_vec);\n            /* For two lanes, just use VMOVN and VSHRN. */\n            /* data_key_lo = data_key & 0xFFFFFFFF; */\n            uint32x2_t data_key_lo = vmovn_u64(data_key);\n            /* data_key_hi = data_key >> 32; */\n            uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32);\n            /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */\n            uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi);\n            /* Same Clang workaround as before */\n            XXH_COMPILER_GUARD_CLANG_NEON(sum);\n            /* xacc[i] = acc_vec + sum; */\n            xacc[i] = vaddq_u64 (xacc[i], sum);\n        }\n    }\n}\nXXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon)\n\nXXH_FORCE_INLINE void\nXXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n\n    {   xxh_aliasing_uint64x2_t* xacc       = (xxh_aliasing_uint64x2_t*) acc;\n        uint8_t const* xsecret = (uint8_t const*) secret;\n\n        size_t i;\n        /* WASM uses operator overloads and doesn't need these. */\n#ifndef __wasm_simd128__\n        /* { prime32_1, prime32_1 } */\n        uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1);\n        /* { 0, prime32_1, 0, prime32_1 } */\n        uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32));\n#endif\n\n        /* AArch64 uses both scalar and neon at the same time */\n        for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {\n            XXH3_scalarScrambleRound(acc, secret, i);\n        }\n        for (i=0; i < XXH3_NEON_LANES / 2; i++) {\n            /* xacc[i] ^= (xacc[i] >> 47); */\n            uint64x2_t acc_vec  = xacc[i];\n            uint64x2_t shifted  = vshrq_n_u64(acc_vec, 47);\n            uint64x2_t data_vec = veorq_u64(acc_vec, shifted);\n\n            /* xacc[i] ^= xsecret[i]; */\n            uint64x2_t key_vec  = XXH_vld1q_u64(xsecret + (i * 16));\n            uint64x2_t data_key = veorq_u64(data_vec, key_vec);\n            /* xacc[i] *= XXH_PRIME32_1 */\n#ifdef __wasm_simd128__\n            /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */\n            xacc[i] = data_key * XXH_PRIME32_1;\n#else\n            /*\n             * Expanded version with portable NEON intrinsics\n             *\n             *    lo(x) * lo(y) + (hi(x) * lo(y) << 32)\n             *\n             * prod_hi = hi(data_key) * lo(prime) << 32\n             *\n             * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector\n             * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits\n             * and avoid the shift.\n             */\n            uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi);\n            /* Extract low bits for vmlal_u32  */\n            uint32x2_t data_key_lo = vmovn_u64(data_key);\n            /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */\n            xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo);\n#endif\n        }\n    }\n}\n#endif\n\n#if (XXH_VECTOR == XXH_VSX)\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_vsx(  void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    /* presumed aligned */\n    xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;\n    xxh_u8 const* const xinput   = (xxh_u8 const*) input;   /* no alignment restriction */\n    xxh_u8 const* const xsecret  = (xxh_u8 const*) secret;    /* no alignment restriction */\n    xxh_u64x2 const v32 = { 32, 32 };\n    size_t i;\n    for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {\n        /* data_vec = xinput[i]; */\n        xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i);\n        /* key_vec = xsecret[i]; */\n        xxh_u64x2 const key_vec  = XXH_vec_loadu(xsecret + 16*i);\n        xxh_u64x2 const data_key = data_vec ^ key_vec;\n        /* shuffled = (data_key << 32) | (data_key >> 32); */\n        xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32);\n        /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */\n        xxh_u64x2 const product  = XXH_vec_mulo((xxh_u32x4)data_key, shuffled);\n        /* acc_vec = xacc[i]; */\n        xxh_u64x2 acc_vec        = xacc[i];\n        acc_vec += product;\n\n        /* swap high and low halves */\n#ifdef __s390x__\n        acc_vec += vec_permi(data_vec, data_vec, 2);\n#else\n        acc_vec += vec_xxpermdi(data_vec, data_vec, 2);\n#endif\n        xacc[i] = acc_vec;\n    }\n}\nXXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx)\n\nXXH_FORCE_INLINE void\nXXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n\n    {   xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;\n        const xxh_u8* const xsecret = (const xxh_u8*) secret;\n        /* constants */\n        xxh_u64x2 const v32  = { 32, 32 };\n        xxh_u64x2 const v47 = { 47, 47 };\n        xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 };\n        size_t i;\n        for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {\n            /* xacc[i] ^= (xacc[i] >> 47); */\n            xxh_u64x2 const acc_vec  = xacc[i];\n            xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47);\n\n            /* xacc[i] ^= xsecret[i]; */\n            xxh_u64x2 const key_vec  = XXH_vec_loadu(xsecret + 16*i);\n            xxh_u64x2 const data_key = data_vec ^ key_vec;\n\n            /* xacc[i] *= XXH_PRIME32_1 */\n            /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF);  */\n            xxh_u64x2 const prod_even  = XXH_vec_mule((xxh_u32x4)data_key, prime);\n            /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32);  */\n            xxh_u64x2 const prod_odd  = XXH_vec_mulo((xxh_u32x4)data_key, prime);\n            xacc[i] = prod_odd + (prod_even << v32);\n    }   }\n}\n\n#endif\n\n#if (XXH_VECTOR == XXH_SVE)\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_sve( void* XXH_RESTRICT acc,\n                   const void* XXH_RESTRICT input,\n                   const void* XXH_RESTRICT secret)\n{\n    uint64_t *xacc = (uint64_t *)acc;\n    const uint64_t *xinput = (const uint64_t *)(const void *)input;\n    const uint64_t *xsecret = (const uint64_t *)(const void *)secret;\n    svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);\n    uint64_t element_count = svcntd();\n    if (element_count >= 8) {\n        svbool_t mask = svptrue_pat_b64(SV_VL8);\n        svuint64_t vacc = svld1_u64(mask, xacc);\n        ACCRND(vacc, 0);\n        svst1_u64(mask, xacc, vacc);\n    } else if (element_count == 2) {   /* sve128 */\n        svbool_t mask = svptrue_pat_b64(SV_VL2);\n        svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n        svuint64_t acc1 = svld1_u64(mask, xacc + 2);\n        svuint64_t acc2 = svld1_u64(mask, xacc + 4);\n        svuint64_t acc3 = svld1_u64(mask, xacc + 6);\n        ACCRND(acc0, 0);\n        ACCRND(acc1, 2);\n        ACCRND(acc2, 4);\n        ACCRND(acc3, 6);\n        svst1_u64(mask, xacc + 0, acc0);\n        svst1_u64(mask, xacc + 2, acc1);\n        svst1_u64(mask, xacc + 4, acc2);\n        svst1_u64(mask, xacc + 6, acc3);\n    } else {\n        svbool_t mask = svptrue_pat_b64(SV_VL4);\n        svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n        svuint64_t acc1 = svld1_u64(mask, xacc + 4);\n        ACCRND(acc0, 0);\n        ACCRND(acc1, 4);\n        svst1_u64(mask, xacc + 0, acc0);\n        svst1_u64(mask, xacc + 4, acc1);\n    }\n}\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc,\n               const xxh_u8* XXH_RESTRICT input,\n               const xxh_u8* XXH_RESTRICT secret,\n               size_t nbStripes)\n{\n    if (nbStripes != 0) {\n        uint64_t *xacc = (uint64_t *)acc;\n        const uint64_t *xinput = (const uint64_t *)(const void *)input;\n        const uint64_t *xsecret = (const uint64_t *)(const void *)secret;\n        svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);\n        uint64_t element_count = svcntd();\n        if (element_count >= 8) {\n            svbool_t mask = svptrue_pat_b64(SV_VL8);\n            svuint64_t vacc = svld1_u64(mask, xacc + 0);\n            do {\n                /* svprfd(svbool_t, void *, enum svfprop); */\n                svprfd(mask, xinput + 128, SV_PLDL1STRM);\n                ACCRND(vacc, 0);\n                xinput += 8;\n                xsecret += 1;\n                nbStripes--;\n           } while (nbStripes != 0);\n\n           svst1_u64(mask, xacc + 0, vacc);\n        } else if (element_count == 2) { /* sve128 */\n            svbool_t mask = svptrue_pat_b64(SV_VL2);\n            svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n            svuint64_t acc1 = svld1_u64(mask, xacc + 2);\n            svuint64_t acc2 = svld1_u64(mask, xacc + 4);\n            svuint64_t acc3 = svld1_u64(mask, xacc + 6);\n            do {\n                svprfd(mask, xinput + 128, SV_PLDL1STRM);\n                ACCRND(acc0, 0);\n                ACCRND(acc1, 2);\n                ACCRND(acc2, 4);\n                ACCRND(acc3, 6);\n                xinput += 8;\n                xsecret += 1;\n                nbStripes--;\n           } while (nbStripes != 0);\n\n           svst1_u64(mask, xacc + 0, acc0);\n           svst1_u64(mask, xacc + 2, acc1);\n           svst1_u64(mask, xacc + 4, acc2);\n           svst1_u64(mask, xacc + 6, acc3);\n        } else {\n            svbool_t mask = svptrue_pat_b64(SV_VL4);\n            svuint64_t acc0 = svld1_u64(mask, xacc + 0);\n            svuint64_t acc1 = svld1_u64(mask, xacc + 4);\n            do {\n                svprfd(mask, xinput + 128, SV_PLDL1STRM);\n                ACCRND(acc0, 0);\n                ACCRND(acc1, 4);\n                xinput += 8;\n                xsecret += 1;\n                nbStripes--;\n           } while (nbStripes != 0);\n\n           svst1_u64(mask, xacc + 0, acc0);\n           svst1_u64(mask, xacc + 4, acc1);\n       }\n    }\n}\n\n#endif\n\n#if (XXH_VECTOR == XXH_LSX)\n#define _LSX_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))\n\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_lsx( void* XXH_RESTRICT acc,\n                    const void* XXH_RESTRICT input,\n                    const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    {\n        __m128i* const xacc    =       (__m128i *) acc;\n        const __m128i* const xinput  = (const __m128i *) input;\n        const __m128i* const xsecret = (const __m128i *) secret;\n\n        for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) {\n            /* data_vec = xinput[i]; */\n            __m128i const data_vec = __lsx_vld(xinput + i, 0);\n            /* key_vec = xsecret[i]; */\n            __m128i const key_vec = __lsx_vld(xsecret + i, 0);\n            /* data_key = data_vec ^ key_vec; */\n            __m128i const data_key = __lsx_vxor_v(data_vec, key_vec);\n            /* data_key_lo = data_key >> 32; */\n            __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32);\n            // __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32);\n            /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */\n            __m128i const product = __lsx_vmulwev_d_wu(data_key, data_key_lo);\n            /* xacc[i] += swap(data_vec); */\n            __m128i const data_swap = __lsx_vshuf4i_w(data_vec, _LSX_SHUFFLE(1, 0, 3, 2));\n            __m128i const sum = __lsx_vadd_d(xacc[i], data_swap);\n            /* xacc[i] += product; */\n            xacc[i] = __lsx_vadd_d(product, sum);\n        }\n    }\n}\nXXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(lsx)\n\nXXH_FORCE_INLINE void\nXXH3_scrambleAcc_lsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    XXH_ASSERT((((size_t)acc) & 15) == 0);\n    {\n        __m128i* const xacc = (__m128i*) acc;\n        const __m128i* const xsecret = (const __m128i *) secret;\n        const __m128i prime32 = __lsx_vreplgr2vr_w((int)XXH_PRIME32_1);\n\n        for (size_t i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) {\n            /* xacc[i] ^= (xacc[i] >> 47) */\n            __m128i const acc_vec = xacc[i];\n            __m128i const shifted = __lsx_vsrli_d(acc_vec, 47);\n            __m128i const data_vec = __lsx_vxor_v(acc_vec, shifted);\n            /* xacc[i] ^= xsecret[i]; */\n            __m128i const key_vec = __lsx_vld(xsecret + i, 0);\n            __m128i const data_key = __lsx_vxor_v(data_vec, key_vec);\n\n            /* xacc[i] *= XXH_PRIME32_1; */\n            __m128i const data_key_hi = __lsx_vsrli_d(data_key, 32);\n            __m128i const prod_lo = __lsx_vmulwev_d_wu(data_key, prime32);\n            __m128i const prod_hi = __lsx_vmulwev_d_wu(data_key_hi, prime32);\n            xacc[i] = __lsx_vadd_d(prod_lo, __lsx_vslli_d(prod_hi, 32));\n        }\n    }\n}\n\n#endif\n\n/* scalar variants - universal */\n\n#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__))\n/*\n * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they\n * emit an excess mask and a full 64-bit multiply-add (MADD X-form).\n *\n * While this might not seem like much, as AArch64 is a 64-bit architecture, only\n * big Cortex designs have a full 64-bit multiplier.\n *\n * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit\n * multiplies expand to 2-3 multiplies in microcode. This has a major penalty\n * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline.\n *\n * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does\n * not have this penalty and does the mask automatically.\n */\nXXH_FORCE_INLINE xxh_u64\nXXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)\n{\n    xxh_u64 ret;\n    /* note: %x = 64-bit register, %w = 32-bit register */\n    __asm__(\"umaddl %x0, %w1, %w2, %x3\" : \"=r\" (ret) : \"r\" (lhs), \"r\" (rhs), \"r\" (acc));\n    return ret;\n}\n#else\nXXH_FORCE_INLINE xxh_u64\nXXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)\n{\n    return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc;\n}\n#endif\n\n/*!\n * @internal\n * @brief Scalar round for @ref XXH3_accumulate_512_scalar().\n *\n * This is extracted to its own function because the NEON path uses a combination\n * of NEON and scalar.\n */\nXXH_FORCE_INLINE void\nXXH3_scalarRound(void* XXH_RESTRICT acc,\n                 void const* XXH_RESTRICT input,\n                 void const* XXH_RESTRICT secret,\n                 size_t lane)\n{\n    xxh_u64* xacc = (xxh_u64*) acc;\n    xxh_u8 const* xinput  = (xxh_u8 const*) input;\n    xxh_u8 const* xsecret = (xxh_u8 const*) secret;\n    XXH_ASSERT(lane < XXH_ACC_NB);\n    XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0);\n    {\n        xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8);\n        xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8);\n        xacc[lane ^ 1] += data_val; /* swap adjacent lanes */\n        xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]);\n    }\n}\n\n/*!\n * @internal\n * @brief Processes a 64 byte block of data using the scalar path.\n */\nXXH_FORCE_INLINE void\nXXH3_accumulate_512_scalar(void* XXH_RESTRICT acc,\n                     const void* XXH_RESTRICT input,\n                     const void* XXH_RESTRICT secret)\n{\n    size_t i;\n    /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */\n#if defined(__GNUC__) && !defined(__clang__) \\\n  && (defined(__arm__) || defined(__thumb2__)) \\\n  && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \\\n  && XXH_SIZE_OPT <= 0\n#  pragma GCC unroll 8\n#endif\n    for (i=0; i < XXH_ACC_NB; i++) {\n        XXH3_scalarRound(acc, input, secret, i);\n    }\n}\nXXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar)\n\n/*!\n * @internal\n * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar().\n *\n * This is extracted to its own function because the NEON path uses a combination\n * of NEON and scalar.\n */\nXXH_FORCE_INLINE void\nXXH3_scalarScrambleRound(void* XXH_RESTRICT acc,\n                         void const* XXH_RESTRICT secret,\n                         size_t lane)\n{\n    xxh_u64* const xacc = (xxh_u64*) acc;   /* presumed aligned */\n    const xxh_u8* const xsecret = (const xxh_u8*) secret;   /* no alignment restriction */\n    XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0);\n    XXH_ASSERT(lane < XXH_ACC_NB);\n    {\n        xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8);\n        xxh_u64 acc64 = xacc[lane];\n        acc64 = XXH_xorshift64(acc64, 47);\n        acc64 ^= key64;\n        acc64 *= XXH_PRIME32_1;\n        xacc[lane] = acc64;\n    }\n}\n\n/*!\n * @internal\n * @brief Scrambles the accumulators after a large chunk has been read\n */\nXXH_FORCE_INLINE void\nXXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)\n{\n    size_t i;\n    for (i=0; i < XXH_ACC_NB; i++) {\n        XXH3_scalarScrambleRound(acc, secret, i);\n    }\n}\n\nXXH_FORCE_INLINE void\nXXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64)\n{\n    /*\n     * We need a separate pointer for the hack below,\n     * which requires a non-const pointer.\n     * Any decent compiler will optimize this out otherwise.\n     */\n    const xxh_u8* kSecretPtr = XXH3_kSecret;\n    XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);\n\n#if defined(__GNUC__) && defined(__aarch64__)\n    /*\n     * UGLY HACK:\n     * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are\n     * placed sequentially, in order, at the top of the unrolled loop.\n     *\n     * While MOVK is great for generating constants (2 cycles for a 64-bit\n     * constant compared to 4 cycles for LDR), it fights for bandwidth with\n     * the arithmetic instructions.\n     *\n     *   I   L   S\n     * MOVK\n     * MOVK\n     * MOVK\n     * MOVK\n     * ADD\n     * SUB      STR\n     *          STR\n     * By forcing loads from memory (as the asm line causes the compiler to assume\n     * that XXH3_kSecretPtr has been changed), the pipelines are used more\n     * efficiently:\n     *   I   L   S\n     *      LDR\n     *  ADD LDR\n     *  SUB     STR\n     *          STR\n     *\n     * See XXH3_NEON_LANES for details on the pipsline.\n     *\n     * XXH3_64bits_withSeed, len == 256, Snapdragon 835\n     *   without hack: 2654.4 MB/s\n     *   with hack:    3202.9 MB/s\n     */\n    XXH_COMPILER_GUARD(kSecretPtr);\n#endif\n    {   int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16;\n        int i;\n        for (i=0; i < nbRounds; i++) {\n            /*\n             * The asm hack causes the compiler to assume that kSecretPtr aliases with\n             * customSecret, and on aarch64, this prevented LDP from merging two\n             * loads together for free. Putting the loads together before the stores\n             * properly generates LDP.\n             */\n            xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i)     + seed64;\n            xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64;\n            XXH_writeLE64((xxh_u8*)customSecret + 16*i,     lo);\n            XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi);\n    }   }\n}\n\n\ntypedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t);\ntypedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*);\ntypedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64);\n\n\n#if (XXH_VECTOR == XXH_AVX512)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_avx512\n#define XXH3_accumulate     XXH3_accumulate_avx512\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_avx512\n#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512\n\n#elif (XXH_VECTOR == XXH_AVX2)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_avx2\n#define XXH3_accumulate     XXH3_accumulate_avx2\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_avx2\n#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2\n\n#elif (XXH_VECTOR == XXH_SSE2)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_sse2\n#define XXH3_accumulate     XXH3_accumulate_sse2\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_sse2\n#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2\n\n#elif (XXH_VECTOR == XXH_NEON)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_neon\n#define XXH3_accumulate     XXH3_accumulate_neon\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_neon\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#elif (XXH_VECTOR == XXH_VSX)\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_vsx\n#define XXH3_accumulate     XXH3_accumulate_vsx\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_vsx\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#elif (XXH_VECTOR == XXH_SVE)\n#define XXH3_accumulate_512 XXH3_accumulate_512_sve\n#define XXH3_accumulate     XXH3_accumulate_sve\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_scalar\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#elif (XXH_VECTOR == XXH_LSX)\n#define XXH3_accumulate_512 XXH3_accumulate_512_lsx\n#define XXH3_accumulate     XXH3_accumulate_lsx\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_lsx\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#else /* scalar */\n\n#define XXH3_accumulate_512 XXH3_accumulate_512_scalar\n#define XXH3_accumulate     XXH3_accumulate_scalar\n#define XXH3_scrambleAcc    XXH3_scrambleAcc_scalar\n#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n\n#endif\n\n#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */\n#  undef XXH3_initCustomSecret\n#  define XXH3_initCustomSecret XXH3_initCustomSecret_scalar\n#endif\n\nXXH_FORCE_INLINE void\nXXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc,\n                      const xxh_u8* XXH_RESTRICT input, size_t len,\n                      const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                            XXH3_f_accumulate f_acc,\n                            XXH3_f_scrambleAcc f_scramble)\n{\n    size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;\n    size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock;\n    size_t const nb_blocks = (len - 1) / block_len;\n\n    size_t n;\n\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);\n\n    for (n = 0; n < nb_blocks; n++) {\n        f_acc(acc, input + n*block_len, secret, nbStripesPerBlock);\n        f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN);\n    }\n\n    /* last partial block */\n    XXH_ASSERT(len > XXH_STRIPE_LEN);\n    {   size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN;\n        XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE));\n        f_acc(acc, input + nb_blocks*block_len, secret, nbStripes);\n\n        /* last stripe */\n        {   const xxh_u8* const p = input + len - XXH_STRIPE_LEN;\n#define XXH_SECRET_LASTACC_START 7  /* not aligned on 8, last secret is different from acc & scrambler */\n            XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START);\n    }   }\n}\n\nXXH_FORCE_INLINE xxh_u64\nXXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret)\n{\n    return XXH3_mul128_fold64(\n               acc[0] ^ XXH_readLE64(secret),\n               acc[1] ^ XXH_readLE64(secret+8) );\n}\n\nstatic XXH_PUREF XXH64_hash_t\nXXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start)\n{\n    xxh_u64 result64 = start;\n    size_t i = 0;\n\n    for (i = 0; i < 4; i++) {\n        result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i);\n#if defined(__clang__)                                /* Clang */ \\\n    && (defined(__arm__) || defined(__thumb__))       /* ARMv7 */ \\\n    && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */  \\\n    && !defined(XXH_ENABLE_AUTOVECTORIZE)             /* Define to disable */\n        /*\n         * UGLY HACK:\n         * Prevent autovectorization on Clang ARMv7-a. Exact same problem as\n         * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b.\n         * XXH3_64bits, len == 256, Snapdragon 835:\n         *   without hack: 2063.7 MB/s\n         *   with hack:    2560.7 MB/s\n         */\n        XXH_COMPILER_GUARD(result64);\n#endif\n    }\n\n    return XXH3_avalanche(result64);\n}\n\n/* do not align on 8, so that the secret is different from the accumulator */\n#define XXH_SECRET_MERGEACCS_START 11\n\nstatic XXH_PUREF XXH64_hash_t\nXXH3_finalizeLong_64b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 len)\n{\n    return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, len * XXH_PRIME64_1);\n}\n\n#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \\\n                        XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 }\n\nXXH_FORCE_INLINE XXH64_hash_t\nXXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len,\n                           const void* XXH_RESTRICT secret, size_t secretSize,\n                           XXH3_f_accumulate f_acc,\n                           XXH3_f_scrambleAcc f_scramble)\n{\n    XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;\n\n    XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble);\n\n    /* converge into final hash */\n    XXH_STATIC_ASSERT(sizeof(acc) == 64);\n    XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);\n    return XXH3_finalizeLong_64b(acc, (const xxh_u8*)secret, (xxh_u64)len);\n}\n\n/*\n * It's important for performance to transmit secret's size (when it's static)\n * so that the compiler can properly optimize the vectorized loop.\n * This makes a big performance difference for \"medium\" keys (<1 KB) when using AVX instruction set.\n * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE\n * breaks -Og, this is XXH_NO_INLINE.\n */\nXXH3_WITH_SECRET_INLINE XXH64_hash_t\nXXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len,\n                             XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64;\n    return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n/*\n * It's preferable for performance that XXH3_hashLong is not inlined,\n * as it results in a smaller function for small data, easier to the instruction cache.\n * Note that inside this no_inline function, we do inline the internal loop,\n * and provide a statically defined secret size to allow optimization of vector loop.\n */\nXXH_NO_INLINE XXH_PUREF XXH64_hash_t\nXXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len,\n                          XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64; (void)secret; (void)secretLen;\n    return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n/*\n * XXH3_hashLong_64b_withSeed():\n * Generate a custom key based on alteration of default XXH3_kSecret with the seed,\n * and then use this key for long mode hashing.\n *\n * This operation is decently fast but nonetheless costs a little bit of time.\n * Try to avoid it whenever possible (typically when seed==0).\n *\n * It's important for performance that XXH3_hashLong is not inlined. Not sure\n * why (uop cache maybe?), but the difference is large and easily measurable.\n */\nXXH_FORCE_INLINE XXH64_hash_t\nXXH3_hashLong_64b_withSeed_internal(const void* input, size_t len,\n                                    XXH64_hash_t seed,\n                                    XXH3_f_accumulate f_acc,\n                                    XXH3_f_scrambleAcc f_scramble,\n                                    XXH3_f_initCustomSecret f_initSec)\n{\n#if XXH_SIZE_OPT <= 0\n    if (seed == 0)\n        return XXH3_hashLong_64b_internal(input, len,\n                                          XXH3_kSecret, sizeof(XXH3_kSecret),\n                                          f_acc, f_scramble);\n#endif\n    {   XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];\n        f_initSec(secret, seed);\n        return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret),\n                                          f_acc, f_scramble);\n    }\n}\n\n/*\n * It's important for performance that XXH3_hashLong is not inlined.\n */\nXXH_NO_INLINE XXH64_hash_t\nXXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len,\n                           XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)secret; (void)secretLen;\n    return XXH3_hashLong_64b_withSeed_internal(input, len, seed,\n                XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret);\n}\n\n\ntypedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t,\n                                          XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t);\n\nXXH_FORCE_INLINE XXH64_hash_t\nXXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len,\n                     XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,\n                     XXH3_hashLong64_f f_hashLong)\n{\n    XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);\n    /*\n     * If an action is to be taken if `secretLen` condition is not respected,\n     * it should be done here.\n     * For now, it's a contract pre-condition.\n     * Adding a check and a branch here would cost performance at every hash.\n     * Also, note that function signature doesn't offer room to return an error.\n     */\n    if (len <= 16)\n        return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);\n    if (len <= 128)\n        return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    if (len <= XXH3_MIDSIZE_MAX)\n        return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen);\n}\n\n\n/* ===   Public entry point   === */\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length)\n{\n    return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t\nXXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t\nXXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed)\n{\n    return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed);\n}\n\nXXH_PUBLIC_API XXH64_hash_t\nXXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)\n{\n    if (length <= XXH3_MIDSIZE_MAX)\n        return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);\n    return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize);\n}\n\n\n/* ===   XXH3 streaming   === */\n#ifndef XXH_NO_STREAM\n/*\n * Malloc's a pointer that is always aligned to @align.\n *\n * This must be freed with `XXH_alignedFree()`.\n *\n * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte\n * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2\n * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON.\n *\n * This underalignment previously caused a rather obvious crash which went\n * completely unnoticed due to XXH3_createState() not actually being tested.\n * Credit to RedSpah for noticing this bug.\n *\n * The alignment is done manually: Functions like posix_memalign or _mm_malloc\n * are avoided: To maintain portability, we would have to write a fallback\n * like this anyways, and besides, testing for the existence of library\n * functions without relying on external build tools is impossible.\n *\n * The method is simple: Overallocate, manually align, and store the offset\n * to the original behind the returned pointer.\n *\n * Align must be a power of 2 and 8 <= align <= 128.\n */\nstatic XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align)\n{\n    XXH_ASSERT(align <= 128 && align >= 8); /* range check */\n    XXH_ASSERT((align & (align-1)) == 0);   /* power of 2 */\n    XXH_ASSERT(s != 0 && s < (s + align));  /* empty/overflow */\n    {   /* Overallocate to make room for manual realignment and an offset byte */\n        xxh_u8* base = (xxh_u8*)XXH_malloc(s + align);\n        if (base != NULL) {\n            /*\n             * Get the offset needed to align this pointer.\n             *\n             * Even if the returned pointer is aligned, there will always be\n             * at least one byte to store the offset to the original pointer.\n             */\n            size_t offset = align - ((size_t)base & (align - 1)); /* base % align */\n            /* Add the offset for the now-aligned pointer */\n            xxh_u8* ptr = base + offset;\n\n            XXH_ASSERT((size_t)ptr % align == 0);\n\n            /* Store the offset immediately before the returned pointer. */\n            ptr[-1] = (xxh_u8)offset;\n            return ptr;\n        }\n        return NULL;\n    }\n}\n/*\n * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass\n * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout.\n */\nstatic void XXH_alignedFree(void* p)\n{\n    if (p != NULL) {\n        xxh_u8* ptr = (xxh_u8*)p;\n        /* Get the offset byte we added in XXH_malloc. */\n        xxh_u8 offset = ptr[-1];\n        /* Free the original malloc'd pointer */\n        xxh_u8* base = ptr - offset;\n        XXH_free(base);\n    }\n}\n/*! @ingroup XXH3_family */\n/*!\n * @brief Allocate an @ref XXH3_state_t.\n *\n * @return An allocated pointer of @ref XXH3_state_t on success.\n * @return `NULL` on failure.\n *\n * @note Must be freed with XXH3_freeState().\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH3_state_t* XXH3_createState(void)\n{\n    XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64);\n    if (state==NULL) return NULL;\n    XXH3_INITSTATE(state);\n    return state;\n}\n\n/*! @ingroup XXH3_family */\n/*!\n * @brief Frees an @ref XXH3_state_t.\n *\n * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().\n *\n * @return @ref XXH_OK.\n *\n * @note Must be allocated with XXH3_createState().\n *\n * @see @ref streaming_example \"Streaming Example\"\n */\nXXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr)\n{\n    XXH_alignedFree(statePtr);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API void\nXXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state)\n{\n    XXH_memcpy(dst_state, src_state, sizeof(*dst_state));\n}\n\nstatic void\nXXH3_reset_internal(XXH3_state_t* statePtr,\n                    XXH64_hash_t seed,\n                    const void* secret, size_t secretSize)\n{\n    size_t const initStart = offsetof(XXH3_state_t, bufferedSize);\n    size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart;\n    XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart);\n    XXH_ASSERT(statePtr != NULL);\n    /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */\n    memset((char*)statePtr + initStart, 0, initLength);\n    statePtr->acc[0] = XXH_PRIME32_3;\n    statePtr->acc[1] = XXH_PRIME64_1;\n    statePtr->acc[2] = XXH_PRIME64_2;\n    statePtr->acc[3] = XXH_PRIME64_3;\n    statePtr->acc[4] = XXH_PRIME64_4;\n    statePtr->acc[5] = XXH_PRIME32_2;\n    statePtr->acc[6] = XXH_PRIME64_5;\n    statePtr->acc[7] = XXH_PRIME32_1;\n    statePtr->seed = seed;\n    statePtr->useSeed = (seed != 0);\n    statePtr->extSecret = (const unsigned char*)secret;\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);\n    statePtr->secretLimit = secretSize - XXH_STRIPE_LEN;\n    statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    XXH3_reset_internal(statePtr, 0, secret, secretSize);\n    if (secret == NULL) return XXH_ERROR;\n    if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    if (seed==0) return XXH3_64bits_reset(statePtr);\n    if ((seed != statePtr->seed) || (statePtr->extSecret != NULL))\n        XXH3_initCustomSecret(statePtr->customSecret, seed);\n    XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE);\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64)\n{\n    if (statePtr == NULL) return XXH_ERROR;\n    if (secret == NULL) return XXH_ERROR;\n    if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;\n    XXH3_reset_internal(statePtr, seed64, secret, secretSize);\n    statePtr->useSeed = 1; /* always, even if seed64==0 */\n    return XXH_OK;\n}\n\n/*!\n * @internal\n * @brief Processes a large input for XXH3_update() and XXH3_digest_long().\n *\n * Unlike XXH3_hashLong_internal_loop(), this can process data that overlaps a block.\n *\n * @param acc                Pointer to the 8 accumulator lanes\n * @param nbStripesSoFarPtr  In/out pointer to the number of leftover stripes in the block*\n * @param nbStripesPerBlock  Number of stripes in a block\n * @param input              Input pointer\n * @param nbStripes          Number of stripes to process\n * @param secret             Secret pointer\n * @param secretLimit        Offset of the last block in @p secret\n * @param f_acc              Pointer to an XXH3_accumulate implementation\n * @param f_scramble         Pointer to an XXH3_scrambleAcc implementation\n * @return                   Pointer past the end of @p input after processing\n */\nXXH_FORCE_INLINE const xxh_u8 *\nXXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc,\n                    size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock,\n                    const xxh_u8* XXH_RESTRICT input, size_t nbStripes,\n                    const xxh_u8* XXH_RESTRICT secret, size_t secretLimit,\n                    XXH3_f_accumulate f_acc,\n                    XXH3_f_scrambleAcc f_scramble)\n{\n    const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE;\n    /* Process full blocks */\n    if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) {\n        /* Process the initial partial block... */\n        size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr;\n\n        do {\n            /* Accumulate and scramble */\n            f_acc(acc, input, initialSecret, nbStripesThisIter);\n            f_scramble(acc, secret + secretLimit);\n            input += nbStripesThisIter * XXH_STRIPE_LEN;\n            nbStripes -= nbStripesThisIter;\n            /* Then continue the loop with the full block size */\n            nbStripesThisIter = nbStripesPerBlock;\n            initialSecret = secret;\n        } while (nbStripes >= nbStripesPerBlock);\n        *nbStripesSoFarPtr = 0;\n    }\n    /* Process a partial block */\n    if (nbStripes > 0) {\n        f_acc(acc, input, initialSecret, nbStripes);\n        input += nbStripes * XXH_STRIPE_LEN;\n        *nbStripesSoFarPtr += nbStripes;\n    }\n    /* Return end pointer */\n    return input;\n}\n\n#ifndef XXH3_STREAM_USE_STACK\n# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */\n#   define XXH3_STREAM_USE_STACK 1\n# endif\n#endif\n/*\n * Both XXH3_64bits_update and XXH3_128bits_update use this routine.\n */\nXXH_FORCE_INLINE XXH_errorcode\nXXH3_update(XXH3_state_t* XXH_RESTRICT const state,\n            const xxh_u8* XXH_RESTRICT input, size_t len,\n            XXH3_f_accumulate f_acc,\n            XXH3_f_scrambleAcc f_scramble)\n{\n    if (input==NULL) {\n        XXH_ASSERT(len == 0);\n        return XXH_OK;\n    }\n\n    XXH_ASSERT(state != NULL);\n    {   const xxh_u8* const bEnd = input + len;\n        const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;\n#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1\n        /* For some reason, gcc and MSVC seem to suffer greatly\n         * when operating accumulators directly into state.\n         * Operating into stack space seems to enable proper optimization.\n         * clang, on the other hand, doesn't seem to need this trick */\n        XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8];\n        XXH_memcpy(acc, state->acc, sizeof(acc));\n#else\n        xxh_u64* XXH_RESTRICT const acc = state->acc;\n#endif\n        state->totalLen += len;\n        XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE);\n\n        /* small input : just fill in tmp buffer */\n        if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) {\n            XXH_memcpy(state->buffer + state->bufferedSize, input, len);\n            state->bufferedSize += (XXH32_hash_t)len;\n            return XXH_OK;\n        }\n\n        /* total input is now > XXH3_INTERNALBUFFER_SIZE */\n        #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN)\n        XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0);   /* clean multiple */\n\n        /*\n         * Internal buffer is partially filled (always, except at beginning)\n         * Complete it, then consume it.\n         */\n        if (state->bufferedSize) {\n            size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize;\n            XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize);\n            input += loadSize;\n            XXH3_consumeStripes(acc,\n                               &state->nbStripesSoFar, state->nbStripesPerBlock,\n                                state->buffer, XXH3_INTERNALBUFFER_STRIPES,\n                                secret, state->secretLimit,\n                                f_acc, f_scramble);\n            state->bufferedSize = 0;\n        }\n        XXH_ASSERT(input < bEnd);\n        if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) {\n            size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN;\n            input = XXH3_consumeStripes(acc,\n                                       &state->nbStripesSoFar, state->nbStripesPerBlock,\n                                       input, nbStripes,\n                                       secret, state->secretLimit,\n                                       f_acc, f_scramble);\n            XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN);\n\n        }\n        /* Some remaining input (always) : buffer it */\n        XXH_ASSERT(input < bEnd);\n        XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE);\n        XXH_ASSERT(state->bufferedSize == 0);\n        XXH_memcpy(state->buffer, input, (size_t)(bEnd-input));\n        state->bufferedSize = (XXH32_hash_t)(bEnd-input);\n#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1\n        /* save stack accumulators into state */\n        XXH_memcpy(state->acc, acc, sizeof(acc));\n#endif\n    }\n\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)\n{\n    return XXH3_update(state, (const xxh_u8*)input, len,\n                       XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n\nXXH_FORCE_INLINE void\nXXH3_digest_long (XXH64_hash_t* acc,\n                  const XXH3_state_t* state,\n                  const unsigned char* secret)\n{\n    xxh_u8 lastStripe[XXH_STRIPE_LEN];\n    const xxh_u8* lastStripePtr;\n\n    /*\n     * Digest on a local copy. This way, the state remains unaltered, and it can\n     * continue ingesting more input afterwards.\n     */\n    XXH_memcpy(acc, state->acc, sizeof(state->acc));\n    if (state->bufferedSize >= XXH_STRIPE_LEN) {\n        /* Consume remaining stripes then point to remaining data in buffer */\n        size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN;\n        size_t nbStripesSoFar = state->nbStripesSoFar;\n        XXH3_consumeStripes(acc,\n                           &nbStripesSoFar, state->nbStripesPerBlock,\n                            state->buffer, nbStripes,\n                            secret, state->secretLimit,\n                            XXH3_accumulate, XXH3_scrambleAcc);\n        lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN;\n    } else {  /* bufferedSize < XXH_STRIPE_LEN */\n        /* Copy to temp buffer */\n        size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize;\n        XXH_ASSERT(state->bufferedSize > 0);  /* there is always some input buffered */\n        XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize);\n        XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize);\n        lastStripePtr = lastStripe;\n    }\n    /* Last stripe */\n    XXH3_accumulate_512(acc,\n                        lastStripePtr,\n                        secret + state->secretLimit - XXH_SECRET_LASTACC_START);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* state)\n{\n    const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;\n    if (state->totalLen > XXH3_MIDSIZE_MAX) {\n        XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];\n        XXH3_digest_long(acc, state, secret);\n        return XXH3_finalizeLong_64b(acc, secret, (xxh_u64)state->totalLen);\n    }\n    /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */\n    if (state->useSeed)\n        return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);\n    return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen),\n                                  secret, state->secretLimit + XXH_STRIPE_LEN);\n}\n#endif /* !XXH_NO_STREAM */\n\n\n/* ==========================================\n * XXH3 128 bits (a.k.a XXH128)\n * ==========================================\n * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant,\n * even without counting the significantly larger output size.\n *\n * For example, extra steps are taken to avoid the seed-dependent collisions\n * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B).\n *\n * This strength naturally comes at the cost of some speed, especially on short\n * lengths. Note that longer hashes are about as fast as the 64-bit version\n * due to it using only a slight modification of the 64-bit loop.\n *\n * XXH128 is also more oriented towards 64-bit machines. It is still extremely\n * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64).\n */\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    /* A doubled version of 1to3_64b with different constants. */\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(1 <= len && len <= 3);\n    XXH_ASSERT(secret != NULL);\n    /*\n     * len = 1: combinedl = { input[0], 0x01, input[0], input[0] }\n     * len = 2: combinedl = { input[1], 0x02, input[0], input[1] }\n     * len = 3: combinedl = { input[2], 0x03, input[0], input[1] }\n     */\n    {   xxh_u8 const c1 = input[0];\n        xxh_u8 const c2 = input[len >> 1];\n        xxh_u8 const c3 = input[len - 1];\n        xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24)\n                                | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8);\n        xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13);\n        xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;\n        xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed;\n        xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl;\n        xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph;\n        XXH128_hash_t h128;\n        h128.low64  = XXH64_avalanche(keyed_lo);\n        h128.high64 = XXH64_avalanche(keyed_hi);\n        return h128;\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(4 <= len && len <= 8);\n    seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;\n    {   xxh_u32 const input_lo = XXH_readLE32(input);\n        xxh_u32 const input_hi = XXH_readLE32(input + len - 4);\n        xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32);\n        xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed;\n        xxh_u64 const keyed = input_64 ^ bitflip;\n\n        /* Shift len to the left to ensure it is even, this avoids even multiplies. */\n        XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2));\n\n        m128.high64 += (m128.low64 << 1);\n        m128.low64  ^= (m128.high64 >> 3);\n\n        m128.low64   = XXH_xorshift64(m128.low64, 35);\n        m128.low64  *= PRIME_MX2;\n        m128.low64   = XXH_xorshift64(m128.low64, 28);\n        m128.high64  = XXH3_avalanche(m128.high64);\n        return m128;\n    }\n}\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(input != NULL);\n    XXH_ASSERT(secret != NULL);\n    XXH_ASSERT(9 <= len && len <= 16);\n    {   xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed;\n        xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed;\n        xxh_u64 const input_lo = XXH_readLE64(input);\n        xxh_u64       input_hi = XXH_readLE64(input + len - 8);\n        XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1);\n        /*\n         * Put len in the middle of m128 to ensure that the length gets mixed to\n         * both the low and high bits in the 128x64 multiply below.\n         */\n        m128.low64 += (xxh_u64)(len - 1) << 54;\n        input_hi   ^= bitfliph;\n        /*\n         * Add the high 32 bits of input_hi to the high 32 bits of m128, then\n         * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to\n         * the high 64 bits of m128.\n         *\n         * The best approach to this operation is different on 32-bit and 64-bit.\n         */\n        if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */\n            /*\n             * 32-bit optimized version, which is more readable.\n             *\n             * On 32-bit, it removes an ADC and delays a dependency between the two\n             * halves of m128.high64, but it generates an extra mask on 64-bit.\n             */\n            m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2);\n        } else {\n            /*\n             * 64-bit optimized (albeit more confusing) version.\n             *\n             * Uses some properties of addition and multiplication to remove the mask:\n             *\n             * Let:\n             *    a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF)\n             *    b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000)\n             *    c = XXH_PRIME32_2\n             *\n             *    a + (b * c)\n             * Inverse Property: x + y - x == y\n             *    a + (b * (1 + c - 1))\n             * Distributive Property: x * (y + z) == (x * y) + (x * z)\n             *    a + (b * 1) + (b * (c - 1))\n             * Identity Property: x * 1 == x\n             *    a + b + (b * (c - 1))\n             *\n             * Substitute a, b, and c:\n             *    input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))\n             *\n             * Since input_hi.hi + input_hi.lo == input_hi, we get this:\n             *    input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))\n             */\n            m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1);\n        }\n        /* m128 ^= XXH_swap64(m128 >> 64); */\n        m128.low64  ^= XXH_swap64(m128.high64);\n\n        {   /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */\n            XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2);\n            h128.high64 += m128.high64 * XXH_PRIME64_2;\n\n            h128.low64   = XXH3_avalanche(h128.low64);\n            h128.high64  = XXH3_avalanche(h128.high64);\n            return h128;\n    }   }\n}\n\n/*\n * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN\n */\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)\n{\n    XXH_ASSERT(len <= 16);\n    {   if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed);\n        if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed);\n        if (len) return XXH3_len_1to3_128b(input, len, secret, seed);\n        {   XXH128_hash_t h128;\n            xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72);\n            xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88);\n            h128.low64 = XXH64_avalanche(seed ^ bitflipl);\n            h128.high64 = XXH64_avalanche( seed ^ bitfliph);\n            return h128;\n    }   }\n}\n\n/*\n * A bit slower than XXH3_mix16B, but handles multiply by zero better.\n */\nXXH_FORCE_INLINE XXH128_hash_t\nXXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2,\n              const xxh_u8* secret, XXH64_hash_t seed)\n{\n    acc.low64  += XXH3_mix16B (input_1, secret+0, seed);\n    acc.low64  ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8);\n    acc.high64 += XXH3_mix16B (input_2, secret+16, seed);\n    acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8);\n    return acc;\n}\n\n\nXXH_FORCE_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                      const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                      XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(16 < len && len <= 128);\n\n    {   XXH128_hash_t acc;\n        acc.low64 = len * XXH_PRIME64_1;\n        acc.high64 = 0;\n\n#if XXH_SIZE_OPT >= 1\n        {\n            /* Smaller, but slightly slower. */\n            unsigned int i = (unsigned int)(len - 1) / 32;\n            do {\n                acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed);\n            } while (i-- != 0);\n        }\n#else\n        if (len > 32) {\n            if (len > 64) {\n                if (len > 96) {\n                    acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed);\n                }\n                acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed);\n            }\n            acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed);\n        }\n        acc = XXH128_mix32B(acc, input, input+len-16, secret, seed);\n#endif\n        {   XXH128_hash_t h128;\n            h128.low64  = acc.low64 + acc.high64;\n            h128.high64 = (acc.low64    * XXH_PRIME64_1)\n                        + (acc.high64   * XXH_PRIME64_4)\n                        + ((len - seed) * XXH_PRIME64_2);\n            h128.low64  = XXH3_avalanche(h128.low64);\n            h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);\n            return h128;\n        }\n    }\n}\n\nXXH_NO_INLINE XXH_PUREF XXH128_hash_t\nXXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len,\n                       const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                       XXH64_hash_t seed)\n{\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;\n    XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);\n\n    {   XXH128_hash_t acc;\n        unsigned i;\n        acc.low64 = len * XXH_PRIME64_1;\n        acc.high64 = 0;\n        /*\n         *  We set as `i` as offset + 32. We do this so that unchanged\n         * `len` can be used as upper bound. This reaches a sweet spot\n         * where both x86 and aarch64 get simple agen and good codegen\n         * for the loop.\n         */\n        for (i = 32; i < 160; i += 32) {\n            acc = XXH128_mix32B(acc,\n                                input  + i - 32,\n                                input  + i - 16,\n                                secret + i - 32,\n                                seed);\n        }\n        acc.low64 = XXH3_avalanche(acc.low64);\n        acc.high64 = XXH3_avalanche(acc.high64);\n        /*\n         * NB: `i <= len` will duplicate the last 32-bytes if\n         * len % 32 was zero. This is an unfortunate necessity to keep\n         * the hash result stable.\n         */\n        for (i=160; i <= len; i += 32) {\n            acc = XXH128_mix32B(acc,\n                                input + i - 32,\n                                input + i - 16,\n                                secret + XXH3_MIDSIZE_STARTOFFSET + i - 160,\n                                seed);\n        }\n        /* last bytes */\n        acc = XXH128_mix32B(acc,\n                            input + len - 16,\n                            input + len - 32,\n                            secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16,\n                            (XXH64_hash_t)0 - seed);\n\n        {   XXH128_hash_t h128;\n            h128.low64  = acc.low64 + acc.high64;\n            h128.high64 = (acc.low64    * XXH_PRIME64_1)\n                        + (acc.high64   * XXH_PRIME64_4)\n                        + ((len - seed) * XXH_PRIME64_2);\n            h128.low64  = XXH3_avalanche(h128.low64);\n            h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);\n            return h128;\n        }\n    }\n}\n\nstatic XXH_PUREF XXH128_hash_t\nXXH3_finalizeLong_128b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, xxh_u64 len)\n{\n    XXH128_hash_t h128;\n    h128.low64 = XXH3_finalizeLong_64b(acc, secret, len);\n    h128.high64 = XXH3_mergeAccs(acc, secret + secretSize\n                                             - XXH_STRIPE_LEN - XXH_SECRET_MERGEACCS_START,\n                                             ~(len * XXH_PRIME64_2));\n    return h128;\n}\n\nXXH_FORCE_INLINE XXH128_hash_t\nXXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len,\n                            const xxh_u8* XXH_RESTRICT secret, size_t secretSize,\n                            XXH3_f_accumulate f_acc,\n                            XXH3_f_scrambleAcc f_scramble)\n{\n    XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;\n\n    XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble);\n\n    /* converge into final hash */\n    XXH_STATIC_ASSERT(sizeof(acc) == 64);\n    XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);\n    return XXH3_finalizeLong_128b(acc, secret, secretSize, (xxh_u64)len);\n}\n\n/*\n * It's important for performance that XXH3_hashLong() is not inlined.\n */\nXXH_NO_INLINE XXH_PUREF XXH128_hash_t\nXXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len,\n                           XXH64_hash_t seed64,\n                           const void* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64; (void)secret; (void)secretLen;\n    return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret),\n                                       XXH3_accumulate, XXH3_scrambleAcc);\n}\n\n/*\n * It's important for performance to pass @p secretLen (when it's static)\n * to the compiler, so that it can properly optimize the vectorized loop.\n *\n * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE\n * breaks -Og, this is XXH_NO_INLINE.\n */\nXXH3_WITH_SECRET_INLINE XXH128_hash_t\nXXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len,\n                              XXH64_hash_t seed64,\n                              const void* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)seed64;\n    return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen,\n                                       XXH3_accumulate, XXH3_scrambleAcc);\n}\n\nXXH_FORCE_INLINE XXH128_hash_t\nXXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len,\n                                XXH64_hash_t seed64,\n                                XXH3_f_accumulate f_acc,\n                                XXH3_f_scrambleAcc f_scramble,\n                                XXH3_f_initCustomSecret f_initSec)\n{\n    if (seed64 == 0)\n        return XXH3_hashLong_128b_internal(input, len,\n                                           XXH3_kSecret, sizeof(XXH3_kSecret),\n                                           f_acc, f_scramble);\n    {   XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];\n        f_initSec(secret, seed64);\n        return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret),\n                                           f_acc, f_scramble);\n    }\n}\n\n/*\n * It's important for performance that XXH3_hashLong is not inlined.\n */\nXXH_NO_INLINE XXH128_hash_t\nXXH3_hashLong_128b_withSeed(const void* input, size_t len,\n                            XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen)\n{\n    (void)secret; (void)secretLen;\n    return XXH3_hashLong_128b_withSeed_internal(input, len, seed64,\n                XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret);\n}\n\ntypedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t,\n                                            XXH64_hash_t, const void* XXH_RESTRICT, size_t);\n\nXXH_FORCE_INLINE XXH128_hash_t\nXXH3_128bits_internal(const void* input, size_t len,\n                      XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,\n                      XXH3_hashLong128_f f_hl128)\n{\n    XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);\n    /*\n     * If an action is to be taken if `secret` conditions are not respected,\n     * it should be done here.\n     * For now, it's a contract pre-condition.\n     * Adding a check and a branch here would cost performance at every hash.\n     */\n    if (len <= 16)\n        return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);\n    if (len <= 128)\n        return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    if (len <= XXH3_MIDSIZE_MAX)\n        return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);\n    return f_hl128(input, len, seed64, secret, secretLen);\n}\n\n\n/* ===   Public XXH128 API   === */\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len)\n{\n    return XXH3_128bits_internal(input, len, 0,\n                                 XXH3_kSecret, sizeof(XXH3_kSecret),\n                                 XXH3_hashLong_128b_default);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    return XXH3_128bits_internal(input, len, 0,\n                                 (const xxh_u8*)secret, secretSize,\n                                 XXH3_hashLong_128b_withSecret);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)\n{\n    return XXH3_128bits_internal(input, len, seed,\n                                 XXH3_kSecret, sizeof(XXH3_kSecret),\n                                 XXH3_hashLong_128b_withSeed);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)\n{\n    if (len <= XXH3_MIDSIZE_MAX)\n        return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);\n    return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)\n{\n    return XXH3_128bits_withSeed(input, len, seed);\n}\n\n\n/* ===   XXH3 128-bit streaming   === */\n#ifndef XXH_NO_STREAM\n/*\n * All initialization and update functions are identical to 64-bit streaming variant.\n * The only difference is the finalization routine.\n */\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr)\n{\n    return XXH3_64bits_reset(statePtr);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize)\n{\n    return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed)\n{\n    return XXH3_64bits_reset_withSeed(statePtr, seed);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)\n{\n    return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)\n{\n    return XXH3_64bits_update(state, input, len);\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* state)\n{\n    const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;\n    if (state->totalLen > XXH3_MIDSIZE_MAX) {\n        XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];\n        XXH3_digest_long(acc, state, secret);\n        XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);\n        return XXH3_finalizeLong_128b(acc, secret, state->secretLimit + XXH_STRIPE_LEN,  (xxh_u64)state->totalLen);\n    }\n    /* len <= XXH3_MIDSIZE_MAX : short code */\n    if (state->useSeed)\n        return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);\n    return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen),\n                                   secret, state->secretLimit + XXH_STRIPE_LEN);\n}\n#endif /* !XXH_NO_STREAM */\n/* 128-bit utility functions */\n\n#include <string.h>   /* memcmp, memcpy */\n\n/* return : 1 is equal, 0 if different */\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2)\n{\n    /* note : XXH128_hash_t is compact, it has no padding byte */\n    return !(memcmp(&h1, &h2, sizeof(h1)));\n}\n\n/* This prototype is compatible with stdlib's qsort().\n * @return : >0 if *h128_1  > *h128_2\n *           <0 if *h128_1  < *h128_2\n *           =0 if *h128_1 == *h128_2  */\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2)\n{\n    XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1;\n    XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2;\n    int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64);\n    /* note : bets that, in most cases, hash values are different */\n    if (hcmp) return hcmp;\n    return (h1.low64 > h2.low64) - (h2.low64 > h1.low64);\n}\n\n\n/*======   Canonical representation   ======*/\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API void\nXXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash)\n{\n    XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t));\n    if (XXH_CPU_LITTLE_ENDIAN) {\n        hash.high64 = XXH_swap64(hash.high64);\n        hash.low64  = XXH_swap64(hash.low64);\n    }\n    XXH_memcpy(dst, &hash.high64, sizeof(hash.high64));\n    XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64));\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH128_hash_t\nXXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src)\n{\n    XXH128_hash_t h;\n    h.high64 = XXH_readBE64(src);\n    h.low64  = XXH_readBE64(src->digest + 8);\n    return h;\n}\n\n\n\n/* ==========================================\n * Secret generators\n * ==========================================\n */\n#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x))\n\nXXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128)\n{\n    XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 );\n    XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 );\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API XXH_errorcode\nXXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize)\n{\n#if (XXH_DEBUGLEVEL >= 1)\n    XXH_ASSERT(secretBuffer != NULL);\n    XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);\n#else\n    /* production mode, assert() are disabled */\n    if (secretBuffer == NULL) return XXH_ERROR;\n    if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;\n#endif\n\n    if (customSeedSize == 0) {\n        customSeed = XXH3_kSecret;\n        customSeedSize = XXH_SECRET_DEFAULT_SIZE;\n    }\n#if (XXH_DEBUGLEVEL >= 1)\n    XXH_ASSERT(customSeed != NULL);\n#else\n    if (customSeed == NULL) return XXH_ERROR;\n#endif\n\n    /* Fill secretBuffer with a copy of customSeed - repeat as needed */\n    {   size_t pos = 0;\n        while (pos < secretSize) {\n            size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize);\n            memcpy((char*)secretBuffer + pos, customSeed, toCopy);\n            pos += toCopy;\n    }   }\n\n    {   size_t const nbSeg16 = secretSize / 16;\n        size_t n;\n        XXH128_canonical_t scrambler;\n        XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0));\n        for (n=0; n<nbSeg16; n++) {\n            XXH128_hash_t const h128 = XXH128(&scrambler, sizeof(scrambler), n);\n            XXH3_combine16((char*)secretBuffer + n*16, h128);\n        }\n        /* last segment */\n        XXH3_combine16((char*)secretBuffer + secretSize - 16, XXH128_hashFromCanonical(&scrambler));\n    }\n    return XXH_OK;\n}\n\n/*! @ingroup XXH3_family */\nXXH_PUBLIC_API void\nXXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed)\n{\n    XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];\n    XXH3_initCustomSecret(secret, seed);\n    XXH_ASSERT(secretBuffer != NULL);\n    memcpy(secretBuffer, secret, XXH_SECRET_DEFAULT_SIZE);\n}\n\n\n\n/* Pop our optimization override from above */\n#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \\\n  && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \\\n  && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */\n#  pragma GCC pop_options\n#endif\n\n#endif  /* XXH_NO_LONG_LONG */\n\n#endif  /* XXH_NO_XXH3 */\n\n/*!\n * @}\n */\n#endif  /* XXH_IMPLEMENTATION */\n\n\n#if defined (__cplusplus)\n} /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/BrotliDecoder.cpp",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"BrotliDecoder.h\"\n\nnamespace NCompress {\nnamespace NBROTLI {\n\nCDecoder::CDecoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors())\n{\n  _props.clear();\n}\n\nCDecoder::~CDecoder()\n{\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte * prop, UInt32 size))\n{\n  DProps *pProps = (DProps *)prop;\n\n  if (size != sizeof(DProps))\n    return E_NOTIMPL;\n\n  memcpy(&_props, pProps, sizeof (DProps));\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = BROTLIMT_THREAD_MAX;\n  // if single-threaded, retain artificial number set in BrotliHandler (always prefer .br format):\n  if ((int)numThreads < 1) {\n    numThreads = 0;\n  }\n  else\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\nHRESULT CDecoder::SetOutStreamSizeResume(const UInt64 * /*outSize*/)\n{\n  _processedOut = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 * outSize))\n{\n  _processedIn = 0;\n  RINOK(SetOutStreamSizeResume(outSize));\n  return S_OK;\n}\n\nHRESULT CDecoder::CodeSpec(ISequentialInStream * inStream,\n  ISequentialOutStream * outStream, ICompressProgressInfo * progress)\n{\n    NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n    Context.InputStream = inStream;\n    Context.OutputStream = outStream;\n    Context.Progress = progress;\n    Context.ProcessedInputSize = &_processedIn;\n    Context.ProcessedOutputSize = &_processedOut;\n    return ::NanaZipCodecsBrotliDecode(&Context, _numThreads, _inputSize);\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream * inStream, ISequentialOutStream * outStream,\n  const UInt64 * /*inSize */, const UInt64 *outSize, ICompressProgressInfo * progress))\n{\n  SetOutStreamSize(outSize);\n  return CodeSpec(inStream, outStream, progress);\n}\n\n#ifndef Z7_NO_READ_FROM_CODER\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream * inStream))\n{\n  _inStream = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n{\n  _inStream.Release();\n  return S_OK;\n}\n#endif\n\nHRESULT CDecoder::CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress)\n{\n  RINOK(SetOutStreamSizeResume(outSize));\n  return CodeSpec(_inStream, outStream, progress);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/BrotliDecoder.h",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#define BROTLI_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <brotli/decode.h>\n#include <brotli-mt.h>\n\n#include \"../../SevenZip/CPP/Windows/System.h\"\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n#include \"../../SevenZip/CPP/7zip/Common/ProgressMt.h\"\n\n#include <NanaZip.Codecs.MultiThreadWrapper.Brotli.h>\n\nnamespace NCompress {\nnamespace NBROTLI {\n\nstruct DProps\n{\n  DProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = BROTLI_VERSION_MAJOR;\n    _ver_minor = BROTLI_VERSION_MINOR;\n    _level = 1;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n};\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetCoderMt,\n  public ICompressSetInStream,\n  public CMyUnknownImp\n{\n  CMyComPtr < ISequentialInStream > _inStream;\n\npublic:\n  DProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n  HRESULT CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress);\n  HRESULT SetOutStreamSizeResume(const UInt64 *outSize);\n\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM_QI_ENTRY(ICompressSetInStream)\n#endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n  Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize));\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_IFACE_COM7_IMP(ICompressSetInStream)\n  UInt64 GetInputProcessedSize() const { return _processedIn; }\n#endif\n\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/BrotliEncoder.cpp",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"BrotliEncoder.h\"\n#include \"BrotliDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NBROTLI {\n\nCEncoder::CEncoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors()),\n  _Long(-1),\n  _WindowLog(-1),\n  unpackSize(0),\n  _ctx(NULL)\n{\n  _props.clear();\n}\n\nCEncoder::~CEncoder()\n{\n  if (_ctx)\n    BROTLIMT_freeCCtx(_ctx);\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID * propIDs, const PROPVARIANT * coderProps, UInt32 numProps))\n{\n  _props.clear();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT & prop = coderProps[i];\n    PROPID propID = propIDs[i];\n    UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n    case NCoderPropID::kLevel:\n      {\n        if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n\n        _props._level = static_cast < Byte > (prop.ulVal);\n        Byte mylevel = static_cast < Byte > (BROTLIMT_LEVEL_MAX);\n        if (_props._level > mylevel)\n          _props._level = mylevel;\n\n        break;\n      }\n    case NCoderPropID::kNumThreads:\n      {\n        SetNumberOfThreads(v);\n        break;\n      }\n    case NCoderPropID::kLong:\n      {\n        /* like --long in zstd cli program */\n        _Long = 1;\n        if (v == 0) {\n          if (prop.vt == VT_EMPTY) {\n            // m0=brotli:long -> long=default\n            _WindowLog = BROTLI_MAX_WINDOW_BITS; //BROTLI_DEFAULT_WINDOW;\n          } else {\n            // m0=brotli:long=0 -> long=auto\n            _WindowLog = 0;\n          }\n        } else if (v < BROTLI_MIN_WINDOW_BITS) {\n          // m0=brotli:long=9 -> long=10\n          _WindowLog = BROTLI_MIN_WINDOW_BITS;\n        } else if (v > BROTLI_LARGE_MAX_WINDOW_BITS) {\n          // m0=brotli:long=33 -> long=max\n          _WindowLog = BROTLI_LARGE_MAX_WINDOW_BITS;\n        } else {\n          // m0=brotli:long=15 -> long=value\n          _WindowLog = v;\n        }\n        break;\n      }\n    case NCoderPropID::kWindowLog:\n      {\n        if (v < BROTLI_MIN_WINDOW_BITS) v = BROTLI_MIN_WINDOW_BITS;\n        if (v > BROTLI_MAX_WINDOW_BITS) v = BROTLI_MAX_WINDOW_BITS;\n        _WindowLog = v;\n        break;\n      }\n    default:\n      {\n        break;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    if (propID == NCoderPropID::kExpectedDataSize)\n      if (prop.vt == VT_UI8 && prop.uhVal.QuadPart)\n        unpackSize = prop.uhVal.QuadPart;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream * outStream))\n{\n  return WriteStream(outStream, &_props, sizeof (_props));\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream,\n  ISequentialOutStream *outStream, const UInt64 * /*inSize*/ ,\n  const UInt64 * /*outSize */, ICompressProgressInfo *progress))\n{\n  BROTLIMT_RdWr_t rdwr;\n  size_t result;\n  HRESULT res = S_OK;\n  \n  _processedIn = 0;\n  _processedOut = 0;\n\n  NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n  Context.InputStream = inStream;\n  Context.OutputStream = outStream;\n  Context.Progress = progress;\n  Context.ProcessedInputSize = &_processedIn;\n  Context.ProcessedOutputSize = &_processedOut;\n\n  /* 1) setup read/write functions */\n  rdwr.fn_read = ::NanaZipCodecsBrotliRead;\n  rdwr.fn_write = ::NanaZipCodecsBrotliWrite;\n  rdwr.arg_read = reinterpret_cast<void*>(&Context);\n  rdwr.arg_write = reinterpret_cast<void*>(&Context);\n\n  /* 2) create compression context, if needed */\n  if (!_ctx)\n    _ctx = BROTLIMT_createCCtx(_numThreads, unpackSize, _props._level, _inputSize, \n      _WindowLog >= 0 ? _WindowLog : BROTLI_MAX_WINDOW_BITS);\n  if (!_ctx)\n    return S_FALSE;\n\n  /* 4) compress */\n  result = BROTLIMT_compressCCtx(_ctx, &rdwr);\n  if (BROTLIMT_isError(result)) {\n    if (result == (size_t)-BROTLIMT_error_canceled)\n      return E_ABORT;\n    return E_FAIL;\n  }\n\n  return res;\n}\n\nZ7_COM7F_IMF(CEncoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = BROTLIMT_THREAD_MAX;\n  // if single-threaded, retain artificial number set in BrotliHandler (always prefer .br format):\n  if ((int)numThreads < 1) {\n    numThreads = 0;\n  }\n  else\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/BrotliEncoder.h",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#define BROTLI_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <brotli/encode.h>\n#include <brotli-mt.h>\n\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NBROTLI {\n\nstruct CProps\n{\n  CProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = BROTLI_VERSION_MAJOR;\n    _ver_minor = BROTLI_VERSION_MINOR;\n    _level = 3;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n};\n\nclass CEncoder Z7_final:\n  public ICompressCoder,\n  public ICompressWriteCoderProperties,\n  public ICompressSetCoderMt,\n  public ICompressSetCoderProperties,\n  public ICompressSetCoderPropertiesOpt,\n  public CMyUnknownImp\n{\npublic:\n  CProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  Int32 _Long;\n  Int32 _WindowLog;\n  UInt64 unpackSize;\n\n  BROTLIMT_CCtx *_ctx;\n\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressWriteCoderProperties)\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n  Z7_COM_QI_ENTRY(ICompressSetCoderProperties)\n  Z7_COM_QI_ENTRY(ICompressSetCoderPropertiesOpt)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\npublic:\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties)\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n  Z7_IFACE_COM7_IMP(ICompressSetCoderProperties)\n  Z7_IFACE_COM7_IMP(ICompressSetCoderPropertiesOpt)\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/BrotliHandler.cpp",
    "content": "﻿// BrotliHandler.cpp\n\n#include \"../../SevenZip/CPP/7zip/Archive/StdAfx.h\"\n\n#include \"../../SevenZip/C/CpuArch.h\"\n#include <brotli/decode.h>\n\n#include \"../../SevenZip/CPP/Common/ComTry.h\"\n#include \"../../SevenZip/CPP/Common/Defs.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/ProgressUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterArc.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#include \"BrotliDecoder.h\"\n#include \"BrotliEncoder.h\"\n#include \"../../SevenZip/CPP/7zip/Compress/CopyCoder.h\"\n\n#include \"../../SevenZip/CPP/7zip/Archive/Common/DummyOutStream.h\"\n#include \"../../SevenZip/CPP/7zip/Archive/Common/HandlerOut.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NBROTLI {\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n  IArchiveOpenSeq,\n  IOutArchive,\n  ISetProperties\n)\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  bool _isArc;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize;\n\n  CSingleMethodProps _props;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams,\n  kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID /*propID*/, PROPVARIANT * /*value*/))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n// Notes about Brotli .br detection\n// - raw Brotli (RFC 7932) has no signature\n// - framed Brotli (RFC 9841) has sig but isn't well deployed\n// - variant 1: detect brotli by it's (mostly not used) signature\n// - variant 2: try to decompress raw brotli stream\n// - warning: most brotli compressed data is raw format\n// /TR 28.12.2025\nAPI_FUNC_static_IsArc IsArc_Brotli(const Byte *p, size_t size)\n{\n  if (size < 5)\n    return k_IsArc_Res_NEED_MORE;\n\n  // Brotli - https://github.com/madler/brotli/blob/master/br-format-v3.txt\n  if (p[0] == 0xCE && p[1] == 0xB2 && p[2] == 0xCF && p[3] == 0x81)\n    return k_IsArc_Res_YES;\n\n  // Brotli (RFC 9841)\n  if (p[0] == 0x91 && p[1] == 0x19 && p[2] == 0x62 && p[3] == 0x66)\n    return k_IsArc_Res_YES;\n\n  // try to detect raw brotli stream\n  BrotliDecoderState *st = BrotliDecoderCreateInstance(NULL, NULL, NULL);\n  if (!st)\n    return k_IsArc_Res_NO;\n\n  const uint8_t *next_in = p;\n  size_t avail_in = size;\n  uint8_t out[256];\n  uint8_t *x = out;\n  size_t avail_out = sizeof(out);\n  BrotliDecoderResult r;\n  r = BrotliDecoderDecompressStream(st, &avail_in, &next_in, &avail_out, &x, NULL);\n  BrotliDecoderDestroyInstance(st);\n  if (r == BROTLI_DECODER_RESULT_ERROR)\n    return k_IsArc_Res_NO;\n\n  // when we get here, the begin of some brotli stream was detected:\n  // - BROTLI_DECODER_RESULT_SUCCESS\n  // - BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT\n  // - BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT\n  return k_IsArc_Res_YES;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    _isArc = true;\n    _stream = stream;\n    _seqStream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n\n  _packSize = 0;\n\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    extractCallback->SetTotal(_packSize);\n\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  extractCallback->PrepareOperation(askMode);\n\n  Int32 opRes;\n\n  {\n\n  NCompress::NBROTLI::CDecoder *decoderSpec = new NCompress::NBROTLI::CDecoder;\n  /*\n   * Brotli stream doesn't contain info about threads and it is normally\n   * single-threaded by default (.br files without header/mt-frames),\n   * so force it here as 0 for brotli-st, unless it's specified (e. g. was compressed\n   * also multi-threaded, important for -mmt>=1 to use brotli-mt instead of brotli-st)\n   */\n  decoderSpec->SetNumberOfThreads(!_props._numThreads_WasForced ? 0 : _props._numThreads);\n  CMyComPtr<ICompressCoder> decoder = decoderSpec;\n  decoderSpec->SetInStream(_seqStream);\n\n  CDummyOutStream *outStreamSpec = new CDummyOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n  outStreamSpec->SetStream(realOutStream);\n  outStreamSpec->Init();\n\n  realOutStream.Release();\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, true);\n\n  UInt64 packSize = 0;\n  UInt64 unpackedSize = 0;\n\n  HRESULT result = S_OK;\n\n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackedSize;\n\n    RINOK(lps->SetCur());\n    result = decoderSpec->CodeResume(outStream, &unpackedSize, progress);\n    UInt64 streamSize = decoderSpec->GetInputProcessedSize();\n\n    if (result != S_FALSE && result != S_OK)\n      return result;\n\n    if (unpackedSize == 0)\n      break;\n\n    if (streamSize == packSize)\n    {\n      // no new bytes in input stream, So it's good end of archive.\n      result = S_OK;\n      break;\n    }\n\n    if (packSize > streamSize)\n      return E_FAIL;\n\n    if (result != S_OK)\n      break;\n  }\n\n  decoderSpec->ReleaseInStream();\n  outStream.Release();\n\n  if (!_isArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (_dataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK) {\n    _unpackSize = outStreamSpec->GetSize();\n    _unpackSize_Defined = true;\n    opRes = NExtract::NOperationResult::kOK;\n  } else\n    return result;\n\n  }\n\n  return extractCallback->SetOperationResult(opRes);\n\n  COM_TRY_END\n}\n\nstatic HRESULT UpdateArchive(\n    UInt64 unpackSize,\n    ISequentialOutStream *outStream,\n    const CProps &props,\n    IArchiveUpdateCallback *updateCallback)\n{\n  RINOK(updateCallback->SetTotal(unpackSize));\n  CMyComPtr<ISequentialInStream> fileInStream;\n  RINOK(updateCallback->GetStream(0, &fileInStream));\n  CLocalProgress *localProgressSpec = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;\n  localProgressSpec->Init(updateCallback, true);\n  NCompress::NBROTLI::CEncoder *encoderSpec = new NCompress::NBROTLI::CEncoder;\n  encoderSpec->unpackSize = unpackSize;\n  encoderSpec->SetNumberOfThreads(0); /* .br - single threaded processing (without header/mt-frames) */\n  CMyComPtr<ICompressCoder> encoder = encoderSpec;\n  RINOK(props.SetCoderProps(encoderSpec, NULL));\n  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));\n  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  *type = NFileTimeType::kUnix;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\n \n  if ((newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n  \n  if ((newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n    return UpdateArchive(size, outStream, _props, updateCallback);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(updateCallback, true);\n\n  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;\n  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, 0,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  if (_stream)\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n\n  return NCompress::CopyStream(_stream, outStream, progress);\n\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  return _props.SetProperties(names, values, numProps);\n}\n\nIMP_CreateArcIn\nIMP_CreateArcOut\nREGISTER_ARC_R(\n  \"brotli\", \"br brotli tbr\", 0, 0x1F,\n  0, NULL,\n  0,\n  NArcInfoFlags::kKeepName | NArcInfoFlags::kPureStartOpen | NArcInfoFlags::kByExtOnlyOpen,\n  0,\n  CreateArc, CreateArcOut, \n  IsArc_Brotli)\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/BrotliRegister.cpp",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n\n#include \"BrotliDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"BrotliEncoder.h\"\n#endif\n\nREGISTER_CODEC_E(\n  BROTLI,\n  NCompress::NBROTLI::CDecoder(),\n  NCompress::NBROTLI::CEncoder(),\n  0x4F71102, \"BROTLI\")\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/FastLzma2Encoder.cpp",
    "content": "﻿// FastLzma2Encoder.cpp\n\n#define NOMINMAX\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n\n#include <algorithm>\n\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Lzma2Enc.h\"\n#include <fl2_errors.h>\n\n#include \"../../SevenZip/CPP/7zip/Common/CWrappers.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#include \"FastLzma2Encoder.h\"\n\nnamespace NCompress {\n\nnamespace NLzma {\n\nHRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);\n\n}\n\nnamespace NLzma2 {\n\nHRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT& prop, CLzma2EncProps& lzma2Props);\n\n// Fast LZMA2 encoder\n\nstatic HRESULT TranslateError(size_t res)\n{\n  if (FL2_getErrorCode(res) == FL2_error_memory_allocation)\n    return E_OUTOFMEMORY;\n  return S_FALSE;\n}\n\n#define CHECK_S(f_) do { \\\n  size_t r_ = f_; \\\n  if (FL2_isError(r_)) \\\n    return TranslateError(r_); \\\n} while (false)\n\n#define CHECK_H(f_) do { \\\n  HRESULT r_ = f_; \\\n  if (r_ != S_OK) \\\n    return r_; \\\n} while (false)\n\n#define CHECK_P(f) if (FL2_isError(f)) return E_INVALIDARG;  /* check and convert error code */\n\n#define MIN_BLOCK_SIZE (1U << 20)\n#define MAX_BLOCK_SIZE (1U << 28)\n\nCFastEncoder::FastLzma2::FastLzma2()\n  : fcs(NULL),\n  dict_pos(0)\n{\n}\n\nCFastEncoder::FastLzma2::~FastLzma2()\n{\n  FL2_freeCCtx(fcs);\n}\n\nHRESULT CFastEncoder::FastLzma2::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)\n{\n  CLzma2EncProps lzma2Props;\n  Lzma2EncProps_Init(&lzma2Props);\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props));\n  }\n  if (fcs == NULL) {\n    fcs = FL2_createCStreamMt(lzma2Props.numTotalThreads, 1);\n    if (fcs == NULL)\n      return E_OUTOFMEMORY;\n  }\n  if (lzma2Props.lzmaProps.algo > 2) {\n    if (lzma2Props.lzmaProps.algo > 3)\n      return E_INVALIDARG;\n    lzma2Props.lzmaProps.algo = 2;\n    FL2_CCtx_setParameter(fcs, FL2_p_highCompression, 1);\n    FL2_CCtx_setParameter(fcs, FL2_p_compressionLevel, lzma2Props.lzmaProps.level);\n  }\n  else {\n    FL2_CCtx_setParameter(fcs, FL2_p_compressionLevel, lzma2Props.lzmaProps.level);\n  }\n  size_t dictSize = lzma2Props.lzmaProps.dictSize;\n  if (!dictSize) {\n    dictSize = FL2_CCtx_getParameter(fcs, FL2_p_dictionarySize);\n  }\n  size_t reduceSize = (size_t)lzma2Props.lzmaProps.reduceSize;\n  reduceSize += (reduceSize < (size_t)-1); /* prevent extra buffer shift after read */\n  dictSize = std::min(dictSize, reduceSize);\n  dictSize = std::max(dictSize, (size_t)FL2_DICTSIZE_MIN);\n  CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_dictionarySize, dictSize));\n  if (lzma2Props.lzmaProps.algo >= 0) {\n    CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_strategy, (unsigned)lzma2Props.lzmaProps.algo));\n  }\n  if (lzma2Props.lzmaProps.fb > 0)\n    CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_fastLength, lzma2Props.lzmaProps.fb));\n  if (lzma2Props.lzmaProps.mc > 0)\n    CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_hybridCycles, lzma2Props.lzmaProps.mc));\n  if (lzma2Props.lzmaProps.lc >= 0)\n    CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_literalCtxBits, lzma2Props.lzmaProps.lc));\n  if (lzma2Props.lzmaProps.lp >= 0)\n    CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_literalPosBits, lzma2Props.lzmaProps.lp));\n  if (lzma2Props.lzmaProps.pb >= 0)\n    CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_posBits, lzma2Props.lzmaProps.pb));\n  if (lzma2Props.blockSize == 0)\n    lzma2Props.blockSize = std::min(std::max((size_t)MIN_BLOCK_SIZE, dictSize * 4U), (size_t)MAX_BLOCK_SIZE);\n  else if (lzma2Props.blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)\n    lzma2Props.blockSize = 0;\n  unsigned r = 0;\n  if (lzma2Props.blockSize != 0) {\n    r = 1;\n    // Do not exceed the block size. TODO: the lib should support setting a value instead of a multiplier.\n    while (r < FL2_RESET_INTERVAL_MAX && (r + 1) * (UInt64)dictSize <= lzma2Props.blockSize)\n      ++r;\n  }\n  CHECK_P(FL2_CCtx_setParameter(fcs, FL2_p_resetInterval, r));\n  FL2_CCtx_setParameter(fcs, FL2_p_omitProperties, 1);\n  FL2_setCStreamTimeout(fcs, 500);\n  return S_OK;\n}\n\nsize_t CFastEncoder::FastLzma2::GetDictSize() const\n{\n  return FL2_CCtx_getParameter(fcs, FL2_p_dictionarySize);\n}\n\nHRESULT CFastEncoder::FastLzma2::Begin()\n{\n  CHECK_S(FL2_initCStream(fcs, 0));\n  CHECK_S(FL2_getDictionaryBuffer(fcs, &dict));\n  dict_pos = 0;\n  return S_OK;\n}\n\nBYTE* CFastEncoder::FastLzma2::GetAvailableBuffer(unsigned long& size)\n{\n  size = static_cast<unsigned long>(dict.size - dict_pos);\n  return reinterpret_cast<BYTE*>(dict.dst) + dict_pos;\n}\n\nHRESULT CFastEncoder::FastLzma2::WaitAndReport(size_t& res, ICompressProgressInfo *progress)\n{\n  while (FL2_isTimedOut(res)) {\n    if (!UpdateProgress(progress))\n      return S_FALSE;\n    res = FL2_waitCStream(fcs);\n  }\n  CHECK_S(res);\n  return S_OK;\n}\n\nHRESULT CFastEncoder::FastLzma2::AddByteCount(size_t count, ISequentialOutStream *outStream, ICompressProgressInfo *progress)\n{\n  dict_pos += count;\n  if (dict_pos == dict.size) {\n    size_t res = FL2_updateDictionary(fcs, dict_pos);\n    CHECK_H(WaitAndReport(res, progress));\n    if (res != 0)\n      CHECK_H(WriteBuffers(outStream));\n    res = FL2_getDictionaryBuffer(fcs, &dict);\n    while (FL2_isTimedOut(res)) {\n      if (!UpdateProgress(progress))\n        return S_FALSE;\n      res = FL2_getDictionaryBuffer(fcs, &dict);\n    }\n    CHECK_S(res);\n    dict_pos = 0;\n  }\n  if (!UpdateProgress(progress))\n    return S_FALSE;\n  return S_OK;\n}\n\nbool CFastEncoder::FastLzma2::UpdateProgress(ICompressProgressInfo *progress)\n{\n  if (progress) {\n    UInt64 outProcessed;\n    UInt64 inProcessed = FL2_getCStreamProgress(fcs, &outProcessed);\n    HRESULT err = progress->SetRatioInfo(&inProcessed, &outProcessed);\n    if (err != S_OK) {\n      FL2_cancelCStream(fcs);\n      return false;\n    }\n  }\n  return true;\n}\n\nHRESULT CFastEncoder::FastLzma2::WriteBuffers(ISequentialOutStream *outStream)\n{\n  size_t csize;\n  for (;;) {\n    FL2_cBuffer cbuf;\n    do {\n      csize = FL2_getNextCompressedBuffer(fcs, &cbuf);\n    } while (FL2_isTimedOut(csize));\n    CHECK_S(csize);\n    if (csize == 0)\n      break;\n    HRESULT err = WriteStream(outStream, cbuf.src, cbuf.size);\n    if (err != S_OK)\n      return err;\n  }\n  return S_OK;\n}\n\nHRESULT CFastEncoder::FastLzma2::End(ISequentialOutStream *outStream, ICompressProgressInfo *progress)\n{\n  if (dict_pos) {\n    size_t res = FL2_updateDictionary(fcs, dict_pos);\n    CHECK_H(WaitAndReport(res, progress));\n  }\n\n  size_t res = FL2_endStream(fcs, nullptr);\n  CHECK_H(WaitAndReport(res, progress));\n  while (res) {\n    CHECK_H(WriteBuffers(outStream));\n    res = FL2_endStream(fcs, nullptr);\n    CHECK_H(WaitAndReport(res, progress));\n  }\n  return S_OK;\n}\n\nvoid CFastEncoder::FastLzma2::Cancel()\n{\n  FL2_cancelCStream(fcs);\n}\n\nZ7_COM7F_IMF(CFastEncoder::SetCoderProperties(const PROPID *propIDs,\n  const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  return _encoder.SetCoderProperties(propIDs, coderProps, numProps);\n}\n\n#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))\nZ7_COM7F_IMF(CFastEncoder::WriteCoderProperties(ISequentialOutStream *outStream))\n{\n  Byte prop;\n  unsigned i;\n  size_t dictSize = _encoder.GetDictSize();\n  for (i = 0; i < 40; i++)\n    if (dictSize <= LZMA2_DIC_SIZE_FROM_PROP(i))\n      break;\n  prop = (Byte)i;\n  return WriteStream(outStream, &prop, 1);\n}\n\n\nZ7_COM7F_IMF(CFastEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n  const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))\n{\n  CHECK_H(_encoder.Begin());\n  size_t inSize;\n  unsigned long dSize;\n  do\n  {\n    BYTE* dict = _encoder.GetAvailableBuffer(dSize);\n\n    inSize = dSize;\n    HRESULT err = ReadStream(inStream, dict, &inSize);\n    if (err != S_OK) {\n      _encoder.Cancel();\n      return err;\n    }\n    CHECK_H(_encoder.AddByteCount(inSize, outStream, progress));\n\n  } while (inSize == dSize);\n\n  CHECK_H(_encoder.End(outStream, progress));\n\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/FastLzma2Encoder.h",
    "content": "﻿// FastLzma2Encoder.h\n\n#ifndef __FASTLZMA2_ENCODER_H\n#define __FASTLZMA2_ENCODER_H\n\n#include \"../../SevenZip/C/Lzma2Enc.h\"\n#include <fast-lzma2.h>\n\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/Common/MyBuffer.h\"\n\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n\nnamespace NCompress {\nnamespace NLzma2 {\n\nclass CFastEncoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetCoderProperties,\n  public ICompressWriteCoderProperties,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_3(\n      ICompressCoder,\n      ICompressSetCoderProperties,\n      ICompressWriteCoderProperties)\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetCoderProperties)\n  Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties)\n\npublic:\n  class FastLzma2\n  {\n  public:\n    FastLzma2();\n    ~FastLzma2();\n    HRESULT SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\n    size_t GetDictSize() const;\n    HRESULT Begin();\n    BYTE* GetAvailableBuffer(unsigned long& size);\n    HRESULT AddByteCount(size_t count, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n    HRESULT End(ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n    void Cancel();\n\n  private:\n    bool UpdateProgress(ICompressProgressInfo *progress);\n    HRESULT WaitAndReport(size_t& res, ICompressProgressInfo *progress);\n    HRESULT WriteBuffers(ISequentialOutStream *outStream);\n\n    FL2_CStream* fcs;\n    FL2_dictBuffer dict;\n    size_t dict_pos;\n\n    FastLzma2(const FastLzma2&) = delete;\n    FastLzma2& operator=(const FastLzma2&) = delete;\n  };\n\n  FastLzma2 _encoder;\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/FastLzma2Register.cpp",
    "content": "﻿// FastLzma2Register.cpp\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n\n#include \"../../SevenZip/CPP/7zip/Compress/Lzma2Decoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"FastLzma2Encoder.h\"\n#endif\n\nREGISTER_CODEC_E(\n  FLZMA2,\n  NCompress::NLzma2::CDecoder(),\n  NCompress::NLzma2::CFastEncoder(),\n  0x21,\n  \"FLZMA2\")\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/LizardDecoder.cpp",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"LizardDecoder.h\"\n\nnamespace NCompress {\nnamespace NLIZARD {\n\nCDecoder::CDecoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors())\n{\n  _props.clear();\n}\n\nCDecoder::~CDecoder()\n{\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte * prop, UInt32 size))\n{\n  DProps *pProps = (DProps *)prop;\n\n  if (size > 5)\n    return E_NOTIMPL;\n\n  memcpy(&_props, pProps, sizeof (DProps));\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = LIZARDMT_THREAD_MAX;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\nHRESULT CDecoder::SetOutStreamSizeResume(const UInt64 * /*outSize*/)\n{\n  _processedOut = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 * outSize))\n{\n  _processedIn = 0;\n  RINOK(SetOutStreamSizeResume(outSize));\n  return S_OK;\n}\n\nHRESULT CDecoder::CodeSpec(ISequentialInStream * inStream,\n  ISequentialOutStream * outStream, ICompressProgressInfo * progress)\n{\n  NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n  Context.InputStream = inStream;\n  Context.OutputStream = outStream;\n  Context.Progress = progress;\n  Context.ProcessedInputSize = &_processedIn;\n  Context.ProcessedOutputSize = &_processedOut;\n  return ::NanaZipCodecsLizardDecode(&Context, _numThreads, _inputSize);\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream * inStream, ISequentialOutStream * outStream,\n  const UInt64 * /*inSize */, const UInt64 *outSize, ICompressProgressInfo * progress))\n{\n  SetOutStreamSize(outSize);\n  return CodeSpec(inStream, outStream, progress);\n}\n\n#ifndef Z7_NO_READ_FROM_CODER\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream * inStream))\n{\n  _inStream = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n{\n  _inStream.Release();\n  return S_OK;\n}\n#endif\n\nHRESULT CDecoder::CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress)\n{\n  RINOK(SetOutStreamSizeResume(outSize));\n  return CodeSpec(_inStream, outStream, progress);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/LizardDecoder.h",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#define LIZARD_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <lizard_compress.h>\n#include <lizard_decompress.h>\n#include <lizard_frame.h>\n\n#include \"../../SevenZip/CPP/Windows/System.h\"\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n#include \"../../SevenZip/CPP/7zip/Common/ProgressMt.h\"\n\n#include <NanaZip.Codecs.MultiThreadWrapper.Lizard.h>\n\nnamespace NCompress {\nnamespace NLIZARD {\n\nstruct DProps\n{\n  DProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = LIZARD_VERSION_MAJOR;\n    _ver_minor = LIZARD_VERSION_MINOR;\n    _level = 1;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n};\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetCoderMt,\n  public CMyUnknownImp\n{\n  CMyComPtr < ISequentialInStream > _inStream;\n\npublic:\n  DProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n  HRESULT CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress);\n  HRESULT SetOutStreamSizeResume(const UInt64 *outSize);\n\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n#ifndef Z7_NO_READ_FROM_CODER\n  //Z7_COM_QI_ENTRY(ICompressSetInStream)\n#endif\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n  Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize));\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM7F_IMF(SetInStream(ISequentialInStream *inStream));\n  Z7_COM7F_IMF(ReleaseInStream());\n  UInt64 GetInputProcessedSize() const { return _processedIn; }\n#endif\n\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/LizardEncoder.cpp",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"LizardEncoder.h\"\n#include \"LizardDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NLIZARD {\n\nCEncoder::CEncoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors()),\n  _ctx(NULL)\n{\n  _props.clear();\n}\n\nCEncoder::~CEncoder()\n{\n  if (_ctx)\n    LIZARDMT_freeCCtx(_ctx);\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID * propIDs, const PROPVARIANT * coderProps, UInt32 numProps))\n{\n  _props.clear();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT & prop = coderProps[i];\n    PROPID propID = propIDs[i];\n    UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n    case NCoderPropID::kLevel:\n      {\n        if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n\n        /* level 1..22 */\n        _props._level = static_cast < Byte > (prop.ulVal);\n        Byte mylevel = static_cast < Byte > (LIZARDMT_LEVEL_MAX);\n        if (_props._level > mylevel)\n          _props._level = mylevel;\n\n        break;\n      }\n    case NCoderPropID::kNumThreads:\n      {\n        SetNumberOfThreads(v);\n        break;\n      }\n    default:\n      {\n        break;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream * outStream))\n{\n  return WriteStream(outStream, &_props, sizeof (_props));\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream,\n  ISequentialOutStream *outStream, const UInt64 * /*inSize*/ ,\n  const UInt64 * /*outSize */, ICompressProgressInfo *progress))\n{\n  LIZARDMT_RdWr_t rdwr;\n  size_t result;\n  HRESULT res = S_OK;\n\n  NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n  Context.InputStream = inStream;\n  Context.OutputStream = outStream;\n  Context.Progress = progress;\n  Context.ProcessedInputSize = &_processedIn;\n  Context.ProcessedOutputSize = &_processedOut;\n\n  /* 1) setup read/write functions */\n  rdwr.fn_read = ::NanaZipCodecsLizardRead;\n  rdwr.fn_write = ::NanaZipCodecsLizardWrite;\n  rdwr.arg_read = reinterpret_cast<void*>(&Context);\n  rdwr.arg_write = reinterpret_cast<void*>(&Context);\n\n  /* 2) create compression context, if needed */\n  if (!_ctx)\n    _ctx = LIZARDMT_createCCtx(_numThreads, _props._level, _inputSize);\n  if (!_ctx)\n    return S_FALSE;\n\n  /* 3) compress */\n  result = LIZARDMT_compressCCtx(_ctx, &rdwr);\n  if (LIZARDMT_isError(result)) {\n    if (result == (size_t)-LIZARDMT_error_canceled)\n      return E_ABORT;\n    return E_FAIL;\n  }\n\n  return res;\n}\n\nZ7_COM7F_IMF(CEncoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = LIZARDMT_THREAD_MAX;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/LizardEncoder.h",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#define LIZARD_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <lizard_compress.h>\n#include <lizard_frame.h>\n#include <lizard-mt.h>\n\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NLIZARD {\n\nstruct CProps\n{\n  CProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = LIZARD_VERSION_MAJOR;\n    _ver_minor = LIZARD_VERSION_MINOR;\n    _level = LIZARDMT_LEVEL_MIN;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n};\n\nZ7_CLASS_IMP_COM_4(\n  CEncoder,\n  ICompressCoder,\n  ICompressSetCoderMt,\n  ICompressSetCoderProperties,\n  ICompressWriteCoderProperties\n)\npublic:\n  CProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  LIZARDMT_CCtx *_ctx;\n\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/LizardHandler.cpp",
    "content": "﻿// LizardHandler.cpp\n\n#include \"../../SevenZip/CPP/7zip/Archive/StdAfx.h\"\n\n#include \"../../SevenZip/C/CpuArch.h\"\n#include \"../../SevenZip/CPP/Common/ComTry.h\"\n#include \"../../SevenZip/CPP/Common/Defs.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/ProgressUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterArc.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#include \"LizardDecoder.h\"\n#include \"LizardEncoder.h\"\n#include \"../../SevenZip/CPP/7zip/Compress/CopyCoder.h\"\n\n#include \"../../SevenZip/CPP/7zip/Archive/Common/DummyOutStream.h\"\n#include \"../../SevenZip/CPP/7zip/Archive/Common/HandlerOut.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NLIZARD {\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n  IArchiveOpenSeq,\n  IOutArchive,\n  ISetProperties\n)\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  bool _isArc;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize;\n\n  CSingleMethodProps _props;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams,\n  kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID /*propID*/, PROPVARIANT * /*value*/))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nstatic const unsigned kSignatureCheckSize = 4;\n\nAPI_FUNC_static_IsArc IsArc_lizard(const Byte *p, size_t size)\n{\n  if (size < 4)\n    return k_IsArc_Res_NEED_MORE;\n\n  UInt32 magic = GetUi32(p);\n\n  // skippable frames\n  if (magic >= 0x184D2A50 && magic <= 0x184D2A5F) {\n    if (size < 16)\n      return k_IsArc_Res_NEED_MORE;\n    magic = GetUi32(p+12);\n  }\n\n  // Lizard Magic\n  if (magic == 0x184D2206)\n    return k_IsArc_Res_YES;\n\n  return k_IsArc_Res_NO;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    Byte buf[kSignatureCheckSize];\n    RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize));\n    if (IsArc_lizard(buf, kSignatureCheckSize) == k_IsArc_Res_NO)\n      return S_FALSE;\n    _isArc = true;\n    _stream = stream;\n    _seqStream = stream;\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n\n  _packSize = 0;\n\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    extractCallback->SetTotal(_packSize);\n\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  extractCallback->PrepareOperation(askMode);\n\n  Int32 opRes;\n\n  {\n\n  NCompress::NLIZARD::CDecoder *decoderSpec = new NCompress::NLIZARD::CDecoder;\n  CMyComPtr<ICompressCoder> decoder = decoderSpec;\n  decoderSpec->SetInStream(_seqStream);\n\n  CDummyOutStream *outStreamSpec = new CDummyOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n  outStreamSpec->SetStream(realOutStream);\n  outStreamSpec->Init();\n\n  realOutStream.Release();\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, true);\n\n  UInt64 packSize = 0;\n  UInt64 unpackedSize = 0;\n\n  HRESULT result = S_OK;\n\n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackedSize;\n\n    RINOK(lps->SetCur());\n    result = decoderSpec->CodeResume(outStream, &unpackedSize, progress);\n    UInt64 streamSize = decoderSpec->GetInputProcessedSize();\n\n    if (result != S_FALSE && result != S_OK)\n      return result;\n\n    if (unpackedSize == 0)\n      break;\n\n    if (streamSize == packSize)\n    {\n      // no new bytes in input stream, So it's good end of archive.\n      result = S_OK;\n      break;\n    }\n\n    if (packSize > streamSize)\n      return E_FAIL;\n\n    if (result != S_OK)\n      break;\n  }\n\n  decoderSpec->ReleaseInStream();\n  outStream.Release();\n\n  if (!_isArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (_dataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK) {\n    _unpackSize = outStreamSpec->GetSize();\n    _unpackSize_Defined = true;\n    opRes = NExtract::NOperationResult::kOK;\n  } else\n    return result;\n\n  }\n\n  return extractCallback->SetOperationResult(opRes);\n\n  COM_TRY_END\n}\n\nstatic HRESULT UpdateArchive(\n    UInt64 unpackSize,\n    ISequentialOutStream *outStream,\n    const CProps &props,\n    IArchiveUpdateCallback *updateCallback)\n{\n  RINOK(updateCallback->SetTotal(unpackSize));\n  CMyComPtr<ISequentialInStream> fileInStream;\n  RINOK(updateCallback->GetStream(0, &fileInStream));\n  CLocalProgress *localProgressSpec = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;\n  localProgressSpec->Init(updateCallback, true);\n  NCompress::NLIZARD::CEncoder *encoderSpec = new NCompress::NLIZARD::CEncoder;\n  CMyComPtr<ICompressCoder> encoder = encoderSpec;\n  RINOK(props.SetCoderProps(encoderSpec, NULL));\n  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));\n  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  *type = NFileTimeType::kUnix;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\n \n  if ((newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n  \n  if ((newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n    return UpdateArchive(size, outStream, _props, updateCallback);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(updateCallback, true);\n\n  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;\n  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, 0,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  if (_stream)\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n\n  return NCompress::CopyStream(_stream, outStream, progress);\n\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  return _props.SetProperties(names, values, numProps);\n}\n\nstatic const Byte k_Signature[] = \"0x184D2206\";\n\nREGISTER_ARC_IO(\n  \"lizard\", \"liz tliz\", \"* .tar\", 0x11,\n  k_Signature,\n  0,\n  NArcInfoFlags::kKeepName,\n  0,\n  IsArc_lizard)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/LizardRegister.cpp",
    "content": "﻿// (C) 2017 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n\n#include \"LizardDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"LizardEncoder.h\"\n#endif\n\nREGISTER_CODEC_E(\n  LIZARD,\n  NCompress::NLIZARD::CDecoder(),\n  NCompress::NLIZARD::CEncoder(),\n  0x4F71106, \"LIZARD\")\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz4Decoder.cpp",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"Lz4Decoder.h\"\n\nnamespace NCompress {\nnamespace NLZ4 {\n\nCDecoder::CDecoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors())\n{\n  _props.clear();\n}\n\nCDecoder::~CDecoder()\n{\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte * prop, UInt32 size))\n{\n  DProps *pProps = (DProps *)prop;\n\n  if (size > 5)\n    return E_NOTIMPL;\n\n  memcpy(&_props, pProps, sizeof (DProps));\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = LZ4MT_THREAD_MAX;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\nHRESULT CDecoder::SetOutStreamSizeResume(const UInt64 * /*outSize*/)\n{\n  _processedOut = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 * outSize))\n{\n  _processedIn = 0;\n  RINOK(SetOutStreamSizeResume(outSize))\n  return S_OK;\n}\n\nHRESULT CDecoder::CodeSpec(ISequentialInStream * inStream,\n  ISequentialOutStream * outStream, ICompressProgressInfo * progress)\n{\n  NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n  Context.InputStream = inStream;\n  Context.OutputStream = outStream;\n  Context.Progress = progress;\n  Context.ProcessedInputSize = &_processedIn;\n  Context.ProcessedOutputSize = &_processedOut;\n  return ::NanaZipCodecsLz4Decode(&Context, _numThreads, _inputSize);\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream * inStream, ISequentialOutStream * outStream,\n  const UInt64 * /*inSize */, const UInt64 *outSize, ICompressProgressInfo * progress))\n{\n  SetOutStreamSize(outSize);\n  return CodeSpec(inStream, outStream, progress);\n}\n\n#ifndef Z7_NO_READ_FROM_CODER\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream * inStream))\n{\n  _inStream = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n{\n  _inStream.Release();\n  return S_OK;\n}\n#endif\n\nHRESULT CDecoder::CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress)\n{\n  RINOK(SetOutStreamSizeResume(outSize))\n  return CodeSpec(_inStream, outStream, progress);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz4Decoder.h",
    "content": "﻿// (C) 2016 - 2017 Tino Reichardt\n\n#define LZ4_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <lz4.h>\n\n#include \"../../SevenZip/CPP/Windows/System.h\"\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n#include \"../../SevenZip/CPP/7zip/Common/ProgressMt.h\"\n\n#include <NanaZip.Codecs.MultiThreadWrapper.LZ4.h>\n\nnamespace NCompress {\nnamespace NLZ4 {\n\nstruct DProps\n{\n  DProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = LZ4_VERSION_MAJOR;\n    _ver_minor = LZ4_VERSION_MINOR;\n    _level = 1;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n  Byte _reserved[2];\n};\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetCoderMt,\n  public CMyUnknownImp\n{\n  CMyComPtr < ISequentialInStream > _inStream;\n\npublic:\n  DProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n  HRESULT CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress);\n  HRESULT SetOutStreamSizeResume(const UInt64 *outSize);\n\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n  Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize));\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM7F_IMF(SetInStream(ISequentialInStream *inStream));\n  Z7_COM7F_IMF(ReleaseInStream());\n  UInt64 GetInputProcessedSize() const { return _processedIn; }\n#endif\n\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz4Encoder.cpp",
    "content": "﻿// (C) 2016 - 2020 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"Lz4Encoder.h\"\n#include \"Lz4Decoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NLZ4 {\n\nCEncoder::CEncoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(1),\n  _ctx(NULL)\n{\n  _props.clear();\n}\n\nCEncoder::~CEncoder()\n{\n  if (_ctx)\n    LZ4MT_freeCCtx(_ctx);\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID * propIDs, const PROPVARIANT * coderProps, UInt32 numProps))\n{\n  _props.clear();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT & prop = coderProps[i];\n    PROPID propID = propIDs[i];\n    UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n    case NCoderPropID::kLevel:\n      {\n        if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n\n        _props._level = static_cast < Byte > (prop.ulVal);\n        Byte mylevel = static_cast < Byte > (LZ4MT_LEVEL_MAX);\n        if (_props._level > mylevel)\n          _props._level = mylevel;\n\n        break;\n      }\n    case NCoderPropID::kNumThreads:\n      {\n        SetNumberOfThreads(v);\n        break;\n      }\n    default:\n      {\n        break;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream * outStream))\n{\n  return WriteStream(outStream, &_props, sizeof (_props));\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream,\n  ISequentialOutStream *outStream, const UInt64 * /*inSize*/ ,\n  const UInt64 * /*outSize */, ICompressProgressInfo *progress))\n{\n  LZ4MT_RdWr_t rdwr;\n  size_t result;\n  HRESULT res = S_OK;\n\n  NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n  Context.InputStream = inStream;\n  Context.OutputStream = outStream;\n  Context.Progress = progress;\n  Context.ProcessedInputSize = &_processedIn;\n  Context.ProcessedOutputSize = &_processedOut;\n\n  /* 1) setup read/write functions */\n  rdwr.fn_read = ::NanaZipCodecsLz4Read;\n  rdwr.fn_write = ::NanaZipCodecsLz4Write;\n  rdwr.arg_read = reinterpret_cast<void*>(&Context);\n  rdwr.arg_write = reinterpret_cast<void*>(&Context);\n\n  /* 2) create compression context, if needed */\n  if (!_ctx)\n    _ctx = LZ4MT_createCCtx(_numThreads, _props._level, _inputSize);\n  if (!_ctx)\n    return S_FALSE;\n\n  /* 3) compress */\n  result = LZ4MT_compressCCtx(_ctx, &rdwr);\n  if (LZ4MT_isError(result)) {\n    if (result == (size_t)-LZ4MT_error_canceled)\n      return E_ABORT;\n    return E_FAIL;\n  }\n\n  return res;\n}\n\nZ7_COM7F_IMF(CEncoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = LZ4MT_THREAD_MAX;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz4Encoder.h",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#define LZ4_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <lz4.h>\n#include <lz4-mt.h>\n\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NLZ4 {\n\nstruct CProps\n{\n  CProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = LZ4_VERSION_MAJOR;\n    _ver_minor = LZ4_VERSION_MINOR;\n    _level = 3;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n  Byte _reserved[2];\n};\n\nZ7_CLASS_IMP_COM_4(\n  CEncoder,\n  ICompressCoder,\n  ICompressSetCoderMt,\n  ICompressSetCoderProperties,\n  ICompressWriteCoderProperties\n)\npublic:\n  CProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  LZ4MT_CCtx *_ctx;\n\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz4Handler.cpp",
    "content": "﻿// Lz4Handler.cpp\n\n#include \"../../SevenZip/CPP/7zip/Archive/StdAfx.h\"\n\n#include \"../../SevenZip/C/CpuArch.h\"\n#include \"../../SevenZip/CPP/Common/ComTry.h\"\n#include \"../../SevenZip/CPP/Common/Defs.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/ProgressUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterArc.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#include \"Lz4Decoder.h\"\n#include \"Lz4Encoder.h\"\n#include \"../../SevenZip/CPP/7zip/Compress/CopyCoder.h\"\n\n#include \"../../SevenZip/CPP/7zip/Archive/Common/DummyOutStream.h\"\n#include \"../../SevenZip/CPP/7zip/Archive/Common/HandlerOut.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NLZ4 {\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n  IArchiveOpenSeq,\n  IOutArchive,\n  ISetProperties\n)\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  bool _isArc;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize;\n\n  CSingleMethodProps _props;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams,\n  kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID /*propID*/, PROPVARIANT * /*value*/))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nstatic const unsigned kSignatureCheckSize = 4;\n\nAPI_FUNC_static_IsArc IsArc_lz4(const Byte *p, size_t size)\n{\n  if (size < 4)\n    return k_IsArc_Res_NEED_MORE;\n\n  UInt32 magic = GetUi32(p);\n\n  // skippable frames\n  if (magic >= 0x184D2A50 && magic <= 0x184D2A5F) {\n    if (size < 16)\n      return k_IsArc_Res_NEED_MORE;\n    magic = GetUi32(p+12);\n  }\n\n  // lz4 magic\n  if (magic == 0x184D2204)\n    return k_IsArc_Res_YES;\n\n  return k_IsArc_Res_NO;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    Byte buf[kSignatureCheckSize];\n    RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize));\n    if (IsArc_lz4(buf, kSignatureCheckSize) == k_IsArc_Res_NO)\n      return S_FALSE;\n    _isArc = true;\n    _stream = stream;\n    _seqStream = stream;\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n\n  _packSize = 0;\n\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    extractCallback->SetTotal(_packSize);\n\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  extractCallback->PrepareOperation(askMode);\n\n  Int32 opRes;\n\n  {\n\n  NCompress::NLZ4::CDecoder *decoderSpec = new NCompress::NLZ4::CDecoder;\n  CMyComPtr<ICompressCoder> decoder = decoderSpec;\n  decoderSpec->SetInStream(_seqStream);\n\n  CDummyOutStream *outStreamSpec = new CDummyOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n  outStreamSpec->SetStream(realOutStream);\n  outStreamSpec->Init();\n\n  realOutStream.Release();\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, true);\n\n  UInt64 packSize = 0;\n  UInt64 unpackedSize = 0;\n\n  HRESULT result = S_OK;\n\n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackedSize;\n\n    RINOK(lps->SetCur());\n    result = decoderSpec->CodeResume(outStream, &unpackedSize, progress);\n    UInt64 streamSize = decoderSpec->GetInputProcessedSize();\n\n    if (result != S_FALSE && result != S_OK)\n      return result;\n\n    if (unpackedSize == 0)\n      break;\n\n    if (streamSize == packSize)\n    {\n      // no new bytes in input stream, So it's good end of archive.\n      result = S_OK;\n      break;\n    }\n\n    if (packSize > streamSize)\n      return E_FAIL;\n\n    if (result != S_OK)\n      break;\n  }\n\n  decoderSpec->ReleaseInStream();\n  outStream.Release();\n\n  if (!_isArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (_dataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK) {\n    _unpackSize = outStreamSpec->GetSize();\n    _unpackSize_Defined = true;\n    opRes = NExtract::NOperationResult::kOK;\n  } else\n    return result;\n\n  }\n\n  return extractCallback->SetOperationResult(opRes);\n\n  COM_TRY_END\n}\n\nstatic HRESULT UpdateArchive(\n    UInt64 unpackSize,\n    ISequentialOutStream *outStream,\n    const CProps &props,\n    IArchiveUpdateCallback *updateCallback)\n{\n  RINOK(updateCallback->SetTotal(unpackSize));\n  CMyComPtr<ISequentialInStream> fileInStream;\n  RINOK(updateCallback->GetStream(0, &fileInStream));\n  CLocalProgress *localProgressSpec = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;\n  localProgressSpec->Init(updateCallback, true);\n  NCompress::NLZ4::CEncoder *encoderSpec = new NCompress::NLZ4::CEncoder;\n  CMyComPtr<ICompressCoder> encoder = encoderSpec;\n  RINOK(props.SetCoderProps(encoderSpec, NULL));\n  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));\n  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  *type = NFileTimeType::kUnix;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\n \n  if ((newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n  \n  if ((newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n    return UpdateArchive(size, outStream, _props, updateCallback);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(updateCallback, true);\n\n  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;\n  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, 0,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  if (_stream)\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n\n  return NCompress::CopyStream(_stream, outStream, progress);\n\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  return _props.SetProperties(names, values, numProps);\n}\n\nstatic const Byte k_Signature[] = \"0x184D2204\";\n\nREGISTER_ARC_IO(\n  \"lz4\", \"lz4 tlz4\", \"* .tar\", 0x0f,\n  k_Signature,\n  0,\n  NArcInfoFlags::kKeepName,\n  0,\n  IsArc_lz4)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz4Register.cpp",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n\n#include \"Lz4Decoder.h\"\n#if !defined(Z7_EXTRACT_ONLY) && !defined(Z7_LZ4_EXTRACT_ONLY)\n#include \"Lz4Encoder.h\"\n#endif\n\nnamespace NCompress {\nnamespace NLZ4 {\n\nREGISTER_CODEC_E(\n  LZ4,\n  NCompress::NLZ4::CDecoder(),\n  NCompress::NLZ4::CEncoder(),\n  0x4F71104, \"LZ4\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz5Decoder.cpp",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"Lz5Decoder.h\"\n\nnamespace NCompress {\nnamespace NLZ5 {\n\nCDecoder::CDecoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors())\n{\n  _props.clear();\n}\n\nCDecoder::~CDecoder()\n{\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte * prop, UInt32 size))\n{\n  DProps *pProps = (DProps *)prop;\n\n  if (size > 5)\n    return E_NOTIMPL;\n\n  memcpy(&_props, pProps, sizeof (DProps));\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = LZ5MT_THREAD_MAX;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\nHRESULT CDecoder::SetOutStreamSizeResume(const UInt64 * /*outSize*/)\n{\n  _processedOut = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 * outSize))\n{\n  _processedIn = 0;\n  RINOK(SetOutStreamSizeResume(outSize));\n  return S_OK;\n}\n\nHRESULT CDecoder::CodeSpec(ISequentialInStream * inStream,\n  ISequentialOutStream * outStream, ICompressProgressInfo * progress)\n{\n  NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n  Context.InputStream = inStream;\n  Context.OutputStream = outStream;\n  Context.Progress = progress;\n  Context.ProcessedInputSize = &_processedIn;\n  Context.ProcessedOutputSize = &_processedOut;\n  return ::NanaZipCodecsLz5Decode(&Context, _numThreads, _inputSize);\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream * inStream, ISequentialOutStream * outStream,\n  const UInt64 * /*inSize */, const UInt64 *outSize, ICompressProgressInfo * progress))\n{\n  SetOutStreamSize(outSize);\n  return CodeSpec(inStream, outStream, progress);\n}\n\n#ifndef Z7_NO_READ_FROM_CODER\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream * inStream))\n{\n  _inStream = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n{\n  _inStream.Release();\n  return S_OK;\n}\n#endif\n\nHRESULT CDecoder::CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress)\n{\n  RINOK(SetOutStreamSizeResume(outSize));\n  return CodeSpec(_inStream, outStream, progress);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz5Decoder.h",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#define LZ5_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <lz5.h>\n\n#include \"../../SevenZip/CPP/Windows/System.h\"\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n#include \"../../SevenZip/CPP/7zip/Common/ProgressMt.h\"\n\n#include <NanaZip.Codecs.MultiThreadWrapper.LZ5.h>\n\nnamespace NCompress {\nnamespace NLZ5 {\n\nstruct DProps\n{\n  DProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = LZ5_VERSION_MAJOR;\n    _ver_minor = LZ5_VERSION_MINOR;\n    _level = 1;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n  Byte _reserved[2];\n};\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetCoderMt,\n  public CMyUnknownImp\n{\n  CMyComPtr < ISequentialInStream > _inStream;\n\npublic:\n  DProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n  HRESULT CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress);\n  HRESULT SetOutStreamSizeResume(const UInt64 *outSize);\n\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n#ifndef Z7_NO_READ_FROM_CODER\n  //Z7_COM_QI_ENTRY(ICompressSetInStream)\n#endif\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n  Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize));\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM7F_IMF(SetInStream(ISequentialInStream *inStream));\n  Z7_COM7F_IMF(ReleaseInStream());\n  UInt64 GetInputProcessedSize() const { return _processedIn; }\n#endif\n\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz5Encoder.cpp",
    "content": "﻿// (C) 2016 - 2020 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"Lz5Encoder.h\"\n#include \"Lz5Decoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NLZ5 {\n\nCEncoder::CEncoder():\n  _processedIn(0),\n  _processedOut(0),\n  _inputSize(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors()),\n  _ctx(NULL)\n{\n  _props.clear();\n}\n\nCEncoder::~CEncoder()\n{\n  if (_ctx)\n    LZ5MT_freeCCtx(_ctx);\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID * propIDs, const PROPVARIANT * coderProps, UInt32 numProps))\n{\n  _props.clear();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT & prop = coderProps[i];\n    PROPID propID = propIDs[i];\n    UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n    case NCoderPropID::kLevel:\n      {\n        if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n\n        _props._level = static_cast < Byte > (prop.ulVal);\n        Byte mylevel = static_cast < Byte > (LZ5MT_LEVEL_MAX);\n        if (_props._level > mylevel)\n          _props._level = mylevel;\n\n        break;\n      }\n    case NCoderPropID::kNumThreads:\n      {\n        SetNumberOfThreads(v);\n        break;\n      }\n    default:\n      {\n        break;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream * outStream))\n{\n  return WriteStream(outStream, &_props, sizeof (_props));\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream,\n  ISequentialOutStream *outStream, const UInt64 * /*inSize*/ ,\n  const UInt64 * /*outSize */, ICompressProgressInfo *progress))\n{\n  LZ5MT_RdWr_t rdwr;\n  size_t result;\n  HRESULT res = S_OK;\n\n  NANAZIP_CODECS_ZSTDMT_STREAM_CONTEXT Context = {};\n  Context.InputStream = inStream;\n  Context.OutputStream = outStream;\n  Context.Progress = progress;\n  Context.ProcessedInputSize = &_processedIn;\n  Context.ProcessedOutputSize = &_processedOut;\n\n  /* 1) setup read/write functions */\n  rdwr.fn_read = ::NanaZipCodecsLz5Read;\n  rdwr.fn_write = ::NanaZipCodecsLz5Write;\n  rdwr.arg_read = reinterpret_cast<void*>(&Context);\n  rdwr.arg_write = reinterpret_cast<void*>(&Context);\n\n  /* 2) create compression context, if needed */\n  if (!_ctx)\n    _ctx = LZ5MT_createCCtx(_numThreads, _props._level, _inputSize);\n  if (!_ctx)\n    return S_FALSE;\n\n  /* 3) compress */\n  result = LZ5MT_compressCCtx(_ctx, &rdwr);\n  if (LZ5MT_isError(result)) {\n    if (result == (size_t)-LZ5MT_error_canceled)\n      return E_ABORT;\n    return E_FAIL;\n  }\n\n  return res;\n}\n\nZ7_COM7F_IMF(CEncoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = LZ5MT_THREAD_MAX;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz5Encoder.h",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#define LZ5_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <lz5.h>\n#include <lz5-mt.h>\n\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NLZ5 {\n\nstruct CProps\n{\n  CProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = LZ5_VERSION_MAJOR;\n    _ver_minor = LZ5_VERSION_MINOR;\n    _level = 3;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n  Byte _reserved[2];\n};\n\nZ7_CLASS_IMP_COM_4(\n  CEncoder,\n  ICompressCoder,\n  ICompressSetCoderMt,\n  ICompressSetCoderProperties,\n  ICompressWriteCoderProperties\n)\npublic:\n  CProps _props;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _inputSize;\n  UInt32 _numThreads;\n\n  LZ5MT_CCtx *_ctx;\n\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz5Handler.cpp",
    "content": "﻿// Lz5Handler.cpp\n\n#include \"../../SevenZip/CPP/7zip/Archive/StdAfx.h\"\n\n#include \"../../SevenZip/C/CpuArch.h\"\n#include \"../../SevenZip/CPP/Common/ComTry.h\"\n#include \"../../SevenZip/CPP/Common/Defs.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/ProgressUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterArc.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#include \"Lz5Decoder.h\"\n#include \"Lz5Encoder.h\"\n#include \"../../SevenZip/CPP/7zip/Compress/CopyCoder.h\"\n\n#include \"../../SevenZip/CPP/7zip/Archive/Common/DummyOutStream.h\"\n#include \"../../SevenZip/CPP/7zip/Archive/Common/HandlerOut.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NLZ5 {\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n  IArchiveOpenSeq,\n  IOutArchive,\n  ISetProperties\n)\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  bool _isArc;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize;\n\n  CSingleMethodProps _props;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams,\n  kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID /*propID*/, PROPVARIANT * /*value*/))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nstatic const unsigned kSignatureCheckSize = 4;\n\nAPI_FUNC_static_IsArc IsArc_lz5(const Byte *p, size_t size)\n{\n  if (size < 4)\n    return k_IsArc_Res_NEED_MORE;\n\n  UInt32 magic = GetUi32(p);\n\n  // skippable frames\n  if (magic >= 0x184D2A50 && magic <= 0x184D2A5F) {\n    if (size < 16)\n      return k_IsArc_Res_NEED_MORE;\n    magic = GetUi32(p+12);\n  }\n\n  // Lz5 Magic\n  if (magic == 0x184D2205)\n    return k_IsArc_Res_YES;\n\n  return k_IsArc_Res_NO;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    Byte buf[kSignatureCheckSize];\n    RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize));\n    if (IsArc_lz5(buf, kSignatureCheckSize) == k_IsArc_Res_NO)\n      return S_FALSE;\n    _isArc = true;\n    _stream = stream;\n    _seqStream = stream;\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n\n  _packSize = 0;\n\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    extractCallback->SetTotal(_packSize);\n\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  extractCallback->PrepareOperation(askMode);\n\n  Int32 opRes;\n\n  {\n\n  NCompress::NLZ5::CDecoder *decoderSpec = new NCompress::NLZ5::CDecoder;\n  CMyComPtr<ICompressCoder> decoder = decoderSpec;\n  decoderSpec->SetInStream(_seqStream);\n\n  CDummyOutStream *outStreamSpec = new CDummyOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n  outStreamSpec->SetStream(realOutStream);\n  outStreamSpec->Init();\n\n  realOutStream.Release();\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, true);\n\n  UInt64 packSize = 0;\n  UInt64 unpackedSize = 0;\n\n  HRESULT result = S_OK;\n\n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackedSize;\n\n    RINOK(lps->SetCur());\n    result = decoderSpec->CodeResume(outStream, &unpackedSize, progress);\n    UInt64 streamSize = decoderSpec->GetInputProcessedSize();\n\n    if (result != S_FALSE && result != S_OK)\n      return result;\n\n    if (unpackedSize == 0)\n      break;\n\n    if (streamSize == packSize)\n    {\n      // no new bytes in input stream, So it's good end of archive.\n      result = S_OK;\n      break;\n    }\n\n    if (packSize > streamSize)\n      return E_FAIL;\n\n    if (result != S_OK)\n      break;\n  }\n\n  decoderSpec->ReleaseInStream();\n  outStream.Release();\n\n  if (!_isArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (_dataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK) {\n    _unpackSize = outStreamSpec->GetSize();\n    _unpackSize_Defined = true;\n    opRes = NExtract::NOperationResult::kOK;\n  } else\n    return result;\n\n  }\n\n  return extractCallback->SetOperationResult(opRes);\n\n  COM_TRY_END\n}\n\nstatic HRESULT UpdateArchive(\n    UInt64 unpackSize,\n    ISequentialOutStream *outStream,\n    const CProps &props,\n    IArchiveUpdateCallback *updateCallback)\n{\n  RINOK(updateCallback->SetTotal(unpackSize));\n  CMyComPtr<ISequentialInStream> fileInStream;\n  RINOK(updateCallback->GetStream(0, &fileInStream));\n  CLocalProgress *localProgressSpec = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;\n  localProgressSpec->Init(updateCallback, true);\n  NCompress::NLZ5::CEncoder *encoderSpec = new NCompress::NLZ5::CEncoder;\n  CMyComPtr<ICompressCoder> encoder = encoderSpec;\n  RINOK(props.SetCoderProps(encoderSpec, NULL));\n  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));\n  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  *type = NFileTimeType::kUnix;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\n \n  if ((newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n  \n  if ((newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n    return UpdateArchive(size, outStream, _props, updateCallback);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(updateCallback, true);\n\n  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;\n  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, 0,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  if (_stream)\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n\n  return NCompress::CopyStream(_stream, outStream, progress);\n\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  return _props.SetProperties(names, values, numProps);\n}\n\nstatic const Byte k_Signature[] = \"0x184D2205\";\n\nREGISTER_ARC_IO(\n  \"lz5\", \"lz5 tlz5\", \"* .tar\", 0x10,\n  k_Signature,\n  0,\n  NArcInfoFlags::kKeepName,\n  0,\n  IsArc_lz5)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/Lz5Register.cpp",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n\n#include \"Lz5Decoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"Lz5Encoder.h\"\n#endif\n\nREGISTER_CODEC_E(\n  LZ5,\n  NCompress::NLZ5::CDecoder(),\n  NCompress::NLZ5::CEncoder(),\n  0x4F71105, \"LZ5\")\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/LzHandler.cpp",
    "content": "﻿// LzHandler.cpp\n\n#include \"../../SevenZip/CPP/7zip/Archive/StdAfx.h\"\n\n#include \"../../SevenZip/C/CpuArch.h\"\n\n#include \"../../SevenZip/CPP/Common/ComTry.h\"\n#include \"../../SevenZip/CPP/Common/IntToString.h\"\n\n#include \"../../SevenZip/CPP/Windows/PropVariant.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/ProgressUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterArc.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#include \"../../SevenZip/CPP/7zip/Compress/LzmaDecoder.h\"\n\n#include \"../../SevenZip/CPP/7zip/Archive/Common/OutStreamWithCRC.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NLz {\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize,\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams\n};\n\nstatic const Byte k_Signature[5] = { 'L', 'Z', 'I', 'P', 1 };\nenum { k_SignatureSize = 5 };\n\nstruct CHeader\n{\n  Byte data[6];\t\t// 0-3 magic bytes, 4 version, 5 coded_dict_size\n  enum { size = 6 };\n  enum { min_dictionary_size = 1 << 12, max_dictionary_size = 1 << 29 };\n  unsigned DicSize;\n  Byte LzmaProps[5];\n\n  bool Parse();\n};\n\nstruct CTrailer\n{\n  Byte data[20];\t//  0-3  CRC32 of the uncompressed data\n\t\t\t//  4-11 size of the uncompressed data\n\t\t\t// 12-19 member size including header and trailer\n  enum { size = 20 };\n\n  unsigned data_crc() const\n    {\n    unsigned tmp = 0;\n    for( int i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; }\n    return tmp;\n    }\n\n  UInt64 data_size() const\n    {\n    UInt64 tmp = 0;\n    for( int i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; }\n    return tmp;\n    }\n\n  UInt64 member_size() const\n    {\n    UInt64 tmp = 0;\n    for( int i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; }\n    return tmp;\n    }\n};\n\nclass CDecoder\n{\n  CMyComPtr<ICompressCoder> _lzmaDecoder;\npublic:\n  NCompress::NLzma::CDecoder *_lzmaDecoderSpec;\n\n  ~CDecoder();\n  HRESULT Create(ISequentialInStream *inStream);\n\n  HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n\n  UInt64 GetInputProcessedSize() const { return _lzmaDecoderSpec->GetInputProcessedSize(); }\n\n  void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoderSpec->ReleaseInStream(); }\n\n  HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)\n    { return _lzmaDecoderSpec->ReadFromInputStream(data, size, processedSize); }\n};\n\nHRESULT CDecoder::Create(ISequentialInStream *inStream)\n{\n  if (!_lzmaDecoder)\n  {\n    _lzmaDecoderSpec = new NCompress::NLzma::CDecoder;\n    _lzmaDecoderSpec->FinishStream = true;\n    _lzmaDecoder = _lzmaDecoderSpec;\n  }\n\n  return _lzmaDecoderSpec->SetInStream(inStream);\n}\n\nCDecoder::~CDecoder()\n{\n  ReleaseInStream();\n}\n\nHRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,\n    ICompressProgressInfo *progress)\n{\n  {\n    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;\n    _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);\n    if (!setDecoderProperties)\n      return E_NOTIMPL;\n    RINOK(setDecoderProperties->SetDecoderProperties2(header.LzmaProps, 5));\n  }\n\n  RINOK(_lzmaDecoderSpec->CodeResume(outStream, NULL, progress));\n\n  return S_OK;\n}\n\n\n//  IInArchiveGetStream,\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IArchiveOpenSeq\n)\n  CHeader _header;\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  bool _isArc;\n  bool _needSeekToStart;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n  bool _numStreams_Defined;\n\n  bool _dataError;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize;\n  UInt64 _numStreams;\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n    case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;;\n      if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;\n      if (_dataError) v |= kpv_ErrorFlags_DataError;\n      prop = v;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nAPI_FUNC_static_IsArc IsArc_Lz(const Byte *p, size_t size)\n{\n  if (size < k_SignatureSize)\n    return k_IsArc_Res_NEED_MORE;\n  for( int i = 0; i < k_SignatureSize; ++i )\n    if( p[i] != k_Signature[i] )\n      return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\nbool CHeader::Parse()\n{\n  if (IsArc_Lz(data, k_SignatureSize) == k_IsArc_Res_NO)\n    return false;\n  DicSize = ( 1 << ( data[5] & 0x1F ) );\n  if( DicSize > min_dictionary_size )\n    DicSize -= ( DicSize / 16 ) * ( ( data[5] >> 5 ) & 7 );\n  LzmaProps[0] = 93;\t\t\t/* (45 * 2) + (9 * 0) + 3 */\n  unsigned ds = DicSize;\n  for( int i = 1; i <= 4; ++i ) { LzmaProps[i] = ds & 0xFF; ds >>= 8; }\n  return (DicSize >= min_dictionary_size && DicSize <= max_dictionary_size);\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *))\n{\n  Close();\n\n  RINOK(ReadStream_FALSE(inStream, _header.data, CHeader::size));\n\n  if (!_header.Parse())\n    return S_FALSE;\n\n  RINOK(inStream->Seek(0, STREAM_SEEK_END, &_packSize));\n  if (_packSize < 36)\n    return S_FALSE;\n  _isArc = true;\n  _stream = inStream;\n  _seqStream = inStream;\n  _needSeekToStart = true;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n  _numStreams_Defined = false;\n\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n  _dataError = false;\n\n  _packSize = 0;\n\n  _needSeekToStart = false;\n\n  _stream.Release();\n  _seqStream.Release();\n   return S_OK;\n}\n\nZ7_CLASS_IMP_COM_1(\n  CCompressProgressInfoImp,\n  ICompressProgressInfo\n)\n  CMyComPtr<IArchiveOpenCallback> Callback;\npublic:\n  UInt64 Offset;\n  void Init(IArchiveOpenCallback *callback) { Callback = callback; }\n};\n\nZ7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))\n{\n  if (Callback)\n  {\n    UInt64 files = 0;\n    UInt64 value = Offset + *inSize;\n    return Callback->SetCompleted(&files, &value);\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    extractCallback->SetTotal(_packSize);\n\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  extractCallback->PrepareOperation(askMode);\n\n  COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n  outStreamSpec->SetStream(realOutStream);\n  outStreamSpec->Init();\n  realOutStream.Release();\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, true);\n\n  if (_needSeekToStart)\n  {\n    if (!_stream)\n      return E_FAIL;\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n  }\n  else\n    _needSeekToStart = true;\n\n  CDecoder decoder;\n  HRESULT result = decoder.Create(_seqStream);\n  RINOK(result);\n\n  bool firstItem = true;\n\n  UInt64 packSize = 0;\n  UInt64 unpackSize = 0;\n  UInt64 numStreams = 0;\n\n  bool crcError = false;\n  bool dataAfterEnd = false;\n\n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackSize;\n    RINOK(lps->SetCur());\n\n    CHeader st;\n    UInt32 processed;\n    RINOK(decoder.ReadInput(st.data, CHeader::size, &processed));\n    if (processed != CHeader::size)\n    {\n      if (processed != 0)\n        dataAfterEnd = true;\n      break;\n    }\n\n    if (!st.Parse())\n    {\n      dataAfterEnd = true;\n      break;\n    }\n    numStreams++;\n    firstItem = false;\n    outStreamSpec->InitCRC();\n\n    result = decoder.Code(st, outStream, progress);\n\n    UInt64 member_size = decoder.GetInputProcessedSize() - packSize;\n    packSize += member_size;\n    UInt64 data_size = outStreamSpec->GetSize() - unpackSize;\n    unpackSize += data_size;\n\n    if (result == S_OK)\n    {\n      CTrailer trailer;\n      RINOK(decoder.ReadInput(trailer.data, CTrailer::size, &processed));\n      packSize += processed; member_size += processed;\n      if (processed != CTrailer::size ||\n          trailer.data_crc() != outStreamSpec->GetCRC() ||\n          trailer.data_size() != data_size ||\n          trailer.member_size() != member_size)\n      {\n        crcError = true;\n        result = S_FALSE;\n        break;\n      }\n    }\n    if (result == S_FALSE)\n      break;\n    RINOK(result);\n  }\n\n  if (firstItem)\n  {\n    _isArc = false;\n    result = S_FALSE;\n  }\n  else if (result == S_OK || result == S_FALSE)\n  {\n    if (dataAfterEnd)\n      _dataAfterEnd = true;\n    else if (decoder._lzmaDecoderSpec->NeedsMoreInput())\n      _needMoreInput = true;\n\n    _packSize = packSize;\n    _unpackSize = unpackSize;\n    _numStreams = numStreams;\n\n    _packSize_Defined = true;\n    _unpackSize_Defined = true;\n    _numStreams_Defined = true;\n  }\n\n  Int32 opResult = NExtract::NOperationResult::kOK;\n\n  if (!_isArc)\n    opResult = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opResult = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (crcError)\n    opResult = NExtract::NOperationResult::kCRCError;\n  else if (_dataAfterEnd)\n    opResult = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    opResult = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK) {\n    _unpackSize = outStreamSpec->GetSize();\n    _unpackSize_Defined = true;\n    opResult = NExtract::NOperationResult::kOK;\n  } else\n    return result;\n\n  outStream.Release();\n  return extractCallback->SetOperationResult(opResult);\n\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"lzip\", \"lz tlz\", \"* .tar\", 0x12,\n  k_Signature,\n  0,\n  NArcInfoFlags::kKeepName,\n  IsArc_Lz)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/ZstdDecoder.cpp",
    "content": "﻿// (C) 2016 - 2020 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"ZstdDecoder.h\"\n\nnamespace NCompress {\nnamespace NZSTD {\n\nCDecoder::CDecoder():\n  _ctx(NULL),\n  _srcBuf(NULL),\n  _dstBuf(NULL),\n  _srcBufSize(ZSTD_DStreamInSize()),\n  _dstBufSize(ZSTD_DStreamOutSize()),\n  _processedIn(0),\n  _processedOut(0)\n{\n  _props.clear();\n}\n\nCDecoder::~CDecoder()\n{\n  if (_ctx) {\n    ZSTD_freeDCtx(_ctx);\n    MyFree(_srcBuf);\n    MyFree(_dstBuf);\n  }\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte * prop, UInt32 size))\n{\n  switch (size) {\n  case 1:\n    _props._flags = *prop;\n    // flags currently unused, todo: maybe some handling is necessary if set to not 0\n    // if (_props._flags != 0) ...\n    return S_OK;\n  // for backwards compatibility only:\n  // size 3 or 5 was accepted in previous versions, so allow it here too\n  // (since the old props members _ver/_level seemed to be unused anyway)\n  case 3:\n  case 5:\n    return S_OK;\n  default:\n    return E_NOTIMPL;\n  }\n}\n\nHRESULT CDecoder::SetOutStreamSizeResume(const UInt64 * /*outSize*/)\n{\n  _processedOut = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 * outSize))\n{\n  _processedIn = 0;\n  RINOK(SetOutStreamSizeResume(outSize))\n  return S_OK;\n}\n\nHRESULT CDecoder::CodeSpec(ISequentialInStream * inStream,\n  ISequentialOutStream * outStream, ICompressProgressInfo * progress)\n{\n  size_t srcBufLen, result;\n  ZSTD_inBuffer zIn;\n  ZSTD_outBuffer zOut;\n\n  /* 1) create context */\n  if (!_ctx) {\n    _ctx = ZSTD_createDCtx();\n    if (!_ctx)\n      return E_OUTOFMEMORY;\n\n    _srcBuf = MyAlloc(_srcBufSize);\n    if (!_srcBuf)\n      return E_OUTOFMEMORY;\n\n    _dstBuf = MyAlloc(_dstBufSize);\n    if (!_dstBuf)\n      return E_OUTOFMEMORY;\n\n    result = ZSTD_DCtx_setParameter(_ctx, ZSTD_d_windowLogMax, ZSTD_WINDOWLOG_MAX);\n    if (ZSTD_isError(result))\n      return E_OUTOFMEMORY;\n  } else {\n    result = ZSTD_DCtx_reset(_ctx, ZSTD_reset_session_only);\n    if (ZSTD_isError(result))\n      return E_FAIL;\n  }\n\n  zOut.dst = _dstBuf;\n  srcBufLen = _srcBufSize;\n\n  /* read first input block */\n  RINOK(ReadStream(inStream, _srcBuf, &srcBufLen))\n  _processedIn += srcBufLen;\n\n  zIn.src = _srcBuf;\n  zIn.size = srcBufLen;\n  zIn.pos = 0;\n\n  /* Main decompression Loop */\n  for (;;) {\n    for (;;) {\n      /* decompress loop */\n      zOut.size = _dstBufSize;\n      zOut.pos = 0;\n\n      result = ZSTD_decompressStream(_ctx, &zOut, &zIn);\n      if (ZSTD_isError(result)) {\n        switch (ZSTD_getErrorCode(result)) {\n          /* @Igor: would be nice, if we have an API to store the errmsg */\n          case ZSTD_error_memory_allocation:\n            return E_OUTOFMEMORY;\n          case ZSTD_error_frameParameter_unsupported:\n          case ZSTD_error_parameter_unsupported:\n          case ZSTD_error_version_unsupported:\n            return E_NOTIMPL;\n          case ZSTD_error_frameParameter_windowTooLarge:\n          case ZSTD_error_parameter_outOfBound:\n            return E_INVALIDARG;\n          default:\n            return E_FAIL;\n        }\n      }\n\n      /* write decompressed result */\n      if (zOut.pos) {\n        RINOK(WriteStream(outStream, _dstBuf, zOut.pos))\n        _processedOut += zOut.pos;\n        if (progress)\n        {\n          RINOK(progress->SetRatioInfo(&_processedIn, &_processedOut))\n        }\n      }\n\n      /* finished with buffer */\n      if (zIn.pos == zIn.size)\n        break;\n\n      /* end of frame */\n      if (result == 0) {\n        result = ZSTD_DCtx_reset(_ctx, ZSTD_reset_session_only);\n        if (ZSTD_isError(result))\n          return E_FAIL;\n\n        /* end of frame, but more data */\n        if (zIn.pos < zIn.size)\n          continue;\n\n        /* read next input, or eof */\n        break;\n      }\n    } /* for() decompress */\n\n    /* read next input */\n    srcBufLen = _srcBufSize;\n    RINOK(ReadStream(inStream, _srcBuf, &srcBufLen))\n    _processedIn += srcBufLen;\n\n    /* finished */\n    if (srcBufLen == 0)\n      return S_OK;\n\n    zIn.size = srcBufLen;\n    zIn.pos = 0;\n  }\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream * inStream, ISequentialOutStream * outStream,\n  const UInt64 * /*inSize */, const UInt64 *outSize, ICompressProgressInfo * progress))\n{\n  SetOutStreamSize(outSize);\n  return CodeSpec(inStream, outStream, progress);\n}\n\n#ifndef Z7_NO_READ_FROM_CODER\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream * inStream))\n{\n  _inStream = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n{\n  _inStream.Release();\n  return S_OK;\n}\n#endif\n\nZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 /* numThreads */))\n{\n  return S_OK;\n}\n\nHRESULT CDecoder::CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress)\n{\n  RINOK(SetOutStreamSizeResume(outSize))\n  return CodeSpec(_inStream, outStream, progress);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/ZstdDecoder.h",
    "content": "﻿// (C) 2016 - 2018 Tino Reichardt\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include <zstd.h>\n#include <zstd_errors.h>\n\n#include \"../../SevenZip/CPP/Windows/System.h\"\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n#include \"../../SevenZip/CPP/7zip/Common/ProgressMt.h\"\n\n/**\n * possible return values @ 7zip:\n * S_OK / S_FALSE\n * E_NOTIMPL\n * E_NOINTERFACE\n * E_ABORT\n * E_FAIL\n * E_OUTOFMEMORY\n * E_INVALIDARG\n */\n\n#define ZSTD_LEVEL_MIN      1\n#define ZSTD_LEVEL_MAX     22\n#define ZSTD_THREAD_MAX   256\n\nnamespace NCompress {\nnamespace NZSTD {\n\nstruct DProps\n{\n  DProps() { clear (); }\n  void clear ()\n  {\n    _flags = 0; // the needs are currently unknown (unused)\n  }\n\n  Byte _flags;\n};\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetCoderMt,\n  public CMyUnknownImp\n{\n  CMyComPtr < ISequentialInStream > _inStream;\n\npublic:\n  DProps _props;\n\n  ZSTD_DCtx* _ctx;\n  void*  _srcBuf;\n  void*  _dstBuf;\n  size_t _srcBufSize;\n  size_t _dstBufSize;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n\n  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n  HRESULT CodeResume(ISequentialOutStream * outStream, const UInt64 * outSize, ICompressProgressInfo * progress);\n  HRESULT SetOutStreamSizeResume(const UInt64 *outSize);\n\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n\n  Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize));\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM7F_IMF(SetInStream(ISequentialInStream *inStream));\n  Z7_COM7F_IMF(ReleaseInStream());\n  UInt64 GetInputProcessedSize() const { return _processedIn; }\n#endif\n\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/ZstdEncoder.cpp",
    "content": "﻿// (C) 2016 - 2020 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n#include \"ZstdEncoder.h\"\n#include \"ZstdDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NZSTD {\n\nCEncoder::CEncoder():\n  _ctx(NULL),\n  _srcBuf(NULL),\n  _dstBuf(NULL),\n  _srcBufSize(ZSTD_CStreamInSize()),\n  _dstBufSize(ZSTD_CStreamOutSize()),\n  _processedIn(0),\n  _processedOut(0),\n  _numThreads(NWindows::NSystem::GetNumberOfProcessors()),\n  _Max(false),\n  _Long(-1),\n  _Level(ZSTD_CLEVEL_DEFAULT),\n  _Strategy(-1),\n  _WindowLog(-1),\n  _HashLog(-1),\n  _ChainLog(-1),\n  _SearchLog(-1),\n  _MinMatch(-1),\n  _TargetLen(-1),\n  _OverlapLog(-1),\n  _LdmHashLog(-1),\n  _LdmMinMatch(-1),\n  _LdmBucketSizeLog(-1),\n  _LdmHashRateLog(-1),\n  dictIDFlag(-1),\n  checksumFlag(-1),\n  unpackSize(0)\n{\n  _props.clear();\n}\n\nCEncoder::~CEncoder()\n{\n  if (_ctx) {\n    ZSTD_freeCCtx(_ctx);\n    MyFree(_srcBuf);\n    MyFree(_dstBuf);\n  }\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID * propIDs, const PROPVARIANT * coderProps, UInt32 numProps))\n{\n  _props.clear();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT & prop = coderProps[i];\n    PROPID propID = propIDs[i];\n    UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n    case NCoderPropID::kNumThreads:\n      {\n        SetNumberOfThreads(v);\n        break;\n      }\n    case NCoderPropID::kStrategy:\n      {\n        if (v < 1) v = 1;\n        if (v > 8) v = 8;\n        _Strategy = v;\n        break;\n      }\n    case NCoderPropID::kAdvMax:\n      if (!v)\n        break;\n    #if Z7_ZSTD_ADVMAX_ALLOWED // 64-bit only\n      _Max = true;\n    #endif\n      v = Z7_ZSTD_ULTIMATE_LEV;\n      /* fall-through */\n    case NCoderPropID::kLevel:\n      {\n        _Level = !_Max ? v : Z7_ZSTD_ULTIMATE_LEV;\n        if (v < 1) {\n          _Level = 1;\n        } else if ((Int32)v > ZSTD_maxCLevel()) {\n          if ((Int32)v > Z7_ZSTD_FAST_LEV_INC && _Level != Z7_ZSTD_ULTIMATE_LEV) { // special case (inverter for fast lever)\n            v -= Z7_ZSTD_FAST_LEV_INC;\n            goto fastLevel;\n          }\n        #if Z7_ZSTD_ADVMAX_ALLOWED // 64-bit only\n          _Max = (_Level == Z7_ZSTD_ULTIMATE_LEV); // special case (level from GUI)\n        #endif\n          _Level = ZSTD_maxCLevel();\n        }\n\n        /**\n         * zstd default levels: _Level => 1..ZSTD_maxCLevel(), Z7_ZSTD_ULTIMATE_LEV (128) == --max\n         */\n        _props._level = static_cast < Byte > (!_Max ? _Level : Z7_ZSTD_ULTIMATE_LEV);\n        break;\n      }\n    case NCoderPropID::kFast:\n     fastLevel:\n      if (!_Max)\n      {\n        /* like --fast in zstd cli program */\n        UInt32 _Fast = v;\n\n        if (v < 1) {\n          _Fast = 1;\n        } else if (v > 64) {\n          _Fast = 64;\n        }\n\n        /**\n         * zstd fast levels:\n         * _Fast  => 1..ZSTD_minCLevel()  (_Level => _Fast + Z7_ZSTD_FAST_LEV_INC)\n         */\n        _props._level = static_cast < Byte > (_Fast + Z7_ZSTD_FAST_LEV_INC);\n\n        /* negative levels are the fast ones */\n        _Level = _Fast * -1;\n        break;\n      }\n      /* fall-through */\n    case NCoderPropID::kLong:\n      {\n        /* like --long in zstd cli program */\n        _Long = 1;\n        if (v == 0) {\n          // m0=zstd:long:tlen=x -> long=default\n          _WindowLog = 27;\n        } else if (v < ZSTD_WINDOWLOG_MIN) {\n          // m0=zstd:long=9 -> long=10\n          _WindowLog = ZSTD_WINDOWLOG_MIN;\n        } else if (v > ZSTD_WINDOWLOG_MAX) {\n          // m0=zstd:long=33 -> long=max\n          _WindowLog = ZSTD_WINDOWLOG_MAX;\n        } else {\n          // m0=zstd:long=15 -> long=value\n          _WindowLog = v;\n        }\n        break;\n      }\n    case NCoderPropID::kWindowLog:\n      {\n        if (v < ZSTD_WINDOWLOG_MIN) v = ZSTD_WINDOWLOG_MIN;\n        if (v > ZSTD_WINDOWLOG_MAX) v = ZSTD_WINDOWLOG_MAX;\n        _WindowLog = v;\n        break;\n      }\n    case NCoderPropID::kHashLog:\n      {\n        if (v < ZSTD_HASHLOG_MIN) v = ZSTD_HASHLOG_MIN;\n        if (v > ZSTD_HASHLOG_MAX) v = ZSTD_HASHLOG_MAX;\n        _HashLog = v;\n        break;\n      }\n    case NCoderPropID::kChainLog:\n      {\n        if (v < ZSTD_CHAINLOG_MIN) v = ZSTD_CHAINLOG_MIN;\n        if (v > ZSTD_CHAINLOG_MAX) v = ZSTD_CHAINLOG_MAX;\n        _ChainLog = v;\n        break;\n      }\n    case NCoderPropID::kSearchLog:\n      {\n        if (v < ZSTD_SEARCHLOG_MIN) v = ZSTD_SEARCHLOG_MIN;\n        if (v > ZSTD_SEARCHLOG_MAX) v = ZSTD_SEARCHLOG_MAX;\n        _SearchLog = v;\n        break;\n      }\n    case NCoderPropID::kMinMatch:\n      {\n        if (v < ZSTD_MINMATCH_MIN) v = ZSTD_MINMATCH_MIN;\n        if (v > ZSTD_MINMATCH_MAX) v = ZSTD_MINMATCH_MAX;\n        _MinMatch = v;\n        break;\n      }\n    case NCoderPropID::kTargetLen:\n      {\n        if (v > ZSTD_TARGETLENGTH_MAX) v = ZSTD_TARGETLENGTH_MAX;\n        _TargetLen = 0;\n        break;\n      }\n    case NCoderPropID::kOverlapLog:\n      {\n        if (v > 9) v = 9; /* full size */\n        _OverlapLog = v;\n        break;\n      }\n    case NCoderPropID::kLdmHashLog:\n      {\n        if (v < ZSTD_HASHLOG_MIN) v = ZSTD_HASHLOG_MIN;\n        if (v > ZSTD_HASHLOG_MAX) v = ZSTD_HASHLOG_MAX;\n        _LdmHashLog = v;\n        break;\n      }\n    case NCoderPropID::kLdmSearchLength:\n      {\n        if (v < ZSTD_LDM_MINMATCH_MIN) v = ZSTD_LDM_MINMATCH_MIN;\n        if (v > ZSTD_LDM_MINMATCH_MAX) v = ZSTD_LDM_MINMATCH_MAX;\n        _LdmMinMatch = v;\n        break;\n      }\n    case NCoderPropID::kLdmBucketSizeLog:\n      {\n        if (v < 1) v = 1;\n        if (v > ZSTD_LDM_BUCKETSIZELOG_MAX) v = ZSTD_LDM_BUCKETSIZELOG_MAX;\n        _LdmBucketSizeLog = v;\n        break;\n      }\n    case NCoderPropID::kLdmHashRateLog:\n      {\n        if (v > (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN)) v = (ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN);\n        _LdmHashRateLog = v;\n        break;\n      }\n    default:\n      {\n        break;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    if (propID == NCoderPropID::kExpectedDataSize)\n      if (prop.vt == VT_UI8 && prop.uhVal.QuadPart)\n        unpackSize = prop.uhVal.QuadPart;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream * outStream))\n{\n  return WriteStream(outStream, &_props, sizeof (_props));\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream,\n  ISequentialOutStream *outStream, const UInt64 * /*inSize*/ ,\n  const UInt64 * /*outSize */, ICompressProgressInfo *progress))\n{\n  ZSTD_EndDirective ZSTD_todo = ZSTD_e_continue;\n  ZSTD_outBuffer outBuff;\n  ZSTD_inBuffer inBuff;\n  size_t err, srcSize;\n\n  _processedIn = 0;\n  _processedOut = 0;\n\n  if (!_ctx) {\n    _ctx = ZSTD_createCCtx();\n    if (!_ctx)\n      return E_OUTOFMEMORY;\n\n    _srcBuf = MyAlloc(_srcBufSize);\n    if (!_srcBuf)\n      return E_OUTOFMEMORY;\n\n    _dstBuf = MyAlloc(_dstBufSize);\n    if (!_dstBuf)\n      return E_OUTOFMEMORY;\n\n  #if Z7_ZSTD_ADVMAX_ALLOWED // 64-bit only\n    // params from setMaxCompression(), https://github.com/facebook/zstd/blob/v1.5.7/programs/zstdcli.c#L642 :\n    if (_Max) {\n      _Long = 1;\n      _WindowLog = ZSTD_WINDOWLOG_MAX;\n      _ChainLog = ZSTD_CHAINLOG_MAX;\n      _HashLog = ZSTD_HASHLOG_MAX;\n      _SearchLog = ZSTD_SEARCHLOG_MAX;\n      _MinMatch = ZSTD_MINMATCH_MIN;\n      _TargetLen = ZSTD_TARGETLENGTH_MAX;\n      _Strategy = ZSTD_STRATEGY_MAX;\n      _OverlapLog = ZSTD_OVERLAPLOG_MAX;\n      _LdmHashLog = ZSTD_LDM_HASHLOG_MAX;\n      _LdmHashRateLog = 0; /* automatically derived */\n      _LdmMinMatch = 16; /* heuristic */\n      _LdmBucketSizeLog = ZSTD_LDM_BUCKETSIZELOG_MAX;\n      _Level = ZSTD_maxCLevel();\n    }\n  #endif\n\n    /* setup level */\n    err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_compressionLevel, (UInt32)_Level);\n    if (ZSTD_isError(err)) return E_INVALIDARG;\n\n    /* setup thread count */\n    err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_nbWorkers, _numThreads);\n    if (ZSTD_isError(err)) return E_INVALIDARG;\n\n    /* set the content size flag */\n    err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_contentSizeFlag, 1);\n    if (ZSTD_isError(err)) return E_INVALIDARG;\n\n    if (dictIDFlag != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_dictIDFlag, dictIDFlag);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n    if (checksumFlag != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_checksumFlag, checksumFlag);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (unpackSize && unpackSize != (UInt64)(Int64)-1) { // size is known\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_srcSizeHint, (int)(unpackSize <= INT_MAX ? unpackSize : INT_MAX));\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    /* enable ldm for large windowlog values */\n    if (_WindowLog > 27 && _Long == 0)\n      _Long = 1;\n\n    /* set ldm */\n    if (_Long != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_enableLongDistanceMatching, _Long);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_Strategy != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_strategy, _Strategy);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_WindowLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_windowLog, _WindowLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_HashLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_hashLog, _HashLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_ChainLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_chainLog, _ChainLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_SearchLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_searchLog, _SearchLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_MinMatch != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_minMatch, _MinMatch);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_TargetLen != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_targetLength, _TargetLen);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_OverlapLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_overlapLog, _OverlapLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_LdmHashLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_ldmHashLog, _LdmHashLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_LdmMinMatch != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_ldmMinMatch, _LdmMinMatch);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_LdmBucketSizeLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_ldmBucketSizeLog, _LdmBucketSizeLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    if (_LdmHashRateLog != -1) {\n      err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_ldmHashRateLog, _LdmHashRateLog);\n      if (ZSTD_isError(err)) return E_INVALIDARG;\n    }\n\n    //err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_literalCompressionMode, (int)ZSTD_ps_auto);\n    //if (ZSTD_isError(err)) return E_INVALIDARG;\n\n    //err = ZSTD_CCtx_setParameter(_ctx, ZSTD_c_enableDedicatedDictSearch, 1);\n    //if (ZSTD_isError(err)) return E_INVALIDARG;\n  }\n\n  for (;;) {\n\n    /* read input */\n    srcSize = _srcBufSize;\n    RINOK(ReadStream(inStream, _srcBuf, &srcSize))\n\n    /* eof */\n    if (srcSize == 0)\n      ZSTD_todo = ZSTD_e_end;\n\n    /* compress data */\n    _processedIn += srcSize;\n\n    for (;;) {\n      outBuff.dst = _dstBuf;\n      outBuff.size = _dstBufSize;\n      outBuff.pos = 0;\n\n      if (ZSTD_todo == ZSTD_e_continue) {\n        inBuff.src = _srcBuf;\n        inBuff.size = srcSize;\n        inBuff.pos = 0;\n      } else {\n        inBuff.src = 0;\n        inBuff.size = srcSize;\n        inBuff.pos = 0;\n      }\n\n      err = ZSTD_compressStream2(_ctx, &outBuff, &inBuff, ZSTD_todo);\n      if (ZSTD_isError(err)) {\n        switch (ZSTD_getErrorCode(err)) {\n          /* @Igor: would be nice, if we have an API to store the errmsg */\n          case ZSTD_error_memory_allocation:\n            return E_OUTOFMEMORY;\n          case ZSTD_error_version_unsupported:\n          case ZSTD_error_frameParameter_unsupported:\n            return E_NOTIMPL;\n          case ZSTD_error_frameParameter_windowTooLarge:\n          case ZSTD_error_parameter_unsupported:\n          case ZSTD_error_parameter_outOfBound:\n            return E_INVALIDARG;\n          default:\n            return E_FAIL;\n        }\n      }\n\n      /* write output */\n      if (outBuff.pos) {\n        RINOK(WriteStream(outStream, _dstBuf, outBuff.pos))\n        _processedOut += outBuff.pos;\n      }\n\n      if (progress)\n        RINOK(progress->SetRatioInfo(&_processedIn, &_processedOut))\n\n      /* done */\n      if (ZSTD_todo == ZSTD_e_end && err == 0)\n        return S_OK;\n\n      /* need more input */\n      if (inBuff.pos == inBuff.size)\n        break;\n    }\n  }\n}\n\nZ7_COM7F_IMF(CEncoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = ZSTD_THREAD_MAX;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  _numThreads = numThreads;\n  return S_OK;\n}\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/ZstdEncoder.h",
    "content": "﻿// (C) 2016 - 2018 Tino Reichardt\n\n#define ZSTD_STATIC_LINKING_ONLY\n#include \"../../SevenZip/C/Alloc.h\"\n#include \"../../SevenZip/C/Threads.h\"\n#include <zstd.h>\n\n#include \"../../SevenZip/CPP/Common/Common.h\"\n#include \"../../SevenZip/CPP/Common/MyCom.h\"\n#include \"../../SevenZip/CPP/7zip/ICoder.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#ifndef Z7_EXTRACT_ONLY\nnamespace NCompress {\nnamespace NZSTD {\n\nstruct CProps\n{\n  CProps() { clear (); }\n  void clear ()\n  {\n    memset(this, 0, sizeof (*this));\n    _ver_major = ZSTD_VERSION_MAJOR;\n    _ver_minor = ZSTD_VERSION_MINOR;\n    _level = 3;\n  }\n\n  Byte _ver_major;\n  Byte _ver_minor;\n  Byte _level;\n  Byte _reserved[2];\n};\n\nZ7_CLASS_IMP_COM_5(\n  CEncoder,\n  ICompressCoder,\n  ICompressSetCoderMt,\n  ICompressSetCoderProperties,\n  ICompressSetCoderPropertiesOpt,\n  ICompressWriteCoderProperties\n)\npublic:\n  CProps _props;\n\n  ZSTD_CCtx* _ctx;\n  void*  _srcBuf;\n  void*  _dstBuf;\n  size_t _srcBufSize;\n  size_t _dstBufSize;\n\n  UInt64 _processedIn;\n  UInt64 _processedOut;\n  UInt32 _numThreads;\n\n  /* zstd advanced compression options */\n  bool  _Max;\n  Int32 _Long;\n  Int32 _Level;\n  Int32 _Strategy;\n  Int32 _WindowLog;\n  Int32 _HashLog;\n  Int32 _ChainLog;\n  Int32 _SearchLog;\n  Int32 _MinMatch;\n  Int32 _TargetLen;\n  Int32 _OverlapLog;\n  Int32 _LdmHashLog;\n  Int32 _LdmMinMatch;\n  Int32 _LdmBucketSizeLog;\n  Int32 _LdmHashRateLog;\n\n  int dictIDFlag;\n  int checksumFlag;\n  UInt64 unpackSize;\n\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/ZstdHandler.cpp",
    "content": "﻿// ZstdHandler.cpp\n\n#include \"../../SevenZip/CPP/7zip/Archive/StdAfx.h\"\n\n#include \"../../SevenZip/C/CpuArch.h\"\n#include \"../../SevenZip/CPP/Common/ComTry.h\"\n#include \"../../SevenZip/CPP/Common/Defs.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/ProgressUtils.h\"\n#include \"../../SevenZip/CPP/7zip/Common/RegisterArc.h\"\n#include \"../../SevenZip/CPP/7zip/Common/StreamUtils.h\"\n\n#include \"ZstdDecoder.h\"\n#include \"ZstdEncoder.h\"\n#include \"../../SevenZip/CPP/7zip/Compress/CopyCoder.h\"\n\n#include \"../../SevenZip/CPP/7zip/Archive/Common/DummyOutStream.h\"\n#include \"../../SevenZip/CPP/7zip/Archive/Common/HandlerOut.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NZSTD {\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n  IArchiveOpenSeq,\n  IOutArchive,\n  ISetProperties\n)\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  bool _isArc;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize;\n\n  CSingleMethodProps _props;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams,\n  kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID /*propID*/, PROPVARIANT * /*value*/))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nstatic const unsigned kSignatureCheckSize = 4;\n\nAPI_FUNC_static_IsArc IsArc_zstd(const Byte *p, size_t size)\n{\n  if (size < 4)\n    return k_IsArc_Res_NEED_MORE;\n\n  UInt32 magic = GetUi32(p);\n\n  // skippable frames\n  if (magic >= 0x184D2A50 && magic <= 0x184D2A5F) {\n    if (size < 16)\n      return k_IsArc_Res_NEED_MORE;\n    magic = GetUi32(p+12);\n  }\n\n#ifdef ZSTD_LEGACY_SUPPORT\n  // zstd 0.1\n  if (magic == 0xFD2FB51E)\n    return k_IsArc_Res_YES;\n\n  // zstd magic's for 0.2 .. 0.8 (aka 1.x)\n  if (magic >= 0xFD2FB522 && magic <= 0xFD2FB528)\n    return k_IsArc_Res_YES;\n#else\n  /* only version 1.x */\n  if (magic == 0xFD2FB528)\n    return k_IsArc_Res_YES;\n#endif\n\n  return k_IsArc_Res_NO;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    Byte buf[kSignatureCheckSize];\n    RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize));\n    if (IsArc_zstd(buf, kSignatureCheckSize) == k_IsArc_Res_NO)\n      return S_FALSE;\n    _isArc = true;\n    _stream = stream;\n    _seqStream = stream;\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n\n  _packSize = 0;\n\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    extractCallback->SetTotal(_packSize);\n\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode));\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  extractCallback->PrepareOperation(askMode);\n\n  Int32 opRes;\n\n  {\n\n  NCompress::NZSTD::CDecoder *decoderSpec = new NCompress::NZSTD::CDecoder;\n  CMyComPtr<ICompressCoder> decoder = decoderSpec;\n  decoderSpec->SetInStream(_seqStream);\n\n  CDummyOutStream *outStreamSpec = new CDummyOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n  outStreamSpec->SetStream(realOutStream);\n  outStreamSpec->Init();\n\n  realOutStream.Release();\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, true);\n\n  UInt64 packSize = 0;\n  UInt64 unpackedSize = 0;\n\n  HRESULT result = S_OK;\n\n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackedSize;\n\n    RINOK(lps->SetCur());\n    result = decoderSpec->CodeResume(outStream, &unpackedSize, progress);\n    UInt64 streamSize = decoderSpec->GetInputProcessedSize();\n\n    if (result != S_FALSE && result != S_OK)\n      return result;\n\n    if (unpackedSize == 0)\n      break;\n\n    if (streamSize == packSize)\n    {\n      // no new bytes in input stream, So it's good end of archive.\n      result = S_OK;\n      break;\n    }\n\n    if (packSize > streamSize)\n      return E_FAIL;\n\n    if (result != S_OK)\n      break;\n  }\n\n  decoderSpec->ReleaseInStream();\n  outStream.Release();\n\n  if (!_isArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (_dataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK) {\n    _unpackSize = outStreamSpec->GetSize();\n    _unpackSize_Defined = true;\n    opRes = NExtract::NOperationResult::kOK;\n  } else\n    return result;\n\n  }\n\n  return extractCallback->SetOperationResult(opRes);\n\n  COM_TRY_END\n}\n\nstatic HRESULT UpdateArchive(\n    UInt64 unpackSize,\n    ISequentialOutStream *outStream,\n    const CProps &props,\n    IArchiveUpdateCallback *updateCallback)\n{\n  RINOK(updateCallback->SetTotal(unpackSize));\n  CMyComPtr<ISequentialInStream> fileInStream;\n  RINOK(updateCallback->GetStream(0, &fileInStream));\n  CLocalProgress *localProgressSpec = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;\n  localProgressSpec->Init(updateCallback, true);\n  NCompress::NZSTD::CEncoder *encoderSpec = new NCompress::NZSTD::CEncoder;\n  // by zstd archive type store dictID and checksum (similar to zstd client)\n  encoderSpec->dictIDFlag = 1;\n  encoderSpec->checksumFlag = 1;\n  encoderSpec->unpackSize = unpackSize;\n  CMyComPtr<ICompressCoder> encoder = encoderSpec;\n  RINOK(props.SetCoderProps(encoderSpec, NULL));\n  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));\n  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  *type = NFileTimeType::kUnix;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));\n \n  if ((newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n  \n  if ((newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop));\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n    return UpdateArchive(size, outStream, _props, updateCallback);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(updateCallback, true);\n\n  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;\n  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, 0,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  if (_stream)\n    RINOK(_stream->Seek(0, STREAM_SEEK_SET, NULL));\n\n  return NCompress::CopyStream(_stream, outStream, progress);\n\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  return _props.SetProperties(names, values, numProps);\n}\n\nstatic const Byte k_Signature[] = \"0xFD2FB522..28\";\n\nREGISTER_ARC_IO(\n  \"zstd\", \"zst zstd tzst tzstd\", \"* * .tar .tar\", 0x0e,\n  k_Signature,\n  0,\n  NArcInfoFlags::kKeepName,\n  0,\n  IsArc_zstd)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/Extensions/ZSCodecs/ZstdRegister.cpp",
    "content": "﻿// (C) 2016 Tino Reichardt\n\n#include \"../../SevenZip/CPP/7zip/Compress/StdAfx.h\"\n\n#include \"../../SevenZip/CPP/7zip/Common/RegisterCodec.h\"\n\n#include \"ZstdDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"ZstdEncoder.h\"\n#endif\n\nREGISTER_CODEC_E(\n  ZSTD,\n  NCompress::NZSTD::CDecoder(),\n  NCompress::NZSTD::CEncoder(),\n  0x4F71101, \"ZSTD\")\n"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Console.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n\t<compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n\t\t<application>\n\t\t\t<supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n\t\t</application>\n\t</compatibility>\n</assembly>\n"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Console.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{96C0A1A0-D964-4725-AFDC-73EBF7FC1416}</ProjectGuid>\n    <RootNamespace>NanaZip.Core.Sfx.Console</RootNamespace>\n    <MileProjectType>ConsoleApplication</MileProjectType>\n    <MileProjectManifestFile>NanaZip.Core.Sfx.Console.manifest</MileProjectManifestFile>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Self Extracting Executable (Console)</MileProjectFileDescription>\n    <MileProjectInternalName>NanaZip.Core.Sfx.Console</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>NanaZip.Core.Console.sfx</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Project=\"..\\NanaZip.Core\\NanaZip.Core.Sfx.Shared.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <PropertyGroup>\n    <TargetName>NanaZip.Core.Console</TargetName>\n    <TargetExt>.sfx</TargetExt>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <AdditionalOptions>%(AdditionalOptions) /Wv:18</AdditionalOptions>\n      <Optimization Condition=\"'$(Configuration)' == 'Release'\">MinSpace</Optimization>\n      <FavorSizeOrSpeed Condition=\"'$(Configuration)' == 'Release'\">Size</FavorSizeOrSpeed>\n    </ClCompile>\n    <Link>\n      <LargeAddressAware>true</LargeAddressAware>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n      <RandomizedBaseAddress Condition=\"'$(Platform)' != 'ARM64'\">false</RandomizedBaseAddress>\n      <FixedBaseAddress Condition=\"'$(Platform)' != 'ARM64'\">true</FixedBaseAddress>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Core.Sfx.Console.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Windows.Helpers\">\n      <Version>1.0.1171</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXCon\\SfxCon.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\PropIDUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SortUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ConsoleClose.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ExtractCallbackConsole.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\List.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\MainAr.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\OpenCallbackConsole.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\PercentPrinter.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\UserInputUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CommandLineParser.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\ListFileUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StdInStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StdOutStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\DLL.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileLink.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileMapping.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\MemoryLock.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Registry.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\SecurityUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\C\\DllSecur.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXCon\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveCommandLine.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DirItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\EnumDirItems.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExitCode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractMode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\HashCalc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\IFileExtractCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Property.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\PropIDUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SetProperties.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SortUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Update.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdateAction.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdateCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdatePair.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdateProduce.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ZipRegistry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ConsoleClose.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ExtractCallbackConsole.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\List.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\OpenCallbackConsole.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\PercentPrinter.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\UserInputUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\CommandLineParser.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ListFileUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyException.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdInStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdOutStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\COM.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\DLL.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileMapping.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\MemoryLock.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Registry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\SecurityUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\" />\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\" />\n    <ClInclude Include=\"SevenZip\\C\\DllSecur.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"SevenZip\\CPP\\7zip\\GuiCommon.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXCon\\resource.rc\" />\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Console.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Core.Sfx.Console.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Filter Include=\"SevenZip\">\n      <UniqueIdentifier>{a02cac51-1e92-4845-ab01-7a8994a0e11b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\C\">\n      <UniqueIdentifier>{84607bb2-dc83-492b-9e74-203e374bd409}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\">\n      <UniqueIdentifier>{dc981d09-b8f6-4d46-a33b-32847831241d}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Common\">\n      <UniqueIdentifier>{a6168604-3fb5-4bc4-841e-7d088d375f51}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Windows\">\n      <UniqueIdentifier>{e24867cb-9368-4158-8149-fcbe8557d98f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\">\n      <UniqueIdentifier>{46da4253-ab9e-49e7-b976-2576e5f74c22}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Common\">\n      <UniqueIdentifier>{ac36e384-c7a6-4f82-ba20-87ee0ac6b3c4}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\">\n      <UniqueIdentifier>{7b89335d-ede3-499b-8bef-78a8ffbd2c6b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\Common\">\n      <UniqueIdentifier>{1e9a48b2-76d4-405a-b0a8-c887e4426828}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\">\n      <UniqueIdentifier>{c29efec3-96d9-47ff-a505-60e2beffdea4}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Compress\">\n      <UniqueIdentifier>{4b9b700e-82d1-4bd9-8ece-4c84a86e58a7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Bundles\">\n      <UniqueIdentifier>{b1606924-7695-490c-bc89-149f510181fc}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXCon\">\n      <UniqueIdentifier>{3f346a35-6f38-4175-bab8-6e37ec34c72b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\Console\">\n      <UniqueIdentifier>{eb3e8305-c831-400a-abb3-e5fb91c37eaf}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\C\\DllSecur.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CommandLineParser.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\DLL.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Registry.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXCon\\SfxCon.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXCon</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StdInStream.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StdOutStream.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\PropIDUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ConsoleClose.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ExtractCallbackConsole.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\List.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\MainAr.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\OpenCallbackConsole.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\PercentPrinter.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\UserInputUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\ListFileUtils.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileMapping.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\SecurityUtils.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\MemoryLock.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SortUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileLink.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\DllSecur.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\CommandLineParser.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\COM.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\DLL.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Registry.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DirItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExitCode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractMode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\HashCalc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\IFileExtractCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Property.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SetProperties.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ZipRegistry.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXCon\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXCon</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdInStream.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdOutStream.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\PropIDUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ConsoleClose.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\ExtractCallbackConsole.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\List.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\OpenCallbackConsole.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\PercentPrinter.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Console\\UserInputUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Console</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyException.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveCommandLine.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\EnumDirItems.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ListFileUtils.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileMapping.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\SecurityUtils.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\MemoryLock.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SortUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Update.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdatePair.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdateProduce.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdateAction.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\UpdateCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"SevenZip\\CPP\\7zip\\GuiCommon.rc\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXCon\\resource.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXCon</Filter>\n    </ResourceCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Setup.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n\t<dependency>\n\t\t<dependentAssembly>\n\t\t\t<assemblyIdentity\n\t\t\t\ttype=\"win32\"\n\t\t\t\tname=\"Microsoft.Windows.Common-Controls\"\n\t\t\t\tversion=\"6.0.0.0\"\n\t\t\t\tprocessorArchitecture=\"*\"\n\t\t\t\tpublicKeyToken=\"6595b64144ccf1df\"\n\t\t\t\tlanguage=\"*\"/>\n\t\t</dependentAssembly>\n\t</dependency>\n\t<application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n\t\t<windowsSettings>\n\t\t\t<dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2</dpiAwareness>\n\t\t</windowsSettings>\n\t</application>\n\t<compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n\t\t<application>\n\t\t\t<supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n\t\t</application>\n\t</compatibility>\n</assembly>\n"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Setup.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{43308629-5328-46BF-8E1C-A258A937B981}</ProjectGuid>\n    <RootNamespace>NanaZip.Core.Sfx.Setup</RootNamespace>\n    <MileProjectType>WindowsApplication</MileProjectType>\n    <MileProjectManifestFile>NanaZip.Core.Sfx.Setup.manifest</MileProjectManifestFile>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Self Extracting Executable (Setup)</MileProjectFileDescription>\n    <MileProjectInternalName>NanaZip.Core.Sfx.Setup</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>NanaZip.Core.Setup.sfx</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Project=\"..\\NanaZip.Core\\NanaZip.Core.Sfx.Shared.props\" />\n  <Import Project=\"..\\K7User\\K7UserStatic.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <PropertyGroup>\n    <TargetName>NanaZip.Core.Setup</TargetName>\n    <TargetExt>.sfx</TargetExt>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <AdditionalOptions>%(AdditionalOptions) /Wv:18</AdditionalOptions>\n      <PreprocessorDefinitions>Z7_NO_REGISTRY;Z7_NO_CRYPTO;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <LargeAddressAware>true</LargeAddressAware>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n      <RandomizedBaseAddress Condition=\"'$(Platform)' != 'ARM64'\">false</RandomizedBaseAddress>\n      <FixedBaseAddress Condition=\"'$(Platform)' != 'ARM64'\">true</FixedBaseAddress>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Core.Sfx.Setup.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Windows.Helpers\">\n      <Version>1.0.1171</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractCallbackSfx.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractEngine.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\SfxSetup.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CommandLineParser.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\TextConfig.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\DLL.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Registry.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ResourceString.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Window.cpp\" />\n    <ClCompile Include=\"SevenZip\\C\\DllSecur.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractCallbackSfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractEngine.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\resource.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DirItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExitCode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractMode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\HashCalc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\IFileExtractCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Property.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SetProperties.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ZipRegistry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\DialogSize.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\LangUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MyWindowsNew.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialogRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resource.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resourceGui.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\CommandLineParser.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\TextConfig.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\COM.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Edit.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ProgressBar.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Static.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\DLL.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Registry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ResourceString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Window.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\" />\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\" />\n    <ClInclude Include=\"SevenZip\\C\\DllSecur.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"SevenZip\\CPP\\7zip\\GuiCommon.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\resource.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog.rc\" />\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Setup.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Core.Sfx.Setup.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Filter Include=\"SevenZip\">\n      <UniqueIdentifier>{79656359-57f0-46e0-92e7-ef95f40a7b3c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\C\">\n      <UniqueIdentifier>{32d5484f-562c-4698-9f2f-cb8fb950a350}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\">\n      <UniqueIdentifier>{ff1936d1-c7cb-44aa-ab21-7e178829ae3e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Common\">\n      <UniqueIdentifier>{e5d6abfb-a849-4b69-8bf2-2e3aedd2828e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Windows\">\n      <UniqueIdentifier>{77e65beb-5963-4543-b6df-a8c8cdc2320e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Windows\\Control\">\n      <UniqueIdentifier>{f9122055-bdf0-4579-818a-2707183b267b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\">\n      <UniqueIdentifier>{6b238a58-c7ef-4580-8601-1fc4b40cb412}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Common\">\n      <UniqueIdentifier>{eac2b828-a798-4c20-818a-6e9f46c1ff84}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\">\n      <UniqueIdentifier>{0bcddf01-be5c-4c2e-92e7-47782131dbd3}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\Common\">\n      <UniqueIdentifier>{0bbaf451-4c14-46ba-879c-a748fe227a00}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\">\n      <UniqueIdentifier>{eda412f3-53f5-43d7-96a0-42e6e814c8a7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\">\n      <UniqueIdentifier>{8f2535da-aeaa-4780-8ea8-94dca0bb6865}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\">\n      <UniqueIdentifier>{0c5d8c57-80ef-486c-a465-66ed0cce4865}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Compress\">\n      <UniqueIdentifier>{96d6763e-8e47-41f9-a366-a7f918c91d3d}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Bundles\">\n      <UniqueIdentifier>{2c44900a-f97b-42fa-8e70-0107ee71b153}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\">\n      <UniqueIdentifier>{da434e39-c4d1-4d70-9ea2-1a7d0d524e98}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\C\\DllSecur.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CommandLineParser.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\DLL.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Registry.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ResourceString.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Window.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.cpp\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Explorer</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractCallbackSfx.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractEngine.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\SfxSetup.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\TextConfig.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\DllSecur.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\CommandLineParser.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\COM.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\DLL.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Registry.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ResourceString.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Window.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Edit.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ProgressBar.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Static.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DirItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExitCode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractMode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\HashCalc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\IFileExtractCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Property.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SetProperties.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ZipRegistry.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Explorer</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Explorer</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\DialogSize.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\LangUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MyWindowsNew.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resource.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resourceGui.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractCallbackSfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\ExtractEngine.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\resource.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\TextConfig.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialogRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"SevenZip\\CPP\\7zip\\GuiCommon.rc\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXSetup\\resource.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXSetup</Filter>\n    </ResourceCompile>\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </None>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Shared.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <Import Project=\"..\\K7Base\\K7BaseStatic.props\" />\n  <Import Project=\"..\\NanaZip.Codecs\\NanaZip.Codecs.Sfx.Shared.props\" />\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>Z7_EXTRACT_ONLY;Z7_NO_READ_FROM_CODER;Z7_SFX;Z7_NO_LONG_PATH;Z7_NO_LARGE_PAGES;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <PreprocessorDefinitions Condition=\"'$(Platform)' == 'x64'\">Z7_LZMA_DEC_OPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>$(OutDir)NanaZip.Core.Sfx.Shared.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <!--\n        Set the dependent load flag to LOAD_LIBRARY_SEARCH_SYSTEM32 to prevent\n        static imports from searching elsewhere:\n        https://docs.microsoft.com/en-us/cpp/build/reference/dependentloadflag\n        Note that any new static imports on the SFX must be audited since this\n        flag may not cover all scenarios; see\n        https://github.com/pbatard/rufus/issues/2701#issuecomment-2874788564\n        for more details.\n      -->\n      <AdditionalOptions Condition=\"'$(Configuration)' == 'Release'\">%(AdditionalOptions) /DEPENDENTLOADFLAG:0x800</AdditionalOptions>\n    </Link>\n  </ItemDefinitionGroup>\n  <Target Name=\"NanaZipCoreSfxSharedBuildSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup>\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)Extensions\\ZSCodecs\\ZstdRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Archive\\7z\\7zExtract.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Archive\\7z\\7zRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Archive\\SplitHandler.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\Bcj2Register.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\BcjRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\BranchRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\CopyRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\DeltaFilter.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\Lzma2Register.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\LzmaRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Compress\\PpmdRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\7zip\\Crypto\\7zAesRegister.cpp\" />\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)SevenZip\\CPP\\Common\\CRC.cpp\" />\n    </ItemGroup>\n  </Target>\n  <ItemGroup>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)NanaZip.Core.Sfx.Shared.vcxproj\">\n      <Project>{7262BA1E-732D-4814-972F-698F0B4330A1}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Shared.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{7262BA1E-732D-4814-972F-698F0B4330A1}</ProjectGuid>\n    <RootNamespace>NanaZip.Core.Sfx.Shared</RootNamespace>\n    <MileProjectType>StaticLibrary</MileProjectType>\n  </PropertyGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Condition=\"'$(Platform)' == 'x64'\" Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.props\" />\n  <Import Project=\"..\\K7Base\\K7BaseStatic.props\" />\n  <Import Project=\"..\\NanaZip.Codecs\\NanaZip.Codecs.Sfx.Shared.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>Z7_EXTRACT_ONLY;Z7_NO_READ_FROM_CODER;Z7_SFX;Z7_NO_LONG_PATH;Z7_NO_LARGE_PAGES;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <PreprocessorDefinitions Condition=\"'$(Platform)' == 'x64'\">Z7_LZMA_DEC_OPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <DisableSpecificWarnings>4113;</DisableSpecificWarnings>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Core.Sfx.Shared.props\" />\n    <None Include=\"SevenZip\\ASM\\x86\\7zAsm.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\7zCrcOpt.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\AesOpt.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\LzmaDecOpt.asm\" />\n    <None Include=\"SevenZip\\C\\7zCrcOpt.c\" />\n    <None Include=\"SevenZip\\C\\AesOpt.c\" />\n    <None Include=\"Extensions\\ZSCodecs\\ZstdRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zExtract.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\SplitHandler.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Register.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\DeltaFilter.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Register.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAesRegister.cpp\" />\n    <None Include=\"SevenZip\\CPP\\Common\\CRC.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\PropId.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\IntToString.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyString.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\NewHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringConvert.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\UTFConvert.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\Wildcard.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileDir.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileFind.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileIO.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileName.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariant.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Synchronization.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\System.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\TimeUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\C\\7zCrc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\7zStream.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Aes.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Alloc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Bcj2.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Bra.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Bra86.c\" />\n    <ClCompile Include=\"SevenZip\\C\\CpuArch.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Delta.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Lzma2Dec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Lzma2DecMt.c\" />\n    <ClCompile Include=\"SevenZip\\C\\LzmaDec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\MtDec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7Dec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Threads.c\" />\n    <ClCompile Include=\"Wrappers\\Sha256Wrapper.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\ZstdDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zCompressionMode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHeader.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zProperties.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\HandlerOut.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\RandGen.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common0.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer2.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyException.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zCrc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Aes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Bcj2.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Bra.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\" />\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Delta.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Lzma2Dec.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Lzma2DecMt.h\" />\n    <ClInclude Include=\"SevenZip\\C\\LzmaDec.h\" />\n    <ClInclude Include=\"SevenZip\\C\\MtDec.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Ppmd.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Ppmd7.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\" />\n    <ClInclude Include=\"SevenZip\\C\\RotateDefs.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sha256.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\" />\n    <ClInclude Include=\"Wrappers\\Sha256Wrapper.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Text Include=\"SevenZip\\CPP\\7zip\\Guid.txt\" />\n  </ItemGroup>\n  <Target Name=\"NanaZipCoreAesHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\AesOpt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreAesHardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' != 'x64'\">\n      <ClCompile Include=\"SevenZip\\C\\AesOpt.c\">\n        <Optimization Condition=\"'$(Configuration)' == 'Release'\">MaxSpeed</Optimization>\n      </ClCompile>\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreLzmaDecHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\LzmaDecOpt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreCrcHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\7zCrcOpt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreCrcHardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' != 'x64'\">\n      <ClCompile Include=\"SevenZip\\C\\7zCrcOpt.c\">\n        <Optimization Condition=\"'$(Configuration)' == 'Release'\">MaxSpeed</Optimization>\n      </ClCompile>\n    </ItemGroup>\n  </Target>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n  <Import Condition=\"'$(Platform)' == 'x64'\" Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.targets\" />\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Shared.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"SevenZip\">\n      <UniqueIdentifier>{831b4812-8fbb-43f7-b499-2c0a9de0247f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\ASM\">\n      <UniqueIdentifier>{5c1978db-a255-4b49-83d0-4afd0ddb4c55}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\ASM\\x86\">\n      <UniqueIdentifier>{eee9d966-6cc4-436c-9e8a-c2edd167628b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\C\">\n      <UniqueIdentifier>{90fbd600-a33d-4632-875b-c01b75ce1160}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\">\n      <UniqueIdentifier>{f80dd93f-9ebe-4400-9008-036f7236b666}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Windows\">\n      <UniqueIdentifier>{bd4aae15-456a-49f3-a4e0-de4a254573e7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Common\">\n      <UniqueIdentifier>{b524552a-a407-4857-9f47-637f9cfaf52e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\">\n      <UniqueIdentifier>{f203a629-0427-475a-a1ab-b19024bf3571}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Common\">\n      <UniqueIdentifier>{8ab18a25-f277-4e74-8884-d49d361f0f03}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Crypto\">\n      <UniqueIdentifier>{6bff2406-ccdb-47eb-b690-b763478d7288}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Compress\">\n      <UniqueIdentifier>{8b75ba80-7601-4c71-95b8-27f0ec8d0b14}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\">\n      <UniqueIdentifier>{c9419a55-e2ed-4fb8-984f-c25eb525c124}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\">\n      <UniqueIdentifier>{c7d86060-8c21-4cbe-bcb5-d4642e441e3d}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\">\n      <UniqueIdentifier>{90bdad4f-0ef4-4cb5-a451-71a8b415d708}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Extensions\">\n      <UniqueIdentifier>{8892af78-26a4-4504-9e3d-d303756f56ac}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Extensions\\ZSCodecs\">\n      <UniqueIdentifier>{1f305354-6929-465a-96f8-c10248b20758}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Wrappers\">\n      <UniqueIdentifier>{f2cb8db9-ad05-4731-87cb-b0ff70879041}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Core.Sfx.Shared.props\" />\n    <None Include=\"SevenZip\\ASM\\x86\\7zAsm.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\AesOpt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\LzmaDecOpt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\C\\AesOpt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\7zCrcOpt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\C\\7zCrcOpt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </None>\n    <None Include=\"Extensions\\ZSCodecs\\ZstdRegister.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zExtract.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\SplitHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Register.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\DeltaFilter.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Register.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAesRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\Common\\CRC.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\C\\Aes.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Bcj2.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Bra.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Bra86.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Lzma2Dec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Lzma2DecMt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\LzmaDec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\MtDec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7Dec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\7zStream.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Threads.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Delta.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\7zCrc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Alloc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\CpuArch.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileDir.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileFind.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileIO.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileName.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariant.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Synchronization.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\System.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\IntToString.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyString.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\NewHandler.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringConvert.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\UTFConvert.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\Wildcard.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\PropId.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\TimeUtils.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Wrappers\\Sha256Wrapper.cpp\">\n      <Filter>Wrappers</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdDecoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"SevenZip\\C\\Aes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Bcj2.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Bra.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Lzma2Dec.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Lzma2DecMt.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\LzmaDec.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\MtDec.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Ppmd.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Ppmd7.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sha256.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\RandGen.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Delta.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zCrc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\RotateDefs.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer2.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyException.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\HandlerOut.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zCompressionMode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHeader.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zProperties.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common0.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Wrappers\\Sha256Wrapper.h\">\n      <Filter>Wrappers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\ZstdDecoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <Text Include=\"SevenZip\\CPP\\7zip\\Guid.txt\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </Text>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Windows.Resources.h",
    "content": "﻿#define REDIRECTED_IDOK                             401\n#define REDIRECTED_IDCANCEL                         402\n#define REDIRECTED_IDYES                            406\n#define REDIRECTED_IDNO                             407\n#define IDS_CLOSE                                   408\n#define IDS_CONTINUE                                411\n#define IDB_YES_TO_ALL                              440\n#define IDB_NO_TO_ALL                               441\n#define IDB_PROGRESS_BACKGROUND                     444\n#define IDS_PROGRESS_FOREGROUND                     445\n#define IDB_PAUSE                                   446\n#define IDS_PROGRESS_PAUSED                         447\n#define IDS_PROGRESS_ASK_CANCEL                     448\n#define IDT_PROGRESS_PACKED                         1008\n#define IDS_PROP_MTIME                              1012\n#define IDT_PROGRESS_FILES                          1032\n#define IDS_MEM_ERROR                               3000\n#define IDS_CANNOT_CREATE_FOLDER                    3003\n#define IDS_UPDATE_NOT_SUPPORTED                    3004\n#define IDS_CANT_OPEN_ARCHIVE                       3005\n#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE             3006\n#define IDS_UNSUPPORTED_ARCHIVE_TYPE                3007\n#define IDS_CANT_OPEN_AS_TYPE                       3017\n#define IDS_IS_OPEN_AS_TYPE                         3018\n#define IDS_IS_OPEN_WITH_OFFSET                     3019\n#define IDS_PROGRESS_EXTRACTING                     3300\n#define IDS_PROGRESS_SKIPPING                       3325\n#define IDT_EXTRACT_EXTRACT_TO                      3401\n#define IDS_EXTRACT_SET_FOLDER                      3402\n#define IDS_EXTRACT_PATHS_FULL                      3411\n#define IDS_EXTRACT_PATHS_NO                        3412\n#define IDS_EXTRACT_PATHS_ABS                       3413\n#define IDS_PATH_MODE_RELAT                         3414\n#define IDS_EXTRACT_OVERWRITE_ASK                   3421\n#define IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT        3422\n#define IDS_EXTRACT_OVERWRITE_SKIP_EXISTING         3423\n#define IDS_EXTRACT_OVERWRITE_RENAME                3424\n#define IDS_EXTRACT_OVERWRITE_RENAME_EXISTING       3425\n#define IDD_OVERWRITE                               3500\n#define IDT_OVERWRITE_HEADER                        3501\n#define IDT_OVERWRITE_QUESTION_BEGIN                3502\n#define IDT_OVERWRITE_QUESTION_END                  3503\n#define IDS_FILE_SIZE                               3504\n#define IDB_AUTO_RENAME                             3505\n#define IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD      3700\n#define IDS_EXTRACT_MESSAGE_DATA_ERROR              3701\n#define IDS_EXTRACT_MESSAGE_CRC_ERROR               3702\n#define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED    3703\n#define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED     3704\n#define IDS_EXTRACT_MSG_WRONG_PSW_GUESS             3710\n#define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD          3721\n#define IDS_EXTRACT_MSG_DATA_ERROR                  3722\n#define IDS_EXTRACT_MSG_CRC_ERROR                   3723\n#define IDS_EXTRACT_MSG_UNAVAILABLE_DATA            3724\n#define IDS_EXTRACT_MSG_UEXPECTED_END               3725\n#define IDS_EXTRACT_MSG_DATA_AFTER_END              3726\n#define IDS_EXTRACT_MSG_IS_NOT_ARC                  3727\n#define IDS_EXTRACT_MSG_HEADERS_ERROR               3728\n#define IDS_EXTRACT_MSG_WRONG_PSW_CLAIM             3729\n#define IDS_OPEN_MSG_UNAVAILABLE_START              3763\n#define IDS_OPEN_MSG_UNCONFIRMED_START              3764\n#define IDS_OPEN_MSG_UNSUPPORTED_FEATURE            3768\n#define IDD_PASSWORD                                3800\n#define IDT_PASSWORD_ENTER                          3801\n#define IDX_PASSWORD_SHOW                           3803\n#define IDT_PROGRESS_ELAPSED                        3900\n#define IDT_PROGRESS_REMAINING                      3901\n#define IDT_PROGRESS_TOTAL                          3902\n#define IDT_PROGRESS_SPEED                          3903\n#define IDT_PROGRESS_PROCESSED                      3904\n#define IDT_PROGRESS_RATIO                          3905\n#define IDT_PROGRESS_ERRORS                         3906\n"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Windows.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n\t<dependency>\n\t\t<dependentAssembly>\n\t\t\t<assemblyIdentity\n\t\t\t\ttype=\"win32\"\n\t\t\t\tname=\"Microsoft.Windows.Common-Controls\"\n\t\t\t\tversion=\"6.0.0.0\"\n\t\t\t\tprocessorArchitecture=\"*\"\n\t\t\t\tpublicKeyToken=\"6595b64144ccf1df\"\n\t\t\t\tlanguage=\"*\"/>\n\t\t</dependentAssembly>\n\t</dependency>\n\t<application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n\t\t<windowsSettings>\n\t\t\t<dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2</dpiAwareness>\n\t\t</windowsSettings>\n\t</application>\n\t<compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n\t\t<application>\n\t\t\t<supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n\t\t</application>\n\t</compatibility>\n</assembly>\n"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Windows.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{C11F288B-9E3C-4DA9-8206-852BB91C7E4C}</ProjectGuid>\n    <RootNamespace>NanaZip.Core.Sfx.Windows</RootNamespace>\n    <MileProjectType>WindowsApplication</MileProjectType>\n    <MileProjectManifestFile>NanaZip.Core.Sfx.Windows.manifest</MileProjectManifestFile>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Self Extracting Executable (Windows)</MileProjectFileDescription>\n    <MileProjectInternalName>NanaZip.Core.Sfx.Windows</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>NanaZip.Core.Windows.sfx</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n    <MileWindowsHelpersNoCppWinRTHelpers>true</MileWindowsHelpersNoCppWinRTHelpers>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Project=\"..\\NanaZip.Core\\NanaZip.Core.Sfx.Shared.props\" />\n  <Import Project=\"..\\K7User\\K7UserStatic.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <PropertyGroup>\n    <TargetName>NanaZip.Core.Windows</TargetName>\n    <TargetExt>.sfx</TargetExt>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <AdditionalOptions>%(AdditionalOptions) /Wv:18</AdditionalOptions>\n      <PreprocessorDefinitions>Z7_NO_REGISTRY;Z7_LANG;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <LargeAddressAware>true</LargeAddressAware>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n      <RandomizedBaseAddress Condition=\"'$(Platform)' != 'ARM64'\">false</RandomizedBaseAddress>\n      <FixedBaseAddress Condition=\"'$(Platform)' != 'ARM64'\">true</FixedBaseAddress>\n      <AdditionalDependencies>Shlwapi.lib;comctl32.lib;comdlg32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n    <ResourceCompile>\n      <PreprocessorDefinitions>Z7_SFX;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\resource.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DirItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExitCode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractMode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\HashCalc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\IFileExtractCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Property.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SetProperties.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ZipRegistry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\BrowseDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\BrowseDialogRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialogRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\DialogSize.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ExtractCallback.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\LangUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MemDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MemDialogRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MyWindowsNew.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialogRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialogRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2Res.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PropertyName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PropertyNameRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resource.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resourceGui.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\SysIconUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialogRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractGUI.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractRes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\HashGUI.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\resource2.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\CommandLineParser.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Lang.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Clipboard.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\COM.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\CommonDialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ComboBox.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Edit.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ListView.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ProgressBar.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Static.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\DLL.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\MemoryGlobal.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Registry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ResourceString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Shell.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Window.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\" />\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\" />\n    <ClInclude Include=\"SevenZip\\C\\DllSecur.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\" />\n    <ClInclude Include=\"NanaZip.Core.Sfx.Windows.Resources.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialog.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialog.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialog.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2a.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialog.rc\" />\n    <ResourceCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\resource.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\GuiCommon.rc\" />\n    <ResourceCompile Include=\"NanaZip.Core.Sfx.Windows.Resources.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Core.Sfx.Windows.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Windows.Helpers\">\n      <Version>1.0.1171</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\SfxWin.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\BrowseDialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ExtractCallback.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\LangUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PropertyName.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\SysIconUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractGUI.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CommandLineParser.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\Lang.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Clipboard.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\CommonDialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\ComboBox.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\ListView.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\DLL.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\MemoryGlobal.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Registry.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ResourceString.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Shell.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Window.cpp\" />\n    <ClCompile Include=\"SevenZip\\C\\DllSecur.c\" />\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.Sfx.Windows.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <ClInclude Include=\"NanaZip.Core.Sfx.Windows.Resources.h\" />\n    <ClInclude Include=\"SevenZip\\C\\DllSecur.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\CommandLineParser.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\DLL.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ComboBox.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ListView.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\COM.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Clipboard.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\CommonDialog.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\MemoryGlobal.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\ResourceString.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Shell.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Window.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Explorer</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Explorer</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\BrowseDialog.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\BrowseDialogRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialog.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialogRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ExtractCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialog.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialogRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialog.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialogRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2Res.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PropertyName.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PropertyNameRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\SysIconUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Edit.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\Static.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\LangUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialog.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialogRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractGUI.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Lang.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resourceGui.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\DialogSize.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\resource.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\HashCalc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractMode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Property.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\IFileExtractCallback.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DirItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ZipRegistry.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\SetProperties.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Control\\ProgressBar.h\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MyWindowsNew.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\resource2.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\HashGUI.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\resource.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXWin</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXWin</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExitCode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Registry.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MemDialog.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\MemDialogRes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"NanaZip.Core.Sfx.Windows.Resources.rc\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialog.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialog.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialog.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2a.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialog.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </None>\n    <ResourceCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\resource.rc\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXWin</Filter>\n    </ResourceCompile>\n    <None Include=\"SevenZip\\CPP\\7zip\\GuiCommon.rc\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Core.Sfx.Windows.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Filter Include=\"SevenZip\">\n      <UniqueIdentifier>{228b4446-765f-408f-bf2f-0fdbca672a0a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\C\">\n      <UniqueIdentifier>{8e54617b-ff61-48bb-9161-0092be0b4007}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\">\n      <UniqueIdentifier>{b2adb5aa-4f67-4488-8c46-bb4dc2d3f0bf}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Common\">\n      <UniqueIdentifier>{1a8e5a77-dcba-4972-8b01-58be6745af39}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Windows\">\n      <UniqueIdentifier>{ff56f996-125c-4e42-abeb-8214a2d12605}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\">\n      <UniqueIdentifier>{63424395-d2fa-41d6-adcd-529cde0644ce}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Common\">\n      <UniqueIdentifier>{c2b0e71b-99ec-4dc3-9da7-1544dcde5247}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Windows\\Control\">\n      <UniqueIdentifier>{df91ecb3-2a4b-4c73-9947-6c2c4a7faf1e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\">\n      <UniqueIdentifier>{96b4f174-c41b-4ca7-9a22-3429f2fb5ace}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\Common\">\n      <UniqueIdentifier>{6b4aa66f-e8d1-4aa3-a893-66987573c8ad}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\">\n      <UniqueIdentifier>{99b5982a-e4b7-4576-adee-e20e10940bc2}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\">\n      <UniqueIdentifier>{8a5f233b-88a1-4680-8fa2-5d8244c5e0f2}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\">\n      <UniqueIdentifier>{e1f474ba-bade-4dbf-a901-c31edbb0a137}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\">\n      <UniqueIdentifier>{00479e9e-e0ea-4d6e-8f64-9ff02c20ad71}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Compress\">\n      <UniqueIdentifier>{0e2eaacb-3bb8-4b11-82f1-ea3440282956}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Bundles\">\n      <UniqueIdentifier>{f82f7440-7ccb-4b2e-b354-4e31b654e9a3}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\">\n      <UniqueIdentifier>{82024473-dd95-49eb-afcd-9894944fcce8}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\C\\DllSecur.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CommandLineParser.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\DLL.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ErrorMsg.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\ComboBox.cpp\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\Dialog.cpp\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Control\\ListView.cpp\">\n      <Filter>SevenZip\\CPP\\Windows\\Control</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Clipboard.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\CommonDialog.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\MemoryGlobal.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\ResourceString.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Shell.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Window.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilePathAutoRename.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FileStreams.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveExtractCallback.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ArchiveOpenCallback.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\DefaultName.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\Extract.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\ExtractingFilePath.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\LoadCodecs.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Common\\OpenArchive.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\Explorer\\MyMessages.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\Explorer</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\BrowseDialog.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ComboDialog.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ExtractCallback.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\FormatUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\OverwriteDialog.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PasswordDialog.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\ProgressDialog2.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\PropertyName.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\SysIconUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\LangUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractDialog.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\GUI\\ExtractGUI.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\GUI</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\Lang.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Bundles\\SFXWin\\SfxWin.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Bundles\\SFXWin</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\UI\\FileManager\\RegistryUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\UI\\FileManager</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Registry.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{5220420B-9A5C-44A7-BE69-97F25365BB26}</ProjectGuid>\n    <RootNamespace>NanaZip.Core</RootNamespace>\n    <MileProjectType>DynamicLibrary</MileProjectType>\n    <WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Core</MileProjectFileDescription>\n    <MileProjectInternalName>NanaZip.Core</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>NanaZip.Core.dll</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.ARM64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <Import Condition=\"'$(Platform)' == 'x64'\" Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.props\" />\n  <Import Project=\"..\\K7Base\\K7Base.props\" />\n  <Import Project=\"..\\NanaZip.Codecs\\NanaZip.Codecs.props\" />\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>Z7_EXTERNAL_CODECS;NSIS_SCRIPT;ZSTD_MULTITHREAD;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <PreprocessorDefinitions Condition=\"'$(Platform)' == 'x64'\">Z7_LZMA_DEC_OPT;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <DisableSpecificWarnings>4100;4113;4127;4146;4189;4200;4244;4267;4334;4702;</DisableSpecificWarnings>\n    </ClCompile>\n    <Link>\n      <LargeAddressAware>true</LargeAddressAware>\n      <ModuleDefinitionFile>SevenZip\\CPP\\7zip\\Archive\\Archive2.def</ModuleDefinitionFile>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <None Include=\"SevenZip\\ASM\\x86\\7zAsm.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\7zCrcOpt.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\AesOpt.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\LzFindOpt.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\LzmaDecOpt.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\Sort.asm\" />\n    <None Include=\"SevenZip\\ASM\\x86\\XzCrc64Opt.asm\" />\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\Archive2.def\" />\n    <None Include=\"SevenZip\\C\\7zCrcOpt.c\" />\n    <None Include=\"SevenZip\\C\\AesOpt.c\" />\n    <None Include=\"SevenZip\\C\\XzCrc64Opt.c\" />\n    <None Include=\"SevenZip\\C\\LzFindOpt.c\" />\n    <None Include=\"SevenZip\\C\\Sort.c\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliDecoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliEncoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliHandler.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliRegister.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\FastLzma2Encoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\FastLzma2Register.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardDecoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardEncoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardHandler.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardRegister.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Decoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Encoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Handler.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Register.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Decoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Encoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Handler.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Register.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LzHandler.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdDecoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdEncoder.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdHandler.cpp\" />\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zEncode.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zExtract.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zFolderInStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandlerOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHeader.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zProperties.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zUpdate.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ApfsHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ApmHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ArchiveExports.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ArHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ArjHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\AvbHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Base64Handler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Bz2Handler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabBlockInStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHeader.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ComHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\DummyOutStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\FindSignature.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\HandlerOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\InStreamWithCRC.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithSha1.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\CpioHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\CramfsHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\DllExports2.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\DmgHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ElfHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ExtHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\FatHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\FlvHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\GptHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\GzHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\HandlerCont.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\HfsHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\IhexHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHeader.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LpHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LvmHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LzhHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LzmaHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MachoHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MbrHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MslzHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MubHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisDecode.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\NtfsHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\PeHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\PpmdHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\QcowHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\Rar5Handler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\RpmHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SparseHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SplitHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SquashfsHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SwfHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHandlerOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHeader.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarUpdate.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\UefiHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VdiHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VhdHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VhdxHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VmdkHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimHandlerOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\XarHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\XzHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ZHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipAddCommon.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHandlerOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipIn.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipItem.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipOut.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipUpdate.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\InOutTempBuffer.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\MemBlocks.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OffsetStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OutMemStream.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressMt.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\PropId.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Register.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BitlDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ByteSwap.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Crc.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Decoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Encoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Register.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CodecExports.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Deflate64Register.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateEncoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeltaFilter.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ImplodeDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzfseDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzhDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Encoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Register.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaEncoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmsDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzOutWindow.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzxDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdEncoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdZip.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\QuantumDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar1Decoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar2Decoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Decoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Vm.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar5Decoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\RarCodecsRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ShrinkDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\XpressDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\XzDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\XzEncoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ZDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibDecoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibEncoder.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAesRegister.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha1.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha256.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAesReg.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\Pbkdf2HmacSha1.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\RandGen.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar20Crypto.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar5Aes.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\RarAes.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\WzAes.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipCrypto.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipStrong.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CRC.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CrcReg.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\DynLimBuf.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\IntToString.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\LzFindPrepare.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyMap.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyString.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyXml.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\NewHandler.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringConvert.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\UTFConvert.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\Wildcard.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\XzCrc64Init.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\XzCrc64Reg.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileDir.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileFind.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileIO.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileName.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariant.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariantUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Synchronization.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\System.cpp\" />\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\TimeUtils.cpp\" />\n    <ClCompile Include=\"SevenZip\\C\\7zBuf2.c\" />\n    <ClCompile Include=\"SevenZip\\C\\7zCrc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\7zStream.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Aes.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Alloc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Bcj2.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Bcj2Enc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Blake2s.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Bra.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Bra86.c\" />\n    <ClCompile Include=\"SevenZip\\C\\BwtSort.c\" />\n    <ClCompile Include=\"SevenZip\\C\\CpuArch.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Delta.c\" />\n    <ClCompile Include=\"SevenZip\\C\\HuffEnc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\LzFind.c\" />\n    <ClCompile Include=\"SevenZip\\C\\LzFindMt.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Lzma2Dec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Lzma2DecMt.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Lzma2Enc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\LzmaDec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\LzmaEnc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\MtCoder.c\" />\n    <ClCompile Include=\"SevenZip\\C\\MtDec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7aDec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7Dec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7Enc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd8.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd8Dec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Ppmd8Enc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\SwapBytes.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Threads.c\" />\n    <ClCompile Include=\"SevenZip\\C\\Xz.c\" />\n    <ClCompile Include=\"SevenZip\\C\\XzCrc64.c\" />\n    <ClCompile Include=\"SevenZip\\C\\XzDec.c\" />\n    <ClCompile Include=\"SevenZip\\C\\XzEnc.c\" />\n    <ClCompile Include=\"SevenZip\\C\\XzIn.c\" />\n    <ClCompile Include=\"Wrappers\\Sha1Wrapper.cpp\" />\n    <ClCompile Include=\"Wrappers\\Sha256Wrapper.cpp\" />\n    <ClCompile Include=\"Wrappers\\Sha512Wrapper.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\BrotliDecoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\BrotliEncoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\FastLzma2Encoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\LizardDecoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\LizardEncoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz4Decoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz4Encoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz5Decoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz5Encoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\ZstdDecoder.h\" />\n    <ClInclude Include=\"Extensions\\ZSCodecs\\ZstdEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zCompressionMode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zEncode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zFolderInStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHeader.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zOut.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zProperties.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zSpecStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zUpdate.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabBlockInStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHeader.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\DummyOutStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\FindSignature.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\HandlerOut.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\InStreamWithCRC.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithSha1.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ParseProperties.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\HandlerCont.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\HfsHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHeader.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisDecode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\Rar5Handler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarHeader.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarVol.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHeader.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarOut.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarUpdate.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\XzHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipAddCommon.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipCompressionMode.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHeader.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipIn.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipItem.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipOut.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipUpdate.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\InOutTempBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LockedStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MemBlocks.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OffsetStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OutMemStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressMt.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitlDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitlEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitmDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitmEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Const.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Crc.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Decoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Encoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateConst.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\HuffmanDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ImplodeDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzfseDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzhDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Encoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmsDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzOutWindow.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzxDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Mtf8.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdZip.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\QuantumDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar1Decoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar2Decoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Decoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Vm.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar5Decoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ShrinkDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\XpressDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\XzDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\XzEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ZDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibDecoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibEncoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha1.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha256.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Pbkdf2HmacSha1.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\RandGen.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar20Crypto.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar5Aes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\RarAes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Sha1Cls.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\WzAes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipCrypto.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipStrong.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\MyVersion.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\AutoPtr.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common0.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\DynamicBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\DynLimBuf.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer2.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyException.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyMap.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyXml.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantUtils.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\" />\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zBuf.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zCrc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zVersion.h\" />\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Aes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Bcj2.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Blake2.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Bra.h\" />\n    <ClInclude Include=\"SevenZip\\C\\BwtSort.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\" />\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Delta.h\" />\n    <ClInclude Include=\"SevenZip\\C\\HuffEnc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\LzFind.h\" />\n    <ClInclude Include=\"SevenZip\\C\\LzFindMt.h\" />\n    <ClInclude Include=\"SevenZip\\C\\LzHash.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Lzma2Dec.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Lzma2DecMt.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Lzma2Enc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\LzmaDec.h\" />\n    <ClInclude Include=\"SevenZip\\C\\LzmaEnc.h\" />\n    <ClInclude Include=\"SevenZip\\C\\MtCoder.h\" />\n    <ClInclude Include=\"SevenZip\\C\\MtDec.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Ppmd.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Ppmd7.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Ppmd8.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\" />\n    <ClInclude Include=\"SevenZip\\C\\RotateDefs.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sha1.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sha256.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sha512.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\" />\n    <ClInclude Include=\"SevenZip\\C\\SwapBytes.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\" />\n    <ClInclude Include=\"SevenZip\\C\\Xz.h\" />\n    <ClInclude Include=\"SevenZip\\C\\XzCrc64.h\" />\n    <ClInclude Include=\"SevenZip\\C\\XzEnc.h\" />\n    <ClInclude Include=\"Wrappers\\Sha1Wrapper.h\" />\n    <ClInclude Include=\"Wrappers\\Sha256Wrapper.h\" />\n    <ClInclude Include=\"Wrappers\\Sha512Wrapper.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Text Include=\"SevenZip\\CPP\\7zip\\Guid.txt\" />\n  </ItemGroup>\n  <Target Name=\"NanaZipCoreAesHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\AesOpt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreAesHardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' != 'x64'\">\n      <ClCompile Include=\"SevenZip\\C\\AesOpt.c\">\n        <Optimization Condition=\"'$(Configuration)' == 'Release'\">MaxSpeed</Optimization>\n      </ClCompile>\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreCrcHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\7zCrcOpt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreCrcHardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' != 'x64'\">\n      <ClCompile Include=\"SevenZip\\C\\7zCrcOpt.c\">\n        <Optimization Condition=\"'$(Configuration)' == 'Release'\">MaxSpeed</Optimization>\n      </ClCompile>\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreLzmaDecHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\LzmaDecOpt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreCrc64HardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\XzCrc64Opt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreCrc64HardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' != 'x64'\">\n      <ClCompile Include=\"SevenZip\\C\\XzCrc64Opt.c\">\n        <Optimization Condition=\"'$(Configuration)' == 'Release'\">MaxSpeed</Optimization>\n      </ClCompile>\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreLzFindOptHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\LzFindOpt.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreLzFindOptHardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' != 'x64'\">\n      <ClCompile Include=\"SevenZip\\C\\LzFindOpt.c\">\n        <Optimization Condition=\"'$(Configuration)' == 'Release'\">MaxSpeed</Optimization>\n      </ClCompile>\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreSortHardwareAccelerationBuildAssemblySource\" BeforeTargets=\"_MASM\">\n    <ItemGroup Condition=\"'$(Platform)' == 'x64'\">\n      <MASM Include=\"SevenZip\\ASM\\x86\\Sort.asm\" />\n    </ItemGroup>\n  </Target>\n  <Target Name=\"NanaZipCoreSortHardwareAccelerationBuildCSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup Condition=\"'$(Platform)' != 'x64'\">\n      <ClCompile Include=\"SevenZip\\C\\Sort.c\">\n        <Optimization Condition=\"'$(Configuration)' == 'Release'\">MaxSpeed</Optimization>\n      </ClCompile>\n    </ItemGroup>\n  </Target>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n  <Import Condition=\"'$(Platform)' == 'x64'\" Project=\"$(VCTargetsPath)\\BuildCustomizations\\masm.targets\" />\n</Project>\n"
  },
  {
    "path": "NanaZip.Core/NanaZip.Core.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"SevenZip\">\n      <UniqueIdentifier>{ab30c45f-b94f-4cef-95f7-b6c77366335e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\ASM\">\n      <UniqueIdentifier>{a93a8ba7-f371-436d-bdc5-103a6c339173}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\ASM\\x86\">\n      <UniqueIdentifier>{24120ed9-96c2-475f-8519-e4a8b7f774ca}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\C\">\n      <UniqueIdentifier>{26036cec-9a01-4a14-88fb-a44636eb8129}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\">\n      <UniqueIdentifier>{5a2d4169-869f-488f-99e7-af4abb9775b5}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Windows\">\n      <UniqueIdentifier>{27fa45ef-44fc-4fb5-a116-141f50012484}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\Common\">\n      <UniqueIdentifier>{e70030d6-67dd-4d5a-9d23-d563cd718846}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\">\n      <UniqueIdentifier>{1fff9892-c97d-4d92-baed-74fe78d19ca3}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Common\">\n      <UniqueIdentifier>{f262e8b8-fdaa-4667-93ef-f51068f4f29c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Crypto\">\n      <UniqueIdentifier>{a0f39159-fd1b-41e2-b742-cc3036a2c2b6}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Compress\">\n      <UniqueIdentifier>{18afff66-4965-4ff5-abf8-e1fb68f66d10}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\">\n      <UniqueIdentifier>{5a536b98-a491-47df-be57-27ce987713fb}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\">\n      <UniqueIdentifier>{dbcdee1b-b65c-4985-8471-57630b6e38e0}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\">\n      <UniqueIdentifier>{7a1f7ed3-5a5a-4aeb-8e17-587dbe3bf3fb}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\">\n      <UniqueIdentifier>{9ad1ca6a-b7bc-459f-8aef-34bb7f5ab107}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\">\n      <UniqueIdentifier>{96396a40-5b4f-4f95-8308-10e6123a39ea}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\">\n      <UniqueIdentifier>{5bf67f2d-0d63-4721-9ffe-bd44897e4ec7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\">\n      <UniqueIdentifier>{4cfb48c0-dd45-4e32-b37f-7b7e2751efc7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\">\n      <UniqueIdentifier>{0ca2474a-4c03-4e62-9856-ed9cc56a2c4c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\">\n      <UniqueIdentifier>{33335916-4969-451d-8a1b-cc918334dabb}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\">\n      <UniqueIdentifier>{fb6f25e6-0471-4b1c-88d9-c8728b3d1850}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\">\n      <UniqueIdentifier>{32a49a20-5234-406b-9d2c-f46e15aefbb9}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\">\n      <UniqueIdentifier>{dc789ffa-7db5-46a0-91e2-c2d6f1a5fe3e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Extensions\">\n      <UniqueIdentifier>{ad1ce36b-5416-4c51-bdd0-26e4d2afe6b5}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Extensions\\ZSCodecs\">\n      <UniqueIdentifier>{c1700c83-d324-448c-99e2-b2cb2b51d3ad}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Wrappers\">\n      <UniqueIdentifier>{7054b707-7fa9-4e3a-bc77-e5cc37eb9200}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"SevenZip\\ASM\\x86\\7zAsm.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\7zCrcOpt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\AesOpt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\LzFindOpt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\LzmaDecOpt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\Sort.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\ASM\\x86\\XzCrc64Opt.asm\">\n      <Filter>SevenZip\\ASM\\x86</Filter>\n    </None>\n    <None Include=\"SevenZip\\CPP\\7zip\\Archive\\Archive2.def\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </None>\n    <None Include=\"SevenZip\\C\\7zCrcOpt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </None>\n    <None Include=\"SevenZip\\C\\AesOpt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </None>\n    <None Include=\"SevenZip\\C\\LzFindOpt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </None>\n    <None Include=\"SevenZip\\C\\Sort.c\">\n      <Filter>SevenZip\\C</Filter>\n    </None>\n    <None Include=\"SevenZip\\C\\XzCrc64Opt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </None>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"SevenZip\\C\\7zStream.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Alloc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Bcj2.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Bra.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Bra86.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\CpuArch.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Delta.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Lzma2Dec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Lzma2DecMt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\LzmaDec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\MtDec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7Dec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Threads.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileDir.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileFind.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileIO.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\FileName.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariant.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\Synchronization.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\System.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CRC.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\IntToString.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyString.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\NewHandler.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringConvert.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\UTFConvert.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\Wildcard.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\PropId.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAesRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Register.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeltaFilter.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Register.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SplitHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zExtract.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\7zBuf2.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Bcj2Enc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Blake2s.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\BwtSort.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\HuffEnc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\LzFind.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\LzFindMt.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Lzma2Enc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\LzmaEnc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\MtCoder.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7aDec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd7Enc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd8.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd8Dec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Ppmd8Enc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\SwapBytes.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Xz.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\XzDec.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\XzEnc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\XzIn.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\CrcReg.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\DynLimBuf.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\LzFindPrepare.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyMap.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\MyXml.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\StringToInt.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\XzCrc64Init.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Common\\XzCrc64Reg.cpp\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\PropVariantUtils.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\Windows\\TimeUtils.cpp\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\InOutTempBuffer.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\MemBlocks.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OffsetStream.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\OutMemStream.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressMt.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BitlDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ByteSwap.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Crc.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Decoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Encoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Register.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Deflate64Register.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateEncoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ImplodeDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzfseDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzhDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Encoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaEncoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmsDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzOutWindow.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\LzxDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdEncoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdZip.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\QuantumDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar1Decoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar2Decoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Decoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Vm.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar5Decoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\RarCodecsRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ShrinkDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\XpressDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\XzDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\XzEncoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ZDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibDecoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibEncoder.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha1.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha256.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAesReg.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\Pbkdf2HmacSha1.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\RandGen.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar5Aes.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar20Crypto.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\RarAes.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\WzAes.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipCrypto.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipStrong.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zEncode.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zFolderInStream.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandlerOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHeader.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zProperties.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zUpdate.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabBlockInStream.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHeader.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Chm</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Chm</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\DummyOutStream.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\FindSignature.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\HandlerOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\InStreamWithCRC.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithSha1.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHeader.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisDecode.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\Rar5Handler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHandlerOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHeader.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarUpdate.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Udf</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Udf</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Wim</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimHandlerOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Wim</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Wim</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Wim</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipAddCommon.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHandlerOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipIn.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipItem.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipOut.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipRegister.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipUpdate.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ApfsHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ApmHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ArHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ArjHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Base64Handler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\Bz2Handler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ComHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\CpioHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\CramfsHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\DmgHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ElfHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ExtHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\FatHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\FlvHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\GptHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\GzHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\HandlerCont.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\HfsHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\IhexHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LpHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LzhHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LzmaHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MachoHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MbrHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MslzHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\MubHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\NtfsHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\PeHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\PpmdHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\QcowHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\RpmHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SparseHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SquashfsHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\SwfHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\UefiHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VdiHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VhdHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VhdxHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\VmdkHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\XarHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\XzHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ZHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Compress\\CodecExports.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\ArchiveExports.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\DllExports2.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\7zCrc.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\Aes.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\C\\XzCrc64.c\">\n      <Filter>SevenZip\\C</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdRegister.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliDecoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliEncoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliRegister.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\FastLzma2Register.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardDecoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardEncoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardRegister.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Decoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Encoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Register.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Decoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Encoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Register.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdEncoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\FastLzma2Encoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\BrotliHandler.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LizardHandler.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz4Handler.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\Lz5Handler.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\LzHandler.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdHandler.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\AvbHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"SevenZip\\CPP\\7zip\\Archive\\LvmHandler.cpp\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Wrappers\\Sha512Wrapper.cpp\">\n      <Filter>Wrappers</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Wrappers\\Sha256Wrapper.cpp\">\n      <Filter>Wrappers</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Wrappers\\Sha1Wrapper.cpp\">\n      <Filter>Wrappers</Filter>\n    </ClCompile>\n    <ClCompile Include=\"Extensions\\ZSCodecs\\ZstdDecoder.cpp\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"SevenZip\\C\\7zCrc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zTypes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zWindows.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Aes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Alloc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Bcj2.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Bra.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Compiler.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\CpuArch.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Delta.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Lzma2Dec.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Lzma2DecMt.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\LzmaDec.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\MtDec.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Ppmd.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Ppmd7.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Precomp.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\RotateDefs.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sha256.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Threads.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileDir.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileFind.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileIO.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\FileName.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Handle.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariant.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantConv.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Synchronization.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\System.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\Thread.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\TimeUtils.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\ComTry.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Defs.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\IntToString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyBuffer2.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyCom.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyException.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyLinux.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyString.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyTypes.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyUnknown.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyVector.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyWindows.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\NewHandler.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\UTFConvert.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Wildcard.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\ICoder.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IDecl.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IPassword.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IProgress.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\IStream.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\PropID.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CreateCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\CWrappers.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\FilterCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\InBuffer.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LimitedStreams.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodId.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OutBuffer.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterCodec.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamBinder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamObjects.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\StreamUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\VirtThread.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MethodProps.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\RegisterArc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\7zAes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\MyAes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\RandGen.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Bcj2Coder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BcjCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BranchMisc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\CopyCoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Decoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\IArchive.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zDecode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zCompressionMode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zHeader.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zProperties.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\CoderMixer2.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ItemNameUtils.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\MultiStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithCRC.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\HandlerOut.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zBuf.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Blake2.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\BwtSort.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\HuffEnc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\LzFind.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\LzFindMt.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Lzma2Enc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\LzmaEnc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\MtCoder.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Ppmd8.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sort.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\SwapBytes.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Xz.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\XzEnc.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\DynLimBuf.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyMap.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyXml.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\StringToInt.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sha1.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\XzCrc64.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\PropVariantUtils.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\InOutTempBuffer.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\LockedStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\MemBlocks.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OffsetStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\OutMemStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\ProgressMt.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Common\\UniqBlocks.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitlDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitlEncoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitmDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BitmEncoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Const.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Crc.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Decoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\BZip2Encoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateConst.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\DeflateEncoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\HuffmanDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ImplodeDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzfseDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzhDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzma2Encoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmaEncoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzmsDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzOutWindow.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Lzx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\LzxDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Mtf8.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdEncoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\PpmdZip.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\QuantumDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar1Decoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar2Decoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Decoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar3Vm.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\Rar5Decoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ShrinkDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\XpressDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\XzDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\XzEncoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ZDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibDecoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Compress\\ZlibEncoder.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Compress</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\LzHash.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha1.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\HmacSha256.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Pbkdf2HmacSha1.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar5Aes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Rar20Crypto.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\RarAes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\Sha1Cls.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\WzAes.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipCrypto.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Crypto\\ZipStrong.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Crypto</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zEncode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zFolderInStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zOut.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zSpecStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\7z\\7zUpdate.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\7z</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabBlockInStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabHeader.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\CabItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Cab\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Cab</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Chm</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\ChmIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Chm</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Chm\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Chm</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\DummyOutStream.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\FindSignature.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\InStreamWithCRC.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\OutStreamWithSha1.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Common\\ParseProperties.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoHeader.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\IsoItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Iso\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Iso</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisDecode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\NsisIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Nsis\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Nsis</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\Rar5Handler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarHeader.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\RarVol.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Rar\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Rar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarHeader.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarOut.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Tar\\TarUpdate.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Tar</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Udf</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Udf</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Udf\\UdfIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Udf</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Wim</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Wim</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Wim\\WimIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Wim</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\StdAfx.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipAddCommon.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipCompressionMode.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipHeader.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipIn.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipItem.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipOut.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\Zip\\ZipUpdate.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive\\Zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\HandlerCont.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\HfsHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\Archive\\XzHandler.h\">\n      <Filter>SevenZip\\CPP\\7zip\\Archive</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\7zVersion.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\AutoPtr.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\DynamicBuffer.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\7zip\\MyVersion.h\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Windows\\NtCheck.h\">\n      <Filter>SevenZip\\CPP\\Windows</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\MyInitGuid.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\BrotliDecoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\BrotliEncoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\LizardDecoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\LizardEncoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz4Decoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz4Encoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz5Decoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\Lz5Encoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\ZstdEncoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\FastLzma2Encoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\CPP\\Common\\Common0.h\">\n      <Filter>SevenZip\\CPP\\Common</Filter>\n    </ClInclude>\n    <ClInclude Include=\"SevenZip\\C\\Sha512.h\">\n      <Filter>SevenZip\\C</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Wrappers\\Sha512Wrapper.h\">\n      <Filter>Wrappers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Wrappers\\Sha256Wrapper.h\">\n      <Filter>Wrappers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Wrappers\\Sha1Wrapper.h\">\n      <Filter>Wrappers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"Extensions\\ZSCodecs\\ZstdDecoder.h\">\n      <Filter>Extensions\\ZSCodecs</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <Text Include=\"SevenZip\\CPP\\7zip\\Guid.txt\">\n      <Filter>SevenZip\\CPP\\7zip</Filter>\n    </Text>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Core/SevenZip/.gitignore",
    "content": "﻿!*"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zBuf.h",
    "content": "﻿/* 7zBuf.h -- Byte Buffer\n2023-03-04 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_7Z_BUF_H\n#define ZIP7_INC_7Z_BUF_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\ntypedef struct\n{\n  Byte *data;\n  size_t size;\n} CBuf;\n\nvoid Buf_Init(CBuf *p);\nint Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);\nvoid Buf_Free(CBuf *p, ISzAllocPtr alloc);\n\ntypedef struct\n{\n  Byte *data;\n  size_t size;\n  size_t pos;\n} CDynBuf;\n\nvoid DynBuf_Construct(CDynBuf *p);\nvoid DynBuf_SeekToBeg(CDynBuf *p);\nint DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);\nvoid DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zBuf2.c",
    "content": "﻿/* 7zBuf2.c -- Byte Buffer\n2017-04-03 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n#include \"7zBuf.h\"\n\nvoid DynBuf_Construct(CDynBuf *p)\n{\n  p->data = 0;\n  p->size = 0;\n  p->pos = 0;\n}\n\nvoid DynBuf_SeekToBeg(CDynBuf *p)\n{\n  p->pos = 0;\n}\n\nint DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc)\n{\n  if (size > p->size - p->pos)\n  {\n    size_t newSize = p->pos + size;\n    Byte *data;\n    newSize += newSize / 4;\n    data = (Byte *)ISzAlloc_Alloc(alloc, newSize);\n    if (!data)\n      return 0;\n    p->size = newSize;\n    if (p->pos != 0)\n      memcpy(data, p->data, p->pos);\n    ISzAlloc_Free(alloc, p->data);\n    p->data = data;\n  }\n  if (size != 0)\n  {\n    memcpy(p->data + p->pos, buf, size);\n    p->pos += size;\n  }\n  return 1;\n}\n\nvoid DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->data);\n  p->data = 0;\n  p->size = 0;\n  p->pos = 0;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zCrc.c",
    "content": "﻿/* 7zCrc.c -- CRC32 calculation and init\n2024-03-01 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"7zCrc.h\"\n#include \"CpuArch.h\"\n\n// for debug:\n// #define __ARM_FEATURE_CRC32 1\n\n#ifdef __ARM_FEATURE_CRC32\n// #pragma message(\"__ARM_FEATURE_CRC32\")\n#define Z7_CRC_HW_FORCE\n#endif\n\n// #define Z7_CRC_DEBUG_BE\n#ifdef Z7_CRC_DEBUG_BE\n#undef MY_CPU_LE\n#define MY_CPU_BE\n#endif\n\n#ifdef Z7_CRC_HW_FORCE\n  #define Z7_CRC_NUM_TABLES_USE  1\n#else\n#ifdef Z7_CRC_NUM_TABLES\n  #define Z7_CRC_NUM_TABLES_USE  Z7_CRC_NUM_TABLES\n#else\n  #define Z7_CRC_NUM_TABLES_USE  12\n#endif\n#endif\n\n#if Z7_CRC_NUM_TABLES_USE < 1\n  #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES\n#endif\n\n#if defined(MY_CPU_LE) || (Z7_CRC_NUM_TABLES_USE == 1)\n  #define Z7_CRC_NUM_TABLES_TOTAL  Z7_CRC_NUM_TABLES_USE\n#else\n  #define Z7_CRC_NUM_TABLES_TOTAL  (Z7_CRC_NUM_TABLES_USE + 1)\n#endif\n\n#ifndef Z7_CRC_HW_FORCE\n\n#if Z7_CRC_NUM_TABLES_USE == 1 \\\n   || (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))\n#define CRC_UPDATE_BYTE_2(crc, b)   (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n#define Z7_CRC_UPDATE_T1_FUNC_NAME  CrcUpdateGT1\nstatic UInt32 Z7_FASTCALL Z7_CRC_UPDATE_T1_FUNC_NAME(UInt32 v, const void *data, size_t size)\n{\n  const UInt32 *table = g_CrcTable;\n  const Byte *p = (const Byte *)data;\n  const Byte *lim = p + size;\n  for (; p != lim; p++)\n    v = CRC_UPDATE_BYTE_2(v, *p);\n  return v;\n}\n#endif\n\n\n#if Z7_CRC_NUM_TABLES_USE != 1\n#ifndef MY_CPU_BE\n  #define FUNC_NAME_LE_2(s)   CrcUpdateT ## s\n  #define FUNC_NAME_LE_1(s)   FUNC_NAME_LE_2(s)\n  #define FUNC_NAME_LE        FUNC_NAME_LE_1(Z7_CRC_NUM_TABLES_USE)\n  UInt32 Z7_FASTCALL FUNC_NAME_LE (UInt32 v, const void *data, size_t size, const UInt32 *table);\n#endif\n#ifndef MY_CPU_LE\n  #define FUNC_NAME_BE_2(s)   CrcUpdateT1_BeT ## s\n  #define FUNC_NAME_BE_1(s)   FUNC_NAME_BE_2(s)\n  #define FUNC_NAME_BE        FUNC_NAME_BE_1(Z7_CRC_NUM_TABLES_USE)\n  UInt32 Z7_FASTCALL FUNC_NAME_BE (UInt32 v, const void *data, size_t size, const UInt32 *table);\n#endif\n#endif\n\n#endif // Z7_CRC_HW_FORCE\n\n/* ---------- hardware CRC ---------- */\n\n#ifdef MY_CPU_LE\n\n#if defined(MY_CPU_ARM_OR_ARM64)\n// #pragma message(\"ARM*\")\n\n  #if (defined(__clang__) && (__clang_major__ >= 3)) \\\n     || defined(__GNUC__) && (__GNUC__ >= 6) && defined(MY_CPU_ARM64) \\\n     || defined(__GNUC__) && (__GNUC__ >= 8)\n      #if !defined(__ARM_FEATURE_CRC32)\n//        #pragma message(\"!defined(__ARM_FEATURE_CRC32)\")\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n        #define __ARM_FEATURE_CRC32 1\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n        #define Z7_ARM_FEATURE_CRC32_WAS_SET\n        #if defined(__clang__)\n          #if defined(MY_CPU_ARM64)\n            #define ATTRIB_CRC __attribute__((__target__(\"crc\")))\n          #else\n            #define ATTRIB_CRC __attribute__((__target__(\"armv8-a,crc\")))\n          #endif\n        #else\n          #if defined(MY_CPU_ARM64)\n#if !defined(Z7_GCC_VERSION) || (Z7_GCC_VERSION >= 60000)\n            #define ATTRIB_CRC __attribute__((__target__(\"+crc\")))\n#endif\n          #else\n#if !defined(Z7_GCC_VERSION) || (__GNUC__  >= 8)\n#if defined(__ARM_FP) && __GNUC__ >= 8\n// for -mfloat-abi=hard: similar to <arm_acle.h>\n            #define ATTRIB_CRC __attribute__((__target__(\"arch=armv8-a+crc+simd\")))\n#else\n            #define ATTRIB_CRC __attribute__((__target__(\"arch=armv8-a+crc\")))\n#endif\n#endif\n          #endif\n        #endif\n      #endif\n      #if defined(__ARM_FEATURE_CRC32)\n      // #pragma message(\"<arm_acle.h>\")\n/*\narm_acle.h (GGC):\n    before Nov 17, 2017:\n#ifdef __ARM_FEATURE_CRC32\n\n    Nov 17, 2017: gcc10.0  (gcc 9.2.0) checked\"\n#if __ARM_ARCH >= 8\n#pragma GCC target (\"arch=armv8-a+crc\")\n\n    Aug 22, 2019: GCC 8.4?, 9.2.1, 10.1:\n#ifdef __ARM_FEATURE_CRC32\n#ifdef __ARM_FP\n#pragma GCC target (\"arch=armv8-a+crc+simd\")\n#else\n#pragma GCC target (\"arch=armv8-a+crc\")\n#endif\n*/\n#if defined(__ARM_ARCH) && __ARM_ARCH < 8\n#if defined(Z7_GCC_VERSION) && (__GNUC__ ==   8) && (Z7_GCC_VERSION <  80400) \\\n || defined(Z7_GCC_VERSION) && (__GNUC__ ==   9) && (Z7_GCC_VERSION <  90201) \\\n || defined(Z7_GCC_VERSION) && (__GNUC__ ==  10) && (Z7_GCC_VERSION < 100100)\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n// #pragma message(\"#define __ARM_ARCH 8\")\n#undef  __ARM_ARCH\n#define __ARM_ARCH 8\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif\n#endif\n        #define Z7_CRC_HW_USE\n        #include <arm_acle.h>\n      #endif\n  #elif defined(_MSC_VER)\n    #if defined(MY_CPU_ARM64)\n    #if (_MSC_VER >= 1910)\n    #ifdef __clang__\n       // #define Z7_CRC_HW_USE\n       // #include <arm_acle.h>\n    #else\n       #define Z7_CRC_HW_USE\n       #include <intrin.h>\n    #endif\n    #endif\n    #endif\n  #endif\n\n#else // non-ARM*\n\n// #define Z7_CRC_HW_USE // for debug : we can test HW-branch of code\n#ifdef Z7_CRC_HW_USE\n#include \"7zCrcEmu.h\"\n#endif\n\n#endif // non-ARM*\n\n\n\n#if defined(Z7_CRC_HW_USE)\n\n// #pragma message(\"USE ARM HW CRC\")\n\n#ifdef MY_CPU_64BIT\n  #define CRC_HW_WORD_TYPE  UInt64\n  #define CRC_HW_WORD_FUNC  __crc32d\n#else\n  #define CRC_HW_WORD_TYPE  UInt32\n  #define CRC_HW_WORD_FUNC  __crc32w\n#endif\n\n#define CRC_HW_UNROLL_BYTES (sizeof(CRC_HW_WORD_TYPE) * 4)\n\n#ifdef ATTRIB_CRC\n  ATTRIB_CRC\n#endif\nZ7_NO_INLINE\n#ifdef Z7_CRC_HW_FORCE\n         UInt32 Z7_FASTCALL CrcUpdate\n#else\n  static UInt32 Z7_FASTCALL CrcUpdate_HW\n#endif\n    (UInt32 v, const void *data, size_t size)\n{\n  const Byte *p = (const Byte *)data;\n  for (; size != 0 && ((unsigned)(ptrdiff_t)p & (CRC_HW_UNROLL_BYTES - 1)) != 0; size--)\n    v = __crc32b(v, *p++);\n  if (size >= CRC_HW_UNROLL_BYTES)\n  {\n    const Byte *lim = p + size;\n    size &= CRC_HW_UNROLL_BYTES - 1;\n    lim -= size;\n    do\n    {\n      v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));\n      v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));\n      p += 2 * sizeof(CRC_HW_WORD_TYPE);\n      v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p));\n      v = CRC_HW_WORD_FUNC(v, *(const CRC_HW_WORD_TYPE *)(const void *)(p + sizeof(CRC_HW_WORD_TYPE)));\n      p += 2 * sizeof(CRC_HW_WORD_TYPE);\n    }\n    while (p != lim);\n  }\n  \n  for (; size != 0; size--)\n    v = __crc32b(v, *p++);\n\n  return v;\n}\n\n#ifdef Z7_ARM_FEATURE_CRC32_WAS_SET\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n#undef __ARM_FEATURE_CRC32\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#undef Z7_ARM_FEATURE_CRC32_WAS_SET\n#endif\n\n#endif // defined(Z7_CRC_HW_USE)\n#endif // MY_CPU_LE\n\n\n\n#ifndef Z7_CRC_HW_FORCE\n\n#if defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)\n/*\ntypedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_WITH_TABLE_FUNC)\n    (UInt32 v, const void *data, size_t size, const UInt32 *table);\nZ7_CRC_UPDATE_WITH_TABLE_FUNC g_CrcUpdate;\n*/\nstatic unsigned g_Crc_Algo;\n#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))\nstatic unsigned g_Crc_Be;\n#endif\n#endif // defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME)\n\n\n\nZ7_NO_INLINE\n#ifdef Z7_CRC_HW_USE\n  static UInt32 Z7_FASTCALL CrcUpdate_Base\n#else\n         UInt32 Z7_FASTCALL CrcUpdate\n#endif\n    (UInt32 crc, const void *data, size_t size)\n{\n#if Z7_CRC_NUM_TABLES_USE == 1\n    return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);\n#else // Z7_CRC_NUM_TABLES_USE != 1\n#ifdef Z7_CRC_UPDATE_T1_FUNC_NAME\n  if (g_Crc_Algo == 1)\n    return Z7_CRC_UPDATE_T1_FUNC_NAME(crc, data, size);\n#endif\n\n#ifdef MY_CPU_LE\n    return FUNC_NAME_LE(crc, data, size, g_CrcTable);\n#elif defined(MY_CPU_BE)\n    return FUNC_NAME_BE(crc, data, size, g_CrcTable);\n#else\n  if (g_Crc_Be)\n    return FUNC_NAME_BE(crc, data, size, g_CrcTable);\n  else\n    return FUNC_NAME_LE(crc, data, size, g_CrcTable);\n#endif\n#endif // Z7_CRC_NUM_TABLES_USE != 1\n}\n\n\n#ifdef Z7_CRC_HW_USE\nZ7_NO_INLINE\nUInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size)\n{\n  if (g_Crc_Algo == 0)\n    return CrcUpdate_HW(crc, data, size);\n  return CrcUpdate_Base(crc, data, size);\n}\n#endif\n\n#endif // !defined(Z7_CRC_HW_FORCE)\n\n\n\nUInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size)\n{\n  return CrcUpdate(CRC_INIT_VAL, data, size) ^ CRC_INIT_VAL;\n}\n\n\nMY_ALIGN(64)\nUInt32 g_CrcTable[256 * Z7_CRC_NUM_TABLES_TOTAL];\n\n\nvoid Z7_FASTCALL CrcGenerateTable(void)\n{\n  UInt32 i;\n  for (i = 0; i < 256; i++)\n  {\n#if defined(Z7_CRC_HW_FORCE)\n    g_CrcTable[i] = __crc32b(i, 0);\n#else\n    #define kCrcPoly 0xEDB88320\n    UInt32 r = i;\n    unsigned j;\n    for (j = 0; j < 8; j++)\n      r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));\n    g_CrcTable[i] = r;\n#endif\n  }\n  for (i = 256; i < 256 * Z7_CRC_NUM_TABLES_USE; i++)\n  {\n    const UInt32 r = g_CrcTable[(size_t)i - 256];\n    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);\n  }\n\n#if !defined(Z7_CRC_HW_FORCE) && \\\n    (defined(Z7_CRC_HW_USE) || defined(Z7_CRC_UPDATE_T1_FUNC_NAME) || defined(MY_CPU_BE))\n\n#if Z7_CRC_NUM_TABLES_USE <= 1\n    g_Crc_Algo = 1;\n#else // Z7_CRC_NUM_TABLES_USE <= 1\n\n#if defined(MY_CPU_LE)\n    g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;\n#else // !defined(MY_CPU_LE)\n  {\n#ifndef MY_CPU_BE\n    UInt32 k = 0x01020304;\n    const Byte *p = (const Byte *)&k;\n    if (p[0] == 4 && p[1] == 3)\n      g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;\n    else if (p[0] != 1 || p[1] != 2)\n      g_Crc_Algo = 1;\n    else\n#endif // MY_CPU_BE\n    {\n      for (i = 256 * Z7_CRC_NUM_TABLES_TOTAL - 1; i >= 256; i--)\n      {\n        const UInt32 x = g_CrcTable[(size_t)i - 256];\n        g_CrcTable[i] = Z7_BSWAP32(x);\n      }\n#if defined(Z7_CRC_UPDATE_T1_FUNC_NAME)\n      g_Crc_Algo = Z7_CRC_NUM_TABLES_USE;\n#endif\n#if (!defined(MY_CPU_LE) && !defined(MY_CPU_BE))\n      g_Crc_Be = 1;\n#endif\n    }\n  }\n#endif  // !defined(MY_CPU_LE)\n\n#ifdef MY_CPU_LE\n#ifdef Z7_CRC_HW_USE\n  if (CPU_IsSupported_CRC32())\n    g_Crc_Algo = 0;\n#endif // Z7_CRC_HW_USE\n#endif // MY_CPU_LE\n\n#endif // Z7_CRC_NUM_TABLES_USE <= 1\n#endif // g_Crc_Algo was declared\n}\n\nZ7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo)\n{\n  if (algo == 0)\n    return &CrcUpdate;\n\n#if defined(Z7_CRC_HW_USE)\n  if (algo == sizeof(CRC_HW_WORD_TYPE) * 8)\n  {\n#ifdef Z7_CRC_HW_FORCE\n    return &CrcUpdate;\n#else\n    if (g_Crc_Algo == 0)\n      return &CrcUpdate_HW;\n#endif\n  }\n#endif\n\n#ifndef Z7_CRC_HW_FORCE\n  if (algo == Z7_CRC_NUM_TABLES_USE)\n    return\n  #ifdef Z7_CRC_HW_USE\n      &CrcUpdate_Base;\n  #else\n      &CrcUpdate;\n  #endif\n#endif\n\n  return NULL;\n}\n\n#undef kCrcPoly\n#undef Z7_CRC_NUM_TABLES_USE\n#undef Z7_CRC_NUM_TABLES_TOTAL\n#undef CRC_UPDATE_BYTE_2\n#undef FUNC_NAME_LE_2\n#undef FUNC_NAME_LE_1\n#undef FUNC_NAME_LE\n#undef FUNC_NAME_BE_2\n#undef FUNC_NAME_BE_1\n#undef FUNC_NAME_BE\n\n#undef CRC_HW_UNROLL_BYTES\n#undef CRC_HW_WORD_FUNC\n#undef CRC_HW_WORD_TYPE\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zCrc.h",
    "content": "﻿/* 7zCrc.h -- CRC32 calculation\n2024-01-22 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_7Z_CRC_H\n#define ZIP7_INC_7Z_CRC_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\nextern UInt32 g_CrcTable[];\n\n/* Call CrcGenerateTable one time before other CRC functions */\nvoid Z7_FASTCALL CrcGenerateTable(void);\n\n#define CRC_INIT_VAL 0xFFFFFFFF\n#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)\n#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n\nUInt32 Z7_FASTCALL CrcUpdate(UInt32 crc, const void *data, size_t size);\nUInt32 Z7_FASTCALL CrcCalc(const void *data, size_t size);\n\ntypedef UInt32 (Z7_FASTCALL *Z7_CRC_UPDATE_FUNC)(UInt32 v, const void *data, size_t size);\nZ7_CRC_UPDATE_FUNC z7_GetFunc_CrcUpdate(unsigned algo);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zCrcOpt.c",
    "content": "﻿/* 7zCrcOpt.c -- CRC32 calculation (optimized functions)\n2023-12-07 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"CpuArch.h\"\n\n#if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1\n\n// for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu\n// #define Z7_CRC_DEBUG_BE\n#ifdef Z7_CRC_DEBUG_BE\n#undef MY_CPU_LE\n#define MY_CPU_BE\n#endif\n\n// the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c\n#ifdef Z7_CRC_NUM_TABLES\n#define Z7_CRC_NUM_TABLES_USE  Z7_CRC_NUM_TABLES\n#else\n#define Z7_CRC_NUM_TABLES_USE  12\n#endif\n\n#if Z7_CRC_NUM_TABLES_USE % 4     || \\\n    Z7_CRC_NUM_TABLES_USE < 4 * 1 || \\\n    Z7_CRC_NUM_TABLES_USE > 4 * 6\n  #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES\n#endif\n\n\n#ifndef MY_CPU_BE\n\n#define CRC_UPDATE_BYTE_2(crc, b)  (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n\n#define Q(n, d) \\\n    ( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \\\n    ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )\n\n#define R(a)  *((const UInt32 *)(const void *)p + (a))\n\n#define CRC_FUNC_PRE_LE2(step) \\\nUInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)\n\n#define CRC_FUNC_PRE_LE(step)   \\\n        CRC_FUNC_PRE_LE2(step); \\\n        CRC_FUNC_PRE_LE2(step)\n\nCRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)\n{\n  const Byte *p = (const Byte *)data;\n  const Byte *lim;\n  for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)\n    v = CRC_UPDATE_BYTE_2(v, *p);\n  lim = p + size;\n  if (size >= Z7_CRC_NUM_TABLES_USE)\n  {\n    lim -= Z7_CRC_NUM_TABLES_USE;\n    do\n    {\n      v ^= R(0);\n      {\n#if Z7_CRC_NUM_TABLES_USE == 1 * 4\n        v = Q(0, v);\n#else\n#define U2(r, op) \\\n        { d = R(r);  x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }\n        UInt32 d, x;\n        U2(1, =)\n#if Z7_CRC_NUM_TABLES_USE >= 3 * 4\n#define U(r)  U2(r, ^=)\n        U(2)\n#if Z7_CRC_NUM_TABLES_USE >= 4 * 4\n        U(3)\n#if Z7_CRC_NUM_TABLES_USE >= 5 * 4\n        U(4)\n#if Z7_CRC_NUM_TABLES_USE >= 6 * 4\n        U(5)\n#if Z7_CRC_NUM_TABLES_USE >= 7 * 4\n#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES\n#endif\n#endif\n#endif\n#endif\n#endif\n#undef U\n#undef U2\n        v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);\n#endif\n      }\n      p += Z7_CRC_NUM_TABLES_USE;\n    }\n    while (p <= lim);\n    lim += Z7_CRC_NUM_TABLES_USE;\n  }\n  for (; p < lim; p++)\n    v = CRC_UPDATE_BYTE_2(v, *p);\n  return v;\n}\n\n#undef CRC_UPDATE_BYTE_2\n#undef R\n#undef Q\n#undef CRC_FUNC_PRE_LE\n#undef CRC_FUNC_PRE_LE2\n\n#endif\n\n\n\n\n#ifndef MY_CPU_LE\n\n#define CRC_UPDATE_BYTE_2_BE(crc, b)  (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8))\n\n#define Q(n, d) \\\n    ( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \\\n    ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )\n\n#ifdef Z7_CRC_DEBUG_BE\n  #define R(a)  GetBe32a((const UInt32 *)(const void *)p + (a))\n#else\n  #define R(a)         *((const UInt32 *)(const void *)p + (a))\n#endif\n\n\n#define CRC_FUNC_PRE_BE2(step) \\\nUInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)\n\n#define CRC_FUNC_PRE_BE(step)   \\\n        CRC_FUNC_PRE_BE2(step); \\\n        CRC_FUNC_PRE_BE2(step)\n\nCRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)\n{\n  const Byte *p = (const Byte *)data;\n  const Byte *lim;\n  table += 0x100;\n  v = Z7_BSWAP32(v);\n  for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)\n    v = CRC_UPDATE_BYTE_2_BE(v, *p);\n  lim = p + size;\n  if (size >= Z7_CRC_NUM_TABLES_USE)\n  {\n    lim -= Z7_CRC_NUM_TABLES_USE;\n    do\n    {\n      v ^= R(0);\n      {\n#if Z7_CRC_NUM_TABLES_USE == 1 * 4\n        v = Q(0, v);\n#else\n#define U2(r, op) \\\n        { d = R(r);  x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }\n        UInt32 d, x;\n        U2(1, =)\n#if Z7_CRC_NUM_TABLES_USE >= 3 * 4\n#define U(r)  U2(r, ^=)\n        U(2)\n#if Z7_CRC_NUM_TABLES_USE >= 4 * 4\n        U(3)\n#if Z7_CRC_NUM_TABLES_USE >= 5 * 4\n        U(4)\n#if Z7_CRC_NUM_TABLES_USE >= 6 * 4\n        U(5)\n#if Z7_CRC_NUM_TABLES_USE >= 7 * 4\n#error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES\n#endif\n#endif\n#endif\n#endif\n#endif\n#undef U\n#undef U2\n        v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);\n#endif\n      }\n      p += Z7_CRC_NUM_TABLES_USE;\n    }\n    while (p <= lim);\n    lim += Z7_CRC_NUM_TABLES_USE;\n  }\n  for (; p < lim; p++)\n    v = CRC_UPDATE_BYTE_2_BE(v, *p);\n  return Z7_BSWAP32(v);\n}\n\n#undef CRC_UPDATE_BYTE_2_BE\n#undef R\n#undef Q\n#undef CRC_FUNC_PRE_BE\n#undef CRC_FUNC_PRE_BE2\n\n#endif\n#undef Z7_CRC_NUM_TABLES_USE\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zStream.c",
    "content": "﻿/* 7zStream.c -- 7z Stream functions\n2023-04-02 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n#include \"7zTypes.h\"\n\n\nSRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize)\n{\n  size_t size = *processedSize;\n  *processedSize = 0;\n  while (size != 0)\n  {\n    size_t cur = size;\n    const SRes res = ISeqInStream_Read(stream, buf, &cur);\n    *processedSize += cur;\n    buf = (void *)((Byte *)buf + cur);\n    size -= cur;\n    if (res != SZ_OK)\n      return res;\n    if (cur == 0)\n      return SZ_OK;\n  }\n  return SZ_OK;\n}\n\n/*\nSRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType)\n{\n  while (size != 0)\n  {\n    size_t processed = size;\n    RINOK(ISeqInStream_Read(stream, buf, &processed))\n    if (processed == 0)\n      return errorType;\n    buf = (void *)((Byte *)buf + processed);\n    size -= processed;\n  }\n  return SZ_OK;\n}\n\nSRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size)\n{\n  return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);\n}\n*/\n\n\nSRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf)\n{\n  size_t processed = 1;\n  RINOK(ISeqInStream_Read(stream, buf, &processed))\n  return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;\n}\n\n\n\nSRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset)\n{\n  Int64 t = (Int64)offset;\n  return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);\n}\n\nSRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size)\n{\n  const void *lookBuf;\n  if (*size == 0)\n    return SZ_OK;\n  RINOK(ILookInStream_Look(stream, &lookBuf, size))\n  memcpy(buf, lookBuf, *size);\n  return ILookInStream_Skip(stream, *size);\n}\n\nSRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType)\n{\n  while (size != 0)\n  {\n    size_t processed = size;\n    RINOK(ILookInStream_Read(stream, buf, &processed))\n    if (processed == 0)\n      return errorType;\n    buf = (void *)((Byte *)buf + processed);\n    size -= processed;\n  }\n  return SZ_OK;\n}\n\nSRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size)\n{\n  return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);\n}\n\n\n\n#define GET_LookToRead2  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLookToRead2)\n\nstatic SRes LookToRead2_Look_Lookahead(ILookInStreamPtr pp, const void **buf, size_t *size)\n{\n  SRes res = SZ_OK;\n  GET_LookToRead2\n  size_t size2 = p->size - p->pos;\n  if (size2 == 0 && *size != 0)\n  {\n    p->pos = 0;\n    p->size = 0;\n    size2 = p->bufSize;\n    res = ISeekInStream_Read(p->realStream, p->buf, &size2);\n    p->size = size2;\n  }\n  if (*size > size2)\n    *size = size2;\n  *buf = p->buf + p->pos;\n  return res;\n}\n\nstatic SRes LookToRead2_Look_Exact(ILookInStreamPtr pp, const void **buf, size_t *size)\n{\n  SRes res = SZ_OK;\n  GET_LookToRead2\n  size_t size2 = p->size - p->pos;\n  if (size2 == 0 && *size != 0)\n  {\n    p->pos = 0;\n    p->size = 0;\n    if (*size > p->bufSize)\n      *size = p->bufSize;\n    res = ISeekInStream_Read(p->realStream, p->buf, size);\n    size2 = p->size = *size;\n  }\n  if (*size > size2)\n    *size = size2;\n  *buf = p->buf + p->pos;\n  return res;\n}\n\nstatic SRes LookToRead2_Skip(ILookInStreamPtr pp, size_t offset)\n{\n  GET_LookToRead2\n  p->pos += offset;\n  return SZ_OK;\n}\n\nstatic SRes LookToRead2_Read(ILookInStreamPtr pp, void *buf, size_t *size)\n{\n  GET_LookToRead2\n  size_t rem = p->size - p->pos;\n  if (rem == 0)\n    return ISeekInStream_Read(p->realStream, buf, size);\n  if (rem > *size)\n    rem = *size;\n  memcpy(buf, p->buf + p->pos, rem);\n  p->pos += rem;\n  *size = rem;\n  return SZ_OK;\n}\n\nstatic SRes LookToRead2_Seek(ILookInStreamPtr pp, Int64 *pos, ESzSeek origin)\n{\n  GET_LookToRead2\n  p->pos = p->size = 0;\n  return ISeekInStream_Seek(p->realStream, pos, origin);\n}\n\nvoid LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)\n{\n  p->vt.Look = lookahead ?\n      LookToRead2_Look_Lookahead :\n      LookToRead2_Look_Exact;\n  p->vt.Skip = LookToRead2_Skip;\n  p->vt.Read = LookToRead2_Read;\n  p->vt.Seek = LookToRead2_Seek;\n}\n\n\n\nstatic SRes SecToLook_Read(ISeqInStreamPtr pp, void *buf, size_t *size)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToLook)\n  return LookInStream_LookRead(p->realStream, buf, size);\n}\n\nvoid SecToLook_CreateVTable(CSecToLook *p)\n{\n  p->vt.Read = SecToLook_Read;\n}\n\nstatic SRes SecToRead_Read(ISeqInStreamPtr pp, void *buf, size_t *size)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSecToRead)\n  return ILookInStream_Read(p->realStream, buf, size);\n}\n\nvoid SecToRead_CreateVTable(CSecToRead *p)\n{\n  p->vt.Read = SecToRead_Read;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zTypes.h",
    "content": "﻿/* 7zTypes.h -- Basic types\n2024-01-24 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_7Z_TYPES_H\n#define ZIP7_7Z_TYPES_H\n\n#ifdef _WIN32\n/* #include <windows.h> */\n#else\n#include <errno.h>\n#endif\n\n#include <stddef.h>\n\n#ifndef EXTERN_C_BEGIN\n#ifdef __cplusplus\n#define EXTERN_C_BEGIN extern \"C\" {\n#define EXTERN_C_END }\n#else\n#define EXTERN_C_BEGIN\n#define EXTERN_C_END\n#endif\n#endif\n\nEXTERN_C_BEGIN\n\n#define SZ_OK 0\n\n#define SZ_ERROR_DATA 1\n#define SZ_ERROR_MEM 2\n#define SZ_ERROR_CRC 3\n#define SZ_ERROR_UNSUPPORTED 4\n#define SZ_ERROR_PARAM 5\n#define SZ_ERROR_INPUT_EOF 6\n#define SZ_ERROR_OUTPUT_EOF 7\n#define SZ_ERROR_READ 8\n#define SZ_ERROR_WRITE 9\n#define SZ_ERROR_PROGRESS 10\n#define SZ_ERROR_FAIL 11\n#define SZ_ERROR_THREAD 12\n\n#define SZ_ERROR_ARCHIVE 16\n#define SZ_ERROR_NO_ARCHIVE 17\n\ntypedef int SRes;\n\n\n#ifdef _MSC_VER\n  #if _MSC_VER > 1200\n    #define MY_ALIGN(n) __declspec(align(n))\n  #else\n    #define MY_ALIGN(n)\n  #endif\n#else\n  /*\n  // C11/C++11:\n  #include <stdalign.h>\n  #define MY_ALIGN(n) alignas(n)\n  */\n  #define MY_ALIGN(n) __attribute__ ((aligned(n)))\n#endif\n\n\n#ifdef _WIN32\n\n/* typedef DWORD WRes; */\ntypedef unsigned WRes;\n#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)\n\n// #define MY_HRES_ERROR_INTERNAL_ERROR  MY_SRes_HRESULT_FROM_WRes(ERROR_INTERNAL_ERROR)\n\n#else // _WIN32\n\n// #define ENV_HAVE_LSTAT\ntypedef int WRes;\n\n// (FACILITY_ERRNO = 0x800) is 7zip's FACILITY constant to represent (errno) errors in HRESULT\n#define MY_FACILITY_ERRNO  0x800\n#define MY_FACILITY_WIN32  7\n#define MY_FACILITY_WRes  MY_FACILITY_ERRNO\n\n#define MY_HRESULT_FROM_errno_CONST_ERROR(x) ((HRESULT)( \\\n          ( (HRESULT)(x) & 0x0000FFFF) \\\n          | (MY_FACILITY_WRes << 16)  \\\n          | (HRESULT)0x80000000 ))\n\n#define MY_SRes_HRESULT_FROM_WRes(x) \\\n  ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : MY_HRESULT_FROM_errno_CONST_ERROR(x))\n\n// we call macro HRESULT_FROM_WIN32 for system errors (WRes) that are (errno)\n#define HRESULT_FROM_WIN32(x) MY_SRes_HRESULT_FROM_WRes(x)\n\n/*\n#define ERROR_FILE_NOT_FOUND             2L\n#define ERROR_ACCESS_DENIED              5L\n#define ERROR_NO_MORE_FILES              18L\n#define ERROR_LOCK_VIOLATION             33L\n#define ERROR_FILE_EXISTS                80L\n#define ERROR_DISK_FULL                  112L\n#define ERROR_NEGATIVE_SEEK              131L\n#define ERROR_ALREADY_EXISTS             183L\n#define ERROR_DIRECTORY                  267L\n#define ERROR_TOO_MANY_POSTS             298L\n\n#define ERROR_INTERNAL_ERROR             1359L\n#define ERROR_INVALID_REPARSE_DATA       4392L\n#define ERROR_REPARSE_TAG_INVALID        4393L\n#define ERROR_REPARSE_TAG_MISMATCH       4394L\n*/\n\n// we use errno equivalents for some WIN32 errors:\n\n#define ERROR_INVALID_PARAMETER     EINVAL\n#define ERROR_INVALID_FUNCTION      EINVAL\n#define ERROR_ALREADY_EXISTS        EEXIST\n#define ERROR_FILE_EXISTS           EEXIST\n#define ERROR_PATH_NOT_FOUND        ENOENT\n#define ERROR_FILE_NOT_FOUND        ENOENT\n#define ERROR_DISK_FULL             ENOSPC\n// #define ERROR_INVALID_HANDLE        EBADF\n\n// we use FACILITY_WIN32 for errors that has no errno equivalent\n// Too many posts were made to a semaphore.\n#define ERROR_TOO_MANY_POSTS        ((HRESULT)0x8007012AL)\n#define ERROR_INVALID_REPARSE_DATA  ((HRESULT)0x80071128L)\n#define ERROR_REPARSE_TAG_INVALID   ((HRESULT)0x80071129L)\n\n// if (MY_FACILITY_WRes != FACILITY_WIN32),\n// we use FACILITY_WIN32 for COM errors:\n#define E_OUTOFMEMORY               ((HRESULT)0x8007000EL)\n#define E_INVALIDARG                ((HRESULT)0x80070057L)\n#define MY_E_ERROR_NEGATIVE_SEEK    ((HRESULT)0x80070083L)\n\n/*\n// we can use FACILITY_ERRNO for some COM errors, that have errno equivalents:\n#define E_OUTOFMEMORY             MY_HRESULT_FROM_errno_CONST_ERROR(ENOMEM)\n#define E_INVALIDARG              MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL)\n#define MY_E_ERROR_NEGATIVE_SEEK  MY_HRESULT_FROM_errno_CONST_ERROR(EINVAL)\n*/\n\n#define TEXT(quote) quote\n\n#define FILE_ATTRIBUTE_READONLY       0x0001\n#define FILE_ATTRIBUTE_HIDDEN         0x0002\n#define FILE_ATTRIBUTE_SYSTEM         0x0004\n#define FILE_ATTRIBUTE_DIRECTORY      0x0010\n#define FILE_ATTRIBUTE_ARCHIVE        0x0020\n#define FILE_ATTRIBUTE_DEVICE         0x0040\n#define FILE_ATTRIBUTE_NORMAL         0x0080\n#define FILE_ATTRIBUTE_TEMPORARY      0x0100\n#define FILE_ATTRIBUTE_SPARSE_FILE    0x0200\n#define FILE_ATTRIBUTE_REPARSE_POINT  0x0400\n#define FILE_ATTRIBUTE_COMPRESSED     0x0800\n#define FILE_ATTRIBUTE_OFFLINE        0x1000\n#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x2000\n#define FILE_ATTRIBUTE_ENCRYPTED      0x4000\n\n#define FILE_ATTRIBUTE_UNIX_EXTENSION 0x8000   /* trick for Unix */\n\n#endif\n\n\n#ifndef RINOK\n#define RINOK(x) { const int _result_ = (x); if (_result_ != 0) return _result_; }\n#endif\n\n#ifndef RINOK_WRes\n#define RINOK_WRes(x) { const WRes _result_ = (x); if (_result_ != 0) return _result_; }\n#endif\n\ntypedef unsigned char Byte;\ntypedef short Int16;\ntypedef unsigned short UInt16;\n\n#ifdef Z7_DECL_Int32_AS_long\ntypedef long Int32;\ntypedef unsigned long UInt32;\n#else\ntypedef int Int32;\ntypedef unsigned int UInt32;\n#endif\n\n\n#ifndef _WIN32\n\ntypedef int INT;\ntypedef Int32 INT32;\ntypedef unsigned int UINT;\ntypedef UInt32 UINT32;\ntypedef INT32 LONG;   // LONG, ULONG and DWORD must be 32-bit for _WIN32 compatibility\ntypedef UINT32 ULONG;\n\n#undef DWORD\ntypedef UINT32 DWORD;\n\n#define VOID void\n\n#define HRESULT LONG\n\ntypedef void *LPVOID;\n// typedef void VOID;\n// typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;\n// gcc / clang on Unix  : sizeof(long==sizeof(void*) in 32 or 64 bits)\ntypedef          long  INT_PTR;\ntypedef unsigned long  UINT_PTR;\ntypedef          long  LONG_PTR;\ntypedef unsigned long  DWORD_PTR;\n\ntypedef size_t SIZE_T;\n\n#endif //  _WIN32\n\n\n#define MY_HRES_ERROR_INTERNAL_ERROR  ((HRESULT)0x8007054FL)\n\n\n#ifdef Z7_DECL_Int64_AS_long\n\ntypedef long Int64;\ntypedef unsigned long UInt64;\n\n#else\n\n#if (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__clang__)\ntypedef __int64 Int64;\ntypedef unsigned __int64 UInt64;\n#else\n#if defined(__clang__) || defined(__GNUC__)\n#include <stdint.h>\ntypedef int64_t Int64;\ntypedef uint64_t UInt64;\n#else\ntypedef long long int Int64;\ntypedef unsigned long long int UInt64;\n// #define UINT64_CONST(n) n ## ULL\n#endif\n#endif\n\n#endif\n\n#define UINT64_CONST(n) n\n\n\n#ifdef Z7_DECL_SizeT_AS_unsigned_int\ntypedef unsigned int SizeT;\n#else\ntypedef size_t SizeT;\n#endif\n\n/*\n#if (defined(_MSC_VER) && _MSC_VER <= 1200)\ntypedef size_t MY_uintptr_t;\n#else\n#include <stdint.h>\ntypedef uintptr_t MY_uintptr_t;\n#endif\n*/\n\ntypedef int BoolInt;\n/* typedef BoolInt Bool; */\n#define True 1\n#define False 0\n\n\n#ifdef _WIN32\n#define Z7_STDCALL __stdcall\n#else\n#define Z7_STDCALL\n#endif\n\n#ifdef _MSC_VER\n\n#if _MSC_VER >= 1300\n#define Z7_NO_INLINE __declspec(noinline)\n#else\n#define Z7_NO_INLINE\n#endif\n\n#define Z7_FORCE_INLINE __forceinline\n\n#define Z7_CDECL      __cdecl\n#define Z7_FASTCALL  __fastcall\n\n#else //  _MSC_VER\n\n#if (defined(__GNUC__) && (__GNUC__ >= 4)) \\\n    || (defined(__clang__) && (__clang_major__ >= 4)) \\\n    || defined(__INTEL_COMPILER) \\\n    || defined(__xlC__)\n#define Z7_NO_INLINE      __attribute__((noinline))\n#define Z7_FORCE_INLINE   __attribute__((always_inline)) inline\n#else\n#define Z7_NO_INLINE\n#define Z7_FORCE_INLINE\n#endif\n\n#define Z7_CDECL\n\n#if  defined(_M_IX86) \\\n  || defined(__i386__)\n// #define Z7_FASTCALL __attribute__((fastcall))\n// #define Z7_FASTCALL __attribute__((cdecl))\n#define Z7_FASTCALL\n#elif defined(MY_CPU_AMD64)\n// #define Z7_FASTCALL __attribute__((ms_abi))\n#define Z7_FASTCALL\n#else\n#define Z7_FASTCALL\n#endif\n\n#endif //  _MSC_VER\n\n\n/* The following interfaces use first parameter as pointer to structure */\n\n// #define Z7_C_IFACE_CONST_QUAL\n#define Z7_C_IFACE_CONST_QUAL const\n\n#define Z7_C_IFACE_DECL(a) \\\n  struct a ## _; \\\n  typedef Z7_C_IFACE_CONST_QUAL struct a ## _ * a ## Ptr; \\\n  typedef struct a ## _ a; \\\n  struct a ## _\n\n\nZ7_C_IFACE_DECL (IByteIn)\n{\n  Byte (*Read)(IByteInPtr p); /* reads one byte, returns 0 in case of EOF or error */\n};\n#define IByteIn_Read(p) (p)->Read(p)\n\n\nZ7_C_IFACE_DECL (IByteOut)\n{\n  void (*Write)(IByteOutPtr p, Byte b);\n};\n#define IByteOut_Write(p, b) (p)->Write(p, b)\n\n\nZ7_C_IFACE_DECL (ISeqInStream)\n{\n  SRes (*Read)(ISeqInStreamPtr p, void *buf, size_t *size);\n    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\n       (output(*size) < input(*size)) is allowed */\n};\n#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)\n\n/* try to read as much as avail in stream and limited by (*processedSize) */\nSRes SeqInStream_ReadMax(ISeqInStreamPtr stream, void *buf, size_t *processedSize);\n/* it can return SZ_ERROR_INPUT_EOF */\n// SRes SeqInStream_Read(ISeqInStreamPtr stream, void *buf, size_t size);\n// SRes SeqInStream_Read2(ISeqInStreamPtr stream, void *buf, size_t size, SRes errorType);\nSRes SeqInStream_ReadByte(ISeqInStreamPtr stream, Byte *buf);\n\n\nZ7_C_IFACE_DECL (ISeqOutStream)\n{\n  size_t (*Write)(ISeqOutStreamPtr p, const void *buf, size_t size);\n    /* Returns: result - the number of actually written bytes.\n       (result < size) means error */\n};\n#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)\n\ntypedef enum\n{\n  SZ_SEEK_SET = 0,\n  SZ_SEEK_CUR = 1,\n  SZ_SEEK_END = 2\n} ESzSeek;\n\n\nZ7_C_IFACE_DECL (ISeekInStream)\n{\n  SRes (*Read)(ISeekInStreamPtr p, void *buf, size_t *size);  /* same as ISeqInStream::Read */\n  SRes (*Seek)(ISeekInStreamPtr p, Int64 *pos, ESzSeek origin);\n};\n#define ISeekInStream_Read(p, buf, size)   (p)->Read(p, buf, size)\n#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)\n\n\nZ7_C_IFACE_DECL (ILookInStream)\n{\n  SRes (*Look)(ILookInStreamPtr p, const void **buf, size_t *size);\n    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.\n       (output(*size) > input(*size)) is not allowed\n       (output(*size) < input(*size)) is allowed */\n  SRes (*Skip)(ILookInStreamPtr p, size_t offset);\n    /* offset must be <= output(*size) of Look */\n  SRes (*Read)(ILookInStreamPtr p, void *buf, size_t *size);\n    /* reads directly (without buffer). It's same as ISeqInStream::Read */\n  SRes (*Seek)(ILookInStreamPtr p, Int64 *pos, ESzSeek origin);\n};\n\n#define ILookInStream_Look(p, buf, size)   (p)->Look(p, buf, size)\n#define ILookInStream_Skip(p, offset)      (p)->Skip(p, offset)\n#define ILookInStream_Read(p, buf, size)   (p)->Read(p, buf, size)\n#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)\n\n\nSRes LookInStream_LookRead(ILookInStreamPtr stream, void *buf, size_t *size);\nSRes LookInStream_SeekTo(ILookInStreamPtr stream, UInt64 offset);\n\n/* reads via ILookInStream::Read */\nSRes LookInStream_Read2(ILookInStreamPtr stream, void *buf, size_t size, SRes errorType);\nSRes LookInStream_Read(ILookInStreamPtr stream, void *buf, size_t size);\n\n\ntypedef struct\n{\n  ILookInStream vt;\n  ISeekInStreamPtr realStream;\n \n  size_t pos;\n  size_t size; /* it's data size */\n  \n  /* the following variables must be set outside */\n  Byte *buf;\n  size_t bufSize;\n} CLookToRead2;\n\nvoid LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);\n\n#define LookToRead2_INIT(p) { (p)->pos = (p)->size = 0; }\n\n\ntypedef struct\n{\n  ISeqInStream vt;\n  ILookInStreamPtr realStream;\n} CSecToLook;\n\nvoid SecToLook_CreateVTable(CSecToLook *p);\n\n\n\ntypedef struct\n{\n  ISeqInStream vt;\n  ILookInStreamPtr realStream;\n} CSecToRead;\n\nvoid SecToRead_CreateVTable(CSecToRead *p);\n\n\nZ7_C_IFACE_DECL (ICompressProgress)\n{\n  SRes (*Progress)(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize);\n    /* Returns: result. (result != SZ_OK) means break.\n       Value (UInt64)(Int64)-1 for size means unknown value. */\n};\n\n#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)\n\n\n\ntypedef struct ISzAlloc ISzAlloc;\ntypedef const ISzAlloc * ISzAllocPtr;\n\nstruct ISzAlloc\n{\n  void *(*Alloc)(ISzAllocPtr p, size_t size);\n  void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */\n};\n\n#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)\n#define ISzAlloc_Free(p, a) (p)->Free(p, a)\n\n/* deprecated */\n#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)\n#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)\n\n\n\n\n\n#ifndef MY_offsetof\n  #ifdef offsetof\n    #define MY_offsetof(type, m) offsetof(type, m)\n    /*\n    #define MY_offsetof(type, m) FIELD_OFFSET(type, m)\n    */\n  #else\n    #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))\n  #endif\n#endif\n\n\n\n#ifndef Z7_container_of\n\n/*\n#define Z7_container_of(ptr, type, m) container_of(ptr, type, m)\n#define Z7_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)\n#define Z7_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))\n#define Z7_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))\n*/\n\n/*\n  GCC shows warning: \"perhaps the 'offsetof' macro was used incorrectly\"\n    GCC 3.4.4 : classes with constructor\n    GCC 4.8.1 : classes with non-public variable members\"\n*/\n\n#define Z7_container_of(ptr, type, m) \\\n  ((type *)(void *)((char *)(void *) \\\n  (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m)))\n\n#define Z7_container_of_CONST(ptr, type, m) \\\n  ((const type *)(const void *)((const char *)(const void *) \\\n  (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m)))\n\n/*\n#define Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m) \\\n  ((type *)(void *)(const void *)((const char *)(const void *) \\\n  (1 ? (ptr) : &((type *)NULL)->m) - MY_offsetof(type, m)))\n*/\n\n#endif\n\n#define Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(void *)(ptr))\n\n// #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)\n#define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of(ptr, type, m)\n// #define Z7_CONTAINER_FROM_VTBL(ptr, type, m) Z7_container_of_NON_CONST_FROM_CONST(ptr, type, m)\n\n#define Z7_CONTAINER_FROM_VTBL_CONST(ptr, type, m) Z7_container_of_CONST(ptr, type, m)\n\n#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)\n/*\n#define Z7_CONTAINER_FROM_VTBL_CLS(ptr, type, m) Z7_CONTAINER_FROM_VTBL(ptr, type, m)\n*/\n#if defined (__clang__) || defined(__GNUC__)\n#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \\\n  _Pragma(\"GCC diagnostic push\") \\\n  _Pragma(\"GCC diagnostic ignored \\\"-Wcast-qual\\\"\")\n#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL \\\n  _Pragma(\"GCC diagnostic pop\")\n#else\n#define Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL\n#define Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL\n#endif\n\n#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(ptr, type, m, p) \\\n  Z7_DIAGNOSTIC_IGNORE_BEGIN_CAST_QUAL \\\n  type *p = Z7_CONTAINER_FROM_VTBL(ptr, type, m); \\\n  Z7_DIAGNOSTIC_IGNORE_END_CAST_QUAL\n\n#define Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(type) \\\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR(pp, type, vt, p)\n\n\n// #define ZIP7_DECLARE_HANDLE(name)  typedef void *name;\n#define Z7_DECLARE_HANDLE(name)  struct name##_dummy{int unused;}; typedef struct name##_dummy *name;\n\n\n#define Z7_memset_0_ARRAY(a)  memset((a), 0, sizeof(a))\n\n#ifndef Z7_ARRAY_SIZE\n#define Z7_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))\n#endif\n\n\n#ifdef _WIN32\n\n#define CHAR_PATH_SEPARATOR '\\\\'\n#define WCHAR_PATH_SEPARATOR L'\\\\'\n#define STRING_PATH_SEPARATOR \"\\\\\"\n#define WSTRING_PATH_SEPARATOR L\"\\\\\"\n\n#else\n\n#define CHAR_PATH_SEPARATOR '/'\n#define WCHAR_PATH_SEPARATOR L'/'\n#define STRING_PATH_SEPARATOR \"/\"\n#define WSTRING_PATH_SEPARATOR L\"/\"\n\n#endif\n\n#define k_PropVar_TimePrec_0        0\n#define k_PropVar_TimePrec_Unix     1\n#define k_PropVar_TimePrec_DOS      2\n#define k_PropVar_TimePrec_HighPrec 3\n#define k_PropVar_TimePrec_Base     16\n#define k_PropVar_TimePrec_100ns (k_PropVar_TimePrec_Base + 7)\n#define k_PropVar_TimePrec_1ns   (k_PropVar_TimePrec_Base + 9)\n\nEXTERN_C_END\n\n#endif\n\n/*\n#ifndef Z7_ST\n#ifdef _7ZIP_ST\n#define Z7_ST\n#endif\n#endif\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zVersion.h",
    "content": "﻿#define MY_VER_MAJOR 26\n#define MY_VER_MINOR 0\n#define MY_VER_BUILD 0\n#define MY_VERSION_NUMBERS \"26.00\"\n#define MY_VERSION MY_VERSION_NUMBERS\n\n#ifdef MY_CPU_NAME\n  #define MY_VERSION_CPU MY_VERSION \" (\" MY_CPU_NAME \")\"\n#else\n  #define MY_VERSION_CPU MY_VERSION\n#endif\n\n#define MY_DATE \"2026-02-12\"\n#undef MY_COPYRIGHT\n#undef MY_VERSION_COPYRIGHT_DATE\n#define MY_AUTHOR_NAME \"Igor Pavlov\"\n#define MY_COPYRIGHT_PD \"Igor Pavlov : Public domain\"\n#define MY_COPYRIGHT_CR \"Copyright (c) 1999-2026 Igor Pavlov\"\n\n#ifdef USE_COPYRIGHT_CR\n  #define MY_COPYRIGHT MY_COPYRIGHT_CR\n#else\n  #define MY_COPYRIGHT MY_COPYRIGHT_PD\n#endif\n\n#define MY_COPYRIGHT_DATE MY_COPYRIGHT \" : \" MY_DATE\n#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU \" : \" MY_COPYRIGHT \" : \" MY_DATE\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/7zWindows.h",
    "content": "﻿/* 7zWindows.h -- Windows.h and related code\nIgor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_7Z_WINDOWS_H\n#define ZIP7_INC_7Z_WINDOWS_H\n\n#ifdef _WIN32\n\n#if defined(_MSC_VER) && _MSC_VER >= 1950 && !defined(__clang__) // VS2026\n// <Windows.h> and some another windows files need that option\n// VS2026: wtypesbase.h: warning C4865: 'tagCLSCTX': the underlying type will change from 'int' to 'unsigned int' when '/Zc:enumTypes' is specified on the command line\n#pragma warning(disable : 4865)\n#endif\n\n#if defined(__clang__)\n# pragma clang diagnostic push\n#endif\n\n#if defined(_MSC_VER)\n\n#pragma warning(push)\n#pragma warning(disable : 4668) // '_WIN32_WINNT' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'\n\n#if _MSC_VER == 1900\n// for old kit10 versions\n// #pragma warning(disable : 4255) // winuser.h(13979): warning C4255: 'GetThreadDpiAwarenessContext':\n#endif\n// win10 Windows Kit:\n#endif // _MSC_VER\n\n#if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64)\n// for msvc6 without sdk2003\n#define RPC_NO_WINDOWS_H\n#endif\n\n#if defined(__MINGW32__) || defined(__MINGW64__)\n// #if defined(__GNUC__) && !defined(__clang__)\n#include <windows.h>\n#else\n#include <Windows.h>\n#endif\n// #include <basetsd.h>\n// #include <wtypes.h>\n\n// but if precompiled with clang-cl then we need\n// #include <windows.h>\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#if defined(__clang__)\n# pragma clang diagnostic pop\n#endif\n\n#if defined(_MSC_VER) && _MSC_VER <= 1200 && !defined(_WIN64)\n#ifndef _W64\n\ntypedef long LONG_PTR, *PLONG_PTR;\ntypedef unsigned long ULONG_PTR, *PULONG_PTR;\ntypedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;\n\n#define Z7_OLD_WIN_SDK\n#endif // _W64\n#endif // _MSC_VER == 1200\n\n#ifdef Z7_OLD_WIN_SDK\n\n#ifndef INVALID_FILE_ATTRIBUTES\n#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)\n#endif\n#ifndef INVALID_SET_FILE_POINTER\n#define INVALID_SET_FILE_POINTER ((DWORD)-1)\n#endif\n#ifndef FILE_SPECIAL_ACCESS\n#define FILE_SPECIAL_ACCESS    (FILE_ANY_ACCESS)\n#endif\n\n// ShlObj.h:\n// #define BIF_NEWDIALOGSTYLE     0x0040\n\n#pragma warning(disable : 4201)\n// #pragma warning(disable : 4115)\n\n#undef  VARIANT_TRUE\n#define VARIANT_TRUE ((VARIANT_BOOL)-1)\n#endif\n\n#endif // Z7_OLD_WIN_SDK\n\n#ifdef UNDER_CE\n#undef  VARIANT_TRUE\n#define VARIANT_TRUE ((VARIANT_BOOL)-1)\n#endif\n\n\n#if defined(_MSC_VER)\n#if _MSC_VER >= 1400 && _MSC_VER <= 1600\n  // BaseTsd.h(148) : 'HandleToULong' : unreferenced inline function has been removed\n  // string.h\n  // #pragma warning(disable : 4514)\n#endif\n#endif\n\n\n/* #include \"7zTypes.h\" */\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Aes.c",
    "content": "﻿/* Aes.c -- AES encryption / decryption\n2024-03-01 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"CpuArch.h\"\n#include \"Aes.h\"\n\nAES_CODE_FUNC g_AesCbc_Decode;\n#ifndef Z7_SFX\nAES_CODE_FUNC g_AesCbc_Encode;\nAES_CODE_FUNC g_AesCtr_Code;\nUInt32 g_Aes_SupportedFunctions_Flags;\n#endif\n\nMY_ALIGN(64)\nstatic UInt32 T[256 * 4];\nMY_ALIGN(64)\nstatic const Byte Sbox[256] = {\n  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,\n  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,\n  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,\n  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,\n  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,\n  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,\n  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,\n  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,\n  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,\n  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,\n  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,\n  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,\n  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,\n  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,\n  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,\n  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};\n\n\nMY_ALIGN(64)\nstatic UInt32 D[256 * 4];\nMY_ALIGN(64)\nstatic Byte InvS[256];\n\n#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)\n\n#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24))\n\n#define gb0(x) ( (x)          & 0xFF)\n#define gb1(x) (((x) >> ( 8)) & 0xFF)\n#define gb2(x) (((x) >> (16)) & 0xFF)\n#define gb3(x) (((x) >> (24)))\n\n#define gb(n, x) gb ## n(x)\n\n#define TT(x) (T + (x << 8))\n#define DD(x) (D + (x << 8))\n\n\n// #define Z7_SHOW_AES_STATUS\n\n#ifdef MY_CPU_X86_OR_AMD64\n\n  #if defined(__INTEL_COMPILER)\n    #if (__INTEL_COMPILER >= 1110)\n      #define USE_HW_AES\n      #if (__INTEL_COMPILER >= 1900)\n        #define USE_HW_VAES\n      #endif\n    #endif\n  #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \\\n     || defined(Z7_GCC_VERSION)   && (Z7_GCC_VERSION   >= 40400)\n    #define USE_HW_AES\n      #if defined(__clang__) && (__clang_major__ >= 8) \\\n          || defined(__GNUC__) && (__GNUC__ >= 8)\n        #define USE_HW_VAES\n      #endif\n  #elif defined(_MSC_VER)\n    #define USE_HW_AES\n    #define USE_HW_VAES\n  #endif\n\n#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)\n  \n  #if   defined(__ARM_FEATURE_AES) \\\n     || defined(__ARM_FEATURE_CRYPTO)\n    #define USE_HW_AES\n  #else\n    #if  defined(MY_CPU_ARM64) \\\n      || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \\\n      || defined(Z7_MSC_VER_ORIGINAL)\n    #if  defined(__ARM_FP) && \\\n          (   defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \\\n           || defined(__GNUC__) && (__GNUC__ >= 6) \\\n          ) \\\n      || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)\n    #if  defined(MY_CPU_ARM64) \\\n      || !defined(Z7_CLANG_VERSION) \\\n      || defined(__ARM_NEON) && \\\n          (Z7_CLANG_VERSION < 170000 || \\\n           Z7_CLANG_VERSION > 170001)\n      #define USE_HW_AES\n    #endif\n    #endif\n    #endif\n  #endif\n#endif\n\n#ifdef USE_HW_AES\n// #pragma message(\"=== Aes.c USE_HW_AES === \")\n#ifdef Z7_SHOW_AES_STATUS\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n#endif\n\n\nvoid AesGenTables(void)\n{\n  unsigned i;\n  for (i = 0; i < 256; i++)\n    InvS[Sbox[i]] = (Byte)i;\n  \n  for (i = 0; i < 256; i++)\n  {\n    {\n      const UInt32 a1 = Sbox[i];\n      const UInt32 a2 = xtime(a1);\n      const UInt32 a3 = a2 ^ a1;\n      TT(0)[i] = Ui32(a2, a1, a1, a3);\n      TT(1)[i] = Ui32(a3, a2, a1, a1);\n      TT(2)[i] = Ui32(a1, a3, a2, a1);\n      TT(3)[i] = Ui32(a1, a1, a3, a2);\n    }\n    {\n      const UInt32 a1 = InvS[i];\n      const UInt32 a2 = xtime(a1);\n      const UInt32 a4 = xtime(a2);\n      const UInt32 a8 = xtime(a4);\n      const UInt32 a9 = a8 ^ a1;\n      const UInt32 aB = a8 ^ a2 ^ a1;\n      const UInt32 aD = a8 ^ a4 ^ a1;\n      const UInt32 aE = a8 ^ a4 ^ a2;\n      DD(0)[i] = Ui32(aE, a9, aD, aB);\n      DD(1)[i] = Ui32(aB, aE, a9, aD);\n      DD(2)[i] = Ui32(aD, aB, aE, a9);\n      DD(3)[i] = Ui32(a9, aD, aB, aE);\n    }\n  }\n  \n  {\n  AES_CODE_FUNC d = AesCbc_Decode;\n  #ifndef Z7_SFX\n  AES_CODE_FUNC e = AesCbc_Encode;\n  AES_CODE_FUNC c = AesCtr_Code;\n  UInt32 flags = 0;\n  #endif\n  \n  #ifdef USE_HW_AES\n  if (CPU_IsSupported_AES())\n  {\n    // #pragma message (\"AES HW\")\n    PRF(printf(\"\\n===AES HW\\n\"));\n    d = AesCbc_Decode_HW;\n\n    #ifndef Z7_SFX\n    e = AesCbc_Encode_HW;\n    c = AesCtr_Code_HW;\n    flags = k_Aes_SupportedFunctions_HW;\n    #endif\n\n    #ifdef MY_CPU_X86_OR_AMD64\n    #ifdef USE_HW_VAES\n    if (CPU_IsSupported_VAES_AVX2())\n    {\n      PRF(printf(\"\\n===vaes avx2\\n\"));\n      d = AesCbc_Decode_HW_256;\n      #ifndef Z7_SFX\n      c = AesCtr_Code_HW_256;\n      flags |= k_Aes_SupportedFunctions_HW_256;\n      #endif\n    }\n    #endif\n    #endif\n  }\n  #endif\n\n  g_AesCbc_Decode = d;\n  #ifndef Z7_SFX\n  g_AesCbc_Encode = e;\n  g_AesCtr_Code = c;\n  g_Aes_SupportedFunctions_Flags = flags;\n  #endif\n  }\n}\n\n\n#define HT(i, x, s) TT(x)[gb(x, s[(i + x) & 3])]\n\n#define HT4(m, i, s, p) m[i] = \\\n    HT(i, 0, s) ^ \\\n    HT(i, 1, s) ^ \\\n    HT(i, 2, s) ^ \\\n    HT(i, 3, s) ^ w[p + i]\n\n#define HT16(m, s, p) \\\n    HT4(m, 0, s, p); \\\n    HT4(m, 1, s, p); \\\n    HT4(m, 2, s, p); \\\n    HT4(m, 3, s, p); \\\n\n#define FT(i, x) Sbox[gb(x, m[(i + x) & 3])]\n#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];\n\n\n#define HD(i, x, s) DD(x)[gb(x, s[(i - x) & 3])]\n\n#define HD4(m, i, s, p) m[i] = \\\n    HD(i, 0, s) ^ \\\n    HD(i, 1, s) ^ \\\n    HD(i, 2, s) ^ \\\n    HD(i, 3, s) ^ w[p + i];\n\n#define HD16(m, s, p) \\\n    HD4(m, 0, s, p); \\\n    HD4(m, 1, s, p); \\\n    HD4(m, 2, s, p); \\\n    HD4(m, 3, s, p); \\\n\n#define FD(i, x) InvS[gb(x, m[(i - x) & 3])]\n#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];\n\nvoid Z7_FASTCALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize)\n{\n  unsigned i, m;\n  const UInt32 *wLim;\n  UInt32 t;\n  UInt32 rcon = 1;\n  \n  keySize /= 4;\n  w[0] = ((UInt32)keySize / 2) + 3;\n  w += 4;\n\n  for (i = 0; i < keySize; i++, key += 4)\n    w[i] = GetUi32(key);\n\n  t = w[(size_t)keySize - 1];\n  wLim = w + (size_t)keySize * 3 + 28;\n  m = 0;\n  do\n  {\n    if (m == 0)\n    {\n      t = Ui32(Sbox[gb1(t)] ^ rcon, Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);\n      rcon <<= 1;\n      if (rcon & 0x100)\n        rcon = 0x1b;\n      m = keySize;\n    }\n    else if (m == 4 && keySize > 6)\n      t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);\n    m--;\n    t ^= w[0];\n    w[keySize] = t;\n  }\n  while (++w != wLim);\n}\n\nvoid Z7_FASTCALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize)\n{\n  unsigned i, num;\n  Aes_SetKey_Enc(w, key, keySize);\n  num = keySize + 20;\n  w += 8;\n  for (i = 0; i < num; i++)\n  {\n    UInt32 r = w[i];\n    w[i] =\n      DD(0)[Sbox[gb0(r)]] ^\n      DD(1)[Sbox[gb1(r)]] ^\n      DD(2)[Sbox[gb2(r)]] ^\n      DD(3)[Sbox[gb3(r)]];\n  }\n}\n\n/* Aes_Encode and Aes_Decode functions work with little-endian words.\n  src and dest are pointers to 4 UInt32 words.\n  src and dest can point to same block */\n\n// Z7_FORCE_INLINE\nstatic void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src)\n{\n  UInt32 s[4];\n  UInt32 m[4];\n  UInt32 numRounds2 = w[0];\n  w += 4;\n  s[0] = src[0] ^ w[0];\n  s[1] = src[1] ^ w[1];\n  s[2] = src[2] ^ w[2];\n  s[3] = src[3] ^ w[3];\n  w += 4;\n  for (;;)\n  {\n    HT16(m, s, 0)\n    if (--numRounds2 == 0)\n      break;\n    HT16(s, m, 4)\n    w += 8;\n  }\n  w += 4;\n  FT4(0)\n  FT4(1)\n  FT4(2)\n  FT4(3)\n}\n\nZ7_FORCE_INLINE\nstatic void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src)\n{\n  UInt32 s[4];\n  UInt32 m[4];\n  UInt32 numRounds2 = w[0];\n  w += 4 + numRounds2 * 8;\n  s[0] = src[0] ^ w[0];\n  s[1] = src[1] ^ w[1];\n  s[2] = src[2] ^ w[2];\n  s[3] = src[3] ^ w[3];\n  for (;;)\n  {\n    w -= 8;\n    HD16(m, s, 4)\n    if (--numRounds2 == 0)\n      break;\n    HD16(s, m, 0)\n  }\n  FD4(0)\n  FD4(1)\n  FD4(2)\n  FD4(3)\n}\n\nvoid AesCbc_Init(UInt32 *p, const Byte *iv)\n{\n  unsigned i;\n  for (i = 0; i < 4; i++)\n    p[i] = GetUi32(iv + i * 4);\n}\n\nvoid Z7_FASTCALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks)\n{\n  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)\n  {\n    p[0] ^= GetUi32(data);\n    p[1] ^= GetUi32(data + 4);\n    p[2] ^= GetUi32(data + 8);\n    p[3] ^= GetUi32(data + 12);\n    \n    Aes_Encode(p + 4, p, p);\n    \n    SetUi32(data,      p[0])\n    SetUi32(data + 4,  p[1])\n    SetUi32(data + 8,  p[2])\n    SetUi32(data + 12, p[3])\n  }\n}\n\nvoid Z7_FASTCALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks)\n{\n  UInt32 in[4], out[4];\n  for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE)\n  {\n    in[0] = GetUi32(data);\n    in[1] = GetUi32(data + 4);\n    in[2] = GetUi32(data + 8);\n    in[3] = GetUi32(data + 12);\n\n    Aes_Decode(p + 4, out, in);\n\n    SetUi32(data,      p[0] ^ out[0])\n    SetUi32(data + 4,  p[1] ^ out[1])\n    SetUi32(data + 8,  p[2] ^ out[2])\n    SetUi32(data + 12, p[3] ^ out[3])\n    \n    p[0] = in[0];\n    p[1] = in[1];\n    p[2] = in[2];\n    p[3] = in[3];\n  }\n}\n\nvoid Z7_FASTCALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks)\n{\n  for (; numBlocks != 0; numBlocks--)\n  {\n    UInt32 temp[4];\n    unsigned i;\n\n    if (++p[0] == 0)\n      p[1]++;\n    \n    Aes_Encode(p + 4, temp, p);\n    \n    for (i = 0; i < 4; i++, data += 4)\n    {\n      const UInt32 t = temp[i];\n\n      #ifdef MY_CPU_LE_UNALIGN\n        *((UInt32 *)(void *)data) ^= t;\n      #else\n        data[0] = (Byte)(data[0] ^ (t & 0xFF));\n        data[1] = (Byte)(data[1] ^ ((t >> 8) & 0xFF));\n        data[2] = (Byte)(data[2] ^ ((t >> 16) & 0xFF));\n        data[3] = (Byte)(data[3] ^ ((t >> 24)));\n      #endif\n    }\n  }\n}\n\n#undef xtime\n#undef Ui32\n#undef gb0\n#undef gb1\n#undef gb2\n#undef gb3\n#undef gb\n#undef TT\n#undef DD\n#undef USE_HW_AES\n#undef PRF\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Aes.h",
    "content": "﻿/* Aes.h -- AES encryption / decryption\n2023-04-02 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_AES_H\n#define ZIP7_INC_AES_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define AES_BLOCK_SIZE 16\n\n/* Call AesGenTables one time before other AES functions */\nvoid AesGenTables(void);\n\n/* UInt32 pointers must be 16-byte aligned */\n\n/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */\n#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4)\n\n/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */\n/* keySize = 16 or 24 or 32 (bytes) */\ntypedef void (Z7_FASTCALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize);\nvoid Z7_FASTCALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize);\nvoid Z7_FASTCALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize);\n\n/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */\nvoid AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */\n\n/* data - 16-byte aligned pointer to data */\n/* numBlocks - the number of 16-byte blocks in data array */\ntypedef void (Z7_FASTCALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks);\n\nextern AES_CODE_FUNC g_AesCbc_Decode;\n#ifndef Z7_SFX\nextern AES_CODE_FUNC g_AesCbc_Encode;\nextern AES_CODE_FUNC g_AesCtr_Code;\n#define k_Aes_SupportedFunctions_HW     (1 << 2)\n#define k_Aes_SupportedFunctions_HW_256 (1 << 3)\nextern UInt32 g_Aes_SupportedFunctions_Flags;\n#endif\n\n\n#define Z7_DECLARE_AES_CODE_FUNC(funcName) \\\n    void Z7_FASTCALL funcName(UInt32 *ivAes, Byte *data, size_t numBlocks);\n\nZ7_DECLARE_AES_CODE_FUNC (AesCbc_Encode)\nZ7_DECLARE_AES_CODE_FUNC (AesCbc_Decode)\nZ7_DECLARE_AES_CODE_FUNC (AesCtr_Code)\n\nZ7_DECLARE_AES_CODE_FUNC (AesCbc_Encode_HW)\nZ7_DECLARE_AES_CODE_FUNC (AesCbc_Decode_HW)\nZ7_DECLARE_AES_CODE_FUNC (AesCtr_Code_HW)\n\nZ7_DECLARE_AES_CODE_FUNC (AesCbc_Decode_HW_256)\nZ7_DECLARE_AES_CODE_FUNC (AesCtr_Code_HW_256)\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/AesOpt.c",
    "content": "﻿/* AesOpt.c -- AES optimized code for x86 AES hardware instructions\nIgor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Aes.h\"\n#include \"CpuArch.h\"\n\n#ifdef MY_CPU_X86_OR_AMD64\n\n  #if defined(__INTEL_COMPILER)\n    #if (__INTEL_COMPILER >= 1110)\n      #define USE_INTEL_AES\n      #if (__INTEL_COMPILER >= 1900)\n        #define USE_INTEL_VAES\n      #endif\n    #endif\n  #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \\\n     || defined(Z7_GCC_VERSION)   && (Z7_GCC_VERSION   >= 40400)\n        #define USE_INTEL_AES\n        #if !defined(__AES__)\n          #define ATTRIB_AES __attribute__((__target__(\"aes\")))\n        #endif\n      #if defined(__clang__) && (__clang_major__ >= 8) \\\n          || defined(__GNUC__) && (__GNUC__ >= 8)\n        #define USE_INTEL_VAES\n        #if !defined(__AES__) || !defined(__VAES__) || !defined(__AVX__) || !defined(__AVX2__)\n          #define ATTRIB_VAES __attribute__((__target__(\"aes,vaes,avx,avx2\")))\n        #endif\n      #endif\n  #elif defined(_MSC_VER)\n    #if (_MSC_VER > 1500) || (_MSC_FULL_VER >= 150030729)\n      #define USE_INTEL_AES\n      #if (_MSC_VER >= 1910)\n        #define USE_INTEL_VAES\n      #endif\n    #endif\n    #ifndef USE_INTEL_AES\n      #define Z7_USE_AES_HW_STUB\n    #endif\n    #ifndef USE_INTEL_VAES\n      #define Z7_USE_VAES_HW_STUB\n    #endif\n  #endif\n\n    #ifndef USE_INTEL_AES\n      // #define Z7_USE_AES_HW_STUB // for debug\n    #endif\n    #ifndef USE_INTEL_VAES\n      // #define Z7_USE_VAES_HW_STUB // for debug\n    #endif\n\n\n#ifdef USE_INTEL_AES\n\n#include <wmmintrin.h>\n\n#if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB)\n#define AES_TYPE_keys UInt32\n#define AES_TYPE_data Byte\n// #define AES_TYPE_keys __m128i\n// #define AES_TYPE_data __m128i\n#endif\n\n#ifndef ATTRIB_AES\n  #define ATTRIB_AES\n#endif\n\n#define AES_FUNC_START(name) \\\n    void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks)\n    // void Z7_FASTCALL name(__m128i *p, __m128i *data, size_t numBlocks)\n\n#define AES_FUNC_START2(name) \\\nAES_FUNC_START (name); \\\nATTRIB_AES \\\nAES_FUNC_START (name)\n\n#define MM_OP(op, dest, src)  dest = op(dest, src);\n#define MM_OP_m(op, src)      MM_OP(op, m, src)\n\n#define MM_XOR( dest, src)    MM_OP(_mm_xor_si128,    dest, src)\n\n#if 1\n// use aligned SSE load/store for data.\n// It is required for our Aes functions, that data is aligned for 16-bytes.\n// So we can use this branch of code.\n// and compiler can use fused load-op SSE instructions:\n//   xorps xmm0, XMMWORD PTR [rdx]\n#define LOAD_128(pp)        (*(__m128i *)(void *)(pp))\n#define STORE_128(pp, _v)    *(__m128i *)(void *)(pp) = _v\n// use aligned SSE load/store for data. Alternative code with direct access\n// #define LOAD_128(pp)        _mm_load_si128(pp)\n// #define STORE_128(pp, _v)   _mm_store_si128(pp, _v)\n#else\n// use unaligned load/store for data: movdqu XMMWORD PTR [rdx]\n#define LOAD_128(pp)        _mm_loadu_si128(pp)\n#define STORE_128(pp, _v)   _mm_storeu_si128(pp, _v)\n#endif\n\nAES_FUNC_START2 (AesCbc_Encode_HW)\n{\n  if (numBlocks == 0)\n    return;\n  {\n  __m128i *p = (__m128i *)(void *)ivAes;\n  __m128i *data = (__m128i *)(void *)data8;\n  __m128i m = *p;\n  const __m128i k0 = p[2];\n  const __m128i k1 = p[3];\n  const UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1;\n  do\n  {\n    UInt32 r = numRounds2;\n    const __m128i *w = p + 4;\n    __m128i temp = LOAD_128(data);\n    MM_XOR (temp, k0)\n    MM_XOR (m, temp)\n    MM_OP_m (_mm_aesenc_si128, k1)\n    do\n    {\n      MM_OP_m (_mm_aesenc_si128, w[0])\n      MM_OP_m (_mm_aesenc_si128, w[1])\n      w += 2;\n    }\n    while (--r);\n    MM_OP_m (_mm_aesenclast_si128, w[0])\n    STORE_128(data, m);\n    data++;\n  }\n  while (--numBlocks);\n  *p = m;\n  }\n}\n\n\n#define WOP_1(op)\n#define WOP_2(op)   WOP_1 (op)  op (m1, 1)\n#define WOP_3(op)   WOP_2 (op)  op (m2, 2)\n#define WOP_4(op)   WOP_3 (op)  op (m3, 3)\n#ifdef MY_CPU_AMD64\n#define WOP_5(op)   WOP_4 (op)  op (m4, 4)\n#define WOP_6(op)   WOP_5 (op)  op (m5, 5)\n#define WOP_7(op)   WOP_6 (op)  op (m6, 6)\n#define WOP_8(op)   WOP_7 (op)  op (m7, 7)\n#endif\n/*\n#define WOP_9(op)   WOP_8 (op)  op (m8, 8);\n#define WOP_10(op)  WOP_9 (op)  op (m9, 9);\n#define WOP_11(op)  WOP_10(op)  op (m10, 10);\n#define WOP_12(op)  WOP_11(op)  op (m11, 11);\n#define WOP_13(op)  WOP_12(op)  op (m12, 12);\n#define WOP_14(op)  WOP_13(op)  op (m13, 13);\n*/\n\n#ifdef MY_CPU_AMD64\n  #define NUM_WAYS      8\n  #define WOP_M1    WOP_8\n#else\n  #define NUM_WAYS      4\n  #define WOP_M1    WOP_4\n#endif\n\n#define WOP(op)  op (m0, 0)  WOP_M1(op)\n\n#define DECLARE_VAR(reg, ii)  __m128i reg;\n#define LOAD_data_ii(ii)      LOAD_128(data + (ii))\n#define LOAD_data(  reg, ii)  reg = LOAD_data_ii(ii);\n#define STORE_data( reg, ii)  STORE_128(data + (ii), reg);\n#if (NUM_WAYS > 1)\n#define XOR_data_M1(reg, ii)  MM_XOR (reg, LOAD_128(data + (ii- 1)))\n#endif\n\n#define MM_OP_key(op, reg)  MM_OP(op, reg, key);\n\n#define AES_DEC(      reg, ii)   MM_OP_key (_mm_aesdec_si128,     reg)\n#define AES_DEC_LAST( reg, ii)   MM_OP_key (_mm_aesdeclast_si128, reg)\n#define AES_ENC(      reg, ii)   MM_OP_key (_mm_aesenc_si128,     reg)\n#define AES_ENC_LAST( reg, ii)   MM_OP_key (_mm_aesenclast_si128, reg)\n#define AES_XOR(      reg, ii)   MM_OP_key (_mm_xor_si128,        reg)\n\n#define CTR_START(reg, ii)  MM_OP (_mm_add_epi64, ctr, one)  reg = ctr;\n#define CTR_END(  reg, ii)  STORE_128(data + (ii), _mm_xor_si128(reg, \\\n                            LOAD_128 (data + (ii))));\n#define WOP_KEY(op, n) { \\\n    const __m128i key = w[n]; \\\n    WOP(op) }\n\n#define WIDE_LOOP_START  \\\n    dataEnd = data + numBlocks;  \\\n    if (numBlocks >= NUM_WAYS)  \\\n    { dataEnd -= NUM_WAYS; do {  \\\n\n#define WIDE_LOOP_END  \\\n    data += NUM_WAYS;  \\\n    } while (data <= dataEnd);  \\\n    dataEnd += NUM_WAYS; }  \\\n\n#define SINGLE_LOOP  \\\n    for (; data < dataEnd; data++)\n\n\n\n#ifdef USE_INTEL_VAES\n\n#define AVX_XOR(dest, src)    MM_OP(_mm256_xor_si256, dest, src)\n#define AVX_DECLARE_VAR(reg, ii)  __m256i reg;\n\n#if 1\n// use unaligned AVX load/store for data.\n// It is required for our Aes functions, that data is aligned for 16-bytes.\n// But we need 32-bytes reading.\n// So we use intrinsics for unaligned AVX load/store.\n// notes for _mm256_storeu_si256:\n// msvc2022: uses vmovdqu and keeps the order of instruction sequence.\n// new gcc11 uses vmovdqu\n// old gcc9 could use pair of instructions:\n//   vmovups        %xmm7, -224(%rax)\n//   vextracti128   $0x1, %ymm7, -208(%rax)\n#define AVX_LOAD(p)         _mm256_loadu_si256((const __m256i *)(const void *)(p))\n#define AVX_STORE(p, _v)    _mm256_storeu_si256((__m256i *)(void *)(p), _v);\n#else\n// use aligned AVX load/store for data.\n// for debug: we can use this branch, if we are sure that data is aligned for 32-bytes.\n// msvc2022 uses vmovdqu still\n// gcc      uses vmovdqa (that requires 32-bytes alignment)\n#define AVX_LOAD(p)         (*(const __m256i *)(const void *)(p))\n#define AVX_STORE(p, _v)    (*(__m256i *)(void *)(p)) = _v;\n#endif\n\n#define AVX_LOAD_data(  reg, ii)  reg = AVX_LOAD((const __m256i *)(const void *)data + (ii));\n#define AVX_STORE_data( reg, ii)  AVX_STORE((__m256i *)(void *)data + (ii), reg)\n/*\nAVX_XOR_data_M1() needs unaligned memory load, even if (data)\nis aligned for 256-bits, because we read 32-bytes chunk that\ncrosses (data) position: from (data - 16bytes) to (data + 16bytes).\n*/\n#define AVX_XOR_data_M1(reg, ii)  AVX_XOR (reg, _mm256_loadu_si256((const __m256i *)(const void *)(data - 1) + (ii)))\n\n#define AVX_AES_DEC(      reg, ii)   MM_OP_key (_mm256_aesdec_epi128,     reg)\n#define AVX_AES_DEC_LAST( reg, ii)   MM_OP_key (_mm256_aesdeclast_epi128, reg)\n#define AVX_AES_ENC(      reg, ii)   MM_OP_key (_mm256_aesenc_epi128,     reg)\n#define AVX_AES_ENC_LAST( reg, ii)   MM_OP_key (_mm256_aesenclast_epi128, reg)\n#define AVX_AES_XOR(      reg, ii)   MM_OP_key (_mm256_xor_si256,         reg)\n#define AVX_CTR_START(reg, ii)  \\\n    MM_OP (_mm256_add_epi64, ctr2, two) \\\n    reg = _mm256_xor_si256(ctr2, key);\n\n#define AVX_CTR_END(reg, ii)  \\\n    AVX_STORE((__m256i *)(void *)data + (ii), _mm256_xor_si256(reg, \\\n    AVX_LOAD ((__m256i *)(void *)data + (ii))));\n\n#define AVX_WOP_KEY(op, n) { \\\n    const __m256i key = w[n]; \\\n    WOP(op) }\n\n#define NUM_AES_KEYS_MAX 15\n\n#define WIDE_LOOP_START_AVX(OP)  \\\n    dataEnd = data + numBlocks;  \\\n    if (numBlocks >= NUM_WAYS * 2)  \\\n    { __m256i keys[NUM_AES_KEYS_MAX];  \\\n      OP  \\\n      { UInt32 ii; for (ii = 0; ii < numRounds; ii++)  \\\n        keys[ii] = _mm256_broadcastsi128_si256(p[ii]); }  \\\n      dataEnd -= NUM_WAYS * 2; \\\n      do {  \\\n\n#define WIDE_LOOP_END_AVX(OP)  \\\n        data += NUM_WAYS * 2;  \\\n      } while (data <= dataEnd);  \\\n      dataEnd += NUM_WAYS * 2;  \\\n      OP  \\\n      _mm256_zeroupper();  \\\n    }  \\\n\n/* MSVC for x86: If we don't call _mm256_zeroupper(), and -arch:IA32 is not specified,\n   MSVC still can insert vzeroupper instruction. */\n\n#endif\n\n\n\nAES_FUNC_START2 (AesCbc_Decode_HW)\n{\n  __m128i *p = (__m128i *)(void *)ivAes;\n  __m128i *data = (__m128i *)(void *)data8;\n  __m128i iv = *p;\n  const __m128i * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2 + 2 - 1;\n  const __m128i *dataEnd;\n  p += 2;\n  \n  WIDE_LOOP_START\n  {\n    const __m128i *w = wStart;\n    WOP (DECLARE_VAR)\n    WOP (LOAD_data)\n    WOP_KEY (AES_XOR, 1)\n    do\n    {\n      WOP_KEY (AES_DEC, 0)\n\n      w--;\n    }\n    while (w != p);\n    WOP_KEY (AES_DEC_LAST, 0)\n\n    MM_XOR (m0, iv)\n    WOP_M1 (XOR_data_M1)\n    LOAD_data(iv, NUM_WAYS - 1)\n    WOP (STORE_data)\n  }\n  WIDE_LOOP_END\n\n  SINGLE_LOOP\n  {\n    const __m128i *w = wStart - 1;\n    __m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0));\n    \n    do\n    {\n      MM_OP_m (_mm_aesdec_si128, w[1])\n      MM_OP_m (_mm_aesdec_si128, w[0])\n      w -= 2;\n    }\n    while (w != p);\n    MM_OP_m (_mm_aesdec_si128,     w[1])\n    MM_OP_m (_mm_aesdeclast_si128, w[0])\n    MM_XOR (m, iv)\n    LOAD_data(iv, 0)\n    STORE_data(m, 0)\n  }\n  \n  p[-2] = iv;\n}\n\n\nAES_FUNC_START2 (AesCtr_Code_HW)\n{\n  __m128i *p = (__m128i *)(void *)ivAes;\n  __m128i *data = (__m128i *)(void *)data8;\n  __m128i ctr = *p;\n  const UInt32 numRoundsMinus2 = *(const UInt32 *)(p + 1) * 2 - 1;\n  const __m128i *dataEnd;\n  const __m128i one = _mm_cvtsi32_si128(1);\n\n  p += 2;\n  \n  WIDE_LOOP_START\n  {\n    const __m128i *w = p;\n    UInt32 r = numRoundsMinus2;\n    WOP (DECLARE_VAR)\n    WOP (CTR_START)\n    WOP_KEY (AES_XOR, 0)\n    w += 1;\n    do\n    {\n      WOP_KEY (AES_ENC, 0)\n      w += 1;\n    }\n    while (--r);\n    WOP_KEY (AES_ENC_LAST, 0)\n    WOP (CTR_END)\n  }\n  WIDE_LOOP_END\n\n  SINGLE_LOOP\n  {\n    UInt32 numRounds2 = *(const UInt32 *)(p - 2 + 1) - 1;\n    const __m128i *w = p;\n    __m128i m;\n    MM_OP (_mm_add_epi64, ctr, one)\n    m = _mm_xor_si128 (ctr, p[0]);\n    w += 1;\n    do\n    {\n      MM_OP_m (_mm_aesenc_si128, w[0])\n      MM_OP_m (_mm_aesenc_si128, w[1])\n      w += 2;\n    }\n    while (--numRounds2);\n    MM_OP_m (_mm_aesenc_si128,     w[0])\n    MM_OP_m (_mm_aesenclast_si128, w[1])\n    CTR_END (m, 0)\n  }\n  \n  p[-2] = ctr;\n}\n\n\n\n#ifdef USE_INTEL_VAES\n\n/*\nGCC before 2013-Jun:\n  <immintrin.h>:\n    #ifdef __AVX__\n     #include <avxintrin.h>\n    #endif\nGCC after 2013-Jun:\n  <immintrin.h>:\n    #include <avxintrin.h>\nCLANG 3.8+:\n{\n  <immintrin.h>:\n    #if !defined(_MSC_VER) || defined(__AVX__)\n      #include <avxintrin.h>\n    #endif\n\n  if (the compiler is clang for Windows and if global arch is not set for __AVX__)\n    [ if (defined(_MSC_VER) && !defined(__AVX__)) ]\n  {\n    <immintrin.h> doesn't include <avxintrin.h>\n    and we have 2 ways to fix it:\n      1) we can define required __AVX__ before <immintrin.h>\n      or\n      2) we can include <avxintrin.h> after <immintrin.h>\n  }\n}\n\nIf we include <avxintrin.h> manually for GCC/CLANG, it's\nrequired that <immintrin.h> must be included before <avxintrin.h>.\n*/\n\n/*\n#if defined(__clang__) && defined(_MSC_VER)\n#define __AVX__\n#define __AVX2__\n#define __VAES__\n#endif\n*/\n\n#include <immintrin.h>\n#if defined(__clang__) && defined(_MSC_VER)\n  #if !defined(__AVX__)\n    #include <avxintrin.h>\n  #endif\n  #if !defined(__AVX2__)\n    #include <avx2intrin.h>\n  #endif\n  #if !defined(__VAES__)\n    #include <vaesintrin.h>\n  #endif\n#endif  // __clang__ && _MSC_VER\n\n#ifndef ATTRIB_VAES\n  #define ATTRIB_VAES\n#endif\n\n#define VAES_FUNC_START2(name) \\\nAES_FUNC_START (name); \\\nATTRIB_VAES \\\nAES_FUNC_START (name)\n\nVAES_FUNC_START2 (AesCbc_Decode_HW_256)\n{\n  __m128i *p = (__m128i *)(void *)ivAes;\n  __m128i *data = (__m128i *)(void *)data8;\n  __m128i iv = *p;\n  const __m128i *dataEnd;\n  const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;\n  p += 2;\n  \n  WIDE_LOOP_START_AVX(;)\n  {\n    const __m256i *w = keys + numRounds - 2;\n    \n    WOP (AVX_DECLARE_VAR)\n    WOP (AVX_LOAD_data)\n    AVX_WOP_KEY (AVX_AES_XOR, 1)\n\n    do\n    {\n      AVX_WOP_KEY (AVX_AES_DEC, 0)\n      w--;\n    }\n    while (w != keys);\n    AVX_WOP_KEY (AVX_AES_DEC_LAST, 0)\n\n    AVX_XOR (m0, _mm256_setr_m128i(iv, LOAD_data_ii(0)))\n    WOP_M1 (AVX_XOR_data_M1)\n    LOAD_data (iv, NUM_WAYS * 2 - 1)\n    WOP (AVX_STORE_data)\n  }\n  WIDE_LOOP_END_AVX(;)\n\n  SINGLE_LOOP\n  {\n    const __m128i *w = p - 2 + (size_t)*(const UInt32 *)(p + 1 - 2) * 2;\n    __m128i m = _mm_xor_si128 (w[2], LOAD_data_ii(0));\n    do\n    {\n      MM_OP_m (_mm_aesdec_si128, w[1])\n      MM_OP_m (_mm_aesdec_si128, w[0])\n      w -= 2;\n    }\n    while (w != p);\n    MM_OP_m (_mm_aesdec_si128,     w[1])\n    MM_OP_m (_mm_aesdeclast_si128, w[0])\n\n    MM_XOR (m, iv)\n    LOAD_data(iv, 0)\n    STORE_data(m, 0)\n  }\n  \n  p[-2] = iv;\n}\n\n\n/*\nSSE2: _mm_cvtsi32_si128 : movd\nAVX:  _mm256_setr_m128i            : vinsertf128\nAVX2: _mm256_add_epi64             : vpaddq ymm, ymm, ymm\n      _mm256_extracti128_si256     : vextracti128\n      _mm256_broadcastsi128_si256  : vbroadcasti128\n*/\n\n#define AVX_CTR_LOOP_START  \\\n    ctr2 = _mm256_setr_m128i(_mm_sub_epi64(ctr, one), ctr); \\\n    two = _mm256_setr_m128i(one, one); \\\n    two = _mm256_add_epi64(two, two); \\\n\n// two = _mm256_setr_epi64x(2, 0, 2, 0);\n  \n#define AVX_CTR_LOOP_ENC  \\\n    ctr = _mm256_extracti128_si256 (ctr2, 1); \\\n \nVAES_FUNC_START2 (AesCtr_Code_HW_256)\n{\n  __m128i *p = (__m128i *)(void *)ivAes;\n  __m128i *data = (__m128i *)(void *)data8;\n  __m128i ctr = *p;\n  const UInt32 numRounds = *(const UInt32 *)(p + 1) * 2 + 1;\n  const __m128i *dataEnd;\n  const __m128i one = _mm_cvtsi32_si128(1);\n  __m256i ctr2, two;\n  p += 2;\n  \n  WIDE_LOOP_START_AVX (AVX_CTR_LOOP_START)\n  {\n    const __m256i *w = keys;\n    UInt32 r = numRounds - 2;\n    WOP (AVX_DECLARE_VAR)\n    AVX_WOP_KEY (AVX_CTR_START, 0)\n\n    w += 1;\n    do\n    {\n      AVX_WOP_KEY (AVX_AES_ENC, 0)\n      w += 1;\n    }\n    while (--r);\n    AVX_WOP_KEY (AVX_AES_ENC_LAST, 0)\n   \n    WOP (AVX_CTR_END)\n  }\n  WIDE_LOOP_END_AVX (AVX_CTR_LOOP_ENC)\n  \n  SINGLE_LOOP\n  {\n    UInt32 numRounds2 = *(const UInt32 *)(p - 2 + 1) - 1;\n    const __m128i *w = p;\n    __m128i m;\n    MM_OP (_mm_add_epi64, ctr, one)\n    m = _mm_xor_si128 (ctr, p[0]);\n    w += 1;\n    do\n    {\n      MM_OP_m (_mm_aesenc_si128, w[0])\n      MM_OP_m (_mm_aesenc_si128, w[1])\n      w += 2;\n    }\n    while (--numRounds2);\n    MM_OP_m (_mm_aesenc_si128,     w[0])\n    MM_OP_m (_mm_aesenclast_si128, w[1])\n    CTR_END (m, 0)\n  }\n\n  p[-2] = ctr;\n}\n\n#endif // USE_INTEL_VAES\n\n#else // USE_INTEL_AES\n\n/* no USE_INTEL_AES */\n\n#if defined(Z7_USE_AES_HW_STUB)\n// We can compile this file with another C compiler,\n// or we can compile asm version.\n// So we can generate real code instead of this stub function.\n// #if defined(_MSC_VER)\n#pragma message(\"AES  HW_SW stub was used\")\n// #endif\n\n#if !defined(USE_INTEL_VAES) && defined(Z7_USE_VAES_HW_STUB)\n#define AES_TYPE_keys UInt32\n#define AES_TYPE_data Byte\n#endif\n\n#define AES_FUNC_START(name) \\\n    void Z7_FASTCALL name(UInt32 *p, Byte *data, size_t numBlocks) \\\n\n#define AES_COMPAT_STUB(name) \\\n    AES_FUNC_START(name); \\\n    AES_FUNC_START(name ## _HW) \\\n    { name(p, data, numBlocks); }\n\nAES_COMPAT_STUB (AesCbc_Encode)\nAES_COMPAT_STUB (AesCbc_Decode)\nAES_COMPAT_STUB (AesCtr_Code)\n#endif // Z7_USE_AES_HW_STUB\n\n#endif // USE_INTEL_AES\n\n\n#ifndef USE_INTEL_VAES\n#if defined(Z7_USE_VAES_HW_STUB)\n// #if defined(_MSC_VER)\n#pragma message(\"VAES HW_SW stub was used\")\n// #endif\n\n#define VAES_COMPAT_STUB(name) \\\n    void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks); \\\n    void Z7_FASTCALL name ## _256(UInt32 *p, Byte *data, size_t numBlocks) \\\n    { name((AES_TYPE_keys *)(void *)p, (AES_TYPE_data *)(void *)data, numBlocks); }\n\nVAES_COMPAT_STUB (AesCbc_Decode_HW)\nVAES_COMPAT_STUB (AesCtr_Code_HW)\n#endif\n#endif // ! USE_INTEL_VAES\n\n\n\n\n#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)\n\n  #if   defined(__ARM_FEATURE_AES) \\\n     || defined(__ARM_FEATURE_CRYPTO)\n    #define USE_HW_AES\n  #else\n    #if  defined(MY_CPU_ARM64) \\\n      || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \\\n      || defined(Z7_MSC_VER_ORIGINAL)\n    #if  defined(__ARM_FP) && \\\n          (   defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \\\n           || defined(__GNUC__) && (__GNUC__ >= 6) \\\n          ) \\\n      || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)\n    #if  defined(MY_CPU_ARM64) \\\n      || !defined(Z7_CLANG_VERSION) \\\n      || defined(__ARM_NEON) && \\\n          (Z7_CLANG_VERSION < 170000 || \\\n           Z7_CLANG_VERSION > 170001)\n      #define USE_HW_AES\n    #endif\n    #endif\n    #endif\n  #endif\n\n#ifdef USE_HW_AES\n\n// #pragma message(\"=== AES HW === \")\n// __ARM_FEATURE_CRYPTO macro is deprecated in favor of the finer grained feature macro __ARM_FEATURE_AES\n\n#if defined(__clang__) || defined(__GNUC__)\n#if !defined(__ARM_FEATURE_AES) && \\\n    !defined(__ARM_FEATURE_CRYPTO)\n  #ifdef MY_CPU_ARM64\n#if defined(__clang__)\n    #define ATTRIB_AES __attribute__((__target__(\"crypto\")))\n#else\n    #define ATTRIB_AES __attribute__((__target__(\"+crypto\")))\n#endif\n  #else\n#if defined(__clang__)\n    #define ATTRIB_AES __attribute__((__target__(\"armv8-a,aes\")))\n#else\n    #define ATTRIB_AES __attribute__((__target__(\"fpu=crypto-neon-fp-armv8\")))\n#endif\n  #endif\n#endif\n#else\n  // _MSC_VER\n  // for arm32\n  #define _ARM_USE_NEW_NEON_INTRINSICS\n#endif\n\n#ifndef ATTRIB_AES\n  #define ATTRIB_AES\n#endif\n\n#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)\n#include <arm64_neon.h>\n#else\n/*\n  clang-17.0.1: error : Cannot select: intrinsic %llvm.arm.neon.aese\n  clang\n   3.8.1 : __ARM_NEON             :                    defined(__ARM_FEATURE_CRYPTO)\n   7.0.1 : __ARM_NEON             : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)\n  11.?.0 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)\n  13.0.1 : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8 && defined(__ARM_FEATURE_AES)\n  16     : __ARM_NEON && __ARM_FP : __ARM_ARCH >= 8\n*/\n#if defined(__clang__) && __clang_major__ < 16\n#if !defined(__ARM_FEATURE_AES) && \\\n    !defined(__ARM_FEATURE_CRYPTO)\n//     #pragma message(\"=== we set __ARM_FEATURE_CRYPTO 1 === \")\n    Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n    #define Z7_ARM_FEATURE_CRYPTO_WAS_SET 1\n// #if defined(__clang__) && __clang_major__ < 13\n    #define __ARM_FEATURE_CRYPTO 1\n// #else\n    #define __ARM_FEATURE_AES 1\n// #endif\n    Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif\n#endif // clang\n\n#if defined(__clang__)\n\n#if defined(__ARM_ARCH) && __ARM_ARCH < 8\n    Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n//    #pragma message(\"#define __ARM_ARCH 8\")\n    #undef  __ARM_ARCH\n    #define __ARM_ARCH 8\n    Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif\n\n#endif // clang\n\n#include <arm_neon.h>\n\n#if defined(Z7_ARM_FEATURE_CRYPTO_WAS_SET) && \\\n    defined(__ARM_FEATURE_CRYPTO) && \\\n    defined(__ARM_FEATURE_AES)\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n    #undef __ARM_FEATURE_CRYPTO\n    #undef __ARM_FEATURE_AES\n    #undef Z7_ARM_FEATURE_CRYPTO_WAS_SET\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n//    #pragma message(\"=== we undefine __ARM_FEATURE_CRYPTO === \")\n#endif\n\n#endif // Z7_MSC_VER_ORIGINAL\n\ntypedef uint8x16_t v128;\n\n#define AES_FUNC_START(name) \\\n    void Z7_FASTCALL name(UInt32 *ivAes, Byte *data8, size_t numBlocks)\n    // void Z7_FASTCALL name(v128 *p, v128 *data, size_t numBlocks)\n\n#define AES_FUNC_START2(name) \\\nAES_FUNC_START (name); \\\nATTRIB_AES \\\nAES_FUNC_START (name)\n\n#define MM_OP(op, dest, src)  dest = op(dest, src);\n#define MM_OP_m(op, src)      MM_OP(op, m, src)\n#define MM_OP1_m(op)          m = op(m);\n\n#define MM_XOR( dest, src)    MM_OP(veorq_u8, dest, src)\n#define MM_XOR_m( src)        MM_XOR(m, src)\n\n#define AES_E_m(k)     MM_OP_m (vaeseq_u8, k)\n#define AES_E_MC_m(k)  AES_E_m (k)  MM_OP1_m(vaesmcq_u8)\n\n\nAES_FUNC_START2 (AesCbc_Encode_HW)\n{\n  if (numBlocks == 0)\n    return;\n  {\n  v128 * const p = (v128 *)(void *)ivAes;\n  v128 *data = (v128 *)(void *)data8;\n  v128 m = *p;\n  const UInt32 numRounds2 = *(const UInt32 *)(p + 1);\n  const v128 *w = p + (size_t)numRounds2 * 2;\n  const v128 k0 = p[2];\n  const v128 k1 = p[3];\n  const v128 k2 = p[4];\n  const v128 k3 = p[5];\n  const v128 k4 = p[6];\n  const v128 k5 = p[7];\n  const v128 k6 = p[8];\n  const v128 k7 = p[9];\n  const v128 k8 = p[10];\n  const v128 k9 = p[11];\n  const v128 k_z4 = w[-2];\n  const v128 k_z3 = w[-1];\n  const v128 k_z2 = w[0];\n  const v128 k_z1 = w[1];\n  const v128 k_z0 = w[2];\n  // we don't use optimization veorq_u8(*data, k_z0) that can reduce one cycle,\n  // because gcc/clang compilers are not good for that optimization.\n  do\n  {\n    MM_XOR_m (*data)\n    AES_E_MC_m (k0)\n    AES_E_MC_m (k1)\n    AES_E_MC_m (k2)\n    AES_E_MC_m (k3)\n    AES_E_MC_m (k4)\n    AES_E_MC_m (k5)\n    if (numRounds2 >= 6)\n    {\n      AES_E_MC_m (k6)\n      AES_E_MC_m (k7)\n      if (numRounds2 != 6)\n      {\n        AES_E_MC_m (k8)\n        AES_E_MC_m (k9)\n      }\n    }\n    AES_E_MC_m (k_z4)\n    AES_E_MC_m (k_z3)\n    AES_E_MC_m (k_z2)\n    AES_E_m    (k_z1)\n    MM_XOR_m   (k_z0)\n    *data++ = m;\n  }\n  while (--numBlocks);\n  *p = m;\n  }\n}\n\n\n#define WOP_1(op)\n#define WOP_2(op)   WOP_1 (op)  op (m1, 1)\n#define WOP_3(op)   WOP_2 (op)  op (m2, 2)\n#define WOP_4(op)   WOP_3 (op)  op (m3, 3)\n#define WOP_5(op)   WOP_4 (op)  op (m4, 4)\n#define WOP_6(op)   WOP_5 (op)  op (m5, 5)\n#define WOP_7(op)   WOP_6 (op)  op (m6, 6)\n#define WOP_8(op)   WOP_7 (op)  op (m7, 7)\n\n  #define NUM_WAYS      8\n  #define WOP_M1    WOP_8\n\n#define WOP(op)  op (m0, 0)   WOP_M1(op)\n\n#define DECLARE_VAR(reg, ii)  v128 reg;\n#define LOAD_data(  reg, ii)  reg = data[ii];\n#define STORE_data( reg, ii)  data[ii] = reg;\n#if (NUM_WAYS > 1)\n#define XOR_data_M1(reg, ii)  MM_XOR (reg, data[ii- 1])\n#endif\n\n#define MM_OP_key(op, reg)  MM_OP (op, reg, key)\n\n#define AES_D_m(k)      MM_OP_m (vaesdq_u8, k)\n#define AES_D_IMC_m(k)  AES_D_m (k)  MM_OP1_m (vaesimcq_u8)\n\n#define AES_XOR(   reg, ii)  MM_OP_key (veorq_u8,  reg)\n#define AES_D(     reg, ii)  MM_OP_key (vaesdq_u8, reg)\n#define AES_E(     reg, ii)  MM_OP_key (vaeseq_u8, reg)\n\n#define AES_D_IMC( reg, ii)  AES_D (reg, ii)  reg = vaesimcq_u8(reg);\n#define AES_E_MC(  reg, ii)  AES_E (reg, ii)  reg = vaesmcq_u8(reg);\n\n#define CTR_START(reg, ii)  MM_OP (vaddq_u64, ctr, one)  reg = vreinterpretq_u8_u64(ctr);\n#define CTR_END(  reg, ii)  MM_XOR (data[ii], reg)\n\n#define WOP_KEY(op, n) { \\\n    const v128 key = w[n]; \\\n    WOP(op) }\n\n#define WIDE_LOOP_START  \\\n    dataEnd = data + numBlocks;  \\\n    if (numBlocks >= NUM_WAYS)  \\\n    { dataEnd -= NUM_WAYS; do {  \\\n\n#define WIDE_LOOP_END  \\\n    data += NUM_WAYS;  \\\n    } while (data <= dataEnd);  \\\n    dataEnd += NUM_WAYS; }  \\\n\n#define SINGLE_LOOP  \\\n    for (; data < dataEnd; data++)\n\n\nAES_FUNC_START2 (AesCbc_Decode_HW)\n{\n  v128 *p = (v128 *)(void *)ivAes;\n  v128 *data = (v128 *)(void *)data8;\n  v128 iv = *p;\n  const v128 * const wStart = p + (size_t)*(const UInt32 *)(p + 1) * 2;\n  const v128 *dataEnd;\n  p += 2;\n  \n  WIDE_LOOP_START\n  {\n    const v128 *w = wStart;\n    WOP (DECLARE_VAR)\n    WOP (LOAD_data)\n    WOP_KEY (AES_D_IMC, 2)\n    do\n    {\n      WOP_KEY (AES_D_IMC, 1)\n      WOP_KEY (AES_D_IMC, 0)\n      w -= 2;\n    }\n    while (w != p);\n    WOP_KEY (AES_D,   1)\n    WOP_KEY (AES_XOR, 0)\n    MM_XOR (m0, iv)\n    WOP_M1 (XOR_data_M1)\n    LOAD_data(iv, NUM_WAYS - 1)\n    WOP (STORE_data)\n  }\n  WIDE_LOOP_END\n\n  SINGLE_LOOP\n  {\n    const v128 *w = wStart;\n    v128 m;  LOAD_data(m, 0)\n    AES_D_IMC_m (w[2])\n    do\n    {\n      AES_D_IMC_m (w[1])\n      AES_D_IMC_m (w[0])\n      w -= 2;\n    }\n    while (w != p);\n    AES_D_m  (w[1])\n    MM_XOR_m (w[0])\n    MM_XOR_m (iv)\n    LOAD_data(iv, 0)\n    STORE_data(m, 0)\n  }\n  \n  p[-2] = iv;\n}\n\n\nAES_FUNC_START2 (AesCtr_Code_HW)\n{\n  v128 *p = (v128 *)(void *)ivAes;\n  v128 *data = (v128 *)(void *)data8;\n  uint64x2_t ctr = vreinterpretq_u64_u8(*p);\n  const v128 * const wEnd = p + (size_t)*(const UInt32 *)(p + 1) * 2;\n  const v128 *dataEnd;\n// the bug in clang:\n// __builtin_neon_vsetq_lane_i64(__s0, (int8x16_t)__s1, __p2);\n#if defined(__clang__) && (__clang_major__ <= 9)\n#pragma GCC diagnostic ignored \"-Wvector-conversion\"\n#endif\n  const uint64x2_t one = vsetq_lane_u64(1, vdupq_n_u64(0), 0);\n  p += 2;\n  \n  WIDE_LOOP_START\n  {\n    const v128 *w = p;\n    WOP (DECLARE_VAR)\n    WOP (CTR_START)\n    do\n    {\n      WOP_KEY (AES_E_MC, 0)\n      WOP_KEY (AES_E_MC, 1)\n      w += 2;\n    }\n    while (w != wEnd);\n    WOP_KEY (AES_E_MC, 0)\n    WOP_KEY (AES_E,    1)\n    WOP_KEY (AES_XOR,  2)\n    WOP (CTR_END)\n  }\n  WIDE_LOOP_END\n\n  SINGLE_LOOP\n  {\n    const v128 *w = p;\n    v128 m;\n    CTR_START (m, 0)\n    do\n    {\n      AES_E_MC_m (w[0])\n      AES_E_MC_m (w[1])\n      w += 2;\n    }\n    while (w != wEnd);\n    AES_E_MC_m (w[0])\n    AES_E_m    (w[1])\n    MM_XOR_m   (w[2])\n    CTR_END (m, 0)\n  }\n  \n  p[-2] = vreinterpretq_u8_u64(ctr);\n}\n\n#endif // USE_HW_AES\n\n#endif // MY_CPU_ARM_OR_ARM64\n\n#undef NUM_WAYS\n#undef WOP_M1\n#undef WOP\n#undef DECLARE_VAR\n#undef LOAD_data\n#undef STORE_data\n#undef USE_INTEL_AES\n#undef USE_HW_AES\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Alloc.c",
    "content": "﻿/* Alloc.c -- Memory allocation functions\n2024-02-18 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#ifdef _WIN32\n#include \"7zWindows.h\"\n#endif\n#include <stdlib.h>\n\n#include \"Alloc.h\"\n\n#if defined(Z7_LARGE_PAGES) && defined(_WIN32) && \\\n    (!defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502)  // < Win2003 (xp-64)\n  #define Z7_USE_DYN_GetLargePageMinimum\n#endif\n\n// for debug:\n#if 0\n#if defined(__CHERI__) && defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)\n// #pragma message(\"=== Z7_ALLOC_NO_OFFSET_ALLOCATOR === \")\n#define Z7_ALLOC_NO_OFFSET_ALLOCATOR\n#endif\n#endif\n\n// #define SZ_ALLOC_DEBUG\n/* #define SZ_ALLOC_DEBUG */\n\n/* use SZ_ALLOC_DEBUG to debug alloc/free operations */\n#ifdef SZ_ALLOC_DEBUG\n\n#include <string.h>\n#include <stdio.h>\nstatic int g_allocCount = 0;\n#ifdef _WIN32\nstatic int g_allocCountMid = 0;\nstatic int g_allocCountBig = 0;\n#endif\n\n\n#define CONVERT_INT_TO_STR(charType, tempSize) \\\n  char temp[tempSize]; unsigned i = 0; \\\n  while (val >= 10) { temp[i++] = (char)('0' + (unsigned)(val % 10)); val /= 10; } \\\n  *s++ = (charType)('0' + (unsigned)val); \\\n  while (i != 0) { i--; *s++ = temp[i]; } \\\n  *s = 0;\n\nstatic void ConvertUInt64ToString(UInt64 val, char *s)\n{\n  CONVERT_INT_TO_STR(char, 24)\n}\n\n#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))\n\nstatic void ConvertUInt64ToHex(UInt64 val, char *s)\n{\n  UInt64 v = val;\n  unsigned i;\n  for (i = 1;; i++)\n  {\n    v >>= 4;\n    if (v == 0)\n      break;\n  }\n  s[i] = 0;\n  do\n  {\n    unsigned t = (unsigned)(val & 0xF);\n    val >>= 4;\n    s[--i] = GET_HEX_CHAR(t);\n  }\n  while (i);\n}\n\n#define DEBUG_OUT_STREAM stderr\n\nstatic void Print(const char *s)\n{\n  fputs(s, DEBUG_OUT_STREAM);\n}\n\nstatic void PrintAligned(const char *s, size_t align)\n{\n  size_t len = strlen(s);\n  for(;;)\n  {\n    fputc(' ', DEBUG_OUT_STREAM);\n    if (len >= align)\n      break;\n    ++len;\n  }\n  Print(s);\n}\n\nstatic void PrintLn(void)\n{\n  Print(\"\\n\");\n}\n\nstatic void PrintHex(UInt64 v, size_t align)\n{\n  char s[32];\n  ConvertUInt64ToHex(v, s);\n  PrintAligned(s, align);\n}\n\nstatic void PrintDec(int v, size_t align)\n{\n  char s[32];\n  ConvertUInt64ToString((unsigned)v, s);\n  PrintAligned(s, align);\n}\n\nstatic void PrintAddr(void *p)\n{\n  PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12);\n}\n\n\n#define PRINT_REALLOC(name, cnt, size, ptr) { \\\n    Print(name \" \"); \\\n    if (!ptr) PrintDec(cnt++, 10); \\\n    PrintHex(size, 10); \\\n    PrintAddr(ptr); \\\n    PrintLn(); }\n\n#define PRINT_ALLOC(name, cnt, size, ptr) { \\\n    Print(name \" \"); \\\n    PrintDec(cnt++, 10); \\\n    PrintHex(size, 10); \\\n    PrintAddr(ptr); \\\n    PrintLn(); }\n \n#define PRINT_FREE(name, cnt, ptr) if (ptr) { \\\n    Print(name \" \"); \\\n    PrintDec(--cnt, 10); \\\n    PrintAddr(ptr); \\\n    PrintLn(); }\n \n#else\n\n#ifdef _WIN32\n#define PRINT_ALLOC(name, cnt, size, ptr)\n#endif\n#define PRINT_FREE(name, cnt, ptr)\n#define Print(s)\n#define PrintLn()\n#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR\n#define PrintHex(v, align)\n#endif\n#define PrintAddr(p)\n\n#endif\n\n\n/*\nby specification:\n  malloc(non_NULL, 0)   : returns NULL or a unique pointer value that can later be successfully passed to free()\n  realloc(NULL, size)   : the call is equivalent to malloc(size)\n  realloc(non_NULL, 0)  : the call is equivalent to free(ptr)\n\nin main compilers:\n  malloc(0)             : returns non_NULL\n  realloc(NULL,     0)  : returns non_NULL\n  realloc(non_NULL, 0)  : returns NULL\n*/\n\n\nvoid *MyAlloc(size_t size)\n{\n  if (size == 0)\n    return NULL;\n  // PRINT_ALLOC(\"Alloc    \", g_allocCount, size, NULL)\n  #ifdef SZ_ALLOC_DEBUG\n  {\n    void *p = malloc(size);\n    if (p)\n    {\n      PRINT_ALLOC(\"Alloc    \", g_allocCount, size, p)\n    }\n    return p;\n  }\n  #else\n  return malloc(size);\n  #endif\n}\n\nvoid MyFree(void *address)\n{\n  PRINT_FREE(\"Free    \", g_allocCount, address)\n  \n  free(address);\n}\n\nvoid *MyRealloc(void *address, size_t size)\n{\n  if (size == 0)\n  {\n    MyFree(address);\n    return NULL;\n  }\n  // PRINT_REALLOC(\"Realloc  \", g_allocCount, size, address)\n  #ifdef SZ_ALLOC_DEBUG\n  {\n    void *p = realloc(address, size);\n    if (p)\n    {\n      PRINT_REALLOC(\"Realloc    \", g_allocCount, size, address)\n    }\n    return p;\n  }\n  #else\n  return realloc(address, size);\n  #endif\n}\n\n\n#ifdef _WIN32\n\nvoid *MidAlloc(size_t size)\n{\n  if (size == 0)\n    return NULL;\n  #ifdef SZ_ALLOC_DEBUG\n  {\n    void *p = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);\n    if (p)\n    {\n      PRINT_ALLOC(\"Alloc-Mid\", g_allocCountMid, size, p)\n    }\n    return p;\n  }\n  #else\n  return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);\n  #endif\n}\n\nvoid MidFree(void *address)\n{\n  PRINT_FREE(\"Free-Mid\", g_allocCountMid, address)\n\n  if (!address)\n    return;\n  VirtualFree(address, 0, MEM_RELEASE);\n}\n\n#ifdef Z7_LARGE_PAGES\n\n#ifdef MEM_LARGE_PAGES\n  #define MY_MEM_LARGE_PAGES  MEM_LARGE_PAGES\n#else\n  #define MY_MEM_LARGE_PAGES  0x20000000\n#endif\n\nextern\nSIZE_T g_LargePageSize;\nSIZE_T g_LargePageSize = 0;\ntypedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);\n\nvoid SetLargePageSize(void)\n{\n  SIZE_T size;\n#ifdef Z7_USE_DYN_GetLargePageMinimum\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\n  const\n   Func_GetLargePageMinimum fn =\n  (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT(\"kernel32.dll\")),\n       \"GetLargePageMinimum\");\n  if (!fn)\n    return;\n  size = fn();\n#else\n  size = GetLargePageMinimum();\n#endif\n  if (size == 0 || (size & (size - 1)) != 0)\n    return;\n  g_LargePageSize = size;\n}\n\n#endif // Z7_LARGE_PAGES\n\nvoid *BigAlloc(size_t size)\n{\n  if (size == 0)\n    return NULL;\n\n  PRINT_ALLOC(\"Alloc-Big\", g_allocCountBig, size, NULL)\n\n  #ifdef Z7_LARGE_PAGES\n  {\n    SIZE_T ps = g_LargePageSize;\n    if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))\n    {\n      size_t size2;\n      ps--;\n      size2 = (size + ps) & ~ps;\n      if (size2 >= size)\n      {\n        void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE);\n        if (p)\n        {\n          PRINT_ALLOC(\"Alloc-BM \", g_allocCountMid, size2, p)\n          return p;\n        }\n      }\n    }\n  }\n  #endif\n\n  return MidAlloc(size);\n}\n\nvoid BigFree(void *address)\n{\n  PRINT_FREE(\"Free-Big\", g_allocCountBig, address)\n  MidFree(address);\n}\n\n#endif // _WIN32\n\n\nstatic void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p)  return MyAlloc(size); }\nstatic void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p)  MyFree(address); }\nconst ISzAlloc g_Alloc = { SzAlloc, SzFree };\n\n#ifdef _WIN32\nstatic void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p)  return MidAlloc(size); }\nstatic void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p)  MidFree(address); }\nstatic void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p)  return BigAlloc(size); }\nstatic void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p)  BigFree(address); }\nconst ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };\nconst ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };\n#endif\n\n#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR\n\n#define ADJUST_ALLOC_SIZE 0\n/*\n#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1)\n*/\n/*\n  Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if\n     MyAlloc() can return address that is NOT multiple of sizeof(void *).\n*/\n\n/*\n  uintptr_t : <stdint.h> C99 (optional)\n            : unsupported in VS6\n*/\ntypedef\n  #ifdef _WIN32\n    UINT_PTR\n  #elif 1\n    uintptr_t\n  #else\n    ptrdiff_t\n  #endif\n    MY_uintptr_t;\n\n#if 0 \\\n    || (defined(__CHERI__) \\\n    || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ > 8))\n// for 128-bit pointers (cheri):\n#define MY_ALIGN_PTR_DOWN(p, align)  \\\n    ((void *)((char *)(p) - ((size_t)(MY_uintptr_t)(p) & ((align) - 1))))\n#else\n#define MY_ALIGN_PTR_DOWN(p, align) \\\n    ((void *)((((MY_uintptr_t)(p)) & ~((MY_uintptr_t)(align) - 1))))\n#endif\n\n#endif\n\n#if !defined(_WIN32) \\\n    && (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \\\n        || defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L))\n  #define USE_posix_memalign\n#endif\n\n#ifndef USE_posix_memalign\n#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align)\n#endif\n\n/*\n  This posix_memalign() is for test purposes only.\n  We also need special Free() function instead of free(),\n  if this posix_memalign() is used.\n*/\n\n/*\nstatic int posix_memalign(void **ptr, size_t align, size_t size)\n{\n  size_t newSize = size + align;\n  void *p;\n  void *pAligned;\n  *ptr = NULL;\n  if (newSize < size)\n    return 12; // ENOMEM\n  p = MyAlloc(newSize);\n  if (!p)\n    return 12; // ENOMEM\n  pAligned = MY_ALIGN_PTR_UP_PLUS(p, align);\n  ((void **)pAligned)[-1] = p;\n  *ptr = pAligned;\n  return 0;\n}\n*/\n\n/*\n  ALLOC_ALIGN_SIZE >= sizeof(void *)\n  ALLOC_ALIGN_SIZE >= cache_line_size\n*/\n\n#define ALLOC_ALIGN_SIZE ((size_t)1 << 7)\n\nvoid *z7_AlignedAlloc(size_t size)\n{\n#ifndef USE_posix_memalign\n  \n  void *p;\n  void *pAligned;\n  size_t newSize;\n\n  /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned\n     block to prevent cache line sharing with another allocated blocks */\n\n  newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE;\n  if (newSize < size)\n    return NULL;\n\n  p = MyAlloc(newSize);\n  \n  if (!p)\n    return NULL;\n  pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE);\n\n  Print(\" size=\"); PrintHex(size, 8);\n  Print(\" a_size=\"); PrintHex(newSize, 8);\n  Print(\" ptr=\"); PrintAddr(p);\n  Print(\" a_ptr=\"); PrintAddr(pAligned);\n  PrintLn();\n\n  ((void **)pAligned)[-1] = p;\n\n  return pAligned;\n\n#else\n\n  void *p;\n  if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size))\n    return NULL;\n\n  Print(\" posix_memalign=\"); PrintAddr(p);\n  PrintLn();\n\n  return p;\n\n#endif\n}\n\n\nvoid z7_AlignedFree(void *address)\n{\n#ifndef USE_posix_memalign\n  if (address)\n    MyFree(((void **)address)[-1]);\n#else\n  free(address);\n#endif\n}\n\n\nstatic void *SzAlignedAlloc(ISzAllocPtr pp, size_t size)\n{\n  UNUSED_VAR(pp)\n  return z7_AlignedAlloc(size);\n}\n\n\nstatic void SzAlignedFree(ISzAllocPtr pp, void *address)\n{\n  UNUSED_VAR(pp)\n#ifndef USE_posix_memalign\n  if (address)\n    MyFree(((void **)address)[-1]);\n#else\n  free(address);\n#endif\n}\n\n\nconst ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };\n\n\n\n/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */\n#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR\n#if 1\n  #define MY_ALIGN_PTR_DOWN_1(p)  MY_ALIGN_PTR_DOWN(p, sizeof(void *))\n  #define REAL_BLOCK_PTR_VAR(p)  ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1]\n#else\n  // we can use this simplified code,\n  // if (CAlignOffsetAlloc::offset == (k * sizeof(void *))\n  #define REAL_BLOCK_PTR_VAR(p)  (((void **)(p))[-1])\n#endif\n#endif\n\n\n#if 0\n#ifndef Z7_ALLOC_NO_OFFSET_ALLOCATOR\n#include <stdio.h>\nstatic void PrintPtr(const char *s, const void *p)\n{\n  const Byte *p2 = (const Byte *)&p;\n  unsigned i;\n  printf(\"%s %p \", s, p);\n  for (i = sizeof(p); i != 0;)\n  {\n    i--;\n    printf(\"%02x\", p2[i]);\n  }\n  printf(\"\\n\");\n}\n#endif\n#endif\n\n\nstatic void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size)\n{\n#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)\n  UNUSED_VAR(pp)\n  return z7_AlignedAlloc(size);\n#else\n  const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);\n  void *adr;\n  void *pAligned;\n  size_t newSize;\n  size_t extra;\n  size_t alignSize = (size_t)1 << p->numAlignBits;\n\n  if (alignSize < sizeof(void *))\n    alignSize = sizeof(void *);\n  \n  if (p->offset >= alignSize)\n    return NULL;\n\n  /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned\n     block to prevent cache line sharing with another allocated blocks */\n  extra = p->offset & (sizeof(void *) - 1);\n  newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE;\n  if (newSize < size)\n    return NULL;\n\n  adr = ISzAlloc_Alloc(p->baseAlloc, newSize);\n  \n  if (!adr)\n    return NULL;\n\n  pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr +\n      alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset;\n\n#if 0\n  printf(\"\\nalignSize = %6x, offset=%6x, size=%8x \\n\", (unsigned)alignSize, (unsigned)p->offset, (unsigned)size);\n  PrintPtr(\"base\", adr);\n  PrintPtr(\"alig\", pAligned);\n#endif\n\n  PrintLn();\n  Print(\"- Aligned: \");\n  Print(\" size=\"); PrintHex(size, 8);\n  Print(\" a_size=\"); PrintHex(newSize, 8);\n  Print(\" ptr=\"); PrintAddr(adr);\n  Print(\" a_ptr=\"); PrintAddr(pAligned);\n  PrintLn();\n\n  REAL_BLOCK_PTR_VAR(pAligned) = adr;\n\n  return pAligned;\n#endif\n}\n\n\nstatic void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address)\n{\n#if defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR)\n  UNUSED_VAR(pp)\n  z7_AlignedFree(address);\n#else\n  if (address)\n  {\n    const CAlignOffsetAlloc *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CAlignOffsetAlloc, vt);\n    PrintLn();\n    Print(\"- Aligned Free: \");\n    PrintLn();\n    ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address));\n  }\n#endif\n}\n\n\nvoid AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p)\n{\n  p->vt.Alloc = AlignOffsetAlloc_Alloc;\n  p->vt.Free = AlignOffsetAlloc_Free;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Alloc.h",
    "content": "﻿/* Alloc.h -- Memory allocation functions\n2024-01-22 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_ALLOC_H\n#define ZIP7_INC_ALLOC_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n/*\n  MyFree(NULL)        : is allowed, as free(NULL)\n  MyAlloc(0)          : returns NULL : but malloc(0)        is allowed to return NULL or non_NULL\n  MyRealloc(NULL, 0)  : returns NULL : but realloc(NULL, 0) is allowed to return NULL or non_NULL\nMyRealloc() is similar to realloc() for the following cases:\n  MyRealloc(non_NULL, 0)         : returns NULL and always calls MyFree(ptr)\n  MyRealloc(NULL, non_ZERO)      : returns NULL, if allocation failed\n  MyRealloc(non_NULL, non_ZERO)  : returns NULL, if reallocation failed\n*/\n\nvoid *MyAlloc(size_t size);\nvoid MyFree(void *address);\nvoid *MyRealloc(void *address, size_t size);\n\nvoid *z7_AlignedAlloc(size_t size);\nvoid  z7_AlignedFree(void *p);\n\n#ifdef _WIN32\n\n#ifdef Z7_LARGE_PAGES\nvoid SetLargePageSize(void);\n#endif\n\nvoid *MidAlloc(size_t size);\nvoid MidFree(void *address);\nvoid *BigAlloc(size_t size);\nvoid BigFree(void *address);\n\n/* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */\n\n#else\n\n#define MidAlloc(size)    z7_AlignedAlloc(size)\n#define MidFree(address)  z7_AlignedFree(address)\n#define BigAlloc(size)    z7_AlignedAlloc(size)\n#define BigFree(address)  z7_AlignedFree(address)\n\n#endif\n\nextern const ISzAlloc g_Alloc;\n\n#ifdef _WIN32\nextern const ISzAlloc g_BigAlloc;\nextern const ISzAlloc g_MidAlloc;\n#else\n#define g_BigAlloc g_AlignedAlloc\n#define g_MidAlloc g_AlignedAlloc\n#endif\n\nextern const ISzAlloc g_AlignedAlloc;\n\n\ntypedef struct\n{\n  ISzAlloc vt;\n  ISzAllocPtr baseAlloc;\n  unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */\n  size_t offset;         /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */\n} CAlignOffsetAlloc;\n\nvoid AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p);\n\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Bcj2.c",
    "content": "﻿/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)\n2023-03-01 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Bcj2.h\"\n#include \"CpuArch.h\"\n\n#define kTopValue ((UInt32)1 << 24)\n#define kNumBitModelTotalBits 11\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\n#define kNumMoveBits 5\n\n// UInt32 bcj2_stats[256 + 2][2];\n\nvoid Bcj2Dec_Init(CBcj2Dec *p)\n{\n  unsigned i;\n  p->state = BCJ2_STREAM_RC; // BCJ2_DEC_STATE_OK;\n  p->ip = 0;\n  p->temp = 0;\n  p->range = 0;\n  p->code = 0;\n  for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)\n    p->probs[i] = kBitModelTotal >> 1;\n}\n\nSRes Bcj2Dec_Decode(CBcj2Dec *p)\n{\n  UInt32 v = p->temp;\n  // const Byte *src;\n  if (p->range <= 5)\n  {\n    UInt32 code = p->code;\n    p->state = BCJ2_DEC_STATE_ERROR; /* for case if we return SZ_ERROR_DATA; */\n    for (; p->range != 5; p->range++)\n    {\n      if (p->range == 1 && code != 0)\n        return SZ_ERROR_DATA;\n      if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])\n      {\n        p->state = BCJ2_STREAM_RC;\n        return SZ_OK;\n      }\n      code = (code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\n      p->code = code;\n    }\n    if (code == 0xffffffff)\n      return SZ_ERROR_DATA;\n    p->range = 0xffffffff;\n  }\n  // else\n  {\n    unsigned state = p->state;\n    // we check BCJ2_IS_32BIT_STREAM() here instead of check in the main loop\n    if (BCJ2_IS_32BIT_STREAM(state))\n    {\n      const Byte *cur = p->bufs[state];\n      if (cur == p->lims[state])\n        return SZ_OK;\n      p->bufs[state] = cur + 4;\n      {\n        const UInt32 ip = p->ip + 4;\n        v = GetBe32a(cur) - ip;\n        p->ip = ip;\n      }\n      state = BCJ2_DEC_STATE_ORIG_0;\n    }\n    if ((unsigned)(state - BCJ2_DEC_STATE_ORIG_0) < 4)\n    {\n      Byte *dest = p->dest;\n      for (;;)\n      {\n        if (dest == p->destLim)\n        {\n          p->state = state;\n          p->temp = v;\n          return SZ_OK;\n        }\n        *dest++ = (Byte)v;\n        p->dest = dest;\n        if (++state == BCJ2_DEC_STATE_ORIG_3 + 1)\n          break;\n        v >>= 8;\n      }\n    }\n  }\n\n  // src = p->bufs[BCJ2_STREAM_MAIN];\n  for (;;)\n  {\n    /*\n    if (BCJ2_IS_32BIT_STREAM(p->state))\n      p->state = BCJ2_DEC_STATE_OK;\n    else\n    */\n    {\n      if (p->range < kTopValue)\n      {\n        if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])\n        {\n          p->state = BCJ2_STREAM_RC;\n          p->temp = v;\n          return SZ_OK;\n        }\n        p->range <<= 8;\n        p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\n      }\n      {\n        const Byte *src = p->bufs[BCJ2_STREAM_MAIN];\n        const Byte *srcLim;\n        Byte *dest = p->dest;\n        {\n          const SizeT rem = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - src);\n          SizeT num = (SizeT)(p->destLim - dest);\n          if (num >= rem)\n            num = rem;\n        #define NUM_ITERS 4\n        #if (NUM_ITERS & (NUM_ITERS - 1)) == 0\n          num &= ~((SizeT)NUM_ITERS - 1);   // if (NUM_ITERS == (1 << x))\n        #else\n          num -= num % NUM_ITERS; // if (NUM_ITERS != (1 << x))\n        #endif\n          srcLim = src + num;\n        }\n\n        #define NUM_SHIFT_BITS  24\n        #define ONE_ITER(indx) { \\\n          const unsigned b = src[indx]; \\\n          *dest++ = (Byte)b; \\\n          v = (v << NUM_SHIFT_BITS) | b; \\\n          if (((b + (0x100 - 0xe8)) & 0xfe) == 0) break; \\\n          if (((v - (((UInt32)0x0f << (NUM_SHIFT_BITS)) + 0x80)) & \\\n              ((((UInt32)1 << (4 + NUM_SHIFT_BITS)) - 0x1) << 4)) == 0) break; \\\n            /* ++dest */; /* v = b; */ }\n          \n        if (src != srcLim)\n        for (;;)\n        {\n            /* The dependency chain of 2-cycle for (v) calculation is not big problem here.\n               But we can remove dependency chain with v = b in the end of loop. */\n          ONE_ITER(0)\n          #if (NUM_ITERS > 1)\n            ONE_ITER(1)\n          #if (NUM_ITERS > 2)\n            ONE_ITER(2)\n          #if (NUM_ITERS > 3)\n            ONE_ITER(3)\n          #if (NUM_ITERS > 4)\n            ONE_ITER(4)\n          #if (NUM_ITERS > 5)\n            ONE_ITER(5)\n          #if (NUM_ITERS > 6)\n            ONE_ITER(6)\n          #if (NUM_ITERS > 7)\n            ONE_ITER(7)\n          #endif\n          #endif\n          #endif\n          #endif\n          #endif\n          #endif\n          #endif\n          \n          src += NUM_ITERS;\n          if (src == srcLim)\n            break;\n        }\n\n        if (src == srcLim)\n      #if (NUM_ITERS > 1)\n        for (;;)\n      #endif\n        {\n        #if (NUM_ITERS > 1)\n          if (src == p->lims[BCJ2_STREAM_MAIN] || dest == p->destLim)\n        #endif\n          {\n            const SizeT num = (SizeT)(src - p->bufs[BCJ2_STREAM_MAIN]);\n            p->bufs[BCJ2_STREAM_MAIN] = src;\n            p->dest = dest;\n            p->ip += (UInt32)num;\n            /* state BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */\n            p->state =\n              src == p->lims[BCJ2_STREAM_MAIN] ?\n                (unsigned)BCJ2_STREAM_MAIN :\n                (unsigned)BCJ2_DEC_STATE_ORIG;\n            p->temp = v;\n            return SZ_OK;\n          }\n        #if (NUM_ITERS > 1)\n          ONE_ITER(0)\n          src++;\n        #endif\n        }\n\n        {\n          const SizeT num = (SizeT)(dest - p->dest);\n          p->dest = dest; // p->dest += num;\n          p->bufs[BCJ2_STREAM_MAIN] += num; // = src;\n          p->ip += (UInt32)num;\n        }\n        {\n          UInt32 bound, ttt;\n          CBcj2Prob *prob; // unsigned index;\n          /*\n          prob = p->probs + (unsigned)((Byte)v == 0xe8 ?\n              2 + (Byte)(v >> 8) :\n              ((v >> 5) & 1));  // ((Byte)v < 0xe8 ? 0 : 1));\n          */\n          {\n            const unsigned c = ((v + 0x17) >> 6) & 1;\n            prob = p->probs + (unsigned)\n                (((0 - c) & (Byte)(v >> NUM_SHIFT_BITS)) + c + ((v >> 5) & 1));\n                // (Byte)\n                // 8x->0     : e9->1     : xxe8->xx+2\n                // 8x->0x100 : e9->0x101 : xxe8->xx\n                // (((0x100 - (e & ~v)) & (0x100 | (v >> 8))) + (e & v));\n                // (((0x101 + (~e | v)) & (0x100 | (v >> 8))) + (e & v));\n          }\n          ttt = *prob;\n          bound = (p->range >> kNumBitModelTotalBits) * ttt;\n          if (p->code < bound)\n          {\n            // bcj2_stats[prob - p->probs][0]++;\n            p->range = bound;\n            *prob = (CBcj2Prob)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\n            continue;\n          }\n          {\n            // bcj2_stats[prob - p->probs][1]++;\n            p->range -= bound;\n            p->code -= bound;\n            *prob = (CBcj2Prob)(ttt - (ttt >> kNumMoveBits));\n          }\n        }\n      }\n    }\n    {\n      /* (v == 0xe8 ? 0 : 1) uses setcc instruction with additional zero register usage in x64 MSVC. */\n      // const unsigned cj = ((Byte)v == 0xe8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;\n      const unsigned cj = (((v + 0x57) >> 6) & 1) + BCJ2_STREAM_CALL;\n      const Byte *cur = p->bufs[cj];\n      Byte *dest;\n      SizeT rem;\n      if (cur == p->lims[cj])\n      {\n        p->state = cj;\n        break;\n      }\n      v = GetBe32a(cur);\n      p->bufs[cj] = cur + 4;\n      {\n        const UInt32 ip = p->ip + 4;\n        v -= ip;\n        p->ip = ip;\n      }\n      dest = p->dest;\n      rem = (SizeT)(p->destLim - dest);\n      if (rem < 4)\n      {\n        if ((unsigned)rem > 0) { dest[0] = (Byte)v;  v >>= 8;\n        if ((unsigned)rem > 1) { dest[1] = (Byte)v;  v >>= 8;\n        if ((unsigned)rem > 2) { dest[2] = (Byte)v;  v >>= 8; }}}\n        p->temp = v;\n        p->dest = dest + rem;\n        p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;\n        break;\n      }\n      SetUi32(dest, v)\n      v >>= 24;\n      p->dest = dest + 4;\n    }\n  }\n\n  if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])\n  {\n    p->range <<= 8;\n    p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;\n  }\n  return SZ_OK;\n}\n\n#undef NUM_ITERS\n#undef ONE_ITER\n#undef NUM_SHIFT_BITS\n#undef kTopValue\n#undef kNumBitModelTotalBits\n#undef kBitModelTotal\n#undef kNumMoveBits\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Bcj2.h",
    "content": "﻿/* Bcj2.h -- BCJ2 converter for x86 code (Branch CALL/JUMP variant2)\n2023-03-02 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_BCJ2_H\n#define ZIP7_INC_BCJ2_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define BCJ2_NUM_STREAMS 4\n\nenum\n{\n  BCJ2_STREAM_MAIN,\n  BCJ2_STREAM_CALL,\n  BCJ2_STREAM_JUMP,\n  BCJ2_STREAM_RC\n};\n\nenum\n{\n  BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,\n  BCJ2_DEC_STATE_ORIG_1,\n  BCJ2_DEC_STATE_ORIG_2,\n  BCJ2_DEC_STATE_ORIG_3,\n  \n  BCJ2_DEC_STATE_ORIG,\n  BCJ2_DEC_STATE_ERROR     /* after detected data error */\n};\n\nenum\n{\n  BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,\n  BCJ2_ENC_STATE_FINISHED  /* it's state after fully encoded stream */\n};\n\n\n/* #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) */\n#define BCJ2_IS_32BIT_STREAM(s) ((unsigned)((unsigned)(s) - (unsigned)BCJ2_STREAM_CALL) < 2)\n\n/*\nCBcj2Dec / CBcj2Enc\nbufs sizes:\n  BUF_SIZE(n) = lims[n] - bufs[n]\nbufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be multiply of 4:\n    (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0\n    (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0\n*/\n\n// typedef UInt32 CBcj2Prob;\ntypedef UInt16 CBcj2Prob;\n\n/*\nBCJ2 encoder / decoder internal requirements:\n  - If last bytes of stream contain marker (e8/e8/0f8x), then\n    there is also encoded symbol (0 : no conversion) in RC stream.\n  - One case of overlapped instructions is supported,\n    if last byte of converted instruction is (0f) and next byte is (8x):\n      marker [xx xx xx 0f] 8x\n    then the pair (0f 8x) is treated as marker.\n*/\n\n/* ---------- BCJ2 Decoder ---------- */\n\n/*\nCBcj2Dec:\n(dest) is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:\n  bufs[BCJ2_STREAM_MAIN] >= dest &&\n  bufs[BCJ2_STREAM_MAIN] - dest >=\n        BUF_SIZE(BCJ2_STREAM_CALL) +\n        BUF_SIZE(BCJ2_STREAM_JUMP)\n  reserve = bufs[BCJ2_STREAM_MAIN] - dest -\n      ( BUF_SIZE(BCJ2_STREAM_CALL) +\n        BUF_SIZE(BCJ2_STREAM_JUMP) )\n  and additional conditions:\n  if (it's first call of Bcj2Dec_Decode() after Bcj2Dec_Init())\n  {\n    (reserve != 1) : if (ver <  v23.00)\n  }\n  else // if there are more than one calls of Bcj2Dec_Decode() after Bcj2Dec_Init())\n  {\n    (reserve >= 6) : if (ver <  v23.00)\n    (reserve >= 4) : if (ver >= v23.00)\n    We need that (reserve) because after first call of Bcj2Dec_Decode(),\n    CBcj2Dec::temp can contain up to 4 bytes for writing to (dest).\n  }\n  (reserve == 0) is allowed, if we decode full stream via single call of Bcj2Dec_Decode().\n  (reserve == 0) also is allowed in case of multi-call, if we use fixed buffers,\n     and (reserve) is calculated from full (final) sizes of all streams before first call.\n*/\n\ntypedef struct\n{\n  const Byte *bufs[BCJ2_NUM_STREAMS];\n  const Byte *lims[BCJ2_NUM_STREAMS];\n  Byte *dest;\n  const Byte *destLim;\n\n  unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */\n\n  UInt32 ip;      /* property of starting base for decoding */\n  UInt32 temp;    /* Byte temp[4]; */\n  UInt32 range;\n  UInt32 code;\n  CBcj2Prob probs[2 + 256];\n} CBcj2Dec;\n\n\n/* Note:\n   Bcj2Dec_Init() sets (CBcj2Dec::ip = 0)\n   if (ip != 0) property is required, the caller must set CBcj2Dec::ip after Bcj2Dec_Init()\n*/\nvoid Bcj2Dec_Init(CBcj2Dec *p);\n\n\n/* Bcj2Dec_Decode():\n   returns:\n     SZ_OK\n     SZ_ERROR_DATA : if data in 5 starting bytes of BCJ2_STREAM_RC stream are not correct\n*/\nSRes Bcj2Dec_Decode(CBcj2Dec *p);\n\n/* To check that decoding was finished you can compare\n   sizes of processed streams with sizes known from another sources.\n   You must do at least one mandatory check from the two following options:\n      - the check for size of processed output (ORIG) stream.\n      - the check for size of processed input  (MAIN) stream.\n   additional optional checks:\n      - the checks for processed sizes of all input streams (MAIN, CALL, JUMP, RC)\n      - the checks Bcj2Dec_IsMaybeFinished*()\n   also before actual decoding you can check that the\n   following condition is met for stream sizes:\n     ( size(ORIG) == size(MAIN) + size(CALL) + size(JUMP) )\n*/\n\n/* (state == BCJ2_STREAM_MAIN) means that decoder is ready for\n      additional input data in BCJ2_STREAM_MAIN stream.\n   Note that (state == BCJ2_STREAM_MAIN) is allowed for non-finished decoding.\n*/\n#define Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) ((_p_)->state == BCJ2_STREAM_MAIN)\n\n/* if the stream decoding was finished correctly, then range decoder\n   part of CBcj2Dec also was finished, and then (CBcj2Dec::code == 0).\n   Note that (CBcj2Dec::code == 0) is allowed for non-finished decoding.\n*/\n#define Bcj2Dec_IsMaybeFinished_code(_p_) ((_p_)->code == 0)\n\n/* use Bcj2Dec_IsMaybeFinished() only as additional check\n    after at least one mandatory check from the two following options:\n      - the check for size of processed output (ORIG) stream.\n      - the check for size of processed input  (MAIN) stream.\n*/\n#define Bcj2Dec_IsMaybeFinished(_p_) ( \\\n        Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) && \\\n        Bcj2Dec_IsMaybeFinished_code(_p_))\n\n\n\n/* ---------- BCJ2 Encoder ---------- */\n\ntypedef enum\n{\n  BCJ2_ENC_FINISH_MODE_CONTINUE,\n  BCJ2_ENC_FINISH_MODE_END_BLOCK,\n  BCJ2_ENC_FINISH_MODE_END_STREAM\n} EBcj2Enc_FinishMode;\n\n/*\n  BCJ2_ENC_FINISH_MODE_CONTINUE:\n     process non finished encoding.\n     It notifies the encoder that additional further calls\n     can provide more input data (src) than provided by current call.\n     In  that case the CBcj2Enc encoder still can move (src) pointer\n     up to (srcLim), but CBcj2Enc encoder can store some of the last\n     processed bytes (up to 4 bytes) from src to internal CBcj2Enc::temp[] buffer.\n   at return:\n       (CBcj2Enc::src will point to position that includes\n       processed data and data copied to (temp[]) buffer)\n       That data from (temp[]) buffer will be used in further calls.\n  \n  BCJ2_ENC_FINISH_MODE_END_BLOCK:\n     finish encoding of current block (ended at srcLim) without RC flushing.\n   at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_ORIG) &&\n                  CBcj2Enc::src == CBcj2Enc::srcLim)\n        :  it shows that block encoding was finished. And the encoder is\n           ready for new (src) data or for stream finish operation.\n     finished block means\n     {\n       CBcj2Enc has completed block encoding up to (srcLim).\n       (1 + 4 bytes) or (2 + 4 bytes) CALL/JUMP cortages will\n       not cross block boundary at (srcLim).\n       temporary CBcj2Enc buffer for (ORIG) src data is empty.\n       3 output uncompressed streams (MAIN, CALL, JUMP) were flushed.\n       RC stream was not flushed. And RC stream will cross block boundary.\n     }\n     Note: some possible implementation of BCJ2 encoder could\n     write branch marker (e8/e8/0f8x) in one call of Bcj2Enc_Encode(),\n     and it could calculate symbol for RC in another call of Bcj2Enc_Encode().\n     BCJ2 encoder uses ip/fileIp/fileSize/relatLimit values to calculate RC symbol.\n     And these CBcj2Enc variables can have different values in different Bcj2Enc_Encode() calls.\n     So caller must finish each block with BCJ2_ENC_FINISH_MODE_END_BLOCK\n     to ensure that RC symbol is calculated and written in proper block.\n    \n  BCJ2_ENC_FINISH_MODE_END_STREAM\n     finish encoding of stream (ended at srcLim) fully including RC flushing.\n   at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_FINISHED)\n        : it shows that stream encoding was finished fully,\n          and all output streams were flushed fully.\n     also Bcj2Enc_IsFinished() can be called.\n*/\n\n\n/*\n  32-bit relative offset in JUMP/CALL commands is\n    - (mod 4 GiB)  for 32-bit x86 code\n    - signed Int32 for 64-bit x86-64 code\n  BCJ2 encoder also does internal relative to absolute address conversions.\n  And there are 2 possible ways to do it:\n    before v23: we used 32-bit variables and (mod 4 GiB) conversion\n    since  v23: we use  64-bit variables and (signed Int32 offset) conversion.\n  The absolute address condition for conversion in v23:\n    ((UInt64)((Int64)ip64 - (Int64)fileIp64 + 5 + (Int32)offset) < (UInt64)fileSize64)\n  note that if (fileSize64 > 2 GiB). there is difference between\n  old (mod 4 GiB) way (v22) and new (signed Int32 offset) way (v23).\n  And new (v23) way is more suitable to encode 64-bit x86-64 code for (fileSize64 > 2 GiB) cases.\n*/\n\n/*\n// for old (v22) way for conversion:\ntypedef UInt32 CBcj2Enc_ip_unsigned;\ntypedef  Int32 CBcj2Enc_ip_signed;\n#define BCJ2_ENC_FileSize_MAX ((UInt32)1 << 31)\n*/\ntypedef UInt64 CBcj2Enc_ip_unsigned;\ntypedef  Int64 CBcj2Enc_ip_signed;\n\n/* maximum size of file that can be used for conversion condition */\n#define BCJ2_ENC_FileSize_MAX             ((CBcj2Enc_ip_unsigned)0 - 2)\n\n/* default value of fileSize64_minus1 variable that means\n   that absolute address limitation will not be used */\n#define BCJ2_ENC_FileSizeField_UNLIMITED  ((CBcj2Enc_ip_unsigned)0 - 1)\n\n/* calculate value that later can be set to CBcj2Enc::fileSize64_minus1 */\n#define BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize) \\\n    ((CBcj2Enc_ip_unsigned)(fileSize) - 1)\n\n/* set CBcj2Enc::fileSize64_minus1 variable from size of file */\n#define Bcj2Enc_SET_FileSize(p, fileSize) \\\n    (p)->fileSize64_minus1 = BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize);\n\n\ntypedef struct\n{\n  Byte *bufs[BCJ2_NUM_STREAMS];\n  const Byte *lims[BCJ2_NUM_STREAMS];\n  const Byte *src;\n  const Byte *srcLim;\n\n  unsigned state;\n  EBcj2Enc_FinishMode finishMode;\n\n  Byte context;\n  Byte flushRem;\n  Byte isFlushState;\n\n  Byte cache;\n  UInt32 range;\n  UInt64 low;\n  UInt64 cacheSize;\n  \n  // UInt32 context;  // for marker version, it can include marker flag.\n\n  /* (ip64) and (fileIp64) correspond to virtual source stream position\n     that doesn't include data in temp[] */\n  CBcj2Enc_ip_unsigned ip64;         /* current (ip) position */\n  CBcj2Enc_ip_unsigned fileIp64;     /* start (ip) position of current file */\n  CBcj2Enc_ip_unsigned fileSize64_minus1;   /* size of current file (for conversion limitation) */\n  UInt32 relatLimit;  /* (relatLimit <= ((UInt32)1 << 31)) : 0 means disable_conversion */\n  // UInt32 relatExcludeBits;\n\n  UInt32 tempTarget;\n  unsigned tempPos; /* the number of bytes that were copied to temp[] buffer\n                       (tempPos <= 4) outside of Bcj2Enc_Encode() */\n  // Byte temp[4]; // for marker version\n  Byte temp[8];\n  CBcj2Prob probs[2 + 256];\n} CBcj2Enc;\n\nvoid Bcj2Enc_Init(CBcj2Enc *p);\n\n\n/*\nBcj2Enc_Encode(): at exit:\n  p->State <  BCJ2_NUM_STREAMS    : we need more buffer space for output stream\n                                    (bufs[p->State] == lims[p->State])\n  p->State == BCJ2_ENC_STATE_ORIG : we need more data in input src stream\n                                    (src == srcLim)\n  p->State == BCJ2_ENC_STATE_FINISHED : after fully encoded stream\n*/\nvoid Bcj2Enc_Encode(CBcj2Enc *p);\n\n/* Bcj2Enc encoder can look ahead for up 4 bytes of source stream.\n   CBcj2Enc::tempPos : is the number of bytes that were copied from input stream to temp[] buffer.\n   (CBcj2Enc::src) after Bcj2Enc_Encode() is starting position after\n   fully processed data and after data copied to temp buffer.\n   So if the caller needs to get real number of fully processed input\n   bytes (without look ahead data in temp buffer),\n   the caller must subtruct (CBcj2Enc::tempPos) value from processed size\n   value that is calculated based on current (CBcj2Enc::src):\n     cur_processed_pos = Calc_Big_Processed_Pos(enc.src)) -\n        Bcj2Enc_Get_AvailInputSize_in_Temp(&enc);\n*/\n/* get the size of input data that was stored in temp[] buffer: */\n#define Bcj2Enc_Get_AvailInputSize_in_Temp(p) ((p)->tempPos)\n\n#define Bcj2Enc_IsFinished(p) ((p)->flushRem == 0)\n\n/* Note : the decoder supports overlapping of marker (0f 80).\n   But we can eliminate such overlapping cases by setting\n   the limit for relative offset conversion as\n     CBcj2Enc::relatLimit <= (0x0f << 24) == (240 MiB)\n*/\n/* default value for CBcj2Enc::relatLimit */\n#define BCJ2_ENC_RELAT_LIMIT_DEFAULT  ((UInt32)0x0f << 24)\n#define BCJ2_ENC_RELAT_LIMIT_MAX      ((UInt32)1 << 31)\n// #define BCJ2_RELAT_EXCLUDE_NUM_BITS 5\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Bcj2Enc.c",
    "content": "﻿/* Bcj2Enc.c -- BCJ2 Encoder converter for x86 code (Branch CALL/JUMP variant2)\n2023-04-02 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n/* #define SHOW_STAT */\n#ifdef SHOW_STAT\n#include <stdio.h>\n#define PRF2(s) printf(\"%s ip=%8x  tempPos=%d  src= %8x\\n\", s, (unsigned)p->ip64, p->tempPos, (unsigned)(p->srcLim - p->src));\n#else\n#define PRF2(s)\n#endif\n\n#include \"Bcj2.h\"\n#include \"CpuArch.h\"\n\n#define kTopValue ((UInt32)1 << 24)\n#define kNumBitModelTotalBits 11\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\n#define kNumMoveBits 5\n\nvoid Bcj2Enc_Init(CBcj2Enc *p)\n{\n  unsigned i;\n  p->state = BCJ2_ENC_STATE_ORIG;\n  p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;\n  p->context = 0;\n  p->flushRem = 5;\n  p->isFlushState = 0;\n  p->cache = 0;\n  p->range = 0xffffffff;\n  p->low = 0;\n  p->cacheSize = 1;\n  p->ip64 = 0;\n  p->fileIp64 = 0;\n  p->fileSize64_minus1 = BCJ2_ENC_FileSizeField_UNLIMITED;\n  p->relatLimit = BCJ2_ENC_RELAT_LIMIT_DEFAULT;\n  // p->relatExcludeBits = 0;\n  p->tempPos = 0;\n  for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)\n    p->probs[i] = kBitModelTotal >> 1;\n}\n\n// Z7_NO_INLINE\nZ7_FORCE_INLINE\nstatic BoolInt Bcj2_RangeEnc_ShiftLow(CBcj2Enc *p)\n{\n  const UInt32 low = (UInt32)p->low;\n  const unsigned high = (unsigned)\n    #if defined(Z7_MSC_VER_ORIGINAL) \\\n        && defined(MY_CPU_X86) \\\n        && defined(MY_CPU_LE) \\\n        && !defined(MY_CPU_64BIT)\n      // we try to rid of __aullshr() call in MSVS-x86\n      (((const UInt32 *)&p->low)[1]); // [1] : for little-endian only\n    #else\n      (p->low >> 32);\n    #endif\n  if (low < (UInt32)0xff000000 || high != 0)\n  {\n    Byte *buf = p->bufs[BCJ2_STREAM_RC];\n    do\n    {\n      if (buf == p->lims[BCJ2_STREAM_RC])\n      {\n        p->state = BCJ2_STREAM_RC;\n        p->bufs[BCJ2_STREAM_RC] = buf;\n        return True;\n      }\n      *buf++ = (Byte)(p->cache + high);\n      p->cache = 0xff;\n    }\n    while (--p->cacheSize);\n    p->bufs[BCJ2_STREAM_RC] = buf;\n    p->cache = (Byte)(low >> 24);\n  }\n  p->cacheSize++;\n  p->low = low << 8;\n  return False;\n}\n\n\n/*\nWe can use 2 alternative versions of code:\n1) non-marker version:\n  Byte CBcj2Enc::context\n  Byte temp[8];\n  Last byte of marker (e8/e9/[0f]8x) can be written to temp[] buffer.\n  Encoder writes last byte of marker (e8/e9/[0f]8x) to dest, only in conjunction\n  with writing branch symbol to range coder in same Bcj2Enc_Encode_2() call.\n\n2) marker version:\n  UInt32 CBcj2Enc::context\n  Byte CBcj2Enc::temp[4];\n  MARKER_FLAG in CBcj2Enc::context shows that CBcj2Enc::context contains finded marker.\n  it's allowed that\n    one call of Bcj2Enc_Encode_2() writes last byte of marker (e8/e9/[0f]8x) to dest,\n    and another call of Bcj2Enc_Encode_2() does offset conversion.\n    So different values of (fileIp) and (fileSize) are possible\n    in these different Bcj2Enc_Encode_2() calls.\n\nAlso marker version requires additional if((v & MARKER_FLAG) == 0) check in main loop.\nSo we use non-marker version.\n*/\n\n/*\n  Corner cases with overlap in multi-block.\n  before v23: there was one corner case, where converted instruction\n    could start in one sub-stream and finish in next sub-stream.\n  If multi-block (solid) encoding is used,\n    and BCJ2_ENC_FINISH_MODE_END_BLOCK is used for each sub-stream.\n    and (0f) is last byte of previous sub-stream\n    and (8x) is first byte of current sub-stream\n  then (0f 8x) pair is treated as marker by BCJ2 encoder and decoder.\n  BCJ2 encoder can converts 32-bit offset for that (0f 8x) cortage,\n  if that offset meets limit requirements.\n  If encoder allows 32-bit offset conversion for such overlap case,\n  then the data in 3 uncompressed BCJ2 streams for some sub-stream\n  can depend from data of previous sub-stream.\n  That corner case is not big problem, and it's rare case.\n  Since v23.00 we do additional check to prevent conversions in such overlap cases.\n*/\n\n/*\n  Bcj2Enc_Encode_2() output variables at exit:\n  {\n    if (Bcj2Enc_Encode_2() exits with (p->state == BCJ2_ENC_STATE_ORIG))\n    {\n      it means that encoder needs more input data.\n      if (p->srcLim == p->src) at exit, then\n      {\n        (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM)\n        all input data were read and processed, and we are ready for\n        new input data.\n      }\n      else\n      {\n        (p->srcLim != p->src)\n        (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE)\n          The encoder have found e8/e9/0f_8x marker,\n          and p->src points to last byte of that marker,\n          Bcj2Enc_Encode_2() needs more input data to get totally\n          5 bytes (last byte of marker and 32-bit branch offset)\n          as continuous array starting from p->src.\n        (p->srcLim - p->src < 5) requirement is met after exit.\n          So non-processed resedue from p->src to p->srcLim is always less than 5 bytes.\n      }\n    }\n  }\n*/\n\nZ7_NO_INLINE\nstatic void Bcj2Enc_Encode_2(CBcj2Enc *p)\n{\n  if (!p->isFlushState)\n  {\n    const Byte *src;\n    UInt32 v;\n    {\n      const unsigned state = p->state;\n      if (BCJ2_IS_32BIT_STREAM(state))\n      {\n        Byte *cur = p->bufs[state];\n        if (cur == p->lims[state])\n          return;\n        SetBe32a(cur, p->tempTarget)\n        p->bufs[state] = cur + 4;\n      }\n    }\n    p->state = BCJ2_ENC_STATE_ORIG; // for main reason of exit\n    src = p->src;\n    v = p->context;\n    \n    // #define WRITE_CONTEXT  p->context = v; // for marker version\n    #define WRITE_CONTEXT           p->context = (Byte)v;\n    #define WRITE_CONTEXT_AND_SRC   p->src = src;  WRITE_CONTEXT\n\n    for (;;)\n    {\n      // const Byte *src;\n      // UInt32 v;\n      CBcj2Enc_ip_unsigned ip;\n      if (p->range < kTopValue)\n      {\n        // to reduce register pressure and code size: we save and restore local variables.\n        WRITE_CONTEXT_AND_SRC\n        if (Bcj2_RangeEnc_ShiftLow(p))\n          return;\n        p->range <<= 8;\n        src = p->src;\n        v = p->context;\n      }\n      // src = p->src;\n      // #define MARKER_FLAG  ((UInt32)1 << 17)\n      // if ((v & MARKER_FLAG) == 0) // for marker version\n      {\n        const Byte *srcLim;\n        Byte *dest = p->bufs[BCJ2_STREAM_MAIN];\n        {\n          const SizeT remSrc = (SizeT)(p->srcLim - src);\n          SizeT rem = (SizeT)(p->lims[BCJ2_STREAM_MAIN] - dest);\n          if (rem >= remSrc)\n            rem = remSrc;\n          srcLim = src + rem;\n        }\n        /* p->context contains context of previous byte:\n           bits [0 : 7]  : src[-1], if (src) was changed in this call\n           bits [8 : 31] : are undefined for non-marker version\n        */\n        // v = p->context;\n        #define NUM_SHIFT_BITS  24\n        #define CONV_FLAG  ((UInt32)1 << 16)\n        #define ONE_ITER { \\\n          b = src[0]; \\\n          *dest++ = (Byte)b; \\\n          v = (v << NUM_SHIFT_BITS) | b; \\\n          if (((b + (0x100 - 0xe8)) & 0xfe) == 0) break; \\\n          if (((v - (((UInt32)0x0f << (NUM_SHIFT_BITS)) + 0x80)) & \\\n              ((((UInt32)1 << (4 + NUM_SHIFT_BITS)) - 0x1) << 4)) == 0) break; \\\n          src++; if (src == srcLim) { break; } }\n\n        if (src != srcLim)\n        for (;;)\n        {\n          /* clang can generate ineffective code with setne instead of two jcc instructions.\n             we can use 2 iterations and external (unsigned b) to avoid that ineffective code genaration. */\n          unsigned b;\n          ONE_ITER\n          ONE_ITER\n        }\n        \n        ip = p->ip64 + (CBcj2Enc_ip_unsigned)(SizeT)(dest - p->bufs[BCJ2_STREAM_MAIN]);\n        p->bufs[BCJ2_STREAM_MAIN] = dest;\n        p->ip64 = ip;\n\n        if (src == srcLim)\n        {\n          WRITE_CONTEXT_AND_SRC\n          if (src != p->srcLim)\n          {\n            p->state = BCJ2_STREAM_MAIN;\n            return;\n          }\n          /* (p->src == p->srcLim)\n          (p->state == BCJ2_ENC_STATE_ORIG) */\n          if (p->finishMode != BCJ2_ENC_FINISH_MODE_END_STREAM)\n            return;\n          /* (p->finishMode == BCJ2_ENC_FINISH_MODE_END_STREAM */\n          // (p->flushRem == 5);\n          p->isFlushState = 1;\n          break;\n        }\n        src++;\n        // p->src = src;\n      }\n      // ip = p->ip; // for marker version\n      /* marker was found */\n      /* (v) contains marker that was found:\n           bits [NUM_SHIFT_BITS : NUM_SHIFT_BITS + 7]\n                         : value of src[-2] : xx/xx/0f\n           bits [0 : 7]  : value of src[-1] : e8/e9/8x\n      */\n      {\n        {\n        #if NUM_SHIFT_BITS != 24\n          v &= ~(UInt32)CONV_FLAG;\n        #endif\n          // UInt32 relat = 0;\n          if ((SizeT)(p->srcLim - src) >= 4)\n          {\n            /*\n            if (relat != 0 || (Byte)v != 0xe8)\n            BoolInt isBigOffset = True;\n            */\n            const UInt32 relat = GetUi32(src);\n            /*\n            #define EXCLUDE_FLAG  ((UInt32)1 << 4)\n            #define NEED_CONVERT(rel) ((((rel) + EXCLUDE_FLAG) & (0 - EXCLUDE_FLAG * 2)) != 0)\n            if (p->relatExcludeBits != 0)\n            {\n              const UInt32 flag = (UInt32)1 << (p->relatExcludeBits - 1);\n              isBigOffset = (((relat + flag) & (0 - flag * 2)) != 0);\n            }\n            // isBigOffset = False; // for debug\n            */\n            ip -= p->fileIp64;\n            // Use the following if check, if (ip) is 64-bit:\n            if (ip > (((v + 0x20) >> 5) & 1))  // 23.00 : we eliminate milti-block overlap for (Of 80) and (e8/e9)\n            if ((CBcj2Enc_ip_unsigned)((CBcj2Enc_ip_signed)ip + 4 + (Int32)relat) <= p->fileSize64_minus1)\n            if (((UInt32)(relat + p->relatLimit) >> 1) < p->relatLimit)\n              v |= CONV_FLAG;\n          }\n          else if (p->finishMode == BCJ2_ENC_FINISH_MODE_CONTINUE)\n          {\n            // (p->srcLim - src < 4)\n            // /*\n            // for non-marker version\n            p->ip64--; // p->ip = ip - 1;\n            p->bufs[BCJ2_STREAM_MAIN]--;\n            src--;\n            v >>= NUM_SHIFT_BITS;\n            // (0 < p->srcLim - p->src <= 4)\n            // */\n            // v |= MARKER_FLAG; // for marker version\n            /* (p->state == BCJ2_ENC_STATE_ORIG) */\n            WRITE_CONTEXT_AND_SRC\n            return;\n          }\n          {\n            const unsigned c = ((v + 0x17) >> 6) & 1;\n            CBcj2Prob *prob = p->probs + (unsigned)\n                (((0 - c) & (Byte)(v >> NUM_SHIFT_BITS)) + c + ((v >> 5) & 1));\n            /*\n                ((Byte)v == 0xe8 ? 2 + ((Byte)(v >> 8)) :\n                ((Byte)v < 0xe8 ? 0 : 1));  // ((v >> 5) & 1));\n            */\n            const unsigned ttt = *prob;\n            const UInt32 bound = (p->range >> kNumBitModelTotalBits) * ttt;\n            if ((v & CONV_FLAG) == 0)\n            {\n              // static int yyy = 0; yyy++; printf(\"\\n!needConvert = %d\\n\", yyy);\n              // v = (Byte)v; // for marker version\n              p->range = bound;\n              *prob = (CBcj2Prob)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\n              // WRITE_CONTEXT_AND_SRC\n              continue;\n            }\n            p->low += bound;\n            p->range -= bound;\n            *prob = (CBcj2Prob)(ttt - (ttt >> kNumMoveBits));\n          }\n          // p->context = src[3];\n          {\n            // const unsigned cj = ((Byte)v == 0xe8 ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP);\n            const unsigned cj = (((v + 0x57) >> 6) & 1) + BCJ2_STREAM_CALL;\n            ip = p->ip64;\n            v = GetUi32(src); // relat\n            ip += 4;\n            p->ip64 = ip;\n            src += 4;\n            // p->src = src;\n            {\n              const UInt32 absol = (UInt32)ip + v;\n              Byte *cur = p->bufs[cj];\n              v >>= 24;\n              // WRITE_CONTEXT\n              if (cur == p->lims[cj])\n              {\n                p->state = cj;\n                p->tempTarget = absol;\n                WRITE_CONTEXT_AND_SRC\n                return;\n              }\n              SetBe32a(cur, absol)\n              p->bufs[cj] = cur + 4;\n            }\n          }\n        }\n      }\n    } // end of loop\n  }\n\n  for (; p->flushRem != 0; p->flushRem--)\n    if (Bcj2_RangeEnc_ShiftLow(p))\n      return;\n  p->state = BCJ2_ENC_STATE_FINISHED;\n}\n\n\n/*\nBCJ2 encoder needs look ahead for up to 4 bytes in (src) buffer.\nSo base function Bcj2Enc_Encode_2()\n  in BCJ2_ENC_FINISH_MODE_CONTINUE mode can return with\n  (p->state == BCJ2_ENC_STATE_ORIG && p->src < p->srcLim)\nBcj2Enc_Encode() solves that look ahead problem by using p->temp[] buffer.\n  so if (p->state == BCJ2_ENC_STATE_ORIG) after Bcj2Enc_Encode(),\n    then (p->src == p->srcLim).\n  And the caller's code is simpler with Bcj2Enc_Encode().\n*/\n\nZ7_NO_INLINE\nvoid Bcj2Enc_Encode(CBcj2Enc *p)\n{\n  PRF2(\"\\n----\")\n  if (p->tempPos != 0)\n  {\n    /* extra: number of bytes that were copied from (src) to (temp) buffer in this call */\n    unsigned extra = 0;\n    /* We will touch only minimal required number of bytes in input (src) stream.\n       So we will add input bytes from (src) stream to temp[] with step of 1 byte.\n       We don't add new bytes to temp[] before Bcj2Enc_Encode_2() call\n         in first loop iteration because\n         - previous call of Bcj2Enc_Encode() could use another (finishMode),\n         - previous call could finish with (p->state != BCJ2_ENC_STATE_ORIG).\n       the case with full temp[] buffer (p->tempPos == 4) is possible here.\n    */\n    for (;;)\n    {\n      // (0 < p->tempPos <= 5) // in non-marker version\n      /* p->src : the current src data position including extra bytes\n                  that were copied to temp[] buffer in this call */\n      const Byte *src = p->src;\n      const Byte *srcLim = p->srcLim;\n      const EBcj2Enc_FinishMode finishMode = p->finishMode;\n      if (src != srcLim)\n      {\n        /* if there are some src data after the data copied to temp[],\n           then we use MODE_CONTINUE for temp data */\n        p->finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;\n      }\n      p->src = p->temp;\n      p->srcLim = p->temp + p->tempPos;\n      PRF2(\"    \")\n      Bcj2Enc_Encode_2(p);\n      {\n        const unsigned num = (unsigned)(p->src - p->temp);\n        const unsigned tempPos = p->tempPos - num;\n        unsigned i;\n        p->tempPos = tempPos;\n        for (i = 0; i < tempPos; i++)\n          p->temp[i] = p->temp[(SizeT)i + num];\n        // tempPos : number of bytes in temp buffer\n        p->src = src;\n        p->srcLim = srcLim;\n        p->finishMode = finishMode;\n        if (p->state != BCJ2_ENC_STATE_ORIG)\n        {\n          // (p->tempPos <= 4) // in non-marker version\n          /* if (the reason of exit from Bcj2Enc_Encode_2()\n                 is not BCJ2_ENC_STATE_ORIG),\n             then we exit from Bcj2Enc_Encode() with same reason */\n          // optional code begin : we rollback (src) and tempPos, if it's possible:\n          if (extra >= tempPos)\n            extra = tempPos;\n          p->src = src - extra;\n          p->tempPos = tempPos - extra;\n          // optional code end : rollback of (src) and tempPos\n          return;\n        }\n        /* (p->tempPos <= 4)\n           (p->state == BCJ2_ENC_STATE_ORIG)\n             so encoder needs more data than in temp[] */\n        if (src == srcLim)\n          return; // src buffer has no more input data.\n        /* (src != srcLim)\n           so we can provide more input data from src for Bcj2Enc_Encode_2() */\n        if (extra >= tempPos)\n        {\n          /* (extra >= tempPos) means that temp buffer contains\n             only data from src buffer of this call.\n             So now we can encode without temp buffer */\n          p->src = src - tempPos; // rollback (src)\n          p->tempPos = 0;\n          break;\n        }\n        // we append one additional extra byte from (src) to temp[] buffer:\n        p->temp[tempPos] = *src;\n        p->tempPos = tempPos + 1;\n        // (0 < p->tempPos <= 5) // in non-marker version\n        p->src = src + 1;\n        extra++;\n      }\n    }\n  }\n\n  PRF2(\"++++\")\n  // (p->tempPos == 0)\n  Bcj2Enc_Encode_2(p);\n  PRF2(\"====\")\n  \n  if (p->state == BCJ2_ENC_STATE_ORIG)\n  {\n    const Byte *src = p->src;\n    const Byte *srcLim = p->srcLim;\n    const unsigned rem = (unsigned)(srcLim - src);\n    /* (rem <= 4) here.\n       if (p->src != p->srcLim), then\n         - we copy non-processed bytes from (p->src) to temp[] buffer,\n         - we set p->src equal to p->srcLim.\n    */\n    if (rem)\n    {\n      unsigned i = 0;\n      p->src = srcLim;\n      p->tempPos = rem;\n      // (0 < p->tempPos <= 4)\n      do\n        p->temp[i] = src[i];\n      while (++i != rem);\n    }\n    // (p->tempPos <= 4)\n    // (p->src == p->srcLim)\n  }\n}\n\n#undef PRF2\n#undef CONV_FLAG\n#undef MARKER_FLAG\n#undef WRITE_CONTEXT\n#undef WRITE_CONTEXT_AND_SRC\n#undef ONE_ITER\n#undef NUM_SHIFT_BITS\n#undef kTopValue\n#undef kNumBitModelTotalBits\n#undef kBitModelTotal\n#undef kNumMoveBits\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Blake2.h",
    "content": "﻿/* Blake2.h -- BLAKE2sp Hash\n2024-01-17 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_BLAKE2_H\n#define ZIP7_INC_BLAKE2_H\n\n#include \"7zTypes.h\"\n\n#if 0\n#include \"Compiler.h\"\n#include \"CpuArch.h\"\n#if defined(MY_CPU_X86_OR_AMD64)\n#if defined(__SSE2__) \\\n    || defined(_MSC_VER) && _MSC_VER > 1200 \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \\\n    || defined(__clang__) \\\n    || defined(__INTEL_COMPILER)\n#include <emmintrin.h> // SSE2\n#endif\n\n#if defined(__AVX2__) \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \\\n    || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \\\n    || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \\\n    || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \\\n    || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)\n#include <immintrin.h>\n#if defined(__clang__)\n#include <avxintrin.h>\n#include <avx2intrin.h>\n#endif\n#endif // avx2\n#endif // MY_CPU_X86_OR_AMD64\n#endif // 0\n\nEXTERN_C_BEGIN\n\n#define Z7_BLAKE2S_BLOCK_SIZE         64\n#define Z7_BLAKE2S_DIGEST_SIZE        32\n#define Z7_BLAKE2SP_PARALLEL_DEGREE   8\n#define Z7_BLAKE2SP_NUM_STRUCT_WORDS  16\n\n#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)\ntypedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_COMPRESS)(UInt32 *states, const Byte *data, const Byte *end);\ntypedef void (Z7_FASTCALL *Z7_BLAKE2SP_FUNC_INIT)(UInt32 *states);\n#endif\n\n// it's required that CBlake2sp is aligned for 32-bytes,\n// because the code can use unaligned access with sse and avx256.\n// but 64-bytes alignment can be better.\nMY_ALIGN(64)\ntypedef struct\n{\n  union\n  {\n#if 0\n#if defined(MY_CPU_X86_OR_AMD64)\n#if defined(__SSE2__) \\\n    || defined(_MSC_VER) && _MSC_VER > 1200 \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \\\n    || defined(__clang__) \\\n    || defined(__INTEL_COMPILER)\n    __m128i _pad_align_128bit[4];\n#endif // sse2\n#if defined(__AVX2__) \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \\\n    || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \\\n    || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \\\n    || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \\\n    || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)\n    __m256i _pad_align_256bit[2];\n#endif // avx2\n#endif // x86\n#endif // 0\n\n    void * _pad_align_ptr[8];\n    UInt32 _pad_align_32bit[16];\n    struct\n    {\n      unsigned cycPos;\n      unsigned _pad_unused;\n#if 1 || defined(Z7_BLAKE2SP_USE_FUNCTIONS)\n      Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Fast;\n      Z7_BLAKE2SP_FUNC_COMPRESS func_Compress_Single;\n      Z7_BLAKE2SP_FUNC_INIT func_Init;\n      Z7_BLAKE2SP_FUNC_INIT func_Final;\n#endif\n    } header;\n  } u;\n  // MY_ALIGN(64)\n  UInt32 states[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS];\n  // MY_ALIGN(64)\n  UInt32  buf32[Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2SP_NUM_STRUCT_WORDS * 2];\n} CBlake2sp;\n\nBoolInt Blake2sp_SetFunction(CBlake2sp *p, unsigned algo);\nvoid Blake2sp_Init(CBlake2sp *p);\nvoid Blake2sp_InitState(CBlake2sp *p);\nvoid Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size);\nvoid Blake2sp_Final(CBlake2sp *p, Byte *digest);\nvoid z7_Black2sp_Prepare(void);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Blake2s.c",
    "content": "﻿/* Blake2s.c -- BLAKE2sp Hash\n2024-05-18 : Igor Pavlov : Public domain\n2015-2019 : Samuel Neves : original code : CC0 1.0 Universal (CC0 1.0). */\n\n#include \"Precomp.h\"\n\n// #include <stdio.h>\n#include <string.h>\n\n#include \"Blake2.h\"\n#include \"RotateDefs.h\"\n#include \"Compiler.h\"\n#include \"CpuArch.h\"\n\n/*\n  if defined(__AVX512F__) && defined(__AVX512VL__)\n  {\n    we define Z7_BLAKE2S_USE_AVX512_ALWAYS,\n    but the compiler can use avx512 for any code.\n  }\n  else if defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)\n    { we use avx512 only for sse* and avx* branches of code. }\n*/\n// #define Z7_BLAKE2S_USE_AVX512_ALWAYS // for debug\n\n#if defined(__SSE2__)\n    #define Z7_BLAKE2S_USE_VECTORS\n#elif defined(MY_CPU_X86_OR_AMD64)\n  #if  defined(_MSC_VER) && _MSC_VER > 1200 \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 30300) \\\n    || defined(__clang__) \\\n    || defined(__INTEL_COMPILER)\n    #define Z7_BLAKE2S_USE_VECTORS\n  #endif\n#endif\n\n#ifdef Z7_BLAKE2S_USE_VECTORS\n\n#define Z7_BLAKE2SP_USE_FUNCTIONS\n\n//  define Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED, if CBlake2sp can be non aligned for 32-bytes.\n// #define Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED\n\n// SSSE3 : for _mm_shuffle_epi8 (pshufb) that improves the performance for 5-15%.\n#if defined(__SSSE3__)\n  #define Z7_BLAKE2S_USE_SSSE3\n#elif  defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1500) \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40300) \\\n    || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40000) \\\n    || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 20300) \\\n    || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1000)\n  #define Z7_BLAKE2S_USE_SSSE3\n#endif\n\n#ifdef Z7_BLAKE2S_USE_SSSE3\n/* SSE41 : for _mm_insert_epi32 (pinsrd)\n  it can slightly reduce code size and improves the performance in some cases.\n    it's used only for last 512-1024 bytes, if FAST versions (2 or 3) of vector algos are used.\n    it can be used for all blocks in another algos (4+).\n*/\n#if defined(__SSE4_1__)\n  #define Z7_BLAKE2S_USE_SSE41\n#elif  defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1500) \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40300) \\\n    || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40000) \\\n    || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 20300) \\\n    || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1000)\n  #define Z7_BLAKE2S_USE_SSE41\n#endif\n#endif // SSSE3\n\n#if defined(__GNUC__) || defined(__clang__)\n#if defined(Z7_BLAKE2S_USE_AVX512_ALWAYS) && !(defined(__AVX512F__) && defined(__AVX512VL__))\n    #define BLAKE2S_ATTRIB_128BIT  __attribute__((__target__(\"avx512vl,avx512f\")))\n#else\n  #if defined(Z7_BLAKE2S_USE_SSE41)\n    #define BLAKE2S_ATTRIB_128BIT  __attribute__((__target__(\"sse4.1\")))\n  #elif defined(Z7_BLAKE2S_USE_SSSE3)\n    #define BLAKE2S_ATTRIB_128BIT  __attribute__((__target__(\"ssse3\")))\n  #else\n    #define BLAKE2S_ATTRIB_128BIT  __attribute__((__target__(\"sse2\")))\n  #endif\n#endif\n#endif\n\n\n#if defined(__AVX2__)\n  #define Z7_BLAKE2S_USE_AVX2\n#else\n  #if    defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \\\n      || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \\\n      || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100)\n    #define Z7_BLAKE2S_USE_AVX2\n    #ifdef Z7_BLAKE2S_USE_AVX2\n#if defined(Z7_BLAKE2S_USE_AVX512_ALWAYS) && !(defined(__AVX512F__) && defined(__AVX512VL__))\n      #define BLAKE2S_ATTRIB_AVX2  __attribute__((__target__(\"avx512vl,avx512f\")))\n#else\n      #define BLAKE2S_ATTRIB_AVX2  __attribute__((__target__(\"avx2\")))\n#endif\n    #endif\n  #elif  defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \\\n      || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)\n    #if (Z7_MSC_VER_ORIGINAL == 1900)\n      #pragma warning(disable : 4752) // found Intel(R) Advanced Vector Extensions; consider using /arch:AVX\n    #endif\n    #define Z7_BLAKE2S_USE_AVX2\n  #endif\n#endif\n\n#ifdef Z7_BLAKE2S_USE_SSE41\n#include <smmintrin.h> // SSE4.1\n#elif defined(Z7_BLAKE2S_USE_SSSE3)\n#include <tmmintrin.h> // SSSE3\n#else\n#include <emmintrin.h> // SSE2\n#endif\n\n#ifdef Z7_BLAKE2S_USE_AVX2\n#include <immintrin.h>\n#if defined(__clang__)\n#include <avxintrin.h>\n#include <avx2intrin.h>\n#endif\n#endif // avx2\n\n\n#if defined(__AVX512F__) && defined(__AVX512VL__)\n   // && defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL > 1930)\n  #ifndef Z7_BLAKE2S_USE_AVX512_ALWAYS\n  #define Z7_BLAKE2S_USE_AVX512_ALWAYS\n  #endif\n  // #pragma message (\"=== Blake2s AVX512\")\n#endif\n\n\n#define Z7_BLAKE2S_USE_V128_FAST\n// for speed optimization for small messages:\n// #define Z7_BLAKE2S_USE_V128_WAY2\n\n#ifdef Z7_BLAKE2S_USE_AVX2\n\n// for debug:\n// gather is slow\n// #define Z7_BLAKE2S_USE_GATHER\n\n  #define   Z7_BLAKE2S_USE_AVX2_FAST\n// for speed optimization for small messages:\n//   #define   Z7_BLAKE2S_USE_AVX2_WAY2\n//   #define   Z7_BLAKE2S_USE_AVX2_WAY4\n#if defined(Z7_BLAKE2S_USE_AVX2_WAY2) || \\\n    defined(Z7_BLAKE2S_USE_AVX2_WAY4)\n  #define   Z7_BLAKE2S_USE_AVX2_WAY_SLOW\n#endif\n#endif\n\n  #define Z7_BLAKE2SP_ALGO_DEFAULT    0\n  #define Z7_BLAKE2SP_ALGO_SCALAR     1\n#ifdef Z7_BLAKE2S_USE_V128_FAST\n  #define Z7_BLAKE2SP_ALGO_V128_FAST  2\n#endif\n#ifdef Z7_BLAKE2S_USE_AVX2_FAST\n  #define Z7_BLAKE2SP_ALGO_V256_FAST  3\n#endif\n  #define Z7_BLAKE2SP_ALGO_V128_WAY1  4\n#ifdef Z7_BLAKE2S_USE_V128_WAY2\n  #define Z7_BLAKE2SP_ALGO_V128_WAY2  5\n#endif\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY2\n  #define Z7_BLAKE2SP_ALGO_V256_WAY2  6\n#endif\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY4\n  #define Z7_BLAKE2SP_ALGO_V256_WAY4  7\n#endif\n\n#endif // Z7_BLAKE2S_USE_VECTORS\n\n\n\n\n#define BLAKE2S_FINAL_FLAG  (~(UInt32)0)\n#define NSW                 Z7_BLAKE2SP_NUM_STRUCT_WORDS\n#define SUPER_BLOCK_SIZE    (Z7_BLAKE2S_BLOCK_SIZE * Z7_BLAKE2SP_PARALLEL_DEGREE)\n#define SUPER_BLOCK_MASK    (SUPER_BLOCK_SIZE - 1)\n\n#define V_INDEX_0_0   0\n#define V_INDEX_1_0   1\n#define V_INDEX_2_0   2\n#define V_INDEX_3_0   3\n#define V_INDEX_0_1   4\n#define V_INDEX_1_1   5\n#define V_INDEX_2_1   6\n#define V_INDEX_3_1   7\n#define V_INDEX_0_2   8\n#define V_INDEX_1_2   9\n#define V_INDEX_2_2  10\n#define V_INDEX_3_2  11\n#define V_INDEX_0_3  12\n#define V_INDEX_1_3  13\n#define V_INDEX_2_3  14\n#define V_INDEX_3_3  15\n#define V_INDEX_4_0   0\n#define V_INDEX_5_0   1\n#define V_INDEX_6_0   2\n#define V_INDEX_7_0   3\n#define V_INDEX_7_1   4\n#define V_INDEX_4_1   5\n#define V_INDEX_5_1   6\n#define V_INDEX_6_1   7\n#define V_INDEX_6_2   8\n#define V_INDEX_7_2   9\n#define V_INDEX_4_2  10\n#define V_INDEX_5_2  11\n#define V_INDEX_5_3  12\n#define V_INDEX_6_3  13\n#define V_INDEX_7_3  14\n#define V_INDEX_4_3  15\n\n#define V(row, col)  v[V_INDEX_ ## row ## _ ## col]\n\n#define k_Blake2s_IV_0  0x6A09E667UL\n#define k_Blake2s_IV_1  0xBB67AE85UL\n#define k_Blake2s_IV_2  0x3C6EF372UL\n#define k_Blake2s_IV_3  0xA54FF53AUL\n#define k_Blake2s_IV_4  0x510E527FUL\n#define k_Blake2s_IV_5  0x9B05688CUL\n#define k_Blake2s_IV_6  0x1F83D9ABUL\n#define k_Blake2s_IV_7  0x5BE0CD19UL\n\n#define KIV(n)  (k_Blake2s_IV_## n)\n\n#ifdef Z7_BLAKE2S_USE_VECTORS\nMY_ALIGN(16)\nstatic const UInt32 k_Blake2s_IV[8] =\n{\n  KIV(0), KIV(1), KIV(2), KIV(3), KIV(4), KIV(5), KIV(6), KIV(7)\n};\n#endif\n\n#define STATE_T(s)        ((s) + 8)\n#define STATE_F(s)        ((s) + 10)\n\n#ifdef Z7_BLAKE2S_USE_VECTORS\n\n#define LOAD_128(p)    _mm_load_si128 ((const __m128i *)(const void *)(p))\n#define LOADU_128(p)   _mm_loadu_si128((const __m128i *)(const void *)(p))\n#ifdef Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED\n  // here we use unaligned load and stores\n  // use this branch if CBlake2sp can be unaligned for 16 bytes\n  #define STOREU_128(p, r)  _mm_storeu_si128((__m128i *)(void *)(p), r)\n  #define LOAD_128_FROM_STRUCT(p)     LOADU_128(p)\n  #define STORE_128_TO_STRUCT(p, r)   STOREU_128(p, r)\n#else\n  // here we use aligned load and stores\n  // use this branch if CBlake2sp is aligned for 16 bytes\n  #define STORE_128(p, r)  _mm_store_si128((__m128i *)(void *)(p), r)\n  #define LOAD_128_FROM_STRUCT(p)     LOAD_128(p)\n  #define STORE_128_TO_STRUCT(p, r)   STORE_128(p, r)\n#endif\n\n#endif // Z7_BLAKE2S_USE_VECTORS\n\n\n#if 0\nstatic void PrintState(const UInt32 *s, unsigned num)\n{\n  unsigned i;\n  printf(\"\\n\");\n  for (i = 0; i < num; i++)\n    printf(\" %08x\", (unsigned)s[i]);\n}\nstatic void PrintStates2(const UInt32 *s, unsigned x, unsigned y)\n{\n  unsigned i;\n  for (i = 0; i < y; i++)\n    PrintState(s + i * x, x);\n  printf(\"\\n\");\n}\n#endif\n\n\n#define REP8_MACRO(m)  { m(0) m(1) m(2) m(3) m(4) m(5) m(6) m(7) }\n\n#define BLAKE2S_NUM_ROUNDS  10\n\n#if defined(Z7_BLAKE2S_USE_VECTORS)\n#define ROUNDS_LOOP(mac) \\\n  { unsigned r; for (r = 0; r < BLAKE2S_NUM_ROUNDS; r++) mac(r) }\n#endif\n/*\n#define ROUNDS_LOOP_2(mac) \\\n  { unsigned r; for (r = 0; r < BLAKE2S_NUM_ROUNDS; r += 2) { mac(r) mac(r + 1) } }\n*/\n#if 0 || 1 && !defined(Z7_BLAKE2S_USE_VECTORS)\n#define ROUNDS_LOOP_UNROLLED(m) \\\n  { m(0) m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) m(9) }\n#endif\n\n#define SIGMA_TABLE(M) \\\n  M(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 ), \\\n  M( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 ), \\\n  M( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 ), \\\n  M(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 ), \\\n  M(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 ), \\\n  M(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 ), \\\n  M( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 ), \\\n  M( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 ), \\\n  M(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 ), \\\n  M( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13,  0 )\n\n#define SIGMA_TABLE_MULT(m, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \\\n  { a0*m,a1*m,a2*m,a3*m,a4*m,a5*m,a6*m,a7*m,a8*m,a9*m,a10*m,a11*m,a12*m,a13*m,a14*m,a15*m }\n#define SIGMA_TABLE_MULT_4( a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \\\n        SIGMA_TABLE_MULT(4, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)\n\n// MY_ALIGN(32)\nMY_ALIGN(16)\nstatic const Byte k_Blake2s_Sigma_4[BLAKE2S_NUM_ROUNDS][16] =\n  { SIGMA_TABLE(SIGMA_TABLE_MULT_4) };\n\n#define GET_SIGMA_PTR(p, index) \\\n    ((const void *)((const Byte *)(const void *)(p) + (index)))\n\n#define GET_STATE_TABLE_PTR_FROM_BYTE_POS(s, pos) \\\n    ((UInt32 *)(void *)((Byte *)(void *)(s) + (pos)))\n\n\n#ifdef Z7_BLAKE2S_USE_VECTORS\n\n\n#if 0\n  // use loading constants from memory\n  // is faster for some compilers.\n  #define KK4(n)  KIV(n), KIV(n), KIV(n), KIV(n)\nMY_ALIGN(64)\nstatic const UInt32 k_Blake2s_IV_WAY4[]=\n{\n  KK4(0), KK4(1), KK4(2), KK4(3), KK4(4), KK4(5), KK4(6), KK4(7)\n};\n  #define GET_128_IV_WAY4(i)  LOAD_128(k_Blake2s_IV_WAY4 + 4 * (i))\n#else\n  // use constant generation:\n  #define GET_128_IV_WAY4(i)  _mm_set1_epi32((Int32)KIV(i))\n#endif\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW\n#define GET_CONST_128_FROM_ARRAY32(k) \\\n    _mm_set_epi32((Int32)(k)[3], (Int32)(k)[2], (Int32)(k)[1], (Int32)(k)[0])\n#endif\n\n\n#if 0\n#define k_r8    _mm_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1)\n#define k_r16   _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2)\n#define k_inc   _mm_set_epi32(0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE)\n#define k_iv0_128  GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 0)\n#define k_iv4_128  GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 4)\n#else\n#if  defined(Z7_BLAKE2S_USE_SSSE3) && \\\n    !defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)\nMY_ALIGN(16) static const Byte k_r8_arr [16] = { 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8 ,13, 14, 15, 12 };\nMY_ALIGN(16) static const Byte k_r16_arr[16] = { 2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13 };\n#define k_r8    LOAD_128(k_r8_arr)\n#define k_r16   LOAD_128(k_r16_arr)\n#endif\nMY_ALIGN(16) static const UInt32 k_inc_arr[4] = { Z7_BLAKE2S_BLOCK_SIZE, 0, 0, 0 };\n#define k_inc   LOAD_128(k_inc_arr)\n#define k_iv0_128  LOAD_128(k_Blake2s_IV + 0)\n#define k_iv4_128  LOAD_128(k_Blake2s_IV + 4)\n#endif\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW\n\n#ifdef Z7_BLAKE2S_USE_AVX2\n#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 80000)\n  #define MY_mm256_set_m128i(hi, lo)  _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1)\n#else\n  #define MY_mm256_set_m128i  _mm256_set_m128i\n#endif\n\n#define SET_FROM_128(a)  MY_mm256_set_m128i(a, a)\n\n#ifndef Z7_BLAKE2S_USE_AVX512_ALWAYS\nMY_ALIGN(32) static const Byte k_r8_arr_256 [32] =\n{\n  1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8 ,13, 14, 15, 12,\n  1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8 ,13, 14, 15, 12\n};\nMY_ALIGN(32) static const Byte k_r16_arr_256[32] =\n{\n  2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13,\n  2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13\n};\n#define k_r8_256    LOAD_256(k_r8_arr_256)\n#define k_r16_256   LOAD_256(k_r16_arr_256)\n#endif\n\n// #define k_r8_256    SET_FROM_128(_mm_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1))\n// #define k_r16_256   SET_FROM_128(_mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2))\n// #define k_inc_256   SET_FROM_128(_mm_set_epi32(0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE))\n// #define k_iv0_256   SET_FROM_128(GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 0))\n#define k_iv4_256   SET_FROM_128(GET_CONST_128_FROM_ARRAY32(k_Blake2s_IV + 4))\n#endif // Z7_BLAKE2S_USE_AVX2_WAY_SLOW\n#endif\n\n\n/*\nIPC(TP) ports:\n1 p__5  : skl-      : SSE   : shufps  : _mm_shuffle_ps\n2 p_15  : icl+\n1 p__5  : nhm-bdw   : SSE   : xorps   : _mm_xor_ps\n3 p015  : skl+\n\n3 p015              : SSE2  : pxor    : _mm_xor_si128\n2 p_15:   snb-bdw   : SSE2  : padd    : _mm_add_epi32\n2 p0_5:   mrm-wsm   :\n3 p015  : skl+\n\n2 p_15  : ivb-,icl+ : SSE2  : punpcklqdq, punpckhqdq, punpckldq, punpckhdq\n2 p_15  :           : SSE2  : pshufd  : _mm_shuffle_epi32\n2 p_15  :           : SSE2  : pshuflw : _mm_shufflelo_epi16\n2 p_15  :           : SSE2  : psrldq  :\n2 p_15  :           : SSE3  : pshufb  : _mm_shuffle_epi8\n2 p_15  :           : SSE4  : pblendw : _mm_blend_epi16\n1 p__5  : hsw-skl   : *\n\n1 p0                : SSE2  : pslld (i8) : _mm_slli_si128\n2 p01   : skl+      :\n\n2 p_15  : ivb-      : SSE3  : palignr\n1 p__5  : hsw+\n\n2 p_15 + p23 : ivb-, icl+ : SSE4   : pinsrd  : _mm_insert_epi32(xmm, m32, i8)\n1 p__5 + p23 : hsw-skl\n1 p_15 + p5  : ivb-, ice+ : SSE4   : pinsrd  : _mm_insert_epi32(xmm, r32, i8)\n0.5    2*p5  : hsw-skl\n\n2 p23               : SSE2   : movd (m32)\n3 p23A  : adl       :\n1 p5:               : SSE2   : movd (r32)\n*/\n\n#if 0 && defined(__XOP__)\n// we must debug and test __XOP__ instruction\n#include <x86intrin.h>\n#include <ammintrin.h>\n    #define LOAD_ROTATE_CONSTS\n    #define MM_ROR_EPI32(r, c)  _mm_roti_epi32(r, -(c))\n    #define Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED\n#elif 1 && defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)\n    #define LOAD_ROTATE_CONSTS\n    #define MM_ROR_EPI32(r, c)  _mm_ror_epi32(r, c)\n    #define Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED\n#else\n\n// MSVC_1937+ uses \"orps\" instruction for _mm_or_si128().\n// But \"orps\" has low throughput: TP=1 for bdw-nhm.\n// So it can be better to use _mm_add_epi32()/\"paddd\" (TP=2 for bdw-nhm) instead of \"xorps\".\n// But \"orps\" is fast for modern cpus (skl+).\n// So we are default with \"or\" version:\n#if 0 || 0 && defined(Z7_MSC_VER_ORIGINAL) && Z7_MSC_VER_ORIGINAL > 1937\n  // minor optimization for some old cpus, if \"xorps\" is slow.\n  #define MM128_EPI32_OR_or_ADD  _mm_add_epi32\n#else\n  #define MM128_EPI32_OR_or_ADD  _mm_or_si128\n#endif\n\n  #define MM_ROR_EPI32_VIA_SHIFT(r, c)( \\\n    MM128_EPI32_OR_or_ADD( \\\n      _mm_srli_epi32((r), (c)), \\\n      _mm_slli_epi32((r), 32-(c))))\n  #if defined(Z7_BLAKE2S_USE_SSSE3) || defined(Z7_BLAKE2S_USE_SSE41)\n    #define LOAD_ROTATE_CONSTS \\\n      const __m128i  r8 = k_r8; \\\n      const __m128i r16 = k_r16;\n    #define MM_ROR_EPI32(r, c) ( \\\n      ( 8==(c)) ? _mm_shuffle_epi8(r,r8) \\\n    : (16==(c)) ? _mm_shuffle_epi8(r,r16) \\\n    : MM_ROR_EPI32_VIA_SHIFT(r, c))\n  #else\n    #define LOAD_ROTATE_CONSTS\n    #define  MM_ROR_EPI32(r, c) ( \\\n      (16==(c)) ? _mm_shufflehi_epi16(_mm_shufflelo_epi16(r, 0xb1), 0xb1) \\\n    : MM_ROR_EPI32_VIA_SHIFT(r, c))\n  #endif\n#endif\n\n/*\nwe have 3 main ways to load 4 32-bit integers to __m128i:\n  1) SSE2:  _mm_set_epi32()\n  2) SSE2:  _mm_unpacklo_epi64() / _mm_unpacklo_epi32 / _mm_cvtsi32_si128()\n  3) SSE41: _mm_insert_epi32() and _mm_cvtsi32_si128()\ngood compiler for _mm_set_epi32() generates these instructions:\n{\n  movd xmm, [m32]; vpunpckldq; vpunpckldq; vpunpcklqdq;\n}\ngood new compiler generates one instruction\n{\n  for _mm_insert_epi32()  : { pinsrd xmm, [m32], i }\n  for _mm_cvtsi32_si128() : { movd xmm, [m32] }\n}\nbut vc2010 generates slow pair of instructions:\n{\n  for _mm_insert_epi32()  : { mov r32, [m32];  pinsrd xmm, r32, i  }\n  for _mm_cvtsi32_si128() : { mov r32, [m32];  movd  xmm, r32 }\n}\n_mm_insert_epi32() (pinsrd) code reduces xmm register pressure\nin comparison with _mm_set_epi32() (movd + vpunpckld) code.\nNote that variant with \"movd xmm, r32\" can be more slow,\nbut register pressure can be more important.\nSo we can force to \"pinsrd\" always.\n*/\n// #if !defined(Z7_MSC_VER_ORIGINAL) || Z7_MSC_VER_ORIGINAL > 1600 || defined(MY_CPU_X86)\n#ifdef Z7_BLAKE2S_USE_SSE41\n  /* _mm_set_epi32() can be more effective for GCC and CLANG\n     _mm_insert_epi32()  is more effective for MSVC */\n  #if 0 || 1 && defined(Z7_MSC_VER_ORIGINAL)\n    #define Z7_BLAKE2S_USE_INSERT_INSTRUCTION\n  #endif\n#endif // USE_SSE41\n// #endif\n\n#ifdef Z7_BLAKE2S_USE_INSERT_INSTRUCTION\n  // for SSE4.1\n#define MM_LOAD_EPI32_FROM_4_POINTERS(p0, p1, p2, p3)  \\\n    _mm_insert_epi32( \\\n    _mm_insert_epi32( \\\n    _mm_insert_epi32( \\\n    _mm_cvtsi32_si128( \\\n        *(const Int32 *)p0), \\\n        *(const Int32 *)p1, 1), \\\n        *(const Int32 *)p2, 2), \\\n        *(const Int32 *)p3, 3)\n#elif 0 || 1 && defined(Z7_MSC_VER_ORIGINAL)\n/* MSVC 1400 implements _mm_set_epi32() via slow memory write/read.\n   Also _mm_unpacklo_epi32 is more effective for another MSVC compilers.\n   But _mm_set_epi32() is more effective for GCC and CLANG.\n   So we use _mm_unpacklo_epi32 for MSVC only */\n#define MM_LOAD_EPI32_FROM_4_POINTERS(p0, p1, p2, p3)  \\\n    _mm_unpacklo_epi64(  \\\n        _mm_unpacklo_epi32( _mm_cvtsi32_si128(*(const Int32 *)p0),  \\\n                            _mm_cvtsi32_si128(*(const Int32 *)p1)), \\\n        _mm_unpacklo_epi32( _mm_cvtsi32_si128(*(const Int32 *)p2),  \\\n                            _mm_cvtsi32_si128(*(const Int32 *)p3)))\n#else\n#define MM_LOAD_EPI32_FROM_4_POINTERS(p0, p1, p2, p3)  \\\n    _mm_set_epi32( \\\n        *(const Int32 *)p3, \\\n        *(const Int32 *)p2, \\\n        *(const Int32 *)p1, \\\n        *(const Int32 *)p0)\n#endif\n\n#define SET_ROW_FROM_SIGMA_BASE(input, i0, i1, i2, i3)  \\\n      MM_LOAD_EPI32_FROM_4_POINTERS( \\\n        GET_SIGMA_PTR(input, i0), \\\n        GET_SIGMA_PTR(input, i1), \\\n        GET_SIGMA_PTR(input, i2), \\\n        GET_SIGMA_PTR(input, i3))\n\n#define SET_ROW_FROM_SIGMA(input, sigma_index)  \\\n        SET_ROW_FROM_SIGMA_BASE(input, \\\n            sigma[(sigma_index)        ], \\\n            sigma[(sigma_index) + 2 * 1], \\\n            sigma[(sigma_index) + 2 * 2], \\\n            sigma[(sigma_index) + 2 * 3]) \\\n\n\n#define ADD_128(a, b)   _mm_add_epi32(a, b)\n#define XOR_128(a, b)   _mm_xor_si128(a, b)\n\n#define D_ADD_128(dest, src)        dest = ADD_128(dest, src)\n#define D_XOR_128(dest, src)        dest = XOR_128(dest, src)\n#define D_ROR_128(dest, shift)      dest = MM_ROR_EPI32(dest, shift)\n#define D_ADD_EPI64_128(dest, src)  dest = _mm_add_epi64(dest, src)\n\n\n#define AXR(a, b, d, shift) \\\n    D_ADD_128(a, b); \\\n    D_XOR_128(d, a); \\\n    D_ROR_128(d, shift);\n\n#define AXR2(a, b, c, d, input, sigma_index, shift1, shift2) \\\n    a = _mm_add_epi32 (a, SET_ROW_FROM_SIGMA(input, sigma_index)); \\\n    AXR(a, b, d, shift1) \\\n    AXR(c, d, b, shift2)\n\n#define ROTATE_WORDS_TO_RIGHT(a, n) \\\n    a = _mm_shuffle_epi32(a, _MM_SHUFFLE((3+n)&3, (2+n)&3, (1+n)&3, (0+n)&3));\n\n#define AXR4(a, b, c, d, input, sigma_index)  \\\n    AXR2(a, b, c, d, input, sigma_index,     16, 12) \\\n    AXR2(a, b, c, d, input, sigma_index + 1,  8,  7) \\\n\n#define RR2(a, b, c, d, input) \\\n  { \\\n    AXR4(a, b, c, d, input, 0) \\\n      ROTATE_WORDS_TO_RIGHT(b, 1) \\\n      ROTATE_WORDS_TO_RIGHT(c, 2) \\\n      ROTATE_WORDS_TO_RIGHT(d, 3) \\\n    AXR4(a, b, c, d, input, 8) \\\n      ROTATE_WORDS_TO_RIGHT(b, 3) \\\n      ROTATE_WORDS_TO_RIGHT(c, 2) \\\n      ROTATE_WORDS_TO_RIGHT(d, 1) \\\n  }\n\n\n/*\nWay1:\nper 64 bytes block:\n10 rounds * 4 iters * (7 + 2) = 360 cycles = if pslld TP=1\n                    * (7 + 1) = 320 cycles = if pslld TP=2 (skl+)\nadditional operations per 7_op_iter :\n4 movzx   byte mem\n1 movd    mem\n3 pinsrd  mem\n1.5 pshufd\n*/\n\nstatic\n#if 0 || 0 && (defined(Z7_BLAKE2S_USE_V128_WAY2) || \\\n               defined(Z7_BLAKE2S_USE_V256_WAY2))\n  Z7_NO_INLINE\n#else\n  Z7_FORCE_INLINE\n#endif\n#ifdef BLAKE2S_ATTRIB_128BIT\n       BLAKE2S_ATTRIB_128BIT\n#endif\nvoid\nZ7_FASTCALL\nBlake2s_Compress_V128_Way1(UInt32 * const s, const Byte * const input)\n{\n  __m128i a, b, c, d;\n  __m128i f0, f1;\n\n  LOAD_ROTATE_CONSTS\n  d = LOAD_128_FROM_STRUCT(STATE_T(s));\n  c = k_iv0_128;\n  a = f0 = LOAD_128_FROM_STRUCT(s);\n  b = f1 = LOAD_128_FROM_STRUCT(s + 4);\n  D_ADD_EPI64_128(d, k_inc);\n  STORE_128_TO_STRUCT (STATE_T(s), d);\n  D_XOR_128(d, k_iv4_128);\n\n#define RR(r) { const Byte * const sigma = k_Blake2s_Sigma_4[r]; \\\n      RR2(a, b, c, d, input) }\n\n  ROUNDS_LOOP(RR)\n#undef RR\n\n  STORE_128_TO_STRUCT(s    , XOR_128(f0, XOR_128(a, c)));\n  STORE_128_TO_STRUCT(s + 4, XOR_128(f1, XOR_128(b, d)));\n}\n\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_128BIT\n       BLAKE2S_ATTRIB_128BIT\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Compress2_V128_Way1(UInt32 *s_items, const Byte *data, const Byte *end)\n{\n  size_t pos = 0;\n  do\n  {\n    UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n    Blake2s_Compress_V128_Way1(s, data);\n    data += Z7_BLAKE2S_BLOCK_SIZE;\n    pos  += Z7_BLAKE2S_BLOCK_SIZE;\n    pos &= SUPER_BLOCK_MASK;\n  }\n  while (data != end);\n}\n\n\n#if defined(Z7_BLAKE2S_USE_V128_WAY2) || \\\n    defined(Z7_BLAKE2S_USE_AVX2_WAY2)\n#if 1\n  #define Z7_BLAKE2S_CompressSingleBlock(s, data) \\\n    Blake2sp_Compress2_V128_Way1(s, data, \\\n        (const Byte *)(const void *)(data) + Z7_BLAKE2S_BLOCK_SIZE)\n#else\n  #define Z7_BLAKE2S_CompressSingleBlock  Blake2s_Compress_V128_Way1\n#endif\n#endif\n\n\n#if (defined(Z7_BLAKE2S_USE_AVX2_WAY_SLOW) || \\\n     defined(Z7_BLAKE2S_USE_V128_WAY2)) && \\\n    !defined(Z7_BLAKE2S_USE_GATHER)\n#define AXR2_LOAD_INDEXES(sigma_index) \\\n      const unsigned i0 = sigma[(sigma_index)]; \\\n      const unsigned i1 = sigma[(sigma_index) + 2 * 1]; \\\n      const unsigned i2 = sigma[(sigma_index) + 2 * 2]; \\\n      const unsigned i3 = sigma[(sigma_index) + 2 * 3]; \\\n\n#define SET_ROW_FROM_SIGMA_W(input) \\\n    SET_ROW_FROM_SIGMA_BASE(input, i0, i1, i2, i3)\n#endif\n\n\n#ifdef Z7_BLAKE2S_USE_V128_WAY2\n\n#if 1 || !defined(Z7_BLAKE2S_USE_SSE41)\n/* we use SET_ROW_FROM_SIGMA_BASE, that uses\n   (SSE4) _mm_insert_epi32(), if Z7_BLAKE2S_USE_INSERT_INSTRUCTION is defined\n   (SSE2) _mm_set_epi32()\n   MSVC can be faster for this branch:\n*/\n#define AXR2_W(sigma_index, shift1, shift2) \\\n  { \\\n    AXR2_LOAD_INDEXES(sigma_index) \\\n    a0 = _mm_add_epi32(a0, SET_ROW_FROM_SIGMA_W(data)); \\\n    a1 = _mm_add_epi32(a1, SET_ROW_FROM_SIGMA_W(data + Z7_BLAKE2S_BLOCK_SIZE)); \\\n    AXR(a0, b0, d0, shift1) \\\n    AXR(a1, b1, d1, shift1) \\\n    AXR(c0, d0, b0, shift2) \\\n    AXR(c1, d1, b1, shift2) \\\n  }\n#else\n/* we use interleaved _mm_insert_epi32():\n   GCC can be faster for this branch:\n*/\n#define AXR2_W_PRE_INSERT(sigma_index, i) \\\n  { const unsigned ii = sigma[(sigma_index) + i * 2]; \\\n    t0 = _mm_insert_epi32(t0, *(const Int32 *)GET_SIGMA_PTR(data, ii),                      i); \\\n    t1 = _mm_insert_epi32(t1, *(const Int32 *)GET_SIGMA_PTR(data, Z7_BLAKE2S_BLOCK_SIZE + ii), i); \\\n  }\n#define AXR2_W(sigma_index, shift1, shift2) \\\n  { __m128i t0, t1; \\\n    { const unsigned ii = sigma[sigma_index]; \\\n      t0 = _mm_cvtsi32_si128(*(const Int32 *)GET_SIGMA_PTR(data, ii)); \\\n      t1 = _mm_cvtsi32_si128(*(const Int32 *)GET_SIGMA_PTR(data, Z7_BLAKE2S_BLOCK_SIZE + ii)); \\\n    } \\\n    AXR2_W_PRE_INSERT(sigma_index, 1) \\\n    AXR2_W_PRE_INSERT(sigma_index, 2) \\\n    AXR2_W_PRE_INSERT(sigma_index, 3) \\\n    a0 = _mm_add_epi32(a0, t0); \\\n    a1 = _mm_add_epi32(a1, t1); \\\n    AXR(a0, b0, d0, shift1) \\\n    AXR(a1, b1, d1, shift1) \\\n    AXR(c0, d0, b0, shift2) \\\n    AXR(c1, d1, b1, shift2) \\\n  }\n#endif\n\n\n#define AXR4_W(sigma_index) \\\n    AXR2_W(sigma_index,     16, 12) \\\n    AXR2_W(sigma_index + 1,  8,  7) \\\n\n#define WW(r) \\\n  { const Byte * const sigma = k_Blake2s_Sigma_4[r]; \\\n    AXR4_W(0) \\\n      ROTATE_WORDS_TO_RIGHT(b0, 1) \\\n      ROTATE_WORDS_TO_RIGHT(b1, 1) \\\n      ROTATE_WORDS_TO_RIGHT(c0, 2) \\\n      ROTATE_WORDS_TO_RIGHT(c1, 2) \\\n      ROTATE_WORDS_TO_RIGHT(d0, 3) \\\n      ROTATE_WORDS_TO_RIGHT(d1, 3) \\\n    AXR4_W(8) \\\n      ROTATE_WORDS_TO_RIGHT(b0, 3) \\\n      ROTATE_WORDS_TO_RIGHT(b1, 3) \\\n      ROTATE_WORDS_TO_RIGHT(c0, 2) \\\n      ROTATE_WORDS_TO_RIGHT(c1, 2) \\\n      ROTATE_WORDS_TO_RIGHT(d0, 1) \\\n      ROTATE_WORDS_TO_RIGHT(d1, 1) \\\n  }\n\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_128BIT\n       BLAKE2S_ATTRIB_128BIT\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Compress2_V128_Way2(UInt32 *s_items, const Byte *data, const Byte *end)\n{\n  size_t pos = 0;\n  end -= Z7_BLAKE2S_BLOCK_SIZE;\n\n  if (data != end)\n  {\n    LOAD_ROTATE_CONSTS\n    do\n    {\n      UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n      __m128i a0, b0, c0, d0;\n      __m128i a1, b1, c1, d1;\n      {\n        const __m128i inc = k_inc;\n        const __m128i temp = k_iv4_128;\n        d0 = LOAD_128_FROM_STRUCT (STATE_T(s));\n        d1 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW));\n        D_ADD_EPI64_128(d0, inc);\n        D_ADD_EPI64_128(d1, inc);\n        STORE_128_TO_STRUCT (STATE_T(s      ), d0);\n        STORE_128_TO_STRUCT (STATE_T(s + NSW), d1);\n        D_XOR_128(d0, temp);\n        D_XOR_128(d1, temp);\n      }\n      c1 = c0 = k_iv0_128;\n      a0 = LOAD_128_FROM_STRUCT(s);\n      b0 = LOAD_128_FROM_STRUCT(s + 4);\n      a1 = LOAD_128_FROM_STRUCT(s + NSW);\n      b1 = LOAD_128_FROM_STRUCT(s + NSW + 4);\n      \n      ROUNDS_LOOP (WW)\n\n#undef WW\n      \n      D_XOR_128(a0, c0);\n      D_XOR_128(b0, d0);\n      D_XOR_128(a1, c1);\n      D_XOR_128(b1, d1);\n      \n      D_XOR_128(a0, LOAD_128_FROM_STRUCT(s));\n      D_XOR_128(b0, LOAD_128_FROM_STRUCT(s + 4));\n      D_XOR_128(a1, LOAD_128_FROM_STRUCT(s + NSW));\n      D_XOR_128(b1, LOAD_128_FROM_STRUCT(s + NSW + 4));\n      \n      STORE_128_TO_STRUCT(s,           a0);\n      STORE_128_TO_STRUCT(s + 4,       b0);\n      STORE_128_TO_STRUCT(s + NSW,     a1);\n      STORE_128_TO_STRUCT(s + NSW + 4, b1);\n      \n      data += Z7_BLAKE2S_BLOCK_SIZE * 2;\n      pos  += Z7_BLAKE2S_BLOCK_SIZE * 2;\n      pos &= SUPER_BLOCK_MASK;\n    }\n    while (data < end);\n    if (data != end)\n      return;\n  }\n  {\n    UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n    Z7_BLAKE2S_CompressSingleBlock(s, data);\n  }\n}\n#endif // Z7_BLAKE2S_USE_V128_WAY2\n\n\n#ifdef Z7_BLAKE2S_USE_V128_WAY2\n  #define Z7_BLAKE2S_Compress2_V128  Blake2sp_Compress2_V128_Way2\n#else\n  #define Z7_BLAKE2S_Compress2_V128  Blake2sp_Compress2_V128_Way1\n#endif\n\n\n\n#ifdef Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED\n  #define ROT_128_8(x)    MM_ROR_EPI32(x, 8)\n  #define ROT_128_16(x)   MM_ROR_EPI32(x, 16)\n  #define ROT_128_7(x)    MM_ROR_EPI32(x, 7)\n  #define ROT_128_12(x)   MM_ROR_EPI32(x, 12)\n#else\n#if defined(Z7_BLAKE2S_USE_SSSE3) || defined(Z7_BLAKE2S_USE_SSE41)\n  #define ROT_128_8(x)    _mm_shuffle_epi8(x, r8)   // k_r8\n  #define ROT_128_16(x)   _mm_shuffle_epi8(x, r16)  // k_r16\n#else\n  #define ROT_128_8(x)    MM_ROR_EPI32_VIA_SHIFT(x, 8)\n  #define ROT_128_16(x)   MM_ROR_EPI32_VIA_SHIFT(x, 16)\n#endif\n  #define ROT_128_7(x)    MM_ROR_EPI32_VIA_SHIFT(x, 7)\n  #define ROT_128_12(x)   MM_ROR_EPI32_VIA_SHIFT(x, 12)\n#endif\n\n\n#if 1\n// this branch can provide similar speed on x86* in most cases,\n// because [base + index*4] provides same speed as [base + index].\n// but some compilers can generate different code with this branch, that can be faster sometimes.\n// this branch uses additional table of 10*16=160 bytes.\n#define SIGMA_TABLE_MULT_16( a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \\\n        SIGMA_TABLE_MULT(16, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)\nMY_ALIGN(16)\nstatic const Byte k_Blake2s_Sigma_16[BLAKE2S_NUM_ROUNDS][16] =\n  { SIGMA_TABLE(SIGMA_TABLE_MULT_16) };\n#define GET_SIGMA_PTR_128(r)  const Byte * const sigma = k_Blake2s_Sigma_16[r];\n#define GET_SIGMA_VAL_128(n)  (sigma[n])\n#else\n#define GET_SIGMA_PTR_128(r)  const Byte * const sigma = k_Blake2s_Sigma_4[r];\n#define GET_SIGMA_VAL_128(n)  (4 * (size_t)sigma[n])\n#endif\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2_FAST\n#if 1\n#define SIGMA_TABLE_MULT_32( a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \\\n        SIGMA_TABLE_MULT(32, a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)\nMY_ALIGN(64)\nstatic const UInt16 k_Blake2s_Sigma_32[BLAKE2S_NUM_ROUNDS][16] =\n  { SIGMA_TABLE(SIGMA_TABLE_MULT_32) };\n#define GET_SIGMA_PTR_256(r)  const UInt16 * const sigma = k_Blake2s_Sigma_32[r];\n#define GET_SIGMA_VAL_256(n)  (sigma[n])\n#else\n#define GET_SIGMA_PTR_256(r)  const Byte * const sigma = k_Blake2s_Sigma_4[r];\n#define GET_SIGMA_VAL_256(n)  (8 * (size_t)sigma[n])\n#endif\n#endif // Z7_BLAKE2S_USE_AVX2_FAST\n\n\n#define D_ROT_128_7(dest)     dest = ROT_128_7(dest)\n#define D_ROT_128_8(dest)     dest = ROT_128_8(dest)\n#define D_ROT_128_12(dest)    dest = ROT_128_12(dest)\n#define D_ROT_128_16(dest)    dest = ROT_128_16(dest)\n\n#define OP_L(a, i)   D_ADD_128 (V(a, 0), \\\n    LOAD_128((const Byte *)(w) + GET_SIGMA_VAL_128(2*(a)+(i))));\n\n#define OP_0(a)   OP_L(a, 0)\n#define OP_7(a)   OP_L(a, 1)\n\n#define OP_1(a)   D_ADD_128 (V(a, 0), V(a, 1));\n#define OP_2(a)   D_XOR_128 (V(a, 3), V(a, 0));\n#define OP_4(a)   D_ADD_128 (V(a, 2), V(a, 3));\n#define OP_5(a)   D_XOR_128 (V(a, 1), V(a, 2));\n\n#define OP_3(a)   D_ROT_128_16 (V(a, 3));\n#define OP_6(a)   D_ROT_128_12 (V(a, 1));\n#define OP_8(a)   D_ROT_128_8  (V(a, 3));\n#define OP_9(a)   D_ROT_128_7  (V(a, 1));\n\n\n// for 32-bit x86 : interleave mode works slower, because of register pressure.\n\n#if 0 || 1 && (defined(MY_CPU_X86) \\\n  || defined(__GNUC__) && !defined(__clang__))\n// non-inteleaved version:\n// is fast for x86 32-bit.\n// is fast for GCC x86-64.\n\n#define V4G(a) \\\n  OP_0 (a) \\\n  OP_1 (a) \\\n  OP_2 (a) \\\n  OP_3 (a) \\\n  OP_4 (a) \\\n  OP_5 (a) \\\n  OP_6 (a) \\\n  OP_7 (a) \\\n  OP_1 (a) \\\n  OP_2 (a) \\\n  OP_8 (a) \\\n  OP_4 (a) \\\n  OP_5 (a) \\\n  OP_9 (a) \\\n\n#define V4R \\\n{ \\\n  V4G (0) \\\n  V4G (1) \\\n  V4G (2) \\\n  V4G (3) \\\n  V4G (4) \\\n  V4G (5) \\\n  V4G (6) \\\n  V4G (7) \\\n}\n\n#elif 0 || 1 && defined(MY_CPU_X86)\n\n#define OP_INTER_2(op, a,b) \\\n  op (a) \\\n  op (b) \\\n\n#define V4G(a,b) \\\n  OP_INTER_2 (OP_0, a,b) \\\n  OP_INTER_2 (OP_1, a,b) \\\n  OP_INTER_2 (OP_2, a,b) \\\n  OP_INTER_2 (OP_3, a,b) \\\n  OP_INTER_2 (OP_4, a,b) \\\n  OP_INTER_2 (OP_5, a,b) \\\n  OP_INTER_2 (OP_6, a,b) \\\n  OP_INTER_2 (OP_7, a,b) \\\n  OP_INTER_2 (OP_1, a,b) \\\n  OP_INTER_2 (OP_2, a,b) \\\n  OP_INTER_2 (OP_8, a,b) \\\n  OP_INTER_2 (OP_4, a,b) \\\n  OP_INTER_2 (OP_5, a,b) \\\n  OP_INTER_2 (OP_9, a,b) \\\n\n#define V4R \\\n{ \\\n  V4G (0, 1) \\\n  V4G (2, 3) \\\n  V4G (4, 5) \\\n  V4G (6, 7) \\\n}\n\n#else\n// iterleave-4 version is fast for x64 (MSVC/CLANG)\n\n#define OP_INTER_4(op, a,b,c,d) \\\n  op (a) \\\n  op (b) \\\n  op (c) \\\n  op (d) \\\n\n#define V4G(a,b,c,d) \\\n  OP_INTER_4 (OP_0, a,b,c,d) \\\n  OP_INTER_4 (OP_1, a,b,c,d) \\\n  OP_INTER_4 (OP_2, a,b,c,d) \\\n  OP_INTER_4 (OP_3, a,b,c,d) \\\n  OP_INTER_4 (OP_4, a,b,c,d) \\\n  OP_INTER_4 (OP_5, a,b,c,d) \\\n  OP_INTER_4 (OP_6, a,b,c,d) \\\n  OP_INTER_4 (OP_7, a,b,c,d) \\\n  OP_INTER_4 (OP_1, a,b,c,d) \\\n  OP_INTER_4 (OP_2, a,b,c,d) \\\n  OP_INTER_4 (OP_8, a,b,c,d) \\\n  OP_INTER_4 (OP_4, a,b,c,d) \\\n  OP_INTER_4 (OP_5, a,b,c,d) \\\n  OP_INTER_4 (OP_9, a,b,c,d) \\\n\n#define V4R \\\n{ \\\n  V4G (0, 1, 2, 3) \\\n  V4G (4, 5, 6, 7) \\\n}\n\n#endif\n\n#define V4_ROUND(r)  { GET_SIGMA_PTR_128(r); V4R }\n\n\n#define V4_LOAD_MSG_1(w, m, i) \\\n{ \\\n  __m128i m0, m1, m2, m3; \\\n  __m128i t0, t1, t2, t3; \\\n  m0 = LOADU_128((m) + ((i) + 0 * 4) * 16); \\\n  m1 = LOADU_128((m) + ((i) + 1 * 4) * 16); \\\n  m2 = LOADU_128((m) + ((i) + 2 * 4) * 16); \\\n  m3 = LOADU_128((m) + ((i) + 3 * 4) * 16); \\\n  t0 = _mm_unpacklo_epi32(m0, m1); \\\n  t1 = _mm_unpackhi_epi32(m0, m1); \\\n  t2 = _mm_unpacklo_epi32(m2, m3); \\\n  t3 = _mm_unpackhi_epi32(m2, m3); \\\n  w[(i) * 4 + 0] = _mm_unpacklo_epi64(t0, t2); \\\n  w[(i) * 4 + 1] = _mm_unpackhi_epi64(t0, t2); \\\n  w[(i) * 4 + 2] = _mm_unpacklo_epi64(t1, t3); \\\n  w[(i) * 4 + 3] = _mm_unpackhi_epi64(t1, t3); \\\n}\n\n#define V4_LOAD_MSG(w, m) \\\n{ \\\n  V4_LOAD_MSG_1 (w, m, 0) \\\n  V4_LOAD_MSG_1 (w, m, 1) \\\n  V4_LOAD_MSG_1 (w, m, 2) \\\n  V4_LOAD_MSG_1 (w, m, 3) \\\n}\n\n#define V4_LOAD_UNPACK_PAIR_128(src32, i, d0, d1) \\\n{ \\\n  const __m128i v0 = LOAD_128_FROM_STRUCT((src32) + (i    ) * 4);  \\\n  const __m128i v1 = LOAD_128_FROM_STRUCT((src32) + (i + 1) * 4);  \\\n  d0 = _mm_unpacklo_epi32(v0, v1);  \\\n  d1 = _mm_unpackhi_epi32(v0, v1);  \\\n}\n\n#define V4_UNPACK_PAIR_128(dest32, i, s0, s1) \\\n{ \\\n  STORE_128_TO_STRUCT((dest32) + i * 4     , _mm_unpacklo_epi64(s0, s1));  \\\n  STORE_128_TO_STRUCT((dest32) + i * 4 + 16, _mm_unpackhi_epi64(s0, s1));  \\\n}\n\n#define V4_UNPACK_STATE(dest32, src32) \\\n{ \\\n  __m128i t0, t1, t2, t3, t4, t5, t6, t7; \\\n  V4_LOAD_UNPACK_PAIR_128(src32, 0, t0, t1)  \\\n  V4_LOAD_UNPACK_PAIR_128(src32, 2, t2, t3)  \\\n  V4_LOAD_UNPACK_PAIR_128(src32, 4, t4, t5)  \\\n  V4_LOAD_UNPACK_PAIR_128(src32, 6, t6, t7)  \\\n  V4_UNPACK_PAIR_128(dest32, 0, t0, t2)  \\\n  V4_UNPACK_PAIR_128(dest32, 8, t1, t3)  \\\n  V4_UNPACK_PAIR_128(dest32, 1, t4, t6)  \\\n  V4_UNPACK_PAIR_128(dest32, 9, t5, t7)  \\\n}\n\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_128BIT\n       BLAKE2S_ATTRIB_128BIT\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Compress2_V128_Fast(UInt32 *s_items, const Byte *data, const Byte *end)\n{\n  // PrintStates2(s_items, 8, 16);\n  size_t pos = 0;\n  pos /= 2;\n  do\n  {\n#if defined(Z7_BLAKE2S_USE_SSSE3) && \\\n   !defined(Z7_BLAKE2S_MM_ROR_EPI32_IS_SUPPORTED)\n    const __m128i  r8 = k_r8;\n    const __m128i r16 = k_r16;\n#endif\n    __m128i w[16];\n    __m128i v[16];\n    UInt32 *s;\n    V4_LOAD_MSG(w, data)\n    s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n    {\n      __m128i ctr = LOAD_128_FROM_STRUCT(s + 64);\n      D_ADD_EPI64_128 (ctr, k_inc);\n      STORE_128_TO_STRUCT(s + 64, ctr);\n      v[12] = XOR_128 (GET_128_IV_WAY4(4), _mm_shuffle_epi32(ctr, _MM_SHUFFLE(0, 0, 0, 0)));\n      v[13] = XOR_128 (GET_128_IV_WAY4(5), _mm_shuffle_epi32(ctr, _MM_SHUFFLE(1, 1, 1, 1)));\n    }\n    v[ 8] = GET_128_IV_WAY4(0);\n    v[ 9] = GET_128_IV_WAY4(1);\n    v[10] = GET_128_IV_WAY4(2);\n    v[11] = GET_128_IV_WAY4(3);\n    v[14] = GET_128_IV_WAY4(6);\n    v[15] = GET_128_IV_WAY4(7);\n    \n#define LOAD_STATE_128_FROM_STRUCT(i) \\\n      v[i] = LOAD_128_FROM_STRUCT(s + (i) * 4);\n\n#define UPDATE_STATE_128_IN_STRUCT(i) \\\n      STORE_128_TO_STRUCT(s + (i) * 4, XOR_128( \\\n      XOR_128(v[i], v[(i) + 8]), \\\n      LOAD_128_FROM_STRUCT(s + (i) * 4)));\n    \n    REP8_MACRO (LOAD_STATE_128_FROM_STRUCT)\n    ROUNDS_LOOP (V4_ROUND)\n    REP8_MACRO (UPDATE_STATE_128_IN_STRUCT)\n\n    data += Z7_BLAKE2S_BLOCK_SIZE * 4;\n    pos  += Z7_BLAKE2S_BLOCK_SIZE * 4 / 2;\n    pos &= SUPER_BLOCK_SIZE / 2 - 1;\n  }\n  while (data != end);\n}\n\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_128BIT\n       BLAKE2S_ATTRIB_128BIT\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Final_V128_Fast(UInt32 *states)\n{\n  const __m128i ctr = LOAD_128_FROM_STRUCT(states + 64);\n  // printf(\"\\nBlake2sp_Compress2_V128_Fast_Final4\\n\");\n  // PrintStates2(states, 8, 16);\n  {\n    ptrdiff_t pos = 8 * 4;\n    do\n    {\n      UInt32 *src32  = states + (size_t)(pos * 1);\n      UInt32 *dest32 = states + (size_t)(pos * 2);\n      V4_UNPACK_STATE(dest32, src32)\n      pos -= 8 * 4;\n    }\n    while (pos >= 0);\n  }\n  {\n    unsigned k;\n    for (k = 0; k < 8; k++)\n    {\n      UInt32 *s = states + (size_t)k * 16;\n      STORE_128_TO_STRUCT (STATE_T(s), ctr);\n    }\n  }\n  // PrintStates2(states, 8, 16);\n}\n\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2\n\n#define ADD_256(a, b)  _mm256_add_epi32(a, b)\n#define XOR_256(a, b)  _mm256_xor_si256(a, b)\n\n#if 1 && defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)\n  #define MM256_ROR_EPI32  _mm256_ror_epi32\n  #define Z7_MM256_ROR_EPI32_IS_SUPPORTED\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY2\n  #define LOAD_ROTATE_CONSTS_256\n#endif\n#else\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY2\n  #define LOAD_ROTATE_CONSTS_256 \\\n      const __m256i  r8 = k_r8_256; \\\n      const __m256i r16 = k_r16_256;\n#endif // AVX2_WAY2\n\n  #define MM256_ROR_EPI32(r, c) ( \\\n      ( 8==(c)) ? _mm256_shuffle_epi8(r,r8) \\\n    : (16==(c)) ? _mm256_shuffle_epi8(r,r16) \\\n    : _mm256_or_si256( \\\n      _mm256_srli_epi32((r), (c)), \\\n      _mm256_slli_epi32((r), 32-(c))))\n#endif // WAY_SLOW\n#endif\n\n\n#define D_ADD_256(dest, src)  dest = ADD_256(dest, src)\n#define D_XOR_256(dest, src)  dest = XOR_256(dest, src)\n\n#define LOADU_256(p)     _mm256_loadu_si256((const __m256i *)(const void *)(p))\n\n#ifdef Z7_BLAKE2S_USE_AVX2_FAST\n\n#ifdef Z7_MM256_ROR_EPI32_IS_SUPPORTED\n#define ROT_256_16(x) MM256_ROR_EPI32((x), 16)\n#define ROT_256_12(x) MM256_ROR_EPI32((x), 12)\n#define ROT_256_8(x)  MM256_ROR_EPI32((x),  8)\n#define ROT_256_7(x)  MM256_ROR_EPI32((x),  7)\n#else\n#define ROTATE8  _mm256_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1, \\\n                                 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1)\n#define ROTATE16 _mm256_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2, \\\n                                 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2)\n#define ROT_256_16(x) _mm256_shuffle_epi8((x), ROTATE16)\n#define ROT_256_12(x) _mm256_or_si256(_mm256_srli_epi32((x), 12), _mm256_slli_epi32((x), 20))\n#define ROT_256_8(x)  _mm256_shuffle_epi8((x), ROTATE8)\n#define ROT_256_7(x)  _mm256_or_si256(_mm256_srli_epi32((x),  7), _mm256_slli_epi32((x), 25))\n#endif\n\n#define D_ROT_256_7(dest)     dest = ROT_256_7(dest)\n#define D_ROT_256_8(dest)     dest = ROT_256_8(dest)\n#define D_ROT_256_12(dest)    dest = ROT_256_12(dest)\n#define D_ROT_256_16(dest)    dest = ROT_256_16(dest)\n\n#define LOAD_256(p)      _mm256_load_si256((const __m256i *)(const void *)(p))\n#ifdef Z7_BLAKE2SP_STRUCT_IS_NOT_ALIGNED\n  #define STOREU_256(p, r) _mm256_storeu_si256((__m256i *)(void *)(p), r)\n  #define LOAD_256_FROM_STRUCT(p)     LOADU_256(p)\n  #define STORE_256_TO_STRUCT(p, r)   STOREU_256(p, r)\n#else\n  // if struct is aligned for 32-bytes\n  #define STORE_256(p, r)  _mm256_store_si256((__m256i *)(void *)(p), r)\n  #define LOAD_256_FROM_STRUCT(p)     LOAD_256(p)\n  #define STORE_256_TO_STRUCT(p, r)   STORE_256(p, r)\n#endif\n\n#endif // Z7_BLAKE2S_USE_AVX2_FAST\n\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY_SLOW\n\n#if 0\n    #define DIAG_PERM2(s) \\\n    { \\\n      const __m256i a = LOAD_256_FROM_STRUCT((s)      ); \\\n      const __m256i b = LOAD_256_FROM_STRUCT((s) + NSW); \\\n      STORE_256_TO_STRUCT((s      ), _mm256_permute2x128_si256(a, b, 0x20)); \\\n      STORE_256_TO_STRUCT((s + NSW), _mm256_permute2x128_si256(a, b, 0x31)); \\\n    }\n#else\n    #define DIAG_PERM2(s) \\\n    { \\\n      const __m128i a = LOAD_128_FROM_STRUCT((s) + 4); \\\n      const __m128i b = LOAD_128_FROM_STRUCT((s) + NSW); \\\n      STORE_128_TO_STRUCT((s) + NSW, a); \\\n      STORE_128_TO_STRUCT((s) + 4  , b); \\\n    }\n#endif\n    #define DIAG_PERM8(s_items) \\\n    { \\\n      DIAG_PERM2(s_items) \\\n      DIAG_PERM2(s_items + NSW * 2) \\\n      DIAG_PERM2(s_items + NSW * 4) \\\n      DIAG_PERM2(s_items + NSW * 6) \\\n    }\n\n\n#define AXR256(a, b, d, shift) \\\n    D_ADD_256(a, b); \\\n    D_XOR_256(d, a); \\\n    d = MM256_ROR_EPI32(d, shift); \\\n\n\n\n#ifdef Z7_BLAKE2S_USE_GATHER\n\n  #define TABLE_GATHER_256_4(a0,a1,a2,a3) \\\n    a0,a1,a2,a3, a0+16,a1+16,a2+16,a3+16\n  #define TABLE_GATHER_256( \\\n    a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15) \\\n  { TABLE_GATHER_256_4(a0,a2,a4,a6), \\\n    TABLE_GATHER_256_4(a1,a3,a5,a7), \\\n    TABLE_GATHER_256_4(a8,a10,a12,a14), \\\n    TABLE_GATHER_256_4(a9,a11,a13,a15) }\nMY_ALIGN(64)\nstatic const UInt32 k_Blake2s_Sigma_gather256[BLAKE2S_NUM_ROUNDS][16 * 2] =\n  { SIGMA_TABLE(TABLE_GATHER_256) };\n  #define GET_SIGMA(r) \\\n    const UInt32 * const sigma = k_Blake2s_Sigma_gather256[r];\n  #define AXR2_LOAD_INDEXES_AVX(sigma_index) \\\n    const __m256i i01234567 = LOAD_256(sigma + (sigma_index));\n  #define SET_ROW_FROM_SIGMA_AVX(in) \\\n    _mm256_i32gather_epi32((const void *)(in), i01234567, 4)\n  #define SIGMA_INTERLEAVE    8\n  #define SIGMA_HALF_ROW_SIZE 16\n\n#else // !Z7_BLAKE2S_USE_GATHER\n\n  #define GET_SIGMA(r) \\\n    const Byte * const sigma = k_Blake2s_Sigma_4[r];\n  #define AXR2_LOAD_INDEXES_AVX(sigma_index) \\\n    AXR2_LOAD_INDEXES(sigma_index)\n  #define SET_ROW_FROM_SIGMA_AVX(in) \\\n    MY_mm256_set_m128i( \\\n        SET_ROW_FROM_SIGMA_W((in) + Z7_BLAKE2S_BLOCK_SIZE), \\\n        SET_ROW_FROM_SIGMA_W(in))\n  #define SIGMA_INTERLEAVE    1\n  #define SIGMA_HALF_ROW_SIZE 8\n#endif // !Z7_BLAKE2S_USE_GATHER\n\n\n#define ROTATE_WORDS_TO_RIGHT_256(a, n) \\\n    a = _mm256_shuffle_epi32(a, _MM_SHUFFLE((3+n)&3, (2+n)&3, (1+n)&3, (0+n)&3));\n\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY2\n\n#define AXR2_A(sigma_index, shift1, shift2) \\\n    AXR2_LOAD_INDEXES_AVX(sigma_index) \\\n    D_ADD_256( a0, SET_ROW_FROM_SIGMA_AVX(data)); \\\n    AXR256(a0, b0, d0, shift1) \\\n    AXR256(c0, d0, b0, shift2) \\\n\n#define AXR4_A(sigma_index) \\\n    { AXR2_A(sigma_index, 16, 12) } \\\n    { AXR2_A(sigma_index + SIGMA_INTERLEAVE, 8, 7) }\n\n#define EE1(r) \\\n    { GET_SIGMA(r) \\\n      AXR4_A(0) \\\n        ROTATE_WORDS_TO_RIGHT_256(b0, 1) \\\n        ROTATE_WORDS_TO_RIGHT_256(c0, 2) \\\n        ROTATE_WORDS_TO_RIGHT_256(d0, 3) \\\n      AXR4_A(SIGMA_HALF_ROW_SIZE) \\\n        ROTATE_WORDS_TO_RIGHT_256(b0, 3) \\\n        ROTATE_WORDS_TO_RIGHT_256(c0, 2) \\\n        ROTATE_WORDS_TO_RIGHT_256(d0, 1) \\\n    }\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_AVX2\n       BLAKE2S_ATTRIB_AVX2\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Compress2_AVX2_Way2(UInt32 *s_items, const Byte *data, const Byte *end)\n{\n  size_t pos = 0;\n  end -= Z7_BLAKE2S_BLOCK_SIZE;\n\n  if (data != end)\n  {\n    LOAD_ROTATE_CONSTS_256\n    DIAG_PERM8(s_items)\n    do\n    {\n      UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n      __m256i a0, b0, c0, d0;\n      {\n        const __m128i inc = k_inc;\n        __m128i d0_128 = LOAD_128_FROM_STRUCT (STATE_T(s));\n        __m128i d1_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW));\n        D_ADD_EPI64_128(d0_128, inc);\n        D_ADD_EPI64_128(d1_128, inc);\n        STORE_128_TO_STRUCT (STATE_T(s      ), d0_128);\n        STORE_128_TO_STRUCT (STATE_T(s + NSW), d1_128);\n        d0 = MY_mm256_set_m128i(d1_128, d0_128);\n        D_XOR_256(d0, k_iv4_256);\n      }\n      c0 = SET_FROM_128(k_iv0_128);\n      a0 = LOAD_256_FROM_STRUCT(s + NSW * 0);\n      b0 = LOAD_256_FROM_STRUCT(s + NSW * 1);\n      \n      ROUNDS_LOOP (EE1)\n      \n      D_XOR_256(a0, c0);\n      D_XOR_256(b0, d0);\n      \n      D_XOR_256(a0, LOAD_256_FROM_STRUCT(s + NSW * 0));\n      D_XOR_256(b0, LOAD_256_FROM_STRUCT(s + NSW * 1));\n      \n      STORE_256_TO_STRUCT(s + NSW * 0, a0);\n      STORE_256_TO_STRUCT(s + NSW * 1, b0);\n      \n      data += Z7_BLAKE2S_BLOCK_SIZE * 2;\n      pos  += Z7_BLAKE2S_BLOCK_SIZE * 2;\n      pos &= SUPER_BLOCK_MASK;\n    }\n    while (data < end);\n    DIAG_PERM8(s_items)\n    if (data != end)\n      return;\n  }\n  {\n    UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n    Z7_BLAKE2S_CompressSingleBlock(s, data);\n  }\n}\n\n#endif // Z7_BLAKE2S_USE_AVX2_WAY2\n\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY4\n\n#define AXR2_X(sigma_index, shift1, shift2) \\\n    AXR2_LOAD_INDEXES_AVX(sigma_index) \\\n    D_ADD_256( a0, SET_ROW_FROM_SIGMA_AVX(data)); \\\n    D_ADD_256( a1, SET_ROW_FROM_SIGMA_AVX((data) + Z7_BLAKE2S_BLOCK_SIZE * 2)); \\\n    AXR256(a0, b0, d0, shift1) \\\n    AXR256(a1, b1, d1, shift1) \\\n    AXR256(c0, d0, b0, shift2) \\\n    AXR256(c1, d1, b1, shift2) \\\n\n#define AXR4_X(sigma_index) \\\n    { AXR2_X(sigma_index, 16, 12) } \\\n    { AXR2_X(sigma_index + SIGMA_INTERLEAVE, 8, 7) }\n\n#define EE2(r) \\\n    { GET_SIGMA(r) \\\n      AXR4_X(0) \\\n        ROTATE_WORDS_TO_RIGHT_256(b0, 1) \\\n        ROTATE_WORDS_TO_RIGHT_256(b1, 1) \\\n        ROTATE_WORDS_TO_RIGHT_256(c0, 2) \\\n        ROTATE_WORDS_TO_RIGHT_256(c1, 2) \\\n        ROTATE_WORDS_TO_RIGHT_256(d0, 3) \\\n        ROTATE_WORDS_TO_RIGHT_256(d1, 3) \\\n      AXR4_X(SIGMA_HALF_ROW_SIZE) \\\n        ROTATE_WORDS_TO_RIGHT_256(b0, 3) \\\n        ROTATE_WORDS_TO_RIGHT_256(b1, 3) \\\n        ROTATE_WORDS_TO_RIGHT_256(c0, 2) \\\n        ROTATE_WORDS_TO_RIGHT_256(c1, 2) \\\n        ROTATE_WORDS_TO_RIGHT_256(d0, 1) \\\n        ROTATE_WORDS_TO_RIGHT_256(d1, 1) \\\n    }\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_AVX2\n       BLAKE2S_ATTRIB_AVX2\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Compress2_AVX2_Way4(UInt32 *s_items, const Byte *data, const Byte *end)\n{\n  size_t pos = 0;\n\n  if ((size_t)(end - data) >= Z7_BLAKE2S_BLOCK_SIZE * 4)\n  {\n#ifndef Z7_MM256_ROR_EPI32_IS_SUPPORTED\n    const __m256i  r8 = k_r8_256;\n    const __m256i r16 = k_r16_256;\n#endif\n    end -= Z7_BLAKE2S_BLOCK_SIZE * 3;\n    DIAG_PERM8(s_items)\n    do\n    {\n      UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n      __m256i a0, b0, c0, d0;\n      __m256i a1, b1, c1, d1;\n      {\n        const __m128i inc = k_inc;\n        __m128i d0_128 = LOAD_128_FROM_STRUCT (STATE_T(s));\n        __m128i d1_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW));\n        __m128i d2_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW * 2));\n        __m128i d3_128 = LOAD_128_FROM_STRUCT (STATE_T(s + NSW * 3));\n        D_ADD_EPI64_128(d0_128, inc);\n        D_ADD_EPI64_128(d1_128, inc);\n        D_ADD_EPI64_128(d2_128, inc);\n        D_ADD_EPI64_128(d3_128, inc);\n        STORE_128_TO_STRUCT (STATE_T(s          ), d0_128);\n        STORE_128_TO_STRUCT (STATE_T(s + NSW * 1), d1_128);\n        STORE_128_TO_STRUCT (STATE_T(s + NSW * 2), d2_128);\n        STORE_128_TO_STRUCT (STATE_T(s + NSW * 3), d3_128);\n        d0 = MY_mm256_set_m128i(d1_128, d0_128);\n        d1 = MY_mm256_set_m128i(d3_128, d2_128);\n        D_XOR_256(d0, k_iv4_256);\n        D_XOR_256(d1, k_iv4_256);\n      }\n      c1 = c0 = SET_FROM_128(k_iv0_128);\n      a0 = LOAD_256_FROM_STRUCT(s + NSW * 0);\n      b0 = LOAD_256_FROM_STRUCT(s + NSW * 1);\n      a1 = LOAD_256_FROM_STRUCT(s + NSW * 2);\n      b1 = LOAD_256_FROM_STRUCT(s + NSW * 3);\n      \n      ROUNDS_LOOP (EE2)\n\n      D_XOR_256(a0, c0);\n      D_XOR_256(b0, d0);\n      D_XOR_256(a1, c1);\n      D_XOR_256(b1, d1);\n      \n      D_XOR_256(a0, LOAD_256_FROM_STRUCT(s + NSW * 0));\n      D_XOR_256(b0, LOAD_256_FROM_STRUCT(s + NSW * 1));\n      D_XOR_256(a1, LOAD_256_FROM_STRUCT(s + NSW * 2));\n      D_XOR_256(b1, LOAD_256_FROM_STRUCT(s + NSW * 3));\n      \n      STORE_256_TO_STRUCT(s + NSW * 0, a0);\n      STORE_256_TO_STRUCT(s + NSW * 1, b0);\n      STORE_256_TO_STRUCT(s + NSW * 2, a1);\n      STORE_256_TO_STRUCT(s + NSW * 3, b1);\n      \n      data += Z7_BLAKE2S_BLOCK_SIZE * 4;\n      pos  += Z7_BLAKE2S_BLOCK_SIZE * 4;\n      pos &= SUPER_BLOCK_MASK;\n    }\n    while (data < end);\n    DIAG_PERM8(s_items)\n    end += Z7_BLAKE2S_BLOCK_SIZE * 3;\n  }\n  if (data == end)\n    return;\n  // Z7_BLAKE2S_Compress2_V128(s_items, data, end, pos);\n  do\n  {\n    UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n    Z7_BLAKE2S_CompressSingleBlock(s, data);\n    data += Z7_BLAKE2S_BLOCK_SIZE;\n    pos  += Z7_BLAKE2S_BLOCK_SIZE;\n    pos &= SUPER_BLOCK_MASK;\n  }\n  while (data != end);\n}\n\n#endif // Z7_BLAKE2S_USE_AVX2_WAY4\n#endif // Z7_BLAKE2S_USE_AVX2_WAY_SLOW\n\n\n// ---------------------------------------------------------\n\n#ifdef Z7_BLAKE2S_USE_AVX2_FAST\n\n#define OP256_L(a, i)   D_ADD_256 (V(a, 0), \\\n    LOAD_256((const Byte *)(w) + GET_SIGMA_VAL_256(2*(a)+(i))));\n\n#define OP256_0(a)   OP256_L(a, 0)\n#define OP256_7(a)   OP256_L(a, 1)\n\n#define OP256_1(a)   D_ADD_256 (V(a, 0), V(a, 1));\n#define OP256_2(a)   D_XOR_256 (V(a, 3), V(a, 0));\n#define OP256_4(a)   D_ADD_256 (V(a, 2), V(a, 3));\n#define OP256_5(a)   D_XOR_256 (V(a, 1), V(a, 2));\n\n#define OP256_3(a)   D_ROT_256_16 (V(a, 3));\n#define OP256_6(a)   D_ROT_256_12 (V(a, 1));\n#define OP256_8(a)   D_ROT_256_8  (V(a, 3));\n#define OP256_9(a)   D_ROT_256_7  (V(a, 1));\n\n\n#if 0 || 1 && defined(MY_CPU_X86)\n\n#define V8_G(a) \\\n  OP256_0 (a) \\\n  OP256_1 (a) \\\n  OP256_2 (a) \\\n  OP256_3 (a) \\\n  OP256_4 (a) \\\n  OP256_5 (a) \\\n  OP256_6 (a) \\\n  OP256_7 (a) \\\n  OP256_1 (a) \\\n  OP256_2 (a) \\\n  OP256_8 (a) \\\n  OP256_4 (a) \\\n  OP256_5 (a) \\\n  OP256_9 (a) \\\n\n#define V8R { \\\n  V8_G (0); \\\n  V8_G (1); \\\n  V8_G (2); \\\n  V8_G (3); \\\n  V8_G (4); \\\n  V8_G (5); \\\n  V8_G (6); \\\n  V8_G (7); \\\n}\n\n#else\n\n#define OP256_INTER_4(op, a,b,c,d) \\\n  op (a) \\\n  op (b) \\\n  op (c) \\\n  op (d) \\\n\n#define V8_G(a,b,c,d) \\\n  OP256_INTER_4 (OP256_0, a,b,c,d) \\\n  OP256_INTER_4 (OP256_1, a,b,c,d) \\\n  OP256_INTER_4 (OP256_2, a,b,c,d) \\\n  OP256_INTER_4 (OP256_3, a,b,c,d) \\\n  OP256_INTER_4 (OP256_4, a,b,c,d) \\\n  OP256_INTER_4 (OP256_5, a,b,c,d) \\\n  OP256_INTER_4 (OP256_6, a,b,c,d) \\\n  OP256_INTER_4 (OP256_7, a,b,c,d) \\\n  OP256_INTER_4 (OP256_1, a,b,c,d) \\\n  OP256_INTER_4 (OP256_2, a,b,c,d) \\\n  OP256_INTER_4 (OP256_8, a,b,c,d) \\\n  OP256_INTER_4 (OP256_4, a,b,c,d) \\\n  OP256_INTER_4 (OP256_5, a,b,c,d) \\\n  OP256_INTER_4 (OP256_9, a,b,c,d) \\\n\n#define V8R { \\\n  V8_G (0, 1, 2, 3) \\\n  V8_G (4, 5, 6, 7) \\\n}\n#endif\n\n#define V8_ROUND(r)  { GET_SIGMA_PTR_256(r); V8R }\n\n\n// for debug:\n// #define Z7_BLAKE2S_PERMUTE_WITH_GATHER\n#if defined(Z7_BLAKE2S_PERMUTE_WITH_GATHER)\n// gather instruction is slow.\n#define V8_LOAD_MSG(w, m) \\\n{ \\\n  unsigned i; \\\n  for (i = 0; i < 16; ++i) { \\\n    w[i] = _mm256_i32gather_epi32( \\\n      (const void *)((m) + i * sizeof(UInt32)),\\\n      _mm256_set_epi32(0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00), \\\n      sizeof(UInt32)); \\\n  } \\\n}\n#else // !Z7_BLAKE2S_PERMUTE_WITH_GATHER\n\n#define V8_LOAD_MSG_2(w, a0, a1) \\\n{ \\\n  (w)[0] = _mm256_permute2x128_si256(a0, a1, 0x20);  \\\n  (w)[4] = _mm256_permute2x128_si256(a0, a1, 0x31);  \\\n}\n\n#define V8_LOAD_MSG_4(w, z0, z1, z2, z3) \\\n{ \\\n  __m256i s0, s1, s2, s3;  \\\n  s0 = _mm256_unpacklo_epi64(z0, z1);  \\\n  s1 = _mm256_unpackhi_epi64(z0, z1);  \\\n  s2 = _mm256_unpacklo_epi64(z2, z3);  \\\n  s3 = _mm256_unpackhi_epi64(z2, z3);  \\\n  V8_LOAD_MSG_2((w) + 0, s0, s2)   \\\n  V8_LOAD_MSG_2((w) + 1, s1, s3)   \\\n}\n\n#define V8_LOAD_MSG_0(t0, t1, m) \\\n{ \\\n  __m256i m0, m1;  \\\n  m0 = LOADU_256(m);  \\\n  m1 = LOADU_256((m) + 2 * 32);  \\\n  t0 = _mm256_unpacklo_epi32(m0, m1);  \\\n  t1 = _mm256_unpackhi_epi32(m0, m1);  \\\n}\n\n#define V8_LOAD_MSG_8(w, m) \\\n{ \\\n  __m256i t0, t1, t2, t3, t4, t5, t6, t7;  \\\n  V8_LOAD_MSG_0(t0, t4, (m) + 0 * 4 * 32)  \\\n  V8_LOAD_MSG_0(t1, t5, (m) + 1 * 4 * 32)  \\\n  V8_LOAD_MSG_0(t2, t6, (m) + 2 * 4 * 32)  \\\n  V8_LOAD_MSG_0(t3, t7, (m) + 3 * 4 * 32)  \\\n  V8_LOAD_MSG_4((w)    , t0, t1, t2, t3)   \\\n  V8_LOAD_MSG_4((w) + 2, t4, t5, t6, t7)   \\\n}\n\n#define V8_LOAD_MSG(w, m) \\\n{ \\\n  V8_LOAD_MSG_8(w, m)  \\\n  V8_LOAD_MSG_8((w) + 8, (m) + 32)  \\\n}\n\n#endif // !Z7_BLAKE2S_PERMUTE_WITH_GATHER\n\n\n#define V8_PERM_PAIR_STORE(u, a0, a2) \\\n{ \\\n  STORE_256_TO_STRUCT((u),     _mm256_permute2x128_si256(a0, a2, 0x20));  \\\n  STORE_256_TO_STRUCT((u) + 8, _mm256_permute2x128_si256(a0, a2, 0x31));  \\\n}\n\n#define V8_UNPACK_STORE_4(u, z0, z1, z2, z3) \\\n{ \\\n  __m256i s0, s1, s2, s3;  \\\n  s0 = _mm256_unpacklo_epi64(z0, z1);  \\\n  s1 = _mm256_unpackhi_epi64(z0, z1);  \\\n  s2 = _mm256_unpacklo_epi64(z2, z3);  \\\n  s3 = _mm256_unpackhi_epi64(z2, z3);  \\\n  V8_PERM_PAIR_STORE(u + 0, s0, s2)  \\\n  V8_PERM_PAIR_STORE(u + 2, s1, s3)  \\\n}\n\n#define V8_UNPACK_STORE_0(src32, d0, d1) \\\n{ \\\n  const __m256i v0 = LOAD_256_FROM_STRUCT ((src32)    );  \\\n  const __m256i v1 = LOAD_256_FROM_STRUCT ((src32) + 8);  \\\n  d0 = _mm256_unpacklo_epi32(v0, v1);  \\\n  d1 = _mm256_unpackhi_epi32(v0, v1);  \\\n}\n\n#define V8_UNPACK_STATE(dest32, src32) \\\n{ \\\n  __m256i t0, t1, t2, t3, t4, t5, t6, t7;  \\\n  V8_UNPACK_STORE_0 ((src32) + 16 * 0, t0, t4)  \\\n  V8_UNPACK_STORE_0 ((src32) + 16 * 1, t1, t5)  \\\n  V8_UNPACK_STORE_0 ((src32) + 16 * 2, t2, t6)  \\\n  V8_UNPACK_STORE_0 ((src32) + 16 * 3, t3, t7)  \\\n  V8_UNPACK_STORE_4 ((__m256i *)(void *)(dest32)    , t0, t1, t2, t3)  \\\n  V8_UNPACK_STORE_4 ((__m256i *)(void *)(dest32) + 4, t4, t5, t6, t7)  \\\n}\n\n\n\n#define V8_LOAD_STATE_256_FROM_STRUCT(i) \\\n      v[i] = LOAD_256_FROM_STRUCT(s_items + (i) * 8);\n\n#if 0 || 0 && defined(MY_CPU_X86)\n#define Z7_BLAKE2S_AVX2_FAST_USE_STRUCT\n#endif\n\n#ifdef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT\n// this branch doesn't use (iv) array\n// so register pressure can be lower.\n// it can be faster sometimes\n#define V8_LOAD_STATE_256(i)  V8_LOAD_STATE_256_FROM_STRUCT(i)\n#define V8_UPDATE_STATE_256(i) \\\n{ \\\n    STORE_256_TO_STRUCT(s_items + (i) * 8, XOR_256( \\\n    XOR_256(v[i], v[(i) + 8]), \\\n    LOAD_256_FROM_STRUCT(s_items + (i) * 8))); \\\n}\n#else\n// it uses more variables (iv) registers\n// it's better for gcc\n// maybe that branch is better, if register pressure will be lower (avx512)\n#define V8_LOAD_STATE_256(i)   { iv[i] = v[i]; }\n#define V8_UPDATE_STATE_256(i) { v[i] = XOR_256(XOR_256(v[i], v[i + 8]), iv[i]); }\n#define V8_STORE_STATE_256(i)  { STORE_256_TO_STRUCT(s_items + (i) * 8, v[i]); }\n#endif\n\n\n#if 0\n  // use loading constants from memory\n  #define KK8(n)  KIV(n), KIV(n), KIV(n), KIV(n), KIV(n), KIV(n), KIV(n), KIV(n)\nMY_ALIGN(64)\nstatic const UInt32 k_Blake2s_IV_WAY8[]=\n{\n  KK8(0), KK8(1), KK8(2), KK8(3), KK8(4), KK8(5), KK8(6), KK8(7)\n};\n  #define GET_256_IV_WAY8(i)  LOAD_256(k_Blake2s_IV_WAY8 + 8 * (i))\n#else\n  // use constant generation:\n  #define GET_256_IV_WAY8(i)  _mm256_set1_epi32((Int32)KIV(i))\n#endif\n\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_AVX2\n       BLAKE2S_ATTRIB_AVX2\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Compress2_AVX2_Fast(UInt32 *s_items, const Byte *data, const Byte *end)\n{\n#ifndef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT\n  __m256i v[16];\n#endif\n\n  // PrintStates2(s_items, 8, 16);\n\n#ifndef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT\n  REP8_MACRO (V8_LOAD_STATE_256_FROM_STRUCT)\n#endif\n\n  do\n  {\n    __m256i w[16];\n#ifdef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT\n    __m256i v[16];\n#else\n    __m256i iv[8];\n#endif\n    V8_LOAD_MSG(w, data)\n    {\n      // we use load/store ctr inside loop to reduce register pressure:\n#if 1 || 1 && defined(MY_CPU_X86)\n      const __m256i ctr = _mm256_add_epi64(\n          LOAD_256_FROM_STRUCT(s_items + 64),\n          _mm256_set_epi32(\n              0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE,\n              0, 0, 0, Z7_BLAKE2S_BLOCK_SIZE));\n      STORE_256_TO_STRUCT(s_items + 64, ctr);\n#else\n      const UInt64 ctr64 = *(const UInt64 *)(const void *)(s_items + 64)\n          + Z7_BLAKE2S_BLOCK_SIZE;\n      const __m256i ctr = _mm256_set_epi64x(0, (Int64)ctr64, 0, (Int64)ctr64);\n      *(UInt64 *)(void *)(s_items + 64) = ctr64;\n#endif\n      v[12] = XOR_256 (GET_256_IV_WAY8(4), _mm256_shuffle_epi32(ctr, _MM_SHUFFLE(0, 0, 0, 0)));\n      v[13] = XOR_256 (GET_256_IV_WAY8(5), _mm256_shuffle_epi32(ctr, _MM_SHUFFLE(1, 1, 1, 1)));\n    }\n    v[ 8] = GET_256_IV_WAY8(0);\n    v[ 9] = GET_256_IV_WAY8(1);\n    v[10] = GET_256_IV_WAY8(2);\n    v[11] = GET_256_IV_WAY8(3);\n    v[14] = GET_256_IV_WAY8(6);\n    v[15] = GET_256_IV_WAY8(7);\n\n    REP8_MACRO (V8_LOAD_STATE_256)\n    ROUNDS_LOOP (V8_ROUND)\n    REP8_MACRO (V8_UPDATE_STATE_256)\n    data += SUPER_BLOCK_SIZE;\n  }\n  while (data != end);\n\n#ifndef Z7_BLAKE2S_AVX2_FAST_USE_STRUCT\n  REP8_MACRO (V8_STORE_STATE_256)\n#endif\n}\n\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_AVX2\n       BLAKE2S_ATTRIB_AVX2\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_Final_AVX2_Fast(UInt32 *states)\n{\n  const __m128i ctr = LOAD_128_FROM_STRUCT(states + 64);\n  // PrintStates2(states, 8, 16);\n  V8_UNPACK_STATE(states, states)\n  // PrintStates2(states, 8, 16);\n  {\n    unsigned k;\n    for (k = 0; k < 8; k++)\n    {\n      UInt32 *s = states + (size_t)k * 16;\n      STORE_128_TO_STRUCT (STATE_T(s), ctr);\n    }\n  }\n  // PrintStates2(states, 8, 16);\n  // printf(\"\\nafter V8_UNPACK_STATE \\n\");\n}\n\n#endif // Z7_BLAKE2S_USE_AVX2_FAST\n#endif // avx2\n#endif // vector\n\n\n/*\n#define Blake2s_Increment_Counter(s, inc) \\\n  { STATE_T(s)[0] += (inc);  STATE_T(s)[1] += (STATE_T(s)[0] < (inc)); }\n#define Blake2s_Increment_Counter_Small(s, inc) \\\n  { STATE_T(s)[0] += (inc); }\n*/\n\n#define Blake2s_Set_LastBlock(s) \\\n  { STATE_F(s)[0] = BLAKE2S_FINAL_FLAG; /* STATE_F(s)[1] = p->u.header.lastNode_f1; */ }\n\n\n#if 0 || 1 && defined(Z7_MSC_VER_ORIGINAL) && Z7_MSC_VER_ORIGINAL >= 1600\n  // good for vs2022\n  #define LOOP_8(mac) { unsigned kkk; for (kkk = 0; kkk < 8; kkk++) mac(kkk) }\n#else\n   // good for Z7_BLAKE2S_UNROLL for GCC9 (arm*/x86*) and MSC_VER_1400-x64.\n  #define LOOP_8(mac) { REP8_MACRO(mac) }\n#endif\n\n\nstatic\nZ7_FORCE_INLINE\n// Z7_NO_INLINE\nvoid\nZ7_FASTCALL\nBlake2s_Compress(UInt32 *s, const Byte *input)\n{\n  UInt32 m[16];\n  UInt32 v[16];\n  {\n    unsigned i;\n    for (i = 0; i < 16; i++)\n      m[i] = GetUi32(input + i * 4);\n  }\n\n#define INIT_v_FROM_s(i)  v[i] = s[i];\n  \n  LOOP_8(INIT_v_FROM_s)\n \n  // Blake2s_Increment_Counter(s, Z7_BLAKE2S_BLOCK_SIZE)\n  {\n    const UInt32 t0 = STATE_T(s)[0] + Z7_BLAKE2S_BLOCK_SIZE;\n    const UInt32 t1 = STATE_T(s)[1] + (t0 < Z7_BLAKE2S_BLOCK_SIZE);\n    STATE_T(s)[0] = t0;\n    STATE_T(s)[1] = t1;\n    v[12] = t0 ^ KIV(4);\n    v[13] = t1 ^ KIV(5);\n  }\n  // v[12] = STATE_T(s)[0] ^ KIV(4);\n  // v[13] = STATE_T(s)[1] ^ KIV(5);\n  v[14] = STATE_F(s)[0] ^ KIV(6);\n  v[15] = STATE_F(s)[1] ^ KIV(7);\n\n  v[ 8] = KIV(0);\n  v[ 9] = KIV(1);\n  v[10] = KIV(2);\n  v[11] = KIV(3);\n  // PrintStates2((const UInt32 *)v, 1, 16);\n\n  #define ADD_SIGMA(a, index)  V(a, 0) += *(const UInt32 *)GET_SIGMA_PTR(m, sigma[index]);\n  #define ADD32M(dest, src, a)    V(a, dest) += V(a, src);\n  #define XOR32M(dest, src, a)    V(a, dest) ^= V(a, src);\n  #define RTR32M(dest, shift, a)  V(a, dest) = rotrFixed(V(a, dest), shift);\n\n// big interleaving can provides big performance gain, if scheduler queues are small.\n#if 0 || 1 && defined(MY_CPU_X86)\n  // interleave-1: for small register number (x86-32bit)\n  #define G2(index, a, x, y) \\\n    ADD_SIGMA (a, (index) + 2 * 0) \\\n    ADD32M (0, 1, a) \\\n    XOR32M (3, 0, a) \\\n    RTR32M (3, x, a) \\\n    ADD32M (2, 3, a) \\\n    XOR32M (1, 2, a) \\\n    RTR32M (1, y, a) \\\n\n  #define G(a) \\\n    G2(a * 2    , a, 16, 12) \\\n    G2(a * 2 + 1, a,  8,  7) \\\n\n  #define R2 \\\n    G(0) \\\n    G(1) \\\n    G(2) \\\n    G(3) \\\n    G(4) \\\n    G(5) \\\n    G(6) \\\n    G(7) \\\n\n#elif 0 || 1 && defined(MY_CPU_X86_OR_AMD64)\n  // interleave-2: is good if the number of registers is not big (x86-64).\n\n  #define REP2(mac, dest, src, a, b) \\\n      mac(dest, src, a) \\\n      mac(dest, src, b)\n\n  #define G2(index, a, b, x, y) \\\n    ADD_SIGMA (a, (index) + 2 * 0) \\\n    ADD_SIGMA (b, (index) + 2 * 1) \\\n    REP2 (ADD32M, 0, 1, a, b) \\\n    REP2 (XOR32M, 3, 0, a, b) \\\n    REP2 (RTR32M, 3, x, a, b) \\\n    REP2 (ADD32M, 2, 3, a, b) \\\n    REP2 (XOR32M, 1, 2, a, b) \\\n    REP2 (RTR32M, 1, y, a, b) \\\n\n  #define G(a, b) \\\n    G2(a * 2    , a, b, 16, 12) \\\n    G2(a * 2 + 1, a, b,  8,  7) \\\n\n  #define R2 \\\n    G(0, 1) \\\n    G(2, 3) \\\n    G(4, 5) \\\n    G(6, 7) \\\n\n#else\n  // interleave-4:\n  // it has big register pressure for x86/x64.\n  // and MSVC compilers for x86/x64 are slow for this branch.\n  // but if we have big number of registers, this branch can be faster.\n\n  #define REP4(mac, dest, src, a, b, c, d) \\\n      mac(dest, src, a) \\\n      mac(dest, src, b) \\\n      mac(dest, src, c) \\\n      mac(dest, src, d)\n\n  #define G2(index, a, b, c, d, x, y) \\\n    ADD_SIGMA (a, (index) + 2 * 0) \\\n    ADD_SIGMA (b, (index) + 2 * 1) \\\n    ADD_SIGMA (c, (index) + 2 * 2) \\\n    ADD_SIGMA (d, (index) + 2 * 3) \\\n    REP4 (ADD32M, 0, 1, a, b, c, d) \\\n    REP4 (XOR32M, 3, 0, a, b, c, d) \\\n    REP4 (RTR32M, 3, x, a, b, c, d) \\\n    REP4 (ADD32M, 2, 3, a, b, c, d) \\\n    REP4 (XOR32M, 1, 2, a, b, c, d) \\\n    REP4 (RTR32M, 1, y, a, b, c, d) \\\n\n  #define G(a, b, c, d) \\\n    G2(a * 2    , a, b, c, d, 16, 12) \\\n    G2(a * 2 + 1, a, b, c, d,  8,  7) \\\n\n  #define R2 \\\n    G(0, 1, 2, 3) \\\n    G(4, 5, 6, 7) \\\n\n#endif\n\n  #define R(r)  { const Byte *sigma = k_Blake2s_Sigma_4[r];  R2 }\n\n  // Z7_BLAKE2S_UNROLL gives 5-6 KB larger code, but faster:\n  //   20-40% faster for (x86/x64) VC2010+/GCC/CLANG.\n  //   30-60% faster for (arm64-arm32) GCC.\n  //    5-11% faster for (arm64) CLANG-MAC.\n  // so Z7_BLAKE2S_UNROLL is good optimization, if there is no vector branch.\n  // But if there is vectors branch (for x86*), this scalar code will be unused mostly.\n  // So we want smaller code (without unrolling) in that case (x86*).\n#if 0 || 1 && !defined(Z7_BLAKE2S_USE_VECTORS)\n  #define Z7_BLAKE2S_UNROLL\n#endif\n\n#ifdef Z7_BLAKE2S_UNROLL\n    ROUNDS_LOOP_UNROLLED (R)\n#else\n    ROUNDS_LOOP (R)\n#endif\n  \n  #undef G\n  #undef G2\n  #undef R\n  #undef R2\n\n  // printf(\"\\n v after: \\n\");\n  // PrintStates2((const UInt32 *)v, 1, 16);\n#define XOR_s_PAIR_v(i)  s[i] ^= v[i] ^ v[i + 8];\n\n  LOOP_8(XOR_s_PAIR_v)\n  // printf(\"\\n s after:\\n\");\n  // PrintStates2((const UInt32 *)s, 1, 16);\n}\n\n\nstatic\nZ7_NO_INLINE\nvoid\nZ7_FASTCALL\nBlake2sp_Compress2(UInt32 *s_items, const Byte *data, const Byte *end)\n{\n  size_t pos = 0;\n  // PrintStates2(s_items, 8, 16);\n  do\n  {\n    UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(s_items, pos);\n    Blake2s_Compress(s, data);\n    data += Z7_BLAKE2S_BLOCK_SIZE;\n    pos  += Z7_BLAKE2S_BLOCK_SIZE;\n    pos &= SUPER_BLOCK_MASK;\n  }\n  while (data != end);\n}\n\n\n#ifdef Z7_BLAKE2S_USE_VECTORS\n\nstatic Z7_BLAKE2SP_FUNC_COMPRESS g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast   = Blake2sp_Compress2;\nstatic Z7_BLAKE2SP_FUNC_COMPRESS g_Z7_BLAKE2SP_FUNC_COMPRESS_Single = Blake2sp_Compress2;\nstatic Z7_BLAKE2SP_FUNC_INIT     g_Z7_BLAKE2SP_FUNC_INIT_Init;\nstatic Z7_BLAKE2SP_FUNC_INIT     g_Z7_BLAKE2SP_FUNC_INIT_Final;\nstatic unsigned g_z7_Blake2sp_SupportedFlags;\n\n  #define Z7_BLAKE2SP_Compress_Fast(p)   (p)->u.header.func_Compress_Fast\n  #define Z7_BLAKE2SP_Compress_Single(p) (p)->u.header.func_Compress_Single\n#else\n  #define Z7_BLAKE2SP_Compress_Fast(p)   Blake2sp_Compress2\n  #define Z7_BLAKE2SP_Compress_Single(p) Blake2sp_Compress2\n#endif // Z7_BLAKE2S_USE_VECTORS\n\n\n#if 1 && defined(MY_CPU_LE)\n    #define GET_DIGEST(_s, _digest) \\\n      { memcpy(_digest, _s, Z7_BLAKE2S_DIGEST_SIZE); }\n#else\n    #define GET_DIGEST(_s, _digest) \\\n    { unsigned _i; for (_i = 0; _i < 8; _i++) \\\n        { SetUi32((_digest) + 4 * _i, (_s)[_i]) } \\\n    }\n#endif\n\n\n/* ---------- BLAKE2s ---------- */\n/*\n// we need to xor CBlake2s::h[i] with input parameter block after Blake2s_Init0()\ntypedef struct\n{\n  Byte  digest_length;\n  Byte  key_length;\n  Byte  fanout;               // = 1 : in sequential mode\n  Byte  depth;                // = 1 : in sequential mode\n  UInt32 leaf_length;\n  Byte  node_offset[6];       // 0 for the first, leftmost, leaf, or in sequential mode\n  Byte  node_depth;           // 0 for the leaves, or in sequential mode\n  Byte  inner_length;         // [0, 32], 0 in sequential mode\n  Byte  salt[BLAKE2S_SALTBYTES];\n  Byte  personal[BLAKE2S_PERSONALBYTES];\n} CBlake2sParam;\n*/\n\n#define k_Blake2sp_IV_0  \\\n    (KIV(0) ^ (Z7_BLAKE2S_DIGEST_SIZE | ((UInt32)Z7_BLAKE2SP_PARALLEL_DEGREE << 16) | ((UInt32)2 << 24)))\n#define k_Blake2sp_IV_3_FROM_NODE_DEPTH(node_depth)  \\\n    (KIV(3) ^ ((UInt32)(node_depth) << 16) ^ ((UInt32)Z7_BLAKE2S_DIGEST_SIZE << 24))\n\nZ7_FORCE_INLINE\nstatic void Blake2sp_Init_Spec(UInt32 *s, unsigned node_offset, unsigned node_depth)\n{\n  s[0] = k_Blake2sp_IV_0;\n  s[1] = KIV(1);\n  s[2] = KIV(2) ^ (UInt32)node_offset;\n  s[3] = k_Blake2sp_IV_3_FROM_NODE_DEPTH(node_depth);\n  s[4] = KIV(4);\n  s[5] = KIV(5);\n  s[6] = KIV(6);\n  s[7] = KIV(7);\n\n  STATE_T(s)[0] = 0;\n  STATE_T(s)[1] = 0;\n  STATE_F(s)[0] = 0;\n  STATE_F(s)[1] = 0;\n}\n\n\n#ifdef Z7_BLAKE2S_USE_V128_FAST\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_128BIT\n       BLAKE2S_ATTRIB_128BIT\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_InitState_V128_Fast(UInt32 *states)\n{\n#define STORE_128_PAIR_INIT_STATES_2(i, t0, t1) \\\n  { STORE_128_TO_STRUCT(states +  0 + 4 * (i), (t0)); \\\n    STORE_128_TO_STRUCT(states + 32 + 4 * (i), (t1)); \\\n  }\n#define STORE_128_PAIR_INIT_STATES_1(i, mac) \\\n  { const __m128i t = mac; \\\n    STORE_128_PAIR_INIT_STATES_2(i, t, t) \\\n  }\n#define STORE_128_PAIR_INIT_STATES_IV(i) \\\n    STORE_128_PAIR_INIT_STATES_1(i, GET_128_IV_WAY4(i))\n\n  STORE_128_PAIR_INIT_STATES_1  (0, _mm_set1_epi32((Int32)k_Blake2sp_IV_0))\n  STORE_128_PAIR_INIT_STATES_IV (1)\n  {\n    const __m128i t = GET_128_IV_WAY4(2);\n    STORE_128_PAIR_INIT_STATES_2 (2,\n        XOR_128(t, _mm_set_epi32(3, 2, 1, 0)),\n        XOR_128(t, _mm_set_epi32(7, 6, 5, 4)))\n  }\n  STORE_128_PAIR_INIT_STATES_1  (3, _mm_set1_epi32((Int32)k_Blake2sp_IV_3_FROM_NODE_DEPTH(0)))\n  STORE_128_PAIR_INIT_STATES_IV (4)\n  STORE_128_PAIR_INIT_STATES_IV (5)\n  STORE_128_PAIR_INIT_STATES_IV (6)\n  STORE_128_PAIR_INIT_STATES_IV (7)\n  STORE_128_PAIR_INIT_STATES_1  (16, _mm_set_epi32(0, 0, 0, 0))\n  // printf(\"\\n== exit Blake2sp_InitState_V128_Fast ctr=%d\\n\", states[64]);\n}\n\n#endif // Z7_BLAKE2S_USE_V128_FAST\n\n\n#ifdef Z7_BLAKE2S_USE_AVX2_FAST\n\nstatic\nZ7_NO_INLINE\n#ifdef BLAKE2S_ATTRIB_AVX2\n       BLAKE2S_ATTRIB_AVX2\n#endif\nvoid\nZ7_FASTCALL\nBlake2sp_InitState_AVX2_Fast(UInt32 *states)\n{\n#define STORE_256_INIT_STATES(i, t) \\\n    STORE_256_TO_STRUCT(states + 8 * (i), t);\n#define STORE_256_INIT_STATES_IV(i) \\\n    STORE_256_INIT_STATES(i, GET_256_IV_WAY8(i))\n\n  STORE_256_INIT_STATES    (0,  _mm256_set1_epi32((Int32)k_Blake2sp_IV_0))\n  STORE_256_INIT_STATES_IV (1)\n  STORE_256_INIT_STATES    (2, XOR_256( GET_256_IV_WAY8(2),\n                                _mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0)))\n  STORE_256_INIT_STATES    (3,  _mm256_set1_epi32((Int32)k_Blake2sp_IV_3_FROM_NODE_DEPTH(0)))\n  STORE_256_INIT_STATES_IV (4)\n  STORE_256_INIT_STATES_IV (5)\n  STORE_256_INIT_STATES_IV (6)\n  STORE_256_INIT_STATES_IV (7)\n  STORE_256_INIT_STATES    (8, _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, 0))\n  // printf(\"\\n== exit Blake2sp_InitState_AVX2_Fast\\n\");\n}\n\n#endif // Z7_BLAKE2S_USE_AVX2_FAST\n\n\n\nZ7_NO_INLINE\nvoid Blake2sp_InitState(CBlake2sp *p)\n{\n  size_t i;\n  // memset(p->states, 0, sizeof(p->states)); // for debug\n  p->u.header.cycPos = 0;\n#ifdef Z7_BLAKE2SP_USE_FUNCTIONS\n  if (p->u.header.func_Init)\n  {\n    p->u.header.func_Init(p->states);\n    return;\n  }\n#endif\n  for (i = 0; i < Z7_BLAKE2SP_PARALLEL_DEGREE; i++)\n    Blake2sp_Init_Spec(p->states + i * NSW, (unsigned)i, 0);\n}\n\nvoid Blake2sp_Init(CBlake2sp *p)\n{\n#ifdef Z7_BLAKE2SP_USE_FUNCTIONS\n  p->u.header.func_Compress_Fast =\n#ifdef Z7_BLAKE2S_USE_VECTORS\n    g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast;\n#else\n    NULL;\n#endif\n\n  p->u.header.func_Compress_Single =\n#ifdef Z7_BLAKE2S_USE_VECTORS\n    g_Z7_BLAKE2SP_FUNC_COMPRESS_Single;\n#else\n    NULL;\n#endif\n\n  p->u.header.func_Init =\n#ifdef Z7_BLAKE2S_USE_VECTORS\n    g_Z7_BLAKE2SP_FUNC_INIT_Init;\n#else\n    NULL;\n#endif\n\n  p->u.header.func_Final =\n#ifdef Z7_BLAKE2S_USE_VECTORS\n    g_Z7_BLAKE2SP_FUNC_INIT_Final;\n#else\n    NULL;\n#endif\n#endif\n\n  Blake2sp_InitState(p);\n}\n\n\nvoid Blake2sp_Update(CBlake2sp *p, const Byte *data, size_t size)\n{\n  size_t pos;\n  // printf(\"\\nsize = 0x%6x, cycPos = %5u data = %p\\n\", (unsigned)size, (unsigned)p->u.header.cycPos, data);\n  if (size == 0)\n    return;\n  pos = p->u.header.cycPos;\n  // pos <  SUPER_BLOCK_SIZE * 2  : is expected\n  // pos == SUPER_BLOCK_SIZE * 2  : is not expected, but is supported also\n  {\n    const size_t pos2 = pos & SUPER_BLOCK_MASK;\n    if (pos2)\n    {\n      const size_t rem = SUPER_BLOCK_SIZE - pos2;\n      if (rem > size)\n      {\n        p->u.header.cycPos = (unsigned)(pos + size);\n        // cycPos < SUPER_BLOCK_SIZE * 2\n        memcpy((Byte *)(void *)p->buf32 + pos, data, size);\n        /* to simpilify the code here we don't try to process first superblock,\n           if (cycPos > SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE) */\n        return;\n      }\n      // (rem <= size)\n      memcpy((Byte *)(void *)p->buf32 + pos, data, rem);\n      pos += rem;\n      data += rem;\n      size -= rem;\n    }\n  }\n\n  // pos <= SUPER_BLOCK_SIZE * 2\n  // pos  % SUPER_BLOCK_SIZE == 0\n  if (pos)\n  {\n    /* pos == SUPER_BLOCK_SIZE ||\n       pos == SUPER_BLOCK_SIZE * 2 */\n    size_t end = pos;\n    if (size > SUPER_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE\n        || (end -= SUPER_BLOCK_SIZE))\n    {\n      Z7_BLAKE2SP_Compress_Fast(p)(p->states,\n          (const Byte *)(const void *)p->buf32,\n          (const Byte *)(const void *)p->buf32 + end);\n      if (pos -= end)\n        memcpy(p->buf32, (const Byte *)(const void *)p->buf32\n            + SUPER_BLOCK_SIZE, SUPER_BLOCK_SIZE);\n    }\n  }\n\n  // pos == 0 || (pos == SUPER_BLOCK_SIZE && size <= SUPER_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE)\n  if (size > SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE)\n  {\n    // pos == 0\n    const Byte *end;\n    const size_t size2 = (size - (SUPER_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE + 1))\n        & ~(size_t)SUPER_BLOCK_MASK;\n    size -= size2;\n    // size < SUPER_BLOCK_SIZE * 2\n    end = data + size2;\n    Z7_BLAKE2SP_Compress_Fast(p)(p->states, data, end);\n    data = end;\n  }\n  \n  if (size != 0)\n  {\n    memcpy((Byte *)(void *)p->buf32 + pos, data, size);\n    pos += size;\n  }\n  p->u.header.cycPos = (unsigned)pos;\n  // cycPos < SUPER_BLOCK_SIZE * 2\n}\n\n\nvoid Blake2sp_Final(CBlake2sp *p, Byte *digest)\n{\n  // UInt32 * const R_states = p->states;\n  // printf(\"\\nBlake2sp_Final \\n\");\n#ifdef Z7_BLAKE2SP_USE_FUNCTIONS\n  if (p->u.header.func_Final)\n      p->u.header.func_Final(p->states);\n#endif\n  // printf(\"\\n=====\\nBlake2sp_Final \\n\");\n  // PrintStates(p->states, 32);\n\n  // (p->u.header.cycPos == SUPER_BLOCK_SIZE) can be processed in any branch:\n  if (p->u.header.cycPos <= SUPER_BLOCK_SIZE)\n  {\n    unsigned pos;\n    memset((Byte *)(void *)p->buf32 + p->u.header.cycPos,\n        0, SUPER_BLOCK_SIZE - p->u.header.cycPos);\n    STATE_F(&p->states[(Z7_BLAKE2SP_PARALLEL_DEGREE - 1) * NSW])[1] = BLAKE2S_FINAL_FLAG;\n    for (pos = 0; pos < SUPER_BLOCK_SIZE; pos += Z7_BLAKE2S_BLOCK_SIZE)\n    {\n      UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, pos);\n      Blake2s_Set_LastBlock(s)\n      if (pos + Z7_BLAKE2S_BLOCK_SIZE > p->u.header.cycPos)\n      {\n        UInt32 delta = Z7_BLAKE2S_BLOCK_SIZE;\n        if (pos < p->u.header.cycPos)\n          delta -= p->u.header.cycPos & (Z7_BLAKE2S_BLOCK_SIZE - 1);\n        // 0 < delta <= Z7_BLAKE2S_BLOCK_SIZE\n        {\n          const UInt32 v = STATE_T(s)[0];\n          STATE_T(s)[1] -= v < delta; //  (v < delta) is same condition here as (v == 0)\n          STATE_T(s)[0]  = v - delta;\n        }\n      }\n    }\n    // PrintStates(p->states, 16);\n    Z7_BLAKE2SP_Compress_Single(p)(p->states,\n        (Byte *)(void *)p->buf32,\n        (Byte *)(void *)p->buf32 + SUPER_BLOCK_SIZE);\n    // PrintStates(p->states, 16);\n  }\n  else\n  {\n    // (p->u.header.cycPos > SUPER_BLOCK_SIZE)\n    unsigned pos;\n    for (pos = 0; pos < SUPER_BLOCK_SIZE; pos += Z7_BLAKE2S_BLOCK_SIZE)\n    {\n      UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, pos);\n      if (pos + SUPER_BLOCK_SIZE >= p->u.header.cycPos)\n        Blake2s_Set_LastBlock(s)\n    }\n    if (p->u.header.cycPos <= SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE)\n      STATE_F(&p->states[(Z7_BLAKE2SP_PARALLEL_DEGREE - 1) * NSW])[1] = BLAKE2S_FINAL_FLAG;\n\n    Z7_BLAKE2SP_Compress_Single(p)(p->states,\n        (Byte *)(void *)p->buf32,\n        (Byte *)(void *)p->buf32 + SUPER_BLOCK_SIZE);\n\n    // if (p->u.header.cycPos > SUPER_BLOCK_SIZE * 2 - Z7_BLAKE2S_BLOCK_SIZE;\n      STATE_F(&p->states[(Z7_BLAKE2SP_PARALLEL_DEGREE - 1) * NSW])[1] = BLAKE2S_FINAL_FLAG;\n\n    // if (p->u.header.cycPos != SUPER_BLOCK_SIZE)\n    {\n      pos = SUPER_BLOCK_SIZE;\n      for (;;)\n      {\n        UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, pos & SUPER_BLOCK_MASK);\n        Blake2s_Set_LastBlock(s)\n        pos += Z7_BLAKE2S_BLOCK_SIZE;\n        if (pos >= p->u.header.cycPos)\n        {\n          if (pos != p->u.header.cycPos)\n          {\n            const UInt32 delta = pos - p->u.header.cycPos;\n            const UInt32 v = STATE_T(s)[0];\n            STATE_T(s)[1] -= v < delta;\n            STATE_T(s)[0]  = v - delta;\n            memset((Byte *)(void *)p->buf32 + p->u.header.cycPos, 0, delta);\n          }\n          break;\n        }\n      }\n      Z7_BLAKE2SP_Compress_Single(p)(p->states,\n          (Byte *)(void *)p->buf32 + SUPER_BLOCK_SIZE,\n          (Byte *)(void *)p->buf32 + pos);\n    }\n  }\n\n  {\n    size_t pos;\n    for (pos = 0; pos < SUPER_BLOCK_SIZE / 2; pos += Z7_BLAKE2S_BLOCK_SIZE / 2)\n    {\n      const UInt32 * const s = GET_STATE_TABLE_PTR_FROM_BYTE_POS(p->states, (pos * 2));\n      Byte *dest = (Byte *)(void *)p->buf32 + pos;\n      GET_DIGEST(s, dest)\n    }\n  }\n  Blake2sp_Init_Spec(p->states, 0, 1);\n  {\n    size_t pos;\n    for (pos = 0; pos < (Z7_BLAKE2SP_PARALLEL_DEGREE * Z7_BLAKE2S_DIGEST_SIZE)\n        - Z7_BLAKE2S_BLOCK_SIZE; pos += Z7_BLAKE2S_BLOCK_SIZE)\n    {\n      Z7_BLAKE2SP_Compress_Single(p)(p->states,\n          (const Byte *)(const void *)p->buf32 + pos,\n          (const Byte *)(const void *)p->buf32 + pos + Z7_BLAKE2S_BLOCK_SIZE);\n    }\n  }\n  // Blake2s_Final(p->states, 0, digest, p, (Byte *)(void *)p->buf32 + i);\n  Blake2s_Set_LastBlock(p->states)\n  STATE_F(p->states)[1] = BLAKE2S_FINAL_FLAG;\n  {\n    Z7_BLAKE2SP_Compress_Single(p)(p->states,\n        (const Byte *)(const void *)p->buf32 + Z7_BLAKE2SP_PARALLEL_DEGREE / 2 * Z7_BLAKE2S_BLOCK_SIZE - Z7_BLAKE2S_BLOCK_SIZE,\n        (const Byte *)(const void *)p->buf32 + Z7_BLAKE2SP_PARALLEL_DEGREE / 2 * Z7_BLAKE2S_BLOCK_SIZE);\n  }\n  GET_DIGEST(p->states, digest)\n  // printf(\"\\n Blake2sp_Final 555 numDataInBufs = %5u\\n\", (unsigned)p->u.header.numDataInBufs);\n}\n\n\nBoolInt Blake2sp_SetFunction(CBlake2sp *p, unsigned algo)\n{\n  // printf(\"\\n========== setfunction = %d ======== \\n\",  algo);\n#ifdef Z7_BLAKE2SP_USE_FUNCTIONS\n  Z7_BLAKE2SP_FUNC_COMPRESS func = NULL;\n  Z7_BLAKE2SP_FUNC_COMPRESS func_Single = NULL;\n  Z7_BLAKE2SP_FUNC_INIT     func_Final = NULL;\n  Z7_BLAKE2SP_FUNC_INIT     func_Init = NULL;\n#else\n  UNUSED_VAR(p)\n#endif\n  \n#ifdef Z7_BLAKE2S_USE_VECTORS\n\n  func = func_Single = Blake2sp_Compress2;\n\n  if (algo != Z7_BLAKE2SP_ALGO_SCALAR)\n  {\n    // printf(\"\\n========== setfunction NON-SCALER ======== \\n\");\n    if (algo == Z7_BLAKE2SP_ALGO_DEFAULT)\n    {\n      func        = g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast;\n      func_Single = g_Z7_BLAKE2SP_FUNC_COMPRESS_Single;\n      func_Init   = g_Z7_BLAKE2SP_FUNC_INIT_Init;\n      func_Final  = g_Z7_BLAKE2SP_FUNC_INIT_Final;\n    }\n    else\n    {\n      if ((g_z7_Blake2sp_SupportedFlags & (1u << algo)) == 0)\n        return False;\n\n#ifdef Z7_BLAKE2S_USE_AVX2\n\n      func_Single =\n#if defined(Z7_BLAKE2S_USE_AVX2_WAY2)\n        Blake2sp_Compress2_AVX2_Way2;\n#else\n        Z7_BLAKE2S_Compress2_V128;\n#endif\n\n#ifdef Z7_BLAKE2S_USE_AVX2_FAST\n      if (algo == Z7_BLAKE2SP_ALGO_V256_FAST)\n      {\n        func = Blake2sp_Compress2_AVX2_Fast;\n        func_Final = Blake2sp_Final_AVX2_Fast;\n        func_Init  = Blake2sp_InitState_AVX2_Fast;\n      }\n      else\n#endif\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY2\n      if (algo == Z7_BLAKE2SP_ALGO_V256_WAY2)\n        func = Blake2sp_Compress2_AVX2_Way2;\n      else\n#endif\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY4\n      if (algo == Z7_BLAKE2SP_ALGO_V256_WAY4)\n      {\n        func_Single = func = Blake2sp_Compress2_AVX2_Way4;\n      }\n      else\n#endif\n#endif // avx2\n      {\n        if (algo == Z7_BLAKE2SP_ALGO_V128_FAST)\n        {\n          func       = Blake2sp_Compress2_V128_Fast;\n          func_Final = Blake2sp_Final_V128_Fast;\n          func_Init  = Blake2sp_InitState_V128_Fast;\n          func_Single = Z7_BLAKE2S_Compress2_V128;\n        }\n        else\n#ifdef Z7_BLAKE2S_USE_V128_WAY2\n        if (algo == Z7_BLAKE2SP_ALGO_V128_WAY2)\n          func = func_Single = Blake2sp_Compress2_V128_Way2;\n        else\n#endif\n        {\n          if (algo != Z7_BLAKE2SP_ALGO_V128_WAY1)\n            return False;\n          func = func_Single = Blake2sp_Compress2_V128_Way1;\n        }\n      }\n    }\n  }\n#else // !VECTORS\n  if (algo > 1) // Z7_BLAKE2SP_ALGO_SCALAR\n    return False;\n#endif // !VECTORS\n\n#ifdef Z7_BLAKE2SP_USE_FUNCTIONS\n  p->u.header.func_Compress_Fast = func;\n  p->u.header.func_Compress_Single = func_Single;\n  p->u.header.func_Final = func_Final;\n  p->u.header.func_Init = func_Init;\n#endif\n  // printf(\"\\n p->u.header.func_Compress = %p\", p->u.header.func_Compress);\n  return True;\n}\n\n\nvoid z7_Black2sp_Prepare(void)\n{\n#ifdef Z7_BLAKE2S_USE_VECTORS\n  unsigned flags = 0; // (1u << Z7_BLAKE2SP_ALGO_V128_SCALAR);\n\n  Z7_BLAKE2SP_FUNC_COMPRESS func_Fast = Blake2sp_Compress2;\n  Z7_BLAKE2SP_FUNC_COMPRESS func_Single = Blake2sp_Compress2;\n  Z7_BLAKE2SP_FUNC_INIT func_Init = NULL;\n  Z7_BLAKE2SP_FUNC_INIT func_Final = NULL;\n\n#if defined(MY_CPU_X86_OR_AMD64)\n    #if defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)\n      // optional check\n      #if 0 || !(defined(__AVX512F__) && defined(__AVX512VL__))\n      if (CPU_IsSupported_AVX512F_AVX512VL())\n      #endif\n    #elif defined(Z7_BLAKE2S_USE_SSE41)\n      if (CPU_IsSupported_SSE41())\n    #elif defined(Z7_BLAKE2S_USE_SSSE3)\n      if (CPU_IsSupported_SSSE3())\n    #elif !defined(MY_CPU_AMD64)\n      if (CPU_IsSupported_SSE2())\n    #endif\n#endif\n  {\n    #if defined(Z7_BLAKE2S_USE_SSE41)\n      // printf(\"\\n========== Blake2s SSE41 128-bit\\n\");\n    #elif defined(Z7_BLAKE2S_USE_SSSE3)\n      // printf(\"\\n========== Blake2s SSSE3 128-bit\\n\");\n    #else\n      // printf(\"\\n========== Blake2s SSE2 128-bit\\n\");\n    #endif\n    // func_Fast = f_vector = Blake2sp_Compress2_V128_Way2;\n    // printf(\"\\n========== Blake2sp_Compress2_V128_Way2\\n\");\n    func_Fast   =\n    func_Single = Z7_BLAKE2S_Compress2_V128;\n    flags |= (1u << Z7_BLAKE2SP_ALGO_V128_WAY1);\n#ifdef Z7_BLAKE2S_USE_V128_WAY2\n    flags |= (1u << Z7_BLAKE2SP_ALGO_V128_WAY2);\n#endif\n#ifdef Z7_BLAKE2S_USE_V128_FAST\n    flags |= (1u << Z7_BLAKE2SP_ALGO_V128_FAST);\n    func_Fast  = Blake2sp_Compress2_V128_Fast;\n    func_Init  = Blake2sp_InitState_V128_Fast;\n    func_Final = Blake2sp_Final_V128_Fast;\n#endif\n\n#ifdef Z7_BLAKE2S_USE_AVX2\n#if defined(MY_CPU_X86_OR_AMD64)\n    \n    #if defined(Z7_BLAKE2S_USE_AVX512_ALWAYS)\n      #if 0\n        if (CPU_IsSupported_AVX512F_AVX512VL())\n      #endif\n    #else\n        if (CPU_IsSupported_AVX2())\n    #endif\n#endif\n    {\n    // #pragma message (\"=== Blake2s AVX2\")\n    // printf(\"\\n========== Blake2s AVX2\\n\");\n    \n#ifdef Z7_BLAKE2S_USE_AVX2_WAY2\n      func_Single = Blake2sp_Compress2_AVX2_Way2;\n      flags |= (1u << Z7_BLAKE2SP_ALGO_V256_WAY2);\n#endif\n#ifdef Z7_BLAKE2S_USE_AVX2_WAY4\n      flags |= (1u << Z7_BLAKE2SP_ALGO_V256_WAY4);\n#endif\n\n#ifdef Z7_BLAKE2S_USE_AVX2_FAST\n      flags |= (1u << Z7_BLAKE2SP_ALGO_V256_FAST);\n      func_Fast  = Blake2sp_Compress2_AVX2_Fast;\n      func_Init  = Blake2sp_InitState_AVX2_Fast;\n      func_Final = Blake2sp_Final_AVX2_Fast;\n#elif defined(Z7_BLAKE2S_USE_AVX2_WAY4)\n      func_Fast  = Blake2sp_Compress2_AVX2_Way4;\n#elif defined(Z7_BLAKE2S_USE_AVX2_WAY2)\n      func_Fast  = Blake2sp_Compress2_AVX2_Way2;\n#endif\n    } // avx2\n#endif // avx2\n  } // sse*\n  g_Z7_BLAKE2SP_FUNC_COMPRESS_Fast   = func_Fast;\n  g_Z7_BLAKE2SP_FUNC_COMPRESS_Single = func_Single;\n  g_Z7_BLAKE2SP_FUNC_INIT_Init       = func_Init;\n  g_Z7_BLAKE2SP_FUNC_INIT_Final      = func_Final;\n  g_z7_Blake2sp_SupportedFlags = flags;\n  // printf(\"\\nflags=%x\\n\", flags);\n#endif // vectors\n}\n\n/*\n#ifdef Z7_BLAKE2S_USE_VECTORS\nvoid align_test2(CBlake2sp *sp);\nvoid align_test2(CBlake2sp *sp)\n{\n  __m128i a = LOAD_128(sp->states);\n  D_XOR_128(a, LOAD_128(sp->states + 4));\n  STORE_128(sp->states, a);\n}\nvoid align_test2(void);\nvoid align_test2(void)\n{\n  CBlake2sp sp;\n  Blake2sp_Init(&sp);\n  Blake2sp_Update(&sp, NULL, 0);\n}\n#endif\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Bra.c",
    "content": "﻿/* Bra.c -- Branch converters for RISC code\n2024-01-20 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Bra.h\"\n#include \"RotateDefs.h\"\n#include \"CpuArch.h\"\n\n#if defined(MY_CPU_SIZEOF_POINTER) \\\n    && ( MY_CPU_SIZEOF_POINTER == 4 \\\n      || MY_CPU_SIZEOF_POINTER == 8)\n  #define BR_CONV_USE_OPT_PC_PTR\n#endif\n\n#ifdef BR_CONV_USE_OPT_PC_PTR\n#define BR_PC_INIT  pc -= (UInt32)(SizeT)p;\n#define BR_PC_GET   (pc + (UInt32)(SizeT)p)\n#else\n#define BR_PC_INIT  pc += (UInt32)size;\n#define BR_PC_GET   (pc - (UInt32)(SizeT)(lim - p))\n// #define BR_PC_INIT\n// #define BR_PC_GET   (pc + (UInt32)(SizeT)(p - data))\n#endif\n\n#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;\n// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;\n\n#define Z7_BRANCH_CONV(name) z7_ ## name\n\n#define Z7_BRANCH_FUNC_MAIN(name) \\\nstatic \\\nZ7_FORCE_INLINE \\\nZ7_ATTRIB_NO_VECTOR \\\nByte *Z7_BRANCH_CONV(name)(Byte *p, SizeT size, UInt32 pc, int encoding)\n\n#define Z7_BRANCH_FUNC_IMP(name, m, encoding) \\\nZ7_NO_INLINE \\\nZ7_ATTRIB_NO_VECTOR \\\nByte *m(name)(Byte *data, SizeT size, UInt32 pc) \\\n  { return Z7_BRANCH_CONV(name)(data, size, pc, encoding); } \\\n\n#ifdef Z7_EXTRACT_ONLY\n#define Z7_BRANCH_FUNCS_IMP(name) \\\n  Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0)\n#else\n#define Z7_BRANCH_FUNCS_IMP(name) \\\n  Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_DEC_2, 0) \\\n  Z7_BRANCH_FUNC_IMP(name, Z7_BRANCH_CONV_ENC_2, 1)\n#endif\n\n#if defined(__clang__)\n#define BR_EXTERNAL_FOR\n#define BR_NEXT_ITERATION  continue;\n#else\n#define BR_EXTERNAL_FOR    for (;;)\n#define BR_NEXT_ITERATION  break;\n#endif\n\n#if defined(__clang__) && (__clang_major__ >= 8) \\\n  || defined(__GNUC__) && (__GNUC__ >= 1000) \\\n  // GCC is not good for __builtin_expect() here\n  /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */\n  // #define Z7_unlikely [[unlikely]]\n  // #define Z7_LIKELY(x)   (__builtin_expect((x), 1))\n  #define Z7_UNLIKELY(x) (__builtin_expect((x), 0))\n  // #define Z7_likely [[likely]]\n#else\n  // #define Z7_LIKELY(x)   (x)\n  #define Z7_UNLIKELY(x) (x)\n  // #define Z7_likely\n#endif\n\n\nZ7_BRANCH_FUNC_MAIN(BranchConv_ARM64)\n{\n  // Byte *p = data;\n  const Byte *lim;\n  const UInt32 flag = (UInt32)1 << (24 - 4);\n  const UInt32 mask = ((UInt32)1 << 24) - (flag << 1);\n  size &= ~(SizeT)3;\n  // if (size == 0) return p;\n  lim = p + size;\n  BR_PC_INIT\n  pc -= 4;  // because (p) will point to next instruction\n  \n  BR_EXTERNAL_FOR\n  {\n    // Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n    for (;;)\n    {\n      UInt32 v;\n      if Z7_UNLIKELY(p == lim)\n        return p;\n      v = GetUi32a(p);\n      p += 4;\n      if Z7_UNLIKELY(((v - 0x94000000) & 0xfc000000) == 0)\n      {\n        UInt32 c = BR_PC_GET >> 2;\n        BR_CONVERT_VAL(v, c)\n        v &= 0x03ffffff;\n        v |= 0x94000000;\n        SetUi32a(p - 4, v)\n        BR_NEXT_ITERATION\n      }\n      // v = rotlFixed(v, 8);  v += (flag << 8) - 0x90;  if Z7_UNLIKELY((v & ((mask << 8) + 0x9f)) == 0)\n      v -= 0x90000000;  if Z7_UNLIKELY((v & 0x9f000000) == 0)\n      {\n        UInt32 z, c;\n        // v = rotrFixed(v, 8);\n        v += flag; if Z7_UNLIKELY(v & mask) continue;\n        z = (v & 0xffffffe0) | (v >> 26);\n        c = (BR_PC_GET >> (12 - 3)) & ~(UInt32)7;\n        BR_CONVERT_VAL(z, c)\n        v &= 0x1f;\n        v |= 0x90000000;\n        v |= z << 26;\n        v |= 0x00ffffe0 & ((z & (((flag << 1) - 1))) - flag);\n        SetUi32a(p - 4, v)\n      }\n    }\n  }\n}\nZ7_BRANCH_FUNCS_IMP(BranchConv_ARM64)\n\n\nZ7_BRANCH_FUNC_MAIN(BranchConv_ARM)\n{\n  // Byte *p = data;\n  const Byte *lim;\n  size &= ~(SizeT)3;\n  lim = p + size;\n  BR_PC_INIT\n  /* in ARM: branch offset is relative to the +2 instructions from current instruction.\n     (p) will point to next instruction */\n  pc += 8 - 4;\n  \n  for (;;)\n  {\n    for (;;)\n    {\n      if Z7_UNLIKELY(p >= lim) { return p; }  p += 4;  if Z7_UNLIKELY(p[-1] == 0xeb) break;\n      if Z7_UNLIKELY(p >= lim) { return p; }  p += 4;  if Z7_UNLIKELY(p[-1] == 0xeb) break;\n    }\n    {\n      UInt32 v = GetUi32a(p - 4);\n      UInt32 c = BR_PC_GET >> 2;\n      BR_CONVERT_VAL(v, c)\n      v &= 0x00ffffff;\n      v |= 0xeb000000;\n      SetUi32a(p - 4, v)\n    }\n  }\n}\nZ7_BRANCH_FUNCS_IMP(BranchConv_ARM)\n\n\nZ7_BRANCH_FUNC_MAIN(BranchConv_PPC)\n{\n  // Byte *p = data;\n  const Byte *lim;\n  size &= ~(SizeT)3;\n  lim = p + size;\n  BR_PC_INIT\n  pc -= 4;  // because (p) will point to next instruction\n  \n  for (;;)\n  {\n    UInt32 v;\n    for (;;)\n    {\n      if Z7_UNLIKELY(p == lim)\n        return p;\n      // v = GetBe32a(p);\n      v = *(UInt32 *)(void *)p;\n      p += 4;\n      // if ((v & 0xfc000003) == 0x48000001) break;\n      // if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1) break;\n      if Z7_UNLIKELY(\n          ((v - Z7_CONV_BE_TO_NATIVE_CONST32(0x48000001))\n              & Z7_CONV_BE_TO_NATIVE_CONST32(0xfc000003)) == 0) break;\n    }\n    {\n      v = Z7_CONV_NATIVE_TO_BE_32(v);\n      {\n        UInt32 c = BR_PC_GET;\n        BR_CONVERT_VAL(v, c)\n      }\n      v &= 0x03ffffff;\n      v |= 0x48000000;\n      SetBe32a(p - 4, v)\n    }\n  }\n}\nZ7_BRANCH_FUNCS_IMP(BranchConv_PPC)\n\n\n#ifdef Z7_CPU_FAST_ROTATE_SUPPORTED\n#define BR_SPARC_USE_ROTATE\n#endif\n\nZ7_BRANCH_FUNC_MAIN(BranchConv_SPARC)\n{\n  // Byte *p = data;\n  const Byte *lim;\n  const UInt32 flag = (UInt32)1 << 22;\n  size &= ~(SizeT)3;\n  lim = p + size;\n  BR_PC_INIT\n  pc -= 4;  // because (p) will point to next instruction\n  for (;;)\n  {\n    UInt32 v;\n    for (;;)\n    {\n      if Z7_UNLIKELY(p == lim)\n        return p;\n      /* // the code without GetBe32a():\n      { const UInt32 v = GetUi16a(p) & 0xc0ff; p += 4; if (v == 0x40 || v == 0xc07f) break; }\n      */\n      v = GetBe32a(p);\n      p += 4;\n    #ifdef BR_SPARC_USE_ROTATE\n      v = rotlFixed(v, 2);\n      v += (flag << 2) - 1;\n      if Z7_UNLIKELY((v & (3 - (flag << 3))) == 0)\n    #else\n      v += (UInt32)5 << 29;\n      v ^= (UInt32)7 << 29;\n      v += flag;\n      if Z7_UNLIKELY((v & (0 - (flag << 1))) == 0)\n    #endif\n        break;\n    }\n    {\n      // UInt32 v = GetBe32a(p - 4);\n    #ifndef BR_SPARC_USE_ROTATE\n      v <<= 2;\n    #endif\n      {\n        UInt32 c = BR_PC_GET;\n        BR_CONVERT_VAL(v, c)\n      }\n      v &= (flag << 3) - 1;\n    #ifdef BR_SPARC_USE_ROTATE\n      v -= (flag << 2) - 1;\n      v = rotrFixed(v, 2);\n    #else\n      v -= (flag << 2);\n      v >>= 2;\n      v |= (UInt32)1 << 30;\n    #endif\n      SetBe32a(p - 4, v)\n    }\n  }\n}\nZ7_BRANCH_FUNCS_IMP(BranchConv_SPARC)\n\n\nZ7_BRANCH_FUNC_MAIN(BranchConv_ARMT)\n{\n  // Byte *p = data;\n  Byte *lim;\n  size &= ~(SizeT)1;\n  // if (size == 0) return p;\n  if (size <= 2) return p;\n  size -= 2;\n  lim = p + size;\n  BR_PC_INIT\n  /* in ARM: branch offset is relative to the +2 instructions from current instruction.\n     (p) will point to the +2 instructions from current instruction */\n  // pc += 4 - 4;\n  // if (encoding) pc -= 0xf800 << 1; else pc += 0xf800 << 1;\n  // #define ARMT_TAIL_PROC { goto armt_tail; }\n  #define ARMT_TAIL_PROC { return p; }\n  \n  do\n  {\n    /* in MSVC 32-bit x86 compilers:\n       UInt32 version : it loads value from memory with movzx\n       Byte   version : it loads value to 8-bit register (AL/CL)\n       movzx version is slightly faster in some cpus\n    */\n    unsigned b1;\n    // Byte / unsigned\n    b1 = p[1];\n    // optimized version to reduce one (p >= lim) check:\n    // unsigned a1 = p[1];  b1 = p[3];  p += 2;  if Z7_LIKELY((b1 & (a1 ^ 8)) < 0xf8)\n    for (;;)\n    {\n      unsigned b3; // Byte / UInt32\n      /* (Byte)(b3) normalization can use low byte computations in MSVC.\n         It gives smaller code, and no loss of speed in some compilers/cpus.\n         But new MSVC 32-bit x86 compilers use more slow load\n         from memory to low byte register in that case.\n         So we try to use full 32-bit computations for faster code.\n      */\n      // if (p >= lim) { ARMT_TAIL_PROC }  b3 = b1 + 8;  b1 = p[3];  p += 2;  if ((b3 & b1) >= 0xf8) break;\n      if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC }  b3 = p[3];  p += 2;  if Z7_UNLIKELY((b3 & (b1 ^ 8)) >= 0xf8) break;\n      if Z7_UNLIKELY(p >= lim) { ARMT_TAIL_PROC }  b1 = p[3];  p += 2;  if Z7_UNLIKELY((b1 & (b3 ^ 8)) >= 0xf8) break;\n    }\n    {\n      /* we can adjust pc for (0xf800) to rid of (& 0x7FF) operation.\n         But gcc/clang for arm64 can use bfi instruction for full code here */\n      UInt32 v =\n          ((UInt32)GetUi16a(p - 2) << 11) |\n          ((UInt32)GetUi16a(p) & 0x7FF);\n      /*\n      UInt32 v =\n            ((UInt32)p[1 - 2] << 19)\n          + (((UInt32)p[1] & 0x7) << 8)\n          + (((UInt32)p[-2] << 11))\n          + (p[0]);\n      */\n      p += 2;\n      {\n        UInt32 c = BR_PC_GET >> 1;\n        BR_CONVERT_VAL(v, c)\n      }\n      SetUi16a(p - 4, (UInt16)(((v >> 11) & 0x7ff) | 0xf000))\n      SetUi16a(p - 2, (UInt16)(v | 0xf800))\n      /*\n      p[-4] = (Byte)(v >> 11);\n      p[-3] = (Byte)(0xf0 | ((v >> 19) & 0x7));\n      p[-2] = (Byte)v;\n      p[-1] = (Byte)(0xf8 | (v >> 8));\n      */\n    }\n  }\n  while (p < lim);\n  return p;\n  // armt_tail:\n  // if ((Byte)((lim[1] & 0xf8)) != 0xf0) { lim += 2; }  return lim;\n  // return (Byte *)(lim + ((Byte)((lim[1] ^ 0xf0) & 0xf8) == 0 ? 0 : 2));\n  // return (Byte *)(lim + (((lim[1] ^ ~0xfu) & ~7u) == 0 ? 0 : 2));\n  // return (Byte *)(lim + 2 - (((((unsigned)lim[1] ^ 8) + 8) >> 7) & 2));\n}\nZ7_BRANCH_FUNCS_IMP(BranchConv_ARMT)\n\n\n// #define BR_IA64_NO_INLINE\n\nZ7_BRANCH_FUNC_MAIN(BranchConv_IA64)\n{\n  // Byte *p = data;\n  const Byte *lim;\n  size &= ~(SizeT)15;\n  lim = p + size;\n  pc -= 1 << 4;\n  pc >>= 4 - 1;\n  // pc -= 1 << 1;\n  \n  for (;;)\n  {\n    unsigned m;\n    for (;;)\n    {\n      if Z7_UNLIKELY(p == lim)\n        return p;\n      m = (unsigned)((UInt32)0x334b0000 >> (*p & 0x1e));\n      p += 16;\n      pc += 1 << 1;\n      if (m &= 3)\n        break;\n    }\n    {\n      p += (ptrdiff_t)m * 5 - 20; // negative value is expected here.\n      do\n      {\n        const UInt32 t =\n          #if defined(MY_CPU_X86_OR_AMD64)\n            // we use 32-bit load here to reduce code size on x86:\n            GetUi32(p);\n          #else\n            GetUi16(p);\n          #endif\n        UInt32 z = GetUi32(p + 1) >> m;\n        p += 5;\n        if (((t >> m) & (0x70 << 1)) == 0\n            && ((z - (0x5000000 << 1)) & (0xf000000 << 1)) == 0)\n        {\n          UInt32 v = (UInt32)((0x8fffff << 1) | 1) & z;\n          z ^= v;\n        #ifdef BR_IA64_NO_INLINE\n          v |= (v & ((UInt32)1 << (23 + 1))) >> 3;\n          {\n            UInt32 c = pc;\n            BR_CONVERT_VAL(v, c)\n          }\n          v &= (0x1fffff << 1) | 1;\n        #else\n          {\n            if (encoding)\n            {\n              // pc &= ~(0xc00000 << 1); // we just need to clear at least 2 bits\n              pc &= (0x1fffff << 1) | 1;\n              v += pc;\n            }\n            else\n            {\n              // pc |= 0xc00000 << 1; // we need to set at least 2 bits\n              pc |= ~(UInt32)((0x1fffff << 1) | 1);\n              v -= pc;\n            }\n          }\n          v &= ~(UInt32)(0x600000 << 1);\n        #endif\n          v += (0x700000 << 1);\n          v &= (0x8fffff << 1) | 1;\n          z |= v;\n          z <<= m;\n          SetUi32(p + 1 - 5, z)\n        }\n        m++;\n      }\n      while (m &= 3); // while (m < 4);\n    }\n  }\n}\nZ7_BRANCH_FUNCS_IMP(BranchConv_IA64)\n\n\n#define BR_CONVERT_VAL_ENC(v)  v += BR_PC_GET;\n#define BR_CONVERT_VAL_DEC(v)  v -= BR_PC_GET;\n\n#if 1 && defined(MY_CPU_LE_UNALIGN)\n  #define RISCV_USE_UNALIGNED_LOAD\n#endif\n\n#ifdef RISCV_USE_UNALIGNED_LOAD\n  #define RISCV_GET_UI32(p)      GetUi32(p)\n  #define RISCV_SET_UI32(p, v)   { SetUi32(p, v) }\n#else\n  #define RISCV_GET_UI32(p) \\\n    ((UInt32)GetUi16a(p) + \\\n    ((UInt32)GetUi16a((p) + 2) << 16))\n  #define RISCV_SET_UI32(p, v) { \\\n    SetUi16a(p, (UInt16)(v)) \\\n    SetUi16a((p) + 2, (UInt16)(v >> 16)) }\n#endif\n\n#if 1 && defined(MY_CPU_LE)\n  #define RISCV_USE_16BIT_LOAD\n#endif\n\n#ifdef RISCV_USE_16BIT_LOAD\n  #define RISCV_LOAD_VAL(p)  GetUi16a(p)\n#else\n  #define RISCV_LOAD_VAL(p)  (*(p))\n#endif\n\n#define RISCV_INSTR_SIZE  2\n#define RISCV_STEP_1      (4 + RISCV_INSTR_SIZE)\n#define RISCV_STEP_2      4\n#define RISCV_REG_VAL     (2 << 7)\n#define RISCV_CMD_VAL     3\n#if 1\n  // for code size optimization:\n  #define RISCV_DELTA_7F  0x7f\n#else\n  #define RISCV_DELTA_7F  0\n#endif\n\n#define RISCV_CHECK_1(v, b) \\\n    (((((b) - RISCV_CMD_VAL) ^ ((v) << 8)) & (0xf8000 + RISCV_CMD_VAL)) == 0)\n\n#if 1\n  #define RISCV_CHECK_2(v, r) \\\n    ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL | 8)) \\\n           << 18) \\\n     < ((r) & 0x1d))\n#else\n  // this branch gives larger code, because\n  // compilers generate larger code for big constants.\n  #define RISCV_CHECK_2(v, r) \\\n    ((((v) - ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \\\n           & ((RISCV_CMD_VAL << 12) | RISCV_REG_VAL)) \\\n     < ((r) & 0x1d))\n#endif\n\n\n#define RISCV_SCAN_LOOP \\\n  Byte *lim; \\\n  size &= ~(SizeT)(RISCV_INSTR_SIZE - 1); \\\n  if (size <= 6) return p; \\\n  size -= 6; \\\n  lim = p + size; \\\n  BR_PC_INIT \\\n  for (;;) \\\n  { \\\n    UInt32 a, v; \\\n    /* Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE */ \\\n    for (;;) \\\n    { \\\n      if Z7_UNLIKELY(p >= lim) { return p; } \\\n      a = (RISCV_LOAD_VAL(p) ^ 0x10u) + 1; \\\n      if ((a & 0x77) == 0) break; \\\n      a = (RISCV_LOAD_VAL(p + RISCV_INSTR_SIZE) ^ 0x10u) + 1; \\\n      p += RISCV_INSTR_SIZE * 2; \\\n      if ((a & 0x77) == 0) \\\n      { \\\n        p -= RISCV_INSTR_SIZE; \\\n        if Z7_UNLIKELY(p >= lim) { return p; } \\\n        break; \\\n      } \\\n    }\n// (xx6f ^ 10) + 1 = xx7f + 1 = xx80       : JAL\n// (xxef ^ 10) + 1 = xxff + 1 = xx00 + 100 : JAL\n// (xx17 ^ 10) + 1 = xx07 + 1 = xx08       : AUIPC\n// (xx97 ^ 10) + 1 = xx87 + 1 = xx88       : AUIPC\n\nByte * Z7_BRANCH_CONV_ENC(RISCV)(Byte *p, SizeT size, UInt32 pc)\n{\n  RISCV_SCAN_LOOP\n    v = a;\n    a = RISCV_GET_UI32(p);\n#ifndef RISCV_USE_16BIT_LOAD\n    v += (UInt32)p[1] << 8;\n#endif\n\n    if ((v & 8) == 0) // JAL\n    {\n      if ((v - (0x100 /* - RISCV_DELTA_7F */)) & 0xd80)\n      {\n        p += RISCV_INSTR_SIZE;\n        continue;\n      }\n      {\n        v = ((a &    1u << 31) >> 11)\n          | ((a & 0x3ff << 21) >> 20)\n          | ((a &     1 << 20) >> 9)\n          |  (a &  0xff << 12);\n        BR_CONVERT_VAL_ENC(v)\n        // ((v & 1) == 0)\n        // v: bits [1 : 20] contain offset bits\n#if 0 && defined(RISCV_USE_UNALIGNED_LOAD)\n        a &= 0xfff;\n        a |= ((UInt32)(v << 23))\n          |  ((UInt32)(v <<  7) & ((UInt32)0xff << 16))\n          |  ((UInt32)(v >>  5) & ((UInt32)0xf0 << 8));\n        RISCV_SET_UI32(p, a)\n#else // aligned\n#if 0\n        SetUi16a(p, (UInt16)(((v >> 5) & 0xf000) | (a & 0xfff)))\n#else\n        p[1] = (Byte)(((v >> 13) & 0xf0) | ((a >> 8) & 0xf));\n#endif\n\n#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)\n        v <<= 15;\n        v = Z7_BSWAP32(v);\n        SetUi16a(p + 2, (UInt16)v)\n#else\n        p[2] = (Byte)(v >> 9);\n        p[3] = (Byte)(v >> 1);\n#endif\n#endif // aligned\n      }\n      p += 4;\n      continue;\n    } // JAL\n\n    {\n      // AUIPC\n      if (v & 0xe80)  // (not x0) and (not x2)\n      {\n        const UInt32 b = RISCV_GET_UI32(p + 4);\n        if (RISCV_CHECK_1(v, b))\n        {\n          {\n            const UInt32 temp = (b << 12) | (0x17 + RISCV_REG_VAL);\n            RISCV_SET_UI32(p, temp)\n          }\n          a &= 0xfffff000;\n          {\n#if 1\n          const int t = -1 >> 1;\n          if (t != -1)\n            a += (b >> 20) - ((b >> 19) & 0x1000); // arithmetic right shift emulation\n          else\n#endif\n            a += (UInt32)((Int32)b >> 20); // arithmetic right shift (sign-extension).\n          }\n          BR_CONVERT_VAL_ENC(a)\n#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)\n          a = Z7_BSWAP32(a);\n          RISCV_SET_UI32(p + 4, a)\n#else\n          SetBe32(p + 4, a)\n#endif\n          p += 8;\n        }\n        else\n          p += RISCV_STEP_1;\n      }\n      else\n      {\n        UInt32 r = a >> 27;\n        if (RISCV_CHECK_2(v, r))\n        {\n          v = RISCV_GET_UI32(p + 4);\n          r = (r << 7) + 0x17 + (v & 0xfffff000);\n          a = (a >> 12) | (v << 20);\n          RISCV_SET_UI32(p, r)\n          RISCV_SET_UI32(p + 4, a)\n          p += 8;\n        }\n        else\n          p += RISCV_STEP_2;\n      }\n    }\n  } // for\n}\n\n\nByte * Z7_BRANCH_CONV_DEC(RISCV)(Byte *p, SizeT size, UInt32 pc)\n{\n  RISCV_SCAN_LOOP\n#ifdef RISCV_USE_16BIT_LOAD\n    if ((a & 8) == 0)\n    {\n#else\n    v = a;\n    a += (UInt32)p[1] << 8;\n    if ((v & 8) == 0)\n    {\n#endif\n      // JAL\n      a -= 0x100 - RISCV_DELTA_7F;\n      if (a & 0xd80)\n      {\n        p += RISCV_INSTR_SIZE;\n        continue;\n      }\n      {\n        const UInt32 a_old = (a + (0xef - RISCV_DELTA_7F)) & 0xfff;\n#if 0 // unaligned\n        a = GetUi32(p);\n        v = (UInt32)(a >> 23) & ((UInt32)0xff << 1)\n          | (UInt32)(a >>  7) & ((UInt32)0xff << 9)\n#elif 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)\n        v = GetUi16a(p + 2);\n        v = Z7_BSWAP32(v) >> 15\n#else\n        v = (UInt32)p[3] << 1\n          | (UInt32)p[2] << 9\n#endif\n          | (UInt32)((a & 0xf000) << 5);\n        BR_CONVERT_VAL_DEC(v)\n        a = a_old\n          | (v << 11 &    1u << 31)\n          | (v << 20 & 0x3ff << 21)\n          | (v <<  9 &     1 << 20)\n          | (v       &  0xff << 12);\n        RISCV_SET_UI32(p, a)\n      }\n      p += 4;\n      continue;\n    } // JAL\n\n    {\n      // AUIPC\n      v = a;\n#if 1 && defined(RISCV_USE_UNALIGNED_LOAD)\n      a = GetUi32(p);\n#else\n      a |= (UInt32)GetUi16a(p + 2) << 16;\n#endif\n      if ((v & 0xe80) == 0)  // x0/x2\n      {\n        const UInt32 r = a >> 27;\n        if (RISCV_CHECK_2(v, r))\n        {\n          UInt32 b;\n#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE)\n          b = RISCV_GET_UI32(p + 4);\n          b = Z7_BSWAP32(b);\n#else\n          b = GetBe32(p + 4);\n#endif\n          v = a >> 12;\n          BR_CONVERT_VAL_DEC(b)\n          a = (r << 7) + 0x17;\n          a += (b + 0x800) & 0xfffff000;\n          v |= b << 20;\n          RISCV_SET_UI32(p, a)\n          RISCV_SET_UI32(p + 4, v)\n          p += 8;\n        }\n        else\n          p += RISCV_STEP_2;\n      }\n      else\n      {\n        const UInt32 b = RISCV_GET_UI32(p + 4);\n        if (!RISCV_CHECK_1(v, b))\n          p += RISCV_STEP_1;\n        else\n        {\n          v = (a & 0xfffff000) | (b >> 20);\n          a = (b << 12) | (0x17 + RISCV_REG_VAL);\n          RISCV_SET_UI32(p, a)\n          RISCV_SET_UI32(p + 4, v)\n          p += 8;\n        }\n      }\n    }\n  } // for\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Bra.h",
    "content": "﻿/* Bra.h -- Branch converters for executables\n2024-01-20 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_BRA_H\n#define ZIP7_INC_BRA_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n/* #define PPC BAD_PPC_11 // for debug */\n\n#define Z7_BRANCH_CONV_DEC_2(name)  z7_ ## name ## _Dec\n#define Z7_BRANCH_CONV_ENC_2(name)  z7_ ## name ## _Enc\n#define Z7_BRANCH_CONV_DEC(name)    Z7_BRANCH_CONV_DEC_2(BranchConv_ ## name)\n#define Z7_BRANCH_CONV_ENC(name)    Z7_BRANCH_CONV_ENC_2(BranchConv_ ## name)\n#define Z7_BRANCH_CONV_ST_DEC(name) z7_BranchConvSt_ ## name ## _Dec\n#define Z7_BRANCH_CONV_ST_ENC(name) z7_BranchConvSt_ ## name ## _Enc\n\n#define Z7_BRANCH_CONV_DECL(name)    Byte * name(Byte *data, SizeT size, UInt32 pc)\n#define Z7_BRANCH_CONV_ST_DECL(name) Byte * name(Byte *data, SizeT size, UInt32 pc, UInt32 *state)\n\ntypedef Z7_BRANCH_CONV_DECL(   (*z7_Func_BranchConv));\ntypedef Z7_BRANCH_CONV_ST_DECL((*z7_Func_BranchConvSt));\n\n#define Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL 0\nZ7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_DEC(X86));\nZ7_BRANCH_CONV_ST_DECL (Z7_BRANCH_CONV_ST_ENC(X86));\n\n#define Z7_BRANCH_FUNCS_DECL(name) \\\nZ7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_DEC_2(name)); \\\nZ7_BRANCH_CONV_DECL (Z7_BRANCH_CONV_ENC_2(name));\n\nZ7_BRANCH_FUNCS_DECL (BranchConv_ARM64)\nZ7_BRANCH_FUNCS_DECL (BranchConv_ARM)\nZ7_BRANCH_FUNCS_DECL (BranchConv_ARMT)\nZ7_BRANCH_FUNCS_DECL (BranchConv_PPC)\nZ7_BRANCH_FUNCS_DECL (BranchConv_SPARC)\nZ7_BRANCH_FUNCS_DECL (BranchConv_IA64)\nZ7_BRANCH_FUNCS_DECL (BranchConv_RISCV)\n\n/*\nThese functions convert data that contain CPU instructions.\nEach such function converts relative addresses to absolute addresses in some\nbranch instructions: CALL (in all converters) and JUMP (X86 converter only).\nSuch conversion allows to increase compression ratio, if we compress that data.\n\nThere are 2 types of converters:\n  Byte * Conv_RISC (Byte *data, SizeT size, UInt32 pc);\n  Byte * ConvSt_X86(Byte *data, SizeT size, UInt32 pc, UInt32 *state);\nEach Converter supports 2 versions: one for encoding\nand one for decoding (_Enc/_Dec postfixes in function name).\n\nIn params:\n  data  : data buffer\n  size  : size of data\n  pc    : current virtual Program Counter (Instruction Pointer) value\nIn/Out param:\n  state : pointer to state variable (for X86 converter only)\n\nReturn:\n  The pointer to position in (data) buffer after last byte that was processed.\n  If the caller calls converter again, it must call it starting with that position.\n  But the caller is allowed to move data in buffer. So pointer to\n  current processed position also will be changed for next call.\n  Also the caller must increase internal (pc) value for next call.\n  \nEach converter has some characteristics: Endian, Alignment, LookAhead.\n  Type   Endian  Alignment  LookAhead\n  \n  X86    little      1          4\n  ARMT   little      2          2\n  RISCV  little      2          6\n  ARM    little      4          0\n  ARM64  little      4          0\n  PPC     big        4          0\n  SPARC   big        4          0\n  IA64   little     16          0\n\n  (data) must be aligned for (Alignment).\n  processed size can be calculated as:\n    SizeT processed = Conv(data, size, pc) - data;\n  if (processed == 0)\n    it means that converter needs more data for processing.\n  If (size < Alignment + LookAhead)\n    then (processed == 0) is allowed.\n\nExample code for conversion in loop:\n  UInt32 pc = 0;\n  size = 0;\n  for (;;)\n  {\n    size += Load_more_input_data(data + size);\n    SizeT processed = Conv(data, size, pc) - data;\n    if (processed == 0 && no_more_input_data_after_size)\n      break; // we stop convert loop\n    data += processed;\n    size -= processed;\n    pc += processed;\n  }\n*/\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Bra86.c",
    "content": "﻿/* Bra86.c -- Branch converter for X86 code (BCJ)\n2023-04-02 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Bra.h\"\n#include \"CpuArch.h\"\n\n\n#if defined(MY_CPU_SIZEOF_POINTER) \\\n    && ( MY_CPU_SIZEOF_POINTER == 4 \\\n      || MY_CPU_SIZEOF_POINTER == 8)\n  #define BR_CONV_USE_OPT_PC_PTR\n#endif\n\n#ifdef BR_CONV_USE_OPT_PC_PTR\n#define BR_PC_INIT  pc -= (UInt32)(SizeT)p; // (MY_uintptr_t)\n#define BR_PC_GET   (pc + (UInt32)(SizeT)p)\n#else\n#define BR_PC_INIT  pc += (UInt32)size;\n#define BR_PC_GET   (pc - (UInt32)(SizeT)(lim - p))\n// #define BR_PC_INIT\n// #define BR_PC_GET   (pc + (UInt32)(SizeT)(p - data))\n#endif\n\n#define BR_CONVERT_VAL(v, c) if (encoding) v += c; else v -= c;\n// #define BR_CONVERT_VAL(v, c) if (!encoding) c = (UInt32)0 - c; v += c;\n\n#define Z7_BRANCH_CONV_ST(name) z7_BranchConvSt_ ## name\n\n#define BR86_NEED_CONV_FOR_MS_BYTE(b) ((((b) + 1) & 0xfe) == 0)\n\n#ifdef MY_CPU_LE_UNALIGN\n  #define BR86_PREPARE_BCJ_SCAN  const UInt32 v = GetUi32(p) ^ 0xe8e8e8e8;\n  #define BR86_IS_BCJ_BYTE(n)    ((v & ((UInt32)0xfe << (n) * 8)) == 0)\n#else\n  #define BR86_PREPARE_BCJ_SCAN\n  // bad for MSVC X86 (partial write to byte reg):\n  #define BR86_IS_BCJ_BYTE(n)    ((p[n - 4] & 0xfe) == 0xe8)\n  // bad for old MSVC (partial write to byte reg):\n  // #define BR86_IS_BCJ_BYTE(n)    (((*p ^ 0xe8) & 0xfe) == 0)\n#endif\n \nstatic\nZ7_FORCE_INLINE\nZ7_ATTRIB_NO_VECTOR\nByte *Z7_BRANCH_CONV_ST(X86)(Byte *p, SizeT size, UInt32 pc, UInt32 *state, int encoding)\n{\n  if (size < 5)\n    return p;\n {\n  // Byte *p = data;\n  const Byte *lim = p + size - 4;\n  unsigned mask = (unsigned)*state;  // & 7;\n#ifdef BR_CONV_USE_OPT_PC_PTR\n  /* if BR_CONV_USE_OPT_PC_PTR is defined: we need to adjust (pc) for (+4),\n        because call/jump offset is relative to the next instruction.\n     if BR_CONV_USE_OPT_PC_PTR is not defined : we don't need to adjust (pc) for (+4),\n         because  BR_PC_GET uses (pc - (lim - p)), and lim was adjusted for (-4) before.\n  */\n  pc += 4;\n#endif\n  BR_PC_INIT\n  goto start;\n\n  for (;; mask |= 4)\n  {\n    // cont: mask |= 4;\n  start:\n    if (p >= lim)\n      goto fin;\n    {\n      BR86_PREPARE_BCJ_SCAN\n      p += 4;\n      if (BR86_IS_BCJ_BYTE(0))  { goto m0; }  mask >>= 1;\n      if (BR86_IS_BCJ_BYTE(1))  { goto m1; }  mask >>= 1;\n      if (BR86_IS_BCJ_BYTE(2))  { goto m2; }  mask = 0;\n      if (BR86_IS_BCJ_BYTE(3))  { goto a3; }\n    }\n    goto main_loop;\n\n  m0: p--;\n  m1: p--;\n  m2: p--;\n    if (mask == 0)\n      goto a3;\n    if (p > lim)\n      goto fin_p;\n   \n    // if (((0x17u >> mask) & 1) == 0)\n    if (mask > 4 || mask == 3)\n    {\n      mask >>= 1;\n      continue; // goto cont;\n    }\n    mask >>= 1;\n    if (BR86_NEED_CONV_FOR_MS_BYTE(p[mask]))\n      continue; // goto cont;\n    // if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont;\n    {\n      UInt32 v = GetUi32(p);\n      UInt32 c;\n      v += (1 << 24);  if (v & 0xfe000000) continue; // goto cont;\n      c = BR_PC_GET;\n      BR_CONVERT_VAL(v, c)\n      {\n        mask <<= 3;\n        if (BR86_NEED_CONV_FOR_MS_BYTE(v >> mask))\n        {\n          v ^= (((UInt32)0x100 << mask) - 1);\n          #ifdef MY_CPU_X86\n          // for X86 : we can recalculate (c) to reduce register pressure\n            c = BR_PC_GET;\n          #endif\n          BR_CONVERT_VAL(v, c)\n        }\n        mask = 0;\n      }\n      // v = (v & ((1 << 24) - 1)) - (v & (1 << 24));\n      v &= (1 << 25) - 1;  v -= (1 << 24);\n      SetUi32(p, v)\n      p += 4;\n      goto main_loop;\n    }\n\n  main_loop:\n    if (p >= lim)\n      goto fin;\n    for (;;)\n    {\n      BR86_PREPARE_BCJ_SCAN\n      p += 4;\n      if (BR86_IS_BCJ_BYTE(0))  { goto a0; }\n      if (BR86_IS_BCJ_BYTE(1))  { goto a1; }\n      if (BR86_IS_BCJ_BYTE(2))  { goto a2; }\n      if (BR86_IS_BCJ_BYTE(3))  { goto a3; }\n      if (p >= lim)\n        goto fin;\n    }\n  \n  a0: p--;\n  a1: p--;\n  a2: p--;\n  a3:\n    if (p > lim)\n      goto fin_p;\n    // if (!BR86_NEED_CONV_FOR_MS_BYTE(p[3])) continue; // goto cont;\n    {\n      UInt32 v = GetUi32(p);\n      UInt32 c;\n      v += (1 << 24);  if (v & 0xfe000000) continue; // goto cont;\n      c = BR_PC_GET;\n      BR_CONVERT_VAL(v, c)\n      // v = (v & ((1 << 24) - 1)) - (v & (1 << 24));\n      v &= (1 << 25) - 1;  v -= (1 << 24);\n      SetUi32(p, v)\n      p += 4;\n      goto main_loop;\n    }\n  }\n\nfin_p:\n  p--;\nfin:\n  // the following processing for tail is optional and can be commented\n  /*\n  lim += 4;\n  for (; p < lim; p++, mask >>= 1)\n    if ((*p & 0xfe) == 0xe8)\n      break;\n  */\n  *state = (UInt32)mask;\n  return p;\n }\n}\n\n\n#define Z7_BRANCH_CONV_ST_FUNC_IMP(name, m, encoding) \\\nZ7_NO_INLINE \\\nZ7_ATTRIB_NO_VECTOR \\\nByte *m(name)(Byte *data, SizeT size, UInt32 pc, UInt32 *state) \\\n  { return Z7_BRANCH_CONV_ST(name)(data, size, pc, state, encoding); }\n\nZ7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_DEC, 0)\n#ifndef Z7_EXTRACT_ONLY\nZ7_BRANCH_CONV_ST_FUNC_IMP(X86, Z7_BRANCH_CONV_ST_ENC, 1)\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/BwtSort.c",
    "content": "﻿/* BwtSort.c -- BWT block sorting\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"BwtSort.h\"\n#include \"Sort.h\"\n\n/* #define BLOCK_SORT_USE_HEAP_SORT */\n// #define BLOCK_SORT_USE_HEAP_SORT\n\n#ifdef BLOCK_SORT_USE_HEAP_SORT\n\n#define HeapSortRefDown(p, vals, n, size, temp) \\\n  { size_t k = n; UInt32 val = vals[temp]; for (;;) { \\\n    size_t s = k << 1; \\\n    if (s > size) break; \\\n    if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \\\n    if (val >= vals[p[s]]) break; \\\n    p[k] = p[s]; k = s; \\\n  } p[k] = temp; }\n\nvoid HeapSortRef(UInt32 *p, UInt32 *vals, size_t size)\n{\n  if (size <= 1)\n    return;\n  p--;\n  {\n    size_t i = size / 2;\n    do\n    {\n      UInt32 temp = p[i];\n      HeapSortRefDown(p, vals, i, size, temp);\n    }\n    while (--i != 0);\n  }\n  do\n  {\n    UInt32 temp = p[size];\n    p[size--] = p[1];\n    HeapSortRefDown(p, vals, 1, size, temp);\n  }\n  while (size > 1);\n}\n\n#endif // BLOCK_SORT_USE_HEAP_SORT\n\n\n/* Don't change it !!! */\n#define kNumHashBytes 2\n#define kNumHashValues (1 << (kNumHashBytes * 8))\n\n/* kNumRefBitsMax must be < (kNumHashBytes * 8) = 16 */\n#define kNumRefBitsMax 12\n\n#define BS_TEMP_SIZE kNumHashValues\n\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n\n/* 32 Flags in UInt32 word */\n#define kNumFlagsBits 5\n#define kNumFlagsInWord (1 << kNumFlagsBits)\n#define kFlagsMask (kNumFlagsInWord - 1)\n#define kAllFlags 0xFFFFFFFF\n\n#else\n\n#define kNumBitsMax     20\n#define kIndexMask      (((UInt32)1 << kNumBitsMax) - 1)\n#define kNumExtraBits   (32 - kNumBitsMax)\n#define kNumExtra0Bits  (kNumExtraBits - 2)\n#define kNumExtra0Mask  ((1 << kNumExtra0Bits) - 1)\n\n#define SetFinishedGroupSize(p, size) \\\n  {  *(p) |= ((((UInt32)(size) - 1) & kNumExtra0Mask) << kNumBitsMax); \\\n    if ((size) > (1 << kNumExtra0Bits)) { \\\n      *(p) |= 0x40000000; \\\n      *((p) + 1) |= (((UInt32)(size) - 1) >> kNumExtra0Bits) << kNumBitsMax; } } \\\n\nstatic void SetGroupSize(UInt32 *p, size_t size)\n{\n  if (--size == 0)\n    return;\n  *p |= 0x80000000 | (((UInt32)size & kNumExtra0Mask) << kNumBitsMax);\n  if (size >= (1 << kNumExtra0Bits))\n  {\n    *p |= 0x40000000;\n    p[1] |= (((UInt32)size >> kNumExtra0Bits) << kNumBitsMax);\n  }\n}\n\n#endif\n\n/*\nSortGroup - is recursive Range-Sort function with HeapSort optimization for small blocks\n  \"range\" is not real range. It's only for optimization.\nreturns: 1 - if there are groups, 0 - no more groups\n*/\n\nstatic\nunsigned\nZ7_FASTCALL\nSortGroup(size_t BlockSize, size_t NumSortedBytes,\n    size_t groupOffset, size_t groupSize,\n    unsigned NumRefBits, UInt32 *Indices\n#ifndef BLOCK_SORT_USE_HEAP_SORT\n    , size_t left, size_t range\n#endif\n  )\n{\n  UInt32 *ind2 = Indices + groupOffset;\n  UInt32 *Groups;\n  if (groupSize <= 1)\n  {\n    /*\n    #ifndef BLOCK_SORT_EXTERNAL_FLAGS\n    SetFinishedGroupSize(ind2, 1)\n    #endif\n    */\n    return 0;\n  }\n  Groups = Indices + BlockSize + BS_TEMP_SIZE;\n  if (groupSize <= ((size_t)1 << NumRefBits)\n#ifndef BLOCK_SORT_USE_HEAP_SORT\n      && groupSize <= range\n#endif\n      )\n  {\n    UInt32 *temp = Indices + BlockSize;\n    size_t j, group;\n    UInt32 mask, cg;\n    unsigned thereAreGroups;\n    {\n      UInt32 gPrev;\n      UInt32 gRes = 0;\n      {\n        size_t sp = ind2[0] + NumSortedBytes;\n        if (sp >= BlockSize)\n            sp -= BlockSize;\n        gPrev = Groups[sp];\n        temp[0] = gPrev << NumRefBits;\n      }\n      \n      for (j = 1; j < groupSize; j++)\n      {\n        size_t sp = ind2[j] + NumSortedBytes;\n        UInt32 g;\n        if (sp >= BlockSize)\n            sp -= BlockSize;\n        g = Groups[sp];\n        temp[j] = (g << NumRefBits) | (UInt32)j;\n        gRes |= (gPrev ^ g);\n      }\n      if (gRes == 0)\n      {\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n        SetGroupSize(ind2, groupSize);\n#endif\n        return 1;\n      }\n    }\n    \n    HeapSort(temp, groupSize);\n    mask = ((UInt32)1 << NumRefBits) - 1;\n    thereAreGroups = 0;\n    \n    group = groupOffset;\n    cg = temp[0] >> NumRefBits;\n    temp[0] = ind2[temp[0] & mask];\n\n    {\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n    UInt32 *Flags = Groups + BlockSize;\n#else\n    size_t prevGroupStart = 0;\n#endif\n    \n    for (j = 1; j < groupSize; j++)\n    {\n      const UInt32 val = temp[j];\n      const UInt32 cgCur = val >> NumRefBits;\n      \n      if (cgCur != cg)\n      {\n        cg = cgCur;\n        group = groupOffset + j;\n\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n        {\n          const size_t t = group - 1;\n          Flags[t >> kNumFlagsBits] &= ~((UInt32)1 << (t & kFlagsMask));\n        }\n#else\n        SetGroupSize(temp + prevGroupStart, j - prevGroupStart);\n        prevGroupStart = j;\n#endif\n      }\n      else\n        thereAreGroups = 1;\n      {\n        const UInt32 ind = ind2[val & mask];\n        temp[j] = ind;\n        Groups[ind] = (UInt32)group;\n      }\n    }\n\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n    SetGroupSize(temp + prevGroupStart, j - prevGroupStart);\n#endif\n    }\n\n    for (j = 0; j < groupSize; j++)\n      ind2[j] = temp[j];\n    return thereAreGroups;\n  }\n\n  /* Check that all strings are in one group (cannot sort) */\n  {\n    UInt32 group;\n    size_t j;\n    size_t sp = ind2[0] + NumSortedBytes;\n    if (sp >= BlockSize)\n        sp -= BlockSize;\n    group = Groups[sp];\n    for (j = 1; j < groupSize; j++)\n    {\n      sp = ind2[j] + NumSortedBytes;\n      if (sp >= BlockSize)\n          sp -= BlockSize;\n      if (Groups[sp] != group)\n        break;\n    }\n    if (j == groupSize)\n    {\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n      SetGroupSize(ind2, groupSize);\n#endif\n      return 1;\n    }\n  }\n\n#ifndef BLOCK_SORT_USE_HEAP_SORT\n  {\n  /* ---------- Range Sort ---------- */\n  size_t i;\n  size_t mid;\n  for (;;)\n  {\n    size_t j;\n    if (range <= 1)\n    {\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n      SetGroupSize(ind2, groupSize);\n#endif\n      return 1;\n    }\n    mid = left + ((range + 1) >> 1);\n    j = groupSize;\n    i = 0;\n    do\n    {\n      size_t sp = ind2[i] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;\n      if (Groups[sp] >= mid)\n      {\n        for (j--; j > i; j--)\n        {\n          sp = ind2[j] + NumSortedBytes; if (sp >= BlockSize) sp -= BlockSize;\n          if (Groups[sp] < mid)\n          {\n            UInt32 temp = ind2[i]; ind2[i] = ind2[j]; ind2[j] = temp;\n            break;\n          }\n        }\n        if (i >= j)\n          break;\n      }\n    }\n    while (++i < j);\n    if (i == 0)\n    {\n      range = range - (mid - left);\n      left = mid;\n    }\n    else if (i == groupSize)\n      range = (mid - left);\n    else\n      break;\n  }\n\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n  {\n    const size_t t = groupOffset + i - 1;\n    UInt32 *Flags = Groups + BlockSize;\n    Flags[t >> kNumFlagsBits] &= ~((UInt32)1 << (t & kFlagsMask));\n  }\n#endif\n\n  {\n    size_t j;\n    for (j = i; j < groupSize; j++)\n      Groups[ind2[j]] = (UInt32)(groupOffset + i);\n  }\n\n  {\n    unsigned res = SortGroup(BlockSize, NumSortedBytes, groupOffset, i, NumRefBits, Indices, left, mid - left);\n    return   res | SortGroup(BlockSize, NumSortedBytes, groupOffset + i, groupSize - i, NumRefBits, Indices, mid, range - (mid - left));\n  }\n\n  }\n\n#else // BLOCK_SORT_USE_HEAP_SORT\n\n  /* ---------- Heap Sort ---------- */\n\n  {\n    size_t j;\n    for (j = 0; j < groupSize; j++)\n    {\n      size_t sp = ind2[j] + NumSortedBytes;\n      if (sp >= BlockSize)\n          sp -= BlockSize;\n      ind2[j] = (UInt32)sp;\n    }\n\n    HeapSortRef(ind2, Groups, groupSize);\n\n    /* Write Flags */\n    {\n    size_t sp = ind2[0];\n    UInt32 group = Groups[sp];\n\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n    UInt32 *Flags = Groups + BlockSize;\n#else\n    size_t prevGroupStart = 0;\n#endif\n\n    for (j = 1; j < groupSize; j++)\n    {\n      sp = ind2[j];\n      if (Groups[sp] != group)\n      {\n        group = Groups[sp];\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n        {\n        const size_t t = groupOffset + j - 1;\n        Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask));\n        }\n#else\n        SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);\n        prevGroupStart = j;\n#endif\n      }\n    }\n\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n    SetGroupSize(ind2 + prevGroupStart, j - prevGroupStart);\n#endif\n    }\n    {\n    /* Write new Groups values and Check that there are groups */\n    unsigned thereAreGroups = 0;\n    for (j = 0; j < groupSize; j++)\n    {\n      size_t group = groupOffset + j;\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n      UInt32 subGroupSize = ((ind2[j] & ~0xC0000000) >> kNumBitsMax);\n      if (ind2[j] & 0x40000000)\n        subGroupSize += ((ind2[(size_t)j + 1] >> kNumBitsMax) << kNumExtra0Bits);\n      subGroupSize++;\n      for (;;)\n      {\n        const UInt32 original = ind2[j];\n        size_t sp = original & kIndexMask;\n        if (sp < NumSortedBytes)\n          sp += BlockSize;\n        sp -= NumSortedBytes;\n        ind2[j] = (UInt32)sp | (original & ~kIndexMask);\n        Groups[sp] = (UInt32)group;\n        if (--subGroupSize == 0)\n          break;\n        j++;\n        thereAreGroups = 1;\n      }\n#else\n      UInt32 *Flags = Groups + BlockSize;\n      for (;;)\n      {\n        size_t sp = ind2[j];\n        if (sp < NumSortedBytes)\n          sp += BlockSize;\n        sp -= NumSortedBytes;\n        ind2[j] = (UInt32)sp;\n        Groups[sp] = (UInt32)group;\n        if ((Flags[(groupOffset + j) >> kNumFlagsBits] & (1 << ((groupOffset + j) & kFlagsMask))) == 0)\n          break;\n        j++;\n        thereAreGroups = 1;\n      }\n#endif\n    }\n    return thereAreGroups;\n    }\n  }\n#endif // BLOCK_SORT_USE_HEAP_SORT\n}\n\n\n/* conditions: blockSize > 0 */\nUInt32 BlockSort(UInt32 *Indices, const Byte *data, size_t blockSize)\n{\n  UInt32 *counters = Indices + blockSize;\n  size_t i;\n  UInt32 *Groups;\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n  UInt32 *Flags;\n#endif\n\n/* Radix-Sort for 2 bytes */\n// { UInt32 yyy; for (yyy = 0; yyy < 100; yyy++) {\n  for (i = 0; i < kNumHashValues; i++)\n    counters[i] = 0;\n  {\n    const Byte *data2 = data;\n    size_t a = data[(size_t)blockSize - 1];\n    const Byte *data_lim = data + blockSize;\n    if (blockSize >= 4)\n    {\n      data_lim -= 3;\n      do\n      {\n        size_t b;\n        b = data2[0]; counters[(a << 8) | b]++;\n        a = data2[1]; counters[(b << 8) | a]++;\n        b = data2[2]; counters[(a << 8) | b]++;\n        a = data2[3]; counters[(b << 8) | a]++;\n        data2 += 4;\n      }\n      while (data2 < data_lim);\n      data_lim += 3;\n    }\n    while (data2 != data_lim)\n    {\n      size_t b = *data2++;\n      counters[(a << 8) | b]++;\n      a = b;\n    }\n  }\n// }}\n\n  Groups = counters + BS_TEMP_SIZE;\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n  Flags = Groups + blockSize;\n  {\n    const size_t numWords = (blockSize + kFlagsMask) >> kNumFlagsBits;\n    for (i = 0; i < numWords; i++)\n      Flags[i] = kAllFlags;\n  }\n#endif\n\n  {\n    UInt32 sum = 0;\n    for (i = 0; i < kNumHashValues; i++)\n    {\n      const UInt32 groupSize = counters[i];\n      counters[i] = sum;\n      sum += groupSize;\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n      if (groupSize)\n      {\n        const UInt32 t = sum - 1;\n        Flags[t >> kNumFlagsBits] &= ~((UInt32)1 << (t & kFlagsMask));\n      }\n#endif\n    }\n  }\n\n  for (i = 0; i < blockSize - 1; i++)\n    Groups[i] = counters[((unsigned)data[i] << 8) | data[(size_t)i + 1]];\n  Groups[i] = counters[((unsigned)data[i] << 8) | data[0]];\n  \n  {\n#define SET_Indices(a, b, i)  \\\n    { UInt32 c; \\\n      a = (a << 8) | (b); \\\n      c = counters[a]; \\\n      Indices[c] = (UInt32)i++; \\\n      counters[a] = c + 1; \\\n    }\n\n    size_t a = data[0];\n    const Byte *data_ptr = data + 1;\n    i = 0;\n    if (blockSize >= 3)\n    {\n      blockSize -= 2;\n      do\n      {\n        size_t b;\n        b = data_ptr[0];  SET_Indices(a, b, i)\n        a = data_ptr[1];  SET_Indices(b, a, i)\n        data_ptr += 2;\n      }\n      while (i < blockSize);\n      blockSize += 2;\n    }\n    if (i < blockSize - 1)\n    {\n      SET_Indices(a, data[(size_t)i + 1], i)\n      a = (Byte)a;\n    }\n    SET_Indices(a, data[0], i)\n  }\n  \n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n  {\n    UInt32 prev = 0;\n    for (i = 0; i < kNumHashValues; i++)\n    {\n      const UInt32 prevGroupSize = counters[i] - prev;\n      if (prevGroupSize == 0)\n        continue;\n      SetGroupSize(Indices + prev, prevGroupSize);\n      prev = counters[i];\n    }\n  }\n#endif\n\n  {\n  unsigned NumRefBits;\n  size_t NumSortedBytes;\n  for (NumRefBits = 0; ((blockSize - 1) >> NumRefBits) != 0; NumRefBits++)\n  {}\n  NumRefBits = 32 - NumRefBits;\n  if (NumRefBits > kNumRefBitsMax)\n      NumRefBits = kNumRefBitsMax;\n\n  for (NumSortedBytes = kNumHashBytes; ; NumSortedBytes <<= 1)\n  {\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n    size_t finishedGroupSize = 0;\n#endif\n    size_t newLimit = 0;\n    for (i = 0; i < blockSize;)\n    {\n      size_t groupSize;\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n\n      if ((Flags[i >> kNumFlagsBits] & (1 << (i & kFlagsMask))) == 0)\n      {\n        i++;\n        continue;\n      }\n      for (groupSize = 1;\n        (Flags[(i + groupSize) >> kNumFlagsBits] & (1 << ((i + groupSize) & kFlagsMask))) != 0;\n        groupSize++)\n        {}\n      groupSize++;\n\n#else\n\n      groupSize = (Indices[i] & ~0xC0000000) >> kNumBitsMax;\n      {\n        const BoolInt finishedGroup = ((Indices[i] & 0x80000000) == 0);\n        if (Indices[i] & 0x40000000)\n        {\n          groupSize += ((Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits);\n          Indices[(size_t)i + 1] &= kIndexMask;\n        }\n        Indices[i] &= kIndexMask;\n        groupSize++;\n        if (finishedGroup || groupSize == 1)\n        {\n          Indices[i - finishedGroupSize] &= kIndexMask;\n          if (finishedGroupSize > 1)\n            Indices[(size_t)(i - finishedGroupSize) + 1] &= kIndexMask;\n          {\n            const size_t newGroupSize = groupSize + finishedGroupSize;\n            SetFinishedGroupSize(Indices + i - finishedGroupSize, newGroupSize)\n            finishedGroupSize = newGroupSize;\n          }\n          i += groupSize;\n          continue;\n        }\n        finishedGroupSize = 0;\n      }\n\n#endif\n      \n      if (NumSortedBytes >= blockSize)\n      {\n        size_t j;\n        for (j = 0; j < groupSize; j++)\n        {\n          size_t t = i + j;\n          /* Flags[t >> kNumFlagsBits] &= ~(1 << (t & kFlagsMask)); */\n          Groups[Indices[t]] = (UInt32)t;\n        }\n      }\n      else\n        if (SortGroup(blockSize, NumSortedBytes, i, groupSize, NumRefBits, Indices\n            #ifndef BLOCK_SORT_USE_HEAP_SORT\n              , 0, blockSize\n            #endif\n            ))\n          newLimit = i + groupSize;\n      i += groupSize;\n    }\n    if (newLimit == 0)\n      break;\n  }\n  }\n#ifndef BLOCK_SORT_EXTERNAL_FLAGS\n  for (i = 0; i < blockSize;)\n  {\n    size_t groupSize = (Indices[i] & ~0xC0000000) >> kNumBitsMax;\n    if (Indices[i] & 0x40000000)\n    {\n      groupSize += (Indices[(size_t)i + 1] >> kNumBitsMax) << kNumExtra0Bits;\n      Indices[(size_t)i + 1] &= kIndexMask;\n    }\n    Indices[i] &= kIndexMask;\n    groupSize++;\n    i += groupSize;\n  }\n#endif\n  return Groups[0];\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/BwtSort.h",
    "content": "﻿/* BwtSort.h -- BWT block sorting\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_BWT_SORT_H\n#define ZIP7_INC_BWT_SORT_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */\n/* #define BLOCK_SORT_EXTERNAL_FLAGS */\n// #define BLOCK_SORT_EXTERNAL_FLAGS\n\n#ifdef BLOCK_SORT_EXTERNAL_FLAGS\n#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) (((blockSize) + 31) >> 5)\n#else\n#define BLOCK_SORT_EXTERNAL_SIZE(blockSize) 0\n#endif\n\n#define BLOCK_SORT_BUF_SIZE(blockSize) ((blockSize) * 2 + BLOCK_SORT_EXTERNAL_SIZE(blockSize) + (1 << 16))\n\nUInt32 BlockSort(UInt32 *indices, const Byte *data, size_t blockSize);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Compiler.h",
    "content": "﻿/* Compiler.h : Compiler specific defines and pragmas\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_COMPILER_H\n#define ZIP7_INC_COMPILER_H\n\n#if defined(__clang__)\n# define Z7_CLANG_VERSION  (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)\n#endif\n#if defined(__clang__) && defined(__apple_build_version__)\n# define Z7_APPLE_CLANG_VERSION   Z7_CLANG_VERSION\n#elif defined(__clang__)\n# define Z7_LLVM_CLANG_VERSION    Z7_CLANG_VERSION\n#elif defined(__GNUC__)\n# define Z7_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)\n#endif\n\n#ifdef _MSC_VER\n#if !defined(__clang__) && !defined(__GNUC__)\n#define Z7_MSC_VER_ORIGINAL _MSC_VER\n#endif\n#endif\n\n#if defined(__MINGW32__) || defined(__MINGW64__)\n#define Z7_MINGW\n#endif\n\n#if defined(__LCC__) && (defined(__MCST__) || defined(__e2k__))\n#define Z7_MCST_LCC\n#define Z7_MCST_LCC_VERSION (__LCC__ * 100 + __LCC_MINOR__)\n#endif\n\n/*\n#if defined(__AVX2__) \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) \\\n    || defined(Z7_APPLE_CLANG_VERSION) && (Z7_APPLE_CLANG_VERSION >= 40600) \\\n    || defined(Z7_LLVM_CLANG_VERSION) && (Z7_LLVM_CLANG_VERSION >= 30100) \\\n    || defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1800) \\\n    || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1400)\n    #define Z7_COMPILER_AVX2_SUPPORTED\n  #endif\n#endif\n*/\n\n// #pragma GCC diagnostic ignored \"-Wunknown-pragmas\"\n\n#ifdef __clang__\n// padding size of '' with 4 bytes to alignment boundary\n#pragma GCC diagnostic ignored \"-Wpadded\"\n\n#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \\\n  && defined(__FreeBSD__)\n// freebsd:\n#pragma GCC diagnostic ignored \"-Wexcess-padding\"\n#endif\n\n#if __clang_major__ >= 16\n#pragma GCC diagnostic ignored \"-Wunsafe-buffer-usage\"\n#endif\n\n#if __clang_major__ == 13\n#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)\n// cheri\n#pragma GCC diagnostic ignored \"-Wcapability-to-integer-cast\"\n#endif\n#endif\n\n#if __clang_major__ == 13\n  // for <arm_neon.h>\n  #pragma GCC diagnostic ignored \"-Wreserved-identifier\"\n#endif\n\n#endif // __clang__\n\n#if defined(_WIN32) && defined(__clang__) && __clang_major__ >= 16\n// #pragma GCC diagnostic ignored \"-Wcast-function-type-strict\"\n#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \\\n  _Pragma(\"GCC diagnostic ignored \\\"-Wcast-function-type-strict\\\"\")\n#else\n#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n#endif\n\ntypedef void (*Z7_void_Function)(void);\n#if defined(__clang__) || defined(__GNUC__)\n#define Z7_CAST_FUNC_C  (Z7_void_Function)\n#elif defined(_MSC_VER) && _MSC_VER > 1920\n#define Z7_CAST_FUNC_C  (void *)\n// #pragma warning(disable : 4191) // 'type cast': unsafe conversion from 'FARPROC' to 'void (__cdecl *)()'\n#else\n#define Z7_CAST_FUNC_C\n#endif\n/*\n#if (defined(__GNUC__) && (__GNUC__ >= 8)) || defined(__clang__)\n  // #pragma GCC diagnostic ignored \"-Wcast-function-type\"\n#endif\n*/\n#ifdef __GNUC__\n#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40000) && (Z7_GCC_VERSION < 70000)\n#pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n#endif\n#endif\n\n\n#ifdef _MSC_VER\n\n  #ifdef UNDER_CE\n    #define RPC_NO_WINDOWS_H\n    /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */\n    #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union\n    #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int\n  #endif\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n\n// == 1200 : -O1 : for __forceinline\n// >= 1900 : -O1 : for printf\n#pragma warning(disable : 4710) // function not inlined\n\n#if _MSC_VER < 1900\n// winnt.h: 'Int64ShllMod32'\n#pragma warning(disable : 4514) // unreferenced inline function has been removed\n#endif\n    \n#if _MSC_VER < 1300\n// #pragma warning(disable : 4702) // unreachable code\n// Bra.c : -O1:\n#pragma warning(disable : 4714) // function marked as __forceinline not inlined\n#endif\n\n/*\n#if _MSC_VER > 1400 && _MSC_VER <= 1900\n// strcat: This function or variable may be unsafe\n// sysinfoapi.h: kit10: GetVersion was declared deprecated\n#pragma warning(disable : 4996)\n#endif\n*/\n\n#if _MSC_VER > 1200\n// -Wall warnings\n\n#pragma warning(disable : 4711) // function selected for automatic inline expansion\n#pragma warning(disable : 4820) // '2' bytes padding added after data member\n\n#if _MSC_VER >= 1400 && _MSC_VER < 1920\n// 1400: string.h: _DBG_MEMCPY_INLINE_\n// 1600 - 191x : smmintrin.h __cplusplus'\n// is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'\n#pragma warning(disable : 4668)\n\n// 1400 - 1600 : WinDef.h : 'FARPROC' :\n// 1900 - 191x : immintrin.h: _readfsbase_u32\n// no function prototype given : converting '()' to '(void)'\n#pragma warning(disable : 4255)\n#endif\n\n#if _MSC_VER >= 1914\n// Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified\n#pragma warning(disable : 5045)\n#endif\n\n#endif // _MSC_VER > 1200\n#endif // _MSC_VER\n\n\n#if defined(__clang__) && (__clang_major__ >= 4)\n  #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \\\n    _Pragma(\"clang loop unroll(disable)\") \\\n    _Pragma(\"clang loop vectorize(disable)\")\n  #define Z7_ATTRIB_NO_VECTORIZE\n#elif defined(__GNUC__) && (__GNUC__ >= 5) \\\n    && (!defined(Z7_MCST_LCC_VERSION) || (Z7_MCST_LCC_VERSION >= 12610))\n  #define Z7_ATTRIB_NO_VECTORIZE __attribute__((optimize(\"no-tree-vectorize\")))\n  // __attribute__((optimize(\"no-unroll-loops\")));\n  #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n#elif defined(_MSC_VER) && (_MSC_VER >= 1920)\n  #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \\\n    _Pragma(\"loop( no_vector )\")\n  #define Z7_ATTRIB_NO_VECTORIZE\n#else\n  #define Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  #define Z7_ATTRIB_NO_VECTORIZE\n#endif\n\n#if defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1920)\n  #define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE _Pragma(\"optimize ( \\\"s\\\", on )\")\n  #define Z7_PRAGMA_OPTIMIZE_DEFAULT       _Pragma(\"optimize ( \\\"\\\", on )\")\n#else\n  #define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE\n  #define Z7_PRAGMA_OPTIMIZE_DEFAULT\n#endif\n\n\n\n#if defined(MY_CPU_X86_OR_AMD64) && ( \\\n       defined(__clang__) && (__clang_major__ >= 4) \\\n    || defined(__GNUC__) && (__GNUC__ >= 5))\n  #define Z7_ATTRIB_NO_SSE  __attribute__((__target__(\"no-sse\")))\n#else\n  #define Z7_ATTRIB_NO_SSE\n#endif\n\n#define Z7_ATTRIB_NO_VECTOR \\\n  Z7_ATTRIB_NO_VECTORIZE \\\n  Z7_ATTRIB_NO_SSE\n\n\n#if defined(__clang__) && (__clang_major__ >= 8) \\\n  || defined(__GNUC__) && (__GNUC__ >= 1000) \\\n  /* || defined(_MSC_VER) && (_MSC_VER >= 1920) */\n  // GCC is not good for __builtin_expect()\n  #define Z7_LIKELY(x)   (__builtin_expect((x), 1))\n  #define Z7_UNLIKELY(x) (__builtin_expect((x), 0))\n  // #define Z7_unlikely [[unlikely]]\n  // #define Z7_likely [[likely]]\n#else\n  #define Z7_LIKELY(x)   (x)\n  #define Z7_UNLIKELY(x) (x)\n  // #define Z7_likely\n#endif\n\n\n#if (defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30600))\n\n#if (Z7_CLANG_VERSION < 130000)\n#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \\\n  _Pragma(\"GCC diagnostic push\") \\\n  _Pragma(\"GCC diagnostic ignored \\\"-Wreserved-id-macro\\\"\")\n#else\n#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER \\\n  _Pragma(\"GCC diagnostic push\") \\\n  _Pragma(\"GCC diagnostic ignored \\\"-Wreserved-macro-identifier\\\"\")\n#endif\n\n#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER \\\n  _Pragma(\"GCC diagnostic pop\")\n#else\n#define Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n#define Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif\n\n#define UNUSED_VAR(x) (void)x;\n/* #define UNUSED_VAR(x) x=x; */\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/CpuArch.c",
    "content": "﻿/* CpuArch.c -- CPU specific code\nIgor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n// #include <stdio.h>\n\n#include \"CpuArch.h\"\n\n#ifdef MY_CPU_X86_OR_AMD64\n\n#undef NEED_CHECK_FOR_CPUID\n#if !defined(MY_CPU_AMD64)\n#define NEED_CHECK_FOR_CPUID\n#endif\n\n/*\n  cpuid instruction supports (subFunction) parameter in ECX,\n  that is used only with some specific (function) parameter values.\n  most functions use only (subFunction==0).\n*/\n/*\n  __cpuid(): MSVC and GCC/CLANG use same function/macro name\n             but parameters are different.\n   We use MSVC __cpuid() parameters style for our z7_x86_cpuid() function.\n*/\n\n#if defined(__GNUC__) /* && (__GNUC__ >= 10) */ \\\n    || defined(__clang__) /* && (__clang_major__ >= 10) */\n\n/* there was some CLANG/GCC compilers that have issues with\n   rbx(ebx) handling in asm blocks in -fPIC mode (__PIC__ is defined).\n   compiler's <cpuid.h> contains the macro __cpuid() that is similar to our code.\n   The history of __cpuid() changes in CLANG/GCC:\n   GCC:\n     2007: it preserved ebx for (__PIC__ && __i386__)\n     2013: it preserved rbx and ebx for __PIC__\n     2014: it doesn't preserves rbx and ebx anymore\n     we suppose that (__GNUC__ >= 5) fixed that __PIC__ ebx/rbx problem.\n   CLANG:\n     2014+: it preserves rbx, but only for 64-bit code. No __PIC__ check.\n   Why CLANG cares about 64-bit mode only, and doesn't care about ebx (in 32-bit)?\n   Do we need __PIC__ test for CLANG or we must care about rbx even if\n   __PIC__ is not defined?\n*/\n\n#define ASM_LN \"\\n\"\n   \n#if defined(MY_CPU_AMD64) && defined(__PIC__) \\\n    && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))\n\n  /* \"=&r\" selects free register. It can select even rbx, if that register is free.\n     \"=&D\" for (RDI) also works, but the code can be larger with \"=&D\"\n     \"2\"(subFun) : 2 is (zero-based) index in the output constraint list \"=c\" (ECX). */\n\n#define x86_cpuid_MACRO_2(p, func, subFunc) { \\\n  __asm__ __volatile__ ( \\\n    ASM_LN   \"mov     %%rbx, %q1\"  \\\n    ASM_LN   \"cpuid\"               \\\n    ASM_LN   \"xchg    %%rbx, %q1\"  \\\n    : \"=a\" ((p)[0]), \"=&r\" ((p)[1]), \"=c\" ((p)[2]), \"=d\" ((p)[3]) : \"0\" (func), \"2\"(subFunc)); }\n\n#elif defined(MY_CPU_X86) && defined(__PIC__) \\\n    && ((defined (__GNUC__) && (__GNUC__ < 5)) || defined(__clang__))\n\n#define x86_cpuid_MACRO_2(p, func, subFunc) { \\\n  __asm__ __volatile__ ( \\\n    ASM_LN   \"mov     %%ebx, %k1\"  \\\n    ASM_LN   \"cpuid\"               \\\n    ASM_LN   \"xchg    %%ebx, %k1\"  \\\n    : \"=a\" ((p)[0]), \"=&r\" ((p)[1]), \"=c\" ((p)[2]), \"=d\" ((p)[3]) : \"0\" (func), \"2\"(subFunc)); }\n\n#else\n\n#define x86_cpuid_MACRO_2(p, func, subFunc) { \\\n  __asm__ __volatile__ ( \\\n    ASM_LN   \"cpuid\"               \\\n    : \"=a\" ((p)[0]), \"=b\" ((p)[1]), \"=c\" ((p)[2]), \"=d\" ((p)[3]) : \"0\" (func), \"2\"(subFunc)); }\n\n#endif\n\n#define x86_cpuid_MACRO(p, func)  x86_cpuid_MACRO_2(p, func, 0)\n\nvoid Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)\n{\n  x86_cpuid_MACRO(p, func)\n}\n\nstatic\nvoid Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)\n{\n  x86_cpuid_MACRO_2(p, func, subFunc)\n}\n\n\nZ7_NO_INLINE\nUInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)\n{\n #if defined(NEED_CHECK_FOR_CPUID)\n  #define EFALGS_CPUID_BIT 21\n  UInt32 a;\n  __asm__ __volatile__ (\n    ASM_LN   \"pushf\"\n    ASM_LN   \"pushf\"\n    ASM_LN   \"pop     %0\"\n    // ASM_LN   \"movl    %0, %1\"\n    // ASM_LN   \"xorl    $0x200000, %0\"\n    ASM_LN   \"btc     %1, %0\"\n    ASM_LN   \"push    %0\"\n    ASM_LN   \"popf\"\n    ASM_LN   \"pushf\"\n    ASM_LN   \"pop     %0\"\n    ASM_LN   \"xorl    (%%esp), %0\"\n\n    ASM_LN   \"popf\"\n    ASM_LN\n    : \"=&r\" (a) // \"=a\"\n    : \"i\" (EFALGS_CPUID_BIT)\n    );\n  if ((a & (1 << EFALGS_CPUID_BIT)) == 0)\n    return 0;\n #endif\n  {\n    UInt32 p[4];\n    x86_cpuid_MACRO(p, 0)\n    return p[0];\n  }\n}\n\n#undef ASM_LN\n\n#elif !defined(_MSC_VER)\n\n/*\n// for gcc/clang and other: we can try to use __cpuid macro:\n#include <cpuid.h>\nvoid Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)\n{\n  __cpuid(func, p[0], p[1], p[2], p[3]);\n}\nUInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)\n{\n  return (UInt32)__get_cpuid_max(0, NULL);\n}\n*/\n// for unsupported cpuid:\nvoid Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)\n{\n  UNUSED_VAR(func)\n  p[0] = p[1] = p[2] = p[3] = 0;\n}\nUInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)\n{\n  return 0;\n}\n\n#else // _MSC_VER\n\n#if !defined(MY_CPU_AMD64)\n\nUInt32 __declspec(naked) Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)\n{\n  #if defined(NEED_CHECK_FOR_CPUID)\n  #define EFALGS_CPUID_BIT 21\n  __asm   pushfd\n  __asm   pushfd\n  /*\n  __asm   pop     eax\n  // __asm   mov     edx, eax\n  __asm   btc     eax, EFALGS_CPUID_BIT\n  __asm   push    eax\n  */\n  __asm   btc     dword ptr [esp], EFALGS_CPUID_BIT\n  __asm   popfd\n  __asm   pushfd\n  __asm   pop     eax\n  // __asm   xor     eax, edx\n  __asm   xor     eax, [esp]\n  // __asm   push    edx\n  __asm   popfd\n  __asm   and     eax, (1 shl EFALGS_CPUID_BIT)\n  __asm   jz end_func\n  #endif\n  __asm   push    ebx\n  __asm   xor     eax, eax    // func\n  __asm   xor     ecx, ecx    // subFunction (optional) for (func == 0)\n  __asm   cpuid\n  __asm   pop     ebx\n  #if defined(NEED_CHECK_FOR_CPUID)\n  end_func:\n  #endif\n  __asm   ret 0\n}\n\nvoid __declspec(naked) Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)\n{\n  UNUSED_VAR(p)\n  UNUSED_VAR(func)\n  __asm   push    ebx\n  __asm   push    edi\n  __asm   mov     edi, ecx    // p\n  __asm   mov     eax, edx    // func\n  __asm   xor     ecx, ecx    // subfunction (optional) for (func == 0)\n  __asm   cpuid\n  __asm   mov     [edi     ], eax\n  __asm   mov     [edi +  4], ebx\n  __asm   mov     [edi +  8], ecx\n  __asm   mov     [edi + 12], edx\n  __asm   pop     edi\n  __asm   pop     ebx\n  __asm   ret     0\n}\n\nstatic\nvoid __declspec(naked) Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)\n{\n  UNUSED_VAR(p)\n  UNUSED_VAR(func)\n  UNUSED_VAR(subFunc)\n  __asm   push    ebx\n  __asm   push    edi\n  __asm   mov     edi, ecx    // p\n  __asm   mov     eax, edx    // func\n  __asm   mov     ecx, [esp + 12]  // subFunc\n  __asm   cpuid\n  __asm   mov     [edi     ], eax\n  __asm   mov     [edi +  4], ebx\n  __asm   mov     [edi +  8], ecx\n  __asm   mov     [edi + 12], edx\n  __asm   pop     edi\n  __asm   pop     ebx\n  __asm   ret     4\n}\n\n#else // MY_CPU_AMD64\n\n    #if _MSC_VER >= 1600\n      #include <intrin.h>\n      #define MY_cpuidex  __cpuidex\n\nstatic\nvoid Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)\n{\n  __cpuidex((int *)p, func, subFunc);\n}\n\n    #else\n/*\n __cpuid (func == (0 or 7)) requires subfunction number in ECX.\n  MSDN: The __cpuid intrinsic clears the ECX register before calling the cpuid instruction.\n   __cpuid() in new MSVC clears ECX.\n   __cpuid() in old MSVC (14.00) x64 doesn't clear ECX\n We still can use __cpuid for low (func) values that don't require ECX,\n but __cpuid() in old MSVC will be incorrect for some func values: (func == 7).\n So here we use the hack for old MSVC to send (subFunction) in ECX register to cpuid instruction,\n where ECX value is first parameter for FASTCALL / NO_INLINE func.\n So the caller of MY_cpuidex_HACK() sets ECX as subFunction, and\n old MSVC for __cpuid() doesn't change ECX and cpuid instruction gets (subFunction) value.\n \nDON'T remove Z7_NO_INLINE and Z7_FASTCALL for MY_cpuidex_HACK(): !!!\n*/\nstatic\nZ7_NO_INLINE void Z7_FASTCALL MY_cpuidex_HACK(Int32 subFunction, Int32 func, Int32 *CPUInfo)\n{\n  UNUSED_VAR(subFunction)\n  __cpuid(CPUInfo, func);\n}\n      #define MY_cpuidex(info, func, func2)  MY_cpuidex_HACK(func2, func, info)\n      #pragma message(\"======== MY_cpuidex_HACK WAS USED ========\")\nstatic\nvoid Z7_FASTCALL z7_x86_cpuid_subFunc(UInt32 p[4], UInt32 func, UInt32 subFunc)\n{\n  MY_cpuidex_HACK(subFunc, func, (Int32 *)p);\n}\n    #endif // _MSC_VER >= 1600\n\n#if !defined(MY_CPU_AMD64)\n/* inlining for __cpuid() in MSVC x86 (32-bit) produces big ineffective code,\n   so we disable inlining here */\nZ7_NO_INLINE\n#endif\nvoid Z7_FASTCALL z7_x86_cpuid(UInt32 p[4], UInt32 func)\n{\n  MY_cpuidex((Int32 *)p, (Int32)func, 0);\n}\n\nZ7_NO_INLINE\nUInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void)\n{\n  Int32 a[4];\n  MY_cpuidex(a, 0, 0);\n  return a[0];\n}\n\n#endif // MY_CPU_AMD64\n#endif // _MSC_VER\n\n#if defined(NEED_CHECK_FOR_CPUID)\n#define CHECK_CPUID_IS_SUPPORTED { if (z7_x86_cpuid_GetMaxFunc() == 0) return 0; }\n#else\n#define CHECK_CPUID_IS_SUPPORTED\n#endif\n#undef NEED_CHECK_FOR_CPUID\n\n\nstatic\nBoolInt x86cpuid_Func_1(UInt32 *p)\n{\n  CHECK_CPUID_IS_SUPPORTED\n  z7_x86_cpuid(p, 1);\n  return True;\n}\n\n/*\nstatic const UInt32 kVendors[][1] =\n{\n  { 0x756E6547 }, // , 0x49656E69, 0x6C65746E },\n  { 0x68747541 }, // , 0x69746E65, 0x444D4163 },\n  { 0x746E6543 }  // , 0x48727561, 0x736C7561 }\n};\n*/\n\n/*\ntypedef struct\n{\n  UInt32 maxFunc;\n  UInt32 vendor[3];\n  UInt32 ver;\n  UInt32 b;\n  UInt32 c;\n  UInt32 d;\n} Cx86cpuid;\n\nenum\n{\n  CPU_FIRM_INTEL,\n  CPU_FIRM_AMD,\n  CPU_FIRM_VIA\n};\nint x86cpuid_GetFirm(const Cx86cpuid *p);\n#define x86cpuid_ver_GetFamily(ver) (((ver >> 16) & 0xff0) | ((ver >> 8) & 0xf))\n#define x86cpuid_ver_GetModel(ver)  (((ver >> 12) &  0xf0) | ((ver >> 4) & 0xf))\n#define x86cpuid_ver_GetStepping(ver) (ver & 0xf)\n\nint x86cpuid_GetFirm(const Cx86cpuid *p)\n{\n  unsigned i;\n  for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[0]); i++)\n  {\n    const UInt32 *v = kVendors[i];\n    if (v[0] == p->vendor[0]\n        // && v[1] == p->vendor[1]\n        // && v[2] == p->vendor[2]\n        )\n      return (int)i;\n  }\n  return -1;\n}\n\nBoolInt CPU_Is_InOrder()\n{\n  Cx86cpuid p;\n  UInt32 family, model;\n  if (!x86cpuid_CheckAndRead(&p))\n    return True;\n\n  family = x86cpuid_ver_GetFamily(p.ver);\n  model = x86cpuid_ver_GetModel(p.ver);\n\n  switch (x86cpuid_GetFirm(&p))\n  {\n    case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (\n        // In-Order Atom CPU\n           model == 0x1C  // 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330\n        || model == 0x26  // 45 nm, Z6xx\n        || model == 0x27  // 32 nm, Z2460\n        || model == 0x35  // 32 nm, Z2760\n        || model == 0x36  // 32 nm, N2xxx, D2xxx\n        )));\n    case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));\n    case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));\n  }\n  return False; // v23 : unknown processors are not In-Order\n}\n*/\n\n#ifdef _WIN32\n#include \"7zWindows.h\"\n#endif\n\n#if !defined(MY_CPU_AMD64) && defined(_WIN32)\n\n/* for legacy SSE ia32: there is no user-space cpu instruction to check\n   that OS supports SSE register storing/restoring on context switches.\n   So we need some OS-specific function to check that it's safe to use SSE registers.\n*/\n\nZ7_FORCE_INLINE\nstatic BoolInt CPU_Sys_Is_SSE_Supported(void)\n{\n#ifdef _MSC_VER\n  #pragma warning(push)\n  #pragma warning(disable : 4996) // `GetVersion': was declared deprecated\n#endif\n  /* low byte is major version of Windows\n     We suppose that any Windows version since\n     Windows2000 (major == 5) supports SSE registers */\n  return (Byte)GetVersion() >= 5;\n#if defined(_MSC_VER)\n  #pragma warning(pop)\n#endif\n}\n#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;\n#else\n#define CHECK_SYS_SSE_SUPPORT\n#endif\n\n\n#if !defined(MY_CPU_AMD64)\n\nBoolInt CPU_IsSupported_CMOV(void)\n{\n  UInt32 a[4];\n  if (!x86cpuid_Func_1(&a[0]))\n    return 0;\n  return (BoolInt)(a[3] >> 15) & 1;\n}\n\nBoolInt CPU_IsSupported_SSE(void)\n{\n  UInt32 a[4];\n  CHECK_SYS_SSE_SUPPORT\n  if (!x86cpuid_Func_1(&a[0]))\n    return 0;\n  return (BoolInt)(a[3] >> 25) & 1;\n}\n\nBoolInt CPU_IsSupported_SSE2(void)\n{\n  UInt32 a[4];\n  CHECK_SYS_SSE_SUPPORT\n  if (!x86cpuid_Func_1(&a[0]))\n    return 0;\n  return (BoolInt)(a[3] >> 26) & 1;\n}\n\n#endif\n\n\nstatic UInt32 x86cpuid_Func_1_ECX(void)\n{\n  UInt32 a[4];\n  CHECK_SYS_SSE_SUPPORT\n  if (!x86cpuid_Func_1(&a[0]))\n    return 0;\n  return a[2];\n}\n\nBoolInt CPU_IsSupported_AES(void)\n{\n  return (BoolInt)(x86cpuid_Func_1_ECX() >> 25) & 1;\n}\n\nBoolInt CPU_IsSupported_SSSE3(void)\n{\n  return (BoolInt)(x86cpuid_Func_1_ECX() >> 9) & 1;\n}\n\nBoolInt CPU_IsSupported_SSE41(void)\n{\n  return (BoolInt)(x86cpuid_Func_1_ECX() >> 19) & 1;\n}\n\nBoolInt CPU_IsSupported_SHA(void)\n{\n  CHECK_SYS_SSE_SUPPORT\n\n  if (z7_x86_cpuid_GetMaxFunc() < 7)\n    return False;\n  {\n    UInt32 d[4];\n    z7_x86_cpuid(d, 7);\n    return (BoolInt)(d[1] >> 29) & 1;\n  }\n}\n\n\nBoolInt CPU_IsSupported_SHA512(void)\n{\n  if (!CPU_IsSupported_AVX2()) return False; // maybe CPU_IsSupported_AVX() is enough here\n\n  if (z7_x86_cpuid_GetMaxFunc() < 7)\n    return False;\n  {\n    UInt32 d[4];\n    z7_x86_cpuid_subFunc(d, 7, 0);\n    if (d[0] < 1) // d[0] - is max supported subleaf value\n      return False;\n    z7_x86_cpuid_subFunc(d, 7, 1);\n    return (BoolInt)(d[0]) & 1;\n  }\n}\n\n/*\nMSVC: _xgetbv() intrinsic is available since VS2010SP1.\n   MSVC also defines (_XCR_XFEATURE_ENABLED_MASK) macro in\n   <immintrin.h> that we can use or check.\n   For any 32-bit x86 we can use asm code in MSVC,\n   but MSVC asm code is huge after compilation.\n   So _xgetbv() is better\n\nICC: _xgetbv() intrinsic is available (in what version of ICC?)\n   ICC defines (__GNUC___) and it supports gnu assembler\n   also ICC supports MASM style code with -use-msasm switch.\n   but ICC doesn't support __attribute__((__target__))\n\nGCC/CLANG 9:\n  _xgetbv() is macro that works via __builtin_ia32_xgetbv()\n  and we need __attribute__((__target__(\"xsave\")).\n  But with __target__(\"xsave\") the function will be not\n  inlined to function that has no __target__(\"xsave\") attribute.\n  If we want _xgetbv() call inlining, then we should use asm version\n  instead of calling _xgetbv().\n  Note:intrinsic is broke before GCC 8.2:\n    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85684\n*/\n\n#if    defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100) \\\n    || defined(_MSC_VER) && (_MSC_VER >= 1600) && (_MSC_FULL_VER >= 160040219)  \\\n    || defined(__GNUC__) && (__GNUC__ >= 9) \\\n    || defined(__clang__) && (__clang_major__ >= 9)\n// we define ATTRIB_XGETBV, if we want to use predefined _xgetbv() from compiler\n#if defined(__INTEL_COMPILER)\n#define ATTRIB_XGETBV\n#elif defined(__GNUC__) || defined(__clang__)\n// we don't define ATTRIB_XGETBV here, because asm version is better for inlining.\n// #define ATTRIB_XGETBV __attribute__((__target__(\"xsave\")))\n#else\n#define ATTRIB_XGETBV\n#endif\n#endif\n\n#if defined(ATTRIB_XGETBV)\n#include <immintrin.h>\n#endif\n\n\n// XFEATURE_ENABLED_MASK/XCR0\n#define MY_XCR_XFEATURE_ENABLED_MASK 0\n\n#if defined(ATTRIB_XGETBV)\nATTRIB_XGETBV\n#endif\nstatic UInt64 x86_xgetbv_0(UInt32 num)\n{\n#if defined(ATTRIB_XGETBV)\n  {\n    return\n      #if (defined(_MSC_VER))\n        _xgetbv(num);\n      #else\n        __builtin_ia32_xgetbv(\n          #if !defined(__clang__)\n            (int)\n          #endif\n            num);\n      #endif\n  }\n\n#elif defined(__GNUC__) || defined(__clang__) || defined(__SUNPRO_CC)\n\n  UInt32 a, d;\n #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))\n  __asm__\n  (\n    \"xgetbv\"\n    : \"=a\"(a), \"=d\"(d) : \"c\"(num) : \"cc\"\n  );\n #else // is old gcc\n  __asm__\n  (\n    \".byte 0x0f, 0x01, 0xd0\" \"\\n\\t\"\n    : \"=a\"(a), \"=d\"(d) : \"c\"(num) : \"cc\"\n  );\n #endif\n  return ((UInt64)d << 32) | a;\n  // return a;\n\n#elif defined(_MSC_VER) && !defined(MY_CPU_AMD64)\n  \n  UInt32 a, d;\n  __asm {\n    push eax\n    push edx\n    push ecx\n    mov ecx, num;\n    // xor ecx, ecx // = MY_XCR_XFEATURE_ENABLED_MASK\n    _emit 0x0f\n    _emit 0x01\n    _emit 0xd0\n    mov a, eax\n    mov d, edx\n    pop ecx\n    pop edx\n    pop eax\n  }\n  return ((UInt64)d << 32) | a;\n  // return a;\n\n#else // it's unknown compiler\n  // #error \"Need xgetbv function\"\n  UNUSED_VAR(num)\n  // for MSVC-X64 we could call external function from external file.\n  /* Actually we had checked OSXSAVE/AVX in cpuid before.\n     So it's expected that OS supports at least AVX and below. */\n  // if (num != MY_XCR_XFEATURE_ENABLED_MASK) return 0; // if not XCR0\n  return\n      // (1 << 0) |  // x87\n        (1 << 1)   // SSE\n      | (1 << 2);  // AVX\n  \n#endif\n}\n\n#ifdef _WIN32\n/*\n  Windows versions do not know about new ISA extensions that\n  can be introduced. But we still can use new extensions,\n  even if Windows doesn't report about supporting them,\n  But we can use new extensions, only if Windows knows about new ISA extension\n  that changes the number or size of registers: SSE, AVX/XSAVE, AVX512\n  So it's enough to check\n    MY_PF_AVX_INSTRUCTIONS_AVAILABLE\n      instead of\n    MY_PF_AVX2_INSTRUCTIONS_AVAILABLE\n*/\n#define MY_PF_XSAVE_ENABLED                            17\n// #define MY_PF_SSSE3_INSTRUCTIONS_AVAILABLE             36\n// #define MY_PF_SSE4_1_INSTRUCTIONS_AVAILABLE            37\n// #define MY_PF_SSE4_2_INSTRUCTIONS_AVAILABLE            38\n// #define MY_PF_AVX_INSTRUCTIONS_AVAILABLE               39\n// #define MY_PF_AVX2_INSTRUCTIONS_AVAILABLE              40\n// #define MY_PF_AVX512F_INSTRUCTIONS_AVAILABLE           41\n#endif\n\nBoolInt CPU_IsSupported_AVX(void)\n{\n  #ifdef _WIN32\n  if (!IsProcessorFeaturePresent(MY_PF_XSAVE_ENABLED))\n    return False;\n  /* PF_AVX_INSTRUCTIONS_AVAILABLE probably is supported starting from\n     some latest Win10 revisions. But we need AVX in older Windows also.\n     So we don't use the following check: */\n  /*\n  if (!IsProcessorFeaturePresent(MY_PF_AVX_INSTRUCTIONS_AVAILABLE))\n    return False;\n  */\n  #endif\n\n  /*\n    OS must use new special XSAVE/XRSTOR instructions to save\n    AVX registers when it required for context switching.\n    At OS statring:\n      OS sets CR4.OSXSAVE flag to signal the processor that OS supports the XSAVE extensions.\n      Also OS sets bitmask in XCR0 register that defines what\n      registers will be processed by XSAVE instruction:\n        XCR0.SSE[bit 0] - x87 registers and state\n        XCR0.SSE[bit 1] - SSE registers and state\n        XCR0.AVX[bit 2] - AVX registers and state\n    CR4.OSXSAVE is reflected to CPUID.1:ECX.OSXSAVE[bit 27].\n       So we can read that bit in user-space.\n    XCR0 is available for reading in user-space by new XGETBV instruction.\n  */\n  {\n    const UInt32 c = x86cpuid_Func_1_ECX();\n    if (0 == (1\n        & (c >> 28)   // AVX instructions are supported by hardware\n        & (c >> 27))) // OSXSAVE bit: XSAVE and related instructions are enabled by OS.\n      return False;\n  }\n\n  /* also we can check\n     CPUID.1:ECX.XSAVE [bit 26] : that shows that\n        XSAVE, XRESTOR, XSETBV, XGETBV instructions are supported by hardware.\n     But that check is redundant, because if OSXSAVE bit is set, then XSAVE is also set */\n\n  /* If OS have enabled XSAVE extension instructions (OSXSAVE == 1),\n     in most cases we expect that OS also will support storing/restoring\n     for AVX and SSE states at least.\n     But to be ensure for that we call user-space instruction\n     XGETBV(0) to get XCR0 value that contains bitmask that defines\n     what exact states(registers) OS have enabled for storing/restoring.\n  */\n\n  {\n    const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);\n    // printf(\"\\n=== XGetBV=0x%x\\n\", bm);\n    return 1\n        & (BoolInt)(bm >> 1)  // SSE state is supported (set by OS) for storing/restoring\n        & (BoolInt)(bm >> 2); // AVX state is supported (set by OS) for storing/restoring\n  }\n  // since Win7SP1: we can use GetEnabledXStateFeatures();\n}\n\n\nBoolInt CPU_IsSupported_AVX2(void)\n{\n  if (!CPU_IsSupported_AVX())\n    return False;\n  if (z7_x86_cpuid_GetMaxFunc() < 7)\n    return False;\n  {\n    UInt32 d[4];\n    z7_x86_cpuid(d, 7);\n    // printf(\"\\ncpuid(7): ebx=%8x ecx=%8x\\n\", d[1], d[2]);\n    return 1\n      & (BoolInt)(d[1] >> 5); // avx2\n  }\n}\n\n#if 0\nBoolInt CPU_IsSupported_AVX512F_AVX512VL(void)\n{\n  if (!CPU_IsSupported_AVX())\n    return False;\n  if (z7_x86_cpuid_GetMaxFunc() < 7)\n    return False;\n  {\n    UInt32 d[4];\n    BoolInt v;\n    z7_x86_cpuid(d, 7);\n    // printf(\"\\ncpuid(7): ebx=%8x ecx=%8x\\n\", d[1], d[2]);\n    v = 1\n      & (BoolInt)(d[1] >> 16)  // avx512f\n      & (BoolInt)(d[1] >> 31); // avx512vl\n    if (!v)\n      return False;\n  }\n  {\n    const UInt32 bm = (UInt32)x86_xgetbv_0(MY_XCR_XFEATURE_ENABLED_MASK);\n    // printf(\"\\n=== XGetBV=0x%x\\n\", bm);\n    return 1\n        & (BoolInt)(bm >> 5)  // OPMASK\n        & (BoolInt)(bm >> 6)  // ZMM upper 256-bit\n        & (BoolInt)(bm >> 7); // ZMM16 ... ZMM31\n  }\n}\n#endif\n\nBoolInt CPU_IsSupported_VAES_AVX2(void)\n{\n  if (!CPU_IsSupported_AVX())\n    return False;\n  if (z7_x86_cpuid_GetMaxFunc() < 7)\n    return False;\n  {\n    UInt32 d[4];\n    z7_x86_cpuid(d, 7);\n    // printf(\"\\ncpuid(7): ebx=%8x ecx=%8x\\n\", d[1], d[2]);\n    return 1\n      & (BoolInt)(d[1] >> 5) // avx2\n      // & (d[1] >> 31) // avx512vl\n      & (BoolInt)(d[2] >> 9); // vaes // VEX-256/EVEX\n  }\n}\n\nBoolInt CPU_IsSupported_PageGB(void)\n{\n  CHECK_CPUID_IS_SUPPORTED\n  {\n    UInt32 d[4];\n    z7_x86_cpuid(d, 0x80000000);\n    if (d[0] < 0x80000001)\n      return False;\n    z7_x86_cpuid(d, 0x80000001);\n    return (BoolInt)(d[3] >> 26) & 1;\n  }\n}\n\n\n#elif defined(MY_CPU_ARM_OR_ARM64)\n\n#ifdef _WIN32\n\n#include \"7zWindows.h\"\n\nBoolInt CPU_IsSupported_CRC32(void)  { return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }\nBoolInt CPU_IsSupported_CRYPTO(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }\nBoolInt CPU_IsSupported_NEON(void)   { return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) ? 1 : 0; }\n\n#else\n\n#if defined(__APPLE__)\n\n/*\n#include <stdio.h>\n#include <string.h>\nstatic void Print_sysctlbyname(const char *name)\n{\n  size_t bufSize = 256;\n  char buf[256];\n  int res = sysctlbyname(name, &buf, &bufSize, NULL, 0);\n  {\n    int i;\n    printf(\"\\nres = %d : %s : '%s' : bufSize = %d, numeric\", res, name, buf, (unsigned)bufSize);\n    for (i = 0; i < 20; i++)\n      printf(\" %2x\", (unsigned)(Byte)buf[i]);\n\n  }\n}\n*/\n/*\n  Print_sysctlbyname(\"hw.pagesize\");\n  Print_sysctlbyname(\"machdep.cpu.brand_string\");\n*/\n\nstatic BoolInt z7_sysctlbyname_Get_BoolInt(const char *name)\n{\n  UInt32 val = 0;\n  if (z7_sysctlbyname_Get_UInt32(name, &val) == 0 && val == 1)\n    return 1;\n  return 0;\n}\n\nBoolInt CPU_IsSupported_CRC32(void)\n{\n  return z7_sysctlbyname_Get_BoolInt(\"hw.optional.armv8_crc32\");\n}\n\nBoolInt CPU_IsSupported_NEON(void)\n{\n  return z7_sysctlbyname_Get_BoolInt(\"hw.optional.neon\");\n}\n\nBoolInt CPU_IsSupported_SHA512(void)\n{\n  return z7_sysctlbyname_Get_BoolInt(\"hw.optional.armv8_2_sha512\");\n}\n\n/*\nBoolInt CPU_IsSupported_SHA3(void)\n{\n  return z7_sysctlbyname_Get_BoolInt(\"hw.optional.armv8_2_sha3\");\n}\n*/\n\n#ifdef MY_CPU_ARM64\n#define APPLE_CRYPTO_SUPPORT_VAL 1\n#else\n#define APPLE_CRYPTO_SUPPORT_VAL 0\n#endif\n\nBoolInt CPU_IsSupported_SHA1(void) { return APPLE_CRYPTO_SUPPORT_VAL; }\nBoolInt CPU_IsSupported_SHA2(void) { return APPLE_CRYPTO_SUPPORT_VAL; }\nBoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }\n\n\n#else // __APPLE__\n\n#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)\n  #define Z7_GETAUXV_AVAILABLE\n#elif !defined(__QNXNTO__)\n// #pragma message(\"=== is not NEW GLIBC === \")\n  #if defined __has_include\n  #if __has_include (<sys/auxv.h>)\n// #pragma message(\"=== sys/auxv.h is avail=== \")\n    #define Z7_GETAUXV_AVAILABLE\n  #endif\n  #endif\n#endif\n\n#ifdef Z7_GETAUXV_AVAILABLE\n// #pragma message(\"=== Z7_GETAUXV_AVAILABLE === \")\n#include <sys/auxv.h>\n#define USE_HWCAP\n#endif\n\n#ifdef USE_HWCAP\n\n#if defined(__FreeBSD__) || defined(__OpenBSD__)\nstatic unsigned long MY_getauxval(int aux)\n{\n  unsigned long val;\n  if (elf_aux_info(aux, &val, sizeof(val)))\n    return 0;\n  return val;\n}\n#else\n#define MY_getauxval  getauxval\n  #if defined __has_include\n  #if __has_include (<asm/hwcap.h>)\n#include <asm/hwcap.h>\n  #endif\n  #endif\n#endif\n\n  #define MY_HWCAP_CHECK_FUNC_2(name1, name2) \\\n  BoolInt CPU_IsSupported_ ## name1(void) { return (MY_getauxval(AT_HWCAP)  & (HWCAP_  ## name2)); }\n\n#ifdef MY_CPU_ARM64\n  #define MY_HWCAP_CHECK_FUNC(name) \\\n  MY_HWCAP_CHECK_FUNC_2(name, name)\n#if 1 || defined(__ARM_NEON)\n  BoolInt CPU_IsSupported_NEON(void) { return True; }\n#else\n  MY_HWCAP_CHECK_FUNC_2(NEON, ASIMD)\n#endif\n// MY_HWCAP_CHECK_FUNC (ASIMD)\n#elif defined(MY_CPU_ARM)\n  #define MY_HWCAP_CHECK_FUNC(name) \\\n  BoolInt CPU_IsSupported_ ## name(void) { return (MY_getauxval(AT_HWCAP2) & (HWCAP2_ ## name)); }\n  MY_HWCAP_CHECK_FUNC_2(NEON, NEON)\n#endif\n\n#else // USE_HWCAP\n\n  #define MY_HWCAP_CHECK_FUNC(name) \\\n  BoolInt CPU_IsSupported_ ## name(void) { return 0; }\n#if defined(__ARM_NEON)\n  BoolInt CPU_IsSupported_NEON(void) { return True; }\n#else\n  MY_HWCAP_CHECK_FUNC(NEON)\n#endif\n\n#endif // USE_HWCAP\n\nMY_HWCAP_CHECK_FUNC (CRC32)\nMY_HWCAP_CHECK_FUNC (SHA1)\nMY_HWCAP_CHECK_FUNC (SHA2)\nMY_HWCAP_CHECK_FUNC (AES)\n#ifdef MY_CPU_ARM64\n// <hwcap.h> supports HWCAP_SHA512 and HWCAP_SHA3 since 2017.\n// we define them here, if they are not defined\n#ifndef HWCAP_SHA3\n// #define HWCAP_SHA3    (1 << 17)\n#endif\n#ifndef HWCAP_SHA512\n// #pragma message(\"=== HWCAP_SHA512 define === \")\n#define HWCAP_SHA512  (1 << 21)\n#endif\nMY_HWCAP_CHECK_FUNC (SHA512)\n// MY_HWCAP_CHECK_FUNC (SHA3)\n#endif\n\n#endif // __APPLE__\n#endif // _WIN32\n\n#endif // MY_CPU_ARM_OR_ARM64\n\n\n\n#ifdef __APPLE__\n\n#include <sys/sysctl.h>\n\nint z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize)\n{\n  return sysctlbyname(name, buf, bufSize, NULL, 0);\n}\n\nint z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val)\n{\n  size_t bufSize = sizeof(*val);\n  const int res = z7_sysctlbyname_Get(name, val, &bufSize);\n  if (res == 0 && bufSize != sizeof(*val))\n    return EFAULT;\n  return res;\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/CpuArch.h",
    "content": "﻿/* CpuArch.h -- CPU specific code\nIgor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_CPU_ARCH_H\n#define ZIP7_INC_CPU_ARCH_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n/*\nMY_CPU_LE means that CPU is LITTLE ENDIAN.\nMY_CPU_BE means that CPU is BIG ENDIAN.\nIf MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.\n\nMY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.\n\nMY_CPU_64BIT means that processor can work with 64-bit registers.\n  MY_CPU_64BIT can be used to select fast code branch\n  MY_CPU_64BIT doesn't mean that (sizeof(void *) == 8)\n*/\n\n#if !defined(_M_ARM64EC)\n#if  defined(_M_X64) \\\n  || defined(_M_AMD64) \\\n  || defined(__x86_64__) \\\n  || defined(__AMD64__) \\\n  || defined(__amd64__)\n  #define MY_CPU_AMD64\n  #ifdef __ILP32__\n    #define MY_CPU_NAME \"x32\"\n    #define MY_CPU_SIZEOF_POINTER 4\n  #else\n    #if defined(__APX_EGPR__) || defined(__EGPR__)\n      #define MY_CPU_NAME \"x64-apx\"\n      #define MY_CPU_AMD64_APX\n    #else\n      #define MY_CPU_NAME \"x64\"\n    #endif\n    #define MY_CPU_SIZEOF_POINTER 8\n  #endif\n  #define MY_CPU_64BIT\n#endif\n#endif\n\n\n#if  defined(_M_IX86) \\\n  || defined(__i386__)\n  #define MY_CPU_X86\n  #define MY_CPU_NAME \"x86\"\n  /* #define MY_CPU_32BIT */\n  #define MY_CPU_SIZEOF_POINTER 4\n#endif\n\n#if defined(__SSE2__) \\\n    || defined(MY_CPU_AMD64) \\\n    || defined(_M_IX86_FP) && (_M_IX86_FP >= 2)\n#define MY_CPU_SSE2\n#endif\n\n\n#if  defined(_M_ARM64) \\\n  || defined(_M_ARM64EC) \\\n  || defined(__AARCH64EL__) \\\n  || defined(__AARCH64EB__) \\\n  || defined(__aarch64__)\n  #define MY_CPU_ARM64\n#if   defined(__ILP32__) \\\n   || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)\n    #define MY_CPU_NAME \"arm64-32\"\n    #define MY_CPU_SIZEOF_POINTER 4\n#elif defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 16)\n    #define MY_CPU_NAME \"arm64-128\"\n    #define MY_CPU_SIZEOF_POINTER 16\n#else\n#if defined(_M_ARM64EC)\n    #define MY_CPU_NAME \"arm64ec\"\n#else\n    #define MY_CPU_NAME \"arm64\"\n#endif\n    #define MY_CPU_SIZEOF_POINTER 8\n#endif\n  #define MY_CPU_64BIT\n#endif\n\n\n#if  defined(_M_ARM) \\\n  || defined(_M_ARM_NT) \\\n  || defined(_M_ARMT) \\\n  || defined(__arm__) \\\n  || defined(__thumb__) \\\n  || defined(__ARMEL__) \\\n  || defined(__ARMEB__) \\\n  || defined(__THUMBEL__) \\\n  || defined(__THUMBEB__)\n  #define MY_CPU_ARM\n\n  #if defined(__thumb__) || defined(__THUMBEL__) || defined(_M_ARMT)\n    #define MY_CPU_ARMT\n    #define MY_CPU_NAME \"armt\"\n  #else\n    #define MY_CPU_ARM32\n    #define MY_CPU_NAME \"arm\"\n  #endif\n  /* #define MY_CPU_32BIT */\n  #define MY_CPU_SIZEOF_POINTER 4\n#endif\n\n\n#if  defined(_M_IA64) \\\n  || defined(__ia64__)\n  #define MY_CPU_IA64\n  #define MY_CPU_NAME \"ia64\"\n  #define MY_CPU_64BIT\n#endif\n\n\n#if  defined(__mips64) \\\n  || defined(__mips64__) \\\n  || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))\n  #define MY_CPU_NAME \"mips64\"\n  #define MY_CPU_64BIT\n#elif defined(__mips__)\n  #define MY_CPU_NAME \"mips\"\n  /* #define MY_CPU_32BIT */\n#endif\n\n\n#if  defined(__ppc64__) \\\n  || defined(__powerpc64__) \\\n  || defined(__ppc__) \\\n  || defined(__powerpc__) \\\n  || defined(__PPC__) \\\n  || defined(_POWER)\n\n#define MY_CPU_PPC_OR_PPC64\n\n#if  defined(__ppc64__) \\\n  || defined(__powerpc64__) \\\n  || defined(_LP64) \\\n  || defined(__64BIT__)\n  #ifdef __ILP32__\n    #define MY_CPU_NAME \"ppc64-32\"\n    #define MY_CPU_SIZEOF_POINTER 4\n  #else\n    #define MY_CPU_NAME \"ppc64\"\n    #define MY_CPU_SIZEOF_POINTER 8\n  #endif\n  #define MY_CPU_64BIT\n#else\n  #define MY_CPU_NAME \"ppc\"\n  #define MY_CPU_SIZEOF_POINTER 4\n  /* #define MY_CPU_32BIT */\n#endif\n#endif\n\n\n#if   defined(__sparc__) \\\n   || defined(__sparc)\n  #define MY_CPU_SPARC\n  #if  defined(__LP64__) \\\n    || defined(_LP64) \\\n    || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)\n    #define MY_CPU_NAME \"sparcv9\"\n    #define MY_CPU_SIZEOF_POINTER 8\n    #define MY_CPU_64BIT\n  #elif defined(__sparc_v9__) \\\n     || defined(__sparcv9)\n    #define MY_CPU_64BIT\n    #if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)\n      #define MY_CPU_NAME \"sparcv9-32\"\n    #else\n      #define MY_CPU_NAME \"sparcv9m\"\n    #endif\n  #elif defined(__sparc_v8__) \\\n     || defined(__sparcv8)\n    #define MY_CPU_NAME \"sparcv8\"\n    #define MY_CPU_SIZEOF_POINTER 4\n  #else\n    #define MY_CPU_NAME \"sparc\"\n  #endif\n#endif\n\n\n#if  defined(__riscv) \\\n  || defined(__riscv__)\n    #define MY_CPU_RISCV\n  #if __riscv_xlen == 32\n    #define MY_CPU_NAME \"riscv32\"\n  #elif __riscv_xlen == 64\n    #define MY_CPU_NAME \"riscv64\"\n  #else\n    #define MY_CPU_NAME \"riscv\"\n  #endif\n#endif\n\n\n#if defined(__loongarch__)\n  #define MY_CPU_LOONGARCH\n  #if defined(__loongarch64) || defined(__loongarch_grlen) && (__loongarch_grlen == 64)\n  #define MY_CPU_64BIT\n  #endif\n  #if defined(__loongarch64)\n  #define MY_CPU_NAME \"loongarch64\"\n  #define MY_CPU_LOONGARCH64\n  #else\n  #define MY_CPU_NAME \"loongarch\"\n  #endif\n#endif\n\n\n// #undef MY_CPU_NAME\n// #undef MY_CPU_SIZEOF_POINTER\n// #define __e2k__\n// #define __SIZEOF_POINTER__ 4\n#if  defined(__e2k__)\n  #define MY_CPU_E2K\n  #if defined(__ILP32__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 4)\n    #define MY_CPU_NAME \"e2k-32\"\n    #define MY_CPU_SIZEOF_POINTER 4\n  #else\n    #define MY_CPU_NAME \"e2k\"\n    #if defined(__LP64__) || defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ == 8)\n      #define MY_CPU_SIZEOF_POINTER 8\n    #endif\n  #endif\n  #define MY_CPU_64BIT\n#endif\n\n\n#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)\n#define MY_CPU_X86_OR_AMD64\n#endif\n\n#if defined(MY_CPU_ARM) || defined(MY_CPU_ARM64)\n#define MY_CPU_ARM_OR_ARM64\n#endif\n\n\n#ifdef _WIN32\n\n  #ifdef MY_CPU_ARM\n  #define MY_CPU_ARM_LE\n  #endif\n\n  #ifdef MY_CPU_ARM64\n  #define MY_CPU_ARM64_LE\n  #endif\n\n  #ifdef _M_IA64\n  #define MY_CPU_IA64_LE\n  #endif\n\n#endif\n\n\n#if defined(MY_CPU_X86_OR_AMD64) \\\n    || defined(MY_CPU_ARM_LE) \\\n    || defined(MY_CPU_ARM64_LE) \\\n    || defined(MY_CPU_IA64_LE) \\\n    || defined(_LITTLE_ENDIAN) \\\n    || defined(__LITTLE_ENDIAN__) \\\n    || defined(__ARMEL__) \\\n    || defined(__THUMBEL__) \\\n    || defined(__AARCH64EL__) \\\n    || defined(__MIPSEL__) \\\n    || defined(__MIPSEL) \\\n    || defined(_MIPSEL) \\\n    || defined(__BFIN__) \\\n    || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))\n  #define MY_CPU_LE\n#endif\n\n#if defined(__BIG_ENDIAN__) \\\n    || defined(__ARMEB__) \\\n    || defined(__THUMBEB__) \\\n    || defined(__AARCH64EB__) \\\n    || defined(__MIPSEB__) \\\n    || defined(__MIPSEB) \\\n    || defined(_MIPSEB) \\\n    || defined(__m68k__) \\\n    || defined(__s390__) \\\n    || defined(__s390x__) \\\n    || defined(__zarch__) \\\n    || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))\n  #define MY_CPU_BE\n#endif\n\n\n#if defined(MY_CPU_LE) && defined(MY_CPU_BE)\n  #error Stop_Compiling_Bad_Endian\n#endif\n\n#if !defined(MY_CPU_LE) && !defined(MY_CPU_BE)\n  #error Stop_Compiling_CPU_ENDIAN_must_be_detected_at_compile_time\n#endif\n\n#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)\n  #error Stop_Compiling_Bad_32_64_BIT\n#endif\n\n#ifdef __SIZEOF_POINTER__\n  #ifdef MY_CPU_SIZEOF_POINTER\n    #if MY_CPU_SIZEOF_POINTER != __SIZEOF_POINTER__\n      #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE\n    #endif\n  #else\n    #define MY_CPU_SIZEOF_POINTER  __SIZEOF_POINTER__\n  #endif\n#endif\n\n#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)\n#if defined (_LP64)\n      #error Stop_Compiling_Bad_MY_CPU_PTR_SIZE\n#endif\n#endif\n\n#ifdef _MSC_VER\n  #if _MSC_VER >= 1300\n    #define MY_CPU_pragma_pack_push_1   __pragma(pack(push, 1))\n    #define MY_CPU_pragma_pop           __pragma(pack(pop))\n  #else\n    #define MY_CPU_pragma_pack_push_1\n    #define MY_CPU_pragma_pop\n  #endif\n#else\n  #ifdef __xlC__\n    #define MY_CPU_pragma_pack_push_1   _Pragma(\"pack(1)\")\n    #define MY_CPU_pragma_pop           _Pragma(\"pack()\")\n  #else\n    #define MY_CPU_pragma_pack_push_1   _Pragma(\"pack(push, 1)\")\n    #define MY_CPU_pragma_pop           _Pragma(\"pack(pop)\")\n  #endif\n#endif\n\n\n#ifndef MY_CPU_NAME\n  // #define MY_CPU_IS_UNKNOWN\n  #ifdef MY_CPU_LE\n    #define MY_CPU_NAME \"LE\"\n  #elif defined(MY_CPU_BE)\n    #define MY_CPU_NAME \"BE\"\n  #else\n    /*\n    #define MY_CPU_NAME \"\"\n    */\n  #endif\n#endif\n\n\n\n\n\n#ifdef __has_builtin\n  #define Z7_has_builtin(x)  __has_builtin(x)\n#else\n  #define Z7_has_builtin(x)  0\n#endif\n\n\n#define Z7_BSWAP32_CONST(v) \\\n       ( (((UInt32)(v) << 24)                   ) \\\n       | (((UInt32)(v) <<  8) & (UInt32)0xff0000) \\\n       | (((UInt32)(v) >>  8) & (UInt32)0xff00  ) \\\n       | (((UInt32)(v) >> 24)                   ))\n\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1300)\n\n#include <stdlib.h>\n\n/* Note: these macros will use bswap instruction (486), that is unsupported in 386 cpu */\n\n#pragma intrinsic(_byteswap_ushort)\n#pragma intrinsic(_byteswap_ulong)\n#pragma intrinsic(_byteswap_uint64)\n\n#define Z7_BSWAP16(v)  _byteswap_ushort(v)\n#define Z7_BSWAP32(v)  _byteswap_ulong (v)\n#define Z7_BSWAP64(v)  _byteswap_uint64(v)\n#define Z7_CPU_FAST_BSWAP_SUPPORTED\n\n/* GCC can generate slow code that calls function for __builtin_bswap32() for:\n     - GCC for RISCV, if Zbb/XTHeadBb extension is not used.\n     - GCC for SPARC.\n   The code from CLANG for SPARC also is not fastest.\n   So we don't define Z7_CPU_FAST_BSWAP_SUPPORTED in some cases.\n*/\n#elif (!defined(MY_CPU_RISCV) || defined (__riscv_zbb) || defined(__riscv_xtheadbb)) \\\n    && !defined(MY_CPU_SPARC) \\\n    && ( \\\n       (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \\\n    || (defined(__clang__) && Z7_has_builtin(__builtin_bswap16)) \\\n    )\n\n#define Z7_BSWAP16(v)  __builtin_bswap16(v)\n#define Z7_BSWAP32(v)  __builtin_bswap32(v)\n#define Z7_BSWAP64(v)  __builtin_bswap64(v)\n#define Z7_CPU_FAST_BSWAP_SUPPORTED\n\n#else\n\n#define Z7_BSWAP16(v) ((UInt16) \\\n       ( ((UInt32)(v) << 8) \\\n       | ((UInt32)(v) >> 8) \\\n       ))\n\n#define Z7_BSWAP32(v) Z7_BSWAP32_CONST(v)\n\n#define Z7_BSWAP64(v) \\\n       ( ( ( (UInt64)(v)                           ) << 8 * 7 ) \\\n       | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 1) ) << 8 * 5 ) \\\n       | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 2) ) << 8 * 3 ) \\\n       | ( ( (UInt64)(v) & ((UInt32)0xff << 8 * 3) ) << 8 * 1 ) \\\n       | ( ( (UInt64)(v) >> 8 * 1 ) & ((UInt32)0xff << 8 * 3) ) \\\n       | ( ( (UInt64)(v) >> 8 * 3 ) & ((UInt32)0xff << 8 * 2) ) \\\n       | ( ( (UInt64)(v) >> 8 * 5 ) & ((UInt32)0xff << 8 * 1) ) \\\n       | ( ( (UInt64)(v) >> 8 * 7 )                           ) \\\n       )\n\n#endif\n\n\n\n#ifdef MY_CPU_LE\n  #if defined(MY_CPU_X86_OR_AMD64) \\\n      || defined(MY_CPU_ARM64) \\\n      || defined(MY_CPU_RISCV) && defined(__riscv_misaligned_fast) \\\n      || defined(MY_CPU_E2K) && defined(__iset__) && (__iset__ >= 6)\n    #define MY_CPU_LE_UNALIGN\n    #define MY_CPU_LE_UNALIGN_64\n  #elif defined(__ARM_FEATURE_UNALIGNED)\n/* === ALIGNMENT on 32-bit arm and LDRD/STRD/LDM/STM instructions.\n  Description of problems:\nproblem-1 : 32-bit ARM architecture:\n  multi-access (pair of 32-bit accesses) instructions (LDRD/STRD/LDM/STM)\n  require 32-bit (WORD) alignment (by 32-bit ARM architecture).\n  So there is \"Alignment fault exception\", if data is not aligned for 32-bit.\n\nproblem-2 : 32-bit kernels and arm64 kernels:\n  32-bit linux kernels provide fixup for these \"paired\" instruction \"Alignment fault exception\".\n  So unaligned paired-access instructions work via exception handler in kernel in 32-bit linux.\n \n  But some arm64 kernels do not handle these faults in 32-bit programs.\n  So we have unhandled exception for such instructions.\n  Probably some new arm64 kernels have fixed it, and unaligned\n  paired-access instructions work in new kernels?\n\nproblem-3 : compiler for 32-bit arm:\n  Compilers use LDRD/STRD/LDM/STM for UInt64 accesses\n  and for another cases where two 32-bit accesses are fused\n  to one multi-access instruction.\n  So UInt64 variables must be aligned for 32-bit, and each\n  32-bit access must be aligned for 32-bit, if we want to\n  avoid \"Alignment fault\" exception (handled or unhandled).\n\nproblem-4 : performace:\n  Even if unaligned access is handled by kernel, it will be slow.\n  So if we allow unaligned access, we can get fast unaligned\n  single-access, and slow unaligned paired-access.\n\n  We don't allow unaligned access on 32-bit arm, because compiler\n  genarates paired-access instructions that require 32-bit alignment,\n  and some arm64 kernels have no handler for these instructions.\n  Also unaligned paired-access instructions will be slow, if kernel handles them.\n*/\n    // it must be disabled:\n    // #define MY_CPU_LE_UNALIGN\n  #endif\n#endif\n\n\n#ifdef MY_CPU_LE_UNALIGN\n\n#define GetUi16(p) (*(const UInt16 *)(const void *)(p))\n#define GetUi32(p) (*(const UInt32 *)(const void *)(p))\n#ifdef MY_CPU_LE_UNALIGN_64\n#define GetUi64(p) (*(const UInt64 *)(const void *)(p))\n#define SetUi64(p, v) { *(UInt64 *)(void *)(p) = (v); }\n#endif\n\n#define SetUi16(p, v) { *(UInt16 *)(void *)(p) = (v); }\n#define SetUi32(p, v) { *(UInt32 *)(void *)(p) = (v); }\n\n#else\n\n#define GetUi16(p) ( (UInt16) ( \\\n             ((const Byte *)(p))[0] | \\\n    ((UInt16)((const Byte *)(p))[1] << 8) ))\n\n#define GetUi32(p) ( \\\n             ((const Byte *)(p))[0]        | \\\n    ((UInt32)((const Byte *)(p))[1] <<  8) | \\\n    ((UInt32)((const Byte *)(p))[2] << 16) | \\\n    ((UInt32)((const Byte *)(p))[3] << 24))\n\n#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \\\n    _ppp_[0] = (Byte)_vvv_; \\\n    _ppp_[1] = (Byte)(_vvv_ >> 8); }\n\n#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \\\n    _ppp_[0] = (Byte)_vvv_; \\\n    _ppp_[1] = (Byte)(_vvv_ >> 8); \\\n    _ppp_[2] = (Byte)(_vvv_ >> 16); \\\n    _ppp_[3] = (Byte)(_vvv_ >> 24); }\n\n#endif\n\n\n#ifndef GetUi64\n#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))\n#endif\n\n#ifndef SetUi64\n#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \\\n    SetUi32(_ppp2_    , (UInt32)_vvv2_) \\\n    SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)) }\n#endif\n\n\n#if defined(MY_CPU_LE_UNALIGN) && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)\n\n#if 0\n// Z7_BSWAP16 can be slow for x86-msvc\n#define GetBe16_to32(p)  (Z7_BSWAP16 (*(const UInt16 *)(const void *)(p)))\n#else\n#define GetBe16_to32(p)  (Z7_BSWAP32 (*(const UInt16 *)(const void *)(p)) >> 16)\n#endif\n\n#define GetBe32(p)  Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))\n#define SetBe32(p, v) { (*(UInt32 *)(void *)(p)) = Z7_BSWAP32(v); }\n\n#if defined(MY_CPU_LE_UNALIGN_64)\n#define GetBe64(p)  Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))\n#define SetBe64(p, v) { (*(UInt64 *)(void *)(p)) = Z7_BSWAP64(v); }\n#endif\n\n#else\n\n#define GetBe32(p) ( \\\n    ((UInt32)((const Byte *)(p))[0] << 24) | \\\n    ((UInt32)((const Byte *)(p))[1] << 16) | \\\n    ((UInt32)((const Byte *)(p))[2] <<  8) | \\\n             ((const Byte *)(p))[3] )\n\n#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \\\n    _ppp_[0] = (Byte)(_vvv_ >> 24); \\\n    _ppp_[1] = (Byte)(_vvv_ >> 16); \\\n    _ppp_[2] = (Byte)(_vvv_ >> 8); \\\n    _ppp_[3] = (Byte)_vvv_; }\n\n#endif\n\n#ifndef GetBe64\n#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))\n#endif\n\n#ifndef SetBe64\n#define SetBe64(p, v) { Byte *_ppp_ = (Byte *)(p); UInt64 _vvv_ = (v); \\\n    _ppp_[0] = (Byte)(_vvv_ >> 56); \\\n    _ppp_[1] = (Byte)(_vvv_ >> 48); \\\n    _ppp_[2] = (Byte)(_vvv_ >> 40); \\\n    _ppp_[3] = (Byte)(_vvv_ >> 32); \\\n    _ppp_[4] = (Byte)(_vvv_ >> 24); \\\n    _ppp_[5] = (Byte)(_vvv_ >> 16); \\\n    _ppp_[6] = (Byte)(_vvv_ >> 8); \\\n    _ppp_[7] = (Byte)_vvv_; }\n#endif\n\n#ifndef GetBe16\n#ifdef GetBe16_to32\n#define GetBe16(p) ( (UInt16) GetBe16_to32(p))\n#else\n#define GetBe16(p) ( (UInt16) ( \\\n    ((UInt16)((const Byte *)(p))[0] << 8) | \\\n             ((const Byte *)(p))[1] ))\n#endif\n#endif\n\n\n#if defined(MY_CPU_BE)\n#define Z7_CONV_BE_TO_NATIVE_CONST32(v)  (v)\n#define Z7_CONV_LE_TO_NATIVE_CONST32(v)  Z7_BSWAP32_CONST(v)\n#define Z7_CONV_NATIVE_TO_BE_32(v)       (v)\n// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1)  ((b1) | ((b0) << 8))\n#elif defined(MY_CPU_LE)\n#define Z7_CONV_BE_TO_NATIVE_CONST32(v)  Z7_BSWAP32_CONST(v)\n#define Z7_CONV_LE_TO_NATIVE_CONST32(v)  (v)\n#define Z7_CONV_NATIVE_TO_BE_32(v)       Z7_BSWAP32(v)\n// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1)  ((b0) | ((b1) << 8))\n#else\n#error Stop_Compiling_Unknown_Endian_CONV\n#endif\n\n\n#if defined(MY_CPU_BE)\n\n#define GetBe64a(p)      (*(const UInt64 *)(const void *)(p))\n#define GetBe32a(p)      (*(const UInt32 *)(const void *)(p))\n#define GetBe16a(p)      (*(const UInt16 *)(const void *)(p))\n#define SetBe32a(p, v)   { *(UInt32 *)(void *)(p) = (v); }\n#define SetBe16a(p, v)   { *(UInt16 *)(void *)(p) = (v); }\n\n// gcc and clang for powerpc can transform load byte access to load reverse word access.\n// sp we can use byte access instead of word access. Z7_BSWAP64 cab be slow\n#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_64BIT)\n#define GetUi64a(p)   Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))\n#else\n#define GetUi64a(p)      GetUi64(p)\n#endif\n\n#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)\n#define GetUi32a(p)   Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))\n#else\n#define GetUi32a(p)      GetUi32(p)\n#endif\n\n#define GetUi16a(p)      GetUi16(p)\n#define SetUi32a(p, v)   SetUi32(p, v)\n#define SetUi16a(p, v)   SetUi16(p, v)\n\n#elif defined(MY_CPU_LE)\n\n#define GetUi64a(p)      (*(const UInt64 *)(const void *)(p))\n#define GetUi32a(p)      (*(const UInt32 *)(const void *)(p))\n#define GetUi16a(p)      (*(const UInt16 *)(const void *)(p))\n#define SetUi32a(p, v)   { *(UInt32 *)(void *)(p) = (v); }\n#define SetUi16a(p, v)   { *(UInt16 *)(void *)(p) = (v); }\n\n#define GetBe64a(p)      GetBe64(p)\n#define GetBe32a(p)      GetBe32(p)\n#define GetBe16a(p)      GetBe16(p)\n#define SetBe32a(p, v)   SetBe32(p, v)\n#define SetBe16a(p, v)   SetBe16(p, v)\n\n#else\n#error Stop_Compiling_Unknown_Endian_CPU_a\n#endif\n\n\n#ifndef GetBe16_to32\n#define GetBe16_to32(p) GetBe16(p)\n#endif\n\n\n#if defined(MY_CPU_X86_OR_AMD64) \\\n  || defined(MY_CPU_ARM_OR_ARM64) \\\n  || defined(MY_CPU_PPC_OR_PPC64)\n  #define Z7_CPU_FAST_ROTATE_SUPPORTED\n#endif\n\n\n#ifdef MY_CPU_X86_OR_AMD64\n\nvoid Z7_FASTCALL z7_x86_cpuid(UInt32 a[4], UInt32 function);\nUInt32 Z7_FASTCALL z7_x86_cpuid_GetMaxFunc(void);\n#if defined(MY_CPU_AMD64)\n#define Z7_IF_X86_CPUID_SUPPORTED\n#else\n#define Z7_IF_X86_CPUID_SUPPORTED if (z7_x86_cpuid_GetMaxFunc())\n#endif\n\nBoolInt CPU_IsSupported_AES(void);\nBoolInt CPU_IsSupported_AVX(void);\nBoolInt CPU_IsSupported_AVX2(void);\nBoolInt CPU_IsSupported_AVX512F_AVX512VL(void);\nBoolInt CPU_IsSupported_VAES_AVX2(void);\nBoolInt CPU_IsSupported_CMOV(void);\nBoolInt CPU_IsSupported_SSE(void);\nBoolInt CPU_IsSupported_SSE2(void);\nBoolInt CPU_IsSupported_SSSE3(void);\nBoolInt CPU_IsSupported_SSE41(void);\nBoolInt CPU_IsSupported_SHA(void);\nBoolInt CPU_IsSupported_SHA512(void);\nBoolInt CPU_IsSupported_PageGB(void);\n\n#elif defined(MY_CPU_ARM_OR_ARM64)\n\nBoolInt CPU_IsSupported_CRC32(void);\nBoolInt CPU_IsSupported_NEON(void);\n\n#if defined(_WIN32)\nBoolInt CPU_IsSupported_CRYPTO(void);\n#define CPU_IsSupported_SHA1  CPU_IsSupported_CRYPTO\n#define CPU_IsSupported_SHA2  CPU_IsSupported_CRYPTO\n#define CPU_IsSupported_AES   CPU_IsSupported_CRYPTO\n#else\nBoolInt CPU_IsSupported_SHA1(void);\nBoolInt CPU_IsSupported_SHA2(void);\nBoolInt CPU_IsSupported_AES(void);\n#endif\nBoolInt CPU_IsSupported_SHA512(void);\n\n#endif\n\n#if defined(__APPLE__)\nint z7_sysctlbyname_Get(const char *name, void *buf, size_t *bufSize);\nint z7_sysctlbyname_Get_UInt32(const char *name, UInt32 *val);\n#endif\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Delta.c",
    "content": "﻿/* Delta.c -- Delta converter\n2021-02-09 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Delta.h\"\n\nvoid Delta_Init(Byte *state)\n{\n  unsigned i;\n  for (i = 0; i < DELTA_STATE_SIZE; i++)\n    state[i] = 0;\n}\n\n\nvoid Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)\n{\n  Byte temp[DELTA_STATE_SIZE];\n\n  if (size == 0)\n    return;\n\n  {\n    unsigned i = 0;\n    do\n      temp[i] = state[i];\n    while (++i != delta);\n  }\n\n  if (size <= delta)\n  {\n    unsigned i = 0, k;\n    do\n    {\n      Byte b = *data;\n      *data++ = (Byte)(b - temp[i]);\n      temp[i] = b;\n    }\n    while (++i != size);\n    \n    k = 0;\n    \n    do\n    {\n      if (i == delta)\n        i = 0;\n      state[k] = temp[i++];\n    }\n    while (++k != delta);\n    \n    return;\n  }\n    \n  {\n    Byte *p = data + size - delta;\n    {\n      unsigned i = 0;\n      do\n        state[i] = *p++;\n      while (++i != delta);\n    }\n    {\n      const Byte *lim = data + delta;\n      ptrdiff_t dif = -(ptrdiff_t)delta;\n      \n      if (((ptrdiff_t)size + dif) & 1)\n      {\n        --p;  *p = (Byte)(*p - p[dif]);\n      }\n\n      while (p != lim)\n      {\n        --p;  *p = (Byte)(*p - p[dif]);\n        --p;  *p = (Byte)(*p - p[dif]);\n      }\n      \n      dif = -dif;\n      \n      do\n      {\n        --p;  *p = (Byte)(*p - temp[--dif]);\n      }\n      while (dif != 0);\n    }\n  }\n}\n\n\nvoid Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)\n{\n  unsigned i;\n  const Byte *lim;\n\n  if (size == 0)\n    return;\n  \n  i = 0;\n  lim = data + size;\n  \n  if (size <= delta)\n  {\n    do\n      *data = (Byte)(*data + state[i++]);\n    while (++data != lim);\n\n    for (; delta != i; state++, delta--)\n      *state = state[i];\n    data -= i;\n  }\n  else\n  {\n    /*\n    #define B(n) b ## n\n    #define I(n) Byte B(n) = state[n];\n    #define U(n) { B(n) = (Byte)((B(n)) + *data++); data[-1] = (B(n)); }\n    #define F(n) if (data != lim) { U(n) }\n\n    if (delta == 1)\n    {\n      I(0)\n      if ((lim - data) & 1) { U(0) }\n      while (data != lim) { U(0) U(0) }\n      data -= 1;\n    }\n    else if (delta == 2)\n    {\n      I(0) I(1)\n      lim -= 1; while (data < lim) { U(0) U(1) }\n      lim += 1; F(0)\n      data -= 2;\n    }\n    else if (delta == 3)\n    {\n      I(0) I(1) I(2)\n      lim -= 2; while (data < lim) { U(0) U(1) U(2) }\n      lim += 2; F(0) F(1)\n      data -= 3;\n    }\n    else if (delta == 4)\n    {\n      I(0) I(1) I(2) I(3)\n      lim -= 3; while (data < lim) { U(0) U(1) U(2) U(3) }\n      lim += 3; F(0) F(1) F(2)\n      data -= 4;\n    }\n    else\n    */\n    {\n      do\n      {\n        *data = (Byte)(*data + state[i++]);\n        data++;\n      }\n      while (i != delta);\n  \n      {\n        ptrdiff_t dif = -(ptrdiff_t)delta;\n        do\n          *data = (Byte)(*data + data[dif]);\n        while (++data != lim);\n        data += dif;\n      }\n    }\n  }\n\n  do\n    *state++ = *data;\n  while (++data != lim);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Delta.h",
    "content": "﻿/* Delta.h -- Delta converter\n2023-03-03 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_DELTA_H\n#define ZIP7_INC_DELTA_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define DELTA_STATE_SIZE 256\n\nvoid Delta_Init(Byte *state);\nvoid Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);\nvoid Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/DllSecur.c",
    "content": "﻿/* DllSecur.c -- DLL loading security\n2023-12-03 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#ifdef _WIN32\n\n#include \"7zWindows.h\"\n\n#include \"DllSecur.h\"\n\n#ifndef UNDER_CE\n\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\ntypedef BOOL (WINAPI *Func_SetDefaultDllDirectories)(DWORD DirectoryFlags);\n\n#define MY_LOAD_LIBRARY_SEARCH_USER_DIRS 0x400\n#define MY_LOAD_LIBRARY_SEARCH_SYSTEM32  0x800\n\n#define DELIM \"\\0\"\n\nstatic const char * const g_Dlls =\n         \"userenv\"\n  DELIM  \"setupapi\"\n  DELIM  \"apphelp\"\n  DELIM  \"propsys\"\n  DELIM  \"dwmapi\"\n  DELIM  \"cryptbase\"\n  DELIM  \"oleacc\"\n  DELIM  \"clbcatq\"\n  DELIM  \"version\"\n  #ifndef _CONSOLE\n  DELIM  \"uxtheme\"\n  #endif\n  DELIM;\n\n#endif\n\n#ifdef __clang__\n  #pragma GCC diagnostic ignored \"-Wdeprecated-declarations\"\n#endif\n#if defined (_MSC_VER) && _MSC_VER >= 1900\n// sysinfoapi.h: kit10: GetVersion was declared deprecated\n#pragma warning(disable : 4996)\n#endif\n\n#define IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN \\\n    if ((UInt16)GetVersion() != 6) { \\\n      const \\\n       Func_SetDefaultDllDirectories setDllDirs = \\\n      (Func_SetDefaultDllDirectories) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT(\"kernel32.dll\")), \\\n           \"SetDefaultDllDirectories\"); \\\n      if (setDllDirs) if (setDllDirs(MY_LOAD_LIBRARY_SEARCH_SYSTEM32 | MY_LOAD_LIBRARY_SEARCH_USER_DIRS)) return; }\n\nvoid My_SetDefaultDllDirectories(void)\n{\n  #ifndef UNDER_CE\n  IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN\n  #endif\n}\n\n\nvoid LoadSecurityDlls(void)\n{\n  #ifndef UNDER_CE\n  // at Vista (ver 6.0) : CoCreateInstance(CLSID_ShellLink, ...) doesn't work after SetDefaultDllDirectories() : Check it ???\n  IF_NON_VISTA_SET_DLL_DIRS_AND_RETURN\n  {\n    wchar_t buf[MAX_PATH + 100];\n    const char *dll;\n    unsigned pos = GetSystemDirectoryW(buf, MAX_PATH + 2);\n    if (pos == 0 || pos > MAX_PATH)\n      return;\n    if (buf[pos - 1] != '\\\\')\n      buf[pos++] = '\\\\';\n    for (dll = g_Dlls; *dll != 0;)\n    {\n      wchar_t *dest = &buf[pos];\n      for (;;)\n      {\n        const char c = *dll++;\n        if (c == 0)\n          break;\n        *dest++ = (Byte)c;\n      }\n      dest[0] = '.';\n      dest[1] = 'd';\n      dest[2] = 'l';\n      dest[3] = 'l';\n      dest[4] = 0;\n      // lstrcatW(buf, L\".dll\");\n      LoadLibraryExW(buf, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);\n    }\n  }\n  #endif\n}\n\n#endif // _WIN32\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/DllSecur.h",
    "content": "﻿/* DllSecur.h -- DLL loading for security\n2023-03-03 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_DLL_SECUR_H\n#define ZIP7_INC_DLL_SECUR_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#ifdef _WIN32\n\nvoid My_SetDefaultDllDirectories(void);\nvoid LoadSecurityDlls(void);\n\n#endif\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/HuffEnc.c",
    "content": "﻿/* HuffEnc.c -- functions for Huffman encoding\nIgor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n#include \"HuffEnc.h\"\n#include \"Sort.h\"\n#include \"CpuArch.h\"\n\n#define kMaxLen       Z7_HUFFMAN_LEN_MAX\n#define NUM_BITS      10\n#define MASK          ((1u << NUM_BITS) - 1)\n#define FREQ_MASK     (~(UInt32)MASK)\n#define NUM_COUNTERS  (104 * 2) // (80 * 2) or (128 * 2) : ((prime_number + 1) * 2) for smaller code.\n\n#if 1 && (defined(MY_CPU_LE) || defined(MY_CPU_BE))\n#if defined(MY_CPU_LE)\n  #define HI_HALF_OFFSET 1\n#else\n  #define HI_HALF_OFFSET 0\n#endif\n#define LOAD_PARENT(p)                  ((unsigned)*((const UInt16 *)(p) + HI_HALF_OFFSET))\n#define STORE_PARENT(p, fb, val)         *((UInt16 *)(p) + HI_HALF_OFFSET) = (UInt16)(val);\n#define STORE_PARENT_DIRECT(p, fb, hi)  STORE_PARENT(p, fb, hi)\n#define UPDATE_E(eHi)                   eHi++;\n#else\n#define LOAD_PARENT(p)                  ((unsigned)(*(p) >> NUM_BITS))\n#define STORE_PARENT_DIRECT(p, fb, hi)  *(p) = ((fb) & MASK) | (hi); // set parent field\n#define STORE_PARENT(p, fb, val)        STORE_PARENT_DIRECT(p, fb, ((UInt32)(val) << NUM_BITS))\n#define UPDATE_E(eHi)                   eHi += 1 << NUM_BITS;\n#endif\n\nvoid Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, unsigned numSymbols, unsigned maxLen)\n{\n#if NUM_COUNTERS > 2\n  unsigned counters[NUM_COUNTERS];\n#endif\n#if 1 && NUM_COUNTERS > (kMaxLen + 4) * 2\n  #define lenCounters   (counters)\n  #define codes         (counters + kMaxLen + 4)\n#else\n  unsigned lenCounters[kMaxLen + 1];\n  UInt32 codes[kMaxLen + 1];\n#endif\n\n  unsigned num;\n  {\n    unsigned i;\n    // UInt32 sum = 0;\n\n#if NUM_COUNTERS > 2\n    \n#define CTR_ITEM_FOR_FREQ(freq) \\\n    counters[(freq) >= NUM_COUNTERS - 1 ? NUM_COUNTERS - 1 : (unsigned)(freq)]\n\n    for (i = 0; i < NUM_COUNTERS; i++)\n      counters[i] = 0;\n    memset(lens, 0, numSymbols);\n    {\n      const UInt32 *fp = freqs + numSymbols;\n#define NUM_UNROLLS 1\n#if NUM_UNROLLS > 1 // use 1 if odd (numSymbols) is possisble\n      if (numSymbols & 1)\n      {\n        UInt32 f;\n        f = *--fp;  CTR_ITEM_FOR_FREQ(f)++;\n        // sum += f;\n      }\n#endif\n      do\n      {\n        UInt32 f;\n        fp -= NUM_UNROLLS;\n        f = fp[0];  CTR_ITEM_FOR_FREQ(f)++;\n        // sum += f;\n#if NUM_UNROLLS > 1\n        f = fp[1];  CTR_ITEM_FOR_FREQ(f)++;\n        // sum += f;\n#endif\n      }\n      while (fp != freqs);\n    }\n#if 0\n    printf(\"\\nsum=%8u numSymbols =%3u ctrs:\", sum, numSymbols);\n    {\n      unsigned k = 0;\n      for (k = 0; k < NUM_COUNTERS; k++)\n        printf(\" %u\", counters[k]);\n    }\n#endif\n        \n    num = counters[1];\n    counters[1] = 0;\n    for (i = 2; i != NUM_COUNTERS; i += 2)\n    {\n      const unsigned c0 = (counters    )[i];\n      const unsigned c1 = (counters + 1)[i];\n      (counters    )[i] = num;  num += c0;\n      (counters + 1)[i] = num;  num += c1;\n    }\n    counters[0] = num; // we want to write (freq==0) symbols to the end of (p) array\n    {\n      i = 0;\n      do\n      {\n        const UInt32 f = freqs[i];\n#if 0\n        if (f == 0) lens[i] = 0; else\n#endif\n          p[CTR_ITEM_FOR_FREQ(f)++] = i | (f << NUM_BITS);\n      }\n      while (++i != numSymbols);\n    }\n    HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);\n    \n#else // NUM_COUNTERS <= 2\n    \n    num = 0;\n    for (i = 0; i < numSymbols; i++)\n    {\n      const UInt32 freq = freqs[i];\n      if (freq == 0)\n        lens[i] = 0;\n      else\n        p[num++] = i | (freq << NUM_BITS);\n    }\n    HeapSort(p, num);\n\n#endif\n  }\n\n  if (num <= 2)\n  {\n    unsigned minCode = 0;\n    unsigned maxCode = 1;\n    if (num)\n    {\n      maxCode = (unsigned)p[(size_t)num - 1] & MASK;\n      if (num == 2)\n      {\n        minCode = (unsigned)p[0] & MASK;\n        if (minCode > maxCode)\n        {\n          const unsigned temp = minCode;\n          minCode = maxCode;\n          maxCode = temp;\n        }\n      }\n      else if (maxCode == 0)\n        maxCode++;\n    }\n    p[minCode] = 0;\n    p[maxCode] = 1;\n    lens[minCode] = lens[maxCode] = 1;\n    return;\n  }\n  {\n    unsigned i;\n    for (i = 0; i <= kMaxLen; i++)\n      lenCounters[i] = 0;\n    lenCounters[1] = 2;  // by default root node has 2 child leaves at level 1.\n  }\n  // if (num != 2)\n  {\n    // num > 2\n    // the binary tree will contain (num - 1) internal nodes.\n    // p[num - 2] will be root node of binary tree.\n    UInt32 *b;\n    UInt32 *n;\n    // first node will have two leaf childs: p[0] and p[1]:\n    // p[0] += p[1] & FREQ_MASK; // set frequency sum of child leafs\n    // if (pi == n) exit(0);\n    // if (pi != n)\n    {\n      UInt32 fb = (p[1] & FREQ_MASK) + p[0];\n      UInt32 f = p[2] & FREQ_MASK;\n      const UInt32 *pi = p + 2;\n      UInt32 *e = p;\n      UInt32 eHi = 0;\n      n = p + num;\n      b = p;\n      // p[0] = fb;\n      for (;;)\n      {\n        // (b <= e)\n        UInt32 sum;\n        e++;\n        UPDATE_E(eHi)\n\n        // (b < e)\n\n        // p range : high bits\n        // [0, b)  : parent :     processed nodes that have parent and childs\n        // [b, e)  : FREQ   : non-processed nodes that have no parent but have childs\n        // [e, pi) : FREQ   :     processed leaves for which parent node was     created\n        // [pi, n) : FREQ   : non-processed leaves for which parent node was not created\n\n        // first child\n        // note : (*b < f) is same result as ((*b & FREQ_MASK) < f)\n        if (fb < f)\n        {\n          // node freq is smaller\n          sum = fb & FREQ_MASK;\n          STORE_PARENT_DIRECT (b, fb, eHi)\n          b++;\n          fb = *b;\n          if (b == e)\n          {\n            if (++pi == n)\n              break;\n            sum += f;\n            fb &= MASK;\n            fb |= sum;\n            *e = fb;\n            f = *pi & FREQ_MASK;\n            continue;\n          }\n        }\n        else if (++pi == n)\n        {\n          STORE_PARENT_DIRECT (b, fb, eHi)\n          b++;\n          break;\n        }\n        else\n        {\n          sum = f;\n          f = *pi & FREQ_MASK;\n        }\n\n        // (b < e)\n\n        // second child\n        if (fb < f)\n        {\n          sum += fb;\n          sum &= FREQ_MASK;\n          STORE_PARENT_DIRECT (b, fb, eHi)\n          b++;\n          *e = (*e & MASK) | sum; // set frequency sum\n          // (b <= e) is possible here\n          fb = *b;\n        }\n        else if (++pi == n)\n          break;\n        else\n        {\n          sum += f;\n          f = *pi & FREQ_MASK;\n          *e = (*e & MASK) | sum; // set frequency sum\n        }\n      }\n    }\n    \n    // printf(\"\\nnum-e=%3u, numSymbols=%3u, num=%3u, b=%3u\", n - e, numSymbols, n - p, b - p);\n    {\n      n -= 2;\n      *n &= MASK; // root node : we clear high bits (zero bits mean level == 0)\n      if (n != b)\n      {\n        // We go here, if we have some number of non-created nodes up to root.\n        // We process them in simplified code:\n        // position of parent for each pair of nodes is known.\n        // n[-2], n[-1] : current pair of child nodes\n        // (p1) : parent node for current pair.\n        UInt32 *p1 = n;\n        do\n        {\n          const unsigned len = LOAD_PARENT(p1) + 1;\n          p1--;\n          (lenCounters    )[len] -= 2;                  // we remove 2 leaves from level (len)\n          (lenCounters + 1)[len] += 2 * 2;  // we add 4 leaves at level (len + 1)\n          n -= 2;\n          STORE_PARENT (n    , n[0], len)\n          STORE_PARENT (n + 1, n[1], len)\n        }\n        while (n != b);\n      }\n    }\n    \n    if (b != p)\n    {\n      // we detect level of each node (realtive to root),\n      // and update lenCounters[].\n      // We process only intermediate nodes and we don't process leaves.\n      do\n      {\n        // if (ii <  b) : parent_bits_of (p[ii]) == index of parent node : ii < (p[ii])\n        // if (ii >= b) : parent_bits_of (p[ii]) == level of this (ii) node in tree\n        unsigned len;\n        b--;\n        len = (unsigned)LOAD_PARENT(p + LOAD_PARENT(b)) + 1;\n        STORE_PARENT (b, *b, len)\n        if (len >= maxLen)\n        {\n          // We are not allowed to create node at level (maxLen) and higher,\n          // because all leaves must be placed to level (maxLen) or lower.\n          // We find nearest allowed leaf and place current node to level of that leaf:\n          for (len = maxLen - 1; lenCounters[len] == 0; len--) {}\n        }\n        lenCounters[len]--;                 // we remove 1 leaf from level (len)\n        (lenCounters + 1)[len] += 2;  // we add 2 leaves at level (len + 1)\n      }\n      while (b != p);\n    }\n  }\n  {\n    {\n      unsigned len = maxLen;\n      const UInt32 *p2 = p;\n      do\n      {\n        unsigned k = lenCounters[len];\n        if (k)\n          do\n            lens[(unsigned)*p2++ & MASK] = (Byte)len;\n          while (--k);\n      }\n      while (--len);\n    }\n    codes[0] = 0; // we don't want garbage values to be written to p[] array.\n    // codes[1] = 0;\n    {\n      UInt32 code = 0;\n      unsigned len;\n      for (len = 0; len < kMaxLen; len++)\n        (codes + 1)[len] = code = (code + lenCounters[len]) << 1;\n    }\n    /* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */\n    {\n      const Byte * const limit = lens + numSymbols;\n      do\n      {\n        unsigned len;\n        UInt32 c;\n        len = lens[0];  c = codes[len];  p[0] = c;  codes[len] = c + 1;\n        // len = lens[1];  c = codes[len];  p[1] = c;  codes[len] = c + 1;\n        p += 1;\n        lens += 1;\n      }\n      while (lens != limit);\n    }\n  }\n}\n\n#undef kMaxLen\n#undef NUM_BITS\n#undef MASK\n#undef FREQ_MASK\n#undef NUM_COUNTERS\n#undef CTR_ITEM_FOR_FREQ\n#undef LOAD_PARENT\n#undef STORE_PARENT\n#undef STORE_PARENT_DIRECT\n#undef UPDATE_E\n#undef HI_HALF_OFFSET\n#undef NUM_UNROLLS\n#undef lenCounters\n#undef codes\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/HuffEnc.h",
    "content": "﻿/* HuffEnc.h -- Huffman encoding\nIgor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_HUFF_ENC_H\n#define ZIP7_INC_HUFF_ENC_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define Z7_HUFFMAN_LEN_MAX 16\n/*\nConditions:\n  2 <= num <= 1024 = 2 ^ NUM_BITS\n  Sum(freqs) < 4M = 2 ^ (32 - NUM_BITS)\n  1 <= maxLen <= 16 = Z7_HUFFMAN_LEN_MAX\n  Num_Items(p) >= HUFFMAN_TEMP_SIZE(num)\n*/\nvoid Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, unsigned num, unsigned maxLen);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzFind.c",
    "content": "﻿/* LzFind.c -- Match finder for LZ algorithms\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n// #include <stdio.h>\n\n#include \"CpuArch.h\"\n#include \"LzFind.h\"\n#include \"LzHash.h\"\n\n#define kBlockMoveAlign       (1 << 7)    // alignment for memmove()\n#define kBlockSizeAlign       (1 << 16)   // alignment for block allocation\n#define kBlockSizeReserveMin  (1 << 24)   // it's 1/256 from 4 GB dictinary\n\n#define kEmptyHashValue 0\n\n#define kMaxValForNormalize ((UInt32)0)\n// #define kMaxValForNormalize ((UInt32)(1 << 20) + 0xfff) // for debug\n\n// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses\n\n#define GET_AVAIL_BYTES(p) \\\n  Inline_MatchFinder_GetNumAvailableBytes(p)\n\n\n// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)\n#define kFix5HashSize kFix4HashSize\n\n/*\n HASH2_CALC:\n   if (hv) match, then cur[0] and cur[1] also match\n*/\n#define HASH2_CALC hv = GetUi16(cur);\n\n// (crc[0 ... 255] & 0xFF) provides one-to-one correspondence to [0 ... 255]\n\n/*\n HASH3_CALC:\n   if (cur[0]) and (h2) match, then cur[1]            also match\n   if (cur[0]) and (hv) match, then cur[1] and cur[2] also match\n*/\n#define HASH3_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  h2 = temp & (kHash2Size - 1); \\\n  hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }\n\n#define HASH4_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  h2 = temp & (kHash2Size - 1); \\\n  temp ^= ((UInt32)cur[2] << 8); \\\n  h3 = temp & (kHash3Size - 1); \\\n  hv = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hashMask; }\n\n#define HASH5_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  h2 = temp & (kHash2Size - 1); \\\n  temp ^= ((UInt32)cur[2] << 8); \\\n  h3 = temp & (kHash3Size - 1); \\\n  temp ^= (p->crc[cur[3]] << kLzHash_CrcShift_1); \\\n  /* h4 = temp & p->hash4Mask; */ /* (kHash4Size - 1); */ \\\n  hv = (temp ^ (p->crc[cur[4]] << kLzHash_CrcShift_2)) & p->hashMask; }\n\n#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;\n\n\nstatic void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc)\n{\n  // if (!p->directInput)\n  {\n    ISzAlloc_Free(alloc, p->bufBase);\n    p->bufBase = NULL;\n  }\n}\n\n\nstatic int LzInWindow_Create2(CMatchFinder *p, UInt32 blockSize, ISzAllocPtr alloc)\n{\n  if (blockSize == 0)\n    return 0;\n  if (!p->bufBase || p->blockSize != blockSize)\n  {\n    // size_t blockSizeT;\n    LzInWindow_Free(p, alloc);\n    p->blockSize = blockSize;\n    // blockSizeT = blockSize;\n    \n    // printf(\"\\nblockSize = 0x%x\\n\", blockSize);\n    /*\n    #if defined _WIN64\n    // we can allocate 4GiB, but still use UInt32 for (p->blockSize)\n    // we use UInt32 type for (p->blockSize), because\n    // we don't want to wrap over 4 GiB,\n    // when we use (p->streamPos - p->pos) that is UInt32.\n    if (blockSize >= (UInt32)0 - (UInt32)kBlockSizeAlign)\n    {\n      blockSizeT = ((size_t)1 << 32);\n      printf(\"\\nchanged to blockSizeT = 4GiB\\n\");\n    }\n    #endif\n    */\n    \n    p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, blockSize);\n    // printf(\"\\nbufferBase = %p\\n\", p->bufBase);\n    // return 0; // for debug\n  }\n  return (p->bufBase != NULL);\n}\n\nstatic const Byte *MatchFinder_GetPointerToCurrentPos(void *p)\n{\n  return ((CMatchFinder *)p)->buffer;\n}\n\nstatic UInt32 MatchFinder_GetNumAvailableBytes(void *p)\n{\n  return GET_AVAIL_BYTES((CMatchFinder *)p);\n}\n\n\nZ7_NO_INLINE\nstatic void MatchFinder_ReadBlock(CMatchFinder *p)\n{\n  if (p->streamEndWasReached || p->result != SZ_OK)\n    return;\n\n  /* We use (p->streamPos - p->pos) value.\n     (p->streamPos < p->pos) is allowed. */\n\n  if (p->directInput)\n  {\n    UInt32 curSize = 0xFFFFFFFF - GET_AVAIL_BYTES(p);\n    if (curSize > p->directInputRem)\n      curSize = (UInt32)p->directInputRem;\n    p->streamPos += curSize;\n    p->directInputRem -= curSize;\n    if (p->directInputRem == 0)\n      p->streamEndWasReached = 1;\n    return;\n  }\n  \n  for (;;)\n  {\n    const Byte *dest = p->buffer + GET_AVAIL_BYTES(p);\n    size_t size = (size_t)(p->bufBase + p->blockSize - dest);\n    if (size == 0)\n    {\n      /* we call ReadBlock() after NeedMove() and MoveBlock().\n         NeedMove() and MoveBlock() povide more than (keepSizeAfter)\n         to the end of (blockSize).\n         So we don't execute this branch in normal code flow.\n         We can go here, if we will call ReadBlock() before NeedMove(), MoveBlock().\n      */\n      // p->result = SZ_ERROR_FAIL; // we can show error here\n      return;\n    }\n\n    // #define kRead 3\n    // if (size > kRead) size = kRead; // for debug\n\n    /*\n    // we need cast (Byte *)dest.\n    #ifdef __clang__\n      #pragma GCC diagnostic ignored \"-Wcast-qual\"\n    #endif\n    */\n    p->result = ISeqInStream_Read(p->stream,\n        p->bufBase + (dest - p->bufBase), &size);\n    if (p->result != SZ_OK)\n      return;\n    if (size == 0)\n    {\n      p->streamEndWasReached = 1;\n      return;\n    }\n    p->streamPos += (UInt32)size;\n    if (GET_AVAIL_BYTES(p) > p->keepSizeAfter)\n      return;\n    /* here and in another (p->keepSizeAfter) checks we keep on 1 byte more than was requested by Create() function\n         (GET_AVAIL_BYTES(p) >= p->keepSizeAfter) - minimal required size */\n  }\n\n  // on exit: (p->result != SZ_OK || p->streamEndWasReached || GET_AVAIL_BYTES(p) > p->keepSizeAfter)\n}\n\n\n\nZ7_NO_INLINE\nvoid MatchFinder_MoveBlock(CMatchFinder *p)\n{\n  const size_t offset = (size_t)(p->buffer - p->bufBase) - p->keepSizeBefore;\n  const size_t keepBefore = (offset & (kBlockMoveAlign - 1)) + p->keepSizeBefore;\n  p->buffer = p->bufBase + keepBefore;\n  memmove(p->bufBase,\n      p->bufBase + (offset & ~((size_t)kBlockMoveAlign - 1)),\n      keepBefore + (size_t)GET_AVAIL_BYTES(p));\n}\n\n/* We call MoveBlock() before ReadBlock().\n   So MoveBlock() can be wasteful operation, if the whole input data\n   can fit in current block even without calling MoveBlock().\n   in important case where (dataSize <= historySize)\n     condition (p->blockSize > dataSize + p->keepSizeAfter) is met\n     So there is no MoveBlock() in that case case.\n*/\n\nint MatchFinder_NeedMove(CMatchFinder *p)\n{\n  if (p->directInput)\n    return 0;\n  if (p->streamEndWasReached || p->result != SZ_OK)\n    return 0;\n  return ((size_t)(p->bufBase + p->blockSize - p->buffer) <= p->keepSizeAfter);\n}\n\nvoid MatchFinder_ReadIfRequired(CMatchFinder *p)\n{\n  if (p->keepSizeAfter >= GET_AVAIL_BYTES(p))\n    MatchFinder_ReadBlock(p);\n}\n\n\n\nstatic void MatchFinder_SetDefaultSettings(CMatchFinder *p)\n{\n  p->cutValue = 32;\n  p->btMode = 1;\n  p->numHashBytes = 4;\n  p->numHashBytes_Min = 2;\n  p->numHashOutBits = 0;\n  p->bigHash = 0;\n}\n\n#define kCrcPoly 0xEDB88320\n\nvoid MatchFinder_Construct(CMatchFinder *p)\n{\n  unsigned i;\n  p->buffer = NULL;\n  p->bufBase = NULL;\n  p->directInput = 0;\n  p->stream = NULL;\n  p->hash = NULL;\n  p->expectedDataSize = (UInt64)(Int64)-1;\n  MatchFinder_SetDefaultSettings(p);\n\n  for (i = 0; i < 256; i++)\n  {\n    UInt32 r = (UInt32)i;\n    unsigned j;\n    for (j = 0; j < 8; j++)\n      r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));\n    p->crc[i] = r;\n  }\n}\n\n#undef kCrcPoly\n\nstatic void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->hash);\n  p->hash = NULL;\n}\n\nvoid MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc)\n{\n  MatchFinder_FreeThisClassMemory(p, alloc);\n  LzInWindow_Free(p, alloc);\n}\n\nstatic CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc)\n{\n  const size_t sizeInBytes = (size_t)num * sizeof(CLzRef);\n  if (sizeInBytes / sizeof(CLzRef) != num)\n    return NULL;\n  return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes);\n}\n\n#if (kBlockSizeReserveMin < kBlockSizeAlign * 2)\n  #error Stop_Compiling_Bad_Reserve\n#endif\n\n\n\nstatic UInt32 GetBlockSize(CMatchFinder *p, UInt32 historySize)\n{\n  UInt32 blockSize = (p->keepSizeBefore + p->keepSizeAfter);\n  /*\n  if (historySize > kMaxHistorySize)\n    return 0;\n  */\n  // printf(\"\\nhistorySize == 0x%x\\n\", historySize);\n  \n  if (p->keepSizeBefore < historySize || blockSize < p->keepSizeBefore)  // if 32-bit overflow\n    return 0;\n  \n  {\n    const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)kBlockSizeAlign;\n    const UInt32 rem = kBlockSizeMax - blockSize;\n    const UInt32 reserve = (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2))\n        + (1 << 12) + kBlockMoveAlign + kBlockSizeAlign; // do not overflow 32-bit here\n    if (blockSize >= kBlockSizeMax\n        || rem < kBlockSizeReserveMin) // we reject settings that will be slow\n      return 0;\n    if (reserve >= rem)\n      blockSize = kBlockSizeMax;\n    else\n    {\n      blockSize += reserve;\n      blockSize &= ~(UInt32)(kBlockSizeAlign - 1);\n    }\n  }\n  // printf(\"\\n LzFind_blockSize = %x\\n\", blockSize);\n  // printf(\"\\n LzFind_blockSize = %d\\n\", blockSize >> 20);\n  return blockSize;\n}\n\n\n// input is historySize\nstatic UInt32 MatchFinder_GetHashMask2(CMatchFinder *p, UInt32 hs)\n{\n  if (p->numHashBytes == 2)\n    return (1 << 16) - 1;\n  if (hs != 0)\n    hs--;\n  hs |= (hs >> 1);\n  hs |= (hs >> 2);\n  hs |= (hs >> 4);\n  hs |= (hs >> 8);\n  // we propagated 16 bits in (hs). Low 16 bits must be set later\n  if (hs >= (1 << 24))\n  {\n    if (p->numHashBytes == 3)\n      hs = (1 << 24) - 1;\n    /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */\n  }\n  // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2)\n  hs |= (1 << 16) - 1; /* don't change it! */\n  // bt5: we adjust the size with recommended minimum size\n  if (p->numHashBytes >= 5)\n    hs |= (256 << kLzHash_CrcShift_2) - 1;\n  return hs;\n}\n\n// input is historySize\nstatic UInt32 MatchFinder_GetHashMask(CMatchFinder *p, UInt32 hs)\n{\n  if (p->numHashBytes == 2)\n    return (1 << 16) - 1;\n  if (hs != 0)\n    hs--;\n  hs |= (hs >> 1);\n  hs |= (hs >> 2);\n  hs |= (hs >> 4);\n  hs |= (hs >> 8);\n  // we propagated 16 bits in (hs). Low 16 bits must be set later\n  hs >>= 1;\n  if (hs >= (1 << 24))\n  {\n    if (p->numHashBytes == 3)\n      hs = (1 << 24) - 1;\n    else\n      hs >>= 1;\n    /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */\n  }\n  // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2)\n  hs |= (1 << 16) - 1; /* don't change it! */\n  // bt5: we adjust the size with recommended minimum size\n  if (p->numHashBytes >= 5)\n    hs |= (256 << kLzHash_CrcShift_2) - 1;\n  return hs;\n}\n\n\nint MatchFinder_Create(CMatchFinder *p, UInt32 historySize,\n    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,\n    ISzAllocPtr alloc)\n{\n  /* we need one additional byte in (p->keepSizeBefore),\n     since we use MoveBlock() after (p->pos++) and before dictionary using */\n  // keepAddBufferBefore = (UInt32)0xFFFFFFFF - (1 << 22); // for debug\n  p->keepSizeBefore = historySize + keepAddBufferBefore + 1;\n\n  keepAddBufferAfter += matchMaxLen;\n  /* we need (p->keepSizeAfter >= p->numHashBytes) */\n  if (keepAddBufferAfter < p->numHashBytes)\n    keepAddBufferAfter = p->numHashBytes;\n  // keepAddBufferAfter -= 2; // for debug\n  p->keepSizeAfter = keepAddBufferAfter;\n\n  if (p->directInput)\n    p->blockSize = 0;\n  if (p->directInput || LzInWindow_Create2(p, GetBlockSize(p, historySize), alloc))\n  {\n    size_t hashSizeSum;\n    {\n      UInt32 hs;\n      UInt32 hsCur;\n      \n      if (p->numHashOutBits != 0)\n      {\n        unsigned numBits = p->numHashOutBits;\n        const unsigned nbMax =\n            (p->numHashBytes == 2 ? 16 :\n            (p->numHashBytes == 3 ? 24 : 32));\n        if (numBits >= nbMax)\n          numBits = nbMax;\n        if (numBits >= 32)\n          hs = (UInt32)0 - 1;\n        else\n          hs = ((UInt32)1 << numBits) - 1;\n        // (hash_size >= (1 << 16)) : Required for (numHashBytes > 2)\n        hs |= (1 << 16) - 1; /* don't change it! */\n        if (p->numHashBytes >= 5)\n          hs |= (256 << kLzHash_CrcShift_2) - 1;\n        {\n          const UInt32 hs2 = MatchFinder_GetHashMask2(p, historySize);\n          if (hs >= hs2)\n            hs = hs2;\n        }\n        hsCur = hs;\n        if (p->expectedDataSize < historySize)\n        {\n          const UInt32 hs2 = MatchFinder_GetHashMask2(p, (UInt32)p->expectedDataSize);\n          if (hsCur >= hs2)\n            hsCur = hs2;\n        }\n      }\n      else\n      {\n        hs = MatchFinder_GetHashMask(p, historySize);\n        hsCur = hs;\n        if (p->expectedDataSize < historySize)\n        {\n          hsCur = MatchFinder_GetHashMask(p, (UInt32)p->expectedDataSize);\n          if (hsCur >= hs) // is it possible?\n            hsCur = hs;\n        }\n      }\n\n      p->hashMask = hsCur;\n\n      hashSizeSum = hs;\n      hashSizeSum++;\n      if (hashSizeSum < hs)\n        return 0;\n      {\n        UInt32 fixedHashSize = 0;\n        if (p->numHashBytes > 2 && p->numHashBytes_Min <= 2) fixedHashSize += kHash2Size;\n        if (p->numHashBytes > 3 && p->numHashBytes_Min <= 3) fixedHashSize += kHash3Size;\n        // if (p->numHashBytes > 4) p->fixedHashSize += hs4; // kHash4Size;\n        hashSizeSum += fixedHashSize;\n        p->fixedHashSize = fixedHashSize;\n      }\n    }\n\n    p->matchMaxLen = matchMaxLen;\n\n    {\n      size_t newSize;\n      size_t numSons;\n      const UInt32 newCyclicBufferSize = historySize + 1; // do not change it\n      p->historySize = historySize;\n      p->cyclicBufferSize = newCyclicBufferSize; // it must be = (historySize + 1)\n      \n      numSons = newCyclicBufferSize;\n      if (p->btMode)\n        numSons <<= 1;\n      newSize = hashSizeSum + numSons;\n\n      if (numSons < newCyclicBufferSize || newSize < numSons)\n        return 0;\n\n      // aligned size is not required here, but it can be better for some loops\n      #define NUM_REFS_ALIGN_MASK 0xF\n      newSize = (newSize + NUM_REFS_ALIGN_MASK) & ~(size_t)NUM_REFS_ALIGN_MASK;\n\n      // 22.02: we don't reallocate buffer, if old size is enough\n      if (p->hash && p->numRefs >= newSize)\n        return 1;\n      \n      MatchFinder_FreeThisClassMemory(p, alloc);\n      p->numRefs = newSize;\n      p->hash = AllocRefs(newSize, alloc);\n      \n      if (p->hash)\n      {\n        p->son = p->hash + hashSizeSum;\n        return 1;\n      }\n    }\n  }\n\n  MatchFinder_Free(p, alloc);\n  return 0;\n}\n\n\nstatic void MatchFinder_SetLimits(CMatchFinder *p)\n{\n  UInt32 k;\n  UInt32 n = kMaxValForNormalize - p->pos;\n  if (n == 0)\n    n = (UInt32)(Int32)-1;  // we allow (pos == 0) at start even with (kMaxValForNormalize == 0)\n  \n  k = p->cyclicBufferSize - p->cyclicBufferPos;\n  if (k < n)\n    n = k;\n\n  k = GET_AVAIL_BYTES(p);\n  {\n    const UInt32 ksa = p->keepSizeAfter;\n    UInt32 mm = p->matchMaxLen;\n    if (k > ksa)\n      k -= ksa; // we must limit exactly to keepSizeAfter for ReadBlock\n    else if (k >= mm)\n    {\n      // the limitation for (p->lenLimit) update\n      k -= mm;   // optimization : to reduce the number of checks\n      k++;\n      // k = 1; // non-optimized version : for debug\n    }\n    else\n    {\n      mm = k;\n      if (k != 0)\n        k = 1;\n    }\n    p->lenLimit = mm;\n  }\n  if (k < n)\n    n = k;\n  \n  p->posLimit = p->pos + n;\n}\n\n\nvoid MatchFinder_Init_LowHash(CMatchFinder *p)\n{\n  size_t i;\n  CLzRef *items = p->hash;\n  const size_t numItems = p->fixedHashSize;\n  for (i = 0; i < numItems; i++)\n    items[i] = kEmptyHashValue;\n}\n\n\nvoid MatchFinder_Init_HighHash(CMatchFinder *p)\n{\n  size_t i;\n  CLzRef *items = p->hash + p->fixedHashSize;\n  const size_t numItems = (size_t)p->hashMask + 1;\n  for (i = 0; i < numItems; i++)\n    items[i] = kEmptyHashValue;\n}\n\n\nvoid MatchFinder_Init_4(CMatchFinder *p)\n{\n  if (!p->directInput)\n    p->buffer = p->bufBase;\n  {\n    /* kEmptyHashValue = 0 (Zero) is used in hash tables as NO-VALUE marker.\n       the code in CMatchFinderMt expects (pos = 1) */\n    p->pos =\n    p->streamPos =\n        1; // it's smallest optimal value. do not change it\n        // 0; // for debug\n  }\n  p->result = SZ_OK;\n  p->streamEndWasReached = 0;\n}\n\n\n// (CYC_TO_POS_OFFSET == 0) is expected by some optimized code\n#define CYC_TO_POS_OFFSET 0\n// #define CYC_TO_POS_OFFSET 1 // for debug\n\nvoid MatchFinder_Init(void *_p)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  MatchFinder_Init_HighHash(p);\n  MatchFinder_Init_LowHash(p);\n  MatchFinder_Init_4(p);\n  // if (readData)\n  MatchFinder_ReadBlock(p);\n\n  /* if we init (cyclicBufferPos = pos), then we can use one variable\n     instead of both (cyclicBufferPos) and (pos) : only before (cyclicBufferPos) wrapping */\n  p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET); // init with relation to (pos)\n  // p->cyclicBufferPos = 0; // smallest value\n  // p->son[0] = p->son[1] = 0; // unused: we can init skipped record for speculated accesses.\n  MatchFinder_SetLimits(p);\n}\n\n\n\n#ifdef MY_CPU_X86_OR_AMD64\n  #if defined(__clang__) && (__clang_major__ >= 4) \\\n    || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900)\n    // || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900)\n\n      #define USE_LZFIND_SATUR_SUB_128\n      #define USE_LZFIND_SATUR_SUB_256\n      #define LZFIND_ATTRIB_SSE41 __attribute__((__target__(\"sse4.1\")))\n      #define LZFIND_ATTRIB_AVX2  __attribute__((__target__(\"avx2\")))\n  #elif defined(_MSC_VER)\n    #if (_MSC_VER >= 1600)\n      #define USE_LZFIND_SATUR_SUB_128\n    #endif\n    #if (_MSC_VER >= 1900)\n      #define USE_LZFIND_SATUR_SUB_256\n    #endif\n  #endif\n\n#elif defined(MY_CPU_ARM64) \\\n  /* || (defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) */\n\n  #if  defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \\\n    || defined(__GNUC__) && (__GNUC__ >= 6)\n      #define USE_LZFIND_SATUR_SUB_128\n    #ifdef MY_CPU_ARM64\n      // #define LZFIND_ATTRIB_SSE41 __attribute__((__target__(\"\")))\n    #else\n      #define LZFIND_ATTRIB_SSE41 __attribute__((__target__(\"fpu=neon\")))\n    #endif\n\n  #elif defined(_MSC_VER)\n    #if (_MSC_VER >= 1910)\n      #define USE_LZFIND_SATUR_SUB_128\n    #endif\n  #endif\n\n  #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)\n    #include <arm64_neon.h>\n  #else\n    #include <arm_neon.h>\n  #endif\n\n#endif\n\n\n#ifdef USE_LZFIND_SATUR_SUB_128\n\n// #define Z7_SHOW_HW_STATUS\n\n#ifdef Z7_SHOW_HW_STATUS\n#include <stdio.h>\n#define PRF(x) x\nPRF(;)\n#else\n#define PRF(x)\n#endif\n\n\n#ifdef MY_CPU_ARM_OR_ARM64\n\n#ifdef MY_CPU_ARM64\n// #define FORCE_LZFIND_SATUR_SUB_128\n#endif\ntypedef uint32x4_t LzFind_v128;\n#define SASUB_128_V(v, s) \\\n  vsubq_u32(vmaxq_u32(v, s), s)\n\n#else // MY_CPU_ARM_OR_ARM64\n\n#include <smmintrin.h> // sse4.1\n\ntypedef __m128i LzFind_v128;\n// SSE 4.1\n#define SASUB_128_V(v, s)   \\\n  _mm_sub_epi32(_mm_max_epu32(v, s), s)\n\n#endif // MY_CPU_ARM_OR_ARM64\n\n\n#define SASUB_128(i) \\\n  *(      LzFind_v128 *)(      void *)(items + (i) * 4) = SASUB_128_V( \\\n  *(const LzFind_v128 *)(const void *)(items + (i) * 4), sub2);\n\n\nZ7_NO_INLINE\nstatic\n#ifdef LZFIND_ATTRIB_SSE41\nLZFIND_ATTRIB_SSE41\n#endif\nvoid\nZ7_FASTCALL\nLzFind_SaturSub_128(UInt32 subValue, CLzRef *items, const CLzRef *lim)\n{\n  const LzFind_v128 sub2 =\n    #ifdef MY_CPU_ARM_OR_ARM64\n      vdupq_n_u32(subValue);\n    #else\n      _mm_set_epi32((Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue);\n    #endif\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SASUB_128(0)  SASUB_128(1)  items += 2 * 4;\n    SASUB_128(0)  SASUB_128(1)  items += 2 * 4;\n  }\n  while (items != lim);\n}\n\n\n\n#ifdef USE_LZFIND_SATUR_SUB_256\n\n#include <immintrin.h> // avx\n/*\nclang :immintrin.h uses\n#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) ||      \\\n    defined(__AVX2__)\n#include <avx2intrin.h>\n#endif\nso we need <avxintrin.h> for clang-cl */\n\n#if defined(__clang__)\n#include <avxintrin.h>\n#include <avx2intrin.h>\n#endif\n\n// AVX2:\n#define SASUB_256(i) \\\n    *(      __m256i *)(      void *)(items + (i) * 8) = \\\n   _mm256_sub_epi32(_mm256_max_epu32( \\\n    *(const __m256i *)(const void *)(items + (i) * 8), sub2), sub2);\n\nZ7_NO_INLINE\nstatic\n#ifdef LZFIND_ATTRIB_AVX2\nLZFIND_ATTRIB_AVX2\n#endif\nvoid\nZ7_FASTCALL\nLzFind_SaturSub_256(UInt32 subValue, CLzRef *items, const CLzRef *lim)\n{\n  const __m256i sub2 = _mm256_set_epi32(\n      (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue,\n      (Int32)subValue, (Int32)subValue, (Int32)subValue, (Int32)subValue);\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SASUB_256(0)  SASUB_256(1)  items += 2 * 8;\n    SASUB_256(0)  SASUB_256(1)  items += 2 * 8;\n  }\n  while (items != lim);\n}\n#endif // USE_LZFIND_SATUR_SUB_256\n\n#ifndef FORCE_LZFIND_SATUR_SUB_128\ntypedef void (Z7_FASTCALL *LZFIND_SATUR_SUB_CODE_FUNC)(\n    UInt32 subValue, CLzRef *items, const CLzRef *lim);\nstatic LZFIND_SATUR_SUB_CODE_FUNC g_LzFind_SaturSub;\n#endif // FORCE_LZFIND_SATUR_SUB_128\n\n#endif // USE_LZFIND_SATUR_SUB_128\n\n\n// kEmptyHashValue must be zero\n// #define SASUB_32(i)  { UInt32 v = items[i];  UInt32 m = v - subValue;  if (v < subValue) m = kEmptyHashValue;  items[i] = m; }\n#define SASUB_32(i)  { UInt32 v = items[i];  if (v < subValue) v = subValue; items[i] = v - subValue; }\n\n#ifdef FORCE_LZFIND_SATUR_SUB_128\n\n#define DEFAULT_SaturSub LzFind_SaturSub_128\n\n#else\n\n#define DEFAULT_SaturSub LzFind_SaturSub_32\n\nZ7_NO_INLINE\nstatic\nvoid\nZ7_FASTCALL\nLzFind_SaturSub_32(UInt32 subValue, CLzRef *items, const CLzRef *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SASUB_32(0)  SASUB_32(1)  items += 2;\n    SASUB_32(0)  SASUB_32(1)  items += 2;\n    SASUB_32(0)  SASUB_32(1)  items += 2;\n    SASUB_32(0)  SASUB_32(1)  items += 2;\n  }\n  while (items != lim);\n}\n\n#endif\n\n\nZ7_NO_INLINE\nvoid MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems)\n{\n  #define LZFIND_NORM_ALIGN_BLOCK_SIZE (1 << 7)\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (LZFIND_NORM_ALIGN_BLOCK_SIZE - 1)) != 0; numItems--)\n  {\n    SASUB_32(0)\n    items++;\n  }\n  {\n    const size_t k_Align_Mask = (LZFIND_NORM_ALIGN_BLOCK_SIZE / 4 - 1);\n    CLzRef *lim = items + (numItems & ~(size_t)k_Align_Mask);\n    numItems &= k_Align_Mask;\n    if (items != lim)\n    {\n      #if defined(USE_LZFIND_SATUR_SUB_128) && !defined(FORCE_LZFIND_SATUR_SUB_128)\n        if (g_LzFind_SaturSub)\n          g_LzFind_SaturSub(subValue, items, lim);\n        else\n      #endif\n          DEFAULT_SaturSub(subValue, items, lim);\n    }\n    items = lim;\n  }\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  for (; numItems != 0; numItems--)\n  {\n    SASUB_32(0)\n    items++;\n  }\n}\n\n\n\n// call MatchFinder_CheckLimits() only after (p->pos++) update\n\nZ7_NO_INLINE\nstatic void MatchFinder_CheckLimits(CMatchFinder *p)\n{\n  if (// !p->streamEndWasReached && p->result == SZ_OK &&\n      p->keepSizeAfter == GET_AVAIL_BYTES(p))\n  {\n    // we try to read only in exact state (p->keepSizeAfter == GET_AVAIL_BYTES(p))\n    if (MatchFinder_NeedMove(p))\n      MatchFinder_MoveBlock(p);\n    MatchFinder_ReadBlock(p);\n  }\n\n  if (p->pos == kMaxValForNormalize)\n  if (GET_AVAIL_BYTES(p) >= p->numHashBytes) // optional optimization for last bytes of data.\n    /*\n       if we disable normalization for last bytes of data, and\n       if (data_size == 4 GiB), we don't call wastfull normalization,\n       but (pos) will be wrapped over Zero (0) in that case.\n       And we cannot resume later to normal operation\n    */\n  {\n    // MatchFinder_Normalize(p);\n    /* after normalization we need (p->pos >= p->historySize + 1); */\n    /* we can reduce subValue to aligned value, if want to keep alignment\n       of (p->pos) and (p->buffer) for speculated accesses. */\n    const UInt32 subValue = (p->pos - p->historySize - 1) /* & ~(UInt32)(kNormalizeAlign - 1) */;\n    // const UInt32 subValue = (1 << 15); // for debug\n    // printf(\"\\nMatchFinder_Normalize() subValue == 0x%x\\n\", subValue);\n    MatchFinder_REDUCE_OFFSETS(p, subValue)\n    MatchFinder_Normalize3(subValue, p->hash, (size_t)p->hashMask + 1 + p->fixedHashSize);\n    {\n      size_t numSonRefs = p->cyclicBufferSize;\n      if (p->btMode)\n        numSonRefs <<= 1;\n      MatchFinder_Normalize3(subValue, p->son, numSonRefs);\n    }\n  }\n\n  if (p->cyclicBufferPos == p->cyclicBufferSize)\n    p->cyclicBufferPos = 0;\n  \n  MatchFinder_SetLimits(p);\n}\n\n\n/*\n  (lenLimit > maxLen)\n*/\nZ7_FORCE_INLINE\nstatic UInt32 * Hc_GetMatchesSpec(size_t lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,\n    UInt32 *d, unsigned maxLen)\n{\n  /*\n  son[_cyclicBufferPos] = curMatch;\n  for (;;)\n  {\n    UInt32 delta = pos - curMatch;\n    if (cutValue-- == 0 || delta >= _cyclicBufferSize)\n      return d;\n    {\n      const Byte *pb = cur - delta;\n      curMatch = son[_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)];\n      if (pb[maxLen] == cur[maxLen] && *pb == *cur)\n      {\n        UInt32 len = 0;\n        while (++len != lenLimit)\n          if (pb[len] != cur[len])\n            break;\n        if (maxLen < len)\n        {\n          maxLen = len;\n          *d++ = len;\n          *d++ = delta - 1;\n          if (len == lenLimit)\n            return d;\n        }\n      }\n    }\n  }\n  */\n\n  const Byte *lim = cur + lenLimit;\n  son[_cyclicBufferPos] = curMatch;\n\n  do\n  {\n    UInt32 delta;\n\n    if (curMatch == 0)\n      break;\n    // if (curMatch2 >= curMatch) return NULL;\n    delta = pos - curMatch;\n    if (delta >= _cyclicBufferSize)\n      break;\n    {\n      ptrdiff_t diff;\n      curMatch = son[_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)];\n      diff = (ptrdiff_t)0 - (ptrdiff_t)delta;\n      if (cur[maxLen] == cur[(ptrdiff_t)maxLen + diff])\n      {\n        const Byte *c = cur;\n        while (*c == c[diff])\n        {\n          if (++c == lim)\n          {\n            d[0] = (UInt32)(lim - cur);\n            d[1] = delta - 1;\n            return d + 2;\n          }\n        }\n        {\n          const unsigned len = (unsigned)(c - cur);\n          if (maxLen < len)\n          {\n            maxLen = len;\n            d[0] = (UInt32)len;\n            d[1] = delta - 1;\n            d += 2;\n          }\n        }\n      }\n    }\n  }\n  while (--cutValue);\n  \n  return d;\n}\n\n\nZ7_FORCE_INLINE\nUInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,\n    UInt32 *d, UInt32 maxLen)\n{\n  CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;\n  CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);\n  unsigned len0 = 0, len1 = 0;\n\n  UInt32 cmCheck;\n\n  // if (curMatch >= pos) { *ptr0 = *ptr1 = kEmptyHashValue; return NULL; }\n\n  cmCheck = (UInt32)(pos - _cyclicBufferSize);\n  if ((UInt32)pos < _cyclicBufferSize)\n    cmCheck = 0;\n\n  if (cmCheck < curMatch)\n  do\n  {\n    const UInt32 delta = pos - curMatch;\n    {\n      CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)) << 1);\n      const Byte *pb = cur - delta;\n      unsigned len = (len0 < len1 ? len0 : len1);\n      const UInt32 pair0 = pair[0];\n      if (pb[len] == cur[len])\n      {\n        if (++len != lenLimit && pb[len] == cur[len])\n          while (++len != lenLimit)\n            if (pb[len] != cur[len])\n              break;\n        if (maxLen < len)\n        {\n          maxLen = (UInt32)len;\n          *d++ = (UInt32)len;\n          *d++ = delta - 1;\n          if (len == lenLimit)\n          {\n            *ptr1 = pair0;\n            *ptr0 = pair[1];\n            return d;\n          }\n        }\n      }\n      if (pb[len] < cur[len])\n      {\n        *ptr1 = curMatch;\n        // const UInt32 curMatch2 = pair[1];\n        // if (curMatch2 >= curMatch) { *ptr0 = *ptr1 = kEmptyHashValue;  return NULL; }\n        // curMatch = curMatch2;\n        curMatch = pair[1];\n        ptr1 = pair + 1;\n        len1 = len;\n      }\n      else\n      {\n        *ptr0 = curMatch;\n        curMatch = pair[0];\n        ptr0 = pair;\n        len0 = len;\n      }\n    }\n  }\n  while(--cutValue && cmCheck < curMatch);\n\n  *ptr0 = *ptr1 = kEmptyHashValue;\n  return d;\n}\n\n\nstatic void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)\n{\n  CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;\n  CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);\n  unsigned len0 = 0, len1 = 0;\n\n  UInt32 cmCheck;\n\n  cmCheck = (UInt32)(pos - _cyclicBufferSize);\n  if ((UInt32)pos < _cyclicBufferSize)\n    cmCheck = 0;\n\n  if (// curMatch >= pos ||  // failure\n      cmCheck < curMatch)\n  do\n  {\n    const UInt32 delta = pos - curMatch;\n    {\n      CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + (_cyclicBufferPos < delta ? _cyclicBufferSize : 0)) << 1);\n      const Byte *pb = cur - delta;\n      unsigned len = (len0 < len1 ? len0 : len1);\n      if (pb[len] == cur[len])\n      {\n        while (++len != lenLimit)\n          if (pb[len] != cur[len])\n            break;\n        {\n          if (len == lenLimit)\n          {\n            *ptr1 = pair[0];\n            *ptr0 = pair[1];\n            return;\n          }\n        }\n      }\n      if (pb[len] < cur[len])\n      {\n        *ptr1 = curMatch;\n        curMatch = pair[1];\n        ptr1 = pair + 1;\n        len1 = len;\n      }\n      else\n      {\n        *ptr0 = curMatch;\n        curMatch = pair[0];\n        ptr0 = pair;\n        len0 = len;\n      }\n    }\n  }\n  while(--cutValue && cmCheck < curMatch);\n  \n  *ptr0 = *ptr1 = kEmptyHashValue;\n  return;\n}\n\n\n#define MOVE_POS \\\n  p->cyclicBufferPos++; \\\n  p->buffer++; \\\n  { const UInt32 pos1 = p->pos + 1; \\\n    p->pos = pos1; \\\n    if (pos1 == p->posLimit) MatchFinder_CheckLimits(p); }\n\n#define MOVE_POS_RET MOVE_POS return distances;\n\nZ7_NO_INLINE\nstatic void MatchFinder_MovePos(CMatchFinder *p)\n{\n  /* we go here at the end of stream data, when (avail < num_hash_bytes)\n     We don't update sons[cyclicBufferPos << btMode].\n     So (sons) record will contain junk. And we cannot resume match searching\n     to normal operation, even if we will provide more input data in buffer.\n     p->sons[p->cyclicBufferPos << p->btMode] = 0;  // kEmptyHashValue\n     if (p->btMode)\n        p->sons[(p->cyclicBufferPos << p->btMode) + 1] = 0;  // kEmptyHashValue\n  */\n  MOVE_POS\n}\n\n#define GET_MATCHES_HEADER2(minLen, ret_op) \\\n  UInt32 hv; const Byte *cur; UInt32 curMatch; \\\n  UInt32 lenLimit = p->lenLimit; \\\n  if (lenLimit < minLen) { MatchFinder_MovePos(p);  ret_op; } \\\n  cur = p->buffer;\n\n#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return distances)\n#define SKIP_HEADER(minLen)  \\\n  do { GET_MATCHES_HEADER2(minLen, continue)\n\n#define MF_PARAMS(p)  lenLimit, curMatch, p->pos, p->buffer, p->son, \\\n    p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue\n\n#define SKIP_FOOTER  \\\n    SkipMatchesSpec(MF_PARAMS(p)); \\\n    MOVE_POS \\\n  } while (--num);\n\n#define GET_MATCHES_FOOTER_BASE(_maxLen_, func) \\\n  distances = func(MF_PARAMS(p), distances, (UInt32)_maxLen_); \\\n  MOVE_POS_RET\n\n#define GET_MATCHES_FOOTER_BT(_maxLen_) \\\n  GET_MATCHES_FOOTER_BASE(_maxLen_, GetMatchesSpec1)\n\n#define GET_MATCHES_FOOTER_HC(_maxLen_) \\\n  GET_MATCHES_FOOTER_BASE(_maxLen_, Hc_GetMatchesSpec)\n\n\n\n#define UPDATE_maxLen { \\\n    const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)d2; \\\n    const Byte *c = cur + maxLen; \\\n    const Byte *lim = cur + lenLimit; \\\n    for (; c != lim; c++) if (*(c + diff) != *c) break; \\\n    maxLen = (unsigned)(c - cur); }\n\nstatic UInt32* Bt2_MatchFinder_GetMatches(void *_p, UInt32 *distances)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  GET_MATCHES_HEADER(2)\n  HASH2_CALC\n  curMatch = p->hash[hv];\n  p->hash[hv] = p->pos;\n  GET_MATCHES_FOOTER_BT(1)\n}\n\nUInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  GET_MATCHES_HEADER(3)\n  HASH_ZIP_CALC\n  curMatch = p->hash[hv];\n  p->hash[hv] = p->pos;\n  GET_MATCHES_FOOTER_BT(2)\n}\n\n\n#define SET_mmm  \\\n  mmm = p->cyclicBufferSize; \\\n  if (pos < mmm) \\\n    mmm = pos;\n\n\nstatic UInt32* Bt3_MatchFinder_GetMatches(void *_p, UInt32 *distances)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  UInt32 mmm;\n  UInt32 h2, d2, pos;\n  unsigned maxLen;\n  UInt32 *hash;\n  GET_MATCHES_HEADER(3)\n\n  HASH3_CALC\n\n  hash = p->hash;\n  pos = p->pos;\n\n  d2 = pos - hash[h2];\n\n  curMatch = (hash + kFix3HashSize)[hv];\n  \n  hash[h2] = pos;\n  (hash + kFix3HashSize)[hv] = pos;\n\n  SET_mmm\n\n  maxLen = 2;\n\n  if (d2 < mmm && *(cur - d2) == *cur)\n  {\n    UPDATE_maxLen\n    distances[0] = (UInt32)maxLen;\n    distances[1] = d2 - 1;\n    distances += 2;\n    if (maxLen == lenLimit)\n    {\n      SkipMatchesSpec(MF_PARAMS(p));\n      MOVE_POS_RET\n    }\n  }\n  \n  GET_MATCHES_FOOTER_BT(maxLen)\n}\n\n\nstatic UInt32* Bt4_MatchFinder_GetMatches(void *_p, UInt32 *distances)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  UInt32 mmm;\n  UInt32 h2, h3, d2, d3, pos;\n  unsigned maxLen;\n  UInt32 *hash;\n  GET_MATCHES_HEADER(4)\n\n  HASH4_CALC\n\n  hash = p->hash;\n  pos = p->pos;\n\n  d2 = pos - hash                  [h2];\n  d3 = pos - (hash + kFix3HashSize)[h3];\n  curMatch = (hash + kFix4HashSize)[hv];\n\n  hash                  [h2] = pos;\n  (hash + kFix3HashSize)[h3] = pos;\n  (hash + kFix4HashSize)[hv] = pos;\n\n  SET_mmm\n\n  maxLen = 3;\n  \n  for (;;)\n  {\n    if (d2 < mmm && *(cur - d2) == *cur)\n    {\n      distances[0] = 2;\n      distances[1] = d2 - 1;\n      distances += 2;\n      if (*(cur - d2 + 2) == cur[2])\n      {\n        // distances[-2] = 3;\n      }\n      else if (d3 < mmm && *(cur - d3) == *cur)\n      {\n        d2 = d3;\n        distances[1] = d3 - 1;\n        distances += 2;\n      }\n      else\n        break;\n    }\n    else if (d3 < mmm && *(cur - d3) == *cur)\n    {\n      d2 = d3;\n      distances[1] = d3 - 1;\n      distances += 2;\n    }\n    else\n      break;\n  \n    UPDATE_maxLen\n    distances[-2] = (UInt32)maxLen;\n    if (maxLen == lenLimit)\n    {\n      SkipMatchesSpec(MF_PARAMS(p));\n      MOVE_POS_RET\n    }\n    break;\n  }\n  \n  GET_MATCHES_FOOTER_BT(maxLen)\n}\n\n\nstatic UInt32* Bt5_MatchFinder_GetMatches(void *_p, UInt32 *distances)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  UInt32 mmm;\n  UInt32 h2, h3, d2, d3, pos;\n  unsigned maxLen;\n  UInt32 *hash;\n  GET_MATCHES_HEADER(5)\n\n  HASH5_CALC\n\n  hash = p->hash;\n  pos = p->pos;\n\n  d2 = pos - hash                  [h2];\n  d3 = pos - (hash + kFix3HashSize)[h3];\n  // d4 = pos - (hash + kFix4HashSize)[h4];\n\n  curMatch = (hash + kFix5HashSize)[hv];\n\n  hash                  [h2] = pos;\n  (hash + kFix3HashSize)[h3] = pos;\n  // (hash + kFix4HashSize)[h4] = pos;\n  (hash + kFix5HashSize)[hv] = pos;\n\n  SET_mmm\n\n  maxLen = 4;\n\n  for (;;)\n  {\n    if (d2 < mmm && *(cur - d2) == *cur)\n    {\n      distances[0] = 2;\n      distances[1] = d2 - 1;\n      distances += 2;\n      if (*(cur - d2 + 2) == cur[2])\n      {\n      }\n      else if (d3 < mmm && *(cur - d3) == *cur)\n      {\n        distances[1] = d3 - 1;\n        distances += 2;\n        d2 = d3;\n      }\n      else\n        break;\n    }\n    else if (d3 < mmm && *(cur - d3) == *cur)\n    {\n      distances[1] = d3 - 1;\n      distances += 2;\n      d2 = d3;\n    }\n    else\n      break;\n\n    distances[-2] = 3;\n    if (*(cur - d2 + 3) != cur[3])\n      break;\n    UPDATE_maxLen\n    distances[-2] = (UInt32)maxLen;\n    if (maxLen == lenLimit)\n    {\n      SkipMatchesSpec(MF_PARAMS(p));\n      MOVE_POS_RET\n    }\n    break;\n  }\n  \n  GET_MATCHES_FOOTER_BT(maxLen)\n}\n\n\nstatic UInt32* Hc4_MatchFinder_GetMatches(void *_p, UInt32 *distances)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  UInt32 mmm;\n  UInt32 h2, h3, d2, d3, pos;\n  unsigned maxLen;\n  UInt32 *hash;\n  GET_MATCHES_HEADER(4)\n\n  HASH4_CALC\n\n  hash = p->hash;\n  pos = p->pos;\n  \n  d2 = pos - hash                  [h2];\n  d3 = pos - (hash + kFix3HashSize)[h3];\n  curMatch = (hash + kFix4HashSize)[hv];\n\n  hash                  [h2] = pos;\n  (hash + kFix3HashSize)[h3] = pos;\n  (hash + kFix4HashSize)[hv] = pos;\n\n  SET_mmm\n\n  maxLen = 3;\n\n  for (;;)\n  {\n    if (d2 < mmm && *(cur - d2) == *cur)\n    {\n      distances[0] = 2;\n      distances[1] = d2 - 1;\n      distances += 2;\n      if (*(cur - d2 + 2) == cur[2])\n      {\n        // distances[-2] = 3;\n      }\n      else if (d3 < mmm && *(cur - d3) == *cur)\n      {\n        d2 = d3;\n        distances[1] = d3 - 1;\n        distances += 2;\n      }\n      else\n        break;\n    }\n    else if (d3 < mmm && *(cur - d3) == *cur)\n    {\n      d2 = d3;\n      distances[1] = d3 - 1;\n      distances += 2;\n    }\n    else\n      break;\n\n    UPDATE_maxLen\n    distances[-2] = (UInt32)maxLen;\n    if (maxLen == lenLimit)\n    {\n      p->son[p->cyclicBufferPos] = curMatch;\n      MOVE_POS_RET\n    }\n    break;\n  }\n  \n  GET_MATCHES_FOOTER_HC(maxLen)\n}\n\n\nstatic UInt32 * Hc5_MatchFinder_GetMatches(void *_p, UInt32 *distances)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  UInt32 mmm;\n  UInt32 h2, h3, d2, d3, pos;\n  unsigned maxLen;\n  UInt32 *hash;\n  GET_MATCHES_HEADER(5)\n\n  HASH5_CALC\n\n  hash = p->hash;\n  pos = p->pos;\n\n  d2 = pos - hash                  [h2];\n  d3 = pos - (hash + kFix3HashSize)[h3];\n  // d4 = pos - (hash + kFix4HashSize)[h4];\n\n  curMatch = (hash + kFix5HashSize)[hv];\n\n  hash                  [h2] = pos;\n  (hash + kFix3HashSize)[h3] = pos;\n  // (hash + kFix4HashSize)[h4] = pos;\n  (hash + kFix5HashSize)[hv] = pos;\n\n  SET_mmm\n  \n  maxLen = 4;\n\n  for (;;)\n  {\n    if (d2 < mmm && *(cur - d2) == *cur)\n    {\n      distances[0] = 2;\n      distances[1] = d2 - 1;\n      distances += 2;\n      if (*(cur - d2 + 2) == cur[2])\n      {\n      }\n      else if (d3 < mmm && *(cur - d3) == *cur)\n      {\n        distances[1] = d3 - 1;\n        distances += 2;\n        d2 = d3;\n      }\n      else\n        break;\n    }\n    else if (d3 < mmm && *(cur - d3) == *cur)\n    {\n      distances[1] = d3 - 1;\n      distances += 2;\n      d2 = d3;\n    }\n    else\n      break;\n\n    distances[-2] = 3;\n    if (*(cur - d2 + 3) != cur[3])\n      break;\n    UPDATE_maxLen\n    distances[-2] = (UInt32)maxLen;\n    if (maxLen == lenLimit)\n    {\n      p->son[p->cyclicBufferPos] = curMatch;\n      MOVE_POS_RET\n    }\n    break;\n  }\n  \n  GET_MATCHES_FOOTER_HC(maxLen)\n}\n\n\nUInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)\n{\n  GET_MATCHES_HEADER(3)\n  HASH_ZIP_CALC\n  curMatch = p->hash[hv];\n  p->hash[hv] = p->pos;\n  GET_MATCHES_FOOTER_HC(2)\n}\n\n\nstatic void Bt2_MatchFinder_Skip(void *_p, UInt32 num)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  SKIP_HEADER(2)\n  {\n    HASH2_CALC\n    curMatch = p->hash[hv];\n    p->hash[hv] = p->pos;\n  }\n  SKIP_FOOTER\n}\n\nvoid Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  SKIP_HEADER(3)\n  {\n    HASH_ZIP_CALC\n    curMatch = p->hash[hv];\n    p->hash[hv] = p->pos;\n  }\n  SKIP_FOOTER\n}\n\nstatic void Bt3_MatchFinder_Skip(void *_p, UInt32 num)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  SKIP_HEADER(3)\n  {\n    UInt32 h2;\n    UInt32 *hash;\n    HASH3_CALC\n    hash = p->hash;\n    curMatch = (hash + kFix3HashSize)[hv];\n    hash[h2] =\n    (hash + kFix3HashSize)[hv] = p->pos;\n  }\n  SKIP_FOOTER\n}\n\nstatic void Bt4_MatchFinder_Skip(void *_p, UInt32 num)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  SKIP_HEADER(4)\n  {\n    UInt32 h2, h3;\n    UInt32 *hash;\n    HASH4_CALC\n    hash = p->hash;\n    curMatch = (hash + kFix4HashSize)[hv];\n    hash                  [h2] =\n    (hash + kFix3HashSize)[h3] =\n    (hash + kFix4HashSize)[hv] = p->pos;\n  }\n  SKIP_FOOTER\n}\n\nstatic void Bt5_MatchFinder_Skip(void *_p, UInt32 num)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  SKIP_HEADER(5)\n  {\n    UInt32 h2, h3;\n    UInt32 *hash;\n    HASH5_CALC\n    hash = p->hash;\n    curMatch = (hash + kFix5HashSize)[hv];\n    hash                  [h2] =\n    (hash + kFix3HashSize)[h3] =\n    // (hash + kFix4HashSize)[h4] =\n    (hash + kFix5HashSize)[hv] = p->pos;\n  }\n  SKIP_FOOTER\n}\n\n\n#define HC_SKIP_HEADER(minLen) \\\n    do { if (p->lenLimit < minLen) { MatchFinder_MovePos(p); num--; continue; } { \\\n    const Byte *cur; \\\n    UInt32 *hash; \\\n    UInt32 *son; \\\n    UInt32 pos = p->pos; \\\n    UInt32 num2 = num; \\\n    /* (p->pos == p->posLimit) is not allowed here !!! */ \\\n    { const UInt32 rem = p->posLimit - pos; if (num2 >= rem) num2 = rem; } \\\n    num -= num2; \\\n    { const UInt32 cycPos = p->cyclicBufferPos; \\\n      son = p->son + cycPos; \\\n      p->cyclicBufferPos = cycPos + num2; } \\\n    cur = p->buffer; \\\n    hash = p->hash; \\\n    do { \\\n    UInt32 curMatch; \\\n    UInt32 hv;\n\n\n#define HC_SKIP_FOOTER \\\n    cur++;  pos++;  *son++ = curMatch; \\\n    } while (--num2); \\\n    p->buffer = cur; \\\n    p->pos = pos; \\\n    if (pos == p->posLimit) MatchFinder_CheckLimits(p); \\\n    }} while(num); \\\n\n\nstatic void Hc4_MatchFinder_Skip(void *_p, UInt32 num)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  HC_SKIP_HEADER(4)\n\n    UInt32 h2, h3;\n    HASH4_CALC\n    curMatch = (hash + kFix4HashSize)[hv];\n    hash                  [h2] =\n    (hash + kFix3HashSize)[h3] =\n    (hash + kFix4HashSize)[hv] = pos;\n  \n  HC_SKIP_FOOTER\n}\n\n\nstatic void Hc5_MatchFinder_Skip(void *_p, UInt32 num)\n{\n  CMatchFinder *p = (CMatchFinder *)_p;\n  HC_SKIP_HEADER(5)\n  \n    UInt32 h2, h3;\n    HASH5_CALC\n    curMatch = (hash + kFix5HashSize)[hv];\n    hash                  [h2] =\n    (hash + kFix3HashSize)[h3] =\n    // (hash + kFix4HashSize)[h4] =\n    (hash + kFix5HashSize)[hv] = pos;\n  \n  HC_SKIP_FOOTER\n}\n\n\nvoid Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)\n{\n  HC_SKIP_HEADER(3)\n\n    HASH_ZIP_CALC\n    curMatch = hash[hv];\n    hash[hv] = pos;\n\n  HC_SKIP_FOOTER\n}\n\n\nvoid MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable)\n{\n  vTable->Init = MatchFinder_Init;\n  vTable->GetNumAvailableBytes = MatchFinder_GetNumAvailableBytes;\n  vTable->GetPointerToCurrentPos = MatchFinder_GetPointerToCurrentPos;\n  if (!p->btMode)\n  {\n    if (p->numHashBytes <= 4)\n    {\n      vTable->GetMatches = Hc4_MatchFinder_GetMatches;\n      vTable->Skip = Hc4_MatchFinder_Skip;\n    }\n    else\n    {\n      vTable->GetMatches = Hc5_MatchFinder_GetMatches;\n      vTable->Skip = Hc5_MatchFinder_Skip;\n    }\n  }\n  else if (p->numHashBytes == 2)\n  {\n    vTable->GetMatches = Bt2_MatchFinder_GetMatches;\n    vTable->Skip = Bt2_MatchFinder_Skip;\n  }\n  else if (p->numHashBytes == 3)\n  {\n    vTable->GetMatches = Bt3_MatchFinder_GetMatches;\n    vTable->Skip = Bt3_MatchFinder_Skip;\n  }\n  else if (p->numHashBytes == 4)\n  {\n    vTable->GetMatches = Bt4_MatchFinder_GetMatches;\n    vTable->Skip = Bt4_MatchFinder_Skip;\n  }\n  else\n  {\n    vTable->GetMatches = Bt5_MatchFinder_GetMatches;\n    vTable->Skip = Bt5_MatchFinder_Skip;\n  }\n}\n\n\n\nvoid LzFindPrepare(void)\n{\n  #ifndef FORCE_LZFIND_SATUR_SUB_128\n  #ifdef USE_LZFIND_SATUR_SUB_128\n  LZFIND_SATUR_SUB_CODE_FUNC f = NULL;\n  #ifdef MY_CPU_ARM_OR_ARM64\n  {\n    if (CPU_IsSupported_NEON())\n    {\n      // #pragma message (\"=== LzFind NEON\")\n      PRF(printf(\"\\n=== LzFind NEON\\n\"));\n      f = LzFind_SaturSub_128;\n    }\n    // f = 0; // for debug\n  }\n  #else // MY_CPU_ARM_OR_ARM64\n  if (CPU_IsSupported_SSE41())\n  {\n    // #pragma message (\"=== LzFind SSE41\")\n    PRF(printf(\"\\n=== LzFind SSE41\\n\"));\n    f = LzFind_SaturSub_128;\n\n    #ifdef USE_LZFIND_SATUR_SUB_256\n    if (CPU_IsSupported_AVX2())\n    {\n      // #pragma message (\"=== LzFind AVX2\")\n      PRF(printf(\"\\n=== LzFind AVX2\\n\"));\n      f = LzFind_SaturSub_256;\n    }\n    #endif\n  }\n  #endif // MY_CPU_ARM_OR_ARM64\n  g_LzFind_SaturSub = f;\n  #endif // USE_LZFIND_SATUR_SUB_128\n  #endif // FORCE_LZFIND_SATUR_SUB_128\n}\n\n\n#undef MOVE_POS\n#undef MOVE_POS_RET\n#undef PRF\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzFind.h",
    "content": "﻿/* LzFind.h -- Match finder for LZ algorithms\n2024-01-22 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZ_FIND_H\n#define ZIP7_INC_LZ_FIND_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\ntypedef UInt32 CLzRef;\n\ntypedef struct\n{\n  const Byte *buffer;\n  UInt32 pos;\n  UInt32 posLimit;\n  UInt32 streamPos;  /* wrap over Zero is allowed (streamPos < pos). Use (UInt32)(streamPos - pos) */\n  UInt32 lenLimit;\n\n  UInt32 cyclicBufferPos;\n  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */\n\n  Byte streamEndWasReached;\n  Byte btMode;\n  Byte bigHash;\n  Byte directInput;\n\n  UInt32 matchMaxLen;\n  CLzRef *hash;\n  CLzRef *son;\n  UInt32 hashMask;\n  UInt32 cutValue;\n\n  Byte *bufBase;\n  ISeqInStreamPtr stream;\n  \n  UInt32 blockSize;\n  UInt32 keepSizeBefore;\n  UInt32 keepSizeAfter;\n\n  UInt32 numHashBytes;\n  size_t directInputRem;\n  UInt32 historySize;\n  UInt32 fixedHashSize;\n  Byte numHashBytes_Min;\n  Byte numHashOutBits;\n  Byte _pad2_[2];\n  SRes result;\n  UInt32 crc[256];\n  size_t numRefs;\n\n  UInt64 expectedDataSize;\n} CMatchFinder;\n\n#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((const Byte *)(p)->buffer)\n\n#define Inline_MatchFinder_GetNumAvailableBytes(p) ((UInt32)((p)->streamPos - (p)->pos))\n\n/*\n#define Inline_MatchFinder_IsFinishedOK(p) \\\n    ((p)->streamEndWasReached \\\n        && (p)->streamPos == (p)->pos \\\n        && (!(p)->directInput || (p)->directInputRem == 0))\n*/\n      \nint MatchFinder_NeedMove(CMatchFinder *p);\n/* Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); */\nvoid MatchFinder_MoveBlock(CMatchFinder *p);\nvoid MatchFinder_ReadIfRequired(CMatchFinder *p);\n\nvoid MatchFinder_Construct(CMatchFinder *p);\n\n/* (directInput = 0) is default value.\n   It's required to provide correct (directInput) value\n   before calling MatchFinder_Create().\n   You can set (directInput) by any of the following calls:\n     - MatchFinder_SET_DIRECT_INPUT_BUF()\n     - MatchFinder_SET_STREAM()\n     - MatchFinder_SET_STREAM_MODE()\n*/\n\n#define MatchFinder_SET_DIRECT_INPUT_BUF(p, _src_, _srcLen_) { \\\n  (p)->stream = NULL; \\\n  (p)->directInput = 1; \\\n  (p)->buffer = (_src_); \\\n  (p)->directInputRem = (_srcLen_); }\n\n/*\n#define MatchFinder_SET_STREAM_MODE(p) { \\\n  (p)->directInput = 0; }\n*/\n\n#define MatchFinder_SET_STREAM(p, _stream_) { \\\n  (p)->stream = _stream_; \\\n  (p)->directInput = 0; }\n  \n\nint MatchFinder_Create(CMatchFinder *p, UInt32 historySize,\n    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,\n    ISzAllocPtr alloc);\nvoid MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);\nvoid MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);\n\n/*\n#define MatchFinder_INIT_POS(p, val) \\\n    (p)->pos = (val); \\\n    (p)->streamPos = (val);\n*/\n\n// void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);\n#define MatchFinder_REDUCE_OFFSETS(p, subValue) \\\n    (p)->pos -= (subValue); \\\n    (p)->streamPos -= (subValue);\n\n\nUInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,\n    UInt32 *distances, UInt32 maxLen);\n\n/*\nConditions:\n  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.\n  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function\n*/\n\ntypedef void (*Mf_Init_Func)(void *object);\ntypedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);\ntypedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);\ntypedef UInt32 * (*Mf_GetMatches_Func)(void *object, UInt32 *distances);\ntypedef void (*Mf_Skip_Func)(void *object, UInt32);\n\ntypedef struct\n{\n  Mf_Init_Func Init;\n  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;\n  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;\n  Mf_GetMatches_Func GetMatches;\n  Mf_Skip_Func Skip;\n} IMatchFinder2;\n\nvoid MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder2 *vTable);\n\nvoid MatchFinder_Init_LowHash(CMatchFinder *p);\nvoid MatchFinder_Init_HighHash(CMatchFinder *p);\nvoid MatchFinder_Init_4(CMatchFinder *p);\n// void MatchFinder_Init(CMatchFinder *p);\nvoid MatchFinder_Init(void *p);\n\nUInt32* Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);\nUInt32* Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);\n\nvoid Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);\nvoid Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);\n\nvoid LzFindPrepare(void);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzFindMt.c",
    "content": "﻿/* LzFindMt.c -- multithreaded Match finder for LZ algorithms\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n// #include <stdio.h>\n\n#include \"CpuArch.h\"\n\n#include \"LzHash.h\"\n#include \"LzFindMt.h\"\n\n// #define LOG_ITERS\n\n// #define LOG_THREAD\n\n#ifdef LOG_THREAD\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#ifdef LOG_ITERS\n#include <stdio.h>\nextern UInt64 g_NumIters_Tree;\nextern UInt64 g_NumIters_Loop;\nextern UInt64 g_NumIters_Bytes;\n#define LOG_ITER(x) x\n#else\n#define LOG_ITER(x)\n#endif\n\n#define kMtHashBlockSize ((UInt32)1 << 17)\n#define kMtHashNumBlocks (1 << 1)\n\n#define GET_HASH_BLOCK_OFFSET(i)  (((i) & (kMtHashNumBlocks - 1)) * kMtHashBlockSize)\n\n#define kMtBtBlockSize ((UInt32)1 << 16)\n#define kMtBtNumBlocks (1 << 4)\n\n#define GET_BT_BLOCK_OFFSET(i)  (((i) & (kMtBtNumBlocks - 1)) * (size_t)kMtBtBlockSize)\n\n/*\n  HASH functions:\n  We use raw 8/16 bits from a[1] and a[2],\n  xored with crc(a[0]) and crc(a[3]).\n  We check a[0], a[3] only. We don't need to compare a[1] and a[2] in matches.\n  our crc() function provides one-to-one correspondence for low 8-bit values:\n    (crc[0...0xFF] & 0xFF) <-> [0...0xFF]\n*/\n\n#define MF(mt) ((mt)->MatchFinder)\n#define MF_CRC (p->crc)\n\n// #define MF(mt) (&(mt)->MatchFinder)\n// #define MF_CRC (p->MatchFinder.crc)\n\n#define MT_HASH2_CALC \\\n  h2 = (MF_CRC[cur[0]] ^ cur[1]) & (kHash2Size - 1);\n\n#define MT_HASH3_CALC { \\\n  UInt32 temp = MF_CRC[cur[0]] ^ cur[1]; \\\n  h2 = temp & (kHash2Size - 1); \\\n  h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }\n\n/*\n#define MT_HASH3_CALC__NO_2 { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }\n\n#define MT_HASH4_CALC { \\\n  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \\\n  h2 = temp & (kHash2Size - 1); \\\n  temp ^= ((UInt32)cur[2] << 8); \\\n  h3 = temp & (kHash3Size - 1); \\\n  h4 = (temp ^ (p->crc[cur[3]] << kLzHash_CrcShift_1)) & p->hash4Mask; }\n  // (kHash4Size - 1);\n*/\n\n\nZ7_NO_INLINE\nstatic void MtSync_Construct(CMtSync *p)\n{\n  p->affinityGroup = -1;\n  p->affinityInGroup = 0;\n  p->affinity = 0;\n  p->wasCreated = False;\n  p->csWasInitialized = False;\n  p->csWasEntered = False;\n  Thread_CONSTRUCT(&p->thread)\n  Event_Construct(&p->canStart);\n  Event_Construct(&p->wasStopped);\n  Semaphore_Construct(&p->freeSemaphore);\n  Semaphore_Construct(&p->filledSemaphore);\n}\n\n\n// #define DEBUG_BUFFER_LOCK   // define it to debug lock state\n\n#ifdef DEBUG_BUFFER_LOCK\n#include <stdlib.h>\n#define BUFFER_MUST_BE_LOCKED(p)    if (!(p)->csWasEntered) exit(1);\n#define BUFFER_MUST_BE_UNLOCKED(p)  if ( (p)->csWasEntered) exit(1);\n#else\n#define BUFFER_MUST_BE_LOCKED(p)\n#define BUFFER_MUST_BE_UNLOCKED(p)\n#endif\n\n#define LOCK_BUFFER(p) { \\\n    BUFFER_MUST_BE_UNLOCKED(p); \\\n    CriticalSection_Enter(&(p)->cs); \\\n    (p)->csWasEntered = True; }\n\n#define UNLOCK_BUFFER(p) { \\\n    BUFFER_MUST_BE_LOCKED(p); \\\n    CriticalSection_Leave(&(p)->cs); \\\n    (p)->csWasEntered = False; }\n\n\nZ7_NO_INLINE\nstatic UInt32 MtSync_GetNextBlock(CMtSync *p)\n{\n  UInt32 numBlocks = 0;\n  if (p->needStart)\n  {\n    BUFFER_MUST_BE_UNLOCKED(p)\n    p->numProcessedBlocks = 1;\n    p->needStart = False;\n    p->stopWriting = False;\n    p->exit = False;\n    Event_Reset(&p->wasStopped);\n    Event_Set(&p->canStart);\n  }\n  else\n  {\n    UNLOCK_BUFFER(p)\n    // we free current block\n    numBlocks = p->numProcessedBlocks++;\n    Semaphore_Release1(&p->freeSemaphore);\n  }\n\n  // buffer is UNLOCKED here\n  Semaphore_Wait(&p->filledSemaphore);\n  LOCK_BUFFER(p)\n  return numBlocks;\n}\n\n\n/* if Writing (Processing) thread was started, we must call MtSync_StopWriting() */\n\nZ7_NO_INLINE\nstatic void MtSync_StopWriting(CMtSync *p)\n{\n  if (!Thread_WasCreated(&p->thread) || p->needStart)\n    return;\n\n    PRF(printf(\"\\nMtSync_StopWriting %p\\n\", p));\n\n  if (p->csWasEntered)\n  {\n    /* we don't use buffer in this thread after StopWriting().\n       So we UNLOCK buffer.\n       And we restore default UNLOCKED state for stopped thread */\n    UNLOCK_BUFFER(p)\n  }\n\n  /* We send (p->stopWriting) message and release freeSemaphore\n     to free current block.\n     So the thread will see (p->stopWriting) at some\n     iteration after Wait(freeSemaphore).\n     The thread doesn't need to fill all avail free blocks,\n     so we can get fast thread stop.\n  */\n\n  p->stopWriting = True;\n  Semaphore_Release1(&p->freeSemaphore); // check semaphore count !!!\n\n    PRF(printf(\"\\nMtSync_StopWriting %p : Event_Wait(&p->wasStopped)\\n\", p));\n  Event_Wait(&p->wasStopped);\n    PRF(printf(\"\\nMtSync_StopWriting %p : Event_Wait() finsihed\\n\", p));\n\n  /* 21.03 : we don't restore samaphore counters here.\n     We will recreate and reinit samaphores in next start */\n\n  p->needStart = True;\n}\n\n\nZ7_NO_INLINE\nstatic void MtSync_Destruct(CMtSync *p)\n{\n    PRF(printf(\"\\nMtSync_Destruct %p\\n\", p));\n  \n  if (Thread_WasCreated(&p->thread))\n  {\n    /* we want thread to be in Stopped state before sending EXIT command.\n       note: stop(btSync) will stop (htSync) also */\n    MtSync_StopWriting(p);\n    /* thread in Stopped state here : (p->needStart == true) */\n    p->exit = True;\n    // if (p->needStart)  // it's (true)\n    Event_Set(&p->canStart);  // we send EXIT command to thread\n    Thread_Wait_Close(&p->thread);  // we wait thread finishing\n  }\n\n  if (p->csWasInitialized)\n  {\n    CriticalSection_Delete(&p->cs);\n    p->csWasInitialized = False;\n  }\n  p->csWasEntered = False;\n\n  Event_Close(&p->canStart);\n  Event_Close(&p->wasStopped);\n  Semaphore_Close(&p->freeSemaphore);\n  Semaphore_Close(&p->filledSemaphore);\n\n  p->wasCreated = False;\n}\n\n\n// #define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }\n// we want to get real system error codes here instead of SZ_ERROR_THREAD\n#define RINOK_THREAD(x)  RINOK_WRes(x)\n\n\n// call it before each new file (when new starting is required):\nZ7_NO_INLINE\nstatic SRes MtSync_Init(CMtSync *p, UInt32 numBlocks)\n{\n  WRes wres;\n  // BUFFER_MUST_BE_UNLOCKED(p)\n  if (!p->needStart || p->csWasEntered)\n    return SZ_ERROR_FAIL;\n  wres = Semaphore_OptCreateInit(&p->freeSemaphore, numBlocks, numBlocks);\n  if (wres == 0)\n    wres = Semaphore_OptCreateInit(&p->filledSemaphore, 0, numBlocks);\n  return MY_SRes_HRESULT_FROM_WRes(wres);\n}\n\n\nstatic WRes MtSync_Create_WRes(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj)\n{\n  WRes wres;\n\n  if (p->wasCreated)\n    return SZ_OK;\n\n  RINOK_THREAD(CriticalSection_Init(&p->cs))\n  p->csWasInitialized = True;\n  p->csWasEntered = False;\n\n  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart))\n  RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped))\n\n  p->needStart = True;\n  p->exit = True;  /* p->exit is unused before (canStart) Event.\n     But in case of some unexpected code failure we will get fast exit from thread */\n\n  // return ERROR_TOO_MANY_POSTS; // for debug\n  // return EINVAL; // for debug\n\n#ifdef _WIN32\n  if (p->affinityGroup >= 0)\n    wres = Thread_Create_With_Group(&p->thread, startAddress, obj,\n        (unsigned)(UInt32)p->affinityGroup, (CAffinityMask)p->affinityInGroup);\n  else\n#endif\n  if (p->affinity != 0)\n    wres = Thread_Create_With_Affinity(&p->thread, startAddress, obj, (CAffinityMask)p->affinity);\n  else\n    wres = Thread_Create(&p->thread, startAddress, obj);\n\n  RINOK_THREAD(wres)\n  p->wasCreated = True;\n  return SZ_OK;\n}\n\n\nZ7_NO_INLINE\nstatic SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj)\n{\n  const WRes wres = MtSync_Create_WRes(p, startAddress, obj);\n  if (wres == 0)\n    return 0;\n  MtSync_Destruct(p);\n  return MY_SRes_HRESULT_FROM_WRes(wres);\n}\n\n\n// ---------- HASH THREAD ----------\n\n#define kMtMaxValForNormalize 0xFFFFFFFF\n// #define kMtMaxValForNormalize ((1 << 21)) // for debug\n// #define kNormalizeAlign (1 << 7) // alignment for speculated accesses\n\n#ifdef MY_CPU_LE_UNALIGN\n  #define GetUi24hi_from32(p) ((UInt32)GetUi32(p) >> 8)\n#else\n  #define GetUi24hi_from32(p) ((p)[1] ^ ((UInt32)(p)[2] << 8) ^ ((UInt32)(p)[3] << 16))\n#endif\n\n#define GetHeads_DECL(name) \\\n    static void GetHeads ## name(const Byte *p, UInt32 pos, \\\n      UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc)\n\n#define GetHeads_LOOP(v) \\\n    for (; numHeads != 0; numHeads--) { \\\n      const UInt32 value = (v); \\\n      p++; \\\n      *heads++ = pos - hash[value]; \\\n      hash[value] = pos++; }\n\n#define DEF_GetHeads2(name, v, action) \\\n    GetHeads_DECL(name) { action \\\n    GetHeads_LOOP(v) }\n \n#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;)\n\nDEF_GetHeads2(2, GetUi16(p), UNUSED_VAR(hashMask); UNUSED_VAR(crc); )\nDEF_GetHeads(3,  (crc[p[0]] ^ GetUi16(p + 1)) & hashMask)\nDEF_GetHeads2(3b, GetUi16(p) ^ ((UInt32)(p)[2] << 16), UNUSED_VAR(hashMask); UNUSED_VAR(crc); )\n// BT3 is not good for crc collisions for big hashMask values.\n\n/*\nGetHeads_DECL(3b)\n{\n  UNUSED_VAR(hashMask);\n  UNUSED_VAR(crc);\n  {\n  const Byte *pLim = p + numHeads;\n  if (numHeads == 0)\n    return;\n  pLim--;\n  while (p < pLim)\n  {\n    UInt32 v1 = GetUi32(p);\n    UInt32 v0 = v1 & 0xFFFFFF;\n    UInt32 h0, h1;\n    p += 2;\n    v1 >>= 8;\n    h0 = hash[v0]; hash[v0] = pos; heads[0] = pos - h0; pos++;\n    h1 = hash[v1]; hash[v1] = pos; heads[1] = pos - h1; pos++;\n    heads += 2;\n  }\n  if (p == pLim)\n  {\n    UInt32 v0 = GetUi16(p) ^ ((UInt32)(p)[2] << 16);\n    *heads = pos - hash[v0];\n    hash[v0] = pos;\n  }\n  }\n}\n*/\n\n/*\nGetHeads_DECL(4)\n{\n  unsigned sh = 0;\n  UNUSED_VAR(crc)\n  while ((hashMask & 0x80000000) == 0)\n  {\n    hashMask <<= 1;\n    sh++;\n  }\n  GetHeads_LOOP((GetUi32(p) * 0xa54a1) >> sh)\n}\n#define GetHeads4b GetHeads4\n*/\n\n#define USE_GetHeads_LOCAL_CRC\n\n#ifdef USE_GetHeads_LOCAL_CRC\n\nGetHeads_DECL(4)\n{\n  UInt32 crc0[256];\n  UInt32 crc1[256];\n  {\n    unsigned i;\n    for (i = 0; i < 256; i++)\n    {\n      UInt32 v = crc[i];\n      crc0[i] = v & hashMask;\n      crc1[i] = (v << kLzHash_CrcShift_1) & hashMask;\n      // crc1[i] = rotlFixed(v, 8) & hashMask;\n    }\n  }\n  GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ (UInt32)GetUi16(p+1))\n}\n\nGetHeads_DECL(4b)\n{\n  UInt32 crc0[256];\n  {\n    unsigned i;\n    for (i = 0; i < 256; i++)\n      crc0[i] = crc[i] & hashMask;\n  }\n  GetHeads_LOOP(crc0[p[0]] ^ GetUi24hi_from32(p))\n}\n\nGetHeads_DECL(5)\n{\n  UInt32 crc0[256];\n  UInt32 crc1[256];\n  UInt32 crc2[256];\n  {\n    unsigned i;\n    for (i = 0; i < 256; i++)\n    {\n      UInt32 v = crc[i];\n      crc0[i] = v & hashMask;\n      crc1[i] = (v << kLzHash_CrcShift_1) & hashMask;\n      crc2[i] = (v << kLzHash_CrcShift_2) & hashMask;\n    }\n  }\n  GetHeads_LOOP(crc0[p[0]] ^ crc1[p[3]] ^ crc2[p[4]] ^ (UInt32)GetUi16(p+1))\n}\n\nGetHeads_DECL(5b)\n{\n  UInt32 crc0[256];\n  UInt32 crc1[256];\n  {\n    unsigned i;\n    for (i = 0; i < 256; i++)\n    {\n      UInt32 v = crc[i];\n      crc0[i] = v & hashMask;\n      crc1[i] = (v << kLzHash_CrcShift_1) & hashMask;\n    }\n  }\n  GetHeads_LOOP(crc0[p[0]] ^ crc1[p[4]] ^ GetUi24hi_from32(p))\n}\n\n#else\n\nDEF_GetHeads(4,  (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (UInt32)GetUi16(p+1)) & hashMask)\nDEF_GetHeads(4b, (crc[p[0]] ^ GetUi24hi_from32(p)) & hashMask)\nDEF_GetHeads(5,  (crc[p[0]] ^ (crc[p[3]] << kLzHash_CrcShift_1) ^ (crc[p[4]] << kLzHash_CrcShift_2) ^ (UInt32)GetUi16(p + 1)) & hashMask)\nDEF_GetHeads(5b, (crc[p[0]] ^ (crc[p[4]] << kLzHash_CrcShift_1) ^ GetUi24hi_from32(p)) & hashMask)\n\n#endif\n \n\nstatic void HashThreadFunc(CMatchFinderMt *mt)\n{\n  CMtSync *p = &mt->hashSync;\n    PRF(printf(\"\\nHashThreadFunc\\n\"));\n  \n  for (;;)\n  {\n    UInt32 blockIndex = 0;\n      PRF(printf(\"\\nHashThreadFunc : Event_Wait(&p->canStart)\\n\"));\n    Event_Wait(&p->canStart);\n      PRF(printf(\"\\nHashThreadFunc : Event_Wait(&p->canStart) : after \\n\"));\n    if (p->exit)\n    {\n      PRF(printf(\"\\nHashThreadFunc : exit \\n\"));\n      return;\n    }\n\n    MatchFinder_Init_HighHash(MF(mt));\n\n    for (;;)\n    {\n      PRF(printf(\"Hash thread block = %d pos = %d\\n\", (unsigned)blockIndex, mt->MatchFinder->pos));\n\n      {\n        CMatchFinder *mf = MF(mt);\n        if (MatchFinder_NeedMove(mf))\n        {\n          CriticalSection_Enter(&mt->btSync.cs);\n          CriticalSection_Enter(&mt->hashSync.cs);\n          {\n            const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf);\n            ptrdiff_t offset;\n            MatchFinder_MoveBlock(mf);\n            offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf);\n            mt->pointerToCurPos -= offset;\n            mt->buffer -= offset;\n          }\n          CriticalSection_Leave(&mt->hashSync.cs);\n          CriticalSection_Leave(&mt->btSync.cs);\n          continue;\n        }\n\n        Semaphore_Wait(&p->freeSemaphore);\n\n        if (p->exit) // exit is unexpected here. But we check it here for some failure case\n          return;\n\n        // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore)\n        if (p->stopWriting)\n          break;\n\n        MatchFinder_ReadIfRequired(mf);\n        {\n          UInt32 *heads = mt->hashBuf + GET_HASH_BLOCK_OFFSET(blockIndex++);\n          UInt32 num = Inline_MatchFinder_GetNumAvailableBytes(mf);\n          heads[0] = 2;\n          heads[1] = num;\n\n          /* heads[1] contains the number of avail bytes:\n             if (avail < mf->numHashBytes) :\n             {\n               it means that stream was finished\n               HASH_THREAD and BT_TREAD must move position for heads[1] (avail) bytes.\n               HASH_THREAD doesn't stop,\n               HASH_THREAD fills only the header (2 numbers) for all next blocks:\n               {2, NumHashBytes - 1}, {2,0}, {2,0}, ... , {2,0}\n             }\n             else\n             {\n               HASH_THREAD and BT_TREAD must move position for (heads[0] - 2) bytes;\n             }\n          */\n\n          if (num >= mf->numHashBytes)\n          {\n            num = num - mf->numHashBytes + 1;\n            if (num > kMtHashBlockSize - 2)\n              num = kMtHashBlockSize - 2;\n\n            if (mf->pos > (UInt32)kMtMaxValForNormalize - num)\n            {\n              const UInt32 subValue = (mf->pos - mf->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1);\n              MatchFinder_REDUCE_OFFSETS(mf, subValue)\n              MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1);\n            }\n\n            heads[0] = 2 + num;\n            mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc);\n          }\n\n          mf->pos += num;  // wrap over zero is allowed at the end of stream\n          mf->buffer += num;\n        }\n      }\n\n      Semaphore_Release1(&p->filledSemaphore);\n    } // for() processing end\n\n    // p->numBlocks_Sent = blockIndex;\n    Event_Set(&p->wasStopped);\n  } // for() thread end\n}\n\n\n\n\n// ---------- BT THREAD ----------\n\n/* we use one variable instead of two (cyclicBufferPos == pos) before CyclicBuf wrap.\n   here we define fixed offset of (p->pos) from (p->cyclicBufferPos) */\n#define CYC_TO_POS_OFFSET 0\n// #define CYC_TO_POS_OFFSET 1 // for debug\n\n#define MFMT_GM_INLINE\n\n#ifdef MFMT_GM_INLINE\n\n/*\n  we use size_t for (pos) instead of UInt32\n  to eliminate \"movsx\" BUG in old MSVC x64 compiler.\n*/\n\n\nUInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,\n    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,\n    UInt32 *posRes);\n\n#endif\n\n\nstatic void BtGetMatches(CMatchFinderMt *p, UInt32 *d)\n{\n  UInt32 numProcessed = 0;\n  UInt32 curPos = 2;\n  \n  /* GetMatchesSpec() functions don't create (len = 1)\n     in [len, dist] match pairs, if (p->numHashBytes >= 2)\n     Also we suppose here that (matchMaxLen >= 2).\n     So the following code for (reserve) is not required\n     UInt32 reserve = (p->matchMaxLen * 2);\n     const UInt32 kNumHashBytes_Max = 5; // BT_HASH_BYTES_MAX\n     if (reserve < kNumHashBytes_Max - 1)\n        reserve = kNumHashBytes_Max - 1;\n     const UInt32 limit = kMtBtBlockSize - (reserve);\n  */\n\n  const UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);\n\n  d[1] = p->hashNumAvail;\n\n  if (p->failure_BT)\n  {\n    // printf(\"\\n == 1 BtGetMatches() p->failure_BT\\n\");\n    d[0] = 0;\n    // d[1] = 0;\n    return;\n  }\n  \n  while (curPos < limit)\n  {\n    if (p->hashBufPos == p->hashBufPosLimit)\n    {\n      // MatchFinderMt_GetNextBlock_Hash(p);\n      UInt32 avail;\n      {\n        const UInt32 bi = MtSync_GetNextBlock(&p->hashSync);\n        const UInt32 k = GET_HASH_BLOCK_OFFSET(bi);\n        const UInt32 *h = p->hashBuf + k;\n        avail = h[1];\n        p->hashBufPosLimit = k + h[0];\n        p->hashNumAvail = avail;\n        p->hashBufPos = k + 2;\n      }\n\n      {\n        /* we must prevent UInt32 overflow for avail total value,\n           if avail was increased with new hash block */\n        UInt32 availSum = numProcessed + avail;\n        if (availSum < numProcessed)\n          availSum = (UInt32)(Int32)-1;\n        d[1] = availSum;\n      }\n\n      if (avail >= p->numHashBytes)\n        continue;\n\n      // if (p->hashBufPos != p->hashBufPosLimit) exit(1);\n\n      /* (avail < p->numHashBytes)\n         It means that stream was finished.\n         And (avail) - is a number of remaining bytes,\n         we fill (d) for (avail) bytes for LZ_THREAD (receiver).\n         but we don't update (p->pos) and (p->cyclicBufferPos) here in BT_THREAD */\n\n      /* here we suppose that we have space enough:\n         (kMtBtBlockSize - curPos >= p->hashNumAvail) */\n      p->hashNumAvail = 0;\n      d[0] = curPos + avail;\n      d += curPos;\n      for (; avail != 0; avail--)\n        *d++ = 0;\n      return;\n    }\n    {\n      UInt32 size = p->hashBufPosLimit - p->hashBufPos;\n      UInt32 pos = p->pos;\n      UInt32 cyclicBufferPos = p->cyclicBufferPos;\n      UInt32 lenLimit = p->matchMaxLen;\n      if (lenLimit >= p->hashNumAvail)\n        lenLimit = p->hashNumAvail;\n      {\n        UInt32 size2 = p->hashNumAvail - lenLimit + 1;\n        if (size2 < size)\n          size = size2;\n        size2 = p->cyclicBufferSize - cyclicBufferPos;\n        if (size2 < size)\n          size = size2;\n      }\n      \n      if (pos > (UInt32)kMtMaxValForNormalize - size)\n      {\n        const UInt32 subValue = (pos - p->cyclicBufferSize); // & ~(UInt32)(kNormalizeAlign - 1);\n        pos -= subValue;\n        p->pos = pos;\n        MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2);\n      }\n\n      #ifndef MFMT_GM_INLINE\n      while (curPos < limit && size-- != 0)\n      {\n        UInt32 *startDistances = d + curPos;\n        UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++],\n            pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,\n            startDistances + 1, p->numHashBytes - 1) - startDistances);\n        *startDistances = num - 1;\n        curPos += num;\n        cyclicBufferPos++;\n        pos++;\n        p->buffer++;\n      }\n      #else\n      {\n        UInt32 posRes = pos;\n        const UInt32 *d_end;\n        {\n          d_end = GetMatchesSpecN_2(\n              p->buffer + lenLimit - 1,\n              pos, p->buffer, p->son, p->cutValue, d + curPos,\n              p->numHashBytes - 1, p->hashBuf + p->hashBufPos,\n              d + limit, p->hashBuf + p->hashBufPos + size,\n              cyclicBufferPos, p->cyclicBufferSize,\n              &posRes);\n        }\n        {\n          if (!d_end)\n          {\n            // printf(\"\\n == 2 BtGetMatches() p->failure_BT\\n\");\n            // internal data failure\n            p->failure_BT = True;\n            d[0] = 0;\n            // d[1] = 0;\n            return;\n          }\n        }\n        curPos = (UInt32)(d_end - d);\n        {\n          const UInt32 processed = posRes - pos;\n          pos = posRes;\n          p->hashBufPos += processed;\n          cyclicBufferPos += processed;\n          p->buffer += processed;\n        }\n      }\n      #endif\n\n      {\n        const UInt32 processed = pos - p->pos;\n        numProcessed += processed;\n        p->hashNumAvail -= processed;\n        p->pos = pos;\n      }\n      if (cyclicBufferPos == p->cyclicBufferSize)\n        cyclicBufferPos = 0;\n      p->cyclicBufferPos = cyclicBufferPos;\n    }\n  }\n  \n  d[0] = curPos;\n}\n\n\nstatic void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex)\n{\n  CMtSync *sync = &p->hashSync;\n  \n  BUFFER_MUST_BE_UNLOCKED(sync)\n  \n  if (!sync->needStart)\n  {\n    LOCK_BUFFER(sync)\n  }\n  \n  BtGetMatches(p, p->btBuf + GET_BT_BLOCK_OFFSET(globalBlockIndex));\n  \n  /* We suppose that we have called GetNextBlock() from start.\n     So buffer is LOCKED */\n\n  UNLOCK_BUFFER(sync)\n}\n\n\nZ7_NO_INLINE\nstatic void BtThreadFunc(CMatchFinderMt *mt)\n{\n  CMtSync *p = &mt->btSync;\n  for (;;)\n  {\n    UInt32 blockIndex = 0;\n    Event_Wait(&p->canStart);\n\n    for (;;)\n    {\n        PRF(printf(\"  BT thread block = %d  pos = %d\\n\", (unsigned)blockIndex, mt->pos));\n      /* (p->exit == true) is possible after (p->canStart) at first loop iteration\n         and is unexpected after more Wait(freeSemaphore) iterations */\n      if (p->exit)\n        return;\n\n      Semaphore_Wait(&p->freeSemaphore);\n      \n      // for faster stop : we check (p->stopWriting) after Wait(freeSemaphore)\n      if (p->stopWriting)\n        break;\n\n      BtFillBlock(mt, blockIndex++);\n      \n      Semaphore_Release1(&p->filledSemaphore);\n    }\n\n    // we stop HASH_THREAD here\n    MtSync_StopWriting(&mt->hashSync);\n\n    // p->numBlocks_Sent = blockIndex;\n    Event_Set(&p->wasStopped);\n  }\n}\n\n\nvoid MatchFinderMt_Construct(CMatchFinderMt *p)\n{\n  p->hashBuf = NULL;\n  MtSync_Construct(&p->hashSync);\n  MtSync_Construct(&p->btSync);\n}\n\nstatic void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->hashBuf);\n  p->hashBuf = NULL;\n}\n\nvoid MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc)\n{\n  /*\n     HASH_THREAD can use CriticalSection(s) btSync.cs and hashSync.cs.\n     So we must be sure that HASH_THREAD will not use CriticalSection(s)\n     after deleting CriticalSection here.\n\n     we call ReleaseStream(p)\n       that calls StopWriting(btSync)\n         that calls StopWriting(hashSync), if it's required to stop HASH_THREAD.\n     after StopWriting() it's safe to destruct MtSync(s) in any order */\n\n  MatchFinderMt_ReleaseStream(p);\n\n  MtSync_Destruct(&p->btSync);\n  MtSync_Destruct(&p->hashSync);\n\n  LOG_ITER(\n  printf(\"\\nTree %9d * %7d iter = %9d = sum  :  bytes = %9d\\n\",\n      (UInt32)(g_NumIters_Tree / 1000),\n      (UInt32)(((UInt64)g_NumIters_Loop * 1000) / (g_NumIters_Tree + 1)),\n      (UInt32)(g_NumIters_Loop / 1000),\n      (UInt32)(g_NumIters_Bytes / 1000)\n      ));\n\n  MatchFinderMt_FreeMem(p, alloc);\n}\n\n\n#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)\n#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)\n\n\nstatic THREAD_FUNC_DECL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p);  return 0; }\nstatic THREAD_FUNC_DECL BtThreadFunc2(void *p)\n{\n  Byte allocaDummy[0x180];\n  unsigned i = 0;\n  for (i = 0; i < 16; i++)\n    allocaDummy[i] = (Byte)0;\n  if (allocaDummy[0] == 0)\n    BtThreadFunc((CMatchFinderMt *)p);\n  return 0;\n}\n\n\nSRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,\n    UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc)\n{\n  CMatchFinder *mf = MF(p);\n  p->historySize = historySize;\n  if (kMtBtBlockSize <= matchMaxLen * 4)\n    return SZ_ERROR_PARAM;\n  if (!p->hashBuf)\n  {\n    p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, ((size_t)kHashBufferSize + (size_t)kBtBufferSize) * sizeof(UInt32));\n    if (!p->hashBuf)\n      return SZ_ERROR_MEM;\n    p->btBuf = p->hashBuf + kHashBufferSize;\n  }\n  keepAddBufferBefore += (kHashBufferSize + kBtBufferSize);\n  keepAddBufferAfter += kMtHashBlockSize;\n  if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc))\n    return SZ_ERROR_MEM;\n\n  RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p))\n  RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p))\n  return SZ_OK;\n}\n\n\nSRes MatchFinderMt_InitMt(CMatchFinderMt *p)\n{\n  RINOK(MtSync_Init(&p->hashSync, kMtHashNumBlocks))\n  return MtSync_Init(&p->btSync, kMtBtNumBlocks);\n}\n\n\nstatic void MatchFinderMt_Init(void *_p)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  CMatchFinder *mf = MF(p);\n  \n  p->btBufPos =\n  p->btBufPosLimit = NULL;\n  p->hashBufPos =\n  p->hashBufPosLimit = 0;\n  p->hashNumAvail = 0; // 21.03\n  \n  p->failure_BT = False;\n\n  /* Init without data reading. We don't want to read data in this thread */\n  MatchFinder_Init_4(mf);\n\n  MatchFinder_Init_LowHash(mf);\n  \n  p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf);\n  p->btNumAvailBytes = 0;\n  p->failure_LZ_BT = False;\n  // p->failure_LZ_LZ = False;\n  \n  p->lzPos =\n      1; // optimal smallest value\n      // 0; // for debug: ignores match to start\n      // kNormalizeAlign; // for debug\n\n  p->hash = mf->hash;\n  p->fixedHashSize = mf->fixedHashSize;\n  // p->hash4Mask = mf->hash4Mask;\n  p->crc = mf->crc;\n  // memcpy(p->crc, mf->crc, sizeof(mf->crc));\n\n  p->son = mf->son;\n  p->matchMaxLen = mf->matchMaxLen;\n  p->numHashBytes = mf->numHashBytes;\n  \n  /* (mf->pos) and (mf->streamPos) were already initialized to 1 in MatchFinder_Init_4() */\n  // mf->streamPos = mf->pos = 1; // optimal smallest value\n      // 0; // for debug: ignores match to start\n      // kNormalizeAlign; // for debug\n\n  /* we must init (p->pos = mf->pos) for BT, because\n     BT code needs (p->pos == delta_value_for_empty_hash_record == mf->pos) */\n  p->pos = mf->pos; // do not change it\n  \n  p->cyclicBufferPos = (p->pos - CYC_TO_POS_OFFSET);\n  p->cyclicBufferSize = mf->cyclicBufferSize;\n  p->buffer = mf->buffer;\n  p->cutValue = mf->cutValue;\n  // p->son[0] = p->son[1] = 0; // unused: to init skipped record for speculated accesses.\n}\n\n\n/* ReleaseStream is required to finish multithreading */\nvoid MatchFinderMt_ReleaseStream(CMatchFinderMt *p)\n{\n  // Sleep(1); // for debug\n  MtSync_StopWriting(&p->btSync);\n  // Sleep(200); // for debug\n  /* p->MatchFinder->ReleaseStream(); */\n}\n\n\nZ7_NO_INLINE\nstatic UInt32 MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p)\n{\n  if (p->failure_LZ_BT)\n    p->btBufPos = p->failureBuf;\n  else\n  {\n    const UInt32 bi = MtSync_GetNextBlock(&p->btSync);\n    const UInt32 *bt = p->btBuf + GET_BT_BLOCK_OFFSET(bi);\n    {\n      const UInt32 numItems = bt[0];\n      p->btBufPosLimit = bt + numItems;\n      p->btNumAvailBytes = bt[1];\n      p->btBufPos = bt + 2;\n      if (numItems < 2 || numItems > kMtBtBlockSize)\n      {\n        p->failureBuf[0] = 0;\n        p->btBufPos = p->failureBuf;\n        p->btBufPosLimit = p->failureBuf + 1;\n        p->failure_LZ_BT = True;\n        // p->btNumAvailBytes = 0;\n        /* we don't want to decrease AvailBytes, that was load before.\n            that can be unxepected for the code that have loaded anopther value before */\n      }\n    }\n  \n    if (p->lzPos >= (UInt32)kMtMaxValForNormalize - (UInt32)kMtBtBlockSize)\n    {\n      /* we don't check (lzPos) over exact avail bytes in (btBuf).\n         (fixedHashSize) is small, so normalization is fast */\n      const UInt32 subValue = (p->lzPos - p->historySize - 1); // & ~(UInt32)(kNormalizeAlign - 1);\n      p->lzPos -= subValue;\n      MatchFinder_Normalize3(subValue, p->hash, p->fixedHashSize);\n    }\n  }\n  return p->btNumAvailBytes;\n}\n\n\n\nstatic const Byte * MatchFinderMt_GetPointerToCurrentPos(void *_p)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  return p->pointerToCurPos;\n}\n\n\n#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p);\n\n\nstatic UInt32 MatchFinderMt_GetNumAvailableBytes(void *_p)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  if (p->btBufPos != p->btBufPosLimit)\n    return p->btNumAvailBytes;\n  return MatchFinderMt_GetNextBlock_Bt(p);\n}\n\n\n// #define CHECK_FAILURE_LZ(_match_, _pos_) if (_match_ >= _pos_) { p->failure_LZ_LZ = True;  return d; }\n#define CHECK_FAILURE_LZ(_match_, _pos_)\n\nstatic UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d)\n{\n  UInt32 h2, c2;\n  UInt32 *hash = p->hash;\n  const Byte *cur = p->pointerToCurPos;\n  const UInt32 m = p->lzPos;\n  MT_HASH2_CALC\n      \n  c2 = hash[h2];\n  hash[h2] = m;\n\n  if (c2 >= matchMinPos)\n  {\n    CHECK_FAILURE_LZ(c2, m)\n    if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0])\n    {\n      *d++ = 2;\n      *d++ = m - c2 - 1;\n    }\n  }\n  \n  return d;\n}\n\nstatic UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d)\n{\n  UInt32 h2, h3, c2, c3;\n  UInt32 *hash = p->hash;\n  const Byte *cur = p->pointerToCurPos;\n  const UInt32 m = p->lzPos;\n  MT_HASH3_CALC\n\n  c2 = hash[h2];\n  c3 = (hash + kFix3HashSize)[h3];\n  \n  hash[h2] = m;\n  (hash + kFix3HashSize)[h3] = m;\n\n  if (c2 >= matchMinPos)\n  {\n    CHECK_FAILURE_LZ(c2, m)\n    if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0])\n    {\n      d[1] = m - c2 - 1;\n      if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2])\n      {\n        d[0] = 3;\n        return d + 2;\n      }\n      d[0] = 2;\n      d += 2;\n    }\n  }\n  \n  if (c3 >= matchMinPos)\n  {\n    CHECK_FAILURE_LZ(c3, m)\n    if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0])\n    {\n      *d++ = 3;\n      *d++ = m - c3 - 1;\n    }\n  }\n  \n  return d;\n}\n\n\n#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++;\n\n/*\nstatic\nUInt32* MatchFinderMt_GetMatches_Bt4(CMatchFinderMt *p, UInt32 *d)\n{\n  const UInt32 *bt = p->btBufPos;\n  const UInt32 len = *bt++;\n  const UInt32 *btLim = bt + len;\n  UInt32 matchMinPos;\n  UInt32 avail = p->btNumAvailBytes - 1;\n  p->btBufPos = btLim;\n\n  {\n    p->btNumAvailBytes = avail;\n\n    #define BT_HASH_BYTES_MAX 5\n      \n    matchMinPos = p->lzPos;\n\n    if (len != 0)\n      matchMinPos -= bt[1];\n    else if (avail < (BT_HASH_BYTES_MAX - 1) - 1)\n    {\n      INCREASE_LZ_POS\n      return d;\n    }\n    else\n    {\n      const UInt32 hs = p->historySize;\n      if (matchMinPos > hs)\n        matchMinPos -= hs;\n      else\n        matchMinPos = 1;\n    }\n  }\n\n  for (;;)\n  {\n  \n  UInt32 h2, h3, c2, c3;\n  UInt32 *hash = p->hash;\n  const Byte *cur = p->pointerToCurPos;\n  UInt32 m = p->lzPos;\n  MT_HASH3_CALC\n\n  c2 = hash[h2];\n  c3 = (hash + kFix3HashSize)[h3];\n \n  hash[h2] = m;\n  (hash + kFix3HashSize)[h3] = m;\n\n  if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0])\n  {\n    d[1] = m - c2 - 1;\n    if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2])\n    {\n      d[0] = 3;\n      d += 2;\n      break;\n    }\n    // else\n    {\n      d[0] = 2;\n      d += 2;\n    }\n  }\n  if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0])\n  {\n    *d++ = 3;\n    *d++ = m - c3 - 1;\n  }\n  break;\n  }\n\n  if (len != 0)\n  {\n    do\n    {\n      const UInt32 v0 = bt[0];\n      const UInt32 v1 = bt[1];\n      bt += 2;\n      d[0] = v0;\n      d[1] = v1;\n      d += 2;\n    }\n    while (bt != btLim);\n  }\n  INCREASE_LZ_POS\n  return d;\n}\n*/\n\n\nstatic UInt32 * MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *d)\n{\n  UInt32 h2, h3, /* h4, */ c2, c3 /* , c4 */;\n  UInt32 *hash = p->hash;\n  const Byte *cur = p->pointerToCurPos;\n  const UInt32 m = p->lzPos;\n  MT_HASH3_CALC\n  // MT_HASH4_CALC\n  c2 = hash[h2];\n  c3 = (hash + kFix3HashSize)[h3];\n  // c4 = (hash + kFix4HashSize)[h4];\n  \n  hash[h2] = m;\n  (hash + kFix3HashSize)[h3] = m;\n  // (hash + kFix4HashSize)[h4] = m;\n\n  // #define BT5_USE_H2\n  // #ifdef BT5_USE_H2\n  if (c2 >= matchMinPos && cur[(ptrdiff_t)c2 - (ptrdiff_t)m] == cur[0])\n  {\n    d[1] = m - c2 - 1;\n    if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 2] == cur[2])\n    {\n      // d[0] = (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3]) ? 4 : 3;\n      // return d + 2;\n\n      if (cur[(ptrdiff_t)c2 - (ptrdiff_t)m + 3] == cur[3])\n      {\n        d[0] = 4;\n        return d + 2;\n      }\n      d[0] = 3;\n      d += 2;\n\n      #ifdef BT5_USE_H4\n      if (c4 >= matchMinPos)\n        if (\n          cur[(ptrdiff_t)c4 - (ptrdiff_t)m]     == cur[0] &&\n          cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3]\n          )\n      {\n        *d++ = 4;\n        *d++ = m - c4 - 1;\n      }\n      #endif\n      return d;\n    }\n    d[0] = 2;\n    d += 2;\n  }\n  // #endif\n  \n  if (c3 >= matchMinPos && cur[(ptrdiff_t)c3 - (ptrdiff_t)m] == cur[0])\n  {\n    d[1] = m - c3 - 1;\n    if (cur[(ptrdiff_t)c3 - (ptrdiff_t)m + 3] == cur[3])\n    {\n      d[0] = 4;\n      return d + 2;\n    }\n    d[0] = 3;\n    d += 2;\n  }\n\n  #ifdef BT5_USE_H4\n  if (c4 >= matchMinPos)\n    if (\n      cur[(ptrdiff_t)c4 - (ptrdiff_t)m]     == cur[0] &&\n      cur[(ptrdiff_t)c4 - (ptrdiff_t)m + 3] == cur[3]\n      )\n    {\n      *d++ = 4;\n      *d++ = m - c4 - 1;\n    }\n  #endif\n  \n  return d;\n}\n\n\nstatic UInt32 * MatchFinderMt2_GetMatches(void *_p, UInt32 *d)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  const UInt32 *bt = p->btBufPos;\n  const UInt32 len = *bt++;\n  const UInt32 *btLim = bt + len;\n  p->btBufPos = btLim;\n  p->btNumAvailBytes--;\n  INCREASE_LZ_POS\n  {\n    while (bt != btLim)\n    {\n      const UInt32 v0 = bt[0];\n      const UInt32 v1 = bt[1];\n      bt += 2;\n      d[0] = v0;\n      d[1] = v1;\n      d += 2;\n    }\n  }\n  return d;\n}\n\n\n\nstatic UInt32 * MatchFinderMt_GetMatches(void *_p, UInt32 *d)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  const UInt32 *bt = p->btBufPos;\n  UInt32 len = *bt++;\n  const UInt32 avail = p->btNumAvailBytes - 1;\n  p->btNumAvailBytes = avail;\n  p->btBufPos = bt + len;\n  if (len == 0)\n  {\n    #define BT_HASH_BYTES_MAX 5\n    if (avail >= (BT_HASH_BYTES_MAX - 1) - 1)\n    {\n      UInt32 m = p->lzPos;\n      if (m > p->historySize)\n        m -= p->historySize;\n      else\n        m = 1;\n      d = p->MixMatchesFunc(p, m, d);\n    }\n  }\n  else\n  {\n    /*\n      first match pair from BinTree: (match_len, match_dist),\n      (match_len >= numHashBytes).\n      MixMatchesFunc() inserts only hash matches that are nearer than (match_dist)\n    */\n    d = p->MixMatchesFunc(p, p->lzPos - bt[1], d);\n    // if (d) // check for failure\n    do\n    {\n      const UInt32 v0 = bt[0];\n      const UInt32 v1 = bt[1];\n      bt += 2;\n      d[0] = v0;\n      d[1] = v1;\n      d += 2;\n    }\n    while (len -= 2);\n  }\n  INCREASE_LZ_POS\n  return d;\n}\n\n#define SKIP_HEADER2_MT  do { GET_NEXT_BLOCK_IF_REQUIRED\n#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash;\n#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += (size_t)*p->btBufPos + 1; } while (--num != 0);\n\nstatic void MatchFinderMt0_Skip(void *_p, UInt32 num)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  SKIP_HEADER2_MT { p->btNumAvailBytes--;\n  SKIP_FOOTER_MT\n}\n\nstatic void MatchFinderMt2_Skip(void *_p, UInt32 num)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  SKIP_HEADER_MT(2)\n      UInt32 h2;\n      MT_HASH2_CALC\n      hash[h2] = p->lzPos;\n  SKIP_FOOTER_MT\n}\n\nstatic void MatchFinderMt3_Skip(void *_p, UInt32 num)\n{\n  CMatchFinderMt *p = (CMatchFinderMt *)_p;\n  SKIP_HEADER_MT(3)\n      UInt32 h2, h3;\n      MT_HASH3_CALC\n      (hash + kFix3HashSize)[h3] =\n      hash[                h2] =\n        p->lzPos;\n  SKIP_FOOTER_MT\n}\n\n/*\n// MatchFinderMt4_Skip() is similar to MatchFinderMt3_Skip().\n// The difference is that MatchFinderMt3_Skip() updates hash for last 3 bytes of stream.\n\nstatic void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num)\n{\n  SKIP_HEADER_MT(4)\n      UInt32 h2, h3; // h4\n      MT_HASH3_CALC\n      // MT_HASH4_CALC\n      // (hash + kFix4HashSize)[h4] =\n      (hash + kFix3HashSize)[h3] =\n      hash[                h2] =\n        p->lzPos;\n  SKIP_FOOTER_MT\n}\n*/\n\nvoid MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable)\n{\n  vTable->Init = MatchFinderMt_Init;\n  vTable->GetNumAvailableBytes = MatchFinderMt_GetNumAvailableBytes;\n  vTable->GetPointerToCurrentPos = MatchFinderMt_GetPointerToCurrentPos;\n  vTable->GetMatches = MatchFinderMt_GetMatches;\n  \n  switch (MF(p)->numHashBytes)\n  {\n    case 2:\n      p->GetHeadsFunc = GetHeads2;\n      p->MixMatchesFunc = NULL;\n      vTable->Skip = MatchFinderMt0_Skip;\n      vTable->GetMatches = MatchFinderMt2_GetMatches;\n      break;\n    case 3:\n      p->GetHeadsFunc = MF(p)->bigHash ? GetHeads3b : GetHeads3;\n      p->MixMatchesFunc = MixMatches2;\n      vTable->Skip = MatchFinderMt2_Skip;\n      break;\n    case 4:\n      p->GetHeadsFunc = MF(p)->bigHash ? GetHeads4b : GetHeads4;\n\n      // it's fast inline version of GetMatches()\n      // vTable->GetMatches = MatchFinderMt_GetMatches_Bt4;\n\n      p->MixMatchesFunc = MixMatches3;\n      vTable->Skip = MatchFinderMt3_Skip;\n      break;\n    default:\n      p->GetHeadsFunc = MF(p)->bigHash ? GetHeads5b : GetHeads5;\n      p->MixMatchesFunc = MixMatches4;\n      vTable->Skip =\n          MatchFinderMt3_Skip;\n          // MatchFinderMt4_Skip;\n      break;\n  }\n}\n\n#undef RINOK_THREAD\n#undef PRF\n#undef MF\n#undef GetUi24hi_from32\n#undef LOCK_BUFFER\n#undef UNLOCK_BUFFER\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzFindMt.h",
    "content": "﻿/* LzFindMt.h -- multithreaded Match finder for LZ algorithms\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZ_FIND_MT_H\n#define ZIP7_INC_LZ_FIND_MT_H\n\n#include \"LzFind.h\"\n#include \"Threads.h\"\n\nEXTERN_C_BEGIN\n\ntypedef struct\n{\n  UInt32 numProcessedBlocks;\n  Int32 affinityGroup;\n  UInt64 affinityInGroup;\n  UInt64 affinity;\n  CThread thread;\n\n  BoolInt wasCreated;\n  BoolInt needStart;\n  BoolInt csWasInitialized;\n  BoolInt csWasEntered;\n\n  BoolInt exit;\n  BoolInt stopWriting;\n\n  CAutoResetEvent canStart;\n  CAutoResetEvent wasStopped;\n  CSemaphore freeSemaphore;\n  CSemaphore filledSemaphore;\n  CCriticalSection cs;\n  // UInt32 numBlocks_Sent;\n} CMtSync;\n\n\nstruct CMatchFinderMt_;\n\ntypedef UInt32 * (*Mf_Mix_Matches)(struct CMatchFinderMt_ *p, UInt32 matchMinPos, UInt32 *distances);\n\n/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */\n#define kMtCacheLineDummy 128\n\ntypedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos,\n  UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc);\n\ntypedef struct CMatchFinderMt_\n{\n  /* LZ */\n  const Byte *pointerToCurPos;\n  UInt32 *btBuf;\n  const UInt32 *btBufPos;\n  const UInt32 *btBufPosLimit;\n  UInt32 lzPos;\n  UInt32 btNumAvailBytes;\n\n  UInt32 *hash;\n  UInt32 fixedHashSize;\n  // UInt32 hash4Mask;\n  UInt32 historySize;\n  const UInt32 *crc;\n\n  Mf_Mix_Matches MixMatchesFunc;\n  UInt32 failure_LZ_BT; // failure in BT transfered to LZ\n  // UInt32 failure_LZ_LZ; // failure in LZ tables\n  UInt32 failureBuf[1];\n  // UInt32 crc[256];\n\n  /* LZ + BT */\n  CMtSync btSync;\n  Byte btDummy[kMtCacheLineDummy];\n\n  /* BT */\n  UInt32 *hashBuf;\n  UInt32 hashBufPos;\n  UInt32 hashBufPosLimit;\n  UInt32 hashNumAvail;\n  UInt32 failure_BT;\n\n\n  CLzRef *son;\n  UInt32 matchMaxLen;\n  UInt32 numHashBytes;\n  UInt32 pos;\n  const Byte *buffer;\n  UInt32 cyclicBufferPos;\n  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */\n  UInt32 cutValue;\n\n  /* BT + Hash */\n  CMtSync hashSync;\n  /* Byte hashDummy[kMtCacheLineDummy]; */\n  \n  /* Hash */\n  Mf_GetHeads GetHeadsFunc;\n  CMatchFinder *MatchFinder;\n  // CMatchFinder MatchFinder;\n} CMatchFinderMt;\n\n// only for Mt part\nvoid MatchFinderMt_Construct(CMatchFinderMt *p);\nvoid MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc);\n\nSRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore,\n    UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc);\nvoid MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder2 *vTable);\n\n/* call MatchFinderMt_InitMt() before IMatchFinder::Init() */\nSRes MatchFinderMt_InitMt(CMatchFinderMt *p);\nvoid MatchFinderMt_ReleaseStream(CMatchFinderMt *p);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzFindOpt.c",
    "content": "﻿/* LzFindOpt.c -- multithreaded Match finder for LZ algorithms\n2023-04-02 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"CpuArch.h\"\n#include \"LzFind.h\"\n\n// #include \"LzFindMt.h\"\n\n// #define LOG_ITERS\n\n// #define LOG_THREAD\n\n#ifdef LOG_THREAD\n#include <stdio.h>\n#define PRF(x) x\n#else\n// #define PRF(x)\n#endif\n\n#ifdef LOG_ITERS\n#include <stdio.h>\nUInt64 g_NumIters_Tree;\nUInt64 g_NumIters_Loop;\nUInt64 g_NumIters_Bytes;\n#define LOG_ITER(x) x\n#else\n#define LOG_ITER(x)\n#endif\n\n// ---------- BT THREAD ----------\n\n#define USE_SON_PREFETCH\n#define USE_LONG_MATCH_OPT\n\n#define kEmptyHashValue 0\n\n// #define CYC_TO_POS_OFFSET 0\n\n// #define CYC_TO_POS_OFFSET 1 // for debug\n\n/*\nZ7_NO_INLINE\nUInt32 * Z7_FASTCALL GetMatchesSpecN_1(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,\n    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size, UInt32 *posRes)\n{\n  do\n  {\n    UInt32 delta;\n    if (hash == size)\n      break;\n    delta = *hash++;\n\n    if (delta == 0 || delta > (UInt32)pos)\n      return NULL;\n\n    lenLimit++;\n\n    if (delta == (UInt32)pos)\n    {\n      CLzRef *ptr1 = son + ((size_t)pos << 1) - CYC_TO_POS_OFFSET * 2;\n      *d++ = 0;\n      ptr1[0] = kEmptyHashValue;\n      ptr1[1] = kEmptyHashValue;\n    }\nelse\n{\n  UInt32 *_distances = ++d;\n\n  CLzRef *ptr0 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2 + 1;\n  CLzRef *ptr1 = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;\n\n  const Byte *len0 = cur, *len1 = cur;\n  UInt32 cutValue = _cutValue;\n  const Byte *maxLen = cur + _maxLen;\n\n  for (LOG_ITER(g_NumIters_Tree++);;)\n  {\n    LOG_ITER(g_NumIters_Loop++);\n    {\n      const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;\n      CLzRef *pair = son + ((size_t)(((ptrdiff_t)pos - CYC_TO_POS_OFFSET) + diff) << 1);\n      const Byte *len = (len0 < len1 ? len0 : len1);\n\n    #ifdef USE_SON_PREFETCH\n      const UInt32 pair0 = *pair;\n    #endif\n\n      if (len[diff] == len[0])\n      {\n        if (++len != lenLimit && len[diff] == len[0])\n          while (++len != lenLimit)\n          {\n            LOG_ITER(g_NumIters_Bytes++);\n            if (len[diff] != len[0])\n              break;\n          }\n        if (maxLen < len)\n        {\n          maxLen = len;\n          *d++ = (UInt32)(len - cur);\n          *d++ = delta - 1;\n          \n          if (len == lenLimit)\n          {\n            const UInt32 pair1 = pair[1];\n            *ptr1 =\n              #ifdef USE_SON_PREFETCH\n                pair0;\n              #else\n                pair[0];\n              #endif\n            *ptr0 = pair1;\n\n            _distances[-1] = (UInt32)(d - _distances);\n\n            #ifdef USE_LONG_MATCH_OPT\n\n                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)\n                  break;\n\n            {\n              for (;;)\n              {\n                hash++;\n                pos++;\n                cur++;\n                lenLimit++;\n                {\n                  CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;\n                  #if 0\n                  *(UInt64 *)(void *)ptr = ((const UInt64 *)(const void *)ptr)[diff];\n                  #else\n                  const UInt32 p0 = ptr[0 + (diff * 2)];\n                  const UInt32 p1 = ptr[1 + (diff * 2)];\n                  ptr[0] = p0;\n                  ptr[1] = p1;\n                  // ptr[0] = ptr[0 + (diff * 2)];\n                  // ptr[1] = ptr[1 + (diff * 2)];\n                  #endif\n                }\n                // PrintSon(son + 2, pos - 1);\n                // printf(\"\\npos = %x delta = %x\\n\", pos, delta);\n                len++;\n                *d++ = 2;\n                *d++ = (UInt32)(len - cur);\n                *d++ = delta - 1;\n                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)\n                  break;\n              }\n            }\n            #endif\n\n            break;\n          }\n        }\n      }\n\n      {\n        const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff);\n        if (len[diff] < len[0])\n        {\n          delta = pair[1];\n          if (delta >= curMatch)\n            return NULL;\n          *ptr1 = curMatch;\n          ptr1 = pair + 1;\n          len1 = len;\n        }\n        else\n        {\n          delta = *pair;\n          if (delta >= curMatch)\n            return NULL;\n          *ptr0 = curMatch;\n          ptr0 = pair;\n          len0 = len;\n        }\n\n        delta = (UInt32)pos - delta;\n \n        if (--cutValue == 0 || delta >= pos)\n        {\n          *ptr0 = *ptr1 = kEmptyHashValue;\n          _distances[-1] = (UInt32)(d - _distances);\n          break;\n        }\n      }\n    }\n  } // for (tree iterations)\n}\n    pos++;\n    cur++;\n  }\n  while (d < limit);\n  *posRes = (UInt32)pos;\n  return d;\n}\n*/\n\n/* define cbs if you use 2 functions.\n       GetMatchesSpecN_1() :  (pos <  _cyclicBufferSize)\n       GetMatchesSpecN_2() :  (pos >= _cyclicBufferSize)\n\n  do not define cbs if you use 1 function:\n       GetMatchesSpecN_2()\n*/\n\n// #define cbs _cyclicBufferSize\n\n/*\n  we use size_t for (pos) and (_cyclicBufferPos_ instead of UInt32\n  to eliminate \"movsx\" BUG in old MSVC x64 compiler.\n*/\n\nUInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,\n    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,\n    UInt32 *posRes);\n\nZ7_NO_INLINE\nUInt32 * Z7_FASTCALL GetMatchesSpecN_2(const Byte *lenLimit, size_t pos, const Byte *cur, CLzRef *son,\n    UInt32 _cutValue, UInt32 *d, size_t _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,\n    UInt32 *posRes)\n{\n  do // while (hash != size)\n  {\n    UInt32 delta;\n    \n  #ifndef cbs\n    UInt32 cbs;\n  #endif\n\n    if (hash == size)\n      break;\n\n    delta = *hash++;\n\n    if (delta == 0)\n      return NULL;\n\n    lenLimit++;\n\n  #ifndef cbs\n    cbs = _cyclicBufferSize;\n    if ((UInt32)pos < cbs)\n    {\n      if (delta > (UInt32)pos)\n        return NULL;\n      cbs = (UInt32)pos;\n    }\n  #endif\n\n    if (delta >= cbs)\n    {\n      CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);\n      *d++ = 0;\n      ptr1[0] = kEmptyHashValue;\n      ptr1[1] = kEmptyHashValue;\n    }\nelse\n{\n  UInt32 *_distances = ++d;\n\n  CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;\n  CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);\n\n  UInt32 cutValue = _cutValue;\n  const Byte *len0 = cur, *len1 = cur;\n  const Byte *maxLen = cur + _maxLen;\n\n  // if (cutValue == 0) { *ptr0 = *ptr1 = kEmptyHashValue; } else\n  for (LOG_ITER(g_NumIters_Tree++);;)\n  {\n    LOG_ITER(g_NumIters_Loop++);\n    {\n      // SPEC code\n      CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - (ptrdiff_t)delta\n          + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)\n          ) << 1);\n\n      const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;\n      const Byte *len = (len0 < len1 ? len0 : len1);\n\n    #ifdef USE_SON_PREFETCH\n      const UInt32 pair0 = *pair;\n    #endif\n\n      if (len[diff] == len[0])\n      {\n        if (++len != lenLimit && len[diff] == len[0])\n          while (++len != lenLimit)\n          {\n            LOG_ITER(g_NumIters_Bytes++);\n            if (len[diff] != len[0])\n              break;\n          }\n        if (maxLen < len)\n        {\n          maxLen = len;\n          *d++ = (UInt32)(len - cur);\n          *d++ = delta - 1;\n          \n          if (len == lenLimit)\n          {\n            const UInt32 pair1 = pair[1];\n            *ptr1 =\n              #ifdef USE_SON_PREFETCH\n                pair0;\n              #else\n                pair[0];\n              #endif\n            *ptr0 = pair1;\n\n            _distances[-1] = (UInt32)(d - _distances);\n\n            #ifdef USE_LONG_MATCH_OPT\n\n                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)\n                  break;\n\n            {\n              for (;;)\n              {\n                *d++ = 2;\n                *d++ = (UInt32)(lenLimit - cur);\n                *d++ = delta - 1;\n                cur++;\n                lenLimit++;\n                // SPEC\n                _cyclicBufferPos++;\n                {\n                  // SPEC code\n                  CLzRef *dest = son + ((size_t)(_cyclicBufferPos) << 1);\n                  const CLzRef *src = dest + ((diff\n                      + (ptrdiff_t)(UInt32)((_cyclicBufferPos < delta) ? cbs : 0)) << 1);\n                  // CLzRef *ptr = son + ((size_t)(pos) << 1) - CYC_TO_POS_OFFSET * 2;\n                  #if 0\n                  *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src);\n                  #else\n                  const UInt32 p0 = src[0];\n                  const UInt32 p1 = src[1];\n                  dest[0] = p0;\n                  dest[1] = p1;\n                  #endif\n                }\n                pos++;\n                hash++;\n                if (hash == size || *hash != delta || lenLimit[diff] != lenLimit[0] || d >= limit)\n                  break;\n              } // for() end for long matches\n            }\n            #endif\n\n            break; // break from TREE iterations\n          }\n        }\n      }\n      {\n        const UInt32 curMatch = (UInt32)pos - delta; // (UInt32)(pos + diff);\n        if (len[diff] < len[0])\n        {\n          delta = pair[1];\n          *ptr1 = curMatch;\n          ptr1 = pair + 1;\n          len1 = len;\n          if (delta >= curMatch)\n            return NULL;\n        }\n        else\n        {\n          delta = *pair;\n          *ptr0 = curMatch;\n          ptr0 = pair;\n          len0 = len;\n          if (delta >= curMatch)\n            return NULL;\n        }\n        delta = (UInt32)pos - delta;\n \n        if (--cutValue == 0 || delta >= cbs)\n        {\n          *ptr0 = *ptr1 = kEmptyHashValue;\n          _distances[-1] = (UInt32)(d - _distances);\n          break;\n        }\n      }\n    }\n  } // for (tree iterations)\n}\n    pos++;\n    _cyclicBufferPos++;\n    cur++;\n  }\n  while (d < limit);\n  *posRes = (UInt32)pos;\n  return d;\n}\n\n\n\n/*\ntypedef UInt32 uint32plus; // size_t\n\nUInt32 * Z7_FASTCALL GetMatchesSpecN_3(uint32plus lenLimit, size_t pos, const Byte *cur, CLzRef *son,\n    UInt32 _cutValue, UInt32 *d, uint32plus _maxLen, const UInt32 *hash, const UInt32 *limit, const UInt32 *size,\n    size_t _cyclicBufferPos, UInt32 _cyclicBufferSize,\n    UInt32 *posRes)\n{\n  do // while (hash != size)\n  {\n    UInt32 delta;\n\n  #ifndef cbs\n    UInt32 cbs;\n  #endif\n\n    if (hash == size)\n      break;\n\n    delta = *hash++;\n\n    if (delta == 0)\n      return NULL;\n\n  #ifndef cbs\n    cbs = _cyclicBufferSize;\n    if ((UInt32)pos < cbs)\n    {\n      if (delta > (UInt32)pos)\n        return NULL;\n      cbs = (UInt32)pos;\n    }\n  #endif\n    \n    if (delta >= cbs)\n    {\n      CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);\n      *d++ = 0;\n      ptr1[0] = kEmptyHashValue;\n      ptr1[1] = kEmptyHashValue;\n    }\nelse\n{\n  CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;\n  CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);\n  UInt32 *_distances = ++d;\n  uint32plus len0 = 0, len1 = 0;\n  UInt32 cutValue = _cutValue;\n  uint32plus maxLen = _maxLen;\n  // lenLimit++; // const Byte *lenLimit = cur + _lenLimit;\n\n  for (LOG_ITER(g_NumIters_Tree++);;)\n  {\n    LOG_ITER(g_NumIters_Loop++);\n    {\n      // const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;\n      CLzRef *pair = son + ((size_t)((ptrdiff_t)_cyclicBufferPos - delta\n          + (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)\n          ) << 1);\n      const Byte *pb = cur - delta;\n      uint32plus len = (len0 < len1 ? len0 : len1);\n\n    #ifdef USE_SON_PREFETCH\n      const UInt32 pair0 = *pair;\n    #endif\n\n      if (pb[len] == cur[len])\n      {\n        if (++len != lenLimit && pb[len] == cur[len])\n          while (++len != lenLimit)\n            if (pb[len] != cur[len])\n              break;\n        if (maxLen < len)\n        {\n          maxLen = len;\n          *d++ = (UInt32)len;\n          *d++ = delta - 1;\n          if (len == lenLimit)\n          {\n            {\n              const UInt32 pair1 = pair[1];\n              *ptr0 = pair1;\n              *ptr1 =\n              #ifdef USE_SON_PREFETCH\n                pair0;\n              #else\n                pair[0];\n              #endif\n            }\n\n            _distances[-1] = (UInt32)(d - _distances);\n\n            #ifdef USE_LONG_MATCH_OPT\n\n                if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit)\n                  break;\n\n            {\n              const ptrdiff_t diff = (ptrdiff_t)0 - (ptrdiff_t)delta;\n              for (;;)\n              {\n                *d++ = 2;\n                *d++ = (UInt32)lenLimit;\n                *d++ = delta - 1;\n                _cyclicBufferPos++;\n                {\n                  CLzRef *dest = son + ((size_t)_cyclicBufferPos << 1);\n                  const CLzRef *src = dest + ((diff +\n                      (ptrdiff_t)(UInt32)(_cyclicBufferPos < delta ? cbs : 0)) << 1);\n                #if 0\n                  *(UInt64 *)(void *)dest = *((const UInt64 *)(const void *)src);\n                #else\n                  const UInt32 p0 = src[0];\n                  const UInt32 p1 = src[1];\n                  dest[0] = p0;\n                  dest[1] = p1;\n                #endif\n                }\n                hash++;\n                pos++;\n                cur++;\n                pb++;\n                if (hash == size || *hash != delta || pb[lenLimit] != cur[lenLimit] || d >= limit)\n                  break;\n              }\n            }\n            #endif\n\n            break;\n          }\n        }\n      }\n      {\n        const UInt32 curMatch = (UInt32)pos - delta;\n        if (pb[len] < cur[len])\n        {\n          delta = pair[1];\n          *ptr1 = curMatch;\n          ptr1 = pair + 1;\n          len1 = len;\n        }\n        else\n        {\n          delta = *pair;\n          *ptr0 = curMatch;\n          ptr0 = pair;\n          len0 = len;\n        }\n\n        {\n          if (delta >= curMatch)\n            return NULL;\n          delta = (UInt32)pos - delta;\n          if (delta >= cbs\n              // delta >= _cyclicBufferSize || delta >= pos\n              || --cutValue == 0)\n          {\n            *ptr0 = *ptr1 = kEmptyHashValue;\n            _distances[-1] = (UInt32)(d - _distances);\n            break;\n          }\n        }\n      }\n    }\n  } // for (tree iterations)\n}\n    pos++;\n    _cyclicBufferPos++;\n    cur++;\n  }\n  while (d < limit);\n  *posRes = (UInt32)pos;\n  return d;\n}\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzHash.h",
    "content": "﻿/* LzHash.h -- HASH constants for LZ algorithms\n2023-03-05 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZ_HASH_H\n#define ZIP7_INC_LZ_HASH_H\n\n/*\n  (kHash2Size >= (1 <<  8)) : Required\n  (kHash3Size >= (1 << 16)) : Required\n*/\n\n#define kHash2Size (1 << 10)\n#define kHash3Size (1 << 16)\n// #define kHash4Size (1 << 20)\n\n#define kFix3HashSize (kHash2Size)\n#define kFix4HashSize (kHash2Size + kHash3Size)\n// #define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)\n\n/*\n  We use up to 3 crc values for hash:\n    crc0\n    crc1 << Shift_1\n    crc2 << Shift_2\n  (Shift_1 = 5) and (Shift_2 = 10) is good tradeoff.\n  Small values for Shift are not good for collision rate.\n  Big value for Shift_2 increases the minimum size\n  of hash table, that will be slow for small files.\n*/\n\n#define kLzHash_CrcShift_1 5\n#define kLzHash_CrcShift_2 10\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Lzma2Dec.c",
    "content": "﻿/* Lzma2Dec.c -- LZMA2 Decoder\n2024-03-01 : Igor Pavlov : Public domain */\n\n/* #define SHOW_DEBUG_INFO */\n\n#include \"Precomp.h\"\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#include <string.h>\n\n#include \"Lzma2Dec.h\"\n\n/*\n00000000  -  End of data\n00000001 U U  -  Uncompressed, reset dic, need reset state and set new prop\n00000010 U U  -  Uncompressed, no reset\n100uuuuu U U P P  -  LZMA, no reset\n101uuuuu U U P P  -  LZMA, reset state\n110uuuuu U U P P S  -  LZMA, reset state + set new prop\n111uuuuu U U P P S  -  LZMA, reset state + set new prop, reset dic\n\n  u, U - Unpack Size\n  P - Pack Size\n  S - Props\n*/\n\n#define LZMA2_CONTROL_COPY_RESET_DIC 1\n\n#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)\n\n#define LZMA2_LCLP_MAX 4\n#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\ntypedef enum\n{\n  LZMA2_STATE_CONTROL,\n  LZMA2_STATE_UNPACK0,\n  LZMA2_STATE_UNPACK1,\n  LZMA2_STATE_PACK0,\n  LZMA2_STATE_PACK1,\n  LZMA2_STATE_PROP,\n  LZMA2_STATE_DATA,\n  LZMA2_STATE_DATA_CONT,\n  LZMA2_STATE_FINISHED,\n  LZMA2_STATE_ERROR\n} ELzma2State;\n\nstatic SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)\n{\n  UInt32 dicSize;\n  if (prop > 40)\n    return SZ_ERROR_UNSUPPORTED;\n  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);\n  props[0] = (Byte)LZMA2_LCLP_MAX;\n  props[1] = (Byte)(dicSize);\n  props[2] = (Byte)(dicSize >> 8);\n  props[3] = (Byte)(dicSize >> 16);\n  props[4] = (Byte)(dicSize >> 24);\n  return SZ_OK;\n}\n\nSRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)\n{\n  Byte props[LZMA_PROPS_SIZE];\n  RINOK(Lzma2Dec_GetOldProps(prop, props))\n  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);\n}\n\nSRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)\n{\n  Byte props[LZMA_PROPS_SIZE];\n  RINOK(Lzma2Dec_GetOldProps(prop, props))\n  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);\n}\n\nvoid Lzma2Dec_Init(CLzma2Dec *p)\n{\n  p->state = LZMA2_STATE_CONTROL;\n  p->needInitLevel = 0xE0;\n  p->isExtraMode = False;\n  p->unpackSize = 0;\n  \n  // p->decoder.dicPos = 0; // we can use it instead of full init\n  LzmaDec_Init(&p->decoder);\n}\n\n// ELzma2State\nstatic unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)\n{\n  switch (p->state)\n  {\n    case LZMA2_STATE_CONTROL:\n      p->isExtraMode = False;\n      p->control = b;\n      PRF(printf(\"\\n %8X\", (unsigned)p->decoder.dicPos));\n      PRF(printf(\" %02X\", (unsigned)b));\n      if (b == 0)\n        return LZMA2_STATE_FINISHED;\n      if (LZMA2_IS_UNCOMPRESSED_STATE(p))\n      {\n        if (b == LZMA2_CONTROL_COPY_RESET_DIC)\n          p->needInitLevel = 0xC0;\n        else if (b > 2 || p->needInitLevel == 0xE0)\n          return LZMA2_STATE_ERROR;\n      }\n      else\n      {\n        if (b < p->needInitLevel)\n          return LZMA2_STATE_ERROR;\n        p->needInitLevel = 0;\n        p->unpackSize = (UInt32)(b & 0x1F) << 16;\n      }\n      return LZMA2_STATE_UNPACK0;\n    \n    case LZMA2_STATE_UNPACK0:\n      p->unpackSize |= (UInt32)b << 8;\n      return LZMA2_STATE_UNPACK1;\n    \n    case LZMA2_STATE_UNPACK1:\n      p->unpackSize |= (UInt32)b;\n      p->unpackSize++;\n      PRF(printf(\" %7u\", (unsigned)p->unpackSize));\n      return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;\n    \n    case LZMA2_STATE_PACK0:\n      p->packSize = (UInt32)b << 8;\n      return LZMA2_STATE_PACK1;\n\n    case LZMA2_STATE_PACK1:\n      p->packSize |= (UInt32)b;\n      p->packSize++;\n      // if (p->packSize < 5) return LZMA2_STATE_ERROR;\n      PRF(printf(\" %5u\", (unsigned)p->packSize));\n      return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;\n\n    case LZMA2_STATE_PROP:\n    {\n      unsigned lc, lp;\n      if (b >= (9 * 5 * 5))\n        return LZMA2_STATE_ERROR;\n      lc = b % 9;\n      b /= 9;\n      p->decoder.prop.pb = (Byte)(b / 5);\n      lp = b % 5;\n      if (lc + lp > LZMA2_LCLP_MAX)\n        return LZMA2_STATE_ERROR;\n      p->decoder.prop.lc = (Byte)lc;\n      p->decoder.prop.lp = (Byte)lp;\n      return LZMA2_STATE_DATA;\n    }\n    \n    default:\n      return LZMA2_STATE_ERROR;\n  }\n}\n\nstatic void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)\n{\n  memcpy(p->dic + p->dicPos, src, size);\n  p->dicPos += size;\n  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)\n    p->checkDicSize = p->prop.dicSize;\n  p->processedPos += (UInt32)size;\n}\n\nvoid LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);\n\n\nSRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\n{\n  SizeT inSize = *srcLen;\n  *srcLen = 0;\n  *status = LZMA_STATUS_NOT_SPECIFIED;\n\n  while (p->state != LZMA2_STATE_ERROR)\n  {\n    SizeT dicPos;\n\n    if (p->state == LZMA2_STATE_FINISHED)\n    {\n      *status = LZMA_STATUS_FINISHED_WITH_MARK;\n      return SZ_OK;\n    }\n    \n    dicPos = p->decoder.dicPos;\n    \n    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)\n    {\n      *status = LZMA_STATUS_NOT_FINISHED;\n      return SZ_OK;\n    }\n\n    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)\n    {\n      if (*srcLen == inSize)\n      {\n        *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n        return SZ_OK;\n      }\n      (*srcLen)++;\n      p->state = Lzma2Dec_UpdateState(p, *src++);\n      if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)\n        break;\n      continue;\n    }\n    \n    {\n      SizeT inCur = inSize - *srcLen;\n      SizeT outCur = dicLimit - dicPos;\n      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;\n      \n      if (outCur >= p->unpackSize)\n      {\n        outCur = (SizeT)p->unpackSize;\n        curFinishMode = LZMA_FINISH_END;\n      }\n\n      if (LZMA2_IS_UNCOMPRESSED_STATE(p))\n      {\n        if (inCur == 0)\n        {\n          *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n          return SZ_OK;\n        }\n\n        if (p->state == LZMA2_STATE_DATA)\n        {\n          BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);\n          LzmaDec_InitDicAndState(&p->decoder, initDic, False);\n        }\n\n        if (inCur > outCur)\n          inCur = outCur;\n        if (inCur == 0)\n          break;\n\n        LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);\n\n        src += inCur;\n        *srcLen += inCur;\n        p->unpackSize -= (UInt32)inCur;\n        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;\n      }\n      else\n      {\n        SRes res;\n\n        if (p->state == LZMA2_STATE_DATA)\n        {\n          BoolInt initDic = (p->control >= 0xE0);\n          BoolInt initState = (p->control >= 0xA0);\n          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);\n          p->state = LZMA2_STATE_DATA_CONT;\n        }\n  \n        if (inCur > p->packSize)\n          inCur = (SizeT)p->packSize;\n        \n        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);\n\n        src += inCur;\n        *srcLen += inCur;\n        p->packSize -= (UInt32)inCur;\n        outCur = p->decoder.dicPos - dicPos;\n        p->unpackSize -= (UInt32)outCur;\n\n        if (res != 0)\n          break;\n        \n        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)\n        {\n          if (p->packSize == 0)\n            break;\n          return SZ_OK;\n        }\n\n        if (inCur == 0 && outCur == 0)\n        {\n          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\n              || p->unpackSize != 0\n              || p->packSize != 0)\n            break;\n          p->state = LZMA2_STATE_CONTROL;\n        }\n        \n        *status = LZMA_STATUS_NOT_SPECIFIED;\n      }\n    }\n  }\n  \n  *status = LZMA_STATUS_NOT_SPECIFIED;\n  p->state = LZMA2_STATE_ERROR;\n  return SZ_ERROR_DATA;\n}\n\n\n\n\nELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,\n    SizeT outSize,\n    const Byte *src, SizeT *srcLen,\n    int checkFinishBlock)\n{\n  SizeT inSize = *srcLen;\n  *srcLen = 0;\n\n  while (p->state != LZMA2_STATE_ERROR)\n  {\n    if (p->state == LZMA2_STATE_FINISHED)\n      return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;\n\n    if (outSize == 0 && !checkFinishBlock)\n      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;\n    \n    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)\n    {\n      if (*srcLen == inSize)\n        return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;\n      (*srcLen)++;\n\n      p->state = Lzma2Dec_UpdateState(p, *src++);\n\n      if (p->state == LZMA2_STATE_UNPACK0)\n      {\n        // if (p->decoder.dicPos != 0)\n        if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)\n          return LZMA2_PARSE_STATUS_NEW_BLOCK;\n        // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;\n      }\n\n      // The following code can be commented.\n      // It's not big problem, if we read additional input bytes.\n      // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.\n\n      if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)\n      {\n        // checkFinishBlock is true. So we expect that block must be finished,\n        // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here\n        // break;\n        return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;\n      }\n\n      if (p->state == LZMA2_STATE_DATA)\n        return LZMA2_PARSE_STATUS_NEW_CHUNK;\n\n      continue;\n    }\n\n    if (outSize == 0)\n      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;\n\n    {\n      SizeT inCur = inSize - *srcLen;\n\n      if (LZMA2_IS_UNCOMPRESSED_STATE(p))\n      {\n        if (inCur == 0)\n          return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;\n        if (inCur > p->unpackSize)\n          inCur = p->unpackSize;\n        if (inCur > outSize)\n          inCur = outSize;\n        p->decoder.dicPos += inCur;\n        src += inCur;\n        *srcLen += inCur;\n        outSize -= inCur;\n        p->unpackSize -= (UInt32)inCur;\n        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;\n      }\n      else\n      {\n        p->isExtraMode = True;\n\n        if (inCur == 0)\n        {\n          if (p->packSize != 0)\n            return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;\n        }\n        else if (p->state == LZMA2_STATE_DATA)\n        {\n          p->state = LZMA2_STATE_DATA_CONT;\n          if (*src != 0)\n          {\n            // first byte of lzma chunk must be Zero\n            *srcLen += 1;\n            p->packSize--;\n            break;\n          }\n        }\n  \n        if (inCur > p->packSize)\n          inCur = (SizeT)p->packSize;\n\n        src += inCur;\n        *srcLen += inCur;\n        p->packSize -= (UInt32)inCur;\n\n        if (p->packSize == 0)\n        {\n          SizeT rem = outSize;\n          if (rem > p->unpackSize)\n            rem = p->unpackSize;\n          p->decoder.dicPos += rem;\n          p->unpackSize -= (UInt32)rem;\n          outSize -= rem;\n          if (p->unpackSize == 0)\n            p->state = LZMA2_STATE_CONTROL;\n        }\n      }\n    }\n  }\n  \n  p->state = LZMA2_STATE_ERROR;\n  return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;\n}\n\n\n\n\nSRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\n{\n  SizeT outSize = *destLen, inSize = *srcLen;\n  *srcLen = *destLen = 0;\n  \n  for (;;)\n  {\n    SizeT inCur = inSize, outCur, dicPos;\n    ELzmaFinishMode curFinishMode;\n    SRes res;\n    \n    if (p->decoder.dicPos == p->decoder.dicBufSize)\n      p->decoder.dicPos = 0;\n    dicPos = p->decoder.dicPos;\n    curFinishMode = LZMA_FINISH_ANY;\n    outCur = p->decoder.dicBufSize - dicPos;\n    \n    if (outCur >= outSize)\n    {\n      outCur = outSize;\n      curFinishMode = finishMode;\n    }\n\n    res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);\n    \n    src += inCur;\n    inSize -= inCur;\n    *srcLen += inCur;\n    outCur = p->decoder.dicPos - dicPos;\n    memcpy(dest, p->decoder.dic + dicPos, outCur);\n    dest += outCur;\n    outSize -= outCur;\n    *destLen += outCur;\n    if (res != 0)\n      return res;\n    if (outCur == 0 || outSize == 0)\n      return SZ_OK;\n  }\n}\n\n\nSRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)\n{\n  CLzma2Dec p;\n  SRes res;\n  SizeT outSize = *destLen, inSize = *srcLen;\n  *destLen = *srcLen = 0;\n  *status = LZMA_STATUS_NOT_SPECIFIED;\n  Lzma2Dec_CONSTRUCT(&p)\n  RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc))\n  p.decoder.dic = dest;\n  p.decoder.dicBufSize = outSize;\n  Lzma2Dec_Init(&p);\n  *srcLen = inSize;\n  res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);\n  *destLen = p.decoder.dicPos;\n  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\n    res = SZ_ERROR_INPUT_EOF;\n  Lzma2Dec_FreeProbs(&p, alloc);\n  return res;\n}\n\n#undef PRF\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Lzma2Dec.h",
    "content": "﻿/* Lzma2Dec.h -- LZMA2 Decoder\n2023-03-03 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZMA2_DEC_H\n#define ZIP7_INC_LZMA2_DEC_H\n\n#include \"LzmaDec.h\"\n\nEXTERN_C_BEGIN\n\n/* ---------- State Interface ---------- */\n\ntypedef struct\n{\n  unsigned state;\n  Byte control;\n  Byte needInitLevel;\n  Byte isExtraMode;\n  Byte _pad_;\n  UInt32 packSize;\n  UInt32 unpackSize;\n  CLzmaDec decoder;\n} CLzma2Dec;\n\n#define Lzma2Dec_CONSTRUCT(p)  LzmaDec_CONSTRUCT(&(p)->decoder)\n#define Lzma2Dec_Construct(p)  Lzma2Dec_CONSTRUCT(p)\n#define Lzma2Dec_FreeProbs(p, alloc)  LzmaDec_FreeProbs(&(p)->decoder, alloc)\n#define Lzma2Dec_Free(p, alloc)  LzmaDec_Free(&(p)->decoder, alloc)\n\nSRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);\nSRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);\nvoid Lzma2Dec_Init(CLzma2Dec *p);\n\n/*\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen or dicLimit).\n  LZMA_FINISH_ANY - use smallest number of input bytes\n  LZMA_FINISH_END - read EndOfStream marker after decoding\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n      LZMA_STATUS_NEEDS_MORE_INPUT\n  SZ_ERROR_DATA - Data error\n*/\n\nSRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\nSRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\n\n/* ---------- LZMA2 block and chunk parsing ---------- */\n\n/*\nLzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.\nIt can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:\n  - LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.\n  - LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.\n                                   CLzma2Dec::unpackSize contains unpack size of that chunk\n*/\n\ntypedef enum\n{\n/*\n  LZMA_STATUS_NOT_SPECIFIED                 // data error\n  LZMA_STATUS_FINISHED_WITH_MARK\n  LZMA_STATUS_NOT_FINISHED                  //\n  LZMA_STATUS_NEEDS_MORE_INPUT\n  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK   // unused\n*/\n  LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,\n  LZMA2_PARSE_STATUS_NEW_CHUNK\n} ELzma2ParseStatus;\n\nELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,\n    SizeT outSize,   // output size\n    const Byte *src, SizeT *srcLen,\n    int checkFinishBlock   // set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position.\n    );\n\n/*\nLZMA2 parser doesn't decode LZMA chunks, so we must read\n  full input LZMA chunk to decode some part of LZMA chunk.\n\nLzma2Dec_GetUnpackExtra() returns the value that shows\n    max possible number of output bytes that can be output by decoder\n    at current input positon.\n*/\n\n#define Lzma2Dec_GetUnpackExtra(p)  ((p)->isExtraMode ? (p)->unpackSize : 0)\n\n\n/* ---------- One Call Interface ---------- */\n\n/*\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  LZMA_FINISH_ANY - use smallest number of input bytes\n  LZMA_FINISH_END - read EndOfStream marker after decoding\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n  SZ_ERROR_DATA - Data error\n  SZ_ERROR_MEM  - Memory allocation error\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\n*/\n\nSRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Lzma2DecMt.c",
    "content": "﻿/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread\n2023-04-13 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n// #define SHOW_DEBUG_INFO\n// #define Z7_ST\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#include \"Alloc.h\"\n\n#include \"Lzma2Dec.h\"\n#include \"Lzma2DecMt.h\"\n\n#ifndef Z7_ST\n#include \"MtDec.h\"\n\n#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)\n#endif\n\n\n#ifndef Z7_ST\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n#define PRF_STR(s) PRF(printf(\"\\n\" s \"\\n\");)\n#define PRF_STR_INT_2(s, d1, d2) PRF(printf(\"\\n\" s \" %d %d\\n\", (unsigned)d1, (unsigned)d2);)\n#endif\n\n\nvoid Lzma2DecMtProps_Init(CLzma2DecMtProps *p)\n{\n  p->inBufSize_ST = 1 << 20;\n  p->outStep_ST = 1 << 20;\n\n  #ifndef Z7_ST\n  p->numThreads = 1;\n  p->inBufSize_MT = 1 << 18;\n  p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT;\n  p->inBlockMax = p->outBlockMax + p->outBlockMax / 16;\n  #endif\n}\n\n\n\n#ifndef Z7_ST\n\n/* ---------- CLzma2DecMtThread ---------- */\n\ntypedef struct\n{\n  CLzma2Dec dec;\n  Byte dec_created;\n  Byte needInit;\n  \n  Byte *outBuf;\n  size_t outBufSize;\n\n  EMtDecParseState state;\n  ELzma2ParseStatus parseStatus;\n\n  size_t inPreSize;\n  size_t outPreSize;\n\n  size_t inCodeSize;\n  size_t outCodeSize;\n  SRes codeRes;\n\n  CAlignOffsetAlloc alloc;\n\n  Byte mtPad[1 << 7];\n} CLzma2DecMtThread;\n\n#endif\n\n\n/* ---------- CLzma2DecMt ---------- */\n\nstruct CLzma2DecMt\n{\n  // ISzAllocPtr alloc;\n  ISzAllocPtr allocMid;\n\n  CAlignOffsetAlloc alignOffsetAlloc;\n  CLzma2DecMtProps props;\n  Byte prop;\n  \n  ISeqInStreamPtr inStream;\n  ISeqOutStreamPtr outStream;\n  ICompressProgressPtr progress;\n\n  BoolInt finishMode;\n  BoolInt outSize_Defined;\n  UInt64 outSize;\n\n  UInt64 outProcessed;\n  UInt64 inProcessed;\n  BoolInt readWasFinished;\n  SRes readRes;\n\n  Byte *inBuf;\n  size_t inBufSize;\n  Byte dec_created;\n  CLzma2Dec dec;\n\n  size_t inPos;\n  size_t inLim;\n\n  #ifndef Z7_ST\n  UInt64 outProcessed_Parse;\n  BoolInt mtc_WasConstructed;\n  CMtDec mtc;\n  CLzma2DecMtThread coders[MTDEC_THREADS_MAX];\n  #endif\n};\n\n\n\nCLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)\n{\n  CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt));\n  if (!p)\n    return NULL;\n  \n  // p->alloc = alloc;\n  p->allocMid = allocMid;\n\n  AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);\n  p->alignOffsetAlloc.numAlignBits = 7;\n  p->alignOffsetAlloc.offset = 0;\n  p->alignOffsetAlloc.baseAlloc = alloc;\n\n  p->inBuf = NULL;\n  p->inBufSize = 0;\n  p->dec_created = False;\n\n  // Lzma2DecMtProps_Init(&p->props);\n\n  #ifndef Z7_ST\n  p->mtc_WasConstructed = False;\n  {\n    unsigned i;\n    for (i = 0; i < MTDEC_THREADS_MAX; i++)\n    {\n      CLzma2DecMtThread *t = &p->coders[i];\n      t->dec_created = False;\n      t->outBuf = NULL;\n      t->outBufSize = 0;\n    }\n  }\n  #endif\n\n  return (CLzma2DecMtHandle)(void *)p;\n}\n\n\n#ifndef Z7_ST\n\nstatic void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p)\n{\n  unsigned i;\n  for (i = 0; i < MTDEC_THREADS_MAX; i++)\n  {\n    CLzma2DecMtThread *t = &p->coders[i];\n    if (t->outBuf)\n    {\n      ISzAlloc_Free(p->allocMid, t->outBuf);\n      t->outBuf = NULL;\n      t->outBufSize = 0;\n    }\n  }\n}\n\n#endif\n\n\nstatic void Lzma2DecMt_FreeSt(CLzma2DecMt *p)\n{\n  if (p->dec_created)\n  {\n    Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt);\n    p->dec_created = False;\n  }\n  if (p->inBuf)\n  {\n    ISzAlloc_Free(p->allocMid, p->inBuf);\n    p->inBuf = NULL;\n  }\n  p->inBufSize = 0;\n}\n\n\n// #define GET_CLzma2DecMt_p CLzma2DecMt *p = (CLzma2DecMt *)(void *)pp;\n\nvoid Lzma2DecMt_Destroy(CLzma2DecMtHandle p)\n{\n  // GET_CLzma2DecMt_p\n\n  Lzma2DecMt_FreeSt(p);\n\n  #ifndef Z7_ST\n\n  if (p->mtc_WasConstructed)\n  {\n    MtDec_Destruct(&p->mtc);\n    p->mtc_WasConstructed = False;\n  }\n  {\n    unsigned i;\n    for (i = 0; i < MTDEC_THREADS_MAX; i++)\n    {\n      CLzma2DecMtThread *t = &p->coders[i];\n      if (t->dec_created)\n      {\n        // we don't need to free dict here\n        Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!!\n        t->dec_created = False;\n      }\n    }\n  }\n  Lzma2DecMt_FreeOutBufs(p);\n\n  #endif\n\n  ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p);\n}\n\n\n\n#ifndef Z7_ST\n\nstatic void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)\n{\n  CLzma2DecMt *me = (CLzma2DecMt *)obj;\n  CLzma2DecMtThread *t = &me->coders[coderIndex];\n\n  PRF_STR_INT_2(\"Parse\", coderIndex, cc->srcSize)\n\n  cc->state = MTDEC_PARSE_CONTINUE;\n\n  if (cc->startCall)\n  {\n    if (!t->dec_created)\n    {\n      Lzma2Dec_CONSTRUCT(&t->dec)\n      t->dec_created = True;\n      AlignOffsetAlloc_CreateVTable(&t->alloc);\n      {\n        /* (1 << 12) is expected size of one way in data cache.\n           We optimize alignment for cache line size of 128 bytes and smaller */\n        const unsigned kNumAlignBits = 12;\n        const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */\n        t->alloc.numAlignBits = kNumAlignBits;\n        t->alloc.offset = ((UInt32)coderIndex * (((unsigned)1 << 11) + (1 << 8) + (1 << 6))) & (((unsigned)1 << kNumAlignBits) - ((unsigned)1 << kNumCacheLineBits));\n        t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc;\n      }\n    }\n    Lzma2Dec_Init(&t->dec);\n    \n    t->inPreSize = 0;\n    t->outPreSize = 0;\n    // t->blockWasFinished = False;\n    // t->finishedWithMark = False;\n    t->parseStatus = (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;\n    t->state = MTDEC_PARSE_CONTINUE;\n\n    t->inCodeSize = 0;\n    t->outCodeSize = 0;\n    t->codeRes = SZ_OK;\n\n    // (cc->srcSize == 0) is allowed\n  }\n\n  {\n    ELzma2ParseStatus status;\n    BoolInt overflow;\n    UInt32 unpackRem = 0;\n    \n    int checkFinishBlock = True;\n    size_t limit = me->props.outBlockMax;\n    if (me->outSize_Defined)\n    {\n      UInt64 rem = me->outSize - me->outProcessed_Parse;\n      if (limit >= rem)\n      {\n        limit = (size_t)rem;\n        if (!me->finishMode)\n          checkFinishBlock = False;\n      }\n    }\n\n    // checkFinishBlock = False, if we want to decode partial data\n    // that must be finished at position <= outBlockMax.\n\n    {\n      const size_t srcOrig = cc->srcSize;\n      SizeT srcSize_Point = 0;\n      SizeT dicPos_Point = 0;\n      \n      cc->srcSize = 0;\n      overflow = False;\n\n      for (;;)\n      {\n        SizeT srcCur = (SizeT)(srcOrig - cc->srcSize);\n        \n        status = Lzma2Dec_Parse(&t->dec,\n            (SizeT)limit - t->dec.decoder.dicPos,\n            cc->src + cc->srcSize, &srcCur,\n            checkFinishBlock);\n\n        cc->srcSize += srcCur;\n\n        if (status == LZMA2_PARSE_STATUS_NEW_CHUNK)\n        {\n          if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos)\n          {\n            overflow = True;\n            break;\n          }\n          continue;\n        }\n        \n        if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)\n        {\n          if (t->dec.decoder.dicPos == 0)\n            continue;\n          // we decode small blocks in one thread\n          if (t->dec.decoder.dicPos >= (1 << 14))\n            break;\n          dicPos_Point = t->dec.decoder.dicPos;\n          srcSize_Point = (SizeT)cc->srcSize;\n          continue;\n        }\n\n        if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock\n            // && limit == t->dec.decoder.dicPos\n            // && limit == me->props.outBlockMax\n            )\n        {\n          overflow = True;\n          break;\n        }\n        \n        unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec);\n        break;\n      }\n\n      if (dicPos_Point != 0\n          && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK\n          && (int)status != LZMA_STATUS_FINISHED_WITH_MARK\n          && (int)status != LZMA_STATUS_NOT_SPECIFIED)\n      {\n        // we revert to latest newBlock state\n        status = LZMA2_PARSE_STATUS_NEW_BLOCK;\n        unpackRem = 0;\n        t->dec.decoder.dicPos = dicPos_Point;\n        cc->srcSize = srcSize_Point;\n        overflow = False;\n      }\n    }\n\n    t->inPreSize += cc->srcSize;\n    t->parseStatus = status;\n\n    if (overflow)\n      cc->state = MTDEC_PARSE_OVERFLOW;\n    else\n    {\n      size_t dicPos = t->dec.decoder.dicPos;\n\n      if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT)\n      {\n        if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)\n        {\n          cc->state = MTDEC_PARSE_NEW;\n          cc->srcSize--; // we don't need control byte of next block\n          t->inPreSize--;\n        }\n        else\n        {\n          cc->state = MTDEC_PARSE_END;\n          if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK)\n          {\n            // (status == LZMA_STATUS_NOT_SPECIFIED)\n            // (status == LZMA_STATUS_NOT_FINISHED)\n            if (unpackRem != 0)\n            {\n              /* we also reserve space for max possible number of output bytes of current LZMA chunk */\n              size_t rem = limit - dicPos;\n              if (rem > unpackRem)\n                rem = unpackRem;\n              dicPos += rem;\n            }\n          }\n        }\n    \n        me->outProcessed_Parse += dicPos;\n      }\n      \n      cc->outPos = dicPos;\n      t->outPreSize = (size_t)dicPos;\n    }\n\n    t->state = cc->state;\n    return;\n  }\n}\n\n\nstatic SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex)\n{\n  CLzma2DecMt *me = (CLzma2DecMt *)pp;\n  CLzma2DecMtThread *t = &me->coders[coderIndex];\n  Byte *dest = t->outBuf;\n\n  if (t->inPreSize == 0)\n  {\n    t->codeRes = SZ_ERROR_DATA;\n    return t->codeRes;\n  }\n\n  if (!dest || t->outBufSize < t->outPreSize)\n  {\n    if (dest)\n    {\n      ISzAlloc_Free(me->allocMid, dest);\n      t->outBuf = NULL;\n      t->outBufSize = 0;\n    }\n\n    dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize\n        // + (1 << 28)\n        );\n    // Sleep(200);\n    if (!dest)\n      return SZ_ERROR_MEM;\n    t->outBuf = dest;\n    t->outBufSize = t->outPreSize;\n  }\n\n  t->dec.decoder.dic = dest;\n  t->dec.decoder.dicBufSize = (SizeT)t->outPreSize;\n\n  t->needInit = True;\n\n  return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt\n}\n\n\nstatic SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex,\n    const Byte *src, size_t srcSize, int srcFinished,\n    // int finished, int blockFinished,\n    UInt64 *inCodePos, UInt64 *outCodePos, int *stop)\n{\n  CLzma2DecMt *me = (CLzma2DecMt *)pp;\n  CLzma2DecMtThread *t = &me->coders[coderIndex];\n\n  UNUSED_VAR(srcFinished)\n\n  PRF_STR_INT_2(\"Code\", coderIndex, srcSize)\n\n  *inCodePos = t->inCodeSize;\n  *outCodePos = 0;\n  *stop = True;\n\n  if (t->needInit)\n  {\n    Lzma2Dec_Init(&t->dec);\n    t->needInit = False;\n  }\n\n  {\n    ELzmaStatus status;\n    SizeT srcProcessed = (SizeT)srcSize;\n    BoolInt blockWasFinished =\n        ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK\n        || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK);\n    \n    SRes res = Lzma2Dec_DecodeToDic(&t->dec,\n        (SizeT)t->outPreSize,\n        src, &srcProcessed,\n        blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY,\n        &status);\n\n    t->codeRes = res;\n\n    t->inCodeSize += srcProcessed;\n    *inCodePos = t->inCodeSize;\n    t->outCodeSize = t->dec.decoder.dicPos;\n    *outCodePos = t->dec.decoder.dicPos;\n\n    if (res != SZ_OK)\n      return res;\n\n    if (srcProcessed == srcSize)\n      *stop = False;\n\n    if (blockWasFinished)\n    {\n      if (srcSize != srcProcessed)\n        return SZ_ERROR_FAIL;\n      \n      if (t->inPreSize == t->inCodeSize)\n      {\n        if (t->outPreSize != t->outCodeSize)\n          return SZ_ERROR_FAIL;\n        *stop = True;\n      }\n    }\n    else\n    {\n      if (t->outPreSize == t->outCodeSize)\n        *stop = True;\n    }\n\n    return SZ_OK;\n  }\n}\n\n\n#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24)\n\nstatic SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,\n    BoolInt needWriteToStream,\n    const Byte *src, size_t srcSize, BoolInt isCross,\n    BoolInt *needContinue, BoolInt *canRecode)\n{\n  CLzma2DecMt *me = (CLzma2DecMt *)pp;\n  const CLzma2DecMtThread *t = &me->coders[coderIndex];\n  size_t size = t->outCodeSize;\n  const Byte *data = t->outBuf;\n  BoolInt needContinue2 = True;\n\n  UNUSED_VAR(src)\n  UNUSED_VAR(srcSize)\n  UNUSED_VAR(isCross)\n\n  PRF_STR_INT_2(\"Write\", coderIndex, srcSize)\n\n  *needContinue = False;\n  *canRecode = True;\n\n  if (\n      // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK\n         t->state == MTDEC_PARSE_OVERFLOW\n      || t->state == MTDEC_PARSE_END)\n    needContinue2 = False;\n\n\n  if (!needWriteToStream)\n    return SZ_OK;\n\n  me->mtc.inProcessed += t->inCodeSize;\n\n  if (t->codeRes == SZ_OK)\n  if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK\n      || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)\n  if (t->outPreSize != t->outCodeSize\n      || t->inPreSize != t->inCodeSize)\n    return SZ_ERROR_FAIL;\n\n  *canRecode = False;\n    \n  if (me->outStream)\n  {\n    for (;;)\n    {\n      size_t cur = size;\n      size_t written;\n      if (cur > LZMA2DECMT_STREAM_WRITE_STEP)\n        cur = LZMA2DECMT_STREAM_WRITE_STEP;\n\n      written = ISeqOutStream_Write(me->outStream, data, cur);\n      \n      me->outProcessed += written;\n      // me->mtc.writtenTotal += written;\n      if (written != cur)\n        return SZ_ERROR_WRITE;\n      data += cur;\n      size -= cur;\n      if (size == 0)\n      {\n        *needContinue = needContinue2;\n        return SZ_OK;\n      }\n      RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0))\n    }\n  }\n  \n  return SZ_ERROR_FAIL;\n  /*\n  if (size > me->outBufSize)\n    return SZ_ERROR_OUTPUT_EOF;\n  memcpy(me->outBuf, data, size);\n  me->outBufSize -= size;\n  me->outBuf += size;\n  *needContinue = needContinue2;\n  return SZ_OK;\n  */\n}\n\n#endif\n\n\nstatic SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)\n{\n  if (!p->dec_created)\n  {\n    Lzma2Dec_CONSTRUCT(&p->dec)\n    p->dec_created = True;\n  }\n\n  RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt))\n\n  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)\n  {\n    ISzAlloc_Free(p->allocMid, p->inBuf);\n    p->inBufSize = 0;\n    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);\n    if (!p->inBuf)\n      return SZ_ERROR_MEM;\n    p->inBufSize = p->props.inBufSize_ST;\n  }\n\n  Lzma2Dec_Init(&p->dec);\n  \n  return SZ_OK;\n}\n\n\nstatic SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p\n    #ifndef Z7_ST\n    , BoolInt tMode\n    #endif\n    )\n{\n  SizeT wrPos;\n  size_t inPos, inLim;\n  const Byte *inData;\n  UInt64 inPrev, outPrev;\n\n  CLzma2Dec *dec;\n\n  #ifndef Z7_ST\n  if (tMode)\n  {\n    Lzma2DecMt_FreeOutBufs(p);\n    tMode = MtDec_PrepareRead(&p->mtc);\n  }\n  #endif\n\n  RINOK(Lzma2Dec_Prepare_ST(p))\n\n  dec = &p->dec;\n\n  inPrev = p->inProcessed;\n  outPrev = p->outProcessed;\n\n  inPos = 0;\n  inLim = 0;\n  inData = NULL;\n  wrPos = dec->decoder.dicPos;\n\n  for (;;)\n  {\n    SizeT dicPos;\n    SizeT size;\n    ELzmaFinishMode finishMode;\n    SizeT inProcessed;\n    ELzmaStatus status;\n    SRes res;\n\n    SizeT outProcessed;\n    BoolInt outFinished;\n    BoolInt needStop;\n\n    if (inPos == inLim)\n    {\n      #ifndef Z7_ST\n      if (tMode)\n      {\n        inData = MtDec_Read(&p->mtc, &inLim);\n        inPos = 0;\n        if (inData)\n          continue;\n        tMode = False;\n        inLim = 0;\n      }\n      #endif\n      \n      if (!p->readWasFinished)\n      {\n        inPos = 0;\n        inLim = p->inBufSize;\n        inData = p->inBuf;\n        p->readRes = ISeqInStream_Read(p->inStream, (void *)(p->inBuf), &inLim);\n        // p->readProcessed += inLim;\n        // inLim -= 5; p->readWasFinished = True; // for test\n        if (inLim == 0 || p->readRes != SZ_OK)\n          p->readWasFinished = True;\n      }\n    }\n\n    dicPos = dec->decoder.dicPos;\n    {\n      SizeT next = dec->decoder.dicBufSize;\n      if (next - wrPos > p->props.outStep_ST)\n        next = wrPos + (SizeT)p->props.outStep_ST;\n      size = next - dicPos;\n    }\n\n    finishMode = LZMA_FINISH_ANY;\n    if (p->outSize_Defined)\n    {\n      const UInt64 rem = p->outSize - p->outProcessed;\n      if (size >= rem)\n      {\n        size = (SizeT)rem;\n        if (p->finishMode)\n          finishMode = LZMA_FINISH_END;\n      }\n    }\n\n    inProcessed = (SizeT)(inLim - inPos);\n    \n    res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);\n\n    inPos += inProcessed;\n    p->inProcessed += inProcessed;\n    outProcessed = dec->decoder.dicPos - dicPos;\n    p->outProcessed += outProcessed;\n\n    outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);\n\n    needStop = (res != SZ_OK\n        || (inProcessed == 0 && outProcessed == 0)\n        || status == LZMA_STATUS_FINISHED_WITH_MARK\n        || (!p->finishMode && outFinished));\n\n    if (needStop || outProcessed >= size)\n    {\n      SRes res2;\n      {\n        size_t writeSize = dec->decoder.dicPos - wrPos;\n        size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);\n        res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;\n      }\n\n      if (dec->decoder.dicPos == dec->decoder.dicBufSize)\n        dec->decoder.dicPos = 0;\n      wrPos = dec->decoder.dicPos;\n\n      RINOK(res2)\n\n      if (needStop)\n      {\n        if (res != SZ_OK)\n          return res;\n\n        if (status == LZMA_STATUS_FINISHED_WITH_MARK)\n        {\n          if (p->finishMode)\n          {\n            if (p->outSize_Defined && p->outSize != p->outProcessed)\n              return SZ_ERROR_DATA;\n          }\n          return SZ_OK;\n        }\n\n        if (!p->finishMode && outFinished)\n          return SZ_OK;\n\n        if (status == LZMA_STATUS_NEEDS_MORE_INPUT)\n          return SZ_ERROR_INPUT_EOF;\n        \n        return SZ_ERROR_DATA;\n      }\n    }\n    \n    if (p->progress)\n    {\n      UInt64 inDelta = p->inProcessed - inPrev;\n      UInt64 outDelta = p->outProcessed - outPrev;\n      if (inDelta >= (1 << 22) || outDelta >= (1 << 22))\n      {\n        RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed))\n        inPrev = p->inProcessed;\n        outPrev = p->outProcessed;\n      }\n    }\n  }\n}\n\n\n\nSRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,\n    Byte prop,\n    const CLzma2DecMtProps *props,\n    ISeqOutStreamPtr outStream, const UInt64 *outDataSize, int finishMode,\n    // Byte *outBuf, size_t *outBufSize,\n    ISeqInStreamPtr inStream,\n    // const Byte *inData, size_t inDataSize,\n    UInt64 *inProcessed,\n    // UInt64 *outProcessed,\n    int *isMT,\n    ICompressProgressPtr progress)\n{\n  // GET_CLzma2DecMt_p\n  #ifndef Z7_ST\n  BoolInt tMode;\n  #endif\n\n  *inProcessed = 0;\n\n  if (prop > 40)\n    return SZ_ERROR_UNSUPPORTED;\n\n  p->prop = prop;\n  p->props = *props;\n\n  p->inStream = inStream;\n  p->outStream = outStream;\n  p->progress = progress;\n\n  p->outSize = 0;\n  p->outSize_Defined = False;\n  if (outDataSize)\n  {\n    p->outSize_Defined = True;\n    p->outSize = *outDataSize;\n  }\n  p->finishMode = finishMode;\n\n  p->outProcessed = 0;\n  p->inProcessed = 0;\n\n  p->readWasFinished = False;\n  p->readRes = SZ_OK;\n\n  *isMT = False;\n\n  \n  #ifndef Z7_ST\n\n  tMode = False;\n\n  // p->mtc.parseRes = SZ_OK;\n\n  // p->mtc.numFilledThreads = 0;\n  // p->mtc.crossStart = 0;\n  // p->mtc.crossEnd = 0;\n  // p->mtc.allocError_for_Read_BlockIndex = 0;\n  // p->mtc.isAllocError = False;\n\n  if (p->props.numThreads > 1)\n  {\n    IMtDecCallback2 vt;\n\n    Lzma2DecMt_FreeSt(p);\n\n    p->outProcessed_Parse = 0;\n\n    if (!p->mtc_WasConstructed)\n    {\n      p->mtc_WasConstructed = True;\n      MtDec_Construct(&p->mtc);\n    }\n    \n    p->mtc.progress = progress;\n    p->mtc.inStream = inStream;\n\n    // p->outBuf = NULL;\n    // p->outBufSize = 0;\n    /*\n    if (!outStream)\n    {\n      // p->outBuf = outBuf;\n      // p->outBufSize = *outBufSize;\n      // *outBufSize = 0;\n      return SZ_ERROR_PARAM;\n    }\n    */\n\n    // p->mtc.inBlockMax = p->props.inBlockMax;\n    p->mtc.alloc = &p->alignOffsetAlloc.vt;\n      // p->alignOffsetAlloc.baseAlloc;\n    // p->mtc.inData = inData;\n    // p->mtc.inDataSize = inDataSize;\n    p->mtc.mtCallback = &vt;\n    p->mtc.mtCallbackObject = p;\n\n    p->mtc.inBufSize = p->props.inBufSize_MT;\n\n    p->mtc.numThreadsMax = p->props.numThreads;\n\n    *isMT = True;\n\n    vt.Parse = Lzma2DecMt_MtCallback_Parse;\n    vt.PreCode = Lzma2DecMt_MtCallback_PreCode;\n    vt.Code = Lzma2DecMt_MtCallback_Code;\n    vt.Write = Lzma2DecMt_MtCallback_Write;\n\n    {\n      BoolInt needContinue = False;\n\n      SRes res = MtDec_Code(&p->mtc);\n\n      /*\n      if (!outStream)\n        *outBufSize = p->outBuf - outBuf;\n      */\n\n      *inProcessed = p->mtc.inProcessed;\n\n      needContinue = False;\n\n      if (res == SZ_OK)\n      {\n        if (p->mtc.mtProgress.res != SZ_OK)\n          res = p->mtc.mtProgress.res;\n        else\n          needContinue = p->mtc.needContinue;\n      }\n\n      if (!needContinue)\n      {\n        if (res == SZ_OK)\n          return p->mtc.readRes;\n        return res;\n      }\n\n      tMode = True;\n      p->readRes = p->mtc.readRes;\n      p->readWasFinished = p->mtc.readWasFinished;\n      p->inProcessed = p->mtc.inProcessed;\n      \n      PRF_STR(\"----- decoding ST -----\")\n    }\n  }\n\n  #endif\n\n\n  *isMT = False;\n\n  {\n    SRes res = Lzma2Dec_Decode_ST(p\n        #ifndef Z7_ST\n        , tMode\n        #endif\n        );\n\n    *inProcessed = p->inProcessed;\n\n    // res = SZ_OK; // for test\n    if (res == SZ_ERROR_INPUT_EOF)\n    {\n      if (p->readRes != SZ_OK)\n        res = p->readRes;\n    }\n    else if (res == SZ_OK && p->readRes != SZ_OK)\n      res = p->readRes;\n    \n    /*\n    #ifndef Z7_ST\n    if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)\n      res = p->mtc.parseRes;\n    #endif\n    */\n    \n    return res;\n  }\n}\n\n\n/* ---------- Read from CLzma2DecMtHandle Interface ---------- */\n\nSRes Lzma2DecMt_Init(CLzma2DecMtHandle p,\n    Byte prop,\n    const CLzma2DecMtProps *props,\n    const UInt64 *outDataSize, int finishMode,\n    ISeqInStreamPtr inStream)\n{\n  // GET_CLzma2DecMt_p\n\n  if (prop > 40)\n    return SZ_ERROR_UNSUPPORTED;\n\n  p->prop = prop;\n  p->props = *props;\n\n  p->inStream = inStream;\n\n  p->outSize = 0;\n  p->outSize_Defined = False;\n  if (outDataSize)\n  {\n    p->outSize_Defined = True;\n    p->outSize = *outDataSize;\n  }\n  p->finishMode = finishMode;\n\n  p->outProcessed = 0;\n  p->inProcessed = 0;\n\n  p->inPos = 0;\n  p->inLim = 0;\n\n  return Lzma2Dec_Prepare_ST(p);\n}\n\n\nSRes Lzma2DecMt_Read(CLzma2DecMtHandle p,\n    Byte *data, size_t *outSize,\n    UInt64 *inStreamProcessed)\n{\n  // GET_CLzma2DecMt_p\n  ELzmaFinishMode finishMode;\n  SRes readRes;\n  size_t size = *outSize;\n\n  *outSize = 0;\n  *inStreamProcessed = 0;\n\n  finishMode = LZMA_FINISH_ANY;\n  if (p->outSize_Defined)\n  {\n    const UInt64 rem = p->outSize - p->outProcessed;\n    if (size >= rem)\n    {\n      size = (size_t)rem;\n      if (p->finishMode)\n        finishMode = LZMA_FINISH_END;\n    }\n  }\n\n  readRes = SZ_OK;\n\n  for (;;)\n  {\n    SizeT inCur;\n    SizeT outCur;\n    ELzmaStatus status;\n    SRes res;\n\n    if (p->inPos == p->inLim && readRes == SZ_OK)\n    {\n      p->inPos = 0;\n      p->inLim = p->props.inBufSize_ST;\n      readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);\n    }\n\n    inCur = (SizeT)(p->inLim - p->inPos);\n    outCur = (SizeT)size;\n\n    res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,\n        p->inBuf + p->inPos, &inCur, finishMode, &status);\n    \n    p->inPos += inCur;\n    p->inProcessed += inCur;\n    *inStreamProcessed += inCur;\n    p->outProcessed += outCur;\n    *outSize += outCur;\n    size -= outCur;\n    data += outCur;\n    \n    if (res != 0)\n      return res;\n    \n    /*\n    if (status == LZMA_STATUS_FINISHED_WITH_MARK)\n      return readRes;\n\n    if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)\n    {\n      if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)\n        return SZ_ERROR_DATA;\n      return readRes;\n    }\n    */\n\n    if (inCur == 0 && outCur == 0)\n      return readRes;\n  }\n}\n\n#undef PRF\n#undef PRF_STR\n#undef PRF_STR_INT_2\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Lzma2DecMt.h",
    "content": "﻿/* Lzma2DecMt.h -- LZMA2 Decoder Multi-thread\n2023-04-13 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZMA2_DEC_MT_H\n#define ZIP7_INC_LZMA2_DEC_MT_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\ntypedef struct\n{\n  size_t inBufSize_ST;\n  size_t outStep_ST;\n  \n  #ifndef Z7_ST\n  unsigned numThreads;\n  size_t inBufSize_MT;\n  size_t outBlockMax;\n  size_t inBlockMax;\n  #endif\n} CLzma2DecMtProps;\n\n/* init to single-thread mode */\nvoid Lzma2DecMtProps_Init(CLzma2DecMtProps *p);\n\n\n/* ---------- CLzma2DecMtHandle Interface ---------- */\n\n/* Lzma2DecMt_ * functions can return the following exit codes:\nSRes:\n  SZ_OK           - OK\n  SZ_ERROR_MEM    - Memory allocation error\n  SZ_ERROR_PARAM  - Incorrect paramater in props\n  SZ_ERROR_WRITE  - ISeqOutStream write callback error\n  // SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output\n  SZ_ERROR_PROGRESS - some break from progress callback\n  SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)\n*/\n\ntypedef struct CLzma2DecMt CLzma2DecMt;\ntypedef CLzma2DecMt * CLzma2DecMtHandle;\n// Z7_DECLARE_HANDLE(CLzma2DecMtHandle)\n\nCLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);\nvoid Lzma2DecMt_Destroy(CLzma2DecMtHandle p);\n\nSRes Lzma2DecMt_Decode(CLzma2DecMtHandle p,\n    Byte prop,\n    const CLzma2DecMtProps *props,\n    ISeqOutStreamPtr outStream,\n    const UInt64 *outDataSize, // NULL means undefined\n    int finishMode,            // 0 - partial unpacking is allowed, 1 - if lzma2 stream must be finished\n    // Byte *outBuf, size_t *outBufSize,\n    ISeqInStreamPtr inStream,\n    // const Byte *inData, size_t inDataSize,\n    \n    // out variables:\n    UInt64 *inProcessed,\n    int *isMT,  /* out: (*isMT == 0), if single thread decoding was used */\n\n    // UInt64 *outProcessed,\n    ICompressProgressPtr progress);\n\n\n/* ---------- Read from CLzma2DecMtHandle Interface ---------- */\n\nSRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,\n    Byte prop,\n    const CLzma2DecMtProps *props,\n    const UInt64 *outDataSize, int finishMode,\n    ISeqInStreamPtr inStream);\n\nSRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,\n    Byte *data, size_t *outSize,\n    UInt64 *inStreamProcessed);\n\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Lzma2Enc.c",
    "content": "﻿/* Lzma2Enc.c -- LZMA2 Encoder\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n/* #define Z7_ST */\n\n#include \"Lzma2Enc.h\"\n\n#ifndef Z7_ST\n#include \"MtCoder.h\"\n#else\n#define MTCODER_THREADS_MAX 1\n#endif\n\n#define LZMA2_CONTROL_LZMA (1 << 7)\n#define LZMA2_CONTROL_COPY_NO_RESET 2\n#define LZMA2_CONTROL_COPY_RESET_DIC 1\n#define LZMA2_CONTROL_EOF 0\n\n#define LZMA2_LCLP_MAX 4\n\n#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))\n\n#define LZMA2_PACK_SIZE_MAX (1 << 16)\n#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX\n#define LZMA2_UNPACK_SIZE_MAX (1 << 21)\n#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX\n\n#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)\n\n\n#define PRF(x) /* x */\n\n\n/* ---------- CLimitedSeqInStream ---------- */\n\ntypedef struct\n{\n  ISeqInStream vt;\n  ISeqInStreamPtr realStream;\n  UInt64 limit;\n  UInt64 processed;\n  int finished;\n} CLimitedSeqInStream;\n\nstatic void LimitedSeqInStream_Init(CLimitedSeqInStream *p)\n{\n  p->limit = (UInt64)(Int64)-1;\n  p->processed = 0;\n  p->finished = 0;\n}\n\nstatic SRes LimitedSeqInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLimitedSeqInStream)\n  size_t size2 = *size;\n  SRes res = SZ_OK;\n  \n  if (p->limit != (UInt64)(Int64)-1)\n  {\n    const UInt64 rem = p->limit - p->processed;\n    if (size2 > rem)\n      size2 = (size_t)rem;\n  }\n  if (size2 != 0)\n  {\n    res = ISeqInStream_Read(p->realStream, data, &size2);\n    p->finished = (size2 == 0 ? 1 : 0);\n    p->processed += size2;\n  }\n  *size = size2;\n  return res;\n}\n\n\n/* ---------- CLzma2EncInt ---------- */\n\ntypedef struct\n{\n  CLzmaEncHandle enc;\n  Byte propsAreSet;\n  Byte propsByte;\n  Byte needInitState;\n  Byte needInitProp;\n  UInt64 srcPos;\n} CLzma2EncInt;\n\n\nstatic SRes Lzma2EncInt_InitStream(CLzma2EncInt *p, const CLzma2EncProps *props)\n{\n  if (!p->propsAreSet)\n  {\n    SizeT propsSize = LZMA_PROPS_SIZE;\n    Byte propsEncoded[LZMA_PROPS_SIZE];\n    RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps))\n    RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize))\n    p->propsByte = propsEncoded[0];\n    p->propsAreSet = True;\n  }\n  return SZ_OK;\n}\n\nstatic void Lzma2EncInt_InitBlock(CLzma2EncInt *p)\n{\n  p->srcPos = 0;\n  p->needInitState = True;\n  p->needInitProp = True;\n}\n\n\nSRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize,\n    ISzAllocPtr alloc, ISzAllocPtr allocBig);\nSRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen,\n    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);\nSRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,\n    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);\nconst Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p);\nvoid LzmaEnc_Finish(CLzmaEncHandle p);\nvoid LzmaEnc_SaveState(CLzmaEncHandle p);\nvoid LzmaEnc_RestoreState(CLzmaEncHandle p);\n\n/*\nUInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p);\n*/\n\nstatic SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,\n    size_t *packSizeRes, ISeqOutStreamPtr outStream)\n{\n  size_t packSizeLimit = *packSizeRes;\n  size_t packSize = packSizeLimit;\n  UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;\n  unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);\n  BoolInt useCopyBlock;\n  SRes res;\n\n  *packSizeRes = 0;\n  if (packSize < lzHeaderSize)\n    return SZ_ERROR_OUTPUT_EOF;\n  packSize -= lzHeaderSize;\n  \n  LzmaEnc_SaveState(p->enc);\n  res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,\n      outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);\n  \n  PRF(printf(\"\\npackSize = %7d unpackSize = %7d  \", packSize, unpackSize));\n\n  if (unpackSize == 0)\n    return res;\n\n  if (res == SZ_OK)\n    useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));\n  else\n  {\n    if (res != SZ_ERROR_OUTPUT_EOF)\n      return res;\n    res = SZ_OK;\n    useCopyBlock = True;\n  }\n\n  if (useCopyBlock)\n  {\n    size_t destPos = 0;\n    PRF(printf(\"################# COPY           \"));\n\n    while (unpackSize > 0)\n    {\n      const UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;\n      if (packSizeLimit - destPos < u + 3)\n        return SZ_ERROR_OUTPUT_EOF;\n      outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);\n      outBuf[destPos++] = (Byte)((u - 1) >> 8);\n      outBuf[destPos++] = (Byte)(u - 1);\n      memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);\n      unpackSize -= u;\n      destPos += u;\n      p->srcPos += u;\n      \n      if (outStream)\n      {\n        *packSizeRes += destPos;\n        if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)\n          return SZ_ERROR_WRITE;\n        destPos = 0;\n      }\n      else\n        *packSizeRes = destPos;\n      /* needInitState = True; */\n    }\n    \n    LzmaEnc_RestoreState(p->enc);\n    return SZ_OK;\n  }\n\n  {\n    size_t destPos = 0;\n    const UInt32 u = unpackSize - 1;\n    const UInt32 pm = (UInt32)(packSize - 1);\n    const unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);\n\n    PRF(printf(\"               \"));\n\n    outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F));\n    outBuf[destPos++] = (Byte)(u >> 8);\n    outBuf[destPos++] = (Byte)u;\n    outBuf[destPos++] = (Byte)(pm >> 8);\n    outBuf[destPos++] = (Byte)pm;\n    \n    if (p->needInitProp)\n      outBuf[destPos++] = p->propsByte;\n    \n    p->needInitProp = False;\n    p->needInitState = False;\n    destPos += packSize;\n    p->srcPos += unpackSize;\n\n    if (outStream)\n      if (ISeqOutStream_Write(outStream, outBuf, destPos) != destPos)\n        return SZ_ERROR_WRITE;\n    \n    *packSizeRes = destPos;\n    return SZ_OK;\n  }\n}\n\n\n/* ---------- Lzma2 Props ---------- */\n\nvoid Lzma2EncProps_Init(CLzma2EncProps *p)\n{\n  LzmaEncProps_Init(&p->lzmaProps);\n  p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO;\n  p->numBlockThreads_Reduced = -1;\n  p->numBlockThreads_Max = -1;\n  p->numTotalThreads = -1;\n  p->numThreadGroups = 0;\n}\n\nvoid Lzma2EncProps_Normalize(CLzma2EncProps *p)\n{\n  UInt64 fileSize;\n  int t1, t1n, t2, t2r, t3;\n  {\n    CLzmaEncProps lzmaProps = p->lzmaProps;\n    LzmaEncProps_Normalize(&lzmaProps);\n    t1n = lzmaProps.numThreads;\n  }\n\n  t1 = p->lzmaProps.numThreads;\n  t2 = p->numBlockThreads_Max;\n  t3 = p->numTotalThreads;\n\n  if (t2 > MTCODER_THREADS_MAX)\n    t2 = MTCODER_THREADS_MAX;\n\n  if (t3 <= 0)\n  {\n    if (t2 <= 0)\n      t2 = 1;\n    t3 = t1n * t2;\n  }\n  else if (t2 <= 0)\n  {\n    t2 = t3 / t1n;\n    if (t2 == 0)\n    {\n      t1 = 1;\n      t2 = t3;\n    }\n    if (t2 > MTCODER_THREADS_MAX)\n      t2 = MTCODER_THREADS_MAX;\n  }\n  else if (t1 <= 0)\n  {\n    t1 = t3 / t2;\n    if (t1 == 0)\n      t1 = 1;\n  }\n  else\n    t3 = t1n * t2;\n\n  p->lzmaProps.numThreads = t1;\n\n  t2r = t2;\n\n  fileSize = p->lzmaProps.reduceSize;\n\n  if (   p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID\n      && p->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO\n      && (p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))\n    p->lzmaProps.reduceSize = p->blockSize;\n\n  LzmaEncProps_Normalize(&p->lzmaProps);\n\n  p->lzmaProps.reduceSize = fileSize;\n\n  t1 = p->lzmaProps.numThreads;\n\n  if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)\n  {\n    t2r = t2 = 1;\n    t3 = t1;\n  }\n  else if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO && t2 <= 1)\n  {\n    /* if there is no block multi-threading, we use SOLID block */\n    p->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;\n  }\n  else\n  {\n    if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO)\n    {\n      const UInt32 kMinSize = (UInt32)1 << 20;\n      const UInt32 kMaxSize = (UInt32)1 << 28;\n      const UInt32 dictSize = p->lzmaProps.dictSize;\n      UInt64 blockSize = (UInt64)dictSize << 2;\n      if (blockSize < kMinSize) blockSize = kMinSize;\n      if (blockSize > kMaxSize) blockSize = kMaxSize;\n      if (blockSize < dictSize) blockSize = dictSize;\n      blockSize += (kMinSize - 1);\n      blockSize &= ~(UInt64)(kMinSize - 1);\n      p->blockSize = blockSize;\n    }\n    \n    if (t2 > 1 && fileSize != (UInt64)(Int64)-1)\n    {\n      UInt64 numBlocks = fileSize / p->blockSize;\n      if (numBlocks * p->blockSize != fileSize)\n        numBlocks++;\n      if (numBlocks < (unsigned)t2)\n      {\n        t2r = (int)numBlocks;\n        if (t2r == 0)\n          t2r = 1;\n        t3 = t1 * t2r;\n      }\n    }\n  }\n  \n  p->numBlockThreads_Max = t2;\n  p->numBlockThreads_Reduced = t2r;\n  p->numTotalThreads = t3;\n}\n\n\nstatic SRes Progress(ICompressProgressPtr p, UInt64 inSize, UInt64 outSize)\n{\n  return (p && ICompressProgress_Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;\n}\n\n\n/* ---------- Lzma2 ---------- */\n\nstruct CLzma2Enc\n{\n  Byte propEncoded;\n  CLzma2EncProps props;\n  UInt64 expectedDataSize;\n  \n  Byte *tempBufLzma;\n\n  ISzAllocPtr alloc;\n  ISzAllocPtr allocBig;\n\n  CLzma2EncInt coders[MTCODER_THREADS_MAX];\n\n  #ifndef Z7_ST\n  \n  ISeqOutStreamPtr outStream;\n  Byte *outBuf;\n  size_t outBuf_Rem;   /* remainder in outBuf */\n\n  size_t outBufSize;   /* size of allocated outBufs[i] */\n  size_t outBufsDataSizes[MTCODER_BLOCKS_MAX];\n  BoolInt mtCoder_WasConstructed;\n  CMtCoder mtCoder;\n  Byte *outBufs[MTCODER_BLOCKS_MAX];\n\n  #endif\n};\n\n\n\nCLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  CLzma2Enc *p = (CLzma2Enc *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Enc));\n  if (!p)\n    return NULL;\n  Lzma2EncProps_Init(&p->props);\n  Lzma2EncProps_Normalize(&p->props);\n  p->expectedDataSize = (UInt64)(Int64)-1;\n  p->tempBufLzma = NULL;\n  p->alloc = alloc;\n  p->allocBig = allocBig;\n  {\n    unsigned i;\n    for (i = 0; i < MTCODER_THREADS_MAX; i++)\n      p->coders[i].enc = NULL;\n  }\n  \n  #ifndef Z7_ST\n  p->mtCoder_WasConstructed = False;\n  {\n    unsigned i;\n    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)\n      p->outBufs[i] = NULL;\n    p->outBufSize = 0;\n  }\n  #endif\n\n  return (CLzma2EncHandle)p;\n}\n\n\n#ifndef Z7_ST\n\nstatic void Lzma2Enc_FreeOutBufs(CLzma2Enc *p)\n{\n  unsigned i;\n  for (i = 0; i < MTCODER_BLOCKS_MAX; i++)\n    if (p->outBufs[i])\n    {\n      ISzAlloc_Free(p->alloc, p->outBufs[i]);\n      p->outBufs[i] = NULL;\n    }\n  p->outBufSize = 0;\n}\n\n#endif\n\n// #define GET_CLzma2Enc_p  CLzma2Enc *p = (CLzma2Enc *)(void *)p;\n\nvoid Lzma2Enc_Destroy(CLzma2EncHandle p)\n{\n  // GET_CLzma2Enc_p\n  unsigned i;\n  for (i = 0; i < MTCODER_THREADS_MAX; i++)\n  {\n    CLzma2EncInt *t = &p->coders[i];\n    if (t->enc)\n    {\n      LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);\n      t->enc = NULL;\n    }\n  }\n\n\n  #ifndef Z7_ST\n  if (p->mtCoder_WasConstructed)\n  {\n    MtCoder_Destruct(&p->mtCoder);\n    p->mtCoder_WasConstructed = False;\n  }\n  Lzma2Enc_FreeOutBufs(p);\n  #endif\n\n  ISzAlloc_Free(p->alloc, p->tempBufLzma);\n  p->tempBufLzma = NULL;\n\n  ISzAlloc_Free(p->alloc, p);\n}\n\n\nSRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props)\n{\n  // GET_CLzma2Enc_p\n  CLzmaEncProps lzmaProps = props->lzmaProps;\n  LzmaEncProps_Normalize(&lzmaProps);\n  if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)\n    return SZ_ERROR_PARAM;\n  p->props = *props;\n  Lzma2EncProps_Normalize(&p->props);\n  return SZ_OK;\n}\n\n\nvoid Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize)\n{\n  // GET_CLzma2Enc_p\n  p->expectedDataSize = expectedDataSiize;\n}\n\n\nByte Lzma2Enc_WriteProperties(CLzma2EncHandle p)\n{\n  // GET_CLzma2Enc_p\n  unsigned i;\n  UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);\n  for (i = 0; i < 40; i++)\n    if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))\n      break;\n  return (Byte)i;\n}\n\n\nstatic SRes Lzma2Enc_EncodeMt1(\n    CLzma2Enc *me,\n    CLzma2EncInt *p,\n    ISeqOutStreamPtr outStream,\n    Byte *outBuf, size_t *outBufSize,\n    ISeqInStreamPtr inStream,\n    const Byte *inData, size_t inDataSize,\n    int finished,\n    ICompressProgressPtr progress)\n{\n  UInt64 unpackTotal = 0;\n  UInt64 packTotal = 0;\n  size_t outLim = 0;\n  CLimitedSeqInStream limitedInStream;\n\n  if (outBuf)\n  {\n    outLim = *outBufSize;\n    *outBufSize = 0;\n  }\n\n  if (!p->enc)\n  {\n    p->propsAreSet = False;\n    p->enc = LzmaEnc_Create(me->alloc);\n    if (!p->enc)\n      return SZ_ERROR_MEM;\n  }\n\n  limitedInStream.realStream = inStream;\n  if (inStream)\n  {\n    limitedInStream.vt.Read = LimitedSeqInStream_Read;\n  }\n  \n  if (!outBuf)\n  {\n    // outStream version works only in one thread. So we use CLzma2Enc::tempBufLzma\n    if (!me->tempBufLzma)\n    {\n      me->tempBufLzma = (Byte *)ISzAlloc_Alloc(me->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);\n      if (!me->tempBufLzma)\n        return SZ_ERROR_MEM;\n    }\n  }\n\n  RINOK(Lzma2EncInt_InitStream(p, &me->props))\n\n  for (;;)\n  {\n    SRes res = SZ_OK;\n    SizeT inSizeCur = 0;\n\n    Lzma2EncInt_InitBlock(p);\n    \n    LimitedSeqInStream_Init(&limitedInStream);\n    limitedInStream.limit = me->props.blockSize;\n\n    if (inStream)\n    {\n      UInt64 expected = (UInt64)(Int64)-1;\n      // inStream version works only in one thread. So we use CLzma2Enc::expectedDataSize\n      if (me->expectedDataSize != (UInt64)(Int64)-1\n          && me->expectedDataSize >= unpackTotal)\n        expected = me->expectedDataSize - unpackTotal;\n      if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID\n          && expected > me->props.blockSize)\n        expected = (size_t)me->props.blockSize;\n\n      LzmaEnc_SetDataSize(p->enc, expected);\n\n      RINOK(LzmaEnc_PrepareForLzma2(p->enc,\n          &limitedInStream.vt,\n          LZMA2_KEEP_WINDOW_SIZE,\n          me->alloc,\n          me->allocBig))\n    }\n    else\n    {\n      inSizeCur = (SizeT)(inDataSize - (size_t)unpackTotal);\n      if (me->props.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID\n          && inSizeCur > me->props.blockSize)\n        inSizeCur = (SizeT)(size_t)me->props.blockSize;\n    \n      // LzmaEnc_SetDataSize(p->enc, inSizeCur);\n      \n      RINOK(LzmaEnc_MemPrepare(p->enc,\n          inData + (size_t)unpackTotal, inSizeCur,\n          LZMA2_KEEP_WINDOW_SIZE,\n          me->alloc,\n          me->allocBig))\n    }\n\n    for (;;)\n    {\n      size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;\n      if (outBuf)\n        packSize = outLim - (size_t)packTotal;\n      \n      res = Lzma2EncInt_EncodeSubblock(p,\n          outBuf ? outBuf + (size_t)packTotal : me->tempBufLzma, &packSize,\n          outBuf ? NULL : outStream);\n      \n      if (res != SZ_OK)\n        break;\n\n      packTotal += packSize;\n      if (outBuf)\n        *outBufSize = (size_t)packTotal;\n      \n      res = Progress(progress, unpackTotal + p->srcPos, packTotal);\n      if (res != SZ_OK)\n        break;\n\n      /*\n      if (LzmaEnc_GetNumAvailableBytes(p->enc) == 0)\n        break;\n      */\n\n      if (packSize == 0)\n        break;\n    }\n    \n    LzmaEnc_Finish(p->enc);\n    \n    unpackTotal += p->srcPos;\n    \n    RINOK(res)\n\n    if (p->srcPos != (inStream ? limitedInStream.processed : inSizeCur))\n      return SZ_ERROR_FAIL;\n    \n    if (inStream ? limitedInStream.finished : (unpackTotal == inDataSize))\n    {\n      if (finished)\n      {\n        if (outBuf)\n        {\n          const size_t destPos = *outBufSize;\n          if (destPos >= outLim)\n            return SZ_ERROR_OUTPUT_EOF;\n          outBuf[destPos] = LZMA2_CONTROL_EOF; // 0\n          *outBufSize = destPos + 1;\n        }\n        else\n        {\n          const Byte b = LZMA2_CONTROL_EOF; // 0;\n          if (ISeqOutStream_Write(outStream, &b, 1) != 1)\n            return SZ_ERROR_WRITE;\n        }\n      }\n      return SZ_OK;\n    }\n  }\n}\n\n\n\n#ifndef Z7_ST\n\nstatic SRes Lzma2Enc_MtCallback_Code(void *p, unsigned coderIndex, unsigned outBufIndex,\n    const Byte *src, size_t srcSize, int finished)\n{\n  CLzma2Enc *me = (CLzma2Enc *)p;\n  size_t destSize = me->outBufSize;\n  SRes res;\n  CMtProgressThunk progressThunk;\n\n  Byte *dest = me->outBufs[outBufIndex];\n\n  me->outBufsDataSizes[outBufIndex] = 0;\n\n  if (!dest)\n  {\n    dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);\n    if (!dest)\n      return SZ_ERROR_MEM;\n    me->outBufs[outBufIndex] = dest;\n  }\n\n  MtProgressThunk_CreateVTable(&progressThunk);\n  progressThunk.mtProgress = &me->mtCoder.mtProgress;\n  progressThunk.inSize = 0;\n  progressThunk.outSize = 0;\n\n  res = Lzma2Enc_EncodeMt1(me,\n      &me->coders[coderIndex],\n      NULL, dest, &destSize,\n      NULL, src, srcSize,\n      finished,\n      &progressThunk.vt);\n\n  me->outBufsDataSizes[outBufIndex] = destSize;\n\n  return res;\n}\n\n\nstatic SRes Lzma2Enc_MtCallback_Write(void *p, unsigned outBufIndex)\n{\n  CLzma2Enc *me = (CLzma2Enc *)p;\n  size_t size = me->outBufsDataSizes[outBufIndex];\n  const Byte *data = me->outBufs[outBufIndex];\n  \n  if (me->outStream)\n    return ISeqOutStream_Write(me->outStream, data, size) == size ? SZ_OK : SZ_ERROR_WRITE;\n  \n  if (size > me->outBuf_Rem)\n    return SZ_ERROR_OUTPUT_EOF;\n  memcpy(me->outBuf, data, size);\n  me->outBuf_Rem -= size;\n  me->outBuf += size;\n  return SZ_OK;\n}\n\n#endif\n\n\n\nSRes Lzma2Enc_Encode2(CLzma2EncHandle p,\n    ISeqOutStreamPtr outStream,\n    Byte *outBuf, size_t *outBufSize,\n    ISeqInStreamPtr inStream,\n    const Byte *inData, size_t inDataSize,\n    ICompressProgressPtr progress)\n{\n  // GET_CLzma2Enc_p\n\n  if (inStream && inData)\n    return SZ_ERROR_PARAM;\n\n  if (outStream && outBuf)\n    return SZ_ERROR_PARAM;\n\n  {\n    unsigned i;\n    for (i = 0; i < MTCODER_THREADS_MAX; i++)\n      p->coders[i].propsAreSet = False;\n  }\n\n  #ifndef Z7_ST\n  \n  if (p->props.numBlockThreads_Reduced > 1)\n  {\n    IMtCoderCallback2 vt;\n\n    if (!p->mtCoder_WasConstructed)\n    {\n      p->mtCoder_WasConstructed = True;\n      MtCoder_Construct(&p->mtCoder);\n    }\n\n    vt.Code = Lzma2Enc_MtCallback_Code;\n    vt.Write = Lzma2Enc_MtCallback_Write;\n\n    p->outStream = outStream;\n    p->outBuf = NULL;\n    p->outBuf_Rem = 0;\n    if (!outStream)\n    {\n      p->outBuf = outBuf;\n      p->outBuf_Rem = *outBufSize;\n      *outBufSize = 0;\n    }\n\n    p->mtCoder.allocBig = p->allocBig;\n    p->mtCoder.progress = progress;\n    p->mtCoder.inStream = inStream;\n    p->mtCoder.inData = inData;\n    p->mtCoder.inDataSize = inDataSize;\n    p->mtCoder.mtCallback = &vt;\n    p->mtCoder.mtCallbackObject = p;\n\n    p->mtCoder.blockSize = (size_t)p->props.blockSize;\n    if (p->mtCoder.blockSize != p->props.blockSize)\n      return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */\n\n    {\n      const size_t destBlockSize = p->mtCoder.blockSize + (p->mtCoder.blockSize >> 10) + 16;\n      if (destBlockSize < p->mtCoder.blockSize)\n        return SZ_ERROR_PARAM;\n      if (p->outBufSize != destBlockSize)\n        Lzma2Enc_FreeOutBufs(p);\n      p->outBufSize = destBlockSize;\n    }\n\n    p->mtCoder.numThreadsMax = (unsigned)p->props.numBlockThreads_Max;\n    p->mtCoder.numThreadGroups = p->props.numThreadGroups;\n    p->mtCoder.expectedDataSize = p->expectedDataSize;\n    \n    {\n      const SRes res = MtCoder_Code(&p->mtCoder);\n      if (!outStream)\n        *outBufSize = (size_t)(p->outBuf - outBuf);\n      return res;\n    }\n  }\n\n  #endif\n\n\n  return Lzma2Enc_EncodeMt1(p,\n      &p->coders[0],\n      outStream, outBuf, outBufSize,\n      inStream, inData, inDataSize,\n      True, /* finished */\n      progress);\n}\n\n#undef PRF\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Lzma2Enc.h",
    "content": "﻿/* Lzma2Enc.h -- LZMA2 Encoder\n2023-04-13 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZMA2_ENC_H\n#define ZIP7_INC_LZMA2_ENC_H\n\n#include \"LzmaEnc.h\"\n\nEXTERN_C_BEGIN\n\n#define LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO   0\n#define LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID  ((UInt64)(Int64)-1)\n\ntypedef struct\n{\n  CLzmaEncProps lzmaProps;\n  UInt64 blockSize;\n  int numBlockThreads_Reduced;\n  int numBlockThreads_Max;\n  int numTotalThreads;\n  unsigned numThreadGroups; // 0 : no groups\n} CLzma2EncProps;\n\nvoid Lzma2EncProps_Init(CLzma2EncProps *p);\nvoid Lzma2EncProps_Normalize(CLzma2EncProps *p);\n\n/* ---------- CLzmaEnc2Handle Interface ---------- */\n\n/* Lzma2Enc_* functions can return the following exit codes:\nSRes:\n  SZ_OK           - OK\n  SZ_ERROR_MEM    - Memory allocation error\n  SZ_ERROR_PARAM  - Incorrect paramater in props\n  SZ_ERROR_WRITE  - ISeqOutStream write callback error\n  SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output\n  SZ_ERROR_PROGRESS - some break from progress callback\n  SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)\n*/\n\ntypedef struct CLzma2Enc CLzma2Enc;\ntypedef CLzma2Enc * CLzma2EncHandle;\n// Z7_DECLARE_HANDLE(CLzma2EncHandle)\n\nCLzma2EncHandle Lzma2Enc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);\nvoid Lzma2Enc_Destroy(CLzma2EncHandle p);\nSRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);\nvoid Lzma2Enc_SetDataSize(CLzma2EncHandle p, UInt64 expectedDataSiize);\nByte Lzma2Enc_WriteProperties(CLzma2EncHandle p);\nSRes Lzma2Enc_Encode2(CLzma2EncHandle p,\n    ISeqOutStreamPtr outStream,\n    Byte *outBuf, size_t *outBufSize,\n    ISeqInStreamPtr inStream,\n    const Byte *inData, size_t inDataSize,\n    ICompressProgressPtr progress);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzmaDec.c",
    "content": "﻿/* LzmaDec.c -- LZMA Decoder\n2023-04-07 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n/* #include \"CpuArch.h\" */\n#include \"LzmaDec.h\"\n\n// #define kNumTopBits 24\n#define kTopValue ((UInt32)1 << 24)\n\n#define kNumBitModelTotalBits 11\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\n\n#define RC_INIT_SIZE 5\n\n#ifndef Z7_LZMA_DEC_OPT\n\n#define kNumMoveBits 5\n#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }\n\n#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)\n#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\n#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));\n#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \\\n  { UPDATE_0(p)  i = (i + i); A0; } else \\\n  { UPDATE_1(p)  i = (i + i) + 1; A1; }\n\n#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); }\n\n#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \\\n  { UPDATE_0(p + i)  A0; } else \\\n  { UPDATE_1(p + i)  A1; }\n#define REV_BIT_VAR(  p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; )\n#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m;       , i += m * 2; )\n#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m        , ; )\n\n#define TREE_DECODE(probs, limit, i) \\\n  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }\n\n/* #define Z7_LZMA_SIZE_OPT */\n\n#ifdef Z7_LZMA_SIZE_OPT\n#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)\n#else\n#define TREE_6_DECODE(probs, i) \\\n  { i = 1; \\\n  TREE_GET_BIT(probs, i) \\\n  TREE_GET_BIT(probs, i) \\\n  TREE_GET_BIT(probs, i) \\\n  TREE_GET_BIT(probs, i) \\\n  TREE_GET_BIT(probs, i) \\\n  TREE_GET_BIT(probs, i) \\\n  i -= 0x40; }\n#endif\n\n#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol)\n#define MATCHED_LITER_DEC \\\n  matchByte += matchByte; \\\n  bit = offs; \\\n  offs &= matchByte; \\\n  probLit = prob + (offs + bit + symbol); \\\n  GET_BIT2(probLit, symbol, offs ^= bit; , ;)\n\n#endif // Z7_LZMA_DEC_OPT\n\n\n#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); }\n\n#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)\n#define UPDATE_0_CHECK range = bound;\n#define UPDATE_1_CHECK range -= bound; code -= bound;\n#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \\\n  { UPDATE_0_CHECK  i = (i + i); A0; } else \\\n  { UPDATE_1_CHECK  i = (i + i) + 1; A1; }\n#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)\n#define TREE_DECODE_CHECK(probs, limit, i) \\\n  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }\n\n\n#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \\\n  { UPDATE_0_CHECK  i += m; m += m; } else \\\n  { UPDATE_1_CHECK  m += m; i += m; }\n\n\n#define kNumPosBitsMax 4\n#define kNumPosStatesMax (1 << kNumPosBitsMax)\n\n#define kLenNumLowBits 3\n#define kLenNumLowSymbols (1 << kLenNumLowBits)\n#define kLenNumHighBits 8\n#define kLenNumHighSymbols (1 << kLenNumHighBits)\n\n#define LenLow 0\n#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits))\n#define kNumLenProbs (LenHigh + kLenNumHighSymbols)\n\n#define LenChoice LenLow\n#define LenChoice2 (LenLow + (1 << kLenNumLowBits))\n\n#define kNumStates 12\n#define kNumStates2 16\n#define kNumLitStates 7\n\n#define kStartPosModelIndex 4\n#define kEndPosModelIndex 14\n#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\n\n#define kNumPosSlotBits 6\n#define kNumLenToPosStates 4\n\n#define kNumAlignBits 4\n#define kAlignTableSize (1 << kNumAlignBits)\n\n#define kMatchMinLen 2\n#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)\n\n#define kMatchSpecLen_Error_Data (1 << 9)\n#define kMatchSpecLen_Error_Fail (kMatchSpecLen_Error_Data - 1)\n\n/* External ASM code needs same CLzmaProb array layout. So don't change it. */\n\n/* (probs_1664) is faster and better for code size at some platforms */\n/*\n#ifdef MY_CPU_X86_OR_AMD64\n*/\n#define kStartOffset 1664\n#define GET_PROBS p->probs_1664\n/*\n#define GET_PROBS p->probs + kStartOffset\n#else\n#define kStartOffset 0\n#define GET_PROBS p->probs\n#endif\n*/\n\n#define SpecPos (-kStartOffset)\n#define IsRep0Long (SpecPos + kNumFullDistances)\n#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax))\n#define LenCoder (RepLenCoder + kNumLenProbs)\n#define IsMatch (LenCoder + kNumLenProbs)\n#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax))\n#define IsRep (Align + kAlignTableSize)\n#define IsRepG0 (IsRep + kNumStates)\n#define IsRepG1 (IsRepG0 + kNumStates)\n#define IsRepG2 (IsRepG1 + kNumStates)\n#define PosSlot (IsRepG2 + kNumStates)\n#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\n#define NUM_BASE_PROBS (Literal + kStartOffset)\n\n#if Align != 0 && kStartOffset != 0\n  #error Stop_Compiling_Bad_LZMA_kAlign\n#endif\n\n#if NUM_BASE_PROBS != 1984\n  #error Stop_Compiling_Bad_LZMA_PROBS\n#endif\n\n\n#define LZMA_LIT_SIZE 0x300\n\n#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))\n\n\n#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4)\n#define COMBINED_PS_STATE (posState + state)\n#define GET_LEN_STATE (posState)\n\n#define LZMA_DIC_MIN (1 << 12)\n\n/*\np->remainLen : shows status of LZMA decoder:\n    < kMatchSpecLenStart  : the number of bytes to be copied with (p->rep0) offset\n    = kMatchSpecLenStart  : the LZMA stream was finished with end mark\n    = kMatchSpecLenStart + 1  : need init range coder\n    = kMatchSpecLenStart + 2  : need init range coder and state\n    = kMatchSpecLen_Error_Fail                : Internal Code Failure\n    = kMatchSpecLen_Error_Data + [0 ... 273]  : LZMA Data Error\n*/\n\n/* ---------- LZMA_DECODE_REAL ---------- */\n/*\nLzmaDec_DecodeReal_3() can be implemented in external ASM file.\n3 - is the code compatibility version of that function for check at link time.\n*/\n\n#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3\n\n/*\nLZMA_DECODE_REAL()\nIn:\n  RangeCoder is normalized\n  if (p->dicPos == limit)\n  {\n    LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.\n    So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol\n    is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary,\n    the function returns SZ_OK, and the caller can use (p->remainLen) and (p->reps[0]) later.\n  }\n\nProcessing:\n  The first LZMA symbol will be decoded in any case.\n  All main checks for limits are at the end of main loop,\n  It decodes additional LZMA-symbols while (p->buf < bufLimit && dicPos < limit),\n  RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.\n  But if (p->buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for\n  next iteration  before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX),\n  that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit.\n  So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte.\n\nOut:\n  RangeCoder is normalized\n  Result:\n    SZ_OK - OK\n      p->remainLen:\n        < kMatchSpecLenStart : the number of bytes to be copied with (p->reps[0]) offset\n        = kMatchSpecLenStart : the LZMA stream was finished with end mark\n\n    SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary\n      p->remainLen : undefined\n      p->reps[*]    : undefined\n*/\n\n\n#ifdef Z7_LZMA_DEC_OPT\n\nint Z7_FASTCALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit);\n\n#else\n\nstatic\nint Z7_FASTCALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\n{\n  CLzmaProb *probs = GET_PROBS;\n  unsigned state = (unsigned)p->state;\n  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];\n  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;\n  unsigned lc = p->prop.lc;\n  unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc);\n\n  Byte *dic = p->dic;\n  SizeT dicBufSize = p->dicBufSize;\n  SizeT dicPos = p->dicPos;\n  \n  UInt32 processedPos = p->processedPos;\n  UInt32 checkDicSize = p->checkDicSize;\n  unsigned len = 0;\n\n  const Byte *buf = p->buf;\n  UInt32 range = p->range;\n  UInt32 code = p->code;\n\n  do\n  {\n    CLzmaProb *prob;\n    UInt32 bound;\n    unsigned ttt;\n    unsigned posState = CALC_POS_STATE(processedPos, pbMask);\n\n    prob = probs + IsMatch + COMBINED_PS_STATE;\n    IF_BIT_0(prob)\n    {\n      unsigned symbol;\n      UPDATE_0(prob)\n      prob = probs + Literal;\n      if (processedPos != 0 || checkDicSize != 0)\n        prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);\n      processedPos++;\n\n      if (state < kNumLitStates)\n      {\n        state -= (state < 4) ? state : 3;\n        symbol = 1;\n        #ifdef Z7_LZMA_SIZE_OPT\n        do { NORMAL_LITER_DEC } while (symbol < 0x100);\n        #else\n        NORMAL_LITER_DEC\n        NORMAL_LITER_DEC\n        NORMAL_LITER_DEC\n        NORMAL_LITER_DEC\n        NORMAL_LITER_DEC\n        NORMAL_LITER_DEC\n        NORMAL_LITER_DEC\n        NORMAL_LITER_DEC\n        #endif\n      }\n      else\n      {\n        unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\n        unsigned offs = 0x100;\n        state -= (state < 10) ? 3 : 6;\n        symbol = 1;\n        #ifdef Z7_LZMA_SIZE_OPT\n        do\n        {\n          unsigned bit;\n          CLzmaProb *probLit;\n          MATCHED_LITER_DEC\n        }\n        while (symbol < 0x100);\n        #else\n        {\n          unsigned bit;\n          CLzmaProb *probLit;\n          MATCHED_LITER_DEC\n          MATCHED_LITER_DEC\n          MATCHED_LITER_DEC\n          MATCHED_LITER_DEC\n          MATCHED_LITER_DEC\n          MATCHED_LITER_DEC\n          MATCHED_LITER_DEC\n          MATCHED_LITER_DEC\n        }\n        #endif\n      }\n\n      dic[dicPos++] = (Byte)symbol;\n      continue;\n    }\n    \n    {\n      UPDATE_1(prob)\n      prob = probs + IsRep + state;\n      IF_BIT_0(prob)\n      {\n        UPDATE_0(prob)\n        state += kNumStates;\n        prob = probs + LenCoder;\n      }\n      else\n      {\n        UPDATE_1(prob)\n        prob = probs + IsRepG0 + state;\n        IF_BIT_0(prob)\n        {\n          UPDATE_0(prob)\n          prob = probs + IsRep0Long + COMBINED_PS_STATE;\n          IF_BIT_0(prob)\n          {\n            UPDATE_0(prob)\n  \n            // that case was checked before with kBadRepCode\n            // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; }\n            // The caller doesn't allow (dicPos == limit) case here\n            // so we don't need the following check:\n            // if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; }\n            \n            dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\n            dicPos++;\n            processedPos++;\n            state = state < kNumLitStates ? 9 : 11;\n            continue;\n          }\n          UPDATE_1(prob)\n        }\n        else\n        {\n          UInt32 distance;\n          UPDATE_1(prob)\n          prob = probs + IsRepG1 + state;\n          IF_BIT_0(prob)\n          {\n            UPDATE_0(prob)\n            distance = rep1;\n          }\n          else\n          {\n            UPDATE_1(prob)\n            prob = probs + IsRepG2 + state;\n            IF_BIT_0(prob)\n            {\n              UPDATE_0(prob)\n              distance = rep2;\n            }\n            else\n            {\n              UPDATE_1(prob)\n              distance = rep3;\n              rep3 = rep2;\n            }\n            rep2 = rep1;\n          }\n          rep1 = rep0;\n          rep0 = distance;\n        }\n        state = state < kNumLitStates ? 8 : 11;\n        prob = probs + RepLenCoder;\n      }\n      \n      #ifdef Z7_LZMA_SIZE_OPT\n      {\n        unsigned lim, offset;\n        CLzmaProb *probLen = prob + LenChoice;\n        IF_BIT_0(probLen)\n        {\n          UPDATE_0(probLen)\n          probLen = prob + LenLow + GET_LEN_STATE;\n          offset = 0;\n          lim = (1 << kLenNumLowBits);\n        }\n        else\n        {\n          UPDATE_1(probLen)\n          probLen = prob + LenChoice2;\n          IF_BIT_0(probLen)\n          {\n            UPDATE_0(probLen)\n            probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);\n            offset = kLenNumLowSymbols;\n            lim = (1 << kLenNumLowBits);\n          }\n          else\n          {\n            UPDATE_1(probLen)\n            probLen = prob + LenHigh;\n            offset = kLenNumLowSymbols * 2;\n            lim = (1 << kLenNumHighBits);\n          }\n        }\n        TREE_DECODE(probLen, lim, len)\n        len += offset;\n      }\n      #else\n      {\n        CLzmaProb *probLen = prob + LenChoice;\n        IF_BIT_0(probLen)\n        {\n          UPDATE_0(probLen)\n          probLen = prob + LenLow + GET_LEN_STATE;\n          len = 1;\n          TREE_GET_BIT(probLen, len)\n          TREE_GET_BIT(probLen, len)\n          TREE_GET_BIT(probLen, len)\n          len -= 8;\n        }\n        else\n        {\n          UPDATE_1(probLen)\n          probLen = prob + LenChoice2;\n          IF_BIT_0(probLen)\n          {\n            UPDATE_0(probLen)\n            probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);\n            len = 1;\n            TREE_GET_BIT(probLen, len)\n            TREE_GET_BIT(probLen, len)\n            TREE_GET_BIT(probLen, len)\n          }\n          else\n          {\n            UPDATE_1(probLen)\n            probLen = prob + LenHigh;\n            TREE_DECODE(probLen, (1 << kLenNumHighBits), len)\n            len += kLenNumLowSymbols * 2;\n          }\n        }\n      }\n      #endif\n\n      if (state >= kNumStates)\n      {\n        UInt32 distance;\n        prob = probs + PosSlot +\n            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);\n        TREE_6_DECODE(prob, distance)\n        if (distance >= kStartPosModelIndex)\n        {\n          unsigned posSlot = (unsigned)distance;\n          unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));\n          distance = (2 | (distance & 1));\n          if (posSlot < kEndPosModelIndex)\n          {\n            distance <<= numDirectBits;\n            prob = probs + SpecPos;\n            {\n              UInt32 m = 1;\n              distance++;\n              do\n              {\n                REV_BIT_VAR(prob, distance, m)\n              }\n              while (--numDirectBits);\n              distance -= m;\n            }\n          }\n          else\n          {\n            numDirectBits -= kNumAlignBits;\n            do\n            {\n              NORMALIZE\n              range >>= 1;\n              \n              {\n                UInt32 t;\n                code -= range;\n                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */\n                distance = (distance << 1) + (t + 1);\n                code += range & t;\n              }\n              /*\n              distance <<= 1;\n              if (code >= range)\n              {\n                code -= range;\n                distance |= 1;\n              }\n              */\n            }\n            while (--numDirectBits);\n            prob = probs + Align;\n            distance <<= kNumAlignBits;\n            {\n              unsigned i = 1;\n              REV_BIT_CONST(prob, i, 1)\n              REV_BIT_CONST(prob, i, 2)\n              REV_BIT_CONST(prob, i, 4)\n              REV_BIT_LAST (prob, i, 8)\n              distance |= i;\n            }\n            if (distance == (UInt32)0xFFFFFFFF)\n            {\n              len = kMatchSpecLenStart;\n              state -= kNumStates;\n              break;\n            }\n          }\n        }\n        \n        rep3 = rep2;\n        rep2 = rep1;\n        rep1 = rep0;\n        rep0 = distance + 1;\n        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;\n        if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))\n        {\n          len += kMatchSpecLen_Error_Data + kMatchMinLen;\n          // len = kMatchSpecLen_Error_Data;\n          // len += kMatchMinLen;\n          break;\n        }\n      }\n\n      len += kMatchMinLen;\n\n      {\n        SizeT rem;\n        unsigned curLen;\n        SizeT pos;\n        \n        if ((rem = limit - dicPos) == 0)\n        {\n          /*\n          We stop decoding and return SZ_OK, and we can resume decoding later.\n          Any error conditions can be tested later in caller code.\n          For more strict mode we can stop decoding with error\n          // len += kMatchSpecLen_Error_Data;\n          */\n          break;\n        }\n        \n        curLen = ((rem < len) ? (unsigned)rem : len);\n        pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);\n\n        processedPos += (UInt32)curLen;\n\n        len -= curLen;\n        if (curLen <= dicBufSize - pos)\n        {\n          Byte *dest = dic + dicPos;\n          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;\n          const Byte *lim = dest + curLen;\n          dicPos += (SizeT)curLen;\n          do\n            *(dest) = (Byte)*(dest + src);\n          while (++dest != lim);\n        }\n        else\n        {\n          do\n          {\n            dic[dicPos++] = dic[pos];\n            if (++pos == dicBufSize)\n              pos = 0;\n          }\n          while (--curLen != 0);\n        }\n      }\n    }\n  }\n  while (dicPos < limit && buf < bufLimit);\n\n  NORMALIZE\n  \n  p->buf = buf;\n  p->range = range;\n  p->code = code;\n  p->remainLen = (UInt32)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too.\n  p->dicPos = dicPos;\n  p->processedPos = processedPos;\n  p->reps[0] = rep0;\n  p->reps[1] = rep1;\n  p->reps[2] = rep2;\n  p->reps[3] = rep3;\n  p->state = (UInt32)state;\n  if (len >= kMatchSpecLen_Error_Data)\n    return SZ_ERROR_DATA;\n  return SZ_OK;\n}\n#endif\n\n\n\nstatic void Z7_FASTCALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)\n{\n  unsigned len = (unsigned)p->remainLen;\n  if (len == 0 /* || len >= kMatchSpecLenStart */)\n    return;\n  {\n    SizeT dicPos = p->dicPos;\n    Byte *dic;\n    SizeT dicBufSize;\n    SizeT rep0;   /* we use SizeT to avoid the BUG of VC14 for AMD64 */\n    {\n      SizeT rem = limit - dicPos;\n      if (rem < len)\n      {\n        len = (unsigned)(rem);\n        if (len == 0)\n          return;\n      }\n    }\n\n    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)\n      p->checkDicSize = p->prop.dicSize;\n\n    p->processedPos += (UInt32)len;\n    p->remainLen -= (UInt32)len;\n    dic = p->dic;\n    rep0 = p->reps[0];\n    dicBufSize = p->dicBufSize;\n    do\n    {\n      dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\n      dicPos++;\n    }\n    while (--len);\n    p->dicPos = dicPos;\n  }\n}\n\n\n/*\nAt staring of new stream we have one of the following symbols:\n  - Literal        - is allowed\n  - Non-Rep-Match  - is allowed only if it's end marker symbol\n  - Rep-Match      - is not allowed\nWe use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code\n*/\n\n#define kRange0 0xFFFFFFFF\n#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))\n#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))\n#if kBadRepCode != (0xC0000000 - 0x400)\n  #error Stop_Compiling_Bad_LZMA_Check\n#endif\n\n\n/*\nLzmaDec_DecodeReal2():\n  It calls LZMA_DECODE_REAL() and it adjusts limit according (p->checkDicSize).\n\nWe correct (p->checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(),\nand we support the following state of (p->checkDicSize):\n  if (total_processed < p->prop.dicSize) then\n  {\n    (total_processed == p->processedPos)\n    (p->checkDicSize == 0)\n  }\n  else\n    (p->checkDicSize == p->prop.dicSize)\n*/\n\nstatic int Z7_FASTCALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\n{\n  if (p->checkDicSize == 0)\n  {\n    UInt32 rem = p->prop.dicSize - p->processedPos;\n    if (limit - p->dicPos > rem)\n      limit = p->dicPos + rem;\n  }\n  {\n    int res = LZMA_DECODE_REAL(p, limit, bufLimit);\n    if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)\n      p->checkDicSize = p->prop.dicSize;\n    return res;\n  }\n}\n\n\n\ntypedef enum\n{\n  DUMMY_INPUT_EOF, /* need more input data */\n  DUMMY_LIT,\n  DUMMY_MATCH,\n  DUMMY_REP\n} ELzmaDummy;\n\n\n#define IS_DUMMY_END_MARKER_POSSIBLE(dummyRes) ((dummyRes) == DUMMY_MATCH)\n\nstatic ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byte **bufOut)\n{\n  UInt32 range = p->range;\n  UInt32 code = p->code;\n  const Byte *bufLimit = *bufOut;\n  const CLzmaProb *probs = GET_PROBS;\n  unsigned state = (unsigned)p->state;\n  ELzmaDummy res;\n\n  for (;;)\n  {\n    const CLzmaProb *prob;\n    UInt32 bound;\n    unsigned ttt;\n    unsigned posState = CALC_POS_STATE(p->processedPos, ((unsigned)1 << p->prop.pb) - 1);\n\n    prob = probs + IsMatch + COMBINED_PS_STATE;\n    IF_BIT_0_CHECK(prob)\n    {\n      UPDATE_0_CHECK\n\n      prob = probs + Literal;\n      if (p->checkDicSize != 0 || p->processedPos != 0)\n        prob += ((UInt32)LZMA_LIT_SIZE *\n            ((((p->processedPos) & (((unsigned)1 << (p->prop.lp)) - 1)) << p->prop.lc) +\n            ((unsigned)p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));\n\n      if (state < kNumLitStates)\n      {\n        unsigned symbol = 1;\n        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);\n      }\n      else\n      {\n        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +\n            (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];\n        unsigned offs = 0x100;\n        unsigned symbol = 1;\n        do\n        {\n          unsigned bit;\n          const CLzmaProb *probLit;\n          matchByte += matchByte;\n          bit = offs;\n          offs &= matchByte;\n          probLit = prob + (offs + bit + symbol);\n          GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; )\n        }\n        while (symbol < 0x100);\n      }\n      res = DUMMY_LIT;\n    }\n    else\n    {\n      unsigned len;\n      UPDATE_1_CHECK\n\n      prob = probs + IsRep + state;\n      IF_BIT_0_CHECK(prob)\n      {\n        UPDATE_0_CHECK\n        state = 0;\n        prob = probs + LenCoder;\n        res = DUMMY_MATCH;\n      }\n      else\n      {\n        UPDATE_1_CHECK\n        res = DUMMY_REP;\n        prob = probs + IsRepG0 + state;\n        IF_BIT_0_CHECK(prob)\n        {\n          UPDATE_0_CHECK\n          prob = probs + IsRep0Long + COMBINED_PS_STATE;\n          IF_BIT_0_CHECK(prob)\n          {\n            UPDATE_0_CHECK\n            break;\n          }\n          else\n          {\n            UPDATE_1_CHECK\n          }\n        }\n        else\n        {\n          UPDATE_1_CHECK\n          prob = probs + IsRepG1 + state;\n          IF_BIT_0_CHECK(prob)\n          {\n            UPDATE_0_CHECK\n          }\n          else\n          {\n            UPDATE_1_CHECK\n            prob = probs + IsRepG2 + state;\n            IF_BIT_0_CHECK(prob)\n            {\n              UPDATE_0_CHECK\n            }\n            else\n            {\n              UPDATE_1_CHECK\n            }\n          }\n        }\n        state = kNumStates;\n        prob = probs + RepLenCoder;\n      }\n      {\n        unsigned limit, offset;\n        const CLzmaProb *probLen = prob + LenChoice;\n        IF_BIT_0_CHECK(probLen)\n        {\n          UPDATE_0_CHECK\n          probLen = prob + LenLow + GET_LEN_STATE;\n          offset = 0;\n          limit = 1 << kLenNumLowBits;\n        }\n        else\n        {\n          UPDATE_1_CHECK\n          probLen = prob + LenChoice2;\n          IF_BIT_0_CHECK(probLen)\n          {\n            UPDATE_0_CHECK\n            probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);\n            offset = kLenNumLowSymbols;\n            limit = 1 << kLenNumLowBits;\n          }\n          else\n          {\n            UPDATE_1_CHECK\n            probLen = prob + LenHigh;\n            offset = kLenNumLowSymbols * 2;\n            limit = 1 << kLenNumHighBits;\n          }\n        }\n        TREE_DECODE_CHECK(probLen, limit, len)\n        len += offset;\n      }\n\n      if (state < 4)\n      {\n        unsigned posSlot;\n        prob = probs + PosSlot +\n            ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<\n            kNumPosSlotBits);\n        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot)\n        if (posSlot >= kStartPosModelIndex)\n        {\n          unsigned numDirectBits = ((posSlot >> 1) - 1);\n\n          if (posSlot < kEndPosModelIndex)\n          {\n            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);\n          }\n          else\n          {\n            numDirectBits -= kNumAlignBits;\n            do\n            {\n              NORMALIZE_CHECK\n              range >>= 1;\n              code -= range & (((code - range) >> 31) - 1);\n              /* if (code >= range) code -= range; */\n            }\n            while (--numDirectBits);\n            prob = probs + Align;\n            numDirectBits = kNumAlignBits;\n          }\n          {\n            unsigned i = 1;\n            unsigned m = 1;\n            do\n            {\n              REV_BIT_CHECK(prob, i, m)\n            }\n            while (--numDirectBits);\n          }\n        }\n      }\n    }\n    break;\n  }\n  NORMALIZE_CHECK\n\n  *bufOut = buf;\n  return res;\n}\n\nvoid LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);\nvoid LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)\n{\n  p->remainLen = kMatchSpecLenStart + 1;\n  p->tempBufSize = 0;\n\n  if (initDic)\n  {\n    p->processedPos = 0;\n    p->checkDicSize = 0;\n    p->remainLen = kMatchSpecLenStart + 2;\n  }\n  if (initState)\n    p->remainLen = kMatchSpecLenStart + 2;\n}\n\nvoid LzmaDec_Init(CLzmaDec *p)\n{\n  p->dicPos = 0;\n  LzmaDec_InitDicAndState(p, True, True);\n}\n\n\n/*\nLZMA supports optional end_marker.\nSo the decoder can lookahead for one additional LZMA-Symbol to check end_marker.\nThat additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream.\nWhen the decoder reaches dicLimit, it looks (finishMode) parameter:\n  if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead\n  if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position\n\nWhen the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways:\n  1) Strict mode (default) : the decoder returns SZ_ERROR_DATA.\n  2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller\n     must check (status) value. The caller can show the error,\n     if the end of stream is expected, and the (status) is noit\n     LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK.\n*/\n\n\n#define RETURN_NOT_FINISHED_FOR_FINISH \\\n  *status = LZMA_STATUS_NOT_FINISHED; \\\n  return SZ_ERROR_DATA; // for strict mode\n  // return SZ_OK; // for relaxed mode\n\n\nSRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,\n    ELzmaFinishMode finishMode, ELzmaStatus *status)\n{\n  SizeT inSize = *srcLen;\n  (*srcLen) = 0;\n  *status = LZMA_STATUS_NOT_SPECIFIED;\n\n  if (p->remainLen > kMatchSpecLenStart)\n  {\n    if (p->remainLen > kMatchSpecLenStart + 2)\n      return p->remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA;\n\n    for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)\n      p->tempBuf[p->tempBufSize++] = *src++;\n    if (p->tempBufSize != 0 && p->tempBuf[0] != 0)\n      return SZ_ERROR_DATA;\n    if (p->tempBufSize < RC_INIT_SIZE)\n    {\n      *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n      return SZ_OK;\n    }\n    p->code =\n        ((UInt32)p->tempBuf[1] << 24)\n      | ((UInt32)p->tempBuf[2] << 16)\n      | ((UInt32)p->tempBuf[3] << 8)\n      | ((UInt32)p->tempBuf[4]);\n\n    if (p->checkDicSize == 0\n        && p->processedPos == 0\n        && p->code >= kBadRepCode)\n      return SZ_ERROR_DATA;\n\n    p->range = 0xFFFFFFFF;\n    p->tempBufSize = 0;\n\n    if (p->remainLen > kMatchSpecLenStart + 1)\n    {\n      SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);\n      SizeT i;\n      CLzmaProb *probs = p->probs;\n      for (i = 0; i < numProbs; i++)\n        probs[i] = kBitModelTotal >> 1;\n      p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;\n      p->state = 0;\n    }\n\n    p->remainLen = 0;\n  }\n\n  for (;;)\n  {\n    if (p->remainLen == kMatchSpecLenStart)\n    {\n      if (p->code != 0)\n        return SZ_ERROR_DATA;\n      *status = LZMA_STATUS_FINISHED_WITH_MARK;\n      return SZ_OK;\n    }\n\n    LzmaDec_WriteRem(p, dicLimit);\n\n    {\n      // (p->remainLen == 0 || p->dicPos == dicLimit)\n\n      int checkEndMarkNow = 0;\n\n      if (p->dicPos >= dicLimit)\n      {\n        if (p->remainLen == 0 && p->code == 0)\n        {\n          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;\n          return SZ_OK;\n        }\n        if (finishMode == LZMA_FINISH_ANY)\n        {\n          *status = LZMA_STATUS_NOT_FINISHED;\n          return SZ_OK;\n        }\n        if (p->remainLen != 0)\n        {\n          RETURN_NOT_FINISHED_FOR_FINISH\n        }\n        checkEndMarkNow = 1;\n      }\n\n      // (p->remainLen == 0)\n\n      if (p->tempBufSize == 0)\n      {\n        const Byte *bufLimit;\n        int dummyProcessed = -1;\n        \n        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\n        {\n          const Byte *bufOut = src + inSize;\n          \n          ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut);\n          \n          if (dummyRes == DUMMY_INPUT_EOF)\n          {\n            size_t i;\n            if (inSize >= LZMA_REQUIRED_INPUT_MAX)\n              break;\n            (*srcLen) += inSize;\n            p->tempBufSize = (unsigned)inSize;\n            for (i = 0; i < inSize; i++)\n              p->tempBuf[i] = src[i];\n            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n            return SZ_OK;\n          }\n \n          dummyProcessed = (int)(bufOut - src);\n          if ((unsigned)dummyProcessed > LZMA_REQUIRED_INPUT_MAX)\n            break;\n          \n          if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes))\n          {\n            unsigned i;\n            (*srcLen) += (unsigned)dummyProcessed;\n            p->tempBufSize = (unsigned)dummyProcessed;\n            for (i = 0; i < (unsigned)dummyProcessed; i++)\n              p->tempBuf[i] = src[i];\n            // p->remainLen = kMatchSpecLen_Error_Data;\n            RETURN_NOT_FINISHED_FOR_FINISH\n          }\n          \n          bufLimit = src;\n          // we will decode only one iteration\n        }\n        else\n          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;\n\n        p->buf = src;\n        \n        {\n          int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit);\n          \n          SizeT processed = (SizeT)(p->buf - src);\n\n          if (dummyProcessed < 0)\n          {\n            if (processed > inSize)\n              break;\n          }\n          else if ((unsigned)dummyProcessed != processed)\n            break;\n\n          src += processed;\n          inSize -= processed;\n          (*srcLen) += processed;\n\n          if (res != SZ_OK)\n          {\n            p->remainLen = kMatchSpecLen_Error_Data;\n            return SZ_ERROR_DATA;\n          }\n        }\n        continue;\n      }\n\n      {\n        // we have some data in (p->tempBuf)\n        // in strict mode: tempBufSize is not enough for one Symbol decoding.\n        // in relaxed mode: tempBufSize not larger than required for one Symbol decoding.\n\n        unsigned rem = p->tempBufSize;\n        unsigned ahead = 0;\n        int dummyProcessed = -1;\n        \n        while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize)\n          p->tempBuf[rem++] = src[ahead++];\n        \n        // ahead - the size of new data copied from (src) to (p->tempBuf)\n        // rem   - the size of temp buffer including new data from (src)\n        \n        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\n        {\n          const Byte *bufOut = p->tempBuf + rem;\n        \n          ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p->tempBuf, &bufOut);\n          \n          if (dummyRes == DUMMY_INPUT_EOF)\n          {\n            if (rem >= LZMA_REQUIRED_INPUT_MAX)\n              break;\n            p->tempBufSize = rem;\n            (*srcLen) += (SizeT)ahead;\n            *status = LZMA_STATUS_NEEDS_MORE_INPUT;\n            return SZ_OK;\n          }\n          \n          dummyProcessed = (int)(bufOut - p->tempBuf);\n\n          if ((unsigned)dummyProcessed < p->tempBufSize)\n            break;\n\n          if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes))\n          {\n            (*srcLen) += (unsigned)dummyProcessed - p->tempBufSize;\n            p->tempBufSize = (unsigned)dummyProcessed;\n            // p->remainLen = kMatchSpecLen_Error_Data;\n            RETURN_NOT_FINISHED_FOR_FINISH\n          }\n        }\n\n        p->buf = p->tempBuf;\n        \n        {\n          // we decode one symbol from (p->tempBuf) here, so the (bufLimit) is equal to (p->buf)\n          int res = LzmaDec_DecodeReal2(p, dicLimit, p->buf);\n\n          SizeT processed = (SizeT)(p->buf - p->tempBuf);\n          rem = p->tempBufSize;\n          \n          if (dummyProcessed < 0)\n          {\n            if (processed > LZMA_REQUIRED_INPUT_MAX)\n              break;\n            if (processed < rem)\n              break;\n          }\n          else if ((unsigned)dummyProcessed != processed)\n            break;\n          \n          processed -= rem;\n\n          src += processed;\n          inSize -= processed;\n          (*srcLen) += processed;\n          p->tempBufSize = 0;\n          \n          if (res != SZ_OK)\n          {\n            p->remainLen = kMatchSpecLen_Error_Data;\n            return SZ_ERROR_DATA;\n          }\n        }\n      }\n    }\n  }\n\n  /*  Some unexpected error: internal error of code, memory corruption or hardware failure */\n  p->remainLen = kMatchSpecLen_Error_Fail;\n  return SZ_ERROR_FAIL;\n}\n\n\n\nSRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\n{\n  SizeT outSize = *destLen;\n  SizeT inSize = *srcLen;\n  *srcLen = *destLen = 0;\n  for (;;)\n  {\n    SizeT inSizeCur = inSize, outSizeCur, dicPos;\n    ELzmaFinishMode curFinishMode;\n    SRes res;\n    if (p->dicPos == p->dicBufSize)\n      p->dicPos = 0;\n    dicPos = p->dicPos;\n    if (outSize > p->dicBufSize - dicPos)\n    {\n      outSizeCur = p->dicBufSize;\n      curFinishMode = LZMA_FINISH_ANY;\n    }\n    else\n    {\n      outSizeCur = dicPos + outSize;\n      curFinishMode = finishMode;\n    }\n\n    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);\n    src += inSizeCur;\n    inSize -= inSizeCur;\n    *srcLen += inSizeCur;\n    outSizeCur = p->dicPos - dicPos;\n    memcpy(dest, p->dic + dicPos, outSizeCur);\n    dest += outSizeCur;\n    outSize -= outSizeCur;\n    *destLen += outSizeCur;\n    if (res != 0)\n      return res;\n    if (outSizeCur == 0 || outSize == 0)\n      return SZ_OK;\n  }\n}\n\nvoid LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->probs);\n  p->probs = NULL;\n}\n\nstatic void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->dic);\n  p->dic = NULL;\n}\n\nvoid LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc)\n{\n  LzmaDec_FreeProbs(p, alloc);\n  LzmaDec_FreeDict(p, alloc);\n}\n\nSRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)\n{\n  UInt32 dicSize;\n  Byte d;\n  \n  if (size < LZMA_PROPS_SIZE)\n    return SZ_ERROR_UNSUPPORTED;\n  else\n    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);\n \n  if (dicSize < LZMA_DIC_MIN)\n    dicSize = LZMA_DIC_MIN;\n  p->dicSize = dicSize;\n\n  d = data[0];\n  if (d >= (9 * 5 * 5))\n    return SZ_ERROR_UNSUPPORTED;\n\n  p->lc = (Byte)(d % 9);\n  d /= 9;\n  p->pb = (Byte)(d / 5);\n  p->lp = (Byte)(d % 5);\n\n  return SZ_OK;\n}\n\nstatic SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc)\n{\n  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);\n  if (!p->probs || numProbs != p->numProbs)\n  {\n    LzmaDec_FreeProbs(p, alloc);\n    p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb));\n    if (!p->probs)\n      return SZ_ERROR_MEM;\n    p->probs_1664 = p->probs + 1664;\n    p->numProbs = numProbs;\n  }\n  return SZ_OK;\n}\n\nSRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)\n{\n  CLzmaProps propNew;\n  RINOK(LzmaProps_Decode(&propNew, props, propsSize))\n  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc))\n  p->prop = propNew;\n  return SZ_OK;\n}\n\nSRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)\n{\n  CLzmaProps propNew;\n  SizeT dicBufSize;\n  RINOK(LzmaProps_Decode(&propNew, props, propsSize))\n  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc))\n\n  {\n    UInt32 dictSize = propNew.dicSize;\n    SizeT mask = ((UInt32)1 << 12) - 1;\n         if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;\n    else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;\n    dicBufSize = ((SizeT)dictSize + mask) & ~mask;\n    if (dicBufSize < dictSize)\n      dicBufSize = dictSize;\n  }\n\n  if (!p->dic || dicBufSize != p->dicBufSize)\n  {\n    LzmaDec_FreeDict(p, alloc);\n    p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize);\n    if (!p->dic)\n    {\n      LzmaDec_FreeProbs(p, alloc);\n      return SZ_ERROR_MEM;\n    }\n  }\n  p->dicBufSize = dicBufSize;\n  p->prop = propNew;\n  return SZ_OK;\n}\n\nSRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\n    ELzmaStatus *status, ISzAllocPtr alloc)\n{\n  CLzmaDec p;\n  SRes res;\n  SizeT outSize = *destLen, inSize = *srcLen;\n  *destLen = *srcLen = 0;\n  *status = LZMA_STATUS_NOT_SPECIFIED;\n  if (inSize < RC_INIT_SIZE)\n    return SZ_ERROR_INPUT_EOF;\n  LzmaDec_CONSTRUCT(&p)\n  RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc))\n  p.dic = dest;\n  p.dicBufSize = outSize;\n  LzmaDec_Init(&p);\n  *srcLen = inSize;\n  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);\n  *destLen = p.dicPos;\n  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\n    res = SZ_ERROR_INPUT_EOF;\n  LzmaDec_FreeProbs(&p, alloc);\n  return res;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzmaDec.h",
    "content": "﻿/* LzmaDec.h -- LZMA Decoder\n2023-04-02 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZMA_DEC_H\n#define ZIP7_INC_LZMA_DEC_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n/* #define Z7_LZMA_PROB32 */\n/* Z7_LZMA_PROB32 can increase the speed on some CPUs,\n   but memory usage for CLzmaDec::probs will be doubled in that case */\n\ntypedef\n#ifdef Z7_LZMA_PROB32\n  UInt32\n#else\n  UInt16\n#endif\n  CLzmaProb;\n\n\n/* ---------- LZMA Properties ---------- */\n\n#define LZMA_PROPS_SIZE 5\n\ntypedef struct\n{\n  Byte lc;\n  Byte lp;\n  Byte pb;\n  Byte _pad_;\n  UInt32 dicSize;\n} CLzmaProps;\n\n/* LzmaProps_Decode - decodes properties\nReturns:\n  SZ_OK\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n*/\n\nSRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);\n\n\n/* ---------- LZMA Decoder state ---------- */\n\n/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.\n   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */\n\n#define LZMA_REQUIRED_INPUT_MAX 20\n\ntypedef struct\n{\n  /* Don't change this structure. ASM code can use it. */\n  CLzmaProps prop;\n  CLzmaProb *probs;\n  CLzmaProb *probs_1664;\n  Byte *dic;\n  SizeT dicBufSize;\n  SizeT dicPos;\n  const Byte *buf;\n  UInt32 range;\n  UInt32 code;\n  UInt32 processedPos;\n  UInt32 checkDicSize;\n  UInt32 reps[4];\n  UInt32 state;\n  UInt32 remainLen;\n\n  UInt32 numProbs;\n  unsigned tempBufSize;\n  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];\n} CLzmaDec;\n\n#define LzmaDec_CONSTRUCT(p) { (p)->dic = NULL; (p)->probs = NULL; }\n#define LzmaDec_Construct(p) LzmaDec_CONSTRUCT(p)\n\nvoid LzmaDec_Init(CLzmaDec *p);\n\n/* There are two types of LZMA streams:\n     - Stream with end mark. That end mark adds about 6 bytes to compressed size.\n     - Stream without end mark. You must know exact uncompressed size to decompress such stream. */\n\ntypedef enum\n{\n  LZMA_FINISH_ANY,   /* finish at any point */\n  LZMA_FINISH_END    /* block must be finished at the end */\n} ELzmaFinishMode;\n\n/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!\n\n   You must use LZMA_FINISH_END, when you know that current output buffer\n   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.\n\n   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,\n   and output value of destLen will be less than output buffer size limit.\n   You can check status result also.\n\n   You can use multiple checks to test data integrity after full decompression:\n     1) Check Result and \"status\" variable.\n     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.\n     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.\n        You must use correct finish mode in that case. */\n\ntypedef enum\n{\n  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */\n  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */\n  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */\n  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */\n  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */\n} ELzmaStatus;\n\n/* ELzmaStatus is used only as output value for function call */\n\n\n/* ---------- Interfaces ---------- */\n\n/* There are 3 levels of interfaces:\n     1) Dictionary Interface\n     2) Buffer Interface\n     3) One Call Interface\n   You can select any of these interfaces, but don't mix functions from different\n   groups for same object. */\n\n\n/* There are two variants to allocate state for Dictionary Interface:\n     1) LzmaDec_Allocate / LzmaDec_Free\n     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs\n   You can use variant 2, if you set dictionary buffer manually.\n   For Buffer Interface you must always use variant 1.\n\nLzmaDec_Allocate* can return:\n  SZ_OK\n  SZ_ERROR_MEM         - Memory allocation error\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n*/\n   \nSRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);\nvoid LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);\n\nSRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);\nvoid LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);\n\n/* ---------- Dictionary Interface ---------- */\n\n/* You can use it, if you want to eliminate the overhead for data copying from\n   dictionary to some other external buffer.\n   You must work with CLzmaDec variables directly in this interface.\n\n   STEPS:\n     LzmaDec_Construct()\n     LzmaDec_Allocate()\n     for (each new stream)\n     {\n       LzmaDec_Init()\n       while (it needs more decompression)\n       {\n         LzmaDec_DecodeToDic()\n         use data from CLzmaDec::dic and update CLzmaDec::dicPos\n       }\n     }\n     LzmaDec_Free()\n*/\n\n/* LzmaDec_DecodeToDic\n   \n   The decoding to internal dictionary buffer (CLzmaDec::dic).\n   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (dicLimit).\n  LZMA_FINISH_ANY - Decode just dicLimit bytes.\n  LZMA_FINISH_END - Stream must be finished after dicLimit.\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n      LZMA_STATUS_NEEDS_MORE_INPUT\n      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\n  SZ_ERROR_DATA - Data error\n  SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure\n*/\n\nSRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\n\n/* ---------- Buffer Interface ---------- */\n\n/* It's zlib-like interface.\n   See LzmaDec_DecodeToDic description for information about STEPS and return results,\n   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need\n   to work with CLzmaDec variables manually.\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  LZMA_FINISH_ANY - Decode just destLen bytes.\n  LZMA_FINISH_END - Stream must be finished after (*destLen).\n*/\n\nSRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);\n\n\n/* ---------- One Call Interface ---------- */\n\n/* LzmaDecode\n\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  LZMA_FINISH_ANY - Decode just destLen bytes.\n  LZMA_FINISH_END - Stream must be finished after (*destLen).\n\nReturns:\n  SZ_OK\n    status:\n      LZMA_STATUS_FINISHED_WITH_MARK\n      LZMA_STATUS_NOT_FINISHED\n      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\n  SZ_ERROR_DATA - Data error\n  SZ_ERROR_MEM  - Memory allocation error\n  SZ_ERROR_UNSUPPORTED - Unsupported properties\n  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\n  SZ_ERROR_FAIL - Some unexpected error: internal error of code, memory corruption or hardware failure\n*/\n\nSRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\n    ELzmaStatus *status, ISzAllocPtr alloc);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzmaEnc.c",
    "content": "﻿/* LzmaEnc.c -- LZMA Encoder\nIgor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n/* #define SHOW_STAT */\n/* #define SHOW_STAT2 */\n\n#if defined(SHOW_STAT) || defined(SHOW_STAT2)\n#include <stdio.h>\n#endif\n\n#include \"CpuArch.h\"\n#include \"LzmaEnc.h\"\n\n#include \"LzFind.h\"\n#ifndef Z7_ST\n#include \"LzFindMt.h\"\n#endif\n\n/* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */\n\nSRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p, ISeqInStreamPtr inStream, UInt32 keepWindowSize,\n    ISzAllocPtr alloc, ISzAllocPtr allocBig);\nSRes LzmaEnc_MemPrepare(CLzmaEncHandle p, const Byte *src, SizeT srcLen,\n    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);\nSRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,\n    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);\nconst Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p);\nvoid LzmaEnc_Finish(CLzmaEncHandle p);\nvoid LzmaEnc_SaveState(CLzmaEncHandle p);\nvoid LzmaEnc_RestoreState(CLzmaEncHandle p);\n\n#ifdef SHOW_STAT\nstatic unsigned g_STAT_OFFSET = 0;\n#endif\n\n/* for good normalization speed we still reserve 256 MB before 4 GB range */\n#define kLzmaMaxHistorySize ((UInt32)15 << 28)\n\n// #define kNumTopBits 24\n#define kTopValue ((UInt32)1 << 24)\n\n#define kNumBitModelTotalBits 11\n#define kBitModelTotal (1 << kNumBitModelTotalBits)\n#define kNumMoveBits 5\n#define kProbInitValue (kBitModelTotal >> 1)\n\n#define kNumMoveReducingBits 4\n#define kNumBitPriceShiftBits 4\n// #define kBitPrice (1 << kNumBitPriceShiftBits)\n\n#define REP_LEN_COUNT 64\n\nvoid LzmaEncProps_Init(CLzmaEncProps *p)\n{\n  p->level = 5;\n  p->dictSize = p->mc = 0;\n  p->reduceSize = (UInt64)(Int64)-1;\n  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;\n  p->numHashOutBits = 0;\n  p->writeEndMark = 0;\n  p->affinityGroup = -1;\n  p->affinity = 0;\n  p->affinityInGroup = 0;\n}\n\nvoid LzmaEncProps_Normalize(CLzmaEncProps *p)\n{\n  int level = p->level;\n  if (level < 0) level = 5;\n  p->level = level;\n  \n  if (p->dictSize == 0)\n    p->dictSize = (unsigned)level <= 4 ?\n        (UInt32)1 << (level * 2 + 16) :\n        (unsigned)level <= sizeof(size_t) / 2 + 4 ?\n          (UInt32)1 << (level + 20) :\n          (UInt32)1 << (sizeof(size_t) / 2 + 24);\n\n  if (p->dictSize > p->reduceSize)\n  {\n    UInt32 v = (UInt32)p->reduceSize;\n    const UInt32 kReduceMin = ((UInt32)1 << 12);\n    if (v < kReduceMin)\n      v = kReduceMin;\n    if (p->dictSize > v)\n      p->dictSize = v;\n  }\n\n  if (p->lc < 0) p->lc = 3;\n  if (p->lp < 0) p->lp = 0;\n  if (p->pb < 0) p->pb = 2;\n\n  if (p->algo < 0) p->algo = (unsigned)level < 5 ? 0 : 1;\n  if (p->fb < 0) p->fb = (unsigned)level < 7 ? 32 : 64;\n  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);\n  if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5);\n  if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1);\n  \n  if (p->numThreads < 0)\n    p->numThreads =\n      #ifndef Z7_ST\n      ((p->btMode && p->algo) ? 2 : 1);\n      #else\n      1;\n      #endif\n}\n\nUInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)\n{\n  CLzmaEncProps props = *props2;\n  LzmaEncProps_Normalize(&props);\n  return props.dictSize;\n}\n\n\n/*\nx86/x64:\n\nBSR:\n  IF (SRC == 0) ZF = 1, DEST is undefined;\n                  AMD : DEST is unchanged;\n  IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit\n  BSR is slow in some processors\n\nLZCNT:\n  IF (SRC  == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64)\n  IF (SRC  != 0) CF = 0, DEST = num_lead_zero_bits\n  IF (DEST == 0) ZF = 1;\n\nLZCNT works only in new processors starting from Haswell.\nif LZCNT is not supported by processor, then it's executed as BSR.\nLZCNT can be faster than BSR, if supported.\n*/\n\n// #define LZMA_LOG_BSR\n\n#if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */\n\n  #if (defined(__clang__) && (__clang_major__ >= 6)) \\\n      || (defined(__GNUC__) && (__GNUC__ >= 6))\n      #define LZMA_LOG_BSR\n  #elif defined(_MSC_VER) && (_MSC_VER >= 1300)\n    // #if defined(MY_CPU_ARM_OR_ARM64)\n      #define LZMA_LOG_BSR\n    // #endif\n  #endif\n#endif\n\n// #include <intrin.h>\n\n#ifdef LZMA_LOG_BSR\n\n#if defined(__clang__) \\\n    || defined(__GNUC__)\n\n/*\n  C code:                  : (30 - __builtin_clz(x))\n    gcc9/gcc10 for x64 /x86  : 30 - (bsr(x) xor 31)\n    clang10 for x64          : 31 + (bsr(x) xor -32)\n*/\n\n  #define MY_clz(x)  ((unsigned)__builtin_clz(x))\n  // __lzcnt32\n  // __builtin_ia32_lzcnt_u32\n\n#else  // #if defined(_MSC_VER)\n\n  #ifdef MY_CPU_ARM_OR_ARM64\n\n    #define MY_clz  _CountLeadingZeros\n\n  #else // if defined(MY_CPU_X86_OR_AMD64)\n\n    // #define MY_clz  __lzcnt  // we can use lzcnt (unsupported by old CPU)\n    // _BitScanReverse code is not optimal for some MSVC compilers\n    #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \\\n      res = (zz + zz) + (pos >> zz); }\n\n  #endif // MY_CPU_X86_OR_AMD64\n\n#endif // _MSC_VER\n\n\n#ifndef BSR2_RET\n\n    #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \\\n      res = (zz + zz) + (pos >> zz); }\n\n#endif\n\n\nunsigned GetPosSlot1(UInt32 pos);\nunsigned GetPosSlot1(UInt32 pos)\n{\n  unsigned res;\n  BSR2_RET(pos, res)\n  return res;\n}\n#define GetPosSlot2(pos, res) { BSR2_RET(pos, res) }\n#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res) }\n\n\n#else // ! LZMA_LOG_BSR\n\n#define kNumLogBits (11 + sizeof(size_t) / 8 * 3)\n\n#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)\n\nstatic void LzmaEnc_FastPosInit(Byte *g_FastPos)\n{\n  unsigned slot;\n  g_FastPos[0] = 0;\n  g_FastPos[1] = 1;\n  g_FastPos += 2;\n  \n  for (slot = 2; slot < kNumLogBits * 2; slot++)\n  {\n    size_t k = ((size_t)1 << ((slot >> 1) - 1));\n    size_t j;\n    for (j = 0; j < k; j++)\n      g_FastPos[j] = (Byte)slot;\n    g_FastPos += k;\n  }\n}\n\n/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */\n/*\n#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \\\n  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \\\n  res = p->g_FastPos[pos >> zz] + (zz * 2); }\n*/\n\n/*\n#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \\\n  (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \\\n  res = p->g_FastPos[pos >> zz] + (zz * 2); }\n*/\n\n#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \\\n  res = p->g_FastPos[pos >> zz] + (zz * 2); }\n\n/*\n#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \\\n  p->g_FastPos[pos >> 6] + 12 : \\\n  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }\n*/\n\n#define GetPosSlot1(pos) p->g_FastPos[pos]\n#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }\n#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }\n\n#endif // LZMA_LOG_BSR\n\n\n#define LZMA_NUM_REPS 4\n\ntypedef UInt16 CState;\ntypedef UInt16 CExtra;\n\ntypedef struct\n{\n  UInt32 price;\n  CState state;\n  CExtra extra;\n      // 0   : normal\n      // 1   : LIT : MATCH\n      // > 1 : MATCH (extra-1) : LIT : REP0 (len)\n  UInt32 len;\n  UInt32 dist;\n  UInt32 reps[LZMA_NUM_REPS];\n} COptimal;\n\n\n// 18.06\n#define kNumOpts (1 << 11)\n#define kPackReserve (kNumOpts * 8)\n// #define kNumOpts (1 << 12)\n// #define kPackReserve (1 + kNumOpts * 2)\n\n#define kNumLenToPosStates 4\n#define kNumPosSlotBits 6\n// #define kDicLogSizeMin 0\n#define kDicLogSizeMax 32\n#define kDistTableSizeMax (kDicLogSizeMax * 2)\n\n#define kNumAlignBits 4\n#define kAlignTableSize (1 << kNumAlignBits)\n#define kAlignMask (kAlignTableSize - 1)\n\n#define kStartPosModelIndex 4\n#define kEndPosModelIndex 14\n#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\n\ntypedef\n#ifdef Z7_LZMA_PROB32\n  UInt32\n#else\n  UInt16\n#endif\n  CLzmaProb;\n\n#define LZMA_PB_MAX 4\n#define LZMA_LC_MAX 8\n#define LZMA_LP_MAX 4\n\n#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)\n\n#define kLenNumLowBits 3\n#define kLenNumLowSymbols (1 << kLenNumLowBits)\n#define kLenNumHighBits 8\n#define kLenNumHighSymbols (1 << kLenNumHighBits)\n#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)\n\n#define LZMA_MATCH_LEN_MIN 2\n#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)\n\n#define kNumStates 12\n\n\ntypedef struct\n{\n  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];\n  CLzmaProb high[kLenNumHighSymbols];\n} CLenEnc;\n\n\ntypedef struct\n{\n  unsigned tableSize;\n  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];\n  // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2];\n  // UInt32 prices2[kLenNumSymbolsTotal];\n} CLenPriceEnc;\n\n#define GET_PRICE_LEN(p, posState, len) \\\n    ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN])\n\n/*\n#define GET_PRICE_LEN(p, posState, len) \\\n    ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9)))\n*/\n\ntypedef struct\n{\n  UInt32 range;\n  unsigned cache;\n  UInt64 low;\n  UInt64 cacheSize;\n  Byte *buf;\n  Byte *bufLim;\n  Byte *bufBase;\n  ISeqOutStreamPtr outStream;\n  UInt64 processed;\n  SRes res;\n} CRangeEnc;\n\n\ntypedef struct\n{\n  CLzmaProb *litProbs;\n\n  unsigned state;\n  UInt32 reps[LZMA_NUM_REPS];\n\n  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\n  CLzmaProb isRep[kNumStates];\n  CLzmaProb isRepG0[kNumStates];\n  CLzmaProb isRepG1[kNumStates];\n  CLzmaProb isRepG2[kNumStates];\n  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\n  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\n\n  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\n  CLzmaProb posEncoders[kNumFullDistances];\n  \n  CLenEnc lenProbs;\n  CLenEnc repLenProbs;\n\n} CSaveState;\n\n\ntypedef UInt32 CProbPrice;\n\n\nstruct CLzmaEnc\n{\n  void *matchFinderObj;\n  IMatchFinder2 matchFinder;\n\n  unsigned optCur;\n  unsigned optEnd;\n\n  unsigned longestMatchLen;\n  unsigned numPairs;\n  UInt32 numAvail;\n\n  unsigned state;\n  unsigned numFastBytes;\n  unsigned additionalOffset;\n  UInt32 reps[LZMA_NUM_REPS];\n  unsigned lpMask, pbMask;\n  CLzmaProb *litProbs;\n  CRangeEnc rc;\n\n  UInt32 backRes;\n\n  unsigned lc, lp, pb;\n  unsigned lclp;\n\n  BoolInt fastMode;\n  BoolInt writeEndMark;\n  BoolInt finished;\n  BoolInt multiThread;\n  BoolInt needInit;\n  // BoolInt _maxMode;\n\n  UInt64 nowPos64;\n  \n  unsigned matchPriceCount;\n  // unsigned alignPriceCount;\n  int repLenEncCounter;\n\n  unsigned distTableSize;\n\n  UInt32 dictSize;\n  SRes result;\n\n  #ifndef Z7_ST\n  BoolInt mtMode;\n  // begin of CMatchFinderMt is used in LZ thread\n  CMatchFinderMt matchFinderMt;\n  // end of CMatchFinderMt is used in BT and HASH threads\n  // #else\n  // CMatchFinder matchFinderBase;\n  #endif\n  CMatchFinder matchFinderBase;\n\n  \n  // we suppose that we have 8-bytes alignment after CMatchFinder\n \n  #ifndef Z7_ST\n  Byte pad[128];\n  #endif\n  \n  // LZ thread\n  CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];\n\n  // we want {len , dist} pairs to be 8-bytes aligned in matches array\n  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2];\n\n  // we want 8-bytes alignment here\n  UInt32 alignPrices[kAlignTableSize];\n  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];\n  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];\n\n  CLzmaProb posAlignEncoder[1 << kNumAlignBits];\n  CLzmaProb isRep[kNumStates];\n  CLzmaProb isRepG0[kNumStates];\n  CLzmaProb isRepG1[kNumStates];\n  CLzmaProb isRepG2[kNumStates];\n  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];\n  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];\n  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];\n  CLzmaProb posEncoders[kNumFullDistances];\n  \n  CLenEnc lenProbs;\n  CLenEnc repLenProbs;\n\n  #ifndef LZMA_LOG_BSR\n  Byte g_FastPos[1 << kNumLogBits];\n  #endif\n\n  CLenPriceEnc lenEnc;\n  CLenPriceEnc repLenEnc;\n\n  COptimal opt[kNumOpts];\n\n  CSaveState saveState;\n\n  // BoolInt mf_Failure;\n  #ifndef Z7_ST\n  Byte pad2[128];\n  #endif\n};\n\n\n#define MFB (p->matchFinderBase)\n/*\n#ifndef Z7_ST\n#define MFB (p->matchFinderMt.MatchFinder)\n#endif\n*/\n\n// #define GET_CLzmaEnc_p  CLzmaEnc *p = (CLzmaEnc*)(void *)p;\n// #define GET_const_CLzmaEnc_p  const CLzmaEnc *p = (const CLzmaEnc*)(const void *)p;\n\n#define COPY_ARR(dest, src, arr)  memcpy((dest)->arr, (src)->arr, sizeof((src)->arr));\n\n#define COPY_LZMA_ENC_STATE(d, s, p)  \\\n  (d)->state = (s)->state;  \\\n  COPY_ARR(d, s, reps)  \\\n  COPY_ARR(d, s, posAlignEncoder)  \\\n  COPY_ARR(d, s, isRep)  \\\n  COPY_ARR(d, s, isRepG0)  \\\n  COPY_ARR(d, s, isRepG1)  \\\n  COPY_ARR(d, s, isRepG2)  \\\n  COPY_ARR(d, s, isMatch)  \\\n  COPY_ARR(d, s, isRep0Long)  \\\n  COPY_ARR(d, s, posSlotEncoder)  \\\n  COPY_ARR(d, s, posEncoders)  \\\n  (d)->lenProbs = (s)->lenProbs;  \\\n  (d)->repLenProbs = (s)->repLenProbs;  \\\n  memcpy((d)->litProbs, (s)->litProbs, ((size_t)0x300 * sizeof(CLzmaProb)) << (p)->lclp);\n\nvoid LzmaEnc_SaveState(CLzmaEncHandle p)\n{\n  // GET_CLzmaEnc_p\n  CSaveState *v = &p->saveState;\n  COPY_LZMA_ENC_STATE(v, p, p)\n}\n\nvoid LzmaEnc_RestoreState(CLzmaEncHandle p)\n{\n  // GET_CLzmaEnc_p\n  const CSaveState *v = &p->saveState;\n  COPY_LZMA_ENC_STATE(p, v, p)\n}\n\n\nZ7_NO_INLINE\nSRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props2)\n{\n  // GET_CLzmaEnc_p\n  CLzmaEncProps props = *props2;\n  LzmaEncProps_Normalize(&props);\n\n  if (props.lc > LZMA_LC_MAX\n      || props.lp > LZMA_LP_MAX\n      || props.pb > LZMA_PB_MAX)\n    return SZ_ERROR_PARAM;\n\n\n  if (props.dictSize > kLzmaMaxHistorySize)\n    props.dictSize = kLzmaMaxHistorySize;\n\n  #ifndef LZMA_LOG_BSR\n  {\n    const UInt64 dict64 = props.dictSize;\n    if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress))\n      return SZ_ERROR_PARAM;\n  }\n  #endif\n\n  p->dictSize = props.dictSize;\n  {\n    unsigned fb = (unsigned)props.fb;\n    if (fb < 5)\n      fb = 5;\n    if (fb > LZMA_MATCH_LEN_MAX)\n      fb = LZMA_MATCH_LEN_MAX;\n    p->numFastBytes = fb;\n  }\n  p->lc = (unsigned)props.lc;\n  p->lp = (unsigned)props.lp;\n  p->pb = (unsigned)props.pb;\n  p->fastMode = (props.algo == 0);\n  // p->_maxMode = True;\n  MFB.btMode = (Byte)(props.btMode ? 1 : 0);\n  // MFB.btMode = (Byte)(props.btMode);\n  {\n    unsigned numHashBytes = 4;\n    if (props.btMode)\n    {\n           if (props.numHashBytes <  2) numHashBytes = 2;\n      else if (props.numHashBytes <  4) numHashBytes = (unsigned)props.numHashBytes;\n    }\n    if (props.numHashBytes >= 5) numHashBytes = 5;\n\n    MFB.numHashBytes = numHashBytes;\n    // MFB.numHashBytes_Min = 2;\n    MFB.numHashOutBits = (Byte)props.numHashOutBits;\n  }\n\n  MFB.cutValue = props.mc;\n\n  p->writeEndMark = (BoolInt)props.writeEndMark;\n\n  #ifndef Z7_ST\n  /*\n  if (newMultiThread != _multiThread)\n  {\n    ReleaseMatchFinder();\n    _multiThread = newMultiThread;\n  }\n  */\n  p->multiThread = (props.numThreads > 1);\n  p->matchFinderMt.btSync.affinity =\n  p->matchFinderMt.hashSync.affinity = props.affinity;\n  p->matchFinderMt.btSync.affinityGroup =\n  p->matchFinderMt.hashSync.affinityGroup = props.affinityGroup;\n  p->matchFinderMt.btSync.affinityInGroup =\n  p->matchFinderMt.hashSync.affinityInGroup = props.affinityInGroup;\n  #endif\n\n  return SZ_OK;\n}\n\n\nvoid LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize)\n{\n  // GET_CLzmaEnc_p\n  MFB.expectedDataSize = expectedDataSiize;\n}\n\n\n#define kState_Start 0\n#define kState_LitAfterMatch 4\n#define kState_LitAfterRep   5\n#define kState_MatchAfterLit 7\n#define kState_RepAfterLit   8\n\nstatic const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};\nstatic const Byte kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\nstatic const Byte kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\nstatic const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};\n\n#define IsLitState(s) ((s) < 7)\n#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)\n#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)\n\n#define kInfinityPrice (1 << 30)\n\nstatic void RangeEnc_Construct(CRangeEnc *p)\n{\n  p->outStream = NULL;\n  p->bufBase = NULL;\n}\n\n#define RangeEnc_GetProcessed(p)       (        (p)->processed + (size_t)((p)->buf - (p)->bufBase) +         (p)->cacheSize)\n#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)\n\n#define RC_BUF_SIZE (1 << 16)\n\nstatic int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)\n{\n  if (!p->bufBase)\n  {\n    p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);\n    if (!p->bufBase)\n      return 0;\n    p->bufLim = p->bufBase + RC_BUF_SIZE;\n  }\n  return 1;\n}\n\nstatic void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->bufBase);\n  p->bufBase = NULL;\n}\n\nstatic void RangeEnc_Init(CRangeEnc *p)\n{\n  p->range = 0xFFFFFFFF;\n  p->cache = 0;\n  p->low = 0;\n  p->cacheSize = 0;\n\n  p->buf = p->bufBase;\n\n  p->processed = 0;\n  p->res = SZ_OK;\n}\n\nZ7_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)\n{\n  const size_t num = (size_t)(p->buf - p->bufBase);\n  if (p->res == SZ_OK)\n  {\n    if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))\n      p->res = SZ_ERROR_WRITE;\n  }\n  p->processed += num;\n  p->buf = p->bufBase;\n}\n\nZ7_NO_INLINE static void Z7_FASTCALL RangeEnc_ShiftLow(CRangeEnc *p)\n{\n  UInt32 low = (UInt32)p->low;\n  unsigned high = (unsigned)(p->low >> 32);\n  p->low = (UInt32)(low << 8);\n  if (low < (UInt32)0xFF000000 || high != 0)\n  {\n    {\n      Byte *buf = p->buf;\n      *buf++ = (Byte)(p->cache + high);\n      p->cache = (unsigned)(low >> 24);\n      p->buf = buf;\n      if (buf == p->bufLim)\n        RangeEnc_FlushStream(p);\n      if (p->cacheSize == 0)\n        return;\n    }\n    high += 0xFF;\n    for (;;)\n    {\n      Byte *buf = p->buf;\n      *buf++ = (Byte)(high);\n      p->buf = buf;\n      if (buf == p->bufLim)\n        RangeEnc_FlushStream(p);\n      if (--p->cacheSize == 0)\n        return;\n    }\n  }\n  p->cacheSize++;\n}\n\nstatic void RangeEnc_FlushData(CRangeEnc *p)\n{\n  int i;\n  for (i = 0; i < 5; i++)\n    RangeEnc_ShiftLow(p);\n}\n\n#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }\n\n#define RC_BIT_PRE(p, prob) \\\n  ttt = *(prob); \\\n  newBound = (range >> kNumBitModelTotalBits) * ttt;\n\n// #define Z7_LZMA_ENC_USE_BRANCH\n\n#ifdef Z7_LZMA_ENC_USE_BRANCH\n\n#define RC_BIT(p, prob, bit) { \\\n  RC_BIT_PRE(p, prob) \\\n  if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \\\n  else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \\\n  *(prob) = (CLzmaProb)ttt; \\\n  RC_NORM(p) \\\n  }\n\n#else\n\n#define RC_BIT(p, prob, bit) { \\\n  UInt32 mask; \\\n  RC_BIT_PRE(p, prob) \\\n  mask = 0 - (UInt32)bit; \\\n  range &= mask; \\\n  mask &= newBound; \\\n  range -= mask; \\\n  (p)->low += mask; \\\n  mask = (UInt32)bit - 1; \\\n  range += newBound & mask; \\\n  mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \\\n  mask += ((1 << kNumMoveBits) - 1); \\\n  ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \\\n  *(prob) = (CLzmaProb)ttt; \\\n  RC_NORM(p) \\\n  }\n\n#endif\n\n\n\n\n#define RC_BIT_0_BASE(p, prob) \\\n  range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\n\n#define RC_BIT_1_BASE(p, prob) \\\n  range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \\\n\n#define RC_BIT_0(p, prob) \\\n  RC_BIT_0_BASE(p, prob) \\\n  RC_NORM(p)\n\n#define RC_BIT_1(p, prob) \\\n  RC_BIT_1_BASE(p, prob) \\\n  RC_NORM(p)\n\nstatic void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)\n{\n  UInt32 range, ttt, newBound;\n  range = p->range;\n  RC_BIT_PRE(p, prob)\n  RC_BIT_0(p, prob)\n  p->range = range;\n}\n\nstatic void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym)\n{\n  UInt32 range = p->range;\n  sym |= 0x100;\n  do\n  {\n    UInt32 ttt, newBound;\n    // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1);\n    CLzmaProb *prob = probs + (sym >> 8);\n    UInt32 bit = (sym >> 7) & 1;\n    sym <<= 1;\n    RC_BIT(p, prob, bit)\n  }\n  while (sym < 0x10000);\n  p->range = range;\n}\n\nstatic void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte)\n{\n  UInt32 range = p->range;\n  UInt32 offs = 0x100;\n  sym |= 0x100;\n  do\n  {\n    UInt32 ttt, newBound;\n    CLzmaProb *prob;\n    UInt32 bit;\n    matchByte <<= 1;\n    // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1);\n    prob = probs + (offs + (matchByte & offs) + (sym >> 8));\n    bit = (sym >> 7) & 1;\n    sym <<= 1;\n    offs &= ~(matchByte ^ sym);\n    RC_BIT(p, prob, bit)\n  }\n  while (sym < 0x10000);\n  p->range = range;\n}\n\n\n\nstatic void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)\n{\n  UInt32 i;\n  for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)\n  {\n    const unsigned kCyclesBits = kNumBitPriceShiftBits;\n    UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));\n    unsigned bitCount = 0;\n    unsigned j;\n    for (j = 0; j < kCyclesBits; j++)\n    {\n      w = w * w;\n      bitCount <<= 1;\n      while (w >= ((UInt32)1 << 16))\n      {\n        w >>= 1;\n        bitCount++;\n      }\n    }\n    ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);\n    // printf(\"\\n%3d: %5d\", i, ProbPrices[i]);\n  }\n}\n\n\n#define GET_PRICE(prob, bit) \\\n  p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]\n\n#define GET_PRICEa(prob, bit) \\\n     ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]\n\n#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]\n#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\n\n#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]\n#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]\n\n\nstatic UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices)\n{\n  UInt32 price = 0;\n  sym |= 0x100;\n  do\n  {\n    unsigned bit = sym & 1;\n    sym >>= 1;\n    price += GET_PRICEa(probs[sym], bit);\n  }\n  while (sym >= 2);\n  return price;\n}\n\n\nstatic UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices)\n{\n  UInt32 price = 0;\n  UInt32 offs = 0x100;\n  sym |= 0x100;\n  do\n  {\n    matchByte <<= 1;\n    price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1);\n    sym <<= 1;\n    offs &= ~(matchByte ^ sym);\n  }\n  while (sym < 0x10000);\n  return price;\n}\n\n\nstatic void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym)\n{\n  UInt32 range = rc->range;\n  unsigned m = 1;\n  do\n  {\n    UInt32 ttt, newBound;\n    unsigned bit = sym & 1;\n    // RangeEnc_EncodeBit(rc, probs + m, bit);\n    sym >>= 1;\n    RC_BIT(rc, probs + m, bit)\n    m = (m << 1) | bit;\n  }\n  while (--numBits);\n  rc->range = range;\n}\n\n\n\nstatic void LenEnc_Init(CLenEnc *p)\n{\n  unsigned i;\n  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)\n    p->low[i] = kProbInitValue;\n  for (i = 0; i < kLenNumHighSymbols; i++)\n    p->high[i] = kProbInitValue;\n}\n\nstatic void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState)\n{\n  UInt32 range, ttt, newBound;\n  CLzmaProb *probs = p->low;\n  range = rc->range;\n  RC_BIT_PRE(rc, probs)\n  if (sym >= kLenNumLowSymbols)\n  {\n    RC_BIT_1(rc, probs)\n    probs += kLenNumLowSymbols;\n    RC_BIT_PRE(rc, probs)\n    if (sym >= kLenNumLowSymbols * 2)\n    {\n      RC_BIT_1(rc, probs)\n      rc->range = range;\n      // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2);\n      LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2);\n      return;\n    }\n    sym -= kLenNumLowSymbols;\n  }\n\n  // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym);\n  {\n    unsigned m;\n    unsigned bit;\n    RC_BIT_0(rc, probs)\n    probs += (posState << (1 + kLenNumLowBits));\n    bit = (sym >> 2)    ; RC_BIT(rc, probs + 1, bit)  m = (1 << 1) + bit;\n    bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit)  m = (m << 1) + bit;\n    bit =  sym       & 1; RC_BIT(rc, probs + m, bit)\n    rc->range = range;\n  }\n}\n\nstatic void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)\n{\n  unsigned i;\n  for (i = 0; i < 8; i += 2)\n  {\n    UInt32 price = startPrice;\n    UInt32 prob;\n    price += GET_PRICEa(probs[1           ], (i >> 2));\n    price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);\n    prob = probs[4 + (i >> 1)];\n    prices[i    ] = price + GET_PRICEa_0(prob);\n    prices[i + 1] = price + GET_PRICEa_1(prob);\n  }\n}\n\n\nZ7_NO_INLINE static void Z7_FASTCALL LenPriceEnc_UpdateTables(\n    CLenPriceEnc *p,\n    unsigned numPosStates,\n    const CLenEnc *enc,\n    const CProbPrice *ProbPrices)\n{\n  UInt32 b;\n \n  {\n    unsigned prob = enc->low[0];\n    UInt32 a, c;\n    unsigned posState;\n    b = GET_PRICEa_1(prob);\n    a = GET_PRICEa_0(prob);\n    c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);\n    for (posState = 0; posState < numPosStates; posState++)\n    {\n      UInt32 *prices = p->prices[posState];\n      const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));\n      SetPrices_3(probs, a, prices, ProbPrices);\n      SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices);\n    }\n  }\n\n  /*\n  {\n    unsigned i;\n    UInt32 b;\n    a = GET_PRICEa_0(enc->low[0]);\n    for (i = 0; i < kLenNumLowSymbols; i++)\n      p->prices2[i] = a;\n    a = GET_PRICEa_1(enc->low[0]);\n    b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);\n    for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++)\n      p->prices2[i] = b;\n    a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);\n  }\n  */\n \n  // p->counter = numSymbols;\n  // p->counter = 64;\n\n  {\n    unsigned i = p->tableSize;\n    \n    if (i > kLenNumLowSymbols * 2)\n    {\n      const CLzmaProb *probs = enc->high;\n      UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2;\n      i -= kLenNumLowSymbols * 2 - 1;\n      i >>= 1;\n      b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);\n      do\n      {\n        /*\n        p->prices2[i] = a +\n        // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);\n        LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices);\n        */\n        // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices);\n        unsigned sym = --i + (1 << (kLenNumHighBits - 1));\n        UInt32 price = b;\n        do\n        {\n          const unsigned bit = sym & 1;\n          sym >>= 1;\n          price += GET_PRICEa(probs[sym], bit);\n        }\n        while (sym >= 2);\n\n        {\n          const unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];\n          prices[(size_t)i * 2    ] = price + GET_PRICEa_0(prob);\n          prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);\n        }\n      }\n      while (i);\n\n      {\n        unsigned posState;\n        const size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);\n        for (posState = 1; posState < numPosStates; posState++)\n          memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);\n      }\n    }\n  }\n}\n\n/*\n  #ifdef SHOW_STAT\n  g_STAT_OFFSET += num;\n  printf(\"\\n MovePos %u\", num);\n  #endif\n*/\n  \n#define MOVE_POS(p, num) { \\\n    p->additionalOffset += (num); \\\n    p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }\n\n\nstatic unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)\n{\n  unsigned numPairs;\n  \n  p->additionalOffset++;\n  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\n  {\n    const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);\n    // if (!d) { p->mf_Failure = True; *numPairsRes = 0;  return 0; }\n    numPairs = (unsigned)(d - p->matches);\n  }\n  *numPairsRes = numPairs;\n  \n  #ifdef SHOW_STAT\n  printf(\"\\n i = %u numPairs = %u    \", g_STAT_OFFSET, numPairs / 2);\n  g_STAT_OFFSET++;\n  {\n    unsigned i;\n    for (i = 0; i < numPairs; i += 2)\n      printf(\"%2u %6u   | \", p->matches[i], p->matches[i + 1]);\n  }\n  #endif\n  \n  if (numPairs == 0)\n    return 0;\n  {\n    const unsigned len = p->matches[(size_t)numPairs - 2];\n    if (len != p->numFastBytes)\n      return len;\n    {\n      UInt32 numAvail = p->numAvail;\n      if (numAvail > LZMA_MATCH_LEN_MAX)\n        numAvail = LZMA_MATCH_LEN_MAX;\n      {\n        const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n        const Byte *p2 = p1 + len;\n        const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1];\n        const Byte *lim = p1 + numAvail;\n        for (; p2 != lim && *p2 == p2[dif]; p2++)\n        {}\n        return (unsigned)(p2 - p1);\n      }\n    }\n  }\n}\n\n#define MARK_LIT ((UInt32)(Int32)-1)\n\n#define MakeAs_Lit(p)       { (p)->dist = MARK_LIT; (p)->extra = 0; }\n#define MakeAs_ShortRep(p)  { (p)->dist = 0; (p)->extra = 0; }\n#define IsShortRep(p)       ((p)->dist == 0)\n\n\n#define GetPrice_ShortRep(p, state, posState) \\\n  ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))\n\n#define GetPrice_Rep_0(p, state, posState) ( \\\n    GET_PRICE_1(p->isMatch[state][posState]) \\\n  + GET_PRICE_1(p->isRep0Long[state][posState])) \\\n  + GET_PRICE_1(p->isRep[state]) \\\n  + GET_PRICE_0(p->isRepG0[state])\n  \nZ7_FORCE_INLINE\nstatic UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)\n{\n  UInt32 price;\n  UInt32 prob = p->isRepG0[state];\n  if (repIndex == 0)\n  {\n    price = GET_PRICE_0(prob);\n    price += GET_PRICE_1(p->isRep0Long[state][posState]);\n  }\n  else\n  {\n    price = GET_PRICE_1(prob);\n    prob = p->isRepG1[state];\n    if (repIndex == 1)\n      price += GET_PRICE_0(prob);\n    else\n    {\n      price += GET_PRICE_1(prob);\n      price += GET_PRICE(p->isRepG2[state], repIndex - 2);\n    }\n  }\n  return price;\n}\n\n\nstatic unsigned Backward(CLzmaEnc *p, unsigned cur)\n{\n  unsigned wr = cur + 1;\n  p->optEnd = wr;\n\n  for (;;)\n  {\n    UInt32 dist = p->opt[cur].dist;\n    unsigned len = (unsigned)p->opt[cur].len;\n    unsigned extra = (unsigned)p->opt[cur].extra;\n    cur -= len;\n\n    if (extra)\n    {\n      wr--;\n      p->opt[wr].len = (UInt32)len;\n      cur -= extra;\n      len = extra;\n      if (extra == 1)\n      {\n        p->opt[wr].dist = dist;\n        dist = MARK_LIT;\n      }\n      else\n      {\n        p->opt[wr].dist = 0;\n        len--;\n        wr--;\n        p->opt[wr].dist = MARK_LIT;\n        p->opt[wr].len = 1;\n      }\n    }\n\n    if (cur == 0)\n    {\n      p->backRes = dist;\n      p->optCur = wr;\n      return len;\n    }\n    \n    wr--;\n    p->opt[wr].dist = dist;\n    p->opt[wr].len = (UInt32)len;\n  }\n}\n\n\n\n#define LIT_PROBS(pos, prevByte) \\\n  (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))\n\n\nstatic unsigned GetOptimum(CLzmaEnc *p, UInt32 position)\n{\n  unsigned last, cur;\n  UInt32 reps[LZMA_NUM_REPS];\n  unsigned repLens[LZMA_NUM_REPS];\n  UInt32 *matches;\n\n  {\n    UInt32 numAvail;\n    unsigned numPairs, mainLen, repMaxIndex, i, posState;\n    UInt32 matchPrice, repMatchPrice;\n    const Byte *data;\n    Byte curByte, matchByte;\n    \n    p->optCur = p->optEnd = 0;\n    \n    if (p->additionalOffset == 0)\n      mainLen = ReadMatchDistances(p, &numPairs);\n    else\n    {\n      mainLen = p->longestMatchLen;\n      numPairs = p->numPairs;\n    }\n    \n    numAvail = p->numAvail;\n    if (numAvail < 2)\n    {\n      p->backRes = MARK_LIT;\n      return 1;\n    }\n    if (numAvail > LZMA_MATCH_LEN_MAX)\n      numAvail = LZMA_MATCH_LEN_MAX;\n    \n    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n    repMaxIndex = 0;\n    \n    for (i = 0; i < LZMA_NUM_REPS; i++)\n    {\n      unsigned len;\n      const Byte *data2;\n      reps[i] = p->reps[i];\n      data2 = data - reps[i];\n      if (data[0] != data2[0] || data[1] != data2[1])\n      {\n        repLens[i] = 0;\n        continue;\n      }\n      for (len = 2; len < numAvail && data[len] == data2[len]; len++)\n      {}\n      repLens[i] = len;\n      if (len > repLens[repMaxIndex])\n        repMaxIndex = i;\n      if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization\n        break;\n    }\n    \n    if (repLens[repMaxIndex] >= p->numFastBytes)\n    {\n      unsigned len;\n      p->backRes = (UInt32)repMaxIndex;\n      len = repLens[repMaxIndex];\n      MOVE_POS(p, len - 1)\n      return len;\n    }\n    \n    matches = p->matches;\n    #define MATCHES  matches\n    // #define MATCHES  p->matches\n    \n    if (mainLen >= p->numFastBytes)\n    {\n      p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS;\n      MOVE_POS(p, mainLen - 1)\n      return mainLen;\n    }\n    \n    curByte = *data;\n    matchByte = *(data - reps[0]);\n\n    last = repLens[repMaxIndex];\n    if (last <= mainLen)\n      last = mainLen;\n    \n    if (last < 2 && curByte != matchByte)\n    {\n      p->backRes = MARK_LIT;\n      return 1;\n    }\n    \n    p->opt[0].state = (CState)p->state;\n    \n    posState = (position & p->pbMask);\n    \n    {\n      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\n      p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +\n        (!IsLitState(p->state) ?\n          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :\n          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\n    }\n\n    MakeAs_Lit(&p->opt[1])\n    \n    matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);\n    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);\n    \n    // 18.06\n    if (matchByte == curByte && repLens[0] == 0)\n    {\n      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);\n      if (shortRepPrice < p->opt[1].price)\n      {\n        p->opt[1].price = shortRepPrice;\n        MakeAs_ShortRep(&p->opt[1])\n      }\n      if (last < 2)\n      {\n        p->backRes = p->opt[1].dist;\n        return 1;\n      }\n    }\n   \n    p->opt[1].len = 1;\n    \n    p->opt[0].reps[0] = reps[0];\n    p->opt[0].reps[1] = reps[1];\n    p->opt[0].reps[2] = reps[2];\n    p->opt[0].reps[3] = reps[3];\n    \n    // ---------- REP ----------\n    \n    for (i = 0; i < LZMA_NUM_REPS; i++)\n    {\n      unsigned repLen = repLens[i];\n      UInt32 price;\n      if (repLen < 2)\n        continue;\n      price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);\n      do\n      {\n        UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen);\n        COptimal *opt = &p->opt[repLen];\n        if (price2 < opt->price)\n        {\n          opt->price = price2;\n          opt->len = (UInt32)repLen;\n          opt->dist = (UInt32)i;\n          opt->extra = 0;\n        }\n      }\n      while (--repLen >= 2);\n    }\n    \n    \n    // ---------- MATCH ----------\n    {\n      unsigned len = repLens[0] + 1;\n      if (len <= mainLen)\n      {\n        unsigned offs = 0;\n        UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);\n\n        if (len < 2)\n          len = 2;\n        else\n          while (len > MATCHES[offs])\n            offs += 2;\n    \n        for (; ; len++)\n        {\n          COptimal *opt;\n          UInt32 dist = MATCHES[(size_t)offs + 1];\n          UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);\n          unsigned lenToPosState = GetLenToPosState(len);\n       \n          if (dist < kNumFullDistances)\n            price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];\n          else\n          {\n            unsigned slot;\n            GetPosSlot2(dist, slot)\n            price += p->alignPrices[dist & kAlignMask];\n            price += p->posSlotPrices[lenToPosState][slot];\n          }\n          \n          opt = &p->opt[len];\n          \n          if (price < opt->price)\n          {\n            opt->price = price;\n            opt->len = (UInt32)len;\n            opt->dist = dist + LZMA_NUM_REPS;\n            opt->extra = 0;\n          }\n          \n          if (len == MATCHES[offs])\n          {\n            offs += 2;\n            if (offs == numPairs)\n              break;\n          }\n        }\n      }\n    }\n    \n\n    cur = 0;\n\n    #ifdef SHOW_STAT2\n    /* if (position >= 0) */\n    {\n      unsigned i;\n      printf(\"\\n pos = %4X\", position);\n      for (i = cur; i <= last; i++)\n      printf(\"\\nprice[%4X] = %u\", position - cur + i, p->opt[i].price);\n    }\n    #endif\n  }\n\n\n  \n  // ---------- Optimal Parsing ----------\n\n  for (;;)\n  {\n    unsigned numAvail;\n    UInt32 numAvailFull;\n    unsigned newLen, numPairs, prev, state, posState, startLen;\n    UInt32 litPrice, matchPrice, repMatchPrice;\n    BoolInt nextIsLit;\n    Byte curByte, matchByte;\n    const Byte *data;\n    COptimal *curOpt, *nextOpt;\n\n    if (++cur == last)\n      break;\n    \n    // 18.06\n    if (cur >= kNumOpts - 64)\n    {\n      unsigned j, best;\n      UInt32 price = p->opt[cur].price;\n      best = cur;\n      for (j = cur + 1; j <= last; j++)\n      {\n        UInt32 price2 = p->opt[j].price;\n        if (price >= price2)\n        {\n          price = price2;\n          best = j;\n        }\n      }\n      {\n        unsigned delta = best - cur;\n        if (delta != 0)\n        {\n          MOVE_POS(p, delta)\n        }\n      }\n      cur = best;\n      break;\n    }\n\n    newLen = ReadMatchDistances(p, &numPairs);\n    \n    if (newLen >= p->numFastBytes)\n    {\n      p->numPairs = numPairs;\n      p->longestMatchLen = newLen;\n      break;\n    }\n    \n    curOpt = &p->opt[cur];\n\n    position++;\n\n    // we need that check here, if skip_items in p->opt are possible\n    /*\n    if (curOpt->price >= kInfinityPrice)\n      continue;\n    */\n\n    prev = cur - curOpt->len;\n\n    if (curOpt->len == 1)\n    {\n      state = (unsigned)p->opt[prev].state;\n      if (IsShortRep(curOpt))\n        state = kShortRepNextStates[state];\n      else\n        state = kLiteralNextStates[state];\n    }\n    else\n    {\n      const COptimal *prevOpt;\n      UInt32 b0;\n      UInt32 dist = curOpt->dist;\n\n      if (curOpt->extra)\n      {\n        prev -= (unsigned)curOpt->extra;\n        state = kState_RepAfterLit;\n        if (curOpt->extra == 1)\n          state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit);\n      }\n      else\n      {\n        state = (unsigned)p->opt[prev].state;\n        if (dist < LZMA_NUM_REPS)\n          state = kRepNextStates[state];\n        else\n          state = kMatchNextStates[state];\n      }\n\n      prevOpt = &p->opt[prev];\n      b0 = prevOpt->reps[0];\n\n      if (dist < LZMA_NUM_REPS)\n      {\n        if (dist == 0)\n        {\n          reps[0] = b0;\n          reps[1] = prevOpt->reps[1];\n          reps[2] = prevOpt->reps[2];\n          reps[3] = prevOpt->reps[3];\n        }\n        else\n        {\n          reps[1] = b0;\n          b0 = prevOpt->reps[1];\n          if (dist == 1)\n          {\n            reps[0] = b0;\n            reps[2] = prevOpt->reps[2];\n            reps[3] = prevOpt->reps[3];\n          }\n          else\n          {\n            reps[2] = b0;\n            reps[0] = prevOpt->reps[dist];\n            reps[3] = prevOpt->reps[dist ^ 1];\n          }\n        }\n      }\n      else\n      {\n        reps[0] = (dist - LZMA_NUM_REPS + 1);\n        reps[1] = b0;\n        reps[2] = prevOpt->reps[1];\n        reps[3] = prevOpt->reps[2];\n      }\n    }\n    \n    curOpt->state = (CState)state;\n    curOpt->reps[0] = reps[0];\n    curOpt->reps[1] = reps[1];\n    curOpt->reps[2] = reps[2];\n    curOpt->reps[3] = reps[3];\n\n    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n    curByte = *data;\n    matchByte = *(data - reps[0]);\n\n    posState = (position & p->pbMask);\n\n    /*\n    The order of Price checks:\n       <  LIT\n       <= SHORT_REP\n       <  LIT : REP_0\n       <  REP    [ : LIT : REP_0 ]\n       <  MATCH  [ : LIT : REP_0 ]\n    */\n\n    {\n      UInt32 curPrice = curOpt->price;\n      unsigned prob = p->isMatch[state][posState];\n      matchPrice = curPrice + GET_PRICE_1(prob);\n      litPrice = curPrice + GET_PRICE_0(prob);\n    }\n\n    nextOpt = &p->opt[(size_t)cur + 1];\n    nextIsLit = False;\n\n    // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice)\n    // 18.new.06\n    if ((nextOpt->price < kInfinityPrice\n        // && !IsLitState(state)\n        && matchByte == curByte)\n        || litPrice > nextOpt->price\n        )\n      litPrice = 0;\n    else\n    {\n      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));\n      litPrice += (!IsLitState(state) ?\n          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :\n          LitEnc_GetPrice(probs, curByte, p->ProbPrices));\n      \n      if (litPrice < nextOpt->price)\n      {\n        nextOpt->price = litPrice;\n        nextOpt->len = 1;\n        MakeAs_Lit(nextOpt)\n        nextIsLit = True;\n      }\n    }\n\n    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);\n    \n    numAvailFull = p->numAvail;\n    {\n      unsigned temp = kNumOpts - 1 - cur;\n      if (numAvailFull > temp)\n        numAvailFull = (UInt32)temp;\n    }\n\n    // 18.06\n    // ---------- SHORT_REP ----------\n    if (IsLitState(state)) // 18.new\n    if (matchByte == curByte)\n    if (repMatchPrice < nextOpt->price) // 18.new\n    // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1))\n    if (\n        // nextOpt->price >= kInfinityPrice ||\n        nextOpt->len < 2   // we can check nextOpt->len, if skip items are not allowed in p->opt\n        || (nextOpt->dist != 0\n            // && nextOpt->extra <= 1 // 17.old\n            )\n        )\n    {\n      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);\n      // if (shortRepPrice <= nextOpt->price) // 17.old\n      if (shortRepPrice < nextOpt->price)  // 18.new\n      {\n        nextOpt->price = shortRepPrice;\n        nextOpt->len = 1;\n        MakeAs_ShortRep(nextOpt)\n        nextIsLit = False;\n      }\n    }\n    \n    if (numAvailFull < 2)\n      continue;\n    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);\n\n    // numAvail <= p->numFastBytes\n\n    // ---------- LIT : REP_0 ----------\n\n    if (!nextIsLit\n        && litPrice != 0 // 18.new\n        && matchByte != curByte\n        && numAvailFull > 2)\n    {\n      const Byte *data2 = data - reps[0];\n      if (data[1] == data2[1] && data[2] == data2[2])\n      {\n        unsigned len;\n        unsigned limit = p->numFastBytes + 1;\n        if (limit > numAvailFull)\n          limit = numAvailFull;\n        for (len = 3; len < limit && data[len] == data2[len]; len++)\n        {}\n        \n        {\n          unsigned state2 = kLiteralNextStates[state];\n          unsigned posState2 = (position + 1) & p->pbMask;\n          UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);\n          {\n            unsigned offset = cur + len;\n\n            if (last < offset)\n              last = offset;\n          \n            // do\n            {\n              UInt32 price2;\n              COptimal *opt;\n              len--;\n              // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);\n              price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len);\n\n              opt = &p->opt[offset];\n              // offset--;\n              if (price2 < opt->price)\n              {\n                opt->price = price2;\n                opt->len = (UInt32)len;\n                opt->dist = 0;\n                opt->extra = 1;\n              }\n            }\n            // while (len >= 3);\n          }\n        }\n      }\n    }\n    \n    startLen = 2; /* speed optimization */\n\n    {\n      // ---------- REP ----------\n      unsigned repIndex = 0; // 17.old\n      // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused\n      for (; repIndex < LZMA_NUM_REPS; repIndex++)\n      {\n        unsigned len;\n        UInt32 price;\n        const Byte *data2 = data - reps[repIndex];\n        if (data[0] != data2[0] || data[1] != data2[1])\n          continue;\n        \n        for (len = 2; len < numAvail && data[len] == data2[len]; len++)\n        {}\n        \n        // if (len < startLen) continue; // 18.new: speed optimization\n\n        {\n          unsigned offset = cur + len;\n          if (last < offset)\n            last = offset;\n        }\n        {\n          unsigned len2 = len;\n          price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);\n          do\n          {\n            UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2);\n            COptimal *opt = &p->opt[cur + len2];\n            if (price2 < opt->price)\n            {\n              opt->price = price2;\n              opt->len = (UInt32)len2;\n              opt->dist = (UInt32)repIndex;\n              opt->extra = 0;\n            }\n          }\n          while (--len2 >= 2);\n        }\n        \n        if (repIndex == 0) startLen = len + 1;  // 17.old\n        // startLen = len + 1; // 18.new\n\n        /* if (_maxMode) */\n        {\n          // ---------- REP : LIT : REP_0 ----------\n          // numFastBytes + 1 + numFastBytes\n\n          unsigned len2 = len + 1;\n          unsigned limit = len2 + p->numFastBytes;\n          if (limit > numAvailFull)\n            limit = numAvailFull;\n          \n          len2 += 2;\n          if (len2 <= limit)\n          if (data[len2 - 2] == data2[len2 - 2])\n          if (data[len2 - 1] == data2[len2 - 1])\n          {\n            unsigned state2 = kRepNextStates[state];\n            unsigned posState2 = (position + len) & p->pbMask;\n            price += GET_PRICE_LEN(&p->repLenEnc, posState, len)\n                + GET_PRICE_0(p->isMatch[state2][posState2])\n                + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),\n                    data[len], data2[len], p->ProbPrices);\n            \n            // state2 = kLiteralNextStates[state2];\n            state2 = kState_LitAfterRep;\n            posState2 = (posState2 + 1) & p->pbMask;\n\n\n            price += GetPrice_Rep_0(p, state2, posState2);\n\n          for (; len2 < limit && data[len2] == data2[len2]; len2++)\n          {}\n          \n          len2 -= len;\n          // if (len2 >= 3)\n          {\n            {\n              unsigned offset = cur + len + len2;\n\n              if (last < offset)\n                last = offset;\n              // do\n              {\n                UInt32 price2;\n                COptimal *opt;\n                len2--;\n                // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);\n                price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);\n\n                opt = &p->opt[offset];\n                // offset--;\n                if (price2 < opt->price)\n                {\n                  opt->price = price2;\n                  opt->len = (UInt32)len2;\n                  opt->extra = (CExtra)(len + 1);\n                  opt->dist = (UInt32)repIndex;\n                }\n              }\n              // while (len2 >= 3);\n            }\n          }\n          }\n        }\n      }\n    }\n\n\n    // ---------- MATCH ----------\n    /* for (unsigned len = 2; len <= newLen; len++) */\n    if (newLen > numAvail)\n    {\n      newLen = numAvail;\n      for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2);\n      MATCHES[numPairs] = (UInt32)newLen;\n      numPairs += 2;\n    }\n    \n    // startLen = 2; /* speed optimization */\n\n    if (newLen >= startLen)\n    {\n      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);\n      UInt32 dist;\n      unsigned offs, posSlot, len;\n      \n      {\n        unsigned offset = cur + newLen;\n        if (last < offset)\n          last = offset;\n      }\n\n      offs = 0;\n      while (startLen > MATCHES[offs])\n        offs += 2;\n      dist = MATCHES[(size_t)offs + 1];\n      \n      // if (dist >= kNumFullDistances)\n      GetPosSlot2(dist, posSlot)\n      \n      for (len = /*2*/ startLen; ; len++)\n      {\n        UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);\n        {\n          COptimal *opt;\n          unsigned lenNorm = len - 2;\n          lenNorm = GetLenToPosState2(lenNorm);\n          if (dist < kNumFullDistances)\n            price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)];\n          else\n            price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask];\n          \n          opt = &p->opt[cur + len];\n          if (price < opt->price)\n          {\n            opt->price = price;\n            opt->len = (UInt32)len;\n            opt->dist = dist + LZMA_NUM_REPS;\n            opt->extra = 0;\n          }\n        }\n\n        if (len == MATCHES[offs])\n        {\n          // if (p->_maxMode) {\n          // MATCH : LIT : REP_0\n\n          const Byte *data2 = data - dist - 1;\n          unsigned len2 = len + 1;\n          unsigned limit = len2 + p->numFastBytes;\n          if (limit > numAvailFull)\n            limit = numAvailFull;\n          \n          len2 += 2;\n          if (len2 <= limit)\n          if (data[len2 - 2] == data2[len2 - 2])\n          if (data[len2 - 1] == data2[len2 - 1])\n          {\n          for (; len2 < limit && data[len2] == data2[len2]; len2++)\n          {}\n          \n          len2 -= len;\n          \n          // if (len2 >= 3)\n          {\n            unsigned state2 = kMatchNextStates[state];\n            unsigned posState2 = (position + len) & p->pbMask;\n            unsigned offset;\n            price += GET_PRICE_0(p->isMatch[state2][posState2]);\n            price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),\n                    data[len], data2[len], p->ProbPrices);\n\n            // state2 = kLiteralNextStates[state2];\n            state2 = kState_LitAfterMatch;\n\n            posState2 = (posState2 + 1) & p->pbMask;\n            price += GetPrice_Rep_0(p, state2, posState2);\n\n            offset = cur + len + len2;\n\n            if (last < offset)\n              last = offset;\n            // do\n            {\n              UInt32 price2;\n              COptimal *opt;\n              len2--;\n              // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);\n              price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);\n              opt = &p->opt[offset];\n              // offset--;\n              if (price2 < opt->price)\n              {\n                opt->price = price2;\n                opt->len = (UInt32)len2;\n                opt->extra = (CExtra)(len + 1);\n                opt->dist = dist + LZMA_NUM_REPS;\n              }\n            }\n            // while (len2 >= 3);\n          }\n\n          }\n        \n          offs += 2;\n          if (offs == numPairs)\n            break;\n          dist = MATCHES[(size_t)offs + 1];\n          // if (dist >= kNumFullDistances)\n            GetPosSlot2(dist, posSlot)\n        }\n      }\n    }\n  }\n\n  do\n    p->opt[last].price = kInfinityPrice;\n  while (--last);\n\n  return Backward(p, cur);\n}\n\n\n\n#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))\n\n\n\nstatic unsigned GetOptimumFast(CLzmaEnc *p)\n{\n  UInt32 numAvail, mainDist;\n  unsigned mainLen, numPairs, repIndex, repLen, i;\n  const Byte *data;\n\n  if (p->additionalOffset == 0)\n    mainLen = ReadMatchDistances(p, &numPairs);\n  else\n  {\n    mainLen = p->longestMatchLen;\n    numPairs = p->numPairs;\n  }\n\n  numAvail = p->numAvail;\n  p->backRes = MARK_LIT;\n  if (numAvail < 2)\n    return 1;\n  // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused\n  if (numAvail > LZMA_MATCH_LEN_MAX)\n    numAvail = LZMA_MATCH_LEN_MAX;\n  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n  repLen = repIndex = 0;\n  \n  for (i = 0; i < LZMA_NUM_REPS; i++)\n  {\n    unsigned len;\n    const Byte *data2 = data - p->reps[i];\n    if (data[0] != data2[0] || data[1] != data2[1])\n      continue;\n    for (len = 2; len < numAvail && data[len] == data2[len]; len++)\n    {}\n    if (len >= p->numFastBytes)\n    {\n      p->backRes = (UInt32)i;\n      MOVE_POS(p, len - 1)\n      return len;\n    }\n    if (len > repLen)\n    {\n      repIndex = i;\n      repLen = len;\n    }\n  }\n\n  if (mainLen >= p->numFastBytes)\n  {\n    p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;\n    MOVE_POS(p, mainLen - 1)\n    return mainLen;\n  }\n\n  mainDist = 0; /* for GCC */\n  \n  if (mainLen >= 2)\n  {\n    mainDist = p->matches[(size_t)numPairs - 1];\n    while (numPairs > 2)\n    {\n      UInt32 dist2;\n      if (mainLen != p->matches[(size_t)numPairs - 4] + 1)\n        break;\n      dist2 = p->matches[(size_t)numPairs - 3];\n      if (!ChangePair(dist2, mainDist))\n        break;\n      numPairs -= 2;\n      mainLen--;\n      mainDist = dist2;\n    }\n    if (mainLen == 2 && mainDist >= 0x80)\n      mainLen = 1;\n  }\n\n  if (repLen >= 2)\n    if (    repLen + 1 >= mainLen\n        || (repLen + 2 >= mainLen && mainDist >= (1 << 9))\n        || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))\n  {\n    p->backRes = (UInt32)repIndex;\n    MOVE_POS(p, repLen - 1)\n    return repLen;\n  }\n  \n  if (mainLen < 2 || numAvail <= 2)\n    return 1;\n\n  {\n    unsigned len1 = ReadMatchDistances(p, &p->numPairs);\n    p->longestMatchLen = len1;\n  \n    if (len1 >= 2)\n    {\n      UInt32 newDist = p->matches[(size_t)p->numPairs - 1];\n      if (   (len1 >= mainLen && newDist < mainDist)\n          || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))\n          || (len1 >  mainLen + 1)\n          || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))\n        return 1;\n    }\n  }\n  \n  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\n  \n  for (i = 0; i < LZMA_NUM_REPS; i++)\n  {\n    unsigned len, limit;\n    const Byte *data2 = data - p->reps[i];\n    if (data[0] != data2[0] || data[1] != data2[1])\n      continue;\n    limit = mainLen - 1;\n    for (len = 2;; len++)\n    {\n      if (len >= limit)\n        return 1;\n      if (data[len] != data2[len])\n        break;\n    }\n  }\n  \n  p->backRes = mainDist + LZMA_NUM_REPS;\n  if (mainLen != 2)\n  {\n    MOVE_POS(p, mainLen - 2)\n  }\n  return mainLen;\n}\n\n\n\n\nstatic void WriteEndMarker(CLzmaEnc *p, unsigned posState)\n{\n  UInt32 range;\n  range = p->rc.range;\n  {\n    UInt32 ttt, newBound;\n    CLzmaProb *prob = &p->isMatch[p->state][posState];\n    RC_BIT_PRE(&p->rc, prob)\n    RC_BIT_1(&p->rc, prob)\n    prob = &p->isRep[p->state];\n    RC_BIT_PRE(&p->rc, prob)\n    RC_BIT_0(&p->rc, prob)\n  }\n  p->state = kMatchNextStates[p->state];\n  \n  p->rc.range = range;\n  LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);\n  range = p->rc.range;\n\n  {\n    // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);\n    CLzmaProb *probs = p->posSlotEncoder[0];\n    unsigned m = 1;\n    do\n    {\n      UInt32 ttt, newBound;\n      RC_BIT_PRE(p, probs + m)\n      RC_BIT_1(&p->rc, probs + m)\n      m = (m << 1) + 1;\n    }\n    while (m < (1 << kNumPosSlotBits));\n  }\n  {\n    // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits);    UInt32 range = p->range;\n    unsigned numBits = 30 - kNumAlignBits;\n    do\n    {\n      range >>= 1;\n      p->rc.low += range;\n      RC_NORM(&p->rc)\n    }\n    while (--numBits);\n  }\n   \n  {\n    // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);\n    CLzmaProb *probs = p->posAlignEncoder;\n    unsigned m = 1;\n    do\n    {\n      UInt32 ttt, newBound;\n      RC_BIT_PRE(p, probs + m)\n      RC_BIT_1(&p->rc, probs + m)\n      m = (m << 1) + 1;\n    }\n    while (m < kAlignTableSize);\n  }\n  p->rc.range = range;\n}\n\n\nstatic SRes CheckErrors(CLzmaEnc *p)\n{\n  if (p->result != SZ_OK)\n    return p->result;\n  if (p->rc.res != SZ_OK)\n    p->result = SZ_ERROR_WRITE;\n\n  #ifndef Z7_ST\n  if (\n      // p->mf_Failure ||\n        (p->mtMode &&\n          ( // p->matchFinderMt.failure_LZ_LZ ||\n            p->matchFinderMt.failure_LZ_BT))\n     )\n  {\n    p->result = MY_HRES_ERROR_INTERNAL_ERROR;\n    // printf(\"\\nCheckErrors p->matchFinderMt.failureLZ\\n\");\n  }\n  #endif\n\n  if (MFB.result != SZ_OK)\n    p->result = SZ_ERROR_READ;\n  \n  if (p->result != SZ_OK)\n    p->finished = True;\n  return p->result;\n}\n\n\nZ7_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)\n{\n  /* ReleaseMFStream(); */\n  p->finished = True;\n  if (p->writeEndMark)\n    WriteEndMarker(p, nowPos & p->pbMask);\n  RangeEnc_FlushData(&p->rc);\n  RangeEnc_FlushStream(&p->rc);\n  return CheckErrors(p);\n}\n\n\nZ7_NO_INLINE static void FillAlignPrices(CLzmaEnc *p)\n{\n  unsigned i;\n  const CProbPrice *ProbPrices = p->ProbPrices;\n  const CLzmaProb *probs = p->posAlignEncoder;\n  // p->alignPriceCount = 0;\n  for (i = 0; i < kAlignTableSize / 2; i++)\n  {\n    UInt32 price = 0;\n    unsigned sym = i;\n    unsigned m = 1;\n    unsigned bit;\n    UInt32 prob;\n    bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\n    bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\n    bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\n    prob = probs[m];\n    p->alignPrices[i    ] = price + GET_PRICEa_0(prob);\n    p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);\n    // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);\n  }\n}\n\n\nZ7_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)\n{\n  // int y; for (y = 0; y < 100; y++) {\n\n  UInt32 tempPrices[kNumFullDistances];\n  unsigned i, lps;\n\n  const CProbPrice *ProbPrices = p->ProbPrices;\n  p->matchPriceCount = 0;\n\n  for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++)\n  {\n    unsigned posSlot = GetPosSlot1(i);\n    unsigned footerBits = (posSlot >> 1) - 1;\n    unsigned base = ((2 | (posSlot & 1)) << footerBits);\n    const CLzmaProb *probs = p->posEncoders + (size_t)base * 2;\n    // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);\n    UInt32 price = 0;\n    unsigned m = 1;\n    unsigned sym = i;\n    unsigned offset = (unsigned)1 << footerBits;\n    base += i;\n    \n    if (footerBits)\n    do\n    {\n      unsigned bit = sym & 1;\n      sym >>= 1;\n      price += GET_PRICEa(probs[m], bit);\n      m = (m << 1) + bit;\n    }\n    while (--footerBits);\n\n    {\n      unsigned prob = probs[m];\n      tempPrices[base         ] = price + GET_PRICEa_0(prob);\n      tempPrices[base + offset] = price + GET_PRICEa_1(prob);\n    }\n  }\n\n  for (lps = 0; lps < kNumLenToPosStates; lps++)\n  {\n    unsigned slot;\n    unsigned distTableSize2 = (p->distTableSize + 1) >> 1;\n    UInt32 *posSlotPrices = p->posSlotPrices[lps];\n    const CLzmaProb *probs = p->posSlotEncoder[lps];\n    \n    for (slot = 0; slot < distTableSize2; slot++)\n    {\n      // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices);\n      UInt32 price;\n      unsigned bit;\n      unsigned sym = slot + (1 << (kNumPosSlotBits - 1));\n      unsigned prob;\n      bit = sym & 1; sym >>= 1; price  = GET_PRICEa(probs[sym], bit);\n      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);\n      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);\n      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);\n      bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);\n      prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))];\n      posSlotPrices[(size_t)slot * 2    ] = price + GET_PRICEa_0(prob);\n      posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob);\n    }\n    \n    {\n      UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);\n      for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++)\n      {\n        posSlotPrices[(size_t)slot * 2    ] += delta;\n        posSlotPrices[(size_t)slot * 2 + 1] += delta;\n        delta += ((UInt32)1 << kNumBitPriceShiftBits);\n      }\n    }\n\n    {\n      UInt32 *dp = p->distancesPrices[lps];\n      \n      dp[0] = posSlotPrices[0];\n      dp[1] = posSlotPrices[1];\n      dp[2] = posSlotPrices[2];\n      dp[3] = posSlotPrices[3];\n\n      for (i = 4; i < kNumFullDistances; i += 2)\n      {\n        UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];\n        dp[i    ] = slotPrice + tempPrices[i];\n        dp[i + 1] = slotPrice + tempPrices[i + 1];\n      }\n    }\n  }\n  // }\n}\n\n\n\nstatic void LzmaEnc_Construct(CLzmaEnc *p)\n{\n  RangeEnc_Construct(&p->rc);\n  MatchFinder_Construct(&MFB);\n  \n  #ifndef Z7_ST\n  p->matchFinderMt.MatchFinder = &MFB;\n  MatchFinderMt_Construct(&p->matchFinderMt);\n  #endif\n\n  {\n    CLzmaEncProps props;\n    LzmaEncProps_Init(&props);\n    LzmaEnc_SetProps((CLzmaEncHandle)(void *)p, &props);\n  }\n\n  #ifndef LZMA_LOG_BSR\n  LzmaEnc_FastPosInit(p->g_FastPos);\n  #endif\n\n  LzmaEnc_InitPriceTables(p->ProbPrices);\n  p->litProbs = NULL;\n  p->saveState.litProbs = NULL;\n}\n\nCLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)\n{\n  void *p;\n  p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));\n  if (p)\n    LzmaEnc_Construct((CLzmaEnc *)p);\n  return p;\n}\n\nstatic void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->litProbs);\n  ISzAlloc_Free(alloc, p->saveState.litProbs);\n  p->litProbs = NULL;\n  p->saveState.litProbs = NULL;\n}\n\nstatic void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  #ifndef Z7_ST\n  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);\n  #endif\n  \n  MatchFinder_Free(&MFB, allocBig);\n  LzmaEnc_FreeLits(p, alloc);\n  RangeEnc_Free(&p->rc, alloc);\n}\n\nvoid LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  // GET_CLzmaEnc_p\n  LzmaEnc_Destruct(p, alloc, allocBig);\n  ISzAlloc_Free(alloc, p);\n}\n\n\nZ7_NO_INLINE\nstatic SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)\n{\n  UInt32 nowPos32, startPos32;\n  if (p->needInit)\n  {\n    #ifndef Z7_ST\n    if (p->mtMode)\n    {\n      RINOK(MatchFinderMt_InitMt(&p->matchFinderMt))\n    }\n    #endif\n    p->matchFinder.Init(p->matchFinderObj);\n    p->needInit = 0;\n  }\n\n  if (p->finished)\n    return p->result;\n  RINOK(CheckErrors(p))\n\n  nowPos32 = (UInt32)p->nowPos64;\n  startPos32 = nowPos32;\n\n  if (p->nowPos64 == 0)\n  {\n    unsigned numPairs;\n    Byte curByte;\n    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\n      return Flush(p, nowPos32);\n    ReadMatchDistances(p, &numPairs);\n    RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);\n    // p->state = kLiteralNextStates[p->state];\n    curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);\n    LitEnc_Encode(&p->rc, p->litProbs, curByte);\n    p->additionalOffset--;\n    nowPos32++;\n  }\n\n  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)\n  \n  for (;;)\n  {\n    UInt32 dist;\n    unsigned len, posState;\n    UInt32 range, ttt, newBound;\n    CLzmaProb *probs;\n  \n    if (p->fastMode)\n      len = GetOptimumFast(p);\n    else\n    {\n      unsigned oci = p->optCur;\n      if (p->optEnd == oci)\n        len = GetOptimum(p, nowPos32);\n      else\n      {\n        const COptimal *opt = &p->opt[oci];\n        len = opt->len;\n        p->backRes = opt->dist;\n        p->optCur = oci + 1;\n      }\n    }\n\n    posState = (unsigned)nowPos32 & p->pbMask;\n    range = p->rc.range;\n    probs = &p->isMatch[p->state][posState];\n    \n    RC_BIT_PRE(&p->rc, probs)\n    \n    dist = p->backRes;\n\n    #ifdef SHOW_STAT2\n    printf(\"\\n pos = %6X, len = %3u  pos = %6u\", nowPos32, len, dist);\n    #endif\n\n    if (dist == MARK_LIT)\n    {\n      Byte curByte;\n      const Byte *data;\n      unsigned state;\n\n      RC_BIT_0(&p->rc, probs)\n      p->rc.range = range;\n      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\n      probs = LIT_PROBS(nowPos32, *(data - 1));\n      curByte = *data;\n      state = p->state;\n      p->state = kLiteralNextStates[state];\n      if (IsLitState(state))\n        LitEnc_Encode(&p->rc, probs, curByte);\n      else\n        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));\n    }\n    else\n    {\n      RC_BIT_1(&p->rc, probs)\n      probs = &p->isRep[p->state];\n      RC_BIT_PRE(&p->rc, probs)\n      \n      if (dist < LZMA_NUM_REPS)\n      {\n        RC_BIT_1(&p->rc, probs)\n        probs = &p->isRepG0[p->state];\n        RC_BIT_PRE(&p->rc, probs)\n        if (dist == 0)\n        {\n          RC_BIT_0(&p->rc, probs)\n          probs = &p->isRep0Long[p->state][posState];\n          RC_BIT_PRE(&p->rc, probs)\n          if (len != 1)\n          {\n            RC_BIT_1_BASE(&p->rc, probs)\n          }\n          else\n          {\n            RC_BIT_0_BASE(&p->rc, probs)\n            p->state = kShortRepNextStates[p->state];\n          }\n        }\n        else\n        {\n          RC_BIT_1(&p->rc, probs)\n          probs = &p->isRepG1[p->state];\n          RC_BIT_PRE(&p->rc, probs)\n          if (dist == 1)\n          {\n            RC_BIT_0_BASE(&p->rc, probs)\n            dist = p->reps[1];\n          }\n          else\n          {\n            RC_BIT_1(&p->rc, probs)\n            probs = &p->isRepG2[p->state];\n            RC_BIT_PRE(&p->rc, probs)\n            if (dist == 2)\n            {\n              RC_BIT_0_BASE(&p->rc, probs)\n              dist = p->reps[2];\n            }\n            else\n            {\n              RC_BIT_1_BASE(&p->rc, probs)\n              dist = p->reps[3];\n              p->reps[3] = p->reps[2];\n            }\n            p->reps[2] = p->reps[1];\n          }\n          p->reps[1] = p->reps[0];\n          p->reps[0] = dist;\n        }\n\n        RC_NORM(&p->rc)\n\n        p->rc.range = range;\n\n        if (len != 1)\n        {\n          LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);\n          --p->repLenEncCounter;\n          p->state = kRepNextStates[p->state];\n        }\n      }\n      else\n      {\n        unsigned posSlot;\n        RC_BIT_0(&p->rc, probs)\n        p->rc.range = range;\n        p->state = kMatchNextStates[p->state];\n\n        LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);\n        // --p->lenEnc.counter;\n\n        dist -= LZMA_NUM_REPS;\n        p->reps[3] = p->reps[2];\n        p->reps[2] = p->reps[1];\n        p->reps[1] = p->reps[0];\n        p->reps[0] = dist + 1;\n        \n        p->matchPriceCount++;\n        GetPosSlot(dist, posSlot)\n        // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);\n        {\n          UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits);\n          range = p->rc.range;\n          probs = p->posSlotEncoder[GetLenToPosState(len)];\n          do\n          {\n            CLzmaProb *prob = probs + (sym >> kNumPosSlotBits);\n            UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1;\n            sym <<= 1;\n            RC_BIT(&p->rc, prob, bit)\n          }\n          while (sym < (1 << kNumPosSlotBits * 2));\n          p->rc.range = range;\n        }\n        \n        if (dist >= kStartPosModelIndex)\n        {\n          unsigned footerBits = ((posSlot >> 1) - 1);\n\n          if (dist < kNumFullDistances)\n          {\n            unsigned base = ((2 | (posSlot & 1)) << footerBits);\n            RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */));\n          }\n          else\n          {\n            UInt32 pos2 = (dist | 0xF) << (32 - footerBits);\n            range = p->rc.range;\n            // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\n            /*\n            do\n            {\n              range >>= 1;\n              p->rc.low += range & (0 - ((dist >> --footerBits) & 1));\n              RC_NORM(&p->rc)\n            }\n            while (footerBits > kNumAlignBits);\n            */\n            do\n            {\n              range >>= 1;\n              p->rc.low += range & (0 - (pos2 >> 31));\n              pos2 += pos2;\n              RC_NORM(&p->rc)\n            }\n            while (pos2 != 0xF0000000);\n\n\n            // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);\n\n            {\n              unsigned m = 1;\n              unsigned bit;\n              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit)  m = (m << 1) + bit;\n              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit)  m = (m << 1) + bit;\n              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit)  m = (m << 1) + bit;\n              bit = dist & 1;             RC_BIT(&p->rc, p->posAlignEncoder + m, bit)\n              p->rc.range = range;\n              // p->alignPriceCount++;\n            }\n          }\n        }\n      }\n    }\n\n    nowPos32 += (UInt32)len;\n    p->additionalOffset -= len;\n    \n    if (p->additionalOffset == 0)\n    {\n      UInt32 processed;\n\n      if (!p->fastMode)\n      {\n        /*\n        if (p->alignPriceCount >= 16) // kAlignTableSize\n          FillAlignPrices(p);\n        if (p->matchPriceCount >= 128)\n          FillDistancesPrices(p);\n        if (p->lenEnc.counter <= 0)\n          LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);\n        */\n        if (p->matchPriceCount >= 64)\n        {\n          FillAlignPrices(p);\n          // { int y; for (y = 0; y < 100; y++) {\n          FillDistancesPrices(p);\n          // }}\n          LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);\n        }\n        if (p->repLenEncCounter <= 0)\n        {\n          p->repLenEncCounter = REP_LEN_COUNT;\n          LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);\n        }\n      }\n    \n      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\n        break;\n      processed = nowPos32 - startPos32;\n      \n      if (maxPackSize)\n      {\n        if (processed + kNumOpts + 300 >= maxUnpackSize\n            || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)\n          break;\n      }\n      else if (processed >= (1 << 17))\n      {\n        p->nowPos64 += nowPos32 - startPos32;\n        return CheckErrors(p);\n      }\n    }\n  }\n\n  p->nowPos64 += nowPos32 - startPos32;\n  return Flush(p, nowPos32);\n}\n\n\n\n#define kBigHashDicLimit ((UInt32)1 << 24)\n\nstatic SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  UInt32 beforeSize = kNumOpts;\n  UInt32 dictSize;\n\n  if (!RangeEnc_Alloc(&p->rc, alloc))\n    return SZ_ERROR_MEM;\n\n  #ifndef Z7_ST\n  p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0));\n  #endif\n\n  {\n    const unsigned lclp = p->lc + p->lp;\n    if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)\n    {\n      LzmaEnc_FreeLits(p, alloc);\n      p->litProbs =           (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp);\n      p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((size_t)0x300 * sizeof(CLzmaProb)) << lclp);\n      if (!p->litProbs || !p->saveState.litProbs)\n      {\n        LzmaEnc_FreeLits(p, alloc);\n        return SZ_ERROR_MEM;\n      }\n      p->lclp = lclp;\n    }\n  }\n\n  MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);\n\n\n  dictSize = p->dictSize;\n  if (dictSize == ((UInt32)2 << 30) ||\n      dictSize == ((UInt32)3 << 30))\n  {\n    /* 21.03 : here we reduce the dictionary for 2 reasons:\n       1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary.\n       2) we want to elimate useless last MatchFinder_Normalize3() for corner cases,\n          where data size is aligned for 1 GB: 5/6/8 GB.\n          That reducing must be >= 1 for such corner cases. */\n    dictSize -= 1;\n  }\n\n  if (beforeSize + dictSize < keepWindowSize)\n    beforeSize = keepWindowSize - dictSize;\n\n  /* in worst case we can look ahead for\n        max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes.\n     we send larger value for (keepAfter) to MantchFinder_Create():\n        (numFastBytes + LZMA_MATCH_LEN_MAX + 1)\n  */\n\n  #ifndef Z7_ST\n  if (p->mtMode)\n  {\n    RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize,\n        p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */\n        , allocBig))\n    p->matchFinderObj = &p->matchFinderMt;\n    MFB.bigHash = (Byte)(MFB.hashMask >= 0xFFFFFF ? 1 : 0);\n    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);\n  }\n  else\n  #endif\n  {\n    if (!MatchFinder_Create(&MFB, dictSize, beforeSize,\n        p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */\n        , allocBig))\n      return SZ_ERROR_MEM;\n    p->matchFinderObj = &MFB;\n    MatchFinder_CreateVTable(&MFB, &p->matchFinder);\n  }\n  \n  return SZ_OK;\n}\n\nstatic void LzmaEnc_Init(CLzmaEnc *p)\n{\n  unsigned i;\n  p->state = 0;\n  p->reps[0] =\n  p->reps[1] =\n  p->reps[2] =\n  p->reps[3] = 1;\n\n  RangeEnc_Init(&p->rc);\n\n  for (i = 0; i < (1 << kNumAlignBits); i++)\n    p->posAlignEncoder[i] = kProbInitValue;\n\n  for (i = 0; i < kNumStates; i++)\n  {\n    unsigned j;\n    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)\n    {\n      p->isMatch[i][j] = kProbInitValue;\n      p->isRep0Long[i][j] = kProbInitValue;\n    }\n    p->isRep[i] = kProbInitValue;\n    p->isRepG0[i] = kProbInitValue;\n    p->isRepG1[i] = kProbInitValue;\n    p->isRepG2[i] = kProbInitValue;\n  }\n\n  {\n    for (i = 0; i < kNumLenToPosStates; i++)\n    {\n      CLzmaProb *probs = p->posSlotEncoder[i];\n      unsigned j;\n      for (j = 0; j < (1 << kNumPosSlotBits); j++)\n        probs[j] = kProbInitValue;\n    }\n  }\n  {\n    for (i = 0; i < kNumFullDistances; i++)\n      p->posEncoders[i] = kProbInitValue;\n  }\n\n  {\n    const size_t num = (size_t)0x300 << (p->lp + p->lc);\n    size_t k;\n    CLzmaProb *probs = p->litProbs;\n    for (k = 0; k < num; k++)\n      probs[k] = kProbInitValue;\n  }\n\n\n  LenEnc_Init(&p->lenProbs);\n  LenEnc_Init(&p->repLenProbs);\n\n  p->optEnd = 0;\n  p->optCur = 0;\n\n  {\n    for (i = 0; i < kNumOpts; i++)\n      p->opt[i].price = kInfinityPrice;\n  }\n\n  p->additionalOffset = 0;\n\n  p->pbMask = ((unsigned)1 << p->pb) - 1;\n  p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);\n\n  // p->mf_Failure = False;\n}\n\n\nstatic void LzmaEnc_InitPrices(CLzmaEnc *p)\n{\n  if (!p->fastMode)\n  {\n    FillDistancesPrices(p);\n    FillAlignPrices(p);\n  }\n\n  p->lenEnc.tableSize =\n  p->repLenEnc.tableSize =\n      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;\n\n  p->repLenEncCounter = REP_LEN_COUNT;\n\n  LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);\n  LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);\n}\n\nstatic SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  unsigned i;\n  for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)\n    if (p->dictSize <= ((UInt32)1 << i))\n      break;\n  p->distTableSize = i * 2;\n\n  p->finished = False;\n  p->result = SZ_OK;\n  p->nowPos64 = 0;\n  p->needInit = 1;\n  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig))\n  LzmaEnc_Init(p);\n  LzmaEnc_InitPrices(p);\n  return SZ_OK;\n}\n\nstatic SRes LzmaEnc_Prepare(CLzmaEncHandle p,\n    ISeqOutStreamPtr outStream,\n    ISeqInStreamPtr inStream,\n    ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  // GET_CLzmaEnc_p\n  MatchFinder_SET_STREAM(&MFB, inStream)\n  p->rc.outStream = outStream;\n  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);\n}\n\nSRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle p,\n    ISeqInStreamPtr inStream, UInt32 keepWindowSize,\n    ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  // GET_CLzmaEnc_p\n  MatchFinder_SET_STREAM(&MFB, inStream)\n  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\n}\n\nSRes LzmaEnc_MemPrepare(CLzmaEncHandle p,\n    const Byte *src, SizeT srcLen,\n    UInt32 keepWindowSize,\n    ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  // GET_CLzmaEnc_p\n  MatchFinder_SET_DIRECT_INPUT_BUF(&MFB, src, srcLen)\n  LzmaEnc_SetDataSize(p, srcLen);\n  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\n}\n\nvoid LzmaEnc_Finish(CLzmaEncHandle p)\n{\n  #ifndef Z7_ST\n  // GET_CLzmaEnc_p\n  if (p->mtMode)\n    MatchFinderMt_ReleaseStream(&p->matchFinderMt);\n  #else\n  UNUSED_VAR(p)\n  #endif\n}\n\n\ntypedef struct\n{\n  ISeqOutStream vt;\n  Byte *data;\n  size_t rem;\n  BoolInt overflow;\n} CLzmaEnc_SeqOutStreamBuf;\n\nstatic size_t SeqOutStreamBuf_Write(ISeqOutStreamPtr pp, const void *data, size_t size)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CLzmaEnc_SeqOutStreamBuf)\n  if (p->rem < size)\n  {\n    size = p->rem;\n    p->overflow = True;\n  }\n  if (size != 0)\n  {\n    memcpy(p->data, data, size);\n    p->rem -= size;\n    p->data += size;\n  }\n  return size;\n}\n\n\n/*\nUInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle p)\n{\n  GET_const_CLzmaEnc_p\n  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\n}\n*/\n\nconst Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle p)\n{\n  // GET_const_CLzmaEnc_p\n  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\n}\n\n\n// (desiredPackSize == 0) is not allowed\nSRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle p, BoolInt reInit,\n    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)\n{\n  // GET_CLzmaEnc_p\n  UInt64 nowPos64;\n  SRes res;\n  CLzmaEnc_SeqOutStreamBuf outStream;\n\n  outStream.vt.Write = SeqOutStreamBuf_Write;\n  outStream.data = dest;\n  outStream.rem = *destLen;\n  outStream.overflow = False;\n\n  p->writeEndMark = False;\n  p->finished = False;\n  p->result = SZ_OK;\n\n  if (reInit)\n    LzmaEnc_Init(p);\n  LzmaEnc_InitPrices(p);\n  RangeEnc_Init(&p->rc);\n  p->rc.outStream = &outStream.vt;\n  nowPos64 = p->nowPos64;\n  \n  res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);\n  \n  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);\n  *destLen -= outStream.rem;\n  if (outStream.overflow)\n    return SZ_ERROR_OUTPUT_EOF;\n\n  return res;\n}\n\n\nZ7_NO_INLINE\nstatic SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgressPtr progress)\n{\n  SRes res = SZ_OK;\n\n  #ifndef Z7_ST\n  Byte allocaDummy[0x300];\n  allocaDummy[0] = 0;\n  allocaDummy[1] = allocaDummy[0];\n  #endif\n\n  for (;;)\n  {\n    res = LzmaEnc_CodeOneBlock(p, 0, 0);\n    if (res != SZ_OK || p->finished)\n      break;\n    if (progress)\n    {\n      res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));\n      if (res != SZ_OK)\n      {\n        res = SZ_ERROR_PROGRESS;\n        break;\n      }\n    }\n  }\n  \n  LzmaEnc_Finish((CLzmaEncHandle)(void *)p);\n\n  /*\n  if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB))\n    res = SZ_ERROR_FAIL;\n  }\n  */\n\n  return res;\n}\n\n\nSRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress,\n    ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  // GET_CLzmaEnc_p\n  RINOK(LzmaEnc_Prepare(p, outStream, inStream, alloc, allocBig))\n  return LzmaEnc_Encode2(p, progress);\n}\n\n\nSRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *props, SizeT *size)\n{\n  if (*size < LZMA_PROPS_SIZE)\n    return SZ_ERROR_PARAM;\n  *size = LZMA_PROPS_SIZE;\n  {\n    // GET_CLzmaEnc_p\n    const UInt32 dictSize = p->dictSize;\n    UInt32 v;\n    props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);\n    \n    // we write aligned dictionary value to properties for lzma decoder\n    if (dictSize >= ((UInt32)1 << 21))\n    {\n      const UInt32 kDictMask = ((UInt32)1 << 20) - 1;\n      v = (dictSize + kDictMask) & ~kDictMask;\n      if (v < dictSize)\n        v = dictSize;\n    }\n    else\n    {\n      unsigned i = 11 * 2;\n      do\n      {\n        v = (UInt32)(2 + (i & 1)) << (i >> 1);\n        i++;\n      }\n      while (v < dictSize);\n    }\n\n    SetUi32(props + 1, v)\n    return SZ_OK;\n  }\n}\n\n\nunsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p)\n{\n  // GET_CLzmaEnc_p\n  return (unsigned)p->writeEndMark;\n}\n\n\nSRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  SRes res;\n  // GET_CLzmaEnc_p\n\n  CLzmaEnc_SeqOutStreamBuf outStream;\n\n  outStream.vt.Write = SeqOutStreamBuf_Write;\n  outStream.data = dest;\n  outStream.rem = *destLen;\n  outStream.overflow = False;\n\n  p->writeEndMark = writeEndMark;\n  p->rc.outStream = &outStream.vt;\n\n  res = LzmaEnc_MemPrepare(p, src, srcLen, 0, alloc, allocBig);\n  \n  if (res == SZ_OK)\n  {\n    res = LzmaEnc_Encode2(p, progress);\n    if (res == SZ_OK && p->nowPos64 != srcLen)\n      res = SZ_ERROR_FAIL;\n  }\n\n  *destLen -= (SizeT)outStream.rem;\n  if (outStream.overflow)\n    return SZ_ERROR_OUTPUT_EOF;\n  return res;\n}\n\n\nSRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\n    ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  CLzmaEncHandle p = LzmaEnc_Create(alloc);\n  SRes res;\n  if (!p)\n    return SZ_ERROR_MEM;\n\n  res = LzmaEnc_SetProps(p, props);\n  if (res == SZ_OK)\n  {\n    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);\n    if (res == SZ_OK)\n      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,\n          writeEndMark, progress, alloc, allocBig);\n  }\n\n  LzmaEnc_Destroy(p, alloc, allocBig);\n  return res;\n}\n\n\n/*\n#ifndef Z7_ST\nvoid LzmaEnc_GetLzThreads(CLzmaEncHandle p, HANDLE lz_threads[2])\n{\n  GET_const_CLzmaEnc_p\n  lz_threads[0] = p->matchFinderMt.hashSync.thread;\n  lz_threads[1] = p->matchFinderMt.btSync.thread;\n}\n#endif\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/LzmaEnc.h",
    "content": "﻿/*  LzmaEnc.h -- LZMA Encoder\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_LZMA_ENC_H\n#define ZIP7_INC_LZMA_ENC_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define LZMA_PROPS_SIZE 5\n\ntypedef struct\n{\n  int level;       /* 0 <= level <= 9 */\n  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version\n                      (1 << 12) <= dictSize <= (3 << 29) for 64-bit version\n                      default = (1 << 24) */\n  int lc;          /* 0 <= lc <= 8, default = 3 */\n  int lp;          /* 0 <= lp <= 4, default = 0 */\n  int pb;          /* 0 <= pb <= 4, default = 2 */\n  int algo;        /* 0 - fast, 1 - normal, default = 1 */\n  int fb;          /* 5 <= fb <= 273, default = 32 */\n  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */\n  int numHashBytes; /* 2, 3 or 4, default = 4 */\n  unsigned numHashOutBits;  /* default = ? */\n  UInt32 mc;       /* 1 <= mc <= (1 << 30), default = 32 */\n  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */\n  int numThreads;  /* 1 or 2, default = 2 */\n\n  // int _pad;\n  Int32 affinityGroup;\n\n  UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.\n                        Encoder uses this value to reduce dictionary size */\n\n  UInt64 affinity;\n  UInt64 affinityInGroup;\n} CLzmaEncProps;\n\nvoid LzmaEncProps_Init(CLzmaEncProps *p);\nvoid LzmaEncProps_Normalize(CLzmaEncProps *p);\nUInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);\n\n\n/* ---------- CLzmaEncHandle Interface ---------- */\n\n/* LzmaEnc* functions can return the following exit codes:\nSRes:\n  SZ_OK           - OK\n  SZ_ERROR_MEM    - Memory allocation error\n  SZ_ERROR_PARAM  - Incorrect paramater in props\n  SZ_ERROR_WRITE  - ISeqOutStream write callback error\n  SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output\n  SZ_ERROR_PROGRESS - some break from progress callback\n  SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)\n*/\n\ntypedef struct CLzmaEnc CLzmaEnc;\ntypedef CLzmaEnc * CLzmaEncHandle;\n// Z7_DECLARE_HANDLE(CLzmaEncHandle)\n\nCLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);\nvoid LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);\n\nSRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);\nvoid LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);\nSRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);\nunsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);\n\nSRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream,\n    ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);\nSRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    int writeEndMark, ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);\n\n\n/* ---------- One Call Interface ---------- */\n\nSRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\n    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\n    ICompressProgressPtr progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/MtCoder.c",
    "content": "﻿/* MtCoder.c -- Multi-thread Coder\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"MtCoder.h\"\n\n#ifndef Z7_ST\n\nstatic SRes MtProgressThunk_Progress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CMtProgressThunk)\n  UInt64 inSize2 = 0;\n  UInt64 outSize2 = 0;\n  if (inSize != (UInt64)(Int64)-1)\n  {\n    inSize2 = inSize - p->inSize;\n    p->inSize = inSize;\n  }\n  if (outSize != (UInt64)(Int64)-1)\n  {\n    outSize2 = outSize - p->outSize;\n    p->outSize = outSize;\n  }\n  return MtProgress_ProgressAdd(p->mtProgress, inSize2, outSize2);\n}\n\n\nvoid MtProgressThunk_CreateVTable(CMtProgressThunk *p)\n{\n  p->vt.Progress = MtProgressThunk_Progress;\n}\n\n\n\n#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }\n\n\nstatic THREAD_FUNC_DECL ThreadFunc(void *pp);\n\n\nstatic SRes MtCoderThread_CreateAndStart(CMtCoderThread *t\n#ifdef _WIN32\n    , CMtCoder * const mtc\n#endif\n    )\n{\n  WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->startEvent);\n  // printf(\"\\n====== MtCoderThread_CreateAndStart : \\n\");\n  if (wres == 0)\n  {\n    t->stop = False;\n    if (!Thread_WasCreated(&t->thread))\n    {\n#ifdef _WIN32\n      if (mtc->numThreadGroups)\n        wres = Thread_Create_With_Group(&t->thread, ThreadFunc, t,\n            ThreadNextGroup_GetNext(&mtc->nextGroup), // group\n            0); // affinityMask\n      else\n#endif\n        wres = Thread_Create(&t->thread, ThreadFunc, t);\n    }\n    if (wres == 0)\n      wres = Event_Set(&t->startEvent);\n  }\n  if (wres == 0)\n    return SZ_OK;\n  return MY_SRes_HRESULT_FROM_WRes(wres);\n}\n\n\nZ7_FORCE_INLINE\nstatic void MtCoderThread_Destruct(CMtCoderThread *t)\n{\n  if (Thread_WasCreated(&t->thread))\n  {\n    t->stop = 1;\n    Event_Set(&t->startEvent);\n    Thread_Wait_Close(&t->thread);\n  }\n\n  Event_Close(&t->startEvent);\n\n  if (t->inBuf)\n  {\n    ISzAlloc_Free(t->mtCoder->allocBig, t->inBuf);\n    t->inBuf = NULL;\n  }\n}\n\n\n\n\n/*\n  ThreadFunc2() returns:\n  SZ_OK           - in all normal cases (even for stream error or memory allocation error)\n  SZ_ERROR_THREAD - in case of failure in system synch function\n*/\n\nstatic SRes ThreadFunc2(CMtCoderThread *t)\n{\n  CMtCoder * const mtc = t->mtCoder;\n\n  for (;;)\n  {\n    unsigned bi;\n    SRes res;\n    SRes res2;\n    BoolInt finished;\n    unsigned bufIndex;\n    size_t size;\n    const Byte *inData;\n    UInt64 readProcessed = 0;\n    \n    RINOK_THREAD(Event_Wait(&mtc->readEvent))\n\n    /* after Event_Wait(&mtc->readEvent) we must call Event_Set(&mtc->readEvent) in any case to unlock another threads */\n\n    if (mtc->stopReading)\n    {\n      return Event_Set(&mtc->readEvent) == 0 ? SZ_OK : SZ_ERROR_THREAD;\n    }\n\n    res = MtProgress_GetError(&mtc->mtProgress);\n    \n    size = 0;\n    inData = NULL;\n    finished = True;\n\n    if (res == SZ_OK)\n    {\n      size = mtc->blockSize;\n      if (mtc->inStream)\n      {\n        if (!t->inBuf)\n        {\n          t->inBuf = (Byte *)ISzAlloc_Alloc(mtc->allocBig, mtc->blockSize);\n          if (!t->inBuf)\n            res = SZ_ERROR_MEM;\n        }\n        if (res == SZ_OK)\n        {\n          res = SeqInStream_ReadMax(mtc->inStream, t->inBuf, &size);\n          readProcessed = mtc->readProcessed + size;\n          mtc->readProcessed = readProcessed;\n        }\n        if (res != SZ_OK)\n        {\n          mtc->readRes = res;\n          /* after reading error - we can stop encoding of previous blocks */\n          MtProgress_SetError(&mtc->mtProgress, res);\n        }\n        else\n          finished = (size != mtc->blockSize);\n      }\n      else\n      {\n        size_t rem;\n        readProcessed = mtc->readProcessed;\n        rem = mtc->inDataSize - (size_t)readProcessed;\n        if (size > rem)\n          size = rem;\n        inData = mtc->inData + (size_t)readProcessed;\n        readProcessed += size;\n        mtc->readProcessed = readProcessed;\n        finished = (mtc->inDataSize == (size_t)readProcessed);\n      }\n    }\n\n    /* we must get some block from blocksSemaphore before Event_Set(&mtc->readEvent) */\n\n    res2 = SZ_OK;\n\n    if (Semaphore_Wait(&mtc->blocksSemaphore) != 0)\n    {\n      res2 = SZ_ERROR_THREAD;\n      if (res == SZ_OK)\n      {\n        res = res2;\n        // MtProgress_SetError(&mtc->mtProgress, res);\n      }\n    }\n\n    bi = mtc->blockIndex;\n\n    if (++mtc->blockIndex >= mtc->numBlocksMax)\n      mtc->blockIndex = 0;\n\n    bufIndex = (unsigned)(int)-1;\n\n    if (res == SZ_OK)\n      res = MtProgress_GetError(&mtc->mtProgress);\n\n    if (res != SZ_OK)\n      finished = True;\n\n    if (!finished)\n    {\n      if (mtc->numStartedThreads < mtc->numStartedThreadsLimit\n          && mtc->expectedDataSize != readProcessed)\n      {\n        res = MtCoderThread_CreateAndStart(&mtc->threads[mtc->numStartedThreads]\n#ifdef _WIN32\n            , mtc\n#endif\n            );\n        if (res == SZ_OK)\n          mtc->numStartedThreads++;\n        else\n        {\n          MtProgress_SetError(&mtc->mtProgress, res);\n          finished = True;\n        }\n      }\n    }\n\n    if (finished)\n      mtc->stopReading = True;\n\n    RINOK_THREAD(Event_Set(&mtc->readEvent))\n\n    if (res2 != SZ_OK)\n      return res2;\n\n    if (res == SZ_OK)\n    {\n      CriticalSection_Enter(&mtc->cs);\n      bufIndex = mtc->freeBlockHead;\n      mtc->freeBlockHead = mtc->freeBlockList[bufIndex];\n      CriticalSection_Leave(&mtc->cs);\n      \n      res = mtc->mtCallback->Code(mtc->mtCallbackObject, t->index, bufIndex,\n          mtc->inStream ? t->inBuf : inData, size, finished);\n      \n      // MtProgress_Reinit(&mtc->mtProgress, t->index);\n\n      if (res != SZ_OK)\n        MtProgress_SetError(&mtc->mtProgress, res);\n    }\n\n    {\n      CMtCoderBlock * const block = &mtc->blocks[bi];\n      block->res = res;\n      block->bufIndex = bufIndex;\n      block->finished = finished;\n    }\n    \n    #ifdef MTCODER_USE_WRITE_THREAD\n      RINOK_THREAD(Event_Set(&mtc->writeEvents[bi]))\n    #else\n    {\n      unsigned wi;\n      {\n        CriticalSection_Enter(&mtc->cs);\n        wi = mtc->writeIndex;\n        if (wi == bi)\n          mtc->writeIndex = (unsigned)(int)-1;\n        else\n          mtc->ReadyBlocks[bi] = True;\n        CriticalSection_Leave(&mtc->cs);\n      }\n\n      if (wi != bi)\n      {\n        if (res != SZ_OK || finished)\n          return 0;\n        continue;\n      }\n\n      if (mtc->writeRes != SZ_OK)\n        res = mtc->writeRes;\n\n      for (;;)\n      {\n        if (res == SZ_OK && bufIndex != (unsigned)(int)-1)\n        {\n          res = mtc->mtCallback->Write(mtc->mtCallbackObject, bufIndex);\n          if (res != SZ_OK)\n          {\n            mtc->writeRes = res;\n            MtProgress_SetError(&mtc->mtProgress, res);\n          }\n        }\n\n        if (++wi >= mtc->numBlocksMax)\n          wi = 0;\n        {\n          BoolInt isReady;\n\n          CriticalSection_Enter(&mtc->cs);\n          \n          if (bufIndex != (unsigned)(int)-1)\n          {\n            mtc->freeBlockList[bufIndex] = mtc->freeBlockHead;\n            mtc->freeBlockHead = bufIndex;\n          }\n          \n          isReady = mtc->ReadyBlocks[wi];\n          \n          if (isReady)\n            mtc->ReadyBlocks[wi] = False;\n          else\n            mtc->writeIndex = wi;\n          \n          CriticalSection_Leave(&mtc->cs);\n\n          RINOK_THREAD(Semaphore_Release1(&mtc->blocksSemaphore))\n\n          if (!isReady)\n            break;\n        }\n\n        {\n          CMtCoderBlock *block = &mtc->blocks[wi];\n          if (res == SZ_OK && block->res != SZ_OK)\n            res = block->res;\n          bufIndex = block->bufIndex;\n          finished = block->finished;\n        }\n      }\n    }\n    #endif\n      \n    if (finished || res != SZ_OK)\n      return 0;\n  }\n}\n\n\nstatic THREAD_FUNC_DECL ThreadFunc(void *pp)\n{\n  CMtCoderThread * const t = (CMtCoderThread *)pp;\n  for (;;)\n  {\n    if (Event_Wait(&t->startEvent) != 0)\n      return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD;\n    if (t->stop)\n      return 0;\n    {\n      const SRes res = ThreadFunc2(t);\n      CMtCoder *mtc = t->mtCoder;\n      if (res != SZ_OK)\n      {\n        MtProgress_SetError(&mtc->mtProgress, res);\n      }\n      \n      #ifndef MTCODER_USE_WRITE_THREAD\n      {\n        const unsigned numFinished = (unsigned)InterlockedIncrement(&mtc->numFinishedThreads);\n        if (numFinished == mtc->numStartedThreads)\n          if (Event_Set(&mtc->finishedEvent) != 0)\n            return (THREAD_FUNC_RET_TYPE)SZ_ERROR_THREAD;\n      }\n      #endif\n    }\n  }\n}\n\n\n\nvoid MtCoder_Construct(CMtCoder *p)\n{\n  unsigned i;\n  \n  p->blockSize = 0;\n  p->numThreadsMax = 0;\n  p->numThreadGroups = 0;\n  p->expectedDataSize = (UInt64)(Int64)-1;\n\n  p->inStream = NULL;\n  p->inData = NULL;\n  p->inDataSize = 0;\n\n  p->progress = NULL;\n  p->allocBig = NULL;\n\n  p->mtCallback = NULL;\n  p->mtCallbackObject = NULL;\n\n  p->allocatedBufsSize = 0;\n\n  Event_Construct(&p->readEvent);\n  Semaphore_Construct(&p->blocksSemaphore);\n\n  for (i = 0; i < MTCODER_THREADS_MAX; i++)\n  {\n    CMtCoderThread *t = &p->threads[i];\n    t->mtCoder = p;\n    t->index = i;\n    t->inBuf = NULL;\n    t->stop = False;\n    Event_Construct(&t->startEvent);\n    Thread_CONSTRUCT(&t->thread)\n  }\n\n  #ifdef MTCODER_USE_WRITE_THREAD\n    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)\n      Event_Construct(&p->writeEvents[i]);\n  #else\n    Event_Construct(&p->finishedEvent);\n  #endif\n\n  CriticalSection_Init(&p->cs);\n  CriticalSection_Init(&p->mtProgress.cs);\n}\n\n\n\n\nstatic void MtCoder_Free(CMtCoder *p)\n{\n  unsigned i;\n\n  /*\n  p->stopReading = True;\n  if (Event_IsCreated(&p->readEvent))\n    Event_Set(&p->readEvent);\n  */\n\n  for (i = 0; i < MTCODER_THREADS_MAX; i++)\n    MtCoderThread_Destruct(&p->threads[i]);\n\n  Event_Close(&p->readEvent);\n  Semaphore_Close(&p->blocksSemaphore);\n\n  #ifdef MTCODER_USE_WRITE_THREAD\n    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)\n      Event_Close(&p->writeEvents[i]);\n  #else\n    Event_Close(&p->finishedEvent);\n  #endif\n}\n\n\nvoid MtCoder_Destruct(CMtCoder *p)\n{\n  MtCoder_Free(p);\n\n  CriticalSection_Delete(&p->cs);\n  CriticalSection_Delete(&p->mtProgress.cs);\n}\n\n\nSRes MtCoder_Code(CMtCoder *p)\n{\n  unsigned numThreads = p->numThreadsMax;\n  unsigned numBlocksMax;\n  unsigned i;\n  SRes res = SZ_OK;\n\n  // printf(\"\\n====== MtCoder_Code : \\n\");\n\n  if (numThreads > MTCODER_THREADS_MAX)\n      numThreads = MTCODER_THREADS_MAX;\n  numBlocksMax = MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads);\n  \n  if (p->blockSize < ((UInt32)1 << 26)) numBlocksMax++;\n  if (p->blockSize < ((UInt32)1 << 24)) numBlocksMax++;\n  if (p->blockSize < ((UInt32)1 << 22)) numBlocksMax++;\n\n  if (numBlocksMax > MTCODER_BLOCKS_MAX)\n      numBlocksMax = MTCODER_BLOCKS_MAX;\n\n  if (p->blockSize != p->allocatedBufsSize)\n  {\n    for (i = 0; i < MTCODER_THREADS_MAX; i++)\n    {\n      CMtCoderThread *t = &p->threads[i];\n      if (t->inBuf)\n      {\n        ISzAlloc_Free(p->allocBig, t->inBuf);\n        t->inBuf = NULL;\n      }\n    }\n    p->allocatedBufsSize = p->blockSize;\n  }\n\n  p->readRes = SZ_OK;\n\n  MtProgress_Init(&p->mtProgress, p->progress);\n\n  #ifdef MTCODER_USE_WRITE_THREAD\n    for (i = 0; i < numBlocksMax; i++)\n    {\n      RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->writeEvents[i]))\n    }\n  #else\n    RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent))\n  #endif\n\n  {\n    RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->readEvent))\n    RINOK_THREAD(Semaphore_OptCreateInit(&p->blocksSemaphore, (UInt32)numBlocksMax, (UInt32)numBlocksMax))\n  }\n\n  for (i = 0; i < MTCODER_BLOCKS_MAX - 1; i++)\n    p->freeBlockList[i] = i + 1;\n  p->freeBlockList[MTCODER_BLOCKS_MAX - 1] = (unsigned)(int)-1;\n  p->freeBlockHead = 0;\n\n  p->readProcessed = 0;\n  p->blockIndex = 0;\n  p->numBlocksMax = numBlocksMax;\n  p->stopReading = False;\n\n  #ifndef MTCODER_USE_WRITE_THREAD\n    p->writeIndex = 0;\n    p->writeRes = SZ_OK;\n    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)\n      p->ReadyBlocks[i] = False;\n    p->numFinishedThreads = 0;\n  #endif\n\n  p->numStartedThreadsLimit = numThreads;\n  p->numStartedThreads = 0;\n  ThreadNextGroup_Init(&p->nextGroup, p->numThreadGroups, 0); // startGroup\n\n  // for (i = 0; i < numThreads; i++)\n  {\n    // here we create new thread for first block.\n    // And each new thread will create another new thread after block reading\n    // until numStartedThreadsLimit is reached.\n    CMtCoderThread *nextThread = &p->threads[p->numStartedThreads++];\n    {\n      const SRes res2 = MtCoderThread_CreateAndStart(nextThread\n#ifdef _WIN32\n            , p\n#endif\n            );\n      RINOK(res2)\n    }\n  }\n\n  RINOK_THREAD(Event_Set(&p->readEvent))\n\n  #ifdef MTCODER_USE_WRITE_THREAD\n  {\n    unsigned bi = 0;\n\n    for (;; bi++)\n    {\n      if (bi >= numBlocksMax)\n        bi = 0;\n\n      RINOK_THREAD(Event_Wait(&p->writeEvents[bi]))\n\n      {\n        const CMtCoderBlock * const block = &p->blocks[bi];\n        const unsigned bufIndex = block->bufIndex;\n        const BoolInt finished = block->finished;\n        if (res == SZ_OK && block->res != SZ_OK)\n          res = block->res;\n\n        if (bufIndex != (unsigned)(int)-1)\n        {\n          if (res == SZ_OK)\n          {\n            res = p->mtCallback->Write(p->mtCallbackObject, bufIndex);\n            if (res != SZ_OK)\n              MtProgress_SetError(&p->mtProgress, res);\n          }\n          \n          CriticalSection_Enter(&p->cs);\n          {\n            p->freeBlockList[bufIndex] = p->freeBlockHead;\n            p->freeBlockHead = bufIndex;\n          }\n          CriticalSection_Leave(&p->cs);\n        }\n        \n        RINOK_THREAD(Semaphore_Release1(&p->blocksSemaphore))\n\n        if (finished)\n          break;\n      }\n    }\n  }\n  #else\n  {\n    const WRes wres = Event_Wait(&p->finishedEvent);\n    res = MY_SRes_HRESULT_FROM_WRes(wres);\n  }\n  #endif\n\n  if (res == SZ_OK)\n    res = p->readRes;\n\n  if (res == SZ_OK)\n    res = p->mtProgress.res;\n\n  #ifndef MTCODER_USE_WRITE_THREAD\n    if (res == SZ_OK)\n      res = p->writeRes;\n  #endif\n\n  if (res != SZ_OK)\n    MtCoder_Free(p);\n  return res;\n}\n\n#endif\n\n#undef RINOK_THREAD\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/MtCoder.h",
    "content": "﻿/* MtCoder.h -- Multi-thread Coder\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_MT_CODER_H\n#define ZIP7_INC_MT_CODER_H\n\n#include \"MtDec.h\"\n\nEXTERN_C_BEGIN\n\n/*\n  if (    defined MTCODER_USE_WRITE_THREAD) : main thread writes all data blocks to output stream\n  if (not defined MTCODER_USE_WRITE_THREAD) : any coder thread can write data blocks to output stream\n*/\n/* #define MTCODER_USE_WRITE_THREAD */\n\n#ifndef Z7_ST\n  #define MTCODER_GET_NUM_BLOCKS_FROM_THREADS(numThreads) ((numThreads) + (numThreads) / 8 + 1)\n  #define MTCODER_THREADS_MAX 256\n  #define MTCODER_BLOCKS_MAX (MTCODER_GET_NUM_BLOCKS_FROM_THREADS(MTCODER_THREADS_MAX) + 3)\n#else\n  #define MTCODER_THREADS_MAX 1\n  #define MTCODER_BLOCKS_MAX 1\n#endif\n\n\n#ifndef Z7_ST\n\n\ntypedef struct\n{\n  ICompressProgress vt;\n  CMtProgress *mtProgress;\n  UInt64 inSize;\n  UInt64 outSize;\n} CMtProgressThunk;\n\nvoid MtProgressThunk_CreateVTable(CMtProgressThunk *p);\n    \n#define MtProgressThunk_INIT(p) { (p)->inSize = 0; (p)->outSize = 0; }\n\n\nstruct CMtCoder_;\n\n\ntypedef struct\n{\n  struct CMtCoder_ *mtCoder;\n  unsigned index;\n  int stop;\n  Byte *inBuf;\n\n  CAutoResetEvent startEvent;\n  CThread thread;\n} CMtCoderThread;\n\n\ntypedef struct\n{\n  SRes (*Code)(void *p, unsigned coderIndex, unsigned outBufIndex,\n      const Byte *src, size_t srcSize, int finished);\n  SRes (*Write)(void *p, unsigned outBufIndex);\n} IMtCoderCallback2;\n\n\ntypedef struct\n{\n  SRes res;\n  unsigned bufIndex;\n  BoolInt finished;\n} CMtCoderBlock;\n\n\ntypedef struct CMtCoder_\n{\n  /* input variables */\n  \n  size_t blockSize;        /* size of input block */\n  unsigned numThreadsMax;\n  unsigned numThreadGroups;\n  UInt64 expectedDataSize;\n\n  ISeqInStreamPtr inStream;\n  const Byte *inData;\n  size_t inDataSize;\n\n  ICompressProgressPtr progress;\n  ISzAllocPtr allocBig;\n\n  IMtCoderCallback2 *mtCallback;\n  void *mtCallbackObject;\n\n  \n  /* internal variables */\n  \n  size_t allocatedBufsSize;\n\n  CAutoResetEvent readEvent;\n  CSemaphore blocksSemaphore;\n\n  BoolInt stopReading;\n  SRes readRes;\n\n  #ifdef MTCODER_USE_WRITE_THREAD\n    CAutoResetEvent writeEvents[MTCODER_BLOCKS_MAX];\n  #else\n    CAutoResetEvent finishedEvent;\n    SRes writeRes;\n    unsigned writeIndex;\n    Byte ReadyBlocks[MTCODER_BLOCKS_MAX];\n    LONG numFinishedThreads;\n  #endif\n\n  unsigned numStartedThreadsLimit;\n  unsigned numStartedThreads;\n\n  unsigned numBlocksMax;\n  unsigned blockIndex;\n  UInt64 readProcessed;\n\n  CCriticalSection cs;\n\n  unsigned freeBlockHead;\n  unsigned freeBlockList[MTCODER_BLOCKS_MAX];\n\n  CMtProgress mtProgress;\n  CMtCoderBlock blocks[MTCODER_BLOCKS_MAX];\n  CMtCoderThread threads[MTCODER_THREADS_MAX];\n\n  CThreadNextGroup nextGroup;\n} CMtCoder;\n\n\nvoid MtCoder_Construct(CMtCoder *p);\nvoid MtCoder_Destruct(CMtCoder *p);\nSRes MtCoder_Code(CMtCoder *p);\n\n\n#endif\n\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/MtDec.c",
    "content": "﻿/* MtDec.c -- Multi-thread Decoder\n2024-02-20 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n// #define SHOW_DEBUG_INFO\n\n// #include <stdio.h>\n#include <string.h>\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#include \"MtDec.h\"\n\n#ifndef Z7_ST\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#define PRF_STR_INT(s, d) PRF(printf(\"\\n\" s \" %d\\n\", (unsigned)d))\n\nvoid MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress)\n{\n  p->progress = progress;\n  p->res = SZ_OK;\n  p->totalInSize = 0;\n  p->totalOutSize = 0;\n}\n\n\nSRes MtProgress_Progress_ST(CMtProgress *p)\n{\n  if (p->res == SZ_OK && p->progress)\n    if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)\n      p->res = SZ_ERROR_PROGRESS;\n  return p->res;\n}\n\n\nSRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize)\n{\n  SRes res;\n  CriticalSection_Enter(&p->cs);\n  \n  p->totalInSize += inSize;\n  p->totalOutSize += outSize;\n  if (p->res == SZ_OK && p->progress)\n    if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)\n      p->res = SZ_ERROR_PROGRESS;\n  res = p->res;\n  \n  CriticalSection_Leave(&p->cs);\n  return res;\n}\n\n\nSRes MtProgress_GetError(CMtProgress *p)\n{\n  SRes res;\n  CriticalSection_Enter(&p->cs);\n  res = p->res;\n  CriticalSection_Leave(&p->cs);\n  return res;\n}\n\n\nvoid MtProgress_SetError(CMtProgress *p, SRes res)\n{\n  CriticalSection_Enter(&p->cs);\n  if (p->res == SZ_OK)\n    p->res = res;\n  CriticalSection_Leave(&p->cs);\n}\n\n\n#define RINOK_THREAD(x) RINOK_WRes(x)\n\n\nstruct CMtDecBufLink_\n{\n  struct CMtDecBufLink_ *next;\n  void *pad[3];\n};\n\ntypedef struct CMtDecBufLink_ CMtDecBufLink;\n\n#define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink)\n#define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET)\n\n\n\nstatic THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp);\n\n\nstatic WRes MtDecThread_CreateEvents(CMtDecThread *t)\n{\n  WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->canWrite);\n  if (wres == 0)\n  {\n    wres = AutoResetEvent_OptCreate_And_Reset(&t->canRead);\n    if (wres == 0)\n      return SZ_OK;\n  }\n  return wres;\n}\n\n\nstatic SRes MtDecThread_CreateAndStart(CMtDecThread *t)\n{\n  WRes wres = MtDecThread_CreateEvents(t);\n  // wres = 17; // for test\n  if (wres == 0)\n  {\n    if (Thread_WasCreated(&t->thread))\n      return SZ_OK;\n    wres = Thread_Create(&t->thread, MtDec_ThreadFunc, t);\n    if (wres == 0)\n      return SZ_OK;\n  }\n  return MY_SRes_HRESULT_FROM_WRes(wres);\n}\n\n\nvoid MtDecThread_FreeInBufs(CMtDecThread *t)\n{\n  if (t->inBuf)\n  {\n    void *link = t->inBuf;\n    t->inBuf = NULL;\n    do\n    {\n      void *next = ((CMtDecBufLink *)link)->next;\n      ISzAlloc_Free(t->mtDec->alloc, link);\n      link = next;\n    }\n    while (link);\n  }\n}\n\n\nstatic void MtDecThread_CloseThread(CMtDecThread *t)\n{\n  if (Thread_WasCreated(&t->thread))\n  {\n    Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */\n    Event_Set(&t->canRead);\n    Thread_Wait_Close(&t->thread);\n  }\n\n  Event_Close(&t->canRead);\n  Event_Close(&t->canWrite);\n}\n\nstatic void MtDec_CloseThreads(CMtDec *p)\n{\n  unsigned i;\n  for (i = 0; i < MTDEC_THREADS_MAX; i++)\n    MtDecThread_CloseThread(&p->threads[i]);\n}\n\nstatic void MtDecThread_Destruct(CMtDecThread *t)\n{\n  MtDecThread_CloseThread(t);\n  MtDecThread_FreeInBufs(t);\n}\n\n\n\nstatic SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, BoolInt *wasInterrupted)\n{\n  SRes res;\n  CriticalSection_Enter(&p->mtProgress.cs);\n  *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);\n  res = p->mtProgress.res;\n  CriticalSection_Leave(&p->mtProgress.cs);\n  return res;\n}\n\nstatic SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, BoolInt *wasInterrupted)\n{\n  SRes res;\n  CriticalSection_Enter(&p->mtProgress.cs);\n\n  p->mtProgress.totalInSize += inSize;\n  p->mtProgress.totalOutSize += outSize;\n  if (p->mtProgress.res == SZ_OK && p->mtProgress.progress)\n    if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK)\n      p->mtProgress.res = SZ_ERROR_PROGRESS;\n\n  *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);\n  res = p->mtProgress.res;\n  \n  CriticalSection_Leave(&p->mtProgress.cs);\n\n  return res;\n}\n\nstatic void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex)\n{\n  CriticalSection_Enter(&p->mtProgress.cs);\n  if (!p->needInterrupt || interruptIndex < p->interruptIndex)\n  {\n    p->interruptIndex = interruptIndex;\n    p->needInterrupt = True;\n  }\n  CriticalSection_Leave(&p->mtProgress.cs);\n}\n\nByte *MtDec_GetCrossBuff(CMtDec *p)\n{\n  Byte *cr = p->crossBlock;\n  if (!cr)\n  {\n    cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);\n    if (!cr)\n      return NULL;\n    p->crossBlock = cr;\n  }\n  return MTDEC__DATA_PTR_FROM_LINK(cr);\n}\n\n\n/*\n  MtDec_ThreadFunc2() returns:\n  0      - in all normal cases (even for stream error or memory allocation error)\n  (!= 0) - WRes error return by system threading function\n*/\n\n// #define MTDEC_ProgessStep (1 << 22)\n#define MTDEC_ProgessStep (1 << 0)\n\nstatic WRes MtDec_ThreadFunc2(CMtDecThread *t)\n{\n  CMtDec *p = t->mtDec;\n\n  PRF_STR_INT(\"MtDec_ThreadFunc2\", t->index)\n\n  // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index);\n\n  for (;;)\n  {\n    SRes res, codeRes;\n    BoolInt wasInterrupted, isAllocError, overflow, finish;\n    SRes threadingErrorSRes;\n    BoolInt needCode, needWrite, needContinue;\n    \n    size_t inDataSize_Start;\n    UInt64 inDataSize;\n    // UInt64 inDataSize_Full;\n    \n    UInt64 blockIndex;\n\n    UInt64 inPrev = 0;\n    UInt64 outPrev = 0;\n    UInt64 inCodePos;\n    UInt64 outCodePos;\n    \n    Byte *afterEndData = NULL;\n    size_t afterEndData_Size = 0;\n    BoolInt afterEndData_IsCross = False;\n\n    BoolInt canCreateNewThread = False;\n    // CMtDecCallbackInfo parse;\n    CMtDecThread *nextThread;\n\n    PRF_STR_INT(\"=============== Event_Wait(&t->canRead)\", t->index)\n\n    RINOK_THREAD(Event_Wait(&t->canRead))\n    if (p->exitThread)\n      return 0;\n\n    PRF_STR_INT(\"after Event_Wait(&t->canRead)\", t->index)\n\n    // if (t->index == 3) return 19; // for test\n\n    blockIndex = p->blockIndex++;\n\n    // PRF(printf(\"\\ncanRead\\n\"))\n\n    res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);\n\n    finish = p->readWasFinished;\n    needCode = False;\n    needWrite = False;\n    isAllocError = False;\n    overflow = False;\n\n    inDataSize_Start = 0;\n    inDataSize = 0;\n    // inDataSize_Full = 0;\n\n    if (res == SZ_OK && !wasInterrupted)\n    {\n      // if (p->inStream)\n      {\n        CMtDecBufLink *prev = NULL;\n        CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;\n        size_t crossSize = p->crossEnd - p->crossStart;\n\n        PRF(printf(\"\\ncrossSize = %d\\n\", crossSize));\n\n        for (;;)\n        {\n          if (!link)\n          {\n            link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);\n            if (!link)\n            {\n              finish = True;\n              // p->allocError_for_Read_BlockIndex = blockIndex;\n              isAllocError = True;\n              break;\n            }\n            link->next = NULL;\n            if (prev)\n            {\n              // static unsigned g_num = 0;\n              // printf(\"\\n%6d : %x\", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev));\n              prev->next = link;\n            }\n            else\n              t->inBuf = (void *)link;\n          }\n\n          {\n            Byte *data = MTDEC__DATA_PTR_FROM_LINK(link);\n            Byte *parseData = data;\n            size_t size;\n\n            if (crossSize != 0)\n            {\n              inDataSize = crossSize;\n              // inDataSize_Full = inDataSize;\n              inDataSize_Start = crossSize;\n              size = crossSize;\n              parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;\n              PRF(printf(\"\\ncross : crossStart = %7d  crossEnd = %7d finish = %1d\",\n                  (int)p->crossStart, (int)p->crossEnd, (int)finish));\n            }\n            else\n            {\n              size = p->inBufSize;\n              \n              res = SeqInStream_ReadMax(p->inStream, data, &size);\n              \n              // size = 10; // test\n\n              inDataSize += size;\n              // inDataSize_Full = inDataSize;\n              if (!prev)\n                inDataSize_Start = size;\n\n              p->readProcessed += size;\n              finish = (size != p->inBufSize);\n              if (finish)\n                p->readWasFinished = True;\n              \n              // res = E_INVALIDARG; // test\n\n              if (res != SZ_OK)\n              {\n                // PRF(printf(\"\\nRead error = %d\\n\", res))\n                // we want to decode all data before error\n                p->readRes = res;\n                // p->readError_BlockIndex = blockIndex;\n                p->readWasFinished = True;\n                finish = True;\n                res = SZ_OK;\n                // break;\n              }\n\n              if (inDataSize - inPrev >= MTDEC_ProgessStep)\n              {\n                res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);\n                if (res != SZ_OK || wasInterrupted)\n                  break;\n                inPrev = inDataSize;\n              }\n            }\n\n            {\n              CMtDecCallbackInfo parse;\n\n              parse.startCall = (prev == NULL);\n              parse.src = parseData;\n              parse.srcSize = size;\n              parse.srcFinished = finish;\n              parse.canCreateNewThread = True;\n\n              PRF(printf(\"\\nParse size = %d\\n\", (unsigned)size));\n\n              p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse);\n\n              PRF(printf(\"   Parse processed = %d, state = %d \\n\", (unsigned)parse.srcSize, (unsigned)parse.state));\n\n              needWrite = True;\n              canCreateNewThread = parse.canCreateNewThread;\n\n              // printf(\"\\n\\n%12I64u %12I64u\", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize);\n              \n              if (\n                  // parseRes != SZ_OK ||\n                  // inDataSize - (size - parse.srcSize) > p->inBlockMax\n                  // ||\n                  parse.state == MTDEC_PARSE_OVERFLOW\n                  // || wasInterrupted\n                  )\n              {\n                // Overflow or Parse error - switch from MT decoding to ST decoding\n                finish = True;\n                overflow = True;\n\n                {\n                  PRF(printf(\"\\n Overflow\"));\n                  // PRF(printf(\"\\nisBlockFinished = %d\", (unsigned)parse.blockWasFinished));\n                  PRF(printf(\"\\n inDataSize = %d\", (unsigned)inDataSize));\n                }\n                \n                if (crossSize != 0)\n                  memcpy(data, parseData, size);\n                p->crossStart = 0;\n                p->crossEnd = 0;\n                break;\n              }\n\n              if (crossSize != 0)\n              {\n                memcpy(data, parseData, parse.srcSize);\n                p->crossStart += parse.srcSize;\n              }\n\n              if (parse.state != MTDEC_PARSE_CONTINUE || finish)\n              {\n                // we don't need to parse in current thread anymore\n\n                if (parse.state == MTDEC_PARSE_END)\n                  finish = True;\n\n                needCode = True;\n                // p->crossFinished = finish;\n\n                if (parse.srcSize == size)\n                {\n                  // full parsed - no cross transfer\n                  p->crossStart = 0;\n                  p->crossEnd = 0;\n                  break;\n                }\n\n                if (parse.state == MTDEC_PARSE_END)\n                {\n                  afterEndData = parseData + parse.srcSize;\n                  afterEndData_Size = size - parse.srcSize;\n                  if (crossSize != 0)\n                    afterEndData_IsCross = True;\n                  // we reduce data size to required bytes (parsed only)\n                  inDataSize -= afterEndData_Size;\n                  if (!prev)\n                    inDataSize_Start = parse.srcSize;\n                  break;\n                }\n\n                {\n                  // partial parsed - need cross transfer\n                  if (crossSize != 0)\n                    inDataSize = parse.srcSize; // it's only parsed now\n                  else\n                  {\n                    // partial parsed - is not in initial cross block - we need to copy new data to cross block\n                    Byte *cr = MtDec_GetCrossBuff(p);\n                    if (!cr)\n                    {\n                      {\n                        PRF(printf(\"\\ncross alloc error error\\n\"));\n                        // res = SZ_ERROR_MEM;\n                        finish = True;\n                        // p->allocError_for_Read_BlockIndex = blockIndex;\n                        isAllocError = True;\n                        break;\n                      }\n                    }\n\n                    {\n                      size_t crSize = size - parse.srcSize;\n                      inDataSize -= crSize;\n                      p->crossEnd = crSize;\n                      p->crossStart = 0;\n                      memcpy(cr, parseData + parse.srcSize, crSize);\n                    }\n                  }\n\n                  // inDataSize_Full = inDataSize;\n                  if (!prev)\n                    inDataSize_Start = parse.srcSize; // it's partial size (parsed only)\n\n                  finish = False;\n                  break;\n                }\n              }\n\n              if (parse.srcSize != size)\n              {\n                res = SZ_ERROR_FAIL;\n                PRF(printf(\"\\nfinished error SZ_ERROR_FAIL = %d\\n\", res));\n                break;\n              }\n            }\n          }\n          \n          prev = link;\n          link = link->next;\n\n          if (crossSize != 0)\n          {\n            crossSize = 0;\n            p->crossStart = 0;\n            p->crossEnd = 0;\n          }\n        }\n      }\n\n      if (res == SZ_OK)\n        res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted);\n    }\n\n    codeRes = SZ_OK;\n\n    if (res == SZ_OK && needCode && !wasInterrupted)\n    {\n      codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index);\n      if (codeRes != SZ_OK)\n      {\n        needCode = False;\n        finish = True;\n        // SZ_ERROR_MEM is expected error here.\n        //   if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later.\n        //   if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding.\n      }\n    }\n    \n    if (res != SZ_OK || wasInterrupted)\n      finish = True;\n    \n    nextThread = NULL;\n    threadingErrorSRes = SZ_OK;\n\n    if (!finish)\n    {\n      if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread)\n      {\n        SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]);\n        if (res2 == SZ_OK)\n        {\n          // if (p->numStartedThreads % 1000 == 0) PRF(printf(\"\\n numStartedThreads=%d\\n\", p->numStartedThreads));\n          p->numStartedThreads++;\n        }\n        else\n        {\n          PRF(printf(\"\\nERROR: numStartedThreads=%d\\n\", p->numStartedThreads));\n          if (p->numStartedThreads == 1)\n          {\n            // if only one thread is possible, we leave muti-threading code\n            finish = True;\n            needCode = False;\n            threadingErrorSRes = res2;\n          }\n          else\n            p->numStartedThreads_Limit = p->numStartedThreads;\n        }\n      }\n      \n      if (!finish)\n      {\n        unsigned nextIndex = t->index + 1;\n        nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex];\n        RINOK_THREAD(Event_Set(&nextThread->canRead))\n        // We have started executing for new iteration (with next thread)\n        // And that next thread now is responsible for possible exit from decoding (threading_code)\n      }\n    }\n\n    // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite)\n    // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case\n    // if (  finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block):\n    //   - if (needContinue) after Write(&needContinue), we restore decoding with new iteration\n    //   - otherwise we stop decoding and exit from MtDec_ThreadFunc2()\n\n    // Don't change (finish) variable in the further code\n\n\n    // ---------- CODE ----------\n\n    inPrev = 0;\n    outPrev = 0;\n    inCodePos = 0;\n    outCodePos = 0;\n\n    if (res == SZ_OK && needCode && codeRes == SZ_OK)\n    {\n      BoolInt isStartBlock = True;\n      CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;\n\n      for (;;)\n      {\n        size_t inSize;\n        int stop;\n\n        if (isStartBlock)\n          inSize = inDataSize_Start;\n        else\n        {\n          UInt64 rem = inDataSize - inCodePos;\n          inSize = p->inBufSize;\n          if (inSize > rem)\n            inSize = (size_t)rem;\n        }\n\n        inCodePos += inSize;\n        stop = True;\n\n        codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index,\n            (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize,\n            (inCodePos == inDataSize), // srcFinished\n            &inCodePos, &outCodePos, &stop);\n        \n        if (codeRes != SZ_OK)\n        {\n          PRF(printf(\"\\nCode Interrupt error = %x\\n\", codeRes));\n          // we interrupt only later blocks\n          MtDec_Interrupt(p, blockIndex);\n          break;\n        }\n\n        if (stop || inCodePos == inDataSize)\n          break;\n  \n        {\n          const UInt64 inDelta = inCodePos - inPrev;\n          const UInt64 outDelta = outCodePos - outPrev;\n          if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep)\n          {\n            // Sleep(1);\n            res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted);\n            if (res != SZ_OK || wasInterrupted)\n              break;\n            inPrev = inCodePos;\n            outPrev = outCodePos;\n          }\n        }\n\n        link = link->next;\n        isStartBlock = False;\n      }\n    }\n\n\n    // ---------- WRITE ----------\n   \n    RINOK_THREAD(Event_Wait(&t->canWrite))\n\n  {\n    BoolInt isErrorMode = False;\n    BoolInt canRecode = True;\n    BoolInt needWriteToStream = needWrite;\n\n    if (p->exitThread) return 0; // it's never executed in normal cases\n\n    if (p->wasInterrupted)\n      wasInterrupted = True;\n    else\n    {\n      if (codeRes != SZ_OK) // || !needCode // check it !!!\n      {\n        p->wasInterrupted = True;\n        p->codeRes = codeRes;\n        if (codeRes == SZ_ERROR_MEM)\n          isAllocError = True;\n      }\n      \n      if (threadingErrorSRes)\n      {\n        p->wasInterrupted = True;\n        p->threadingErrorSRes = threadingErrorSRes;\n        needWriteToStream = False;\n      }\n      if (isAllocError)\n      {\n        p->wasInterrupted = True;\n        p->isAllocError = True;\n        needWriteToStream = False;\n      }\n      if (overflow)\n      {\n        p->wasInterrupted = True;\n        p->overflow = True;\n        needWriteToStream = False;\n      }\n    }\n\n    if (needCode)\n    {\n      if (wasInterrupted)\n      {\n        inCodePos = 0;\n        outCodePos = 0;\n      }\n      {\n        const UInt64 inDelta = inCodePos - inPrev;\n        const UInt64 outDelta = outCodePos - outPrev;\n        // if (inDelta != 0 || outDelta != 0)\n        res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta);\n      }\n    }\n\n    needContinue = (!finish);\n\n    // if (res == SZ_OK && needWrite && !wasInterrupted)\n    if (needWrite)\n    {\n      // p->inProcessed += inCodePos;\n\n      PRF(printf(\"\\n--Write afterSize = %d\\n\", (unsigned)afterEndData_Size));\n\n      res = p->mtCallback->Write(p->mtCallbackObject, t->index,\n          res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite\n          afterEndData, afterEndData_Size, afterEndData_IsCross,\n          &needContinue,\n          &canRecode);\n\n      // res = SZ_ERROR_FAIL; // for test\n\n      PRF(printf(\"\\nAfter Write needContinue = %d\\n\", (unsigned)needContinue));\n      PRF(printf(\"\\nprocessed = %d\\n\", (unsigned)p->inProcessed));\n\n      if (res != SZ_OK)\n      {\n        PRF(printf(\"\\nWrite error = %d\\n\", res));\n        isErrorMode = True;\n        p->wasInterrupted = True;\n      }\n      if (res != SZ_OK\n          || (!needContinue && !finish))\n      {\n        PRF(printf(\"\\nWrite Interrupt error = %x\\n\", res));\n        MtDec_Interrupt(p, blockIndex);\n      }\n    }\n\n    if (canRecode)\n    if (!needCode\n        || res != SZ_OK\n        || p->wasInterrupted\n        || codeRes != SZ_OK\n        || wasInterrupted\n        || p->numFilledThreads != 0\n        || isErrorMode)\n    {\n      if (p->numFilledThreads == 0)\n        p->filledThreadStart = t->index;\n      if (inDataSize != 0 || !finish)\n      {\n        t->inDataSize_Start = inDataSize_Start;\n        t->inDataSize = inDataSize;\n        p->numFilledThreads++;\n      }\n      PRF(printf(\"\\np->numFilledThreads = %d\\n\", p->numFilledThreads));\n      PRF(printf(\"p->filledThreadStart = %d\\n\", p->filledThreadStart));\n    }\n\n    if (!finish)\n    {\n      RINOK_THREAD(Event_Set(&nextThread->canWrite))\n    }\n    else\n    {\n      if (needContinue)\n      {\n        // we restore decoding with new iteration\n        RINOK_THREAD(Event_Set(&p->threads[0].canWrite))\n      }\n      else\n      {\n        // we exit from decoding\n        if (t->index == 0)\n          return SZ_OK;\n        p->exitThread = True;\n      }\n      RINOK_THREAD(Event_Set(&p->threads[0].canRead))\n    }\n  }\n  }\n}\n\n#ifdef _WIN32\n#define USE_ALLOCA\n#endif\n\n#ifdef USE_ALLOCA\n#ifdef _WIN32\n#include <malloc.h>\n#else\n#include <stdlib.h>\n#endif\n#endif\n\n\ntypedef\n  #ifdef _WIN32\n    UINT_PTR\n  #elif 1\n    uintptr_t\n  #else\n    ptrdiff_t\n  #endif\n    MY_uintptr_t;\n\nstatic THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)\n{\n  WRes res;\n\n  CMtDecThread *t = (CMtDecThread *)pp;\n  CMtDec *p;\n\n  // fprintf(stdout, \"\\n%d = %p\\n\", t->index, &t);\n\n  res = MtDec_ThreadFunc2(t);\n  p = t->mtDec;\n  if (res == 0)\n    return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)p->exitThreadWRes;\n  {\n    // it's unexpected situation for some threading function error\n    if (p->exitThreadWRes == 0)\n      p->exitThreadWRes = res;\n    PRF(printf(\"\\nthread exit error = %d\\n\", res));\n    p->exitThread = True;\n    Event_Set(&p->threads[0].canRead);\n    Event_Set(&p->threads[0].canWrite);\n    MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res));\n  }\n  return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)res;\n}\n\nstatic Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp)\n{\n  #ifdef USE_ALLOCA\n  CMtDecThread *t = (CMtDecThread *)pp;\n  // fprintf(stderr, \"\\n%d = %p - before\", t->index, &t);\n  t->allocaPtr = alloca(t->index * 128);\n  #endif\n  return MtDec_ThreadFunc1(pp);\n}\n\n\nint MtDec_PrepareRead(CMtDec *p)\n{\n  if (p->crossBlock && p->crossStart == p->crossEnd)\n  {\n    ISzAlloc_Free(p->alloc, p->crossBlock);\n    p->crossBlock = NULL;\n  }\n    \n  {\n    unsigned i;\n    for (i = 0; i < MTDEC_THREADS_MAX; i++)\n      if (i > p->numStartedThreads\n          || p->numFilledThreads <=\n            (i >= p->filledThreadStart ?\n              i - p->filledThreadStart :\n              i + p->numStartedThreads - p->filledThreadStart))\n        MtDecThread_FreeInBufs(&p->threads[i]);\n  }\n\n  return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd);\n}\n\n    \nconst Byte *MtDec_Read(CMtDec *p, size_t *inLim)\n{\n  while (p->numFilledThreads != 0)\n  {\n    CMtDecThread *t = &p->threads[p->filledThreadStart];\n    \n    if (*inLim != 0)\n    {\n      {\n        void *link = t->inBuf;\n        void *next = ((CMtDecBufLink *)link)->next;\n        ISzAlloc_Free(p->alloc, link);\n        t->inBuf = next;\n      }\n      \n      if (t->inDataSize == 0)\n      {\n        MtDecThread_FreeInBufs(t);\n        if (--p->numFilledThreads == 0)\n          break;\n        if (++p->filledThreadStart == p->numStartedThreads)\n          p->filledThreadStart = 0;\n        t = &p->threads[p->filledThreadStart];\n      }\n    }\n    \n    {\n      size_t lim = t->inDataSize_Start;\n      if (lim != 0)\n        t->inDataSize_Start = 0;\n      else\n      {\n        UInt64 rem = t->inDataSize;\n        lim = p->inBufSize;\n        if (lim > rem)\n          lim = (size_t)rem;\n      }\n      t->inDataSize -= lim;\n      *inLim = lim;\n      return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf);\n    }\n  }\n\n  {\n    size_t crossSize = p->crossEnd - p->crossStart;\n    if (crossSize != 0)\n    {\n      const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;\n      *inLim = crossSize;\n      p->crossStart = 0;\n      p->crossEnd = 0;\n      return data;\n    }\n    *inLim = 0;\n    if (p->crossBlock)\n    {\n      ISzAlloc_Free(p->alloc, p->crossBlock);\n      p->crossBlock = NULL;\n    }\n    return NULL;\n  }\n}\n\n\nvoid MtDec_Construct(CMtDec *p)\n{\n  unsigned i;\n  \n  p->inBufSize = (size_t)1 << 18;\n\n  p->numThreadsMax = 0;\n\n  p->inStream = NULL;\n  \n  // p->inData = NULL;\n  // p->inDataSize = 0;\n\n  p->crossBlock = NULL;\n  p->crossStart = 0;\n  p->crossEnd = 0;\n\n  p->numFilledThreads = 0;\n\n  p->progress = NULL;\n  p->alloc = NULL;\n\n  p->mtCallback = NULL;\n  p->mtCallbackObject = NULL;\n\n  p->allocatedBufsSize = 0;\n\n  for (i = 0; i < MTDEC_THREADS_MAX; i++)\n  {\n    CMtDecThread *t = &p->threads[i];\n    t->mtDec = p;\n    t->index = i;\n    t->inBuf = NULL;\n    Event_Construct(&t->canRead);\n    Event_Construct(&t->canWrite);\n    Thread_CONSTRUCT(&t->thread)\n  }\n\n  // Event_Construct(&p->finishedEvent);\n\n  CriticalSection_Init(&p->mtProgress.cs);\n}\n\n\nstatic void MtDec_Free(CMtDec *p)\n{\n  unsigned i;\n\n  p->exitThread = True;\n\n  for (i = 0; i < MTDEC_THREADS_MAX; i++)\n    MtDecThread_Destruct(&p->threads[i]);\n\n  // Event_Close(&p->finishedEvent);\n\n  if (p->crossBlock)\n  {\n    ISzAlloc_Free(p->alloc, p->crossBlock);\n    p->crossBlock = NULL;\n  }\n}\n\n\nvoid MtDec_Destruct(CMtDec *p)\n{\n  MtDec_Free(p);\n\n  CriticalSection_Delete(&p->mtProgress.cs);\n}\n\n\nSRes MtDec_Code(CMtDec *p)\n{\n  unsigned i;\n\n  p->inProcessed = 0;\n\n  p->blockIndex = 1; // it must be larger than not_defined index (0)\n  p->isAllocError = False;\n  p->overflow = False;\n  p->threadingErrorSRes = SZ_OK;\n\n  p->needContinue = True;\n\n  p->readWasFinished = False;\n  p->needInterrupt = False;\n  p->interruptIndex = (UInt64)(Int64)-1;\n\n  p->readProcessed = 0;\n  p->readRes = SZ_OK;\n  p->codeRes = SZ_OK;\n  p->wasInterrupted = False;\n\n  p->crossStart = 0;\n  p->crossEnd = 0;\n\n  p->filledThreadStart = 0;\n  p->numFilledThreads = 0;\n\n  {\n    unsigned numThreads = p->numThreadsMax;\n    if (numThreads > MTDEC_THREADS_MAX)\n      numThreads = MTDEC_THREADS_MAX;\n    p->numStartedThreads_Limit = numThreads;\n    p->numStartedThreads = 0;\n  }\n\n  if (p->inBufSize != p->allocatedBufsSize)\n  {\n    for (i = 0; i < MTDEC_THREADS_MAX; i++)\n    {\n      CMtDecThread *t = &p->threads[i];\n      if (t->inBuf)\n        MtDecThread_FreeInBufs(t);\n    }\n    if (p->crossBlock)\n    {\n      ISzAlloc_Free(p->alloc, p->crossBlock);\n      p->crossBlock = NULL;\n    }\n\n    p->allocatedBufsSize = p->inBufSize;\n  }\n\n  MtProgress_Init(&p->mtProgress, p->progress);\n\n  // RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent))\n  p->exitThread = False;\n  p->exitThreadWRes = 0;\n\n  {\n    WRes wres;\n    SRes sres;\n    CMtDecThread *nextThread = &p->threads[p->numStartedThreads++];\n    // wres = MtDecThread_CreateAndStart(nextThread);\n    wres = MtDecThread_CreateEvents(nextThread);\n    if (wres == 0) { wres = Event_Set(&nextThread->canWrite);\n    if (wres == 0) { wres = Event_Set(&nextThread->canRead);\n    if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread);\n    wres = (WRes)(MY_uintptr_t)res;\n    if (wres != 0)\n    {\n      p->needContinue = False;\n      MtDec_CloseThreads(p);\n    }}}}\n\n    // wres = 17; // for test\n    // wres = Event_Wait(&p->finishedEvent);\n\n    sres = MY_SRes_HRESULT_FROM_WRes(wres);\n\n    if (sres != 0)\n      p->threadingErrorSRes = sres;\n\n    if (\n        // wres == 0\n        // wres != 0\n        // || p->mtc.codeRes == SZ_ERROR_MEM\n        p->isAllocError\n        || p->threadingErrorSRes != SZ_OK\n        || p->overflow)\n    {\n      // p->needContinue = True;\n    }\n    else\n      p->needContinue = False;\n    \n    if (p->needContinue)\n      return SZ_OK;\n\n    // if (sres != SZ_OK)\n    return sres;\n    // return SZ_ERROR_FAIL;\n  }\n}\n\n#endif\n\n#undef PRF\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/MtDec.h",
    "content": "﻿/* MtDec.h -- Multi-thread Decoder\n2023-04-02 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_MT_DEC_H\n#define ZIP7_INC_MT_DEC_H\n\n#include \"7zTypes.h\"\n\n#ifndef Z7_ST\n#include \"Threads.h\"\n#endif\n\nEXTERN_C_BEGIN\n\n#ifndef Z7_ST\n\n#ifndef Z7_ST\n  #define MTDEC_THREADS_MAX 32\n#else\n  #define MTDEC_THREADS_MAX 1\n#endif\n\n\ntypedef struct\n{\n  ICompressProgressPtr progress;\n  SRes res;\n  UInt64 totalInSize;\n  UInt64 totalOutSize;\n  CCriticalSection cs;\n} CMtProgress;\n\nvoid MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress);\nSRes MtProgress_Progress_ST(CMtProgress *p);\nSRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize);\nSRes MtProgress_GetError(CMtProgress *p);\nvoid MtProgress_SetError(CMtProgress *p, SRes res);\n\nstruct CMtDec;\n\ntypedef struct\n{\n  struct CMtDec_ *mtDec;\n  unsigned index;\n  void *inBuf;\n\n  size_t inDataSize_Start; // size of input data in start block\n  UInt64 inDataSize;       // total size of input data in all blocks\n\n  CThread thread;\n  CAutoResetEvent canRead;\n  CAutoResetEvent canWrite;\n  void  *allocaPtr;\n} CMtDecThread;\n\nvoid MtDecThread_FreeInBufs(CMtDecThread *t);\n\n\ntypedef enum\n{\n  MTDEC_PARSE_CONTINUE, // continue this block with more input data\n  MTDEC_PARSE_OVERFLOW, // MT buffers overflow, need switch to single-thread\n  MTDEC_PARSE_NEW,      // new block\n  MTDEC_PARSE_END       // end of block threading. But we still can return to threading after Write(&needContinue)\n} EMtDecParseState;\n\ntypedef struct\n{\n  // in\n  int startCall;\n  const Byte *src;\n  size_t srcSize;\n      // in  : (srcSize == 0) is allowed\n      // out : it's allowed to return less that actually was used ?\n  int srcFinished;\n\n  // out\n  EMtDecParseState state;\n  BoolInt canCreateNewThread;\n  UInt64 outPos; // check it (size_t)\n} CMtDecCallbackInfo;\n\n\ntypedef struct\n{\n  void (*Parse)(void *p, unsigned coderIndex, CMtDecCallbackInfo *ci);\n  \n  // PreCode() and Code():\n  // (SRes_return_result != SZ_OK) means stop decoding, no need another blocks\n  SRes (*PreCode)(void *p, unsigned coderIndex);\n  SRes (*Code)(void *p, unsigned coderIndex,\n      const Byte *src, size_t srcSize, int srcFinished,\n      UInt64 *inCodePos, UInt64 *outCodePos, int *stop);\n  // stop - means stop another Code calls\n\n\n  /* Write() must be called, if Parse() was called\n      set (needWrite) if\n      {\n         && (was not interrupted by progress)\n         && (was not interrupted in previous block)\n      }\n\n    out:\n      if (*needContinue), decoder still need to continue decoding with new iteration,\n         even after MTDEC_PARSE_END\n      if (*canRecode), we didn't flush current block data, so we still can decode current block later.\n  */\n  SRes (*Write)(void *p, unsigned coderIndex,\n      BoolInt needWriteToStream,\n      const Byte *src, size_t srcSize, BoolInt isCross,\n      // int srcFinished,\n      BoolInt *needContinue,\n      BoolInt *canRecode);\n\n} IMtDecCallback2;\n\n\n\ntypedef struct CMtDec_\n{\n  /* input variables */\n  \n  size_t inBufSize;        /* size of input block */\n  unsigned numThreadsMax;\n  // size_t inBlockMax;\n  unsigned numThreadsMax_2;\n\n  ISeqInStreamPtr inStream;\n  // const Byte *inData;\n  // size_t inDataSize;\n\n  ICompressProgressPtr progress;\n  ISzAllocPtr alloc;\n\n  IMtDecCallback2 *mtCallback;\n  void *mtCallbackObject;\n\n  \n  /* internal variables */\n  \n  size_t allocatedBufsSize;\n\n  BoolInt exitThread;\n  WRes exitThreadWRes;\n\n  UInt64 blockIndex;\n  BoolInt isAllocError;\n  BoolInt overflow;\n  SRes threadingErrorSRes;\n\n  BoolInt needContinue;\n\n  // CAutoResetEvent finishedEvent;\n\n  SRes readRes;\n  SRes codeRes;\n\n  BoolInt wasInterrupted;\n\n  unsigned numStartedThreads_Limit;\n  unsigned numStartedThreads;\n\n  Byte *crossBlock;\n  size_t crossStart;\n  size_t crossEnd;\n  UInt64 readProcessed;\n  BoolInt readWasFinished;\n  UInt64 inProcessed;\n\n  unsigned filledThreadStart;\n  unsigned numFilledThreads;\n\n  #ifndef Z7_ST\n  BoolInt needInterrupt;\n  UInt64 interruptIndex;\n  CMtProgress mtProgress;\n  CMtDecThread threads[MTDEC_THREADS_MAX];\n  #endif\n} CMtDec;\n\n\nvoid MtDec_Construct(CMtDec *p);\nvoid MtDec_Destruct(CMtDec *p);\n\n/*\nMtDec_Code() returns:\n  SZ_OK - in most cases\n  MY_SRes_HRESULT_FROM_WRes(WRes_error) - in case of unexpected error in threading function\n*/\n  \nSRes MtDec_Code(CMtDec *p);\nByte *MtDec_GetCrossBuff(CMtDec *p);\n\nint MtDec_PrepareRead(CMtDec *p);\nconst Byte *MtDec_Read(CMtDec *p, size_t *inLim);\n\n#endif\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd.h",
    "content": "﻿/* Ppmd.h -- PPMD codec common code\n2023-03-05 : Igor Pavlov : Public domain\nThis code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */\n\n#ifndef ZIP7_INC_PPMD_H\n#define ZIP7_INC_PPMD_H\n\n#include \"CpuArch.h\"\n\nEXTERN_C_BEGIN\n\n#if defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 4)\n/*\n   PPMD code always uses 32-bit internal fields in PPMD structures to store internal references in main block.\n   if (PPMD_32BIT is     defined), the PPMD code stores internal pointers to 32-bit reference fields.\n   if (PPMD_32BIT is NOT defined), the PPMD code stores internal UInt32 offsets to reference fields.\n   if (pointer size is 64-bit), then (PPMD_32BIT) mode is not allowed,\n   if (pointer size is 32-bit), then (PPMD_32BIT) mode is optional,\n     and it's allowed to disable PPMD_32BIT mode even if pointer is 32-bit.\n   PPMD code works slightly faster in (PPMD_32BIT) mode.\n*/\n  #define PPMD_32BIT\n#endif\n\n#define PPMD_INT_BITS 7\n#define PPMD_PERIOD_BITS 7\n#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS))\n\n#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift))\n#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2)\n#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob))\n#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob))\n\n#define PPMD_N1 4\n#define PPMD_N2 4\n#define PPMD_N3 4\n#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4)\n#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4)\n\nMY_CPU_pragma_pack_push_1\n/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */\n\n/* SEE-contexts for PPM-contexts with masked symbols */\ntypedef struct\n{\n  UInt16 Summ; /* Freq */\n  Byte Shift;  /* Speed of Freq change; low Shift is for fast change */\n  Byte Count;  /* Count to next change of Shift */\n} CPpmd_See;\n\n#define Ppmd_See_UPDATE(p) \\\n  { if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \\\n    { (p)->Summ = (UInt16)((p)->Summ << 1); \\\n      (p)->Count = (Byte)(3 << (p)->Shift++); }}\n\n\ntypedef struct\n{\n  Byte Symbol;\n  Byte Freq;\n  UInt16 Successor_0;\n  UInt16 Successor_1;\n} CPpmd_State;\n\ntypedef struct CPpmd_State2_\n{\n  Byte Symbol;\n  Byte Freq;\n} CPpmd_State2;\n\ntypedef struct CPpmd_State4_\n{\n  UInt16 Successor_0;\n  UInt16 Successor_1;\n} CPpmd_State4;\n\nMY_CPU_pragma_pop\n\n/*\n   PPMD code can write full CPpmd_State structure data to CPpmd*_Context\n      at (byte offset = 2) instead of some fields of original CPpmd*_Context structure.\n   \n   If we use pointers to different types, but that point to shared\n   memory space, we can have aliasing problem (strict aliasing).\n   \n   XLC compiler in -O2 mode can change the order of memory write instructions\n   in relation to read instructions, if we have use pointers to different types.\n   \n   To solve that aliasing problem we use combined CPpmd*_Context structure\n   with unions that contain the fields from both structures:\n   the original CPpmd*_Context and CPpmd_State.\n   So we can access the fields from both structures via one pointer,\n   and the compiler doesn't change the order of write instructions\n   in relation to read instructions.\n\n   If we don't use memory write instructions to shared memory in\n   some local code, and we use only reading instructions (read only),\n   then probably it's safe to use pointers to different types for reading.\n*/\n  \n\n\n#ifdef PPMD_32BIT\n\n  #define Ppmd_Ref_Type(type)   type *\n  #define Ppmd_GetRef(p, ptr)   (ptr)\n  #define Ppmd_GetPtr(p, ptr)   (ptr)\n  #define Ppmd_GetPtr_Type(p, ptr, note_type) (ptr)\n\n#else\n\n  #define Ppmd_Ref_Type(type)   UInt32\n  #define Ppmd_GetRef(p, ptr)   ((UInt32)((Byte *)(ptr) - (p)->Base))\n  #define Ppmd_GetPtr(p, offs)  ((void *)((p)->Base + (offs)))\n  #define Ppmd_GetPtr_Type(p, offs, type) ((type *)Ppmd_GetPtr(p, offs))\n\n#endif // PPMD_32BIT\n\n\ntypedef Ppmd_Ref_Type(CPpmd_State) CPpmd_State_Ref;\ntypedef Ppmd_Ref_Type(void)        CPpmd_Void_Ref;\ntypedef Ppmd_Ref_Type(Byte)        CPpmd_Byte_Ref;\n\n\n/*\n#ifdef MY_CPU_LE_UNALIGN\n// the unaligned 32-bit access latency can be too large, if the data is not in L1 cache.\n#define Ppmd_GET_SUCCESSOR(p) ((CPpmd_Void_Ref)*(const UInt32 *)(const void *)&(p)->Successor_0)\n#define Ppmd_SET_SUCCESSOR(p, v) *(UInt32 *)(void *)(void *)&(p)->Successor_0 = (UInt32)(v)\n\n#else\n*/\n\n/*\n   We can write 16-bit halves to 32-bit (Successor) field in any selected order.\n   But the native order is more consistent way.\n   So we use the native order, if LE/BE order can be detected here at compile time.\n*/\n\n#ifdef MY_CPU_BE\n\n  #define Ppmd_GET_SUCCESSOR(p) \\\n    ( (CPpmd_Void_Ref) (((UInt32)(p)->Successor_0 << 16) | (p)->Successor_1) )\n\n  #define Ppmd_SET_SUCCESSOR(p, v) { \\\n    (p)->Successor_0 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); \\\n    (p)->Successor_1 = (UInt16)((UInt32)(v) /* & 0xFFFF */); }\n\n#else\n\n  #define Ppmd_GET_SUCCESSOR(p) \\\n    ( (CPpmd_Void_Ref) ((p)->Successor_0 | ((UInt32)(p)->Successor_1 << 16)) )\n\n  #define Ppmd_SET_SUCCESSOR(p, v) { \\\n    (p)->Successor_0 = (UInt16)((UInt32)(v) /* & 0xFFFF */); \\\n    (p)->Successor_1 = (UInt16)(((UInt32)(v) >> 16) /* & 0xFFFF */); }\n\n#endif\n\n// #endif\n\n\n#define PPMD_SetAllBitsIn256Bytes(p) \\\n  { size_t z; for (z = 0; z < 256 / sizeof(p[0]); z += 8) { \\\n  p[z+7] = p[z+6] = p[z+5] = p[z+4] = p[z+3] = p[z+2] = p[z+1] = p[z+0] = ~(size_t)0; }}\n\nEXTERN_C_END\n \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd7.c",
    "content": "﻿/* Ppmd7.c -- PPMdH codec\n2023-09-07 : Igor Pavlov : Public domain\nThis code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n#include \"Ppmd7.h\"\n\n/* define PPMD7_ORDER_0_SUPPPORT to suport order-0 mode, unsupported by orignal PPMd var.H. code */\n// #define PPMD7_ORDER_0_SUPPPORT\n \nMY_ALIGN(16)\nstatic const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };\nMY_ALIGN(16)\nstatic const UInt16 PPMD7_kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};\n\n#define MAX_FREQ 124\n#define UNIT_SIZE 12\n\n#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)\n#define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1])\n#define I2U(indx) ((unsigned)p->Indx2Units[indx])\n#define I2U_UInt16(indx) ((UInt16)p->Indx2Units[indx])\n\n#define REF(ptr) Ppmd_GetRef(p, ptr)\n\n#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))\n\n#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))\n#define STATS(ctx) Ppmd7_GetStats(p, ctx)\n#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx)\n#define SUFFIX(ctx) CTX((ctx)->Suffix)\n\ntypedef CPpmd7_Context * PPMD7_CTX_PTR;\n\nstruct CPpmd7_Node_;\n\ntypedef Ppmd_Ref_Type(struct CPpmd7_Node_) CPpmd7_Node_Ref;\n\ntypedef struct CPpmd7_Node_\n{\n  UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */\n  UInt16 NU;\n  CPpmd7_Node_Ref Next; /* must be at offset >= 4 */\n  CPpmd7_Node_Ref Prev;\n} CPpmd7_Node;\n\n#define NODE(r)  Ppmd_GetPtr_Type(p, r, CPpmd7_Node)\n\nvoid Ppmd7_Construct(CPpmd7 *p)\n{\n  unsigned i, k, m;\n\n  p->Base = NULL;\n\n  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)\n  {\n    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);\n    do { p->Units2Indx[k++] = (Byte)i; } while (--step);\n    p->Indx2Units[i] = (Byte)k;\n  }\n\n  p->NS2BSIndx[0] = (0 << 1);\n  p->NS2BSIndx[1] = (1 << 1);\n  memset(p->NS2BSIndx + 2, (2 << 1), 9);\n  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);\n\n  for (i = 0; i < 3; i++)\n    p->NS2Indx[i] = (Byte)i;\n\n  for (m = i, k = 1; i < 256; i++)\n  {\n    p->NS2Indx[i] = (Byte)m;\n    if (--k == 0)\n      k = (++m) - 2;\n  }\n\n  memcpy(p->ExpEscape, PPMD7_kExpEscape, 16);\n}\n\n\nvoid Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->Base);\n  p->Size = 0;\n  p->Base = NULL;\n}\n\n\nBoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc)\n{\n  if (!p->Base || p->Size != size)\n  {\n    Ppmd7_Free(p, alloc);\n    p->AlignOffset = (4 - size) & 3;\n    if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL)\n      return False;\n    p->Size = size;\n  }\n  return True;\n}\n\n\n\n// ---------- Internal Memory Allocator ----------\n\n/* We can use CPpmd7_Node in list of free units (as in Ppmd8)\n   But we still need one additional list walk pass in Ppmd7_GlueFreeBlocks().\n   So we use simple CPpmd_Void_Ref instead of CPpmd7_Node in Ppmd7_InsertNode() / Ppmd7_RemoveNode()\n*/\n\n#define EMPTY_NODE 0\n\n\nstatic void Ppmd7_InsertNode(CPpmd7 *p, void *node, unsigned indx)\n{\n  *((CPpmd_Void_Ref *)node) = p->FreeList[indx];\n  // ((CPpmd7_Node *)node)->Next = (CPpmd7_Node_Ref)p->FreeList[indx];\n\n  p->FreeList[indx] = REF(node);\n\n}\n\n\nstatic void *Ppmd7_RemoveNode(CPpmd7 *p, unsigned indx)\n{\n  CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]);\n  p->FreeList[indx] = *node;\n  // CPpmd7_Node *node = NODE((CPpmd7_Node_Ref)p->FreeList[indx]);\n  // p->FreeList[indx] = node->Next;\n  return node;\n}\n\n\nstatic void Ppmd7_SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx)\n{\n  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);\n  ptr = (Byte *)ptr + U2B(I2U(newIndx));\n  if (I2U(i = U2I(nu)) != nu)\n  {\n    unsigned k = I2U(--i);\n    Ppmd7_InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);\n  }\n  Ppmd7_InsertNode(p, ptr, i);\n}\n\n\n/* we use CPpmd7_Node_Union union to solve XLC -O2 strict pointer aliasing problem */\n\ntypedef union\n{\n  CPpmd7_Node     Node;\n  CPpmd7_Node_Ref NextRef;\n} CPpmd7_Node_Union;\n\n/* Original PPmdH (Ppmd7) code uses doubly linked list in Ppmd7_GlueFreeBlocks()\n   we use single linked list similar to Ppmd8 code */\n\n\nstatic void Ppmd7_GlueFreeBlocks(CPpmd7 *p)\n{\n  /*\n  we use first UInt16 field of 12-bytes UNITs as record type stamp\n    CPpmd_State    { Byte Symbol; Byte Freq; : Freq != 0\n    CPpmd7_Context { UInt16 NumStats;        : NumStats != 0\n    CPpmd7_Node    { UInt16 Stamp            : Stamp == 0 for free record\n                                             : Stamp == 1 for head record and guard\n    Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd7_Context record.\n  */\n  CPpmd7_Node_Ref head, n = 0;\n \n  p->GlueCount = 255;\n\n  \n  /* we set guard NODE at LoUnit */\n  if (p->LoUnit != p->HiUnit)\n    ((CPpmd7_Node *)(void *)p->LoUnit)->Stamp = 1;\n\n  {\n    /* Create list of free blocks.\n       We still need one additional list walk pass before Glue. */\n    unsigned i;\n    for (i = 0; i < PPMD_NUM_INDEXES; i++)\n    {\n      const UInt16 nu = I2U_UInt16(i);\n      CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i];\n      p->FreeList[i] = 0;\n      while (next != 0)\n      {\n        /* Don't change the order of the following commands: */\n        CPpmd7_Node_Union *un = (CPpmd7_Node_Union *)NODE(next);\n        const CPpmd7_Node_Ref tmp = next;\n        next = un->NextRef;\n        un->Node.Stamp = EMPTY_NODE;\n        un->Node.NU = nu;\n        un->Node.Next = n;\n        n = tmp;\n      }\n    }\n  }\n\n  head = n;\n  /* Glue and Fill must walk the list in same direction */\n  {\n    /* Glue free blocks */\n    CPpmd7_Node_Ref *prev = &head;\n    while (n)\n    {\n      CPpmd7_Node *node = NODE(n);\n      UInt32 nu = node->NU;\n      n = node->Next;\n      if (nu == 0)\n      {\n        *prev = n;\n        continue;\n      }\n      prev = &node->Next;\n      for (;;)\n      {\n        CPpmd7_Node *node2 = node + nu;\n        nu += node2->NU;\n        if (node2->Stamp != EMPTY_NODE || nu >= 0x10000)\n          break;\n        node->NU = (UInt16)nu;\n        node2->NU = 0;\n      }\n    }\n  }\n\n  /* Fill lists of free blocks */\n  for (n = head; n != 0;)\n  {\n    CPpmd7_Node *node = NODE(n);\n    UInt32 nu = node->NU;\n    unsigned i;\n    n = node->Next;\n    if (nu == 0)\n      continue;\n    for (; nu > 128; nu -= 128, node += 128)\n      Ppmd7_InsertNode(p, node, PPMD_NUM_INDEXES - 1);\n    if (I2U(i = U2I(nu)) != nu)\n    {\n      unsigned k = I2U(--i);\n      Ppmd7_InsertNode(p, node + k, (unsigned)nu - k - 1);\n    }\n    Ppmd7_InsertNode(p, node, i);\n  }\n}\n\n\nZ7_NO_INLINE\nstatic void *Ppmd7_AllocUnitsRare(CPpmd7 *p, unsigned indx)\n{\n  unsigned i;\n  \n  if (p->GlueCount == 0)\n  {\n    Ppmd7_GlueFreeBlocks(p);\n    if (p->FreeList[indx] != 0)\n      return Ppmd7_RemoveNode(p, indx);\n  }\n  \n  i = indx;\n  \n  do\n  {\n    if (++i == PPMD_NUM_INDEXES)\n    {\n      UInt32 numBytes = U2B(I2U(indx));\n      Byte *us = p->UnitsStart;\n      p->GlueCount--;\n      return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : NULL;\n    }\n  }\n  while (p->FreeList[i] == 0);\n\n  {\n    void *block = Ppmd7_RemoveNode(p, i);\n    Ppmd7_SplitBlock(p, block, i, indx);\n    return block;\n  }\n}\n\n\nstatic void *Ppmd7_AllocUnits(CPpmd7 *p, unsigned indx)\n{\n  if (p->FreeList[indx] != 0)\n    return Ppmd7_RemoveNode(p, indx);\n  {\n    UInt32 numBytes = U2B(I2U(indx));\n    Byte *lo = p->LoUnit;\n    if ((UInt32)(p->HiUnit - lo) >= numBytes)\n    {\n      p->LoUnit = lo + numBytes;\n      return lo;\n    }\n  }\n  return Ppmd7_AllocUnitsRare(p, indx);\n}\n\n\n#define MEM_12_CPY(dest, src, num) \\\n  { UInt32 *d = (UInt32 *)(dest); \\\n    const UInt32 *z = (const UInt32 *)(src); \\\n    unsigned n = (num); \\\n    do { \\\n      d[0] = z[0]; \\\n      d[1] = z[1]; \\\n      d[2] = z[2]; \\\n      z += 3; \\\n      d += 3; \\\n    } while (--n); \\\n  }\n\n\n/*\nstatic void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)\n{\n  unsigned i0 = U2I(oldNU);\n  unsigned i1 = U2I(newNU);\n  if (i0 == i1)\n    return oldPtr;\n  if (p->FreeList[i1] != 0)\n  {\n    void *ptr = Ppmd7_RemoveNode(p, i1);\n    MEM_12_CPY(ptr, oldPtr, newNU)\n    Ppmd7_InsertNode(p, oldPtr, i0);\n    return ptr;\n  }\n  Ppmd7_SplitBlock(p, oldPtr, i0, i1);\n  return oldPtr;\n}\n*/\n\n\n#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)\nstatic void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)\n{\n  Ppmd_SET_SUCCESSOR(p, v)\n}\n\n\n\nZ7_NO_INLINE\nstatic\nvoid Ppmd7_RestartModel(CPpmd7 *p)\n{\n  unsigned i, k;\n\n  memset(p->FreeList, 0, sizeof(p->FreeList));\n  \n  p->Text = p->Base + p->AlignOffset;\n  p->HiUnit = p->Text + p->Size;\n  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;\n  p->GlueCount = 0;\n\n  p->OrderFall = p->MaxOrder;\n  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;\n  p->PrevSuccess = 0;\n\n  {\n    CPpmd7_Context *mc = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */\n    CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* Ppmd7_AllocUnits(p, PPMD_NUM_INDEXES - 1); */\n    \n    p->LoUnit += U2B(256 / 2);\n    p->MaxContext = p->MinContext = mc;\n    p->FoundState = s;\n\n    mc->NumStats = 256;\n    mc->Union2.SummFreq = 256 + 1;\n    mc->Union4.Stats = REF(s);\n    mc->Suffix = 0;\n\n    for (i = 0; i < 256; i++, s++)\n    {\n      s->Symbol = (Byte)i;\n      s->Freq = 1;\n      SetSuccessor(s, 0);\n    }\n\n    #ifdef PPMD7_ORDER_0_SUPPPORT\n    if (p->MaxOrder == 0)\n    {\n      CPpmd_Void_Ref r = REF(mc);\n      s = p->FoundState;\n      for (i = 0; i < 256; i++, s++)\n        SetSuccessor(s, r);\n      return;\n    }\n    #endif\n  }\n\n  for (i = 0; i < 128; i++)\n    \n    \n    \n    for (k = 0; k < 8; k++)\n    {\n      unsigned m;\n      UInt16 *dest = p->BinSumm[i] + k;\n      const UInt16 val = (UInt16)(PPMD_BIN_SCALE - PPMD7_kInitBinEsc[k] / (i + 2));\n      for (m = 0; m < 64; m += 8)\n        dest[m] = val;\n    }\n\n    \n  for (i = 0; i < 25; i++)\n  {\n\n    CPpmd_See *s = p->See[i];\n    \n    \n    \n    unsigned summ = ((5 * i + 10) << (PPMD_PERIOD_BITS - 4));\n    for (k = 0; k < 16; k++, s++)\n    {\n      s->Summ = (UInt16)summ;\n      s->Shift = (PPMD_PERIOD_BITS - 4);\n      s->Count = 4;\n    }\n  }\n  \n  p->DummySee.Summ = 0; /* unused */\n  p->DummySee.Shift = PPMD_PERIOD_BITS;\n  p->DummySee.Count = 64; /* unused */\n}\n\n\nvoid Ppmd7_Init(CPpmd7 *p, unsigned maxOrder)\n{\n  p->MaxOrder = maxOrder;\n\n  Ppmd7_RestartModel(p);\n}\n\n\n\n/*\n  Ppmd7_CreateSuccessors()\n  It's called when (FoundState->Successor) is RAW-Successor,\n  that is the link to position in Raw text.\n  So we create Context records and write the links to\n  FoundState->Successor and to identical RAW-Successors in suffix\n  contexts of MinContex.\n  \n  The function returns:\n  if (OrderFall == 0) then MinContext is already at MAX order,\n    { return pointer to new or existing context of same MAX order }\n  else\n    { return pointer to new real context that will be (Order+1) in comparison with MinContext\n\n  also it can return pointer to real context of same order,\n*/\n\nZ7_NO_INLINE\nstatic PPMD7_CTX_PTR Ppmd7_CreateSuccessors(CPpmd7 *p)\n{\n  PPMD7_CTX_PTR c = p->MinContext;\n  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);\n  Byte newSym, newFreq;\n  unsigned numPs = 0;\n  CPpmd_State *ps[PPMD7_MAX_ORDER];\n\n  if (p->OrderFall != 0)\n    ps[numPs++] = p->FoundState;\n  \n  while (c->Suffix)\n  {\n    CPpmd_Void_Ref successor;\n    CPpmd_State *s;\n    c = SUFFIX(c);\n    \n\n    if (c->NumStats != 1)\n    {\n      Byte sym = p->FoundState->Symbol;\n      for (s = STATS(c); s->Symbol != sym; s++);\n\n    }\n    else\n    {\n      s = ONE_STATE(c);\n\n    }\n    successor = SUCCESSOR(s);\n    if (successor != upBranch)\n    {\n      // (c) is real record Context here,\n      c = CTX(successor);\n      if (numPs == 0)\n      {\n        // (c) is real record MAX Order Context here,\n        // So we don't need to create any new contexts.\n        return c;\n      }\n      break;\n    }\n    ps[numPs++] = s;\n  }\n  \n  // All created contexts will have single-symbol with new RAW-Successor\n  // All new RAW-Successors will point to next position in RAW text\n  // after FoundState->Successor\n\n  newSym = *(const Byte *)Ppmd7_GetPtr(p, upBranch);\n  upBranch++;\n  \n  \n  if (c->NumStats == 1)\n    newFreq = ONE_STATE(c)->Freq;\n  else\n  {\n    UInt32 cf, s0;\n    CPpmd_State *s;\n    for (s = STATS(c); s->Symbol != newSym; s++);\n    cf = (UInt32)s->Freq - 1;\n    s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf;\n    /*\n      cf - is frequency of symbol that will be Successor in new context records.\n      s0 - is commulative frequency sum of another symbols from parent context.\n      max(newFreq)= (s->Freq + 1), when (s0 == 1)\n      we have requirement (Ppmd7Context_OneState()->Freq <= 128) in BinSumm[]\n      so (s->Freq < 128) - is requirement for multi-symbol contexts\n    */\n    newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : (2 * cf + s0 - 1) / (2 * s0) + 1));\n  }\n\n  // Create new single-symbol contexts from low order to high order in loop\n\n  do\n  {\n    PPMD7_CTX_PTR c1;\n    /* = AllocContext(p); */\n    if (p->HiUnit != p->LoUnit)\n      c1 = (PPMD7_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE);\n    else if (p->FreeList[0] != 0)\n      c1 = (PPMD7_CTX_PTR)Ppmd7_RemoveNode(p, 0);\n    else\n    {\n      c1 = (PPMD7_CTX_PTR)Ppmd7_AllocUnitsRare(p, 0);\n      if (!c1)\n        return NULL;\n    }\n    \n    c1->NumStats = 1;\n    ONE_STATE(c1)->Symbol = newSym;\n    ONE_STATE(c1)->Freq = newFreq;\n    SetSuccessor(ONE_STATE(c1), upBranch);\n    c1->Suffix = REF(c);\n    SetSuccessor(ps[--numPs], REF(c1));\n    c = c1;\n  }\n  while (numPs != 0);\n  \n  return c;\n}\n\n\n\n#define SWAP_STATES(s) \\\n  { CPpmd_State tmp = s[0]; s[0] = s[-1]; s[-1] = tmp; }\n\n\nvoid Ppmd7_UpdateModel(CPpmd7 *p);\nZ7_NO_INLINE\nvoid Ppmd7_UpdateModel(CPpmd7 *p)\n{\n  CPpmd_Void_Ref maxSuccessor, minSuccessor;\n  PPMD7_CTX_PTR c, mc;\n  unsigned s0, ns;\n\n\n\n  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)\n  {\n    /* Update Freqs in Suffix Context */\n\n    c = SUFFIX(p->MinContext);\n    \n    if (c->NumStats == 1)\n    {\n      CPpmd_State *s = ONE_STATE(c);\n      if (s->Freq < 32)\n        s->Freq++;\n    }\n    else\n    {\n      CPpmd_State *s = STATS(c);\n      Byte sym = p->FoundState->Symbol;\n      \n      if (s->Symbol != sym)\n      {\n        do\n        {\n          // s++; if (s->Symbol == sym) break;\n          s++;\n        }\n        while (s->Symbol != sym);\n        \n        if (s[0].Freq >= s[-1].Freq)\n        {\n          SWAP_STATES(s)\n          s--;\n        }\n      }\n\n      if (s->Freq < MAX_FREQ - 9)\n      {\n        s->Freq = (Byte)(s->Freq + 2);\n        c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2);\n      }\n    }\n  }\n\n  \n  if (p->OrderFall == 0)\n  {\n    /* MAX ORDER context */\n    /* (FoundState->Successor) is RAW-Successor. */\n    p->MaxContext = p->MinContext = Ppmd7_CreateSuccessors(p);\n    if (!p->MinContext)\n    {\n      Ppmd7_RestartModel(p);\n      return;\n    }\n    SetSuccessor(p->FoundState, REF(p->MinContext));\n    return;\n  }\n\n  \n  /* NON-MAX ORDER context */\n  \n  {\n    Byte *text = p->Text;\n    *text++ = p->FoundState->Symbol;\n    p->Text = text;\n    if (text >= p->UnitsStart)\n    {\n      Ppmd7_RestartModel(p);\n      return;\n    }\n    maxSuccessor = REF(text);\n  }\n  \n  minSuccessor = SUCCESSOR(p->FoundState);\n\n  if (minSuccessor)\n  {\n    // there is Successor for FoundState in MinContext.\n    // So the next context will be one order higher than MinContext.\n    \n    if (minSuccessor <= maxSuccessor)\n    {\n      // minSuccessor is RAW-Successor. So we will create real contexts records:\n      PPMD7_CTX_PTR cs = Ppmd7_CreateSuccessors(p);\n      if (!cs)\n      {\n        Ppmd7_RestartModel(p);\n        return;\n      }\n      minSuccessor = REF(cs);\n    }\n\n    // minSuccessor now is real Context pointer that points to existing (Order+1) context\n    \n    if (--p->OrderFall == 0)\n    {\n      /*\n      if we move to MaxOrder context, then minSuccessor will be common Succesor for both:\n        MinContext that is (MaxOrder - 1)\n        MaxContext that is (MaxOrder)\n      so we don't need new RAW-Successor, and we can use real minSuccessor\n      as succssors for both MinContext and MaxContext.\n      */\n      maxSuccessor = minSuccessor;\n      \n      /*\n      if (MaxContext != MinContext)\n      {\n        there was order fall from MaxOrder and we don't need current symbol\n        to transfer some RAW-Succesors to real contexts.\n        So we roll back pointer in raw data for one position.\n      }\n      */\n      p->Text -= (p->MaxContext != p->MinContext);\n    }\n  }\n  else\n  {\n    /*\n    FoundState has NULL-Successor here.\n    And only root 0-order context can contain NULL-Successors.\n    We change Successor in FoundState to RAW-Successor,\n    And next context will be same 0-order root Context.\n    */\n    SetSuccessor(p->FoundState, maxSuccessor);\n    minSuccessor = REF(p->MinContext);\n  }\n\n  mc = p->MinContext;\n  c = p->MaxContext;\n\n  p->MaxContext = p->MinContext = CTX(minSuccessor);\n\n  if (c == mc)\n    return;\n\n  // s0 : is pure Escape Freq\n  s0 = mc->Union2.SummFreq - (ns = mc->NumStats) - ((unsigned)p->FoundState->Freq - 1);\n\n  do\n  {\n    unsigned ns1;\n    UInt32 sum;\n    \n    if ((ns1 = c->NumStats) != 1)\n    {\n      if ((ns1 & 1) == 0)\n      {\n        /* Expand for one UNIT */\n        const unsigned oldNU = ns1 >> 1;\n        const unsigned i = U2I(oldNU);\n        if (i != U2I((size_t)oldNU + 1))\n        {\n          void *ptr = Ppmd7_AllocUnits(p, i + 1);\n          void *oldPtr;\n          if (!ptr)\n          {\n            Ppmd7_RestartModel(p);\n            return;\n          }\n          oldPtr = STATS(c);\n          MEM_12_CPY(ptr, oldPtr, oldNU)\n          Ppmd7_InsertNode(p, oldPtr, i);\n          c->Union4.Stats = STATS_REF(ptr);\n        }\n      }\n      sum = c->Union2.SummFreq;\n      /* max increase of Escape_Freq is 3 here.\n         total increase of Union2.SummFreq for all symbols is less than 256 here */\n      sum += (UInt32)(unsigned)((2 * ns1 < ns) + 2 * ((unsigned)(4 * ns1 <= ns) & (sum <= 8 * ns1)));\n      /* original PPMdH uses 16-bit variable for (sum) here.\n         But (sum < 0x9000). So we don't truncate (sum) to 16-bit */\n      // sum = (UInt16)sum;\n    }\n    else\n    {\n      // instead of One-symbol context we create 2-symbol context\n      CPpmd_State *s = (CPpmd_State*)Ppmd7_AllocUnits(p, 0);\n      if (!s)\n      {\n        Ppmd7_RestartModel(p);\n        return;\n      }\n      {\n        unsigned freq = c->Union2.State2.Freq;\n        // s = *ONE_STATE(c);\n        s->Symbol = c->Union2.State2.Symbol;\n        s->Successor_0 = c->Union4.State4.Successor_0;\n        s->Successor_1 = c->Union4.State4.Successor_1;\n        // SetSuccessor(s, c->Union4.Stats);  // call it only for debug purposes to check the order of\n                                              // (Successor_0 and Successor_1) in LE/BE.\n        c->Union4.Stats = REF(s);\n        if (freq < MAX_FREQ / 4 - 1)\n          freq <<= 1;\n        else\n          freq = MAX_FREQ - 4;\n        // (max(s->freq) == 120), when we convert from 1-symbol into 2-symbol context\n        s->Freq = (Byte)freq;\n        // max(InitEsc = PPMD7_kExpEscape[*]) is 25. So the max(escapeFreq) is 26 here\n        sum = (UInt32)(freq + p->InitEsc + (ns > 3));\n      }\n    }\n    \n    {\n      CPpmd_State *s = STATS(c) + ns1;\n      UInt32 cf = 2 * (sum + 6) * (UInt32)p->FoundState->Freq;\n      UInt32 sf = (UInt32)s0 + sum;\n      s->Symbol = p->FoundState->Symbol;\n      c->NumStats = (UInt16)(ns1 + 1);\n      SetSuccessor(s, maxSuccessor);\n      \n      if (cf < 6 * sf)\n      {\n        cf = (UInt32)1 + (cf > sf) + (cf >= 4 * sf);\n        sum += 3;\n        /* It can add (0, 1, 2) to Escape_Freq */\n      }\n      else\n      {\n        cf = (UInt32)4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf);\n        sum += cf;\n      }\n     \n      c->Union2.SummFreq = (UInt16)sum;\n      s->Freq = (Byte)cf;\n    }\n    c = SUFFIX(c);\n  }\n  while (c != mc);\n}\n  \n\n\nZ7_NO_INLINE\nstatic void Ppmd7_Rescale(CPpmd7 *p)\n{\n  unsigned i, adder, sumFreq, escFreq;\n  CPpmd_State *stats = STATS(p->MinContext);\n  CPpmd_State *s = p->FoundState;\n\n  /* Sort the list by Freq */\n  if (s != stats)\n  {\n    CPpmd_State tmp = *s;\n    do\n      s[0] = s[-1];\n    while (--s != stats);\n    *s = tmp;\n  }\n\n  sumFreq = s->Freq;\n  escFreq = p->MinContext->Union2.SummFreq - sumFreq;\n  \n  /*\n  if (p->OrderFall == 0), adder = 0 : it's     allowed to remove symbol from     MAX Order context\n  if (p->OrderFall != 0), adder = 1 : it's NOT allowed to remove symbol from NON-MAX Order context\n  */\n\n  adder = (p->OrderFall != 0);\n\n  #ifdef PPMD7_ORDER_0_SUPPPORT\n  adder |= (p->MaxOrder == 0); // we don't remove symbols from order-0 context\n  #endif\n\n  sumFreq = (sumFreq + 4 + adder) >> 1;\n  i = (unsigned)p->MinContext->NumStats - 1;\n  s->Freq = (Byte)sumFreq;\n  \n  do\n  {\n    unsigned freq = (++s)->Freq;\n    escFreq -= freq;\n    freq = (freq + adder) >> 1;\n    sumFreq += freq;\n    s->Freq = (Byte)freq;\n    if (freq > s[-1].Freq)\n    {\n      CPpmd_State tmp = *s;\n      CPpmd_State *s1 = s;\n      do\n      {\n        s1[0] = s1[-1];\n      }\n      while (--s1 != stats && freq > s1[-1].Freq);\n      *s1 = tmp;\n    }\n  }\n  while (--i);\n  \n  if (s->Freq == 0)\n  {\n    /* Remove all items with Freq == 0 */\n    CPpmd7_Context *mc;\n    unsigned numStats, numStatsNew, n0, n1;\n    \n    i = 0; do { i++; } while ((--s)->Freq == 0);\n    \n    /* We increase (escFreq) for the number of removed symbols.\n       So we will have (0.5) increase for Escape_Freq in avarage per\n       removed symbol after Escape_Freq halving */\n    escFreq += i;\n    mc = p->MinContext;\n    numStats = mc->NumStats;\n    numStatsNew = numStats - i;\n    mc->NumStats = (UInt16)(numStatsNew);\n    n0 = (numStats + 1) >> 1;\n    \n    if (numStatsNew == 1)\n    {\n      /* Create Single-Symbol context */\n      unsigned freq = stats->Freq;\n      \n      do\n      {\n        escFreq >>= 1;\n        freq = (freq + 1) >> 1;\n      }\n      while (escFreq > 1);\n\n      s = ONE_STATE(mc);\n      *s = *stats;\n      s->Freq = (Byte)freq; // (freq <= 260 / 4)\n      p->FoundState = s;\n      Ppmd7_InsertNode(p, stats, U2I(n0));\n      return;\n    }\n    \n    n1 = (numStatsNew + 1) >> 1;\n    if (n0 != n1)\n    {\n      // p->MinContext->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));\n      unsigned i0 = U2I(n0);\n      unsigned i1 = U2I(n1);\n      if (i0 != i1)\n      {\n        if (p->FreeList[i1] != 0)\n        {\n          void *ptr = Ppmd7_RemoveNode(p, i1);\n          p->MinContext->Union4.Stats = STATS_REF(ptr);\n          MEM_12_CPY(ptr, (const void *)stats, n1)\n          Ppmd7_InsertNode(p, stats, i0);\n        }\n        else\n          Ppmd7_SplitBlock(p, stats, i0, i1);\n      }\n    }\n  }\n  {\n    CPpmd7_Context *mc = p->MinContext;\n    mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));\n    // Escape_Freq halving here\n    p->FoundState = STATS(mc);\n  }\n}\n\n\nCPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq)\n{\n  CPpmd_See *see;\n  const CPpmd7_Context *mc = p->MinContext;\n  unsigned numStats = mc->NumStats;\n  if (numStats != 256)\n  {\n    unsigned nonMasked = numStats - numMasked;\n    see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]]\n        + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - numStats)\n        + 2 * (unsigned)(mc->Union2.SummFreq < 11 * numStats)\n        + 4 * (unsigned)(numMasked > nonMasked) +\n        p->HiBitsFlag;\n    {\n      // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ\n      const unsigned summ = (UInt16)see->Summ; // & 0xFFFF\n      const unsigned r = (summ >> see->Shift);\n      see->Summ = (UInt16)(summ - r);\n      *escFreq = (UInt32)(r + (r == 0));\n    }\n  }\n  else\n  {\n    see = &p->DummySee;\n    *escFreq = 1;\n  }\n  return see;\n}\n\n\nstatic void Ppmd7_NextContext(CPpmd7 *p)\n{\n  PPMD7_CTX_PTR c = CTX(SUCCESSOR(p->FoundState));\n  if (p->OrderFall == 0 && (const Byte *)c > p->Text)\n    p->MaxContext = p->MinContext = c;\n  else\n    Ppmd7_UpdateModel(p);\n}\n\n\nvoid Ppmd7_Update1(CPpmd7 *p)\n{\n  CPpmd_State *s = p->FoundState;\n  unsigned freq = s->Freq;\n  freq += 4;\n  p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);\n  s->Freq = (Byte)freq;\n  if (freq > s[-1].Freq)\n  {\n    SWAP_STATES(s)\n    p->FoundState = --s;\n    if (freq > MAX_FREQ)\n      Ppmd7_Rescale(p);\n  }\n  Ppmd7_NextContext(p);\n}\n\n\nvoid Ppmd7_Update1_0(CPpmd7 *p)\n{\n  CPpmd_State *s = p->FoundState;\n  CPpmd7_Context *mc = p->MinContext;\n  unsigned freq = s->Freq;\n  const unsigned summFreq = mc->Union2.SummFreq;\n  p->PrevSuccess = (2 * freq > summFreq);\n  p->RunLength += (Int32)p->PrevSuccess;\n  mc->Union2.SummFreq = (UInt16)(summFreq + 4);\n  freq += 4;\n  s->Freq = (Byte)freq;\n  if (freq > MAX_FREQ)\n    Ppmd7_Rescale(p);\n  Ppmd7_NextContext(p);\n}\n\n\n/*\nvoid Ppmd7_UpdateBin(CPpmd7 *p)\n{\n  unsigned freq = p->FoundState->Freq;\n  p->FoundState->Freq = (Byte)(freq + (freq < 128));\n  p->PrevSuccess = 1;\n  p->RunLength++;\n  Ppmd7_NextContext(p);\n}\n*/\n\nvoid Ppmd7_Update2(CPpmd7 *p)\n{\n  CPpmd_State *s = p->FoundState;\n  unsigned freq = s->Freq;\n  freq += 4;\n  p->RunLength = p->InitRL;\n  p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);\n  s->Freq = (Byte)freq;\n  if (freq > MAX_FREQ)\n    Ppmd7_Rescale(p);\n  Ppmd7_UpdateModel(p);\n}\n\n\n\n/*\nPPMd Memory Map:\n{\n  [ 0 ]           contains subset of original raw text, that is required to create context\n                  records, Some symbols are not written, when max order context was reached\n  [ Text ]        free area\n  [ UnitsStart ]  CPpmd_State vectors and CPpmd7_Context records\n  [ LoUnit ]      free  area for CPpmd_State and CPpmd7_Context items\n[ HiUnit ]      CPpmd7_Context records\n  [ Size ]        end of array\n}\n\nThese addresses don't cross at any time.\nAnd the following condtions is true for addresses:\n  (0  <= Text < UnitsStart <= LoUnit <= HiUnit <= Size)\n\nRaw text is BYTE--aligned.\nthe data in block [ UnitsStart ... Size ] contains 12-bytes aligned UNITs.\n\nLast UNIT of array at offset (Size - 12) is root order-0 CPpmd7_Context record.\nThe code can free UNITs memory blocks that were allocated to store CPpmd_State vectors.\nThe code doesn't free UNITs allocated for CPpmd7_Context records.\n\nThe code calls Ppmd7_RestartModel(), when there is no free memory for allocation.\nAnd Ppmd7_RestartModel() changes the state to orignal start state, with full free block.\n\n\nThe code allocates UNITs with the following order:\n\nAllocation of 1 UNIT for Context record\n  - from free space (HiUnit) down to (LoUnit)\n  - from FreeList[0]\n  - Ppmd7_AllocUnitsRare()\n\nPpmd7_AllocUnits() for CPpmd_State vectors:\n  - from FreeList[i]\n  - from free space (LoUnit) up to (HiUnit)\n  - Ppmd7_AllocUnitsRare()\n\nPpmd7_AllocUnitsRare()\n  - if (GlueCount == 0)\n       {  Glue lists, GlueCount = 255, allocate from FreeList[i]] }\n  - loop for all higher sized FreeList[...] lists\n  - from (UnitsStart - Text), GlueCount--\n  - ERROR\n\n\nEach Record with Context contains the CPpmd_State vector, where each\nCPpmd_State contains the link to Successor.\nThere are 3 types of Successor:\n  1) NULL-Successor   - NULL pointer. NULL-Successor links can be stored\n                        only in 0-order Root Context Record.\n                        We use 0 value as NULL-Successor\n  2) RAW-Successor    - the link to position in raw text,\n                        that \"RAW-Successor\" is being created after first\n                        occurrence of new symbol for some existing context record.\n                        (RAW-Successor > 0).\n  3) RECORD-Successor - the link to CPpmd7_Context record of (Order+1),\n                        that record is being created when we go via RAW-Successor again.\n\nFor any successors at any time: the following condtions are true for Successor links:\n(NULL-Successor < RAW-Successor < UnitsStart <= RECORD-Successor)\n\n\n---------- Symbol Frequency, SummFreq and Range in Range_Coder ----------\n\nCPpmd7_Context::SummFreq = Sum(Stats[].Freq) + Escape_Freq\n\nThe PPMd code tries to fulfill the condition:\n  (SummFreq <= (256 * 128 = RC::kBot))\n\nWe have (Sum(Stats[].Freq) <= 256 * 124), because of (MAX_FREQ = 124)\nSo (4 = 128 - 124) is average reserve for Escape_Freq for each symbol.\nIf (CPpmd_State::Freq) is not aligned for 4, the reserve can be 5, 6 or 7.\nSummFreq and Escape_Freq can be changed in Ppmd7_Rescale() and *Update*() functions.\nPpmd7_Rescale() can remove symbols only from max-order contexts. So Escape_Freq can increase after multiple calls of Ppmd7_Rescale() for\nmax-order context.\n\nWhen the PPMd code still break (Total <= RC::Range) condition in range coder,\nwe have two ways to resolve that problem:\n  1) we can report error, if we want to keep compatibility with original PPMd code that has no fix for such cases.\n  2) we can reduce (Total) value to (RC::Range) by reducing (Escape_Freq) part of (Total) value.\n*/\n\n#undef MAX_FREQ\n#undef UNIT_SIZE\n#undef U2B\n#undef U2I\n#undef I2U\n#undef I2U_UInt16\n#undef REF\n#undef STATS_REF\n#undef CTX\n#undef STATS\n#undef ONE_STATE\n#undef SUFFIX\n#undef NODE\n#undef EMPTY_NODE\n#undef MEM_12_CPY\n#undef SUCCESSOR\n#undef SWAP_STATES\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd7.h",
    "content": "﻿/* Ppmd7.h -- Ppmd7 (PPMdH) compression codec\n2023-04-02 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.H (2001): Dmitry Shkarin : Public domain */\n \n\n#ifndef ZIP7_INC_PPMD7_H\n#define ZIP7_INC_PPMD7_H\n\n#include \"Ppmd.h\"\n\nEXTERN_C_BEGIN\n\n#define PPMD7_MIN_ORDER 2\n#define PPMD7_MAX_ORDER 64\n\n#define PPMD7_MIN_MEM_SIZE (1 << 11)\n#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3)\n\nstruct CPpmd7_Context_;\n\ntypedef Ppmd_Ref_Type(struct CPpmd7_Context_) CPpmd7_Context_Ref;\n\n// MY_CPU_pragma_pack_push_1\n\ntypedef struct CPpmd7_Context_\n{\n  UInt16 NumStats;\n\n\n  union\n  {\n    UInt16 SummFreq;\n    CPpmd_State2 State2;\n  } Union2;\n\n  union\n  {\n    CPpmd_State_Ref Stats;\n    CPpmd_State4 State4;\n  } Union4;\n\n  CPpmd7_Context_Ref Suffix;\n} CPpmd7_Context;\n\n// MY_CPU_pragma_pop\n\n#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->Union2)\n\n\n\n\ntypedef struct\n{\n  UInt32 Range;\n  UInt32 Code;\n  UInt32 Low;\n  IByteInPtr Stream;\n} CPpmd7_RangeDec;\n\n\ntypedef struct\n{\n  UInt32 Range;\n  Byte Cache;\n  // Byte _dummy_[3];\n  UInt64 Low;\n  UInt64 CacheSize;\n  IByteOutPtr Stream;\n} CPpmd7z_RangeEnc;\n\n\ntypedef struct\n{\n  CPpmd7_Context *MinContext, *MaxContext;\n  CPpmd_State *FoundState;\n  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag;\n  Int32 RunLength, InitRL; /* must be 32-bit at least */\n\n  UInt32 Size;\n  UInt32 GlueCount;\n  UInt32 AlignOffset;\n  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;\n\n\n  \n  \n  union\n  {\n    CPpmd7_RangeDec dec;\n    CPpmd7z_RangeEnc enc;\n  } rc;\n  \n  Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment\n  Byte Units2Indx[128];\n  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];\n\n  Byte NS2BSIndx[256], NS2Indx[256];\n  Byte ExpEscape[16];\n  CPpmd_See DummySee, See[25][16];\n  UInt16 BinSumm[128][64];\n  // int LastSymbol;\n} CPpmd7;\n\n\nvoid Ppmd7_Construct(CPpmd7 *p);\nBoolInt Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAllocPtr alloc);\nvoid Ppmd7_Free(CPpmd7 *p, ISzAllocPtr alloc);\nvoid Ppmd7_Init(CPpmd7 *p, unsigned maxOrder);\n#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)\n\n\n/* ---------- Internal Functions ---------- */\n\n#define Ppmd7_GetPtr(p, ptr)     Ppmd_GetPtr(p, ptr)\n#define Ppmd7_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd7_Context)\n#define Ppmd7_GetStats(p, ctx)   Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State)\n\nvoid Ppmd7_Update1(CPpmd7 *p);\nvoid Ppmd7_Update1_0(CPpmd7 *p);\nvoid Ppmd7_Update2(CPpmd7 *p);\n\n#define PPMD7_HiBitsFlag_3(sym) ((((unsigned)sym + 0xC0) >> (8 - 3)) & (1 << 3))\n#define PPMD7_HiBitsFlag_4(sym) ((((unsigned)sym + 0xC0) >> (8 - 4)) & (1 << 4))\n// #define PPMD7_HiBitsFlag_3(sym) ((sym) < 0x40 ? 0 : (1 << 3))\n// #define PPMD7_HiBitsFlag_4(sym) ((sym) < 0x40 ? 0 : (1 << 4))\n\n#define Ppmd7_GetBinSumm(p) \\\n    &p->BinSumm[(size_t)(unsigned)Ppmd7Context_OneState(p->MinContext)->Freq - 1] \\\n    [ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \\\n    + p->NS2BSIndx[(size_t)Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] \\\n    + PPMD7_HiBitsFlag_4(Ppmd7Context_OneState(p->MinContext)->Symbol) \\\n    + (p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol)) ]\n\nCPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale);\n\n\n/*\nWe support two versions of Ppmd7 (PPMdH) methods that use same CPpmd7 structure:\n  1) Ppmd7a_*: original PPMdH\n  2) Ppmd7z_*: modified PPMdH with 7z Range Coder\nPpmd7_*: the structures and functions that are common for both versions of PPMd7 (PPMdH)\n*/\n\n/* ---------- Decode ---------- */\n\n#define PPMD7_SYM_END    (-1)\n#define PPMD7_SYM_ERROR  (-2)\n\n/*\nYou must set (CPpmd7::rc.dec.Stream) before Ppmd7*_RangeDec_Init()\n\nPpmd7*_DecodeSymbol()\nout:\n  >= 0 : decoded byte\n    -1 : PPMD7_SYM_END   : End of payload marker\n    -2 : PPMD7_SYM_ERROR : Data error\n*/\n\n/* Ppmd7a_* : original PPMdH */\nBoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p);\n#define Ppmd7a_RangeDec_IsFinishedOK(p) ((p)->Code == 0)\nint Ppmd7a_DecodeSymbol(CPpmd7 *p);\n\n/* Ppmd7z_* : modified PPMdH with 7z Range Coder */\nBoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p);\n#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0)\nint Ppmd7z_DecodeSymbol(CPpmd7 *p);\n// Byte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim);\n\n\n/* ---------- Encode ---------- */\n\nvoid Ppmd7z_Init_RangeEnc(CPpmd7 *p);\nvoid Ppmd7z_Flush_RangeEnc(CPpmd7 *p);\n// void Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol);\nvoid Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim);\n\nEXTERN_C_END\n \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd7Dec.c",
    "content": "﻿/* Ppmd7Dec.c -- Ppmd7z (PPMdH with 7z Range Coder) Decoder\n2023-09-07 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.H (2001): Dmitry Shkarin : Public domain */\n\n\n#include \"Precomp.h\"\n\n#include \"Ppmd7.h\"\n\n#define kTopValue ((UInt32)1 << 24)\n\n\n#define READ_BYTE(p) IByteIn_Read((p)->Stream)\n\nBoolInt Ppmd7z_RangeDec_Init(CPpmd7_RangeDec *p)\n{\n  unsigned i;\n  p->Code = 0;\n  p->Range = 0xFFFFFFFF;\n  if (READ_BYTE(p) != 0)\n    return False;\n  for (i = 0; i < 4; i++)\n    p->Code = (p->Code << 8) | READ_BYTE(p);\n  return (p->Code < 0xFFFFFFFF);\n}\n\n#define RC_NORM_BASE(p) if ((p)->Range < kTopValue) \\\n  { (p)->Code = ((p)->Code << 8) | READ_BYTE(p); (p)->Range <<= 8;\n\n#define RC_NORM_1(p)  RC_NORM_BASE(p) }\n#define RC_NORM(p)    RC_NORM_BASE(p) RC_NORM_BASE(p) }}\n\n// we must use only one type of Normalization from two: LOCAL or REMOTE\n#define RC_NORM_LOCAL(p)    // RC_NORM(p)\n#define RC_NORM_REMOTE(p)   RC_NORM(p)\n\n#define R (&p->rc.dec)\n\nZ7_FORCE_INLINE\n// Z7_NO_INLINE\nstatic void Ppmd7z_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size)\n{\n\n  \n  R->Code -= start * R->Range;\n  R->Range *= size;\n  RC_NORM_LOCAL(R)\n}\n\n#define RC_Decode(start, size)  Ppmd7z_RD_Decode(p, start, size);\n#define RC_DecodeFinal(start, size)  RC_Decode(start, size)  RC_NORM_REMOTE(R)\n#define RC_GetThreshold(total)  (R->Code / (R->Range /= (total)))\n\n\n#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))\n// typedef CPpmd7_Context * CTX_PTR;\n#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)\nvoid Ppmd7_UpdateModel(CPpmd7 *p);\n\n#define MASK(sym)  ((Byte *)charMask)[sym]\n// Z7_FORCE_INLINE\n// static\nint Ppmd7z_DecodeSymbol(CPpmd7 *p)\n{\n  size_t charMask[256 / sizeof(size_t)];\n\n  if (p->MinContext->NumStats != 1)\n  {\n    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);\n    unsigned i;\n    UInt32 count, hiCnt;\n    const UInt32 summFreq = p->MinContext->Union2.SummFreq;\n\n    \n    \n    \n    count = RC_GetThreshold(summFreq);\n    hiCnt = count;\n    \n    if ((Int32)(count -= s->Freq) < 0)\n    {\n      Byte sym;\n      RC_DecodeFinal(0, s->Freq)\n      p->FoundState = s;\n      sym = s->Symbol;\n      Ppmd7_Update1_0(p);\n      return sym;\n    }\n  \n    p->PrevSuccess = 0;\n    i = (unsigned)p->MinContext->NumStats - 1;\n    \n    do\n    {\n      if ((Int32)(count -= (++s)->Freq) < 0)\n      {\n        Byte sym;\n        RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)\n        p->FoundState = s;\n        sym = s->Symbol;\n        Ppmd7_Update1(p);\n        return sym;\n      }\n    }\n    while (--i);\n    \n    if (hiCnt >= summFreq)\n      return PPMD7_SYM_ERROR;\n    \n    hiCnt -= count;\n    RC_Decode(hiCnt, summFreq - hiCnt)\n\n    p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol);\n    PPMD_SetAllBitsIn256Bytes(charMask)\n    // i = p->MinContext->NumStats - 1;\n    // do { MASK((--s)->Symbol) = 0; } while (--i);\n    {\n      CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);\n      MASK(s->Symbol) = 0;\n      do\n      {\n        const unsigned sym0 = s2[0].Symbol;\n        const unsigned sym1 = s2[1].Symbol;\n        s2 += 2;\n        MASK(sym0) = 0;\n        MASK(sym1) = 0;\n      }\n      while (s2 < s);\n    }\n  }\n  else\n  {\n    CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);\n    UInt16 *prob = Ppmd7_GetBinSumm(p);\n    UInt32 pr = *prob;\n    UInt32 size0 = (R->Range >> 14) * pr;\n    pr = PPMD_UPDATE_PROB_1(pr);\n\n    if (R->Code < size0)\n    {\n      Byte sym;\n      *prob = (UInt16)(pr + (1 << PPMD_INT_BITS));\n      \n      // RangeDec_DecodeBit0(size0);\n      R->Range = size0;\n      RC_NORM_1(R)\n      /* we can use single byte normalization here because of\n         (min(BinSumm[][]) = 95) > (1 << (14 - 8)) */\n\n      // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;\n      // Ppmd7_UpdateBin(p);\n      {\n        unsigned freq = s->Freq;\n        CPpmd7_Context *c = CTX(SUCCESSOR(s));\n        sym = s->Symbol;\n        p->FoundState = s;\n        p->PrevSuccess = 1;\n        p->RunLength++;\n        s->Freq = (Byte)(freq + (freq < 128));\n        // NextContext(p);\n        if (p->OrderFall == 0 && (const Byte *)c > p->Text)\n          p->MaxContext = p->MinContext = c;\n        else\n          Ppmd7_UpdateModel(p);\n      }\n      return sym;\n    }\n\n    *prob = (UInt16)pr;\n    p->InitEsc = p->ExpEscape[pr >> 10];\n\n    // RangeDec_DecodeBit1(size0);\n    \n    R->Code -= size0;\n    R->Range -= size0;\n    RC_NORM_LOCAL(R)\n    \n    PPMD_SetAllBitsIn256Bytes(charMask)\n    MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;\n    p->PrevSuccess = 0;\n  }\n\n  for (;;)\n  {\n    CPpmd_State *s, *s2;\n    UInt32 freqSum, count, hiCnt;\n\n    CPpmd_See *see;\n    CPpmd7_Context *mc;\n    unsigned numMasked;\n    RC_NORM_REMOTE(R)\n    mc = p->MinContext;\n    numMasked = mc->NumStats;\n\n    do\n    {\n      p->OrderFall++;\n      if (!mc->Suffix)\n        return PPMD7_SYM_END;\n      mc = Ppmd7_GetContext(p, mc->Suffix);\n    }\n    while (mc->NumStats == numMasked);\n    \n    s = Ppmd7_GetStats(p, mc);\n\n    {\n      unsigned num = mc->NumStats;\n      unsigned num2 = num / 2;\n      \n      num &= 1;\n      hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);\n      s += num;\n      p->MinContext = mc;\n\n      do\n      {\n        const unsigned sym0 = s[0].Symbol;\n        const unsigned sym1 = s[1].Symbol;\n        s += 2;\n        hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));\n        hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));\n      }\n      while (--num2);\n    }\n\n    see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);\n    freqSum += hiCnt;\n\n\n\n\n    count = RC_GetThreshold(freqSum);\n    \n    if (count < hiCnt)\n    {\n      Byte sym;\n\n      s = Ppmd7_GetStats(p, p->MinContext);\n      hiCnt = count;\n      // count -= s->Freq & (UInt32)(MASK(s->Symbol));\n      // if ((Int32)count >= 0)\n      {\n        for (;;)\n        {\n          count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;\n          // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;\n        }\n      }\n      s--;\n      RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)\n\n      // new (see->Summ) value can overflow over 16-bits in some rare cases\n      Ppmd_See_UPDATE(see)\n      p->FoundState = s;\n      sym = s->Symbol;\n      Ppmd7_Update2(p);\n      return sym;\n    }\n\n    if (count >= freqSum)\n      return PPMD7_SYM_ERROR;\n    \n    RC_Decode(hiCnt, freqSum - hiCnt)\n\n    // We increase (see->Summ) for sum of Freqs of all non_Masked symbols.\n    // new (see->Summ) value can overflow over 16-bits in some rare cases\n    see->Summ = (UInt16)(see->Summ + freqSum);\n\n    s = Ppmd7_GetStats(p, p->MinContext);\n    s2 = s + p->MinContext->NumStats;\n    do\n    {\n      MASK(s->Symbol) = 0;\n      s++;\n    }\n    while (s != s2);\n  }\n}\n\n/*\nByte *Ppmd7z_DecodeSymbols(CPpmd7 *p, Byte *buf, const Byte *lim)\n{\n  int sym = 0;\n  if (buf != lim)\n  do\n  {\n    sym = Ppmd7z_DecodeSymbol(p);\n    if (sym < 0)\n      break;\n    *buf = (Byte)sym;\n  }\n  while (++buf < lim);\n  p->LastSymbol = sym;\n  return buf;\n}\n*/\n\n#undef kTopValue\n#undef READ_BYTE\n#undef RC_NORM_BASE\n#undef RC_NORM_1\n#undef RC_NORM\n#undef RC_NORM_LOCAL\n#undef RC_NORM_REMOTE\n#undef R\n#undef RC_Decode\n#undef RC_DecodeFinal\n#undef RC_GetThreshold\n#undef CTX\n#undef SUCCESSOR\n#undef MASK\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd7Enc.c",
    "content": "﻿/* Ppmd7Enc.c -- Ppmd7z (PPMdH with 7z Range Coder) Encoder\n2023-09-07 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.H (2001): Dmitry Shkarin : Public domain */\n\n\n#include \"Precomp.h\"\n\n#include \"Ppmd7.h\"\n\n#define kTopValue ((UInt32)1 << 24)\n\n#define R (&p->rc.enc)\n\nvoid Ppmd7z_Init_RangeEnc(CPpmd7 *p)\n{\n  R->Low = 0;\n  R->Range = 0xFFFFFFFF;\n  R->Cache = 0;\n  R->CacheSize = 1;\n}\n\nZ7_NO_INLINE\nstatic void Ppmd7z_RangeEnc_ShiftLow(CPpmd7 *p)\n{\n  if ((UInt32)R->Low < (UInt32)0xFF000000 || (unsigned)(R->Low >> 32) != 0)\n  {\n    Byte temp = R->Cache;\n    do\n    {\n      IByteOut_Write(R->Stream, (Byte)(temp + (Byte)(R->Low >> 32)));\n      temp = 0xFF;\n    }\n    while (--R->CacheSize != 0);\n    R->Cache = (Byte)((UInt32)R->Low >> 24);\n  }\n  R->CacheSize++;\n  R->Low = (UInt32)((UInt32)R->Low << 8);\n}\n\n#define RC_NORM_BASE(p) if (R->Range < kTopValue) { R->Range <<= 8;  Ppmd7z_RangeEnc_ShiftLow(p);\n#define RC_NORM_1(p)    RC_NORM_BASE(p) }\n#define RC_NORM(p)      RC_NORM_BASE(p)  RC_NORM_BASE(p) }}\n\n// we must use only one type of Normalization from two: LOCAL or REMOTE\n#define RC_NORM_LOCAL(p)    // RC_NORM(p)\n#define RC_NORM_REMOTE(p)   RC_NORM(p)\n\n/*\n#define Ppmd7z_RangeEnc_Encode(p, start, _size_) \\\n  { UInt32 size = _size_; \\\n    R->Low += start * R->Range; \\\n    R->Range *= size; \\\n    RC_NORM_LOCAL(p); }\n*/\n\nZ7_FORCE_INLINE\n// Z7_NO_INLINE\nstatic void Ppmd7z_RangeEnc_Encode(CPpmd7 *p, UInt32 start, UInt32 size)\n{\n  R->Low += start * R->Range;\n  R->Range *= size;\n  RC_NORM_LOCAL(p)\n}\n\nvoid Ppmd7z_Flush_RangeEnc(CPpmd7 *p)\n{\n  unsigned i;\n  for (i = 0; i < 5; i++)\n    Ppmd7z_RangeEnc_ShiftLow(p);\n}\n\n\n\n#define RC_Encode(start, size)  Ppmd7z_RangeEnc_Encode(p, start, size);\n#define RC_EncodeFinal(start, size)  RC_Encode(start, size) RC_NORM_REMOTE(p)\n\n#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))\n#define SUFFIX(ctx) CTX((ctx)->Suffix)\n// typedef CPpmd7_Context * CTX_PTR;\n#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)\n\nvoid Ppmd7_UpdateModel(CPpmd7 *p);\n\n#define MASK(sym)  ((Byte *)charMask)[sym]\n\nZ7_FORCE_INLINE\nstatic\nvoid Ppmd7z_EncodeSymbol(CPpmd7 *p, int symbol)\n{\n  size_t charMask[256 / sizeof(size_t)];\n  \n  if (p->MinContext->NumStats != 1)\n  {\n    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);\n    UInt32 sum;\n    unsigned i;\n   \n\n    \n    \n    R->Range /= p->MinContext->Union2.SummFreq;\n    \n    if (s->Symbol == symbol)\n    {\n      // R->Range /= p->MinContext->Union2.SummFreq;\n      RC_EncodeFinal(0, s->Freq)\n      p->FoundState = s;\n      Ppmd7_Update1_0(p);\n      return;\n    }\n    p->PrevSuccess = 0;\n    sum = s->Freq;\n    i = (unsigned)p->MinContext->NumStats - 1;\n    do\n    {\n      if ((++s)->Symbol == symbol)\n      {\n        // R->Range /= p->MinContext->Union2.SummFreq;\n        RC_EncodeFinal(sum, s->Freq)\n        p->FoundState = s;\n        Ppmd7_Update1(p);\n        return;\n      }\n      sum += s->Freq;\n    }\n    while (--i);\n\n    // R->Range /= p->MinContext->Union2.SummFreq;\n    RC_Encode(sum, p->MinContext->Union2.SummFreq - sum)\n    \n    p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol);\n    PPMD_SetAllBitsIn256Bytes(charMask)\n    // MASK(s->Symbol) = 0;\n    // i = p->MinContext->NumStats - 1;\n    // do { MASK((--s)->Symbol) = 0; } while (--i);\n    {\n      CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);\n      MASK(s->Symbol) = 0;\n      do\n      {\n        const unsigned sym0 = s2[0].Symbol;\n        const unsigned sym1 = s2[1].Symbol;\n        s2 += 2;\n        MASK(sym0) = 0;\n        MASK(sym1) = 0;\n      }\n      while (s2 < s);\n    }\n  }\n  else\n  {\n    UInt16 *prob = Ppmd7_GetBinSumm(p);\n    CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);\n    UInt32 pr = *prob;\n    const UInt32 bound = (R->Range >> 14) * pr;\n    pr = PPMD_UPDATE_PROB_1(pr);\n    if (s->Symbol == symbol)\n    {\n      *prob = (UInt16)(pr + (1 << PPMD_INT_BITS));\n      // RangeEnc_EncodeBit_0(p, bound);\n      R->Range = bound;\n      RC_NORM_1(p)\n      \n      // p->FoundState = s;\n      // Ppmd7_UpdateBin(p);\n      {\n        const unsigned freq = s->Freq;\n        CPpmd7_Context *c = CTX(SUCCESSOR(s));\n        p->FoundState = s;\n        p->PrevSuccess = 1;\n        p->RunLength++;\n        s->Freq = (Byte)(freq + (freq < 128));\n        // NextContext(p);\n        if (p->OrderFall == 0 && (const Byte *)c > p->Text)\n          p->MaxContext = p->MinContext = c;\n        else\n          Ppmd7_UpdateModel(p);\n      }\n      return;\n    }\n\n    *prob = (UInt16)pr;\n    p->InitEsc = p->ExpEscape[pr >> 10];\n    // RangeEnc_EncodeBit_1(p, bound);\n    R->Low += bound;\n    R->Range -= bound;\n    RC_NORM_LOCAL(p)\n    \n    PPMD_SetAllBitsIn256Bytes(charMask)\n    MASK(s->Symbol) = 0;\n    p->PrevSuccess = 0;\n  }\n\n  for (;;)\n  {\n    CPpmd_See *see;\n    CPpmd_State *s;\n    UInt32 sum, escFreq;\n    CPpmd7_Context *mc;\n    unsigned i, numMasked;\n    \n    RC_NORM_REMOTE(p)\n\n    mc = p->MinContext;\n    numMasked = mc->NumStats;\n\n    do\n    {\n      p->OrderFall++;\n      if (!mc->Suffix)\n        return; /* EndMarker (symbol = -1) */\n      mc = Ppmd7_GetContext(p, mc->Suffix);\n      i = mc->NumStats;\n    }\n    while (i == numMasked);\n\n    p->MinContext = mc;\n    \n    // see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq);\n    {\n      if (i != 256)\n      {\n        unsigned nonMasked = i - numMasked;\n        see = p->See[(unsigned)p->NS2Indx[(size_t)nonMasked - 1]]\n            + p->HiBitsFlag\n            + (nonMasked < (unsigned)SUFFIX(mc)->NumStats - i)\n            + 2 * (unsigned)(mc->Union2.SummFreq < 11 * i)\n            + 4 * (unsigned)(numMasked > nonMasked);\n        {\n          // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ\n          unsigned summ = (UInt16)see->Summ; // & 0xFFFF\n          unsigned r = (summ >> see->Shift);\n          see->Summ = (UInt16)(summ - r);\n          escFreq = r + (r == 0);\n        }\n      }\n      else\n      {\n        see = &p->DummySee;\n        escFreq = 1;\n      }\n    }\n\n    s = Ppmd7_GetStats(p, mc);\n    sum = 0;\n    // i = mc->NumStats;\n\n    do\n    {\n      const unsigned cur = s->Symbol;\n      if ((int)cur == symbol)\n      {\n        const UInt32 low = sum;\n        const UInt32 freq = s->Freq;\n        unsigned num2;\n\n        Ppmd_See_UPDATE(see)\n        p->FoundState = s;\n        sum += escFreq;\n\n        num2 = i / 2;\n        i &= 1;\n        sum += freq & (0 - (UInt32)i);\n        if (num2 != 0)\n        {\n          s += i;\n          do\n          {\n            const unsigned sym0 = s[0].Symbol;\n            const unsigned sym1 = s[1].Symbol;\n            s += 2;\n            sum += (s[-2].Freq & (unsigned)(MASK(sym0)));\n            sum += (s[-1].Freq & (unsigned)(MASK(sym1)));\n          }\n          while (--num2);\n        }\n\n        \n        R->Range /= sum;\n        RC_EncodeFinal(low, freq)\n        Ppmd7_Update2(p);\n        return;\n      }\n      sum += (s->Freq & (unsigned)(MASK(cur)));\n      s++;\n    }\n    while (--i);\n    \n    {\n      const UInt32 total = sum + escFreq;\n      see->Summ = (UInt16)(see->Summ + total);\n\n      R->Range /= total;\n      RC_Encode(sum, escFreq)\n    }\n\n    {\n      const CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);\n      s--;\n      MASK(s->Symbol) = 0;\n      do\n      {\n        const unsigned sym0 = s2[0].Symbol;\n        const unsigned sym1 = s2[1].Symbol;\n        s2 += 2;\n        MASK(sym0) = 0;\n        MASK(sym1) = 0;\n      }\n      while (s2 < s);\n    }\n  }\n}\n\n\nvoid Ppmd7z_EncodeSymbols(CPpmd7 *p, const Byte *buf, const Byte *lim)\n{\n  for (; buf < lim; buf++)\n  {\n    Ppmd7z_EncodeSymbol(p, *buf);\n  }\n}\n\n#undef kTopValue\n#undef WRITE_BYTE\n#undef RC_NORM_BASE\n#undef RC_NORM_1\n#undef RC_NORM\n#undef RC_NORM_LOCAL\n#undef RC_NORM_REMOTE\n#undef R\n#undef RC_Encode\n#undef RC_EncodeFinal\n#undef SUFFIX\n#undef CTX\n#undef SUCCESSOR\n#undef MASK\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd7aDec.c",
    "content": "﻿/* Ppmd7aDec.c -- PPMd7a (PPMdH) Decoder\n2023-09-07 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.H (2001): Dmitry Shkarin : Public domain\n  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Ppmd7.h\"\n\n#define kTop ((UInt32)1 << 24)\n#define kBot ((UInt32)1 << 15)\n\n#define READ_BYTE(p) IByteIn_Read((p)->Stream)\n\nBoolInt Ppmd7a_RangeDec_Init(CPpmd7_RangeDec *p)\n{\n  unsigned i;\n  p->Code = 0;\n  p->Range = 0xFFFFFFFF;\n  p->Low = 0;\n  \n  for (i = 0; i < 4; i++)\n    p->Code = (p->Code << 8) | READ_BYTE(p);\n  return (p->Code < 0xFFFFFFFF);\n}\n\n#define RC_NORM(p) \\\n  while ((p->Low ^ (p->Low + p->Range)) < kTop \\\n    || (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) { \\\n      p->Code = (p->Code << 8) | READ_BYTE(p); \\\n      p->Range <<= 8; p->Low <<= 8; }\n\n// we must use only one type of Normalization from two: LOCAL or REMOTE\n#define RC_NORM_LOCAL(p)    // RC_NORM(p)\n#define RC_NORM_REMOTE(p)   RC_NORM(p)\n\n#define R (&p->rc.dec)\n\nZ7_FORCE_INLINE\n// Z7_NO_INLINE\nstatic void Ppmd7a_RD_Decode(CPpmd7 *p, UInt32 start, UInt32 size)\n{\n  start *= R->Range;\n  R->Low += start;\n  R->Code -= start;\n  R->Range *= size;\n  RC_NORM_LOCAL(R)\n}\n\n#define RC_Decode(start, size)  Ppmd7a_RD_Decode(p, start, size);\n#define RC_DecodeFinal(start, size)  RC_Decode(start, size)  RC_NORM_REMOTE(R)\n#define RC_GetThreshold(total)  (R->Code / (R->Range /= (total)))\n\n\n#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref))\ntypedef CPpmd7_Context * CTX_PTR;\n#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)\nvoid Ppmd7_UpdateModel(CPpmd7 *p);\n\n#define MASK(sym)  ((Byte *)charMask)[sym]\n\n\nint Ppmd7a_DecodeSymbol(CPpmd7 *p)\n{\n  size_t charMask[256 / sizeof(size_t)];\n\n  if (p->MinContext->NumStats != 1)\n  {\n    CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext);\n    unsigned i;\n    UInt32 count, hiCnt;\n    const UInt32 summFreq = p->MinContext->Union2.SummFreq;\n\n    if (summFreq > R->Range)\n      return PPMD7_SYM_ERROR;\n\n    count = RC_GetThreshold(summFreq);\n    hiCnt = count;\n    \n    if ((Int32)(count -= s->Freq) < 0)\n    {\n      Byte sym;\n      RC_DecodeFinal(0, s->Freq)\n      p->FoundState = s;\n      sym = s->Symbol;\n      Ppmd7_Update1_0(p);\n      return sym;\n    }\n  \n    p->PrevSuccess = 0;\n    i = (unsigned)p->MinContext->NumStats - 1;\n    \n    do\n    {\n      if ((Int32)(count -= (++s)->Freq) < 0)\n      {\n        Byte sym;\n        RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)\n        p->FoundState = s;\n        sym = s->Symbol;\n        Ppmd7_Update1(p);\n        return sym;\n      }\n    }\n    while (--i);\n    \n    if (hiCnt >= summFreq)\n      return PPMD7_SYM_ERROR;\n    \n    hiCnt -= count;\n    RC_Decode(hiCnt, summFreq - hiCnt)\n\n    p->HiBitsFlag = PPMD7_HiBitsFlag_3(p->FoundState->Symbol);\n    PPMD_SetAllBitsIn256Bytes(charMask)\n    // i = p->MinContext->NumStats - 1;\n    // do { MASK((--s)->Symbol) = 0; } while (--i);\n    {\n      CPpmd_State *s2 = Ppmd7_GetStats(p, p->MinContext);\n      MASK(s->Symbol) = 0;\n      do\n      {\n        const unsigned sym0 = s2[0].Symbol;\n        const unsigned sym1 = s2[1].Symbol;\n        s2 += 2;\n        MASK(sym0) = 0;\n        MASK(sym1) = 0;\n      }\n      while (s2 < s);\n    }\n  }\n  else\n  {\n    CPpmd_State *s = Ppmd7Context_OneState(p->MinContext);\n    UInt16 *prob = Ppmd7_GetBinSumm(p);\n    UInt32 pr = *prob;\n    UInt32 size0 = (R->Range >> 14) * pr;\n    pr = PPMD_UPDATE_PROB_1(pr);\n\n    if (R->Code < size0)\n    {\n      Byte sym;\n      *prob = (UInt16)(pr + (1 << PPMD_INT_BITS));\n      \n      // RangeDec_DecodeBit0(size0);\n      R->Range = size0;\n      RC_NORM(R)\n      \n        \n        \n      // sym = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol;\n      // Ppmd7_UpdateBin(p);\n      {\n        unsigned freq = s->Freq;\n        CTX_PTR c = CTX(SUCCESSOR(s));\n        sym = s->Symbol;\n        p->FoundState = s;\n        p->PrevSuccess = 1;\n        p->RunLength++;\n        s->Freq = (Byte)(freq + (freq < 128));\n        // NextContext(p);\n        if (p->OrderFall == 0 && (const Byte *)c > p->Text)\n          p->MaxContext = p->MinContext = c;\n        else\n          Ppmd7_UpdateModel(p);\n      }\n      return sym;\n    }\n\n    *prob = (UInt16)pr;\n    p->InitEsc = p->ExpEscape[pr >> 10];\n\n    // RangeDec_DecodeBit1(size0);\n    R->Low += size0;\n    R->Code -= size0;\n    R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - size0;\n    RC_NORM_LOCAL(R)\n    \n    PPMD_SetAllBitsIn256Bytes(charMask)\n    MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0;\n    p->PrevSuccess = 0;\n  }\n\n  for (;;)\n  {\n    CPpmd_State *s, *s2;\n    UInt32 freqSum, count, hiCnt;\n\n    CPpmd_See *see;\n    CPpmd7_Context *mc;\n    unsigned numMasked;\n    RC_NORM_REMOTE(R)\n    mc = p->MinContext;\n    numMasked = mc->NumStats;\n\n    do\n    {\n      p->OrderFall++;\n      if (!mc->Suffix)\n        return PPMD7_SYM_END;\n      mc = Ppmd7_GetContext(p, mc->Suffix);\n    }\n    while (mc->NumStats == numMasked);\n    \n    s = Ppmd7_GetStats(p, mc);\n\n    {\n      unsigned num = mc->NumStats;\n      unsigned num2 = num / 2;\n      \n      num &= 1;\n      hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);\n      s += num;\n      p->MinContext = mc;\n\n      do\n      {\n        const unsigned sym0 = s[0].Symbol;\n        const unsigned sym1 = s[1].Symbol;\n        s += 2;\n        hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));\n        hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));\n      }\n      while (--num2);\n    }\n\n    see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum);\n    freqSum += hiCnt;\n\n    if (freqSum > R->Range)\n      return PPMD7_SYM_ERROR;\n\n    count = RC_GetThreshold(freqSum);\n    \n    if (count < hiCnt)\n    {\n      Byte sym;\n\n      s = Ppmd7_GetStats(p, p->MinContext);\n      hiCnt = count;\n      // count -= s->Freq & (UInt32)(MASK(s->Symbol));\n      // if ((Int32)count >= 0)\n      {\n        for (;;)\n        {\n          count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;\n          // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;\n        }\n      }\n      s--;\n      RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)\n\n      // new (see->Summ) value can overflow over 16-bits in some rare cases\n      Ppmd_See_UPDATE(see)\n      p->FoundState = s;\n      sym = s->Symbol;\n      Ppmd7_Update2(p);\n      return sym;\n    }\n\n    if (count >= freqSum)\n      return PPMD7_SYM_ERROR;\n    \n    RC_Decode(hiCnt, freqSum - hiCnt)\n\n    // We increase (see->Summ) for sum of Freqs of all non_Masked symbols.\n    // new (see->Summ) value can overflow over 16-bits in some rare cases\n    see->Summ = (UInt16)(see->Summ + freqSum);\n\n    s = Ppmd7_GetStats(p, p->MinContext);\n    s2 = s + p->MinContext->NumStats;\n    do\n    {\n      MASK(s->Symbol) = 0;\n      s++;\n    }\n    while (s != s2);\n  }\n}\n\n#undef kTop\n#undef kBot\n#undef READ_BYTE\n#undef RC_NORM_BASE\n#undef RC_NORM_1\n#undef RC_NORM\n#undef RC_NORM_LOCAL\n#undef RC_NORM_REMOTE\n#undef R\n#undef RC_Decode\n#undef RC_DecodeFinal\n#undef RC_GetThreshold\n#undef CTX\n#undef SUCCESSOR\n#undef MASK\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd8.c",
    "content": "﻿/* Ppmd8.c -- PPMdI codec\n2023-09-07 : Igor Pavlov : Public domain\nThis code is based on PPMd var.I (2002): Dmitry Shkarin : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n#include \"Ppmd8.h\"\n\n\n\n\nMY_ALIGN(16)\nstatic const Byte PPMD8_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };\nMY_ALIGN(16)\nstatic const UInt16 PPMD8_kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051};\n\n#define MAX_FREQ 124\n#define UNIT_SIZE 12\n\n#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE)\n#define U2I(nu) (p->Units2Indx[(size_t)(nu) - 1])\n#define I2U(indx) ((unsigned)p->Indx2Units[indx])\n\n\n#define REF(ptr) Ppmd_GetRef(p, ptr)\n\n#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr))\n\n#define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))\n#define STATS(ctx) Ppmd8_GetStats(p, ctx)\n#define ONE_STATE(ctx) Ppmd8Context_OneState(ctx)\n#define SUFFIX(ctx) CTX((ctx)->Suffix)\n\ntypedef CPpmd8_Context * PPMD8_CTX_PTR;\n\nstruct CPpmd8_Node_;\n\ntypedef Ppmd_Ref_Type(struct CPpmd8_Node_) CPpmd8_Node_Ref;\n\ntypedef struct CPpmd8_Node_\n{\n  UInt32 Stamp;\n  \n  CPpmd8_Node_Ref Next;\n  UInt32 NU;\n} CPpmd8_Node;\n\n#define NODE(r)  Ppmd_GetPtr_Type(p, r, CPpmd8_Node)\n\nvoid Ppmd8_Construct(CPpmd8 *p)\n{\n  unsigned i, k, m;\n\n  p->Base = NULL;\n\n  for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++)\n  {\n    unsigned step = (i >= 12 ? 4 : (i >> 2) + 1);\n    do { p->Units2Indx[k++] = (Byte)i; } while (--step);\n    p->Indx2Units[i] = (Byte)k;\n  }\n\n  p->NS2BSIndx[0] = (0 << 1);\n  p->NS2BSIndx[1] = (1 << 1);\n  memset(p->NS2BSIndx + 2, (2 << 1), 9);\n  memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11);\n\n  for (i = 0; i < 5; i++)\n    p->NS2Indx[i] = (Byte)i;\n  \n  for (m = i, k = 1; i < 260; i++)\n  {\n    p->NS2Indx[i] = (Byte)m;\n    if (--k == 0)\n      k = (++m) - 4;\n  }\n\n  memcpy(p->ExpEscape, PPMD8_kExpEscape, 16);\n}\n\n\nvoid Ppmd8_Free(CPpmd8 *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->Base);\n  p->Size = 0;\n  p->Base = NULL;\n}\n\n\nBoolInt Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAllocPtr alloc)\n{\n  if (!p->Base || p->Size != size)\n  {\n    Ppmd8_Free(p, alloc);\n    p->AlignOffset = (4 - size) & 3;\n    if ((p->Base = (Byte *)ISzAlloc_Alloc(alloc, p->AlignOffset + size)) == NULL)\n      return False;\n    p->Size = size;\n  }\n  return True;\n}\n\n\n\n// ---------- Internal Memory Allocator ----------\n\n\n\n\n\n\n#define EMPTY_NODE 0xFFFFFFFF\n\n\nstatic void Ppmd8_InsertNode(CPpmd8 *p, void *node, unsigned indx)\n{\n  ((CPpmd8_Node *)node)->Stamp = EMPTY_NODE;\n  ((CPpmd8_Node *)node)->Next = (CPpmd8_Node_Ref)p->FreeList[indx];\n  ((CPpmd8_Node *)node)->NU = I2U(indx);\n  p->FreeList[indx] = REF(node);\n  p->Stamps[indx]++;\n}\n\n\nstatic void *Ppmd8_RemoveNode(CPpmd8 *p, unsigned indx)\n{\n  CPpmd8_Node *node = NODE((CPpmd8_Node_Ref)p->FreeList[indx]);\n  p->FreeList[indx] = node->Next;\n  p->Stamps[indx]--;\n\n  return node;\n}\n\n\nstatic void Ppmd8_SplitBlock(CPpmd8 *p, void *ptr, unsigned oldIndx, unsigned newIndx)\n{\n  unsigned i, nu = I2U(oldIndx) - I2U(newIndx);\n  ptr = (Byte *)ptr + U2B(I2U(newIndx));\n  if (I2U(i = U2I(nu)) != nu)\n  {\n    unsigned k = I2U(--i);\n    Ppmd8_InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1);\n  }\n  Ppmd8_InsertNode(p, ptr, i);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nstatic void Ppmd8_GlueFreeBlocks(CPpmd8 *p)\n{\n  /*\n  we use first UInt32 field of 12-bytes UNITs as record type stamp\n    CPpmd_State    { Byte Symbol; Byte Freq; : Freq != 0xFF\n    CPpmd8_Context { Byte NumStats; Byte Flags; UInt16 SummFreq;  : Flags != 0xFF ???\n    CPpmd8_Node    { UInt32 Stamp            : Stamp == 0xFFFFFFFF for free record\n                                             : Stamp == 0 for guard\n    Last 12-bytes UNIT in array is always contains 12-bytes order-0 CPpmd8_Context record\n  */\n  CPpmd8_Node_Ref n;\n\n  p->GlueCount = 1 << 13;\n  memset(p->Stamps, 0, sizeof(p->Stamps));\n  \n  /* we set guard NODE at LoUnit */\n  if (p->LoUnit != p->HiUnit)\n    ((CPpmd8_Node *)(void *)p->LoUnit)->Stamp = 0;\n\n  {\n    /* Glue free blocks */\n    CPpmd8_Node_Ref *prev = &n;\n    unsigned i;\n    for (i = 0; i < PPMD_NUM_INDEXES; i++)\n    {\n\n      CPpmd8_Node_Ref next = (CPpmd8_Node_Ref)p->FreeList[i];\n      p->FreeList[i] = 0;\n      while (next != 0)\n      {\n        CPpmd8_Node *node = NODE(next);\n        UInt32 nu = node->NU;\n        *prev = next;\n        next = node->Next;\n        if (nu != 0)\n        {\n          CPpmd8_Node *node2;\n          prev = &(node->Next);\n          while ((node2 = node + nu)->Stamp == EMPTY_NODE)\n          {\n            nu += node2->NU;\n            node2->NU = 0;\n            node->NU = nu;\n          }\n        }\n      }\n    }\n\n    *prev = 0;\n  }\n\n\n\n  \n\n\n\n\n\n\n  \n\n  \n  \n  \n  \n  \n  \n  \n  \n  /* Fill lists of free blocks */\n  while (n != 0)\n  {\n    CPpmd8_Node *node = NODE(n);\n    UInt32 nu = node->NU;\n    unsigned i;\n    n = node->Next;\n    if (nu == 0)\n      continue;\n    for (; nu > 128; nu -= 128, node += 128)\n      Ppmd8_InsertNode(p, node, PPMD_NUM_INDEXES - 1);\n    if (I2U(i = U2I(nu)) != nu)\n    {\n      unsigned k = I2U(--i);\n      Ppmd8_InsertNode(p, node + k, (unsigned)nu - k - 1);\n    }\n    Ppmd8_InsertNode(p, node, i);\n  }\n}\n\n\nZ7_NO_INLINE\nstatic void *Ppmd8_AllocUnitsRare(CPpmd8 *p, unsigned indx)\n{\n  unsigned i;\n  \n  if (p->GlueCount == 0)\n  {\n    Ppmd8_GlueFreeBlocks(p);\n    if (p->FreeList[indx] != 0)\n      return Ppmd8_RemoveNode(p, indx);\n  }\n  \n  i = indx;\n  \n  do\n  {\n    if (++i == PPMD_NUM_INDEXES)\n    {\n      UInt32 numBytes = U2B(I2U(indx));\n      Byte *us = p->UnitsStart;\n      p->GlueCount--;\n      return ((UInt32)(us - p->Text) > numBytes) ? (p->UnitsStart = us - numBytes) : (NULL);\n    }\n  }\n  while (p->FreeList[i] == 0);\n  \n  {\n    void *block = Ppmd8_RemoveNode(p, i);\n    Ppmd8_SplitBlock(p, block, i, indx);\n    return block;\n  }\n}\n\n\nstatic void *Ppmd8_AllocUnits(CPpmd8 *p, unsigned indx)\n{\n  if (p->FreeList[indx] != 0)\n    return Ppmd8_RemoveNode(p, indx);\n  {\n    UInt32 numBytes = U2B(I2U(indx));\n    Byte *lo = p->LoUnit;\n    if ((UInt32)(p->HiUnit - lo) >= numBytes)\n    {\n      p->LoUnit = lo + numBytes;\n      return lo;\n    }\n  }\n  return Ppmd8_AllocUnitsRare(p, indx);\n}\n\n\n#define MEM_12_CPY(dest, src, num) \\\n  { UInt32 *d = (UInt32 *)(dest); \\\n    const UInt32 *z = (const UInt32 *)(src); \\\n    unsigned n = (num); \\\n    do { \\\n      d[0] = z[0]; \\\n      d[1] = z[1]; \\\n      d[2] = z[2]; \\\n      z += 3; \\\n      d += 3; \\\n    } while (--n); \\\n  }\n\n\n\nstatic void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)\n{\n  unsigned i0 = U2I(oldNU);\n  unsigned i1 = U2I(newNU);\n  if (i0 == i1)\n    return oldPtr;\n  if (p->FreeList[i1] != 0)\n  {\n    void *ptr = Ppmd8_RemoveNode(p, i1);\n    MEM_12_CPY(ptr, oldPtr, newNU)\n    Ppmd8_InsertNode(p, oldPtr, i0);\n    return ptr;\n  }\n  Ppmd8_SplitBlock(p, oldPtr, i0, i1);\n  return oldPtr;\n}\n\n\nstatic void FreeUnits(CPpmd8 *p, void *ptr, unsigned nu)\n{\n  Ppmd8_InsertNode(p, ptr, U2I(nu));\n}\n\n\nstatic void SpecialFreeUnit(CPpmd8 *p, void *ptr)\n{\n  if ((Byte *)ptr != p->UnitsStart)\n    Ppmd8_InsertNode(p, ptr, 0);\n  else\n  {\n    #ifdef PPMD8_FREEZE_SUPPORT\n    *(UInt32 *)ptr = EMPTY_NODE; /* it's used for (Flags == 0xFF) check in RemoveBinContexts() */\n    #endif\n    p->UnitsStart += UNIT_SIZE;\n  }\n}\n\n\n/*\nstatic void *MoveUnitsUp(CPpmd8 *p, void *oldPtr, unsigned nu)\n{\n  unsigned indx = U2I(nu);\n  void *ptr;\n  if ((Byte *)oldPtr > p->UnitsStart + (1 << 14) || REF(oldPtr) > p->FreeList[indx])\n    return oldPtr;\n  ptr = Ppmd8_RemoveNode(p, indx);\n  MEM_12_CPY(ptr, oldPtr, nu)\n  if ((Byte *)oldPtr != p->UnitsStart)\n    Ppmd8_InsertNode(p, oldPtr, indx);\n  else\n    p->UnitsStart += U2B(I2U(indx));\n  return ptr;\n}\n*/\n\nstatic void ExpandTextArea(CPpmd8 *p)\n{\n  UInt32 count[PPMD_NUM_INDEXES];\n  unsigned i;\n \n  memset(count, 0, sizeof(count));\n  if (p->LoUnit != p->HiUnit)\n    ((CPpmd8_Node *)(void *)p->LoUnit)->Stamp = 0;\n  \n  {\n    CPpmd8_Node *node = (CPpmd8_Node *)(void *)p->UnitsStart;\n    while (node->Stamp == EMPTY_NODE)\n    {\n      UInt32 nu = node->NU;\n      node->Stamp = 0;\n      count[U2I(nu)]++;\n      node += nu;\n    }\n    p->UnitsStart = (Byte *)node;\n  }\n  \n  for (i = 0; i < PPMD_NUM_INDEXES; i++)\n  {\n    UInt32 cnt = count[i];\n    if (cnt == 0)\n      continue;\n    {\n      CPpmd8_Node_Ref *prev = (CPpmd8_Node_Ref *)&p->FreeList[i];\n      CPpmd8_Node_Ref n = *prev;\n      p->Stamps[i] -= cnt;\n      for (;;)\n      {\n        CPpmd8_Node *node = NODE(n);\n        n = node->Next;\n        if (node->Stamp != 0)\n        {\n          prev = &node->Next;\n          continue;\n        }\n        *prev = n;\n        if (--cnt == 0)\n          break;\n      }\n    }\n  }\n}\n\n\n#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)\nstatic void Ppmd8State_SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)\n{\n  Ppmd_SET_SUCCESSOR(p, v)\n}\n\n#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }\n\nZ7_NO_INLINE\nstatic\nvoid Ppmd8_RestartModel(CPpmd8 *p)\n{\n  unsigned i, k, m;\n\n  memset(p->FreeList, 0, sizeof(p->FreeList));\n  memset(p->Stamps, 0, sizeof(p->Stamps));\n  RESET_TEXT(0)\n  p->HiUnit = p->Text + p->Size;\n  p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE;\n  p->GlueCount = 0;\n\n  p->OrderFall = p->MaxOrder;\n  p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1;\n  p->PrevSuccess = 0;\n\n  {\n    CPpmd8_Context *mc = (PPMD8_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */\n    CPpmd_State *s = (CPpmd_State *)p->LoUnit; /* Ppmd8_AllocUnits(p, PPMD_NUM_INDEXES - 1); */\n    \n    p->LoUnit += U2B(256 / 2);\n    p->MaxContext = p->MinContext = mc;\n    p->FoundState = s;\n    mc->Flags = 0;\n    mc->NumStats = 256 - 1;\n    mc->Union2.SummFreq = 256 + 1;\n    mc->Union4.Stats = REF(s);\n    mc->Suffix = 0;\n\n    for (i = 0; i < 256; i++, s++)\n    {\n      s->Symbol = (Byte)i;\n      s->Freq = 1;\n      Ppmd8State_SetSuccessor(s, 0);\n    }\n  }\n\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  for (i = m = 0; m < 25; m++)\n  {\n    while (p->NS2Indx[i] == m)\n      i++;\n    for (k = 0; k < 8; k++)\n    {\n      unsigned r;\n      UInt16 *dest = p->BinSumm[m] + k;\n      const UInt16 val = (UInt16)(PPMD_BIN_SCALE - PPMD8_kInitBinEsc[k] / (i + 1));\n      for (r = 0; r < 64; r += 8)\n        dest[r] = val;\n    }\n  }\n\n  for (i = m = 0; m < 24; m++)\n  {\n    unsigned summ;\n    CPpmd_See *s;\n    while (p->NS2Indx[(size_t)i + 3] == m + 3)\n      i++;\n    s = p->See[m];\n    summ = ((2 * i + 5) << (PPMD_PERIOD_BITS - 4));\n    for (k = 0; k < 32; k++, s++)\n    {\n      s->Summ = (UInt16)summ;\n      s->Shift = (PPMD_PERIOD_BITS - 4);\n      s->Count = 7;\n    }\n  }\n\n  p->DummySee.Summ = 0; /* unused */\n  p->DummySee.Shift = PPMD_PERIOD_BITS;\n  p->DummySee.Count = 64; /* unused */\n}\n\n\nvoid Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod)\n{\n  p->MaxOrder = maxOrder;\n  p->RestoreMethod = restoreMethod;\n  Ppmd8_RestartModel(p);\n}\n\n\n#define FLAG_RESCALED  (1 << 2)\n// #define FLAG_SYM_HIGH  (1 << 3)\n#define FLAG_PREV_HIGH (1 << 4)\n\n#define HiBits_Prepare(sym) ((unsigned)(sym) + 0xC0)\n\n#define HiBits_Convert_3(flags) (((flags) >> (8 - 3)) & (1 << 3))\n#define HiBits_Convert_4(flags) (((flags) >> (8 - 4)) & (1 << 4))\n\n#define PPMD8_HiBitsFlag_3(sym) HiBits_Convert_3(HiBits_Prepare(sym))\n#define PPMD8_HiBitsFlag_4(sym) HiBits_Convert_4(HiBits_Prepare(sym))\n\n// #define PPMD8_HiBitsFlag_3(sym) (0x08 * ((sym) >= 0x40))\n// #define PPMD8_HiBitsFlag_4(sym) (0x10 * ((sym) >= 0x40))\n\n/*\nRefresh() is called when we remove some symbols (successors) in context.\nIt increases Escape_Freq for sum of all removed symbols.\n*/\n\nstatic void Refresh(CPpmd8 *p, PPMD8_CTX_PTR ctx, unsigned oldNU, unsigned scale)\n{\n  unsigned i = ctx->NumStats, escFreq, sumFreq, flags;\n  CPpmd_State *s = (CPpmd_State *)ShrinkUnits(p, STATS(ctx), oldNU, (i + 2) >> 1);\n  ctx->Union4.Stats = REF(s);\n\n  // #ifdef PPMD8_FREEZE_SUPPORT\n  /*\n    (ctx->Union2.SummFreq >= ((UInt32)1 << 15)) can be in FREEZE mode for some files.\n    It's not good for range coder. So new versions of support fix:\n       -   original PPMdI code rev.1\n       +   original PPMdI code rev.2\n       -   7-Zip default ((PPMD8_FREEZE_SUPPORT is not defined)\n       +   7-Zip (p->RestoreMethod >= PPMD8_RESTORE_METHOD_FREEZE)\n    if we       use that fixed line, we can lose compatibility with some files created before fix\n    if we don't use that fixed line, the program can work incorrectly in FREEZE mode in rare case.\n  */\n  // if (p->RestoreMethod >= PPMD8_RESTORE_METHOD_FREEZE)\n  {\n    scale |= (ctx->Union2.SummFreq >= ((UInt32)1 << 15));\n  }\n  // #endif\n\n\n\n  flags = HiBits_Prepare(s->Symbol);\n  {\n    unsigned freq = s->Freq;\n    escFreq = ctx->Union2.SummFreq - freq;\n    freq = (freq + scale) >> scale;\n    sumFreq = freq;\n    s->Freq = (Byte)freq;\n  }\n \n  do\n  {\n    unsigned freq = (++s)->Freq;\n    escFreq -= freq;\n    freq = (freq + scale) >> scale;\n    sumFreq += freq;\n    s->Freq = (Byte)freq;\n    flags |= HiBits_Prepare(s->Symbol);\n  }\n  while (--i);\n  \n  ctx->Union2.SummFreq = (UInt16)(sumFreq + ((escFreq + scale) >> scale));\n  ctx->Flags = (Byte)((ctx->Flags & (FLAG_PREV_HIGH + FLAG_RESCALED * scale)) + HiBits_Convert_3(flags));\n}\n\n\nstatic void SWAP_STATES(CPpmd_State *t1, CPpmd_State *t2)\n{\n  CPpmd_State tmp = *t1;\n  *t1 = *t2;\n  *t2 = tmp;\n}\n\n\n/*\nCutOff() reduces contexts:\n  It conversts Successors at MaxOrder to another Contexts to NULL-Successors\n  It removes RAW-Successors and NULL-Successors that are not Order-0\n      and it removes contexts when it has no Successors.\n  if the (Union4.Stats) is close to (UnitsStart), it moves it up.\n*/\n\nstatic CPpmd_Void_Ref CutOff(CPpmd8 *p, PPMD8_CTX_PTR ctx, unsigned order)\n{\n  int ns = ctx->NumStats;\n  unsigned nu;\n  CPpmd_State *stats;\n  \n  if (ns == 0)\n  {\n    CPpmd_State *s = ONE_STATE(ctx);\n    CPpmd_Void_Ref successor = SUCCESSOR(s);\n    if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart)\n    {\n      if (order < p->MaxOrder)\n        successor = CutOff(p, CTX(successor), order + 1);\n      else\n        successor = 0;\n      Ppmd8State_SetSuccessor(s, successor);\n      if (successor || order <= 9) /* O_BOUND */\n        return REF(ctx);\n    }\n    SpecialFreeUnit(p, ctx);\n    return 0;\n  }\n\n  nu = ((unsigned)ns + 2) >> 1;\n  // ctx->Union4.Stats = STATS_REF(MoveUnitsUp(p, STATS(ctx), nu));\n  {\n    unsigned indx = U2I(nu);\n    stats = STATS(ctx);\n\n    if ((UInt32)((Byte *)stats - p->UnitsStart) <= (1 << 14)\n        && (CPpmd_Void_Ref)ctx->Union4.Stats <= p->FreeList[indx])\n    {\n      void *ptr = Ppmd8_RemoveNode(p, indx);\n      ctx->Union4.Stats = STATS_REF(ptr);\n      MEM_12_CPY(ptr, (const void *)stats, nu)\n      if ((Byte *)stats != p->UnitsStart)\n        Ppmd8_InsertNode(p, stats, indx);\n      else\n        p->UnitsStart += U2B(I2U(indx));\n      stats = ptr;\n    }\n  }\n\n  {\n    CPpmd_State *s = stats + (unsigned)ns;\n    do\n    {\n      CPpmd_Void_Ref successor = SUCCESSOR(s);\n      if ((Byte *)Ppmd8_GetPtr(p, successor) < p->UnitsStart)\n      {\n        CPpmd_State *s2 = stats + (unsigned)(ns--);\n        if (order)\n        {\n          if (s != s2)\n            *s = *s2;\n        }\n        else\n        {\n          SWAP_STATES(s, s2);\n          Ppmd8State_SetSuccessor(s2, 0);\n        }\n      }\n      else\n      {\n        if (order < p->MaxOrder)\n          Ppmd8State_SetSuccessor(s, CutOff(p, CTX(successor), order + 1));\n        else\n          Ppmd8State_SetSuccessor(s, 0);\n      }\n    }\n    while (--s >= stats);\n  }\n  \n  if (ns != ctx->NumStats && order)\n  {\n    if (ns < 0)\n    {\n      FreeUnits(p, stats, nu);\n      SpecialFreeUnit(p, ctx);\n      return 0;\n    }\n    ctx->NumStats = (Byte)ns;\n    if (ns == 0)\n    {\n      const Byte sym = stats->Symbol;\n      ctx->Flags = (Byte)((ctx->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(sym));\n      // *ONE_STATE(ctx) = *stats;\n      ctx->Union2.State2.Symbol = sym;\n      ctx->Union2.State2.Freq = (Byte)(((unsigned)stats->Freq + 11) >> 3);\n      ctx->Union4.State4.Successor_0 = stats->Successor_0;\n      ctx->Union4.State4.Successor_1 = stats->Successor_1;\n      FreeUnits(p, stats, nu);\n    }\n    else\n    {\n      Refresh(p, ctx, nu, ctx->Union2.SummFreq > 16 * (unsigned)ns);\n    }\n  }\n  \n  return REF(ctx);\n}\n\n\n\n#ifdef PPMD8_FREEZE_SUPPORT\n\n/*\nRemoveBinContexts()\n  It conversts Successors at MaxOrder to another Contexts to NULL-Successors\n  It changes RAW-Successors to NULL-Successors\n  removes Bin Context without Successor, if suffix of that context is also binary.\n*/\n\nstatic CPpmd_Void_Ref RemoveBinContexts(CPpmd8 *p, PPMD8_CTX_PTR ctx, unsigned order)\n{\n  if (!ctx->NumStats)\n  {\n    CPpmd_State *s = ONE_STATE(ctx);\n    CPpmd_Void_Ref successor = SUCCESSOR(s);\n    if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart && order < p->MaxOrder)\n      successor = RemoveBinContexts(p, CTX(successor), order + 1);\n    else\n      successor = 0;\n    Ppmd8State_SetSuccessor(s, successor);\n    /* Suffix context can be removed already, since different (high-order)\n       Successors may refer to same context. So we check Flags == 0xFF (Stamp == EMPTY_NODE) */\n    if (!successor && (!SUFFIX(ctx)->NumStats || SUFFIX(ctx)->Flags == 0xFF))\n    {\n      FreeUnits(p, ctx, 1);\n      return 0;\n    }\n  }\n  else\n  {\n    CPpmd_State *s = STATS(ctx) + ctx->NumStats;\n    do\n    {\n      CPpmd_Void_Ref successor = SUCCESSOR(s);\n      if ((Byte *)Ppmd8_GetPtr(p, successor) >= p->UnitsStart && order < p->MaxOrder)\n        Ppmd8State_SetSuccessor(s, RemoveBinContexts(p, CTX(successor), order + 1));\n      else\n        Ppmd8State_SetSuccessor(s, 0);\n    }\n    while (--s >= STATS(ctx));\n  }\n  \n  return REF(ctx);\n}\n\n#endif\n\n\n\nstatic UInt32 GetUsedMemory(const CPpmd8 *p)\n{\n  UInt32 v = 0;\n  unsigned i;\n  for (i = 0; i < PPMD_NUM_INDEXES; i++)\n    v += p->Stamps[i] * I2U(i);\n  return p->Size - (UInt32)(p->HiUnit - p->LoUnit) - (UInt32)(p->UnitsStart - p->Text) - U2B(v);\n}\n\n#ifdef PPMD8_FREEZE_SUPPORT\n  #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1, fSuccessor)\n#else\n  #define RESTORE_MODEL(c1, fSuccessor) RestoreModel(p, c1)\n#endif\n\n\nstatic void RestoreModel(CPpmd8 *p, PPMD8_CTX_PTR ctxError\n    #ifdef PPMD8_FREEZE_SUPPORT\n    , PPMD8_CTX_PTR fSuccessor\n    #endif\n    )\n{\n  PPMD8_CTX_PTR c;\n  CPpmd_State *s;\n  RESET_TEXT(0)\n\n  // we go here in cases of error of allocation for context (c1)\n  // Order(MinContext) < Order(ctxError) <= Order(MaxContext)\n  \n  // We remove last symbol from each of contexts [p->MaxContext ... ctxError) contexts\n  // So we rollback all created (symbols) before error.\n  for (c = p->MaxContext; c != ctxError; c = SUFFIX(c))\n    if (--(c->NumStats) == 0)\n    {\n      s = STATS(c);\n      c->Flags = (Byte)((c->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(s->Symbol));\n      // *ONE_STATE(c) = *s;\n      c->Union2.State2.Symbol = s->Symbol;\n      c->Union2.State2.Freq = (Byte)(((unsigned)s->Freq + 11) >> 3);\n      c->Union4.State4.Successor_0 = s->Successor_0;\n      c->Union4.State4.Successor_1 = s->Successor_1;\n\n      SpecialFreeUnit(p, s);\n    }\n    else\n    {\n      /* Refresh() can increase Escape_Freq on value of Freq of last symbol, that was added before error.\n         so the largest possible increase for Escape_Freq is (8) from value before ModelUpoadet() */\n      Refresh(p, c, ((unsigned)c->NumStats + 3) >> 1, 0);\n    }\n \n  // increase Escape Freq for context [ctxError ... p->MinContext)\n  for (; c != p->MinContext; c = SUFFIX(c))\n    if (c->NumStats == 0)\n    {\n      // ONE_STATE(c)\n      c->Union2.State2.Freq = (Byte)(((unsigned)c->Union2.State2.Freq + 1) >> 1);\n    }\n    else if ((c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 4)) > 128 + 4 * c->NumStats)\n      Refresh(p, c, ((unsigned)c->NumStats + 2) >> 1, 1);\n\n  #ifdef PPMD8_FREEZE_SUPPORT\n  if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\n  {\n    p->MaxContext = fSuccessor;\n    p->GlueCount += !(p->Stamps[1] & 1); // why?\n  }\n  else if (p->RestoreMethod == PPMD8_RESTORE_METHOD_FREEZE)\n  {\n    while (p->MaxContext->Suffix)\n      p->MaxContext = SUFFIX(p->MaxContext);\n    RemoveBinContexts(p, p->MaxContext, 0);\n    // we change the current mode to (PPMD8_RESTORE_METHOD_FREEZE + 1)\n    p->RestoreMethod = PPMD8_RESTORE_METHOD_FREEZE + 1;\n    p->GlueCount = 0;\n    p->OrderFall = p->MaxOrder;\n  }\n  else\n  #endif\n  if (p->RestoreMethod == PPMD8_RESTORE_METHOD_RESTART || GetUsedMemory(p) < (p->Size >> 1))\n    Ppmd8_RestartModel(p);\n  else\n  {\n    while (p->MaxContext->Suffix)\n      p->MaxContext = SUFFIX(p->MaxContext);\n    do\n    {\n      CutOff(p, p->MaxContext, 0);\n      ExpandTextArea(p);\n    }\n    while (GetUsedMemory(p) > 3 * (p->Size >> 2));\n    p->GlueCount = 0;\n    p->OrderFall = p->MaxOrder;\n  }\n  p->MinContext = p->MaxContext;\n}\n\n\n\nZ7_NO_INLINE\nstatic PPMD8_CTX_PTR Ppmd8_CreateSuccessors(CPpmd8 *p, BoolInt skip, CPpmd_State *s1, PPMD8_CTX_PTR c)\n{\n\n  CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState);\n  Byte newSym, newFreq, flags;\n  unsigned numPs = 0;\n  CPpmd_State *ps[PPMD8_MAX_ORDER + 1]; /* fixed over Shkarin's code. Maybe it could work without + 1 too. */\n  \n  if (!skip)\n    ps[numPs++] = p->FoundState;\n  \n  while (c->Suffix)\n  {\n    CPpmd_Void_Ref successor;\n    CPpmd_State *s;\n    c = SUFFIX(c);\n    \n    if (s1) { s = s1; s1 = NULL; }\n    else if (c->NumStats != 0)\n    {\n      Byte sym = p->FoundState->Symbol;\n      for (s = STATS(c); s->Symbol != sym; s++);\n      if (s->Freq < MAX_FREQ - 9) { s->Freq++; c->Union2.SummFreq++; }\n    }\n    else\n    {\n      s = ONE_STATE(c);\n      s->Freq = (Byte)(s->Freq + (!SUFFIX(c)->NumStats & (s->Freq < 24)));\n    }\n    successor = SUCCESSOR(s);\n    if (successor != upBranch)\n    {\n\n      c = CTX(successor);\n      if (numPs == 0)\n      {\n        \n       \n        return c;\n      }\n      break;\n    }\n    ps[numPs++] = s;\n  }\n  \n  \n  \n  \n  \n  newSym = *(const Byte *)Ppmd8_GetPtr(p, upBranch);\n  upBranch++;\n  flags = (Byte)(PPMD8_HiBitsFlag_4(p->FoundState->Symbol) + PPMD8_HiBitsFlag_3(newSym));\n  \n  if (c->NumStats == 0)\n    newFreq = c->Union2.State2.Freq;\n  else\n  {\n    UInt32 cf, s0;\n    CPpmd_State *s;\n    for (s = STATS(c); s->Symbol != newSym; s++);\n    cf = (UInt32)s->Freq - 1;\n    s0 = (UInt32)c->Union2.SummFreq - c->NumStats - cf;\n    /*\n    \n\n      max(newFreq)= (s->Freq - 1), when (s0 == 1)\n\n\n    */\n    newFreq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((cf + 2 * s0 - 3) / s0)));\n  }\n\n\n\n  do\n  {\n    PPMD8_CTX_PTR c1;\n    /* = AllocContext(p); */\n    if (p->HiUnit != p->LoUnit)\n      c1 = (PPMD8_CTX_PTR)(void *)(p->HiUnit -= UNIT_SIZE);\n    else if (p->FreeList[0] != 0)\n      c1 = (PPMD8_CTX_PTR)Ppmd8_RemoveNode(p, 0);\n    else\n    {\n      c1 = (PPMD8_CTX_PTR)Ppmd8_AllocUnitsRare(p, 0);\n      if (!c1)\n        return NULL;\n    }\n    c1->Flags = flags;\n    c1->NumStats = 0;\n    c1->Union2.State2.Symbol = newSym;\n    c1->Union2.State2.Freq = newFreq;\n    Ppmd8State_SetSuccessor(ONE_STATE(c1), upBranch);\n    c1->Suffix = REF(c);\n    Ppmd8State_SetSuccessor(ps[--numPs], REF(c1));\n    c = c1;\n  }\n  while (numPs != 0);\n  \n  return c;\n}\n\n\nstatic PPMD8_CTX_PTR ReduceOrder(CPpmd8 *p, CPpmd_State *s1, PPMD8_CTX_PTR c)\n{\n  CPpmd_State *s = NULL;\n  PPMD8_CTX_PTR c1 = c;\n  CPpmd_Void_Ref upBranch = REF(p->Text);\n  \n  #ifdef PPMD8_FREEZE_SUPPORT\n  /* The BUG in Shkarin's code was fixed: ps could overflow in CUT_OFF mode. */\n  CPpmd_State *ps[PPMD8_MAX_ORDER + 1];\n  unsigned numPs = 0;\n  ps[numPs++] = p->FoundState;\n  #endif\n\n  Ppmd8State_SetSuccessor(p->FoundState, upBranch);\n  p->OrderFall++;\n\n  for (;;)\n  {\n    if (s1)\n    {\n      c = SUFFIX(c);\n      s = s1;\n      s1 = NULL;\n    }\n    else\n    {\n      if (!c->Suffix)\n      {\n        #ifdef PPMD8_FREEZE_SUPPORT\n        if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\n        {\n          do { Ppmd8State_SetSuccessor(ps[--numPs], REF(c)); } while (numPs);\n          RESET_TEXT(1)\n          p->OrderFall = 1;\n        }\n        #endif\n        return c;\n      }\n      c = SUFFIX(c);\n      if (c->NumStats)\n      {\n        if ((s = STATS(c))->Symbol != p->FoundState->Symbol)\n          do { s++; } while (s->Symbol != p->FoundState->Symbol);\n        if (s->Freq < MAX_FREQ - 9)\n        {\n          s->Freq = (Byte)(s->Freq + 2);\n          c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2);\n        }\n      }\n      else\n      {\n        s = ONE_STATE(c);\n        s->Freq = (Byte)(s->Freq + (s->Freq < 32));\n      }\n    }\n    if (SUCCESSOR(s))\n      break;\n    #ifdef PPMD8_FREEZE_SUPPORT\n    ps[numPs++] = s;\n    #endif\n    Ppmd8State_SetSuccessor(s, upBranch);\n    p->OrderFall++;\n  }\n  \n  #ifdef PPMD8_FREEZE_SUPPORT\n  if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\n  {\n    c = CTX(SUCCESSOR(s));\n    do { Ppmd8State_SetSuccessor(ps[--numPs], REF(c)); } while (numPs);\n    RESET_TEXT(1)\n    p->OrderFall = 1;\n    return c;\n  }\n  else\n  #endif\n  if (SUCCESSOR(s) <= upBranch)\n  {\n    PPMD8_CTX_PTR successor;\n    CPpmd_State *s2 = p->FoundState;\n    p->FoundState = s;\n\n    successor = Ppmd8_CreateSuccessors(p, False, NULL, c);\n    if (!successor)\n      Ppmd8State_SetSuccessor(s, 0);\n    else\n      Ppmd8State_SetSuccessor(s, REF(successor));\n    p->FoundState = s2;\n  }\n  \n  {\n    CPpmd_Void_Ref successor = SUCCESSOR(s);\n    if (p->OrderFall == 1 && c1 == p->MaxContext)\n    {\n      Ppmd8State_SetSuccessor(p->FoundState, successor);\n      p->Text--;\n    }\n    if (successor == 0)\n      return NULL;\n    return CTX(successor);\n  }\n}\n\n\n\nvoid Ppmd8_UpdateModel(CPpmd8 *p);\nZ7_NO_INLINE\nvoid Ppmd8_UpdateModel(CPpmd8 *p)\n{\n  CPpmd_Void_Ref maxSuccessor, minSuccessor = SUCCESSOR(p->FoundState);\n  PPMD8_CTX_PTR c;\n  unsigned s0, ns, fFreq = p->FoundState->Freq;\n  Byte flag, fSymbol = p->FoundState->Symbol;\n  {\n  CPpmd_State *s = NULL;\n  if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0)\n  {\n    /* Update Freqs in Suffix Context */\n\n    c = SUFFIX(p->MinContext);\n    \n    if (c->NumStats == 0)\n    {\n      s = ONE_STATE(c);\n      if (s->Freq < 32)\n        s->Freq++;\n    }\n    else\n    {\n      Byte sym = p->FoundState->Symbol;\n      s = STATS(c);\n\n      if (s->Symbol != sym)\n      {\n        do\n        {\n        \n          s++;\n        }\n        while (s->Symbol != sym);\n        \n        if (s[0].Freq >= s[-1].Freq)\n        {\n          SWAP_STATES(&s[0], &s[-1]);\n          s--;\n        }\n      }\n      \n      if (s->Freq < MAX_FREQ - 9)\n      {\n        s->Freq = (Byte)(s->Freq + 2);\n        c->Union2.SummFreq = (UInt16)(c->Union2.SummFreq + 2);\n      }\n    }\n  }\n  \n  c = p->MaxContext;\n  if (p->OrderFall == 0 && minSuccessor)\n  {\n    PPMD8_CTX_PTR cs = Ppmd8_CreateSuccessors(p, True, s, p->MinContext);\n    if (!cs)\n    {\n      Ppmd8State_SetSuccessor(p->FoundState, 0);\n      RESTORE_MODEL(c, CTX(minSuccessor));\n      return;\n    }\n    Ppmd8State_SetSuccessor(p->FoundState, REF(cs));\n    p->MinContext = p->MaxContext = cs;\n    return;\n  }\n  \n\n\n\n  {\n    Byte *text = p->Text;\n    *text++ = p->FoundState->Symbol;\n    p->Text = text;\n    if (text >= p->UnitsStart)\n    {\n      RESTORE_MODEL(c, CTX(minSuccessor)); /* check it */\n      return;\n    }\n    maxSuccessor = REF(text);\n  }\n\n  if (!minSuccessor)\n  {\n    PPMD8_CTX_PTR cs = ReduceOrder(p, s, p->MinContext);\n    if (!cs)\n    {\n      RESTORE_MODEL(c, NULL);\n      return;\n    }\n    minSuccessor = REF(cs);\n  }\n  else if ((Byte *)Ppmd8_GetPtr(p, minSuccessor) < p->UnitsStart)\n  {\n    PPMD8_CTX_PTR cs = Ppmd8_CreateSuccessors(p, False, s, p->MinContext);\n    if (!cs)\n    {\n      RESTORE_MODEL(c, NULL);\n      return;\n    }\n    minSuccessor = REF(cs);\n  }\n  \n  if (--p->OrderFall == 0)\n  {\n    maxSuccessor = minSuccessor;\n    p->Text -= (p->MaxContext != p->MinContext);\n  }\n  #ifdef PPMD8_FREEZE_SUPPORT\n  else if (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE)\n  {\n    maxSuccessor = minSuccessor;\n    RESET_TEXT(0)\n    p->OrderFall = 0;\n  }\n  #endif\n  }\n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n  \n\n  \n  \n  flag = (Byte)(PPMD8_HiBitsFlag_3(fSymbol));\n  s0 = p->MinContext->Union2.SummFreq - (ns = p->MinContext->NumStats) - fFreq;\n  \n  for (; c != p->MinContext; c = SUFFIX(c))\n  {\n    unsigned ns1;\n    UInt32 sum;\n    \n    if ((ns1 = c->NumStats) != 0)\n    {\n      if ((ns1 & 1) != 0)\n      {\n        /* Expand for one UNIT */\n        const unsigned oldNU = (ns1 + 1) >> 1;\n        const unsigned i = U2I(oldNU);\n        if (i != U2I((size_t)oldNU + 1))\n        {\n          void *ptr = Ppmd8_AllocUnits(p, i + 1);\n          void *oldPtr;\n          if (!ptr)\n          {\n            RESTORE_MODEL(c, CTX(minSuccessor));\n            return;\n          }\n          oldPtr = STATS(c);\n          MEM_12_CPY(ptr, oldPtr, oldNU)\n          Ppmd8_InsertNode(p, oldPtr, i);\n          c->Union4.Stats = STATS_REF(ptr);\n        }\n      }\n      sum = c->Union2.SummFreq;\n      /* max increase of Escape_Freq is 1 here.\n         an average increase is 1/3 per symbol */\n      sum += (UInt32)(unsigned)(3 * ns1 + 1 < ns);\n      /* original PPMdH uses 16-bit variable for (sum) here.\n         But (sum < ???). Do we need to truncate (sum) to 16-bit */\n      // sum = (UInt16)sum;\n    }\n    else\n    {\n      \n      CPpmd_State *s = (CPpmd_State*)Ppmd8_AllocUnits(p, 0);\n      if (!s)\n      {\n        RESTORE_MODEL(c, CTX(minSuccessor));\n        return;\n      }\n      {\n        unsigned freq = c->Union2.State2.Freq;\n        // s = *ONE_STATE(c);\n        s->Symbol = c->Union2.State2.Symbol;\n        s->Successor_0 = c->Union4.State4.Successor_0;\n        s->Successor_1 = c->Union4.State4.Successor_1;\n        // Ppmd8State_SetSuccessor(s, c->Union4.Stats);  // call it only for debug purposes to check the order of\n                                              // (Successor_0 and Successor_1) in LE/BE.\n        c->Union4.Stats = REF(s);\n        if (freq < MAX_FREQ / 4 - 1)\n          freq <<= 1;\n        else\n          freq = MAX_FREQ - 4;\n\n        s->Freq = (Byte)freq;\n\n        sum = (UInt32)(freq + p->InitEsc + (ns > 2));   // Ppmd8 (> 2)\n      }\n    }\n\n    {\n      CPpmd_State *s = STATS(c) + ns1 + 1;\n      UInt32 cf = 2 * (sum + 6) * (UInt32)fFreq;\n      UInt32 sf = (UInt32)s0 + sum;\n      s->Symbol = fSymbol;\n      c->NumStats = (Byte)(ns1 + 1);\n      Ppmd8State_SetSuccessor(s, maxSuccessor);\n      c->Flags |= flag;\n      if (cf < 6 * sf)\n      {\n        cf = (unsigned)1 + (cf > sf) + (cf >= 4 * sf);\n        sum += 4;\n        /* It can add (1, 2, 3) to Escape_Freq */\n      }\n      else\n      {\n        cf = (unsigned)4 + (cf > 9 * sf) + (cf > 12 * sf) + (cf > 15 * sf);\n        sum += cf;\n      }\n\n      c->Union2.SummFreq = (UInt16)sum;\n      s->Freq = (Byte)cf;\n    }\n\n  }\n  p->MaxContext = p->MinContext = CTX(minSuccessor);\n}\n  \n\n\nZ7_NO_INLINE\nstatic void Ppmd8_Rescale(CPpmd8 *p)\n{\n  unsigned i, adder, sumFreq, escFreq;\n  CPpmd_State *stats = STATS(p->MinContext);\n  CPpmd_State *s = p->FoundState;\n\n  /* Sort the list by Freq */\n  if (s != stats)\n  {\n    CPpmd_State tmp = *s;\n    do\n      s[0] = s[-1];\n    while (--s != stats);\n    *s = tmp;\n  }\n\n  sumFreq = s->Freq;\n  escFreq = p->MinContext->Union2.SummFreq - sumFreq;\n\n\n  \n  \n  \n  \n  adder = (p->OrderFall != 0);\n  \n  #ifdef PPMD8_FREEZE_SUPPORT\n  adder |= (p->RestoreMethod > PPMD8_RESTORE_METHOD_FREEZE);\n  #endif\n  \n  sumFreq = (sumFreq + 4 + adder) >> 1;\n  i = p->MinContext->NumStats;\n  s->Freq = (Byte)sumFreq;\n  \n  do\n  {\n    unsigned freq = (++s)->Freq;\n    escFreq -= freq;\n    freq = (freq + adder) >> 1;\n    sumFreq += freq;\n    s->Freq = (Byte)freq;\n    if (freq > s[-1].Freq)\n    {\n      CPpmd_State tmp = *s;\n      CPpmd_State *s1 = s;\n      do\n      {\n        s1[0] = s1[-1];\n      }\n      while (--s1 != stats && freq > s1[-1].Freq);\n      *s1 = tmp;\n    }\n  }\n  while (--i);\n  \n  if (s->Freq == 0)\n  {\n    /* Remove all items with Freq == 0 */\n    CPpmd8_Context *mc;\n    unsigned numStats, numStatsNew, n0, n1;\n    \n    i = 0; do { i++; } while ((--s)->Freq == 0);\n    \n    \n\n    \n    escFreq += i;\n    mc = p->MinContext;\n    numStats = mc->NumStats;\n    numStatsNew = numStats - i;\n    mc->NumStats = (Byte)(numStatsNew);\n    n0 = (numStats + 2) >> 1;\n    \n    if (numStatsNew == 0)\n    {\n    \n      unsigned freq = (2 * (unsigned)stats->Freq + escFreq - 1) / escFreq;\n      if (freq > MAX_FREQ / 3)\n        freq = MAX_FREQ / 3;\n      mc->Flags = (Byte)((mc->Flags & FLAG_PREV_HIGH) + PPMD8_HiBitsFlag_3(stats->Symbol));\n      \n      \n      \n      \n      \n      s = ONE_STATE(mc);\n      *s = *stats;\n      s->Freq = (Byte)freq;\n      p->FoundState = s;\n      Ppmd8_InsertNode(p, stats, U2I(n0));\n      return;\n    }\n\n    n1 = (numStatsNew + 2) >> 1;\n    if (n0 != n1)\n      mc->Union4.Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1));\n    {\n      // here we are for max order only. So Ppmd8_MakeEscFreq() doesn't use mc->Flags\n      // but we still need current (Flags & FLAG_PREV_HIGH), if we will convert context to 1-symbol context later.\n      /*\n      unsigned flags = HiBits_Prepare((s = STATS(mc))->Symbol);\n      i = mc->NumStats;\n      do { flags |= HiBits_Prepare((++s)->Symbol); } while (--i);\n      mc->Flags = (Byte)((mc->Flags & ~FLAG_SYM_HIGH) + HiBits_Convert_3(flags));\n      */\n    }\n  }\n\n\n\n  \n\n\n  {\n    CPpmd8_Context *mc = p->MinContext;\n    mc->Union2.SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1));\n    mc->Flags |= FLAG_RESCALED;\n    p->FoundState = STATS(mc);\n  }\n}\n\n\nCPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked1, UInt32 *escFreq)\n{\n  CPpmd_See *see;\n  const CPpmd8_Context *mc = p->MinContext;\n  unsigned numStats = mc->NumStats;\n  if (numStats != 0xFF)\n  {\n    // (3 <= numStats + 2 <= 256)   (3 <= NS2Indx[3] and NS2Indx[256] === 26)\n    see = p->See[(size_t)(unsigned)p->NS2Indx[(size_t)numStats + 2] - 3]\n        + (mc->Union2.SummFreq > 11 * (numStats + 1))\n        + 2 * (unsigned)(2 * numStats < ((unsigned)SUFFIX(mc)->NumStats + numMasked1))\n        + mc->Flags;\n\n    {\n      // if (see->Summ) field is larger than 16-bit, we need only low 16 bits of Summ\n      const unsigned summ = (UInt16)see->Summ; // & 0xFFFF\n      const unsigned r = (summ >> see->Shift);\n      see->Summ = (UInt16)(summ - r);\n      *escFreq = (UInt32)(r + (r == 0));\n    }\n  }\n  else\n  {\n    see = &p->DummySee;\n    *escFreq = 1;\n  }\n  return see;\n}\n\n \nstatic void Ppmd8_NextContext(CPpmd8 *p)\n{\n  PPMD8_CTX_PTR c = CTX(SUCCESSOR(p->FoundState));\n  if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart)\n    p->MaxContext = p->MinContext = c;\n  else\n    Ppmd8_UpdateModel(p);\n}\n \n\nvoid Ppmd8_Update1(CPpmd8 *p)\n{\n  CPpmd_State *s = p->FoundState;\n  unsigned freq = s->Freq;\n  freq += 4;\n  p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);\n  s->Freq = (Byte)freq;\n  if (freq > s[-1].Freq)\n  {\n    SWAP_STATES(s, &s[-1]);\n    p->FoundState = --s;\n    if (freq > MAX_FREQ)\n      Ppmd8_Rescale(p);\n  }\n  Ppmd8_NextContext(p);\n}\n\n\nvoid Ppmd8_Update1_0(CPpmd8 *p)\n{\n  CPpmd_State *s = p->FoundState;\n  CPpmd8_Context *mc = p->MinContext;\n  unsigned freq = s->Freq;\n  const unsigned summFreq = mc->Union2.SummFreq;\n  p->PrevSuccess = (2 * freq >= summFreq); // Ppmd8 (>=)\n  p->RunLength += (Int32)p->PrevSuccess;\n  mc->Union2.SummFreq = (UInt16)(summFreq + 4);\n  freq += 4;\n  s->Freq = (Byte)freq;\n  if (freq > MAX_FREQ)\n    Ppmd8_Rescale(p);\n  Ppmd8_NextContext(p);\n}\n\n\n/*\nvoid Ppmd8_UpdateBin(CPpmd8 *p)\n{\n  unsigned freq = p->FoundState->Freq;\n  p->FoundState->Freq = (Byte)(freq + (freq < 196)); // Ppmd8 (196)\n  p->PrevSuccess = 1;\n  p->RunLength++;\n  Ppmd8_NextContext(p);\n}\n*/\n\nvoid Ppmd8_Update2(CPpmd8 *p)\n{\n  CPpmd_State *s = p->FoundState;\n  unsigned freq = s->Freq;\n  freq += 4;\n  p->RunLength = p->InitRL;\n  p->MinContext->Union2.SummFreq = (UInt16)(p->MinContext->Union2.SummFreq + 4);\n  s->Freq = (Byte)freq;\n  if (freq > MAX_FREQ)\n    Ppmd8_Rescale(p);\n  Ppmd8_UpdateModel(p);\n}\n\n/* H->I changes:\n  NS2Indx\n  GlueCount, and Glue method\n  BinSum\n  See / EscFreq\n  Ppmd8_CreateSuccessors updates more suffix contexts\n  Ppmd8_UpdateModel consts.\n  PrevSuccess Update\n\nFlags:\n  (1 << 2) - the Context was Rescaled\n  (1 << 3) - there is symbol in Stats with (sym >= 0x40) in\n  (1 << 4) - main symbol of context is (sym >= 0x40)\n*/\n\n#undef RESET_TEXT\n#undef FLAG_RESCALED\n#undef FLAG_PREV_HIGH\n#undef HiBits_Prepare\n#undef HiBits_Convert_3\n#undef HiBits_Convert_4\n#undef PPMD8_HiBitsFlag_3\n#undef PPMD8_HiBitsFlag_4\n#undef RESTORE_MODEL\n\n#undef MAX_FREQ\n#undef UNIT_SIZE\n#undef U2B\n#undef U2I\n#undef I2U\n\n#undef REF\n#undef STATS_REF\n#undef CTX\n#undef STATS\n#undef ONE_STATE\n#undef SUFFIX\n#undef NODE\n#undef EMPTY_NODE\n#undef MEM_12_CPY\n#undef SUCCESSOR\n#undef SWAP_STATES\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd8.h",
    "content": "﻿/* Ppmd8.h -- Ppmd8 (PPMdI) compression codec\n2023-04-02 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.I (2002): Dmitry Shkarin : Public domain\n  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\n\n#ifndef ZIP7_INC_PPMD8_H\n#define ZIP7_INC_PPMD8_H\n\n#include \"Ppmd.h\"\n\nEXTERN_C_BEGIN\n\n#define PPMD8_MIN_ORDER 2\n#define PPMD8_MAX_ORDER 16\n\n\n\n\nstruct CPpmd8_Context_;\n\ntypedef Ppmd_Ref_Type(struct CPpmd8_Context_) CPpmd8_Context_Ref;\n\n// MY_CPU_pragma_pack_push_1\n\ntypedef struct CPpmd8_Context_\n{\n  Byte NumStats;\n  Byte Flags;\n  \n  union\n  {\n    UInt16 SummFreq;\n    CPpmd_State2 State2;\n  } Union2;\n  \n  union\n  {\n    CPpmd_State_Ref Stats;\n    CPpmd_State4 State4;\n  } Union4;\n\n  CPpmd8_Context_Ref Suffix;\n} CPpmd8_Context;\n\n// MY_CPU_pragma_pop\n\n#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->Union2)\n\n/* PPMdI code rev.2 contains the fix over PPMdI code rev.1.\n   But the code PPMdI.2 is not compatible with PPMdI.1 for some files compressed\n   in FREEZE mode. So we disable FREEZE mode support. */\n\n// #define PPMD8_FREEZE_SUPPORT\n\nenum\n{\n  PPMD8_RESTORE_METHOD_RESTART,\n  PPMD8_RESTORE_METHOD_CUT_OFF\n  #ifdef PPMD8_FREEZE_SUPPORT\n  , PPMD8_RESTORE_METHOD_FREEZE\n  #endif\n  , PPMD8_RESTORE_METHOD_UNSUPPPORTED\n};\n\n\n\n\n\n\n\n\ntypedef struct\n{\n  CPpmd8_Context *MinContext, *MaxContext;\n  CPpmd_State *FoundState;\n  unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, RestoreMethod;\n  Int32 RunLength, InitRL; /* must be 32-bit at least */\n\n  UInt32 Size;\n  UInt32 GlueCount;\n  UInt32 AlignOffset;\n  Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;\n\n  UInt32 Range;\n  UInt32 Code;\n  UInt32 Low;\n  union\n  {\n    IByteInPtr In;\n    IByteOutPtr Out;\n  } Stream;\n\n  Byte Indx2Units[PPMD_NUM_INDEXES + 2]; // +2 for alignment\n  Byte Units2Indx[128];\n  CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];\n  UInt32 Stamps[PPMD_NUM_INDEXES];\n  Byte NS2BSIndx[256], NS2Indx[260];\n  Byte ExpEscape[16];\n  CPpmd_See DummySee, See[24][32];\n  UInt16 BinSumm[25][64];\n\n} CPpmd8;\n\n\nvoid Ppmd8_Construct(CPpmd8 *p);\nBoolInt Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAllocPtr alloc);\nvoid Ppmd8_Free(CPpmd8 *p, ISzAllocPtr alloc);\nvoid Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);\n#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)\n\n\n/* ---------- Internal Functions ---------- */\n\n#define Ppmd8_GetPtr(p, ptr)     Ppmd_GetPtr(p, ptr)\n#define Ppmd8_GetContext(p, ptr) Ppmd_GetPtr_Type(p, ptr, CPpmd8_Context)\n#define Ppmd8_GetStats(p, ctx)   Ppmd_GetPtr_Type(p, (ctx)->Union4.Stats, CPpmd_State)\n\nvoid Ppmd8_Update1(CPpmd8 *p);\nvoid Ppmd8_Update1_0(CPpmd8 *p);\nvoid Ppmd8_Update2(CPpmd8 *p);\n\n\n\n\n\n\n#define Ppmd8_GetBinSumm(p) \\\n    &p->BinSumm[p->NS2Indx[(size_t)Ppmd8Context_OneState(p->MinContext)->Freq - 1]] \\\n    [ p->PrevSuccess + ((p->RunLength >> 26) & 0x20) \\\n    + p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \\\n    + p->MinContext->Flags ]\n\n\nCPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);\n\n\n/* 20.01: the original PPMdI encoder and decoder probably could work incorrectly in some rare cases,\n   where the original PPMdI code can give \"Divide by Zero\" operation.\n   We use the following fix to allow correct working of encoder and decoder in any cases.\n   We correct (Escape_Freq) and (_sum_), if (_sum_) is larger than p->Range) */\n#define PPMD8_CORRECT_SUM_RANGE(p, _sum_) if (_sum_ > p->Range /* /1 */) _sum_ = p->Range;\n\n\n/* ---------- Decode ---------- */\n\n#define PPMD8_SYM_END    (-1)\n#define PPMD8_SYM_ERROR  (-2)\n\n/*\nYou must set (CPpmd8::Stream.In) before Ppmd8_RangeDec_Init()\n\nPpmd8_DecodeSymbol()\nout:\n  >= 0 : decoded byte\n    -1 : PPMD8_SYM_END   : End of payload marker\n    -2 : PPMD8_SYM_ERROR : Data error\n*/\n\n\nBoolInt Ppmd8_Init_RangeDec(CPpmd8 *p);\n#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)\nint Ppmd8_DecodeSymbol(CPpmd8 *p);\n\n\n\n\n\n\n\n\n/* ---------- Encode ---------- */\n\n#define Ppmd8_Init_RangeEnc(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }\nvoid Ppmd8_Flush_RangeEnc(CPpmd8 *p);\nvoid Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol);\n\n\nEXTERN_C_END\n \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd8Dec.c",
    "content": "﻿/* Ppmd8Dec.c -- Ppmd8 (PPMdI) Decoder\n2023-09-07 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.I (2002): Dmitry Shkarin : Public domain\n  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Ppmd8.h\"\n\n#define kTop ((UInt32)1 << 24)\n#define kBot ((UInt32)1 << 15)\n\n#define READ_BYTE(p) IByteIn_Read((p)->Stream.In)\n\nBoolInt Ppmd8_Init_RangeDec(CPpmd8 *p)\n{\n  unsigned i;\n  p->Code = 0;\n  p->Range = 0xFFFFFFFF;\n  p->Low = 0;\n  \n  for (i = 0; i < 4; i++)\n    p->Code = (p->Code << 8) | READ_BYTE(p);\n  return (p->Code < 0xFFFFFFFF);\n}\n\n#define RC_NORM(p) \\\n  while ((p->Low ^ (p->Low + p->Range)) < kTop \\\n    || (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) { \\\n      p->Code = (p->Code << 8) | READ_BYTE(p); \\\n      p->Range <<= 8; p->Low <<= 8; }\n\n// we must use only one type of Normalization from two: LOCAL or REMOTE\n#define RC_NORM_LOCAL(p)    // RC_NORM(p)\n#define RC_NORM_REMOTE(p)   RC_NORM(p)\n\n#define R p\n\nZ7_FORCE_INLINE\n// Z7_NO_INLINE\nstatic void Ppmd8_RD_Decode(CPpmd8 *p, UInt32 start, UInt32 size)\n{\n  start *= R->Range;\n  R->Low += start;\n  R->Code -= start;\n  R->Range *= size;\n  RC_NORM_LOCAL(R)\n}\n\n#define RC_Decode(start, size)  Ppmd8_RD_Decode(p, start, size);\n#define RC_DecodeFinal(start, size)  RC_Decode(start, size)  RC_NORM_REMOTE(R)\n#define RC_GetThreshold(total)  (R->Code / (R->Range /= (total)))\n\n\n#define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))\n// typedef CPpmd8_Context * CTX_PTR;\n#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)\nvoid Ppmd8_UpdateModel(CPpmd8 *p);\n\n#define MASK(sym)  ((Byte *)charMask)[sym]\n\n\nint Ppmd8_DecodeSymbol(CPpmd8 *p)\n{\n  size_t charMask[256 / sizeof(size_t)];\n\n  if (p->MinContext->NumStats != 0)\n  {\n    CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);\n    unsigned i;\n    UInt32 count, hiCnt;\n    UInt32 summFreq = p->MinContext->Union2.SummFreq;\n\n    PPMD8_CORRECT_SUM_RANGE(p, summFreq)\n\n\n    count = RC_GetThreshold(summFreq);\n    hiCnt = count;\n    \n    if ((Int32)(count -= s->Freq) < 0)\n    {\n      Byte sym;\n      RC_DecodeFinal(0, s->Freq)\n      p->FoundState = s;\n      sym = s->Symbol;\n      Ppmd8_Update1_0(p);\n      return sym;\n    }\n    \n    p->PrevSuccess = 0;\n    i = p->MinContext->NumStats;\n    \n    do\n    {\n      if ((Int32)(count -= (++s)->Freq) < 0)\n      {\n        Byte sym;\n        RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)\n        p->FoundState = s;\n        sym = s->Symbol;\n        Ppmd8_Update1(p);\n        return sym;\n      }\n    }\n    while (--i);\n    \n    if (hiCnt >= summFreq)\n      return PPMD8_SYM_ERROR;\n\n    hiCnt -= count;\n    RC_Decode(hiCnt, summFreq - hiCnt)\n    \n    \n    PPMD_SetAllBitsIn256Bytes(charMask)\n    // i = p->MinContext->NumStats - 1;\n    // do { MASK((--s)->Symbol) = 0; } while (--i);\n    {\n      CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext);\n      MASK(s->Symbol) = 0;\n      do\n      {\n        const unsigned sym0 = s2[0].Symbol;\n        const unsigned sym1 = s2[1].Symbol;\n        s2 += 2;\n        MASK(sym0) = 0;\n        MASK(sym1) = 0;\n      }\n      while (s2 < s);\n    }\n  }\n  else\n  {\n    CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);\n    UInt16 *prob = Ppmd8_GetBinSumm(p);\n    UInt32 pr = *prob;\n    UInt32 size0 = (R->Range >> 14) * pr;\n    pr = PPMD_UPDATE_PROB_1(pr);\n    \n    if (R->Code < size0)\n    {\n      Byte sym;\n      *prob = (UInt16)(pr + (1 << PPMD_INT_BITS));\n      \n      // RangeDec_DecodeBit0(size0);\n      R->Range = size0;\n      RC_NORM(R)\n      \n      \n        \n      // sym = (p->FoundState = Ppmd8Context_OneState(p->MinContext))->Symbol;\n      // Ppmd8_UpdateBin(p);\n      {\n        unsigned freq = s->Freq;\n        CPpmd8_Context *c = CTX(SUCCESSOR(s));\n        sym = s->Symbol;\n        p->FoundState = s;\n        p->PrevSuccess = 1;\n        p->RunLength++;\n        s->Freq = (Byte)(freq + (freq < 196));\n        // NextContext(p);\n        if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart)\n          p->MaxContext = p->MinContext = c;\n        else\n          Ppmd8_UpdateModel(p);\n      }\n      return sym;\n    }\n    \n    *prob = (UInt16)pr;\n    p->InitEsc = p->ExpEscape[pr >> 10];\n    \n    // RangeDec_DecodeBit1(rc2, size0);\n    R->Low += size0;\n    R->Code -= size0;\n    R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - size0;\n    RC_NORM_LOCAL(R)\n    \n    PPMD_SetAllBitsIn256Bytes(charMask)\n    MASK(Ppmd8Context_OneState(p->MinContext)->Symbol) = 0;\n    p->PrevSuccess = 0;\n  }\n  \n  for (;;)\n  {\n    CPpmd_State *s, *s2;\n    UInt32 freqSum, count, hiCnt;\n    UInt32 freqSum2;\n    CPpmd_See *see;\n    CPpmd8_Context *mc;\n    unsigned numMasked;\n    RC_NORM_REMOTE(R)\n    mc = p->MinContext;\n    numMasked = mc->NumStats;\n    \n    do\n    {\n      p->OrderFall++;\n      if (!mc->Suffix)\n        return PPMD8_SYM_END;\n      mc = Ppmd8_GetContext(p, mc->Suffix);\n    }\n    while (mc->NumStats == numMasked);\n    \n    s = Ppmd8_GetStats(p, mc);\n\n    {\n      unsigned num = (unsigned)mc->NumStats + 1;\n      unsigned num2 = num / 2;\n\n      num &= 1;\n      hiCnt = (s->Freq & (UInt32)(MASK(s->Symbol))) & (0 - (UInt32)num);\n      s += num;\n      p->MinContext = mc;\n\n      do\n      {\n        const unsigned sym0 = s[0].Symbol;\n        const unsigned sym1 = s[1].Symbol;\n        s += 2;\n        hiCnt += (s[-2].Freq & (UInt32)(MASK(sym0)));\n        hiCnt += (s[-1].Freq & (UInt32)(MASK(sym1)));\n      }\n      while (--num2);\n    }\n    \n    see = Ppmd8_MakeEscFreq(p, numMasked, &freqSum);\n    freqSum += hiCnt;\n    freqSum2 = freqSum;\n    PPMD8_CORRECT_SUM_RANGE(R, freqSum2)\n\n\n    count = RC_GetThreshold(freqSum2);\n    \n    if (count < hiCnt)\n    {\n      Byte sym;\n      // Ppmd_See_UPDATE(see) // new (see->Summ) value can overflow over 16-bits in some rare cases\n      s = Ppmd8_GetStats(p, p->MinContext);\n      hiCnt = count;\n\n      \n      {\n        for (;;)\n        {\n          count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;\n          // count -= s->Freq & (UInt32)(MASK((s)->Symbol)); s++; if ((Int32)count < 0) break;\n        }\n      }\n      s--;\n      RC_DecodeFinal((hiCnt - count) - s->Freq, s->Freq)\n\n      // new (see->Summ) value can overflow over 16-bits in some rare cases\n      Ppmd_See_UPDATE(see)\n      p->FoundState = s;\n      sym = s->Symbol;\n      Ppmd8_Update2(p);\n      return sym;\n    }\n\n    if (count >= freqSum2)\n      return PPMD8_SYM_ERROR;\n    \n    RC_Decode(hiCnt, freqSum2 - hiCnt)\n    \n    // We increase (see->Summ) for sum of Freqs of all non_Masked symbols.\n    // new (see->Summ) value can overflow over 16-bits in some rare cases\n    see->Summ = (UInt16)(see->Summ + freqSum);\n    \n    s = Ppmd8_GetStats(p, p->MinContext);\n    s2 = s + p->MinContext->NumStats + 1;\n    do\n    {\n      MASK(s->Symbol) = 0;\n      s++;\n    }\n    while (s != s2);\n  }\n}\n\n#undef kTop\n#undef kBot\n#undef READ_BYTE\n#undef RC_NORM_BASE\n#undef RC_NORM_1\n#undef RC_NORM\n#undef RC_NORM_LOCAL\n#undef RC_NORM_REMOTE\n#undef R\n#undef RC_Decode\n#undef RC_DecodeFinal\n#undef RC_GetThreshold\n#undef CTX\n#undef SUCCESSOR\n#undef MASK\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Ppmd8Enc.c",
    "content": "﻿/* Ppmd8Enc.c -- Ppmd8 (PPMdI) Encoder\n2023-09-07 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.I (2002): Dmitry Shkarin : Public domain\n  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Ppmd8.h\"\n\n#define kTop ((UInt32)1 << 24)\n#define kBot ((UInt32)1 << 15)\n\n#define WRITE_BYTE(p) IByteOut_Write(p->Stream.Out, (Byte)(p->Low >> 24))\n\nvoid Ppmd8_Flush_RangeEnc(CPpmd8 *p)\n{\n  unsigned i;\n  for (i = 0; i < 4; i++, p->Low <<= 8 )\n    WRITE_BYTE(p);\n}\n\n\n\n\n\n\n#define RC_NORM(p) \\\n  while ((p->Low ^ (p->Low + p->Range)) < kTop \\\n    || (p->Range < kBot && ((p->Range = (0 - p->Low) & (kBot - 1)), 1))) \\\n    { WRITE_BYTE(p); p->Range <<= 8; p->Low <<= 8; }\n\n\n\n\n\n\n\n\n\n\n\n\n\n// we must use only one type of Normalization from two: LOCAL or REMOTE\n#define RC_NORM_LOCAL(p)    // RC_NORM(p)\n#define RC_NORM_REMOTE(p)   RC_NORM(p)\n\n// #define RC_PRE(total) p->Range /= total;\n// #define RC_PRE(total)\n\n#define R p\n\n\n\n\nZ7_FORCE_INLINE\n// Z7_NO_INLINE\nstatic void Ppmd8_RangeEnc_Encode(CPpmd8 *p, UInt32 start, UInt32 size, UInt32 total)\n{\n  R->Low += start * (R->Range /= total);\n  R->Range *= size;\n  RC_NORM_LOCAL(R)\n}\n\n\n\n\n\n\n\n\n\n\n#define RC_Encode(start, size, total)  Ppmd8_RangeEnc_Encode(p, start, size, total);\n#define RC_EncodeFinal(start, size, total)  RC_Encode(start, size, total)  RC_NORM_REMOTE(p)\n\n#define CTX(ref) ((CPpmd8_Context *)Ppmd8_GetContext(p, ref))\n\n// typedef CPpmd8_Context * CTX_PTR;\n#define SUCCESSOR(p) Ppmd_GET_SUCCESSOR(p)\n\nvoid Ppmd8_UpdateModel(CPpmd8 *p);\n\n#define MASK(sym)  ((Byte *)charMask)[sym]\n\n// Z7_FORCE_INLINE\n// static\nvoid Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol)\n{\n  size_t charMask[256 / sizeof(size_t)];\n  \n  if (p->MinContext->NumStats != 0)\n  {\n    CPpmd_State *s = Ppmd8_GetStats(p, p->MinContext);\n    UInt32 sum;\n    unsigned i;\n    UInt32 summFreq = p->MinContext->Union2.SummFreq;\n    \n    PPMD8_CORRECT_SUM_RANGE(p, summFreq)\n\n    // RC_PRE(summFreq);\n\n    if (s->Symbol == symbol)\n    {\n\n      RC_EncodeFinal(0, s->Freq, summFreq)\n      p->FoundState = s;\n      Ppmd8_Update1_0(p);\n      return;\n    }\n    p->PrevSuccess = 0;\n    sum = s->Freq;\n    i = p->MinContext->NumStats;\n    do\n    {\n      if ((++s)->Symbol == symbol)\n      {\n\n        RC_EncodeFinal(sum, s->Freq, summFreq)\n        p->FoundState = s;\n        Ppmd8_Update1(p);\n        return;\n      }\n      sum += s->Freq;\n    }\n    while (--i);\n    \n    \n    RC_Encode(sum, summFreq - sum, summFreq)\n    \n    \n    PPMD_SetAllBitsIn256Bytes(charMask)\n    // MASK(s->Symbol) = 0;\n    // i = p->MinContext->NumStats;\n    // do { MASK((--s)->Symbol) = 0; } while (--i);\n    {\n      CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext);\n      MASK(s->Symbol) = 0;\n      do\n      {\n        const unsigned sym0 = s2[0].Symbol;\n        const unsigned sym1 = s2[1].Symbol;\n        s2 += 2;\n        MASK(sym0) = 0;\n        MASK(sym1) = 0;\n      }\n      while (s2 < s);\n    }\n  }\n  else\n  {\n    UInt16 *prob = Ppmd8_GetBinSumm(p);\n    CPpmd_State *s = Ppmd8Context_OneState(p->MinContext);\n    UInt32 pr = *prob;\n    const UInt32 bound = (R->Range >> 14) * pr;\n    pr = PPMD_UPDATE_PROB_1(pr);\n    if (s->Symbol == symbol)\n    {\n      *prob = (UInt16)(pr + (1 << PPMD_INT_BITS));\n      // RangeEnc_EncodeBit_0(p, bound);\n      R->Range = bound;\n      RC_NORM(R)\n\n      // p->FoundState = s;\n      // Ppmd8_UpdateBin(p);\n      {\n        const unsigned freq = s->Freq;\n        CPpmd8_Context *c = CTX(SUCCESSOR(s));\n        p->FoundState = s;\n        p->PrevSuccess = 1;\n        p->RunLength++;\n        s->Freq = (Byte)(freq + (freq < 196)); // Ppmd8 (196)\n        // NextContext(p);\n        if (p->OrderFall == 0 && (const Byte *)c >= p->UnitsStart)\n          p->MaxContext = p->MinContext = c;\n        else\n          Ppmd8_UpdateModel(p);\n      }\n      return;\n    }\n\n    *prob = (UInt16)pr;\n    p->InitEsc = p->ExpEscape[pr >> 10];\n    // RangeEnc_EncodeBit_1(p, bound);\n    R->Low += bound;\n    R->Range = (R->Range & ~((UInt32)PPMD_BIN_SCALE - 1)) - bound;\n    RC_NORM_LOCAL(R)\n\n    PPMD_SetAllBitsIn256Bytes(charMask)\n    MASK(s->Symbol) = 0;\n    p->PrevSuccess = 0;\n  }\n\n  for (;;)\n  {\n    CPpmd_See *see;\n    CPpmd_State *s;\n    UInt32 sum, escFreq;\n    CPpmd8_Context *mc;\n    unsigned i, numMasked;\n\n    RC_NORM_REMOTE(p)\n\n    mc = p->MinContext;\n    numMasked = mc->NumStats;\n\n    do\n    {\n      p->OrderFall++;\n      if (!mc->Suffix)\n        return; /* EndMarker (symbol = -1) */\n      mc = Ppmd8_GetContext(p, mc->Suffix);\n\n    }\n    while (mc->NumStats == numMasked);\n    \n    p->MinContext = mc;\n\n    see = Ppmd8_MakeEscFreq(p, numMasked, &escFreq);\n    \n    \n    \n    \n    \n    \n    \n    \n    \n\n    \n    \n    \n    \n    \n    \n\n    \n    \n    \n    \n    \n    \n    \n    s = Ppmd8_GetStats(p, p->MinContext);\n    sum = 0;\n    i = (unsigned)p->MinContext->NumStats + 1;\n\n    do\n    {\n      const unsigned cur = s->Symbol;\n      if ((int)cur == symbol)\n      {\n        const UInt32 low = sum;\n        const UInt32 freq = s->Freq;\n        unsigned num2;\n\n        Ppmd_See_UPDATE(see)\n        p->FoundState = s;\n        sum += escFreq;\n\n        num2 = i / 2;\n        i &= 1;\n        sum += freq & (0 - (UInt32)i);\n        if (num2 != 0)\n        {\n          s += i;\n          do\n          {\n            const unsigned sym0 = s[0].Symbol;\n            const unsigned sym1 = s[1].Symbol;\n            s += 2;\n            sum += (s[-2].Freq & (unsigned)(MASK(sym0)));\n            sum += (s[-1].Freq & (unsigned)(MASK(sym1)));\n          }\n          while (--num2);\n        }\n\n        PPMD8_CORRECT_SUM_RANGE(p, sum)\n\n        RC_EncodeFinal(low, freq, sum)\n        Ppmd8_Update2(p);\n        return;\n      }\n      sum += (s->Freq & (unsigned)(MASK(cur)));\n      s++;\n    }\n    while (--i);\n    \n    {\n      UInt32 total = sum + escFreq;\n      see->Summ = (UInt16)(see->Summ + total);\n      PPMD8_CORRECT_SUM_RANGE(p, total)\n\n      RC_Encode(sum, total - sum, total)\n    }\n\n    {\n      const CPpmd_State *s2 = Ppmd8_GetStats(p, p->MinContext);\n      s--;\n      MASK(s->Symbol) = 0;\n      do\n      {\n        const unsigned sym0 = s2[0].Symbol;\n        const unsigned sym1 = s2[1].Symbol;\n        s2 += 2;\n        MASK(sym0) = 0;\n        MASK(sym1) = 0;\n      }\n      while (s2 < s);\n    }\n  }\n}\n\n\n\n\n\n\n\n\n\n#undef kTop\n#undef kBot\n#undef WRITE_BYTE\n#undef RC_NORM_BASE\n#undef RC_NORM_1\n#undef RC_NORM\n#undef RC_NORM_LOCAL\n#undef RC_NORM_REMOTE\n#undef R\n#undef RC_Encode\n#undef RC_EncodeFinal\n\n#undef CTX\n#undef SUCCESSOR\n#undef MASK\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Precomp.h",
    "content": "﻿/* Precomp.h -- precompilation file\n2024-01-25 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_PRECOMP_H\n#define ZIP7_INC_PRECOMP_H\n\n/*\n  this file must be included before another *.h files and before <windows.h>.\n  this file is included from the following files:\n    C\\*.c\n    C\\Util\\*\\Precomp.h   <-  C\\Util\\*\\*.c\n    CPP\\Common\\Common.h  <-  *\\StdAfx.h    <-  *\\*.cpp\n\n  this file can set the following macros:\n    Z7_LARGE_PAGES 1\n    Z7_LONG_PATH 1\n    Z7_WIN32_WINNT_MIN  0x0500 (or higher) : we require at least win2000+ for 7-Zip\n    _WIN32_WINNT        0x0500 (or higher)\n    WINVER  _WIN32_WINNT\n    UNICODE 1\n    _UNICODE 1\n*/\n\n#include \"Compiler.h\"\n\n#ifdef _MSC_VER\n// #pragma warning(disable : 4206) // nonstandard extension used : translation unit is empty\n#if _MSC_VER >= 1912\n// #pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern \"C\"' function under - EHc.Undefined behavior may occur if this function throws an exception.\n#endif\n#endif\n\n/*\n// for debug:\n#define UNICODE 1\n#define _UNICODE 1\n#define  _WIN32_WINNT  0x0500  // win2000\n#ifndef WINVER\n  #define WINVER  _WIN32_WINNT\n#endif\n*/\n\n#ifdef _WIN32\n/*\n  this \"Precomp.h\" file must be included before <windows.h>,\n  if we want to define _WIN32_WINNT before <windows.h>.\n*/\n\n#ifndef Z7_LARGE_PAGES\n#ifndef Z7_NO_LARGE_PAGES\n#define Z7_LARGE_PAGES 1\n#endif\n#endif\n\n#ifndef Z7_LONG_PATH\n#ifndef Z7_NO_LONG_PATH\n#define Z7_LONG_PATH 1\n#endif\n#endif\n\n#ifndef Z7_DEVICE_FILE\n#ifndef Z7_NO_DEVICE_FILE\n// #define Z7_DEVICE_FILE 1\n#endif\n#endif\n\n// we don't change macros if included after <windows.h>\n#ifndef _WINDOWS_\n\n#ifndef Z7_WIN32_WINNT_MIN\n  #if defined(_M_ARM64) || defined(__aarch64__)\n    // #define Z7_WIN32_WINNT_MIN  0x0a00  // win10\n    #define Z7_WIN32_WINNT_MIN  0x0600  // vista\n  #elif defined(_M_ARM) && defined(_M_ARMT) && defined(_M_ARM_NT)\n    // #define Z7_WIN32_WINNT_MIN  0x0602  // win8\n    #define Z7_WIN32_WINNT_MIN  0x0600  // vista\n  #elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IA64)\n    #define Z7_WIN32_WINNT_MIN  0x0503  // win2003\n  // #elif defined(_M_IX86) || defined(__i386__)\n  //   #define Z7_WIN32_WINNT_MIN  0x0500  // win2000\n  #else // x86 and another(old) systems\n    #define Z7_WIN32_WINNT_MIN  0x0500  // win2000\n    // #define Z7_WIN32_WINNT_MIN  0x0502  // win2003 // for debug\n  #endif\n#endif // Z7_WIN32_WINNT_MIN\n\n\n#ifndef Z7_DO_NOT_DEFINE_WIN32_WINNT\n#ifdef _WIN32_WINNT\n  // #error Stop_Compiling_Bad_WIN32_WINNT\n#else\n  #ifndef Z7_NO_DEFINE_WIN32_WINNT\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n    #define _WIN32_WINNT  Z7_WIN32_WINNT_MIN\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n  #endif\n#endif // _WIN32_WINNT\n\n#ifndef WINVER\n  #define WINVER  _WIN32_WINNT\n#endif\n#endif // Z7_DO_NOT_DEFINE_WIN32_WINNT\n\n\n#ifndef _MBCS\n#ifndef Z7_NO_UNICODE\n// UNICODE and _UNICODE are used by <windows.h> and by 7-zip code.\n\n#ifndef UNICODE\n#define UNICODE 1\n#endif\n\n#ifndef _UNICODE\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n#define _UNICODE 1\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif\n\n#endif // Z7_NO_UNICODE\n#endif // _MBCS\n#endif // _WINDOWS_\n\n// #include \"7zWindows.h\"\n\n#endif // _WIN32\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/RotateDefs.h",
    "content": "﻿/* RotateDefs.h -- Rotate functions\n2023-06-18 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_ROTATE_DEFS_H\n#define ZIP7_INC_ROTATE_DEFS_H\n\n#ifdef _MSC_VER\n\n#include <stdlib.h>\n\n/* don't use _rotl with old MINGW. It can insert slow call to function. */\n \n/* #if (_MSC_VER >= 1200) */\n#pragma intrinsic(_rotl)\n#pragma intrinsic(_rotr)\n/* #endif */\n\n#define rotlFixed(x, n) _rotl((x), (n))\n#define rotrFixed(x, n) _rotr((x), (n))\n\n#if (_MSC_VER >= 1300)\n#define Z7_ROTL64(x, n) _rotl64((x), (n))\n#define Z7_ROTR64(x, n) _rotr64((x), (n))\n#else\n#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))\n#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))\n#endif\n\n#else\n\n/* new compilers can translate these macros to fast commands. */\n\n#if defined(__clang__) && (__clang_major__ >= 4) \\\n  || defined(__GNUC__) && (__GNUC__ >= 5)\n/* GCC 4.9.0 and clang 3.5 can recognize more correct version: */\n#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (-(n) & 31)))\n#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (-(n) & 31)))\n#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (-(n) & 63)))\n#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (-(n) & 63)))\n#else\n/* for old GCC / clang: */\n#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))\n#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))\n#define Z7_ROTL64(x, n) (((x) << (n)) | ((x) >> (64 - (n))))\n#define Z7_ROTR64(x, n) (((x) >> (n)) | ((x) << (64 - (n))))\n#endif\n\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Sha1.h",
    "content": "﻿// **************** NanaZip Modification Start ****************\n// Redirect to K7Base Wrapper\n#include \"../../Wrappers/Sha1Wrapper.h\"\n// **************** NanaZip Modification End ****************\n/* Sha1.h -- SHA-1 Hash\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_SHA1_H\n#define ZIP7_INC_SHA1_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define SHA1_NUM_BLOCK_WORDS  16\n#define SHA1_NUM_DIGEST_WORDS  5\n\n#define SHA1_BLOCK_SIZE   (SHA1_NUM_BLOCK_WORDS * 4)\n#define SHA1_DIGEST_SIZE  (SHA1_NUM_DIGEST_WORDS * 4)\n\n\n\n\ntypedef void (Z7_FASTCALL *SHA1_FUNC_UPDATE_BLOCKS)(UInt32 state[5], const Byte *data, size_t numBlocks);\n\n/*\n  if (the system supports different SHA1 code implementations)\n  {\n    (CSha1::func_UpdateBlocks) will be used\n    (CSha1::func_UpdateBlocks) can be set by\n       Sha1_Init()        - to default (fastest)\n       Sha1_SetFunction() - to any algo\n  }\n  else\n  {\n    (CSha1::func_UpdateBlocks) is ignored.\n  }\n*/\n\ntypedef struct\n{\n  union\n  {\n    struct\n    {\n      SHA1_FUNC_UPDATE_BLOCKS func_UpdateBlocks;\n      UInt64 count;\n    } vars;\n    UInt64 _pad_64bit[4];\n    void *_pad_align_ptr[2];\n  } v;\n  UInt32 state[SHA1_NUM_DIGEST_WORDS];\n  UInt32 _pad_3[3];\n  Byte buffer[SHA1_BLOCK_SIZE];\n} CSha1;\n\n\n#define SHA1_ALGO_DEFAULT 0\n#define SHA1_ALGO_SW      1\n#define SHA1_ALGO_HW      2\n\n/*\nSha1_SetFunction()\nreturn:\n  0 - (algo) value is not supported, and func_UpdateBlocks was not changed\n  1 - func_UpdateBlocks was set according (algo) value.\n*/\n\nBoolInt Sha1_SetFunction(CSha1 *p, unsigned algo);\n\nvoid Sha1_InitState(CSha1 *p);\nvoid Sha1_Init(CSha1 *p);\nvoid Sha1_Update(CSha1 *p, const Byte *data, size_t size);\nvoid Sha1_Final(CSha1 *p, Byte *digest);\n\nvoid Sha1_PrepareBlock(const CSha1 *p, Byte *block, unsigned size);\nvoid Sha1_GetBlockDigest(const CSha1 *p, const Byte *data, Byte *destDigest);\n\n// void Z7_FASTCALL Sha1_UpdateBlocks(UInt32 state[5], const Byte *data, size_t numBlocks);\n\n/*\ncall Sha1Prepare() once at program start.\nIt prepares all supported implementations, and detects the fastest implementation.\n*/\n\nvoid Sha1Prepare(void);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Sha256.h",
    "content": "﻿// **************** NanaZip Modification Start ****************\n// Redirect to K7Base Wrapper\n#include \"../../Wrappers/Sha256Wrapper.h\"\n// **************** NanaZip Modification End ****************\n/* Sha256.h -- SHA-256 Hash\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_SHA256_H\n#define ZIP7_INC_SHA256_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define SHA256_NUM_BLOCK_WORDS  16\n#define SHA256_NUM_DIGEST_WORDS  8\n\n#define SHA256_BLOCK_SIZE   (SHA256_NUM_BLOCK_WORDS * 4)\n#define SHA256_DIGEST_SIZE  (SHA256_NUM_DIGEST_WORDS * 4)\n\n\n\n\ntypedef void (Z7_FASTCALL *SHA256_FUNC_UPDATE_BLOCKS)(UInt32 state[8], const Byte *data, size_t numBlocks);\n\n/*\n  if (the system supports different SHA256 code implementations)\n  {\n    (CSha256::func_UpdateBlocks) will be used\n    (CSha256::func_UpdateBlocks) can be set by\n       Sha256_Init()        - to default (fastest)\n       Sha256_SetFunction() - to any algo\n  }\n  else\n  {\n    (CSha256::func_UpdateBlocks) is ignored.\n  }\n*/\n\ntypedef struct\n{\n  union\n  {\n    struct\n    {\n      SHA256_FUNC_UPDATE_BLOCKS func_UpdateBlocks;\n      UInt64 count;\n    } vars;\n    UInt64 _pad_64bit[4];\n    void *_pad_align_ptr[2];\n  } v;\n  UInt32 state[SHA256_NUM_DIGEST_WORDS];\n\n  Byte buffer[SHA256_BLOCK_SIZE];\n} CSha256;\n\n\n#define SHA256_ALGO_DEFAULT 0\n#define SHA256_ALGO_SW      1\n#define SHA256_ALGO_HW      2\n\n/*\nSha256_SetFunction()\nreturn:\n  0 - (algo) value is not supported, and func_UpdateBlocks was not changed\n  1 - func_UpdateBlocks was set according (algo) value.\n*/\n\nBoolInt Sha256_SetFunction(CSha256 *p, unsigned algo);\n\nvoid Sha256_InitState(CSha256 *p);\nvoid Sha256_Init(CSha256 *p);\nvoid Sha256_Update(CSha256 *p, const Byte *data, size_t size);\nvoid Sha256_Final(CSha256 *p, Byte *digest);\n\n\n\n\n// void Z7_FASTCALL Sha256_UpdateBlocks(UInt32 state[8], const Byte *data, size_t numBlocks);\n\n/*\ncall Sha256Prepare() once at program start.\nIt prepares all supported implementations, and detects the fastest implementation.\n*/\n\nvoid Sha256Prepare(void);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Sha512.h",
    "content": "﻿// **************** NanaZip Modification Start ****************\n// Redirect to K7Base Wrapper\n#include \"../../Wrappers/Sha512Wrapper.h\"\n// **************** NanaZip Modification End ****************\n/* Sha512.h -- SHA-512 Hash\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_SHA512_H\n#define ZIP7_INC_SHA512_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#define SHA512_NUM_BLOCK_WORDS  16\n#define SHA512_NUM_DIGEST_WORDS  8\n\n#define SHA512_BLOCK_SIZE   (SHA512_NUM_BLOCK_WORDS * 8)\n#define SHA512_DIGEST_SIZE  (SHA512_NUM_DIGEST_WORDS * 8)\n#define SHA512_224_DIGEST_SIZE  (224 / 8)\n#define SHA512_256_DIGEST_SIZE  (256 / 8)\n#define SHA512_384_DIGEST_SIZE  (384 / 8)\n\ntypedef void (Z7_FASTCALL *SHA512_FUNC_UPDATE_BLOCKS)(UInt64 state[8], const Byte *data, size_t numBlocks);\n\n/*\n  if (the system supports different SHA512 code implementations)\n  {\n    (CSha512::func_UpdateBlocks) will be used\n    (CSha512::func_UpdateBlocks) can be set by\n       Sha512_Init()        - to default (fastest)\n       Sha512_SetFunction() - to any algo\n  }\n  else\n  {\n    (CSha512::func_UpdateBlocks) is ignored.\n  }\n*/\n\ntypedef struct\n{\n  union\n  {\n    struct\n    {\n      SHA512_FUNC_UPDATE_BLOCKS func_UpdateBlocks;\n      UInt64 count;\n    } vars;\n    UInt64 _pad_64bit[8];\n    void *_pad_align_ptr[2];\n  } v;\n  UInt64 state[SHA512_NUM_DIGEST_WORDS];\n\n  Byte buffer[SHA512_BLOCK_SIZE];\n} CSha512;\n\n\n#define SHA512_ALGO_DEFAULT 0\n#define SHA512_ALGO_SW      1\n#define SHA512_ALGO_HW      2\n\n/*\nSha512_SetFunction()\nreturn:\n  0 - (algo) value is not supported, and func_UpdateBlocks was not changed\n  1 - func_UpdateBlocks was set according (algo) value.\n*/\n\nBoolInt Sha512_SetFunction(CSha512 *p, unsigned algo);\n// we support only these (digestSize) values: 224/8, 256/8, 384/8, 512/8\nvoid Sha512_InitState(CSha512 *p, unsigned digestSize);\nvoid Sha512_Init(CSha512 *p, unsigned digestSize);\nvoid Sha512_Update(CSha512 *p, const Byte *data, size_t size);\nvoid Sha512_Final(CSha512 *p, Byte *digest, unsigned digestSize);\n\n\n\n\n// void Z7_FASTCALL Sha512_UpdateBlocks(UInt64 state[8], const Byte *data, size_t numBlocks);\n\n/*\ncall Sha512Prepare() once at program start.\nIt prepares all supported implementations, and detects the fastest implementation.\n*/\n\nvoid Sha512Prepare(void);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Sort.c",
    "content": "﻿/* Sort.c -- Sort functions\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Sort.h\"\n#include \"CpuArch.h\"\n\n#if (  (defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \\\n    || (defined(__clang__) && Z7_has_builtin(__builtin_prefetch)) \\\n    )\n// the code with prefetch is slow for small arrays on x86.\n// So we disable prefetch for x86.\n#ifndef MY_CPU_X86\n  // #pragma message(\"Z7_PREFETCH : __builtin_prefetch\")\n  #define Z7_PREFETCH(a)  __builtin_prefetch((a))\n#endif\n\n#elif defined(_WIN32) // || defined(_MSC_VER) && (_MSC_VER >= 1200)\n\n#include \"7zWindows.h\"\n\n// NOTE: CLANG/GCC/MSVC can define different values for _MM_HINT_T0 / PF_TEMPORAL_LEVEL_1.\n// For example, clang-cl can generate \"prefetcht2\" instruction for\n// PreFetchCacheLine(PF_TEMPORAL_LEVEL_1) call.\n// But we want to generate \"prefetcht0\" instruction.\n// So for CLANG/GCC we must use __builtin_prefetch() in code branch above\n// instead of PreFetchCacheLine() / _mm_prefetch().\n\n// New msvc-x86 compiler generates \"prefetcht0\" instruction for PreFetchCacheLine() call.\n// But old x86 cpus don't support \"prefetcht0\".\n// So we will use PreFetchCacheLine(), only if we are sure that\n// generated instruction is supported by all cpus of that isa.\n#if defined(MY_CPU_AMD64) \\\n    || defined(MY_CPU_ARM64) \\\n    || defined(MY_CPU_IA64)\n// we need to use additional braces for (a) in PreFetchCacheLine call, because\n// PreFetchCacheLine macro doesn't use braces:\n//   #define PreFetchCacheLine(l, a)  _mm_prefetch((CHAR CONST *) a, l)\n  // #pragma message(\"Z7_PREFETCH : PreFetchCacheLine\")\n  #define Z7_PREFETCH(a)  PreFetchCacheLine(PF_TEMPORAL_LEVEL_1, (a))\n#endif\n\n#endif // _WIN32\n\n\n#define PREFETCH_NO(p,k,s,size)\n\n#ifndef Z7_PREFETCH\n  #define SORT_PREFETCH(p,k,s,size)\n#else\n\n// #define PREFETCH_LEVEL 2  // use it if cache line is 32-bytes\n#define PREFETCH_LEVEL 3  // it is fast for most cases (64-bytes cache line prefetch)\n// #define PREFETCH_LEVEL 4  // it can be faster for big array (128-bytes prefetch)\n\n#if PREFETCH_LEVEL == 0\n\n  #define SORT_PREFETCH(p,k,s,size)\n\n#else // PREFETCH_LEVEL != 0\n\n/*\nif  defined(USE_PREFETCH_FOR_ALIGNED_ARRAY)\n    we prefetch one value per cache line.\n    Use it if array is aligned for cache line size (64 bytes)\n    or if array is small (less than L1 cache size).\n\nif !defined(USE_PREFETCH_FOR_ALIGNED_ARRAY)\n    we perfetch all cache lines that can be required.\n    it can be faster for big unaligned arrays.\n*/\n  #define USE_PREFETCH_FOR_ALIGNED_ARRAY\n\n// s == k * 2\n#if 0 && PREFETCH_LEVEL <= 3 && defined(MY_CPU_X86_OR_AMD64)\n  // x86 supports (lea r1*8+offset)\n  #define PREFETCH_OFFSET(k,s)  ((s) << PREFETCH_LEVEL)\n#else\n  #define PREFETCH_OFFSET(k,s)  ((k) << (PREFETCH_LEVEL + 1))\n#endif\n\n#if 1 && PREFETCH_LEVEL <= 3 && defined(USE_PREFETCH_FOR_ALIGNED_ARRAY)\n  #define PREFETCH_ADD_OFFSET   0\n#else\n  // last offset that can be reqiured in PREFETCH_LEVEL step:\n  #define PREFETCH_RANGE        ((2 << PREFETCH_LEVEL) - 1)\n  #define PREFETCH_ADD_OFFSET   PREFETCH_RANGE / 2\n#endif\n\n#if PREFETCH_LEVEL <= 3\n\n#ifdef USE_PREFETCH_FOR_ALIGNED_ARRAY\n  #define SORT_PREFETCH(p,k,s,size) \\\n  { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_ADD_OFFSET; \\\n    if (s2 <= size) { \\\n      Z7_PREFETCH((p + s2)); \\\n  }}\n#else /* for unaligned array */\n  #define SORT_PREFETCH(p,k,s,size) \\\n  { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE; \\\n    if (s2 <= size) { \\\n      Z7_PREFETCH((p + s2 - PREFETCH_RANGE)); \\\n      Z7_PREFETCH((p + s2)); \\\n  }}\n#endif\n\n#else // PREFETCH_LEVEL > 3\n\n#ifdef USE_PREFETCH_FOR_ALIGNED_ARRAY\n  #define SORT_PREFETCH(p,k,s,size) \\\n  { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE - 16 / 2; \\\n    if (s2 <= size) { \\\n      Z7_PREFETCH((p + s2 - 16)); \\\n      Z7_PREFETCH((p + s2)); \\\n  }}\n#else /* for unaligned array */\n  #define SORT_PREFETCH(p,k,s,size) \\\n  { const size_t s2 = PREFETCH_OFFSET(k,s) + PREFETCH_RANGE; \\\n    if (s2 <= size) { \\\n      Z7_PREFETCH((p + s2 - PREFETCH_RANGE)); \\\n      Z7_PREFETCH((p + s2 - PREFETCH_RANGE / 2)); \\\n      Z7_PREFETCH((p + s2)); \\\n  }}\n#endif\n\n#endif // PREFETCH_LEVEL > 3\n#endif // PREFETCH_LEVEL != 0\n#endif // Z7_PREFETCH\n\n\n#if defined(MY_CPU_ARM64) \\\n    /* || defined(MY_CPU_AMD64) */ \\\n    /* || defined(MY_CPU_ARM) && !defined(_MSC_VER) */\n  // we want to use cmov, if cmov is very fast:\n  // - this cmov version is slower for clang-x64.\n  // - this cmov version is faster for gcc-arm64 for some fast arm64 cpus.\n  #define Z7_FAST_CMOV_SUPPORTED\n#endif\n \n#ifdef Z7_FAST_CMOV_SUPPORTED\n  // we want to use cmov here, if cmov is fast: new arm64 cpus.\n  // we want the compiler to use conditional move for this branch\n  #define GET_MAX_VAL(n0, n1, max_val_slow)  if (n0 < n1) n0 = n1;\n#else\n  // use this branch, if cpu doesn't support fast conditional move.\n  // it uses slow array access reading:\n  #define GET_MAX_VAL(n0, n1, max_val_slow)  n0 = max_val_slow;\n#endif\n\n#define HeapSortDown(p, k, size, temp, macro_prefetch) \\\n{ \\\n  for (;;) { \\\n    UInt32 n0, n1; \\\n    size_t s = k * 2; \\\n    if (s >= size) { \\\n      if (s == size) { \\\n        n0 = p[s]; \\\n        p[k] = n0; \\\n        if (temp < n0) k = s; \\\n      } \\\n      break; \\\n    } \\\n    n0 = p[k * 2]; \\\n    n1 = p[k * 2 + 1]; \\\n    s += n0 < n1; \\\n    GET_MAX_VAL(n0, n1, p[s]) \\\n    if (temp >= n0) break; \\\n    macro_prefetch(p, k, s, size) \\\n    p[k] = n0; \\\n    k = s; \\\n  } \\\n  p[k] = temp; \\\n}\n\n\n/*\nstage-1 : O(n) :\n  we generate intermediate partially sorted binary tree:\n  p[0]  : it's additional item for better alignment of tree structure in memory.\n  p[1]\n  p[2]       p[3]\n  p[4] p[5]  p[6] p[7]\n  ...\n  p[x] >= p[x * 2]\n  p[x] >= p[x * 2 + 1]\n  \nstage-2 : O(n)*log2(N):\n  we move largest item p[0] from head of tree to the end of array\n  and insert last item to sorted binary tree.\n*/\n\n// (p) must be aligned for cache line size (64-bytes) for best performance\n\nvoid Z7_FASTCALL HeapSort(UInt32 *p, size_t size)\n{\n  if (size < 2)\n    return;\n  if (size == 2)\n  {\n    const UInt32 a0 = p[0];\n    const UInt32 a1 = p[1];\n    const unsigned k = a1 < a0;\n    p[k] = a0;\n    p[k ^ 1] = a1;\n    return;\n  }\n  {\n    // stage-1 : O(n)\n    // we transform array to partially sorted binary tree.\n    size_t i = --size / 2;\n    // (size) now is the index of the last item in tree,\n    // if (i)\n    {\n      do\n      {\n        const UInt32 temp = p[i];\n        size_t k = i;\n        HeapSortDown(p, k, size, temp, PREFETCH_NO)\n      }\n      while (--i);\n    }\n    {\n      const UInt32 temp = p[0];\n      const UInt32 a1 = p[1];\n      if (temp < a1)\n      {\n        size_t k = 1;\n        p[0] = a1;\n        HeapSortDown(p, k, size, temp, PREFETCH_NO)\n      }\n    }\n  }\n\n  if (size < 3)\n  {\n    // size == 2\n    const UInt32 a0 = p[0];\n    p[0] = p[2];\n    p[2] = a0;\n    return;\n  }\n  if (size != 3)\n  {\n    // stage-2 : O(size) * log2(size):\n    // we move largest item p[0] from head to the end of array,\n    // and insert last item to sorted binary tree.\n    do\n    {\n      const UInt32 temp = p[size];\n      size_t k = p[2] < p[3] ? 3 : 2;\n      p[size--] = p[0];\n      p[0] = p[1];\n      p[1] = p[k];\n      HeapSortDown(p, k, size, temp, SORT_PREFETCH) // PREFETCH_NO\n    }\n    while (size != 3);\n  }\n  {\n    const UInt32 a2 = p[2];\n    const UInt32 a3 = p[3];\n    const size_t k = a2 < a3;\n    p[2] = p[1];\n    p[3] = p[0];\n    p[k] = a3;\n    p[k ^ 1] = a2;\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Sort.h",
    "content": "﻿/* Sort.h -- Sort functions\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_SORT_H\n#define ZIP7_INC_SORT_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\nvoid Z7_FASTCALL HeapSort(UInt32 *p, size_t size);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/SwapBytes.c",
    "content": "﻿/* SwapBytes.c -- Byte Swap conversion filter\n2024-03-01 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"Compiler.h\"\n#include \"CpuArch.h\"\n#include \"RotateDefs.h\"\n#include \"SwapBytes.h\"\n\ntypedef UInt16 CSwapUInt16;\ntypedef UInt32 CSwapUInt32;\n\n// #define k_SwapBytes_Mode_BASE   0\n\n#ifdef MY_CPU_X86_OR_AMD64\n\n#define k_SwapBytes_Mode_SSE2   1\n#define k_SwapBytes_Mode_SSSE3  2\n#define k_SwapBytes_Mode_AVX2   3\n\n  // #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900)\n  #if defined(__clang__) && (__clang_major__ >= 4) \\\n      || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701)\n      #define k_SwapBytes_Mode_MAX  k_SwapBytes_Mode_AVX2\n      #define SWAP_ATTRIB_SSE2  __attribute__((__target__(\"sse2\")))\n      #define SWAP_ATTRIB_SSSE3 __attribute__((__target__(\"ssse3\")))\n      #define SWAP_ATTRIB_AVX2  __attribute__((__target__(\"avx2\")))\n  #elif defined(_MSC_VER)\n    #if (_MSC_VER == 1900)\n      #pragma warning(disable : 4752) // found Intel(R) Advanced Vector Extensions; consider using /arch:AVX\n    #endif\n    #if (_MSC_VER >= 1900)\n      #define k_SwapBytes_Mode_MAX  k_SwapBytes_Mode_AVX2\n    #elif (_MSC_VER >= 1500)  // (VS2008)\n      #define k_SwapBytes_Mode_MAX  k_SwapBytes_Mode_SSSE3\n    #elif (_MSC_VER >= 1310)  // (VS2003)\n      #define k_SwapBytes_Mode_MAX  k_SwapBytes_Mode_SSE2\n    #endif\n  #endif // _MSC_VER\n\n/*\n// for debug\n#ifdef k_SwapBytes_Mode_MAX\n#undef k_SwapBytes_Mode_MAX\n#endif\n*/\n\n#ifndef k_SwapBytes_Mode_MAX\n#define k_SwapBytes_Mode_MAX 0\n#endif\n\n#if (k_SwapBytes_Mode_MAX != 0) && defined(MY_CPU_AMD64)\n  #define k_SwapBytes_Mode_MIN  k_SwapBytes_Mode_SSE2\n#else\n  #define k_SwapBytes_Mode_MIN  0\n#endif\n\n#if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_AVX2)\n  #define USE_SWAP_AVX2\n#endif\n#if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_SSSE3)\n  #define USE_SWAP_SSSE3\n#endif\n#if (k_SwapBytes_Mode_MAX >= k_SwapBytes_Mode_SSE2)\n  #define USE_SWAP_128\n#endif\n\n#if k_SwapBytes_Mode_MAX <= k_SwapBytes_Mode_MIN || !defined(USE_SWAP_128)\n#define FORCE_SWAP_MODE\n#endif\n\n\n#ifdef USE_SWAP_128\n/*\n <mmintrin.h> MMX\n<xmmintrin.h> SSE\n<emmintrin.h> SSE2\n<pmmintrin.h> SSE3\n<tmmintrin.h> SSSE3\n<smmintrin.h> SSE4.1\n<nmmintrin.h> SSE4.2\n<ammintrin.h> SSE4A\n<wmmintrin.h> AES\n<immintrin.h> AVX, AVX2, FMA\n*/\n\n#include <emmintrin.h> // sse2\n// typedef __m128i v128;\n\n#define SWAP2_128(i) { \\\n  const __m128i v = *(const __m128i *)(const void *)(items + (i) * 8); \\\n                    *(      __m128i *)(      void *)(items + (i) * 8) = \\\n    _mm_or_si128( \\\n      _mm_slli_epi16(v, 8), \\\n      _mm_srli_epi16(v, 8)); }\n// _mm_or_si128() has more ports to execute than _mm_add_epi16().\n\nstatic\n#ifdef SWAP_ATTRIB_SSE2\nSWAP_ATTRIB_SSE2\n#endif\nvoid\nZ7_FASTCALL\nSwapBytes2_128(CSwapUInt16 *items, const CSwapUInt16 *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP2_128(0)  SWAP2_128(1)  items += 2 * 8;\n    SWAP2_128(0)  SWAP2_128(1)  items += 2 * 8;\n  }\n  while (items != lim);\n}\n\n/*\n// sse2\n#define SWAP4_128_pack(i) { \\\n  __m128i v = *(const __m128i *)(const void *)(items + (i) * 4); \\\n  __m128i v0 = _mm_unpacklo_epi8(v, mask); \\\n  __m128i v1 = _mm_unpackhi_epi8(v, mask); \\\n  v0 = _mm_shufflelo_epi16(v0, 0x1b); \\\n  v1 = _mm_shufflelo_epi16(v1, 0x1b); \\\n  v0 = _mm_shufflehi_epi16(v0, 0x1b); \\\n  v1 = _mm_shufflehi_epi16(v1, 0x1b); \\\n  *(__m128i *)(void *)(items + (i) * 4) = _mm_packus_epi16(v0, v1); }\n\nstatic\n#ifdef SWAP_ATTRIB_SSE2\nSWAP_ATTRIB_SSE2\n#endif\nvoid\nZ7_FASTCALL\nSwapBytes4_128_pack(CSwapUInt32 *items, const CSwapUInt32 *lim)\n{\n  const __m128i mask = _mm_setzero_si128();\n  // const __m128i mask = _mm_set_epi16(0, 0, 0, 0, 0, 0, 0, 0);\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP4_128_pack(0); items += 1 * 4;\n    // SWAP4_128_pack(0); SWAP4_128_pack(1); items += 2 * 4;\n  }\n  while (items != lim);\n}\n\n// sse2\n#define SWAP4_128_shift(i) { \\\n  __m128i v = *(const __m128i *)(const void *)(items + (i) * 4); \\\n  __m128i v2; \\\n  v2 = _mm_or_si128( \\\n        _mm_slli_si128(_mm_and_si128(v, mask), 1), \\\n        _mm_and_si128(_mm_srli_si128(v, 1), mask)); \\\n  v = _mm_or_si128( \\\n        _mm_slli_epi32(v, 24), \\\n        _mm_srli_epi32(v, 24)); \\\n  *(__m128i *)(void *)(items + (i) * 4) = _mm_or_si128(v2, v); }\n\nstatic\n#ifdef SWAP_ATTRIB_SSE2\nSWAP_ATTRIB_SSE2\n#endif\nvoid\nZ7_FASTCALL\nSwapBytes4_128_shift(CSwapUInt32 *items, const CSwapUInt32 *lim)\n{\n  #define M1 0xff00\n  const __m128i mask = _mm_set_epi32(M1, M1, M1, M1);\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    // SWAP4_128_shift(0)  SWAP4_128_shift(1)  items += 2 * 4;\n    // SWAP4_128_shift(0)  SWAP4_128_shift(1)  items += 2 * 4;\n    SWAP4_128_shift(0); items += 1 * 4;\n  }\n  while (items != lim);\n}\n*/\n\n\n#if defined(USE_SWAP_SSSE3) || defined(USE_SWAP_AVX2)\n\n#define SWAP_SHUF_REV_SEQ_2_VALS(v)                (v)+1, (v)\n#define SWAP_SHUF_REV_SEQ_4_VALS(v)  (v)+3, (v)+2, (v)+1, (v)\n\n#define SWAP2_SHUF_MASK_16_BYTES \\\n    SWAP_SHUF_REV_SEQ_2_VALS (0 * 2), \\\n    SWAP_SHUF_REV_SEQ_2_VALS (1 * 2), \\\n    SWAP_SHUF_REV_SEQ_2_VALS (2 * 2), \\\n    SWAP_SHUF_REV_SEQ_2_VALS (3 * 2), \\\n    SWAP_SHUF_REV_SEQ_2_VALS (4 * 2), \\\n    SWAP_SHUF_REV_SEQ_2_VALS (5 * 2), \\\n    SWAP_SHUF_REV_SEQ_2_VALS (6 * 2), \\\n    SWAP_SHUF_REV_SEQ_2_VALS (7 * 2)\n\n#define SWAP4_SHUF_MASK_16_BYTES \\\n    SWAP_SHUF_REV_SEQ_4_VALS (0 * 4), \\\n    SWAP_SHUF_REV_SEQ_4_VALS (1 * 4), \\\n    SWAP_SHUF_REV_SEQ_4_VALS (2 * 4), \\\n    SWAP_SHUF_REV_SEQ_4_VALS (3 * 4)\n\n#if defined(USE_SWAP_AVX2)\n/* if we use 256_BIT_INIT_MASK, each static array mask will be larger for 16 bytes */\n// #define SWAP_USE_256_BIT_INIT_MASK\n#endif\n\n#if defined(SWAP_USE_256_BIT_INIT_MASK) && defined(USE_SWAP_AVX2)\n#define SWAP_MASK_INIT_SIZE 32\n#else\n#define SWAP_MASK_INIT_SIZE 16\n#endif\n\nMY_ALIGN(SWAP_MASK_INIT_SIZE)\nstatic const Byte k_ShufMask_Swap2[] =\n{\n    SWAP2_SHUF_MASK_16_BYTES\n  #if SWAP_MASK_INIT_SIZE > 16\n  , SWAP2_SHUF_MASK_16_BYTES\n  #endif\n};\n\nMY_ALIGN(SWAP_MASK_INIT_SIZE)\nstatic const Byte k_ShufMask_Swap4[] =\n{\n    SWAP4_SHUF_MASK_16_BYTES\n  #if SWAP_MASK_INIT_SIZE > 16\n  , SWAP4_SHUF_MASK_16_BYTES\n  #endif\n};\n\n\n#ifdef USE_SWAP_SSSE3\n\n#include <tmmintrin.h> // ssse3\n\n#define SHUF_128(i)   *(items + (i)) = \\\n     _mm_shuffle_epi8(*(items + (i)), mask); // SSSE3\n\n// Z7_NO_INLINE\nstatic\n#ifdef SWAP_ATTRIB_SSSE3\nSWAP_ATTRIB_SSSE3\n#endif\nZ7_ATTRIB_NO_VECTORIZE\nvoid\nZ7_FASTCALL\nShufBytes_128(void *items8, const void *lim8, const void *mask128_ptr)\n{\n  __m128i *items = (__m128i *)items8;\n  const __m128i *lim = (const __m128i *)lim8;\n  // const __m128i mask = _mm_set_epi8(SHUF_SWAP2_MASK_16_VALS);\n  // const __m128i mask = _mm_set_epi8(SHUF_SWAP4_MASK_16_VALS);\n  // const __m128i mask = _mm_load_si128((const __m128i *)(const void *)&(k_ShufMask_Swap4[0]));\n  // const __m128i mask = _mm_load_si128((const __m128i *)(const void *)&(k_ShufMask_Swap4[0]));\n  // const __m128i mask = *(const __m128i *)(const void *)&(k_ShufMask_Swap4[0]);\n  const __m128i mask = *(const __m128i *)mask128_ptr;\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SHUF_128(0)  SHUF_128(1)  items += 2;\n    SHUF_128(0)  SHUF_128(1)  items += 2;\n  }\n  while (items != lim);\n}\n\n#endif // USE_SWAP_SSSE3\n\n\n\n#ifdef USE_SWAP_AVX2\n\n#include <immintrin.h> // avx, avx2\n#if defined(__clang__)\n#include <avxintrin.h>\n#include <avx2intrin.h>\n#endif\n\n#define SHUF_256(i)   *(items + (i)) = \\\n  _mm256_shuffle_epi8(*(items + (i)), mask); // AVX2\n\n// Z7_NO_INLINE\nstatic\n#ifdef SWAP_ATTRIB_AVX2\nSWAP_ATTRIB_AVX2\n#endif\nZ7_ATTRIB_NO_VECTORIZE\nvoid\nZ7_FASTCALL\nShufBytes_256(void *items8, const void *lim8, const void *mask128_ptr)\n{\n  __m256i *items = (__m256i *)items8;\n  const __m256i *lim = (const __m256i *)lim8;\n  /*\n  UNUSED_VAR(mask128_ptr)\n  __m256i mask =\n  for Swap4: _mm256_setr_epi8(SWAP4_SHUF_MASK_16_BYTES, SWAP4_SHUF_MASK_16_BYTES);\n  for Swap2: _mm256_setr_epi8(SWAP2_SHUF_MASK_16_BYTES, SWAP2_SHUF_MASK_16_BYTES);\n  */\n  const __m256i mask =\n #if SWAP_MASK_INIT_SIZE > 16\n      *(const __m256i *)(const void *)mask128_ptr;\n #else\n  /* msvc: broadcastsi128() version reserves the stack for no reason\n     msvc 19.29-: _mm256_insertf128_si256() / _mm256_set_m128i)) versions use non-avx movdqu   xmm0,XMMWORD PTR [r8]\n     msvc 19.30+ (VS2022): replaces _mm256_set_m128i(m,m) to vbroadcastf128(m) as we want\n  */\n  // _mm256_broadcastsi128_si256(*mask128_ptr);\n#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 80000)\n  #define MY_mm256_set_m128i(hi, lo)  _mm256_insertf128_si256(_mm256_castsi128_si256(lo), (hi), 1)\n#else\n  #define MY_mm256_set_m128i  _mm256_set_m128i\n#endif\n      MY_mm256_set_m128i(\n        *(const __m128i *)mask128_ptr,\n        *(const __m128i *)mask128_ptr);\n #endif\n  \n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SHUF_256(0)  SHUF_256(1)  items += 2;\n    SHUF_256(0)  SHUF_256(1)  items += 2;\n  }\n  while (items != lim);\n}\n\n#endif // USE_SWAP_AVX2\n#endif // USE_SWAP_SSSE3 || USE_SWAP_AVX2\n#endif // USE_SWAP_128\n\n\n\n// compile message \"NEON intrinsics not available with the soft-float ABI\"\n#elif defined(MY_CPU_ARM_OR_ARM64) \\\n    && defined(MY_CPU_LE) \\\n    && !defined(Z7_DISABLE_ARM_NEON)\n\n  #if defined(__clang__) && (__clang_major__ >= 8) \\\n    || defined(__GNUC__) && (__GNUC__ >= 6)\n    #if defined(__ARM_FP)\n    #if (defined(__ARM_ARCH) && (__ARM_ARCH >= 4)) \\\n        || defined(MY_CPU_ARM64)\n    #if  defined(MY_CPU_ARM64) \\\n      || !defined(Z7_CLANG_VERSION) \\\n      || defined(__ARM_NEON)\n      #define USE_SWAP_128\n    #ifdef MY_CPU_ARM64\n      // #define SWAP_ATTRIB_NEON __attribute__((__target__(\"\")))\n    #else\n#if defined(Z7_CLANG_VERSION)\n      // #define SWAP_ATTRIB_NEON __attribute__((__target__(\"neon\")))\n#else\n      // #pragma message(\"SWAP_ATTRIB_NEON __attribute__((__target__(fpu=neon))\")\n      #define SWAP_ATTRIB_NEON __attribute__((__target__(\"fpu=neon\")))\n#endif\n    #endif // MY_CPU_ARM64\n    #endif // __ARM_NEON\n    #endif // __ARM_ARCH\n    #endif // __ARM_FP\n\n  #elif defined(_MSC_VER)\n    #if (_MSC_VER >= 1910)\n      #define USE_SWAP_128\n    #endif\n  #endif\n\n  #ifdef USE_SWAP_128\n  #if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_ARM64)\n    #include <arm64_neon.h>\n  #else\n\n/*\n#if !defined(__ARM_NEON)\n#if defined(Z7_GCC_VERSION) && (__GNUC__  <   5) \\\n || defined(Z7_GCC_VERSION) && (__GNUC__ ==   5) && (Z7_GCC_VERSION <  90201) \\\n || defined(Z7_GCC_VERSION) && (__GNUC__ ==   5) && (Z7_GCC_VERSION < 100100)\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n#pragma message(\"#define __ARM_NEON 1\")\n// #define __ARM_NEON 1\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif\n#endif\n*/\n    #include <arm_neon.h>\n  #endif\n  #endif\n\n#ifndef USE_SWAP_128\n  #define FORCE_SWAP_MODE\n#else\n \n#ifdef MY_CPU_ARM64\n  // for debug : comment it\n  #define FORCE_SWAP_MODE\n#else\n  #define k_SwapBytes_Mode_NEON 1\n#endif\n// typedef uint8x16_t v128;\n#define SWAP2_128(i)   *(uint8x16_t *)      (void *)(items + (i) * 8) = \\\n      vrev16q_u8(*(const uint8x16_t *)(const void *)(items + (i) * 8));\n#define SWAP4_128(i)   *(uint8x16_t *)      (void *)(items + (i) * 4) = \\\n      vrev32q_u8(*(const uint8x16_t *)(const void *)(items + (i) * 4));\n\n// Z7_NO_INLINE\nstatic\n#ifdef SWAP_ATTRIB_NEON\nSWAP_ATTRIB_NEON\n#endif\nZ7_ATTRIB_NO_VECTORIZE\nvoid\nZ7_FASTCALL\nSwapBytes2_128(CSwapUInt16 *items, const CSwapUInt16 *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP2_128(0)  SWAP2_128(1)  items += 2 * 8;\n    SWAP2_128(0)  SWAP2_128(1)  items += 2 * 8;\n  }\n  while (items != lim);\n}\n\n// Z7_NO_INLINE\nstatic\n#ifdef SWAP_ATTRIB_NEON\nSWAP_ATTRIB_NEON\n#endif\nZ7_ATTRIB_NO_VECTORIZE\nvoid\nZ7_FASTCALL\nSwapBytes4_128(CSwapUInt32 *items, const CSwapUInt32 *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP4_128(0)  SWAP4_128(1)  items += 2 * 4;\n    SWAP4_128(0)  SWAP4_128(1)  items += 2 * 4;\n  }\n  while (items != lim);\n}\n\n#endif // USE_SWAP_128\n\n#else // MY_CPU_ARM_OR_ARM64\n#define FORCE_SWAP_MODE\n#endif // MY_CPU_ARM_OR_ARM64\n\n\n\n\n\n\n#if defined(Z7_MSC_VER_ORIGINAL) && defined(MY_CPU_X86)\n  /* _byteswap_ushort() in MSVC x86 32-bit works via slow { mov dh, al; mov dl, ah }\n     So we use own versions of byteswap function */\n  #if (_MSC_VER < 1400 )  // old MSVC-X86 without _rotr16() support\n    #define SWAP2_16(i)  { UInt32 v = items[i];  v += (v << 16);  v >>= 8;  items[i] = (CSwapUInt16)v; }\n  #else  // is new MSVC-X86 with fast _rotr16()\n    #include <intrin.h>\n    #define SWAP2_16(i)  { items[i] = _rotr16(items[i], 8); }\n  #endif\n#else  // is not MSVC-X86\n  #define SWAP2_16(i)  { CSwapUInt16 v = items[i];  items[i] = Z7_BSWAP16(v); }\n#endif  // MSVC-X86\n\n#if defined(Z7_CPU_FAST_BSWAP_SUPPORTED)\n  #define SWAP4_32(i)  { CSwapUInt32 v = items[i];  items[i] = Z7_BSWAP32(v); }\n#else\n  #define SWAP4_32(i)  \\\n    { UInt32 v = items[i]; \\\n      v = ((v & 0xff00ff) << 8) + ((v >> 8) & 0xff00ff); \\\n      v = rotlFixed(v, 16); \\\n      items[i] = v; }\n#endif\n\n\n\n\n#if defined(FORCE_SWAP_MODE) && defined(USE_SWAP_128)\n  #define DEFAULT_Swap2  SwapBytes2_128\n  #if !defined(MY_CPU_X86_OR_AMD64)\n    #define DEFAULT_Swap4  SwapBytes4_128\n  #endif\n#endif\n\n#if !defined(DEFAULT_Swap2) || !defined(DEFAULT_Swap4)\n\n#define SWAP_BASE_FUNCS_PREFIXES \\\nZ7_FORCE_INLINE  \\\nstatic \\\nZ7_ATTRIB_NO_VECTOR  \\\nvoid Z7_FASTCALL\n\n\n#if defined(MY_CPU_ARM_OR_ARM64)\n#if defined(__clang__)\n#pragma GCC diagnostic ignored \"-Wlanguage-extension-token\"\n#endif\n#endif\n\n\n#ifdef MY_CPU_64BIT\n\n#if defined(MY_CPU_ARM64) \\\n    && defined(__ARM_ARCH) && (__ARM_ARCH >= 8) \\\n    && (  (defined(__GNUC__) && (__GNUC__ >= 4)) \\\n       || (defined(__clang__) && (__clang_major__ >= 4)))\n\n  #define SWAP2_64_VAR(v)  asm (\"rev16 %x0,%x0\" : \"+r\" (v));\n  #define SWAP4_64_VAR(v)  asm (\"rev32 %x0,%x0\" : \"+r\" (v));\n\n#else  // is not ARM64-GNU\n\n#if !defined(MY_CPU_X86_OR_AMD64) || (k_SwapBytes_Mode_MIN == 0) || !defined(USE_SWAP_128)\n  #define SWAP2_64_VAR(v) \\\n    v = ( 0x00ff00ff00ff00ff & (v >> 8))  \\\n      + ((0x00ff00ff00ff00ff & v) << 8);\n      /* plus gives faster code in MSVC */\n#endif\n\n#ifdef Z7_CPU_FAST_BSWAP_SUPPORTED\n  #define SWAP4_64_VAR(v) \\\n    v = Z7_BSWAP64(v); \\\n    v = Z7_ROTL64(v, 32);\n#else\n  #define SWAP4_64_VAR(v) \\\n    v = ( 0x000000ff000000ff & (v >> 24))  \\\n      + ((0x000000ff000000ff & v) << 24 )  \\\n      + ( 0x0000ff000000ff00 & (v >>  8))  \\\n      + ((0x0000ff000000ff00 & v) <<  8 )  \\\n      ;\n#endif\n\n#endif  // ARM64-GNU\n\n\n#ifdef SWAP2_64_VAR\n\n#define SWAP2_64(i) { \\\n    UInt64 v = *(const UInt64 *)(const void *)(items + (i) * 4); \\\n    SWAP2_64_VAR(v) \\\n    *(UInt64 *)(void *)(items + (i) * 4) = v; }\n\nSWAP_BASE_FUNCS_PREFIXES\nSwapBytes2_64(CSwapUInt16 *items, const CSwapUInt16 *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP2_64(0)  SWAP2_64(1)  items += 2 * 4;\n    SWAP2_64(0)  SWAP2_64(1)  items += 2 * 4;\n  }\n  while (items != lim);\n}\n\n  #define DEFAULT_Swap2  SwapBytes2_64\n  #if !defined(FORCE_SWAP_MODE)\n    #define SWAP2_DEFAULT_MODE 0\n  #endif\n#else // !defined(SWAP2_64_VAR)\n  #define DEFAULT_Swap2  SwapBytes2_128\n  #if !defined(FORCE_SWAP_MODE)\n    #define SWAP2_DEFAULT_MODE 1\n  #endif\n#endif // SWAP2_64_VAR\n\n\n#define SWAP4_64(i) { \\\n    UInt64 v = *(const UInt64 *)(const void *)(items + (i) * 2); \\\n    SWAP4_64_VAR(v) \\\n    *(UInt64 *)(void *)(items + (i) * 2) = v; }\n\nSWAP_BASE_FUNCS_PREFIXES\nSwapBytes4_64(CSwapUInt32 *items, const CSwapUInt32 *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP4_64(0)  SWAP4_64(1)  items += 2 * 2;\n    SWAP4_64(0)  SWAP4_64(1)  items += 2 * 2;\n  }\n  while (items != lim);\n}\n\n#define DEFAULT_Swap4  SwapBytes4_64\n\n#else  // is not 64BIT\n\n\n#if defined(MY_CPU_ARM_OR_ARM64) \\\n    && defined(__ARM_ARCH) && (__ARM_ARCH >= 6) \\\n    && (  (defined(__GNUC__) && (__GNUC__ >= 4)) \\\n       || (defined(__clang__) && (__clang_major__ >= 4)))\n\n#ifdef MY_CPU_64BIT\n  #define SWAP2_32_VAR(v)  asm (\"rev16 %w0,%w0\" : \"+r\" (v));\n#else\n  #define SWAP2_32_VAR(v)  asm (\"rev16 %0,%0\" : \"+r\" (v)); // for clang/gcc\n    // asm (\"rev16 %r0,%r0\" : \"+r\" (a));  // for gcc\n#endif\n\n#elif defined(_MSC_VER) && (_MSC_VER < 1300) && defined(MY_CPU_X86) \\\n    || !defined(Z7_CPU_FAST_BSWAP_SUPPORTED) \\\n    || !defined(Z7_CPU_FAST_ROTATE_SUPPORTED)\n  // old msvc doesn't support _byteswap_ulong()\n  #define SWAP2_32_VAR(v) \\\n    v = ((v & 0xff00ff) << 8) + ((v >> 8) & 0xff00ff);\n\n#else  // is not ARM and is not old-MSVC-X86 and fast BSWAP/ROTATE are supported\n  #define SWAP2_32_VAR(v) \\\n    v = Z7_BSWAP32(v); \\\n    v = rotlFixed(v, 16);\n\n#endif  // GNU-ARM*\n\n#define SWAP2_32(i) { \\\n    UInt32 v = *(const UInt32 *)(const void *)(items + (i) * 2); \\\n    SWAP2_32_VAR(v); \\\n    *(UInt32 *)(void *)(items + (i) * 2) = v; }\n\n\nSWAP_BASE_FUNCS_PREFIXES\nSwapBytes2_32(CSwapUInt16 *items, const CSwapUInt16 *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP2_32(0)  SWAP2_32(1)  items += 2 * 2;\n    SWAP2_32(0)  SWAP2_32(1)  items += 2 * 2;\n  }\n  while (items != lim);\n}\n\n\nSWAP_BASE_FUNCS_PREFIXES\nSwapBytes4_32(CSwapUInt32 *items, const CSwapUInt32 *lim)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  do\n  {\n    SWAP4_32(0)  SWAP4_32(1)  items += 2;\n    SWAP4_32(0)  SWAP4_32(1)  items += 2;\n  }\n  while (items != lim);\n}\n\n#define DEFAULT_Swap2  SwapBytes2_32\n#define DEFAULT_Swap4  SwapBytes4_32\n#if !defined(FORCE_SWAP_MODE)\n  #define SWAP2_DEFAULT_MODE 0\n#endif\n\n#endif // MY_CPU_64BIT\n#endif // if !defined(DEFAULT_Swap2) || !defined(DEFAULT_Swap4)\n\n\n\n#if !defined(FORCE_SWAP_MODE)\nstatic unsigned g_SwapBytes_Mode;\n#endif\n\n/* size of largest unrolled loop iteration: 128 bytes = 4 * 32 bytes (AVX). */\n#define SWAP_ITERATION_BLOCK_SIZE_MAX  (1 << 7)\n\n// 32 bytes for (AVX) or 2 * 16-bytes for NEON.\n#define SWAP_VECTOR_ALIGN_SIZE  (1 << 5)\n\nZ7_NO_INLINE\nvoid z7_SwapBytes2(CSwapUInt16 *items, size_t numItems)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (SWAP_VECTOR_ALIGN_SIZE - 1)) != 0; numItems--)\n  {\n    SWAP2_16(0)\n    items++;\n  }\n  {\n    const size_t k_Align_Mask = SWAP_ITERATION_BLOCK_SIZE_MAX / sizeof(CSwapUInt16) - 1;\n    size_t numItems2 = numItems;\n    CSwapUInt16 *lim;\n    numItems &= k_Align_Mask;\n    numItems2 &= ~(size_t)k_Align_Mask;\n    lim = items + numItems2;\n    if (numItems2 != 0)\n    {\n     #if !defined(FORCE_SWAP_MODE)\n      #ifdef MY_CPU_X86_OR_AMD64\n        #ifdef USE_SWAP_AVX2\n          if (g_SwapBytes_Mode > k_SwapBytes_Mode_SSSE3)\n            ShufBytes_256((__m256i *)(void *)items,\n                (const __m256i *)(const void *)lim,\n                (const __m128i *)(const void *)&(k_ShufMask_Swap2[0]));\n          else\n        #endif\n        #ifdef USE_SWAP_SSSE3\n          if (g_SwapBytes_Mode >= k_SwapBytes_Mode_SSSE3)\n            ShufBytes_128((__m128i *)(void *)items,\n                (const __m128i *)(const void *)lim,\n                (const __m128i *)(const void *)&(k_ShufMask_Swap2[0]));\n          else\n        #endif\n      #endif  // MY_CPU_X86_OR_AMD64\n      #if SWAP2_DEFAULT_MODE == 0\n          if (g_SwapBytes_Mode != 0)\n            SwapBytes2_128(items, lim);\n          else\n      #endif\n     #endif // FORCE_SWAP_MODE\n            DEFAULT_Swap2(items, lim);\n    }\n    items = lim;\n  }\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  for (; numItems != 0; numItems--)\n  {\n    SWAP2_16(0)\n    items++;\n  }\n}\n\n\nZ7_NO_INLINE\nvoid z7_SwapBytes4(CSwapUInt32 *items, size_t numItems)\n{\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  for (; numItems != 0 && ((unsigned)(ptrdiff_t)items & (SWAP_VECTOR_ALIGN_SIZE - 1)) != 0; numItems--)\n  {\n    SWAP4_32(0)\n    items++;\n  }\n  {\n    const size_t k_Align_Mask = SWAP_ITERATION_BLOCK_SIZE_MAX / sizeof(CSwapUInt32) - 1;\n    size_t numItems2 = numItems;\n    CSwapUInt32 *lim;\n    numItems &= k_Align_Mask;\n    numItems2 &= ~(size_t)k_Align_Mask;\n    lim = items + numItems2;\n    if (numItems2 != 0)\n    {\n     #if !defined(FORCE_SWAP_MODE)\n      #ifdef MY_CPU_X86_OR_AMD64\n        #ifdef USE_SWAP_AVX2\n          if (g_SwapBytes_Mode > k_SwapBytes_Mode_SSSE3)\n            ShufBytes_256((__m256i *)(void *)items,\n                (const __m256i *)(const void *)lim,\n                (const __m128i *)(const void *)&(k_ShufMask_Swap4[0]));\n          else\n        #endif\n        #ifdef USE_SWAP_SSSE3\n          if (g_SwapBytes_Mode >= k_SwapBytes_Mode_SSSE3)\n            ShufBytes_128((__m128i *)(void *)items,\n                (const __m128i *)(const void *)lim,\n                (const __m128i *)(const void *)&(k_ShufMask_Swap4[0]));\n          else\n        #endif\n      #else  // MY_CPU_X86_OR_AMD64\n\n          if (g_SwapBytes_Mode != 0)\n            SwapBytes4_128(items, lim);\n          else\n      #endif  // MY_CPU_X86_OR_AMD64\n     #endif // FORCE_SWAP_MODE\n            DEFAULT_Swap4(items, lim);\n    }\n    items = lim;\n  }\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n  for (; numItems != 0; numItems--)\n  {\n    SWAP4_32(0)\n    items++;\n  }\n}\n\n\n// #define SHOW_HW_STATUS\n\n#ifdef SHOW_HW_STATUS\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\nvoid z7_SwapBytesPrepare(void)\n{\n#ifndef FORCE_SWAP_MODE\n  unsigned mode = 0; // k_SwapBytes_Mode_BASE;\n\n#ifdef MY_CPU_ARM_OR_ARM64\n  {\n    if (CPU_IsSupported_NEON())\n    {\n      // #pragma message (\"=== SwapBytes NEON\")\n      PRF(printf(\"\\n=== SwapBytes NEON\\n\");)\n      mode = k_SwapBytes_Mode_NEON;\n    }\n  }\n#else // MY_CPU_ARM_OR_ARM64\n  {\n    #ifdef USE_SWAP_AVX2\n      if (CPU_IsSupported_AVX2())\n      {\n        // #pragma message (\"=== SwapBytes AVX2\")\n        PRF(printf(\"\\n=== SwapBytes AVX2\\n\");)\n        mode = k_SwapBytes_Mode_AVX2;\n      }\n      else\n    #endif\n    #ifdef USE_SWAP_SSSE3\n      if (CPU_IsSupported_SSSE3())\n      {\n        // #pragma message (\"=== SwapBytes SSSE3\")\n        PRF(printf(\"\\n=== SwapBytes SSSE3\\n\");)\n        mode = k_SwapBytes_Mode_SSSE3;\n      }\n      else\n    #endif\n    #if !defined(MY_CPU_AMD64)\n      if (CPU_IsSupported_SSE2())\n    #endif\n      {\n        // #pragma message (\"=== SwapBytes SSE2\")\n        PRF(printf(\"\\n=== SwapBytes SSE2\\n\");)\n        mode = k_SwapBytes_Mode_SSE2;\n      }\n  }\n#endif // MY_CPU_ARM_OR_ARM64\n  g_SwapBytes_Mode = mode;\n  // g_SwapBytes_Mode = 0; // for debug\n#endif // FORCE_SWAP_MODE\n  PRF(printf(\"\\n=== SwapBytesPrepare\\n\");)\n}\n\n#undef PRF\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/SwapBytes.h",
    "content": "﻿/* SwapBytes.h -- Byte Swap conversion filter\n2023-04-02 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_SWAP_BYTES_H\n#define ZIP7_INC_SWAP_BYTES_H\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\nvoid z7_SwapBytes2(UInt16 *data, size_t numItems);\nvoid z7_SwapBytes4(UInt32 *data, size_t numItems);\nvoid z7_SwapBytesPrepare(void);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Threads.c",
    "content": "﻿/* Threads.c -- multithreading library\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#ifdef _WIN32\n\n#ifndef USE_THREADS_CreateThread\n#include <process.h>\n#endif\n\n#include \"Threads.h\"\n\nstatic WRes GetError(void)\n{\n  const DWORD res = GetLastError();\n  return res ? (WRes)res : 1;\n}\n\nstatic WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); }\nstatic WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }\n\nWRes HandlePtr_Close(HANDLE *p)\n{\n  if (*p != NULL)\n  {\n    if (!CloseHandle(*p))\n      return GetError();\n    *p = NULL;\n  }\n  return 0;\n}\n\nWRes Handle_WaitObject(HANDLE h)\n{\n  DWORD dw = WaitForSingleObject(h, INFINITE);\n  /*\n    (dw) result:\n    WAIT_OBJECT_0  // 0\n    WAIT_ABANDONED // 0x00000080 : is not compatible with Win32 Error space\n    WAIT_TIMEOUT   // 0x00000102 : is     compatible with Win32 Error space\n    WAIT_FAILED    // 0xFFFFFFFF\n  */\n  if (dw == WAIT_FAILED)\n  {\n    dw = GetLastError();\n    if (dw == 0)\n      return WAIT_FAILED;\n  }\n  return (WRes)dw;\n}\n\n#define Thread_Wait(p) Handle_WaitObject(*(p))\n\nWRes Thread_Wait_Close(CThread *p)\n{\n  WRes res = Thread_Wait(p);\n  WRes res2 = Thread_Close(p);\n  return (res != 0 ? res : res2);\n}\n\ntypedef struct MY_PROCESSOR_NUMBER {\n    WORD  Group;\n    BYTE  Number;\n    BYTE  Reserved;\n} MY_PROCESSOR_NUMBER, *MY_PPROCESSOR_NUMBER;\n\ntypedef struct MY_GROUP_AFFINITY {\n#if defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION < 100000)\n    // KAFFINITY is not defined in old mingw\n    ULONG_PTR\n#else\n    KAFFINITY\n#endif\n      Mask;\n    WORD   Group;\n    WORD   Reserved[3];\n} MY_GROUP_AFFINITY, *MY_PGROUP_AFFINITY;\n\ntypedef BOOL (WINAPI *Func_SetThreadGroupAffinity)(\n    HANDLE hThread,\n    CONST MY_GROUP_AFFINITY *GroupAffinity,\n    MY_PGROUP_AFFINITY PreviousGroupAffinity);\n\ntypedef BOOL (WINAPI *Func_GetThreadGroupAffinity)(\n    HANDLE hThread,\n    MY_PGROUP_AFFINITY GroupAffinity);\n\ntypedef BOOL (WINAPI *Func_GetProcessGroupAffinity)(\n    HANDLE hProcess,\n    PUSHORT GroupCount,\n    PUSHORT GroupArray);\n\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\n#if 0\n#include <stdio.h>\n#define PRF(x) x\n/*\n--\n  before call of SetThreadGroupAffinity()\n    GetProcessGroupAffinity return one group.\n  after call of SetThreadGroupAffinity():\n    GetProcessGroupAffinity return more than group,\n    if SetThreadGroupAffinity() was to another group.\n--\n  GetProcessAffinityMask MS DOCs:\n  {\n    If the calling process contains threads in multiple groups,\n    the function returns zero for both affinity masks.\n  }\n  but tests in win10 with 2 groups (less than 64 cores total):\n    GetProcessAffinityMask() still returns non-zero affinity masks\n    even after SetThreadGroupAffinity() calls.\n*/\nstatic void PrintProcess_Info()\n{\n  {\n    const\n      Func_GetProcessGroupAffinity fn_GetProcessGroupAffinity =\n     (Func_GetProcessGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT(\"kernel32.dll\")),\n          \"GetProcessGroupAffinity\");\n    if (fn_GetProcessGroupAffinity)\n    {\n      unsigned i;\n      USHORT GroupCounts[64];\n      USHORT GroupCount = Z7_ARRAY_SIZE(GroupCounts);\n      BOOL boolRes = fn_GetProcessGroupAffinity(GetCurrentProcess(),\n          &GroupCount, GroupCounts);\n      printf(\"\\n====== GetProcessGroupAffinity : \"\n          \"boolRes=%u GroupCounts = %u :\",\n          boolRes, (unsigned)GroupCount);\n      for (i = 0; i < GroupCount; i++)\n        printf(\" %u\", GroupCounts[i]);\n      printf(\"\\n\");\n    }\n  }\n  {\n    DWORD_PTR processAffinityMask, systemAffinityMask;\n    if (GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask))\n    {\n      PRF(printf(\"\\n====== GetProcessAffinityMask : \"\n        \": processAffinityMask=%x, systemAffinityMask=%x\\n\",\n        (UInt32)processAffinityMask, (UInt32)systemAffinityMask);)\n    }\n    else\n      printf(\"\\n==GetProcessAffinityMask FAIL\");\n  }\n}\n#else\n#ifndef USE_THREADS_CreateThread\n// #define PRF(x)\n#endif\n#endif\n\nWRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)\n{\n  /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */\n\n  #ifdef USE_THREADS_CreateThread\n\n  DWORD threadId;\n  *p = CreateThread(NULL, 0, func, param, 0, &threadId);\n  \n  #else\n  \n  unsigned threadId;\n  *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId));\n\n#if 0 // 1 : for debug\n  {\n      DWORD_PTR prevMask;\n      DWORD_PTR affinity = 1 << 0;\n      prevMask = SetThreadAffinityMask(*p, (DWORD_PTR)affinity);\n      prevMask = prevMask;\n  }\n#endif\n#if 0 // 1 : for debug\n  {\n      /* win10: new thread will be created in same group that is assigned to parent thread\n                but affinity mask will contain all allowed threads of that group,\n                even if affinity mask of parent group is not full\n         win11: what group it will be created, if we have set\n                affinity of parent thread with ThreadGroupAffinity?\n      */\n      const\n         Func_GetThreadGroupAffinity fn =\n        (Func_GetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT(\"kernel32.dll\")),\n             \"GetThreadGroupAffinity\");\n      if (fn)\n      {\n        // BOOL wres2;\n        MY_GROUP_AFFINITY groupAffinity;\n        memset(&groupAffinity, 0, sizeof(groupAffinity));\n        /* wres2 = */ fn(*p, &groupAffinity);\n        PRF(printf(\"\\n==Thread_Create cur = %6u GetThreadGroupAffinity(): \"\n            \"wres2_BOOL = %u, group=%u mask=%x\\n\",\n            GetCurrentThreadId(),\n            wres2,\n            groupAffinity.Group,\n            (UInt32)groupAffinity.Mask);)\n      }\n  }\n#endif\n\n  #endif\n\n  /* maybe we must use errno here, but probably GetLastError() is also OK. */\n  return HandleToWRes(*p);\n}\n\n\nWRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)\n{\n  #ifdef USE_THREADS_CreateThread\n\n  UNUSED_VAR(affinity)\n  return Thread_Create(p, func, param);\n  \n  #else\n  \n  /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */\n  HANDLE h;\n  WRes wres;\n  unsigned threadId;\n  h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));\n  *p = h;\n  wres = HandleToWRes(h);\n  if (h)\n  {\n    {\n      // DWORD_PTR prevMask =\n      SetThreadAffinityMask(h, (DWORD_PTR)affinity);\n      /*\n      if (prevMask == 0)\n      {\n        // affinity change is non-critical error, so we can ignore it\n        // wres = GetError();\n      }\n      */\n    }\n    {\n      const DWORD prevSuspendCount = ResumeThread(h);\n      /* ResumeThread() returns:\n         0 : was_not_suspended\n         1 : was_resumed\n        -1 : error\n      */\n      if (prevSuspendCount == (DWORD)-1)\n        wres = GetError();\n    }\n  }\n\n  /* maybe we must use errno here, but probably GetLastError() is also OK. */\n  return wres;\n\n  #endif\n}\n\n\nWRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask)\n{\n#ifdef USE_THREADS_CreateThread\n\n  UNUSED_VAR(group)\n  UNUSED_VAR(affinityMask)\n  return Thread_Create(p, func, param);\n  \n#else\n  \n  /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */\n  HANDLE h;\n  WRes wres;\n  unsigned threadId;\n  h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));\n  *p = h;\n  wres = HandleToWRes(h);\n  if (h)\n  {\n    // PrintProcess_Info();\n    {\n      const\n         Func_SetThreadGroupAffinity fn =\n        (Func_SetThreadGroupAffinity) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT(\"kernel32.dll\")),\n             \"SetThreadGroupAffinity\");\n      if (fn)\n      {\n        // WRes wres2;\n        MY_GROUP_AFFINITY groupAffinity, prev_groupAffinity;\n        memset(&groupAffinity, 0, sizeof(groupAffinity));\n        // groupAffinity.Mask must use only bits that supported by current group\n        // (groupAffinity.Mask = 0) means all allowed bits\n        groupAffinity.Mask = affinityMask;\n        groupAffinity.Group = (WORD)group;\n        // wres2 =\n        fn(h, &groupAffinity, &prev_groupAffinity);\n        /*\n        if (groupAffinity.Group == prev_groupAffinity.Group)\n          wres2 = wres2;\n        else\n          wres2 = wres2;\n        if (wres2 == 0)\n        {\n          wres2 = GetError();\n          PRF(printf(\"\\n==SetThreadGroupAffinity error: %u\\n\", wres2);)\n        }\n        else\n        {\n          PRF(printf(\"\\n==Thread_Create_With_Group::SetThreadGroupAffinity()\"\n            \" threadId = %6u\"\n            \" group=%u mask=%x\\n\",\n            threadId,\n            prev_groupAffinity.Group,\n            (UInt32)prev_groupAffinity.Mask);)\n        }\n        */\n      }\n    }\n    {\n      const DWORD prevSuspendCount = ResumeThread(h);\n      /* ResumeThread() returns:\n         0 : was_not_suspended\n         1 : was_resumed\n        -1 : error\n      */\n      if (prevSuspendCount == (DWORD)-1)\n        wres = GetError();\n    }\n  }\n\n  /* maybe we must use errno here, but probably GetLastError() is also OK. */\n  return wres;\n\n  #endif\n}\n\n\nstatic WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)\n{\n  *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);\n  return HandleToWRes(*p);\n}\n\nWRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }\nWRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }\n\nWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }\nWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }\nWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }\nWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }\n\n\nWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)\n{\n  // negative ((LONG)maxCount) is not supported in WIN32::CreateSemaphore()\n  *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);\n  return HandleToWRes(*p);\n}\n\nWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount)\n{\n  // if (Semaphore_IsCreated(p))\n  {\n    WRes wres = Semaphore_Close(p);\n    if (wres != 0)\n      return wres;\n  }\n  return Semaphore_Create(p, initCount, maxCount);\n}\n\nstatic WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)\n  { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }\nWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)\n  { return Semaphore_Release(p, (LONG)num, NULL); }\nWRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }\n\nWRes CriticalSection_Init(CCriticalSection *p)\n{\n  /* InitializeCriticalSection() can raise exception:\n     Windows XP, 2003 : can raise a STATUS_NO_MEMORY exception\n     Windows Vista+   : no exceptions */\n  #ifdef _MSC_VER\n  #ifdef __clang__\n    #pragma GCC diagnostic ignored \"-Wlanguage-extension-token\"\n  #endif\n  __try\n  #endif\n  {\n    InitializeCriticalSection(p);\n    /* InitializeCriticalSectionAndSpinCount(p, 0); */\n  }\n  #ifdef _MSC_VER\n  __except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; }\n  #endif\n  return 0;\n}\n\n\n\n\n#else // _WIN32\n\n// ---------- POSIX ----------\n\n#if defined(__linux__) && !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)\n#ifndef Z7_AFFINITY_DISABLE\n// _GNU_SOURCE can be required for pthread_setaffinity_np() / CPU_ZERO / CPU_SET\n// clang < 3.6       : unknown warning group '-Wreserved-id-macro'\n// clang 3.6 - 12.01 : gives warning \"macro name is a reserved identifier\"\n// clang >= 13       : do not give warning\n#if !defined(_GNU_SOURCE)\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n// #define _GNU_SOURCE\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif // !defined(_GNU_SOURCE)\n#endif // Z7_AFFINITY_DISABLE\n#endif // __linux__\n\n#include \"Threads.h\"\n\n#include <errno.h>\n#include <stdlib.h>\n#include <string.h>\n#ifdef Z7_AFFINITY_SUPPORTED\n// #include <sched.h>\n#endif\n\n\n// #include <stdio.h>\n// #define PRF(p) p\n#define PRF(p)\n#define Print(s) PRF(printf(\"\\n%s\\n\", s);)\n\nWRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet)\n{\n  // new thread in Posix probably inherits affinity from parrent thread\n  Print(\"Thread_Create_With_CpuSet\")\n\n  pthread_attr_t attr;\n  int ret;\n  // int ret2;\n\n  p->_created = 0;\n\n  RINOK(pthread_attr_init(&attr))\n\n  ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);\n\n  if (!ret)\n  {\n    if (cpuSet)\n    {\n      // pthread_attr_setaffinity_np() is not supported for MUSL compile.\n      // so we check for __GLIBC__ here\n#if defined(Z7_AFFINITY_SUPPORTED) && defined( __GLIBC__)\n      /*\n      printf(\"\\n affinity :\");\n      unsigned i;\n      for (i = 0; i < sizeof(*cpuSet) && i < 8; i++)\n      {\n        Byte b = *((const Byte *)cpuSet + i);\n        char temp[32];\n        #define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))\n        temp[0] = GET_HEX_CHAR((b & 0xF));\n        temp[1] = GET_HEX_CHAR((b >> 4));\n        // temp[0] = GET_HEX_CHAR((b >> 4));  // big-endian\n        // temp[1] = GET_HEX_CHAR((b & 0xF));  // big-endian\n        temp[2] = 0;\n        printf(\"%s\", temp);\n      }\n      printf(\"\\n\");\n      */\n\n      // ret2 =\n      pthread_attr_setaffinity_np(&attr, sizeof(*cpuSet), cpuSet);\n      // if (ret2) ret = ret2;\n#endif\n    }\n    \n    ret = pthread_create(&p->_tid, &attr, func, param);\n    \n    if (!ret)\n    {\n      p->_created = 1;\n      /*\n      if (cpuSet)\n      {\n        // ret2 =\n        pthread_setaffinity_np(p->_tid, sizeof(*cpuSet), cpuSet);\n        // if (ret2) ret = ret2;\n      }\n      */\n    }\n  }\n  // ret2 =\n  pthread_attr_destroy(&attr);\n  // if (ret2 != 0) ret = ret2;\n  return ret;\n}\n\n\nWRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)\n{\n  return Thread_Create_With_CpuSet(p, func, param, NULL);\n}\n\n/*\nWRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinity)\n{\n  UNUSED_VAR(group)\n  return Thread_Create_With_Affinity(p, func, param, affinity);\n}\n*/\n\nWRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity)\n{\n  Print(\"Thread_Create_WithAffinity\")\n  CCpuSet cs;\n  unsigned i;\n  CpuSet_Zero(&cs);\n  for (i = 0; i < sizeof(affinity) * 8; i++)\n  {\n    if (affinity == 0)\n      break;\n    if (affinity & 1)\n    {\n      CpuSet_Set(&cs, i);\n    }\n    affinity >>= 1;\n  }\n  return Thread_Create_With_CpuSet(p, func, param, &cs);\n}\n\n\nWRes Thread_Close(CThread *p)\n{\n  // Print(\"Thread_Close\")\n  int ret;\n  if (!p->_created)\n    return 0;\n    \n  ret = pthread_detach(p->_tid);\n  p->_tid = 0;\n  p->_created = 0;\n  return ret;\n}\n\n\nWRes Thread_Wait_Close(CThread *p)\n{\n  // Print(\"Thread_Wait_Close\")\n  void *thread_return;\n  int ret;\n  if (!p->_created)\n    return EINVAL;\n\n  ret = pthread_join(p->_tid, &thread_return);\n  // probably we can't use that (_tid) after pthread_join(), so we close thread here\n  p->_created = 0;\n  p->_tid = 0;\n  return ret;\n}\n\n\n\nstatic WRes Event_Create(CEvent *p, int manualReset, int signaled)\n{\n  RINOK(pthread_mutex_init(&p->_mutex, NULL))\n  RINOK(pthread_cond_init(&p->_cond, NULL))\n  p->_manual_reset = manualReset;\n  p->_state = (signaled ? True : False);\n  p->_created = 1;\n  return 0;\n}\n\nWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled)\n  { return Event_Create(p, True, signaled); }\nWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p)\n  { return ManualResetEvent_Create(p, 0); }\nWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled)\n  { return Event_Create(p, False, signaled); }\nWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)\n  { return AutoResetEvent_Create(p, 0); }\n\n\n#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13)\n// freebsd:\n#pragma GCC diagnostic ignored \"-Wthread-safety-analysis\"\n#endif\n\nWRes Event_Set(CEvent *p)\n{\n  RINOK(pthread_mutex_lock(&p->_mutex))\n  p->_state = True;\n  {\n    const int res1 = pthread_cond_broadcast(&p->_cond);\n    const int res2 = pthread_mutex_unlock(&p->_mutex);\n    return (res2 ? res2 : res1);\n  }\n}\n\nWRes Event_Reset(CEvent *p)\n{\n  RINOK(pthread_mutex_lock(&p->_mutex))\n  p->_state = False;\n  return pthread_mutex_unlock(&p->_mutex);\n}\n \nWRes Event_Wait(CEvent *p)\n{\n  RINOK(pthread_mutex_lock(&p->_mutex))\n  while (p->_state == False)\n  {\n    // ETIMEDOUT\n    // ret =\n    pthread_cond_wait(&p->_cond, &p->_mutex);\n    // if (ret != 0) break;\n  }\n  if (p->_manual_reset == False)\n  {\n    p->_state = False;\n  }\n  return pthread_mutex_unlock(&p->_mutex);\n}\n\nWRes Event_Close(CEvent *p)\n{\n  if (!p->_created)\n    return 0;\n  p->_created = 0;\n  {\n    const int res1 = pthread_mutex_destroy(&p->_mutex);\n    const int res2 = pthread_cond_destroy(&p->_cond);\n    return (res1 ? res1 : res2);\n  }\n}\n\n\nWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)\n{\n  if (initCount > maxCount || maxCount < 1)\n    return EINVAL;\n  RINOK(pthread_mutex_init(&p->_mutex, NULL))\n  RINOK(pthread_cond_init(&p->_cond, NULL))\n  p->_count = initCount;\n  p->_maxCount = maxCount;\n  p->_created = 1;\n  return 0;\n}\n\n\nWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount)\n{\n  if (Semaphore_IsCreated(p))\n  {\n    /*\n    WRes wres = Semaphore_Close(p);\n    if (wres != 0)\n      return wres;\n    */\n    if (initCount > maxCount || maxCount < 1)\n      return EINVAL;\n    // return EINVAL; // for debug\n    p->_count = initCount;\n    p->_maxCount = maxCount;\n    return 0;\n  }\n  return Semaphore_Create(p, initCount, maxCount);\n}\n\n\nWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)\n{\n  UInt32 newCount;\n  int ret;\n\n  if (releaseCount < 1)\n    return EINVAL;\n\n  RINOK(pthread_mutex_lock(&p->_mutex))\n\n  newCount = p->_count + releaseCount;\n  if (newCount > p->_maxCount)\n    ret = ERROR_TOO_MANY_POSTS; // EINVAL;\n  else\n  {\n    p->_count = newCount;\n    ret = pthread_cond_broadcast(&p->_cond);\n  }\n  RINOK(pthread_mutex_unlock(&p->_mutex))\n  return ret;\n}\n\nWRes Semaphore_Wait(CSemaphore *p)\n{\n  RINOK(pthread_mutex_lock(&p->_mutex))\n  while (p->_count < 1)\n  {\n    pthread_cond_wait(&p->_cond, &p->_mutex);\n  }\n  p->_count--;\n  return pthread_mutex_unlock(&p->_mutex);\n}\n\nWRes Semaphore_Close(CSemaphore *p)\n{\n  if (!p->_created)\n    return 0;\n  p->_created = 0;\n  {\n    const int res1 = pthread_mutex_destroy(&p->_mutex);\n    const int res2 = pthread_cond_destroy(&p->_cond);\n    return (res1 ? res1 : res2);\n  }\n}\n\n\n\nWRes CriticalSection_Init(CCriticalSection *p)\n{\n  // Print(\"CriticalSection_Init\")\n  if (!p)\n    return EINTR;\n  return pthread_mutex_init(&p->_mutex, NULL);\n}\n\nvoid CriticalSection_Enter(CCriticalSection *p)\n{\n  // Print(\"CriticalSection_Enter\")\n  if (p)\n  {\n    // int ret =\n    pthread_mutex_lock(&p->_mutex);\n  }\n}\n\nvoid CriticalSection_Leave(CCriticalSection *p)\n{\n  // Print(\"CriticalSection_Leave\")\n  if (p)\n  {\n    // int ret =\n    pthread_mutex_unlock(&p->_mutex);\n  }\n}\n\nvoid CriticalSection_Delete(CCriticalSection *p)\n{\n  // Print(\"CriticalSection_Delete\")\n  if (p)\n  {\n    // int ret =\n    pthread_mutex_destroy(&p->_mutex);\n  }\n}\n\nLONG InterlockedIncrement(LONG volatile *addend)\n{\n  // Print(\"InterlockedIncrement\")\n  #ifdef USE_HACK_UNSAFE_ATOMIC\n    LONG val = *addend + 1;\n    *addend = val;\n    return val;\n  #else\n\n  #if defined(__clang__) && (__clang_major__ >= 8)\n    #pragma GCC diagnostic ignored \"-Watomic-implicit-seq-cst\"\n  #endif\n    return __sync_add_and_fetch(addend, 1);\n  #endif\n}\n\nLONG InterlockedDecrement(LONG volatile *addend)\n{\n  // Print(\"InterlockedDecrement\")\n  #ifdef USE_HACK_UNSAFE_ATOMIC\n    LONG val = *addend - 1;\n    *addend = val;\n    return val;\n  #else\n    return __sync_sub_and_fetch(addend, 1);\n  #endif\n}\n\n#endif // _WIN32\n\nWRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p)\n{\n  if (Event_IsCreated(p))\n    return Event_Reset(p);\n  return AutoResetEvent_CreateNotSignaled(p);\n}\n\nvoid ThreadNextGroup_Init(CThreadNextGroup *p, UInt32 numGroups, UInt32 startGroup)\n{\n  // printf(\"\\n====== ThreadNextGroup_Init numGroups = %x: startGroup=%x\\n\", numGroups, startGroup);\n  if (numGroups == 0)\n      numGroups = 1;\n  p->NumGroups = numGroups;\n  p->NextGroup = startGroup % numGroups;\n}\n\n\nUInt32 ThreadNextGroup_GetNext(CThreadNextGroup *p)\n{\n  const UInt32 next = p->NextGroup;\n  p->NextGroup = (next + 1) % p->NumGroups;\n  return next;\n}\n\n#undef PRF\n#undef Print\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Threads.h",
    "content": "﻿/* Threads.h -- multithreading library\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_THREADS_H\n#define ZIP7_INC_THREADS_H\n\n#ifdef _WIN32\n#include \"7zWindows.h\"\n\n#else\n\n#include \"Compiler.h\"\n\n// #define Z7_AFFINITY_DISABLE\n#if defined(__linux__)\n#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)\n#ifndef Z7_AFFINITY_DISABLE\n#define Z7_AFFINITY_SUPPORTED\n// #pragma message(\" ==== Z7_AFFINITY_SUPPORTED\")\n#if !defined(_GNU_SOURCE)\n// #pragma message(\" ==== _GNU_SOURCE set\")\n// we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL\nZ7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER\n#define _GNU_SOURCE\nZ7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER\n#endif\n#endif\n#endif\n#endif\n\n#include <pthread.h>\n\n#endif\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n#ifdef _WIN32\n\nWRes HandlePtr_Close(HANDLE *h);\nWRes Handle_WaitObject(HANDLE h);\n\ntypedef HANDLE CThread;\n\n#define Thread_CONSTRUCT(p) { *(p) = NULL; }\n#define Thread_WasCreated(p) (*(p) != NULL)\n#define Thread_Close(p) HandlePtr_Close(p)\n// #define Thread_Wait(p) Handle_WaitObject(*(p))\n\n#ifdef UNDER_CE\n  // if (USE_THREADS_CreateThread is      defined), we use _beginthreadex()\n  // if (USE_THREADS_CreateThread is not definned), we use CreateThread()\n  #define USE_THREADS_CreateThread\n#endif\n\ntypedef\n    #ifdef USE_THREADS_CreateThread\n      DWORD\n    #else\n      unsigned\n    #endif\n    THREAD_FUNC_RET_TYPE;\n\n#define THREAD_FUNC_RET_ZERO  0\n\ntypedef DWORD_PTR CAffinityMask;\ntypedef DWORD_PTR CCpuSet;\n\n#define CpuSet_Zero(p)        *(p) = (0)\n#define CpuSet_Set(p, cpu)    *(p) |= ((DWORD_PTR)1 << (cpu))\n\n#else //  _WIN32\n\ntypedef struct\n{\n  pthread_t _tid;\n  int _created;\n} CThread;\n\n#define Thread_CONSTRUCT(p)   { (p)->_tid = 0;  (p)->_created = 0; }\n#define Thread_WasCreated(p)  ((p)->_created != 0)\nWRes Thread_Close(CThread *p);\n// #define Thread_Wait Thread_Wait_Close\n\ntypedef void * THREAD_FUNC_RET_TYPE;\n#define THREAD_FUNC_RET_ZERO  NULL\n\n\ntypedef UInt64 CAffinityMask;\n\n#ifdef Z7_AFFINITY_SUPPORTED\n\ntypedef cpu_set_t CCpuSet;\n#define CpuSet_Zero(p)        CPU_ZERO(p)\n#define CpuSet_Set(p, cpu)    CPU_SET(cpu, p)\n#define CpuSet_IsSet(p, cpu)  CPU_ISSET(cpu, p)\n\n#else\n\ntypedef UInt64 CCpuSet;\n#define CpuSet_Zero(p)        *(p) = (0)\n#define CpuSet_Set(p, cpu)    *(p) |= ((UInt64)1 << (cpu))\n#define CpuSet_IsSet(p, cpu)  ((*(p) & ((UInt64)1 << (cpu))) != 0)\n\n#endif\n\n\n#endif //  _WIN32\n\n\n#define THREAD_FUNC_CALL_TYPE Z7_STDCALL\n\n#if defined(_WIN32) && defined(__GNUC__)\n/* GCC compiler for x86 32-bit uses the rule:\n   the stack is 16-byte aligned before CALL instruction for function calling.\n   But only root function main() contains instructions that\n   set 16-byte alignment for stack pointer. And another functions\n   just keep alignment, if it was set in some parent function.\n   \n   The problem:\n    if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(),\n       the root function of thread doesn't set 16-byte alignment.\n       And stack frames in all child functions also will be unaligned in that case.\n   \n   Here we set (force_align_arg_pointer) attribute for root function of new thread.\n   Do we need (force_align_arg_pointer) also for another systems?  */\n  \n  #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer))\n  // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions\n#else\n  #define THREAD_FUNC_ATTRIB_ALIGN_ARG\n#endif\n\n#define THREAD_FUNC_DECL  THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE\n\ntypedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);\nWRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);\nWRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity);\nWRes Thread_Wait_Close(CThread *p);\n\n#ifdef _WIN32\nWRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask);\n#define Thread_Create_With_CpuSet(p, func, param, cs) \\\n  Thread_Create_With_Affinity(p, func, param, *cs)\n#else\nWRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);\n#endif\n\ntypedef struct\n{\n  unsigned NumGroups;\n  unsigned NextGroup;\n} CThreadNextGroup;\n\nvoid ThreadNextGroup_Init(CThreadNextGroup *p, unsigned numGroups, unsigned startGroup);\nunsigned ThreadNextGroup_GetNext(CThreadNextGroup *p);\n\n\n#ifdef _WIN32\n\ntypedef HANDLE CEvent;\ntypedef CEvent CAutoResetEvent;\ntypedef CEvent CManualResetEvent;\n#define Event_Construct(p) *(p) = NULL\n#define Event_IsCreated(p) (*(p) != NULL)\n#define Event_Close(p) HandlePtr_Close(p)\n#define Event_Wait(p) Handle_WaitObject(*(p))\nWRes Event_Set(CEvent *p);\nWRes Event_Reset(CEvent *p);\nWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);\nWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);\nWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);\nWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);\n\ntypedef HANDLE CSemaphore;\n#define Semaphore_Construct(p) *(p) = NULL\n#define Semaphore_IsCreated(p) (*(p) != NULL)\n#define Semaphore_Close(p) HandlePtr_Close(p)\n#define Semaphore_Wait(p) Handle_WaitObject(*(p))\nWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);\nWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);\nWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);\nWRes Semaphore_Release1(CSemaphore *p);\n\ntypedef CRITICAL_SECTION CCriticalSection;\nWRes CriticalSection_Init(CCriticalSection *p);\n#define CriticalSection_Delete(p) DeleteCriticalSection(p)\n#define CriticalSection_Enter(p) EnterCriticalSection(p)\n#define CriticalSection_Leave(p) LeaveCriticalSection(p)\n\n\n#else // _WIN32\n\ntypedef struct\n{\n  int _created;\n  int _manual_reset;\n  int _state;\n  pthread_mutex_t _mutex;\n  pthread_cond_t _cond;\n} CEvent;\n\ntypedef CEvent CAutoResetEvent;\ntypedef CEvent CManualResetEvent;\n\n#define Event_Construct(p) (p)->_created = 0\n#define Event_IsCreated(p) ((p)->_created)\n\nWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);\nWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);\nWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);\nWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);\n\nWRes Event_Set(CEvent *p);\nWRes Event_Reset(CEvent *p);\nWRes Event_Wait(CEvent *p);\nWRes Event_Close(CEvent *p);\n\n\ntypedef struct\n{\n  int _created;\n  UInt32 _count;\n  UInt32 _maxCount;\n  pthread_mutex_t _mutex;\n  pthread_cond_t _cond;\n} CSemaphore;\n\n#define Semaphore_Construct(p) (p)->_created = 0\n#define Semaphore_IsCreated(p) ((p)->_created)\n\nWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);\nWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);\nWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);\n#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)\nWRes Semaphore_Wait(CSemaphore *p);\nWRes Semaphore_Close(CSemaphore *p);\n\n\ntypedef struct\n{\n  pthread_mutex_t _mutex;\n} CCriticalSection;\n\nWRes CriticalSection_Init(CCriticalSection *p);\nvoid CriticalSection_Delete(CCriticalSection *cs);\nvoid CriticalSection_Enter(CCriticalSection *cs);\nvoid CriticalSection_Leave(CCriticalSection *cs);\n\nLONG InterlockedIncrement(LONG volatile *addend);\nLONG InterlockedDecrement(LONG volatile *addend);\n\n#endif  // _WIN32\n\nWRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Xz.c",
    "content": "﻿/* Xz.c - Xz\n2024-03-01 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"7zCrc.h\"\n#include \"CpuArch.h\"\n#include \"Xz.h\"\n#include \"XzCrc64.h\"\n\nconst Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };\n/* const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; */\n\nunsigned Xz_WriteVarInt(Byte *buf, UInt64 v)\n{\n  unsigned i = 0;\n  do\n  {\n    buf[i++] = (Byte)((v & 0x7F) | 0x80);\n    v >>= 7;\n  }\n  while (v != 0);\n  buf[(size_t)i - 1] &= 0x7F;\n  return i;\n}\n\nvoid Xz_Construct(CXzStream *p)\n{\n  p->numBlocks = 0;\n  p->blocks = NULL;\n  p->flags = 0;\n}\n\nvoid Xz_Free(CXzStream *p, ISzAllocPtr alloc)\n{\n  ISzAlloc_Free(alloc, p->blocks);\n  p->numBlocks = 0;\n  p->blocks = NULL;\n}\n\nunsigned XzFlags_GetCheckSize(CXzStreamFlags f)\n{\n  unsigned t = XzFlags_GetCheckType(f);\n  return (t == 0) ? 0 : ((unsigned)4 << ((t - 1) / 3));\n}\n\nvoid XzCheck_Init(CXzCheck *p, unsigned mode)\n{\n  p->mode = mode;\n  switch (mode)\n  {\n    case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;\n    case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;\n    case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;\n    default: break;\n  }\n}\n\nvoid XzCheck_Update(CXzCheck *p, const void *data, size_t size)\n{\n  switch (p->mode)\n  {\n    case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;\n    case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;\n    case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;\n    default: break;\n  }\n}\n\nint XzCheck_Final(CXzCheck *p, Byte *digest)\n{\n  switch (p->mode)\n  {\n    case XZ_CHECK_CRC32:\n      SetUi32(digest, CRC_GET_DIGEST(p->crc))\n      break;\n    case XZ_CHECK_CRC64:\n    {\n      int i;\n      UInt64 v = CRC64_GET_DIGEST(p->crc64);\n      for (i = 0; i < 8; i++, v >>= 8)\n        digest[i] = (Byte)(v & 0xFF);\n      break;\n    }\n    case XZ_CHECK_SHA256:\n      Sha256_Final(&p->sha, digest);\n      break;\n    default:\n      return 0;\n  }\n  return 1;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/Xz.h",
    "content": "﻿/* Xz.h - Xz interface\nIgor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_XZ_H\n#define ZIP7_INC_XZ_H\n\n#include \"Sha256.h\"\n#include \"Delta.h\"\n\nEXTERN_C_BEGIN\n\n#define XZ_ID_Subblock 1\n#define XZ_ID_Delta 3\n#define XZ_ID_X86   4\n#define XZ_ID_PPC   5\n#define XZ_ID_IA64  6\n#define XZ_ID_ARM   7\n#define XZ_ID_ARMT  8\n#define XZ_ID_SPARC 9\n#define XZ_ID_ARM64 0xa\n#define XZ_ID_RISCV 0xb\n#define XZ_ID_LZMA2 0x21\n\nunsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);\nunsigned Xz_WriteVarInt(Byte *buf, UInt64 v);\n\n/* ---------- xz block ---------- */\n\n#define XZ_BLOCK_HEADER_SIZE_MAX 1024\n\n#define XZ_NUM_FILTERS_MAX 4\n#define XZ_BF_NUM_FILTERS_MASK 3\n#define XZ_BF_PACK_SIZE (1 << 6)\n#define XZ_BF_UNPACK_SIZE (1 << 7)\n\n#define XZ_FILTER_PROPS_SIZE_MAX 20\n\ntypedef struct\n{\n  UInt64 id;\n  UInt32 propsSize;\n  Byte props[XZ_FILTER_PROPS_SIZE_MAX];\n} CXzFilter;\n\ntypedef struct\n{\n  UInt64 packSize;\n  UInt64 unpackSize;\n  Byte flags;\n  CXzFilter filters[XZ_NUM_FILTERS_MAX];\n} CXzBlock;\n\n#define XzBlock_GetNumFilters(p) (((unsigned)(p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)\n#define XzBlock_HasPackSize(p)   (((p)->flags & XZ_BF_PACK_SIZE) != 0)\n#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)\n#define XzBlock_HasUnsupportedFlags(p) (((p)->flags & ~(XZ_BF_NUM_FILTERS_MASK | XZ_BF_PACK_SIZE | XZ_BF_UNPACK_SIZE)) != 0)\n\nSRes XzBlock_Parse(CXzBlock *p, const Byte *header);\nSRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes);\n\n/* ---------- xz stream ---------- */\n\n#define XZ_SIG_SIZE 6\n#define XZ_FOOTER_SIG_SIZE 2\n\nextern const Byte XZ_SIG[XZ_SIG_SIZE];\n\n/*\nextern const Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];\n*/\n\n#define XZ_FOOTER_SIG_0 'Y'\n#define XZ_FOOTER_SIG_1 'Z'\n\n#define XZ_STREAM_FLAGS_SIZE 2\n#define XZ_STREAM_CRC_SIZE 4\n\n#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)\n#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)\n\n#define XZ_CHECK_MASK 0xF\n#define XZ_CHECK_NO 0\n#define XZ_CHECK_CRC32 1\n#define XZ_CHECK_CRC64 4\n#define XZ_CHECK_SHA256 10\n\ntypedef struct\n{\n  unsigned mode;\n  UInt32 crc;\n  UInt64 crc64;\n  CSha256 sha;\n} CXzCheck;\n\nvoid XzCheck_Init(CXzCheck *p, unsigned mode);\nvoid XzCheck_Update(CXzCheck *p, const void *data, size_t size);\nint XzCheck_Final(CXzCheck *p, Byte *digest);\n\ntypedef UInt16 CXzStreamFlags;\n\n#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)\n#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)\n#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)\nunsigned XzFlags_GetCheckSize(CXzStreamFlags f);\n\nSRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);\nSRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream);\n\ntypedef struct\n{\n  UInt64 unpackSize;\n  UInt64 totalSize;\n} CXzBlockSizes;\n\ntypedef struct\n{\n  CXzStreamFlags flags;\n  // Byte _pad[6];\n  size_t numBlocks;\n  CXzBlockSizes *blocks;\n  UInt64 startOffset;\n} CXzStream;\n\n#define Xz_CONSTRUCT(p) { (p)->numBlocks = 0;  (p)->blocks = NULL;  (p)->flags = 0; }\nvoid Xz_Construct(CXzStream *p);\nvoid Xz_Free(CXzStream *p, ISzAllocPtr alloc);\n\n#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)\n\nUInt64 Xz_GetUnpackSize(const CXzStream *p);\nUInt64 Xz_GetPackSize(const CXzStream *p);\n\ntypedef struct\n{\n  size_t num;\n  size_t numAllocated;\n  CXzStream *streams;\n} CXzs;\n\n#define Xzs_CONSTRUCT(p) { (p)->num = 0;  (p)->numAllocated = 0;  (p)->streams = NULL; }\nvoid Xzs_Construct(CXzs *p);\nvoid Xzs_Free(CXzs *p, ISzAllocPtr alloc);\n/*\nXzs_ReadBackward() must be called for empty CXzs object.\nXzs_ReadBackward() can return non empty object with (p->num != 0) even in case of error.\n*/\nSRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr inStream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc);\n\nUInt64 Xzs_GetNumBlocks(const CXzs *p);\nUInt64 Xzs_GetUnpackSize(const CXzs *p);\n\n\n// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder\n\ntypedef enum\n{\n  CODER_STATUS_NOT_SPECIFIED,               /* use main error code instead */\n  CODER_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */\n  CODER_STATUS_NOT_FINISHED,                /* stream was not finished */\n  CODER_STATUS_NEEDS_MORE_INPUT             /* you must provide more input bytes */\n} ECoderStatus;\n\n\n// ECoderFinishMode values are identical to ELzmaFinishMode\n\ntypedef enum\n{\n  CODER_FINISH_ANY,   /* finish at any point */\n  CODER_FINISH_END    /* block must be finished at the end */\n} ECoderFinishMode;\n\n\ntypedef struct\n{\n  void *p; // state object;\n  void (*Free)(void *p, ISzAllocPtr alloc);\n  SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAllocPtr alloc);\n  void (*Init)(void *p);\n  SRes (*Code2)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n      int srcWasFinished, ECoderFinishMode finishMode,\n      // int *wasFinished,\n      ECoderStatus *status);\n  SizeT (*Filter)(void *p, Byte *data, SizeT size);\n} IStateCoder;\n\n\ntypedef struct\n{\n  UInt32 methodId;\n  UInt32 delta;\n  UInt32 ip;\n  UInt32 X86_State;\n  Byte delta_State[DELTA_STATE_SIZE];\n} CXzBcFilterStateBase;\n\ntypedef SizeT (*Xz_Func_BcFilterStateBase_Filter)(CXzBcFilterStateBase *p, Byte *data, SizeT size);\n\nSRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,\n    Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc);\n\n\n#define MIXCODER_NUM_FILTERS_MAX 4\n\ntypedef struct\n{\n  ISzAllocPtr alloc;\n  Byte *buf;\n  unsigned numCoders;\n\n  Byte *outBuf;\n  size_t outBufSize;\n  size_t outWritten; // is equal to lzmaDecoder.dicPos (in outBuf mode)\n  BoolInt wasFinished;\n  SRes res;\n  ECoderStatus status;\n  // BoolInt SingleBufMode;\n  \n  int finished[MIXCODER_NUM_FILTERS_MAX - 1];\n  size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];\n  size_t size[MIXCODER_NUM_FILTERS_MAX - 1];\n  UInt64 ids[MIXCODER_NUM_FILTERS_MAX];\n  SRes results[MIXCODER_NUM_FILTERS_MAX];\n  IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];\n} CMixCoder;\n\n\ntypedef enum\n{\n  XZ_STATE_STREAM_HEADER,\n  XZ_STATE_STREAM_INDEX,\n  XZ_STATE_STREAM_INDEX_CRC,\n  XZ_STATE_STREAM_FOOTER,\n  XZ_STATE_STREAM_PADDING,\n  XZ_STATE_BLOCK_HEADER,\n  XZ_STATE_BLOCK,\n  XZ_STATE_BLOCK_FOOTER\n} EXzState;\n\n\ntypedef struct\n{\n  EXzState state;\n  unsigned pos;\n  unsigned alignPos;\n  unsigned indexPreSize;\n\n  CXzStreamFlags streamFlags;\n  \n  unsigned blockHeaderSize;\n  UInt64 packSize;\n  UInt64 unpackSize;\n\n  UInt64 numBlocks; // number of finished blocks in current stream\n  UInt64 indexSize;\n  UInt64 indexPos;\n  UInt64 padSize;\n\n  UInt64 numStartedStreams;\n  UInt64 numFinishedStreams;\n  UInt64 numTotalBlocks;\n\n  UInt32 crc;\n  CMixCoder decoder;\n  CXzBlock block;\n  CXzCheck check;\n  CSha256 sha;\n\n  BoolInt parseMode;\n  BoolInt headerParsedOk;\n  BoolInt decodeToStreamSignature;\n  unsigned decodeOnlyOneBlock;\n\n  Byte *outBuf;\n  size_t outBufSize;\n  size_t outDataWritten; // the size of data in (outBuf) that were fully unpacked\n\n  UInt32 shaDigest32[SHA256_DIGEST_SIZE / 4];\n  Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; // it must be aligned for 4-bytes\n} CXzUnpacker;\n\n/* alloc : aligned for cache line allocation is better */\nvoid XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc);\nvoid XzUnpacker_Init(CXzUnpacker *p);\nvoid XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize);\nvoid XzUnpacker_Free(CXzUnpacker *p);\n\n/*\n  XzUnpacker\n  The sequence for decoding functions:\n  {\n    XzUnpacker_Construct()\n    [Decoding_Calls]\n    XzUnpacker_Free()\n  }\n\n  [Decoding_Calls]\n\n  There are 3 types of interfaces for [Decoding_Calls] calls:\n\n  Interface-1 : Partial output buffers:\n    {\n      XzUnpacker_Init()\n      for()\n      {\n        XzUnpacker_Code();\n      }\n      XzUnpacker_IsStreamWasFinished()\n    }\n    \n  Interface-2 : Direct output buffer:\n    Use it, if you know exact size of decoded data, and you need\n    whole xz unpacked data in one output buffer.\n    xz unpacker doesn't allocate additional buffer for lzma2 dictionary in that mode.\n    {\n      XzUnpacker_Init()\n      XzUnpacker_SetOutBufMode(); // to set output buffer and size\n      for()\n      {\n        XzUnpacker_Code(); // (dest = NULL) in XzUnpacker_Code()\n      }\n      XzUnpacker_IsStreamWasFinished()\n    }\n\n  Interface-3 : Direct output buffer : One call full decoding\n    It unpacks whole input buffer to output buffer in one call.\n    It uses Interface-2 internally.\n    {\n      XzUnpacker_CodeFull()\n      XzUnpacker_IsStreamWasFinished()\n    }\n*/\n\n/*\nfinishMode:\n  It has meaning only if the decoding reaches output limit (*destLen).\n  CODER_FINISH_ANY - use smallest number of input bytes\n  CODER_FINISH_END - read EndOfStream marker after decoding\n\nReturns:\n  SZ_OK\n    status:\n      CODER_STATUS_NOT_FINISHED,\n      CODER_STATUS_NEEDS_MORE_INPUT - the decoder can return it in two cases:\n         1) it needs more input data to finish current xz stream\n         2) xz stream was finished successfully. But the decoder supports multiple\n            concatented xz streams. So it expects more input data for new xz streams.\n         Call XzUnpacker_IsStreamWasFinished() to check that latest xz stream was finished successfully.\n\n  SZ_ERROR_MEM  - Memory allocation error\n  SZ_ERROR_DATA - Data error\n  SZ_ERROR_UNSUPPORTED - Unsupported method or method properties\n  SZ_ERROR_CRC  - CRC error\n  // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).\n\n  SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons:\n     - xz Stream Signature failure\n     - CRC32 of xz Stream Header is failed\n     - The size of Stream padding is not multiple of four bytes.\n    It's possible to get that error, if xz stream was finished and the stream\n    contains some another data. In that case you can call XzUnpacker_GetExtraSize()\n    function to get real size of xz stream.\n*/\n\n\nSRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen, int srcFinished,\n    ECoderFinishMode finishMode, ECoderStatus *status);\n\nSRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen,\n    ECoderFinishMode finishMode, ECoderStatus *status);\n\n/*\nIf you decode full xz stream(s), then you can call XzUnpacker_IsStreamWasFinished()\nafter successful XzUnpacker_CodeFull() or after last call of XzUnpacker_Code().\n*/\n\nBoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p);\n\n/*\nXzUnpacker_GetExtraSize() returns then number of unconfirmed bytes,\n if it's in (XZ_STATE_STREAM_HEADER) state or in (XZ_STATE_STREAM_PADDING) state.\nThese bytes can be some data after xz archive, or\nit can be start of new xz stream.\n \nCall XzUnpacker_GetExtraSize() after XzUnpacker_Code() function to detect real size of\nxz stream in two cases, if XzUnpacker_Code() returns:\n  res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT\n  res == SZ_ERROR_NO_ARCHIVE\n*/\n\nUInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p);\n\n\n/*\n  for random block decoding:\n    XzUnpacker_Init();\n    set CXzUnpacker::streamFlags\n    XzUnpacker_PrepareToRandomBlockDecoding()\n    loop\n    {\n      XzUnpacker_Code()\n      XzUnpacker_IsBlockFinished()\n    }\n*/\n\nvoid XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p);\nBoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p);\n\n#define XzUnpacker_GetPackSizeForIndex(p) ((p)->packSize + (p)->blockHeaderSize + XzFlags_GetCheckSize((p)->streamFlags))\n\n\n\n\n\n\n/* ---- Single-Thread and Multi-Thread xz Decoding with Input/Output Streams ---- */\n\n/*\n  if (CXzDecMtProps::numThreads > 1), the decoder can try to use\n  Multi-Threading. The decoder analyses xz block header, and if\n  there are pack size and unpack size values stored in xz block header,\n  the decoder reads compressed data of block to internal buffers,\n  and then it can start parallel decoding, if there are another blocks.\n  The decoder can switch back to Single-Thread decoding after some conditions.\n\n  The sequence of calls for xz decoding with in/out Streams:\n  {\n    XzDecMt_Create()\n    XzDecMtProps_Init(XzDecMtProps) to set default values of properties\n    // then you can change some XzDecMtProps parameters with required values\n    // here you can set the number of threads and (memUseMax) - the maximum\n    Memory usage for multithreading decoding.\n    for()\n    {\n      XzDecMt_Decode() // one call per one file\n    }\n    XzDecMt_Destroy()\n  }\n*/\n\n\ntypedef struct\n{\n  size_t inBufSize_ST;    // size of input buffer for Single-Thread decoding\n  size_t outStep_ST;      // size of output buffer for Single-Thread decoding\n  BoolInt ignoreErrors;   // if set to 1, the decoder can ignore some errors and it skips broken parts of data.\n  \n  #ifndef Z7_ST\n  unsigned numThreads;    // the number of threads for Multi-Thread decoding. if (umThreads == 1) it will use Single-thread decoding\n  size_t inBufSize_MT;    // size of small input data buffers for Multi-Thread decoding. Big number of such small buffers can be created\n  size_t memUseMax;       // the limit of total memory usage for Multi-Thread decoding.\n                          // it's recommended to set (memUseMax) manually to value that is smaller of total size of RAM in computer.\n  #endif\n} CXzDecMtProps;\n\nvoid XzDecMtProps_Init(CXzDecMtProps *p);\n\ntypedef struct CXzDecMt CXzDecMt;\ntypedef CXzDecMt * CXzDecMtHandle;\n// Z7_DECLARE_HANDLE(CXzDecMtHandle)\n\n/*\n  alloc    : XzDecMt uses CAlignOffsetAlloc internally for addresses allocated by (alloc).\n  allocMid : for big allocations, aligned allocation is better\n*/\n\nCXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid);\nvoid XzDecMt_Destroy(CXzDecMtHandle p);\n\n\ntypedef struct\n{\n  Byte UnpackSize_Defined;\n  Byte NumStreams_Defined;\n  Byte NumBlocks_Defined;\n\n  Byte DataAfterEnd;      // there are some additional data after good xz streams, and that data is not new xz stream.\n  Byte DecodingTruncated; // Decoding was Truncated, we need only partial output data\n\n  UInt64 InSize;          // pack size processed. That value doesn't include the data after\n                          // end of xz stream, if that data was not correct\n  UInt64 OutSize;\n\n  UInt64 NumStreams;\n  UInt64 NumBlocks;\n\n  SRes DecodeRes;         // the error code of xz streams data decoding\n  SRes ReadRes;           // error code from ISeqInStream:Read()\n  SRes ProgressRes;       // error code from ICompressProgress:Progress()\n\n  SRes CombinedRes;       // Combined result error code that shows main rusult\n                          // = S_OK, if there is no error.\n                          // but check also (DataAfterEnd) that can show additional minor errors.\n \n  SRes CombinedRes_Type;  // = SZ_ERROR_READ,     if error from ISeqInStream\n                          // = SZ_ERROR_PROGRESS, if error from ICompressProgress\n                          // = SZ_ERROR_WRITE,    if error from ISeqOutStream\n                          // = SZ_ERROR_* codes for decoding\n} CXzStatInfo;\n\nvoid XzStatInfo_Clear(CXzStatInfo *p);\n\n/*\n\nXzDecMt_Decode()\nSRes: it's combined decoding result. It also is equal to stat->CombinedRes.\n\n  SZ_OK               - no error\n                        check also output value in (stat->DataAfterEnd)\n                        that can show additional possible error\n\n  SZ_ERROR_MEM        - Memory allocation error\n  SZ_ERROR_NO_ARCHIVE - is not xz archive\n  SZ_ERROR_ARCHIVE    - Headers error\n  SZ_ERROR_DATA       - Data Error\n  SZ_ERROR_UNSUPPORTED - Unsupported method or method properties\n  SZ_ERROR_CRC        - CRC Error\n  SZ_ERROR_INPUT_EOF  - it needs more input data\n  SZ_ERROR_WRITE      - ISeqOutStream error\n  (SZ_ERROR_READ)     - ISeqInStream errors\n  (SZ_ERROR_PROGRESS) - ICompressProgress errors\n  // SZ_ERROR_THREAD     - error in multi-threading functions\n  MY_SRes_HRESULT_FROM_WRes(WRes_error) - error in multi-threading function\n*/\n\nSRes XzDecMt_Decode(CXzDecMtHandle p,\n    const CXzDecMtProps *props,\n    const UInt64 *outDataSize, // NULL means undefined\n    int finishMode,            // 0 - partial unpacking is allowed, 1 - xz stream(s) must be finished\n    ISeqOutStreamPtr outStream,\n    // Byte *outBuf, size_t *outBufSize,\n    ISeqInStreamPtr inStream,\n    // const Byte *inData, size_t inDataSize,\n    CXzStatInfo *stat,         // out: decoding results and statistics\n    int *isMT,                 // out: 0 means that ST (Single-Thread) version was used\n                               //      1 means that MT (Multi-Thread) version was used\n    ICompressProgressPtr progress);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/XzCrc64.c",
    "content": "﻿/* XzCrc64.c -- CRC64 calculation\n2023-12-08 : Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"XzCrc64.h\"\n#include \"CpuArch.h\"\n\n#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42)\n\n// for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu\n// #define Z7_CRC64_DEBUG_BE\n#ifdef Z7_CRC64_DEBUG_BE\n#undef MY_CPU_LE\n#define MY_CPU_BE\n#endif\n\n#ifdef Z7_CRC64_NUM_TABLES\n  #define Z7_CRC64_NUM_TABLES_USE  Z7_CRC64_NUM_TABLES\n#else\n  #define Z7_CRC64_NUM_TABLES_USE  12\n#endif\n\n#if Z7_CRC64_NUM_TABLES_USE < 1\n  #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES\n#endif\n\n\n#if Z7_CRC64_NUM_TABLES_USE != 1\n\n#ifndef MY_CPU_BE\n  #define FUNC_NAME_LE_2(s)   XzCrc64UpdateT ## s\n  #define FUNC_NAME_LE_1(s)   FUNC_NAME_LE_2(s)\n  #define FUNC_NAME_LE        FUNC_NAME_LE_1(Z7_CRC64_NUM_TABLES_USE)\n  UInt64 Z7_FASTCALL FUNC_NAME_LE (UInt64 v, const void *data, size_t size, const UInt64 *table);\n#endif\n#ifndef MY_CPU_LE\n  #define FUNC_NAME_BE_2(s)   XzCrc64UpdateBeT ## s\n  #define FUNC_NAME_BE_1(s)   FUNC_NAME_BE_2(s)\n  #define FUNC_NAME_BE        FUNC_NAME_BE_1(Z7_CRC64_NUM_TABLES_USE)\n  UInt64 Z7_FASTCALL FUNC_NAME_BE (UInt64 v, const void *data, size_t size, const UInt64 *table);\n#endif\n\n#if defined(MY_CPU_LE)\n  #define FUNC_REF  FUNC_NAME_LE\n#elif defined(MY_CPU_BE)\n  #define FUNC_REF  FUNC_NAME_BE\n#else\n  #define FUNC_REF  g_Crc64Update\n  static UInt64 (Z7_FASTCALL *FUNC_REF)(UInt64 v, const void *data, size_t size, const UInt64 *table);\n#endif\n\n#endif\n\n\nMY_ALIGN(64)\nstatic UInt64 g_Crc64Table[256 * Z7_CRC64_NUM_TABLES_USE];\n\n\nUInt64 Z7_FASTCALL Crc64Update(UInt64 v, const void *data, size_t size)\n{\n#if Z7_CRC64_NUM_TABLES_USE == 1\n  #define CRC64_UPDATE_BYTE_2(crc, b)  (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n  const UInt64 *table = g_Crc64Table;\n  const Byte *p = (const Byte *)data;\n  const Byte *lim = p + size;\n  for (; p != lim; p++)\n    v = CRC64_UPDATE_BYTE_2(v, *p);\n  return v;\n  #undef CRC64_UPDATE_BYTE_2\n#else\n  return FUNC_REF (v, data, size, g_Crc64Table);\n#endif\n}\n\n\nZ7_NO_INLINE\nvoid Z7_FASTCALL Crc64GenerateTable(void)\n{\n  unsigned i;\n  for (i = 0; i < 256; i++)\n  {\n    UInt64 r = i;\n    unsigned j;\n    for (j = 0; j < 8; j++)\n      r = (r >> 1) ^ (kCrc64Poly & ((UInt64)0 - (r & 1)));\n    g_Crc64Table[i] = r;\n  }\n\n#if Z7_CRC64_NUM_TABLES_USE != 1\n#if 1 || 1 && defined(MY_CPU_X86) // low register count\n  for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i++)\n  {\n    const UInt64 r0 = g_Crc64Table[(size_t)i];\n    g_Crc64Table[(size_t)i + 256] = g_Crc64Table[(Byte)r0] ^ (r0 >> 8);\n  }\n#else\n  for (i = 0; i < 256 * (Z7_CRC64_NUM_TABLES_USE - 1); i += 2)\n  {\n    UInt64 r0 = g_Crc64Table[(size_t)(i)    ];\n    UInt64 r1 = g_Crc64Table[(size_t)(i) + 1];\n    r0 = g_Crc64Table[(Byte)r0] ^ (r0 >> 8);\n    r1 = g_Crc64Table[(Byte)r1] ^ (r1 >> 8);\n    g_Crc64Table[(size_t)i + 256    ] = r0;\n    g_Crc64Table[(size_t)i + 256 + 1] = r1;\n  }\n#endif\n\n#ifndef MY_CPU_LE\n  {\n#ifndef MY_CPU_BE\n    UInt32 k = 1;\n    if (*(const Byte *)&k == 1)\n      FUNC_REF = FUNC_NAME_LE;\n    else\n#endif\n    {\n#ifndef MY_CPU_BE\n      FUNC_REF = FUNC_NAME_BE;\n#endif\n      for (i = 0; i < 256 * Z7_CRC64_NUM_TABLES_USE; i++)\n      {\n        const UInt64 x = g_Crc64Table[i];\n        g_Crc64Table[i] = Z7_BSWAP64(x);\n      }\n    }\n  }\n#endif // ndef MY_CPU_LE\n#endif // Z7_CRC64_NUM_TABLES_USE != 1\n}\n\n#undef kCrc64Poly\n#undef Z7_CRC64_NUM_TABLES_USE\n#undef FUNC_REF\n#undef FUNC_NAME_LE_2\n#undef FUNC_NAME_LE_1\n#undef FUNC_NAME_LE\n#undef FUNC_NAME_BE_2\n#undef FUNC_NAME_BE_1\n#undef FUNC_NAME_BE\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/XzCrc64.h",
    "content": "﻿/* XzCrc64.h -- CRC64 calculation\n2023-12-08 : Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_XZ_CRC64_H\n#define ZIP7_INC_XZ_CRC64_H\n\n#include <stddef.h>\n\n#include \"7zTypes.h\"\n\nEXTERN_C_BEGIN\n\n// extern UInt64 g_Crc64Table[];\n\nvoid Z7_FASTCALL Crc64GenerateTable(void);\n\n#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF)\n#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL)\n// #define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n\nUInt64 Z7_FASTCALL Crc64Update(UInt64 crc, const void *data, size_t size);\n// UInt64 Z7_FASTCALL Crc64Calc(const void *data, size_t size);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/XzCrc64Opt.c",
    "content": "﻿/* XzCrc64Opt.c -- CRC64 calculation (optimized functions)\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include \"CpuArch.h\"\n\n#if !defined(Z7_CRC64_NUM_TABLES) || Z7_CRC64_NUM_TABLES > 1\n\n// for debug only : define Z7_CRC64_DEBUG_BE to test big-endian code in little-endian cpu\n// #define Z7_CRC64_DEBUG_BE\n#ifdef Z7_CRC64_DEBUG_BE\n#undef MY_CPU_LE\n#define MY_CPU_BE\n#endif\n\n#if defined(MY_CPU_64BIT)\n#define Z7_CRC64_USE_64BIT\n#endif\n\n// the value Z7_CRC64_NUM_TABLES_USE must be defined to same value as in XzCrc64.c\n#ifdef Z7_CRC64_NUM_TABLES\n#define Z7_CRC64_NUM_TABLES_USE  Z7_CRC64_NUM_TABLES\n#else\n#define Z7_CRC64_NUM_TABLES_USE  12\n#endif\n\n#if Z7_CRC64_NUM_TABLES_USE % 4 || \\\n    Z7_CRC64_NUM_TABLES_USE < 4 || \\\n    Z7_CRC64_NUM_TABLES_USE > 4 * 4\n  #error Stop_Compiling_Bad_CRC64_NUM_TABLES\n#endif\n\n\n#ifndef MY_CPU_BE\n\n#define CRC64_UPDATE_BYTE_2(crc, b)  (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n\n#if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0)\n\n#define Q64LE(n, d) \\\n    ( (table + ((n) * 8 + 7) * 0x100)[((d)         ) & 0xFF] \\\n    ^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 1 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 2 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 3 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 4 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 5 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 6 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 0) * 0x100)[((d) >> 7 * 8)] )\n\n#define R64(a)  *((const UInt64 *)(const void *)p + (a))\n\n#else\n\n#define Q32LE(n, d) \\\n    ( (table + ((n) * 4 + 3) * 0x100)[((d)         ) & 0xFF] \\\n    ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )\n\n#define R32(a)  *((const UInt32 *)(const void *)p + (a))\n\n#endif\n\n\n#define CRC64_FUNC_PRE_LE2(step) \\\nUInt64 Z7_FASTCALL XzCrc64UpdateT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table)\n\n#define CRC64_FUNC_PRE_LE(step)   \\\n        CRC64_FUNC_PRE_LE2(step); \\\n        CRC64_FUNC_PRE_LE2(step)\n\nCRC64_FUNC_PRE_LE(Z7_CRC64_NUM_TABLES_USE)\n{\n  const Byte *p = (const Byte *)data;\n  const Byte *lim;\n  for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++)\n    v = CRC64_UPDATE_BYTE_2(v, *p);\n  lim = p + size;\n  if (size >= Z7_CRC64_NUM_TABLES_USE)\n  {\n    lim -= Z7_CRC64_NUM_TABLES_USE;\n    do\n    {\n#if Z7_CRC64_NUM_TABLES_USE == 4\n      const UInt32 d = (UInt32)v ^ R32(0);\n      v = (v >> 32) ^ Q32LE(0, d);\n#elif Z7_CRC64_NUM_TABLES_USE == 8\n#ifdef Z7_CRC64_USE_64BIT\n      v ^= R64(0);\n      v = Q64LE(0, v);\n#else\n      UInt32 v0, v1;\n      v0 = (UInt32)v         ^ R32(0);\n      v1 = (UInt32)(v >> 32) ^ R32(1);\n      v = Q32LE(1, v0) ^ Q32LE(0, v1);\n#endif\n#elif Z7_CRC64_NUM_TABLES_USE == 12\n      UInt32 w;\n      UInt32 v0, v1;\n      v0 = (UInt32)v         ^ R32(0);\n      v1 = (UInt32)(v >> 32) ^ R32(1);\n      w = R32(2);\n      v = Q32LE(0, w);\n      v ^= Q32LE(2, v0) ^ Q32LE(1, v1);\n#elif Z7_CRC64_NUM_TABLES_USE == 16\n#ifdef Z7_CRC64_USE_64BIT\n      UInt64 w;\n      UInt64 x;\n      w  = R64(1);      x = Q64LE(0, w);\n      v ^= R64(0);  v = x ^ Q64LE(1, v);\n#else\n      UInt32 v0, v1;\n      UInt32 r0, r1;\n      v0 = (UInt32)v         ^ R32(0);\n      v1 = (UInt32)(v >> 32) ^ R32(1);\n      r0 =                     R32(2);\n      r1 =                     R32(3);\n      v  = Q32LE(1, r0) ^ Q32LE(0, r1);\n      v ^= Q32LE(3, v0) ^ Q32LE(2, v1);\n#endif\n#else\n#error Stop_Compiling_Bad_CRC64_NUM_TABLES\n#endif\n      p += Z7_CRC64_NUM_TABLES_USE;\n    }\n    while (p <= lim);\n    lim += Z7_CRC64_NUM_TABLES_USE;\n  }\n  for (; p < lim; p++)\n    v = CRC64_UPDATE_BYTE_2(v, *p);\n  return v;\n}\n\n#undef CRC64_UPDATE_BYTE_2\n#undef R32\n#undef R64\n#undef Q32LE\n#undef Q64LE\n#undef CRC64_FUNC_PRE_LE\n#undef CRC64_FUNC_PRE_LE2\n\n#endif\n\n\n\n\n#ifndef MY_CPU_LE\n\n#define CRC64_UPDATE_BYTE_2_BE(crc, b)  (table[((crc) >> 56) ^ (b)] ^ ((crc) << 8))\n\n#if defined(Z7_CRC64_USE_64BIT) && (Z7_CRC64_NUM_TABLES_USE % 8 == 0)\n\n#define Q64BE(n, d) \\\n    ( (table + ((n) * 8 + 0) * 0x100)[(Byte)(d)] \\\n    ^ (table + ((n) * 8 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 3) * 0x100)[((d) >> 3 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 4) * 0x100)[((d) >> 4 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 5) * 0x100)[((d) >> 5 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 6) * 0x100)[((d) >> 6 * 8) & 0xFF] \\\n    ^ (table + ((n) * 8 + 7) * 0x100)[((d) >> 7 * 8)] )\n\n#ifdef Z7_CRC64_DEBUG_BE\n  #define R64BE(a)  GetBe64a((const UInt64 *)(const void *)p + (a))\n#else\n  #define R64BE(a)         *((const UInt64 *)(const void *)p + (a))\n#endif\n\n#else\n\n#define Q32BE(n, d) \\\n    ( (table + ((n) * 4 + 0) * 0x100)[(Byte)(d)] \\\n    ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \\\n    ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )\n\n#ifdef Z7_CRC64_DEBUG_BE\n  #define R32BE(a)  GetBe32a((const UInt32 *)(const void *)p + (a))\n#else\n  #define R32BE(a)         *((const UInt32 *)(const void *)p + (a))\n#endif\n\n#endif\n\n#define CRC64_FUNC_PRE_BE2(step) \\\nUInt64 Z7_FASTCALL XzCrc64UpdateBeT ## step (UInt64 v, const void *data, size_t size, const UInt64 *table)\n\n#define CRC64_FUNC_PRE_BE(step)   \\\n        CRC64_FUNC_PRE_BE2(step); \\\n        CRC64_FUNC_PRE_BE2(step)\n\nCRC64_FUNC_PRE_BE(Z7_CRC64_NUM_TABLES_USE)\n{\n  const Byte *p = (const Byte *)data;\n  const Byte *lim;\n  v = Z7_BSWAP64(v);\n  for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC64_NUM_TABLES_USE & 4))) != 0; size--, p++)\n    v = CRC64_UPDATE_BYTE_2_BE(v, *p);\n  lim = p + size;\n  if (size >= Z7_CRC64_NUM_TABLES_USE)\n  {\n    lim -= Z7_CRC64_NUM_TABLES_USE;\n    do\n    {\n#if   Z7_CRC64_NUM_TABLES_USE == 4\n      const UInt32 d = (UInt32)(v >> 32) ^ R32BE(0);\n      v = (v << 32) ^ Q32BE(0, d);\n#elif Z7_CRC64_NUM_TABLES_USE == 12\n      const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);\n      const UInt32 d0 = (UInt32)(v      ) ^ R32BE(1);\n      const UInt32 w =                      R32BE(2);\n      v  = Q32BE(0, w);\n      v ^= Q32BE(2, d1) ^ Q32BE(1, d0);\n\n#elif Z7_CRC64_NUM_TABLES_USE == 8\n  #ifdef Z7_CRC64_USE_64BIT\n      v ^= R64BE(0);\n      v  = Q64BE(0, v);\n  #else\n      const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);\n      const UInt32 d0 = (UInt32)(v      ) ^ R32BE(1);\n      v = Q32BE(1, d1) ^ Q32BE(0, d0);\n  #endif\n#elif Z7_CRC64_NUM_TABLES_USE == 16\n  #ifdef Z7_CRC64_USE_64BIT\n      const UInt64 w = R64BE(1);\n      v ^= R64BE(0);\n      v  = Q64BE(0, w) ^ Q64BE(1, v);\n  #else\n      const UInt32 d1 = (UInt32)(v >> 32) ^ R32BE(0);\n      const UInt32 d0 = (UInt32)(v      ) ^ R32BE(1);\n      const UInt32 w1 =                     R32BE(2);\n      const UInt32 w0 =                     R32BE(3);\n      v  = Q32BE(1, w1) ^ Q32BE(0, w0);\n      v ^= Q32BE(3, d1) ^ Q32BE(2, d0);\n  #endif\n#else\n#error Stop_Compiling_Bad_CRC64_NUM_TABLES\n#endif\n      p += Z7_CRC64_NUM_TABLES_USE;\n    }\n    while (p <= lim);\n    lim += Z7_CRC64_NUM_TABLES_USE;\n  }\n  for (; p < lim; p++)\n    v = CRC64_UPDATE_BYTE_2_BE(v, *p);\n  return Z7_BSWAP64(v);\n}\n\n#undef CRC64_UPDATE_BYTE_2_BE\n#undef R32BE\n#undef R64BE\n#undef Q32BE\n#undef Q64BE\n#undef CRC64_FUNC_PRE_BE\n#undef CRC64_FUNC_PRE_BE2\n\n#endif\n#undef Z7_CRC64_NUM_TABLES_USE\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/XzDec.c",
    "content": "﻿/* XzDec.c -- Xz Decode\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n// #include <stdio.h>\n\n// #define XZ_DUMP\n\n/* #define XZ_DUMP */\n\n#ifdef XZ_DUMP\n#include <stdio.h>\n#endif\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#define PRF_STR(s) PRF(printf(\"\\n\" s \"\\n\"))\n#define PRF_STR_INT(s, d) PRF(printf(\"\\n\" s \" %d\\n\", (unsigned)d))\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"7zCrc.h\"\n#include \"Alloc.h\"\n#include \"Bra.h\"\n#include \"CpuArch.h\"\n#include \"Delta.h\"\n#include \"Lzma2Dec.h\"\n\n// #define USE_SUBBLOCK\n\n#ifdef USE_SUBBLOCK\n#include \"Bcj3Dec.c\"\n#include \"SbDec.h\"\n#endif\n\n#include \"Xz.h\"\n\n#define XZ_CHECK_SIZE_MAX 64\n\n#define CODER_BUF_SIZE ((size_t)1 << 17)\n\nunsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)\n{\n  unsigned i, limit;\n  *value = 0;\n  limit = (maxSize > 9) ? 9 : (unsigned)maxSize;\n\n  for (i = 0; i < limit;)\n  {\n    const unsigned b = p[i];\n    *value |= (UInt64)(b & 0x7F) << (7 * i++);\n    if ((b & 0x80) == 0)\n      return (b == 0 && i != 1) ? 0 : i;\n  }\n  return 0;\n}\n\n\n/* ---------- XzBcFilterState ---------- */\n\n#define BRA_BUF_SIZE (1 << 14)\n\ntypedef struct\n{\n  size_t bufPos;\n  size_t bufConv;\n  size_t bufTotal;\n  Byte *buf;  // must be aligned for 4 bytes\n  Xz_Func_BcFilterStateBase_Filter filter_func;\n  // int encodeMode;\n  CXzBcFilterStateBase base;\n  // Byte buf[BRA_BUF_SIZE];\n} CXzBcFilterState;\n\n\nstatic void XzBcFilterState_Free(void *pp, ISzAllocPtr alloc)\n{\n  if (pp)\n  {\n    CXzBcFilterState *p = ((CXzBcFilterState *)pp);\n    ISzAlloc_Free(alloc, p->buf);\n    ISzAlloc_Free(alloc, pp);\n  }\n}\n\n\nstatic SRes XzBcFilterState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)\n{\n  CXzBcFilterStateBase *p = &((CXzBcFilterState *)pp)->base;\n  UNUSED_VAR(alloc)\n  p->ip = 0;\n  if (p->methodId == XZ_ID_Delta)\n  {\n    if (propSize != 1)\n      return SZ_ERROR_UNSUPPORTED;\n    p->delta = (UInt32)props[0] + 1;\n  }\n  else\n  {\n    if (propSize == 4)\n    {\n      const UInt32 v = GetUi32(props);\n      switch (p->methodId)\n      {\n        case XZ_ID_PPC:\n        case XZ_ID_ARM:\n        case XZ_ID_SPARC:\n        case XZ_ID_ARM64:\n          if (v & 3)\n            return SZ_ERROR_UNSUPPORTED;\n          break;\n        case XZ_ID_ARMT:\n        case XZ_ID_RISCV:\n          if (v & 1)\n            return SZ_ERROR_UNSUPPORTED;\n          break;\n        case XZ_ID_IA64:\n          if (v & 0xf)\n            return SZ_ERROR_UNSUPPORTED;\n          break;\n        default: break;\n      }\n      p->ip = v;\n    }\n    else if (propSize != 0)\n      return SZ_ERROR_UNSUPPORTED;\n  }\n  return SZ_OK;\n}\n\n\nstatic void XzBcFilterState_Init(void *pp)\n{\n  CXzBcFilterState *p = ((CXzBcFilterState *)pp);\n  p->bufPos = p->bufConv = p->bufTotal = 0;\n  p->base.X86_State = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL;\n  if (p->base.methodId == XZ_ID_Delta)\n    Delta_Init(p->base.delta_State);\n}\n\n\nstatic const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Dec[] =\n{\n  Z7_BRANCH_CONV_DEC_2 (BranchConv_PPC),\n  Z7_BRANCH_CONV_DEC_2 (BranchConv_IA64),\n  Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM),\n  Z7_BRANCH_CONV_DEC_2 (BranchConv_ARMT),\n  Z7_BRANCH_CONV_DEC_2 (BranchConv_SPARC),\n  Z7_BRANCH_CONV_DEC_2 (BranchConv_ARM64),\n  Z7_BRANCH_CONV_DEC_2 (BranchConv_RISCV)\n};\n\nstatic SizeT XzBcFilterStateBase_Filter_Dec(CXzBcFilterStateBase *p, Byte *data, SizeT size)\n{\n  switch (p->methodId)\n  {\n    case XZ_ID_Delta:\n      Delta_Decode(p->delta_State, p->delta, data, size);\n      break;\n    case XZ_ID_X86:\n      size = (SizeT)(z7_BranchConvSt_X86_Dec(data, size, p->ip, &p->X86_State) - data);\n      break;\n    default:\n      if (p->methodId >= XZ_ID_PPC)\n      {\n        const UInt32 i = p->methodId - XZ_ID_PPC;\n        if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Dec))\n          size = (SizeT)(g_Funcs_BranchConv_RISC_Dec[i](data, size, p->ip) - data);\n      }\n      break;\n  }\n  p->ip += (UInt32)size;\n  return size;\n}\n\n\nstatic SizeT XzBcFilterState_Filter(void *pp, Byte *data, SizeT size)\n{\n  CXzBcFilterState *p = ((CXzBcFilterState *)pp);\n  return p->filter_func(&p->base, data, size);\n}\n\n\nstatic SRes XzBcFilterState_Code2(void *pp,\n    Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen, int srcWasFinished,\n    ECoderFinishMode finishMode,\n    // int *wasFinished\n    ECoderStatus *status)\n{\n  CXzBcFilterState *p = ((CXzBcFilterState *)pp);\n  SizeT destRem = *destLen;\n  SizeT srcRem = *srcLen;\n  UNUSED_VAR(finishMode)\n\n  *destLen = 0;\n  *srcLen = 0;\n  // *wasFinished = False;\n  *status = CODER_STATUS_NOT_FINISHED;\n  \n  while (destRem != 0)\n  {\n    {\n      size_t size = p->bufConv - p->bufPos;\n      if (size)\n      {\n        if (size > destRem)\n          size = destRem;\n        memcpy(dest, p->buf + p->bufPos, size);\n        p->bufPos += size;\n        *destLen += size;\n        dest += size;\n        destRem -= size;\n        continue;\n      }\n    }\n    \n    p->bufTotal -= p->bufPos;\n    memmove(p->buf, p->buf + p->bufPos, p->bufTotal);\n    p->bufPos = 0;\n    p->bufConv = 0;\n    {\n      size_t size = BRA_BUF_SIZE - p->bufTotal;\n      if (size > srcRem)\n        size = srcRem;\n      memcpy(p->buf + p->bufTotal, src, size);\n      *srcLen += size;\n      src += size;\n      srcRem -= size;\n      p->bufTotal += size;\n    }\n    if (p->bufTotal == 0)\n      break;\n    \n    p->bufConv = p->filter_func(&p->base, p->buf, p->bufTotal);\n\n    if (p->bufConv == 0)\n    {\n      if (!srcWasFinished)\n        break;\n      p->bufConv = p->bufTotal;\n    }\n  }\n\n  if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)\n  {\n    *status = CODER_STATUS_FINISHED_WITH_MARK;\n    // *wasFinished = 1;\n  }\n\n  return SZ_OK;\n}\n\n\n#define XZ_IS_SUPPORTED_FILTER_ID(id) \\\n    ((id) >= XZ_ID_Delta && (id) <= XZ_ID_RISCV)\n     \nSRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,\n    Xz_Func_BcFilterStateBase_Filter func, ISzAllocPtr alloc)\n{\n  CXzBcFilterState *decoder;\n  if (!XZ_IS_SUPPORTED_FILTER_ID(id))\n    return SZ_ERROR_UNSUPPORTED;\n  decoder = (CXzBcFilterState *)p->p;\n  if (!decoder)\n  {\n    decoder = (CXzBcFilterState *)ISzAlloc_Alloc(alloc, sizeof(CXzBcFilterState));\n    if (!decoder)\n      return SZ_ERROR_MEM;\n    decoder->buf = ISzAlloc_Alloc(alloc, BRA_BUF_SIZE);\n    if (!decoder->buf)\n    {\n      ISzAlloc_Free(alloc, decoder);\n      return SZ_ERROR_MEM;\n    }\n    p->p = decoder;\n    p->Free     = XzBcFilterState_Free;\n    p->SetProps = XzBcFilterState_SetProps;\n    p->Init     = XzBcFilterState_Init;\n    p->Code2    = XzBcFilterState_Code2;\n    p->Filter   = XzBcFilterState_Filter;\n    decoder->filter_func = func;\n  }\n  decoder->base.methodId = (UInt32)id;\n  // decoder->encodeMode = encodeMode;\n  return SZ_OK;\n}\n\n\n\n/* ---------- SbState ---------- */\n\n#ifdef USE_SUBBLOCK\n\nstatic void SbState_Free(void *pp, ISzAllocPtr alloc)\n{\n  CSbDec *p = (CSbDec *)pp;\n  SbDec_Free(p);\n  ISzAlloc_Free(alloc, pp);\n}\n\nstatic SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)\n{\n  UNUSED_VAR(pp)\n  UNUSED_VAR(props)\n  UNUSED_VAR(alloc)\n  return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;\n}\n\nstatic void SbState_Init(void *pp)\n{\n  SbDec_Init((CSbDec *)pp);\n}\n\nstatic SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    int srcWasFinished, ECoderFinishMode finishMode,\n    // int *wasFinished\n    ECoderStatus *status)\n{\n  CSbDec *p = (CSbDec *)pp;\n  SRes res;\n  UNUSED_VAR(srcWasFinished)\n  p->dest = dest;\n  p->destLen = *destLen;\n  p->src = src;\n  p->srcLen = *srcLen;\n  p->finish = finishMode; /* change it */\n  res = SbDec_Decode((CSbDec *)pp);\n  *destLen -= p->destLen;\n  *srcLen -= p->srcLen;\n  // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */\n  *status = (*destLen == 0 && *srcLen == 0) ?\n      CODER_STATUS_FINISHED_WITH_MARK :\n      CODER_STATUS_NOT_FINISHED;\n  return res;\n}\n\nstatic SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)\n{\n  CSbDec *decoder = (CSbDec *)p->p;\n  if (!decoder)\n  {\n    decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));\n    if (!decoder)\n      return SZ_ERROR_MEM;\n    p->p = decoder;\n    p->Free = SbState_Free;\n    p->SetProps = SbState_SetProps;\n    p->Init = SbState_Init;\n    p->Code2 = SbState_Code2;\n    p->Filter = NULL;\n  }\n  SbDec_Construct(decoder);\n  SbDec_SetAlloc(decoder, alloc);\n  return SZ_OK;\n}\n\n#endif\n\n\n\n/* ---------- Lzma2 ---------- */\n\ntypedef struct\n{\n  CLzma2Dec decoder;\n  BoolInt outBufMode;\n} CLzma2Dec_Spec;\n\n\nstatic void Lzma2State_Free(void *pp, ISzAllocPtr alloc)\n{\n  CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;\n  if (p->outBufMode)\n    Lzma2Dec_FreeProbs(&p->decoder, alloc);\n  else\n    Lzma2Dec_Free(&p->decoder, alloc);\n  ISzAlloc_Free(alloc, pp);\n}\n\nstatic SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)\n{\n  if (propSize != 1)\n    return SZ_ERROR_UNSUPPORTED;\n  {\n    CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;\n    if (p->outBufMode)\n      return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);\n    else\n      return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);\n  }\n}\n\nstatic void Lzma2State_Init(void *pp)\n{\n  Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);\n}\n\n\n/*\n  if (outBufMode), then (dest) is not used. Use NULL.\n         Data is unpacked to (spec->decoder.decoder.dic) output buffer.\n*/\n\nstatic SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\n    int srcWasFinished, ECoderFinishMode finishMode,\n    // int *wasFinished,\n    ECoderStatus *status)\n{\n  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;\n  ELzmaStatus status2;\n  /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */\n  SRes res;\n  UNUSED_VAR(srcWasFinished)\n  if (spec->outBufMode)\n  {\n    SizeT dicPos = spec->decoder.decoder.dicPos;\n    SizeT dicLimit = dicPos + *destLen;\n    res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);\n    *destLen = spec->decoder.decoder.dicPos - dicPos;\n  }\n  else\n    res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);\n  // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);\n  // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder\n  *status = (ECoderStatus)status2;\n  return res;\n}\n\n\nstatic SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)\n{\n  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;\n  if (!spec)\n  {\n    spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));\n    if (!spec)\n      return SZ_ERROR_MEM;\n    p->p = spec;\n    p->Free = Lzma2State_Free;\n    p->SetProps = Lzma2State_SetProps;\n    p->Init = Lzma2State_Init;\n    p->Code2 = Lzma2State_Code2;\n    p->Filter = NULL;\n    Lzma2Dec_CONSTRUCT(&spec->decoder)\n  }\n  spec->outBufMode = False;\n  if (outBuf)\n  {\n    spec->outBufMode = True;\n    spec->decoder.decoder.dic = outBuf;\n    spec->decoder.decoder.dicBufSize = outBufSize;\n  }\n  return SZ_OK;\n}\n\n\nstatic SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)\n{\n  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;\n  if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))\n    return SZ_ERROR_FAIL;\n  if (outBuf)\n  {\n    spec->decoder.decoder.dic = outBuf;\n    spec->decoder.decoder.dicBufSize = outBufSize;\n  }\n  return SZ_OK;\n}\n\n\n\nstatic void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)\n{\n  unsigned i;\n  p->alloc = alloc;\n  p->buf = NULL;\n  p->numCoders = 0;\n  \n  p->outBufSize = 0;\n  p->outBuf = NULL;\n  // p->SingleBufMode = False;\n\n  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)\n    p->coders[i].p = NULL;\n}\n\n\nstatic void MixCoder_Free(CMixCoder *p)\n{\n  unsigned i;\n  p->numCoders = 0;\n  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)\n  {\n    IStateCoder *sc = &p->coders[i];\n    if (sc->p)\n    {\n      sc->Free(sc->p, p->alloc);\n      sc->p = NULL;\n    }\n  }\n  if (p->buf)\n  {\n    ISzAlloc_Free(p->alloc, p->buf);\n    p->buf = NULL; /* 9.31: the BUG was fixed */\n  }\n}\n\nstatic void MixCoder_Init(CMixCoder *p)\n{\n  unsigned i;\n  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)\n  {\n    p->size[i] = 0;\n    p->pos[i] = 0;\n    p->finished[i] = 0;\n  }\n  for (i = 0; i < p->numCoders; i++)\n  {\n    IStateCoder *coder = &p->coders[i];\n    coder->Init(coder->p);\n    p->results[i] = SZ_OK;\n  }\n  p->outWritten = 0;\n  p->wasFinished = False;\n  p->res = SZ_OK;\n  p->status = CODER_STATUS_NOT_SPECIFIED;\n}\n\n\nstatic SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)\n{\n  IStateCoder *sc = &p->coders[coderIndex];\n  p->ids[coderIndex] = methodId;\n  if (methodId == XZ_ID_LZMA2)\n    return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);\n#ifdef USE_SUBBLOCK\n  if (methodId == XZ_ID_Subblock)\n    return SbState_SetFromMethod(sc, p->alloc);\n#endif\n  if (coderIndex == 0)\n    return SZ_ERROR_UNSUPPORTED;\n  return Xz_StateCoder_Bc_SetFromMethod_Func(sc, methodId,\n      XzBcFilterStateBase_Filter_Dec, p->alloc);\n}\n\n\nstatic SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)\n{\n  IStateCoder *sc = &p->coders[coderIndex];\n  if (methodId == XZ_ID_LZMA2)\n    return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);\n  return SZ_ERROR_UNSUPPORTED;\n}\n\n\n\n/*\n if (destFinish) - then unpack data block is finished at (*destLen) position,\n                   and we can return data that were not processed by filter\n\noutput (status) can be :\n  CODER_STATUS_NOT_FINISHED\n  CODER_STATUS_FINISHED_WITH_MARK\n  CODER_STATUS_NEEDS_MORE_INPUT - not implemented still\n*/\n\nstatic SRes MixCoder_Code(CMixCoder *p,\n    Byte *dest, SizeT *destLen, int destFinish,\n    const Byte *src, SizeT *srcLen, int srcWasFinished,\n    ECoderFinishMode finishMode)\n{\n  SizeT destLenOrig = *destLen;\n  SizeT srcLenOrig = *srcLen;\n\n  *destLen = 0;\n  *srcLen = 0;\n\n  if (p->wasFinished)\n    return p->res;\n  \n  p->status = CODER_STATUS_NOT_FINISHED;\n\n  // if (p->SingleBufMode)\n  if (p->outBuf)\n  {\n    SRes res;\n    SizeT destLen2, srcLen2;\n    int wasFinished;\n    \n    PRF_STR(\"------- MixCoder Single ----------\")\n      \n    srcLen2 = srcLenOrig;\n    destLen2 = destLenOrig;\n    \n    {\n      IStateCoder *coder = &p->coders[0];\n      res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,\n          // &wasFinished,\n          &p->status);\n      wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);\n    }\n    \n    p->res = res;\n    \n    /*\n    if (wasFinished)\n      p->status = CODER_STATUS_FINISHED_WITH_MARK;\n    else\n    {\n      if (res == SZ_OK)\n        if (destLen2 != destLenOrig)\n          p->status = CODER_STATUS_NEEDS_MORE_INPUT;\n    }\n    */\n\n    \n    *srcLen = srcLen2;\n    src += srcLen2;\n    p->outWritten += destLen2;\n    \n    if (res != SZ_OK || srcWasFinished || wasFinished)\n      p->wasFinished = True;\n    \n    if (p->numCoders == 1)\n      *destLen = destLen2;\n    else if (p->wasFinished)\n    {\n      unsigned i;\n      size_t processed = p->outWritten;\n      \n      for (i = 1; i < p->numCoders; i++)\n      {\n        IStateCoder *coder = &p->coders[i];\n        processed = coder->Filter(coder->p, p->outBuf, processed);\n        if (wasFinished || (destFinish && p->outWritten == destLenOrig))\n          processed = p->outWritten;\n        PRF_STR_INT(\"filter\", i)\n      }\n      *destLen = processed;\n    }\n    return res;\n  }\n\n  PRF_STR(\"standard mix\")\n\n  if (p->numCoders != 1)\n  {\n    if (!p->buf)\n    {\n      p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));\n      if (!p->buf)\n        return SZ_ERROR_MEM;\n    }\n    \n    finishMode = CODER_FINISH_ANY;\n  }\n\n  for (;;)\n  {\n    BoolInt processed = False;\n    BoolInt allFinished = True;\n    SRes resMain = SZ_OK;\n    unsigned i;\n\n    p->status = CODER_STATUS_NOT_FINISHED;\n    /*\n    if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)\n      break;\n    */\n\n    for (i = 0; i < p->numCoders; i++)\n    {\n      SRes res;\n      IStateCoder *coder = &p->coders[i];\n      Byte *dest2;\n      SizeT destLen2, srcLen2; // destLen2_Orig;\n      const Byte *src2;\n      int srcFinished2;\n      int encodingWasFinished;\n      ECoderStatus status2;\n      \n      if (i == 0)\n      {\n        src2 = src;\n        srcLen2 = srcLenOrig - *srcLen;\n        srcFinished2 = srcWasFinished;\n      }\n      else\n      {\n        size_t k = i - 1;\n        src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];\n        srcLen2 = p->size[k] - p->pos[k];\n        srcFinished2 = p->finished[k];\n      }\n      \n      if (i == p->numCoders - 1)\n      {\n        dest2 = dest;\n        destLen2 = destLenOrig - *destLen;\n      }\n      else\n      {\n        if (p->pos[i] != p->size[i])\n          continue;\n        dest2 = p->buf + (CODER_BUF_SIZE * i);\n        destLen2 = CODER_BUF_SIZE;\n      }\n      \n      // destLen2_Orig = destLen2;\n      \n      if (p->results[i] != SZ_OK)\n      {\n        if (resMain == SZ_OK)\n          resMain = p->results[i];\n        continue;\n      }\n\n      res = coder->Code2(coder->p,\n          dest2, &destLen2,\n          src2, &srcLen2, srcFinished2,\n          finishMode,\n          // &encodingWasFinished,\n          &status2);\n\n      if (res != SZ_OK)\n      {\n        p->results[i] = res;\n        if (resMain == SZ_OK)\n          resMain = res;\n      }\n\n      encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);\n      \n      if (!encodingWasFinished)\n      {\n        allFinished = False;\n        if (p->numCoders == 1 && res == SZ_OK)\n          p->status = status2;\n      }\n\n      if (i == 0)\n      {\n        *srcLen += srcLen2;\n        src += srcLen2;\n      }\n      else\n        p->pos[(size_t)i - 1] += srcLen2;\n\n      if (i == p->numCoders - 1)\n      {\n        *destLen += destLen2;\n        dest += destLen2;\n      }\n      else\n      {\n        p->size[i] = destLen2;\n        p->pos[i] = 0;\n        p->finished[i] = encodingWasFinished;\n      }\n      \n      if (destLen2 != 0 || srcLen2 != 0)\n        processed = True;\n    }\n    \n    if (!processed)\n    {\n      if (allFinished)\n        p->status = CODER_STATUS_FINISHED_WITH_MARK;\n      return resMain;\n    }\n  }\n}\n\n\nSRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)\n{\n  *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);\n  if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=\n      GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))\n    return SZ_ERROR_NO_ARCHIVE;\n  return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;\n}\n\nstatic BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)\n{\n  return indexSize == (((UInt64)GetUi32a(buf + 4) + 1) << 2)\n      && GetUi32a(buf) == CrcCalc(buf + 4, 6)\n      && flags == GetBe16a(buf + 8)\n      && GetUi16a(buf + 10) == (XZ_FOOTER_SIG_0 | (XZ_FOOTER_SIG_1 << 8));\n}\n\n#define READ_VARINT_AND_CHECK(buf, pos, size, res) \\\n  { const unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \\\n  if (s == 0) return SZ_ERROR_ARCHIVE; \\\n  pos += s; }\n\n\nstatic BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p)\n{\n  const unsigned numFilters = XzBlock_GetNumFilters(p) - 1;\n  unsigned i;\n  {\n    const CXzFilter *f = &p->filters[numFilters];\n    if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)\n      return False;\n  }\n\n  for (i = 0; i < numFilters; i++)\n  {\n    const CXzFilter *f = &p->filters[i];\n    if (f->id == XZ_ID_Delta)\n    {\n      if (f->propsSize != 1)\n        return False;\n    }\n    else if (!XZ_IS_SUPPORTED_FILTER_ID(f->id)\n        || (f->propsSize != 0 && f->propsSize != 4))\n      return False;\n  }\n  return True;\n}\n\n\nSRes XzBlock_Parse(CXzBlock *p, const Byte *header)\n{\n  unsigned pos;\n  unsigned numFilters, i;\n  unsigned headerSize = (unsigned)header[0] << 2;\n\n  /* (headerSize != 0) : another code checks */\n\n  if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))\n    return SZ_ERROR_ARCHIVE;\n\n  pos = 1;\n  p->flags = header[pos++];\n\n  p->packSize = (UInt64)(Int64)-1;\n  if (XzBlock_HasPackSize(p))\n  {\n    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize)\n    if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)\n      return SZ_ERROR_ARCHIVE;\n  }\n\n  p->unpackSize = (UInt64)(Int64)-1;\n  if (XzBlock_HasUnpackSize(p))\n  {\n    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize)\n  }\n\n  numFilters = XzBlock_GetNumFilters(p);\n  for (i = 0; i < numFilters; i++)\n  {\n    CXzFilter *filter = p->filters + i;\n    UInt64 size;\n    READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id)\n    READ_VARINT_AND_CHECK(header, pos, headerSize, &size)\n    if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)\n      return SZ_ERROR_ARCHIVE;\n    filter->propsSize = (UInt32)size;\n    memcpy(filter->props, header + pos, (size_t)size);\n    pos += (unsigned)size;\n\n    #ifdef XZ_DUMP\n    printf(\"\\nf[%u] = %2X: \", i, (unsigned)filter->id);\n    {\n      unsigned i;\n      for (i = 0; i < size; i++)\n        printf(\" %2X\", filter->props[i]);\n    }\n    #endif\n  }\n\n  if (XzBlock_HasUnsupportedFlags(p))\n    return SZ_ERROR_UNSUPPORTED;\n\n  while (pos < headerSize)\n    if (header[pos++] != 0)\n      return SZ_ERROR_ARCHIVE;\n  return SZ_OK;\n}\n\n\n\n\nstatic SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)\n{\n  unsigned i;\n  BoolInt needReInit = True;\n  unsigned numFilters = XzBlock_GetNumFilters(block);\n\n  if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))\n  {\n    needReInit = False;\n    for (i = 0; i < numFilters; i++)\n      if (p->ids[i] != block->filters[numFilters - 1 - i].id)\n      {\n        needReInit = True;\n        break;\n      }\n  }\n\n  // p->SingleBufMode = (outBuf != NULL);\n  p->outBuf = outBuf;\n  p->outBufSize = outBufSize;\n\n  // p->SingleBufMode = False;\n  // outBuf = NULL;\n  \n  if (needReInit)\n  {\n    MixCoder_Free(p);\n    for (i = 0; i < numFilters; i++)\n    {\n      RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize))\n    }\n    p->numCoders = numFilters;\n  }\n  else\n  {\n    RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize))\n  }\n\n  for (i = 0; i < numFilters; i++)\n  {\n    const CXzFilter *f = &block->filters[numFilters - 1 - i];\n    IStateCoder *sc = &p->coders[i];\n    RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc))\n  }\n  \n  MixCoder_Init(p);\n  return SZ_OK;\n}\n\n\n\nvoid XzUnpacker_Init(CXzUnpacker *p)\n{\n  p->state = XZ_STATE_STREAM_HEADER;\n  p->pos = 0;\n  p->numStartedStreams = 0;\n  p->numFinishedStreams = 0;\n  p->numTotalBlocks = 0;\n  p->padSize = 0;\n  p->decodeOnlyOneBlock = 0;\n\n  p->parseMode = False;\n  p->decodeToStreamSignature = False;\n\n  // p->outBuf = NULL;\n  // p->outBufSize = 0;\n  p->outDataWritten = 0;\n}\n\n\nvoid XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)\n{\n  p->outBuf = outBuf;\n  p->outBufSize = outBufSize;\n}\n\n\nvoid XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)\n{\n  MixCoder_Construct(&p->decoder, alloc);\n  p->outBuf = NULL;\n  p->outBufSize = 0;\n  XzUnpacker_Init(p);\n}\n\n\nvoid XzUnpacker_Free(CXzUnpacker *p)\n{\n  MixCoder_Free(&p->decoder);\n}\n\n\nvoid XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)\n{\n  p->indexSize = 0;\n  p->numBlocks = 0;\n  Sha256_Init(&p->sha);\n  p->state = XZ_STATE_BLOCK_HEADER;\n  p->pos = 0;\n  p->decodeOnlyOneBlock = 1;\n}\n\n\nstatic void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)\n{\n  Byte temp[32];\n  unsigned num = Xz_WriteVarInt(temp, packSize);\n  num += Xz_WriteVarInt(temp + num, unpackSize);\n  Sha256_Update(&p->sha, temp, num);\n  p->indexSize += num;\n  p->numBlocks++;\n}\n\n\n\nSRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen, int srcFinished,\n    ECoderFinishMode finishMode, ECoderStatus *status)\n{\n  SizeT destLenOrig = *destLen;\n  SizeT srcLenOrig = *srcLen;\n  *destLen = 0;\n  *srcLen = 0;\n  *status = CODER_STATUS_NOT_SPECIFIED;\n\n  for (;;)\n  {\n    SizeT srcRem;\n\n    if (p->state == XZ_STATE_BLOCK)\n    {\n      SizeT destLen2 = destLenOrig - *destLen;\n      SizeT srcLen2 = srcLenOrig - *srcLen;\n      SRes res;\n\n      ECoderFinishMode finishMode2 = finishMode;\n      BoolInt srcFinished2 = (BoolInt)srcFinished;\n      BoolInt destFinish = False;\n\n      if (p->block.packSize != (UInt64)(Int64)-1)\n      {\n        UInt64 rem = p->block.packSize - p->packSize;\n        if (srcLen2 >= rem)\n        {\n          srcFinished2 = True;\n          srcLen2 = (SizeT)rem;\n        }\n        if (rem == 0 && p->block.unpackSize == p->unpackSize)\n          return SZ_ERROR_DATA;\n      }\n\n      if (p->block.unpackSize != (UInt64)(Int64)-1)\n      {\n        UInt64 rem = p->block.unpackSize - p->unpackSize;\n        if (destLen2 >= rem)\n        {\n          destFinish = True;\n          finishMode2 = CODER_FINISH_END;\n          destLen2 = (SizeT)rem;\n        }\n      }\n\n      /*\n      if (srcLen2 == 0 && destLen2 == 0)\n      {\n        *status = CODER_STATUS_NOT_FINISHED;\n        return SZ_OK;\n      }\n      */\n      \n      {\n        res = MixCoder_Code(&p->decoder,\n            (p->outBuf ? NULL : dest), &destLen2, destFinish,\n            src, &srcLen2, srcFinished2,\n            finishMode2);\n\n        *status = p->decoder.status;\n        XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);\n        if (!p->outBuf)\n          dest += destLen2;\n        p->outDataWritten += destLen2;\n      }\n      \n      (*srcLen) += srcLen2;\n      src += srcLen2;\n      p->packSize += srcLen2;\n      (*destLen) += destLen2;\n      p->unpackSize += destLen2;\n\n      RINOK(res)\n\n      if (*status != CODER_STATUS_FINISHED_WITH_MARK)\n      {\n        if (p->block.packSize == p->packSize\n            && *status == CODER_STATUS_NEEDS_MORE_INPUT)\n        {\n          PRF_STR(\"CODER_STATUS_NEEDS_MORE_INPUT\")\n          *status = CODER_STATUS_NOT_SPECIFIED;\n          return SZ_ERROR_DATA;\n        }\n        \n        return SZ_OK;\n      }\n      {\n        XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);\n        p->state = XZ_STATE_BLOCK_FOOTER;\n        p->pos = 0;\n        p->alignPos = 0;\n        *status = CODER_STATUS_NOT_SPECIFIED;\n\n        if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)\n           || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))\n        {\n          PRF_STR(\"ERROR: block.size mismatch\")\n          return SZ_ERROR_DATA;\n        }\n      }\n      // continue;\n    }\n\n    srcRem = srcLenOrig - *srcLen;\n\n    // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes\n    if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)\n    {\n      *status = CODER_STATUS_NEEDS_MORE_INPUT;\n      return SZ_OK;\n    }\n\n    switch ((int)p->state)\n    {\n      case XZ_STATE_STREAM_HEADER:\n      {\n        if (p->pos < XZ_STREAM_HEADER_SIZE)\n        {\n          if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])\n            return SZ_ERROR_NO_ARCHIVE;\n          if (p->decodeToStreamSignature)\n            return SZ_OK;\n          p->buf[p->pos++] = *src++;\n          (*srcLen)++;\n        }\n        else\n        {\n          RINOK(Xz_ParseHeader(&p->streamFlags, p->buf))\n          p->numStartedStreams++;\n          p->indexSize = 0;\n          p->numBlocks = 0;\n          Sha256_Init(&p->sha);\n          p->state = XZ_STATE_BLOCK_HEADER;\n          p->pos = 0;\n        }\n        break;\n      }\n\n      case XZ_STATE_BLOCK_HEADER:\n      {\n        if (p->pos == 0)\n        {\n          p->buf[p->pos++] = *src++;\n          (*srcLen)++;\n          if (p->buf[0] == 0)\n          {\n            if (p->decodeOnlyOneBlock)\n              return SZ_ERROR_DATA;\n            p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);\n            p->indexPos = p->indexPreSize;\n            p->indexSize += p->indexPreSize;\n            Sha256_Final(&p->sha, (Byte *)(void *)p->shaDigest32);\n            Sha256_Init(&p->sha);\n            p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);\n            p->state = XZ_STATE_STREAM_INDEX;\n            break;\n          }\n          p->blockHeaderSize = ((unsigned)p->buf[0] << 2) + 4;\n          break;\n        }\n        \n        if (p->pos != p->blockHeaderSize)\n        {\n          unsigned cur = p->blockHeaderSize - p->pos;\n          if (cur > srcRem)\n            cur = (unsigned)srcRem;\n          memcpy(p->buf + p->pos, src, cur);\n          p->pos += cur;\n          (*srcLen) += cur;\n          src += cur;\n        }\n        else\n        {\n          RINOK(XzBlock_Parse(&p->block, p->buf))\n          if (!XzBlock_AreSupportedFilters(&p->block))\n            return SZ_ERROR_UNSUPPORTED;\n          p->numTotalBlocks++;\n          p->state = XZ_STATE_BLOCK;\n          p->packSize = 0;\n          p->unpackSize = 0;\n          XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));\n          if (p->parseMode)\n          {\n            p->headerParsedOk = True;\n            return SZ_OK;\n          }\n          RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize))\n        }\n        break;\n      }\n\n      case XZ_STATE_BLOCK_FOOTER:\n      {\n        if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)\n        {\n          if (srcRem == 0)\n          {\n            *status = CODER_STATUS_NEEDS_MORE_INPUT;\n            return SZ_OK;\n          }\n          (*srcLen)++;\n          p->alignPos++;\n          if (*src++ != 0)\n            return SZ_ERROR_CRC;\n        }\n        else\n        {\n          const unsigned checkSize = XzFlags_GetCheckSize(p->streamFlags);\n          unsigned cur = checkSize - p->pos;\n          if (cur != 0)\n          {\n            if (srcRem == 0)\n            {\n              *status = CODER_STATUS_NEEDS_MORE_INPUT;\n              return SZ_OK;\n            }\n            if (cur > srcRem)\n              cur = (unsigned)srcRem;\n            memcpy(p->buf + p->pos, src, cur);\n            p->pos += cur;\n            (*srcLen) += cur;\n            src += cur;\n            if (checkSize != p->pos)\n              break;\n          }\n          {\n            UInt32 digest32[XZ_CHECK_SIZE_MAX / 4];\n            p->state = XZ_STATE_BLOCK_HEADER;\n            p->pos = 0;\n            if (XzCheck_Final(&p->check, (void *)digest32) && memcmp(digest32, p->buf, checkSize) != 0)\n              return SZ_ERROR_CRC;\n            if (p->decodeOnlyOneBlock)\n            {\n              *status = CODER_STATUS_FINISHED_WITH_MARK;\n              return SZ_OK;\n            }\n          }\n        }\n        break;\n      }\n\n      case XZ_STATE_STREAM_INDEX:\n      {\n        if (p->pos < p->indexPreSize)\n        {\n          (*srcLen)++;\n          if (*src++ != p->buf[p->pos++])\n            return SZ_ERROR_CRC;\n        }\n        else\n        {\n          if (p->indexPos < p->indexSize)\n          {\n            UInt64 cur = p->indexSize - p->indexPos;\n            if (srcRem > cur)\n              srcRem = (SizeT)cur;\n            p->crc = CrcUpdate(p->crc, src, srcRem);\n            Sha256_Update(&p->sha, src, srcRem);\n            (*srcLen) += srcRem;\n            src += srcRem;\n            p->indexPos += srcRem;\n          }\n          else if ((p->indexPos & 3) != 0)\n          {\n            Byte b = *src++;\n            p->crc = CRC_UPDATE_BYTE(p->crc, b);\n            (*srcLen)++;\n            p->indexPos++;\n            p->indexSize++;\n            if (b != 0)\n              return SZ_ERROR_CRC;\n          }\n          else\n          {\n            UInt32 digest32[SHA256_DIGEST_SIZE / 4];\n            p->state = XZ_STATE_STREAM_INDEX_CRC;\n            p->indexSize += 4;\n            p->pos = 0;\n            Sha256_Final(&p->sha, (void *)digest32);\n            if (memcmp(digest32, p->shaDigest32, SHA256_DIGEST_SIZE) != 0)\n              return SZ_ERROR_CRC;\n          }\n        }\n        break;\n      }\n\n      case XZ_STATE_STREAM_INDEX_CRC:\n      {\n        if (p->pos < 4)\n        {\n          (*srcLen)++;\n          p->buf[p->pos++] = *src++;\n        }\n        else\n        {\n          const Byte *ptr = p->buf;\n          p->state = XZ_STATE_STREAM_FOOTER;\n          p->pos = 0;\n          if (CRC_GET_DIGEST(p->crc) != GetUi32a(ptr))\n            return SZ_ERROR_CRC;\n        }\n        break;\n      }\n\n      case XZ_STATE_STREAM_FOOTER:\n      {\n        unsigned cur = XZ_STREAM_FOOTER_SIZE - p->pos;\n        if (cur > srcRem)\n          cur = (unsigned)srcRem;\n        memcpy(p->buf + p->pos, src, cur);\n        p->pos += cur;\n        (*srcLen) += cur;\n        src += cur;\n        if (p->pos == XZ_STREAM_FOOTER_SIZE)\n        {\n          p->state = XZ_STATE_STREAM_PADDING;\n          p->numFinishedStreams++;\n          p->padSize = 0;\n          if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))\n            return SZ_ERROR_CRC;\n        }\n        break;\n      }\n\n      case XZ_STATE_STREAM_PADDING:\n      {\n        if (*src != 0)\n        {\n          if ((unsigned)p->padSize & 3)\n            return SZ_ERROR_NO_ARCHIVE;\n          p->pos = 0;\n          p->state = XZ_STATE_STREAM_HEADER;\n        }\n        else\n        {\n          (*srcLen)++;\n          src++;\n          p->padSize++;\n        }\n        break;\n      }\n      \n      case XZ_STATE_BLOCK: break; /* to disable GCC warning */\n      \n      default: return SZ_ERROR_FAIL;\n    }\n  }\n  /*\n  if (p->state == XZ_STATE_FINISHED)\n    *status = CODER_STATUS_FINISHED_WITH_MARK;\n  return SZ_OK;\n  */\n}\n\n\nSRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,\n    const Byte *src, SizeT *srcLen,\n    ECoderFinishMode finishMode, ECoderStatus *status)\n{\n  XzUnpacker_Init(p);\n  XzUnpacker_SetOutBuf(p, dest, *destLen);\n\n  return XzUnpacker_Code(p,\n      NULL, destLen,\n      src, srcLen, True,\n      finishMode, status);\n}\n\n\nBoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p)\n{\n  return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);\n}\n\nBoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)\n{\n  return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);\n}\n\nUInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)\n{\n  UInt64 num = 0;\n  if (p->state == XZ_STATE_STREAM_PADDING)\n    num = p->padSize;\n  else if (p->state == XZ_STATE_STREAM_HEADER)\n    num = p->padSize + p->pos;\n  return num;\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n#ifndef Z7_ST\n#include \"MtDec.h\"\n#endif\n\n\nvoid XzDecMtProps_Init(CXzDecMtProps *p)\n{\n  p->inBufSize_ST = 1 << 18;\n  p->outStep_ST = 1 << 20;\n  p->ignoreErrors = False;\n\n  #ifndef Z7_ST\n  p->numThreads = 1;\n  p->inBufSize_MT = 1 << 18;\n  p->memUseMax = sizeof(size_t) << 28;\n  #endif\n}\n\n\n\n#ifndef Z7_ST\n\n/* ---------- CXzDecMtThread ---------- */\n\ntypedef struct\n{\n  Byte *outBuf;\n  size_t outBufSize;\n  size_t outPreSize;\n  size_t inPreSize;\n  size_t inPreHeaderSize;\n  size_t blockPackSize_for_Index;  // including block header and checksum.\n  size_t blockPackTotal;  // including stream header, block header and checksum.\n  size_t inCodeSize;\n  size_t outCodeSize;\n  ECoderStatus status;\n  SRes codeRes;\n  BoolInt skipMode;\n  // BoolInt finishedWithMark;\n  EMtDecParseState parseState;\n  BoolInt parsing_Truncated;\n  BoolInt atBlockHeader;\n  CXzStreamFlags streamFlags;\n  // UInt64 numFinishedStreams\n  UInt64 numStreams;\n  UInt64 numTotalBlocks;\n  UInt64 numBlocks;\n\n  BoolInt dec_created;\n  CXzUnpacker dec;\n\n  Byte mtPad[1 << 7];\n} CXzDecMtThread;\n\n#endif\n\n\n/* ---------- CXzDecMt ---------- */\n\nstruct CXzDecMt\n{\n  CAlignOffsetAlloc alignOffsetAlloc;\n  ISzAllocPtr allocMid;\n\n  CXzDecMtProps props;\n  size_t unpackBlockMaxSize;\n  \n  ISeqInStreamPtr inStream;\n  ISeqOutStreamPtr outStream;\n  ICompressProgressPtr progress;\n\n  BoolInt finishMode;\n  BoolInt outSize_Defined;\n  UInt64 outSize;\n\n  UInt64 outProcessed;\n  UInt64 inProcessed;\n  UInt64 readProcessed;\n  BoolInt readWasFinished;\n  SRes readRes;\n  SRes writeRes;\n\n  Byte *outBuf;\n  size_t outBufSize;\n  Byte *inBuf;\n  size_t inBufSize;\n\n  CXzUnpacker dec;\n\n  ECoderStatus status;\n  SRes codeRes;\n\n  #ifndef Z7_ST\n  BoolInt mainDecoderWasCalled;\n  // int statErrorDefined;\n  int finishedDecoderIndex;\n\n  // global values that are used in Parse stage\n  CXzStreamFlags streamFlags;\n  // UInt64 numFinishedStreams\n  UInt64 numStreams;\n  UInt64 numTotalBlocks;\n  UInt64 numBlocks;\n\n  // UInt64 numBadBlocks;\n  SRes mainErrorCode;  // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage\n                       // it can be = SZ_ERROR_INPUT_EOF\n                       // it can be = SZ_ERROR_DATA, in some another cases\n  BoolInt isBlockHeaderState_Parse;\n  BoolInt isBlockHeaderState_Write;\n  UInt64 outProcessed_Parse;\n  BoolInt parsing_Truncated;\n\n  BoolInt mtc_WasConstructed;\n  CMtDec mtc;\n  CXzDecMtThread coders[MTDEC_THREADS_MAX];\n  #endif\n};\n\n\n\nCXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)\n{\n  CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));\n  if (!p)\n    return NULL;\n  \n  AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);\n  p->alignOffsetAlloc.baseAlloc = alloc;\n  p->alignOffsetAlloc.numAlignBits = 7;\n  p->alignOffsetAlloc.offset = 0;\n\n  p->allocMid = allocMid;\n\n  p->outBuf = NULL;\n  p->outBufSize = 0;\n  p->inBuf = NULL;\n  p->inBufSize = 0;\n\n  XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);\n\n  p->unpackBlockMaxSize = 0;\n\n  XzDecMtProps_Init(&p->props);\n\n  #ifndef Z7_ST\n  p->mtc_WasConstructed = False;\n  {\n    unsigned i;\n    for (i = 0; i < MTDEC_THREADS_MAX; i++)\n    {\n      CXzDecMtThread *coder = &p->coders[i];\n      coder->dec_created = False;\n      coder->outBuf = NULL;\n      coder->outBufSize = 0;\n    }\n  }\n  #endif\n\n  return (CXzDecMtHandle)p;\n}\n\n\n#ifndef Z7_ST\n\nstatic void XzDecMt_FreeOutBufs(CXzDecMt *p)\n{\n  unsigned i;\n  for (i = 0; i < MTDEC_THREADS_MAX; i++)\n  {\n    CXzDecMtThread *coder = &p->coders[i];\n    if (coder->outBuf)\n    {\n      ISzAlloc_Free(p->allocMid, coder->outBuf);\n      coder->outBuf = NULL;\n      coder->outBufSize = 0;\n    }\n  }\n  p->unpackBlockMaxSize = 0;\n}\n\n#endif\n\n\n\nstatic void XzDecMt_FreeSt(CXzDecMt *p)\n{\n  XzUnpacker_Free(&p->dec);\n  \n  if (p->outBuf)\n  {\n    ISzAlloc_Free(p->allocMid, p->outBuf);\n    p->outBuf = NULL;\n  }\n  p->outBufSize = 0;\n  \n  if (p->inBuf)\n  {\n    ISzAlloc_Free(p->allocMid, p->inBuf);\n    p->inBuf = NULL;\n  }\n  p->inBufSize = 0;\n}\n\n\n// #define GET_CXzDecMt_p  CXzDecMt *p = pp;\n\nvoid XzDecMt_Destroy(CXzDecMtHandle p)\n{\n  // GET_CXzDecMt_p\n\n  XzDecMt_FreeSt(p);\n\n  #ifndef Z7_ST\n\n  if (p->mtc_WasConstructed)\n  {\n    MtDec_Destruct(&p->mtc);\n    p->mtc_WasConstructed = False;\n  }\n  {\n    unsigned i;\n    for (i = 0; i < MTDEC_THREADS_MAX; i++)\n    {\n      CXzDecMtThread *t = &p->coders[i];\n      if (t->dec_created)\n      {\n        // we don't need to free dict here\n        XzUnpacker_Free(&t->dec);\n        t->dec_created = False;\n      }\n    }\n  }\n  XzDecMt_FreeOutBufs(p);\n\n  #endif\n\n  ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, p);\n}\n\n\n\n#ifndef Z7_ST\n\nstatic void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)\n{\n  CXzDecMt *me = (CXzDecMt *)obj;\n  CXzDecMtThread *coder = &me->coders[coderIndex];\n  size_t srcSize = cc->srcSize;\n\n  cc->srcSize = 0;\n  cc->outPos = 0;\n  cc->state = MTDEC_PARSE_CONTINUE;\n\n  cc->canCreateNewThread = True;\n\n  if (cc->startCall)\n  {\n    coder->outPreSize = 0;\n    coder->inPreSize = 0;\n    coder->inPreHeaderSize = 0;\n    coder->parseState = MTDEC_PARSE_CONTINUE;\n    coder->parsing_Truncated = False;\n    coder->skipMode = False;\n    coder->codeRes = SZ_OK;\n    coder->status = CODER_STATUS_NOT_SPECIFIED;\n    coder->inCodeSize = 0;\n    coder->outCodeSize = 0;\n\n    coder->numStreams = me->numStreams;\n    coder->numTotalBlocks = me->numTotalBlocks;\n    coder->numBlocks = me->numBlocks;\n\n    if (!coder->dec_created)\n    {\n      XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);\n      coder->dec_created = True;\n    }\n    \n    XzUnpacker_Init(&coder->dec);\n\n    if (me->isBlockHeaderState_Parse)\n    {\n      coder->dec.streamFlags = me->streamFlags;\n      coder->atBlockHeader = True;\n      XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);\n    }\n    else\n    {\n      coder->atBlockHeader = False;\n      me->isBlockHeaderState_Parse = True;\n    }\n\n    coder->dec.numStartedStreams = me->numStreams;\n    coder->dec.numTotalBlocks = me->numTotalBlocks;\n    coder->dec.numBlocks = me->numBlocks;\n  }\n\n  while (!coder->skipMode)\n  {\n    ECoderStatus status;\n    SRes res;\n    size_t srcSize2 = srcSize;\n    size_t destSize = (size_t)0 - 1;\n\n    coder->dec.parseMode = True;\n    coder->dec.headerParsedOk = False;\n    \n    PRF_STR_INT(\"Parse\", srcSize2)\n    \n    res = XzUnpacker_Code(&coder->dec,\n        NULL, &destSize,\n        cc->src, &srcSize2, cc->srcFinished,\n        CODER_FINISH_END, &status);\n    \n    // PRF(printf(\" res = %d, srcSize2 = %d\", res, (unsigned)srcSize2));\n    \n    coder->codeRes = res;\n    coder->status = status;\n    cc->srcSize += srcSize2;\n    srcSize -= srcSize2;\n    coder->inPreHeaderSize += srcSize2;\n    coder->inPreSize = coder->inPreHeaderSize;\n    \n    if (res != SZ_OK)\n    {\n      cc->state =\n      coder->parseState = MTDEC_PARSE_END;\n      /*\n      if (res == SZ_ERROR_MEM)\n        return res;\n      return SZ_OK;\n      */\n      return; // res;\n    }\n    \n    if (coder->dec.headerParsedOk)\n    {\n      const CXzBlock *block = &coder->dec.block;\n      if (XzBlock_HasUnpackSize(block)\n          // && block->unpackSize <= me->props.outBlockMax\n          && XzBlock_HasPackSize(block))\n      {\n        {\n          if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)\n          {\n            cc->state = MTDEC_PARSE_OVERFLOW;\n            return; // SZ_OK;\n          }\n        }\n        {\n        const UInt64 packSize = block->packSize;\n        const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);\n        const unsigned checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);\n        const UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;\n        // if (blockPackSum <= me->props.inBlockMax)\n        // unpackBlockMaxSize\n        {\n          coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);\n          coder->blockPackTotal = (size_t)blockPackSum;\n          coder->outPreSize = (size_t)block->unpackSize;\n          coder->streamFlags = coder->dec.streamFlags;\n          me->streamFlags = coder->dec.streamFlags;\n          coder->skipMode = True;\n          break;\n        }\n        }\n      }\n    }\n    else\n    // if (coder->inPreSize <= me->props.inBlockMax)\n    {\n      if (!cc->srcFinished)\n        return; // SZ_OK;\n      cc->state =\n      coder->parseState = MTDEC_PARSE_END;\n      return; // SZ_OK;\n    }\n    cc->state = MTDEC_PARSE_OVERFLOW;\n    return; // SZ_OK;\n  }\n\n  // ---------- skipMode ----------\n  {\n    UInt64 rem = coder->blockPackTotal - coder->inPreSize;\n    size_t cur = srcSize;\n    if (cur > rem)\n      cur = (size_t)rem;\n    cc->srcSize += cur;\n    coder->inPreSize += cur;\n    srcSize -= cur;\n\n    if (coder->inPreSize == coder->blockPackTotal)\n    {\n      if (srcSize == 0)\n      {\n        if (!cc->srcFinished)\n          return; // SZ_OK;\n        cc->state = MTDEC_PARSE_END;\n      }\n      else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block\n        cc->state = MTDEC_PARSE_END;\n      else\n      {\n        cc->state = MTDEC_PARSE_NEW;\n\n        {\n          size_t blockMax = me->unpackBlockMaxSize;\n          if (blockMax < coder->outPreSize)\n            blockMax = coder->outPreSize;\n          {\n            UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;\n            if (me->props.memUseMax < required)\n              cc->canCreateNewThread = False;\n          }\n        }\n\n        if (me->outSize_Defined)\n        {\n          // next block can be zero size\n          const UInt64 rem2 = me->outSize - me->outProcessed_Parse;\n          if (rem2 < coder->outPreSize)\n          {\n            coder->parsing_Truncated = True;\n            cc->state = MTDEC_PARSE_END;\n          }\n          me->outProcessed_Parse += coder->outPreSize;\n        }\n      }\n    }\n    else if (cc->srcFinished)\n      cc->state = MTDEC_PARSE_END;\n    else\n      return; // SZ_OK;\n\n    coder->parseState = cc->state;\n    cc->outPos = coder->outPreSize;\n    \n    me->numStreams = coder->dec.numStartedStreams;\n    me->numTotalBlocks = coder->dec.numTotalBlocks;\n    me->numBlocks = coder->dec.numBlocks + 1;\n    return; // SZ_OK;\n  }\n}\n\n\nstatic SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)\n{\n  CXzDecMt *me = (CXzDecMt *)pp;\n  CXzDecMtThread *coder = &me->coders[coderIndex];\n  Byte *dest;\n\n  if (!coder->dec.headerParsedOk)\n    return SZ_OK;\n\n  dest = coder->outBuf;\n\n  if (!dest || coder->outBufSize < coder->outPreSize)\n  {\n    if (dest)\n    {\n      ISzAlloc_Free(me->allocMid, dest);\n      coder->outBuf = NULL;\n      coder->outBufSize = 0;\n    }\n    {\n      size_t outPreSize = coder->outPreSize;\n      if (outPreSize == 0)\n        outPreSize = 1;\n      dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);\n    }\n    if (!dest)\n      return SZ_ERROR_MEM;\n    coder->outBuf = dest;\n    coder->outBufSize = coder->outPreSize;\n\n    if (coder->outBufSize > me->unpackBlockMaxSize)\n      me->unpackBlockMaxSize = coder->outBufSize;\n  }\n\n  // return SZ_ERROR_MEM;\n\n  XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);\n\n  {\n    SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);\n    // res = SZ_ERROR_UNSUPPORTED; // to test\n    coder->codeRes = res;\n    if (res != SZ_OK)\n    {\n      // if (res == SZ_ERROR_MEM) return res;\n      if (me->props.ignoreErrors && res != SZ_ERROR_MEM)\n        return SZ_OK;\n      return res;\n    }\n  }\n\n  return SZ_OK;\n}\n\n\nstatic SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,\n    const Byte *src, size_t srcSize, int srcFinished,\n    // int finished, int blockFinished,\n    UInt64 *inCodePos, UInt64 *outCodePos, int *stop)\n{\n  CXzDecMt *me = (CXzDecMt *)pp;\n  CXzDecMtThread *coder = &me->coders[coderIndex];\n\n  *inCodePos = coder->inCodeSize;\n  *outCodePos = coder->outCodeSize;\n  *stop = True;\n\n  if (srcSize > coder->inPreSize - coder->inCodeSize)\n    return SZ_ERROR_FAIL;\n  \n  if (coder->inCodeSize < coder->inPreHeaderSize)\n  {\n    size_t step = coder->inPreHeaderSize - coder->inCodeSize;\n    if (step > srcSize)\n      step = srcSize;\n    src += step;\n    srcSize -= step;\n    coder->inCodeSize += step;\n    *inCodePos = coder->inCodeSize;\n    if (coder->inCodeSize < coder->inPreHeaderSize)\n    {\n      *stop = False;\n      return SZ_OK;\n    }\n  }\n\n  if (!coder->dec.headerParsedOk)\n    return SZ_OK;\n  if (!coder->outBuf)\n    return SZ_OK;\n\n  if (coder->codeRes == SZ_OK)\n  {\n    ECoderStatus status;\n    SRes res;\n    size_t srcProcessed = srcSize;\n    size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;\n\n    // PRF(printf(\"\\nCallback_Code: Code %d %d\\n\", (unsigned)srcSize, (unsigned)outSizeCur));\n\n    res = XzUnpacker_Code(&coder->dec,\n        NULL, &outSizeCur,\n        src, &srcProcessed, srcFinished,\n        // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,\n        CODER_FINISH_END,\n        &status);\n\n    // PRF(printf(\" res = %d, srcSize2 = %d, outSizeCur = %d\", res, (unsigned)srcProcessed, (unsigned)outSizeCur));\n\n    coder->codeRes = res;\n    coder->status = status;\n    coder->inCodeSize += srcProcessed;\n    coder->outCodeSize = coder->dec.outDataWritten;\n    *inCodePos = coder->inCodeSize;\n    *outCodePos = coder->outCodeSize;\n\n    if (res == SZ_OK)\n    {\n      if (srcProcessed == srcSize)\n        *stop = False;\n      return SZ_OK;\n    }\n  }\n\n  if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)\n  {\n    *inCodePos = coder->inPreSize;\n    *outCodePos = coder->outPreSize;\n    return SZ_OK;\n  }\n  return coder->codeRes;\n}\n\n\n#define XZDECMT_STREAM_WRITE_STEP (1 << 24)\n\nstatic SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,\n    BoolInt needWriteToStream,\n    const Byte *src, size_t srcSize, BoolInt isCross,\n    // int srcFinished,\n    BoolInt *needContinue,\n    BoolInt *canRecode)\n{\n  CXzDecMt *me = (CXzDecMt *)pp;\n  const CXzDecMtThread *coder = &me->coders[coderIndex];\n\n  // PRF(printf(\"\\nWrite processed = %d srcSize = %d\\n\", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));\n  \n  *needContinue = False;\n  *canRecode = True;\n  \n  if (!needWriteToStream)\n    return SZ_OK;\n\n  if (!coder->dec.headerParsedOk || !coder->outBuf)\n  {\n    if (me->finishedDecoderIndex < 0)\n      me->finishedDecoderIndex = (int)coderIndex;\n    return SZ_OK;\n  }\n\n  if (me->finishedDecoderIndex >= 0)\n    return SZ_OK;\n\n  me->mtc.inProcessed += coder->inCodeSize;\n\n  *canRecode = False;\n\n  {\n    SRes res;\n    size_t size = coder->outCodeSize;\n    Byte *data = coder->outBuf;\n    \n    // we use in me->dec: sha, numBlocks, indexSize\n\n    if (!me->isBlockHeaderState_Write)\n    {\n      XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);\n      me->dec.decodeOnlyOneBlock = False;\n      me->dec.numStartedStreams = coder->dec.numStartedStreams;\n      me->dec.streamFlags = coder->streamFlags;\n\n      me->isBlockHeaderState_Write = True;\n    }\n    \n    me->dec.numTotalBlocks = coder->dec.numTotalBlocks;\n    XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);\n    \n    if (coder->outPreSize != size)\n    {\n      if (me->props.ignoreErrors)\n      {\n        memset(data + size, 0, coder->outPreSize - size);\n        size = coder->outPreSize;\n      }\n      // me->numBadBlocks++;\n      if (me->mainErrorCode == SZ_OK)\n      {\n        if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)\n          me->mainErrorCode = SZ_ERROR_INPUT_EOF;\n        else\n          me->mainErrorCode = SZ_ERROR_DATA;\n      }\n    }\n    \n    if (me->writeRes != SZ_OK)\n      return me->writeRes;\n\n    res = SZ_OK;\n    {\n      if (me->outSize_Defined)\n      {\n        const UInt64 rem = me->outSize - me->outProcessed;\n        if (size > rem)\n          size = (SizeT)rem;\n      }\n\n      for (;;)\n      {\n        size_t cur = size;\n        size_t written;\n        if (cur > XZDECMT_STREAM_WRITE_STEP)\n          cur = XZDECMT_STREAM_WRITE_STEP;\n\n        written = ISeqOutStream_Write(me->outStream, data, cur);\n\n        // PRF(printf(\"\\nWritten ask = %d written = %d\\n\", (unsigned)cur, (unsigned)written));\n        \n        me->outProcessed += written;\n        if (written != cur)\n        {\n          me->writeRes = SZ_ERROR_WRITE;\n          res = me->writeRes;\n          break;\n        }\n        data += cur;\n        size -= cur;\n        // PRF_STR_INT(\"Written size =\", size)\n        if (size == 0)\n          break;\n        res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);\n        if (res != SZ_OK)\n          break;\n      }\n    }\n\n    if (coder->codeRes != SZ_OK)\n      if (!me->props.ignoreErrors)\n      {\n        me->finishedDecoderIndex = (int)coderIndex;\n        return res;\n      }\n\n    RINOK(res)\n\n    if (coder->inPreSize != coder->inCodeSize\n        || coder->blockPackTotal != coder->inCodeSize)\n    {\n      me->finishedDecoderIndex = (int)coderIndex;\n      return SZ_OK;\n    }\n\n    if (coder->parseState != MTDEC_PARSE_END)\n    {\n      *needContinue = True;\n      return SZ_OK;\n    }\n  }\n\n  // (coder->state == MTDEC_PARSE_END) means that there are no other working threads\n  // so we can use mtc variables without lock\n\n  PRF_STR_INT(\"Write MTDEC_PARSE_END\", me->mtc.inProcessed)\n\n  me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;\n  {\n    CXzUnpacker *dec = &me->dec;\n    \n    PRF_STR_INT(\"PostSingle\", srcSize)\n    \n    {\n      size_t srcProcessed = srcSize;\n      ECoderStatus status;\n      size_t outSizeCur = 0;\n      SRes res;\n      \n      // dec->decodeOnlyOneBlock = False;\n      dec->decodeToStreamSignature = True;\n\n      me->mainDecoderWasCalled = True;\n\n      if (coder->parsing_Truncated)\n      {\n        me->parsing_Truncated = True;\n        return SZ_OK;\n      }\n      \n      /*\n      We have processed all xz-blocks of stream,\n      And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where\n      (src) is a pointer to xz-Index structure.\n      We finish reading of current xz-Stream, including Zero padding after xz-Stream.\n      We exit, if we reach extra byte (first byte of new-Stream or another data).\n      But we don't update input stream pointer for that new extra byte.\n      If extra byte is not correct first byte of xz-signature,\n      we have SZ_ERROR_NO_ARCHIVE error here.\n      */\n\n      res = XzUnpacker_Code(dec,\n          NULL, &outSizeCur,\n          src, &srcProcessed,\n          me->mtc.readWasFinished, // srcFinished\n          CODER_FINISH_END, // CODER_FINISH_ANY,\n          &status);\n\n      // res = SZ_ERROR_ARCHIVE; // for failure test\n      \n      me->status = status;\n      me->codeRes = res;\n\n      if (isCross)\n        me->mtc.crossStart += srcProcessed;\n\n      me->mtc.inProcessed += srcProcessed;\n      me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;\n\n      srcSize -= srcProcessed;\n      src += srcProcessed;\n\n      if (res != SZ_OK)\n      {\n        return SZ_OK;\n        // return res;\n      }\n      \n      if (dec->state == XZ_STATE_STREAM_HEADER)\n      {\n        *needContinue = True;\n        me->isBlockHeaderState_Parse = False;\n        me->isBlockHeaderState_Write = False;\n\n        if (!isCross)\n        {\n          Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);\n          if (!crossBuf)\n            return SZ_ERROR_MEM;\n          if (srcSize != 0)\n            memcpy(crossBuf, src, srcSize);\n          me->mtc.crossStart = 0;\n          me->mtc.crossEnd = srcSize;\n        }\n\n        PRF_STR_INT(\"XZ_STATE_STREAM_HEADER crossEnd = \", (unsigned)me->mtc.crossEnd)\n\n        return SZ_OK;\n      }\n      \n      if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0)\n      {\n        return SZ_ERROR_FAIL;\n      }\n      \n      if (me->mtc.readWasFinished)\n      {\n        return SZ_OK;\n      }\n    }\n    \n    {\n      size_t inPos;\n      size_t inLim;\n      // const Byte *inData;\n      UInt64 inProgressPrev = me->mtc.inProcessed;\n      \n      // XzDecMt_Prepare_InBuf_ST(p);\n      Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);\n      if (!crossBuf)\n        return SZ_ERROR_MEM;\n      \n      inPos = 0;\n      inLim = 0;\n      \n      // inData = crossBuf;\n      \n      for (;;)\n      {\n        SizeT inProcessed;\n        SizeT outProcessed;\n        ECoderStatus status;\n        SRes res;\n        \n        if (inPos == inLim)\n        {\n          if (!me->mtc.readWasFinished)\n          {\n            inPos = 0;\n            inLim = me->mtc.inBufSize;\n            me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim);\n            me->mtc.readProcessed += inLim;\n            if (inLim == 0 || me->mtc.readRes != SZ_OK)\n              me->mtc.readWasFinished = True;\n          }\n        }\n        \n        inProcessed = inLim - inPos;\n        outProcessed = 0;\n\n        res = XzUnpacker_Code(dec,\n            NULL, &outProcessed,\n            crossBuf + inPos, &inProcessed,\n            (inProcessed == 0), // srcFinished\n            CODER_FINISH_END, &status);\n        \n        me->codeRes = res;\n        me->status = status;\n        inPos += inProcessed;\n        me->mtc.inProcessed += inProcessed;\n        me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;\n\n        if (res != SZ_OK)\n        {\n          return SZ_OK;\n          // return res;\n        }\n\n        if (dec->state == XZ_STATE_STREAM_HEADER)\n        {\n          *needContinue = True;\n          me->mtc.crossStart = inPos;\n          me->mtc.crossEnd = inLim;\n          me->isBlockHeaderState_Parse = False;\n          me->isBlockHeaderState_Write = False;\n          return SZ_OK;\n        }\n        \n        if (status != CODER_STATUS_NEEDS_MORE_INPUT)\n          return SZ_ERROR_FAIL;\n        \n        if (me->mtc.progress)\n        {\n          UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;\n          if (inDelta >= (1 << 22))\n          {\n            RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress))\n            inProgressPrev = me->mtc.inProcessed;\n          }\n        }\n        if (me->mtc.readWasFinished)\n          return SZ_OK;\n      }\n    }\n  }\n}\n\n\n#endif\n\n\n\nvoid XzStatInfo_Clear(CXzStatInfo *p)\n{\n  p->InSize = 0;\n  p->OutSize = 0;\n  \n  p->NumStreams = 0;\n  p->NumBlocks = 0;\n  \n  p->UnpackSize_Defined = False;\n  \n  p->NumStreams_Defined = False;\n  p->NumBlocks_Defined = False;\n  \n  p->DataAfterEnd = False;\n  p->DecodingTruncated = False;\n  \n  p->DecodeRes = SZ_OK;\n  p->ReadRes = SZ_OK;\n  p->ProgressRes = SZ_OK;\n\n  p->CombinedRes = SZ_OK;\n  p->CombinedRes_Type = SZ_OK;\n}\n\n\n\n/*\n  XzDecMt_Decode_ST() can return SZ_OK or the following errors\n     - SZ_ERROR_MEM for memory allocation error\n     - error from XzUnpacker_Code() function\n     - SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case\n     - ICompressProgress::Progress() error,  stat->CombinedRes_Type = SZ_ERROR_PROGRESS.\n  But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors.\n  ISeqInStream::Read() result is set to p->readRes.\n  also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS.\n*/\n\nstatic SRes XzDecMt_Decode_ST(CXzDecMt *p\n    #ifndef Z7_ST\n    , BoolInt tMode\n    #endif\n    , CXzStatInfo *stat)\n{\n  size_t outPos;\n  size_t inPos, inLim;\n  const Byte *inData;\n  UInt64 inPrev, outPrev;\n\n  CXzUnpacker *dec;\n\n  #ifndef Z7_ST\n  if (tMode)\n  {\n    XzDecMt_FreeOutBufs(p);\n    tMode = (BoolInt)MtDec_PrepareRead(&p->mtc);\n  }\n  #endif\n\n  if (!p->outBuf || p->outBufSize != p->props.outStep_ST)\n  {\n    ISzAlloc_Free(p->allocMid, p->outBuf);\n    p->outBufSize = 0;\n    p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);\n    if (!p->outBuf)\n      return SZ_ERROR_MEM;\n    p->outBufSize = p->props.outStep_ST;\n  }\n\n  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)\n  {\n    ISzAlloc_Free(p->allocMid, p->inBuf);\n    p->inBufSize = 0;\n    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);\n    if (!p->inBuf)\n      return SZ_ERROR_MEM;\n    p->inBufSize = p->props.inBufSize_ST;\n  }\n\n  dec = &p->dec;\n  dec->decodeToStreamSignature = False;\n  // dec->decodeOnlyOneBlock = False;\n\n  XzUnpacker_SetOutBuf(dec, NULL, 0);\n\n  inPrev = p->inProcessed;\n  outPrev = p->outProcessed;\n\n  inPos = 0;\n  inLim = 0;\n  inData = NULL;\n  outPos = 0;\n\n  for (;;)\n  {\n    SizeT outSize;\n    BoolInt finished;\n    ECoderFinishMode finishMode;\n    SizeT inProcessed;\n    ECoderStatus status;\n    SRes res;\n\n    SizeT outProcessed;\n\n\n\n    if (inPos == inLim)\n    {\n      #ifndef Z7_ST\n      if (tMode)\n      {\n        inData = MtDec_Read(&p->mtc, &inLim);\n        inPos = 0;\n        if (inData)\n          continue;\n        tMode = False;\n        inLim = 0;\n      }\n      #endif\n      \n      if (!p->readWasFinished)\n      {\n        inPos = 0;\n        inLim = p->inBufSize;\n        inData = p->inBuf;\n        p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim);\n        p->readProcessed += inLim;\n        if (inLim == 0 || p->readRes != SZ_OK)\n          p->readWasFinished = True;\n      }\n    }\n\n    outSize = p->props.outStep_ST - outPos;\n\n    finishMode = CODER_FINISH_ANY;\n    if (p->outSize_Defined)\n    {\n      const UInt64 rem = p->outSize - p->outProcessed;\n      if (outSize >= rem)\n      {\n        outSize = (SizeT)rem;\n        if (p->finishMode)\n          finishMode = CODER_FINISH_END;\n      }\n    }\n\n    inProcessed = inLim - inPos;\n    outProcessed = outSize;\n\n    res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,\n        inData + inPos, &inProcessed,\n        (inPos == inLim), // srcFinished\n        finishMode, &status);\n\n    p->codeRes = res;\n    p->status = status;\n\n    inPos += inProcessed;\n    outPos += outProcessed;\n    p->inProcessed += inProcessed;\n    p->outProcessed += outProcessed;\n\n    finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);\n\n    if (finished || outProcessed >= outSize)\n      if (outPos != 0)\n      {\n        const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);\n        // p->outProcessed += written; // 21.01: BUG fixed\n        if (written != outPos)\n        {\n          stat->CombinedRes_Type = SZ_ERROR_WRITE;\n          return SZ_ERROR_WRITE;\n        }\n        outPos = 0;\n      }\n\n    if (p->progress && res == SZ_OK)\n    {\n      if (p->inProcessed - inPrev >= (1 << 22) ||\n          p->outProcessed - outPrev >= (1 << 22))\n      {\n        res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);\n        if (res != SZ_OK)\n        {\n          stat->CombinedRes_Type = SZ_ERROR_PROGRESS;\n          stat->ProgressRes = res;\n          return res;\n        }\n        inPrev = p->inProcessed;\n        outPrev = p->outProcessed;\n      }\n    }\n\n    if (finished)\n    {\n      // p->codeRes is preliminary error from XzUnpacker_Code.\n      // and it can be corrected later as final result\n      // so we return SZ_OK here instead of (res);\n      return SZ_OK;\n      // return res;\n    }\n  }\n}\n\n\n\n/*\nXzStatInfo_SetStat() transforms\n    CXzUnpacker return code and status to combined CXzStatInfo results.\n    it can convert SZ_OK to SZ_ERROR_INPUT_EOF\n    it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1)\n*/\n\nstatic void XzStatInfo_SetStat(const CXzUnpacker *dec,\n    int finishMode,\n    // UInt64 readProcessed,\n    UInt64 inProcessed,\n    SRes res,                     // it's result from CXzUnpacker unpacker\n    ECoderStatus status,\n    BoolInt decodingTruncated,\n    CXzStatInfo *stat)\n{\n  UInt64 extraSize;\n  \n  stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);\n  stat->InSize = inProcessed;\n  stat->NumStreams = dec->numStartedStreams;\n  stat->NumBlocks = dec->numTotalBlocks;\n  \n  stat->UnpackSize_Defined = True;\n  stat->NumStreams_Defined = True;\n  stat->NumBlocks_Defined = True;\n  \n  extraSize = XzUnpacker_GetExtraSize(dec);\n  \n  if (res == SZ_OK)\n  {\n    if (status == CODER_STATUS_NEEDS_MORE_INPUT)\n    {\n      // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams\n      // any extra data is part of correct data\n      extraSize = 0;\n      // if xz stream was not finished, then we need more data\n      if (!XzUnpacker_IsStreamWasFinished(dec))\n        res = SZ_ERROR_INPUT_EOF;\n    }\n    else\n    {\n      // CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding\n      // so he we have (status == CODER_STATUS_NOT_FINISHED)\n      // if (status != CODER_STATUS_FINISHED_WITH_MARK)\n      if (!decodingTruncated || finishMode)\n        res = SZ_ERROR_DATA;\n    }\n  }\n  else if (res == SZ_ERROR_NO_ARCHIVE)\n  {\n    /*\n    SZ_ERROR_NO_ARCHIVE is possible for 2 states:\n      XZ_STATE_STREAM_HEADER  - if bad signature or bad CRC\n      XZ_STATE_STREAM_PADDING - if non-zero padding data\n    extraSize and inProcessed don't include \"bad\" byte\n    */\n    // if (inProcessed == extraSize), there was no any good xz stream header, and we keep error\n    if (inProcessed != extraSize) // if there were good xz streams before error\n    {\n      // if (extraSize != 0 || readProcessed != inProcessed)\n      {\n        // he we suppose that all xz streams were finsihed OK, and we have\n        // some extra data after all streams\n        stat->DataAfterEnd = True;\n        res = SZ_OK;\n      }\n    }\n  }\n  \n  if (stat->DecodeRes == SZ_OK)\n    stat->DecodeRes = res;\n\n  stat->InSize -= extraSize;\n}\n\n\n\nSRes XzDecMt_Decode(CXzDecMtHandle p,\n    const CXzDecMtProps *props,\n    const UInt64 *outDataSize, int finishMode,\n    ISeqOutStreamPtr outStream,\n    // Byte *outBuf, size_t *outBufSize,\n    ISeqInStreamPtr inStream,\n    // const Byte *inData, size_t inDataSize,\n    CXzStatInfo *stat,\n    int *isMT,\n    ICompressProgressPtr progress)\n{\n  // GET_CXzDecMt_p\n  #ifndef Z7_ST\n  BoolInt tMode;\n  #endif\n\n  XzStatInfo_Clear(stat);\n\n  p->props = *props;\n\n  p->inStream = inStream;\n  p->outStream = outStream;\n  p->progress = progress;\n  // p->stat = stat;\n\n  p->outSize = 0;\n  p->outSize_Defined = False;\n  if (outDataSize)\n  {\n    p->outSize_Defined = True;\n    p->outSize = *outDataSize;\n  }\n\n  p->finishMode = (BoolInt)finishMode;\n\n  // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test\n\n  p->writeRes = SZ_OK;\n  p->outProcessed = 0;\n  p->inProcessed = 0;\n  p->readProcessed = 0;\n  p->readWasFinished = False;\n  p->readRes = SZ_OK;\n\n  p->codeRes = SZ_OK;\n  p->status = CODER_STATUS_NOT_SPECIFIED;\n\n  XzUnpacker_Init(&p->dec);\n\n  *isMT = False;\n\n    /*\n    p->outBuf = NULL;\n    p->outBufSize = 0;\n    if (!outStream)\n    {\n      p->outBuf = outBuf;\n      p->outBufSize = *outBufSize;\n      *outBufSize = 0;\n    }\n    */\n\n  \n  #ifndef Z7_ST\n\n  p->isBlockHeaderState_Parse = False;\n  p->isBlockHeaderState_Write = False;\n  // p->numBadBlocks = 0;\n  p->mainErrorCode = SZ_OK;\n  p->mainDecoderWasCalled = False;\n\n  tMode = False;\n\n  if (p->props.numThreads > 1)\n  {\n    IMtDecCallback2 vt;\n    BoolInt needContinue;\n    SRes res;\n    // we just free ST buffers here\n    // but we still keep state variables, that was set in XzUnpacker_Init()\n    XzDecMt_FreeSt(p);\n\n    p->outProcessed_Parse = 0;\n    p->parsing_Truncated = False;\n\n    p->numStreams = 0;\n    p->numTotalBlocks = 0;\n    p->numBlocks = 0;\n    p->finishedDecoderIndex = -1;\n\n    if (!p->mtc_WasConstructed)\n    {\n      p->mtc_WasConstructed = True;\n      MtDec_Construct(&p->mtc);\n    }\n    \n    p->mtc.mtCallback = &vt;\n    p->mtc.mtCallbackObject = p;\n\n    p->mtc.progress = progress;\n    p->mtc.inStream = inStream;\n    p->mtc.alloc = &p->alignOffsetAlloc.vt;\n    // p->mtc.inData = inData;\n    // p->mtc.inDataSize = inDataSize;\n    p->mtc.inBufSize = p->props.inBufSize_MT;\n    // p->mtc.inBlockMax = p->props.inBlockMax;\n    p->mtc.numThreadsMax = p->props.numThreads;\n\n    *isMT = True;\n\n    vt.Parse = XzDecMt_Callback_Parse;\n    vt.PreCode = XzDecMt_Callback_PreCode;\n    vt.Code = XzDecMt_Callback_Code;\n    vt.Write = XzDecMt_Callback_Write;\n\n\n    res = MtDec_Code(&p->mtc);\n\n\n    stat->InSize = p->mtc.inProcessed;\n    \n    p->inProcessed = p->mtc.inProcessed;\n    p->readRes = p->mtc.readRes;\n    p->readWasFinished = p->mtc.readWasFinished;\n    p->readProcessed = p->mtc.readProcessed;\n    \n    tMode = True;\n    needContinue = False;\n    \n    if (res == SZ_OK)\n    {\n      if (p->mtc.mtProgress.res != SZ_OK)\n      {\n        res = p->mtc.mtProgress.res;\n        stat->ProgressRes = res;\n        stat->CombinedRes_Type = SZ_ERROR_PROGRESS;\n      }\n      else\n        needContinue = p->mtc.needContinue;\n    }\n    \n    if (!needContinue)\n    {\n      {\n        SRes codeRes;\n        BoolInt truncated = False;\n        ECoderStatus status;\n        const CXzUnpacker *dec;\n\n        stat->OutSize = p->outProcessed;\n       \n        if (p->finishedDecoderIndex >= 0)\n        {\n          const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];\n          codeRes = coder->codeRes;\n          dec = &coder->dec;\n          status = coder->status;\n        }\n        else if (p->mainDecoderWasCalled)\n        {\n          codeRes = p->codeRes;\n          dec = &p->dec;\n          status = p->status;\n          truncated = p->parsing_Truncated;\n        }\n        else\n          return SZ_ERROR_FAIL;\n\n        if (p->mainErrorCode != SZ_OK)\n          stat->DecodeRes = p->mainErrorCode;\n\n        XzStatInfo_SetStat(dec, p->finishMode,\n            // p->mtc.readProcessed,\n            p->mtc.inProcessed,\n            codeRes, status,\n            truncated,\n            stat);\n      }\n\n      if (res == SZ_OK)\n      {\n        stat->ReadRes = p->mtc.readRes;\n\n        if (p->writeRes != SZ_OK)\n        {\n          res = p->writeRes;\n          stat->CombinedRes_Type = SZ_ERROR_WRITE;\n        }\n        else if (p->mtc.readRes != SZ_OK\n            // && p->mtc.inProcessed == p->mtc.readProcessed\n            && stat->DecodeRes == SZ_ERROR_INPUT_EOF)\n        {\n          res = p->mtc.readRes;\n          stat->CombinedRes_Type = SZ_ERROR_READ;\n        }\n        else if (stat->DecodeRes != SZ_OK)\n          res = stat->DecodeRes;\n      }\n      \n      stat->CombinedRes = res;\n      if (stat->CombinedRes_Type == SZ_OK)\n        stat->CombinedRes_Type = res;\n      return res;\n    }\n\n    PRF_STR(\"----- decoding ST -----\")\n  }\n\n  #endif\n\n\n  *isMT = False;\n\n  {\n    SRes res = XzDecMt_Decode_ST(p\n        #ifndef Z7_ST\n        , tMode\n        #endif\n        , stat\n        );\n\n    #ifndef Z7_ST\n    // we must set error code from MT decoding at first\n    if (p->mainErrorCode != SZ_OK)\n      stat->DecodeRes = p->mainErrorCode;\n    #endif\n\n    XzStatInfo_SetStat(&p->dec,\n        p->finishMode,\n        // p->readProcessed,\n        p->inProcessed,\n        p->codeRes, p->status,\n        False, // truncated\n        stat);\n\n    stat->ReadRes = p->readRes;\n\n    if (res == SZ_OK)\n    {\n      if (p->readRes != SZ_OK\n          // && p->inProcessed == p->readProcessed\n          && stat->DecodeRes == SZ_ERROR_INPUT_EOF)\n      {\n        // we set read error as combined error, only if that error was the reason\n        // of decoding problem\n        res = p->readRes;\n        stat->CombinedRes_Type = SZ_ERROR_READ;\n      }\n      else if (stat->DecodeRes != SZ_OK)\n        res = stat->DecodeRes;\n    }\n\n    stat->CombinedRes = res;\n    if (stat->CombinedRes_Type == SZ_OK)\n      stat->CombinedRes_Type = res;\n    return res;\n  }\n}\n\n#undef PRF\n#undef PRF_STR\n#undef PRF_STR_INT_2\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/XzEnc.c",
    "content": "﻿/* XzEnc.c -- Xz Encode\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"7zCrc.h\"\n#include \"Bra.h\"\n#include \"CpuArch.h\"\n\n#ifdef USE_SUBBLOCK\n#include \"Bcj3Enc.c\"\n#include \"SbFind.c\"\n#include \"SbEnc.c\"\n#endif\n\n#include \"XzEnc.h\"\n\n// #define Z7_ST\n\n#ifndef Z7_ST\n#include \"MtCoder.h\"\n#else\n#define MTCODER_THREADS_MAX 1\n#define MTCODER_BLOCKS_MAX 1\n#endif\n\n#define XZ_GET_PAD_SIZE(dataSize) ((4 - ((unsigned)(dataSize) & 3)) & 3)\n\n#define XZ_CHECK_SIZE_MAX 64\n/* max pack size for LZMA2 block + pad4 + check_size: */\n#define XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize) ((unpackSize) + ((unpackSize) >> 10) + 16 + XZ_CHECK_SIZE_MAX)\n\n#define XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(unpackSize) (XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(unpackSize))\n\n\n// #define XzBlock_ClearFlags(p)       (p)->flags = 0;\n#define XzBlock_ClearFlags_SetNumFilters(p, n) (p)->flags = (Byte)((n) - 1);\n#define XzBlock_SetHasPackSize(p)   (p)->flags |= XZ_BF_PACK_SIZE;\n#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE;\n\n\nstatic SRes WriteBytes(ISeqOutStreamPtr s, const void *buf, size_t size)\n{\n  return (ISeqOutStream_Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;\n}\n\nstatic SRes WriteBytes_UpdateCrc(ISeqOutStreamPtr s, const void *buf, size_t size, UInt32 *crc)\n{\n  *crc = CrcUpdate(*crc, buf, size);\n  return WriteBytes(s, buf, size);\n}\n\n\nstatic SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStreamPtr s)\n{\n  UInt32 crc;\n  Byte header[XZ_STREAM_HEADER_SIZE];\n  memcpy(header, XZ_SIG, XZ_SIG_SIZE);\n  header[XZ_SIG_SIZE] = (Byte)(f >> 8);\n  header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF);\n  crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE);\n  SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc)\n  return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);\n}\n\n\nstatic SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStreamPtr s)\n{\n  Byte header[XZ_BLOCK_HEADER_SIZE_MAX];\n\n  unsigned pos = 1;\n  unsigned numFilters, i;\n  header[pos++] = p->flags;\n\n  if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);\n  if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);\n  numFilters = XzBlock_GetNumFilters(p);\n  \n  for (i = 0; i < numFilters; i++)\n  {\n    const CXzFilter *f = &p->filters[i];\n    pos += Xz_WriteVarInt(header + pos, f->id);\n    pos += Xz_WriteVarInt(header + pos, f->propsSize);\n    memcpy(header + pos, f->props, f->propsSize);\n    pos += f->propsSize;\n  }\n\n  while ((pos & 3) != 0)\n    header[pos++] = 0;\n\n  header[0] = (Byte)(pos >> 2);\n  SetUi32(header + pos, CrcCalc(header, pos))\n  return WriteBytes(s, header, pos + 4);\n}\n\n\n\n\ntypedef struct\n{\n  size_t numBlocks;\n  size_t size;\n  size_t allocated;\n  Byte *blocks;\n} CXzEncIndex;\n\n\nstatic void XzEncIndex_Construct(CXzEncIndex *p)\n{\n  p->numBlocks = 0;\n  p->size = 0;\n  p->allocated = 0;\n  p->blocks = NULL;\n}\n\nstatic void XzEncIndex_Init(CXzEncIndex *p)\n{\n  p->numBlocks = 0;\n  p->size = 0;\n}\n\nstatic void XzEncIndex_Free(CXzEncIndex *p, ISzAllocPtr alloc)\n{\n  if (p->blocks)\n  {\n    ISzAlloc_Free(alloc, p->blocks);\n    p->blocks = NULL;\n  }\n  p->numBlocks = 0;\n  p->size = 0;\n  p->allocated = 0;\n}\n\n\nstatic SRes XzEncIndex_ReAlloc(CXzEncIndex *p, size_t newSize, ISzAllocPtr alloc)\n{\n  Byte *blocks = (Byte *)ISzAlloc_Alloc(alloc, newSize);\n  if (!blocks)\n    return SZ_ERROR_MEM;\n  if (p->size != 0)\n    memcpy(blocks, p->blocks, p->size);\n  if (p->blocks)\n    ISzAlloc_Free(alloc, p->blocks);\n  p->blocks = blocks;\n  p->allocated = newSize;\n  return SZ_OK;\n}\n\n\nstatic SRes XzEncIndex_PreAlloc(CXzEncIndex *p, UInt64 numBlocks, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc)\n{\n  UInt64 pos;\n  {\n    Byte buf[32];\n    unsigned pos2 = Xz_WriteVarInt(buf, totalSize);\n    pos2 += Xz_WriteVarInt(buf + pos2, unpackSize);\n    pos = numBlocks * pos2;\n  }\n  \n  if (pos <= p->allocated - p->size)\n    return SZ_OK;\n  {\n    UInt64 newSize64 = p->size + pos;\n    size_t newSize = (size_t)newSize64;\n    if (newSize != newSize64)\n      return SZ_ERROR_MEM;\n    return XzEncIndex_ReAlloc(p, newSize, alloc);\n  }\n}\n\n\nstatic SRes XzEncIndex_AddIndexRecord(CXzEncIndex *p, UInt64 unpackSize, UInt64 totalSize, ISzAllocPtr alloc)\n{\n  Byte buf[32];\n  unsigned pos = Xz_WriteVarInt(buf, totalSize);\n  pos += Xz_WriteVarInt(buf + pos, unpackSize);\n\n  if (pos > p->allocated - p->size)\n  {\n    size_t newSize = p->allocated * 2 + 16 * 2;\n    if (newSize < p->size + pos)\n      return SZ_ERROR_MEM;\n    RINOK(XzEncIndex_ReAlloc(p, newSize, alloc))\n  }\n  memcpy(p->blocks + p->size, buf, pos);\n  p->size += pos;\n  p->numBlocks++;\n  return SZ_OK;\n}\n\n\nstatic SRes XzEncIndex_WriteFooter(const CXzEncIndex *p, CXzStreamFlags flags, ISeqOutStreamPtr s)\n{\n  Byte buf[32];\n  UInt64 globalPos;\n  UInt32 crc = CRC_INIT_VAL;\n  unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);\n  \n  globalPos = pos;\n  buf[0] = 0;\n  RINOK(WriteBytes_UpdateCrc(s, buf, pos, &crc))\n  RINOK(WriteBytes_UpdateCrc(s, p->blocks, p->size, &crc))\n  globalPos += p->size;\n  \n  pos = XZ_GET_PAD_SIZE(globalPos);\n  buf[1] = 0;\n  buf[2] = 0;\n  buf[3] = 0;\n  globalPos += pos;\n  \n  crc = CrcUpdate(crc, buf + 4 - pos, pos);\n  SetUi32(buf + 4, CRC_GET_DIGEST(crc))\n  \n  SetUi32(buf + 8 + 4, (UInt32)(globalPos >> 2))\n  buf[8 + 8] = (Byte)(flags >> 8);\n  buf[8 + 9] = (Byte)(flags & 0xFF);\n  SetUi32(buf + 8, CrcCalc(buf + 8 + 4, 6))\n  buf[8 + 10] = XZ_FOOTER_SIG_0;\n  buf[8 + 11] = XZ_FOOTER_SIG_1;\n  \n  return WriteBytes(s, buf + 4 - pos, pos + 4 + 12);\n}\n\n\n\n/* ---------- CSeqCheckInStream ---------- */\n\ntypedef struct\n{\n  ISeqInStream vt;\n  ISeqInStreamPtr realStream;\n  const Byte *data;\n  UInt64 limit;\n  UInt64 processed;\n  int realStreamFinished;\n  CXzCheck check;\n} CSeqCheckInStream;\n\nstatic void SeqCheckInStream_Init(CSeqCheckInStream *p, unsigned checkMode)\n{\n  p->limit = (UInt64)(Int64)-1;\n  p->processed = 0;\n  p->realStreamFinished = 0;\n  XzCheck_Init(&p->check, checkMode);\n}\n\nstatic void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)\n{\n  XzCheck_Final(&p->check, digest);\n}\n\nstatic SRes SeqCheckInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqCheckInStream)\n  size_t size2 = *size;\n  SRes res = SZ_OK;\n  \n  if (p->limit != (UInt64)(Int64)-1)\n  {\n    UInt64 rem = p->limit - p->processed;\n    if (size2 > rem)\n      size2 = (size_t)rem;\n  }\n  if (size2 != 0)\n  {\n    if (p->realStream)\n    {\n      res = ISeqInStream_Read(p->realStream, data, &size2);\n      p->realStreamFinished = (size2 == 0) ? 1 : 0;\n    }\n    else\n      memcpy(data, p->data + (size_t)p->processed, size2);\n    XzCheck_Update(&p->check, data, size2);\n    p->processed += size2;\n  }\n  *size = size2;\n  return res;\n}\n\n\n/* ---------- CSeqSizeOutStream ---------- */\n\ntypedef struct\n{\n  ISeqOutStream vt;\n  ISeqOutStreamPtr realStream;\n  Byte *outBuf;\n  size_t outBufLimit;\n  UInt64 processed;\n} CSeqSizeOutStream;\n\nstatic size_t SeqSizeOutStream_Write(ISeqOutStreamPtr pp, const void *data, size_t size)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqSizeOutStream)\n  if (p->realStream)\n    size = ISeqOutStream_Write(p->realStream, data, size);\n  else\n  {\n    if (size > p->outBufLimit - (size_t)p->processed)\n      return 0;\n    memcpy(p->outBuf + (size_t)p->processed, data, size);\n  }\n  p->processed += size;\n  return size;\n}\n\n\n/* ---------- CSeqInFilter ---------- */\n\n#define FILTER_BUF_SIZE (1 << 20)\n\ntypedef struct\n{\n  ISeqInStream vt;\n  ISeqInStreamPtr realStream;\n  IStateCoder StateCoder;\n  Byte *buf;\n  size_t curPos;\n  size_t endPos;\n  int srcWasFinished;\n} CSeqInFilter;\n\n\nstatic const z7_Func_BranchConv g_Funcs_BranchConv_RISC_Enc[] =\n{\n  Z7_BRANCH_CONV_ENC_2 (BranchConv_PPC),\n  Z7_BRANCH_CONV_ENC_2 (BranchConv_IA64),\n  Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM),\n  Z7_BRANCH_CONV_ENC_2 (BranchConv_ARMT),\n  Z7_BRANCH_CONV_ENC_2 (BranchConv_SPARC),\n  Z7_BRANCH_CONV_ENC_2 (BranchConv_ARM64),\n  Z7_BRANCH_CONV_ENC_2 (BranchConv_RISCV)\n};\n\nstatic SizeT XzBcFilterStateBase_Filter_Enc(CXzBcFilterStateBase *p, Byte *data, SizeT size)\n{\n  switch (p->methodId)\n  {\n    case XZ_ID_Delta:\n      Delta_Encode(p->delta_State, p->delta, data, size);\n      break;\n    case XZ_ID_X86:\n      size = (SizeT)(z7_BranchConvSt_X86_Enc(data, size, p->ip, &p->X86_State) - data);\n      break;\n    default:\n      if (p->methodId >= XZ_ID_PPC)\n      {\n        const UInt32 i = p->methodId - XZ_ID_PPC;\n        if (i < Z7_ARRAY_SIZE(g_Funcs_BranchConv_RISC_Enc))\n          size = (SizeT)(g_Funcs_BranchConv_RISC_Enc[i](data, size, p->ip) - data);\n      }\n      break;\n  }\n  p->ip += (UInt32)size;\n  return size;\n}\n\n\nstatic SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props, ISzAllocPtr alloc)\n{\n  if (!p->buf)\n  {\n    p->buf = (Byte *)ISzAlloc_Alloc(alloc, FILTER_BUF_SIZE);\n    if (!p->buf)\n      return SZ_ERROR_MEM;\n  }\n  p->curPos = p->endPos = 0;\n  p->srcWasFinished = 0;\n  RINOK(Xz_StateCoder_Bc_SetFromMethod_Func(&p->StateCoder, props->id, XzBcFilterStateBase_Filter_Enc, alloc))\n  RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, alloc))\n  p->StateCoder.Init(p->StateCoder.p);\n  return SZ_OK;\n}\n\n\nstatic SRes SeqInFilter_Read(ISeqInStreamPtr pp, void *data, size_t *size)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqInFilter)\n  const size_t sizeOriginal = *size;\n  if (sizeOriginal == 0)\n    return SZ_OK;\n  *size = 0;\n  \n  for (;;)\n  {\n    if (!p->srcWasFinished && p->curPos == p->endPos)\n    {\n      p->curPos = 0;\n      p->endPos = FILTER_BUF_SIZE;\n      RINOK(ISeqInStream_Read(p->realStream, p->buf, &p->endPos))\n      if (p->endPos == 0)\n        p->srcWasFinished = 1;\n    }\n    {\n      SizeT srcLen = p->endPos - p->curPos;\n      ECoderStatus status;\n      SRes res;\n      *size = sizeOriginal;\n      res = p->StateCoder.Code2(p->StateCoder.p,\n          (Byte *)data, size,\n          p->buf + p->curPos, &srcLen,\n          p->srcWasFinished, CODER_FINISH_ANY,\n          &status);\n      p->curPos += srcLen;\n      if (*size != 0 || srcLen == 0 || res != SZ_OK)\n        return res;\n    }\n  }\n}\n\nZ7_FORCE_INLINE\nstatic void SeqInFilter_Construct(CSeqInFilter *p)\n{\n  p->buf = NULL;\n  p->StateCoder.p = NULL;\n  p->vt.Read = SeqInFilter_Read;\n}\n\nZ7_FORCE_INLINE\nstatic void SeqInFilter_Free(CSeqInFilter *p, ISzAllocPtr alloc)\n{\n  if (p->StateCoder.p)\n  {\n    p->StateCoder.Free(p->StateCoder.p, alloc);\n    p->StateCoder.p = NULL;\n  }\n  if (p->buf)\n  {\n    ISzAlloc_Free(alloc, p->buf);\n    p->buf = NULL;\n  }\n}\n\n\n/* ---------- CSbEncInStream ---------- */\n\n#ifdef USE_SUBBLOCK\n\ntypedef struct\n{\n  ISeqInStream vt;\n  ISeqInStreamPtr inStream;\n  CSbEnc enc;\n} CSbEncInStream;\n\nstatic SRes SbEncInStream_Read(ISeqInStreamPtr pp, void *data, size_t *size)\n{\n  CSbEncInStream *p = Z7_CONTAINER_FROM_VTBL(pp, CSbEncInStream, vt);\n  size_t sizeOriginal = *size;\n  if (sizeOriginal == 0)\n    return SZ_OK;\n  \n  for (;;)\n  {\n    if (p->enc.needRead && !p->enc.readWasFinished)\n    {\n      size_t processed = p->enc.needReadSizeMax;\n      RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed))\n      p->enc.readPos += processed;\n      if (processed == 0)\n      {\n        p->enc.readWasFinished = True;\n        p->enc.isFinalFinished = True;\n      }\n      p->enc.needRead = False;\n    }\n  \n    *size = sizeOriginal;\n    RINOK(SbEnc_Read(&p->enc, data, size))\n    if (*size != 0 || !p->enc.needRead)\n      return SZ_OK;\n  }\n}\n\nvoid SbEncInStream_Construct(CSbEncInStream *p, ISzAllocPtr alloc)\n{\n  SbEnc_Construct(&p->enc, alloc);\n  p->vt.Read = SbEncInStream_Read;\n}\n\nSRes SbEncInStream_Init(CSbEncInStream *p)\n{\n  return SbEnc_Init(&p->enc);\n}\n\nvoid SbEncInStream_Free(CSbEncInStream *p)\n{\n  SbEnc_Free(&p->enc);\n}\n\n#endif\n\n\n\n/* ---------- CXzProps ---------- */\n\n\nvoid XzFilterProps_Init(CXzFilterProps *p)\n{\n  p->id = 0;\n  p->delta = 0;\n  p->ip = 0;\n  p->ipDefined = False;\n}\n\nvoid XzProps_Init(CXzProps *p)\n{\n  p->checkId = XZ_CHECK_CRC32;\n  p->numThreadGroups = 0;\n  p->blockSize = XZ_PROPS_BLOCK_SIZE_AUTO;\n  p->numBlockThreads_Reduced = -1;\n  p->numBlockThreads_Max = -1;\n  p->numTotalThreads = -1;\n  p->reduceSize = (UInt64)(Int64)-1;\n  p->forceWriteSizesInHeader = 0;\n  // p->forceWriteSizesInHeader = 1;\n\n  XzFilterProps_Init(&p->filterProps);\n  Lzma2EncProps_Init(&p->lzma2Props);\n}\n\n\nstatic void XzEncProps_Normalize_Fixed(CXzProps *p)\n{\n  UInt64 fileSize;\n  int t1, t1n, t2, t2r, t3;\n  {\n    CLzma2EncProps tp = p->lzma2Props;\n    if (tp.numTotalThreads <= 0)\n      tp.numTotalThreads = p->numTotalThreads;\n    Lzma2EncProps_Normalize(&tp);\n    t1n = tp.numTotalThreads;\n  }\n\n  t1 = p->lzma2Props.numTotalThreads;\n  t2 = p->numBlockThreads_Max;\n  t3 = p->numTotalThreads;\n\n  if (t2 > MTCODER_THREADS_MAX)\n    t2 = MTCODER_THREADS_MAX;\n\n  if (t3 <= 0)\n  {\n    if (t2 <= 0)\n      t2 = 1;\n    t3 = t1n * t2;\n  }\n  else if (t2 <= 0)\n  {\n    t2 = t3 / t1n;\n    if (t2 == 0)\n    {\n      t1 = 1;\n      t2 = t3;\n    }\n    if (t2 > MTCODER_THREADS_MAX)\n      t2 = MTCODER_THREADS_MAX;\n  }\n  else if (t1 <= 0)\n  {\n    t1 = t3 / t2;\n    if (t1 == 0)\n      t1 = 1;\n  }\n  else\n    t3 = t1n * t2;\n\n  p->lzma2Props.numTotalThreads = t1;\n\n  t2r = t2;\n\n  fileSize = p->reduceSize;\n\n  if ((p->blockSize < fileSize || fileSize == (UInt64)(Int64)-1))\n    p->lzma2Props.lzmaProps.reduceSize = p->blockSize;\n\n  Lzma2EncProps_Normalize(&p->lzma2Props);\n\n  t1 = p->lzma2Props.numTotalThreads;\n\n  {\n    if (t2 > 1 && fileSize != (UInt64)(Int64)-1)\n    {\n      UInt64 numBlocks = fileSize / p->blockSize;\n      if (numBlocks * p->blockSize != fileSize)\n        numBlocks++;\n      if (numBlocks < (unsigned)t2)\n      {\n        t2r = (int)numBlocks;\n        if (t2r == 0)\n          t2r = 1;\n        t3 = t1 * t2r;\n      }\n    }\n  }\n  \n  p->numBlockThreads_Max = t2;\n  p->numBlockThreads_Reduced = t2r;\n  p->numTotalThreads = t3;\n}\n\n\nstatic void XzProps_Normalize(CXzProps *p)\n{\n  /* we normalize xzProps properties, but we normalize only some of CXzProps::lzma2Props properties.\n     Lzma2Enc_SetProps() will normalize lzma2Props later. */\n  \n  if (p->blockSize == XZ_PROPS_BLOCK_SIZE_SOLID)\n  {\n    p->lzma2Props.lzmaProps.reduceSize = p->reduceSize;\n    p->numBlockThreads_Reduced = 1;\n    p->numBlockThreads_Max = 1;\n    if (p->lzma2Props.numTotalThreads <= 0)\n      p->lzma2Props.numTotalThreads = p->numTotalThreads;\n    return;\n  }\n  else\n  {\n    CLzma2EncProps *lzma2 = &p->lzma2Props;\n    if (p->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO)\n    {\n      // xz-auto\n      p->lzma2Props.lzmaProps.reduceSize = p->reduceSize;\n\n      if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)\n      {\n        // if (xz-auto && lzma2-solid) - we use solid for both\n        p->blockSize = XZ_PROPS_BLOCK_SIZE_SOLID;\n        p->numBlockThreads_Reduced = 1;\n        p->numBlockThreads_Max = 1;\n        if (p->lzma2Props.numTotalThreads <= 0)\n          p->lzma2Props.numTotalThreads = p->numTotalThreads;\n      }\n      else\n      {\n        // if (xz-auto && (lzma2-auto || lzma2-fixed_)\n        //   we calculate block size for lzma2 and use that block size for xz, lzma2 uses single-chunk per block\n        CLzma2EncProps tp = p->lzma2Props;\n        if (tp.numTotalThreads <= 0)\n          tp.numTotalThreads = p->numTotalThreads;\n        \n        Lzma2EncProps_Normalize(&tp);\n        \n        p->blockSize = tp.blockSize; // fixed or solid\n        p->numBlockThreads_Reduced = tp.numBlockThreads_Reduced;\n        p->numBlockThreads_Max = tp.numBlockThreads_Max;\n        if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO)\n          lzma2->blockSize = tp.blockSize; // fixed or solid, LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID\n        if (lzma2->lzmaProps.reduceSize > tp.blockSize && tp.blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)\n          lzma2->lzmaProps.reduceSize = tp.blockSize;\n        lzma2->numBlockThreads_Reduced = 1;\n        lzma2->numBlockThreads_Max = 1;\n        return;\n      }\n    }\n    else\n    {\n      // xz-fixed\n      // we can use xz::reduceSize or xz::blockSize as base for lzmaProps::reduceSize\n      \n      p->lzma2Props.lzmaProps.reduceSize = p->reduceSize;\n      {\n        UInt64 r = p->reduceSize;\n        if (r > p->blockSize || r == (UInt64)(Int64)-1)\n          r = p->blockSize;\n        lzma2->lzmaProps.reduceSize = r;\n      }\n      if (lzma2->blockSize == LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO)\n        lzma2->blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;\n      else if (lzma2->blockSize > p->blockSize && lzma2->blockSize != LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID)\n        lzma2->blockSize = p->blockSize;\n      \n      XzEncProps_Normalize_Fixed(p);\n    }\n  }\n}\n\n\n/* ---------- CLzma2WithFilters ---------- */\n\ntypedef struct\n{\n  CLzma2EncHandle lzma2;\n  CSeqInFilter filter;\n\n  #ifdef USE_SUBBLOCK\n  CSbEncInStream sb;\n  #endif\n} CLzma2WithFilters;\n\n\nZ7_FORCE_INLINE\nstatic void Lzma2WithFilters_Construct(CLzma2WithFilters *p)\n{\n  p->lzma2 = NULL;\n  SeqInFilter_Construct(&p->filter);\n\n  #ifdef USE_SUBBLOCK\n  SbEncInStream_Construct(&p->sb, alloc);\n  #endif\n}\n\n\nstatic SRes Lzma2WithFilters_Create(CLzma2WithFilters *p, ISzAllocPtr alloc, ISzAllocPtr bigAlloc)\n{\n  if (!p->lzma2)\n  {\n    p->lzma2 = Lzma2Enc_Create(alloc, bigAlloc);\n    if (!p->lzma2)\n      return SZ_ERROR_MEM;\n  }\n  return SZ_OK;\n}\n\n\nZ7_FORCE_INLINE\nstatic void Lzma2WithFilters_Free(CLzma2WithFilters *p, ISzAllocPtr alloc)\n{\n  #ifdef USE_SUBBLOCK\n  SbEncInStream_Free(&p->sb);\n  #endif\n\n  SeqInFilter_Free(&p->filter, alloc);\n  if (p->lzma2)\n  {\n    Lzma2Enc_Destroy(p->lzma2);\n    p->lzma2 = NULL;\n  }\n}\n\n\ntypedef struct\n{\n  UInt64 unpackSize;\n  UInt64 totalSize;\n  size_t headerSize;\n} CXzEncBlockInfo;\n\n\nstatic SRes Xz_CompressBlock(\n    CLzma2WithFilters *lzmaf,\n    \n    ISeqOutStreamPtr outStream,\n    Byte *outBufHeader,\n    Byte *outBufData, size_t outBufDataLimit,\n\n    ISeqInStreamPtr inStream,\n    // UInt64 expectedSize,\n    const Byte *inBuf, // used if (!inStream)\n    size_t inBufSize,  // used if (!inStream), it's block size, props->blockSize is ignored\n\n    const CXzProps *props,\n    ICompressProgressPtr progress,\n    int *inStreamFinished,  /* only for inStream version */\n    CXzEncBlockInfo *blockSizes,\n    ISzAllocPtr alloc,\n    ISzAllocPtr allocBig)\n{\n  CSeqCheckInStream checkInStream;\n  CSeqSizeOutStream seqSizeOutStream;\n  CXzBlock block;\n  unsigned filterIndex = 0;\n  CXzFilter *filter = NULL;\n  const CXzFilterProps *fp = &props->filterProps;\n  if (fp->id == 0)\n    fp = NULL;\n  \n  *inStreamFinished = False;\n  \n  RINOK(Lzma2WithFilters_Create(lzmaf, alloc, allocBig))\n  \n  RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, &props->lzma2Props))\n  \n  // XzBlock_ClearFlags(&block)\n  XzBlock_ClearFlags_SetNumFilters(&block, 1 + (fp ? 1 : 0))\n  \n  if (fp)\n  {\n    filter = &block.filters[filterIndex++];\n    filter->id = fp->id;\n    filter->propsSize = 0;\n    \n    if (fp->id == XZ_ID_Delta)\n    {\n      filter->props[0] = (Byte)(fp->delta - 1);\n      filter->propsSize = 1;\n    }\n    else if (fp->ipDefined)\n    {\n      Byte *ptr = filter->props;\n      SetUi32(ptr, fp->ip)\n      filter->propsSize = 4;\n    }\n  }\n  \n  {\n    CXzFilter *f = &block.filters[filterIndex++];\n    f->id = XZ_ID_LZMA2;\n    f->propsSize = 1;\n    f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);\n  }\n  \n  seqSizeOutStream.vt.Write = SeqSizeOutStream_Write;\n  seqSizeOutStream.realStream = outStream;\n  seqSizeOutStream.outBuf = outBufData;\n  seqSizeOutStream.outBufLimit = outBufDataLimit;\n  seqSizeOutStream.processed = 0;\n    \n  /*\n  if (expectedSize != (UInt64)(Int64)-1)\n  {\n    block.unpackSize = expectedSize;\n    if (props->blockSize != (UInt64)(Int64)-1)\n      if (expectedSize > props->blockSize)\n        block.unpackSize = props->blockSize;\n    XzBlock_SetHasUnpackSize(&block)\n  }\n  */\n\n  if (outStream)\n  {\n    RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt))\n  }\n  \n  checkInStream.vt.Read = SeqCheckInStream_Read;\n  SeqCheckInStream_Init(&checkInStream, props->checkId);\n  \n  checkInStream.realStream = inStream;\n  checkInStream.data = inBuf;\n  checkInStream.limit = props->blockSize;\n  if (!inStream)\n    checkInStream.limit = inBufSize;\n\n  if (fp)\n  {\n    #ifdef USE_SUBBLOCK\n    if (fp->id == XZ_ID_Subblock)\n    {\n      lzmaf->sb.inStream = &checkInStream.vt;\n      RINOK(SbEncInStream_Init(&lzmaf->sb))\n    }\n    else\n    #endif\n    {\n      lzmaf->filter.realStream = &checkInStream.vt;\n      RINOK(SeqInFilter_Init(&lzmaf->filter, filter, alloc))\n    }\n  }\n\n  {\n    SRes res;\n    Byte *outBuf = NULL;\n    size_t outSize = 0;\n    BoolInt useStream = (fp || inStream);\n    // useStream = True;\n    \n    if (!useStream)\n    {\n      XzCheck_Update(&checkInStream.check, inBuf, inBufSize);\n      checkInStream.processed = inBufSize;\n    }\n    \n    if (!outStream)\n    {\n      outBuf = seqSizeOutStream.outBuf; //  + (size_t)seqSizeOutStream.processed;\n      outSize = seqSizeOutStream.outBufLimit; // - (size_t)seqSizeOutStream.processed;\n    }\n    \n    res = Lzma2Enc_Encode2(lzmaf->lzma2,\n        outBuf ? NULL : &seqSizeOutStream.vt,\n        outBuf,\n        outBuf ? &outSize : NULL,\n      \n        useStream ?\n          (fp ?\n            (\n            #ifdef USE_SUBBLOCK\n            (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.vt:\n            #endif\n            &lzmaf->filter.vt) :\n            &checkInStream.vt) : NULL,\n      \n        useStream ? NULL : inBuf,\n        useStream ? 0 : inBufSize,\n        \n        progress);\n    \n    if (outBuf)\n      seqSizeOutStream.processed += outSize;\n    \n    RINOK(res)\n    blockSizes->unpackSize = checkInStream.processed;\n  }\n  {\n    Byte buf[4 + XZ_CHECK_SIZE_MAX];\n    const unsigned padSize = XZ_GET_PAD_SIZE(seqSizeOutStream.processed);\n    const UInt64 packSize = seqSizeOutStream.processed;\n    \n    buf[0] = 0;\n    buf[1] = 0;\n    buf[2] = 0;\n    buf[3] = 0;\n    \n    SeqCheckInStream_GetDigest(&checkInStream, buf + 4);\n    RINOK(WriteBytes(&seqSizeOutStream.vt, buf + (4 - padSize),\n        padSize + XzFlags_GetCheckSize((CXzStreamFlags)props->checkId)))\n    \n    blockSizes->totalSize = seqSizeOutStream.processed - padSize;\n    \n    if (!outStream)\n    {\n      seqSizeOutStream.outBuf = outBufHeader;\n      seqSizeOutStream.outBufLimit = XZ_BLOCK_HEADER_SIZE_MAX;\n      seqSizeOutStream.processed = 0;\n      \n      block.unpackSize = blockSizes->unpackSize;\n      XzBlock_SetHasUnpackSize(&block)\n      \n      block.packSize = packSize;\n      XzBlock_SetHasPackSize(&block)\n      \n      RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.vt))\n      \n      blockSizes->headerSize = (size_t)seqSizeOutStream.processed;\n      blockSizes->totalSize += seqSizeOutStream.processed;\n    }\n  }\n  \n  if (inStream)\n    *inStreamFinished = checkInStream.realStreamFinished;\n  else\n  {\n    *inStreamFinished = False;\n    if (checkInStream.processed != inBufSize)\n      return SZ_ERROR_FAIL;\n  }\n\n  return SZ_OK;\n}\n\n\n\ntypedef struct\n{\n  ICompressProgress vt;\n  ICompressProgressPtr progress;\n  UInt64 inOffset;\n  UInt64 outOffset;\n} CCompressProgress_XzEncOffset;\n\n\nstatic SRes CompressProgress_XzEncOffset_Progress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize)\n{\n  const CCompressProgress_XzEncOffset *p = Z7_CONTAINER_FROM_VTBL_CONST(pp, CCompressProgress_XzEncOffset, vt);\n  inSize += p->inOffset;\n  outSize += p->outOffset;\n  return ICompressProgress_Progress(p->progress, inSize, outSize);\n}\n\n\n\n\nstruct CXzEnc\n{\n  ISzAllocPtr alloc;\n  ISzAllocPtr allocBig;\n\n  CXzProps xzProps;\n  UInt64 expectedDataSize;\n\n  CXzEncIndex xzIndex;\n\n  CLzma2WithFilters lzmaf_Items[MTCODER_THREADS_MAX];\n  \n  size_t outBufSize;       /* size of allocated outBufs[i] */\n  Byte *outBufs[MTCODER_BLOCKS_MAX];\n\n  #ifndef Z7_ST\n  unsigned checkType;\n  ISeqOutStreamPtr outStream;\n  BoolInt mtCoder_WasConstructed;\n  CMtCoder mtCoder;\n  CXzEncBlockInfo EncBlocks[MTCODER_BLOCKS_MAX];\n  #endif\n};\n\n\nstatic void XzEnc_Construct(CXzEnc *p)\n{\n  unsigned i;\n\n  XzEncIndex_Construct(&p->xzIndex);\n\n  for (i = 0; i < MTCODER_THREADS_MAX; i++)\n    Lzma2WithFilters_Construct(&p->lzmaf_Items[i]);\n\n  #ifndef Z7_ST\n  p->mtCoder_WasConstructed = False;\n  {\n    for (i = 0; i < MTCODER_BLOCKS_MAX; i++)\n      p->outBufs[i] = NULL;\n    p->outBufSize = 0;\n  }\n  #endif\n}\n\n\nstatic void XzEnc_FreeOutBufs(CXzEnc *p)\n{\n  unsigned i;\n  for (i = 0; i < MTCODER_BLOCKS_MAX; i++)\n    if (p->outBufs[i])\n    {\n      ISzAlloc_Free(p->alloc, p->outBufs[i]);\n      p->outBufs[i] = NULL;\n    }\n  p->outBufSize = 0;\n}\n\n\nstatic void XzEnc_Free(CXzEnc *p, ISzAllocPtr alloc)\n{\n  unsigned i;\n\n  XzEncIndex_Free(&p->xzIndex, alloc);\n\n  for (i = 0; i < MTCODER_THREADS_MAX; i++)\n    Lzma2WithFilters_Free(&p->lzmaf_Items[i], alloc);\n  \n  #ifndef Z7_ST\n  if (p->mtCoder_WasConstructed)\n  {\n    MtCoder_Destruct(&p->mtCoder);\n    p->mtCoder_WasConstructed = False;\n  }\n  XzEnc_FreeOutBufs(p);\n  #endif\n}\n\n\nCXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig)\n{\n  CXzEnc *p = (CXzEnc *)ISzAlloc_Alloc(alloc, sizeof(CXzEnc));\n  if (!p)\n    return NULL;\n  XzEnc_Construct(p);\n  XzProps_Init(&p->xzProps);\n  XzProps_Normalize(&p->xzProps);\n  p->expectedDataSize = (UInt64)(Int64)-1;\n  p->alloc = alloc;\n  p->allocBig = allocBig;\n  return (CXzEncHandle)p;\n}\n\n// #define GET_CXzEnc_p  CXzEnc *p = (CXzEnc *)(void *)pp;\n\nvoid XzEnc_Destroy(CXzEncHandle p)\n{\n  // GET_CXzEnc_p\n  XzEnc_Free(p, p->alloc);\n  ISzAlloc_Free(p->alloc, p);\n}\n\n\nSRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props)\n{\n  // GET_CXzEnc_p\n  p->xzProps = *props;\n  XzProps_Normalize(&p->xzProps);\n  return SZ_OK;\n}\n\n\nvoid XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize)\n{\n  // GET_CXzEnc_p\n  p->expectedDataSize = expectedDataSiize;\n}\n\n\n\n\n#ifndef Z7_ST\n\nstatic SRes XzEnc_MtCallback_Code(void *pp, unsigned coderIndex, unsigned outBufIndex,\n    const Byte *src, size_t srcSize, int finished)\n{\n  CXzEnc *me = (CXzEnc *)pp;\n  SRes res;\n  CMtProgressThunk progressThunk;\n  Byte *dest;\n  UNUSED_VAR(finished)\n  {\n    CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];\n    bInfo->totalSize = 0;\n    bInfo->unpackSize = 0;\n    bInfo->headerSize = 0;\n    // v23.02: we don't compress empty blocks\n    // also we must ignore that empty block in XzEnc_MtCallback_Write()\n    if (srcSize == 0)\n      return SZ_OK;\n  }\n  dest = me->outBufs[outBufIndex];\n  if (!dest)\n  {\n    dest = (Byte *)ISzAlloc_Alloc(me->alloc, me->outBufSize);\n    if (!dest)\n      return SZ_ERROR_MEM;\n    me->outBufs[outBufIndex] = dest;\n  }\n  \n  MtProgressThunk_CreateVTable(&progressThunk);\n  progressThunk.mtProgress = &me->mtCoder.mtProgress;\n  MtProgressThunk_INIT(&progressThunk)\n\n  {\n    CXzEncBlockInfo blockSizes;\n    int inStreamFinished;\n\n    res = Xz_CompressBlock(\n        &me->lzmaf_Items[coderIndex],\n        \n        NULL,\n        dest,\n        dest + XZ_BLOCK_HEADER_SIZE_MAX, me->outBufSize - XZ_BLOCK_HEADER_SIZE_MAX,\n\n        NULL,\n        // srcSize, // expectedSize\n        src, srcSize,\n\n        &me->xzProps,\n        &progressThunk.vt,\n        &inStreamFinished,\n        &blockSizes,\n        me->alloc,\n        me->allocBig);\n    \n    if (res == SZ_OK)\n      me->EncBlocks[outBufIndex] = blockSizes;\n\n    return res;\n  }\n}\n\n\nstatic SRes XzEnc_MtCallback_Write(void *pp, unsigned outBufIndex)\n{\n  CXzEnc *me = (CXzEnc *)pp;\n  const CXzEncBlockInfo *bInfo = &me->EncBlocks[outBufIndex];\n  // v23.02: we don't write empty blocks\n  // note: if (bInfo->unpackSize == 0) then there is no compressed data of block\n  if (bInfo->unpackSize == 0)\n    return SZ_OK;\n  {\n    const Byte *data = me->outBufs[outBufIndex];\n    RINOK(WriteBytes(me->outStream, data, bInfo->headerSize))\n    {\n      const UInt64 totalPackFull = bInfo->totalSize + XZ_GET_PAD_SIZE(bInfo->totalSize);\n      RINOK(WriteBytes(me->outStream, data + XZ_BLOCK_HEADER_SIZE_MAX, (size_t)totalPackFull - bInfo->headerSize))\n    }\n    return XzEncIndex_AddIndexRecord(&me->xzIndex, bInfo->unpackSize, bInfo->totalSize, me->alloc);\n  }\n}\n\n#endif\n\n\n\nSRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress)\n{\n  // GET_CXzEnc_p\n\n  const CXzProps *props = &p->xzProps;\n\n  XzEncIndex_Init(&p->xzIndex);\n  {\n    UInt64 numBlocks = 1;\n    UInt64 blockSize = props->blockSize;\n    \n    if (blockSize != XZ_PROPS_BLOCK_SIZE_SOLID\n        && props->reduceSize != (UInt64)(Int64)-1)\n    {\n      numBlocks = props->reduceSize / blockSize;\n      if (numBlocks * blockSize != props->reduceSize)\n        numBlocks++;\n    }\n    else\n      blockSize = (UInt64)1 << 62;\n    \n    RINOK(XzEncIndex_PreAlloc(&p->xzIndex, numBlocks, blockSize, XZ_GET_ESTIMATED_BLOCK_TOTAL_PACK_SIZE(blockSize), p->alloc))\n  }\n\n  RINOK(Xz_WriteHeader((CXzStreamFlags)props->checkId, outStream))\n\n\n  #ifndef Z7_ST\n  if (props->numBlockThreads_Reduced > 1)\n  {\n    IMtCoderCallback2 vt;\n\n    if (!p->mtCoder_WasConstructed)\n    {\n      p->mtCoder_WasConstructed = True;\n      MtCoder_Construct(&p->mtCoder);\n    }\n\n    vt.Code = XzEnc_MtCallback_Code;\n    vt.Write = XzEnc_MtCallback_Write;\n\n    p->checkType = props->checkId;\n    p->xzProps = *props;\n    \n    p->outStream = outStream;\n\n    p->mtCoder.allocBig = p->allocBig;\n    p->mtCoder.progress = progress;\n    p->mtCoder.inStream = inStream;\n    p->mtCoder.inData = NULL;\n    p->mtCoder.inDataSize = 0;\n    p->mtCoder.mtCallback = &vt;\n    p->mtCoder.mtCallbackObject = p;\n\n    if (   props->blockSize == XZ_PROPS_BLOCK_SIZE_SOLID\n        || props->blockSize == XZ_PROPS_BLOCK_SIZE_AUTO)\n      return SZ_ERROR_FAIL;\n\n    p->mtCoder.blockSize = (size_t)props->blockSize;\n    if (p->mtCoder.blockSize != props->blockSize)\n      return SZ_ERROR_PARAM; /* SZ_ERROR_MEM */\n\n    {\n      size_t destBlockSize = XZ_BLOCK_HEADER_SIZE_MAX + XZ_GET_MAX_BLOCK_PACK_SIZE(p->mtCoder.blockSize);\n      if (destBlockSize < p->mtCoder.blockSize)\n        return SZ_ERROR_PARAM;\n      if (p->outBufSize != destBlockSize)\n        XzEnc_FreeOutBufs(p);\n      p->outBufSize = destBlockSize;\n    }\n\n    p->mtCoder.numThreadsMax = (unsigned)props->numBlockThreads_Max;\n    p->mtCoder.numThreadGroups = props->numThreadGroups;\n    p->mtCoder.expectedDataSize = p->expectedDataSize;\n    \n    RINOK(MtCoder_Code(&p->mtCoder))\n  }\n  else\n  #endif\n  {\n    int writeStartSizes;\n    CCompressProgress_XzEncOffset progress2;\n    Byte *bufData = NULL;\n    size_t bufSize = 0;\n\n    progress2.vt.Progress = CompressProgress_XzEncOffset_Progress;\n    progress2.inOffset = 0;\n    progress2.outOffset = 0;\n    progress2.progress = progress;\n    \n    writeStartSizes = 0;\n    \n    if (props->blockSize != XZ_PROPS_BLOCK_SIZE_SOLID)\n    {\n      writeStartSizes = (props->forceWriteSizesInHeader > 0);\n      \n      if (writeStartSizes)\n      {\n        size_t t2;\n        size_t t = (size_t)props->blockSize;\n        if (t != props->blockSize)\n          return SZ_ERROR_PARAM;\n        t = XZ_GET_MAX_BLOCK_PACK_SIZE(t);\n        if (t < props->blockSize)\n          return SZ_ERROR_PARAM;\n        t2 = XZ_BLOCK_HEADER_SIZE_MAX + t;\n        if (!p->outBufs[0] || t2 != p->outBufSize)\n        {\n          XzEnc_FreeOutBufs(p);\n          p->outBufs[0] = (Byte *)ISzAlloc_Alloc(p->alloc, t2);\n          if (!p->outBufs[0])\n            return SZ_ERROR_MEM;\n          p->outBufSize = t2;\n        }\n        bufData = p->outBufs[0] + XZ_BLOCK_HEADER_SIZE_MAX;\n        bufSize = t;\n      }\n    }\n    \n    for (;;)\n    {\n      CXzEncBlockInfo blockSizes;\n      int inStreamFinished;\n      \n      /*\n      UInt64 rem = (UInt64)(Int64)-1;\n      if (props->reduceSize != (UInt64)(Int64)-1\n          && props->reduceSize >= progress2.inOffset)\n        rem = props->reduceSize - progress2.inOffset;\n      */\n\n      blockSizes.headerSize = 0; // for GCC\n      \n      RINOK(Xz_CompressBlock(\n          &p->lzmaf_Items[0],\n          \n          writeStartSizes ? NULL : outStream,\n          writeStartSizes ? p->outBufs[0] : NULL,\n          bufData, bufSize,\n          \n          inStream,\n          // rem,\n          NULL, 0,\n          \n          props,\n          progress ? &progress2.vt : NULL,\n          &inStreamFinished,\n          &blockSizes,\n          p->alloc,\n          p->allocBig))\n\n      {\n        UInt64 totalPackFull = blockSizes.totalSize + XZ_GET_PAD_SIZE(blockSizes.totalSize);\n      \n        if (writeStartSizes)\n        {\n          RINOK(WriteBytes(outStream, p->outBufs[0], blockSizes.headerSize))\n          RINOK(WriteBytes(outStream, bufData, (size_t)totalPackFull - blockSizes.headerSize))\n        }\n        \n        RINOK(XzEncIndex_AddIndexRecord(&p->xzIndex, blockSizes.unpackSize, blockSizes.totalSize, p->alloc))\n        \n        progress2.inOffset += blockSizes.unpackSize;\n        progress2.outOffset += totalPackFull;\n      }\n        \n      if (inStreamFinished)\n        break;\n    }\n  }\n\n  return XzEncIndex_WriteFooter(&p->xzIndex, (CXzStreamFlags)props->checkId, outStream);\n}\n\n\n#include \"Alloc.h\"\n\nSRes Xz_Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream,\n    const CXzProps *props, ICompressProgressPtr progress)\n{\n  SRes res;\n  CXzEncHandle xz = XzEnc_Create(&g_Alloc, &g_BigAlloc);\n  if (!xz)\n    return SZ_ERROR_MEM;\n  res = XzEnc_SetProps(xz, props);\n  if (res == SZ_OK)\n    res = XzEnc_Encode(xz, outStream, inStream, progress);\n  XzEnc_Destroy(xz);\n  return res;\n}\n\n\nSRes Xz_EncodeEmpty(ISeqOutStreamPtr outStream)\n{\n  SRes res;\n  CXzEncIndex xzIndex;\n  XzEncIndex_Construct(&xzIndex);\n  res = Xz_WriteHeader((CXzStreamFlags)0, outStream);\n  if (res == SZ_OK)\n    res = XzEncIndex_WriteFooter(&xzIndex, (CXzStreamFlags)0, outStream);\n  XzEncIndex_Free(&xzIndex, NULL); // g_Alloc\n  return res;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/XzEnc.h",
    "content": "﻿/* XzEnc.h -- Xz Encode\n: Igor Pavlov : Public domain */\n\n#ifndef ZIP7_INC_XZ_ENC_H\n#define ZIP7_INC_XZ_ENC_H\n\n#include \"Lzma2Enc.h\"\n\n#include \"Xz.h\"\n\nEXTERN_C_BEGIN\n\n\n#define XZ_PROPS_BLOCK_SIZE_AUTO   LZMA2_ENC_PROPS_BLOCK_SIZE_AUTO\n#define XZ_PROPS_BLOCK_SIZE_SOLID  LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID\n\n\ntypedef struct\n{\n  UInt32 id;\n  UInt32 delta;\n  UInt32 ip;\n  int ipDefined;\n} CXzFilterProps;\n\nvoid XzFilterProps_Init(CXzFilterProps *p);\n\n\ntypedef struct\n{\n  CLzma2EncProps lzma2Props;\n  CXzFilterProps filterProps;\n  unsigned checkId;\n  unsigned numThreadGroups; // 0 : no groups\n  UInt64 blockSize;\n  int numBlockThreads_Reduced;\n  int numBlockThreads_Max;\n  int numTotalThreads;\n  int forceWriteSizesInHeader;\n  UInt64 reduceSize;\n} CXzProps;\n\nvoid XzProps_Init(CXzProps *p);\n\ntypedef struct CXzEnc CXzEnc;\ntypedef CXzEnc * CXzEncHandle;\n// Z7_DECLARE_HANDLE(CXzEncHandle)\n\nCXzEncHandle XzEnc_Create(ISzAllocPtr alloc, ISzAllocPtr allocBig);\nvoid XzEnc_Destroy(CXzEncHandle p);\nSRes XzEnc_SetProps(CXzEncHandle p, const CXzProps *props);\nvoid XzEnc_SetDataSize(CXzEncHandle p, UInt64 expectedDataSiize);\nSRes XzEnc_Encode(CXzEncHandle p, ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream, ICompressProgressPtr progress);\n\nSRes Xz_Encode(ISeqOutStreamPtr outStream, ISeqInStreamPtr inStream,\n    const CXzProps *props, ICompressProgressPtr progress);\n\nSRes Xz_EncodeEmpty(ISeqOutStreamPtr outStream);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/C/XzIn.c",
    "content": "﻿/* XzIn.c - Xz input\n: Igor Pavlov : Public domain */\n\n#include \"Precomp.h\"\n\n#include <string.h>\n\n#include \"7zCrc.h\"\n#include \"Xz.h\"\n#include \"CpuArch.h\"\n\n#define XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(p) \\\n    (GetUi16a((const Byte *)(const void *)(p) + 10) == \\\n      (XZ_FOOTER_SIG_0 | (XZ_FOOTER_SIG_1 << 8)))\n\nSRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStreamPtr inStream)\n{\n  UInt32 data32[XZ_STREAM_HEADER_SIZE / 4];\n  size_t processedSize = XZ_STREAM_HEADER_SIZE;\n  RINOK(SeqInStream_ReadMax(inStream, data32, &processedSize))\n  if (processedSize != XZ_STREAM_HEADER_SIZE\n      || memcmp(data32, XZ_SIG, XZ_SIG_SIZE) != 0)\n    return SZ_ERROR_NO_ARCHIVE;\n  return Xz_ParseHeader(p, (const Byte *)(const void *)data32);\n}\n\n#define READ_VARINT_AND_CHECK(buf, size, res) \\\n{ const unsigned s = Xz_ReadVarInt(buf, size, res); \\\n  if (s == 0) return SZ_ERROR_ARCHIVE; \\\n  size -= s; \\\n  buf += s; \\\n}\n\nSRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStreamPtr inStream, BoolInt *isIndex, UInt32 *headerSizeRes)\n{\n  MY_ALIGN(4)\n  Byte header[XZ_BLOCK_HEADER_SIZE_MAX];\n  unsigned headerSize;\n  *headerSizeRes = 0;\n  RINOK(SeqInStream_ReadByte(inStream, &header[0]))\n  headerSize = header[0];\n  if (headerSize == 0)\n  {\n    *headerSizeRes = 1;\n    *isIndex = True;\n    return SZ_OK;\n  }\n\n  *isIndex = False;\n  headerSize = (headerSize << 2) + 4;\n  *headerSizeRes = (UInt32)headerSize;\n  {\n    size_t processedSize = headerSize - 1;\n    RINOK(SeqInStream_ReadMax(inStream, header + 1, &processedSize))\n    if (processedSize != headerSize - 1)\n      return SZ_ERROR_INPUT_EOF;\n  }\n  return XzBlock_Parse(p, header);\n}\n\n\n#define ADD_SIZE_CHECK(size, val) \\\n{ const UInt64 newSize = size + (val); \\\n  if (newSize < size) return XZ_SIZE_OVERFLOW; \\\n  size = newSize; \\\n}\n\nUInt64 Xz_GetUnpackSize(const CXzStream *p)\n{\n  UInt64 size = 0;\n  size_t i;\n  for (i = 0; i < p->numBlocks; i++)\n  {\n    ADD_SIZE_CHECK(size, p->blocks[i].unpackSize)\n  }\n  return size;\n}\n\nUInt64 Xz_GetPackSize(const CXzStream *p)\n{\n  UInt64 size = 0;\n  size_t i;\n  for (i = 0; i < p->numBlocks; i++)\n  {\n    ADD_SIZE_CHECK(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3)\n  }\n  return size;\n}\n\n\n// input;\n//   CXzStream (p) is empty object.\n//   size != 0\n//   (size & 3) == 0\n//   (buf) is aligned for at least 4 bytes.\n// output:\n//   p->numBlocks is number of allocated items in p->blocks\n//   p->blocks[*] values must be ignored, if function returns error.\nstatic SRes Xz_ParseIndex(CXzStream *p, const Byte *buf, size_t size, ISzAllocPtr alloc)\n{\n  size_t numBlocks;\n  if (size < 5 || buf[0] != 0)\n    return SZ_ERROR_ARCHIVE;\n  size -= 4;\n  {\n    const UInt32 crc = CrcCalc(buf, size);\n    if (crc != GetUi32a(buf + size))\n      return SZ_ERROR_ARCHIVE;\n  }\n  buf++;\n  size--;\n  {\n    UInt64 numBlocks64;\n    READ_VARINT_AND_CHECK(buf, size, &numBlocks64)\n    // (numBlocks64) is 63-bit value, so we can calculate (numBlocks64 * 2):\n    if (numBlocks64 * 2 > size)\n      return SZ_ERROR_ARCHIVE;\n    if (numBlocks64 >= ((size_t)1 << (sizeof(size_t) * 8 - 1)) / sizeof(CXzBlockSizes))\n      return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE\n    numBlocks = (size_t)numBlocks64;\n  }\n  // Xz_Free(p, alloc); // it's optional, because (p) is empty already\n  if (numBlocks)\n  {\n    CXzBlockSizes *blocks = (CXzBlockSizes *)ISzAlloc_Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);\n    if (!blocks)\n      return SZ_ERROR_MEM;\n    p->blocks = blocks;\n    p->numBlocks = numBlocks;\n    // the caller will call Xz_Free() in case of error\n    do\n    {\n      READ_VARINT_AND_CHECK(buf, size, &blocks->totalSize)\n      READ_VARINT_AND_CHECK(buf, size, &blocks->unpackSize)\n      if (blocks->totalSize == 0)\n        return SZ_ERROR_ARCHIVE;\n      blocks++;\n    }\n    while (--numBlocks);\n  }\n  if (size >= 4)\n    return SZ_ERROR_ARCHIVE;\n  while (size)\n    if (buf[--size])\n      return SZ_ERROR_ARCHIVE;\n  return SZ_OK;\n}\n\n\n/*\nstatic SRes Xz_ReadIndex(CXzStream *p, ILookInStreamPtr stream, UInt64 indexSize, ISzAllocPtr alloc)\n{\n  SRes res;\n  size_t size;\n  Byte *buf;\n  if (indexSize >= ((size_t)1 << (sizeof(size_t) * 8 - 1)))\n    return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE\n  size = (size_t)indexSize;\n  buf = (Byte *)ISzAlloc_Alloc(alloc, size);\n  if (!buf)\n    return SZ_ERROR_MEM;\n  res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);\n  if (res == SZ_OK)\n    res = Xz_ParseIndex(p, buf, size, alloc);\n  ISzAlloc_Free(alloc, buf);\n  return res;\n}\n*/\n\nstatic SRes LookInStream_SeekRead_ForArc(ILookInStreamPtr stream, UInt64 offset, void *buf, size_t size)\n{\n  RINOK(LookInStream_SeekTo(stream, offset))\n  return LookInStream_Read(stream, buf, size);\n  /* return LookInStream_Read2(stream, buf, size, SZ_ERROR_NO_ARCHIVE); */\n}\n\n\n/*\nin:\n  (*startOffset) is position in (stream) where xz_stream must be finished.\nout:\n  if returns SZ_OK, then (*startOffset) is position in stream that shows start of xz_stream.\n*/\nstatic SRes Xz_ReadBackward(CXzStream *p, ILookInStreamPtr stream, Int64 *startOffset, ISzAllocPtr alloc)\n{\n  #define TEMP_BUF_SIZE  (1 << 10)\n  UInt32 buf32[TEMP_BUF_SIZE / 4];\n  UInt64 pos = (UInt64)*startOffset;\n\n  if ((pos & 3) || pos < XZ_STREAM_FOOTER_SIZE)\n    return SZ_ERROR_NO_ARCHIVE;\n  pos -= XZ_STREAM_FOOTER_SIZE;\n  RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, XZ_STREAM_FOOTER_SIZE))\n  \n  if (!XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(buf32))\n  {\n    pos += XZ_STREAM_FOOTER_SIZE;\n    for (;;)\n    {\n      // pos != 0\n      // (pos & 3) == 0\n      size_t i = pos >= TEMP_BUF_SIZE ? TEMP_BUF_SIZE : (size_t)pos;\n      pos -= i;\n      RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, i))\n      i /= 4;\n      do\n        if (buf32[i - 1] != 0)\n          break;\n      while (--i);\n\n      pos += i * 4;\n      #define XZ_STREAM_BACKWARD_READING_PAD_MAX (1 << 16)\n      // here we don't support rare case with big padding for xz stream.\n      // so we have padding limit for backward reading.\n      if ((UInt64)*startOffset - pos > XZ_STREAM_BACKWARD_READING_PAD_MAX)\n        return SZ_ERROR_NO_ARCHIVE;\n      if (i)\n        break;\n    }\n    // we try to open xz stream after skipping zero padding.\n    // ((UInt64)*startOffset == pos) is possible here!\n    if (pos < XZ_STREAM_FOOTER_SIZE)\n      return SZ_ERROR_NO_ARCHIVE;\n    pos -= XZ_STREAM_FOOTER_SIZE;\n    RINOK(LookInStream_SeekRead_ForArc(stream, pos, buf32, XZ_STREAM_FOOTER_SIZE))\n    if (!XZ_FOOTER_12B_ALIGNED16_SIG_CHECK(buf32))\n      return SZ_ERROR_NO_ARCHIVE;\n  }\n  \n  p->flags = (CXzStreamFlags)GetBe16a(buf32 + 2);\n  if (!XzFlags_IsSupported(p->flags))\n    return SZ_ERROR_UNSUPPORTED;\n  {\n    /* to eliminate GCC 6.3 warning:\n       dereferencing type-punned pointer will break strict-aliasing rules */\n    const UInt32 *buf_ptr = buf32;\n    if (GetUi32a(buf_ptr) != CrcCalc(buf32 + 1, 6))\n      return SZ_ERROR_ARCHIVE;\n  }\n  {\n    const UInt64 indexSize = ((UInt64)GetUi32a(buf32 + 1) + 1) << 2;\n    if (pos < indexSize)\n      return SZ_ERROR_ARCHIVE;\n    pos -= indexSize;\n    // v25.00: relaxed indexSize check. We allow big index table.\n    // if (indexSize > ((UInt32)1 << 31))\n    if (indexSize >= ((size_t)1 << (sizeof(size_t) * 8 - 1)))\n      return SZ_ERROR_MEM; // SZ_ERROR_ARCHIVE\n    RINOK(LookInStream_SeekTo(stream, pos))\n    // RINOK(Xz_ReadIndex(p, stream, indexSize, alloc))\n    {\n      SRes res;\n      const size_t size = (size_t)indexSize;\n      // if (size != indexSize) return SZ_ERROR_UNSUPPORTED;\n      Byte *buf = (Byte *)ISzAlloc_Alloc(alloc, size);\n      if (!buf)\n        return SZ_ERROR_MEM;\n      res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);\n      if (res == SZ_OK)\n        res = Xz_ParseIndex(p, buf, size, alloc);\n      ISzAlloc_Free(alloc, buf);\n      RINOK(res)\n    }\n  }\n  {\n    UInt64 total = Xz_GetPackSize(p);\n    if (total == XZ_SIZE_OVERFLOW || total >= ((UInt64)1 << 63))\n      return SZ_ERROR_ARCHIVE;\n    total += XZ_STREAM_HEADER_SIZE;\n    if (pos < total)\n      return SZ_ERROR_ARCHIVE;\n    pos -= total;\n    RINOK(LookInStream_SeekTo(stream, pos))\n    *startOffset = (Int64)pos;\n  }\n  {\n    CXzStreamFlags headerFlags;\n    CSecToRead secToRead;\n    SecToRead_CreateVTable(&secToRead);\n    secToRead.realStream = stream;\n    RINOK(Xz_ReadHeader(&headerFlags, &secToRead.vt))\n    return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;\n  }\n}\n\n\n/* ---------- Xz Streams ---------- */\n\nvoid Xzs_Construct(CXzs *p)\n{\n  Xzs_CONSTRUCT(p)\n}\n\nvoid Xzs_Free(CXzs *p, ISzAllocPtr alloc)\n{\n  size_t i;\n  for (i = 0; i < p->num; i++)\n    Xz_Free(&p->streams[i], alloc);\n  ISzAlloc_Free(alloc, p->streams);\n  p->num = p->numAllocated = 0;\n  p->streams = NULL;\n}\n\nUInt64 Xzs_GetNumBlocks(const CXzs *p)\n{\n  UInt64 num = 0;\n  size_t i;\n  for (i = 0; i < p->num; i++)\n    num += p->streams[i].numBlocks;\n  return num;\n}\n\nUInt64 Xzs_GetUnpackSize(const CXzs *p)\n{\n  UInt64 size = 0;\n  size_t i;\n  for (i = 0; i < p->num; i++)\n  {\n    ADD_SIZE_CHECK(size, Xz_GetUnpackSize(&p->streams[i]))\n  }\n  return size;\n}\n\n/*\nUInt64 Xzs_GetPackSize(const CXzs *p)\n{\n  UInt64 size = 0;\n  size_t i;\n  for (i = 0; i < p->num; i++)\n  {\n    ADD_SIZE_CHECK(size, Xz_GetTotalSize(&p->streams[i]))\n  }\n  return size;\n}\n*/\n\nSRes Xzs_ReadBackward(CXzs *p, ILookInStreamPtr stream, Int64 *startOffset, ICompressProgressPtr progress, ISzAllocPtr alloc)\n{\n  Int64 endOffset = 0;\n  // it's supposed that CXzs object is empty here.\n  // if CXzs object is not empty, it will add new streams to that non-empty object.\n  // Xzs_Free(p, alloc); // it's optional call to empty CXzs object.\n  RINOK(ILookInStream_Seek(stream, &endOffset, SZ_SEEK_END))\n  *startOffset = endOffset;\n  for (;;)\n  {\n    CXzStream st;\n    SRes res;\n    Xz_CONSTRUCT(&st)\n    res = Xz_ReadBackward(&st, stream, startOffset, alloc);\n    // if (res == SZ_OK), then (*startOffset) is start offset of new stream if\n    // if (res != SZ_OK), then (*startOffset) is unchend or it's expected start offset of stream with error\n    st.startOffset = (UInt64)*startOffset;\n    // we must store (st) object to array, or we must free (st) local object.\n    if (res != SZ_OK)\n    {\n      Xz_Free(&st, alloc);\n      return res;\n    }\n    if (p->num == p->numAllocated)\n    {\n      const size_t newNum = p->num + p->num / 4 + 1;\n      void *data = ISzAlloc_Alloc(alloc, newNum * sizeof(CXzStream));\n      if (!data)\n      {\n        Xz_Free(&st, alloc);\n        return SZ_ERROR_MEM;\n      }\n      p->numAllocated = newNum;\n      if (p->num != 0)\n        memcpy(data, p->streams, p->num * sizeof(CXzStream));\n      ISzAlloc_Free(alloc, p->streams);\n      p->streams = (CXzStream *)data;\n    }\n    // we use direct copying of raw data from local variable (st) to object in array.\n    // so we don't need to call Xz_Free(&st, alloc) after copying and after p->num++\n    p->streams[p->num++] = st;\n    if (*startOffset == 0)\n      return SZ_OK;\n    // seek operation is optional:\n    // RINOK(LookInStream_SeekTo(stream, (UInt64)*startOffset))\n    if (progress && ICompressProgress_Progress(progress, (UInt64)(endOffset - *startOffset), (UInt64)(Int64)-1) != SZ_OK)\n      return SZ_ERROR_PROGRESS;\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zCompressionMode.h",
    "content": "﻿// 7zCompressionMode.h\n\n#ifndef ZIP7_INC_7Z_COMPRESSION_MODE_H\n#define ZIP7_INC_7Z_COMPRESSION_MODE_H\n\n#include \"../../Common/MethodId.h\"\n#include \"../../Common/MethodProps.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nstruct CMethodFull: public CMethodProps\n{\n  CMethodId Id;\n  UInt32 NumStreams;\n  int CodecIndex;\n  UInt32 NumThreads;\n  bool Set_NumThreads;\n\n  CMethodFull(): CodecIndex(-1), NumThreads(1), Set_NumThreads(false) {}\n  bool IsSimpleCoder() const { return NumStreams == 1; }\n};\n\nstruct CBond2\n{\n  UInt32 OutCoder;\n  UInt32 OutStream;\n  UInt32 InCoder;\n};\n\nstruct CCompressionMethodMode\n{\n  /*\n    if (Bonds.Empty()), then default bonds must be created\n    if (Filter_was_Inserted)\n    {\n      Methods[0] is filter method\n      Bonds don't contain bonds for filter (these bonds must be created)\n    }\n  */\n\n  CObjectVector<CMethodFull> Methods;\n  CRecordVector<CBond2> Bonds;\n\n  bool IsThereBond_to_Coder(unsigned coderIndex) const\n  {\n    FOR_VECTOR(i, Bonds)\n      if (Bonds[i].InCoder == coderIndex)\n        return true;\n    return false;\n  }\n\n  bool DefaultMethod_was_Inserted;\n  bool Filter_was_Inserted;\n  bool PasswordIsDefined;\n  bool MemoryUsageLimit_WasSet;\n\n  #ifndef Z7_ST\n  bool NumThreads_WasForced;\n  bool MultiThreadMixer;\n  UInt32 NumThreads;\n  UInt32 NumThreadGroups;\n  #endif\n\n  UString Password; // _Wipe\n  UInt64 MemoryUsageLimit;\n \n  bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }\n  CCompressionMethodMode():\n        DefaultMethod_was_Inserted(false)\n      , Filter_was_Inserted(false)\n      , PasswordIsDefined(false)\n      , MemoryUsageLimit_WasSet(false)\n      #ifndef Z7_ST\n      , NumThreads_WasForced(false)\n      , MultiThreadMixer(true)\n      , NumThreads(1)\n      , NumThreadGroups(0)\n      #endif\n      , MemoryUsageLimit((UInt64)1 << 30)\n  {}\n\n#ifdef Z7_CPP_IS_SUPPORTED_default\n  CCompressionMethodMode(const CCompressionMethodMode &) = default;\n  CCompressionMethodMode& operator =(const CCompressionMethodMode &) = default;\n#endif\n  ~CCompressionMethodMode() { Password.Wipe_and_Empty(); }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zDecode.cpp",
    "content": "﻿// 7zDecode.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"7zDecode.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nZ7_CLASS_IMP_COM_1(\n  CDecProgress\n  , ICompressProgressInfo\n)\n  CMyComPtr<ICompressProgressInfo> _progress;\npublic:\n  CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}\n};\n\nZ7_COM7F_IMF(CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize))\n{\n  return _progress->SetRatioInfo(NULL, outSize);\n}\n\nstatic void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)\n{\n  bi.Clear();\n  \n  bi.Bonds.ClearAndSetSize(folder.Bonds.Size());\n  unsigned i;\n  for (i = 0; i < folder.Bonds.Size(); i++)\n  {\n    NCoderMixer2::CBond &bond = bi.Bonds[i];\n    const N7z::CBond &folderBond = folder.Bonds[i];\n    bond.PackIndex = folderBond.PackIndex;\n    bond.UnpackIndex = folderBond.UnpackIndex;\n  }\n\n  bi.Coders.ClearAndSetSize(folder.Coders.Size());\n  bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());\n  for (i = 0; i < folder.Coders.Size(); i++)\n  {\n    const CCoderInfo &coderInfo = folder.Coders[i];\n    bi.Coders[i].NumStreams = coderInfo.NumStreams;\n    bi.CoderMethodIDs[i] = coderInfo.MethodID;\n  }\n  \n  /*\n  if (!bi.SetUnpackCoder())\n    throw 1112;\n  */\n  bi.UnpackCoder = folder.UnpackCoder;\n  bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());\n  for (i = 0; i < folder.PackStreams.Size(); i++)\n    bi.PackStreams[i] = folder.PackStreams[i];\n}\n\nstatic inline bool AreCodersEqual(\n    const NCoderMixer2::CCoderStreamsInfo &a1,\n    const NCoderMixer2::CCoderStreamsInfo &a2)\n{\n  return (a1.NumStreams == a2.NumStreams);\n}\n\nstatic inline bool AreBondsEqual(\n    const NCoderMixer2::CBond &a1,\n    const NCoderMixer2::CBond &a2)\n{\n  return\n    (a1.PackIndex == a2.PackIndex) &&\n    (a1.UnpackIndex == a2.UnpackIndex);\n}\n\nstatic bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)\n{\n  if (a1.Coders.Size() != a2.Coders.Size())\n    return false;\n  unsigned i;\n  for (i = 0; i < a1.Coders.Size(); i++)\n    if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))\n      return false;\n  \n  if (a1.Bonds.Size() != a2.Bonds.Size())\n    return false;\n  for (i = 0; i < a1.Bonds.Size(); i++)\n    if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))\n      return false;\n  \n  for (i = 0; i < a1.CoderMethodIDs.Size(); i++)\n    if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])\n      return false;\n  \n  if (a1.PackStreams.Size() != a2.PackStreams.Size())\n    return false;\n  for (i = 0; i < a1.PackStreams.Size(); i++)\n    if (a1.PackStreams[i] != a2.PackStreams[i])\n      return false;\n\n  /*\n  if (a1.UnpackCoder != a2.UnpackCoder)\n    return false;\n  */\n  return true;\n}\n\nCDecoder::CDecoder(bool useMixerMT):\n    _bindInfoPrev_Defined(false)\n{\n  #if defined(USE_MIXER_ST) && defined(USE_MIXER_MT)\n  _useMixerMT = useMixerMT;\n  #else\n  UNUSED_VAR(useMixerMT)\n  #endif\n}\n\n\nZ7_CLASS_IMP_COM_0(\n  CLockedInStream\n)\npublic:\n  CMyComPtr<IInStream> Stream;\n  UInt64 Pos;\n\n  #ifdef USE_MIXER_MT\n  NWindows::NSynchronization::CCriticalSection CriticalSection;\n  #endif\n};\n\n\n#ifdef USE_MIXER_MT\n\nZ7_CLASS_IMP_COM_1(\n  CLockedSequentialInStreamMT\n  , ISequentialInStream\n)\n  CLockedInStream *_glob;\n  UInt64 _pos;\n  CMyComPtr<IUnknown> _globRef;\npublic:\n  void Init(CLockedInStream *lockedInStream, UInt64 startPos)\n  {\n    _globRef = lockedInStream;\n    _glob = lockedInStream;\n    _pos = startPos;\n  }\n};\n\nZ7_COM7F_IMF(CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);\n\n  if (_pos != _glob->Pos)\n  {\n    RINOK(InStream_SeekSet(_glob->Stream, _pos))\n    _glob->Pos = _pos;\n  }\n\n  UInt32 realProcessedSize = 0;\n  const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);\n  _pos += realProcessedSize;\n  _glob->Pos = _pos;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return res;\n}\n\n#endif\n\n\n#ifdef USE_MIXER_ST\n\nZ7_CLASS_IMP_COM_1(\n  CLockedSequentialInStreamST\n  , ISequentialInStream\n)\n  CLockedInStream *_glob;\n  UInt64 _pos;\n  CMyComPtr<IUnknown> _globRef;\npublic:\n  void Init(CLockedInStream *lockedInStream, UInt64 startPos)\n  {\n    _globRef = lockedInStream;\n    _glob = lockedInStream;\n    _pos = startPos;\n  }\n};\n\nZ7_COM7F_IMF(CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (_pos != _glob->Pos)\n  {\n    RINOK(InStream_SeekSet(_glob->Stream, _pos))\n    _glob->Pos = _pos;\n  }\n\n  UInt32 realProcessedSize = 0;\n  const HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);\n  _pos += realProcessedSize;\n  _glob->Pos = _pos;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return res;\n}\n\n#endif\n\n\n\nHRESULT CDecoder::Decode(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    IInStream *inStream,\n    UInt64 startPos,\n    const CFolders &folders, unsigned folderIndex,\n    const UInt64 *unpackSize\n\n    , ISequentialOutStream *outStream\n    , ICompressProgressInfo *compressProgress\n    \n    , ISequentialInStream **\n        #ifdef USE_MIXER_ST\n        inStreamMainRes\n        #endif\n\n    , bool &dataAfterEnd_Error\n    \n    Z7_7Z_DECODER_CRYPRO_VARS_DECL\n\n    #if !defined(Z7_ST)\n    , bool mtMode, UInt32 numThreads, UInt64 memUsage\n    #endif\n    )\n{\n  dataAfterEnd_Error = false;\n\n  const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];\n  CFolderEx folderInfo;\n  folders.ParseFolderEx(folderIndex, folderInfo);\n\n  if (!folderInfo.IsDecodingSupported())\n    return E_NOTIMPL;\n\n  CBindInfoEx bindInfo;\n  Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);\n  if (!bindInfo.CalcMapsAndCheck())\n    return E_NOTIMPL;\n  \n  UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);\n  bool fullUnpack = true;\n  if (unpackSize)\n  {\n    if (*unpackSize > folderUnpackSize)\n      return E_FAIL;\n    fullUnpack = (*unpackSize == folderUnpackSize);\n  }\n\n  /*\n  We don't need to init isEncrypted and passwordIsDefined\n  We must upgrade them only\n  \n  #ifndef Z7_NO_CRYPTO\n  isEncrypted = false;\n  passwordIsDefined = false;\n  #endif\n  */\n  \n  if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))\n  {\n    _bindInfoPrev_Defined = false;\n    _mixerRef.Release();\n\n    #ifdef USE_MIXER_MT\n    #ifdef USE_MIXER_ST\n    if (_useMixerMT)\n    #endif\n    {\n      _mixerMT = new NCoderMixer2::CMixerMT(false);\n      _mixerRef = _mixerMT;\n      _mixer = _mixerMT;\n    }\n    #ifdef USE_MIXER_ST\n    else\n    #endif\n    #endif\n    {\n      #ifdef USE_MIXER_ST\n      _mixerST = new NCoderMixer2::CMixerST(false);\n      _mixerRef = _mixerST;\n      _mixer = _mixerST;\n      #endif\n    }\n    \n    RINOK(_mixer->SetBindInfo(bindInfo))\n    \n    FOR_VECTOR(i, folderInfo.Coders)\n    {\n      const CCoderInfo &coderInfo = folderInfo.Coders[i];\n\n      #ifndef Z7_SFX\n      // we don't support RAR codecs here\n      if ((coderInfo.MethodID >> 8) == 0x403)\n        return E_NOTIMPL;\n      #endif\n  \n      CCreatedCoder cod;\n      RINOK(CreateCoder_Id(\n          EXTERNAL_CODECS_LOC_VARS\n          coderInfo.MethodID, false, cod))\n    \n      if (coderInfo.IsSimpleCoder())\n      {\n        if (!cod.Coder)\n          return E_NOTIMPL;\n        // CMethodId m = coderInfo.MethodID;\n        // isFilter = (IsFilterMethod(m) || m == k_AES);\n      }\n      else\n      {\n        if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)\n          return E_NOTIMPL;\n      }\n      _mixer->AddCoder(cod);\n      \n      // now there is no codec that uses another external codec\n      /*\n      #ifdef Z7_EXTERNAL_CODECS\n      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\n      decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\n      if (setCompressCodecsInfo)\n      {\n        // we must use g_ExternalCodecs also\n        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));\n      }\n      #endif\n      */\n    }\n    \n    _bindInfoPrev = bindInfo;\n    _bindInfoPrev_Defined = true;\n  }\n\n  RINOK(_mixer->ReInit2())\n  \n  UInt32 packStreamIndex = 0;\n  UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];\n\n  unsigned i;\n\n  #if !defined(Z7_ST)\n  bool mt_wasUsed = false;\n  #endif\n\n  for (i = 0; i < folderInfo.Coders.Size(); i++)\n  {\n    const CCoderInfo &coderInfo = folderInfo.Coders[i];\n    IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();\n\n    // now there is no codec that uses another external codec\n    /*\n    #ifdef Z7_EXTERNAL_CODECS\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(ISetCompressCodecsInfo,\n          setCompressCodecsInfo, decoder)\n      if (setCompressCodecsInfo)\n      {\n        // we must use g_ExternalCodecs also\n        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))\n      }\n    }\n    #endif\n    */\n\n    #if !defined(Z7_ST)\n    if (!mt_wasUsed)\n    {\n      if (mtMode)\n      {\n        Z7_DECL_CMyComPtr_QI_FROM(ICompressSetCoderMt,\n            setCoderMt, decoder)\n        if (setCoderMt)\n        {\n          mt_wasUsed = true;\n          RINOK(setCoderMt->SetNumberOfThreads(numThreads))\n        }\n      }\n      // if (memUsage != 0)\n      {\n        Z7_DECL_CMyComPtr_QI_FROM(ICompressSetMemLimit,\n            setMemLimit, decoder)\n        if (setMemLimit)\n        {\n          mt_wasUsed = true;\n          RINOK(setMemLimit->SetMemLimit(memUsage))\n        }\n      }\n    }\n    #endif\n\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          ICompressSetDecoderProperties2,\n          setDecoderProperties, decoder)\n      const CByteBuffer &props = coderInfo.Props;\n      const UInt32 size32 = (UInt32)props.Size();\n      if (props.Size() != size32)\n        return E_NOTIMPL;\n      if (setDecoderProperties)\n      {\n        HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, size32);\n        if (res == E_INVALIDARG)\n          res = E_NOTIMPL;\n        RINOK(res)\n      }\n      else if (size32 != 0)\n      {\n        // v23: we fail, if decoder doesn't support properties\n        return E_NOTIMPL;\n      }\n    }\n\n    #ifndef Z7_NO_CRYPTO\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          ICryptoSetPassword,\n          cryptoSetPassword, decoder)\n      if (cryptoSetPassword)\n      {\n        isEncrypted = true;\n        if (!getTextPassword)\n          return E_NOTIMPL;\n        CMyComBSTR_Wipe passwordBSTR;\n        RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR))\n        passwordIsDefined = true;\n        password.Wipe_and_Empty();\n        size_t len = 0;\n        if (passwordBSTR)\n        {\n          password = passwordBSTR;\n          len = password.Len();\n        }\n        CByteBuffer_Wipe buffer(len * 2);\n        const LPCOLESTR psw = passwordBSTR;\n        for (size_t k = 0; k < len; k++)\n        {\n          const wchar_t c = psw[k];\n          ((Byte *)buffer)[k * 2] = (Byte)c;\n          ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);\n        }\n        RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()))\n      }\n    }\n    #endif\n\n    bool finishMode = false;\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          ICompressSetFinishMode,\n          setFinishMode, decoder)\n      if (setFinishMode)\n      {\n        finishMode = fullUnpack;\n        RINOK(setFinishMode->SetFinishMode(BoolToUInt(finishMode)))\n      }\n    }\n    \n    UInt32 numStreams = (UInt32)coderInfo.NumStreams;\n    \n    CObjArray<UInt64> packSizes(numStreams);\n    CObjArray<const UInt64 *> packSizesPointers(numStreams);\n       \n    for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)\n    {\n      int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);\n      \n      if (bond >= 0)\n        packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];\n      else\n      {\n        int index = folderInfo.Find_in_PackStreams(packStreamIndex);\n        if (index < 0)\n          return E_NOTIMPL;\n        packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];\n        packSizesPointers[j] = &packSizes[j];\n      }\n    }\n\n    const UInt64 *unpackSizesPointer =\n        (unpackSize && i == bindInfo.UnpackCoder) ?\n            unpackSize :\n            &folders.CoderUnpackSizes[unpackStreamIndexStart + i];\n    \n    _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers, finishMode);\n  }\n\n  if (outStream)\n  {\n    _mixer->SelectMainCoder(!fullUnpack);\n  }\n\n  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;\n  \n  CMyComPtr2_Create<IUnknown, CLockedInStream> lockedInStream;\n\n  #ifdef USE_MIXER_MT\n  #ifdef USE_MIXER_ST\n  bool needMtLock = _useMixerMT;\n  #endif\n  #endif\n\n  if (folderInfo.PackStreams.Size() > 1)\n  {\n    // lockedInStream.Pos = (UInt64)(Int64)-1;\n    // RINOK(InStream_GetPos(inStream, lockedInStream.Pos))\n    RINOK(inStream->Seek((Int64)(startPos + packPositions[0]), STREAM_SEEK_SET, &lockedInStream->Pos))\n    lockedInStream->Stream = inStream;\n\n    #ifdef USE_MIXER_MT\n    #ifdef USE_MIXER_ST\n    /*\n      For ST-mixer mode:\n      If parallel input stream reading from pack streams is possible,\n      we must use MT-lock for packed streams.\n      Internal decoders in 7-Zip will not read pack streams in parallel in ST-mixer mode.\n      So we force to needMtLock mode only if there is unknown (external) decoder.\n    */\n    if (!needMtLock && _mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))\n      needMtLock = true;\n    #endif\n    #endif\n  }\n\n  for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)\n  {\n    CMyComPtr<ISequentialInStream> packStream;\n    const UInt64 packPos = startPos + packPositions[j];\n\n    if (folderInfo.PackStreams.Size() == 1)\n    {\n      RINOK(InStream_SeekSet(inStream, packPos))\n      packStream = inStream;\n    }\n    else\n    {\n      #ifdef USE_MIXER_MT\n      #ifdef USE_MIXER_ST\n      if (needMtLock)\n      #endif\n      {\n        CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;\n        packStream = lockedStreamImpSpec;\n        lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);\n      }\n      #ifdef USE_MIXER_ST\n      else\n      #endif\n      #endif\n      {\n        #ifdef USE_MIXER_ST\n        CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;\n        packStream = lockedStreamImpSpec;\n        lockedStreamImpSpec->Init(lockedInStream.ClsPtr(), packPos);\n        #endif\n      }\n    }\n\n    CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\n    inStreams.AddNew() = streamSpec;\n    streamSpec->SetStream(packStream);\n    streamSpec->Init(packPositions[j + 1] - packPositions[j]);\n  }\n  \n  const unsigned num = inStreams.Size();\n  CObjArray<ISequentialInStream *> inStreamPointers(num);\n  for (i = 0; i < num; i++)\n    inStreamPointers[i] = inStreams[i];\n\n  if (outStream)\n  {\n    CMyComPtr<ICompressProgressInfo> progress2;\n    if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))\n      progress2 = new CDecProgress(compressProgress);\n\n    ISequentialOutStream *outStreamPointer = outStream;\n    return _mixer->Code(inStreamPointers, &outStreamPointer,\n        progress2 ? (ICompressProgressInfo *)progress2 : compressProgress,\n        dataAfterEnd_Error);\n  }\n  \n  #ifdef USE_MIXER_ST\n    return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);\n  #else\n    return E_FAIL;\n  #endif\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zDecode.h",
    "content": "﻿// 7zDecode.h\n\n#ifndef ZIP7_INC_7Z_DECODE_H\n#define ZIP7_INC_7Z_DECODE_H\n\n#include \"../Common/CoderMixer2.h\"\n\n#include \"7zIn.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nstruct CBindInfoEx: public NCoderMixer2::CBindInfo\n{\n  CRecordVector<CMethodId> CoderMethodIDs;\n\n  void Clear()\n  {\n    CBindInfo::Clear();\n    CoderMethodIDs.Clear();\n  }\n};\n\nclass CDecoder\n{\n  bool _bindInfoPrev_Defined;\n  #ifdef USE_MIXER_ST\n  #ifdef USE_MIXER_MT\n    bool _useMixerMT;\n  #endif\n  #endif\n  CBindInfoEx _bindInfoPrev;\n  \n  #ifdef USE_MIXER_ST\n    NCoderMixer2::CMixerST *_mixerST;\n  #endif\n  \n  #ifdef USE_MIXER_MT\n    NCoderMixer2::CMixerMT *_mixerMT;\n  #endif\n  \n  NCoderMixer2::CMixer *_mixer;\n  CMyComPtr<IUnknown> _mixerRef;\n\npublic:\n\n  CDecoder(bool useMixerMT);\n  \n  HRESULT Decode(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      IInStream *inStream,\n      UInt64 startPos,\n      const CFolders &folders, unsigned folderIndex,\n      const UInt64 *unpackSize // if (!unpackSize), then full folder is required\n                               // if (unpackSize), then only *unpackSize bytes from folder are required\n\n      , ISequentialOutStream *outStream\n      , ICompressProgressInfo *compressProgress\n\n      , ISequentialInStream **inStreamMainRes\n      , bool &dataAfterEnd_Error\n      \n      Z7_7Z_DECODER_CRYPRO_VARS_DECL\n      \n      #if !defined(Z7_ST)\n      , bool mtMode, UInt32 numThreads, UInt64 memUsage\n      #endif\n      );\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zEncode.cpp",
    "content": "﻿// 7zEncode.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/FilterCoder.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/InOutTempBuffer.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamObjects.h\"\n\n#include \"7zEncode.h\"\n#include \"7zSpecStream.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nvoid CEncoder::InitBindConv()\n{\n  unsigned numIn = _bindInfo.Coders.Size();\n  \n  SrcIn_to_DestOut.ClearAndSetSize(numIn);\n  DestOut_to_SrcIn.ClearAndSetSize(numIn);\n\n  unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();\n  SrcOut_to_DestIn.ClearAndSetSize(numOut);\n  // _DestIn_to_SrcOut.ClearAndSetSize(numOut);\n\n  UInt32 destIn = 0;\n  UInt32 destOut = 0;\n\n  for (unsigned i = _bindInfo.Coders.Size(); i != 0;)\n  {\n    i--;\n\n    const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];\n\n    numIn--;\n    numOut -= coder.NumStreams;\n    \n    SrcIn_to_DestOut[numIn] = destOut;\n    DestOut_to_SrcIn[destOut] = numIn;\n\n    destOut++;\n  \n    for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)\n    {\n      UInt32 index = numOut + j;\n      SrcOut_to_DestIn[index] = destIn;\n      // _DestIn_to_SrcOut[destIn] = index;\n    }\n  }\n}\n\nvoid CEncoder::SetFolder(CFolder &folder)\n{\n  folder.Bonds.SetSize(_bindInfo.Bonds.Size());\n  \n  unsigned i;\n\n  for (i = 0; i < _bindInfo.Bonds.Size(); i++)\n  {\n    CBond &fb = folder.Bonds[i];\n    const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];\n    fb.PackIndex = SrcOut_to_DestIn[mixerBond.PackIndex];\n    fb.UnpackIndex = SrcIn_to_DestOut[mixerBond.UnpackIndex];\n  }\n  \n  folder.Coders.SetSize(_bindInfo.Coders.Size());\n  \n  for (i = 0; i < _bindInfo.Coders.Size(); i++)\n  {\n    CCoderInfo &coderInfo = folder.Coders[i];\n    const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];\n    \n    coderInfo.NumStreams = coderStreamsInfo.NumStreams;\n    coderInfo.MethodID = _decompressionMethods[i];\n    // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.\n  }\n  \n  folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());\n  \n  for (i = 0; i < _bindInfo.PackStreams.Size(); i++)\n    folder.PackStreams[i] = SrcOut_to_DestIn[_bindInfo.PackStreams[i]];\n}\n\n\n\nstatic HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)\n{\n  Z7_DECL_CMyComPtr_QI_FROM(\n      ICompressSetCoderProperties,\n      setCoderProperties, coder)\n  if (setCoderProperties)\n    return props.SetCoderProps(setCoderProperties, dataSizeReduce);\n  return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;\n}\n\n\n\nvoid CMtEncMultiProgress::Init(ICompressProgressInfo *progress)\n{\n  _progress = progress;\n  OutSize = 0;\n}\n\nZ7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))\n{\n  UInt64 outSize2;\n  {\n    #ifndef Z7_ST\n    NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\n    #endif\n    outSize2 = OutSize;\n  }\n  \n  if (_progress)\n    return _progress->SetRatioInfo(inSize, &outSize2);\n   \n  return S_OK;\n}\n\n\n\nHRESULT CEncoder::CreateMixerCoder(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const UInt64 *inSizeForReduce)\n{\n  #ifdef USE_MIXER_MT\n  #ifdef USE_MIXER_ST\n  if (_options.MultiThreadMixer)\n  #endif\n  {\n    _mixerMT = new NCoderMixer2::CMixerMT(true);\n    _mixerRef = _mixerMT;\n    _mixer = _mixerMT;\n  }\n  #ifdef USE_MIXER_ST\n  else\n  #endif\n  #endif\n  {\n    #ifdef USE_MIXER_ST\n    _mixerST = new NCoderMixer2::CMixerST(true);\n    _mixerRef = _mixerST;\n    _mixer = _mixerST;\n    #endif\n  }\n\n  RINOK(_mixer->SetBindInfo(_bindInfo))\n\n  FOR_VECTOR (m, _options.Methods)\n  {\n    const CMethodFull &methodFull = _options.Methods[m];\n\n    CCreatedCoder cod;\n    \n    if (methodFull.CodecIndex >= 0)\n    {\n      RINOK(CreateCoder_Index(\n        EXTERNAL_CODECS_LOC_VARS\n        (unsigned)methodFull.CodecIndex, true, cod))\n    }\n    else\n    {\n      RINOK(CreateCoder_Id(\n        EXTERNAL_CODECS_LOC_VARS\n        methodFull.Id, true, cod))\n    }\n\n    if (!cod.Coder && !cod.Coder2)\n    {\n      return E_NOTIMPL; // unsupported method, if encoder\n      // return E_FAIL;\n    }\n\n    if (cod.NumStreams != methodFull.NumStreams)\n      return E_FAIL;\n\n    CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;\n   \n    #ifndef Z7_ST\n    if (methodFull.Set_NumThreads)\n    {\n      CMyComPtr<ICompressSetCoderMt> setCoderMt;\n      encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);\n      if (setCoderMt)\n      {\n        RINOK(setCoderMt->SetNumberOfThreads(\n            /* _options.NumThreads */\n            methodFull.NumThreads\n            ))\n      }\n    }\n    #endif\n        \n    RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon))\n\n    /*\n    CMyComPtr<ICryptoResetSalt> resetSalt;\n    encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);\n    if (resetSalt)\n    {\n      resetSalt->ResetSalt();\n    }\n    */\n\n    // now there is no codec that uses another external codec\n    /*\n    #ifdef Z7_EXTERNAL_CODECS\n    CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\n    encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\n    if (setCompressCodecsInfo)\n    {\n      // we must use g_ExternalCodecs also\n      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));\n    }\n    #endif\n    */\n    \n    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;\n    encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);\n\n    if (cryptoSetPassword)\n    {\n      const unsigned sizeInBytes = _options.Password.Len() * 2;\n      CByteBuffer_Wipe buffer(sizeInBytes);\n      for (unsigned i = 0; i < _options.Password.Len(); i++)\n      {\n        wchar_t c = _options.Password[i];\n        ((Byte *)buffer)[i * 2] = (Byte)c;\n        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);\n      }\n      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes))\n    }\n\n    _mixer->AddCoder(cod);\n  }\n  return S_OK;\n}\n\n\n\nZ7_CLASS_IMP_COM_1(\n  CSequentialOutTempBufferImp2\n  , ISequentialOutStream\n)\npublic:\n  CInOutTempBuffer TempBuffer;\n  CMtEncMultiProgress *_mtProgressSpec;\n  \n  CSequentialOutTempBufferImp2(): _mtProgressSpec(NULL) {}\n};\n\nZ7_COM7F_IMF(CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed))\n{\n  COM_TRY_BEGIN\n  if (processed)\n    *processed = 0;\n  RINOK(TempBuffer.Write_HRESULT(data, size))\n  if (processed)\n    *processed = size;\n  if (_mtProgressSpec)\n    _mtProgressSpec->AddOutSize(size);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_CLASS_IMP_COM_1(\n  CSequentialOutMtNotify\n  , ISequentialOutStream\n)\npublic:\n  CMyComPtr<ISequentialOutStream> _stream;\n  CMtEncMultiProgress *_mtProgressSpec;\n  \n  CSequentialOutMtNotify(): _mtProgressSpec(NULL) {}\n};\n\nZ7_COM7F_IMF(CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed))\n{\n  UInt32 realProcessed = 0;\n  HRESULT res = _stream->Write(data, size, &realProcessed);\n  if (processed)\n    *processed = realProcessed;\n  if (_mtProgressSpec)\n    _mtProgressSpec->AddOutSize(size);\n  return res;\n}\n\n\nstatic HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)\n{\n  Z7_DECL_CMyComPtr_QI_FROM(\n      ICompressWriteCoderProperties,\n      writeCoderProperties, coder)\n  if (writeCoderProperties)\n  {\n    CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> outStreamSpec;\n    outStreamSpec->Init();\n    RINOK(writeCoderProperties->WriteCoderProperties(outStreamSpec))\n    outStreamSpec->CopyToBuffer(props);\n  }\n  else\n    props.Free();\n  return S_OK;\n}\n\nHRESULT CEncoder::Encode1(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    ISequentialInStream *inStream,\n    // const UInt64 *inStreamSize,\n    const UInt64 *inSizeForReduce,\n    UInt64 expectedDataSize,\n    CFolder &folderItem,\n    // CRecordVector<UInt64> &coderUnpackSizes,\n    // UInt64 &unpackSize,\n    ISequentialOutStream *outStream,\n    CRecordVector<UInt64> &packSizes,\n    ICompressProgressInfo *compressProgress)\n{\n  RINOK(EncoderConstr())\n\n  if (!_mixerRef)\n  {\n    RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce))\n  }\n  \n  RINOK(_mixer->ReInit2())\n\n  CMyComPtr2<ICompressProgressInfo, CMtEncMultiProgress> mtProgress;\n  CMyComPtr2<ISequentialOutStream, CSequentialOutMtNotify> mtOutStreamNotify;\n\n  CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;\n  CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;\n  \n  unsigned i;\n\n  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)\n  {\n    CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2();\n    CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;\n    tempBufferSpecs.Add(tempBufferSpec);\n    tempBuffers.Add(tempBuffer);\n  }\n\n  const unsigned numMethods = _bindInfo.Coders.Size();\n\n  for (i = 0; i < numMethods; i++)\n    _mixer->SetCoderInfo(i, NULL, NULL, false);\n\n\n  /* inStreamSize can be used by BCJ2 to set optimal range of conversion.\n     But current BCJ2 encoder uses also another way to check exact size of current file.\n     So inStreamSize is not required. */\n\n  /*\n  if (inStreamSize)\n    _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);\n  */\n\n  \n  /*\n  CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;\n  CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;\n  */\n\n  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;\n  CMyComPtr<ISequentialOutStream> outStreamSizeCount;\n\n  // inStreamSizeCountSpec->Init(inStream);\n\n  // ISequentialInStream *inStreamPointer = inStreamSizeCount;\n  ISequentialInStream *inStreamPointer = inStream;\n\n  CRecordVector<ISequentialOutStream *> outStreamPointers;\n  \n  SetFolder(folderItem);\n\n  for (i = 0; i < numMethods; i++)\n  {\n    IUnknown *coder = _mixer->GetCoder(i).GetUnknown();\n    /*\n    {\n      CEncoder *sfEncoder = NULL;\n      Z7_DECL_CMyComPtr_QI_FROM(\n          IGetSfEncoderInternal,\n          sf, coder)\n      if (sf)\n      {\n        RINOK(sf->GetSfEncoder(&sfEncoder));\n        if (!sfEncoder)\n          return E_FAIL;\n\n      }\n    }\n    */\n    /*\n    #ifdef Z7_EXTERNAL_CODECS\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          ISetCompressCodecsInfo,\n          setCompressCodecsInfo, coder)\n      if (setCompressCodecsInfo)\n      {\n        // we must use g_ExternalCodecs also\n        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))\n      }\n    }\n    #endif\n    */\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          ICryptoResetInitVector,\n          resetInitVector, coder)\n      if (resetInitVector)\n      {\n        RINOK(resetInitVector->ResetInitVector())\n      }\n    }\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          ICompressSetCoderPropertiesOpt,\n          optProps, coder)\n      if (optProps)\n      {\n        const PROPID propID = NCoderPropID::kExpectedDataSize;\n        NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;\n        RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))\n      }\n    }\n    // we must write properties from coder after ResetInitVector()\n    RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))\n  }\n\n  _mixer->SelectMainCoder(false);\n  const UInt32 mainCoder = _mixer->MainCoderIndex;\n\n  bool useMtProgress = false;\n  if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))\n  {\n    #ifdef Z7_ST\n    if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))\n    #endif\n      useMtProgress = true;\n  }\n\n  if (useMtProgress)\n  {\n    mtProgress.SetFromCls(new CMtEncMultiProgress);\n    mtProgress->Init(compressProgress);\n    \n    mtOutStreamNotify.SetFromCls(new CSequentialOutMtNotify);\n    mtOutStreamNotify->_stream = outStream;\n    mtOutStreamNotify->_mtProgressSpec = mtProgress.ClsPtr();\n    \n    FOR_VECTOR (t, tempBufferSpecs)\n    {\n      tempBufferSpecs[t]->_mtProgressSpec = mtProgress.ClsPtr();\n    }\n  }\n  \n  \n  if (_bindInfo.PackStreams.Size() != 0)\n  {\n    outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;\n    outStreamSizeCount = outStreamSizeCountSpec;\n    outStreamSizeCountSpec->SetStream(mtOutStreamNotify.IsDefined() ?\n        mtOutStreamNotify.Interface() : outStream);\n    outStreamSizeCountSpec->Init();\n    outStreamPointers.Add(outStreamSizeCount);\n  }\n\n  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)\n    outStreamPointers.Add(tempBuffers[i - 1]);\n\n  bool dataAfterEnd_Error;\n\n  RINOK(_mixer->Code(\n      &inStreamPointer,\n      outStreamPointers.ConstData(),\n      mtProgress.IsDefined() ? mtProgress.Interface() :\n        compressProgress, dataAfterEnd_Error))\n  \n  if (_bindInfo.PackStreams.Size() != 0)\n    packSizes.Add(outStreamSizeCountSpec->GetSize());\n  \n  for (i = 1; i < _bindInfo.PackStreams.Size(); i++)\n  {\n    CInOutTempBuffer &iotb = tempBufferSpecs[i - 1]->TempBuffer;\n    RINOK(iotb.WriteToStream(outStream))\n    packSizes.Add(iotb.GetDataSize());\n  }\n\n  /* Code() in some future codec can change properties.\n     v23: so we fill properties again after Code() */\n  for (i = 0; i < numMethods; i++)\n  {\n    IUnknown *coder = _mixer->GetCoder(i).GetUnknown();\n    RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))\n  }\n\n  return S_OK;\n}\n\n\nvoid CEncoder::Encode_Post(\n      UInt64 unpackSize,\n      CRecordVector<UInt64> &coderUnpackSizes)\n{\n  // unpackSize = 0;\n  for (unsigned i = 0; i < _bindInfo.Coders.Size(); i++)\n  {\n    const int bond = _bindInfo.FindBond_for_UnpackStream(DestOut_to_SrcIn[i]);\n    UInt64 streamSize;\n    if (bond < 0)\n    {\n      // streamSize = inStreamSizeCountSpec->GetSize();\n      // unpackSize = streamSize;\n      streamSize = unpackSize;\n    }\n    else\n      streamSize = _mixer->GetBondStreamSize((unsigned)bond);\n    coderUnpackSizes.Add(streamSize);\n  }\n}\n\n\nCEncoder::CEncoder(const CCompressionMethodMode &options):\n    _constructed(false)\n{\n  if (options.IsEmpty())\n    throw 1;\n\n  _options = options;\n\n  #ifdef USE_MIXER_ST\n    _mixerST = NULL;\n  #endif\n  \n  #ifdef USE_MIXER_MT\n    _mixerMT = NULL;\n  #endif\n\n  _mixer = NULL;\n}\n\n\nHRESULT CEncoder::EncoderConstr()\n{\n  if (_constructed)\n    return S_OK;\n  if (_options.Methods.IsEmpty())\n  {\n    // it has only password method;\n    if (!_options.PasswordIsDefined)\n      throw 1;\n    if (!_options.Bonds.IsEmpty())\n      throw 1;\n\n    CMethodFull method;\n    method.Id = k_AES;\n    method.NumStreams = 1;\n    _options.Methods.Add(method);\n\n    NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;\n    coderStreamsInfo.NumStreams = 1;\n    _bindInfo.Coders.Add(coderStreamsInfo);\n  \n    _bindInfo.PackStreams.Add(0);\n    _bindInfo.UnpackCoder = 0;\n  }\n  else\n  {\n\n  UInt32 numOutStreams = 0;\n  unsigned i;\n  \n  for (i = 0; i < _options.Methods.Size(); i++)\n  {\n    const CMethodFull &methodFull = _options.Methods[i];\n    NCoderMixer2::CCoderStreamsInfo cod;\n    \n    cod.NumStreams = methodFull.NumStreams;\n\n    if (_options.Bonds.IsEmpty())\n    {\n      // if there are no bonds in options, we create bonds via first streams of coders\n      if (i != _options.Methods.Size() - 1)\n      {\n        NCoderMixer2::CBond bond;\n        bond.PackIndex = numOutStreams;\n        bond.UnpackIndex = i + 1; // it's next coder\n        _bindInfo.Bonds.Add(bond);\n      }\n      else if (cod.NumStreams != 0)\n        _bindInfo.PackStreams.Insert(0, numOutStreams);\n      \n      for (UInt32 j = 1; j < cod.NumStreams; j++)\n        _bindInfo.PackStreams.Add(numOutStreams + j);\n    }\n    \n    numOutStreams += cod.NumStreams;\n\n    _bindInfo.Coders.Add(cod);\n  }\n\n  if (!_options.Bonds.IsEmpty())\n  {\n    for (i = 0; i < _options.Bonds.Size(); i++)\n    {\n      NCoderMixer2::CBond mixerBond;\n      const CBond2 &bond = _options.Bonds[i];\n      if (bond.InCoder >= _bindInfo.Coders.Size()\n          || bond.OutCoder >= _bindInfo.Coders.Size()\n          || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)\n        return E_INVALIDARG;\n      mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;\n      mixerBond.UnpackIndex = bond.InCoder;\n      _bindInfo.Bonds.Add(mixerBond);\n    }\n\n    for (i = 0; i < numOutStreams; i++)\n      if (_bindInfo.FindBond_for_PackStream(i) == -1)\n        _bindInfo.PackStreams.Add(i);\n  }\n\n  if (!_bindInfo.SetUnpackCoder())\n    return E_INVALIDARG;\n\n  if (!_bindInfo.CalcMapsAndCheck())\n    return E_INVALIDARG;\n\n  if (_bindInfo.PackStreams.Size() != 1)\n  {\n    /* main_PackStream is pack stream of main path of coders tree.\n       We find main_PackStream, and place to start of list of out streams.\n       It allows to use more optimal memory usage for temp buffers,\n       if main_PackStream is largest stream. */\n\n    UInt32 ci = _bindInfo.UnpackCoder;\n    \n    for (;;)\n    {\n      if (_bindInfo.Coders[ci].NumStreams == 0)\n        break;\n      \n      const UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];\n      const int bond = _bindInfo.FindBond_for_PackStream(outIndex);\n      if (bond >= 0)\n      {\n        ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;\n        continue;\n      }\n      \n      const int si = _bindInfo.FindStream_in_PackStreams(outIndex);\n      if (si >= 0)\n        _bindInfo.PackStreams.MoveToFront((unsigned)si);\n      break;\n    }\n  }\n\n  if (_options.PasswordIsDefined)\n  {\n    unsigned numCryptoStreams = _bindInfo.PackStreams.Size();\n\n    unsigned numInStreams = _bindInfo.Coders.Size();\n    \n    for (i = 0; i < numCryptoStreams; i++)\n    {\n      NCoderMixer2::CBond bond;\n      bond.UnpackIndex = numInStreams + i;\n      bond.PackIndex = _bindInfo.PackStreams[i];\n      _bindInfo.Bonds.Add(bond);\n    }\n    _bindInfo.PackStreams.Clear();\n\n    /*\n    if (numCryptoStreams == 0)\n      numCryptoStreams = 1;\n    */\n\n    for (i = 0; i < numCryptoStreams; i++)\n    {\n      CMethodFull method;\n      method.NumStreams = 1;\n      method.Id = k_AES;\n      _options.Methods.Add(method);\n\n      NCoderMixer2::CCoderStreamsInfo cod;\n      cod.NumStreams = 1;\n      _bindInfo.Coders.Add(cod);\n\n      _bindInfo.PackStreams.Add(numOutStreams++);\n    }\n  }\n\n  }\n\n  for (unsigned i = _options.Methods.Size(); i != 0;)\n    _decompressionMethods.Add(_options.Methods[--i].Id);\n\n  if (_bindInfo.Coders.Size() > 16)\n    return E_INVALIDARG;\n  if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)\n    return E_INVALIDARG;\n\n  if (!_bindInfo.CalcMapsAndCheck())\n    return E_INVALIDARG;\n\n  InitBindConv();\n  _constructed = true;\n  return S_OK;\n}\n\nCEncoder::~CEncoder() {}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zEncode.h",
    "content": "﻿// 7zEncode.h\n\n#ifndef ZIP7_INC_7Z_ENCODE_H\n#define ZIP7_INC_7Z_ENCODE_H\n\n#include \"7zCompressionMode.h\"\n\n#include \"../Common/CoderMixer2.h\"\n\n#include \"7zItem.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nZ7_CLASS_IMP_COM_1(\n  CMtEncMultiProgress,\n  ICompressProgressInfo\n)\n  CMyComPtr<ICompressProgressInfo> _progress;\n  #ifndef Z7_ST\n  NWindows::NSynchronization::CCriticalSection CriticalSection;\n  #endif\n\npublic:\n  UInt64 OutSize;\n\n  CMtEncMultiProgress(): OutSize(0) {}\n\n  void Init(ICompressProgressInfo *progress);\n\n  void AddOutSize(UInt64 addOutSize)\n  {\n    #ifndef Z7_ST\n    NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\n    #endif\n    OutSize += addOutSize;\n  }\n};\n\n\nclass CEncoder Z7_final MY_UNCOPYABLE\n{\n  #ifdef USE_MIXER_ST\n    NCoderMixer2::CMixerST *_mixerST;\n  #endif\n  #ifdef USE_MIXER_MT\n    NCoderMixer2::CMixerMT *_mixerMT;\n  #endif\n  \n  NCoderMixer2::CMixer *_mixer;\n  CMyComPtr<IUnknown> _mixerRef;\n\n  CCompressionMethodMode _options;\n  NCoderMixer2::CBindInfo _bindInfo;\n  CRecordVector<CMethodId> _decompressionMethods;\n\n  CRecordVector<UInt32> SrcIn_to_DestOut;\n  CRecordVector<UInt32> SrcOut_to_DestIn;\n  // CRecordVector<UInt32> DestIn_to_SrcOut;\n  CRecordVector<UInt32> DestOut_to_SrcIn;\n\n  void InitBindConv();\n  void SetFolder(CFolder &folder);\n\n  HRESULT CreateMixerCoder(DECL_EXTERNAL_CODECS_LOC_VARS\n      const UInt64 *inSizeForReduce);\n\n  bool _constructed;\npublic:\n\n  CEncoder(const CCompressionMethodMode &options);\n  ~CEncoder();\n  HRESULT EncoderConstr();\n  HRESULT Encode1(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      ISequentialInStream *inStream,\n      // const UInt64 *inStreamSize,\n      const UInt64 *inSizeForReduce,\n      UInt64 expectedDataSize,\n      CFolder &folderItem,\n      // CRecordVector<UInt64> &coderUnpackSizes,\n      // UInt64 &unpackSize,\n      ISequentialOutStream *outStream,\n      CRecordVector<UInt64> &packSizes,\n      ICompressProgressInfo *compressProgress);\n\n  void Encode_Post(\n      UInt64 unpackSize,\n      CRecordVector<UInt64> &coderUnpackSizes);\n\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zExtract.cpp",
    "content": "﻿// 7zExtract.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/7zCrc.h\"\n\n#include \"../../../Common/ComTry.h\"\n\n#include \"../../Common/ProgressUtils.h\"\n\n#include \"7zDecode.h\"\n#include \"7zHandler.h\"\n\n// EXTERN_g_ExternalCodecs\n\nnamespace NArchive {\nnamespace N7z {\n\nZ7_CLASS_IMP_COM_1(\n  CFolderOutStream\n  , ISequentialOutStream\n  /* , ICompressGetSubStreamSize */\n)\n  CMyComPtr<ISequentialOutStream> _stream;\npublic:\n  bool TestMode;\n  bool CheckCrc;\nprivate:\n  bool _fileIsOpen;\n  bool _calcCrc;\n  UInt32 _crc;\n  UInt64 _rem;\n\n  const UInt32 *_indexes;\n  // unsigned _startIndex;\n  unsigned _numFiles;\n  unsigned _fileIndex;\n\n  HRESULT OpenFile(bool isCorrupted = false);\n  HRESULT CloseFile_and_SetResult(Int32 res);\n  HRESULT CloseFile();\n  HRESULT ProcessEmptyFiles();\n\npublic:\n  const CDbEx *_db;\n  CMyComPtr<IArchiveExtractCallback> ExtractCallback;\n\n  bool ExtraWriteWasCut;\n\n  CFolderOutStream():\n      TestMode(false),\n      CheckCrc(true)\n      {}\n\n  HRESULT Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles);\n  HRESULT FlushCorrupted(Int32 callbackOperationResult);\n\n  bool WasWritingFinished() const { return _numFiles == 0; }\n};\n\n\nHRESULT CFolderOutStream::Init(unsigned startIndex, const UInt32 *indexes, unsigned numFiles)\n{\n  // _startIndex = startIndex;\n  _fileIndex = startIndex;\n  _indexes = indexes;\n  _numFiles = numFiles;\n  \n  _fileIsOpen = false;\n  ExtraWriteWasCut = false;\n  \n  return ProcessEmptyFiles();\n}\n\nHRESULT CFolderOutStream::OpenFile(bool isCorrupted)\n{\n  const CFileItem &fi = _db->Files[_fileIndex];\n  const UInt32 nextFileIndex = (_indexes ? *_indexes : _fileIndex);\n  Int32 askMode = (_fileIndex == nextFileIndex) ? TestMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract :\n      NExtract::NAskMode::kSkip;\n\n  if (isCorrupted\n      && askMode == NExtract::NAskMode::kExtract\n      && !_db->IsItemAnti(_fileIndex)\n      && !fi.IsDir)\n    askMode = NExtract::NAskMode::kTest;\n  \n  CMyComPtr<ISequentialOutStream> realOutStream;\n  RINOK(ExtractCallback->GetStream(_fileIndex, &realOutStream, askMode))\n  \n  _stream = realOutStream;\n  _crc = CRC_INIT_VAL;\n  _calcCrc = (CheckCrc && fi.CrcDefined && !fi.IsDir);\n\n  _fileIsOpen = true;\n  _rem = fi.Size;\n  \n  if (askMode == NExtract::NAskMode::kExtract\n      && !realOutStream\n      && !_db->IsItemAnti(_fileIndex)\n      && !fi.IsDir)\n    askMode = NExtract::NAskMode::kSkip;\n  return ExtractCallback->PrepareOperation(askMode);\n}\n\nHRESULT CFolderOutStream::CloseFile_and_SetResult(Int32 res)\n{\n  _stream.Release();\n  _fileIsOpen = false;\n  \n  if (!_indexes)\n    _numFiles--;\n  else if (*_indexes == _fileIndex)\n  {\n    _indexes++;\n    _numFiles--;\n  }\n\n  _fileIndex++;\n  return ExtractCallback->SetOperationResult(res);\n}\n\nHRESULT CFolderOutStream::CloseFile()\n{\n  const CFileItem &fi = _db->Files[_fileIndex];\n  return CloseFile_and_SetResult((!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc)) ?\n      NExtract::NOperationResult::kOK :\n      NExtract::NOperationResult::kCRCError);\n}\n\nHRESULT CFolderOutStream::ProcessEmptyFiles()\n{\n  while (_numFiles != 0 && _db->Files[_fileIndex].Size == 0)\n  {\n    RINOK(OpenFile())\n    RINOK(CloseFile())\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  \n  while (size != 0)\n  {\n    if (_fileIsOpen)\n    {\n      UInt32 cur = (size < _rem ? size : (UInt32)_rem);\n      if (_calcCrc)\n      {\n        const UInt32 k_Step = (UInt32)1 << 20;\n        if (cur > k_Step)\n          cur = k_Step;\n      }\n      HRESULT result = S_OK;\n      if (_stream)\n        result = _stream->Write(data, cur, &cur);\n      if (_calcCrc)\n        _crc = CrcUpdate(_crc, data, cur);\n      if (processedSize)\n        *processedSize += cur;\n      data = (const Byte *)data + cur;\n      size -= cur;\n      _rem -= cur;\n      if (_rem == 0)\n      {\n        RINOK(CloseFile())\n        RINOK(ProcessEmptyFiles())\n      }\n      RINOK(result)\n      if (cur == 0)\n        break;\n      continue;\n    }\n  \n    RINOK(ProcessEmptyFiles())\n    if (_numFiles == 0)\n    {\n      // we support partial extracting\n      /*\n      if (processedSize)\n        *processedSize += size;\n      break;\n      */\n      ExtraWriteWasCut = true;\n      // return S_FALSE;\n      return k_My_HRESULT_WritingWasCut;\n    }\n    RINOK(OpenFile())\n  }\n  \n  return S_OK;\n}\n\nHRESULT CFolderOutStream::FlushCorrupted(Int32 callbackOperationResult)\n{\n  while (_numFiles != 0)\n  {\n    if (_fileIsOpen)\n    {\n      RINOK(CloseFile_and_SetResult(callbackOperationResult))\n    }\n    else\n    {\n      RINOK(OpenFile(true))\n    }\n  }\n  return S_OK;\n}\n\n/*\nZ7_COM7F_IMF(CFolderOutStream::GetSubStreamSize(UInt64 subStream, UInt64 *value))\n{\n  *value = 0;\n  // const unsigned numFiles_Original = _numFiles + _fileIndex - _startIndex;\n  const unsigned numFiles_Original = _numFiles;\n  if (subStream >= numFiles_Original)\n    return S_FALSE; // E_FAIL;\n  *value = _db->Files[_startIndex + (unsigned)subStream].Size;\n  return S_OK;\n}\n*/\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec))\n{\n  // for GCC\n  // CFolderOutStream *folderOutStream = new CFolderOutStream;\n  // CMyComPtr<ISequentialOutStream> outStream(folderOutStream);\n\n  COM_TRY_BEGIN\n  \n  CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;\n  \n  UInt64 importantTotalUnpacked = 0;\n\n  // numItems = (UInt32)(Int32)-1;\n\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _db.Files.Size();\n\n  if (numItems == 0)\n    return S_OK;\n\n  {\n    CNum prevFolder = kNumNoIndex;\n    UInt32 nextFile = 0;\n    \n    UInt32 i;\n    \n    for (i = 0; i < numItems; i++)\n    {\n      const UInt32 fileIndex = allFilesMode ? i : indices[i];\n      const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];\n      if (folderIndex == kNumNoIndex)\n        continue;\n      if (folderIndex != prevFolder || fileIndex < nextFile)\n        nextFile = _db.FolderStartFileIndex[folderIndex];\n      for (CNum index = nextFile; index <= fileIndex; index++)\n        importantTotalUnpacked += _db.Files[index].Size;\n      nextFile = fileIndex + 1;\n      prevFolder = folderIndex;\n    }\n  }\n\n  RINOK(extractCallback->SetTotal(importantTotalUnpacked))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  CDecoder decoder(\n    #if !defined(USE_MIXER_MT)\n      false\n    #elif !defined(USE_MIXER_ST)\n      true\n    #elif !defined(Z7_7Z_SET_PROPERTIES)\n      #ifdef Z7_ST\n        false\n      #else\n        true\n      #endif\n    #else\n      _useMultiThreadMixer\n    #endif\n    );\n\n  UInt64 curPacked, curUnpacked;\n\n  CMyComPtr<IArchiveExtractCallbackMessage2> callbackMessage;\n  extractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage2, &callbackMessage);\n\n  CFolderOutStream *folderOutStream = new CFolderOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(folderOutStream);\n\n  folderOutStream->_db = &_db;\n  folderOutStream->ExtractCallback = extractCallback;\n  folderOutStream->TestMode = (testModeSpec != 0);\n  folderOutStream->CheckCrc = (_crcSize != 0);\n\n  for (UInt32 i = 0;; lps->OutSize += curUnpacked, lps->InSize += curPacked)\n  {\n    RINOK(lps->SetCur())\n\n    if (i >= numItems)\n      break;\n\n    curUnpacked = 0;\n    curPacked = 0;\n\n    UInt32 fileIndex = allFilesMode ? i : indices[i];\n    const CNum folderIndex = _db.FileIndexToFolderIndexMap[fileIndex];\n\n    UInt32 numSolidFiles = 1;\n\n    if (folderIndex != kNumNoIndex)\n    {\n      curPacked = _db.GetFolderFullPackSize(folderIndex);\n      UInt32 nextFile = fileIndex + 1;\n      fileIndex = _db.FolderStartFileIndex[folderIndex];\n      UInt32 k;\n\n      for (k = i + 1; k < numItems; k++)\n      {\n        const UInt32 fileIndex2 = allFilesMode ? k : indices[k];\n        if (_db.FileIndexToFolderIndexMap[fileIndex2] != folderIndex\n            || fileIndex2 < nextFile)\n          break;\n        nextFile = fileIndex2 + 1;\n      }\n      \n      numSolidFiles = k - i;\n      \n      for (k = fileIndex; k < nextFile; k++)\n        curUnpacked += _db.Files[k].Size;\n    }\n\n    {\n      const HRESULT result = folderOutStream->Init(fileIndex,\n          allFilesMode ? NULL : indices + i,\n          numSolidFiles);\n\n      i += numSolidFiles;\n\n      RINOK(result)\n    }\n\n    if (folderOutStream->WasWritingFinished())\n    {\n      // for debug: to test zero size stream unpacking\n      // if (folderIndex == kNumNoIndex)  // enable this check for debug\n      continue;\n    }\n\n    if (folderIndex == kNumNoIndex)\n      return E_FAIL;\n\n    #ifndef Z7_NO_CRYPTO\n    CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n    if (extractCallback)\n      extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);\n    #endif\n\n    try\n    {\n      #ifndef Z7_NO_CRYPTO\n        bool isEncrypted = false;\n        bool passwordIsDefined = false;\n        UString_Wipe password;\n      #endif\n\n      bool dataAfterEnd_Error = false;\n\n      const HRESULT result = decoder.Decode(\n          EXTERNAL_CODECS_VARS\n          _inStream,\n          _db.ArcInfo.DataStartPosition,\n          _db, folderIndex,\n          &curUnpacked,\n\n          outStream,\n          lps,\n          NULL // *inStreamMainRes\n          , dataAfterEnd_Error\n          \n          Z7_7Z_DECODER_CRYPRO_VARS\n          #if !defined(Z7_ST)\n            , true, _numThreads, _memUsage_Decompress\n          #endif\n          );\n\n      if (result == S_FALSE || result == E_NOTIMPL || dataAfterEnd_Error)\n      {\n        const bool wasFinished = folderOutStream->WasWritingFinished();\n\n        int resOp = NExtract::NOperationResult::kDataError;\n        \n        if (result != S_FALSE)\n        {\n          if (result == E_NOTIMPL)\n            resOp = NExtract::NOperationResult::kUnsupportedMethod;\n          else if (wasFinished && dataAfterEnd_Error)\n            resOp = NExtract::NOperationResult::kDataAfterEnd;\n        }\n\n        RINOK(folderOutStream->FlushCorrupted(resOp))\n\n        if (wasFinished)\n        {\n          // we don't show error, if it's after required files\n          if (/* !folderOutStream->ExtraWriteWasCut && */ callbackMessage)\n          {\n            RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, resOp))\n          }\n        }\n        continue;\n      }\n      \n      if (result != S_OK)\n        return result;\n\n      RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError))\n      continue;\n    }\n    catch(...)\n    {\n      RINOK(folderOutStream->FlushCorrupted(NExtract::NOperationResult::kDataError))\n      // continue;\n      // return E_FAIL;\n      throw;\n    }\n  }\n\n  return S_OK;\n\n  COM_TRY_END\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zFolderInStream.cpp",
    "content": "﻿// 7zFolderInStream.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"7zFolderInStream.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nvoid CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,\n    const UInt32 *indexes, unsigned numFiles)\n{\n  _updateCallback = updateCallback;\n  _indexes = indexes;\n  _numFiles = numFiles;\n\n  _totalSize_for_Coder = 0;\n  ClearFileInfo();\n  \n  Processed.ClearAndReserve(numFiles);\n  Sizes.ClearAndReserve(numFiles);\n  CRCs.ClearAndReserve(numFiles);\n  TimesDefined.ClearAndReserve(numFiles);\n  MTimes.ClearAndReserve(Need_MTime ? numFiles : (unsigned)0);\n  CTimes.ClearAndReserve(Need_CTime ? numFiles : (unsigned)0);\n  ATimes.ClearAndReserve(Need_ATime ? numFiles : (unsigned)0);\n  Attribs.ClearAndReserve(Need_Attrib ? numFiles : (unsigned)0);\n\n  // FolderCrc = CRC_INIT_VAL;\n  _stream.Release();\n}\n\nvoid CFolderInStream::ClearFileInfo()\n{\n  _pos = 0;\n  _crc = CRC_INIT_VAL;\n  _size_Defined = false;\n  _times_Defined = false;\n  _size = 0;\n  FILETIME_Clear(_mTime);\n  FILETIME_Clear(_cTime);\n  FILETIME_Clear(_aTime);\n  _attrib = 0;\n}\n\nHRESULT CFolderInStream::OpenStream()\n{\n  while (Processed.Size() < _numFiles)\n  {\n    CMyComPtr<ISequentialInStream> stream;\n    const HRESULT result = _updateCallback->GetStream(_indexes[Processed.Size()], &stream);\n    if (result != S_OK && result != S_FALSE)\n      return result;\n\n    _stream = stream;\n    \n    if (stream)\n    {\n      {\n        CMyComPtr<IStreamGetProps> getProps;\n        stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps);\n        if (getProps)\n        {\n          // access could be changed in first myx pass\n          if (getProps->GetProps(&_size,\n              Need_CTime ? &_cTime : NULL,\n              Need_ATime ? &_aTime : NULL,\n              Need_MTime ? &_mTime : NULL,\n              Need_Attrib ? &_attrib : NULL)\n              == S_OK)\n          {\n            _size_Defined = true;\n            _times_Defined = true;\n          }\n          return S_OK;\n        }\n      }\n      {\n        CMyComPtr<IStreamGetSize> streamGetSize;\n        stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);\n        if (streamGetSize)\n        {\n          if (streamGetSize->GetSize(&_size) == S_OK)\n            _size_Defined = true;\n        }\n        return S_OK;\n      }\n    }\n    \n    RINOK(AddFileInfo(result == S_OK))\n  }\n  return S_OK;\n}\n\nstatic void AddFt(CRecordVector<UInt64> &vec, const FILETIME &ft)\n{\n  vec.AddInReserved(FILETIME_To_UInt64(ft));\n}\n\n/*\nHRESULT ReportItemProps(IArchiveUpdateCallbackArcProp *reportArcProp,\n    UInt32 index, UInt64 size, const UInt32 *crc)\n{\n  PROPVARIANT prop;\n  prop.vt = VT_EMPTY;\n  prop.wReserved1 = 0;\n  \n  NWindows::NCOM::PropVarEm_Set_UInt64(&prop, size);\n  RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop));\n  if (crc)\n  {\n    NWindows::NCOM::PropVarEm_Set_UInt32(&prop, *crc);\n    RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop));\n  }\n  return reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK);\n}\n*/\n\nHRESULT CFolderInStream::AddFileInfo(bool isProcessed)\n{\n  // const UInt32 index = _indexes[Processed.Size()];\n  Processed.AddInReserved(isProcessed);\n  Sizes.AddInReserved(_pos);\n  CRCs.AddInReserved(CRC_GET_DIGEST(_crc));\n  if (Need_Attrib) Attribs.AddInReserved(_attrib);\n  TimesDefined.AddInReserved(_times_Defined);\n  if (Need_MTime) AddFt(MTimes, _mTime);\n  if (Need_CTime) AddFt(CTimes, _cTime);\n  if (Need_ATime) AddFt(ATimes, _aTime);\n  ClearFileInfo();\n  /*\n  if (isProcessed && _reportArcProp)\n    RINOK(ReportItemProps(_reportArcProp, index, _pos, &crc))\n  */\n  return _updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  while (size != 0)\n  {\n    if (_stream)\n    {\n      /*\n      if (_pos == 0)\n      {\n        const UInt32 align = (UInt32)1 << AlignLog;\n        const UInt32 offset = (UInt32)_totalSize_for_Coder & (align - 1);\n        if (offset != 0)\n        {\n          UInt32 cur = align - offset;\n          if (cur > size)\n            cur = size;\n          memset(data, 0, cur);\n          data = (Byte *)data + cur;\n          size -= cur;\n          // _pos += cur; // for debug\n          _totalSize_for_Coder += cur;\n          if (processedSize)\n            *processedSize += cur;\n          continue;\n        }\n      }\n      */\n      UInt32 cur = size;\n      const UInt32 kMax = (UInt32)1 << 20;\n      if (cur > kMax)\n        cur = kMax;\n      RINOK(_stream->Read(data, cur, &cur))\n      if (cur != 0)\n      {\n        // if (Need_Crc)\n        _crc = CrcUpdate(_crc, data, cur);\n        /*\n        if (FolderCrc)\n          FolderCrc = CrcUpdate(FolderCrc, data, cur);\n        */\n        _pos += cur;\n        _totalSize_for_Coder += cur;\n        if (processedSize)\n          *processedSize = cur; // use +=cur, if continue is possible in loop\n        return S_OK;\n      }\n      \n      _stream.Release();\n      RINOK(AddFileInfo(true))\n    }\n    \n    if (Processed.Size() >= _numFiles)\n      break;\n    RINOK(OpenStream())\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value))\n{\n  *value = 0;\n  if (subStream > Sizes.Size())\n    return S_FALSE; // E_FAIL;\n  \n  const unsigned index = (unsigned)subStream;\n  if (index < Sizes.Size())\n  {\n    *value = Sizes[index];\n    return S_OK;\n  }\n  \n  if (!_size_Defined)\n  {\n    *value = _pos;\n    return S_FALSE;\n  }\n  \n  *value = (_pos > _size ? _pos : _size);\n  return S_OK;\n}\n\n\n/*\nHRESULT CFolderInStream::CloseCrcStream()\n{\n  if (!_crcStream)\n    return S_OK;\n  if (!_crcStream_Spec->WasFinished())\n    return E_FAIL;\n  _crc = _crcStream_Spec->GetCRC() ^ CRC_INIT_VAL; // change it\n  const UInt64 size = _crcStream_Spec->GetSize();\n  _pos = size;\n  _totalSize_for_Coder += size;\n  _crcStream.Release();\n  // _crcStream->ReleaseStream();\n  _stream.Release();\n  return AddFileInfo(true);\n}\n\nZ7_COM7F_IMF(CFolderInStream::GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream)\n{\n  RINOK(CloseCrcStream())\n  *stream = NULL;\n  *streamIndexRes = Processed.Size();\n  if (Processed.Size() >= _numFiles)\n    return S_OK;\n  RINOK(OpenStream());\n  if (!_stream)\n    return S_OK;\n  if (!_crcStream)\n  {\n    _crcStream_Spec = new CSequentialInStreamWithCRC;\n    _crcStream = _crcStream_Spec;\n  }\n  _crcStream_Spec->Init();\n  _crcStream_Spec->SetStream(_stream);\n  *stream = _crcStream;\n  _crcStream->AddRef();\n  return S_OK;\n}\n*/\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zFolderInStream.h",
    "content": "﻿// 7zFolderInStream.h\n\n#ifndef ZIP7_INC_7Z_FOLDER_IN_STREAM_H\n#define ZIP7_INC_7Z_FOLDER_IN_STREAM_H\n\n#include \"../../../../C/7zCrc.h\"\n\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/MyVector.h\"\n// #include \"../Common/InStreamWithCRC.h\"\n\n#include \"../../ICoder.h\"\n#include \"../IArchive.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nZ7_CLASS_IMP_COM_2(\n  CFolderInStream\n  , ISequentialInStream\n  , ICompressGetSubStreamSize\n)\n  /*\n  Z7_COM7F_IMP(GetNextStream(UInt64 *streamIndex))\n  Z7_IFACE_COM7_IMP(ICompressInSubStreams)\n  */\n\n  CMyComPtr<ISequentialInStream> _stream;\n  UInt64 _totalSize_for_Coder;\n  UInt64 _pos;\n  UInt32 _crc;\n  bool _size_Defined;\n  bool _times_Defined;\n  UInt64 _size;\n  FILETIME _mTime;\n  FILETIME _cTime;\n  FILETIME _aTime;\n  UInt32 _attrib;\n\n  unsigned _numFiles;\n  const UInt32 *_indexes;\n\n  CMyComPtr<IArchiveUpdateCallback> _updateCallback;\n\n  void ClearFileInfo();\n  HRESULT OpenStream();\n  HRESULT AddFileInfo(bool isProcessed);\n  // HRESULT CloseCrcStream();\npublic:\n  bool Need_MTime;\n  bool Need_CTime;\n  bool Need_ATime;\n  bool Need_Attrib;\n  // bool Need_Crc;\n  // bool Need_FolderCrc;\n  // unsigned AlignLog;\n  \n  CRecordVector<bool> Processed;\n  CRecordVector<UInt64> Sizes;\n  CRecordVector<UInt32> CRCs;\n  CRecordVector<UInt32> Attribs;\n  CRecordVector<bool> TimesDefined;\n  CRecordVector<UInt64> MTimes;\n  CRecordVector<UInt64> CTimes;\n  CRecordVector<UInt64> ATimes;\n  // UInt32 FolderCrc;\n\n  // UInt32 GetFolderCrc() const { return CRC_GET_DIGEST(FolderCrc); }\n  // CSequentialInStreamWithCRC *_crcStream_Spec;\n  // CMyComPtr<ISequentialInStream> _crcStream;\n  // CMyComPtr<IArchiveUpdateCallbackArcProp> _reportArcProp;\n\n  void Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles);\n\n  bool WasFinished() const { return Processed.Size() == _numFiles; }\n\n  UInt64 Get_TotalSize_for_Coder() const { return _totalSize_for_Coder; }\n  /*\n  UInt64 GetFullSize() const\n  {\n    UInt64 size = 0;\n    FOR_VECTOR (i, Sizes)\n      size += Sizes[i];\n    return size;\n  }\n  */\n\n  CFolderInStream():\n      Need_MTime(false),\n      Need_CTime(false),\n      Need_ATime(false),\n      Need_Attrib(false)\n      // , Need_Crc(true)\n      // , Need_FolderCrc(false)\n      // , AlignLog(0)\n      {}\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zHandler.cpp",
    "content": "﻿// 7zHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n\n#ifndef Z7_7Z_SET_PROPERTIES\n#include \"../../../Windows/System.h\"\n#endif\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"7zHandler.h\"\n#include \"7zProperties.h\"\n\n#ifdef Z7_7Z_SET_PROPERTIES\n#ifdef Z7_EXTRACT_ONLY\n#include \"../Common/ParseProperties.h\"\n#endif\n#endif\n\nusing namespace NWindows;\nusing namespace NCOM;\n\nnamespace NArchive {\nnamespace N7z {\n\nCHandler::CHandler()\n{\n  #ifndef Z7_NO_CRYPTO\n  _isEncrypted = false;\n  _passwordIsDefined = false;\n  #endif\n\n  #ifdef Z7_EXTRACT_ONLY\n  \n  _crcSize = 4;\n  \n  #ifdef Z7_7Z_SET_PROPERTIES\n  _useMultiThreadMixer = true;\n  #endif\n  \n  #endif\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _db.Files.Size();\n  return S_OK;\n}\n\n#ifdef Z7_SFX\n\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps))\n{\n  *numProps = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetPropertyInfo(UInt32 /* index */,\n      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */))\n{\n  return E_NOTIMPL;\n}\n\n#else\n\nstatic const Byte kArcProps[] =\n{\n  kpidHeadersSize,\n  kpidMethod,\n  kpidSolid,\n  kpidNumBlocks\n  // , kpidIsTree\n};\n\nIMP_IInArchive_ArcProps\n\nstatic inline char GetHex(unsigned value)\n{\n  return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));\n}\n\nstatic unsigned ConvertMethodIdToString_Back(char *s, UInt64 id)\n{\n  int len = 0;\n  do\n  {\n    s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;\n    s[--len] = GetHex((unsigned)id & 0xF); id >>= 4;\n  }\n  while (id != 0);\n  return (unsigned)-len;\n}\n\nstatic void ConvertMethodIdToString(AString &res, UInt64 id)\n{\n  const unsigned kLen = 32;\n  char s[kLen];\n  unsigned len = kLen - 1;\n  s[len] = 0;\n  res += s + len - ConvertMethodIdToString_Back(s + len, id);\n}\n\n\nstatic char *GetStringForSizeValue(char *s, UInt32 val)\n{\n  for (unsigned i = 0; i < 32; i++)\n    if (((UInt32)1 << i) == val)\n    {\n      if (i >= 10)\n      {\n        *s++= (char)('0' + i / 10);\n        i %= 10;\n      }\n      *s++ = (char)('0' + i);\n      *s = 0;\n      return s;\n    }\n  \n  char c = 'b';\n  if      ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }\n  else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }\n  s = ConvertUInt32ToString(val, s);\n  *s++ = c;\n  *s = 0;\n  return s;\n}\n\n\nstatic void GetLzma2String(char *s, unsigned d)\n{\n  if (d > 40)\n  {\n    *s = 0;\n    return;\n    // s = MyStpCpy(s, \"unsup\");\n  }\n  else if ((d & 1) == 0)\n    d = (d >> 1) + 12;\n  else\n  {\n    // s = GetStringForSizeValue(s, (UInt32)3 << ((d >> 1) + 11));\n    d = (d >> 1) + 1;\n    char c = 'k';\n    if (d >= 10)\n    {\n      c = 'm';\n      d -= 10;\n    }\n    s = ConvertUInt32ToString((UInt32)3 << d, s);\n    *s++ = c;\n    *s = 0;\n    return;\n  }\n  ConvertUInt32ToString(d, s);\n}\n\n\n/*\nstatic inline void AddHexToString(UString &res, Byte value)\n{\n  res += GetHex((Byte)(value >> 4));\n  res += GetHex((Byte)(value & 0xF));\n}\n*/\n\nstatic char *AddProp32(char *s, const char *name, UInt32 v)\n{\n  *s++ = ':';\n  s = MyStpCpy(s, name);\n  return ConvertUInt32ToString(v, s);\n}\n \nvoid CHandler::AddMethodName(AString &s, UInt64 id)\n{\n  AString name;\n  FindMethod(EXTERNAL_CODECS_VARS id, name);\n  if (name.IsEmpty())\n    ConvertMethodIdToString(s, id);\n  else\n    s += name;\n}\n\n#endif\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  #ifndef Z7_SFX\n  COM_TRY_BEGIN\n  #endif\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    #ifndef Z7_SFX\n    case kpidMethod:\n    {\n      AString s;\n      const CParsedMethods &pm = _db.ParsedMethods;\n      FOR_VECTOR (i, pm.IDs)\n      {\n        UInt64 id = pm.IDs[i];\n        s.Add_Space_if_NotEmpty();\n        char temp[16];\n        if (id == k_LZMA2)\n        {\n          s += \"LZMA2:\";\n          GetLzma2String(temp, pm.Lzma2Prop);\n          s += temp;\n        }\n        else if (id == k_LZMA)\n        {\n          s += \"LZMA:\";\n          GetStringForSizeValue(temp, pm.LzmaDic);\n          s += temp;\n        }\n        /*\n        else if (id == k_ZSTD)\n        {\n          s += \"ZSTD\";\n        }\n        */\n        else\n          AddMethodName(s, id);\n      }\n      prop = s;\n      break;\n    }\n    case kpidSolid: prop = _db.IsSolid(); break;\n    case kpidNumBlocks: prop = (UInt32)_db.NumFolders; break;\n    case kpidHeadersSize:  prop = _db.HeadersSize; break;\n    case kpidPhySize:  prop = _db.PhySize; break;\n    case kpidOffset: if (_db.ArcInfo.StartPosition != 0) prop = _db.ArcInfo.StartPosition; break;\n    /*\n    case kpidIsTree: if (_db.IsTree) prop = true; break;\n    case kpidIsAltStream: if (_db.ThereAreAltStreams) prop = true; break;\n    case kpidIsAux: if (_db.IsTree) prop = true; break;\n    */\n    // case kpidError: if (_db.ThereIsHeaderError) prop = \"Header error\"; break;\n    #endif\n    \n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      if (_db.StartHeaderWasRecovered) v |= kpv_ErrorFlags_HeadersError;\n      if (_db.UnsupportedFeatureWarning) v |= kpv_ErrorFlags_UnsupportedFeature;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n    \n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_db.IsArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_db.ThereIsHeaderError) v |= kpv_ErrorFlags_HeadersError;\n      if (_db.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;\n      // if (_db.UnsupportedVersion) v |= kpv_ErrorFlags_Unsupported;\n      if (_db.UnsupportedFeatureError) v |= kpv_ErrorFlags_UnsupportedFeature;\n      prop = v;\n      break;\n    }\n\n    case kpidReadOnly:\n    {\n      if (!_db.CanUpdate())\n        prop = true;\n      break;\n    }\n    default: break;\n  }\n  return prop.Detach(value);\n  #ifndef Z7_SFX\n  COM_TRY_END\n  #endif\n}\n\nstatic void SetFileTimeProp_From_UInt64Def(PROPVARIANT *prop, const CUInt64DefVector &v, unsigned index)\n{\n  UInt64 value;\n  if (v.GetItem(index, value))\n    PropVarEm_Set_FileTime64_Prec(prop, value, k_PropVar_TimePrec_100ns);\n}\n\nbool CHandler::IsFolderEncrypted(CNum folderIndex) const\n{\n  if (folderIndex == kNumNoIndex)\n    return false;\n  const size_t startPos = _db.FoCodersDataOffset[folderIndex];\n  const Byte *p = _db.CodersData.ConstData() + startPos;\n  const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;\n  CInByte2 inByte;\n  inByte.Init(p, size);\n  \n  CNum numCoders = inByte.ReadNum();\n  for (; numCoders != 0; numCoders--)\n  {\n    const Byte mainByte = inByte.ReadByte();\n    const unsigned idSize = (mainByte & 0xF);\n    const Byte *longID = inByte.GetPtr();\n    UInt64 id64 = 0;\n    for (unsigned j = 0; j < idSize; j++)\n      id64 = ((id64 << 8) | longID[j]);\n    inByte.SkipDataNoCheck(idSize);\n    if (id64 == k_AES)\n      return true;\n    if ((mainByte & 0x20) != 0)\n      inByte.SkipDataNoCheck(inByte.ReadNum());\n  }\n  return false;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID))\n{\n  *name = NULL;\n  *propID = kpidNtSecure;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 /* index */, UInt32 *parent, UInt32 *parentType))\n{\n  /*\n  const CFileItem &file = _db.Files[index];\n  *parentType = (file.IsAltStream ? NParentType::kAltStream : NParentType::kDir);\n  *parent = (UInt32)(Int32)file.Parent;\n  */\n  *parentType = NParentType::kDir;\n  *parent = (UInt32)(Int32)-1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n\n  if (/* _db.IsTree && propID == kpidName ||\n      !_db.IsTree && */ propID == kpidPath)\n  {\n    if (_db.NameOffsets && _db.NamesBuf)\n    {\n      const size_t offset = _db.NameOffsets[index];\n      const size_t size = (_db.NameOffsets[index + 1] - offset) * 2;\n      if (size < ((UInt32)1 << 31))\n      {\n        *data = (const void *)(_db.NamesBuf.ConstData() + offset * 2);\n        *dataSize = (UInt32)size;\n        *propType = NPropDataType::kUtf16z;\n      }\n    }\n    return S_OK;\n  }\n  /*\n  if (propID == kpidNtSecure)\n  {\n    if (index < (UInt32)_db.SecureIDs.Size())\n    {\n      int id = _db.SecureIDs[index];\n      size_t offs = _db.SecureOffsets[id];\n      size_t size = _db.SecureOffsets[id + 1] - offs;\n      if (size >= 0)\n      {\n        *data = _db.SecureBuf + offs;\n        *dataSize = (UInt32)size;\n        *propType = NPropDataType::kRaw;\n      }\n    }\n  }\n  */\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\nHRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const\n{\n  PropVariant_Clear(prop);\n  if (folderIndex == kNumNoIndex)\n    return S_OK;\n  // for (int ttt = 0; ttt < 1; ttt++) {\n  const unsigned kTempSize = 256;\n  char temp[kTempSize];\n  unsigned pos = kTempSize;\n  temp[--pos] = 0;\n \n  const size_t startPos = _db.FoCodersDataOffset[folderIndex];\n  const Byte *p = _db.CodersData.ConstData() + startPos;\n  const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;\n  CInByte2 inByte;\n  inByte.Init(p, size);\n  \n  // numCoders == 0 ???\n  CNum numCoders = inByte.ReadNum();\n  bool needSpace = false;\n  \n  for (; numCoders != 0; numCoders--, needSpace = true)\n  {\n    if (pos < 32) // max size of property\n      break;\n    const Byte mainByte = inByte.ReadByte();\n    UInt64 id64 = 0;\n    const unsigned idSize = (mainByte & 0xF);\n    const Byte *longID = inByte.GetPtr();\n    for (unsigned j = 0; j < idSize; j++)\n      id64 = ((id64 << 8) | longID[j]);\n    inByte.SkipDataNoCheck(idSize);\n\n    if ((mainByte & 0x10) != 0)\n    {\n      inByte.ReadNum(); // NumInStreams\n      inByte.ReadNum(); // NumOutStreams\n    }\n  \n    CNum propsSize = 0;\n    const Byte *props = NULL;\n    if ((mainByte & 0x20) != 0)\n    {\n      propsSize = inByte.ReadNum();\n      props = inByte.GetPtr();\n      inByte.SkipDataNoCheck(propsSize);\n    }\n    \n    const char *name = NULL;\n    char s[32];\n    s[0] = 0;\n    \n    if (id64 <= (UInt32)0xFFFFFFFF)\n    {\n      const UInt32 id = (UInt32)id64;\n      if (id == k_LZMA)\n      {\n        name = \"LZMA\";\n        if (propsSize == 5)\n        {\n          const UInt32 dicSize = GetUi32((const Byte *)props + 1);\n          char *dest = GetStringForSizeValue(s, dicSize);\n          UInt32 d = props[0];\n          if (d != 0x5D)\n          {\n            const UInt32 lc = d % 9;\n            d /= 9;\n            const UInt32 pb = d / 5;\n            const UInt32 lp = d % 5;\n            if (lc != 3) dest = AddProp32(dest, \"lc\", lc);\n            if (lp != 0) dest = AddProp32(dest, \"lp\", lp);\n            if (pb != 2) dest = AddProp32(dest, \"pb\", pb);\n          }\n        }\n      }\n      else if (id == k_LZMA2)\n      {\n        name = \"LZMA2\";\n        if (propsSize == 1)\n          GetLzma2String(s, props[0]);\n      }\n      else if (id == k_PPMD)\n      {\n        name = \"PPMD\";\n        if (propsSize == 5)\n        {\n          char *dest = s;\n          *dest++ = 'o';\n          dest = ConvertUInt32ToString(*props, dest);\n          dest = MyStpCpy(dest, \":mem\");\n          GetStringForSizeValue(dest, GetUi32(props + 1));\n        }\n      }\n      else if (id == k_Delta)\n      {\n        name = \"Delta\";\n        if (propsSize == 1)\n          ConvertUInt32ToString((UInt32)props[0] + 1, s);\n      }\n      else if (id == k_ARM64 || id == k_RISCV)\n      {\n        name = id == k_ARM64 ? \"ARM64\" : \"RISCV\";\n        if (propsSize == 4)\n          ConvertUInt32ToString(GetUi32(props), s);\n        /*\n        else if (propsSize != 0)\n          MyStringCopy(s, \"unsupported\");\n        */\n      }\n      else if (id == k_BCJ2) name = \"BCJ2\";\n      else if (id == k_BCJ) name = \"BCJ\";\n      else if (id == k_AES)\n      {\n        name = \"7zAES\";\n        if (propsSize >= 1)\n        {\n          const Byte firstByte = props[0];\n          const UInt32 numCyclesPower = firstByte & 0x3F;\n          ConvertUInt32ToString(numCyclesPower, s);\n        }\n      }\n    }\n    \n    if (name)\n    {\n      const unsigned nameLen = MyStringLen(name);\n      const unsigned propsLen = MyStringLen(s);\n      unsigned totalLen = nameLen + propsLen;\n      if (propsLen != 0)\n        totalLen++;\n      if (needSpace)\n        totalLen++;\n      if (totalLen + 5 >= pos)\n        break;\n      pos -= totalLen;\n      MyStringCopy(temp + pos, name);\n      if (propsLen != 0)\n      {\n        char *dest = temp + pos + nameLen;\n        *dest++ = ':';\n        MyStringCopy(dest, s);\n      }\n      if (needSpace)\n        temp[pos + totalLen - 1] = ' ';\n    }\n    else\n    {\n      AString methodName;\n      FindMethod(EXTERNAL_CODECS_VARS id64, methodName);\n      if (needSpace)\n        temp[--pos] = ' ';\n      if (methodName.IsEmpty())\n        pos -= ConvertMethodIdToString_Back(temp + pos, id64);\n      else\n      {\n        const unsigned len = methodName.Len();\n        if (len + 5 > pos)\n          break;\n        pos -= len;\n        for (unsigned i = 0; i < len; i++)\n          temp[pos + i] = methodName[i];\n      }\n    }\n  }\n  \n  if (numCoders != 0 && pos >= 4)\n  {\n    temp[--pos] = ' ';\n    temp[--pos] = '.';\n    temp[--pos] = '.';\n    temp[--pos] = '.';\n  }\n  \n  return PropVarEm_Set_Str(prop, temp + pos);\n  // }\n}\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n/*\n   Used to obtain the method with level from first archived item block where it would be able to retrieve them\n   (and will set this method (and if found also the level) in the caller (only if no methods are specified\n   in command-line arguments or supplied from UI);\n   The filtered methods (BCJ, etc) and encryption (7zAES) will be ignored, so first not filtered method of \n   first block will win.\n   Current restrictions (todo's):\n   - complex compressed archives, e. g. using multiple codecs per item (first method will win) or different \n     methods across items groups (method of first item will win);\n   - not all methods allow to obtain levels (e. g. LZMA, LZMA2, PPMD)\n   - ZSTD fast levels will be not set to codec at the moment (and resulting to level 1); also other parameters\n     like windowLog are not supported currently by recompression.\n */\nbool CHandler::ObtainMethodFromBlocks(CHandler::MethodInfo *info) const\n{\n  // no blocks - no methods can be found:\n  if (!_db.NumFolders) return false;\n  // for every block:\n  CNum folderIndex;\n  for (folderIndex = 0; folderIndex < _db.NumFolders; folderIndex++) {\n    if (ObtainBlockMethods(folderIndex, NULL, info) == S_OK &&\n        !info->methName.IsEmpty()\n    ) {\n      return true;\n    }\n  }\n  return false;\n}\n\nHRESULT CHandler::ObtainBlockMethods(CNum folderIndex, PROPVARIANT *prop, CHandler::MethodInfo *info) const\n{\n  if (prop) PropVariant_Clear(prop);\n  if (folderIndex == kNumNoIndex)\n    return S_OK;\n  const unsigned kTempSize = 256;\n  char temp[kTempSize];\n  unsigned pos = kTempSize;\n  temp[--pos] = 0;\n \n  const size_t startPos = _db.FoCodersDataOffset[folderIndex];\n  const Byte *p = _db.CodersData.ConstData() + startPos;\n  const size_t size = _db.FoCodersDataOffset[folderIndex + 1] - startPos;\n  CInByte2 inByte;\n  inByte.Init(p, size);\n  \n  // numCoders == 0 ???\n  CNum numCoders = inByte.ReadNum();\n  bool needSpace = false;\n  \n  for (; numCoders != 0; numCoders--)\n  {\n    if (pos < 32) // max size of property\n      break;\n    const Byte mainByte = inByte.ReadByte();\n    UInt64 id64 = 0;\n    const unsigned idSize = (mainByte & 0xF);\n    const Byte *longID = inByte.GetPtr();\n    for (unsigned j = 0; j < idSize; j++)\n      id64 = ((id64 << 8) | longID[j]);\n    inByte.SkipDataNoCheck(idSize);\n\n    if ((mainByte & 0x10) != 0)\n    {\n      inByte.ReadNum(); // NumInStreams\n      inByte.ReadNum(); // NumOutStreams\n    }\n  \n    CNum propsSize = 0;\n    const Byte *props = NULL;\n    if ((mainByte & 0x20) != 0)\n    {\n      propsSize = inByte.ReadNum();\n      props = inByte.GetPtr();\n      inByte.SkipDataNoCheck(propsSize);\n    }\n    \n    const char *name = NULL;\n    int lev = (int)-1;\n    char s[32];\n    s[0] = 0;\n    \n    if (id64 <= (UInt32)0xFFFFFFFF)\n    {\n      const UInt32 id = (UInt32)id64;\n      switch (id) {\n      case k_LZMA:\n        name = \"LZMA\";\n        if (info) {goto obtainInfo;}\n        if (propsSize == 5)\n        {\n          const UInt32 dicSize = GetUi32((const Byte *)props + 1);\n          char *dest = GetStringForSizeValue(s, dicSize);\n          UInt32 d = props[0];\n          if (d != 0x5D)\n          {\n            const UInt32 lc = d % 9;\n            d /= 9;\n            const UInt32 pb = d / 5;\n            const UInt32 lp = d % 5;\n            if (lc != 3) dest = AddProp32(dest, \"lc\", lc);\n            if (lp != 0) dest = AddProp32(dest, \"lp\", lp);\n            if (pb != 2) dest = AddProp32(dest, \"pb\", pb);\n          }\n        }\n        break;\n      case k_LZMA2:\n        name = \"LZMA2\";\n        if (info) {goto obtainInfo;}\n        if (propsSize == 1)\n          GetLzma2String(s, props[0]);\n        break;\n      case k_PPMD:\n        name = \"PPMD\";\n        if (info) {goto obtainInfo;}\n        if (propsSize == 5)\n        {\n          char *dest = s;\n          *dest++ = 'o';\n          dest = ConvertUInt32ToString(*props, dest);\n          dest = MyStpCpy(dest, \":mem\");\n          GetStringForSizeValue(dest, GetUi32(props + 1));\n        }\n        break;\n      case k_LZHAM:\n        name = \"LZHAM\";\n        if (propsSize == 5)\n        {\n          if (info) {lev = props[2]; goto obtainInfo;}\n          char *dest = s;\n          *dest++ = 'v';\n          ConvertUInt32ToString(props[0], dest);\n          dest += MyStringLen(dest);\n          *dest++ = ',';\n          *dest++ = 'd';\n          ConvertUInt32ToString(props[1], dest);\n          dest += MyStringLen(dest);\n          *dest++ = ',';\n          *dest++ = 'l';\n          ConvertUInt32ToString(props[2], dest);\n          dest += MyStringLen(dest);\n        }\n        break;\n      case k_BROTLI:\n        name = \"Brotli\";\n        if (propsSize == 3)\n        {\n          if (info) {lev = props[2]; goto obtainInfo;}\n          char *dest = s;\n          *dest++ = 'v';\n          ConvertUInt32ToString(props[0], dest);\n          dest += MyStringLen(dest);\n          *dest++ = '.';\n          ConvertUInt32ToString(props[1], dest);\n          dest += MyStringLen(dest);\n          *dest++ = ',';\n          *dest++ = 'l';\n          ConvertUInt32ToString(props[2], dest);\n          dest += MyStringLen(dest);\n        }\n        break;\n      case k_LIZARD:\n        name = \"Lizard\";\n        if (propsSize == 3)\n        {\n          if (info) {lev = props[2]; goto obtainInfo;}\n          char *dest = s;\n          *dest++ = 'v';\n          ConvertUInt32ToString(props[0], dest);\n          dest += MyStringLen(dest);\n          *dest++ = '.';\n          ConvertUInt32ToString(props[1], dest);\n          dest += MyStringLen(dest);\n          *dest++ = ',';\n          *dest++ = 'l';\n          ConvertUInt32ToString(props[2], dest);\n          dest += MyStringLen(dest);\n        }\n        break;\n      case k_LZ4:\n        name = \"LZ4\";\n        if (propsSize == 3 || propsSize == 5)\n        {\n          if (info) {lev = props[2]; goto obtainInfo;}\n          char *dest = s;\n          *dest++ = 'v';\n          ConvertUInt32ToString(props[0], dest);\n          dest += MyStringLen(dest);\n          *dest++ = '.';\n          ConvertUInt32ToString(props[1], dest);\n          dest += MyStringLen(dest);\n          *dest++ = ',';\n          *dest++ = 'l';\n          ConvertUInt32ToString(props[2], dest);\n          dest += MyStringLen(dest);\n        }\n        break;\n      case k_LZ5:\n        name = \"LZ5\";\n        if (propsSize == 3 || propsSize == 5)\n        {\n          if (info) {lev = props[2]; goto obtainInfo;}\n          char *dest = s;\n          *dest++ = 'v';\n          ConvertUInt32ToString(props[0], dest);\n          dest += MyStringLen(dest);\n          *dest++ = '.';\n          ConvertUInt32ToString(props[1], dest);\n          dest += MyStringLen(dest);\n          *dest++ = ',';\n          *dest++ = 'l';\n          ConvertUInt32ToString(props[2], dest);\n          dest += MyStringLen(dest);\n        }\n        break;\n      case k_ZSTD:\n        name = \"ZSTD\";\n        if (propsSize == 3 || propsSize == 5)\n        {\n          UInt32 l = props[2];\n          if (info) {\n            if (l <= 22 || l == Z7_ZSTD_ULTIMATE_LEV) {\n              lev = l;\n            } else {\n              // todo: need parameter to set fast mode (to NCoderPropID::kFast)\n              // fast = 1;\n              // l -= 32;\n              lev = 1; // use fastest positive level at the moment;\n            }\n            goto obtainInfo;\n          }\n          char *dest = s;\n          *dest++ = 'v';\n          ConvertUInt32ToString(props[0], dest);\n          dest += MyStringLen(dest);\n          *dest++ = '.';\n          ConvertUInt32ToString(props[1], dest);\n          dest += MyStringLen(dest);\n          *dest++ = ',';\n          if (l <= 22) {\n            *dest++ = 'l';\n            ConvertUInt32ToString(l, dest);\n          } else if (l == Z7_ZSTD_ULTIMATE_LEV) { // special level for zstd --max (advanced ultra) \n            *dest++ = 'm';\n            *dest++ = 'a';\n            *dest++ = 'x';\n            *dest = '\\0';\n          } else {\n            *dest++ = 'f';\n            *dest++ = 'l';\n            ConvertUInt32ToString(l - Z7_ZSTD_FAST_LEV_INC, dest);\n          }\n          dest += MyStringLen(dest);\n        }\n        break;\n      // filtered methods from here, if we need method info, ignore them - continue search\n      case k_Delta:\n        if (info) continue;\n        name = \"Delta\";\n        if (propsSize == 1)\n          ConvertUInt32ToString((UInt32)props[0] + 1, s);\n        break;\n      case k_ARM64:\n        if (info) continue;\n        name = \"ARM64\";\n        // **************** 7-Zip ZS Modification Start ****************\n        break;\n        // **************** 7-Zip ZS Modification End ****************\n      case k_RISCV:\n        if (info) continue;\n        if (id == k_RISCV) name = \"RISCV\";\n        if (propsSize == 4)\n          ConvertUInt32ToString(GetUi32(props), s);\n        /*\n        else if (propsSize != 0)\n          MyStringCopy(s, \"unsupported\");\n        */\n        break;\n      case k_BCJ2:\n        if (info) continue;\n        name = \"BCJ2\";\n        break;\n      case k_BCJ:\n        if (info) continue;\n        name = \"BCJ\";\n        break;\n      case k_SWAP2:\n        if (info) continue;\n        name = \"SWAP2\";\n        break;\n      case k_SWAP4:\n        if (info) continue;\n        name = \"SWAP4\";\n        break;\n      case k_PPC:\n        if (info) continue;\n        name = \"PPC\";\n        break;\n      case k_IA64:\n        if (info) continue;\n        name = \"IA64\";\n        break;\n      case k_ARM:\n        if (info) continue;\n        name = \"ARM\";\n        break;\n      case k_ARMT:\n        if (info) continue;\n        name = \"ARMT\";\n        break;\n      case k_SPARC:\n        if (info) continue;\n        name = \"SPARC\";\n        break;\n      // and encryption (also ignore by obtaining info):\n      case k_AES:\n        if (info) continue;\n        name = \"7zAES\";\n        if (propsSize >= 1)\n        {\n          const Byte firstByte = props[0];\n          const UInt32 numCyclesPower = firstByte & 0x3F;\n          ConvertUInt32ToString(numCyclesPower, s);\n        }\n        break;\n      }\n    }\n  \n  // if need to retrieve single method info only:\n  obtainInfo:\n    if (info) {\n      if (name)\n      {\n        info->methName = name;\n      }\n      else\n      {\n        FindMethod(EXTERNAL_CODECS_VARS id64, info->methName);\n      }\n      //printf(\"******* %d/%d %s - %d\\n\", folderIndex, numCoders, info->methName.Ptr(), lev);\n      // found 1st useable for compression method, use it for now:\n      if (!info->methName.IsEmpty()) {\n        info->level = lev;\n        return S_OK;\n      }\n      // search for another method:\n      continue;\n    }\n    \n    if (name)\n    {\n      const unsigned nameLen = MyStringLen(name);\n      const unsigned propsLen = MyStringLen(s);\n      unsigned totalLen = nameLen + propsLen;\n      if (propsLen != 0)\n        totalLen++;\n      if (needSpace)\n        totalLen++;\n      if (totalLen + 5 >= pos)\n        break;\n      pos -= totalLen;\n      MyStringCopy(temp + pos, name);\n      if (propsLen != 0)\n      {\n        char *dest = temp + pos + nameLen;\n        *dest++ = ':';\n        MyStringCopy(dest, s);\n      }\n      if (needSpace)\n        temp[pos + totalLen - 1] = ' ';\n    }\n    else\n    {\n      AString methodName;\n      FindMethod(EXTERNAL_CODECS_VARS id64, methodName);\n      if (needSpace)\n        temp[--pos] = ' ';\n      if (methodName.IsEmpty())\n        pos -= ConvertMethodIdToString_Back(temp + pos, id64);\n      else\n      {\n        const unsigned len = methodName.Len();\n        if (len + 5 > pos)\n          break;\n        pos -= len;\n        for (unsigned i = 0; i < len; i++)\n          temp[pos + i] = methodName[i];\n      }\n    }\n    needSpace = true;\n  }\n  \n  if (numCoders != 0 && pos >= 4)\n  {\n    temp[--pos] = ' ';\n    temp[--pos] = '.';\n    temp[--pos] = '.';\n    temp[--pos] = '.';\n  }\n  \n  if (prop)\n    return PropVarEm_Set_Str(prop, temp + pos);\n  return S_OK;\n  // }\n}\n\nHRESULT CHandler::SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const\n{\n  return ObtainBlockMethods(folderIndex, prop, NULL);\n}\n// **************** 7-Zip ZS Modification End ****************\n\n#endif\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  RINOK(PropVariant_Clear(value))\n  // COM_TRY_BEGIN\n  // NCOM::CPropVariant prop;\n  \n  /*\n  const CRef2 &ref2 = _refs[index];\n  if (ref2.Refs.IsEmpty())\n    return E_FAIL;\n  const CRef &ref = ref2.Refs.Front();\n  */\n  \n  const CFileItem &item = _db.Files[index];\n  const UInt32 index2 = index;\n\n  switch (propID)\n  {\n    case kpidIsDir: PropVarEm_Set_Bool(value, item.IsDir); break;\n    case kpidSize:\n    {\n      PropVarEm_Set_UInt64(value, item.Size);\n      // prop = ref2.Size;\n      break;\n    }\n    case kpidPackSize:\n    {\n      // prop = ref2.PackSize;\n      {\n        const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\n        if (folderIndex != kNumNoIndex)\n        {\n          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2)\n            PropVarEm_Set_UInt64(value, _db.GetFolderFullPackSize(folderIndex));\n          /*\n          else\n            PropVarEm_Set_UInt64(value, 0);\n          */\n        }\n        else\n          PropVarEm_Set_UInt64(value, 0);\n      }\n      break;\n    }\n    // case kpidIsAux: prop = _db.IsItemAux(index2); break;\n    case kpidPosition:  { UInt64 v; if (_db.StartPos.GetItem(index2, v)) PropVarEm_Set_UInt64(value, v); break; }\n    case kpidCTime:  SetFileTimeProp_From_UInt64Def(value, _db.CTime, index2); break;\n    case kpidATime:  SetFileTimeProp_From_UInt64Def(value, _db.ATime, index2); break;\n    case kpidMTime:  SetFileTimeProp_From_UInt64Def(value, _db.MTime, index2); break;\n    case kpidAttrib:  if (_db.Attrib.ValidAndDefined(index2)) PropVarEm_Set_UInt32(value, _db.Attrib.Vals[index2]); break;\n    case kpidCRC:  if (item.CrcDefined) PropVarEm_Set_UInt32(value, item.Crc); break;\n    case kpidEncrypted:  PropVarEm_Set_Bool(value, IsFolderEncrypted(_db.FileIndexToFolderIndexMap[index2])); break;\n    case kpidIsAnti:  PropVarEm_Set_Bool(value, _db.IsItemAnti(index2)); break;\n    /*\n    case kpidIsAltStream:  prop = item.IsAltStream; break;\n    case kpidNtSecure:\n      {\n        int id = _db.SecureIDs[index];\n        size_t offs = _db.SecureOffsets[id];\n        size_t size = _db.SecureOffsets[id + 1] - offs;\n        if (size >= 0)\n        {\n          prop.SetBlob(_db.SecureBuf + offs, (ULONG)size);\n        }\n        break;\n      }\n    */\n\n    case kpidPath: return _db.GetPath_Prop(index, value);\n    \n    #ifndef Z7_SFX\n    \n    case kpidMethod: return SetMethodToProp(_db.FileIndexToFolderIndexMap[index2], value);\n    case kpidBlock:\n      {\n        const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\n        if (folderIndex != kNumNoIndex)\n          PropVarEm_Set_UInt32(value, (UInt32)folderIndex);\n      }\n      break;\n   #ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES\n    case kpidPackedSize0:\n    case kpidPackedSize1:\n    case kpidPackedSize2:\n    case kpidPackedSize3:\n    case kpidPackedSize4:\n      {\n        const CNum folderIndex = _db.FileIndexToFolderIndexMap[index2];\n        if (folderIndex != kNumNoIndex)\n        {\n          if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 &&\n              _db.FoStartPackStreamIndex[folderIndex + 1] -\n              _db.FoStartPackStreamIndex[folderIndex] > (propID - kpidPackedSize0))\n          {\n            PropVarEm_Set_UInt64(value, _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0));\n          }\n        }\n        else\n          PropVarEm_Set_UInt64(value, 0);\n      }\n      break;\n   #endif\n    \n    #endif\n    default: break;\n  }\n  // return prop.Detach(value);\n  return S_OK;\n  // COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *openArchiveCallback))\n{\n  COM_TRY_BEGIN\n  Close();\n  #ifndef Z7_SFX\n  _fileInfoPopIDs.Clear();\n  #endif\n  \n  try\n  {\n    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;\n\n    #ifndef Z7_NO_CRYPTO\n    CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n    if (openArchiveCallback)\n      openArchiveCallbackTemp.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);\n    #endif\n\n    CInArchive archive(\n          #ifdef Z7_7Z_SET_PROPERTIES\n          _useMultiThreadMixer\n          #else\n          true\n          #endif\n          );\n    _db.IsArc = false;\n    RINOK(archive.Open(stream, maxCheckStartPosition))\n    _db.IsArc = true;\n    \n    HRESULT result = archive.ReadDatabase(\n        EXTERNAL_CODECS_VARS\n        _db\n        #ifndef Z7_NO_CRYPTO\n          , getTextPassword, _isEncrypted, _passwordIsDefined, _password\n        #endif\n        );\n    RINOK(result)\n    \n    _inStream = stream;\n  }\n  catch(...)\n  {\n    Close();\n    // return E_INVALIDARG;\n    // return S_FALSE;\n    // we must return out_of_memory here\n    return E_OUTOFMEMORY;\n  }\n  // _inStream = stream;\n  #ifndef Z7_SFX\n  FillPopIDs();\n  #endif\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  COM_TRY_BEGIN\n  _inStream.Release();\n  _db.Clear();\n  #ifndef Z7_NO_CRYPTO\n  _isEncrypted = false;\n  _passwordIsDefined = false;\n  _password.Wipe_and_Empty();\n  #endif\n  return S_OK;\n  COM_TRY_END\n}\n\n#ifdef Z7_7Z_SET_PROPERTIES\n#ifdef Z7_EXTRACT_ONLY\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  COM_TRY_BEGIN\n  \n  InitCommon();\n  _useMultiThreadMixer = true;\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    UString name = names[i];\n    name.MakeLower_Ascii();\n    if (name.IsEmpty())\n      return E_INVALIDARG;\n    const PROPVARIANT &value = values[i];\n    UInt32 number;\n    const unsigned index = ParseStringToUInt32(name, number);\n    if (index == 0)\n    {\n      if (name.IsEqualTo(\"mtf\"))\n      {\n        RINOK(PROPVARIANT_to_bool(value, _useMultiThreadMixer))\n        continue;\n      }\n      {\n        HRESULT hres;\n        if (SetCommonProperty(name, value, hres))\n        {\n          RINOK(hres)\n          continue;\n        }\n      }\n      return E_INVALIDARG;\n    }\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n#endif\n#endif\n\nIMPL_ISetCompressCodecsInfo\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zHandler.h",
    "content": "﻿// 7z/Handler.h\n\n#ifndef ZIP7_7Z_HANDLER_H\n#define ZIP7_7Z_HANDLER_H\n\n#include \"../../ICoder.h\"\n#include \"../IArchive.h\"\n\n#include \"../../Common/CreateCoder.h\"\n\n#ifndef Z7_7Z_SET_PROPERTIES\n\n#ifdef Z7_EXTRACT_ONLY\n  #if !defined(Z7_ST) && !defined(Z7_SFX)\n    #define Z7_7Z_SET_PROPERTIES\n  #endif\n#else\n  #define Z7_7Z_SET_PROPERTIES\n#endif\n\n#endif\n\n// #ifdef Z7_7Z_SET_PROPERTIES\n#include \"../Common/HandlerOut.h\"\n// #endif\n\n#include \"7zCompressionMode.h\"\n#include \"7zIn.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nclass COutHandler: public CMultiMethodProps\n{\n  HRESULT SetSolidFromString(const UString &s);\n  HRESULT SetSolidFromPROPVARIANT(const PROPVARIANT &value);\npublic:\n  UInt64 _numSolidFiles;\n  UInt64 _numSolidBytes;\n  bool _numSolidBytesDefined;\n  bool _solidExtension;\n  bool _useTypeSorting;\n\n  bool _compressHeaders;\n  bool _encryptHeadersSpecified;\n  bool _encryptHeaders;\n  // bool _useParents; 9.26\n\n  CHandlerTimeOptions TimeOptions;\n\n  CBoolPair Write_Attrib;\n\n  bool _useMultiThreadMixer;\n  bool _removeSfxBlock;\n  // bool _volumeMode;\n\n  UInt32 _decoderCompatibilityVersion;\n  CUIntVector _enabledFilters;\n  CUIntVector _disabledFilters;\n  \n  void InitSolidFiles() { _numSolidFiles = (UInt64)(Int64)(-1); }\n  void InitSolidSize()  { _numSolidBytes = (UInt64)(Int64)(-1); }\n  void InitSolid()\n  {\n    InitSolidFiles();\n    InitSolidSize();\n    _solidExtension = false;\n    _numSolidBytesDefined = false;\n  }\n\n  void InitProps7z();\n  void InitProps();\n\n  COutHandler() { InitProps7z(); }\n\n  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);\n};\n\n#endif\n\nclass CHandler Z7_final:\n  public IInArchive,\n  public IArchiveGetRawProps,\n  \n  #ifdef Z7_7Z_SET_PROPERTIES\n  public ISetProperties,\n  #endif\n  \n  #ifndef Z7_EXTRACT_ONLY\n  public IOutArchive,\n  #endif\n  \n  Z7_PUBLIC_ISetCompressCodecsInfo_IFEC\n  \n  public CMyUnknownImp,\n\n  #ifndef Z7_EXTRACT_ONLY\n    public COutHandler\n  #else\n    public CCommonMethodProps\n  #endif\n{\n  Z7_COM_QI_BEGIN2(IInArchive)\n  Z7_COM_QI_ENTRY(IArchiveGetRawProps)\n #ifdef Z7_7Z_SET_PROPERTIES\n  Z7_COM_QI_ENTRY(ISetProperties)\n #endif\n #ifndef Z7_EXTRACT_ONLY\n  Z7_COM_QI_ENTRY(IOutArchive)\n #endif\n  Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(IInArchive)\n  Z7_IFACE_COM7_IMP(IArchiveGetRawProps)\n #ifdef Z7_7Z_SET_PROPERTIES\n  Z7_IFACE_COM7_IMP(ISetProperties)\n #endif\n #ifndef Z7_EXTRACT_ONLY\n  Z7_IFACE_COM7_IMP(IOutArchive)\n #endif\n  DECL_ISetCompressCodecsInfo\n\nprivate:\n  CMyComPtr<IInStream> _inStream;\n  NArchive::N7z::CDbEx _db;\n  \n #ifndef Z7_NO_CRYPTO\n  bool _isEncrypted;\n  bool _passwordIsDefined;\n  UString _password; // _Wipe\n #endif\n\n  #ifdef Z7_EXTRACT_ONLY\n  \n  #ifdef Z7_7Z_SET_PROPERTIES\n  bool _useMultiThreadMixer;\n  #endif\n\n  UInt32 _crcSize;\n\n  #else\n  \n  CRecordVector<CBond2> _bonds;\n\n  HRESULT PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m);\n  HRESULT SetHeaderMethod(CCompressionMethodMode &headerMethod);\n  HRESULT SetMainMethod(CCompressionMethodMode &method);\n\n  #endif\n\n  bool IsFolderEncrypted(CNum folderIndex) const;\n  #ifndef Z7_SFX\n\n  CRecordVector<UInt64> _fileInfoPopIDs;\n  void FillPopIDs();\n  void AddMethodName(AString &s, UInt64 id);\n  // **************** 7-Zip ZS Modification Start ****************\n  typedef struct MethodInfo {\n      AString methName;\n      int level;\n  } MethodInfo;\n  bool ObtainMethodFromBlocks(MethodInfo* info) const;\n  HRESULT ObtainBlockMethods(CNum folderIndex, PROPVARIANT* prop, MethodInfo* info) const;\n  // **************** 7-Zip ZS Modification End ****************\n  HRESULT SetMethodToProp(CNum folderIndex, PROPVARIANT *prop) const;\n\n  #endif\n\n  DECL_EXTERNAL_CODECS_VARS\n\npublic:\n  CHandler();\n  ~CHandler()\n  {\n    Close();\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zHandlerOut.cpp",
    "content": "﻿// 7zHandlerOut.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/StringToInt.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n#include \"../Common/ParseProperties.h\"\n\n#include \"7zHandler.h\"\n#include \"7zOut.h\"\n#include \"7zUpdate.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace N7z {\n\nstatic const UInt32 k_decoderCompatibilityVersion = 2301;\n// 7-Zip version 2301 supports ARM64 filter\n\n#define k_LZMA_Name \"LZMA\"\n#define kDefaultMethodName \"LZMA2\"\n#define k_Copy_Name \"Copy\"\n\n#define k_MatchFinder_ForHeaders \"BT2\"\n\nstatic const UInt32 k_NumFastBytes_ForHeaders = 273;\nstatic const UInt32 k_Level_ForHeaders = 5;\nstatic const UInt32 k_Dictionary_ForHeaders =\n  #ifdef UNDER_CE\n  1 << 18;\n  #else\n  1 << 20;\n  #endif\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  *type = NFileTimeType::kWindows;\n  return S_OK;\n}\n\nHRESULT CHandler::PropsMethod_To_FullMethod(CMethodFull &dest, const COneMethodInfo &m)\n{\n  bool isFilter;\n  dest.CodecIndex = FindMethod_Index(\n      EXTERNAL_CODECS_VARS\n      m.MethodName, true,\n      dest.Id, dest.NumStreams, isFilter);\n  if (dest.CodecIndex < 0)\n    return E_INVALIDARG;\n  (CProps &)dest = (CProps &)m;\n  return S_OK;\n}\n\nHRESULT CHandler::SetHeaderMethod(CCompressionMethodMode &headerMethod)\n{\n  if (!_compressHeaders)\n    return S_OK;\n  COneMethodInfo m;\n  m.MethodName = k_LZMA_Name;\n  m.AddProp_Ascii(NCoderPropID::kMatchFinder, k_MatchFinder_ForHeaders);\n  m.AddProp_Level(k_Level_ForHeaders);\n  m.AddProp32(NCoderPropID::kNumFastBytes, k_NumFastBytes_ForHeaders);\n  m.AddProp32(NCoderPropID::kDictionarySize, k_Dictionary_ForHeaders);\n  m.AddProp_NumThreads(1);\n\n  CMethodFull &methodFull = headerMethod.Methods.AddNew();\n  return PropsMethod_To_FullMethod(methodFull, m);\n}\n\n\nHRESULT CHandler::SetMainMethod(CCompressionMethodMode &methodMode)\n{\n  methodMode.Bonds = _bonds;\n\n  // we create local copy of _methods. So we can modify it.\n  CObjectVector<COneMethodInfo> methods = _methods;\n\n  {\n    FOR_VECTOR (i, methods)\n    {\n      AString &methodName = methods[i].MethodName;\n      if (methodName.IsEmpty())\n        methodName = kDefaultMethodName;\n    }\n    if (methods.IsEmpty())\n    {\n      COneMethodInfo &m = methods.AddNew();\n      m.MethodName = (GetLevel() == 0 ? k_Copy_Name : kDefaultMethodName);\n      methodMode.DefaultMethod_was_Inserted = true;\n    }\n  }\n\n  if (!_filterMethod.MethodName.IsEmpty())\n  {\n    // if (methodMode.Bonds.IsEmpty())\n    {\n      FOR_VECTOR (k, methodMode.Bonds)\n      {\n        CBond2 &bond = methodMode.Bonds[k];\n        bond.InCoder++;\n        bond.OutCoder++;\n      }\n      methods.Insert(0, _filterMethod);\n      methodMode.Filter_was_Inserted = true;\n    }\n  }\n\n  const UInt64 kSolidBytes_Min = 1 << 24;\n  const UInt64 kSolidBytes_Max = (UInt64)1 << 32;  // for non-LZMA2 methods\n\n  bool needSolid = false;\n  \n  FOR_VECTOR (i, methods)\n  {\n    COneMethodInfo &oneMethodInfo = methods[i];\n\n    SetGlobalLevelTo(oneMethodInfo);\n\n#ifndef Z7_ST\n    const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0);\n    if (!numThreads_WasSpecifiedInMethod)\n    {\n      // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already\n      CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, methodMode.NumThreads);\n    }\n    if (methodMode.NumThreadGroups > 1)\n      CMultiMethodProps::Set_Method_NumThreadGroups_IfNotFinded(oneMethodInfo, methodMode.NumThreadGroups);\n#endif\n\n    CMethodFull &methodFull = methodMode.Methods.AddNew();\n    RINOK(PropsMethod_To_FullMethod(methodFull, oneMethodInfo))\n\n#ifndef Z7_ST\n    methodFull.Set_NumThreads = true;\n    methodFull.NumThreads = methodMode.NumThreads;\n#endif\n\n    if (methodFull.Id != k_Copy)\n      needSolid = true;\n\n    UInt64 dicSize;\n    switch (methodFull.Id)\n    {\n      case k_LZMA:\n      case k_LZMA2: dicSize = oneMethodInfo.Get_Lzma_DicSize(); break;\n      case k_PPMD: dicSize = oneMethodInfo.Get_Ppmd_MemSize(); break;\n      case k_Deflate: dicSize = (UInt32)1 << 15; break;\n      case k_Deflate64: dicSize = (UInt32)1 << 16; break;\n      case k_BZip2: dicSize = oneMethodInfo.Get_BZip2_BlockSize(); break;\n      // case k_ZSTD: dicSize = 1 << 23; break;\n      default: continue;\n    }\n\n    UInt64 numSolidBytes;\n\n    /*\n    if (methodFull.Id == k_ZSTD)\n    {\n      // continue;\n      // **************** 7-Zip ZS Modification Start ****************\n      // NCompress::NZstd::CEncoderProps encoderProps;\n      NCompress::NZSTD::CEncoderProps encoderProps;\n      // **************** 7-Zip ZS Modification End ****************\n      RINOK(oneMethodInfo.Set_PropsTo_zstd(encoderProps));\n      CZstdEncProps &zstdProps = encoderProps.EncProps;\n      ZstdEncProps_NormalizeFull(&zstdProps);\n      UInt64 cs = (UInt64)(zstdProps.jobSize);\n      UInt32 winSize = (UInt32)(1 << zstdProps.windowLog);\n      if (cs < winSize)\n        cs = winSize;\n      numSolidBytes = cs << 6;\n      const UInt64 kSolidBytes_Zstd_Max = ((UInt64)1 << 34);\n      if (numSolidBytes > kSolidBytes_Zstd_Max)\n        numSolidBytes = kSolidBytes_Zstd_Max;\n\n      methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder\n\n      #ifndef Z7_ST\n      if (!numThreads_WasSpecifiedInMethod\n          && !methodMode.NumThreads_WasForced\n          && methodMode.MemoryUsageLimit_WasSet\n          )\n      {\n        const UInt32 numThreads_Original = methodMode.NumThreads;\n        const UInt32 numThreads_New = ZstdEncProps_GetNumThreads_for_MemUsageLimit(\n            &zstdProps,\n            methodMode.MemoryUsageLimit,\n            numThreads_Original);\n        if (numThreads_Original != numThreads_New)\n        {\n          CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New);\n        }\n      }\n      #endif\n    }\n    else\n    */\n    if (methodFull.Id == k_LZMA2)\n    {\n      // he we calculate default chunk Size for LZMA2 as defined in LZMA2 encoder code\n      /* lzma2 code use dictionary up to fake 4 GiB to calculate ChunkSize.\n         So we do same */\n      UInt64 cs = (UInt64)dicSize << 2;\n      const UInt32 kMinSize = (UInt32)1 << 20;\n      const UInt32 kMaxSize = (UInt32)1 << 28;\n      if (cs < kMinSize) cs = kMinSize;\n      if (cs > kMaxSize) cs = kMaxSize;\n      if (cs < dicSize) cs = dicSize;\n      cs += (kMinSize - 1);\n      cs &= ~(UInt64)(kMinSize - 1);\n      // we want to use at least 64 chunks (threads) per one solid block.\n\n      // here we don't use chunkSize property\n      numSolidBytes = cs << 6;\n\n      // here we get real chunkSize\n      cs = oneMethodInfo.Get_Xz_BlockSize();\n      if (dicSize > cs)\n          dicSize = cs;\n\n      const UInt64 kSolidBytes_Lzma2_Max = (UInt64)1 << 34;\n      if (numSolidBytes > kSolidBytes_Lzma2_Max)\n          numSolidBytes = kSolidBytes_Lzma2_Max;\n\n      methodFull.Set_NumThreads = false; // we don't use ICompressSetCoderMt::SetNumberOfThreads() for LZMA2 encoder\n\n      #ifndef Z7_ST\n      if (!numThreads_WasSpecifiedInMethod\n          && !methodMode.NumThreads_WasForced\n          && methodMode.MemoryUsageLimit_WasSet)\n      {\n        const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads();\n        const UInt32 numBlockThreads_Original = methodMode.NumThreads / lzmaThreads;\n\n        if (numBlockThreads_Original > 1)\n        {\n          /*\n            const UInt32 kNumThreads_Max = 1024;\n            if (numBlockThreads > kNumMaxThreads)\n            numBlockThreads = kNumMaxThreads;\n          */\n\n          UInt32 numBlockThreads = numBlockThreads_Original;\n          const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false); // solid\n          \n          for (; numBlockThreads > 1; numBlockThreads--)\n          {\n            UInt64 size = numBlockThreads * (lzmaMemUsage + cs);\n            UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;\n            if (cs < ((UInt32)1 << 26)) numPackChunks++;\n            if (cs < ((UInt32)1 << 24)) numPackChunks++;\n            if (cs < ((UInt32)1 << 22)) numPackChunks++;\n            size += numPackChunks * cs;\n            // printf(\"\\nnumBlockThreads = %d, size = %d\\n\", (unsigned)(numBlockThreads), (unsigned)(size >> 20));\n            if (size <= methodMode.MemoryUsageLimit)\n              break;\n          }\n\n          if (numBlockThreads == 0)\n            numBlockThreads = 1;\n          if (numBlockThreads != numBlockThreads_Original)\n          {\n            const UInt32 numThreads_New = numBlockThreads * lzmaThreads;\n            CMultiMethodProps::SetMethodThreadsTo_Replace(methodFull, numThreads_New);\n          }\n        }\n      }\n      #endif\n    }\n    else\n    {\n      numSolidBytes = (UInt64)dicSize << 7;\n      if (numSolidBytes > kSolidBytes_Max)\n          numSolidBytes = kSolidBytes_Max;\n    }\n\n    if (_numSolidBytesDefined)\n      continue;\n\n    if (numSolidBytes < kSolidBytes_Min)\n        numSolidBytes = kSolidBytes_Min;\n    _numSolidBytes = numSolidBytes;\n    _numSolidBytesDefined = true;\n  }\n\n  if (!_numSolidBytesDefined)\n  {\n    if (needSolid)\n      _numSolidBytes = kSolidBytes_Max;\n    else\n      _numSolidBytes = 0;\n  }\n  _numSolidBytesDefined = true;\n\n\n  return S_OK;\n}\n\n\n\nstatic HRESULT GetTime(IArchiveUpdateCallback *updateCallback, unsigned index, PROPID propID, UInt64 &ft, bool &ftDefined)\n{\n  // ft = 0;\n  // ftDefined = false;\n  NCOM::CPropVariant prop;\n  RINOK(updateCallback->GetProperty(index, propID, &prop))\n  if (prop.vt == VT_FILETIME)\n  {\n    ft = prop.filetime.dwLowDateTime | ((UInt64)prop.filetime.dwHighDateTime << 32);\n    ftDefined = true;\n  }\n  else if (prop.vt != VT_EMPTY)\n    return E_INVALIDARG;\n  else\n  {\n    ft = 0;\n    ftDefined = false;\n  }\n  return S_OK;\n}\n\n/*\n\n#ifdef _WIN32\nstatic const wchar_t kDirDelimiter1 = L'\\\\';\n#endif\nstatic const wchar_t kDirDelimiter2 = L'/';\n\nstatic inline bool IsCharDirLimiter(wchar_t c)\n{\n  return (\n    #ifdef _WIN32\n    c == kDirDelimiter1 ||\n    #endif\n    c == kDirDelimiter2);\n}\n\nstatic int FillSortIndex(CObjectVector<CTreeFolder> &treeFolders, int cur, int curSortIndex)\n{\n  CTreeFolder &tf = treeFolders[cur];\n  tf.SortIndex = curSortIndex++;\n  for (int i = 0; i < tf.SubFolders.Size(); i++)\n    curSortIndex = FillSortIndex(treeFolders, tf.SubFolders[i], curSortIndex);\n  tf.SortIndexEnd = curSortIndex;\n  return curSortIndex;\n}\n\nstatic int FindSubFolder(const CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name, int &insertPos)\n{\n  const CIntVector &subFolders = treeFolders[cur].SubFolders;\n  int left = 0, right = subFolders.Size();\n  insertPos = -1;\n  for (;;)\n  {\n    if (left == right)\n    {\n      insertPos = left;\n      return -1;\n    }\n    int mid = (left + right) / 2;\n    int midFolder = subFolders[mid];\n    int compare = CompareFileNames(name, treeFolders[midFolder].Name);\n    if (compare == 0)\n      return midFolder;\n    if (compare < 0)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n}\n\nstatic int AddFolder(CObjectVector<CTreeFolder> &treeFolders, int cur, const UString &name)\n{\n  int insertPos;\n  int folderIndex = FindSubFolder(treeFolders, cur, name, insertPos);\n  if (folderIndex < 0)\n  {\n    folderIndex = treeFolders.Size();\n    CTreeFolder &newFolder = treeFolders.AddNew();\n    newFolder.Parent = cur;\n    newFolder.Name = name;\n    treeFolders[cur].SubFolders.Insert(insertPos, folderIndex);\n  }\n  // else if (treeFolders[folderIndex].IsAltStreamFolder != isAltStreamFolder) throw 1123234234;\n  return folderIndex;\n}\n*/\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  const CDbEx *db = NULL;\n  #ifdef Z7_7Z_VOL\n  if (_volumes.Size() > 1)\n    return E_FAIL;\n  const CVolume *volume = 0;\n  if (_volumes.Size() == 1)\n  {\n    volume = &_volumes.Front();\n    db = &volume->Database;\n  }\n  #else\n  if (_inStream)\n    db = &_db;\n  #endif\n\n  if (db && !db->CanUpdate())\n    return E_NOTIMPL;\n\n  /*\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveGetRawProps,\n      getRawProps, updateCallback)\n\n  CUniqBlocks secureBlocks;\n  secureBlocks.AddUniq(NULL, 0);\n\n  CObjectVector<CTreeFolder> treeFolders;\n  {\n    CTreeFolder folder;\n    folder.Parent = -1;\n    treeFolders.Add(folder);\n  }\n  */\n\n  CObjectVector<CUpdateItem> updateItems;\n\n  bool need_CTime = (TimeOptions.Write_CTime.Def && TimeOptions.Write_CTime.Val);\n  bool need_ATime = (TimeOptions.Write_ATime.Def && TimeOptions.Write_ATime.Val);\n  bool need_MTime = (TimeOptions.Write_MTime.Def ? TimeOptions.Write_MTime.Val : true);\n  bool need_Attrib = (Write_Attrib.Def ? Write_Attrib.Val : true);\n  \n  if (db && !db->Files.IsEmpty())\n  {\n    if (!TimeOptions.Write_CTime.Def) need_CTime = !db->CTime.Defs.IsEmpty();\n    if (!TimeOptions.Write_ATime.Def) need_ATime = !db->ATime.Defs.IsEmpty();\n    if (!TimeOptions.Write_MTime.Def) need_MTime = !db->MTime.Defs.IsEmpty();\n    if (!Write_Attrib.Def) need_Attrib = !db->Attrib.Defs.IsEmpty();\n  }\n\n  // **************** 7-Zip ZS Modification Start ****************\n  // if no methods specified in options (and not pure copy) - try to obtain it from archived item,\n  // (at the moment only once for 1st item block, because otherwise we'd need to rewrite every interface to set codecs per item):\n  if (_methods.IsEmpty() && _level != 0) {\n    CHandler::MethodInfo mInfo;\n    if (ObtainMethodFromBlocks(&mInfo)) {\n      //printf(\"************ fnd-block-method: %s, lev: %d\\n\", mInfo.methName.Ptr(), mInfo.level);\n      // set as default method (also _methods is not empty now, so this shall not be invoked anymore):\n      if (!mInfo.methName.IsEmpty()) {\n        COneMethodInfo &m = _methods.AddNew();\n        m.MethodName = mInfo.methName;\n        // **************** 7-Zip ZS Modification Start ****************\n        //if ((_level == -1) && (mInfo.level != -1)) {\n        if ((_level == (UInt32)-1) && (mInfo.level != -1)) {\n          // XXX - does not work in linux this way\n        // **************** 7-Zip ZS Modification End ****************\n          _level = mInfo.level;\n        }\n      }\n    }\n  }\n  // **************** 7-Zip ZS Modification End ****************\n\n  // UString s;\n  UString name;\n\n  for (UInt32 i = 0; i < numItems; i++)\n  {\n    Int32 newData, newProps;\n    UInt32 indexInArchive;\n    if (!updateCallback)\n      return E_FAIL;\n    RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive))\n    CUpdateItem ui;\n    ui.NewProps = IntToBool(newProps);\n    ui.NewData = IntToBool(newData);\n    ui.IndexInArchive = (int)indexInArchive;\n    ui.IndexInClient = i;\n    ui.IsAnti = false;\n    ui.Size = 0;\n\n    name.Empty();\n    // bool isAltStream = false;\n    if (ui.IndexInArchive != -1)\n    {\n      if (!db || (unsigned)ui.IndexInArchive >= db->Files.Size())\n        return E_INVALIDARG;\n      const CFileItem &fi = db->Files[(unsigned)ui.IndexInArchive];\n      if (!ui.NewProps)\n      {\n        _db.GetPath((unsigned)ui.IndexInArchive, name);\n      }\n      ui.IsDir = fi.IsDir;\n      ui.Size = fi.Size;\n      // isAltStream = fi.IsAltStream;\n      ui.IsAnti = db->IsItemAnti((unsigned)ui.IndexInArchive);\n      \n      if (!ui.NewProps)\n      {\n        ui.CTimeDefined = db->CTime.GetItem((unsigned)ui.IndexInArchive, ui.CTime);\n        ui.ATimeDefined = db->ATime.GetItem((unsigned)ui.IndexInArchive, ui.ATime);\n        ui.MTimeDefined = db->MTime.GetItem((unsigned)ui.IndexInArchive, ui.MTime);\n      }\n    }\n\n    if (ui.NewProps)\n    {\n      bool folderStatusIsDefined;\n      if (need_Attrib)\n      {\n        NCOM::CPropVariant prop;\n        RINOK(updateCallback->GetProperty(i, kpidAttrib, &prop))\n        if (prop.vt == VT_EMPTY)\n          ui.AttribDefined = false;\n        else if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n        else\n        {\n          ui.Attrib = prop.ulVal;\n          ui.AttribDefined = true;\n        }\n      }\n      \n      // we need MTime to sort files.\n      if (need_CTime) RINOK(GetTime(updateCallback, i, kpidCTime, ui.CTime, ui.CTimeDefined))\n      if (need_ATime) RINOK(GetTime(updateCallback, i, kpidATime, ui.ATime, ui.ATimeDefined))\n      if (need_MTime) RINOK(GetTime(updateCallback, i, kpidMTime, ui.MTime, ui.MTimeDefined))\n\n      /*\n      if (getRawProps)\n      {\n        const void *data;\n        UInt32 dataSize;\n        UInt32 propType;\n\n        getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);\n        if (dataSize != 0 && propType != NPropDataType::kRaw)\n          return E_FAIL;\n        ui.SecureIndex = secureBlocks.AddUniq((const Byte *)data, dataSize);\n      }\n      */\n\n      {\n        NCOM::CPropVariant prop;\n        RINOK(updateCallback->GetProperty(i, kpidPath, &prop))\n        if (prop.vt == VT_EMPTY)\n        {\n        }\n        else if (prop.vt != VT_BSTR)\n          return E_INVALIDARG;\n        else\n        {\n          name = prop.bstrVal;\n          NItemName::ReplaceSlashes_OsToUnix(name);\n        }\n      }\n      {\n        NCOM::CPropVariant prop;\n        RINOK(updateCallback->GetProperty(i, kpidIsDir, &prop))\n        if (prop.vt == VT_EMPTY)\n          folderStatusIsDefined = false;\n        else if (prop.vt != VT_BOOL)\n          return E_INVALIDARG;\n        else\n        {\n          ui.IsDir = (prop.boolVal != VARIANT_FALSE);\n          folderStatusIsDefined = true;\n        }\n      }\n\n      {\n        NCOM::CPropVariant prop;\n        RINOK(updateCallback->GetProperty(i, kpidIsAnti, &prop))\n        if (prop.vt == VT_EMPTY)\n          ui.IsAnti = false;\n        else if (prop.vt != VT_BOOL)\n          return E_INVALIDARG;\n        else\n          ui.IsAnti = (prop.boolVal != VARIANT_FALSE);\n      }\n\n      /*\n      {\n        NCOM::CPropVariant prop;\n        RINOK(updateCallback->GetProperty(i, kpidIsAltStream, &prop));\n        if (prop.vt == VT_EMPTY)\n          isAltStream = false;\n        else if (prop.vt != VT_BOOL)\n          return E_INVALIDARG;\n        else\n          isAltStream = (prop.boolVal != VARIANT_FALSE);\n      }\n      */\n\n      if (ui.IsAnti)\n      {\n        ui.AttribDefined = false;\n\n        ui.CTimeDefined = false;\n        ui.ATimeDefined = false;\n        ui.MTimeDefined = false;\n        \n        ui.Size = 0;\n      }\n\n      if (!folderStatusIsDefined && ui.AttribDefined)\n        ui.SetDirStatusFromAttrib();\n    }\n    else\n    {\n      /*\n      if (_db.SecureIDs.IsEmpty())\n        ui.SecureIndex = secureBlocks.AddUniq(NULL, 0);\n      else\n      {\n        int id = _db.SecureIDs[ui.IndexInArchive];\n        size_t offs = _db.SecureOffsets[id];\n        size_t size = _db.SecureOffsets[id + 1] - offs;\n        ui.SecureIndex = secureBlocks.AddUniq(_db.SecureBuf + offs, size);\n      }\n      */\n    }\n\n    /*\n    {\n      int folderIndex = 0;\n      if (_useParents)\n      {\n        int j;\n        s.Empty();\n        for (j = 0; j < name.Len(); j++)\n        {\n          wchar_t c = name[j];\n          if (IsCharDirLimiter(c))\n          {\n            folderIndex = AddFolder(treeFolders, folderIndex, s);\n            s.Empty();\n            continue;\n          }\n          s += c;\n        }\n        if (isAltStream)\n        {\n          int colonPos = s.Find(':');\n          if (colonPos < 0)\n          {\n            // isAltStream = false;\n            return E_INVALIDARG;\n          }\n          UString mainName = s.Left(colonPos);\n          int newFolderIndex = AddFolder(treeFolders, folderIndex, mainName);\n          if (treeFolders[newFolderIndex].UpdateItemIndex < 0)\n          {\n            for (int j = updateItems.Size() - 1; j >= 0; j--)\n            {\n              CUpdateItem &ui2 = updateItems[j];\n              if (ui2.ParentFolderIndex == folderIndex\n                  && ui2.Name == mainName)\n              {\n                ui2.TreeFolderIndex = newFolderIndex;\n                treeFolders[newFolderIndex].UpdateItemIndex = j;\n              }\n            }\n          }\n          folderIndex = newFolderIndex;\n          s.Delete(0, colonPos + 1);\n        }\n        ui.Name = s;\n      }\n      else\n        ui.Name = name;\n      ui.IsAltStream = isAltStream;\n      ui.ParentFolderIndex = folderIndex;\n      ui.TreeFolderIndex = -1;\n      if (ui.IsDir && !s.IsEmpty())\n      {\n        ui.TreeFolderIndex = AddFolder(treeFolders, folderIndex, s);\n        treeFolders[ui.TreeFolderIndex].UpdateItemIndex = updateItems.Size();\n      }\n    }\n    */\n    ui.Name = name;\n\n    if (ui.NewData)\n    {\n      ui.Size = 0;\n      if (!ui.IsDir)\n      {\n        NCOM::CPropVariant prop;\n        RINOK(updateCallback->GetProperty(i, kpidSize, &prop))\n        if (prop.vt != VT_UI8)\n          return E_INVALIDARG;\n        ui.Size = (UInt64)prop.uhVal.QuadPart;\n        if (ui.Size != 0 && ui.IsAnti)\n          return E_INVALIDARG;\n      }\n    }\n    \n    updateItems.Add(ui);\n  }\n\n  /*\n  FillSortIndex(treeFolders, 0, 0);\n  for (i = 0; i < (UInt32)updateItems.Size(); i++)\n  {\n    CUpdateItem &ui = updateItems[i];\n    ui.ParentSortIndex = treeFolders[ui.ParentFolderIndex].SortIndex;\n    ui.ParentSortIndexEnd = treeFolders[ui.ParentFolderIndex].SortIndexEnd;\n  }\n  */\n\n  CCompressionMethodMode methodMode, headerMethod;\n\n  methodMode.MemoryUsageLimit = _memUsage_Compress;\n  methodMode.MemoryUsageLimit_WasSet = _memUsage_WasSet;\n\n  #ifndef Z7_ST\n  {\n    UInt32 numThreads = _numThreads;\n    const UInt32 kNumThreads_Max = 1024;\n    if (numThreads > kNumThreads_Max)\n      numThreads = kNumThreads_Max;\n    methodMode.NumThreads = numThreads;\n    methodMode.NumThreads_WasForced = _numThreads_WasForced;\n    methodMode.MultiThreadMixer = _useMultiThreadMixer;\n#ifdef _WIN32\n    methodMode.NumThreadGroups = _numThreadGroups; // _change it\n#endif\n    // headerMethod.NumThreads = 1;\n    headerMethod.MultiThreadMixer = _useMultiThreadMixer;\n  }\n  #endif\n\n  const HRESULT res = SetMainMethod(methodMode);\n  RINOK(res)\n\n  RINOK(SetHeaderMethod(headerMethod))\n  \n  Z7_DECL_CMyComPtr_QI_FROM(\n    ICryptoGetTextPassword2,\n    getPassword2, updateCallback)\n\n  methodMode.PasswordIsDefined = false;\n  methodMode.Password.Wipe_and_Empty();\n  if (getPassword2)\n  {\n    CMyComBSTR_Wipe password;\n    Int32 passwordIsDefined;\n    RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password))\n    methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);\n    if (methodMode.PasswordIsDefined && password)\n      methodMode.Password = password;\n  }\n\n  bool compressMainHeader = _compressHeaders;  // check it\n\n  bool encryptHeaders = false;\n\n  #ifndef Z7_NO_CRYPTO\n  if (!methodMode.PasswordIsDefined && _passwordIsDefined)\n  {\n    // if header is compressed, we use that password for updated archive\n    methodMode.PasswordIsDefined = true;\n    methodMode.Password = _password;\n  }\n  #endif\n\n  if (methodMode.PasswordIsDefined)\n  {\n    if (_encryptHeadersSpecified)\n      encryptHeaders = _encryptHeaders;\n    #ifndef Z7_NO_CRYPTO\n    else\n      encryptHeaders = _passwordIsDefined;\n    #endif\n    compressMainHeader = true;\n    if (encryptHeaders)\n    {\n      headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;\n      headerMethod.Password = methodMode.Password;\n    }\n  }\n\n  if (numItems < 2)\n    compressMainHeader = false;\n\n  const int level = GetLevel();\n\n  CUpdateOptions options;\n  options.Need_CTime = need_CTime;\n  options.Need_ATime = need_ATime;\n  options.Need_MTime = need_MTime;\n  options.Need_Attrib = need_Attrib;\n  // options.Need_Crc = (_crcSize != 0); // for debug\n\n  options.Method = &methodMode;\n  options.HeaderMethod = (_compressHeaders || encryptHeaders) ? &headerMethod : NULL;\n  options.UseFilters = (level != 0 && _autoFilter && !methodMode.Filter_was_Inserted);\n  options.MaxFilter = (level >= 8);\n  options.AnalysisLevel = GetAnalysisLevel();\n\n  options.SetFilterSupporting_ver_enabled_disabled(\n      _decoderCompatibilityVersion,\n      _enabledFilters,\n      _disabledFilters);\n\n  options.HeaderOptions.CompressMainHeader = compressMainHeader;\n  /*\n  options.HeaderOptions.WriteCTime = Write_CTime;\n  options.HeaderOptions.WriteATime = Write_ATime;\n  options.HeaderOptions.WriteMTime = Write_MTime;\n  options.HeaderOptions.WriteAttrib = Write_Attrib;\n  */\n  \n  options.NumSolidFiles = _numSolidFiles;\n  options.NumSolidBytes = _numSolidBytes;\n  options.SolidExtension = _solidExtension;\n  options.UseTypeSorting = _useTypeSorting;\n\n  options.RemoveSfxBlock = _removeSfxBlock;\n  // options.VolumeMode = _volumeMode;\n\n  options.MultiThreadMixer = _useMultiThreadMixer;\n\n  /*\n  if (secureBlocks.Sorted.Size() > 1)\n  {\n    secureBlocks.GetReverseMap();\n    for (int i = 0; i < updateItems.Size(); i++)\n    {\n      int &secureIndex = updateItems[i].SecureIndex;\n      secureIndex = secureBlocks.BufIndexToSortedIndex[secureIndex];\n    }\n  }\n  */\n\n  return Update(\n      EXTERNAL_CODECS_VARS\n      #ifdef Z7_7Z_VOL\n      volume ? volume->Stream: 0,\n      volume ? db : 0,\n      #else\n      _inStream,\n      db,\n      #endif\n      updateItems,\n      // treeFolders,\n      // secureBlocks,\n      outStream, updateCallback, options);\n\n  COM_TRY_END\n}\n\nstatic HRESULT ParseBond(UString &srcString, UInt32 &coder, UInt32 &stream)\n{\n  stream = 0;\n  {\n    const unsigned index = ParseStringToUInt32(srcString, coder);\n    if (index == 0)\n      return E_INVALIDARG;\n    srcString.DeleteFrontal(index);\n  }\n  if (srcString[0] == 's')\n  {\n    srcString.Delete(0);\n    const unsigned index = ParseStringToUInt32(srcString, stream);\n    if (index == 0)\n      return E_INVALIDARG;\n    srcString.DeleteFrontal(index);\n  }\n  return S_OK;\n}\n\nvoid COutHandler::InitProps7z()\n{\n  _removeSfxBlock = false;\n  _compressHeaders = true;\n  _encryptHeadersSpecified = false;\n  _encryptHeaders = false;\n  // _useParents = false;\n  \n  TimeOptions.Init();\n  Write_Attrib.Init();\n\n  _useMultiThreadMixer = true;\n\n  // _volumeMode = false;\n\n  InitSolid();\n  _useTypeSorting = false;\n\n  _decoderCompatibilityVersion = k_decoderCompatibilityVersion;\n  _enabledFilters.Clear();\n  _disabledFilters.Clear();\n}\n\nvoid COutHandler::InitProps()\n{\n  CMultiMethodProps::Init();\n  InitProps7z();\n}\n\n\n\nHRESULT COutHandler::SetSolidFromString(const UString &s)\n{\n  UString s2 = s;\n  s2.MakeLower_Ascii();\n  for (unsigned i = 0; i < s2.Len();)\n  {\n    const wchar_t *start = ((const wchar_t *)s2) + i;\n    const wchar_t *end;\n    UInt64 v = ConvertStringToUInt64(start, &end);\n    if (start == end)\n    {\n      if (s2[i++] != 'e')\n        return E_INVALIDARG;\n      _solidExtension = true;\n      continue;\n    }\n    i += (unsigned)(end - start);\n    if (i == s2.Len())\n      return E_INVALIDARG;\n    const wchar_t c = s2[i++];\n    if (c == 'f')\n    {\n      if (v < 1)\n        v = 1;\n      _numSolidFiles = v;\n    }\n    else\n    {\n      unsigned numBits;\n      switch (c)\n      {\n        case 'b': numBits =  0; break;\n        case 'k': numBits = 10; break;\n        case 'm': numBits = 20; break;\n        case 'g': numBits = 30; break;\n        case 't': numBits = 40; break;\n        default: return E_INVALIDARG;\n      }\n      _numSolidBytes = (v << numBits);\n      _numSolidBytesDefined = true;\n      /*\n      if (_numSolidBytes == 0)\n        _numSolidFiles = 1;\n      */\n    }\n  }\n  return S_OK;\n}\n\nHRESULT COutHandler::SetSolidFromPROPVARIANT(const PROPVARIANT &value)\n{\n  bool isSolid;\n  switch (value.vt)\n  {\n    case VT_EMPTY: isSolid = true; break;\n    case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;\n    case VT_BSTR:\n      if (StringToBool(value.bstrVal, isSolid))\n        break;\n      return SetSolidFromString(value.bstrVal);\n    default: return E_INVALIDARG;\n  }\n  if (isSolid)\n    InitSolid();\n  else\n    _numSolidFiles = 1;\n  return S_OK;\n}\n\nstatic HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)\n{\n  RINOK(PROPVARIANT_to_bool(prop, dest.Val))\n  dest.Def = true;\n  return S_OK;\n}\n\nstruct C_Id_Name_pair\n{\n  UInt32 Id;\n  const char *Name;\n};\n\nstatic const C_Id_Name_pair g_filter_pairs[] =\n{\n  { k_Delta, \"Delta\" },\n  { k_ARM64, \"ARM64\" },\n  { k_RISCV, \"RISCV\" },\n  { k_SWAP2, \"SWAP2\" },\n  { k_SWAP4, \"SWAP4\" },\n  { k_BCJ,   \"BCJ\" },\n  { k_BCJ2 , \"BCJ2\" },\n  { k_PPC,   \"PPC\" },\n  { k_IA64,  \"IA64\" },\n  { k_ARM,   \"ARM\" },\n  { k_ARMT,  \"ARMT\" },\n  { k_SPARC, \"SPARC\" }\n};\n\n\nHRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)\n{\n  UString name = nameSpec;\n  name.MakeLower_Ascii();\n  if (name.IsEmpty())\n    return E_INVALIDARG;\n  \n  if (name[0] == L's')\n  {\n    name.Delete(0);\n    if (name.IsEmpty())\n      return SetSolidFromPROPVARIANT(value);\n    if (value.vt != VT_EMPTY)\n      return E_INVALIDARG;\n    return SetSolidFromString(name);\n  }\n\n  UInt32 number;\n  const unsigned index = ParseStringToUInt32(name, number);\n  // UString realName = name.Ptr(index);\n  if (index == 0)\n  {\n    if (name.IsEqualTo(\"rsfx\")) return PROPVARIANT_to_bool(value, _removeSfxBlock);\n    if (name.IsEqualTo(\"hc\")) return PROPVARIANT_to_bool(value, _compressHeaders);\n    // if (name.IsEqualToNoCase(L\"HS\")) return PROPVARIANT_to_bool(value, _useParents);\n    \n    if (name.IsEqualTo(\"hcf\"))\n    {\n      bool compressHeadersFull = true;\n      RINOK(PROPVARIANT_to_bool(value, compressHeadersFull))\n      return compressHeadersFull ? S_OK: E_INVALIDARG;\n    }\n    \n    if (name.IsEqualTo(\"he\"))\n    {\n      RINOK(PROPVARIANT_to_bool(value, _encryptHeaders))\n      _encryptHeadersSpecified = true;\n      return S_OK;\n    }\n    \n    {\n      bool processed;\n      RINOK(TimeOptions.Parse(name, value, processed))\n      if (processed)\n      {\n        if (   TimeOptions.Prec != (UInt32)(Int32)-1\n            && TimeOptions.Prec != k_PropVar_TimePrec_0\n            && TimeOptions.Prec != k_PropVar_TimePrec_HighPrec\n            && TimeOptions.Prec != k_PropVar_TimePrec_100ns)\n          return E_INVALIDARG;\n        return S_OK;\n      }\n    }\n\n    if (name.IsEqualTo(\"tr\")) return PROPVARIANT_to_BoolPair(value, Write_Attrib);\n    \n    if (name.IsEqualTo(\"mtf\")) return PROPVARIANT_to_bool(value, _useMultiThreadMixer);\n\n    if (name.IsEqualTo(\"qs\")) return PROPVARIANT_to_bool(value, _useTypeSorting);\n\n    if (name.IsPrefixedBy_Ascii_NoCase(\"yv\"))\n    {\n      name.Delete(0, 2);\n      UInt32 v = 1 << 16;  // if no number is noit specified, we use big value\n      RINOK(ParsePropToUInt32(name, value, v))\n      _decoderCompatibilityVersion = v;\n      // if (v == 0) _decoderCompatibilityVersion = k_decoderCompatibilityVersion;\n      return S_OK;\n    }\n\n    if (name.IsPrefixedBy_Ascii_NoCase(\"yf\"))\n    {\n      name.Delete(0, 2);\n      CUIntVector *vec;\n           if (name.IsEqualTo_Ascii_NoCase(\"a\")) vec = &_enabledFilters;\n      else if (name.IsEqualTo_Ascii_NoCase(\"d\")) vec = &_disabledFilters;\n      else return E_INVALIDARG;\n\n      if (value.vt != VT_BSTR)\n        return E_INVALIDARG;\n      for (unsigned k = 0;; k++)\n      {\n        if (k == Z7_ARRAY_SIZE(g_filter_pairs))\n        {\n          // maybe we can ignore unsupported filter names here?\n          return E_INVALIDARG;\n        }\n        const C_Id_Name_pair &pair = g_filter_pairs[k];\n        if (StringsAreEqualNoCase_Ascii(value.bstrVal, pair.Name))\n        {\n          vec->AddToUniqueSorted(pair.Id);\n          break;\n        }\n      }\n      return S_OK;\n    }\n\n    // if (name.IsEqualTo(\"v\"))  return PROPVARIANT_to_bool(value, _volumeMode);\n  }\n  return CMultiMethodProps::SetProperty(name, value);\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  COM_TRY_BEGIN\n  _bonds.Clear();\n  InitProps();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    UString name = names[i];\n    name.MakeLower_Ascii();\n    if (name.IsEmpty())\n      return E_INVALIDARG;\n\n    const PROPVARIANT &value = values[i];\n\n    if (name.Find(L':') >= 0) // 'b' was used as NCoderPropID::kBlockSize2 before v23\n    if (name[0] == 'b')\n    {\n      if (value.vt != VT_EMPTY)\n        return E_INVALIDARG;\n      name.Delete(0);\n      \n      CBond2 bond;\n      RINOK(ParseBond(name, bond.OutCoder, bond.OutStream))\n      if (name[0] != ':')\n        return E_INVALIDARG;\n      name.Delete(0);\n      UInt32 inStream = 0;\n      RINOK(ParseBond(name, bond.InCoder, inStream))\n      if (inStream != 0)\n        return E_INVALIDARG;\n      if (!name.IsEmpty())\n        return E_INVALIDARG;\n      _bonds.Add(bond);\n      continue;\n    }\n\n    RINOK(SetProperty(name, value))\n  }\n\n  unsigned numEmptyMethods = GetNumEmptyMethods();\n  if (numEmptyMethods > 0)\n  {\n    unsigned k;\n    for (k = 0; k < _bonds.Size(); k++)\n    {\n      const CBond2 &bond = _bonds[k];\n      if (bond.InCoder < (UInt32)numEmptyMethods ||\n          bond.OutCoder < (UInt32)numEmptyMethods)\n        return E_INVALIDARG;\n    }\n    for (k = 0; k < _bonds.Size(); k++)\n    {\n      CBond2 &bond = _bonds[k];\n      bond.InCoder -= (UInt32)numEmptyMethods;\n      bond.OutCoder -= (UInt32)numEmptyMethods;\n    }\n    _methods.DeleteFrontal(numEmptyMethods);\n  }\n  \n  FOR_VECTOR (k, _bonds)\n  {\n    const CBond2 &bond = _bonds[k];\n    if (bond.InCoder >= (UInt32)_methods.Size() ||\n        bond.OutCoder >= (UInt32)_methods.Size())\n      return E_INVALIDARG;\n  }\n\n  return S_OK;\n  COM_TRY_END\n}\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zHeader.cpp",
    "content": "﻿// 7zHeader.cpp\n\n#include \"StdAfx.h\"\n\n#include \"7zHeader.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nByte kSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};\n#ifdef Z7_7Z_VOL\nByte kFinishSignature[kSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};\n#endif\n\n// We can change signature. So file doesn't contain correct signature.\n// struct SignatureInitializer { SignatureInitializer() { kSignature[0]--; } };\n// static SignatureInitializer g_SignatureInitializer;\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zHeader.h",
    "content": "﻿// 7z/7zHeader.h\n\n#ifndef ZIP7_INC_7Z_HEADER_H\n#define ZIP7_INC_7Z_HEADER_H\n\n#include \"../../../Common/MyTypes.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nconst unsigned kSignatureSize = 6;\nextern Byte kSignature[kSignatureSize];\n\n// #define Z7_7Z_VOL\n// 7z-MultiVolume is not finished yet.\n// It can work already, but I still do not like some\n// things of that new multivolume format.\n// So please keep it commented.\n\n#ifdef Z7_7Z_VOL\nextern Byte kFinishSignature[kSignatureSize];\n#endif\n\nstruct CArchiveVersion\n{\n  Byte Major;\n  Byte Minor;\n};\n\nconst Byte kMajorVersion = 0;\n\nstruct CStartHeader\n{\n  UInt64 NextHeaderOffset;\n  UInt64 NextHeaderSize;\n  UInt32 NextHeaderCRC;\n};\n\nconst UInt32 kStartHeaderSize = 20;\n\n#ifdef Z7_7Z_VOL\nstruct CFinishHeader: public CStartHeader\n{\n  UInt64 ArchiveStartOffset;  // data offset from end if that struct\n  UInt64 AdditionalStartBlockSize; // start  signature & start header size\n};\n\nconst UInt32 kFinishHeaderSize = kStartHeaderSize + 16;\n#endif\n\nnamespace NID\n{\n  enum EEnum\n  {\n    kEnd,\n\n    kHeader,\n\n    kArchiveProperties,\n    \n    kAdditionalStreamsInfo,\n    kMainStreamsInfo,\n    kFilesInfo,\n    \n    kPackInfo,\n    kUnpackInfo,\n    kSubStreamsInfo,\n\n    kSize,\n    kCRC,\n\n    kFolder,\n\n    kCodersUnpackSize,\n    kNumUnpackStream,\n\n    kEmptyStream,\n    kEmptyFile,\n    kAnti,\n\n    kName,\n    kCTime,\n    kATime,\n    kMTime,\n    kWinAttrib,\n    kComment,\n\n    kEncodedHeader,\n\n    kStartPos,\n    kDummy\n\n    // kNtSecure,\n    // kParent,\n    // kIsAux\n  };\n}\n\n\nconst UInt32 k_Copy = 0;\nconst UInt32 k_Delta = 3;\nconst UInt32 k_ARM64 = 0xa;\nconst UInt32 k_RISCV = 0xb;\n\nconst UInt32 k_LZMA2 = 0x21;\n\nconst UInt32 k_SWAP2 = 0x20302;\nconst UInt32 k_SWAP4 = 0x20304;\n\nconst UInt32 k_LZMA  = 0x30101;\nconst UInt32 k_PPMD  = 0x30401;\n\nconst UInt32 k_Deflate   = 0x40108;\nconst UInt32 k_Deflate64 = 0x40109;\nconst UInt32 k_BZip2     = 0x40202;\n\nconst UInt32 k_BCJ   = 0x3030103;\nconst UInt32 k_BCJ2  = 0x303011B;\nconst UInt32 k_PPC   = 0x3030205;\nconst UInt32 k_IA64  = 0x3030401;\nconst UInt32 k_ARM   = 0x3030501;\nconst UInt32 k_ARMT  = 0x3030701;\nconst UInt32 k_SPARC = 0x3030805;\n\n// **************** 7-Zip ZS Modification Start ****************\nconst UInt32 k_LZHAM = 0x4F71001;\nconst UInt32 k_ZSTD  = 0x4F71101;\nconst UInt32 k_BROTLI= 0x4F71102;\nconst UInt32 k_LZ4   = 0x4F71104;\nconst UInt32 k_LZ5   = 0x4F71105;\nconst UInt32 k_LIZARD= 0x4F71106;\n// **************** 7-Zip ZS Modification End ****************\n\nconst UInt32 k_AES   = 0x6F10701;\n\n// const UInt32 k_ZSTD = 0x4015D; // winzip zstd\n// 0x4F71101, 7z-zstd\n\ninline bool IsFilterMethod(UInt64 m)\n{\n  if (m > (UInt32)0xFFFFFFFF)\n    return false;\n  switch ((UInt32)m)\n  {\n    case k_Delta:\n    case k_ARM64:\n    case k_RISCV:\n    case k_BCJ:\n    case k_BCJ2:\n    case k_PPC:\n    case k_IA64:\n    case k_ARM:\n    case k_ARMT:\n    case k_SPARC:\n    case k_SWAP2:\n    case k_SWAP4:\n      return true;\n    default: break;\n  }\n  return false;\n}\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zIn.cpp",
    "content": "﻿// 7zIn.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef _WIN32\n#include <wchar.h>\n#else\n#include <ctype.h>\n#endif\n\n#include \"../../../../C/7zCrc.h\"\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/MyBuffer2.h\"\n// #include \"../../../Common/UTFConvert.h\"\n\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"7zDecode.h\"\n#include \"7zIn.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader\n#ifndef Z7_SFX\n#define FORMAT_7Z_RECOVERY\n#endif\n\nusing namespace NWindows;\nusing namespace NCOM;\n\nunsigned BoolVector_CountSum(const CBoolVector &v);\nZ7_NO_INLINE\nunsigned BoolVector_CountSum(const CBoolVector &v)\n{\n  unsigned sum = 0;\n  const unsigned size = v.Size();\n  if (size)\n  {\n    const bool *p = v.ConstData();\n    const bool * const lim = p + size;\n    do\n     if (*p)\n       sum++;\n    while (++p != lim);\n  }\n  return sum;\n}\n\nstatic inline bool BoolVector_Item_IsValidAndTrue(const CBoolVector &v, unsigned i)\n{\n  return i < v.Size() ? v[i] : false;\n}\n\nZ7_NO_INLINE\nstatic void BoolVector_Fill_False(CBoolVector &v, unsigned size)\n{\n  v.ClearAndSetSize(size);\n  bool *p = v.NonConstData();\n  for (unsigned i = 0; i < size; i++)\n    p[i] = false;\n}\n\n\nnamespace NArchive {\nnamespace N7z {\n\n#define k_Scan_NumCoders_MAX 64\n#define k_Scan_NumCodersStreams_in_Folder_MAX 64\n\nclass CInArchiveException {};\nclass CUnsupportedFeatureException: public CInArchiveException {};\n\nZ7_ATTR_NORETURN\nstatic void ThrowException() { throw CInArchiveException(); }\nZ7_ATTR_NORETURN\nstatic inline void ThrowEndOfData()   { ThrowException(); }\nZ7_ATTR_NORETURN\nstatic inline void ThrowUnsupported() { throw CUnsupportedFeatureException(); }\nZ7_ATTR_NORETURN\nstatic inline void ThrowIncorrect()   { ThrowException(); }\n\nclass CStreamSwitch\n{\n  CInArchive *_archive;\n  bool _needRemove;\n  bool _needUpdatePos;\npublic:\n  CStreamSwitch(): _needRemove(false), _needUpdatePos(false) {}\n  ~CStreamSwitch() { Remove(); }\n  void Remove();\n  void Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos);\n  void Set(CInArchive *archive, const CByteBuffer &byteBuffer);\n  void Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);\n};\n\nvoid CStreamSwitch::Remove()\n{\n  if (_needRemove)\n  {\n    if (_archive->_inByteBack->GetRem() != 0)\n      _archive->ThereIsHeaderError = true;\n    _archive->DeleteByteStream(_needUpdatePos);\n    _needRemove = false;\n  }\n}\n\nvoid CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size, bool needUpdatePos)\n{\n  Remove();\n  _archive = archive;\n  _archive->AddByteStream(data, size);\n  _needRemove = true;\n  _needUpdatePos = needUpdatePos;\n}\n\nvoid CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)\n{\n  Set(archive, byteBuffer, byteBuffer.Size(), false);\n}\n\nvoid CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)\n{\n  Remove();\n  const Byte external = archive->ReadByte();\n  if (external != 0)\n  {\n    if (!dataVector)\n      ThrowIncorrect();\n    const CNum dataIndex = archive->ReadNum();\n    if (dataIndex >= dataVector->Size())\n      ThrowIncorrect();\n    Set(archive, (*dataVector)[dataIndex]);\n  }\n}\n\nvoid CInArchive::AddByteStream(const Byte *buf, size_t size)\n{\n  if (_numInByteBufs == kNumBufLevelsMax)\n    ThrowIncorrect();\n  _inByteBack = &_inByteVector[_numInByteBufs++];\n  _inByteBack->Init(buf, size);\n}\n  \n\nByte CInByte2::ReadByte()\n{\n  if (_pos >= _size)\n    ThrowEndOfData();\n  return _buffer[_pos++];\n}\n\nvoid CInByte2::ReadBytes(Byte *data, size_t size)\n{\n  if (size == 0)\n    return;\n  if (size > _size - _pos)\n    ThrowEndOfData();\n  memcpy(data, _buffer + _pos, size);\n  _pos += size;\n}\n\nvoid CInByte2::SkipData(UInt64 size)\n{\n  if (size > _size - _pos)\n    ThrowEndOfData();\n  _pos += (size_t)size;\n}\n\nvoid CInByte2::SkipData()\n{\n  SkipData(ReadNumber());\n}\n\nstatic UInt64 ReadNumberSpec(const Byte *p, size_t size, size_t &processed)\n{\n  if (size == 0)\n  {\n    processed = 0;\n    return 0;\n  }\n  \n  const unsigned b = *p++;\n  size--;\n  \n  if ((b & 0x80) == 0)\n  {\n    processed = 1;\n    return b;\n  }\n  \n  if (size == 0)\n  {\n    processed = 0;\n    return 0;\n  }\n  \n  UInt64 value = (UInt64)*p;\n  p++;\n  size--;\n  \n  for (unsigned i = 1; i < 8; i++)\n  {\n    const unsigned mask = (unsigned)0x80 >> i;\n    if ((b & mask) == 0)\n    {\n      const UInt64 high = b & (mask - 1);\n      value |= (high << (i * 8));\n      processed = i + 1;\n      return value;\n    }\n    \n    if (size == 0)\n    {\n      processed = 0;\n      return 0;\n    }\n    \n    value |= ((UInt64)*p << (i * 8));\n    p++;\n    size--;\n  }\n  \n  processed = 9;\n  return value;\n}\n\nUInt64 CInByte2::ReadNumber()\n{\n  size_t processed;\n  const UInt64 res = ReadNumberSpec(_buffer + _pos, _size - _pos, processed);\n  if (processed == 0)\n    ThrowEndOfData();\n  _pos += processed;\n  return res;\n}\n\nCNum CInByte2::ReadNum()\n{\n  /*\n  if (_pos < _size)\n  {\n    Byte val = _buffer[_pos];\n    if ((unsigned)val < 0x80)\n    {\n      _pos++;\n      return (unsigned)val;\n    }\n  }\n  */\n  const UInt64 value = ReadNumber();\n  if (value > kNumMax)\n    ThrowUnsupported();\n  return (CNum)value;\n}\n\nUInt32 CInByte2::ReadUInt32()\n{\n  if (_pos + 4 > _size)\n    ThrowEndOfData();\n  const UInt32 res = Get32(_buffer + _pos);\n  _pos += 4;\n  return res;\n}\n\nUInt64 CInByte2::ReadUInt64()\n{\n  if (_pos + 8 > _size)\n    ThrowEndOfData();\n  const UInt64 res = Get64(_buffer + _pos);\n  _pos += 8;\n  return res;\n}\n\n#define Y0  '7'\n#define Y1  'z'\n#define Y2  0xBC\n#define Y3  0xAF\n#define Y4  0x27\n#define Y5  0x1C\n\n#define IS_SIGNATURE(p)( \\\n        (p)[2] == Y2 &&  \\\n        (p)[3] == Y3 &&  \\\n        (p)[5] == Y5 &&  \\\n        (p)[4] == Y4 &&  \\\n        (p)[1] == Y1 &&  \\\n        (p)[0] == Y0)\n\n/* FindSignature_10() is allowed to access data up to and including &limit[9].\n   limit[10] access is not allowed.\n  return:\n    (return_ptr <  limit) : signature was found at (return_ptr)\n    (return_ptr >= limit) : limit was reached or crossed. So no signature found before limit\n*/\nZ7_NO_INLINE\nstatic const Byte *FindSignature_10(const Byte *p, const Byte *limit)\n{\n  for (;;)\n  {\n    for (;;)\n    {\n      if (p >= limit)\n        return limit;\n      const Byte b = p[5];\n      p += 6;\n      if (b == Y0) {         break; }\n      if (b == Y1) { p -= 1; break; }\n      if (b == Y2) { p -= 2; break; }\n      if (b == Y3) { p -= 3; break; }\n      if (b == Y4) { p -= 4; break; }\n      if (b == Y5) { p -= 5; break; }\n    }\n    if (IS_SIGNATURE(p - 1))\n      return p - 1;\n  }\n}\n\n\nstatic inline bool TestStartCrc(const Byte *p)\n{\n  return CrcCalc(p + 12, 20) == Get32(p + 8);\n}\n\nstatic inline bool TestSignature2(const Byte *p)\n{\n  if (!IS_SIGNATURE(p))\n    return false;\n #ifdef FORMAT_7Z_RECOVERY\n  if (TestStartCrc(p))\n    return true;\n  for (unsigned i = 8; i < kHeaderSize; i++)\n    if (p[i] != 0)\n      return false;\n  return (p[6] != 0 || p[7] != 0);\n #else\n  return TestStartCrc(p);\n #endif\n}\n\n\nHRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\n{\n  RINOK(ReadStream_FALSE(stream, _header, kHeaderSize))\n\n  if (TestSignature2(_header))\n    return S_OK;\n  if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)\n    return S_FALSE;\n\n  const UInt32 kBufSize = (1 << 15) + kHeaderSize;  // must be > (kHeaderSize * 2)\n  CAlignedBuffer1 buf(kBufSize);\n  memcpy(buf, _header, kHeaderSize);\n  UInt64 offset = 0;\n  \n  for (;;)\n  {\n    UInt32 readSize =\n        (offset == 0) ?\n          kBufSize - kHeaderSize - kHeaderSize :\n          kBufSize - kHeaderSize;\n    if (searchHeaderSizeLimit)\n    {\n      const UInt64 rem = *searchHeaderSizeLimit - offset;\n      if (readSize > rem)\n        readSize = (UInt32)rem;\n      if (readSize == 0)\n        return S_FALSE;\n    }\n    \n    UInt32 processed = 0;\n    RINOK(stream->Read(buf + kHeaderSize, readSize, &processed))\n    if (processed == 0)\n      return S_FALSE;\n\n    /* &buf[0] was already tested for signature before.\n       So first search here will be for &buf[1] */\n    \n    for (UInt32 pos = 0;;)\n    {\n      const Byte *p = buf + pos + 1;\n      const Byte *lim = buf + processed + 1;\n      /* we have (kHeaderSize - 1 = 31) filled bytes starting from (lim),\n         and it's safe to access just 10 bytes in that reserved area */\n      p = FindSignature_10(p, lim);\n      if (p >= lim)\n        break;\n      pos = (UInt32)(p - buf);\n      if (TestStartCrc(p))\n      {\n        memcpy(_header, p, kHeaderSize);\n        _arhiveBeginStreamPosition += offset + pos;\n        return InStream_SeekSet(stream, _arhiveBeginStreamPosition + kHeaderSize);\n      }\n    }\n    \n    offset += processed;\n    memmove(buf, buf + processed, kHeaderSize);\n  }\n}\n\n// S_FALSE means that file is not archive\nHRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\n{\n  HeadersSize = 0;\n  Close();\n  RINOK(InStream_GetPos_GetSize(stream, _arhiveBeginStreamPosition, _fileEndPosition))\n  RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit))\n  _stream = stream;\n  return S_OK;\n}\n  \nvoid CInArchive::Close()\n{\n  _numInByteBufs = 0;\n  _stream.Release();\n  ThereIsHeaderError = false;\n}\n\nvoid CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)\n{\n  for (;;)\n  {\n    if (ReadID() == NID::kEnd)\n      break;\n    SkipData();\n  }\n}\n\n// CFolder &folder can be non empty. So we must set all fields\n\nvoid CInByte2::ParseFolder(CFolder &folder)\n{\n  const UInt32 numCoders = ReadNum();\n\n  if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)\n    ThrowUnsupported();\n\n  folder.Coders.SetSize(numCoders);\n\n  UInt32 numInStreams = 0;\n  UInt32 i;\n  for (i = 0; i < numCoders; i++)\n  {\n    CCoderInfo &coder = folder.Coders[i];\n    {\n      const Byte mainByte = ReadByte();\n      if ((mainByte & 0xC0) != 0)\n        ThrowUnsupported();\n      const unsigned idSize = (mainByte & 0xF);\n      if (idSize > 8 || idSize > GetRem())\n        ThrowUnsupported();\n      const Byte *longID = GetPtr();\n      UInt64 id = 0;\n      for (unsigned j = 0; j < idSize; j++)\n        id = ((id << 8) | longID[j]);\n      SkipDataNoCheck(idSize);\n      coder.MethodID = id;\n\n      if ((mainByte & 0x10) != 0)\n      {\n        coder.NumStreams = ReadNum();\n        // if (coder.NumStreams > k_Scan_NumCodersStreams_in_Folder_MAX) ThrowUnsupported();\n        /* numOutStreams = */ ReadNum();\n        // if (ReadNum() != 1) // numOutStreams ThrowUnsupported();\n      }\n      else\n      {\n        coder.NumStreams = 1;\n      }\n      \n      if ((mainByte & 0x20) != 0)\n      {\n        const CNum propsSize = ReadNum();\n        coder.Props.Alloc((size_t)propsSize);\n        ReadBytes((Byte *)coder.Props, (size_t)propsSize);\n      }\n      else\n        coder.Props.Free();\n    }\n    numInStreams += coder.NumStreams;\n  }\n\n  const UInt32 numBonds = numCoders - 1;\n  folder.Bonds.SetSize(numBonds);\n  for (i = 0; i < numBonds; i++)\n  {\n    CBond &bp = folder.Bonds[i];\n    bp.PackIndex = ReadNum();\n    bp.UnpackIndex = ReadNum();\n  }\n\n  if (numInStreams < numBonds)\n    ThrowUnsupported();\n  const UInt32 numPackStreams = numInStreams - numBonds;\n  folder.PackStreams.SetSize(numPackStreams);\n  \n  if (numPackStreams == 1)\n  {\n    for (i = 0; i < numInStreams; i++)\n      if (folder.FindBond_for_PackStream(i) < 0)\n      {\n        folder.PackStreams[0] = i;\n        break;\n      }\n    if (i == numInStreams)\n      ThrowUnsupported();\n  }\n  else\n    for (i = 0; i < numPackStreams; i++)\n      folder.PackStreams[i] = ReadNum();\n}\n\nvoid CFolders::ParseFolderInfo(unsigned folderIndex, CFolder &folder) const\n{\n  const size_t startPos = FoCodersDataOffset[folderIndex];\n  CInByte2 inByte;\n  inByte.Init(CodersData.ConstData() + startPos, FoCodersDataOffset[folderIndex + 1] - startPos);\n  inByte.ParseFolder(folder);\n  if (inByte.GetRem() != 0)\n    throw 20120424;\n}\n\n\nvoid CDatabase::GetPath(unsigned index, UString &path) const\n{\n  path.Empty();\n  if (!NameOffsets || !NamesBuf)\n    return;\n\n  const size_t offset = NameOffsets[index];\n  const size_t size = NameOffsets[index + 1] - offset;\n\n  if (size >= (1 << 28))\n    return;\n\n  wchar_t *s = path.GetBuf((unsigned)size - 1);\n\n  const Byte *p = ((const Byte *)NamesBuf + offset * 2);\n\n  #if defined(_WIN32) && defined(MY_CPU_LE)\n  \n  wmemcpy(s, (const wchar_t *)(const void *)p, size);\n  \n  #else\n\n  for (size_t i = 0; i < size; i++)\n  {\n    *s = Get16(p);\n    p += 2;\n    s++;\n  }\n\n  #endif\n\n  path.ReleaseBuf_SetLen((unsigned)size - 1);\n}\n\nHRESULT CDatabase::GetPath_Prop(unsigned index, PROPVARIANT *path) const throw()\n{\n  PropVariant_Clear(path);\n  if (!NameOffsets || !NamesBuf)\n    return S_OK;\n\n  const size_t offset = NameOffsets[index];\n  const size_t size = NameOffsets[index + 1] - offset;\n\n  if (size >= (1 << 14))\n    return S_OK;\n\n  // (size) includes null terminator\n\n  /*\n  #if WCHAR_MAX > 0xffff\n  \n  const Byte *p = ((const Byte *)NamesBuf + offset * 2);\n  size = Utf16LE__Get_Num_WCHARs(p, size - 1);\n  // (size) doesn't include null terminator\n  RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size));\n  wchar_t *s = path->bstrVal;\n  wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, size, s);\n  *sEnd = 0;\n  if (s + size != sEnd) return E_FAIL;\n\n  #else\n  */\n\n  RINOK(PropVarEm_Alloc_Bstr(path, (unsigned)size - 1))\n  wchar_t *s = path->bstrVal;\n  const Byte *p = ((const Byte *)NamesBuf + offset * 2);\n  // Utf16LE__To_WCHARs_Sep(p, size, s);\n\n  for (size_t i = 0; i < size; i++)\n  {\n    wchar_t c = Get16(p);\n    p += 2;\n    #if WCHAR_PATH_SEPARATOR != L'/'\n    if (c == L'/')\n      c = WCHAR_PATH_SEPARATOR;\n    else if (c == L'\\\\')\n      c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme\n    #endif\n    *s++ = c;\n  }\n\n  // #endif\n\n  return S_OK;\n\n  /*\n  unsigned cur = index;\n  unsigned size = 0;\n  \n  for (int i = 0;; i++)\n  {\n    size_t len = NameOffsets[cur + 1] - NameOffsets[cur];\n    size += (unsigned)len;\n    if (i > 256 || len > (1 << 14) || size > (1 << 14))\n      return PropVarEm_Set_Str(path, \"[TOO-LONG]\");\n    cur = Files[cur].Parent;\n    if (cur < 0)\n      break;\n  }\n  size--;\n\n  RINOK(PropVarEm_Alloc_Bstr(path, size));\n  wchar_t *s = path->bstrVal;\n  s += size;\n  *s = 0;\n  cur = index;\n  \n  for (;;)\n  {\n    unsigned len = (unsigned)(NameOffsets[cur + 1] - NameOffsets[cur] - 1);\n    const Byte *p = (const Byte *)NamesBuf + (NameOffsets[cur + 1] * 2) - 2;\n    for (; len != 0; len--)\n    {\n      p -= 2;\n      --s;\n      wchar_t c = Get16(p);\n      if (c == '/')\n        c = WCHAR_PATH_SEPARATOR;\n      *s = c;\n    }\n\n    const CFileItem &file = Files[cur];\n    cur = file.Parent;\n    if (cur < 0)\n      return S_OK;\n    *(--s) = (file.IsAltStream ? ':' : WCHAR_PATH_SEPARATOR);\n  }\n  */\n}\n\nvoid CInArchive::WaitId(UInt64 id)\n{\n  for (;;)\n  {\n    const UInt64 type = ReadID();\n    if (type == id)\n      return;\n    if (type == NID::kEnd)\n      ThrowIncorrect();\n    SkipData();\n  }\n}\n\n\nvoid CInArchive::Read_UInt32_Vector(CUInt32DefVector &v)\n{\n  const unsigned numItems = v.Defs.Size();\n  v.Vals.ClearAndSetSize(numItems);\n  UInt32 *p = &v.Vals[0];\n  const bool *defs = &v.Defs[0];\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    UInt32 a = 0;\n    if (defs[i])\n      a = ReadUInt32();\n    p[i] = a;\n  }\n}\n\n\nvoid CInArchive::ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs)\n{\n  ReadBoolVector2(numItems, crcs.Defs);\n  Read_UInt32_Vector(crcs);\n}\n\n\nvoid CInArchive::ReadPackInfo(CFolders &f)\n{\n  const CNum numPackStreams = ReadNum();\n  \n  WaitId(NID::kSize);\n  f.PackPositions.Alloc(numPackStreams + 1);\n  f.NumPackStreams = numPackStreams;\n  UInt64 sum = 0;\n  for (CNum i = 0; i < numPackStreams; i++)\n  {\n    f.PackPositions[i] = sum;\n    const UInt64 packSize = ReadNumber();\n    sum += packSize;\n    if (sum < packSize)\n      ThrowIncorrect();\n  }\n  f.PackPositions[numPackStreams] = sum;\n\n  UInt64 type;\n  for (;;)\n  {\n    type = ReadID();\n    if (type == NID::kEnd)\n      return;\n    if (type == NID::kCRC)\n    {\n      CUInt32DefVector PackCRCs;\n      ReadHashDigests(numPackStreams, PackCRCs);\n      continue;\n    }\n    SkipData();\n  }\n}\n\nvoid CInArchive::ReadUnpackInfo(\n    const CObjectVector<CByteBuffer> *dataVector,\n    CFolders &folders)\n{\n  WaitId(NID::kFolder);\n  const CNum numFolders = ReadNum();\n\n  CNum numCodersOutStreams = 0;\n  {\n    CStreamSwitch streamSwitch;\n    streamSwitch.Set(this, dataVector);\n    const Byte *startBufPtr = _inByteBack->GetPtr();\n    folders.NumFolders = numFolders;\n\n    folders.FoStartPackStreamIndex.Alloc(numFolders + 1);\n    folders.FoToMainUnpackSizeIndex.Alloc(numFolders);\n    folders.FoCodersDataOffset.Alloc(numFolders + 1);\n    folders.FoToCoderUnpackSizes.Alloc(numFolders + 1);\n\n    CBoolVector StreamUsed;\n    CBoolVector CoderUsed;\n\n    CNum packStreamIndex = 0;\n    CNum fo;\n    CInByte2 *inByte = _inByteBack;\n    \n    for (fo = 0; fo < numFolders; fo++)\n    {\n      UInt32 indexOfMainStream = 0;\n      UInt32 numPackStreams = 0;\n      folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);\n\n      CNum numInStreams = 0;\n      const CNum numCoders = inByte->ReadNum();\n    \n      if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)\n        ThrowUnsupported();\n\n      for (CNum ci = 0; ci < numCoders; ci++)\n      {\n        const Byte mainByte = inByte->ReadByte();\n        if ((mainByte & 0xC0) != 0)\n          ThrowUnsupported();\n        \n        const unsigned idSize = (mainByte & 0xF);\n        if (idSize > 8)\n          ThrowUnsupported();\n        if (idSize > inByte->GetRem())\n          ThrowEndOfData();\n        const Byte *longID = inByte->GetPtr();\n        UInt64 id = 0;\n        for (unsigned j = 0; j < idSize; j++)\n          id = ((id << 8) | longID[j]);\n        inByte->SkipDataNoCheck(idSize);\n        if (folders.ParsedMethods.IDs.Size() < 128)\n          folders.ParsedMethods.IDs.AddToUniqueSorted(id);\n        \n        CNum coderInStreams = 1;\n        if ((mainByte & 0x10) != 0)\n        {\n          coderInStreams = inByte->ReadNum();\n          if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)\n            ThrowUnsupported();\n          if (inByte->ReadNum() != 1)\n            ThrowUnsupported();\n        }\n\n        numInStreams += coderInStreams;\n        if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)\n          ThrowUnsupported();\n        \n        if ((mainByte & 0x20) != 0)\n        {\n          const CNum propsSize = inByte->ReadNum();\n          if (propsSize > inByte->GetRem())\n            ThrowEndOfData();\n          if (id == k_LZMA2 && propsSize == 1)\n          {\n            const Byte v = *_inByteBack->GetPtr();\n            if (folders.ParsedMethods.Lzma2Prop < v)\n              folders.ParsedMethods.Lzma2Prop = v;\n          }\n          else if (id == k_LZMA && propsSize == 5)\n          {\n            const UInt32 dicSize = GetUi32(_inByteBack->GetPtr() + 1);\n            if (folders.ParsedMethods.LzmaDic < dicSize)\n              folders.ParsedMethods.LzmaDic = dicSize;\n          }\n          inByte->SkipDataNoCheck((size_t)propsSize);\n        }\n      }\n      \n      if (numCoders == 1 && numInStreams == 1)\n      {\n        indexOfMainStream = 0;\n        numPackStreams = 1;\n      }\n      else\n      {\n        UInt32 i;\n        const CNum numBonds = numCoders - 1;\n        if (numInStreams < numBonds)\n          ThrowUnsupported();\n        \n        BoolVector_Fill_False(StreamUsed, numInStreams);\n        BoolVector_Fill_False(CoderUsed, numCoders);\n        \n        for (i = 0; i < numBonds; i++)\n        {\n          CNum index = ReadNum();\n          if (index >= numInStreams || StreamUsed[index])\n            ThrowUnsupported();\n          StreamUsed[index] = true;\n          \n          index = ReadNum();\n          if (index >= numCoders || CoderUsed[index])\n            ThrowUnsupported();\n          CoderUsed[index] = true;\n        }\n        \n        numPackStreams = numInStreams - numBonds;\n        \n        if (numPackStreams != 1)\n          for (i = 0; i < numPackStreams; i++)\n          {\n            const CNum index = inByte->ReadNum(); // PackStreams\n            if (index >= numInStreams || StreamUsed[index])\n              ThrowUnsupported();\n            StreamUsed[index] = true;\n          }\n          \n        for (i = 0; i < numCoders; i++)\n          if (!CoderUsed[i])\n          {\n            indexOfMainStream = i;\n            break;\n          }\n          \n        if (i == numCoders)\n          ThrowUnsupported();\n      }\n      \n      folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;\n      numCodersOutStreams += numCoders;\n      folders.FoStartPackStreamIndex[fo] = packStreamIndex;\n      if (numPackStreams > folders.NumPackStreams - packStreamIndex)\n        ThrowIncorrect();\n      packStreamIndex += numPackStreams;\n      folders.FoToMainUnpackSizeIndex[fo] = (Byte)indexOfMainStream;\n    }\n    \n    const size_t dataSize = (size_t)(_inByteBack->GetPtr() - startBufPtr);\n    folders.FoToCoderUnpackSizes[fo] = numCodersOutStreams;\n    folders.FoStartPackStreamIndex[fo] = packStreamIndex;\n    folders.FoCodersDataOffset[fo] = (size_t)(_inByteBack->GetPtr() - startBufPtr);\n    folders.CodersData.CopyFrom(startBufPtr, dataSize);\n\n    // if (folders.NumPackStreams != packStreamIndex) ThrowUnsupported();\n  }\n\n  WaitId(NID::kCodersUnpackSize);\n  folders.CoderUnpackSizes.Alloc(numCodersOutStreams);\n  for (CNum i = 0; i < numCodersOutStreams; i++)\n    folders.CoderUnpackSizes[i] = ReadNumber();\n\n  for (;;)\n  {\n    const UInt64 type = ReadID();\n    if (type == NID::kEnd)\n      return;\n    if (type == NID::kCRC)\n    {\n      ReadHashDigests(numFolders, folders.FolderCRCs);\n      continue;\n    }\n    SkipData();\n  }\n}\n\nvoid CInArchive::ReadSubStreamsInfo(\n    CFolders &folders,\n    CRecordVector<UInt64> &unpackSizes,\n    CUInt32DefVector &digests)\n{\n  folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);\n  CNum i;\n  for (i = 0; i < folders.NumFolders; i++)\n    folders.NumUnpackStreamsVector[i] = 1;\n  \n  UInt64 type;\n  \n  for (;;)\n  {\n    type = ReadID();\n    if (type == NID::kNumUnpackStream)\n    {\n      for (i = 0; i < folders.NumFolders; i++)\n        folders.NumUnpackStreamsVector[i] = ReadNum();\n      continue;\n    }\n    if (type == NID::kCRC || type == NID::kSize || type == NID::kEnd)\n      break;\n    SkipData();\n  }\n\n  if (type == NID::kSize)\n  {\n    for (i = 0; i < folders.NumFolders; i++)\n    {\n      // v3.13 incorrectly worked with empty folders\n      // v4.07: we check that folder is empty\n      const CNum numSubstreams = folders.NumUnpackStreamsVector[i];\n      if (numSubstreams == 0)\n        continue;\n      UInt64 sum = 0;\n      for (CNum j = 1; j < numSubstreams; j++)\n      {\n        const UInt64 size = ReadNumber();\n        unpackSizes.Add(size);\n        sum += size;\n        if (sum < size)\n          ThrowIncorrect();\n      }\n      const UInt64 folderUnpackSize = folders.GetFolderUnpackSize(i);\n      if (folderUnpackSize < sum)\n        ThrowIncorrect();\n      unpackSizes.Add(folderUnpackSize - sum);\n    }\n    type = ReadID();\n  }\n  else\n  {\n    for (i = 0; i < folders.NumFolders; i++)\n    {\n      /* v9.26 - v9.29 incorrectly worked:\n         if (folders.NumUnpackStreamsVector[i] == 0), it threw error */\n      const CNum val = folders.NumUnpackStreamsVector[i];\n      if (val > 1)\n        ThrowIncorrect();\n      if (val == 1)\n        unpackSizes.Add(folders.GetFolderUnpackSize(i));\n    }\n  }\n\n  unsigned numDigests = 0;\n  for (i = 0; i < folders.NumFolders; i++)\n  {\n    const CNum numSubstreams = folders.NumUnpackStreamsVector[i];\n    if (numSubstreams != 1 || !folders.FolderCRCs.ValidAndDefined(i))\n      numDigests += numSubstreams;\n  }\n\n  for (;;)\n  {\n    if (type == NID::kEnd)\n      break;\n    if (type == NID::kCRC)\n    {\n      // CUInt32DefVector digests2;\n      // ReadHashDigests(numDigests, digests2);\n      CBoolVector digests2;\n      ReadBoolVector2(numDigests, digests2);\n\n      digests.ClearAndSetSize(unpackSizes.Size());\n      \n      unsigned k = 0;\n      unsigned k2 = 0;\n      \n      for (i = 0; i < folders.NumFolders; i++)\n      {\n        const CNum numSubstreams = folders.NumUnpackStreamsVector[i];\n        if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))\n        {\n          digests.Defs[k] = true;\n          digests.Vals[k] = folders.FolderCRCs.Vals[i];\n          k++;\n        }\n        else for (CNum j = 0; j < numSubstreams; j++)\n        {\n          bool defined = digests2[k2++];\n          digests.Defs[k] = defined;\n          UInt32 crc = 0;\n          if (defined)\n            crc = ReadUInt32();\n          digests.Vals[k] = crc;\n          k++;\n        }\n      }\n      // if (k != unpackSizes.Size()) throw 1234567;\n    }\n    else\n      SkipData();\n    \n    type = ReadID();\n  }\n\n  if (digests.Defs.Size() != unpackSizes.Size())\n  {\n    digests.ClearAndSetSize(unpackSizes.Size());\n    unsigned k = 0;\n    for (i = 0; i < folders.NumFolders; i++)\n    {\n      const CNum numSubstreams = folders.NumUnpackStreamsVector[i];\n      if (numSubstreams == 1 && folders.FolderCRCs.ValidAndDefined(i))\n      {\n        digests.Defs[k] = true;\n        digests.Vals[k] = folders.FolderCRCs.Vals[i];\n        k++;\n      }\n      else for (CNum j = 0; j < numSubstreams; j++)\n      {\n        digests.Defs[k] = false;\n        digests.Vals[k] = 0;\n        k++;\n      }\n    }\n  }\n}\n\n\n\nvoid CInArchive::ReadStreamsInfo(\n    const CObjectVector<CByteBuffer> *dataVector,\n    UInt64 &dataOffset,\n    CFolders &folders,\n    CRecordVector<UInt64> &unpackSizes,\n    CUInt32DefVector &digests)\n{\n  UInt64 type = ReadID();\n  \n  if (type == NID::kPackInfo)\n  {\n    dataOffset = ReadNumber();\n    if (dataOffset > _rangeLimit)\n      ThrowIncorrect();\n    ReadPackInfo(folders);\n    if (folders.PackPositions[folders.NumPackStreams] > _rangeLimit - dataOffset)\n      ThrowIncorrect();\n    type = ReadID();\n  }\n\n  if (type == NID::kUnpackInfo)\n  {\n    ReadUnpackInfo(dataVector, folders);\n    type = ReadID();\n  }\n\n  if (folders.NumFolders != 0 && !folders.PackPositions)\n  {\n    // if there are folders, we need PackPositions also\n    folders.PackPositions.Alloc(1);\n    folders.PackPositions[0] = 0;\n  }\n  \n  if (type == NID::kSubStreamsInfo)\n  {\n    ReadSubStreamsInfo(folders, unpackSizes, digests);\n    type = ReadID();\n  }\n  else\n  {\n    folders.NumUnpackStreamsVector.Alloc(folders.NumFolders);\n    /* If digests.Defs.Size() == 0, it means that there are no crcs.\n       So we don't need to fill digests with values. */\n    // digests.Vals.ClearAndSetSize(folders.NumFolders);\n    // BoolVector_Fill_False(digests.Defs, folders.NumFolders);\n    for (CNum i = 0; i < folders.NumFolders; i++)\n    {\n      folders.NumUnpackStreamsVector[i] = 1;\n      unpackSizes.Add(folders.GetFolderUnpackSize(i));\n      // digests.Vals[i] = 0;\n    }\n  }\n  \n  if (type != NID::kEnd)\n    ThrowIncorrect();\n}\n\nvoid CInArchive::ReadBoolVector(unsigned numItems, CBoolVector &v)\n{\n  v.ClearAndSetSize(numItems);\n  Byte b = 0;\n  Byte mask = 0;\n  bool *p = &v[0];\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    if (mask == 0)\n    {\n      b = ReadByte();\n      mask = 0x80;\n    }\n    p[i] = ((b & mask) != 0);\n    mask = (Byte)(mask >> 1);\n  }\n}\n\nvoid CInArchive::ReadBoolVector2(unsigned numItems, CBoolVector &v)\n{\n  const Byte allAreDefined = ReadByte();\n  if (allAreDefined == 0)\n  {\n    ReadBoolVector(numItems, v);\n    return;\n  }\n  v.ClearAndSetSize(numItems);\n  bool *p = &v[0];\n  for (unsigned i = 0; i < numItems; i++)\n    p[i] = true;\n}\n\nvoid CInArchive::ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,\n    CUInt64DefVector &v, unsigned numItems)\n{\n  ReadBoolVector2(numItems, v.Defs);\n\n  CStreamSwitch streamSwitch;\n  streamSwitch.Set(this, &dataVector);\n  \n  v.Vals.ClearAndSetSize(numItems);\n  UInt64 *p = &v.Vals[0];\n  const bool *defs = &v.Defs[0];\n\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    UInt64 t = 0;\n    if (defs[i])\n      t = ReadUInt64();\n    p[i] = t;\n  }\n}\n\nHRESULT CInArchive::ReadAndDecodePackedStreams(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    UInt64 baseOffset,\n    UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector\n    Z7_7Z_DECODER_CRYPRO_VARS_DECL\n    )\n{\n  CFolders folders;\n  CRecordVector<UInt64> unpackSizes;\n  CUInt32DefVector  digests;\n  \n  ReadStreamsInfo(NULL,\n    dataOffset,\n    folders,\n    unpackSizes,\n    digests);\n  \n  CDecoder decoder(_useMixerMT);\n\n  for (CNum i = 0; i < folders.NumFolders; i++)\n  {\n    CByteBuffer &data = dataVector.AddNew();\n    const UInt64 unpackSize64 = folders.GetFolderUnpackSize(i);\n    const size_t unpackSize = (size_t)unpackSize64;\n    if (unpackSize != unpackSize64)\n      ThrowUnsupported();\n    data.Alloc(unpackSize);\n    \n    CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamSpec;\n    outStreamSpec->Init(data, unpackSize);\n    \n    bool dataAfterEnd_Error = false;\n\n    HRESULT result = decoder.Decode(\n        EXTERNAL_CODECS_LOC_VARS\n        _stream, baseOffset + dataOffset,\n        folders, i,\n        NULL, // &unpackSize64\n        \n        outStreamSpec,\n        NULL, // *compressProgress\n\n        NULL  // **inStreamMainRes\n        , dataAfterEnd_Error\n        \n        Z7_7Z_DECODER_CRYPRO_VARS\n        #if !defined(Z7_ST)\n          , false // mtMode\n          , 1     // numThreads\n          , 0     // memUsage\n        #endif\n      );\n    \n    RINOK(result)\n    \n    if (dataAfterEnd_Error)\n      ThereIsHeaderError = true;\n    \n    if (unpackSize != outStreamSpec->GetPos())\n      ThrowIncorrect();\n\n    if (folders.FolderCRCs.ValidAndDefined(i))\n      if (CrcCalc(data, unpackSize) != folders.FolderCRCs.Vals[i])\n        ThrowIncorrect();\n  }\n\n  if (folders.PackPositions)\n    HeadersSize += folders.PackPositions[folders.NumPackStreams];\n\n  return S_OK;\n}\n\nHRESULT CInArchive::ReadHeader(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CDbEx &db\n    Z7_7Z_DECODER_CRYPRO_VARS_DECL\n    )\n{\n  UInt64 type = ReadID();\n\n  if (type == NID::kArchiveProperties)\n  {\n    ReadArchiveProperties(db.ArcInfo);\n    type = ReadID();\n  }\n \n  CObjectVector<CByteBuffer> dataVector;\n  \n  if (type == NID::kAdditionalStreamsInfo)\n  {\n    const HRESULT result = ReadAndDecodePackedStreams(\n        EXTERNAL_CODECS_LOC_VARS\n        db.ArcInfo.StartPositionAfterHeader,\n        db.ArcInfo.DataStartPosition2,\n        dataVector\n        Z7_7Z_DECODER_CRYPRO_VARS\n        );\n    RINOK(result)\n    db.ArcInfo.DataStartPosition2 += db.ArcInfo.StartPositionAfterHeader;\n    type = ReadID();\n  }\n\n  CRecordVector<UInt64> unpackSizes;\n  CUInt32DefVector digests;\n  \n  if (type == NID::kMainStreamsInfo)\n  {\n    ReadStreamsInfo(&dataVector,\n        db.ArcInfo.DataStartPosition,\n        (CFolders &)db,\n        unpackSizes,\n        digests);\n    db.ArcInfo.DataStartPosition += db.ArcInfo.StartPositionAfterHeader;\n    type = ReadID();\n  }\n\n  if (type == NID::kFilesInfo)\n  {\n  \n  const CNum numFiles = ReadNum();\n\n  db.ArcInfo.FileInfoPopIDs.Add(NID::kSize);\n  // if (!db.PackSizes.IsEmpty())\n    db.ArcInfo.FileInfoPopIDs.Add(NID::kPackInfo);\n  if (numFiles > 0 && !digests.Defs.IsEmpty())\n    db.ArcInfo.FileInfoPopIDs.Add(NID::kCRC);\n\n  CBoolVector emptyStreamVector;\n  CBoolVector emptyFileVector;\n  CBoolVector antiFileVector;\n  unsigned numEmptyStreams = 0;\n\n  for (;;)\n  {\n    const UInt64 type2 = ReadID();\n    if (type2 == NID::kEnd)\n      break;\n    const UInt64 size = ReadNumber();\n    if (size > _inByteBack->GetRem())\n      ThrowIncorrect();\n    CStreamSwitch switchProp;\n    switchProp.Set(this, _inByteBack->GetPtr(), (size_t)size, true);\n    bool addPropIdToList = true;\n    bool isKnownType = true;\n    if (type2 > ((UInt32)1 << 30))\n      isKnownType = false;\n    else switch ((UInt32)type2)\n    {\n      case NID::kName:\n      {\n        CStreamSwitch streamSwitch;\n        streamSwitch.Set(this, &dataVector);\n        const size_t rem = _inByteBack->GetRem();\n        db.NamesBuf.Alloc(rem);\n        ReadBytes(db.NamesBuf, rem);\n        db.NameOffsets.Alloc(numFiles + 1);\n        size_t pos = 0;\n        unsigned i;\n        for (i = 0; i < numFiles; i++)\n        {\n          const size_t curRem = (rem - pos) / 2;\n          const UInt16 *buf = (const UInt16 *)(const void *)(db.NamesBuf.ConstData() + pos);\n          size_t j;\n          for (j = 0; j < curRem && buf[j] != 0; j++);\n          if (j == curRem)\n            ThrowEndOfData();\n          db.NameOffsets[i] = pos / 2;\n          pos += j * 2 + 2;\n        }\n        db.NameOffsets[i] = pos / 2;\n        if (pos != rem)\n          ThereIsHeaderError = true;\n        break;\n      }\n\n      case NID::kWinAttrib:\n      {\n        ReadBoolVector2(numFiles, db.Attrib.Defs);\n        CStreamSwitch streamSwitch;\n        streamSwitch.Set(this, &dataVector);\n        Read_UInt32_Vector(db.Attrib);\n        break;\n      }\n      \n      /*\n      case NID::kIsAux:\n      {\n        ReadBoolVector(numFiles, db.IsAux);\n        break;\n      }\n      case NID::kParent:\n      {\n        db.IsTree = true;\n        // CBoolVector boolVector;\n        // ReadBoolVector2(numFiles, boolVector);\n        // CStreamSwitch streamSwitch;\n        // streamSwitch.Set(this, &dataVector);\n        CBoolVector boolVector;\n        ReadBoolVector2(numFiles, boolVector);\n\n        db.ThereAreAltStreams = false;\n        for (i = 0; i < numFiles; i++)\n        {\n          CFileItem &file = db.Files[i];\n          // file.Parent = -1;\n          // if (boolVector[i])\n          file.Parent = (int)ReadUInt32();\n          file.IsAltStream = !boolVector[i];\n          if (file.IsAltStream)\n            db.ThereAreAltStreams = true;\n        }\n        break;\n      }\n      */\n      case NID::kEmptyStream:\n      {\n        ReadBoolVector(numFiles, emptyStreamVector);\n        numEmptyStreams = BoolVector_CountSum(emptyStreamVector);\n        emptyFileVector.Clear();\n        antiFileVector.Clear();\n        break;\n      }\n      case NID::kEmptyFile:  ReadBoolVector(numEmptyStreams, emptyFileVector); break;\n      case NID::kAnti:  ReadBoolVector(numEmptyStreams, antiFileVector); break;\n      case NID::kStartPos:  ReadUInt64DefVector(dataVector, db.StartPos, (unsigned)numFiles); break;\n      case NID::kCTime:  ReadUInt64DefVector(dataVector, db.CTime, (unsigned)numFiles); break;\n      case NID::kATime:  ReadUInt64DefVector(dataVector, db.ATime, (unsigned)numFiles); break;\n      case NID::kMTime:  ReadUInt64DefVector(dataVector, db.MTime, (unsigned)numFiles); break;\n      case NID::kDummy:\n      {\n        for (UInt64 j = 0; j < size; j++)\n          if (ReadByte() != 0)\n            ThereIsHeaderError = true;\n        addPropIdToList = false;\n        break;\n      }\n      /*\n      case NID::kNtSecure:\n      {\n        try\n        {\n          {\n            CStreamSwitch streamSwitch;\n            streamSwitch.Set(this, &dataVector);\n            UInt32 numDescriptors = ReadUInt32();\n            size_t offset = 0;\n            db.SecureOffsets.Clear();\n            for (i = 0; i < numDescriptors; i++)\n            {\n              UInt32 size = ReadUInt32();\n              db.SecureOffsets.Add(offset);\n              offset += size;\n            }\n            // ThrowIncorrect();;\n            db.SecureOffsets.Add(offset);\n            db.SecureBuf.SetCapacity(offset);\n            for (i = 0; i < numDescriptors; i++)\n            {\n              offset = db.SecureOffsets[i];\n              ReadBytes(db.SecureBuf + offset, db.SecureOffsets[i + 1] - offset);\n            }\n            db.SecureIDs.Clear();\n            for (unsigned i = 0; i < numFiles; i++)\n            {\n              db.SecureIDs.Add(ReadNum());\n              // db.SecureIDs.Add(ReadUInt32());\n            }\n            // ReadUInt32();\n            if (_inByteBack->GetRem() != 0)\n              ThrowIncorrect();;\n          }\n        }\n        catch(CInArchiveException &)\n        {\n          ThereIsHeaderError = true;\n          addPropIdToList = isKnownType = false;\n          db.ClearSecure();\n        }\n        break;\n      }\n      */\n      default:\n        addPropIdToList = isKnownType = false;\n    }\n    if (isKnownType)\n    {\n      if (addPropIdToList)\n        db.ArcInfo.FileInfoPopIDs.Add(type2);\n    }\n    else\n    {\n      db.UnsupportedFeatureWarning = true;\n      _inByteBack->SkipRem();\n    }\n    // SkipData worked incorrectly in some versions before v4.59 (7zVer <= 0.02)\n    if (_inByteBack->GetRem() != 0)\n      ThrowIncorrect();\n  }\n\n  type = ReadID(); // Read (NID::kEnd) end of headers\n\n  if (numFiles - numEmptyStreams != unpackSizes.Size())\n    ThrowUnsupported();\n\n  CNum emptyFileIndex = 0;\n  CNum sizeIndex = 0;\n\n  const unsigned numAntiItems = BoolVector_CountSum(antiFileVector);\n\n  if (numAntiItems != 0)\n    db.IsAnti.ClearAndSetSize(numFiles);\n\n  db.Files.ClearAndSetSize(numFiles);\n\n  for (CNum i = 0; i < numFiles; i++)\n  {\n    CFileItem &file = db.Files[i];\n    bool isAnti;\n    file.Crc = 0;\n    if (!BoolVector_Item_IsValidAndTrue(emptyStreamVector, i))\n    {\n      file.HasStream = true;\n      file.IsDir = false;\n      isAnti = false;\n      file.Size = unpackSizes[sizeIndex];\n      file.CrcDefined = digests.ValidAndDefined(sizeIndex);\n      if (file.CrcDefined)\n        file.Crc = digests.Vals[sizeIndex];\n      sizeIndex++;\n    }\n    else\n    {\n      file.HasStream = false;\n      file.IsDir = !BoolVector_Item_IsValidAndTrue(emptyFileVector, emptyFileIndex);\n      isAnti = BoolVector_Item_IsValidAndTrue(antiFileVector, emptyFileIndex);\n      emptyFileIndex++;\n      file.Size = 0;\n      file.CrcDefined = false;\n    }\n    if (numAntiItems != 0)\n      db.IsAnti[i] = isAnti;\n  }\n  \n  }\n  \n  db.FillLinks();\n\n  if (type != NID::kEnd || _inByteBack->GetRem() != 0)\n  {\n    db.UnsupportedFeatureWarning = true;\n    // ThrowIncorrect();\n  }\n\n  return S_OK;\n}\n\n\nvoid CDbEx::FillLinks()\n{\n  FolderStartFileIndex.Alloc(NumFolders);\n  FileIndexToFolderIndexMap.Alloc(Files.Size());\n  \n  CNum folderIndex = 0;\n  CNum indexInFolder = 0;\n  unsigned i;\n\n  for (i = 0; i < Files.Size(); i++)\n  {\n    const bool emptyStream = !Files[i].HasStream;\n    if (indexInFolder == 0)\n    {\n      if (emptyStream)\n      {\n        FileIndexToFolderIndexMap[i] = kNumNoIndex;\n        continue;\n      }\n      // v3.13 incorrectly worked with empty folders\n      // v4.07: we skip empty folders\n      for (;;)\n      {\n        if (folderIndex >= NumFolders)\n          ThrowIncorrect();\n        FolderStartFileIndex[folderIndex] = i;\n        if (NumUnpackStreamsVector[folderIndex] != 0)\n          break;\n        folderIndex++;\n      }\n    }\n    FileIndexToFolderIndexMap[i] = folderIndex;\n    if (emptyStream)\n      continue;\n    if (++indexInFolder >= NumUnpackStreamsVector[folderIndex])\n    {\n      folderIndex++;\n      indexInFolder = 0;\n    }\n  }\n\n  if (indexInFolder != 0)\n  {\n    folderIndex++;\n    // 18.06\n    ThereIsHeaderError = true;\n    // ThrowIncorrect();\n  }\n  \n  for (;;)\n  {\n    if (folderIndex >= NumFolders)\n      return;\n    FolderStartFileIndex[folderIndex] = i;\n    if (NumUnpackStreamsVector[folderIndex] != 0)\n    {\n      // 18.06\n      ThereIsHeaderError = true;\n      // ThrowIncorrect();\n    }\n    folderIndex++;\n  }\n}\n\n\nHRESULT CInArchive::ReadDatabase2(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CDbEx &db\n    Z7_7Z_DECODER_CRYPRO_VARS_DECL\n    )\n{\n  db.Clear();\n  db.ArcInfo.StartPosition = _arhiveBeginStreamPosition;\n\n  db.ArcInfo.Version.Major = _header[6];\n  db.ArcInfo.Version.Minor = _header[7];\n\n  if (db.ArcInfo.Version.Major != kMajorVersion)\n  {\n    // db.UnsupportedVersion = true;\n    return S_FALSE;\n  }\n\n  UInt64 nextHeaderOffset = Get64(_header + 12);\n  UInt64 nextHeaderSize = Get64(_header + 20);\n  UInt32 nextHeaderCRC = Get32(_header + 28);\n\n  #ifdef FORMAT_7Z_RECOVERY\n  const UInt32 crcFromArc = Get32(_header + 8);\n  if (crcFromArc == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)\n  {\n    UInt64 cur, fileSize;\n    RINOK(InStream_GetPos(_stream, cur))\n    const unsigned kCheckSize = 512;\n    Byte buf[kCheckSize];\n    RINOK(InStream_GetSize_SeekToEnd(_stream, fileSize))\n    const UInt64 rem = fileSize - cur;\n    unsigned checkSize = kCheckSize;\n    if (rem < kCheckSize)\n      checkSize = (unsigned)(rem);\n    if (checkSize < 3)\n      return S_FALSE;\n    RINOK(InStream_SeekSet(_stream, fileSize - checkSize))\n    RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize))\n\n    if (buf[checkSize - 1] != 0)\n      return S_FALSE;\n\n    unsigned i;\n    for (i = checkSize - 2;; i--)\n    {\n      if ((buf[i] == NID::kEncodedHeader && buf[i + 1] == NID::kPackInfo) ||\n          (buf[i] == NID::kHeader        && buf[i + 1] == NID::kMainStreamsInfo))\n        break;\n      if (i == 0)\n        return S_FALSE;\n    }\n    nextHeaderSize = checkSize - i;\n    nextHeaderOffset = rem - nextHeaderSize;\n    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);\n    RINOK(InStream_SeekSet(_stream, cur))\n    db.StartHeaderWasRecovered = true;\n  }\n  else\n  #endif\n  {\n    // Crc was tested already at signature check\n    // if (CrcCalc(_header + 12, 20) != crcFromArchive) ThrowIncorrect();\n  }\n\n  db.ArcInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;\n  db.PhySize = kHeaderSize;\n\n  db.IsArc = false;\n  if ((Int64)nextHeaderOffset < 0 ||\n      nextHeaderSize > ((UInt64)1 << 62))\n    return S_FALSE;\n\n  HeadersSize = kHeaderSize;\n\n  if (nextHeaderSize == 0)\n  {\n    if (nextHeaderOffset != 0 || nextHeaderCRC != 0)\n      return S_FALSE;\n    db.IsArc = true;\n    db.HeadersSize = HeadersSize;\n    return S_OK;\n  }\n  \n  if (!db.StartHeaderWasRecovered)\n    db.IsArc = true;\n  \n  HeadersSize += nextHeaderSize;\n  // db.EndHeaderOffset = nextHeaderOffset;\n  _rangeLimit = nextHeaderOffset;\n\n  db.PhySize = kHeaderSize + nextHeaderOffset + nextHeaderSize;\n  if (_fileEndPosition - db.ArcInfo.StartPositionAfterHeader < nextHeaderOffset + nextHeaderSize)\n  {\n    db.UnexpectedEnd = true;\n    return S_FALSE;\n  }\n  RINOK(_stream->Seek((Int64)nextHeaderOffset, STREAM_SEEK_CUR, NULL))\n\n  const size_t nextHeaderSize_t = (size_t)nextHeaderSize;\n  if (nextHeaderSize_t != nextHeaderSize)\n    return E_OUTOFMEMORY;\n  CByteBuffer buffer2(nextHeaderSize_t);\n\n  RINOK(ReadStream_FALSE(_stream, buffer2, nextHeaderSize_t))\n\n  if (CrcCalc(buffer2, nextHeaderSize_t) != nextHeaderCRC)\n    ThrowIncorrect();\n\n  if (!db.StartHeaderWasRecovered)\n    db.PhySizeWasConfirmed = true;\n  \n  CStreamSwitch streamSwitch;\n  streamSwitch.Set(this, buffer2);\n  \n  CObjectVector<CByteBuffer> dataVector;\n  \n  const UInt64 type = ReadID();\n  if (type != NID::kHeader)\n  {\n    if (type != NID::kEncodedHeader)\n      ThrowIncorrect();\n    const HRESULT result = ReadAndDecodePackedStreams(\n        EXTERNAL_CODECS_LOC_VARS\n        db.ArcInfo.StartPositionAfterHeader,\n        db.ArcInfo.DataStartPosition2,\n        dataVector\n        Z7_7Z_DECODER_CRYPRO_VARS\n        );\n    RINOK(result)\n    if (dataVector.Size() == 0)\n      return S_OK;\n    if (dataVector.Size() > 1)\n      ThrowIncorrect();\n    streamSwitch.Remove();\n    streamSwitch.Set(this, dataVector.Front());\n    if (ReadID() != NID::kHeader)\n      ThrowIncorrect();\n  }\n\n  db.IsArc = true;\n\n  db.HeadersSize = HeadersSize;\n\n  return ReadHeader(\n    EXTERNAL_CODECS_LOC_VARS\n    db\n    Z7_7Z_DECODER_CRYPRO_VARS\n    );\n}\n\n\nHRESULT CInArchive::ReadDatabase(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CDbEx &db\n    Z7_7Z_DECODER_CRYPRO_VARS_DECL\n    )\n{\n  try\n  {\n    const HRESULT res = ReadDatabase2(\n      EXTERNAL_CODECS_LOC_VARS db\n      Z7_7Z_DECODER_CRYPRO_VARS\n      );\n    if (ThereIsHeaderError)\n      db.ThereIsHeaderError = true;\n    if (res == E_NOTIMPL)\n      ThrowUnsupported();\n    return res;\n  }\n  catch(CUnsupportedFeatureException &)\n  {\n    db.UnsupportedFeatureError = true;\n    return S_FALSE;\n  }\n  catch(CInArchiveException &)\n  {\n    db.ThereIsHeaderError = true;\n    return S_FALSE;\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zIn.h",
    "content": "﻿// 7zIn.h\n\n#ifndef ZIP7_INC_7Z_IN_H\n#define ZIP7_INC_7Z_IN_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"../../IPassword.h\"\n#include \"../../IStream.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/InBuffer.h\"\n\n#include \"7zItem.h\"\n \nnamespace NArchive {\nnamespace N7z {\n\n/*\n  We don't need to init isEncrypted and passwordIsDefined\n  We must upgrade them only */\n\n#ifdef Z7_NO_CRYPTO\n#define Z7_7Z_DECODER_CRYPRO_VARS_DECL\n#define Z7_7Z_DECODER_CRYPRO_VARS\n#else\n#define Z7_7Z_DECODER_CRYPRO_VARS_DECL , ICryptoGetTextPassword *getTextPassword, bool &isEncrypted, bool &passwordIsDefined, UString &password\n#define Z7_7Z_DECODER_CRYPRO_VARS , getTextPassword, isEncrypted, passwordIsDefined, password\n#endif\n\nstruct CParsedMethods\n{\n  Byte Lzma2Prop;\n  UInt32 LzmaDic;\n  CRecordVector<UInt64> IDs;\n\n  CParsedMethods(): Lzma2Prop(0), LzmaDic(0) {}\n};\n\nstruct CFolderEx: public CFolder\n{\n  unsigned UnpackCoder;\n};\n\nstruct CFolders\n{\n  CNum NumPackStreams;\n  CNum NumFolders;\n\n  CObjArray<UInt64> PackPositions; // NumPackStreams + 1\n  // CUInt32DefVector PackCRCs; // we don't use PackCRCs now\n\n  CUInt32DefVector FolderCRCs;             // NumFolders\n  CObjArray<CNum> NumUnpackStreamsVector;  // NumFolders\n\n  CObjArray<UInt64> CoderUnpackSizes;      // including unpack sizes of bond coders\n  CObjArray<CNum> FoToCoderUnpackSizes;    // NumFolders + 1\n  CObjArray<CNum> FoStartPackStreamIndex;  // NumFolders + 1\n  CObjArray<Byte> FoToMainUnpackSizeIndex; // NumFolders\n  \n  CObjArray<size_t> FoCodersDataOffset;    // NumFolders + 1\n  CByteBuffer CodersData;\n\n  CParsedMethods ParsedMethods;\n\n  void ParseFolderInfo(unsigned folderIndex, CFolder &folder) const;\n  void ParseFolderEx(unsigned folderIndex, CFolderEx &folder) const\n  {\n    ParseFolderInfo(folderIndex, folder);\n    folder.UnpackCoder = FoToMainUnpackSizeIndex[folderIndex];\n  }\n  \n  unsigned GetNumFolderUnpackSizes(unsigned folderIndex) const\n  {\n    return (unsigned)(FoToCoderUnpackSizes[folderIndex + 1] - FoToCoderUnpackSizes[folderIndex]);\n  }\n\n  UInt64 GetFolderUnpackSize(unsigned folderIndex) const\n  {\n    return CoderUnpackSizes[FoToCoderUnpackSizes[folderIndex] + FoToMainUnpackSizeIndex[folderIndex]];\n  }\n\n  UInt64 GetStreamPackSize(unsigned index) const\n  {\n    return PackPositions[index + 1] - PackPositions[index];\n  }\n\n  CFolders(): NumPackStreams(0), NumFolders(0) {}\n\n  void Clear()\n  {\n    NumPackStreams = 0;\n    PackPositions.Free();\n    // PackCRCs.Clear();\n\n    NumFolders = 0;\n    FolderCRCs.Clear();\n    NumUnpackStreamsVector.Free();\n    CoderUnpackSizes.Free();\n    FoToCoderUnpackSizes.Free();\n    FoStartPackStreamIndex.Free();\n    FoToMainUnpackSizeIndex.Free();\n    FoCodersDataOffset.Free();\n    CodersData.Free();\n  }\n};\n\nstruct CDatabase: public CFolders\n{\n  CRecordVector<CFileItem> Files;\n\n  CUInt64DefVector CTime;\n  CUInt64DefVector ATime;\n  CUInt64DefVector MTime;\n  CUInt64DefVector StartPos;\n  CUInt32DefVector Attrib;\n  CBoolVector IsAnti;\n  /*\n  CBoolVector IsAux;\n  CByteBuffer SecureBuf;\n  CRecordVector<UInt32> SecureIDs;\n  */\n\n  CByteBuffer NamesBuf;\n  CObjArray<size_t> NameOffsets; // numFiles + 1, offsets of utf-16 symbols\n\n  /*\n  void ClearSecure()\n  {\n    SecureBuf.Free();\n    SecureIDs.Clear();\n  }\n  */\n\n  void Clear()\n  {\n    CFolders::Clear();\n    // ClearSecure();\n\n    NamesBuf.Free();\n    NameOffsets.Free();\n    \n    Files.Clear();\n    CTime.Clear();\n    ATime.Clear();\n    MTime.Clear();\n    StartPos.Clear();\n    Attrib.Clear();\n    IsAnti.Clear();\n    // IsAux.Clear();\n  }\n\n  bool IsSolid() const\n  {\n    for (CNum i = 0; i < NumFolders; i++)\n      if (NumUnpackStreamsVector[i] > 1)\n        return true;\n    return false;\n  }\n  bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }\n  // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }\n\n  /*\n  const void* GetName(unsigned index) const\n  {\n    if (!NameOffsets || !NamesBuf)\n      return NULL;\n    return (void *)((const Byte *)NamesBuf + NameOffsets[index] * 2);\n  };\n  */\n  void GetPath(unsigned index, UString &path) const;\n  HRESULT GetPath_Prop(unsigned index, PROPVARIANT *path) const throw();\n};\n\n\nstruct CInArchiveInfo\n{\n  CArchiveVersion Version;\n  UInt64 StartPosition;               // in stream\n  UInt64 StartPositionAfterHeader;    // in stream\n  UInt64 DataStartPosition;           // in stream\n  UInt64 DataStartPosition2;          // in stream. it's for headers\n  CRecordVector<UInt64> FileInfoPopIDs;\n  \n  void Clear()\n  {\n    StartPosition = 0;\n    StartPositionAfterHeader = 0;\n    DataStartPosition = 0;\n    DataStartPosition2 = 0;\n    FileInfoPopIDs.Clear();\n  }\n};\n\n\nstruct CDbEx: public CDatabase\n{\n  CInArchiveInfo ArcInfo;\n  \n  CObjArray<CNum> FolderStartFileIndex;\n  CObjArray<CNum> FileIndexToFolderIndexMap;\n\n  UInt64 HeadersSize;\n  UInt64 PhySize;\n  // UInt64 EndHeaderOffset; // relative to position after StartHeader (32 bytes)\n\n  /*\n  CRecordVector<size_t> SecureOffsets;\n  bool IsTree;\n  bool ThereAreAltStreams;\n  */\n\n  bool IsArc;\n  bool PhySizeWasConfirmed;\n\n  bool ThereIsHeaderError;\n  bool UnexpectedEnd;\n  // bool UnsupportedVersion;\n\n  bool StartHeaderWasRecovered;\n  bool UnsupportedFeatureWarning;\n  bool UnsupportedFeatureError;\n\n  /*\n  void ClearSecureEx()\n  {\n    ClearSecure();\n    SecureOffsets.Clear();\n  }\n  */\n\n  void Clear()\n  {\n    IsArc = false;\n    PhySizeWasConfirmed = false;\n\n    ThereIsHeaderError = false;\n    UnexpectedEnd = false;\n    // UnsupportedVersion = false;\n\n    StartHeaderWasRecovered = false;\n    UnsupportedFeatureError = false;\n    UnsupportedFeatureWarning = false;\n\n    /*\n    IsTree = false;\n    ThereAreAltStreams = false;\n    */\n\n    CDatabase::Clear();\n    \n    // SecureOffsets.Clear();\n    ArcInfo.Clear();\n    FolderStartFileIndex.Free();\n    FileIndexToFolderIndexMap.Free();\n\n    HeadersSize = 0;\n    PhySize = 0;\n    // EndHeaderOffset = 0;\n  }\n\n  bool CanUpdate() const\n  {\n    if (ThereIsHeaderError\n        || UnexpectedEnd\n        || StartHeaderWasRecovered\n        || UnsupportedFeatureError)\n      return false;\n    return true;\n  }\n\n  void FillLinks();\n  \n  UInt64 GetFolderStreamPos(size_t folderIndex, size_t indexInFolder) const\n  {\n    return ArcInfo.DataStartPosition + PackPositions.ConstData()\n        [FoStartPackStreamIndex.ConstData()[folderIndex] + indexInFolder];\n  }\n  \n  UInt64 GetFolderFullPackSize(size_t folderIndex) const\n  {\n    return\n      PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex + 1]] -\n      PackPositions[FoStartPackStreamIndex.ConstData()[folderIndex]];\n  }\n  \n  UInt64 GetFolderPackStreamSize(size_t folderIndex, size_t streamIndex) const\n  {\n    const size_t i = FoStartPackStreamIndex.ConstData()[folderIndex] + streamIndex;\n    return PackPositions.ConstData()[i + 1] -\n           PackPositions.ConstData()[i];\n  }\n\n  /*\n  UInt64 GetFilePackSize(size_t fileIndex) const\n  {\n    const CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];\n    if (folderIndex != kNumNoIndex)\n      if (FolderStartFileIndex[folderIndex] == fileIndex)\n        return GetFolderFullPackSize(folderIndex);\n    return 0;\n  }\n  */\n};\n\nconst unsigned kNumBufLevelsMax = 4;\n\nstruct CInByte2\n{\n  const Byte *_buffer;\npublic:\n  size_t _size;\n  size_t _pos;\n  \n  size_t GetRem() const { return _size - _pos; }\n  const Byte *GetPtr() const { return _buffer + _pos; }\n  void Init(const Byte *buffer, size_t size)\n  {\n    _buffer = buffer;\n    _size = size;\n    _pos = 0;\n  }\n  Byte ReadByte();\n  void ReadBytes(Byte *data, size_t size);\n  void SkipDataNoCheck(UInt64 size) { _pos += (size_t)size; }\n  void SkipData(UInt64 size);\n\n  void SkipData();\n  void SkipRem() { _pos = _size; }\n  UInt64 ReadNumber();\n  CNum ReadNum();\n  UInt32 ReadUInt32();\n  UInt64 ReadUInt64();\n\n  void ParseFolder(CFolder &folder);\n};\n\nclass CStreamSwitch;\n\nconst UInt32 kHeaderSize = 32;\n\nclass CInArchive\n{\n  friend class CStreamSwitch;\n\n  CMyComPtr<IInStream> _stream;\n\n  unsigned _numInByteBufs;\n  CInByte2 _inByteVector[kNumBufLevelsMax];\n\n  CInByte2 *_inByteBack;\n  bool ThereIsHeaderError;\n \n  UInt64 _arhiveBeginStreamPosition;\n  UInt64 _fileEndPosition;\n\n  UInt64 _rangeLimit; // relative to position after StartHeader (32 bytes)\n\n  Byte _header[kHeaderSize];\n\n  UInt64 HeadersSize;\n\n  bool _useMixerMT;\n\n  void AddByteStream(const Byte *buffer, size_t size);\n  \n  void DeleteByteStream(bool needUpdatePos)\n  {\n    _numInByteBufs--;\n    if (_numInByteBufs > 0)\n    {\n      _inByteBack = &_inByteVector[_numInByteBufs - 1];\n      if (needUpdatePos)\n        _inByteBack->_pos += _inByteVector[_numInByteBufs]._pos;\n    }\n  }\n\n  HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit);\n  \n  void ReadBytes(Byte *data, size_t size) { _inByteBack->ReadBytes(data, size); }\n  Byte ReadByte() { return _inByteBack->ReadByte(); }\n  UInt64 ReadNumber() { return _inByteBack->ReadNumber(); }\n  CNum ReadNum() { return _inByteBack->ReadNum(); }\n  UInt64 ReadID() { return _inByteBack->ReadNumber(); }\n  UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }\n  UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }\n  void SkipData(UInt64 size) { _inByteBack->SkipData(size); }\n  void SkipData() { _inByteBack->SkipData(); }\n  void WaitId(UInt64 id);\n\n  void Read_UInt32_Vector(CUInt32DefVector &v);\n\n  void ReadArchiveProperties(CInArchiveInfo &archiveInfo);\n  void ReadHashDigests(unsigned numItems, CUInt32DefVector &crcs);\n  \n  void ReadPackInfo(CFolders &f);\n  \n  void ReadUnpackInfo(\n      const CObjectVector<CByteBuffer> *dataVector,\n      CFolders &folders);\n  \n  void ReadSubStreamsInfo(\n      CFolders &folders,\n      CRecordVector<UInt64> &unpackSizes,\n      CUInt32DefVector &digests);\n\n  void ReadStreamsInfo(\n      const CObjectVector<CByteBuffer> *dataVector,\n      UInt64 &dataOffset,\n      CFolders &folders,\n      CRecordVector<UInt64> &unpackSizes,\n      CUInt32DefVector &digests);\n\n  void ReadBoolVector(unsigned numItems, CBoolVector &v);\n  void ReadBoolVector2(unsigned numItems, CBoolVector &v);\n  void ReadUInt64DefVector(const CObjectVector<CByteBuffer> &dataVector,\n      CUInt64DefVector &v, unsigned numItems);\n  HRESULT ReadAndDecodePackedStreams(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      UInt64 baseOffset, UInt64 &dataOffset,\n      CObjectVector<CByteBuffer> &dataVector\n      Z7_7Z_DECODER_CRYPRO_VARS_DECL\n      );\n  HRESULT ReadHeader(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      CDbEx &db\n      Z7_7Z_DECODER_CRYPRO_VARS_DECL\n      );\n  HRESULT ReadDatabase2(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      CDbEx &db\n      Z7_7Z_DECODER_CRYPRO_VARS_DECL\n      );\npublic:\n  CInArchive(bool useMixerMT):\n      _numInByteBufs(0),\n      _useMixerMT(useMixerMT)\n      {}\n  \n  HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive\n  void Close();\n\n  HRESULT ReadDatabase(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      CDbEx &db\n      Z7_7Z_DECODER_CRYPRO_VARS_DECL\n      );\n};\n  \n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zItem.h",
    "content": "﻿// 7zItem.h\n\n#ifndef ZIP7_INC_7Z_ITEM_H\n#define ZIP7_INC_7Z_ITEM_H\n\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyString.h\"\n\n#include \"../../Common/MethodId.h\"\n\n#include \"7zHeader.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\ntypedef UInt32 CNum;\nconst CNum kNumMax     = 0x7FFFFFFF;\nconst CNum kNumNoIndex = 0xFFFFFFFF;\n\nstruct CCoderInfo\n{\n  CMethodId MethodID;\n  CByteBuffer Props;\n  UInt32 NumStreams;\n  \n  bool IsSimpleCoder() const { return NumStreams == 1; }\n};\n\n\nstruct CBond\n{\n  UInt32 PackIndex;\n  UInt32 UnpackIndex;\n};\n\n\nstruct CFolder\n{\n  Z7_CLASS_NO_COPY(CFolder)\npublic:\n  CObjArray2<CCoderInfo> Coders;\n  CObjArray2<CBond> Bonds;\n  CObjArray2<UInt32> PackStreams;\n\n  CFolder() {}\n\n  bool IsDecodingSupported() const { return Coders.Size() <= 32; }\n\n  int Find_in_PackStreams(UInt32 packStream) const\n  {\n    FOR_VECTOR(i, PackStreams)\n      if (PackStreams[i] == packStream)\n        return (int)i;\n    return -1;\n  }\n\n  int FindBond_for_PackStream(UInt32 packStream) const\n  {\n    FOR_VECTOR(i, Bonds)\n      if (Bonds[i].PackIndex == packStream)\n        return (int)i;\n    return -1;\n  }\n  \n  /*\n  int FindBond_for_UnpackStream(UInt32 unpackStream) const\n  {\n    FOR_VECTOR(i, Bonds)\n      if (Bonds[i].UnpackIndex == unpackStream)\n        return i;\n    return -1;\n  }\n\n  int FindOutCoder() const\n  {\n    for (int i = (int)Coders.Size() - 1; i >= 0; i--)\n      if (FindBond_for_UnpackStream(i) < 0)\n        return i;\n    return -1;\n  }\n  */\n\n  bool IsEncrypted() const\n  {\n    FOR_VECTOR(i, Coders)\n      if (Coders[i].MethodID == k_AES)\n        return true;\n    return false;\n  }\n};\n\n\nstruct CUInt32DefVector\n{\n  CBoolVector Defs;\n  CRecordVector<UInt32> Vals;\n\n  void ClearAndSetSize(unsigned newSize)\n  {\n    Defs.ClearAndSetSize(newSize);\n    Vals.ClearAndSetSize(newSize);\n  }\n\n  void Clear()\n  {\n    Defs.Clear();\n    Vals.Clear();\n  }\n\n  void ReserveDown()\n  {\n    Defs.ReserveDown();\n    Vals.ReserveDown();\n  }\n\n  bool GetItem(unsigned index, UInt32 &value) const\n  {\n    if (index < Defs.Size() && Defs[index])\n    {\n      value = Vals[index];\n      return true;\n    }\n    value = 0;\n    return false;\n  }\n\n  bool ValidAndDefined(unsigned i) const { return i < Defs.Size() && Defs[i]; }\n\n  bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }\n\n  void SetItem(unsigned index, bool defined, UInt32 value);\n  void if_NonEmpty_FillResidue_with_false(unsigned numItems)\n  {\n    if (Defs.Size() != 0 && Defs.Size() < numItems)\n      SetItem(numItems - 1, false, 0);\n  }\n};\n\n\nstruct CUInt64DefVector\n{\n  CBoolVector Defs;\n  CRecordVector<UInt64> Vals;\n  \n  void Clear()\n  {\n    Defs.Clear();\n    Vals.Clear();\n  }\n  \n  void ReserveDown()\n  {\n    Defs.ReserveDown();\n    Vals.ReserveDown();\n  }\n\n  bool GetItem(unsigned index, UInt64 &value) const\n  {\n    if (index < Defs.Size() && Defs[index])\n    {\n      value = Vals[index];\n      return true;\n    }\n    value = 0;\n    return false;\n  }\n  \n  bool CheckSize(unsigned size) const { return Defs.Size() == size || Defs.Size() == 0; }\n\n  void SetItem(unsigned index, bool defined, UInt64 value);\n};\n\n\nstruct CFileItem\n{\n  UInt64 Size;\n  UInt32 Crc;\n  /*\n  int Parent;\n  bool IsAltStream;\n  */\n  bool HasStream; // Test it !!! it means that there is\n                  // stream in some folder. It can be empty stream\n  bool IsDir;\n  bool CrcDefined;\n\n  /*\n  void Clear()\n  {\n    HasStream = true;\n    IsDir = false;\n    CrcDefined = false;\n  }\n\n  CFileItem():\n    // Parent(-1),\n    // IsAltStream(false),\n    HasStream(true),\n    IsDir(false),\n    CrcDefined(false),\n      {}\n  */\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zOut.cpp",
    "content": "﻿// 7zOut.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/7zCrc.h\"\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/AutoPtr.h\"\n// #include \"../../../Common/UTFConvert.h\"\n\n#include \"../../Common/StreamObjects.h\"\n#include \"../Common/OutStreamWithCRC.h\"\n\n#include \"7zOut.h\"\n\nunsigned BoolVector_CountSum(const CBoolVector &v);\n\nstatic UInt64 UInt64Vector_CountSum(const CRecordVector<UInt64> &v)\n{\n  UInt64 sum = 0;\n  const unsigned size = v.Size();\n  if (size)\n  {\n    const UInt64 *p = v.ConstData();\n    const UInt64 * const lim = p + size;\n    do\n      sum += *p++;\n    while (p != lim);\n  }\n  return sum;\n}\n\n\nnamespace NArchive {\nnamespace N7z {\n\nstatic void FillSignature(Byte *buf)\n{\n  memcpy(buf, kSignature, kSignatureSize);\n  buf[kSignatureSize] = kMajorVersion;\n  buf[kSignatureSize + 1] = 4;\n}\n\n#ifdef Z7_7Z_VOL\nHRESULT COutArchive::WriteFinishSignature()\n{\n  RINOK(WriteDirect(kFinishSignature, kSignatureSize));\n  CArchiveVersion av;\n  av.Major = kMajorVersion;\n  av.Minor = 2;\n  RINOK(WriteDirectByte(av.Major));\n  return WriteDirectByte(av.Minor);\n}\n#endif\n\nstatic void SetUInt32(Byte *p, UInt32 d)\n{\n  for (int i = 0; i < 4; i++, d >>= 8)\n    p[i] = (Byte)d;\n}\n\nstatic void SetUInt64(Byte *p, UInt64 d)\n{\n  for (int i = 0; i < 8; i++, d >>= 8)\n    p[i] = (Byte)d;\n}\n\nHRESULT COutArchive::WriteStartHeader(const CStartHeader &h)\n{\n  Byte buf[32];\n  FillSignature(buf);\n  SetUInt64(buf + 8 + 4, h.NextHeaderOffset);\n  SetUInt64(buf + 8 + 12, h.NextHeaderSize);\n  SetUInt32(buf + 8 + 20, h.NextHeaderCRC);\n  SetUInt32(buf + 8, CrcCalc(buf + 8 + 4, 20));\n  return WriteDirect(buf, sizeof(buf));\n}\n\n#ifdef Z7_7Z_VOL\nHRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)\n{\n  CCRC crc;\n  crc.UpdateUInt64(h.NextHeaderOffset);\n  crc.UpdateUInt64(h.NextHeaderSize);\n  crc.UpdateUInt32(h.NextHeaderCRC);\n  crc.UpdateUInt64(h.ArchiveStartOffset);\n  crc.UpdateUInt64(h.AdditionalStartBlockSize);\n  RINOK(WriteDirectUInt32(crc.GetDigest()));\n  RINOK(WriteDirectUInt64(h.NextHeaderOffset));\n  RINOK(WriteDirectUInt64(h.NextHeaderSize));\n  RINOK(WriteDirectUInt32(h.NextHeaderCRC));\n  RINOK(WriteDirectUInt64(h.ArchiveStartOffset));\n  return WriteDirectUInt64(h.AdditionalStartBlockSize);\n}\n#endif\n\nHRESULT COutArchive::Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */)\n{\n  Close();\n  #ifdef Z7_7Z_VOL\n  // endMarker = false;\n  _endMarker = endMarker;\n  #endif\n  SeqStream = stream;\n  // if (!endMarker)\n  {\n    SeqStream.QueryInterface(IID_IOutStream, &Stream);\n    if (!Stream)\n    {\n      return E_NOTIMPL;\n      // endMarker = true;\n    }\n    RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_signatureHeaderPos))\n    Byte buf[32];\n    FillSignature(buf);\n    memset(&buf[8], 0, 32 - 8);\n    return WriteDirect(buf, sizeof(buf));\n  }\n  #ifdef Z7_7Z_VOL\n  if (endMarker)\n  {\n    /*\n    CStartHeader sh;\n    sh.NextHeaderOffset = (UInt32)(Int32)-1;\n    sh.NextHeaderSize = (UInt32)(Int32)-1;\n    sh.NextHeaderCRC = 0;\n    WriteStartHeader(sh);\n    return S_OK;\n    */\n  }\n  #endif\n}\n\nvoid COutArchive::Close()\n{\n  SeqStream.Release();\n  Stream.Release();\n}\n\nUInt64 COutArchive::GetPos() const\n{\n  if (_countMode)\n    return _countSize;\n  if (_writeToStream)\n    return _outByte.GetProcessedSize();\n  return _outByte2.GetPos();\n}\n\nvoid COutArchive::WriteBytes(const void *data, size_t size)\n{\n  if (_countMode)\n    _countSize += size;\n  else if (_writeToStream)\n  {\n    _outByte.WriteBytes(data, size);\n    // _crc = CrcUpdate(_crc, data, size);\n  }\n  else\n    _outByte2.WriteBytes(data, size);\n}\n\nvoid COutArchive::WriteByte(Byte b)\n{\n  if (_countMode)\n    _countSize++;\n  else if (_writeToStream)\n    WriteByte_ToStream(b);\n  else\n    _outByte2.WriteByte(b);\n}\n\n/*\nvoid COutArchive::WriteUInt32(UInt32 value)\n{\n  for (int i = 0; i < 4; i++)\n  {\n    WriteByte((Byte)value);\n    value >>= 8;\n  }\n}\n\nvoid COutArchive::WriteUInt64(UInt64 value)\n{\n  for (int i = 0; i < 8; i++)\n  {\n    WriteByte((Byte)value);\n    value >>= 8;\n  }\n}\n*/\n\nvoid COutArchive::WriteNumber(UInt64 value)\n{\n  Byte firstByte = 0;\n  Byte mask = 0x80;\n  int i;\n  for (i = 0; i < 8; i++)\n  {\n    if (value < ((UInt64(1) << ( 7  * (i + 1)))))\n    {\n      firstByte |= Byte(value >> (8 * i));\n      break;\n    }\n    firstByte |= mask;\n    mask = (Byte)(mask >> 1);\n  }\n  WriteByte(firstByte);\n  for (; i > 0; i--)\n  {\n    WriteByte((Byte)value);\n    value >>= 8;\n  }\n}\n\nstatic unsigned GetBigNumberSize(UInt64 value)\n{\n  unsigned i;\n  for (i = 1; i < 9; i++)\n    if (value < (((UInt64)1 << (i * 7))))\n      break;\n  return i;\n}\n\n#ifdef Z7_7Z_VOL\nUInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)\n{\n  UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;\n  if (nameLength != 0)\n  {\n    nameLength = (nameLength + 1) * 2;\n    result += nameLength + GetBigNumberSize(nameLength) + 2;\n  }\n  if (props)\n  {\n    result += 20;\n  }\n  if (result >= 128)\n    result++;\n  result += kSignatureSize + 2 + kFinishHeaderSize;\n  return result;\n}\n\nUInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)\n{\n  UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);\n  int testSize;\n  if (volSize > headersSizeBase)\n    testSize = volSize - headersSizeBase;\n  else\n    testSize = 1;\n  UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);\n  UInt64 pureSize = 1;\n  if (volSize > headersSize)\n    pureSize = volSize - headersSize;\n  return pureSize;\n}\n#endif\n\nvoid COutArchive::WriteFolder(const CFolder &folder)\n{\n  WriteNumber(folder.Coders.Size());\n  unsigned i;\n  \n  for (i = 0; i < folder.Coders.Size(); i++)\n  {\n    const CCoderInfo &coder = folder.Coders[i];\n    {\n      UInt64 id = coder.MethodID;\n      unsigned idSize;\n      for (idSize = 1; idSize < sizeof(id); idSize++)\n        if ((id >> (8 * idSize)) == 0)\n          break;\n      // idSize &= 0xF; // idSize is smaller than 16 already\n      Byte temp[16];\n      for (unsigned t = idSize; t != 0; t--, id >>= 8)\n        temp[t] = (Byte)(id & 0xFF);\n  \n      unsigned b = idSize;\n      const bool isComplex = !coder.IsSimpleCoder();\n      b |= (isComplex ? 0x10 : 0);\n\n      const size_t propsSize = coder.Props.Size();\n      b |= ((propsSize != 0) ? 0x20 : 0);\n      temp[0] = (Byte)b;\n      WriteBytes(temp, idSize + 1);\n      if (isComplex)\n      {\n        WriteNumber(coder.NumStreams);\n        WriteNumber(1); // NumOutStreams;\n      }\n      if (propsSize == 0)\n        continue;\n      WriteNumber(propsSize);\n      WriteBytes(coder.Props, propsSize);\n    }\n  }\n  \n  for (i = 0; i < folder.Bonds.Size(); i++)\n  {\n    const CBond &bond = folder.Bonds[i];\n    WriteNumber(bond.PackIndex);\n    WriteNumber(bond.UnpackIndex);\n  }\n  \n  if (folder.PackStreams.Size() > 1)\n    for (i = 0; i < folder.PackStreams.Size(); i++)\n      WriteNumber(folder.PackStreams[i]);\n}\n\nvoid COutArchive::Write_BoolVector(const CBoolVector &boolVector)\n{\n  Byte b = 0;\n  Byte mask = 0x80;\n  FOR_VECTOR (i, boolVector)\n  {\n    if (boolVector[i])\n      b |= mask;\n    mask = (Byte)(mask >> 1);\n    if (mask == 0)\n    {\n      WriteByte(b);\n      mask = 0x80;\n      b = 0;\n    }\n  }\n  if (mask != 0x80)\n    WriteByte(b);\n}\n\nstatic inline unsigned Bv_GetSizeInBytes(const CBoolVector &v) { return ((unsigned)v.Size() + 7) / 8; }\n\nvoid COutArchive::WritePropBoolVector(Byte id, const CBoolVector &boolVector)\n{\n  WriteByte(id);\n  WriteNumber(Bv_GetSizeInBytes(boolVector));\n  Write_BoolVector(boolVector);\n}\n\nvoid COutArchive::Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined)\n{\n  if (numDefined == boolVector.Size())\n    WriteByte(1);\n  else\n  {\n    WriteByte(0);\n    Write_BoolVector(boolVector);\n  }\n}\n\n\nvoid COutArchive::WriteHashDigests(const CUInt32DefVector &digests)\n{\n  const unsigned numDefined = BoolVector_CountSum(digests.Defs);\n  if (numDefined == 0)\n    return;\n  WriteByte(NID::kCRC);\n  Write_BoolVector_numDefined(digests.Defs, numDefined);\n  Write_UInt32DefVector_numDefined(digests, numDefined);\n}\n\n\nvoid COutArchive::WritePackInfo(\n    UInt64 dataOffset,\n    const CRecordVector<UInt64> &packSizes,\n    const CUInt32DefVector &packCRCs)\n{\n  if (packSizes.IsEmpty())\n    return;\n  WriteByte(NID::kPackInfo);\n  WriteNumber(dataOffset);\n  WriteNumber(packSizes.Size());\n  WriteByte(NID::kSize);\n  FOR_VECTOR (i, packSizes)\n    WriteNumber(packSizes[i]);\n\n  WriteHashDigests(packCRCs);\n  \n  WriteByte(NID::kEnd);\n}\n\nvoid COutArchive::WriteUnpackInfo(const CObjectVector<CFolder> &folders, const COutFolders &outFolders)\n{\n  if (folders.IsEmpty())\n    return;\n\n  WriteByte(NID::kUnpackInfo);\n\n  WriteByte(NID::kFolder);\n  WriteNumber(folders.Size());\n  {\n    WriteByte(0);\n    FOR_VECTOR (i, folders)\n      WriteFolder(folders[i]);\n  }\n  \n  WriteByte(NID::kCodersUnpackSize);\n  FOR_VECTOR (i, outFolders.CoderUnpackSizes)\n    WriteNumber(outFolders.CoderUnpackSizes[i]);\n  \n  WriteHashDigests(outFolders.FolderUnpackCRCs);\n  \n  WriteByte(NID::kEnd);\n}\n\nvoid COutArchive::WriteSubStreamsInfo(const CObjectVector<CFolder> &folders,\n    const COutFolders &outFolders,\n    const CRecordVector<UInt64> &unpackSizes,\n    const CUInt32DefVector &digests)\n{\n  const CRecordVector<CNum> &numUnpackStreamsInFolders = outFolders.NumUnpackStreamsVector;\n  WriteByte(NID::kSubStreamsInfo);\n\n  unsigned i;\n  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\n    if (numUnpackStreamsInFolders[i] != 1)\n    {\n      WriteByte(NID::kNumUnpackStream);\n      for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\n        WriteNumber(numUnpackStreamsInFolders[i]);\n      break;\n    }\n \n  for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\n    if (numUnpackStreamsInFolders[i] > 1)\n    {\n      WriteByte(NID::kSize);\n      CNum index = 0;\n      for (i = 0; i < numUnpackStreamsInFolders.Size(); i++)\n      {\n        CNum num = numUnpackStreamsInFolders[i];\n        for (CNum j = 0; j < num; j++)\n        {\n          if (j + 1 != num)\n            WriteNumber(unpackSizes[index]);\n          index++;\n        }\n      }\n      break;\n    }\n\n  CUInt32DefVector digests2;\n\n  unsigned digestIndex = 0;\n  for (i = 0; i < folders.Size(); i++)\n  {\n    unsigned numSubStreams = (unsigned)numUnpackStreamsInFolders[i];\n    if (numSubStreams == 1 && outFolders.FolderUnpackCRCs.ValidAndDefined(i))\n      digestIndex++;\n    else\n      for (unsigned j = 0; j < numSubStreams; j++, digestIndex++)\n      {\n        digests2.Defs.Add(digests.Defs[digestIndex]);\n        digests2.Vals.Add(digests.Vals[digestIndex]);\n      }\n  }\n  WriteHashDigests(digests2);\n  WriteByte(NID::kEnd);\n}\n\n// 7-Zip 4.50 - 4.58 contain BUG, so they do not support .7z archives with Unknown field.\n\nvoid COutArchive::SkipToAligned(unsigned pos, unsigned alignShifts)\n{\n  if (!_useAlign)\n    return;\n\n  const unsigned alignSize = (unsigned)1 << alignShifts;\n  pos += (unsigned)GetPos();\n  pos &= (alignSize - 1);\n  if (pos == 0)\n    return;\n  unsigned skip = alignSize - pos;\n  if (skip < 2)\n    skip += alignSize;\n  skip -= 2;\n  WriteByte(NID::kDummy);\n  WriteByte((Byte)skip);\n  for (unsigned i = 0; i < skip; i++)\n    WriteByte(0);\n}\n\nvoid COutArchive::WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts)\n{\n  const unsigned bvSize = (numDefined == v.Size()) ? 0 : Bv_GetSizeInBytes(v);\n  const UInt64 dataSize = ((UInt64)numDefined << itemSizeShifts) + bvSize + 2;\n  SkipToAligned(3 + bvSize + GetBigNumberSize(dataSize), itemSizeShifts);\n\n  WriteByte(type);\n  WriteNumber(dataSize);\n  Write_BoolVector_numDefined(v, numDefined);\n  WriteByte(0); // 0 means no switching to external stream\n}\n\n\nvoid COutArchive::Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined)\n{\n  if (_countMode)\n  {\n    _countSize += (size_t)numDefined * 4;\n    return;\n  }\n\n  const bool * const defs = v.Defs.ConstData();\n  const UInt32 * const vals = v.Vals.ConstData();\n  const size_t num = v.Defs.Size();\n\n  for (size_t i = 0; i < num; i++)\n    if (defs[i])\n    {\n      UInt32 value = vals[i];\n      for (int k = 0; k < 4; k++)\n      {\n        if (_writeToStream)\n          WriteByte_ToStream((Byte)value);\n        else\n          _outByte2.WriteByte((Byte)value);\n        // WriteByte((Byte)value);\n        value >>= 8;\n      }\n      // WriteUInt32(v.Vals[i]);\n    }\n}\n\n\nvoid COutArchive::Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type)\n{\n  const unsigned numDefined = BoolVector_CountSum(v.Defs);\n  if (numDefined == 0)\n    return;\n\n  WriteAlignedBools(v.Defs, numDefined, type, 3);\n  \n  if (_countMode)\n  {\n    _countSize += (size_t)numDefined * 8;\n    return;\n  }\n\n  const bool * const defs = v.Defs.ConstData();\n  const UInt64 * const vals = v.Vals.ConstData();\n  const size_t num = v.Defs.Size();\n\n  for (size_t i = 0; i < num; i++)\n    if (defs[i])\n    {\n      UInt64 value = vals[i];\n      for (int k = 0; k < 8; k++)\n      {\n        if (_writeToStream)\n          WriteByte_ToStream((Byte)value);\n        else\n          _outByte2.WriteByte((Byte)value);\n        // WriteByte((Byte)value);\n        value >>= 8;\n      }\n      // WriteUInt64(v.Vals[i]);\n    }\n}\n\n\nHRESULT COutArchive::EncodeStream(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CEncoder &encoder, const CByteBuffer &data,\n    CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders)\n{\n  CMyComPtr2_Create<ISequentialInStream, CBufInStream> streamSpec;\n  streamSpec->Init(data, data.Size());\n  outFolders.FolderUnpackCRCs.Defs.Add(true);\n  outFolders.FolderUnpackCRCs.Vals.Add(CrcCalc(data, data.Size()));\n  // outFolders.NumUnpackStreamsVector.Add(1);\n  const UInt64 dataSize64 = data.Size();\n  const UInt64 expectSize = data.Size();\n  RINOK(encoder.Encode1(\n      EXTERNAL_CODECS_LOC_VARS\n      streamSpec,\n      // NULL,\n      &dataSize64,  // inSizeForReduce\n      expectSize,\n      folders.AddNew(),\n      // outFolders.CoderUnpackSizes, unpackSize,\n      SeqStream, packSizes, NULL))\n  if (!streamSpec->WasFinished())\n    return E_FAIL;\n  encoder.Encode_Post(dataSize64, outFolders.CoderUnpackSizes);\n  return S_OK;\n}\n\nvoid COutArchive::WriteHeader(\n    const CArchiveDatabaseOut &db,\n    // const CHeaderOptions &headerOptions,\n    UInt64 &headerOffset)\n{\n  /*\n  bool thereIsSecure = (db.SecureBuf.Size() != 0);\n  */\n  _useAlign = true;\n\n  headerOffset = UInt64Vector_CountSum(db.PackSizes);\n\n  WriteByte(NID::kHeader);\n\n  /*\n  {\n    // It's example for per archive properies writing\n  \n    WriteByte(NID::kArchiveProperties);\n\n    // you must use random 40-bit number that will identify you\n    // then you can use same kDeveloperID for any properties and methods\n    const UInt64 kDeveloperID = 0x123456789A; // change that value to real random 40-bit number\n\n    #define GENERATE_7Z_ID(developerID, subID) (((UInt64)0x3F << 56) | ((UInt64)developerID << 16) | subID)\n\n    {\n      const UInt64 kSubID = 0x1; // you can use small number for subID\n      const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);\n      WriteNumber(kID);\n      const unsigned kPropsSize = 3; // it's example size\n      WriteNumber(kPropsSize);\n      for (unsigned i = 0; i < kPropsSize; i++)\n        WriteByte((Byte)(i & 0xFF));\n    }\n    {\n      const UInt64 kSubID = 0x2; // you can use small number for subID\n      const UInt64 kID = GENERATE_7Z_ID(kDeveloperID, kSubID);\n      WriteNumber(kID);\n      const unsigned kPropsSize = 5; // it's example size\n      WriteNumber(kPropsSize);\n      for (unsigned i = 0; i < kPropsSize; i++)\n        WriteByte((Byte)(i + 16));\n    }\n    WriteByte(NID::kEnd);\n  }\n  */\n\n  if (db.Folders.Size() > 0)\n  {\n    WriteByte(NID::kMainStreamsInfo);\n    WritePackInfo(0, db.PackSizes, db.PackCRCs);\n    WriteUnpackInfo(db.Folders, (const COutFolders &)db);\n\n    CRecordVector<UInt64> unpackSizes;\n    CUInt32DefVector digests;\n    FOR_VECTOR (i, db.Files)\n    {\n      const CFileItem &file = db.Files[i];\n      if (!file.HasStream)\n        continue;\n      unpackSizes.Add(file.Size);\n      digests.Defs.Add(file.CrcDefined);\n      digests.Vals.Add(file.Crc);\n    }\n\n    WriteSubStreamsInfo(db.Folders, (const COutFolders &)db, unpackSizes, digests);\n    WriteByte(NID::kEnd);\n  }\n\n  if (db.Files.IsEmpty())\n  {\n    WriteByte(NID::kEnd);\n    return;\n  }\n\n  WriteByte(NID::kFilesInfo);\n  WriteNumber(db.Files.Size());\n\n  {\n    /* ---------- Empty Streams ---------- */\n    CBoolVector emptyStreamVector;\n    emptyStreamVector.ClearAndSetSize(db.Files.Size());\n    unsigned numEmptyStreams = 0;\n    {\n      FOR_VECTOR (i, db.Files)\n        if (db.Files[i].HasStream)\n          emptyStreamVector[i] = false;\n        else\n        {\n          emptyStreamVector[i] = true;\n          numEmptyStreams++;\n        }\n    }\n\n    if (numEmptyStreams != 0)\n    {\n      WritePropBoolVector(NID::kEmptyStream, emptyStreamVector);\n      \n      CBoolVector emptyFileVector, antiVector;\n      emptyFileVector.ClearAndSetSize(numEmptyStreams);\n      antiVector.ClearAndSetSize(numEmptyStreams);\n      bool thereAreEmptyFiles = false, thereAreAntiItems = false;\n      unsigned cur = 0;\n      \n      FOR_VECTOR (i, db.Files)\n      {\n        const CFileItem &file = db.Files[i];\n        if (file.HasStream)\n          continue;\n        emptyFileVector[cur] = !file.IsDir;\n        if (!file.IsDir)\n          thereAreEmptyFiles = true;\n        bool isAnti = db.IsItemAnti(i);\n        antiVector[cur] = isAnti;\n        if (isAnti)\n          thereAreAntiItems = true;\n        cur++;\n      }\n      \n      if (thereAreEmptyFiles)\n        WritePropBoolVector(NID::kEmptyFile, emptyFileVector);\n      if (thereAreAntiItems)\n        WritePropBoolVector(NID::kAnti, antiVector);\n    }\n  }\n\n\n  {\n    /* ---------- Names ---------- */\n    \n    size_t namesDataSize = 0;\n    {\n      FOR_VECTOR (i, db.Files)\n      {\n        const UString &name = db.Names[i];\n        const size_t numUtfChars =\n        /*\n        #if WCHAR_MAX > 0xffff\n        Get_Num_Utf16_chars_from_wchar_string(name.Ptr());\n        #else\n        */\n        name.Len();\n        // #endif\n        namesDataSize += numUtfChars;\n      }\n    }\n    if (namesDataSize)\n    {\n      namesDataSize += db.Files.Size();  // we will write tail zero wchar for each name\n      namesDataSize *= 2;  // 2 bytes per wchar for UTF16 encoding\n      namesDataSize++;     // for additional switch byte (zero value)\n      SkipToAligned(2 + GetBigNumberSize(namesDataSize), 4);\n      WriteByte(NID::kName);\n      WriteNumber(namesDataSize);\n\n      if (_countMode)\n        _countSize += namesDataSize;\n      else\n      {\n        WriteByte(0);\n        FOR_VECTOR (i, db.Files)\n        {\n          const UString &name = db.Names[i];\n          const wchar_t *p = name.Ptr();\n          const size_t len = (size_t)name.Len() + 1;\n          const wchar_t * const lim = p + len;\n          if (_writeToStream)\n          {\n            do\n            {\n              const wchar_t c = *p++;\n              WriteByte_ToStream((Byte)c);\n              WriteByte_ToStream((Byte)(c >> 8));\n            }\n            while (p != lim);\n          }\n          else\n          {\n            Byte *dest = _outByte2.GetDest_and_Update(len * 2);\n            do\n            {\n              /*\n              #if WCHAR_MAX > 0xffff\n              if (c >= 0x10000)\n              {\n                c -= 0x10000;\n                if (c < (1 << 20))\n                {\n                  unsigned c0 = 0xd800 + ((c >> 10) & 0x3FF);\n                  WriteByte((Byte)c0);\n                  WriteByte((Byte)(c0 >> 8));\n                  c = 0xdc00 + (c & 0x3FF);\n                }\n                else\n                c = '_'; // we change character unsupported by UTF16\n              }\n              #endif\n              */\n              const wchar_t c = *p++;\n              SetUi16(dest, (UInt16)c)\n              dest += 2;\n            }\n            while (p != lim);\n          }\n        }\n      }\n    }\n  }\n\n  /* if (headerOptions.WriteCTime) */ Write_UInt64DefVector_type(db.CTime, NID::kCTime);\n  /* if (headerOptions.WriteATime) */ Write_UInt64DefVector_type(db.ATime, NID::kATime);\n  /* if (headerOptions.WriteMTime) */ Write_UInt64DefVector_type(db.MTime, NID::kMTime);\n  Write_UInt64DefVector_type(db.StartPos, NID::kStartPos);\n  \n  {\n    /* ---------- Write Attrib ---------- */\n    const unsigned numDefined = BoolVector_CountSum(db.Attrib.Defs);\n    if (numDefined != 0)\n    {\n      WriteAlignedBools(db.Attrib.Defs, numDefined, NID::kWinAttrib, 2);\n      Write_UInt32DefVector_numDefined(db.Attrib, numDefined);\n    }\n  }\n\n  /*\n  {\n    // ---------- Write IsAux ----------\n    if (BoolVector_CountSum(db.IsAux) != 0)\n      WritePropBoolVector(NID::kIsAux, db.IsAux);\n  }\n\n  {\n    // ---------- Write Parent ----------\n    CBoolVector boolVector;\n    boolVector.Reserve(db.Files.Size());\n    unsigned numIsDir = 0;\n    unsigned numParentLinks = 0;\n    for (i = 0; i < db.Files.Size(); i++)\n    {\n      const CFileItem &file = db.Files[i];\n      bool defined = !file.IsAltStream;\n      boolVector.Add(defined);\n      if (defined)\n        numIsDir++;\n      if (file.Parent >= 0)\n        numParentLinks++;\n    }\n    if (numParentLinks > 0)\n    {\n      // WriteAlignedBools(boolVector, numDefined, NID::kParent, 2);\n      const unsigned bvSize = (numIsDir == boolVector.Size()) ? 0 : Bv_GetSizeInBytes(boolVector);\n      const UInt64 dataSize = (UInt64)db.Files.Size() * 4 + bvSize + 1;\n      SkipToAligned(2 + (unsigned)bvSize + (unsigned)GetBigNumberSize(dataSize), 2);\n      \n      WriteByte(NID::kParent);\n      WriteNumber(dataSize);\n      Write_BoolVector_numDefined(boolVector, numIsDir);\n      for (i = 0; i < db.Files.Size(); i++)\n      {\n        const CFileItem &file = db.Files[i];\n        // if (file.Parent >= 0)\n          WriteUInt32(file.Parent);\n      }\n    }\n  }\n\n  if (thereIsSecure)\n  {\n    UInt64 secureDataSize = 1 + 4 +\n       db.SecureBuf.Size() +\n       db.SecureSizes.Size() * 4;\n    // secureDataSize += db.SecureIDs.Size() * 4;\n    for (i = 0; i < db.SecureIDs.Size(); i++)\n      secureDataSize += GetBigNumberSize(db.SecureIDs[i]);\n    SkipToAligned(2 + GetBigNumberSize(secureDataSize), 2);\n    WriteByte(NID::kNtSecure);\n    WriteNumber(secureDataSize);\n    WriteByte(0);\n    WriteUInt32(db.SecureSizes.Size());\n    for (i = 0; i < db.SecureSizes.Size(); i++)\n      WriteUInt32(db.SecureSizes[i]);\n    WriteBytes(db.SecureBuf, db.SecureBuf.Size());\n    for (i = 0; i < db.SecureIDs.Size(); i++)\n    {\n      WriteNumber(db.SecureIDs[i]);\n      // WriteUInt32(db.SecureIDs[i]);\n    }\n  }\n  */\n\n  WriteByte(NID::kEnd); // for files\n  WriteByte(NID::kEnd); // for headers\n}\n\nHRESULT COutArchive::WriteDatabase(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const CArchiveDatabaseOut &db,\n    const CCompressionMethodMode *options,\n    const CHeaderOptions &headerOptions)\n{\n  if (!db.CheckNumFiles())\n    return E_FAIL;\n\n  CStartHeader sh;\n  sh.NextHeaderOffset = 0;\n  sh.NextHeaderSize = 0;\n  sh.NextHeaderCRC = 0; // CrcCalc(NULL, 0);\n\n  if (!db.IsEmpty())\n  {\n    CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> crcStream;\n    crcStream->SetStream(SeqStream);\n    crcStream->Init();\n\n    bool encodeHeaders = false;\n    if (options)\n      if (options->IsEmpty())\n        options = NULL;\n    if (options)\n      if (options->PasswordIsDefined || headerOptions.CompressMainHeader)\n        encodeHeaders = true;\n\n    if (!_outByte.Create(1 << 16))\n      return E_OUTOFMEMORY;\n    _outByte.SetStream(crcStream.Interface());\n    _outByte.Init();\n    // _crc = CRC_INIT_VAL;\n    _countMode = encodeHeaders;\n    _writeToStream = true;\n    _countSize = 0;\n    WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);\n\n    if (encodeHeaders)\n    {\n      CByteBuffer buf(_countSize);\n      _outByte2.Init((Byte *)buf, _countSize);\n      \n      _countMode = false;\n      _writeToStream = false;\n      WriteHeader(db, /* headerOptions, */ sh.NextHeaderOffset);\n      \n      if (_countSize != _outByte2.GetPos())\n        return E_FAIL;\n\n      CCompressionMethodMode encryptOptions;\n      encryptOptions.PasswordIsDefined = options->PasswordIsDefined;\n      encryptOptions.Password = options->Password;\n      CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);\n      CRecordVector<UInt64> packSizes;\n      CObjectVector<CFolder> folders;\n      COutFolders outFolders;\n\n      RINOK(EncodeStream(\n          EXTERNAL_CODECS_LOC_VARS\n          encoder, buf,\n          packSizes, folders, outFolders))\n\n      _writeToStream = true;\n      \n      if (folders.Size() == 0)\n        throw 1;\n\n      WriteID(NID::kEncodedHeader);\n      WritePackInfo(sh.NextHeaderOffset, packSizes, CUInt32DefVector());\n      WriteUnpackInfo(folders, outFolders);\n      WriteByte(NID::kEnd);\n\n      sh.NextHeaderOffset += UInt64Vector_CountSum(packSizes);\n    }\n    RINOK(_outByte.Flush())\n    sh.NextHeaderCRC = crcStream->GetCRC();\n    // sh.NextHeaderCRC = CRC_GET_DIGEST(_crc);\n    // if (CRC_GET_DIGEST(_crc) != sh.NextHeaderCRC) throw 1;\n    sh.NextHeaderSize = _outByte.GetProcessedSize();\n  }\n  #ifdef Z7_7Z_VOL\n  if (_endMarker)\n  {\n    CFinishHeader h;\n    h.NextHeaderSize = headerSize;\n    h.NextHeaderCRC = headerCRC;\n    h.NextHeaderOffset =\n        UInt64(0) - (headerSize +\n        4 + kFinishHeaderSize);\n    h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;\n    h.AdditionalStartBlockSize = 0;\n    RINOK(WriteFinishHeader(h));\n    return WriteFinishSignature();\n  }\n  else\n  #endif\n  if (Stream)\n  {\n    RINOK(Stream->Seek((Int64)_signatureHeaderPos, STREAM_SEEK_SET, NULL))\n    return WriteStartHeader(sh);\n  }\n  return S_OK;\n}\n\nvoid CUInt32DefVector::SetItem(unsigned index, bool defined, UInt32 value)\n{\n  while (index >= Defs.Size())\n    Defs.Add(false);\n  Defs[index] = defined;\n  if (!defined)\n    return;\n  while (index >= Vals.Size())\n    Vals.Add(0);\n  Vals[index] = value;\n}\n\nvoid CUInt64DefVector::SetItem(unsigned index, bool defined, UInt64 value)\n{\n  while (index >= Defs.Size())\n    Defs.Add(false);\n  Defs[index] = defined;\n  if (!defined)\n    return;\n  while (index >= Vals.Size())\n    Vals.Add(0);\n  Vals[index] = value;\n}\n\nvoid CArchiveDatabaseOut::AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name)\n{\n  unsigned index = Files.Size();\n  CTime.SetItem(index, file2.CTimeDefined, file2.CTime);\n  ATime.SetItem(index, file2.ATimeDefined, file2.ATime);\n  MTime.SetItem(index, file2.MTimeDefined, file2.MTime);\n  StartPos.SetItem(index, file2.StartPosDefined, file2.StartPos);\n  Attrib.SetItem(index, file2.AttribDefined, file2.Attrib);\n  SetItem_Anti(index, file2.IsAnti);\n  // SetItem_Aux(index, file2.IsAux);\n  Names.Add(name);\n  Files.Add(file);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zOut.h",
    "content": "﻿// 7zOut.h\n\n#ifndef ZIP7_INC_7Z_OUT_H\n#define ZIP7_INC_7Z_OUT_H\n\n#include \"7zCompressionMode.h\"\n#include \"7zEncode.h\"\n#include \"7zHeader.h\"\n#include \"7zItem.h\"\n\n#include \"../../Common/OutBuffer.h\"\n#include \"../../Common/StreamUtils.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nconst unsigned k_StartHeadersRewriteSize = 32;\n\nclass CWriteBufferLoc\n{\n  Byte *_data;\n  Byte *_dataLim;\n  Byte *_dataBase;\npublic:\n  // CWriteBufferLoc(): _data(NULL), _dataLim(NULL), _dataBase(NULL) {}\n  void Init(Byte *data, size_t size)\n  {\n    _data = data;\n    _dataBase = data;\n    _dataLim = data + size;\n  }\n  \n  Byte *GetDest_and_Update(size_t size)\n  {\n    Byte *dest = _data;\n    if (size > (size_t)(_dataLim - dest))\n      throw 1;\n    _data = dest + size;\n    return dest;\n  }\n  void WriteBytes(const void *data, size_t size)\n  {\n    if (size == 0)\n      return;\n    Byte *dest = GetDest_and_Update(size);\n    memcpy(dest, data, size);\n  }\n  void WriteByte(Byte b)\n  {\n    Byte *dest = _data;\n    if (dest == _dataLim)\n      throw 1;\n    *dest++ = b;\n    _data = dest;\n  }\n  size_t GetPos() const { return (size_t)(_data - _dataBase); }\n};\n\n\nstruct CHeaderOptions\n{\n  bool CompressMainHeader;\n  /*\n  bool WriteCTime;\n  bool WriteATime;\n  bool WriteMTime;\n  */\n\n  CHeaderOptions():\n      CompressMainHeader(true)\n      /*\n      , WriteCTime(false)\n      , WriteATime(false)\n      , WriteMTime(true)\n      */\n      {}\n};\n\n\nstruct CFileItem2\n{\n  UInt64 CTime;\n  UInt64 ATime;\n  UInt64 MTime;\n  UInt64 StartPos;\n  UInt32 Attrib;\n\n  bool CTimeDefined;\n  bool ATimeDefined;\n  bool MTimeDefined;\n  bool StartPosDefined;\n  bool AttribDefined;\n  bool IsAnti;\n  // bool IsAux;\n\n  /*\n  void Init()\n  {\n    CTimeDefined = false;\n    ATimeDefined = false;\n    MTimeDefined = false;\n    StartPosDefined = false;\n    AttribDefined = false;\n    IsAnti = false;\n    // IsAux = false;\n  }\n  */\n};\n\n\nstruct COutFolders\n{\n  CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only.\n\n  CRecordVector<CNum> NumUnpackStreamsVector;\n  CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders\n\n  void OutFoldersClear()\n  {\n    FolderUnpackCRCs.Clear();\n    NumUnpackStreamsVector.Clear();\n    CoderUnpackSizes.Clear();\n  }\n\n  void OutFoldersReserveDown()\n  {\n    FolderUnpackCRCs.ReserveDown();\n    NumUnpackStreamsVector.ReserveDown();\n    CoderUnpackSizes.ReserveDown();\n  }\n};\n\n\nstruct CArchiveDatabaseOut: public COutFolders\n{\n  CRecordVector<UInt64> PackSizes;\n  CUInt32DefVector PackCRCs;\n  CObjectVector<CFolder> Folders;\n\n  CRecordVector<CFileItem> Files;\n  UStringVector Names;\n  CUInt64DefVector CTime;\n  CUInt64DefVector ATime;\n  CUInt64DefVector MTime;\n  CUInt64DefVector StartPos;\n  CUInt32DefVector Attrib;\n  CBoolVector IsAnti;\n\n  /*\n  CBoolVector IsAux;\n\n  CByteBuffer SecureBuf;\n  CRecordVector<UInt32> SecureSizes;\n  CRecordVector<UInt32> SecureIDs;\n\n  void ClearSecure()\n  {\n    SecureBuf.Free();\n    SecureSizes.Clear();\n    SecureIDs.Clear();\n  }\n  */\n\n  void Clear()\n  {\n    OutFoldersClear();\n\n    PackSizes.Clear();\n    PackCRCs.Clear();\n    Folders.Clear();\n  \n    Files.Clear();\n    Names.Clear();\n    CTime.Clear();\n    ATime.Clear();\n    MTime.Clear();\n    StartPos.Clear();\n    Attrib.Clear();\n    IsAnti.Clear();\n\n    /*\n    IsAux.Clear();\n    ClearSecure();\n    */\n  }\n\n  void ReserveDown()\n  {\n    OutFoldersReserveDown();\n\n    PackSizes.ReserveDown();\n    PackCRCs.ReserveDown();\n    Folders.ReserveDown();\n    \n    Files.ReserveDown();\n    Names.ReserveDown();\n    CTime.ReserveDown();\n    ATime.ReserveDown();\n    MTime.ReserveDown();\n    StartPos.ReserveDown();\n    Attrib.ReserveDown();\n    IsAnti.ReserveDown();\n\n    /*\n    IsAux.ReserveDown();\n    */\n  }\n\n  bool IsEmpty() const\n  {\n    return (\n      PackSizes.IsEmpty() &&\n      NumUnpackStreamsVector.IsEmpty() &&\n      Folders.IsEmpty() &&\n      Files.IsEmpty());\n  }\n\n  bool CheckNumFiles() const\n  {\n    unsigned size = Files.Size();\n    return (\n           CTime.CheckSize(size)\n        && ATime.CheckSize(size)\n        && MTime.CheckSize(size)\n        && StartPos.CheckSize(size)\n        && Attrib.CheckSize(size)\n        && (size == IsAnti.Size() || IsAnti.Size() == 0));\n  }\n\n  bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); }\n  // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); }\n\n  void SetItem_Anti(unsigned index, bool isAnti)\n  {\n    while (index >= IsAnti.Size())\n      IsAnti.Add(false);\n    IsAnti[index] = isAnti;\n  }\n  /*\n  void SetItem_Aux(unsigned index, bool isAux)\n  {\n    while (index >= IsAux.Size())\n      IsAux.Add(false);\n    IsAux[index] = isAux;\n  }\n  */\n\n  void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name);\n};\n\n\nclass COutArchive\n{\n  HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); }\n  \n  UInt64 GetPos() const;\n  void WriteBytes(const void *data, size_t size);\n  void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); }\n  void WriteByte(Byte b);\n  void WriteByte_ToStream(Byte b)\n  {\n    _outByte.WriteByte(b);\n    // _crc = CRC_UPDATE_BYTE(_crc, b);\n  }\n  // void WriteUInt32(UInt32 value);\n  // void WriteUInt64(UInt64 value);\n  void WriteNumber(UInt64 value);\n  void WriteID(UInt64 value) { WriteNumber(value); }\n\n  void WriteFolder(const CFolder &folder);\n  HRESULT WriteFileHeader(const CFileItem &itemInfo);\n  void Write_BoolVector(const CBoolVector &boolVector);\n  void Write_BoolVector_numDefined(const CBoolVector &boolVector, unsigned numDefined);\n  void WritePropBoolVector(Byte id, const CBoolVector &boolVector);\n\n  void WriteHashDigests(const CUInt32DefVector &digests);\n\n  void WritePackInfo(\n      UInt64 dataOffset,\n      const CRecordVector<UInt64> &packSizes,\n      const CUInt32DefVector &packCRCs);\n\n  void WriteUnpackInfo(\n      const CObjectVector<CFolder> &folders,\n      const COutFolders &outFolders);\n\n  void WriteSubStreamsInfo(\n      const CObjectVector<CFolder> &folders,\n      const COutFolders &outFolders,\n      const CRecordVector<UInt64> &unpackSizes,\n      const CUInt32DefVector &digests);\n\n  void SkipToAligned(unsigned pos, unsigned alignShifts);\n  void WriteAlignedBools(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSizeShifts);\n  void Write_UInt32DefVector_numDefined(const CUInt32DefVector &v, unsigned numDefined);\n  void Write_UInt64DefVector_type(const CUInt64DefVector &v, Byte type);\n\n  HRESULT EncodeStream(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      CEncoder &encoder, const CByteBuffer &data,\n      CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders);\n  void WriteHeader(\n      const CArchiveDatabaseOut &db,\n      // const CHeaderOptions &headerOptions,\n      UInt64 &headerOffset);\n  \n  bool _countMode;\n  bool _writeToStream;\n  bool _useAlign;\n  #ifdef Z7_7Z_VOL\n  bool _endMarker;\n  #endif\n  // UInt32 _crc;\n  size_t _countSize;\n  CWriteBufferLoc _outByte2;\n  COutBuffer _outByte;\n  UInt64 _signatureHeaderPos;\n  CMyComPtr<IOutStream> Stream;\n\n  #ifdef Z7_7Z_VOL\n  HRESULT WriteFinishSignature();\n  HRESULT WriteFinishHeader(const CFinishHeader &h);\n  #endif\n  HRESULT WriteStartHeader(const CStartHeader &h);\n\npublic:\n  CMyComPtr<ISequentialOutStream> SeqStream;\n\n  // COutArchive();\n  HRESULT Create_and_WriteStartPrefix(ISequentialOutStream *stream /* , bool endMarker */);\n  void Close();\n  HRESULT WriteDatabase(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      const CArchiveDatabaseOut &db,\n      const CCompressionMethodMode *options,\n      const CHeaderOptions &headerOptions);\n\n  #ifdef Z7_7Z_VOL\n  static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);\n  static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);\n  #endif\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zProperties.cpp",
    "content": "﻿// 7zProperties.cpp\n\n#include \"StdAfx.h\"\n\n#include \"7zHandler.h\"\n#include \"7zProperties.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nstruct CPropMap\n{\n  Byte FilePropID;\n  // CStatProp StatProp;\n  VARTYPE vt;\n  UInt32 StatPropID;\n};\n\n// #define STAT_PROP(name, id, vt)  { name, id, vt }\n#define STAT_PROP(name, id, vt)  vt, id\n\n#define STAT_PROP2(id, vt) STAT_PROP(NULL, id, vt)\n\n#define k_7z_id_Encrypted    97\n#define k_7z_id_Method       98\n#define k_7z_id_Block        99\n\nstatic const CPropMap kPropMap[] =\n{\n  { NID::kName, STAT_PROP2(kpidPath, VT_BSTR) },\n  { NID::kSize, STAT_PROP2(kpidSize, VT_UI8) },\n  { NID::kPackInfo, STAT_PROP2(kpidPackSize, VT_UI8) },\n  \n  #ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES\n#define k_7z_id_PackedSize0 100\n  { k_7z_id_PackedSize0 + 0, STAT_PROP(\"Pack0\", kpidPackedSize0, VT_UI8) },\n  { k_7z_id_PackedSize0 + 1, STAT_PROP(\"Pack1\", kpidPackedSize1, VT_UI8) },\n  { k_7z_id_PackedSize0 + 2, STAT_PROP(\"Pack2\", kpidPackedSize2, VT_UI8) },\n  { k_7z_id_PackedSize0 + 3, STAT_PROP(\"Pack3\", kpidPackedSize3, VT_UI8) },\n  { k_7z_id_PackedSize0 + 4, STAT_PROP(\"Pack4\", kpidPackedSize4, VT_UI8) },\n  #endif\n\n  { NID::kCTime, STAT_PROP2(kpidCTime, VT_FILETIME) },\n  { NID::kMTime, STAT_PROP2(kpidMTime, VT_FILETIME) },\n  { NID::kATime, STAT_PROP2(kpidATime, VT_FILETIME) },\n  { NID::kWinAttrib, STAT_PROP2(kpidAttrib, VT_UI4) },\n  { NID::kStartPos, STAT_PROP2(kpidPosition, VT_UI8) },\n\n  { NID::kCRC, STAT_PROP2(kpidCRC, VT_UI4) },\n  // { NID::kIsAux, STAT_PROP2(kpidIsAux, VT_BOOL) },\n  { NID::kAnti, STAT_PROP2(kpidIsAnti, VT_BOOL) }\n\n  #ifndef Z7_SFX\n  , { k_7z_id_Encrypted, STAT_PROP2(kpidEncrypted, VT_BOOL) }\n  , { k_7z_id_Method,    STAT_PROP2(kpidMethod, VT_BSTR) }\n  , { k_7z_id_Block,     STAT_PROP2(kpidBlock, VT_UI4) }\n  #endif\n};\n\nstatic void CopyOneItem(CRecordVector<UInt64> &src,\n    CRecordVector<UInt64> &dest, const UInt32 item)\n{\n  FOR_VECTOR (i, src)\n    if (src[i] == item)\n    {\n      dest.Add(item);\n      src.Delete(i);\n      return;\n    }\n}\n\nstatic void RemoveOneItem(CRecordVector<UInt64> &src, const UInt32 item)\n{\n  FOR_VECTOR (i, src)\n    if (src[i] == item)\n    {\n      src.Delete(i);\n      return;\n    }\n}\n\nstatic void InsertToHead(CRecordVector<UInt64> &dest, const UInt32 item)\n{\n  FOR_VECTOR (i, dest)\n    if (dest[i] == item)\n    {\n      dest.Delete(i);\n      break;\n    }\n  dest.Insert(0, item);\n}\n\n#define COPY_ONE_ITEM(id) CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::id);\n\nvoid CHandler::FillPopIDs()\n{\n  _fileInfoPopIDs.Clear();\n\n  #ifdef Z7_7Z_VOL\n  if (_volumes.Size() < 1)\n    return;\n  const CVolume &volume = _volumes.Front();\n  const CArchiveDatabaseEx &_db = volume.Database;\n  #endif\n\n  CRecordVector<UInt64> fileInfoPopIDs = _db.ArcInfo.FileInfoPopIDs;\n\n  RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);\n  RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);\n  /*\n  RemoveOneItem(fileInfoPopIDs, NID::kParent);\n  RemoveOneItem(fileInfoPopIDs, NID::kNtSecure);\n  */\n\n  COPY_ONE_ITEM(kName)\n  COPY_ONE_ITEM(kAnti)\n  COPY_ONE_ITEM(kSize)\n  COPY_ONE_ITEM(kPackInfo)\n  COPY_ONE_ITEM(kCTime)\n  COPY_ONE_ITEM(kMTime)\n  COPY_ONE_ITEM(kATime)\n  COPY_ONE_ITEM(kWinAttrib)\n  COPY_ONE_ITEM(kCRC)\n  COPY_ONE_ITEM(kComment)\n\n  _fileInfoPopIDs += fileInfoPopIDs;\n \n  #ifndef Z7_SFX\n  _fileInfoPopIDs.Add(k_7z_id_Encrypted);\n  _fileInfoPopIDs.Add(k_7z_id_Method);\n  _fileInfoPopIDs.Add(k_7z_id_Block);\n  #endif\n\n  #ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES\n  for (unsigned i = 0; i < 5; i++)\n    _fileInfoPopIDs.Add(k_7z_id_PackedSize0 + i);\n  #endif\n\n  #ifndef Z7_SFX\n  InsertToHead(_fileInfoPopIDs, NID::kMTime);\n  InsertToHead(_fileInfoPopIDs, NID::kPackInfo);\n  InsertToHead(_fileInfoPopIDs, NID::kSize);\n  InsertToHead(_fileInfoPopIDs, NID::kName);\n  #endif\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfProperties(UInt32 *numProps))\n{\n  *numProps = _fileInfoPopIDs.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType))\n{\n  if (index >= _fileInfoPopIDs.Size())\n    return E_INVALIDARG;\n  const UInt64 id = _fileInfoPopIDs[index];\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPropMap); i++)\n  {\n    const CPropMap &pr = kPropMap[i];\n    if (pr.FilePropID == id)\n    {\n      *propID = pr.StatPropID;\n      *varType = pr.vt;\n      /*\n      const CStatProp &st = pr.StatProp;\n      *propID = st.PropID;\n      *varType = st.vt;\n      */\n      /*\n      if (st.lpwstrName)\n        *name = ::SysAllocString(st.lpwstrName);\n      else\n      */\n        *name = NULL;\n      return S_OK;\n    }\n  }\n  return E_INVALIDARG;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zProperties.h",
    "content": "﻿// 7zProperties.h\n\n#ifndef ZIP7_INC_7Z_PROPERTIES_H\n#define ZIP7_INC_7Z_PROPERTIES_H\n\n#include \"../../PropID.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\n// #define Z7_7Z_SHOW_PACK_STREAMS_SIZES // for debug\n\n#ifdef Z7_7Z_SHOW_PACK_STREAMS_SIZES\nenum\n{\n  kpidPackedSize0 = kpidUserDefined,\n  kpidPackedSize1,\n  kpidPackedSize2,\n  kpidPackedSize3,\n  kpidPackedSize4\n};\n#endif\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zRegister.cpp",
    "content": "﻿// 7zRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/RegisterArc.h\"\n\n#include \"7zHandler.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\nstatic Byte k_Signature_Dec[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};\n\nREGISTER_ARC_IO_DECREMENT_SIG(\n  \"7z\", \"7z\", NULL, 7,\n  k_Signature_Dec,\n  0,\n    NArcInfoFlags::kFindSignature\n  | NArcInfoFlags::kCTime\n  | NArcInfoFlags::kATime\n  | NArcInfoFlags::kMTime\n  | NArcInfoFlags::kMTime_Default\n  , TIME_PREC_TO_ARC_FLAGS_MASK(NFileTimeType::kWindows)\n  | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(NFileTimeType::kWindows)\n  , NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zSpecStream.h",
    "content": "﻿// 7zSpecStream.h\n\n#ifndef ZIP7_INC_7Z_SPEC_STREAM_H\n#define ZIP7_INC_7Z_SPEC_STREAM_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../ICoder.h\"\n\n/*\n#define Z7_COM_QI_ENTRY_AG_2(i, sub0, sub) else if (iid == IID_ ## i) \\\n  { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \\\n    { i *ti = this;  *outObject = ti; }  }\n\nclass CSequentialInStreamSizeCount2 Z7_final:\n  public ISequentialInStream,\n  public ICompressGetSubStreamSize,\n  public ICompressInSubStreams,\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ISequentialInStream)\n    Z7_COM_QI_ENTRY(ICompressGetSubStreamSize)\n    Z7_COM_QI_ENTRY_AG_2(ISequentialInStream, _stream, _compressGetSubStreamSize)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n  Z7_IFACE_COM7_IMP(ICompressGetSubStreamSize)\n  Z7_IFACE_COM7_IMP(ICompressInSubStreams)\n\n  CMyComPtr<ISequentialInStream> _stream;\n  CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;\n  CMyComPtr<ICompressInSubStreams> _compressGetSubStreamSize;\n  UInt64 _size;\npublic:\n  void Init(ISequentialInStream *stream)\n  {\n    _size = 0;\n    _getSubStreamSize.Release();\n    _compressGetSubStreamSize.Release();\n    _stream = stream;\n    _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);\n    _stream.QueryInterface(IID_ICompressInSubStreams, &_compressGetSubStreamSize);\n  }\n  UInt64 GetSize() const { return _size; }\n};\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zUpdate.cpp",
    "content": "﻿// 7zUpdate.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/StringToInt.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"7zDecode.h\"\n#include \"7zEncode.h\"\n#include \"7zFolderInStream.h\"\n#include \"7zHandler.h\"\n#include \"7zOut.h\"\n#include \"7zUpdate.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\n#define k_X86 k_BCJ\n\nstruct CFilterMode\n{\n  UInt32 Id;\n  UInt32 Delta;  // required File Size alignment, if Id is not k_Delta.\n                 // (Delta == 0) means unknown alignment\n  UInt32 Offset; // for k_ARM64 / k_RISCV\n  // UInt32 AlignSizeOpt; // for k_ARM64\n\n  CFilterMode():\n    Id(0),\n    Delta(0),\n    Offset(0)\n    // , AlignSizeOpt(0)\n    {}\n\n  void ClearFilterMode()\n  {\n    Id = 0;\n    Delta = 0;\n    Offset = 0;\n    // AlignSizeOpt = 0;\n  }\n\n  // it sets Delta as Align value, if Id is exe filter\n  // in another cases it sets Delta = 0, that\n  void SetDelta()\n  {\n    if (Id == k_IA64)\n      Delta = 16;\n    else if (Id == k_ARM64 || Id == k_ARM || Id == k_PPC || Id == k_SPARC)\n      Delta = 4;\n    else if (Id == k_ARMT || Id == k_RISCV)\n      Delta = 2;\n    else if (Id == k_BCJ || Id == k_BCJ2)\n      Delta = 1; // do we need it?\n    else\n      Delta = 0;\n  }\n};\n\n\n/* ---------- PE ---------- */\n\n#define MZ_SIG 0x5A4D\n\n#define PE_SIG 0x00004550\n#define PE_OptHeader_Magic_32 0x10B\n#define PE_OptHeader_Magic_64 0x20B\n// #define PE_SectHeaderSize 40\n// #define PE_SECT_EXECUTE 0x20000000\n\nstatic int Parse_EXE(const Byte *buf, size_t size, CFilterMode *filterMode)\n{\n  if (size < 512 || GetUi16(buf) != MZ_SIG)\n    return 0;\n\n  const Byte *p;\n  UInt32 peOffset, optHeaderSize, filterId;\n\n  peOffset = GetUi32(buf + 0x3C);\n  if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)\n    return 0;\n  p = buf + peOffset;\n  if (GetUi32(p) != PE_SIG)\n    return 0;\n  p += 4;\n  \n  const unsigned machine = GetUi16(p);\n\n  switch (machine)\n  {\n    case 0x014C:\n    case 0x8664:  filterId = k_X86; break;\n    case 0xAA64:  filterId = k_ARM64; break;\n    \n    /*\n    IMAGE_FILE_MACHINE_ARM   0x01C0  // ARM LE\n    IMAGE_FILE_MACHINE_THUMB 0x01C2  // ARM Thumb / Thumb-2 LE\n    IMAGE_FILE_MACHINE_ARMNT 0x01C4  // ARM Thumb-2, LE\n    Note: We use ARM filter for 0x01C2. (WinCE 5 - 0x01C2) files mostly contain ARM code (not Thumb/Thumb-2).\n    */\n\n    case 0x01C0:                            // WinCE old\n    case 0x01C2:  filterId = k_ARM; break;  // WinCE new\n    case 0x01C4:  filterId = k_ARMT; break; // WinRT\n\n    case 0x5032:  // RISCV32\n    case 0x5064:  // RISCV64\n    // case 0x5128:  // RISCV128\n                  filterId = k_RISCV; break;\n\n    case 0x0200:  filterId = k_IA64; break;\n    default:  return 0;\n  }\n\n  const UInt32 numSections = GetUi16(p + 2);\n  optHeaderSize = GetUi16(p + 16);\n  if (optHeaderSize > (1 << 10))\n    return 0;\n\n  p += 20; /* headerSize */\n\n  switch (GetUi16(p))\n  {\n    case PE_OptHeader_Magic_32:\n    case PE_OptHeader_Magic_64:\n      break;\n    default:\n      return 0;\n  }\n\n    // Windows exe file sizes are not aligned for 4 KiB.\n    // So we can't use (CFilterMode::Offset != 0) in solid archives.\n    // So we just don't set Offset here.\n#define NUM_SCAN_SECTIONS_MAX (1 << 6)\n// #define EXE_SECTION_OFFSET_MAX (1 << 27)\n// #define EXE_SECTION_SIZE_MIN (1 << 8)\n// #define EXE_SECTION_SIZE_MAX (1 << 27)\n#define PE_SectHeaderSize 40\n// #define PE_SECT_EXECUTE 0x20000000\n\n/*\n  if (numSections > NUM_SCAN_SECTIONS_MAX)\n    return 0;\n*/\n\n  if ((size_t)(p - buf) + optHeaderSize <= size)\n  {\n  p += optHeaderSize;\n/*\n  // UInt32 numExeSections = 0;\n  // bool execute_finded = false;\n  // UInt32 sect_va = 0;\n  // UInt32 sect_size = 0;\n  // UInt32 sect_offset = 0;\n*/\n  if (numSections <= NUM_SCAN_SECTIONS_MAX)\n  if (machine == 0x8664)\n  for (UInt32 i = 0; i < numSections\n        ; i++, p += PE_SectHeaderSize)\n  {\n    // UInt32 characts, rawSize, offset;\n    if ((UInt32)(p - buf) + PE_SectHeaderSize > size)\n    {\n      // return 0;\n      break;\n    }\n    if (memcmp(p, \".a64xrm\", 8) == 0)\n    {\n      // ARM64EC\n      filterId = k_ARM64;\n      break;\n    }\n/*\n    rawSize = GetUi32(p + 16);\n    offset = GetUi32(p + 20);\n    characts = GetUi32(p + 36);\n    if (rawSize >= EXE_SECTION_SIZE_MIN &&\n        rawSize <= EXE_SECTION_SIZE_MAX &&\n        offset <= EXE_SECTION_OFFSET_MAX &&\n        // offset < limit &&\n        offset > 0)\n    {\n      if ((characts & PE_SECT_EXECUTE) != 0)\n      {\n        // execute_finded = true;\n        // sect_va = GetUi32(p + 12);\n        // sect_size = rawSize;\n        // sect_offset = offset;\n        break;\n      }\n    }\n*/\n  }\n  }\n\n  /*\n  filterMode->Offset = 0;\n  if (filterId == k_ARM64)\n  {\n    // filterMode->AlignSizeOpt = (1 << 12);\n    // const UInt32 offs = (sect_va - sect_offset) & 0xFFF;\n    // if (offs != 0)\n    // filterMode->Offset = offs; // change it\n  }\n  */\n  filterMode->Id = filterId;\n  return 1;\n}\n\n\n/*\n  Filters don't improve the compression ratio for relocatable object files (\".o\").\n  But we can get compression ratio gain, if we compress object\n  files and executables in same solid block.\n  So we use filters for relocatable object files (\".o\"):\n*/\n// #define Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ\n\n/* ---------- ELF ---------- */\n\n#define ELF_SIG 0x464C457F\n\n#define ELF_CLASS_32  1\n#define ELF_CLASS_64  2\n\n#define ELF_DATA_2LSB 1\n#define ELF_DATA_2MSB 2\n\nstatic UInt16 Get16(const Byte *p, BoolInt be) { if (be) return (UInt16)GetBe16(p); return (UInt16)GetUi16(p); }\nstatic UInt32 Get32(const Byte *p, BoolInt be) { if (be) return GetBe32(p); return GetUi32(p); }\n// static UInt64 Get64(const Byte *p, BoolInt be) { if (be) return GetBe64(p); return GetUi64(p); }\n\nstatic int Parse_ELF(const Byte *buf, size_t size, CFilterMode *filterMode)\n{\n  BoolInt /* is32, */ be;\n  UInt32 filterId;\n\n  if (size < 512 || buf[6] != 1) /* ver */\n    return 0;\n\n  if (GetUi32(buf) != ELF_SIG)\n    return 0;\n\n  switch (buf[4])\n  {\n    case ELF_CLASS_32: /* is32 = True; */ break;\n    case ELF_CLASS_64: /* is32 = False; */ break;\n    default: return 0;\n  }\n\n  switch (buf[5])\n  {\n    case ELF_DATA_2LSB: be = False; break;\n    case ELF_DATA_2MSB: be = True; break;\n    default: return 0;\n  }\n\n#ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ\n#define ELF_ET_REL  1\n  if (Get16(buf + 0x10, be) == ELF_ET_REL)\n    return 0;\n#endif\n\n  switch (Get16(buf + 0x12, be))\n  {\n    case 3:\n    case 6:\n    case 62: filterId = k_X86; break;\n    case 2:\n    case 18:\n    case 43: filterId = k_SPARC; break;\n    case 20:\n    case 21: if (!be) return 0; filterId = k_PPC; break;\n    case 40:  if (be) return 0; filterId = k_ARM; break;\n    case 183: if (be) return 0; filterId = k_ARM64; break;\n    case 243: if (be) return 0; filterId = k_RISCV; break;\n\n    /* Some IA-64 ELF executables have size that is not aligned for 16 bytes.\n       So we don't use IA-64 filter for IA-64 ELF */\n    // case 50: if ( be) return 0; filterId = k_IA64; break;\n\n    default: return 0;\n  }\n\n  filterMode->Id = filterId;\n  return 1;\n}\n\n\n\n/* ---------- Mach-O ---------- */\n\n#define MACH_SIG_BE_32 0xCEFAEDFE\n#define MACH_SIG_BE_64 0xCFFAEDFE\n#define MACH_SIG_LE_32 0xFEEDFACE\n#define MACH_SIG_LE_64 0xFEEDFACF\n\n#define MACH_ARCH_ABI64 (1 << 24)\n#define MACH_MACHINE_386 7\n#define MACH_MACHINE_ARM 12\n#define MACH_MACHINE_SPARC 14\n#define MACH_MACHINE_PPC 18\n#define MACH_MACHINE_PPC64 (MACH_ARCH_ABI64 | MACH_MACHINE_PPC)\n#define MACH_MACHINE_AMD64 (MACH_ARCH_ABI64 | MACH_MACHINE_386)\n#define MACH_MACHINE_ARM64 (MACH_ARCH_ABI64 | MACH_MACHINE_ARM)\n\nstatic unsigned Parse_MACH(const Byte *buf, size_t size, CFilterMode *filterMode)\n{\n  UInt32 filterId, numCommands, commandsSize;\n\n  if (size < 512)\n    return 0;\n\n  BoolInt /* mode64, */ be;\n  switch (GetUi32(buf))\n  {\n    case MACH_SIG_BE_32: /* mode64 = False; */ be = True; break;\n    case MACH_SIG_BE_64: /* mode64 = True;  */ be = True; break;\n    case MACH_SIG_LE_32: /* mode64 = False; */ be = False; break;\n    case MACH_SIG_LE_64: /* mode64 = True;  */ be = False; break;\n    default: return 0;\n  }\n\n#ifdef Z7_7Z_CREATE_ARC_DISABLE_FILTER_FOR_OBJ\n#define MACH_TYPE_OBJECT 1\n  if (Get32(buf + 0xC, be) == MACH_TYPE_OBJECT)\n      return 0;\n#endif\n\n  switch (Get32(buf + 4, be))\n  {\n    case MACH_MACHINE_386:\n    case MACH_MACHINE_AMD64: filterId = k_X86; break;\n    case MACH_MACHINE_ARM:   if ( be) return 0; filterId = k_ARM; break;\n    case MACH_MACHINE_SPARC: if (!be) return 0; filterId = k_SPARC; break;\n    case MACH_MACHINE_PPC:\n    case MACH_MACHINE_PPC64: if (!be) return 0; filterId = k_PPC; break;\n    case MACH_MACHINE_ARM64: if ( be) return 0; filterId = k_ARM64; break;\n    default: return 0;\n  }\n\n  numCommands = Get32(buf + 0x10, be);\n  commandsSize = Get32(buf + 0x14, be);\n\n  if (commandsSize > (1 << 24) || numCommands > (1 << 18))\n    return 0;\n\n  filterMode->Id = filterId;\n  return 1;\n}\n\n\n/* ---------- WAV ---------- */\n\n#define WAV_SUBCHUNK_fmt  0x20746D66\n#define WAV_SUBCHUNK_data 0x61746164\n\n#define RIFF_SIG 0x46464952\n\nstatic BoolInt Parse_WAV(const Byte *buf, size_t size, CFilterMode *filterMode)\n{\n  UInt32 subChunkSize, pos;\n  if (size < 0x2C)\n    return False;\n\n  if (GetUi32(buf + 0) != RIFF_SIG ||\n      GetUi32(buf + 8) != 0x45564157 || // WAVE\n      GetUi32(buf + 0xC) != WAV_SUBCHUNK_fmt)\n    return False;\n  subChunkSize = GetUi32(buf + 0x10);\n  /* [0x14 = format] = 1 (PCM) */\n  if (subChunkSize < 0x10 || subChunkSize > 0x12 || GetUi16(buf + 0x14) != 1)\n    return False;\n  \n  const unsigned numChannels = GetUi16(buf + 0x16);\n  const unsigned bitsPerSample = GetUi16(buf + 0x22);\n  if ((bitsPerSample & 0x7) != 0)\n    return False;\n  const UInt32 delta = (UInt32)numChannels * (bitsPerSample >> 3);\n  if (delta == 0 || delta > 256)\n    return False;\n\n  pos = 0x14 + subChunkSize;\n\n  const int kNumSubChunksTests = 10;\n  // Do we need to scan more than 3 sub-chunks?\n  for (int i = 0; i < kNumSubChunksTests; i++)\n  {\n    if (pos + 8 > size)\n      return False;\n    subChunkSize = GetUi32(buf + pos + 4);\n    if (GetUi32(buf + pos) == WAV_SUBCHUNK_data)\n    {\n      filterMode->Id = k_Delta;\n      filterMode->Delta = delta;\n      return True;\n    }\n    if (subChunkSize > (1 << 16))\n      return False;\n    pos += subChunkSize + 8;\n  }\n  return False;\n}\n\n\n/*\n  filterMode->Delta will be set as:\n    = delta value : [1, 256] : for k_Delta\n    = 0 for another filters (branch filters)\n*/\nstatic BoolInt ParseFile(const Byte *buf, size_t size, CFilterMode *filterMode)\n{\n  filterMode->ClearFilterMode();\n\n  if (Parse_EXE(buf, size, filterMode)) return True;\n  if (Parse_ELF(buf, size, filterMode)) return True;\n  if (Parse_MACH(buf, size, filterMode)) return True;\n  return Parse_WAV(buf, size, filterMode);\n}\n\n\n\n\nstruct CFilterMode2: public CFilterMode\n{\n  bool Encrypted;\n  unsigned GroupIndex;\n  \n  CFilterMode2(): Encrypted(false) {}\n\n  int Compare(const CFilterMode2 &m) const\n  {\n    if (!Encrypted)\n    {\n      if (m.Encrypted)\n        return -1;\n    }\n    else if (!m.Encrypted)\n      return 1;\n    \n    const UInt32 id1 = Id;\n    const UInt32 id2 = m.Id;\n    /*\n    // we can change the order to place k_ARM64 files close to another exe files\n    if (id1 <= k_SPARC &&\n        id2 <= k_SPARC)\n    {\n      #define k_ARM64_FOR_SORT 0x3030901\n      if (id1 == k_ARM64) id1 = k_ARM64_FOR_SORT;\n      if (id2 == k_ARM64) id2 = k_ARM64_FOR_SORT;\n    }\n    */\n    if (id1 < id2) return -1;\n    if (id1 > id2) return 1;\n\n    if (Delta < m.Delta) return -1;\n    if (Delta > m.Delta) return 1;\n\n    if (Offset < m.Offset) return -1;\n    if (Offset > m.Offset) return 1;\n\n    /* we don't go here, because GetGroup()\n       and operator ==(const CFilterMode2 &m)\n       add only unique CFilterMode2:: { Id, Delta, Offset, Encrypted } items.\n    */\n    /*\n    if (GroupIndex < m.GroupIndex) return -1;\n    if (GroupIndex > m.GroupIndex) return 1;\n    */\n    return 0;\n  }\n  \n  bool operator ==(const CFilterMode2 &m) const\n  {\n    return Id == m.Id\n        && Delta == m.Delta\n        && Offset == m.Offset\n        && Encrypted == m.Encrypted;\n  }\n};\n\nstatic unsigned GetGroup(CRecordVector<CFilterMode2> &filters, const CFilterMode2 &m)\n{\n  unsigned i;\n  for (i = 0; i < filters.Size(); i++)\n  {\n    const CFilterMode2 &m2 = filters[i];\n    if (m == m2)\n      return i;\n    /*\n    if (m.Encrypted != m2.Encrypted)\n    {\n      if (!m.Encrypted)\n        break;\n      continue;\n    }\n    \n    if (m.Id < m2.Id)  break;\n    if (m.Id != m2.Id) continue;\n\n    if (m.Delta < m2.Delta) break;\n    if (m.Delta != m2.Delta) continue;\n    */\n  }\n  // filters.Insert(i, m);\n  // return i;\n  return filters.Add(m);\n}\n\nstatic inline bool Is86Filter(CMethodId m)\n{\n  return (m == k_BCJ || m == k_BCJ2);\n}\n\nstatic inline bool IsExeFilter(CMethodId m)\n{\n  switch (m)\n  {\n    case k_ARM64:\n    case k_RISCV:\n    case k_BCJ:\n    case k_BCJ2:\n    case k_ARM:\n    case k_ARMT:\n    case k_PPC:\n    case k_SPARC:\n    case k_IA64:\n      return true;\n    default: break;\n  }\n  return false;\n}\n\nstatic unsigned Get_FilterGroup_for_Folder(\n    CRecordVector<CFilterMode2> &filters, const CFolderEx &f, bool extractFilter)\n{\n  CFilterMode2 m;\n  // m.Id = 0;\n  // m.Delta = 0;\n  // m.Offset = 0;\n  m.Encrypted = f.IsEncrypted();\n\n  if (extractFilter)\n  {\n    const CCoderInfo &coder = f.Coders[f.UnpackCoder];\n  \n    if (coder.MethodID == k_Delta)\n    {\n      if (coder.Props.Size() == 1)\n      {\n        m.Delta = (unsigned)coder.Props[0] + 1;\n        m.Id = k_Delta;\n      }\n    }\n    else if (IsExeFilter(coder.MethodID))\n    {\n      m.Id = (UInt32)coder.MethodID;\n      if (m.Id == k_BCJ2)\n        m.Id = k_BCJ;\n      m.SetDelta();\n      if (m.Id == k_ARM64 ||\n          m.Id == k_RISCV)\n        if (coder.Props.Size() == 4)\n          m.Offset = GetUi32(coder.Props);\n    }\n  }\n  \n  return GetGroup(filters, m);\n}\n\n\n\n\nstatic HRESULT WriteRange(IInStream *inStream, ISequentialOutStream *outStream,\n    UInt64 position, UInt64 size, ICompressProgressInfo *progress)\n{\n  RINOK(InStream_SeekSet(inStream, position))\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;\n  streamSpec->SetStream(inStream);\n  streamSpec->Init(size);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, progress))\n  return (copyCoder->TotalSize == size ? S_OK : E_FAIL);\n}\n\n/*\nunsigned CUpdateItem::GetExtensionPos() const\n{\n  int slashPos = Name.ReverseFind_PathSepar();\n  int dotPos = Name.ReverseFind_Dot();\n  if (dotPos <= slashPos)\n    return Name.Len();\n  return dotPos + 1;\n}\n\nUString CUpdateItem::GetExtension() const\n{\n  return Name.Ptr(GetExtensionPos());\n}\n*/\n\n#define RINOZ(x) { const int _t_ = (x); if (_t_ != 0) return _t_; }\n\n#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))\n\n/*\nstatic int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)\n{\n  size_t c1 = a1.GetCapacity();\n  size_t c2 = a2.GetCapacity();\n  RINOZ_COMP(c1, c2);\n  for (size_t i = 0; i < c1; i++)\n    RINOZ_COMP(a1[i], a2[i]);\n  return 0;\n}\n\nstatic int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)\n{\n  RINOZ_COMP(c1.NumInStreams, c2.NumInStreams);\n  RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams);\n  RINOZ_COMP(c1.MethodID, c2.MethodID);\n  return CompareBuffers(c1.Props, c2.Props);\n}\n\nstatic int CompareBonds(const CBond &b1, const CBond &b2)\n{\n  RINOZ_COMP(b1.InIndex, b2.InIndex);\n  return MyCompare(b1.OutIndex, b2.OutIndex);\n}\n\nstatic int CompareFolders(const CFolder &f1, const CFolder &f2)\n{\n  int s1 = f1.Coders.Size();\n  int s2 = f2.Coders.Size();\n  RINOZ_COMP(s1, s2);\n  int i;\n  for (i = 0; i < s1; i++)\n    RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));\n  s1 = f1.Bonds.Size();\n  s2 = f2.Bonds.Size();\n  RINOZ_COMP(s1, s2);\n  for (i = 0; i < s1; i++)\n    RINOZ(CompareBonds(f1.Bonds[i], f2.Bonds[i]));\n  return 0;\n}\n*/\n\n/*\nstatic int CompareFiles(const CFileItem &f1, const CFileItem &f2)\n{\n  return CompareFileNames(f1.Name, f2.Name);\n}\n*/\n\nstruct CFolderRepack\n{\n  unsigned FolderIndex;\n  CNum NumCopyFiles;\n};\n\n/*\nstatic int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *)\n{\n  int i1 = p1->FolderIndex;\n  int i2 = p2->FolderIndex;\n  // In that version we don't want to parse folders here, so we don't compare folders\n  // probably it must be improved in future\n  // const CDbEx &db = *(const CDbEx *)param;\n  // RINOZ(CompareFolders(\n  //     db.Folders[i1],\n  //     db.Folders[i2]));\n\n  return MyCompare(i1, i2);\n  \n  // RINOZ_COMP(\n  //     db.NumUnpackStreamsVector[i1],\n  //     db.NumUnpackStreamsVector[i2]);\n  // if (db.NumUnpackStreamsVector[i1] == 0)\n  //   return 0;\n  // return CompareFiles(\n  //     db.Files[db.FolderStartFileIndex[i1]],\n  //     db.Files[db.FolderStartFileIndex[i2]]);\n}\n*/\n\n/*\n  we sort empty files and dirs in such order:\n  - Dir.NonAnti   (name sorted)\n  - File.NonAnti  (name sorted)\n  - File.Anti     (name sorted)\n  - Dir.Anti (reverse name sorted)\n*/\n\nstatic int CompareEmptyItems(const unsigned *p1, const unsigned *p2, void *param)\n{\n  const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;\n  const CUpdateItem &u1 = updateItems[*p1];\n  const CUpdateItem &u2 = updateItems[*p2];\n  // NonAnti < Anti\n  if (u1.IsAnti != u2.IsAnti)\n    return (u1.IsAnti ? 1 : -1);\n  if (u1.IsDir != u2.IsDir)\n  {\n    // Dir.NonAnti < File < Dir.Anti\n    if (u1.IsDir)\n      return (u1.IsAnti ? 1 : -1);\n    return (u2.IsAnti ? -1 : 1);\n  }\n  int n = CompareFileNames(u1.Name, u2.Name);\n  return (u1.IsDir && u1.IsAnti) ? -n : n;\n}\n\nstatic const char * const g_Exts =\n  \" 7z xz lzma ace arc arj bz tbz bz2 tbz2 cab deb gz tgz ha lha lzh lzo lzx pak rar rpm sit zoo\"\n  // **************** 7-Zip ZS Modification Start ****************\n  \" lzma2 liz tliz lz tlz lz4 tlz4 lz5 tlz5 zst tzst zstd tzstd\"\n  // **************** 7-Zip ZS Modification End ****************\n  \" zip jar ear war msi\"\n  \" 3gp avi mov mpeg mpg mpe wmv\"\n  \" aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav\"\n  \" swf\"\n  \" chm hxi hxs\"\n  \" gif jpeg jpg jp2 png tiff  bmp ico psd psp\"\n  \" awg ps eps cgm dxf svg vrml wmf emf ai md\"\n  \" cad dwg pps key sxi\"\n  \" max 3ds\"\n  \" iso bin nrg mdf img pdi tar cpio xpi\"\n  \" vfd vhd vud vmc vsv\"\n  \" vmdk dsk nvram vmem vmsd vmsn vmss vmtm\"\n  \" inl inc idl acf asa\"\n  \" h hpp hxx c cpp cxx m mm go swift\"\n  \" rc java cs rs pas bas vb cls ctl frm dlg def\"\n  \" f77 f f90 f95\"\n  \" asm s\"\n  \" sql manifest dep\"\n  \" mak clw csproj vcproj sln dsp dsw\"\n  \" class\"\n  \" bat cmd bash sh\"\n  \" xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml\"\n  \" awk sed hta js json php php3 php4 php5 phptml pl pm py pyo rb tcl ts vbs\"\n  \" text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf\"\n  \" sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf\"\n  \" abw afp cwk lwp wpd wps wpt wrf wri\"\n  \" abf afm bdf fon mgf otf pcf pfa snf ttf\"\n  \" dbf mdb nsf ntf wdb db fdb gdb\"\n  \" exe dll ocx vbx sfx sys tlb awx com obj lib out o so\"\n  \" pdb pch idb ncb opt\";\n\nstatic unsigned GetExtIndex(const char *ext)\n{\n  unsigned extIndex = 1;\n  const char *p = g_Exts;\n  for (;;)\n  {\n    char c = *p++;\n    if (c == 0)\n      return extIndex;\n    if (c == ' ')\n      continue;\n    unsigned pos = 0;\n    for (;;)\n    {\n      char c2 = ext[pos++];\n      if (c2 == 0 && (c == 0 || c == ' '))\n        return extIndex;\n      if (c != c2)\n        break;\n      c = *p++;\n    }\n    extIndex++;\n    for (;;)\n    {\n      if (c == 0)\n        return extIndex;\n      if (c == ' ')\n        break;\n      c = *p++;\n    }\n  }\n}\n\nstruct CRefItem\n{\n  const CUpdateItem *UpdateItem;\n  UInt32 Index;\n  unsigned ExtensionPos;\n  unsigned NamePos;\n  unsigned ExtensionIndex;\n  \n  CRefItem() {}\n  CRefItem(UInt32 index, const CUpdateItem &ui, bool sortByType):\n    UpdateItem(&ui),\n    Index(index),\n    ExtensionPos(0),\n    NamePos(0),\n    ExtensionIndex(0)\n  {\n    if (sortByType)\n    {\n      const int slashPos = ui.Name.ReverseFind_PathSepar();\n      NamePos = (unsigned)(slashPos + 1);\n      const int dotPos = ui.Name.ReverseFind_Dot();\n      if (dotPos <= slashPos)\n        ExtensionPos = ui.Name.Len();\n      else\n      {\n        ExtensionPos = (unsigned)(dotPos + 1);\n        if (ExtensionPos != ui.Name.Len())\n        {\n          AString s;\n          for (unsigned pos = ExtensionPos;; pos++)\n          {\n            const wchar_t c = ui.Name[pos];\n            if (c >= 0x80)\n              break;\n            if (c == 0)\n            {\n              ExtensionIndex = GetExtIndex(s);\n              break;\n            }\n            s.Add_Char((char)MyCharLower_Ascii((char)c));\n          }\n        }\n      }\n    }\n  }\n};\n\nstruct CSortParam\n{\n  // const CObjectVector<CTreeFolder> *TreeFolders;\n  bool SortByType;\n};\n\n/*\n  we sort files in such order:\n  - Dir.NonAnti   (name sorted)\n  - alt streams\n  - Dirs\n  - Dir.Anti (reverse name sorted)\n*/\n\n\nstatic int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)\n{\n  const CRefItem &a1 = *p1;\n  const CRefItem &a2 = *p2;\n  const CUpdateItem &u1 = *a1.UpdateItem;\n  const CUpdateItem &u2 = *a2.UpdateItem;\n\n  /*\n  if (u1.IsAltStream != u2.IsAltStream)\n    return u1.IsAltStream ? 1 : -1;\n  */\n  \n  // Actually there are no dirs that time. They were stored in other steps\n  // So that code is unused?\n  if (u1.IsDir != u2.IsDir)\n    return u1.IsDir ? 1 : -1;\n  if (u1.IsDir)\n  {\n    if (u1.IsAnti != u2.IsAnti)\n      return (u1.IsAnti ? 1 : -1);\n    int n = CompareFileNames(u1.Name, u2.Name);\n    return -n;\n  }\n  \n  // bool sortByType = *(bool *)param;\n  const CSortParam *sortParam = (const CSortParam *)param;\n  const bool sortByType = sortParam->SortByType;\n  if (sortByType)\n  {\n    RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex)\n    RINOZ(CompareFileNames(u1.Name.Ptr(a1.ExtensionPos), u2.Name.Ptr(a2.ExtensionPos)))\n    RINOZ(CompareFileNames(u1.Name.Ptr(a1.NamePos), u2.Name.Ptr(a2.NamePos)))\n    if (!u1.MTimeDefined && u2.MTimeDefined) return 1;\n    if (u1.MTimeDefined && !u2.MTimeDefined) return -1;\n    if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime)\n    RINOZ_COMP(u1.Size, u2.Size)\n  }\n  /*\n  int par1 = a1.UpdateItem->ParentFolderIndex;\n  int par2 = a2.UpdateItem->ParentFolderIndex;\n  const CTreeFolder &tf1 = (*sortParam->TreeFolders)[par1];\n  const CTreeFolder &tf2 = (*sortParam->TreeFolders)[par2];\n\n  int b1 = tf1.SortIndex, e1 = tf1.SortIndexEnd;\n  int b2 = tf2.SortIndex, e2 = tf2.SortIndexEnd;\n  if (b1 < b2)\n  {\n    if (e1 <= b2)\n      return -1;\n    // p2 in p1\n    int par = par2;\n    for (;;)\n    {\n      const CTreeFolder &tf = (*sortParam->TreeFolders)[par];\n      par = tf.Parent;\n      if (par == par1)\n      {\n        RINOZ(CompareFileNames(u1.Name, tf.Name));\n        break;\n      }\n    }\n  }\n  else if (b2 < b1)\n  {\n    if (e2 <= b1)\n      return 1;\n    // p1 in p2\n    int par = par1;\n    for (;;)\n    {\n      const CTreeFolder &tf = (*sortParam->TreeFolders)[par];\n      par = tf.Parent;\n      if (par == par2)\n      {\n        RINOZ(CompareFileNames(tf.Name, u2.Name));\n        break;\n      }\n    }\n  }\n  */\n  // RINOZ_COMP(a1.UpdateItem->ParentSortIndex, a2.UpdateItem->ParentSortIndex);\n  RINOK(CompareFileNames(u1.Name, u2.Name))\n  RINOZ_COMP(a1.UpdateItem->IndexInClient, a2.UpdateItem->IndexInClient)\n  RINOZ_COMP(a1.UpdateItem->IndexInArchive, a2.UpdateItem->IndexInArchive)\n  return 0;\n}\n\nstruct CSolidGroup\n{\n  CRecordVector<UInt32> Indices;\n\n  CRecordVector<CFolderRepack> folderRefs;\n};\n\nstatic const char * const g_Exe_Exts[] =\n{\n    \"dll\"\n  , \"exe\"\n  , \"ocx\"\n  , \"sfx\"\n  , \"sys\"\n};\n\nstatic const char * const g_ExeUnix_Exts[] =\n{\n    \"so\"\n  , \"dylib\"\n};\n\nstatic bool IsExt_Exe(const wchar_t *ext)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Exe_Exts); i++)\n    if (StringsAreEqualNoCase_Ascii(ext, g_Exe_Exts[i]))\n      return true;\n  return false;\n}\n\n/*\nstatic bool IsExt_ExeUnix(const wchar_t *ext)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++)\n    if (StringsAreEqualNoCase_Ascii(ext, g_ExeUnix_Exts[i]))\n      return true;\n  return false;\n}\n*/\n\n// we try to find \"so\" extension in such name: libstdc++.so.6.0.29\nstatic bool IsExt_ExeUnix_NumericAllowed(const UString &path)\n{\n  unsigned pos = path.Len();\n  unsigned dotPos = pos;\n  for (;;)\n  {\n    if (pos == 0)\n      return false;\n    const wchar_t c = path[--pos];\n    if (IS_PATH_SEPAR(c))\n      return false;\n    if (c == '.')\n    {\n      const unsigned num = (dotPos - pos) - 1;\n      if (num < 1)\n        return false;\n      const wchar_t *cur = path.Ptr(pos + 1);\n      for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExeUnix_Exts); i++)\n      {\n        const char *ext = g_ExeUnix_Exts[i];\n        if (num == MyStringLen(ext))\n          if (IsString1PrefixedByString2_NoCase_Ascii(cur, ext))\n            return true;\n      }\n      const wchar_t *end;\n      ConvertStringToUInt32(cur, &end);\n      if ((size_t)(end - cur) != num)\n        return false;\n      dotPos = pos;\n    }\n  }\n}\n\n\nstruct CAnalysis\n{\n  CMyComPtr<IArchiveUpdateCallbackFile> Callback;\n  CByteBuffer Buffer;\n\n  bool ParseWav;\n  bool ParseExe;\n  bool ParseExeUnix;\n  bool ParseNoExt;\n  bool ParseAll;\n\n  /*\n  bool Need_ATime;\n  bool ATime_Defined;\n  FILETIME ATime;\n  */\n\n  CAnalysis():\n      ParseWav(false),\n      ParseExe(false),\n      ParseExeUnix(false),\n      ParseNoExt(false),\n      ParseAll(false)\n      /*\n      , Need_ATime(false)\n      , ATime_Defined(false)\n      */\n  {}\n\n  HRESULT GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode);\n};\n\nstatic const size_t kAnalysisBufSize = 1 << 14;\n\nHRESULT CAnalysis::GetFilterGroup(UInt32 index, const CUpdateItem &ui, CFilterMode &filterMode)\n{\n  filterMode.Id = 0;\n  filterMode.Delta = 0;\n  filterMode.Offset = 0;\n\n  CFilterMode filterModeTemp = filterMode;\n\n  const int slashPos = ui.Name.ReverseFind_PathSepar();\n  const int dotPos = ui.Name.ReverseFind_Dot();\n\n  // if (dotPos > slashPos)\n  {\n    bool needReadFile = ParseAll;\n    /* if (Callback) is not supported by client,\n       we still try to use file name extension to detect executable file */\n    bool probablyIsSameIsa = false;\n\n    if (!needReadFile || !Callback)\n    {\n      const wchar_t *ext = NULL;\n      if (dotPos > slashPos)\n        ext = ui.Name.Ptr((unsigned)(dotPos + 1));\n      // 7-zip stores posix attributes in high 16 bits and sets (0x8000) flag\n      if (ui.Attrib & 0x8000)\n      {\n        const unsigned st_mode = ui.Attrib >> 16;\n        /* note: executable \".so\" can be without execute permission,\n           and symbolic link to such \".so\" file is possible */\n        // st_mode = 00111; // for debug\n        /* in Linux we expect such permissions:\n             0755 : for most executables\n             0644 : for some \".so\" files\n             0777 : in WSL for all files.\n                    We can try to exclude some such 0777 cases from analysis,\n                    if there is non-executable extension.\n        */\n\n        if ((st_mode & (\n              MY_LIN_S_IXUSR |\n              MY_LIN_S_IXGRP |\n              MY_LIN_S_IXOTH)) != 0\n            && MY_LIN_S_ISREG(st_mode)\n            && (ui.Size >= (1u << 11)))\n        {\n          #ifndef _WIN32\n          probablyIsSameIsa = true;\n          #endif\n          needReadFile = true;\n        }\n      }\n\n      if (!needReadFile)\n      {\n        if (!ext)\n          needReadFile = ParseNoExt;\n        else\n        {\n          bool isUnixExt = false;\n          if (ParseExeUnix)\n            isUnixExt = IsExt_ExeUnix_NumericAllowed(ui.Name);\n          if (isUnixExt)\n          {\n            needReadFile = true;\n            #ifndef _WIN32\n              probablyIsSameIsa = true;\n            #endif\n          }\n          else if (IsExt_Exe(ext))\n          {\n            needReadFile = ParseExe;\n            #ifdef _WIN32\n              probablyIsSameIsa = true;\n            #endif\n          }\n          else if (StringsAreEqualNoCase_Ascii(ext, \"wav\"))\n          {\n            if (!needReadFile)\n              needReadFile = ParseWav;\n          }\n        }\n      }\n    }\n\n    if (needReadFile)\n    {\n      BoolInt parseRes = false;\n      if (Callback)\n      {\n        if (Buffer.Size() != kAnalysisBufSize)\n          Buffer.Alloc(kAnalysisBufSize);\n        CMyComPtr<ISequentialInStream> stream;\n        HRESULT result = Callback->GetStream2(index, &stream, NUpdateNotifyOp::kAnalyze);\n        if (result == S_OK && stream)\n        {\n          /*\n          if (Need_ATime)\n          {\n            // access time could be changed in analysis pass\n            CMyComPtr<IStreamGetProps> getProps;\n            stream.QueryInterface(IID_IStreamGetProps, (void **)&getProps);\n            if (getProps)\n              if (getProps->GetProps(NULL, NULL, &ATime, NULL, NULL) == S_OK)\n                ATime_Defined = true;\n          }\n          */\n          size_t size = kAnalysisBufSize;\n          result = ReadStream(stream, Buffer, &size);\n          stream.Release();\n          // RINOK(Callback->SetOperationResult2(index, NUpdate::NOperationResult::kOK));\n          if (result == S_OK)\n          {\n            parseRes = ParseFile(Buffer, size, &filterModeTemp);\n          }\n        }\n      } // Callback\n      else if (probablyIsSameIsa)\n      {\n        #ifdef MY_CPU_X86_OR_AMD64\n          filterModeTemp.Id = k_X86;\n        #endif\n        #ifdef MY_CPU_ARM64\n          filterModeTemp.Id = k_ARM64;\n        #endif\n        #ifdef MY_CPU_RISCV\n          filterModeTemp.Id = k_RISCV;\n        #endif\n        #ifdef MY_CPU_SPARC\n          filterModeTemp.Id = k_SPARC;\n        #endif\n        parseRes = true;\n      }\n\n      if (parseRes\n          && filterModeTemp.Id != k_Delta\n          && filterModeTemp.Delta == 0)\n      {\n        /* ParseFile() sets (filterModeTemp.Delta == 0) for all\n           methods except of k_Delta. */\n        // it's not k_Delta\n        // So we call SetDelta() to set Delta\n        filterModeTemp.SetDelta();\n        if (filterModeTemp.Delta > 1)\n        {\n          /* If file Size is not aligned, then branch filter\n             will not work for next file in solid block.\n             Maybe we should allow filter for non-aligned-size file in non-solid archives ?\n          */\n          if (ui.Size % filterModeTemp.Delta != 0)\n            parseRes = false;\n          // windows exe files are not aligned for 4 KiB.\n          /*\n          else if (filterModeTemp.Id == k_ARM64 && filterModeTemp.Offset != 0)\n          {\n            if (ui.Size % (1 << 12) != 0)\n            {\n              // If Size is not aligned for 4 KiB, then Offset will not work for next file in solid block.\n              // so we place such file in group with (Offset==0).\n              filterModeTemp.Offset = 0;\n            }\n          }\n          */\n        }\n      }\n      if (!parseRes)\n        filterModeTemp.ClearFilterMode();\n    }\n  }\n  \n  filterMode = filterModeTemp;\n  return S_OK;\n}\n\nstatic inline void GetMethodFull(UInt64 methodID, UInt32 numStreams, CMethodFull &m)\n{\n  m.Id = methodID;\n  m.NumStreams = numStreams;\n}\n\n\n// we add bond for mode.Methods[0] that is filter\nstatic HRESULT AddBondForFilter(CCompressionMethodMode &mode)\n{\n  for (unsigned c = 1; c < mode.Methods.Size(); c++)\n  {\n    if (!mode.IsThereBond_to_Coder(c))\n    {\n      CBond2 bond;\n      bond.OutCoder = 0;\n      bond.OutStream = 0;\n      bond.InCoder = c;\n      mode.Bonds.Add(bond);\n      return S_OK;\n    }\n  }\n  return E_INVALIDARG;\n}\n\n/*\nstatic HRESULT AddBondForFilter_if_ThereAreBonds(CCompressionMethodMode &mode)\n{\n  if (!mode.Bonds.IsEmpty())\n    return AddBondForFilter(mode);\n  return S_OK;\n}\n*/\n\nstatic HRESULT AddBcj2Methods(CCompressionMethodMode &mode)\n{\n  // mode.Methods[0] must be k_BCJ2 method !\n  // mode.Methods[1] : we expect that there is at least one method after BCJ2\n\n  CMethodFull m;\n  GetMethodFull(k_LZMA, 1, m);\n  \n  m.AddProp32(NCoderPropID::kDictionarySize, 1 << 20);\n  m.AddProp32(NCoderPropID::kNumFastBytes, 128);\n  m.AddProp32(NCoderPropID::kNumThreads, 1);\n  m.AddProp32(NCoderPropID::kLitPosBits, 2);\n  m.AddProp32(NCoderPropID::kLitContextBits, 0);\n  // m.AddProp_Ascii(NCoderPropID::kMatchFinder, \"BT2\");\n\n  const unsigned methodIndex = mode.Methods.Size();\n\n  if (mode.Bonds.IsEmpty())\n  {\n    for (unsigned i = 1; i + 1 < mode.Methods.Size(); i++)\n    {\n      CBond2 bond;\n      bond.OutCoder = i;\n      bond.OutStream = 0;\n      bond.InCoder = i + 1;\n      mode.Bonds.Add(bond);\n    }\n  }\n\n  mode.Methods.Add(m);\n  mode.Methods.Add(m);\n  \n  RINOK(AddBondForFilter(mode))\n  CBond2 bond;\n  bond.OutCoder = 0; // index of BCJ2 coder\n  bond.InCoder = methodIndex;      bond.OutStream = 1;  mode.Bonds.Add(bond);\n  bond.InCoder = methodIndex + 1;  bond.OutStream = 2;  mode.Bonds.Add(bond);\n  return S_OK;\n}\n\n\nstatic HRESULT MakeExeMethod(CCompressionMethodMode &mode,\n    const CFilterMode &filterMode,\n    const bool bcj2_IsAllowed,\n    const CUIntVector &disabledFilterIDs)\n{\n  if (mode.Filter_was_Inserted)\n  {\n    // filter was inserted, but bond for that filter was not added still.\n    const CMethodFull &m = mode.Methods[0];\n    if (m.Id == k_BCJ2)\n      return AddBcj2Methods(mode);\n    if (!m.IsSimpleCoder())\n      return E_NOTIMPL;\n    if (mode.Bonds.IsEmpty())\n      return S_OK;\n    return AddBondForFilter(mode);\n  }\n\n  if (filterMode.Id == 0)\n    return S_OK;\n\n  unsigned nextCoder;\n\n  const bool useBcj2 = bcj2_IsAllowed\n      && Is86Filter(filterMode.Id)\n      && disabledFilterIDs.FindInSorted(k_BCJ2) < 0;\n\n  if (!useBcj2 && disabledFilterIDs.FindInSorted(filterMode.Id) >= 0)\n  {\n    // required filter is disabled,\n    // but we still can use information about data alignment.\n#if 0 // 1 for debug\n    // we can return here, if we want default lzma properties\n    return S_OK;\n#else\n    // we will try to change lzma/lzma2 properties\n    nextCoder = 0;\n    if (!mode.Bonds.IsEmpty())\n      for (unsigned c = 0;; c++)\n      {\n        if (c == mode.Methods.Size())\n          return S_OK;\n        if (!mode.IsThereBond_to_Coder(c))\n        {\n          nextCoder = c;\n          break;\n        }\n      }\n#endif\n  }\n  else\n  {\n    // we insert new filter method:\n    CMethodFull &m = mode.Methods.InsertNew(0); // 0 == index of new inserted item\n    {\n      // we move all coder indexes in bonds up for 1 position:\n      FOR_VECTOR (k, mode.Bonds)\n      {\n        CBond2 &bond = mode.Bonds[k];\n        bond.InCoder++;\n        bond.OutCoder++;\n      }\n    }\n    if (useBcj2)\n    {\n      GetMethodFull(k_BCJ2, 4, m);\n      return AddBcj2Methods(mode);\n    }\n    \n    GetMethodFull(filterMode.Id, 1, m);\n    \n    if (filterMode.Id == k_Delta)\n      m.AddProp32(NCoderPropID::kDefaultProp, filterMode.Delta);\n    else if (filterMode.Id == k_ARM64\n          || filterMode.Id == k_RISCV)\n    {\n      // if (filterMode.Offset != 0)\n      m.AddProp32(\n        NCoderPropID::kDefaultProp,\n        // NCoderPropID::kBranchOffset,\n        filterMode.Offset);\n    }\n    \n    nextCoder = 1;\n    if (!mode.Bonds.IsEmpty())\n    {\n      RINOK(AddBondForFilter(mode))\n      nextCoder = mode.Bonds.Back().InCoder;\n    }\n  }\n\n  if (nextCoder >= mode.Methods.Size())\n  {\n    // we don't expect that case, if there was non-filter method.\n    // but we return S_OK to support filter-only case.\n    return S_OK;\n  }\n\n  int alignBits = -1;\n  {\n    const UInt32 delta = filterMode.Delta;\n    if (delta == 0 || delta > 16)\n    {\n      // if (delta == 0) alignBits = GetAlignForFilterMethod(filterMode.Id);\n    }\n    else if ((delta & ((1 << 4) - 1)) == 0) alignBits = 4;\n    else if ((delta & ((1 << 3) - 1)) == 0) alignBits = 3;\n    else if ((delta & ((1 << 2) - 1)) == 0) alignBits = 2;\n    else if ((delta & ((1 << 1) - 1)) == 0) alignBits = 1;\n    // else alignBits = 0;\n    /* alignBits=0 is default mode for lzma/lzma2.\n    So we don't set alignBits=0 here. */\n  }\n  if (alignBits <= 0)\n    return S_OK;\n  // (alignBits > 0)\n  CMethodFull &nextMethod = mode.Methods[nextCoder];\n  if (nextMethod.Id == k_LZMA || nextMethod.Id == k_LZMA2)\n  if (!nextMethod.Are_Lzma_Model_Props_Defined())\n  {\n    if (alignBits > 2 || filterMode.Id == k_Delta)\n      nextMethod.AddProp32(NCoderPropID::kPosStateBits, (unsigned)alignBits);\n    const unsigned lc = (alignBits < 3) ? (unsigned)(3 - alignBits) : 0u;\n    nextMethod.AddProp32(NCoderPropID::kLitContextBits, lc);\n    nextMethod.AddProp32(NCoderPropID::kLitPosBits, (unsigned)alignBits);\n  }\n  return S_OK;\n}\n\n\nstatic void UpdateItem_To_FileItem2(const CUpdateItem &ui, CFileItem2 &file2)\n{\n  file2.Attrib = ui.Attrib;  file2.AttribDefined = ui.AttribDefined;\n  file2.CTime = ui.CTime;  file2.CTimeDefined = ui.CTimeDefined;\n  file2.ATime = ui.ATime;  file2.ATimeDefined = ui.ATimeDefined;\n  file2.MTime = ui.MTime;  file2.MTimeDefined = ui.MTimeDefined;\n  file2.IsAnti = ui.IsAnti;\n  // file2.IsAux = false;\n  file2.StartPosDefined = false;\n  // file2.StartPos = 0;\n}\n\n\nstatic void UpdateItem_To_FileItem(const CUpdateItem &ui,\n    CFileItem &file, CFileItem2 &file2)\n{\n  UpdateItem_To_FileItem2(ui, file2);\n\n  file.Size = ui.Size;\n  file.IsDir = ui.IsDir;\n  file.HasStream = ui.HasStream();\n  // file.IsAltStream = ui.IsAltStream;\n}\n\n\n\nZ7_CLASS_IMP_COM_2(\n  CRepackInStreamWithSizes\n  , ISequentialInStream\n  , ICompressGetSubStreamSize\n)\n  CMyComPtr<ISequentialInStream> _stream;\n  UInt64 _size;\n  const CBoolVector *_extractStatuses;\n  UInt32 _startIndex;\npublic:\n  const CDbEx *_db;\n\n  void Init(ISequentialInStream *stream, UInt32 startIndex, const CBoolVector *extractStatuses)\n  {\n    _startIndex = startIndex;\n    _extractStatuses = extractStatuses;\n    _size = 0;\n    _stream = stream;\n  }\n  UInt64 GetSize() const { return _size; }\n};\n\nZ7_COM7F_IMF(CRepackInStreamWithSizes::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize;\n  const HRESULT result = _stream->Read(data, size, &realProcessedSize);\n  _size += realProcessedSize;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return result;\n}\n\nZ7_COM7F_IMF(CRepackInStreamWithSizes::GetSubStreamSize(UInt64 subStream, UInt64 *value))\n{\n  *value = 0;\n  if (subStream >= _extractStatuses->Size())\n    return S_FALSE; // E_FAIL;\n  const unsigned index = (unsigned)subStream;\n  if ((*_extractStatuses)[index])\n  {\n    const CFileItem &fi = _db->Files[_startIndex + index];\n    if (fi.HasStream)\n      *value = fi.Size;\n  }\n  return S_OK;\n}\n\n\nclass CRepackStreamBase\n{\nprotected:\n  bool _needWrite;\n  bool _fileIsOpen;\n  bool _calcCrc;\n  UInt32 _crc;\n  UInt64 _rem;\n\n  const CBoolVector *_extractStatuses;\n  UInt32 _startIndex;\n  unsigned _currentIndex;\n\n  HRESULT OpenFile();\n  HRESULT CloseFile();\n  HRESULT ProcessEmptyFiles();\n\npublic:\n  const CDbEx *_db;\n  CMyComPtr<IArchiveUpdateCallbackFile> _opCallback;\n  CMyComPtr<IArchiveExtractCallbackMessage2> _extractCallback;\n\n  HRESULT Init(UInt32 startIndex, const CBoolVector *extractStatuses);\n  HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }\n};\n\nHRESULT CRepackStreamBase::Init(UInt32 startIndex, const CBoolVector *extractStatuses)\n{\n  _startIndex = startIndex;\n  _extractStatuses = extractStatuses;\n\n  _currentIndex = 0;\n  _fileIsOpen = false;\n  \n  return ProcessEmptyFiles();\n}\n\nHRESULT CRepackStreamBase::OpenFile()\n{\n  UInt32 arcIndex = _startIndex + _currentIndex;\n  const CFileItem &fi = _db->Files[arcIndex];\n  \n  _needWrite = (*_extractStatuses)[_currentIndex];\n  if (_opCallback)\n  {\n    RINOK(_opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, arcIndex,\n        _needWrite ?\n            NUpdateNotifyOp::kRepack :\n            NUpdateNotifyOp::kSkip))\n  }\n\n  _crc = CRC_INIT_VAL;\n  _calcCrc = (fi.CrcDefined && !fi.IsDir);\n\n  _fileIsOpen = true;\n  _rem = fi.Size;\n  return S_OK;\n}\n\nconst HRESULT k_My_HRESULT_CRC_ERROR = 0x20000002;\n\nHRESULT CRepackStreamBase::CloseFile()\n{\n  UInt32 arcIndex = _startIndex + _currentIndex;\n  const CFileItem &fi = _db->Files[arcIndex];\n  _fileIsOpen = false;\n  _currentIndex++;\n  if (!_calcCrc || fi.Crc == CRC_GET_DIGEST(_crc))\n    return S_OK;\n\n  if (_extractCallback)\n  {\n    RINOK(_extractCallback->ReportExtractResult(\n        NEventIndexType::kInArcIndex, arcIndex,\n        NExtract::NOperationResult::kCRCError))\n  }\n  // return S_FALSE;\n  return k_My_HRESULT_CRC_ERROR;\n}\n\nHRESULT CRepackStreamBase::ProcessEmptyFiles()\n{\n  while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)\n  {\n    RINOK(OpenFile())\n    RINOK(CloseFile())\n  }\n  return S_OK;\n}\n  \n\n\n#ifndef Z7_ST\n\nclass CFolderOutStream2 Z7_final:\n  public CRepackStreamBase,\n  public ISequentialOutStream,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_0\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\npublic:\n  CMyComPtr<ISequentialOutStream> _stream;\n};\n\nZ7_COM7F_IMF(CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  \n  while (size != 0)\n  {\n    if (_fileIsOpen)\n    {\n      UInt32 cur = (size < _rem ? size : (UInt32)_rem);\n      HRESULT result = S_OK;\n      if (_needWrite)\n        result = _stream->Write(data, cur, &cur);\n      if (_calcCrc)\n        _crc = CrcUpdate(_crc, data, cur);\n      if (processedSize)\n        *processedSize += cur;\n      data = (const Byte *)data + cur;\n      size -= cur;\n      _rem -= cur;\n      if (_rem == 0)\n      {\n        RINOK(CloseFile())\n        RINOK(ProcessEmptyFiles())\n      }\n      RINOK(result)\n      if (cur == 0)\n        break;\n      continue;\n    }\n\n    RINOK(ProcessEmptyFiles())\n    if (_currentIndex == _extractStatuses->Size())\n    {\n      // we don't support write cut here\n      return E_FAIL;\n    }\n    RINOK(OpenFile())\n  }\n\n  return S_OK;\n}\n\n#endif\n\n\n\nstatic const UInt32 kTempBufSize = 1 << 16;\n\nclass CFolderInStream2 Z7_final:\n  public CRepackStreamBase,\n  public ISequentialInStream,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_0\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n\n  Byte *_buf;\npublic:\n  CMyComPtr<ISequentialInStream> _inStream;\n  HRESULT Result;\n\n  CFolderInStream2():\n      Result(S_OK)\n  {\n    _buf = new Byte[kTempBufSize];\n  }\n\n  ~CFolderInStream2()\n  {\n    delete []_buf;\n  }\n\n  void Init() { Result = S_OK; }\n};\n\nZ7_COM7F_IMF(CFolderInStream2::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  \n  while (size != 0)\n  {\n    if (_fileIsOpen)\n    {\n      UInt32 cur = (size < _rem ? size : (UInt32)_rem);\n      \n      void *buf;\n      if (_needWrite)\n        buf = data;\n      else\n      {\n        buf = _buf;\n        if (cur > kTempBufSize)\n          cur = kTempBufSize;\n      }\n\n      const HRESULT result = _inStream->Read(buf, cur, &cur);\n      _crc = CrcUpdate(_crc, buf, cur);\n      _rem -= cur;\n\n      if (_needWrite)\n      {\n        data = (Byte *)data + cur;\n        size -= cur;\n        if (processedSize)\n          *processedSize += cur;\n      }\n\n      if (result != S_OK)\n        Result = result;\n\n      if (_rem == 0)\n      {\n        RINOK(CloseFile())\n        RINOK(ProcessEmptyFiles())\n      }\n\n      RINOK(result)\n      \n      if (cur == 0)\n        return E_FAIL;\n\n      continue;\n    }\n\n    RINOK(ProcessEmptyFiles())\n    if (_currentIndex == _extractStatuses->Size())\n    {\n      return S_OK;\n    }\n    RINOK(OpenFile())\n  }\n  \n  return S_OK;\n}\n\n\nclass CThreadDecoder Z7_final\n  #ifndef Z7_ST\n    : public CVirtThread\n  #endif\n{\npublic:\n  CDecoder Decoder;\n\n  CThreadDecoder(bool multiThreadMixer):\n      Decoder(multiThreadMixer)\n  {\n    #ifndef Z7_ST\n    if (multiThreadMixer)\n    {\n      MtMode = false;\n      NumThreads = 1;\n      FosSpec = new CFolderOutStream2;\n      Fos = FosSpec;\n      Result = E_FAIL;\n    }\n    #endif\n    // UnpackSize = 0;\n    // send_UnpackSize = false;\n  }\n\n  #ifndef Z7_ST\n  \n  bool dataAfterEnd_Error;\n  HRESULT Result;\n  CMyComPtr<IInStream> InStream;\n\n  CFolderOutStream2 *FosSpec;\n  CMyComPtr<ISequentialOutStream> Fos;\n\n  UInt64 StartPos;\n  const CFolders *Folders;\n  unsigned FolderIndex;\n\n  // bool send_UnpackSize;\n  // UInt64 UnpackSize;\n  \n  #ifndef Z7_NO_CRYPTO\n  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n  #endif\n\n  DECL_EXTERNAL_CODECS_LOC_VARS_DECL\n\n  #ifndef Z7_ST\n  bool MtMode;\n  UInt32 NumThreads;\n  #endif\n\n  \n  ~CThreadDecoder() Z7_DESTRUCTOR_override\n  {\n    /* WaitThreadFinish() will be called in ~CVirtThread().\n       But we need WaitThreadFinish() call before\n       destructors of this class members.\n    */\n    CVirtThread::WaitThreadFinish();\n  }\nprivate:\n  virtual void Execute() Z7_override;\n\n  #endif\n};\n\n#ifndef Z7_ST\n\nvoid CThreadDecoder::Execute()\n{\n  try\n  {\n    #ifndef Z7_NO_CRYPTO\n      bool isEncrypted = false;\n      bool passwordIsDefined = false;\n      UString password;\n    #endif\n \n    dataAfterEnd_Error = false;\n      \n    Result = Decoder.Decode(\n      EXTERNAL_CODECS_LOC_VARS\n      InStream,\n      StartPos,\n      *Folders, FolderIndex,\n      \n      // send_UnpackSize ? &UnpackSize : NULL,\n      NULL, // unpackSize : FULL unpack\n      \n      Fos,\n      NULL, // compressProgress\n\n      NULL  // *inStreamMainRes\n      , dataAfterEnd_Error\n\n      Z7_7Z_DECODER_CRYPRO_VARS\n      #ifndef Z7_ST\n        , MtMode, NumThreads,\n        0 // MemUsage\n      #endif\n\n      );\n  }\n  catch(...)\n  {\n    Result = E_FAIL;\n  }\n  \n  /*\n  if (Result == S_OK)\n    Result = FosSpec->CheckFinishedState();\n  */\n  FosSpec->_stream.Release();\n}\n\n#endif\n\n#ifndef Z7_NO_CRYPTO\n\nZ7_CLASS_IMP_NOQIB_1(\n  CCryptoGetTextPassword\n  , ICryptoGetTextPassword\n)\npublic:\n  UString Password;\n};\n\nZ7_COM7F_IMF(CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password))\n{\n  return StringToBstr(Password, password);\n}\n\n#endif\n\n\nstatic void GetFile(const CDatabase &inDb, unsigned index, CFileItem &file, CFileItem2 &file2)\n{\n  file = inDb.Files[index];\n  file2.CTimeDefined = inDb.CTime.GetItem(index, file2.CTime);\n  file2.ATimeDefined = inDb.ATime.GetItem(index, file2.ATime);\n  file2.MTimeDefined = inDb.MTime.GetItem(index, file2.MTime);\n  file2.StartPosDefined = inDb.StartPos.GetItem(index, file2.StartPos);\n  file2.AttribDefined = inDb.Attrib.GetItem(index, file2.Attrib);\n  file2.IsAnti = inDb.IsItemAnti(index);\n  // file2.IsAux = inDb.IsItemAux(index);\n}\n\nHRESULT Update(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    IInStream *inStream,\n    const CDbEx *db,\n    CObjectVector<CUpdateItem> &updateItems,\n    // const CObjectVector<CTreeFolder> &treeFolders,\n    // const CUniqBlocks &secureBlocks,\n    ISequentialOutStream *seqOutStream,\n    IArchiveUpdateCallback *updateCallback,\n    const CUpdateOptions &options)\n{\n  UInt64 numSolidFiles = options.NumSolidFiles;\n  if (numSolidFiles == 0)\n    numSolidFiles = 1;\n\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveUpdateCallbackFile,\n      opCallback, updateCallback)\n\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveExtractCallbackMessage2,\n      extractCallback, updateCallback)\n\n  /*\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveUpdateCallbackArcProp,\n      reportArcProp, updateCallback)\n  */\n\n  // size_t totalSecureDataSize = (size_t)secureBlocks.GetTotalSizeInBytes();\n\n  CMyComPtr<IStreamSetRestriction> v_StreamSetRestriction;\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IOutStream,\n        outStream, seqOutStream)\n    if (!outStream)\n      return E_NOTIMPL;\n    const UInt64 sfxBlockSize = (db && !options.RemoveSfxBlock) ?\n        db->ArcInfo.StartPosition: 0;\n    seqOutStream->QueryInterface(IID_IStreamSetRestriction, (void **)&v_StreamSetRestriction);\n    if (v_StreamSetRestriction)\n    {\n      UInt64 offset = 0;\n      RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &offset))\n      RINOK(v_StreamSetRestriction->SetRestriction(\n          outStream ? offset + sfxBlockSize : 0,\n          outStream ? offset + sfxBlockSize + k_StartHeadersRewriteSize : 0))\n    }\n    outStream.Release();\n    if (sfxBlockSize != 0)\n    {\n      RINOK(WriteRange(inStream, seqOutStream, 0, sfxBlockSize, NULL))\n    }\n  }\n\n  CIntArr fileIndexToUpdateIndexMap;\n  UInt64 complexity = 0;\n  bool isThere_UnknownSize = false;\n  UInt64 inSizeForReduce2 = 0;\n\n #ifndef Z7_NO_CRYPTO\n  bool needEncryptedRepack = false;\n #endif\n\n  CRecordVector<CFilterMode2> filters;\n  CObjectVector<CSolidGroup> groups;\n  \n  #ifndef Z7_ST\n  bool thereAreRepacks = false;\n  #endif\n\n  bool useFilters = options.UseFilters;\n  if (useFilters)\n  {\n    const CCompressionMethodMode &method = *options.Method;\n\n    FOR_VECTOR (i, method.Methods)\n    {\n      /* IsFilterMethod() knows only built-in codecs\n         FIXME: we should check IsFilter status for external filters too */\n      if (IsFilterMethod(method.Methods[i].Id))\n      {\n        useFilters = false;\n        break;\n      }\n    }\n  }\n  \n  if (db)\n  {\n    fileIndexToUpdateIndexMap.Alloc(db->Files.Size());\n    unsigned i;\n    \n    for (i = 0; i < db->Files.Size(); i++)\n      fileIndexToUpdateIndexMap[i] = -1;\n\n    for (i = 0; i < updateItems.Size(); i++)\n    {\n      int index = updateItems[i].IndexInArchive;\n      if (index != -1)\n        fileIndexToUpdateIndexMap[(unsigned)index] = (int)i;\n    }\n\n    for (i = 0; i < db->NumFolders; i++)\n    {\n      CNum indexInFolder = 0;\n      CNum numCopyItems = 0;\n      const CNum numUnpackStreams = db->NumUnpackStreamsVector[i];\n      UInt64 repackSize = 0;\n      \n      for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)\n      {\n        if (fi >= db->Files.Size())\n          return E_FAIL;\n\n        const CFileItem &file = db->Files[fi];\n        if (file.HasStream)\n        {\n          indexInFolder++;\n          const int updateIndex = fileIndexToUpdateIndexMap[fi];\n          if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData)\n          {\n            numCopyItems++;\n            repackSize += file.Size;\n          }\n        }\n      }\n\n      if (numCopyItems == 0)\n        continue;\n\n      CFolderRepack rep;\n      rep.FolderIndex = i;\n      rep.NumCopyFiles = numCopyItems;\n      CFolderEx f;\n      db->ParseFolderEx(i, f);\n\n     #ifndef Z7_NO_CRYPTO\n      const bool isEncrypted = f.IsEncrypted();\n     #endif\n      const bool needCopy = (numCopyItems == numUnpackStreams);\n      const bool extractFilter = (useFilters || needCopy);\n\n      const unsigned groupIndex = Get_FilterGroup_for_Folder(filters, f, extractFilter);\n      \n      while (groupIndex >= groups.Size())\n        groups.AddNew();\n\n      groups[groupIndex].folderRefs.Add(rep);\n      \n      if (needCopy)\n        complexity += db->GetFolderFullPackSize(i);\n      else\n      {\n        #ifndef Z7_ST\n        thereAreRepacks = true;\n        #endif\n        complexity += repackSize;\n        if (inSizeForReduce2 < repackSize)\n          inSizeForReduce2 = repackSize;\n       #ifndef Z7_NO_CRYPTO\n        if (isEncrypted)\n          needEncryptedRepack = true;\n       #endif\n      }\n    }\n  }\n\n  UInt64 inSizeForReduce = 0;\n  {\n    const bool isSolid = (numSolidFiles > 1 && options.NumSolidBytes != 0);\n    FOR_VECTOR (i, updateItems)\n    {\n      const CUpdateItem &ui = updateItems[i];\n      if (ui.NewData)\n      {\n        if (ui.Size == (UInt64)(Int64)-1)\n          isThere_UnknownSize = true;\n        else\n        {\n          complexity += ui.Size;\n          if (isSolid)\n            inSizeForReduce += ui.Size;\n          else if (inSizeForReduce < ui.Size)\n            inSizeForReduce = ui.Size;\n        }\n      }\n    }\n  }\n\n  if (isThere_UnknownSize)\n    inSizeForReduce = (UInt64)(Int64)-1;\n  else\n    RINOK(updateCallback->SetTotal(complexity))\n\n  if (inSizeForReduce < inSizeForReduce2)\n      inSizeForReduce = inSizeForReduce2;\n\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(updateCallback, true);\n\n  #ifndef Z7_ST\n  \n  CStreamBinder sb;\n  /*\n  if (options.MultiThreadMixer)\n  {\n    RINOK(sb.CreateEvents());\n  }\n  */\n  \n  #endif\n\n  CThreadDecoder threadDecoder(options.MultiThreadMixer);\n  \n  #ifndef Z7_ST\n  if (options.MultiThreadMixer && thereAreRepacks)\n  {\n    #ifdef Z7_EXTERNAL_CODECS\n    threadDecoder._externalCodecs = _externalCodecs;\n    #endif\n    const WRes wres = threadDecoder.Create();\n    if (wres != 0)\n      return HRESULT_FROM_WIN32(wres);\n  }\n  #endif\n\n  {\n    CAnalysis analysis;\n    // analysis.Need_ATime = options.Need_ATime;\n    int analysisLevel = options.AnalysisLevel;\n    // (analysisLevel < 0) means default level (5)\n    if (analysisLevel < 0)\n      analysisLevel = 5;\n    if (analysisLevel != 0)\n    {\n      analysis.Callback = opCallback;\n      analysis.ParseWav = true;\n      if (analysisLevel >= 5)\n      {\n        analysis.ParseExe = true;\n        analysis.ParseExeUnix = true;\n        // analysis.ParseNoExt = true;\n        if (analysisLevel >= 7)\n        {\n          analysis.ParseNoExt = true;\n          if (analysisLevel >= 9)\n            analysis.ParseAll = true;\n        }\n      }\n    }\n\n    // ---------- Split files to groups ----------\n\n    const CCompressionMethodMode &method = *options.Method;\n    \n    FOR_VECTOR (i, updateItems)\n    {\n      const CUpdateItem &ui = updateItems[i];\n      if (!ui.NewData || !ui.HasStream())\n        continue;\n\n      CFilterMode2 fm;\n      if (useFilters)\n      {\n        // analysis.ATime_Defined = false;\n        RINOK(analysis.GetFilterGroup(i, ui, fm))\n        /*\n        if (analysis.ATime_Defined)\n        {\n          ui.ATime = FILETIME_To_UInt64(analysis.ATime);\n          ui.ATime_WasReadByAnalysis = true;\n        }\n        */\n      }\n      fm.Encrypted = method.PasswordIsDefined;\n\n      const unsigned groupIndex = GetGroup(filters, fm);\n      while (groupIndex >= groups.Size())\n        groups.AddNew();\n      groups[groupIndex].Indices.Add(i);\n    }\n  }\n\n\n  #ifndef Z7_NO_CRYPTO\n\n  CCryptoGetTextPassword *getPasswordSpec = NULL;\n  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n  if (needEncryptedRepack)\n  {\n    getPasswordSpec = new CCryptoGetTextPassword;\n    getTextPassword = getPasswordSpec;\n    \n    #ifndef Z7_ST\n    threadDecoder.getTextPassword = getPasswordSpec;\n    #endif\n\n    if (options.Method->PasswordIsDefined)\n      getPasswordSpec->Password = options.Method->Password;\n    else\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          ICryptoGetTextPassword,\n          getDecoderPassword, updateCallback)\n      if (!getDecoderPassword)\n        return E_NOTIMPL;\n      CMyComBSTR password;\n      RINOK(getDecoderPassword->CryptoGetTextPassword(&password))\n      if (password)\n        getPasswordSpec->Password = password;\n    }\n  }\n\n  #endif\n\n  // ---------- Compress ----------\n\n  COutArchive archive;\n  CArchiveDatabaseOut newDatabase;\n\n  RINOK(archive.Create_and_WriteStartPrefix(seqOutStream))\n\n  /*\n  CIntVector treeFolderToArcIndex;\n  treeFolderToArcIndex.Reserve(treeFolders.Size());\n  for (i = 0; i < treeFolders.Size(); i++)\n    treeFolderToArcIndex.Add(-1);\n  // ---------- Write Tree (only AUX dirs) ----------\n  for (i = 1; i < treeFolders.Size(); i++)\n  {\n    const CTreeFolder &treeFolder = treeFolders[i];\n    CFileItem file;\n    CFileItem2 file2;\n    file2.Init();\n    int secureID = 0;\n    if (treeFolder.UpdateItemIndex < 0)\n    {\n      // we can store virtual dir item wuthout attrib, but we want all items have attrib.\n      file.SetAttrib(FILE_ATTRIBUTE_DIRECTORY);\n      file2.IsAux = true;\n    }\n    else\n    {\n      const CUpdateItem &ui = updateItems[treeFolder.UpdateItemIndex];\n      // if item is not dir, then it's parent for alt streams.\n      // we will write such items later\n      if (!ui.IsDir)\n        continue;\n      secureID = ui.SecureIndex;\n      if (ui.NewProps)\n        UpdateItem_To_FileItem(ui, file, file2);\n      else\n        GetFile(*db, ui.IndexInArchive, file, file2);\n    }\n    file.Size = 0;\n    file.HasStream = false;\n    file.IsDir = true;\n    file.Parent = treeFolder.Parent;\n    \n    treeFolderToArcIndex[i] = newDatabase.Files.Size();\n    newDatabase.AddFile(file, file2, treeFolder.Name);\n    \n    if (totalSecureDataSize != 0)\n      newDatabase.SecureIDs.Add(secureID);\n  }\n  */\n\n  {\n    /* ---------- Write non-AUX dirs and Empty files ---------- */\n    CUIntVector emptyRefs;\n    \n    unsigned i;\n\n    for (i = 0; i < updateItems.Size(); i++)\n    {\n      const CUpdateItem &ui = updateItems[i];\n      if (ui.NewData)\n      {\n        if (ui.HasStream())\n          continue;\n      }\n      else if (ui.IndexInArchive != -1 && db->Files[(unsigned)ui.IndexInArchive].HasStream)\n        continue;\n      /*\n      if (ui.TreeFolderIndex >= 0)\n        continue;\n      */\n      emptyRefs.Add(i);\n    }\n    \n    emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);\n    \n    for (i = 0; i < emptyRefs.Size(); i++)\n    {\n      const CUpdateItem &ui = updateItems[emptyRefs[i]];\n      CFileItem file;\n      CFileItem2 file2;\n      UString name;\n      if (ui.NewProps)\n      {\n        UpdateItem_To_FileItem(ui, file, file2);\n        file.CrcDefined = false;\n        name = ui.Name;\n      }\n      else\n      {\n        GetFile(*db, (unsigned)ui.IndexInArchive, file, file2);\n        db->GetPath((unsigned)ui.IndexInArchive, name);\n      }\n      \n      /*\n      if (totalSecureDataSize != 0)\n        newDatabase.SecureIDs.Add(ui.SecureIndex);\n      file.Parent = ui.ParentFolderIndex;\n      */\n      newDatabase.AddFile(file, file2, name);\n    }\n  }\n\n  lps->ProgressOffset = 0;\n\n  {\n    // ---------- Sort Filters ----------\n    FOR_VECTOR (i, filters)\n    {\n      filters[i].GroupIndex = i;\n    }\n    filters.Sort2();\n  }\n\n  for (unsigned groupIndex = 0; groupIndex < filters.Size(); groupIndex++)\n  {\n    const CFilterMode2 &filterMode = filters[groupIndex];\n\n    CCompressionMethodMode method = *options.Method;\n    {\n      const HRESULT res = MakeExeMethod(method, filterMode,\n        // bcj2_IsAllowed:\n        #ifdef Z7_ST\n          false\n        #else\n          options.MaxFilter && options.MultiThreadMixer\n        #endif\n        , options.DisabledFilterIDs);\n\n      RINOK(res)\n    }\n\n    if (filterMode.Encrypted)\n    {\n      if (!method.PasswordIsDefined)\n      {\n        #ifndef Z7_NO_CRYPTO\n        if (getPasswordSpec)\n          method.Password = getPasswordSpec->Password;\n        #endif\n        method.PasswordIsDefined = true;\n      }\n    }\n    else\n    {\n      method.PasswordIsDefined = false;\n      method.Password.Empty();\n    }\n\n    CEncoder encoder(method);\n\n    // ---------- Repack and copy old solid blocks ----------\n\n    const CSolidGroup &group = groups[filterMode.GroupIndex];\n    \n    FOR_VECTOR (folderRefIndex, group.folderRefs)\n    {\n      const CFolderRepack &rep = group.folderRefs[folderRefIndex];\n\n      const unsigned folderIndex = rep.FolderIndex;\n      \n      const CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];\n\n      if (rep.NumCopyFiles == numUnpackStreams)\n      {\n        if (opCallback)\n        {\n          RINOK(opCallback->ReportOperation(\n              NEventIndexType::kBlockIndex, (UInt32)folderIndex,\n              NUpdateNotifyOp::kReplicate))\n\n          // ---------- Copy old solid block ----------\n          {\n            CNum indexInFolder = 0;\n            for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)\n            {\n              if (db->Files[fi].HasStream)\n              {\n                indexInFolder++;\n                RINOK(opCallback->ReportOperation(\n                    NEventIndexType::kInArcIndex, (UInt32)fi,\n                    NUpdateNotifyOp::kReplicate))\n              }\n            }\n          }\n        }\n\n        const UInt64 packSize = db->GetFolderFullPackSize(folderIndex);\n        RINOK(WriteRange(inStream, archive.SeqStream,\n            db->GetFolderStreamPos(folderIndex, 0), packSize, lps))\n        lps->ProgressOffset += packSize;\n\n        const unsigned folderIndex_New = newDatabase.Folders.Size();\n        CFolder &folder = newDatabase.Folders.AddNew();\n        // v23.01: we copy FolderCrc, if FolderCrc was used\n        if (db->FolderCRCs.ValidAndDefined(folderIndex))\n          newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New,\n              true, db->FolderCRCs.Vals[folderIndex]);\n\n        db->ParseFolderInfo(folderIndex, folder);\n        const CNum startIndex = db->FoStartPackStreamIndex[folderIndex];\n        FOR_VECTOR (j, folder.PackStreams)\n        {\n          newDatabase.PackSizes.Add(db->GetStreamPackSize(startIndex + j));\n          // newDatabase.PackCRCsDefined.Add(db.PackCRCsDefined[startIndex + j]);\n          // newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);\n        }\n\n        size_t indexStart = db->FoToCoderUnpackSizes[folderIndex];\n        const size_t indexEnd = db->FoToCoderUnpackSizes[folderIndex + 1];\n        for (; indexStart < indexEnd; indexStart++)\n          newDatabase.CoderUnpackSizes.Add(db->CoderUnpackSizes.ConstData()[indexStart]);\n      }\n      else\n      {\n        // ---------- Repack old solid block ----------\n\n        CBoolVector extractStatuses;\n        \n        CNum indexInFolder = 0;\n\n        if (opCallback)\n        {\n          RINOK(opCallback->ReportOperation(\n              NEventIndexType::kBlockIndex, (UInt32)folderIndex,\n              NUpdateNotifyOp::kRepack))\n        }\n\n        /* We could reduce data size of decoded folder, if we don't need to repack\n           last files in folder. But the gain in speed is small in most cases.\n           So we unpack full folder. */\n           \n        UInt64 sizeToEncode = 0;\n  \n        /*\n        UInt64 importantUnpackSize = 0;\n        unsigned numImportantFiles = 0;\n        UInt64 decodeSize = 0;\n        */\n\n        for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)\n        {\n          bool needExtract = false;\n          const CFileItem &file = db->Files[fi];\n  \n          if (file.HasStream)\n          {\n            indexInFolder++;\n            const int updateIndex = fileIndexToUpdateIndexMap[fi];\n            if (updateIndex >= 0 && !updateItems[(unsigned)updateIndex].NewData)\n              needExtract = true;\n            // decodeSize += file.Size;\n          }\n          \n          extractStatuses.Add(needExtract);\n          if (needExtract)\n          {\n            sizeToEncode += file.Size;\n            /*\n            numImportantFiles = extractStatuses.Size();\n            importantUnpackSize = decodeSize;\n            */\n          }\n        }\n\n        // extractStatuses.DeleteFrom(numImportantFiles);\n\n        unsigned startPackIndex = newDatabase.PackSizes.Size();\n        UInt64 curUnpackSize;\n        {\n          CMyComPtr<ISequentialInStream> sbInStream;\n          CRepackStreamBase *repackBase;\n          CFolderInStream2 *FosSpec2 = NULL;\n\n          CRepackInStreamWithSizes *inStreamSizeCountSpec = new CRepackInStreamWithSizes;\n          CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;\n          {\n            #ifndef Z7_ST\n            if (options.MultiThreadMixer)\n            {\n              repackBase = threadDecoder.FosSpec;\n              CMyComPtr<ISequentialOutStream> sbOutStream;\n              sb.CreateStreams2(sbInStream, sbOutStream);\n              RINOK(sb.Create_ReInit())\n              \n              threadDecoder.FosSpec->_stream = sbOutStream;\n              \n              threadDecoder.InStream = inStream;\n              threadDecoder.StartPos = db->ArcInfo.DataStartPosition; // db->GetFolderStreamPos(folderIndex, 0);\n              threadDecoder.Folders = (const CFolders *)db;\n              threadDecoder.FolderIndex = folderIndex;\n             \n              // threadDecoder.UnpackSize = importantUnpackSize;\n              // threadDecoder.send_UnpackSize = true;\n            }\n            else\n            #endif\n            {\n              FosSpec2 = new CFolderInStream2;\n              FosSpec2->Init();\n              sbInStream = FosSpec2;\n              repackBase = FosSpec2;\n\n              #ifndef Z7_NO_CRYPTO\n              bool isEncrypted = false;\n              bool passwordIsDefined = false;\n              UString password;\n              #endif\n              \n              CMyComPtr<ISequentialInStream> decodedStream;\n              bool dataAfterEnd_Error = false;\n\n              const HRESULT res = threadDecoder.Decoder.Decode(\n                  EXTERNAL_CODECS_LOC_VARS\n                  inStream,\n                  db->ArcInfo.DataStartPosition, // db->GetFolderStreamPos(folderIndex, 0);,\n                  *db, folderIndex,\n                  // &importantUnpackSize, // *unpackSize\n                  NULL, // *unpackSize : FULL unpack\n                \n                  NULL, // *outStream\n                  NULL, // *compressProgress\n\n                  &decodedStream\n                  , dataAfterEnd_Error\n                \n                  Z7_7Z_DECODER_CRYPRO_VARS\n                  #ifndef Z7_ST\n                    , false // mtMode\n                    , 1 // numThreads\n                    , 0 // memUsage\n                  #endif\n                );\n          \n              RINOK(res)\n              if (!decodedStream)\n                return E_FAIL;\n\n              FosSpec2->_inStream = decodedStream;\n            }\n\n            repackBase->_db = db;\n            repackBase->_opCallback = opCallback;\n            repackBase->_extractCallback = extractCallback;\n\n            UInt32 startIndex = db->FolderStartFileIndex[folderIndex];\n            RINOK(repackBase->Init(startIndex, &extractStatuses))\n\n            inStreamSizeCountSpec->_db = db;\n            inStreamSizeCountSpec->Init(sbInStream, startIndex, &extractStatuses);\n\n            #ifndef Z7_ST\n            if (options.MultiThreadMixer)\n            {\n              WRes wres = threadDecoder.Start();\n              if (wres != 0)\n                return HRESULT_FROM_WIN32(wres);\n            }\n            #endif\n          }\n\n          // curUnpackSize = sizeToEncode;\n\n          HRESULT encodeRes = encoder.Encode1(\n              EXTERNAL_CODECS_LOC_VARS\n              inStreamSizeCount,\n              // NULL,\n              &inSizeForReduce,\n              sizeToEncode, // expectedDataSize\n              newDatabase.Folders.AddNew(),\n              // newDatabase.CoderUnpackSizes, curUnpackSize,\n              archive.SeqStream, newDatabase.PackSizes, lps);\n\n          if (encodeRes == k_My_HRESULT_CRC_ERROR)\n            return E_FAIL;\n\n          curUnpackSize = inStreamSizeCountSpec->GetSize();\n\n          if (encodeRes == S_OK)\n          {\n            encoder.Encode_Post(curUnpackSize, newDatabase.CoderUnpackSizes);\n          }\n\n          #ifndef Z7_ST\n          if (options.MultiThreadMixer)\n          {\n            // 16.00: hang was fixed : for case if decoding was not finished.\n            // We close CBinderInStream and it calls CStreamBinder::CloseRead()\n            inStreamSizeCount.Release();\n            sbInStream.Release();\n            \n            {\n              const WRes wres = threadDecoder.WaitExecuteFinish();\n              if (wres != 0)\n                return HRESULT_FROM_WIN32(wres);\n            }\n            \n            const HRESULT decodeRes = threadDecoder.Result;\n            // if (res == k_My_HRESULT_CRC_ERROR)\n            if (decodeRes == S_FALSE || threadDecoder.dataAfterEnd_Error)\n            {\n              if (extractCallback)\n              {\n                RINOK(extractCallback->ReportExtractResult(\n                    NEventIndexType::kInArcIndex, db->FolderStartFileIndex[folderIndex],\n                    // NEventIndexType::kBlockIndex, (UInt32)folderIndex,\n                    (decodeRes != S_OK ?\n                      NExtract::NOperationResult::kDataError :\n                      NExtract::NOperationResult::kDataAfterEnd)))\n              }\n              if (decodeRes != S_OK)\n                return E_FAIL;\n            }\n            RINOK(decodeRes)\n            if (encodeRes == S_OK)\n              if (sb.ProcessedSize != sizeToEncode)\n                encodeRes = E_FAIL;\n          }\n          else\n          #endif\n          {\n            if (FosSpec2->Result == S_FALSE)\n            {\n              if (extractCallback)\n              {\n                RINOK(extractCallback->ReportExtractResult(\n                    NEventIndexType::kBlockIndex, (UInt32)folderIndex,\n                    NExtract::NOperationResult::kDataError))\n              }\n              return E_FAIL;\n            }\n            RINOK(FosSpec2->Result)\n          }\n\n          RINOK(encodeRes)\n          RINOK(repackBase->CheckFinishedState())\n\n          if (curUnpackSize != sizeToEncode)\n            return E_FAIL;\n        }\n\n        for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)\n          lps->OutSize += newDatabase.PackSizes[startPackIndex];\n        lps->InSize += curUnpackSize;\n      }\n      \n      newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);\n      \n      CNum indexInFolder = 0;\n      for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)\n      {\n        if (db->Files[fi].HasStream)\n        {\n          indexInFolder++;\n          const int updateIndex = fileIndexToUpdateIndexMap[fi];\n          if (updateIndex >= 0)\n          {\n            const CUpdateItem &ui = updateItems[(unsigned)updateIndex];\n            if (ui.NewData)\n              continue;\n\n            UString name;\n            CFileItem file;\n            CFileItem2 file2;\n            GetFile(*db, fi, file, file2);\n\n            if (ui.NewProps)\n            {\n              UpdateItem_To_FileItem2(ui, file2);\n              file.IsDir = ui.IsDir;\n              name = ui.Name;\n            }\n            else\n              db->GetPath(fi, name);\n\n            /*\n            file.Parent = ui.ParentFolderIndex;\n            if (ui.TreeFolderIndex >= 0)\n              treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();\n            if (totalSecureDataSize != 0)\n              newDatabase.SecureIDs.Add(ui.SecureIndex);\n            */\n            newDatabase.AddFile(file, file2, name);\n          }\n        }\n      }\n    }\n\n\n    // ---------- Compress files to new solid blocks ----------\n\n    const unsigned numFiles = group.Indices.Size();\n    if (numFiles == 0)\n      continue;\n    CRecordVector<CRefItem> refItems;\n    refItems.ClearAndSetSize(numFiles);\n    // bool sortByType = (options.UseTypeSorting && isSoid); // numSolidFiles > 1\n    const bool sortByType = options.UseTypeSorting;\n    \n    unsigned i;\n\n    for (i = 0; i < numFiles; i++)\n      refItems[i] = CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType);\n\n    CSortParam sortParam;\n    // sortParam.TreeFolders = &treeFolders;\n    sortParam.SortByType = sortByType;\n    refItems.Sort(CompareUpdateItems, (void *)&sortParam);\n    \n    CObjArray<UInt32> indices(numFiles);\n\n    for (i = 0; i < numFiles; i++)\n    {\n      const UInt32 index = refItems[i].Index;\n      indices[i] = index;\n      /*\n      const CUpdateItem &ui = updateItems[index];\n      CFileItem file;\n      if (ui.NewProps)\n        UpdateItem_To_FileItem(ui, file);\n      else\n        file = db.Files[ui.IndexInArchive];\n      if (file.IsAnti || file.IsDir)\n        return E_FAIL;\n      newDatabase.Files.Add(file);\n      */\n    }\n    \n    for (i = 0; i < numFiles;)\n    {\n      UInt64 totalSize = 0;\n      unsigned numSubFiles;\n      \n      const wchar_t *prevExtension = NULL;\n      \n      for (numSubFiles = 0; i + numSubFiles < numFiles && numSubFiles < numSolidFiles; numSubFiles++)\n      {\n        const CUpdateItem &ui = updateItems[indices[i + numSubFiles]];\n        totalSize += ui.Size;\n        if (totalSize > options.NumSolidBytes)\n          break;\n        if (options.SolidExtension)\n        {\n          const int slashPos = ui.Name.ReverseFind_PathSepar();\n          const int dotPos = ui.Name.ReverseFind_Dot();\n          const wchar_t *ext = ui.Name.Ptr(dotPos <= slashPos ? ui.Name.Len() : (unsigned)(dotPos + 1));\n          if (numSubFiles == 0)\n            prevExtension = ext;\n          else if (!StringsAreEqualNoCase(ext, prevExtension))\n            break;\n        }\n      }\n\n      if (numSubFiles < 1)\n        numSubFiles = 1;\n\n      RINOK(lps->SetCur())\n\n      /*\n      const unsigned folderIndex = newDatabase.NumUnpackStreamsVector.Size();\n\n      if (opCallback)\n      {\n        RINOK(opCallback->ReportOperation(\n            NEventIndexType::kBlockIndex, (UInt32)folderIndex,\n            NUpdateNotifyOp::kAdd));\n      }\n      */\n\n\n      CMyComPtr2_Create<ISequentialInStream, CFolderInStream> inStreamSpec; // solidInStream;\n\n      // inStreamSpec->_reportArcProp = reportArcProp;\n      \n      inStreamSpec->Need_CTime = options.Need_CTime;\n      inStreamSpec->Need_ATime = options.Need_ATime;\n      inStreamSpec->Need_MTime = options.Need_MTime;\n      inStreamSpec->Need_Attrib = options.Need_Attrib;\n      // inStreamSpec->Need_Crc = options.Need_Crc;\n\n      inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);\n      \n      unsigned startPackIndex = newDatabase.PackSizes.Size();\n      // UInt64 curFolderUnpackSize = totalSize;\n      // curFolderUnpackSize = (UInt64)(Int64)-1; // for debug\n      const UInt64 expectedDataSize = totalSize;\n\n      // const unsigned folderIndex_New = newDatabase.Folders.Size();\n      \n      RINOK(encoder.Encode1(\n          EXTERNAL_CODECS_LOC_VARS\n          inStreamSpec,\n          // NULL,\n          &inSizeForReduce,\n          expectedDataSize, // expected size\n          newDatabase.Folders.AddNew(),\n          // newDatabase.CoderUnpackSizes, curFolderUnpackSize,\n          archive.SeqStream, newDatabase.PackSizes, lps))\n\n      if (!inStreamSpec->WasFinished())\n        return E_FAIL;\n\n      /*\n      if (inStreamSpec->Need_FolderCrc)\n        newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New,\n            true, inStreamSpec->GetFolderCrc());\n      */\n\n      const UInt64 curFolderUnpackSize = inStreamSpec->Get_TotalSize_for_Coder();\n      encoder.Encode_Post(curFolderUnpackSize, newDatabase.CoderUnpackSizes);\n\n      UInt64 packSize = 0;\n      // const UInt32 numStreams = newDatabase.PackSizes.Size() - startPackIndex;\n      for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)\n        packSize += newDatabase.PackSizes[startPackIndex];\n      lps->OutSize += packSize;\n\n      // for ()\n      // newDatabase.PackCRCsDefined.Add(false);\n      // newDatabase.PackCRCs.Add(0);\n\n      CNum numUnpackStreams = 0;\n      UInt64 skippedSize = 0;\n      UInt64 procSize = 0;\n      // unsigned numProcessedFiles = 0;\n\n      for (unsigned subIndex = 0; subIndex < numSubFiles; subIndex++)\n      {\n        const CUpdateItem &ui = updateItems[indices[i + subIndex]];\n        CFileItem file;\n        CFileItem2 file2;\n        UString name;\n        if (ui.NewProps)\n        {\n          UpdateItem_To_FileItem(ui, file, file2);\n          name = ui.Name;\n        }\n        else\n        {\n          GetFile(*db, (unsigned)ui.IndexInArchive, file, file2);\n          db->GetPath((unsigned)ui.IndexInArchive, name);\n        }\n        if (file2.IsAnti || file.IsDir)\n          return E_FAIL;\n        \n        /*\n        CFileItem &file = newDatabase.Files[\n              startFileIndexInDatabase + i + subIndex];\n        */\n        if (!inStreamSpec->Processed[subIndex])\n        {\n          // we don't add file here\n          skippedSize += ui.Size;\n          continue; // comment it for debug\n          // name += \".locked\"; // for debug\n        }\n\n        // if (inStreamSpec->Need_Crc)\n        file.Crc = inStreamSpec->CRCs[subIndex];\n        file.Size = inStreamSpec->Sizes[subIndex];\n        \n        procSize += file.Size;\n        // if (file.Size >= 0) // for debug: test purposes\n        if (file.Size != 0)\n        {\n          file.CrcDefined = true; // inStreamSpec->Need_Crc;\n          file.HasStream = true;\n          numUnpackStreams++;\n        }\n        else\n        {\n          file.CrcDefined = false;\n          file.HasStream = false;\n        }\n\n        if (inStreamSpec->TimesDefined[subIndex])\n        {\n          if (inStreamSpec->Need_CTime)\n            { file2.CTimeDefined = true;  file2.CTime = inStreamSpec->CTimes[subIndex]; }\n          if (inStreamSpec->Need_ATime\n              // && !ui.ATime_WasReadByAnalysis\n              )\n            { file2.ATimeDefined = true;  file2.ATime = inStreamSpec->ATimes[subIndex]; }\n          if (inStreamSpec->Need_MTime)\n            { file2.MTimeDefined = true;  file2.MTime = inStreamSpec->MTimes[subIndex]; }\n          if (inStreamSpec->Need_Attrib)\n          {\n            file2.AttribDefined = true;\n            file2.Attrib = inStreamSpec->Attribs[subIndex];\n          }\n        }\n\n        /*\n        file.Parent = ui.ParentFolderIndex;\n        if (ui.TreeFolderIndex >= 0)\n          treeFolderToArcIndex[ui.TreeFolderIndex] = newDatabase.Files.Size();\n        if (totalSecureDataSize != 0)\n          newDatabase.SecureIDs.Add(ui.SecureIndex);\n        */\n        /*\n        if (reportArcProp)\n        {\n          RINOK(ReportItemProps(reportArcProp, ui.IndexInClient, file.Size,\n              file.CrcDefined ? &file.Crc : NULL))\n        }\n        */\n\n        // numProcessedFiles++;\n        newDatabase.AddFile(file, file2, name);\n      }\n\n      /*\n      // for debug:\n      // we can write crc to folders area, if folder contains only one file\n      if (numUnpackStreams == 1 && numSubFiles == 1)\n      {\n        const CFileItem &file = newDatabase.Files.Back();\n        if (file.CrcDefined)\n          newDatabase.FolderUnpackCRCs.SetItem(folderIndex_New, true, file.Crc);\n      }\n      */\n\n      /*\n      // it's optional check to ensure that sizes are correct\n      if (inStreamSpec->TotalSize_for_Coder != curFolderUnpackSize)\n        return E_FAIL;\n      */\n      // if (inStreamSpec->AlignLog == 0)\n      {\n        if (procSize != curFolderUnpackSize)\n          return E_FAIL;\n      }\n      // else\n      {\n        /*\n        {\n          const CFolder &old = newDatabase.Folders.Back();\n          CFolder &folder = newDatabase.Folders.AddNew();\n          {\n            const unsigned numBonds = old.Bonds.Size();\n            folder.Bonds.SetSize(numBonds + 1);\n            for (unsigned k = 0; k < numBonds; k++)\n              folder.Bonds[k] = old.Bonds[k];\n            CBond &bond = folder.Bonds[numBonds];\n            bond.PackIndex = 0;\n            bond.UnpackIndex = 0;\n          }\n          {\n            const unsigned numCoders = old.Coders.Size();\n            folder.Coders.SetSize(numCoders + 1);\n            for (unsigned k = 0; k < numCoders; k++)\n              folder.Coders[k] = old.Coders[k];\n            CCoderInfo &cod = folder.Coders[numCoders];\n            cod.Props.Alloc(1);\n            cod.Props[0] = (Byte)inStreamSpec->AlignLog;\n            cod.NumStreams = 1;\n          }\n          {\n            const unsigned numPackStreams = old.Coders.Size();\n            folder.Coders.SetSize(numPackStreams);\n            for (unsigned k = 0; k < numPackStreams; k++)\n              folder.PackStreams[k] = old.PackStreams[k];\n          }\n        }\n        newDatabase.Folders.Delete(newDatabase.Folders.Size() - 2);\n        */\n      }\n\n\n      lps->InSize += procSize;\n      // lps->InSize += curFolderUnpackSize;\n\n      // numUnpackStreams = 0 is very bad case for locked files\n      // v3.13 doesn't understand it.\n      newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);\n      i += numSubFiles;\n\n      if (skippedSize != 0 && complexity >= skippedSize)\n      {\n        complexity -= skippedSize;\n        RINOK(updateCallback->SetTotal(complexity))\n      }\n\n      /*\n      if (reportArcProp)\n      {\n        PROPVARIANT prop;\n        prop.vt = VT_EMPTY;\n        prop.wReserved1 = 0;\n        {\n          NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numProcessedFiles);\n          RINOK(reportArcProp->ReportProp(\n              NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumSubFiles, &prop));\n        }\n        {\n          NWindows::NCOM::PropVarEm_Set_UInt64(&prop, curFolderUnpackSize);\n          RINOK(reportArcProp->ReportProp(\n              NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidSize, &prop));\n        }\n        {\n          NWindows::NCOM::PropVarEm_Set_UInt64(&prop, packSize);\n          RINOK(reportArcProp->ReportProp(\n              NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidPackSize, &prop));\n        }\n        {\n          NWindows::NCOM::PropVarEm_Set_UInt32(&prop, numStreams);\n          RINOK(reportArcProp->ReportProp(\n              NEventIndexType::kBlockIndex, (UInt32)folderIndex, kpidNumStreams, &prop));\n        }\n        RINOK(reportArcProp->ReportFinished(NEventIndexType::kBlockIndex, (UInt32)folderIndex, NUpdate::NOperationResult::kOK));\n      }\n      */\n      /*\n      if (opCallback)\n      {\n        RINOK(opCallback->ReportOperation(\n            NEventIndexType::kBlockIndex, (UInt32)folderIndex,\n            NUpdateNotifyOp::kOpFinished));\n      }\n      */\n    }\n  }\n\n  RINOK(lps->SetCur())\n\n  /*\n  fileIndexToUpdateIndexMap.ClearAndFree();\n  groups.ClearAndFree();\n  */\n\n  /*\n  for (i = 0; i < newDatabase.Files.Size(); i++)\n  {\n    CFileItem &file = newDatabase.Files[i];\n    file.Parent = treeFolderToArcIndex[file.Parent];\n  }\n\n  if (totalSecureDataSize != 0)\n  {\n    newDatabase.SecureBuf.SetCapacity(totalSecureDataSize);\n    size_t pos = 0;\n    newDatabase.SecureSizes.Reserve(secureBlocks.Sorted.Size());\n    for (i = 0; i < secureBlocks.Sorted.Size(); i++)\n    {\n      const CByteBuffer &buf = secureBlocks.Bufs[secureBlocks.Sorted[i]];\n      size_t size = buf.GetCapacity();\n      if (size != 0)\n        memcpy(newDatabase.SecureBuf + pos, buf, size);\n      newDatabase.SecureSizes.Add((UInt32)size);\n      pos += size;\n    }\n  }\n  */\n\n  {\n    const unsigned numFolders = newDatabase.Folders.Size();\n    if (newDatabase.NumUnpackStreamsVector.Size() != numFolders\n        || newDatabase.FolderUnpackCRCs.Defs.Size() > numFolders)\n      return E_FAIL;\n    newDatabase.FolderUnpackCRCs.if_NonEmpty_FillResidue_with_false(numFolders);\n  }\n  \n  updateItems.ClearAndFree();\n  newDatabase.ReserveDown();\n\n  if (opCallback)\n    RINOK(opCallback->ReportOperation(NEventIndexType::kNoIndex, (UInt32)(Int32)-1, NUpdateNotifyOp::kHeader))\n\n  RINOK(archive.WriteDatabase(EXTERNAL_CODECS_LOC_VARS\n      newDatabase, options.HeaderMethod, options.HeaderOptions))\n\n  if (v_StreamSetRestriction)\n    RINOK(v_StreamSetRestriction->SetRestriction(0, 0))\n\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/7zUpdate.h",
    "content": "﻿// 7zUpdate.h\n\n#ifndef ZIP7_INC_7Z_UPDATE_H\n#define ZIP7_INC_7Z_UPDATE_H\n\n#include \"../IArchive.h\"\n\n// #include \"../../Common/UniqBlocks.h\"\n\n#include \"7zCompressionMode.h\"\n#include \"7zIn.h\"\n\nnamespace NArchive {\nnamespace N7z {\n\n/*\nstruct CTreeFolder\n{\n  UString Name;\n  int Parent;\n  CIntVector SubFolders;\n  int UpdateItemIndex;\n  int SortIndex;\n  int SortIndexEnd;\n\n  CTreeFolder(): UpdateItemIndex(-1) {}\n};\n*/\n\nstruct CUpdateItem\n{\n  int IndexInArchive;\n  unsigned IndexInClient;\n  \n  UInt64 CTime;\n  UInt64 ATime;\n  UInt64 MTime;\n\n  UInt64 Size;\n  UString Name;\n  /*\n  bool IsAltStream;\n  int ParentFolderIndex;\n  int TreeFolderIndex;\n  */\n\n  // that code is not used in 9.26\n  // int ParentSortIndex;\n  // int ParentSortIndexEnd;\n\n  UInt32 Attrib;\n  \n  bool NewData;\n  bool NewProps;\n\n  bool IsAnti;\n  bool IsDir;\n\n  bool AttribDefined;\n  bool CTimeDefined;\n  bool ATimeDefined;\n  bool MTimeDefined;\n\n  // bool ATime_WasReadByAnalysis;\n\n  // int SecureIndex; // 0 means (no_security)\n\n  bool HasStream() const { return !IsDir && !IsAnti && Size != 0; }\n  // bool HasStream() const { return !IsDir && !IsAnti /* && Size != 0 */; } // for test purposes\n\n  CUpdateItem():\n      // ParentSortIndex(-1),\n      // IsAltStream(false),\n      IsAnti(false),\n      IsDir(false),\n      AttribDefined(false),\n      CTimeDefined(false),\n      ATimeDefined(false),\n      MTimeDefined(false)\n      // , ATime_WasReadByAnalysis(false)\n      // SecureIndex(0)\n      {}\n  void SetDirStatusFromAttrib() { IsDir = ((Attrib & FILE_ATTRIBUTE_DIRECTORY) != 0); }\n\n  // unsigned GetExtensionPos() const;\n  // UString GetExtension() const;\n};\n\nstruct CUpdateOptions\n{\n  const CCompressionMethodMode *Method;\n  const CCompressionMethodMode *HeaderMethod;\n  bool UseFilters; // use additional filters for some files\n  bool MaxFilter;  // use BCJ2 filter instead of BCJ\n  int AnalysisLevel;\n\n  UInt64 NumSolidFiles;\n  UInt64 NumSolidBytes;\n  bool SolidExtension;\n  \n  bool UseTypeSorting;\n  \n  bool RemoveSfxBlock;\n  bool MultiThreadMixer;\n\n  bool Need_CTime;\n  bool Need_ATime;\n  bool Need_MTime;\n  bool Need_Attrib;\n  // bool Need_Crc;\n\n  CHeaderOptions HeaderOptions;\n\n  CUIntVector DisabledFilterIDs;\n\n  void Add_DisabledFilter_for_id(UInt32 id,\n      const CUIntVector &enabledFilters)\n  {\n    if (enabledFilters.FindInSorted(id) < 0)\n      DisabledFilterIDs.AddToUniqueSorted(id);\n  }\n\n  void SetFilterSupporting_ver_enabled_disabled(\n      UInt32 compatVer,\n      const CUIntVector &enabledFilters,\n      const CUIntVector &disabledFilters)\n  {\n    DisabledFilterIDs = disabledFilters;\n    if (compatVer < 2300) Add_DisabledFilter_for_id(k_ARM64, enabledFilters);\n    if (compatVer < 2402) Add_DisabledFilter_for_id(k_RISCV, enabledFilters);\n  }\n\n  CUpdateOptions():\n      Method(NULL),\n      HeaderMethod(NULL),\n      UseFilters(false),\n      MaxFilter(false),\n      AnalysisLevel(-1),\n      NumSolidFiles((UInt64)(Int64)(-1)),\n      NumSolidBytes((UInt64)(Int64)(-1)),\n      SolidExtension(false),\n      UseTypeSorting(true),\n      RemoveSfxBlock(false),\n      MultiThreadMixer(true),\n      Need_CTime(false),\n      Need_ATime(false),\n      Need_MTime(false),\n      Need_Attrib(false)\n      // , Need_Crc(true)\n  {\n    DisabledFilterIDs.Add(k_RISCV);\n  }\n};\n\nHRESULT Update(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    IInStream *inStream,\n    const CDbEx *db,\n    CObjectVector<CUpdateItem> &updateItems,\n    // const CObjectVector<CTreeFolder> &treeFolders, // treeFolders[0] is root\n    // const CUniqBlocks &secureBlocks,\n    ISequentialOutStream *seqOutStream,\n    IArchiveUpdateCallback *updateCallback,\n    const CUpdateOptions &options);\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/7z/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ApfsHandler.cpp",
    "content": "﻿// ApfsHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/Sha256.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer2.h\"\n#include \"../../Common/MyLinux.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariantConv.h\"\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/ItemNameUtils.h\"\n\n#include \"HfsHandler.h\"\n\n// if APFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files.\n#define APFS_SHOW_ALT_STREAMS\n\n#define VI_MINUS1   ((unsigned)(int)-1)\n#define IsViDef(x)      ((int)(x) != -1)\n#define IsViNotDef(x)   ((int)(x) == -1)\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define G16(_offs_, dest) dest = Get16(p + (_offs_));\n#define G32(_offs_, dest) dest = Get32(p + (_offs_));\n#define G64(_offs_, dest) dest = Get64(p + (_offs_));\n\nnamespace NArchive {\nnamespace NApfs {\n\nstruct CUuid\n{\n  Byte Data[16];\n\n  void SetHex_To_str(char *s) const\n  {\n    ConvertDataToHex_Lower(s, Data, sizeof(Data));\n  }\n\n  void AddHexToString(UString &dest) const\n  {\n    char temp[sizeof(Data) * 2 + 4];\n    SetHex_To_str(temp);\n    dest += temp;\n  }\n\n  void SetFrom(const Byte *p) { memcpy(Data, p, 16); }\n};\n\n\ntypedef UInt64  oid_t;\ntypedef UInt64  xid_t;\n// typedef Int64   paddr_t;\ntypedef UInt64   paddr_t_unsigned;\n\n#define G64o G64\n#define G64x G64\n// #define G64a G64\n\n/*\nstruct prange_t\n{\n  paddr_t start_paddr;\n  UInt64 block_count;\n  \n  void Parse(const Byte *p)\n  {\n    G64a (0, start_paddr);\n    G64 (8, block_count);\n  }\n};\n*/\n\n#define OBJECT_TYPE_NX_SUPERBLOCK       0x1\n#define OBJECT_TYPE_BTREE               0x2\n#define OBJECT_TYPE_BTREE_NODE          0x3\n/*\n#define OBJECT_TYPE_SPACEMAN            0x5\n#define OBJECT_TYPE_SPACEMAN_CAB        0x6\n#define OBJECT_TYPE_SPACEMAN_CIB        0x7\n#define OBJECT_TYPE_SPACEMAN_BITMAP     0x8\n#define OBJECT_TYPE_SPACEMAN_FREE_QUEUE 0x9\n#define OBJECT_TYPE_EXTENT_LIST_TREE    0xa\n*/\n#define OBJECT_TYPE_OMAP                0xb\n/*\n#define OBJECT_TYPE_CHECKPOINT_MAP      0xc\n*/\n#define OBJECT_TYPE_FS                  0xd\n#define OBJECT_TYPE_FSTREE              0xe\n/*\n#define OBJECT_TYPE_BLOCKREFTREE        0xf\n#define OBJECT_TYPE_SNAPMETATREE        0x10\n#define OBJECT_TYPE_NX_REAPER           0x11\n#define OBJECT_TYPE_NX_REAP_LIST        0x12\n#define OBJECT_TYPE_OMAP_SNAPSHOT       0x13\n#define OBJECT_TYPE_EFI_JUMPSTART       0x14\n#define OBJECT_TYPE_FUSION_MIDDLE_TREE  0x15\n#define OBJECT_TYPE_NX_FUSION_WBC       0x16\n#define OBJECT_TYPE_NX_FUSION_WBC_LIST  0x17\n#define OBJECT_TYPE_ER_STATE            0x18\n#define OBJECT_TYPE_GBITMAP             0x19\n#define OBJECT_TYPE_GBITMAP_TREE        0x1a\n#define OBJECT_TYPE_GBITMAP_BLOCK       0x1b\n#define OBJECT_TYPE_ER_RECOVERY_BLOCK   0x1c\n#define OBJECT_TYPE_SNAP_META_EXT       0x1d\n*/\n#define OBJECT_TYPE_INTEGRITY_META      0x1e\n#define OBJECT_TYPE_FEXT_TREE           0x1f\n/*\n#define OBJECT_TYPE_RESERVED_20         0x20\n\n#define OBJECT_TYPE_INVALID       0x0\n#define OBJECT_TYPE_TEST          0xff\n#define OBJECT_TYPE_CONTAINER_KEYBAG  'keys'\n#define OBJECT_TYPE_VOLUME_KEYBAG     'recs'\n#define OBJECT_TYPE_MEDIA_KEYBAG      'mkey'\n\n#define OBJ_VIRTUAL       0x0\n#define OBJ_EPHEMERAL     0x80000000\n*/\n#define OBJ_PHYSICAL      0x40000000\n/*\n#define OBJ_NOHEADER      0x20000000\n#define OBJ_ENCRYPTED     0x10000000\n#define OBJ_NONPERSISTENT 0x08000000\n*/\n#define OBJECT_TYPE_MASK                0x0000ffff\n/*\n#define OBJECT_TYPE_FLAGS_MASK          0xffff0000\n#define OBJ_STORAGETYPE_MASK            0xc0000000\n#define OBJECT_TYPE_FLAGS_DEFINED_MASK  0xf8000000\n*/\n\n// #define MAX_CKSUM_SIZE 8\n\nstatic const unsigned k_obj_phys_Size = 0x20;\n\n// obj_phys_t\nstruct CPhys\n{\n  // Byte cksum[MAX_CKSUM_SIZE];\n  oid_t oid;\n  xid_t xid;\n  UInt32 type;\n  UInt32 subtype;\n\n  UInt32 GetType() const { return type & OBJECT_TYPE_MASK; }\n  void Parse(const Byte *p);\n};\n\nvoid CPhys::Parse(const Byte *p)\n{\n  // memcpy(cksum, p, MAX_CKSUM_SIZE);\n  G64o (8, oid)\n  G64x (0x10, xid)\n  G32 (0x18, type)\n  G32 (0x1C, subtype)\n}\n\n#define NX_MAX_FILE_SYSTEMS   100\n/*\n#define NX_EPH_INFO_COUNT   4\n#define NX_EPH_MIN_BLOCK_COUNT  8\n#define NX_MAX_FILE_SYSTEM_EPH_STRUCTS  4\n#define NX_TX_MIN_CHECKPOINT_COUNT  4\n#define NX_EPH_INFO_VERSION_1   1\n*/\n\n/*\ntypedef enum\n{\n  NX_CNTR_OBJ_CKSUM_SET = 0,\n  NX_CNTR_OBJ_CKSUM_FAIL = 1,\n  NX_NUM_COUNTERS = 32\n} counter_id_t;\n*/\n\n/* Incompatible volume feature flags */\n#define APFS_INCOMPAT_CASE_INSENSITIVE          (1 << 0)\n/*\n#define APFS_INCOMPAT_DATALESS_SNAPS            (1 << 1)\n#define APFS_INCOMPAT_ENC_ROLLED                (1 << 2)\n*/\n#define APFS_INCOMPAT_NORMALIZATION_INSENSITIVE (1 << 3)\n/*\n#define APFS_INCOMPAT_INCOMPLETE_RESTORE        (1 << 4)\n*/\n#define APFS_INCOMPAT_SEALED_VOLUME             (1 << 5)\n/*\n#define APFS_INCOMPAT_RESERVED_40               (1 << 6)\n*/\n\nstatic const char * const g_APFS_INCOMPAT_Flags[] =\n{\n    \"CASE_INSENSITIVE\"\n  , \"DATALESS_SNAPS\"\n  , \"ENC_ROLLED\"\n  , \"NORMALIZATION_INSENSITIVE\"\n  , \"INCOMPLETE_RESTORE\"\n  , \"SEALED_VOLUME\"\n};\n\n/*\n#define APFS_SUPPORTED_INCOMPAT_MASK \\\n    ( APFS_INCOMPAT_CASE_INSENSITIVE \\\n    | APFS_INCOMPAT_DATALESS_SNAPS \\\n    | APFS_INCOMPAT_ENC_ROLLED \\\n    | APFS_INCOMPAT_NORMALIZATION_INSENSITIVE \\\n    | APFS_INCOMPAT_INCOMPLETE_RESTORE \\\n    | APFS_INCOMPAT_SEALED_VOLUME \\\n    | APFS_INCOMPAT_RESERVED_40 \\\n)\n*/\n\n// superblock_t\nstruct CSuperBlock\n{\n  // CPhys o;\n  // UInt32 magic;\n  UInt32 block_size;\n  unsigned block_size_Log;\n  UInt64 block_count;\n  // UInt64 features;\n  // UInt64 readonly_compatible_features;\n  // UInt64 incompatible_features;\n  CUuid uuid;\n  /*\n  oid_t next_oid;\n  xid_t next_xid;\n  UInt32 xp_desc_blocks;\n  UInt32 xp_data_blocks;\n  paddr_t xp_desc_base;\n  paddr_t xp_data_base;\n  UInt32 xp_desc_next;\n  UInt32 xp_data_next;\n  UInt32 xp_desc_index;\n  UInt32 xp_desc_len;\n  UInt32 xp_data_index;\n  UInt32 xp_data_len;\n  oid_t spaceman_oid;\n  */\n  oid_t omap_oid;\n  // oid_t reaper_oid;\n  // UInt32 test_type;\n  UInt32 max_file_systems;\n  // oid_t fs_oid[NX_MAX_FILE_SYSTEMS];\n  /*\n  UInt64 counters[NX_NUM_COUNTERS]; // counter_id_t\n  prange_t blocked_out_prange;\n  oid_t evict_mapping_tree_oid;\n  UInt64 flags;\n  paddr_t efi_jumpstart;\n  CUuid fusion_uuid;\n  prange_t keylocker;\n  UInt64 ephemeral_info[NX_EPH_INFO_COUNT];\n  oid_t test_oid;\n  oid_t fusion_mt_oid;\n  oid_t fusion_wbc_oid;\n  prange_t fusion_wbc;\n  UInt64 newest_mounted_version;\n  prange_t mkb_locker;\n  */\n\n  bool Parse(const Byte *p);\n};\n\nstruct CSuperBlock2\n{\n  oid_t fs_oid[NX_MAX_FILE_SYSTEMS];\n  void Parse(const Byte *p)\n  {\n    for (unsigned i = 0; i < NX_MAX_FILE_SYSTEMS; i++)\n    {\n      G64o (0xb8 + i * 8, fs_oid[i])\n    }\n  }\n};\n\n\n// we include one additional byte of next field (block_size)\nstatic const unsigned k_SignatureOffset = 32;\nstatic const Byte k_Signature[] = { 'N', 'X', 'S', 'B', 0 };\n\n// size must be 4 bytes aligned\nstatic UInt64 Fletcher64(const Byte *data, size_t size)\n{\n  const UInt32 kMax32 = 0xffffffff;\n  const UInt64 val = 0; // startVal\n  UInt64 a = val & kMax32;\n  UInt64 b = (val >> 32) & kMax32;\n  for (size_t i = 0; i < size; i += 4)\n  {\n    a += GetUi32(data + i);\n    b += a;\n  }\n  a %= kMax32;\n  b %= kMax32;\n  b = (UInt32)(kMax32 - ((a + b) % kMax32));\n  a = (UInt32)(kMax32 - ((a + b) % kMax32));\n  return (a << 32) | b;\n}\n\nstatic bool CheckFletcher64(const Byte *p, size_t size)\n{\n  const UInt64 calculated_checksum = Fletcher64(p + 8, size - 8);\n  const UInt64 stored_checksum = Get64(p);\n  return (stored_checksum == calculated_checksum);\n}\n\n\nstatic unsigned GetLogSize(UInt32 size)\n{\n  unsigned k;\n  for (k = 0; k < 32; k++)\n    if (((UInt32)1 << k) == size)\n      return k;\n  return k;\n}\n\nstatic const unsigned kApfsHeaderSize = 1 << 12;\n\n// #define OID_INVALID         0\n#define OID_NX_SUPERBLOCK   1\n// #define OID_RESERVED_COUNT  1024\n// This range of identifiers is reserved for physical, virtual, and ephemeral objects\n\nbool CSuperBlock::Parse(const Byte *p)\n{\n  CPhys o;\n  o.Parse(p);\n  if (o.oid != OID_NX_SUPERBLOCK)\n    return false;\n  if (o.GetType() != OBJECT_TYPE_NX_SUPERBLOCK)\n    return false;\n  if (o.subtype != 0)\n    return false;\n  if (memcmp(p + k_SignatureOffset, k_Signature, 4) != 0)\n    return false;\n  if (!CheckFletcher64(p, kApfsHeaderSize))\n    return false;\n\n  G32 (0x24, block_size)\n  {\n    const unsigned logSize = GetLogSize(block_size);\n    // don't change it. Some code requires (block_size <= 16)\n    if (logSize < 12 || logSize > 16)\n      return false;\n    block_size_Log = logSize;\n  }\n\n  G64 (0x28, block_count)\n\n  const UInt64 kArcSize_MAX = (UInt64)1 << 62;\n  if (block_count > (kArcSize_MAX >> block_size_Log))\n    return false;\n\n  // G64 (0x30, features);\n  // G64 (0x38, readonly_compatible_features);\n  // G64 (0x40, incompatible_features);\n  uuid.SetFrom(p + 0x48);\n  /*\n  G64o (0x58, next_oid);\n  G64x (0x60, next_xid);\n  G32 (0x68, xp_desc_blocks);\n  G32 (0x6c, xp_data_blocks);\n  G64a (0x70, xp_desc_base);\n  G64a (0x78, xp_data_base);\n  G32 (0x80, xp_desc_next);\n  G32 (0x84, xp_data_next);\n  G32 (0x88, xp_desc_index);\n  G32 (0x8c, xp_desc_len);\n  G32 (0x90, xp_data_index);\n  G32 (0x94, xp_data_len);\n  G64o (0x98, spaceman_oid);\n  */\n  G64o (0xa0, omap_oid)\n  // G64o (0xa8, reaper_oid);\n  // G32 (0xb0, test_type);\n  G32 (0xb4, max_file_systems)\n  if (max_file_systems > NX_MAX_FILE_SYSTEMS)\n    return false;\n  /*\n  {\n    for (unsigned i = 0; i < NX_MAX_FILE_SYSTEMS; i++)\n    {\n      G64o (0xb8 + i * 8, fs_oid[i]);\n    }\n  }\n  */\n  /*\n  {\n    for (unsigned i = 0; i < NX_NUM_COUNTERS; i++)\n    {\n      G64 (0x3d8 + i * 8, counters[i]);\n    }\n  }\n  blocked_out_prange.Parse(p + 0x4d8);\n  G64o (0x4e8, evict_mapping_tree_oid);\n  #define NX_CRYPTO_SW 0x00000004LL\n  G64 (0x4f0, flags);\n  G64a (0x4f8, efi_jumpstart);\n  fusion_uuid.SetFrom(p + 0x500);\n  keylocker.Parse(p + 0x510);\n  {\n    for (unsigned i = 0; i < NX_EPH_INFO_COUNT; i++)\n    {\n      G64 (0x520 + i * 8, ephemeral_info[i]);\n    }\n  }\n  G64o (0x540, test_oid);\n  G64o (0x548, fusion_mt_oid);\n  G64o (0x550, fusion_wbc_oid);\n  fusion_wbc.Parse(p + 0x558);\n  G64 (0x568, newest_mounted_version); // decimal 1412141 001 000 000\n  mkb_locker.Parse(p + 0x570);\n  */\n\n  return true;\n}\n\n\nenum apfs_hash_type_t\n{\n  APFS_HASH_INVALID = 0,\n  APFS_HASH_SHA256 = 1,\n  APFS_HASH_SHA512_256 = 2,\n  APFS_HASH_SHA384 = 3,\n  APFS_HASH_SHA512 = 4,\n\n  APFS_HASH_MIN = APFS_HASH_SHA256,\n  APFS_HASH_MAX = APFS_HASH_SHA512,\n\n  APFS_HASH_DEFAULT = APFS_HASH_SHA256\n};\n\nstatic unsigned GetHashSize(unsigned hashType)\n{\n  if (hashType > APFS_HASH_MAX) return 0;\n  if (hashType < APFS_HASH_MIN) return 0;\n  if (hashType == APFS_HASH_SHA256) return 32;\n  return hashType * 16;\n}\n\n#define APFS_HASH_MAX_SIZE 64\n\nstatic const char * const g_hash_types[] =\n{\n    NULL\n  , \"SHA256\"\n  , \"SHA512_256\"\n  , \"SHA384\"\n  , \"SHA512\"\n};\n\n\nstruct C_integrity_meta_phys\n{\n  // CPhys im_o;\n  // UInt32 im_version;\n  UInt32 im_flags;\n  // apfs_hash_type_t\n  UInt32 im_hash_type;\n  // UInt32 im_root_hash_offset;\n  // xid_t im_broken_xid;\n  // UInt64 im_reserved[9];\n\n  unsigned HashSize;\n  Byte Hash[APFS_HASH_MAX_SIZE];\n\n  bool Is_SHA256() const { return im_hash_type == APFS_HASH_SHA256; }\n\n  C_integrity_meta_phys()\n  {\n    memset(this, 0, sizeof(*this));\n  }\n  bool Parse(const Byte *p, size_t size, oid_t oid);\n};\n\nbool C_integrity_meta_phys::Parse(const Byte *p, size_t size, oid_t oid)\n{\n  CPhys o;\n  if (!CheckFletcher64(p, size))\n    return false;\n  o.Parse(p);\n  if (o.GetType() != OBJECT_TYPE_INTEGRITY_META)\n    return false;\n  if (o.oid != oid)\n    return false;\n  // G32 (0x20, im_version);\n  G32 (0x24, im_flags)\n  G32 (0x28, im_hash_type)\n  UInt32 im_root_hash_offset;\n  G32 (0x2C, im_root_hash_offset)\n  // G64x (0x30, im_broken_xid);\n  const unsigned hashSize = GetHashSize(im_hash_type);\n  HashSize = hashSize;\n  if (im_root_hash_offset >= size || size - im_root_hash_offset < hashSize)\n    return false;\n  memcpy(Hash, p + im_root_hash_offset, hashSize);\n  return true;\n}\n\n\nstruct C_omap_phys\n{\n  // om_ prefix\n  // CPhys o;\n  /*\n  UInt32 flags;\n  UInt32 snap_count;\n  UInt32 tree_type;\n  UInt32 snapshot_tree_type;\n  */\n  oid_t tree_oid;\n  /*\n  oid_t snapshot_tree_oid;\n  xid_t most_recent_snap;\n  xid_t pending_revert_min;\n  xid_t pending_revert_max;\n  */\n  bool Parse(const Byte *p, size_t size, oid_t oid);\n};\n\nbool C_omap_phys::Parse(const Byte *p, size_t size, oid_t oid)\n{\n  CPhys o;\n  if (!CheckFletcher64(p, size))\n    return false;\n  o.Parse(p);\n  if (o.GetType() != OBJECT_TYPE_OMAP)\n    return false;\n  if (o.oid != oid)\n    return false;\n  /*\n  G32 (0x20, flags);\n  G32 (0x24, snap_count);\n  G32 (0x28, tree_type);\n  G32 (0x2C, snapshot_tree_type);\n  */\n  G64o (0x30, tree_oid)\n  /*\n  G64o (0x38, snapshot_tree_oid);\n  G64x (0x40, most_recent_snap);\n  G64x (0x48, pending_revert_min);\n  G64x (0x50, pending_revert_max);\n  */\n  return true;\n}\n\n\n// #define BTOFF_INVALID 0xffff\n/* This value is stored in the off field of nloc_t to indicate that\nthere's no offset. For example, the last entry in a free\nlist has no entry after it, so it uses this value for its off field. */\n\n// A location within a B-tree node\nstruct nloc\n{\n  UInt16 off;\n  UInt16 len;\n  \n  void Parse(const Byte *p)\n  {\n    G16 (0, off)\n    G16 (2, len)\n  }\n  UInt32 GetEnd() const { return (UInt32)off + len; }\n  bool CheckOverLimit(UInt32 limit)\n  {\n    return off < limit && len <= limit - off;\n  }\n};\n\n\n// The location, within a B-tree node, of a key and value\nstruct kvloc\n{\n  nloc k;\n  nloc v;\n  \n  void Parse(const Byte *p)\n  {\n    k.Parse(p);\n    v.Parse(p + 4);\n  }\n};\n\n\n// The location, within a B-tree node, of a fixed-size key and value\nstruct kvoff\n{\n  UInt16 k;\n  UInt16 v;\n\n  void Parse(const Byte *p)\n  {\n    G16 (0, k)\n    G16 (2, v)\n  }\n};\n\n\n#define BTNODE_ROOT             (1 << 0)\n#define BTNODE_LEAF             (1 << 1)\n#define BTNODE_FIXED_KV_SIZE    (1 << 2)\n#define BTNODE_HASHED           (1 << 3)\n#define BTNODE_NOHEADER         (1 << 4)\n/*\n#define BTNODE_CHECK_KOFF_INVAL (1 << 15)\n*/\n\nstatic const unsigned k_Toc_offset = 0x38;\n\n// btree_node_phys\nstruct CBTreeNodePhys\n{\n  // btn_ prefix\n  CPhys ophys;\n  UInt16 flags;\n  UInt16 level;       // the number of child levels below this node. 0 -  for a leaf node, 1 for the immediate parent of a leaf node\n  UInt32 nkeys;       // The number of keys stored in this node.\n  nloc table_space;\n  /*\n  nloc free_space;\n  nloc key_free_list;\n  nloc val_free_list;\n  */\n\n  bool Is_FIXED_KV_SIZE() const { return (flags & BTNODE_FIXED_KV_SIZE) != 0; }\n  bool Is_NOHEADER() const { return (flags & BTNODE_NOHEADER) != 0; }\n  bool Is_HASHED() const { return (flags & BTNODE_HASHED) != 0; }\n\n  bool Parse(const Byte *p, size_t size, bool noHeader = false)\n  {\n    G16 (0x20, flags)\n    G16 (0x22, level)\n    G32 (0x24, nkeys)\n    table_space.Parse(p + 0x28);\n    /*\n    free_space.Parse(p + 0x2C);\n    key_free_list.Parse(p + 0x30);\n    val_free_list.Parse(p + 0x34);\n    */\n    memset(&ophys, 0, sizeof(ophys));\n    if (noHeader)\n    {\n      for (unsigned i = 0; i < k_obj_phys_Size; i++)\n        if (p[i] != 0)\n          return false;\n    }\n    else\n    {\n      if (!CheckFletcher64(p, size))\n        return false;\n      ophys.Parse(p);\n    }\n    if (Is_NOHEADER() != noHeader)\n      return false;\n    return true;\n  }\n};\n\n/*\n#define BTREE_UINT64_KEYS       (1 << 0)\n#define BTREE_SEQUENTIAL_INSERT (1 << 1)\n#define BTREE_ALLOW_GHOSTS      (1 << 2)\n*/\n#define BTREE_EPHEMERAL         (1 << 3)\n#define BTREE_PHYSICAL          (1 << 4)\n/*\n#define BTREE_NONPERSISTENT     (1 << 5)\n#define BTREE_KV_NONALIGNED     (1 << 6)\n#define BTREE_HASHED            (1 << 7)\n*/\n#define BTREE_NOHEADER          (1 << 8)\n\n/*\n  BTREE_EPHEMERAL: The nodes in the B-tree use ephemeral object identifiers to link to child nodes\n  BTREE_PHYSICAL : The nodes in the B-tree use physical object identifiers to link to child nodes.\n  If neither flag is set, nodes in the B-tree use virtual object\n  identifiers to link to their child nodes.\n*/\n\n// Static information about a B-tree.\nstruct btree_info_fixed\n{\n  UInt32 flags;\n  UInt32 node_size;\n  UInt32 key_size;\n  UInt32 val_size;\n\n  void Parse(const Byte *p)\n  {\n    G32 (0, flags)\n    G32 (4, node_size)\n    G32 (8, key_size)\n    G32 (12, val_size)\n  }\n};\n\nstatic const unsigned k_btree_info_Size = 0x28;\n\nstruct btree_info\n{\n  btree_info_fixed fixed;\n  UInt32 longest_key;\n  UInt32 longest_val;\n  UInt64 key_count;\n  UInt64 node_count;\n\n  bool Is_EPHEMERAL() const { return (fixed.flags & BTREE_EPHEMERAL) != 0; }\n  bool Is_PHYSICAL()  const { return (fixed.flags & BTREE_PHYSICAL) != 0; }\n  bool Is_NOHEADER()  const { return (fixed.flags & BTREE_NOHEADER) != 0; }\n\n  void Parse(const Byte *p)\n  {\n    fixed.Parse(p);\n    G32 (0x10, longest_key)\n    G32 (0x14, longest_val)\n    G64 (0x18, key_count)\n    G64 (0x20, node_count)\n  }\n};\n\n\n/*\ntypedef UInt32  cp_key_class_t;\ntypedef UInt32  cp_key_os_version_t;\ntypedef UInt16  cp_key_revision_t;\ntypedef UInt32  crypto_flags_t;\n\nstruct wrapped_meta_crypto_state\n{\n  UInt16 major_version;\n  UInt16 minor_version;\n  crypto_flags_t cpflags;\n  cp_key_class_t persistent_class;\n  cp_key_os_version_t key_os_version;\n  cp_key_revision_t key_revision;\n  // UInt16 unused;\n\n  void Parse(const Byte *p)\n  {\n    G16 (0, major_version);\n    G16 (2, minor_version);\n    G32 (4, cpflags);\n    G32 (8, persistent_class);\n    G32 (12, key_os_version);\n    G16 (16, key_revision);\n  }\n};\n*/\n\n\n#define APFS_MODIFIED_NAMELEN 32\n#define sizeof_apfs_modified_by_t (APFS_MODIFIED_NAMELEN + 16)\n\nstruct apfs_modified_by_t\n{\n  Byte id[APFS_MODIFIED_NAMELEN];\n  UInt64 timestamp;\n  xid_t last_xid;\n  \n  void Parse(const Byte *p)\n  {\n    memcpy(id, p, APFS_MODIFIED_NAMELEN);\n    p += APFS_MODIFIED_NAMELEN;\n    G64 (0, timestamp)\n    G64x (8, last_xid)\n  }\n};\n\n\n#define APFS_MAX_HIST 8\n#define APFS_VOLNAME_LEN 256\n\nstruct CApfs\n{\n  // apfs_\n  CPhys o;\n  // UInt32 magic;\n  UInt32 fs_index; // index of the object identifier for this volume's file system in the container's array of file systems.\n  // UInt64 features;\n  // UInt64 readonly_compatible_features;\n  UInt64 incompatible_features;\n  UInt64 unmount_time;\n  // UInt64 fs_reserve_block_count;\n  // UInt64 fs_quota_block_count;\n  UInt64 fs_alloc_count;\n  // wrapped_meta_crypto_state meta_crypto;\n  // UInt32 root_tree_type;\n    /* The type of the root file-system tree.\n        The value is typically OBJ_VIRTUAL | OBJECT_TYPE_BTREE,\n        with a subtype of OBJECT_TYPE_FSTREE */\n\n  // UInt32 extentref_tree_type;\n  // UInt32 snap_meta_tree_type;\n  oid_t omap_oid;\n  oid_t root_tree_oid;\n  /*\n  oid_t extentref_tree_oid;\n  oid_t snap_meta_tree_oid;\n  xid_t revert_to_xid;\n  oid_t revert_to_sblock_oid;\n  UInt64 next_obj_id;\n  */\n  UInt64 num_files;\n  UInt64 num_directories;\n  UInt64 num_symlinks;\n  UInt64 num_other_fsobjects;\n  UInt64 num_snapshots;\n  UInt64 total_blocks_alloced;\n  UInt64 total_blocks_freed;\n  CUuid vol_uuid;\n  UInt64 last_mod_time;\n  UInt64 fs_flags;\n  apfs_modified_by_t formatted_by;\n  apfs_modified_by_t modified_by[APFS_MAX_HIST];\n  Byte volname[APFS_VOLNAME_LEN];\n  /*\n  UInt32 next_doc_id;\n  UInt16 role; //  APFS_VOL_ROLE_NONE   APFS_VOL_ROLE_SYSTEM ....\n  UInt16 reserved;\n  xid_t root_to_xid;\n  oid_t er_state_oid;\n  UInt64 cloneinfo_id_epoch;\n  UInt64 cloneinfo_xid;\n  oid_t snap_meta_ext_oid;\n  CUuid volume_group_id;\n  */\n  oid_t integrity_meta_oid; // virtual object identifier of the integrity metadata object\n  oid_t fext_tree_oid;      // virtual object identifier of the file extent tree.\n  UInt32 fext_tree_type;    // The type of the file extent tree.\n  /*\n  UInt32 reserved_type;\n  oid_t reserved_oid;\n  */\n\n  UInt64 GetTotalItems() const\n  {\n    return num_files + num_directories + num_symlinks + num_other_fsobjects;\n  }\n\n  bool IsHashedName() const\n  {\n    return\n      (incompatible_features & APFS_INCOMPAT_CASE_INSENSITIVE) != 0 ||\n      (incompatible_features & APFS_INCOMPAT_NORMALIZATION_INSENSITIVE) != 0;\n  }\n\n  bool Parse(const Byte *p, size_t size);\n};\n\n\nbool CApfs::Parse(const Byte *p, size_t size)\n{\n  o.Parse(p);\n  if (Get32(p + 32) != 0x42535041) //  { 'A', 'P', 'S', 'B' };\n    return false;\n  if (o.GetType() != OBJECT_TYPE_FS)\n    return false;\n  if (!CheckFletcher64(p, size))\n    return false;\n  // if (o.GetType() != OBJECT_TYPE_NX_SUPERBLOCK) return false;\n\n  G32 (0x24, fs_index)\n  // G64 (0x28, features);\n  // G64 (0x30, readonly_compatible_features);\n  G64 (0x38, incompatible_features)\n  G64 (0x40, unmount_time)\n  // G64 (0x48, fs_reserve_block_count);\n  // G64 (0x50, fs_quota_block_count);\n  G64 (0x58, fs_alloc_count)\n  // meta_crypto.Parse(p + 0x60);\n  // G32 (0x74, root_tree_type);\n  // G32 (0x78, extentref_tree_type);\n  // G32 (0x7C, snap_meta_tree_type);\n\n  G64o (0x80, omap_oid)\n  G64o (0x88, root_tree_oid)\n  /*\n  G64o (0x90, extentref_tree_oid);\n  G64o (0x98, snap_meta_tree_oid);\n  G64x (0xa0, revert_to_xid);\n  G64o (0xa8, revert_to_sblock_oid);\n  G64 (0xb0, next_obj_id);\n  */\n  G64 (0xb8, num_files)\n  G64 (0xc0, num_directories)\n  G64 (0xc8, num_symlinks)\n  G64 (0xd0, num_other_fsobjects)\n  G64 (0xd8, num_snapshots)\n  G64 (0xe0, total_blocks_alloced)\n  G64 (0xe8, total_blocks_freed)\n  vol_uuid.SetFrom(p + 0xf0);\n  G64 (0x100, last_mod_time)\n  G64 (0x108, fs_flags)\n  p += 0x110;\n  formatted_by.Parse(p);\n  p += sizeof_apfs_modified_by_t;\n  for (unsigned i = 0; i < APFS_MAX_HIST; i++)\n  {\n    modified_by[i].Parse(p);\n    p += sizeof_apfs_modified_by_t;\n  }\n  memcpy(volname, p, APFS_VOLNAME_LEN);\n  p += APFS_VOLNAME_LEN;\n  /*\n  G32 (0, next_doc_id);\n  G16 (4, role);\n  G16 (6, reserved);\n  G64x (8, root_to_xid);\n  G64o (0x10, er_state_oid);\n  G64 (0x18, cloneinfo_id_epoch);\n  G64 (0x20, cloneinfo_xid);\n  G64o (0x28, snap_meta_ext_oid);\n  volume_group_id.SetFrom(p + 0x30);\n  */\n  G64o (0x40, integrity_meta_oid)\n  G64o (0x48, fext_tree_oid)\n  G32 (0x50, fext_tree_type)\n  /*\n  G32 (0x54, reserved_type);\n  G64o (0x58, reserved_oid);\n  */\n  return true;\n}\n\n\n#define OBJ_ID_MASK         0x0fffffffffffffff\n/*\n#define OBJ_TYPE_MASK       0xf000000000000000\n#define SYSTEM_OBJ_ID_MARK  0x0fffffff00000000\n*/\n#define OBJ_TYPE_SHIFT      60\n\ntypedef enum\n{\n  APFS_TYPE_ANY           = 0,\n  APFS_TYPE_SNAP_METADATA = 1,\n  APFS_TYPE_EXTENT        = 2,\n  APFS_TYPE_INODE         = 3,\n  APFS_TYPE_XATTR         = 4,\n  APFS_TYPE_SIBLING_LINK  = 5,\n  APFS_TYPE_DSTREAM_ID    = 6,\n  APFS_TYPE_CRYPTO_STATE  = 7,\n  APFS_TYPE_FILE_EXTENT   = 8,\n  APFS_TYPE_DIR_REC       = 9,\n  APFS_TYPE_DIR_STATS     = 10,\n  APFS_TYPE_SNAP_NAME     = 11,\n  APFS_TYPE_SIBLING_MAP   = 12,\n  APFS_TYPE_FILE_INFO     = 13,\n  APFS_TYPE_MAX_VALID     = 13,\n  APFS_TYPE_MAX           = 15,\n  APFS_TYPE_INVALID       = 15\n} j_obj_types;\n\n\nstruct j_key_t\n{\n  UInt64 obj_id_and_type;\n\n  void Parse(const Byte *p) { G64(0, obj_id_and_type) }\n  unsigned GetType() const { return (unsigned)(obj_id_and_type >> OBJ_TYPE_SHIFT); }\n  UInt64 GetID() const { return obj_id_and_type & OBJ_ID_MASK; }\n};\n\n\n\n#define J_DREC_LEN_MASK   0x000003ff\n/*\n#define J_DREC_HASH_MASK  0xfffff400\n#define J_DREC_HASH_SHIFT 10\n*/\n\nstatic const unsigned k_SizeOf_j_drec_val = 0x12;\n\nstruct j_drec_val\n{\n  UInt64 file_id;\n  UInt64 date_added; /* The time that this directory entry was added to the directory.\n       It's not updated when modifying the directory entry for example,\n       by renaming a file without moving it to a different directory. */\n  UInt16 flags;\n\n  // bool IsFlags_File() const { return flags == MY_LIN_DT_REG; }\n  bool IsFlags_Unknown() const { return flags == MY_LIN_DT_UNKNOWN; }\n  bool IsFlags_Dir()     const { return flags == MY_LIN_DT_DIR; }\n\n  // uint8_t xfields[];\n  void Parse(const Byte *p)\n  {\n    G64 (0, file_id)\n    G64 (8, date_added)\n    G16 (0x10, flags)\n  }\n};\n\n\nstruct CItem\n{\n  // j_key_t hdr;\n  UInt64 ParentId;\n  AString Name;\n  j_drec_val Val;\n\n  unsigned ParentItemIndex;\n  unsigned RefIndex;\n  // unsigned  iNode_Index;\n  \n  void Clear()\n  {\n    Name.Empty();\n    ParentItemIndex = VI_MINUS1;\n    RefIndex = VI_MINUS1;\n  }\n};\n\n\n/*\n#define INVALID_INO_NUM       0\n#define ROOT_DIR_PARENT       1  // parent for \"root\" and \"private-dir\", there's no inode on disk with this inode number.\n*/\n#define ROOT_DIR_INO_NUM      2  // \"root\" - parent for all main files\n#define PRIV_DIR_INO_NUM      3  // \"private-dir\"\n/*\n#define SNAP_DIR_INO_NUM      6  //  the directory where snapshot metadata is stored. Snapshot inodes are stored in the snapshot metedata tree.\n#define PURGEABLE_DIR_INO_NUM 7\n#define MIN_USER_INO_NUM      16\n\n#define UNIFIED_ID_SPACE_MARK 0x0800000000000000\n*/\n\n//typedef enum\n// {\n/*\nINODE_IS_APFS_PRIVATE         = 0x00000001,\nINODE_MAINTAIN_DIR_STATS      = 0x00000002,\nINODE_DIR_STATS_ORIGIN        = 0x00000004,\nINODE_PROT_CLASS_EXPLICIT     = 0x00000008,\nINODE_WAS_CLONED              = 0x00000010,\nINODE_FLAG_UNUSED             = 0x00000020,\nINODE_HAS_SECURITY_EA         = 0x00000040,\nINODE_BEING_TRUNCATED         = 0x00000080,\nINODE_HAS_FINDER_INFO         = 0x00000100,\nINODE_IS_SPARSE               = 0x00000200,\nINODE_WAS_EVER_CLONED         = 0x00000400,\nINODE_ACTIVE_FILE_TRIMMED     = 0x00000800,\nINODE_PINNED_TO_MAIN          = 0x00001000,\nINODE_PINNED_TO_TIER2         = 0x00002000,\n*/\n// INODE_HAS_RSRC_FORK           = 0x00004000,\n/*\nINODE_NO_RSRC_FORK            = 0x00008000,\nINODE_ALLOCATION_SPILLEDOVER  = 0x00010000,\nINODE_FAST_PROMOTE            = 0x00020000,\n*/\n#define INODE_HAS_UNCOMPRESSED_SIZE  0x00040000\n/*\nINODE_IS_PURGEABLE            = 0x00080000,\nINODE_WANTS_TO_BE_PURGEABLE   = 0x00100000,\nINODE_IS_SYNC_ROOT            = 0x00200000,\nINODE_SNAPSHOT_COW_EXEMPTION  = 0x00400000,\n\n\nINODE_INHERITED_INTERNAL_FLAGS = \\\n    ( INODE_MAINTAIN_DIR_STATS \\\n    | INODE_SNAPSHOT_COW_EXEMPTION),\n\nINODE_CLONED_INTERNAL_FLAGS = \\\n    ( INODE_HAS_RSRC_FORK \\\n    | INODE_NO_RSRC_FORK \\\n    | INODE_HAS_FINDER_INFO \\\n    | INODE_SNAPSHOT_COW_EXEMPTION),\n*/\n// }\n// j_inode_flags;\n\n\n/*\n#define APFS_VALID_INTERNAL_INODE_FLAGS \\\n( INODE_IS_APFS_PRIVATE \\\n| INODE_MAINTAIN_DIR_STATS \\\n| INODE_DIR_STATS_ORIGIN \\\n| INODE_PROT_CLASS_EXPLICIT \\\n| INODE_WAS_CLONED \\\n| INODE_HAS_SECURITY_EA \\\n| INODE_BEING_TRUNCATED \\\n| INODE_HAS_FINDER_INFO \\\n| INODE_IS_SPARSE \\\n| INODE_WAS_EVER_CLONED \\\n| INODE_ACTIVE_FILE_TRIMMED \\\n| INODE_PINNED_TO_MAIN \\\n| INODE_PINNED_TO_TIER2 \\\n| INODE_HAS_RSRC_FORK \\\n| INODE_NO_RSRC_FORK \\\n| INODE_ALLOCATION_SPILLEDOVER \\\n| INODE_FAST_PROMOTE \\\n| INODE_HAS_UNCOMPRESSED_SIZE \\\n| INODE_IS_PURGEABLE \\\n| INODE_WANTS_TO_BE_PURGEABLE \\\n| INODE_IS_SYNC_ROOT \\\n| INODE_SNAPSHOT_COW_EXEMPTION)\n\n#define APFS_INODE_PINNED_MASK (INODE_PINNED_TO_MAIN | INODE_PINNED_TO_TIER2)\n*/\n\nstatic const char * const g_INODE_Flags[] =\n{\n    \"IS_APFS_PRIVATE\"\n  , \"MAINTAIN_DIR_STATS\"\n  , \"DIR_STATS_ORIGIN\"\n  , \"PROT_CLASS_EXPLICIT\"\n  , \"WAS_CLONED\"\n  , \"FLAG_UNUSED\"\n  , \"HAS_SECURITY_EA\"\n  , \"BEING_TRUNCATED\"\n  , \"HAS_FINDER_INFO\"\n  , \"IS_SPARSE\"\n  , \"WAS_EVER_CLONED\"\n  , \"ACTIVE_FILE_TRIMMED\"\n  , \"PINNED_TO_MAIN\"\n  , \"PINNED_TO_TIER2\"\n  , \"HAS_RSRC_FORK\"\n  , \"NO_RSRC_FORK\"\n  , \"ALLOCATION_SPILLEDOVER\"\n  , \"FAST_PROMOTE\"\n  , \"HAS_UNCOMPRESSED_SIZE\"\n  , \"IS_PURGEABLE\"\n  , \"WANTS_TO_BE_PURGEABLE\"\n  , \"IS_SYNC_ROOT\"\n  , \"SNAPSHOT_COW_EXEMPTION\"\n};\n\n\n// bsd stat.h\n/*\n#define MY_UF_SETTABLE   0x0000ffff  // mask of owner changeable flags\n#define MY_UF_NODUMP     0x00000001  // do not dump file\n#define MY_UF_IMMUTABLE  0x00000002  // file may not be changed\n#define MY_UF_APPEND     0x00000004  // writes to file may only append\n#define MY_UF_OPAQUE     0x00000008  // directory is opaque wrt. union\n#define MY_UF_NOUNLINK   0x00000010  // file entry may not be removed or renamed Not implement in MacOS\n#define MY_UF_COMPRESSED 0x00000020  // file entry is compressed\n#define MY_UF_TRACKED    0x00000040  // notify about file entry changes\n#define MY_UF_DATAVAULT  0x00000080  // entitlement required for reading and writing\n#define MY_UF_HIDDEN     0x00008000  // file entry is hidden\n\n#define MY_SF_SETTABLE   0xffff0000  // mask of superuser changeable flags\n#define MY_SF_ARCHIVED   0x00010000  // file is archived\n#define MY_SF_IMMUTABLE  0x00020000  // file may not be changed\n#define MY_SF_APPEND     0x00040000  // writes to file may only append\n#define MY_SF_RESTRICTED 0x00080000  // entitlement required for writing\n#define MY_SF_NOUNLINK   0x00100000  // file entry may not be removed, renamed or used as mount point\n#define MY_SF_SNAPSHOT   0x00200000  // snapshot inode\nNot implement in MacOS\n*/\n\nstatic const char * const g_INODE_BSD_Flags[] =\n{\n    \"UF_NODUMP\"\n  , \"UF_IMMUTABLE\"\n  , \"UF_APPEND\"\n  , \"UF_OPAQUE\"\n  , \"UF_NOUNLINK\"\n  , \"UF_COMPRESSED\"\n  , \"UF_TRACKED\"\n  , \"UF_DATAVAULT\"\n  , NULL, NULL, NULL, NULL\n  , NULL, NULL, NULL\n  , \"UF_HIDDEN\"\n\n  , \"SF_ARCHIVE\"\n  , \"SF_IMMUTABLE\"\n  , \"SF_APPEND\"\n  , \"SF_RESTRICTED\"\n  , \"SF_NOUNLINK\"\n  , \"SF_SNAPSHOT\"\n};\n\n/*\n#define INO_EXT_TYPE_SNAP_XID       1\n#define INO_EXT_TYPE_DELTA_TREE_OID 2\n#define INO_EXT_TYPE_DOCUMENT_ID    3\n*/\n#define INO_EXT_TYPE_NAME           4\n/*\n#define INO_EXT_TYPE_PREV_FSIZE     5\n#define INO_EXT_TYPE_RESERVED_6     6\n#define INO_EXT_TYPE_FINDER_INFO    7\n*/\n#define INO_EXT_TYPE_DSTREAM        8\n/*\n#define INO_EXT_TYPE_RESERVED_9     9\n#define INO_EXT_TYPE_DIR_STATS_KEY  10\n#define INO_EXT_TYPE_FS_UUID        11\n#define INO_EXT_TYPE_RESERVED_12    12\n#define INO_EXT_TYPE_SPARSE_BYTES   13\n#define INO_EXT_TYPE_RDEV           14\n#define INO_EXT_TYPE_PURGEABLE_FLAGS 15\n#define INO_EXT_TYPE_ORIG_SYNC_ROOT_ID 16\n*/\n\n\nstatic const unsigned k_SizeOf_j_dstream = 8 * 5;\n\nstruct j_dstream\n{\n  UInt64 size;\n  UInt64 alloced_size;\n  UInt64 default_crypto_id;\n  UInt64 total_bytes_written;\n  UInt64 total_bytes_read;\n\n  void Parse(const Byte *p)\n  {\n    G64 (0, size)\n    G64 (0x8, alloced_size)\n    G64 (0x10, default_crypto_id)\n    G64 (0x18, total_bytes_written)\n    G64 (0x20, total_bytes_read)\n  }\n};\n\nstatic const unsigned k_SizeOf_j_file_extent_val = 8 * 3;\n\n#define J_FILE_EXTENT_LEN_MASK    0x00ffffffffffffffU\n// #define J_FILE_EXTENT_FLAG_MASK   0xff00000000000000U\n// #define J_FILE_EXTENT_FLAG_SHIFT  56\n\n#define EXTENT_GET_LEN(x) ((x) & J_FILE_EXTENT_LEN_MASK)\n\nstruct j_file_extent_val\n{\n  UInt64 len_and_flags;   // The length must be a multiple of the block size defined by the nx_block_size field of nx_superblock_t.\n                          // There are currently no flags defined\n  UInt64 phys_block_num;  // The physical block address that the extent starts at\n  // UInt64 crypto_id;       // The encryption key or the encryption tweak used in this extent.\n  \n  void Parse(const Byte *p)\n  {\n    G64 (0, len_and_flags)\n    G64 (0x8, phys_block_num)\n    // G64 (0x10, crypto_id);\n  }\n};\n\n\nstruct CExtent\n{\n  UInt64 logical_offset;\n  UInt64 len_and_flags;   // The length must be a multiple of the block size defined by the nx_block_size field of nx_superblock_t.\n                          // There are currently no flags defined\n  UInt64 phys_block_num;  // The physical block address that the extent starts at\n\n  UInt64 GetEndOffset() const { return logical_offset + EXTENT_GET_LEN(len_and_flags); }\n};\n\n\ntypedef UInt32  MY_uid_t;\ntypedef UInt32  MY_gid_t;\ntypedef UInt16  MY_mode_t;\n\n\ntypedef enum\n{\n  XATTR_DATA_STREAM       = 1 << 0,\n  XATTR_DATA_EMBEDDED     = 1 << 1,\n  XATTR_FILE_SYSTEM_OWNED = 1 << 2,\n  XATTR_RESERVED_8        = 1 << 3\n} j_xattr_flags;\n\n\nstruct CAttr\n{\n  AString Name;\n  UInt32 flags;\n  bool dstream_defined;\n  bool NeedShow;\n  CByteBuffer Data;\n\n  j_dstream dstream;\n  UInt64 Id;\n\n  bool Is_dstream_OK_for_SymLink() const\n  {\n    return dstream_defined && dstream.size <= (1 << 12) && dstream.size != 0;\n  }\n\n  UInt64 GetSize() const\n  {\n    if (dstream_defined) // dstream has more priority\n      return dstream.size;\n    return Data.Size();\n  }\n  \n  void Clear()\n  {\n    dstream_defined = false;\n    NeedShow = true;\n    Data.Free();\n    Name.Empty();\n  }\n\n  bool Is_STREAM()   const { return (flags & XATTR_DATA_STREAM) != 0; }\n  bool Is_EMBEDDED() const { return (flags & XATTR_DATA_EMBEDDED) != 0; }\n};\n\n\n// j_inode_val_t\nstruct CNode\n{\n  unsigned ItemIndex;      // index to CItem. We set it only if Node is directory.\n  unsigned NumCalcedLinks; // Num links to that node\n  // unsigned NumItems;    // Num Items in that node\n\n  UInt64 parent_id;    // The identifier of the file system record for the parent directory.\n  UInt64 private_id;\n  UInt64 create_time;\n  UInt64 mod_time;\n  UInt64 change_time;\n  UInt64 access_time;\n  UInt64 internal_flags;\n  union\n  {\n    UInt32 nchildren; /* The number of directory entries.\n                         is valid only if the inode is a directory */\n    UInt32 nlink;     /* The number of hard links whose target is this inode.\n                         is valid only if the inode isn't a directory.\n    Inodes with multiple hard links (nlink > 1)\n       - The parent_id field refers to the parent directory of the primary link.\n       - The name field contains the name of the primary link.\n       - The INO_EXT_TYPE_NAME extended field contains the name of this link.\n    */\n  };\n  // cp_key_class_t default_protection_class;\n  UInt32 write_generation_counter;\n  UInt32 bsd_flags;\n  MY_uid_t owner;\n  MY_gid_t group;\n  MY_mode_t mode;\n  UInt16 pad1;\n  UInt64 uncompressed_size;\n\n  j_dstream dstream;\n  AString PrimaryName;\n  \n  bool dstream_defined;\n  bool refcnt_defined;\n\n  UInt32 refcnt; // j_dstream_id_val_t\n  CRecordVector<CExtent> Extents;\n  CObjectVector<CAttr> Attrs;\n  unsigned SymLinkIndex; // index in Attrs\n  unsigned DecmpfsIndex; // index in Attrs\n  unsigned ResourceIndex; // index in Attrs\n  \n  NHfs::CCompressHeader CompressHeader;\n  \n  CNode():\n      ItemIndex(VI_MINUS1),\n      NumCalcedLinks(0),\n      // NumItems(0),\n      dstream_defined(false),\n      refcnt_defined(false),\n      SymLinkIndex(VI_MINUS1),\n      DecmpfsIndex(VI_MINUS1),\n      ResourceIndex(VI_MINUS1)\n      {}\n\n  bool IsDir() const { return MY_LIN_S_ISDIR(mode); }\n  bool IsSymLink() const { return MY_LIN_S_ISLNK(mode); }\n\n  bool Has_UNCOMPRESSED_SIZE() const { return (internal_flags & INODE_HAS_UNCOMPRESSED_SIZE) != 0; }\n\n  unsigned Get_Type_From_mode() const { return mode >> 12; }\n\n  bool GetSize(unsigned attrIndex, UInt64 &size) const\n  {\n    if (IsViNotDef(attrIndex))\n    {\n      if (dstream_defined)\n      {\n        size = dstream.size;\n        return true;\n      }\n      size = 0;\n      if (Has_UNCOMPRESSED_SIZE())\n      {\n        size = uncompressed_size;\n        return true;\n      }\n      if (!IsSymLink())\n        return false;\n      attrIndex = SymLinkIndex;\n      if (IsViNotDef(attrIndex))\n        return false;\n    }\n    const CAttr &attr = Attrs[(unsigned)attrIndex];\n    if (attr.dstream_defined)\n      size = attr.dstream.size;\n    else\n      size = attr.Data.Size();\n    return true;\n  }\n  \n  bool GetPackSize(unsigned attrIndex, UInt64 &size) const\n  {\n    if (IsViNotDef(attrIndex))\n    {\n      if (dstream_defined)\n      {\n        size = dstream.alloced_size;\n        return true;\n      }\n      size = 0;\n      \n      if (IsSymLink())\n        attrIndex = SymLinkIndex;\n      else\n      {\n        if (!CompressHeader.IsCorrect ||\n            !CompressHeader.IsSupported)\n          return false;\n        const CAttr &attr = Attrs[DecmpfsIndex];\n        if (!CompressHeader.IsMethod_Resource())\n        {\n          size = attr.Data.Size() - CompressHeader.DataPos;\n          return true;\n        }\n        attrIndex = ResourceIndex;\n      }\n      if (IsViNotDef(attrIndex))\n        return false;\n    }\n    const CAttr &attr = Attrs[(unsigned)attrIndex];\n    if (attr.dstream_defined)\n      size = attr.dstream.alloced_size;\n    else\n      size = attr.Data.Size();\n    return true;\n  }\n\n  void Parse(const Byte *p);\n};\n\n\n// it's used for Attr streams\nstruct CSmallNode\n{\n  CRecordVector<CExtent> Extents;\n  // UInt32 NumLinks;\n  // CSmallNode(): NumLinks(0) {}\n};\n\nstatic const unsigned k_SizeOf_j_inode_val = 0x5c;\n\nvoid CNode::Parse(const Byte *p)\n{\n  G64 (0, parent_id)\n  G64 (0x8, private_id)\n  G64 (0x10, create_time)\n  G64 (0x18, mod_time)\n  G64 (0x20, change_time)\n  G64 (0x28, access_time)\n  G64 (0x30, internal_flags)\n  {\n    G32 (0x38, nchildren)\n    //  G32 (0x38, nlink);\n  }\n  // G32 (0x3c, default_protection_class);\n  G32 (0x40, write_generation_counter)\n  G32 (0x44, bsd_flags)\n  G32 (0x48, owner)\n  G32 (0x4c, group)\n  G16 (0x50, mode)\n  // G16 (0x52, pad1);\n  G64 (0x54, uncompressed_size)\n}\n\n\nstruct CRef\n{\n  unsigned ItemIndex;\n  unsigned NodeIndex;\n  unsigned ParentRefIndex;\n\n #ifdef APFS_SHOW_ALT_STREAMS\n  unsigned AttrIndex;\n  bool IsAltStream() const { return IsViDef(AttrIndex); }\n  unsigned GetAttrIndex() const { return AttrIndex; }\n #else\n  // bool IsAltStream() const { return false; }\n  unsigned GetAttrIndex() const { return VI_MINUS1; }\n #endif\n};\n\n\nstruct CRef2\n{\n  unsigned VolIndex;\n  unsigned RefIndex;\n};\n\n\nstruct CHashChunk\n{\n  UInt64 lba;\n  UInt32 hashed_len; // the value is UInt16\n  Byte hash[APFS_HASH_MAX_SIZE];\n};\n\ntypedef CRecordVector<CHashChunk> CStreamHashes;\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithHash\n  , ISequentialOutStream\n)\n  bool _hashError;\n  CAlignedBuffer1 _sha;\n  CMyComPtr<ISequentialOutStream> _stream;\n  const CStreamHashes *_hashes;\n  unsigned _blockSizeLog;\n  unsigned _chunkIndex;\n  UInt32 _offsetInChunk;\n  // UInt64 _size;\n\n  CSha256 *Sha() { return (CSha256 *)(void *)(Byte *)_sha; }\npublic:\n  COutStreamWithHash(): _sha(sizeof(CSha256)) {}\n\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  // void ReleaseStream() { _stream.Release(); }\n  void Init(const CStreamHashes *hashes, unsigned blockSizeLog)\n  {\n    _hashes = hashes;\n    _blockSizeLog = blockSizeLog;\n    _chunkIndex = 0;\n    _offsetInChunk = 0;\n    _hashError = false;\n    // _size = 0;\n  }\n  // UInt64 GetSize() const { return _size; }\n  bool FinalCheck();\n};\n\n\nstatic bool Sha256_Final_and_CheckDigest(CSha256 *sha256, const Byte *digest)\n{\n  MY_ALIGN (16)\n  UInt32 temp[SHA256_NUM_DIGEST_WORDS];\n  Sha256_Final(sha256, (Byte *)temp);\n  return memcmp(temp, digest, SHA256_DIGEST_SIZE) == 0;\n}\n\n\nZ7_COM7F_IMF(COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  if (processedSize)\n    *processedSize = size;\n  while (size != 0)\n  {\n    if (_hashError)\n      break;\n    if (_chunkIndex >= _hashes->Size())\n    {\n      _hashError = true;\n      break;\n    }\n    if (_offsetInChunk == 0)\n      Sha256_Init(Sha());\n    const CHashChunk &chunk = (*_hashes)[_chunkIndex];\n    /* (_blockSizeLog <= 16) && chunk.hashed_len is 16-bit.\n       so we can use 32-bit chunkSize here */\n    const UInt32 chunkSize = ((UInt32)chunk.hashed_len << _blockSizeLog);\n    const UInt32 rem = chunkSize - _offsetInChunk;\n    UInt32 cur = size;\n    if (cur > rem)\n      cur = (UInt32)rem;\n    Sha256_Update(Sha(), (const Byte *)data, cur);\n    data = (const void *)((const Byte *)data + cur);\n    size -= cur;\n    // _size += cur;\n    _offsetInChunk += cur;\n    if (chunkSize == _offsetInChunk)\n    {\n      if (!Sha256_Final_and_CheckDigest(Sha(), chunk.hash))\n        _hashError = true;\n      _offsetInChunk = 0;\n      _chunkIndex++;\n    }\n  }\n  return result;\n}\n\n\nbool COutStreamWithHash::FinalCheck()\n{\n  if (_hashError)\n    return false;\n\n  if (_offsetInChunk != 0)\n  {\n    const CHashChunk &chunk = (*_hashes)[_chunkIndex];\n    {\n      const UInt32 chunkSize = ((UInt32)chunk.hashed_len << _blockSizeLog);\n      const UInt32 rem = chunkSize - _offsetInChunk;\n      Byte b = 0;\n      for (UInt32 i = 0; i < rem; i++)\n        Sha256_Update(Sha(), &b, 1);\n    }\n    if (!Sha256_Final_and_CheckDigest(Sha(), chunk.hash))\n      _hashError = true;\n    _offsetInChunk = 0;\n    _chunkIndex++;\n  }\n  if (_chunkIndex != _hashes->Size())\n    _hashError = true;\n  return !_hashError;\n}\n\n\n\nstruct CVol\n{\n  CObjectVector<CNode> Nodes;\n  CRecordVector<UInt64> NodeIDs;\n  CObjectVector<CItem> Items;\n  CRecordVector<CRef> Refs;\n\n  CObjectVector<CSmallNode> SmallNodes;\n  CRecordVector<UInt64> SmallNodeIDs;\n\n  CObjectVector<CSmallNode> FEXT_Nodes;\n  CRecordVector<UInt64> FEXT_NodeIDs;\n\n  CObjectVector<CStreamHashes> Hash_Vectors;\n  CRecordVector<UInt64> Hash_IDs;\n\n  unsigned StartRef2Index;  // ref2_Index for Refs[0] item\n  unsigned RootRef2Index;   // ref2_Index of virtual root folder (Volume1)\n  CApfs apfs;\n  C_integrity_meta_phys integrity;\n\n  bool NodeNotFound;\n  bool ThereAreUnlinkedNodes;\n  bool WrongInodeLink;\n  bool UnsupportedFeature;\n  bool UnsupportedMethod;\n\n  unsigned NumItems_In_PrivateDir;\n  unsigned NumAltStreams;\n\n  UString RootName;\n\n  bool ThereAreErrors() const\n  {\n    return NodeNotFound || ThereAreUnlinkedNodes || WrongInodeLink;\n  }\n\n  void AddComment(UString &s) const;\n\n  HRESULT FillRefs();\n  \n  CVol():\n      StartRef2Index(0),\n      RootRef2Index(VI_MINUS1),\n      NodeNotFound(false),\n      ThereAreUnlinkedNodes(false),\n      WrongInodeLink(false),\n      UnsupportedFeature(false),\n      UnsupportedMethod(false),\n      NumItems_In_PrivateDir(0),\n      NumAltStreams(0)\n      {}\n};\n\n\nstatic void ApfsTimeToFileTime(UInt64 apfsTime, FILETIME &ft, UInt32 &ns100)\n{\n  const UInt64 s = apfsTime / 1000000000;\n  const UInt32 ns = (UInt32)(apfsTime % 1000000000);\n  ns100 = (ns % 100);\n  const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64((Int64)s) + ns / 100;\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n}\n\nstatic void AddComment_Name(UString &s, const char *name)\n{\n  s += name;\n  s += \": \";\n}\n\n/*\nstatic void AddComment_Bool(UString &s, const char *name, bool val)\n{\n  AddComment_Name(s, name);\n  s += val ? \"+\" : \"-\";\n  s.Add_LF();\n}\n*/\n\nstatic void AddComment_UInt64(UString &s, const char *name, UInt64 v)\n{\n  AddComment_Name(s, name);\n  s.Add_UInt64(v);\n  s.Add_LF();\n}\n\n\nstatic void AddComment_Time(UString &s, const char *name, UInt64 v)\n{\n  AddComment_Name(s, name);\n\n  FILETIME ft;\n  UInt32 ns100;\n  ApfsTimeToFileTime(v, ft, ns100);\n  char temp[64];\n  ConvertUtcFileTimeToString2(ft, ns100, temp\n    // , kTimestampPrintLevel_SEC);\n    , kTimestampPrintLevel_NS);\n  s += temp;\n  s.Add_LF();\n}\n\n\nstatic void AddComment_modified_by_t(UString &s, const char *name, const apfs_modified_by_t &v)\n{\n  AddComment_Name(s, name);\n  AString s2;\n  s2.SetFrom_CalcLen((const char *)v.id, sizeof(v.id));\n  s += s2;\n  s.Add_LF();\n  s += \"  \";\n  AddComment_Time(s, \"timestamp\", v.timestamp);\n  s += \"  \";\n  AddComment_UInt64(s, \"last_xid\", v.last_xid);\n}\n\n\nstatic void AddVolInternalName_toString(UString &s, const CApfs &apfs)\n{\n  AString temp;\n  temp.SetFrom_CalcLen((const char *)apfs.volname, sizeof(apfs.volname));\n  UString unicode;\n  ConvertUTF8ToUnicode(temp, unicode);\n  s += unicode;\n}\n\n\nvoid CVol::AddComment(UString &s) const\n{\n  AddComment_UInt64(s, \"fs_index\", apfs.fs_index);\n  {\n    AddComment_Name(s, \"volume_name\");\n    AddVolInternalName_toString(s, apfs);\n    s.Add_LF();\n  }\n  AddComment_Name(s, \"vol_uuid\");\n  apfs.vol_uuid.AddHexToString(s);\n  s.Add_LF();\n\n  AddComment_Name(s, \"incompatible_features\");\n  s += FlagsToString(g_APFS_INCOMPAT_Flags,\n      Z7_ARRAY_SIZE(g_APFS_INCOMPAT_Flags),\n      (UInt32)apfs.incompatible_features);\n  s.Add_LF();\n\n\n  if (apfs.integrity_meta_oid != 0)\n  {\n    /*\n    AddComment_Name(s, \"im_version\");\n    s.Add_UInt32(integrity.im_version);\n    s.Add_LF();\n    */\n    AddComment_Name(s, \"im_flags\");\n    s.Add_UInt32(integrity.im_flags);\n    s.Add_LF();\n    AddComment_Name(s, \"im_hash_type\");\n    const char *p = NULL;\n    if (integrity.im_hash_type < Z7_ARRAY_SIZE(g_hash_types))\n      p = g_hash_types[integrity.im_hash_type];\n    if (p)\n      s += p;\n    else\n      s.Add_UInt32(integrity.im_hash_type);\n    s.Add_LF();\n  }\n\n\n  // AddComment_UInt64(s, \"reserve_block_count\", apfs.fs_reserve_block_count, false);\n  // AddComment_UInt64(s, \"quota_block_count\", apfs.fs_quota_block_count);\n  AddComment_UInt64(s, \"fs_alloc_count\", apfs.fs_alloc_count);\n\n  AddComment_UInt64(s, \"num_files\", apfs.num_files);\n  AddComment_UInt64(s, \"num_directories\", apfs.num_directories);\n  AddComment_UInt64(s, \"num_symlinks\", apfs.num_symlinks);\n  AddComment_UInt64(s, \"num_other_fsobjects\", apfs.num_other_fsobjects);\n\n  AddComment_UInt64(s, \"Num_Attr_Streams\", NumAltStreams);\n\n  AddComment_UInt64(s, \"num_snapshots\", apfs.num_snapshots);\n  AddComment_UInt64(s, \"total_blocks_alloced\", apfs.total_blocks_alloced);\n  AddComment_UInt64(s, \"total_blocks_freed\", apfs.total_blocks_freed);\n\n  AddComment_Time(s, \"unmounted\", apfs.unmount_time);\n  AddComment_Time(s, \"last_modified\", apfs.last_mod_time);\n  AddComment_modified_by_t(s, \"formatted_by\", apfs.formatted_by);\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(apfs.modified_by); i++)\n  {\n    const apfs_modified_by_t &v = apfs.modified_by[i];\n    if (v.last_xid == 0 && v.timestamp == 0 && v.id[0] == 0)\n      continue;\n    AString name (\"modified_by[\");\n    name.Add_UInt32(i);\n    name += ']';\n    AddComment_modified_by_t(s, name.Ptr(), v);\n  }\n}\n\n\n\nstruct CKeyValPair\n{\n  CByteBuffer Key;\n  CByteBuffer Val;\n  // unsigned ValPos; // for alognment\n};\n\n\nstruct omap_key\n{\n  oid_t oid; // The object identifier\n  xid_t xid; // The transaction identifier\n  void Parse(const Byte *p)\n  {\n    G64o (0, oid)\n    G64x (8, xid)\n  }\n};\n\n/*\n#define OMAP_VAL_DELETED            (1 << 0)\n#define OMAP_VAL_SAVED              (1 << 1)\n#define OMAP_VAL_ENCRYPTED          (1 << 2)\n*/\n#define OMAP_VAL_NOHEADER           (1 << 3)\n/*\n#define OMAP_VAL_CRYPTO_GENERATION  (1 << 4)\n*/\n\nstruct omap_val\n{\n  UInt32 flags;\n  UInt32 size;\n  // paddr_t paddr;\n  paddr_t_unsigned paddr;\n\n  bool IsFlag_NoHeader() const { return (flags & OMAP_VAL_NOHEADER) != 0; }\n  \n  void Parse(const Byte *p)\n  {\n    G32 (0, flags)\n    G32 (4, size)\n    G64 (8, paddr)\n  }\n};\n\n\nstruct CObjectMap\n{\n  CRecordVector<UInt64> Keys;\n  CRecordVector<omap_val> Vals;\n\n  bool Parse(const CObjectVector<CKeyValPair> &pairs);\n  int FindKey(UInt64 id) const { return Keys.FindInSorted(id); }\n};\n\nbool CObjectMap::Parse(const CObjectVector<CKeyValPair> &pairs)\n{\n  omap_key prev;\n  prev.oid = 0;\n  prev.xid = 0;\n  FOR_VECTOR (i, pairs)\n  {\n    const CKeyValPair &pair = pairs[i];\n    if (pair.Key.Size() != 16 || pair.Val.Size() != 16)\n      return false;\n    omap_key key;\n    key.Parse(pair.Key);\n    omap_val val;\n    val.Parse(pair.Val);\n    /* Object map B-trees are sorted by object identifier and then by transaction identifier\n       but it's possible to have identical Ids in map ?\n       do we need to look transaction id ?\n       and search key with largest transaction id? */\n    if (key.oid <= prev.oid)\n      return false;\n    prev = key;\n    Keys.Add(key.oid);\n    Vals.Add(val);\n  }\n  return true;\n}\n\n\nstruct CMap\n{\n  CObjectVector<CKeyValPair> Pairs;\n  \n  CObjectMap Omap;\n  btree_info bti;\n  UInt64 NumNodes;\n\n  // we use thnese options to check:\n  UInt32 Subtype;\n  bool IsPhysical;\n  \n  bool CheckAtFinish() const\n  {\n    return NumNodes == bti.node_count && Pairs.Size() == bti.key_count;\n  }\n\n  CMap():\n      NumNodes(0),\n      Subtype(0),\n      IsPhysical(true)\n      {}\n};\n\n\n\nstruct CDatabase\n{\n  CRecordVector<CRef2> Refs2;\n  CObjectVector<CVol> Vols;\n\n  bool HeadersError;\n  bool ThereAreAltStreams;\n  bool UnsupportedFeature;\n  bool UnsupportedMethod;\n  \n  CSuperBlock sb;\n\n  IInStream *OpenInStream;\n  IArchiveOpenCallback *OpenCallback;\n  UInt64 ProgressVal_Cur;\n  UInt64 ProgressVal_Prev;\n  UInt64 ProgressVal_NumFilesTotal;\n  CObjectVector<CByteBuffer> Buffers;\n\n  UInt32 MethodsMask;\n  UInt64 GetSize(const UInt32 index) const;\n\n  void Clear()\n  {\n    HeadersError = false;\n    ThereAreAltStreams = false;\n    UnsupportedFeature = false;\n    UnsupportedMethod = false;\n    \n    ProgressVal_Cur = 0;\n    ProgressVal_Prev = 0;\n    ProgressVal_NumFilesTotal = 0;\n\n    MethodsMask = 0;\n    \n    Vols.Clear();\n    Refs2.Clear();\n    Buffers.Clear();\n  }\n\n  HRESULT SeekReadBlock_FALSE(UInt64 oid, void *data);\n  void GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::CPropVariant &path) const;\n  HRESULT ReadMap(UInt64 oid, bool noHeader, CVol *vol, const Byte *hash,\n      CMap &map, unsigned recurseLevel);\n  HRESULT ReadObjectMap(UInt64 oid, CVol *vol, CObjectMap &map);\n  HRESULT OpenVolume(const CObjectMap &omap, const oid_t fs_oid);\n  HRESULT Open2();\n\n  HRESULT GetAttrStream(IInStream *apfsInStream, const CVol &vol,\n      const CAttr &attr, ISequentialInStream **stream);\n\n  HRESULT GetAttrStream_dstream(IInStream *apfsInStream, const CVol &vol,\n      const CAttr &attr, ISequentialInStream **stream);\n\n  HRESULT GetStream2(\n      IInStream *apfsInStream,\n      const CRecordVector<CExtent> *extents, UInt64 rem,\n      ISequentialInStream **stream);\n};\n\n\nHRESULT CDatabase::SeekReadBlock_FALSE(UInt64 oid, void *data)\n{\n  if (OpenCallback)\n  {\n    if (ProgressVal_Cur - ProgressVal_Prev >= (1 << 22))\n    {\n      RINOK(OpenCallback->SetCompleted(NULL, &ProgressVal_Cur))\n      ProgressVal_Prev = ProgressVal_Cur;\n    }\n    ProgressVal_Cur += sb.block_size;\n  }\n  if (oid == 0 || oid >= sb.block_count)\n    return S_FALSE;\n  RINOK(InStream_SeekSet(OpenInStream, oid << sb.block_size_Log))\n  return ReadStream_FALSE(OpenInStream, data, sb.block_size);\n}\n\n\n\nAPI_FUNC_static_IsArc IsArc_APFS(const Byte *p, size_t size)\n{\n  if (size < kApfsHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  CSuperBlock sb;\n  if (!sb.Parse(p))\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\n\nstatic bool CheckHash(unsigned hashAlgo, const Byte *data, size_t size, const Byte *digest)\n{\n  if (hashAlgo == APFS_HASH_SHA256)\n  {\n    MY_ALIGN (16)\n    CSha256 sha;\n    Sha256_Init(&sha);\n    Sha256_Update(&sha, data, size);\n    return Sha256_Final_and_CheckDigest(&sha, digest);\n  }\n  return true;\n}\n\n \nHRESULT CDatabase::ReadMap(UInt64 oid, bool noHeader,\n    CVol *vol, const Byte *hash,\n    CMap &map, unsigned recurseLevel)\n{\n  // is it allowed to use big number of levels ?\n  if (recurseLevel > (1 << 10))\n    return S_FALSE;\n\n  const UInt32 blockSize = sb.block_size;\n  if (Buffers.Size() <= recurseLevel)\n  {\n    Buffers.AddNew();\n    if (Buffers.Size() <= recurseLevel)\n      throw 123;\n    Buffers.Back().Alloc(blockSize);\n  }\n  const Byte *buf;\n  {\n    CByteBuffer &buf2 = Buffers[recurseLevel];\n    RINOK(SeekReadBlock_FALSE(oid, buf2))\n    buf = buf2;\n  }\n\n  if (hash && vol)\n    if (!CheckHash(vol->integrity.im_hash_type, buf, blockSize, hash))\n      return S_FALSE;\n\n  CBTreeNodePhys bt;\n  if (!bt.Parse(buf, blockSize, noHeader))\n    return S_FALSE;\n  \n  map.NumNodes++;\n\n  /* Specification: All values are stored in leaf nodes, which\n     makes these B+ trees, and the values in nonleaf nodes are object\n     identifiers of child nodes.\n  \n     The entries in the table of contents are sorted by key. The comparison function used for sorting depends on the keys type\n      - Object map B-trees are sorted by object identifier and then by transaction identifier.\n      - Free queue B-trees are sorted by transaction identifier and then by physical address.\n      - File-system records are sorted according to the rules listed in File-System Objects.\n  */\n  \n  if (!noHeader)\n  if (bt.ophys.subtype != map.Subtype)\n    return S_FALSE;\n\n  unsigned endLimit = blockSize;\n\n  if (recurseLevel == 0)\n  {\n    if (!noHeader)\n    if (bt.ophys.GetType() != OBJECT_TYPE_BTREE)\n      return S_FALSE;\n    if ((bt.flags & BTNODE_ROOT) == 0)\n      return S_FALSE;\n    endLimit -= k_btree_info_Size;\n    map.bti.Parse(buf + endLimit);\n    btree_info &bti = map.bti;\n    if (bti.fixed.key_size >= blockSize)\n      return S_FALSE;\n    if (bti.Is_EPHEMERAL() &&\n        bti.Is_PHYSICAL())\n      return S_FALSE;\n    if (bti.Is_PHYSICAL() != map.IsPhysical)\n      return S_FALSE;\n    if (bti.Is_NOHEADER() != noHeader)\n      return S_FALSE;\n    // we don't allow volumes with big number of Keys\n    const unsigned kNumItemsMax = k_VectorSizeMax;\n    if (map.bti.node_count > kNumItemsMax)\n      return S_FALSE;\n    if (map.bti.key_count > kNumItemsMax)\n      return S_FALSE;\n  }\n  else\n  {\n    if (!noHeader)\n    if (bt.ophys.GetType() != OBJECT_TYPE_BTREE_NODE)\n      return S_FALSE;\n    if ((bt.flags & BTNODE_ROOT) != 0)\n      return S_FALSE;\n    if (map.NumNodes > map.bti.node_count\n        || map.Pairs.Size() > map.bti.key_count)\n      return S_FALSE;\n  }\n\n  const bool isLeaf = (bt.flags & BTNODE_LEAF) != 0;\n\n  if (isLeaf)\n  {\n    if (bt.level != 0)\n      return S_FALSE;\n  }\n  else\n  {\n    if (bt.level == 0)\n      return S_FALSE;\n  }\n\n  if (!bt.table_space.CheckOverLimit(endLimit - k_Toc_offset))\n    return S_FALSE;\n\n  const unsigned tableEnd = k_Toc_offset + bt.table_space.GetEnd();\n  const unsigned keyValRange = endLimit - tableEnd;\n  const unsigned tocEntrySize = bt.Is_FIXED_KV_SIZE() ? 4 : 8;\n  if (bt.table_space.len / tocEntrySize < bt.nkeys)\n    return S_FALSE;\n\n  for (unsigned i = 0; i < bt.nkeys; i++)\n  {\n    const Byte *p = buf + k_Toc_offset + bt.table_space.off + i * tocEntrySize;\n    if (bt.Is_FIXED_KV_SIZE())\n    {\n      kvoff a;\n      a.Parse(p);\n      if (a.k + map.bti.fixed.key_size > keyValRange\n          || a.v > keyValRange)\n        return S_FALSE;\n      {\n        CKeyValPair pair;\n        \n        const Byte *p2 = buf + k_Toc_offset + bt.table_space.len;\n        p2 += a.k;\n        pair.Key.CopyFrom(p2, map.bti.fixed.key_size);\n\n        p2 = buf + endLimit;\n        p2 -= a.v;\n        if (isLeaf)\n        {\n          if (a.v < map.bti.fixed.val_size)\n            return S_FALSE;\n          pair.Val.CopyFrom(p2, map.bti.fixed.val_size);\n          // pair.ValPos = endLimit - a.v;\n          map.Pairs.Add(pair);\n          continue;\n        }\n        {\n          if (a.v < 8)\n            return S_FALSE;\n          // value is only 64-bit for non leaf.\n          const oid_t oidNext = Get64(p2);\n          if (map.bti.Is_PHYSICAL())\n          {\n            RINOK(ReadMap(oidNext, noHeader, vol,\n                NULL, /* hash */\n                map, recurseLevel + 1))\n            continue;\n          }\n          else\n          {\n            // fixme\n            return S_FALSE;\n          }\n        }\n      }\n    }\n    else\n    {\n      kvloc a;\n      a.Parse(p);\n      if (!a.k.CheckOverLimit(keyValRange)\n          || a.v.off > keyValRange\n          || a.v.len > a.v.off)\n        return S_FALSE;\n      {\n        CKeyValPair pair;\n        const Byte *p2 = buf + k_Toc_offset + bt.table_space.len;\n        p2 += a.k.off;\n        pair.Key.CopyFrom(p2, a.k.len);\n\n        p2 = buf + endLimit;\n        p2 -= a.v.off;\n        if (isLeaf)\n        {\n          pair.Val.CopyFrom(p2, a.v.len);\n          // pair.ValPos = endLimit - a.v.off;\n          map.Pairs.Add(pair);\n          continue;\n        }\n        {\n          if (a.v.len < 8)\n            return S_FALSE;\n\n          const Byte *hashNew = NULL;\n          oid_t oidNext = Get64(p2);\n\n          if (bt.Is_HASHED())\n          {\n            if (!vol)\n              return S_FALSE;\n            /*\n            struct btn_index_node_val {\n              oid_t binv_child_oid;\n              uint8_t binv_child_hash[BTREE_NODE_HASH_SIZE_MAX];\n            };\n            */\n            /* (a.v.len == 40) is possible if Is_HASHED()\n               so there is hash (for example, 256-bit) after 64-bit id) */\n            if (a.v.len != 8 + vol->integrity.HashSize)\n              return S_FALSE;\n            hashNew = p2 + 8;\n            /* we need to add root_tree_oid here,\n               but where it's defined in apfs specification ? */\n            oidNext += vol->apfs.root_tree_oid;\n          }\n          else\n          {\n            if (a.v.len != 8)\n              return S_FALSE;\n          }\n\n          // value is only 64-bit for non leaf.\n\n          if (map.bti.Is_PHYSICAL())\n          {\n            return S_FALSE;\n            // the code was not tested:\n            // RINOK(ReadMap(oidNext, map, recurseLevel + 1));\n            // continue;\n          }\n          /*\n          else if (map.bti.Is_EPHEMERAL())\n          {\n            // Ephemeral objects are stored in memory while the container is mounted and in a checkpoint when the container isn't mounted\n            // the code was not tested:\n            return S_FALSE;\n          }\n          */\n          else\n          {\n            /* nodes in the B-tree use virtual object identifiers to link to their child nodes. */\n            const int index = map.Omap.FindKey(oidNext);\n            if (index == -1)\n              return S_FALSE;\n            const omap_val &ov = map.Omap.Vals[(unsigned)index];\n            if (ov.size != blockSize) // change it : it must be multiple of\n              return S_FALSE;\n            RINOK(ReadMap(ov.paddr, ov.IsFlag_NoHeader(), vol, hashNew,\n                map, recurseLevel + 1))\n            continue;\n          }\n        }\n      }\n    }\n  }\n\n  if (recurseLevel == 0)\n    if (!map.CheckAtFinish())\n      return S_FALSE;\n  return S_OK;\n}\n\n\n\nHRESULT CDatabase::ReadObjectMap(UInt64 oid, CVol *vol, CObjectMap &omap)\n{\n  CByteBuffer buf;\n  const size_t blockSize = sb.block_size;\n  buf.Alloc(blockSize);\n  RINOK(SeekReadBlock_FALSE(oid, buf))\n  C_omap_phys op;\n  if (!op.Parse(buf, blockSize, oid))\n    return S_FALSE;\n  CMap map;\n  map.Subtype = OBJECT_TYPE_OMAP;\n  map.IsPhysical = true;\n  RINOK(ReadMap(op.tree_oid,\n      false /* noHeader */,\n      vol,\n      NULL, /* hash */\n      map, 0))\n  if (!omap.Parse(map.Pairs))\n    return S_FALSE;\n  return S_OK;\n}\n\n\n\nHRESULT CDatabase::Open2()\n{\n  Clear();\n  CSuperBlock2 sb2;\n  {\n    Byte buf[kApfsHeaderSize];\n    RINOK(ReadStream_FALSE(OpenInStream, buf, kApfsHeaderSize))\n    if (!sb.Parse(buf))\n      return S_FALSE;\n    sb2.Parse(buf);\n  }\n\n  {\n    CObjectMap omap;\n    RINOK(ReadObjectMap(sb.omap_oid,\n        NULL, /* CVol */\n        omap))\n    unsigned numRefs = 0;\n    for (unsigned i = 0; i < sb.max_file_systems; i++)\n    {\n      const oid_t oid = sb2.fs_oid[i];\n      if (oid == 0)\n        continue;\n      // for (unsigned k = 0; k < 1; k++) // for debug\n      RINOK(OpenVolume(omap, oid))\n      const unsigned a = Vols.Back().Refs.Size();\n      numRefs += a;\n      if (numRefs < a)\n        return S_FALSE; // overflow\n    }\n  }\n\n  const bool needVolumePrefix = (Vols.Size() > 1);\n  // const bool needVolumePrefix = true; // for debug\n  {\n    unsigned numRefs = 0;\n    FOR_VECTOR (i, Vols)\n    {\n      const unsigned a = Vols[i].Refs.Size();\n      numRefs += a;\n      if (numRefs < a)\n        return S_FALSE; // overflow\n    }\n    numRefs += Vols.Size();\n    if (numRefs < Vols.Size())\n      return S_FALSE; // overflow\n    Refs2.Reserve(numRefs);\n  }\n  {\n    FOR_VECTOR (i, Vols)\n    {\n      CVol &vol = Vols[i];\n\n      CRef2 ref2;\n      ref2.VolIndex = i;\n      \n      if (needVolumePrefix)\n      {\n        vol.RootName = \"Volume\";\n        vol.RootName.Add_UInt32(1 + (UInt32)i);\n        vol.RootRef2Index = Refs2.Size();\n        ref2.RefIndex = VI_MINUS1;\n        Refs2.Add(ref2);\n      }\n\n      vol.StartRef2Index = Refs2.Size();\n      const unsigned numItems = vol.Refs.Size();\n      for (unsigned k = 0; k < numItems; k++)\n      {\n        ref2.RefIndex = k;\n        Refs2.Add(ref2);\n      }\n    }\n  }\n  return S_OK;\n}\n\n\nHRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)\n{\n  const size_t blockSize = sb.block_size;\n  CByteBuffer buf;\n  {\n    const int index = omap.FindKey(fs_oid);\n    if (index == -1)\n      return S_FALSE;\n    const omap_val &ov = omap.Vals[(unsigned)index];\n    if (ov.size != blockSize) // change it : it must be multiple of\n      return S_FALSE;\n    buf.Alloc(blockSize);\n    RINOK(SeekReadBlock_FALSE(ov.paddr, buf))\n  }\n\n  CVol &vol = Vols.AddNew();\n  CApfs &apfs = vol.apfs;\n\n  if (!apfs.Parse(buf, blockSize))\n    return S_FALSE;\n\n  if (apfs.fext_tree_oid != 0)\n  {\n    if ((apfs.incompatible_features & APFS_INCOMPAT_SEALED_VOLUME) == 0)\n      return S_FALSE;\n    if ((apfs.fext_tree_type & OBJ_PHYSICAL) == 0)\n      return S_FALSE;\n    if ((apfs.fext_tree_type & OBJECT_TYPE_MASK) != OBJECT_TYPE_BTREE)\n      return S_FALSE;\n\n    CMap map2;\n    map2.Subtype = OBJECT_TYPE_FEXT_TREE;\n    map2.IsPhysical = true;\n\n    RINOK(ReadMap(apfs.fext_tree_oid,\n        false /* noHeader */,\n        &vol,\n        NULL, /* hash */\n        map2, 0))\n\n    UInt64 prevId = 1;\n\n    FOR_VECTOR (i, map2.Pairs)\n    {\n      if (OpenCallback && (i & 0xffff) == 1)\n      {\n        const UInt64 numFiles = ProgressVal_NumFilesTotal +\n            (vol.Items.Size() + vol.Nodes.Size()) / 2;\n        RINOK(OpenCallback->SetCompleted(&numFiles, &ProgressVal_Cur))\n      }\n      // The key half of a record from a file extent tree.\n      // struct fext_tree_key\n      const CKeyValPair &pair = map2.Pairs[i];\n      if (pair.Key.Size() != 16)\n        return S_FALSE;\n      const Byte *p = pair.Key;\n      const UInt64 id = GetUi64(p);\n      if (id < prevId)\n        return S_FALSE;  // IDs must be sorted\n      prevId = id;\n\n      CExtent ext;\n      ext.logical_offset = GetUi64(p + 8);\n      {\n        if (pair.Val.Size() != 16)\n          return S_FALSE;\n        const Byte *p2 = pair.Val;\n        ext.len_and_flags = GetUi64(p2);\n        ext.phys_block_num = GetUi64(p2 + 8);\n      }\n\n      PRF(printf(\"\\n%6d: id=%6d logical_addr = %2d len_and_flags=%5x phys_block_num = %5d\",\n          i, (unsigned)id,\n          (unsigned)ext.logical_offset,\n          (unsigned)ext.len_and_flags,\n          (unsigned)ext.phys_block_num));\n\n      if (vol.FEXT_NodeIDs.IsEmpty() ||\n          vol.FEXT_NodeIDs.Back() != id)\n      {\n        vol.FEXT_NodeIDs.Add(id);\n        vol.FEXT_Nodes.AddNew();\n      }\n      CRecordVector<CExtent> &extents = vol.FEXT_Nodes.Back().Extents;\n      if (!extents.IsEmpty())\n        if (ext.logical_offset != extents.Back().GetEndOffset())\n          return S_FALSE;\n      extents.Add(ext);\n      continue;\n    }\n\n    PRF(printf(\"\\n\\n\"));\n  }\n\n  /* For each volume, read the root file system tree's virtual object\n     identifier from the apfs_root_tree_oid field,\n     and then look it up in the volume object map indicated\n     by the omap_oid field. */\n\n  CMap map;\n  ReadObjectMap(apfs.omap_oid, &vol, map.Omap);\n\n  const Byte *hash_for_root = NULL;\n\n  if (apfs.integrity_meta_oid != 0)\n  {\n    if ((apfs.incompatible_features & APFS_INCOMPAT_SEALED_VOLUME) == 0)\n      return S_FALSE;\n    const int index = map.Omap.FindKey(apfs.integrity_meta_oid);\n    if (index == -1)\n      return S_FALSE;\n    const omap_val &ov = map.Omap.Vals[(unsigned)index];\n    if (ov.size != blockSize)\n      return S_FALSE;\n    RINOK(SeekReadBlock_FALSE(ov.paddr, buf))\n    if (!vol.integrity.Parse(buf, blockSize, apfs.integrity_meta_oid))\n      return S_FALSE;\n    if (vol.integrity.im_hash_type != 0)\n      hash_for_root = vol.integrity.Hash;\n  }\n\n  {\n    const int index = map.Omap.FindKey(apfs.root_tree_oid);\n    if (index == -1)\n      return S_FALSE;\n    const omap_val &ov = map.Omap.Vals[(unsigned)index];\n    if (ov.size != blockSize) // change it : it must be multiple of\n      return S_FALSE;\n    map.Subtype = OBJECT_TYPE_FSTREE;\n    map.IsPhysical = false;\n    RINOK(ReadMap(ov.paddr, ov.IsFlag_NoHeader(),\n        &vol, hash_for_root,\n        map, 0))\n  }\n\n  bool needParseAttr = false;\n\n  {\n    const bool isHashed = apfs.IsHashedName();\n    UInt64 prevId = 1;\n\n    {\n      const UInt64 numApfsItems = vol.apfs.GetTotalItems()\n          + 2;   // we will have 2 additional hidden directories: root and private-dir\n      const UInt64 numApfsItems_Reserve = numApfsItems\n          + 16;  // we reserve 16 for some possible unexpected items\n      if (numApfsItems_Reserve < map.Pairs.Size())\n      {\n        vol.Items.ClearAndReserve((unsigned)numApfsItems_Reserve);\n        vol.Nodes.ClearAndReserve((unsigned)numApfsItems_Reserve);\n        vol.NodeIDs.ClearAndReserve((unsigned)numApfsItems_Reserve);\n      }\n      if (OpenCallback)\n      {\n        const UInt64 numFiles = ProgressVal_NumFilesTotal + numApfsItems;\n        RINOK(OpenCallback->SetTotal(&numFiles, NULL))\n      }\n    }\n\n    CAttr attr;\n    CItem item;\n\n    FOR_VECTOR (i, map.Pairs)\n    {\n      if (OpenCallback && (i & 0xffff) == 1)\n      {\n        const UInt64 numFiles = ProgressVal_NumFilesTotal +\n            (vol.Items.Size() + vol.Nodes.Size()) / 2;\n        RINOK(OpenCallback->SetCompleted(&numFiles, &ProgressVal_Cur))\n      }\n\n      const CKeyValPair &pair = map.Pairs[i];\n      j_key_t jkey;\n      if (pair.Key.Size() < 8)\n        return S_FALSE;\n      const Byte *p = pair.Key;\n      jkey.Parse(p);\n      const unsigned type = jkey.GetType();\n      const UInt64 id = jkey.GetID();\n      if (id < prevId)\n        return S_FALSE;  // IDs must be sorted\n      prevId = id;\n\n      PRF(printf(\"\\n%6d: id=%6d type = %2d \", i, (unsigned)id, type));\n      \n      if (type == APFS_TYPE_INODE)\n      {\n        PRF(printf(\"INODE\"));\n        if (pair.Key.Size() != 8 ||\n            pair.Val.Size() < k_SizeOf_j_inode_val)\n          return S_FALSE;\n\n        CNode inode;\n        inode.Parse(pair.Val);\n\n        if (inode.private_id != id)\n        {\n          /* private_id : The unique identifier used by this file's data stream.\n             This identifier appears in the owning_obj_id field of j_phys_ext_val_t\n             records that describe the extents where the data is stored.\n             For an inode that doesn't have data, the value of this\n             field is the file-system object's identifier.\n          */\n          // APFS_TYPE_EXTENT allow to link physical address extents.\n          // we don't support case (private_id != id)\n          UnsupportedFeature = true;\n          // return S_FALSE;\n        }\n        const UInt32 extraSize = (UInt32)pair.Val.Size() - k_SizeOf_j_inode_val;\n        if (extraSize != 0)\n        {\n          if (extraSize < 4)\n            return S_FALSE;\n          /*\n          struct xf_blob\n          {\n            uint16_t xf_num_exts;\n            uint16_t xf_used_data;\n            uint8_t xf_data[];\n          };\n          */\n          const Byte *p2 = pair.Val + k_SizeOf_j_inode_val;\n          const UInt32 xf_num_exts = Get16(p2);\n          const UInt32 xf_used_data = Get16(p2 + 2);\n          UInt32 offset = 4 + (UInt32)xf_num_exts * 4;\n          if (offset + xf_used_data != extraSize)\n            return S_FALSE;\n\n          PRF(printf(\" parent_id = %d\", (unsigned)inode.parent_id));\n\n          for (unsigned k = 0; k < xf_num_exts; k++)\n          {\n            // struct x_field\n            const Byte *p3 = p2 + 4 + k * 4;\n            const Byte x_type = p3[0];\n            // const Byte x_flags = p3[1];\n            const UInt32 x_size = Get16(p3 + 2);\n            const UInt32 x_size_ceil = (x_size + 7) & ~(UInt32)7;\n            if (offset + x_size_ceil > extraSize)\n              return S_FALSE;\n            const Byte *p4 = p2 + offset;\n            if (x_type == INO_EXT_TYPE_NAME)\n            {\n              if (x_size < 2)\n                return S_FALSE;\n              inode.PrimaryName.SetFrom_CalcLen((const char *)p4, x_size);\n              PRF(printf(\" PrimaryName = %s\", inode.PrimaryName.Ptr()));\n              if (inode.PrimaryName.Len() != x_size - 1)\n                HeadersError = true;\n              // return S_FALSE;\n            }\n            else if (x_type == INO_EXT_TYPE_DSTREAM)\n            {\n              if (x_size != k_SizeOf_j_dstream)\n                return S_FALSE;\n              if (inode.dstream_defined)\n                return S_FALSE;\n              inode.dstream.Parse(p4);\n              inode.dstream_defined = true;\n            }\n            else\n            {\n              // UnsupportedFeature = true;\n              // return S_FALSE;\n            }\n            offset += x_size_ceil;\n          }\n          if (offset != extraSize)\n            return S_FALSE;\n        }\n\n        if (!vol.NodeIDs.IsEmpty())\n          if (id <= vol.NodeIDs.Back())\n            return S_FALSE;\n        vol.Nodes.Add(inode);\n        vol.NodeIDs.Add(id);\n        continue;\n      }\n\n      if (type == APFS_TYPE_XATTR)\n      {\n        PRF(printf(\"  XATTR\"));\n\n        /*\n        struct j_xattr_key\n        {\n          j_key_t hdr;\n          uint16_t name_len;\n          uint8_t name[0];\n        }\n        */\n\n        UInt32 len;\n        unsigned nameOffset;\n        {\n          nameOffset = 8 + 2;\n          if (pair.Key.Size() < nameOffset + 1)\n            return S_FALSE;\n          len = Get16(p + 8);\n        }\n        if (nameOffset + len != pair.Key.Size())\n          return S_FALSE;\n\n        attr.Clear();\n        attr.Name.SetFrom_CalcLen((const char *)p + nameOffset, len);\n        if (attr.Name.Len() != len - 1)\n          return S_FALSE;\n\n        PRF(printf(\"  name=%s\", attr.Name.Ptr()));\n\n        const unsigned k_SizeOf_j_xattr_val = 4;\n        if (pair.Val.Size() < k_SizeOf_j_xattr_val)\n          return S_FALSE;\n        /*\n        struct j_xattr_val\n        {\n          uint16_t flags;\n          uint16_t xdata_len;\n          uint8_t xdata[0];\n        }\n        */\n        attr.flags = Get16(pair.Val);\n        const UInt32 xdata_len = Get16(pair.Val + 2);\n\n        PRF(printf(\"  flags=%x xdata_len = %d\",\n            (unsigned)attr.flags,\n            (unsigned)xdata_len));\n\n        const Byte *p4 = pair.Val + 4;\n\n        if (k_SizeOf_j_xattr_val + xdata_len != pair.Val.Size())\n          return S_FALSE;\n        if (attr.Is_EMBEDDED())\n          attr.Data.CopyFrom(p4, xdata_len);\n        else if (attr.Is_STREAM())\n        {\n          // why (attr.flags == 0x11) here? (0x11 is undocummented flag)\n          if (k_SizeOf_j_xattr_val + 8 + k_SizeOf_j_dstream != pair.Val.Size())\n            return S_FALSE;\n          attr.Id = Get64(p4);\n          attr.dstream.Parse(p4 + 8);\n          attr.dstream_defined = true;\n          PRF(printf(\" streamID=%d streamSize=%d\", (unsigned)attr.Id, (unsigned)attr.dstream.size));\n        }\n        else\n        {\n          // unknown attribute\n          // UnsupportedFeature = true;\n          // return S_FALSE;\n        }\n\n        if (vol.NodeIDs.IsEmpty() ||\n            vol.NodeIDs.Back() != id)\n        {\n          return S_FALSE;\n          // UnsupportedFeature = true;\n          // continue;\n        }\n        \n        CNode &inode = vol.Nodes.Back();\n        \n        if (attr.Name.IsEqualTo(\"com.apple.fs.symlink\"))\n        {\n          inode.SymLinkIndex = inode.Attrs.Size();\n          if (attr.Is_dstream_OK_for_SymLink())\n            needParseAttr = true;\n        }\n        else if (attr.Name.IsEqualTo(\"com.apple.decmpfs\"))\n        {\n          inode.DecmpfsIndex = inode.Attrs.Size();\n          // if (attr.dstream_defined)\n          needParseAttr = true;\n        }\n        else if (attr.Name.IsEqualTo(\"com.apple.ResourceFork\"))\n        {\n          inode.ResourceIndex = inode.Attrs.Size();\n        }\n        inode.Attrs.Add(attr);\n        continue;\n      }\n\n      if (type == APFS_TYPE_DSTREAM_ID)\n      {\n        PRF(printf(\"  DSTREAM_ID\"));\n        if (pair.Key.Size() != 8)\n          return S_FALSE;\n        // j_dstream_id_val_t\n        if (pair.Val.Size() != 4)\n          return S_FALSE;\n        const UInt32 refcnt = Get32(pair.Val);\n\n        // The data stream record can be deleted when its reference count reaches zero.\n        PRF(printf(\"  refcnt = %d\", (unsigned)refcnt));\n\n        if (vol.NodeIDs.IsEmpty())\n          return S_FALSE;\n        \n        if (vol.NodeIDs.Back() != id)\n        {\n          // is it possible ?\n          // continue;\n          return S_FALSE;\n        }\n        \n        CNode &inode = vol.Nodes.Back();\n\n        if (inode.refcnt_defined)\n          return S_FALSE;\n\n        inode.refcnt = refcnt;\n        inode.refcnt_defined = true;\n        if (inode.refcnt != (UInt32)inode.nlink)\n        {\n          PRF(printf(\" refcnt != nlink\"));\n          // is it possible ?\n          // return S_FALSE;\n        }\n        continue;\n      }\n      \n      if (type == APFS_TYPE_FILE_EXTENT)\n      {\n        PRF(printf(\"  FILE_EXTENT\"));\n        /*\n        struct j_file_extent_key\n        {\n          j_key_t hdr;\n          uint64_t logical_addr;\n        }\n        */\n        if (pair.Key.Size() != 16)\n          return S_FALSE;\n        // The offset within the file's data, in bytes, for the data stored in this extent\n        const UInt64 logical_addr = Get64(p + 8);\n\n        j_file_extent_val eval;\n        if (pair.Val.Size() != k_SizeOf_j_file_extent_val)\n          return S_FALSE;\n        eval.Parse(pair.Val);\n\n        if (logical_addr != 0)\n        {\n          PRF(printf(\"  logical_addr = %d\", (unsigned)logical_addr));\n        }\n        PRF(printf(\"  len = %8d  pos = %8d\",\n            (unsigned)eval.len_and_flags,\n            (unsigned)eval.phys_block_num\n            ));\n\n        CExtent ext;\n        ext.logical_offset = logical_addr;\n        ext.len_and_flags = eval.len_and_flags;\n        ext.phys_block_num = eval.phys_block_num;\n        \n        if (vol.NodeIDs.IsEmpty())\n          return S_FALSE;\n        if (vol.NodeIDs.Back() != id)\n        {\n          // extents for Attributs;\n          if (vol.SmallNodeIDs.IsEmpty() ||\n              vol.SmallNodeIDs.Back() != id)\n          {\n            vol.SmallNodeIDs.Add(id);\n            vol.SmallNodes.AddNew();\n          }\n          vol.SmallNodes.Back().Extents.Add(ext);\n          continue;\n          // return S_FALSE;\n        }\n        \n        CNode &inode = vol.Nodes.Back();\n        inode.Extents.Add(ext);\n        continue;\n      }\n\n      if (type == APFS_TYPE_DIR_REC)\n      {\n        UInt32 len;\n        unsigned nameOffset;\n\n        if (isHashed)\n        {\n          /*\n          struct j_drec_hashed_key\n          {\n            j_key_t hdr;\n            UInt32 name_len_and_hash;\n            uint8_t name[0];\n          }\n          */\n          nameOffset = 8 + 4;\n          if (pair.Key.Size() < nameOffset + 1)\n            return S_FALSE;\n          const UInt32 name_len_and_hash = Get32(p + 8);\n          len = name_len_and_hash & J_DREC_LEN_MASK;\n        }\n        else\n        {\n          /*\n          struct j_drec_key\n          {\n            j_key_t hdr;\n            UInt16 name_len; // The length of the name, including the final null character\n            uint8_t name[0]; // The name, represented as a null-terminated UTF-8 string\n          }\n          */\n          nameOffset = 8 + 2;\n          if (pair.Key.Size() < nameOffset + 1)\n            return S_FALSE;\n          len = Get16(p + 8);\n        }\n        if (nameOffset + len != pair.Key.Size())\n          return S_FALSE;\n        \n        // CItem item;\n        item.Clear();\n\n        item.ParentId = id;\n        item.Name.SetFrom_CalcLen((const char *)p + nameOffset, len);\n        if (item.Name.Len() != len - 1)\n          return S_FALSE;\n\n        if (pair.Val.Size() < k_SizeOf_j_drec_val)\n          return S_FALSE;\n\n        item.Val.Parse(pair.Val);\n\n        if (pair.Val.Size() > k_SizeOf_j_drec_val)\n        {\n          // fixme: parse extra fields;\n          // UnsupportedFeature = true;\n          // return S_FALSE;\n        }\n        \n        vol.Items.Add(item);\n\n        /*\n        if (!vol.NodeIDs.IsEmpty() && vol.NodeIDs.Back() == id)\n          vol.Nodes.Back().NumItems++;\n        */\n        if (id == PRIV_DIR_INO_NUM)\n          vol.NumItems_In_PrivateDir++;\n        \n        PRF(printf(\" DIR_REC next=%6d flags=%2x %s\",\n            (unsigned)item.Val.file_id,\n            (unsigned)item.Val.flags,\n            item.Name.Ptr()));\n        continue;\n      }\n\n      if (type == APFS_TYPE_FILE_INFO)\n      {\n        if (pair.Key.Size() != 16)\n          return S_FALSE;\n        // j_file_info_key\n        const UInt64 info_and_lba = Get64(p + 8);\n       \n      #define J_FILE_INFO_LBA_MASK    0x00ffffffffffffffUL\n      // #define J_FILE_INFO_TYPE_MASK   0xff00000000000000UL\n      #define J_FILE_INFO_TYPE_SHIFT  56\n      #define APFS_FILE_INFO_DATA_HASH 1\n        \n        const unsigned infoType = (unsigned)(info_and_lba >> J_FILE_INFO_TYPE_SHIFT);\n        // address is a paddr_t\n        const UInt64 lba = info_and_lba & J_FILE_INFO_LBA_MASK;\n        // j_file_data_hash_val_t\n        /* Use this field of the union if the type stored in the info_and_lba field of j_file_info_val_t is\n           APFS_FILE_INFO_DATA_HASH */\n        if (infoType != APFS_FILE_INFO_DATA_HASH)\n          return S_FALSE;\n        if (pair.Val.Size() != 3 + vol.integrity.HashSize)\n          return S_FALSE;\n        /*\n        struct j_file_data_hash_val\n        {\n          UInt16 hashed_len; // The length, in blocks, of the data segment that was hashed.\n          UInt8 hash_size; // must be consistent with integrity_meta_phys_t::im_hash_type\n          UInt8 hash[0];\n        }\n        */\n\n        const unsigned hash_size = pair.Val[2];\n        if (hash_size != vol.integrity.HashSize)\n          return S_FALSE;\n\n        CHashChunk hr;\n        hr.hashed_len = GetUi16(pair.Val);\n        if (hr.hashed_len == 0)\n          return S_FALSE;\n        memcpy(hr.hash, (const Byte *)pair.Val + 3, vol.integrity.HashSize);\n        // (hashed_len <= 4) : we have seen\n        hr.lba = lba;\n        \n        PRF(printf(\"   FILE_INFO lba = %6x, hashed_len=%6d\",\n            (unsigned)lba,\n            (unsigned)hr.hashed_len));\n        \n        if (vol.Hash_IDs.IsEmpty() || vol.Hash_IDs.Back() != id)\n        {\n          vol.Hash_Vectors.AddNew();\n          vol.Hash_IDs.Add(id);\n        }\n        CStreamHashes &hashes = vol.Hash_Vectors.Back();\n        if (hashes.Size() != 0)\n        {\n          const CHashChunk &hr_Back = hashes.Back();\n          if (lba != hr_Back.lba + ((UInt64)hr_Back.hashed_len << sb.block_size_Log))\n            return S_FALSE;\n        }\n        hashes.Add(hr);\n        continue;\n      }\n\n      if (type == APFS_TYPE_SNAP_METADATA)\n      {\n        if (pair.Key.Size() != 8)\n          return S_FALSE;\n        PRF(printf(\" SNAP_METADATA\"));\n        // continue;\n      }\n\n      /* SIBLING items are used, if there are more than one hard link to some inode\n         key                                     : value\n         parent_id_1  DIR_REC                    : inode_id, name_1\n         parent_id_2  DIR_REC                    : inode_id, name_2\n         inode_id     INODE                      : parent_id_1, name_1\n         inode_id     SIBLING_LINK  sibling_id_1 : parent_id_1, name_1\n         inode_id     SIBLING_LINK  sibling_id_2 : parent_id_2, name_2\n         sibling_id_1 SIBLING_MAP                : inode_id\n         sibling_id_2 SIBLING_MAP                : inode_id\n      */\n      \n      if (type == APFS_TYPE_SIBLING_LINK)\n      {\n        if (pair.Key.Size() != 16)\n          return S_FALSE;\n        if (pair.Val.Size() < 10 + 1)\n          return S_FALSE;\n        /*\n        // struct j_sibling_key\n        // The sibling's unique identifier.\n        // This value matches the object identifier for the sibling map record\n        const UInt64 sibling_id = Get64(p + 8);\n        // struct j_sibling_val\n        const Byte *v = pair.Val;\n        const UInt64 parent_id = Get64(v); // The object identifier for the inode that's the parent directory.\n        const unsigned name_len = Get16(v + 8); // len including the final null character\n        if (10 + name_len != pair.Val.Size())\n          return S_FALSE;\n        if (v[10 + name_len - 1] != 0)\n          return S_FALSE;\n        AString name ((const char *)(v + 10));\n        if (name.Len() != name_len - 1)\n          return S_FALSE;\n        PRF(printf(\" SIBLING_LINK sibling_id = %6d : parent_id=%6d %s\",\n            (unsigned)sibling_id, (unsigned)parent_id, name.Ptr()));\n        */\n        continue;\n      }\n      \n      if (type == APFS_TYPE_SIBLING_MAP)\n      {\n        // struct j_sibling_map_key\n        // The object identifier in the header is the sibling's unique identifier\n        if (pair.Key.Size() != 8 || pair.Val.Size() != 8)\n          return S_FALSE;\n        /*\n        // j_sibling_map_val\n        // The inode number of the underlying file\n        const UInt64 file_id = Get64(pair.Val);\n        PRF(printf(\" SIBLING_MAP : file_id = %d\", (unsigned)file_id));\n        */\n        continue;\n      }\n      \n      UnsupportedFeature = true;\n      // return S_FALSE;\n    }\n    ProgressVal_NumFilesTotal += vol.Items.Size();\n  }\n\n\n  if (needParseAttr)\n  {\n    /* we read external streams for attributes\n       So we can get SymLink for GetProperty(kpidSymLink) later */\n    FOR_VECTOR (i, vol.Nodes)\n    {\n      CNode &node = vol.Nodes[i];\n\n      FOR_VECTOR (a, node.Attrs)\n      {\n        CAttr &attr = node.Attrs[a];\n        if (attr.Data.Size() != 0 || !attr.dstream_defined)\n          continue;\n        if (a == node.SymLinkIndex)\n        {\n          if (!attr.Is_dstream_OK_for_SymLink())\n            continue;\n        }\n        else\n        {\n          if (a != node.DecmpfsIndex\n              // && a != node.ResourceIndex\n              )\n          continue;\n        }\n        // we don't expect big streams here\n        // largest dstream for Decmpfs attribute is (2Kib+17)\n        if (attr.dstream.size > ((UInt32)1 << 16))\n          continue;\n        CMyComPtr<ISequentialInStream> inStream;\n        const HRESULT res = GetAttrStream_dstream(OpenInStream, vol, attr, &inStream);\n        if (res == S_OK && inStream)\n        {\n          CByteBuffer buf2;\n          const size_t size = (size_t)attr.dstream.size;\n          buf2.Alloc(size);\n          if (ReadStream_FAIL(inStream, buf2, size) == S_OK)\n            attr.Data = buf2;\n\n          ProgressVal_Cur += size;\n          if (OpenCallback)\n          if (ProgressVal_Cur - ProgressVal_Prev >= (1 << 22))\n          {\n\n            RINOK(OpenCallback->SetCompleted(\n                &ProgressVal_NumFilesTotal,\n                &ProgressVal_Cur))\n            ProgressVal_Prev = ProgressVal_Cur;\n          }\n        }\n      }\n\n      if (node.Has_UNCOMPRESSED_SIZE())\n      if (IsViDef(node.DecmpfsIndex))\n      {\n        CAttr &attr = node.Attrs[node.DecmpfsIndex];\n        node.CompressHeader.Parse(attr.Data, attr.Data.Size());\n        \n        if (node.CompressHeader.IsCorrect)\n          if (node.CompressHeader.Method < sizeof(MethodsMask) * 8)\n            MethodsMask |= ((UInt32)1 << node.CompressHeader.Method);\n\n        if (node.CompressHeader.IsCorrect\n            && node.CompressHeader.IsSupported\n            && node.CompressHeader.UnpackSize == node.uncompressed_size)\n        {\n          attr.NeedShow = false;\n          if (node.CompressHeader.IsMethod_Resource()\n              && IsViDef(node.ResourceIndex))\n            node.Attrs[node.ResourceIndex].NeedShow = false;\n        }\n        else\n        {\n          vol.UnsupportedMethod = true;\n        }\n      }\n    }\n  }\n\n  const HRESULT res = vol.FillRefs();\n\n  if (vol.ThereAreErrors())\n    HeadersError = true;\n  if (vol.UnsupportedFeature)\n    UnsupportedFeature = true;\n  if (vol.UnsupportedMethod)\n    UnsupportedMethod = true;\n  if (vol.NumAltStreams != 0)\n    ThereAreAltStreams = true;\n  \n  return res;\n}\n\n\n\nHRESULT CVol::FillRefs()\n{\n  {\n    Refs.Reserve(Items.Size());\n    // we fill Refs[*]\n    // we\n    // and set Nodes[*].ItemIndex for Nodes that are directories;\n    FOR_VECTOR (i, Items)\n    {\n      CItem &item = Items[i];\n      const UInt64 id = item.Val.file_id;\n      // if (item.Id == ROOT_DIR_PARENT) continue;\n      /* for two root folders items\n         we don't set Node.ItemIndex; */\n      // so nodes\n      if (id == ROOT_DIR_INO_NUM)\n        continue;\n      if (id == PRIV_DIR_INO_NUM)\n        if (NumItems_In_PrivateDir == 0) // if (inode.NumItems == 0)\n          continue;\n      \n      CRef ref;\n      ref.ItemIndex = i;\n      // ref.NodeIndex = VI_MINUS1;\n      ref.ParentRefIndex = VI_MINUS1;\n     #ifdef APFS_SHOW_ALT_STREAMS\n      ref.AttrIndex = VI_MINUS1;\n     #endif\n      const int index = NodeIDs.FindInSorted(id);\n      // const int index = -1; // for debug\n      ref.NodeIndex = (unsigned)index;\n      item.RefIndex = Refs.Size();\n      Refs.Add(ref);\n\n      if (index == -1)\n      {\n        NodeNotFound = true;\n        continue;\n        // return S_FALSE;\n      }\n      \n      // item.iNode_Index = index;\n      CNode &inode = Nodes[(unsigned)index];\n      if (!item.Val.IsFlags_Unknown()\n          && inode.Get_Type_From_mode() != item.Val.flags)\n      {\n        Refs.Back().NodeIndex = VI_MINUS1;\n        WrongInodeLink = true;\n        continue;\n        // return S_FALSE;\n      }\n\n      const bool isDir = inode.IsDir();\n      if (isDir)\n      {\n        if (IsViDef(inode.ItemIndex))\n        {\n          // hard links to dirs are not supported\n          Refs.Back().NodeIndex = VI_MINUS1;\n          WrongInodeLink = true;\n          continue;\n        }\n        inode.ItemIndex = i;\n      }\n      inode.NumCalcedLinks++;\n\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!isDir)\n      {\n        // we use alt streams only for files\n        const unsigned numAttrs = inode.Attrs.Size();\n        if (numAttrs != 0)\n        {\n          ref.ParentRefIndex = item.RefIndex;\n          for (unsigned k = 0; k < numAttrs; k++)\n          {\n            // comment it for debug\n            const CAttr &attr = inode.Attrs[k];\n            if (!attr.NeedShow)\n              continue;\n\n            if (k == inode.SymLinkIndex)\n              continue;\n            ref.AttrIndex = k;\n            NumAltStreams++;\n            Refs.Add(ref);\n            /*\n            if (attr.dstream_defined)\n            {\n              const int idIndex = SmallNodeIDs.FindInSorted(attr.Id);\n              if (idIndex != -1)\n                SmallNodes[(unsigned)idIndex].NumLinks++; // for debug\n            }\n            */\n          }\n        }\n      }\n     #endif\n    }\n  }\n\n\n  {\n    // fill ghost nodes\n    CRef ref;\n    ref.ItemIndex = VI_MINUS1;\n    ref.ParentRefIndex = VI_MINUS1;\n   #ifdef APFS_SHOW_ALT_STREAMS\n    ref.AttrIndex = VI_MINUS1;\n   #endif\n    FOR_VECTOR (i, Nodes)\n    {\n      if (Nodes[i].NumCalcedLinks != 0)\n        continue;\n      const UInt64 id = NodeIDs[i];\n      if (id == ROOT_DIR_INO_NUM ||\n          id == PRIV_DIR_INO_NUM)\n        continue;\n      ThereAreUnlinkedNodes = true;\n      ref.NodeIndex = i;\n      Refs.Add(ref);\n    }\n  }\n\n  /* if want to create Refs for ghost data streams,\n     we need additional CRef::SmallNodeIndex field */\n\n  {\n    /* all Nodes[*].ItemIndex were already filled for directory Nodes,\n       except of \"root\" and \"private-dir\" Nodes. */\n    \n    // now we fill Items[*].ParentItemIndex and Refs[*].ParentRefIndex\n\n    UInt64 prev_ID = (UInt64)(Int64)-1;\n    unsigned prev_ParentItemIndex = VI_MINUS1;\n\n    FOR_VECTOR (i, Items)\n    {\n      CItem &item = Items[i];\n      const UInt64 id = item.ParentId; // it's id of parent NODE\n      if (id != prev_ID)\n      {\n        prev_ID = id;\n        prev_ParentItemIndex = VI_MINUS1;\n        const int index = NodeIDs.FindInSorted(id);\n        if (index == -1)\n          continue;\n        prev_ParentItemIndex = Nodes[(unsigned)index].ItemIndex;\n      }\n\n      if (IsViNotDef(prev_ParentItemIndex))\n        continue;\n      item.ParentItemIndex = prev_ParentItemIndex;\n      if (IsViNotDef(item.RefIndex))\n      {\n        // RefIndex is not set for 2 Items (root folders)\n        // but there is no node for them usually\n        continue;\n      }\n      CRef &ref = Refs[item.RefIndex];\n\n      /*\n      // it's optional check that parent_id is set correclty\n      if (IsViDef(ref.NodeIndex))\n      {\n        const CNode &node = Nodes[ref.NodeIndex];\n        if (node.IsDir() && node.parent_id != id)\n          return S_FALSE;\n      }\n      */\n\n      /*\n      if (id == ROOT_DIR_INO_NUM)\n      {\n        // ItemIndex in Node for ROOT_DIR_INO_NUM was not set bofere\n        // probably unused now.\n        ref.ParentRefIndex = VI_MINUS1;\n      }\n      else\n      */\n        ref.ParentRefIndex = Items[prev_ParentItemIndex].RefIndex;\n    }\n  }\n\n  {\n    // check for loops\n    const unsigned numItems = Items.Size();\n    if (numItems + 1 == 0)\n      return S_FALSE;\n    CUIntArr arr;\n    arr.Alloc(numItems);\n    {\n      for (unsigned i = 0; i < numItems; i++)\n        arr[i] = 0;\n    }\n    for (unsigned i = 0; i < numItems;)\n    {\n      unsigned k = i++;\n      for (;;)\n      {\n        const unsigned a = arr[k];\n        if (a != 0)\n        {\n          if (a == i)\n            return S_FALSE;\n          break;\n        }\n        arr[k] = i;\n        k = Items[k].ParentItemIndex;\n        if (IsViNotDef(k))\n          break;\n      }\n    }\n  }\n  \n  return S_OK;\n}\n\n\n\nZ7_class_CHandler_final:\n  public IInArchive,\n  public IArchiveGetRawProps,\n  public IInArchiveGetStream,\n  public CMyUnknownImp,\n  public CDatabase\n{\n  Z7_IFACES_IMP_UNK_3(\n      IInArchive,\n      IArchiveGetRawProps,\n      IInArchiveGetStream)\n\n  CMyComPtr<IInStream> _stream;\n  int FindHashIndex_for_Item(UInt32 index);\n};\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  Close();\n  OpenInStream = inStream;\n  OpenCallback = callback;\n  RINOK(Open2())\n  _stream = inStream;\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _stream.Release();\n  Clear();\n  return S_OK;\n}\n\n\nenum\n{\n  kpidBytesWritten = kpidUserDefined,\n  kpidBytesRead,\n  kpidPrimeName,\n  kpidParentINode,\n  kpidAddTime,\n  kpidGeneration,\n  kpidBsdFlags\n  // kpidUncompressedSize\n};\n\nstatic const CStatProp kProps[] =\n{\n  { NULL, kpidPath, VT_BSTR },\n  { NULL, kpidSize, VT_UI8 },\n  { NULL, kpidPackSize, VT_UI8 },\n  { NULL, kpidPosixAttrib, VT_UI4 },\n  { NULL, kpidMTime, VT_FILETIME },\n  { NULL, kpidCTime, VT_FILETIME },\n  { NULL, kpidATime, VT_FILETIME },\n  { NULL, kpidChangeTime, VT_FILETIME },\n  { \"Added Time\", kpidAddTime, VT_FILETIME },\n  { NULL, kpidMethod, VT_BSTR },\n  { NULL, kpidINode, VT_UI8 },\n  { NULL, kpidLinks, VT_UI4 },\n  { NULL, kpidSymLink, VT_BSTR },\n  { NULL, kpidUserId, VT_UI4 },\n  { NULL, kpidGroupId, VT_UI4 },\n  { NULL, kpidCharacts, VT_BSTR },\n #ifdef APFS_SHOW_ALT_STREAMS\n  { NULL, kpidIsAltStream, VT_BOOL },\n #endif\n  { \"Parent iNode\", kpidParentINode, VT_UI8 },\n  { \"Primary Name\", kpidPrimeName, VT_BSTR },\n  { \"Generation\", kpidGeneration, VT_UI4 },\n  { \"Written Size\", kpidBytesWritten, VT_UI8 },\n  { \"Read Size\", kpidBytesRead, VT_UI8 },\n  { \"BSD Flags\", kpidBsdFlags, VT_UI4 }\n  // , { \"Uncompressed Size\", kpidUncompressedSize, VT_UI8 }\n};\n\n\nstatic const Byte kArcProps[] =\n{\n  kpidName,\n  kpidCharacts,\n  kpidId,\n  kpidClusterSize,\n  kpidCTime,\n  kpidMTime,\n  kpidComment\n};\n\nIMP_IInArchive_Props_WITH_NAME\nIMP_IInArchive_ArcProps\n\n\nstatic void ApfsTimeToProp(UInt64 hfsTime, NWindows::NCOM::CPropVariant &prop)\n{\n  if (hfsTime == 0)\n    return;\n  FILETIME ft;\n  UInt32 ns100;\n  ApfsTimeToFileTime(hfsTime, ft, ns100);\n  prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100);\n}\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CApfs *apfs = NULL;\n  if (Vols.Size() == 1)\n    apfs = &Vols[0].apfs;\n  switch (propID)\n  {\n    case kpidPhySize:\n      prop = (UInt64)sb.block_count << sb.block_size_Log;\n      break;\n    case kpidClusterSize: prop = (UInt32)(sb.block_size); break;\n    case kpidCharacts: NHfs::MethodsMaskToProp(MethodsMask, prop); break;\n    case kpidMTime:\n      if (apfs)\n        ApfsTimeToProp(apfs->modified_by[0].timestamp, prop);\n      break;\n    case kpidCTime:\n      if (apfs)\n        ApfsTimeToProp(apfs->formatted_by.timestamp, prop);\n      break;\n    case kpidIsTree: prop = true; break;\n    case kpidErrorFlags:\n    {\n      UInt32 flags = 0;\n      if (HeadersError) flags |= kpv_ErrorFlags_HeadersError;\n      if (flags != 0)\n        prop = flags;\n      break;\n    }\n    case kpidWarningFlags:\n    {\n      UInt32 flags = 0;\n      if (UnsupportedFeature) flags |= kpv_ErrorFlags_UnsupportedFeature;\n      if (UnsupportedMethod) flags |= kpv_ErrorFlags_UnsupportedMethod;\n      if (flags != 0)\n        prop = flags;\n      break;\n    }\n\n    case kpidName:\n    {\n      if (apfs)\n      {\n        UString s;\n        AddVolInternalName_toString(s, *apfs);\n        s += \".apfs\";\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidId:\n    {\n      char s[32 + 4];\n      sb.uuid.SetHex_To_str(s);\n      prop = s;\n      break;\n    }\n\n    case kpidComment:\n    {\n      UString s;\n      {\n        AddComment_UInt64(s, \"block_size\", sb.block_size);\n\n        FOR_VECTOR (i, Vols)\n        {\n          if (Vols.Size() > 1)\n          {\n            if (i != 0)\n            {\n              s += \"----\";\n              s.Add_LF();\n            }\n            AddComment_UInt64(s, \"Volume\", i + 1);\n          }\n          Vols[i].AddComment(s);\n        }\n      }\n      prop = s;\n      break;\n    }\n\n   #ifdef APFS_SHOW_ALT_STREAMS\n    case kpidIsAltStream:\n      prop = ThereAreAltStreams;\n      // prop = false; // for debug\n      break;\n   #endif\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = 0;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID))\n{\n  *name = NULL;\n  *propID = 0;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  *parentType = NParentType::kDir;\n\n  const CRef2 &ref2 = Refs2[index];\n  const CVol &vol = Vols[ref2.VolIndex];\n  UInt32 parentIndex = (UInt32)(Int32)-1;\n\n  if (IsViDef(ref2.RefIndex))\n  {\n    const CRef &ref = vol.Refs[ref2.RefIndex];\n   #ifdef APFS_SHOW_ALT_STREAMS\n    if (ref.IsAltStream())\n      *parentType = NParentType::kAltStream;\n   #endif\n    if (IsViDef(ref.ParentRefIndex))\n      parentIndex = (UInt32)(ref.ParentRefIndex + vol.StartRef2Index);\n    else if (index != vol.RootRef2Index && IsViDef(vol.RootRef2Index))\n      parentIndex = (UInt32)vol.RootRef2Index;\n  }\n\n  *parent = parentIndex;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n  UNUSED_VAR(index)\n  UNUSED_VAR(propID)\n  return S_OK;\n}\n\n\nstatic void Utf8Name_to_InterName(const AString &src, UString &dest)\n{\n  ConvertUTF8ToUnicode(src, dest);\n  NItemName::NormalizeSlashes_in_FileName_for_OsPath(dest);\n}\n\n\nstatic void AddNodeName(UString &s, const CNode &inode, UInt64 id)\n{\n  s += \"node\";\n  s.Add_UInt64(id);\n  if (!inode.PrimaryName.IsEmpty())\n  {\n    s.Add_Dot();\n    UString s2;\n    Utf8Name_to_InterName(inode.PrimaryName, s2);\n    s += s2;\n  }\n}\n\n\nvoid CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::CPropVariant &path) const\n{\n  const unsigned kNumLevelsMax = (1 << 10);\n  const unsigned kLenMax = (1 << 12);\n  UString s;\n  const CRef2 &ref2 = Refs2[index];\n  const CVol &vol = Vols[ref2.VolIndex];\n  \n  if (IsViDef(ref2.RefIndex))\n  {\n    const CRef &ref = vol.Refs[ref2.RefIndex];\n    unsigned cur = ref.ItemIndex;\n    UString s2;\n    if (IsViNotDef(cur))\n    {\n      if (inode)\n        AddNodeName(s, *inode, vol.NodeIDs[ref.NodeIndex]);\n    }\n    else\n    {\n      for (unsigned i = 0;; i++)\n      {\n        if (i >= kNumLevelsMax || s.Len() > kLenMax)\n        {\n          s.Insert(0, UString(\"[LONG_PATH]\"));\n          break;\n        }\n        const CItem &item = vol.Items[(unsigned)cur];\n        Utf8Name_to_InterName(item.Name, s2);\n        // s2 += \"a\\\\b\"; // for debug\n        s.Insert(0, s2);\n        cur = item.ParentItemIndex;\n        if (IsViNotDef(cur))\n          break;\n        // ParentItemIndex was not set for such items\n        // if (item.ParentId == ROOT_DIR_INO_NUM) break;\n        s.InsertAtFront(WCHAR_PATH_SEPARATOR);\n      }\n    }\n   \n   #ifdef APFS_SHOW_ALT_STREAMS\n    if (IsViDef(ref.AttrIndex) && inode)\n    {\n      s.Add_Colon();\n      Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2);\n      // s2 += \"a\\\\b\"; // for debug\n      s += s2;\n    }\n   #endif\n  }\n    \n  if (!vol.RootName.IsEmpty())\n  {\n    if (IsViDef(ref2.RefIndex))\n      s.InsertAtFront(WCHAR_PATH_SEPARATOR);\n    s.Insert(0, vol.RootName);\n  }\n\n  path = s;\n}\n\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n\n  const CRef2 &ref2 = Refs2[index];\n  const CVol &vol = Vols[ref2.VolIndex];\n\n  if (IsViNotDef(ref2.RefIndex))\n  {\n    switch (propID)\n    {\n      case kpidName:\n      case kpidPath:\n        GetItemPath(index, NULL, prop);\n        break;\n      case kpidIsDir:\n        prop = true;\n        break;\n    }\n    prop.Detach(value);\n    return S_OK;\n  }\n\n  const CRef &ref = vol.Refs[ref2.RefIndex];\n\n  const CItem *item = NULL;\n  if (IsViDef(ref.ItemIndex))\n    item = &vol.Items[ref.ItemIndex];\n\n  const CNode *inode = NULL;\n  if (IsViDef(ref.NodeIndex))\n    inode = &vol.Nodes[ref.NodeIndex];\n\n  switch (propID)\n  {\n    case kpidPath:\n      GetItemPath(index, inode, prop);\n      break;\n    case kpidPrimeName:\n    {\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!ref.IsAltStream())\n     #endif\n      if (inode && !inode->PrimaryName.IsEmpty())\n      {\n        UString s;\n        ConvertUTF8ToUnicode(inode->PrimaryName, s);\n        /*\n        // for debug:\n        if (inode.PrimaryName != item.Name) throw 123456;\n        */\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidName:\n    {\n      UString s;\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (ref.IsAltStream())\n      {\n        // if (inode)\n        {\n          const CAttr &attr = inode->Attrs[(unsigned)ref.AttrIndex];\n          ConvertUTF8ToUnicode(attr.Name, s);\n        }\n      }\n      else\n     #endif\n      {\n        if (item)\n          ConvertUTF8ToUnicode(item->Name, s);\n        else if (inode)\n          AddNodeName(s, *inode, vol.NodeIDs[ref.NodeIndex]);\n        else\n          break;\n      }\n      // s += \"s/1bs\\\\2\"; // for debug:\n      prop = s;\n      break;\n    }\n\n    case kpidSymLink:\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!ref.IsAltStream())\n     #endif\n      if (inode)\n      {\n        if (inode->IsSymLink() && IsViDef(inode->SymLinkIndex))\n        {\n          const CByteBuffer &buf = inode->Attrs[(unsigned)inode->SymLinkIndex].Data;\n          if (buf.Size() != 0)\n          {\n            AString s;\n            s.SetFrom_CalcLen((const char *)(const Byte *)buf, (unsigned)buf.Size());\n            if (s.Len() == buf.Size() - 1)\n            {\n              UString u;\n              ConvertUTF8ToUnicode(s, u);\n              prop = u;\n            }\n          }\n        }\n      }\n      break;\n\n    case kpidSize:\n      if (inode)\n      {\n        UInt64 size = 0;\n        if (inode->GetSize(ref.GetAttrIndex(), size) ||\n            !inode->IsDir())\n          prop = size;\n      }\n      break;\n\n    case kpidPackSize:\n      if (inode)\n      {\n        UInt64 size;\n        if (inode->GetPackSize(ref.GetAttrIndex(), size) ||\n            !inode->IsDir())\n          prop = size;\n      }\n      break;\n\n    case kpidMethod:\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!ref.IsAltStream())\n     #endif\n      if (inode)\n      {\n        if (inode->CompressHeader.IsCorrect)\n          inode->CompressHeader.MethodToProp(prop);\n        else if (IsViDef(inode->DecmpfsIndex))\n          prop = \"decmpfs\";\n        else if (!inode->IsDir() && !inode->dstream_defined)\n        {\n          if (inode->IsSymLink())\n          {\n            if (IsViDef(inode->SymLinkIndex))\n              prop = \"symlink\";\n          }\n          // else prop = \"no_dstream\";\n        }\n      }\n      break;\n    \n    /*\n    case kpidUncompressedSize:\n      if (inode && inode->Has_UNCOMPRESSED_SIZE())\n        prop = inode->uncompressed_size;\n      break;\n    */\n\n    case kpidIsDir:\n    {\n      bool isDir = false;\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!ref.IsAltStream())\n     #endif\n      {\n        if (inode)\n          isDir = inode->IsDir();\n        else if (item)\n          isDir = item->Val.IsFlags_Dir();\n      }\n      prop = isDir;\n      break;\n    }\n\n    case kpidPosixAttrib:\n    {\n      if (inode)\n      {\n        UInt32 mode = inode->mode;\n       #ifdef APFS_SHOW_ALT_STREAMS\n        if (ref.IsAltStream())\n        {\n          mode &= 0666; // we disable execution\n          mode |= MY_LIN_S_IFREG;\n        }\n       #endif\n        prop = (UInt32)mode;\n      }\n      else if (item && !item->Val.IsFlags_Unknown())\n        prop = (UInt32)(item->Val.flags << 12);\n      break;\n    }\n    \n    case kpidCTime: if (inode) ApfsTimeToProp(inode->create_time, prop); break;\n    case kpidMTime: if (inode) ApfsTimeToProp(inode->mod_time, prop); break;\n    case kpidATime: if (inode) ApfsTimeToProp(inode->access_time, prop); break;\n    case kpidChangeTime: if (inode) ApfsTimeToProp(inode->change_time, prop); break;\n    case kpidAddTime: if (item) ApfsTimeToProp(item->Val.date_added, prop); break;\n\n    case kpidBytesWritten:\n       #ifdef APFS_SHOW_ALT_STREAMS\n        if (!ref.IsAltStream())\n       #endif\n        if (inode && inode->dstream_defined)\n          prop = inode->dstream.total_bytes_written;\n        break;\n    case kpidBytesRead:\n       #ifdef APFS_SHOW_ALT_STREAMS\n        if (!ref.IsAltStream())\n       #endif\n        if (inode && inode->dstream_defined)\n          prop = inode->dstream.total_bytes_read;\n        break;\n\n   #ifdef APFS_SHOW_ALT_STREAMS\n    case kpidIsAltStream:\n      prop = ref.IsAltStream();\n      break;\n   #endif\n     \n    case kpidCharacts:\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!ref.IsAltStream())\n     #endif\n      if (inode)\n      {\n        FLAGS_TO_PROP(g_INODE_Flags, (UInt32)inode->internal_flags, prop);\n      }\n      break;\n\n    case kpidBsdFlags:\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!ref.IsAltStream())\n     #endif\n      if (inode)\n      {\n        FLAGS_TO_PROP(g_INODE_BSD_Flags, inode->bsd_flags, prop);\n      }\n      break;\n\n    case kpidGeneration:\n     #ifdef APFS_SHOW_ALT_STREAMS\n      // if (!ref.IsAltStream())\n     #endif\n      if (inode)\n        prop = inode->write_generation_counter;\n      break;\n\n    case kpidUserId:\n      if (inode)\n        prop = (UInt32)inode->owner;\n      break;\n\n    case kpidGroupId:\n      if (inode)\n        prop = (UInt32)inode->group;\n      break;\n\n    case kpidLinks:\n     #ifdef APFS_SHOW_ALT_STREAMS\n      if (!ref.IsAltStream())\n     #endif\n      if (inode && !inode->IsDir())\n        prop = (UInt32)inode->nlink;\n      break;\n\n    case kpidINode:\n     #ifdef APFS_SHOW_ALT_STREAMS\n      // here we can disable iNode for alt stream.\n      if (!ref.IsAltStream())\n     #endif\n      if (IsViDef(ref.NodeIndex))\n        prop = (UInt32)vol.NodeIDs[ref.NodeIndex];\n      break;\n\n    case kpidParentINode:\n       #ifdef APFS_SHOW_ALT_STREAMS\n        if (!ref.IsAltStream())\n       #endif\n      if (inode)\n        prop = (UInt32)inode->parent_id;\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nUInt64 CDatabase::GetSize(const UInt32 index) const\n{\n  const CRef2 &ref2 = Refs2[index];\n  const CVol &vol = Vols[ref2.VolIndex];\n  if (IsViNotDef(ref2.RefIndex))\n    return 0;\n  const CRef &ref = vol.Refs[ref2.RefIndex];\n  if (IsViNotDef(ref.NodeIndex))\n    return 0;\n  const CNode &inode = vol.Nodes[ref.NodeIndex];\n  UInt64 size;\n  if (inode.GetSize(ref.GetAttrIndex(), size))\n    return size;\n  return 0;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = Refs2.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt32 i;\n  {\n    UInt64 totalSize = 0;\n    for (i = 0; i < numItems; i++)\n    {\n      const UInt32 index = allFilesMode ? i : indices[i];\n      totalSize += GetSize(index);\n    }\n    RINOK(extractCallback->SetTotal(totalSize))\n  }\n\n  UInt64 currentTotalSize = 0, currentItemSize = 0;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  // We don't know if zlib without Adler is allowed in APFS.\n  // But zlib without Adler is allowed in HFS.\n  // So here we allow apfs/zlib without Adler:\n  NHfs::CDecoder decoder(true); // IsAdlerOptional\n\n  for (i = 0;; i++, currentTotalSize += currentItemSize)\n  {\n    lps->InSize = currentTotalSize;\n    lps->OutSize = currentTotalSize;\n    RINOK(lps->SetCur())\n\n    if (i >= numItems)\n      break;\n\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CRef2 &ref2 = Refs2[index];\n    const CVol &vol = Vols[ref2.VolIndex];\n\n    currentItemSize = GetSize(index);\n\n    int opRes;\n   {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    if (IsViNotDef(ref2.RefIndex))\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    const CRef &ref = vol.Refs[ref2.RefIndex];\n    bool isDir = false;\n    if (IsViDef(ref.NodeIndex))\n      isDir = vol.Nodes[ref.NodeIndex].IsDir();\n    else if (IsViDef(ref.ItemIndex))\n      isDir =\n        #ifdef APFS_SHOW_ALT_STREAMS\n          !ref.IsAltStream() &&\n        #endif\n          vol.Items[ref.ItemIndex].Val.IsFlags_Dir();\n\n    if (isDir)\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n    opRes = NExtract::NOperationResult::kDataError;\n\n    if (IsViDef(ref.NodeIndex))\n    {\n      const CNode &inode = vol.Nodes[ref.NodeIndex];\n      if (\n        #ifdef APFS_SHOW_ALT_STREAMS\n          !ref.IsAltStream() &&\n        #endif\n             !inode.dstream_defined\n          && inode.Extents.IsEmpty()\n          && inode.Has_UNCOMPRESSED_SIZE()\n          && inode.uncompressed_size == inode.CompressHeader.UnpackSize)\n      {\n        if (inode.CompressHeader.IsSupported)\n        {\n          CMyComPtr<ISequentialInStream> inStreamFork;\n          UInt64 forkSize = 0;\n          const CByteBuffer *decmpfs_Data = NULL;\n          \n          if (inode.CompressHeader.IsMethod_Resource())\n          {\n            if (IsViDef(inode.ResourceIndex))\n            {\n              const CAttr &attr = inode.Attrs[inode.ResourceIndex];\n              forkSize = attr.GetSize();\n              GetAttrStream(_stream, vol, attr, &inStreamFork);\n            }\n          }\n          else\n          {\n            const CAttr &attr = inode.Attrs[inode.DecmpfsIndex];\n            decmpfs_Data = &attr.Data;\n          }\n          \n          if (inStreamFork || decmpfs_Data)\n          {\n            const HRESULT hres = decoder.Extract(\n                inStreamFork, realOutStream,\n                forkSize,\n                inode.CompressHeader,\n                decmpfs_Data,\n                currentTotalSize, extractCallback,\n                opRes);\n            if (hres != S_FALSE && hres != S_OK)\n              return hres;\n          }\n        }\n        else\n          opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      }\n      else\n      {\n        CMyComPtr<ISequentialInStream> inStream;\n        if (GetStream(index, &inStream) == S_OK && inStream)\n        {\n          CMyComPtr2<ISequentialOutStream, COutStreamWithHash> hashStream;\n         \n          if (vol.integrity.Is_SHA256())\n          {\n            const int hashIndex = FindHashIndex_for_Item(index);\n            if (hashIndex != -1)\n            {\n              hashStream.Create_if_Empty();\n              hashStream->SetStream(realOutStream);\n              hashStream->Init(&(vol.Hash_Vectors[(unsigned)hashIndex]), sb.block_size_Log);\n            }\n          }\n          \n          RINOK(copyCoder.Interface()->Code(inStream,\n              hashStream.IsDefined() ?\n                  hashStream.Interface() :\n                  realOutStream.Interface(),\n              NULL, NULL, lps))\n          opRes = NExtract::NOperationResult::kDataError;\n          if (copyCoder->TotalSize == currentItemSize)\n          {\n            opRes = NExtract::NOperationResult::kOK;\n            if (hashStream.IsDefined())\n              if (!hashStream->FinalCheck())\n                opRes = NExtract::NOperationResult::kCRCError;\n          }\n          else if (copyCoder->TotalSize < currentItemSize)\n            opRes = NExtract::NOperationResult::kUnexpectedEnd;\n        }\n      }\n    }\n   }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = Refs2.Size();\n  return S_OK;\n}\n\n\nint CHandler::FindHashIndex_for_Item(UInt32 index)\n{\n  const CRef2 &ref2 = Refs2[index];\n  const CVol &vol = Vols[ref2.VolIndex];\n  if (IsViNotDef(ref2.RefIndex))\n    return -1;\n\n  const CRef &ref = vol.Refs[ref2.RefIndex];\n  if (IsViNotDef(ref.NodeIndex))\n    return -1;\n  const CNode &inode = vol.Nodes[ref.NodeIndex];\n\n  unsigned attrIndex = ref.GetAttrIndex();\n\n  if (IsViNotDef(attrIndex)\n      && !inode.dstream_defined\n      && inode.IsSymLink())\n  {\n    attrIndex = inode.SymLinkIndex;\n    if (IsViNotDef(attrIndex))\n      return -1;\n  }\n\n  if (IsViDef(attrIndex))\n  {\n    /* we have seen examples, where hash available for \"com.apple.ResourceFork\" stream.\n       these hashes for \"com.apple.ResourceFork\" stream are for unpacked data.\n       but the caller here needs packed data of stream. So we don't use hashes */\n    return -1;\n  }\n  else\n  {\n    if (!inode.dstream_defined)\n      return -1;\n    const UInt64 id = vol.NodeIDs[ref.NodeIndex];\n    return vol.Hash_IDs.FindInSorted(id);\n  }\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  *stream = NULL;\n\n  const CRef2 &ref2 = Refs2[index];\n  const CVol &vol = Vols[ref2.VolIndex];\n  if (IsViNotDef(ref2.RefIndex))\n    return S_FALSE;\n\n  const CRef &ref = vol.Refs[ref2.RefIndex];\n  if (IsViNotDef(ref.NodeIndex))\n    return S_FALSE;\n  const CNode &inode = vol.Nodes[ref.NodeIndex];\n\n  const CRecordVector<CExtent> *extents;\n  UInt64 rem = 0;\n\n  unsigned attrIndex = ref.GetAttrIndex();\n\n  if (IsViNotDef(attrIndex)\n      && !inode.dstream_defined\n      && inode.IsSymLink())\n  {\n    attrIndex = inode.SymLinkIndex;\n    if (IsViNotDef(attrIndex))\n      return S_FALSE;\n  }\n\n  if (IsViDef(attrIndex))\n  {\n    const CAttr &attr = inode.Attrs[(unsigned)attrIndex];\n    if (!attr.dstream_defined)\n    {\n      CMyComPtr2<ISequentialInStream, CBufInStream> streamTemp;\n      streamTemp.Create_if_Empty();\n      streamTemp->Init(attr.Data, attr.Data.Size(), (IInArchive *)this);\n      *stream = streamTemp.Detach();\n      return S_OK;\n    }\n    const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id);\n    if (idIndex != -1)\n      extents = &vol.SmallNodes[(unsigned)idIndex].Extents;\n    else\n    {\n      const int fext_Index = vol.FEXT_NodeIDs.FindInSorted(attr.Id);\n      if (fext_Index == -1)\n        return S_FALSE;\n      extents = &vol.FEXT_Nodes[(unsigned)fext_Index].Extents;\n    }\n    rem = attr.dstream.size;\n  }\n  else\n  {\n    if (IsViDef(ref.ItemIndex))\n      if (vol.Items[ref.ItemIndex].Val.IsFlags_Dir())\n        return S_FALSE;\n    if (inode.IsDir())\n      return S_FALSE;\n    extents = &inode.Extents;\n    if (inode.dstream_defined)\n    {\n      rem = inode.dstream.size;\n      if (inode.Extents.Size() == 0)\n      {\n        const int fext_Index = vol.FEXT_NodeIDs.FindInSorted(vol.NodeIDs[ref.NodeIndex]);\n        if (fext_Index != -1)\n          extents = &vol.FEXT_Nodes[(unsigned)fext_Index].Extents;\n      }\n    }\n    else\n    {\n      // return S_FALSE; // check it !!!  How zero size files are stored with dstream_defined?\n    }\n  }\n  return GetStream2(_stream, extents, rem, stream);\n}\n\n\n\nHRESULT CDatabase::GetAttrStream(IInStream *apfsInStream, const CVol &vol,\n    const CAttr &attr, ISequentialInStream **stream)\n{\n  *stream = NULL;\n  if (!attr.dstream_defined)\n  {\n    CMyComPtr2<ISequentialInStream, CBufInStream> streamTemp;\n    streamTemp.Create_if_Empty();\n    streamTemp->Init(attr.Data, attr.Data.Size(), (IInArchive *)this);\n    *stream = streamTemp.Detach();\n    return S_OK;\n  }\n  return GetAttrStream_dstream(apfsInStream, vol, attr, stream);\n}\n\n\nHRESULT CDatabase::GetAttrStream_dstream( IInStream *apfsInStream, const CVol &vol,\n    const CAttr &attr, ISequentialInStream **stream)\n{\n  const CRecordVector<CExtent> *extents;\n  {\n    const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id);\n    if (idIndex != -1)\n      extents = &vol.SmallNodes[(unsigned)idIndex].Extents;\n    else\n    {\n      const int fext_Index = vol.FEXT_NodeIDs.FindInSorted(attr.Id);\n      if (fext_Index == -1)\n        return S_FALSE;\n      extents = &vol.FEXT_Nodes[(unsigned)fext_Index].Extents;\n    }\n  }\n  return GetStream2(apfsInStream, extents, attr.dstream.size, stream);\n}\n\n\nHRESULT CDatabase::GetStream2(\n    IInStream *apfsInStream,\n    const CRecordVector<CExtent> *extents, UInt64 rem,\n    ISequentialInStream **stream)\n{\n  CMyComPtr2<ISequentialInStream, CExtentsStream> extentStream;\n  extentStream.Create_if_Empty();\n\n  UInt64 virt = 0;\n  FOR_VECTOR (i, *extents)\n  {\n    const CExtent &e = (*extents)[i];\n    if (virt != e.logical_offset)\n      return S_FALSE;\n    const UInt64 len = EXTENT_GET_LEN(e.len_and_flags);\n    if (len == 0)\n    {\n      return S_FALSE;\n      // continue;\n    }\n    if (rem == 0)\n      return S_FALSE;\n    UInt64 cur = len;\n    if (cur > rem)\n      cur = rem;\n    CSeekExtent se;\n    se.Phy = (UInt64)e.phys_block_num << sb.block_size_Log;\n    se.Virt = virt;\n    virt += cur;\n    rem -= cur;\n    extentStream->Extents.Add(se);\n    if (rem == 0)\n      if (i != extents->Size() - 1)\n        return S_FALSE;\n  }\n  \n  if (rem != 0)\n    return S_FALSE;\n  \n  CSeekExtent se;\n  se.Phy = 0;\n  se.Virt = virt;\n  extentStream->Extents.Add(se);\n  extentStream->Stream = apfsInStream;\n  extentStream->Init();\n  *stream = extentStream.Detach();\n  return S_OK;\n}\n\n\nREGISTER_ARC_I(\n  \"APFS\", \"apfs img\", NULL, 0xc3,\n  k_Signature,\n  k_SignatureOffset,\n  0,\n  IsArc_APFS)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ApmHandler.cpp",
    "content": "﻿// ApmHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get32(p) GetBe32a(p)\n\nusing namespace NWindows;\n\nnamespace NArchive {\n\nnamespace NDmg {\n  const char *Find_Apple_FS_Ext(const AString &name);\n  bool Is_Apple_FS_Or_Unknown(const AString &name);\n}\n\nnamespace NApm {\n\nstatic const Byte kSig0 = 'E';\nstatic const Byte kSig1 = 'R';\n\nstatic const CUInt32PCharPair k_Flags[] =\n{\n  { 0, \"VALID\" },\n  { 1, \"ALLOCATED\" },\n  { 2, \"IN_USE\" },\n  { 3, \"BOOTABLE\" },\n  { 4, \"READABLE\" },\n  { 5, \"WRITABLE\" },\n  { 6, \"OS_PIC_CODE\" },\n  // { 7, \"OS_SPECIFIC_2\" }, // \"Unused\"\n  { 8, \"ChainCompatible\" }, // \"OS_SPECIFIC_1\"\n  { 9, \"RealDeviceDriver\" },\n  // { 10, \"CanChainToNext\" },\n  { 30, \"MOUNTED_AT_STARTUP\" },\n  { 31, \"STARTUP\" }\n};\n\n#define DPME_FLAGS_VALID      (1u << 0)\n#define DPME_FLAGS_ALLOCATED  (1u << 1)\n\nstatic const unsigned k_Str_Size = 32;\n\nstruct CItem\n{\n  UInt32 StartBlock;\n  UInt32 NumBlocks;\n  UInt32 Flags; // pmPartStatus\n  char Name[k_Str_Size];\n  char Type[k_Str_Size];\n  /*\n  UInt32 DataStartBlock;\n  UInt32 NumDataBlocks;\n  UInt32 BootStartBlock;\n  UInt32 BootSize;\n  UInt32 BootAddr;\n  UInt32 BootEntry;\n  UInt32 BootChecksum;\n  char Processor[16];\n  */\n\n  bool Is_Valid_and_Allocated() const\n    { return (Flags & (DPME_FLAGS_VALID | DPME_FLAGS_ALLOCATED)) != 0; }\n\n  bool Parse(const UInt32 *p32, UInt32 &numBlocksInMap)\n  {\n    if (GetUi32a(p32) != 0x4d50) // \"PM\"\n      return false;\n    numBlocksInMap = Get32(p32 + 4 / 4);\n    StartBlock = Get32(p32 + 8 / 4);\n    NumBlocks = Get32(p32 + 0xc / 4);\n    Flags = Get32(p32 + 0x58 / 4);\n    memcpy(Name, p32 + 0x10 / 4, k_Str_Size);\n    memcpy(Type, p32 + 0x30 / 4, k_Str_Size);\n    /*\n    DataStartBlock = Get32(p + 0x50);\n    NumDataBlocks = Get32(p + 0x54);\n    BootStartBlock = Get32(p + 0x5c);\n    BootSize = Get32(p + 0x60);\n    BootAddr = Get32(p + 0x64);\n    if (Get32(p + 0x68) != 0)\n      return false;\n    BootEntry = Get32(p + 0x6c);\n    if (Get32(p + 0x70) != 0)\n      return false;\n    BootChecksum = Get32(p + 0x74);\n    memcpy(Processor, p32 + 0x78 / 4, 16);\n    */\n    return true;\n  }\n};\n\n\nZ7_class_CHandler_final: public CHandlerCont\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Cont)\n\n  CRecordVector<CItem> _items;\n  unsigned _blockSizeLog;\n  bool _isArc;\n  // UInt32 _numBlocks;\n  UInt64 _phySize;\n\n  UInt64 BlocksToBytes(UInt32 i) const { return (UInt64)i << _blockSizeLog; }\n\n  virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override\n  {\n    const CItem &item = _items[index];\n    pos = BlocksToBytes(item.StartBlock);\n    size = BlocksToBytes(item.NumBlocks);\n    return NExtract::NOperationResult::kOK;\n  }\n};\n\nstatic const UInt32 kSectorSize = 512;\n\n// we support only 4 cluster sizes: 512, 1024, 2048, 4096 */\n\nAPI_FUNC_static_IsArc IsArc_Apm(const Byte *p, size_t size)\n{\n  if (size < kSectorSize)\n    return k_IsArc_Res_NEED_MORE;\n  if (GetUi32(p + 12) != 0)\n    return k_IsArc_Res_NO;\n  UInt32 v = GetUi32(p); // we read as little-endian\n  v ^= kSig0 | (unsigned)kSig1 << 8;\n  if (v & ~((UInt32)0xf << 17))\n    return k_IsArc_Res_NO;\n  if ((0x116u >> (v >> 17)) & 1)\n    return k_IsArc_Res_YES;\n  return k_IsArc_Res_NO;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))\n{\n  COM_TRY_BEGIN\n  Close();\n\n  UInt32 buf32[kSectorSize / 4];\n  unsigned numPadSectors, blockSizeLog_from_Header;\n  {\n    // Driver Descriptor Map (DDM)\n    RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))\n    //  8: UInt16 sbDevType : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso\n    // 10: UInt16 sbDevId   : =0 (usually), =1 in Apple Mac OS X 10.3.0 iso\n    // 12: UInt32 sbData    : =0\n    if (buf32[3] != 0)\n      return S_FALSE;\n    UInt32 v = GetUi32a(buf32); // we read as little-endian\n    v ^= kSig0 | (unsigned)kSig1 << 8;\n    if (v & ~((UInt32)0xf << 17))\n      return S_FALSE;\n    v >>= 16;\n    if (v == 0)\n      return S_FALSE;\n    if (v & (v - 1))\n      return S_FALSE;\n    // v == { 16,8,4,2 } : block size (x256 bytes)\n    const unsigned a =\n#if 1\n        (0x30210u >> v) & 3;\n#else\n        0; // for debug : hardcoded switch to 512-bytes mode\n#endif\n    numPadSectors = (1u << a) - 1;\n    _blockSizeLog = blockSizeLog_from_Header = 9 + a;\n  }\n\n/*\n  some APMs (that are \".iso\" macOS installation files) contain\n    (blockSizeLog == 11) in DDM header,\n  and contain 2 overlapping maps:\n    1) map for  512-bytes-step\n    2) map for 2048-bytes-step\n   512-bytes-step map is correct.\n  2048-bytes-step map can be incorrect in some cases.\n\n  macos 8 / OSX DP2 iso:\n    There is shared \"hfs\" item in both maps.\n    And correct (offset/size) values for \"hfs\" partition\n    can be calculated only in 512-bytes mode (ignoring blockSizeLog == 11).\n    But some records (Macintosh.Apple_Driver*_)\n    can be correct on both modes: 512-bytes mode / 2048-bytes-step.\n  \n  macos 921 ppc / Apple Mac OS X 10.3.0 iso:\n    Both maps are correct.\n    If we use 512-bytes-step, each 4th item is (Apple_Void) with zero size.\n    And these zero size (Apple_Void) items will be first items in 2048-bytes-step map.\n*/\n\n// we define Z7_APM_SWITCH_TO_512_BYTES, because\n// we want to support old MACOS APMs that contain correct value only\n// for 512-bytes-step mode\n#define Z7_APM_SWITCH_TO_512_BYTES\n\n  const UInt32 numBlocks_from_Header = Get32(buf32 + 1);\n  UInt32 numBlocks = 0;\n  {\n    for (unsigned k = 0; k < numPadSectors; k++)\n    {\n      RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))\n#ifdef Z7_APM_SWITCH_TO_512_BYTES\n      if (k == 0)\n      {\n        if (GetUi32a(buf32) == 0x4d50        // \"PM\"\n            // && (Get32(buf32 + 0x58 / 4) & 1) // Flags::VALID\n            // some old APMs don't use VALID flag for Apple_partition_map item\n            && Get32(buf32 + 8 / 4) == 1)    // StartBlock\n        {\n          // we switch the mode to 512-bytes-step map reading:\n          numPadSectors = 0;\n          _blockSizeLog = 9;\n          break;\n        }\n      }\n#endif\n    }\n  }\n\n  for (unsigned i = 0;;)\n  {\n#ifdef Z7_APM_SWITCH_TO_512_BYTES\n    if (i != 0 || _blockSizeLog == blockSizeLog_from_Header)\n#endif\n    {\n      RINOK(ReadStream_FALSE(stream, buf32, kSectorSize))\n    }\n \n    CItem item;\n    UInt32 numBlocksInMap = 0;\n    if (!item.Parse(buf32, numBlocksInMap))\n      return S_FALSE;\n    // v24.09: we don't check that all entries have same (numBlocksInMap) values,\n    // because some APMs have different (numBlocksInMap) values, if (Apple_Void) is used.\n    if (numBlocksInMap > (1 << 8) || numBlocksInMap <= i)\n      return S_FALSE;\n\n    const UInt32 finish = item.StartBlock + item.NumBlocks;\n    if (finish < item.StartBlock)\n      return S_FALSE;\n    if (numBlocks < finish)\n        numBlocks = finish;\n    \n    _items.Add(item);\n    if (numPadSectors != 0)\n    {\n      RINOK(stream->Seek(numPadSectors << 9, STREAM_SEEK_CUR, NULL))\n    }\n    if (++i == numBlocksInMap)\n      break;\n  }\n  \n  _phySize = BlocksToBytes(numBlocks);\n  // _numBlocks = numBlocks;\n  const UInt64 physSize = (UInt64)numBlocks_from_Header << blockSizeLog_from_Header;\n  if (_phySize < physSize)\n      _phySize = physSize;\n  _isArc = true;\n  _stream = stream;\n\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _phySize = 0;\n  _items.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidOffset,\n  kpidCharacts\n  // , kpidCpu\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidClusterSize\n  // , kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic void GetString(AString &dest, const char *src)\n{\n  dest.SetFrom_CalcLen(src, k_Str_Size);\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile:\n    {\n      int mainIndex = -1;\n      FOR_VECTOR (i, _items)\n      {\n        const CItem &item = _items[i];\n        if (!item.Is_Valid_and_Allocated())\n          continue;\n        AString s;\n        GetString(s, item.Type);\n        if (NDmg::Is_Apple_FS_Or_Unknown(s))\n        {\n          if (mainIndex != -1)\n          {\n            mainIndex = -1;\n            break;\n          }\n          mainIndex = (int)i;\n        }\n      }\n      if (mainIndex != -1)\n        prop = (UInt32)(Int32)mainIndex;\n      break;\n    }\n    case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;\n    case kpidPhySize: prop = _phySize; break;\n    // case kpidNumBlocks: prop = _numBlocks; break;\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  const CItem &item = _items[index];\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      AString s;\n      GetString(s, item.Name);\n      if (s.IsEmpty())\n        s.Add_UInt32(index);\n      AString type;\n      GetString(type, item.Type);\n      {\n        const char *ext = NDmg::Find_Apple_FS_Ext(type);\n        if (ext)\n          type = ext;\n      }\n      if (!type.IsEmpty())\n      {\n        s.Add_Dot();\n        s += type;\n      }\n      prop = s;\n      break;\n    }\n/*\n    case kpidCpu:\n    {\n      AString s;\n      s.SetFrom_CalcLen(item.Processor, sizeof(item.Processor));\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n*/\n    case kpidSize:\n    case kpidPackSize:\n      prop = BlocksToBytes(item.NumBlocks);\n      break;\n    case kpidOffset: prop = BlocksToBytes(item.StartBlock); break;\n    case kpidCharacts: FLAGS_TO_PROP(k_Flags, item.Flags, prop); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = { kSig0, kSig1 };\n\nREGISTER_ARC_I(\n  \"APM\", \"apm\", NULL, 0xD4,\n  k_Signature,\n  0,\n  0,\n  IsArc_Apm)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ArHandler.cpp",
    "content": "﻿// ArHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/StringConvert.h\"\n#include \"../../Common/StringToInt.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/ItemNameUtils.h\"\n\nusing namespace NWindows;\nusing namespace NTime;\n\nnamespace NArchive {\nnamespace NAr {\n\n/*\nThe end of each file member (including last file in archive) is 2-bytes aligned.\nIt uses 0xA padding if required.\n\nFile Names:\n\nGNU/SVR4 variant (.a static library):\n  /       - archive symbol table\n  //      - the list of the long filenames, separated by one or more LF characters.\n  /N      - the reference to name string in long filenames list\n  name/   - the name\n\nMicrosoft variant (.lib static library):\n  /       - First linker file (archive symbol table)\n  /       - Second linker file\n  //      - the list of the long filenames, null-terminated. Each string begins\n            immediately after the null byte in the previous string.\n  /N      - the reference to name string in long filenames list\n  name/   - the name\n\nBSD (Mac OS X) variant:\n  \"__.SYMDEF\"         -  archive symbol table\n    or\n  \"__.SYMDEF SORTED\"  -  archive symbol table\n  #1/N    - the real filename of length N is appended to the file header.\n*/\n\nstatic const unsigned kSignatureLen = 8;\nstatic const Byte kSignature[kSignatureLen] =\n  { '!', '<', 'a', 'r', 'c', 'h', '>', 0x0A };\n\nstatic const unsigned kNameSize = 16;\nstatic const unsigned kTimeSize = 12;\nstatic const unsigned kUserSize = 6;\nstatic const unsigned kModeSize = 8;\nstatic const unsigned kSizeSize = 10;\n\nstatic const unsigned kHeaderSize = kNameSize + kTimeSize + kUserSize * 2 + kModeSize + kSizeSize + 1 + 1;\n\nenum EType\n{\n  kType_Ar,\n  kType_ALib,\n  kType_Deb,\n  kType_Lib\n};\n\nstatic const char * const k_TypeExtionsions[] =\n{\n    \"ar\"\n  , \"a\"\n  , \"deb\"\n  , \"lib\"\n};\n\nenum ESubType\n{\n  kSubType_None,\n  kSubType_BSD\n};\n\n/*\nstruct CHeader\n{\n  char Name[kNameSize];\n  char MTime[kTimeSize];\n  char User[kUserSize];\n  char Group[kUserSize];\n  char Mode[kModeSize];\n  char Size[kSizeSize];\n  char Quote;\n  char NewLine;\n};\n*/\n\nstruct CItem\n{\n  AString Name;\n  UInt64 Size;\n  UInt32 MTime;\n  UInt32 User;\n  UInt32 Group;\n  UInt32 Mode;\n  \n  UInt64 HeaderPos;\n  UInt64 HeaderSize;\n\n  int TextFileIndex;\n  int SameNameIndex;\n\n  CItem(): TextFileIndex(-1), SameNameIndex(-1) {}\n  UInt64 GetDataPos() const { return HeaderPos + HeaderSize; }\n};\n\nclass CInArchive\n{\n  CMyComPtr<IInStream> m_Stream;\n  \npublic:\n  UInt64 Position;\n  ESubType SubType;\n  \n  HRESULT GetNextItem(CItem &itemInfo, bool &filled);\n  HRESULT Open(IInStream *inStream);\n  HRESULT SkipData(UInt64 dataSize)\n  {\n    return m_Stream->Seek((Int64)(dataSize + (dataSize & 1)), STREAM_SEEK_CUR, &Position);\n  }\n};\n\nHRESULT CInArchive::Open(IInStream *inStream)\n{\n  SubType = kSubType_None;\n  RINOK(InStream_GetPos(inStream, Position))\n  char signature[kSignatureLen];\n  RINOK(ReadStream_FALSE(inStream, signature, kSignatureLen))\n  Position += kSignatureLen;\n  if (memcmp(signature, kSignature, kSignatureLen) != 0)\n    return S_FALSE;\n  m_Stream = inStream;\n  return S_OK;\n}\n\nstatic unsigned RemoveTailSpaces(char *dest, const char *s, unsigned size)\n{\n  memcpy(dest, s, size);\n  for (; size != 0; size--)\n  {\n    if (dest[size - 1] != ' ')\n      break;\n  }\n  dest[size] = 0;\n  return size;\n}\n\nstatic bool OctalToNumber32(const char *s, unsigned size, UInt32 &res)\n{\n  res = 0;\n  char sz[32];\n  size = RemoveTailSpaces(sz, s, size);\n  if (size == 0 || strcmp(sz, \"-1\") == 0)\n    return true; // some items don't contain any numbers\n  const char *end;\n  UInt64 res64 = ConvertOctStringToUInt64(sz, &end);\n  if ((unsigned)(end - sz) != size)\n    return false;\n  res = (UInt32)res64;\n  return (res64 <= 0xFFFFFFFF);\n}\n\nstatic bool DecimalToNumber(const char *s, unsigned size, UInt64 &res)\n{\n  res = 0;\n  char sz[32];\n  size = RemoveTailSpaces(sz, s, size);\n  if (size == 0 || strcmp(sz, \"-1\") == 0)\n    return true; // some items don't contain any numbers\n  const char *end;\n  res = ConvertStringToUInt64(sz, &end);\n  return ((unsigned)(end - sz) == size);\n}\n\nstatic bool DecimalToNumber32(const char *s, unsigned size, UInt32 &res)\n{\n  UInt64 res64;\n  if (!DecimalToNumber(s, size, res64))\n    return false;\n  res = (UInt32)res64;\n  return (res64 <= 0xFFFFFFFF);\n}\n\n#define RIF(x) { if (!(x)) return S_FALSE; }\n\n\nHRESULT CInArchive::GetNextItem(CItem &item, bool &filled)\n{\n  filled = false;\n\n  char header[kHeaderSize];\n  const char *cur = header;\n\n  {\n    size_t processedSize = sizeof(header);\n    item.HeaderPos = Position;\n    item.HeaderSize = kHeaderSize;\n    RINOK(ReadStream(m_Stream, header, &processedSize))\n    if (processedSize != sizeof(header))\n      return S_OK;\n    if (header[kHeaderSize - 2] != 0x60 ||\n      header[kHeaderSize - 1] != 0x0A)\n      return S_OK;\n    for (unsigned i = 0; i < kHeaderSize - 2; i++)\n      // if (header[i] < 0x20)\n      if (header[i] == 0)\n        return S_OK;\n    Position += processedSize;\n  }\n\n  UInt32 longNameLen = 0;\n  if (cur[0] == '#' &&\n      cur[1] == '1' &&\n      cur[2] == '/' &&\n      cur[3] != 0)\n  {\n    // BSD variant\n    RIF(DecimalToNumber32(cur + 3, kNameSize - 3 , longNameLen))\n    if (longNameLen >= (1 << 12))\n      longNameLen = 0;\n  }\n  else\n  {\n    char tempString[kNameSize + 1];\n    RemoveTailSpaces(tempString, cur, kNameSize);\n    item.Name = tempString;\n  }\n  cur += kNameSize;\n\n  RIF(DecimalToNumber32(cur, kTimeSize, item.MTime)) cur += kTimeSize;\n  RIF(DecimalToNumber32(cur, kUserSize, item.User)) cur += kUserSize;\n  RIF(DecimalToNumber32(cur, kUserSize, item.Group)) cur += kUserSize;\n  RIF(OctalToNumber32(cur, kModeSize, item.Mode)) cur += kModeSize;\n  RIF(DecimalToNumber(cur, kSizeSize, item.Size)) cur += kSizeSize;\n\n  if (longNameLen != 0 && longNameLen <= item.Size)\n  {\n    SubType = kSubType_BSD;\n    size_t processedSize = longNameLen;\n    char *s = item.Name.GetBuf(longNameLen);\n    HRESULT res = ReadStream(m_Stream, s, &processedSize);\n    item.Name.ReleaseBuf_CalcLen(longNameLen);\n    RINOK(res)\n    if (processedSize != longNameLen)\n      return S_OK;\n    item.Size -= longNameLen;\n    item.HeaderSize += longNameLen;\n    Position += processedSize;\n  }\n\n  filled = true;\n  return S_OK;\n}\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  bool _isArc;\n  CObjectVector<CItem> _items;\n  CMyComPtr<IInStream> _stream;\n  UInt64 _phySize;\n  Int32 _mainSubfile;\n\n  EType _type;\n  ESubType _subType;\n  int _longNames_FileIndex;\n  unsigned _numLibFiles;\n  AString _errorMessage;\n  AString _libFiles[2];\n\n  void UpdateErrorMessage(const char *s);\n  \n  HRESULT ParseLongNames(IInStream *stream);\n  void ChangeDuplicateNames();\n  int FindItem(UInt32 offset) const;\n  HRESULT AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos);\n  HRESULT ParseLibSymbols(IInStream *stream, unsigned fileIndex);\n};\n\nvoid CHandler::UpdateErrorMessage(const char *s)\n{\n  if (!_errorMessage.IsEmpty())\n    _errorMessage.Add_LF();\n  _errorMessage += s;\n}\n\nstatic const Byte kArcProps[] =\n{\n  kpidSubType\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidMTime,\n  kpidPosixAttrib,\n  kpidUserId,\n  kpidGroupId\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nHRESULT CHandler::ParseLongNames(IInStream *stream)\n{\n  unsigned i;\n  for (i = 0; i < _items.Size(); i++)\n    if (_items[i].Name.IsEqualTo(\"//\"))\n      break;\n  if (i == _items.Size())\n    return S_OK;\n\n  unsigned fileIndex = i;\n  const CItem &item = _items[fileIndex];\n  if (item.Size > ((UInt32)1 << 30))\n    return S_FALSE;\n  RINOK(InStream_SeekSet(stream, item.GetDataPos()))\n  const size_t size = (size_t)item.Size;\n\n  CByteArr p(size);\n  RINOK(ReadStream_FALSE(stream, p, size))\n  \n  for (i = 0; i < _items.Size(); i++)\n  {\n    CItem &item2 = _items[i];\n    if (item2.Name[0] != '/')\n      continue;\n    const char *ptr = item2.Name.Ptr(1);\n    const char *end;\n    UInt32 pos = ConvertStringToUInt32(ptr, &end);\n    if (*end != 0 || end == ptr)\n      continue;\n    if (pos >= size)\n      continue;\n    UInt32 start = pos;\n    for (;;)\n    {\n      if (pos >= size)\n        return S_FALSE;\n      const Byte c = p[pos];\n      if (c == 0 || c == 0x0A)\n        break;\n      pos++;\n    }\n    item2.Name.SetFrom((const char *)(p + start), (unsigned)(pos - start));\n  }\n  \n  _longNames_FileIndex = (int)fileIndex;\n  return S_OK;\n}\n\nvoid CHandler::ChangeDuplicateNames()\n{\n  unsigned i;\n  for (i = 1; i < _items.Size(); i++)\n  {\n    CItem &item = _items[i];\n    if (item.Name[0] == '/')\n      continue;\n    CItem &prev = _items[i - 1];\n    if (item.Name.IsEqualTo(prev.Name))\n    {\n      if (prev.SameNameIndex < 0)\n        prev.SameNameIndex = 0;\n      item.SameNameIndex = prev.SameNameIndex + 1;\n    }\n  }\n  for (i = 0; i < _items.Size(); i++)\n  {\n    CItem &item = _items[i];\n    if (item.SameNameIndex < 0)\n      continue;\n    char sz[32];\n    ConvertUInt32ToString((unsigned)item.SameNameIndex + 1, sz);\n    unsigned len = MyStringLen(sz);\n    sz[len++] = '.';\n    sz[len] = 0;\n    item.Name.Insert(0, sz);\n  }\n}\n\nint CHandler::FindItem(UInt32 offset) const\n{\n  unsigned left = 0, right = _items.Size();\n  while (left != right)\n  {\n    const unsigned mid = (left + right) / 2;\n    const UInt64 midVal = _items[mid].HeaderPos;\n    if (offset == midVal)\n      return (int)mid;\n    if (offset < midVal)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  return -1;\n}\n\nHRESULT CHandler::AddFunc(UInt32 offset, const Byte *data, size_t size, size_t &pos)\n{\n  const int fileIndex = FindItem(offset);\n  if (fileIndex < (int)0)\n    return S_FALSE;\n\n  size_t i = pos;\n  do\n  {\n    if (i >= size)\n      return S_FALSE;\n  }\n  while (data[i++] != 0);\n  \n  AString &s = _libFiles[_numLibFiles];\n  const AString &name = _items[(unsigned)fileIndex].Name;\n  s += name;\n  if (!name.IsEmpty() && name.Back() == '/')\n    s.DeleteBack();\n  s += \"    \";\n  s += (const char *)(data + pos);\n  // s.Add_Char((char)0xD);\n  s.Add_LF();\n  pos = i;\n  return S_OK;\n}\n\nstatic UInt32 Get32(const Byte *p, unsigned be) { if (be) return GetBe32(p); return GetUi32(p); }\n\nHRESULT CHandler::ParseLibSymbols(IInStream *stream, unsigned fileIndex)\n{\n  CItem &item = _items[fileIndex];\n  if (!item.Name.IsEqualTo(\"/\") &&\n      !item.Name.IsEqualTo(\"__.SYMDEF\")  &&\n      !item.Name.IsEqualTo(\"__.SYMDEF SORTED\"))\n    return S_OK;\n  if (item.Size > ((UInt32)1 << 30) ||\n      item.Size < 4)\n    return S_OK;\n  RINOK(InStream_SeekSet(stream, item.GetDataPos()))\n  size_t size = (size_t)item.Size;\n  CByteArr p(size);\n  RINOK(ReadStream_FALSE(stream, p, size))\n \n  size_t pos = 0;\n\n  if (!item.Name.IsEqualTo(\"/\"))\n  {\n    // \"__.SYMDEF\" parsing (BSD)\n    unsigned be;\n    for (be = 0; be < 2; be++)\n    {\n      const UInt32 tableSize = Get32(p, be);\n      pos = 4;\n      if (size - pos < tableSize || (tableSize & 7) != 0)\n        continue;\n      size_t namesStart = pos + tableSize;\n      const UInt32 namesSize = Get32(p.ConstData() + namesStart, be);\n      namesStart += 4;\n      if (namesStart > size || namesStart + namesSize != size)\n        continue;\n      \n      const UInt32 numSymbols = tableSize >> 3;\n      UInt32 i;\n      for (i = 0; i < numSymbols; i++, pos += 8)\n      {\n        size_t namePos = Get32(p + pos, be);\n        const UInt32 offset = Get32(p + pos + 4, be);\n        if (AddFunc(offset, p + namesStart, namesSize, namePos) != S_OK)\n          break;\n      }\n      if (i == numSymbols)\n      {\n        pos = size;\n        _type = kType_ALib;\n        _subType = kSubType_BSD;\n        break;\n      }\n    }\n    if (be == 2)\n      return S_FALSE;\n  }\n  else if (_numLibFiles == 0)\n  {\n    // archive symbol table (GNU)\n    const UInt32 numSymbols = GetBe32(p);\n    pos = 4;\n    if (numSymbols > (size - pos) / 4)\n      return S_FALSE;\n    pos += 4 * numSymbols;\n    \n    for (UInt32 i = 0; i < numSymbols; i++)\n    {\n      const UInt32 offset = GetBe32(p + 4 + i * 4);\n      RINOK(AddFunc(offset, p, size, pos))\n    }\n    _type = kType_ALib;\n  }\n  else\n  {\n    // Second linker file (Microsoft .lib)\n    const UInt32 numMembers = GetUi32(p);\n    pos = 4;\n    if (numMembers > (size - pos) / 4)\n      return S_FALSE;\n    pos += 4 * numMembers;\n    \n    if (size - pos < 4)\n      return S_FALSE;\n    const UInt32 numSymbols = GetUi32(p + pos);\n    pos += 4;\n    if (numSymbols > (size - pos) / 2)\n      return S_FALSE;\n    size_t indexStart = pos;\n    pos += 2 * numSymbols;\n    \n    for (UInt32 i = 0; i < numSymbols; i++)\n    {\n      // index is 1-based. So 32-bit numSymbols field works as item[0]\n      const UInt32 index = GetUi16(p + indexStart + i * 2);\n      if (index == 0 || index > numMembers)\n        return S_FALSE;\n      const UInt32 offset = GetUi32(p + index * 4);\n      RINOK(AddFunc(offset, p, size, pos))\n    }\n    _type = kType_Lib;\n  }\n  // size can be 2-byte aligned in linux files\n  if (pos != size && pos + (pos & 1) != size)\n    return S_FALSE;\n  item.TextFileIndex = (int)(_numLibFiles++);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n\n    UInt64 fileSize;\n    RINOK(InStream_AtBegin_GetSize(stream, fileSize))\n\n    CInArchive arc;\n    RINOK(arc.Open(stream))\n\n    if (callback)\n    {\n      RINOK(callback->SetTotal(NULL, &fileSize))\n      const UInt64 numFiles = _items.Size();\n      RINOK(callback->SetCompleted(&numFiles, &arc.Position))\n    }\n\n    CItem item;\n    for (;;)\n    {\n      bool filled;\n      RINOK(arc.GetNextItem(item, filled))\n      if (!filled)\n        break;\n      _items.Add(item);\n      arc.SkipData(item.Size);\n      if (callback && (_items.Size() & 0xFF) == 0)\n      {\n        const UInt64 numFiles = _items.Size();\n        RINOK(callback->SetCompleted(&numFiles, &arc.Position))\n      }\n    }\n\n    if (_items.IsEmpty())\n    {\n      // we don't need false empty archives (8-bytes signature only)\n      if (arc.Position != fileSize)\n        return S_FALSE;\n    }\n\n    _isArc = true;\n\n    _subType = arc.SubType;\n    \n    if (ParseLongNames(stream) != S_OK)\n      UpdateErrorMessage(\"Long file names parsing error\");\n    if (_longNames_FileIndex >= 0)\n      _items.Delete((unsigned)_longNames_FileIndex);\n\n    if (!_items.IsEmpty() && _items[0].Name.IsEqualTo(\"debian-binary\"))\n    {\n      _type = kType_Deb;\n      _items.DeleteFrontal(1);\n      for (unsigned i = 0; i < _items.Size(); i++)\n        if (_items[i].Name.IsPrefixedBy(\"data.tar.\"))\n        {\n          if (_mainSubfile < 0)\n            _mainSubfile = (int)i;\n          else\n          {\n            _mainSubfile = -1;\n            break;\n          }\n        }\n    }\n    else\n    {\n      ChangeDuplicateNames();\n      bool error = false;\n      for (unsigned li = 0; li < 2 && li < _items.Size(); li++)\n        if (ParseLibSymbols(stream, li) != S_OK)\n          error = true;\n      if (error)\n        UpdateErrorMessage(\"Library symbols information error\");\n    }\n\n    _stream = stream;\n    _phySize = arc.Position;\n\n    /*\n    if (fileSize < _phySize)\n      UpdateErrorMessage(\"Unexpected end of archive\");\n    */\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _phySize = 0;\n\n  _errorMessage.Empty();\n  _stream.Release();\n  _items.Clear();\n\n  _type = kType_Ar;\n  _subType = kSubType_None;\n  _mainSubfile = -1;\n  _longNames_FileIndex = -1;\n\n  _numLibFiles = 0;\n  _libFiles[0].Empty();\n  _libFiles[1].Empty();\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _phySize; break;\n    case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;\n    case kpidExtension: prop = k_TypeExtionsions[(unsigned)_type]; break;\n    case kpidShortComment:\n    case kpidSubType:\n    {\n      AString s (k_TypeExtionsions[(unsigned)_type]);\n      if (_subType == kSubType_BSD)\n        s += \":BSD\";\n      prop = s;\n      break;\n    }\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      prop = v;\n      break;\n    }\n    case kpidWarning: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;\n    case kpidIsNotArcType: if (_type != kType_Deb) prop = true; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CItem &item = _items[index];\n  switch (propID)\n  {\n    case kpidPath:\n      if (item.TextFileIndex >= 0)\n        prop = (item.TextFileIndex == 0) ? \"1.txt\" : \"2.txt\";\n      else\n        prop = (const wchar_t *)NItemName::GetOsPath_Remove_TailSlash(MultiByteToUnicodeString(item.Name, CP_OEMCP));\n      break;\n    case kpidSize:\n    case kpidPackSize:\n      if (item.TextFileIndex >= 0)\n        prop = (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len();\n      else\n        prop = item.Size;\n      break;\n    case kpidMTime:\n    {\n      if (item.MTime != 0)\n        PropVariant_SetFrom_UnixTime(prop, item.MTime);\n      break;\n    }\n    case kpidUserId: if (item.User != 0) prop = item.User; break;\n    case kpidGroupId: if (item.Group != 0) prop = item.Group; break;\n    case kpidPosixAttrib:\n      if (item.TextFileIndex < 0)\n        prop = item.Mode;\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const CItem &item = _items[allFilesMode ? i : indices[i]];\n    totalSize +=\n      (item.TextFileIndex >= 0) ?\n        (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;\n  }\n  extractCallback->SetTotal(totalSize);\n\n  UInt64 currentTotalSize = 0;\n  \n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_stream);\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = lps->OutSize = currentTotalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    Int32 opRes;\n   {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem &item = _items[index];\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n    currentTotalSize += (item.TextFileIndex >= 0) ?\n        (UInt64)_libFiles[(unsigned)item.TextFileIndex].Len() : item.Size;\n    \n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n    if (testMode)\n    {\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    opRes = NExtract::NOperationResult::kOK;\n    if (item.TextFileIndex >= 0)\n    {\n      const AString &f = _libFiles[(unsigned)item.TextFileIndex];\n      if (realOutStream)\n        RINOK(WriteStream(realOutStream, f, f.Len()))\n    }\n    else\n    {\n      RINOK(InStream_SeekSet(_stream, item.GetDataPos()))\n      inStream->Init(item.Size);\n      RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n      if (copyCoder->TotalSize != item.Size)\n        opRes = NExtract::NOperationResult::kDataError;\n    }\n   }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  const CItem &item = _items[index];\n  if (item.TextFileIndex >= 0)\n  {\n    const AString &f = _libFiles[(unsigned)item.TextFileIndex];\n    Create_BufInStream_WithNewBuffer((const void *)(const char *)f, f.Len(), stream);\n    return S_OK;\n  }\n  else\n    return CreateLimitedInStream(_stream, item.GetDataPos(), item.Size, stream);\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"Ar\", \"ar a deb udeb lib\", NULL, 0xEC,\n  kSignature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Archive2.def",
    "content": "EXPORTS\n  CreateObject PRIVATE\n\n  GetHandlerProperty PRIVATE\n  GetNumberOfFormats PRIVATE\n  GetHandlerProperty2 PRIVATE\n  GetIsArc PRIVATE\n\n  GetNumberOfMethods PRIVATE\n  GetMethodProperty PRIVATE\n  CreateDecoder PRIVATE\n  CreateEncoder PRIVATE\n\n  GetHashers PRIVATE\n\n  SetCodecs PRIVATE\n\n  SetLargePageMode PRIVATE\n  SetCaseSensitive PRIVATE\n\n  GetModuleProp PRIVATE\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ArchiveExports.cpp",
    "content": "﻿// ArchiveExports.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/7zVersion.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/RegisterArc.h\"\n\nstatic const unsigned kNumArcsMax = 256;\nstatic unsigned g_NumArcs = 0;\nstatic unsigned g_DefaultArcIndex = 0;\nstatic const CArcInfo *g_Arcs[kNumArcsMax];\n\nvoid RegisterArc(const CArcInfo *arcInfo) throw()\n{\n  if (g_NumArcs < kNumArcsMax)\n  {\n    const char *p = arcInfo->Name;\n    if (p[0] == '7' && p[1] == 'z' && p[2] == 0)\n      g_DefaultArcIndex = g_NumArcs;\n    g_Arcs[g_NumArcs++] = arcInfo;\n  }\n  // else throw 1;\n}\n\nZ7_DEFINE_GUID(CLSID_CArchiveHandler,\n    k_7zip_GUID_Data1,\n    k_7zip_GUID_Data2,\n    k_7zip_GUID_Data3_Common,\n    0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);\n\n#define CLS_ARC_ID_ITEM(cls) ((cls).Data4[5])\n\nstatic inline HRESULT SetPropStrFromBin(const char *s, unsigned size, PROPVARIANT *value)\n{\n  if ((value->bstrVal = ::SysAllocStringByteLen(s, size)) != NULL)\n    value->vt = VT_BSTR;\n  return S_OK;\n}\n\nstatic inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value)\n{\n  return SetPropStrFromBin((const char *)&guid, sizeof(guid), value);\n}\n\nstatic int FindFormatCalssId(const GUID *clsid)\n{\n  GUID cls = *clsid;\n  CLS_ARC_ID_ITEM(cls) = 0;\n  if (cls != CLSID_CArchiveHandler)\n    return -1;\n  const Byte id = CLS_ARC_ID_ITEM(*clsid);\n  for (unsigned i = 0; i < g_NumArcs; i++)\n    if (g_Arcs[i]->Id == id)\n      return (int)i;\n  return -1;\n}\n\nSTDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);\nSTDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject)\n{\n  COM_TRY_BEGIN\n  {\n    const int needIn = (*iid == IID_IInArchive);\n    const int needOut = (*iid == IID_IOutArchive);\n    if (!needIn && !needOut)\n      return E_NOINTERFACE;\n    const int formatIndex = FindFormatCalssId(clsid);\n    if (formatIndex < 0)\n      return CLASS_E_CLASSNOTAVAILABLE;\n    \n    const CArcInfo &arc = *g_Arcs[formatIndex];\n    if (needIn)\n    {\n      *outObject = arc.CreateInArchive();\n      ((IInArchive *)*outObject)->AddRef();\n    }\n    else\n    {\n      if (!arc.CreateOutArchive)\n        return CLASS_E_CLASSNOTAVAILABLE;\n      *outObject = arc.CreateOutArchive();\n      ((IOutArchive *)*outObject)->AddRef();\n    }\n  }\n  COM_TRY_END\n  return S_OK;\n}\n\nSTDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value);\nSTDAPI GetHandlerProperty2(UInt32 formatIndex, PROPID propID, PROPVARIANT *value)\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::PropVariant_Clear(value);\n  if (formatIndex >= g_NumArcs)\n    return E_INVALIDARG;\n  const CArcInfo &arc = *g_Arcs[formatIndex];\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case NArchive::NHandlerPropID::kName: prop = arc.Name; break;\n    case NArchive::NHandlerPropID::kClassID:\n    {\n      GUID clsId = CLSID_CArchiveHandler;\n      CLS_ARC_ID_ITEM(clsId) = arc.Id;\n      return SetPropGUID(clsId, value);\n    }\n    case NArchive::NHandlerPropID::kExtension: if (arc.Ext) prop = arc.Ext; break;\n    case NArchive::NHandlerPropID::kAddExtension: if (arc.AddExt) prop = arc.AddExt; break;\n    case NArchive::NHandlerPropID::kUpdate: prop = (bool)(arc.CreateOutArchive != NULL); break;\n    case NArchive::NHandlerPropID::kKeepName:   prop = ((arc.Flags & NArcInfoFlags::kKeepName) != 0); break;\n    case NArchive::NHandlerPropID::kAltStreams: prop = ((arc.Flags & NArcInfoFlags::kAltStreams) != 0); break;\n    case NArchive::NHandlerPropID::kNtSecure:   prop = ((arc.Flags & NArcInfoFlags::kNtSecure) != 0); break;\n    case NArchive::NHandlerPropID::kFlags: prop = (UInt32)arc.Flags; break;\n    case NArchive::NHandlerPropID::kTimeFlags: prop = (UInt32)arc.TimeFlags; break;\n    case NArchive::NHandlerPropID::kSignatureOffset: prop = (UInt32)arc.SignatureOffset; break;\n    // case NArchive::NHandlerPropID::kVersion: prop = (UInt32)MY_VER_MIX; break;\n\n    case NArchive::NHandlerPropID::kSignature:\n      if (arc.SignatureSize != 0 && !arc.IsMultiSignature())\n        return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);\n      break;\n    case NArchive::NHandlerPropID::kMultiSignature:\n      if (arc.SignatureSize != 0 && arc.IsMultiSignature())\n        return SetPropStrFromBin((const char *)arc.Signature, arc.SignatureSize, value);\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nSTDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value);\nSTDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)\n{\n  return GetHandlerProperty2(g_DefaultArcIndex, propID, value);\n}\n\nSTDAPI GetNumberOfFormats(UINT32 *numFormats);\nSTDAPI GetNumberOfFormats(UINT32 *numFormats)\n{\n  *numFormats = g_NumArcs;\n  return S_OK;\n}\n\nSTDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc);\nSTDAPI GetIsArc(UInt32 formatIndex, Func_IsArc *isArc)\n{\n  *isArc = NULL;\n  if (formatIndex >= g_NumArcs)\n    return E_INVALIDARG;\n  *isArc = g_Arcs[formatIndex]->IsArc;\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ArjHandler.cpp",
    "content": "﻿// ArjHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/AutoPtr.h\"\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/LzhDecoder.h\"\n\n#include \"Common/ItemNameUtils.h\"\n#include \"Common/OutStreamWithCRC.h\"\n\nnamespace NCompress {\nnamespace NArj {\nnamespace NDecoder {\n\nstatic const unsigned kMatchMinLen = 3;\nstatic const UInt32 kWindowSize = 1 << 15; // must be >= (1 << 14)\n\nclass CCoder\n{\n  CLzOutWindow _outWindow;\n  NBitm::CDecoder<CInBuffer> _inBitStream;\n  // bool FinishMode;\n\n  class CCoderReleaser\n  {\n    CCoder *_coder;\n  public:\n    CCoderReleaser(CCoder *coder): _coder(coder) {}\n    void Disable() { _coder = NULL; }\n    ~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); }\n  };\n  friend class CCoderReleaser;\n\n  HRESULT CodeReal(UInt32 outSize, ICompressProgressInfo *progress);\npublic:\n\n  // CCoder(): FinishMode(true) {}\n  UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }\n  HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    UInt32 outSize, ICompressProgressInfo *progress);\n};\n\n\nHRESULT CCoder::CodeReal(UInt32 rem, ICompressProgressInfo *progress)\n{\n  const UInt32 kStep = 1 << 20;\n  UInt32 next = 0;\n  if (rem > kStep && progress)\n    next = rem - kStep;\n\n  while (rem != 0)\n  {\n    if (rem <= next)\n    {\n      if (_inBitStream.ExtraBitsWereRead())\n        return S_FALSE;\n      const UInt64 packSize = _inBitStream.GetProcessedSize();\n      const UInt64 pos = _outWindow.GetProcessedSize();\n      RINOK(progress->SetRatioInfo(&packSize, &pos))\n      next = 0;\n      if (rem > kStep)\n        next = rem - kStep;\n    }\n\n    UInt32 len;\n    {\n      const unsigned kNumBits = 7 + 7;\n      const UInt32 val = _inBitStream.GetValue(kNumBits);\n      \n      if ((val & (1u << (kNumBits - 1))) == 0)\n      {\n        _outWindow.PutByte((Byte)(val >> 5));\n        _inBitStream.MovePos(1 + 8);\n        rem--;\n        continue;\n      }\n\n      unsigned w;\n      {\n        UInt32 flag = (UInt32)1 << (kNumBits - 2);\n        for (w = 1; w < 7; w++, flag >>= 1)\n          if ((val & flag) == 0)\n            break;\n      }\n      const unsigned readBits = (w != 7 ? 1 : 0) + w * 2;\n      const UInt32 mask = ((UInt32)1 << w) - 1;\n      len = mask + kMatchMinLen - 1 +\n          ((val >> (kNumBits - readBits)) & mask);\n      _inBitStream.MovePos(readBits);\n    }\n    {\n      const unsigned kNumBits = 4 + 13;\n      const UInt32 val = _inBitStream.GetValue(kNumBits);\n      unsigned readBits = 1;\n      unsigned w;\n           if ((val & ((UInt32)1 << 16)) == 0) w = 9;\n      else if ((val & ((UInt32)1 << 15)) == 0) w = 10;\n      else if ((val & ((UInt32)1 << 14)) == 0) w = 11;\n      else if ((val & ((UInt32)1 << 13)) == 0) w = 12;\n      else { w = 13; readBits = 0; }\n\n      readBits += w + w - 9;\n      const UInt32 dist = ((UInt32)1 << w) - (1 << 9) +\n          (((val >> (kNumBits - readBits)) & ((1 << w) - 1)));\n      _inBitStream.MovePos(readBits);\n      if (len > rem)\n      {\n        // if (FinishMode)\n        return S_FALSE;\n        // else len = (UInt32)rem;\n      }\n      if (!_outWindow.CopyBlock(dist, len))\n        return S_FALSE;\n      rem -= len;\n    }\n  }\n\n  // if (FinishMode)\n  {\n    if (_inBitStream.ReadAlignBits() != 0)\n      return S_FALSE;\n  }\n  if (_inBitStream.ExtraBitsWereRead())\n    return S_FALSE;\n  return S_OK;\n}\n\n\nHRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    UInt32 outSize, ICompressProgressInfo *progress)\n{\n  try\n  {\n    if (!_outWindow.Create(kWindowSize))\n      return E_OUTOFMEMORY;\n    if (!_inBitStream.Create(1 << 17))\n      return E_OUTOFMEMORY;\n    _outWindow.SetStream(outStream);\n    _outWindow.Init(false);\n    _inBitStream.SetStream(inStream);\n    _inBitStream.Init();\n    {\n      CCoderReleaser coderReleaser(this);\n      RINOK(CodeReal(outSize, progress))\n      coderReleaser.Disable();\n    }\n    return _outWindow.Flush();\n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\n}}}\n\n\n\n\nusing namespace NWindows;\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n\nnamespace NArchive {\nnamespace NArj {\n\nstatic const unsigned kBlockSizeMin = 30;\nstatic const unsigned kBlockSizeMax = 2600;\n\nstatic const Byte kSig0 = 0x60;\nstatic const Byte kSig1 = 0xEA;\n\nnamespace NCompressionMethod\n{\n  enum\n  {\n    kStored = 0,\n    kCompressed1a = 1,\n    kCompressed1b = 2,\n    kCompressed1c = 3,\n    kCompressed2 = 4,\n    kNoDataNoCRC = 8,\n    kNoData = 9\n  };\n}\n\nnamespace NFileType\n{\n  enum\n  {\n    kBinary = 0,\n    k7BitText,\n    kArchiveHeader,\n    kDirectory,\n    kVolumeLablel,\n    kChapterLabel\n  };\n}\n\nnamespace NFlags\n{\n  const Byte kGarbled  = 1 << 0;\n  // const Byte kAnsiPage = 1 << 1; // or (OLD_SECURED_FLAG) obsolete\n  const Byte kVolume   = 1 << 2;\n  const Byte kExtFile  = 1 << 3;\n  // const Byte kPathSym  = 1 << 4;\n  // const Byte kBackup   = 1 << 5; // obsolete\n  // const Byte kSecured  = 1 << 6;\n  // const Byte kDualName = 1 << 7;\n}\n\nnamespace NHostOS\n{\n  enum EEnum\n  {\n    kMSDOS = 0,  // MS-DOS, OS/2, Win32, pkarj 2.50 (FAT / VFAT / FAT32)\n    kPRIMOS,\n    kUnix,\n    kAMIGA,\n    kMac,\n    kOS_2,\n    kAPPLE_GS,\n    kAtari_ST,\n    kNext,\n    kVAX_VMS,\n    kWIN95\n  };\n}\n\nstatic const char * const kHostOS[] =\n{\n    \"MSDOS\"\n  , \"PRIMOS\"\n  , \"UNIX\"\n  , \"AMIGA\"\n  , \"MAC\"\n  , \"OS/2\"\n  , \"APPLE GS\"\n  , \"ATARI ST\"\n  , \"NEXT\"\n  , \"VAX VMS\"\n  , \"WIN95\"\n};\n\nstruct CArcHeader\n{\n  // Byte ArchiverVersion;\n  // Byte ExtractVersion;\n  Byte HostOS;\n  // Byte Flags;\n  // Byte SecuryVersion;\n  // Byte FileType;\n  // Byte Reserved;\n  UInt32 CTime;\n  UInt32 MTime;\n  UInt32 ArchiveSize;\n  // UInt32 SecurPos;\n  // UInt16 FilespecPosInFilename;\n  UInt16 SecurSize;\n  // Byte EncryptionVersion;\n  // Byte LastChapter;\n  AString Name;\n  AString Comment;\n  \n  HRESULT Parse(const Byte *p, unsigned size);\n};\n\nAPI_FUNC_static_IsArc IsArc_Arj(const Byte *p, size_t size)\n{\n  if (size < kBlockSizeMin + 4)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != kSig0 || p[1] != kSig1)\n    return k_IsArc_Res_NO;\n  UInt32 blockSize = Get16(p + 2);\n  if (blockSize < kBlockSizeMin ||\n      blockSize > kBlockSizeMax)\n    return k_IsArc_Res_NO;\n\n  p += 4;\n  size -= 4;\n\n  Byte headerSize = p[0];\n  if (headerSize < kBlockSizeMin ||\n      headerSize > blockSize ||\n      p[6] != NFileType::kArchiveHeader ||\n      p[28] > 8) // EncryptionVersion\n    return k_IsArc_Res_NO;\n\n  if (blockSize + 4 <= size)\n    if (Get32(p + blockSize) != CrcCalc(p, blockSize))\n      return k_IsArc_Res_NO;\n\n  return k_IsArc_Res_YES;\n}\n}\n\nstatic HRESULT ReadString(const Byte *p, unsigned &size, AString &res)\n{\n  unsigned num = size;\n  for (unsigned i = 0; i < num;)\n  {\n    if (p[i++] == 0)\n    {\n      size = i;\n      res = (const char *)p;\n      return S_OK;\n    }\n  }\n  return S_FALSE;\n}\n\nHRESULT CArcHeader::Parse(const Byte *p, unsigned size)\n{\n  Byte headerSize = p[0];\n  if (headerSize < kBlockSizeMin || headerSize > size)\n    return S_FALSE;\n  // ArchiverVersion = p[1];\n  // ExtractVersion = p[2];\n  HostOS = p[3];\n  // Flags = p[4];\n  // SecuryVersion = p[5];\n  if (p[6] != NFileType::kArchiveHeader)\n    return S_FALSE;\n  // Reserved = p[7];\n  CTime = Get32(p + 8);\n  MTime = Get32(p + 12);\n  ArchiveSize = Get32(p + 16); // it can be zero. (currently used only for secured archives)\n  // SecurPos = Get32(p + 20);\n  // UInt16 filespecPositionInFilename = Get16(p + 24);\n  SecurSize = Get16(p + 26);\n  // EncryptionVersion = p[28];\n  // LastChapter = p[29];\n  unsigned pos = headerSize;\n  unsigned size1 = size - pos;\n  RINOK(ReadString(p + pos, size1, Name))\n  pos += size1;\n  size1 = size - pos;\n  RINOK(ReadString(p + pos, size1, Comment))\n  pos += size1;\n  return S_OK;\n}\n\n\nstruct CExtendedInfo\n{\n  UInt64 Size;\n  bool CrcError;\n  \n  void Clear()\n  {\n    Size = 0;\n    CrcError = false;\n  }\n  void ParseToPropVar(NCOM::CPropVariant &prop) const\n  {\n    if (Size != 0)\n    {\n       AString s;\n       s += \"Extended:\";\n       s.Add_UInt32((UInt32)Size);\n       if (CrcError)\n         s += \":CRC_ERROR\";\n       prop = s;\n    }\n  }\n};\n\n\nstruct CItem\n{\n  AString Name;\n  AString Comment;\n\n  UInt32 MTime;\n  UInt32 PackSize;\n  UInt32 Size;\n  UInt32 FileCRC;\n  UInt32 SplitPos;\n\n  Byte Version;\n  Byte ExtractVersion;\n  Byte HostOS;\n  Byte Flags;\n  Byte Method;\n  Byte FileType;\n\n  // UInt16 FilespecPosInFilename;\n  UInt16 FileAccessMode;\n  // Byte FirstChapter;\n  // Byte LastChapter;\n  \n  UInt64 DataPosition;\n\n  CExtendedInfo ExtendedInfo;\n  \n  bool IsEncrypted() const { return (Flags & NFlags::kGarbled) != 0; }\n  bool IsDir() const { return (FileType == NFileType::kDirectory); }\n  bool IsSplitAfter() const { return (Flags & NFlags::kVolume) != 0; }\n  bool IsSplitBefore() const { return (Flags & NFlags::kExtFile) != 0; }\n  UInt32 GetWinAttrib() const\n  {\n    UInt32 atrrib = 0;\n    switch (HostOS)\n    {\n      case NHostOS::kMSDOS:\n      case NHostOS::kWIN95:\n        atrrib = FileAccessMode;\n        break;\n    }\n    if (IsDir())\n      atrrib |= FILE_ATTRIBUTE_DIRECTORY;\n    return atrrib;\n  }\n\n  HRESULT Parse(const Byte *p, unsigned size);\n};\n\nHRESULT CItem::Parse(const Byte *p, unsigned size)\n{\n  Byte headerSize = p[0];\n  if (headerSize < kBlockSizeMin || headerSize > size)\n    return S_FALSE;\n  Version = p[1];\n  ExtractVersion = p[2];\n  HostOS = p[3];\n  Flags = p[4];\n  Method = p[5];\n  FileType = p[6];\n  // Reserved = p[7];\n  MTime = Get32(p + 8);\n  PackSize = Get32(p + 12);\n  Size = Get32(p + 16);\n  FileCRC = Get32(p + 20);\n  // FilespecPosInFilename = Get16(p + 24);\n  FileAccessMode = Get16(p + 26);\n  // FirstChapter = p[28];\n  // FirstChapter = p[29];\n\n  SplitPos = 0;\n  if (IsSplitBefore() && headerSize >= 34)\n    SplitPos = Get32(p + 30);\n\n  unsigned pos = headerSize;\n  unsigned size1 = size - pos;\n  RINOK(ReadString(p + pos, size1, Name))\n  pos += size1;\n  size1 = size - pos;\n  RINOK(ReadString(p + pos, size1, Comment))\n  pos += size1;\n\n  return S_OK;\n}\n\nenum EErrorType\n{\n  k_ErrorType_OK,\n  k_ErrorType_Corrupted,\n  k_ErrorType_UnexpectedEnd\n};\n\nclass CArc\n{\npublic:\n  UInt64 Processed;\n  EErrorType Error;\n  bool IsArc;\n  IInStream *Stream;\n  IArchiveOpenCallback *Callback;\n  UInt64 NumFiles;\n  CArcHeader Header;\n\n  CExtendedInfo ExtendedInfo;\n\n  HRESULT Open();\n  HRESULT GetNextItem(CItem &item, bool &filled);\n  void Close()\n  {\n    IsArc = false;\n    Error = k_ErrorType_OK;\n    ExtendedInfo.Clear();\n  }\nprivate:\n  unsigned _blockSize;\n  CByteBuffer _block;\n\n  HRESULT ReadBlock(bool &filled, CExtendedInfo *extendedInfo);\n  HRESULT SkipExtendedHeaders(CExtendedInfo &extendedInfo);\n  HRESULT Read(void *data, size_t *size);\n};\n\nHRESULT CArc::Read(void *data, size_t *size)\n{\n  HRESULT res = ReadStream(Stream, data, size);\n  Processed += *size;\n  return res;\n}\n\n#define READ_STREAM(_dest_, _size_) \\\n  { size_t _processed_ = (_size_); RINOK(Read(_dest_, &_processed_)); \\\n  if (_processed_ != (_size_)) { Error = k_ErrorType_UnexpectedEnd; return S_OK; } }\n\nHRESULT CArc::ReadBlock(bool &filled, CExtendedInfo *extendedInfo)\n{\n  Error = k_ErrorType_OK;\n  filled = false;\n  Byte buf[4];\n  const unsigned signSize = extendedInfo ? 0 : 2;\n  READ_STREAM(buf, signSize + 2)\n  if (!extendedInfo)\n    if (buf[0] != kSig0 || buf[1] != kSig1)\n    {\n      Error = k_ErrorType_Corrupted;\n      return S_OK;\n    }\n  _blockSize = Get16(buf + signSize);\n  if (_blockSize == 0) // end of archive\n    return S_OK;\n\n  if (!extendedInfo)\n    if (_blockSize < kBlockSizeMin || _blockSize > kBlockSizeMax)\n    {\n      Error = k_ErrorType_Corrupted;\n      return S_OK;\n    }\n\n  const size_t readSize = _blockSize + 4;\n  if (readSize > _block.Size())\n  {\n    // extended data size is limited by (64 KB)\n    // _blockSize is less than 64 KB\n    const size_t upSize = (_blockSize > kBlockSizeMax ? (1 << 16) : kBlockSizeMax);\n    _block.Alloc(upSize + 4);\n  }\n\n  if (extendedInfo)\n    extendedInfo->Size += _blockSize;\n\n  READ_STREAM(_block, readSize)\n  if (Get32(_block + _blockSize) != CrcCalc(_block, _blockSize))\n  {\n    if (extendedInfo)\n      extendedInfo->CrcError = true;\n    else\n    {\n      Error = k_ErrorType_Corrupted;\n      return S_OK;\n    }\n  }\n  filled = true;\n  return S_OK;\n}\n\nHRESULT CArc::SkipExtendedHeaders(CExtendedInfo &extendedInfo)\n{\n  extendedInfo.Clear();\n  for (UInt32 i = 0;; i++)\n  {\n    bool filled;\n    RINOK(ReadBlock(filled, &extendedInfo))\n    if (!filled)\n      return S_OK;\n    if (Callback && (i & 0xFF) == 0)\n      RINOK(Callback->SetCompleted(&NumFiles, &Processed))\n  }\n}\n\nHRESULT CArc::Open()\n{\n  bool filled;\n  RINOK(ReadBlock(filled, NULL)) // (extendedInfo = NULL)\n  if (!filled)\n    return S_FALSE;\n  RINOK(Header.Parse(_block, _blockSize))\n  IsArc = true;\n  return SkipExtendedHeaders(ExtendedInfo);\n}\n\nHRESULT CArc::GetNextItem(CItem &item, bool &filled)\n{\n  RINOK(ReadBlock(filled, NULL)) // (extendedInfo = NULL)\n  if (!filled)\n    return S_OK;\n  filled = false;\n  if (item.Parse(_block, _blockSize) != S_OK)\n  {\n    Error = k_ErrorType_Corrupted;\n    return S_OK;\n  }\n  /*\n  UInt32 extraData;\n  if ((header.Flags & NFlags::kExtFile) != 0)\n    extraData = GetUi32(_block + pos);\n  */\n\n  RINOK(SkipExtendedHeaders(item.ExtendedInfo))\n  filled = true;\n  return S_OK;\n}\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  CObjectVector<CItem> _items;\n  CMyComPtr<IInStream> _stream;\n  UInt64 _phySize;\n  CArc _arc;\n\n  HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *callback);\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidName,\n  kpidCTime,\n  kpidMTime,\n  kpidHostOS,\n  kpidComment,\n  kpidCharacts\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPosition,\n  kpidPackSize,\n  kpidMTime,\n  kpidAttrib,\n  kpidEncrypted,\n  kpidCRC,\n  kpidMethod,\n  kpidHostOS,\n  kpidComment,\n  kpidCharacts\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic void SetTime(UInt32 dosTime, NCOM::CPropVariant &prop)\n{\n  if (dosTime == 0)\n    return;\n  PropVariant_SetFrom_DosTime(prop, dosTime);\n}\n\nstatic void SetHostOS(Byte hostOS, NCOM::CPropVariant &prop)\n{\n  TYPE_TO_PROP(kHostOS, hostOS, prop);\n}\n\nstatic void SetUnicodeString(const AString &s, NCOM::CPropVariant &prop)\n{\n  if (!s.IsEmpty())\n    prop = MultiByteToUnicodeString(s, CP_OEMCP);\n}\n \nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _phySize; break;\n    case kpidName: SetUnicodeString(_arc.Header.Name, prop); break;\n    case kpidCTime: SetTime(_arc.Header.CTime, prop); break;\n    case kpidMTime: SetTime(_arc.Header.MTime, prop); break;\n    case kpidHostOS: SetHostOS(_arc.Header.HostOS, prop); break;\n    case kpidComment: SetUnicodeString(_arc.Header.Comment, prop); break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_arc.IsArc) v |= kpv_ErrorFlags_IsNotArc;\n      switch (_arc.Error)\n      {\n        case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break;\n        case k_ErrorType_Corrupted: v |= kpv_ErrorFlags_HeadersError; break;\n        case k_ErrorType_OK:\n        // default:\n          break;\n      }\n      prop = v;\n      break;\n    }\n    case kpidCharacts: _arc.ExtendedInfo.ParseToPropVar(prop); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  const CItem &item = _items[index];\n  switch (propID)\n  {\n    case kpidPath:  prop = NItemName::GetOsPath(MultiByteToUnicodeString(item.Name, CP_OEMCP)); break;\n    case kpidIsDir:  prop = item.IsDir(); break;\n    case kpidSize:  prop = item.Size; break;\n    case kpidPackSize:  prop = item.PackSize; break;\n    case kpidPosition:  if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break;\n    case kpidAttrib:  prop = item.GetWinAttrib(); break;\n    case kpidEncrypted:  prop = item.IsEncrypted(); break;\n    case kpidCRC:  prop = item.FileCRC; break;\n    case kpidMethod:  prop = item.Method; break;\n    case kpidHostOS:  SetHostOS(item.HostOS, prop); break;\n    case kpidMTime:  SetTime(item.MTime, prop); break;\n    case kpidComment:  SetUnicodeString(item.Comment, prop); break;\n    case kpidCharacts: item.ExtendedInfo.ParseToPropVar(prop); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nHRESULT CHandler::Open2(IInStream *inStream, IArchiveOpenCallback *callback)\n{\n  Close();\n  \n  UInt64 endPos;\n  RINOK(InStream_AtBegin_GetSize(inStream, endPos))\n  \n  _arc.Stream = inStream;\n  _arc.Callback = callback;\n  _arc.NumFiles = 0;\n  _arc.Processed = 0;\n\n  RINOK(_arc.Open())\n\n  _phySize = _arc.Processed;\n  if (_arc.Header.ArchiveSize != 0)\n    _phySize = (UInt64)_arc.Header.ArchiveSize + _arc.Header.SecurSize;\n\n  for (;;)\n  {\n    CItem item;\n    bool filled;\n\n    _arc.Error = k_ErrorType_OK;\n    RINOK(_arc.GetNextItem(item, filled))\n\n    if (_arc.Error != k_ErrorType_OK)\n      break;\n    \n    if (!filled)\n    {\n      if (_arc.Error == k_ErrorType_OK)\n        if (_arc.Header.ArchiveSize == 0)\n          _phySize = _arc.Processed;\n      break;\n    }\n    item.DataPosition = _arc.Processed;\n    _items.Add(item);\n    \n    UInt64 pos = item.DataPosition + item.PackSize;\n    if (_arc.Header.ArchiveSize == 0)\n      _phySize = pos;\n    if (pos > endPos)\n    {\n      _arc.Error = k_ErrorType_UnexpectedEnd;\n      break;\n    }\n\n    RINOK(InStream_SeekSet(inStream, pos))\n    _arc.NumFiles = _items.Size();\n    _arc.Processed = pos;\n    \n    if (callback && (_items.Size() & 0xFF) == 0)\n    {\n      RINOK(callback->SetCompleted(&_arc.NumFiles, &_arc.Processed))\n    }\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  HRESULT res;\n  {\n    res = Open2(inStream, callback);\n    if (res == S_OK)\n    {\n      _stream = inStream;\n      return S_OK;\n    }\n  }\n  return res;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _arc.Close();\n  _phySize = 0;\n  _items.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  UInt64 totalUnpacked = 0, totalPacked = 0;\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const CItem &item = _items[allFilesMode ? i : indices[i]];\n    totalUnpacked += item.Size;\n    // totalPacked += item.PackSize;\n  }\n  RINOK(extractCallback->SetTotal(totalUnpacked))\n\n  totalUnpacked = totalPacked = 0;\n  UInt32 curUnpacked, curPacked;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;\n  CMyUniquePtr<NCompress::NArj::NDecoder::CCoder> arjDecoder;\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_stream);\n\n  for (i = 0;; i++,\n      totalUnpacked += curUnpacked,\n      totalPacked += curPacked)\n  {\n    lps->InSize = totalPacked;\n    lps->OutSize = totalUnpacked;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    curUnpacked = curPacked = 0;\n\n    Int32 opRes;\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      const Int32 askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      const UInt32 index = allFilesMode ? i : indices[i];\n      const CItem &item = _items[index];\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n        \n      if (item.IsDir())\n      {\n        // if (!testMode)\n        {\n          RINOK(extractCallback->PrepareOperation(askMode))\n          // realOutStream.Release();\n          RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        }\n        continue;\n      }\n      \n      if (!testMode && !realOutStream)\n        continue;\n      \n      RINOK(extractCallback->PrepareOperation(askMode))\n      curUnpacked = item.Size;\n      curPacked = item.PackSize;\n\n      CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;\n      outStream->SetStream(realOutStream);\n      // realOutStream.Release();\n      outStream->Init();\n  \n      inStream->Init(item.PackSize);\n      \n      RINOK(InStream_SeekSet(_stream, item.DataPosition))\n\n      HRESULT result = S_OK;\n      opRes = NExtract::NOperationResult::kOK;\n\n      if (item.IsEncrypted())\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      else\n      {\n        switch (item.Method)\n        {\n          case NCompressionMethod::kStored:\n          {\n            result = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);\n            if (result == S_OK && copyCoder->TotalSize != item.PackSize)\n              result = S_FALSE;\n            break;\n          }\n          case NCompressionMethod::kCompressed1a:\n          case NCompressionMethod::kCompressed1b:\n          case NCompressionMethod::kCompressed1c:\n          {\n            lzhDecoder.Create_if_Empty();\n            // lzhDecoder->FinishMode = true;\n            const UInt32 kHistorySize = 26624;\n            lzhDecoder->SetDictSize(kHistorySize);\n            result = lzhDecoder->Code(inStream, outStream, curUnpacked, lps);\n            if (result == S_OK && lzhDecoder->GetInputProcessedSize() != item.PackSize)\n              result = S_FALSE;\n            break;\n          }\n          case NCompressionMethod::kCompressed2:\n          {\n            arjDecoder.Create_if_Empty();\n            // arjDecoderSpec->FinishMode = true;\n            result = arjDecoder->Code(inStream, outStream, curUnpacked, lps);\n            if (result == S_OK && arjDecoder->GetInputProcessedSize() != item.PackSize)\n              result = S_FALSE;\n            break;\n          }\n          default:\n            opRes = NExtract::NOperationResult::kUnsupportedMethod;\n        }\n      }\n      \n      if (opRes == NExtract::NOperationResult::kOK)\n      {\n        if (result == S_FALSE)\n          opRes = NExtract::NOperationResult::kDataError;\n        else\n        {\n          RINOK(result)\n          opRes = (outStream->GetCRC() == item.FileCRC) ?\n              NExtract::NOperationResult::kOK:\n              NExtract::NOperationResult::kCRCError;\n        }\n      }\n    }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  \n  return S_OK;\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = { kSig0, kSig1 };\n\nREGISTER_ARC_I(\n  \"Arj\", \"arj\", NULL, 4,\n  k_Signature,\n  0,\n  0,\n  IsArc_Arj)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/AvbHandler.cpp",
    "content": "﻿// AvbHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get32(p) GetBe32(p)\n#define Get64(p) GetBe64(p)\n\n#define G32(_offs_, dest) dest = Get32(p + (_offs_))\n#define G64(_offs_, dest) dest = Get64(p + (_offs_))\n\nusing namespace NWindows;\n\nnamespace NArchive {\n\nnamespace NExt {\nAPI_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize);\n}\n\nnamespace NAvb {\n\nstatic void AddNameToString(AString &s, const Byte *name, unsigned size, bool strictConvert)\n{\n  for (unsigned i = 0; i < size; i++)\n  {\n    Byte c = name[i];\n    if (c == 0)\n      return;\n    if (strictConvert && c < 32)\n      c = '_';\n    s += (char)c;\n  }\n}\n\n/* Maximum size of a vbmeta image - 64 KiB. */\n#define VBMETA_MAX_SIZE (64 * 1024)\n\n#define SIGNATURE { 'A', 'V', 'B', 'f', 0, 0, 0, 1 }\n  \nstatic const unsigned k_SignatureSize = 8;\nstatic const Byte k_Signature[k_SignatureSize] = SIGNATURE;\n\n// #define AVB_FOOTER_MAGIC \"AVBf\"\n// #define AVB_FOOTER_MAGIC_LEN 4\n/* The current footer version used - keep in sync with avbtool. */\n#define AVB_FOOTER_VERSION_MAJOR 1\n\n/* The struct used as a footer used on partitions, used to find the\n * AvbVBMetaImageHeader struct. This struct is always stored at the\n * end of a partition.\n */\n// #define AVB_FOOTER_SIZE 64\nstatic const unsigned kFooterSize = 64;\n\nstruct CFooter\n{\n  /*   0: Four bytes equal to \"AVBf\" (AVB_FOOTER_MAGIC). */\n  // Byte magic[AVB_FOOTER_MAGIC_LEN];\n  /*   4: The major version of the footer struct. */\n  UInt32 version_major;\n  /*   8: The minor version of the footer struct. */\n  UInt32 version_minor;\n\n  /*  12: The original size of the image on the partition. */\n  UInt64 original_image_size;\n\n  /*  20: The offset of the |AvbVBMetaImageHeader| struct. */\n  UInt64 vbmeta_offset;\n\n  /*  28: The size of the vbmeta block (header + auth + aux blocks). */\n  UInt64 vbmeta_size;\n\n  /*  36: Padding to ensure struct is size AVB_FOOTER_SIZE bytes. This\n   * must be set to zeroes.\n   */\n  Byte reserved[28];\n\n  void Parse(const Byte *p)\n  {\n    G32 (4, version_major);\n    G32 (8, version_minor);\n    G64 (12, original_image_size);\n    G64 (20, vbmeta_offset);\n    G64 (28, vbmeta_size);\n  }\n};\n\n\n/* Size of the vbmeta image header. */\n#define AVB_VBMETA_IMAGE_HEADER_SIZE 256\n\n/* Magic for the vbmeta image header. */\n// #define AVB_MAGIC \"AVB0\"\n// #define AVB_MAGIC_LEN 4\n/* Maximum size of the release string including the terminating NUL byte. */\n#define AVB_RELEASE_STRING_SIZE 48\n\nstruct AvbVBMetaImageHeader\n{\n  /*   0: Four bytes equal to \"AVB0\" (AVB_MAGIC). */\n  // Byte magic[AVB_MAGIC_LEN];\n\n  /*   4: The major version of libavb required for this header. */\n  UInt32 required_libavb_version_major;\n  /*   8: The minor version of libavb required for this header. */\n  UInt32 required_libavb_version_minor;\n\n  /*  12: The size of the signature block. */\n  UInt64 authentication_data_block_size;\n  /*  20: The size of the auxiliary data block. */\n  UInt64 auxiliary_data_block_size;\n\n  /*  28: The verification algorithm used, see |AvbAlgorithmType| enum. */\n  UInt32 algorithm_type;\n\n  /*  32: Offset into the \"Authentication data\" block of hash data. */\n  UInt64 hash_offset;\n  /*  40: Length of the hash data. */\n  UInt64 hash_size;\n\n  /*  48: Offset into the \"Authentication data\" block of signature data. */\n  UInt64 signature_offset;\n  /*  56: Length of the signature data. */\n  UInt64 signature_size;\n\n  /*  64: Offset into the \"Auxiliary data\" block of public key data. */\n  UInt64 public_key_offset;\n  /*  72: Length of the public key data. */\n  UInt64 public_key_size;\n\n  /*  80: Offset into the \"Auxiliary data\" block of public key metadata. */\n  UInt64 public_key_metadata_offset;\n  /*  88: Length of the public key metadata. Must be set to zero if there\n   *  is no public key metadata.\n   */\n  UInt64 public_key_metadata_size;\n\n  /*  96: Offset into the \"Auxiliary data\" block of descriptor data. */\n  UInt64 descriptors_offset;\n  /* 104: Length of descriptor data. */\n  UInt64 descriptors_size;\n\n  /* 112: The rollback index which can be used to prevent rollback to\n   *  older versions.\n   */\n  UInt64 rollback_index;\n\n  /* 120: Flags from the AvbVBMetaImageFlags enumeration. This must be\n   * set to zero if the vbmeta image is not a top-level image.\n   */\n  UInt32 flags;\n\n  /* 124: The location of the rollback index defined in this header.\n   * Only valid for the main vbmeta. For chained partitions, the rollback\n   * index location must be specified in the AvbChainPartitionDescriptor\n   * and this value must be set to 0.\n   */\n  UInt32 rollback_index_location;\n\n  /* 128: The release string from avbtool, e.g. \"avbtool 1.0.0\" or\n   * \"avbtool 1.0.0 xyz_board Git-234abde89\". Is guaranteed to be NUL\n   * terminated. Applications must not make assumptions about how this\n   * string is formatted.\n   */\n  Byte release_string[AVB_RELEASE_STRING_SIZE];\n\n  /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE\n   * bytes. This must be set to zeroes.\n   */\n  // Byte reserved[80];\n  bool Parse(const Byte *p);\n};\n\nbool AvbVBMetaImageHeader::Parse(const Byte *p)\n{\n  // Byte magic[AVB_MAGIC_LEN];\n  if (Get32(p) != 0x41564230) // \"AVB0\"\n    return false;\n  G32 (4, required_libavb_version_major);\n  if (required_libavb_version_major != AVB_FOOTER_VERSION_MAJOR) // \"AVB0\"\n    return false;\n  G32 (8, required_libavb_version_minor);\n  G64 (12, authentication_data_block_size);\n  G64 (20, auxiliary_data_block_size);\n  G32 (28, algorithm_type);\n  G64 (32, hash_offset);\n  G64 (40, hash_size);\n  G64 (48, signature_offset);\n  G64 (56, signature_size);\n  G64 (64, public_key_offset);\n  G64 (72, public_key_size);\n  G64 (80, public_key_metadata_offset);\n  G64 (88, public_key_metadata_size);\n  G64 (96, descriptors_offset);\n  G64 (104, descriptors_size);\n  G64 (112, rollback_index);\n  G32 (120, flags);\n  G32 (124, rollback_index_location);\n  memcpy(release_string, p + 128, AVB_RELEASE_STRING_SIZE);\n\n  /* 176: Padding to ensure struct is size AVB_VBMETA_IMAGE_HEADER_SIZE\n   * bytes. This must be set to zeroes.\n   */\n  // Byte reserved[80];\n  return true;\n}\n\n\nstatic const unsigned k_Descriptor_Size = 16;\n\nenum AvbDescriptorTag\n{\n  AVB_DESCRIPTOR_TAG_PROPERTY,\n  AVB_DESCRIPTOR_TAG_HASHTREE,\n  AVB_DESCRIPTOR_TAG_HASH,\n  AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE,\n  AVB_DESCRIPTOR_TAG_CHAIN_PARTITION\n};\n\nstruct AvbDescriptor\n{\n  UInt64 Tag;\n  UInt64 Size;\n\n  void Parse(const Byte *p)\n  {\n    G64 (0, Tag);\n    G64 (8, Size);\n  }\n};\n\n\nenum AvbHashtreeDescriptorFlags\n{\n  AVB_HASHTREE_DESCRIPTOR_FLAGS_DO_NOT_USE_AB = (1 << 0),\n  AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE = (1 << 1)\n};\n\n/* A descriptor containing information about a dm-verity hashtree.\n *\n * Hash-trees are used to verify large partitions typically containing\n * file systems. See\n * https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity for more\n * information about dm-verity.\n *\n * Following this struct are |partition_name_len| bytes of the\n * partition name (UTF-8 encoded), |salt_len| bytes of salt, and then\n * |root_digest_len| bytes of the root digest.\n *\n * The |reserved| field is for future expansion and must be set to NUL\n * bytes.\n *\n * Changes in v1.1:\n *   - flags field is added which supports AVB_HASHTREE_DESCRIPTOR_FLAGS_USE_AB\n *   - digest_len may be zero, which indicates the use of a persistent digest\n */\n\nstatic const unsigned k_Hashtree_Size_Min = 164;\n\nstruct AvbHashtreeDescriptor\n{\n  UInt32 dm_verity_version;\n  UInt64 image_size;\n  UInt64 tree_offset;\n  UInt64 tree_size;\n  UInt32 data_block_size;\n  UInt32 hash_block_size;\n  UInt32 fec_num_roots;\n  UInt64 fec_offset;\n  UInt64 fec_size;\n  Byte hash_algorithm[32];\n  UInt32 partition_name_len;\n  UInt32 salt_len;\n  UInt32 root_digest_len;\n  UInt32 flags;\n  Byte reserved[60];\n  void Parse(const Byte *p)\n  {\n    G32 (0, dm_verity_version);\n    G64 (4, image_size);\n    G64 (12, tree_offset);\n    G64 (20, tree_size);\n    G32 (28, data_block_size);\n    G32 (32, hash_block_size);\n    G32 (36, fec_num_roots);\n    G64 (40, fec_offset);\n    G64 (48, fec_size);\n    memcpy(hash_algorithm, p + 56, 32);\n    G32 (88, partition_name_len);\n    G32 (92, salt_len);\n    G32 (96, root_digest_len);\n    G32 (100, flags);\n  }\n};\n\nstatic const unsigned k_PropertyDescriptor_Size_Min = 16;\n\nstruct AvbPropertyDescriptor\n{\n  UInt64 key_num_bytes;\n  UInt64 value_num_bytes;\n  \n  void Parse(const Byte *p)\n  {\n    G64 (0, key_num_bytes);\n    G64 (8, value_num_bytes);\n  }\n};\n\nZ7_class_CHandler_final: public CHandlerCont\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Cont)\n\n  // UInt64 _startOffset;\n  UInt64 _phySize;\n\n  CFooter Footer;\n  AString Name;\n  const char *Ext;\n\n  HRESULT Open2(IInStream *stream);\n\n  virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override\n  {\n    if (index != 0)\n      return NExtract::NOperationResult::kUnavailable;\n    // pos = _startOffset;\n    pos = 0;\n    size = Footer.original_image_size;\n    return NExtract::NOperationResult::kOK;\n  }\n};\n\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  UInt64 fileSize;\n  {\n    Byte buf[kFooterSize];\n    RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))\n    if (fileSize < kFooterSize)\n      return S_FALSE;\n    RINOK(InStream_SeekSet(stream, fileSize - kFooterSize))\n    RINOK(ReadStream_FALSE(stream, buf, kFooterSize))\n    if (memcmp(buf, k_Signature, k_SignatureSize) != 0)\n      return S_FALSE;\n    Footer.Parse(buf);\n    if (Footer.vbmeta_size > VBMETA_MAX_SIZE ||\n        Footer.vbmeta_size < AVB_VBMETA_IMAGE_HEADER_SIZE)\n      return S_FALSE;\n    for (unsigned i = 36; i < kFooterSize; i++)\n      if (buf[i] != 0)\n        return S_FALSE;\n  }\n  {\n    CByteBuffer buf;\n    buf.Alloc((size_t)Footer.vbmeta_size);\n    RINOK(InStream_SeekSet(stream, Footer.vbmeta_offset))\n    RINOK(ReadStream_FALSE(stream, buf, (size_t)Footer.vbmeta_size))\n\n    AvbVBMetaImageHeader meta;\n    if (!meta.Parse(buf))\n      return S_FALSE;\n\n    unsigned offset = (unsigned)AVB_VBMETA_IMAGE_HEADER_SIZE;\n    unsigned rem = (unsigned)(Footer.vbmeta_size - offset);\n    \n    if (meta.authentication_data_block_size != 0)\n    {\n      if (rem < meta.authentication_data_block_size)\n        return S_FALSE;\n      const unsigned u = (unsigned)meta.authentication_data_block_size;\n      offset += u;\n      rem -= u;\n    }\n\n    if (rem < meta.descriptors_offset ||\n        rem - meta.descriptors_offset < meta.descriptors_size)\n      return S_FALSE;\n    rem = (unsigned)meta.descriptors_size;\n    while (rem != 0)\n    {\n      if (rem < k_Descriptor_Size)\n        return S_FALSE;\n      AvbDescriptor desc;\n      desc.Parse(buf + offset);\n      offset += k_Descriptor_Size;\n      rem -= k_Descriptor_Size;\n      if (desc.Size > rem)\n        return S_FALSE;\n      const unsigned descSize = (unsigned)desc.Size;\n      if (desc.Tag == AVB_DESCRIPTOR_TAG_HASHTREE)\n      {\n        if (descSize < k_Hashtree_Size_Min)\n          return S_FALSE;\n        AvbHashtreeDescriptor ht;\n        ht.Parse(buf + offset);\n        unsigned pos = k_Hashtree_Size_Min;\n\n        if (pos + ht.partition_name_len > descSize)\n          return S_FALSE;\n        Name.Empty(); // UTF-8\n        AddNameToString(Name, buf + offset + pos, ht.partition_name_len, false);\n        pos += ht.partition_name_len;\n        \n        if (pos + ht.salt_len > descSize)\n          return S_FALSE;\n        CByteBuffer salt;\n        salt.CopyFrom(buf + offset + pos, ht.salt_len);\n        pos += ht.salt_len;\n        \n        if (pos + ht.root_digest_len > descSize)\n          return S_FALSE;\n        CByteBuffer digest;\n        digest.CopyFrom(buf + offset + pos, ht.root_digest_len);\n        pos += ht.root_digest_len;\n        // what is that digest?\n      }\n      else if (desc.Tag == AVB_DESCRIPTOR_TAG_PROPERTY)\n      {\n        if (descSize < k_PropertyDescriptor_Size_Min + 2)\n          return S_FALSE;\n        AvbPropertyDescriptor pt;\n        pt.Parse(buf + offset);\n        unsigned pos = k_PropertyDescriptor_Size_Min;\n        \n        if (pt.key_num_bytes > descSize - pos - 1)\n          return S_FALSE;\n        AString key; // UTF-8\n        AddNameToString(key, buf + offset + pos, (unsigned)pt.key_num_bytes, false);\n        pos += (unsigned)pt.key_num_bytes + 1;\n\n        if (descSize < pos)\n          return S_FALSE;\n        if (pt.value_num_bytes > descSize - pos - 1)\n          return S_FALSE;\n        AString value; // UTF-8\n        AddNameToString(value, buf + offset + pos, (unsigned)pt.value_num_bytes, false);\n        pos += (unsigned)pt.value_num_bytes + 1;\n      }\n      offset += descSize;\n      rem -= descSize;\n    }\n\n    _phySize = fileSize;\n\n    // _startOffset = 0;\n    return S_OK;\n  }\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  try\n  {\n    if (Open2(stream) != S_OK)\n      return S_FALSE;\n    _stream = stream;\n\n    {\n      CMyComPtr<ISequentialInStream> parseStream;\n      if (GetStream(0, &parseStream) == S_OK && parseStream)\n      {\n        const size_t kParseSize = 1 << 11;\n        Byte buf[kParseSize];\n        if (ReadStream_FAIL(parseStream, buf, kParseSize) == S_OK)\n        {\n          UInt64 extSize;\n          if (NExt::IsArc_Ext_PhySize(buf, kParseSize, &extSize) == k_IsArc_Res_YES)\n            if (extSize == Footer.original_image_size)\n              Ext = \"ext\";\n        }\n      }\n    }\n  }\n  catch(...) { return S_FALSE; }\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _stream.Release();\n  // _startOffset = 0;\n  _phySize = 0;\n  Ext = NULL;\n  Name.Empty();\n  return S_OK;\n}\n\n\nstatic const Byte kArcProps[] =\n{\n  kpidName\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize,\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidPhySize: prop = _phySize; break;\n    case kpidName:\n    {\n      if (!Name.IsEmpty())\n      {\n        AString s (Name);\n        s += \".avb\";\n        prop = s;\n      }\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      if (!Name.IsEmpty())\n      {\n        AString s (Name);\n        s += '.';\n        s += Ext ? Ext : \"img\";\n        prop = s;\n      }\n      break;\n    }\n    case kpidPackSize:\n    case kpidSize:\n      prop = Footer.original_image_size;\n      break;\n    case kpidExtension: prop = (Ext ? Ext : \"img\"); break;\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\n\nREGISTER_ARC_I_NO_SIG(\n  \"AVB\", \"avb img\", NULL, 0xc0,\n  /* k_Signature, */\n  0,\n  /* NArcInfoFlags::kUseGlobalOffset | */\n  NArcInfoFlags::kBackwardOpen\n  ,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Base64Handler.cpp",
    "content": "﻿// Base64Handler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyVector.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n#include \"../Common/InBuffer.h\"\n\n/*\nspaces:\n  9(TAB),10(LF),13(CR),32(SPACE)\n  Non-breaking space:\n    0xa0 : Unicode, Windows code pages 1250-1258\n    0xff (unused): DOS code pages\n\nend of stream markers: '=' (0x3d):\n  \"=\"  , if numBytes (% 3 == 2)\n  \"==\" , if numBytes (% 3 == 1)\n*/\n\n\nstatic const Byte k_Base64Table[256] =\n{\n  66,77,77,77,77,77,77,77,77,65,65,77,77,65,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  65,77,77,77,77,77,77,77,77,77,77,62,77,77,77,63,\n  52,53,54,55,56,57,58,59,60,61,77,77,77,64,77,77,\n  77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,\n  15,16,17,18,19,20,21,22,23,24,25,77,77,77,77,77,\n  77,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,\n  41,42,43,44,45,46,47,48,49,50,51,77,77,77,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  65,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,\n  77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77\n};\n\nstatic const unsigned k_Code_Equals = 64;\nstatic const unsigned k_Code_Space = 65;\nstatic const unsigned k_Code_Zero = 66;\n\nAPI_FUNC_static_IsArc IsArc_Base64(const Byte *p, size_t size)\n{\n  size_t num = 0;\n  size_t firstSpace = 0;\n\n  for (;;)\n  {\n    if (size == 0)\n      return k_IsArc_Res_NEED_MORE;\n    UInt32 c = k_Base64Table[(Byte)(*p++)];\n    size--;\n    if (c < 64)\n    {\n      num++;\n      continue;\n    }\n\n    if (c == k_Code_Space)\n    {\n      if (p[-1] == ' ' && firstSpace == 0)\n        firstSpace = num;\n      continue;\n    }\n\n    if (c != k_Code_Equals)\n      return k_IsArc_Res_NO;\n    break;\n  }\n\n  {\n    // we try to redece false positive detection here.\n    // we don't expect space character in starting base64 line\n    const unsigned kNumExpectedNonSpaceSyms = 20;\n    if (firstSpace != 0 && firstSpace < num && firstSpace < kNumExpectedNonSpaceSyms)\n      return k_IsArc_Res_NO;\n  }\n\n  num &= 3;\n\n  if (num <= 1)\n    return k_IsArc_Res_NO;\n  if (num != 3)\n  {\n    if (size == 0)\n      return k_IsArc_Res_NEED_MORE;\n    UInt32 c = k_Base64Table[(Byte)(*p++)];\n    size--;\n    if (c != k_Code_Equals)\n      return k_IsArc_Res_NO;\n  }\n\n  for (;;)\n  {\n    if (size == 0)\n      return k_IsArc_Res_YES;\n    UInt32 c = k_Base64Table[(Byte)(*p++)];\n    size--;\n    if (c == k_Code_Space)\n      continue;\n    return k_IsArc_Res_NO;\n  }\n}\n}\n\n\nenum EBase64Res\n{\n  k_Base64_RES_MaybeFinished,\n  k_Base64_RES_Finished,\n  k_Base64_RES_NeedMoreInput,\n  k_Base64_RES_UnexpectedChar\n};\n\n\nstatic EBase64Res Base64ToBin(Byte *p, size_t size, const Byte **srcEnd, Byte **destEnd)\n{\n  Byte *dest = p;\n  UInt32 val = 1;\n  EBase64Res res = k_Base64_RES_NeedMoreInput;\n  \n  for (;;)\n  {\n    if (size == 0)\n    {\n      if (val == 1)\n        res = k_Base64_RES_MaybeFinished;\n      break;\n    }\n    UInt32 c = k_Base64Table[(Byte)(*p++)];\n    size--;\n    if (c < 64)\n    {\n      val = (val << 6) | c;\n      if ((val & ((UInt32)1 << 24)) == 0)\n        continue;\n      dest[0] = (Byte)(val >> 16);\n      dest[1] = (Byte)(val >> 8);\n      dest[2] = (Byte)(val);\n      dest += 3;\n      val = 1;\n      continue;\n    }\n\n    if (c == k_Code_Space)\n      continue;\n    \n    if (c == k_Code_Equals)\n    {\n      if (val >= (1 << 12))\n      {\n        if (val & (1 << 18))\n        {\n          res = k_Base64_RES_Finished;\n          break;\n        }\n        if (size == 0)\n          break;\n        c = k_Base64Table[(Byte)(*p++)];\n        size--;\n        if (c == k_Code_Equals)\n        {\n          res = k_Base64_RES_Finished;\n          break;\n        }\n      }\n    }\n\n    p--;\n    res = k_Base64_RES_UnexpectedChar;\n    break;\n  }\n\n  if (val >= ((UInt32)1 << 12))\n  {\n    if (val & (1 << 18))\n    {\n      *dest++ = (Byte)(val >> 10);\n      val <<= 2;\n    }\n    *dest++ = (Byte)(val >> 4);\n  }\n  \n  *srcEnd = p;\n  *destEnd = dest;\n  return res;\n}\n\n\nstatic const Byte *Base64_SkipSpaces(const Byte *p, size_t size)\n{\n  for (;;)\n  {\n    if (size == 0)\n      return p;\n    const UInt32 c = k_Base64Table[(Byte)(*p++)];\n    size--;\n    if (c == k_Code_Space)\n      continue;\n    return p - 1;\n  }\n}\n\n\n// the following function is used by DmgHandler.cpp\n\nByte *Base64ToBin(Byte *dest, const char *src);\nByte *Base64ToBin(Byte *dest, const char *src)\n{\n  UInt32 val = 1;\n  \n  for (;;)\n  {\n    const UInt32 c = k_Base64Table[(Byte)(*src++)];\n\n    if (c < 64)\n    {\n      val = (val << 6) | c;\n      if ((val & ((UInt32)1 << 24)) == 0)\n        continue;\n      dest[0] = (Byte)(val >> 16);\n      dest[1] = (Byte)(val >> 8);\n      dest[2] = (Byte)(val);\n      dest += 3;\n      val = 1;\n      continue;\n    }\n    \n    if (c == k_Code_Space)\n      continue;\n    \n    if (c == k_Code_Equals)\n      break;\n    \n    if (c == k_Code_Zero && val == 1) // end of string\n      return dest;\n    \n    return NULL;\n  }\n\n  if (val < (1 << 12))\n    return NULL;\n\n  if (val & (1 << 18))\n  {\n    *dest++ = (Byte)(val >> 10);\n    val <<= 2;\n  }\n  else if (k_Base64Table[(Byte)(*src++)] != k_Code_Equals)\n    return NULL;\n  *dest++ = (Byte)(val >> 4);\n\n  for (;;)\n  {\n    const Byte c = k_Base64Table[(Byte)(*src++)];\n    if (c == k_Code_Space)\n      continue;\n    if (c == k_Code_Zero)\n      return dest;\n    return NULL;\n  }\n}\n\n\nnamespace NArchive {\nnamespace NBase64 {\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  bool _isArc;\n  UInt64 _phySize;\n  size_t _size;\n  EBase64Res _sres;\n  CByteBuffer _data;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize,\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_phySize != 0) prop = _phySize; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_sres == k_Base64_RES_NeedMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  // COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidSize: prop = (UInt64)_size; break;\n    case kpidPackSize: prop = _phySize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  // COM_TRY_END\n}\n\n\nstatic HRESULT ReadStream_OpenProgress(ISequentialInStream *stream, void *data, size_t size, IArchiveOpenCallback *openCallback) throw()\n{\n  UInt64 bytes = 0;\n  while (size != 0)\n  {\n    const UInt32 kBlockSize = ((UInt32)1 << 24);\n    const UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;\n    UInt32 processedSizeLoc;\n    RINOK(stream->Read(data, curSize, &processedSizeLoc))\n    if (processedSizeLoc == 0)\n      return E_FAIL;\n    data = (void *)((Byte *)data + processedSizeLoc);\n    size -= processedSizeLoc;\n    bytes += processedSizeLoc;\n    const UInt64 files = 1;\n    RINOK(openCallback->SetCompleted(&files, &bytes))\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    {\n      const unsigned kStartSize = 1 << 12;\n      _data.Alloc(kStartSize);\n      size_t size = kStartSize;\n      RINOK(ReadStream(stream, _data, &size))\n      if (IsArc_Base64(_data, size) == k_IsArc_Res_NO)\n        return S_FALSE;\n    }\n    _isArc = true;\n\n    UInt64 packSize64;\n    RINOK(InStream_GetSize_SeekToEnd(stream, packSize64))\n    if (packSize64 == 0)\n      return S_FALSE;\n    size_t curSize = 1 << 16;\n    if (curSize > packSize64)\n      curSize = (size_t)packSize64;\n    const unsigned kLogStep = 4;\n\n    for (;;)\n    {\n      RINOK(InStream_SeekSet(stream, 0))\n      \n      _data.Alloc(curSize);\n      RINOK(ReadStream_OpenProgress(stream, _data, curSize, openCallback))\n      \n      const Byte *srcEnd;\n      Byte *dest;\n      _sres = Base64ToBin(_data, curSize, &srcEnd, &dest);\n      _size = (size_t)(dest - _data);\n      const size_t mainSize = (size_t)(srcEnd - _data);\n      _phySize = mainSize;\n      if (_sres == k_Base64_RES_UnexpectedChar)\n        break;\n      if (curSize != mainSize)\n      {\n        const Byte *end2 = Base64_SkipSpaces(srcEnd, curSize - mainSize);\n        if ((size_t)(end2 - _data) != curSize)\n          break;\n        _phySize = curSize;\n      }\n\n      if (curSize == packSize64)\n        break;\n      \n      UInt64 curSize64 = packSize64;\n      if (curSize < (packSize64 >> kLogStep))\n        curSize64 = (UInt64)curSize << kLogStep;\n      curSize = (size_t)curSize64;\n      if (curSize != curSize64)\n        return E_OUTOFMEMORY;\n    }\n    if (_size == 0)\n      return S_FALSE;\n    return S_OK;\n  }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _phySize = 0;\n  _size = 0;\n  _isArc = false;\n  _sres = k_Base64_RES_MaybeFinished;\n  _data.Free();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  RINOK(extractCallback->SetTotal(_size))\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  // RINOK(lps->SetCur())\n  Int32 opRes;\n  {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n    if (!testMode && !realOutStream)\n      return S_OK;\n    RINOK(extractCallback->PrepareOperation(askMode))\n    if (realOutStream)\n    {\n      RINOK(WriteStream(realOutStream, (const Byte *)_data, _size))\n    }\n    opRes = NExtract::NOperationResult::kOK;\n    if (_sres != k_Base64_RES_Finished)\n    {\n      if (_sres == k_Base64_RES_NeedMoreInput)\n        opRes = NExtract::NOperationResult::kUnexpectedEnd;\n      else if (_sres == k_Base64_RES_UnexpectedChar)\n        opRes = NExtract::NOperationResult::kDataError;\n    }\n  }\n  RINOK(extractCallback->SetOperationResult(opRes))\n  lps->InSize = _phySize;\n  lps->OutSize = _size;\n  return lps->SetCur();\n  COM_TRY_END\n}\n\nREGISTER_ARC_I_NO_SIG(\n  \"Base64\", \"b64\", NULL, 0xC5,\n  0,\n    NArcInfoFlags::kKeepName\n  | NArcInfoFlags::kStartOpen\n  | NArcInfoFlags::kByExtOnlyOpen,\n  IsArc_Base64)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Bz2Handler.cpp",
    "content": "﻿// Bz2Handler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/BZip2Decoder.h\"\n#include \"../Compress/BZip2Encoder.h\"\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/DummyOutStream.h\"\n#include \"Common/HandlerOut.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NBz2 {\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n  IArchiveOpenSeq,\n  IOutArchive,\n  ISetProperties\n)\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n  \n  bool _isArc;\n  bool _needSeekToStart;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n  bool _numStreams_Defined;\n  bool _numBlocks_Defined;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize;\n  UInt64 _numStreams;\n  UInt64 _numBlocks;\n\n  CSingleMethodProps _props;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams,\n  kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n    case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;\n    case kpidNumBlocks: if (_numBlocks_Defined) prop = _numBlocks; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;\n      prop = v;\n      break;\n    }\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nstatic const unsigned kSignatureCheckSize = 10;\n\nAPI_FUNC_static_IsArc IsArc_BZip2(const Byte *p, size_t size)\n{\n  if (size < kSignatureCheckSize)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != 'B' || p[1] != 'Z' || p[2] != 'h' || p[3] < '1' || p[3] > '9')\n    return k_IsArc_Res_NO;\n  p += 4;\n  if (NCompress::NBZip2::IsBlockSig(p))\n    return k_IsArc_Res_YES;\n  if (NCompress::NBZip2::IsEndSig(p))\n    return k_IsArc_Res_YES;\n  return k_IsArc_Res_NO;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    Byte buf[kSignatureCheckSize];\n    RINOK(ReadStream_FALSE(stream, buf, kSignatureCheckSize))\n    if (IsArc_BZip2(buf, kSignatureCheckSize) == k_IsArc_Res_NO)\n      return S_FALSE;\n    _isArc = true;\n    _stream = stream;\n    _seqStream = stream;\n    _needSeekToStart = true;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _needSeekToStart = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n  _numStreams_Defined = false;\n  _numBlocks_Defined = false;\n\n  _packSize = 0;\n\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n  {\n    RINOK(extractCallback->SetTotal(_packSize))\n  }\n\n  Int32 opRes;\n {\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  if (_needSeekToStart)\n  {\n    if (!_stream)\n      return E_FAIL;\n    RINOK(InStream_SeekToBegin(_stream))\n  }\n  else\n    _needSeekToStart = true;\n\n  // try {\n\n  CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CDecoder> decoder;\n\n  #ifndef Z7_ST\n  RINOK(decoder->SetNumberOfThreads(_props._numThreads))\n  #endif\n\n  CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;\n  outStream->SetStream(realOutStream);\n  outStream->Init();\n  // realOutStream.Release();\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, true);\n\n  decoder->FinishMode = true;\n  decoder->Base.DecodeAllStreams = true;\n  \n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  HRESULT result = decoder.Interface()->Code(_seqStream, outStream, NULL, NULL, lps);\n  \n  if (result != S_FALSE && result != S_OK)\n    return result;\n  \n  if (decoder->Base.NumStreams == 0)\n  {\n    _isArc = false;\n    result = S_FALSE;\n  }\n  else\n  {\n    const UInt64 inProcessedSize = decoder->GetInputProcessedSize();\n    UInt64 packSize = inProcessedSize;\n\n    if (decoder->Base.NeedMoreInput)\n      _needMoreInput = true;\n    \n    if (!decoder->Base.IsBz)\n    {\n      packSize = decoder->Base.FinishedPackSize;\n      if (packSize != inProcessedSize)\n        _dataAfterEnd = true;\n    }\n\n    _packSize = packSize;\n    _unpackSize = decoder->GetOutProcessedSize();\n    _numStreams = decoder->Base.NumStreams;\n    _numBlocks = decoder->GetNumBlocks();\n\n    _packSize_Defined = true;\n    _unpackSize_Defined = true;\n    _numStreams_Defined = true;\n    _numBlocks_Defined = true;\n\n    // RINOK(\n    lps.Interface()->SetRatioInfo(&packSize, &_unpackSize);\n  }\n  \n  // outStream.Release();\n\n  if (!_isArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (decoder->GetCrcError())\n    opRes = NExtract::NOperationResult::kCRCError;\n  else if (_dataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (decoder->Base.MinorError)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK)\n    opRes = NExtract::NOperationResult::kOK;\n  else\n    return result;\n\n }\n  return extractCallback->SetOperationResult(opRes);\n\n  // } catch(...)  { return E_FAIL; }\n\n  COM_TRY_END\n}\n\n\n/*\nstatic HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)\n{\n  return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value);\n}\n\nstatic HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)\n{\n  return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value);\n}\n\nstatic HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,\n    const UInt64 *unpackSize,\n    const UInt64 *numBlocks)\n{\n  NCOM::CPropVariant sizeProp;\n  if (unpackSize)\n  {\n    sizeProp = *unpackSize;\n    RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp));\n    RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK));\n  }\n \n  if (unpackSize)\n  {\n    RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp));\n  }\n  if (numBlocks)\n  {\n    NCOM::CPropVariant prop;\n    prop = *numBlocks;\n    RINOK(ReportArcProp(reportArcProp, kpidNumBlocks, &prop));\n  }\n  return S_OK;\n}\n*/\n\nstatic HRESULT UpdateArchive(\n    UInt64 unpackSize,\n    ISequentialOutStream *outStream,\n    const CProps &props,\n    IArchiveUpdateCallback *updateCallback\n    // , ArchiveUpdateCallbackArcProp *reportArcProp\n    )\n{\n  {\n    CMyComPtr<ISequentialInStream> fileInStream;\n    RINOK(updateCallback->GetStream(0, &fileInStream))\n    if (!fileInStream)\n      return S_FALSE;\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          IStreamGetSize,\n          streamGetSize, fileInStream)\n      if (streamGetSize)\n      {\n        UInt64 size;\n        if (streamGetSize->GetSize(&size) == S_OK)\n          unpackSize = size;\n      }\n    }\n    RINOK(updateCallback->SetTotal(unpackSize))\n\n    CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n    lps->Init(updateCallback, true);\n    {\n      CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CEncoder> encoder;\n      RINOK(props.SetCoderProps(encoder.ClsPtr(), NULL))\n      RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))\n      /*\n      if (reportArcProp)\n      {\n        unpackSize = encoderSpec->GetInProcessedSize();\n        RINOK(ReportArcProps(reportArcProp, &unpackSize, &encoderSpec->NumBlocks));\n      }\n      */\n    }\n  }\n  return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))\n{\n  *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType;\n  // *timeType = NFileTimeType::kUnix;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IStreamSetRestriction,\n        setRestriction, outStream)\n    if (setRestriction)\n      RINOK(setRestriction->SetRestriction(0, 0))\n  }\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))\n \n  // Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp, reportArcProp, updateCallback)\n\n  if (IntToBool(newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n  \n  if (IntToBool(newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop))\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n\n    CMethodProps props2 = _props;\n#ifndef Z7_ST\n    props2.AddProp_NumThreads(_props._numThreads);\n#ifdef _WIN32\n    if (_props._numThreadGroups > 1)\n      props2.AddProp32(NCoderPropID::kNumThreadGroups, _props._numThreadGroups);\n#endif\n#endif\n\n    return UpdateArchive(size, outStream, props2, updateCallback);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(updateCallback, true);\n\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveUpdateCallbackFile,\n      opCallback, updateCallback)\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, 0,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  if (_stream)\n    RINOK(InStream_SeekToBegin(_stream))\n\n  return NCompress::CopyStream(_stream, outStream, lps);\n\n  // return ReportArcProps(reportArcProp, NULL, NULL);\n\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  return _props.SetProperties(names, values, numProps);\n}\n\nstatic const Byte k_Signature[] = { 'B', 'Z', 'h' };\n\nREGISTER_ARC_IO(\n  \"bzip2\", \"bz2 bzip2 tbz2 tbz\", \"* * .tar .tar\", 2,\n  k_Signature,\n  0,\n  NArcInfoFlags::kKeepName\n  , 0\n  , IsArc_BZip2)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabBlockInStream.cpp",
    "content": "﻿// CabBlockInStream.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/Alloc.h\"\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../Common/StreamUtils.h\"\n\n#include \"CabBlockInStream.h\"\n\nnamespace NArchive {\nnamespace NCab {\n\nstatic const UInt32 kBlockSize = 1 << 16;\nstatic const unsigned k_OverReadPadZone_Size = 32;\nstatic const unsigned kHeaderSize = 8;\nstatic const unsigned kReservedMax = 256;\nstatic const unsigned kHeaderOffset = kBlockSize + k_OverReadPadZone_Size;\n\nbool CBlockPackData::Create() throw()\n{\n  if (!_buf)\n    _buf = (Byte *)z7_AlignedAlloc(kBlockSize + k_OverReadPadZone_Size + kHeaderSize + kReservedMax);\n  return _buf != NULL;\n}\n\nCBlockPackData::~CBlockPackData() throw()\n{\n  z7_AlignedFree(_buf);\n}\n\nstatic UInt32 CheckSum(const Byte *p, UInt32 size) throw()\n{\n#ifdef MY_CPU_64BIT\n \n  UInt64 sum64 = 0;\n  if (size >= 16)\n  {\n    const Byte *lim = p + (size_t)size - 16;\n    do\n    {\n      sum64 ^= GetUi64(p) ^ GetUi64(p + 8);\n      p += 16;\n    }\n    while (p <= lim);\n    size = (UInt32)(lim + 16 - p);\n  }\n  if (size >= 8)\n  {\n    sum64 ^= GetUi64(p);\n    p += 8;\n    size -= 8;\n  }\n\n  UInt32 sum = (UInt32)(sum64 >> 32) ^ (UInt32)sum64;\n\n#else\n\n  UInt32 sum = 0;\n  if (size >= 16)\n  {\n    const Byte *lim = p + (size_t)size - 16;\n    do\n    {\n      sum ^= GetUi32(p)\n           ^ GetUi32(p + 4)\n           ^ GetUi32(p + 8)\n           ^ GetUi32(p + 12);\n      p += 16;\n    }\n    while (p <= lim);\n    size = (UInt32)(lim + 16 - p);\n  }\n  if (size >= 8)\n  {\n    sum ^= GetUi32(p + 0) ^ GetUi32(p + 4);\n    p += 8;\n    size -= 8;\n  }\n\n#endif\n  \n  if (size >= 4)\n  {\n    sum ^= GetUi32(p);\n    p += 4;\n  }\n  if (size &= 3)\n  {\n    if (size >= 2)\n    {\n      if (size > 2)\n        sum ^= (UInt32)(*p++) << 16;\n      sum ^= (UInt32)(*p++) << 8;\n    }\n    sum ^= (UInt32)(*p++);\n  }\n  return sum;\n}\n\n\nHRESULT CBlockPackData::Read(ISequentialInStream *stream, Byte ReservedSize, UInt32 &packSizeRes, UInt32 &unpackSize) throw()\n{\n  const UInt32 reserved8 = kHeaderSize + ReservedSize;\n  const Byte *header = _buf + kHeaderOffset;\n  RINOK(ReadStream_FALSE(stream, (void *)header, reserved8))\n  unpackSize = GetUi16a(header + 6);\n  const UInt32 packSize = GetUi16a(header + 4);\n  packSizeRes = packSize;\n  if (packSize > kBlockSize - _size)\n    return S_FALSE;\n  RINOK(ReadStream_FALSE(stream, _buf + _size, packSize))\n  memset(_buf + _size + packSize, 0xff, k_OverReadPadZone_Size);\n  if (*(const UInt32 *)(const void *)header != 0) // checkSum\n    if (CheckSum(header, reserved8) != CheckSum(_buf + _size, packSize))\n      return S_FALSE;\n  _size += packSize;\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabBlockInStream.h",
    "content": "﻿// CabBlockInStream.h\n\n#ifndef ZIP7_INC_CAB_BLOCK_IN_STREAM_H\n#define ZIP7_INC_CAB_BLOCK_IN_STREAM_H\n\n#include \"../../IStream.h\"\n\nnamespace NArchive {\nnamespace NCab {\n\nclass CBlockPackData\n{\n  Byte *_buf;\n  UInt32 _size;\npublic:\n  CBlockPackData(): _buf(NULL), _size(0) {}\n  ~CBlockPackData() throw();\n  bool Create() throw();\n  void InitForNewBlock() { _size = 0; }\n  HRESULT Read(ISequentialInStream *stream, Byte ReservedSize, UInt32 &packSize, UInt32 &unpackSize) throw();\n  UInt32 GetPackSize() const { return _size; }\n  // 32 bytes of overread zone is available after PackSize:\n  const Byte *GetData() const { return _buf; }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabHandler.cpp",
    "content": "﻿// CabHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../../C/Alloc.h\"\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/AutoPtr.h\"\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/DeflateDecoder.h\"\n#include \"../../Compress/LzxDecoder.h\"\n#include \"../../Compress/QuantumDecoder.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"CabBlockInStream.h\"\n#include \"CabHandler.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NCab {\n\n// #define CAB_DETAILS\n\n#ifdef CAB_DETAILS\nenum\n{\n  kpidBlockReal = kpidUserDefined\n};\n#endif\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidMTime,\n  kpidAttrib,\n  kpidMethod,\n  kpidBlock\n  #ifdef CAB_DETAILS\n  ,\n  // kpidBlockReal, // L\"BlockReal\",\n  kpidOffset,\n  kpidVolume\n  #endif\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidTotalPhySize,\n  kpidMethod,\n  // kpidSolid,\n  kpidNumBlocks,\n  kpidNumVolumes,\n  kpidVolumeIndex,\n  kpidId\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic const char * const kMethods[] =\n{\n    \"None\"\n  , \"MSZip\"\n  , \"Quantum\"\n  , \"LZX\"\n};\n\nstatic const unsigned kMethodNameBufSize = 32; // \"Quantum:255\"\n\nstatic void SetMethodName(char *s, unsigned method, unsigned param)\n{\n  if (method < Z7_ARRAY_SIZE(kMethods))\n  {\n    s = MyStpCpy(s, kMethods[method]);\n    if (method != NHeader::NMethod::kLZX &&\n        method != NHeader::NMethod::kQuantum)\n      return;\n    *s++ = ':';\n    method = param;\n  }\n  ConvertUInt32ToString(method, s);\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMethod:\n    {\n      UInt32 mask = 0;\n      UInt32 params[2] = { 0, 0 };\n      {\n        FOR_VECTOR (v, m_Database.Volumes)\n        {\n          const CRecordVector<CFolder> &folders = m_Database.Volumes[v].Folders;\n          FOR_VECTOR (i, folders)\n          {\n            const CFolder &folder = folders[i];\n            const unsigned method = folder.GetMethod();\n            mask |= ((UInt32)1 << method);\n            if (method == NHeader::NMethod::kLZX ||\n                method == NHeader::NMethod::kQuantum)\n            {\n              const unsigned di = (method == NHeader::NMethod::kQuantum) ? 0 : 1;\n              if (params[di] < folder.MethodMinor)\n                  params[di] = folder.MethodMinor;\n            }\n          }\n        }\n      }\n      \n      AString s;\n      \n      for (unsigned i = 0; i < kNumMethodsMax; i++)\n      {\n        if ((mask & (1 << i)) == 0)\n          continue;\n        s.Add_Space_if_NotEmpty();\n        char temp[kMethodNameBufSize];\n        SetMethodName(temp, i, params[i == NHeader::NMethod::kQuantum ? 0 : 1]);\n        s += temp;\n      }\n      \n      prop = s;\n      break;\n    }\n    // case kpidSolid: prop = _database.IsSolid(); break;\n    case kpidNumBlocks:\n    {\n      UInt32 numFolders = 0;\n      FOR_VECTOR (v, m_Database.Volumes)\n        numFolders += m_Database.Volumes[v].Folders.Size();\n      prop = numFolders;\n      break;\n    }\n\n    case kpidTotalPhySize:\n    {\n      if (m_Database.Volumes.Size() > 1)\n      {\n        UInt64 sum = 0;\n        FOR_VECTOR (v, m_Database.Volumes)\n          sum += m_Database.Volumes[v].ArcInfo.Size;\n        prop = sum;\n      }\n      break;\n    }\n\n    case kpidNumVolumes:\n      prop = (UInt32)m_Database.Volumes.Size();\n      break;\n\n    case kpidVolumeIndex:\n    {\n      if (!m_Database.Volumes.IsEmpty())\n      {\n        const CDatabaseEx &db = m_Database.Volumes[0];\n        const CInArcInfo &ai = db.ArcInfo;\n        prop = (UInt32)ai.CabinetNumber;\n      }\n      break;\n    }\n\n    case kpidId:\n    {\n      if (m_Database.Volumes.Size() != 0)\n      {\n        prop = (UInt32)m_Database.Volumes[0].ArcInfo.SetID;\n      }\n      break;\n    }\n\n    case kpidOffset:\n      /*\n      if (m_Database.Volumes.Size() == 1)\n        prop = m_Database.Volumes[0].StartPosition;\n      */\n      prop = _offset;\n      break;\n    \n    case kpidPhySize:\n      /*\n      if (m_Database.Volumes.Size() == 1)\n        prop = (UInt64)m_Database.Volumes[0].ArcInfo.Size;\n      */\n      prop = (UInt64)_phySize;\n      break;\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_errorInHeaders) v |= kpv_ErrorFlags_HeadersError;\n      if (_unexpectedEnd)  v |= kpv_ErrorFlags_UnexpectedEnd;\n      prop = v;\n      break;\n    }\n    \n    case kpidError:\n      if (!_errorMessage.IsEmpty())\n        prop = _errorMessage;\n      break;\n\n    case kpidName:\n    {\n      if (m_Database.Volumes.Size() == 1)\n      {\n        const CDatabaseEx &db = m_Database.Volumes[0];\n        const CInArcInfo &ai = db.ArcInfo;\n        if (ai.SetID != 0)\n        {\n          AString s;\n          s.Add_UInt32(ai.SetID);\n          s.Add_Char('_');\n          s.Add_UInt32(ai.CabinetNumber + 1);\n          s += \".cab\";\n          prop = s;\n        }\n        /*\n        // that code is incomplete. It gcan give accurate name of volume\n        char s[32];\n        ConvertUInt32ToString(ai.CabinetNumber + 2, s);\n        unsigned len = MyStringLen(s);\n        if (ai.IsThereNext())\n        {\n          AString fn = ai.NextArc.FileName;\n          if (fn.Len() > 4 && StringsAreEqualNoCase_Ascii(fn.RightPtr(4), \".cab\"))\n            fn.DeleteFrom(fn.Len() - 4);\n          if (len < fn.Len())\n          {\n            if (strcmp(s, fn.RightPtr(len)) == 0)\n            {\n              AString s2 = fn;\n              s2.DeleteFrom(fn.Len() - len);\n              ConvertUInt32ToString(ai.CabinetNumber + 1, s);\n              s2 += s;\n              s2 += \".cab\";\n              prop = GetUnicodeString(s2);\n            }\n          }\n        }\n        */\n      }\n      break;\n    }\n\n    // case kpidShortComment:\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  \n  const CMvItem &mvItem = m_Database.Items[index];\n  const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];\n  const unsigned itemIndex = mvItem.ItemIndex;\n  const CItem &item = db.Items[itemIndex];\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      UString unicodeName;\n      if (item.IsNameUTF())\n        ConvertUTF8ToUnicode(item.Name, unicodeName);\n      else\n        unicodeName = MultiByteToUnicodeString(item.Name, CP_ACP);\n      prop = (const wchar_t *)NItemName::WinPathToOsPath(unicodeName);\n      break;\n    }\n    \n    case kpidIsDir:  prop = item.IsDir(); break;\n    case kpidSize:  prop = item.Size; break;\n    case kpidAttrib:  prop = item.GetWinAttrib(); break;\n\n    case kpidMTime:\n    {\n      PropVariant_SetFrom_DosTime(prop, item.Time);\n      break;\n    }\n\n    case kpidMethod:\n    {\n      const int realFolderIndex = item.GetFolderIndex(db.Folders.Size());\n      if (realFolderIndex >= 0)\n      {\n        const CFolder &folder = db.Folders[(unsigned)realFolderIndex];\n        char s[kMethodNameBufSize];\n        SetMethodName(s, folder.GetMethod(), folder.MethodMinor);\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidBlock:  prop.Set_Int32((Int32)m_Database.GetFolderIndex(&mvItem)); break;\n    \n    #ifdef CAB_DETAILS\n    \n    // case kpidBlockReal:  prop = (UInt32)item.FolderIndex; break;\n    case kpidOffset:  prop = (UInt32)item.Offset; break;\n    case kpidVolume:  prop = (UInt32)mvItem.VolumeIndex; break;\n\n    #endif\n\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  Close();\n\n  CInArchive archive;\n  CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\n  if (callback)\n    callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\n  \n  CMyComPtr<IInStream> nextStream = inStream;\n  bool prevChecked = false;\n  UString startVolName;\n  bool startVolName_was_Requested = false;\n  UInt64 numItems = 0;\n  unsigned numTempVolumes = 0;\n  // try\n  {\n    while (nextStream)\n    {\n      CDatabaseEx db;\n      db.Stream = nextStream;\n      \n      HRESULT res = archive.Open(db, maxCheckStartPosition);\n      \n      _errorInHeaders |= archive.HeaderError;\n      _errorInHeaders |= archive.ErrorInNames;\n      _unexpectedEnd |= archive.UnexpectedEnd;\n      \n      if (res == S_OK && !m_Database.Volumes.IsEmpty())\n      {\n        const CArchInfo &lastArc = m_Database.Volumes.Back().ArcInfo;\n        const unsigned cabNumber = db.ArcInfo.CabinetNumber;\n        if (lastArc.SetID != db.ArcInfo.SetID)\n          res = S_FALSE;\n        else if (prevChecked)\n        {\n          if (cabNumber != lastArc.CabinetNumber + 1)\n            res = S_FALSE;\n        }\n        else if (cabNumber >= lastArc.CabinetNumber)\n          res = S_FALSE;\n        else if (numTempVolumes != 0)\n        {\n          const CArchInfo &prevArc = m_Database.Volumes[numTempVolumes - 1].ArcInfo;\n          if (cabNumber != prevArc.CabinetNumber + 1)\n            res = S_FALSE;\n        }\n      }\n      \n      if (archive.IsArc || res == S_OK)\n      {\n        _isArc = true;\n        if (m_Database.Volumes.IsEmpty())\n        {\n          _offset = db.StartPosition;\n          _phySize = db.ArcInfo.Size;\n        }\n      }\n      \n      if (res == S_OK)\n      {\n        numItems += db.Items.Size();\n        m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : numTempVolumes, db);\n        if (!prevChecked && m_Database.Volumes.Size() > 1)\n        {\n          numTempVolumes++;\n          if (db.ArcInfo.CabinetNumber + 1 == m_Database.Volumes[numTempVolumes].ArcInfo.CabinetNumber)\n            numTempVolumes = 0;\n        }\n      }\n      else\n      {\n        if (res != S_FALSE)\n          return res;\n        if (m_Database.Volumes.IsEmpty())\n          return S_FALSE;\n        if (prevChecked)\n          break;\n        prevChecked = true;\n        if (numTempVolumes != 0)\n        {\n          m_Database.Volumes.DeleteFrontal(numTempVolumes);\n          numTempVolumes = 0;\n        }\n      }\n\n      if (callback)\n      {\n        RINOK(callback->SetCompleted(&numItems, NULL))\n      }\n        \n      nextStream = NULL;\n      \n      for (;;)\n      {\n        const COtherArc *otherArc = NULL;\n        \n        if (!prevChecked)\n        {\n          if (numTempVolumes == 0)\n          {\n            const CInArcInfo &ai = m_Database.Volumes[0].ArcInfo;\n            if (ai.IsTherePrev())\n              otherArc = &ai.PrevArc;\n            else\n              prevChecked = true;\n          }\n          else\n          {\n            const CInArcInfo &ai = m_Database.Volumes[numTempVolumes - 1].ArcInfo;\n            if (ai.IsThereNext())\n              otherArc = &ai.NextArc;\n            else\n            {\n              prevChecked = true;\n              m_Database.Volumes.DeleteFrontal(numTempVolumes);\n              numTempVolumes = 0;\n            }\n          }\n        }\n        \n        if (!otherArc)\n        {\n          const CInArcInfo &ai = m_Database.Volumes.Back().ArcInfo;\n          if (ai.IsThereNext())\n            otherArc = &ai.NextArc;\n        }\n        \n        if (!otherArc)\n          break;\n        if (!openVolumeCallback)\n          break;\n        // printf(\"\\n%s\", otherArc->FileName);\n        const UString fullName = MultiByteToUnicodeString(otherArc->FileName, CP_ACP);\n\n        if (!startVolName_was_Requested)\n        {\n          // some \"bad\" cab example can contain the link to itself.\n          startVolName_was_Requested = true;\n          {\n            NCOM::CPropVariant prop;\n            RINOK(openVolumeCallback->GetProperty(kpidName, &prop))\n            if (prop.vt == VT_BSTR)\n              startVolName = prop.bstrVal;\n          }\n          if (fullName == startVolName)\n            break;\n        }\n\n        const HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);\n        if (result == S_OK)\n          break;\n        if (result != S_FALSE)\n          return result;\n\n        if (!_errorMessage.IsEmpty())\n          _errorMessage.Add_LF();\n        _errorMessage += \"Can't open volume: \";\n        _errorMessage += fullName;\n        \n        if (prevChecked)\n          break;\n        prevChecked = true;\n        if (numTempVolumes != 0)\n        {\n          m_Database.Volumes.DeleteFrontal(numTempVolumes);\n          numTempVolumes = 0;\n        }\n      }\n\n    } // read nextStream iteration\n\n    if (numTempVolumes != 0)\n    {\n      m_Database.Volumes.DeleteFrontal(numTempVolumes);\n      numTempVolumes = 0;\n    }\n    if (m_Database.Volumes.IsEmpty())\n      return S_FALSE;\n    else\n    {\n      m_Database.FillSortAndShrink();\n      if (!m_Database.Check())\n        return S_FALSE;\n    }\n  }\n  COM_TRY_END\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _errorMessage.Empty();\n  _isArc = false;\n  _errorInHeaders = false;\n  _unexpectedEnd = false;\n  // _mainVolIndex = -1;\n  _phySize = 0;\n  _offset = 0;\n\n  m_Database.Clear();\n  return S_OK;\n}\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CFolderOutStream\n  , ISequentialOutStream\n)\n  bool m_TestMode;\n  bool TempBufMode;\n  bool m_IsOk;\n  bool m_FileIsOpen;\n\n  const CMvDatabaseEx *m_Database;\n  const CRecordVector<bool> *m_ExtractStatuses;\n  \n  Byte *TempBuf;\n  UInt32 TempBufSize;\n  UInt32 TempBufWritten;\n  unsigned NumIdenticalFiles;\n\n  unsigned m_StartIndex;\n  unsigned m_CurrentIndex;\n\n  UInt32 m_RemainFileSize;\n\n  UInt64 m_FolderSize;\n  UInt64 m_PosInFolder;\n\n  CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;\n  CMyComPtr<ISequentialOutStream> m_RealOutStream;\n\n  void FreeTempBuf()\n  {\n    ::MyFree(TempBuf);\n    TempBuf = NULL;\n  }\n\n  HRESULT OpenFile();\n  HRESULT CloseFileWithResOp(Int32 resOp);\n  HRESULT CloseFile();\npublic:\n  HRESULT WriteEmptyFiles();\n\n  CFolderOutStream(): TempBuf(NULL) {}\n  ~CFolderOutStream() { FreeTempBuf(); }\n  void Init(\n      const CMvDatabaseEx *database,\n      const CRecordVector<bool> *extractStatuses,\n      unsigned startIndex,\n      UInt64 folderSize,\n      IArchiveExtractCallback *extractCallback,\n      bool testMode);\n  HRESULT FlushCorrupted(unsigned folderIndex);\n  HRESULT Unsupported();\n\n  bool NeedMoreWrite() const { return (m_FolderSize > m_PosInFolder); }\n  UInt64 GetRemain() const { return m_FolderSize - m_PosInFolder; }\n  UInt64 GetPosInFolder() const { return m_PosInFolder; }\n};\n\n\nvoid CFolderOutStream::Init(\n    const CMvDatabaseEx *database,\n    const CRecordVector<bool> *extractStatuses,\n    unsigned startIndex,\n    UInt64 folderSize,\n    IArchiveExtractCallback *extractCallback,\n    bool testMode)\n{\n  m_Database = database;\n  m_ExtractStatuses = extractStatuses;\n  m_StartIndex = startIndex;\n  m_FolderSize = folderSize;\n\n  m_ExtractCallback = extractCallback;\n  m_TestMode = testMode;\n\n  m_CurrentIndex = 0;\n  m_PosInFolder = 0;\n  m_FileIsOpen = false;\n  m_IsOk = true;\n  TempBufMode = false;\n  NumIdenticalFiles = 0;\n}\n\n\nHRESULT CFolderOutStream::CloseFileWithResOp(Int32 resOp)\n{\n  m_RealOutStream.Release();\n  m_FileIsOpen = false;\n  NumIdenticalFiles--;\n  return m_ExtractCallback->SetOperationResult(resOp);\n}\n\n\nHRESULT CFolderOutStream::CloseFile()\n{\n  return CloseFileWithResOp(m_IsOk ?\n      NExtract::NOperationResult::kOK:\n      NExtract::NOperationResult::kDataError);\n}\n\n\nHRESULT CFolderOutStream::OpenFile()\n{\n  if (NumIdenticalFiles == 0)\n  {\n    const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];\n    const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\n    unsigned numExtractItems = 0;\n    unsigned curIndex;\n    \n    for (curIndex = m_CurrentIndex; curIndex < m_ExtractStatuses->Size(); curIndex++)\n    {\n      const CMvItem &mvItem2 = m_Database->Items[m_StartIndex + curIndex];\n      const CItem &item2 = m_Database->Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex];\n      if (item.Offset != item2.Offset ||\n          item.Size != item2.Size ||\n          item.Size == 0)\n        break;\n      if (!m_TestMode && (*m_ExtractStatuses)[curIndex])\n        numExtractItems++;\n    }\n    \n    NumIdenticalFiles = (curIndex - m_CurrentIndex);\n    if (NumIdenticalFiles == 0)\n      NumIdenticalFiles = 1;\n    TempBufMode = false;\n    \n    if (numExtractItems > 1)\n    {\n      if (!TempBuf || item.Size > TempBufSize)\n      {\n        FreeTempBuf();\n        TempBuf = (Byte *)MyAlloc(item.Size);\n        TempBufSize = item.Size;\n        if (!TempBuf)\n          return E_OUTOFMEMORY;\n      }\n      TempBufMode = true;\n      TempBufWritten = 0;\n    }\n    else if (numExtractItems == 1)\n    {\n      while (NumIdenticalFiles && !(*m_ExtractStatuses)[m_CurrentIndex])\n      {\n        CMyComPtr<ISequentialOutStream> stream;\n        RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &stream, NExtract::NAskMode::kSkip))\n        if (stream)\n          return E_FAIL;\n        RINOK(m_ExtractCallback->PrepareOperation(NExtract::NAskMode::kSkip))\n        m_CurrentIndex++;\n        m_FileIsOpen = true;\n        CloseFile();\n      }\n    }\n  }\n\n  Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? m_TestMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract :\n      NExtract::NAskMode::kSkip;\n  RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode))\n  if (!m_RealOutStream && !m_TestMode)\n    askMode = NExtract::NAskMode::kSkip;\n  return m_ExtractCallback->PrepareOperation(askMode);\n}\n\n\nHRESULT CFolderOutStream::WriteEmptyFiles()\n{\n  if (m_FileIsOpen)\n    return S_OK;\n  for (; m_CurrentIndex < m_ExtractStatuses->Size(); m_CurrentIndex++)\n  {\n    const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];\n    const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\n    const UInt64 fileSize = item.Size;\n    if (fileSize != 0)\n      return S_OK;\n    const HRESULT result = OpenFile();\n    m_RealOutStream.Release();\n    RINOK(result)\n    RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  // (data == NULL) means Error_Data for solid folder flushing\n  COM_TRY_BEGIN\n  \n  UInt32 realProcessed = 0;\n  if (processedSize)\n   *processedSize = 0;\n  \n  while (size != 0)\n  {\n    if (m_FileIsOpen)\n    {\n      UInt32 numBytesToWrite = MyMin(m_RemainFileSize, size);\n      HRESULT res = S_OK;\n      if (numBytesToWrite != 0)\n      {\n        if (!data)\n          m_IsOk = false;\n        \n        if (m_RealOutStream)\n        {\n          UInt32 processedSizeLocal = 0;\n          // 18.01 : we don't want ZEROs instead of missing data\n          if (data)\n            res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);\n          else\n            processedSizeLocal = numBytesToWrite;\n          numBytesToWrite = processedSizeLocal;\n        }\n        \n        if (TempBufMode && TempBuf)\n        {\n          if (data)\n          {\n            memcpy(TempBuf + TempBufWritten, data, numBytesToWrite);\n            TempBufWritten += numBytesToWrite;\n          }\n        }\n      }\n      realProcessed += numBytesToWrite;\n      if (processedSize)\n        *processedSize = realProcessed;\n      if (data)\n        data = (const void *)((const Byte *)data + numBytesToWrite);\n      size -= numBytesToWrite;\n      m_RemainFileSize -= numBytesToWrite;\n      m_PosInFolder += numBytesToWrite;\n      \n      if (res != S_OK)\n        return res;\n      \n      if (m_RemainFileSize == 0)\n      {\n        RINOK(CloseFile())\n\n        while (NumIdenticalFiles)\n        {\n          HRESULT result = OpenFile();\n          m_FileIsOpen = true;\n          m_CurrentIndex++;\n          if (result == S_OK && m_RealOutStream && TempBuf)\n            result = WriteStream(m_RealOutStream, TempBuf, TempBufWritten);\n          \n          if (!TempBuf && TempBufMode && m_RealOutStream)\n          {\n            RINOK(CloseFileWithResOp(NExtract::NOperationResult::kUnsupportedMethod))\n          }\n          else\n          {\n            RINOK(CloseFile())\n          }\n      \n          RINOK(result)\n        }\n      \n        TempBufMode = false;\n      }\n  \n      if (realProcessed > 0)\n        break; // with this break this function works as Write-Part\n    }\n    else\n    {\n      if (m_CurrentIndex >= m_ExtractStatuses->Size())\n      {\n        // we ignore extra data;\n        realProcessed += size;\n        if (processedSize)\n          *processedSize = realProcessed;\n        m_PosInFolder += size;\n        return S_OK;\n        // return E_FAIL;\n      }\n\n      const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];\n      const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\n\n      m_RemainFileSize = item.Size;\n\n      const UInt32 fileOffset = item.Offset;\n      \n      if (fileOffset < m_PosInFolder)\n        return E_FAIL;\n      \n      if (fileOffset > m_PosInFolder)\n      {\n        const UInt32 numBytesToWrite = MyMin(fileOffset - (UInt32)m_PosInFolder, size);\n        realProcessed += numBytesToWrite;\n        if (processedSize)\n          *processedSize = realProcessed;\n        if (data)\n          data = (const void *)((const Byte *)data + numBytesToWrite);\n        size -= numBytesToWrite;\n        m_PosInFolder += numBytesToWrite;\n      }\n      \n      if (fileOffset == m_PosInFolder)\n      {\n        RINOK(OpenFile())\n        m_FileIsOpen = true;\n        m_CurrentIndex++;\n        m_IsOk = true;\n      }\n    }\n  }\n  \n  return WriteEmptyFiles();\n  \n  COM_TRY_END\n}\n\n\nHRESULT CFolderOutStream::FlushCorrupted(unsigned folderIndex)\n{\n  if (!NeedMoreWrite())\n  {\n    CMyComPtr<IArchiveExtractCallbackMessage2> callbackMessage;\n    m_ExtractCallback.QueryInterface(IID_IArchiveExtractCallbackMessage2, &callbackMessage);\n    if (callbackMessage)\n    {\n      RINOK(callbackMessage->ReportExtractResult(NEventIndexType::kBlockIndex, folderIndex, NExtract::NOperationResult::kDataError))\n    }\n    return S_OK;\n  }\n\n  for (;;)\n  {\n    if (!NeedMoreWrite())\n      return S_OK;\n    const UInt64 remain = GetRemain();\n    UInt32 size = (UInt32)1 << 20;\n    if (size > remain)\n      size = (UInt32)remain;\n    UInt32 processedSizeLocal = 0;\n    RINOK(Write(NULL, size, &processedSizeLocal))\n  }\n}\n\n\nHRESULT CFolderOutStream::Unsupported()\n{\n  while (m_CurrentIndex < m_ExtractStatuses->Size())\n  {\n    const HRESULT result = OpenFile();\n    if (result != S_FALSE && result != S_OK)\n      return result;\n    m_RealOutStream.Release();\n    RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))\n    m_CurrentIndex++;\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = m_Database.Items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalUnPacked = 0;\n\n  UInt32 i;\n  int lastFolder = -2;\n  UInt64 lastFolderSize = 0;\n  \n  for (i = 0; i < numItems; i++)\n  {\n    const unsigned index = allFilesMode ? i : indices[i];\n    const CMvItem &mvItem = m_Database.Items[index];\n    const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\n    if (item.IsDir())\n      continue;\n    const int folderIndex = m_Database.GetFolderIndex(&mvItem);\n    if (folderIndex != lastFolder)\n      totalUnPacked += lastFolderSize;\n    lastFolder = folderIndex;\n    lastFolderSize = item.GetEndOffset();\n  }\n  \n  totalUnPacked += lastFolderSize;\n  RINOK(extractCallback->SetTotal(totalUnPacked))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  CMyComPtr2<ICompressCoder, NCompress::NDeflate::NDecoder::CCOMCoder> deflateDecoder;\n  CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;\n  CMyUniquePtr<NCompress::NQuantum::CDecoder> quantumDecoder;\n\n  CBlockPackData blockPackData;\n  if (!blockPackData.Create())\n    return E_OUTOFMEMORY;\n\n  CMyComPtr2_Create<ISequentialInStream, CBufInStream> inBufStream;\n\n  CRecordVector<bool> extractStatuses;\n\n  totalUnPacked = 0;\n  UInt64 totalPacked = 0;\n  \n  for (i = 0;;)\n  {\n    lps->OutSize = totalUnPacked;\n    lps->InSize = totalPacked;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    const unsigned index = allFilesMode ? i : indices[i];\n\n    const CMvItem &mvItem = m_Database.Items[index];\n    const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];\n    const unsigned itemIndex = mvItem.ItemIndex;\n    const CItem &item = db.Items[itemIndex];\n\n    i++;\n    if (item.IsDir())\n    {\n      const Int32 askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      RINOK(extractCallback->PrepareOperation(askMode))\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    \n    const int folderIndex = m_Database.GetFolderIndex(&mvItem);\n    \n    if (folderIndex < 0)\n    {\n      // If we need previous archive\n      const Int32 askMode= testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      RINOK(extractCallback->PrepareOperation(askMode))\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kDataError))\n      continue;\n    }\n    \n    const unsigned startIndex2 = m_Database.FolderStartFileIndex[(unsigned)folderIndex];\n    unsigned startIndex = startIndex2;\n    extractStatuses.Clear();\n    for (; startIndex < index; startIndex++)\n      extractStatuses.Add(false);\n    extractStatuses.Add(true);\n    startIndex++;\n    UInt64 curUnpack = item.GetEndOffset();\n    \n    for (; i < numItems; i++)\n    {\n      const unsigned indexNext = allFilesMode ? i : indices[i];\n      const CMvItem &mvItem2 = m_Database.Items[indexNext];\n      const CItem &item2 = m_Database.Volumes[mvItem2.VolumeIndex].Items[mvItem2.ItemIndex];\n      if (item2.IsDir())\n        continue;\n      const int newFolderIndex = m_Database.GetFolderIndex(&mvItem2);\n\n      if (newFolderIndex != folderIndex)\n        break;\n      for (; startIndex < indexNext; startIndex++)\n        extractStatuses.Add(false);\n      extractStatuses.Add(true);\n      startIndex++;\n      curUnpack = item2.GetEndOffset();\n    }\n\n    CMyComPtr2_Create<ISequentialOutStream, CFolderOutStream> cabFolderOutStream;\n\n    const int folderIndex2 = item.GetFolderIndex(db.Folders.Size());\n    if (folderIndex2 < 0)\n      return E_FAIL;\n    const CFolder &folder = db.Folders[(unsigned)folderIndex2];\n\n    cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2,\n        curUnpack, extractCallback, testMode != 0);\n\n    HRESULT res = S_OK;\n    \n    switch (folder.GetMethod())\n    {\n      case NHeader::NMethod::kNone:\n        break;\n      \n      case NHeader::NMethod::kMSZip:\n        deflateDecoder.Create_if_Empty();\n        break;\n      \n      case NHeader::NMethod::kLZX:\n        lzxDecoder.Create_if_Empty();\n        res = lzxDecoder->Set_DictBits_and_Alloc(folder.MethodMinor);\n        break;\n\n      case NHeader::NMethod::kQuantum:\n        quantumDecoder.Create_if_Empty();\n        res = quantumDecoder->SetParams(folder.MethodMinor);\n        break;\n      \n      default:\n        res = E_INVALIDARG;\n        break;\n    }\n\n    if (res == E_INVALIDARG)\n    {\n      RINOK(cabFolderOutStream->Unsupported())\n      totalUnPacked += curUnpack;\n      continue;\n    }\n    RINOK(res)\n\n    {\n      unsigned volIndex = mvItem.VolumeIndex;\n      int locFolderIndex = item.GetFolderIndex(db.Folders.Size());\n      bool keepHistory = false;\n      bool keepInputBuffer = false;\n      bool thereWasNotAlignedChunk = false;\n      \n      for (UInt32 bl = 0; cabFolderOutStream->NeedMoreWrite();)\n      {\n        if (volIndex >= m_Database.Volumes.Size())\n        {\n          res = S_FALSE;\n          break;\n        }\n\n        const CDatabaseEx &db2 = m_Database.Volumes[volIndex];\n        if (locFolderIndex < 0)\n          return E_FAIL;\n        const CFolder &folder2 = db2.Folders[(unsigned)locFolderIndex];\n        \n        if (bl == 0)\n        {\n          RINOK(InStream_SeekSet(db2.Stream, db2.StartPosition + folder2.DataStart))\n        }\n        \n        if (bl == folder2.NumDataBlocks)\n        {\n          /*\n            CFolder::NumDataBlocks (CFFOLDER::cCFData in CAB specification) is 16-bit.\n            But there are some big CAB archives from MS that contain more\n            than (0xFFFF) CFDATA blocks in folder.\n            Old cab extracting software can show error (or ask next volume)\n            but cab extracting library in new Windows ignores this error.\n            15.00 : We also try to ignore such error, if archive is not multi-volume.\n          */\n          if (m_Database.Volumes.Size() > 1)\n          {\n            volIndex++;\n            locFolderIndex = 0;\n            bl = 0;\n            continue;\n          }\n        }\n        \n        bl++;\n\n        if (!keepInputBuffer)\n          blockPackData.InitForNewBlock();\n\n        UInt32 packSize, unpackSize;\n        res = blockPackData.Read(db2.Stream, db2.ArcInfo.GetDataBlockReserveSize(), packSize, unpackSize);\n        if (res == S_FALSE)\n          break;\n        RINOK(res)\n        keepInputBuffer = (unpackSize == 0);\n        if (keepInputBuffer)\n          continue;\n\n        const UInt64 totalUnPacked2 = totalUnPacked + cabFolderOutStream->GetPosInFolder();\n        totalPacked += packSize;\n\n        if (totalUnPacked2 - lps->OutSize >= (1 << 26)\n            || totalPacked - lps->InSize >= (1 << 24))\n        {\n          lps->OutSize = totalUnPacked2;\n          lps->InSize = totalPacked;\n          RINOK(lps->SetCur())\n        }\n\n        const unsigned kBlockSizeMax = 1u << 15;\n\n        if (unpackSize != kBlockSizeMax)\n        {\n          if (unpackSize > kBlockSizeMax || thereWasNotAlignedChunk)\n          {\n            res = S_FALSE;\n            break;\n          }\n          thereWasNotAlignedChunk = true;\n        }\n\n        /* We don't try to reduce last block.\n           Note that LZX converts data with x86 filter.\n           and filter needs larger input data than reduced size.\n           It's simpler to decompress full chunk here.\n           also we need full block for quantum for more integrity checks */\n\n        const UInt64 unpackSize64 = unpackSize;\n        const UInt32 packSizeChunk = blockPackData.GetPackSize();\n\n        switch (folder2.GetMethod())\n        {\n          case NHeader::NMethod::kNone:\n            if (unpackSize != packSizeChunk)\n            {\n              res = S_FALSE;\n              break;\n            }\n            res = WriteStream(cabFolderOutStream, blockPackData.GetData(), packSizeChunk);\n            break;\n          \n          case NHeader::NMethod::kMSZip:\n          {\n            /* v24.00 : fixed : we check 2-bytes MSZIP signature only\n               when block was constructed from all volumes. */\n            const Byte *packData = blockPackData.GetData();\n            if (unpackSize > (1u << 15) + 12 /* MSZIP specification */\n                || packSizeChunk < 2 || GetUi16(packData) != 0x4b43)\n            {\n              res = S_FALSE;\n              break;\n            }\n            const UInt32 packSizeChunk_2 = packSizeChunk - 2;\n            inBufStream->Init(packData + 2, packSizeChunk_2);\n\n            deflateDecoder->Set_KeepHistory(keepHistory);\n            /* v9.31: now we follow MSZIP specification that requires\n               to finish deflate stream at the end of each block.\n               But PyCabArc can create CAB archives that don't have\n               finish marker at the end of block.\n               Cabarc probably ignores such errors in cab archives.\n               Maybe we also should ignore such error?\n               Or we should extract full file and show the warning? */\n            deflateDecoder->Set_NeedFinishInput(true);\n            res = deflateDecoder.Interface()->Code(inBufStream, cabFolderOutStream, NULL, &unpackSize64, NULL);\n            if (res == S_OK)\n            {\n              if (!deflateDecoder->IsFinished())\n                res = S_FALSE;\n              if (!deflateDecoder->IsFinalBlock())\n                res = S_FALSE;\n              if (deflateDecoder->GetInputProcessedSize() != packSizeChunk_2)\n                res = S_FALSE;\n            }\n            break;\n          }\n\n          case NHeader::NMethod::kLZX:\n            lzxDecoder->Set_KeepHistory(keepHistory);\n            lzxDecoder->Set_KeepHistoryForNext(true);\n            res = lzxDecoder->Code_WithExceedReadWrite(blockPackData.GetData(),\n                packSizeChunk, unpackSize);\n            if (res == S_OK)\n              res = WriteStream(cabFolderOutStream,\n                  lzxDecoder->GetUnpackData(),\n                  lzxDecoder->GetUnpackSize());\n            break;\n          \n          case NHeader::NMethod::kQuantum:\n          {\n            res = quantumDecoder->Code(blockPackData.GetData(),\n                packSizeChunk, unpackSize, keepHistory);\n            if (res == S_OK)\n            {\n              const UInt32 num = unpackSize;\n              res = WriteStream(cabFolderOutStream,\n                  quantumDecoder->GetDataPtr() - num, num);\n            }\n            break;\n          }\n          default:\n            // it's unexpected case, because we checked method before\n            // res = E_NOTIMPL;\n            break;\n        }\n      \n        if (res != S_OK)\n        {\n          if (res != S_FALSE)\n            return res;\n          break;\n        }\n        \n        keepHistory = true;\n      }\n      \n      if (res == S_OK)\n      {\n        RINOK(cabFolderOutStream->WriteEmptyFiles())\n      }\n    }\n\n    if (res != S_OK || cabFolderOutStream->NeedMoreWrite())\n    {\n      RINOK(cabFolderOutStream->FlushCorrupted((unsigned)folderIndex2))\n    }\n\n    totalUnPacked += curUnpack;\n  }\n\n  return S_OK;\n\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = m_Database.Items.Size();\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabHandler.h",
    "content": "﻿// CabHandler.h\n\n#ifndef ZIP7_INC_CAB_HANDLER_H\n#define ZIP7_INC_CAB_HANDLER_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../IArchive.h\"\n\n#include \"CabIn.h\"\n\nnamespace NArchive {\nnamespace NCab {\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  CMvDatabaseEx m_Database;\n  UString _errorMessage;\n  bool _isArc;\n  bool _errorInHeaders;\n  bool _unexpectedEnd;\n  // int _mainVolIndex;\n  UInt32 _phySize;\n  UInt64 _offset;\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabHeader.cpp",
    "content": "﻿// CabHeader.cpp\n\n#include \"StdAfx.h\"\n\n#include \"CabHeader.h\"\n\nnamespace NArchive {\nnamespace NCab {\nnamespace NHeader {\n\nconst Byte kMarker[kMarkerSize] = {'M', 'S', 'C', 'F', 0, 0, 0, 0 };\n\n// struct CSignatureInitializer { CSignatureInitializer() { kMarker[0]--; } } g_SignatureInitializer;\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabHeader.h",
    "content": "﻿// Archive/CabHeader.h\n\n#ifndef ZIP7_INC_ARCHIVE_CAB_HEADER_H\n#define ZIP7_INC_ARCHIVE_CAB_HEADER_H\n\n#include \"../../../Common/MyTypes.h\"\n\nnamespace NArchive {\nnamespace NCab {\nnamespace NHeader {\n\nconst unsigned kMarkerSize = 8;\nextern const Byte kMarker[kMarkerSize];\n\nnamespace NArcFlags\n{\n  const unsigned kPrevCabinet = 1;\n  const unsigned kNextCabinet = 2;\n  const unsigned kReservePresent = 4;\n}\n\nnamespace NMethod\n{\n  const Byte kNone = 0;\n  const Byte kMSZip = 1;\n  const Byte kQuantum = 2;\n  const Byte kLZX = 3;\n}\n\nconst unsigned kFileNameIsUtf8_Mask = 0x80;\n\nnamespace NFolderIndex\n{\n  const unsigned kContinuedFromPrev    = 0xFFFD;\n  const unsigned kContinuedToNext      = 0xFFFE;\n  const unsigned kContinuedPrevAndNext = 0xFFFF;\n}\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabIn.cpp",
    "content": "﻿// Archive/CabIn.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"CabIn.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n\nnamespace NArchive {\nnamespace NCab {\n\nstruct CUnexpectedEndException {};\n\nvoid CInArchive::Skip(unsigned size)\n{\n  if (_inBuffer.Skip(size) != size)\n    throw CUnexpectedEndException();\n}\n\nvoid CInArchive::Read(Byte *data, unsigned size)\n{\n  if (_inBuffer.ReadBytes(data, size) != size)\n    throw CUnexpectedEndException();\n}\n\nvoid CInArchive::ReadName(AString &s)\n{\n  for (size_t i = 0; i < ((size_t)1 << 13); i++)\n  {\n    Byte b;\n    if (!_inBuffer.ReadByte(b))\n      throw CUnexpectedEndException();\n    if (b == 0)\n    {\n      s.SetFrom((const char *)(const Byte *)_tempBuf, (unsigned)i);\n      return;\n    }\n    if (_tempBuf.Size() == i)\n      _tempBuf.ChangeSize_KeepData(i * 2, i);\n    _tempBuf[i] = b;\n  }\n  \n  for (;;)\n  {\n    Byte b;\n    if (!_inBuffer.ReadByte(b))\n      throw CUnexpectedEndException();\n    if (b == 0)\n      break;\n  }\n  \n  ErrorInNames = true;\n  s = \"[ERROR-LONG-PATH]\";\n}\n\nvoid CInArchive::ReadOtherArc(COtherArc &oa)\n{\n  ReadName(oa.FileName);\n  ReadName(oa.DiskName);\n}\n\n\nstruct CSignatureFinder\n{\n  Byte *Buf;\n  UInt32 Pos;\n  UInt32 End;\n  const Byte *Signature;\n  UInt32 SignatureSize;\n  \n  UInt32 _headerSize;\n  UInt32 _alignSize;\n  UInt32 _bufUseCapacity;\n\n  const UInt64 *SearchLimit;\n  ISequentialInStream *Stream;\n  UInt64 Processed; // Global offset of start of Buf\n\n  UInt32 GetTotalCapacity(UInt32 basicSize, UInt32 headerSize)\n  {\n    _headerSize = headerSize;\n    for (_alignSize = (1 << 5); _alignSize < _headerSize; _alignSize <<= 1);\n    _bufUseCapacity = basicSize + _alignSize;\n    return _bufUseCapacity + 16;\n  }\n\n  /*\n  returns:\n    S_OK      - signature found (at Pos)\n    S_FALSE   - signature not found\n  */\n  HRESULT Find();\n};\n\n\nHRESULT CSignatureFinder::Find()\n{\n  for (;;)\n  {\n    Buf[End] = Signature[0]; // it's for fast search;\n\n    while (End - Pos >= _headerSize)\n    {\n      const Byte *p = Buf + Pos;\n      const Byte b = Signature[0];\n      for (;;)\n      {\n        if (*p == b) { break; }  p++;\n        if (*p == b) { break; }  p++;\n      }\n      Pos = (UInt32)(p - Buf);\n      if (End - Pos < _headerSize)\n      {\n        Pos = End - _headerSize + 1;\n        break;\n      }\n      UInt32 i;\n      for (i = 1; i < SignatureSize && p[i] == Signature[i]; i++);\n      if (i == SignatureSize)\n        return S_OK;\n      Pos++;\n    }\n\n    if (Pos >= _alignSize)\n    {\n      const UInt32 num = (Pos & ~(_alignSize - 1));\n      Processed += num;\n      Pos -= num;\n      End -= num;\n      memmove(Buf, Buf + num, End);\n    }\n    UInt32 rem = _bufUseCapacity - End;\n    if (SearchLimit)\n    {\n      if (Processed + Pos > *SearchLimit)\n        return S_FALSE;\n      const UInt64 rem2 = *SearchLimit - (Processed + End) + _headerSize;\n      if (rem > rem2)\n        rem = (UInt32)rem2;\n    }\n    \n    UInt32 processedSize;\n    if (Processed == 0 && rem == _bufUseCapacity - _headerSize)\n      rem -= _alignSize; // to make reads more aligned.\n    RINOK(Stream->Read(Buf + End, rem, &processedSize))\n    if (processedSize == 0)\n      return S_FALSE;\n    End += processedSize;\n  }\n}\n\n\nbool CInArcInfo::Parse(const Byte *p)\n{\n  if (Get32(p + 0x0C) != 0 ||\n      Get32(p + 0x14) != 0)\n    return false;\n  Size = Get32(p + 8);\n  if (Size < 36)\n    return false;\n  Flags = Get16(p + 0x1E);\n  if (Flags > 7)\n    return false;\n  FileHeadersOffset = Get32(p + 0x10);\n  if (FileHeadersOffset != 0 && FileHeadersOffset > Size)\n    return false;\n  VersionMinor = p[0x18];\n  VersionMajor = p[0x19];\n  NumFolders = Get16(p + 0x1A);\n  NumFiles = Get16(p + 0x1C);\n  return true;\n}\n  \n\nHRESULT CInArchive::Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)\n{\n  IsArc = false;\n  ErrorInNames = false;\n  UnexpectedEnd = false;\n  HeaderError = false;\n\n  db.Clear();\n  RINOK(InStream_GetPos(db.Stream, db.StartPosition))\n  // UInt64 temp = db.StartPosition;\n\n  CByteBuffer buffer;\n  CInArcInfo &ai = db.ArcInfo;\n  UInt64 startInBuf = 0;\n\n  CLimitedSequentialInStream *limitedStreamSpec = NULL;\n  CMyComPtr<ISequentialInStream> limitedStream;\n\n  // for (int iii = 0; iii < 10000; iii++)\n  {\n    // db.StartPosition = temp; RINOK(InStream_SeekSet(db.Stream, db.StartPosition))\n    \n    const UInt32 kMainHeaderSize = 32;\n    Byte header[kMainHeaderSize];\n    const UInt32 kBufSize = 1 << 15;\n    RINOK(ReadStream_FALSE(db.Stream, header, kMainHeaderSize))\n    if (memcmp(header, NHeader::kMarker, NHeader::kMarkerSize) == 0 && ai.Parse(header))\n    {\n      limitedStreamSpec = new CLimitedSequentialInStream;\n      limitedStream = limitedStreamSpec;\n      limitedStreamSpec->SetStream(db.Stream);\n      limitedStreamSpec->Init(ai.Size - NHeader::kMarkerSize);\n      buffer.Alloc(kBufSize);\n      memcpy(buffer, header, kMainHeaderSize);\n      UInt32 numProcessedBytes;\n      RINOK(limitedStream->Read(buffer + kMainHeaderSize, kBufSize - kMainHeaderSize, &numProcessedBytes))\n      _inBuffer.SetBuf(buffer, (UInt32)kBufSize, kMainHeaderSize + numProcessedBytes, kMainHeaderSize);\n    }\n    else\n    {\n      if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)\n        return S_FALSE;\n\n      CSignatureFinder finder;\n\n      finder.Stream = db.Stream;\n      finder.Signature = NHeader::kMarker;\n      finder.SignatureSize = NHeader::kMarkerSize;\n      finder.SearchLimit = searchHeaderSizeLimit;\n\n      buffer.Alloc(finder.GetTotalCapacity(kBufSize, kMainHeaderSize));\n      finder.Buf = buffer;\n\n      memcpy(buffer, header, kMainHeaderSize);\n      finder.Processed = db.StartPosition;\n      finder.End = kMainHeaderSize;\n      finder.Pos = 1;\n  \n      for (;;)\n      {\n        RINOK(finder.Find())\n        if (ai.Parse(finder.Buf + finder.Pos))\n        {\n          db.StartPosition = finder.Processed + finder.Pos;\n          limitedStreamSpec = new CLimitedSequentialInStream;\n          limitedStreamSpec->SetStream(db.Stream);\n          limitedStream = limitedStreamSpec;\n          const UInt32 remInFinder = finder.End - finder.Pos;\n          if (ai.Size <= remInFinder)\n          {\n            limitedStreamSpec->Init(0);\n            finder.End = finder.Pos + ai.Size;\n          }\n          else\n            limitedStreamSpec->Init(ai.Size - remInFinder);\n\n          startInBuf = finder.Pos;\n          _inBuffer.SetBuf(buffer, (UInt32)kBufSize, finder.End, finder.Pos + kMainHeaderSize);\n          break;\n        }\n        finder.Pos++;\n      }\n    }\n  }\n  \n  IsArc = true;\n\n  _inBuffer.SetStream(limitedStream);\n  if (_tempBuf.Size() == 0)\n    _tempBuf.Alloc(1 << 12);\n\n  Byte p[16];\n  const unsigned nextSize = 4 + (ai.ReserveBlockPresent() ? 4 : 0);\n  Read(p, nextSize);\n  ai.SetID = Get16(p);\n  ai.CabinetNumber = Get16(p + 2);\n\n  if (ai.ReserveBlockPresent())\n  {\n    ai.PerCabinet_AreaSize = Get16(p + 4);\n    ai.PerFolder_AreaSize = p[6];\n    ai.PerDataBlock_AreaSize = p[7];\n    Skip(ai.PerCabinet_AreaSize);\n  }\n\n  if (ai.IsTherePrev()) ReadOtherArc(ai.PrevArc);\n  if (ai.IsThereNext()) ReadOtherArc(ai.NextArc);\n  \n  UInt32 i;\n  \n  db.Folders.ClearAndReserve(ai.NumFolders);\n  \n  for (i = 0; i < ai.NumFolders; i++)\n  {\n    Read(p, 8);\n    CFolder folder;\n    folder.DataStart = Get32(p);\n    folder.NumDataBlocks = Get16(p + 4);\n    folder.MethodMajor = p[6];\n    folder.MethodMinor = p[7];\n    Skip(ai.PerFolder_AreaSize);\n    db.Folders.AddInReserved(folder);\n  }\n  \n  // for (int iii = 0; iii < 10000; iii++) {\n\n  if (_inBuffer.GetProcessedSize() - startInBuf != ai.FileHeadersOffset)\n  {\n    // printf(\"\\n!!! Seek Error !!!!\\n\");\n    // fflush(stdout);\n    RINOK(InStream_SeekSet(db.Stream, db.StartPosition + ai.FileHeadersOffset))\n    limitedStreamSpec->Init(ai.Size - ai.FileHeadersOffset);\n    _inBuffer.Init();\n  }\n\n  db.Items.ClearAndReserve(ai.NumFiles);\n\n  for (i = 0; i < ai.NumFiles; i++)\n  {\n    Read(p, 16);\n    CItem &item = db.Items.AddNewInReserved();\n    item.Size = Get32(p);\n    item.Offset = Get32(p + 4);\n    item.FolderIndex = Get16(p + 8);\n    const UInt16 pureDate = Get16(p + 10);\n    const UInt16 pureTime = Get16(p + 12);\n    item.Time = (((UInt32)pureDate << 16)) | pureTime;\n    item.Attributes = Get16(p + 14);\n\n    ReadName(item.Name);\n    \n    if (item.GetFolderIndex(db.Folders.Size()) >= (int)db.Folders.Size())\n    {\n      HeaderError = true;\n      return S_FALSE;\n    }\n  }\n  \n  // }\n  \n  return S_OK;\n}\n\n\nHRESULT CInArchive::Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit)\n{\n  try\n  {\n    return Open2(db, searchHeaderSizeLimit);\n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; }\n}\n\n\n\n#define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }\n\nstatic int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)\n{\n  const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;\n  const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];\n  const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];\n  const CItem &item1 = db1.Items[p1->ItemIndex];\n  const CItem &item2 = db2.Items[p2->ItemIndex];\n  const bool isDir1 = item1.IsDir();\n  const bool isDir2 = item2.IsDir();\n  if (isDir1 && !isDir2) return -1;\n  if (isDir2 && !isDir1) return 1;\n  const int f1 = mvDb.GetFolderIndex(p1);\n  const int f2 = mvDb.GetFolderIndex(p2);\n  RINOZ(MyCompare(f1, f2))\n  RINOZ(MyCompare(item1.Offset, item2.Offset))\n  RINOZ(MyCompare(item1.Size, item2.Size))\n  RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex))\n  return MyCompare(p1->ItemIndex, p2->ItemIndex);\n}\n\n\nbool CMvDatabaseEx::AreItemsEqual(unsigned i1, unsigned i2)\n{\n  const CMvItem *p1 = &Items[i1];\n  const CMvItem *p2 = &Items[i2];\n  const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];\n  const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];\n  const CItem &item1 = db1.Items[p1->ItemIndex];\n  const CItem &item2 = db2.Items[p2->ItemIndex];\n  return GetFolderIndex(p1) == GetFolderIndex(p2)\n      && item1.Offset == item2.Offset\n      && item1.Size == item2.Size\n      && item1.Name == item2.Name;\n}\n\n\nvoid CMvDatabaseEx::FillSortAndShrink()\n{\n  Items.Clear();\n  StartFolderOfVol.Clear();\n  FolderStartFileIndex.Clear();\n  \n  int offset = 0;\n  \n  FOR_VECTOR (v, Volumes)\n  {\n    const CDatabaseEx &db = Volumes[v];\n    int curOffset = offset;\n    if (db.IsTherePrevFolder())\n      curOffset--;\n    StartFolderOfVol.Add(curOffset);\n    offset += db.GetNumberOfNewFolders();\n\n    CMvItem mvItem;\n    mvItem.VolumeIndex = v;\n    FOR_VECTOR (i, db.Items)\n    {\n      mvItem.ItemIndex = i;\n      Items.Add(mvItem);\n    }\n  }\n\n  if (Items.Size() > 1)\n  {\n    Items.Sort(CompareMvItems, (void *)this);\n    unsigned j = 1;\n    unsigned i = 1;\n    for (; i < Items.Size(); i++)\n      if (!AreItemsEqual(i, i - 1))\n        Items[j++] = Items[i];\n    Items.DeleteFrom(j);\n  }\n\n  FOR_VECTOR (i, Items)\n  {\n    const int folderIndex = GetFolderIndex(&Items[i]);\n    while (folderIndex >= (int)FolderStartFileIndex.Size())\n      FolderStartFileIndex.Add(i);\n  }\n}\n\n\nbool CMvDatabaseEx::Check()\n{\n  for (unsigned v = 1; v < Volumes.Size(); v++)\n  {\n    const CDatabaseEx &db1 = Volumes[v];\n    if (db1.IsTherePrevFolder())\n    {\n      const CDatabaseEx &db0 = Volumes[v - 1];\n      if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())\n        return false;\n      const CFolder &f0 = db0.Folders.Back();\n      const CFolder &f1 = db1.Folders.FrontItem();\n      if (f0.MethodMajor != f1.MethodMajor ||\n          f0.MethodMinor != f1.MethodMinor)\n        return false;\n    }\n  }\n\n  UInt32 beginPos = 0;\n  UInt64 endPos = 0;\n  int prevFolder = -2;\n  \n  FOR_VECTOR (i, Items)\n  {\n    const CMvItem &mvItem = Items[i];\n    const int fIndex = GetFolderIndex(&mvItem);\n    if (fIndex >= (int)FolderStartFileIndex.Size())\n      return false;\n    const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];\n    if (item.IsDir())\n      continue;\n    \n    const int folderIndex = GetFolderIndex(&mvItem);\n  \n    if (folderIndex != prevFolder)\n      prevFolder = folderIndex;\n    else if (item.Offset < endPos &&\n        (item.Offset != beginPos || item.GetEndOffset() != endPos))\n      return false;\n    \n    beginPos = item.Offset;\n    endPos = item.GetEndOffset();\n  }\n  \n  return true;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabIn.h",
    "content": "﻿// Archive/CabIn.h\n\n#ifndef ZIP7_INC_ARCHIVE_CAB_IN_H\n#define ZIP7_INC_ARCHIVE_CAB_IN_H\n\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../Common/InBuffer.h\"\n\n#include \"CabItem.h\"\n\nnamespace NArchive {\nnamespace NCab {\n\nstruct COtherArc\n{\n  AString FileName;\n  AString DiskName;\n  \n  void Clear()\n  {\n    FileName.Empty();\n    DiskName.Empty();\n  }\n};\n\n\nstruct CArchInfo\n{\n  Byte VersionMinor; // cabinet file format version, minor\n  Byte VersionMajor; // cabinet file format version, major\n  UInt32 NumFolders; // number of CFFOLDER entries in this cabinet\n  UInt32 NumFiles;   // number of CFFILE entries in this cabinet\n  UInt32 Flags;      // cabinet file option indicators\n  UInt32 SetID;      // must be the same for all cabinets in a set\n  UInt32 CabinetNumber; // number of this cabinet file in a set\n\n  UInt16 PerCabinet_AreaSize; // (optional) size of per-cabinet reserved area\n  Byte PerFolder_AreaSize;    // (optional) size of per-folder reserved area\n  Byte PerDataBlock_AreaSize; // (optional) size of per-datablock reserved area\n\n  COtherArc PrevArc; // prev link can skip some volumes !!!\n  COtherArc NextArc;\n\n  bool ReserveBlockPresent() const { return (Flags & NHeader::NArcFlags::kReservePresent) != 0; }\n  bool IsTherePrev() const { return (Flags & NHeader::NArcFlags::kPrevCabinet) != 0; }\n  bool IsThereNext() const { return (Flags & NHeader::NArcFlags::kNextCabinet) != 0; }\n  Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlock_AreaSize : 0); }\n\n  CArchInfo()\n  {\n    PerCabinet_AreaSize = 0;\n    PerFolder_AreaSize = 0;\n    PerDataBlock_AreaSize = 0;\n  }\n\n  void Clear()\n  {\n    PerCabinet_AreaSize = 0;\n    PerFolder_AreaSize = 0;\n    PerDataBlock_AreaSize = 0;\n\n    PrevArc.Clear();\n    NextArc.Clear();\n  }\n};\n\n\nstruct CInArcInfo: public CArchInfo\n{\n  UInt32 Size; // size of this cabinet file in bytes\n  UInt32 FileHeadersOffset; // offset of the first CFFILE entry\n\n  bool Parse(const Byte *p);\n};\n\n\nstruct CDatabase\n{\n  CRecordVector<CFolder> Folders;\n  CObjectVector<CItem> Items;\n  UInt64 StartPosition;\n  CInArcInfo ArcInfo;\n  \n  void Clear()\n  {\n    ArcInfo.Clear();\n    Folders.Clear();\n    Items.Clear();\n  }\n  \n  bool IsTherePrevFolder() const\n  {\n    FOR_VECTOR (i, Items)\n      if (Items[i].ContinuedFromPrev())\n        return true;\n    return false;\n  }\n  \n  int GetNumberOfNewFolders() const\n  {\n    int res = (int)Folders.Size();\n    if (IsTherePrevFolder())\n      res--;\n    return res;\n  }\n};\n\n\nstruct CDatabaseEx: public CDatabase\n{\n  CMyComPtr<IInStream> Stream;\n};\n\n\nstruct CMvItem\n{\n  unsigned VolumeIndex;\n  unsigned ItemIndex;\n};\n\n\nclass CMvDatabaseEx\n{\n  bool AreItemsEqual(unsigned i1, unsigned i2);\n\npublic:\n  CObjectVector<CDatabaseEx> Volumes;\n  CRecordVector<CMvItem> Items;\n  CRecordVector<int> StartFolderOfVol; // can be negative\n  CRecordVector<unsigned> FolderStartFileIndex;\n\n  int GetFolderIndex(const CMvItem *mvi) const\n  {\n    const CDatabaseEx &db = Volumes[mvi->VolumeIndex];\n    return StartFolderOfVol[mvi->VolumeIndex] +\n        db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size());\n  }\n\n  void Clear()\n  {\n    Volumes.Clear();\n    Items.Clear();\n    StartFolderOfVol.Clear();\n    FolderStartFileIndex.Clear();\n  }\n  \n  void FillSortAndShrink();\n  bool Check();\n};\n\n\nclass CInArchive\n{\n  CInBufferBase _inBuffer;\n  CByteBuffer _tempBuf;\n\n  void Skip(unsigned size);\n  void Read(Byte *data, unsigned size);\n  void ReadName(AString &s);\n  void ReadOtherArc(COtherArc &oa);\n  HRESULT Open2(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);\n\npublic:\n  bool IsArc;\n  bool ErrorInNames;\n  bool UnexpectedEnd;\n  bool HeaderError;\n\n  HRESULT Open(CDatabaseEx &db, const UInt64 *searchHeaderSizeLimit);\n};\n  \n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabItem.h",
    "content": "﻿// Archive/CabItem.h\n\n#ifndef ZIP7_INC_ARCHIVE_CAB_ITEM_H\n#define ZIP7_INC_ARCHIVE_CAB_ITEM_H\n\n#include \"../../../Common/MyString.h\"\n\n#include \"CabHeader.h\"\n\nnamespace NArchive {\nnamespace NCab {\n\nconst unsigned kNumMethodsMax = 16;\n\nstruct CFolder\n{\n  UInt32 DataStart; // offset of the first CFDATA block in this folder\n  UInt16 NumDataBlocks; // number of CFDATA blocks in this folder\n  Byte MethodMajor;\n  Byte MethodMinor;\n  \n  Byte GetMethod() const { return (Byte)(MethodMajor & 0xF); }\n};\n\nstruct CItem\n{\n  AString Name;\n  UInt32 Offset;\n  UInt32 Size;\n  UInt32 Time;\n  UInt32 FolderIndex;\n  UInt16 Flags;\n  UInt16 Attributes;\n  \n  UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }\n  UInt32 GetWinAttrib() const { return (UInt32)Attributes & ~(UInt32)NHeader::kFileNameIsUtf8_Mask; }\n  bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUtf8_Mask) != 0; }\n  bool IsDir() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }\n\n  bool ContinuedFromPrev() const\n  {\n    return\n      FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev ||\n      FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;\n  }\n  \n  bool ContinuedToNext() const\n  {\n    return\n      FolderIndex == NHeader::NFolderIndex::kContinuedToNext ||\n      FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext;\n  }\n\n  int GetFolderIndex(unsigned numFolders) const\n  {\n    if (ContinuedFromPrev())\n      return 0;\n    if (ContinuedToNext())\n      return (int)numFolders - 1;\n    return (int)FolderIndex;\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/CabRegister.cpp",
    "content": "﻿// CabRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/RegisterArc.h\"\n\n#include \"CabHandler.h\"\n\nnamespace NArchive {\nnamespace NCab {\n\nREGISTER_ARC_I(\n  \"Cab\", \"cab\", NULL, 8,\n  NHeader::kMarker,\n  0,\n  NArcInfoFlags::kFindSignature,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Cab/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Chm/ChmHandler.cpp",
    "content": "﻿// ChmHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/AutoPtr.h\"\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamUtils.h\"\n#include \"../../Common/RegisterArc.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n#include \"../../Compress/LzxDecoder.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"ChmHandler.h\"\n\nusing namespace NWindows;\nusing namespace NTime;\n\nnamespace NArchive {\nnamespace NChm {\n\n// #define CHM_DETAILS\n\n#ifdef CHM_DETAILS\n\nenum\n{\n  kpidSection = kpidUserDefined\n};\n\n#endif\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidMethod,\n  kpidBlock\n  \n  #ifdef CHM_DETAILS\n  ,\n  L\"Section\", kpidSection,\n  kpidOffset\n  #endif\n};\n\n/*\nstatic const Byte kArcProps[] =\n{\n  // kpidNumBlocks,\n};\n*/\n\nIMP_IInArchive_Props\n\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  // COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    /*\n    case kpidNumBlocks:\n    {\n      UInt64 numBlocks = 0;\n      FOR_VECTOR(i, m_Database.Sections)\n      {\n        const CSectionInfo &s = m_Database.Sections[i];\n        FOR_VECTOR(j, s.Methods)\n        {\n          const CMethodInfo &m = s.Methods[j];\n          if (m.IsLzx())\n            numBlocks += m.LzxInfo.ResetTable.GetNumBlocks();\n        }\n      }\n      prop = numBlocks;\n      break;\n    }\n    */\n    case kpidOffset: prop = m_Database.StartPosition; break;\n    case kpidPhySize: prop = m_Database.PhySize; break;\n\n    case kpidErrorFlags: prop = m_ErrorFlags; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  // COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  \n  if (m_Database.NewFormat)\n  {\n    switch (propID)\n    {\n      case kpidSize:\n        prop = (UInt64)m_Database.NewFormatString.Len();\n      break;\n    }\n    prop.Detach(value);\n    return S_OK;\n  }\n  \n  unsigned entryIndex;\n  if (m_Database.LowLevel)\n    entryIndex = index;\n  else\n    entryIndex = m_Database.Indices[index];\n  \n  const CItem &item = m_Database.Items[entryIndex];\n  \n  switch (propID)\n  {\n    case kpidPath:\n    {\n      UString us;\n      // if (\n      ConvertUTF8ToUnicode(item.Name, us);\n      {\n        if (!m_Database.LowLevel)\n        {\n          if (us.Len() > 1 && us[0] == L'/')\n            us.Delete(0);\n        }\n        NItemName::ReplaceToOsSlashes_Remove_TailSlash(us);\n        prop = us;\n      }\n      break;\n    }\n    case kpidIsDir:  prop = item.IsDir(); break;\n    case kpidSize:  prop = item.Size; break;\n    case kpidMethod:\n    {\n      if (!item.IsDir())\n      {\n        if (item.Section == 0)\n          prop = \"Copy\";\n        else if (item.Section < m_Database.Sections.Size())\n          prop = m_Database.Sections[(unsigned)item.Section].GetMethodName();\n      }\n      break;\n    }\n    case kpidBlock:\n      if (m_Database.LowLevel)\n        prop = item.Section;\n      else if (item.Section != 0 && item.Section < m_Database.Sections.Size())\n        prop = m_Database.GetFolder(index);\n      break;\n    \n    #ifdef CHM_DETAILS\n    \n    case kpidSection:  prop = (UInt32)item.Section; break;\n    case kpidOffset:  prop = (UInt32)item.Offset; break;\n\n    #endif\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  try\n  {\n    CInArchive archive(_help2);\n    // CProgressImp progressImp(openArchiveCallback);\n    const HRESULT res = archive.Open(inStream, maxCheckStartPosition, m_Database);\n    if (!archive.IsArc) m_ErrorFlags |= kpv_ErrorFlags_IsNotArc;\n    if (archive.HeadersError) m_ErrorFlags |= kpv_ErrorFlags_HeadersError;\n    if (archive.UnexpectedEnd)  m_ErrorFlags |= kpv_ErrorFlags_UnexpectedEnd;\n    if (archive.UnsupportedFeature)  m_ErrorFlags |= kpv_ErrorFlags_UnsupportedFeature;\n    \n    RINOK(res)\n    /*\n    if (m_Database.LowLevel)\n      return S_FALSE;\n    */\n    m_Stream = inStream;\n  }\n  catch(...)\n  {\n    return S_FALSE;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  m_ErrorFlags = 0;\n  m_Database.Clear();\n  m_Stream.Release();\n  return S_OK;\n}\n\nZ7_CLASS_IMP_NOQIB_1(\n  CChmFolderOutStream\n  , ISequentialOutStream\n)\n  bool m_TestMode;\n  bool m_IsOk;\n  bool m_FileIsOpen;\n  const CFilesDatabase *m_Database;\n  CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;\n  CMyComPtr<ISequentialOutStream> m_RealOutStream;\n  UInt64 m_RemainFileSize;\n\n  HRESULT OpenFile();\n  HRESULT WriteEmptyFiles();\n  HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);\npublic:\n\n  UInt64 m_FolderSize;\n  UInt64 m_PosInFolder;\n  UInt64 m_PosInSection;\n  const CRecordVector<bool> *m_ExtractStatuses;\n  unsigned m_StartIndex;\n  unsigned m_CurrentIndex;\n  unsigned m_NumFiles;\n\n  void Init(\n    const CFilesDatabase *database,\n    IArchiveExtractCallback *extractCallback,\n    bool testMode);\n  HRESULT FlushCorrupted(UInt64 maxSize);\n};\n\nvoid CChmFolderOutStream::Init(\n    const CFilesDatabase *database,\n    IArchiveExtractCallback *extractCallback,\n    bool testMode)\n{\n  m_Database = database;\n  m_ExtractCallback = extractCallback;\n  m_TestMode = testMode;\n\n  m_CurrentIndex = 0;\n  m_FileIsOpen = false;\n}\n\nHRESULT CChmFolderOutStream::OpenFile()\n{\n  Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? m_TestMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract :\n      NExtract::NAskMode::kSkip;\n  m_RealOutStream.Release();\n  RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode))\n  if (!m_RealOutStream && !m_TestMode)\n    askMode = NExtract::NAskMode::kSkip;\n  return m_ExtractCallback->PrepareOperation(askMode);\n}\n\nHRESULT CChmFolderOutStream::WriteEmptyFiles()\n{\n  if (m_FileIsOpen)\n    return S_OK;\n  for (; m_CurrentIndex < m_NumFiles; m_CurrentIndex++)\n  {\n    const UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);\n    if (fileSize != 0)\n      return S_OK;\n    const HRESULT result = OpenFile();\n    m_RealOutStream.Release();\n    RINOK(result)\n    RINOK(m_ExtractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n  }\n  return S_OK;\n}\n\n// This is WritePart function\nHRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)\n{\n  UInt32 realProcessed = 0;\n  if (processedSize)\n   *processedSize = 0;\n  \n  while (size != 0)\n  {\n    if (m_FileIsOpen)\n    {\n      UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size));\n      HRESULT res = S_OK;\n      if (numBytesToWrite > 0)\n      {\n        if (!isOK)\n          m_IsOk = false;\n        if (m_RealOutStream)\n        {\n          UInt32 processedSizeLocal = 0;\n          res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);\n          numBytesToWrite = processedSizeLocal;\n        }\n      }\n      realProcessed += numBytesToWrite;\n      if (processedSize)\n        *processedSize = realProcessed;\n      data = (const void *)((const Byte *)data + numBytesToWrite);\n      size -= numBytesToWrite;\n      m_RemainFileSize -= numBytesToWrite;\n      m_PosInSection += numBytesToWrite;\n      m_PosInFolder += numBytesToWrite;\n      if (res != S_OK)\n        return res;\n      if (m_RemainFileSize == 0)\n      {\n        m_RealOutStream.Release();\n        RINOK(m_ExtractCallback->SetOperationResult(\n          m_IsOk ?\n            NExtract::NOperationResult::kOK:\n            NExtract::NOperationResult::kDataError))\n        m_FileIsOpen = false;\n      }\n      if (realProcessed > 0)\n        break; // with this break this function works as write part\n    }\n    else\n    {\n      if (m_CurrentIndex >= m_NumFiles)\n      {\n        realProcessed += size;\n        if (processedSize)\n          *processedSize = realProcessed;\n        return S_OK;\n        // return E_FAIL;\n      }\n\n      unsigned fullIndex = m_StartIndex + m_CurrentIndex;\n      m_RemainFileSize = m_Database->GetFileSize(fullIndex);\n      UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);\n      if (fileOffset < m_PosInSection)\n        return E_FAIL;\n      \n      if (fileOffset > m_PosInSection)\n      {\n        UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size));\n        realProcessed += numBytesToWrite;\n        if (processedSize)\n          *processedSize = realProcessed;\n        data = (const void *)((const Byte *)data + numBytesToWrite);\n        size -= numBytesToWrite;\n        m_PosInSection += numBytesToWrite;\n        m_PosInFolder += numBytesToWrite;\n      }\n      \n      if (fileOffset == m_PosInSection)\n      {\n        RINOK(OpenFile())\n        m_FileIsOpen = true;\n        m_CurrentIndex++;\n        m_IsOk = true;\n      }\n    }\n  }\n  \n  return WriteEmptyFiles();\n}\n\nZ7_COM7F_IMF(CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  return Write2(data, size, processedSize, true);\n}\n\nHRESULT CChmFolderOutStream::FlushCorrupted(UInt64 maxSize)\n{\n  const UInt32 kBufferSize = (1 << 10);\n  Byte buffer[kBufferSize];\n  for (unsigned i = 0; i < kBufferSize; i++)\n    buffer[i] = 0;\n  if (maxSize > m_FolderSize)\n    maxSize = m_FolderSize;\n  while (m_PosInFolder < maxSize)\n  {\n    UInt32 size = (UInt32)MyMin(maxSize - m_PosInFolder, (UInt64)kBufferSize);\n    UInt32 processedSizeLocal = 0;\n    RINOK(Write2(buffer, size, &processedSizeLocal, false))\n    if (processedSizeLocal == 0)\n      return S_OK;\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testModeSpec, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n\n  if (allFilesMode)\n    numItems = m_Database.NewFormat ? 1:\n      (m_Database.LowLevel ?\n      m_Database.Items.Size():\n      m_Database.Indices.Size());\n  if (numItems == 0)\n    return S_OK;\n  const bool testMode = (testModeSpec != 0);\n\n  UInt64 currentTotalSize = 0;\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(m_Stream);\n\n  UInt32 i;\n\n  if (m_Database.LowLevel)\n  {\n    UInt64 currentItemSize = 0;\n    UInt64 totalSize = 0;\n    \n    if (m_Database.NewFormat)\n      totalSize = m_Database.NewFormatString.Len();\n    else\n      for (i = 0; i < numItems; i++)\n        totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;\n    \n    RINOK(extractCallback->SetTotal(totalSize))\n    \n    for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\n    {\n      currentItemSize = 0;\n      lps->InSize = currentTotalSize; // Change it\n      lps->OutSize = currentTotalSize;\n\n      RINOK(lps->SetCur())\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      const Int32 askMode= testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      const UInt32 index = allFilesMode ? i : indices[i];\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n      if (m_Database.NewFormat)\n      {\n        if (index != 0)\n          return E_FAIL;\n        if (!testMode && !realOutStream)\n          continue;\n        if (!testMode)\n        {\n          const unsigned size = m_Database.NewFormatString.Len();\n          RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size))\n        }\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        continue;\n      }\n      \n      const CItem &item = m_Database.Items[index];\n      \n      currentItemSize = item.Size;\n      \n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      if (item.Section != 0)\n      {\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))\n        continue;\n      }\n\n      if (testMode)\n      {\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        continue;\n      }\n      \n      RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))\n      inStream->Init(item.Size);\n      \n      RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult((copyCoder->TotalSize == item.Size) ?\n          NExtract::NOperationResult::kOK:\n          NExtract::NOperationResult::kDataError))\n    }\n    return S_OK;\n  }\n  \n  UInt64 lastFolderIndex = (UInt64)0 - 1;\n  \n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem &item = m_Database.Items[m_Database.Indices[index]];\n    const UInt64 sectionIndex = item.Section;\n    if (item.IsDir() || item.Size == 0)\n      continue;\n    if (sectionIndex == 0)\n    {\n      currentTotalSize += item.Size;\n      continue;\n    }\n\n    if (sectionIndex >= m_Database.Sections.Size())\n      continue;\n\n    const CSectionInfo &section = m_Database.Sections[(unsigned)sectionIndex];\n    if (section.IsLzx())\n    {\n      const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;\n      UInt64 folderIndex = m_Database.GetFolder(index);\n      if (lastFolderIndex == folderIndex)\n        folderIndex++;\n      lastFolderIndex = m_Database.GetLastFolder(index);\n      for (; folderIndex <= lastFolderIndex; folderIndex++)\n        currentTotalSize += lzxInfo.GetFolderSize();\n    }\n  }\n\n  RINOK(extractCallback->SetTotal(currentTotalSize))\n\n  CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;\n  CMyComPtr2_Create<ISequentialOutStream, CChmFolderOutStream> chmFolderOutStream;\n\n  currentTotalSize = 0;\n\n  CRecordVector<bool> extractStatuses;\n\n  CByteBuffer packBuf;\n  \n  for (i = 0;;)\n  {\n    RINOK(extractCallback->SetCompleted(&currentTotalSize))\n\n    if (i >= numItems)\n      break;\n\n    UInt32 index = allFilesMode ? i : indices[i];\n    i++;\n    const CItem &item = m_Database.Items[m_Database.Indices[index]];\n    const UInt64 sectionIndex = item.Section;\n    const Int32 askMode= testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    \n    if (item.IsDir())\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      RINOK(extractCallback->PrepareOperation(askMode))\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    lps->InSize = currentTotalSize; // Change it\n    lps->OutSize = currentTotalSize;\n\n    if (item.Size == 0 || sectionIndex == 0)\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      Int32 opRes = NExtract::NOperationResult::kOK;\n      if (!testMode && item.Size != 0)\n      {\n        RINOK(InStream_SeekSet(m_Stream, m_Database.ContentOffset + item.Offset))\n        inStream->Init(item.Size);\n        RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n        if (copyCoder->TotalSize != item.Size)\n          opRes = NExtract::NOperationResult::kDataError;\n      }\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(opRes))\n      currentTotalSize += item.Size;\n      continue;\n    }\n  \n    if (sectionIndex >= m_Database.Sections.Size())\n    {\n      // we must report error here;\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kHeadersError))\n      continue;\n    }\n\n    const CSectionInfo &section = m_Database.Sections[(unsigned)sectionIndex];\n\n    if (!section.IsLzx())\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))\n      continue;\n    }\n\n    const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;\n\n    chmFolderOutStream->Init(&m_Database, extractCallback, testMode);\n\n    lzxDecoder.Create_if_Empty();\n\n    UInt64 folderIndex = m_Database.GetFolder(index);\n\n    const UInt64 compressedPos = m_Database.ContentOffset + section.Offset;\n    RINOK(lzxDecoder->Set_DictBits_and_Alloc(lzxInfo.GetNumDictBits()))\n\n    const CItem *lastItem = &item;\n    extractStatuses.Clear();\n    extractStatuses.Add(true);\n\n    for (;; folderIndex++)\n    {\n      RINOK(extractCallback->SetCompleted(&currentTotalSize))\n\n      const UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);\n      UInt64 finishPos = lastItem->Offset + lastItem->Size;\n      const UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);\n\n      lastFolderIndex = m_Database.GetLastFolder(index);\n      const UInt64 folderSize = lzxInfo.GetFolderSize();\n      UInt64 unPackSize = folderSize;\n      \n      if (extractStatuses.IsEmpty())\n        chmFolderOutStream->m_StartIndex = index + 1;\n      else\n        chmFolderOutStream->m_StartIndex = index;\n      \n      if (limitFolderIndex == folderIndex)\n      {\n        for (; i < numItems; i++)\n        {\n          const UInt32 nextIndex = allFilesMode ? i : indices[i];\n          const CItem &nextItem = m_Database.Items[m_Database.Indices[nextIndex]];\n          if (nextItem.Section != sectionIndex)\n            break;\n          const UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);\n          if (nextFolderIndex != folderIndex)\n            break;\n          for (index++; index < nextIndex; index++)\n            extractStatuses.Add(false);\n          extractStatuses.Add(true);\n          index = nextIndex;\n          lastItem = &nextItem;\n          if (nextItem.Size != 0)\n            finishPos = nextItem.Offset + nextItem.Size;\n          lastFolderIndex = m_Database.GetLastFolder(index);\n        }\n      }\n      \n      unPackSize = MyMin(finishPos - startPos, unPackSize);\n\n      chmFolderOutStream->m_FolderSize = folderSize;\n      chmFolderOutStream->m_PosInFolder = 0;\n      chmFolderOutStream->m_PosInSection = startPos;\n      chmFolderOutStream->m_ExtractStatuses = &extractStatuses;\n      chmFolderOutStream->m_NumFiles = extractStatuses.Size();\n      chmFolderOutStream->m_CurrentIndex = 0;\n      \n      try\n      {\n        const UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);\n        const CResetTable &rt = lzxInfo.ResetTable;\n        const UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);\n        \n        for (UInt32 b = 0; b < numBlocks; b++)\n        {\n          UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;\n          RINOK(extractCallback->SetCompleted(&completedSize))\n          UInt64 bCur = startBlock + b;\n          if (bCur >= rt.ResetOffsets.Size())\n            return E_FAIL;\n          const UInt64 offset = rt.ResetOffsets[(unsigned)bCur];\n          UInt64 compressedSize;\n          rt.GetCompressedSizeOfBlock(bCur, compressedSize);\n          \n          // chm writes full blocks. So we don't need to use reduced size for last block\n\n          RINOK(InStream_SeekSet(m_Stream, compressedPos + offset))\n          inStream->Init(compressedSize);\n          \n          lzxDecoder->Set_KeepHistory(b > 0);\n      \n          HRESULT res = S_FALSE;\n          if (compressedSize <= (1u << 30))\n          {\n            const unsigned kAdditionalInputSize = 32;\n            const size_t compressedSizeT = (size_t)compressedSize;\n            const size_t allocSize = compressedSizeT + kAdditionalInputSize;\n            if (allocSize <= compressedSize)\n              throw 2;\n            packBuf.AllocAtLeast(allocSize);\n            res = ReadStream_FALSE(inStream, packBuf, compressedSizeT);\n            if (res == S_OK)\n            {\n              memset(packBuf + compressedSizeT, 0xff, kAdditionalInputSize);\n              lzxDecoder->Set_KeepHistoryForNext(true);\n              res = lzxDecoder->Code_WithExceedReadWrite(packBuf, compressedSizeT, kBlockSize); // rt.BlockSize;\n              if (res == S_OK)\n                res = WriteStream(chmFolderOutStream,\n                  lzxDecoder->GetUnpackData(),\n                  lzxDecoder->GetUnpackSize());\n            }\n          }\n          \n          if (res != S_OK)\n          {\n            if (res != S_FALSE)\n              return res;\n            throw 1;\n          }\n        }\n      }\n      catch(...)\n      {\n        RINOK(chmFolderOutStream->FlushCorrupted(unPackSize))\n      }\n      \n      currentTotalSize += folderSize;\n      if (folderIndex == lastFolderIndex)\n        break;\n      extractStatuses.Clear();\n    }\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = m_Database.NewFormat ? 1:\n      (m_Database.LowLevel ?\n      m_Database.Items.Size():\n      m_Database.Indices.Size());\n  return S_OK;\n}\n\nnamespace NChm {\n\nstatic const Byte k_Signature[] = { 'I', 'T', 'S', 'F', 3, 0, 0, 0, 0x60, 0,  0, 0 };\n\nREGISTER_ARC_I_CLS(\n  CHandler(false),\n  \"Chm\", \"chm chi chq chw\", NULL, 0xE9,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}\n\nnamespace NHxs {\n\nstatic const Byte k_Signature[] = { 'I', 'T', 'O', 'L', 'I', 'T', 'L', 'S', 1, 0, 0, 0, 0x28, 0, 0, 0 };\n\nREGISTER_ARC_I_CLS(\n  CHandler(true),\n  \"Hxs\", \"hxs hxi hxr hxq hxw lit\", NULL, 0xCE,\n  k_Signature,\n  0,\n  NArcInfoFlags::kFindSignature,\n  NULL)\n\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Chm/ChmHandler.h",
    "content": "﻿// ChmHandler.h\n\n#ifndef ZIP7_INC_ARCHIVE_CHM_HANDLER_H\n#define ZIP7_INC_ARCHIVE_CHM_HANDLER_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../IArchive.h\"\n\n#include \"ChmIn.h\"\n\nnamespace NArchive {\nnamespace NChm {\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  CFilesDatabase m_Database;\n  CMyComPtr<IInStream> m_Stream;\n  bool _help2;\n  UInt32 m_ErrorFlags;\npublic:\n  CHandler(bool help2): _help2(help2) {}\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Chm/ChmIn.cpp",
    "content": "﻿// Archive/ChmIn.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"ChmIn.h\"\n\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\nnamespace NArchive {\nnamespace NChm {\n\nstatic const UInt32 kSignature_ITSP = 0x50535449;\nstatic const UInt32 kSignature_PMGL = 0x4C474D50;\nstatic const UInt32 kSignature_LZXC = 0x43585A4C;\n\nstatic const UInt32 kSignature_IFCM = 0x4D434649;\nstatic const UInt32 kSignature_AOLL = 0x4C4C4F41;\nstatic const UInt32 kSignature_CAOL = 0x4C4F4143;\n\nstatic const UInt32 kSignature_ITSF = 0x46535449;\nstatic const UInt32 kSignature_ITOL = 0x4C4F5449;\nstatic const UInt32 kSignature_ITLS = 0x534C5449;\n\nstruct CEnexpectedEndException {};\nstruct CHeaderErrorException {};\n\n// define CHM_LOW, if you want to see low level items\n// #define CHM_LOW\n\nstatic const Byte kChmLzxGuid[16]   = { 0x40, 0x89, 0xC2, 0x7F, 0x31, 0x9D, 0xD0, 0x11, 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C };\nstatic const Byte kHelp2LzxGuid[16] = { 0xC6, 0x07, 0x90, 0x0A, 0x76, 0x40, 0xD3, 0x11, 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 };\nstatic const Byte kDesGuid[16]      = { 0xA2, 0xE4, 0xF6, 0x67, 0xBF, 0x60, 0xD3, 0x11, 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF };\n\nstatic bool inline AreGuidsEqual(const Byte *g1, const Byte *g2)\n{\n  return memcmp(g1, g2, 16) == 0;\n}\n\nstatic void PrintByte(unsigned b, AString &s)\n{\n  s += (char)GET_HEX_CHAR_UPPER(b >> 4);\n  s += (char)GET_HEX_CHAR_LOWER(b & 0xF);\n}\n\nAString CMethodInfo::GetGuidString() const\n{\n  char s[16 * 2 + 8];\n  RawLeGuidToString_Braced(Guid, s);\n  // MyStringUpper_Ascii(s);\n  return (AString)s;\n}\n\nbool CMethodInfo::IsLzx() const\n{\n  if (AreGuidsEqual(Guid, kChmLzxGuid))\n    return true;\n  return AreGuidsEqual(Guid, kHelp2LzxGuid);\n}\n\nbool CMethodInfo::IsDes() const\n{\n  return AreGuidsEqual(Guid, kDesGuid);\n}\n\nAString CMethodInfo::GetName() const\n{\n  AString s;\n  if (IsLzx())\n  {\n    s = \"LZX:\";\n    s.Add_UInt32(LzxInfo.GetNumDictBits());\n  }\n  else\n  {\n    if (IsDes())\n      s = \"DES\";\n    else\n    {\n      s = GetGuidString();\n      /*\n      if (ControlData.Size() > 0 && ControlData.Size() <= (1 << 6))\n      {\n        s.Add_Colon();\n        for (size_t i = 0; i < ControlData.Size(); i++)\n          PrintByte(ControlData[i], s);\n      }\n      */\n    }\n  }\n  return s;\n}\n\nbool CSectionInfo::IsLzx() const\n{\n  if (Methods.Size() != 1)\n    return false;\n  return Methods[0].IsLzx();\n}\n\nUString CSectionInfo::GetMethodName() const\n{\n  UString s;\n  if (!IsLzx())\n  {\n    UString temp;\n    ConvertUTF8ToUnicode(Name, temp);\n      s += temp;\n    s += \": \";\n  }\n  FOR_VECTOR (i, Methods)\n  {\n    if (i != 0)\n      s.Add_Space();\n    s += Methods[i].GetName();\n  }\n  return s;\n}\n\nByte CInArchive::ReadByte()\n{\n  Byte b;\n  if (!_inBuffer.ReadByte(b))\n    throw CEnexpectedEndException();\n  return b;\n}\n\nvoid CInArchive::Skip(size_t size)\n{\n  if (_inBuffer.Skip(size) != size)\n    throw CEnexpectedEndException();\n}\n\nvoid CInArchive::ReadBytes(Byte *data, UInt32 size)\n{\n  if (_inBuffer.ReadBytes(data, size) != size)\n    throw CEnexpectedEndException();\n}\n\nUInt16 CInArchive::ReadUInt16()\n{\n  Byte b0, b1;\n  if (!_inBuffer.ReadByte(b0)) throw CEnexpectedEndException();\n  if (!_inBuffer.ReadByte(b1)) throw CEnexpectedEndException();\n  return (UInt16)(((UInt16)b1 << 8) | b0);\n}\n\nUInt32 CInArchive::ReadUInt32()\n{\n  Byte p[4];\n  ReadBytes(p, 4);\n  return Get32(p);\n}\n\nUInt64 CInArchive::ReadUInt64()\n{\n  Byte p[8];\n  ReadBytes(p, 8);\n  return Get64(p);\n}\n\nUInt64 CInArchive::ReadEncInt()\n{\n  UInt64 val = 0;\n  for (int i = 0; i < 9; i++)\n  {\n    const unsigned b = ReadByte();\n    val |= (b & 0x7F);\n    if (b < 0x80)\n      return val;\n    val <<= 7;\n  }\n  throw CHeaderErrorException();\n}\n\nvoid CInArchive::ReadGUID(Byte *g)\n{\n  ReadBytes(g, 16);\n}\n\nvoid CInArchive::ReadString(unsigned size, AString &s)\n{\n  s.Empty();\n  if (size != 0)\n  {\n    ReadBytes((Byte *)s.GetBuf(size), size);\n    s.ReleaseBuf_CalcLen(size);\n  }\n}\n\nvoid CInArchive::ReadUString(unsigned size, UString &s)\n{\n  s.Empty();\n  while (size-- != 0)\n  {\n    const wchar_t c = ReadUInt16();\n    if (c == 0)\n    {\n      Skip(2 * size);\n      return;\n    }\n    s += c;\n  }\n}\n\nHRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)\n{\n  RINOK(InStream_SeekSet(inStream, pos))\n  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\n  CMyComPtr<ISequentialInStream> limitedStream(streamSpec);\n  streamSpec->SetStream(inStream);\n  streamSpec->Init(size);\n  m_InStreamRef = limitedStream;\n  _inBuffer.SetStream(limitedStream);\n  _inBuffer.Init();\n  return S_OK;\n}\n\nHRESULT CInArchive::ReadDirEntry(CDatabase &database)\n{\n  CItem item;\n  const UInt64 nameLen = ReadEncInt();\n  if (nameLen == 0 || nameLen > (1 << 13))\n    return S_FALSE;\n  ReadString((unsigned)nameLen, item.Name);\n  item.Section = ReadEncInt();\n  item.Offset = ReadEncInt();\n  item.Size = ReadEncInt();\n  database.Items.Add(item);\n  return S_OK;\n}\n\nHRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)\n{\n  UInt32 headerSize = ReadUInt32();\n  if (headerSize != 0x60)\n    return S_FALSE;\n  database.PhySize = headerSize;\n\n  UInt32 unknown1 = ReadUInt32();\n  if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file\n    return S_FALSE;\n\n  IsArc = true;\n\n  /* UInt32 timeStamp = */ ReadUInt32();\n      // Considered as a big-endian DWORD, it appears to contain seconds (MSB) and\n      // fractional seconds (second byte).\n      // The third and fourth bytes may contain even more fractional bits.\n      // The 4 least significant bits in the last byte are constant.\n  /* UInt32 lang = */ ReadUInt32();\n  Byte g[16];\n  ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}\n  ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}\n  const unsigned kNumSections = 2;\n  UInt64 sectionOffsets[kNumSections];\n  UInt64 sectionSizes[kNumSections];\n  unsigned i;\n  for (i = 0; i < kNumSections; i++)\n  {\n    sectionOffsets[i] = ReadUInt64();\n    sectionSizes[i] = ReadUInt64();\n    UInt64 end = sectionOffsets[i] + sectionSizes[i];\n    database.UpdatePhySize(end);\n  }\n  // if (chmVersion == 3)\n    database.ContentOffset = ReadUInt64();\n  /*\n  else\n    database.ContentOffset = database.StartPosition + 0x58\n  */\n\n  // Section 0\n  ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]);\n  if (sectionSizes[0] < 0x18)\n    return S_FALSE;\n  if (ReadUInt32() != 0x01FE)\n    return S_FALSE;\n  ReadUInt32(); // unknown:  0\n  UInt64 fileSize = ReadUInt64();\n  database.UpdatePhySize(fileSize);\n  ReadUInt32(); // unknown:  0\n  ReadUInt32(); // unknown:  0\n\n  // Section 1: The Directory Listing\n  ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]);\n  if (ReadUInt32() != kSignature_ITSP)\n    return S_FALSE;\n  if (ReadUInt32() != 1) // version\n    return S_FALSE;\n  /* UInt32 dirHeaderSize = */ ReadUInt32();\n  ReadUInt32(); // 0x0A (unknown)\n  UInt32 dirChunkSize = ReadUInt32(); // $1000\n  if (dirChunkSize < 32)\n    return S_FALSE;\n  /* UInt32 density = */ ReadUInt32(); //  \"Density\" of quickref section, usually 2.\n  /* UInt32 depth = */ ReadUInt32(); //  Depth of the index tree: 1 there is no index,\n                               // 2 if there is one level of PMGI chunks.\n\n  /* UInt32 chunkNumber = */ ReadUInt32(); //  Chunk number of root index chunk, -1 if there is none\n                                     // (though at least one file has 0 despite there being no\n                                     // index chunk, probably a bug.)\n  /* UInt32 firstPmglChunkNumber = */ ReadUInt32(); // Chunk number of first PMGL (listing) chunk\n  /* UInt32 lastPmglChunkNumber = */ ReadUInt32();  // Chunk number of last PMGL (listing) chunk\n  ReadUInt32(); // -1 (unknown)\n  UInt32 numDirChunks = ReadUInt32(); // Number of directory chunks (total)\n  /* UInt32 windowsLangId = */ ReadUInt32();\n  ReadGUID(g);  // {5D02926A-212E-11D0-9DF9-00A0C922E6EC}\n  ReadUInt32(); // 0x54 (This is the length again)\n  ReadUInt32(); // -1 (unknown)\n  ReadUInt32(); // -1 (unknown)\n  ReadUInt32(); // -1 (unknown)\n\n  for (UInt32 ci = 0; ci < numDirChunks; ci++)\n  {\n    UInt64 chunkPos = _inBuffer.GetProcessedSize();\n    if (ReadUInt32() == kSignature_PMGL)\n    {\n      // The quickref area is written backwards from the end of the chunk.\n      // One quickref entry exists for every n entries in the file, where n\n      // is calculated as 1 + (1 << quickref density). So for density = 2, n = 5.\n\n      const UInt32 quickrefLength = ReadUInt32(); // Len of free space and/or quickref area at end of directory chunk\n      if (quickrefLength > dirChunkSize || quickrefLength < 2)\n        return S_FALSE;\n      ReadUInt32(); // Always 0\n      ReadUInt32(); // Chunk number of previous listing chunk when reading\n                    // directory in sequence (-1 if this is the first listing chunk)\n      ReadUInt32(); // Chunk number of next  listing chunk when reading\n                    // directory in sequence (-1 if this is the last listing chunk)\n      unsigned numItems = 0;\n      \n      for (;;)\n      {\n        const UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;\n        const UInt32 offsetLimit = dirChunkSize - quickrefLength;\n        if (offset > offsetLimit)\n          return S_FALSE;\n        if (offset == offsetLimit)\n          break;\n        RINOK(ReadDirEntry(database))\n        numItems++;\n      }\n      \n      Skip(quickrefLength - 2);\n      \n      const unsigned rrr = ReadUInt16();\n      if (rrr != numItems)\n      {\n        // Lazarus 9-26-2 chm contains 0 here.\n        if (rrr != 0)\n          return S_FALSE;\n      }\n    }\n    else\n      Skip(dirChunkSize - 4);\n  }\n  return S_OK;\n}\n\nHRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)\n{\n  if (ReadUInt32() != 1) // version\n    return S_FALSE;\n  if (ReadUInt32() != 0x28) // Location of header section table\n    return S_FALSE;\n  UInt32 numHeaderSections = ReadUInt32();\n  const unsigned kNumHeaderSectionsMax = 5;\n  if (numHeaderSections != kNumHeaderSectionsMax)\n    return S_FALSE;\n\n  IsArc = true;\n\n  ReadUInt32(); // Len of post-header table\n  Byte g[16];\n  ReadGUID(g);  // {0A9007C1-4076-11D3-8789-0000F8105754}\n\n  // header section table\n  UInt64 sectionOffsets[kNumHeaderSectionsMax];\n  UInt64 sectionSizes[kNumHeaderSectionsMax];\n  UInt32 i;\n  for (i = 0; i < numHeaderSections; i++)\n  {\n    sectionOffsets[i] = ReadUInt64();\n    sectionSizes[i] = ReadUInt64();\n    UInt64 end = sectionOffsets[i] + sectionSizes[i];\n    database.UpdatePhySize(end);\n  }\n  \n  // Post-Header\n  ReadUInt32(); // 2\n  ReadUInt32(); // 0x98: offset to CAOL from beginning of post-header)\n  // ----- Directory information\n  ReadUInt64(); // Chunk number of top-level AOLI chunk in directory, or -1\n  ReadUInt64(); // Chunk number of first AOLL chunk in directory\n  ReadUInt64(); // Chunk number of last AOLL chunk in directory\n  ReadUInt64(); // 0 (unknown)\n  ReadUInt32(); // $2000 (Directory chunk size of directory)\n  ReadUInt32(); // Quickref density for main directory, usually 2\n  ReadUInt32(); // 0 (unknown)\n  ReadUInt32(); // Depth of main directory index tree\n                // 1 there is no index, 2 if there is one level of AOLI chunks.\n  ReadUInt64(); // 0 (unknown)\n  UInt64 numDirEntries = ReadUInt64(); // Number of directory entries\n  // ----- Directory Index Information\n  ReadUInt64(); // -1 (unknown, probably chunk number of top-level AOLI in directory index)\n  ReadUInt64(); // Chunk number of first AOLL chunk in directory index\n  ReadUInt64(); // Chunk number of last AOLL chunk in directory index\n  ReadUInt64(); // 0 (unknown)\n  ReadUInt32(); // $200 (Directory chunk size of directory index)\n  ReadUInt32(); // Quickref density for directory index, usually 2\n  ReadUInt32(); // 0 (unknown)\n  ReadUInt32(); // Depth of directory index index tree.\n  ReadUInt64(); // Possibly flags -- sometimes 1, sometimes 0.\n  ReadUInt64(); // Number of directory index entries (same as number of AOLL\n               // chunks in main directory)\n  \n  // (The obvious guess for the following two fields, which recur in a number\n  // of places, is they are maximum sizes for the directory and directory index.\n  // However, I have seen no direct evidence that this is the case.)\n\n  ReadUInt32(); // $100000 (Same as field following chunk size in directory)\n  ReadUInt32(); // $20000 (Same as field following chunk size in directory index)\n\n  ReadUInt64(); // 0 (unknown)\n  if (ReadUInt32() != kSignature_CAOL)\n    return S_FALSE;\n  if (ReadUInt32() != 2) // (Most likely a version number)\n    return S_FALSE;\n  UInt32 caolLength = ReadUInt32(); // $50 (Len of the CAOL section, which includes the ITSF section)\n  if (caolLength >= 0x2C)\n  {\n    /* UInt32 c7 = */ ReadUInt16(); // Unknown.  Remains the same when identical files are built.\n              // Does not appear to be a checksum.  Many files have\n              // 'HH' (HTML Help?) here, indicating this may be a compiler ID\n              //  field.  But at least one ITOL/ITLS compiler does not set this\n              // field to a constant value.\n    ReadUInt16(); // 0 (Unknown.  Possibly part of 00A4 field)\n    ReadUInt32(); // Unknown.  Two values have been seen -- $43ED, and 0.\n    ReadUInt32(); // $2000 (Directory chunk size of directory)\n    ReadUInt32(); // $200 (Directory chunk size of directory index)\n    ReadUInt32(); // $100000 (Same as field following chunk size in directory)\n    ReadUInt32(); // $20000 (Same as field following chunk size in directory index)\n    ReadUInt32(); // 0 (unknown)\n    ReadUInt32(); // 0 (Unknown)\n    if (caolLength == 0x2C)\n    {\n      // fprintf(stdout, \"\\n !!!NewFormat\\n\");\n      // fflush(stdout);\n      database.ContentOffset = 0; // maybe we must add database.StartPosition here?\n      database.NewFormat = true;\n    }\n    else if (caolLength == 0x50)\n    {\n      ReadUInt32(); // 0 (Unknown)\n      if (ReadUInt32() != kSignature_ITSF)\n        return S_FALSE;\n      if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3)\n        return S_FALSE;\n      if (ReadUInt32() != 0x20) // $20 (length of ITSF)\n        return S_FALSE;\n      UInt32 unknown = ReadUInt32();\n      if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases;\n        return S_FALSE;\n      database.ContentOffset = database.StartPosition + ReadUInt64();\n      /* UInt32 timeStamp = */ ReadUInt32();\n          // A timestamp of some sort.\n          // Considered as a big-endian DWORD, it appears to contain\n          // seconds (MSB) and fractional seconds (second byte).\n          // The third and fourth bytes may contain even more fractional\n          // bits.  The 4 least significant bits in the last byte are constant.\n      /* UInt32 lang = */ ReadUInt32(); // BE?\n    }\n    else\n      return S_FALSE;\n  }\n\n  // Section 0\n  ReadChunk(inStream, database.StartPosition + sectionOffsets[0], sectionSizes[0]);\n  if (sectionSizes[0] < 0x18)\n    return S_FALSE;\n  if (ReadUInt32() != 0x01FE)\n    return S_FALSE;\n  ReadUInt32(); // unknown:  0\n  UInt64 fileSize = ReadUInt64();\n  database.UpdatePhySize(fileSize);\n  ReadUInt32(); // unknown:  0\n  ReadUInt32(); // unknown:  0\n\n  // Section 1: The Directory Listing\n  ReadChunk(inStream, database.StartPosition + sectionOffsets[1], sectionSizes[1]);\n  if (ReadUInt32() != kSignature_IFCM)\n    return S_FALSE;\n  if (ReadUInt32() != 1) // (probably a version number)\n    return S_FALSE;\n  UInt32 dirChunkSize = ReadUInt32(); // $2000\n  if (dirChunkSize < 64)\n    return S_FALSE;\n  ReadUInt32(); // $100000  (unknown)\n  ReadUInt32(); // -1 (unknown)\n  ReadUInt32(); // -1 (unknown)\n  UInt32 numDirChunks = ReadUInt32();\n  ReadUInt32(); // 0 (unknown, probably high word of above)\n\n  for (UInt32 ci = 0; ci < numDirChunks; ci++)\n  {\n    UInt64 chunkPos = _inBuffer.GetProcessedSize();\n    if (ReadUInt32() == kSignature_AOLL)\n    {\n      UInt32 quickrefLength = ReadUInt32(); // Len of quickref area at end of directory chunk\n      if (quickrefLength > dirChunkSize || quickrefLength < 2)\n        return S_FALSE;\n      ReadUInt64(); // Directory chunk number\n            // This must match physical position in file, that is\n            // the chunk size times the chunk number must be the\n            // offset from the end of the directory header.\n      ReadUInt64(); // Chunk number of previous listing chunk when reading\n                    // directory in sequence (-1 if first listing chunk)\n      ReadUInt64(); // Chunk number of next listing chunk when reading\n                    // directory in sequence (-1 if last listing chunk)\n      ReadUInt64(); // Number of first listing entry in this chunk\n      ReadUInt32(); // 1 (unknown -- other values have also been seen here)\n      ReadUInt32(); // 0 (unknown)\n      \n      unsigned numItems = 0;\n      for (;;)\n      {\n        const UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;\n        const UInt32 offsetLimit = dirChunkSize - quickrefLength;\n        if (offset > offsetLimit)\n          return S_FALSE;\n        if (offset == offsetLimit)\n          break;\n        if (database.NewFormat)\n        {\n          const unsigned nameLen = ReadUInt16();\n          if (nameLen == 0)\n            return S_FALSE;\n          UString name;\n          ReadUString(nameLen, name);\n          AString s;\n          ConvertUnicodeToUTF8(name, s);\n          {\n            const unsigned b = ReadByte();\n            s.Add_Space();\n            PrintByte(b, s);\n          }\n          s.Add_Space();\n          UInt64 len = ReadEncInt();\n          // then number of items ?\n          // then length ?\n          // then some data (binary encoding?)\n          if (len > 1u << 29) // what limit here we need?\n            return S_FALSE;\n          if (len)\n          do\n          {\n            const unsigned b = ReadByte();\n            PrintByte(b, s);\n          }\n          while (--len);\n          database.NewFormatString += s;\n          database.NewFormatString += \"\\r\\n\";\n        }\n        else\n        {\n          RINOK(ReadDirEntry(database))\n        }\n        numItems++;\n      }\n      Skip(quickrefLength - 2);\n      if (ReadUInt16() != numItems)\n        return S_FALSE;\n      if (numItems > numDirEntries)\n        return S_FALSE;\n      numDirEntries -= numItems;\n    }\n    else\n      Skip(dirChunkSize - 4);\n  }\n  return numDirEntries == 0 ? S_OK : S_FALSE;\n}\n\nHRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name)\n{\n  int index = database.FindItem(name);\n  if (index < 0)\n    return S_FALSE;\n  const CItem &item = database.Items[index];\n  _chunkSize = item.Size;\n  return ReadChunk(inStream, database.ContentOffset + item.Offset, item.Size);\n}\n\n\n#define DATA_SPACE \"::DataSpace/\"\n#define kNameList DATA_SPACE \"NameList\"\n#define kStorage DATA_SPACE \"Storage/\"\n#define kContent \"Content\"\n#define kControlData \"ControlData\"\n#define kSpanInfo \"SpanInfo\"\n#define kTransform \"Transform/\"\n#define kResetTable \"/InstanceData/ResetTable\"\n#define kTransformList \"List\"\n\nstatic AString GetSectionPrefix(const AString &name)\n{\n  AString s (kStorage);\n  s += name;\n  s.Add_Slash();\n  return s;\n}\n\n#define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }\n\nstatic int CompareFiles(const unsigned *p1, const unsigned *p2, void *param)\n{\n  const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;\n  const CItem &item1 = items[*p1];\n  const CItem &item2 = items[*p2];\n  bool isDir1 = item1.IsDir();\n  bool isDir2 = item2.IsDir();\n  if (isDir1 && !isDir2)\n    return -1;\n  if (isDir2)\n  {\n    if (!isDir1)\n      return 1;\n  }\n  else\n  {\n    RINOZ(MyCompare(item1.Section, item2.Section))\n    RINOZ(MyCompare(item1.Offset, item2.Offset))\n    RINOZ(MyCompare(item1.Size, item2.Size))\n  }\n  return MyCompare(*p1, *p2);\n}\n\nvoid CFilesDatabase::SetIndices()\n{\n  FOR_VECTOR (i, Items)\n  {\n    const CItem &item = Items[i];\n    if (item.IsUserItem() && item.Name.Len() != 1)\n      Indices.Add(i);\n  }\n}\n\nvoid CFilesDatabase::Sort()\n{\n  Indices.Sort(CompareFiles, (void *)&Items);\n}\n\nbool CFilesDatabase::Check()\n{\n  UInt64 maxPos = 0;\n  UInt64 prevSection = 0;\n  FOR_VECTOR (i, Indices)\n  {\n    const CItem &item = Items[Indices[i]];\n    if (item.Section == 0 || item.IsDir())\n      continue;\n    if (item.Section != prevSection)\n    {\n      prevSection = item.Section;\n      maxPos = 0;\n      continue;\n    }\n    if (item.Offset < maxPos)\n      return false;\n    maxPos = item.Offset + item.Size;\n    if (maxPos < item.Offset)\n      return false;\n  }\n  return true;\n}\n\nbool CFilesDatabase::CheckSectionRefs()\n{\n  FOR_VECTOR (i, Indices)\n  {\n    const CItem &item = Items[Indices[i]];\n    if (item.Section == 0 || item.IsDir())\n      continue;\n    if (item.Section >= Sections.Size())\n      return false;\n  }\n  return true;\n}\n\nstatic int inline GetLog(UInt32 num)\n{\n  for (int i = 0; i < 32; i++)\n    if (((UInt32)1 << i) == num)\n      return i;\n  return -1;\n}\n\nHRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)\n{\n  {\n    // The NameList file\n    RINOK(DecompressStream(inStream, database, (AString)kNameList))\n    /* UInt16 length = */ ReadUInt16();\n    UInt16 numSections = ReadUInt16();\n    for (unsigned i = 0; i < numSections; i++)\n    {\n      CSectionInfo section;\n      const unsigned nameLen = ReadUInt16();\n      UString name;\n      ReadUString(nameLen, name);\n      if (ReadUInt16() != 0)\n        return S_FALSE;\n      ConvertUnicodeToUTF8(name, section.Name);\n      // if (!ConvertUnicodeToUTF8(name, section.Name)) return S_FALSE;\n      database.Sections.Add(section);\n    }\n  }\n\n  unsigned si;\n  for (si = 1; si < database.Sections.Size(); si++)\n  {\n    CSectionInfo &section = database.Sections[si];\n    AString sectionPrefix (GetSectionPrefix(section.Name));\n    {\n      // Content\n      int index = database.FindItem(sectionPrefix + kContent);\n      if (index < 0)\n        return S_FALSE;\n      const CItem &item = database.Items[index];\n      section.Offset = item.Offset;\n      section.CompressedSize = item.Size;\n    }\n    AString transformPrefix (sectionPrefix + kTransform);\n    if (database.Help2Format)\n    {\n      // Transform List\n      RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList))\n      if ((_chunkSize & 0xF) != 0)\n        return S_FALSE;\n      unsigned numGuids = (unsigned)(_chunkSize / 0x10);\n      if (numGuids < 1)\n        return S_FALSE;\n      for (unsigned i = 0; i < numGuids; i++)\n      {\n        CMethodInfo method;\n        ReadGUID(method.Guid);\n        section.Methods.Add(method);\n      }\n    }\n    else\n    {\n      CMethodInfo method;\n      memcpy(method.Guid, kChmLzxGuid, 16);\n      section.Methods.Add(method);\n    }\n\n    {\n      // Control Data\n      RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData))\n      \n      FOR_VECTOR (mi, section.Methods)\n      {\n        CMethodInfo &method = section.Methods[mi];\n        UInt32 numDWORDS = ReadUInt32();\n        if (method.IsLzx())\n        {\n          if (numDWORDS < 5)\n            return S_FALSE;\n          if (ReadUInt32() != kSignature_LZXC)\n            return S_FALSE;\n          CLzxInfo &li = method.LzxInfo;\n          li.Version = ReadUInt32();\n          if (li.Version != 2 && li.Version != 3)\n            return S_FALSE;\n          \n          {\n            // There is bug in VC6, if we use function call as parameter for inline function\n            const UInt32 val32 = ReadUInt32();\n            const int n = GetLog(val32);\n            if (n < 0 || n > 16)\n              return S_FALSE;\n            li.ResetIntervalBits = (unsigned)n;\n          }\n          \n          {\n            const UInt32 val32 = ReadUInt32();\n            const int n = GetLog(val32);\n            if (n < 0 || n > 16)\n              return S_FALSE;\n            li.WindowSizeBits = (unsigned)n;\n          }\n\n          li.CacheSize = ReadUInt32();\n          numDWORDS -= 5;\n          if (numDWORDS)\n          do\n            ReadUInt32();\n          while (--numDWORDS);\n        }\n        else\n        {\n          if (numDWORDS > 1u << 27)\n            return S_FALSE;\n          const size_t numBytes = (size_t)numDWORDS * 4;\n          // method.ControlData.Alloc(numBytes);\n          // ReadBytes(method.ControlData, numBytes);\n          Skip(numBytes);\n        }\n      }\n    }\n\n    {\n      // SpanInfo\n      RINOK(DecompressStream(inStream, database, sectionPrefix + kSpanInfo))\n      section.UncompressedSize = ReadUInt64();\n    }\n\n    // read ResetTable for LZX\n    FOR_VECTOR (mi, section.Methods)\n    {\n      CMethodInfo &method = section.Methods[mi];\n      if (method.IsLzx())\n      {\n        // ResetTable;\n        RINOK(DecompressStream(inStream, database, transformPrefix +\n            method.GetGuidString() + kResetTable))\n        CResetTable &rt = method.LzxInfo.ResetTable;\n        \n        if (_chunkSize < 4)\n        {\n          if (_chunkSize != 0)\n            return S_FALSE;\n          // ResetTable is empty in .chw files\n          if (section.UncompressedSize != 0)\n            return S_FALSE;\n          rt.UncompressedSize = 0;\n          rt.CompressedSize = 0;\n          // rt.BlockSize = 0;\n        }\n        else\n        {\n          const UInt32 ver = ReadUInt32(); // 2  unknown (possibly a version number)\n          if (ver != 2 && ver != 3)\n            return S_FALSE;\n          const UInt32 numEntries = ReadUInt32();\n          const unsigned kEntrySize = 8;\n          if (ReadUInt32() != kEntrySize)\n            return S_FALSE;\n          const unsigned kRtHeaderSize = 4 * 4 + 8 * 3;\n          if (ReadUInt32() != kRtHeaderSize)\n            return S_FALSE;\n          if (kRtHeaderSize + kEntrySize * (UInt64)numEntries != _chunkSize)\n            return S_FALSE;\n\n          rt.UncompressedSize = ReadUInt64();\n          rt.CompressedSize = ReadUInt64();\n          UInt64 blockSize = ReadUInt64();\n          if (blockSize != kBlockSize)\n            return S_FALSE;\n          UInt64 numBlocks = (rt.UncompressedSize + kBlockSize + 1) / kBlockSize;\n          if (numEntries != numBlocks &&\n              numEntries != numBlocks + 1)\n            return S_FALSE;\n  \n          rt.ResetOffsets.ClearAndReserve(numEntries);\n          \n          for (UInt32 i = 0; i < numEntries; i++)\n          {\n            UInt64 v = ReadUInt64();\n            if (i != 0 && v < rt.ResetOffsets[i - 1])\n              return S_FALSE;\n            rt.ResetOffsets.AddInReserved(v);\n          }\n\n          if (numEntries != 0)\n            if (rt.ResetOffsets[0] != 0)\n              return S_FALSE;\n\n          if (numEntries == numBlocks + 1)\n          {\n            // Lazarus 9-26-2 chm contains additional entty\n            if (rt.ResetOffsets.Back() != rt.CompressedSize)\n              return S_FALSE;\n          }\n        }\n      }\n    }\n  }\n\n  database.SetIndices();\n  database.Sort();\n  return database.Check() ? S_OK : S_FALSE;\n}\n\nHRESULT CInArchive::Open2(IInStream *inStream,\n    const UInt64 *searchHeaderSizeLimit,\n    CFilesDatabase &database)\n{\n  IsArc = false;\n  HeadersError = false;\n  UnexpectedEnd = false;\n  UnsupportedFeature = false;\n\n  database.Clear();\n  database.Help2Format = _help2;\n  const UInt32 chmVersion = 3;\n\n  RINOK(InStream_GetPos(inStream, database.StartPosition))\n\n  if (!_inBuffer.Create(1 << 14))\n    return E_OUTOFMEMORY;\n  _inBuffer.SetStream(inStream);\n  _inBuffer.Init();\n  \n  if (_help2)\n  {\n    const unsigned kSignatureSize = 8;\n    const UInt64 signature = ((UInt64)kSignature_ITLS << 32) | kSignature_ITOL;\n    UInt64 limit = 1 << 18;\n    \n    if (searchHeaderSizeLimit)\n      if (limit > *searchHeaderSizeLimit)\n        limit = *searchHeaderSizeLimit;\n\n    UInt64 val = 0;\n    \n    for (;;)\n    {\n      Byte b;\n      if (!_inBuffer.ReadByte(b))\n        return S_FALSE;\n      val >>= 8;\n      val |= ((UInt64)b) << ((kSignatureSize - 1) * 8);\n      if (_inBuffer.GetProcessedSize() >= kSignatureSize)\n      {\n        if (val == signature)\n          break;\n        if (_inBuffer.GetProcessedSize() > limit)\n          return S_FALSE;\n      }\n    }\n    \n    database.StartPosition += _inBuffer.GetProcessedSize() - kSignatureSize;\n    RINOK(OpenHelp2(inStream, database))\n    if (database.NewFormat)\n      return S_OK;\n  }\n  else\n  {\n    if (ReadUInt32() != kSignature_ITSF)\n      return S_FALSE;\n    if (ReadUInt32() != chmVersion)\n      return S_FALSE;\n    RINOK(OpenChm(inStream, database))\n  }\n\n\n  #ifndef CHM_LOW\n  \n  try\n  {\n    try\n    {\n      HRESULT res = OpenHighLevel(inStream, database);\n      if (res == S_FALSE)\n      {\n        UnsupportedFeature = true;\n        database.HighLevelClear();\n        return S_OK;\n      }\n      RINOK(res)\n      if (!database.CheckSectionRefs())\n        HeadersError = true;\n      database.LowLevel = false;\n    }\n    catch(...)\n    {\n      database.HighLevelClear();\n      throw;\n    }\n  }\n  // catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(CEnexpectedEndException &) { UnexpectedEnd = true; }\n  catch(CHeaderErrorException &) { HeadersError = true; }\n  catch(...) { throw; }\n\n  #endif\n\n  return S_OK;\n}\n\nHRESULT CInArchive::Open(IInStream *inStream,\n    const UInt64 *searchHeaderSizeLimit,\n    CFilesDatabase &database)\n{\n  try\n  {\n    try\n    {\n      HRESULT res = Open2(inStream, searchHeaderSizeLimit, database);\n      m_InStreamRef.Release();\n      return res;\n    }\n    catch(...)\n    {\n      m_InStreamRef.Release();\n      throw;\n    }\n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(CEnexpectedEndException &) { UnexpectedEnd = true; }\n  catch(CHeaderErrorException &) { HeadersError = true; }\n  return S_FALSE;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Chm/ChmIn.h",
    "content": "﻿// Archive/ChmIn.h\n\n#ifndef ZIP7_INC_ARCHIVE_CHM_IN_H\n#define ZIP7_INC_ARCHIVE_CHM_IN_H\n\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyString.h\"\n\n#include \"../../IStream.h\"\n\n#include \"../../Common/InBuffer.h\"\n\nnamespace NArchive {\nnamespace NChm {\n\nstruct CItem\n{\n  UInt64 Section;\n  UInt64 Offset;\n  UInt64 Size;\n  AString Name;\n\n  bool IsFormatRelatedItem() const\n  {\n    if (Name.Len() < 2)\n      return false;\n    return Name[0] == ':' && Name[1] == ':';\n  }\n  \n  bool IsUserItem() const\n  {\n    if (Name.Len() < 2)\n      return false;\n    return Name[0] == '/';\n  }\n  \n  bool IsDir() const\n  {\n    if (Name.IsEmpty())\n      return false;\n    return (Name.Back() == '/');\n  }\n};\n\n\nstruct CDatabase\n{\n  CObjectVector<CItem> Items;\n  UInt64 StartPosition;\n  UInt64 ContentOffset;\n  AString NewFormatString;\n  bool Help2Format;\n  bool NewFormat;\n  UInt64 PhySize;\n\n  void UpdatePhySize(UInt64 v) { if (PhySize < v) PhySize = v; }\n\n  int FindItem(const AString &name) const\n  {\n    FOR_VECTOR (i, Items)\n      if (Items[i].Name == name)\n        return (int)i;\n    return -1;\n  }\n\n  void Clear()\n  {\n    NewFormat = false;\n    NewFormatString.Empty();\n    Help2Format = false;\n    Items.Clear();\n    StartPosition = 0;\n    PhySize = 0;\n  }\n};\n\n\nconst UInt32 kBlockSize = 1 << 15;\n\nstruct CResetTable\n{\n  UInt64 UncompressedSize;\n  UInt64 CompressedSize;\n  // unsigned BlockSizeBits;\n  CRecordVector<UInt64> ResetOffsets;\n  \n  CResetTable():\n      UncompressedSize(0),\n      CompressedSize(0)\n      {}\n\n  bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const\n  {\n    if (blockIndex >= ResetOffsets.Size())\n      return false;\n    UInt64 startPos = ResetOffsets[(unsigned)blockIndex];\n    if (blockIndex + numBlocks >= ResetOffsets.Size())\n      size = CompressedSize - startPos;\n    else\n      size = ResetOffsets[(unsigned)(blockIndex + numBlocks)] - startPos;\n    return true;\n  }\n\n  bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const\n  {\n    return GetCompressedSizeOfBlocks(blockIndex, 1, size);\n  }\n  \n  UInt64 GetNumBlocks(UInt64 size) const\n  {\n    return (size + kBlockSize - 1) / kBlockSize;\n  }\n};\n\n\nstruct CLzxInfo\n{\n  UInt32 Version;\n  \n  unsigned ResetIntervalBits;\n  unsigned WindowSizeBits;\n  UInt32 CacheSize;\n  \n  CResetTable ResetTable;\n\n  CLzxInfo():\n      Version(0),\n      ResetIntervalBits(0),\n      WindowSizeBits(0),\n      CacheSize(0)\n      {}\n\n  unsigned GetNumDictBits() const\n  {\n    if (Version == 2 || Version == 3)\n      return 15 + WindowSizeBits;\n    return 0;\n  }\n\n  UInt64 GetFolderSize() const { return (UInt64)kBlockSize << ResetIntervalBits; }\n  UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); }\n  UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); }\n  UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex << ResetIntervalBits; }\n\n  bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const\n  {\n    const UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);\n    if (blockIndex >= ResetTable.ResetOffsets.Size())\n      return false;\n    offset = ResetTable.ResetOffsets[(unsigned)blockIndex];\n    return true;\n  }\n  \n  bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const\n  {\n    UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);\n    return ResetTable.GetCompressedSizeOfBlocks(blockIndex, (UInt32)1 << ResetIntervalBits, size);\n  }\n};\n\n\nstruct CMethodInfo\n{\n  Byte Guid[16];\n  // CByteBuffer ControlData;\n  CLzxInfo LzxInfo;\n  \n  bool IsLzx() const;\n  bool IsDes() const;\n  AString GetGuidString() const;\n  AString GetName() const;\n};\n\n\nstruct CSectionInfo\n{\n  UInt64 Offset;\n  UInt64 CompressedSize;\n  UInt64 UncompressedSize;\n\n  AString Name;\n  CObjectVector<CMethodInfo> Methods;\n\n  bool IsLzx() const;\n  UString GetMethodName() const;\n};\n\nclass CFilesDatabase: public CDatabase\n{\npublic:\n  CUIntVector Indices;\n  CObjectVector<CSectionInfo> Sections;\n  bool LowLevel;\n\n  UInt64 GetFileSize(unsigned fileIndex) const { return Items[Indices[fileIndex]].Size; }\n  UInt64 GetFileOffset(unsigned fileIndex) const { return Items[Indices[fileIndex]].Offset; }\n\n  UInt64 GetFolder(unsigned fileIndex) const\n  {\n    const CItem &item = Items[Indices[fileIndex]];\n    if (item.Section < Sections.Size())\n    {\n      const CSectionInfo &section = Sections[(unsigned)item.Section];\n      if (section.IsLzx())\n        return section.Methods[0].LzxInfo.GetFolder(item.Offset);\n    }\n    return 0;\n  }\n\n  UInt64 GetLastFolder(unsigned fileIndex) const\n  {\n    const CItem &item = Items[Indices[fileIndex]];\n    if (item.Section < Sections.Size())\n    {\n      const CSectionInfo &section = Sections[(unsigned)item.Section];\n      if (section.IsLzx())\n        return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);\n    }\n    return 0;\n  }\n\n  void HighLevelClear()\n  {\n    LowLevel = true;\n    Indices.Clear();\n    Sections.Clear();\n  }\n\n  void Clear()\n  {\n    CDatabase::Clear();\n    HighLevelClear();\n  }\n  \n  void SetIndices();\n  void Sort();\n  bool Check();\n  bool CheckSectionRefs();\n};\n\n\nclass CInArchive\n{\n  CMyComPtr<ISequentialInStream> m_InStreamRef;\n  ::CInBuffer _inBuffer;\n  UInt64 _chunkSize;\n  bool _help2;\n\n  Byte ReadByte();\n  void ReadBytes(Byte *data, UInt32 size);\n  void Skip(size_t size);\n  UInt16 ReadUInt16();\n  UInt32 ReadUInt32();\n  UInt64 ReadUInt64();\n  UInt64 ReadEncInt();\n  void ReadString(unsigned size, AString &s);\n  void ReadUString(unsigned size, UString &s);\n  void ReadGUID(Byte *g);\n\n  HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);\n\n  HRESULT ReadDirEntry(CDatabase &database);\n  HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name);\n\npublic:\n  bool IsArc;\n  bool HeadersError;\n  bool UnexpectedEnd;\n  bool UnsupportedFeature;\n\n  CInArchive(bool help2) { _help2 = help2; }\n\n  HRESULT OpenChm(IInStream *inStream, CDatabase &database);\n  HRESULT OpenHelp2(IInStream *inStream, CDatabase &database);\n  HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database);\n  HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);\n  HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);\n};\n  \n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Chm/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ComHandler.cpp",
    "content": "﻿// ComHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/ItemNameUtils.h\"\n\n#define Get16(p) GetUi16a(p)\n#define Get32(p) GetUi32a(p)\n\n// we don't expect to get deleted files in real files\n// define Z7_COMPOUND_SHOW_DELETED for debug\n// #define Z7_COMPOUND_SHOW_DELETED\n\nnamespace NArchive {\nnamespace NCom {\n\nstatic const unsigned k_Long_path_level_limit = 256;\n\nstatic const Byte kSignature[] =\n  { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };\n\n// encoded \"[!]MsiPatchSequence\" name in \"msp\" file\nstatic const Byte k_Sequence_msp[] =\n  { 0x40, 0x48, 0x96, 0x45, 0x6c, 0x3e, 0xe4, 0x45,\n    0xe6, 0x42, 0x16, 0x42, 0x37, 0x41, 0x27, 0x41,\n    0x37, 0x41, 0, 0 };\n\n// encoded \"MergeModule.CABinet\" name in \"msm\" file\nstatic const Byte k_Sequence_msm[] =\n  { 0x16, 0x42, 0xb5, 0x42, 0xa8, 0x3d, 0xf2, 0x41,\n    0xf8, 0x43, 0xa8, 0x47, 0x8c, 0x3a, 0x0b, 0x43,\n    0x31, 0x42, 0x37, 0x48, 0, 0 };\n\n// static const Byte k_CLSID_AAF_V3[] = { 0x41, 0x41, 0x46, 0x42, 0x0d, 0x00, 0x4f, 0x4d, 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0xff };\n// static const Byte k_CLSID_AAF_V4[] = { 0x01, 0x02, 0x01, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x06, 0x0e, 0x2b, 0x34, 0x03, 0x02, 0x01, 0x01 };\n\nenum EArcType\n{\n  k_Type_Common,\n  k_Type_Msi,\n  k_Type_Msp,\n  k_Type_Msm,\n  k_Type_Doc,\n  k_Type_Ppt,\n  k_Type_Xls,\n  k_Type_Aaf\n};\n\nstatic const char * const kExtensions[] =\n{\n    \"compound\"\n  , \"msi\"\n  , \"msp\"\n  , \"msm\"\n  , \"doc\"\n  , \"ppt\"\n  , \"xls\"\n  , \"aaf\"\n};\n\nnamespace NFatID\n{\n  static const UInt32 kFree       = 0xffffffff;\n  static const UInt32 kEndOfChain = 0xfffffffe;\n  static const UInt32 kFatSector  = 0xfffffffd;\n  static const UInt32 k_DIF_SECT  = 0xfffffffc; // double-indirect file allocation table (DIFAT)\n  static const UInt32 kMaxValue   = 0xfffffffa;\n}\n\nnamespace NItemType\n{\n  static const unsigned kEmpty = 0;\n  static const unsigned kStorage = 1;\n  static const unsigned kStream = 2;\n  // static const unsigned kLockBytes = 3;\n  // static const unsigned kProperty = 4;\n  static const unsigned kRootStorage = 5;\n}\n\nstatic const unsigned k_MiniSectorSizeBits = 6;\nstatic const UInt32 k_LongStreamMinSize = 1 << 12;\n\nstatic const unsigned k_Msi_NumBits = 6;\nstatic const unsigned k_Msi_NumChars = 1 << k_Msi_NumBits;\nstatic const unsigned k_Msi_CharMask = k_Msi_NumChars - 1;\nstatic const unsigned k_Msi_UnicodeRange = k_Msi_NumChars * (k_Msi_NumChars + 1);\nstatic const unsigned k_Msi_StartUnicodeChar = 0x3800;\nstatic const unsigned k_Msi_SpecUnicodeChar = k_Msi_StartUnicodeChar + k_Msi_UnicodeRange;\n// (k_Msi_SpecUnicodeChar == 0x4840) is used as special symbol that is used\n// as first character in some names in dir entries\n/*\nstatic bool IsMsiName(const Byte *p)\n{\n  unsigned c = Get16(p);\n  c -= k_Msi_StartUnicodeChar;\n  return c <= k_Msi_UnicodeRange;\n}\n*/\n\nZ7_FORCE_INLINE static bool IsLargeStream(UInt64 size)\n{\n  return size >= k_LongStreamMinSize;\n}\n\nstatic const unsigned kNameSizeMax = 64;\nstatic const UInt32 k_Item_Level_Unused = (UInt32)0 - 1;\n\nstruct CItem\n{\n  Byte Name[kNameSizeMax]; // must be aligned for 2-bytes\n  // UInt16 NameSize;\n  // UInt32 Flags;\n  FILETIME CTime;\n  FILETIME MTime;\n  UInt64 Size;\n  UInt32 LeftDid;\n  UInt32 RightDid;\n  UInt32 SonDid;\n  UInt32 Sid;\n  unsigned Type;  // Byte : we use unsigned instead of Byte for alignment\n\n  UInt32 Level;\n\n  bool IsEmptyType() const { return Type == NItemType::kEmpty; }\n  bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; }\n  bool IsStorage() const { return Type == NItemType::kStorage; }\n\n  bool IsLevel_Unused() const { return Level == k_Item_Level_Unused; }\n\n  // bool IsSpecMsiName() const { return Get16(Name) == k_Msi_SpecUnicodeChar; }\n  bool AreMsiChars() const\n  {\n    for (unsigned i = 0; i < kNameSizeMax; i += 2)\n    {\n      unsigned c = Get16(Name + i);\n      if (c == 0)\n        break;\n      c -= k_Msi_StartUnicodeChar;\n      if (c <= k_Msi_UnicodeRange)\n        return true;\n    }\n    return false;\n  }\n  bool Parse(const Byte *p, bool mode64bit);\n};\n\n\nstatic const UInt32 k_Ref_Parent_Root = 0xffffffff;\n\nstruct CRef\n{\n  UInt32 Parent;  // index in  Refs[]\n  UInt32 Did;     // index in  Items[]\n};\n\n\nclass CDatabase\n{\npublic:\n  CRecordVector<CRef> Refs;\n  CObjectVector<CItem> Items;\n  CObjArray<UInt32> Fat;\n  CObjArray<UInt32> Mat;\n  CObjArray<UInt32> MiniSids;\n\n  UInt32 FatSize;\n  UInt32 MatSize;\n  UInt32 NumSectors_in_MiniStream;\n\n  // UInt32 LongStreamMinSize;\n  unsigned SectorSizeBits;\n\n  Int32 MainSubfile;\n  EArcType Type;\n\n  bool IsArc;\n  bool HeadersError;\n  // bool IsMsi;\n\n  UInt64 PhySize;\n  UInt64 PhySize_Unaligned;\n  // UInt64 FreeSize;\n\n  IArchiveOpenCallback *OpenCallback;\n  UInt32 Callback_Cur;\n\nprivate:\n  /*\n  HRESULT IncreaseOpenTotal(UInt32 numSects)\n  {\n    if (!OpenCallback)\n      return S_OK;\n    const UInt64 total = (UInt64)(Callback_Cur + numSects) << SectorSizeBits;\n    return OpenCallback->SetTotal(NULL, &total);\n  }\n  */\n  HRESULT AddNodes();\n  HRESULT ReadSector(IInStream *inStream, Byte *buf, UInt32 sid);\n  HRESULT ReadIDs(IInStream *inStream, Byte *buf, UInt32 sid, UInt32 *dest);\n  HRESULT Check_Item(unsigned index);\n\npublic:\n  bool IsNotArcType() const\n  {\n    return\n      Type != k_Type_Msi &&\n      Type != k_Type_Msp &&\n      Type != k_Type_Msm;\n  }\n\n  void Clear();\n  UString GetItemPath(UInt32 index) const;\n\n  UInt64 GetItemPackSize(UInt64 size) const\n  {\n    const UInt64 mask = ((UInt32)1 << (IsLargeStream(size) ? SectorSizeBits : k_MiniSectorSizeBits)) - 1;\n    return (size + mask) & ~(UInt64)mask;\n  }\n\n  HRESULT Open(IInStream *inStream);\n};\n\n\nHRESULT CDatabase::ReadSector(IInStream *inStream, Byte *buf, UInt32 sid)\n{\n  const unsigned sb = SectorSizeBits;\n  RINOK(InStream_SeekSet(inStream, ((UInt64)sid + 1) << sb))\n  RINOK(ReadStream_FALSE(inStream, buf, (size_t)1 << sb))\n  if (OpenCallback)\n  {\n    if ((++Callback_Cur & 0xfff) == 0)\n    {\n      const UInt64 processed = (UInt64)Callback_Cur << sb;\n      const UInt64 numFiles = Items.Size();\n      RINOK(OpenCallback->SetCompleted(&numFiles, &processed))\n    }\n  }\n  return S_OK;\n}\n\nHRESULT CDatabase::ReadIDs(IInStream *inStream, Byte *buf, UInt32 sid, UInt32 *dest)\n{\n  RINOK(ReadSector(inStream, buf, sid))\n  const size_t sectorSize = (size_t)1 << SectorSizeBits;\n  for (size_t t = 0; t < sectorSize; t += 4)\n    *dest++ = Get32(buf + t);\n  return S_OK;\n}\n\n\nZ7_FORCE_INLINE\nstatic void GetFileTimeFromMem(const Byte *p, FILETIME *ft)\n{\n  ft->dwLowDateTime = Get32(p);\n  ft->dwHighDateTime = Get32(p + 4);\n}\n\nbool CItem::Parse(const Byte *p, bool mode64bit)\n{\n  memcpy(Name, p, kNameSizeMax);\n  unsigned i;\n  for (i = 0; i < kNameSizeMax; i += 2)\n    if (*(const UInt16 *)(const void *)(p + i) == 0)\n      break;\n#if 0 // 1 : for debug : for more strict field check\n  {\n    for (unsigned k = i; k < kNameSizeMax; k += 2)\n      if (*(const UInt16 *)(const void *)(p + k) != 0)\n        return false;\n  }\n#endif\n  Type = p[66];\n  // DOC: names are limited to 32 UTF-16 code points, including the terminating null character.\n  if (!IsEmptyType())\n    if (i == kNameSizeMax || i + 2 != Get16(p + 64)) //  NameLength\n      return false;\n  if (p[67] >= 2)  // Color: 0 (red) or 1 (black)\n    return false;\n  LeftDid = Get32(p + 68);\n  RightDid = Get32(p + 72);\n  SonDid = Get32(p + 76);\n  // if (Get32(p + 96) == 0) return false; // State / Flags\n  GetFileTimeFromMem(p + 100, &CTime);\n  GetFileTimeFromMem(p + 108, &MTime);\n  Sid = Get32(p + 116);\n  Size = Get32(p + 120);\n  /* MS DOC: it is recommended that parsers ignore the most\n     significant 32 bits of this field in version 3 compound files */\n  if (mode64bit)\n    Size |= ((UInt64)Get32(p + 124) << 32);\n  return true;\n}\n\n\nvoid CDatabase::Clear()\n{\n  Type = k_Type_Common;\n  MainSubfile = -1;\n  IsArc = false;\n  HeadersError = false;\n  // IsMsi = false;\n  PhySize = 0;\n  PhySize_Unaligned = 0;\n  // FreeSize = 0;\n  Callback_Cur = 0;\n  // OpenCallback = NULL;\n\n  FatSize = 0;\n  MatSize = 0;\n  NumSectors_in_MiniStream = 0;\n  \n  Fat.Free();\n  Mat.Free();\n  MiniSids.Free();\n  Items.Clear();\n  Refs.Clear();\n}\n\n\nstatic const UInt32 kNoDid = 0xffffffff;\n\nHRESULT CDatabase::AddNodes()\n{\n  UInt32 index = Items[0].SonDid; // Items[0] is root item\n  if (index == kNoDid) // no files case\n    return S_OK;\n  if (index == 0 || index >= Items.Size())\n    return S_FALSE;\n\n  CObjArray<UInt32> itemParents(Items.Size());\n  CByteArr states(Items.Size());\n  memset(itemParents, 0, (size_t)Items.Size() * sizeof(itemParents[0])); // optional\n  memset(states, 0, Items.Size());\n\n#if 1 // 0 : for debug\n  const UInt32 k_exitParent = 0;\n  const UInt32 k_startLevel = 1;\n  // we don't show \"Root Entry\" dir\n  states[0] = 3; // we mark root node as processed, also we block any cycle links to root node\n  // itemParents[0] = 0xffffffff; // optional / unused value\n#else\n  // we show item[0] \"Root Entry\" dir\n  const UInt32 k_exitParent = 0xffffffff;\n  const UInt32 k_startLevel = 0;\n  index = 0;\n#endif\n \n  UInt32 level = k_startLevel; // directory level\n  unsigned state = 0;\n  UInt32 parent = k_exitParent; // in Items[], itemParents[], states[]\n  UInt32 refParent = k_Ref_Parent_Root; // in Refs[]\n\n  for (;;)\n  {\n    if (state >= 3)\n    {\n      // we return to parent node\n      if (state != 3)\n        return E_FAIL;\n      index = parent;\n      if (index == k_exitParent)\n        break;\n      if (index >= Items.Size())\n        return E_FAIL; // (index) was checked already\n      parent = itemParents[index];\n      state = states[index];\n      if (state == 0)\n        return E_FAIL;\n      if (state == 2)\n      {\n        // we return to parent Dir node\n        if (refParent >= Refs.Size())\n          return E_FAIL;\n        refParent = Refs[refParent].Parent;\n        level--;\n      }\n      continue;\n    }\n\n    if (index >= Items.Size())\n      return S_FALSE;\n    CItem &item = Items[index];\n    if (item.IsEmptyType())\n      return S_FALSE;\n    item.Level = level;\n    state++;\n    states[index] = (Byte)state; // we mark current (index) node as used node\n\n    UInt32 newIndex;\n    if (state != 2)\n      newIndex = (state < 2) ? item.LeftDid : item.RightDid;\n    else\n    {\n      CRef ref;\n      ref.Parent = refParent;\n      ref.Did = index;\n      const unsigned refIndex = Refs.Add(ref);\n      if (!item.IsDir())\n        continue;\n      newIndex = item.SonDid;\n      if (newIndex != kNoDid)\n      {\n        level++;\n        refParent = refIndex;\n      }\n    }\n\n    if (newIndex != kNoDid)\n    {\n      itemParents[index] = parent;\n      state = 0;\n      parent = index;\n      index = newIndex;\n      if (index >= Items.Size() || states[index])\n        return S_FALSE;\n    }\n  }\n  \n  if (level != k_startLevel || refParent != k_Ref_Parent_Root)\n    return E_FAIL;\n#if 1 // 1 : optional\n  // we check that all non-empty items were processed correctly\n  FOR_VECTOR(i, Items)\n  {\n    const unsigned st = states[i];\n    if (Items[i].IsEmptyType())\n    {\n      if (st)\n        return E_FAIL;\n    }\n    else if (st == 3)\n      continue;\n    else if (st)\n      return E_FAIL;\n    else\n      return S_FALSE; // there is unused directory item\n  }\n#endif\n  return S_OK;\n}\n\n\nstatic const char k_Msi_Chars[] =\n  \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._\";\nstatic const char k_Msi_SpecChar_Replace = '!';\n\nstatic bool AreEqualNames(const Byte *rawName, const char *asciiName)\n{\n  for (;;)\n  {\n    const unsigned c = Get16(rawName);\n    rawName += 2;\n    const unsigned c2 = (Byte)*asciiName;\n    asciiName++;\n    if (c != c2)\n      return false;\n    if (c2 == 0)\n      return true;\n  }\n}\n\n\nstatic void MsiName_To_FileName(const Byte *p, UString &res)\n{\n  res.Empty();\n  for (unsigned i = 0; i < kNameSizeMax; i += 2)\n  {\n    unsigned c = Get16(p + i);\n    if (c == 0)\n      break;\n    if (c <= k_Msi_SpecUnicodeChar)\n    {\n      if (c < k_Msi_StartUnicodeChar)\n      {\n        if (c < 0x20)\n        {\n          res.Add_Char('[');\n          res.Add_UInt32((UInt32)c);\n          c = ']';\n        }\n      }\n      else\n      {\n#if 0 // 1 : for debug\n        if (i == 0) res += \"{msi}\";\n#endif\n        c -= k_Msi_StartUnicodeChar;\n        const unsigned c1 = (unsigned)c >> k_Msi_NumBits;\n        if (c1 <= k_Msi_NumChars)\n        {\n          res.Add_Char(k_Msi_Chars[(unsigned)c & k_Msi_CharMask]);\n          if (c1 == k_Msi_NumChars)\n            continue;\n          c = (Byte)k_Msi_Chars[c1];\n        }\n        else\n          c = k_Msi_SpecChar_Replace;\n      }\n    }\n    res += (wchar_t)c;\n  }\n}\n\n\nUString CDatabase::GetItemPath(UInt32 index) const\n{\n  UString s;\n  UString name;\n  unsigned level = 0;\n  while (index != k_Ref_Parent_Root)\n  {\n    const CRef &ref = Refs[index];\n    const CItem &item = Items[ref.Did];\n    if (!s.IsEmpty())\n      s.InsertAtFront(WCHAR_PATH_SEPARATOR);\n    // if (IsMsi)\n    MsiName_To_FileName(item.Name, name);\n    // else NonMsiName_To_FileName(item.Name, name);\n    NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);\n    if (name.IsEmpty())\n      name = \"[]\";\n    s.Insert(0, name);\n    index = ref.Parent;\n#ifdef Z7_COMPOUND_SHOW_DELETED\n    if (item.IsLevel_Unused())\n    {\n      s.Insert(0, L\"[DELETED]\" WSTRING_PATH_SEPARATOR);\n      break;\n    }\n#endif\n    if (item.Level >= k_Long_path_level_limit && level)\n    {\n      s.Insert(0, L\"[LONG_PATH]\" WSTRING_PATH_SEPARATOR);\n      break;\n    }\n    level = 1; // level++;\n  }\n  return s;\n}\n\n\nHRESULT CDatabase::Check_Item(unsigned index)\n{\n  const CItem &item = Items[index];\n  if (item.IsEmptyType() || item.IsStorage())\n    return S_OK;\n  UInt64 size = item.Size;\n  const bool isLargeStream = (index == 0 || IsLargeStream(size));\n  if (!isLargeStream)\n  {\n    const unsigned bsLog = k_MiniSectorSizeBits;\n    const UInt32 clusterSize = (UInt32)1 << bsLog;\n    const UInt64 numClusters = (size + clusterSize - 1) >> bsLog;\n    if (numClusters > MatSize)\n      return S_FALSE;\n    UInt32 sid = item.Sid;\n    if (size != 0)\n    {\n      for (;; size -= clusterSize)\n      {\n        if (sid >= MatSize)\n          return S_FALSE;\n        const unsigned subBits = SectorSizeBits - k_MiniSectorSizeBits;\n        const UInt32 fid = sid >> subBits;\n        if (fid >= NumSectors_in_MiniStream)\n          return false;\n        sid = Mat[sid];\n        if (size <= clusterSize)\n          break;\n      }\n    }\n    if (sid != NFatID::kEndOfChain)\n      return S_FALSE;\n  }\n  else\n  {\n    const unsigned bsLog = SectorSizeBits;\n    const UInt32 clusterSize = (UInt32)1 << bsLog;\n    const UInt64 numClusters = (size + clusterSize - 1) >> bsLog;\n    if (numClusters > FatSize)\n      return S_FALSE;\n    UInt32 sid = item.Sid;\n    if (size != 0)\n    {\n      for (;; size -= clusterSize)\n      {\n        if (sid >= FatSize)\n          return S_FALSE;\n        const UInt32 sidPrev = sid;\n        sid = Fat[sid];\n        if (size <= clusterSize)\n        {\n          const UInt64 phySize = (((UInt64)sidPrev + 1) << SectorSizeBits) + size;\n          if (PhySize_Unaligned < phySize)\n              PhySize_Unaligned = phySize;\n          break;\n        }\n      }\n    }\n    if (sid != NFatID::kEndOfChain)\n      return S_FALSE;\n  }\n  return S_OK;\n}\n\n\nHRESULT CDatabase::Open(IInStream *inStream)\n{\n  const unsigned kHeaderSize = 512;\n  UInt32 p32[kHeaderSize / 4];\n  RINOK(ReadStream_FALSE(inStream, p32, kHeaderSize))\n  const Byte *p = (const Byte *)(const void *)p32;\n  if (memcmp(p, kSignature, Z7_ARRAY_SIZE(kSignature)))\n    return S_FALSE;\n  /*\n  if (memcmp(p + 8, k_CLSID_AAF_V3, Z7_ARRAY_SIZE(k_CLSID_AAF_V3)) == 0 ||\n      memcmp(p + 8, k_CLSID_AAF_V4, Z7_ARRAY_SIZE(k_CLSID_AAF_V4)) == 0)\n  */\n  if (Get32(p32 + 4) == 0x342b0e06) // simplified AAF signature check\n    Type = k_Type_Aaf;\n  if (Get16(p + 0x18) != 0x3e) // minorVer\n    return S_FALSE;\n  const unsigned ver = Get16(p + 0x1a); // majorVer\n  if (ver < 3 || ver > 4)\n    return S_FALSE;\n  if (Get16(p + 0x1c) != 0xfffe) // Little-endian\n    return S_FALSE;\n  const unsigned sectorSizeBits = Get16(p + 0x1e);\n  if (sectorSizeBits != ver * 3) // (ver == 3 ? 9 : 12)\n    return S_FALSE;\n  SectorSizeBits = sectorSizeBits;\n  if (Get16(p + 0x20) != k_MiniSectorSizeBits)\n    return S_FALSE;\n\n  IsArc = true;\n  HeadersError = true;\n\n  const bool mode64bit = (sectorSizeBits >= 12); // (ver == 4)\n  if (Get16(p + 0x22) || p32[9]) // reserved\n    return S_FALSE;\n\n  const UInt32 numDirSectors = Get32(p32 + 10);\n  // If (ver==3), the Number of Directory Sectors MUST be zero.\n  if (ver != 3 + (unsigned)(numDirSectors != 0))\n    return S_FALSE;\n  if (numDirSectors > ((1u << (32 - 2)) >> (sectorSizeBits - (7 + 2))))\n    return S_FALSE;\n\n  const UInt32 numSectorsForFAT = Get32(p32 + 11); // SAT\n\n  // MSDOC: A 512-byte sector compound file MUST be no greater than 2 GB in size for compatibility reasons.\n  // but actual restriction for windows compond creation code can be more strict:\n  // (numSectorsForFAT <  (1 << 15)) : actual restriction in win10 for compound creation code\n  // (numSectorsForFAT <= (1 << 15)) : relaxed restriction to allow 2 GB files.\n  if (sectorSizeBits == 9 &&\n      numSectorsForFAT >= (1u << (31 - (9 + 9 - 2)))) // we use most strict check\n    return S_FALSE;\n\n  // const UInt32 TransactionSignatureNumber = Get32(p32 + 13);\n  if (Get32(p32 + 14) != k_LongStreamMinSize)\n    return S_FALSE;\n\n  const unsigned ssb2 = sectorSizeBits - 2;\n  const UInt32 numSidsInSec = (UInt32)1 << ssb2;\n  const UInt32 numFatItems = numSectorsForFAT << ssb2;\n  if (numFatItems == 0 || (numFatItems >> ssb2) != numSectorsForFAT)\n    return S_FALSE;\n\n  const size_t sectSize = (size_t)1 << sectorSizeBits;\n  CByteArr sect(sectSize);\n  CByteArr used(numFatItems);\n  // don't change these const values. These values use same order as (0xffffffff - NFatID::const)\n  // const Byte k_Used_Free = 0;\n  const Byte k_Used_ChainTo = 1;\n  const Byte k_Used_FAT     = 2;\n  const Byte k_Used_DIFAT   = 3;\n  memset(used, 0, numFatItems);\n  UInt32 *fat;\n  {\n    // ========== READ FAT ==========\n    const UInt32 numSectorsForBat = Get32(p32 + 18); // master sector allocation table\n    const unsigned ssb2_m1 = ssb2 - 1;\n    if (numSectorsForBat > ((1u << 30) >> ssb2_m1 >> ssb2_m1))\n      return S_FALSE;\n    const unsigned kNumHeaderBatItems = 109;\n    UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2); // real size can be smaller\n    CObjArray<UInt32> bat(numBatItems);\n    size_t i;\n    for (i = 0; i < kNumHeaderBatItems; i++)\n      bat[i] = Get32(p32 + 19 + i);\n    {\n      UInt32 sid = Get32(p32 + 17);\n      for (UInt32 s = 0; s < numSectorsForBat; s++)\n      {\n        if (sid >= numFatItems || used[sid])\n          return S_FALSE;\n        used[sid] = k_Used_DIFAT;\n        RINOK(ReadIDs(inStream, sect, sid, bat + i))\n        i += numSidsInSec - 1;\n        sid = bat[i];\n      }\n      if (sid != NFatID::kEndOfChain // NFatID::kEndOfChain is expected value for most files\n         && sid != NFatID::kFree)    // NFatID::kFree is used in some AAF files\n        return S_FALSE;\n    }\n    numBatItems = (UInt32)i; // corrected value\n    if (numSectorsForFAT > numBatItems)\n      return S_FALSE;\n    for (i = numSectorsForFAT; i < numBatItems; i++)\n      if (bat[i] != NFatID::kFree)\n        return S_FALSE;\n\n    // RINOK(IncreaseOpenTotal(numSectorsForFAT + numDirSectors))\n\n    Fat.Alloc(numFatItems);\n    fat = Fat;\n    for (i = 0; i < numSectorsForFAT; i++)\n    {\n      const UInt32 sectorIndex = bat[i];\n      if (sectorIndex >= numFatItems)\n        return S_FALSE;\n      if (used[sectorIndex])\n        return S_FALSE;\n      used[sectorIndex] = k_Used_FAT;\n      UInt32 *fat2 = fat + ((size_t)i << ssb2);\n      RINOK(ReadIDs(inStream, sect, sectorIndex, fat2))\n      for (size_t k = 0; k < numSidsInSec; k++)\n      {\n        const UInt32 sid = fat2[k];\n        if (sid > NFatID::kMaxValue)\n        {\n          if (sid == NFatID::k_DIF_SECT\n            && used[((size_t)i << ssb2) + k] != k_Used_DIFAT)\n              return S_FALSE;\n          continue;\n        }\n        if (sid >= numFatItems || used[sid])\n          return S_FALSE; // strict error check\n        used[sid] = k_Used_ChainTo;\n      }\n    }\n    {\n      for (i = 0; i < numSectorsForFAT; i++)\n        if (fat[bat[i]] != NFatID::kFatSector)\n          return S_FALSE;\n    }\n    FatSize = numFatItems;\n  }\n\n  {\n    size_t i = numFatItems;\n    do\n      if (fat[i - 1] != NFatID::kFree)\n        break;\n    while (--i);\n    PhySize = ((UInt64)i + 1) << sectorSizeBits;\n    /*\n    if (i)\n    {\n      const UInt32 *lim = fat + i;\n      UInt32 num = 0;\n      do\n        if (*fat++ == NFatID::kFree)\n          num++;\n      while (fat != lim);\n      FreeSize = num << sectorSizeBits;\n    }\n    */\n  }\n\n  UInt32 numMatItems;\n  {\n    // ========== READ MAT ==========\n    const UInt32 numSectorsForMat = Get32(p32 + 16);\n    numMatItems = (UInt32)numSectorsForMat << ssb2;\n    if ((numMatItems >> ssb2) != numSectorsForMat)\n      return S_FALSE;\n    Mat.Alloc(numMatItems);\n    UInt32 sid = Get32(p32 + 15); // short-sector table SID\n    if (numMatItems)\n    {\n      if (sid >= numFatItems || used[sid])\n        return S_FALSE;\n      used[sid] = k_Used_ChainTo;\n    }\n    for (UInt32 i = 0; i < numMatItems; i += numSidsInSec)\n    {\n      if (sid >= numFatItems)\n        return S_FALSE;\n      RINOK(ReadIDs(inStream, sect, sid, Mat + i))\n      sid = fat[sid];\n    }\n    if (sid != NFatID::kEndOfChain)\n      return S_FALSE;\n  }\n\n  {\n    // ========== READ DIR ITEMS ==========\n    UInt32 sid = Get32(p32 + 12); // directory stream SID\n    UInt32 numDirSectors_Processed = 0;\n    if (sid >= numFatItems || used[sid])\n      return S_FALSE;\n    used[sid] = k_Used_ChainTo;\n    do\n    {\n      // we need to check sid here becase kEndOfChain sid < numFatItems is required\n      if (sid >= numFatItems)\n        return S_FALSE;\n      if (numDirSectors && numDirSectors_Processed >= numDirSectors)\n        return S_FALSE;\n      numDirSectors_Processed++;\n      RINOK(ReadSector(inStream, sect, sid))\n      for (size_t i = 0; i < sectSize; i += (1 << 7))\n      {\n        CItem item;\n        item.Level = k_Item_Level_Unused;\n        if (!item.Parse(sect + i, mode64bit))\n          return S_FALSE;\n        // we use (item.Size) check here.\n        // so we don't need additional overflow checks for (item.Size +) in another code\n        if ((UInt32)(item.Size >> 32) >= sectSize) // it's because FAT size is limited by (1 << 32) items.\n          return S_FALSE;\n\n        if (Items.IsEmpty())\n        {\n          if (item.Type != NItemType::kRootStorage\n              || item.LeftDid != kNoDid\n              || item.RightDid != kNoDid\n              || item.SonDid == 0)\n            return S_FALSE;\n          if (item.Sid != NFatID::kEndOfChain)\n          {\n            if (item.Sid >= numFatItems || used[item.Sid])\n              return S_FALSE;\n            used[item.Sid] = k_Used_ChainTo;\n          }\n        }\n        else if (item.IsStorage())\n        {\n          if (item.Size != 0) // by specification\n            return S_FALSE;\n          if (item.Sid != 0   // by specification\n              && item.Sid != NFatID::kFree) // NFatID::kFree is used in some AAF files\n            return S_FALSE;\n        }\n        // else if (item.Type == NItemType::kRootStorage) return S_FALSE;\n        else if (item.IsEmptyType())\n        {\n          // kNoDid is expected in *Did fileds, but rare case MSI contains zero in all fields\n          if ((item.Sid != 0  // expected value\n                && item.Sid != NFatID::kFree  // NFatID::kFree is used in some AAF files\n                && item.Sid != NFatID::kEndOfChain) // used by some MSI file\n              || (item.LeftDid  != kNoDid && item.LeftDid)\n              || (item.RightDid != kNoDid && item.RightDid)\n              || (item.SonDid   != kNoDid && item.SonDid)\n            // || item.Size != 0         // the check is disabled because some MSI file contains non zero\n            // || Get16(item.Name) != 0  // the check is disabled because some MSI file contains some name\n              )\n            return S_FALSE;\n        }\n        else\n        {\n          if (item.Type != NItemType::kStream)\n            return S_FALSE;\n          // NItemType::kStream case\n          if (item.SonDid != kNoDid) // optional check\n            return S_FALSE;\n          if (item.Size == 0)\n          {\n            if (item.Sid != NFatID::kEndOfChain)\n              return S_FALSE;\n          }\n          else if (IsLargeStream(item.Size))\n          {\n            if (item.Sid >= numFatItems || used[item.Sid])\n              return S_FALSE;\n            used[item.Sid] = k_Used_ChainTo;\n          }\n        }\n\n        Items.Add(item);\n      }\n      sid = fat[sid];\n    }\n    while (sid != NFatID::kEndOfChain);\n  }\n\n  {\n    // root stream contains all data that stored with mini Sectors\n    const CItem &root = Items[0];\n    UInt32 numSectorsInMiniStream;\n    {\n      const UInt64 numSatSects64 = (root.Size + sectSize - 1) >> sectorSizeBits;\n      if (numSatSects64 > NFatID::kMaxValue + 1)\n        return S_FALSE;\n      numSectorsInMiniStream = (UInt32)numSatSects64;\n    }\n    {\n      const UInt64 matSize64 = (root.Size + (1 << k_MiniSectorSizeBits) - 1) >> k_MiniSectorSizeBits;\n      if (matSize64 > numMatItems)\n        return S_FALSE;\n      MatSize = (UInt32)matSize64;\n    }\n    MiniSids.Alloc(numSectorsInMiniStream);\n    UInt32 * const miniSids = MiniSids;\n    UInt32 sid = root.Sid;\n    for (UInt32 i = 0; ; i++)\n    {\n      if (sid == NFatID::kEndOfChain)\n      {\n        if (i != numSectorsInMiniStream)\n          return S_FALSE;\n        break;\n      }\n      if (i >= numSectorsInMiniStream)\n        return S_FALSE;\n      if (sid >= numFatItems)\n        return S_FALSE;\n      miniSids[i] = sid;\n      sid = fat[sid];\n    }\n    NumSectors_in_MiniStream = numSectorsInMiniStream;\n  }\n\n\n  {\n/*\n  MS DOCs:\n    The range lock sector covers file offsets 0x7FFFFF00-0x7FFFFFFF.\n    These offsets are reserved for byte-range locking to support\n    concurrency, transactions, and other compound file features.\n    The range lock sector MUST be allocated in the FAT and marked with\n    ENDOFCHAIN (0xFFFFFFFE), when the compound file grows beyond 2 GB.\n    If the compound file is greater than 2 GB and then shrinks to below 2 GB,\n    the range lock sector SHOULD be marked as FREESECT (0xFFFFFFFF) in the FAT.\n*/\n    {\n      const UInt32 lockSector = (0x7fffffff >> sectorSizeBits) - 1;\n      if (lockSector < numFatItems)\n      {\n        if (used[lockSector])\n          return S_FALSE;\n        const UInt32 f = fat[lockSector];\n        if (f == NFatID::kEndOfChain)\n          used[lockSector] = k_Used_ChainTo; // we use fake state to pass the check in loop below\n        else if (f != NFatID::kFree)\n          return S_FALSE;\n      }\n    }\n    for (size_t i = 0; i < numFatItems; i++)\n    {\n      UInt32 f = fat[i];\n      const UInt32 u = ~(UInt32)used[i]; // (0xffffffff - used[i])\n      if (f < NFatID::kMaxValue + 1)\n        f = NFatID::kEndOfChain;\n      if (f != u)\n        return S_FALSE;\n    }\n  }\n\n  {\n    // Don't move that code up, becase Check_Item uses Mat[] array.\n    FOR_VECTOR(t, Items)\n    {\n      RINOK(Check_Item(t))\n    }\n  }\n\n  RINOK(AddNodes())\n\n  {\n    // some msi (in rare cases) have unaligned size of archive,\n    // unaligned size of compond files is also possible if we create just one stream\n    // where there is no padding data after payload data in last cluster of archive\n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize))\n    if (   fileSize < PhySize\n        && fileSize > PhySize - sectSize\n        && fileSize >= PhySize_Unaligned\n        && PhySize_Unaligned > PhySize - sectSize)\n      PhySize = PhySize_Unaligned;\n  }\n    \n  bool isMsi = false;\n  {\n    FOR_VECTOR (i, Refs)\n    {\n      const CItem &item = Items[Refs[i].Did];\n      if (item.IsDir())\n        continue;\n      if (item.AreMsiChars())\n      // if (item.IsSpecMsiName())\n      {\n        isMsi = true;\n        break;\n      }\n    }\n  }\n\n  // IsMsi = isMsi;\n  if (isMsi)\n  {\n    unsigned numCabs = 0;\n    UString name;\n    FOR_VECTOR (i, Refs)\n    {\n      const CItem &item = Items[Refs[i].Did];\n      if (item.IsDir() /* || item.IsSpecMsiName() */)\n        continue;\n      MsiName_To_FileName(item.Name, name);\n      if ( (name.Len() >= 4 && StringsAreEqualNoCase_Ascii(name.RightPtr(4), \".cab\"))\n        || (name.Len() >= 3 && StringsAreEqualNoCase_Ascii(name.RightPtr(3), \"exe\"))\n        )\n      {\n        numCabs++;\n        if (numCabs > 1)\n        {\n          MainSubfile = -1;\n          break;\n        }\n        MainSubfile = (int)i;\n      }\n    }\n  }\n\n  if (isMsi) // we provide msi priority over AAF\n    Type = k_Type_Msi;\n  if (Type != k_Type_Aaf)\n  {\n    FOR_VECTOR (i, Refs)\n    {\n      const CItem &item = Items[Refs[i].Did];\n      if (item.IsDir())\n        continue;\n      const Byte *name = item.Name;\n      // if (IsMsiName(name))\n      if (isMsi)\n      {\n        if (memcmp(name, k_Sequence_msp, sizeof(k_Sequence_msp)) == 0)\n        {\n          Type = k_Type_Msp;\n          break;\n        }\n        if (memcmp(name, k_Sequence_msm, sizeof(k_Sequence_msm)) == 0)\n        {\n          Type = k_Type_Msm;\n          break;\n        }\n      }\n      else\n      {\n        if (AreEqualNames(name, \"WordDocument\"))\n        {\n          Type = k_Type_Doc;\n          break;\n        }\n        if (AreEqualNames(name, \"PowerPoint Document\"))\n        {\n          Type = k_Type_Ppt;\n          break;\n        }\n        if (AreEqualNames(name, \"Workbook\"))\n        {\n          Type = k_Type_Xls;\n          break;\n        }\n      }\n    }\n  }\n\n#ifdef Z7_COMPOUND_SHOW_DELETED\n  {\n    // we skip Items[0] that is root item\n    for (unsigned t = 1; t < Items.Size(); t++)\n    {\n      const CItem &item = Items[t];\n      if (\n#if 1 // 0 for debug to show empty files\n          item.IsEmptyType() ||\n#endif\n          !item.IsLevel_Unused())\n        continue;\n      CRef ref;\n      ref.Parent = k_Ref_Parent_Root;\n      ref.Did = t;\n      Refs.Add(ref);\n    }\n  }\n#endif\n\n  HeadersError = false;\n  return S_OK;\n}\n\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CMyComPtr<IInStream> _stream;\n  CDatabase _db;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidCTime,\n  kpidMTime\n  // , kpidCharacts // for debug\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidExtension,\n  kpidClusterSize\n  // , kpidSectorSize\n  // , kpidFreeSpace\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidExtension: prop = kExtensions[(unsigned)_db.Type]; break;\n    case kpidPhySize: prop = _db.PhySize; break;\n    case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;\n    // case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;\n    case kpidMainSubfile: if (_db.MainSubfile >= 0) prop = (UInt32)_db.MainSubfile; break;\n    // case kpidFreeSpace: prop = _db.FreeSize; break;\n    case kpidIsNotArcType: if (_db.IsNotArcType()) prop = true; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_db.IsArc)\n        v |= kpv_ErrorFlags_IsNotArc;\n      if (_db.HeadersError)\n        v |= kpv_ErrorFlags_HeadersError;\n      prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CRef &ref = _db.Refs[index];\n  const CItem &item = _db.Items[ref.Did];\n    \n  switch (propID)\n  {\n    case kpidPath:  prop = _db.GetItemPath(index); break;\n    case kpidIsDir:  prop = item.IsDir(); break;\n    case kpidCTime:  prop = item.CTime; break;\n    case kpidMTime:  prop = item.MTime; break;\n    case kpidPackSize:  if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break;\n    case kpidSize:  if (!item.IsDir()) prop = item.Size; break;\n    // case kpidCharacts:  prop = item.Level; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback *openArchiveCallback))\n{\n  COM_TRY_BEGIN\n  Close();\n  _db.OpenCallback = openArchiveCallback;\n  // try\n  {\n    RINOK(_db.Open(inStream))\n    _stream = inStream;\n  }\n  // catch(...) { return S_FALSE; }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _db.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _db.Refs.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt32 i;\n  UInt64 totalSize = 0;\n  for (i = 0; i < numItems; i++)\n  {\n    const CItem &item = _db.Items[_db.Refs[allFilesMode ? i : indices[i]].Did];\n    if (!item.IsDir())\n      totalSize += item.Size;\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 totalPackSize;\n  totalSize = totalPackSize = 0;\n  \n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = totalPackSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem &item = _db.Items[_db.Refs[index].Did];\n    Int32 res;\n    {\n      CMyComPtr<ISequentialOutStream> outStream;\n      const Int32 askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      RINOK(extractCallback->GetStream(index, &outStream, askMode))\n        \n      if (item.IsDir())\n      {\n        RINOK(extractCallback->PrepareOperation(askMode))\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        continue;\n      }\n      \n      totalPackSize += _db.GetItemPackSize(item.Size);\n      totalSize += item.Size;\n      \n      if (!testMode && !outStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      res = NExtract::NOperationResult::kDataError;\n      CMyComPtr<ISequentialInStream> inStream;\n      const HRESULT hres = GetStream(index, &inStream);\n      if (hres == S_FALSE)\n        res = NExtract::NOperationResult::kDataError;\n      /*\n      else if (hres == E_NOTIMPL)\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n      */\n      else\n      {\n        RINOK(hres)\n        if (inStream)\n        {\n          RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))\n          if (copyCoder->TotalSize == item.Size)\n            res = NExtract::NOperationResult::kOK;\n        }\n      }\n    }\n    RINOK(extractCallback->SetOperationResult(res))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _db.Refs.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  const UInt32 itemIndex = _db.Refs[index].Did;\n  const CItem &item = _db.Items[itemIndex];\n  if (item.IsDir())\n    return S_FALSE;\n  const bool isLargeStream = (itemIndex == 0 || IsLargeStream(item.Size));\n  if (!isLargeStream)\n  {\n    CBufferInStream *streamSpec = new CBufferInStream;\n    CMyComPtr<IInStream> streamTemp = streamSpec;\n\n    UInt32 size = (UInt32)item.Size;\n    streamSpec->Buf.Alloc(size);\n    streamSpec->Init();\n\n    UInt32 sid = item.Sid;\n    Byte *dest = streamSpec->Buf;\n\n    UInt64 phyPos = 0;\n    while (size)\n    {\n      if (sid >= _db.MatSize)\n        return S_FALSE;\n      const unsigned subBits = _db.SectorSizeBits - k_MiniSectorSizeBits;\n      const UInt32 fid = sid >> subBits;\n      if (fid >= _db.NumSectors_in_MiniStream)\n        return false;\n      const UInt64 offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) +\n          ((sid & ((1u << subBits) - 1)) << k_MiniSectorSizeBits);\n      if (phyPos != offset)\n      {\n        RINOK(InStream_SeekSet(_stream, offset))\n        phyPos = offset;\n      }\n      UInt32 readSize = (UInt32)1 << k_MiniSectorSizeBits;\n      if (readSize > size)\n          readSize = size;\n      RINOK(ReadStream_FALSE(_stream, dest, readSize))\n      phyPos += readSize;\n      dest += readSize;\n      sid = _db.Mat[sid];\n      size -= readSize;\n    }\n    if (sid != NFatID::kEndOfChain)\n      return S_FALSE;\n    *stream = streamTemp.Detach();\n    return S_OK;\n  }\n\n  CClusterInStream *streamSpec = new CClusterInStream;\n  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\n  streamSpec->Stream = _stream;\n  streamSpec->StartOffset = 0;\n  const unsigned bsLog = _db.SectorSizeBits;\n  streamSpec->BlockSizeLog = bsLog;\n  streamSpec->Size = item.Size;\n\n  const UInt32 clusterSize = (UInt32)1 << bsLog;\n  const UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog;\n  if (numClusters64 > _db.FatSize)\n    return S_FALSE;\n  streamSpec->Vector.ClearAndReserve((unsigned)numClusters64);\n  UInt32 sid = item.Sid;\n  UInt64 size = item.Size;\n\n  if (size != 0)\n  {\n    for (;; size -= clusterSize)\n    {\n      if (sid >= _db.FatSize)\n        return S_FALSE;\n      streamSpec->Vector.AddInReserved(sid + 1);\n      sid = _db.Fat[sid];\n      if (size <= clusterSize)\n        break;\n    }\n  }\n  if (sid != NFatID::kEndOfChain)\n    return S_FALSE;\n  RINOK(streamSpec->InitAndSeek())\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"Compound\", \"msi msp msm doc xls ppt aaf\", NULL, 0xe5,\n  kSignature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/CoderMixer2.cpp",
    "content": "﻿// CoderMixer2.cpp\n\n#include \"StdAfx.h\"\n\n#include \"CoderMixer2.h\"\n\n#ifdef USE_MIXER_ST\n\nZ7_COM7F_IMF(CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessed = 0;\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Read(data, size, &realProcessed);\n  _size += realProcessed;\n  if (size != 0 && realProcessed == 0)\n    _wasFinished = true;\n  if (processedSize)\n    *processedSize = realProcessed;\n  return result;\n}\n\n\nZ7_COM7F_IMF(COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  _size += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\nZ7_COM7F_IMF(COutStreamCalcSize::OutStreamFinish())\n{\n  HRESULT result = S_OK;\n  if (_stream)\n  {\n    CMyComPtr<IOutStreamFinish> outStreamFinish;\n    _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish);\n    if (outStreamFinish)\n      result = outStreamFinish->OutStreamFinish();\n  }\n  return result;\n}\n\n#endif\n\n\n\n\nnamespace NCoderMixer2 {\n\nstatic void BoolVector_Fill_False(CBoolVector &v, unsigned size)\n{\n  v.ClearAndSetSize(size);\n  bool *p = &v[0];\n  for (unsigned i = 0; i < size; i++)\n    p[i] = false;\n}\n\n\nHRESULT CCoder::CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const\n{\n  if (Coder)\n  {\n    if (PackSizePointers.IsEmpty() || !PackSizePointers[0])\n      return S_OK;\n    CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;\n    Coder.QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);\n    // if (!getInStreamProcessedSize) return E_FAIL;\n    if (getInStreamProcessedSize)\n    {\n      UInt64 processed;\n      RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed))\n      if (processed != (UInt64)(Int64)-1)\n      {\n        const UInt64 size = PackSizes[0];\n        if (processed < size && Finish)\n          dataAfterEnd_Error = true;\n        if (processed > size)\n        {\n          // InternalPackSizeError = true;\n          // return S_FALSE;\n        }\n      }\n    }\n  }\n  else if (Coder2)\n  {\n    CMyComPtr<ICompressGetInStreamProcessedSize2> getInStreamProcessedSize2;\n    Coder2.QueryInterface(IID_ICompressGetInStreamProcessedSize2, (void **)&getInStreamProcessedSize2);\n    if (getInStreamProcessedSize2)\n    FOR_VECTOR (i, PackSizePointers)\n    {\n      if (!PackSizePointers[i])\n        continue;\n      UInt64 processed;\n      RINOK(getInStreamProcessedSize2->GetInStreamProcessedSize2(i, &processed))\n      if (processed != (UInt64)(Int64)-1)\n      {\n        const UInt64 size = PackSizes[i];\n        if (processed < size && Finish)\n          dataAfterEnd_Error = true;\n        else if (processed > size)\n        {\n          // InternalPackSizeError = true;\n          // return S_FALSE;\n        }\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\n\nclass CBondsChecks\n{\n  CBoolVector _coderUsed;\n\n  bool Init();\n  bool CheckCoder(unsigned coderIndex);\npublic:\n  const CBindInfo *BindInfo;\n\n  bool Check();\n};\n\nbool CBondsChecks::CheckCoder(unsigned coderIndex)\n{\n  const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex];\n\n  if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex])\n    return false;\n  _coderUsed[coderIndex] = true;\n  \n  const UInt32 start = BindInfo->Coder_to_Stream[coderIndex];\n\n  for (unsigned i = 0; i < coder.NumStreams; i++)\n  {\n    UInt32 ind = start + i;\n    \n    if (BindInfo->IsStream_in_PackStreams(ind))\n      continue;\n    \n    const int bond = BindInfo->FindBond_for_PackStream(ind);\n    if (bond < 0)\n      return false;\n    if (!CheckCoder(BindInfo->Bonds[(unsigned)bond].UnpackIndex))\n      return false;\n  }\n  \n  return true;\n}\n\nbool CBondsChecks::Check()\n{\n  BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size());\n  \n  if (!CheckCoder(BindInfo->UnpackCoder))\n    return false;\n\n  FOR_VECTOR(i, _coderUsed)\n    if (!_coderUsed[i])\n      return false;\n\n  return true;\n}\n\nvoid CBindInfo::ClearMaps()\n{\n  Coder_to_Stream.Clear();\n  Stream_to_Coder.Clear();\n}\n\nbool CBindInfo::CalcMapsAndCheck()\n{\n  ClearMaps();\n\n  UInt32 numStreams = 0;\n\n  if (Coders.Size() == 0)\n    return false;\n  if (Coders.Size() - 1 != Bonds.Size())\n    return false;\n\n  FOR_VECTOR(i, Coders)\n  {\n    Coder_to_Stream.Add(numStreams);\n    \n    const CCoderStreamsInfo &c = Coders[i];\n    \n    for (unsigned j = 0; j < c.NumStreams; j++)\n      Stream_to_Coder.Add(i);\n\n    numStreams += c.NumStreams;\n  }\n\n  if (numStreams != GetNum_Bonds_and_PackStreams())\n    return false;\n\n  CBondsChecks bc;\n  bc.BindInfo = this;\n  return bc.Check();\n}\n\n\nvoid CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish)\n{\n  Finish = finish;\n\n  if (unpackSize)\n  {\n    UnpackSize = *unpackSize;\n    UnpackSizePointer = &UnpackSize;\n  }\n  else\n  {\n    UnpackSize = 0;\n    UnpackSizePointer = NULL;\n  }\n  \n  PackSizes.ClearAndSetSize((unsigned)NumStreams);\n  PackSizePointers.ClearAndSetSize((unsigned)NumStreams);\n  \n  for (unsigned i = 0; i < NumStreams; i++)\n  {\n    if (packSizes && packSizes[i])\n    {\n      PackSizes[i] = *(packSizes[i]);\n      PackSizePointers[i] = &PackSizes[i];\n    }\n    else\n    {\n      PackSizes[i] = 0;\n      PackSizePointers[i] = NULL;\n    }\n  }\n}\n\nbool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex)\n{\n  if (coderIndex == _bi.UnpackCoder)\n    return true;\n  \n  const int bond = _bi.FindBond_for_UnpackStream(coderIndex);\n  if (bond < 0)\n    throw 20150213;\n  \n  /*\n  UInt32 coderIndex, coderStreamIndex;\n  _bi.GetCoder_for_Stream(_bi.Bonds[(unsigned)bond].PackIndex, coderIndex, coderStreamIndex);\n  */\n  const UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[(unsigned)bond].PackIndex];\n  \n  if (!IsFilter_Vector[nextCoder])\n    return false;\n  \n  return Is_UnpackSize_Correct_for_Coder(nextCoder);\n}\n\nbool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex)\n{\n  if (_bi.IsStream_in_PackStreams(streamIndex))\n    return true;\n  \n  const int bond = _bi.FindBond_for_PackStream(streamIndex);\n  if (bond < 0)\n    throw 20150213;\n\n  const UInt32 nextCoder = _bi.Bonds[(unsigned)bond].UnpackIndex;\n\n  if (!IsFilter_Vector[nextCoder])\n    return false;\n  \n  return Is_PackSize_Correct_for_Coder(nextCoder);\n}\n\nbool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex)\n{\n  const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];\n  const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;\n  for (UInt32 i = 0; i < numStreams; i++)\n    if (!Is_PackSize_Correct_for_Stream(startIndex + i))\n      return false;\n  return true;\n}\n\nbool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex)\n{\n  if (IsExternal_Vector[coderIndex])\n    return true;\n  const UInt32 startIndex = _bi.Coder_to_Stream[coderIndex];\n  const UInt32 numStreams = _bi.Coders[coderIndex].NumStreams;\n  for (UInt32 i = 0; i < numStreams; i++)\n  {\n    const UInt32 si = startIndex + i;\n    if (_bi.IsStream_in_PackStreams(si))\n      continue;\n  \n    const int bond = _bi.FindBond_for_PackStream(si);\n    if (bond < 0)\n      throw 20150213;\n\n    if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[(unsigned)bond].UnpackIndex))\n      return true;\n  }\n  return false;\n}\n\n\n\n\n#ifdef USE_MIXER_ST\n\nCMixerST::CMixerST(bool encodeMode):\n    CMixer(encodeMode)\n    {}\n\nCMixerST::~CMixerST() {}\n\nvoid CMixerST::AddCoder(const CCreatedCoder &cod)\n{\n  IsFilter_Vector.Add(cod.IsFilter);\n  IsExternal_Vector.Add(cod.IsExternal);\n  // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];\n  CCoderST &c2 = _coders.AddNew();\n  c2.NumStreams = cod.NumStreams;\n  c2.Coder = cod.Coder;\n  c2.Coder2 = cod.Coder2;\n\n  /*\n  if (isFilter)\n  {\n    c2.CanRead = true;\n    c2.CanWrite = true;\n  }\n  else\n  */\n  {\n    IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2);\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(ISequentialInStream, s, unk)\n      c2.CanRead = (s != NULL);\n    }\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(ISequentialOutStream, s, unk)\n      c2.CanWrite = (s != NULL);\n    }\n  }\n}\n\nCCoder &CMixerST::GetCoder(unsigned index)\n{\n  return _coders[index];\n}\n\nHRESULT CMixerST::ReInit2() { return S_OK; }\n\nHRESULT CMixerST::GetInStream2(\n    ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */\n    UInt32 outStreamIndex, ISequentialInStream **inStreamRes)\n{\n  UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0;\n\n  if (EncodeMode)\n  {\n    _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex);\n    if (coderStreamIndex != 0)\n      return E_NOTIMPL;\n  }\n\n  const CCoder &coder = _coders[coderIndex];\n  \n  CMyComPtr<ISequentialInStream> seqInStream;\n  coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream);\n  if (!seqInStream)\n    return E_NOTIMPL;\n\n  const UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams;\n  const UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex];\n\n  bool isSet = false;\n  \n  if (numInStreams == 1)\n  {\n    CMyComPtr<ICompressSetInStream> setStream;\n    coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream);\n    if (setStream)\n    {\n      CMyComPtr<ISequentialInStream> seqInStream2;\n      RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2))\n      RINOK(setStream->SetInStream(seqInStream2))\n      isSet = true;\n    }\n  }\n  \n  if (!isSet && numInStreams != 0)\n  {\n    CMyComPtr<ICompressSetInStream2> setStream2;\n    coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2);\n    if (!setStream2)\n      return E_NOTIMPL;\n    \n    for (UInt32 i = 0; i < numInStreams; i++)\n    {\n      CMyComPtr<ISequentialInStream> seqInStream2;\n      RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2))\n      RINOK(setStream2->SetInStream2(i, seqInStream2))\n    }\n  }\n\n  *inStreamRes = seqInStream.Detach();\n  return S_OK;\n}\n\n\nHRESULT CMixerST::GetInStream(\n    ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */\n    UInt32 inStreamIndex, ISequentialInStream **inStreamRes)\n{\n  CMyComPtr<ISequentialInStream> seqInStream;\n  \n  {\n    int index = -1;\n    if (EncodeMode)\n    {\n      if (_bi.UnpackCoder == inStreamIndex)\n        index = 0;\n    }\n    else\n      index = _bi.FindStream_in_PackStreams(inStreamIndex);\n\n    if (index >= 0)\n    {\n      seqInStream = inStreams[(unsigned)index];\n      *inStreamRes = seqInStream.Detach();\n      return S_OK;\n    }\n  }\n  \n  const int bond = FindBond_for_Stream(\n      true, // forInputStream\n      inStreamIndex);\n  if (bond < 0)\n    return E_INVALIDARG;\n\n  RINOK(GetInStream2(inStreams, /* inSizes, */\n      _bi.Bonds[(unsigned)bond].Get_OutIndex(EncodeMode), &seqInStream))\n\n  while (_binderStreams.Size() <= (unsigned)bond)\n    _binderStreams.AddNew();\n  CStBinderStream &bs = _binderStreams[(unsigned)bond];\n\n  if (bs.StreamRef || bs.InStreamSpec)\n    return E_NOTIMPL;\n  \n  CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize;\n  bs.StreamRef = spec;\n  bs.InStreamSpec = spec;\n  \n  spec->SetStream(seqInStream);\n  spec->Init();\n  \n  seqInStream = bs.InStreamSpec;\n\n  *inStreamRes = seqInStream.Detach();\n  return S_OK;\n}\n\n\nHRESULT CMixerST::GetOutStream(\n    ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */\n    UInt32 outStreamIndex, ISequentialOutStream **outStreamRes)\n{\n  CMyComPtr<ISequentialOutStream> seqOutStream;\n  \n  {\n    int index = -1;\n    if (!EncodeMode)\n    {\n      if (_bi.UnpackCoder == outStreamIndex)\n        index = 0;\n    }\n    else\n      index = _bi.FindStream_in_PackStreams(outStreamIndex);\n\n    if (index >= 0)\n    {\n      seqOutStream = outStreams[(unsigned)index];\n      *outStreamRes = seqOutStream.Detach();\n      return S_OK;\n    }\n  }\n  \n  const int bond = FindBond_for_Stream(\n      false, // forInputStream\n      outStreamIndex);\n  if (bond < 0)\n    return E_INVALIDARG;\n\n  const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);\n\n  UInt32 coderIndex = inStreamIndex;\n  UInt32 coderStreamIndex = 0;\n\n  if (!EncodeMode)\n    _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);\n\n  CCoder &coder = _coders[coderIndex];\n\n  /*\n  if (!coder.Coder)\n    return E_NOTIMPL;\n  */\n\n  coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream);\n  if (!seqOutStream)\n    return E_NOTIMPL;\n\n  const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;\n  const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;\n\n  bool isSet = false;\n\n  if (numOutStreams == 1)\n  {\n    CMyComPtr<ICompressSetOutStream> setOutStream;\n    coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);\n    if (setOutStream)\n    {\n      CMyComPtr<ISequentialOutStream> seqOutStream2;\n      RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2))\n      RINOK(setOutStream->SetOutStream(seqOutStream2))\n      isSet = true;\n    }\n  }\n\n  if (!isSet && numOutStreams != 0)\n  {\n    return E_NOTIMPL;\n    /*\n    CMyComPtr<ICompressSetOutStream2> setStream2;\n    coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2);\n    if (!setStream2)\n      return E_NOTIMPL;\n    for (UInt32 i = 0; i < numOutStreams; i++)\n    {\n      CMyComPtr<ISequentialOutStream> seqOutStream2;\n      RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2))\n      RINOK(setStream2->SetOutStream2(i, seqOutStream2))\n    }\n    */\n  }\n\n  while (_binderStreams.Size() <= (unsigned)bond)\n    _binderStreams.AddNew();\n  CStBinderStream &bs = _binderStreams[(unsigned)bond];\n\n  if (bs.StreamRef || bs.OutStreamSpec)\n    return E_NOTIMPL;\n  \n  COutStreamCalcSize *spec = new COutStreamCalcSize;\n  bs.StreamRef = (ISequentialOutStream *)spec;\n  bs.OutStreamSpec = spec;\n  \n  spec->SetStream(seqOutStream);\n  spec->Init();\n\n  seqOutStream = bs.OutStreamSpec;\n  \n  *outStreamRes = seqOutStream.Detach();\n  return S_OK;\n}\n\n\nstatic HRESULT GetError(HRESULT res, HRESULT res2)\n{\n  if (res == res2)\n    return res;\n  if (res == S_OK)\n    return res2;\n  if (res == k_My_HRESULT_WritingWasCut)\n  {\n    if (res2 != S_OK)\n      return res2;\n  }\n  return res;\n}\n\n\nHRESULT CMixerST::FinishStream(UInt32 streamIndex)\n{\n  {\n    int index = -1;\n    if (!EncodeMode)\n    {\n      if (_bi.UnpackCoder == streamIndex)\n        index = 0;\n    }\n    else\n      index = _bi.FindStream_in_PackStreams(streamIndex);\n\n    if (index >= 0)\n      return S_OK;\n  }\n\n  const int bond = FindBond_for_Stream(\n      false, // forInputStream\n      streamIndex);\n  if (bond < 0)\n    return E_INVALIDARG;\n\n  const UInt32 inStreamIndex = _bi.Bonds[(unsigned)bond].Get_InIndex(EncodeMode);\n\n  UInt32 coderIndex = inStreamIndex;\n  UInt32 coderStreamIndex = 0;\n  if (!EncodeMode)\n    _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex);\n\n  CCoder &coder = _coders[coderIndex];\n  CMyComPtr<IOutStreamFinish> finish;\n  coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish);\n  HRESULT res = S_OK;\n  if (finish)\n  {\n    res = finish->OutStreamFinish();\n  }\n  return GetError(res, FinishCoder(coderIndex));\n}\n\n\nHRESULT CMixerST::FinishCoder(UInt32 coderIndex)\n{\n  CCoder &coder = _coders[coderIndex];\n\n  const UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1;\n  const UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex;\n\n  HRESULT res = S_OK;\n  for (unsigned i = 0; i < numOutStreams; i++)\n    res = GetError(res, FinishStream(startIndex + i));\n  return res;\n}\n\n\nvoid CMixerST::SelectMainCoder(bool useFirst)\n{\n  unsigned ci = _bi.UnpackCoder;\n  \n  int firstNonFilter = -1;\n  unsigned firstAllowed = ci;\n  \n  for (;;)\n  {\n    const CCoderST &coder = _coders[ci];\n    // break;\n    \n    if (ci != _bi.UnpackCoder)\n      if (EncodeMode ? !coder.CanWrite : !coder.CanRead)\n      {\n        firstAllowed = ci;\n        firstNonFilter = -2;\n      }\n      \n    if (coder.NumStreams != 1)\n      break;\n    \n    const UInt32 st = _bi.Coder_to_Stream[ci];\n    if (_bi.IsStream_in_PackStreams(st))\n      break;\n    const int bond = _bi.FindBond_for_PackStream(st);\n    if (bond < 0)\n      throw 20150213;\n    \n    if (EncodeMode ? !coder.CanRead : !coder.CanWrite)\n      break;\n    \n    if (firstNonFilter == -1 && !IsFilter_Vector[ci])\n      firstNonFilter = (int)ci;\n    \n    ci = _bi.Bonds[(unsigned)bond].UnpackIndex;\n  }\n  \n  if (useFirst)\n    ci = firstAllowed;\n  else if (firstNonFilter >= 0)\n    ci = (unsigned)firstNonFilter;\n\n  MainCoderIndex = ci;\n}\n\n\nHRESULT CMixerST::Code(\n    ISequentialInStream * const *inStreams,\n    ISequentialOutStream * const *outStreams,\n    ICompressProgressInfo *progress,\n    bool &dataAfterEnd_Error)\n{\n  // InternalPackSizeError = false;\n  dataAfterEnd_Error = false;\n\n  _binderStreams.Clear();\n  const unsigned ci = MainCoderIndex;\n \n  const CCoder &mainCoder = _coders[MainCoderIndex];\n\n  CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;\n  CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;\n  \n  const UInt32 numInStreams  =  EncodeMode ? 1 : mainCoder.NumStreams;\n  const UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams;\n  \n  const UInt32 startInIndex  =  EncodeMode ? ci : _bi.Coder_to_Stream[ci];\n  const UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci];\n  \n  UInt32 i;\n\n  for (i = 0; i < numInStreams; i++)\n  {\n    CMyComPtr<ISequentialInStream> seqInStream;\n    RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream))\n    seqInStreams.Add(seqInStream);\n  }\n  \n  for (i = 0; i < numOutStreams; i++)\n  {\n    CMyComPtr<ISequentialOutStream> seqOutStream;\n    RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream))\n    seqOutStreams.Add(seqOutStream);\n  }\n  \n  CRecordVector< ISequentialInStream * > seqInStreamsSpec;\n  CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;\n  \n  for (i = 0; i < numInStreams; i++)\n    seqInStreamsSpec.Add(seqInStreams[i]);\n  for (i = 0; i < numOutStreams; i++)\n    seqOutStreamsSpec.Add(seqOutStreams[i]);\n\n  for (i = 0; i < _coders.Size(); i++)\n  {\n    if (i == ci)\n      continue;\n   \n    CCoder &coder = _coders[i];\n\n    if (EncodeMode)\n    {\n      CMyComPtr<ICompressInitEncoder> initEncoder;\n      coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder);\n      if (initEncoder)\n      {\n        RINOK(initEncoder->InitEncoder())\n      }\n    }\n    else\n    {\n      CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\n      coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);\n      if (setOutStreamSize)\n      {\n        RINOK(setOutStreamSize->SetOutStreamSize(\n            EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer))\n      }\n    }\n  }\n\n  const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : mainCoder.PackSizePointers.ConstData();\n  const UInt64 * const *outSizes2 = EncodeMode ? mainCoder.PackSizePointers.ConstData() : &mainCoder.UnpackSizePointer;\n\n  HRESULT res;\n  if (mainCoder.Coder)\n  {\n    res = mainCoder.Coder->Code(\n        seqInStreamsSpec[0], seqOutStreamsSpec[0],\n        isSizes2[0], outSizes2[0],\n        progress);\n  }\n  else\n  {\n    res = mainCoder.Coder2->Code(\n        seqInStreamsSpec.ConstData(), isSizes2, numInStreams,\n        seqOutStreamsSpec.ConstData(), outSizes2, numOutStreams,\n        progress);\n  }\n\n  if (res == k_My_HRESULT_WritingWasCut)\n    res = S_OK;\n\n  if (res == S_OK || res == S_FALSE)\n  {\n    res = GetError(res, FinishCoder(ci));\n  }\n\n  for (i = 0; i < _binderStreams.Size(); i++)\n  {\n    const CStBinderStream &bs = _binderStreams[i];\n    if (bs.InStreamSpec)\n      bs.InStreamSpec->ReleaseStream();\n    else\n      bs.OutStreamSpec->ReleaseStream();\n  }\n\n  if (res == k_My_HRESULT_WritingWasCut)\n    res = S_OK;\n\n  if (res != S_OK)\n    return res;\n\n  for (i = 0; i < _coders.Size(); i++)\n  {\n    RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /*, InternalPackSizeError */))\n  }\n\n  return S_OK;\n}\n\n\nHRESULT CMixerST::GetMainUnpackStream(\n    ISequentialInStream * const *inStreams,\n    ISequentialInStream **inStreamRes)\n{\n  CMyComPtr<ISequentialInStream> seqInStream;\n\n  RINOK(GetInStream2(inStreams, /* inSizes, */\n      _bi.UnpackCoder, &seqInStream))\n  \n  FOR_VECTOR (i, _coders)\n  {\n    CCoder &coder = _coders[i];\n    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\n    coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize);\n    if (setOutStreamSize)\n    {\n      RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer))\n    }\n  }\n  \n  *inStreamRes = seqInStream.Detach();\n  return S_OK;\n}\n\n\nUInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const\n{\n  const CStBinderStream &bs = _binderStreams[bondIndex];\n  if (bs.InStreamSpec)\n    return bs.InStreamSpec->GetSize();\n  return bs.OutStreamSpec->GetSize();\n}\n\n#endif\n\n\n\n\n\n\n#ifdef USE_MIXER_MT\n\n\nvoid CCoderMT::Execute()\n{\n  try\n  {\n    Code(NULL);\n  }\n  catch(...)\n  {\n    Result = E_FAIL;\n  }\n}\n\nvoid CCoderMT::Code(ICompressProgressInfo *progress)\n{\n  unsigned numInStreams = EncodeMode ? 1 : NumStreams;\n  unsigned numOutStreams = EncodeMode ? NumStreams : 1;\n\n  InStreamPointers.ClearAndReserve(numInStreams);\n  OutStreamPointers.ClearAndReserve(numOutStreams);\n\n  unsigned i;\n  \n  for (i = 0; i < numInStreams; i++)\n    InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]);\n  \n  for (i = 0; i < numOutStreams; i++)\n    OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]);\n\n  // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers.\n  /*\n  if (UnpackSizePointer)\n    UnpackSizePointer = &UnpackSize;\n  for (i = 0; i < NumStreams; i++)\n    if (PackSizePointers[i])\n      PackSizePointers[i] = &PackSizes[i];\n  */\n\n  CReleaser releaser(*this);\n  \n  if (Coder)\n    Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0],\n        EncodeMode ? UnpackSizePointer : PackSizePointers[0],\n        EncodeMode ? PackSizePointers[0] : UnpackSizePointer,\n        progress);\n  else\n    Result = Coder2->Code(\n        InStreamPointers.ConstData(),  EncodeMode ? &UnpackSizePointer : PackSizePointers.ConstData(), numInStreams,\n        OutStreamPointers.ConstData(), EncodeMode ? PackSizePointers.ConstData(): &UnpackSizePointer, numOutStreams,\n        progress);\n}\n\nHRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo)\n{\n  CMixer::SetBindInfo(bindInfo);\n  \n  _streamBinders.Clear();\n  FOR_VECTOR (i, _bi.Bonds)\n  {\n    // RINOK(_streamBinders.AddNew().CreateEvents())\n    _streamBinders.AddNew();\n  }\n  return S_OK;\n}\n\nvoid CMixerMT::AddCoder(const CCreatedCoder &cod)\n{\n  IsFilter_Vector.Add(cod.IsFilter);\n  IsExternal_Vector.Add(cod.IsExternal);\n  // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()];\n  CCoderMT &c2 = _coders.AddNew();\n  c2.NumStreams = cod.NumStreams;\n  c2.Coder = cod.Coder;\n  c2.Coder2 = cod.Coder2;\n  c2.EncodeMode = EncodeMode;\n}\n\nCCoder &CMixerMT::GetCoder(unsigned index)\n{\n  return _coders[index];\n}\n\nHRESULT CMixerMT::ReInit2()\n{\n  FOR_VECTOR (i, _streamBinders)\n  {\n    RINOK(_streamBinders[i].Create_ReInit())\n  }\n  return S_OK;\n}\n\nvoid CMixerMT::SelectMainCoder(bool useFirst)\n{\n  unsigned ci = _bi.UnpackCoder;\n\n  if (!useFirst)\n  for (;;)\n  {\n    if (_coders[ci].NumStreams != 1)\n      break;\n    if (!IsFilter_Vector[ci])\n      break;\n    \n    UInt32 st = _bi.Coder_to_Stream[ci];\n    if (_bi.IsStream_in_PackStreams(st))\n      break;\n    const int bond = _bi.FindBond_for_PackStream(st);\n    if (bond < 0)\n      throw 20150213;\n    ci = _bi.Bonds[(unsigned)bond].UnpackIndex;\n  }\n  \n  MainCoderIndex = ci;\n}\n\nHRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams)\n{\n  unsigned i;\n  \n  for (i = 0; i < _coders.Size(); i++)\n  {\n    CCoderMT &coderInfo = _coders[i];\n    const CCoderStreamsInfo &csi = _bi.Coders[i];\n    \n    UInt32 j;\n\n    const unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams;\n    const unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1;\n\n    coderInfo.InStreams.Clear();\n    for (j = 0; j < numInStreams; j++)\n      coderInfo.InStreams.AddNew();\n    \n    coderInfo.OutStreams.Clear();\n    for (j = 0; j < numOutStreams; j++)\n      coderInfo.OutStreams.AddNew();\n  }\n\n  for (i = 0; i < _bi.Bonds.Size(); i++)\n  {\n    const CBond &bond = _bi.Bonds[i];\n   \n    UInt32 inCoderIndex, inCoderStreamIndex;\n    UInt32 outCoderIndex, outCoderStreamIndex;\n    \n    {\n      UInt32 coderIndex, coderStreamIndex;\n      _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex);\n\n      inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex;\n      outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex;\n\n      inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex;\n      outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0;\n    }\n\n    _streamBinders[i].CreateStreams2(\n        _coders[inCoderIndex].InStreams[inCoderStreamIndex],\n        _coders[outCoderIndex].OutStreams[outCoderStreamIndex]);\n\n    CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize;\n    _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize);\n    _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize);\n    if (inSetSize && outSetSize)\n    {\n      const UInt32 kBufSize = 1 << 19;\n      inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize);\n      outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize);\n    }\n  }\n\n  {\n    CCoderMT &cod = _coders[_bi.UnpackCoder];\n    if (EncodeMode)\n      cod.InStreams[0] = inStreams[0];\n    else\n      cod.OutStreams[0] = outStreams[0];\n  }\n\n  for (i = 0; i < _bi.PackStreams.Size(); i++)\n  {\n    UInt32 coderIndex, coderStreamIndex;\n    _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex);\n    CCoderMT &cod = _coders[coderIndex];\n    if (EncodeMode)\n      cod.OutStreams[coderStreamIndex] = outStreams[i];\n    else\n      cod.InStreams[coderStreamIndex] = inStreams[i];\n  }\n  \n  return S_OK;\n}\n\nHRESULT CMixerMT::ReturnIfError(HRESULT code)\n{\n  FOR_VECTOR (i, _coders)\n    if (_coders[i].Result == code)\n      return code;\n  return S_OK;\n}\n\nHRESULT CMixerMT::Code(\n    ISequentialInStream * const *inStreams,\n    ISequentialOutStream * const *outStreams,\n    ICompressProgressInfo *progress,\n    bool &dataAfterEnd_Error)\n{\n  // InternalPackSizeError = false;\n  dataAfterEnd_Error = false;\n\n  Init(inStreams, outStreams);\n\n  unsigned i;\n  for (i = 0; i < _coders.Size(); i++)\n    if (i != MainCoderIndex)\n    {\n      const WRes wres = _coders[i].Create();\n      if (wres != 0)\n        return HRESULT_FROM_WIN32(wres);\n    }\n\n  for (i = 0; i < _coders.Size(); i++)\n    if (i != MainCoderIndex)\n    {\n      const WRes wres = _coders[i].Start();\n      if (wres != 0)\n        return HRESULT_FROM_WIN32(wres);\n    }\n\n  _coders[MainCoderIndex].Code(progress);\n\n  WRes wres = 0;\n  for (i = 0; i < _coders.Size(); i++)\n    if (i != MainCoderIndex)\n    {\n      WRes wres2 = _coders[i].WaitExecuteFinish();\n      if (wres == 0)\n        wres = wres2;\n    }\n  if (wres != 0)\n    return HRESULT_FROM_WIN32(wres);\n\n  RINOK(ReturnIfError(E_ABORT))\n  RINOK(ReturnIfError(E_OUTOFMEMORY))\n\n  for (i = 0; i < _coders.Size(); i++)\n  {\n    HRESULT result = _coders[i].Result;\n    if (result != S_OK\n        && result != k_My_HRESULT_WritingWasCut\n        && result != S_FALSE\n        && result != E_FAIL)\n      return result;\n  }\n\n  RINOK(ReturnIfError(S_FALSE))\n\n  for (i = 0; i < _coders.Size(); i++)\n  {\n    HRESULT result = _coders[i].Result;\n    if (result != S_OK && result != k_My_HRESULT_WritingWasCut)\n      return result;\n  }\n\n  for (i = 0; i < _coders.Size(); i++)\n  {\n    RINOK(_coders[i].CheckDataAfterEnd(dataAfterEnd_Error /* , InternalPackSizeError */))\n  }\n\n  return S_OK;\n}\n\nUInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const\n{\n  return _streamBinders[bondIndex].ProcessedSize;\n}\n\n#endif\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/CoderMixer2.h",
    "content": "﻿// CoderMixer2.h\n\n#ifndef ZIP7_INC_CODER_MIXER2_H\n#define ZIP7_INC_CODER_MIXER2_H\n\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/MyVector.h\"\n\n#include \"../../ICoder.h\"\n\n#include \"../../Common/CreateCoder.h\"\n\n#ifdef Z7_ST\n  #define USE_MIXER_ST\n#else\n  #define USE_MIXER_MT\n  #ifndef Z7_SFX\n    #define USE_MIXER_ST\n  #endif\n#endif\n\n#ifdef USE_MIXER_MT\n#include \"../../Common/StreamBinder.h\"\n#include \"../../Common/VirtThread.h\"\n#endif\n\n\n\n#ifdef USE_MIXER_ST\n\nZ7_CLASS_IMP_COM_1(\n  CSequentialInStreamCalcSize\n  , ISequentialInStream\n)\n  bool _wasFinished;\n  CMyComPtr<ISequentialInStream> _stream;\n  UInt64 _size;\npublic:\n  void SetStream(ISequentialInStream *stream) { _stream = stream;  }\n  void Init()\n  {\n    _size = 0;\n    _wasFinished = false;\n  }\n  void ReleaseStream() { _stream.Release(); }\n  UInt64 GetSize() const { return _size; }\n  bool WasFinished() const { return _wasFinished; }\n};\n\n\nZ7_CLASS_IMP_COM_2(\n  COutStreamCalcSize\n  , ISequentialOutStream\n  , IOutStreamFinish\n)\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\npublic:\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init() { _size = 0; }\n  UInt64 GetSize() const { return _size; }\n};\n\n#endif\n\n\n  \nnamespace NCoderMixer2 {\n\nstruct CBond\n{\n  UInt32 PackIndex;\n  UInt32 UnpackIndex;\n\n  UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; }\n  UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; }\n};\n\n\nstruct CCoderStreamsInfo\n{\n  UInt32 NumStreams;\n};\n\n\nstruct CBindInfo\n{\n  CRecordVector<CCoderStreamsInfo> Coders;\n  CRecordVector<CBond> Bonds;\n  CRecordVector<UInt32> PackStreams;\n  unsigned UnpackCoder;\n\n  unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); }\n\n  int FindBond_for_PackStream(UInt32 packStream) const\n  {\n    FOR_VECTOR (i, Bonds)\n      if (Bonds[i].PackIndex == packStream)\n        return (int)i;\n    return -1;\n  }\n\n  int FindBond_for_UnpackStream(UInt32 unpackStream) const\n  {\n    FOR_VECTOR (i, Bonds)\n      if (Bonds[i].UnpackIndex == unpackStream)\n        return (int)i;\n    return -1;\n  }\n\n  bool SetUnpackCoder()\n  {\n    bool isOk = false;\n    FOR_VECTOR (i, Coders)\n    {\n      if (FindBond_for_UnpackStream(i) < 0)\n      {\n        if (isOk)\n          return false;\n        UnpackCoder = i;\n        isOk = true;\n      }\n    }\n    return isOk;\n  }\n  \n  bool IsStream_in_PackStreams(UInt32 streamIndex) const\n  {\n    return FindStream_in_PackStreams(streamIndex) >= 0;\n  }\n\n  int FindStream_in_PackStreams(UInt32 streamIndex) const\n  {\n    FOR_VECTOR (i, PackStreams)\n      if (PackStreams[i] == streamIndex)\n        return (int)i;\n    return -1;\n  }\n\n  \n  // that function is used before Maps is calculated\n\n  UInt32 GetStream_for_Coder(UInt32 coderIndex) const\n  {\n    UInt32 streamIndex = 0;\n    for (UInt32 i = 0; i < coderIndex; i++)\n      streamIndex += Coders[i].NumStreams;\n    return streamIndex;\n  }\n  \n  // ---------- Maps Section ----------\n  \n  CRecordVector<UInt32> Coder_to_Stream;\n  CRecordVector<UInt32> Stream_to_Coder;\n\n  void ClearMaps();\n  bool CalcMapsAndCheck();\n\n  // ---------- End of Maps Section ----------\n\n  void Clear()\n  {\n    Coders.Clear();\n    Bonds.Clear();\n    PackStreams.Clear();\n\n    ClearMaps();\n  }\n  \n  void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const\n  {\n    coderIndex = Stream_to_Coder[streamIndex];\n    coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex];\n  }\n};\n\n\n\nclass CCoder\n{\n  Z7_CLASS_NO_COPY(CCoder)\npublic:\n  CMyComPtr<ICompressCoder> Coder;\n  CMyComPtr<ICompressCoder2> Coder2;\n  UInt32 NumStreams;\n  bool Finish;\n\n  UInt64 UnpackSize;\n  const UInt64 *UnpackSizePointer;\n\n  CRecordVector<UInt64> PackSizes;\n  CRecordVector<const UInt64 *> PackSizePointers;\n\n  CCoder(): Finish(false) {}\n\n  void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish);\n\n  HRESULT CheckDataAfterEnd(bool &dataAfterEnd_Error /* , bool &InternalPackSizeError */) const;\n\n  IUnknown *GetUnknown() const\n  {\n    return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2;\n  }\n\n  HRESULT QueryInterface(REFGUID iid, void** pp) const\n  {\n    return GetUnknown()->QueryInterface(iid, pp);\n  }\n};\n\n\n\nclass CMixer\n{\n  bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex);\n\nprotected:\n  CBindInfo _bi;\n\n  int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const\n  {\n    if (EncodeMode == forInputStream)\n      return _bi.FindBond_for_UnpackStream(streamIndex);\n    else\n      return _bi.FindBond_for_PackStream(streamIndex);\n  }\n\n  CBoolVector IsFilter_Vector;\n  CBoolVector IsExternal_Vector;\n  bool EncodeMode;\npublic:\n  unsigned MainCoderIndex;\n\n  // bool InternalPackSizeError;\n\n  CMixer(bool encodeMode):\n      EncodeMode(encodeMode),\n      MainCoderIndex(0)\n      // , InternalPackSizeError(false)\n      {}\n\n  virtual ~CMixer() {}\n  /*\n  Sequence of calling:\n\n      SetBindInfo();\n      for each coder\n        AddCoder();\n      SelectMainCoder();\n \n      for each file\n      {\n        ReInit()\n        for each coder\n          SetCoderInfo();\n        Code();\n      }\n  */\n\n  virtual HRESULT SetBindInfo(const CBindInfo &bindInfo)\n  {\n    _bi = bindInfo;\n    IsFilter_Vector.Clear();\n    MainCoderIndex = 0;\n    return S_OK;\n  }\n\n  virtual void AddCoder(const CCreatedCoder &cod) = 0;\n  virtual CCoder &GetCoder(unsigned index) = 0;\n  virtual void SelectMainCoder(bool useFirst) = 0;\n  virtual HRESULT ReInit2() = 0;\n  virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) = 0;\n  virtual HRESULT Code(\n      ISequentialInStream * const *inStreams,\n      ISequentialOutStream * const *outStreams,\n      ICompressProgressInfo *progress,\n      bool &dataAfterEnd_Error) = 0;\n  virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0;\n\n  bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex);\n  bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex);\n  bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex);\n};\n\n\n\n\n#ifdef USE_MIXER_ST\n\nstruct CCoderST: public CCoder\n{\n  bool CanRead;\n  bool CanWrite;\n  \n  CCoderST(): CanRead(false), CanWrite(false) {}\n};\n\n\nstruct CStBinderStream\n{\n  CSequentialInStreamCalcSize *InStreamSpec;\n  COutStreamCalcSize *OutStreamSpec;\n  CMyComPtr<IUnknown> StreamRef;\n\n  CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {}\n};\n\n\nclass CMixerST:\n  public IUnknown,\n  public CMixer,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_0\n  Z7_CLASS_NO_COPY(CMixerST)\n\n  HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */\n      UInt32 outStreamIndex, ISequentialInStream **inStreamRes);\n  HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */\n      UInt32 inStreamIndex, ISequentialInStream **inStreamRes);\n  HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */\n      UInt32 outStreamIndex, ISequentialOutStream **outStreamRes);\n\n  HRESULT FinishStream(UInt32 streamIndex);\n  HRESULT FinishCoder(UInt32 coderIndex);\n\npublic:\n  CObjectVector<CCoderST> _coders;\n  \n  CObjectVector<CStBinderStream> _binderStreams;\n\n  CMixerST(bool encodeMode);\n  ~CMixerST() Z7_DESTRUCTOR_override;\n\n  virtual void AddCoder(const CCreatedCoder &cod) Z7_override;\n  virtual CCoder &GetCoder(unsigned index) Z7_override;\n  virtual void SelectMainCoder(bool useFirst) Z7_override;\n  virtual HRESULT ReInit2() Z7_override;\n  virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override\n    { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }\n  virtual HRESULT Code(\n      ISequentialInStream * const *inStreams,\n      ISequentialOutStream * const *outStreams,\n      ICompressProgressInfo *progress,\n      bool &dataAfterEnd_Error) Z7_override;\n  virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override;\n\n  HRESULT GetMainUnpackStream(\n      ISequentialInStream * const *inStreams,\n      ISequentialInStream **inStreamRes);\n};\n\n#endif\n\n\n\n\n#ifdef USE_MIXER_MT\n\nclass CCoderMT: public CCoder, public CVirtThread\n{\n  Z7_CLASS_NO_COPY(CCoderMT)\n  CRecordVector<ISequentialInStream*> InStreamPointers;\n  CRecordVector<ISequentialOutStream*> OutStreamPointers;\n\nprivate:\n  virtual void Execute() Z7_override;\npublic:\n  bool EncodeMode;\n  HRESULT Result;\n  CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;\n  CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;\n\n  void Release()\n  {\n    InStreamPointers.Clear();\n    OutStreamPointers.Clear();\n    unsigned i;\n    for (i = 0; i < InStreams.Size(); i++)\n      InStreams[i].Release();\n    for (i = 0; i < OutStreams.Size(); i++)\n      OutStreams[i].Release();\n  }\n\n  class CReleaser\n  {\n    Z7_CLASS_NO_COPY(CReleaser)\n    CCoderMT &_c;\n  public:\n    CReleaser(CCoderMT &c): _c(c) {}\n    ~CReleaser() { _c.Release(); }\n  };\n\n  CCoderMT(): EncodeMode(false) {}\n  ~CCoderMT() Z7_DESTRUCTOR_override\n  {\n    /* WaitThreadFinish() will be called in ~CVirtThread().\n       But we need WaitThreadFinish() call before CCoder destructor,\n       and before destructors of this class members.\n    */\n    CVirtThread::WaitThreadFinish();\n  }\n  \n  void Code(ICompressProgressInfo *progress);\n};\n\n\nclass CMixerMT:\n  public IUnknown,\n  public CMixer,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_0\n  Z7_CLASS_NO_COPY(CMixerMT)\n\n  CObjectVector<CStreamBinder> _streamBinders;\n\n  HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams);\n  HRESULT ReturnIfError(HRESULT code);\n\n  // virtual ~CMixerMT() {}\npublic:\n  CObjectVector<CCoderMT> _coders;\n\n  virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) Z7_override;\n  virtual void AddCoder(const CCreatedCoder &cod) Z7_override;\n  virtual CCoder &GetCoder(unsigned index) Z7_override;\n  virtual void SelectMainCoder(bool useFirst) Z7_override;\n  virtual HRESULT ReInit2() Z7_override;\n  virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes, bool finish) Z7_override\n    { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes, finish); }\n  virtual HRESULT Code(\n      ISequentialInStream * const *inStreams,\n      ISequentialOutStream * const *outStreams,\n      ICompressProgressInfo *progress,\n      bool &dataAfterEnd_Error) Z7_override;\n  virtual UInt64 GetBondStreamSize(unsigned bondIndex) const Z7_override;\n\n  CMixerMT(bool encodeMode): CMixer(encodeMode) {}\n};\n\n#endif\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/DummyOutStream.cpp",
    "content": "﻿// DummyOutStream.cpp\n\n#include \"StdAfx.h\"\n\n#include \"DummyOutStream.h\"\n\nZ7_COM7F_IMF(CDummyOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize = size;\n  HRESULT res = S_OK;\n  if (_stream)\n    res = _stream->Write(data, size, &realProcessedSize);\n  _size += realProcessedSize;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return res;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/DummyOutStream.h",
    "content": "﻿// DummyOutStream.h\n\n#ifndef ZIP7_INC_DUMMY_OUT_STREAM_H\n#define ZIP7_INC_DUMMY_OUT_STREAM_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../IStream.h\"\n\nZ7_CLASS_IMP_NOQIB_1(\n  CDummyOutStream\n  , ISequentialOutStream\n)\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\npublic:\n  void SetStream(ISequentialOutStream *outStream) { _stream = outStream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init() { _size = 0; }\n  UInt64 GetSize() const { return _size; }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/FindSignature.cpp",
    "content": "﻿// FindSignature.cpp\n\n#include \"StdAfx.h\"\n\n#include <string.h>\n\n#include \"../../../Common/MyBuffer.h\"\n\n#include \"../../Common/StreamUtils.h\"\n\n#include \"FindSignature.h\"\n\nHRESULT FindSignatureInStream(ISequentialInStream *stream,\n    const Byte *signature, unsigned signatureSize,\n    const UInt64 *limit, UInt64 &resPos)\n{\n  resPos = 0;\n  CByteBuffer byteBuffer2(signatureSize);\n  RINOK(ReadStream_FALSE(stream, byteBuffer2, signatureSize))\n\n  if (memcmp(byteBuffer2, signature, signatureSize) == 0)\n    return S_OK;\n\n  const size_t kBufferSize = 1 << 16;\n  CByteBuffer byteBuffer(kBufferSize);\n  Byte *buffer = byteBuffer;\n  size_t numPrevBytes = signatureSize - 1;\n  memcpy(buffer, (const Byte *)byteBuffer2 + 1, numPrevBytes);\n  resPos = 1;\n  for (;;)\n  {\n    if (limit)\n      if (resPos > *limit)\n        return S_FALSE;\n    do\n    {\n      const size_t numReadBytes = kBufferSize - numPrevBytes;\n      UInt32 processedSize;\n      RINOK(stream->Read(buffer + numPrevBytes, (UInt32)numReadBytes, &processedSize))\n      numPrevBytes += (size_t)processedSize;\n      if (processedSize == 0)\n        return S_FALSE;\n    }\n    while (numPrevBytes < signatureSize);\n    const size_t numTests = numPrevBytes - signatureSize + 1;\n    for (size_t pos = 0; pos < numTests; pos++)\n    {\n      const Byte b = signature[0];\n      for (; buffer[pos] != b && pos < numTests; pos++);\n      if (pos == numTests)\n        break;\n      if (memcmp(buffer + pos, signature, signatureSize) == 0)\n      {\n        resPos += pos;\n        return S_OK;\n      }\n    }\n    resPos += numTests;\n    numPrevBytes -= numTests;\n    memmove(buffer, buffer + numTests, numPrevBytes);\n  }\n}\n\nnamespace NArchive {\nHRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);\nHRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize)\n{\n  areThereNonZeros = false;\n  numZeros = 0;\n  const size_t kBufSize = 1 << 11;\n  Byte buf[kBufSize];\n  for (;;)\n  {\n    UInt32 size = 0;\n    RINOK(stream->Read(buf, kBufSize, &size))\n    if (size == 0)\n      return S_OK;\n    for (UInt32 i = 0; i < size; i++)\n      if (buf[i] != 0)\n      {\n        areThereNonZeros = true;\n        numZeros += i;\n        return S_OK;\n      }\n    numZeros += size;\n    if (numZeros > maxSize)\n      return S_OK;\n  }\n}\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/FindSignature.h",
    "content": "﻿// FindSignature.h\n\n#ifndef ZIP7_INC_FIND_SIGNATURE_H\n#define ZIP7_INC_FIND_SIGNATURE_H\n\n#include \"../../IStream.h\"\n\nHRESULT FindSignatureInStream(ISequentialInStream *stream,\n    const Byte *signature, unsigned signatureSize,\n    const UInt64 *limit, UInt64 &resPos);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/HandlerOut.cpp",
    "content": "﻿// HandlerOut.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/StringToInt.h\"\n\n#include \"HandlerOut.h\"\n\nnamespace NArchive {\n\nbool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res)\n{\n  if (*s == 0)\n  {\n    switch (prop.vt)\n    {\n      case VT_UI4: res = prop.ulVal; return true;\n      case VT_UI8: res = prop.uhVal.QuadPart; return true;\n      case VT_BSTR:\n        s = prop.bstrVal;\n        break;\n      default: return false;\n    }\n  }\n  else if (prop.vt != VT_EMPTY)\n    return false;\n\n  bool percentMode = false;\n  {\n    const wchar_t c = *s;\n    if (MyCharLower_Ascii(c) == 'p')\n    {\n      percentMode = true;\n      s++;\n    }\n  }\n\n  const wchar_t *end;\n  const UInt64 v = ConvertStringToUInt64(s, &end);\n  if (s == end)\n    return false;\n  const wchar_t c = *end;\n\n  if (percentMode)\n  {\n    if (c != 0)\n      return false;\n    res = Calc_From_Val_Percents(percentsBase, v);\n    return true;\n  }\n\n  if (c == 0)\n  {\n    res = v;\n    return true;\n  }\n  if (end[1] != 0)\n    return false;\n\n  if (c == '%')\n  {\n    res = Calc_From_Val_Percents(percentsBase, v);\n    return true;\n  }\n\n  unsigned numBits;\n  switch (MyCharLower_Ascii(c))\n  {\n    case 'b': numBits =  0; break;\n    case 'k': numBits = 10; break;\n    case 'm': numBits = 20; break;\n    case 'g': numBits = 30; break;\n    case 't': numBits = 40; break;\n    default: return false;\n  }\n  const UInt64 val2 = v << numBits;\n  if ((val2 >> numBits) != v)\n    return false;\n  res = val2;\n  return true;\n}\n\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\nbool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)\n{\n  hres = S_OK;\n\n  if (name.IsPrefixedBy_Ascii_NoCase(\"mt\"))\n  {\n    #ifndef Z7_ST\n    _numThreads = _numProcessors;\n    _numThreads_WasForced = false;\n    hres = ParseMtProp2(name.Ptr(2), value, _numThreads, _numThreads_WasForced);\n    // \"mt\" means \"_numThreads_WasForced = false\" here\n    #endif\n    return true;\n  }\n  \n  if (name.IsPrefixedBy_Ascii_NoCase(\"memuse\"))\n  {\n    UInt64 v;\n    if (!ParseSizeString(name.Ptr(6), value, _memAvail, v))\n      hres = E_INVALIDARG;\n    _memUsage_Decompress = v;\n    _memUsage_Compress = v;\n    _memUsage_WasSet = true;\n    return true;\n  }\n\n  return false;\n}\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\nint CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)\n{\n  hres = S_OK;\n\n  if (name.IsPrefixedBy_Ascii_NoCase(\"mt\"))\n  {\n    #ifndef Z7_ST\n    hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads);\n    // parameter \"mt\" specified, so it means \"_numThreads_WasForced = true\"\n    _numThreads_WasForced = true;\n    #endif\n    return -1; /* OK, but no return - could be also set by handler itself later */\n  }\n  \n  if (name.IsPrefixedBy_Ascii_NoCase(\"memuse\"))\n  {\n    UInt64 v;\n    if (!ParseSizeString(name.Ptr(6), value, _memAvail, v))\n      hres = E_INVALIDARG;\n    _memUsage_Decompress = v;\n    _memUsage_Compress = v;\n    _memUsage_WasSet = true;\n    return 1;\n  }\n\n  return 0;\n}\n// **************** 7-Zip ZS Modification End ****************\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nstatic void SetMethodProp32(CMethodProps &m, PROPID propID, UInt32 value)\n{\n  if (m.FindProp(propID) < 0)\n    m.AddProp32(propID, value);\n}\n\nvoid CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const\n{\n  UInt32 level = _level;\n  if (level != (UInt32)(Int32)-1)\n    SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);\n}\n\n#ifndef Z7_ST\n\nstatic void SetMethodProp32_Replace(CMethodProps &m, PROPID propID, UInt32 value)\n{\n  const int i = m.FindProp(propID);\n  if (i >= 0)\n  {\n    NWindows::NCOM::CPropVariant &val = m.Props[(unsigned)i].Value;\n    val = (UInt32)value;\n    return;\n  }\n  m.AddProp32(propID, value);\n}\n\nvoid CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreads)\n{\n  SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);\n}\n\nvoid CMultiMethodProps::SetMethodThreadsTo_Replace(CMethodProps &oneMethodInfo, UInt32 numThreads)\n{\n  SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);\n}\n\nvoid CMultiMethodProps::Set_Method_NumThreadGroups_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreadGroups)\n{\n  SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreadGroups, numThreadGroups);\n}\n\n#endif // Z7_ST\n\n\nvoid CMultiMethodProps::InitMulti()\n{\n  _level = (UInt32)(Int32)-1;\n  _analysisLevel = -1;\n  _crcSize = 4;\n  _autoFilter = true;\n}\n\nvoid CMultiMethodProps::Init()\n{\n  InitCommon();\n  InitMulti();\n  _methods.Clear();\n  _filterMethod.Clear();\n}\n\n\nHRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)\n{\n  UString name = nameSpec;\n  name.MakeLower_Ascii();\n  if (name.IsEmpty())\n    return E_INVALIDARG;\n  \n  if (name[0] == 'x')\n  {\n    name.Delete(0);\n    _level = 9;\n    return ParsePropToUInt32(name, value, _level);\n  }\n  // **************** 7-Zip ZS Modification Start ****************\n  if (name == L\"max\")\n  {\n    bool _max;\n    const HRESULT res = PROPVARIANT_to_bool(value, _max);\n    if (res == S_OK && _max) {\n      // adjust level (zstd --max), set it to the highest level too (e. g. setting of options.MaxFilter for BCJ2 etc)\n      _level = Z7_ZSTD_ULTIMATE_LEV;\n    }\n    return res;\n  }\n  // **************** 7-Zip ZS Modification End ****************\n\n  if (name.IsPrefixedBy_Ascii_NoCase(\"yx\"))\n  {\n    name.Delete(0, 2);\n    UInt32 v = 9;\n    RINOK(ParsePropToUInt32(name, value, v))\n    _analysisLevel = (int)v;\n    return S_OK;\n  }\n  \n  if (name.IsPrefixedBy_Ascii_NoCase(\"crc\"))\n  {\n    name.Delete(0, 3);\n    _crcSize = 4;\n    return ParsePropToUInt32(name, value, _crcSize);\n  }\n\n  {\n    HRESULT hres;\n    // **************** NanaZip Modification Start ****************\n    // if (SetCommonProperty(name, value, hres))\n    /* don't return by -1, since many handlers set common properties (e. g. kNumThreads)\n       with SetCoderProperties, so add it also as prop by its ID from name below */\n    if (SetCommonProperty(name, value, hres) > 0) \n    // **************** NanaZip Modification End ****************\n      return hres;\n  }\n  \n  UInt32 number;\n  const unsigned index = ParseStringToUInt32(name, number);\n  const UString realName = name.Ptr(index);\n  if (index == 0)\n  {\n    if (name.IsEqualTo(\"f\"))\n    {\n      const HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);\n      if (res == S_OK)\n        return res;\n      if (value.vt != VT_BSTR)\n        return E_INVALIDARG;\n      return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);\n    }\n    number = 0;\n  }\n  if (number > 64)\n    return E_INVALIDARG;\n  for (unsigned j = _methods.Size(); j <= number; j++)\n    _methods.AddNew();\n  return _methods[number].ParseMethodFromPROPVARIANT(realName, value);\n}\n\n\n\nvoid CSingleMethodProps::Init()\n{\n  InitCommon();\n  InitSingle();\n  Clear();\n}\n\n\nHRESULT CSingleMethodProps::SetProperty(const wchar_t *name2, const PROPVARIANT &value)\n{\n  // processed = false;\n  UString name = name2;\n  name.MakeLower_Ascii();\n  if (name.IsEmpty())\n    return E_INVALIDARG;\n  if (name.IsPrefixedBy_Ascii_NoCase(\"x\"))\n  {\n    UInt32 a = 9;\n    RINOK(ParsePropToUInt32(name.Ptr(1), value, a))\n    _level = a;\n    AddProp_Level(a);\n    // processed = true;\n    return S_OK;\n  }\n  {\n    HRESULT hres;\n    // **************** 7-Zip ZS Modification Start ****************\n    //if (SetCommonProperty(name, value, hres))\n    //{\n    //  // processed = true;\n    //  return S_OK;\n    //}\n    /* don't return by -1, since many handlers set common properties (e. g. kNumThreads)\n       with SetCoderProperties, so add it also as prop by its ID from name below */\n    if (SetCommonProperty(name, value, hres) > 0)\n      return hres;\n    // **************** 7-Zip ZS Modification End ****************\n  }\n  RINOK(ParseMethodFromPROPVARIANT(name, value))\n  return S_OK;\n}\n\n\nHRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)\n{\n  Init();\n  \n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    RINOK(SetProperty(names[i], values[i]))\n  }\n\n  return S_OK;\n}\n\n#endif\n\n\nstatic HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)\n{\n  RINOK(PROPVARIANT_to_bool(prop, dest.Val))\n  dest.Def = true;\n  return S_OK;\n}\n\nHRESULT CHandlerTimeOptions::Parse(const UString &name, const PROPVARIANT &prop, bool &processed)\n{\n  processed = true;\n  if (name.IsEqualTo_Ascii_NoCase(\"tm\")) { return PROPVARIANT_to_BoolPair(prop, Write_MTime); }\n  if (name.IsEqualTo_Ascii_NoCase(\"ta\")) { return PROPVARIANT_to_BoolPair(prop, Write_ATime); }\n  if (name.IsEqualTo_Ascii_NoCase(\"tc\")) { return PROPVARIANT_to_BoolPair(prop, Write_CTime); }\n  if (name.IsPrefixedBy_Ascii_NoCase(\"tp\"))\n  {\n    UInt32 v = 0;\n    RINOK(ParsePropToUInt32(name.Ptr(2), prop, v))\n    Prec = v;\n    return S_OK;\n  }\n  processed = false;\n  return S_OK;\n}\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/HandlerOut.h",
    "content": "﻿// HandlerOut.h\n\n#ifndef ZIP7_INC_HANDLER_OUT_H\n#define ZIP7_INC_HANDLER_OUT_H\n\n#include \"../../../Windows/System.h\"\n\n#include \"../../Common/MethodProps.h\"\n\nnamespace NArchive {\n\nbool ParseSizeString(const wchar_t *name, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res);\n\nclass CCommonMethodProps\n{\nprotected:\n  void InitCommon()\n  {\n    // _Write_MTime = true;\n    {\n#ifndef Z7_ST\n      _numThreads_WasForced = false;\n      UInt32 numThreads;\n#ifdef _WIN32\n      NWindows::NSystem::CProcessAffinity aff;\n      numThreads = aff.Load_and_GetNumberOfThreads();\n      _numThreadGroups = aff.IsGroupMode ? aff.Groups.GroupSizes.Size() : 0;\n#else\n      numThreads = NWindows::NSystem::GetNumberOfProcessors();\n#endif // _WIN32\n      _numProcessors = _numThreads = numThreads;\n#endif // Z7_ST\n    }\n    \n    size_t memAvail = (size_t)sizeof(size_t) << 28;\n    _memAvail = memAvail;\n    _memUsage_Compress = memAvail;\n    _memUsage_Decompress = memAvail;\n    _memUsage_WasSet = NWindows::NSystem::GetRamSize(memAvail);\n    if (_memUsage_WasSet)\n    {\n      _memAvail = memAvail;\n      unsigned bits = sizeof(size_t) * 8;\n      if (bits == 32)\n      {\n        const UInt32 limit2 = (UInt32)7 << 28;\n        if (memAvail > limit2)\n          memAvail = limit2;\n      }\n      // 80% - is auto usage limit in handlers\n      // _memUsage_Compress = memAvail * 4 / 5;\n      // _memUsage_Compress = Calc_From_Val_Percents(memAvail, 80);\n      _memUsage_Compress = Calc_From_Val_Percents_Less100(memAvail, 80);\n      _memUsage_Decompress = memAvail / 32 * 17;\n    }\n  }\n\npublic:\n#ifndef Z7_ST\n  UInt32 _numThreads;\n  UInt32 _numProcessors;\n#ifdef _WIN32\n  UInt32 _numThreadGroups;\n#endif\n  bool _numThreads_WasForced;\n#endif\n\n  bool _memUsage_WasSet;\n  UInt64 _memUsage_Compress;\n  UInt64 _memUsage_Decompress;\n  size_t _memAvail;\n\n  // **************** 7-Zip ZS Modification Start ****************\n  // bool SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres);\n  int SetCommonProperty(const UString& name, const PROPVARIANT& value, HRESULT& hres);\n  // **************** 7-Zip ZS Modification End ****************\n\n  CCommonMethodProps() { InitCommon(); }\n};\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nclass CMultiMethodProps: public CCommonMethodProps\n{\n  // **************** 7-Zip ZS Modification Start ****************\n  void InitMulti();\n\nprotected:\n  // **************** 7-Zip ZS Modification End ****************\n  UInt32 _level;\n  int _analysisLevel;\n\n  // **************** 7-Zip ZS Modification Start ****************\n  // void InitMulti();\n  // **************** 7-Zip ZS Modification End ****************\npublic:\n  UInt32 _crcSize;\n  CObjectVector<COneMethodInfo> _methods;\n  COneMethodInfo _filterMethod;\n  bool _autoFilter;\n\n  \n  void SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const;\n\n#ifndef Z7_ST\n  static void SetMethodThreadsTo_IfNotFinded(CMethodProps &props, UInt32 numThreads);\n  static void SetMethodThreadsTo_Replace(CMethodProps &props, UInt32 numThreads);\n  \n  static void Set_Method_NumThreadGroups_IfNotFinded(CMethodProps &props, UInt32 numThreadGroups);\n#endif\n\n\n  unsigned GetNumEmptyMethods() const\n  {\n    unsigned i;\n    for (i = 0; i < _methods.Size(); i++)\n      if (!_methods[i].IsEmpty())\n        break;\n    return i;\n  }\n\n  int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }\n  int GetAnalysisLevel() const { return _analysisLevel; }\n\n  void Init();\n  CMultiMethodProps() { InitMulti(); }\n\n  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);\n};\n\n\nclass CSingleMethodProps: public COneMethodInfo, public CCommonMethodProps\n{\n  UInt32 _level;\n\n  void InitSingle()\n  {\n    _level = (UInt32)(Int32)-1;\n  }\n\npublic:\n  void Init();\n  CSingleMethodProps() { InitSingle(); }\n  \n  int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; }\n  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &values);\n  HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);\n};\n\n#endif\n\nstruct CHandlerTimeOptions\n{\n  CBoolPair Write_MTime;\n  CBoolPair Write_ATime;\n  CBoolPair Write_CTime;\n  UInt32 Prec;\n\n  void Init()\n  {\n    Write_MTime.Init();\n    Write_MTime.Val = true;\n    Write_ATime.Init();\n    Write_CTime.Init();\n    Prec = (UInt32)(Int32)-1;\n  }\n\n  CHandlerTimeOptions()\n  {\n    Init();\n  }\n\n  HRESULT Parse(const UString &name, const PROPVARIANT &prop, bool &processed);\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/InStreamWithCRC.cpp",
    "content": "﻿// InStreamWithCRC.cpp\n\n#include \"StdAfx.h\"\n\n#include \"InStreamWithCRC.h\"\n\nZ7_COM7F_IMF(CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessed = 0;\n  HRESULT result = S_OK;\n  if (size != 0)\n  {\n    if (_stream)\n      result = _stream->Read(data, size, &realProcessed);\n    _size += realProcessed;\n    if (realProcessed == 0)\n      _wasFinished = true;\n    else\n      _crc = CrcUpdate(_crc, data, realProcessed);\n  }\n  if (processedSize)\n    *processedSize = realProcessed;\n  return result;\n}\n\nZ7_COM7F_IMF(CSequentialInStreamWithCRC::GetSize(UInt64 *size))\n{\n  *size = _fullSize;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessed = 0;\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Read(data, size, &realProcessed);\n  _size += realProcessed;\n  /*\n  if (size != 0 && realProcessed == 0)\n    _wasFinished = true;\n  */\n  _crc = CrcUpdate(_crc, data, realProcessed);\n  if (processedSize)\n    *processedSize = realProcessed;\n  return result;\n}\n\nZ7_COM7F_IMF(CInStreamWithCRC::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  if (seekOrigin != STREAM_SEEK_SET || offset != 0)\n    return E_FAIL;\n  _size = 0;\n  _crc = CRC_INIT_VAL;\n  return _stream->Seek(offset, seekOrigin, newPosition);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/InStreamWithCRC.h",
    "content": "﻿// InStreamWithCRC.h\n\n#ifndef ZIP7_INC_IN_STREAM_WITH_CRC_H\n#define ZIP7_INC_IN_STREAM_WITH_CRC_H\n\n#include \"../../../../C/7zCrc.h\"\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../IStream.h\"\n\nZ7_CLASS_IMP_NOQIB_2(\n  CSequentialInStreamWithCRC\n  , ISequentialInStream\n  , IStreamGetSize\n)\n  CMyComPtr<ISequentialInStream> _stream;\n  UInt64 _size;\n  UInt32 _crc;\n  bool _wasFinished;\n  UInt64 _fullSize;\npublic:\n  \n  CSequentialInStreamWithCRC():\n    _fullSize((UInt64)(Int64)-1)\n    {}\n\n  void SetStream(ISequentialInStream *stream) { _stream = stream; }\n  void SetFullSize(UInt64 fullSize) { _fullSize = fullSize; }\n  void Init()\n  {\n    _size = 0;\n    _crc = CRC_INIT_VAL;\n    _wasFinished = false;\n  }\n  void ReleaseStream() { _stream.Release(); }\n  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }\n  UInt64 GetSize() const { return _size; }\n  bool WasFinished() const { return _wasFinished; }\n};\n\n\nZ7_CLASS_IMP_IInStream(\n  CInStreamWithCRC\n)\n  CMyComPtr<IInStream> _stream;\n  UInt64 _size;\n  UInt32 _crc;\n  // bool _wasFinished;\npublic:\n  void SetStream(IInStream *stream) { _stream = stream; }\n  void Init()\n  {\n    _size = 0;\n    // _wasFinished = false;\n    _crc = CRC_INIT_VAL;\n  }\n  void ReleaseStream() { _stream.Release(); }\n  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }\n  UInt64 GetSize() const { return _size; }\n  // bool WasFinished() const { return _wasFinished; }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/ItemNameUtils.cpp",
    "content": "﻿// Archive/Common/ItemNameUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"ItemNameUtils.h\"\n\nnamespace NArchive {\nnamespace NItemName {\n\nstatic const wchar_t kOsPathSepar = WCHAR_PATH_SEPARATOR;\n\n#if WCHAR_PATH_SEPARATOR != L'/'\nstatic const wchar_t kUnixPathSepar = L'/';\n#endif\n\nvoid ReplaceSlashes_OsToUnix\n#if WCHAR_PATH_SEPARATOR != L'/'\n  (UString &name)\n  {\n    name.Replace(kOsPathSepar, kUnixPathSepar);\n  }\n#else\n  (UString &) {}\n#endif\n\n\nUString GetOsPath(const UString &name)\n{\n  #if WCHAR_PATH_SEPARATOR != L'/'\n    UString newName = name;\n    newName.Replace(kUnixPathSepar, kOsPathSepar);\n    return newName;\n  #else\n    return name;\n  #endif\n}\n\n\nUString GetOsPath_Remove_TailSlash(const UString &name)\n{\n  if (name.IsEmpty())\n    return UString();\n  UString newName = GetOsPath(name);\n  if (newName.Back() == kOsPathSepar)\n    newName.DeleteBack();\n  return newName;\n}\n\n\n#if WCHAR_PATH_SEPARATOR != L'/'\nvoid ReplaceToWinSlashes(UString &name, bool useBackslashReplacement)\n{\n  // name.Replace(kUnixPathSepar, kOsPathSepar);\n  const unsigned len = name.Len();\n  for (unsigned i = 0; i < len; i++)\n  {\n    wchar_t c = name[i];\n    if (c == L'/')\n      c = WCHAR_PATH_SEPARATOR;\n    else if (useBackslashReplacement && c == L'\\\\')\n      c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme\n    else\n      continue;\n    name.ReplaceOneCharAtPos(i, c);\n  }\n}\n#endif\n\nvoid ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool\n    #if WCHAR_PATH_SEPARATOR != L'/'\n      useBackslashReplacement\n    #endif\n    )\n{\n  if (name.IsEmpty())\n    return;\n\n  #if WCHAR_PATH_SEPARATOR != L'/'\n  ReplaceToWinSlashes(name, useBackslashReplacement);\n  #endif\n    \n  if (name.Back() == kOsPathSepar)\n    name.DeleteBack();\n}\n\n\nvoid NormalizeSlashes_in_FileName_for_OsPath(wchar_t *name, unsigned len)\n{\n  for (unsigned i = 0; i < len; i++)\n  {\n    wchar_t c = name[i];\n    if (c == L'/')\n      c = L'_';\n   #if WCHAR_PATH_SEPARATOR != L'/'\n    else if (c == L'\\\\')\n      c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme\n   #endif\n    else\n      continue;\n    name[i] = c;\n  }\n}\n\nvoid NormalizeSlashes_in_FileName_for_OsPath(UString &name)\n{\n  NormalizeSlashes_in_FileName_for_OsPath(name.GetBuf(), name.Len());\n}\n\n\nbool HasTailSlash(const AString &name, UINT\n  #if defined(_WIN32) && !defined(UNDER_CE)\n    codePage\n  #endif\n  )\n{\n  if (name.IsEmpty())\n    return false;\n  char c;\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    if (codePage != CP_UTF8)\n      c = *CharPrevExA((WORD)codePage, name, name.Ptr(name.Len()), 0);\n    else\n    #endif\n    {\n      c = name.Back();\n    }\n  return (c == '/');\n}\n\n\n#ifndef _WIN32\nUString WinPathToOsPath(const UString &name)\n{\n  UString newName = name;\n  newName.Replace(L'\\\\', WCHAR_PATH_SEPARATOR);\n  return newName;\n}\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/ItemNameUtils.h",
    "content": "﻿// Archive/Common/ItemNameUtils.h\n\n#ifndef ZIP7_INC_ARCHIVE_ITEM_NAME_UTILS_H\n#define ZIP7_INC_ARCHIVE_ITEM_NAME_UTILS_H\n\n#include \"../../../Common/MyString.h\"\n\nnamespace NArchive {\nnamespace NItemName {\n\nvoid ReplaceSlashes_OsToUnix(UString &name);\n  \nUString GetOsPath(const UString &name);\nUString GetOsPath_Remove_TailSlash(const UString &name);\n  \n#if WCHAR_PATH_SEPARATOR != L'/'\nvoid ReplaceToWinSlashes(UString &name, bool useBackslashReplacement);\n#endif\nvoid ReplaceToOsSlashes_Remove_TailSlash(UString &name, bool useBackslashReplacement = false);\nvoid NormalizeSlashes_in_FileName_for_OsPath(wchar_t *s, unsigned len);\nvoid NormalizeSlashes_in_FileName_for_OsPath(UString &name);\n  \nbool HasTailSlash(const AString &name, UINT codePage);\n  \n#ifdef _WIN32\n  inline UString WinPathToOsPath(const UString &name)  { return name; }\n#else\n  UString WinPathToOsPath(const UString &name);\n#endif\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/MultiStream.cpp",
    "content": "﻿// MultiStream.cpp\n\n#include \"StdAfx.h\"\n\n#include \"MultiStream.h\"\n\nZ7_COM7F_IMF(CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (_pos >= _totalLength)\n    return S_OK;\n\n  {\n    unsigned left = 0, mid = _streamIndex, right = Streams.Size();\n    for (;;)\n    {\n      CSubStreamInfo &m = Streams[mid];\n      if (_pos < m.GlobalOffset)\n        right = mid;\n      else if (_pos >= m.GlobalOffset + m.Size)\n        left = mid + 1;\n      else\n        break;\n      mid = (left + right) / 2;\n    }\n    _streamIndex = mid;\n  }\n  \n  CSubStreamInfo &s = Streams[_streamIndex];\n  UInt64 localPos = _pos - s.GlobalOffset;\n  if (localPos != s.LocalPos)\n  {\n    RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos))\n  }\n  {\n    const UInt64 rem = s.Size - localPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  const HRESULT result = s.Stream->Read(data, size, &size);\n  _pos += size;\n  s.LocalPos += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n  \nZ7_COM7F_IMF(CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _pos; break;\n    case STREAM_SEEK_END: offset += _totalLength; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _pos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\n\n/*\nclass COutVolumeStream:\n  public ISequentialOutStream,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_0\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\n\n  unsigned _volIndex;\n  UInt64 _volSize;\n  UInt64 _curPos;\n  CMyComPtr<ISequentialOutStream> _volumeStream;\n  COutArchive _archive;\n  CCRC _crc;\n\npublic:\n  CFileItem _file;\n  CUpdateOptions _options;\n  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;\n  void Init(IArchiveUpdateCallback2 *volumeCallback,\n      const UString &name)\n  {\n    _file.Name = name;\n    _file.IsStartPosDefined = true;\n    _file.StartPos = 0;\n    \n    VolumeCallback = volumeCallback;\n    _volIndex = 0;\n    _volSize = 0;\n  }\n  \n  HRESULT Flush();\n};\n\nHRESULT COutVolumeStream::Flush()\n{\n  if (_volumeStream)\n  {\n    _file.UnPackSize = _curPos;\n    _file.FileCRC = _crc.GetDigest();\n    RINOK(WriteVolumeHeader(_archive, _file, _options))\n    _archive.Close();\n    _volumeStream.Release();\n    _file.StartPos += _file.UnPackSize;\n  }\n  return S_OK;\n}\n*/\n\n/*\n\n#include \"../../../Common/Defs.h\"\n\nZ7_COM7F_IMF(COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  while (size > 0)\n  {\n    if (_streamIndex >= Streams.Size())\n    {\n      CSubStreamInfo subStream;\n      RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size))\n      RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream))\n      subStream.Pos = 0;\n      Streams.Add(subStream);\n      continue;\n    }\n    CSubStreamInfo &subStream = Streams[_streamIndex];\n    if (_offsetPos >= subStream.Size)\n    {\n      _offsetPos -= subStream.Size;\n      _streamIndex++;\n      continue;\n    }\n    if (_offsetPos != subStream.Pos)\n    {\n      CMyComPtr<IOutStream> outStream;\n      RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream))\n      RINOK(outStream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL))\n      subStream.Pos = _offsetPos;\n    }\n\n    const UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);\n    UInt32 realProcessed;\n    RINOK(subStream.Stream->Write(data, curSize, &realProcessed))\n    data = (const void *)((const Byte *)data + realProcessed);\n    size -= realProcessed;\n    subStream.Pos += realProcessed;\n    _offsetPos += realProcessed;\n    _absPos += realProcessed;\n    if (_absPos > _length)\n      _length = _absPos;\n    if (processedSize)\n      *processedSize += realProcessed;\n    if (subStream.Pos == subStream.Size)\n    {\n      _streamIndex++;\n      _offsetPos = 0;\n    }\n    if (realProcessed != curSize && realProcessed == 0)\n      return E_FAIL;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _absPos; break;\n    case STREAM_SEEK_END: offset += _length; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _absPos = (UInt64)offset;\n  _offsetPos = _absPos;\n  _streamIndex = 0;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/MultiStream.h",
    "content": "﻿// MultiStream.h\n\n#ifndef ZIP7_INC_MULTI_STREAM_H\n#define ZIP7_INC_MULTI_STREAM_H\n\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/MyVector.h\"\n\n#include \"../../IStream.h\"\n#include \"../../Archive/IArchive.h\"\n\nZ7_CLASS_IMP_IInStream(\n  CMultiStream\n)\n\n  unsigned _streamIndex;\n  UInt64 _pos;\n  UInt64 _totalLength;\n\npublic:\n\n  struct CSubStreamInfo\n  {\n    CMyComPtr<IInStream> Stream;\n    UInt64 Size;\n    UInt64 GlobalOffset;\n    UInt64 LocalPos;\n    CSubStreamInfo(): Size(0), GlobalOffset(0), LocalPos(0) {}\n  };\n\n  CMyComPtr<IArchiveUpdateCallbackFile> updateCallbackFile;\n  CObjectVector<CSubStreamInfo> Streams;\n \n  HRESULT Init()\n  {\n    UInt64 total = 0;\n    FOR_VECTOR (i, Streams)\n    {\n      CSubStreamInfo &s = Streams[i];\n      s.GlobalOffset = total;\n      total += s.Size;\n      s.LocalPos = 0;\n      {\n        // it was already set to start\n        // RINOK(InStream_GetPos(s.Stream, s.LocalPos));\n      }\n    }\n    _totalLength = total;\n    _pos = 0;\n    _streamIndex = 0;\n    return S_OK;\n  }\n};\n\n/*\nZ7_CLASS_IMP_COM_1(\n  COutMultiStream,\n  IOutStream\n)\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\n\n  unsigned _streamIndex; // required stream\n  UInt64 _offsetPos; // offset from start of _streamIndex index\n  UInt64 _absPos;\n  UInt64 _length;\n\n  struct CSubStreamInfo\n  {\n    CMyComPtr<ISequentialOutStream> Stream;\n    UInt64 Size;\n    UInt64 Pos;\n };\n  CObjectVector<CSubStreamInfo> Streams;\npublic:\n  CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;\n  void Init()\n  {\n    _streamIndex = 0;\n    _offsetPos = 0;\n    _absPos = 0;\n    _length = 0;\n  }\n};\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp",
    "content": "﻿// OutStreamWithCRC.cpp\n\n#include \"StdAfx.h\"\n\n#include \"OutStreamWithCRC.h\"\n\nZ7_COM7F_IMF(COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  if (_calculate)\n    _crc = CrcUpdate(_crc, data, size);\n  _size += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/OutStreamWithCRC.h",
    "content": "﻿// OutStreamWithCRC.h\n\n#ifndef ZIP7_INC_OUT_STREAM_WITH_CRC_H\n#define ZIP7_INC_OUT_STREAM_WITH_CRC_H\n\n#include \"../../../../C/7zCrc.h\"\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../IStream.h\"\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithCRC\n  , ISequentialOutStream\n)\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\n  UInt32 _crc;\n  bool _calculate;\npublic:\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init(bool calculate = true)\n  {\n    _size = 0;\n    _calculate = calculate;\n    _crc = CRC_INIT_VAL;\n  }\n  void EnableCalc(bool calculate) { _calculate = calculate; }\n  void InitCRC() { _crc = CRC_INIT_VAL; }\n  UInt64 GetSize() const { return _size; }\n  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp",
    "content": "﻿// OutStreamWithSha1.cpp\n\n#include \"StdAfx.h\"\n\n#include \"OutStreamWithSha1.h\"\n\nZ7_COM7F_IMF(COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  if (_calculate)\n    Sha1_Update(Sha(), (const Byte *)data, size);\n  _size += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\nZ7_COM7F_IMF(CInStreamWithSha1::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize;\n  const HRESULT result = _stream->Read(data, size, &realProcessedSize);\n  _size += realProcessedSize;\n  Sha1_Update(Sha(), (const Byte *)data, realProcessedSize);\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return result;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/OutStreamWithSha1.h",
    "content": "﻿// OutStreamWithSha1.h\n\n#ifndef ZIP7_INC_OUT_STREAM_WITH_SHA1_H\n#define ZIP7_INC_OUT_STREAM_WITH_SHA1_H\n\n#include \"../../../../C/Sha1.h\"\n\n#include \"../../../Common/MyBuffer2.h\"\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../IStream.h\"\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithSha1\n  , ISequentialOutStream\n)\n  bool _calculate;\n  CMyComPtr<ISequentialOutStream> _stream;\n  CAlignedBuffer1 _sha;\n  UInt64 _size;\n\n  CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }\npublic:\n  COutStreamWithSha1(): _sha(sizeof(CSha1)) {}\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init(bool calculate = true)\n  {\n    _calculate = calculate;\n    _size = 0;\n    Sha1_Init(Sha());\n  }\n  void InitSha1() { Sha1_Init(Sha()); }\n  UInt64 GetSize() const { return _size; }\n  void Final(Byte *digest) { Sha1_Final(Sha(), digest); }\n};\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CInStreamWithSha1\n  , ISequentialInStream\n)\n  CMyComPtr<ISequentialInStream> _stream;\n  CAlignedBuffer1 _sha;\n  UInt64 _size;\n\n  CSha1 *Sha() { return (CSha1 *)(void *)(Byte *)_sha; }\npublic:\n  CInStreamWithSha1(): _sha(sizeof(CSha1)) {}\n  void SetStream(ISequentialInStream *stream) { _stream = stream;  }\n  void Init()\n  {\n    _size = 0;\n    Sha1_Init(Sha());\n  }\n  void ReleaseStream() { _stream.Release(); }\n  UInt64 GetSize() const { return _size; }\n  void Final(Byte *digest) { Sha1_Final(Sha(), digest); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/ParseProperties.h",
    "content": "﻿// ParseProperties.h\n\n#ifndef ZIP7_INC_PARSE_PROPERTIES_H\n#define ZIP7_INC_PARSE_PROPERTIES_H\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Common/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/CpioHandler.cpp",
    "content": "﻿// CpioHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyLinux.h\"\n#include \"../../Common/StringConvert.h\"\n#include \"../../Common/StringToInt.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/ItemNameUtils.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NCpio {\n\nstatic const Byte kMagicBin0 = 0xC7;\nstatic const Byte kMagicBin1 = 0x71;\n\nstatic const Byte kMagicHex    = '1'; // New ASCII Format\nstatic const Byte kMagicHexCrc = '2'; // New CRC Format\nstatic const Byte kMagicOct    = '7'; // Portable ASCII Format\n\nstatic const char * const kName_TRAILER = \"TRAILER!!!\";\n\nstatic const unsigned k_BinRecord_Size = 2 + 8 * 2 + 2 * 4;\nstatic const unsigned k_OctRecord_Size = 6 + 8 * 6 + 2 * 11;\nstatic const unsigned k_HexRecord_Size = 6 + 13 * 8;\n\nstatic const unsigned k_RecordSize_Max = k_HexRecord_Size;\n\nenum EType\n{\n  k_Type_BinLe,\n  k_Type_BinBe,\n  k_Type_Oct,\n  k_Type_Hex,\n  k_Type_HexCrc\n};\n\nstatic const char * const k_Types[] =\n{\n    \"Binary LE\"\n  , \"Binary BE\"\n  , \"Portable ASCII\"\n  , \"New ASCII\"\n  , \"New CRC\"\n};\n\nstruct CItem\n{\n  UInt32 inode;\n  unsigned MainIndex_ForInode;\n  UInt32 Mode;\n  UInt32 MTime;\n  UInt32 DevMajor;\n  UInt32 DevMinor;\n  UInt64 Size;\n  AString Name;\n  UInt32 NumLinks;\n  UInt32 UID;\n  UInt32 GID;\n  UInt32 RDevMajor;\n  UInt32 RDevMinor;\n  UInt32 ChkSum;\n\n  UInt32 AlignMask;\n  EType Type;\n\n  UInt32 HeaderSize;\n  UInt64 HeaderPos;\n\n  CByteBuffer Data; // for symlink\n\n\n  UInt32 GetAlignedSize(UInt32 size) const\n  {\n    return (size + AlignMask) & ~(UInt32)AlignMask;\n  }\n\n  UInt64 GetPackSize() const\n  {\n    const UInt64 alignMask64 = AlignMask;\n    return (Size + alignMask64) & ~(UInt64)alignMask64;\n  }\n\n  bool IsSame_inode_Dev(const CItem &item) const\n  {\n    return inode == item.inode\n        && DevMajor == item.DevMajor\n        && DevMinor == item.DevMinor;\n  }\n\n  bool IsBin() const { return Type == k_Type_BinLe || Type == k_Type_BinBe; }\n  bool IsCrcFormat() const { return Type == k_Type_HexCrc; }\n  bool IsDir() const { return MY_LIN_S_ISDIR(Mode); }\n  bool Is_SymLink() const { return MY_LIN_S_ISLNK(Mode); }\n  bool IsTrailer() const { return strcmp(Name, kName_TRAILER) == 0; }\n  UInt64 GetDataPosition() const { return HeaderPos + HeaderSize; }\n};\n\n\nenum EErrorType\n{\n  k_ErrorType_OK,\n  k_ErrorType_BadSignature,\n  k_ErrorType_Corrupted,\n  k_ErrorType_UnexpectedEnd\n};\n\n\nstruct CInArchive\n{\n  EErrorType errorType;\n  ISequentialInStream *Stream;\n  UInt64 Processed;\n  CItem item;\n  \n  HRESULT Read(void *data, size_t *size);\n  HRESULT GetNextItem();\n};\n\nHRESULT CInArchive::Read(void *data, size_t *size)\n{\n  const HRESULT res = ReadStream(Stream, data, size);\n  Processed += *size;\n  return res;\n}\n\n\nstatic bool CheckOctRecord(const Byte *p)\n{\n  for (unsigned i = 6; i < k_OctRecord_Size; i++)\n  {\n    const unsigned c = (unsigned)p[i] - '0';\n    if (c > 7)\n      return false;\n  }\n  return true;\n}\n\nstatic bool CheckHexRecord(const Byte *p)\n{\n  for (unsigned i = 6; i < k_HexRecord_Size; i++)\n  {\n    unsigned c = p[i];\n    c -= '0';\n    if (c > 9)\n    {\n      c -= 'A' - '0';\n      c &= ~0x20u;\n      if (c > 5)\n        return false;\n    }\n  }\n  return true;\n}\n\nstatic UInt32 ReadHex(const Byte *p)\n{\n  char sz[16];\n  memcpy(sz, p, 8);\n  sz[8] = 0;\n  const char *end;\n  return ConvertHexStringToUInt32(sz, &end);\n}\n\nstatic UInt32 ReadOct6(const Byte *p)\n{\n  char sz[16];\n  memcpy(sz, p, 6);\n  sz[6] = 0;\n  const char *end;\n  return ConvertOctStringToUInt32(sz, &end);\n}\n\nstatic UInt64 ReadOct11(const Byte *p)\n{\n  char sz[16];\n  memcpy(sz, p, 11);\n  sz[11] = 0;\n  const char *end;\n  return ConvertOctStringToUInt64(sz, &end);\n}\n\n\n#define READ_HEX(    y, dest)  dest = ReadHex  (p + 6 + (y) * 8);\n#define READ_OCT_6(  y, dest)  dest = ReadOct6 (p + 6 + (y));\n#define READ_OCT_11( y, dest)  dest = ReadOct11(p + 6 + (y));\n\n#define Get32spec(p) (((UInt32)GetUi16(p) << 16) + GetUi16(p + 2))\n#define G16(offs, v) v = GetUi16(p + (offs))\n#define G32(offs, v) v = Get32spec(p + (offs))\n\nstatic const unsigned kNameSizeMax = 1 << 12;\n\n\nAPI_FUNC_static_IsArc IsArc_Cpio(const Byte *p, size_t size)\n{\n  if (size < k_BinRecord_Size)\n    return k_IsArc_Res_NEED_MORE;\n\n  UInt32 namePos;\n  UInt32 nameSize;\n  UInt32 mode;\n  // UInt32 rDevMinor;\n  UInt32 rDevMajor = 0;\n\n  if (p[0] == '0')\n  {\n    if (p[1] != '7' ||\n        p[2] != '0' ||\n        p[3] != '7' ||\n        p[4] != '0')\n      return k_IsArc_Res_NO;\n    if (p[5] == kMagicOct)\n    {\n      if (size < k_OctRecord_Size)\n        return k_IsArc_Res_NEED_MORE;\n      if (!CheckOctRecord(p))\n        return k_IsArc_Res_NO;\n      READ_OCT_6 (2 * 6, mode)\n      // READ_OCT_6 (6 * 6, rDevMinor)\n      READ_OCT_6 (7 * 6 + 11, nameSize)\n      namePos = k_OctRecord_Size;\n    }\n    else if (p[5] == kMagicHex || p[5] == kMagicHexCrc)\n    {\n      if (size < k_HexRecord_Size)\n        return k_IsArc_Res_NEED_MORE;\n      if (!CheckHexRecord(p))\n        return k_IsArc_Res_NO;\n      READ_HEX (1, mode)\n      READ_HEX (9, rDevMajor)\n      // READ_HEX (10, rDevMinor)\n      READ_HEX (11, nameSize)\n      namePos = k_HexRecord_Size;\n    }\n    else\n      return k_IsArc_Res_NO;\n  }\n  else\n  {\n    if (p[0] == kMagicBin0 && p[1] == kMagicBin1)\n    {\n      mode = GetUi16(p + 6);\n      // rDevMinor = GetUi16(p + 14);\n      nameSize = GetUi16(p + 20);\n    }\n    else if (p[0] == kMagicBin1 && p[1] == kMagicBin0)\n    {\n      mode = GetBe16(p + 6);\n      // rDevMinor = GetBe16(p + 14);\n      nameSize = GetBe16(p + 20);\n    }\n    else\n      return k_IsArc_Res_NO;\n    namePos = k_BinRecord_Size;\n  }\n\n  if (mode >= (1 << 16))\n    return k_IsArc_Res_NO;\n\n  /* v23.02: we have disabled rDevMinor check because real file\n     from Apple contains rDevMinor==255 by some unknown reason */\n  if (rDevMajor != 0\n      // || rDevMinor != 0\n      )\n  {\n    if (!MY_LIN_S_ISCHR(mode) &&\n        !MY_LIN_S_ISBLK(mode))\n      return k_IsArc_Res_NO;\n  }\n\n  // nameSize must include the null byte\n  if (nameSize == 0 || nameSize > kNameSizeMax)\n    return k_IsArc_Res_NO;\n  {\n    unsigned lim = namePos + nameSize - 1;\n    if (lim >= size)\n      lim = (unsigned)size;\n    else if (p[lim] != 0)\n      return k_IsArc_Res_NO;\n    for (unsigned i = namePos; i < lim; i++)\n      if (p[i] == 0)\n        return k_IsArc_Res_NO;\n  }\n\n  return k_IsArc_Res_YES;\n}\n}\n\n\n#define READ_STREAM(_dest_, _size_) \\\n  { size_t processed = (_size_); RINOK(Read(_dest_, &processed)); \\\nif (processed != (_size_)) { errorType = k_ErrorType_UnexpectedEnd; return S_OK; } }\n\nHRESULT CInArchive::GetNextItem()\n{\n  errorType = k_ErrorType_BadSignature;\n\n  Byte p[k_RecordSize_Max];\n\n  READ_STREAM(p, k_BinRecord_Size)\n\n  UInt32 nameSize;\n  UInt32 namePos;\n\n  /* we try to reduce probability of false detection,\n     so we check some fields for unuxpected values */\n\n  if (p[0] != '0')\n  {\n         if (p[0] == kMagicBin0 && p[1] == kMagicBin1) { item.Type = k_Type_BinLe; }\n    else if (p[0] == kMagicBin1 && p[1] == kMagicBin0)\n    {\n      for (unsigned i = 2; i < k_BinRecord_Size; i += 2)\n      {\n        const Byte b = p[i];\n        p[i] = p[i + 1];\n        p[i + 1] = b;\n      }\n      item.Type = k_Type_BinBe;\n    }\n    else\n      return S_OK;\n\n    errorType = k_ErrorType_Corrupted;\n\n    item.AlignMask = 2 - 1;\n    item.DevMajor = 0;\n    item.RDevMajor = 0;\n    item.ChkSum = 0;\n\n    G16(2, item.DevMinor);\n    G16(4, item.inode);\n    G16(6, item.Mode);\n    G16(8, item.UID);\n    G16(10, item.GID);\n    G16(12, item.NumLinks);\n    G16(14, item.RDevMinor);\n    G32(16, item.MTime);\n    G16(20, nameSize);\n    G32(22, item.Size);\n\n    namePos = k_BinRecord_Size;\n  }\n  else\n  {\n    if (p[1] != '7' ||\n        p[2] != '0' ||\n        p[3] != '7' ||\n        p[4] != '0')\n      return S_OK;\n    if (p[5] == kMagicOct)\n    {\n      errorType = k_ErrorType_Corrupted;\n\n      item.Type = k_Type_Oct;\n      READ_STREAM(p + k_BinRecord_Size, k_OctRecord_Size - k_BinRecord_Size)\n      item.AlignMask = 1 - 1;\n      item.DevMajor = 0;\n      item.RDevMajor = 0;\n      item.ChkSum = 0;\n\n      if (!CheckOctRecord(p))\n        return S_OK;\n\n      READ_OCT_6 (0, item.DevMinor)\n      READ_OCT_6 (1 * 6, item.inode)\n      READ_OCT_6 (2 * 6, item.Mode)\n      READ_OCT_6 (3 * 6, item.UID)\n      READ_OCT_6 (4 * 6, item.GID)\n      READ_OCT_6 (5 * 6, item.NumLinks)\n      READ_OCT_6 (6 * 6, item.RDevMinor)\n      {\n        UInt64 mTime64;\n        READ_OCT_11 (7 * 6, mTime64)\n        item.MTime = 0;\n        if (mTime64 <= (UInt32)(Int32)-1)\n          item.MTime = (UInt32)mTime64;\n      }\n      READ_OCT_6 (7 * 6 + 11, nameSize)\n      READ_OCT_11 (8 * 6 + 11, item.Size)  // ?????\n\n      namePos = k_OctRecord_Size;\n    }\n    else\n    {\n           if (p[5] == kMagicHex)    item.Type = k_Type_Hex;\n      else if (p[5] == kMagicHexCrc) item.Type = k_Type_HexCrc;\n      else return S_OK;\n\n      errorType = k_ErrorType_Corrupted;\n\n      READ_STREAM(p + k_BinRecord_Size, k_HexRecord_Size - k_BinRecord_Size)\n\n      if (!CheckHexRecord(p))\n        return S_OK;\n\n      item.AlignMask = 4 - 1;\n      READ_HEX (0, item.inode)\n      READ_HEX (1, item.Mode)\n      READ_HEX (2, item.UID)\n      READ_HEX (3, item.GID)\n      READ_HEX (4, item.NumLinks)\n      READ_HEX (5, item.MTime)\n      READ_HEX (6, item.Size)\n      READ_HEX (7, item.DevMajor)\n      READ_HEX (8, item.DevMinor)\n      READ_HEX (9, item.RDevMajor)\n      READ_HEX (10, item.RDevMinor)\n      READ_HEX (11, nameSize)\n      READ_HEX (12, item.ChkSum)\n\n      if (item.Type == k_Type_Hex && item.ChkSum != 0)\n        return S_OK;\n\n      namePos = k_HexRecord_Size;\n    }\n  }\n\n  if (item.Mode >= (1 << 16))\n    return S_OK;\n\n  /* v23.02: we have disabled rDevMinor check because real file\n     from Apple contains rDevMinor==255 by some unknown reason\n     cpio 2.13 and older versions: it copies stat::st_rdev to archive.\n        and stat::st_rdev can be non-zero for some old linux/filesystems cases for regular files.\n     cpio 2.14 (2023) copies st_rdev to archive only if (S_ISBLK (st->st_mode) || S_ISCHR (st->st_mode))\n     v25.00: we have disabled RDevMajor check here to support some rare case created by cpio 2.13- with old linux.\n     But we still keep full check in IsArc_Cpio() to reduce false cpio detection cases.\n  */\n#if 0 // 0 : to disable check to support some old linux cpio archives.\n  if (item.RDevMajor != 0\n      // || item.RDevMinor != 0\n      )\n  {\n    if (!MY_LIN_S_ISCHR(item.Mode) &&\n        !MY_LIN_S_ISBLK(item.Mode))\n      return S_OK;\n  }\n#endif\n\n  // Size must be 0 for FIFOs and directories\n  if (item.IsDir() || MY_LIN_S_ISFIFO(item.Mode))\n    if (item.Size != 0)\n      return S_OK;\n\n  // nameSize must include the null byte\n  if (nameSize == 0 || nameSize > kNameSizeMax)\n    return S_OK;\n  item.HeaderSize = item.GetAlignedSize(namePos + nameSize);\n  const UInt32 rem = item.HeaderSize - namePos;\n  char *s = item.Name.GetBuf(rem);\n  size_t processedSize = rem;\n  RINOK(Read(s, &processedSize))\n  if (processedSize != rem)\n  {\n    item.Name.ReleaseBuf_SetEnd(0);\n    errorType = k_ErrorType_UnexpectedEnd;\n    return S_OK;\n  }\n  bool pad_error = false;\n  for (size_t i = nameSize; i < processedSize; i++)\n    if (s[i] != 0)\n      pad_error = true;\n  item.Name.ReleaseBuf_CalcLen(nameSize);\n  if (item.Name.Len() + 1 != nameSize || pad_error)\n    return S_OK;\n  errorType = k_ErrorType_OK;\n  return S_OK;\n}\n\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CObjectVector<CItem> _items;\n  CMyComPtr<IInStream> _stream;\n  UInt64 _phySize;\n  EType _type;\n  EErrorType _error;\n  bool _isArc;\n  bool _moreThanOneHardLinks_Error;\n  bool _numLinks_Error;\n  bool _pad_Error;\n  bool _symLink_Error;\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidSubType\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidPosixAttrib,\n  kpidLinks,\n  kpidINode,\n  kpidUserId,\n  kpidGroupId,\n  kpidDevMajor,\n  kpidDevMinor,\n  kpidDeviceMajor,\n  kpidDeviceMinor,\n  kpidChecksum,\n  kpidSymLink,\n  kpidStreamId, // for debug\n  kpidOffset\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidSubType: prop = k_Types[(unsigned)_type]; break;\n    case kpidPhySize: prop = _phySize; break;\n    case kpidINode: prop = true; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc)\n        v |= kpv_ErrorFlags_IsNotArc;\n      switch (_error)\n      {\n        case k_ErrorType_UnexpectedEnd: v |= kpv_ErrorFlags_UnexpectedEnd; break;\n        case k_ErrorType_Corrupted:     v |= kpv_ErrorFlags_HeadersError; break;\n        case k_ErrorType_OK:\n        case k_ErrorType_BadSignature:\n        // default:\n          break;\n      }\n      prop = v;\n      break;\n    }\n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      if (_moreThanOneHardLinks_Error)\n        v |= kpv_ErrorFlags_UnsupportedFeature; // kpv_ErrorFlags_HeadersError\n      if (_numLinks_Error\n          || _pad_Error\n          || _symLink_Error)\n        v |= kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nstatic int CompareItems(const unsigned *p1, const unsigned *p2, void *param)\n{\n  const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;\n  const unsigned index1 = *p1;\n  const unsigned index2 = *p2;\n  const CItem &i1 = items[index1];\n  const CItem &i2 = items[index2];\n  if (i1.DevMajor < i2.DevMajor) return -1;\n  if (i1.DevMajor > i2.DevMajor) return 1;\n  if (i1.DevMinor < i2.DevMinor) return -1;\n  if (i1.DevMinor > i2.DevMinor) return 1;\n  if (i1.inode < i2.inode) return -1;\n  if (i1.inode > i2.inode) return 1;\n  if (i1.IsDir())\n  {\n    if (!i2.IsDir())\n      return -1;\n  }\n  else if (i2.IsDir())\n    return 1;\n  return MyCompare(index1, index2);\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    \n    UInt64 endPos;\n    RINOK(InStream_AtBegin_GetSize(stream, endPos))\n    if (callback)\n    {\n      RINOK(callback->SetTotal(NULL, &endPos))\n    }\n\n    CInArchive arc;\n\n    arc.Stream = stream;\n    arc.Processed = 0;\n\n    for (;;)\n    {\n      CItem &item = arc.item;\n      item.HeaderPos = arc.Processed;\n      \n      RINOK(arc.GetNextItem())\n\n      _error = arc.errorType;\n      \n      if (_error != k_ErrorType_OK)\n      {\n        if (_error == k_ErrorType_BadSignature ||\n            _error == k_ErrorType_Corrupted)\n          arc.Processed = item.HeaderPos;\n        break;\n      }\n      \n      if (_items.IsEmpty())\n        _type = item.Type;\n      else if (_items.Back().Type != item.Type)\n      {\n        _error = k_ErrorType_Corrupted;\n        arc.Processed = item.HeaderPos;\n        break;\n      }\n      \n      if (item.IsTrailer())\n        break;\n      \n      item.MainIndex_ForInode = _items.Size();\n      _items.Add(item);\n\n      const UInt64 dataSize = item.GetPackSize();\n      arc.Processed += dataSize;\n      if (arc.Processed > endPos)\n      {\n        _error = k_ErrorType_UnexpectedEnd;\n        break;\n      }\n        \n      if (item.Is_SymLink() && dataSize <= (1 << 12) && item.Size != 0)\n      {\n        size_t cur = (size_t)dataSize;\n        CByteBuffer buf;\n        buf.Alloc(cur);\n        RINOK(ReadStream(stream, buf, &cur))\n        if (cur != dataSize)\n        {\n          _error = k_ErrorType_UnexpectedEnd;\n          break;\n        }\n        size_t i;\n        \n        for (i = (size_t)item.Size; i < dataSize; i++)\n          if (buf[i] != 0)\n            break;\n        if (i != dataSize)\n          _pad_Error = true;\n\n        for (i = 0; i < (size_t)item.Size; i++)\n          if (buf[i] == 0)\n            break;\n        if (i != (size_t)item.Size)\n          _symLink_Error = true;\n        else\n          _items.Back().Data.CopyFrom(buf, (size_t)item.Size);\n      }\n      else if (dataSize != 0)\n      {\n        UInt64 newPos;\n        RINOK(stream->Seek((Int64)dataSize, STREAM_SEEK_CUR, &newPos))\n        if (arc.Processed != newPos)\n          return E_FAIL;\n      }\n\n      if (callback && (_items.Size() & 0xFFF) == 0)\n      {\n        const UInt64 numFiles = _items.Size();\n        RINOK(callback->SetCompleted(&numFiles, &item.HeaderPos))\n      }\n    }\n\n    _phySize = arc.Processed;\n  }\n\n  {\n    if (_error != k_ErrorType_OK)\n    {\n      // we try to reduce probability of false detection\n      if (_items.Size() == 0)\n        return S_FALSE;\n      // bin file uses small signature. So we do additional check for single item case.\n      if (_items.Size() == 1 && _items[0].IsBin())\n        return S_FALSE;\n    }\n    else\n    {\n      // Read tailing zeros.\n      // Most of cpio files use 512-bytes aligned zeros\n      // rare case: 4K/8K aligment is possible also\n      const unsigned kTailSize_MAX = 1 << 9;\n      Byte buf[kTailSize_MAX];\n      \n      unsigned pos = (unsigned)_phySize & (kTailSize_MAX - 1);\n      if (pos != 0) // use this check to support 512 bytes alignment only\n      for (;;)\n      {\n        const unsigned rem = kTailSize_MAX - pos;\n        size_t processed = rem;\n        RINOK(ReadStream(stream, buf + pos, &processed))\n        if (processed != rem)\n          break;\n        for (; pos < kTailSize_MAX && buf[pos] == 0; pos++)\n        {}\n        if (pos != kTailSize_MAX)\n          break;\n        _phySize += processed;\n        pos = 0;\n\n        //       use break to support 512   bytes alignment zero tail\n        // don't use break to support 512*n bytes alignment zero tail\n        break;\n      }\n    }\n  }\n  \n  {\n    /* there was such cpio archive example with hard links:\n       {\n         all hard links (same dev/inode) are stored in neighboring items, and\n           (item.Size == 0)  for non last hard link items\n           (item.Size != 0)  for     last hard link item\n       }\n       but here we sort items by (dev/inode) to support cases\n       where hard links (same dev/inode) are not stored in neighboring items.\n\n       // note: some cpio files have (numLinks == 0) ??\n    */\n\n    CUIntVector indices;\n    {\n      const unsigned numItems = _items.Size();\n      indices.ClearAndSetSize(numItems);\n      if (numItems != 0)\n      {\n        unsigned *vals = &indices[0];\n        for (unsigned i = 0; i < numItems; i++)\n          vals[i] = i;\n        indices.Sort(CompareItems, (void *)&_items);\n      }\n    }\n\n    /* Note: if cpio archive (maybe incorrect) contains\n       more then one non empty streams with identical inode number,\n       we want to extract all such data streams too.\n       \n       So we place items with identical inode to groups:\n       all items in group will have same MainIndex_ForInode,\n       that is index of last item in group with (Size != 0).\n       Another (non last) items in group have (Size == 0).\n       If there are another hard links with same inode number\n       after (Size != 0) item, we place them to another next group(s).\n       \n       Check it: maybe we should use single group for items\n       with identical inode instead, and ignore some extra data streams ?\n    */\n    \n    for (unsigned i = 0; i < indices.Size();)\n    {\n      unsigned k;\n      {\n        const CItem &item_Base = _items[indices[i]];\n\n        if (item_Base.IsDir())\n        {\n          i++;\n          continue;\n        }\n        \n        if (i != 0)\n        {\n          const CItem &item_Prev = _items[indices[i - 1]];\n          if (!item_Prev.IsDir())\n            if (item_Base.IsSame_inode_Dev(item_Prev))\n              _moreThanOneHardLinks_Error = true;\n        }\n        \n        if (item_Base.Size != 0)\n        {\n          if (item_Base.NumLinks != 1)\n            _numLinks_Error = true;\n          i++;\n          continue;\n        }\n        \n        for (k = i + 1; k < indices.Size();)\n        {\n          const CItem &item = _items[indices[k]];\n          if (item.IsDir())\n            break;\n          if (!item.IsSame_inode_Dev(item_Base))\n            break;\n          k++;\n          if (item.Size != 0)\n            break;\n        }\n      }\n\n      const unsigned numLinks = k - i;\n      for (;;)\n      {\n        CItem &item = _items[indices[i]];\n        if (item.NumLinks != numLinks)\n          _numLinks_Error = true;\n        if (++i == k)\n          break;\n        // if (item.Size == 0)\n        item.MainIndex_ForInode = indices[k - 1];\n      }\n    }\n  }\n\n  _isArc = true;\n  _stream = stream;\n\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _items.Clear();\n  _stream.Release();\n  _phySize = 0;\n  _type = k_Type_BinLe;\n  _isArc = false;\n  _moreThanOneHardLinks_Error = false;\n  _numLinks_Error = false;\n  _pad_Error = false;\n  _symLink_Error = false;\n  _error = k_ErrorType_OK;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  const CItem &item = _items[index];\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n#ifdef _WIN32\n      UString u;\n      ConvertUTF8ToUnicode(item.Name, u);\n#else\n      const UString u = MultiByteToUnicodeString(item.Name, CP_OEMCP);\n#endif\n      prop = NItemName::GetOsPath(u);\n      break;\n    }\n    case kpidIsDir: prop = item.IsDir(); break;\n\n    case kpidSize:\n      prop = (UInt64)_items[item.MainIndex_ForInode].Size;\n      break;\n    \n    case kpidPackSize:\n      prop = (UInt64)item.GetPackSize();\n      break;\n    \n    case kpidMTime:\n    {\n      if (item.MTime != 0)\n        PropVariant_SetFrom_UnixTime(prop, item.MTime);\n      break;\n    }\n    case kpidPosixAttrib: prop = item.Mode; break;\n    case kpidINode: prop = item.inode; break;\n    case kpidStreamId:\n      if (!item.IsDir())\n        prop = (UInt32)item.MainIndex_ForInode;\n      break;\n    case kpidDevMajor: prop = (UInt32)item.DevMajor; break;\n    case kpidDevMinor: prop = (UInt32)item.DevMinor; break;\n\n    case kpidUserId: prop = item.UID; break;\n    case kpidGroupId: prop = item.GID; break;\n\n    case kpidSymLink:\n      if (item.Is_SymLink() && item.Data.Size() != 0)\n      {\n        AString s;\n        s.SetFrom_CalcLen((const char *)(const void *)(const Byte *)item.Data, (unsigned)item.Data.Size());\n        if (s.Len() == item.Data.Size())\n        {\n#ifdef _WIN32\n          UString u;\n          ConvertUTF8ToUnicode(s, u);\n#else\n          const UString u = MultiByteToUnicodeString(s, CP_OEMCP);\n#endif\n          prop = u;\n        }\n      }\n      break;\n\n    case kpidLinks: prop = item.NumLinks; break;\n    case kpidDeviceMajor:\n      // if (item.RDevMajor != 0)\n        prop = (UInt32)item.RDevMajor;\n      break;\n    case kpidDeviceMinor:\n      // if (item.RDevMinor != 0)\n        prop = (UInt32)item.RDevMinor;\n      break;\n    case kpidChecksum:\n      if (item.IsCrcFormat())\n        prop = item.ChkSum;\n      break;\n    case kpidOffset: prop = item.GetDataPosition(); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithSum\n  , ISequentialOutStream\n)\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt32 _checksum;\n  bool _calculate;\npublic:\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init(bool calculate)\n  {\n    _calculate = calculate;\n    _checksum = 0;\n  }\n  UInt32 GetChecksum() const { return _checksum; }\n};\n\n\nZ7_COM7F_IMF(COutStreamWithSum::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  if (processedSize)\n    *processedSize = size;\n  if (_calculate)\n  {\n    const Byte *p = (const Byte *)data;\n    const Byte *lim = p + size;\n    UInt32 sum = _checksum;\n    if (size >= 4)\n    {\n      lim -= 4 - 1;\n      do\n      {\n        sum += p[0] + p[1] + p[2] + p[3];\n        p += 4;\n      }\n      while (p < lim);\n      lim += 4 - 1;\n    }\n    if (p != lim) { sum += *p++;\n    if (p != lim) { sum += *p++;\n    if (p != lim) { sum += *p++; }}}\n    _checksum = sum;\n  }\n  return result;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem &item2 = _items[index];\n    const CItem &item = _items[item2.MainIndex_ForInode];\n    totalSize += item.Size;\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_stream);\n  CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSum> outStreamSum;\n\n  UInt64 total_PackSize = 0;\n  UInt64 total_UnpackSize = 0;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = total_PackSize;\n    lps->OutSize = total_UnpackSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem &item2 = _items[index];\n    const CItem &item = _items[item2.MainIndex_ForInode];\n    {\n      CMyComPtr<ISequentialOutStream> outStream;\n      RINOK(extractCallback->GetStream(index, &outStream, askMode))\n        \n      total_PackSize += item2.GetPackSize();\n      total_UnpackSize += item.Size;\n      \n      if (item2.IsDir())\n      {\n        RINOK(extractCallback->PrepareOperation(askMode))\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        continue;\n      }\n      if (!testMode && !outStream)\n        continue;\n      outStreamSum->Init(item.IsCrcFormat());\n      outStreamSum->SetStream(outStream);\n      RINOK(extractCallback->PrepareOperation(askMode))\n    }\n    RINOK(InStream_SeekSet(_stream, item.GetDataPosition()))\n    inStream->Init(item.Size);\n    RINOK(copyCoder.Interface()->Code(inStream, outStreamSum, NULL, NULL, lps))\n    outStreamSum->ReleaseStream();\n    Int32 res = NExtract::NOperationResult::kDataError;\n    if (copyCoder->TotalSize == item.Size)\n    {\n      res = NExtract::NOperationResult::kOK;\n      if (item.IsCrcFormat() && item.ChkSum != outStreamSum->GetChecksum())\n        res = NExtract::NOperationResult::kCRCError;\n    }\n    RINOK(extractCallback->SetOperationResult(res))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  const CItem &item2 = _items[index];\n  const CItem &item = _items[item2.MainIndex_ForInode];\n  return CreateLimitedInStream(_stream, item.GetDataPosition(), item.Size, stream);\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = {\n    5, '0', '7', '0', '7', '0',\n    2, kMagicBin0, kMagicBin1,\n    2, kMagicBin1, kMagicBin0 };\n\nREGISTER_ARC_I(\n  \"Cpio\", \"cpio\", NULL, 0xED,\n  k_Signature,\n  0,\n  NArcInfoFlags::kMultiSignature,\n  IsArc_Cpio)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/CramfsHandler.cpp",
    "content": "﻿// CramfsHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/7zCrc.h\"\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/LzmaDec.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyLinux.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/ZlibDecoder.h\"\n\nnamespace NArchive {\nnamespace NCramfs {\n\nstatic const Byte kSignature[] =\n  { 'C','o','m','p','r','e','s','s','e','d',' ','R','O','M','F','S' };\n\nstatic const UInt32 kArcSizeMax = (256 + 16) << 20;\nstatic const UInt32 kNumFilesMax = (1 << 19);\nstatic const unsigned kNumDirLevelsMax = (1 << 8);\n\nstatic const UInt32 kHeaderSize = 0x40;\nstatic const unsigned kHeaderNameSize = 16;\nstatic const UInt32 kNodeSize = 12;\n\nstatic const UInt32 kFlag_FsVer2 = (1 << 0);\n\nstatic const unsigned k_Flags_BlockSize_Shift = 11;\nstatic const unsigned k_Flags_BlockSize_Mask = 7;\nstatic const unsigned k_Flags_Method_Shift = 14;\nstatic const unsigned k_Flags_Method_Mask = 3;\n\n/*\n  There is possible collision in flags:\n    - Original CramFS writes 0 in method field. But it uses ZLIB.\n    - Modified CramFS writes 0 in method field for \"NONE\" compression?\n  How to solve that collision?\n*/\n\n#define k_Flags_Method_NONE 0\n#define k_Flags_Method_ZLIB 1\n#define k_Flags_Method_LZMA 2\n\nstatic const char * const k_Methods[] =\n{\n    \"Copy\"\n  , \"ZLIB\"\n  , \"LZMA\"\n  , \"Unknown\"\n};\n\nstatic const CUInt32PCharPair k_Flags[] =\n{\n  { 0, \"Ver2\" },\n  { 1, \"SortedDirs\" },\n  { 8, \"Holes\" },\n  { 9, \"WrongSignature\" },\n  { 10, \"ShiftedRootOffset\" }\n};\n\nstatic const unsigned kBlockSizeLog = 12;\n\n/*\nstruct CNode\n{\n  UInt16 Mode;\n  UInt16 Uid;\n  UInt32 Size;\n  Byte Gid;\n  UInt32 NameLen;\n  UInt32 Offset;\n\n  void Parse(const Byte *p)\n  {\n    Mode = GetUi16(p);\n    Uid = GetUi16(p + 2);\n    Size = Get32(p + 4) & 0xFFFFFF;\n    Gid = p[7];\n    NameLen = p[8] & 0x3F;\n    Offset = Get32(p + 8) >> 6;\n  }\n};\n*/\n\n#define Get32(p) (be ? GetBe32(p) : GetUi32(p))\n\nstatic UInt32 GetMode(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }\nstatic bool IsDir(const Byte *p, bool be) { return MY_LIN_S_ISDIR(GetMode(p, be)); }\n\nstatic UInt32 GetSize(const Byte *p, bool be)\n{\n  if (be)\n    return GetBe32(p + 4) >> 8;\n  else\n    return GetUi32(p + 4) & 0xFFFFFF;\n}\n\nstatic UInt32 GetNameLen(const Byte *p, bool be)\n{\n  if (be)\n    return (p[8] & 0xFC);\n  else\n    return ((UInt32)p[8] & (UInt32)0x3F) << 2;\n}\n\nstatic UInt32 GetOffset(const Byte *p, bool be)\n{\n  if (be)\n    return (GetBe32(p + 8) & 0x03FFFFFF) << 2;\n  else\n    return GetUi32(p + 8) >> 6 << 2;\n}\n\nstruct CItem\n{\n  UInt32 Offset;\n  int Parent;\n};\n\nstruct CHeader\n{\n  bool be;\n  UInt32 Size;\n  UInt32 Flags;\n  // UInt32 Future;\n  UInt32 Crc;\n  // UInt32 Edition;\n  UInt32 NumBlocks;\n  UInt32 NumFiles;\n  char Name[kHeaderNameSize];\n\n  bool Parse(const Byte *p)\n  {\n    if (memcmp(p + 16, kSignature, Z7_ARRAY_SIZE(kSignature)) != 0)\n      return false;\n    switch (GetUi32(p))\n    {\n      case 0x28CD3D45: be = false; break;\n      case 0x453DCD28: be = true; break;\n      default: return false;\n    }\n    Size = Get32(p + 4);\n    Flags = Get32(p + 8);\n    // Future = Get32(p + 0xC);\n    Crc = Get32(p + 0x20);\n    // Edition = Get32(p + 0x24);\n    NumBlocks = Get32(p + 0x28);\n    NumFiles = Get32(p + 0x2C);\n    memcpy(Name, p + 0x30, kHeaderNameSize);\n    return true;\n  }\n\n  bool IsVer2() const { return (Flags & kFlag_FsVer2) != 0; }\n  unsigned GetBlockSizeShift() const { return (unsigned)(Flags >> k_Flags_BlockSize_Shift) & k_Flags_BlockSize_Mask; }\n  unsigned GetMethod() const { return (unsigned)(Flags >> k_Flags_Method_Shift) & k_Flags_Method_Mask; }\n};\n\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CRecordVector<CItem> _items;\n  CMyComPtr<IInStream> _stream;\n  Byte *_data;\n  UInt32 _size;\n  UInt32 _headersSize;\n\n  UInt32 _errorFlags;\n  bool _isArc;\n\n  CHeader _h;\n  UInt32 _phySize;\n\n  unsigned _method;\n  unsigned _blockSizeLog;\n\n  // Current file\n\n  NCompress::NZlib::CDecoder *_zlibDecoderSpec;\n  CMyComPtr<ICompressCoder> _zlibDecoder;\n\n  CBufInStream *_inStreamSpec;\n  CMyComPtr<ISequentialInStream> _inStream;\n\n  CBufPtrSeqOutStream *_outStreamSpec;\n  CMyComPtr<ISequentialOutStream> _outStream;\n\n  UInt32 _curBlocksOffset;\n  UInt32 _curNumBlocks;\n\n  HRESULT OpenDir(int parent, UInt32 baseOffsetBase, unsigned level);\n  HRESULT Open2(IInStream *inStream);\n  AString GetPath(unsigned index) const;\n  bool GetPackSize(unsigned index, UInt32 &res) const;\n  void Free();\n\n  UInt32 GetNumBlocks(UInt32 size) const\n  {\n    return (size + ((UInt32)1 << _blockSizeLog) - 1) >> _blockSizeLog;\n  }\n\n  void UpdatePhySize(UInt32 s)\n  {\n    if (_phySize < s)\n      _phySize = s;\n  }\n\npublic:\n  CHandler(): _data(NULL) {}\n  ~CHandler() { Free(); }\n  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidPosixAttrib\n  // kpidOffset\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidVolumeName,\n  kpidBigEndian,\n  kpidCharacts,\n  kpidClusterSize,\n  kpidMethod,\n  kpidHeadersSize,\n  kpidNumSubFiles,\n  kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nHRESULT CHandler::OpenDir(int parent, UInt32 baseOffset, unsigned level)\n{\n  const Byte *p = _data + baseOffset;\n  bool be = _h.be;\n  if (!IsDir(p, be))\n    return S_OK;\n  UInt32 offset = GetOffset(p, be);\n  UInt32 size = GetSize(p, be);\n  if (offset == 0 && size == 0)\n    return S_OK;\n  UInt32 end = offset + size;\n  if (offset < kHeaderSize || end > _size || level > kNumDirLevelsMax)\n    return S_FALSE;\n  UpdatePhySize(end);\n  if (end > _headersSize)\n    _headersSize = end;\n\n  unsigned startIndex = _items.Size();\n  \n  while (size != 0)\n  {\n    if (size < kNodeSize || (UInt32)_items.Size() >= kNumFilesMax)\n      return S_FALSE;\n    CItem item;\n    item.Parent = parent;\n    item.Offset = offset;\n    _items.Add(item);\n    UInt32 nodeLen = kNodeSize + GetNameLen(_data + offset, be);\n    if (size < nodeLen)\n      return S_FALSE;\n    offset += nodeLen;\n    size -= nodeLen;\n  }\n\n  unsigned endIndex = _items.Size();\n  for (unsigned i = startIndex; i < endIndex; i++)\n  {\n    RINOK(OpenDir((int)i, _items[i].Offset, level + 1))\n  }\n  return S_OK;\n}\n\nHRESULT CHandler::Open2(IInStream *inStream)\n{\n  Byte buf[kHeaderSize];\n  RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize))\n  if (!_h.Parse(buf))\n    return S_FALSE;\n  _method = k_Flags_Method_ZLIB;\n  _blockSizeLog = kBlockSizeLog;\n  _phySize = kHeaderSize;\n  if (_h.IsVer2())\n  {\n    _method = _h.GetMethod();\n    // FIT IT. Now we don't know correct way to work with collision in method field.\n    if (_method == k_Flags_Method_NONE)\n      _method = k_Flags_Method_ZLIB;\n    _blockSizeLog = kBlockSizeLog + _h.GetBlockSizeShift();\n    if (_h.Size < kHeaderSize || _h.Size > kArcSizeMax || _h.NumFiles > kNumFilesMax)\n      return S_FALSE;\n    _phySize = _h.Size;\n  }\n  else\n  {\n    UInt64 size;\n    RINOK(InStream_GetSize_SeekToEnd(inStream, size))\n    if (size > kArcSizeMax)\n      size = kArcSizeMax;\n    _h.Size = (UInt32)size;\n    RINOK(InStream_SeekSet(inStream, kHeaderSize))\n  }\n  _data = (Byte *)MidAlloc(_h.Size);\n  if (!_data)\n    return E_OUTOFMEMORY;\n  memcpy(_data, buf, kHeaderSize);\n  size_t processed = _h.Size - kHeaderSize;\n  RINOK(ReadStream(inStream, _data + kHeaderSize, &processed))\n  if (processed < kNodeSize)\n    return S_FALSE;\n  _size = kHeaderSize + (UInt32)processed;\n  if (_h.IsVer2())\n  {\n    if (_size != _h.Size)\n      _errorFlags = kpv_ErrorFlags_UnexpectedEnd;\n    else\n    {\n      SetUi32(_data + 0x20, 0)\n      if (CrcCalc(_data, _h.Size) != _h.Crc)\n      {\n        _errorFlags = kpv_ErrorFlags_HeadersError;\n        // _errorMessage = \"CRC error\";\n      }\n    }\n    if (_h.NumFiles >= 1)\n      _items.ClearAndReserve(_h.NumFiles - 1);\n  }\n  \n  RINOK(OpenDir(-1, kHeaderSize, 0))\n  \n  if (!_h.IsVer2())\n  {\n    FOR_VECTOR (i, _items)\n    {\n      const CItem &item = _items[i];\n      const Byte *p = _data + item.Offset;\n      bool be = _h.be;\n      if (IsDir(p, be))\n        continue;\n      UInt32 offset = GetOffset(p, be);\n      if (offset < kHeaderSize)\n        continue;\n      UInt32 numBlocks = GetNumBlocks(GetSize(p, be));\n      if (numBlocks == 0)\n        continue;\n      UInt32 start = offset + numBlocks * 4;\n      if (start > _size)\n        continue;\n      UInt32 end = Get32(_data + start - 4);\n      if (end >= start)\n        UpdatePhySize(end);\n    }\n\n    // Read tailing zeros. Most cramfs archives use 4096-bytes aligned zeros\n    const UInt32 kTailSize_MAX = 1 << 12;\n    UInt32 endPos = (_phySize + kTailSize_MAX - 1) & ~(kTailSize_MAX - 1);\n    if (endPos > _size)\n      endPos = _size;\n    UInt32 pos;\n    for (pos = _phySize; pos < endPos && _data[pos] == 0; pos++);\n    if (pos == endPos)\n      _phySize = endPos;\n  }\n  return S_OK;\n}\n\nAString CHandler::GetPath(unsigned index) const\n{\n  unsigned len = 0;\n  unsigned indexMem = index;\n  for (;;)\n  {\n    const CItem &item = _items[index];\n    const Byte *p = _data + item.Offset;\n    unsigned size = GetNameLen(p, _h.be);\n    p += kNodeSize;\n    unsigned i;\n    for (i = 0; i < size && p[i]; i++);\n    len += i + 1;\n    index = (unsigned)item.Parent;\n    if (item.Parent < 0)\n      break;\n  }\n  len--;\n\n  AString path;\n  char *dest = path.GetBuf_SetEnd(len) + len;\n  index = indexMem;\n  for (;;)\n  {\n    const CItem &item = _items[index];\n    const Byte *p = _data + item.Offset;\n    unsigned size = GetNameLen(p, _h.be);\n    p += kNodeSize;\n    unsigned i;\n    for (i = 0; i < size && p[i]; i++);\n    dest -= i;\n    memcpy(dest, p, i);\n    index = (unsigned)item.Parent;\n    if (item.Parent < 0)\n      break;\n    *(--dest) = CHAR_PATH_SEPARATOR;\n  }\n  return path;\n}\n\nbool CHandler::GetPackSize(unsigned index, UInt32 &res) const\n{\n  res = 0;\n  const CItem &item = _items[index];\n  const Byte *p = _data + item.Offset;\n  const bool be = _h.be;\n  const UInt32 offset = GetOffset(p, be);\n  if (offset < kHeaderSize)\n    return false;\n  const UInt32 numBlocks = GetNumBlocks(GetSize(p, be));\n  if (numBlocks == 0)\n    return true;\n  const UInt32 start = offset + numBlocks * 4;\n  if (start > _size)\n    return false;\n  const UInt32 end = Get32(_data + start - 4);\n  if (end < start)\n    return false;\n  res = end - start;\n  return true;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* callback */))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    RINOK(Open2(stream))\n    _isArc = true;\n    _stream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nvoid CHandler::Free()\n{\n  MidFree(_data);\n  _data = NULL;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _phySize = 0;\n  _errorFlags = 0;\n  _headersSize = 0;\n  _items.Clear();\n  _stream.Release();\n  Free();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidVolumeName:\n    {\n      char dest[kHeaderNameSize + 4];\n      memcpy(dest, _h.Name, kHeaderNameSize);\n      dest[kHeaderNameSize] = 0;\n      prop = dest;\n      break;\n    }\n    case kpidBigEndian: prop = _h.be; break;\n    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;\n    case kpidMethod: prop = k_Methods[_method]; break;\n    case kpidClusterSize: prop = (UInt32)1 << _blockSizeLog; break;\n    case kpidNumBlocks: if (_h.IsVer2()) prop = _h.NumBlocks; break;\n    case kpidNumSubFiles: if (_h.IsVer2()) prop = _h.NumFiles; break;\n    case kpidPhySize: prop = _phySize; break;\n    case kpidHeadersSize: prop = _headersSize; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = _errorFlags;\n      if (!_isArc)\n        v |= kpv_ErrorFlags_IsNotArc;\n      prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CItem &item = _items[index];\n  const Byte *p = _data + item.Offset;\n  bool be = _h.be;\n  bool isDir = IsDir(p, be);\n  switch (propID)\n  {\n    case kpidPath: prop = MultiByteToUnicodeString(GetPath(index), CP_OEMCP); break;\n    case kpidIsDir: prop = isDir; break;\n    // case kpidOffset: prop = (UInt32)GetOffset(p, be); break;\n    case kpidSize: if (!isDir) prop = GetSize(p, be); break;\n    case kpidPackSize:\n      if (!isDir)\n      {\n        UInt32 size;\n        if (GetPackSize(index, size))\n          prop = size;\n      }\n      break;\n    case kpidPosixAttrib: prop = (UInt32)GetMode(p, be); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nclass CCramfsInStream: public CCachedInStream\n{\n  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) Z7_override;\npublic:\n  CHandler *Handler;\n};\n\nHRESULT CCramfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\n{\n  return Handler->ReadBlock(blockIndex, dest, blockSize);\n}\n\nHRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\n{\n  if (_method == k_Flags_Method_ZLIB)\n  {\n    if (!_zlibDecoder)\n    {\n      _zlibDecoderSpec = new NCompress::NZlib::CDecoder();\n      _zlibDecoder = _zlibDecoderSpec;\n    }\n  }\n  else\n  {\n    if (_method != k_Flags_Method_LZMA)\n    {\n      // probably we must support no-compression archives here.\n      return E_NOTIMPL;\n    }\n  }\n\n  const bool be = _h.be;\n  const Byte *p2 = _data + (_curBlocksOffset + (UInt32)blockIndex * 4);\n  const UInt32 start = (blockIndex == 0 ? _curBlocksOffset + _curNumBlocks * 4: Get32(p2 - 4));\n  const UInt32 end = Get32(p2);\n  if (end < start || end > _size)\n    return S_FALSE;\n  const UInt32 inSize = end - start;\n\n  if (_method == k_Flags_Method_LZMA)\n  {\n    const unsigned kLzmaHeaderSize = LZMA_PROPS_SIZE + 4;\n    if (inSize < kLzmaHeaderSize)\n      return S_FALSE;\n    const Byte *p = _data + start;\n    UInt32 destSize32 = GetUi32(p + LZMA_PROPS_SIZE);\n    if (destSize32 > blockSize)\n      return S_FALSE;\n    SizeT destLen = destSize32;\n    SizeT srcLen = inSize - kLzmaHeaderSize;\n    ELzmaStatus status;\n    SRes res = LzmaDecode(dest, &destLen, p + kLzmaHeaderSize, &srcLen,\n        p, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc);\n    if (res != SZ_OK\n        || (status != LZMA_STATUS_FINISHED_WITH_MARK &&\n            status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)\n        || destLen != destSize32\n        || srcLen != inSize - kLzmaHeaderSize)\n      return S_FALSE;\n    return S_OK;\n  }\n\n  if (!_inStream)\n  {\n    _inStreamSpec = new CBufInStream();\n    _inStream = _inStreamSpec;\n  }\n  if (!_outStream)\n  {\n    _outStreamSpec = new CBufPtrSeqOutStream();\n    _outStream = _outStreamSpec;\n  }\n  _inStreamSpec->Init(_data + start, inSize);\n  _outStreamSpec->Init(dest, blockSize);\n  RINOK(_zlibDecoder->Code(_inStream, _outStream, NULL, NULL, NULL))\n  return (inSize == _zlibDecoderSpec->GetInputProcessedSize() &&\n      _outStreamSpec->GetPos() == blockSize) ? S_OK : S_FALSE;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  bool be = _h.be;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const Byte *p = _data + _items[allFilesMode ? i : indices[i]].Offset;\n    if (!IsDir(p, be))\n      totalSize += GetSize(p, be);\n  }\n  extractCallback->SetTotal(totalSize);\n\n  UInt64 totalPackSize;\n  totalSize = totalPackSize = 0;\n  \n  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\n  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  for (i = 0; i < numItems; i++)\n  {\n    lps->InSize = totalPackSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    CMyComPtr<ISequentialOutStream> outStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem &item = _items[index];\n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n    const Byte *p = _data + item.Offset;\n\n    if (IsDir(p, be))\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    UInt32 curSize = GetSize(p, be);\n    totalSize += curSize;\n    UInt32 packSize;\n    if (GetPackSize(index, packSize))\n      totalPackSize += packSize;\n\n    if (!testMode && !outStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    UInt32 offset = GetOffset(p, be);\n    if (offset < kHeaderSize)\n      curSize = 0;\n\n    int res = NExtract::NOperationResult::kDataError;\n    {\n      CMyComPtr<ISequentialInStream> inSeqStream;\n      HRESULT hres = GetStream(index, &inSeqStream);\n      if (hres == E_OUTOFMEMORY)\n        return E_OUTOFMEMORY;\n      if (hres == S_FALSE || !inSeqStream)\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n      else\n      {\n        RINOK(hres)\n        {\n          hres = copyCoder->Code(inSeqStream, outStream, NULL, NULL, progress);\n          if (hres == S_OK)\n          {\n            if (copyCoderSpec->TotalSize == curSize)\n              res = NExtract::NOperationResult::kOK;\n          }\n          else if (hres == E_NOTIMPL)\n            res = NExtract::NOperationResult::kUnsupportedMethod;\n          else if (hres != S_FALSE)\n            return hres;\n        }\n      }\n    }\n    RINOK(extractCallback->SetOperationResult(res))\n  }\n\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n\n  const CItem &item = _items[index];\n  const Byte *p = _data + item.Offset;\n\n  bool be = _h.be;\n  if (IsDir(p, be))\n    return E_FAIL;\n\n  UInt32 size = GetSize(p, be);\n  UInt32 numBlocks = GetNumBlocks(size);\n  UInt32 offset = GetOffset(p, be);\n  if (offset < kHeaderSize)\n  {\n    if (offset != 0)\n      return S_FALSE;\n    CBufInStream *streamSpec = new CBufInStream;\n    CMyComPtr<IInStream> streamTemp = streamSpec;\n    streamSpec->Init(NULL, 0);\n    *stream = streamTemp.Detach();\n    return S_OK;\n  }\n\n  if (offset + numBlocks * 4 > _size)\n    return S_FALSE;\n  UInt32 prev = offset;\n  for (UInt32 i = 0; i < numBlocks; i++)\n  {\n    UInt32 next = Get32(_data + offset + i * 4);\n    if (next < prev || next > _size)\n      return S_FALSE;\n    prev = next;\n  }\n\n  CCramfsInStream *streamSpec = new CCramfsInStream;\n  CMyComPtr<IInStream> streamTemp = streamSpec;\n  _curNumBlocks = numBlocks;\n  _curBlocksOffset = offset;\n  streamSpec->Handler = this;\n  if (!streamSpec->Alloc(_blockSizeLog, 21 - _blockSizeLog))\n    return E_OUTOFMEMORY;\n  streamSpec->Init(size);\n  *stream = streamTemp.Detach();\n\n  return S_OK;\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"CramFS\", \"cramfs\", NULL, 0xD3,\n  kSignature,\n  16,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/DllExports2.cpp",
    "content": "﻿// DLLExports2.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/MyWindows.h\"\n#include \"../../Common/MyInitGuid.h\"\n\n#if defined(Z7_LARGE_PAGES)\n#include \"../../../C/Alloc.h\"\n#endif\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../../Windows/NtCheck.h\"\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../ICoder.h\"\n#include \"../IPassword.h\"\n\n#include \"../Common/CreateCoder.h\"\n\n#include \"IArchive.h\"\n\n\n#ifdef _WIN32\n\n#if defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)\n#define NT_CHECK_FAIL_ACTION return FALSE;\n#endif\n\nstatic\nHINSTANCE g_hInstance;\n\nextern \"C\"\nBOOL WINAPI DllMain(\n  #ifdef UNDER_CE\n  HANDLE\n  #else\n  HINSTANCE\n  #endif\n  hInstance, DWORD dwReason, LPVOID /*lpReserved*/);\n\nextern \"C\"\nBOOL WINAPI DllMain(\n  #ifdef UNDER_CE\n  HANDLE\n  #else\n  HINSTANCE\n  #endif\n  hInstance, DWORD dwReason, LPVOID /*lpReserved*/)\n{\n  if (dwReason == DLL_PROCESS_ATTACH)\n  {\n    // OutputDebugStringA(\"7z.dll DLL_PROCESS_ATTACH\");\n    g_hInstance = (HINSTANCE)hInstance;\n    NT_CHECK\n  }\n  /*\n  if (dwReason == DLL_PROCESS_DETACH)\n  {\n    OutputDebugStringA(\"7z.dll DLL_PROCESS_DETACH\");\n  }\n  */\n  return TRUE;\n}\n\n#else //  _WIN32\n\n#include \"../../Common/StringConvert.h\"\n// #include <stdio.h>\n\n// STDAPI LibStartup();\nstatic __attribute__((constructor)) void Init_ForceToUTF8();\nstatic __attribute__((constructor)) void Init_ForceToUTF8()\n{\n  g_ForceToUTF8 = IsNativeUTF8();\n  // printf(\"\\nDLLExports2.cpp::Init_ForceToUTF8 =%d\\n\", g_ForceToUTF8 ? 1 : 0);\n}\n\n#endif // _WIN32\n\n\nZ7_DEFINE_GUID(CLSID_CArchiveHandler,\n    k_7zip_GUID_Data1,\n    k_7zip_GUID_Data2,\n    k_7zip_GUID_Data3_Common,\n    0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00);\n\nSTDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);\nSTDAPI CreateHasher(const GUID *clsid, IHasher **hasher);\nSTDAPI CreateArchiver(const GUID *clsid, const GUID *iid, void **outObject);\n\nSTDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject);\nSTDAPI CreateObject(const GUID *clsid, const GUID *iid, void **outObject)\n{\n  // COM_TRY_BEGIN\n  *outObject = NULL;\n  if (*iid == IID_ICompressCoder ||\n      *iid == IID_ICompressCoder2 ||\n      *iid == IID_ICompressFilter)\n    return CreateCoder(clsid, iid, outObject);\n  if (*iid == IID_IHasher)\n    return CreateHasher(clsid, (IHasher **)outObject);\n  return CreateArchiver(clsid, iid, outObject);\n  // COM_TRY_END\n}\n\nSTDAPI SetLargePageMode();\nSTDAPI SetLargePageMode()\n{\n  #if defined(Z7_LARGE_PAGES)\n  #ifdef _WIN32\n  SetLargePageSize();\n  #endif\n  #endif\n  return S_OK;\n}\n\nextern bool g_CaseSensitive;\n\nSTDAPI SetCaseSensitive(Int32 caseSensitive);\nSTDAPI SetCaseSensitive(Int32 caseSensitive)\n{\n  g_CaseSensitive = (caseSensitive != 0);\n  return S_OK;\n}\n\n/*\nUInt32 g_ClientVersion;\nSTDAPI SetClientVersion(UInt32 version);\nSTDAPI SetClientVersion(UInt32 version)\n{\n  g_ClientVersion = version;\n  return S_OK;\n}\n*/\n\n/*\nSTDAPI SetProperty(Int32 id, const PROPVARIANT *value);\nSTDAPI SetProperty(Int32 id, const PROPVARIANT *value)\n{\n  return S_OK;\n}\n*/\n\n#ifdef Z7_EXTERNAL_CODECS\n\nCExternalCodecs g_ExternalCodecs;\n\nSTDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo);\nSTDAPI SetCodecs(ICompressCodecsInfo *compressCodecsInfo)\n{\n  COM_TRY_BEGIN\n\n  // OutputDebugStringA(compressCodecsInfo ? \"SetCodecs\" : \"SetCodecs NULL\");\n  if (compressCodecsInfo)\n  {\n    g_ExternalCodecs.GetCodecs = compressCodecsInfo;\n    return g_ExternalCodecs.Load();\n  }\n  g_ExternalCodecs.ClearAndRelease();\n  return S_OK;\n\n  COM_TRY_END\n}\n\n#else\n\nSTDAPI SetCodecs(ICompressCodecsInfo *);\nSTDAPI SetCodecs(ICompressCodecsInfo *)\n{\n  return S_OK;\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/DmgHandler.cpp",
    "content": "﻿// DmgHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/AutoPtr.h\"\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer2.h\"\n#include \"../../Common/MyXml.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/BZip2Decoder.h\"\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/LzfseDecoder.h\"\n#include \"../Compress/XzDecoder.h\"\n#include \"../Compress/ZlibDecoder.h\"\n\n#include \"Common/OutStreamWithCRC.h\"\n\n// #define DMG_SHOW_RAW\n\n// #define SHOW_DEBUG_INFO\n\n/* for debug only: we can use block cache also for METHOD_COPY blocks.\n   It can reduce the number of Stream->Read() requests.\n   But it can increase memory usage.\n   Note: METHOD_COPY blocks are not fused usually.\n   But if METHOD_COPY blocks is fused in some dmg example,\n   block size can exceed k_Chunk_Size_MAX.\n   So we don't use cache for METHOD_COPY block, if (block_size > k_Chunk_Size_MAX)\n*/\n// for debug only:\n// #define Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n\n#define Get16(p) GetBe16(p)\n#define Get32(p) GetBe32(p)\n#define Get64(p) GetBe64(p)\n\n#define Get32a(p) GetBe32a(p)\n#define Get64a(p) GetBe64a(p)\n\nByte *Base64ToBin(Byte *dest, const char *src);\n\nnamespace NArchive {\nnamespace NDmg {\n\n// allocation limits for compressed blocks for GetStream() interface:\nstatic const unsigned k_NumChunks_MAX = 128;\nstatic const size_t k_Chunk_Size_MAX = (size_t)1 << 28;\n// 256 MB cache for 32-bit:\n//   4 GB cache for 64-bit:\nstatic const size_t k_Chunks_TotalSize_MAX = (size_t)1 << (sizeof(size_t) + 24);\n\n// 2 GB limit for 32-bit:\n// 4 GB limit for 64-bit:\n// that limit can be increased for 64-bit mode, if there are such dmg files\nstatic const size_t k_XmlSize_MAX =\n    ((size_t)1 << (sizeof(size_t) / 4 + 30)) - 256;\n\nstatic const UInt32  METHOD_ZERO_0  = 0; // sparse\nstatic const UInt32  METHOD_COPY    = 1;\nstatic const UInt32  METHOD_ZERO_2  = 2; // sparse : without file CRC calculation\nstatic const UInt32  METHOD_ADC     = 0x80000004;\nstatic const UInt32  METHOD_ZLIB    = 0x80000005;\nstatic const UInt32  METHOD_BZIP2   = 0x80000006;\nstatic const UInt32  METHOD_LZFSE   = 0x80000007;\nstatic const UInt32  METHOD_XZ      = 0x80000008;\nstatic const UInt32  METHOD_COMMENT = 0x7FFFFFFE; // is used to comment \"+beg\" and \"+end\" in extra field.\nstatic const UInt32  METHOD_END     = 0xFFFFFFFF;\n\n\nstruct CBlock\n{\n  UInt32 Type;\n  UInt64 UnpPos;\n  // UInt64 UnpSize;\n  UInt64 PackPos;\n  UInt64 PackSize;\n  \n  bool NeedCrc() const { return Type != METHOD_ZERO_2; }\n  bool IsZeroMethod() const\n  {\n    return (Type & ~(UInt32)METHOD_ZERO_2) == 0;\n    // return Type == METHOD_ZERO_0 || Type == METHOD_ZERO_2;\n  }\n\n  bool IsClusteredMethod() const\n  {\n    // most of dmg files have non-fused COPY_METHOD blocks.\n    // so we don't exclude COPY_METHOD blocks when we try to detect size of cluster.\n    return !IsZeroMethod(); // include COPY_METHOD blocks.\n    // Type > METHOD_ZERO_2; // for debug: exclude COPY_METHOD blocks.\n  }\n\n  bool NeedAllocateBuffer() const\n  {\n    return\n#ifdef Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS\n        !IsZeroMethod();\n#else\n        Type > METHOD_ZERO_2;\n        // !IsZeroMethod() && Type != METHOD_COPY;\n#endif\n  }\n  // we don't store non-data blocks now\n  // bool ThereAreDataInBlock() const { return Type != METHOD_COMMENT && Type != METHOD_END; }\n};\n\nstatic const UInt32 kCheckSumType_CRC = 2;\nstatic const unsigned kChecksumSize_Max = 0x80;\n\nstruct CChecksum\n{\n  UInt32 Type;\n  UInt32 NumBits;\n  Byte Data[kChecksumSize_Max];\n\n  bool IsCrc32() const { return Type == kCheckSumType_CRC && NumBits == 32; }\n  UInt32 GetCrc32() const { return Get32(Data); }\n  void Parse(const Byte *p);\n\n  void PrintType(AString &s) const;\n  void Print(AString &s) const;\n  void Print_with_Name(AString &s) const;\n  void AddToComment(AString &s, const char *name) const;\n};\n\nvoid CChecksum::Parse(const Byte *p)\n{\n  Type = Get32(p);\n  NumBits = Get32(p + 4);\n  memcpy(Data, p + 8, kChecksumSize_Max);\n}\n\n\nvoid CChecksum::PrintType(AString &s) const\n{\n  if (NumBits == 0)\n    return;\n  if (IsCrc32())\n    s += \"CRC\";\n  else\n  {\n    s += \"Checksum\";\n    s.Add_UInt32(Type);\n    s.Add_Minus();\n    s.Add_UInt32(NumBits);\n  }\n}\n\nvoid CChecksum::Print(AString &s) const\n{\n  if (NumBits == 0)\n    return;\n  char temp[kChecksumSize_Max * 2 + 2];\n  /*\n  if (IsCrc32())\n    ConvertUInt32ToHex8Digits(GetCrc32(), temp);\n  else\n  */\n  {\n    UInt32 numBits = kChecksumSize_Max * 8;\n    if (numBits > NumBits)\n        numBits = NumBits;\n    const unsigned numBytes = (numBits + 7) >> 3;\n    if (numBytes <= 8)\n      ConvertDataToHex_Upper(temp, Data, numBytes);\n    else\n      ConvertDataToHex_Lower(temp, Data, numBytes);\n  }\n  s += temp;\n}\n\nvoid CChecksum::Print_with_Name(AString &s) const\n{\n  if (NumBits == 0)\n    return;\n  PrintType(s);\n  s += \": \";\n  Print(s);\n}\n\nstatic void AddToComment_Prop(AString &s, const char *name, const char *val)\n{\n  s += name;\n  s += \": \";\n  s += val;\n  s.Add_LF();\n}\n\nvoid CChecksum::AddToComment(AString &s, const char *name) const\n{\n  AString s2;\n  Print_with_Name(s2);\n  if (!s2.IsEmpty())\n    AddToComment_Prop(s, name, s2);\n}\n\n\nstruct CFile\n{\n  UInt64 Size;\n  CRecordVector<CBlock> Blocks;\n  UInt64 PackSize;\n  UInt64 StartPackPos;\n  UInt64 BlockSize_MAX;\n  UInt64 StartUnpackSector;  // unpack sector position of this file from all files\n  UInt64 NumUnpackSectors;\n  Int32 Descriptor;\n  bool IsCorrect;\n  bool FullFileChecksum;\n  AString Name;\n  // AString Id;\n  CChecksum Checksum;\n\n  UInt64 GetUnpackSize_of_Block(unsigned blockIndex) const\n  {\n    return (blockIndex == Blocks.Size() - 1 ?\n        Size : Blocks[blockIndex + 1].UnpPos) - Blocks[blockIndex].UnpPos;\n  }\n\n  CFile():\n      Size(0),\n      PackSize(0),\n      StartPackPos(0),\n      BlockSize_MAX(0),\n      StartUnpackSector(0),\n      NumUnpackSectors(0),\n      Descriptor(0),\n      IsCorrect(false),\n      FullFileChecksum(false)\n  {\n    Checksum.Type = 0;\n    Checksum.NumBits = 0;\n  }\n  HRESULT Parse(const Byte *p, UInt32 size);\n};\n\n#ifdef DMG_SHOW_RAW\nstruct CExtraFile\n{\n  CByteBuffer Data;\n  AString Name;\n};\n#endif\n\n\nstatic void AddToComment_UInt64(AString &s, UInt64 v, const char *name)\n{\n  s += name;\n  s += \": \";\n  s.Add_UInt64(v);\n  s.Add_LF();\n}\n\nstruct CForkPair\n{\n  UInt64 Offset;\n  UInt64 Len;\n  \n  // (p) is aligned for 8-bytes\n  void Parse(const Byte *p)\n  {\n    Offset = Get64a(p);\n    Len = Get64a(p + 8);\n  }\n\n  bool GetEndPos(UInt64 &endPos)\n  {\n    endPos = Offset + Len;\n    return endPos >= Offset;\n  }\n\n  bool UpdateTop(UInt64 limit, UInt64 &top)\n  {\n    if (Offset > limit || Len > limit - Offset)\n      return false;\n    const UInt64 top2 = Offset + Len;\n    if (top <= top2)\n      top = top2;\n    return true;\n  }\n\n  void Print(AString &s, const char *name) const;\n};\n\nvoid CForkPair::Print(AString &s, const char *name) const\n{\n  if (Offset != 0 || Len != 0)\n  {\n    s += name;  s.Add_Minus();  AddToComment_UInt64(s, Offset, \"offset\");\n    s += name;  s.Add_Minus();  AddToComment_UInt64(s, Len,    \"length\");\n  }\n}\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  bool _masterCrcError;\n  bool _headersError;\n  bool _dataForkError;\n  bool _rsrcMode_wasUsed;\n\n  CMyComPtr<IInStream> _inStream;\n  CObjectVector<CFile> _files;\n\n  // UInt32 _dataStartOffset;\n  UInt64 _startPos;\n  UInt64 _phySize;\n\n  AString _name;\n\n  CForkPair _dataForkPair;\n  CForkPair rsrcPair, xmlPair, blobPair;\n\n  // UInt64 _runningDataForkOffset;\n  // UInt32 _segmentNumber;\n  // UInt32 _segmentCount;\n  UInt64 _numSectors; // total unpacked number of sectors\n  Byte _segmentGUID[16];\n\n  CChecksum _dataForkChecksum;\n  CChecksum _masterChecksum;\n\n#ifdef DMG_SHOW_RAW\n  CObjectVector<CExtraFile> _extras;\n#endif\n\n  HRESULT ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf);\n  bool ParseBlob(const CByteBuffer &data);\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback);\n  HRESULT Extract(IInStream *stream);\n};\n\n\nstruct CMethods\n{\n  CRecordVector<UInt32> Types;\n\n  void Update(const CFile &file);\n  void AddToString(AString &s) const;\n};\n\nvoid CMethods::Update(const CFile &file)\n{\n  FOR_VECTOR (i, file.Blocks)\n  {\n    if (Types.Size() >= (1 << 8))\n      break;\n    Types.AddToUniqueSorted(file.Blocks[i].Type);\n  }\n}\n\nvoid CMethods::AddToString(AString &res) const\n{\n  FOR_VECTOR (i, Types)\n  {\n    const UInt32 type = Types[i];\n    /*\n    if (type == METHOD_COMMENT || type == METHOD_END)\n      continue;\n    */\n    char buf[16];\n    const char *s;\n    switch (type)\n    {\n      // case METHOD_COMMENT: s = \"Comment\"; break;\n      case METHOD_ZERO_0: s = \"Zero0\"; break;\n      case METHOD_ZERO_2: s = \"Zero2\"; break;\n      case METHOD_COPY:   s = \"Copy\";  break;\n      case METHOD_ADC:    s = \"ADC\";   break;\n      case METHOD_ZLIB:   s = \"ZLIB\";  break;\n      case METHOD_BZIP2:  s = \"BZip2\"; break;\n      case METHOD_LZFSE:  s = \"LZFSE\"; break;\n      case METHOD_XZ:     s = \"XZ\";    break;\n      default: ConvertUInt32ToHex(type, buf); s = buf;\n    }\n    res.Add_OptSpaced(s);\n  }\n}\n\n\n\nstruct CAppleName\n{\n  bool IsFs;\n  const char *Ext;\n  const char *AppleName;\n};\n\nstatic const CAppleName k_Names[] =\n{\n  { true,  \"hfs\",  \"Apple_HFS\" },\n  { true,  \"hfsx\", \"Apple_HFSX\" },\n  { true,  \"ufs\",  \"Apple_UFS\" },\n  { true,  \"apfs\", \"Apple_APFS\" },\n  { true,  \"iso\",  \"Apple_ISO\" },\n\n  // efi_sys partition is FAT32, but it's not main file. So we use (IsFs = false)\n  { false,  \"efi_sys\", \"C12A7328-F81F-11D2-BA4B-00A0C93EC93B\" },\n\n  { false, \"free\", \"Apple_Free\" },\n  { false, \"ddm\",  \"DDM\" },\n  { false, NULL,   \"Apple_partition_map\" },\n  { false, NULL,   \" GPT \" },\n    /* \" GPT \" is substring of full name entry in dmg that contains\n         some small metadata GPT entry. It's not real FS entry:\n      \"Primary GPT Header\",\n      \"Primary GPT Table\"\n      \"Backup GPT Header\",\n      \"Backup GPT Table\",\n    */\n  { false, NULL,   \"MBR\" },\n  { false, NULL,   \"Driver\" },\n  { false, NULL,   \"Patches\" }\n};\n  \nstatic const unsigned kNumAppleNames = Z7_ARRAY_SIZE(k_Names);\n\nconst char *Find_Apple_FS_Ext(const AString &name);\nconst char *Find_Apple_FS_Ext(const AString &name)\n{\n  for (unsigned i = 0; i < kNumAppleNames; i++)\n  {\n    const CAppleName &a = k_Names[i];\n    if (a.Ext)\n      if (name.IsEqualTo(a.AppleName))\n        return a.Ext;\n  }\n  return NULL;\n}\n\n\nbool Is_Apple_FS_Or_Unknown(const AString &name);\nbool Is_Apple_FS_Or_Unknown(const AString &name)\n{\n  for (unsigned i = 0; i < kNumAppleNames; i++)\n  {\n    const CAppleName &a = k_Names[i];\n    // if (name.Find(a.AppleName) >= 0)\n    if (strstr(name, a.AppleName))\n      return a.IsFs;\n  }\n  return true;\n}\n\n\n\n// define it for debug only:\n// #define Z7_DMG_SINGLE_FILE_MODE\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidComment,\n  kpidMethod,\n  kpidNumBlocks,\n  kpidClusterSize,\n  kpidChecksum,\n  kpidCRC,\n  kpidId\n  // kpidOffset\n#ifdef Z7_DMG_SINGLE_FILE_MODE\n  , kpidPosition\n#endif\n};\n\nIMP_IInArchive_Props\n\nstatic const Byte kArcProps[] =\n{\n  kpidMethod,\n  kpidNumBlocks,\n  kpidClusterSize,\n  kpidComment\n};\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMethod:\n    {\n      CMethods m;\n      CRecordVector<UInt32> ChecksumTypes;\n      {\n        FOR_VECTOR (i, _files)\n        {\n          const CFile &file = _files[i];\n          m.Update(file);\n          if (ChecksumTypes.Size() < (1 << 8))\n            ChecksumTypes.AddToUniqueSorted(file.Checksum.Type);\n        }\n      }\n      AString s;\n      m.AddToString(s);\n\n      FOR_VECTOR (i, ChecksumTypes)\n      {\n        const UInt32 type = ChecksumTypes[i];\n        switch (type)\n        {\n          case kCheckSumType_CRC:\n            s.Add_OptSpaced(\"CRC\");\n            break;\n          default:\n            s.Add_OptSpaced(\"Checksum\");\n            s.Add_UInt32(type);\n        }\n      }\n\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n    case kpidNumBlocks:\n    {\n      UInt64 numBlocks = 0;\n      FOR_VECTOR (i, _files)\n        numBlocks += _files[i].Blocks.Size();\n      prop = numBlocks;\n      break;\n    }\n    case kpidClusterSize:\n    {\n      UInt64 blockSize_MAX = 0;\n      FOR_VECTOR (i, _files)\n      {\n        const UInt64 a = _files[i].BlockSize_MAX;\n        if (blockSize_MAX < a)\n            blockSize_MAX = a;\n      }\n      prop = blockSize_MAX;\n      break;\n    }\n    case kpidMainSubfile:\n    {\n      int mainIndex = -1;\n      FOR_VECTOR (i, _files)\n      {\n        if (Is_Apple_FS_Or_Unknown(_files[i].Name))\n        {\n          if (mainIndex != -1)\n          {\n            mainIndex = -1;\n            break;\n          }\n          mainIndex = (int)i;\n        }\n      }\n      if (mainIndex != -1)\n        prop = (UInt32)(Int32)mainIndex;\n      break;\n    }\n    case kpidWarning:\n      if (_masterCrcError)\n        prop = \"Master CRC error\";\n      break;\n\n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      if (_headersError)  v |= kpv_ErrorFlags_HeadersError;\n      if (_dataForkError) v |= kpv_ErrorFlags_CrcError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n\n    case kpidOffset: prop = _startPos; break;\n    case kpidPhySize: prop = _phySize; break;\n\n    case kpidComment:\n    {\n      AString s;\n      if (!_name.IsEmpty())\n        AddToComment_Prop(s, \"Name\", _name);\n      AddToComment_UInt64(s, _numSectors << 9, \"unpack-size\");\n      {\n        char temp[sizeof(_segmentGUID) * 2 + 2];\n        ConvertDataToHex_Lower(temp, _segmentGUID, sizeof(_segmentGUID));\n        AddToComment_Prop(s, \"ID\", temp);\n      }\n      _masterChecksum.AddToComment(s, \"master-checksum\");\n      _dataForkChecksum.AddToComment(s, \"pack-checksum\");\n      {\n        /*\n        if (_dataStartOffset != 0)\n          AddToComment_UInt64(s, _dataStartOffset,    \"payload-start-offset\");\n        */\n        // if (_dataForkPair.Offset != 0)\n        _dataForkPair.Print(s, \"pack\");\n        rsrcPair.Print(s, \"rsrc\");\n        xmlPair.Print(s, \"xml\");\n        blobPair.Print(s, \"blob\");\n      }\n      if (_rsrcMode_wasUsed)\n        s += \"RSRC_MODE\\n\";\n      if (!s.IsEmpty())\n        prop = s;\n    }\n    break;\n\n    case kpidName:\n      if (!_name.IsEmpty())\n        prop = _name + \".dmg\";\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nIMP_IInArchive_ArcProps\n\n\n\nstatic const UInt64 kSectorNumber_LIMIT = (UInt64)1 << (63 - 9);\n\nHRESULT CFile::Parse(const Byte *p, UInt32 size)\n{\n  // CFile was initialized to default values: 0 in size variables and (IsCorrect == false)\n  const unsigned kHeadSize = 0xCC;\n  if (size < kHeadSize)\n    return S_FALSE;\n  if (Get32(p) != 0x6D697368) // \"mish\" signature\n    return S_FALSE;\n  if (Get32(p + 4) != 1) // version\n    return S_FALSE;\n  \n  StartUnpackSector = Get64(p + 8);\n  NumUnpackSectors = Get64(p + 0x10);\n  StartPackPos = Get64(p + 0x18);\n\n#ifdef SHOW_DEBUG_INFO\n  /* the number of sectors that must be allocated.\n     ==  0x208 for 256KB clusters\n     ==  0x808 for   1MB clusters\n     == 0x1001 for   1MB clusters in some example\n  */\n  const UInt32 decompressedBufRequested = Get32(p + 0x20);\n#endif\n  \n  // Descriptor is file index. usually started from -1\n  // in one dmg it was started from 0\n  Descriptor = (Int32)Get32(p + 0x24);\n  // char Reserved1[24];\n  \n  Checksum.Parse(p + 0x40);\n  PRF(printf(\"\\n\" \" Checksum Type = %2u\"\n        \"\\n StartUnpackSector = %8x\"\n        \"\\n NumUnpackSectors  = %8x\"\n        \"\\n StartPos = %8x\"\n        \"\\n decompressedBufRequested=%8x\"\n        \"\\n blocksDescriptor=%8x\"\n        , (unsigned)Checksum.Type\n        , (unsigned)StartUnpackSector\n        , (unsigned)NumUnpackSectors\n        , (unsigned)StartPackPos\n        , (unsigned)decompressedBufRequested\n        , (unsigned)Descriptor\n    );)\n\n  const UInt32 numBlocks = Get32(p + 0xC8);\n  const unsigned kRecordSize = 40;\n  if ((UInt64)numBlocks * kRecordSize + kHeadSize != size)\n    return S_FALSE;\n\n  Blocks.ClearAndReserve(numBlocks);\n  FullFileChecksum = true;\n  /* IsCorrect = false; by default\n     So we return S_OK, if we can ignore some error in headers.\n  */\n\n  p += kHeadSize;\n  UInt32 i;\n \n  for (i = 0; i < numBlocks; i++, p += kRecordSize)\n  {\n    CBlock b;\n    b.Type = Get32(p);\n    {\n      const UInt64 a = Get64(p + 0x08);\n      if (a >= kSectorNumber_LIMIT)\n        return S_OK;\n      b.UnpPos = a << 9;\n    }\n    UInt64 unpSize;\n    {\n      const UInt64 a = Get64(p + 0x10);\n      if (a >= kSectorNumber_LIMIT)\n        return S_OK;\n      unpSize = a << 9;\n    }\n    const UInt64 newSize = b.UnpPos + unpSize;\n    if (newSize >= ((UInt64)1 << 63))\n      return S_OK;\n\n    b.PackPos  = Get64(p + 0x18);\n    b.PackSize = Get64(p + 0x20);\n    // b.PackPos can be 0 for some types. So we don't check it\n    if (b.UnpPos != Size)\n      return S_OK;\n    \n    PRF(printf(\"\\nType=%8x  comment=%8x  uPos=%8x  uSize=%7x  pPos=%8x  pSize=%7x\",\n        (unsigned)b.Type, Get32(p + 4), (unsigned)b.UnpPos, (unsigned)unpSize, (unsigned)b.PackPos, (unsigned)b.PackSize));\n    \n    if (b.Type == METHOD_COMMENT)\n    {\n      // some files contain 2 comment block records:\n      // record[0]     : Type=METHOD_COMMENT, comment_field = \"+beg\"\n      // record[num-2] : Type=METHOD_COMMENT, comment_field = \"+end\"\n      // we skip these useless records.\n      continue;\n    }\n    if (b.Type == METHOD_END)\n      break;\n \n    // we add only blocks that have non empty unpacked data:\n    if (unpSize != 0)\n    {\n      const UInt64 k_max_pos = (UInt64)1 << 63;\n      if (b.PackPos >= k_max_pos ||\n          b.PackSize >= k_max_pos - b.PackPos)\n        return S_OK;\n\n      /* we don't count non-ZERO blocks here, because\n         ZERO blocks in dmg files are not limited by some cluster size.\n         note: COPY blocks also sometimes are fused to larger blocks.\n      */\n      if (b.IsClusteredMethod())\n      if (BlockSize_MAX < unpSize)\n          BlockSize_MAX = unpSize;\n\n      PackSize += b.PackSize;\n      if (!b.NeedCrc())\n        FullFileChecksum = false;\n      Blocks.AddInReserved(b);\n      Size = newSize;\n    }\n  }\n\n  PRF(printf(\"\\n\");)\n\n  if (i != numBlocks - 1)\n  {\n    // return S_FALSE;\n    return S_OK;\n  }\n    \n  if ((Size >> 9) == NumUnpackSectors)\n    IsCorrect = true;\n  return S_OK;\n}\n\n\nstatic const CXmlItem *FindKeyPair(const CXmlItem &item, const char *key, const char *nextTag)\n{\n  for (unsigned i = 0; i + 1 < item.SubItems.Size(); i++)\n  {\n    const CXmlItem &si = item.SubItems[i];\n    if (si.IsTagged(\"key\") && si.GetSubString().IsEqualTo(key))\n    {\n      const CXmlItem *si_1 = &item.SubItems[i + 1];\n      if (si_1->IsTagged(nextTag))\n        return si_1;\n    }\n  }\n  return NULL;\n}\n\nstatic const AString *GetStringFromKeyPair(const CXmlItem &item, const char *key, const char *nextTag)\n{\n  const CXmlItem *si_1 = FindKeyPair(item, key, nextTag);\n  if (si_1)\n    return si_1->GetSubStringPtr();\n  return NULL;\n}\n\nstatic const Byte k_Signature[] = { 'k','o','l','y', 0, 0, 0, 4, 0, 0, 2, 0 };\n\nstatic inline bool IsKoly(const Byte *p)\n{\n  return memcmp(p, k_Signature, Z7_ARRAY_SIZE(k_Signature)) == 0;\n  /*\n  if (Get32(p) != 0x6B6F6C79) // \"koly\" signature\n    return false;\n  if (Get32(p + 4) != 4) // version\n    return false;\n  if (Get32(p + 8) != HEADER_SIZE)\n    return false;\n  return true;\n  */\n}\n\n\nHRESULT CHandler::ReadData(IInStream *stream, const CForkPair &pair, CByteBuffer &buf)\n{\n  size_t size = (size_t)pair.Len;\n  if (size != pair.Len)\n    return E_OUTOFMEMORY;\n  buf.Alloc(size);\n  RINOK(InStream_SeekSet(stream, _startPos + pair.Offset))\n  return ReadStream_FALSE(stream, buf, size);\n}\n\n\n\nbool CHandler::ParseBlob(const CByteBuffer &data)\n{\n  const unsigned kHeaderSize = 3 * 4;\n  if (data.Size() < kHeaderSize)\n    return false;\n  const Byte * const p = (const Byte *)data;\n  if (Get32a(p) != 0xfade0cc0) // CSMAGIC_EMBEDDED_SIGNATURE\n    return true;\n  const UInt32 size = Get32a(p + 4);\n  if (size != data.Size())\n    return false;\n  const UInt32 num = Get32a(p + 8);\n  if (num > (size - kHeaderSize) / 8)\n    return false;\n  \n  const UInt32 limit = num * 8 + kHeaderSize;\n  for (size_t i = kHeaderSize; i < limit; i += 8)\n  {\n    // type == 0 == CSSLOT_CODEDIRECTORY for CSMAGIC_CODEDIRECTORY item\n    // UInt32 type = Get32(p + i);\n    const UInt32 offset = Get32a(p + i + 4);\n    if (offset < limit || offset > size - 8)\n      return false;\n    // offset is not aligned for 4 here !!!\n    const Byte * const p2 = p + offset;\n    const UInt32 magic = Get32(p2);\n    const UInt32 len = Get32(p2 + 4);\n    if (size - offset < len || len < 8)\n      return false;\n\n#ifdef DMG_SHOW_RAW\n    CExtraFile &extra = _extras.AddNew();\n    extra.Name = \"_blob_\";\n    extra.Data.CopyFrom(p2, len);\n#endif\n\n    if (magic == 0xfade0c02) // CSMAGIC_CODEDIRECTORY\n    {\n#ifdef DMG_SHOW_RAW\n      extra.Name += \"codedir\";\n#endif\n    \n      if (len < 11 * 4)\n        return false;\n      const UInt32 idOffset = Get32(p2 + 5 * 4);\n      if (idOffset >= len)\n        return false;\n      UInt32 len2 = len - idOffset;\n      const UInt32 kNameLenMax = 1 << 8;\n      if (len2 > kNameLenMax)\n          len2 = kNameLenMax;\n      _name.SetFrom_CalcLen((const char *)(p2 + idOffset), len2);\n      /*\n      // #define kSecCodeSignatureHashSHA1     1\n      // #define kSecCodeSignatureHashSHA256   2\n      const UInt32 hashOffset    = Get32(p2 + 4 * 4);\n      const UInt32 nSpecialSlots = Get32(p2 + 6 * 4);\n      const UInt32 nCodeSlots    = Get32(p2 + 7 * 4);\n      const unsigned hashSize = p2[36];\n      const unsigned hashType = p2[37];\n      // const unsigned unused = p2[38];\n      const unsigned pageSize = p2[39];\n      */\n    }\n#ifdef DMG_SHOW_RAW\n    else if (magic == 0xfade0c01) extra.Name += \"requirements\";\n    else if (magic == 0xfade0b01) extra.Name += \"signed\";\n    else\n    {\n      char temp[16];\n      ConvertUInt32ToHex8Digits(magic, temp);\n      extra.Name += temp;\n    }\n#endif\n  }\n\n  return true;\n}\n\n\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback)\n{\n  /*\n  - usual dmg contains Koly Header at the end:\n  - rare case old dmg contains Koly Header at the begin.\n  */\n\n  // _dataStartOffset = 0;\n  UInt64 fileSize;\n  RINOK(InStream_GetPos_GetSize(stream, _startPos, fileSize))\n\n  const unsigned HEADER_SIZE = 0x200;\n  UInt64 buf[HEADER_SIZE / sizeof(UInt64)];\n  RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE))\n\n  UInt64 headerPos;\n  bool front_Koly_Mode = false;\n\n  /*\n  _dataForkChecksum.Offset ==   0 for koly-at-the-end\n  _dataForkChecksum.Offset == 512 for koly-at-the-start\n  so we can use (_dataForkChecksum.Offset) to detect \"koly-at-the-start\" mode\n  */\n\n  if (IsKoly((const Byte *)(const void *)buf))\n  {\n    // it can be normal koly-at-the-end or koly-at-the-start\n    headerPos = _startPos;\n    /*\n    if (_startPos <= (1 << 8))\n    {\n      // we want to support front_Koly_Mode, even if there is\n      // some data before dmg file, like 128 bytes MacBin header\n      _dataStartOffset = HEADER_SIZE;\n      front_Koly_Mode = true;\n    }\n    */\n  }\n  else\n  {\n    /* we try to open in backward mode only for first attempt\n       when (_startPos == 0) */\n    if (_startPos != 0)\n      return S_FALSE;\n    headerPos = fileSize;\n    if (headerPos < HEADER_SIZE)\n      return S_FALSE;\n    headerPos -= HEADER_SIZE;\n    RINOK(InStream_SeekSet(stream, headerPos))\n    RINOK(ReadStream_FALSE(stream, buf, HEADER_SIZE))\n    if (!IsKoly((const Byte *)(const void *)buf))\n      return S_FALSE;\n  }\n\n  // UInt32 flags = Get32a((const Byte *)(const void *)buf + 12);\n  // _runningDataForkOffset = Get64a((const Byte *)(const void *)buf + 0x10);\n  _dataForkPair.Parse((const Byte *)(const void *)buf + 0x18);\n  rsrcPair.Parse((const Byte *)(const void *)buf + 0x28);\n  // _segmentNumber = Get32a(buf + 0x38); // 0 or 1\n  // _segmentCount = Get32a(buf + 0x3C);  // 0 (if not set) or 1\n  memcpy(_segmentGUID, (const Byte *)(const void *)buf + 0x40, 16);\n  _dataForkChecksum.Parse((const Byte *)(const void *)buf + 0x50);\n  xmlPair.Parse((const Byte *)(const void *)buf + 0xD8);\n  // Byte resereved[]\n  blobPair.Parse((const Byte *)(const void *)buf + 0x128);\n  _masterChecksum.Parse((const Byte *)(const void *)buf + 0x160);\n  // UInt32 imageVariant = Get32a((const Byte *)(const void *)buf + 0x1E8); imageVariant = imageVariant;\n  _numSectors = Get64((const Byte *)(const void *)buf + 0x1EC);  // it's not aligned for 8-bytes\n  // Byte resereved[12];\n\n  if (_dataForkPair.Offset == HEADER_SIZE\n      && headerPos + HEADER_SIZE < fileSize)\n    front_Koly_Mode = true;\n\n  const UInt64 limit = front_Koly_Mode ? fileSize : headerPos;\n  UInt64 top = 0;\n  if (!_dataForkPair.UpdateTop(limit, top)) return S_FALSE;\n  if (!xmlPair.UpdateTop(limit, top)) return S_FALSE;\n  if (!rsrcPair.UpdateTop(limit, top)) return S_FALSE;\n\n  /* Some old dmg files contain garbage data in blobPair field.\n     So we need to ignore such garbage case;\n     And we still need to detect offset of start of archive for \"parser\" mode. */\n  const bool useBlob = blobPair.UpdateTop(limit, top);\n\n  if (front_Koly_Mode)\n    _phySize = top;\n  else\n  {\n    _phySize = headerPos + HEADER_SIZE;\n    _startPos = 0;\n    if (top != headerPos)\n    {\n      /*\n      if expected absolute offset is not equal to real header offset,\n      2 cases are possible:\n        - additional (unknown) headers\n        - archive with offset.\n       So we try to read XML with absolute offset to select from these two ways.\n      */\n      CForkPair xmlPair2 = xmlPair;\n      const char *sz = \"<?xml version\";\n      const unsigned len = (unsigned)strlen(sz);\n      if (xmlPair2.Len > len)\n        xmlPair2.Len = len;\n      CByteBuffer buf2;\n      if (xmlPair2.Len < len\n        || ReadData(stream, xmlPair2, buf2) != S_OK\n        || memcmp(buf2, sz, len) != 0)\n      {\n        // if absolute offset is not OK, probably it's archive with offset\n        _startPos = headerPos - top;\n        _phySize = top + HEADER_SIZE;\n      }\n    }\n  }\n\n  if (useBlob\n      && blobPair.Len != 0\n      && blobPair.Len <= (1u << 24)) // we don't want parsing of big blobs\n  {\n#ifdef DMG_SHOW_RAW\n    CExtraFile &extra = _extras.AddNew();\n    extra.Name = \"_blob.bin\";\n    CByteBuffer &blobBuf = extra.Data;\n#else\n    CByteBuffer blobBuf;\n#endif\n    RINOK(ReadData(stream, blobPair, blobBuf))\n    if (!ParseBlob(blobBuf))\n      _headersError = true;\n  }\n\n\n  UInt64 openTotal = 0;\n  UInt64 openCur = 0;\n  if (_dataForkChecksum.IsCrc32())\n    openTotal = _dataForkPair.Len;\n\n  const UInt32 RSRC_HEAD_SIZE = 0x100;\n\n  /* we have 2 ways to read files and blocks metadata:\n     via Xml or via Rsrc.\n     But some images have no Rsrc fork.\n     Is it possible that there is no Xml?\n     Rsrc method will not work for big files. */\n  // v23.02: we use xml mode by default\n  // if (rsrcPair.Len >= RSRC_HEAD_SIZE && rsrcPair.Len <= ((UInt32)1 << 24)) // for debug\n  if (xmlPair.Len == 0)\n  {\n    // We don't know the size of the field \"offset\" in Rsrc.\n    // We suppose that it uses 24 bits. So we use Rsrc, only if the rsrcPair.Len <= (1 << 24).\n    const bool canUseRsrc = (rsrcPair.Len >= RSRC_HEAD_SIZE && rsrcPair.Len <= ((UInt32)1 << 24));\n    if (!canUseRsrc)\n      return S_FALSE;\n\n    _rsrcMode_wasUsed = true;\n#ifdef DMG_SHOW_RAW\n    CExtraFile &extra = _extras.AddNew();\n    extra.Name = \"rsrc.bin\";\n    CByteBuffer &rsrcBuf = extra.Data;\n#else\n    CByteBuffer rsrcBuf;\n#endif\n\n    RINOK(ReadData(stream, rsrcPair, rsrcBuf))\n\n    const Byte *p = rsrcBuf;\n    const UInt32 headSize     = Get32a(p + 0);\n    const UInt32 footerOffset = Get32a(p + 4);\n    const UInt32 mainDataSize = Get32a(p + 8);\n    const UInt32 footerSize   = Get32a(p + 12);\n    if (headSize != RSRC_HEAD_SIZE\n        || footerOffset >= rsrcPair.Len\n        || mainDataSize >= rsrcPair.Len\n        || footerOffset < mainDataSize\n        || footerOffset != headSize + mainDataSize)\n      return S_FALSE;\n\n    {\n      const UInt32 footerEnd = footerOffset + footerSize;\n      if (footerEnd != rsrcPair.Len)\n      {\n        // there is rare case dmg example, where there are 4 additional bytes\n        const UInt64 rem = rsrcPair.Len - footerOffset;\n        if (rem < footerSize\n          || rem - footerSize != 4\n          || Get32(p + footerEnd) != 0)\n          return S_FALSE;\n      }\n    }\n  \n    if (footerSize < 0x1e)\n      return S_FALSE;\n    if (memcmp(p, p + footerOffset, 16) != 0)\n      return S_FALSE;\n\n    p += footerOffset;\n\n    if ((UInt32)Get16(p + 0x18) != 0x1c)\n      return S_FALSE;\n    const UInt32 namesOffset = Get16(p + 0x1a);\n    if (namesOffset > footerSize)\n      return S_FALSE;\n    \n    const UInt32 numItems = (UInt32)Get16(p + 0x1c) + 1;\n    if (numItems * 8 + 0x1e > namesOffset)\n      return S_FALSE;\n    \n    for (UInt32 i = 0; i < numItems; i++)\n    {\n      const Byte *p2 = p + 0x1e + (size_t)i * 8;\n      const UInt32 typeId = Get32(p2);\n      const UInt32 k_typeId_blkx = 0x626c6b78; // blkx\n#ifndef DMG_SHOW_RAW\n      if (typeId != k_typeId_blkx)\n        continue;\n#endif\n      const UInt32 numFiles = (UInt32)Get16(p2 + 4) + 1;\n      const UInt32 offs = Get16(p2 + 6);\n      if (0x1c + offs + 12 * numFiles > namesOffset)\n        return S_FALSE;\n\n      for (UInt32 k = 0; k < numFiles; k++)\n      {\n        const Byte *p3 = p + 0x1c + offs + k * 12;\n        // UInt32 id = Get16(p3);\n        const UInt32 namePos = Get16(p3 + 2);\n        // Byte attributes = p3[4]; // = 0x50 for blkx #define (ATTRIBUTE_HDIUTIL)\n        // we don't know how many bits we can use. So we use 24 bits only\n        UInt32 blockOffset = Get32(p3 + 4);\n        blockOffset &= ((UInt32)1 << 24) - 1;\n        // UInt32 unknown2 = Get32(p3 + 8); // ???\n        if (blockOffset + 4 >= mainDataSize)\n          return S_FALSE;\n        const Byte *pBlock = rsrcBuf + headSize + blockOffset;\n        const UInt32 blockSize = Get32(pBlock);\n        if (mainDataSize - (blockOffset + 4) < blockSize)\n          return S_FALSE;\n        \n        AString name;\n        \n        if (namePos != 0xffff)\n        {\n          const UInt32 namesBlockSize = footerSize - namesOffset;\n          if (namePos >= namesBlockSize)\n            return S_FALSE;\n          const Byte *namePtr = p + namesOffset + namePos;\n          const UInt32 nameLen = *namePtr;\n          if (namesBlockSize - namePos <= nameLen)\n            return S_FALSE;\n          for (UInt32 r = 1; r <= nameLen; r++)\n          {\n            const Byte c = namePtr[r];\n            if (c < 0x20 || c >= 0x80)\n              break;\n            name += (char)c;\n          }\n        }\n        \n        if (typeId == k_typeId_blkx)\n        {\n          CFile &file = _files.AddNew();\n          file.Name = name;\n          RINOK(file.Parse(pBlock + 4, blockSize))\n          if (!file.IsCorrect)\n            _headersError = true;\n        }\n        \n#ifdef DMG_SHOW_RAW\n        {\n          AString name2;\n          name2.Add_UInt32(i);\n          name2 += '_';\n          {\n            char temp[4 + 1] = { 0 };\n            memcpy(temp, p2, 4);\n            name2 += temp;\n          }\n          name2.Trim();\n          name2 += '_';\n          name2.Add_UInt32(k);\n          if (!name.IsEmpty())\n          {\n            name2 += '_';\n            name2 += name;\n          }\n          CExtraFile &extra2 = _extras.AddNew();\n          extra2.Name = name2;\n          extra2.Data.CopyFrom(pBlock + 4, blockSize);\n        }\n#endif\n      }\n    }\n  }\n  else\n  {\n    if (xmlPair.Len > k_XmlSize_MAX)\n      return S_FALSE;\n    // if (!canUseXml) return S_FALSE;\n    const size_t size = (size_t)xmlPair.Len;\n    // if (size + 1 <= xmlPair.Len) return S_FALSE; // optional check\n    RINOK(InStream_SeekSet(stream, _startPos + xmlPair.Offset))\n    CXml xml;\n    {\n      openTotal += size;\n      if (openArchiveCallback)\n      {\n        RINOK(openArchiveCallback->SetTotal(NULL, &openTotal))\n      }\n      size_t pos = 0;\n      CAlignedBuffer1 xmlStr(size + 1);\n      for (;;)\n      {\n        const size_t k_OpenStep = 1 << 24;\n        const size_t cur = MyMin(k_OpenStep, size - pos);\n        RINOK(ReadStream_FALSE(stream, xmlStr + pos, cur))\n        pos += cur;\n        openCur += cur;\n        if (pos == size)\n          break;\n        if (openArchiveCallback)\n        {\n          RINOK(openArchiveCallback->SetCompleted(NULL, &openCur))\n        }\n      }\n      xmlStr[size] = 0;\n      // if (strlen((const char *)(const void *)(const Byte *)xmlStr) != size) return S_FALSE;\n      if (!xml.Parse((char *)(void *)(Byte *)xmlStr))\n        return S_FALSE;\n\n#ifdef DMG_SHOW_RAW\n      CExtraFile &extra = _extras.AddNew();\n      extra.Name = \"a.xml\";\n      extra.Data.CopyFrom(xmlStr, size);\n#endif\n    }\n    \n    if (!xml.Root.Name.IsEqualTo(\"plist\"))\n      return S_FALSE;\n    \n    const CXmlItem *dictItem = xml.Root.FindSubTag_GetPtr(\"dict\");\n    if (!dictItem)\n      return S_FALSE;\n    \n    const CXmlItem *rfDictItem = FindKeyPair(*dictItem, \"resource-fork\", \"dict\");\n    if (!rfDictItem)\n      return S_FALSE;\n    \n    const CXmlItem *arrItem = FindKeyPair(*rfDictItem, \"blkx\", \"array\");\n    if (!arrItem)\n      return S_FALSE;\n    \n    FOR_VECTOR (i, arrItem->SubItems)\n    {\n      const CXmlItem &item = arrItem->SubItems[i];\n      if (!item.IsTagged(\"dict\"))\n        continue;\n      \n      CByteBuffer rawBuf;\n      unsigned destLen = 0;\n      {\n        const AString *dataString = GetStringFromKeyPair(item, \"Data\", \"data\");\n        if (!dataString)\n          return S_FALSE;\n        destLen = dataString->Len() / 4 * 3 + 4;\n        rawBuf.Alloc(destLen);\n        {\n          const Byte *endPtr = Base64ToBin(rawBuf, *dataString);\n          if (!endPtr)\n            return S_FALSE;\n          destLen = (unsigned)(endPtr - (const Byte *)rawBuf);\n        }\n        \n#ifdef DMG_SHOW_RAW\n        CExtraFile &extra = _extras.AddNew();\n        extra.Name.Add_UInt32(_files.Size());\n        extra.Data.CopyFrom(rawBuf, destLen);\n#endif\n      }\n      CFile &file = _files.AddNew();\n      {\n        /* xml code removes front space for such string:\n             <string> (Apple_Free : 3)</string>\n           maybe we shoud fix xml code and return full string with space.\n        */\n        const AString *name = GetStringFromKeyPair(item, \"Name\", \"string\");\n        if (!name || name->IsEmpty())\n          name = GetStringFromKeyPair(item, \"CFName\", \"string\");\n        if (name)\n          file.Name = *name;\n      }\n      /*\n      {\n        const AString *s = GetStringFromKeyPair(item, \"ID\", \"string\");\n        if (s)\n          file.Id = *s;\n      }\n      */\n      RINOK(file.Parse(rawBuf, destLen))\n      if (!file.IsCorrect)\n        _headersError = true;\n    }\n  }\n\n  if (_masterChecksum.IsCrc32())\n  {\n    UInt32 crc = CRC_INIT_VAL;\n    unsigned i;\n    for (i = 0; i < _files.Size(); i++)\n    {\n      const CChecksum &cs = _files[i].Checksum;\n      if ((cs.NumBits & 0x7) != 0)\n        break;\n      const UInt32 len = cs.NumBits >> 3;\n      if (len > kChecksumSize_Max)\n        break;\n      crc = CrcUpdate(crc, cs.Data, (size_t)len);\n    }\n    if (i == _files.Size())\n      _masterCrcError = (CRC_GET_DIGEST(crc) != _masterChecksum.GetCrc32());\n  }\n\n  {\n    UInt64 sec = 0;\n    FOR_VECTOR (i, _files)\n    {\n      const CFile &file = _files[i];\n      /*\n      if (file.Descriptor != (Int32)i - 1)\n        _headersError = true;\n      */\n      if (file.StartUnpackSector != sec)\n        _headersError = true;\n      if (file.NumUnpackSectors >= kSectorNumber_LIMIT)\n        _headersError = true;\n      sec += file.NumUnpackSectors;\n      if (sec >= kSectorNumber_LIMIT)\n        _headersError = true;\n    }\n    if (sec != _numSectors)\n      _headersError = true;\n  }\n\n  // data checksum calculation can be slow for big dmg file\n  if (_dataForkChecksum.IsCrc32())\n  {\n    UInt64 endPos;\n    if (!_dataForkPair.GetEndPos(endPos)\n        || _dataForkPair.Offset >= ((UInt64)1 << 63))\n      _headersError = true;\n    else\n    {\n      const UInt64 seekPos = _startPos + _dataForkPair.Offset;\n      if (seekPos > fileSize\n        || endPos > fileSize - _startPos)\n      {\n        _headersError = true;\n        // kpv_ErrorFlags_UnexpectedEnd\n      }\n      else\n      {\n        const size_t kBufSize = 1 << 15;\n        CAlignedBuffer1 buf2(kBufSize);\n        RINOK(InStream_SeekSet(stream, seekPos))\n        if (openArchiveCallback)\n        {\n          RINOK(openArchiveCallback->SetTotal(NULL, &openTotal))\n        }\n        UInt32 crc = CRC_INIT_VAL;\n        UInt64 pos = 0;\n        for (;;)\n        {\n          const UInt64 rem = _dataForkPair.Len - pos;\n          size_t cur = kBufSize;\n          if (cur > rem)\n            cur = (UInt32)rem;\n          if (cur == 0)\n            break;\n          RINOK(ReadStream_FALSE(stream, buf2, cur))\n          crc = CrcUpdate(crc, buf2, cur);\n          pos += cur;\n          openCur += cur;\n          if ((pos & ((1 << 24) - 1)) == 0 && openArchiveCallback)\n          {\n            RINOK(openArchiveCallback->SetCompleted(NULL, &openCur))\n          }\n        }\n        if (_dataForkChecksum.GetCrc32() != CRC_GET_DIGEST(crc))\n          _dataForkError = true;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback *openArchiveCallback))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(stream, openArchiveCallback))\n  _inStream = stream;\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _masterCrcError = false;\n  _headersError = false;\n  _dataForkError = false;\n  _rsrcMode_wasUsed = false;\n  _phySize = 0;\n  _startPos = 0;\n  _name.Empty();\n  _inStream.Release();\n  _files.Clear();\n#ifdef DMG_SHOW_RAW\n  _extras.Clear();\n#endif\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _files.Size()\n#ifdef DMG_SHOW_RAW\n    + _extras.Size()\n#endif\n    ;\n  return S_OK;\n}\n\n#ifdef DMG_SHOW_RAW\n#define RAW_PREFIX \"raw\" STRING_PATH_SEPARATOR\n#endif\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  \n#ifdef DMG_SHOW_RAW\n  if (index >= _files.Size())\n  {\n    const CExtraFile &extra = _extras[index - _files.Size()];\n    switch (propID)\n    {\n      case kpidPath:\n        prop = (AString)RAW_PREFIX + extra.Name;\n        break;\n      case kpidSize:\n      case kpidPackSize:\n        prop = (UInt64)extra.Data.Size();\n        break;\n    }\n  }\n  else\n#endif\n  {\n    const CFile &item = _files[index];\n    switch (propID)\n    {\n      case kpidSize:  prop = item.Size; break;\n      case kpidPackSize:  prop = item.PackSize; break;\n      case kpidCRC:\n      {\n        if (item.Checksum.IsCrc32() && item.FullFileChecksum)\n          prop = item.Checksum.GetCrc32();\n        break;\n      }\n      case kpidChecksum:\n      {\n        AString s;\n        item.Checksum.Print(s);\n        if (!s.IsEmpty())\n          prop = s;\n        break;\n      }\n\n      /*\n      case kpidOffset:\n      {\n        prop = item.StartPackPos;\n        break;\n      }\n      */\n\n      case kpidNumBlocks:\n          prop = (UInt32)item.Blocks.Size();\n          break;\n      case kpidClusterSize:\n          prop = item.BlockSize_MAX;\n          break;\n\n      case kpidMethod:\n      {\n        AString s;\n        if (!item.IsCorrect)\n          s.Add_OptSpaced(\"CORRUPTED\");\n        CMethods m;\n        m.Update(item);\n        m.AddToString(s);\n        {\n          AString s2;\n          item.Checksum.PrintType(s2);\n          if (!s2.IsEmpty())\n            s.Add_OptSpaced(s2);\n        }\n        if (!s.IsEmpty())\n          prop = s;\n        break;\n      }\n      \n      case kpidPath:\n      {\n#ifdef Z7_DMG_SINGLE_FILE_MODE\n        prop = \"a.img\";\n#else\n        UString name;\n        name.Add_UInt32(index);\n        unsigned num = 10;\n        unsigned numDigits;\n        for (numDigits = 1; num < _files.Size(); numDigits++)\n          num *= 10;\n        while (name.Len() < numDigits)\n          name.InsertAtFront(L'0');\n\n        AString subName;\n        int pos1 = item.Name.Find('(');\n        if (pos1 >= 0)\n        {\n          pos1++;\n          const int pos2 = item.Name.Find(')', pos1);\n          if (pos2 >= 0)\n          {\n            subName.SetFrom(item.Name.Ptr(pos1), pos2 - pos1);\n            pos1 = subName.Find(':');\n            if (pos1 >= 0)\n              subName.DeleteFrom(pos1);\n          }\n        }\n        else\n          subName = item.Name; // new apfs dmg can be without braces\n        subName.Trim();\n        if (!subName.IsEmpty())\n        {\n          const char *ext = Find_Apple_FS_Ext(subName);\n          if (ext)\n            subName = ext;\n          UString name2;\n          ConvertUTF8ToUnicode(subName, name2);\n          name.Add_Dot();\n          name += name2;\n        }\n        else\n        {\n          UString name2;\n          ConvertUTF8ToUnicode(item.Name, name2);\n          if (!name2.IsEmpty())\n            name += \"_\";\n          name += name2;\n        }\n        prop = name;\n#endif\n\n        break;\n      }\n      \n      case kpidComment:\n      {\n        UString name;\n        ConvertUTF8ToUnicode(item.Name, name);\n        prop = name;\n        break;\n      }\n      case kpidId:\n      {\n        prop.Set_Int32((Int32)item.Descriptor);\n        /*\n        if (!item.Id.IsEmpty())\n        {\n          UString s;\n          ConvertUTF8ToUnicode(item.Id, s);\n          prop = s;\n        }\n        */\n        break;\n      }\n#ifdef Z7_DMG_SINGLE_FILE_MODE\n      case kpidPosition:\n        prop = item.StartUnpackSector << 9;\n        break;\n#endif\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nclass CAdcDecoder\n{\n  CLzOutWindow m_OutWindowStream;\n  CInBuffer m_InStream;\n\n  class CCoderReleaser Z7_final\n  {\n    CAdcDecoder *m_Coder;\n  public:\n    bool NeedFlush;\n    CCoderReleaser(CAdcDecoder *coder): m_Coder(coder), NeedFlush(true) {}\n    ~CCoderReleaser()\n    {\n      if (NeedFlush)\n        m_Coder->m_OutWindowStream.Flush();\n    }\n  };\n  friend class CCoderReleaser;\n\npublic:\n  HRESULT Code(ISequentialInStream * const inStream,\n    ISequentialOutStream *outStream,\n    const UInt64 * const inSize,\n    const UInt64 * const outSize,\n    ICompressProgressInfo * const progress);\n};\n\n\nHRESULT CAdcDecoder::Code(ISequentialInStream * const inStream,\n    ISequentialOutStream *outStream,\n    const UInt64 * const inSize,\n    const UInt64 * const outSizePtr,\n    ICompressProgressInfo * const progress)\n{\n  try {\n\n  if (!m_OutWindowStream.Create(1 << 18)) // at least (1 << 16) is required here\n    return E_OUTOFMEMORY;\n  if (!m_InStream.Create(1 << 18))\n    return E_OUTOFMEMORY;\n\n  m_OutWindowStream.SetStream(outStream);\n  m_OutWindowStream.Init(false);\n  m_InStream.SetStream(inStream);\n  m_InStream.Init();\n  \n  CCoderReleaser coderReleaser(this);\n\n  const UInt32 kStep = 1 << 22;\n  UInt64 nextLimit = kStep;\n  const UInt64 outSize = *outSizePtr;\n  UInt64 pos = 0;\n  /* match sequences and literal sequences do not cross 64KB range\n     in some dmg archive examples. But is it so for any Adc stream? */\n\n  while (pos < outSize)\n  {\n    if (pos >= nextLimit && progress)\n    {\n      nextLimit += kStep;\n      const UInt64 packSize = m_InStream.GetProcessedSize();\n      RINOK(progress->SetRatioInfo(&packSize, &pos))\n    }\n    Byte b;\n    if (!m_InStream.ReadByte(b))\n      return S_FALSE;\n    const UInt64 rem = outSize - pos;\n    if (b & 0x80)\n    {\n      unsigned num = (unsigned)b - 0x80 + 1;\n      if (num > rem)\n        return S_FALSE;\n      pos += num;\n      do\n      {\n        if (!m_InStream.ReadByte(b))\n          return S_FALSE;\n        m_OutWindowStream.PutByte(b);\n      }\n      while (--num);\n      continue;\n    }\n    Byte b1;\n    if (!m_InStream.ReadByte(b1))\n      return S_FALSE;\n\n    UInt32 len, dist;\n\n    if (b & 0x40)\n    {\n      len = (UInt32)b - 0x40 + 4;\n      Byte b2;\n      if (!m_InStream.ReadByte(b2))\n        return S_FALSE;\n      dist = ((UInt32)b1 << 8) + b2;\n    }\n    else\n    {\n      len = ((UInt32)b >> 2) + 3;\n      dist = (((UInt32)b & 3) << 8) + b1;\n    }\n\n    if (/* dist >= pos || */ len > rem)\n      return S_FALSE;\n    if (!m_OutWindowStream.CopyBlock(dist, len))\n      return S_FALSE;\n    pos += len;\n  }\n  if (*inSize != m_InStream.GetProcessedSize())\n    return S_FALSE;\n  coderReleaser.NeedFlush = false;\n  return m_OutWindowStream.Flush();\n\n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\n\n\nstruct CDecoders\n{\n  CMyComPtr2<ICompressCoder, NCompress::NZlib::CDecoder> zlib;\n  CMyComPtr2<ICompressCoder, NCompress::NBZip2::CDecoder> bzip2;\n  CMyComPtr2<ICompressCoder, NCompress::NLzfse::CDecoder> lzfse;\n  CMyUniquePtr<NCompress::NXz::CDecoder> xz;\n  CMyUniquePtr<CAdcDecoder> adc;\n\n  HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const CBlock &block, const UInt64 *unpSize, ICompressProgressInfo *progress);\n};\n\nHRESULT CDecoders::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const CBlock &block, const UInt64 *unpSize, ICompressProgressInfo *progress)\n{\n  HRESULT hres;\n  UInt64 processed;\n  switch (block.Type)\n  {\n    case METHOD_ADC:\n      adc.Create_if_Empty();\n      return adc->Code(inStream, outStream, &block.PackSize, unpSize, progress);\n    case METHOD_LZFSE:\n      lzfse.Create_if_Empty();\n      return lzfse.Interface()->Code(inStream, outStream, &block.PackSize, unpSize, progress);\n    case METHOD_ZLIB:\n      zlib.Create_if_Empty();\n      hres = zlib.Interface()->Code(inStream, outStream, NULL, unpSize, progress);\n      processed = zlib->GetInputProcessedSize();\n      break;\n    case METHOD_BZIP2:\n      bzip2.Create_if_Empty();\n      hres = bzip2.Interface()->Code(inStream, outStream, NULL, unpSize, progress);\n      processed = bzip2->GetInputProcessedSize();\n      break;\n    case METHOD_XZ:\n      xz.Create_if_Empty();\n      hres = xz->Decode(inStream, outStream, unpSize, true, progress);\n      processed = xz->Stat.InSize;\n      break;\n    default:\n      return E_NOTIMPL;\n  }\n  if (hres == S_OK && processed != block.PackSize)\n    hres = S_FALSE;\n  return hres;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _files.Size()\n#ifdef DMG_SHOW_RAW\n    + _extras.Size()\n#endif\n  ;\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  \n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n#ifdef DMG_SHOW_RAW\n    if (index >= _files.Size())\n      totalSize += _extras[index - _files.Size()].Data.Size();\n    else\n#endif\n      totalSize += _files[index].Size;\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  const size_t kZeroBufSize = 1 << 14;\n  CAlignedBuffer1 zeroBuf(kZeroBufSize);\n  memset(zeroBuf, 0, kZeroBufSize);\n  \n  CDecoders decoders;\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_inStream);\n\n  UInt64 total_PackSize = 0;\n  UInt64 total_UnpackSize = 0;\n  UInt64 cur_PackSize = 0;\n  UInt64 cur_UnpackSize = 0;\n\n  for (i = 0;; i++,\n        total_PackSize   += cur_PackSize,\n        total_UnpackSize += cur_UnpackSize)\n  {\n    lps->InSize = total_PackSize;\n    lps->OutSize = total_UnpackSize;\n    cur_PackSize = 0;\n    cur_UnpackSize = 0;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      return S_OK;\n    \n    Int32 opRes = NExtract::NOperationResult::kOK;\n   {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n#ifdef DMG_SHOW_RAW\n    if (index >= _files.Size())\n    {\n      const CByteBuffer &buf = _extras[index - _files.Size()].Data;\n      if (realOutStream)\n        RINOK(WriteStream(realOutStream, buf, buf.Size()))\n      cur_PackSize = cur_UnpackSize = buf.Size();\n    }\n    else\n#endif\n    {\n      const CFile &item = _files[index];\n      cur_PackSize = item.PackSize;\n      cur_UnpackSize = item.Size;\n\n      if (!item.IsCorrect)\n        opRes = NExtract::NOperationResult::kHeadersError;\n      else\n      {\n        CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outCrcStream;\n        outCrcStream->SetStream(realOutStream);\n        // realOutStream.Release();\n        const bool needCrc = item.Checksum.IsCrc32();\n        outCrcStream->Init(needCrc);\n        \n        CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStream;\n        outStream->SetStream(outCrcStream);\n        \n        UInt64 unpPos = 0;\n        UInt64 packPos = 0;\n\n        FOR_VECTOR (blockIndex, item.Blocks)\n        {\n          lps->InSize = total_PackSize + packPos;\n          lps->OutSize = total_UnpackSize + unpPos;\n          RINOK(lps->SetCur())\n\n          const CBlock &block = item.Blocks[blockIndex];\n          // if (!block.ThereAreDataInBlock()) continue;\n\n          packPos += block.PackSize;\n          if (block.UnpPos != unpPos)\n          {\n            opRes = NExtract::NOperationResult::kHeadersError;\n            break;\n          }\n\n          RINOK(InStream_SeekSet(_inStream, _startPos + _dataForkPair.Offset + item.StartPackPos + block.PackPos))\n          inStream->Init(block.PackSize);\n\n          const UInt64 unpSize = item.GetUnpackSize_of_Block(blockIndex);\n\n          outStream->Init(unpSize);\n          HRESULT res = S_OK;\n\n          outCrcStream->EnableCalc(needCrc && block.NeedCrc());\n\n          if (block.IsZeroMethod())\n          {\n            if (block.PackSize != 0)\n              opRes = NExtract::NOperationResult::kUnsupportedMethod;\n          }\n          else if (block.Type == METHOD_COPY)\n          {\n            if (unpSize != block.PackSize)\n              opRes = NExtract::NOperationResult::kUnsupportedMethod;\n            else\n              res = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);\n          }\n          else\n            res = decoders.Code(inStream, outStream, block, &unpSize, lps);\n\n          if (res != S_OK)\n          {\n            if (res != S_FALSE)\n            {\n              if (res != E_NOTIMPL)\n                return res;\n              opRes = NExtract::NOperationResult::kUnsupportedMethod;\n            }\n            if (opRes == NExtract::NOperationResult::kOK)\n              opRes = NExtract::NOperationResult::kDataError;\n          }\n          \n          unpPos += unpSize;\n          \n          if (!outStream->IsFinishedOK())\n          {\n            if (!block.IsZeroMethod() && opRes == NExtract::NOperationResult::kOK)\n              opRes = NExtract::NOperationResult::kDataError;\n\n            for (unsigned k = 0;;)\n            {\n              const UInt64 rem = outStream->GetRem();\n              if (rem == 0)\n                break;\n              size_t size = kZeroBufSize;\n              if (size > rem)\n                size = (size_t)rem;\n              RINOK(WriteStream(outStream, zeroBuf, size))\n              k++;\n              if ((k & 0xfff) == 0)\n              {\n                lps->OutSize = total_UnpackSize + unpPos - outStream->GetRem();\n                RINOK(lps->SetCur())\n              }\n            }\n          }\n        }\n        if (needCrc && opRes == NExtract::NOperationResult::kOK)\n        {\n          if (outCrcStream->GetCRC() != item.Checksum.GetCrc32())\n            opRes = NExtract::NOperationResult::kCRCError;\n        }\n      }\n    }\n   }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n\n  COM_TRY_END\n}\n\n\n\n\nstruct CChunk\n{\n  int BlockIndex;\n  UInt64 AccessMark;\n  Byte *Buf;\n  size_t BufSize;\n\n  void Free()\n  {\n    z7_AlignedFree(Buf);\n    Buf = NULL;\n    BufSize = 0;\n  }\n  void Alloc(size_t size)\n  {\n    Buf = (Byte *)z7_AlignedAlloc(size);\n  }\n};\n\n\nZ7_CLASS_IMP_IInStream(\n  CInStream\n)\n  bool _errorMode;\n  UInt64 _virtPos;\n  int _latestChunk;\n  int _latestBlock;\n  UInt64 _accessMark;\n  UInt64 _chunks_TotalSize;\n  CRecordVector<CChunk> _chunks;\n\npublic:\n  CMyComPtr<IInStream> Stream;\n  const CFile *File;\n  UInt64 Size;\nprivate:\n  UInt64 _startPos;\n\n  ~CInStream();\n  CMyComPtr2<ISequentialOutStream, CBufPtrSeqOutStream> outStream;\n  CMyComPtr2<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  CDecoders decoders;\npublic:\n\n  // HRESULT\n  void Init(UInt64 startPos)\n  {\n    _errorMode = false;\n    _startPos = startPos;\n    _virtPos = 0;\n    _latestChunk = -1;\n    _latestBlock = -1;\n    _accessMark = 0;\n    _chunks_TotalSize = 0;\n\n    inStream.Create_if_Empty();\n    inStream->SetStream(Stream);\n\n    outStream.Create_if_Empty();\n    // return S_OK;\n  }\n};\n\n\nCInStream::~CInStream()\n{\n  unsigned i = _chunks.Size();\n  while (i)\n    _chunks[--i].Free();\n}\n\nstatic unsigned FindBlock(const CRecordVector<CBlock> &blocks, UInt64 pos)\n{\n  unsigned left = 0, right = blocks.Size();\n  for (;;)\n  {\n    const unsigned mid = (left + right) / 2;\n    if (mid == left)\n      return left;\n    if (pos < blocks[mid].UnpPos)\n      right = mid;\n    else\n      left = mid;\n  }\n}\n\nZ7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  // COM_TRY_BEGIN\n  try {\n\n  if (_errorMode)\n    return E_OUTOFMEMORY;\n\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (_virtPos >= Size)\n    return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL;\n  {\n    const UInt64 rem = Size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n\n  if (_latestBlock >= 0)\n  {\n    const CBlock &block = File->Blocks[(unsigned)_latestBlock];\n    if (_virtPos < block.UnpPos ||\n        _virtPos - block.UnpPos >= File->GetUnpackSize_of_Block((unsigned)_latestBlock))\n      _latestBlock = -1;\n  }\n  \n  if (_latestBlock < 0)\n  {\n    _latestChunk = -1;\n    const unsigned blockIndex = FindBlock(File->Blocks, _virtPos);\n    const CBlock &block = File->Blocks[blockIndex];\n    const UInt64 unpSize = File->GetUnpackSize_of_Block(blockIndex);\n    \n    if (block.NeedAllocateBuffer()\n        && unpSize <= k_Chunk_Size_MAX)\n    {\n      unsigned i = 0;\n      {\n        unsigned numChunks = _chunks.Size();\n        if (numChunks)\n        {\n          const CChunk *chunk = _chunks.ConstData();\n          do\n          {\n            if (chunk->BlockIndex == (int)blockIndex)\n              break;\n            chunk++;\n          }\n          while (--numChunks);\n          i = _chunks.Size() - numChunks;\n        }\n      }\n      if (i != _chunks.Size())\n        _latestChunk = (int)i;\n      else\n      {\n        unsigned chunkIndex;\n        for (;;)\n        {\n          if (_chunks.IsEmpty() ||\n              (_chunks.Size() < k_NumChunks_MAX\n              && _chunks_TotalSize + unpSize <= k_Chunks_TotalSize_MAX))\n          {\n            CChunk chunk;\n            chunk.Buf = NULL;\n            chunk.BufSize = 0;\n            chunk.BlockIndex = -1;\n            chunk.AccessMark = 0;\n            chunkIndex = _chunks.Add(chunk);\n            break;\n          }\n          chunkIndex = 0;\n          if (_chunks.Size() == 1)\n            break;\n          {\n            const CChunk *chunks = _chunks.ConstData();\n            UInt64 accessMark_min = chunks[chunkIndex].AccessMark;\n            const unsigned numChunks = _chunks.Size();\n            for (i = 1; i < numChunks; i++)\n            {\n              if (chunks[i].AccessMark < accessMark_min)\n              {\n                chunkIndex = i;\n                accessMark_min = chunks[i].AccessMark;\n              }\n            }\n          }\n          {\n            CChunk &chunk = _chunks[chunkIndex];\n            const UInt64 newTotalSize = _chunks_TotalSize - chunk.BufSize;\n            if (newTotalSize + unpSize <= k_Chunks_TotalSize_MAX)\n              break;\n            _chunks_TotalSize = newTotalSize;\n            chunk.Free();\n          }\n          // we have called chunk.Free() before, because\n          // _chunks.Delete() doesn't call chunk.Free().\n          _chunks.Delete(chunkIndex);\n          PRF(printf(\"\\n++num_chunks=%u, _chunks_TotalSize = %u\\n\", (unsigned)_chunks.Size(), (unsigned)_chunks_TotalSize);)\n        }\n        \n        CChunk &chunk = _chunks[chunkIndex];\n        chunk.BlockIndex = -1;\n        chunk.AccessMark = 0;\n        \n        if (chunk.BufSize < unpSize)\n        {\n          _chunks_TotalSize -= chunk.BufSize;\n          chunk.Free();\n          // if (unpSize > k_Chunk_Size_MAX) return E_FAIL;\n          chunk.Alloc((size_t)unpSize);\n          if (!chunk.Buf)\n            return E_OUTOFMEMORY;\n          chunk.BufSize = (size_t)unpSize;\n          _chunks_TotalSize += chunk.BufSize;\n        }\n        \n        RINOK(InStream_SeekSet(Stream, _startPos + File->StartPackPos + block.PackPos))\n\n        inStream->Init(block.PackSize);\n#ifdef Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS\n        if (block.Type == METHOD_COPY)\n        {\n          if (block.PackSize != unpSize)\n            return E_FAIL;\n          RINOK(ReadStream_FAIL(inStream, chunk.Buf, (size_t)unpSize))\n        }\n        else\n#endif\n        {\n          outStream->Init(chunk.Buf, (size_t)unpSize);\n          RINOK(decoders.Code(inStream, outStream, block, &unpSize, NULL))\n          if (outStream->GetPos() != unpSize)\n            return E_FAIL;\n        }\n        chunk.BlockIndex = (int)blockIndex;\n        _latestChunk = (int)chunkIndex;\n      }\n      \n      _chunks[_latestChunk].AccessMark = _accessMark++;\n    }\n  \n    _latestBlock = (int)blockIndex;\n  }\n\n  const CBlock &block = File->Blocks[(unsigned)_latestBlock];\n  const UInt64 offset = _virtPos - block.UnpPos;\n  {\n    const UInt64 rem = File->GetUnpackSize_of_Block((unsigned)_latestBlock) - offset;\n    if (size > rem)\n      size = (UInt32)rem;\n    if (size == 0) // it's unexpected case. but we check it.\n      return S_OK;\n  }\n  HRESULT res = S_OK;\n  \n  if (block.IsZeroMethod())\n    memset(data, 0, size);\n  else if (_latestChunk >= 0)\n    memcpy(data, _chunks[_latestChunk].Buf + (size_t)offset, size);\n  else\n  {\n    if (block.Type != METHOD_COPY)\n      return E_FAIL;\n    RINOK(InStream_SeekSet(Stream, _startPos + File->StartPackPos + block.PackPos + offset))\n    res = Stream->Read(data, size, &size);\n  }\n  \n  _virtPos += size;\n  if (processedSize)\n    *processedSize = size;\n  return res;\n  // COM_TRY_END\n  }\n  catch(...)\n  {\n    _errorMode = true;\n    return E_OUTOFMEMORY;\n  }\n}\n\n \nZ7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  \n#ifdef DMG_SHOW_RAW\n  if (index >= _files.Size())\n    return S_FALSE;\n#endif\n  \n  CMyComPtr2<ISequentialInStream, CInStream> spec;\n  spec.Create_if_Empty();\n  spec->File = &_files[index];\n  const CFile &file = *spec->File;\n\n  if (!file.IsCorrect)\n    return S_FALSE;\n  \n  FOR_VECTOR (i, file.Blocks)\n  {\n    const CBlock &block = file.Blocks[i];\n    if (!block.NeedAllocateBuffer())\n      continue;\n\n    switch (block.Type)\n    {\n#ifdef Z7_DMG_USE_CACHE_FOR_COPY_BLOCKS\n      case METHOD_COPY:\n        break;\n#endif\n      case METHOD_ADC:\n      case METHOD_ZLIB:\n      case METHOD_BZIP2:\n      case METHOD_LZFSE:\n      case METHOD_XZ:\n      // case METHOD_END:\n        if (file.GetUnpackSize_of_Block(i) > k_Chunk_Size_MAX)\n          return S_FALSE;\n        break;\n      default:\n        return S_FALSE;\n    }\n  }\n  \n  spec->Stream = _inStream;\n  spec->Size = spec->File->Size;\n  // RINOK(\n  spec->Init(_startPos + _dataForkPair.Offset);\n  *stream = spec.Detach();\n  return S_OK;\n  \n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"Dmg\", \"dmg\", NULL, 0xE4,\n  k_Signature,\n  0,\n  NArcInfoFlags::kBackwardOpen |\n  NArcInfoFlags::kUseGlobalOffset,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ElfHandler.cpp",
    "content": "﻿// ElfHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n// #define Z7_ELF_SHOW_DETAILS\n\nusing namespace NWindows;\n\nstatic UInt16 Get16(const Byte *p, bool be) { if (be) return GetBe16a(p); return GetUi16a(p); }\nstatic UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32a(p); return GetUi32a(p); }\nstatic UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64a(p); return GetUi64a(p); }\n\n#define G16(offs, v) v = Get16(p + (offs), be)\n#define G32(offs, v) v = Get32(p + (offs), be)\n#define G64(offs, v) v = Get64(p + (offs), be)\n\nnamespace NArchive {\nnamespace NElf {\n\n/*\nELF Structure example:\n{\n  Header\n  Program header table (is used at runtime) (list of segment metadata records)\n  {\n    Segment (Read)\n      Segment : PT_PHDR : header table itself\n      Segment : PT_INTERP\n      Segment : PT_NOTE\n      .rela.dyn (RELA, ALLOC)\n    Segment (Execute/Read)\n      .text section (PROGBITS, SHF_ALLOC | SHF_EXECINSTR)\n    Segment (Read)\n      .rodata (PROGBITS, SHF_ALLOC | SHF_WRITE)\n      Segment : PT_GNU_EH_FRAME\n        .eh_frame_hdr\n      .eh_frame\n      .gcc_except_table\n    ...\n    Segment (Write/Read) (VaSize > Size)\n      Segment (Read) : PT_GNU_RELRO\n      Segment (Write/Read)\n      .data\n      .bss (Size == 0) (VSize != 0)\n  }\n  .comment (VA == 0)\n  .shstrtab (VA == 0)\n  Section header table (the data for linking and relocation)\n}\n\n  Last top level segment contains .bss section that requires additional VA space.\n  So (VaSize > Size) for that segment.\n\n  Segments can be unsorted (by offset) in table.\n  Top level segments has Type=PT_LOAD : \"Loadable segment\".\n  Top level segments usually are aligned for page size (4 KB).\n  Another segments (non PT_LOAD segments) are inside PT_LOAD segments.\n\n  (VA-offset == 0) is possible for some sections and segments at the beginning of file.\n  (VA-offset == 4KB*N) for most sections and segments where (Size != 0),\n  (VA-offset != 4KB*N) for .bss section (last section), because (Size == 0),\n    and that section is not mapped from image file.\n  Some files contain additional \"virtual\" 4 KB page in VA space after\n  end of data of top level segments (PT_LOAD) before new top level segments.\n  So (VA-offset) value can increase by 4 KB step.\n*/\n\n#define ELF_CLASS_32 1\n#define ELF_CLASS_64 2\n\n#define ELF_DATA_2LSB 1\n#define ELF_DATA_2MSB 2\n\nstatic const unsigned kHeaderSize32 = 0x34;\nstatic const unsigned kHeaderSize64 = 0x40;\n\nstatic const unsigned kSegmentSize32 = 0x20;\nstatic const unsigned kSegmentSize64 = 0x38;\n\nstatic const unsigned kSectionSize32 = 0x28;\nstatic const unsigned kSectionSize64 = 0x40;\n\nstruct CHeader\n{\n  bool Mode64;\n  bool Be;\n  Byte Os;\n  Byte AbiVer;\n\n  UInt16 Type;\n  UInt16 Machine;\n  // UInt32 Version;\n\n  // UInt64 EntryVa;\n  UInt64 ProgOffset;\n  UInt64 SectOffset;\n  UInt32 Flags;\n  UInt16 HeaderSize;\n  UInt16 SegmentEntrySize;\n  UInt16 NumSegments;\n  UInt16 SectionEntrySize;\n  UInt16 NumSections;\n  UInt16 NamesSectIndex;\n\n  bool Parse(const Byte *p);\n\n  UInt32 GetHeadersSize() const { return (UInt32)HeaderSize +\n      (UInt32)NumSegments * SegmentEntrySize +\n      (UInt32)NumSections * SectionEntrySize; }\n};\n\nbool CHeader::Parse(const Byte *p)\n{\n  switch (p[4])\n  {\n    case ELF_CLASS_32: Mode64 = false; break;\n    case ELF_CLASS_64: Mode64 = true; break;\n    default: return false;\n  }\n  bool be;\n  switch (p[5])\n  {\n    case ELF_DATA_2LSB: be = false; break;\n    case ELF_DATA_2MSB: be = true; break;\n    default: return false;\n  }\n  Be = be;\n  if (p[6] != 1) // Version\n    return false;\n  Os = p[7];\n  // AbiVer = p[8];\n  for (int i = 9; i < 16; i++)\n    if (p[i] != 0)\n      return false;\n\n  G16(0x10, Type);\n  G16(0x12, Machine);\n  if (Get32(p + 0x14, be) != 1) // Version\n    return false;\n\n  if (Mode64)\n  {\n    // G64(0x18, EntryVa);\n    G64(0x20, ProgOffset); // == kHeaderSize64 == 0x40 usually\n    G64(0x28, SectOffset);\n    p += 0x30;\n    // we expect that fields are aligned\n    if (ProgOffset & 7) return false;\n    if (SectOffset & 7) return false;\n  }\n  else\n  {\n    // G32(0x18, EntryVa);\n    G32(0x1C, ProgOffset); // == kHeaderSize32 == 0x34 usually\n    G32(0x20, SectOffset);\n    p += 0x24;\n    if (ProgOffset & 3) return false;\n    if (SectOffset & 3) return false;\n  }\n\n  G32(0, Flags);\n  G16(4, HeaderSize);\n  if (HeaderSize != (Mode64 ? kHeaderSize64 : kHeaderSize32))\n    return false;\n\n  G16(6, SegmentEntrySize);\n  G16(8, NumSegments);\n  G16(10, SectionEntrySize);\n  G16(12, NumSections);\n  G16(14, NamesSectIndex);\n\n  if (ProgOffset < HeaderSize && (ProgOffset || NumSegments)) return false;\n  if (SectOffset < HeaderSize && (SectOffset || NumSections)) return false;\n\n  if (SegmentEntrySize == 0) { if (NumSegments) return false; }\n  else if (SegmentEntrySize != (Mode64 ? kSegmentSize64 : kSegmentSize32)) return false;\n\n  if (SectionEntrySize == 0) { if (NumSections) return false; }\n  else if (SectionEntrySize != (Mode64 ? kSectionSize64 : kSectionSize32)) return false;\n\n  return true;\n}\n\n\n#define PT_PHDR 6  // The program header table itself.\n#define PT_GNU_STACK 0x6474e551\n\nstatic const CUInt32PCharPair g_SegnmentTypes[] =\n{\n  { 0, \"Unused\" },\n  { 1, \"Loadable segment\" },\n  { 2, \"Dynamic linking tables\" },\n  { 3, \"Program interpreter path name\" },\n  { 4, \"Note section\" },\n  { 5, \"SHLIB\" },\n  { 6, \"Program header table\" },\n  { 7, \"TLS\" },\n  { 0x6474e550, \"GNU_EH_FRAME\" },\n  { PT_GNU_STACK, \"GNU_STACK\" },\n  { 0x6474e552, \"GNU_RELRO\" }\n};\n\n\nstatic const char * const g_SegmentFlags[] =\n{\n    \"Execute\"\n  , \"Write\"\n  , \"Read\"\n};\n\nstruct CSegment\n{\n  UInt32 Type;\n  UInt32 Flags;\n  UInt64 Offset;\n  UInt64 Va;\n  UInt64 Size;  // size in file\n  UInt64 VSize; // size in memory\n#ifdef Z7_ELF_SHOW_DETAILS\n  UInt64 Pa;    // usually == Va, or == 0\n  UInt64 Align; // if (Align != 0), condition must be met:\n                //   (VSize % Align == Offset % Alig)\n#endif\n  void UpdateTotalSize(UInt64 &totalSize)\n  {\n    const UInt64 t = Offset + Size;\n    if (totalSize < t)\n        totalSize = t;\n  }\n  void Parse(const Byte *p, bool mode64, bool be);\n};\n\nvoid CSegment::Parse(const Byte *p, bool mode64, bool be)\n{\n  G32(0, Type);\n  if (mode64)\n  {\n    G32(4, Flags);\n    G64(8, Offset);\n    G64(0x10, Va);\n    G64(0x20, Size);\n    G64(0x28, VSize);\n#ifdef Z7_ELF_SHOW_DETAILS\n    G64(0x18, Pa);\n    G64(0x30, Align);\n#endif\n  }\n  else\n  {\n    G32(4, Offset);\n    G32(8, Va);\n    G32(0x10, Size);\n    G32(0x14, VSize);\n    G32(0x18, Flags);\n#ifdef Z7_ELF_SHOW_DETAILS\n    G32(0x0C, Pa);\n    G32(0x1C, Align);\n#endif\n  }\n}\n\n// Section_index = 0 means NO section\n\n#define SHN_UNDEF 0\n\n// Section types\n\n/*\n#define SHT_NULL           0\n#define SHT_PROGBITS       1\n#define SHT_SYMTAB         2\n#define SHT_STRTAB         3\n#define SHT_RELA           4\n#define SHT_HASH           5\n#define SHT_DYNAMIC        6\n#define SHT_NOTE           7\n*/\n#define SHT_NOBITS         8\n/*\n#define SHT_REL            9\n#define SHT_SHLIB         10\n#define SHT_DYNSYM        11\n#define SHT_UNKNOWN12     12\n#define SHT_UNKNOWN13     13\n#define SHT_INIT_ARRAY    14\n#define SHT_FINI_ARRAY    15\n#define SHT_PREINIT_ARRAY 16\n#define SHT_GROUP         17\n#define SHT_SYMTAB_SHNDX  18\n*/\n\nstatic const CUInt32PCharPair g_SectTypes[] =\n{\n  { 0, \"NULL\" },\n  { 1, \"PROGBITS\" },\n  { 2, \"SYMTAB\" },\n  { 3, \"STRTAB\" },\n  { 4, \"RELA\" },\n  { 5, \"HASH\" },\n  { 6, \"DYNAMIC\" },\n  { 7, \"NOTE\" },\n  { 8, \"NOBITS\" },\n  { 9, \"REL\" },\n  { 10, \"SHLIB\" },\n  { 11, \"DYNSYM\" },\n  { 12, \"UNKNOWN12\" },\n  { 13, \"UNKNOWN13\" },\n  { 14, \"INIT_ARRAY\" },\n  { 15, \"FINI_ARRAY\" },\n  { 16, \"PREINIT_ARRAY\" },\n  { 17, \"GROUP\" },\n  { 18, \"SYMTAB_SHNDX\" },\n\n  { 0x6ffffff5, \"GNU_ATTRIBUTES\" },\n  { 0x6ffffff6, \"GNU_HASH\" },\n  { 0x6ffffffd, \"GNU_verdef\" },\n  { 0x6ffffffe, \"GNU_verneed\" },\n  { 0x6fffffff, \"GNU_versym\" },\n  // { 0x70000001, \"X86_64_UNWIND\" },\n  { 0x70000001, \"ARM_EXIDX\" },\n  { 0x70000002, \"ARM_PREEMPTMAP\" },\n  { 0x70000003, \"ARM_ATTRIBUTES\" },\n  { 0x70000004, \"ARM_DEBUGOVERLAY\" },\n  { 0x70000005, \"ARM_OVERLAYSECTION\" }\n};\n\n\n// SHF_ flags\nstatic const CUInt32PCharPair g_SectionFlags[] =\n{\n  { 0, \"WRITE\" },\n  { 1, \"ALLOC\" },\n  { 2, \"EXECINSTR\" },\n\n  { 4, \"MERGE\" },\n  { 5, \"STRINGS\" },\n  { 6, \"INFO_LINK\" },\n  { 7, \"LINK_ORDER\" },\n  { 8, \"OS_NONCONFORMING\" },\n  { 9, \"GROUP\" },\n  { 10, \"TLS\" },\n  { 11, \"COMPRESSED\" },\n  { 12, \"DP_SECTION\" },\n  { 13, \"XCORE_SHF_CP_SECTION\" },\n  { 28, \"64_LARGE\" },\n};\n\nstruct CSection\n{\n  UInt32 Name;\n  UInt32 Type;\n  UInt64 Flags;\n  UInt64 Va;\n  UInt64 Offset;\n  UInt64 VSize;\n  UInt32 Link;\n  UInt32 Info;\n  UInt64 AddrAlign;\n  UInt64 EntSize;\n\n  UInt64 GetSize() const { return Type == SHT_NOBITS ? 0 : VSize; }\n\n  void UpdateTotalSize(UInt64 &totalSize)\n  {\n    const UInt64 t = Offset + GetSize();\n    if (totalSize < t)\n        totalSize = t;\n  }\n  bool Parse(const Byte *p, bool mode64, bool be);\n};\n\nbool CSection::Parse(const Byte *p, bool mode64, bool be)\n{\n  G32(0, Name);\n  G32(4, Type);\n  if (mode64)\n  {\n    G64(0x08, Flags);\n    G64(0x10, Va);\n    G64(0x18, Offset);\n    G64(0x20, VSize);\n    G32(0x28, Link);\n    G32(0x2C, Info);\n    G64(0x30, AddrAlign);\n    G64(0x38, EntSize);\n  }\n  else\n  {\n    G32(0x08, Flags);\n    G32(0x0C, Va);\n    G32(0x10, Offset);\n    G32(0x14, VSize);\n    G32(0x18, Link);\n    G32(0x1C, Info);\n    G32(0x20, AddrAlign);\n    G32(0x24, EntSize);\n  }\n  if (EntSize >= ((UInt32)1 << 31))\n    return false;\n  if (EntSize >= ((UInt32)1 << 10) &&\n      EntSize >= VSize &&\n      VSize != 0)\n    return false;\n  return true;\n}\n\n\nstatic const char * const g_Machines[] =\n{\n    \"None\"\n  , \"AT&T WE 32100\"\n  , \"SPARC\"\n  , \"Intel 386\"\n  , \"Motorola 68000\"\n  , \"Motorola 88000\"\n  , \"Intel 486\"\n  , \"Intel i860\"\n  , \"MIPS\"\n  , \"IBM S/370\"\n  , \"MIPS RS3000 LE\"\n  , \"RS6000\"\n  , NULL\n  , NULL\n  , NULL\n  , \"PA-RISC\"\n  , \"nCUBE\"\n  , \"Fujitsu VPP500\"\n  , \"SPARC 32+\"\n  , \"Intel i960\"\n  , \"PowerPC\"\n  , \"PowerPC 64-bit\"\n  , \"IBM S/390\"\n  , \"SPU\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"NEX v800\"\n  , \"Fujitsu FR20\"\n  , \"TRW RH-32\"\n  , \"Motorola RCE\"\n  , \"ARM\"\n  , \"Alpha-STD\"\n  , \"Hitachi SH\"\n  , \"SPARC-V9\"\n  , \"Siemens Tricore\"\n  , \"ARC\"\n  , \"H8/300\"\n  , \"H8/300H\"\n  , \"H8S\"\n  , \"H8/500\"\n  , \"IA-64\"\n  , \"Stanford MIPS-X\"\n  , \"Motorola ColdFire\"\n  , \"M68HC12\"\n  , \"Fujitsu MMA\"\n  , \"Siemens PCP\"\n  , \"Sony nCPU\"\n  , \"Denso NDR1\"\n  , \"Motorola StarCore\"\n  , \"Toyota ME16\"\n  , \"ST100\"\n  , \"Advanced Logic TinyJ\"\n  , \"AMD64\"\n  , \"Sony DSP\"\n  , NULL\n  , NULL\n  , \"Siemens FX66\"\n  , \"ST9+\"\n  , \"ST7\"\n  , \"MC68HC16\"\n  , \"MC68HC11\"\n  , \"MC68HC08\"\n  , \"MC68HC05\"\n  , \"Silicon Graphics SVx\"\n  , \"ST19\"\n  , \"Digital VAX\"\n  , \"Axis CRIS\"\n  , \"Infineon JAVELIN\"\n  , \"Element 14 FirePath\"\n  , \"LSI ZSP\"\n  , \"MMIX\"\n  , \"HUANY\"\n  , \"SiTera Prism\"\n  , \"Atmel AVR\"\n  , \"Fujitsu FR30\"\n  , \"Mitsubishi D10V\"\n  , \"Mitsubishi D30V\"\n  , \"NEC v850\"\n  , \"Mitsubishi M32R\"\n  , \"Matsushita MN10300\"\n  , \"Matsushita MN10200\"\n  , \"picoJava\"\n  , \"OpenRISC\"\n  , \"ARC Tangent-A5\"\n  , \"Tensilica Xtensa\"\n  , \"Alphamosaic VideoCore\"\n  , \"Thompson MM GPP\"\n  , \"National Semiconductor 32K\"\n  , \"Tenor Network TPC\"\n  , \"Trebia SNP 1000\"\n  , \"ST200\"\n  , \"Ubicom IP2xxx\"\n  , \"MAX\"\n  , \"NS CompactRISC\"\n  , \"Fujitsu F2MC16\"\n  , \"TI msp430\"\n  , \"Blackfin (DSP)\"\n  , \"SE S1C33\"\n  , \"Sharp embedded\"\n  , \"Arca RISC\"\n  , \"Unicore\"\n  , \"eXcess\"\n  , \"DXP\"\n  , \"Altera Nios II\"\n  , \"NS CRX\"\n  , \"Motorola XGATE\"\n  , \"Infineon C16x/XC16x\"\n  , \"Renesas M16C\"\n  , \"Microchip Technology dsPIC30F\"\n  , \"Freescale CE\"\n  , \"Renesas M32C\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"Altium TSK3000\"\n  , \"Freescale RS08\"\n  , \"Analog Devices SHARC\"\n  , \"Cyan Technology eCOG2\"\n  , \"Sunplus S+core7 RISC\"\n  , \"NJR 24-bit DSP\"\n  , \"Broadcom VideoCore III\"\n  , \"Lattice FPGA\"\n  , \"SE C17\"\n  , \"TI TMS320C6000\"\n  , \"TI TMS320C2000\"\n  , \"TI TMS320C55x\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"STM 64bit VLIW Data Signal\"\n  , \"Cypress M8C\"\n  , \"Renesas R32C\"\n  , \"NXP TriMedia\"\n  , \"Qualcomm Hexagon\"\n  , \"Intel 8051\"\n  , \"STMicroelectronics STxP7x\"\n  , \"Andes\"\n  , \"Cyan Technology eCOG1X\"\n  , \"Dallas Semiconductor MAXQ30\"\n  , \"NJR 16-bit DSP\"\n  , \"M2000\"\n  , \"Cray NV2\"\n  , \"Renesas RX\"\n  , \"Imagination Technologies META\"\n  , \"MCST Elbrus\"\n  , \"Cyan Technology eCOG16\"\n  , \"National Semiconductor CR16\"\n  , \"Freescale ETPUnit\"\n  , \"Infineon SLE9X\"\n  , \"Intel L10M\"\n  , \"Intel K10M\"\n  , NULL\n  , \"ARM64\"\n  , NULL\n  , \"Atmel AVR32\"\n  , \"STM8\"\n  , \"Tilera TILE64\"\n  , \"Tilera TILEPro\"\n  , \"Xilinx MicroBlaze\"\n  , \"NVIDIA CUDA\"\n  , \"Tilera TILE-Gx\"\n  , \"CloudShield\"\n  , \"KIPO-KAIST Core-A 1st\"\n  , \"KIPO-KAIST Core-A 2nd\"\n  , \"Synopsys ARCompact V2\"\n  , \"Open8\"\n  , \"Renesas RL78\"\n  , \"Broadcom VideoCore V\"\n  , \"Renesas 78KOR\"\n  , \"Freescale 56800EX\" // 200\n};\n\nstatic const CUInt32PCharPair g_MachinePairs[] =\n{\n  { 243, \"RISC-V\" },\n  { 258, \"LoongArch\" },\n  { 0x9026, \"Alpha\" },  // EM_ALPHA_EXP, obsolete, (used by NetBSD/alpha) (written in the absence of an ABI)\n  { 0xbaab, \"Xilinx MicroBlaze\" }\n};\n\nstatic const CUInt32PCharPair g_OS[] =\n{\n  { 0, \"None\" },\n  { 1, \"HP-UX\" },\n  { 2, \"NetBSD\" },\n  { 3, \"Linux\" },\n  { 4, \"Hurd\" },\n\n  { 6, \"Solaris\" },\n  { 7, \"AIX\" },\n  { 8, \"IRIX\" },\n  { 9, \"FreeBSD\" },\n  { 10, \"TRU64\" },\n  { 11, \"Novell Modesto\" },\n  { 12, \"OpenBSD\" },\n  { 13, \"OpenVMS\" },\n  { 14, \"HP NSK\" },\n  { 15, \"AROS\" },\n  { 16, \"FenixOS\" },\n  { 17, \"CloudABI\" },\n  { 18, \"OpenVOS\" },\n  { 64, \"Bare-metal TMS320C6000\" },\n  { 65, \"Linux TMS320C6000\" },\n  { 97, \"ARM\" },\n  { 255, \"Standalone\" }\n};\n\n#define k_Machine_MIPS 8\n#define k_Machine_ARM 40\n#define k_Machine_RISCV 243\n\n/*\n#define EF_ARM_ABIMASK        0xFF000000\n#define EF_ARM_BE8            0x00800000\n#define EF_ARM_GCCMASK        0x00400FFF\n#define EF_ARM_ABI_FLOAT_SOFT 0x00000200\n#define EF_ARM_ABI_FLOAT_HARD 0x00000400\n*/\n\nstatic const CUInt32PCharPair g_ARM_Flags[] =\n{\n  { 1, \"HasEntry\" },\n  { 9, \"SF\" },\n  { 10, \"HF\" },\n  { 23, \"BE8\" }\n};\n\n\nstatic const CUInt32PCharPair g_MIPS_Flags[] =\n{\n  { 0, \"NOREORDER\" },\n  { 1, \"PIC\" },\n  { 2, \"CPIC\" },\n  { 3, \"XGOT\" },\n  { 4, \"64BIT_WHIRL\" },\n  { 5, \"ABI2\" },\n  { 6, \"ABI_ON32\" },\n  { 10, \"NAN2008\" },\n  { 25, \"MicroMIPS\" },\n  { 26, \"M16\" },\n  { 27, \"MDMX\" }\n};\n\nstatic const char * const g_RISCV_Flags[] =\n{\n  \"RVC\",\n  NULL,\n  NULL,\n  \"RVE\",\n  \"TSO\"\n};\n\n\n// #define ET_NONE 0\n#define ET_REL  1\n// #define ET_EXEC 2\n#define ET_DYN  3\n// #define ET_CORE 4\n\nstatic const char * const g_Types[] =\n{\n    \"None\"\n  , \"Relocatable file\"\n  , \"Executable file\"\n  , \"Shared object file\"\n  , \"Core file\"\n};\n\n\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n    IArchiveAllowTail\n)\n  CRecordVector<CSegment> _segments;\n  CRecordVector<CSection> _sections;\n  CByteBuffer _namesData;\n  CMyComPtr<IInStream> _inStream;\n  UInt64 _totalSize;\n  CHeader _header;\n  bool _headersError;\n  bool _allowTail;\n  bool _stackFlags_Defined;\n  UInt32 _stackFlags;\n\n  void GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const;\n  HRESULT Open2(IInStream *stream);\npublic:\n  CHandler(): _allowTail(false) {}\n};\n\nvoid CHandler::GetSectionName(UInt32 index, NCOM::CPropVariant &prop, bool showNULL) const\n{\n  if (index >= _sections.Size())\n    prop = index; // it's possible for some file, but maybe it's ERROR case\n  else\n  {\n    const CSection &section = _sections[index];\n    const UInt32 offset = section.Name;\n    if (index == SHN_UNDEF /* && section.Type == SHT_NULL && offset == 0 */)\n    {\n      if (showNULL)\n        prop = \"NULL\";\n      return;\n    }\n    const Byte *p = _namesData;\n    const size_t size = _namesData.Size();\n    for (size_t i = offset; i < size; i++)\n      if (p[i] == 0)\n      {\n        prop = (const char *)(p + offset);\n        return;\n      }\n    prop = \"ERROR\";\n  }\n}\n\nstatic const Byte kArcProps[] =\n{\n  kpidCpu,\n  kpidBit64,\n  kpidBigEndian,\n  kpidHostOS,\n  kpidCharacts,\n  kpidComment,\n  kpidHeadersSize\n};\n\nenum\n{\n  kpidLinkSection = kpidUserDefined,\n  kpidInfoSection,\n  kpidEntrySize\n#ifdef Z7_ELF_SHOW_DETAILS\n  // , kpidAlign\n  , kpidPa\n  , kpidDelta\n  , kpidOffsetEnd\n#endif\n};\n\nstatic const CStatProp kProps[] =\n{\n  { NULL, kpidPath, VT_BSTR },\n  { NULL, kpidSize, VT_UI8 },\n  { NULL, kpidVirtualSize, VT_UI8 },\n  { NULL, kpidOffset, VT_UI8 },\n  { NULL, kpidVa, VT_UI8 },\n  { NULL, kpidType, VT_BSTR },\n  { NULL, kpidCharacts, VT_BSTR }\n#ifdef Z7_ELF_SHOW_DETAILS\n  // , { \"Align\", kpidAlign, VT_UI8 }\n  , { NULL, kpidClusterSize, VT_UI8 }\n  , { \"PA\", kpidPa, VT_UI8 }\n  , { \"End offset\", kpidOffsetEnd, VT_UI8 }\n  , { \"Delta (VA-Offset)\", kpidDelta, VT_UI8 }\n#endif\n  , { \"Entry Size\", kpidEntrySize, VT_UI8}\n  , { \"Link Section\", kpidLinkSection, VT_BSTR}\n  , { \"Info Section\", kpidInfoSection, VT_BSTR}\n};\n\nIMP_IInArchive_Props_WITH_NAME\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _totalSize; break;\n    case kpidHeadersSize: prop = _header.GetHeadersSize(); break;\n    case kpidBit64: if (_header.Mode64) prop = _header.Mode64; break;\n    case kpidBigEndian: if (_header.Be) prop = _header.Be; break;\n    case kpidShortComment:\n\n    case kpidCpu:\n    {\n      AString s;\n      if (_header.Machine < Z7_ARRAY_SIZE(g_Machines))\n      {\n        const char *name = g_Machines[_header.Machine];\n        if (name)\n          s = name;\n      }\n      if (s.IsEmpty())\n        s = TypePairToString(g_MachinePairs, Z7_ARRAY_SIZE(g_MachinePairs), _header.Machine);\n      UInt32 flags = _header.Flags;\n      if (flags)\n      {\n        s.Add_Space();\n        if (_header.Machine == k_Machine_ARM)\n        {\n          s += FlagsToString(g_ARM_Flags, Z7_ARRAY_SIZE(g_ARM_Flags), flags & (((UInt32)1 << 24) - 1));\n          s += \" ABI:\";\n          s.Add_UInt32(flags >> 24);\n        }\n        else if (_header.Machine == k_Machine_MIPS)\n        {\n          const UInt32 ver = flags >> 28;\n          s.Add_Char('v');\n          s.Add_UInt32(ver);\n          flags &= ((UInt32)1 << 28) - 1;\n          const UInt32 abi = (flags >> 12) & 7;\n          if (abi)\n          {\n            s += \" ABI:\";\n            s.Add_UInt32(abi);\n          }\n          flags &= ~((UInt32)7 << 12);\n          s.Add_Space();\n          s += FlagsToString(g_MIPS_Flags, Z7_ARRAY_SIZE(g_MIPS_Flags), flags);\n        }\n        else if (_header.Machine == k_Machine_RISCV)\n        {\n          s += \"FLOAT_\";\n          const UInt32 fl = (flags >> 1) & 3;\n          /*\n          static const char * const g_RISCV_Flags_Float[] =\n            { \"SOFT\", \"SINGLE\", \"DOUBLE\", \"QUAD\" };\n          s += g_RISCV_Flags_Float[fl];\n          */\n          if (fl)\n            s.Add_UInt32(16u << fl);\n          else\n            s += \"SOFT\";\n          s.Add_Space();\n          flags &= ~(UInt32)6;\n          s += FlagsToString(g_RISCV_Flags, Z7_ARRAY_SIZE(g_RISCV_Flags), flags);\n        }\n#if 0\n#define k_Machine_LOONGARCH 258\n        else if (_header.Machine == k_Machine_LOONGARCH)\n        {\n          s += \"ABI:\";\n          s.Add_UInt32((flags >> 6) & 3);\n          s.Add_Dot();\n          s.Add_UInt32((flags >> 3) & 7);\n          s.Add_Dot();\n#if 1\n          s.Add_UInt32(flags & 7);\n#else\n          static const char k_LoongArch_Float_Type[8] = { '0', 's', 'f', 'd', '4' ,'5', '6', '7' };\n          s.Add_Char(k_LoongArch_Float_Type[flags & 7]);\n#endif\n          flags &= ~(UInt32)0xff;\n          if (flags)\n          {\n            s.Add_Colon();\n            char sz[16];\n            ConvertUInt32ToHex(flags, sz);\n            s += sz;\n          }\n        }\n#endif\n        else\n        {\n          char sz[16];\n          ConvertUInt32ToHex(flags, sz);\n          s += sz;\n        }\n      }\n      prop = s;\n      break;\n    }\n\n    case kpidHostOS: PAIR_TO_PROP(g_OS, _header.Os, prop); break;\n    case kpidCharacts: TYPE_TO_PROP(g_Types, _header.Type, prop); break;\n    case kpidComment:\n    {\n      AString s;\n      if (_stackFlags_Defined)\n      {\n        s += \"STACK: \";\n        s += FlagsToString(g_SegmentFlags, Z7_ARRAY_SIZE(g_SegmentFlags), _stackFlags);\n        s.Add_LF();\n        /*\n        if (_header.EntryVa)\n        {\n          s += \"Entry point: 0x\";\n          char temp[16 + 4];\n          ConvertUInt64ToHex(_header.EntryVa, temp);\n          s += temp;\n          s.Add_LF();\n        }\n        */\n      }\n      if (_header.NumSegments)\n      {\n        s += \"Segments: \";\n        s.Add_UInt32(_header.NumSegments);\n        s.Add_LF();\n      }\n      if (_header.NumSections)\n      {\n        s += \"Sections: \";\n        s.Add_UInt32(_header.NumSections);\n        s.Add_LF();\n      }\n      prop = s;\n      break;\n    }\n    case kpidExtension:\n    {\n      const char *s = NULL;\n      if (_header.Type == ET_DYN)\n        s = \"so\";\n      else if (_header.Type == ET_REL)\n        s = \"o\";\n      if (s)\n        prop = s;\n      break;\n    }\n    // case kpidIsSelfExe: prop = (_header.Type != ET_DYN)  && (_header.Type == ET_REL); break;\n    case kpidErrorFlags:\n    {\n      UInt32 flags = 0;\n      if (_headersError) flags |= kpv_ErrorFlags_HeadersError;\n      if (flags != 0)\n        prop = flags;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  if (index < _segments.Size())\n  {\n    const CSegment &item = _segments[index];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        char sz[16];\n        ConvertUInt32ToString(index, sz);\n        prop = sz;\n        break;\n      }\n      case kpidOffset: prop = item.Offset; break;\n      case kpidVa: prop = item.Va; break;\n#ifdef Z7_ELF_SHOW_DETAILS\n      case kpidDelta: if (item.Va) { prop = item.Va - item.Offset; } break;\n      case kpidOffsetEnd: prop = item.Offset + item.Size; break;\n      case kpidPa: prop = item.Pa; break;\n      case kpidClusterSize: prop = item.Align; break;\n#endif\n      case kpidSize:\n      case kpidPackSize: prop = (UInt64)item.Size; break;\n      case kpidVirtualSize: prop = (UInt64)item.VSize; break;\n      case kpidType: PAIR_TO_PROP(g_SegnmentTypes, item.Type, prop); break;\n      case kpidCharacts: FLAGS_TO_PROP(g_SegmentFlags, item.Flags, prop); break;\n    }\n  }\n  else\n  {\n    index -= _segments.Size();\n    const CSection &item = _sections[index];\n    switch (propID)\n    {\n      case kpidPath: GetSectionName(index, prop, true); break;\n      case kpidOffset: prop = item.Offset; break;\n      case kpidVa: prop = item.Va; break;\n#ifdef Z7_ELF_SHOW_DETAILS\n      case kpidDelta: if (item.Va) { prop = item.Va - item.Offset; } break;\n      case kpidOffsetEnd: prop = item.Offset + item.GetSize(); break;\n#endif\n      case kpidSize:\n      case kpidPackSize: prop = (UInt64)(item.Type == SHT_NOBITS ? 0 : item.VSize); break;\n      case kpidVirtualSize: prop = item.GetSize(); break;\n      case kpidType: PAIR_TO_PROP(g_SectTypes, item.Type, prop); break;\n      case kpidCharacts: FLAGS_TO_PROP(g_SectionFlags, (UInt32)item.Flags, prop); break;\n      // case kpidAlign: prop = item.Align; break;\n      case kpidLinkSection: GetSectionName(item.Link, prop, false); break;\n      case kpidInfoSection: GetSectionName(item.Info, prop, false); break;\n      case kpidEntrySize: prop = (UInt64)item.EntSize; break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  {\n    const UInt32 kStartSize = kHeaderSize64;\n    UInt64 h64[kStartSize / 8];\n    RINOK(ReadStream_FALSE(stream, h64, kStartSize))\n    const Byte *h = (const Byte *)(const void *)h64;\n    if (GetUi32a(h) != 0x464c457f)\n      return S_FALSE;\n    if (!_header.Parse(h))\n      return S_FALSE;\n  }\n\n  _totalSize = _header.HeaderSize;\n\n  bool addSegments = false;\n  bool addSections = false;\n  // first section usually is NULL (with zero offsets and zero sizes).\n  if (_header.NumSegments == 0 || _header.NumSections > 1)\n    addSections = true;\n  else\n    addSegments = true;\n#ifdef Z7_ELF_SHOW_DETAILS\n  addSections = true;\n  addSegments = true;\n#endif\n\n  if (_header.NumSegments)\n  {\n    if (_header.ProgOffset > (UInt64)1 << 60) return S_FALSE;\n    RINOK(InStream_SeekSet(stream, _header.ProgOffset))\n    const size_t size = (size_t)_header.SegmentEntrySize * _header.NumSegments;\n    CByteArr buf(size);\n    RINOK(ReadStream_FALSE(stream, buf, size))\n    {\n      const UInt64 total = _header.ProgOffset + size;\n      if (_totalSize < total)\n          _totalSize = total;\n    }\n    if (addSegments)\n      _segments.ClearAndReserve(_header.NumSegments);\n    const Byte *p = buf;\n    for (unsigned i = 0; i < _header.NumSegments; i++, p += _header.SegmentEntrySize)\n    {\n      CSegment seg;\n      seg.Parse(p, _header.Mode64, _header.Be);\n      seg.UpdateTotalSize(_totalSize);\n      if (seg.Type == PT_GNU_STACK && !_stackFlags_Defined)\n      {\n        _stackFlags = seg.Flags;\n        _stackFlags_Defined = true;\n      }\n      if (addSegments\n          // we don't show program header table segment\n          && seg.Type != PT_PHDR\n          )\n        _segments.AddInReserved(seg);\n    }\n  }\n\n  if (_header.NumSections)\n  {\n    if (_header.SectOffset > (UInt64)1 << 60) return S_FALSE;\n    RINOK(InStream_SeekSet(stream, _header.SectOffset))\n    const size_t size = (size_t)_header.SectionEntrySize * _header.NumSections;\n    CByteArr buf(size);\n    RINOK(ReadStream_FALSE(stream, buf, size))\n    {\n      const UInt64 total = _header.SectOffset + size;\n      if (_totalSize < total)\n          _totalSize = total;\n    }\n    if (addSections)\n      _sections.ClearAndReserve(_header.NumSections);\n    const Byte *p = buf;\n    for (unsigned i = 0; i < _header.NumSections; i++, p += _header.SectionEntrySize)\n    {\n      CSection sect;\n      if (!sect.Parse(p, _header.Mode64, _header.Be))\n      {\n        _headersError = true;\n        return S_FALSE;\n      }\n      sect.UpdateTotalSize(_totalSize);\n      if (addSections)\n        _sections.AddInReserved(sect);\n    }\n  }\n\n  if (addSections)\n  {\n    if (_header.NamesSectIndex < _sections.Size())\n    {\n      const CSection &sect = _sections[_header.NamesSectIndex];\n      const UInt64 size = sect.GetSize();\n      if (size && size < ((UInt64)1 << 31)\n          && (Int64)sect.Offset >= 0)\n      {\n        _namesData.Alloc((size_t)size);\n        RINOK(InStream_SeekSet(stream, sect.Offset))\n        RINOK(ReadStream_FALSE(stream, _namesData, (size_t)size))\n      }\n    }\n    /*\n    // we cannot delete \"NULL\" sections,\n    // because we have links to sections array via indexes\n    for (int i = _sections.Size() - 1; i >= 0; i--)\n      if (_sections[i].Type == SHT_NULL)\n        _items.Delete(i);\n    */\n  }\n\n  if (!_allowTail)\n  {\n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))\n    if (fileSize > _totalSize)\n      return S_FALSE;\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(inStream))\n  _inStream = inStream;\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalSize = 0;\n  _headersError = false;\n  _stackFlags_Defined = false;\n\n  _inStream.Release();\n  _segments.Clear();\n  _sections.Clear();\n  _namesData.Free();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _segments.Size() + _sections.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _segments.Size() + _sections.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n    totalSize += (index < _segments.Size()) ?\n        _segments[index].Size :\n        _sections[index - _segments.Size()].GetSize();\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  totalSize = 0;\n  UInt64 currentItemSize;\n  \n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_inStream);\n\n  for (i = 0;; i++, totalSize += currentItemSize)\n  {\n    lps->InSize = lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    UInt64 offset;\n    if (index < _segments.Size())\n    {\n      const CSegment &item = _segments[index];\n      currentItemSize = item.Size;\n      offset = item.Offset;\n    }\n    else\n    {\n      const CSection &item = _sections[index - _segments.Size()];\n      currentItemSize = item.GetSize();\n      offset = item.Offset;\n    }\n    {\n      CMyComPtr<ISequentialOutStream> outStream;\n      RINOK(extractCallback->GetStream(index, &outStream, askMode))\n      if (!testMode && !outStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(InStream_SeekSet(_inStream, offset))\n      inStream->Init(currentItemSize);\n      RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))\n    }\n    RINOK(extractCallback->SetOperationResult(copyCoder->TotalSize == currentItemSize ?\n        NExtract::NOperationResult::kOK:\n        NExtract::NOperationResult::kDataError))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail))\n{\n  _allowTail = IntToBool(allowTail);\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = { 0x7F, 'E', 'L', 'F' };\n\nREGISTER_ARC_I(\n  \"ELF\", \"elf\", NULL, 0xDE,\n  k_Signature,\n  0,\n  NArcInfoFlags::kPreArc,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ExtHandler.cpp",
    "content": "﻿// ExtHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n// #include <stdio.h>\n// #define PRF2(x) x\n\n#define PRF2(x)\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyLinux.h\"\n#include \"../../Common/StringConvert.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\nusing namespace NWindows;\n\nUInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size);\n\nnamespace NArchive {\nnamespace NExt {\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define LE_16(offs, dest) dest = Get16(p + (offs));\n#define LE_32(offs, dest) dest = Get32(p + (offs));\n#define LE_64(offs, dest) dest = Get64(p + (offs));\n\n#define HI_16(offs, dest) dest |= (((UInt32)Get16(p + (offs))) << 16);\n#define HI_32(offs, dest) dest |= (((UInt64)Get32(p + (offs))) << 32);\n\n/*\nstatic UInt32 g_Crc32CTable[256];\n\nstatic struct CInitCrc32C\n{\n  CInitCrc32C()\n  {\n    for (unsigned i = 0; i < 256; i++)\n    {\n      UInt32 r = i;\n      unsigned j;\n      for (j = 0; j < 8; j++)\n        r = (r >> 1) ^ (0x82F63B78 & ~((r & 1) - 1));\n      g_Crc32CTable[i] = r;\n    }\n  }\n} g_InitCrc32C;\n\n#define CRC32C_INIT_VAL 0xFFFFFFFF\n#define CRC32C_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)\n#define CRC32C_UPDATE_BYTE(crc, b) (g_Crc32CTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n\nstatic UInt32 Crc32C_Update(UInt32 crc, Byte const *data, size_t size)\n{\n  for (size_t i = 0; i < size; i++)\n    crc = CRC32C_UPDATE_BYTE(crc, data[i]);\n  return crc;\n}\n\nstatic UInt32 Crc32C_Calc(Byte const *data, size_t size)\n{\n  return Crc32C_Update(CRC32C_INIT_VAL, data, size);\n}\n*/\n\n\n#define CRC16_INIT_VAL 0xFFFF\n\n#define Crc16Update(crc, data, size)  LzhCrc16Update(crc, data, size)\n\nstatic UInt32 Crc16Calc(Byte const *data, size_t size)\n{\n  return Crc16Update(CRC16_INIT_VAL, data, size);\n}\n\n\n#define EXT4_GOOD_OLD_INODE_SIZE 128\n#define EXT_NODE_SIZE_MIN 128\n\n\n// inodes numbers\n \n// #define k_INODE_BAD          1  // Bad blocks\n#define k_INODE_ROOT         2  // Root dir\n// #define k_INODE_USR_QUOTA    3  // User quota\n// #define k_INODE_GRP_QUOTA    4  // Group quota\n// #define k_INODE_BOOT_LOADER  5  // Boot loader\n// #define k_INODE_UNDEL_DIR    6  // Undelete dir\n#define k_INODE_RESIZE       7  // Reserved group descriptors\n// #define k_INODE_JOURNAL      8  // Journal\n\n// First non-reserved inode for old ext4 filesystems\n#define k_INODE_GOOD_OLD_FIRST  11\n\nstatic const char * const k_SysInode_Names[] =\n{\n    \"0\"\n  , \"Bad\"\n  , \"Root\"\n  , \"UserQuota\"\n  , \"GroupQuota\"\n  , \"BootLoader\"\n  , \"Undelete\"\n  , \"Resize\"\n  , \"Journal\"\n  , \"Exclude\"\n  , \"Replica\"\n};\n\nstatic const char * const kHostOS[] =\n{\n    \"Linux\"\n  , \"Hurd\"\n  , \"Masix\"\n  , \"FreeBSD\"\n  , \"Lites\"\n};\n\nstatic const char * const g_FeatureCompat_Flags[] =\n{\n    \"DIR_PREALLOC\"\n  , \"IMAGIC_INODES\"\n  , \"HAS_JOURNAL\"\n  , \"EXT_ATTR\"\n  , \"RESIZE_INODE\"\n  , \"DIR_INDEX\"\n  , \"LAZY_BG\" // not in Linux\n  , NULL // { 7, \"EXCLUDE_INODE\" // not used\n  , NULL // { 8, \"EXCLUDE_BITMAP\" // not in kernel\n  , \"SPARSE_SUPER2\"\n};\n  \n\n#define EXT4_FEATURE_INCOMPAT_FILETYPE (1 << 1)\n#define EXT4_FEATURE_INCOMPAT_64BIT (1 << 7)\n\nstatic const char * const g_FeatureIncompat_Flags[] =\n{\n    \"COMPRESSION\"\n  , \"FILETYPE\"\n  , \"RECOVER\" /* Needs recovery */\n  , \"JOURNAL_DEV\" /* Journal device */\n  , \"META_BG\"\n  , NULL\n  , \"EXTENTS\" /* extents support */\n  , \"64BIT\"\n  , \"MMP\"\n  , \"FLEX_BG\"\n  , \"EA_INODE\" /* EA in inode */\n  , NULL\n  , \"DIRDATA\" /* data in dirent */\n  , \"BG_USE_META_CSUM\" /* use crc32c for bg */\n  , \"LARGEDIR\" /* >2GB or 3-lvl htree */\n  , \"INLINE_DATA\" /* data in inode */\n  , \"ENCRYPT\" // 16\n};\n\n\nstatic const UInt32 RO_COMPAT_GDT_CSUM = 1 << 4;\nstatic const UInt32 RO_COMPAT_METADATA_CSUM = 1 << 10;\n\nstatic const char * const g_FeatureRoCompat_Flags[] =\n{\n    \"SPARSE_SUPER\"\n  , \"LARGE_FILE\"\n  , \"BTREE_DIR\"\n  , \"HUGE_FILE\"\n  , \"GDT_CSUM\"\n  , \"DIR_NLINK\"\n  , \"EXTRA_ISIZE\"\n  , \"HAS_SNAPSHOT\"\n  , \"QUOTA\"\n  , \"BIGALLOC\"\n  , \"METADATA_CSUM\"\n  , \"REPLICA\"\n  , \"READONLY\" // 12\n};\n\n\n\nstatic const UInt32 k_NodeFlags_HUGE = (UInt32)1 << 18;\nstatic const UInt32 k_NodeFlags_EXTENTS = (UInt32)1 << 19;\n\n\nstatic const char * const g_NodeFlags[] =\n{\n    \"SECRM\"\n  , \"UNRM\"\n  , \"COMPR\"\n  , \"SYNC\"\n  , \"IMMUTABLE\"\n  , \"APPEND\"\n  , \"NODUMP\"\n  , \"NOATIME\"\n  , \"DIRTY\"\n  , \"COMPRBLK\"\n  , \"NOCOMPR\"\n  , \"ENCRYPT\"\n  , \"INDEX\"\n  , \"IMAGIC\"\n  , \"JOURNAL_DATA\"\n  , \"NOTAIL\"\n  , \"DIRSYNC\"\n  , \"TOPDIR\"\n  , \"HUGE_FILE\"\n  , \"EXTENTS\"\n  , NULL\n  , \"EA_INODE\"\n  , \"EOFBLOCKS\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"INLINE_DATA\" // 28\n};\n\n\nenum\n{\n  k_Type_UNKNOWN,\n  k_Type_REG_FILE,\n  k_Type_DIR,\n  k_Type_CHRDEV,\n  k_Type_BLKDEV,\n  k_Type_FIFO,\n  k_Type_SOCK,\n  k_Type_SYMLINK\n};\n\nstatic const UInt16 k_TypeToMode[] =\n{\n  0,\n  MY_LIN_S_IFREG,\n  MY_LIN_S_IFDIR,\n  MY_LIN_S_IFCHR,\n  MY_LIN_S_IFBLK,\n  MY_LIN_S_IFIFO,\n  MY_LIN_S_IFSOCK,\n  MY_LIN_S_IFLNK\n};\n\n\n#define EXT4_GOOD_OLD_REV 0  // old (original) format\n// #define EXT4_DYNAMIC_REV 1  // V2 format with dynamic inode sizes\n \nstruct CHeader\n{\n  unsigned BlockBits;\n  unsigned ClusterBits;\n\n  UInt32 NumInodes;\n  UInt64 NumBlocks;\n  // UInt64 NumBlocksSuper;\n  UInt64 NumFreeBlocks;\n  UInt32 NumFreeInodes;\n  // UInt32 FirstDataBlock;\n\n  UInt32 BlocksPerGroup;\n  UInt32 ClustersPerGroup;\n  UInt32 InodesPerGroup;\n\n  UInt32 MountTime;\n  UInt32 WriteTime;\n\n  // UInt16 NumMounts;\n  // UInt16 NumMountsMax;\n  \n  // UInt16 State;\n  // UInt16 Errors;\n  // UInt16 MinorRevLevel;\n\n  UInt32 LastCheckTime;\n  // UInt32 CheckInterval;\n  UInt32 CreatorOs;\n  UInt32 RevLevel;\n\n  // UInt16 DefResUid;\n  // UInt16 DefResGid;\n\n  UInt32 FirstInode;\n  UInt16 InodeSize;\n  UInt16 BlockGroupNr;\n  UInt32 FeatureCompat;\n  UInt32 FeatureIncompat;\n  UInt32 FeatureRoCompat;\n  Byte Uuid[16];\n  char VolName[16];\n  char LastMount[64];\n  // UInt32 BitmapAlgo;\n\n  UInt32 JournalInode;\n  UInt16 GdSize; // = 64 if 64-bit();\n  UInt32 CTime;\n  UInt16 MinExtraISize;\n  // UInt16 WantExtraISize;\n  // UInt32 Flags;\n  // Byte LogGroupsPerFlex;\n  // Byte ChecksumType;\n\n  UInt64 WrittenKB;\n\n  bool IsOldRev() const { return RevLevel == EXT4_GOOD_OLD_REV; }\n\n  UInt64 GetNumGroups() const { return (NumBlocks + BlocksPerGroup - 1) / BlocksPerGroup; }\n  UInt64 GetNumGroups2() const { return ((UInt64)NumInodes + InodesPerGroup - 1) / InodesPerGroup; }\n\n  bool IsThereFileType() const { return (FeatureIncompat & EXT4_FEATURE_INCOMPAT_FILETYPE) != 0; }\n  bool Is64Bit() const { return (FeatureIncompat & EXT4_FEATURE_INCOMPAT_64BIT) != 0; }\n  bool UseGdtChecksum() const { return (FeatureRoCompat & RO_COMPAT_GDT_CSUM) != 0; }\n  bool UseMetadataChecksum() const { return (FeatureRoCompat & RO_COMPAT_METADATA_CSUM) != 0; }\n\n  UInt64 GetPhySize() const { return NumBlocks << BlockBits; }\n\n  bool Parse(const Byte *p);\n};\n\n\nstatic int inline GetLog(UInt32 num)\n{\n  for (unsigned i = 0; i < 32; i++)\n    if (((UInt32)1 << i) == num)\n      return (int)i;\n  return -1;\n}\n\nstatic bool inline IsEmptyData(const Byte *data, unsigned size)\n{\n  for (unsigned i = 0; i < size; i++)\n    if (data[i] != 0)\n      return false;\n  return true;\n}\n\n\nbool CHeader::Parse(const Byte *p)\n{\n  if (GetUi16(p + 0x38) != 0xEF53)\n    return false;\n  \n  LE_32 (0x18, BlockBits)\n  LE_32 (0x1C, ClusterBits)\n  \n  if (ClusterBits != 0 && BlockBits != ClusterBits)\n    return false;\n\n  if (BlockBits > 16 - 10)\n    return false;\n  BlockBits += 10;\n  \n  LE_32 (0x00, NumInodes)\n  LE_32 (0x04, NumBlocks)\n  // LE_32 (0x08, NumBlocksSuper);\n  LE_32 (0x0C, NumFreeBlocks)\n  LE_32 (0x10, NumFreeInodes)\n\n  if (NumInodes < 2 || NumInodes <= NumFreeInodes)\n    return false;\n\n  UInt32 FirstDataBlock;\n  LE_32 (0x14, FirstDataBlock)\n  if (FirstDataBlock != (unsigned)(BlockBits == 10 ? 1 : 0))\n    return false;\n    \n  LE_32 (0x20, BlocksPerGroup)\n  LE_32 (0x24, ClustersPerGroup)\n\n  if (BlocksPerGroup != ClustersPerGroup)\n    return false;\n  if (BlocksPerGroup == 0)\n    return false;\n  if (BlocksPerGroup != ((UInt32)1 << (BlockBits + 3)))\n  {\n    // it's allowed in ext2\n    // return false;\n  }\n\n  LE_32 (0x28, InodesPerGroup)\n\n  if (InodesPerGroup < 1 || InodesPerGroup > NumInodes)\n    return false;\n  \n  LE_32 (0x2C, MountTime)\n  LE_32 (0x30, WriteTime)\n  \n  // LE_16 (0x34, NumMounts);\n  // LE_16 (0x36, NumMountsMax);\n  \n  // LE_16 (0x3A, State);\n  // LE_16 (0x3C, Errors);\n  // LE_16 (0x3E, MinorRevLevel);\n  \n  LE_32 (0x40, LastCheckTime)\n  // LE_32 (0x44, CheckInterval);\n  LE_32 (0x48, CreatorOs)\n  LE_32 (0x4C, RevLevel)\n  \n  // LE_16 (0x50, DefResUid);\n  // LE_16 (0x52, DefResGid);\n  \n  FirstInode = k_INODE_GOOD_OLD_FIRST;\n  InodeSize = EXT4_GOOD_OLD_INODE_SIZE;\n\n  if (!IsOldRev())\n  {\n    LE_32 (0x54, FirstInode)\n    LE_16 (0x58, InodeSize)\n    if (FirstInode < k_INODE_GOOD_OLD_FIRST)\n      return false;\n    if (InodeSize > ((UInt32)1 << BlockBits)\n        || InodeSize < EXT_NODE_SIZE_MIN\n        || GetLog(InodeSize) < 0)\n      return false;\n  }\n\n  LE_16 (0x5A, BlockGroupNr)\n  LE_32 (0x5C, FeatureCompat)\n  LE_32 (0x60, FeatureIncompat)\n  LE_32 (0x64, FeatureRoCompat)\n  \n  memcpy(Uuid, p + 0x68, sizeof(Uuid));\n  memcpy(VolName, p + 0x78, sizeof(VolName));\n  memcpy(LastMount, p + 0x88, sizeof(LastMount));\n  \n  // LE_32 (0xC8, BitmapAlgo);\n  \n  LE_32 (0xE0, JournalInode)\n  \n  LE_16 (0xFE, GdSize)\n  \n  LE_32 (0x108, CTime)\n\n  if (Is64Bit())\n  {\n    HI_32(0x150, NumBlocks)\n    // HI_32(0x154, NumBlocksSuper);\n    HI_32(0x158, NumFreeBlocks)\n  }\n\n  if (NumBlocks >= (UInt64)1 << (63 - BlockBits))\n    return false;\n\n\n  LE_16(0x15C, MinExtraISize)\n  // LE_16(0x15E, WantExtraISize);\n  // LE_32(0x160, Flags);\n  // LE_16(0x164, RaidStride);\n  // LE_16(0x166, MmpInterval);\n  // LE_64(0x168, MmpBlock);\n  \n  // LogGroupsPerFlex = p[0x174];\n  // ChecksumType = p[0x175];\n\n  LE_64 (0x178, WrittenKB)\n\n  // LE_32(0x194, ErrorCount);\n  // LE_32(0x198, ErrorTime);\n  // LE_32(0x19C, ErrorINode);\n  // LE_32(0x1A0, ErrorBlock);\n  \n  if (NumBlocks < 1)\n    return false;\n  if (NumFreeBlocks > NumBlocks)\n    return false;\n\n  if (GetNumGroups() != GetNumGroups2())\n    return false;\n\n  return true;\n}\n\n\nstruct CGroupDescriptor\n{\n  UInt64 BlockBitmap;\n  UInt64 InodeBitmap;\n  UInt64 InodeTable;\n  UInt32 NumFreeBlocks;\n  UInt32 NumFreeInodes;\n  UInt32 DirCount;\n  \n  UInt16 Flags;\n  \n  UInt64 ExcludeBitmap;\n  UInt32 BlockBitmap_Checksum;\n  UInt32 InodeBitmap_Checksum;\n  UInt32 UnusedCount;\n  UInt16 Checksum;\n\n  void Parse(const Byte *p, unsigned size);\n};\n\nvoid CGroupDescriptor::Parse(const Byte *p, unsigned size)\n{\n  LE_32 (0x00, BlockBitmap)\n  LE_32 (0x04, InodeBitmap)\n  LE_32 (0x08, InodeTable)\n  LE_16 (0x0C, NumFreeBlocks)\n  LE_16 (0x0E, NumFreeInodes)\n  LE_16 (0x10, DirCount)\n  LE_16 (0x12, Flags)\n  LE_32 (0x14, ExcludeBitmap)\n  LE_16 (0x18, BlockBitmap_Checksum)\n  LE_16 (0x1A, InodeBitmap_Checksum)\n  LE_16 (0x1C, UnusedCount)\n  LE_16 (0x1E, Checksum)\n  \n  if (size >= 64)\n  {\n    p += 0x20;\n    HI_32 (0x00, BlockBitmap)\n    HI_32 (0x04, InodeBitmap)\n    HI_32 (0x08, InodeTable)\n    HI_16 (0x0C, NumFreeBlocks)\n    HI_16 (0x0E, NumFreeInodes)\n    HI_16 (0x10, DirCount)\n    HI_16 (0x12, UnusedCount) // instead of Flags\n    HI_32 (0x14, ExcludeBitmap)\n    HI_16 (0x18, BlockBitmap_Checksum)\n    HI_16 (0x1A, InodeBitmap_Checksum)\n    // HI_16 (0x1C, Reserved);\n  }\n}\n\n\nstatic const unsigned kNodeBlockFieldSize = 60;\n\nstruct CExtentTreeHeader\n{\n  UInt16 NumEntries;\n  UInt16 MaxEntries;\n  UInt16 Depth;\n  // UInt32 Generation;\n\n  bool Parse(const Byte *p)\n  {\n    LE_16 (0x02, NumEntries)\n    LE_16 (0x04, MaxEntries)\n    LE_16 (0x06, Depth)\n    // LE_32 (0x08, Generation);\n    return Get16(p) == 0xF30A; // magic\n  }\n};\n\nstruct CExtentIndexNode\n{\n  UInt32 VirtBlock;\n  UInt64 PhyLeaf;\n\n  void Parse(const Byte *p)\n  {\n    LE_32 (0x00, VirtBlock)\n    LE_32 (0x04, PhyLeaf)\n    PhyLeaf |= (((UInt64)Get16(p + 8)) << 32);\n    // unused 16-bit field (at offset 0x0A) can be not zero in some cases. Why?\n  }\n};\n\nstruct CExtent\n{\n  UInt32 VirtBlock;\n  UInt16 Len;\n  bool IsInited;\n  UInt64 PhyStart;\n\n  UInt32 GetVirtEnd() const { return VirtBlock + Len; }\n  bool IsLenOK() const { return VirtBlock + Len >= VirtBlock; }\n\n  void Parse(const Byte *p)\n  {\n    LE_32 (0x00, VirtBlock)\n    LE_16 (0x04, Len)\n    IsInited = true;\n    if (Len > (UInt32)0x8000)\n    {\n      IsInited = false;\n      Len = (UInt16)(Len - (UInt32)0x8000);\n    }\n    LE_32 (0x08, PhyStart)\n    UInt16 hi;\n    LE_16 (0x06, hi)\n    PhyStart |= ((UInt64)hi << 32);\n  }\n};\n\n\n\nstruct CExtTime\n{\n  UInt32 Val;\n  UInt32 Extra;\n};\n\nstruct CNode\n{\n  Int32 ParentNode;   // in _refs[], -1 if not dir\n  int ItemIndex;      // in _items[]   , (set as >=0 only for if (IsDir())\n  int SymLinkIndex;   // in _symLinks[]\n  int DirIndex;       // in _dirs[]\n\n  UInt16 Mode;\n  UInt32 Uid; // fixed 21.02\n  UInt32 Gid; // fixed 21.02\n  // UInt16 Checksum;\n  \n  UInt64 FileSize;\n  CExtTime MTime;\n  CExtTime ATime;\n  CExtTime CTime;\n  CExtTime ChangeTime;\n  // CExtTime DTime;\n\n  UInt64 NumBlocks;\n  UInt32 NumLinks;\n  UInt32 Flags;\n\n  UInt32 NumLinksCalced;\n\n  Byte Block[kNodeBlockFieldSize];\n  \n  CNode():\n      ParentNode(-1),\n      ItemIndex(-1),\n      SymLinkIndex(-1),\n      DirIndex(-1),\n      NumLinksCalced(0)\n        {}\n\n  bool IsFlags_HUGE()    const { return (Flags & k_NodeFlags_HUGE) != 0; }\n  bool IsFlags_EXTENTS() const { return (Flags & k_NodeFlags_EXTENTS) != 0; }\n\n  bool IsDir()     const { return MY_LIN_S_ISDIR(Mode); }\n  bool IsRegular() const { return MY_LIN_S_ISREG(Mode); }\n  bool IsLink()    const { return MY_LIN_S_ISLNK(Mode); }\n\n  bool Parse(const Byte *p, const CHeader &_h);\n};\n\n\nbool CNode::Parse(const Byte *p, const CHeader &_h)\n{\n  MTime.Extra = 0;\n  ATime.Extra = 0;\n  CTime.Extra = 0;\n  CTime.Val = 0;\n  ChangeTime.Extra = 0;\n  // DTime.Extra = 0;\n\n  LE_16 (0x00, Mode)\n  LE_16 (0x02, Uid)\n  LE_32 (0x04, FileSize)\n  LE_32 (0x08, ATime.Val)\n  LE_32 (0x0C, ChangeTime.Val)\n  LE_32 (0x10, MTime.Val)\n  // LE_32 (0x14, DTime.Val);\n  LE_16 (0x18, Gid)\n  LE_16 (0x1A, NumLinks)\n\n  LE_32 (0x1C, NumBlocks)\n  LE_32 (0x20, Flags)\n  // LE_32 (0x24, Union osd1);\n  \n  memcpy(Block, p + 0x28, kNodeBlockFieldSize);\n  \n  // LE_32 (0x64, Generation);  // File version (for NFS)\n  // LE_32 (0x68, ACL);\n  \n  {\n    UInt32 highSize;\n    LE_32 (0x6C, highSize) // In ext2/3 this field was named i_dir_acl\n   \n    if (IsRegular()) // do we need that check ?\n      FileSize |= ((UInt64)highSize << 32);\n  }\n\n  // UInt32 fragmentAddress;\n  // LE_32 (0x70, fragmentAddress);\n  \n  // osd2\n  {\n    // Linux;\n    // ext2:\n    // Byte FragmentNumber = p[0x74];\n    // Byte FragmentSize = p[0x74 + 1];\n    \n    // ext4:\n    UInt32 numBlocksHigh;\n    LE_16 (0x74, numBlocksHigh)\n    NumBlocks |= (UInt64)numBlocksHigh << 32;\n    \n    HI_16 (0x74 + 4, Uid)\n    HI_16 (0x74 + 6, Gid)\n    /*\n    UInt32 checksum;\n    LE_16 (0x74 + 8, checksum);\n    checksum = checksum;\n    */\n  }\n\n  // 0x74: Byte Union osd2[12];\n\n  if (_h.InodeSize > 128)\n  {\n    // InodeSize is power of 2, so the following check is not required:\n    // if (_h.InodeSize < 128 + 2) return false;\n    UInt16 extra_isize;\n    LE_16 (0x80, extra_isize)\n    if (128 + extra_isize > _h.InodeSize)\n      return false;\n    if (extra_isize >= 0x1C)\n    {\n      // UInt16 checksumUpper;\n      // LE_16 (0x82, checksumUpper);\n      LE_32 (0x84, ChangeTime.Extra)\n      LE_32 (0x88, MTime.Extra)\n      LE_32 (0x8C, ATime.Extra)\n      LE_32 (0x90, CTime.Val)\n      LE_32 (0x94, CTime.Extra)\n      // LE_32 (0x98, VersionHi)\n    }\n  }\n\n  PRF(printf(\"size = %5d\", (unsigned)FileSize));\n\n  return true;\n}\n\n\nstruct CItem\n{\n  unsigned Node;        // in _refs[]\n  int ParentNode;       // in _refs[]\n  int SymLinkItemIndex; // in _items[], if the Node contains SymLink to existing dir\n  Byte Type;\n  \n  AString Name;\n\n  CItem():\n      Node(0),\n      ParentNode(-1),\n      SymLinkItemIndex(-1),\n      Type(k_Type_UNKNOWN)\n        {}\n  \n  void Clear()\n  {\n    Node = 0;\n    ParentNode = -1;\n    SymLinkItemIndex = -1;\n    Type = k_Type_UNKNOWN;\n    Name.Empty();\n  }\n\n  bool IsDir() const { return Type == k_Type_DIR; }\n  // bool IsNotDir() const { return Type != k_Type_DIR && Type != k_Type_UNKNOWN; }\n};\n\n\n\nstatic const unsigned kNumTreeLevelsMax = 6; // must be >= 3\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_2(\n  IArchiveGetRawProps,\n  IInArchiveGetStream\n)\n  CObjectVector<CItem> _items;\n  CIntVector _refs;                 // iNode -> (index in _nodes). if (_refs[iNode] < 0), that node is not filled\n  CRecordVector<CNode> _nodes;\n  CObjectVector<CUIntVector> _dirs; // each CUIntVector contains indexes in _items[] only for dir items;\n  AStringVector _symLinks;\n  AStringVector _auxItems;\n  int _auxSysIndex;\n  int _auxUnknownIndex;\n\n  CMyComPtr<IInStream> _stream;\n  UInt64 _phySize;\n  bool _isArc;\n  bool _headersError;\n  bool _headersWarning;\n  bool _linksError;\n  \n  bool _isUTF;\n  \n  CHeader _h;\n\n  IArchiveOpenCallback *_openCallback;\n  UInt64 _totalRead;\n  UInt64 _totalReadPrev;\n\n  CByteBuffer _tempBufs[kNumTreeLevelsMax];\n\n  \n  HRESULT CheckProgress2()\n  {\n    const UInt64 numFiles = _items.Size();\n    return _openCallback->SetCompleted(&numFiles, &_totalRead);\n  }\n\n  HRESULT CheckProgress()\n  {\n    HRESULT res = S_OK;\n    if (_openCallback)\n    {\n      if (_totalRead - _totalReadPrev >= ((UInt32)1 << 20))\n      {\n        _totalReadPrev = _totalRead;\n        res = CheckProgress2();\n      }\n    }\n    return res;\n  }\n\n  \n  int GetParentAux(const CItem &item) const\n  {\n    if (item.Node < _h.FirstInode && _auxSysIndex >= 0)\n      return _auxSysIndex;\n    return _auxUnknownIndex;\n  }\n\n  HRESULT SeekAndRead(IInStream *inStream, UInt64 block, Byte *data, size_t size);\n  HRESULT ParseDir(const Byte *data, size_t size, unsigned iNodeDir);\n  int FindTargetItem_for_SymLink(unsigned dirNode, const AString &path) const;\n\n  HRESULT FillFileBlocks2(UInt32 block, unsigned level, unsigned numBlocks, CRecordVector<UInt32> &blocks);\n  HRESULT FillFileBlocks(const Byte *p, unsigned numBlocks, CRecordVector<UInt32> &blocks);\n  HRESULT FillExtents(const Byte *p, size_t size, CRecordVector<CExtent> &extents, int parentDepth);\n\n  HRESULT GetStream_Node(unsigned nodeIndex, ISequentialInStream **stream);\n  HRESULT ExtractNode(unsigned nodeIndex, CByteBuffer &data);\n\n  void ClearRefs();\n  HRESULT Open2(IInStream *inStream);\n\n  void GetPath(unsigned index, AString &s) const;\n  bool GetPackSize(unsigned index, UInt64 &res) const;\n};\n\n\n\nHRESULT CHandler::ParseDir(const Byte *p, size_t size, unsigned iNodeDir)\n{\n  bool isThereSelfLink = false;\n\n  PRF(printf(\"\\n\\n========= node = %5d    size = %5d\", (unsigned)iNodeDir, (unsigned)size));\n\n  CNode &nodeDir = _nodes[_refs[iNodeDir]];\n  nodeDir.DirIndex = (int)_dirs.Size();\n  CUIntVector &dir = _dirs.AddNew();\n  int parentNode = -1;\n\n  CItem item;\n\n  for (;;)\n  {\n    if (size == 0)\n      break;\n    if (size < 8)\n      return S_FALSE;\n    UInt32 iNode;\n    LE_32 (0x00, iNode)\n    unsigned recLen;\n    LE_16 (0x04, recLen)\n    const unsigned nameLen = p[6];\n    const Byte type = p[7];\n\n    if (recLen > size)\n      return S_FALSE;\n    if (nameLen + 8 > recLen)\n      return S_FALSE;\n\n    if (iNode >= _refs.Size())\n      return S_FALSE;\n\n    item.Clear();\n\n    if (_h.IsThereFileType())\n      item.Type = type;\n    else if (type != 0)\n      return S_FALSE;\n\n    item.ParentNode = (int)iNodeDir;\n    item.Node = iNode;\n    item.Name.SetFrom_CalcLen((const char *)(p + 8), nameLen);\n  \n    p += recLen;\n    size -= recLen;\n   \n    if (item.Name.Len() != nameLen)\n      return S_FALSE;\n    \n    if (_isUTF)\n    {\n      // 21.07 : we force UTF8\n      // _isUTF = CheckUTF8_AString(item.Name);\n    }\n\n    if (iNode == 0)\n    {\n      /*\n      ext3 deleted??\n      if (item.Name.Len() != 0)\n        return S_FALSE;\n      */\n\n      PRF(printf(\"\\n EMPTY %6d %d %s\", (unsigned)recLen, (unsigned)type, (const char *)item.Name));\n      if (type == 0xDE)\n      {\n        // checksum\n      }\n      continue;\n    }\n\n    const int nodeIndex = _refs[iNode];\n    if (nodeIndex < 0)\n      return S_FALSE;\n    CNode &node = _nodes[nodeIndex];\n\n    if (_h.IsThereFileType() && type != 0)\n    {\n      if (type >= Z7_ARRAY_SIZE(k_TypeToMode))\n        return S_FALSE;\n      if (k_TypeToMode[type] != (node.Mode & MY_LIN_S_IFMT))\n        return S_FALSE;\n    }\n\n    node.NumLinksCalced++;\n    \n    PRF(printf(\"\\n%s %6d %s\", item.IsDir() ? \"DIR  \" : \"     \", (unsigned)item.Node, (const char *)item.Name));\n    \n    if (item.Name[0] == '.')\n    {\n      if (item.Name[1] == 0)\n      {\n        if (isThereSelfLink)\n          return S_FALSE;\n        isThereSelfLink = true;\n        if (iNode != iNodeDir)\n          return S_FALSE;\n        continue;\n      }\n      \n      if (item.Name[1] == '.' && item.Name[2] == 0)\n      {\n        if (parentNode >= 0)\n          return S_FALSE;\n        if (!node.IsDir())\n          return S_FALSE;\n        if (iNode == iNodeDir && iNode != k_INODE_ROOT)\n          return S_FALSE;\n        \n        parentNode = (int)iNode;\n\n        if (nodeDir.ParentNode < 0)\n          nodeDir.ParentNode = (int)iNode;\n        else if ((unsigned)nodeDir.ParentNode != iNode)\n          return S_FALSE;\n\n        continue;\n      }\n    }\n\n    if (iNode == iNodeDir)\n      return S_FALSE;\n\n    if (parentNode < 0)\n      return S_FALSE;\n\n    if (node.IsDir())\n    {\n      if (node.ParentNode < 0)\n        node.ParentNode = (int)iNodeDir;\n      else if ((unsigned)node.ParentNode != iNodeDir)\n        return S_FALSE;\n      const unsigned itemIndex = _items.Size();\n      dir.Add(itemIndex);\n      node.ItemIndex = (int)itemIndex;\n    }\n\n    _items.Add(item);\n  }\n\n  if (parentNode < 0 || !isThereSelfLink)\n    return S_FALSE;\n\n  return S_OK;\n}\n\n\nstatic int CompareItemsNames(const unsigned *p1, const unsigned *p2, void *param)\n{\n  const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;\n  return strcmp(items[*p1].Name, items[*p2].Name);\n}\n\n\nint CHandler::FindTargetItem_for_SymLink(unsigned iNode, const AString &path) const\n{\n  unsigned pos = 0;\n  \n  if (path.IsEmpty())\n    return -1;\n  \n  if (path[0] == '/')\n  {\n    iNode = k_INODE_ROOT;\n    if (iNode >= _refs.Size())\n      return -1;\n    pos = 1;\n  }\n\n  AString s;\n\n  while (pos != path.Len())\n  {\n    const CNode &node = _nodes[_refs[iNode]];\n    const int slash = path.Find('/', pos);\n    \n    if (slash < 0)\n    {\n      s = path.Ptr(pos);\n      pos = path.Len();\n    }\n    else\n    {\n      s.SetFrom(path.Ptr(pos), (unsigned)slash - pos);\n      pos = (unsigned)slash + 1;\n    }\n    \n    if (s[0] == '.')\n    {\n      if (s[1] == 0)\n        continue;\n      else if (s[1] == '.' && s[2] == 0)\n      {\n        if (node.ParentNode < 0)\n          return -1;\n        if (iNode == k_INODE_ROOT)\n          return -1;\n        iNode = (unsigned)node.ParentNode;\n        continue;\n      }\n    }\n    \n    if (node.DirIndex < 0)\n      return -1;\n\n    const CUIntVector &dir = _dirs[node.DirIndex];\n    \n    /*\n    for (unsigned i = 0;; i++)\n    {\n      if (i >= dir.Size())\n        return -1;\n      const CItem &item = _items[dir[i]];\n      if (item.Name == s)\n      {\n        iNode = item.Node;\n        break;\n      }\n    }\n    */\n\n    unsigned left = 0, right = dir.Size();\n    for (;;)\n    {\n      if (left == right)\n        return -1;\n      const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const CItem &item = _items[dir[mid]];\n      const int comp = strcmp(s, item.Name);\n      if (comp == 0)\n      {\n        iNode = item.Node;\n        break;\n      }\n      if (comp < 0)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n  }\n\n  return _nodes[_refs[iNode]].ItemIndex;\n}\n\n\nHRESULT CHandler::SeekAndRead(IInStream *inStream, UInt64 block, Byte *data, size_t size)\n{\n  if (block == 0 || block >= _h.NumBlocks)\n    return S_FALSE;\n  if (((size + ((size_t)1 << _h.BlockBits) - 1) >> _h.BlockBits) > _h.NumBlocks - block)\n    return S_FALSE;\n  RINOK(InStream_SeekSet(inStream, (UInt64)block << _h.BlockBits))\n  _totalRead += size;\n  return ReadStream_FALSE(inStream, data, size);\n}\n\n\nstatic const unsigned kHeaderSize = 2 * 1024;\nstatic const unsigned kHeaderDataOffset = 1024;\n\nHRESULT CHandler::Open2(IInStream *inStream)\n{\n  {\n    Byte buf[kHeaderSize];\n    RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize))\n    if (!_h.Parse(buf + kHeaderDataOffset))\n      return S_FALSE;\n    if (_h.BlockGroupNr != 0)\n      return S_FALSE; // it's just copy of super block\n  }\n  \n  {\n    // ---------- Read groups and nodes ----------\n    \n    unsigned numGroups;\n    {\n      const UInt64 numGroups64 = _h.GetNumGroups();\n      if (numGroups64 > (UInt32)1 << 31)\n        return S_FALSE;\n      numGroups = (unsigned)numGroups64;\n    }\n\n    unsigned gdBits = 5;\n    if (_h.Is64Bit())\n    {\n      if (_h.GdSize != 64)\n        return S_FALSE;\n      gdBits = 6;\n    }\n\n    _isArc = true;\n    _phySize = _h.GetPhySize();\n\n    if (_openCallback)\n    {\n      RINOK(_openCallback->SetTotal(NULL, &_phySize))\n    }\n\n    UInt64 fileSize = 0;\n    RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize))\n\n    CRecordVector<CGroupDescriptor> groups;\n\n    {\n      // ---------- Read groups ----------\n\n      CByteBuffer gdBuf;\n      const size_t gdBufSize = (size_t)numGroups << gdBits;\n      if ((gdBufSize >> gdBits) != numGroups)\n        return S_FALSE;\n      gdBuf.Alloc(gdBufSize);\n      RINOK(SeekAndRead(inStream, (_h.BlockBits <= 10 ? 2 : 1), gdBuf, gdBufSize))\n\n      for (unsigned i = 0; i < numGroups; i++)\n      {\n        CGroupDescriptor gd;\n        \n        const Byte *p = gdBuf + ((size_t)i << gdBits);\n        const unsigned gd_Size = (unsigned)1 << gdBits;\n        gd.Parse(p, gd_Size);\n        \n        if (_h.UseMetadataChecksum())\n        {\n          // use CRC32c\n        }\n        else if (_h.UseGdtChecksum())\n        {\n          UInt32 crc = Crc16Calc(_h.Uuid, sizeof(_h.Uuid));\n          Byte i_le[4];\n          SetUi32(i_le, i)\n          crc = Crc16Update(crc, i_le, 4);\n          crc = Crc16Update(crc, p, 32 - 2);\n          if (gd_Size != 32)\n            crc = Crc16Update(crc, p + 32, gd_Size - 32);\n          if (crc != gd.Checksum)\n            return S_FALSE;\n        }\n        \n        groups.Add(gd);\n      }\n    }\n\n    {\n      // ---------- Read nodes ----------\n\n      if (_h.NumInodes < _h.NumFreeInodes)\n        return S_FALSE;\n\n      UInt32 numNodes = _h.InodesPerGroup;\n      if (numNodes > _h.NumInodes)\n        numNodes = _h.NumInodes;\n      const size_t nodesDataSize = (size_t)numNodes * _h.InodeSize;\n      \n      if (nodesDataSize / _h.InodeSize != numNodes)\n        return S_FALSE;\n\n      // that code to reduce false detecting cases\n      if (nodesDataSize > fileSize)\n      {\n        if (numNodes > (1 << 24))\n          return S_FALSE;\n      }\n      \n      const UInt32 numReserveInodes = _h.NumInodes - _h.NumFreeInodes + 1;\n      // numReserveInodes = _h.NumInodes + 1;\n      if (numReserveInodes != 0)\n      {\n        _nodes.Reserve(numReserveInodes);\n        _refs.Reserve(numReserveInodes);\n      }\n      \n      CByteBuffer nodesData;\n      nodesData.Alloc(nodesDataSize);\n      \n      CByteBuffer nodesMap;\n      const size_t blockSize = (size_t)1 << _h.BlockBits;\n      nodesMap.Alloc(blockSize);\n      \n      unsigned globalNodeIndex = 0;\n      // unsigned numEmpty = 0;\n      unsigned numEmpty_in_Maps = 0;\n\n      FOR_VECTOR (gi, groups)\n      {\n        if (globalNodeIndex >= _h.NumInodes)\n          break;\n\n        const CGroupDescriptor &gd = groups[gi];\n        \n        PRF(printf(\"\\n\\ng%6d block = %6x\\n\", gi, (unsigned)gd.InodeTable));\n        \n        RINOK(SeekAndRead(inStream, gd.InodeBitmap, nodesMap, blockSize))\n        RINOK(SeekAndRead(inStream, gd.InodeTable, nodesData, nodesDataSize))\n\n        unsigned numEmpty_in_Map = 0;\n        \n        for (size_t n = 0; n < numNodes && globalNodeIndex < _h.NumInodes; n++, globalNodeIndex++)\n        {\n          if ((nodesMap[n >> 3] & ((unsigned)1 << (n & 7))) == 0)\n          {\n            numEmpty_in_Map++;\n            continue;\n          }\n\n          const Byte *p = nodesData + (size_t)n * _h.InodeSize;\n          if (IsEmptyData(p, _h.InodeSize))\n          {\n            if (globalNodeIndex + 1 >= _h.FirstInode)\n            {\n              _headersError = true;\n              // return S_FALSE;\n            }\n            continue;\n          }\n\n          CNode node;\n              \n          PRF(printf(\"\\nnode = %5d \", (unsigned)n));\n\n          if (!node.Parse(p, _h))\n            return S_FALSE;\n  \n          // PRF(printf(\"\\n %6d\", (unsigned)n));\n          /*\n            SetUi32(p + 0x7C, 0)\n            SetUi32(p + 0x82, 0)\n            \n            UInt32 crc = Crc32C_Calc(_h.Uuid, sizeof(_h.Uuid));\n            Byte i_le[4];\n            SetUi32(i_le, n);\n            crc = Crc32C_Update(crc, i_le, 4);\n            crc = Crc32C_Update(crc, p, _h.InodeSize);\n            if (crc != node.Checksum) return S_FALSE;\n          */\n\n          while (_refs.Size() < globalNodeIndex + 1)\n          {\n            // numEmpty++;\n            _refs.Add(-1);\n          }\n          \n          _refs.Add((int)_nodes.Add(node));\n        }\n\n        \n        numEmpty_in_Maps += numEmpty_in_Map;\n        \n        if (numEmpty_in_Map != gd.NumFreeInodes)\n        {\n          _headersWarning = true;\n          // return S_FALSE;\n        }\n      }\n      \n      if (numEmpty_in_Maps != _h.NumFreeInodes)\n      {\n        // some ext2 examples has incorrect value in _h.NumFreeInodes.\n        // so we disable check;\n        _headersWarning = true;\n      }\n\n      if (_refs.Size() <= k_INODE_ROOT)\n        return S_FALSE;\n\n      // printf(\"\\n numReserveInodes = %6d, _refs.Size() = %d, numEmpty = %7d\\n\", numReserveInodes, _refs.Size(), (unsigned)numEmpty);\n    }\n  }\n\n  _stream = inStream; // we need stream for dir nodes\n\n  {\n    // ---------- Read Dirs ----------\n\n    CByteBuffer dataBuf;\n\n    FOR_VECTOR (i, _refs)\n    {\n      const int nodeIndex = _refs[i];\n      {\n        if (nodeIndex < 0)\n          continue;\n        const CNode &node = _nodes[nodeIndex];\n        if (!node.IsDir())\n          continue;\n      }\n      RINOK(ExtractNode((unsigned)nodeIndex, dataBuf))\n      if (dataBuf.Size() == 0)\n      {\n        // _headersError = true;\n        return S_FALSE;\n      }\n      else\n      {\n        RINOK(ParseDir(dataBuf, dataBuf.Size(), i))\n      }\n      RINOK(CheckProgress())\n    }\n\n    const int ref = _refs[k_INODE_ROOT];\n    if (ref < 0 || _nodes[ref].ParentNode != k_INODE_ROOT)\n      return S_FALSE;\n  }\n\n  {\n    // ---------- Check NumLinks and unreferenced dir nodes ----------\n  \n    FOR_VECTOR (i, _refs)\n    {\n      int nodeIndex = _refs[i];\n      if (nodeIndex < 0)\n        continue;\n      const CNode &node = _nodes[nodeIndex];\n\n      if (node.NumLinks != node.NumLinksCalced)\n      {\n        if (node.NumLinks != 1 || node.NumLinksCalced != 0\n            // ) && i >= _h.FirstInode\n            )\n        {\n          _linksError = true;\n          // return S_FALSE;\n        }\n      }\n\n      if (!node.IsDir())\n        continue;\n\n      if (node.ParentNode < 0)\n      {\n        if (i >= _h.FirstInode)\n          return S_FALSE;\n        continue;\n      }\n    }\n  }\n\n  {\n    // ---------- Check that there is no loops in parents list ----------\n\n    unsigned numNodes = _refs.Size();\n    CIntArr UsedByNode(numNodes);\n    {\n      {\n        for (unsigned i = 0; i < numNodes; i++)\n          UsedByNode[i] = -1;\n      }\n    }\n\n    FOR_VECTOR (i, _refs)\n    {\n      {\n        int nodeIndex = _refs[i];\n        if (nodeIndex < 0)\n          continue;\n        const CNode &node = _nodes[nodeIndex];\n        if (node.ParentNode < 0 // not dir\n            || i == k_INODE_ROOT)\n          continue;\n      }\n\n      unsigned c = i;\n\n      for (;;)\n      {\n        const int nodeIndex = _refs[c];\n        if (nodeIndex < 0)\n          return S_FALSE;\n        CNode &node = _nodes[nodeIndex];\n        \n        if (UsedByNode[c] != -1)\n        {\n          if ((unsigned)UsedByNode[c] == i)\n            return S_FALSE;\n          break;\n        }\n        \n        UsedByNode[c] = (int)i;\n        if (node.ParentNode < 0 || node.ParentNode == k_INODE_ROOT)\n          break;\n        if ((unsigned)node.ParentNode == i)\n          return S_FALSE;\n        c = (unsigned)node.ParentNode;\n      }\n    }\n  }\n  \n  {\n    // ---------- Fill SymLinks data ----------\n\n    AString s;\n    CByteBuffer data;\n\n    unsigned i;\n    for (i = 0; i < _refs.Size(); i++)\n    {\n      const int nodeIndex = _refs[i];\n      if (nodeIndex < 0)\n        continue;\n      CNode &node = _nodes[nodeIndex];\n      if (!node.IsLink())\n        continue;\n      if (node.FileSize > ((UInt32)1 << 14))\n        continue;\n      if (ExtractNode((unsigned)nodeIndex, data) == S_OK && data.Size() != 0)\n      {\n        s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size());\n        if (s.Len() == data.Size())\n          node.SymLinkIndex = (int)_symLinks.Add(s);\n        RINOK(CheckProgress())\n      }\n    }\n\n    for (i = 0; i < _dirs.Size(); i++)\n    {\n      _dirs[i].Sort(CompareItemsNames, (void *)&_items);\n    }\n\n    unsigned prev = 0;\n    unsigned complex = 0;\n\n    for (i = 0; i < _items.Size(); i++)\n    {\n      CItem &item = _items[i];\n      const int sym = _nodes[_refs[item.Node]].SymLinkIndex;\n      if (sym >= 0 && item.ParentNode >= 0)\n      {\n        item.SymLinkItemIndex = FindTargetItem_for_SymLink((unsigned)item.ParentNode, _symLinks[sym]);\n        if (_openCallback)\n        {\n          complex++;\n          if (complex - prev >= (1 << 10))\n          {\n            prev = complex;\n            RINOK(CheckProgress2())\n          }\n        }\n      }\n    }\n  }\n\n  {\n    // ---------- Add items and aux folders for unreferenced files ----------\n\n    bool useSys = false;\n    bool useUnknown = false;\n\n    FOR_VECTOR (i, _refs)\n    {\n      const int nodeIndex = _refs[i];\n      if (nodeIndex < 0)\n        continue;\n      const CNode &node = _nodes[nodeIndex];\n      \n      if (node.NumLinksCalced == 0 /* || i > 100 && i < 150 */) // for debug\n      {\n        CItem item;\n        item.Node = i;\n\n        // we don't know how to work with k_INODE_RESIZE node (strange FileSize and Block values).\n        // so we ignore it;\n        \n        if (i == k_INODE_RESIZE)\n          continue;\n        \n        if (node.FileSize == 0)\n          continue;\n\n        if (i < _h.FirstInode)\n        {\n          if (item.Node < Z7_ARRAY_SIZE(k_SysInode_Names))\n            item.Name = k_SysInode_Names[item.Node];\n          useSys = true;\n        }\n        else\n          useUnknown = true;\n        \n        if (item.Name.IsEmpty())\n          item.Name.Add_UInt32(item.Node);\n\n        _items.Add(item);\n      }\n    }\n\n    if (useSys)\n      _auxSysIndex = (int)_auxItems.Add((AString)\"[SYS]\");\n    if (useUnknown)\n      _auxUnknownIndex = (int)_auxItems.Add((AString)\"[UNKNOWN]\");\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    HRESULT res;\n    try\n    {\n      _openCallback = callback;\n      res = Open2(stream);\n    }\n    catch(...)\n    {\n      ClearRefs();\n      throw;\n    }\n    \n    if (res != S_OK)\n    {\n      ClearRefs();\n      return res;\n    }\n    _stream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n\nvoid CHandler::ClearRefs()\n{\n  _stream.Release();\n  _items.Clear();\n  _nodes.Clear();\n  _refs.Clear();\n  _auxItems.Clear();\n  _symLinks.Clear();\n  _dirs.Clear();\n  _auxSysIndex = -1;\n  _auxUnknownIndex = -1;\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalRead = 0;\n  _totalReadPrev = 0;\n  _phySize = 0;\n  _isArc = false;\n  _headersError = false;\n  _headersWarning = false;\n  _linksError = false;\n  _isUTF = true;\n\n  ClearRefs();\n  return S_OK;\n}\n\n\nstatic void ChangeSeparatorsInName(char *s, unsigned num)\n{\n  for (unsigned i = 0; i < num; i++)\n  {\n    char c = s[i];\n    if (c == CHAR_PATH_SEPARATOR || c == '/')\n      s[i] = '_';\n  }\n}\n\n\nvoid CHandler::GetPath(unsigned index, AString &s) const\n{\n  s.Empty();\n\n  if (index >= _items.Size())\n  {\n    s = _auxItems[index - _items.Size()];\n    return;\n  }\n  \n  for (;;)\n  {\n    const CItem &item = _items[index];\n    if (!s.IsEmpty())\n      s.InsertAtFront(CHAR_PATH_SEPARATOR);\n    s.Insert(0, item.Name);\n    // 18.06\n    ChangeSeparatorsInName(s.GetBuf(), item.Name.Len());\n\n    if (item.ParentNode == k_INODE_ROOT)\n      return;\n\n    if (item.ParentNode < 0)\n    {\n      int aux = GetParentAux(item);\n      if (aux < 0)\n        break;\n      s.InsertAtFront(CHAR_PATH_SEPARATOR);\n      s.Insert(0, _auxItems[aux]);\n      return;\n    }\n\n    const CNode &node = _nodes[_refs[item.ParentNode]];\n    if (node.ItemIndex < 0)\n      return;\n    index = (unsigned)node.ItemIndex;\n\n    if (s.Len() > ((UInt32)1 << 16))\n    {\n      s.Insert(0, \"[LONG]\" STRING_PATH_SEPARATOR);\n      return;\n    }\n  }\n}\n\n\nbool CHandler::GetPackSize(unsigned index, UInt64 &totalPack) const\n{\n  if (index >= _items.Size())\n  {\n    totalPack = 0;\n    return false;\n  }\n\n  const CItem &item = _items[index];\n  const CNode &node = _nodes[_refs[item.Node]];\n\n  // if (!node.IsFlags_EXTENTS())\n  {\n    totalPack = (UInt64)node.NumBlocks << (node.IsFlags_HUGE() ? _h.BlockBits : 9);\n    return true;\n  }\n\n  /*\n  CExtentTreeHeader eth;\n  if (!eth.Parse(node.Block))\n    return false;\n  if (eth.NumEntries > 3)\n    return false;\n  if (!eth.Depth == 0)\n    return false;\n\n  UInt64 numBlocks = 0;\n  {\n    for (unsigned i = 0; i < eth.NumEntries; i++)\n    {\n      CExtent e;\n      e.Parse(node.Block + 12 + i * 12);\n      // const CExtent &e = node.leafs[i];\n      if (e.IsInited)\n        numBlocks += e.Len;\n    }\n  }\n\n  totalPack = numBlocks << _h.BlockBits;\n  return true;\n  */\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size() + _auxItems.Size();\n  return S_OK;\n}\n\nenum\n{\n  kpidMountTime = kpidUserDefined,\n  kpidLastCheckTime,\n  kpidRevision,\n  kpidINodeSize,\n  kpidLastMount,\n  kpidFeatureIncompat,\n  kpidFeatureRoCompat,\n  kpidWrittenKB\n\n  // kpidGroupSize,\n\n  // kpidChangeTime = kpidUserDefined + 256,\n  // kpidDTime\n};\n\nstatic const UInt32 kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidPosixAttrib,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  // kpidChangeTime,\n  // kpidDTime,\n  kpidINode,\n  kpidLinks,\n  kpidSymLink,\n  kpidCharacts,\n  kpidUserId,\n  kpidGroupId\n};\n\n\nstatic const CStatProp kArcProps[] =\n{\n  { NULL, kpidHeadersSize, VT_BSTR },\n  // { NULL, kpidFileSystem, VT_BSTR },\n  // kpidMethod,\n  { NULL, kpidClusterSize, VT_UI4 },\n  // { \"Group Size\", kpidGroupSize, VT_UI8 },\n  { NULL, kpidFreeSpace, VT_UI8 },\n  \n  { NULL, kpidMTime, VT_FILETIME },\n  { NULL, kpidCTime, VT_FILETIME },\n  { \"Mount Time\", kpidMountTime, VT_FILETIME },\n  { \"Last Check Time\", kpidLastCheckTime, VT_FILETIME },\n  \n  { NULL, kpidHostOS, VT_BSTR},\n  { \"Revision\", kpidRevision, VT_UI4},\n  { \"inode Size\", kpidINodeSize, VT_UI4},\n  { NULL, kpidCodePage, VT_BSTR},\n  { NULL, kpidVolumeName, VT_BSTR},\n  { \"Last Mounted\", kpidLastMount, VT_BSTR},\n  { NULL, kpidId, VT_BSTR},\n  { NULL, kpidCharacts, VT_BSTR },\n  { \"Incompatible Features\", kpidFeatureIncompat, VT_BSTR },\n  { \"Readonly-compatible Features\", kpidFeatureRoCompat, VT_BSTR },\n  { \"Written KiB\", kpidWrittenKB, VT_UI8 }\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\nstatic void StringToProp(bool isUTF, const char *s, unsigned size, NCOM::CPropVariant &prop)\n{\n  UString u;\n  AString a;\n  a.SetFrom_CalcLen(s, size);\n  if (!isUTF || !ConvertUTF8ToUnicode(a, u))\n    MultiByteToUnicodeString2(u, a);\n  prop = u;\n}\n\nstatic void UnixTimeToProp(UInt32 val, NCOM::CPropVariant &prop)\n{\n  if (val != 0)\n    PropVariant_SetFrom_UnixTime(prop, val);\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n \n  NCOM::CPropVariant prop;\n  \n  switch (propID)\n  {\n    /*\n    case kpidFileSystem:\n    {\n      AString res = \"Ext4\";\n      prop = res;\n      break;\n    }\n    */\n    \n    case kpidIsTree: prop = true; break;\n    case kpidIsAux: prop = true; break;\n    case kpidINode: prop = true; break;\n\n    case kpidClusterSize: prop = (UInt32)1 << _h.BlockBits; break;\n    // case kpidGroupSize: prop = (UInt64)_h.BlocksPerGroup << _h.BlockBits; break;\n    \n    case kpidFreeSpace: prop = (UInt64)_h.NumFreeBlocks << _h.BlockBits; break;\n\n    case kpidCTime: UnixTimeToProp(_h.CTime, prop); break;\n    case kpidMTime: UnixTimeToProp(_h.WriteTime, prop); break;\n    case kpidMountTime: UnixTimeToProp(_h.MountTime, prop); break;\n    case kpidLastCheckTime: UnixTimeToProp(_h.LastCheckTime, prop); break;\n\n    case kpidHostOS:\n    {\n      TYPE_TO_PROP(kHostOS, _h.CreatorOs, prop);\n      break;\n    }\n    \n    case kpidRevision: prop = _h.RevLevel; break;\n\n    case kpidINodeSize: prop = (UInt32)_h.InodeSize; break;\n\n    case kpidId:\n    {\n      if (!IsEmptyData(_h.Uuid, sizeof(_h.Uuid)))\n      {\n        char s[sizeof(_h.Uuid) * 2 + 2];\n        ConvertDataToHex_Lower(s, _h.Uuid, sizeof(_h.Uuid));\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidCodePage: if (_isUTF) prop = \"UTF-8\"; break;\n    \n    case kpidShortComment:\n    case kpidVolumeName:\n        StringToProp(_isUTF, _h.VolName, sizeof(_h.VolName), prop); break;\n    \n    case kpidLastMount: StringToProp(_isUTF, _h.LastMount, sizeof(_h.LastMount), prop); break;\n\n    case kpidCharacts: FLAGS_TO_PROP(g_FeatureCompat_Flags, _h.FeatureCompat, prop); break;\n    case kpidFeatureIncompat: FLAGS_TO_PROP(g_FeatureIncompat_Flags, _h.FeatureIncompat, prop); break;\n    case kpidFeatureRoCompat: FLAGS_TO_PROP(g_FeatureRoCompat_Flags, _h.FeatureRoCompat, prop); break;\n    case kpidWrittenKB: if (_h.WrittenKB != 0) prop = _h.WrittenKB; break;\n\n    case kpidPhySize: prop = _phySize; break;\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_linksError) v |= kpv_ErrorFlags_HeadersError;\n      if (_headersError) v |= kpv_ErrorFlags_HeadersError;\n      if (!_stream && v == 0 && _isArc)\n        v = kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n\n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      if (_headersWarning) v |= kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n\n  COM_TRY_END\n}\n\n\n/*\nstatic const Byte kRawProps[] =\n{\n  // kpidSha1,\n};\n*/\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  // *numProps = Z7_ARRAY_SIZE(kRawProps);\n  *numProps = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID))\n{\n  // *propID = kRawProps[index];\n  *propID = 0;\n  *name = NULL;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  *parentType = NParentType::kDir;\n  *parent = (UInt32)(Int32)-1;\n\n  if (index >= _items.Size())\n    return S_OK;\n\n  const CItem &item = _items[index];\n  \n  if (item.ParentNode < 0)\n  {\n    const int aux = GetParentAux(item);\n    if (aux >= 0)\n      *parent = _items.Size() + (unsigned)aux;\n  }\n  else\n  {\n    const int itemIndex = _nodes[_refs[item.ParentNode]].ItemIndex;\n    if (itemIndex >= 0)\n      *parent = (unsigned)itemIndex;\n  }\n  \n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n\n  if (propID == kpidName && _isUTF)\n  {\n    if (index < _items.Size())\n    {\n      const AString &s = _items[index].Name;\n      if (!s.IsEmpty())\n      {\n        *data = (void *)(const char *)s;\n        *dataSize = (UInt32)s.Len() + 1;\n        *propType = NPropDataType::kUtf8z;\n      }\n      return S_OK;\n    }\n    else\n    {\n      const AString &s = _auxItems[index - _items.Size()];\n      {\n        *data = (void *)(const char *)s;\n        *dataSize = (UInt32)s.Len() + 1;\n        *propType = NPropDataType::kUtf8z;\n      }\n      return S_OK;\n    }\n  }\n\n  return S_OK;\n}\n\n\nstatic void ExtTimeToProp(const CExtTime &t, NCOM::CPropVariant &prop)\n{\n  if (t.Val == 0 && t.Extra == 0)\n    return;\n\n  FILETIME ft;\n  unsigned low100ns = 0;\n  // if (t.Extra != 0)\n  {\n    // 1901-2446 :\n    Int64 v = (Int64)(Int32)t.Val;\n    v += (UInt64)(t.Extra & 3) << 32;  // 2 low bits are offset for main timestamp\n    UInt64 ft64 = NTime::UnixTime64_To_FileTime64(v);\n    const UInt32 ns = (t.Extra >> 2);\n    if (ns < 1000000000)\n    {\n      ft64 += ns / 100;\n      low100ns = (unsigned)(ns % 100);\n    }\n    ft.dwLowDateTime = (DWORD)ft64;\n    ft.dwHighDateTime = (DWORD)(ft64 >> 32);\n  }\n  /*\n  else\n  {\n    // 1901-2038 : that code is good for ext4 and compatibility with Extra\n    NTime::UnixTime64ToFileTime((Int32)t.Val, ft); // for\n\n    // 1970-2106 : that code is good if timestamp is used as unsigned 32-bit\n    // are there such systems?\n    // NTime::UnixTimeToFileTime(t.Val, ft); // for\n  }\n  */\n  prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, low100ns);\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  if (index >= _items.Size())\n  {\n    switch (propID)\n    {\n      case kpidPath:\n      case kpidName:\n      {\n        prop = _auxItems[index - _items.Size()];\n        break;\n      }\n      case kpidIsDir: prop = true; break;\n      case kpidIsAux: prop = true; break;\n    }\n  }\n  else\n  {\n\n  const CItem &item = _items[index];\n  const CNode &node = _nodes[_refs[item.Node]];\n  bool isDir = node.IsDir();\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      UString u;\n      {\n        AString s;\n        GetPath(index, s);\n        if (!_isUTF || !ConvertUTF8ToUnicode(s, u))\n          MultiByteToUnicodeString2(u, s);\n      }\n      prop = u;\n      break;\n    }\n    \n    case kpidName:\n    {\n      {\n        UString u;\n        {\n          if (!_isUTF || !ConvertUTF8ToUnicode(item.Name, u))\n            MultiByteToUnicodeString2(u, item.Name);\n        }\n        prop = u;\n      }\n      break;\n    }\n    \n    case kpidIsDir:\n    {\n      bool isDir2 = isDir;\n      if (item.SymLinkItemIndex >= 0)\n        isDir2 = _nodes[_refs[_items[item.SymLinkItemIndex].Node]].IsDir();\n      prop = isDir2;\n      break;\n    }\n\n    case kpidSize: if (!isDir) prop = node.FileSize; break;\n    \n    case kpidPackSize:\n      if (!isDir)\n      {\n        UInt64 size;\n        if (GetPackSize(index, size))\n          prop = size;\n      }\n      break;\n\n    case kpidPosixAttrib:\n    {\n      /*\n      if (node.Type != 0 && node.Type < Z7_ARRAY_SIZE(k_TypeToMode))\n        prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type];\n      */\n      prop = (UInt32)(node.Mode);\n      break;\n    }\n\n    case kpidMTime: ExtTimeToProp(node.MTime, prop); break;\n    case kpidCTime: ExtTimeToProp(node.CTime, prop); break;\n    case kpidATime: ExtTimeToProp(node.ATime, prop); break;\n    // case kpidDTime: ExtTimeToProp(node.DTime, prop); break;\n    case kpidChangeTime: ExtTimeToProp(node.ChangeTime, prop); break;\n    case kpidUserId: prop = (UInt32)node.Uid; break;\n    case kpidGroupId: prop = (UInt32)node.Gid; break;\n    case kpidLinks: prop = node.NumLinks; break;\n    case kpidINode: prop = (UInt32)item.Node; break;\n    case kpidStreamId: if (!isDir) prop = (UInt32)item.Node; break;\n    case kpidCharacts: FLAGS_TO_PROP(g_NodeFlags, (UInt32)node.Flags, prop); break;\n\n    case kpidSymLink:\n    {\n      if (node.SymLinkIndex >= 0)\n      {\n        UString u;\n        {\n          const AString &s = _symLinks[node.SymLinkIndex];\n          if (!_isUTF || !ConvertUTF8ToUnicode(s, u))\n            MultiByteToUnicodeString2(u, s);\n        }\n        prop = u;\n      }\n      break;\n    }\n  }\n\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_CLASS_IMP_IInStream(CClusterInStream2\n)\n  UInt64 _virtPos;\n  UInt64 _physPos;\n  UInt32 _curRem;\npublic:\n  unsigned BlockBits;\n  UInt64 Size;\n  CMyComPtr<IInStream> Stream;\n  CRecordVector<UInt32> Vector;\n\n  HRESULT SeekToPhys() { return InStream_SeekSet(Stream, _physPos); }\n\n  HRESULT InitAndSeek()\n  {\n    _curRem = 0;\n    _virtPos = 0;\n    _physPos = 0;\n    if (Vector.Size() > 0)\n    {\n      _physPos = (Vector[0] << BlockBits);\n      return SeekToPhys();\n    }\n    return S_OK;\n  }\n};\n\n\nZ7_COM7F_IMF(CClusterInStream2::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= Size)\n    return S_OK;\n  {\n    UInt64 rem = Size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  if (size == 0)\n    return S_OK;\n\n  if (_curRem == 0)\n  {\n    const UInt32 blockSize = (UInt32)1 << BlockBits;\n    const UInt32 virtBlock = (UInt32)(_virtPos >> BlockBits);\n    const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);\n    const UInt32 phyBlock = Vector[virtBlock];\n    \n    if (phyBlock == 0)\n    {\n      UInt32 cur = blockSize - offsetInBlock;\n      if (cur > size)\n        cur = size;\n      memset(data, 0, cur);\n      _virtPos += cur;\n      if (processedSize)\n        *processedSize = cur;\n      return S_OK;\n    }\n    \n    UInt64 newPos = ((UInt64)phyBlock << BlockBits) + offsetInBlock;\n    if (newPos != _physPos)\n    {\n      _physPos = newPos;\n      RINOK(SeekToPhys())\n    }\n    \n    _curRem = blockSize - offsetInBlock;\n    \n    for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)\n      _curRem += (UInt32)1 << BlockBits;\n  }\n\n  if (size > _curRem)\n    size = _curRem;\n  HRESULT res = Stream->Read(data, size, &size);\n  if (processedSize)\n    *processedSize = size;\n  _physPos += size;\n  _virtPos += size;\n  _curRem -= size;\n  return res;\n}\n \nZ7_COM7F_IMF(CClusterInStream2::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  if (_virtPos != (UInt64)offset)\n    _curRem = 0;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\n\nZ7_CLASS_IMP_IInStream(\n  CExtInStream\n)\n  UInt64 _virtPos;\n  UInt64 _phyPos;\npublic:\n  unsigned BlockBits;\n  UInt64 Size;\n  CMyComPtr<IInStream> Stream;\n  CRecordVector<CExtent> Extents;\n\n  HRESULT StartSeek()\n  {\n    _virtPos = 0;\n    _phyPos = 0;\n    return InStream_SeekSet(Stream, _phyPos);\n  }\n};\n\nZ7_COM7F_IMF(CExtInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= Size)\n    return S_OK;\n  {\n    UInt64 rem = Size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  if (size == 0)\n    return S_OK;\n\n  UInt32 blockIndex = (UInt32)(_virtPos >> BlockBits);\n  \n  unsigned left = 0, right = Extents.Size();\n  for (;;)\n  {\n    unsigned mid = (left + right) / 2;\n    if (mid == left)\n      break;\n    if (blockIndex < Extents[mid].VirtBlock)\n      right = mid;\n    else\n      left = mid;\n  }\n\n  {\n    const CExtent &extent = Extents[left];\n    if (blockIndex < extent.VirtBlock)\n      return E_FAIL;\n    UInt32 bo = blockIndex - extent.VirtBlock;\n    if (bo >= extent.Len)\n      return E_FAIL;\n\n    UInt32 offset = ((UInt32)_virtPos & (((UInt32)1 << BlockBits) - 1));\n    UInt32 remBlocks = extent.Len - bo;\n    UInt64 remBytes = ((UInt64)remBlocks << BlockBits);\n    remBytes -= offset;\n\n    if (size > remBytes)\n      size = (UInt32)remBytes;\n\n    if (!extent.IsInited)\n    {\n      memset(data, 0, size);\n      _virtPos += size;\n      if (processedSize)\n        *processedSize = size;\n      return S_OK;\n    }\n\n    const UInt64 phyBlock = extent.PhyStart + bo;\n    const UInt64 phy = (phyBlock << BlockBits) + offset;\n    \n    if (phy != _phyPos)\n    {\n      RINOK(InStream_SeekSet(Stream, phy))\n      _phyPos = phy;\n    }\n    \n    UInt32 realProcessSize = 0;\n    \n    const HRESULT res = Stream->Read(data, size, &realProcessSize);\n    \n    _phyPos += realProcessSize;\n    _virtPos += realProcessSize;\n    if (processedSize)\n      *processedSize = realProcessSize;\n    return res;\n  }\n}\n\n\nZ7_COM7F_IMF(CExtInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\n\n\nHRESULT CHandler::FillFileBlocks2(UInt32 block, unsigned level, unsigned numBlocks, CRecordVector<UInt32> &blocks)\n{\n  const size_t blockSize = (size_t)1 << _h.BlockBits;\n  CByteBuffer &tempBuf = _tempBufs[level];\n  tempBuf.Alloc(blockSize);\n\n  PRF2(printf(\"\\n level = %d, block = %7d\", level, (unsigned)block));\n\n  RINOK(SeekAndRead(_stream, block, tempBuf, blockSize))\n\n  const Byte *p = tempBuf;\n  size_t num = (size_t)1 << (_h.BlockBits - 2);\n\n  for (size_t i = 0; i < num; i++)\n  {\n    if (blocks.Size() == numBlocks)\n      break;\n    UInt32 val = GetUi32(p + 4 * i);\n    if (val >= _h.NumBlocks)\n      return S_FALSE;\n\n    if (level != 0)\n    {\n      if (val == 0)\n      {\n        /*\n        size_t num = (size_t)1 << ((_h.BlockBits - 2) * (level));\n        PRF2(printf(\"\\n num empty = %3d\", (unsigned)num));\n        for (size_t k = 0; k < num; k++)\n        {\n          blocks.Add(0);\n          if (blocks.Size() == numBlocks)\n            return S_OK;\n        }\n        continue;\n        */\n        return S_FALSE;\n      }\n      \n      RINOK(FillFileBlocks2(val, level - 1, numBlocks, blocks))\n      continue;\n    }\n    \n    PRF2(printf(\"\\n i = %3d,  blocks.Size() = %6d, block = %5d \", i, blocks.Size(), (unsigned)val));\n\n    PRF(printf(\"\\n i = %3d,  start = %5d \", (unsigned)i, (unsigned)val));\n    \n    blocks.Add(val);\n  }\n\n  return S_OK;\n}\n\n\nstatic const unsigned kNumDirectNodeBlocks = 12;\n\nHRESULT CHandler::FillFileBlocks(const Byte *p, unsigned numBlocks, CRecordVector<UInt32> &blocks)\n{\n  // ext2 supports zero blocks (blockIndex == 0).\n\n  blocks.ClearAndReserve(numBlocks);\n\n  for (unsigned i = 0; i < kNumDirectNodeBlocks; i++)\n  {\n    if (i == numBlocks)\n      return S_OK;\n    UInt32 val = GetUi32(p + 4 * i);\n    if (val >= _h.NumBlocks)\n      return S_FALSE;\n    blocks.Add(val);\n  }\n  \n  for (unsigned level = 0; level < 3; level++)\n  {\n    if (blocks.Size() == numBlocks)\n      break;\n    UInt32 val = GetUi32(p + 4 * (kNumDirectNodeBlocks + level));\n    if (val >= _h.NumBlocks)\n      return S_FALSE;\n\n    if (val == 0)\n    {\n      /*\n      size_t num = (size_t)1 << ((_h.BlockBits - 2) * (level + 1));\n      for (size_t k = 0; k < num; k++)\n      {\n        blocks.Add(0);\n        if (blocks.Size() == numBlocks)\n          return S_OK;\n      }\n      continue;\n      */\n      return S_FALSE;\n    }\n\n    RINOK(FillFileBlocks2(val, level, numBlocks, blocks))\n  }\n  \n  return S_OK;\n}\n\n\nstatic void AddSkipExtents(CRecordVector<CExtent> &extents, UInt32 virtBlock, UInt32 numBlocks)\n{\n  while (numBlocks != 0)\n  {\n    UInt32 len = numBlocks;\n    const UInt32 kLenMax = (UInt32)1 << 15;\n    if (len > kLenMax)\n      len = kLenMax;\n    CExtent e;\n    e.VirtBlock = virtBlock;\n    e.Len = (UInt16)len;\n    e.IsInited = false;\n    e.PhyStart = 0;\n    extents.Add(e);\n    virtBlock += len;\n    numBlocks -= len;\n  }\n}\n\nstatic bool UpdateExtents(CRecordVector<CExtent> &extents, UInt32 block)\n{\n  if (extents.IsEmpty())\n  {\n    if (block == 0)\n      return true;\n    AddSkipExtents(extents, 0, block);\n    return true;\n  }\n\n  const CExtent &prev = extents.Back();\n  if (block < prev.VirtBlock)\n    return false;\n  UInt32 prevEnd = prev.GetVirtEnd();\n  if (block == prevEnd)\n    return true;\n  AddSkipExtents(extents, prevEnd, block - prevEnd);\n  return true;\n}\n\n\nHRESULT CHandler::FillExtents(const Byte *p, size_t size, CRecordVector<CExtent> &extents, int parentDepth)\n{\n  CExtentTreeHeader eth;\n  if (!eth.Parse(p))\n    return S_FALSE;\n\n  if (parentDepth >= 0 && eth.Depth != parentDepth - 1) // (eth.Depth >= parentDepth)\n    return S_FALSE;\n\n  if (12 + 12 * (size_t)eth.NumEntries > size)\n    return S_FALSE;\n\n  if (eth.Depth >= kNumTreeLevelsMax)\n    return S_FALSE;\n\n  if (eth.Depth == 0)\n  {\n    for (unsigned i = 0; i < eth.NumEntries; i++)\n    {\n      CExtent e;\n      e.Parse(p + 12 + i * 12);\n      if (e.PhyStart == 0\n          || e.PhyStart > _h.NumBlocks\n          || e.PhyStart + e.Len > _h.NumBlocks\n          || !e.IsLenOK())\n        return S_FALSE;\n      if (!UpdateExtents(extents, e.VirtBlock))\n        return S_FALSE;\n      extents.Add(e);\n    }\n    \n    return S_OK;\n  }\n\n  const size_t blockSize = (size_t)1 << _h.BlockBits;\n  CByteBuffer &tempBuf = _tempBufs[eth.Depth];\n  tempBuf.Alloc(blockSize);\n\n  for (unsigned i = 0; i < eth.NumEntries; i++)\n  {\n    CExtentIndexNode e;\n    e.Parse(p + 12 + i * 12);\n\n    if (e.PhyLeaf == 0 || e.PhyLeaf >= _h.NumBlocks)\n      return S_FALSE;\n\n    if (!UpdateExtents(extents, e.VirtBlock))\n      return S_FALSE;\n\n    RINOK(SeekAndRead(_stream, e.PhyLeaf, tempBuf, blockSize))\n    RINOK(FillExtents(tempBuf, blockSize, extents, eth.Depth))\n  }\n\n  return S_OK;\n}\n\n\nHRESULT CHandler::GetStream_Node(unsigned nodeIndex, ISequentialInStream **stream)\n{\n  COM_TRY_BEGIN\n\n  *stream = NULL;\n\n  const CNode &node = _nodes[nodeIndex];\n\n  if (!node.IsFlags_EXTENTS())\n  {\n    // maybe sparse file can have (node.NumBlocks == 0) ?\n\n    /* The following code doesn't work correctly for some CentOS images,\n       where there are nodes with inline data and (node.NumBlocks != 0).\n       If you know better way to detect inline data, please notify 7-Zip developers. */\n\n    if (node.NumBlocks == 0 && node.FileSize < kNodeBlockFieldSize)\n    {\n      Create_BufInStream_WithNewBuffer(node.Block, (size_t)node.FileSize, stream);\n      return S_OK;\n    }\n  }\n\n  if (node.FileSize >= ((UInt64)1 << 63))\n    return S_FALSE;\n\n  CMyComPtr<IInStream> streamTemp;\n  \n  const UInt64 numBlocks64 = (node.FileSize + (UInt64)(((UInt32)1 << _h.BlockBits) - 1)) >> _h.BlockBits;\n  \n  if (node.IsFlags_EXTENTS())\n  {\n    if ((UInt32)numBlocks64 != numBlocks64)\n      return S_FALSE;\n\n    CExtInStream *streamSpec = new CExtInStream;\n    streamTemp = streamSpec;\n    \n    streamSpec->BlockBits = _h.BlockBits;\n    streamSpec->Size = node.FileSize;\n    streamSpec->Stream = _stream;\n    \n    RINOK(FillExtents(node.Block, kNodeBlockFieldSize, streamSpec->Extents, -1))\n\n    UInt32 end = 0;\n    if (!streamSpec->Extents.IsEmpty())\n      end = streamSpec->Extents.Back().GetVirtEnd();\n    if (end < numBlocks64)\n    {\n      AddSkipExtents(streamSpec->Extents, end, (UInt32)(numBlocks64 - end));\n      // return S_FALSE;\n    }\n\n    RINOK(streamSpec->StartSeek())\n  }\n  else\n  {\n    {\n      UInt64 numBlocks2 = numBlocks64;\n\n      if (numBlocks64 > kNumDirectNodeBlocks)\n      {\n        UInt64 rem = numBlocks64 - kNumDirectNodeBlocks;\n        const unsigned refBits = (_h.BlockBits - 2);\n        const size_t numRefsInBlocks = (size_t)1 << refBits;\n        numBlocks2++;\n        if (rem > numRefsInBlocks)\n        {\n          numBlocks2++;\n          const UInt64 numL2 = (rem - 1) >> refBits;\n          numBlocks2 += numL2;\n          if (numL2 > numRefsInBlocks)\n          {\n            numBlocks2++;\n            numBlocks2 += (numL2 - 1) >> refBits;\n          }\n        }\n      }\n\n      const unsigned specBits = (node.IsFlags_HUGE() ? 0 : _h.BlockBits - 9);\n      const UInt32 specMask = ((UInt32)1 << specBits) - 1;\n      if ((node.NumBlocks & specMask) != 0)\n        return S_FALSE;\n      const UInt64 numBlocks64_from_header = node.NumBlocks >> specBits;\n      if (numBlocks64_from_header < numBlocks2)\n      {\n        // why (numBlocks64_from_header > numBlocks2) in some cases?\n        // return S_FALSE;\n      }\n    }\n\n    unsigned numBlocks = (unsigned)numBlocks64;\n    if (numBlocks != numBlocks64)\n      return S_FALSE;\n\n    CClusterInStream2 *streamSpec = new CClusterInStream2;\n    streamTemp = streamSpec;\n\n    streamSpec->BlockBits = _h.BlockBits;\n    streamSpec->Size = node.FileSize;\n    streamSpec->Stream = _stream;\n\n    RINOK(FillFileBlocks(node.Block, numBlocks, streamSpec->Vector))\n    streamSpec->InitAndSeek();\n  }\n\n  *stream = streamTemp.Detach();\n\n  return S_OK;\n\n  COM_TRY_END\n}\n\n\nHRESULT CHandler::ExtractNode(unsigned nodeIndex, CByteBuffer &data)\n{\n  data.Free();\n  const CNode &node = _nodes[nodeIndex];\n  size_t size = (size_t)node.FileSize;\n  if (size != node.FileSize)\n    return S_FALSE;\n  CMyComPtr<ISequentialInStream> inSeqStream;\n  RINOK(GetStream_Node(nodeIndex, &inSeqStream))\n  if (!inSeqStream)\n    return S_FALSE;\n  data.Alloc(size);\n  _totalRead += size;\n  return ReadStream_FALSE(inSeqStream, data, size);\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size() + _auxItems.Size();\n  if (numItems == 0)\n    return S_OK;\n  \n  UInt64 totalSize = 0;\n  UInt32 i;\n\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n    if (index >= _items.Size())\n      continue;\n    const CItem &item = _items[index];\n    const CNode &node = _nodes[_refs[item.Node]];\n    if (!node.IsDir())\n      totalSize += node.FileSize;\n  }\n  \n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 totalPackSize;\n  totalSize = totalPackSize = 0;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = totalPackSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    int opRes;\n   {\n    CMyComPtr<ISequentialOutStream> outStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    \n    const UInt32 index = allFilesMode ? i : indices[i];\n    \n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n\n    if (index >= _items.Size())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    const CItem &item = _items[index];\n    const CNode &node = _nodes[_refs[item.Node]];\n\n    if (node.IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    UInt64 unpackSize = node.FileSize;\n    totalSize += unpackSize;\n    UInt64 packSize;\n    if (GetPackSize(index, packSize))\n      totalPackSize += packSize;\n\n    if (!testMode && !outStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    opRes = NExtract::NOperationResult::kDataError;\n    {\n      CMyComPtr<ISequentialInStream> inSeqStream;\n      HRESULT hres = GetStream(index, &inSeqStream);\n      if (hres == S_FALSE || !inSeqStream)\n      {\n        if (hres == E_OUTOFMEMORY)\n          return hres;\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      }\n      else\n      {\n        RINOK(hres)\n        {\n          hres = copyCoder.Interface()->Code(inSeqStream, outStream, NULL, NULL, lps);\n          if (hres == S_OK)\n          {\n            if (copyCoder->TotalSize == unpackSize)\n              opRes = NExtract::NOperationResult::kOK;\n          }\n          else if (hres == E_NOTIMPL)\n          {\n            opRes = NExtract::NOperationResult::kUnsupportedMethod;\n          }\n          else if (hres != S_FALSE)\n          {\n            RINOK(hres)\n          }\n        }\n      }\n    }\n   }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  *stream = NULL;\n  if (index >= _items.Size())\n    return S_FALSE;\n  return GetStream_Node((unsigned)_refs[_items[index].Node], stream);\n}\n\n\nAPI_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize);\nAPI_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize)\n{\n  if (phySize)\n    *phySize = 0;\n  if (size < kHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  CHeader h;\n  if (!h.Parse(p + kHeaderDataOffset))\n    return k_IsArc_Res_NO;\n  if (phySize)\n    *phySize = h.GetPhySize();\n  return k_IsArc_Res_YES;\n}\n\n\nAPI_FUNC_IsArc IsArc_Ext(const Byte *p, size_t size);\nAPI_FUNC_IsArc IsArc_Ext(const Byte *p, size_t size)\n{\n  return IsArc_Ext_PhySize(p, size, NULL);\n}\n\n\nstatic const Byte k_Signature[] = { 0x53, 0xEF };\n\nREGISTER_ARC_I(\n  \"Ext\", \"ext ext2 ext3 ext4 img\", NULL, 0xC7,\n  k_Signature,\n  0x438,\n  0,\n  IsArc_Ext)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/FatHandler.cpp",
    "content": "﻿// FatHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyBuffer2.h\"\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/ItemNameUtils.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get16a(p) GetUi16a(p)\n#define Get32a(p) GetUi32a(p)\n\n#if 0\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\nnamespace NArchive {\nnamespace NFat {\n\nstatic const UInt32 kFatItemUsedByDirMask = (UInt32)1 << 31;\n\nstruct CHeader\n{\n  Byte NumFatBits;\n  Byte SectorSizeLog;\n  Byte SectorsPerClusterLog;\n  Byte ClusterSizeLog;\n  Byte NumFats;\n  Byte MediaType;\n\n  bool VolFieldsDefined;\n  bool HeadersWarning;\n\n  UInt32 FatSize;\n  UInt32 BadCluster;\n\n  UInt16 NumReservedSectors;\n  UInt32 NumSectors;\n  UInt32 NumFatSectors;\n  UInt32 RootDirSector;\n  UInt32 NumRootDirSectors;\n  UInt32 DataSector;\n\n  UInt16 SectorsPerTrack;\n  UInt16 NumHeads;\n  UInt32 NumHiddenSectors;\n  \n  UInt32 VolId;\n  // Byte VolName[11];\n  // Byte FileSys[8];\n  // Byte OemName[5];\n\n  // 32-bit FAT\n  UInt16 Flags;\n  UInt16 FsInfoSector;\n  UInt32 RootCluster;\n\n  bool IsFat32() const { return NumFatBits == 32; }\n  UInt64 GetPhySize() const { return (UInt64)NumSectors << SectorSizeLog; }\n  UInt32 SectorSize() const { return (UInt32)1 << SectorSizeLog; }\n  UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }\n  UInt32 ClusterToSector(UInt32 c) const { return DataSector + ((c - 2) << SectorsPerClusterLog); }\n  UInt32 IsEoc(UInt32 c) const { return c > BadCluster; }\n  UInt32 IsEocAndUnused(UInt32 c) const { return c > BadCluster && (c & kFatItemUsedByDirMask) == 0; }\n  UInt32 IsValidCluster(UInt32 c) const { return c >= 2 && c < FatSize; }\n  UInt32 SizeToSectors(UInt32 size) const { return (size + SectorSize() - 1) >> SectorSizeLog; }\n  UInt32 CalcFatSizeInSectors() const { return SizeToSectors((FatSize * (NumFatBits / 4) + 1) / 2); }\n\n  UInt32 GetFatSector() const\n  {\n    UInt32 index = (IsFat32() && (Flags & 0x80) != 0) ? (Flags & 0xF) : 0;\n    if (index > NumFats)\n      index = 0;\n    return NumReservedSectors + index * NumFatSectors;\n  }\n\n  UInt64 GetFilePackSize(UInt32 unpackSize) const\n  {\n    UInt64 mask = ClusterSize() - 1;\n    return (unpackSize + mask) & ~mask;\n  }\n\n  UInt32 GetNumClusters(UInt32 size) const\n    { return (UInt32)(((UInt64)size + ClusterSize() - 1) >> ClusterSizeLog); }\n\n  bool Parse(const Byte *p);\n};\n\n\nstatic const unsigned kHeaderSize = 512;\n\nAPI_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);\nAPI_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size)\n{\n  if (size < kHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  CHeader h;\n  return h.Parse(p) ? k_IsArc_Res_YES : k_IsArc_Res_NO;\n}\n\nbool CHeader::Parse(const Byte *p)\n{\n  if (Get16(p + 0x1FE) != 0xAA55)\n    return false;\n\n  HeadersWarning = false;\n\n  int codeOffset = 0;\n  switch (p[0])\n  {\n    case 0xE9: codeOffset = 3 + (Int16)Get16(p + 1); break;\n    case 0xEB: if (p[2] != 0x90) return false; codeOffset = 2 + (signed char)p[1]; break;\n    default: return false;\n  }\n  {\n    {\n      const unsigned num = Get16(p + 11);\n      unsigned i = 9;\n      unsigned m = 1 << i;\n      for (;;)\n      {\n        if (m == num)\n          break;\n        m <<= 1;\n        if (++i > 12)\n          return false;\n      }\n      SectorSizeLog = (Byte)i;\n    }\n    {\n      const unsigned num = p[13];\n      unsigned i = 0;\n      unsigned m = 1 << i;\n      for (;;)\n      {\n        if (m == num)\n          break;\n        m <<= 1;\n        if (++i > 7)\n          return false;\n      }\n      SectorsPerClusterLog = (Byte)i;\n      i += SectorSizeLog;\n      ClusterSizeLog = (Byte)i;\n      // (2^15 = 32 KB is safe cluster size that is suported by all system.\n      // (2^16 = 64 KB is supported by some systems\n      // (128 KB / 256 KB) can be created by some tools, but it is not supported by many tools.\n      if (i > 18) // 256 KB\n        return false;\n    }\n  }\n\n  NumReservedSectors = Get16(p + 14);\n  if (NumReservedSectors == 0)\n    return false;\n\n  NumFats = p[16];\n  if (NumFats < 1 || NumFats > 4)\n    return false;\n\n  // we also support images that contain 0 in offset field.\n  const bool isOkOffset = (codeOffset == 0)\n      || (codeOffset == (p[0] == 0xEB ? 2 : 3));\n\n  const unsigned numRootDirEntries = Get16(p + 17);\n  if (numRootDirEntries == 0)\n  {\n    if (codeOffset < 90 && !isOkOffset)\n      return false;\n    NumFatBits = 32;\n    NumRootDirSectors = 0;\n  }\n  else\n  {\n    // Some FAT12s don't contain VolFields\n    if (codeOffset < 62 - 24 && !isOkOffset)\n      return false;\n    NumFatBits = 0;\n    const unsigned mask = (1u << (SectorSizeLog - 5)) - 1;\n    if (numRootDirEntries & mask)\n      return false;\n    NumRootDirSectors = (numRootDirEntries /* + mask */) >> (SectorSizeLog - 5);\n  }\n\n  NumSectors = Get16(p + 19);\n  if (NumSectors == 0)\n    NumSectors = Get32(p + 32);\n  /*\n  // mkfs.fat could create fat32 image with 16-bit number of sectors.\n  // v23: we allow 16-bit value for number of sectors in fat32.\n  else if (IsFat32())\n    return false;\n  */\n  MediaType = p[21];\n  NumFatSectors = Get16(p + 22);\n  SectorsPerTrack = Get16(p + 24);\n  NumHeads = Get16(p + 26);\n  NumHiddenSectors = Get32(p + 28);\n\n  // memcpy(OemName, p + 3, 5);\n\n  int curOffset = 36;\n  p += 36;\n  if (IsFat32())\n  {\n    if (NumFatSectors != 0)\n      return false;\n    NumFatSectors = Get32(p);\n    if (NumFatSectors >= (1 << 24))\n      return false;\n\n    Flags = Get16(p + 4);\n    if (Get16(p + 6) != 0)\n      return false;\n    RootCluster = Get32(p + 8);\n    FsInfoSector = Get16(p + 12);\n    for (unsigned i = 16; i < 28; i++)\n      if (p[i] != 0)\n        return false;\n    p += 28;\n    curOffset += 28;\n  }\n\n  // DriveNumber = p[0];\n  VolFieldsDefined = false;\n  if (codeOffset >= curOffset + 3)\n  {\n    VolFieldsDefined = (p[2] == 0x29); // ExtendedBootSig\n    if (VolFieldsDefined)\n    {\n      if (codeOffset < curOffset + 26)\n        return false;\n      VolId = Get32(p + 3);\n      // memcpy(VolName, p + 7, 11);\n      // memcpy(FileSys, p + 18, 8);\n    }\n  }\n\n  if (NumFatSectors == 0)\n    return false;\n  RootDirSector = NumReservedSectors + NumFatSectors * NumFats;\n  DataSector = RootDirSector + NumRootDirSectors;\n  if (NumSectors < DataSector)\n    return false;\n  const UInt32 numDataSectors = NumSectors - DataSector;\n  const UInt32 numClusters = numDataSectors >> SectorsPerClusterLog;\n  \n  BadCluster = 0x0FFFFFF7;\n  // v23: we support unusual (< 0xFFF5) numClusters values in fat32 systems\n  if (NumFatBits != 32)\n  {\n    if (numClusters >= 0xFFF5)\n      return false;\n    NumFatBits = (Byte)(numClusters < 0xFF5 ? 12 : 16);\n    BadCluster &= (((UInt32)1 << NumFatBits) - 1);\n  }\n\n  FatSize = numClusters + 2;\n  if (FatSize > BadCluster)\n    return false;\n  if (CalcFatSizeInSectors() > NumFatSectors)\n  {\n    /* some third-party program can create such FAT image, where\n       size of FAT table (NumFatSectors from headers) is smaller than\n       required value that is calculated from calculated (FatSize) value.\n       Another FAT unpackers probably ignore that error.\n       v23.02: we also ignore that error, and\n       we recalculate (FatSize) value from (NumFatSectors).\n       New (FatSize) will be smaller than original \"full\" (FatSize) value.\n       So we will have some unused clusters at the end of archive.\n    */\n    FatSize = (UInt32)(((UInt64)NumFatSectors << (3 + SectorSizeLog)) / NumFatBits);\n    HeadersWarning = true;\n  }\n  return true;\n}\n\n\n\nclass CItem\n{\n  Z7_CLASS_NO_COPY(CItem)\npublic:\n  UInt32 Size;\n  Byte Attrib;\n  Byte CTime2;\n  UInt16 ADate;\n  CByteBuffer LongName; // if LongName.Size() == 0 : no long name\n                        // if LongName.Size() != 0 : it's NULL terminated UTF16-LE string.\n  char DosName[11];\n  Byte Flags;\n  UInt32 MTime;\n  UInt32 CTime;\n  UInt32 Cluster;\n  Int32 Parent;\n\n  CItem() {}\n\n  // NT uses Flags to store Low Case status\n  bool NameIsLow() const { return (Flags & 0x8) != 0; }\n  bool ExtIsLow() const { return (Flags & 0x10) != 0; }\n  bool IsDir() const { return (Attrib & 0x10) != 0; }\n  void GetShortName(UString &dest) const;\n  void GetName(UString &name) const;\n};\n\n\nstatic char *CopyAndTrim(char *dest, const char *src,\n    unsigned size, unsigned toLower)\n{\n  do\n  {\n    if (src[(size_t)size - 1] != ' ')\n    {\n      const unsigned range = toLower ? 'Z' - 'A' + 1 : 0;\n      do\n      {\n        unsigned c = (Byte)*src++;\n        if ((unsigned)(c - 'A') < range)\n          c += 0x20;\n        *dest++ = (char)c;\n      }\n      while (--size);\n      break;\n    }\n  }\n  while (--size);\n  *dest = 0;\n  return dest;\n}\n\n\nstatic void FatStringToUnicode(UString &dest, const char *s)\n{\n  MultiByteToUnicodeString2(dest, AString(s), CP_OEMCP);\n}\n\nvoid CItem::GetShortName(UString &shortName) const\n{\n  char s[16];\n  char *dest = CopyAndTrim(s, DosName, 8, NameIsLow());\n  *dest++ = '.';\n  char *dest2 = CopyAndTrim(dest, DosName + 8, 3, ExtIsLow());\n  if (dest == dest2)\n    dest[-1] = 0;\n  FatStringToUnicode(shortName, s);\n}\n\n\n\n// numWords != 0\nstatic unsigned ParseLongName(UInt16 *buf, unsigned numWords)\n{\n  unsigned i;\n  for (i = 0; i < numWords; i++)\n  {\n    const unsigned c = buf[i];\n    if (c == 0)\n      break;\n    if (c == 0xFFFF)\n      return 0;\n  }\n  if (i == 0)\n    return 0;\n  buf[i] = 0;\n  numWords -= i;\n  i++;\n  if (numWords > 1)\n  {\n    numWords--;\n    buf += i;\n    do\n      if (*buf++ != 0xFFFF)\n        return 0;\n    while (--numWords);\n  }\n  return i; // it includes NULL terminator\n}\n\n\nvoid CItem::GetName(UString &name) const\n{\n  if (LongName.Size() >= 2)\n  {\n    const Byte * const p = LongName;\n    const unsigned numWords = ((unsigned)LongName.Size() - 2) / 2;\n    wchar_t *dest = name.GetBuf(numWords);\n    for (unsigned i = 0; i < numWords; i++)\n      dest[i] = (wchar_t)Get16(p + (size_t)i * 2);\n    name.ReleaseBuf_SetEnd(numWords);\n  }\n  else\n    GetShortName(name);\n  if (name.IsEmpty()) // it's unexpected\n    name = '_';\n  NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);\n}\n\n\nstatic void GetVolName(const char dosName[11], NWindows::NCOM::CPropVariant &prop)\n{\n  char s[12];\n  CopyAndTrim(s, dosName, 11, false);\n  UString u;\n  FatStringToUnicode(u, AString(s));\n  prop = u;\n}\n\n\nstruct CDatabase\n{\n  CObjectVector<CItem> Items;\n  UInt32 *Fat;\n  CHeader Header;\n  CMyComPtr<IInStream> InStream;\n  IArchiveOpenCallback *OpenCallback;\n  CAlignedBuffer ByteBuf;\n  CByteBuffer LfnBuf;\n\n  UInt32 NumFreeClusters;\n  UInt32 NumDirClusters;\n  UInt64 NumCurUsedBytes;\n  UInt64 PhySize;\n\n  UInt32 Vol_MTime;\n  char VolLabel[11];\n  bool VolItem_Defined;\n\n  CDatabase(): Fat(NULL) {}\n  ~CDatabase() { ClearAndClose(); }\n\n  void Clear();\n  void ClearAndClose();\n  HRESULT OpenProgressFat(bool changeTotal = true);\n  HRESULT OpenProgress();\n\n  void GetItemPath(UInt32 index, UString &s) const;\n  HRESULT Open();\n  HRESULT ReadDir(Int32 parent, UInt32 cluster, unsigned level);\n\n  UInt64 GetHeadersSize() const\n  {\n    return (UInt64)(Header.DataSector + (NumDirClusters << Header.SectorsPerClusterLog)) << Header.SectorSizeLog;\n  }\n  HRESULT SeekToSector(UInt32 sector);\n  HRESULT SeekToCluster(UInt32 cluster) { return SeekToSector(Header.ClusterToSector(cluster)); }\n};\n\n\nHRESULT CDatabase::SeekToSector(UInt32 sector)\n{\n  return InStream_SeekSet(InStream, (UInt64)sector << Header.SectorSizeLog);\n}\n\nvoid CDatabase::Clear()\n{\n  PhySize = 0;\n  VolItem_Defined = false;\n  NumDirClusters = 0;\n  NumCurUsedBytes = 0;\n\n  Items.Clear();\n  delete []Fat;\n  Fat = NULL;\n}\n\nvoid CDatabase::ClearAndClose()\n{\n  Clear();\n  InStream.Release();\n}\n\nHRESULT CDatabase::OpenProgressFat(bool changeTotal)\n{\n  if (!OpenCallback)\n    return S_OK;\n  if (changeTotal)\n  {\n    const UInt64 numTotalBytes = (Header.CalcFatSizeInSectors() << Header.SectorSizeLog) +\n        ((UInt64)(Header.FatSize - NumFreeClusters) << Header.ClusterSizeLog);\n    RINOK(OpenCallback->SetTotal(NULL, &numTotalBytes))\n  }\n  return OpenCallback->SetCompleted(NULL, &NumCurUsedBytes);\n}\n\nHRESULT CDatabase::OpenProgress()\n{\n  if (!OpenCallback)\n    return S_OK;\n  const UInt64 numItems = Items.Size();\n  return OpenCallback->SetCompleted(&numItems, &NumCurUsedBytes);\n}\n\nvoid CDatabase::GetItemPath(UInt32 index, UString &s) const\n{\n  UString name;\n  for (;;)\n  {\n    const CItem &item = Items[index];\n    item.GetName(name);\n    if (item.Parent >= 0)\n      name.InsertAtFront(WCHAR_PATH_SEPARATOR);\n    s.Insert(0, name);\n    index = (UInt32)item.Parent;\n    if (item.Parent < 0)\n      break;\n  }\n}\n\n\nHRESULT CDatabase::ReadDir(Int32 parent, UInt32 cluster, unsigned level)\n{\n  const unsigned startIndex = Items.Size();\n  if (startIndex >= (1 << 30) || level > 256)\n    return S_FALSE;\n\n  UInt32 blockSize = Header.ClusterSize();\n  const bool clusterMode = (Header.IsFat32() || parent >= 0);\n  if (!clusterMode)\n  {\n    blockSize = Header.SectorSize();\n    RINOK(SeekToSector(Header.RootDirSector))\n  }\n\n  ByteBuf.Alloc(blockSize);\n\n  const unsigned k_NumLfnRecords_MAX = 20; // 260 symbols limit (strict limit)\n  // const unsigned k_NumLfnRecords_MAX = 0x40 - 1; // 1260 symbols limit (relaxed limit)\n  const unsigned k_NumLfnBytes_in_Record = 13 * 2;\n  // we reserve 2 additional bytes for NULL terminator\n  LfnBuf.Alloc(k_NumLfnRecords_MAX * k_NumLfnBytes_in_Record + 2 * 1);\n  \n  UInt32 curDirBytes_read = 0;\n  UInt32 sectorIndex = 0;\n  unsigned num_lfn_records = 0;\n  unsigned lfn_RecordIndex = 0;\n  int checkSum = -1;\n  bool is_record_error = false;\n\n  for (UInt32 pos = blockSize;; pos += 32)\n  {\n    if (pos == blockSize)\n    {\n      pos = 0;\n\n      if (clusterMode)\n      {\n        if (Header.IsEoc(cluster))\n          break;\n        if (!Header.IsValidCluster(cluster))\n          return S_FALSE;\n        PRF(printf(\"\\nCluster = %4X\", cluster));\n        RINOK(SeekToCluster(cluster))\n        const UInt32 newCluster = Fat[cluster];\n        if (newCluster & kFatItemUsedByDirMask)\n          return S_FALSE;\n        Fat[cluster] |= kFatItemUsedByDirMask;\n        cluster = newCluster;\n        NumDirClusters++;\n        if ((NumDirClusters & 0xFF) == 0)\n        {\n          RINOK(OpenProgress())\n        }\n        NumCurUsedBytes += Header.ClusterSize();\n      }\n      else if (sectorIndex++ >= Header.NumRootDirSectors)\n        break;\n      \n      // if (curDirBytes_read > (1u << 28)) // do we need some relaxed limit for non-MS FATs?\n      if (curDirBytes_read >= (1u << 21)) // 2MB limit from FAT specification.\n        return S_FALSE;\n      RINOK(ReadStream_FALSE(InStream, ByteBuf, blockSize))\n      curDirBytes_read += blockSize;\n    }\n  \n    if (is_record_error)\n    {\n      Header.HeadersWarning = true;\n      num_lfn_records = 0;\n      lfn_RecordIndex = 0;\n      checkSum = -1;\n    }\n\n    const Byte * const p = ByteBuf + pos;\n   \n    if (p[0] == 0)\n    {\n      /*\n      // FreeDOS formats FAT partition with cluster chain longer than required.\n      if (clusterMode && !Header.IsEoc(cluster))\n        return S_FALSE;\n      */\n      break;\n    }\n\n    is_record_error = true;\n\n    if (p[0] == 0xE5)\n    {\n      // deleted entry\n      if (num_lfn_records == 0)\n        is_record_error = false;\n      continue;\n    }\n    // else\n    {\n      const Byte attrib = p[11];\n      // maybe we can use more strick check : (attrib == 0xF) ?\n      if ((attrib & 0x3F) == 0xF)\n      {\n        // long file name (LFN) entry\n        const unsigned longIndex = p[0] & 0x3F;\n        if (longIndex == 0\n            || longIndex > k_NumLfnRecords_MAX\n            || p[0] > 0x7F\n            || Get16a(p + 26) != 0 // LDIR_FstClusLO\n            )\n        {\n          return S_FALSE;\n          // break;\n        }\n        const bool isLast = (p[0] & 0x40) != 0;\n        if (num_lfn_records == 0)\n        {\n          if (!isLast)\n            continue; // orphan\n          num_lfn_records = longIndex;\n        }\n        else if (isLast || longIndex != lfn_RecordIndex)\n        {\n          return S_FALSE;\n          // break;\n        }\n        \n        lfn_RecordIndex = longIndex - 1;\n        \n        if (p[12] == 0)\n        {\n          Byte * const dest = LfnBuf + k_NumLfnBytes_in_Record * lfn_RecordIndex;\n          memcpy(dest,          p +  1, 5 * 2);\n          memcpy(dest +  5 * 2, p + 14, 6 * 2);\n          memcpy(dest + 11 * 2, p + 28, 2 * 2);\n          if (isLast)\n            checkSum = p[13];\n          if (checkSum == p[13])\n            is_record_error = false;\n          // else return S_FALSE;\n          continue;\n        }\n        // else\n        checkSum = -1; // we will ignore LfnBuf in this case\n        continue;\n      }\n      \n      if (lfn_RecordIndex)\n      {\n        Header.HeadersWarning = true;\n        // return S_FALSE;\n      }\n      // lfn_RecordIndex = 0;\n\n      const unsigned type_in_attrib = attrib & 0x18;\n      if (type_in_attrib == 0x18)\n      {\n        // invalid directory record (both flags are set: dir_flag and volume_flag)\n        return S_FALSE;\n        // break;\n        // continue;\n      }\n      if (type_in_attrib == 8) // volume_flag\n      {\n        if (!VolItem_Defined && level == 0)\n        {\n          VolItem_Defined = true;\n          memcpy(VolLabel, p, 11);\n          Vol_MTime = Get32(p + 22);\n          is_record_error = false;\n        }\n      }\n      else if (memcmp(p, \".          \", 11) == 0\n            || memcmp(p, \"..         \", 11) == 0)\n      {\n        if (num_lfn_records == 0 && type_in_attrib == 0x10) // dir_flag\n          is_record_error = false;\n      }\n      else\n      {\n        CItem &item = Items.AddNew();\n        memcpy(item.DosName, p, 11);\n        if (item.DosName[0] == 5)\n          item.DosName[0] = (char)(Byte)0xE5; // 0xE5 is valid KANJI lead byte value.\n        item.Attrib = attrib;\n        item.Flags = p[12];\n        item.Size = Get32a(p + 28);\n        item.Cluster = Get16a(p + 26);\n        if (Header.NumFatBits > 16)\n          item.Cluster |= ((UInt32)Get16a(p + 20) << 16);\n        else\n        {\n          // OS/2 and WinNT probably can store EA (extended atributes) in that field.\n        }\n        item.CTime = Get32(p + 14);\n        item.CTime2 = p[13];\n        item.ADate = Get16a(p + 18);\n        item.MTime = Get32(p + 22);\n        item.Parent = parent;\n        {\n          if (!item.IsDir())\n            NumCurUsedBytes += Header.GetFilePackSize(item.Size);\n          // PRF(printf(\"\\n%7d: %S\", Items.Size(), GetItemPath(Items.Size() - 1)));\n          PRF(printf(\"\\n%7d\" /* \": %S\" */, Items.Size() /* , item.GetShortName() */ );)\n        }\n        if (num_lfn_records == 0)\n          is_record_error = false;\n        else if (checkSum >= 0 && lfn_RecordIndex == 0)\n        {\n          Byte sum = 0;\n          for (unsigned i = 0; i < 11; i++)\n            sum = (Byte)((sum << 7) + (sum >> 1) + (Byte)item.DosName[i]);\n          if (sum == checkSum)\n          {\n            const unsigned numWords = ParseLongName((UInt16 *)(void *)(Byte *)LfnBuf,\n                num_lfn_records * k_NumLfnBytes_in_Record / 2);\n            if (numWords > 1)\n            {\n              // numWords includes NULL terminator\n              item.LongName.CopyFrom(LfnBuf, numWords * 2);\n              is_record_error = false;\n            }\n          }\n        }\n        \n        if (\n            // item.LongName.Size() < 20 ||  // for debug\n            item.LongName.Size() <= 2 * 1\n            && memcmp(p, \"           \", 11) == 0)\n        {\n          char s[16 + 16];\n          const size_t numChars = (size_t)(ConvertUInt32ToString(\n              Items.Size() - 1 - startIndex,\n              MyStpCpy(s, \"[NONAME]-\")) - s) + 1;\n          item.LongName.Alloc(numChars * 2);\n          for (size_t i = 0; i < numChars; i++)\n          {\n            SetUi16a(item.LongName + i * 2, (Byte)s[i])\n          }\n          Header.HeadersWarning = true;\n        }\n      }\n      num_lfn_records = 0;\n    }\n  }\n\n  if (is_record_error)\n    Header.HeadersWarning = true;\n\n  const unsigned finishIndex = Items.Size();\n  for (unsigned i = startIndex; i < finishIndex; i++)\n  {\n    const CItem &item = Items[i];\n    if (item.IsDir())\n    {\n      PRF(printf(\"\\n---- %c%c%c%c%c\", item.DosName[0], item.DosName[1], item.DosName[2], item.DosName[3], item.DosName[4]));\n      RINOK(ReadDir((int)i, item.Cluster, level + 1))\n    }\n  }\n  return S_OK;\n}\n\n\n\nHRESULT CDatabase::Open()\n{\n  Clear();\n  bool numFreeClusters_Defined = false;\n  {\n    UInt32 buf32[kHeaderSize / 4];\n    RINOK(ReadStream_FALSE(InStream, buf32, kHeaderSize))\n    if (!Header.Parse((Byte *)(void *)buf32))\n      return S_FALSE;\n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(InStream, fileSize))\n\n    /* we comment that check to support truncated images */\n    /*\n    if (fileSize < Header.GetPhySize())\n      return S_FALSE;\n    */\n\n    if (Header.IsFat32())\n    {\n      if (((UInt32)Header.FsInfoSector << Header.SectorSizeLog) + kHeaderSize <= fileSize\n          && SeekToSector(Header.FsInfoSector) == S_OK\n          && ReadStream_FALSE(InStream, buf32, kHeaderSize) == S_OK\n          && 0xaa550000 == Get32a(buf32 + 508 / 4)\n          && 0x41615252 == Get32a(buf32)\n          && 0x61417272 == Get32a(buf32 + 484 / 4))\n      {\n        NumFreeClusters = Get32a(buf32 + 488 / 4);\n        numFreeClusters_Defined = (NumFreeClusters <= Header.FatSize);\n      }\n      else\n        Header.HeadersWarning = true;\n    }\n  }\n\n  // numFreeClusters_Defined = false; // to recalculate NumFreeClusters\n  if (!numFreeClusters_Defined)\n    NumFreeClusters = 0;\n\n  CByteBuffer byteBuf;\n  Fat = new UInt32[Header.FatSize];\n\n  RINOK(OpenProgressFat())\n  RINOK(SeekToSector(Header.GetFatSector()))\n  if (Header.NumFatBits == 32)\n  {\n    const UInt32 kBufSize = 1 << 15;\n    byteBuf.Alloc(kBufSize);\n    for (UInt32 i = 0;;)\n    {\n      UInt32 size = Header.FatSize - i;\n      if (size == 0)\n        break;\n      const UInt32 kBufSize32 = kBufSize / 4;\n      if (size > kBufSize32)\n        size = kBufSize32;\n      const UInt32 readSize = Header.SizeToSectors(size * 4) << Header.SectorSizeLog;\n      RINOK(ReadStream_FALSE(InStream, byteBuf, readSize))\n      NumCurUsedBytes += readSize;\n\n      const UInt32 *src = (const UInt32 *)(const void *)(const Byte *)byteBuf;\n      UInt32 *dest = Fat + i;\n      const UInt32 *srcLim = src + size;\n      if (numFreeClusters_Defined)\n        do\n          *dest++ = Get32a(src) & 0x0FFFFFFF;\n        while (++src != srcLim);\n      else\n      {\n        UInt32 numFreeClusters = 0;\n        do\n        {\n          const UInt32 v = Get32a(src) & 0x0FFFFFFF;\n          *dest++ = v;\n          numFreeClusters += (UInt32)(v - 1) >> 31;\n        }\n        while (++src != srcLim);\n        NumFreeClusters += numFreeClusters;\n      }\n      i += size;\n      if ((i & 0xFFFFF) == 0)\n      {\n        RINOK(OpenProgressFat(!numFreeClusters_Defined))\n      }\n    }\n  }\n  else\n  {\n    const UInt32 kBufSize = (UInt32)Header.CalcFatSizeInSectors() << Header.SectorSizeLog;\n    NumCurUsedBytes += kBufSize;\n    byteBuf.Alloc(kBufSize);\n    Byte *p = byteBuf;\n    RINOK(ReadStream_FALSE(InStream, p, kBufSize))\n    const UInt32 fatSize = Header.FatSize;\n    UInt32 *fat = &Fat[0];\n    if (Header.NumFatBits == 16)\n      for (UInt32 j = 0; j < fatSize; j++)\n        fat[j] = Get16a(p + j * 2);\n    else\n      for (UInt32 j = 0; j < fatSize; j++)\n        fat[j] = (Get16(p + j * 3 / 2) >> ((j & 1) << 2)) & 0xFFF;\n\n    if (!numFreeClusters_Defined)\n    {\n      UInt32 numFreeClusters = 0;\n      for (UInt32 i = 0; i < fatSize; i++)\n        numFreeClusters += (UInt32)(fat[i] - 1) >> 31;\n      NumFreeClusters = numFreeClusters;\n    }\n  }\n\n  RINOK(OpenProgressFat())\n\n  if ((Fat[0] & 0xFF) != Header.MediaType)\n  {\n    // that case can mean error in FAT,\n    // but xdf file: (MediaType == 0xF0 && Fat[0] == 0xFF9)\n    // 19.00: so we use non-strict check\n    if ((Fat[0] & 0xFF) < 0xF0)\n      return S_FALSE;\n  }\n\n  RINOK(ReadDir(-1, Header.RootCluster, 0))\n\n  PhySize = Header.GetPhySize();\n  return S_OK;\n}\n\n\n\nZ7_class_CHandler_final:\n  public IInArchive,\n  public IArchiveGetRawProps,\n  public IInArchiveGetStream,\n  public CMyUnknownImp,\n  CDatabase\n{\n  Z7_IFACES_IMP_UNK_3(IInArchive, IArchiveGetRawProps, IInArchiveGetStream)\n};\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  const CItem &item = Items[index];\n  CClusterInStream *streamSpec = new CClusterInStream;\n  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\n  streamSpec->Stream = InStream;\n  streamSpec->StartOffset = Header.DataSector << Header.SectorSizeLog;\n  streamSpec->BlockSizeLog = Header.ClusterSizeLog;\n  streamSpec->Size = item.Size;\n\n  const UInt32 numClusters = Header.GetNumClusters(item.Size);\n  streamSpec->Vector.ClearAndReserve(numClusters);\n  UInt32 cluster = item.Cluster;\n  UInt32 size = item.Size;\n\n  if (size == 0)\n  {\n    if (cluster != 0)\n      return S_FALSE;\n  }\n  else\n  {\n    const UInt32 clusterSize = Header.ClusterSize();\n    for (;; size -= clusterSize)\n    {\n      if (!Header.IsValidCluster(cluster))\n        return S_FALSE;\n      streamSpec->Vector.AddInReserved(cluster - 2);\n      cluster = Fat[cluster];\n      if (size <= clusterSize)\n        break;\n    }\n    if (!Header.IsEocAndUnused(cluster))\n      return S_FALSE;\n  }\n  RINOK(streamSpec->InitAndSeek())\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidAttrib,\n  kpidShortName\n  // , kpidCharacts\n};\n\nenum\n{\n  kpidNumFats = kpidUserDefined\n  // kpidOemName,\n  // kpidVolName,\n  // kpidFileSysType\n};\n\nstatic const CStatProp kArcProps[] =\n{\n  { NULL, kpidFileSystem, VT_BSTR},\n  { NULL, kpidClusterSize, VT_UI4},\n  { NULL, kpidFreeSpace, VT_UI8},\n  { NULL, kpidHeadersSize, VT_UI8},\n  { NULL, kpidMTime, VT_FILETIME},\n  { NULL, kpidVolumeName, VT_BSTR},\n\n  { \"FATs\", kpidNumFats, VT_UI4},\n  { NULL, kpidSectorSize, VT_UI4},\n  { NULL, kpidId, VT_UI4},\n  // { \"OEM Name\", kpidOemName, VT_BSTR},\n  // { \"Volume Name\", kpidVolName, VT_BSTR},\n  // { \"File System Type\", kpidFileSysType, VT_BSTR}\n  // { NULL, kpidSectorsPerTrack, VT_UI4},\n  // { NULL, kpidNumHeads, VT_UI4},\n  // { NULL, kpidHiddenSectors, VT_UI4}\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\n\nstatic void FatTimeToProp(UInt32 dosTime, UInt32 ms10, NWindows::NCOM::CPropVariant &prop)\n{\n  FILETIME localFileTime, utc;\n  if (NWindows::NTime::DosTime_To_FileTime(dosTime, localFileTime))\n    if (LocalFileTimeToFileTime(&localFileTime, &utc))\n    {\n      UInt64 t64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime;\n      t64 += ms10 * 100000;\n      utc.dwLowDateTime = (DWORD)t64;\n      utc.dwHighDateTime = (DWORD)(t64 >> 32);\n      prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_Base + 2);\n    }\n}\n\n/*\nstatic void StringToProp(const Byte *src, unsigned size, NWindows::NCOM::CPropVariant &prop)\n{\n  char dest[32];\n  memcpy(dest, src, size);\n  dest[size] = 0;\n  prop = FatStringToUnicode(dest);\n}\n\n#define STRING_TO_PROP(s, p) StringToProp(s, sizeof(s), prop)\n*/\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidFileSystem:\n    {\n      char s[16];\n      s[0] = 'F';\n      s[1] = 'A';\n      s[2] = 'T';\n      ConvertUInt32ToString(Header.NumFatBits, s + 3);\n      prop = s;\n      break;\n    }\n    case kpidClusterSize: prop = Header.ClusterSize(); break;\n    case kpidPhySize: prop = PhySize; break;\n    case kpidFreeSpace: prop = (UInt64)NumFreeClusters << Header.ClusterSizeLog; break;\n    case kpidHeadersSize: prop = GetHeadersSize(); break;\n    case kpidMTime: if (VolItem_Defined) PropVariant_SetFrom_DosTime(prop, Vol_MTime); break;\n    case kpidShortComment:\n    case kpidVolumeName: if (VolItem_Defined) GetVolName(VolLabel, prop); break;\n    case kpidNumFats: if (Header.NumFats != 2) prop = Header.NumFats; break;\n    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;\n    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;\n    // case kpidNumHeads: prop = Header.NumHeads; break;\n    // case kpidOemName: STRING_TO_PROP(Header.OemName, prop); break;\n    case kpidId: if (Header.VolFieldsDefined) prop = Header.VolId; break;\n    case kpidIsTree: prop = true; break;\n    // case kpidVolName: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.VolName, prop); break;\n    // case kpidFileSysType: if (Header.VolFieldsDefined) STRING_TO_PROP(Header.FileSys, prop); break;\n    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;\n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      if (Header.HeadersWarning) v |= kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */ , BSTR *name, PROPID *propID))\n{\n  *name = NULL;\n  *propID = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  *parentType = NParentType::kDir;\n  int par = -1;\n  if (index < Items.Size())\n    par = Items[index].Parent;\n  *parent = (UInt32)(Int32)par;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n\n  if (index < Items.Size()\n      && propID == kpidName)\n  {\n    CByteBuffer &buf = Items[index].LongName;\n    const UInt32 size = (UInt32)buf.Size();\n    if (size != 0)\n    {\n      *dataSize = size;\n      *propType = NPropDataType::kUtf16z;\n      *data = (const void *)(const Byte *)buf;\n    }\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CItem &item = Items[index];\n  switch (propID)\n  {\n    case kpidPath:\n    case kpidName:\n    case kpidShortName:\n    {\n      UString s;\n      if (propID == kpidPath)\n        GetItemPath(index, s);\n      else if (propID == kpidName)\n        item.GetName(s);\n      else\n        item.GetShortName(s);\n      prop = s;\n      break;\n    }\n/*\n    case kpidCharacts:\n    {\n      if (item.LongName.Size())\n        prop = \"LFN\";\n      break;\n    }\n*/\n    case kpidIsDir: prop = item.IsDir(); break;\n    case kpidMTime: PropVariant_SetFrom_DosTime(prop, item.MTime); break;\n    case kpidCTime: FatTimeToProp(item.CTime, item.CTime2, prop); break;\n    case kpidATime: PropVariant_SetFrom_DosTime(prop, ((UInt32)item.ADate << 16)); break;\n    case kpidAttrib: prop = (UInt32)item.Attrib; break;\n    case kpidSize: if (!item.IsDir()) prop = item.Size; break;\n    case kpidPackSize: if (!item.IsDir()) prop = Header.GetFilePackSize(item.Size); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    OpenCallback = callback;\n    InStream = stream;\n    HRESULT res;\n    try\n    {\n      res = CDatabase::Open();\n      if (res == S_OK)\n        return S_OK;\n    }\n    catch(...)\n    {\n      Close();\n      throw;\n    }\n    Close();\n    return res;\n  }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  ClearAndClose();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == (UInt32)(Int32)-1)\n  {\n    indices = NULL;\n    numItems = Items.Size();\n    if (numItems == 0)\n      return S_OK;\n  }\n  else\n  {\n    if (numItems == 0)\n      return S_OK;\n    if (!indices)\n      return E_INVALIDARG;\n  }\n  UInt64 totalSize = 0;\n  {\n    UInt32 i = 0;\n    do\n    {\n      UInt32 index = i;\n      if (indices)\n        index = indices[i];\n      const CItem &item = Items[index];\n      if (!item.IsDir())\n        totalSize += item.Size;\n    }\n    while (++i != numItems);\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  UInt64 totalPackSize;\n  totalSize = totalPackSize = 0;\n\n  UInt32 i;\n  for (i = 0;; i++)\n  {\n    lps->InSize = totalPackSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i == numItems)\n      break;\n    int res;\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      const Int32 askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      UInt32 index = i;\n      if (indices)\n        index = indices[i];\n      const CItem &item = Items[index];\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n        \n      if (item.IsDir())\n      {\n        RINOK(extractCallback->PrepareOperation(askMode))\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        continue;\n      }\n      \n      totalPackSize += Header.GetFilePackSize(item.Size);\n      totalSize += item.Size;\n      \n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      res = NExtract::NOperationResult::kDataError;\n      CMyComPtr<ISequentialInStream> inStream;\n      const HRESULT hres = GetStream(index, &inStream);\n      if (hres != S_FALSE)\n      {\n        RINOK(hres)\n        if (inStream)\n        {\n          RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n          if (copyCoder->TotalSize == item.Size)\n            res = NExtract::NOperationResult::kOK;\n        }\n      }\n    }\n    RINOK(extractCallback->SetOperationResult(res))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = Items.Size();\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = { 0x55, 0xAA };\n\nREGISTER_ARC_I(\n  \"FAT\", \"fat img\", NULL, 0xDA,\n  k_Signature,\n  0x1FE,\n  0,\n  IsArc_Fat)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/FlvHandler.cpp",
    "content": "﻿// FlvHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/InBuffer.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#define GetBe24(p) ( \\\n    ((UInt32)((const Byte *)(p))[0] << 16) | \\\n    ((UInt32)((const Byte *)(p))[1] <<  8) | \\\n             ((const Byte *)(p))[2] )\n\n// #define Get16(p) GetBe16(p)\n#define Get24(p) GetBe24(p)\n#define Get32(p) GetBe32(p)\n\nnamespace NArchive {\nnamespace NFlv {\n\n// static const UInt32 kFileSizeMax = (UInt32)1 << 30;\nstatic const UInt32 kNumChunksMax = (UInt32)1 << 23;\n\nstatic const UInt32 kTagHeaderSize = 11;\n\nstatic const Byte kFlag_Video = 1;\nstatic const Byte kFlag_Audio = 4;\n\nstatic const Byte kType_Audio = 8;\nstatic const Byte kType_Video = 9;\nstatic const Byte kType_Meta = 18;\nstatic const unsigned kNumTypes = 19;\n\nstruct CItem\n{\n  CByteBuffer Data;\n  Byte Type;\n};\n\nstruct CItem2\n{\n  Byte Type;\n  Byte SubType;\n  Byte Props;\n  bool SameSubTypes;\n  unsigned NumChunks;\n  size_t Size;\n\n  CReferenceBuf *BufSpec;\n  CMyComPtr<IUnknown> RefBuf;\n\n  bool IsAudio() const { return Type == kType_Audio; }\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CMyComPtr<IInStream> _stream;\n  CObjectVector<CItem2> _items2;\n  CByteBuffer _metadata;\n  bool _isRaw;\n  UInt64 _phySize;\n\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);\n  // AString GetComment();\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidNumBlocks,\n  kpidComment\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nstatic const char * const g_AudioTypes[16] =\n{\n    \"pcm\"\n  , \"adpcm\"\n  , \"mp3\"\n  , \"pcm_le\"\n  , \"nellymoser16\"\n  , \"nellymoser8\"\n  , \"nellymoser\"\n  , \"g711a\"\n  , \"g711m\"\n  , \"audio9\"\n  , \"aac\"\n  , \"speex\"\n  , \"audio12\"\n  , \"audio13\"\n  , \"mp3\"\n  , \"audio15\"\n};\n\nstatic const char * const g_VideoTypes[16] =\n{\n    \"video0\"\n  , \"jpeg\"\n  , \"h263\"\n  , \"screen\"\n  , \"vp6\"\n  , \"vp6alpha\"\n  , \"screen2\"\n  , \"avc\"\n  , \"video8\"\n  , \"video9\"\n  , \"video10\"\n  , \"video11\"\n  , \"video12\"\n  , \"video13\"\n  , \"video14\"\n  , \"video15\"\n};\n\nstatic const char * const g_Rates[4] =\n{\n    \"5.5 kHz\"\n  , \"11 kHz\"\n  , \"22 kHz\"\n  , \"44 kHz\"\n};\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  const CItem2 &item = _items2[index];\n  switch (propID)\n  {\n    case kpidExtension:\n      prop = _isRaw ?\n        (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) :\n        (item.IsAudio() ? \"audio.flv\" : \"video.flv\");\n      break;\n    case kpidSize:\n    case kpidPackSize:\n      prop = (UInt64)item.Size;\n      break;\n    case kpidNumBlocks: prop = (UInt32)item.NumChunks; break;\n    case kpidComment:\n    {\n      char sz[64];\n      char *s = MyStpCpy(sz, (item.IsAudio() ? g_AudioTypes[item.SubType] : g_VideoTypes[item.SubType]) );\n      if (item.IsAudio())\n      {\n        *s++ = ' ';\n        s = MyStpCpy(s, g_Rates[(item.Props >> 2) & 3]);\n        s = MyStpCpy(s, (item.Props & 2) ? \" 16-bit\" : \" 8-bit\");\n        s = MyStpCpy(s, (item.Props & 1) ? \" stereo\" : \" mono\");\n      }\n      prop = sz;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n/*\nAString CHandler::GetComment()\n{\n  const Byte *p = _metadata;\n  size_t size = _metadata.Size();\n  AString res;\n  if (size > 0)\n  {\n    p++;\n    size--;\n    for (;;)\n    {\n      if (size < 2)\n        break;\n      int len = Get16(p);\n      p += 2;\n      size -= 2;\n      if (len == 0 || (size_t)len > size)\n        break;\n      {\n        AString temp;\n        temp.SetFrom_CalcLen((const char *)p, len);\n        if (!res.IsEmpty())\n          res += '\\n';\n        res += temp;\n      }\n      p += len;\n      size -= len;\n      if (size < 1)\n        break;\n      Byte type = *p++;\n      size--;\n      bool ok = false;\n      switch (type)\n      {\n        case 0:\n        {\n          if (size < 8)\n            break;\n          ok = true;\n          Byte reverse[8];\n          for (int i = 0; i < 8; i++)\n          {\n            bool little_endian = 1;\n            if (little_endian)\n              reverse[i] = p[7 - i];\n            else\n              reverse[i] = p[i];\n          }\n          double d = *(double *)reverse;\n          char temp[32];\n          sprintf(temp, \" = %.3f\", d);\n          res += temp;\n          p += 8;\n          size -= 8;\n          break;\n        }\n        case 8:\n        {\n          if (size < 4)\n            break;\n          ok = true;\n          // UInt32 numItems = Get32(p);\n          p += 4;\n          size -= 4;\n          break;\n        }\n      }\n      if (!ok)\n        break;\n    }\n  }\n  return res;\n}\n*/\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  // COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    // case kpidComment: prop = GetComment(); break;\n    case kpidPhySize: prop = (UInt64)_phySize; break;\n    case kpidIsNotArcType: prop = true; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  // COM_TRY_END\n}\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)\n{\n  const UInt32 kHeaderSize = 13;\n  Byte header[kHeaderSize];\n  RINOK(ReadStream_FALSE(stream, header, kHeaderSize))\n  if (header[0] != 'F' ||\n      header[1] != 'L' ||\n      header[2] != 'V' ||\n      header[3] != 1 ||\n      (header[4] & 0xFA) != 0)\n    return S_FALSE;\n  UInt64 offset = Get32(header + 5);\n  if (offset != 9 || Get32(header + 9) != 0)\n    return S_FALSE;\n  offset = kHeaderSize;\n \n  CInBuffer inBuf;\n  if (!inBuf.Create(1 << 15))\n    return E_OUTOFMEMORY;\n  inBuf.SetStream(stream);\n\n  CObjectVector<CItem> items;\n  int lasts[kNumTypes];\n  unsigned i;\n  for (i = 0; i < kNumTypes; i++)\n    lasts[i] = -1;\n\n  _phySize = offset;\n  for (;;)\n  {\n    Byte buf[kTagHeaderSize];\n    CItem item;\n    if (inBuf.ReadBytes(buf, kTagHeaderSize) != kTagHeaderSize)\n      break;\n    item.Type = buf[0];\n    UInt32 size = Get24(buf + 1);\n    if (size < 1)\n      break;\n    // item.Time = Get24(buf + 4);\n    // item.Time |= (UInt32)buf[7] << 24;\n    if (Get24(buf + 8) != 0) // streamID\n      break;\n\n    UInt32 curSize = kTagHeaderSize + size + 4;\n    item.Data.Alloc(curSize);\n    memcpy(item.Data, buf, kTagHeaderSize);\n    if (inBuf.ReadBytes(item.Data + kTagHeaderSize, size) != size)\n      break;\n    if (inBuf.ReadBytes(item.Data + kTagHeaderSize + size, 4) != 4)\n      break;\n\n    if (Get32(item.Data + kTagHeaderSize + size) != kTagHeaderSize + size)\n      break;\n\n    offset += curSize;\n    \n    // printf(\"\\noffset = %6X type = %2d time = %6d size = %6d\", (UInt32)offset, item.Type, item.Time, item.Size);\n\n    if (item.Type == kType_Meta)\n    {\n      // _metadata = item.Buf;\n    }\n    else\n    {\n      if (item.Type != kType_Audio && item.Type != kType_Video)\n        break;\n      if (items.Size() >= kNumChunksMax)\n        return S_FALSE;\n      Byte firstByte = item.Data[kTagHeaderSize];\n      Byte subType, props;\n      if (item.Type == kType_Audio)\n      {\n        subType = (Byte)(firstByte >> 4);\n        props = (Byte)(firstByte & 0xF);\n      }\n      else\n      {\n        subType = (Byte)(firstByte & 0xF);\n        props = (Byte)(firstByte >> 4);\n      }\n      int last = lasts[item.Type];\n      if (last < 0)\n      {\n        CItem2 item2;\n        item2.RefBuf = item2.BufSpec = new CReferenceBuf;\n        item2.Size = curSize;\n        item2.Type = item.Type;\n        item2.SubType = subType;\n        item2.Props = props;\n        item2.NumChunks = 1;\n        item2.SameSubTypes = true;\n        lasts[item.Type] = (int)_items2.Add(item2);\n      }\n      else\n      {\n        CItem2 &item2 = _items2[last];\n        if (subType != item2.SubType)\n          item2.SameSubTypes = false;\n        item2.Size += curSize;\n        item2.NumChunks++;\n      }\n      items.Add(item);\n    }\n    _phySize = offset;\n    if (callback && (items.Size() & 0xFF) == 0)\n    {\n      RINOK(callback->SetCompleted(NULL, &offset))\n    }\n  }\n  if (items.IsEmpty())\n    return S_FALSE;\n\n  _isRaw = (_items2.Size() == 1);\n  for (i = 0; i < _items2.Size(); i++)\n  {\n    CItem2 &item2 = _items2[i];\n    CByteBuffer &itemBuf = item2.BufSpec->Buf;\n    if (_isRaw)\n    {\n      if (!item2.SameSubTypes)\n        return S_FALSE;\n      itemBuf.Alloc((size_t)item2.Size - (size_t)(kTagHeaderSize + 4 + 1) * item2.NumChunks);\n      item2.Size = 0;\n    }\n    else\n    {\n      itemBuf.Alloc(kHeaderSize + (size_t)item2.Size);\n      memcpy(itemBuf, header, kHeaderSize);\n      itemBuf[4] = item2.IsAudio() ? kFlag_Audio : kFlag_Video;\n      item2.Size = kHeaderSize;\n    }\n  }\n\n  for (i = 0; i < items.Size(); i++)\n  {\n    const CItem &item = items[i];\n    CItem2 &item2 = _items2[lasts[item.Type]];\n    size_t size = item.Data.Size();\n    const Byte *src = item.Data;\n    if (_isRaw)\n    {\n      src += kTagHeaderSize + 1;\n      size -= (kTagHeaderSize + 4 + 1);\n    }\n    if (size != 0)\n    {\n      memcpy(item2.BufSpec->Buf + item2.Size, src, size);\n      item2.Size += size;\n    }\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  Close();\n  HRESULT res;\n  try\n  {\n    res = Open2(inStream, callback);\n    if (res == S_OK)\n      _stream = inStream;\n  }\n  catch(...) { res = S_FALSE; }\n  if (res != S_OK)\n  {\n    Close();\n    return S_FALSE;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _phySize = 0;\n  _stream.Release();\n  _items2.Clear();\n  // _metadata.SetCapacity(0);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items2.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items2.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _items2[allFilesMode ? i : indices[i]].Size;\n  extractCallback->SetTotal(totalSize);\n\n  totalSize = 0;\n  \n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  for (i = 0; i < numItems; i++)\n  {\n    lps->InSize = lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    CMyComPtr<ISequentialOutStream> outStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem2 &item = _items2[index];\n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n    totalSize += item.Size;\n    if (!testMode && !outStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n    if (outStream)\n    {\n      RINOK(WriteStream(outStream, item.BufSpec->Buf, item.BufSpec->Buf.Size()))\n    }\n    RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  CBufInStream *streamSpec = new CBufInStream;\n  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\n  streamSpec->Init(_items2[index].BufSpec);\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = { 'F', 'L', 'V', 1, };\n\nREGISTER_ARC_I(\n  \"FLV\", \"flv\", NULL, 0xD6,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/GptHandler.cpp",
    "content": "﻿// GptHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/7zCrc.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\nusing namespace NWindows;\n\nnamespace NArchive {\n\nnamespace NMbr {\nconst char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);\n}\n\nnamespace NFat {\nAPI_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);\n}\n\nnamespace NGpt {\n\nstatic const unsigned k_SignatureSize = 12;\nstatic const Byte k_Signature[k_SignatureSize] =\n    { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };\n\nstatic const CUInt32PCharPair g_PartitionFlags[] =\n{\n  { 0, \"Sys\" },\n  { 1, \"Ignore\" },\n  { 2, \"Legacy\" },\n  { 60, \"Win-Read-only\" },\n  { 62, \"Win-Hidden\" },\n  { 63, \"Win-Not-Automount\" }\n};\n\nstatic const unsigned kNameLen = 36;\n\nstruct CPartition\n{\n  Byte Type[16];\n  Byte Id[16];\n  UInt64 FirstLba;\n  UInt64 LastLba;\n  UInt64 Flags;\n  const char *Ext; // detected later\n  Byte Name[kNameLen * 2];\n\n  bool IsUnused() const\n  {\n    for (unsigned i = 0; i < 16; i++)\n      if (Type[i] != 0)\n        return false;\n    return true;\n  }\n\n  UInt64 GetSize(unsigned sectorSizeLog) const { return (LastLba - FirstLba + 1) << sectorSizeLog; }\n  UInt64 GetPos(unsigned sectorSizeLog) const { return FirstLba << sectorSizeLog; }\n  UInt64 GetEnd(unsigned sectorSizeLog) const { return (LastLba + 1) << sectorSizeLog; }\n\n  void Parse(const Byte *p)\n  {\n    memcpy(Type, p, 16);\n    memcpy(Id, p + 16, 16);\n    FirstLba = Get64(p + 32);\n    LastLba = Get64(p + 40);\n    Flags = Get64(p + 48);\n    memcpy(Name, p + 56, kNameLen * 2);\n    Ext = NULL;\n  }\n};\n\n\nstruct CPartType\n{\n  UInt32 Id;\n  const char *Ext;\n  const char *Type;\n};\n\nstatic const CPartType kPartTypes[] =\n{\n  // { 0x0, NULL, \"Unused\" },\n\n  { 0x21686148, NULL, \"BIOS Boot\" },\n\n  { 0xC12A7328, NULL, \"EFI System\" },\n  { 0x024DEE41, NULL, \"MBR\" },\n      \n  { 0xE3C9E316, NULL, \"Windows MSR\" },\n  { 0xEBD0A0A2, NULL, \"Windows BDP\" },\n  { 0x5808C8AA, NULL, \"Windows LDM Metadata\" },\n  { 0xAF9B60A0, NULL, \"Windows LDM Data\" },\n  { 0xDE94BBA4, NULL, \"Windows Recovery\" },\n  // { 0x37AFFC90, NULL, \"IBM GPFS\" },\n  // { 0xE75CAF8F, NULL, \"Windows Storage Spaces\" },\n\n  { 0x0FC63DAF, NULL, \"Linux Data\" },\n  { 0x0657FD6D, NULL, \"Linux Swap\" },\n  { 0x44479540, NULL, \"Linux root (x86)\" },\n  { 0x4F68BCE3, NULL, \"Linux root (x86-64)\" },\n  { 0x69DAD710, NULL, \"Linux root (ARM)\" },\n  { 0xB921B045, NULL, \"Linux root (ARM64)\" },\n  { 0x993D8D3D, NULL, \"Linux root (IA-64)\" },\n  \n\n  { 0x83BD6B9D, NULL, \"FreeBSD Boot\" },\n  { 0x516E7CB4, NULL, \"FreeBSD Data\" },\n  { 0x516E7CB5, NULL, \"FreeBSD Swap\" },\n  { 0x516E7CB6, \"ufs\", \"FreeBSD UFS\" },\n  { 0x516E7CB8, NULL, \"FreeBSD Vinum\" },\n  { 0x516E7CB8, \"zfs\", \"FreeBSD ZFS\" },\n\n  { 0x48465300, \"hfsx\", \"HFS+\" },\n  { 0x7C3457EF, \"apfs\", \"APFS\" },\n};\n\nstatic int FindPartType(const Byte *guid)\n{\n  const UInt32 val = Get32(guid);\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPartTypes); i++)\n    if (kPartTypes[i].Id == val)\n      return (int)i;\n  return -1;\n}\n\n\nstatic void RawLeGuidToString_Upper(const Byte *g, char *s)\n{\n  RawLeGuidToString(g, s);\n  // MyStringUpper_Ascii(s);\n}\n\n\nZ7_class_CHandler_final: public CHandlerCont\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Cont)\n\n  CRecordVector<CPartition> _items;\n  UInt64 _totalSize;\n  unsigned _sectorSizeLog;\n  Byte Guid[16];\n\n  CByteBuffer _buffer;\n\n  HRESULT Open2(IInStream *stream);\n\n  virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override\n  {\n    const CPartition &item = _items[index];\n    pos = item.GetPos(_sectorSizeLog);\n    size = item.GetSize(_sectorSizeLog);\n    return NExtract::NOperationResult::kOK;\n  }\n};\n\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  const unsigned kBufSize = 2 << 12;\n  _buffer.Alloc(kBufSize);\n  RINOK(ReadStream_FALSE(stream, _buffer, kBufSize))\n  const Byte *buf = _buffer;\n  if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)\n    return S_FALSE;\n  {\n    for (unsigned sectorSizeLog = 9;; sectorSizeLog += 3)\n    {\n      if (sectorSizeLog > 12)\n        return S_FALSE;\n      if (memcmp(buf + ((size_t)1 << sectorSizeLog), k_Signature, k_SignatureSize) == 0)\n      {\n        buf += ((size_t)1 << sectorSizeLog);\n        _sectorSizeLog = sectorSizeLog;\n        break;\n      }\n    }\n  }\n  const UInt32 kSectorSize = 1u << _sectorSizeLog;\n  {\n    // if (Get32(buf + 8) != 0x10000) return S_FALSE; // revision\n    const UInt32 headerSize = Get32(buf + 12); // = 0x5C usually\n    if (headerSize > kSectorSize)\n      return S_FALSE;\n    const UInt32 crc = Get32(buf + 0x10);\n    SetUi32(_buffer + kSectorSize + 0x10, 0)\n    if (CrcCalc(_buffer + kSectorSize, headerSize) != crc)\n      return S_FALSE;\n  }\n  // UInt32 reserved = Get32(buf + 0x14);\n  const UInt64 curLba = Get64(buf + 0x18);\n  if (curLba != 1)\n    return S_FALSE;\n  const UInt64 backupLba = Get64(buf + 0x20);\n  // UInt64 firstUsableLba = Get64(buf + 0x28);\n  // UInt64 lastUsableLba = Get64(buf + 0x30);\n  memcpy(Guid, buf + 0x38, 16);\n  const UInt64 tableLba = Get64(buf + 0x48);\n  if (tableLba < 2 || (tableLba >> (63 - _sectorSizeLog)) != 0)\n    return S_FALSE;\n  const UInt32 numEntries = Get32(buf + 0x50);\n  if (numEntries > (1 << 16))\n    return S_FALSE;\n  const UInt32 entrySize = Get32(buf + 0x54); // = 128 usually\n  if (entrySize < 128 || entrySize > (1 << 12))\n    return S_FALSE;\n  const UInt32 entriesCrc = Get32(buf + 0x58);\n  \n  const UInt32 tableSize = entrySize * numEntries;\n  const UInt32 tableSizeAligned = (tableSize + kSectorSize - 1) & ~(kSectorSize - 1);\n  _buffer.Alloc(tableSizeAligned);\n  const UInt64 tableOffset = tableLba * kSectorSize;\n  RINOK(InStream_SeekSet(stream, tableOffset))\n  RINOK(ReadStream_FALSE(stream, _buffer, tableSizeAligned))\n  \n  if (CrcCalc(_buffer, tableSize) != entriesCrc)\n    return S_FALSE;\n  \n  _totalSize = tableOffset + tableSizeAligned;\n  \n  for (UInt32 i = 0; i < numEntries; i++)\n  {\n    CPartition item;\n    item.Parse(_buffer + i * entrySize);\n    if (item.IsUnused())\n      continue;\n    if (item.LastLba < item.FirstLba)\n      return S_FALSE;\n    if ((item.LastLba >> (63 - _sectorSizeLog)) != 0)\n      return S_FALSE;\n    const UInt64 endPos = item.GetEnd(_sectorSizeLog);\n    if (_totalSize < endPos)\n      _totalSize = endPos;\n    _items.Add(item);\n  }\n\n  _buffer.Free();\n  {\n    if ((backupLba >> (63 - _sectorSizeLog)) != 0)\n      return S_FALSE;\n    const UInt64 end = (backupLba + 1) * kSectorSize;\n    if (_totalSize < end)\n      _totalSize = end;\n  }\n  {\n    UInt64 fileEnd;\n    RINOK(InStream_GetSize_SeekToEnd(stream, fileEnd))\n    \n    if (_totalSize < fileEnd)\n    {\n      const UInt64 rem = fileEnd - _totalSize;\n      const UInt64 kRemMax = 1 << 22;\n      if (rem <= kRemMax)\n      {\n        RINOK(InStream_SeekSet(stream, _totalSize))\n        bool areThereNonZeros = false;\n        UInt64 numZeros = 0;\n        if (ReadZeroTail(stream, areThereNonZeros, numZeros, kRemMax) == S_OK)\n          if (!areThereNonZeros)\n            _totalSize += numZeros;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(stream))\n  _stream = stream;\n\n  FOR_VECTOR (fileIndex, _items)\n  {\n    CPartition &item = _items[fileIndex];\n    const int typeIndex = FindPartType(item.Type);\n    if (typeIndex < 0)\n      continue;\n    const CPartType &t = kPartTypes[(unsigned)typeIndex];\n    if (t.Ext)\n    {\n      item.Ext = t.Ext;\n      continue;\n    }\n    if (t.Type && IsString1PrefixedByString2_NoCase_Ascii(t.Type, \"Windows\"))\n    {\n      CMyComPtr<ISequentialInStream> inStream;\n      if (\n          // ((IInArchiveGetStream *)this)->\n          GetStream(fileIndex, &inStream) == S_OK && inStream)\n      {\n        const char *fs = NMbr::GetFileSystem(inStream, item.GetSize(_sectorSizeLog));\n        if (fs)\n          item.Ext = fs;\n      }\n    }\n  }\n\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _sectorSizeLog = 0;\n  _totalSize = 0;\n  memset(Guid, 0, sizeof(Guid));\n  _items.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidFileSystem,\n  kpidCharacts,\n  kpidOffset,\n  kpidId\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidSectorSize,\n  kpidId\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile:\n    {\n      if (_items.Size() == 1)\n        prop = (UInt32)0;\n      break;\n    }\n    case kpidPhySize: prop = _totalSize; break;\n    case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;\n    case kpidId:\n    {\n      char s[48];\n      RawLeGuidToString_Upper(Guid, s);\n      prop = s;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CPartition &item = _items[index];\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      // Windows BDP partitions can have identical names.\n      // So we add the partition number at front\n      UString s;\n      s.Add_UInt32(index);\n      {\n        UString s2;\n        for (unsigned i = 0; i < kNameLen; i++)\n        {\n          wchar_t c = (wchar_t)Get16(item.Name + i * 2);\n          if (c == 0)\n            break;\n          s2 += c;\n        }\n        if (!s2.IsEmpty())\n        {\n          s.Add_Dot();\n          s += s2;\n        }\n      }\n      {\n        s.Add_Dot();\n        if (item.Ext)\n        {\n          AString fs (item.Ext);\n          fs.MakeLower_Ascii();\n          s += fs;\n        }\n        else\n          s += \"img\";\n      }\n      prop = s;\n      break;\n    }\n    \n    case kpidSize:\n    case kpidPackSize: prop = item.GetSize(_sectorSizeLog); break;\n    case kpidOffset: prop = item.GetPos(_sectorSizeLog); break;\n\n    case kpidFileSystem:\n    {\n      char s[48];\n      const char *res;\n      const int typeIndex = FindPartType(item.Type);\n      if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Type)\n        res = kPartTypes[(unsigned)typeIndex].Type;\n      else\n      {\n        RawLeGuidToString_Upper(item.Type, s);\n        res = s;\n      }\n      prop = res;\n      break;\n    }\n\n    case kpidId:\n    {\n      char s[48];\n      RawLeGuidToString_Upper(item.Id, s);\n      prop = s;\n      break;\n    }\n\n    case kpidCharacts: FLAGS64_TO_PROP(g_PartitionFlags, item.Flags, prop); break;\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n// we suppport signature only for 512-bytes sector.\nREGISTER_ARC_I(\n  \"GPT\", \"gpt mbr\", NULL, 0xCB,\n  k_Signature,\n  1 << 9,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/GzHandler.cpp",
    "content": "﻿// GzHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include  <stdio.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/Defs.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/DeflateDecoder.h\"\n#include \"../Compress/DeflateEncoder.h\"\n\n#include \"Common/HandlerOut.h\"\n#include \"Common/InStreamWithCRC.h\"\n#include \"Common/OutStreamWithCRC.h\"\n\n#define Get32(p) GetUi32(p)\n\nusing namespace NWindows;\n\nusing namespace NCompress;\nusing namespace NDeflate;\n\nnamespace NArchive {\nnamespace NGz {\n\n  static const Byte kSignature_0 = 0x1F;\n  static const Byte kSignature_1 = 0x8B;\n  static const Byte kSignature_2 = 8; //  NCompressionMethod::kDeflate\n\n  // Latest versions of gzip program don't write comment field to gz archive.\n  // We also don't write comment field to gz archive.\n\n  namespace NFlags\n  {\n    // const Byte kIsText  = 1 << 0;\n    const Byte kCrc     = 1 << 1;\n    const Byte kExtra   = 1 << 2;\n    const Byte kName    = 1 << 3;\n    const Byte kComment = 1 << 4;\n    const Byte kReserved = 0xE0;\n  }\n  \n  namespace NExtraFlags\n  {\n    const Byte kMaximum = 2;\n    const Byte kFastest = 4;\n  }\n  \n  namespace NHostOS\n  {\n    enum EEnum\n    {\n      kFAT = 0,\n      kAMIGA,\n      kVMS,\n      kUnix,\n      kVM_CMS,\n      kAtari,\n      kHPFS,\n      kMac,\n      kZ_System,\n      kCPM,\n      kTOPS20,\n      kNTFS,\n      kQDOS,\n      kAcorn,\n      kVFAT,\n      kMVS,\n      kBeOS,\n      kTandem,\n      \n      kUnknown = 255\n    };\n  }\n\nstatic const char * const kHostOSes[] =\n{\n    \"FAT\"\n  , \"AMIGA\"\n  , \"VMS\"\n  , \"Unix\"\n  , \"VM/CMS\"\n  , \"Atari\"\n  , \"HPFS\"\n  , \"Macintosh\"\n  , \"Z-System\"\n  , \"CP/M\"\n  , \"TOPS-20\"\n  , \"NTFS\"\n  , \"SMS/QDOS\"\n  , \"Acorn\"\n  , \"VFAT\"\n  , \"MVS\"\n  , \"BeOS\"\n  , \"Tandem\"\n  , \"OS/400\"\n  , \"OS/X\"\n};\n\n\nclass CItem\n{\n  bool TestFlag(Byte flag) const { return (Flags & flag) != 0; }\npublic:\n  Byte Flags;\n  Byte ExtraFlags;\n  Byte HostOS;\n  UInt32 Time;\n  UInt32 Crc;\n  UInt32 Size32;\n\n  AString Name;\n  AString Comment;\n  // CByteBuffer Extra;\n\n  CItem():\n    Flags(0),\n    ExtraFlags(0),\n    HostOS(0),\n    Time(0),\n    Crc(0),\n    Size32(0) {}\n\n  void Clear()\n  {\n    Name.Empty();\n    Comment.Empty();\n    // Extra.Free();\n  }\n\n  void CopyMetaPropsFrom(const CItem &a)\n  {\n    Flags = a.Flags;\n    HostOS = a.HostOS;\n    Time = a.Time;\n    Name = a.Name;\n    Comment = a.Comment;\n    // Extra = a.Extra;\n  }\n\n  void CopyDataPropsFrom(const CItem &a)\n  {\n    ExtraFlags = a.ExtraFlags;\n    Crc = a.Crc;\n    Size32 = a.Size32;\n  }\n  \n  // bool IsText() const { return TestFlag(NFlags::kIsText); }\n  bool HeaderCrcIsPresent() const { return TestFlag(NFlags::kCrc); }\n  bool ExtraFieldIsPresent() const { return TestFlag(NFlags::kExtra); }\n  bool NameIsPresent() const { return TestFlag(NFlags::kName); }\n  bool CommentIsPresent() const { return TestFlag(NFlags::kComment); }\n  bool IsSupported() const { return (Flags & NFlags::kReserved) == 0; }\n\n  HRESULT ReadHeader(NDecoder::CCOMCoder *stream);\n  HRESULT ReadFooter1(NDecoder::CCOMCoder *stream);\n  HRESULT ReadFooter2(ISequentialInStream *stream);\n\n  HRESULT WriteHeader(ISequentialOutStream *stream);\n  HRESULT WriteFooter(ISequentialOutStream *stream);\n};\n\nstatic HRESULT ReadBytes(NDecoder::CCOMCoder *stream, Byte *data, UInt32 size)\n{\n  for (UInt32 i = 0; i < size; i++)\n    data[i] = stream->ReadAlignedByte();\n  return stream->InputEofError() ? S_FALSE : S_OK;\n}\n\nstatic HRESULT SkipBytes(NDecoder::CCOMCoder *stream, UInt32 size)\n{\n  for (UInt32 i = 0; i < size; i++)\n    stream->ReadAlignedByte();\n  return stream->InputEofError() ? S_FALSE : S_OK;\n}\n\nstatic HRESULT ReadUInt16(NDecoder::CCOMCoder *stream, UInt32 &value /* , UInt32 &crc */)\n{\n  value = 0;\n  for (int i = 0; i < 2; i++)\n  {\n    Byte b = stream->ReadAlignedByte();\n    if (stream->InputEofError())\n      return S_FALSE;\n    // crc = CRC_UPDATE_BYTE(crc, b);\n    value |= ((UInt32)(b) << (8 * i));\n  }\n  return S_OK;\n}\n\nstatic HRESULT ReadString(NDecoder::CCOMCoder *stream, AString &s, size_t limit /* , UInt32 &crc */)\n{\n  s.Empty();\n  for (size_t i = 0; i < limit; i++)\n  {\n    const Byte b = stream->ReadAlignedByte();\n    if (stream->InputEofError())\n      return S_FALSE;\n    // crc = CRC_UPDATE_BYTE(crc, b);\n    if (b == 0)\n      return S_OK;\n    s.Add_Char((char)b);\n  }\n  return S_FALSE;\n}\n\nstatic UInt32 Is_Deflate(const Byte *p, size_t size)\n{\n  if (size < 1)\n    return k_IsArc_Res_NEED_MORE;\n  Byte b = *p;\n  p++;\n  size--;\n  unsigned type = ((unsigned)b >> 1) & 3;\n  if (type == 3)\n    return k_IsArc_Res_NO;\n  if (type == 0)\n  {\n    // Stored (uncompreessed data)\n    if ((b >> 3) != 0)\n      return k_IsArc_Res_NO;\n    if (size < 4)\n      return k_IsArc_Res_NEED_MORE;\n    UInt16 r = (UInt16)~GetUi16(p + 2);\n    if (GetUi16(p) != r)\n      return k_IsArc_Res_NO;\n  }\n  else if (type == 2)\n  {\n    // Dynamic Huffman\n    if (size < 1)\n      return k_IsArc_Res_NEED_MORE;\n    if ((*p & 0x1F) + 1 > 30) // numDistLevels\n      return k_IsArc_Res_NO;\n  }\n  return k_IsArc_Res_YES;\n}\n\nstatic const unsigned kNameMaxLen = 1 << 12;\nstatic const unsigned kCommentMaxLen = 1 << 16;\n\nAPI_FUNC_static_IsArc IsArc_Gz(const Byte *p, size_t size)\n{\n  if (size < 10)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != kSignature_0 ||\n      p[1] != kSignature_1 ||\n      p[2] != kSignature_2)\n    return k_IsArc_Res_NO;\n\n  const Byte flags = p[3];\n  if ((flags & NFlags::kReserved) != 0)\n    return k_IsArc_Res_NO;\n\n  const Byte extraFlags = p[8];\n  // maybe that flag can have another values for some gz archives?\n  if (extraFlags != 0 &&\n      extraFlags != NExtraFlags::kMaximum &&\n      extraFlags != NExtraFlags::kFastest)\n    return k_IsArc_Res_NO;\n\n  size -= 10;\n  p += 10;\n\n  if ((flags & NFlags::kExtra) != 0)\n  {\n    if (size < 2)\n      return k_IsArc_Res_NEED_MORE;\n    unsigned xlen = GetUi16(p);\n    size -= 2;\n    p += 2;\n    while (xlen != 0)\n    {\n      if (xlen < 4)\n        return k_IsArc_Res_NO;\n      if (size < 4)\n        return k_IsArc_Res_NEED_MORE;\n      const unsigned len = GetUi16(p + 2);\n      size -= 4;\n      xlen -= 4;\n      p += 4;\n      if (len > xlen)\n        return k_IsArc_Res_NO;\n      if (len > size)\n        return k_IsArc_Res_NEED_MORE;\n      size -= len;\n      xlen -= len;\n      p += len;\n    }\n  }\n\n  if ((flags & NFlags::kName) != 0)\n  {\n    size_t limit = kNameMaxLen;\n    if (limit > size)\n      limit = size;\n    size_t i;\n    for (i = 0; i < limit && p[i] != 0; i++);\n    if (i == size)\n      return k_IsArc_Res_NEED_MORE;\n    if (i == limit)\n      return k_IsArc_Res_NO;\n    i++;\n    p += i;\n    size -= i;\n  }\n\n  if ((flags & NFlags::kComment) != 0)\n  {\n    size_t limit = kCommentMaxLen;\n    if (limit > size)\n      limit = size;\n    size_t i;\n    for (i = 0; i < limit && p[i] != 0; i++);\n    if (i == size)\n      return k_IsArc_Res_NEED_MORE;\n    if (i == limit)\n      return k_IsArc_Res_NO;\n    i++;\n    p += i;\n    size -= i;\n  }\n  \n  if ((flags & NFlags::kCrc) != 0)\n  {\n    if (size < 2)\n      return k_IsArc_Res_NEED_MORE;\n    p += 2;\n    size -= 2;\n  }\n\n  return Is_Deflate(p, size);\n}\n}\n\nHRESULT CItem::ReadHeader(NDecoder::CCOMCoder *stream)\n{\n  Clear();\n\n  // Header-CRC field had another meaning in old version of gzip!\n  // UInt32 crc = CRC_INIT_VAL;\n  Byte buf[10];\n\n  RINOK(ReadBytes(stream, buf, 10))\n  \n  if (buf[0] != kSignature_0 ||\n      buf[1] != kSignature_1 ||\n      buf[2] != kSignature_2)\n    return S_FALSE;\n\n  Flags = buf[3];\n  if (!IsSupported())\n    return S_FALSE;\n\n  Time = Get32(buf + 4);\n  ExtraFlags = buf[8];\n  HostOS = buf[9];\n\n  // crc = CrcUpdate(crc, buf, 10);\n  \n  if (ExtraFieldIsPresent())\n  {\n    UInt32 xlen;\n    RINOK(ReadUInt16(stream, xlen /* , crc */))\n    RINOK(SkipBytes(stream, xlen))\n    // Extra.SetCapacity(xlen);\n    // RINOK(ReadStream_FALSE(stream, Extra, xlen));\n    // crc = CrcUpdate(crc, Extra, xlen);\n  }\n  if (NameIsPresent())\n    RINOK(ReadString(stream, Name, kNameMaxLen /* , crc */))\n  if (CommentIsPresent())\n    RINOK(ReadString(stream, Comment, kCommentMaxLen /* , crc */))\n\n  if (HeaderCrcIsPresent())\n  {\n    UInt32 headerCRC;\n    // UInt32 dummy = 0;\n    RINOK(ReadUInt16(stream, headerCRC /* , dummy */))\n    /*\n    if ((UInt16)CRC_GET_DIGEST(crc) != headerCRC)\n      return S_FALSE;\n    */\n  }\n  return stream->InputEofError() ? S_FALSE : S_OK;\n}\n\nHRESULT CItem::ReadFooter1(NDecoder::CCOMCoder *stream)\n{\n  Byte buf[8];\n  RINOK(ReadBytes(stream, buf, 8))\n  Crc = Get32(buf);\n  Size32 = Get32(buf + 4);\n  return stream->InputEofError() ? S_FALSE : S_OK;\n}\n\nHRESULT CItem::ReadFooter2(ISequentialInStream *stream)\n{\n  Byte buf[8];\n  RINOK(ReadStream_FALSE(stream, buf, 8))\n  Crc = Get32(buf);\n  Size32 = Get32(buf + 4);\n  return S_OK;\n}\n\nHRESULT CItem::WriteHeader(ISequentialOutStream *stream)\n{\n  Byte buf[10];\n  buf[0] = kSignature_0;\n  buf[1] = kSignature_1;\n  buf[2] = kSignature_2;\n  buf[3] = (Byte)(Flags & NFlags::kName);\n  // buf[3] |= NFlags::kCrc;\n  SetUi32(buf + 4, Time)\n  buf[8] = ExtraFlags;\n  buf[9] = HostOS;\n  RINOK(WriteStream(stream, buf, 10))\n  // crc = CrcUpdate(CRC_INIT_VAL, buf, 10);\n  if (NameIsPresent())\n  {\n    // crc = CrcUpdate(crc, (const char *)Name, Name.Len() + 1);\n    RINOK(WriteStream(stream, (const char *)Name, Name.Len() + 1))\n  }\n  // SetUi16(buf, (UInt16)CRC_GET_DIGEST(crc));\n  // RINOK(WriteStream(stream, buf, 2));\n  return S_OK;\n}\n\nHRESULT CItem::WriteFooter(ISequentialOutStream *stream)\n{\n  Byte buf[8];\n  SetUi32(buf, Crc)\n  SetUi32(buf + 4, Size32)\n  return WriteStream(stream, buf, 8);\n}\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n  IArchiveOpenSeq,\n  IOutArchive,\n  ISetProperties\n)\n  CItem _item;\n\n  bool _isArc;\n  bool _needSeekToStart;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n  bool _numStreams_Defined;\n\n  UInt64 _packSize;\n  UInt64 _unpackSize; // real unpack size (NOT from footer)\n  UInt64 _numStreams;\n  UInt64 _headerSize; // only start header (without footer)\n  \n  CMyComPtr<IInStream> _stream;\n  CMyComPtr2<ICompressCoder, NDecoder::CCOMCoder> _decoder;\n\n  CSingleMethodProps _props;\n  CHandlerTimeOptions _timeOptions;\n\npublic:\n  CHandler():\n      _isArc(false)\n      {}\n  \n  void CreateDecoder()\n  {\n    _decoder.Create_if_Empty();\n  }\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidHostOS,\n  kpidCRC\n  // kpidComment\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidHeadersSize,\n  kpidNumStreams\n};\n\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n    case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;\n    case kpidHeadersSize: if (_headerSize != 0) prop = _headerSize; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;\n      prop = v;\n      break;\n    }\n    case kpidName:\n      if (_item.NameIsPresent())\n      {\n        UString s = MultiByteToUnicodeString(_item.Name, CP_ACP);\n        s += \".gz\";\n        prop = s;\n      }\n      break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPath:\n      if (_item.NameIsPresent())\n        prop = MultiByteToUnicodeString(_item.Name, CP_ACP);\n      break;\n    // case kpidComment: if (_item.CommentIsPresent()) prop = MultiByteToUnicodeString(_item.Comment, CP_ACP); break;\n    case kpidMTime:\n      // gzip specification: MTIME = 0 means no time stamp is available.\n      if (_item.Time != 0)\n        PropVariant_SetFrom_UnixTime(prop, _item.Time);\n      break;\n    case kpidTimeType:\n      if (_item.Time != 0)\n        prop = (UInt32)NFileTimeType::kUnix;\n      break;\n    case kpidSize:\n    {\n      if (_unpackSize_Defined)\n        prop = _unpackSize;\n      else if (_stream)\n        prop = (UInt64)_item.Size32;\n      break;\n    }\n    case kpidPackSize:\n    {\n      if (_packSize_Defined || _stream)\n        prop = _packSize;\n      break;\n    }\n    case kpidHostOS: TYPE_TO_PROP(kHostOSes, _item.HostOS, prop); break;\n    case kpidCRC: if (_stream) prop = _item.Crc; break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_CLASS_IMP_COM_1(\n  CCompressProgressInfoImp,\n  ICompressProgressInfo\n)\n  CMyComPtr<IArchiveOpenCallback> Callback;\npublic:\n  UInt64 Offset;\n  void Init(IArchiveOpenCallback *callback) { Callback = callback; }\n};\n\nZ7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))\n{\n  if (Callback)\n  {\n    UInt64 files = 0;\n    UInt64 value = Offset + *inSize;\n    return Callback->SetCompleted(&files, &value);\n  }\n  return S_OK;\n}\n\n/*\n*/\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  RINOK(OpenSeq(stream))\n  _isArc = false;\n  UInt64 endPos;\n  RINOK(stream->Seek(-8, STREAM_SEEK_END, &endPos))\n  _packSize = endPos + 8;\n  RINOK(_item.ReadFooter2(stream))\n  _stream = stream;\n  _isArc = true;\n  _needSeekToStart = true;\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  COM_TRY_BEGIN\n  try\n  {\n    Close();\n    CreateDecoder();\n    _decoder->SetInStream(stream);\n    _decoder->InitInStream(true);\n    RINOK(_item.ReadHeader(_decoder.ClsPtr()))\n    if (_decoder->InputEofError())\n      return S_FALSE;\n    _headerSize = _decoder->GetInputProcessedSize();\n    _isArc = true;\n    return S_OK;\n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _needSeekToStart = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n  _numStreams_Defined = false;\n\n  _packSize = 0;\n  _headerSize = 0;\n  \n  _stream.Release();\n  if (_decoder)\n    _decoder->ReleaseInStream();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    RINOK(extractCallback->SetTotal(_packSize))\n  // UInt64 currentTotalPacked = 0;\n  // RINOK(extractCallback->SetCompleted(&currentTotalPacked));\n  Int32 retResult;\n {\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  CreateDecoder();\n\n  CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;\n  outStream->SetStream(realOutStream);\n  outStream->Init();\n  // realOutStream.Release();\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, true);\n\n  bool needReadFirstItem = _needSeekToStart;\n  \n  if (_needSeekToStart)\n  {\n    if (!_stream)\n      return E_FAIL;\n    RINOK(InStream_SeekToBegin(_stream))\n    _decoder->InitInStream(true);\n    // printf(\"\\nSeek\");\n  }\n  else\n    _needSeekToStart = true;\n\n  bool firstItem = true;\n\n  UInt64 packSize = _decoder->GetInputProcessedSize();\n  // printf(\"\\npackSize = %d\", (unsigned)packSize);\n\n  UInt64 unpackedSize = 0;\n  UInt64 numStreams = 0;\n\n  bool crcError = false;\n\n  HRESULT result = S_OK;\n\n  try {\n  \n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackedSize;\n\n    RINOK(lps->SetCur())\n\n    CItem item;\n    \n    if (!firstItem || needReadFirstItem)\n    {\n      result = item.ReadHeader(_decoder.ClsPtr());\n\n      if (result != S_OK && result != S_FALSE)\n        return result;\n    \n      if (_decoder->InputEofError())\n        result = S_FALSE;\n\n      if (result != S_OK && firstItem)\n      {\n        _isArc = false;\n        break;\n      }\n\n      if (packSize == _decoder->GetStreamSize())\n      {\n        result = S_OK;\n        break;\n      }\n\n      if (result != S_OK)\n      {\n        _dataAfterEnd = true;\n        break;\n      }\n    }\n    \n    numStreams++;\n    firstItem = false;\n\n    const UInt64 startOffset = outStream->GetSize();\n    outStream->InitCRC();\n\n    result = _decoder->CodeResume(outStream, NULL, lps);\n\n    packSize = _decoder->GetInputProcessedSize();\n    unpackedSize = outStream->GetSize();\n\n    if (result != S_OK && result != S_FALSE)\n      return result;\n\n    if (_decoder->InputEofError())\n    {\n      packSize = _decoder->GetStreamSize();\n      _needMoreInput = true;\n      result = S_FALSE;\n    }\n\n    if (result != S_OK)\n      break;\n\n    _decoder->AlignToByte();\n    \n    result = item.ReadFooter1(_decoder.ClsPtr());\n\n    packSize = _decoder->GetInputProcessedSize();\n\n    if (result != S_OK && result != S_FALSE)\n      return result;\n\n    if (result != S_OK)\n    {\n      if (_decoder->InputEofError())\n      {\n        _needMoreInput = true;\n        result = S_FALSE;\n      }\n      break;\n    }\n\n    if (item.Crc != outStream->GetCRC() ||\n        item.Size32 != (UInt32)(unpackedSize - startOffset))\n    {\n      crcError = true;\n      result = S_FALSE;\n      break;\n    }\n\n    // break; // we can use break, if we need only first stream\n  }\n\n  } catch(const CInBufferException &e) { return e.ErrorCode; }\n\n  if (!firstItem)\n  {\n    _packSize = packSize;\n    _unpackSize = unpackedSize;\n    _numStreams = numStreams;\n\n    _packSize_Defined = true;\n    _unpackSize_Defined = true;\n    _numStreams_Defined = true;\n  }\n\n  // outStream.Release();\n\n  retResult = NExtract::NOperationResult::kDataError;\n\n  if (!_isArc)\n    retResult = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    retResult = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (crcError)\n    retResult = NExtract::NOperationResult::kCRCError;\n  else if (_dataAfterEnd)\n    retResult = NExtract::NOperationResult::kDataAfterEnd;\n  else if (result == S_FALSE)\n    retResult = NExtract::NOperationResult::kDataError;\n  else if (result == S_OK)\n    retResult = NExtract::NOperationResult::kOK;\n  else\n    return result;\n }\n\n  return extractCallback->SetOperationResult(retResult);\n  COM_TRY_END\n}\n\nstatic const Byte kHostOS =\n  #ifdef _WIN32\n  NHostOS::kFAT;\n  #else\n  NHostOS::kUnix;\n  #endif\n\n\n/*\nstatic HRESULT ReportItemProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)\n{\n  return reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, 0, propID, value);\n}\n\nstatic HRESULT ReportArcProp(IArchiveUpdateCallbackArcProp *reportArcProp, PROPID propID, const PROPVARIANT *value)\n{\n  return reportArcProp->ReportProp(NEventIndexType::kArcProp, 0, propID, value);\n}\n\nstatic HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,\n    const CItem &item,\n    bool needTime,\n    bool needCrc,\n    const UInt64 *unpackSize)\n{\n  NCOM::CPropVariant timeProp;\n  NCOM::CPropVariant sizeProp;\n  if (needTime)\n  {\n    FILETIME ft;\n    NTime::UnixTimeToFileTime(item.Time, ft);\n    timeProp.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix);\n  }\n  if (unpackSize)\n  {\n    sizeProp = *unpackSize;\n    RINOK(ReportItemProp(reportArcProp, kpidSize, &sizeProp));\n  }\n  if (needCrc)\n  {\n    NCOM::CPropVariant prop;\n    prop = item.Crc;\n    RINOK(ReportItemProp(reportArcProp, kpidCRC, &prop));\n  }\n  {\n    RINOK(ReportItemProp(reportArcProp, kpidMTime, &timeProp));\n  }\n \n  RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, 0, NArchive::NUpdate::NOperationResult::kOK));\n\n  if (unpackSize)\n  {\n    RINOK(ReportArcProp(reportArcProp, kpidSize, &sizeProp));\n  }\n  {\n    RINOK(ReportArcProp(reportArcProp, kpidComboMTime, &timeProp));\n  }\n  return S_OK;\n}\n*/\n\nstatic HRESULT UpdateArchive(\n    ISequentialOutStream *outStream,\n    UInt64 unpackSize,\n    CItem &item,\n    const CSingleMethodProps &props,\n    const CHandlerTimeOptions &timeOptions,\n    IArchiveUpdateCallback *updateCallback\n    // , IArchiveUpdateCallbackArcProp *reportArcProp\n    )\n{\n  UInt64 unpackSizeReal;\n  {\n  CMyComPtr<ISequentialInStream> fileInStream;\n\n  RINOK(updateCallback->GetStream(0, &fileInStream))\n\n  if (!fileInStream)\n    return S_FALSE;\n\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IStreamGetProps,\n        getProps, fileInStream)\n    if (getProps)\n    {\n      FILETIME mTime;\n      UInt64 size;\n      if (getProps->GetProps(&size, NULL, NULL, &mTime, NULL) == S_OK)\n      {\n        unpackSize = size;\n        if (timeOptions.Write_MTime.Val)\n          NTime::FileTime_To_UnixTime(mTime, item.Time);\n      }\n    }\n  }\n\n  UInt64 complexity = 0;\n  RINOK(updateCallback->SetTotal(unpackSize))\n  RINOK(updateCallback->SetCompleted(&complexity))\n\n  CMyComPtr2_Create<ISequentialInStream, CSequentialInStreamWithCRC> crcStream;\n  crcStream->SetStream(fileInStream);\n  crcStream->Init();\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(updateCallback, true);\n  \n  item.ExtraFlags = props.GetLevel() >= 7 ?\n      NExtraFlags::kMaximum :\n      NExtraFlags::kFastest;\n\n  item.HostOS = kHostOS;\n\n  RINOK(item.WriteHeader(outStream))\n\n  CMyComPtr2_Create<ICompressCoder, NEncoder::CCOMCoder> deflateEncoder;\n\n  RINOK(props.SetCoderProps(deflateEncoder.ClsPtr(), NULL))\n  RINOK(deflateEncoder.Interface()->Code(crcStream, outStream, NULL, NULL, lps))\n\n  item.Crc = crcStream->GetCRC();\n  unpackSizeReal = crcStream->GetSize();\n  item.Size32 = (UInt32)unpackSizeReal;\n  RINOK(item.WriteFooter(outStream))\n  }\n  /*\n  if (reportArcProp)\n  {\n    RINOK(ReportArcProps(reportArcProp,\n        item,\n        props._Write_MTime, // item.Time != 0,\n        true, // writeCrc\n        &unpackSizeReal));\n  }\n  */\n  return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);\n}\n\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))\n{\n  /*\n    if (_item.Time != 0)\n    {\n      we set NFileTimeType::kUnix in precision,\n      and we return NFileTimeType::kUnix in kpidTimeType\n      so GetFileTimeType() value is not used in any version of 7-zip.\n    }\n    else // (_item.Time == 0)\n    {\n      kpidMTime and kpidTimeType are not defined\n      before 22.00 : GetFileTimeType() value is used in GetUpdatePairInfoList();\n             22.00 : GetFileTimeType() value is not used\n    }\n  */\n\n  UInt32 t;\n  t = NFileTimeType::kUnix;\n  if (_isArc ? (_item.Time == 0) : !_timeOptions.Write_MTime.Val)\n  {\n    t = GET_FileTimeType_NotDefined_for_GetFileTimeType;\n    // t = k_PropVar_TimePrec_1ns; // failed in 7-Zip 21\n    // t = (UInt32)(Int32)NFileTimeType::kNotDefined; // failed in 7-Zip 21\n  }\n  *timeType = t;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IStreamSetRestriction,\n        setRestriction, outStream)\n    if (setRestriction)\n      RINOK(setRestriction->SetRestriction(0, 0))\n  }\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))\n\n  // Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackArcProp, reportArcProp, updateCallback)\n\n  CItem newItem;\n  \n  if (!IntToBool(newProps))\n  {\n    newItem.CopyMetaPropsFrom(_item);\n  }\n  else\n  {\n    newItem.HostOS = kHostOS;\n    if (_timeOptions.Write_MTime.Val)\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidMTime, &prop))\n      if (prop.vt == VT_FILETIME)\n        NTime::FileTime_To_UnixTime(prop.filetime, newItem.Time);\n      else if (prop.vt == VT_EMPTY)\n        newItem.Time = 0;\n      else\n        return E_INVALIDARG;\n    }\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidPath, &prop))\n      if (prop.vt == VT_BSTR)\n      {\n        UString name = prop.bstrVal;\n        int slashPos = name.ReverseFind_PathSepar();\n        if (slashPos >= 0)\n          name.DeleteFrontal((unsigned)(slashPos + 1));\n        newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);\n        if (!newItem.Name.IsEmpty())\n          newItem.Flags |= NFlags::kName;\n      }\n      else if (prop.vt != VT_EMPTY)\n        return E_INVALIDARG;\n    }\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n\n  if (IntToBool(newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop))\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n    return UpdateArchive(outStream, size, newItem, _props, _timeOptions, updateCallback);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  if (!_stream)\n    return E_NOTIMPL;\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(updateCallback, true);\n\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveUpdateCallbackFile,\n      opCallback, updateCallback)\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, 0,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  newItem.CopyDataPropsFrom(_item);\n\n  UInt64 offset = 0;\n  if (IntToBool(newProps))\n  {\n    newItem.WriteHeader(outStream);\n    offset += _headerSize;\n  }\n  RINOK(InStream_SeekSet(_stream, offset))\n\n  /*\n  if (reportArcProp)\n    ReportArcProps(reportArcProp, newItem,\n        _props._Write_MTime,\n        false, // writeCrc\n        NULL); // unpacksize\n  */\n\n  return NCompress::CopyStream(_stream, outStream, lps);\n\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  _timeOptions.Init();\n  _props.Init();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    UString name = names[i];\n    name.MakeLower_Ascii();\n    if (name.IsEmpty())\n      return E_INVALIDARG;\n    const PROPVARIANT &value = values[i];\n    {\n      bool processed = false;\n      RINOK(_timeOptions.Parse(name, value, processed))\n      if (processed)\n      {\n        if (_timeOptions.Write_CTime.Val ||\n            _timeOptions.Write_ATime.Val)\n          return E_INVALIDARG;\n        if (   _timeOptions.Prec != (UInt32)(Int32)-1\n            && _timeOptions.Prec != k_PropVar_TimePrec_0\n            && _timeOptions.Prec != k_PropVar_TimePrec_Unix\n            && _timeOptions.Prec != k_PropVar_TimePrec_HighPrec\n            && _timeOptions.Prec != k_PropVar_TimePrec_Base)\n          return E_INVALIDARG;\n        continue;\n      }\n    }\n    RINOK(_props.SetProperty(name, value))\n  }\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = { kSignature_0, kSignature_1, kSignature_2 };\n\nREGISTER_ARC_IO(\n  \"gzip\", \"gz gzip tgz tpz apk\", \"* * .tar .tar .tar\", 0xEF,\n  k_Signature, 0,\n    NArcInfoFlags::kKeepName\n  | NArcInfoFlags::kMTime\n  | NArcInfoFlags::kMTime_Default\n  , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix)\n  | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kUnix)\n  , IsArc_Gz)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/HandlerCont.cpp",
    "content": "﻿// HandlerCont.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"HandlerCont.h\"\n\nnamespace NArchive {\n\nnamespace NExt {\nAPI_FUNC_IsArc IsArc_Ext(const Byte *p, size_t size);\n}\n\nZ7_COM7F_IMF(CHandlerCont::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n  {\n    RINOK(GetNumberOfItems(&numItems))\n  }\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    UInt64 pos, size;\n    GetItem_ExtractInfo(allFilesMode ? i : indices[i], pos, size);\n    totalSize += size;\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  totalSize = 0;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> streamSpec;\n  streamSpec->SetStream(_stream);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = totalSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    CMyComPtr<ISequentialOutStream> outStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    \n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n\n    UInt64 pos, size;\n    int opRes = GetItem_ExtractInfo(index, pos, size);\n    totalSize += size;\n    if (!testMode && !outStream)\n      continue;\n    \n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    if (opRes == NExtract::NOperationResult::kOK)\n    {\n      RINOK(InStream_SeekSet(_stream, pos))\n      streamSpec->Init(size);\n    \n      RINOK(copyCoder.Interface()->Code(streamSpec, outStream, NULL, NULL, lps))\n      \n      opRes = NExtract::NOperationResult::kDataError;\n      if (copyCoder->TotalSize == size)\n        opRes = NExtract::NOperationResult::kOK;\n      else if (copyCoder->TotalSize < size)\n        opRes = NExtract::NOperationResult::kUnexpectedEnd;\n    }\n    \n    outStream.Release();\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  \n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandlerCont::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  UInt64 pos, size;\n  if (GetItem_ExtractInfo(index, pos, size) != NExtract::NOperationResult::kOK)\n    return S_FALSE;\n  return CreateLimitedInStream(_stream, pos, size, stream);\n  COM_TRY_END\n}\n\n\n\nCHandlerImg::CHandlerImg()\n{\n  Clear_HandlerImg_Vars();\n}\n\nZ7_COM7F_IMF(CHandlerImg::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += _size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n  {\n    if (newPosition)\n      *newPosition = _virtPos;\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  }\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\nstatic const Byte k_GDP_Signature[] =\n    { 'E', 'F', 'I', ' ', 'P', 'A', 'R', 'T', 0, 0, 1, 0 };\n// static const Byte k_Ext_Signature[] = { 0x53, 0xEF };\n// static const unsigned k_Ext_Signature_offset = 0x438;\n\nstatic const char *GetImgExt(ISequentialInStream *stream)\n{\n  // const size_t kHeaderSize_for_Ext = (1 << 11); // for ext\n  const size_t kHeaderSize = 2 << 12; // for 4 KB sector GPT\n  Byte buf[kHeaderSize];\n  size_t processed = kHeaderSize;\n  if (ReadStream(stream, buf, &processed) == S_OK)\n  {\n    if (processed >= kHeaderSize)\n    if (buf[0x1FE] == 0x55 && buf[0x1FF] == 0xAA)\n    {\n      for (unsigned k = (1 << 9); k <= (1u << 12); k <<= 3)\n        if (memcmp(buf + k, k_GDP_Signature, sizeof(k_GDP_Signature)) == 0)\n          return \"gpt\";\n      return \"mbr\";\n    }\n    if (NExt::IsArc_Ext(buf, processed) == k_IsArc_Res_YES)\n      return \"ext\";\n  }\n  return NULL;\n}\n\nvoid CHandlerImg::CloseAtError()\n{\n  Stream.Release();\n}\n\nvoid CHandlerImg::Clear_HandlerImg_Vars()\n{\n  _imgExt = NULL;\n  _size = 0;\n  ClearStreamVars();\n  Reset_VirtPos();\n  Reset_PosInArc();\n}\n\nZ7_COM7F_IMF(CHandlerImg::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * openCallback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    HRESULT res;\n    try\n    {\n      res = Open2(stream, openCallback);\n      if (res == S_OK)\n      {\n        CMyComPtr<ISequentialInStream> inStream;\n        const HRESULT res2 = GetStream(0, &inStream);\n        if (res2 == S_OK && inStream)\n          _imgExt = GetImgExt(inStream);\n        // _imgExt = GetImgExt(this); // for debug\n        /*  we reset (_virtPos) to support cases, if some code will\n            call Read() from Handler object instead of GetStream() object. */\n        Reset_VirtPos();\n        // optional: we reset (_posInArc). if real seek position of stream will be changed in external code\n        Reset_PosInArc();\n        // optional: here we could also reset seek positions in parent streams..\n        return S_OK;\n      }\n    }\n    catch(...)\n    {\n      CloseAtError();\n      throw;\n    }\n    CloseAtError();\n    return res;\n  }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandlerImg::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CHandlerImgProgress\n  , ICompressProgressInfo\n)\npublic:\n  CHandlerImg &Handler;\n  CMyComPtr<ICompressProgressInfo> _ratioProgress;\n\n  CHandlerImgProgress(CHandlerImg &handler) : Handler(handler) {}\n};\n\n\nZ7_COM7F_IMF(CHandlerImgProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  UInt64 inSize2;\n  if (Handler.Get_PackSizeProcessed(inSize2))\n    inSize = &inSize2;\n  return _ratioProgress->SetRatioInfo(inSize, outSize);\n}\n  \n\nZ7_COM7F_IMF(CHandlerImg::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  RINOK(extractCallback->SetTotal(_size))\n  CMyComPtr<ISequentialOutStream> outStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &outStream, askMode))\n  if (!testMode && !outStream)\n    return S_OK;\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  int opRes = NExtract::NOperationResult::kDataError;\n  \n  ClearStreamVars();\n  \n  CMyComPtr<ISequentialInStream> inStream;\n  HRESULT hres = GetStream(0, &inStream);\n  if (hres == S_FALSE)\n    hres = E_NOTIMPL;\n\n  if (hres == S_OK && inStream)\n  {\n    CLocalProgress *lps = new CLocalProgress;\n    CMyComPtr<ICompressProgressInfo> progress = lps;\n    lps->Init(extractCallback, false);\n    \n    if (Init_PackSizeProcessed())\n    {\n      CHandlerImgProgress *imgProgressSpec = new CHandlerImgProgress(*this);\n      CMyComPtr<ICompressProgressInfo> imgProgress = imgProgressSpec;\n      imgProgressSpec->_ratioProgress = progress;\n      progress.Release();\n      progress = imgProgress;\n    }\n\n    CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n    hres = copyCoder.Interface()->Code(inStream, outStream, NULL, &_size, progress);\n    if (hres == S_OK)\n    {\n      if (copyCoder->TotalSize == _size)\n        opRes = NExtract::NOperationResult::kOK;\n      \n      if (_stream_unavailData)\n        opRes = NExtract::NOperationResult::kUnavailable;\n      else if (_stream_unsupportedMethod)\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      else if (_stream_dataError)\n        opRes = NExtract::NOperationResult::kDataError;\n      else if (copyCoder->TotalSize < _size)\n        opRes = NExtract::NOperationResult::kUnexpectedEnd;\n    }\n  }\n\n  inStream.Release();\n  outStream.Release();\n  \n  if (hres != S_OK)\n  {\n    if (hres == S_FALSE)\n      opRes = NExtract::NOperationResult::kDataError;\n    else if (hres == E_NOTIMPL)\n      opRes = NExtract::NOperationResult::kUnsupportedMethod;\n    else\n      return hres;\n  }\n \n  return extractCallback->SetOperationResult(opRes);\n  COM_TRY_END\n}\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/HandlerCont.h",
    "content": "﻿// HandlerCont.h\n\n#ifndef ZIP7_INC_HANDLER_CONT_H\n#define ZIP7_INC_HANDLER_CONT_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"IArchive.h\"\n\nnamespace NArchive {\n\n#define Z7_IFACEM_IInArchive_Cont(x) \\\n  x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) \\\n  x(Close()) \\\n  x(GetNumberOfItems(UInt32 *numItems)) \\\n  x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \\\n  /* x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) */ \\\n  x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \\\n  x(GetNumberOfProperties(UInt32 *numProps)) \\\n  x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \\\n  x(GetNumberOfArchiveProperties(UInt32 *numProps)) \\\n  x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \\\n\n\n//  #define Z7_COM7F_PUREO(f)     virtual Z7_COM7F_IMF(f)     Z7_override =0;\n//  #define Z7_COM7F_PUREO2(t, f) virtual Z7_COM7F_IMF2(t, f) Z7_override =0;\n\nclass CHandlerCont:\n  public IInArchive,\n  public IInArchiveGetStream,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_2(\n      IInArchive,\n      IInArchiveGetStream)\n  /*\n  Z7_IFACEM_IInArchive_Cont(Z7_COM7F_PUREO)\n  // Z7_IFACE_COM7_PURE(IInArchive_Cont)\n  */\n  Z7_COM7F_IMP(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback))\nprotected:\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n\n  CMyComPtr<IInStream> _stream;\n  virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const = 0;\n  // destructor must be virtual for this class\n  virtual ~CHandlerCont() {}\n};\n\n\n\n#define Z7_IFACEM_IInArchive_Img(x) \\\n  /* x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) */ \\\n  x(Close()) \\\n  /* x(GetNumberOfItems(UInt32 *numItems)) */ \\\n  x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \\\n  /* x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) */ \\\n  x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \\\n  x(GetNumberOfProperties(UInt32 *numProps)) \\\n  x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \\\n  x(GetNumberOfArchiveProperties(UInt32 *numProps)) \\\n  x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \\\n\n\nclass CHandlerImg:\n  public IInArchive,\n  public IInArchiveGetStream,\n  public IInStream,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_4(\n      IInArchive,\n      IInArchiveGetStream,\n      ISequentialInStream,\n      IInStream)\n\n  Z7_COM7F_IMP(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback))\n  Z7_COM7F_IMP(GetNumberOfItems(UInt32 *numItems))\n  Z7_COM7F_IMP(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback))\n  Z7_IFACE_COM7_IMP(IInStream)\n  // Z7_IFACEM_IInArchive_Img(Z7_COM7F_PUREO)\n\nprotected:\n  bool _stream_unavailData;\n  bool _stream_unsupportedMethod;\n  bool _stream_dataError;\n  // bool _stream_UsePackSize;\n  // UInt64 _stream_PackSize;\n  UInt64 _virtPos;\n  UInt64 _posInArc;\n  UInt64 _size;\n  CMyComPtr<IInStream> Stream;\n  const char *_imgExt;\n  \n  void Reset_PosInArc() { _posInArc = (UInt64)0 - 1; }\n  void Reset_VirtPos() { _virtPos = (UInt64)0; }\n\n  void ClearStreamVars()\n  {\n    _stream_unavailData = false;\n    _stream_unsupportedMethod = false;\n    _stream_dataError = false;\n    // _stream_UsePackSize = false;\n    // _stream_PackSize = 0;\n  }\n\n  void Clear_HandlerImg_Vars(); // it doesn't Release (Stream) var.\n\n  virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) = 0;\n  virtual void CloseAtError();\n  \n  // returns (true), if Get_PackSizeProcessed() is required in Extract()\n  virtual bool Init_PackSizeProcessed()\n  {\n    return false;\n  }\npublic:\n  virtual bool Get_PackSizeProcessed(UInt64 &size)\n  {\n    size = 0;\n    return false;\n  }\n\n  CHandlerImg();\n  // destructor must be virtual for this class\n  virtual ~CHandlerImg() {}\n};\n\n\nHRESULT ReadZeroTail(ISequentialInStream *stream, bool &areThereNonZeros, UInt64 &numZeros, UInt64 maxSize);\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/HfsHandler.cpp",
    "content": "﻿// HfsHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HfsHandler.h\"\n\n/* if HFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files\n   and resource forks. In most cases it looks useless. So we disable it. */\n \n#define HFS_SHOW_ALT_STREAMS\n\n#define Get16(p) GetBe16(p)\n#define Get32(p) GetBe32(p)\n#define Get64(p) GetBe64(p)\n\n#define Get16a(p) GetBe16a(p)\n#define Get32a(p) GetBe32a(p)\n\nnamespace NArchive {\nnamespace NHfs {\n\nstatic const char * const kResFileName = \"rsrc\"; // \"com.apple.ResourceFork\";\n\nstruct CExtent\n{\n  UInt32 Pos;\n  UInt32 NumBlocks;\n};\n\nstruct CIdExtents\n{\n  UInt32 ID;\n  UInt32 StartBlock;\n  CRecordVector<CExtent> Extents;\n};\n\nstruct CFork\n{\n  UInt64 Size;\n  UInt32 NumBlocks;\n  // UInt32 ClumpSize;\n  CRecordVector<CExtent> Extents;\n\n  CFork(): Size(0), NumBlocks(0) {}\n\n  void Parse(const Byte *p);\n\n  bool IsEmpty() const { return Size == 0 && NumBlocks == 0 && Extents.Size() == 0; }\n\n  UInt32 Calc_NumBlocks_from_Extents() const;\n  bool Check_NumBlocks() const;\n\n  bool Check_Size_with_NumBlocks(unsigned blockSizeLog) const\n  {\n    return Size <= ((UInt64)NumBlocks << blockSizeLog);\n  }\n\n  bool IsOk(unsigned blockSizeLog) const\n  {\n    // we don't check cases with extra (empty) blocks in last extent\n    return Check_NumBlocks() && Check_Size_with_NumBlocks(blockSizeLog);\n  }\n\n  bool Upgrade(const CObjectVector<CIdExtents> &items, UInt32 id);\n  bool UpgradeAndTest(const CObjectVector<CIdExtents> &items, UInt32 id, unsigned blockSizeLog)\n  {\n    if (!Upgrade(items, id))\n      return false;\n    return IsOk(blockSizeLog);\n  }\n};\n\nstatic const unsigned kNumFixedExtents = 8;\nstatic const unsigned kForkRecSize = 16 + kNumFixedExtents * 8;\n\n\nvoid CFork::Parse(const Byte *p)\n{\n  Extents.Clear();\n  Size = Get64(p);\n  // ClumpSize = Get32(p + 8);\n  NumBlocks = Get32(p + 12);\n  p += 16;\n  for (unsigned i = 0; i < kNumFixedExtents; i++, p += 8)\n  {\n    CExtent e;\n    e.Pos = Get32(p);\n    e.NumBlocks = Get32(p + 4);\n    if (e.NumBlocks != 0)\n      Extents.Add(e);\n  }\n}\n\nUInt32 CFork::Calc_NumBlocks_from_Extents() const\n{\n  UInt32 num = 0;\n  FOR_VECTOR (i, Extents)\n    num += Extents[i].NumBlocks;\n  return num;\n}\n\nbool CFork::Check_NumBlocks() const\n{\n  UInt32 num = NumBlocks;\n  FOR_VECTOR (i, Extents)\n  {\n    const UInt32 cur = Extents[i].NumBlocks;\n    if (num < cur)\n      return false;\n    num -= cur;\n  }\n  return num == 0;\n}\n\nstruct CIdIndexPair\n{\n  UInt32 ID;\n  unsigned Index;\n\n  int Compare(const CIdIndexPair &a) const;\n};\n\n#define RINOZ(x) { const int _t_ = (x); if (_t_ != 0) return _t_; }\n\nint CIdIndexPair::Compare(const CIdIndexPair &a) const\n{\n  RINOZ(MyCompare(ID, a.ID))\n  return MyCompare(Index, a.Index);\n}\n\nstatic int FindItemIndex(const CRecordVector<CIdIndexPair> &items, UInt32 id)\n{\n  unsigned left = 0, right = items.Size();\n  while (left != right)\n  {\n    const unsigned mid = (left + right) / 2;\n    const UInt32 midVal = items[mid].ID;\n    if (id == midVal)\n      return (int)items[mid].Index;\n    if (id < midVal)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  return -1;\n}\n\nstatic int Find_in_IdExtents(const CObjectVector<CIdExtents> &items, UInt32 id)\n{\n  unsigned left = 0, right = items.Size();\n  while (left != right)\n  {\n    const unsigned mid = (left + right) / 2;\n    const UInt32 midVal = items[mid].ID;\n    if (id == midVal)\n      return (int)mid;\n    if (id < midVal)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  return -1;\n}\n\nbool CFork::Upgrade(const CObjectVector<CIdExtents> &items, UInt32 id)\n{\n  const int index = Find_in_IdExtents(items, id);\n  if (index < 0)\n    return true;\n  const CIdExtents &item = items[index];\n  if (Calc_NumBlocks_from_Extents() != item.StartBlock)\n    return false;\n  Extents += item.Extents;\n  return true;\n}\n\n\nstruct CVolHeader\n{\n  unsigned BlockSizeLog;\n  UInt32 NumFiles;\n  UInt32 NumFolders;\n  UInt32 NumBlocks;\n  UInt32 NumFreeBlocks;\n\n  bool Is_Hsfx_ver5;\n  // UInt32 Attr;\n  // UInt32 LastMountedVersion;\n  // UInt32 JournalInfoBlock;\n\n  UInt32 CTime;\n  UInt32 MTime;\n  // UInt32 BackupTime;\n  // UInt32 CheckedTime;\n  \n  // UInt32 WriteCount;\n  // UInt32 FinderInfo[8];\n  // UInt64 VolID;\n\n  UInt64 GetPhySize() const { return (UInt64)NumBlocks << BlockSizeLog; }\n  UInt64 GetFreeSize() const { return (UInt64)NumFreeBlocks << BlockSizeLog; }\n  bool IsHfsX() const { return Is_Hsfx_ver5; }\n};\n\ninline void HfsTimeToFileTime(UInt32 hfsTime, FILETIME &ft)\n{\n  UInt64 v = ((UInt64)3600 * 24 * (365 * 303 + 24 * 3) + hfsTime) * 10000000;\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n}\n\nenum ERecordType\n{\n  RECORD_TYPE_FOLDER = 1,\n  RECORD_TYPE_FILE,\n  RECORD_TYPE_FOLDER_THREAD,\n  RECORD_TYPE_FILE_THREAD\n};\n\n\n\n// static const UInt32 kMethod_1_NO_COMPRESSION = 1; // in xattr\nstatic const UInt32 kMethod_ZLIB_ATTR = 3;\nstatic const UInt32 kMethod_ZLIB_RSRC = 4;\n// static const UInt32 kMethod_DEDUP = 5; // de-dup within the generation store\n// macos 10.10\nstatic const UInt32 kMethod_LZVN_ATTR = 7;\nstatic const UInt32 kMethod_LZVN_RSRC = 8;\nstatic const UInt32 kMethod_COPY_ATTR = 9;\nstatic const UInt32 kMethod_COPY_RSRC = 10;\n// macos 10.11\n// static const UInt32 kMethod_LZFSE_ATTR = 11;\nstatic const UInt32 kMethod_LZFSE_RSRC = 12;\n\n// static const UInt32 kMethod_ZBM_RSRC = 14;\n\nstatic const char * const g_Methods[] =\n{\n    NULL\n  , NULL\n  , NULL\n  , \"ZLIB-attr\"\n  , \"ZLIB-rsrc\"\n  , NULL\n  , NULL\n  , \"LZVN-attr\"\n  , \"LZVN-rsrc\"\n  , \"COPY-attr\"\n  , \"COPY-rsrc\"\n  , \"LZFSE-attr\"\n  , \"LZFSE-rsrc\"\n  , NULL\n  , \"ZBM-rsrc\"\n};\n\n\nstatic const Byte k_COPY_Uncompressed_Marker = 0xcc;\nstatic const Byte k_LZVN_Uncompressed_Marker = 6;\n\nvoid CCompressHeader::Parse(const Byte *p, size_t dataSize)\n{\n  Clear();\n\n  if (dataSize < k_decmpfs_HeaderSize)\n    return;\n  if (GetUi32(p) != 0x636D7066) // magic == \"fpmc\"\n    return;\n  Method = GetUi32(p + 4);\n  UnpackSize = GetUi64(p + 8);\n  dataSize -= k_decmpfs_HeaderSize;\n  IsCorrect = true;\n  \n  if (   Method == kMethod_ZLIB_RSRC\n      || Method == kMethod_COPY_RSRC\n      || Method == kMethod_LZVN_RSRC\n      || Method == kMethod_LZFSE_RSRC\n      // || Method == kMethod_ZBM_RSRC // for debug\n      )\n  {\n    IsResource = true;\n    if (dataSize == 0)\n      IsSupported = (\n          Method != kMethod_LZFSE_RSRC &&\n          Method != kMethod_COPY_RSRC);\n    return;\n  }\n  \n  if (   Method == kMethod_ZLIB_ATTR\n      || Method == kMethod_COPY_ATTR\n      || Method == kMethod_LZVN_ATTR\n      // || Method == kMethod_LZFSE_ATTR\n    )\n  {\n    if (dataSize == 0)\n      return;\n    const Byte b = p[k_decmpfs_HeaderSize];\n    if (   (Method == kMethod_ZLIB_ATTR && (b & 0xf) == 0xf)\n        || (Method == kMethod_COPY_ATTR && b == k_COPY_Uncompressed_Marker)\n        || (Method == kMethod_LZVN_ATTR && b == k_LZVN_Uncompressed_Marker))\n    {\n      dataSize--;\n      // if (UnpackSize > dataSize)\n      if (UnpackSize != dataSize)\n        return;\n      DataPos = k_decmpfs_HeaderSize + 1;\n      IsSupported = true;\n    }\n    else\n    {\n      if (Method != kMethod_COPY_ATTR)\n        IsSupported = true;\n      DataPos = k_decmpfs_HeaderSize;\n    }\n  }\n}\n\n\nvoid CCompressHeader::MethodToProp(NWindows::NCOM::CPropVariant &prop) const\n{\n  if (!IsCorrect)\n    return;\n  const UInt32 method = Method;\n  const char *p = NULL;\n  if (method < Z7_ARRAY_SIZE(g_Methods))\n    p = g_Methods[method];\n  AString s;\n  if (p)\n    s = p;\n  else\n    s.Add_UInt32(method);\n  // if (!IsSupported) s += \"-unsuported\";\n  prop = s;\n}\n\nvoid MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop)\n{\n  FLAGS_TO_PROP(g_Methods, methodsMask, prop);\n}\n\n\nstruct CItem\n{\n  UString Name;\n  \n  UInt32 ParentID;\n\n  UInt16 Type;\n  UInt16 FileMode;\n  // UInt16 Flags;\n  // UInt32 Valence;\n  UInt32 ID;\n  UInt32 CTime;\n  UInt32 MTime;\n  UInt32 AttrMTime;\n  UInt32 ATime;\n  // UInt32 BackupDate;\n\n  /*\n  UInt32 OwnerID;\n  UInt32 GroupID;\n  Byte AdminFlags;\n  Byte OwnerFlags;\n  union\n  {\n    UInt32  iNodeNum;\n    UInt32  LinkCount;\n    UInt32  RawDevice;\n  } special;\n\n  UInt32 FileType;\n  UInt32 FileCreator;\n  UInt16 FinderFlags;\n  UInt16 Point[2];\n  */\n\n  CFork DataFork;\n  CFork ResourceFork;\n\n  // for compressed attribute (decmpfs)\n  int decmpfs_AttrIndex;\n  CCompressHeader CompressHeader;\n\n  CItem():\n      decmpfs_AttrIndex(-1)\n      {}\n  bool IsDir() const { return Type == RECORD_TYPE_FOLDER; }\n  // const CFork *GetFork(bool isResource) const { return (isResource ? &ResourceFork: &DataFork); }\n};\n\n\nstruct CAttr\n{\n  UInt32 ID;\n  bool Fork_defined;\n  \n  // UInt32 Size;    // for (Fork_defined == false) case\n  // size_t DataPos; // for (Fork_defined == false) case\n  CByteBuffer Data;\n\n  CFork Fork;\n\n  UString Name;\n\n  UInt64 GetSize() const\n  {\n    if (Fork_defined)\n      return Fork.Size;\n    return Data.Size();\n  }\n\n  CAttr():\n      Fork_defined(false)\n      // Size(0),\n      // DataPos(0),\n      {}\n};\n\n\nstatic const int kAttrIndex_Item     = -1;\nstatic const int kAttrIndex_Resource = -2;\n\nstruct CRef\n{\n  unsigned ItemIndex;\n  int AttrIndex;\n  int Parent;\n\n  CRef(): AttrIndex(kAttrIndex_Item), Parent(-1) {}\n  bool IsResource() const { return AttrIndex == kAttrIndex_Resource; }\n  bool IsAltStream() const { return AttrIndex != kAttrIndex_Item; }\n  bool IsItem() const { return AttrIndex == kAttrIndex_Item; }\n};\n\n\nclass CDatabase\n{\n  HRESULT ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream);\n  HRESULT LoadExtentFile(const CFork &fork, IInStream *inStream, CObjectVector<CIdExtents> *overflowExtentsArray);\n  HRESULT LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress);\n  HRESULT LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress);\n  bool Parse_decmpgfs(unsigned attrIndex, CItem &item, bool &skip);\npublic:\n  CRecordVector<CRef> Refs;\n  CObjectVector<CItem> Items;\n  CObjectVector<CAttr> Attrs;\n\n  // CByteBuffer AttrBuf;\n\n  CVolHeader Header;\n  bool HeadersError;\n  bool UnsupportedFeature;\n  bool ThereAreAltStreams;\n  // bool CaseSensetive;\n  UInt32 MethodsMask;\n  UString ResFileName;\n\n  UInt64 SpecOffset;\n  // UInt64 PhySize;\n  UInt64 PhySize2;\n  UInt64 ArcFileSize;\n\n  void Clear()\n  {\n    SpecOffset = 0;\n    // PhySize = 0;\n    PhySize2 = 0;\n    ArcFileSize = 0;\n    MethodsMask = 0;\n    HeadersError = false;\n    UnsupportedFeature = false;\n    ThereAreAltStreams = false;\n    // CaseSensetive = false;\n\n    Refs.Clear();\n    Items.Clear();\n    Attrs.Clear();\n    // AttrBuf.Free();\n  }\n\n  UInt64 Get_UnpackSize_of_Ref(const CRef &ref) const\n  {\n    if (ref.AttrIndex >= 0)\n      return Attrs[ref.AttrIndex].GetSize();\n    const CItem &item = Items[ref.ItemIndex];\n    if (ref.IsResource())\n      return item.ResourceFork.Size;\n    if (item.IsDir())\n      return 0;\n    else if (item.CompressHeader.IsCorrect)\n      return item.CompressHeader.UnpackSize;\n    return item.DataFork.Size;\n  }\n\n  void GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) const;\n  HRESULT Open2(IInStream *inStream, IArchiveOpenCallback *progress);\n};\n\nenum\n{\n  kHfsID_Root                  = 1,\n  kHfsID_RootFolder            = 2,\n  kHfsID_ExtentsFile           = 3,\n  kHfsID_CatalogFile           = 4,\n  kHfsID_BadBlockFile          = 5,\n  kHfsID_AllocationFile        = 6,\n  kHfsID_StartupFile           = 7,\n  kHfsID_AttributesFile        = 8,\n  kHfsID_RepairCatalogFile     = 14,\n  kHfsID_BogusExtentFile       = 15,\n  kHfsID_FirstUserCatalogNode  = 16\n};\n\nvoid CDatabase::GetItemPath(unsigned index, NWindows::NCOM::CPropVariant &path) const\n{\n  unsigned len = 0;\n  const unsigned kNumLevelsMax = (1 << 10);\n  unsigned cur = index;\n  unsigned i;\n  \n  for (i = 0; i < kNumLevelsMax; i++)\n  {\n    const CRef &ref = Refs[cur];\n    const UString *s;\n\n    if (ref.IsResource())\n      s = &ResFileName;\n    else if (ref.AttrIndex >= 0)\n      s = &Attrs[ref.AttrIndex].Name;\n    else\n      s = &Items[ref.ItemIndex].Name;\n\n    len += s->Len();\n    len++;\n    cur = (unsigned)ref.Parent;\n    if (ref.Parent < 0)\n      break;\n  }\n  \n  len--;\n  wchar_t *p = path.AllocBstr(len);\n  p[len] = 0;\n  cur = index;\n  \n  for (;;)\n  {\n    const CRef &ref = Refs[cur];\n    const UString *s;\n    wchar_t delimChar = L':';\n\n    if (ref.IsResource())\n      s = &ResFileName;\n    else if (ref.AttrIndex >= 0)\n      s = &Attrs[ref.AttrIndex].Name;\n    else\n    {\n      delimChar = WCHAR_PATH_SEPARATOR;\n      s = &Items[ref.ItemIndex].Name;\n    }\n\n    unsigned curLen = s->Len();\n    len -= curLen;\n    \n    const wchar_t *src = (const wchar_t *)*s;\n    wchar_t *dest = p + len;\n    for (unsigned j = 0; j < curLen; j++)\n    {\n      wchar_t c = src[j];\n      // 18.06\n      if (c == CHAR_PATH_SEPARATOR || c == '/')\n        c = '_';\n      dest[j] = c;\n    }\n    \n    if (len == 0)\n      break;\n    p[--len] = delimChar;\n    cur = (unsigned)ref.Parent;\n  }\n}\n\n// Actually we read all blocks. It can be larger than fork.Size\n\nHRESULT CDatabase::ReadFile(const CFork &fork, CByteBuffer &buf, IInStream *inStream)\n{\n  if (fork.NumBlocks >= Header.NumBlocks)\n    return S_FALSE;\n  if (((ArcFileSize - SpecOffset) >> Header.BlockSizeLog) + 1 < fork.NumBlocks)\n    return S_FALSE;\n\n  const size_t totalSize = (size_t)fork.NumBlocks << Header.BlockSizeLog;\n  if ((totalSize >> Header.BlockSizeLog) != fork.NumBlocks)\n    return S_FALSE;\n  buf.Alloc(totalSize);\n  UInt32 curBlock = 0;\n  FOR_VECTOR (i, fork.Extents)\n  {\n    if (curBlock >= fork.NumBlocks)\n      return S_FALSE;\n    const CExtent &e = fork.Extents[i];\n    if (e.Pos > Header.NumBlocks ||\n        e.NumBlocks > fork.NumBlocks - curBlock ||\n        e.NumBlocks > Header.NumBlocks - e.Pos)\n      return S_FALSE;\n    RINOK(InStream_SeekSet(inStream, SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog)))\n    RINOK(ReadStream_FALSE(inStream,\n        (Byte *)buf + ((size_t)curBlock << Header.BlockSizeLog),\n        (size_t)e.NumBlocks << Header.BlockSizeLog))\n    curBlock += e.NumBlocks;\n  }\n  return S_OK;\n}\n\nstatic const unsigned kNodeDescriptor_Size = 14;\n\nstruct CNodeDescriptor\n{\n  UInt32 fLink;\n  // UInt32 bLink;\n  Byte Kind;\n  // Byte Height;\n  unsigned NumRecords;\n\n  bool Parse(const Byte *p, unsigned nodeSizeLog);\n};\n\n\nbool CNodeDescriptor::Parse(const Byte *p, unsigned nodeSizeLog)\n{\n  fLink = Get32(p);\n  // bLink = Get32(p + 4);\n  Kind = p[8];\n  // Height = p[9];\n  NumRecords = Get16(p + 10);\n\n  const size_t nodeSize = (size_t)1 << nodeSizeLog;\n  if (kNodeDescriptor_Size + ((UInt32)NumRecords + 1) * 2 > nodeSize)\n    return false;\n  const size_t limit = nodeSize - ((UInt32)NumRecords + 1) * 2;\n\n  p += nodeSize - 2;\n\n  for (unsigned i = 0; i < NumRecords; i++)\n  {\n    const UInt32 offs = Get16(p);\n    p -= 2;\n    const UInt32 offsNext = Get16(p);\n    if (offs < kNodeDescriptor_Size\n        || offs >= offsNext\n        || offsNext > limit)\n      return false;\n  }\n  return true;\n}\n\nstruct CHeaderRec\n{\n  // UInt16 TreeDepth;\n  // UInt32 RootNode;\n  // UInt32 LeafRecords;\n  UInt32 FirstLeafNode;\n  // UInt32 LastLeafNode;\n  unsigned NodeSizeLog;\n  // UInt16 MaxKeyLength;\n  UInt32 TotalNodes;\n  // UInt32 FreeNodes;\n  // UInt16 Reserved1;\n  // UInt32 ClumpSize;\n  // Byte BtreeType;\n  // Byte KeyCompareType;\n  // UInt32 Attributes;\n  // UInt32 Reserved3[16];\n  \n  HRESULT Parse2(const CByteBuffer &buf);\n};\n\nHRESULT CHeaderRec::Parse2(const CByteBuffer &buf)\n{\n  if (buf.Size() < kNodeDescriptor_Size + 0x2A + 16 * 4)\n    return S_FALSE;\n  const Byte * p = (const Byte *)buf + kNodeDescriptor_Size;\n  // TreeDepth = Get16(p);\n  // RootNode = Get32(p + 2);\n  // LeafRecords = Get32(p + 6);\n  FirstLeafNode = Get32(p + 0xA);\n  // LastLeafNode = Get32(p + 0xE);\n  const UInt32 nodeSize = Get16(p + 0x12);\n\n  unsigned i;\n  for (i = 9; ((UInt32)1 << i) != nodeSize; i++)\n    if (i == 16)\n      return S_FALSE;\n  NodeSizeLog = i;\n\n  // MaxKeyLength = Get16(p + 0x14);\n  TotalNodes = Get32(p + 0x16);\n  // FreeNodes = Get32(p + 0x1A);\n  // Reserved1 = Get16(p + 0x1E);\n  // ClumpSize = Get32(p + 0x20);\n  // BtreeType = p[0x24];\n  // KeyCompareType = p[0x25];\n  // Attributes = Get32(p + 0x26);\n  /*\n  for (int i = 0; i < 16; i++)\n    Reserved3[i] = Get32(p + 0x2A + i * 4);\n  */\n\n  if ((buf.Size() >> NodeSizeLog) < TotalNodes)\n    return S_FALSE;\n\n  return S_OK;\n}\n\n\nstatic const Byte kNodeType_Leaf   = 0xFF;\n// static const Byte kNodeType_Index  = 0;\n// static const Byte kNodeType_Header = 1;\n// static const Byte kNodeType_Mode   = 2;\n\nstatic const Byte kExtentForkType_Data = 0;\nstatic const Byte kExtentForkType_Resource = 0xFF;\n\n/* It loads data extents from Extents Overflow File\n   Most dmg installers are not fragmented. So there are no extents in Overflow File. */\n\nHRESULT CDatabase::LoadExtentFile(const CFork &fork, IInStream *inStream, CObjectVector<CIdExtents> *overflowExtentsArray)\n{\n  if (fork.NumBlocks == 0)\n    return S_OK;\n  CByteBuffer buf;\n  RINOK(ReadFile(fork, buf, inStream))\n  const Byte *p = (const Byte *)buf;\n\n  // CNodeDescriptor nodeDesc;\n  // nodeDesc.Parse(p);\n  CHeaderRec hr;\n  RINOK(hr.Parse2(buf))\n\n  UInt32 node = hr.FirstLeafNode;\n  if (node == 0)\n    return S_OK;\n  if (hr.TotalNodes == 0)\n    return S_FALSE;\n\n  CByteArr usedBuf(hr.TotalNodes);\n  memset(usedBuf, 0, hr.TotalNodes);\n\n  while (node != 0)\n  {\n    if (node >= hr.TotalNodes || usedBuf[node] != 0)\n      return S_FALSE;\n    usedBuf[node] = 1;\n\n    const size_t nodeOffset = (size_t)node << hr.NodeSizeLog;\n    CNodeDescriptor desc;\n    if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog))\n      return S_FALSE;\n    if (desc.Kind != kNodeType_Leaf)\n      return S_FALSE;\n    \n    UInt32 endBlock = 0;\n\n    for (unsigned i = 0; i < desc.NumRecords; i++)\n    {\n      const UInt32 nodeSize = ((UInt32)1 << hr.NodeSizeLog);\n      const Byte *r = p + nodeOffset + nodeSize - i * 2;\n      const UInt32 offs = Get16(r - 2);\n      UInt32 recSize = Get16(r - 4) - offs;\n      const unsigned kKeyLen = 10;\n\n      if (recSize != 2 + kKeyLen + kNumFixedExtents * 8)\n        return S_FALSE;\n\n      r = p + nodeOffset + offs;\n      if (Get16(r) != kKeyLen)\n        return S_FALSE;\n      \n      const Byte forkType = r[2];\n      unsigned forkTypeIndex;\n      if (forkType == kExtentForkType_Data)\n        forkTypeIndex = 0;\n      else if (forkType == kExtentForkType_Resource)\n        forkTypeIndex = 1;\n      else\n        continue;\n      CObjectVector<CIdExtents> &overflowExtents = overflowExtentsArray[forkTypeIndex];\n\n      const UInt32 id = Get32(r + 4);\n      const UInt32 startBlock = Get32(r + 8);\n      r += 2 + kKeyLen;\n      \n      bool needNew = true;\n      \n      if (overflowExtents.Size() != 0)\n      {\n        CIdExtents &e = overflowExtents.Back();\n        if (e.ID == id)\n        {\n          if (endBlock != startBlock)\n            return S_FALSE;\n          needNew = false;\n        }\n      }\n      \n      if (needNew)\n      {\n        CIdExtents &e = overflowExtents.AddNew();\n        e.ID = id;\n        e.StartBlock = startBlock;\n        endBlock = startBlock;\n      }\n      \n      CIdExtents &e = overflowExtents.Back();\n      \n      for (unsigned k = 0; k < kNumFixedExtents; k++, r += 8)\n      {\n        CExtent ee;\n        ee.Pos = Get32(r);\n        ee.NumBlocks = Get32(r + 4);\n        if (ee.NumBlocks != 0)\n        {\n          e.Extents.Add(ee);\n          endBlock += ee.NumBlocks;\n        }\n      }\n    }\n\n    node = desc.fLink;\n  }\n  return S_OK;\n}\n\nstatic void LoadName(const Byte *data, unsigned len, UString &dest)\n{\n  wchar_t *p = dest.GetBuf(len);\n  unsigned i;\n  for (i = 0; i < len; i++)\n  {\n    const wchar_t c = Get16(data + i * 2);\n    if (c == 0)\n      break;\n    p[i] = c;\n  }\n  p[i] = 0;\n  dest.ReleaseBuf_SetLen(i);\n}\n\nstatic bool IsNameEqualTo(const Byte *data, const char *name)\n{\n  for (unsigned i = 0;; i++)\n  {\n    const char c = name[i];\n    if (c == 0)\n      return true;\n    if (Get16(data + i * 2) != (Byte)c)\n      return false;\n  }\n}\n\nstatic const UInt32 kAttrRecordType_Inline = 0x10;\nstatic const UInt32 kAttrRecordType_Fork = 0x20;\n// static const UInt32 kAttrRecordType_Extents = 0x30;\n\nHRESULT CDatabase::LoadAttrs(const CFork &fork, IInStream *inStream, IArchiveOpenCallback *progress)\n{\n  if (fork.NumBlocks == 0)\n    return S_OK;\n\n  CByteBuffer AttrBuf;\n  RINOK(ReadFile(fork, AttrBuf, inStream))\n  const Byte *p = (const Byte *)AttrBuf;\n\n  // CNodeDescriptor nodeDesc;\n  // nodeDesc.Parse(p);\n  CHeaderRec hr;\n  RINOK(hr.Parse2(AttrBuf))\n  \n  // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);\n\n  UInt32 node = hr.FirstLeafNode;\n  if (node == 0)\n    return S_OK;\n  if (hr.TotalNodes == 0)\n    return S_FALSE;\n\n  CByteArr usedBuf(hr.TotalNodes);\n  memset(usedBuf, 0, hr.TotalNodes);\n\n  CFork resFork;\n\n  while (node != 0)\n  {\n    if (node >= hr.TotalNodes || usedBuf[node] != 0)\n      return S_FALSE;\n    usedBuf[node] = 1;\n    \n    const size_t nodeOffset = (size_t)node << hr.NodeSizeLog;\n    CNodeDescriptor desc;\n    if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog))\n      return S_FALSE;\n    if (desc.Kind != kNodeType_Leaf)\n      return S_FALSE;\n    \n    for (unsigned i = 0; i < desc.NumRecords; i++)\n    {\n      const UInt32 nodeSize = ((UInt32)1 << hr.NodeSizeLog);\n      const Byte *r = p + nodeOffset + nodeSize - i * 2;\n      const UInt32 offs = Get16(r - 2);\n      UInt32 recSize = Get16(r - 4) - offs;\n      const unsigned kHeadSize = 14;\n      if (recSize < kHeadSize)\n        return S_FALSE;\n\n      r = p + nodeOffset + offs;\n      const UInt32 keyLen = Get16(r);\n\n      // UInt16 pad = Get16(r + 2);\n      const UInt32 fileID = Get32(r + 4);\n      const unsigned startBlock = Get32(r + 8);\n      if (startBlock != 0)\n      {\n        // that case is still unsupported\n        UnsupportedFeature = true;\n        continue;\n      }\n      const unsigned nameLen = Get16(r + 12);\n\n      if (keyLen + 2 > recSize ||\n          keyLen != kHeadSize - 2 + nameLen * 2)\n        return S_FALSE;\n      r += kHeadSize;\n      recSize -= kHeadSize;\n\n      const Byte *name = r;\n      r += nameLen * 2;\n      recSize -= nameLen * 2;\n\n      if (recSize < 4)\n        return S_FALSE;\n\n      const UInt32 recordType = Get32(r);\n\n      if (progress && (Attrs.Size() & 0xFFF) == 0)\n      {\n        const UInt64 numFiles = 0;\n        RINOK(progress->SetCompleted(&numFiles, NULL))\n      }\n\n      if (Attrs.Size() >= ((UInt32)1 << 31))\n        return S_FALSE;\n\n      CAttr &attr = Attrs.AddNew();\n      attr.ID = fileID;\n      LoadName(name, nameLen, attr.Name);\n\n      if (recordType == kAttrRecordType_Fork)\n      {\n        // 22.00 : some hfs files contain it;\n        /* spec: If the attribute has more than 8 extents, there will be additional\n            records (of type kAttrRecordType_Extents) for this attribute. */\n        if (recSize != 8 + kForkRecSize)\n          return S_FALSE;\n        if (Get32(r + 4) != 0) // reserved\n          return S_FALSE;\n        attr.Fork.Parse(r + 8);\n        attr.Fork_defined = true;\n        continue;\n      }\n      else if (recordType != kAttrRecordType_Inline)\n      {\n        UnsupportedFeature = true;\n        continue;\n      }\n\n      const unsigned kRecordHeaderSize = 16;\n      if (recSize < kRecordHeaderSize)\n        return S_FALSE;\n      if (Get32(r + 4) != 0 || Get32(r + 8) != 0) // reserved\n        return S_FALSE;\n      const UInt32 dataSize = Get32(r + 12);\n      \n      r += kRecordHeaderSize;\n      recSize -= kRecordHeaderSize;\n      \n      if (recSize < dataSize)\n        return S_FALSE;\n\n      attr.Data.CopyFrom(r, dataSize);\n      // attr.DataPos = nodeOffset + offs + 2 + keyLen + kRecordHeaderSize;\n      // attr.Size = dataSize;\n    }\n\n    node = desc.fLink;\n  }\n  return S_OK;\n}\n\n\nbool CDatabase::Parse_decmpgfs(unsigned attrIndex, CItem &item, bool &skip)\n{\n  const CAttr &attr = Attrs[attrIndex];\n  skip = false;\n  if (item.CompressHeader.IsCorrect || !item.DataFork.IsEmpty())\n    return false;\n\n  item.CompressHeader.Parse(attr.Data, attr.Data.Size());\n\n  if (item.CompressHeader.IsCorrect)\n  {\n    item.decmpfs_AttrIndex = (int)attrIndex;\n    skip = true;\n    if (item.CompressHeader.Method < sizeof(MethodsMask) * 8)\n      MethodsMask |= ((UInt32)1 << item.CompressHeader.Method);\n  }\n\n  return true;\n}\n\n\nHRESULT CDatabase::LoadCatalog(const CFork &fork, const CObjectVector<CIdExtents> *overflowExtentsArray, IInStream *inStream, IArchiveOpenCallback *progress)\n{\n  CByteBuffer buf;\n  RINOK(ReadFile(fork, buf, inStream))\n  const Byte *p = (const Byte *)buf;\n\n  // CNodeDescriptor nodeDesc;\n  // nodeDesc.Parse(p);\n  CHeaderRec hr;\n  RINOK(hr.Parse2(buf))\n\n  CRecordVector<CIdIndexPair> IdToIndexMap;\n\n  const unsigned reserveSize = (unsigned)(Header.NumFolders + 1 + Header.NumFiles);\n\n  const unsigned kBasicRecSize = 0x58;\n  const unsigned kMinRecSize = kBasicRecSize + 10;\n\n  if ((UInt64)reserveSize * kMinRecSize < buf.Size())\n  {\n    Items.ClearAndReserve(reserveSize);\n    Refs.ClearAndReserve(reserveSize);\n    IdToIndexMap.ClearAndReserve(reserveSize);\n  }\n \n  // CaseSensetive = (Header.IsHfsX() && hr.KeyCompareType == 0xBC);\n\n  CByteArr usedBuf(hr.TotalNodes);\n  if (hr.TotalNodes != 0)\n    memset(usedBuf, 0, hr.TotalNodes);\n\n  CFork resFork;\n\n  UInt32 node = hr.FirstLeafNode;\n  UInt32 numFiles = 0;\n  UInt32 numFolders = 0;\n  \n  while (node != 0)\n  {\n    if (node >= hr.TotalNodes || usedBuf[node] != 0)\n      return S_FALSE;\n    usedBuf[node] = 1;\n    \n    const size_t nodeOffset = (size_t)node << hr.NodeSizeLog;\n    CNodeDescriptor desc;\n    if (!desc.Parse(p + nodeOffset, hr.NodeSizeLog))\n      return S_FALSE;\n    if (desc.Kind != kNodeType_Leaf)\n      return S_FALSE;\n    \n    for (unsigned i = 0; i < desc.NumRecords; i++)\n    {\n      const UInt32 nodeSize = (1 << hr.NodeSizeLog);\n      const Byte *r = p + nodeOffset + nodeSize - i * 2;\n      const UInt32 offs = Get16(r - 2);\n      UInt32 recSize = Get16(r - 4) - offs;\n      if (recSize < 6)\n        return S_FALSE;\n\n      r = p + nodeOffset + offs;\n      UInt32 keyLen = Get16(r);\n      UInt32 parentID = Get32(r + 2);\n      if (keyLen < 6 || (keyLen & 1) != 0 || keyLen + 2 > recSize)\n        return S_FALSE;\n      r += 6;\n      recSize -= 6;\n      keyLen -= 6;\n      \n      unsigned nameLen = Get16(r);\n      if (nameLen * 2 != (unsigned)keyLen)\n        return S_FALSE;\n      r += 2;\n      recSize -= 2;\n     \n      r += nameLen * 2;\n      recSize -= nameLen * 2;\n\n      if (recSize < 2)\n        return S_FALSE;\n      UInt16 type = Get16(r);\n\n      if (type != RECORD_TYPE_FOLDER &&\n          type != RECORD_TYPE_FILE)\n        continue;\n\n      if (recSize < kBasicRecSize)\n        return S_FALSE;\n\n      CItem &item = Items.AddNew();\n      item.ParentID = parentID;\n      item.Type = type;\n      // item.Flags = Get16(r + 2);\n      // item.Valence = Get32(r + 4);\n      item.ID = Get32(r + 8);\n      {\n        const Byte *name = r - (nameLen * 2);\n        LoadName(name, nameLen, item.Name);\n        if (item.Name.Len() <= 1)\n        {\n          if (item.Name.IsEmpty() && nameLen == 21)\n          {\n            if (GetUi32(name) == 0 &&\n                GetUi32(name + 4) == 0 &&\n                IsNameEqualTo(name + 8, \"HFS+ Private Data\"))\n            {\n              // it's folder for \"Hard Links\" files\n              item.Name = \"[HFS+ Private Data]\";\n            }\n          }\n\n          // Some dmg files have ' ' folder item.\n          if (item.Name.IsEmpty() || item.Name[0] == L' ')\n            item.Name = \"[]\";\n        }\n      }\n\n      item.CTime = Get32(r + 0xC);\n      item.MTime = Get32(r + 0x10);\n      item.AttrMTime = Get32(r + 0x14);\n      item.ATime = Get32(r + 0x18);\n      // item.BackupDate = Get32(r + 0x1C);\n      \n      /*\n      item.OwnerID = Get32(r + 0x20);\n      item.GroupID = Get32(r + 0x24);\n      item.AdminFlags = r[0x28];\n      item.OwnerFlags = r[0x29];\n      */\n      item.FileMode = Get16(r + 0x2A);\n      /*\n      item.special.iNodeNum = Get16(r + 0x2C); // or .linkCount\n      item.FileType = Get32(r + 0x30);\n      item.FileCreator = Get32(r + 0x34);\n      item.FinderFlags = Get16(r + 0x38);\n      item.Point[0] = Get16(r + 0x3A); // v\n      item.Point[1] = Get16(r + 0x3C); // h\n      */\n\n      // const refIndex = Refs.Size();\n      CIdIndexPair pair;\n      pair.ID = item.ID;\n      pair.Index = Items.Size() - 1;\n      IdToIndexMap.Add(pair);\n\n      recSize -= kBasicRecSize;\n      r += kBasicRecSize;\n      if (item.IsDir())\n      {\n        numFolders++;\n        if (recSize != 0)\n          return S_FALSE;\n      }\n      else\n      {\n        numFiles++;\n        if (recSize != kForkRecSize * 2)\n          return S_FALSE;\n        \n        item.DataFork.Parse(r);\n\n        if (!item.DataFork.UpgradeAndTest(overflowExtentsArray[0], item.ID, Header.BlockSizeLog))\n          HeadersError = true;\n  \n        item.ResourceFork.Parse(r + kForkRecSize);\n        if (!item.ResourceFork.IsEmpty())\n        {\n          if (!item.ResourceFork.UpgradeAndTest(overflowExtentsArray[1], item.ID, Header.BlockSizeLog))\n            HeadersError = true;\n          // ThereAreAltStreams = true;\n        }\n      }\n      if (progress && (Items.Size() & 0xFFF) == 0)\n      {\n        const UInt64 numItems = Items.Size();\n        RINOK(progress->SetCompleted(&numItems, NULL))\n      }\n    }\n    node = desc.fLink;\n  }\n\n  if (Header.NumFiles != numFiles ||\n      Header.NumFolders + 1 != numFolders)\n    HeadersError = true;\n\n  IdToIndexMap.Sort2();\n  {\n    for (unsigned i = 1; i < IdToIndexMap.Size(); i++)\n      if (IdToIndexMap[i - 1].ID == IdToIndexMap[i].ID)\n        return S_FALSE;\n  }\n\n \n  CBoolArr skipAttr(Attrs.Size());\n  {\n    for (unsigned i = 0; i < Attrs.Size(); i++)\n      skipAttr[i] = false;\n  }\n\n  {\n    FOR_VECTOR (i, Attrs)\n    {\n      const CAttr &attr = Attrs[i];\n\n      const int itemIndex = FindItemIndex(IdToIndexMap, attr.ID);\n      if (itemIndex < 0)\n      {\n        HeadersError = true;\n        continue;\n      }\n  \n      if (attr.Name.IsEqualTo(\"com.apple.decmpfs\"))\n      {\n        if (!Parse_decmpgfs(i, Items[itemIndex], skipAttr[i]))\n          HeadersError = true;\n      }\n    }\n  }\n\n  IdToIndexMap.ClearAndReserve(Items.Size());\n\n  {\n    FOR_VECTOR (i, Items)\n    {\n      const CItem &item = Items[i];\n\n      CIdIndexPair pair;\n      pair.ID = item.ID;\n      pair.Index = Refs.Size();\n      IdToIndexMap.Add(pair);\n\n      CRef ref;\n      ref.ItemIndex = i;\n      Refs.Add(ref);\n      \n      #ifdef HFS_SHOW_ALT_STREAMS\n     \n      if (item.ResourceFork.IsEmpty())\n        continue;\n      if (item.CompressHeader.IsSupported && item.CompressHeader.IsMethod_Resource())\n        continue;\n\n      ThereAreAltStreams = true;\n      ref.AttrIndex = kAttrIndex_Resource;\n      ref.Parent = (int)(Refs.Size() - 1);\n      Refs.Add(ref);\n      \n      #endif\n    }\n  }\n\n  IdToIndexMap.Sort2();\n\n  {\n    FOR_VECTOR (i, Refs)\n    {\n      CRef &ref = Refs[i];\n      if (ref.IsResource())\n        continue;\n      const CItem &item = Items[ref.ItemIndex];\n      ref.Parent = FindItemIndex(IdToIndexMap, item.ParentID);\n      if (ref.Parent >= 0)\n      {\n        if (!Items[Refs[ref.Parent].ItemIndex].IsDir())\n        {\n          ref.Parent = -1;\n          HeadersError = true;\n        }\n      }\n    }\n  }\n\n  #ifdef HFS_SHOW_ALT_STREAMS\n  {\n    FOR_VECTOR (i, Attrs)\n    {\n      if (skipAttr[i])\n        continue;\n      const CAttr &attr = Attrs[i];\n\n      const int refIndex = FindItemIndex(IdToIndexMap, attr.ID);\n      if (refIndex < 0)\n      {\n        HeadersError = true;\n        continue;\n      }\n\n      ThereAreAltStreams = true;\n\n      CRef ref;\n      ref.AttrIndex = (int)i;\n      ref.Parent = refIndex;\n      ref.ItemIndex = Refs[refIndex].ItemIndex;\n      Refs.Add(ref);\n    }\n  }\n  #endif\n\n  return S_OK;\n}\n\nstatic const unsigned kHeaderPadSize = 1 << 10;\nstatic const unsigned kMainHeaderSize = 512;\nstatic const unsigned kHfsHeaderSize = kHeaderPadSize + kMainHeaderSize;\n\nstatic const unsigned k_Signature_LE16_HFS_BD = 'B' + ((unsigned)'D' << 8);\nstatic const unsigned k_Signature_LE16_HPLUS  = 'H' + ((unsigned)'+' << 8);\nstatic const UInt32   k_Signature_LE32_HFSP_VER4 = 'H' + ((UInt32)'+' << 8) + ((UInt32)4 << 24);\nstatic const UInt32   k_Signature_LE32_HFSX_VER5 = 'H' + ((UInt32)'X' << 8) + ((UInt32)5 << 24);\n\nAPI_FUNC_static_IsArc IsArc_HFS(const Byte *p, size_t size)\n{\n  if (size < kHfsHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  p += kHeaderPadSize;\n  const UInt32 sig = GetUi32(p);\n  if (sig != k_Signature_LE32_HFSP_VER4)\n  if (sig != k_Signature_LE32_HFSX_VER5)\n  if ((UInt16)sig != k_Signature_LE16_HFS_BD\n      || GetUi16(p + 0x7c) != k_Signature_LE16_HPLUS)\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\nHRESULT CDatabase::Open2(IInStream *inStream, IArchiveOpenCallback *progress)\n{\n  Clear();\n  UInt32 buf32[kHfsHeaderSize / 4];\n  RINOK(ReadStream_FALSE(inStream, buf32, kHfsHeaderSize))\n  const Byte *p = (const Byte *)buf32 + kHeaderPadSize;\n  CVolHeader &h = Header;\n\n  if (GetUi16a(p) == k_Signature_LE16_HFS_BD)\n  {\n    /*\n    It's header for old HFS format.\n    We don't support old HFS format, but we support\n    special HFS volume that contains embedded HFS+ volume.\n    HFS MDB : Master directory block\n    HFS VIB : Volume information block\n    some old images contain boot data with \"LK\" signature at start of buf32.\n    */\n#if 1\n    // here we check first bytes of archive,\n    // because start data can contain signature of some another\n    // archive type that could have priority over HFS.\n    const void *buf_ptr = (const void *)buf32;\n    const unsigned sig = GetUi16a(buf_ptr);\n    if (sig != 'L' + ((unsigned)'K' << 8))\n    {\n      // some old HFS (non HFS+) files have no \"LK\" signature,\n      // but have non-zero data after 2 first bytes in start 1 KiB.\n      if (sig != 0)\n        return S_FALSE;\n/*\n      for (unsigned i = 0; i < kHeaderPadSize / 4; i++)\n        if (buf32[i] != 0)\n          return S_FALSE;\n*/\n    }\n#endif\n    if (GetUi16a(p + 0x7c) != k_Signature_LE16_HPLUS) // signature of embedded HFS+ volume\n      return S_FALSE;\n    /*\n    h.CTime = Get32(p + 0x2);\n    h.MTime = Get32(p + 0x6);\n    \n    h.NumFiles = Get32(p + 0x54);\n    h.NumFolders = Get32(p + 0x58);\n    \n    if (h.NumFolders > ((UInt32)1 << 29) ||\n        h.NumFiles > ((UInt32)1 << 30))\n      return S_FALSE;\n    if (progress)\n    {\n      UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;\n      RINOK(progress->SetTotal(&numFiles, NULL))\n    }\n    h.NumFreeBlocks = Get16(p + 0x22);\n    */\n    \n    // v24.09: blockSize in old HFS image can be non-power of 2.\n    const UInt32 blockSize = Get32a(p + 0x14); // drAlBlkSiz\n    if (blockSize == 0 || (blockSize & 0x1ff))\n      return S_FALSE;\n    const unsigned numBlocks = Get16a(p + 0x12); // drNmAlBlks\n    // UInt16 drFreeBks = Get16a(p + 0x22); // number of unused allocation blocks\n    /*\n    we suppose that it has the following layout:\n    {\n      start data with header\n      blocks[h.NumBlocks]\n      end data with header (probably size_of_footer <= blockSize).\n    }\n    */\n    // PhySize2 = ((UInt64)numBlocks + 2) * blockSize;\n    const unsigned sector_of_FirstBlock = Get16a(p + 0x1c); // drAlBlSt : first allocation block in volume\n    const UInt32 startBlock = Get16a(p + 0x7c + 2);\n    const UInt32 blockCount = Get16a(p + 0x7c + 4);\n    SpecOffset = (UInt32)sector_of_FirstBlock << 9; // it's 32-bit here\n    PhySize2 = SpecOffset + (UInt64)numBlocks * blockSize;\n    SpecOffset += (UInt64)startBlock * blockSize;\n    // before v24.09: // SpecOffset = (UInt64)(1 + startBlock) * blockSize;\n    const UInt64 phy = SpecOffset + (UInt64)blockCount * blockSize;\n    if (PhySize2 < phy)\n        PhySize2 = phy;\n    UInt32 tail = 1 << 10; // at least 1 KiB tail (for footer MDB) is expected.\n    if (tail < blockSize)\n        tail = blockSize;\n    RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize))\n    if (ArcFileSize > PhySize2 &&\n        ArcFileSize - PhySize2 <= tail)\n    {\n      // data after blocks[h.NumBlocks] must contain another copy of MDB.\n      // In example where blockSize is not power of 2, we have\n      //   (ArcFileSize - PhySize2) < blockSize.\n      // We suppose that data after blocks[h.NumBlocks] is part of HFS archive.\n      // Maybe we should scan for footer MDB data (in last 1 KiB)?\n      PhySize2 = ArcFileSize;\n    }\n    RINOK(InStream_SeekSet(inStream, SpecOffset))\n    RINOK(ReadStream_FALSE(inStream, buf32, kHfsHeaderSize))\n  }\n\n  // HFS+ / HFSX volume header (starting from offset==1024):\n  {\n    // v24.09: we use strict condition test for pair signature(Version):\n    // H+(4), HX(5):\n    const UInt32 sig = GetUi32a(p);\n    // h.Version = Get16(p + 2);\n    h.Is_Hsfx_ver5 = false;\n    if (sig != k_Signature_LE32_HFSP_VER4)\n    {\n      if (sig != k_Signature_LE32_HFSX_VER5)\n        return S_FALSE;\n      h.Is_Hsfx_ver5 = true;\n    }\n  }\n  {\n    const UInt32 blockSize = Get32a(p + 0x28);\n    unsigned i;\n    for (i = 9; ((UInt32)1 << i) != blockSize; i++)\n      if (i == 31)\n        return S_FALSE;\n    h.BlockSizeLog = i;\n  }\n#if 1\n  // HFS Plus DOCs: The first 1024 bytes are reserved for use as boot blocks\n  // v24.09: we don't check starting 1 KiB before old (HFS MDB) block (\"BD\" signture) .\n  //     but we still check starting 1 KiB before HFS+ / HFSX volume header.\n  // are there HFS+ / HFSX images with non-zero data in this reserved area?\n  {\n    for (unsigned i = 0; i < kHeaderPadSize / 4; i++)\n      if (buf32[i] != 0)\n        return S_FALSE;\n  }\n#endif\n  // h.Attr = Get32a(p + 4);\n  // h.LastMountedVersion = Get32a(p + 8);\n  // h.JournalInfoBlock = Get32a(p + 0xC);\n  h.CTime = Get32a(p + 0x10);\n  h.MTime = Get32a(p + 0x14);\n  // h.BackupTime = Get32a(p + 0x18);\n  // h.CheckedTime = Get32a(p + 0x1C);\n  h.NumFiles = Get32a(p + 0x20);\n  h.NumFolders = Get32a(p + 0x24);\n  if (h.NumFolders > ((UInt32)1 << 29) ||\n      h.NumFiles > ((UInt32)1 << 30))\n    return S_FALSE;\n\n  RINOK(InStream_GetSize_SeekToEnd(inStream, ArcFileSize))\n  if (progress)\n  {\n    const UInt64 numFiles = (UInt64)h.NumFiles + h.NumFolders + 1;\n    RINOK(progress->SetTotal(&numFiles, NULL))\n  }\n\n  h.NumBlocks = Get32a(p + 0x2C);\n  h.NumFreeBlocks = Get32a(p + 0x30);\n  /*\n  h.NextCalatlogNodeID = Get32(p + 0x40);\n  h.WriteCount = Get32(p + 0x44);\n  for (i = 0; i < 6; i++)\n    h.FinderInfo[i] = Get32(p + 0x50 + i * 4);\n  h.VolID = Get64(p + 0x68);\n  */\n\n  ResFileName = kResFileName;\n\n  CFork extentsFork, catalogFork, attrFork;\n  // allocationFork.Parse(p + 0x70 + 0x50 * 0);\n  extentsFork.Parse(p + 0x70 + 0x50 * 1);\n  catalogFork.Parse(p + 0x70 + 0x50 * 2);\n  attrFork.Parse   (p + 0x70 + 0x50 * 3);\n  // startupFork.Parse(p + 0x70 + 0x50 * 4);\n\n  CObjectVector<CIdExtents> overflowExtents[2];\n  if (!extentsFork.IsOk(Header.BlockSizeLog))\n    HeadersError = true;\n  else\n  {\n    const HRESULT res = LoadExtentFile(extentsFork, inStream, overflowExtents);\n    if (res == S_FALSE)\n      HeadersError = true;\n    else if (res != S_OK)\n      return res;\n  }\n\n  if (!catalogFork.UpgradeAndTest(overflowExtents[0], kHfsID_CatalogFile, Header.BlockSizeLog))\n    return S_FALSE;\n  \n  if (!attrFork.UpgradeAndTest(overflowExtents[0], kHfsID_AttributesFile, Header.BlockSizeLog))\n    HeadersError = true;\n  else\n  {\n    if (attrFork.Size != 0)\n      RINOK(LoadAttrs(attrFork, inStream, progress))\n  }\n  \n  RINOK(LoadCatalog(catalogFork, overflowExtents, inStream, progress))\n\n  // PhySize = Header.GetPhySize();\n  return S_OK;\n}\n\n\n\nZ7_class_CHandler_final:\n  public IInArchive,\n  public IArchiveGetRawProps,\n  public IInArchiveGetStream,\n  public CMyUnknownImp,\n  public CDatabase\n{\n  Z7_IFACES_IMP_UNK_3(\n      IInArchive,\n      IArchiveGetRawProps,\n      IInArchiveGetStream)\n\n  CMyComPtr<IInStream> _stream;\n  HRESULT GetForkStream(const CFork &fork, ISequentialInStream **stream);\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidCTime,\n  kpidMTime,\n  kpidATime,\n  kpidChangeTime,\n  kpidPosixAttrib,\n  /*\n  kpidUserId,\n  kpidGroupId,\n  */\n#ifdef HFS_SHOW_ALT_STREAMS\n  kpidIsAltStream,\n#endif\n  kpidMethod\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidMethod,\n  kpidCharacts,\n  kpidClusterSize,\n  kpidFreeSpace,\n  kpidCTime,\n  kpidMTime\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop)\n{\n  if (hfsTime == 0)\n    return;\n  FILETIME ft;\n  HfsTimeToFileTime(hfsTime, ft);\n  prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Base);\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidExtension: prop = Header.IsHfsX() ? \"hfsx\" : \"hfs\"; break;\n    case kpidMethod: prop = Header.IsHfsX() ? \"HFSX\" : \"HFS+\"; break;\n    case kpidCharacts: MethodsMaskToProp(MethodsMask, prop); break;\n    case kpidPhySize:\n    {\n      UInt64 v = SpecOffset + Header.GetPhySize(); // PhySize;\n      if (v < PhySize2)\n        v = PhySize2;\n      prop = v;\n      break;\n    }\n    case kpidClusterSize: prop = (UInt32)1 << Header.BlockSizeLog; break;\n    case kpidFreeSpace: prop = (UInt64)Header.GetFreeSize(); break;\n    case kpidMTime: HfsTimeToProp(Header.MTime, prop); break;\n    case kpidCTime:\n    {\n      if (Header.CTime != 0)\n      {\n        FILETIME localFt, ft;\n        HfsTimeToFileTime(Header.CTime, localFt);\n        if (LocalFileTimeToFileTime(&localFt, &ft))\n          prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Base);\n      }\n      break;\n    }\n    case kpidIsTree: prop = true; break;\n    case kpidErrorFlags:\n    {\n      UInt32 flags = 0;\n      if (HeadersError) flags |= kpv_ErrorFlags_HeadersError;\n      if (UnsupportedFeature) flags |= kpv_ErrorFlags_UnsupportedFeature;\n      if (flags != 0)\n        prop = flags;\n      break;\n    }\n    case kpidIsAltStream: prop = ThereAreAltStreams; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 /* index */, BSTR *name, PROPID *propID))\n{\n  *name = NULL;\n  *propID = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  const CRef &ref = Refs[index];\n  *parentType = ref.IsAltStream() ?\n      NParentType::kAltStream :\n      NParentType::kDir;\n  *parent = (UInt32)(Int32)ref.Parent;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n  #ifdef MY_CPU_LE\n  if (propID == kpidName)\n  {\n    const CRef &ref = Refs[index];\n    const UString *s;\n    if (ref.IsResource())\n      s = &ResFileName;\n    else if (ref.AttrIndex >= 0)\n      s = &Attrs[ref.AttrIndex].Name;\n    else\n      s = &Items[ref.ItemIndex].Name;\n    *data = (const wchar_t *)(*s);\n    *dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t);\n    *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;\n    return S_OK;\n  }\n  #else\n  UNUSED_VAR(index)\n  UNUSED_VAR(propID)\n  #endif\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CRef &ref = Refs[index];\n  const CItem &item = Items[ref.ItemIndex];\n  switch (propID)\n  {\n    case kpidPath: GetItemPath(index, prop); break;\n    case kpidName:\n    {\n      const UString *s;\n      if (ref.IsResource())\n        s = &ResFileName;\n      else if (ref.AttrIndex >= 0)\n        s = &Attrs[ref.AttrIndex].Name;\n      else\n        s = &item.Name;\n      prop = *s;\n      break;\n    }\n    case kpidPackSize:\n      {\n        UInt64 size;\n        if (ref.AttrIndex >= 0)\n          size = Attrs[ref.AttrIndex].GetSize();\n        else if (ref.IsResource())\n          size = (UInt64)item.ResourceFork.NumBlocks << Header.BlockSizeLog;\n        else if (item.IsDir())\n          break;\n        else if (item.CompressHeader.IsCorrect)\n        {\n          if (item.CompressHeader.IsMethod_Resource())\n            size = (UInt64)item.ResourceFork.NumBlocks << Header.BlockSizeLog;\n          else if (item.decmpfs_AttrIndex >= 0)\n          {\n            // size = item.PackSize;\n            const CAttr &attr = Attrs[item.decmpfs_AttrIndex];\n            size = attr.Data.Size() - item.CompressHeader.DataPos;\n          }\n          else\n            size = 0;\n        }\n        else\n          size = (UInt64)item.DataFork.NumBlocks << Header.BlockSizeLog;\n        prop = size;\n        break;\n      }\n    case kpidSize:\n      {\n        UInt64 size;\n        if (ref.AttrIndex >= 0)\n          size = Attrs[ref.AttrIndex].GetSize();\n        else if (ref.IsResource())\n          size = item.ResourceFork.Size;\n        else if (item.IsDir())\n          break;\n        else if (item.CompressHeader.IsCorrect)\n          size = item.CompressHeader.UnpackSize;\n        else\n          size = item.DataFork.Size;\n        prop = size;\n        break;\n      }\n    case kpidIsDir: prop = (ref.IsItem() && item.IsDir()); break;\n    case kpidIsAltStream: prop = ref.IsAltStream(); break;\n    case kpidCTime: HfsTimeToProp(item.CTime, prop); break;\n    case kpidMTime: HfsTimeToProp(item.MTime, prop); break;\n    case kpidATime: HfsTimeToProp(item.ATime, prop); break;\n    case kpidChangeTime: HfsTimeToProp(item.AttrMTime, prop); break;\n    case kpidPosixAttrib: if (ref.IsItem()) prop = (UInt32)item.FileMode; break;\n    /*\n    case kpidUserId: prop = (UInt32)item.OwnerID; break;\n    case kpidGroupId: prop = (UInt32)item.GroupID; break;\n    */\n\n    case kpidMethod:\n      if (ref.IsItem())\n        item.CompressHeader.MethodToProp(prop);\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(inStream, callback))\n  _stream = inStream;\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _stream.Release();\n  Clear();\n  return S_OK;\n}\n\nstatic const UInt32 kCompressionBlockSize = 1 << 16;\n\nCDecoder::CDecoder(bool IsAdlerOptional)\n{\n  /* Some new hfs files contain zlib resource fork without Adler checksum.\n     We do not know how we must detect case where there is Adler\n     checksum or there is no Adler checksum.\n  */\n  _zlibDecoder->IsAdlerOptional = IsAdlerOptional;\n  _lzfseDecoder->LzvnMode = true;\n}\n\nHRESULT CDecoder::ExtractResourceFork_ZLIB(\n    ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    UInt64 forkSize, UInt64 unpackSize,\n    UInt64 progressStart, IArchiveExtractCallback *extractCallback)\n{\n  const unsigned kHeaderSize = 0x100 + 8;\n\n  const size_t kBufSize = kCompressionBlockSize;\n  _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header\n\n  RINOK(ReadStream_FALSE(inStream, _buf, kHeaderSize))\n  Byte *buf = _buf;\n  const UInt32 dataPos = Get32(buf);\n  const UInt32 mapPos = Get32(buf + 4);\n  const UInt32 dataSize = Get32(buf + 8);\n  const UInt32 mapSize = Get32(buf + 12);\n\n  const UInt32 kResMapSize = 50;\n\n  if (mapSize != kResMapSize\n      || dataPos > mapPos\n      || dataSize != mapPos - dataPos\n      || mapSize > forkSize\n      || mapPos != forkSize - mapSize)\n    return S_FALSE;\n  \n  const UInt32 dataSize2 = Get32(buf + 0x100);\n  if (4 + dataSize2 != dataSize\n      || dataSize2 < 8\n      || dataSize2 > dataSize)\n    return S_FALSE;\n  \n  const UInt32 numBlocks = GetUi32(buf + 0x100 + 4);\n  if (((dataSize2 - 4) >> 3) < numBlocks)\n    return S_FALSE;\n  {\n    const UInt64 up = unpackSize + kCompressionBlockSize - 1;\n    if (up < unpackSize || up / kCompressionBlockSize != numBlocks)\n      return S_FALSE;\n  }\n\n  const UInt32 tableSize = (numBlocks << 3);\n\n  _tableBuf.AllocAtLeast(tableSize);\n\n  RINOK(ReadStream_FALSE(inStream, _tableBuf, tableSize))\n  const Byte *tableBuf = _tableBuf;\n  \n  UInt32 prev = 4 + tableSize;\n\n  UInt32 i;\n  for (i = 0; i < numBlocks; i++)\n  {\n    const UInt32 offs = GetUi32(tableBuf + i * 8);\n    const UInt32 size = GetUi32(tableBuf + i * 8 + 4);\n    if (size == 0\n        || prev != offs\n        || offs > dataSize2\n        || size > dataSize2 - offs)\n      return S_FALSE;\n    prev = offs + size;\n  }\n\n  if (prev != dataSize2)\n    return S_FALSE;\n\n  CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;\n\n  // bool padError = false;\n  UInt64 outPos = 0;\n\n  for (i = 0; i < numBlocks; i++)\n  {\n    const UInt64 rem = unpackSize - outPos;\n    if (rem == 0)\n      return S_FALSE;\n    UInt32 blockSize = kCompressionBlockSize;\n    if (rem < kCompressionBlockSize)\n      blockSize = (UInt32)rem;\n\n    const UInt32 size = GetUi32(tableBuf + i * 8 + 4);\n\n    if (size > kCompressionBlockSize + 1)\n      return S_FALSE;\n\n    RINOK(ReadStream_FALSE(inStream, buf, size))\n\n    if ((buf[0] & 0xF) == 0xF)\n    {\n      // (buf[0] = 0xff) is marker of uncompressed block in APFS\n      // that code was not tested in HFS\n      if (size - 1 != blockSize)\n        return S_FALSE;\n\n      if (outStream)\n      {\n        RINOK(WriteStream(outStream, buf + 1, blockSize))\n      }\n    }\n    else\n    {\n      const UInt64 blockSize64 = blockSize;\n      bufInStream->Init(buf, size);\n      RINOK(_zlibDecoder.Interface()->Code(bufInStream, outStream, NULL, &blockSize64, NULL))\n      if (_zlibDecoder->GetOutputProcessedSize() != blockSize)\n        return S_FALSE;\n      const UInt64 inSize = _zlibDecoder->GetInputProcessedSize();\n      if (inSize != size)\n      {\n        if (inSize > size)\n          return S_FALSE;\n        // apfs file can contain junk (non-zeros) after data block.\n        /*\n        if (!padError)\n        {\n          const Byte *p = buf + (UInt32)inSize;\n          const Byte *e = p + (size - (UInt32)inSize);\n          do\n          {\n            if (*p != 0)\n            {\n              padError = true;\n              break;\n            }\n          }\n          while (++p != e);\n        }\n        */\n      }\n    }\n    \n    outPos += blockSize;\n    if ((i & 0xFF) == 0)\n    {\n      const UInt64 progressPos = progressStart + outPos;\n      RINOK(extractCallback->SetCompleted(&progressPos))\n    }\n  }\n\n  if (outPos != unpackSize)\n    return S_FALSE;\n\n  // if (padError) return S_FALSE;\n\n  /* We check Resource Map\n     Are there HFS files with another values in Resource Map ??? */\n\n  RINOK(ReadStream_FALSE(inStream, buf, mapSize))\n  const UInt32 types = Get16(buf + 24);\n  const UInt32 names = Get16(buf + 26);\n  const UInt32 numTypes = Get16(buf + 28);\n  if (numTypes != 0 || types != 28 || names != kResMapSize)\n    return S_FALSE;\n  const UInt32 resType = Get32(buf + 30);\n  const UInt32 numResources = Get16(buf + 34);\n  const UInt32 resListOffset = Get16(buf + 36);\n  if (resType != 0x636D7066) // cmpf\n    return S_FALSE;\n  if (numResources != 0 || resListOffset != 10)\n    return S_FALSE;\n\n  const UInt32 entryId = Get16(buf + 38);\n  const UInt32 nameOffset = Get16(buf + 40);\n  // Byte attrib = buf[42];\n  const UInt32 resourceOffset = Get32(buf + 42) & 0xFFFFFF;\n  if (entryId != 1 || nameOffset != 0xFFFF || resourceOffset != 0)\n    return S_FALSE;\n\n  return S_OK;\n}\n\n\n\nHRESULT CDecoder::ExtractResourceFork_LZFSE(\n    ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    UInt64 forkSize, UInt64 unpackSize,\n    UInt64 progressStart, IArchiveExtractCallback *extractCallback)\n{\n  const UInt32 kNumBlocksMax = (UInt32)1 << 29;\n  if (unpackSize >= (UInt64)kNumBlocksMax * kCompressionBlockSize)\n    return S_FALSE;\n  const UInt32 numBlocks = (UInt32)((unpackSize + kCompressionBlockSize - 1) / kCompressionBlockSize);\n  const UInt32 numBlocks2 = numBlocks + 1;\n  const UInt32 tableSize = (numBlocks2 << 2);\n  if (tableSize > forkSize)\n    return S_FALSE;\n  _tableBuf.AllocAtLeast(tableSize);\n  RINOK(ReadStream_FALSE(inStream, _tableBuf, tableSize))\n  const Byte *tableBuf = _tableBuf;\n  \n  {\n    UInt32 prev = GetUi32(tableBuf);\n    if (prev != tableSize)\n      return S_FALSE;\n    for (UInt32 i = 1; i < numBlocks2; i++)\n    {\n      const UInt32 offs = GetUi32(tableBuf + i * 4);\n      if (offs <= prev)\n        return S_FALSE;\n      prev = offs;\n    }\n    if (prev != forkSize)\n      return S_FALSE;\n  }\n\n  const size_t kBufSize = kCompressionBlockSize;\n  _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header\n\n  CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;\n\n  UInt64 outPos = 0;\n\n  for (UInt32 i = 0; i < numBlocks; i++)\n  {\n    const UInt64 rem = unpackSize - outPos;\n    if (rem == 0)\n      return S_FALSE;\n    UInt32 blockSize = kCompressionBlockSize;\n    if (rem < kCompressionBlockSize)\n      blockSize = (UInt32)rem;\n\n    const UInt32 size =\n        GetUi32(tableBuf + i * 4 + 4) -\n        GetUi32(tableBuf + i * 4);\n\n    if (size > kCompressionBlockSize + 1)\n      return S_FALSE;\n\n    RINOK(ReadStream_FALSE(inStream, _buf, size))\n    const Byte *buf = _buf;\n\n    if (buf[0] == k_LZVN_Uncompressed_Marker)\n    {\n      if (size - 1 != blockSize)\n        return S_FALSE;\n      if (outStream)\n      {\n        RINOK(WriteStream(outStream, buf + 1, blockSize))\n      }\n    }\n    else\n    {\n      const UInt64 blockSize64 = blockSize;\n      const UInt64 packSize64 = size;\n      bufInStream->Init(buf, size);\n      RINOK(_lzfseDecoder.Interface()->Code(bufInStream, outStream, &packSize64, &blockSize64, NULL))\n      // in/out sizes were checked in Code()\n    }\n    \n    outPos += blockSize;\n    if ((i & 0xFF) == 0)\n    {\n      const UInt64 progressPos = progressStart + outPos;\n      RINOK(extractCallback->SetCompleted(&progressPos))\n    }\n  }\n\n  return S_OK;\n}\n\n\n/*\nstatic UInt32 GetUi24(const Byte *p)\n{\n  return p[0] + ((UInt32)p[1] << 8) + ((UInt32)p[2] << 24);\n}\n\nHRESULT CDecoder::ExtractResourceFork_ZBM(\n    ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    UInt64 forkSize, UInt64 unpackSize,\n    UInt64 progressStart, IArchiveExtractCallback *extractCallback)\n{\n  const UInt32 kNumBlocksMax = (UInt32)1 << 29;\n  if (unpackSize >= (UInt64)kNumBlocksMax * kCompressionBlockSize)\n    return S_FALSE;\n  const UInt32 numBlocks = (UInt32)((unpackSize + kCompressionBlockSize - 1) / kCompressionBlockSize);\n  const UInt32 numBlocks2 = numBlocks + 1;\n  const UInt32 tableSize = (numBlocks2 << 2);\n  if (tableSize > forkSize)\n    return S_FALSE;\n  _tableBuf.AllocAtLeast(tableSize);\n  RINOK(ReadStream_FALSE(inStream, _tableBuf, tableSize));\n  const Byte *tableBuf = _tableBuf;\n  \n  {\n    UInt32 prev = GetUi32(tableBuf);\n    if (prev != tableSize)\n      return S_FALSE;\n    for (UInt32 i = 1; i < numBlocks2; i++)\n    {\n      const UInt32 offs = GetUi32(tableBuf + i * 4);\n      if (offs <= prev)\n        return S_FALSE;\n      prev = offs;\n    }\n    if (prev != forkSize)\n      return S_FALSE;\n  }\n\n  const size_t kBufSize = kCompressionBlockSize;\n  _buf.Alloc(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header\n\n  CBufInStream *bufInStream = new CBufInStream;\n  CMyComPtr<ISequentialInStream> bufInStream = bufInStream;\n\n  UInt64 outPos = 0;\n\n  for (UInt32 i = 0; i < numBlocks; i++)\n  {\n    const UInt64 rem = unpackSize - outPos;\n    if (rem == 0)\n      return S_FALSE;\n    UInt32 blockSize = kCompressionBlockSize;\n    if (rem < kCompressionBlockSize)\n      blockSize = (UInt32)rem;\n\n    const UInt32 size =\n        GetUi32(tableBuf + i * 4 + 4) -\n        GetUi32(tableBuf + i * 4);\n\n    // if (size > kCompressionBlockSize + 1)\n    if (size > blockSize + 1)\n      return S_FALSE; // we don't expect it, because encode will use uncompressed chunk\n\n    RINOK(ReadStream_FALSE(inStream, _buf, size));\n    const Byte *buf = _buf;\n\n    // (size != 0)\n    // if (size == 0) return S_FALSE;\n\n    if (buf[0] == 0xFF) // uncompressed marker\n    {\n      if (size != blockSize + 1)\n        return S_FALSE;\n      if (outStream)\n      {\n        RINOK(WriteStream(outStream, buf + 1, blockSize));\n      }\n    }\n    else\n    {\n      if (size < 4)\n        return S_FALSE;\n      if (buf[0] != 'Z' ||\n          buf[1] != 'B' ||\n          buf[2] != 'M' ||\n          buf[3] != 9)\n        return S_FALSE;\n      // for debug:\n      unsigned packPos = 4;\n      unsigned unpackPos = 0;\n      unsigned packRem = size - packPos;\n      for (;;)\n      {\n        if (packRem < 6)\n          return S_FALSE;\n        const UInt32 packSize = GetUi24(buf + packPos);\n        const UInt32 chunkUnpackSize = GetUi24(buf + packPos + 3);\n        if (packSize < 6)\n          return S_FALSE;\n        if (packSize > packRem)\n          return S_FALSE;\n        if (chunkUnpackSize > blockSize - unpackPos)\n          return S_FALSE;\n        packPos += packSize;\n        packRem -= packSize;\n        unpackPos += chunkUnpackSize;\n        if (packSize == 6)\n        {\n          if (chunkUnpackSize != 0)\n            return S_FALSE;\n          break;\n        }\n        if (packSize >= chunkUnpackSize + 6)\n        {\n          if (packSize > chunkUnpackSize + 6)\n            return S_FALSE;\n          // uncompressed chunk;\n        }\n        else\n        {\n          // compressed chunk\n          const Byte *t = buf + packPos - packSize + 6;\n          UInt32 r = packSize - 6;\n          if (r < 9)\n            return S_FALSE;\n          const UInt32 v0 = GetUi24(t);\n          const UInt32 v1 = GetUi24(t + 3);\n          const UInt32 v2 = GetUi24(t + 6);\n          if (v0 > v1 || v1 > v2 || v2 > packSize)\n            return S_FALSE;\n          // here we need the code that will decompress ZBM chunk\n        }\n      }\n\n      if (unpackPos != blockSize)\n        return S_FALSE;\n\n      UInt32 size1 = size;\n      if (size1 > kCompressionBlockSize)\n      {\n        size1 = kCompressionBlockSize;\n        // return S_FALSE;\n      }\n      if (outStream)\n      {\n        RINOK(WriteStream(outStream, buf, size1))\n\n        const UInt32 kTempSize = 1 << 16;\n        Byte temp[kTempSize];\n        memset(temp, 0, kTempSize);\n\n        for (UInt32 k = size1; k < kCompressionBlockSize; k++)\n        {\n          UInt32 cur = kCompressionBlockSize - k;\n          if (cur > kTempSize)\n            cur = kTempSize;\n          RINOK(WriteStream(outStream, temp, cur))\n          k += cur;\n        }\n      }\n\n      // const UInt64 blockSize64 = blockSize;\n      // const UInt64 packSize64 = size;\n      // bufInStream->Init(buf, size);\n      // RINOK(_zbmDecoderSpec->Code(bufInStream, outStream, &packSize64, &blockSize64, NULL));\n      // in/out sizes were checked in Code()\n    }\n    \n    outPos += blockSize;\n    if ((i & 0xFF) == 0)\n    {\n      const UInt64 progressPos = progressStart + outPos;\n      RINOK(extractCallback->SetCompleted(&progressPos));\n    }\n  }\n\n  return S_OK;\n}\n*/\n\nHRESULT CDecoder::Extract(\n    ISequentialInStream *inStreamFork, ISequentialOutStream *realOutStream,\n    UInt64 forkSize,\n    const CCompressHeader &compressHeader,\n    const CByteBuffer *data,\n    UInt64 progressStart, IArchiveExtractCallback *extractCallback,\n    int &opRes)\n{\n  opRes = NExtract::NOperationResult::kDataError;\n\n  if (compressHeader.IsMethod_Uncompressed_Inline())\n  {\n    const size_t packSize = data->Size() - compressHeader.DataPos;\n    if (realOutStream)\n    {\n      RINOK(WriteStream(realOutStream, *data + compressHeader.DataPos, packSize))\n    }\n    opRes = NExtract::NOperationResult::kOK;\n    return S_OK;\n  }\n\n  if (compressHeader.Method == kMethod_ZLIB_ATTR ||\n      compressHeader.Method == kMethod_LZVN_ATTR)\n  {\n    CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;\n    const size_t packSize = data->Size() - compressHeader.DataPos;\n    bufInStream->Init(*data + compressHeader.DataPos, packSize);\n    \n    if (compressHeader.Method == kMethod_ZLIB_ATTR)\n    {\n      const HRESULT hres = _zlibDecoder.Interface()->Code(bufInStream, realOutStream,\n          NULL, &compressHeader.UnpackSize, NULL);\n      if (hres == S_OK)\n        if (_zlibDecoder->GetOutputProcessedSize() == compressHeader.UnpackSize\n            && _zlibDecoder->GetInputProcessedSize() == packSize)\n          opRes = NExtract::NOperationResult::kOK;\n      return hres;\n    }\n    {\n      const UInt64 packSize64 = packSize;\n      const HRESULT hres = _lzfseDecoder.Interface()->Code(bufInStream, realOutStream,\n          &packSize64, &compressHeader.UnpackSize, NULL);\n      if (hres == S_OK)\n      {\n        // in/out sizes were checked in Code()\n        opRes = NExtract::NOperationResult::kOK;\n      }\n      return hres;\n    }\n  }\n\n  HRESULT hres;\n  if (compressHeader.Method == NHfs::kMethod_ZLIB_RSRC)\n  {\n    hres = ExtractResourceFork_ZLIB(\n        inStreamFork, realOutStream,\n        forkSize, compressHeader.UnpackSize,\n        progressStart, extractCallback);\n    // for debug:\n    // hres = NCompress::CopyStream(inStreamFork, realOutStream, NULL);\n  }\n  else if (compressHeader.Method == NHfs::kMethod_LZVN_RSRC)\n  {\n    hres = ExtractResourceFork_LZFSE(\n        inStreamFork, realOutStream,\n        forkSize, compressHeader.UnpackSize,\n        progressStart, extractCallback);\n  }\n  /*\n  else if (compressHeader.Method == NHfs::kMethod_ZBM_RSRC)\n  {\n    hres = ExtractResourceFork_ZBM(\n        inStreamFork, realOutStream,\n        forkSize, compressHeader.UnpackSize,\n        progressStart, extractCallback);\n  }\n  */\n  else\n  {\n    opRes = NExtract::NOperationResult::kUnsupportedMethod;\n    hres = S_FALSE;\n  }\n\n  if (hres == S_OK)\n    opRes = NExtract::NOperationResult::kOK;\n  return hres;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = Refs.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt32 i;\n  UInt64 totalSize = 0;\n  for (i = 0; i < numItems; i++)\n  {\n    const CRef &ref = Refs[allFilesMode ? i : indices[i]];\n    totalSize += Get_UnpackSize_of_Ref(ref);\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 currentTotalSize = 0, currentItemSize = 0;\n  \n  const size_t kBufSize = kCompressionBlockSize;\n  CByteBuffer buf(kBufSize + 0x10); // we need 1 additional bytes for uncompressed chunk header\n\n  // there are hfs without adler in zlib.\n  CDecoder decoder(true); // IsAdlerOptional\n\n  for (i = 0;; i++, currentTotalSize += currentItemSize)\n  {\n    RINOK(extractCallback->SetCompleted(&currentTotalSize))\n    if (i >= numItems)\n      break;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CRef &ref = Refs[index];\n    const CItem &item = Items[ref.ItemIndex];\n    currentItemSize = Get_UnpackSize_of_Ref(ref);\n\n    int opRes;\n   {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    if (ref.IsItem() && item.IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    if (!testMode && !realOutStream)\n      continue;\n    \n    RINOK(extractCallback->PrepareOperation(askMode))\n    \n    UInt64 pos = 0;\n    opRes = NExtract::NOperationResult::kDataError;\n    const CFork *fork = NULL;\n    \n    if (ref.AttrIndex >= 0)\n    {\n      const CAttr &attr = Attrs[ref.AttrIndex];\n      if (attr.Fork_defined && attr.Data.Size() == 0)\n        fork = &attr.Fork;\n      else\n      {\n        opRes = NExtract::NOperationResult::kOK;\n        if (realOutStream)\n        {\n          RINOK(WriteStream(realOutStream,\n              // AttrBuf + attr.Pos, attr.Size\n              attr.Data, attr.Data.Size()\n              ))\n        }\n      }\n    }\n    else if (ref.IsResource())\n      fork = &item.ResourceFork;\n    else if (item.CompressHeader.IsSupported)\n    {\n      CMyComPtr<ISequentialInStream> inStreamFork;\n      UInt64 forkSize = 0;\n      const CByteBuffer *decmpfs_Data = NULL;\n\n      if (item.CompressHeader.IsMethod_Resource())\n      {\n        const CFork &resourceFork = item.ResourceFork;\n        forkSize = resourceFork.Size;\n        GetForkStream(resourceFork, &inStreamFork);\n      }\n      else\n      {\n        const CAttr &attr = Attrs[item.decmpfs_AttrIndex];\n        decmpfs_Data = &attr.Data;\n      }\n\n      if (inStreamFork || decmpfs_Data)\n      {\n        const HRESULT hres = decoder.Extract(\n            inStreamFork, realOutStream,\n            forkSize,\n            item.CompressHeader,\n            decmpfs_Data,\n            currentTotalSize, extractCallback,\n            opRes);\n        if (hres != S_FALSE && hres != S_OK)\n          return hres;\n      }\n    }\n    else if (item.CompressHeader.IsCorrect)\n      opRes = NExtract::NOperationResult::kUnsupportedMethod;\n    else\n      fork = &item.DataFork;\n    \n    if (fork)\n    {\n      if (fork->IsOk(Header.BlockSizeLog))\n      {\n        opRes = NExtract::NOperationResult::kOK;\n        unsigned extentIndex;\n        for (extentIndex = 0; extentIndex < fork->Extents.Size(); extentIndex++)\n        {\n          if (opRes != NExtract::NOperationResult::kOK)\n            break;\n          if (fork->Size == pos)\n            break;\n          const CExtent &e = fork->Extents[extentIndex];\n          RINOK(InStream_SeekSet(_stream, SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog)))\n          UInt64 extentRem = (UInt64)e.NumBlocks << Header.BlockSizeLog;\n          while (extentRem != 0)\n          {\n            const UInt64 rem = fork->Size - pos;\n            if (rem == 0)\n            {\n              // Here we check that there are no extra (empty) blocks in last extent.\n              if (extentRem >= ((UInt64)1 << Header.BlockSizeLog))\n                opRes = NExtract::NOperationResult::kDataError;\n              break;\n            }\n            size_t cur = kBufSize;\n            if (cur > rem)\n              cur = (size_t)rem;\n            if (cur > extentRem)\n              cur = (size_t)extentRem;\n            RINOK(ReadStream(_stream, buf, &cur))\n            if (cur == 0)\n            {\n              opRes = NExtract::NOperationResult::kDataError;\n              break;\n            }\n            if (realOutStream)\n            {\n              RINOK(WriteStream(realOutStream, buf, cur))\n            }\n            pos += cur;\n            extentRem -= cur;\n            const UInt64 processed = currentTotalSize + pos;\n            RINOK(extractCallback->SetCompleted(&processed))\n          }\n        }\n        if (extentIndex != fork->Extents.Size() || fork->Size != pos)\n          opRes = NExtract::NOperationResult::kDataError;\n      }\n    }\n   }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = Refs.Size();\n  return S_OK;\n}\n\nHRESULT CHandler::GetForkStream(const CFork &fork, ISequentialInStream **stream)\n{\n  *stream = NULL;\n  \n  if (!fork.IsOk(Header.BlockSizeLog))\n    return S_FALSE;\n\n  CMyComPtr2<ISequentialInStream, CExtentsStream> extentStream;\n  extentStream.Create_if_Empty();\n\n  UInt64 rem = fork.Size;\n  UInt64 virt = 0;\n\n  FOR_VECTOR (i, fork.Extents)\n  {\n    const CExtent &e = fork.Extents[i];\n    if (e.NumBlocks == 0)\n      continue;\n    UInt64 cur = ((UInt64)e.NumBlocks << Header.BlockSizeLog);\n    if (cur > rem)\n    {\n      cur = rem;\n      if (i != fork.Extents.Size() - 1)\n        return S_FALSE;\n    }\n    CSeekExtent se;\n    se.Phy = SpecOffset + ((UInt64)e.Pos << Header.BlockSizeLog);\n    se.Virt = virt;\n    virt += cur;\n    rem -= cur;\n    extentStream->Extents.Add(se);\n  }\n  \n  if (rem != 0)\n    return S_FALSE;\n  \n  CSeekExtent se;\n  se.Phy = 0; // = SpecOffset ?\n  se.Virt = virt;\n  extentStream->Extents.Add(se);\n  extentStream->Stream = _stream;\n  extentStream->Init();\n  *stream = extentStream.Detach();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  *stream = NULL;\n\n  const CRef &ref = Refs[index];\n  const CFork *fork = NULL;\n  if (ref.AttrIndex >= 0)\n  {\n    const CAttr &attr = Attrs[ref.AttrIndex];\n    if (!attr.Fork_defined || attr.Data.Size() != 0)\n      return S_FALSE;\n    fork = &attr.Fork;\n  }\n  else\n  {\n    const CItem &item = Items[ref.ItemIndex];\n    if (ref.IsResource())\n      fork = &item.ResourceFork;\n    else if (item.IsDir())\n      return S_FALSE;\n    else if (item.CompressHeader.IsCorrect)\n      return S_FALSE;\n    else\n      fork = &item.DataFork;\n  }\n  return GetForkStream(*fork, stream);\n}\n\nstatic const Byte k_Signature[] = {\n    2, 'B', 'D',\n    4, 'H', '+', 0, 4,\n    4, 'H', 'X', 0, 5 };\n\nREGISTER_ARC_I(\n  \"HFS\", \"hfs hfsx\", NULL, 0xE3,\n  k_Signature,\n  kHeaderPadSize,\n  NArcInfoFlags::kMultiSignature,\n  IsArc_HFS)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/HfsHandler.h",
    "content": "﻿// HfsHandler.h\n\n#ifndef ZIP7_INC_HFS_HANDLER_H\n#define ZIP7_INC_HFS_HANDLER_H\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Compress/LzfseDecoder.h\"\n#include \"../Compress/ZlibDecoder.h\"\n\nnamespace NArchive {\nnamespace NHfs {\n\nstatic const UInt32 k_decmpfs_HeaderSize = 16;\n\nstruct CCompressHeader\n{\n  UInt64 UnpackSize;\n  UInt32 Method;\n  Byte DataPos;\n  bool IsCorrect;\n  bool IsSupported;\n  bool IsResource;\n\n  bool IsMethod_Compressed_Inline() const { return DataPos == k_decmpfs_HeaderSize; }\n  bool IsMethod_Uncompressed_Inline() const { return DataPos == k_decmpfs_HeaderSize + 1; }\n  bool IsMethod_Resource() const { return IsResource; }\n\n  void Parse(const Byte *p, size_t size);\n\n  void Clear()\n  {\n    UnpackSize = 0;\n    Method = 0;\n    DataPos = 0;\n    IsCorrect = false;\n    IsSupported = false;\n    IsResource = false;\n  }\n\n  CCompressHeader() { Clear(); }\n\n  void MethodToProp(NWindows::NCOM::CPropVariant &prop) const;\n};\n\nvoid MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop);\n\n\nclass CDecoder\n{\n  CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> _zlibDecoder;\n  CMyComPtr2_Create<ICompressCoder, NCompress::NLzfse::CDecoder> _lzfseDecoder;\n\n  CByteBuffer _tableBuf;\n  CByteBuffer _buf;\n\n  HRESULT ExtractResourceFork_ZLIB(\n      ISequentialInStream *inStream, ISequentialOutStream *realOutStream,\n      UInt64 forkSize, UInt64 unpackSize,\n      UInt64 progressStart, IArchiveExtractCallback *extractCallback);\n\n  HRESULT ExtractResourceFork_LZFSE(\n      ISequentialInStream *inStream, ISequentialOutStream *realOutStream,\n      UInt64 forkSize, UInt64 unpackSize,\n      UInt64 progressStart, IArchiveExtractCallback *extractCallback);\n\n  HRESULT ExtractResourceFork_ZBM(\n      ISequentialInStream *inStream, ISequentialOutStream *realOutStream,\n      UInt64 forkSize, UInt64 unpackSize,\n      UInt64 progressStart, IArchiveExtractCallback *extractCallback);\n\npublic:\n\n  HRESULT Extract(\n      ISequentialInStream *inStreamFork, ISequentialOutStream *realOutStream,\n      UInt64 forkSize,\n      const CCompressHeader &compressHeader,\n      const CByteBuffer *data,\n      UInt64 progressStart, IArchiveExtractCallback *extractCallback,\n      int &opRes);\n\n  CDecoder(bool IsAdlerOptional);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/IArchive.h",
    "content": "﻿// IArchive.h\n\n#ifndef ZIP7_INC_IARCHIVE_H\n#define ZIP7_INC_IARCHIVE_H\n\n#include \"../IProgress.h\"\n#include \"../IStream.h\"\n#include \"../PropID.h\"\n\nZ7_PURE_INTERFACES_BEGIN\n\n\n#define Z7_IFACE_CONSTR_ARCHIVE_SUB(i, base, n) \\\n  Z7_DECL_IFACE_7ZIP_SUB(i, base, 6, n) \\\n  { Z7_IFACE_COM7_PURE(i) };\n\n#define Z7_IFACE_CONSTR_ARCHIVE(i, n) \\\n  Z7_IFACE_CONSTR_ARCHIVE_SUB(i, IUnknown, n)\n\n/*\nHow the function in 7-Zip returns object for output parameter via pointer\n\n1) The caller sets the value of variable before function call:\n  PROPVARIANT  :  vt = VT_EMPTY\n  BSTR         :  NULL\n  IUnknown* and derived interfaces  :  NULL\n  another scalar types  :  any non-initialized value is allowed\n\n2) The callee in current 7-Zip code now can free input object for output parameter:\n  PROPVARIANT   : the callee calls VariantClear(propvaiant_ptr) for input\n                  value stored in variable\n  another types : the callee ignores stored value.\n\n3) The callee writes new value to variable for output parameter and\n  returns execution to caller.\n\n4) The caller must free or release object returned by the callee:\n  PROPVARIANT   : VariantClear(&propvaiant)\n  BSTR          : SysFreeString(bstr)\n  IUnknown* and derived interfaces  :  if (ptr) ptr->Relase()\n*/\n\n\nnamespace NFileTimeType\n{\n  enum EEnum\n  {\n    kNotDefined = -1,\n    kWindows = 0,\n    kUnix,\n    kDOS,\n    k1ns\n  };\n}\n\nnamespace NArcInfoFlags\n{\n  const UInt32 kKeepName        = 1 << 0;  // keep name of file in archive name\n  const UInt32 kAltStreams      = 1 << 1;  // the handler supports alt streams\n  const UInt32 kNtSecure        = 1 << 2;  // the handler supports NT security\n  const UInt32 kFindSignature   = 1 << 3;  // the handler can find start of archive\n  const UInt32 kMultiSignature  = 1 << 4;  // there are several signatures\n  const UInt32 kUseGlobalOffset = 1 << 5;  // the seek position of stream must be set as global offset\n  const UInt32 kStartOpen       = 1 << 6;  // call handler for each start position\n  const UInt32 kPureStartOpen   = 1 << 7;  // call handler only for start of file\n  const UInt32 kBackwardOpen    = 1 << 8;  // archive can be open backward\n  const UInt32 kPreArc          = 1 << 9;  // such archive can be stored before real archive (like SFX stub)\n  const UInt32 kSymLinks        = 1 << 10; // the handler supports symbolic links\n  const UInt32 kHardLinks       = 1 << 11; // the handler supports hard links\n  const UInt32 kByExtOnlyOpen   = 1 << 12; // call handler only if file extension matches\n  const UInt32 kHashHandler     = 1 << 13; // the handler contains the hashes (checksums)\n  const UInt32 kCTime           = 1 << 14;\n  const UInt32 kCTime_Default   = 1 << 15;\n  const UInt32 kATime           = 1 << 16;\n  const UInt32 kATime_Default   = 1 << 17;\n  const UInt32 kMTime           = 1 << 18;\n  const UInt32 kMTime_Default   = 1 << 19;\n  // const UInt32 kTTime_Reserved         = 1 << 20;\n  // const UInt32 kTTime_Reserved_Default = 1 << 21;\n}\n\nnamespace NArcInfoTimeFlags\n{\n  const unsigned kTime_Prec_Mask_bit_index = 0;\n  const unsigned kTime_Prec_Mask_num_bits = 26;\n\n  const unsigned kTime_Prec_Default_bit_index = 27;\n  const unsigned kTime_Prec_Default_num_bits = 5;\n}\n\n#define TIME_PREC_TO_ARC_FLAGS_MASK(v) \\\n  ((UInt32)1 << (NArcInfoTimeFlags::kTime_Prec_Mask_bit_index + (v)))\n\n#define TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT(v) \\\n  ((UInt32)(v) << NArcInfoTimeFlags::kTime_Prec_Default_bit_index)\n\nnamespace NArchive\n{\n  namespace NHandlerPropID\n  {\n    enum\n    {\n      kName = 0,        // VT_BSTR\n      kClassID,         // binary GUID in VT_BSTR\n      kExtension,       // VT_BSTR\n      kAddExtension,    // VT_BSTR\n      kUpdate,          // VT_BOOL\n      kKeepName,        // VT_BOOL\n      kSignature,       // binary in VT_BSTR\n      kMultiSignature,  // binary in VT_BSTR\n      kSignatureOffset, // VT_UI4\n      kAltStreams,      // VT_BOOL\n      kNtSecure,        // VT_BOOL\n      kFlags,           // VT_UI4\n      kTimeFlags        // VT_UI4\n    };\n  }\n\n  namespace NExtract\n  {\n    namespace NAskMode\n    {\n      enum\n      {\n        kExtract = 0,\n        kTest,\n        kSkip,\n        kReadExternal\n      };\n    }\n  \n    namespace NOperationResult\n    {\n      enum\n      {\n        kOK = 0,\n        kUnsupportedMethod,\n        kDataError,\n        kCRCError,\n        kUnavailable,\n        kUnexpectedEnd,\n        kDataAfterEnd,\n        kIsNotArc,\n        kHeadersError,\n        kWrongPassword\n        // , kMemError\n      };\n    }\n  }\n\n  namespace NEventIndexType\n  {\n    enum\n    {\n      kNoIndex = 0,\n      kInArcIndex,\n      kBlockIndex,\n      kOutArcIndex\n      // kArcProp\n    };\n  }\n  \n  namespace NUpdate\n  {\n    namespace NOperationResult\n    {\n      enum\n      {\n        kOK = 0\n        // kError = 1,\n        // kError_FileChanged\n      };\n    }\n  }\n}\n\n#define Z7_IFACEM_IArchiveOpenCallback(x) \\\n  x(SetTotal(const UInt64 *files, const UInt64 *bytes)) \\\n  x(SetCompleted(const UInt64 *files, const UInt64 *bytes)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveOpenCallback, 0x10)\n\n/*\nIArchiveExtractCallback::\n\n7-Zip doesn't call IArchiveExtractCallback functions\n  GetStream()\n  PrepareOperation()\n  SetOperationResult()\nfrom different threads simultaneously.\nBut 7-Zip can call functions for IProgress or ICompressProgressInfo functions\nfrom another threads simultaneously with calls for IArchiveExtractCallback interface.\n\nIArchiveExtractCallback::GetStream()\n  UInt32 index - index of item in Archive\n  Int32 askExtractMode  (Extract::NAskMode)\n    if (askMode != NExtract::NAskMode::kExtract)\n    {\n      then the callee doesn't write data to stream: (*outStream == NULL)\n    }\n  \n  Out:\n      (*outStream == NULL) - for directories\n      (*outStream == NULL) - if link (hard link or symbolic link) was created\n      if (*outStream == NULL && askMode == NExtract::NAskMode::kExtract)\n      {\n        then the caller must skip extracting of that file.\n      }\n\n  returns:\n    S_OK     : OK\n    S_FALSE  : data error (for decoders)\n\nif (IProgress::SetTotal() was called)\n{\n  IProgress::SetCompleted(completeValue) uses\n    // **************** 7-Zip ZS Modification Start ****************\n    // packSize   - for some stream formats (xz, gz, bz2, lzma, z, ppmd).\n    packSize   - for some stream formats (xz, gz, bz2, lz, lzma, z, ppmd).\n    // **************** 7-Zip ZS Modification End ****************\n    unpackSize - for another formats.\n}\nelse\n{\n  IProgress::SetCompleted(completeValue) uses packSize.\n}\n\nSetOperationResult()\n  7-Zip calls SetOperationResult at the end of extracting,\n  so the callee can close the file, set attributes, timestamps and security information.\n\n  Int32 opRes (NExtract::NOperationResult)\n*/\n\n// INTERFACE_IProgress(x)\n\n#define Z7_IFACEM_IArchiveExtractCallback(x) \\\n  x(GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)) \\\n  x(PrepareOperation(Int32 askExtractMode)) \\\n  x(SetOperationResult(Int32 opRes)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveExtractCallback, IProgress, 0x20)\n\n\n\n/*\nv23:\nIArchiveExtractCallbackMessage2 can be requested from IArchiveExtractCallback object\n  by Extract() or UpdateItems() functions to report about extracting errors\nReportExtractResult()\n  UInt32 indexType (NEventIndexType)\n  UInt32 index\n  Int32 opRes (NExtract::NOperationResult)\n*/\n/*\nbefore v23:\n#define Z7_IFACEM_IArchiveExtractCallbackMessage(x) \\\n  x(ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes))\nZ7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveExtractCallbackMessage, IProgress, 0x21)\n*/\n#define Z7_IFACEM_IArchiveExtractCallbackMessage2(x) \\\n  x(ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes))\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveExtractCallbackMessage2, 0x22)\n\n#define Z7_IFACEM_IArchiveOpenVolumeCallback(x) \\\n  x(GetProperty(PROPID propID, PROPVARIANT *value)) \\\n  x(GetStream(const wchar_t *name, IInStream **inStream))\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveOpenVolumeCallback, 0x30)\n\n\n#define Z7_IFACEM_IInArchiveGetStream(x) \\\n  x(GetStream(UInt32 index, ISequentialInStream **stream))\nZ7_IFACE_CONSTR_ARCHIVE(IInArchiveGetStream, 0x40)\n\n#define Z7_IFACEM_IArchiveOpenSetSubArchiveName(x) \\\n  x(SetSubArchiveName(const wchar_t *name))\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveOpenSetSubArchiveName, 0x50)\n\n\n/*\nIInArchive::Open\n    stream\n      if (kUseGlobalOffset), stream current position can be non 0.\n      if (!kUseGlobalOffset), stream current position is 0.\n    if (maxCheckStartPosition == NULL), the handler can try to search archive start in stream\n    if (*maxCheckStartPosition == 0), the handler must check only current position as archive start\n\nIInArchive::Extract:\n  indices must be sorted\n  numItems = (UInt32)(Int32)-1 = 0xFFFFFFFF means \"all files\"\n  testMode != 0 means \"test files without writing to outStream\"\n\nIInArchive::GetArchiveProperty:\n  kpidOffset  - start offset of archive.\n      VT_EMPTY : means offset = 0.\n      VT_UI4, VT_UI8, VT_I8 : result offset; negative values is allowed\n  kpidPhySize - size of archive. VT_EMPTY means unknown size.\n    kpidPhySize is allowed to be larger than file size. In that case it must show\n    supposed size.\n\n  kpidIsDeleted:\n  kpidIsAltStream:\n  kpidIsAux:\n  kpidINode:\n    must return VARIANT_TRUE (VT_BOOL), if archive can support that property in GetProperty.\n\n\nNotes:\n  Don't call IInArchive functions for same IInArchive object from different threads simultaneously.\n  Some IInArchive handlers will work incorrectly in that case.\n*/\n\n#if defined(_MSC_VER) && !defined(__clang__)\n  #define MY_NO_THROW_DECL_ONLY  Z7_COM7F_E\n#else\n  #define MY_NO_THROW_DECL_ONLY\n#endif\n\n#define Z7_IFACEM_IInArchive(x) \\\n  x(Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openCallback)) \\\n  x(Close()) \\\n  x(GetNumberOfItems(UInt32 *numItems)) \\\n  x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \\\n  x(Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback)) \\\n  x(GetArchiveProperty(PROPID propID, PROPVARIANT *value)) \\\n  x(GetNumberOfProperties(UInt32 *numProps)) \\\n  x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \\\n  x(GetNumberOfArchiveProperties(UInt32 *numProps)) \\\n  x(GetArchivePropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE(IInArchive, 0x60)\n\nnamespace NParentType\n{\n  enum\n  {\n    kDir = 0,\n    kAltStream\n  };\n}\n\nnamespace NPropDataType\n{\n  const UInt32 kMask_ZeroEnd   = 1 << 4;\n  // const UInt32 kMask_BigEndian = 1 << 5;\n  const UInt32 kMask_Utf       = 1 << 6;\n  const UInt32 kMask_Utf8  = kMask_Utf | 0;\n  const UInt32 kMask_Utf16 = kMask_Utf | 1;\n  // const UInt32 kMask_Utf32 = kMask_Utf | 2;\n\n  const UInt32 kNotDefined = 0;\n  const UInt32 kRaw = 1;\n\n  const UInt32 kUtf8z  = kMask_Utf8  | kMask_ZeroEnd;\n  const UInt32 kUtf16z = kMask_Utf16 | kMask_ZeroEnd;\n}\n\n// UTF string (pointer to wchar_t) with zero end and little-endian.\n#define PROP_DATA_TYPE_wchar_t_PTR_Z_LE ((NPropDataType::kMask_Utf | NPropDataType::kMask_ZeroEnd) + (sizeof(wchar_t) >> 1))\n\n\n/*\nGetRawProp:\n  Result:\n    S_OK - even if property is not set\n*/\n\n#define Z7_IFACEM_IArchiveGetRawProps(x) \\\n  x(GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)) \\\n  x(GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) \\\n  x(GetNumRawProps(UInt32 *numProps)) \\\n  x(GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))\n\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveGetRawProps, 0x70)\n\n#define Z7_IFACEM_IArchiveGetRootProps(x) \\\n  x(GetRootProp(PROPID propID, PROPVARIANT *value)) \\\n  x(GetRootRawProp(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) \\\n \nZ7_IFACE_CONSTR_ARCHIVE(IArchiveGetRootProps, 0x71)\n\n#define Z7_IFACEM_IArchiveOpenSeq(x) \\\n  x(OpenSeq(ISequentialInStream *stream)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveOpenSeq, 0x61)\n\n/*\n  OpenForSize\n  Result:\n    S_FALSE - is not archive\n    ? - DATA error\n*/\n    \n/*\nconst UInt32 kOpenFlags_RealPhySize = 1 << 0;\nconst UInt32 kOpenFlags_NoSeek = 1 << 1;\n// const UInt32 kOpenFlags_BeforeExtract = 1 << 2;\n*/\n\n/*\nFlags:\n   0 - opens archive with IInStream, if IInStream interface is supported\n     - if phySize is not available, it doesn't try to make full parse to get phySize\n   kOpenFlags_NoSeek -  ArcOpen2 function doesn't use IInStream interface, even if it's available\n   kOpenFlags_RealPhySize - the handler will try to get PhySize, even if it requires full decompression for file\n   \n  if handler is not allowed to use IInStream and the flag kOpenFlags_RealPhySize is not specified,\n  the handler can return S_OK, but it doesn't check even Signature.\n  So next Extract can be called for that sequential stream.\n*/\n/*\n#define Z7_IFACEM_IArchiveOpen2(x) \\\n  x(ArcOpen2(ISequentialInStream *stream, UInt32 flags, IArchiveOpenCallback *openCallback))\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveOpen2, 0x62)\n*/\n\n// ---------- UPDATE ----------\n\n/*\nGetUpdateItemInfo outs:\n*newData  *newProps\n   0        0      - Copy data and properties from archive\n   0        1      - Copy data from archive, request new properties\n   1        0      - that combination is unused now\n   1        1      - Request new data and new properties. It can be used even for folders\n\n  indexInArchive = -1 if there is no item in archive, or if it doesn't matter.\n\n\nGetStream out:\n  Result:\n    S_OK:\n      (*inStream == NULL) - only for directories\n                          - the bug was fixed in 9.33: (*Stream == NULL) was in case of anti-file\n      (*inStream != NULL) - for any file, even for empty file or anti-file\n    S_FALSE - skip that file (don't add item to archive) - (client code can't open stream of that file by some reason)\n      (*inStream == NULL)\n\nThe order of calling for hard links:\n  - GetStream()\n  - GetProperty(kpidHardLink)\n\nSetOperationResult()\n  Int32 opRes (NExtract::NOperationResult::kOK)\n*/\n\n// INTERFACE_IProgress(x)\n#define Z7_IFACEM_IArchiveUpdateCallback(x) \\\n  x(GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProps, UInt32 *indexInArchive)) \\\n  x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \\\n  x(GetStream(UInt32 index, ISequentialInStream **inStream)) \\\n  x(SetOperationResult(Int32 operationResult)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveUpdateCallback, IProgress, 0x80)\n\n// INTERFACE_IArchiveUpdateCallback(x)\n#define Z7_IFACEM_IArchiveUpdateCallback2(x) \\\n  x(GetVolumeSize(UInt32 index, UInt64 *size)) \\\n  x(GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)\n\nnamespace NUpdateNotifyOp\n{\n  enum\n  {\n    kAdd = 0,\n    kUpdate,\n    kAnalyze,\n    kReplicate,\n    kRepack,\n    kSkip,\n    kDelete,\n    kHeader,\n    kHashRead,\n    kInFileChanged\n    // , kOpFinished\n    // , kNumDefined\n  };\n}\n\n/*\nIArchiveUpdateCallbackFile::ReportOperation\n  UInt32 indexType (NEventIndexType)\n  UInt32 index\n  UInt32 notifyOp (NUpdateNotifyOp)\n*/\n\n#define Z7_IFACEM_IArchiveUpdateCallbackFile(x) \\\n  x(GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 notifyOp)) \\\n  x(ReportOperation(UInt32 indexType, UInt32 index, UInt32 notifyOp)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveUpdateCallbackFile, 0x83)\n\n\n#define Z7_IFACEM_IArchiveGetDiskProperty(x) \\\n  x(GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \\\n  \nZ7_IFACE_CONSTR_ARCHIVE(IArchiveGetDiskProperty, 0x84)\n\n/*\n#define Z7_IFACEM_IArchiveUpdateCallbackArcProp(x) \\\n  x(ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value)) \\\n  x(ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType)) \\\n  x(ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes)) \\\n  x(DoNeedArcProp(PROPID propID, Int32 *answer)) \\\n \nZ7_IFACE_CONSTR_ARCHIVE(IArchiveUpdateCallbackArcProp, 0x85)\n*/\n\n/*\nUpdateItems()\n-------------\n\n  outStream: output stream. (the handler) MUST support the case when\n    Seek position in outStream is not ZERO.\n    but the caller calls with empty outStream and seek position is ZERO??\n \n  archives with stub:\n\n  If archive is open and the handler and (Offset > 0), then the handler\n  knows about stub size.\n  UpdateItems():\n  1) the handler MUST copy that stub to outStream\n  2) the caller MUST NOT copy the stub to outStream, if\n     \"rsfx\" property is set with SetProperties\n\n  the handler must support the case where\n    ISequentialOutStream *outStream\n*/\n\n\n#define Z7_IFACEM_IOutArchive(x) \\\n  x(UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback)) \\\n  x(GetFileTimeType(UInt32 *type))\n\nZ7_IFACE_CONSTR_ARCHIVE(IOutArchive, 0xA0)\n\n\n/*\nISetProperties::SetProperties()\n  PROPVARIANT values[i].vt:\n    VT_EMPTY\n    VT_BOOL\n    VT_UI4   - if 32-bit number\n    VT_UI8   - if 64-bit number\n    VT_BSTR\n*/\n\n#define Z7_IFACEM_ISetProperties(x) \\\n  x(SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n\nZ7_IFACE_CONSTR_ARCHIVE(ISetProperties, 0x03)\n\n#define Z7_IFACEM_IArchiveKeepModeForNextOpen(x) \\\n  x(KeepModeForNextOpen()) \\\n\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveKeepModeForNextOpen, 0x04)\n\n/* Exe handler: the handler for executable format (PE, ELF, Mach-O).\n   SFX archive: executable stub + some tail data.\n     before 9.31: exe handler didn't parse SFX archives as executable format.\n     for 9.31+: exe handler parses SFX archives as executable format, only if AllowTail(1) was called */\n\n#define Z7_IFACEM_IArchiveAllowTail(x) \\\n  x(AllowTail(Int32 allowTail)) \\\n\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveAllowTail, 0x05)\n\n\nnamespace NRequestMemoryUseFlags\n{\n  const UInt32 k_AllowedSize_WasForced    = 1 << 0;  // (*allowedSize) was forced by -mmemx or -smemx\n  const UInt32 k_DefaultLimit_Exceeded    = 1 << 1;  // default limit of archive format was exceeded\n  const UInt32 k_MLimit_Exceeded          = 1 << 2;  // -mmemx value was exceeded\n  const UInt32 k_SLimit_Exceeded          = 1 << 3;  // -smemx value was exceeded\n  \n  const UInt32 k_NoErrorMessage           = 1 << 10; // do not show error message, and show only request\n  const UInt32 k_IsReport                 = 1 << 11; // only report is required, without user request\n  \n  const UInt32 k_SkipArc_IsExpected       = 1 << 12; // NRequestMemoryAnswerFlags::k_SkipArc flag answer is expected\n  const UInt32 k_Report_SkipArc           = 1 << 13; // report about SkipArc operation\n\n  // const UInt32 k_SkipBigFile_IsExpected   = 1 << 14; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused)\n  // const UInt32 k_Report_SkipBigFile       = 1 << 15; // report about SkipFile operation (unused)\n\n  // const UInt32 k_SkipBigFiles_IsExpected  = 1 << 16; // NRequestMemoryAnswerFlags::k_SkipBigFiles flag answer is expected (unused)\n  // const UInt32 k_Report_SkipBigFiles      = 1 << 17; // report that all big files will be skipped (unused)\n}\n\nnamespace NRequestMemoryAnswerFlags\n{\n  const UInt32 k_Allow          = 1 << 0;  // allow further archive extraction\n  const UInt32 k_Stop           = 1 << 1;  // for exit (and return_code == E_ABORT is used)\n  const UInt32 k_SkipArc        = 1 << 2;  // skip current archive extraction\n  // const UInt32 k_SkipBigFile    = 1 << 4;  // skip extracting of files that exceed limit (unused)\n  // const UInt32 k_SkipBigFiles   = 1 << 5;  // skip extracting of files that exceed limit (unused)\n  const UInt32 k_Limit_Exceeded  = 1 << 10;  // limit was exceeded\n}\n\n/*\n  *allowedSize is in/out:\n    in  : default allowed memory usage size or forced size, if it was changed by switch -mmemx.\n    out : value specified by user or unchanged value.\n\n  *answerFlags is in/out:\n    *answerFlags must be set by caller before calling for default action,\n\n  indexType : must be set with NEventIndexType::* constant\n          (indexType == kNoIndex), if request for whole archive.\n  index : must be set for some (indexType) types (if\n          fileIndex , if (indexType == NEventIndexType::kInArcIndex)\n          0, if       if (indexType == kNoIndex)\n  path : NULL can be used for any indexType.\n*/\n#define Z7_IFACEM_IArchiveRequestMemoryUseCallback(x) \\\n  x(RequestMemoryUse(UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path, \\\n    UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))\nZ7_IFACE_CONSTR_ARCHIVE(IArchiveRequestMemoryUseCallback, 0x09)\n\n\nstruct CStatProp\n{\n  const char *Name;\n  UInt32 PropID;\n  VARTYPE vt;\n};\n\nnamespace NWindows {\nnamespace NCOM {\n// PropVariant.cpp\nBSTR AllocBstrFromAscii(const char *s) throw();\n}}\n\n\n#define IMP_IInArchive_GetProp_Base(fn, f, k) \\\n  Z7_COM7F_IMF(CHandler::fn(UInt32 *numProps)) \\\n    { *numProps = Z7_ARRAY_SIZE(k); return S_OK; } \\\n  Z7_COM7F_IMF(CHandler::f(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \\\n    { if (index >= Z7_ARRAY_SIZE(k)) return E_INVALIDARG; \\\n\n#define IMP_IInArchive_GetProp_NO_NAME(fn, f, k) \\\n  IMP_IInArchive_GetProp_Base(fn, f, k) \\\n    *propID = k[index]; \\\n    *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID]; \\\n    *name = NULL; return S_OK; } \\\n\n#define IMP_IInArchive_GetProp_WITH_NAME(fn, f, k) \\\n  IMP_IInArchive_GetProp_Base(fn, f, k) \\\n    const CStatProp &prop = k[index]; \\\n    *propID = (PROPID)prop.PropID; \\\n    *varType = prop.vt; \\\n    *name = NWindows::NCOM::AllocBstrFromAscii(prop.Name); return S_OK; } \\\n\n\n#define IMP_IInArchive_Props \\\n  IMP_IInArchive_GetProp_NO_NAME(GetNumberOfProperties, GetPropertyInfo, kProps)\n\n#define IMP_IInArchive_Props_WITH_NAME \\\n  IMP_IInArchive_GetProp_WITH_NAME(GetNumberOfProperties, GetPropertyInfo, kProps)\n\n#define IMP_IInArchive_ArcProps \\\n  IMP_IInArchive_GetProp_NO_NAME(GetNumberOfArchiveProperties, GetArchivePropertyInfo, kArcProps)\n\n#define IMP_IInArchive_ArcProps_WITH_NAME \\\n  IMP_IInArchive_GetProp_WITH_NAME(GetNumberOfArchiveProperties, GetArchivePropertyInfo, kArcProps)\n\n#define IMP_IInArchive_ArcProps_NO_Table \\\n  Z7_COM7F_IMF(CHandler::GetNumberOfArchiveProperties(UInt32 *numProps)) \\\n    { *numProps = 0; return S_OK; } \\\n  Z7_COM7F_IMF(CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *)) \\\n    { return E_NOTIMPL; } \\\n\n#define IMP_IInArchive_ArcProps_NO \\\n  IMP_IInArchive_ArcProps_NO_Table \\\n  Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value)) \\\n    { value->vt = VT_EMPTY; return S_OK; }\n\n\n#define Z7_class_CHandler_final \\\n        Z7_class_final(CHandler)\n\n\n#define Z7_CLASS_IMP_CHandler_IInArchive_0 \\\n  Z7_CLASS_IMP_COM_1(CHandler, IInArchive)\n#define Z7_CLASS_IMP_CHandler_IInArchive_1(i1) \\\n  Z7_CLASS_IMP_COM_2(CHandler, IInArchive, i1)\n#define Z7_CLASS_IMP_CHandler_IInArchive_2(i1, i2) \\\n  Z7_CLASS_IMP_COM_3(CHandler, IInArchive, i1, i2)\n#define Z7_CLASS_IMP_CHandler_IInArchive_3(i1, i2, i3) \\\n  Z7_CLASS_IMP_COM_4(CHandler, IInArchive, i1, i2, i3)\n#define Z7_CLASS_IMP_CHandler_IInArchive_4(i1, i2, i3, i4) \\\n  Z7_CLASS_IMP_COM_5(CHandler, IInArchive, i1, i2, i3, i4)\n#define Z7_CLASS_IMP_CHandler_IInArchive_5(i1, i2, i3, i4, i5) \\\n  Z7_CLASS_IMP_COM_6(CHandler, IInArchive, i1, i2, i3, i4, i5)\n\n\n\n#define k_IsArc_Res_NO   0\n#define k_IsArc_Res_YES  1\n#define k_IsArc_Res_NEED_MORE 2\n// #define k_IsArc_Res_YES_LOW_PROB 3\n\n#define API_FUNC_IsArc EXTERN_C UInt32 WINAPI\n#define API_FUNC_static_IsArc extern \"C\" { static UInt32 WINAPI\n\nextern \"C\"\n{\n  typedef HRESULT (WINAPI *Func_CreateObject)(const GUID *clsID, const GUID *iid, void **outObject);\n\n  typedef UInt32 (WINAPI *Func_IsArc)(const Byte *p, size_t size);\n  typedef HRESULT (WINAPI *Func_GetIsArc)(UInt32 formatIndex, Func_IsArc *isArc);\n  // **************** 7-Zip ZS Modification Start ****************\n  typedef HRESULT (WINAPI *Func_GetFormatLevelMask)(UInt32 formatIndex, UInt32 *mask);\n  // **************** 7-Zip ZS Modification End ****************\n\n  typedef HRESULT (WINAPI *Func_GetNumberOfFormats)(UInt32 *numFormats);\n  typedef HRESULT (WINAPI *Func_GetHandlerProperty)(PROPID propID, PROPVARIANT *value);\n  typedef HRESULT (WINAPI *Func_GetHandlerProperty2)(UInt32 index, PROPID propID, PROPVARIANT *value);\n\n  typedef HRESULT (WINAPI *Func_SetCaseSensitive)(Int32 caseSensitive);\n  typedef HRESULT (WINAPI *Func_SetLargePageMode)();\n  // typedef HRESULT (WINAPI *Func_SetClientVersion)(UInt32 version);\n\n  typedef IOutArchive * (*Func_CreateOutArchive)();\n  typedef IInArchive * (*Func_CreateInArchive)();\n}\n\n\n/*\n  if there is no time in archive, external MTime of archive\n  will be used instead of _item.Time from archive.\n  For 7-zip before 22.00 we need to return some supported value.\n  But (kpidTimeType > kDOS) is not allowed in 7-Zip before 22.00.\n  So we return highest precision value supported by old 7-Zip.\n  new 7-Zip 22.00 doesn't use that value in usual cases.\n*/\n\n\n#define DECLARE_AND_SET_CLIENT_VERSION_VAR\n#define GET_FileTimeType_NotDefined_for_GetFileTimeType \\\n      NFileTimeType::kWindows\n\n/*\nextern UInt32 g_ClientVersion;\n\n#define GET_CLIENT_VERSION(major, minor)  \\\n  ((UInt32)(((UInt32)(major) << 16) | (UInt32)(minor)))\n\n#define DECLARE_AND_SET_CLIENT_VERSION_VAR \\\n  UInt32 g_ClientVersion = GET_CLIENT_VERSION(MY_VER_MAJOR, MY_VER_MINOR);\n\n#define GET_FileTimeType_NotDefined_for_GetFileTimeType \\\n      ((UInt32)(g_ClientVersion >= GET_CLIENT_VERSION(22, 0) ? \\\n        (UInt32)(Int32)NFileTimeType::kNotDefined : \\\n        NFileTimeType::kWindows))\n*/\n\nZ7_PURE_INTERFACES_END\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/IhexHandler.cpp",
    "content": "﻿// IhexHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/DynamicBuffer.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/StringToInt.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/InBuffer.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\nnamespace NArchive {\nnamespace NIhex {\n\n/* We still don't support files with custom record types: 20, 22: used by Samsung */\n\nstruct CBlock\n{\n  CByteDynamicBuffer Data;\n  UInt32 Offset;\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  bool _isArc;\n  bool _needMoreInput;\n  bool _dataError;\n  \n  UInt64 _phySize;\n\n  CObjectVector<CBlock> _blocks;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidVa\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _blocks.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_phySize != 0) prop = _phySize; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_dataError) v |= kpv_ErrorFlags_DataError;\n      prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CBlock &block = _blocks[index];\n  switch (propID)\n  {\n    case kpidSize: prop = (UInt64)block.Data.GetPos(); break;\n    case kpidVa: prop = block.Offset; break;\n    case kpidPath:\n    {\n      if (_blocks.Size() != 1)\n      {\n        char s[16];\n        ConvertUInt32ToString(index, s);\n        prop = s;\n      }\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nstatic int Parse(const Byte *p)\n{\n  unsigned v0 = p[0];  Z7_PARSE_HEX_DIGIT(v0, return -1;)\n  unsigned v1 = p[1];  Z7_PARSE_HEX_DIGIT(v1, return -1;)\n  return (int)((v0 << 4) | v1);\n}\n  \n#define kType_Data 0\n#define kType_Eof  1\n#define kType_Seg  2\n// #define kType_CsIp 3\n#define kType_High 4\n// #define kType_Ip32 5\n\n#define kType_MAX  5\n\n// we don't want to read files with big number of spaces between records\n// it's our limitation (out of specification):\nstatic const unsigned k_NumSpaces_LIMIT = 16 + 1;\n\n#define IS_LINE_DELIMITER(c) (/* (c) == 0 || */ (c) == 10 || (c) == 13)\n\nAPI_FUNC_static_IsArc IsArc_Ihex(const Byte *p, size_t size)\n{\n  if (size < 1)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != ':')\n    return k_IsArc_Res_NO;\n  p++;\n  size--;\n\n  const unsigned kNumLinesToCheck = 3; // 1 line is OK also, but we don't want false detection\n\n  for (unsigned j = 0; j < kNumLinesToCheck; j++)\n  {\n    if (size < 4 * 2)\n      return k_IsArc_Res_NEED_MORE;\n    \n    const int num = Parse(p);\n    if (num < 0)\n      return k_IsArc_Res_NO;\n    \n    const int type = Parse(p + 6);\n    if (type < 0 || type > kType_MAX)\n      return k_IsArc_Res_NO;\n    \n    unsigned numChars = ((unsigned)num + 5) * 2;\n    unsigned sum = 0;\n    \n    for (unsigned i = 0; i < numChars; i += 2)\n    {\n      if (i + 2 > size)\n        return k_IsArc_Res_NEED_MORE;\n      int v = Parse(p + i);\n      if (v < 0)\n        return k_IsArc_Res_NO;\n      sum += (unsigned)v;\n    }\n    \n    if (sum & 0xFF)\n      return k_IsArc_Res_NO;\n\n    if (type == kType_Data)\n    {\n      // we don't want to open :0000000000 files\n      if (num == 0)\n        return k_IsArc_Res_NO;\n    }\n    else\n    {\n      if (type == kType_Eof)\n      {\n        if (num != 0)\n          return k_IsArc_Res_NO;\n        return k_IsArc_Res_YES;\n      }\n      if (p[2] != 0 ||\n          p[3] != 0 ||\n          p[4] != 0 ||\n          p[5] != 0)\n        return k_IsArc_Res_NO;\n      if (type == kType_Seg || type == kType_High)\n      {\n        if (num != 2)\n          return k_IsArc_Res_NO;\n      }\n      else\n      {\n        if (num != 4)\n          return k_IsArc_Res_NO;\n      }\n    }\n    \n    p += numChars;\n    size -= numChars;\n    \n    unsigned numSpaces = k_NumSpaces_LIMIT;\n    for (;;)\n    {\n      if (size == 0)\n        return k_IsArc_Res_NEED_MORE;\n      const Byte b = *p++;\n      size--;\n      if (b == ':')\n        break;\n      if (--numSpaces == 0 || !IS_LINE_DELIMITER(b))\n        return k_IsArc_Res_NO;\n    }\n  }\n  \n  return k_IsArc_Res_YES;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openCallback))\n{\n  COM_TRY_BEGIN\n  {\n  Close();\n  try\n  {\n    const unsigned kStartSize = (2 + (256 + 5) + 2) * 2;\n    Byte temp[kStartSize];\n    {\n      size_t size = kStartSize;\n      RINOK(ReadStream(stream, temp, &size))\n      const UInt32 isArcRes = IsArc_Ihex(temp, size);\n      if (isArcRes == k_IsArc_Res_NO)\n        return S_FALSE;\n      if (isArcRes == k_IsArc_Res_NEED_MORE && size != kStartSize)\n        return S_FALSE;\n    }\n    _isArc = true;\n\n    RINOK(InStream_SeekToBegin(stream))\n    CInBuffer s;\n    if (!s.Create(1 << 15))\n      return E_OUTOFMEMORY;\n    s.SetStream(stream);\n    s.Init();\n    {\n      Byte b;\n      if (!s.ReadByte(b))\n      {\n        _needMoreInput = true;\n        return S_FALSE;\n      }\n      if (b != ':')\n      {\n        _dataError = true;\n        return S_FALSE;\n      }\n    }\n\n    UInt32 globalOffset = 0;\n    const UInt32 k_progressStep = 1 << 24;\n    UInt64 progressNext = k_progressStep;\n\n    for (;;)\n    {\n      if (s.ReadBytes(temp, 2) != 2)\n      {\n        _needMoreInput = true;\n        return S_FALSE;\n      }\n      const int num = Parse(temp);\n      if (num < 0)\n      {\n        _dataError = true;\n        return S_FALSE;\n      }\n      {\n        const size_t numPairs = (unsigned)num + 4;\n        const size_t numBytes = numPairs * 2;\n        if (s.ReadBytes(temp, numBytes) != numBytes)\n        {\n          _needMoreInput = true;\n          return S_FALSE;\n        }\n        unsigned sum = (unsigned)num;\n        for (size_t i = 0; i < numPairs; i++)\n        {\n          const int a = Parse(temp + i * 2);\n          if (a < 0)\n          {\n            _dataError = true;\n            return S_FALSE;\n          }\n          temp[i] = (Byte)a;\n          sum += (unsigned)a;\n        }\n        if (sum & 0xFF)\n        {\n          _dataError = true;\n          return S_FALSE;\n        }\n      }\n\n      const unsigned type = temp[2];\n      if (type > kType_MAX)\n      {\n        _dataError = true;\n        return S_FALSE;\n      }\n\n      const UInt32 a = GetBe16(temp);\n\n      if (type == kType_Data)\n      {\n        if (num == 0)\n        {\n          // we don't want to open :0000000000 files\n          // maybe it can mean EOF in old-style files?\n          _dataError = true;\n          return S_FALSE;\n        }\n        // if (num != 0)\n        {\n          const UInt32 offs = globalOffset + a;\n          CBlock *block = NULL;\n          if (!_blocks.IsEmpty())\n          {\n            block = &_blocks.Back();\n            if (block->Offset + block->Data.GetPos() != offs)\n              block = NULL;\n          }\n          if (!block)\n          {\n            block = &_blocks.AddNew();\n            block->Offset = offs;\n          }\n          block->Data.AddData(temp + 3, (unsigned)num);\n        }\n      }\n      else\n      {\n        if (a != 0) // from description: the address field is typically 0.\n        {\n          _dataError = true;\n          return S_FALSE;\n        }\n        if (type == kType_Eof)\n        {\n          if (num != 0)\n          {\n            _dataError = true;\n            return S_FALSE;\n          }\n          _phySize = s.GetProcessedSize();\n          Byte b;\n          if (s.ReadByte(b))\n          {\n            if (b == 10)\n              _phySize++;\n            else if (b == 13)\n            {\n              _phySize++;\n              if (s.ReadByte(b))\n              {\n                if (b == 10)\n                  _phySize++;\n              }\n            }\n          }\n          return S_OK;\n        }\n  \n        if (type == kType_Seg || type == kType_High)\n        {\n          if (num != 2)\n          {\n            _dataError = true;\n            return S_FALSE;\n          }\n          // here we use optimization trick for num shift calculation: (type == kType_Seg ? 4 : 16)\n          globalOffset = (UInt32)GetBe16(temp + 3) << (1u << type);\n        }\n        else\n        {\n          if (num != 4)\n          {\n            _dataError = true;\n            return S_FALSE;\n          }\n        }\n      }\n\n      if (openCallback)\n      {\n        const UInt64 processed = s.GetProcessedSize();\n        if (processed >= progressNext)\n        {\n          progressNext = processed + k_progressStep;\n          const UInt64 numFiles = _blocks.Size();\n          RINOK(openCallback->SetCompleted(&numFiles, &processed))\n        }\n      }\n\n      unsigned numSpaces = k_NumSpaces_LIMIT;\n      for (;;)\n      {\n        Byte b;\n        if (!s.ReadByte(b))\n        {\n          _needMoreInput = true;\n          return S_FALSE;\n        }\n        if (b == ':')\n          break;\n        if (--numSpaces == 0 || !IS_LINE_DELIMITER(b))\n        {\n          _dataError = true;\n          return S_FALSE;\n        }\n      }\n    }\n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  }\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _phySize = 0;\n  _isArc = false;\n  _needMoreInput = false;\n  _dataError = false;\n  _blocks.Clear();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _blocks.Size();\n  if (numItems == 0)\n    return S_OK;\n\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _blocks[allFilesMode ? i : indices[i]].Data.GetPos();\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = lps->OutSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CByteDynamicBuffer &data = _blocks[index].Data;\n    lps->OutSize += data.GetPos();\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      const Int32 askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      if (realOutStream)\n        RINOK(WriteStream(realOutStream, (const Byte *)data, data.GetPos()))\n    }\n    RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n  }\n  \n  return S_OK;\n  COM_TRY_END\n}\n\n// k_Signature: { ':' }\n\nREGISTER_ARC_I_NO_SIG(\n  \"IHex\", \"ihex\", NULL, 0xCD,\n  0,\n  NArcInfoFlags::kStartOpen,\n  IsArc_Ihex)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoHandler.cpp",
    "content": "﻿// IsoHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"IsoHandler.h\"\n\nusing namespace NWindows;\nusing namespace NTime;\n\nnamespace NArchive {\nnamespace NIso {\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  // kpidCTime,\n  // kpidATime,\n  kpidPosixAttrib,\n  // kpidUserId,\n  // kpidGroupId,\n  // kpidLinks,\n  kpidSymLink\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidComment,\n  kpidCTime,\n  kpidMTime,\n  // kpidHeadersSize\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    RINOK(_archive.Open(stream))\n    _stream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _archive.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _archive.Refs.Size() + _archive.BootEntries.Size();\n  return S_OK;\n}\n\nstatic void AddString(AString &s, const char *name, const Byte *p, unsigned size)\n{\n  unsigned i;\n  for (i = 0; i < size && p[i]; i++);\n  for (; i > 0 && p[i - 1] == ' '; i--);\n  if (i != 0)\n  {\n    AString d;\n    d.SetFrom((const char *)p, i);\n    s += name;\n    s += \": \";\n    s += d;\n    s.Add_LF();\n  }\n}\n\nstatic void AddProp_Size64(AString &s, const char *name, UInt64 size)\n{\n  s += name;\n  s += \": \";\n  s.Add_UInt64(size);\n  s.Add_LF();\n}\n\n#define ADD_STRING(n, v) AddString(s, n, vol. v, sizeof(vol. v))\n\nstatic void AddErrorMessage(AString &s, const char *message)\n{\n  if (!s.IsEmpty())\n    s += \". \";\n  s += message;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  if (_stream)\n  {\n  const CVolumeDescriptor &vol = _archive.VolDescs[_archive.MainVolDescIndex];\n  switch (propID)\n  {\n    case kpidComment:\n    {\n      AString s;\n      ADD_STRING(\"System\", SystemId);\n      ADD_STRING(\"Volume\", VolumeId);\n      ADD_STRING(\"VolumeSet\", VolumeSetId);\n      ADD_STRING(\"Publisher\", PublisherId);\n      ADD_STRING(\"Preparer\", DataPreparerId);\n      ADD_STRING(\"Application\", ApplicationId);\n      ADD_STRING(\"Copyright\", CopyrightFileId);\n      ADD_STRING(\"Abstract\", AbstractFileId);\n      ADD_STRING(\"Bib\", BibFileId);\n      // ADD_STRING(\"EscapeSequence\", EscapeSequence);\n      AddProp_Size64(s, \"VolumeSpaceSize\", vol.Get_VolumeSpaceSize_inBytes());\n      AddProp_Size64(s, \"VolumeSetSize\", vol.VolumeSetSize);\n      AddProp_Size64(s, \"VolumeSequenceNumber\", vol.VolumeSequenceNumber);\n      \n      prop = s;\n      break;\n    }\n    case kpidCTime: { vol.CTime.GetFileTime(prop); break; }\n    case kpidMTime: { vol.MTime.GetFileTime(prop); break; }\n  }\n  }\n\n  switch (propID)\n  {\n    case kpidPhySize: prop = _archive.PhySize; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_archive.HeadersError) v |= kpv_ErrorFlags_HeadersError;\n      prop = v;\n      break;\n    }\n    \n    case kpidError:\n    {\n      AString s;\n      if (_archive.IncorrectBigEndian)\n        AddErrorMessage(s, \"Incorrect big-endian headers\");\n      if (_archive.SelfLinkedDirs)\n        AddErrorMessage(s, \"Self-linked directory\");\n      if (_archive.TooDeepDirs)\n        AddErrorMessage(s, \"Too deep directory levels\");\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  if (index >= (UInt32)_archive.Refs.Size())\n  {\n    index -= _archive.Refs.Size();\n    const CBootInitialEntry &be = _archive.BootEntries[index];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        AString s (\"[BOOT]\" STRING_PATH_SEPARATOR);\n        if (_archive.BootEntries.Size() != 1)\n        {\n          s.Add_UInt32(index + 1);\n          s.Add_Minus();\n        }\n        s += be.GetName();\n        prop = s;\n        break;\n      }\n      case kpidIsDir: prop = false; break;\n      case kpidSize:\n      case kpidPackSize:\n        prop = (UInt64)_archive.GetBootItemSize(index);\n        break;\n    }\n  }\n  else\n  {\n    const CRef &ref = _archive.Refs[index];\n    const CDir &item = ref.Dir->_subItems[ref.Index];\n    switch (propID)\n    {\n      case kpidPath:\n        // if (item.FileId.GetCapacity() >= 0)\n        {\n          UString s;\n          if (_archive.IsJoliet())\n            item.GetPathU(s);\n          else\n            s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP);\n\n          if (s.Len() >= 2 && s[s.Len() - 2] == ';' && s.Back() == '1')\n            s.DeleteFrom(s.Len() - 2);\n          \n          if (!s.IsEmpty() && s.Back() == L'.')\n            s.DeleteBack();\n\n          NItemName::ReplaceToOsSlashes_Remove_TailSlash(s);\n          prop = s;\n        }\n        break;\n\n      case kpidSymLink:\n        if (_archive.IsSusp)\n        {\n          UInt32 mode;\n          if (item.GetPx(_archive.SuspSkipSize, k_Px_Mode, mode))\n          {\n            if (MY_LIN_S_ISLNK(mode))\n            {\n              AString s8;\n              if (item.GetSymLink(_archive.SuspSkipSize, s8))\n              {\n                UString s = MultiByteToUnicodeString(s8, CP_OEMCP);\n                prop = s;\n              }\n            }\n          }\n        }\n        break;\n\n\n      case kpidPosixAttrib:\n      /*\n      case kpidLinks:\n      case kpidUserId:\n      case kpidGroupId:\n      */\n      {\n        if (_archive.IsSusp)\n        {\n          UInt32 t = 0;\n          switch (propID)\n          {\n            case kpidPosixAttrib: t = k_Px_Mode; break;\n            /*\n            case kpidLinks: t = k_Px_Links; break;\n            case kpidUserId: t = k_Px_User; break;\n            case kpidGroupId: t = k_Px_Group; break;\n            */\n          }\n          UInt32 v;\n          if (item.GetPx(_archive.SuspSkipSize, t, v))\n            prop = v;\n        }\n        break;\n      }\n      \n      case kpidIsDir: prop = item.IsDir(); break;\n      case kpidSize:\n      case kpidPackSize:\n        if (!item.IsDir())\n          prop = (UInt64)ref.TotalSize;\n        break;\n\n      case kpidMTime:\n      // case kpidCTime:\n      // case kpidATime:\n      {\n        // if\n        item.DateTime.GetFileTime(prop);\n        /*\n        else\n        {\n          UInt32 t = 0;\n          switch (propID)\n          {\n            case kpidMTime: t = k_Tf_MTime; break;\n            case kpidCTime: t = k_Tf_CTime; break;\n            case kpidATime: t = k_Tf_ATime; break;\n          }\n          CRecordingDateTime dt;\n          if (item.GetTf(_archive.SuspSkipSize, t, dt))\n          {\n            FILETIME utc;\n            if (dt.GetFileTime(utc))\n              prop = utc;\n          }\n        }\n        */\n        break;\n      }\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _archive.Refs.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    UInt32 index = (allFilesMode ? i : indices[i]);\n    if (index < (UInt32)_archive.Refs.Size())\n    {\n      const CRef &ref = _archive.Refs[index];\n      const CDir &item = ref.Dir->_subItems[ref.Index];\n      if (!item.IsDir())\n        totalSize += ref.TotalSize;\n    }\n    else\n      totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size());\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 currentTotalSize = 0;\n  UInt64 currentItemSize;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_stream);\n\n  for (i = 0;; i++, currentTotalSize += currentItemSize)\n  {\n    lps->InSize = lps->OutSize = currentTotalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    currentItemSize = 0;\n    Int32 opRes = NExtract::NOperationResult::kOK;\n  {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    \n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    UInt64 blockIndex;\n    if (index < (UInt32)_archive.Refs.Size())\n    {\n      const CRef &ref = _archive.Refs[index];\n      const CDir &item = ref.Dir->_subItems[ref.Index];\n      if (item.IsDir())\n      {\n        RINOK(extractCallback->PrepareOperation(askMode))\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        continue;\n      }\n      currentItemSize = ref.TotalSize;\n      blockIndex = item.ExtentLocation;\n    }\n    else\n    {\n      unsigned bootIndex = index - _archive.Refs.Size();\n      const CBootInitialEntry &be = _archive.BootEntries[bootIndex];\n      currentItemSize = _archive.GetBootItemSize(bootIndex);\n      blockIndex = be.LoadRBA;\n    }\n   \n\n    if (!testMode && !realOutStream)\n      continue;\n\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    if (index < (UInt32)_archive.Refs.Size())\n    {\n      const CRef &ref = _archive.Refs[index];\n      UInt64 offset = 0;\n      for (UInt32 e = 0; e < ref.NumExtents; e++)\n      {\n        const CDir &item2 = ref.Dir->_subItems[ref.Index + e];\n        if (item2.Size == 0)\n          continue;\n        lps->InSize = lps->OutSize = currentTotalSize + offset;\n        RINOK(InStream_SeekSet(_stream, (UInt64)item2.ExtentLocation * kBlockSize))\n        inStream->Init(item2.Size);\n        RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n        if (copyCoder->TotalSize != item2.Size)\n        {\n          opRes = NExtract::NOperationResult::kDataError;\n          break;\n        }\n        offset += item2.Size;\n      }\n    }\n    else\n    {\n      RINOK(InStream_SeekSet(_stream, (UInt64)blockIndex * kBlockSize))\n      inStream->Init(currentItemSize);\n      RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n      if (copyCoder->TotalSize != currentItemSize)\n        opRes = NExtract::NOperationResult::kDataError;\n    }\n    // realOutStream.Release();\n  }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  UInt64 blockIndex;\n  UInt64 currentItemSize;\n  \n  if (index < _archive.Refs.Size())\n  {\n    const CRef &ref = _archive.Refs[index];\n    const CDir &item = ref.Dir->_subItems[ref.Index];\n    if (item.IsDir())\n      return S_FALSE;\n\n    if (ref.NumExtents > 1)\n    {\n      CExtentsStream *extentStreamSpec = new CExtentsStream();\n      CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec;\n      \n      extentStreamSpec->Stream = _stream;\n      \n      UInt64 virtOffset = 0;\n      for (UInt32 i = 0; i < ref.NumExtents; i++)\n      {\n        const CDir &item2 = ref.Dir->_subItems[ref.Index + i];\n        if (item2.Size == 0)\n          continue;\n        CSeekExtent se;\n        se.Phy = (UInt64)item2.ExtentLocation * kBlockSize;\n        se.Virt = virtOffset;\n        extentStreamSpec->Extents.Add(se);\n        virtOffset += item2.Size;\n      }\n      if (virtOffset != ref.TotalSize)\n        return S_FALSE;\n      CSeekExtent se;\n      se.Phy = 0;\n      se.Virt = virtOffset;\n      extentStreamSpec->Extents.Add(se);\n      extentStreamSpec->Init();\n      *stream = extentStream.Detach();\n      return S_OK;\n    }\n    \n    currentItemSize = item.Size;\n    blockIndex = item.ExtentLocation;\n  }\n  else\n  {\n    unsigned bootIndex = index - _archive.Refs.Size();\n    const CBootInitialEntry &be = _archive.BootEntries[bootIndex];\n    currentItemSize = _archive.GetBootItemSize(bootIndex);\n    blockIndex = be.LoadRBA;\n  }\n  \n  return CreateLimitedInStream(_stream, (UInt64)blockIndex * kBlockSize, currentItemSize, stream);\n  COM_TRY_END\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoHandler.h",
    "content": "﻿// IsoHandler.h\n\n#ifndef ZIP7_INC_ISO_HANDLER_H\n#define ZIP7_INC_ISO_HANDLER_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../IArchive.h\"\n\n#include \"IsoIn.h\"\n\nnamespace NArchive {\nnamespace NIso {\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CMyComPtr<IInStream> _stream;\n  CInArchive _archive;\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoHeader.cpp",
    "content": "﻿// Archive/Iso/Header.h\n\n#include \"StdAfx.h\"\n\n#include \"IsoHeader.h\"\n\nnamespace NArchive {\nnamespace NIso {\n\nconst char * const kElToritoSpec = \"EL TORITO SPECIFICATION\\0\\0\\0\\0\\0\\0\\0\\0\\0\";\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoHeader.h",
    "content": "﻿// Archive/IsoHeader.h\n\n#ifndef ZIP7_INC_ARCHIVE_ISO_HEADER_H\n#define ZIP7_INC_ARCHIVE_ISO_HEADER_H\n\n#include \"../../../Common/MyTypes.h\"\n\nnamespace NArchive {\nnamespace NIso {\n\nnamespace NVolDescType\n{\n  const Byte kBootRecord = 0;\n  const Byte kPrimaryVol = 1;\n  const Byte kSupplementaryVol = 2;\n  const Byte kVolParttition = 3;\n  const Byte kTerminator = 255;\n}\n\nconst Byte kVersion = 1;\n\nnamespace NFileFlags\n{\n  const Byte kDirectory = 1 << 1;\n  const Byte kNonFinalExtent = 1 << 7;\n}\n\nextern const char * const kElToritoSpec;\n\nconst UInt32 kStartPos = 0x8000;\n\nnamespace NBootEntryId\n{\n  const Byte kValidationEntry = 1;\n  const Byte kInitialEntryNotBootable = 0;\n  const Byte kInitialEntryBootable = 0x88;\n\n  const Byte kMoreHeaders = 0x90;\n  const Byte kFinalHeader = 0x91;\n  \n  const Byte kExtensionIndicator = 0x44;\n}\n\nnamespace NBootPlatformId\n{\n  const Byte kX86 = 0;\n  const Byte kPowerPC = 1;\n  const Byte kMac = 2;\n}\n\nconst Byte kBootMediaTypeMask = 0xF;\n\nnamespace NBootMediaType\n{\n  const Byte kNoEmulation = 0;\n  const Byte k1d2Floppy = 1;\n  const Byte k1d44Floppy = 2;\n  const Byte k2d88Floppy = 3;\n  const Byte kHardDisk = 4;\n}\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoIn.cpp",
    "content": "﻿// Archive/IsoIn.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/MyException.h\"\n\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../HandlerCont.h\"\n\n#include \"IsoIn.h\"\n\nnamespace NArchive {\nnamespace NIso {\n\nstruct CUnexpectedEndException {};\nstruct CHeaderErrorException {};\nstruct CEndianErrorException {};\n\nstatic const char * const kMediaTypes[] =\n{\n    \"NoEmul\"\n  , \"1.2M\"\n  , \"1.44M\"\n  , \"2.88M\"\n  , \"HardDisk\"\n};\n\nbool CBootInitialEntry::Parse(const Byte *p)\n{\n  Bootable = (p[0] == NBootEntryId::kInitialEntryBootable);\n  BootMediaType = p[1];\n  LoadSegment = GetUi16(p + 2);\n  SystemType = p[4];\n  SectorCount = GetUi16(p + 6);\n  LoadRBA = GetUi32(p + 8);\n  memcpy(VendorSpec, p + 12, 20);\n  if (p[5] != 0)\n    return false;\n  if (p[0] != NBootEntryId::kInitialEntryBootable\n      && p[0] != NBootEntryId::kInitialEntryNotBootable)\n    return false;\n  return true;\n}\n\nAString CBootInitialEntry::GetName() const\n{\n  AString s (Bootable ? \"Boot\" : \"NotBoot\");\n  s.Add_Minus();\n  \n  if (BootMediaType < Z7_ARRAY_SIZE(kMediaTypes))\n    s += kMediaTypes[BootMediaType];\n  else\n    s.Add_UInt32(BootMediaType);\n  \n  if (VendorSpec[0] == 1)\n  {\n    // \"Language and Version Information (IBM)\"\n\n    unsigned i;\n    for (i = 1; i < sizeof(VendorSpec); i++)\n      if (VendorSpec[i] > 0x7F)\n        break;\n    if (i == sizeof(VendorSpec))\n    {\n      s.Add_Minus();\n      for (i = 1; i < sizeof(VendorSpec); i++)\n      {\n        char c = (char)VendorSpec[i];\n        if (c == 0)\n          break;\n        if (c == '\\\\' || c == '/')\n          c = '_';\n        s += c;\n      }\n    }\n  }\n\n  s += \".img\";\n  return s;\n}\n\nByte CInArchive::ReadByte()\n{\n  if (m_BufferPos >= kBlockSize)\n    m_BufferPos = 0;\n  if (m_BufferPos == 0)\n  {\n    size_t processed = kBlockSize;\n    HRESULT res = ReadStream(_stream, m_Buffer, &processed);\n    if (res != S_OK)\n      throw CSystemException(res);\n    if (processed != kBlockSize)\n      throw CUnexpectedEndException();\n    UInt64 end = _position + processed;\n    if (PhySize < end)\n      PhySize = end;\n  }\n  Byte b = m_Buffer[m_BufferPos++];\n  _position++;\n  return b;\n}\n\nvoid CInArchive::ReadBytes(Byte *data, UInt32 size)\n{\n  for (UInt32 i = 0; i < size; i++)\n    data[i] = ReadByte();\n}\n\nvoid CInArchive::Skip(size_t size)\n{\n  while (size-- != 0)\n    ReadByte();\n}\n\nvoid CInArchive::SkipZeros(size_t size)\n{\n  while (size-- != 0)\n  {\n    Byte b = ReadByte();\n    if (b != 0)\n      throw CHeaderErrorException();\n  }\n}\n\nUInt16 CInArchive::ReadUInt16()\n{\n  Byte b[4];\n  ReadBytes(b, 4);\n  UInt32 val = 0;\n  for (int i = 0; i < 2; i++)\n  {\n    if (b[i] != b[3 - i])\n      IncorrectBigEndian = true;\n    val |= ((UInt32)(b[i]) << (8 * i));\n  }\n  return (UInt16)val;\n}\n\nUInt32 CInArchive::ReadUInt32Le()\n{\n  UInt32 val = 0;\n  for (int i = 0; i < 4; i++)\n    val |= ((UInt32)(ReadByte()) << (8 * i));\n  return val;\n}\n\nUInt32 CInArchive::ReadUInt32Be()\n{\n  UInt32 val = 0;\n  for (int i = 0; i < 4; i++)\n  {\n    val <<= 8;\n    val |= ReadByte();\n  }\n  return val;\n}\n\nUInt32 CInArchive::ReadUInt32()\n{\n  Byte b[8];\n  ReadBytes(b, 8);\n  UInt32 val = 0;\n  for (int i = 0; i < 4; i++)\n  {\n    if (b[i] != b[7 - i])\n      throw CEndianErrorException();\n    val |= ((UInt32)(b[i]) << (8 * i));\n  }\n  return val;\n}\n\nUInt32 CInArchive::ReadDigits(int numDigits)\n{\n  UInt32 res = 0;\n  for (int i = 0; i < numDigits; i++)\n  {\n    Byte b = ReadByte();\n    if (b < '0' || b > '9')\n    {\n      if (b == 0 || b == ' ') // it's bug in some CD's\n        b = '0';\n      else\n        throw CHeaderErrorException();\n    }\n    UInt32 d = (UInt32)(b - '0');\n    res *= 10;\n    res += d;\n  }\n  return res;\n}\n\nvoid CInArchive::ReadDateTime(CDateTime &d)\n{\n  d.Year = (UInt16)ReadDigits(4);\n  d.Month = (Byte)ReadDigits(2);\n  d.Day = (Byte)ReadDigits(2);\n  d.Hour = (Byte)ReadDigits(2);\n  d.Minute = (Byte)ReadDigits(2);\n  d.Second = (Byte)ReadDigits(2);\n  d.Hundredths = (Byte)ReadDigits(2);\n  d.GmtOffset = (signed char)ReadByte();\n}\n\nvoid CInArchive::ReadBootRecordDescriptor(CBootRecordDescriptor &d)\n{\n  ReadBytes(d.BootSystemId, sizeof(d.BootSystemId));\n  ReadBytes(d.BootId, sizeof(d.BootId));\n  ReadBytes(d.BootSystemUse, sizeof(d.BootSystemUse));\n}\n\nvoid CInArchive::ReadRecordingDateTime(CRecordingDateTime &t)\n{\n  t.Year = ReadByte();\n  t.Month = ReadByte();\n  t.Day = ReadByte();\n  t.Hour = ReadByte();\n  t.Minute = ReadByte();\n  t.Second = ReadByte();\n  t.GmtOffset = (signed char)ReadByte();\n}\n\nvoid CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)\n{\n  r.ExtendedAttributeRecordLen = ReadByte();\n  if (r.ExtendedAttributeRecordLen != 0)\n    throw CHeaderErrorException();\n  r.ExtentLocation = ReadUInt32();\n  r.Size = ReadUInt32();\n  ReadRecordingDateTime(r.DateTime);\n  r.FileFlags = ReadByte();\n  r.FileUnitSize = ReadByte();\n  r.InterleaveGapSize = ReadByte();\n  r.VolSequenceNumber = ReadUInt16();\n  Byte idLen = ReadByte();\n  r.FileId.Alloc(idLen);\n  ReadBytes((Byte *)r.FileId, idLen);\n  unsigned padSize = 1 - (idLen & 1);\n  \n  // SkipZeros(padSize);\n  Skip(padSize); // it's bug in some cd's. Must be zeros\n\n  unsigned curPos = 33 + idLen + padSize;\n  if (curPos > len)\n    throw CHeaderErrorException();\n  unsigned rem = len - curPos;\n  r.SystemUse.Alloc(rem);\n  ReadBytes((Byte *)r.SystemUse, rem);\n}\n\nvoid CInArchive::ReadDirRecord(CDirRecord &r)\n{\n  Byte len = ReadByte();\n  // Some CDs can have incorrect value len = 48 ('0') in VolumeDescriptor.\n  // But maybe we must use real \"len\" for other records.\n  len = 34;\n  ReadDirRecord2(r, len);\n}\n\nvoid CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)\n{\n  d.VolFlags = ReadByte();\n  ReadBytes(d.SystemId, sizeof(d.SystemId));\n  ReadBytes(d.VolumeId, sizeof(d.VolumeId));\n  SkipZeros(8);\n  d.VolumeSpaceSize = ReadUInt32();\n  ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence));\n  d.VolumeSetSize = ReadUInt16();\n  d.VolumeSequenceNumber = ReadUInt16();\n  d.LogicalBlockSize = ReadUInt16();\n  d.PathTableSize = ReadUInt32();\n  d.LPathTableLocation = ReadUInt32Le();\n  d.LOptionalPathTableLocation = ReadUInt32Le();\n  d.MPathTableLocation = ReadUInt32Be();\n  d.MOptionalPathTableLocation = ReadUInt32Be();\n  ReadDirRecord(d.RootDirRecord);\n  ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId));\n  ReadBytes(d.PublisherId, sizeof(d.PublisherId));\n  ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId));\n  ReadBytes(d.ApplicationId, sizeof(d.ApplicationId));\n  ReadBytes(d.CopyrightFileId, sizeof(d.CopyrightFileId));\n  ReadBytes(d.AbstractFileId, sizeof(d.AbstractFileId));\n  ReadBytes(d.BibFileId, sizeof(d.BibFileId));\n  ReadDateTime(d.CTime);\n  ReadDateTime(d.MTime);\n  ReadDateTime(d.ExpirationTime);\n  ReadDateTime(d.EffectiveTime);\n  const Byte fileStructureVersion = ReadByte();\n  // d.FileStructureVersion = fileStructureVersion;\n  if (fileStructureVersion != 1 &&  // ECMA-119\n      fileStructureVersion != 2)    // some ISO files have fileStructureVersion == 2.\n  {\n    // v24.05: we ignore that field, because we don't know what exact values are allowed there\n    // throw CHeaderErrorException();\n  }\n  SkipZeros(1); // (Reserved for future standardization)\n  ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));\n  // Most ISO contain zeros in the following field (reserved for future standardization).\n  // But some ISO programs write some data to that area.\n  // So we disable check for zeros.\n  Skip(653); // SkipZeros(653);\n}\n\nstatic const Byte kSig_CD001[5] = { 'C', 'D', '0', '0', '1' };\n\n/*\nstatic const Byte kSig_NSR02[5] = { 'N', 'S', 'R', '0', '2' };\nstatic const Byte kSig_NSR03[5] = { 'N', 'S', 'R', '0', '3' };\nstatic const Byte kSig_BEA01[5] = { 'B', 'E', 'A', '0', '1' };\nstatic const Byte kSig_TEA01[5] = { 'T', 'E', 'A', '0', '1' };\n*/\n\nstatic inline bool CheckSignature(const Byte *sig, const Byte *data)\n{\n  for (int i = 0; i < 5; i++)\n    if (sig[i] != data[i])\n      return false;\n  return true;\n}\n\nvoid CInArchive::SeekToBlock(UInt32 blockIndex)\n{\n  const HRESULT res = _stream->Seek(\n      (Int64)((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize),\n      STREAM_SEEK_SET, &_position);\n  if (res != S_OK)\n    throw CSystemException(res);\n  m_BufferPos = 0;\n}\n\nstatic const int kNumLevelsMax = 256;\n\nvoid CInArchive::ReadDir(CDir &d, int level)\n{\n  if (!d.IsDir())\n    return;\n  if (level > kNumLevelsMax)\n  {\n    TooDeepDirs = true;\n    return;\n  }\n\n  {\n    FOR_VECTOR (i, UniqStartLocations)\n      if (UniqStartLocations[i] == d.ExtentLocation)\n      {\n        SelfLinkedDirs = true;\n        return;\n      }\n    UniqStartLocations.Add(d.ExtentLocation);\n  }\n\n  SeekToBlock(d.ExtentLocation);\n  UInt64 startPos = _position;\n\n  bool firstItem = true;\n  for (;;)\n  {\n    UInt64 offset = _position - startPos;\n    if (offset >= d.Size)\n      break;\n    Byte len = ReadByte();\n    if (len == 0)\n      continue;\n    CDir subItem;\n    ReadDirRecord2(subItem, len);\n    if (firstItem && level == 0)\n      IsSusp = subItem.CheckSusp(SuspSkipSize);\n      \n    if (!subItem.IsSystemItem())\n      d._subItems.Add(subItem);\n\n    firstItem = false;\n  }\n  FOR_VECTOR (i, d._subItems)\n    ReadDir(d._subItems[i], level + 1);\n\n  UniqStartLocations.DeleteBack();\n}\n\nvoid CInArchive::CreateRefs(CDir &d)\n{\n  if (!d.IsDir())\n    return;\n  for (unsigned i = 0; i < d._subItems.Size();)\n  {\n    CRef ref;\n    CDir &subItem = d._subItems[i];\n    subItem.Parent = &d;\n    ref.Dir = &d;\n    ref.Index = i++;\n    ref.NumExtents = 1;\n    ref.TotalSize = subItem.Size;\n    if (subItem.IsNonFinalExtent())\n    {\n      for (;;)\n      {\n        if (i == d._subItems.Size())\n        {\n          HeadersError = true;\n          break;\n        }\n        const CDir &next = d._subItems[i];\n        if (!subItem.AreMultiPartEqualWith(next))\n          break;\n        i++;\n        ref.NumExtents++;\n        ref.TotalSize += next.Size;\n        if (!next.IsNonFinalExtent())\n          break;\n      }\n    }\n    Refs.Add(ref);\n    CreateRefs(subItem);\n  }\n}\n\nvoid CInArchive::ReadBootInfo()\n{\n  if (!_bootIsDefined)\n    return;\n  HeadersError = true;\n\n  if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)\n    return;\n  \n  UInt32 blockIndex = GetUi32(_bootDesc.BootSystemUse);\n  SeekToBlock(blockIndex);\n  \n  Byte buf[32];\n  ReadBytes(buf, 32);\n\n  if (buf[0] != NBootEntryId::kValidationEntry\n      || buf[2] != 0\n      || buf[3] != 0\n      || buf[30] != 0x55\n      || buf[31] != 0xAA)\n    return;\n\n  {\n    UInt32 sum = 0;\n    for (unsigned i = 0; i < 32; i += 2)\n      sum += GetUi16(buf + i);\n    if ((sum & 0xFFFF) != 0)\n      return;\n    /*\n    CBootValidationEntry e;\n    e.PlatformId = buf[1];\n    memcpy(e.Id, buf + 4, sizeof(e.Id));\n    // UInt16 checkSum = GetUi16(p + 28);\n    */\n  }\n\n  ReadBytes(buf, 32);\n  {\n    CBootInitialEntry e;\n    if (!e.Parse(buf))\n      return;\n    BootEntries.Add(e);\n  }\n\n  bool error = false;\n  \n  for (;;)\n  {\n    ReadBytes(buf, 32);\n    Byte headerIndicator = buf[0];\n    if (headerIndicator != NBootEntryId::kMoreHeaders\n        && headerIndicator != NBootEntryId::kFinalHeader)\n      break;\n\n    // Section Header\n    // Byte platform = p[1];\n    unsigned numEntries = GetUi16(buf + 2);\n    // id[28]\n      \n    for (unsigned i = 0; i < numEntries; i++)\n    {\n      ReadBytes(buf, 32);\n      CBootInitialEntry e;\n      if (!e.Parse(buf))\n      {\n        error = true;\n        break;\n      }\n      if (e.BootMediaType & (1 << 5))\n      {\n        // Section entry extension\n        for (unsigned j = 0;; j++)\n        {\n          ReadBytes(buf, 32);\n          if (j > 32 || buf[0] != NBootEntryId::kExtensionIndicator)\n          {\n            error = true;\n            break;\n          }\n          if ((buf[1] & (1 << 5)) == 0)\n            break;\n          // info += (buf + 2, 30)\n        }\n      }\n      BootEntries.Add(e);\n    }\n  \n    if (headerIndicator != NBootEntryId::kMoreHeaders)\n      break;\n  }\n    \n  HeadersError = error;\n}\n\nHRESULT CInArchive::Open2()\n{\n  _position = 0;\n  RINOK(InStream_GetSize_SeekToEnd(_stream, _fileSize))\n  if (_fileSize < kStartPos)\n    return S_FALSE;\n  RINOK(_stream->Seek(kStartPos, STREAM_SEEK_SET, &_position))\n\n  PhySize = _position;\n  m_BufferPos = 0;\n  // BlockSize = kBlockSize;\n  \n  for (;;)\n  {\n    Byte sig[7];\n    ReadBytes(sig, 7);\n    Byte ver = sig[6];\n    \n    if (!CheckSignature(kSig_CD001, sig + 1))\n    {\n      return S_FALSE;\n      /*\n      if (sig[0] != 0 || ver != 1)\n        break;\n      if (CheckSignature(kSig_BEA01, sig + 1))\n      {\n      }\n      else if (CheckSignature(kSig_TEA01, sig + 1))\n      {\n        break;\n      }\n      else if (CheckSignature(kSig_NSR02, sig + 1))\n      {\n      }\n      else\n        break;\n      SkipZeros(0x800 - 7);\n      continue;\n      */\n    }\n    \n    // version = 2 for ISO 9660:1999?\n    if (ver > 2)\n      return S_FALSE;\n\n    if (sig[0] == NVolDescType::kTerminator)\n    {\n      break;\n      // Skip(0x800 - 7);\n      // continue;\n    }\n    \n    switch (sig[0])\n    {\n      case NVolDescType::kBootRecord:\n      {\n        _bootIsDefined = true;\n        ReadBootRecordDescriptor(_bootDesc);\n        break;\n      }\n      case NVolDescType::kPrimaryVol:\n      case NVolDescType::kSupplementaryVol:\n      {\n        // some ISOs have two PrimaryVols.\n        CVolumeDescriptor vd;\n        ReadVolumeDescriptor(vd);\n        if (sig[0] == NVolDescType::kPrimaryVol)\n        {\n          // some burners write \"Joliet\" Escape Sequence to primary volume\n          memset(vd.EscapeSequence, 0, sizeof(vd.EscapeSequence));\n        }\n        VolDescs.Add(vd);\n        break;\n      }\n      default:\n        break;\n    }\n  }\n  \n  if (VolDescs.IsEmpty())\n    return S_FALSE;\n  for (MainVolDescIndex = (int)VolDescs.Size() - 1; MainVolDescIndex > 0; MainVolDescIndex--)\n    if (VolDescs[MainVolDescIndex].IsJoliet())\n      break;\n  /* FIXME: some volume can contain Rock Ridge, that is better than\n     Joliet volume. So we need some way to detect such case */\n  // MainVolDescIndex = 0; // to read primary volume\n  const CVolumeDescriptor &vd = VolDescs[MainVolDescIndex];\n  if (vd.LogicalBlockSize != kBlockSize)\n    return S_FALSE;\n\n  {\n    FOR_VECTOR (i, VolDescs)\n    {\n      const CVolumeDescriptor &vd2 = VolDescs[i];\n      UpdatePhySize(0, vd2.Get_VolumeSpaceSize_inBytes());\n    }\n  }\n\n \n  IsArc = true;\n\n  (CDirRecord &)_rootDir = vd.RootDirRecord;\n  ReadDir(_rootDir, 0);\n  CreateRefs(_rootDir);\n  ReadBootInfo();\n\n  {\n    FOR_VECTOR (i, Refs)\n    {\n      const CRef &ref = Refs[i];\n      for (UInt32 j = 0; j < ref.NumExtents; j++)\n      {\n        const CDir &item = ref.Dir->_subItems[ref.Index + j];\n        if (!item.IsDir() && item.Size != 0)\n          UpdatePhySize(item.ExtentLocation, item.Size);\n      }\n    }\n  }\n\n  {\n    // find boot item for expand:\n    // UEFI Specification : 13.3.2.1. ISO-9660 and El Torito\n    _expand_BootEntries_index = -1;\n    FOR_VECTOR (i, BootEntries)\n    {\n      const CBootInitialEntry &be = BootEntries[i];\n      if (be.SectorCount <= 1 && be.BootMediaType == NBootMediaType::kNoEmulation)\n        if (_expand_BootEntries_index == -1\n          || be.LoadRBA >= BootEntries[_expand_BootEntries_index].LoadRBA)\n        _expand_BootEntries_index = (int)i;\n    }\n  }\n\n  {\n    FOR_VECTOR (i, BootEntries)\n    {\n      const CBootInitialEntry &be = BootEntries[i];\n      UpdatePhySize(be.LoadRBA, GetBootItemSize(i));\n    }\n  }\n\n  if (PhySize < _fileSize)\n  {\n    UInt64 rem = _fileSize - PhySize;\n    const UInt64 kRemMax = 1 << 21;\n    if (rem <= kRemMax)\n    {\n      RINOK(InStream_SeekSet(_stream, PhySize))\n      bool areThereNonZeros = false;\n      UInt64 numZeros = 0;\n      RINOK(ReadZeroTail(_stream, areThereNonZeros, numZeros, kRemMax))\n      if (!areThereNonZeros)\n        PhySize += numZeros;\n    }\n  }\n\n  return S_OK;\n}\n\nHRESULT CInArchive::Open(IInStream *inStream)\n{\n  Clear();\n  _stream = inStream;\n  try { return Open2(); }\n  catch(const CSystemException &e) { return e.ErrorCode; }\n  catch(CUnexpectedEndException &) { UnexpectedEnd = true; return S_FALSE; }\n  catch(CHeaderErrorException &) { HeadersError = true; return S_FALSE; }\n  catch(CEndianErrorException &) { IncorrectBigEndian = true; return S_FALSE; }\n}\n\nvoid CInArchive::Clear()\n{\n  IsArc = false;\n  UnexpectedEnd = false;\n  HeadersError = false;\n  IncorrectBigEndian = false;\n  TooDeepDirs = false;\n  SelfLinkedDirs = false;\n\n  UniqStartLocations.Clear();\n\n  Refs.Clear();\n  _rootDir.Clear();\n  VolDescs.Clear();\n  _bootIsDefined = false;\n  BootEntries.Clear();\n  SuspSkipSize = 0;\n  IsSusp = false;\n\n  _expand_BootEntries_index = -1;\n}\n\n\nUInt64 CInArchive::GetBootItemSize(unsigned index) const\n{\n  const CBootInitialEntry &be = BootEntries[index];\n  UInt64 size = be.GetSize();\n       if (be.BootMediaType == NBootMediaType::k1d2Floppy)  size = 1200 << 10;\n  else if (be.BootMediaType == NBootMediaType::k1d44Floppy) size = 1440 << 10;\n  else if (be.BootMediaType == NBootMediaType::k2d88Floppy) size = 2880 << 10;\n  const UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize;\n  if (startPos < _fileSize)\n  {\n    const UInt64 rem = _fileSize - startPos;\n    /*\n       UEFI modification to ISO specification:\n       because SectorCount is 16-bit, size is limited by (32 MB).\n       UEFI Specification :\n        13.3.2.1. ISO-9660 and El Torito\n        If the value of Sector Count is set to 0 or 1,\n        EFI will assume the system partition consumes the space\n        from the beginning of the \"no emulation\" image to the end of the CD-ROM.\n    */\n    //\n    if ((int)index == _expand_BootEntries_index || rem < size)\n      size = rem;\n  }\n  return size;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoIn.h",
    "content": "﻿// Archive/IsoIn.h\n\n#ifndef ZIP7_INC_ARCHIVE_ISO_IN_H\n#define ZIP7_INC_ARCHIVE_ISO_IN_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../IStream.h\"\n\n#include \"IsoHeader.h\"\n#include \"IsoItem.h\"\n\nnamespace NArchive {\nnamespace NIso {\n\nstruct CDir: public CDirRecord\n{\n  CDir *Parent;\n  CObjectVector<CDir> _subItems;\n\n  void Clear()\n  {\n    Parent = NULL;\n    _subItems.Clear();\n  }\n  \n  AString GetPath(bool checkSusp, unsigned skipSize) const\n  {\n    AString s;\n\n    unsigned len = 0;\n    const CDir *cur = this;\n\n    for (;;)\n    {\n      unsigned curLen;\n      cur->GetNameCur(checkSusp, skipSize, curLen);\n      len += curLen;\n      cur = cur->Parent;\n      if (!cur || !cur->Parent)\n        break;\n      len++;\n    }\n\n    char *p = s.GetBuf_SetEnd(len) + len;\n    \n    cur = this;\n    \n    for (;;)\n    {\n      unsigned curLen;\n      const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen);\n      p -= curLen;\n      if (curLen != 0)\n        memcpy(p, name, curLen);\n      cur = cur->Parent;\n      if (!cur || !cur->Parent)\n        break;\n      p--;\n      *p = CHAR_PATH_SEPARATOR;\n    }\n    \n    return s;\n  }\n\n  void GetPathU(UString &s) const\n  {\n    s.Empty();\n    \n    unsigned len = 0;\n    const CDir *cur = this;\n\n    for (;;)\n    {\n      unsigned curLen = (unsigned)(cur->FileId.Size() / 2);\n      const Byte *fid = cur->FileId;\n\n      unsigned i;\n      for (i = 0; i < curLen; i++)\n        if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)\n          break;\n      len += i;\n      cur = cur->Parent;\n      if (!cur || !cur->Parent)\n        break;\n      len++;\n    }\n\n    wchar_t *p = s.GetBuf_SetEnd(len) + len;\n    \n    cur = this;\n    \n    for (;;)\n    {\n      unsigned curLen = (unsigned)(cur->FileId.Size() / 2);\n      const Byte *fid = cur->FileId;\n\n      unsigned i;\n      for (i = 0; i < curLen; i++)\n        if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)\n          break;\n      curLen = i;\n\n      p -= curLen;\n      for (i = 0; i < curLen; i++)\n        p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]);\n      cur = cur->Parent;\n      if (!cur || !cur->Parent)\n        break;\n      p--;\n      *p = WCHAR_PATH_SEPARATOR;\n    }\n  }\n};\n\nstruct CDateTime\n{\n  UInt16 Year;\n  Byte Month;\n  Byte Day;\n  Byte Hour;\n  Byte Minute;\n  Byte Second;\n  Byte Hundredths;\n  signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.\n  \n  bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&\n      Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }\n\n  bool GetFileTime(NWindows::NCOM::CPropVariant &prop) const\n  {\n    UInt64 v;\n    const bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, v);\n    if (res)\n    {\n      v = (UInt64)((Int64)v - (Int64)((Int32)GmtOffset * 15 * 60));\n      v *= 10000000;\n      if (Hundredths < 100)\n        v += (UInt32)Hundredths * 100000;\n      prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base + 2);\n    }\n    return res;\n  }\n};\n\nstruct CBootRecordDescriptor\n{\n  Byte BootSystemId[32];  // a-characters\n  Byte BootId[32];        // a-characters\n  Byte BootSystemUse[1977];\n};\n\nstruct CBootValidationEntry\n{\n  Byte PlatformId;\n  Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM.\n};\n\nstruct CBootInitialEntry\n{\n  bool Bootable;\n  Byte BootMediaType;\n  UInt16 LoadSegment;\n  /* This is the load segment for the initial boot image. If this\n     value is 0 the system will use the traditional segment of 7C0. If this value\n     is non-zero the system will use the specified segment. This applies to x86\n     architectures only. For \"flat\" model architectures (such as Motorola) this\n     is the address divided by 10. */\n  Byte SystemType;    // This must be a copy of byte 5 (System Type) from the\n                      // Partition Table found in the boot image.\n  UInt16 SectorCount; // This is the number of virtual/emulated sectors the system\n                      // will store at Load Segment during the initial boot procedure.\n  UInt32 LoadRBA;     // This is the start address of the virtual disk. CDs use\n                      // Relative/Logical block addressing.\n\n  Byte VendorSpec[20];\n\n  UInt32 GetSize() const\n  {\n    // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);\n    return (UInt32)SectorCount * 512;\n  }\n\n  bool Parse(const Byte *p);\n  AString GetName() const;\n};\n\nstruct CVolumeDescriptor\n{\n  Byte VolFlags;\n  Byte SystemId[32]; // a-characters. An identification of a system\n                     // which can recognize and act upon the content of the Logical\n                     // Sectors with logical Sector Numbers 0 to 15 of the volume.\n  Byte VolumeId[32]; // d-characters. An identification of the volume.\n  UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded\n  Byte EscapeSequence[32];\n  UInt16 VolumeSetSize;\n  UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member.\n  UInt16 LogicalBlockSize;\n  UInt32 PathTableSize;\n  UInt32 LPathTableLocation;\n  UInt32 LOptionalPathTableLocation;\n  UInt32 MPathTableLocation;\n  UInt32 MOptionalPathTableLocation;\n  CDirRecord RootDirRecord;\n  Byte VolumeSetId[128];\n  Byte PublisherId[128];\n  Byte DataPreparerId[128];\n  Byte ApplicationId[128];\n  Byte CopyrightFileId[37];\n  Byte AbstractFileId[37];\n  Byte BibFileId[37];\n  CDateTime CTime;\n  CDateTime MTime;\n  CDateTime ExpirationTime;\n  CDateTime EffectiveTime;\n  // Byte FileStructureVersion; // = 1;\n  Byte ApplicationUse[512];\n\n  bool IsJoliet() const\n  {\n    if ((VolFlags & 1) != 0)\n      return false;\n    const Byte b = EscapeSequence[2];\n    return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F &&\n      (b == 0x40 || b == 0x43 || b == 0x45));\n  }\n\n  UInt64 Get_VolumeSpaceSize_inBytes() const { return (UInt64)VolumeSpaceSize * LogicalBlockSize; }\n};\n\nstruct CRef\n{\n  const CDir *Dir;\n  UInt32 Index;\n  UInt32 NumExtents;\n  UInt64 TotalSize;\n};\n\nconst UInt32 kBlockSize = 1 << 11;\n\nclass CInArchive\n{\n  IInStream *_stream;\n  UInt64 _position;\n\n  UInt32 m_BufferPos;\n  \n  void Skip(size_t size);\n  void SkipZeros(size_t size);\n  Byte ReadByte();\n  void ReadBytes(Byte *data, UInt32 size);\n  UInt16 ReadUInt16();\n  UInt32 ReadUInt32Le();\n  UInt32 ReadUInt32Be();\n  UInt32 ReadUInt32();\n  UInt64 ReadUInt64();\n  UInt32 ReadDigits(int numDigits);\n  void ReadDateTime(CDateTime &d);\n  void ReadRecordingDateTime(CRecordingDateTime &t);\n  void ReadDirRecord2(CDirRecord &r, Byte len);\n  void ReadDirRecord(CDirRecord &r);\n\n  void ReadBootRecordDescriptor(CBootRecordDescriptor &d);\n  void ReadVolumeDescriptor(CVolumeDescriptor &d);\n\n  void SeekToBlock(UInt32 blockIndex);\n  void ReadDir(CDir &d, int level);\n  void CreateRefs(CDir &d);\n\n  void ReadBootInfo();\n  HRESULT Open2();\npublic:\n  HRESULT Open(IInStream *inStream);\n  void Clear();\n\n  UInt64 _fileSize;\n  UInt64 PhySize;\n\n  CRecordVector<CRef> Refs;\n  CObjectVector<CVolumeDescriptor> VolDescs;\n  int MainVolDescIndex;\n  // UInt32 BlockSize;\n  CObjectVector<CBootInitialEntry> BootEntries;\n\nprivate:\n  bool _bootIsDefined;\npublic:\n  bool IsArc;\n  bool UnexpectedEnd;\n  bool HeadersError;\n  bool IncorrectBigEndian;\n  bool TooDeepDirs;\n  bool SelfLinkedDirs;\n  bool IsSusp;\n  unsigned SuspSkipSize;\n\n  int _expand_BootEntries_index;\n\n  CRecordVector<UInt32> UniqStartLocations;\n\n  void UpdatePhySize(const UInt32 blockIndex, const UInt64 size)\n  {\n    const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1);\n    const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize;\n    if (PhySize < end)\n      PhySize = end;\n  }\n\n  bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }\n\n  UInt64 GetBootItemSize(unsigned index) const;\n\nprivate:\n  CDir _rootDir;\n  Byte m_Buffer[kBlockSize];\n  CBootRecordDescriptor _bootDesc;\n};\n  \n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoItem.h",
    "content": "﻿// Archive/IsoItem.h\n\n#ifndef ZIP7_INC_ARCHIVE_ISO_ITEM_H\n#define ZIP7_INC_ARCHIVE_ISO_ITEM_H\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/MyString.h\"\n#include \"../../../Common/MyBuffer.h\"\n\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"IsoHeader.h\"\n\nnamespace NArchive {\nnamespace NIso {\n\nstruct CRecordingDateTime\n{\n  Byte Year;\n  Byte Month;\n  Byte Day;\n  Byte Hour;\n  Byte Minute;\n  Byte Second;\n  signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.\n  \n  bool GetFileTime(NWindows::NCOM::CPropVariant &prop) const\n  {\n    UInt64 v;\n    const bool res = NWindows::NTime::GetSecondsSince1601(Year + 1900, Month, Day, Hour, Minute, Second, v);\n    if (res)\n    {\n      v = (UInt64)((Int64)v - (Int64)((Int32)GmtOffset * 15 * 60));\n      v *= 10000000;\n      prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base);\n    }\n    return res;\n  }\n};\n\nenum EPx\n{\n  k_Px_Mode,\n  k_Px_Links,\n  k_Px_User,\n  k_Px_Group,\n  k_Px_SerialNumber\n\n  // k_Px_Num\n};\n\n/*\nenum ETf\n{\n  k_Tf_CTime,\n  k_Tf_MTime,\n  k_Tf_ATime,\n  k_Tf_Attrib,\n  k_Tf_Backup,\n  k_Tf_Expiration,\n  k_Tf_Effective\n\n  // k_Tf_Num\n};\n*/\n\nstruct CDirRecord\n{\n  UInt32 ExtentLocation;\n  UInt32 Size;\n  CRecordingDateTime DateTime;\n  Byte FileFlags;\n  Byte FileUnitSize;\n  Byte InterleaveGapSize;\n  Byte ExtendedAttributeRecordLen;\n  UInt16 VolSequenceNumber;\n  CByteBuffer FileId;\n  CByteBuffer SystemUse;\n\n  bool AreMultiPartEqualWith(const CDirRecord &a) const\n  {\n    return FileId == a.FileId\n        && (FileFlags & (~NFileFlags::kNonFinalExtent)) ==\n        (a.FileFlags & (~NFileFlags::kNonFinalExtent));\n  }\n\n  bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; }\n  bool IsNonFinalExtent() const { return (FileFlags & NFileFlags::kNonFinalExtent) != 0; }\n\n  bool IsSystemItem() const\n  {\n    if (FileId.Size() != 1)\n      return false;\n    Byte b = *(const Byte *)FileId;\n    return (b == 0 || b == 1);\n  }\n\n  \n  const Byte* FindSuspRecord(unsigned skipSize, Byte id0, Byte id1, unsigned &lenRes) const\n  {\n    lenRes = 0;\n    if (SystemUse.Size() < skipSize)\n      return NULL;\n    const Byte *p = (const Byte *)SystemUse + skipSize;\n    unsigned rem = (unsigned)(SystemUse.Size() - skipSize);\n    while (rem >= 5)\n    {\n      unsigned len = p[2];\n      if (len < 3 || len > rem)\n        return NULL;\n      if (p[0] == id0 && p[1] == id1 && p[3] == 1)\n      {\n        if (len < 4)\n          return NULL; // Check it\n        lenRes = len - 4;\n        return p + 4;\n      }\n      p += len;\n      rem -= len;\n    }\n    return NULL;\n  }\n\n  \n  const Byte* GetNameCur(bool checkSusp, unsigned skipSize, unsigned &nameLenRes) const\n  {\n    const Byte *res = NULL;\n    unsigned len = 0;\n    if (checkSusp)\n      res = FindSuspRecord(skipSize, 'N', 'M', len);\n    if (!res || len < 1)\n    {\n      res = (const Byte *)FileId;\n      len = (unsigned)FileId.Size();\n    }\n    else\n    {\n      res++;\n      len--;\n    }\n    unsigned i;\n    for (i = 0; i < len; i++)\n      if (res[i] == 0)\n        break;\n    nameLenRes = i;\n    return res;\n  }\n\n\n  bool GetSymLink(unsigned skipSize, AString &link) const\n  {\n    link.Empty();\n    const Byte *p = NULL;\n    unsigned len = 0;\n    p = FindSuspRecord(skipSize, 'S', 'L', len);\n    if (!p || len < 1)\n      return false;\n\n    if (*p != 0)\n      return false;\n\n    p++;\n    len--;\n\n    while (len != 0)\n    {\n      if (len < 2)\n        return false;\n      unsigned flags = p[0];\n      unsigned cl = p[1];\n      p += 2;\n      len -= 2;\n\n      if (cl > len)\n        return false;\n\n      bool needSlash = false;\n      \n           if (flags & (1 << 1)) link += \"./\";\n      else if (flags & (1 << 2)) link += \"../\";\n      else if (flags & (1 << 3)) link.Add_Slash();\n      else\n        needSlash = true;\n\n      for (unsigned i = 0; i < cl; i++)\n      {\n        const Byte c = p[i];\n        if (c == 0)\n        {\n          break;\n          // return false;\n        }\n        link += (char)c;\n      }\n\n      p += cl;\n      len -= cl;\n\n      if (len == 0)\n        break;\n\n      if (needSlash)\n        link.Add_Slash();\n    }\n\n    return true;\n  }\n\n  static bool GetLe32Be32(const Byte *p, UInt32 &dest)\n  {\n    UInt32 v1 = GetUi32(p);\n    UInt32 v2 = GetBe32(p + 4);\n    if (v1 == v2)\n    {\n      dest = v1;\n      return true;\n    }\n    return false;\n  }\n\n\n  bool GetPx(unsigned skipSize, unsigned pxType, UInt32 &val) const\n  {\n    val = 0;\n    const Byte *p = NULL;\n    unsigned len = 0;\n    p = FindSuspRecord(skipSize, 'P', 'X', len);\n    if (!p)\n      return false;\n    // px.Clear();\n    if (len < (pxType + 1) * 8)\n      return false;\n\n    return GetLe32Be32(p + pxType * 8, val);\n  }\n\n  /*\n  bool GetTf(int skipSize, unsigned pxType, CRecordingDateTime &t) const\n  {\n    const Byte *p = NULL;\n    unsigned len = 0;\n    p = FindSuspRecord(skipSize, 'T', 'F', len);\n    if (!p)\n      return false;\n    if (len < 1)\n      return false;\n    Byte flags = *p++;\n    len--;\n\n    unsigned step = 7;\n    if (flags & 0x80)\n    {\n      step = 17;\n      return false;\n    }\n\n    if ((flags & (1 << pxType)) == 0)\n      return false;\n\n    for (unsigned i = 0; i < pxType; i++)\n    {\n      if (len < step)\n        return false;\n      if (flags & (1 << i))\n      {\n        p += step;\n        len -= step;\n      }\n    }\n\n    if (len < step)\n      return false;\n    \n    t.Year = p[0];\n    t.Month = p[1];\n    t.Day = p[2];\n    t.Hour = p[3];\n    t.Minute = p[4];\n    t.Second = p[5];\n    t.GmtOffset = (signed char)p[6];\n\n    return true;\n  }\n  */\n\n  bool CheckSusp(const Byte *p, unsigned &startPos) const\n  {\n    if (p[0] == 'S' &&\n        p[1] == 'P' &&\n        p[2] == 0x7 &&\n        p[3] == 0x1 &&\n        p[4] == 0xBE &&\n        p[5] == 0xEF)\n    {\n      startPos = p[6];\n      return true;\n    }\n    return false;\n  }\n\n  bool CheckSusp(unsigned &startPos) const\n  {\n    const Byte *p = (const Byte *)SystemUse;\n    const size_t len = SystemUse.Size();\n    const unsigned kMinLen = 7;\n    if (len < kMinLen)\n      return false;\n    if (CheckSusp(p, startPos))\n      return true;\n    const unsigned kOffset2 = 14;\n    if (len < kOffset2 + kMinLen)\n      return false;\n    return CheckSusp(p + kOffset2, startPos);\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/IsoRegister.cpp",
    "content": "﻿// IsoRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/RegisterArc.h\"\n\n#include \"IsoHandler.h\"\n\nnamespace NArchive {\nnamespace NIso {\n\nstatic const Byte k_Signature[] = { 'C', 'D', '0', '0', '1' };\n\nREGISTER_ARC_I(\n  \"Iso\", \"iso img\", NULL, 0xE7,\n  k_Signature,\n  NArchive::NIso::kStartPos + 1,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Iso/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/LpHandler.cpp",
    "content": "﻿// LpHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/Sha256.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define G16(_offs_, dest) dest = Get16(p + (_offs_));\n#define G32(_offs_, dest) dest = Get32(p + (_offs_));\n#define G64(_offs_, dest) dest = Get64(p + (_offs_));\n\nusing namespace NWindows;\n\nnamespace NArchive {\n\nnamespace NExt {\nAPI_FUNC_IsArc IsArc_Ext_PhySize(const Byte *p, size_t size, UInt64 *phySize);\n}\n\nnamespace NLp {\n\n/*\nAndroid 10+ use Android's Dynamic Partitions to allow the\ndifferent read-only system partitions (e.g. system, vendor, product)\nto share the same pool of storage space (as LVM in Linux).\nName for partition: \"super\" (for GPT) or \"super.img\" (for file).\nDynamic Partition Tools: lpmake\nAll partitions that are A/B-ed should be named as follows (slots are always named a, b, etc.):\nboot_a, boot_b, system_a, system_b, vendor_a, vendor_b.\n*/\n\n#define LP_METADATA_MAJOR_VERSION 10\n// #define LP_METADATA_MINOR_VERSION_MIN 0\n// #define LP_METADATA_MINOR_VERSION_MAX 2\n\n// #define LP_SECTOR_SIZE 512\nstatic const unsigned kSectorSizeLog = 9;\n\n/* Amount of space reserved at the start of every super partition to avoid\n * creating an accidental boot sector. */\n#define LP_PARTITION_RESERVED_BYTES 4096\n#define LP_METADATA_GEOMETRY_SIZE 4096\n#define LP_METADATA_HEADER_MAGIC 0x414C5030\n\nstatic const unsigned k_SignatureSize = 8;\nstatic const Byte k_Signature[k_SignatureSize] =\n  { 0x67, 0x44, 0x6c, 0x61, 0x34, 0, 0, 0 };\n\n// The length (36) is the same as the maximum length of a GPT partition name.\nstatic const unsigned kNameLen = 36;\n\nstatic void AddName36ToString(AString &s, const char *name, bool strictConvert)\n{\n  for (unsigned i = 0; i < kNameLen; i++)\n  {\n    char c = name[i];\n    if (c == 0)\n      return;\n    if (strictConvert && c < 32)\n      c = '_';\n    s += c;\n  }\n}\n\n\nstatic const unsigned k_Geometry_Size = 0x34;\n\n// LpMetadataGeometry\nstruct CGeometry\n{\n  // UInt32 magic;\n  // UInt32 struct_size;\n  // Byte checksum[32];   /*  SHA256 checksum of this struct, with this field set to 0. */\n  \n  /* Maximum amount of space a single copy of the metadata can use,\n     a multiple of LP_SECTOR_SIZE. */\n  UInt32 metadata_max_size;\n  \n  /* Number of copies of the metadata to keep.\n     For Non-A/B: 1, For A/B: 2, for A/B/C: 3.\n     A backup copy of each slot is kept */\n  UInt32 metadata_slot_count;\n  \n  /* minimal alignment for partition and extent sizes, a multiple of LP_SECTOR_SIZE. */\n  UInt32 logical_block_size;\n\n  bool Parse(const Byte *p)\n  {\n    G32 (40, metadata_max_size)\n    G32 (44, metadata_slot_count)\n    G32 (48, logical_block_size)\n    if (metadata_slot_count == 0 || metadata_slot_count >= ((UInt32)1 << 20))\n      return false;\n    if (metadata_max_size == 0)\n      return false;\n    if ((metadata_max_size & (((UInt32)1 << kSectorSizeLog) - 1)) != 0)\n      return false;\n    return true;\n  }\n\n  UInt64 GetTotalMetadataSize() const\n  {\n    // there are 2 copies of GEOMETRY and METADATA slots\n    return LP_PARTITION_RESERVED_BYTES +\n           LP_METADATA_GEOMETRY_SIZE * 2 +\n           ((UInt64)metadata_max_size * metadata_slot_count) * 2;\n  }\n};\n\n\n\n// LpMetadataTableDescriptor\nstruct CDescriptor\n{\n  UInt32 offset;        /*  Location of the table, relative to end of the metadata header. */\n  UInt32 num_entries;   /*  Number of entries in the table. */\n  UInt32 entry_size;    /*  Size of each entry in the table, in bytes. */\n\n  void Parse(const Byte *p)\n  {\n    G32 (0, offset)\n    G32 (4, num_entries)\n    G32 (8, entry_size)\n  }\n \n  bool CheckLimits(UInt32 limit) const\n  {\n    if (entry_size == 0)\n      return false;\n    const UInt32 size = num_entries * entry_size;\n    if (size / entry_size != num_entries)\n      return false;\n    if (offset > limit || limit - offset < size)\n      return false;\n    return true;\n  }\n};\n\n\n// #define LP_PARTITION_ATTR_NONE 0x0\n// #define LP_PARTITION_ATTR_READONLY (1 << 0)\n\n/* This flag is only intended to be used with super_empty.img and super.img on\n * retrofit devices. On these devices there are A and B super partitions, and\n * we don't know ahead of time which slot the image will be applied to.\n *\n * If set, the partition name needs a slot suffix applied. The slot suffix is\n * determined by the metadata slot number (0 = _a, 1 = _b).\n */\n// #define LP_PARTITION_ATTR_SLOT_SUFFIXED (1 << 1)\n\n/* This flag is applied automatically when using MetadataBuilder::NewForUpdate.\n * It signals that the partition was created (or modified) for a snapshot-based\n * update. If this flag is not present, the partition was likely flashed via\n * fastboot.\n */\n// #define LP_PARTITION_ATTR_UPDATED (1 << 2)\n\n/* This flag marks a partition as disabled. It should not be used or mapped. */\n// #define LP_PARTITION_ATTR_DISABLED (1 << 3)\n\nstatic const char * const g_PartitionAttr[] =\n{\n    \"READONLY\"\n  , \"SLOT_SUFFIXED\"\n  , \"UPDATED\"\n  , \"DISABLED\"\n};\n\nstatic unsigned const k_MetaPartition_Size = 52;\n\n// LpMetadataPartition\nstruct CPartition\n{\n  /* ASCII characters: alphanumeric or _. at least one ASCII character,\n     (name) must be unique across all partition names. */\n  char name[kNameLen];\n  \n  UInt32 attributes;   /* (LP_PARTITION_ATTR_*). */\n\n  /* Index of the first extent owned by this partition. The extent will\n   * start at logical sector 0. Gaps between extents are not allowed. */\n  UInt32 first_extent_index;\n  \n  /* Number of extents in the partition. Every partition must have at least one extent. */\n  UInt32 num_extents;\n\n  /* Group this partition belongs to. */\n  UInt32 group_index;\n\n  void Parse(const Byte *p)\n  {\n    memcpy(name, p, kNameLen);\n    G32 (36, attributes)\n    G32 (40, first_extent_index)\n    G32 (44, num_extents)\n    G32 (48, group_index)\n  }\n\n  // calced properties:\n  UInt32 MethodsMask;\n  UInt64 NumSectors;\n  UInt64 NumSectors_Pack;\n  const char *Ext;\n\n  UInt64 GetSize() const { return NumSectors << kSectorSizeLog; }\n  UInt64 GetPackSize() const { return NumSectors_Pack << kSectorSizeLog; }\n  \n  CPartition():\n      MethodsMask(0),\n      NumSectors(0),\n      NumSectors_Pack(0),\n      Ext(NULL)\n      {}\n};\n\n\n\n\n#define LP_TARGET_TYPE_LINEAR 0\n/* This extent is a dm-zero target. The index is ignored and must be 0. */\n#define LP_TARGET_TYPE_ZERO 1\n\nstatic const char * const g_Methods[] =\n{\n    \"RAW\" // \"LINEAR\"\n  , \"ZERO\"\n};\n\nstatic unsigned const k_MetaExtent_Size = 24;\n\n// LpMetadataExtent\nstruct CExtent\n{\n  UInt64 num_sectors;  /*  Length in 512-byte sectors. */\n  UInt32 target_type;  /*  Target type for device-mapper (LP_TARGET_TYPE_*). */\n\n  /* for LINEAR: The sector on the physical partition that this extent maps onto.\n     for ZERO:   must be 0. */\n  UInt64 target_data;\n\n  /* for LINEAR: index into the block devices table.\n     for ZERO:   must be 0. */\n  UInt32 target_source;\n\n  bool IsRAW() const { return target_type == LP_TARGET_TYPE_LINEAR; }\n\n  void Parse(const Byte *p)\n  {\n    G64 (0, num_sectors)\n    G32 (8, target_type)\n    G64 (12, target_data)\n    G32 (20, target_source)\n  }\n};\n\n\n/* This flag is only intended to be used with super_empty.img and super.img on\n * retrofit devices. If set, the group needs a slot suffix to be interpreted\n * correctly. The suffix is automatically applied by ReadMetadata().\n */\n// #define LP_GROUP_SLOT_SUFFIXED (1 << 0)\nstatic unsigned const k_Group_Size = 48;\n\n// LpMetadataPartitionGroup\nstruct CGroup\n{\n  char name[kNameLen];\n  UInt32 flags;  /* (LP_GROUP_*). */\n  UInt64 maximum_size; /* Maximum size in bytes. If 0, the group has no maximum size. */\n\n  void Parse(const Byte *p)\n  {\n    memcpy(name, p, kNameLen);\n    G32 (36, flags)\n    G64 (40, maximum_size)\n  }\n};\n\n\n\n\n/* This flag is only intended to be used with super_empty.img and super.img on\n * retrofit devices. On these devices there are A and B super partitions, and\n * we don't know ahead of time which slot the image will be applied to.\n *\n * If set, the block device needs a slot suffix applied before being used with\n * IPartitionOpener. The slot suffix is determined by the metadata slot number\n * (0 = _a, 1 = _b).\n */\n// #define LP_BLOCK_DEVICE_SLOT_SUFFIXED (1 << 0)\n\nstatic unsigned const k_Device_Size = 64;\n\n/* This struct defines an entry in the block_devices table. There must be at\n * least one device, and the first device must represent the partition holding\n * the super metadata.\n */\n// LpMetadataBlockDevice\nstruct CDevice\n{\n    /* 0: First usable sector for allocating logical partitions. this will be\n     * the first sector after the initial geometry blocks, followed by the\n     * space consumed by metadata_max_size*metadata_slot_count*2.\n     */\n  UInt64 first_logical_sector;\n\n    /* 8: Alignment for defining partitions or partition extents. For example,\n     * an alignment of 1MiB will require that all partitions have a size evenly\n     * divisible by 1MiB, and that the smallest unit the partition can grow by\n     * is 1MiB.\n     *\n     * Alignment is normally determined at runtime when growing or adding\n     * partitions. If for some reason the alignment cannot be determined, then\n     * this predefined alignment in the geometry is used instead. By default\n     * it is set to 1MiB.\n     */\n  UInt32 alignment;\n\n    /* 12: Alignment offset for \"stacked\" devices. For example, if the \"super\"\n     * partition itself is not aligned within the parent block device's\n     * partition table, then we adjust for this in deciding where to place\n     * |first_logical_sector|.\n     *\n     * Similar to |alignment|, this will be derived from the operating system.\n     * If it cannot be determined, it is assumed to be 0.\n     */\n  UInt32 alignment_offset;\n\n    /* 16: Block device size, as specified when the metadata was created. This\n     * can be used to verify the geometry against a target device.\n     */\n  UInt64 size;\n\n    /* 24: Partition name in the GPT*/\n  char partition_name[kNameLen];\n\n    /* 60: Flags (see LP_BLOCK_DEVICE_* flags below). */\n  UInt32 flags;\n\n  void Parse(const Byte *p)\n  {\n    memcpy(partition_name, p + 24, kNameLen);\n    G64 (0, first_logical_sector)\n    G32 (8, alignment)\n    G32 (12, alignment_offset)\n    G64 (16, size)\n    G32 (60, flags)\n  }\n};\n\n\n/* This device uses Virtual A/B. Note that on retrofit devices, the expanded\n * header may not be present.\n */\n// #define LP_HEADER_FLAG_VIRTUAL_AB_DEVICE 0x1\n\nstatic const char * const g_Header_Flags[] =\n{\n  \"VIRTUAL_AB\"\n};\n\n\nstatic const unsigned k_LpMetadataHeader10_size = 128;\nstatic const unsigned k_LpMetadataHeader12_size = 256;\n\nstruct LpMetadataHeader\n{\n  /*  0: Four bytes equal to LP_METADATA_HEADER_MAGIC. */\n  UInt32 magic;\n  \n  /*  4: Version number required to read this metadata. If the version is not\n   * equal to the library version, the metadata should be considered\n   * incompatible.\n   */\n  UInt16 major_version;\n  \n  /*  6: Minor version. A library supporting newer features should be able to\n   * read metadata with an older minor version. However, an older library\n   * should not support reading metadata if its minor version is higher.\n   */\n  UInt16 minor_version;\n  \n  /*  8: The size of this header struct. */\n  UInt32 header_size;\n  \n  /* 12: SHA256 checksum of the header, up to |header_size| bytes, computed as\n   * if this field were set to 0.\n   */\n  // Byte header_checksum[32];\n  \n  /* 44: The total size of all tables. This size is contiguous; tables may not\n   * have gaps in between, and they immediately follow the header.\n   */\n  UInt32 tables_size;\n  \n  /* 48: SHA256 checksum of all table contents. */\n  Byte tables_checksum[32];\n  \n  /* 80: Partition table descriptor. */\n  CDescriptor partitions;\n  /* 92: Extent table descriptor. */\n  CDescriptor extents;\n  /* 104: Updateable group descriptor. */\n  CDescriptor groups;\n  /* 116: Block device table. */\n  CDescriptor block_devices;\n  \n  /* Everything past here is header version 1.2+, and is only included if\n   * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must\n   * zero these additional fields.\n   */\n  \n  /* 128: See LP_HEADER_FLAG_ constants for possible values. Header flags are\n   * independent of the version number and intended to be informational only.\n   * New flags can be added without bumping the version.\n   */\n  // UInt32 flags;\n  \n  /* 132: Reserved (zero), pad to 256 bytes. */\n  // Byte reserved[124];\n\n  void Parse128(const Byte *p)\n  {\n    G32 (0, magic)\n    G16 (4, major_version)\n    G16 (6, minor_version)\n    G32 (8, header_size)\n    // Byte header_checksum[32];\n    G32 (44, tables_size)\n    memcpy (tables_checksum, p + 48, 32);\n    partitions.Parse(p + 80);\n    extents.Parse(p + 92);\n    groups.Parse(p + 104);\n    block_devices.Parse(p + 116);\n    /* Everything past here is header version 1.2+, and is only included if\n     * needed. When liblp supporting >= 1.2 reads a < 1.2 header, it must\n     * zero these additional fields.\n     */\n  }\n};\n\n\nstatic bool CheckSha256(const Byte *data, size_t size, const Byte *checksum)\n{\n  MY_ALIGN (16)\n  CSha256 sha;\n  Sha256_Init(&sha);\n  Sha256_Update(&sha, data, size);\n  MY_ALIGN (16)\n  Byte calced[32];\n  Sha256_Final(&sha, calced);\n  return memcmp(checksum, calced, 32) == 0;\n}\n\nstatic bool CheckSha256_csOffset(Byte *data, size_t size, unsigned hashOffset)\n{\n  MY_ALIGN (4)\n  Byte checksum[32];\n  Byte *shaData = &data[hashOffset];\n  memcpy(checksum, shaData, 32);\n  memset(shaData, 0, 32);\n  return CheckSha256(data, size, checksum);\n}\n\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CRecordVector<CPartition> _items;\n  CRecordVector<CExtent> Extents;\n\n  CMyComPtr<IInStream> _stream;\n  UInt64 _totalSize;\n  // UInt64 _usedSize;\n  // UInt64 _headersSize;\n\n  CGeometry geom;\n  UInt16 Major_version;\n  UInt16 Minor_version;\n  UInt32 Flags;\n\n  Int32 _mainFileIndex;\n  UInt32 MethodsMask;\n  bool _headerWarning;\n  AString GroupsString;\n  AString DevicesString;\n  AString DeviceArcName;\n\n  HRESULT Open2(IInStream *stream);\n};\n\n\nstatic void AddComment_UInt64(AString &s, const char *name, UInt64 val)\n{\n  s.Add_Space();\n  s += name;\n  s += '=';\n  s.Add_UInt64(val);\n}\n\n\nstatic bool IsBufZero(const Byte *data, size_t size)\n{\n  for (size_t i = 0; i < size; i += 4)\n    if (*(const UInt32 *)(const void *)(data + i) != 0)\n      return false;\n  return true;\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  RINOK(InStream_SeekSet(stream, LP_PARTITION_RESERVED_BYTES))\n  {\n    MY_ALIGN (4)\n    Byte buf[k_Geometry_Size];\n    RINOK(ReadStream_FALSE(stream, buf, k_Geometry_Size))\n    if (memcmp(buf, k_Signature, k_SignatureSize) != 0)\n      return S_FALSE;\n    if (!geom.Parse(buf))\n      return S_FALSE;\n    if (!CheckSha256_csOffset(buf, k_Geometry_Size, 8))\n      return S_FALSE;\n  }\n\n  CByteBuffer buffer;\n  RINOK(InStream_SeekToBegin(stream))\n  buffer.Alloc(LP_METADATA_GEOMETRY_SIZE * 2);\n  {\n    // buffer.Size() >= LP_PARTITION_RESERVED_BYTES\n    RINOK(ReadStream_FALSE(stream, buffer, LP_PARTITION_RESERVED_BYTES))\n    if (!IsBufZero(buffer, LP_PARTITION_RESERVED_BYTES))\n    {\n      _headerWarning = true;\n      // return S_FALSE;\n    }\n  }\n\n  RINOK(ReadStream_FALSE(stream, buffer, LP_METADATA_GEOMETRY_SIZE * 2))\n  // we check that 2 copies of GEOMETRY are identical:\n  if (memcmp(buffer, buffer + LP_METADATA_GEOMETRY_SIZE, LP_METADATA_GEOMETRY_SIZE) != 0\n      || !IsBufZero(buffer + k_Geometry_Size, LP_METADATA_GEOMETRY_SIZE - k_Geometry_Size))\n  {\n    _headerWarning = true;\n    // return S_FALSE;\n  }\n\n  RINOK(ReadStream_FALSE(stream, buffer, k_LpMetadataHeader10_size))\n  LpMetadataHeader header;\n  header.Parse128(buffer);\n  if (header.magic != LP_METADATA_HEADER_MAGIC ||\n      header.major_version != LP_METADATA_MAJOR_VERSION ||\n      header.header_size < k_LpMetadataHeader10_size)\n    return S_FALSE;\n  Flags = 0;\n  if (header.header_size > k_LpMetadataHeader10_size)\n  {\n    if (header.header_size != k_LpMetadataHeader12_size)\n      return S_FALSE;\n    RINOK(ReadStream_FALSE(stream, buffer + k_LpMetadataHeader10_size,\n        header.header_size - k_LpMetadataHeader10_size))\n    Flags = Get32(buffer + k_LpMetadataHeader10_size);\n  }\n  Major_version = header.major_version;\n  Minor_version = header.minor_version;\n\n  if (!CheckSha256_csOffset(buffer, header.header_size, 12))\n    return S_FALSE;\n\n  if (geom.metadata_max_size < header.tables_size ||\n      geom.metadata_max_size - header.tables_size < header.header_size)\n    return S_FALSE;\n\n  buffer.AllocAtLeast(header.tables_size);\n  RINOK(ReadStream_FALSE(stream, buffer, header.tables_size))\n\n  const UInt64 totalMetaSize = geom.GetTotalMetadataSize();\n  // _headersSize = _totalSize;\n  _totalSize = totalMetaSize;\n\n  if (!CheckSha256(buffer, header.tables_size, header.tables_checksum))\n    return S_FALSE;\n\n  {\n    const CDescriptor &d = header.partitions;\n    if (!d.CheckLimits(header.tables_size))\n      return S_FALSE;\n    if (d.entry_size != k_MetaPartition_Size)\n      return S_FALSE;\n    for (UInt32 i = 0; i < d.num_entries; i++)\n    {\n      CPartition part;\n      part.Parse(buffer + d.offset + i * d.entry_size);\n      const UInt32 extLimit = part.first_extent_index + part.num_extents;\n      if (extLimit < part.first_extent_index ||\n          extLimit > header.extents.num_entries ||\n          part.group_index >= header.groups.num_entries)\n        return S_FALSE;\n      _items.Add(part);\n    }\n  }\n  {\n    const CDescriptor &d = header.extents;\n    if (!d.CheckLimits(header.tables_size))\n      return S_FALSE;\n    if (d.entry_size != k_MetaExtent_Size)\n      return S_FALSE;\n    for (UInt32 i = 0; i < d.num_entries; i++)\n    {\n      CExtent e;\n      e.Parse(buffer + d.offset + i * d.entry_size);\n      // if (e.target_type > LP_TARGET_TYPE_ZERO) return S_FALSE;\n      if (e.IsRAW())\n      {\n        if (e.target_source >= header.block_devices.num_entries)\n          return S_FALSE;\n        const UInt64 endSector = e.target_data + e.num_sectors;\n        const UInt64 endOffset = endSector << kSectorSizeLog;\n        if (_totalSize < endOffset)\n          _totalSize = endOffset;\n      }\n      MethodsMask |= (UInt32)1 << e.target_type;\n      Extents.Add(e);\n    }\n  }\n  \n  // _usedSize = _totalSize;\n  {\n    const CDescriptor &d = header.groups;\n    if (!d.CheckLimits(header.tables_size))\n      return S_FALSE;\n    if (d.entry_size != k_Group_Size)\n      return S_FALSE;\n    AString s;\n    for (UInt32 i = 0; i < d.num_entries; i++)\n    {\n      CGroup g;\n      g.Parse(buffer + d.offset + i * d.entry_size);\n      if (_totalSize < g.maximum_size)\n        _totalSize = g.maximum_size;\n      s += \"  \";\n      AddName36ToString(s, g.name, true);\n      AddComment_UInt64(s, \"maximum_size\", g.maximum_size);\n      AddComment_UInt64(s, \"flags\", g.flags);\n      s.Add_LF();\n    }\n    GroupsString = s;\n  }\n\n  {\n    const CDescriptor &d = header.block_devices;\n    if (!d.CheckLimits(header.tables_size))\n      return S_FALSE;\n    if (d.entry_size != k_Device_Size)\n      return S_FALSE;\n    AString s;\n    // CRecordVector<CDevice> devices;\n    for (UInt32 i = 0; i < d.num_entries; i++)\n    {\n      CDevice v;\n      v.Parse(buffer + d.offset + i * d.entry_size);\n      // if (i == 0)\n      {\n        // it's super_device is first device;\n        if (totalMetaSize > (v.first_logical_sector << kSectorSizeLog))\n          return S_FALSE;\n      }\n      if (_totalSize < v.size)\n        _totalSize = v.size;\n      s += \"  \";\n      if (i == 0)\n        AddName36ToString(DeviceArcName, v.partition_name, true);\n      // devices.Add(v);\n      AddName36ToString(s, v.partition_name, true);\n      AddComment_UInt64(s, \"size\", v.size);\n      AddComment_UInt64(s, \"first_logical_sector\", v.first_logical_sector);\n      AddComment_UInt64(s, \"alignment\", v.alignment);\n      AddComment_UInt64(s, \"alignment_offset\", v.alignment_offset);\n      AddComment_UInt64(s, \"flags\", v.flags);\n      s.Add_LF();\n    }\n    DevicesString = s;\n  }\n\n  {\n    FOR_VECTOR (i, _items)\n    {\n      CPartition &part = _items[i];\n      if (part.first_extent_index > Extents.Size() ||\n          part.num_extents > Extents.Size() - part.first_extent_index)\n        return S_FALSE;\n\n      UInt64 numSectors = 0;\n      UInt64 numSectors_Pack = 0;\n      UInt32 methods = 0;\n      for (UInt32 k = 0; k < part.num_extents; k++)\n      {\n        const CExtent &e = Extents[part.first_extent_index + k];\n        numSectors += e.num_sectors;\n        if (e.IsRAW())\n          numSectors_Pack += e.num_sectors;\n        methods |= (UInt32)1 << e.target_type;\n      }\n      part.NumSectors = numSectors;\n      part.NumSectors_Pack = numSectors_Pack;\n      part.MethodsMask = methods;\n    }\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(stream))\n  _stream = stream;\n\n  int mainFileIndex = -1;\n  unsigned numNonEmptyParts = 0;\n\n  FOR_VECTOR (fileIndex, _items)\n  {\n    CPartition &item = _items[fileIndex];\n    if (item.NumSectors != 0)\n    {\n      mainFileIndex = (int)fileIndex;\n      numNonEmptyParts++;\n      CMyComPtr<ISequentialInStream> parseStream;\n      if (GetStream(fileIndex, &parseStream) == S_OK && parseStream)\n      {\n        const size_t kParseSize = 1 << 11;\n        Byte buf[kParseSize];\n        if (ReadStream_FAIL(parseStream, buf, kParseSize) == S_OK)\n        {\n          UInt64 extSize;\n          if (NExt::IsArc_Ext_PhySize(buf, kParseSize, &extSize) == k_IsArc_Res_YES)\n            if (extSize == item.GetSize())\n              item.Ext = \"ext\";\n        }\n      }\n    }\n  }\n  if (numNonEmptyParts == 1)\n    _mainFileIndex = mainFileIndex;\n\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalSize = 0;\n  // _usedSize = 0;\n  // _headersSize = 0;\n  _items.Clear();\n  Extents.Clear();\n  _stream.Release();\n  _mainFileIndex = -1;\n  _headerWarning = false;\n  MethodsMask = 0;\n  GroupsString.Empty();\n  DevicesString.Empty();\n  DeviceArcName.Empty();\n  return S_OK;\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidCharacts,\n  kpidMethod,\n  kpidNumBlocks,\n  kpidOffset\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidUnpackVer,\n  kpidMethod,\n  kpidClusterSize,\n  // kpidHeadersSize,\n  // kpidFreeSpace,\n  kpidName,\n  kpidComment\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile:\n    {\n      if (_mainFileIndex >= 0)\n        prop = (UInt32)_mainFileIndex;\n      break;\n    }\n    case kpidPhySize: prop = _totalSize; break;\n\n    // case kpidFreeSpace: if (_usedSize != 0) prop = _totalSize - _usedSize; break;\n    // case kpidHeadersSize: prop = _headersSize; break;\n\n    case kpidMethod:\n    {\n      const UInt32 m = MethodsMask;\n      if (m != 0)\n      {\n        FLAGS_TO_PROP(g_Methods, m, prop);\n      }\n      break;\n    }\n\n    case kpidUnpackVer:\n    {\n      AString s;\n      s.Add_UInt32(Major_version);\n      s.Add_Dot();\n      s.Add_UInt32(Minor_version);\n      prop = s;\n      break;\n    }\n\n    case kpidClusterSize:\n      prop = geom.logical_block_size;\n      break;\n\n    case kpidComment:\n    {\n      AString s;\n\n      s += \"metadata_slot_count: \";\n      s.Add_UInt32(geom.metadata_slot_count);\n      s.Add_LF();\n\n      s += \"metadata_max_size: \";\n      s.Add_UInt32(geom.metadata_max_size);\n      s.Add_LF();\n\n      if (Flags != 0)\n      {\n        s += \"flags: \";\n        s += FlagsToString(g_Header_Flags, Z7_ARRAY_SIZE(g_Header_Flags), Flags);\n        s.Add_LF();\n      }\n\n      if (!GroupsString.IsEmpty())\n      {\n        s += \"Groups:\";\n        s.Add_LF();\n        s += GroupsString;\n      }\n      \n      if (!DevicesString.IsEmpty())\n      {\n        s += \"BlockDevices:\";\n        s.Add_LF();\n        s += DevicesString;\n      }\n      \n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidName:\n      if (!DeviceArcName.IsEmpty())\n        prop = DeviceArcName + \".lpimg\";\n      break;\n\n    case kpidWarningFlags:\n      if (_headerWarning)\n      {\n        UInt32 v = kpv_ErrorFlags_HeadersError;\n        prop = v;\n      }\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CPartition &item = _items[index];\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      AString s;\n      AddName36ToString(s, item.name, false);\n      if (s.IsEmpty())\n        s.Add_UInt32(index);\n      if (item.num_extents != 0)\n      {\n        s.Add_Dot();\n        s += (item.Ext ? item.Ext : \"img\");\n      }\n      prop = s;\n      break;\n    }\n    \n    case kpidSize: prop = item.GetSize(); break;\n    case kpidPackSize: prop = item.GetPackSize(); break;\n    case kpidNumBlocks: prop = item.num_extents; break;\n    case kpidMethod:\n    {\n      const UInt32 m = item.MethodsMask;\n      if (m != 0)\n      {\n        FLAGS_TO_PROP(g_Methods, m, prop);\n      }\n      break;\n    }\n    case kpidOffset:\n      if (item.num_extents != 0)\n        if (item.first_extent_index < Extents.Size())\n          prop = Extents[item.first_extent_index].target_data << kSectorSizeLog;\n      break;\n\n    case kpidCharacts:\n    {\n      AString s;\n      s += \"group:\";\n      s.Add_UInt32(item.group_index);\n      s.Add_Space();\n      s += FlagsToString(g_PartitionAttr, Z7_ARRAY_SIZE(g_PartitionAttr), item.attributes);\n      prop = s;\n      break;\n    }\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  \n  const CPartition &item = _items[index];\n\n  if (item.first_extent_index > Extents.Size()\n      || item.num_extents > Extents.Size() - item.first_extent_index)\n    return S_FALSE;\n\n  if (item.num_extents == 0)\n    return CreateLimitedInStream(_stream, 0, 0, stream);\n\n  if (item.num_extents == 1)\n  {\n    const CExtent &e = Extents[item.first_extent_index];\n    if (e.IsRAW())\n    {\n      const UInt64 pos = e.target_data << kSectorSizeLog;\n      if ((pos >> kSectorSizeLog) != e.target_data)\n        return S_FALSE;\n      const UInt64 size = item.GetSize();\n      if (pos + size < pos)\n        return S_FALSE;\n      return CreateLimitedInStream(_stream, pos, size, stream);\n    }\n  }\n\n  CExtentsStream *extentStreamSpec = new CExtentsStream();\n  CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec;\n\n  // const unsigned kNumDebugExtents = 10;\n  extentStreamSpec->Extents.Reserve(item.num_extents + 1\n      // + kNumDebugExtents\n      );\n\n  UInt64 virt = 0;\n  for (UInt32 k = 0; k < item.num_extents; k++)\n  {\n    const CExtent &e = Extents[item.first_extent_index + k];\n\n    CSeekExtent se;\n    {\n      const UInt64 numSectors = e.num_sectors;\n      if (numSectors == 0)\n      {\n        continue;\n        // return S_FALSE;\n      }\n      const UInt64 numBytes = numSectors << kSectorSizeLog;\n      if ((numBytes >> kSectorSizeLog) != numSectors)\n        return S_FALSE;\n      if (numBytes >= ((UInt64)1 << 63) - virt)\n        return S_FALSE;\n      \n      se.Virt = virt;\n      virt += numBytes;\n    }\n\n    const UInt64 phySector = e.target_data;\n    if (e.target_type == LP_TARGET_TYPE_ZERO)\n    {\n      if (phySector != 0)\n        return S_FALSE;\n      se.SetAs_ZeroFill();\n    }\n    else if (e.target_type == LP_TARGET_TYPE_LINEAR)\n    {\n      se.Phy = phySector << kSectorSizeLog;\n      if ((se.Phy >> kSectorSizeLog) != phySector)\n        return S_FALSE;\n      if (se.Phy >= ((UInt64)1 << 63))\n        return S_FALSE;\n    }\n    else\n      return S_FALSE;\n\n    extentStreamSpec->Extents.AddInReserved(se);\n\n    /*\n    {\n      // for debug\n      const UInt64 kAdd = (e.num_sectors << kSectorSizeLog) / kNumDebugExtents;\n      for (unsigned i = 0; i < kNumDebugExtents; i++)\n      {\n        se.Phy += kAdd;\n        // se.Phy += (UInt64)1 << 63; // for debug\n        // se.Phy += 1; // for debug\n        se.Virt += kAdd;\n        extentStreamSpec->Extents.AddInReserved(se);\n      }\n    }\n    */\n  }\n\n  CSeekExtent se;\n  se.Phy = 0;\n  se.Virt = virt;\n  extentStreamSpec->Extents.Add(se);\n  extentStreamSpec->Stream = _stream;\n  extentStreamSpec->Init();\n  *stream = extentStream.Detach();\n  \n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n    totalSize += _items[index].GetSize();\n  }\n  extractCallback->SetTotal(totalSize);\n\n  totalSize = 0;\n  \n  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\n  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  for (i = 0; i < numItems; i++)\n  {\n    lps->InSize = totalSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    CMyComPtr<ISequentialOutStream> outStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    \n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n\n    const UInt64 size = _items[index].GetSize();\n    totalSize += size;\n    if (!testMode && !outStream)\n      continue;\n    \n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    CMyComPtr<ISequentialInStream> inStream;\n    const HRESULT hres = GetStream(index, &inStream);\n    int opRes = NExtract::NOperationResult::kUnsupportedMethod;\n    if (hres != S_FALSE)\n    {\n      if (hres != S_OK)\n        return hres;\n      RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))\n      opRes = NExtract::NOperationResult::kDataError;\n      if (copyCoderSpec->TotalSize == size)\n        opRes = NExtract::NOperationResult::kOK;\n      else if (copyCoderSpec->TotalSize < size)\n        opRes = NExtract::NOperationResult::kUnexpectedEnd;\n    }\n    outStream.Release();\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  \n  return S_OK;\n  COM_TRY_END\n}\n\n\nREGISTER_ARC_I(\n  \"LP\", \"lpimg img\", NULL, 0xc1,\n  k_Signature,\n  LP_PARTITION_RESERVED_BYTES,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/LvmHandler.cpp",
    "content": "﻿// LvmHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/7zCrc.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/StringToInt.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define LE_32(offs, dest) dest = Get32(p + (offs))\n#define LE_64(offs, dest) dest = Get64(p + (offs))\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NLvm {\n\n#define SIGNATURE { 'L', 'A', 'B', 'E', 'L', 'O', 'N', 'E'  }\n  \nstatic const unsigned k_SignatureSize = 8;\nstatic const Byte k_Signature[k_SignatureSize] = SIGNATURE;\n\nstatic const unsigned k_Signature2Size = 8;\nstatic const Byte k_Signature2[k_Signature2Size] =\n    { 'L', 'V', 'M', '2', ' ', '0', '0', '1'  };\n\nstatic const Byte FMTT_MAGIC[16] =\n    { ' ', 'L', 'V', 'M', '2', ' ', 'x', '[', '5', 'A', '%', 'r', '0', 'N', '*', '>'  };\n\nstatic const UInt32 kSectorSize = 512;\n\n\nstruct CPropVal\n{\n  bool IsNumber;\n  AString String;\n  UInt64 Number;\n  \n  CPropVal(): IsNumber(false), Number(0) {}\n};\n\n\nstruct CConfigProp\n{\n  AString Name;\n  \n  bool IsVector;\n  CPropVal Val;\n  CObjectVector<CPropVal> Vector;\n\n  CConfigProp(): IsVector(false) {}\n};\n\n\nclass CConfigItem\n{\npublic:\n  AString Name;\n  CObjectVector<CConfigProp> Props;\n  CObjectVector<CConfigItem> Items;\n  \n  const char *ParseItem(const char *s, int numAllowedLevels);\n\n  int FindProp(const char *name) const throw();\n  bool GetPropVal_Number(const char *name, UInt64 &val) const throw();\n  bool GetPropVal_String(const char *name, AString &val) const;\n\n  int FindSubItem(const char *tag) const throw();\n};\n\nstruct CConfig\n{\n  CConfigItem Root;\n\n  bool Parse(const char *s);\n};\n\n\nstatic bool IsSpaceChar(char c)\n{\n  return (c == ' ' || c == '\\t' || c == 0x0D || c == 0x0A);\n}\n\nstatic const char *SkipSpaces(const char * s)\n{\n  for (;; s++)\n  {\n    const char c = *s;\n    if (c == 0)\n      return s;\n    if (!IsSpaceChar(c))\n    {\n      if (c != '#')\n        return s;\n      s++;\n      for (;;)\n      {\n        const char c2 = *s;\n        if (c2 == 0)\n          return s;\n        if (c2 == '\\n')\n          break;\n        s++;\n      }\n    }\n  }\n}\n\n#define SKIP_SPACES(s) s = SkipSpaces(s);\n\nint CConfigItem::FindProp(const char *name) const throw()\n{\n  FOR_VECTOR (i, Props)\n    if (Props[i].Name == name)\n      return (int)i;\n  return -1;\n}\n\nbool CConfigItem::GetPropVal_Number(const char *name, UInt64 &val) const throw()\n{\n  val = 0;\n  int index = FindProp(name);\n  if (index < 0)\n    return false;\n  const CConfigProp &prop = Props[index];\n  if (prop.IsVector)\n    return false;\n  if (!prop.Val.IsNumber)\n    return false;\n  val = prop.Val.Number;\n  return true;\n}\n\nbool CConfigItem::GetPropVal_String(const char *name, AString &val) const\n{\n  val.Empty();\n  int index = FindProp(name);\n  if (index < 0)\n    return false;\n  const CConfigProp &prop = Props[index];\n  if (prop.IsVector)\n    return false;\n  if (prop.Val.IsNumber)\n    return false;\n  val = prop.Val.String;\n  return true;\n}\n\nint CConfigItem::FindSubItem(const char *tag) const throw()\n{\n  FOR_VECTOR (i, Items)\n    if (Items[i].Name == tag)\n      return (int)i;\n  return -1;\n}\n\nstatic const char *FillProp(const char *s, CPropVal &val)\n{\n  SKIP_SPACES(s)\n  const char c = *s;\n  if (c == 0)\n    return NULL;\n  \n  if (c == '\\\"')\n  {\n    s++;\n    val.IsNumber = false;\n    val.String.Empty();\n\n    for (;;)\n    {\n      const char c2 = *s;\n      if (c2 == 0)\n        return NULL;\n      s++;\n      if (c2 == '\\\"')\n        break;\n      val.String += c2;\n    }\n  }\n  else\n  {\n    const char *end;\n    val.IsNumber = true;\n    val.Number = ConvertStringToUInt64(s, &end);\n    if (s == end)\n      return NULL;\n    s = end;\n  }\n\n  SKIP_SPACES(s)\n  return s;\n}\n\n\nconst char *CConfigItem::ParseItem(const char *s, int numAllowedLevels)\n{\n  if (numAllowedLevels < 0)\n    return NULL;\n\n  for (;;)\n  {\n    SKIP_SPACES(s)\n    const char *beg = s;\n    \n    for (;; s++)\n    {\n      char c = *s;\n      if (c == 0 || c == '}')\n      {\n        if (s != beg)\n          return NULL;\n        return s;\n      }\n      if (IsSpaceChar(c) || c == '=' || c == '{')\n        break;\n    }\n    \n    if (s == beg)\n      return NULL;\n\n    AString name;\n    name.SetFrom(beg, (unsigned)(s - beg));\n    \n    SKIP_SPACES(s)\n    \n    if (*s == 0 || *s == '}')\n      return NULL;\n    \n    if (*s == '{')\n    {\n      s++;\n      CConfigItem &item = Items.AddNew();\n      item.Name = name;\n      s = item.ParseItem(s, numAllowedLevels - 1);\n      if (!s)\n        return NULL;\n      if (*s != '}')\n        return NULL;\n      s++;\n      continue;\n    }\n\n    if (*s != '=')\n      continue;\n\n    s++;\n    SKIP_SPACES(s)\n    if (*s == 0)\n      return NULL;\n    CConfigProp &prop = Props.AddNew();\n    \n    prop.Name = name;\n    \n    if (*s == '[')\n    {\n      s++;\n      prop.IsVector = true;\n      \n      for (;;)\n      {\n        SKIP_SPACES(s)\n        char c = *s;\n        if (c == 0)\n          return NULL;\n        if (c == ']')\n        {\n          s++;\n          break;\n        }\n        \n        CPropVal val;\n        \n        s = FillProp(s, val);\n        if (!s)\n          return NULL;\n        prop.Vector.Add(val);\n        SKIP_SPACES(s)\n        \n        if (*s == ',')\n        {\n          s++;\n          continue;\n        }\n        if (*s != ']')\n          return NULL;\n        s++;\n        break;\n      }\n    }\n    else\n    {\n      prop.IsVector = false;\n      s = FillProp(s, prop.Val);\n      if (!s)\n        return NULL;\n    }\n  }\n}\n\n\nbool CConfig::Parse(const char *s)\n{\n  s = Root.ParseItem(s, 10);\n  if (!s)\n    return false;\n  SKIP_SPACES(s)\n  return *s == 0;\n}\n\n\n/*\nstatic const CUInt32PCharPair g_PartitionFlags[] =\n{\n  { 0, \"Sys\" },\n  { 1, \"Ignore\" },\n  { 2, \"Legacy\" },\n  { 60, \"Win-Read-only\" },\n  { 62, \"Win-Hidden\" },\n  { 63, \"Win-Not-Automount\" }\n};\n*/\n\n/*\nstatic inline char GetHex(unsigned t) { return (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))); }\n\nstatic void PrintHex(unsigned v, char *s)\n{\n  s[0] = GetHex((v >> 4) & 0xF);\n  s[1] = GetHex(v & 0xF);\n}\n\nstatic void ConvertUInt16ToHex4Digits(UInt32 val, char *s) throw()\n{\n  PrintHex(val >> 8, s);\n  PrintHex(val & 0xFF, s + 2);\n}\n\nstatic void GuidToString(const Byte *g, char *s)\n{\n  ConvertUInt32ToHex8Digits(Get32(g   ),  s);  s += 8;  *s++ = '-';\n  ConvertUInt16ToHex4Digits(Get16(g + 4), s);  s += 4;  *s++ = '-';\n  ConvertUInt16ToHex4Digits(Get16(g + 6), s);  s += 4;  *s++ = '-';\n  for (unsigned i = 0; i < 8; i++)\n  {\n    if (i == 2)\n      *s++ = '-';\n    PrintHex(g[8 + i], s);\n    s += 2;\n  }\n  *s = 0;\n}\n\n*/\n\nstruct CPhyVol\n{\n  AString Name;\n\n  // AString id;\n  // AString device; // \"/dev/sda2\"\n  // AString status; // [\"ALLOCATABLE\"]\n  // AString flags; // []\n  // UInt64 dev_size; // in sectors\n  UInt64 pe_start; // in sectors\n  UInt64 pe_count; // in extents\n\n  bool Parse(const CConfigItem &ci)\n  {\n    Name = ci.Name;\n    // ci.GetPropVal_String(\"id\", id);\n    // ci.GetPropVal_String(\"device\", device);\n    bool res = true;\n    // if (!ci.GetPropVal_Number(\"dev_size\", dev_size)) res = false;\n    if (!ci.GetPropVal_Number(\"pe_start\", pe_start)) res = false;\n    if (!ci.GetPropVal_Number(\"pe_count\", pe_count)) res = false;\n    return res;\n  }\n};\n\nstruct CStripe\n{\n  AString Name; // \"pv0\";\n  UInt64 ExtentOffset; // ????\n};\n\nstruct CSegment\n{\n  UInt64 start_extent;\n  UInt64 extent_count;\n  AString type;\n  CObjectVector<CStripe> stripes;\n\n  bool IsPosSizeOk() const\n  {\n    return\n        (start_extent < ((UInt64)1 << 63)) &&\n        (extent_count < ((UInt64)1 << 63));\n  }\n\n  UInt64 GetEndExtent() const { return start_extent + extent_count; }\n\n  bool Parse(const CConfigItem &si)\n  {\n    UInt64 stripe_count;\n\n    if (!si.GetPropVal_Number(\"start_extent\", start_extent)) return false;\n    if (!si.GetPropVal_Number(\"extent_count\", extent_count)) return false;\n    if (!si.GetPropVal_Number(\"stripe_count\", stripe_count)) return false;\n    if (!si.GetPropVal_String(\"type\", type)) return false;\n\n    //if (stripe_count != 1) return false;\n\n    const int spi = si.FindProp(\"stripes\");\n    if (spi < 0)\n      return false;\n\n    const CConfigProp &prop = si.Props[spi];\n    if (!prop.IsVector)\n      return false;\n\n    if (stripe_count > (1 << 20))\n      return false;\n\n    const unsigned numStripes = (unsigned)stripe_count;\n    if (prop.Vector.Size() != numStripes * 2)\n      return false;\n\n    for (unsigned i = 0; i < numStripes; i++)\n    {\n      const CPropVal &v0 = prop.Vector[i * 2];\n      const CPropVal &v1 = prop.Vector[i * 2 + 1];\n      if (v0.IsNumber || !v1.IsNumber)\n        return false;\n      CStripe stripe;\n      stripe.Name = v0.String;\n      stripe.ExtentOffset = v1.Number;\n      stripes.Add(stripe);\n    }\n       \n    return true;\n  }\n};\n\n\nstruct CLogVol\n{\n  bool IsSupported;\n\n  AString Name;\n\n  AString id;\n  AString status; // [\"READ\", \"WRITE\", \"VISIBLE\"]\n  AString flags; // []\n\n  // UInt64 Pos;\n  // UInt64 Size;\n  \n  // UInt64 GetSize() const { return Size; }\n  // UInt64 GetPos() const { return Pos; }\n\n  CObjectVector<CSegment> Segments;\n\n  CLogVol(): /* Pos(0), Size(0), */ IsSupported(false) {}\n\n  bool Parse(const CConfigItem &ci)\n  {\n    Name = ci.Name;\n\n    UInt64 segment_count;\n    if (!ci.GetPropVal_Number(\"segment_count\", segment_count))\n      return false;\n    \n    if (ci.Items.Size() != segment_count)\n      return false;\n    \n    FOR_VECTOR (segIndex, ci.Items)\n    {\n      const CConfigItem &si = ci.Items[segIndex];\n      {\n        AString t (\"segment\");\n        t.Add_UInt32(segIndex + 1);\n        if (si.Name != t)\n          return false;\n      }\n      \n      CSegment segment;\n      \n      if (!segment.Parse(si))\n        return false;\n      \n      // item.Size += (segment.extent_count * _extentSize) << 9;\n      \n      Segments.Add(segment);\n    }\n    \n    IsSupported = true;\n    return true;\n  }\n\n  bool GetNumExtents(UInt64 &numExtents) const\n  {\n    numExtents = 0;\n    if (Segments.IsEmpty())\n      return true;\n    unsigned i;\n    for (i = 1; i < Segments.Size(); i++)\n      if (!Segments[i].IsPosSizeOk())\n        return false;\n    for (i = 1; i < Segments.Size(); i++)\n      if (Segments[i - 1].GetEndExtent() != Segments[i].start_extent)\n        return false;\n    numExtents = Segments.Back().GetEndExtent();\n    return true;\n  }\n};\n\n\nstruct CItem\n{\n  int LogVol;\n  int PhyVol;\n  UInt64 Pos;\n  UInt64 Size;\n  AString Name;\n  bool IsSupported;\n\n  CItem(): LogVol(-1), PhyVol(-1), Pos(0), Size(0), IsSupported(false) {}\n};\n\n\nstruct CVolGroup\n{\n  CObjectVector<CLogVol> _logVols;\n  CObjectVector<CPhyVol> _phyVols;\n  AString _id;\n  int _extentSizeBits;\n\n  /*\n  UInt64 secno; // 3\n  AString status; // [\"RESIZEABLE\", \"READ\", \"WRITE\"]\n  AString flags; // []\n  UInt64 max_lv; // 0\n  UInt64 max_pv; // 0\n  UInt64 metadata_copies; // 0\n  */\n\n  void Clear()\n  {\n    _logVols.Clear();\n    _phyVols.Clear();\n    _id.Empty();\n    _extentSizeBits = -1;\n  }\n};\n\n\nZ7_class_CHandler_final: public CHandlerCont, public CVolGroup\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Cont)\n\n  CObjectVector<CItem> _items;\n\n  UInt64 _cTime;\n\n  bool _isArc;\n\n  UInt64 _phySize;\n  CByteBuffer _buffer;\n\n  UInt64 _cfgPos;\n  UInt64 _cfgSize;\n\n  HRESULT Open2(IInStream *stream);\n  \n  virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override\n  {\n    if (index >= _items.Size())\n    {\n      pos = _cfgPos;\n      size = _cfgSize;\n      return NExtract::NOperationResult::kOK;\n    }\n    const CItem &item = _items[index];\n    if (!item.IsSupported)\n      return NExtract::NOperationResult::kUnsupportedMethod;\n    pos = item.Pos;\n    size = item.Size;\n    return NExtract::NOperationResult::kOK;\n  }\n};\n\nstatic const UInt32 LVM_CRC_INIT_VAL = 0xf597a6cf;\n\nstatic UInt32 Z7_FASTCALL LvmCrcCalc(const void *data, size_t size)\n{\n  return CrcUpdate(LVM_CRC_INIT_VAL, data, size);\n}\n\nstruct CRawLocn\n{\n  UInt64 Offset;  /* Offset in bytes to start sector */\n  UInt64 Size;    /* Bytes */\n  UInt32 Checksum;\n  UInt32 Flags;\n\n  bool IsEmpty() const { return Offset == 0 && Size == 0; }\n\n  void Parse(const Byte *p)\n  {\n    LE_64(0x00, Offset);\n    LE_64(0x08, Size);\n    LE_32(0x10, Checksum);\n    LE_32(0x14, Flags);\n  }\n};\n\n// #define MDA_HEADER_SIZE 512\n\nstruct mda_header\n{\n  UInt64 Start;   /* Absolute start byte of mda_header */\n  UInt64 Size;    /* Size of metadata area */\n\n  CRecordVector<CRawLocn> raw_locns;\n\n  bool Parse(const Byte *p, size_t size)\n  {\n    if (memcmp(p + 4, FMTT_MAGIC, 16) != 0)\n      return false;\n    UInt32 version;\n    LE_32(0x14, version);\n    if (version != 1)\n      return false;\n    LE_64(0x18, Start);\n    LE_64(0x20, Size);\n\n    unsigned pos = 0x28;\n\n    for (;;)\n    {\n      if (pos + 0x18 > size)\n        return false;\n      CRawLocn locn;\n      locn.Parse(p + pos);\n      if (locn.IsEmpty())\n        break;\n      pos += 0x18;\n      raw_locns.Add(locn);\n    }\n\n    return true;\n  }\n};\n\n\nstatic int inline GetLog(UInt64 num)\n{\n  for (unsigned i = 0; i < 64; i++)\n    if (((UInt64)1 << i) == num)\n      return (int)i;\n  return -1;\n}\n\n#define ID_LEN 32\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  _buffer.Alloc(kSectorSize * 2);\n  RINOK(ReadStream_FALSE(stream, _buffer, kSectorSize * 2))\n  \n  const Byte *buf = _buffer;\n  \n  buf += kSectorSize;\n\n  // label_header\n\n  if (memcmp(buf, k_Signature, k_SignatureSize) != 0)\n    return S_FALSE;\n  const UInt64 sectorNumber = Get64(buf + 8);\n  if (sectorNumber != 1)\n    return S_FALSE;\n  if (Get32(buf + 16) != LvmCrcCalc(buf + 20, kSectorSize - 20))\n    return S_FALSE;\n\n  const UInt32 offsetToCont = Get32(buf + 20);\n  if (memcmp(buf + 24, k_Signature2, k_Signature2Size) != 0)\n    return S_FALSE;\n\n  if (offsetToCont != 32)\n    return S_FALSE;\n\n  // pv_header\n\n  size_t pos = offsetToCont;\n  const Byte *p = buf;\n  \n  /*\n  {\n    Byte id[ID_LEN];\n    memcpy(id, p + pos, ID_LEN);\n  }\n  */\n\n  pos += ID_LEN;\n  const UInt64 device_size_xl = Get64(p + pos);\n  pos += 8;\n\n  _phySize = device_size_xl;\n  _isArc = true;\n\n  for (;;)\n  {\n    if (pos > kSectorSize - 16)\n      return S_FALSE;\n    // disk_locn (data areas)\n    UInt64 offset = Get64(p + pos);\n    UInt64 size = Get64(p + pos + 8);\n    pos += 16;\n    if (offset == 0 && size == 0)\n      break;\n  }\n\n  CConfig cfg;\n  // bool isFinded = false;\n\n  // for (;;)\n  {\n    if (pos > kSectorSize - 16)\n      return S_FALSE;\n    // disk_locn (metadata area headers)\n    UInt64 offset = Get64(p + pos);\n    UInt64 size = Get64(p + pos + 8);\n    pos += 16;\n    if (offset == 0 && size == 0)\n    {\n      // break;\n      return S_FALSE;\n    }\n\n    CByteBuffer meta;\n    const size_t sizeT = (size_t)size;\n    if (sizeT != size)\n      return S_FALSE;\n    meta.Alloc(sizeT);\n    RINOK(InStream_SeekSet(stream, offset))\n    RINOK(ReadStream_FALSE(stream, meta, sizeT))\n    if (Get32(meta) != LvmCrcCalc(meta + 4, kSectorSize - 4))\n      return S_FALSE;\n    mda_header mh;\n    if (!mh.Parse(meta, kSectorSize))\n      return S_FALSE;\n\n    if (mh.raw_locns.Size() != 1)\n      return S_FALSE;\n    unsigned g = 0;\n    // for (unsigned g = 0; g < mh.raw_locns.Size(); g++)\n    {\n      const CRawLocn &locn = mh.raw_locns[g];\n      \n      CByteBuffer vgBuf;\n      if (locn.Size > ((UInt32)1 << 24))\n        return S_FALSE;\n\n      const size_t vgSize = (size_t)locn.Size;\n      if (vgSize == 0)\n        return S_FALSE;\n\n      vgBuf.Alloc(vgSize);\n\n      _cfgPos = offset + locn.Offset;\n      _cfgSize = vgSize;\n      RINOK(InStream_SeekSet(stream, _cfgPos))\n      RINOK(ReadStream_FALSE(stream, vgBuf, vgSize))\n      if (locn.Checksum != LvmCrcCalc(vgBuf, vgSize))\n        return S_FALSE;\n\n      {\n        AString s;\n        s.SetFrom_CalcLen((const char *)(const Byte *)vgBuf, (unsigned)vgSize);\n        _cfgSize = s.Len();\n        if (!cfg.Parse(s))\n          return S_FALSE;\n        // isFinded = true;\n        // break;\n      }\n    }\n    \n    // if (isFinded) break;\n  }\n\n  // if (!isFinded) return S_FALSE;\n\n  if (cfg.Root.Items.Size() != 1)\n    return S_FALSE;\n  const CConfigItem &volGroup = cfg.Root.Items[0];\n  if (volGroup.Name != \"VolGroup00\")\n    return S_FALSE;\n\n  volGroup.GetPropVal_String(\"id\", _id);\n\n  if (!cfg.Root.GetPropVal_Number(\"creation_time\", _cTime))\n    _cTime = 0;\n\n  UInt64 extentSize;\n  if (!volGroup.GetPropVal_Number(\"extent_size\", extentSize))\n    return S_FALSE;\n\n  _extentSizeBits = GetLog(extentSize);\n  if (_extentSizeBits < 0 || _extentSizeBits > (62 - 9))\n    return S_FALSE;\n\n \n  {\n    int pvsIndex = volGroup.FindSubItem(\"physical_volumes\");\n    if (pvsIndex < 0)\n      return S_FALSE;\n    \n    const CConfigItem &phyVols = volGroup.Items[pvsIndex];\n    \n    FOR_VECTOR (i, phyVols.Items)\n    {\n      const CConfigItem &ci = phyVols.Items[i];\n      CPhyVol pv;\n      if (!pv.Parse(ci))\n        return S_FALSE;\n      _phyVols.Add(pv);\n    }\n  }\n\n  {\n    int lvIndex = volGroup.FindSubItem(\"logical_volumes\");\n    if (lvIndex < 0)\n      return S_FALSE;\n    \n    const CConfigItem &logVolumes = volGroup.Items[lvIndex];\n    \n    FOR_VECTOR (i, logVolumes.Items)\n    {\n      const CConfigItem &ci = logVolumes.Items[i];\n      CLogVol &lv = _logVols.AddNew();\n      lv.Parse(ci) ; // check error\n    }\n  }\n\n  {\n    FOR_VECTOR (i, _logVols)\n    {\n      CLogVol &lv = _logVols[i];\n      \n      CItem item;\n      \n      item.LogVol = (int)i;\n      item.Pos = 0;\n      item.Size = 0;\n      item.Name = lv.Name;\n\n      if (lv.IsSupported)\n      {\n        UInt64 numExtents;\n        lv.IsSupported = lv.GetNumExtents(numExtents);\n\n        if (lv.IsSupported)\n        {\n          lv.IsSupported = false;\n          item.Size = numExtents << (_extentSizeBits + 9);\n          \n          if (lv.Segments.Size() == 1)\n          {\n            const CSegment &segment = lv.Segments[0];\n            if (segment.stripes.Size() == 1)\n            {\n              const CStripe &stripe = segment.stripes[0];\n              FOR_VECTOR (pvIndex, _phyVols)\n              {\n                const CPhyVol &pv = _phyVols[pvIndex];\n                if (pv.Name == stripe.Name)\n                {\n                  item.Pos = (pv.pe_start + (stripe.ExtentOffset << _extentSizeBits)) << 9;\n                  lv.IsSupported = true;\n                  item.IsSupported = true;\n                  break;\n                }\n              }\n            }\n          }\n        }\n      }\n\n      _items.Add(item);\n    }\n  }\n\n  {\n    FOR_VECTOR (i, _phyVols)\n    {\n      const CPhyVol &pv = _phyVols[i];\n\n      if (pv.pe_start > (UInt64)1 << (62 - 9))\n        return S_FALSE;\n      if (pv.pe_count > (UInt64)1 << (62 - 9 - _extentSizeBits))\n        return S_FALSE;\n\n      CItem item;\n      \n      item.PhyVol = (int)i;\n      item.Pos = pv.pe_start << 9;\n      item.Size = pv.pe_count << (_extentSizeBits + 9);\n      item.Name = pv.Name;\n      item.IsSupported = true;\n\n      _items.Add(item);\n    }\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(stream))\n  _stream = stream;\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  CVolGroup::Clear();\n  \n  _cfgPos = 0;\n  _cfgSize = 0;\n  _cTime = 0;\n  _phySize = 0;\n  _isArc = false;\n  _items.Clear();\n\n  _stream.Release();\n  return S_OK;\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidFileSystem,\n  kpidCharacts,\n  kpidOffset,\n  kpidId\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidId,\n  kpidCTime,\n  kpidClusterSize\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  \n  switch (propID)\n  {\n    case kpidMainSubfile:\n    {\n      /*\n      if (_items.Size() == 1)\n        prop = (UInt32)0;\n      */\n      break;\n    }\n    case kpidPhySize: if (_phySize != 0) prop = _phySize; break;\n    case kpidId:\n    {\n      prop = _id;\n      break;\n    }\n    case kpidClusterSize:\n    {\n      if (_extentSizeBits >= 0)\n        prop = ((UInt64)1 << (_extentSizeBits + 9));\n      break;\n    }\n    case kpidCTime:\n    {\n      if (_cTime != 0)\n      {\n        FILETIME ft;\n        NTime::UnixTime64_To_FileTime((Int64)_cTime, ft);\n        prop = ft;\n      }\n      break;\n    }\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      // if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;\n      // if (_headerError) v |= kpv_ErrorFlags_HeadersError;\n      if (v == 0 && !_stream)\n        v |= kpv_ErrorFlags_UnsupportedMethod;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size() + (_cfgSize == 0 ? 0 : 1);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CItem &item = _items[index];\n\n  // const CLogVol &item = _items[index];\n\n  if (index >= _items.Size())\n  {\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        prop = \"meta.txt\";\n        break;\n      }\n    \n      case kpidSize:\n      case kpidPackSize: prop = _cfgSize; break;\n    }\n  }\n  else\n  {\n    switch (propID)\n    {\n    case kpidPath:\n      {\n        AString s = item.Name;\n        s += \".img\";\n        prop = s;\n        break;\n      }\n      \n    case kpidSize:\n    case kpidPackSize: prop = item.Size; break;\n    case kpidOffset: prop = item.Pos; break;\n      \n    case kpidId:\n      {\n        // prop = item.id;\n        break;\n      }\n      \n      // case kpidCharacts: FLAGS64_TO_PROP(g_PartitionFlags, item.Flags, prop); break;\n    }\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"LVM\", \"lvm\", NULL, 0xBF,\n  k_Signature,\n  kSectorSize,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/LzhHandler.cpp",
    "content": "﻿// LzhHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/AutoPtr.h\"\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/LzhDecoder.h\"\n\n#include \"IArchive.h\"\n\n#include \"Common/ItemNameUtils.h\"\n\nusing namespace NWindows;\nusing namespace NTime;\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n\n\n// CRC-16 (-IBM, -ANSI). The poly is 0x8005 (x^16 + x^15 + x^2 + 1)\n\nstatic const UInt16 kCrc16Poly = 0xA001;\n\nMY_ALIGN(64)\nstatic UInt16 g_LzhCrc16Table[256];\n\n#define CRC16_UPDATE_BYTE(crc, b) (g_LzhCrc16Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n\nUInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size);\nUInt32 LzhCrc16Update(UInt32 crc, const void *data, size_t size)\n{\n  const Byte *p = (const Byte *)data;\n  const Byte *pEnd = p + size;\n  for (; p != pEnd; p++)\n    crc = CRC16_UPDATE_BYTE(crc, *p);\n  return crc;\n}\n\nstatic struct CLzhCrc16TableInit\n{\n  CLzhCrc16TableInit()\n  {\n    for (UInt32 i = 0; i < 256; i++)\n    {\n      UInt32 r = i;\n      for (unsigned j = 0; j < 8; j++)\n        r = (r >> 1) ^ (kCrc16Poly & ((UInt32)0 - (r & 1)));\n      g_LzhCrc16Table[i] = (UInt16)r;\n    }\n  }\n} g_LzhCrc16TableInit;\n\n\nnamespace NArchive {\nnamespace NLzh{\n\nconst unsigned kMethodIdSize = 5;\n\nconst Byte kExtIdFileName = 0x01;\nconst Byte kExtIdDirName  = 0x02;\nconst Byte kExtIdUnixTime = 0x54;\n\nstruct CExtension\n{\n  Byte Type;\n  CByteBuffer Data;\n  \n  AString GetString() const\n  {\n    AString s;\n    s.SetFrom_CalcLen((const char *)(const Byte *)Data, (unsigned)Data.Size());\n    return s;\n  }\n};\n\nconst UInt32 kBasicPartSize = 22;\n\nAPI_FUNC_static_IsArc IsArc_Lzh(const Byte *p, size_t size)\n{\n  if (size < 2 + kBasicPartSize)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[2] != '-' || p[3] != 'l'  || p[4] != 'h' || p[6] != '-')\n    return k_IsArc_Res_NO;\n  Byte n = p[5];\n  if (n != 'd')\n    if (n < '0' || n > '7')\n      return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\nstruct CItem\n{\n  AString Name;\n  Byte Method[kMethodIdSize];\n  Byte Attributes;\n  Byte Level;\n  Byte OsId;\n  UInt32 PackSize;\n  UInt32 Size;\n  UInt32 ModifiedTime;\n  UInt16 CRC;\n  CObjectVector<CExtension> Extensions;\n\n  bool IsValidMethod() const  { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); }\n  bool IsLhMethod() const  {return (IsValidMethod() && Method[2] == 'h'); }\n  bool IsDir() const {return (IsLhMethod() && Method[3] == 'd'); }\n\n  bool IsCopyMethod() const\n  {\n    return (IsLhMethod() && Method[3] == '0') ||\n      (IsValidMethod() && Method[2] == 'z' && Method[3] == '4');\n  }\n  \n  bool IsLh1GroupMethod() const\n  {\n    if (!IsLhMethod())\n      return false;\n    switch (Method[3])\n    {\n      case '1':\n        return true;\n    }\n    return false;\n  }\n  \n  bool IsLh4GroupMethod() const\n  {\n    if (!IsLhMethod())\n      return false;\n    switch (Method[3])\n    {\n      case '4':\n      case '5':\n      case '6':\n      case '7':\n        return true;\n    }\n    return false;\n  }\n  \n  unsigned GetNumDictBits() const\n  {\n    if (!IsLhMethod())\n      return 0;\n    switch (Method[3])\n    {\n      case '1': return 12;\n      case '2': return 13;\n      case '3': return 13;\n      case '4': return 12;\n      case '5': return 13;\n      case '6': return 15;\n      case '7': return 16;\n    }\n    return 0;\n  }\n\n  int FindExt(Byte type) const\n  {\n    FOR_VECTOR (i, Extensions)\n      if (Extensions[i].Type == type)\n        return (int)i;\n    return -1;\n  }\n  \n  bool GetUnixTime(UInt32 &value) const\n  {\n    value = 0;\n    int index = FindExt(kExtIdUnixTime);\n    if (index < 0\n        || Extensions[index].Data.Size() < 4)\n    {\n      if (Level == 2)\n      {\n        value = ModifiedTime;\n        return true;\n      }\n      return false;\n    }\n    const Byte *data = (const Byte *)(Extensions[index].Data);\n    value = GetUi32(data);\n    return true;\n  }\n\n  AString GetDirName() const\n  {\n    int index = FindExt(kExtIdDirName);\n    if (index < 0)\n      return AString();\n    return Extensions[index].GetString();\n  }\n\n  AString GetFileName() const\n  {\n    int index = FindExt(kExtIdFileName);\n    if (index < 0)\n      return Name;\n    return Extensions[index].GetString();\n  }\n\n  AString GetName() const\n  {\n    AString s (GetDirName());\n    const char kDirSeparator = '\\\\';\n    // check kDirSeparator in Linux\n    s.Replace((char)(Byte)0xFF, kDirSeparator);\n    if (!s.IsEmpty() && s.Back() != kDirSeparator)\n      s += kDirSeparator;\n    s += GetFileName();\n    return s;\n  }\n};\n\nstatic const Byte *ReadUInt16(const Byte *p, UInt16 &v)\n{\n  v = Get16(p);\n  return p + 2;\n}\n\nstatic const Byte *ReadString(const Byte *p, size_t size, AString &s)\n{\n  s.Empty();\n  for (size_t i = 0; i < size; i++)\n  {\n    const Byte c = p[i];\n    if (c == 0)\n      break;\n    s += (char)c;\n  }\n  return p + size;\n}\n\nstatic Byte CalcSum(const Byte *data, size_t size)\n{\n  Byte sum = 0;\n  for (size_t i = 0; i < size; i++)\n    sum = (Byte)(sum + data[i]);\n  return sum;\n}\n\nstatic HRESULT GetNextItem(ISequentialInStream *stream, bool &filled, CItem &item)\n{\n  filled = false;\n\n  size_t processedSize = 2;\n  Byte startHeader[2];\n  RINOK(ReadStream(stream, startHeader, &processedSize))\n  if (processedSize == 0)\n    return S_OK;\n  if (processedSize == 1)\n    return (startHeader[0] == 0) ? S_OK: S_FALSE;\n  if (startHeader[0] == 0 && startHeader[1] == 0)\n    return S_OK;\n\n  Byte header[256];\n  processedSize = kBasicPartSize;\n  RINOK(ReadStream(stream, header, &processedSize))\n  if (processedSize != kBasicPartSize)\n    return (startHeader[0] == 0) ? S_OK: S_FALSE;\n\n  const Byte *p = header;\n  memcpy(item.Method, p, kMethodIdSize);\n  if (!item.IsValidMethod())\n    return S_OK;\n  p += kMethodIdSize;\n  item.PackSize = Get32(p);\n  item.Size = Get32(p + 4);\n  item.ModifiedTime = Get32(p + 8);\n  item.Attributes = p[12];\n  item.Level = p[13];\n  p += 14;\n  if (item.Level > 2)\n    return S_FALSE;\n  UInt32 headerSize;\n  if (item.Level < 2)\n  {\n    headerSize = startHeader[0];\n    if (headerSize < kBasicPartSize)\n      return S_FALSE;\n    RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, headerSize - kBasicPartSize))\n    if (startHeader[1] != CalcSum(header, headerSize))\n      return S_FALSE;\n    const size_t nameLength = *p++;\n    if ((size_t)(p - header) + nameLength + 2 > headerSize)\n      return S_FALSE;\n    p = ReadString(p, nameLength, item.Name);\n  }\n  else\n    headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);\n  p = ReadUInt16(p, item.CRC);\n  if (item.Level != 0)\n  {\n    if (item.Level == 2)\n    {\n      RINOK(ReadStream_FALSE(stream, header + kBasicPartSize, 2))\n    }\n    if ((size_t)(p - header) + 3 > headerSize)\n      return S_FALSE;\n    item.OsId = *p++;\n    UInt16 nextSize;\n    p = ReadUInt16(p, nextSize);\n    while (nextSize != 0)\n    {\n      if (nextSize < 3)\n        return S_FALSE;\n      if (item.Level == 1)\n      {\n        if (item.PackSize < nextSize)\n          return S_FALSE;\n        item.PackSize -= nextSize;\n      }\n      if (item.Extensions.Size() >= (1 << 8))\n        return S_FALSE;\n      CExtension ext;\n      RINOK(ReadStream_FALSE(stream, &ext.Type, 1))\n      nextSize = (UInt16)(nextSize - 3);\n      ext.Data.Alloc(nextSize);\n      RINOK(ReadStream_FALSE(stream, (Byte *)ext.Data, nextSize))\n      item.Extensions.Add(ext);\n      Byte hdr2[2];\n      RINOK(ReadStream_FALSE(stream, hdr2, 2))\n      ReadUInt16(hdr2, nextSize);\n    }\n  }\n  filled = true;\n  return S_OK;\n}\n\n\nstatic const CUInt32PCharPair g_OsPairs[] =\n{\n  {   0, \"MS-DOS\" },\n  { 'M', \"MS-DOS\" },\n  { '2', \"OS/2\" },\n  { '9', \"OS9\" },\n  { 'K', \"OS/68K\" },\n  { '3', \"OS/386\" },\n  { 'H', \"HUMAN\" },\n  { 'U', \"UNIX\" },\n  { 'C', \"CP/M\" },\n  { 'F', \"FLEX\" },\n  { 'm', \"Mac\" },\n  { 'R', \"Runser\" },\n  { 'T', \"TownsOS\" },\n  { 'X', \"XOSK\" },\n  { 'w', \"Windows 95\" },\n  { 'W', \"Windows NT\" },\n  { 'J', \"Java VM\" }\n};\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  // kpidAttrib,\n  kpidCRC,\n  kpidMethod,\n  kpidHostOS\n};\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithCRC\n  , ISequentialOutStream\n)\n  UInt32 _crc;\n  CMyComPtr<ISequentialOutStream> _stream;\npublic:\n  void Init(ISequentialOutStream *stream)\n  {\n    _stream = stream;\n    _crc = 0;\n  }\n  void ReleaseStream() { _stream.Release(); }\n  UInt32 GetCRC() const { return _crc; }\n};\n\nZ7_COM7F_IMF(COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT res = S_OK;\n  if (_stream)\n    res = _stream->Write(data, size, &size);\n  _crc = LzhCrc16Update(_crc, data, size);\n  if (processedSize)\n    *processedSize = size;\n  return res;\n}\n\n\nstruct CItemEx: public CItem\n{\n  UInt64 DataPosition;\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  CObjectVector<CItemEx> _items;\n  CMyComPtr<IInStream> _stream;\n  UInt64 _phySize;\n  UInt32 _errorFlags;\n  bool _isArc;\npublic:\n  CHandler();\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nCHandler::CHandler() {}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _phySize; break;\n   \n    case kpidErrorFlags:\n      UInt32 v = _errorFlags;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      prop = v;\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  const CItemEx &item = _items[index];\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      UString s = NItemName::WinPathToOsPath(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));\n      if (!s.IsEmpty())\n      {\n        if (s.Back() == WCHAR_PATH_SEPARATOR)\n          s.DeleteBack();\n        prop = s;\n      }\n      break;\n    }\n    case kpidIsDir:  prop = item.IsDir(); break;\n    case kpidSize:   prop = (UInt64)item.Size; break;\n    case kpidPackSize:  prop = (UInt64)item.PackSize; break;\n    case kpidCRC:  prop = (UInt32)item.CRC; break;\n    case kpidHostOS:  PAIR_TO_PROP(g_OsPairs, item.OsId, prop); break;\n    case kpidMTime:\n    {\n      UInt32 unixTime;\n      if (item.GetUnixTime(unixTime))\n        PropVariant_SetFrom_UnixTime(prop, unixTime);\n      else\n        PropVariant_SetFrom_DosTime(prop, item.ModifiedTime);\n      break;\n    }\n    // case kpidAttrib:  prop = (UInt32)item.Attributes; break;\n    case kpidMethod:\n    {\n      char method2[kMethodIdSize + 1];\n      method2[kMethodIdSize] = 0;\n      memcpy(method2, item.Method, kMethodIdSize);\n      prop = method2;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  Close();\n  try\n  {\n    _items.Clear();\n\n    UInt64 endPos;\n    bool needSetTotal = true;\n\n    RINOK(InStream_AtBegin_GetSize(stream, endPos))\n\n    for (;;)\n    {\n      CItemEx item;\n      bool filled;\n      const HRESULT res = GetNextItem(stream, filled, item);\n      RINOK(InStream_GetPos(stream, item.DataPosition))\n      if (res == S_FALSE)\n      {\n        _errorFlags = kpv_ErrorFlags_HeadersError;\n        break;\n      }\n\n      if (res != S_OK)\n        return S_FALSE;\n      _phySize = item.DataPosition;\n      if (!filled)\n        break;\n      _items.Add(item);\n\n      _isArc = true;\n\n      UInt64 newPostion;\n      RINOK(stream->Seek(item.PackSize, STREAM_SEEK_CUR, &newPostion))\n      if (newPostion > endPos)\n      {\n        _phySize = endPos;\n        _errorFlags = kpv_ErrorFlags_UnexpectedEnd;\n        break;\n      }\n      _phySize = newPostion;\n      if (callback)\n      {\n        if (needSetTotal)\n        {\n          RINOK(callback->SetTotal(NULL, &endPos))\n          needSetTotal = false;\n        }\n        if (_items.Size() % 100 == 0)\n        {\n          const UInt64 numFiles = _items.Size();\n          const UInt64 numBytes = item.DataPosition;\n          RINOK(callback->SetCompleted(&numFiles, &numBytes))\n        }\n      }\n    }\n    if (_items.IsEmpty())\n      return S_FALSE;\n\n    _stream = stream;\n  }\n  catch(...)\n  {\n    return S_FALSE;\n  }\n  COM_TRY_END\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _phySize = 0;\n  _errorFlags = 0;\n  _items.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalUnPacked = 0 /* , totalPacked = 0 */;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const CItemEx &item = _items[allFilesMode ? i : indices[i]];\n    totalUnPacked += item.Size;\n    // totalPacked += item.PackSize;\n  }\n  RINOK(extractCallback->SetTotal(totalUnPacked))\n\n  UInt32 cur_Unpacked, cur_Packed;\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_stream);\n\n  for (i = 0;; i++,\n      lps->OutSize += cur_Unpacked,\n      lps->InSize += cur_Packed)\n  {\n    cur_Unpacked = 0;\n    cur_Packed = 0;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    Int32 opRes;\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      const Int32 askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      const UInt32 index = allFilesMode ? i : indices[i];\n      const CItemEx &item = _items[index];\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n        \n      if (item.IsDir())\n      {\n        // if (!testMode)\n        {\n          RINOK(extractCallback->PrepareOperation(askMode))\n          RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        }\n        continue;\n      }\n      \n      if (!testMode && !realOutStream)\n        continue;\n      \n      RINOK(extractCallback->PrepareOperation(askMode))\n      cur_Unpacked = item.Size;\n      cur_Packed = item.PackSize;\n\n      CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;\n      outStream->Init(realOutStream);\n      realOutStream.Release();\n      \n      RINOK(InStream_SeekSet(_stream, item.DataPosition))\n\n      inStream->Init(item.PackSize);\n\n      HRESULT res = S_OK;\n      opRes = NExtract::NOperationResult::kOK;\n\n      if (item.IsCopyMethod())\n      {\n        res = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);\n        if (res == S_OK && copyCoder->TotalSize != item.PackSize)\n          res = S_FALSE;\n      }\n      else if (item.IsLh4GroupMethod())\n      {\n        lzhDecoder.Create_if_Empty();\n        // lzhDecoder->FinishMode = true;\n        lzhDecoder->SetDictSize((UInt32)1 << item.GetNumDictBits());\n        res = lzhDecoder->Code(inStream, outStream, cur_Unpacked, lps);\n        if (res == S_OK && lzhDecoder->GetInputProcessedSize() != item.PackSize)\n          res = S_FALSE;\n      }\n      /*\n      else if (item.IsLh1GroupMethod())\n      {\n        if (!lzh1Decoder)\n        {\n          lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder;\n          lzh1Decoder = lzh1DecoderSpec;\n        }\n        lzh1DecoderSpec->SetDictionary(item.GetNumDictBits());\n        res = lzh1Decoder->Code(inStream, outStream, NULL, &cur_Unpacked, progress);\n      }\n      */\n      else\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n\n      if (opRes == NExtract::NOperationResult::kOK)\n      {\n        if (res == S_FALSE)\n          opRes = NExtract::NOperationResult::kDataError;\n        else\n        {\n          RINOK(res)\n          if (outStream->GetCRC() != item.CRC)\n            opRes = NExtract::NOperationResult::kCRCError;\n        }\n      }\n    }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = { '-', 'l', 'h' };\n\nREGISTER_ARC_I(\n  \"Lzh\", \"lzh lha\", NULL, 6,\n  k_Signature,\n  2,\n  0,\n  IsArc_Lzh)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/LzmaHandler.cpp",
    "content": "﻿// LzmaHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/FilterCoder.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/BcjCoder.h\"\n#include \"../Compress/LzmaDecoder.h\"\n\n#include \"Common/DummyOutStream.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NLzma {\n\nstatic bool CheckDicSize(const Byte *p)\n{\n  UInt32 dicSize = GetUi32(p);\n  if (dicSize == 1)\n    return true;\n  for (unsigned i = 0; i <= 30; i++)\n    if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i))\n      return true;\n  return (dicSize == 0xFFFFFFFF);\n}\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize,\n  kpidMethod\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumStreams,\n  kpidMethod\n};\n\nstruct CHeader\n{\n  UInt64 Size;\n  Byte FilterID;\n  Byte LzmaProps[5];\n\n  Byte GetProp() const { return LzmaProps[0]; }\n  UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); }\n  bool HasSize() const { return (Size != (UInt64)(Int64)-1); }\n  bool Parse(const Byte *buf, bool isThereFilter);\n};\n\nbool CHeader::Parse(const Byte *buf, bool isThereFilter)\n{\n  FilterID = 0;\n  if (isThereFilter)\n    FilterID = buf[0];\n  const Byte *sig = buf + (isThereFilter ? 1 : 0);\n  for (int i = 0; i < 5; i++)\n    LzmaProps[i] = sig[i];\n  Size = GetUi64(sig + 5);\n  return\n    LzmaProps[0] < 5 * 5 * 9 &&\n    FilterID < 2 &&\n    (!HasSize() || Size < ((UInt64)1 << 56))\n    && CheckDicSize(LzmaProps + 1);\n}\n\nclass CDecoder Z7_final\n{\n  CMyComPtr<ISequentialOutStream> _bcjStream;\n  CFilterCoder *_filterCoder;\npublic:\n  CMyComPtr2<ICompressCoder, NCompress::NLzma::CDecoder> _lzmaDecoder;\n\n  ~CDecoder();\n  HRESULT Create(bool filtered, ISequentialInStream *inStream);\n\n  HRESULT Code(const CHeader &header, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n\n  UInt64 GetInputProcessedSize() const { return _lzmaDecoder->GetInputProcessedSize(); }\n\n  void ReleaseInStream() { if (_lzmaDecoder) _lzmaDecoder->ReleaseInStream(); }\n\n  HRESULT ReadInput(Byte *data, UInt32 size, UInt32 *processedSize)\n    { return _lzmaDecoder->ReadFromInputStream(data, size, processedSize); }\n};\n\nHRESULT CDecoder::Create(bool filteredMode, ISequentialInStream *inStream)\n{\n  _lzmaDecoder.Create_if_Empty();\n  _lzmaDecoder->FinishStream = true;\n\n  if (filteredMode)\n  {\n    if (!_bcjStream)\n    {\n      _filterCoder = new CFilterCoder(false);\n      CMyComPtr<ICompressCoder> coder = _filterCoder;\n      _filterCoder->Filter = new NCompress::NBcj::CCoder2(z7_BranchConvSt_X86_Dec);\n      _bcjStream = _filterCoder;\n    }\n  }\n\n  return _lzmaDecoder->SetInStream(inStream);\n}\n\nCDecoder::~CDecoder()\n{\n  ReleaseInStream();\n}\n\nHRESULT CDecoder::Code(const CHeader &header, ISequentialOutStream *outStream,\n    ICompressProgressInfo *progress)\n{\n  if (header.FilterID > 1)\n    return E_NOTIMPL;\n\n  RINOK(_lzmaDecoder->SetDecoderProperties2(header.LzmaProps, 5))\n\n  bool filteredMode = (header.FilterID == 1);\n\n  if (filteredMode)\n  {\n    RINOK(_filterCoder->SetOutStream(outStream))\n    outStream = _bcjStream;\n    RINOK(_filterCoder->SetOutStreamSize(NULL))\n  }\n\n  const UInt64 *Size = header.HasSize() ? &header.Size : NULL;\n  HRESULT res = _lzmaDecoder->CodeResume(outStream, Size, progress);\n\n  if (filteredMode)\n  {\n    {\n      HRESULT res2 = _filterCoder->OutStreamFinish();\n      if (res == S_OK)\n        res = res2;\n    }\n    HRESULT res2 = _filterCoder->ReleaseOutStream();\n    if (res == S_OK)\n      res = res2;\n  }\n  \n  RINOK(res)\n\n  if (header.HasSize())\n    if (_lzmaDecoder->GetOutputProcessedSize() != header.Size)\n      return S_FALSE;\n\n  return S_OK;\n}\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IArchiveOpenSeq\n)\n  bool _lzma86;\n  bool _isArc;\n  bool _needSeekToStart;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n  bool _unsupported;\n  bool _dataError;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n  bool _numStreams_Defined;\n\n  CHeader _header;\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n  \n  UInt64 _packSize;\n  UInt64 _unpackSize;\n  UInt64 _numStreams;\n\n  void GetMethod(NCOM::CPropVariant &prop);\n\n  unsigned GetHeaderSize() const { return 5 + 8 + (_lzma86 ? 1 : 0); }\npublic:\n  CHandler(bool lzma86) { _lzma86 = lzma86; }\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidNumStreams: if (_numStreams_Defined) prop = _numStreams; break;\n    case kpidUnpackSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n    case kpidMethod: GetMethod(prop); break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;\n      if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;\n      if (_dataError) v |= kpv_ErrorFlags_DataError;\n      prop = v;\n      break;\n    }\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\n\nstatic char * DictSizeToString(UInt32 val, char *s)\n{\n  for (unsigned i = 0; i < 32; i++)\n    if (((UInt32)1 << i) == val)\n      return ::ConvertUInt32ToString(i, s);\n  char c = 'b';\n       if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }\n  else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }\n  s = ::ConvertUInt32ToString(val, s);\n  *s++ = c;\n  *s = 0;\n  return s;\n}\n\nstatic char *AddProp32(char *s, const char *name, UInt32 v)\n{\n  *s++ = ':';\n  s = MyStpCpy(s, name);\n  return ::ConvertUInt32ToString(v, s);\n}\n\nvoid CHandler::GetMethod(NCOM::CPropVariant &prop)\n{\n  if (!_stream)\n    return;\n\n  char sz[64];\n  char *s = sz;\n  if (_header.FilterID != 0)\n    s = MyStpCpy(s, \"BCJ \");\n  s = MyStpCpy(s, \"LZMA:\");\n  s = DictSizeToString(_header.GetDicSize(), s);\n  \n  UInt32 d = _header.GetProp();\n  // if (d != 0x5D)\n  {\n    UInt32 lc = d % 9;\n    d /= 9;\n    UInt32 pb = d / 5;\n    UInt32 lp = d % 5;\n    if (lc != 3) s = AddProp32(s, \"lc\", lc);\n    if (lp != 0) s = AddProp32(s, \"lp\", lp);\n    if (pb != 2) s = AddProp32(s, \"pb\", pb);\n  }\n  prop = sz;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidSize: if (_stream && _header.HasSize()) prop = _header.Size; break;\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidMethod: GetMethod(prop); break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nAPI_FUNC_static_IsArc IsArc_Lzma(const Byte *p, size_t size)\n{\n  const UInt32 kHeaderSize = 1 + 4 + 8;\n  if (size < kHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] >= 5 * 5 * 9)\n    return k_IsArc_Res_NO;\n  const UInt64 unpackSize = GetUi64(p + 1 + 4);\n  if (unpackSize != (UInt64)(Int64)-1)\n  {\n    if (unpackSize >= ((UInt64)1 << 56))\n      return k_IsArc_Res_NO;\n  }\n  if (unpackSize != 0)\n  {\n    if (size < kHeaderSize + 2)\n      return k_IsArc_Res_NEED_MORE;\n    if (p[kHeaderSize] != 0)\n      return k_IsArc_Res_NO;\n    if (unpackSize != (UInt64)(Int64)-1)\n    {\n      if ((p[kHeaderSize + 1] & 0x80) != 0)\n        return k_IsArc_Res_NO;\n    }\n  }\n  if (!CheckDicSize(p + 1))\n    // return k_IsArc_Res_YES_LOW_PROB;\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\nAPI_FUNC_static_IsArc IsArc_Lzma86(const Byte *p, size_t size)\n{\n  if (size < 1)\n    return k_IsArc_Res_NEED_MORE;\n  Byte filterID = p[0];\n  if (filterID != 0 && filterID != 1)\n    return k_IsArc_Res_NO;\n  return IsArc_Lzma(p + 1, size - 1);\n}\n}\n\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *))\n{\n  Close();\n  \n  const unsigned headerSize = GetHeaderSize();\n  const UInt32 kBufSize = 1 << 7;\n  Byte buf[kBufSize];\n  size_t processedSize = kBufSize;\n  RINOK(ReadStream(inStream, buf, &processedSize))\n  if (processedSize < headerSize + 2)\n    return S_FALSE;\n  if (!_header.Parse(buf, _lzma86))\n    return S_FALSE;\n  const Byte *start = buf + headerSize;\n  if (start[0] != 0 /* || (start[1] & 0x80) != 0 */ ) // empty stream with EOS is not 0x80\n    return S_FALSE;\n\n  RINOK(InStream_GetSize_SeekToEnd(inStream, _packSize))\n\n  SizeT srcLen = (SizeT)processedSize - headerSize;\n\n  if (srcLen > 10\n      && _header.Size == 0\n      // && _header.FilterID == 0\n      && _header.LzmaProps[0] == 0\n      )\n    return S_FALSE;\n\n  const UInt32 outLimit = 1 << 11;\n  Byte outBuf[outLimit];\n\n  SizeT outSize = outLimit;\n  if (outSize > _header.Size)\n    outSize = (SizeT)_header.Size;\n  SizeT destLen = outSize;\n  ELzmaStatus status;\n  \n  SRes res = LzmaDecode(outBuf, &destLen, start, &srcLen,\n      _header.LzmaProps, 5, LZMA_FINISH_ANY,\n      &status, &g_Alloc);\n  \n  if (res != SZ_OK)\n    if (res != SZ_ERROR_INPUT_EOF)\n      return S_FALSE;\n\n  _isArc = true;\n  _stream = inStream;\n  _seqStream = inStream;\n  _needSeekToStart = true;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n  _needSeekToStart = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n  _unsupported = false;\n  _dataError = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined = false;\n  _numStreams_Defined = false;\n\n  _packSize = 0;\n\n  _stream.Release();\n  _seqStream.Release();\n   return S_OK;\n}\n\nZ7_CLASS_IMP_COM_1(\n  CCompressProgressInfoImp,\n  ICompressProgressInfo\n)\n  CMyComPtr<IArchiveOpenCallback> Callback;\npublic:\n  UInt64 Offset;\n\n  void Init(IArchiveOpenCallback *callback) { Callback = callback; }\n};\n\nZ7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))\n{\n  if (Callback)\n  {\n    const UInt64 files = 0;\n    const UInt64 val = Offset + *inSize;\n    return Callback->SetCompleted(&files, &val);\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  if (_packSize_Defined)\n    RINOK(extractCallback->SetTotal(_packSize))\n    \n  Int32 opResult;\n {\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n  if (!testMode && !realOutStream)\n    return S_OK;\n  \n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;\n  outStream->SetStream(realOutStream);\n  outStream->Init();\n  realOutStream.Release();\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, true);\n\n  if (_needSeekToStart)\n  {\n    if (!_stream)\n      return E_FAIL;\n    RINOK(InStream_SeekToBegin(_stream))\n  }\n  else\n    _needSeekToStart = true;\n\n  CDecoder decoder;\n  RINOK(decoder.Create(_lzma86, _seqStream))\n \n  bool firstItem = true;\n\n  UInt64 packSize = 0;\n  UInt64 unpackSize = 0;\n  UInt64 numStreams = 0;\n\n  bool dataAfterEnd = false;\n  \n  HRESULT hres = S_OK;\n\n  for (;;)\n  {\n    lps->InSize = packSize;\n    lps->OutSize = unpackSize;\n    RINOK(lps->SetCur())\n\n    const UInt32 kBufSize = 1 + 5 + 8;\n    Byte buf[kBufSize];\n    const UInt32 headerSize = GetHeaderSize();\n    UInt32 processed;\n    RINOK(decoder.ReadInput(buf, headerSize, &processed))\n    if (processed != headerSize)\n    {\n      if (processed != 0)\n        dataAfterEnd = true;\n      break;\n    }\n  \n    CHeader st;\n    if (!st.Parse(buf, _lzma86))\n    {\n      dataAfterEnd = true;\n      break;\n    }\n    numStreams++;\n    firstItem = false;\n\n    hres = decoder.Code(st, outStream, lps);\n\n    packSize = decoder.GetInputProcessedSize();\n    unpackSize = outStream->GetSize();\n    \n    if (hres == E_NOTIMPL)\n    {\n      _unsupported = true;\n      hres = S_FALSE;\n      break;\n    }\n    if (hres == S_FALSE)\n      break;\n    RINOK(hres)\n  }\n\n  if (firstItem)\n  {\n    _isArc = false;\n    hres = S_FALSE;\n  }\n  else if (hres == S_OK || hres == S_FALSE)\n  {\n    if (dataAfterEnd)\n      _dataAfterEnd = true;\n    else if (decoder._lzmaDecoder->NeedsMoreInput())\n      _needMoreInput = true;\n\n    _packSize = packSize;\n    _unpackSize = unpackSize;\n    _numStreams = numStreams;\n  \n    _packSize_Defined = true;\n    _unpackSize_Defined = true;\n    _numStreams_Defined = true;\n  }\n  \n  opResult = NExtract::NOperationResult::kOK;\n\n  if (!_isArc)\n    opResult = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opResult = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (_unsupported)\n    opResult = NExtract::NOperationResult::kUnsupportedMethod;\n  else if (_dataAfterEnd)\n    opResult = NExtract::NOperationResult::kDataAfterEnd;\n  else if (hres == S_FALSE)\n    opResult = NExtract::NOperationResult::kDataError;\n  else if (hres == S_OK)\n    opResult = NExtract::NOperationResult::kOK;\n  else\n    return hres;\n\n  // outStream.Release();\n }\n  return extractCallback->SetOperationResult(opResult);\n\n  COM_TRY_END\n}\n\nnamespace NLzmaAr {\n\n// 2, { 0x5D, 0x00 },\n\nREGISTER_ARC_I_CLS_NO_SIG(\n  CHandler(false),\n  \"lzma\", \"lzma\", NULL, 0xA,\n  0,\n  NArcInfoFlags::kStartOpen |\n  NArcInfoFlags::kKeepName,\n  IsArc_Lzma)\n \n}\n\nnamespace NLzma86Ar {\n\nREGISTER_ARC_I_CLS_NO_SIG(\n  CHandler(true),\n  \"lzma86\", \"lzma86\", NULL, 0xB,\n  0,\n  NArcInfoFlags::kKeepName,\n  IsArc_Lzma86)\n \n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/MachoHandler.cpp",
    "content": "﻿// MachoHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/StringConvert.h\"\n#include \"../../Common/IntToString.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\nstatic UInt32 Get32(const Byte *p, bool be) { if (be) return GetBe32(p); return GetUi32(p); }\nstatic UInt64 Get64(const Byte *p, bool be) { if (be) return GetBe64(p); return GetUi64(p); }\n\nusing namespace NWindows;\nusing namespace NCOM;\n\nnamespace NArchive {\nnamespace NMacho {\n\n#define CPU_ARCH_ABI64 (1 << 24)\n#define CPU_TYPE_386    7\n#define CPU_TYPE_ARM   12\n#define CPU_TYPE_SPARC 14\n#define CPU_TYPE_PPC   18\n\n#define CPU_SUBTYPE_I386_ALL 3\n\n// #define CPU_TYPE_PPC64 (CPU_ARCH_ABI64 | CPU_TYPE_PPC)\n#define CPU_TYPE_AMD64 (CPU_ARCH_ABI64 | CPU_TYPE_386)\n#define CPU_TYPE_ARM64 (CPU_ARCH_ABI64 | CPU_TYPE_ARM)\n\n#define CPU_SUBTYPE_LIB64 ((UInt32)1 << 31)\n\n#define CPU_SUBTYPE_POWERPC_970 100\n\nstatic const char * const k_PowerPc_SubTypes[] =\n{\n  NULL\n  , \"601\"\n  , \"602\"\n  , \"603\"\n  , \"603e\"\n  , \"603ev\"\n  , \"604\"\n  , \"604e\"\n  , \"620\"\n  , \"750\"\n  , \"7400\"\n  , \"7450\"\n};\n\nstatic const CUInt32PCharPair g_CpuPairs[] =\n{\n  { CPU_TYPE_AMD64, \"x64\" },\n  { CPU_TYPE_ARM64, \"ARM64\" },\n  { CPU_TYPE_386, \"x86\" },\n  { CPU_TYPE_ARM, \"ARM\" },\n  { CPU_TYPE_SPARC, \"SPARC\" },\n  { CPU_TYPE_PPC, \"PowerPC\" }\n};\n\n\n#define CMD_SEGMENT_32 1\n#define CMD_SEGMENT_64 0x19\n\n#define SECT_TYPE_MASK 0x000000FF\n#define SECT_ATTR_MASK 0xFFFFFF00\n\n#define SECT_ATTR_ZEROFILL 1\n\nstatic const char * const g_SectTypes[] =\n{\n    \"REGULAR\"\n  , \"ZEROFILL\"\n  , \"CSTRINGS\"\n  , \"4BYTE_LITERALS\"\n  , \"8BYTE_LITERALS\"\n  , \"LITERAL_POINTERS\"\n  , \"NON_LAZY_SYMBOL_POINTERS\"\n  , \"LAZY_SYMBOL_POINTERS\"\n  , \"SYMBOL_STUBS\"\n  , \"MOD_INIT_FUNC_POINTERS\"\n  , \"MOD_TERM_FUNC_POINTERS\"\n  , \"COALESCED\"\n  , \"GB_ZEROFILL\"\n  , \"INTERPOSING\"\n  , \"16BYTE_LITERALS\"\n  , \"DTRACE_DOF\"\n  , \"LAZY_DYLIB_SYMBOL_POINTERS\"\n  , \"THREAD_LOCAL_REGULAR\"\n  , \"THREAD_LOCAL_ZEROFILL\"\n  , \"THREAD_LOCAL_VARIABLES\"\n  , \"THREAD_LOCAL_VARIABLE_POINTERS\"\n  , \"THREAD_LOCAL_INIT_FUNCTION_POINTERS\"\n};\n\nenum EFileType\n{\n  kType_OBJECT = 1,\n  kType_EXECUTE,\n  kType_FVMLIB,\n  kType_CORE,\n  kType_PRELOAD,\n  kType_DYLIB,\n  kType_DYLINKER,\n  kType_BUNDLE,\n  kType_DYLIB_STUB,\n  kType_DSYM\n};\n\nstatic const char * const g_FileTypes[] =\n{\n    \"0\"\n  , \"OBJECT\"\n  , \"EXECUTE\"\n  , \"FVMLIB\"\n  , \"CORE\"\n  , \"PRELOAD\"\n  , \"DYLIB\"\n  , \"DYLINKER\"\n  , \"BUNDLE\"\n  , \"DYLIB_STUB\"\n  , \"DSYM\"\n};\n\n\nstatic const char * const g_ArcFlags[] =\n{\n    \"NOUNDEFS\"\n  , \"INCRLINK\"\n  , \"DYLDLINK\"\n  , \"BINDATLOAD\"\n  , \"PREBOUND\"\n  , \"SPLIT_SEGS\"\n  , \"LAZY_INIT\"\n  , \"TWOLEVEL\"\n  , \"FORCE_FLAT\"\n  , \"NOMULTIDEFS\"\n  , \"NOFIXPREBINDING\"\n  , \"PREBINDABLE\"\n  , \"ALLMODSBOUND\"\n  , \"SUBSECTIONS_VIA_SYMBOLS\"\n  , \"CANONICAL\"\n  , \"WEAK_DEFINES\"\n  , \"BINDS_TO_WEAK\"\n  , \"ALLOW_STACK_EXECUTION\"\n  , \"ROOT_SAFE\"\n  , \"SETUID_SAFE\"\n  , \"NO_REEXPORTED_DYLIBS\"\n  , \"PIE\"\n  , \"DEAD_STRIPPABLE_DYLIB\"\n  , \"HAS_TLV_DESCRIPTORS\"\n  , \"NO_HEAP_EXECUTION\"\n};\n\n\nstatic const CUInt32PCharPair g_SectFlags[] =\n{\n  { 31, \"PURE_INSTRUCTIONS\" },\n  { 30, \"NO_TOC\" },\n  { 29, \"STRIP_STATIC_SYMS\" },\n  { 28, \"NO_DEAD_STRIP\" },\n  { 27, \"LIVE_SUPPORT\" },\n  { 26, \"SELF_MODIFYING_CODE\" },\n  { 25, \"DEBUG\" },\n  { 10, \"SOME_INSTRUCTIONS\" },\n  {  9, \"EXT_RELOC\" },\n  {  8, \"LOC_RELOC\" }\n};\n\n\n// VM_PROT_*\nstatic const char * const g_SegmentProt[] =\n{\n    \"READ\"\n  , \"WRITE\"\n  , \"EXECUTE\"\n  /*\n  , \"NO_CHANGE\"\n  , \"COPY\"\n  , \"TRUSTED\"\n  , \"IS_MASK\"\n  */\n};\n\n// SG_*\n\nstatic const char * const g_SegmentFlags[] =\n{\n    \"SG_HIGHVM\"\n  , \"SG_FVMLIB\"\n  , \"SG_NORELOC\"\n  , \"SG_PROTECTED_VERSION_1\"\n  , \"SG_READ_ONLY\"\n};\n\nstatic const unsigned kNameSize = 16;\n\nstruct CSegment\n{\n  char Name[kNameSize];\n  UInt32 MaxProt;\n  UInt32 InitProt;\n  UInt32 Flags;\n};\n\nstruct CSection\n{\n  char Name[kNameSize];\n  // char SegName[kNameSize];\n  UInt64 Va;\n  UInt64 Pa;\n  UInt64 VSize;\n  UInt64 PSize;\n\n  UInt32 Align;\n  UInt32 Flags;\n  unsigned SegmentIndex;\n  bool IsDummy;\n\n  CSection(): IsDummy(false) {}\n  // UInt64 GetPackSize() const { return Flags == SECT_ATTR_ZEROFILL ? 0 : Size; }\n  UInt64 GetPackSize() const { return PSize; }\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IArchiveAllowTail\n)\n  CMyComPtr<IInStream> _inStream;\n  CObjectVector<CSegment> _segments;\n  CObjectVector<CSection> _sections;\n  bool _allowTail;\n  bool _mode64;\n  bool _be;\n  UInt32 _cpuType;\n  UInt32 _cpuSubType;\n  UInt32 _type;\n  UInt32 _flags;\n  UInt32 _headersSize;\n  UInt64 _totalSize;\n\n  HRESULT Open2(ISequentialInStream *stream);\npublic:\n  CHandler(): _allowTail(false) {}\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidCpu,\n  kpidBit64,\n  kpidBigEndian,\n  kpidCharacts,\n  kpidHeadersSize\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidCharacts,\n  kpidOffset,\n  kpidVa,\n  kpidClusterSize // Align\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  CPropVariant prop;\n  switch (propID)\n  {\n    case kpidShortComment:\n    case kpidCpu:\n    {\n      AString s;\n      const UInt32 cpu = _cpuType & ~(UInt32)CPU_ARCH_ABI64;\n      UInt32 flag64 = _cpuType & (UInt32)CPU_ARCH_ABI64;\n      {\n        s.Add_UInt32(cpu);\n        for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_CpuPairs); i++)\n        {\n          const CUInt32PCharPair &pair = g_CpuPairs[i];\n          if (pair.Value == cpu || pair.Value == _cpuType)\n          {\n            if (pair.Value == _cpuType)\n              flag64 = 0;\n            s = pair.Name;\n            break;\n          }\n        }\n       \n        if (flag64 != 0)\n          s.Add_OptSpaced(\"64-bit\");\n        else if ((_cpuSubType & CPU_SUBTYPE_LIB64) && _cpuType != CPU_TYPE_AMD64)\n          s.Add_OptSpaced(\"64-bit-lib\");\n      }\n      const UInt32 t = _cpuSubType & ~(UInt32)CPU_SUBTYPE_LIB64;\n      if (t != 0 && (t != CPU_SUBTYPE_I386_ALL || cpu != CPU_TYPE_386))\n      {\n        const char *n = NULL;\n        if (cpu == CPU_TYPE_PPC)\n        {\n          if (t == CPU_SUBTYPE_POWERPC_970)\n            n = \"970\";\n          else if (t < Z7_ARRAY_SIZE(k_PowerPc_SubTypes))\n            n = k_PowerPc_SubTypes[t];\n        }\n        s.Add_Space();\n        if (n)\n          s += n;\n        else\n          s.Add_UInt32(t);\n      }\n      prop = s;\n      break;\n    }\n    case kpidCharacts:\n    {\n      // TYPE_TO_PROP(g_FileTypes, _type, prop); break;\n      AString res (TypeToString(g_FileTypes, Z7_ARRAY_SIZE(g_FileTypes), _type));\n      const AString s (FlagsToString(g_ArcFlags, Z7_ARRAY_SIZE(g_ArcFlags), _flags));\n      if (!s.IsEmpty())\n      {\n        res.Add_Space();\n        res += s;\n      }\n      prop = res;\n      break;\n    }\n    case kpidPhySize:  prop = _totalSize; break;\n    case kpidHeadersSize:  prop = _headersSize; break;\n    case kpidBit64:  if (_mode64) prop = _mode64; break;\n    case kpidBigEndian:  if (_be) prop = _be; break;\n    case kpidExtension:\n    {\n      const char *ext = NULL;\n      if (_type == kType_OBJECT)\n        ext = \"o\";\n      else if (_type == kType_BUNDLE)\n        ext = \"bundle\";\n      else if (_type == kType_DYLIB)\n        ext = \"dylib\"; // main shared library usually does not have extension\n      if (ext)\n        prop = ext;\n      break;\n    }\n    // case kpidIsSelfExe: prop = (_type == kType_EXECUTE); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic void AddName(AString &s, const char *name)\n{\n  char temp[kNameSize + 1];\n  memcpy(temp, name, kNameSize);\n  temp[kNameSize] = 0;\n  s += temp;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  CPropVariant prop;\n  const CSection &item = _sections[index];\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      AString s;\n      AddName(s, _segments[item.SegmentIndex].Name);\n      if (!item.IsDummy)\n      {\n        // CSection::SegName and CSegment::Name are same in real cases.\n        // AddName(s, item.SegName);\n        AddName(s, item.Name);\n      }\n      prop = MultiByteToUnicodeString(s);\n      break;\n    }\n    case kpidSize:  /* prop = (UInt64)item.VSize; break; */\n    case kpidPackSize:  prop = (UInt64)item.GetPackSize(); break;\n    case kpidCharacts:\n    {\n      AString res;\n      {\n        if (!item.IsDummy)\n        {\n          {\n            const AString s (TypeToString(g_SectTypes, Z7_ARRAY_SIZE(g_SectTypes), item.Flags & SECT_TYPE_MASK));\n            if (!s.IsEmpty())\n            {\n              res.Add_OptSpaced(\"sect_type:\");\n              res.Add_OptSpaced(s);\n            }\n          }\n          {\n            const AString s (FlagsToString(g_SectFlags, Z7_ARRAY_SIZE(g_SectFlags), item.Flags & SECT_ATTR_MASK));\n            if (!s.IsEmpty())\n            {\n              res.Add_OptSpaced(\"sect_flags:\");\n              res.Add_OptSpaced(s);\n            }\n          }\n        }\n        const CSegment &seg = _segments[item.SegmentIndex];\n        {\n          const AString s (FlagsToString(g_SegmentFlags, Z7_ARRAY_SIZE(g_SegmentFlags), seg.Flags));\n          if (!s.IsEmpty())\n          {\n            res.Add_OptSpaced(\"seg_flags:\");\n            res.Add_OptSpaced(s);\n          }\n        }\n        {\n          const AString s (FlagsToString(g_SegmentProt, Z7_ARRAY_SIZE(g_SegmentProt), seg.MaxProt));\n          if (!s.IsEmpty())\n          {\n            res.Add_OptSpaced(\"max_prot:\");\n            res.Add_OptSpaced(s);\n          }\n        }\n        {\n          const AString s (FlagsToString(g_SegmentProt, Z7_ARRAY_SIZE(g_SegmentProt), seg.InitProt));\n          if (!s.IsEmpty())\n          {\n            res.Add_OptSpaced(\"init_prot:\");\n            res.Add_OptSpaced(s);\n          }\n        }\n      }\n      if (!res.IsEmpty())\n        prop = res;\n      break;\n    }\n    case kpidOffset:  prop = item.Pa; break;\n    case kpidVa:  prop = item.Va; break;\n    case kpidClusterSize:  prop = (UInt32)1 << item.Align; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nHRESULT CHandler::Open2(ISequentialInStream *stream)\n{\n  const UInt32 kStartHeaderSize = 7 * 4;\n\n  Byte header[kStartHeaderSize];\n  RINOK(ReadStream_FALSE(stream, header, kStartHeaderSize))\n  bool be, mode64;\n  switch (GetUi32(header))\n  {\n    case 0xCEFAEDFE:  be = true; mode64 = false; break;\n    case 0xCFFAEDFE:  be = true; mode64 = true; break;\n    case 0xFEEDFACE:  be = false; mode64 = false; break;\n    case 0xFEEDFACF:  be = false; mode64 = true; break;\n    default: return S_FALSE;\n  }\n  \n  _mode64 = mode64;\n  _be = be;\n\n  const UInt32 numCommands = Get32(header + 0x10, be);\n  const UInt32 commandsSize = Get32(header + 0x14, be);\n\n  if (numCommands == 0)\n    return S_FALSE;\n\n  if (commandsSize > (1 << 24) ||\n      numCommands > (1 << 21) ||\n      numCommands * 8 > commandsSize)\n    return S_FALSE;\n\n  _cpuType = Get32(header + 4, be);\n  _cpuSubType = Get32(header + 8, be);\n  _type = Get32(header + 0xC, be);\n  _flags = Get32(header + 0x18, be);\n\n  /*\n  // Probably the sections are in first commands. So we can reduce the number of commands.\n  bool reduceCommands = false;\n  const UInt32 kNumReduceCommands = 16;\n  if (numCommands > kNumReduceCommands)\n  {\n    reduceCommands = true;\n    numCommands = kNumReduceCommands;\n  }\n  */\n\n  UInt32 startHeaderSize = kStartHeaderSize;\n  if (mode64)\n    startHeaderSize += 4;\n  _headersSize = startHeaderSize + commandsSize;\n  _totalSize = _headersSize;\n  CByteArr buffer(_headersSize);\n  RINOK(ReadStream_FALSE(stream, buffer + kStartHeaderSize, _headersSize - kStartHeaderSize))\n  const Byte *buf = buffer + startHeaderSize;\n  size_t size = _headersSize - startHeaderSize;\n  for (UInt32 cmdIndex = 0; cmdIndex < numCommands; cmdIndex++)\n  {\n    if (size < 8)\n      return S_FALSE;\n    UInt32 cmd = Get32(buf, be);\n    UInt32 cmdSize = Get32(buf + 4, be);\n    if (cmdSize < 8)\n      return S_FALSE;\n    if (size < cmdSize)\n      return S_FALSE;\n    if (cmd == CMD_SEGMENT_32 || cmd == CMD_SEGMENT_64)\n    {\n      UInt32 offs = (cmd == CMD_SEGMENT_64) ? 0x48 : 0x38;\n      if (cmdSize < offs)\n        break;\n\n      UInt64 vmAddr, vmSize, phAddr, phSize;\n\n      {\n        if (cmd == CMD_SEGMENT_64)\n        {\n          vmAddr = Get64(buf + 0x18, be);\n          vmSize = Get64(buf + 0x20, be);\n          phAddr = Get64(buf + 0x28, be);\n          phSize = Get64(buf + 0x30, be);\n        }\n        else\n        {\n          vmAddr = Get32(buf + 0x18, be);\n          vmSize = Get32(buf + 0x1C, be);\n          phAddr = Get32(buf + 0x20, be);\n          phSize = Get32(buf + 0x24, be);\n        }\n        {\n          UInt64 totalSize = phAddr + phSize;\n          if (totalSize < phAddr)\n            return S_FALSE;\n          if (_totalSize < totalSize)\n            _totalSize = totalSize;\n        }\n      }\n      \n      CSegment seg;\n      seg.MaxProt = Get32(buf + offs - 16, be);\n      seg.InitProt = Get32(buf + offs - 12, be);\n      seg.Flags = Get32(buf + offs - 4, be);\n      memcpy(seg.Name, buf + 8, kNameSize);\n      _segments.Add(seg);\n\n      UInt32 numSections = Get32(buf + offs - 8, be);\n      if (numSections > (1 << 8))\n        return S_FALSE;\n\n      if (numSections == 0)\n      {\n        CSection &sect = _sections.AddNew();\n        sect.IsDummy = true;\n        sect.SegmentIndex = _segments.Size() - 1;\n        sect.Va = vmAddr;\n        sect.PSize = phSize;\n        sect.VSize = vmSize;\n        sect.Pa = phAddr;\n        sect.Align = 0;\n        sect.Flags = 0;\n      }\n      else do\n      {\n        const UInt32 headSize = (cmd == CMD_SEGMENT_64) ? 0x50 : 0x44;\n        const Byte *p = buf + offs;\n        if (cmdSize - offs < headSize)\n          break;\n        CSection &sect = _sections.AddNew();\n        unsigned f32Offset;\n        if (cmd == CMD_SEGMENT_64)\n        {\n          sect.Va    = Get64(p + 0x20, be);\n          sect.VSize = Get64(p + 0x28, be);\n          f32Offset = 0x30;\n        }\n        else\n        {\n          sect.Va    = Get32(p + 0x20, be);\n          sect.VSize = Get32(p + 0x24, be);\n          f32Offset = 0x28;\n        }\n        sect.Pa    = Get32(p + f32Offset, be);\n        sect.Align = Get32(p + f32Offset + 4, be);\n        // sect.reloff = Get32(p + f32Offset + 8, be);\n        // sect.nreloc = Get32(p + f32Offset + 12, be);\n        sect.Flags = Get32(p + f32Offset + 16, be);\n        if ((sect.Flags & SECT_TYPE_MASK) == SECT_ATTR_ZEROFILL)\n          sect.PSize = 0;\n        else\n          sect.PSize = sect.VSize;\n        memcpy(sect.Name, p, kNameSize);\n        // memcpy(sect.SegName, p + kNameSize, kNameSize);\n        sect.SegmentIndex = _segments.Size() - 1;\n        offs += headSize;\n      }\n      while (--numSections);\n\n      if (offs != cmdSize)\n        return S_FALSE;\n    }\n    buf += cmdSize;\n    size -= cmdSize;\n  }\n  // return (reduceCommands || (size == 0)) ? S_OK : S_FALSE;\n  if (size != 0)\n    return S_FALSE;\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(inStream))\n  if (!_allowTail)\n  {\n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(inStream, fileSize))\n    if (fileSize > _totalSize)\n      return S_FALSE;\n  }\n  _inStream = inStream;\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalSize = 0;\n  _inStream.Release();\n  _sections.Clear();\n  _segments.Clear();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _sections.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _sections.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _sections[allFilesMode ? i : indices[i]].GetPackSize();\n  extractCallback->SetTotal(totalSize);\n\n  UInt64 currentTotalSize = 0;\n  UInt64 currentItemSize;\n  \n  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\n  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\n  CMyComPtr<ISequentialInStream> inStream(streamSpec);\n  streamSpec->SetStream(_inStream);\n\n  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)\n  {\n    lps->InSize = lps->OutSize = currentTotalSize;\n    RINOK(lps->SetCur())\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CSection &item = _sections[index];\n    currentItemSize = item.GetPackSize();\n\n    CMyComPtr<ISequentialOutStream> outStream;\n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n    if (!testMode && !outStream)\n      continue;\n    \n    RINOK(extractCallback->PrepareOperation(askMode))\n    RINOK(InStream_SeekSet(_inStream, item.Pa))\n    streamSpec->Init(currentItemSize);\n    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))\n    outStream.Release();\n    RINOK(extractCallback->SetOperationResult(copyCoderSpec->TotalSize == currentItemSize ?\n        NExtract::NOperationResult::kOK:\n        NExtract::NOperationResult::kDataError))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail))\n{\n  _allowTail = IntToBool(allowTail);\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = {\n  4, 0xCE, 0xFA, 0xED, 0xFE,\n  4, 0xCF, 0xFA, 0xED, 0xFE,\n  4, 0xFE, 0xED, 0xFA, 0xCE,\n  4, 0xFE, 0xED, 0xFA, 0xCF };\n\nREGISTER_ARC_I(\n  \"MachO\", \"macho\", NULL, 0xDF,\n  k_Signature,\n  0,\n  NArcInfoFlags::kMultiSignature |\n  NArcInfoFlags::kPreArc,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/MbrHandler.cpp",
    "content": "﻿// MbrHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\nusing namespace NWindows;\n\nnamespace NArchive {\n\nnamespace NFat {\nAPI_FUNC_IsArc IsArc_Fat(const Byte *p, size_t size);\n}\n\nnamespace NMbr {\n\nstruct CChs\n{\n  Byte Head;\n  Byte SectCyl;\n  Byte Cyl8;\n  \n  UInt32 GetSector() const { return SectCyl & 0x3F; }\n  UInt32 GetCyl() const { return ((UInt32)SectCyl >> 6 << 8) | Cyl8; }\n  void ToString(NCOM::CPropVariant &prop) const;\n\n  void Parse(const Byte *p)\n  {\n    Head = p[0];\n    SectCyl = p[1];\n    Cyl8 = p[2];\n  }\n  bool Check() const { return GetSector() > 0; }\n};\n\n\n// Chs in some MBRs contains only low bits of \"Cyl number\". So we disable check.\n/*\n#define RINOZ(x) { int _t_ = (x); if (_t_ != 0) return _t_; }\nstatic int CompareChs(const CChs &c1, const CChs &c2)\n{\n  RINOZ(MyCompare(c1.GetCyl(), c2.GetCyl()));\n  RINOZ(MyCompare(c1.Head, c2.Head));\n  return MyCompare(c1.GetSector(), c2.GetSector());\n}\n*/\n\nvoid CChs::ToString(NCOM::CPropVariant &prop) const\n{\n  AString s;\n  s.Add_UInt32(GetCyl());\n  s.Add_Minus();\n  s.Add_UInt32(Head);\n  s.Add_Minus();\n  s.Add_UInt32(GetSector());\n  prop = s;\n}\n\nstruct CPartition\n{\n  Byte Status;\n  CChs BeginChs;\n  Byte Type;\n  CChs EndChs;\n  UInt32 Lba;\n  UInt32 NumBlocks;\n\n  CPartition() { memset (this, 0, sizeof(*this)); }\n  \n  bool IsEmpty() const { return Type == 0; }\n  bool IsExtended() const { return Type == 5 || Type == 0xF; }\n  UInt32 GetLimit() const { return Lba + NumBlocks; }\n  // bool IsActive() const { return Status == 0x80; }\n  UInt64 GetPos(unsigned sectorSizeLog) const { return (UInt64)Lba << sectorSizeLog; }\n  UInt64 GetSize(unsigned sectorSizeLog) const { return (UInt64)NumBlocks << sectorSizeLog; }\n\n  bool CheckLbaLimits() const { return (UInt32)0xFFFFFFFF - Lba >= NumBlocks; }\n  bool Parse(const Byte *p)\n  {\n    Status = p[0];\n    BeginChs.Parse(p + 1);\n    Type = p[4];\n    EndChs.Parse(p + 5);\n    Lba = GetUi32(p + 8);\n    NumBlocks = GetUi32(p + 12);\n    if (Type == 0)\n      return true;\n    if (Status != 0 && Status != 0x80)\n      return false;\n    return BeginChs.Check()\n       && EndChs.Check()\n       // && CompareChs(BeginChs, EndChs) <= 0\n       && NumBlocks > 0\n       && CheckLbaLimits();\n  }\n\n  #ifdef SHOW_DEBUG_INFO\n  void Print() const\n  {\n    NCOM::CPropVariant prop, prop2;\n    BeginChs.ToString(prop);\n    EndChs.ToString(prop2);\n    printf(\"   %2x %2x %8X %8X %12S %12S\", (int)Status, (int)Type, Lba, NumBlocks, prop.bstrVal, prop2.bstrVal);\n  }\n  #endif\n};\n\nstruct CPartType\n{\n  UInt32 Id;\n  const char *Ext;\n  const char *Name;\n};\n\n#define kFat \"fat\"\n\n/*\nif we use \"format\" command in Windows 10 for existing partition:\n  - if we format to ExFAT, it sets type=7\n  - if we format to UDF, it doesn't change type from previous value.\n*/\n  \nstatic const unsigned kType_Windows_NTFS = 7;\n\nstatic const CPartType kPartTypes[] =\n{\n  { 0x01, kFat, \"FAT12\" },\n  { 0x04, kFat, \"FAT16 DOS 3.0+\" },\n  { 0x05, NULL, \"Extended\" },\n  { 0x06, kFat, \"FAT16 DOS 3.31+\" },\n  { 0x07, \"ntfs\", \"NTFS\" },\n  { 0x0B, kFat, \"FAT32\" },\n  { 0x0C, kFat, \"FAT32-LBA\" },\n  { 0x0E, kFat, \"FAT16-LBA\" },\n  { 0x0F, NULL, \"Extended-LBA\" },\n  { 0x11, kFat, \"FAT12-Hidden\" },\n  { 0x14, kFat, \"FAT16-Hidden < 32 MB\" },\n  { 0x16, kFat, \"FAT16-Hidden >= 32 MB\" },\n  { 0x1B, kFat, \"FAT32-Hidden\" },\n  { 0x1C, kFat, \"FAT32-LBA-Hidden\" },\n  { 0x1E, kFat, \"FAT16-LBA-WIN95-Hidden\" },\n  { 0x27, \"ntfs\", \"NTFS-WinRE\" },\n  { 0x82, NULL, \"Solaris x86 / Linux swap\" },\n  { 0x83, NULL, \"Linux\" },\n  { 0x8E, \"lvm\", \"Linux LVM\" },\n  { 0xA5, NULL, \"BSD slice\" },\n  { 0xBE, NULL, \"Solaris 8 boot\" },\n  { 0xBF, NULL, \"New Solaris x86\" },\n  { 0xC2, NULL, \"Linux-Hidden\" },\n  { 0xC3, NULL, \"Linux swap-Hidden\" },\n  { 0xEE, NULL, \"GPT\" },\n  { 0xEE, NULL, \"EFI\" }\n};\n\nstatic int FindPartType(UInt32 type)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(kPartTypes); i++)\n    if (kPartTypes[i].Id == type)\n      return (int)i;\n  return -1;\n}\n\nstruct CItem\n{\n  bool IsReal;\n  bool IsPrim;\n  bool WasParsed;\n  const char *FileSystem;\n  UInt64 Size;\n  CPartition Part;\n\n  CItem():\n      WasParsed(false),\n      FileSystem(NULL)\n      {}\n};\n\n\nZ7_class_CHandler_final: public CHandlerCont\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Cont)\n\n  CObjectVector<CItem> _items;\n  UInt64 _totalSize;\n  CByteBuffer _buffer;\n\n  UInt32 _signature;\n  unsigned _sectorSizeLog;\n\n  virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override Z7_final\n  {\n    const CItem &item = _items[index];\n    pos = item.Part.GetPos(_sectorSizeLog);\n    size = item.Size;\n    return NExtract::NOperationResult::kOK;\n  }\n\n  HRESULT ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level);\n};\n\n/*\nstatic bool IsEmptyBuffer(const Byte *data, size_t size)\n{\n  for (unsigned i = 0; i < size; i++)\n    if (data[i] != 0)\n      return false;\n  return true;\n}\n*/\n\nconst char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize);\n\nHRESULT CHandler::ReadTables(IInStream *stream, UInt32 baseLba, UInt32 lba, unsigned level)\n{\n  if (level >= 128 || _items.Size() >= 128)\n    return S_FALSE;\n\n  const unsigned kNumHeaderParts = 4;\n  CPartition parts[kNumHeaderParts];\n\n  if (level == 0)\n    _sectorSizeLog = 9;\n  const UInt32 kSectorSize = (UInt32)1 << _sectorSizeLog;\n  UInt32 bufSize  = kSectorSize;\n  if (level == 0 && _totalSize >= (1 << 12))\n    bufSize = (1 << 12);\n  _buffer.Alloc(bufSize);\n  {\n    Byte *buf = _buffer;\n    const UInt64 newPos = (UInt64)lba << _sectorSizeLog;\n    if (newPos + bufSize > _totalSize)\n      return S_FALSE;\n    RINOK(InStream_SeekSet(stream, newPos))\n    RINOK(ReadStream_FALSE(stream, buf, bufSize))\n    if (buf[0x1FE] != 0x55 || buf[0x1FF] != 0xAA)\n      return S_FALSE;\n    if (level == 0)\n      _signature = GetUi32(buf + 0x1B8);\n    for (unsigned i = 0; i < kNumHeaderParts; i++)\n      if (!parts[i].Parse(buf + 0x1BE + 16 * i))\n        return S_FALSE;\n  }\n\n  // 23.02: now we try to detect 4kn format (4 KB sectors case)\n  if (level == 0)\n  // if (_totalSize >= (1 << 28)) // we don't expect small images with 4 KB sectors\n  if (bufSize >= (1 << 12))\n  {\n    UInt32 lastLim = 0;\n    UInt32 firstLba = 0;\n    UInt32 numBlocks = 0; // in first partition\n    for (unsigned i = 0; i < kNumHeaderParts; i++)\n    {\n      const CPartition &part = parts[i];\n      if (part.IsEmpty())\n        continue;\n      if (firstLba == 0 && part.NumBlocks != 0)\n      {\n        firstLba = part.Lba;\n        numBlocks = part.NumBlocks;\n      }\n      const UInt32 newLim = part.GetLimit();\n      if (newLim < lastLim)\n        return S_FALSE;\n      lastLim = newLim;\n    }\n    if (lastLim != 0)\n    {\n      const UInt64 lim12 = (UInt64)lastLim << 12;\n      if (lim12 <= _totalSize\n          // && _totalSize - lim12 < (1 << 28) // we can try to exclude false positive cases\n          )\n      // if (IsEmptyBuffer(&_buffer[(1 << 9)], (1 << 12) - (1 << 9)))\n      if (InStream_SeekSet(stream, (UInt64)firstLba << 12) == S_OK)\n      if (GetFileSystem(stream, (UInt64)numBlocks << 12))\n        _sectorSizeLog = 12;\n    }\n  }\n\n  PRF(printf(\"\\n# %8X\", lba));\n\n  UInt32 limLba = lba + 1;\n  if (limLba == 0)\n    return S_FALSE;\n\n  for (unsigned i = 0; i < kNumHeaderParts; i++)\n  {\n    CPartition &part = parts[i];\n    \n    if (part.IsEmpty())\n      continue;\n    PRF(printf(\"\\n   %2d \", (unsigned)level));\n    #ifdef SHOW_DEBUG_INFO\n    part.Print();\n    #endif\n    \n    unsigned numItems = _items.Size();\n    UInt32 newLba = lba + part.Lba;\n    \n    if (part.IsExtended())\n    {\n      // if (part.Type == 5) // Check it!\n      newLba = baseLba + part.Lba;\n      if (newLba < limLba)\n        return S_FALSE;\n      const HRESULT res = ReadTables(stream, level < 1 ? newLba : baseLba, newLba, level + 1);\n      if (res != S_FALSE && res != S_OK)\n        return res;\n    }\n    if (newLba < limLba)\n      return S_FALSE;\n    part.Lba = newLba;\n    if (!part.CheckLbaLimits())\n      return S_FALSE;\n\n    CItem n;\n    n.Part = part;\n    bool addItem = false;\n    if (numItems == _items.Size())\n    {\n      n.IsPrim = (level == 0);\n      n.IsReal = true;\n      addItem = true;\n    }\n    else\n    {\n      const CItem &back = _items.Back();\n      const UInt32 backLimit = back.Part.GetLimit();\n      const UInt32 partLimit = part.GetLimit();\n      if (backLimit < partLimit)\n      {\n        n.IsReal = false;\n        n.Part.Lba = backLimit;\n        n.Part.NumBlocks = partLimit - backLimit;\n        addItem = true;\n      }\n    }\n    if (addItem)\n    {\n      if (n.Part.GetLimit() < limLba)\n        return S_FALSE;\n      limLba = n.Part.GetLimit();\n      n.Size = n.Part.GetSize(_sectorSizeLog);\n      _items.Add(n);\n    }\n  }\n  return S_OK;\n}\n\n\nstatic const Byte k_Ntfs_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };\n\nstatic bool Is_Ntfs(const Byte *p)\n{\n  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)\n    return false;\n  switch (p[0])\n  {\n    case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break;\n    case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break;\n    default: return false;\n  }\n  return memcmp(p + 3, k_Ntfs_Signature, Z7_ARRAY_SIZE(k_Ntfs_Signature)) == 0;\n}\n\nstatic const Byte k_ExFat_Signature[] = { 'E', 'X', 'F', 'A', 'T', ' ', ' ', ' ' };\n\nstatic bool Is_ExFat(const Byte *p)\n{\n  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)\n    return false;\n  if (p[0] != 0xEB || p[1] != 0x76 || p[2] != 0x90)\n    return false;\n  return memcmp(p + 3, k_ExFat_Signature, Z7_ARRAY_SIZE(k_ExFat_Signature)) == 0;\n}\n\nstatic bool AllAreZeros(const Byte *p, size_t size)\n{\n  for (size_t i = 0; i < size; i++)\n    if (p[i] != 0)\n      return false;\n  return true;\n}\n\nstatic const UInt32 k_Udf_StartPos = 0x8000;\nstatic const Byte k_Udf_Signature[] = { 0, 'B', 'E', 'A', '0', '1', 1, 0 };\n\nstatic bool Is_Udf(const Byte *p)\n{\n  return memcmp(p + k_Udf_StartPos, k_Udf_Signature, sizeof(k_Udf_Signature)) == 0;\n}\n\n\nconst char *GetFileSystem(ISequentialInStream *stream, UInt64 partitionSize)\n{\n  const size_t kHeaderSize = 1 << 9;\n  if (partitionSize >= kHeaderSize)\n  {\n    Byte buf[kHeaderSize];\n    if (ReadStream_FAIL(stream, buf, kHeaderSize) == S_OK)\n    {\n      // NTFS is expected default filesystem for (Type == 7)\n      if (Is_Ntfs(buf))\n        return \"NTFS\";\n      if (Is_ExFat(buf))\n        return \"exFAT\";\n      if (NFat::IsArc_Fat(buf, kHeaderSize))\n        return \"FAT\";\n      const size_t kHeaderSize2 = k_Udf_StartPos + (1 << 9);\n      if (partitionSize >= kHeaderSize2)\n      {\n        if (AllAreZeros(buf, kHeaderSize))\n        {\n          CByteBuffer buffer(kHeaderSize2);\n          // memcpy(buffer, buf, kHeaderSize);\n          if (ReadStream_FAIL(stream, buffer + kHeaderSize, kHeaderSize2 - kHeaderSize) == S_OK)\n            if (Is_Udf(buffer))\n              return \"UDF\";\n        }\n      }\n    }\n  }\n  return NULL;\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(InStream_GetSize_SeekToEnd(stream, _totalSize))\n  RINOK(ReadTables(stream, 0, 0, 0))\n  if (_items.IsEmpty())\n    return S_FALSE;\n  {\n    const UInt32 lbaLimit = _items.Back().Part.GetLimit();\n    const UInt64 lim = (UInt64)lbaLimit << _sectorSizeLog;\n    if (lim < _totalSize)\n    {\n      CItem n;\n      n.Part.Lba = lbaLimit;\n      n.Size = _totalSize - lim;\n      n.IsReal = false;\n      _items.Add(n);\n    }\n  }\n\n  FOR_VECTOR (i, _items)\n  {\n    CItem &item = _items[i];\n    if (item.Part.Type != kType_Windows_NTFS)\n      continue;\n    if (InStream_SeekSet(stream, item.Part.GetPos(_sectorSizeLog)) != S_OK)\n      continue;\n    item.FileSystem = GetFileSystem(stream, item.Size);\n    item.WasParsed = true;\n  }\n\n  _stream = stream;\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalSize = 0;\n  _items.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\n\nenum\n{\n  kpidPrimary = kpidUserDefined,\n  kpidBegChs,\n  kpidEndChs\n};\n\nstatic const CStatProp kProps[] =\n{\n  { NULL, kpidPath, VT_BSTR},\n  { NULL, kpidSize, VT_UI8},\n  { NULL, kpidFileSystem, VT_BSTR},\n  { NULL, kpidOffset, VT_UI8},\n  { \"Primary\", kpidPrimary, VT_BOOL},\n  { \"Begin CHS\", kpidBegChs, VT_BSTR},\n  { \"End CHS\", kpidEndChs, VT_BSTR}\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidSectorSize,\n  kpidId\n};\n\nIMP_IInArchive_Props_WITH_NAME\nIMP_IInArchive_ArcProps\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile:\n    {\n      int mainIndex = -1;\n      FOR_VECTOR (i, _items)\n        if (_items[i].IsReal)\n        {\n          if (mainIndex >= 0)\n          {\n            mainIndex = -1;\n            break;\n          }\n          mainIndex = (int)i;\n        }\n      if (mainIndex >= 0)\n        prop = (UInt32)(Int32)mainIndex;\n      break;\n    }\n    case kpidPhySize: prop = _totalSize; break;\n    case kpidSectorSize: prop = (UInt32)((UInt32)1 << _sectorSizeLog); break;\n    case kpidId: prop = _signature; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CItem &item = _items[index];\n  const CPartition &part = item.Part;\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      AString s;\n      s.Add_UInt32(index);\n      if (item.IsReal)\n      {\n        s.Add_Dot();\n        const char *ext = NULL;\n        if (item.FileSystem)\n        {\n          ext = \"\";\n          AString fs (item.FileSystem);\n          fs.MakeLower_Ascii();\n          s += fs;\n        }\n        else if (!item.WasParsed)\n        {\n          const int typeIndex = FindPartType(part.Type);\n          if (typeIndex >= 0)\n            ext = kPartTypes[(unsigned)typeIndex].Ext;\n        }\n        if (!ext)\n          ext = \"img\";\n        s += ext;\n      }\n      prop = s;\n      break;\n    }\n    case kpidFileSystem:\n      if (item.IsReal)\n      {\n        char s[32];\n        ConvertUInt32ToString(part.Type, s);\n        const char *res = s;\n        if (item.FileSystem)\n        {\n          // strcat(s, \"-\");\n          // strcpy(s, item.FileSystem);\n          res = item.FileSystem;\n        }\n        else if (!item.WasParsed)\n        {\n          const int typeIndex = FindPartType(part.Type);\n          if (typeIndex >= 0 && kPartTypes[(unsigned)typeIndex].Name)\n            res = kPartTypes[(unsigned)typeIndex].Name;\n        }\n        prop = res;\n      }\n      break;\n    case kpidSize:\n    case kpidPackSize: prop = item.Size; break;\n    case kpidOffset: prop = part.GetPos(_sectorSizeLog); break;\n    case kpidPrimary: if (item.IsReal) prop = item.IsPrim; break;\n    case kpidBegChs: if (item.IsReal) part.BeginChs.ToString(prop); break;\n    case kpidEndChs: if (item.IsReal) part.EndChs.ToString(prop); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\n  // 3, { 1, 1, 0 },\n  // 2, { 0x55, 0x1FF },\n\nREGISTER_ARC_I_NO_SIG(\n  \"MBR\", \"mbr\", NULL, 0xDB,\n  0,\n  NArcInfoFlags::kPureStartOpen,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/MslzHandler.cpp",
    "content": "﻿// MslzHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/InBuffer.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"Common/DummyOutStream.h\"\n\nnamespace NArchive {\nnamespace NMslz {\n\nstatic const UInt32 kUnpackSizeMax = 0xFFFFFFE0;\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IArchiveOpenSeq\n)\n  CMyComPtr<IInStream> _inStream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  bool _isArc;\n  bool _needSeekToStart;\n  bool _dataAfterEnd;\n  bool _needMoreInput;\n\n  bool _packSize_Defined;\n  bool _unpackSize_Defined;\n\n  UInt32 _unpackSize;\n  UInt64 _packSize;\n  UInt64 _originalFileSize;\n  UString _name;\n\n  void ParseName(Byte replaceByte, IArchiveOpenCallback *callback);\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidExtension: prop = \"mslz\"; break;\n    case kpidIsNotArcType: prop = true; break;\n    case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_needMoreInput) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_dataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;\n      prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPath: if (!_name.IsEmpty()) prop = _name; break;\n    case kpidSize: if (_unpackSize_Defined || _inStream) prop = _unpackSize; break;\n    case kpidPackSize: if (_packSize_Defined || _inStream) prop = _packSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic const unsigned kSignatureSize = 9;\nstatic const unsigned kHeaderSize = kSignatureSize + 1 + 4;\n#define MSLZ_SIGNATURE { 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33, 0x41 }\n// old signature: 53 5A 20 88 F0 27 33\nstatic const Byte kSignature[kSignatureSize] = MSLZ_SIGNATURE;\n\n// we support only 3 chars strings here\nstatic const char * const g_Exts[] =\n{\n    \"bin\"\n  , \"dll\"\n  , \"exe\"\n  , \"kmd\"\n  , \"pdf\"\n  , \"sys\"\n};\n\nvoid CHandler::ParseName(Byte replaceByte, IArchiveOpenCallback *callback)\n{\n  if (!callback)\n    return;\n  Z7_DECL_CMyComPtr_QI_FROM(IArchiveOpenVolumeCallback, volumeCallback, callback)\n  if (!volumeCallback)\n    return;\n\n  NWindows::NCOM::CPropVariant prop;\n  if (volumeCallback->GetProperty(kpidName, &prop) != S_OK || prop.vt != VT_BSTR)\n    return;\n\n  UString s = prop.bstrVal;\n  if (s.IsEmpty() ||\n      s.Back() != L'_')\n    return;\n  \n  s.DeleteBack();\n  _name = s;\n   \n  if (replaceByte == 0)\n  {\n    if (s.Len() < 3 || s[s.Len() - 3] != '.')\n      return;\n    for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_Exts); i++)\n    {\n      const char *ext = g_Exts[i];\n      if (s[s.Len() - 2] == (Byte)ext[0] &&\n          s[s.Len() - 1] == (Byte)ext[1])\n      {\n        replaceByte = (Byte)ext[2];\n        break;\n      }\n    }\n  }\n  \n  if (replaceByte >= 0x20 && replaceByte < 0x80)\n    _name.Add_Char((char)replaceByte);\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    _needSeekToStart = true;\n    Byte buffer[kHeaderSize];\n    RINOK(ReadStream_FALSE(stream, buffer, kHeaderSize))\n    if (memcmp(buffer, kSignature, kSignatureSize) != 0)\n      return S_FALSE;\n    _unpackSize = GetUi32(buffer + 10);\n    if (_unpackSize > kUnpackSizeMax)\n      return S_FALSE;\n    RINOK(InStream_GetSize_SeekToEnd(stream, _originalFileSize))\n    _packSize = _originalFileSize;\n\n    ParseName(buffer[kSignatureSize], callback);\n\n    _isArc = true;\n    _unpackSize_Defined = true;\n    _inStream = stream;\n    _seqStream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _originalFileSize = 0;\n  _packSize = 0;\n  _unpackSize = 0;\n\n  _isArc = false;\n  _needSeekToStart = false;\n  _dataAfterEnd = false;\n  _needMoreInput = false;\n\n  _packSize_Defined = false;\n  _unpackSize_Defined =  false;\n\n  _seqStream.Release();\n  _inStream.Release();\n  _name.Empty();\n  return S_OK;\n}\n\n// MslzDec is modified LZSS algorithm of Haruhiko Okumura:\n//   maxLen = 18; Okumura\n//   maxLen = 16; MS\n\n#define PROGRESS_AND_WRITE \\\n  if ((dest & kMask) == 0) { if (outStream) RINOK(WriteStream(outStream, buf, kBufSize)); \\\n    if ((dest & ((1 << 20) - 1)) == 0) \\\n    if (progress) \\\n      { UInt64 inSize = inStream.GetProcessedSize(); UInt64 outSize = dest; \\\n        RINOK(progress->SetRatioInfo(&inSize, &outSize)); }}\n\nstatic HRESULT MslzDec(CInBuffer &inStream, ISequentialOutStream *outStream, UInt32 unpackSize, bool &needMoreData, ICompressProgressInfo *progress)\n{\n  const unsigned kBufSize = (1 << 12);\n  const unsigned kMask = kBufSize - 1;\n  Byte buf[kBufSize];\n  UInt32 dest = 0;\n  memset(buf, ' ', kBufSize);\n  \n  while (dest < unpackSize)\n  {\n    Byte b;\n    if (!inStream.ReadByte(b))\n    {\n      needMoreData = true;\n      return S_FALSE;\n    }\n    \n    for (unsigned mask = (unsigned)b | 0x100; mask > 1 && dest < unpackSize; mask >>= 1)\n    {\n      if (!inStream.ReadByte(b))\n      {\n        needMoreData = true;\n        return S_FALSE;\n      }\n  \n      if (mask & 1)\n      {\n        buf[dest++ & kMask] = b;\n        PROGRESS_AND_WRITE\n      }\n      else\n      {\n        Byte b1;\n        if (!inStream.ReadByte(b1))\n        {\n          needMoreData = true;\n          return S_FALSE;\n        }\n        const unsigned kMaxLen = 16; // 18 in Okumura's code.\n        unsigned src = (((((unsigned)b1 & 0xF0) << 4) | b) + kMaxLen) & kMask;\n        unsigned len = (b1 & 0xF) + 3;\n        if (len > kMaxLen || dest + len > unpackSize)\n          return S_FALSE;\n    \n        do\n        {\n          buf[dest++ & kMask] = buf[src++ & kMask];\n          PROGRESS_AND_WRITE\n        }\n        while (--len != 0);\n      }\n    }\n  }\n  \n  if (outStream)\n    RINOK(WriteStream(outStream, buf, dest & kMask))\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  COM_TRY_BEGIN\n  Close();\n  _isArc = true;\n  _seqStream = stream;\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  // RINOK(extractCallback->SetTotal(_unpackSize))\n  Int32 opRes;\n  {\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;\n  outStream->SetStream(realOutStream);\n  outStream->Init();\n  // realOutStream.Release();\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  if (_needSeekToStart)\n  {\n    if (!_inStream)\n      return E_FAIL;\n    RINOK(InStream_SeekToBegin(_inStream))\n  }\n  else\n    _needSeekToStart = true;\n\n  opRes = NExtract::NOperationResult::kDataError;\n\n  bool isArc = false;\n  bool needMoreInput = false;\n  try\n  {\n    CInBuffer s;\n    if (!s.Create(1 << 20))\n      return E_OUTOFMEMORY;\n    s.SetStream(_seqStream);\n    s.Init();\n    \n    Byte buffer[kHeaderSize];\n    if (s.ReadBytes(buffer, kHeaderSize) == kHeaderSize)\n    {\n      UInt32 unpackSize;\n      if (memcmp(buffer, kSignature, kSignatureSize) == 0)\n      {\n        unpackSize = GetUi32(buffer + 10);\n        if (unpackSize <= kUnpackSizeMax)\n        {\n          const HRESULT result = MslzDec(s, outStream, unpackSize, needMoreInput, lps);\n          if (result == S_OK)\n            opRes = NExtract::NOperationResult::kOK;\n          else if (result != S_FALSE)\n            return result;\n          _unpackSize = unpackSize;\n          _unpackSize_Defined = true;\n\n          _packSize = s.GetProcessedSize();\n          _packSize_Defined = true;\n\n          if (_inStream && _packSize < _originalFileSize)\n            _dataAfterEnd = true;\n          \n          isArc = true;\n        }\n      }\n    }\n  }\n  catch (CInBufferException &e) { return e.ErrorCode; }\n\n  _isArc = isArc;\n  if (isArc)\n    _needMoreInput = needMoreInput;\n  if (!_isArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (_needMoreInput)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (_dataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  }\n  return extractCallback->SetOperationResult(opRes);\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"MsLZ\", \"mslz\", NULL, 0xD5,\n  kSignature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/MubHandler.cpp",
    "content": "﻿// MubHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/SwapBytes.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\nusing namespace NWindows;\nusing namespace NCOM;\n\nnamespace NArchive {\nnamespace NMub {\n\n#define MACH_CPU_ARCH_ABI64 ((UInt32)1 << 24)\n#define MACH_CPU_TYPE_386    7\n#define MACH_CPU_TYPE_ARM   12\n#define MACH_CPU_TYPE_SPARC 14\n#define MACH_CPU_TYPE_PPC   18\n\n#define MACH_CPU_TYPE_PPC64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_PPC)\n#define MACH_CPU_TYPE_AMD64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_386)\n#define MACH_CPU_TYPE_ARM64 (MACH_CPU_ARCH_ABI64 | MACH_CPU_TYPE_ARM)\n\n#define MACH_CPU_SUBTYPE_LIB64 ((UInt32)1 << 31)\n\n#define MACH_CPU_SUBTYPE_I386_ALL 3\n\nstruct CItem\n{\n  UInt32 Type;\n  UInt32 SubType;\n  UInt32 Offset;\n  UInt32 Size;\n  UInt32 Align;\n};\n\nstatic const UInt32 kNumFilesMax = 6;\n\nZ7_class_CHandler_final: public CHandlerCont\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Cont)\n\n  // UInt64 _startPos;\n  UInt64 _phySize;\n  UInt32 _numItems;\n  bool _bigEndian;\n  CItem _items[kNumFilesMax];\n\n  HRESULT Open2(IInStream *stream);\n\n  virtual int GetItem_ExtractInfo(UInt32 index, UInt64 &pos, UInt64 &size) const Z7_override\n  {\n    const CItem &item = _items[index];\n    pos = item.Offset;\n    size = item.Size;\n    return NExtract::NOperationResult::kOK;\n  }\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidBigEndian\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidOffset,\n  kpidClusterSize // Align\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  PropVariant_Clear(value);\n  switch (propID)\n  {\n    case kpidBigEndian: PropVarEm_Set_Bool(value, _bigEndian); break;\n    case kpidPhySize: PropVarEm_Set_UInt64(value, _phySize); break;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  PropVariant_Clear(value);\n  const CItem &item = _items[index];\n  switch (propID)\n  {\n    case kpidExtension:\n    {\n      char temp[32];\n      const char *ext = NULL;\n      switch (item.Type)\n      {\n        case MACH_CPU_TYPE_386:   ext = \"x86\";   break;\n        case MACH_CPU_TYPE_ARM:   ext = \"arm\";   break;\n        case MACH_CPU_TYPE_SPARC: ext = \"sparc\"; break;\n        case MACH_CPU_TYPE_PPC:   ext = \"ppc\";   break;\n        case MACH_CPU_TYPE_AMD64: ext = \"x64\";   break;\n        case MACH_CPU_TYPE_ARM64: ext = \"arm64\"; break;\n        case MACH_CPU_TYPE_PPC64: ext = \"ppc64\"; break;\n        default:\n          temp[0] = 'c';\n          temp[1] = 'p';\n          temp[2] = 'u';\n          char *p = ConvertUInt32ToString(item.Type & ~MACH_CPU_ARCH_ABI64, temp + 3);\n          if (item.Type & MACH_CPU_ARCH_ABI64)\n            MyStringCopy(p, \"_64\");\n          break;\n      }\n      if (ext)\n        MyStringCopy(temp, ext);\n      if (item.SubType != 0)\n      if ((item.Type != MACH_CPU_TYPE_386 &&\n           item.Type != MACH_CPU_TYPE_AMD64)\n           || (item.SubType & ~(UInt32)MACH_CPU_SUBTYPE_LIB64) != MACH_CPU_SUBTYPE_I386_ALL\n         )\n      {\n        unsigned pos = MyStringLen(temp);\n        temp[pos++] = '-';\n        ConvertUInt32ToString(item.SubType, temp + pos);\n      }\n      return PropVarEm_Set_Str(value, temp);\n    }\n    case kpidSize:\n    case kpidPackSize:\n      PropVarEm_Set_UInt64(value, item.Size);\n      break;\n    case kpidOffset:\n      PropVarEm_Set_UInt64(value, item.Offset);\n      break;\n    case kpidClusterSize:\n      PropVarEm_Set_UInt32(value, (UInt32)1 << item.Align);\n      break;\n  }\n  return S_OK;\n}\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  // RINOK(InStream_GetPos(stream, _startPos));\n\n  const UInt32 kHeaderSize = 2;\n  const UInt32 kRecordSize = 5;\n  const UInt32 kBufSize = kHeaderSize + kNumFilesMax * kRecordSize;\n  UInt32 buf[kBufSize];\n  size_t processed = kBufSize * 4;\n  RINOK(ReadStream(stream, buf, &processed))\n  processed >>= 2;\n  if (processed < kHeaderSize)\n    return S_FALSE;\n  \n  bool be;\n  switch (buf[0])\n  {\n    case Z7_CONV_BE_TO_NATIVE_CONST32(0xCAFEBABE): be = true; break;\n    case Z7_CONV_BE_TO_NATIVE_CONST32(0xB9FAF10E): be = false; break;\n    default: return S_FALSE;\n  }\n  _bigEndian = be;\n  if (\n      #if defined(MY_CPU_BE)\n        !\n      #endif\n        be)\n    z7_SwapBytes4(&buf[1], processed - 1);\n  const UInt32 num = buf[1];\n  if (num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)\n    return S_FALSE;\n  if (num == 0)\n    return S_FALSE;\n  UInt64 endPosMax = kHeaderSize;\n\n  for (UInt32 i = 0; i < num; i++)\n  {\n    const UInt32 *p = buf + kHeaderSize + i * kRecordSize;\n    CItem &sb = _items[i];\n    sb.Type = p[0];\n    sb.SubType = p[1];\n    sb.Offset = p[2];\n    sb.Size = p[3];\n    const UInt32 align = p[4];\n    sb.Align = align;\n    if (align > 31)\n      return S_FALSE;\n    if (sb.Offset < kHeaderSize + num * kRecordSize)\n      return S_FALSE;\n    if ((sb.Type & ~MACH_CPU_ARCH_ABI64) >= 0x100 ||\n        (sb.SubType & ~MACH_CPU_SUBTYPE_LIB64) >= 0x100)\n      return S_FALSE;\n\n    const UInt64 endPos = (UInt64)sb.Offset + sb.Size;\n    if (endPosMax < endPos)\n      endPosMax = endPos;\n  }\n  _numItems = num;\n  _phySize = endPosMax;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  try\n  {\n    if (Open2(inStream) != S_OK)\n      return S_FALSE;\n    _stream = inStream;\n  }\n  catch(...) { return S_FALSE; }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _stream.Release();\n  _numItems = 0;\n  _phySize = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _numItems;\n  return S_OK;\n}\n\nnamespace NBe {\n\nstatic const Byte k_Signature[] = {\n    7, 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0,\n    4, 0xB9, 0xFA, 0xF1, 0x0E };\n\nREGISTER_ARC_I(\n  \"Mub\", \"mub\", NULL, 0xE2,\n  k_Signature,\n  0,\n  NArcInfoFlags::kMultiSignature,\n  NULL)\n\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/NsisDecode.cpp",
    "content": "﻿// NsisDecode.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"NsisDecode.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/MethodId.h\"\n\n#include \"../../Compress/BcjCoder.h\"\n\n#define Get32(p) GetUi32(p)\n\nnamespace NArchive {\nnamespace NNsis {\n\nUInt64 CDecoder::GetInputProcessedSize() const\n{\n  if (_lzmaDecoder)\n    return _lzmaDecoder->GetInputProcessedSize();\n  if (_deflateDecoder)\n    return _deflateDecoder->GetInputProcessedSize();\n  if (_bzDecoder)\n    return _bzDecoder->GetInputProcessedSize();\n  return 0;\n}\n\n\nHRESULT CDecoder::Init(ISequentialInStream *inStream, bool &useFilter)\n{\n  useFilter = false;\n\n  if (_decoderInStream)\n    if (Method != _curMethod)\n      Release();\n  _curMethod = Method;\n  \n  if (!_codecInStream)\n  {\n    switch ((int)Method)\n    {\n      // case NMethodType::kCopy: return E_NOTIMPL;\n      case NMethodType::kDeflate:\n        _deflateDecoder = new NCompress::NDeflate::NDecoder::CCOMCoder();\n        _codecInStream = _deflateDecoder;\n        break;\n      case NMethodType::kBZip2:\n        _bzDecoder = new NCompress::NBZip2::CNsisDecoder();\n        _codecInStream = _bzDecoder;\n        break;\n      case NMethodType::kLZMA:\n        _lzmaDecoder = new NCompress::NLzma::CDecoder();\n        _codecInStream = _lzmaDecoder;\n        break;\n      default: return E_NOTIMPL;\n    }\n  }\n\n  if (Method == NMethodType::kDeflate)\n    _deflateDecoder->SetNsisMode(IsNsisDeflate);\n\n  if (FilterFlag)\n  {\n    Byte flag;\n    RINOK(ReadStream_FALSE(inStream, &flag, 1))\n    if (flag > 1)\n      return E_NOTIMPL;\n    useFilter = (flag != 0);\n  }\n  \n  if (!useFilter)\n    _decoderInStream = _codecInStream;\n  else\n  {\n    if (!_filterInStream)\n    {\n      _filter = new CFilterCoder(false);\n      _filterInStream = _filter;\n      _filter->Filter = new NCompress::NBcj::CCoder2(z7_BranchConvSt_X86_Dec);\n    }\n    RINOK(_filter->SetInStream(_codecInStream))\n    _decoderInStream = _filterInStream;\n  }\n\n  if (Method == NMethodType::kLZMA)\n  {\n    const unsigned kPropsSize = LZMA_PROPS_SIZE;\n    Byte props[kPropsSize];\n    RINOK(ReadStream_FALSE(inStream, props, kPropsSize))\n    RINOK(_lzmaDecoder->SetDecoderProperties2((const Byte *)props, kPropsSize))\n  }\n\n  {\n    CMyComPtr<ICompressSetInStream> setInStream;\n    _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);\n    if (!setInStream)\n      return E_NOTIMPL;\n    RINOK(setInStream->SetInStream(inStream))\n  }\n\n  {\n    CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;\n    _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);\n    if (!setOutStreamSize)\n      return E_NOTIMPL;\n    RINOK(setOutStreamSize->SetOutStreamSize(NULL))\n  }\n\n  if (useFilter)\n  {\n    RINOK(_filter->SetOutStreamSize(NULL))\n  }\n\n  return S_OK;\n}\n\n\nstatic const UInt32 kMask_IsCompressed = (UInt32)1 << 31;\n\n\nHRESULT CDecoder::SetToPos(UInt64 pos, ICompressProgressInfo *progress)\n{\n  if (StreamPos > pos)\n    return E_FAIL;\n  const UInt64 inSizeStart = GetInputProcessedSize();\n  UInt64 offset = 0;\n  while (StreamPos < pos)\n  {\n    size_t size = (size_t)MyMin(pos - StreamPos, (UInt64)Buffer.Size());\n    RINOK(Read(Buffer, &size))\n    if (size == 0)\n      return S_FALSE;\n    StreamPos += size;\n    offset += size;\n\n    const UInt64 inSize = GetInputProcessedSize() - inSizeStart;\n    RINOK(progress->SetRatioInfo(&inSize, &offset))\n  }\n  return S_OK;\n}\n\n\nHRESULT CDecoder::Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize,\n    ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,\n    UInt32 &packSizeRes, UInt32 &unpackSizeRes)\n{\n  CLimitedSequentialInStream *limitedStreamSpec = NULL;\n  CMyComPtr<ISequentialInStream> limitedStream;\n  packSizeRes = 0;\n  unpackSizeRes = 0;\n\n  if (Solid)\n  {\n    Byte temp[4];\n    size_t processedSize = 4;\n    RINOK(Read(temp, &processedSize))\n    StreamPos += processedSize;\n    if (processedSize != 4)\n      return S_FALSE;\n    UInt32 size = Get32(temp);\n    if (unpackSizeDefined && size != unpackSize)\n      return S_FALSE;\n    unpackSize = size;\n    unpackSizeDefined = true;\n  }\n  else\n  {\n    Byte temp[4];\n    {\n      size_t processedSize = 4;\n      RINOK(ReadStream(InputStream, temp, &processedSize))\n      StreamPos += processedSize;\n      if (processedSize != 4)\n        return S_FALSE;\n    }\n    UInt32 size = Get32(temp);\n\n    if ((size & kMask_IsCompressed) == 0)\n    {\n      if (unpackSizeDefined && size != unpackSize)\n        return S_FALSE;\n      packSizeRes = size;\n      if (outBuf)\n        outBuf->Alloc(size);\n\n      UInt64 offset = 0;\n      \n      while (size > 0)\n      {\n        UInt32 curSize = (UInt32)MyMin((size_t)size, Buffer.Size());\n        UInt32 processedSize;\n        RINOK(InputStream->Read(Buffer, curSize, &processedSize))\n        if (processedSize == 0)\n          return S_FALSE;\n        if (outBuf)\n          memcpy((Byte *)*outBuf + (size_t)offset, Buffer, processedSize);\n        offset += processedSize;\n        size -= processedSize;\n        StreamPos += processedSize;\n        unpackSizeRes += processedSize;\n        if (realOutStream)\n          RINOK(WriteStream(realOutStream, Buffer, processedSize))\n        RINOK(progress->SetRatioInfo(&offset, &offset))\n      }\n\n      return S_OK;\n    }\n    \n    size &= ~kMask_IsCompressed;\n    packSizeRes = size;\n    limitedStreamSpec = new CLimitedSequentialInStream;\n    limitedStream = limitedStreamSpec;\n    limitedStreamSpec->SetStream(InputStream);\n    limitedStreamSpec->Init(size);\n    {\n      bool useFilter;\n      RINOK(Init(limitedStream, useFilter))\n    }\n  }\n  \n  if (outBuf)\n  {\n    if (unpackSizeDefined)\n      outBuf->Alloc(unpackSize);\n  }\n\n  const UInt64 inSizeStart = GetInputProcessedSize();\n\n  // we don't allow files larger than 4 GB;\n  if (!unpackSizeDefined)\n    unpackSize = 0xFFFFFFFF;\n  UInt32 offset = 0;\n\n  HRESULT res = S_OK;\n\n  for (;;)\n  {\n    size_t rem = unpackSize - offset;\n    if (rem == 0)\n      break;\n    size_t size = Buffer.Size();\n    if (size > rem)\n      size = rem;\n    RINOK(Read(Buffer, &size))\n    if (size == 0)\n    {\n      if (unpackSizeDefined)\n        res = S_FALSE;\n      break;\n    }\n    \n    if (outBuf)\n    {\n      size_t nextSize = offset + size;\n      if (outBuf->Size() < nextSize)\n      {\n        {\n          const size_t nextSize2 = outBuf->Size() * 2;\n          if (nextSize < nextSize2)\n            nextSize = nextSize2;\n        }\n        outBuf->ChangeSize_KeepData(nextSize, offset);\n      }\n      memcpy((Byte *)*outBuf + (size_t)offset, Buffer, size);\n    }\n    \n    StreamPos += size;\n    offset += (UInt32)size;\n\n    const UInt64 inSize = GetInputProcessedSize() - inSizeStart;\n\n    if (Solid)\n      packSizeRes = (UInt32)inSize;\n    unpackSizeRes += (UInt32)size;\n    \n    UInt64 outSize = offset;\n    RINOK(progress->SetRatioInfo(&inSize, &outSize))\n    if (realOutStream)\n    {\n      res = WriteStream(realOutStream, Buffer, size);\n      if (res != S_OK)\n        break;\n    }\n  }\n\n  if (outBuf && offset != outBuf->Size())\n    outBuf->ChangeSize_KeepData(offset, offset);\n  \n  return res;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/NsisDecode.h",
    "content": "﻿// NsisDecode.h\n\n#ifndef ZIP7_INC_NSIS_DECODE_H\n#define ZIP7_INC_NSIS_DECODE_H\n\n#include \"../../../Common/MyBuffer.h\"\n\n#include \"../../Common/FilterCoder.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/BZip2Decoder.h\"\n#include \"../../Compress/DeflateDecoder.h\"\n#include \"../../Compress/LzmaDecoder.h\"\n\nnamespace NArchive {\nnamespace NNsis {\n\nnamespace NMethodType\n{\n  enum EEnum\n  {\n    kCopy,\n    kDeflate,\n    kBZip2,\n    kLZMA\n  };\n}\n\n/* 7-Zip installers 4.38 - 9.08 used modified version of NSIS that\n   supported BCJ filter for better compression ratio.\n   We support such modified NSIS archives. */\n\nclass CDecoder\n{\n  NMethodType::EEnum _curMethod; // method of created decoder\n\n  CFilterCoder *_filter;\n  CMyComPtr<ISequentialInStream> _filterInStream;\n  CMyComPtr<ISequentialInStream> _codecInStream;\n  CMyComPtr<ISequentialInStream> _decoderInStream;\n\n  NCompress::NBZip2::CNsisDecoder *_bzDecoder;\n  NCompress::NDeflate::NDecoder::CCOMCoder *_deflateDecoder;\n  NCompress::NLzma::CDecoder *_lzmaDecoder;\n\npublic:\n  CMyComPtr<IInStream> InputStream; // for non-solid\n  UInt64 StreamPos; // the pos in unpacked for solid, the pos in Packed for non-solid\n  \n  NMethodType::EEnum Method;\n  bool FilterFlag;\n  bool Solid;\n  bool IsNsisDeflate;\n  \n  CByteBuffer Buffer; // temp buf\n\n  CDecoder():\n      FilterFlag(false),\n      Solid(true),\n      IsNsisDeflate(true)\n  {\n    _bzDecoder = NULL;\n    _deflateDecoder = NULL;\n    _lzmaDecoder = NULL;\n  }\n\n  void Release()\n  {\n    _filterInStream.Release();\n    _codecInStream.Release();\n    _decoderInStream.Release();\n    InputStream.Release();\n\n    _bzDecoder = NULL;\n    _deflateDecoder = NULL;\n    _lzmaDecoder = NULL;\n  }\n\n  UInt64 GetInputProcessedSize() const;\n  \n  HRESULT Init(ISequentialInStream *inStream, bool &useFilter);\n\n  HRESULT Read(void *data, size_t *processedSize)\n  {\n    return ReadStream(_decoderInStream, data, processedSize);\n  }\n\n\n  HRESULT SetToPos(UInt64 pos, ICompressProgressInfo *progress); // for solid\n  HRESULT Decode(CByteBuffer *outBuf, bool unpackSizeDefined, UInt32 unpackSize,\n      ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,\n      UInt32 &packSizeRes, UInt32 &unpackSizeRes);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/NsisHandler.cpp",
    "content": "﻿// NSisHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"NsisHandler.h\"\n\n#define Get32(p) GetUi32(p)\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NNsis {\n\n#define kBcjMethod \"BCJ\"\n#define kUnknownMethod \"Unknown\"\n\nstatic const char * const kMethods[] =\n{\n    \"Copy\"\n  , \"Deflate\"\n  , \"BZip2\"\n  , \"LZMA\"\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidAttrib,\n  kpidMethod,\n  kpidSolid,\n  kpidOffset\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidMethod,\n  kpidSolid,\n  kpidBit64,\n  kpidHeadersSize,\n  kpidEmbeddedStubSize,\n  kpidSubType\n  // kpidCodePage\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\n\nstatic void AddDictProp(AString &s, UInt32 val)\n{\n  for (unsigned i = 0; i < 32; i++)\n    if (((UInt32)1 << i) == val)\n    {\n      s.Add_UInt32(i);\n      return;\n    }\n  char c = 'b';\n  if      ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }\n  else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }\n  s.Add_UInt32(val);\n  s.Add_Char(c);\n}\n\nstatic AString GetMethod(bool useFilter, NMethodType::EEnum method, UInt32 dict)\n{\n  AString s;\n  if (useFilter)\n  {\n    s += kBcjMethod;\n    s.Add_Space();\n  }\n  s += ((unsigned)method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[(unsigned)method] : kUnknownMethod;\n  if (method == NMethodType::kLZMA)\n  {\n    s.Add_Colon();\n    AddDictProp(s, dict);\n  }\n  return s;\n}\n\n/*\nAString CHandler::GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt32 dictionary) const\n{\n  AString s;\n  if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && useItemFilter)\n  {\n    s += kBcjMethod;\n    s.Add_Space();\n  }\n  s += (method < Z7_ARRAY_SIZE(kMethods)) ? kMethods[method] : kUnknownMethod;\n  if (method == NMethodType::kLZMA)\n  {\n    s.Add_Colon();\n    s += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: dictionary);\n  }\n  return s;\n}\n*/\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    // case kpidCodePage: if (_archive.IsUnicode) prop = \"UTF-16\"; break;\n    case kpidSubType:\n    {\n      AString s (_archive.GetFormatDescription());\n      if (!_archive.IsInstaller)\n      {\n        s.Add_Space_if_NotEmpty();\n        s += \"(Uninstall)\";\n      }\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidBit64: if (_archive.Is64Bit) prop = true; break;\n    case kpidMethod: prop = _methodString; break;\n    case kpidSolid: prop = _archive.IsSolid; break;\n    case kpidOffset: prop = _archive.StartOffset; break;\n    case kpidPhySize: prop = (UInt64)((UInt64)_archive.ExeStub.Size() + _archive.FirstHeader.ArcSize); break;\n    case kpidEmbeddedStubSize: prop = (UInt64)_archive.ExeStub.Size(); break;\n    case kpidHeadersSize: prop = _archive.FirstHeader.HeaderSize; break;\n    \n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_archive.IsTruncated()) v |= kpv_ErrorFlags_UnexpectedEnd;\n      prop = v;\n      break;\n    }\n    \n    case kpidName:\n    {\n      AString s;\n      \n      #ifdef NSIS_SCRIPT\n        if (!_archive.Name.IsEmpty())\n          s = _archive.Name;\n        if (!_archive.IsInstaller)\n        {\n          if (!s.IsEmpty())\n            s.Add_Dot();\n          s += \"Uninstall\";\n        }\n      #endif\n\n      if (s.IsEmpty())\n        s = _archive.IsInstaller ? \"Install\" : \"Uninstall\";\n      s += (_archive.ExeStub.Size() == 0) ? \".nsis\" : \".exe\";\n\n      prop = _archive.ConvertToUnicode(s);\n      break;\n    }\n    \n    #ifdef NSIS_SCRIPT\n    case kpidShortComment:\n    {\n      if (!_archive.BrandingText.IsEmpty())\n        prop = _archive.ConvertToUnicode(_archive.BrandingText);\n      break;\n    }\n    #endif\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    if (_archive.Open(stream, maxCheckStartPosition) != S_OK)\n      return S_FALSE;\n    {\n      UInt32 dict = _archive.DictionarySize;\n      if (!_archive.IsSolid)\n      {\n        FOR_VECTOR (i, _archive.Items)\n        {\n          const CItem &item = _archive.Items[i];\n          if (item.DictionarySize > dict)\n            dict = item.DictionarySize;\n        }\n      }\n      _methodString = GetMethod(_archive.UseFilter, _archive.Method, dict);\n    }\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _archive.Clear();\n  _archive.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _archive.Items.Size()\n  #ifdef NSIS_SCRIPT\n    + 1 + _archive.LicenseFiles.Size()\n  #endif\n  ;\n  return S_OK;\n}\n\nbool CHandler::GetUncompressedSize(unsigned index, UInt32 &size) const\n{\n  size = 0;\n  const CItem &item = _archive.Items[index];\n  if (item.Size_Defined)\n    size = item.Size;\n  else if (_archive.IsSolid && item.EstimatedSize_Defined)\n    size = item.EstimatedSize;\n  else if (!item.IsEmptyFile)\n    return false;\n  return true;\n}\n\nbool CHandler::GetCompressedSize(unsigned index, UInt32 &size) const\n{\n  size = 0;\n  const CItem &item = _archive.Items[index];\n  if (item.CompressedSize_Defined)\n    size = item.CompressedSize;\n  else\n  {\n    if (_archive.IsSolid)\n    {\n      if (index == 0)\n        size = _archive.FirstHeader.GetDataSize();\n      else\n        return false;\n    }\n    else\n    {\n      if (!item.IsCompressed)\n        size = item.Size;\n      else\n        return false;\n    }\n  }\n  return true;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  #ifdef NSIS_SCRIPT\n  if (index >= (UInt32)_archive.Items.Size())\n  {\n    if (index == (UInt32)_archive.Items.Size())\n    {\n      switch (propID)\n      {\n        case kpidPath: prop = \"[NSIS].nsi\"; break;\n        case kpidSize:\n        case kpidPackSize: prop = (UInt64)_archive.Script.Len(); break;\n        case kpidSolid: prop = false; break;\n      }\n    }\n    else\n    {\n      const CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)];\n      switch (propID)\n      {\n        case kpidPath: prop = lic.Name; break;\n        case kpidSize:\n        case kpidPackSize: prop = (UInt64)lic.Size; break;\n        case kpidSolid: prop = false; break;\n      }\n    }\n  }\n  else\n  #endif\n  {\n    const CItem &item = _archive.Items[index];\n    switch (propID)\n    {\n      case kpidOffset: prop = item.Pos; break;\n      case kpidPath:\n      {\n        UString s = NItemName::WinPathToOsPath(_archive.GetReducedName(index));\n        if (!s.IsEmpty())\n          prop = (const wchar_t *)s;\n        break;\n      }\n      case kpidSize:\n      {\n        UInt32 size;\n        if (GetUncompressedSize(index, size))\n          prop = (UInt64)size;\n        break;\n      }\n      case kpidPackSize:\n      {\n        UInt32 size;\n        if (GetCompressedSize(index, size))\n          prop = (UInt64)size;\n        break;\n      }\n      case kpidMTime:\n      {\n        if (item.MTime.dwHighDateTime > 0x01000000 &&\n            item.MTime.dwHighDateTime < 0xFF000000)\n          prop = item.MTime;\n        break;\n      }\n      case kpidAttrib:\n      {\n        if (item.Attrib_Defined)\n          prop = item.Attrib;\n        break;\n      }\n      \n      case kpidMethod:\n        if (_archive.IsSolid)\n          prop = _methodString;\n        else\n          prop = GetMethod(_archive.UseFilter, item.IsCompressed ? _archive.Method :\n              NMethodType::kCopy, item.DictionarySize);\n        break;\n      \n      case kpidSolid:  prop = _archive.IsSolid; break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nstatic bool UninstallerPatch(const Byte *p, size_t size, Byte *dest, size_t destSize)\n{\n  for (;;)\n  {\n    if (size < 4)\n      return false;\n    const UInt32 len = Get32(p);\n    if (len == 0)\n      return size == 4;\n    if (size < 8)\n      return false;\n    const UInt32 offs = Get32(p + 4);\n    p += 8;\n    size -= 8;\n    if (size < len || offs > destSize || len > destSize - offs)\n      return false;\n    memcpy(dest + offs, p, len);\n    p += len;\n    size -= len;\n  }\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    GetNumberOfItems(&numItems);\n  if (numItems == 0)\n    return S_OK;\n  \n  UInt64 totalSize = 0;\n  UInt64 solidPosMax = 0;\n\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = (allFilesMode ? i : indices[i]);\n    \n    #ifdef NSIS_SCRIPT\n    if (index >= _archive.Items.Size())\n    {\n      if (index == _archive.Items.Size())\n        totalSize += _archive.Script.Len();\n      else\n        totalSize += _archive.LicenseFiles[index - (_archive.Items.Size() + 1)].Size;\n    }\n    else\n    #endif\n    {\n      UInt32 size;\n      if (_archive.IsSolid)\n      {\n        GetUncompressedSize(index, size);\n        UInt64 pos = (UInt64)_archive.GetPosOfSolidItem(index) + size;\n        if (solidPosMax < pos)\n          solidPosMax = pos;\n      }\n      else\n      {\n        GetCompressedSize(index, size);\n        totalSize += size;\n      }\n    }\n  }\n\n  extractCallback->SetTotal(totalSize + solidPosMax);\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, !_archive.IsSolid);\n\n  if (_archive.IsSolid)\n  {\n    RINOK(_archive.SeekTo_DataStreamOffset())\n    RINOK(_archive.InitDecoder())\n    _archive.Decoder.StreamPos = 0;\n  }\n\n  /* We use tempBuf for solid archives, if there is duplicate item.\n     We don't know uncompressed size for non-solid archives, so we can't\n     allocate exact buffer.\n     We use tempBuf also for first part (EXE stub) of unistall.exe\n     and tempBuf2 is used for second part (NSIS script). */\n\n  CByteBuffer tempBuf;\n  CByteBuffer tempBuf2;\n  \n  /* tempPos is pos in uncompressed stream of previous item for solid archive, that\n     was written to tempBuf  */\n  UInt64 tempPos = (UInt64)(Int64)-1;\n  \n  /* prevPos is pos in uncompressed stream of previous item for solid archive.\n     It's used for test mode (where we don't need to test same file second time */\n  UInt64 prevPos =  (UInt64)(Int64)-1;\n  \n  // if there is error in solid archive, we show error for all subsequent files\n  bool solidDataError = false;\n\n  UInt64 curTotalPacked = 0, curTotalUnpacked = 0;\n  UInt32 curPacked = 0;\n  UInt64 curUnpacked = 0;\n\n  for (i = 0; i < numItems; i++,\n      curTotalPacked += curPacked,\n      curTotalUnpacked += curUnpacked)\n  {\n    lps->InSize = curTotalPacked;\n    lps->OutSize = curTotalUnpacked;\n    if (_archive.IsSolid)\n      lps->OutSize += _archive.Decoder.StreamPos;\n\n    curPacked = 0;\n    curUnpacked = 0;\n    RINOK(lps->SetCur())\n\n    // RINOK(extractCallback->SetCompleted(&currentTotalSize))\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    bool dataError = false;\n\n    #ifdef NSIS_SCRIPT\n    if (index >= (UInt32)_archive.Items.Size())\n    {\n      const void *data;\n      size_t size;\n      if (index == (UInt32)_archive.Items.Size())\n      {\n        data = (const Byte *)_archive.Script;\n        size = _archive.Script.Len();\n      }\n      else\n      {\n        CLicenseFile &lic = _archive.LicenseFiles[index - (_archive.Items.Size() + 1)];\n        if (lic.Text.Size() != 0)\n          data = lic.Text;\n        else\n          data = _archive._data + lic.Offset;\n        size = lic.Size;\n      }\n      curUnpacked = size;\n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      if (realOutStream)\n        RINOK(WriteStream(realOutStream, data, size))\n    }\n    else\n    #endif\n    {\n      const CItem &item = _archive.Items[index];\n      \n      if (!_archive.IsSolid)\n        GetCompressedSize(index, curPacked);\n      \n      if (!testMode && !realOutStream)\n        continue;\n      \n      RINOK(extractCallback->PrepareOperation(askMode))\n      \n      dataError = solidDataError;\n\n      bool needDecompress = false;\n      \n      if (!item.IsEmptyFile)\n      {\n        needDecompress = !solidDataError;\n        if (needDecompress)\n        {\n          if (testMode && _archive.IsSolid && _archive.GetPosOfSolidItem(index) == prevPos)\n            needDecompress = false;\n        }\n      }\n\n      if (needDecompress)\n      {\n        bool writeToTemp = false;\n        bool readFromTemp = false;\n\n        if (!_archive.IsSolid)\n        {\n          RINOK(_archive.SeekToNonSolidItem(index))\n        }\n        else\n        {\n          UInt64 pos = _archive.GetPosOfSolidItem(index);\n          if (pos < _archive.Decoder.StreamPos)\n          {\n            if (pos != tempPos)\n              solidDataError = dataError = true;\n            readFromTemp = true;\n          }\n          else\n          {\n            HRESULT res = _archive.Decoder.SetToPos(pos, lps);\n            if (res != S_OK)\n            {\n              if (res != S_FALSE)\n                return res;\n              solidDataError = dataError = true;\n            }\n            else if (!testMode && i + 1 < numItems)\n            {\n              const UInt32 next = allFilesMode ? i + 1 : indices[i + 1];\n              if (next < _archive.Items.Size())\n              {\n                // next cannot be IsEmptyFile\n                const UInt64 nextPos = _archive.GetPosOfSolidItem(next);\n                if (nextPos == pos)\n                {\n                  writeToTemp = true;\n                  tempPos = pos;\n                }\n              }\n            }\n          }\n          prevPos = pos;\n        }\n\n        /* nsis 3.08 can use (PatchSize == 0) for uninstaller without patched section */\n\n        const bool is_PatchedUninstaller = item.Is_PatchedUninstaller();\n       \n        if (!dataError)\n        {\n          // UInt32 unpackSize = 0;\n          // bool unpackSize_Defined = false;\n          bool writeToTemp1 = writeToTemp;\n          if (is_PatchedUninstaller)\n          {\n            // unpackSize = item.PatchSize;\n            // unpackSize_Defined = true;\n            if (!readFromTemp)\n              writeToTemp = true;\n            writeToTemp1 = writeToTemp;\n            if (_archive.ExeStub.Size() == 0)\n            {\n              if (writeToTemp1 && !readFromTemp)\n                tempBuf.Free();\n              writeToTemp1 = false;\n            }\n          }\n\n          if (readFromTemp)\n          {\n            if (realOutStream && !is_PatchedUninstaller)\n              RINOK(WriteStream(realOutStream, tempBuf, tempBuf.Size()))\n          }\n          else\n          {\n            UInt32 curUnpacked32 = 0;\n            const HRESULT res = _archive.Decoder.Decode(\n                writeToTemp1 ? &tempBuf : NULL,\n                is_PatchedUninstaller, item.PatchSize,\n                is_PatchedUninstaller ? NULL : (ISequentialOutStream *)realOutStream,\n                lps,\n                curPacked, curUnpacked32);\n            curUnpacked = curUnpacked32;\n            if (_archive.IsSolid)\n              curUnpacked = 0;\n            if (res != S_OK)\n            {\n              if (res != S_FALSE)\n                return res;\n              dataError = true;\n              if (_archive.IsSolid)\n                solidDataError = true;\n            }\n          }\n        }\n        \n        if (!dataError && is_PatchedUninstaller)\n        {\n          if (_archive.ExeStub.Size() != 0)\n          {\n            CByteBuffer destBuf = _archive.ExeStub;\n            dataError = !UninstallerPatch(tempBuf, tempBuf.Size(), destBuf, destBuf.Size());\n            if (realOutStream)\n              RINOK(WriteStream(realOutStream, destBuf, destBuf.Size()))\n          }\n          \n          if (readFromTemp)\n          {\n            if (realOutStream)\n              RINOK(WriteStream(realOutStream, tempBuf2, tempBuf2.Size()))\n          }\n          else\n          {\n            UInt32 curPacked2 = 0;\n            UInt32 curUnpacked2 = 0;\n\n            if (!_archive.IsSolid)\n            {\n              RINOK(_archive.SeekTo(_archive.GetPosOfNonSolidItem(index) + 4 + curPacked ))\n            }\n\n            const HRESULT res = _archive.Decoder.Decode(\n                writeToTemp ? &tempBuf2 : NULL,\n                false, 0,\n                realOutStream,\n                lps,\n                curPacked2, curUnpacked2);\n            curPacked += curPacked2;\n            if (!_archive.IsSolid)\n              curUnpacked += curUnpacked2;\n            if (res != S_OK)\n            {\n              if (res != S_FALSE)\n                return res;\n              dataError = true;\n              if (_archive.IsSolid)\n                solidDataError = true;\n            }\n          }\n        }\n      }\n    }\n    realOutStream.Release();\n    RINOK(extractCallback->SetOperationResult(dataError ?\n        NExtract::NOperationResult::kDataError :\n        NExtract::NOperationResult::kOK))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/NsisHandler.h",
    "content": "﻿// NSisHandler.h\n\n#ifndef ZIP7_INC_NSIS_HANDLER_H\n#define ZIP7_INC_NSIS_HANDLER_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../Common/CreateCoder.h\"\n\n#include \"../IArchive.h\"\n\n#include \"NsisIn.h\"\n\nnamespace NArchive {\nnamespace NNsis {\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  CInArchive _archive;\n  AString _methodString;\n\n  bool GetUncompressedSize(unsigned index, UInt32 &size) const;\n  bool GetCompressedSize(unsigned index, UInt32 &size) const;\n\n  // AString GetMethod(NMethodType::EEnum method, bool useItemFilter, UInt32 dictionary) const;\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/NsisIn.cpp",
    "content": "﻿// NsisIn.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringToInt.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n\n#include \"NsisIn.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n\n// #define NUM_SPEED_TESTS 1000\n\nnamespace NArchive {\nnamespace NNsis {\n\nstatic const size_t kInputBufSize = 1 << 20;\n\nconst Byte kSignature[kSignatureSize] = NSIS_SIGNATURE;\nstatic const UInt32 kMask_IsCompressed = (UInt32)1 << 31;\n\nstatic const unsigned kNumCommandParams = 6;\nstatic const unsigned kCmdSize = 4 + kNumCommandParams * 4;\n\n#ifdef NSIS_SCRIPT\n#define CR_LF \"\\x0D\\x0A\"\n#endif\n\nstatic const char * const kErrorStr = \"$_ERROR_STR_\";\n\n#define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }\n\n\n/* There are several versions of NSIS:\n   1) Original NSIS:\n        NSIS-2 ANSI\n        NSIS-3 ANSI\n        NSIS-3 Unicode\n   2) NSIS from Jim Park that extends old NSIS-2 to Unicode support:\n        NSIS-Park-(1,2,3) ANSI\n        NSIS-Park-(1,2,3) Unicode\n\n   The command IDs layout is slightly different for different versions.\n   Also there are additional \"log\" versions of NSIS that support EW_LOG.\n   We use the layout of \"NSIS-3 Unicode\" without \"log\" as main layout.\n   And we transfer the command IDs to main layout, if another layout is detected. */\n\n\nenum\n{\n  EW_INVALID_OPCODE,\n  EW_RET,               // Return\n  EW_NOP,               // Nop, Goto\n  EW_ABORT,             // Abort\n  EW_QUIT,              // Quit\n  EW_CALL,              // Call, InitPluginsDir\n  EW_UPDATETEXT,        // DetailPrint\n  EW_SLEEP,             // Sleep\n  EW_BRINGTOFRONT,      // BringToFront\n  EW_CHDETAILSVIEW,     // SetDetailsView\n  EW_SETFILEATTRIBUTES, // SetFileAttributes\n  EW_CREATEDIR,         // CreateDirectory, SetOutPath\n  EW_IFFILEEXISTS,      // IfFileExists\n  EW_SETFLAG,           // SetRebootFlag, ...\n  EW_IFFLAG,            // IfAbort, IfSilent, IfErrors, IfRebootFlag\n  EW_GETFLAG,           // GetInstDirError, GetErrorLevel\n  EW_RENAME,            // Rename\n  EW_GETFULLPATHNAME,   // GetFullPathName\n  EW_SEARCHPATH,        // SearchPath\n  EW_GETTEMPFILENAME,   // GetTempFileName\n  EW_EXTRACTFILE,       // File\n  EW_DELETEFILE,        // Delete\n  EW_MESSAGEBOX,        // MessageBox\n  EW_RMDIR,             // RMDir\n  EW_STRLEN,            // StrLen\n  EW_ASSIGNVAR,         // StrCpy\n  EW_STRCMP,            // StrCmp\n  EW_READENVSTR,        // ReadEnvStr, ExpandEnvStrings\n  EW_INTCMP,            // IntCmp, IntCmpU\n  EW_INTOP,             // IntOp\n  EW_INTFMT,            // IntFmt/Int64Fmt\n  EW_PUSHPOP,           // Push/Pop/Exchange\n  EW_FINDWINDOW,        // FindWindow\n  EW_SENDMESSAGE,       // SendMessage\n  EW_ISWINDOW,          // IsWindow\n  EW_GETDLGITEM,        // GetDlgItem\n  EW_SETCTLCOLORS,      // SetCtlColors\n  EW_SETBRANDINGIMAGE,  // SetBrandingImage / LoadAndSetImage\n  EW_CREATEFONT,        // CreateFont\n  EW_SHOWWINDOW,        // ShowWindow, EnableWindow, HideWindow\n  EW_SHELLEXEC,         // ExecShell\n  EW_EXECUTE,           // Exec, ExecWait\n  EW_GETFILETIME,       // GetFileTime\n  EW_GETDLLVERSION,     // GetDLLVersion\n\n  // EW_GETFONTVERSION, // Park : 2.46.2\n  // EW_GETFONTNAME,    // Park : 2.46.3\n \n  EW_REGISTERDLL,       // RegDLL, UnRegDLL, CallInstDLL\n  EW_CREATESHORTCUT,    // CreateShortCut\n  EW_COPYFILES,         // CopyFiles\n  EW_REBOOT,            // Reboot\n  EW_WRITEINI,          // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI\n  EW_READINISTR,        // ReadINIStr\n  EW_DELREG,            // DeleteRegValue, DeleteRegKey\n  EW_WRITEREG,          // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD\n  EW_READREGSTR,        // ReadRegStr, ReadRegDWORD\n  EW_REGENUM,           // EnumRegKey, EnumRegValue\n  EW_FCLOSE,            // FileClose\n  EW_FOPEN,             // FileOpen\n  EW_FPUTS,             // FileWrite, FileWriteByte\n  EW_FGETS,             // FileRead, FileReadByte\n\n  // Park\n  // EW_FPUTWS,            // FileWriteUTF16LE, FileWriteWord\n  // EW_FGETWS,            // FileReadUTF16LE, FileReadWord\n  \n  EW_FSEEK,             // FileSeek\n  EW_FINDCLOSE,         // FindClose\n  EW_FINDNEXT,          // FindNext\n  EW_FINDFIRST,         // FindFirst\n  EW_WRITEUNINSTALLER,  // WriteUninstaller\n  \n  // Park : since 2.46.3 the log is enabled in main Park version\n  // EW_LOG,               // LogSet, LogText\n\n  EW_SECTIONSET,        // Get*, Set*\n  EW_INSTTYPESET,       // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType\n\n  /*\n  // before v3.06 nsis it was so:\n  // instructions not actually implemented in exehead, but used in compiler.\n  EW_GETLABELADDR,      // both of these get converted to EW_ASSIGNVAR\n  EW_GETFUNCTIONADDR,\n  */\n  \n  // v3.06 and later it was changed to:\n  EW_GETOSINFO,\n  EW_RESERVEDOPCODE,\n  \n  EW_LOCKWINDOW,        // LockWindow\n  \n  // 2 unicode commands available only in Unicode archive\n  EW_FPUTWS,            // FileWriteUTF16LE, FileWriteWord\n  EW_FGETWS,            // FileReadUTF16LE, FileReadWord\n\n  /*\n  // since v3.06 the fllowing IDs codes was moved here:\n  // Opcodes listed here are not actually used in exehead. No exehead opcodes should be present after these!\n  EW_GETLABELADDR,      // --> EW_ASSIGNVAR\n  EW_GETFUNCTIONADDR,   // --> EW_ASSIGNVAR\n  */\n\n  // The following IDs are not IDs in real order.\n  // We just need some IDs to translate eny extended layout to main layout.\n\n  EW_LOG,               // LogSet, LogText\n\n  // Park\n  EW_FINDPROC,          // FindProc\n  \n  EW_GETFONTVERSION,    // GetFontVersion\n  EW_GETFONTNAME,       // GetFontName\n\n  kNumCmds\n};\n\n\n\nstruct CCommandInfo\n{\n  Byte NumParams;\n};\n\nstatic const CCommandInfo k_Commands[kNumCmds] =\n{\n  { 0 }, // \"Invalid\" },\n  { 0 }, // Return\n  { 1 }, // Nop, Goto\n  { 1 }, // \"Abort\" },\n  { 0 }, // \"Quit\" },\n  { 2 }, // Call\n  { 6 }, // \"DetailPrint\" }, // 1 param in new versions, 6 in old NSIS versions\n  { 1 }, // \"Sleep\" },\n  { 0 }, // \"BringToFront\" },\n  { 2 }, // \"SetDetailsView\" },\n  { 2 }, // \"SetFileAttributes\" },\n  { 3 }, // CreateDirectory, SetOutPath\n  { 3 }, // \"IfFileExists\" },\n  { 3 }, // SetRebootFlag, ...\n  { 4 }, // \"If\" }, // IfAbort, IfSilent, IfErrors, IfRebootFlag\n  { 2 }, // \"Get\" }, // GetInstDirError, GetErrorLevel\n  { 4 }, // \"Rename\" },\n  { 3 }, // \"GetFullPathName\" },\n  { 2 }, // \"SearchPath\" },\n  { 2 }, // \"GetTempFileName\" },\n  { 6 }, // \"File\"\n  { 2 }, // \"Delete\" },\n  { 6 }, // \"MessageBox\" },\n  { 2 }, // \"RMDir\" },\n  { 2 }, // \"StrLen\" },\n  { 4 }, // StrCpy, GetCurrentAddress\n  { 5 }, // \"StrCmp\" },\n  { 3 }, // ReadEnvStr, ExpandEnvStrings\n  { 6 }, // \"IntCmp\" },\n  { 4 }, // \"IntOp\" },\n  { 4 }, // \"IntFmt\" }, EW_INTFMT\n  { 6 }, // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage.\n  { 5 }, // \"FindWindow\" },\n  { 6 }, // \"SendMessage\" },\n  { 3 }, // \"IsWindow\" },\n  { 3 }, // \"GetDlgItem\" },\n  { 2 }, // \"SetCtlColors\" },\n  { 4 }, // \"SetBrandingImage\" } // LoadAndSetImage\n  { 5 }, // \"CreateFont\" },\n  { 4 }, // ShowWindow, EnableWindow, HideWindow\n  { 6 }, // \"ExecShell\" },\n  { 3 }, // \"Exec\" }, // Exec, ExecWait\n  { 3 }, // \"GetFileTime\" },\n  { 4 }, // \"GetDLLVersion\" },\n  { 6 }, // RegDLL, UnRegDLL, CallInstDLL // it must be 5 params. But some multi-command write garbage.\n  { 6 }, // \"CreateShortCut\" },\n  { 4 }, // \"CopyFiles\" },\n  { 1 }, // \"Reboot\" },\n  { 5 }, // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI\n  { 4 }, // \"ReadINIStr\" },\n  { 5 }, // \"DeleteReg\" }, // DeleteRegKey, DeleteRegValue\n  { 6 }, // \"WriteReg\" },  // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD\n  { 5 }, // \"ReadReg\" }, // ReadRegStr, ReadRegDWORD\n  { 5 }, // \"EnumReg\" }, // EnumRegKey, EnumRegValue\n  { 1 }, // \"FileClose\" },\n  { 4 }, // \"FileOpen\" },\n  { 3 }, // \"FileWrite\" }, // FileWrite, FileWriteByte\n  { 4 }, // \"FileRead\" }, // FileRead, FileReadByte\n  { 4 }, // \"FileSeek\" },\n  { 1 }, // \"FindClose\" },\n  { 2 }, // \"FindNext\" },\n  { 3 }, // \"FindFirst\" },\n  { 4 }, // \"WriteUninstaller\" },\n  { 5 }, // \"Section\" },  // ***\n  { 4 }, // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType\n  \n  // { 6 }, // \"GetLabelAddr\" }, // before 3.06\n  { 6 }, // \"GetOsInfo\" }, GetKnownFolderPath, ReadMemory, // v3.06+\n  \n  { 2 }, // \"GetFunctionAddress\" }, // before 3.06\n\n  { 1 }, // \"LockWindow\" },\n  { 4 }, // \"FileWrite\" }, // FileWriteUTF16LE, FileWriteWord\n  { 4 }, // \"FileRead\" }, // FileReadUTF16LE, FileReadWord\n  \n  { 2 }, // \"Log\" }, // LogSet, LogText\n  // Park\n  { 2 }, // \"FindProc\" },\n  { 2 }, // \"GetFontVersion\" },\n  { 2 }, // \"GetFontName\" }\n};\n\n#ifdef NSIS_SCRIPT\n\nstatic const char * const k_CommandNames[kNumCmds] =\n{\n    \"Invalid\"\n  , NULL // Return\n  , NULL // Nop, Goto\n  , \"Abort\"\n  , \"Quit\"\n  , NULL // Call\n  , \"DetailPrint\" // 1 param in new versions, 6 in old NSIS versions\n  , \"Sleep\"\n  , \"BringToFront\"\n  , \"SetDetailsView\"\n  , \"SetFileAttributes\"\n  , NULL // CreateDirectory, SetOutPath\n  , \"IfFileExists\"\n  , NULL // SetRebootFlag, ...\n  , \"If\" // IfAbort, IfSilent, IfErrors, IfRebootFlag\n  , \"Get\" // GetInstDirError, GetErrorLevel\n  , \"Rename\"\n  , \"GetFullPathName\"\n  , \"SearchPath\"\n  , \"GetTempFileName\"\n  , NULL // File\n  , \"Delete\"\n  , \"MessageBox\"\n  , \"RMDir\"\n  , \"StrLen\"\n  , NULL // StrCpy, GetCurrentAddress\n  , \"StrCmp\"\n  , NULL // ReadEnvStr, ExpandEnvStrings\n  , NULL // IntCmp / Int64Cmp / EW_INTCMP\n  , \"IntOp\"\n  , NULL // IntFmt / Int64Fmt / EW_INTFMT\n  , NULL // Push, Pop, Exch // it must be 3 params. But some multi-command write garbage.\n  , \"FindWindow\"\n  , \"SendMessage\"\n  , \"IsWindow\"\n  , \"GetDlgItem\"\n  , \"SetCtlColors\"\n  , \"SetBrandingImage\"\n  , \"CreateFont\"\n  , NULL // ShowWindow, EnableWindow, HideWindow\n  , \"ExecShell\"\n  , \"Exec\" // Exec, ExecWait\n  , \"GetFileTime\"\n  , \"GetDLLVersion\"\n  , NULL // RegDLL, UnRegDLL, CallInstDLL // it must be 5 params. But some multi-command write garbage.\n  , \"CreateShortCut\"\n  , \"CopyFiles\"\n  , \"Reboot\"\n  , NULL // WriteINIStr, DeleteINISec, DeleteINIStr, FlushINI\n  , \"ReadINIStr\"\n  , \"DeleteReg\" // DeleteRegKey, DeleteRegValue\n  , \"WriteReg\"  // WriteRegStr, WriteRegExpandStr, WriteRegBin, WriteRegDWORD\n  , \"ReadReg\" // ReadRegStr, ReadRegDWORD\n  , \"EnumReg\" // EnumRegKey, EnumRegValue\n  , \"FileClose\"\n  , \"FileOpen\"\n  , \"FileWrite\" // FileWrite, FileWriteByte\n  , \"FileRead\" // FileRead, FileReadByte\n  , \"FileSeek\"\n  , \"FindClose\"\n  , \"FindNext\"\n  , \"FindFirst\"\n  , \"WriteUninstaller\"\n  , \"Section\"  // ***\n  , NULL // InstTypeSetText, InstTypeGetText, SetCurInstType, GetCurInstType\n  \n  , NULL // \"GetOsInfo\" // , \"GetLabelAddr\" //\n  , \"GetFunctionAddress\"\n  \n  , \"LockWindow\"\n  , \"FileWrite\" // FileWriteUTF16LE, FileWriteWord\n  , \"FileRead\" // FileReadUTF16LE, FileReadWord\n  \n  , \"Log\" // LogSet, LogText\n\n  // Park\n  , \"FindProc\"\n  , \"GetFontVersion\"\n  , \"GetFontName\"\n};\n\n#endif\n\n/* NSIS can use one name for two CSIDL_*** and CSIDL_COMMON_*** items (CurrentUser / AllUsers)\n   Some NSIS shell names are not identical to WIN32 CSIDL_* names.\n   NSIS doesn't use some CSIDL_* values. But we add name for all CSIDL_ (marked with '+'). */\n\nstatic const char * const kShellStrings[] =\n{\n    \"DESKTOP\"     // +\n  , \"INTERNET\"    // +\n  , \"SMPROGRAMS\"  // CSIDL_PROGRAMS\n  , \"CONTROLS\"    // +\n  , \"PRINTERS\"    // +\n  , \"DOCUMENTS\"   // CSIDL_PERSONAL\n  , \"FAVORITES\"   // CSIDL_FAVORITES\n  , \"SMSTARTUP\"   // CSIDL_STARTUP\n  , \"RECENT\"      // CSIDL_RECENT\n  , \"SENDTO\"      // CSIDL_SENDTO\n  , \"BITBUCKET\"   // +\n  , \"STARTMENU\"\n  , NULL          // CSIDL_MYDOCUMENTS = CSIDL_PERSONAL\n  , \"MUSIC\"       // CSIDL_MYMUSIC\n  , \"VIDEOS\"      // CSIDL_MYVIDEO\n  , NULL\n  , \"DESKTOP\"     // CSIDL_DESKTOPDIRECTORY\n  , \"DRIVES\"      // +\n  , \"NETWORK\"     // +\n  , \"NETHOOD\"\n  , \"FONTS\"\n  , \"TEMPLATES\"\n  , \"STARTMENU\"   // CSIDL_COMMON_STARTMENU\n  , \"SMPROGRAMS\"  // CSIDL_COMMON_PROGRAMS\n  , \"SMSTARTUP\"   // CSIDL_COMMON_STARTUP\n  , \"DESKTOP\"     // CSIDL_COMMON_DESKTOPDIRECTORY\n  , \"APPDATA\"     // CSIDL_APPDATA         !!! \"QUICKLAUNCH\"\n  , \"PRINTHOOD\"\n  , \"LOCALAPPDATA\"\n  , \"ALTSTARTUP\"\n  , \"ALTSTARTUP\"  // CSIDL_COMMON_ALTSTARTUP\n  , \"FAVORITES\"   // CSIDL_COMMON_FAVORITES\n  , \"INTERNET_CACHE\"\n  , \"COOKIES\"\n  , \"HISTORY\"\n  , \"APPDATA\"     // CSIDL_COMMON_APPDATA\n  , \"WINDIR\"\n  , \"SYSDIR\"\n  , \"PROGRAM_FILES\" // +\n  , \"PICTURES\"    // CSIDL_MYPICTURES\n  , \"PROFILE\"\n  , \"SYSTEMX86\" // +\n  , \"PROGRAM_FILESX86\" // +\n  , \"PROGRAM_FILES_COMMON\" // +\n  , \"PROGRAM_FILES_COMMONX8\" // +  CSIDL_PROGRAM_FILES_COMMONX86\n  , \"TEMPLATES\"   // CSIDL_COMMON_TEMPLATES\n  , \"DOCUMENTS\"   // CSIDL_COMMON_DOCUMENTS\n  , \"ADMINTOOLS\"  // CSIDL_COMMON_ADMINTOOLS\n  , \"ADMINTOOLS\"  // CSIDL_ADMINTOOLS\n  , \"CONNECTIONS\" // +\n  , NULL\n  , NULL\n  , NULL\n  , \"MUSIC\"       // CSIDL_COMMON_MUSIC\n  , \"PICTURES\"    // CSIDL_COMMON_PICTURES\n  , \"VIDEOS\"      // CSIDL_COMMON_VIDEO\n  , \"RESOURCES\"\n  , \"RESOURCES_LOCALIZED\"\n  , \"COMMON_OEM_LINKS\" // +\n  , \"CDBURN_AREA\"\n  , NULL // unused\n  , \"COMPUTERSNEARME\" // +\n};\n\n\nstatic inline void UIntToString(AString &s, UInt32 v)\n{\n  s.Add_UInt32(v);\n}\n\n#ifdef NSIS_SCRIPT\n\nvoid CInArchive::Add_UInt(UInt32 v)\n{\n  char sz[16];\n  ConvertUInt32ToString(v, sz);\n  Script += sz;\n}\n\nstatic void Add_SignedInt(CDynLimBuf &s, Int32 v)\n{\n  char sz[32];\n  ConvertInt64ToString(v, sz);\n  s += sz;\n}\n\nstatic void Add_Hex(CDynLimBuf &s, UInt32 v)\n{\n  char sz[16];\n  sz[0] = '0';\n  sz[1] = 'x';\n  ConvertUInt32ToHex(v, sz + 2);\n  s += sz;\n}\n\nstatic UInt32 GetUi16Str_Len(const Byte *p)\n{\n  const Byte *pp = p;\n  for (; *pp != 0 || *(pp + 1) != 0; pp += 2);\n  return (UInt32)((pp - p) >> 1);\n}\n\nvoid CInArchive::AddLicense(UInt32 param, Int32 langID)\n{\n  Space();\n  if (param >= NumStringChars ||\n      param + 1 >= NumStringChars)\n  {\n    Script += kErrorStr;\n    return;\n  }\n  strUsed[param] = 1;\n\n  const UInt32 start = _stringsPos + (IsUnicode ? param * 2 : param);\n  const UInt32 offset = start + (IsUnicode ? 2 : 1);\n  {\n    FOR_VECTOR (i, LicenseFiles)\n    {\n      const CLicenseFile &lic = LicenseFiles[i];\n      if (offset == lic.Offset)\n      {\n        Script += lic.Name;\n        return;\n      }\n    }\n  }\n  AString fileName (\"[LICENSE]\");\n  if (langID >= 0)\n  {\n    fileName += \"\\\\license-\";\n    // LangId_To_String(fileName, langID);\n    UIntToString(fileName, (UInt32)langID);\n  }\n  else if (++_numRootLicenses > 1)\n  {\n    fileName.Add_Minus();\n    UIntToString(fileName, _numRootLicenses);\n  }\n  const Byte *sz = (_data + start);\n  const unsigned marker = IsUnicode ? Get16(sz) : *sz;\n  const bool isRTF = (marker == 2);\n  fileName += isRTF ? \".rtf\" : \".txt\"; // if (*sz == 1) it's text;\n  Script += fileName;\n\n  CLicenseFile &lic = LicenseFiles.AddNew();\n  lic.Name = fileName;\n  lic.Offset = offset;\n  if (!IsUnicode)\n    lic.Size = (UInt32)strlen((const char *)sz + 1);\n  else\n  {\n    sz += 2;\n    const UInt32 len = GetUi16Str_Len(sz);\n    lic.Size = len * 2;\n    if (isRTF)\n    {\n      lic.Text.Alloc((size_t)len);\n      for (UInt32 i = 0; i < len; i++, sz += 2)\n      {\n        unsigned c = Get16(sz);\n        if (c >= 256)\n          c = '?';\n        lic.Text[i] = (Byte)(c);\n      }\n      lic.Size = len;\n      lic.Offset = 0;\n    }\n  }\n}\n\n#endif\n\n\n#ifdef NSIS_SCRIPT\n#define Z7_NSIS_WIN_GENERIC_READ    ((UInt32)1 << 31)\n#endif\n#define Z7_NSIS_WIN_GENERIC_WRITE   ((UInt32)1 << 30)\n#ifdef NSIS_SCRIPT\n#define Z7_NSIS_WIN_GENERIC_EXECUTE ((UInt32)1 << 29)\n#define Z7_NSIS_WIN_GENERIC_ALL     ((UInt32)1 << 28)\n#endif\n\n#ifdef NSIS_SCRIPT\n#define Z7_NSIS_WIN_CREATE_NEW        1\n#endif\n#define Z7_NSIS_WIN_CREATE_ALWAYS     2\n#ifdef NSIS_SCRIPT\n#define Z7_NSIS_WIN_OPEN_EXISTING     3\n#define Z7_NSIS_WIN_OPEN_ALWAYS       4\n#define Z7_NSIS_WIN_TRUNCATE_EXISTING 5\n#endif\n\n\n// #define kVar_CMDLINE    20\n#define kVar_INSTDIR    21\n#define kVar_OUTDIR     22\n#define kVar_EXEDIR     23\n// #define kVar_LANGUAGE   24\n#define kVar_TEMP       25\n#define kVar_PLUGINSDIR 26\n#define kVar_EXEPATH    27  // NSIS 2.26+\n// #define kVar_EXEFILE    28  // NSIS 2.26+\n\n#define kVar_HWNDPARENT_225 27\n#ifdef NSIS_SCRIPT\n#define kVar_HWNDPARENT     29\n#endif\n\n// #define kVar__CLICK 30\n#define kVar_Spec_OUTDIR_225  29  // NSIS 2.04 - 2.25\n#define kVar_Spec_OUTDIR      31  // NSIS 2.26+\n\n\nstatic const char * const kVarStrings[] =\n{\n    \"CMDLINE\"\n  , \"INSTDIR\"\n  , \"OUTDIR\"\n  , \"EXEDIR\"\n  , \"LANGUAGE\"\n  , \"TEMP\"\n  , \"PLUGINSDIR\"\n  , \"EXEPATH\"   // NSIS 2.26+\n  , \"EXEFILE\"   // NSIS 2.26+\n  , \"HWNDPARENT\"\n  , \"_CLICK\"    // is set from page->clicknext\n  , \"_OUTDIR\"   // NSIS 2.04+\n};\n\nstatic const unsigned kNumInternalVars = 20 + Z7_ARRAY_SIZE(kVarStrings);\n\n#define GET_NUM_INTERNAL_VARS (IsNsis200 ? kNumInternalVars - 3 : IsNsis225 ? kNumInternalVars - 2 : kNumInternalVars)\n\nvoid CInArchive::GetVar2(AString &res, UInt32 index)\n{\n  if (index < 20)\n  {\n    if (index >= 10)\n    {\n      res += 'R';\n      index -= 10;\n    }\n    UIntToString(res, index);\n  }\n  else\n  {\n    unsigned numInternalVars = GET_NUM_INTERNAL_VARS;\n    if (index < numInternalVars)\n    {\n      if (IsNsis225 && index >= kVar_EXEPATH)\n        index += 2;\n      res += kVarStrings[index - 20];\n    }\n    else\n    {\n      res += '_';\n      UIntToString(res, index - numInternalVars);\n      res += '_';\n    }\n  }\n}\n\nvoid CInArchive::GetVar(AString &res, UInt32 index)\n{\n  res += '$';\n  GetVar2(res, index);\n}\n\n#ifdef NSIS_SCRIPT\n\nvoid CInArchive::Add_Var(UInt32 index)\n{\n  _tempString_for_GetVar.Empty();\n  GetVar(_tempString_for_GetVar, index);\n  Script += _tempString_for_GetVar;\n}\n\nvoid CInArchive::AddParam_Var(UInt32 index)\n{\n  Space();\n  Add_Var(index);\n}\n\nvoid CInArchive::AddParam_UInt(UInt32 value)\n{\n  Space();\n  Add_UInt(value);\n}\n\n#endif\n\n\n#define NS_CODE_SKIP    252\n#define NS_CODE_VAR     253\n#define NS_CODE_SHELL   254\n// #define NS_CODE_LANG    255\n\n// #define NS_3_CODE_LANG  1\n#define NS_3_CODE_SHELL 2\n#define NS_3_CODE_VAR   3\n#define NS_3_CODE_SKIP  4\n\n#define PARK_CODE_SKIP  0xE000\n#define PARK_CODE_VAR   0xE001\n#define PARK_CODE_SHELL 0xE002\n#define PARK_CODE_LANG  0xE003\n\n#define IS_NS_SPEC_CHAR(c) ((c) >= NS_CODE_SKIP)\n#define IS_PARK_SPEC_CHAR(c) ((c) >= PARK_CODE_SKIP && (c) <= PARK_CODE_LANG)\n\n#define DECODE_NUMBER_FROM_2_CHARS(c0, c1) (((unsigned)(c0) & 0x7F) | (((unsigned)((c1) & 0x7F)) << 7))\n#define CONVERT_NUMBER_NS_3_UNICODE(n) n = ((n & 0x7F) | (((n >> 8) & 0x7F) << 7))\n#define CONVERT_NUMBER_PARK(n) n &= 0x7FFF\n\n\nstatic bool AreStringsEqual_16and8(const Byte *p16, const char *p8)\n{\n  for (;;)\n  {\n    unsigned c16 = Get16(p16); p16 += 2;\n    unsigned c = (Byte)(*p8++);\n    if (c16 != c)\n      return false;\n    if (c == 0)\n      return true;\n  }\n}\n\nvoid CInArchive::GetShellString(AString &s, unsigned index1, unsigned index2)\n{\n  // zeros are not allowed here.\n  // if (index1 == 0 || index2 == 0) throw 333;\n\n  if ((index1 & 0x80) != 0)\n  {\n    unsigned offset = (index1 & 0x3F);\n\n    /* NSIS reads registry string:\n         keyName   = HKLM Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\n         mask      = KEY_WOW64_64KEY, If 64-bit flag in index1 is set\n         valueName = string(offset)\n       If registry reading is failed, NSIS uses second parameter (index2)\n       to read string. The recursion is possible in that case in NSIS.\n       We don't parse index2 string. We only set strUsed status for that\n       string (but without recursion). */\n\n    if (offset >= NumStringChars)\n    {\n      s += kErrorStr;\n      return;\n    }\n    \n    #ifdef NSIS_SCRIPT\n    strUsed[offset] = 1;\n    if (index2 < NumStringChars)\n      strUsed[index2] = 1;\n    #endif\n\n    const Byte *p = (const Byte *)(_data + _stringsPos);\n    int id = -1;\n    if (IsUnicode)\n    {\n      p += offset * 2;\n      if (AreStringsEqual_16and8(p, \"ProgramFilesDir\"))\n        id = 0;\n      else if (AreStringsEqual_16and8(p, \"CommonFilesDir\"))\n        id = 1;\n    }\n    else\n    {\n      p += offset;\n      if (strcmp((const char *)p, \"ProgramFilesDir\") == 0)\n        id = 0;\n      else if (strcmp((const char *)p, \"CommonFilesDir\") == 0)\n        id = 1;\n    }\n\n    s += ((id >= 0) ? (id == 0 ? \"$PROGRAMFILES\" : \"$COMMONFILES\") :\n      \"$_ERROR_UNSUPPORTED_VALUE_REGISTRY_\");\n    // s += ((index1 & 0x40) != 0) ? \"64\" : \"32\";\n    if ((index1 & 0x40) != 0)\n      s += \"64\";\n\n    if (id < 0)\n    {\n      s += '(';\n      if (IsUnicode)\n      {\n        for (unsigned i = 0; i < 256; i++)\n        {\n          wchar_t c = Get16(p + i * 2);\n          if (c == 0)\n            break;\n          if (c < 0x80)\n            s += (char)c;\n        }\n      }\n      else\n        s += (const char *)p;\n      s += ')';\n    }\n    return;\n  }\n\n  s += '$';\n  if (index1 < Z7_ARRAY_SIZE(kShellStrings))\n  {\n    const char *sz = kShellStrings[index1];\n    if (sz)\n    {\n      s += sz;\n      return;\n    }\n  }\n  if (index2 < Z7_ARRAY_SIZE(kShellStrings))\n  {\n    const char *sz = kShellStrings[index2];\n    if (sz)\n    {\n      s += sz;\n      return;\n    }\n  }\n  s += \"_ERROR_UNSUPPORTED_SHELL_\";\n  s += '[';\n  UIntToString(s, index1);\n  s += ',';\n  UIntToString(s, index2);\n  s += ']';\n}\n\n#ifdef NSIS_SCRIPT\n\nvoid CInArchive::Add_LangStr_Simple(UInt32 id)\n{\n  Script += \"LSTR_\";\n  Add_UInt(id);\n}\n\n#endif\n\nvoid CInArchive::Add_LangStr(AString &res, UInt32 id)\n{\n  #ifdef NSIS_SCRIPT\n  langStrIDs.Add(id);\n  #endif\n  res += \"$(LSTR_\";\n  UIntToString(res, id);\n  res += ')';\n}\n\nvoid CInArchive::GetNsisString_Raw(const Byte *s)\n{\n  Raw_AString.Empty();\n\n  if (NsisType != k_NsisType_Nsis3)\n  {\n    for (;;)\n    {\n      Byte c = *s++;\n      if (c == 0)\n        return;\n      if (IS_NS_SPEC_CHAR(c))\n      {\n        Byte c0 = *s++;\n        if (c0 == 0)\n          return;\n        if (c != NS_CODE_SKIP)\n        {\n          Byte c1 = *s++;\n          if (c1 == 0)\n            return;\n          \n          if (c == NS_CODE_SHELL)\n            GetShellString(Raw_AString, c0, c1);\n          else\n          {\n            unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);\n            if (c == NS_CODE_VAR)\n              GetVar(Raw_AString, n);\n            else //  if (c == NS_CODE_LANG)\n              Add_LangStr(Raw_AString, n);\n          }\n          continue;\n        }\n        c = c0;\n      }\n      Raw_AString += (char)c;\n    }\n  }\n\n  // NSIS-3 ANSI\n  for (;;)\n  {\n    Byte c = *s++;\n    if (c <= NS_3_CODE_SKIP)\n    {\n      if (c == 0)\n        return;\n      Byte c0 = *s++;\n      if (c0 == 0)\n        return;\n      if (c != NS_3_CODE_SKIP)\n      {\n        Byte c1 = *s++;\n        if (c1 == 0)\n          return;\n        \n        if (c == NS_3_CODE_SHELL)\n          GetShellString(Raw_AString, c0, c1);\n        else\n        {\n          unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);\n          if (c == NS_3_CODE_VAR)\n            GetVar(Raw_AString, n);\n          else // if (c == NS_3_CODE_LANG)\n            Add_LangStr(Raw_AString, n);\n        }\n        continue;\n      }\n      c = c0;\n    }\n    Raw_AString += (char)c;\n  }\n}\n\n#ifdef NSIS_SCRIPT\n\nvoid CInArchive::GetNsisString(AString &res, const Byte *s)\n{\n  for (;;)\n  {\n    Byte c = *s++;\n    if (c == 0)\n      return;\n    if (NsisType != k_NsisType_Nsis3)\n    {\n      if (IS_NS_SPEC_CHAR(c))\n      {\n        Byte c0 = *s++;\n        if (c0 == 0)\n          return;\n        if (c != NS_CODE_SKIP)\n        {\n          Byte c1 = *s++;\n          if (c1 == 0)\n            return;\n          if (c == NS_CODE_SHELL)\n            GetShellString(res, c0, c1);\n          else\n          {\n            unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);\n            if (c == NS_CODE_VAR)\n              GetVar(res, n);\n            else // if (c == NS_CODE_LANG)\n              Add_LangStr(res, n);\n          }\n          continue;\n        }\n        c = c0;\n      }\n    }\n    else\n    {\n      // NSIS-3 ANSI\n      if (c <= NS_3_CODE_SKIP)\n      {\n        Byte c0 = *s++;\n        if (c0 == 0)\n          return;\n        if (c0 == 0)\n          break;\n        if (c != NS_3_CODE_SKIP)\n        {\n          Byte c1 = *s++;\n          if (c1 == 0)\n            return;\n          if (c == NS_3_CODE_SHELL)\n            GetShellString(res, c0, c1);\n          else\n          {\n            unsigned n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);\n            if (c == NS_3_CODE_VAR)\n              GetVar(res, n);\n            else // if (c == NS_3_CODE_LANG)\n              Add_LangStr(res, n);\n          }\n          continue;\n        }\n        c = c0;\n      }\n    }\n\n    {\n      const char *e;\n           if (c ==   9) e = \"$\\\\t\";\n      else if (c ==  10) e = \"$\\\\n\";\n      else if (c ==  13) e = \"$\\\\r\";\n      else if (c == '\"') e = \"$\\\\\\\"\";\n      else if (c == '$') e = \"$$\";\n      else\n      {\n        res += (char)c;\n        continue;\n      }\n      res += e;\n      continue;\n    }\n  }\n}\n\n#endif\n\nvoid CInArchive::GetNsisString_Unicode_Raw(const Byte *p)\n{\n  Raw_UString.Empty();\n\n  if (IsPark())\n  {\n    for (;;)\n    {\n      unsigned c = Get16(p);\n      p += 2;\n      if (c == 0)\n        break;\n      if (c < 0x80)\n      {\n        Raw_UString.Add_Char((char)c);\n        continue;\n      }\n      \n      if (IS_PARK_SPEC_CHAR(c))\n      {\n        unsigned n = Get16(p);\n        p += 2;\n        if (n == 0)\n          break;\n        if (c != PARK_CODE_SKIP)\n        {\n          Raw_AString.Empty();\n          if (c == PARK_CODE_SHELL)\n            GetShellString(Raw_AString, n & 0xFF, n >> 8);\n          else\n          {\n            CONVERT_NUMBER_PARK(n);\n            if (c == PARK_CODE_VAR)\n              GetVar(Raw_AString, n);\n            else // if (c == PARK_CODE_LANG)\n              Add_LangStr(Raw_AString, n);\n          }\n          Raw_UString += Raw_AString.Ptr(); // check it !\n          continue;\n        }\n        c = n;\n      }\n      \n      Raw_UString += (wchar_t)c;\n    }\n    \n    return;\n  }\n\n  // NSIS-3 Unicode\n  for (;;)\n  {\n    unsigned c = Get16(p);\n    p += 2;\n    if (c > NS_3_CODE_SKIP)\n    {\n      Raw_UString += (wchar_t)c;\n      continue;\n    }\n    if (c == 0)\n      break;\n\n    unsigned n = Get16(p);\n    p += 2;\n    if (n == 0)\n      break;\n    if (c == NS_3_CODE_SKIP)\n    {\n      Raw_UString += (wchar_t)n;\n      continue;\n    }\n\n    Raw_AString.Empty();\n    if (c == NS_3_CODE_SHELL)\n      GetShellString(Raw_AString, n & 0xFF, n >> 8);\n    else\n    {\n      CONVERT_NUMBER_NS_3_UNICODE(n);\n      if (c == NS_3_CODE_VAR)\n        GetVar(Raw_AString, n);\n      else // if (c == NS_3_CODE_LANG)\n        Add_LangStr(Raw_AString, n);\n    }\n    Raw_UString += Raw_AString.Ptr();\n  }\n}\n\n#ifdef NSIS_SCRIPT\n\nstatic const Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };\n\nvoid CInArchive::GetNsisString_Unicode(AString &res, const Byte *p)\n{\n  for (;;)\n  {\n    unsigned c = Get16(p);\n    p += 2;\n    if (c == 0)\n      break;\n    if (IsPark())\n    {\n      if (IS_PARK_SPEC_CHAR(c))\n      {\n        unsigned n = Get16(p);\n        p += 2;\n        if (n == 0)\n          break;\n        if (c != PARK_CODE_SKIP)\n        {\n          if (c == PARK_CODE_SHELL)\n            GetShellString(res, n & 0xFF, n >> 8);\n          else\n          {\n            CONVERT_NUMBER_PARK(n);\n            if (c == PARK_CODE_VAR)\n              GetVar(res, n);\n            else // if (c == PARK_CODE_LANG)\n              Add_LangStr(res, n);\n          }\n          continue;\n        }\n        c = n;\n      }\n    }\n    else\n    {\n      // NSIS-3 Unicode\n      if (c <= NS_3_CODE_SKIP)\n      {\n        unsigned n = Get16(p);\n        p += 2;\n        if (n == 0)\n          break;\n        if (c != NS_3_CODE_SKIP)\n        {\n          if (c == NS_3_CODE_SHELL)\n            GetShellString(res, n & 0xFF, n >> 8);\n          else\n          {\n            CONVERT_NUMBER_NS_3_UNICODE(n);\n            if (c == NS_3_CODE_VAR)\n              GetVar(res, n);\n            else // if (c == NS_3_CODE_LANG)\n              Add_LangStr(res, n);\n          }\n          continue;\n        }\n        c = n;\n      }\n    }\n\n    if (c < 0x80)\n    {\n      const char *e;\n           if (c ==   9) e = \"$\\\\t\";\n      else if (c ==  10) e = \"$\\\\n\";\n      else if (c ==  13) e = \"$\\\\r\";\n      else if (c == '\"') e = \"$\\\\\\\"\";\n      else if (c == '$') e = \"$$\";\n      else\n      {\n        res += (char)c;\n        continue;\n      }\n      res += e;\n      continue;\n    }\n\n    UInt32 value = c;\n    /*\n    if (value >= 0xD800 && value < 0xE000)\n    {\n      UInt32 c2;\n      if (value >= 0xDC00 || srcPos == srcLen)\n        break;\n      c2 = src[srcPos++];\n      if (c2 < 0xDC00 || c2 >= 0xE000)\n        break;\n      value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;\n    }\n    */\n    unsigned numAdds;\n    for (numAdds = 1; numAdds < 5; numAdds++)\n      if (value < (((UInt32)1) << (numAdds * 5 + 6)))\n        break;\n    res += (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));\n    do\n    {\n      numAdds--;\n      res += (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));\n      // destPos++;\n    }\n    while (numAdds != 0);\n\n    // AddToUtf8(res, c);\n  }\n}\n\n#endif\n\nvoid CInArchive::ReadString2_Raw(UInt32 pos)\n{\n  Raw_AString.Empty();\n  Raw_UString.Empty();\n  if ((Int32)pos < 0)\n    Add_LangStr(Raw_AString, (UInt32)-((Int32)pos + 1));\n  else if (pos >= NumStringChars)\n  {\n    Raw_AString += kErrorStr;\n    // UIntToString(Raw_AString, pos);\n  }\n  else\n  {\n    if (IsUnicode)\n      GetNsisString_Unicode_Raw(_data + _stringsPos + pos * 2);\n    else\n      GetNsisString_Raw(_data + _stringsPos + pos);\n    return;\n  }\n  Raw_UString = Raw_AString.Ptr();\n}\n\nbool CInArchive::IsGoodString(UInt32 param) const\n{\n  if (param >= NumStringChars)\n    return false;\n  if (param == 0)\n    return true;\n  const Byte *p = _data + _stringsPos;\n  unsigned c;\n  if (IsUnicode)\n    c = Get16(p + param * 2 - 2);\n  else\n    c = p[param - 1];\n  // some files have '\\\\' character before string?\n  return (c == 0 || c == '\\\\');\n}\n\nbool CInArchive::AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const\n{\n  if (param1 == param2)\n    return true;\n\n  /* NSIS-3.0a1 probably contains bug, so it can use 2 different strings\n     with same content. So we check real string also.\n     Also it's possible to check identical postfix parts of strings. */\n\n  if (param1 >= NumStringChars ||\n      param2 >= NumStringChars)\n    return false;\n\n  const Byte *p = _data + _stringsPos;\n\n  if (IsUnicode)\n  {\n    const Byte *p1 = p + param1 * 2;\n    const Byte *p2 = p + param2 * 2;\n    for (;;)\n    {\n      UInt16 c = Get16(p1);\n      if (c != Get16(p2))\n        return false;\n      if (c == 0)\n        return true;\n      p1 += 2;\n      p2 += 2;\n    }\n  }\n  else\n  {\n    const Byte *p1 = p + param1;\n    const Byte *p2 = p + param2;\n    for (;;)\n    {\n      Byte c = *p1++;\n      if (c != *p2++)\n        return false;\n      if (c == 0)\n        return true;\n    }\n  }\n}\n\n#ifdef NSIS_SCRIPT\n\nUInt32 CInArchive::GetNumUsedVars() const\n{\n  UInt32 numUsedVars = 0;\n  const Byte *data = (const Byte *)_data + _stringsPos;\n  unsigned npi = 0;\n  for (UInt32 i = 0; i < NumStringChars;)\n  {\n    bool process = true;\n    if (npi < noParseStringIndexes.Size() && noParseStringIndexes[npi] == i)\n    {\n      process = false;\n      npi++;\n    }\n    \n    if (IsUnicode)\n    {\n      if (IsPark())\n      {\n        for (;;)\n        {\n          unsigned c = Get16(data + i * 2);\n          i++;\n          if (c == 0)\n            break;\n          if (IS_PARK_SPEC_CHAR(c))\n          {\n            UInt32 n = Get16(data + i * 2);\n            i++;\n            if (n == 0)\n              break;\n            if (process && c == PARK_CODE_VAR)\n            {\n              CONVERT_NUMBER_PARK(n);\n              n++;\n              if (numUsedVars < n)\n                numUsedVars = n;\n            }\n          }\n        }\n      }\n      else // NSIS-3 Unicode\n      {\n        for (;;)\n        {\n          unsigned c = Get16(data + i * 2);\n          i++;\n          if (c == 0)\n            break;\n          if (c > NS_3_CODE_SKIP)\n            continue;\n          UInt32 n = Get16(data + i * 2);\n          i++;\n          if (n == 0)\n            break;\n          if (process && c == NS_3_CODE_VAR)\n          {\n            CONVERT_NUMBER_NS_3_UNICODE(n);\n            n++;\n            if (numUsedVars < n)\n              numUsedVars = n;\n          }\n        }\n      }\n    }\n    else // not Unicode (ANSI)\n    {\n      if (NsisType != k_NsisType_Nsis3)\n      {\n        for (;;)\n        {\n          Byte c = data[i++];\n          if (c == 0)\n            break;\n          if (IS_NS_SPEC_CHAR(c))\n          {\n            Byte c0 = data[i++];\n            if (c0 == 0)\n              break;\n            if (c == NS_CODE_SKIP)\n              continue;\n            Byte c1 = data[i++];\n            if (c1 == 0)\n              break;\n            if (process && c == NS_CODE_VAR)\n            {\n              UInt32 n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);\n              n++;\n              if (numUsedVars < n)\n                numUsedVars = n;\n            }\n          }\n        }\n      }\n      else\n      {\n        // NSIS-3 ANSI\n        for (;;)\n        {\n          Byte c = data[i++];\n          if (c == 0)\n            break;\n          if (c > NS_3_CODE_SKIP)\n            continue;\n\n          Byte c0 = data[i++];\n          if (c0 == 0)\n            break;\n          if (c == NS_3_CODE_SKIP)\n            continue;\n          Byte c1 = data[i++];\n          if (c1 == 0)\n            break;\n          if (process && c == NS_3_CODE_VAR)\n          {\n            UInt32 n = DECODE_NUMBER_FROM_2_CHARS(c0, c1);\n            n++;\n            if (numUsedVars < n)\n              numUsedVars = n;\n          }\n        }\n      }\n    }\n  }\n  return numUsedVars;\n}\n\nvoid CInArchive::ReadString2(AString &s, UInt32 pos)\n{\n  if ((Int32)pos < 0)\n  {\n    Add_LangStr(s, (UInt32)-((Int32)pos + 1));\n    return;\n  }\n\n  if (pos >= NumStringChars)\n  {\n    s += kErrorStr;\n    // UIntToString(s, pos);\n    return;\n  }\n\n  #ifdef NSIS_SCRIPT\n  strUsed[pos] = 1;\n  #endif\n\n  if (IsUnicode)\n    GetNsisString_Unicode(s, _data + _stringsPos + pos * 2);\n  else\n    GetNsisString(s, _data + _stringsPos + pos);\n}\n\n#endif\n\n#ifdef NSIS_SCRIPT\n\n// #define DEL_DIR     1\n#define DEL_RECURSE 2\n#define DEL_REBOOT  4\n// #define DEL_SIMPLE  8\n\nvoid CInArchive::AddRegRoot(UInt32 val)\n{\n  Space();\n  const char *s;\n  switch (val)\n  {\n    case 0:  s = \"SHCTX\"; break;\n    case 0x80000000:  s = \"HKCR\"; break;\n    case 0x80000001:  s = \"HKCU\"; break;\n    case 0x80000002:  s = \"HKLM\"; break;\n    case 0x80000003:  s = \"HKU\";  break;\n    case 0x80000004:  s = \"HKPD\"; break;\n    case 0x80000005:  s = \"HKCC\"; break;\n    case 0x80000006:  s = \"HKDD\"; break;\n    case 0x80000050:  s = \"HKPT\"; break;\n    case 0x80000060:  s = \"HKPN\"; break;\n    default:\n      // Script += \" RRRRR \";\n      // throw 1;\n      Add_Hex(Script, val); return;\n  }\n  Script += s;\n}\n\nstatic const char * const g_WinAttrib[] =\n{\n    \"READONLY\"\n  , \"HIDDEN\"\n  , \"SYSTEM\"\n  , NULL\n  , \"DIRECTORY\"\n  , \"ARCHIVE\"\n  , \"DEVICE\"\n  , \"NORMAL\"\n  , \"TEMPORARY\"\n  , \"SPARSE_FILE\"\n  , \"REPARSE_POINT\"\n  , \"COMPRESSED\"\n  , \"OFFLINE\"\n  , \"NOT_CONTENT_INDEXED\"\n  , \"ENCRYPTED\"\n  , NULL\n  , \"VIRTUAL\"\n};\n\n#define FLAGS_DELIMITER '|'\n\nstatic void FlagsToString2(CDynLimBuf &s, const char * const *table, unsigned num, UInt32 flags)\n{\n  bool filled = false;\n  for (unsigned i = 0; i < num; i++)\n  {\n    UInt32 f = (UInt32)1 << i;\n    if ((flags & f) != 0)\n    {\n      const char *name = table[i];\n      if (name)\n      {\n        if (filled)\n          s += FLAGS_DELIMITER;\n        filled = true;\n        s += name;\n        flags &= ~f;\n      }\n    }\n  }\n  if (flags != 0)\n  {\n    if (filled)\n      s += FLAGS_DELIMITER;\n    Add_Hex(s, flags);\n  }\n}\n\nstatic bool DoesNeedQuotes(const char *s)\n{\n  {\n    char c = s[0];\n    if (c == 0 || c == '#' || c == ';' || (c == '/' && s[1] == '*'))\n      return true;\n  }\n  for (;;)\n  {\n    char c = *s++;\n    if (c == 0)\n      return false;\n    if (c == ' ')\n      return true;\n  }\n}\n\nvoid CInArchive::Add_QuStr(const AString &s)\n{\n  bool needQuotes = DoesNeedQuotes(s);\n  if (needQuotes)\n    Script += '\\\"';\n  Script += s;\n  if (needQuotes)\n    Script += '\\\"';\n}\n\nvoid CInArchive::SpaceQuStr(const AString &s)\n{\n  Space();\n  Add_QuStr(s);\n}\n\nvoid CInArchive::AddParam(UInt32 pos)\n{\n  _tempString.Empty();\n  ReadString2(_tempString, pos);\n  SpaceQuStr(_tempString);\n}\n\nvoid CInArchive::AddParams(const UInt32 *params, unsigned num)\n{\n  for (unsigned i = 0; i < num; i++)\n    AddParam(params[i]);\n}\n\nvoid CInArchive::AddOptionalParam(UInt32 pos)\n{\n  if (pos != 0)\n    AddParam(pos);\n}\n\nstatic unsigned GetNumParams(const UInt32 *params, unsigned num)\n{\n  for (; num > 0 && params[num - 1] == 0; num--);\n  return num;\n}\n \nvoid CInArchive::AddOptionalParams(const UInt32 *params, unsigned num)\n{\n  AddParams(params, GetNumParams(params, num));\n}\n\n\nstatic const UInt32 CMD_REF_Goto    = (1 << 0);\nstatic const UInt32 CMD_REF_Call    = (1 << 1);\nstatic const UInt32 CMD_REF_Pre     = (1 << 2);\nstatic const UInt32 CMD_REF_Show    = (1 << 3);\nstatic const UInt32 CMD_REF_Leave   = (1 << 4);\nstatic const UInt32 CMD_REF_OnFunc  = (1 << 5);\nstatic const UInt32 CMD_REF_Section = (1 << 6);\nstatic const UInt32 CMD_REF_InitPluginDir = (1 << 7);\n// static const UInt32 CMD_REF_Creator = (1 << 5); // CMD_REF_Pre is used instead\nstatic const unsigned CMD_REF_OnFunc_NumShifts = 28; // it uses for onFunc too\nstatic const unsigned CMD_REF_Page_NumShifts = 16; // it uses for onFunc too\nstatic const UInt32 CMD_REF_Page_Mask   = 0x0FFF0000;\nstatic const UInt32 CMD_REF_OnFunc_Mask = 0xF0000000;\n\ninline bool IsPageFunc(UInt32 flag)\n{\n  return (flag & (CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave)) != 0;\n}\n\ninline bool IsFunc(UInt32 flag)\n{\n  // return (flag & (CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave | CMD_REF_OnFunc)) != 0;\n  return (flag & (CMD_REF_Call | CMD_REF_Pre | CMD_REF_Show | CMD_REF_Leave | CMD_REF_OnFunc)) != 0;\n}\n\ninline bool IsProbablyEndOfFunc(UInt32 flag)\n{\n  return (flag != 0 && flag != CMD_REF_Goto);\n}\n\nstatic const char * const kOnFunc[] =\n{\n    \"Init\"\n  , \"InstSuccess\"\n  , \"InstFailed\"\n  , \"UserAbort\"\n  , \"GUIInit\"\n  , \"GUIEnd\"\n  , \"MouseOverSection\"\n  , \"VerifyInstDir\"\n  , \"SelChange\"\n  , \"RebootFailed\"\n};\n\nvoid CInArchive::Add_FuncName(const UInt32 *labels, UInt32 index)\n{\n  UInt32 mask = labels[index];\n  if (mask & CMD_REF_OnFunc)\n  {\n    Script += \".on\";\n    Script += kOnFunc[labels[index] >> CMD_REF_OnFunc_NumShifts];\n  }\n  else if (mask & CMD_REF_InitPluginDir)\n  {\n    /*\n    if (!IsInstaller)\n      Script += \"un.\"\n    */\n    Script += \"Initialize_____Plugins\";\n  }\n  else\n  {\n    Script += \"func_\";\n    Add_UInt(index);\n  }\n}\n\nvoid CInArchive::AddParam_Func(const UInt32 *labels, UInt32 index)\n{\n  Space();\n  if ((Int32)index >= 0)\n    Add_FuncName(labels, index);\n  else\n    AddQuotes();\n}\n\n\nvoid CInArchive::Add_LabelName(UInt32 index)\n{\n  Script += \"label_\";\n  Add_UInt(index);\n}\n\n// param != 0\nvoid CInArchive::Add_GotoVar(UInt32 param)\n{\n  Space();\n  if ((Int32)param < 0)\n    Add_Var((UInt32)-((Int32)param + 1));\n  else\n    Add_LabelName(param - 1);\n}\n\nvoid CInArchive::Add_GotoVar1(UInt32 param)\n{\n  if (param == 0)\n    Script += \" 0\";\n  else\n    Add_GotoVar(param);\n}\n\nvoid CInArchive::Add_GotoVars2(const UInt32 *params)\n{\n  Add_GotoVar1(params[0]);\n  if (params[1] != 0)\n    Add_GotoVar(params[1]);\n}\n\nstatic bool NoLabels(const UInt32 *labels, UInt32 num)\n{\n  for (UInt32 i = 0; i < num; i++)\n    if (labels[i] != 0)\n      return false;\n  return true;\n}\n\nstatic const char * const k_REBOOTOK = \" /REBOOTOK\";\n\n#define Z7_NSIS_WIN_MB_ABORTRETRYIGNORE 2\n#define Z7_NSIS_WIN_MB_RETRYCANCEL      5\n\nstatic const char * const k_MB_Buttons[] =\n{\n    \"OK\"\n  , \"OKCANCEL\"\n  , \"ABORTRETRYIGNORE\"\n  , \"YESNOCANCEL\"\n  , \"YESNO\"\n  , \"RETRYCANCEL\"\n  , \"CANCELTRYCONTINUE\"\n};\n\n#define Z7_NSIS_WIN_MB_ICONSTOP   (1 << 4)\n\nstatic const char * const k_MB_Icons[] =\n{\n    NULL\n  , \"ICONSTOP\"\n  , \"ICONQUESTION\"\n  , \"ICONEXCLAMATION\"\n  , \"ICONINFORMATION\"\n};\n\nstatic const char * const k_MB_Flags[] =\n{\n    \"HELP\"\n  , \"NOFOCUS\"\n  , \"SETFOREGROUND\"\n  , \"DEFAULT_DESKTOP_ONLY\"\n  , \"TOPMOST\"\n  , \"RIGHT\"\n  , \"RTLREADING\"\n  // , \"SERVICE_NOTIFICATION\" // unsupported. That bit is used for NSIS purposes\n};\n\n#define Z7_NSIS_WIN_IDCANCEL 2\n#define Z7_NSIS_WIN_IDIGNORE 5\n\nstatic const char * const k_Button_IDs[] =\n{\n    \"0\"\n  , \"IDOK\"\n  , \"IDCANCEL\"\n  , \"IDABORT\"\n  , \"IDRETRY\"\n  , \"IDIGNORE\"\n  , \"IDYES\"\n  , \"IDNO\"\n  , \"IDCLOSE\"\n  , \"IDHELP\"\n  , \"IDTRYAGAIN\"\n  , \"IDCONTINUE\"\n};\n\nvoid CInArchive::Add_ButtonID(UInt32 buttonID)\n{\n  Space();\n  if (buttonID < Z7_ARRAY_SIZE(k_Button_IDs))\n    Script += k_Button_IDs[buttonID];\n  else\n  {\n    Script += \"Button_\";\n    Add_UInt(buttonID);\n  }\n}\n\nbool CInArchive::IsDirectString_Equal(UInt32 offset, const char *s) const\n{\n  if (offset >= NumStringChars)\n    return false;\n  if (IsUnicode)\n    return AreStringsEqual_16and8(_data + _stringsPos + offset * 2, s);\n  else\n    return strcmp((const char *)(const Byte *)_data + _stringsPos + offset, s) == 0;\n}\n\nstatic bool StringToUInt32(const char *s, UInt32 &res)\n{\n  const char *end;\n  if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))\n    res = ConvertHexStringToUInt32(s + 2, &end);\n  else\n    res = ConvertStringToUInt32(s, &end);\n  return (*end == 0);\n}\n\nstatic const unsigned k_CtlColors32_Size = 24;\nstatic const unsigned k_CtlColors64_Size = 28;\n\n#define GET_CtlColors_SIZE(is64) ((is64) ? k_CtlColors64_Size : k_CtlColors32_Size)\n\nstruct CNsis_CtlColors\n{\n  UInt32 text; // COLORREF\n  UInt32 bkc;  // COLORREF\n  UInt32 lbStyle;\n  UInt32 bkb; // HBRUSH\n  Int32 bkmode;\n  Int32 flags;\n  UInt32 bkb_hi32;\n\n  void Parse(const Byte *p, bool is64);\n};\n\nvoid CNsis_CtlColors::Parse(const Byte *p, bool is64)\n{\n  text = Get32(p);\n  bkc = Get32(p + 4);\n  if (is64)\n  {\n    bkb = Get32(p + 8);\n    bkb_hi32 = Get32(p + 12);\n    lbStyle = Get32(p + 16);\n    p += 4;\n  }\n  else\n  {\n    lbStyle = Get32(p + 8);\n    bkb = Get32(p + 12);\n  }\n  bkmode = (Int32)Get32(p + 16);\n  flags = (Int32)Get32(p + 20);\n}\n\n// Win32 constants\n#define Z7_NSIS_WIN_TRANSPARENT 1\n// #define Z7_NSIS_WIN_OPAQUE      2\n\n// text/bg colors\n#define kColorsFlags_TEXT     1\n#define kColorsFlags_TEXT_SYS 2\n#define kColorsFlags_BK       4\n#define kColorsFlags_BK_SYS   8\n#define kColorsFlags_BKB     16\n\nvoid CInArchive::Add_Color2(UInt32 v)\n{\n  v = ((v & 0xFF) << 16) | (v & 0xFF00) | ((v >> 16) & 0xFF);\n  char sz[32];\n  for (int i = 5; i >= 0; i--)\n  {\n    unsigned t = v & 0xF;\n    v >>= 4;\n    sz[i] = (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));\n  }\n  sz[6] = 0;\n  Script += sz;\n}\n\nvoid CInArchive::Add_ColorParam(UInt32 v)\n{\n  Space();\n  Add_Color2(v);\n}\n\nvoid CInArchive::Add_Color(UInt32 v)\n{\n  Script += \"0x\";\n  Add_Color2(v);\n}\n\n#define Z7_NSIS_WIN_SW_HIDE 0\n#define Z7_NSIS_WIN_SW_SHOWNORMAL 1\n\n#define Z7_NSIS_WIN_SW_SHOWMINIMIZED 2\n#define Z7_NSIS_WIN_SW_SHOWMINNOACTIVE 7\n#define Z7_NSIS_WIN_SW_SHOWNA 8\n\nstatic const char * const kShowWindow_Commands[] =\n{\n    \"HIDE\"\n  , \"SHOWNORMAL\"     // \"NORMAL\"\n  , \"SHOWMINIMIZED\"\n  , \"SHOWMAXIMIZED\"  // \"MAXIMIZE\"\n  , \"SHOWNOACTIVATE\"\n  , \"SHOW\"\n  , \"MINIMIZE\"\n  , \"SHOWMINNOACTIVE\"\n  , \"SHOWNA\"\n  , \"RESTORE\"\n  , \"SHOWDEFAULT\"\n  , \"FORCEMINIMIZE\"  // \"MAX\"\n};\n\nstatic void Add_ShowWindow_Cmd_2(AString &s, UInt32 cmd)\n{\n  if (cmd < Z7_ARRAY_SIZE(kShowWindow_Commands))\n  {\n    s += \"SW_\";\n    s += kShowWindow_Commands[cmd];\n  }\n  else\n    UIntToString(s, cmd);\n}\n\nvoid CInArchive::Add_ShowWindow_Cmd(UInt32 cmd)\n{\n  if (cmd < Z7_ARRAY_SIZE(kShowWindow_Commands))\n  {\n    Script += \"SW_\";\n    Script += kShowWindow_Commands[cmd];\n  }\n  else\n    Add_UInt(cmd);\n}\n\nvoid CInArchive::Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type)\n{\n  if (type < tableSize)\n    Script += table[type];\n  else\n  {\n    Script += '_';\n    Add_UInt(type);\n  }\n}\n\n#define ADD_TYPE_FROM_LIST(table, type) Add_TypeFromList(table, Z7_ARRAY_SIZE(table), type)\n\nenum\n{\n  k_ExecFlags_AutoClose,\n  k_ExecFlags_ShellVarContext,\n  k_ExecFlags_Errors,\n  k_ExecFlags_Abort,\n  k_ExecFlags_RebootFlag,\n  k_ExecFlags_reboot_called,\n  k_ExecFlags_cur_insttype,\n  k_ExecFlags_plugin_api_version,\n  k_ExecFlags_Silent,\n  k_ExecFlags_InstDirError,\n  k_ExecFlags_rtl,\n  k_ExecFlags_ErrorLevel,\n  k_ExecFlags_RegView,\n  k_ExecFlags_DetailsPrint = 13\n};\n\n// Names for NSIS exec_flags_t structure vars\nstatic const char * const kExecFlags_VarsNames[] =\n{\n    \"AutoClose\" // autoclose;\n  , \"ShellVarContext\" // all_user_var;\n  , \"Errors\" // exec_error;\n  , \"Abort\" // abort;\n  , \"RebootFlag\" // exec_reboot; // NSIS_SUPPORT_REBOOT\n  , \"reboot_called\" // reboot_called; // NSIS_SUPPORT_REBOOT\n  , \"cur_insttype\" // XXX_cur_insttype; // depreacted\n  , \"plugin_api_version\" // plugin_api_version; // see NSISPIAPIVER_CURR\n                          // used to be XXX_insttype_changed\n  , \"Silent\" // silent; // NSIS_CONFIG_SILENT_SUPPORT\n  , \"InstDirError\" // instdir_error;\n  , \"rtl\" // rtl;\n  , \"ErrorLevel\" // errlvl;\n  , \"RegView\" // alter_reg_view;\n  , \"DetailsPrint\" // status_update;\n};\n\nvoid CInArchive::Add_ExecFlags(UInt32 flagsType)\n{\n  ADD_TYPE_FROM_LIST(kExecFlags_VarsNames, flagsType);\n}\n\n\n// ---------- Page ----------\n\n// page flags\n#define PF_CANCEL_ENABLE 4\n#define PF_LICENSE_FORCE_SELECTION 32\n#define PF_LICENSE_NO_FORCE_SELECTION 64\n#define PF_PAGE_EX 512\n#define PF_DIR_NO_BTN_DISABLE 1024\n/*\n#define PF_LICENSE_SELECTED 1\n#define PF_NEXT_ENABLE 2\n#define PF_BACK_SHOW 8\n#define PF_LICENSE_STREAM 16\n#define PF_NO_NEXT_FOCUS 128\n#define PF_BACK_ENABLE 256\n*/\n\n// page window proc\nenum\n{\n  PWP_LICENSE,\n  PWP_SELCOM,\n  PWP_DIR,\n  PWP_INSTFILES,\n  PWP_UNINST,\n  PWP_COMPLETED,\n  PWP_CUSTOM\n};\n\nstatic const char * const kPageTypes[] =\n{\n    \"license\"\n  , \"components\"\n  , \"directory\"\n  , \"instfiles\"\n  , \"uninstConfirm\"\n  , \"COMPLETED\"\n  , \"custom\"\n};\n\n#define SET_FUNC_REF(x, flag) if ((Int32)(x) >= 0 && (x) < bh.Num) \\\n  { labels[x] = (labels[x] & ~CMD_REF_Page_Mask) | ((flag) | (pageIndex << CMD_REF_Page_NumShifts)); }\n\n// #define IDD_LICENSE  102\n#define IDD_LICENSE_FSRB 108\n#define IDD_LICENSE_FSCB 109\n\nvoid CInArchive::AddPageOption1(UInt32 param, const char *name)\n{\n  if (param == 0)\n    return;\n  TabString(name);\n  AddParam(param);\n  NewLine();\n}\n\nvoid CInArchive::AddPageOption(const UInt32 *params, unsigned num, const char *name)\n{\n  num = GetNumParams(params, num);\n  if (num == 0)\n    return;\n  TabString(name);\n  AddParams(params, num);\n  NewLine();\n}\n\nvoid CInArchive::Separator()\n{\n  AddLF();\n  AddCommentAndString(\"--------------------\");\n  AddLF();\n}\n\nvoid CInArchive::Space()\n{\n  Script += ' ';\n}\n\nvoid CInArchive::Tab()\n{\n  Script += \"  \";\n}\n\nvoid CInArchive::Tab(bool commented)\n{\n  Script += commented ? \"    ; \" : \"  \";\n}\n\nvoid CInArchive::BigSpaceComment()\n{\n  Script += \"    ; \";\n}\n\nvoid CInArchive::SmallSpaceComment()\n{\n  Script += \" ; \";\n}\n\nvoid CInArchive::AddCommentAndString(const char *s)\n{\n  Script += \"; \";\n  Script += s;\n}\n\nvoid CInArchive::AddError(const char *s)\n{\n  BigSpaceComment();\n  Script += \"!!! ERROR: \";\n  Script += s;\n}\n\nvoid CInArchive::AddErrorLF(const char *s)\n{\n  AddError(s);\n  AddLF();\n}\n\nvoid CInArchive::CommentOpen()\n{\n  AddStringLF(\"/*\");\n}\n\nvoid CInArchive::CommentClose()\n{\n  AddStringLF(\"*/\");\n}\n\nvoid CInArchive::AddLF()\n{\n  Script += CR_LF;\n}\n\nvoid CInArchive::AddQuotes()\n{\n  Script += \"\\\"\\\"\";\n}\n\nvoid CInArchive::TabString(const char *s)\n{\n  Tab();\n  Script += s;\n}\n\nvoid CInArchive::AddStringLF(const char *s)\n{\n  Script += s;\n  AddLF();\n}\n\n// ---------- Section ----------\n\nstatic const char * const kSection_VarsNames[] =\n{\n    \"Text\"\n  , \"InstTypes\"\n  , \"Flags\"\n  , \"Code\"\n  , \"CodeSize\"\n  , \"Size\" // size in KB\n};\n\nvoid CInArchive::Add_SectOp(UInt32 opType)\n{\n  ADD_TYPE_FROM_LIST(kSection_VarsNames, opType);\n}\n\nvoid CSection::Parse(const Byte *p)\n{\n  Name = Get32(p);\n  InstallTypes = Get32(p + 4);\n  Flags = Get32(p + 8);\n  StartCmdIndex = Get32(p + 12);\n  NumCommands = Get32(p + 16);\n  SizeKB = Get32(p + 20);\n}\n\n// used for section->flags\n#define SF_SELECTED   (1 << 0)\n#define SF_SECGRP     (1 << 1)\n#define SF_SECGRPEND  (1 << 2)\n#define SF_BOLD       (1 << 3)\n#define SF_RO         (1 << 4)\n#define SF_EXPAND     (1 << 5)\n/*\n#define SF_PSELECTED  (1 << 6)\n#define SF_TOGGLED    (1 << 7)\n#define SF_NAMECHG    (1 << 8)\n*/\n\nbool CInArchive::PrintSectionBegin(const CSection &sect, unsigned index)\n{\n  AString name;\n  if (sect.Flags & SF_BOLD)\n    name += '!';\n  AString s2;\n  ReadString2(s2, sect.Name);\n  if (!IsInstaller)\n  {\n    if (!StringsAreEqualNoCase_Ascii(s2, \"uninstall\"))\n      name += \"un.\";\n  }\n  name += s2;\n  \n  if (sect.Flags & SF_SECGRPEND)\n  {\n    AddStringLF(\"SectionGroupEnd\");\n    return true;\n  }\n\n  if (sect.Flags & SF_SECGRP)\n  {\n    Script += \"SectionGroup\";\n    if (sect.Flags & SF_EXPAND)\n      Script += \" /e\";\n    SpaceQuStr(name);\n    Script += \"    ; Section\";\n    AddParam_UInt(index);\n    NewLine();\n    return true;\n  }\n\n  Script += \"Section\";\n  if ((sect.Flags & SF_SELECTED) == 0)\n    Script += \" /o\";\n  if (!name.IsEmpty())\n    SpaceQuStr(name);\n  \n  /*\n  if (!name.IsEmpty())\n    Script += ' ';\n  else\n  */\n  SmallSpaceComment();\n  Script += \"Section_\";\n  Add_UInt(index);\n\n  /*\n  Script += \" ; flags = \";\n  Add_Hex(Script, sect.Flags);\n  */\n\n  NewLine();\n\n  if (sect.SizeKB != 0)\n  {\n    // probably we must show AddSize, only if there is additional size.\n    Tab();\n    AddCommentAndString(\"AddSize\");\n    AddParam_UInt(sect.SizeKB);\n    AddLF();\n  }\n\n  bool needSectionIn =\n      (sect.Name != 0 && sect.InstallTypes != 0) ||\n      (sect.Name == 0 && sect.InstallTypes != 0xFFFFFFFF);\n  if (needSectionIn || (sect.Flags & SF_RO) != 0)\n  {\n    TabString(\"SectionIn\");\n    UInt32 instTypes = sect.InstallTypes;\n    for (unsigned i = 0; i < 32; i++, instTypes >>= 1)\n      if ((instTypes & 1) != 0)\n      {\n        AddParam_UInt(i + 1);\n      }\n    if ((sect.Flags & SF_RO) != 0)\n      Script += \" RO\";\n    AddLF();\n  }\n  return false;\n}\n\nvoid CInArchive::PrintSectionEnd()\n{\n  AddStringLF(\"SectionEnd\");\n  AddLF();\n}\n\n// static const unsigned kOnFuncShift = 4;\n\nvoid CInArchive::ClearLangComment()\n{\n  langStrIDs.Clear();\n}\n\nvoid CInArchive::PrintNumComment(const char *name, UInt32 value)\n{\n  // size_t len = Script.Len();\n  AddCommentAndString(name);\n  Script += \": \";\n  Add_UInt(value);\n  AddLF();\n  /*\n  len = Script.Len() - len;\n  char sz[16];\n  ConvertUInt32ToString(value, sz);\n  len += MyStringLen(sz);\n  for (; len < 20; len++)\n    Space();\n  AddStringLF(sz);\n  */\n}\n\n\nvoid CInArchive::NewLine()\n{\n  if (!langStrIDs.IsEmpty())\n  {\n    BigSpaceComment();\n    for (unsigned i = 0; i < langStrIDs.Size() && i < 20; i++)\n    {\n      /*\n      if (i != 0)\n        Script += ' ';\n      */\n      UInt32 langStr = langStrIDs[i];\n      if (langStr >= _numLangStrings)\n      {\n        AddError(\"langStr\");\n        break;\n      }\n      UInt32 param = Get32(_mainLang + langStr * 4);\n      if (param != 0)\n        AddParam(param);\n    }\n    ClearLangComment();\n  }\n  AddLF();\n}\n\nstatic const UInt32 kPageSize = 16 * 4;\n\nstatic const char * const k_SetOverwrite_Modes[] =\n{\n    \"on\"\n  , \"off\"\n  , \"try\"\n  , \"ifnewer\"\n  , \"ifdiff\"\n  // \"lastused\"\n};\n\n\nvoid CInArchive::MessageBox_MB_Part(UInt32 param)\n{\n  {\n    UInt32 v = param & 0xF;\n    Script += \" MB_\";\n    if (v < Z7_ARRAY_SIZE(k_MB_Buttons))\n      Script += k_MB_Buttons[v];\n    else\n    {\n      Script += \"Buttons_\";\n      Add_UInt(v);\n    }\n  }\n  {\n    UInt32 icon = (param >> 4) & 0x7;\n    if (icon != 0)\n    {\n      Script += \"|MB_\";\n      if (icon < Z7_ARRAY_SIZE(k_MB_Icons) && k_MB_Icons[icon])\n        Script += k_MB_Icons[icon];\n      else\n      {\n        Script += \"Icon_\";\n        Add_UInt(icon);\n      }\n    }\n  }\n  if ((param & 0x80) != 0)\n    Script += \"|MB_USERICON\";\n  {\n    UInt32 defButton = (param >> 8) & 0xF;\n    if (defButton != 0)\n    {\n      Script += \"|MB_DEFBUTTON\";\n      Add_UInt(defButton + 1);\n    }\n  }\n  {\n    UInt32 modal = (param >> 12) & 0x3;\n    if (modal == 1) Script += \"|MB_SYSTEMMODAL\";\n    else if (modal == 2) Script += \"|MB_TASKMODAL\";\n    else if (modal == 3) Script += \"|0x3000\";\n    UInt32 flags = (param >> 14);\n    for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_MB_Flags); i++)\n      if ((flags & (1 << i)) != 0)\n      {\n        Script += \"|MB_\";\n        Script += k_MB_Flags[i];\n      }\n  }\n}\n\n#define GET_CMD_PARAM(ppp, index) Get32((ppp) + 4 + (index) * 4)\n\nstatic const Byte k_InitPluginDir_Commands[] =\n  { 13, 26, 31, 13, 19, 21, 11, 14, 25, 31, 1, 22, 4, 1 };\n\nbool CInArchive::CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands)\n{\n  for (UInt32 kkk = 0; kkk < numCommands; kkk++, rawCmds += kCmdSize)\n    if (GetCmd(Get32(rawCmds)) != sequence[kkk])\n      return false;\n  return true;\n}\n\n\nstatic const UInt32 kSectionSize_base = 6 * 4;\n// static const UInt32 kSectionSize_8bit = kSectionSize_base + 1024;\n// static const UInt32 kSectionSize_16bit = kSectionSize_base + 1024 * 2;\n// static const UInt32 kSectionSize_16bit_Big = kSectionSize_base + 8196 * 2;\n// 8196 is default string length in NSIS-Unicode since 2.37.3\n\n#endif\n\n\nstatic void AddString(AString &dest, const char *src)\n{\n  dest.Add_Space_if_NotEmpty();\n  dest += src;\n}\n\nAString CInArchive::GetFormatDescription() const\n{\n  AString s (\"NSIS-\");\n  char c;\n  if (IsPark())\n  {\n    s += \"Park-\";\n    c = '1';\n         if (NsisType == k_NsisType_Park2) c = '2';\n    else if (NsisType == k_NsisType_Park3) c = '3';\n  }\n  else\n  {\n    c = '2';\n    if (NsisType == k_NsisType_Nsis3)\n      c = '3';\n  }\n  s += c;\n  if (IsNsis200)\n    s += \".00\";\n  else if (IsNsis225)\n    s += \".25\";\n\n  if (IsUnicode)\n    AddString(s, \"Unicode\");\n  \n  if (Is64Bit)\n    AddString(s, \"64-bit\");\n\n  if (LogCmdIsEnabled)\n    AddString(s, \"log\");\n\n  if (BadCmd >= 0)\n  {\n    AddString(s, \"BadCmd=\");\n    UIntToString(s, (UInt32)BadCmd);\n  }\n  return s;\n}\n\n#ifdef NSIS_SCRIPT\n\nstatic const unsigned kNumAdditionalParkCmds = 3;\n\nunsigned CInArchive::GetNumSupportedCommands() const\n{\n  unsigned numCmds = IsPark() ? (unsigned)kNumCmds : (unsigned)(kNumCmds) - kNumAdditionalParkCmds;\n  if (!LogCmdIsEnabled)\n    numCmds--;\n  if (!IsUnicode)\n    numCmds -= 2;\n  return numCmds;\n}\n\n#endif\n\nUInt32 CInArchive::GetCmd(UInt32 a)\n{\n  if (!IsPark())\n  {\n    if (!LogCmdIsEnabled)\n      return a;\n    if (a < EW_SECTIONSET)\n      return a;\n    if (a == EW_SECTIONSET)\n      return EW_LOG;\n    return a - 1;\n  }\n\n  if (a < EW_REGISTERDLL)\n    return a;\n  if (NsisType >= k_NsisType_Park2)\n  {\n    if (a == EW_REGISTERDLL) return EW_GETFONTVERSION;\n    a--;\n  }\n  if (NsisType >= k_NsisType_Park3)\n  {\n    if (a == EW_REGISTERDLL) return EW_GETFONTNAME;\n    a--;\n  }\n  if (a >= EW_FSEEK)\n  {\n    if (IsUnicode)\n    {\n      if (a == EW_FSEEK) return EW_FPUTWS;\n      if (a == EW_FSEEK + 1) return EW_FPUTWS + 1;\n      a -= 2;\n    }\n    \n    if (a >= EW_SECTIONSET && LogCmdIsEnabled)\n    {\n      if (a == EW_SECTIONSET)\n        return EW_LOG;\n      return a - 1;\n    }\n    if (a == EW_FPUTWS)\n      return EW_FINDPROC;\n    // if (a > EW_FPUTWS) return 0;\n  }\n  return a;\n}\n\nvoid CInArchive::FindBadCmd(const CBlockHeader &bh, const Byte *p)\n{\n  BadCmd = -1;\n  \n  for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)\n  {\n    const UInt32 id = GetCmd(Get32(p));\n    if (id >= kNumCmds)\n      continue;\n    if (BadCmd >= 0 && id >= (unsigned)BadCmd)\n      continue;\n    unsigned i;\n    if (IsNsis3_OrHigher())\n    {\n      if (id == EW_RESERVEDOPCODE)\n      {\n        BadCmd = (int)id;\n        continue;\n      }\n    }\n    else\n    {\n      // if (id == EW_GETLABELADDR || id == EW_GETFUNCTIONADDR)\n      if (id == EW_RESERVEDOPCODE || id == EW_GETOSINFO)\n      {\n        BadCmd = (int)id;\n        continue;\n      }\n    }\n    for (i = 6; i != 0; i--)\n    {\n      const UInt32 param = Get32(p + i * 4);\n      if (param != 0)\n        break;\n    }\n    if (id == EW_FINDPROC && i == 0)\n    {\n      BadCmd = (int)id;\n      continue;\n    }\n    if (k_Commands[id].NumParams < i)\n      BadCmd = (int)id;\n  }\n}\n\n/* We calculate the number of parameters in commands to detect\n   layout of commands. It's not very good way.\n   If you know simpler and more robust way to detect Version and layout,\n   please write to 7-Zip forum */\n\nvoid CInArchive::DetectNsisType(const CBlockHeader &bh, const Byte *p)\n{\n  bool strongPark = false;\n  bool strongNsis = false;\n\n  if (NumStringChars > 2)\n  {\n    const Byte *strData = _data + _stringsPos;\n    if (IsUnicode)\n    {\n      UInt32 num = NumStringChars - 2;\n      for (UInt32 i = 0; i < num; i++)\n      {\n        if (Get16(strData + i * 2) == 0)\n        {\n          unsigned c2 = Get16(strData + 2 + i * 2);\n          // it can be TXT/RTF with marker char (1 or 2). so we must check next char\n          // if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL)\n          if (c2 == NS_3_CODE_VAR)\n          {\n            // 18.06: fixed: is it correct ?\n            // if ((Get16(strData + 3 + i * 2) & 0x8000) != 0)\n            if ((Get16(strData + 4 + i * 2) & 0x8080) == 0x8080)\n            {\n              NsisType = k_NsisType_Nsis3;\n              strongNsis = true;\n              break;\n            }\n          }\n        }\n      }\n      if (!strongNsis)\n      {\n        NsisType = k_NsisType_Park1;\n        strongPark = true;\n      }\n    }\n    else\n    {\n      UInt32 num = NumStringChars - 2;\n      for (UInt32 i = 0; i < num; i++)\n      {\n        if (strData[i] == 0)\n        {\n          Byte c2 = strData[i + 1];\n          // it can be TXT/RTF with marker char (1 or 2). so we must check next char\n          // for marker=1 (txt)\n          if (c2 == NS_3_CODE_VAR)\n            // if (c2 <= NS_3_CODE_SKIP && c2 != NS_3_CODE_SHELL && c2 != 1)\n          {\n            if ((strData[i + 2] & 0x80) != 0)\n            {\n              // const char *p2 = (const char *)(strData + i + 1);\n              // p2 = p2;\n              NsisType = k_NsisType_Nsis3;\n              strongNsis = true;\n              break;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (NsisType == k_NsisType_Nsis2 && !IsUnicode)\n  {\n    const Byte *p2 = p;\n\n    for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize)\n    {\n      UInt32 cmd = GetCmd(Get32(p2));\n      if (cmd != EW_GETDLGITEM &&\n          cmd != EW_ASSIGNVAR)\n        continue;\n      \n      UInt32 params[kNumCommandParams];\n      for (unsigned i = 0; i < kNumCommandParams; i++)\n        params[i] = Get32(p2 + 4 + 4 * i);\n\n      if (cmd == EW_GETDLGITEM)\n      {\n        // we can use also EW_SETCTLCOLORS\n        if (IsVarStr(params[1], kVar_HWNDPARENT_225))\n        {\n          IsNsis225 = true;\n          if (params[0] == kVar_Spec_OUTDIR_225)\n          {\n            IsNsis200 = true;\n            break;\n          }\n        }\n      }\n      else // if (cmd == EW_ASSIGNVAR)\n      {\n        if (params[0] == kVar_Spec_OUTDIR_225 &&\n            params[2] == 0 &&\n            params[3] == 0 &&\n            IsVarStr(params[1], kVar_OUTDIR))\n          IsNsis225 = true;\n      }\n    }\n  }\n\n  bool parkVer_WasDetected = false;\n\n  if (!strongNsis && !IsNsis225 && !IsNsis200)\n  {\n    // it must be before FindBadCmd(bh, p);\n    unsigned mask = 0;\n\n    unsigned numInsertMax = IsUnicode ? 4 : 2;\n\n    const Byte *p2 = p;\n      \n    for (UInt32 kkk = 0; kkk < bh.Num; kkk++, p2 += kCmdSize)\n    {\n      const UInt32 cmd = Get32(p2); // we use original (not converted) command\n\n      if (cmd < EW_WRITEUNINSTALLER ||\n          cmd > EW_WRITEUNINSTALLER + numInsertMax)\n        continue;\n\n      UInt32 params[kNumCommandParams];\n      for (unsigned i = 0; i < kNumCommandParams; i++)\n        params[i] = Get32(p2 + 4 + 4 * i);\n\n      if (params[4] != 0 ||\n          params[5] != 0 ||\n          params[0] <= 1 ||\n          params[3] <= 1)\n        continue;\n\n      const UInt32 altParam = params[3];\n      if (!IsGoodString(params[0]) ||\n          !IsGoodString(altParam))\n        continue;\n\n      UInt32 additional = 0;\n      if (GetVarIndexFinished(altParam, '\\\\', additional) != kVar_INSTDIR)\n        continue;\n      if (AreTwoParamStringsEqual(altParam + additional, params[0]))\n      {\n        const unsigned numInserts = cmd - EW_WRITEUNINSTALLER;\n        mask |= ((unsigned)1 << numInserts);\n      }\n    }\n\n    if (mask == 1)\n    {\n      parkVer_WasDetected = true; // it can be original NSIS or Park-1\n    }\n    else if (mask != 0)\n    {\n      ENsisType newType = NsisType;\n      if (IsUnicode)\n        switch (mask)\n        {\n          case (1 << 3): newType = k_NsisType_Park2; break;\n          case (1 << 4): newType = k_NsisType_Park3; break;\n        }\n      else\n        switch (mask)\n        {\n          case (1 << 1): newType = k_NsisType_Park2; break;\n          case (1 << 2): newType = k_NsisType_Park3; break;\n        }\n      if (newType != NsisType)\n      {\n        parkVer_WasDetected = true;\n        NsisType = newType;\n      }\n    }\n  }\n\n  FindBadCmd(bh, p);\n\n  /*\n  if (strongNsis)\n    return;\n  */\n\n  if (BadCmd < EW_REGISTERDLL)\n    return;\n\n  /*\n  // in ANSI archive we don't check Park and log version\n  if (!IsUnicode)\n    return;\n  */\n  \n  // We can support Park-ANSI archives, if we remove if (strongPark) check\n  if (strongPark && !parkVer_WasDetected)\n  {\n    if (BadCmd < EW_SECTIONSET)\n    {\n      NsisType = k_NsisType_Park3;\n      LogCmdIsEnabled = true; // version 3 is provided with log enabled\n      FindBadCmd(bh, p);\n      if (BadCmd > 0 && BadCmd < EW_SECTIONSET)\n      {\n        NsisType = k_NsisType_Park2;\n        LogCmdIsEnabled = false;\n        FindBadCmd(bh, p);\n        if (BadCmd > 0 && BadCmd < EW_SECTIONSET)\n        {\n          NsisType = k_NsisType_Park1;\n          FindBadCmd(bh, p);\n        }\n      }\n    }\n  }\n\n  if (BadCmd >= EW_SECTIONSET)\n  {\n    LogCmdIsEnabled = !LogCmdIsEnabled;\n    FindBadCmd(bh, p);\n    if (BadCmd >= EW_SECTIONSET && LogCmdIsEnabled)\n    {\n      LogCmdIsEnabled = false;\n      FindBadCmd(bh, p);\n    }\n  }\n}\n\nInt32 CInArchive::GetVarIndex(UInt32 strPos) const\n{\n  if (strPos >= NumStringChars)\n    return -1;\n  \n  if (IsUnicode)\n  {\n    if (NumStringChars - strPos < 3 * 2)\n      return -1;\n    const Byte *p = _data + _stringsPos + strPos * 2;\n    unsigned code = Get16(p);\n    if (IsPark())\n    {\n      if (code != PARK_CODE_VAR)\n        return -1;\n      UInt32 n = Get16(p + 2);\n      if (n == 0)\n        return -1;\n      CONVERT_NUMBER_PARK(n);\n      return (Int32)n;\n    }\n    \n    // NSIS-3\n    {\n      if (code != NS_3_CODE_VAR)\n        return -1;\n      UInt32 n = Get16(p + 2);\n      if (n == 0)\n        return -1;\n      CONVERT_NUMBER_NS_3_UNICODE(n);\n      return (Int32)n;\n    }\n  }\n  \n  if (NumStringChars - strPos < 4)\n    return -1;\n  \n  const Byte *p = _data + _stringsPos + strPos;\n  unsigned c = *p;\n  if (NsisType == k_NsisType_Nsis3)\n  {\n    if (c != NS_3_CODE_VAR)\n      return -1;\n  }\n  else if (c != NS_CODE_VAR)\n    return -1;\n\n  const unsigned c0 = p[1];\n  if (c0 == 0)\n    return -1;\n  const unsigned c1 = p[2];\n  if (c1 == 0)\n    return -1;\n  return (Int32)DECODE_NUMBER_FROM_2_CHARS(c0, c1);\n}\n\nInt32 CInArchive::GetVarIndex(UInt32 strPos, UInt32 &resOffset) const\n{\n  resOffset = 0;\n  Int32 varIndex = GetVarIndex(strPos);\n  if (varIndex < 0)\n    return varIndex;\n  if (IsUnicode)\n  {\n    if (NumStringChars - strPos < 2 * 2)\n      return -1;\n    resOffset = 2;\n  }\n  else\n  {\n    if (NumStringChars - strPos < 3)\n      return -1;\n    resOffset = 3;\n  }\n  return varIndex;\n}\n\nInt32 CInArchive::GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const\n{\n  resOffset = 0;\n  Int32 varIndex = GetVarIndex(strPos);\n  if (varIndex < 0)\n    return varIndex;\n  if (IsUnicode)\n  {\n    if (NumStringChars - strPos < 3 * 2)\n      return -1;\n    const Byte *p = _data + _stringsPos + strPos * 2;\n    if (Get16(p + 4) != endChar)\n      return -1;\n    resOffset = 3;\n  }\n  else\n  {\n    if (NumStringChars - strPos < 4)\n      return -1;\n    const Byte *p = _data + _stringsPos + strPos;\n    if (p[3] != endChar)\n      return -1;\n    resOffset = 4;\n  }\n  return varIndex;\n}\n\nbool CInArchive::IsVarStr(UInt32 strPos, UInt32 varIndex) const\n{\n  if (varIndex > (UInt32)0x7FFF)\n    return false;\n  UInt32 resOffset;\n  return GetVarIndexFinished(strPos, 0, resOffset) == (Int32)varIndex;\n}\n\nbool CInArchive::IsAbsolutePathVar(UInt32 strPos) const\n{\n  Int32 varIndex = GetVarIndex(strPos);\n  if (varIndex < 0)\n    return false;\n  switch (varIndex)\n  {\n    case kVar_INSTDIR:\n    case kVar_EXEDIR:\n    case kVar_TEMP:\n    case kVar_PLUGINSDIR:\n      return true;\n  }\n  return false;\n}\n\n#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))\n\n// We use same check as in NSIS decoder\nstatic bool IsDrivePath(const wchar_t *s) { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\\\' */ ; }\nstatic bool IsDrivePath(const char *s)    { return IS_LETTER_CHAR(s[0]) && s[1] == ':' /* && s[2] == '\\\\' */ ; }\n\nstatic bool IsAbsolutePath(const wchar_t *s)\n{\n  return (s[0] == WCHAR_PATH_SEPARATOR && s[1] == WCHAR_PATH_SEPARATOR) || IsDrivePath(s);\n}\n\nstatic bool IsAbsolutePath(const char *s)\n{\n  return (s[0] == CHAR_PATH_SEPARATOR && s[1] == CHAR_PATH_SEPARATOR) || IsDrivePath(s);\n}\n\nvoid CInArchive::SetItemName(CItem &item, UInt32 strPos)\n{\n  ReadString2_Raw(strPos);\n  const bool isAbs = IsAbsolutePathVar(strPos);\n  if (IsUnicode)\n  {\n    item.NameU = Raw_UString;\n    if (!isAbs && !IsAbsolutePath(Raw_UString))\n      item.Prefix = (int)UPrefixes.Size() - 1;\n  }\n  else\n  {\n    item.NameA = Raw_AString;\n    if (!isAbs && !IsAbsolutePath(Raw_AString))\n      item.Prefix = (int)APrefixes.Size() - 1;\n  }\n}\n\nHRESULT CInArchive::ReadEntries(const CBlockHeader &bh)\n{\n  #ifdef NSIS_SCRIPT\n  CDynLimBuf &s = Script;\n\n  CObjArray<UInt32> labels;\n  labels.Alloc(bh.Num);\n  memset(labels, 0, bh.Num * sizeof(UInt32));\n\n  {\n    const Byte *p = _data;\n    UInt32 i;\n    for (i = 0; i < numOnFunc; i++)\n    {\n      UInt32 func = Get32(p + onFuncOffset + 4 * i);\n      if (func < bh.Num)\n        labels[func] = (labels[func] & ~CMD_REF_OnFunc_Mask) | (CMD_REF_OnFunc | (i << CMD_REF_OnFunc_NumShifts));\n    }\n  }\n\n  /*\n  {\n    for (int i = 0; i < OnFuncs.Size(); i++)\n    {\n      UInt32 address = OnFuncs[i] >> kOnFuncShift;\n      if (address < bh.Num)\n    }\n  }\n  */\n\n  if (bhPages.Num != 0)\n  {\n    Separator();\n    PrintNumComment(\"PAGES\", bhPages.Num);\n\n    if (bhPages.Num > (1 << 12)\n        || bhPages.Offset > _size\n        || bhPages.Num * kPageSize > _size - bhPages.Offset)\n    {\n      AddErrorLF(\"Pages error\");\n    }\n    else\n    {\n\n    AddLF();\n    const Byte *p = _data + bhPages.Offset;\n    \n    for (UInt32 pageIndex = 0; pageIndex < bhPages.Num; pageIndex++, p += kPageSize)\n    {\n      UInt32 dlgID = Get32(p);\n      UInt32 wndProcID = Get32(p + 4);\n      UInt32 preFunc = Get32(p + 8);\n      UInt32 showFunc = Get32(p + 12);\n      UInt32 leaveFunc = Get32(p + 16);\n      UInt32 flags = Get32(p + 20);\n      UInt32 caption = Get32(p + 24);\n      // UInt32 back = Get32(p + 28);\n      UInt32 next = Get32(p + 32);\n      // UInt32 clickNext = Get32(p + 36);\n      // UInt32 cancel = Get32(p + 40);\n      UInt32 params[5];\n      for (int i = 0; i < 5; i++)\n        params[i] = Get32(p + 44 + 4 * i);\n\n      SET_FUNC_REF(preFunc, CMD_REF_Pre)\n      SET_FUNC_REF(showFunc, CMD_REF_Show)\n      SET_FUNC_REF(leaveFunc, CMD_REF_Leave)\n\n      if (wndProcID == PWP_COMPLETED)\n        CommentOpen();\n\n      AddCommentAndString(\"Page \");\n      Add_UInt(pageIndex);\n      AddLF();\n\n      if (flags & PF_PAGE_EX)\n      {\n        s += \"PageEx \";\n        if (!IsInstaller)\n          s += \"un.\";\n      }\n      else\n        s += IsInstaller ? \"Page \" : \"UninstPage \";\n\n      if (wndProcID < Z7_ARRAY_SIZE(kPageTypes))\n        s += kPageTypes[wndProcID];\n      else\n        Add_UInt(wndProcID);\n\n\n      bool needCallbacks = (\n          (Int32)preFunc >= 0 ||\n          (Int32)showFunc >= 0 ||\n          (Int32)leaveFunc >= 0);\n\n      if (flags & PF_PAGE_EX)\n      {\n        AddLF();\n        if (needCallbacks)\n          TabString(\"PageCallbacks\");\n      }\n\n      if (needCallbacks)\n      {\n        AddParam_Func(labels, preFunc); // it's creator_function for PWP_CUSTOM\n        if (wndProcID != PWP_CUSTOM)\n        {\n          AddParam_Func(labels, showFunc);\n        }\n        AddParam_Func(labels, leaveFunc);\n      }\n\n      if ((flags & PF_PAGE_EX) == 0)\n      {\n        // AddOptionalParam(caption);\n        if (flags & PF_CANCEL_ENABLE)\n          s += \" /ENABLECANCEL\";\n        AddLF();\n      }\n      else\n      {\n        AddLF();\n        AddPageOption1(caption, \"Caption\");\n      }\n\n        if (wndProcID == PWP_LICENSE)\n        {\n          if ((flags & PF_LICENSE_NO_FORCE_SELECTION) != 0 ||\n              (flags & PF_LICENSE_FORCE_SELECTION) != 0)\n          {\n            TabString(\"LicenseForceSelection \");\n            if (flags & PF_LICENSE_NO_FORCE_SELECTION)\n              s += \"off\";\n            else\n            {\n              if (dlgID == IDD_LICENSE_FSCB)\n                s += \"checkbox\";\n              else if (dlgID == IDD_LICENSE_FSRB)\n                s += \"radiobuttons\";\n              else\n                Add_UInt(dlgID);\n              AddOptionalParams(params + 2, 2);\n            }\n            NewLine();\n          }\n\n          if (params[0] != 0 || next != 0)\n          {\n            TabString(\"LicenseText\");\n            AddParam(params[0]);\n            AddOptionalParam(next);\n            NewLine();\n          }\n          if (params[1] != 0)\n          {\n            TabString(\"LicenseData\");\n            if ((Int32)params[1] < 0)\n              AddParam(params[1]);\n            else\n              AddLicense(params[1], -1);\n            ClearLangComment();\n            NewLine();\n          }\n        }\n        else if (wndProcID == PWP_SELCOM)\n          AddPageOption(params, 3, \"ComponentsText\");\n        else if (wndProcID == PWP_DIR)\n        {\n          AddPageOption(params, 4, \"DirText\");\n          if (params[4] != 0)\n          {\n            TabString(\"DirVar\");\n            AddParam_Var(params[4] - 1);\n            AddLF();\n          }\n          if (flags & PF_DIR_NO_BTN_DISABLE)\n          {\n            TabString(\"DirVerify leave\");\n            AddLF();\n          }\n\n        }\n        else if (wndProcID == PWP_INSTFILES)\n        {\n          AddPageOption1(params[2], \"CompletedText\");\n          AddPageOption1(params[1], \"DetailsButtonText\");\n        }\n        else if (wndProcID == PWP_UNINST)\n        {\n          if (params[4] != 0)\n          {\n            TabString(\"DirVar\");\n            AddParam_Var(params[4] - 1);\n            AddLF();\n          }\n          AddPageOption(params, 2, \"UninstallText\");\n        }\n\n      if (flags & PF_PAGE_EX)\n      {\n        s += \"PageExEnd\";\n        NewLine();\n      }\n      if (wndProcID == PWP_COMPLETED)\n        CommentClose();\n      NewLine();\n    }\n    }\n  }\n\n  CObjArray<CSection> Sections;\n\n  {\n    Separator();\n    PrintNumComment(\"SECTIONS\", bhSections.Num);\n    PrintNumComment(\"COMMANDS\", bh.Num);\n    AddLF();\n\n    if (bhSections.Num > (1 << 15)\n        // || bhSections.Offset > _size\n        // || (bhSections.Num * SectionSize > _size - bhSections.Offset)\n      )\n    {\n      AddErrorLF(\"Sections error\");\n    }\n    else if (bhSections.Num != 0)\n    {\n      Sections.Alloc((unsigned)bhSections.Num);\n      const Byte *p = _data + bhSections.Offset;\n      for (UInt32 i = 0; i < bhSections.Num; i++, p += SectionSize)\n      {\n        CSection &section = Sections[i];\n        section.Parse(p);\n        if (section.StartCmdIndex < bh.Num)\n          labels[section.StartCmdIndex] |= CMD_REF_Section;\n      }\n    }\n  }\n\n  #endif\n\n  const Byte *p;\n  UInt32 kkk;\n\n  #ifdef NSIS_SCRIPT\n\n  p = _data + bh.Offset;\n\n  for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)\n  {\n    UInt32 commandId = GetCmd(Get32(p));\n    UInt32 mask;\n    switch (commandId)\n    {\n      case EW_NOP:          mask = 1 << 0; break;\n      case EW_IFFILEEXISTS: mask = 3 << 1; break;\n      case EW_IFFLAG:       mask = 3 << 0; break;\n      case EW_MESSAGEBOX:   mask = 5 << 3; break;\n      case EW_STRCMP:       mask = 3 << 2; break;\n      case EW_INTCMP:       mask = 7 << 2; break;\n      case EW_ISWINDOW:     mask = 3 << 1; break;\n      case EW_CALL:\n      {\n        if (Get32(p + 4 + 4) == 1) // it's Call :Label\n        {\n          mask = 1 << 0;\n          break;\n        }\n        UInt32 param0 = Get32(p + 4);\n        if ((Int32)param0 > 0)\n          labels[param0 - 1] |= CMD_REF_Call;\n        continue;\n      }\n      default: continue;\n    }\n    for (unsigned i = 0; mask != 0; i++, mask >>= 1)\n      if (mask & 1)\n      {\n        UInt32 param = Get32(p + 4 + 4 * i);\n        if ((Int32)param > 0 && (Int32)param <= (Int32)bh.Num)\n          labels[param - 1] |= CMD_REF_Goto;\n      }\n  }\n\n  int InitPluginsDir_Start = -1;\n  int InitPluginsDir_End = -1;\n  p = _data + bh.Offset;\n  for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)\n  {\n    UInt32 flg = labels[kkk];\n    /*\n    if (IsFunc(flg))\n    {\n      AddLF();\n      for (int i = 0; i < 14; i++)\n      {\n        UInt32 commandId = GetCmd(Get32(p + kCmdSize * i));\n        s += \", \";\n        UIntToString(s, commandId);\n      }\n      AddLF();\n    }\n    */\n    if (IsFunc(flg)\n        && bh.Num - kkk >= Z7_ARRAY_SIZE(k_InitPluginDir_Commands)\n        && CompareCommands(p, k_InitPluginDir_Commands, Z7_ARRAY_SIZE(k_InitPluginDir_Commands)))\n    {\n      InitPluginsDir_Start = (int)kkk;\n      InitPluginsDir_End = (int)(kkk + Z7_ARRAY_SIZE(k_InitPluginDir_Commands));\n      labels[kkk] |= CMD_REF_InitPluginDir;\n      break;\n    }\n  }\n\n  #endif\n\n  // AString prefixA_Temp;\n  // UString prefixU_Temp;\n\n\n  // const UInt32 kFindS = 158;\n\n  #ifdef NSIS_SCRIPT\n\n  UInt32 curSectionIndex = 0;\n  // UInt32 lastSectionEndCmd = 0xFFFFFFFF;\n  bool sectionIsOpen = false;\n  // int curOnFunc = 0;\n  bool onFuncIsOpen = false;\n\n  /*\n  for (unsigned yyy = 0; yyy + 3 < _data.Size(); yyy++)\n  {\n    UInt32 val = Get32(_data + yyy);\n    if (val == kFindS)\n      val = val;\n  }\n  */\n\n  UInt32 overwrite_State = 0; // \"SetOverwrite on\"\n  Int32 allowSkipFiles_State = -1; // -1: on, -2: off, >=0 : RAW value\n  UInt32 endCommentIndex = 0;\n\n  unsigned numSupportedCommands = GetNumSupportedCommands();\n\n  #endif\n\n  p = _data + bh.Offset;\n  \n  UString spec_outdir_U;\n  AString spec_outdir_A;\n\n  UPrefixes.Add(UString(\"$INSTDIR\"));\n  APrefixes.Add(AString(\"$INSTDIR\"));\n\n  p = _data + bh.Offset;\n\n  unsigned spec_outdir_VarIndex = IsNsis225 ?\n      kVar_Spec_OUTDIR_225 :\n      kVar_Spec_OUTDIR;\n\n  for (kkk = 0; kkk < bh.Num; kkk++, p += kCmdSize)\n  {\n    UInt32 commandId;\n    UInt32 params[kNumCommandParams];\n    commandId = GetCmd(Get32(p));\n    {\n      for (unsigned i = 0; i < kNumCommandParams; i++)\n      {\n        params[i] = Get32(p + 4 + 4 * i);\n        /*\n        if (params[i] == kFindS)\n          i = i;\n        */\n      }\n    }\n\n    #ifdef NSIS_SCRIPT\n\n    bool IsSectionGroup = false;\n    while (curSectionIndex < bhSections.Num)\n    {\n      const CSection &sect = Sections[curSectionIndex];\n      if (sectionIsOpen)\n      {\n        if (sect.StartCmdIndex + sect.NumCommands + 1 != kkk)\n          break;\n        PrintSectionEnd();\n        sectionIsOpen = false;\n        // lastSectionEndCmd = kkk;\n        curSectionIndex++;\n        continue;\n      }\n      if (sect.StartCmdIndex != kkk)\n        break;\n      if (PrintSectionBegin(sect, curSectionIndex))\n      {\n        IsSectionGroup = true;\n        curSectionIndex++;\n        // do we need to flush prefixes in new section?\n        // FlushOutPathPrefixes();\n      }\n      else\n        sectionIsOpen = true;\n    }\n\n    /*\n    if (curOnFunc < OnFuncs.Size())\n    {\n      if ((OnFuncs[curOnFunc] >> kOnFuncShift) == kkk)\n      {\n        s += \"Function .on\";\n        s += kOnFunc[OnFuncs[curOnFunc++] & ((1 << kOnFuncShift) - 1)];\n        AddLF();\n        onFuncIsOpen = true;\n      }\n    }\n    */\n\n    if (labels[kkk] != 0 && labels[kkk] != CMD_REF_Section)\n    {\n      UInt32 flg = labels[kkk];\n      if (IsFunc(flg))\n      {\n        if ((int)kkk == InitPluginsDir_Start)\n          CommentOpen();\n\n        onFuncIsOpen = true;\n        s += \"Function \";\n        Add_FuncName(labels, kkk);\n        if (IsPageFunc(flg))\n        {\n          BigSpaceComment();\n          s += \"Page \";\n          Add_UInt((flg & CMD_REF_Page_Mask) >> CMD_REF_Page_NumShifts);\n          // if (flg & CMD_REF_Creator) s += \", Creator\";\n          if (flg & CMD_REF_Leave) s += \", Leave\";\n          if (flg & CMD_REF_Pre) s += \", Pre\";\n          if (flg & CMD_REF_Show) s += \", Show\";\n        }\n        AddLF();\n      }\n      if (flg & CMD_REF_Goto)\n      {\n        Add_LabelName(kkk);\n        s += ':';\n        AddLF();\n      }\n    }\n\n    if (commandId != EW_RET)\n    {\n      Tab(kkk < endCommentIndex);\n    }\n      \n    /*\n    UInt32 originalCmd = Get32(p);\n    if (originalCmd >= EW_REGISTERDLL)\n    {\n      UIntToString(s, originalCmd);\n      s += ' ';\n      if (originalCmd != commandId)\n      {\n        UIntToString(s, commandId);\n        s += ' ';\n      }\n    }\n    */\n\n    unsigned numSkipParams = 0;\n\n    if (commandId < Z7_ARRAY_SIZE(k_Commands) && commandId < numSupportedCommands)\n    {\n      numSkipParams = k_Commands[commandId].NumParams;\n      const char *sz = k_CommandNames[commandId];\n      if (sz)\n        s += sz;\n    }\n    else\n    {\n      s += \"Command\";\n      Add_UInt(commandId);\n      /* We don't show wrong commands that use overlapped ids.\n         So we change commandId to big value */\n      if (commandId < (1 << 12))\n        commandId += (1 << 12);\n    }\n\n    #endif\n\n    switch (commandId)\n    {\n      case EW_CREATEDIR:\n      {\n        bool isSetOutPath = (params[1] != 0);\n\n        if (isSetOutPath)\n        {\n          UInt32 par0 = params[0];\n          \n          UInt32 resOffset;\n          Int32 idx = GetVarIndex(par0, resOffset);\n          if (idx == (Int32)spec_outdir_VarIndex ||\n              idx == kVar_OUTDIR)\n            par0 += resOffset;\n\n          ReadString2_Raw(par0);\n\n          if (IsUnicode)\n          {\n            if (idx == (Int32)spec_outdir_VarIndex)\n              Raw_UString.Insert(0, spec_outdir_U);\n            else if (idx == kVar_OUTDIR)\n              Raw_UString.Insert(0, UPrefixes.Back());\n            UPrefixes.Add(Raw_UString);\n          }\n          else\n          {\n            if (idx == (Int32)spec_outdir_VarIndex)\n              Raw_AString.Insert(0, spec_outdir_A);\n            else if (idx == kVar_OUTDIR)\n              Raw_AString.Insert(0, APrefixes.Back());\n            APrefixes.Add(Raw_AString);\n          }\n        }\n        \n        #ifdef NSIS_SCRIPT\n        s += isSetOutPath ? \"SetOutPath\" : \"CreateDirectory\";\n        AddParam(params[0]);\n        if (params[2] != 0) // 2.51+ & 3.0b3+\n        {\n          SmallSpaceComment();\n          s += \"CreateRestrictedDirectory\";\n        }\n        #endif\n        \n        break;\n      }\n\n\n      case EW_ASSIGNVAR:\n      {\n        if (params[0] == spec_outdir_VarIndex)\n        {\n          spec_outdir_U.Empty();\n          spec_outdir_A.Empty();\n          if (IsVarStr(params[1], kVar_OUTDIR) &&\n              params[2] == 0 &&\n              params[3] == 0)\n          {\n            spec_outdir_U = UPrefixes.Back(); // outdir_U;\n            spec_outdir_A = APrefixes.Back(); // outdir_A;\n          }\n        }\n\n        #ifdef NSIS_SCRIPT\n        \n        if (params[2] == 0 &&\n            params[3] == 0 &&\n            params[4] == 0 &&\n            params[5] == 0 &&\n            params[1] != 0 &&\n            params[1] < NumStringChars)\n        {\n          char sz[16];\n          ConvertUInt32ToString(kkk + 1, sz);\n          if (IsDirectString_Equal(params[1], sz))\n          {\n            // we suppose that it's GetCurrentAddress command\n            // but there is probability that it's StrCpy command\n            s += \"GetCurrentAddress\";\n            AddParam_Var(params[0]);\n            SmallSpaceComment();\n          }\n        }\n        s += \"StrCpy\";\n        AddParam_Var(params[0]);\n        AddParam(params[1]);\n\n        AddOptionalParams(params + 2, 2);\n\n        #endif\n\n        break;\n      }\n\n      case EW_EXTRACTFILE:\n      {\n        CItem &item = Items.AddNew();\n\n        UInt32 par1 = params[1];\n\n        SetItemName(item, par1);\n          \n        item.Pos = params[2];\n        item.MTime.dwLowDateTime = params[3];\n        item.MTime.dwHighDateTime = params[4];\n        \n        #ifdef NSIS_SCRIPT\n        \n        {\n          UInt32 overwrite = params[0] & 0x7;\n          if (overwrite != overwrite_State)\n          {\n            s += \"SetOverwrite \";\n            ADD_TYPE_FROM_LIST(k_SetOverwrite_Modes, overwrite);\n            overwrite_State = overwrite;\n            AddLF();\n            Tab(kkk < endCommentIndex);\n          }\n        }\n\n        {\n          UInt32 nsisMB = params[0] >> 3;\n          if ((Int32)nsisMB != allowSkipFiles_State)\n          {\n            UInt32 mb = nsisMB & ((1 << 20) - 1);  // old/new NSIS\n            UInt32 b1 = nsisMB >> 21;  // NSIS 2.06+\n            UInt32 b2 = nsisMB >> 20;  // NSIS old\n            Int32 asf = (Int32)nsisMB;\n            if (mb == (Z7_NSIS_WIN_MB_ABORTRETRYIGNORE | Z7_NSIS_WIN_MB_ICONSTOP) && (b1 == Z7_NSIS_WIN_IDIGNORE || b2 == Z7_NSIS_WIN_IDIGNORE))\n              asf = -1;\n            else if (mb == (Z7_NSIS_WIN_MB_RETRYCANCEL | Z7_NSIS_WIN_MB_ICONSTOP) && (b1 == Z7_NSIS_WIN_IDCANCEL || b2 == Z7_NSIS_WIN_IDCANCEL))\n              asf = -2;\n            else\n            {\n              AddCommentAndString(\"AllowSkipFiles [Overwrite]: \");\n              MessageBox_MB_Part(mb);\n              if (b1 != 0)\n              {\n                s += \" /SD\";\n                Add_ButtonID(b1);\n              }\n            }\n            if (asf != allowSkipFiles_State)\n            {\n              if (asf < 0)\n              {\n                s += \"AllowSkipFiles \";\n                s += (asf == -1) ? \"on\" : \"off\";\n              }\n              AddLF();\n              Tab(kkk < endCommentIndex);\n            }\n            allowSkipFiles_State = (Int32)nsisMB;\n          }\n        }\n          \n        s += \"File\";\n        AddParam(params[1]);\n\n        /* params[5] contains link to LangString (negative value)\n           with NLF_FILE_ERROR or NLF_FILE_ERROR_NOIGNORE message for MessageBox.\n           We don't need to print it. */\n        \n        #endif\n        \n        if (IsVarStr(par1, 10)) // is $R0\n        {\n          // we parse InstallLib macro in 7-Zip installers\n          unsigned kBackOffset = 28;\n          if (kkk > 1)\n          {\n            // detect old version of InstallLib macro\n            if (Get32(p - 1 * kCmdSize) == EW_NOP) // goto command\n              kBackOffset -= 2;\n          }\n\n          if (kkk > kBackOffset)\n          {\n            const Byte *p2 = p - kBackOffset * kCmdSize;\n            UInt32 cmd = Get32(p2);\n            if (cmd == EW_ASSIGNVAR)\n            {\n              UInt32 pars[6];\n              for (int i = 0; i < 6; i++)\n                pars[i] = Get32(p2 + i * 4 + 4);\n              if (pars[0] == 10 + 4 && pars[2] == 0 && pars[3] == 0) // 10 + 4 means $R4\n              {\n                item.Prefix = -1;\n                item.NameA.Empty();\n                item.NameU.Empty();\n                SetItemName(item, pars[1]);\n                // maybe here we can restore original item name, if new name is empty\n              }\n            }\n          }\n        }\n        /* UInt32 allowIgnore = params[5]; */\n        break;\n      }\n\n      case EW_SETFILEATTRIBUTES:\n      {\n        if (kkk > 0 && Get32(p - kCmdSize) == EW_EXTRACTFILE)\n        {\n          if (params[0] == Get32(p - kCmdSize + 4 + 4 * 1)) // compare with PrevCmd.Params[1]\n          {\n            CItem &item = Items.Back();\n            item.Attrib_Defined = true;\n            item.Attrib = params[1];\n          }\n        }\n        #ifdef NSIS_SCRIPT\n        AddParam(params[0]);\n        Space();\n        FlagsToString2(s, g_WinAttrib, Z7_ARRAY_SIZE(g_WinAttrib), params[1]);\n        #endif\n        break;\n      }\n\n      case EW_WRITEUNINSTALLER:\n      {\n        /* NSIS 2.29+ writes alternative path to params[3]\n             \"$INSTDIR\\\\\" + Str(params[0])\n           NSIS installer uses alternative path, if main path\n           from params[0] is not absolute path */\n\n        const bool pathOk = (params[0] > 0) && IsGoodString(params[0]);\n\n        if (!pathOk)\n        {\n          #ifdef NSIS_SCRIPT\n          AddError(\"bad path\");\n          #endif\n          break;\n        }\n\n      #ifdef NSIS_SCRIPT\n\n        bool altPathOk = true;\n\n        const UInt32 altParam = params[3];\n        if (altParam != 0)\n        {\n          altPathOk = false;\n          UInt32 additional = 0;\n          if (GetVarIndexFinished(altParam, '\\\\', additional) == kVar_INSTDIR)\n            altPathOk = AreTwoParamStringsEqual(altParam + additional, params[0]);\n        }\n\n        AddParam(params[0]);\n\n        /*\n        for (int i = 1; i < 3; i++)\n          AddParam_UInt(params[i]);\n        */\n\n        if (params[3] != 0)\n        {\n          SmallSpaceComment();\n          AddParam(params[3]);\n        }\n        \n        if (!altPathOk)\n        {\n          #ifdef NSIS_SCRIPT\n          AddError(\"alt path error\");\n          #endif\n        }\n\n      #endif\n\n        if (BadCmd >= 0 && BadCmd <= EW_WRITEUNINSTALLER)\n        {\n          /* We don't support cases with incorrect installer commands.\n             Such bad installer item can break unpacking for other items. */\n          #ifdef NSIS_SCRIPT\n          AddError(\"SKIP possible BadCmd\");\n          #endif\n          break;\n        }\n\n        CItem &item = Items.AddNew();\n\n        SetItemName(item, params[0]);\n\n        item.Pos = params[1];\n        item.PatchSize = params[2];\n        item.IsUninstaller = true;\n        const UInt32 param3 = params[3];\n        if (param3 != 0 && item.Prefix != -1)\n        {\n          /* (item.Prefix != -1) case means that param[0] path was not absolute.\n              So we use params[3] in that case, as original nsis */\n          SetItemName(item, param3);\n        }\n        /* UNINSTALLER file doesn't use directory prefixes.\n           So we remove prefix: */\n        item.Prefix = -1;\n        \n        /*\n        // we can add second time to test the code\n        CItem item2 = item;\n        item2.NameU += L'2';\n        item2.NameA += '2';\n        Items.Add(item2);\n        */\n\n        break;\n      }\n\n      #ifdef NSIS_SCRIPT\n      \n      case EW_RET:\n      {\n        // bool needComment = false;\n        if (onFuncIsOpen)\n        {\n          if (kkk == bh.Num - 1 || IsProbablyEndOfFunc(labels[kkk + 1]))\n          {\n            AddStringLF(\"FunctionEnd\");\n\n            if ((int)kkk + 1 == InitPluginsDir_End)\n              CommentClose();\n            AddLF();\n            onFuncIsOpen = false;\n            // needComment = true;\n            break;\n          }\n        }\n        // if (!needComment)\n            if (IsSectionGroup)\n              break;\n          if (sectionIsOpen)\n          {\n            const CSection &sect = Sections[curSectionIndex];\n            if (sect.StartCmdIndex + sect.NumCommands == kkk)\n            {\n              PrintSectionEnd();\n              sectionIsOpen = false;\n              curSectionIndex++;\n              break;\n            }\n\n            // needComment = true;\n            // break;\n          }\n\n        /*\n        if (needComment)\n          s += \"  ;\";\n        */\n        TabString(\"Return\");\n        AddLF();\n        break;\n      }\n\n      case EW_NOP:\n      {\n        if (params[0] == 0)\n          s += \"Nop\";\n        else\n        {\n          s += \"Goto\";\n          Add_GotoVar(params[0]);\n        }\n        break;\n      }\n\n      case EW_ABORT:\n      {\n        AddOptionalParam(params[0]);\n        break;\n      }\n\n      case EW_CALL:\n      {\n        if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_EXTRACTFILE)\n        {\n          UInt32 par1 = GET_CMD_PARAM(p + kCmdSize, 1);\n\n          UInt32 pluginPar = 0;\n\n          if (GetVarIndexFinished(par1, '\\\\', pluginPar) == kVar_PLUGINSDIR)\n          {\n            pluginPar += par1;\n            UInt32 commandId2 = GetCmd(Get32(p + kCmdSize * 2));\n            if (commandId2 == EW_SETFLAG || commandId2 == EW_UPDATETEXT)\n            {\n              UInt32 i;\n              for (i = kkk + 3; i < bh.Num; i++)\n              {\n                const Byte *pCmd = p + kCmdSize * (i - kkk);\n                UInt32 commandId3 = GetCmd(Get32(pCmd));\n                if (commandId3 != EW_PUSHPOP\n                    || GET_CMD_PARAM(pCmd, 1) != 0\n                    || GET_CMD_PARAM(pCmd, 2) != 0)\n                  break;\n              }\n              if (i < bh.Num)\n              {\n                const Byte *pCmd = p + kCmdSize * (i - kkk);\n\n                // UInt32 callDll_Param = GET_CMD_PARAM(pCmd, 0);\n                // UInt32 file_Param = GET_CMD_PARAM(p + kCmdSize, 1);\n\n                if (GetCmd(Get32(pCmd)) == EW_REGISTERDLL &&\n                    AreTwoParamStringsEqual(\n                      GET_CMD_PARAM(pCmd, 0),\n                      GET_CMD_PARAM(p + kCmdSize, 1)))\n                {\n                  // params[4] = 1 means GetModuleHandle attempt before default LoadLibraryEx;\n                  /// new versions of NSIS use params[4] = 1 for Plugin command\n                  if (GET_CMD_PARAM(pCmd, 2) == 0\n                    // && GET_CMD_PARAM(pCmd, 4) != 0\n                    )\n                  {\n                    {\n                      AString s2;\n                      ReadString2(s2, pluginPar);\n                      if (s2.Len() >= 4 &&\n                          StringsAreEqualNoCase_Ascii(s2.RightPtr(4), \".dll\"))\n                        s2.DeleteFrom(s2.Len() - 4);\n                      s2 += \"::\";\n                      AString func;\n                      ReadString2(func, GET_CMD_PARAM(pCmd, 1));\n                      s2 += func;\n                      Add_QuStr(s2);\n\n                      if (GET_CMD_PARAM(pCmd, 3) == 1)\n                        s += \" /NOUNLOAD\";\n\n                      for (UInt32 j = i - 1; j >= kkk + 3; j--)\n                      {\n                        const Byte *pCmd2 = p + kCmdSize * (j - kkk);\n                        AddParam(GET_CMD_PARAM(pCmd2, 0));\n                      }\n                      NewLine();\n                      Tab(true);\n                      endCommentIndex = i + 1;\n                    }\n                  }\n                }\n              }\n            }\n          }\n        }\n        {\n          const Byte *nextCmd = p + kCmdSize;\n          UInt32 commandId2 = GetCmd(Get32(nextCmd));\n          if (commandId2 == EW_SETFLAG\n              && GET_CMD_PARAM(nextCmd, 0) == k_ExecFlags_DetailsPrint\n              && GET_CMD_PARAM(nextCmd, 2) != 0) // is \"lastused\"\n            // || commandId2 == EW_UPDATETEXT)\n          {\n            if ((Int32)params[0] > 0 && labels[params[0] - 1] & CMD_REF_InitPluginDir)\n            {\n              s += \"InitPluginsDir\";\n              AddLF();\n              Tab(true);\n              endCommentIndex = kkk + 2;\n            }\n          }\n        }\n        \n        s += \"Call \";\n        if ((Int32)params[0] < 0)\n          Add_Var((UInt32)-((Int32)params[0] + 1));\n        else if (params[0] == 0)\n          s += '0';\n        else\n        {\n          const UInt32 val = params[0] - 1;\n          if (params[1] == 1) // it's Call :Label\n          {\n            s += ':';\n            Add_LabelName(val);\n          }\n          else // if (params[1] == 0) // it's Call Func\n            Add_FuncName(labels, val);\n        }\n        break;\n      }\n\n      case EW_UPDATETEXT:\n      case EW_SLEEP:\n      {\n        AddParam(params[0]);\n        break;\n      }\n      \n      case EW_CHDETAILSVIEW:\n      {\n             if (params[0] == Z7_NSIS_WIN_SW_SHOWNA && params[1] == Z7_NSIS_WIN_SW_HIDE) s += \" show\";\n        else if (params[1] == Z7_NSIS_WIN_SW_SHOWNA && params[0] == Z7_NSIS_WIN_SW_HIDE) s += \" hide\";\n        else\n          for (int i = 0; i < 2; i++)\n          {\n            Space();\n            Add_ShowWindow_Cmd(params[i]);\n          }\n        break;\n      }\n\n      case EW_IFFILEEXISTS:\n      {\n        AddParam(params[0]);\n        Add_GotoVars2(&params[1]);\n        break;\n      }\n\n      case EW_SETFLAG:\n      {\n        AString temp;\n        ReadString2(temp, params[1]);\n        if (params[0] == k_ExecFlags_Errors && params[2] == 0)\n        {\n          s += (temp.Len() == 1 && temp[0] == '0') ? \"ClearErrors\" : \"SetErrors\";\n          break;\n        }\n        s += \"Set\";\n        Add_ExecFlags(params[0]);\n\n        if (params[2] != 0)\n        {\n          s += \" lastused\";\n          break;\n        }\n        UInt32 v;\n        if (StringToUInt32(temp, v))\n        {\n          const char *s2 = NULL;\n          switch (params[0])\n          {\n            case k_ExecFlags_AutoClose:\n            case k_ExecFlags_RebootFlag:\n              if (v < 2) { s2 = (v == 0) ? \"false\" : \"true\"; }  break;\n            case k_ExecFlags_ShellVarContext:\n              if (v < 2) { s2 = (v == 0) ? \"current\" : \"all\"; }  break;\n            case k_ExecFlags_Silent:\n              if (v < 2) { s2 = (v == 0) ? \"normal\" : \"silent\"; }  break;\n            case k_ExecFlags_RegView:\n                   if (v ==   0) s2 = \"32\";\n              else if (v == 256) s2 = \"64\";\n              break;\n            case k_ExecFlags_DetailsPrint:\n                   if (v == 0) s2 = \"both\";\n              else if (v == 2) s2 = \"textonly\";\n              else if (v == 4) s2 = \"listonly\";\n              else if (v == 6) s2 = \"none\";\n              break;\n          }\n          if (s2)\n          {\n            s += ' ';\n            s += s2;\n            break;\n          }\n        }\n        SpaceQuStr(temp);\n        break;\n      }\n\n      case EW_IFFLAG:\n      {\n        Add_ExecFlags(params[2]);\n        Add_GotoVars2(&params[0]);\n        /*\n        const unsigned kIfErrors = 2;\n        if (params[2] != kIfErrors && params[3] != 0xFFFFFFFF ||\n            params[2] == kIfErrors && params[3] != 0)\n        {\n          s += \" # FLAG &= \";\n          AddParam_UInt(params[3]);\n        }\n        */\n        break;\n      }\n\n      case EW_GETFLAG:\n      {\n        Add_ExecFlags(params[1]);\n        AddParam_Var(params[0]);\n        break;\n      }\n\n      case EW_RENAME:\n      {\n        if (params[2] != 0)\n          s += k_REBOOTOK;\n        AddParams(params, 2);\n        if (params[3] != 0)\n        {\n          SmallSpaceComment();\n          AddParam(params[3]); // rename comment for log file\n        }\n        break;\n      }\n      \n      case EW_GETFULLPATHNAME:\n      {\n        if (params[2] == 0)\n          s += \" /SHORT\";\n        AddParam_Var(params[1]);\n        AddParam(params[0]);\n        break;\n      }\n\n      case EW_SEARCHPATH:\n      case EW_STRLEN:\n      {\n        AddParam_Var(params[0]);\n        AddParam(params[1]);\n        break;\n      }\n\n      case EW_GETTEMPFILENAME:\n      {\n        AddParam_Var(params[0]);\n        AString temp;\n        ReadString2(temp, params[1]);\n        if (!temp.IsEqualTo(\"$TEMP\"))\n          SpaceQuStr(temp);\n        break;\n      }\n\n      case EW_DELETEFILE:\n      {\n        UInt32 flag = params[1];\n        if ((flag & DEL_REBOOT) != 0)\n          s += k_REBOOTOK;\n        AddParam(params[0]);\n        break;\n      }\n\n      case EW_MESSAGEBOX:\n      {\n        MessageBox_MB_Part(params[0]);\n        AddParam(params[1]);\n        {\n          UInt32 buttonID = (params[0] >> 21); // NSIS 2.06+\n          if (buttonID != 0)\n          {\n            s += \" /SD\";\n            Add_ButtonID(buttonID);\n          }\n        }\n        for (int i = 2; i < 6; i += 2)\n          if (params[i] != 0)\n          {\n            Add_ButtonID(params[i]);\n            Add_GotoVar1(params[i + 1]);\n          }\n        break;\n      }\n\n      case EW_RMDIR:\n      {\n        UInt32 flag = params[1];\n        if ((flag & DEL_RECURSE) != 0)\n          s += \" /r\";\n        if ((flag & DEL_REBOOT) != 0)\n          s += k_REBOOTOK;\n        AddParam(params[0]);\n        break;\n      }\n\n      case EW_STRCMP:\n      {\n        if (params[4] != 0)\n          s += 'S';\n        AddParams(params, 2);\n        Add_GotoVars2(&params[2]);\n        break;\n      }\n\n      case EW_READENVSTR:\n      {\n        s += (params[2] != 0) ?\n          \"ReadEnvStr\" :\n          \"ExpandEnvStrings\";\n        AddParam_Var(params[0]);\n        AString temp;\n        ReadString2(temp, params[1]);\n        if (params[2] != 0 &&temp.Len() >= 2 && temp[0] == '%' && temp.Back() == '%')\n        {\n          temp.DeleteBack();\n          temp.Delete(0);\n        }\n        SpaceQuStr(temp);\n        break;\n      }\n\n      case EW_INTCMP:\n      {\n        s += \"Int\";\n        const UInt32 param5 = params[5];\n        if (param5 & 0x8000)\n          s += \"64\"; // v3.03+\n        s += \"Cmp\";\n        if (IsNsis3_OrHigher() ? (param5 & 1) : (param5 != 0))\n          s += 'U';\n        AddParams(params, 2);\n        Add_GotoVar1(params[2]);\n        if (params[3] != 0 || params[4] != 0)\n          Add_GotoVars2(params + 3);\n        break;\n      }\n\n      case EW_INTOP:\n      {\n        AddParam_Var(params[0]);\n        const char * const kOps = \"+-*/|&^!|&%<>>\"; // NSIS 2.01+\n                        // \"+-*/|&^!|&%\";   // NSIS 2.0b4+\n                        // \"+-*/|&^~!|&%\";  // NSIS old\n        const UInt32 opIndex = params[3];\n        const char c = (opIndex < 14) ? kOps[opIndex] : '?';\n        const char c2 = (opIndex < 8 || opIndex == 10) ? (char)0 : c;\n        const int numOps = (opIndex == 7) ? 1 : 2;\n        AddParam(params[1]);\n        if (numOps == 2 && c == '^' && IsDirectString_Equal(params[2], \"0xFFFFFFFF\"))\n          s += \" ~    ;\";\n        Space();\n        s += c;\n        if (numOps != 1)\n        {\n          if (opIndex == 13) // v3.03+ : operation \">>>\"\n            s += c;\n          if (c2 != 0)\n            s += c2;\n          AddParam(params[2]);\n        }\n        break;\n      }\n\n      case EW_INTFMT:\n      {\n        if (params[3])\n          s += \"Int64Fmt\";  // v3.03+\n        else\n          s += \"IntFmt\";\n        AddParam_Var(params[0]);\n        AddParams(params + 1, 2);\n        break;\n      }\n\n      case EW_PUSHPOP:\n      {\n        if (params[2] != 0)\n        {\n          s += \"Exch\";\n          if (params[2] != 1)\n            AddParam_UInt(params[2]);\n        }\n        else if (params[1] != 0)\n        {\n          s += \"Pop\";\n          AddParam_Var(params[0]);\n        }\n        else\n        {\n          if (NoLabels(labels + kkk + 1, 2)\n              && Get32(p + kCmdSize) == EW_PUSHPOP // Exch\"\n              && GET_CMD_PARAM(p + kCmdSize, 2) == 1\n              && Get32(p + kCmdSize * 2) == EW_PUSHPOP // Pop $VAR\n              && GET_CMD_PARAM(p + kCmdSize * 2, 1) != 0)\n          {\n            if (IsVarStr(params[0], GET_CMD_PARAM(p + kCmdSize * 2, 0)))\n            {\n              s += \"Exch\";\n              AddParam(params[0]);\n              NewLine();\n              Tab(true);\n              endCommentIndex = kkk + 3;\n            }\n          }\n          s += \"Push\";\n          AddParam(params[0]);\n        }\n        break;\n      }\n\n      case EW_FINDWINDOW:\n      {\n        AddParam_Var(params[0]);\n        AddParam(params[1]);\n        AddOptionalParams(params + 2, 3);\n        break;\n      }\n\n      case EW_SENDMESSAGE:\n      {\n        // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]\n        AddParam(params[1]);\n\n        const char *w = NULL;\n        AString t;\n        ReadString2(t, params[2]);\n        UInt32 wm;\n        if (StringToUInt32(t, wm))\n        {\n          switch (wm)\n          {\n            case 0x0C: w = \"SETTEXT\"; break;\n            case 0x10: w = \"CLOSE\"; break;\n            case 0x30: w = \"SETFONT\"; break;\n          }\n        }\n        if (w)\n        {\n          s += \" ${WM_\";\n          s += w;\n          s += '}';\n        }\n        else\n          SpaceQuStr(t);\n        \n        UInt32 spec = params[5];\n        for (unsigned i = 0; i < 2; i++)\n        {\n          AString s2;\n          if (spec & ((UInt32)1 << i))\n            s2 += \"STR:\";\n          ReadString2(s2, params[3 + i]);\n          SpaceQuStr(s2);\n        }\n\n        if ((Int32)params[0] >= 0)\n          AddParam_Var(params[0]);\n\n        spec >>= 2;\n        if (spec != 0)\n        {\n          s += \" /TIMEOUT=\";\n          Add_UInt(spec);\n        }\n        break;\n      }\n\n      case EW_ISWINDOW:\n      {\n        AddParam(params[0]);\n        Add_GotoVars2(&params[1]);\n        break;\n      }\n\n      case EW_GETDLGITEM:\n      {\n        AddParam_Var(params[0]);\n        AddParams(params + 1, 2);\n        break;\n      }\n      \n      case EW_SETCTLCOLORS:\n      {\n        AddParam(params[0]);\n\n        UInt32 offset = params[1];\n        \n        if (_size < bhCtlColors.Offset\n           || _size - bhCtlColors.Offset < offset\n           || _size - bhCtlColors.Offset - offset < GET_CtlColors_SIZE(Is64Bit))\n        {\n          AddError(\"bad offset\");\n          break;\n        }\n\n        const Byte *p2 = _data + bhCtlColors.Offset + offset;\n        CNsis_CtlColors colors;\n        colors.Parse(p2, Is64Bit);\n\n        if ((colors.flags & kColorsFlags_BK_SYS) != 0 ||\n            (colors.flags & kColorsFlags_TEXT_SYS) != 0)\n          s += \" /BRANDING\";\n        \n        AString bk;\n        bool bkc = false;\n        if (colors.bkmode == Z7_NSIS_WIN_TRANSPARENT)\n          bk += \" transparent\";\n        else if (colors.flags & kColorsFlags_BKB)\n        {\n          if ((colors.flags & kColorsFlags_BK_SYS) == 0 &&\n              (colors.flags & kColorsFlags_BK) != 0)\n            bkc = true;\n        }\n        if ((colors.flags & kColorsFlags_TEXT) != 0 || !bk.IsEmpty() || bkc)\n        {\n          Space();\n          if ((colors.flags & kColorsFlags_TEXT_SYS) != 0 || (colors.flags & kColorsFlags_TEXT) == 0)\n            AddQuotes();\n          else\n            Add_Color(colors.text);\n        }\n        s += bk;\n        if (bkc)\n        {\n          Space();\n          Add_Color(colors.bkc);\n        }\n\n        break;\n      }\n\n      // case EW_LOADANDSETIMAGE:\n      case EW_SETBRANDINGIMAGE:\n      {\n        s += \" /IMGID=\";\n        Add_UInt(params[1]);\n        if (params[2] == 1)\n          s += \" /RESIZETOFIT\";\n        AddParam(params[0]);\n        break;\n      }\n\n      case EW_CREATEFONT:\n      {\n        AddParam_Var(params[0]);\n        AddParam(params[1]);\n        AddOptionalParams(params + 2, 2);\n        if (params[4] & 1) s += \" /ITALIC\";\n        if (params[4] & 2) s += \" /UNDERLINE\";\n        if (params[4] & 4) s += \" /STRIKE\";\n        break;\n      }\n\n      case EW_SHOWWINDOW:\n      {\n        AString hw, sw;\n        ReadString2(hw, params[0]);\n        ReadString2(sw, params[1]);\n        if (params[3] != 0)\n          s += \"EnableWindow\";\n        else\n        {\n          UInt32 val;\n          bool valDefined = false;\n          if (StringToUInt32(sw, val))\n          {\n            if (val < Z7_ARRAY_SIZE(kShowWindow_Commands))\n            {\n              sw.Empty();\n              sw += \"${\";\n              Add_ShowWindow_Cmd_2(sw, val);\n              sw += '}';\n              valDefined = true;\n            }\n          }\n          bool isHwndParent = IsVarStr(params[0], IsNsis225 ? kVar_HWNDPARENT_225 : kVar_HWNDPARENT);\n          if (params[2] != 0)\n          {\n            if (valDefined && val == 0 && isHwndParent)\n            {\n              s += \"HideWindow\";\n              break;\n            }\n          }\n          if (valDefined && val == 5 && isHwndParent &&\n              kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_BRINGTOFRONT)\n          {\n            s += \"  ; \";\n          }\n          s += \"ShowWindow\";\n        }\n        SpaceQuStr(hw);\n        SpaceQuStr(sw);\n        break;\n      }\n\n      case EW_SHELLEXEC:\n      {\n        AddParams(params, 2);\n        if (params[2] != 0 || params[3] != Z7_NSIS_WIN_SW_SHOWNORMAL)\n        {\n          AddParam(params[2]);\n          if (params[3] != Z7_NSIS_WIN_SW_SHOWNORMAL)\n          {\n            Space();\n            Add_ShowWindow_Cmd(params[3]);\n          }\n        }\n        if (params[5] != 0)\n        {\n          s += \"    ;\";\n          AddParam(params[5]); // it's tatus text update\n        }\n        break;\n      }\n\n      case EW_EXECUTE:\n      {\n        if (params[2] != 0)\n          s += \"Wait\";\n        AddParam(params[0]);\n        if (params[2] != 0)\n          if ((Int32)params[1] >= 0)\n            AddParam_Var(params[1]);\n        break;\n      }\n      \n      case EW_GETFILETIME:\n      case EW_GETDLLVERSION:\n      {\n        if (commandId == EW_GETDLLVERSION)\n          if (params[3] == 2)\n            s += \" /ProductVersion\";  // v3.08+\n        AddParam(params[2]);\n        AddParam_Var(params[0]);\n        AddParam_Var(params[1]);\n        break;\n      }\n\n      case EW_REGISTERDLL:\n      {\n        AString func;\n        ReadString2(func, params[1]);\n        bool printFunc = true;\n        // params[4] = 1; for plugin command\n        if (params[2] == 0)\n        {\n          s += \"CallInstDLL\";\n          AddParam(params[0]);\n          if (params[3] == 1)\n            s += \" /NOUNLOAD\";\n        }\n        else\n        {\n          if (func.IsEqualTo(\"DllUnregisterServer\"))\n          {\n            s += \"UnRegDLL\";\n            printFunc = false;\n          }\n          else\n          {\n            s += \"RegDLL\";\n            if (func.IsEqualTo(\"DllRegisterServer\"))\n              printFunc = false;\n          }\n          AddParam(params[0]);\n        }\n        if (printFunc)\n          SpaceQuStr(func);\n        break;\n      }\n\n      case EW_CREATESHORTCUT:\n      {\n        unsigned numParams;\n        #define IsNsis3d0b3_OrHigher() 0 // change it\n        const unsigned v3_0b3 = IsNsis3d0b3_OrHigher();\n        for (numParams = 6; numParams > 2; numParams--)\n          if (params[numParams - 1] != 0)\n            break;\n\n        const UInt32 spec = params[4];\n        const unsigned sw_shift = v3_0b3 ? 12 : 8;\n        const UInt32 sw_mask = v3_0b3 ? 0x7000 : 0x7F;\n        if (spec & 0x8000) // NSIS 3.0b0\n          s += \" /NoWorkingDir\";\n\n        AddParams(params, numParams > 4 ? 4 : numParams);\n        if (numParams <= 4)\n          break;\n\n        UInt32 icon = (spec & (v3_0b3 ? 0xFFF : 0xFF));\n        Space();\n        if (icon != 0)\n          Add_UInt(icon);\n        else\n          AddQuotes();\n\n        if ((spec >> sw_shift) == 0 && numParams < 6)\n          break;\n        UInt32 sw = (spec >> sw_shift) & sw_mask;\n        Space();\n        // NSIS encoder replaces these names:\n        if (sw == Z7_NSIS_WIN_SW_SHOWMINNOACTIVE)\n          sw = Z7_NSIS_WIN_SW_SHOWMINIMIZED;\n        if (sw == 0)\n          AddQuotes();\n        else\n          Add_ShowWindow_Cmd(sw);\n        \n        UInt32 modKey = spec >> 24;\n        UInt32 key = (spec >> 16) & 0xFF;\n\n        if (modKey == 0 && key == 0)\n        {\n          if (numParams < 6)\n            break;\n          Space();\n          AddQuotes();\n        }\n        else\n        {\n          Space();\n          if (modKey & 1) s += \"SHIFT|\"; // HOTKEYF_SHIFT\n          if (modKey & 2) s += \"CONTROL|\";\n          if (modKey & 4) s += \"ALT|\";\n          if (modKey & 8) s += \"EXT|\";\n          \n          const unsigned kMy_VK_F1 = 0x70;\n          if (key >= kMy_VK_F1 && key <= kMy_VK_F1 + 23)\n          {\n            s += 'F';\n            Add_UInt(key - kMy_VK_F1 + 1);\n          }\n          else if ((key >= 'A' && key <= 'Z') || (key >= '0' && key <= '9'))\n            s += (char)key;\n          else\n          {\n            s += \"Char_\";\n            Add_UInt(key);\n          }\n        }\n        AddOptionalParam(params[5]); // description\n        break;\n      }\n\n      case EW_COPYFILES:\n      {\n        if (params[2] & 0x04) s += \" /SILENT\"; // FOF_SILENT\n        if (params[2] & 0x80) s += \" /FILESONLY\"; // FOF_FILESONLY\n        AddParams(params, 2);\n        if (params[3] != 0)\n        {\n          s += \"    ;\";\n          AddParam(params[3]); // status text update\n        }\n        break;\n      }\n\n      case EW_REBOOT:\n      {\n        if (params[0] != 0xbadf00d)\n          s += \" ; Corrupted ???\";\n        else if (kkk + 1 < bh.Num && GetCmd(Get32(p + kCmdSize)) == EW_QUIT)\n          endCommentIndex = kkk + 2;\n        break;\n      }\n\n      case EW_WRITEINI:\n      {\n        unsigned numAlwaysParams = 0;\n        if (params[0] == 0)  // Section\n          s += \"FlushINI\";\n        else if (params[4] != 0)\n        {\n          s += \"WriteINIStr\";\n          numAlwaysParams = 3;\n        }\n        else\n        {\n          s += \"DeleteINI\";\n          s += (params[1] == 0) ? \"Sec\" : \"Str\";\n          numAlwaysParams = 1;\n        }\n        AddParam(params[3]); // filename\n        // Section, EntryName, Value\n        AddParams(params, numAlwaysParams);\n        AddOptionalParams(params + numAlwaysParams, 3 - numAlwaysParams);\n        break;\n      }\n\n      case EW_READINISTR:\n      {\n        AddParam_Var(params[0]);\n        AddParam(params[3]); // FileName\n        AddParams(params +1, 2); // Section, EntryName\n        break;\n      }\n\n      case EW_DELREG:\n      {\n        // NSIS 2.00 used another scheme!\n        \n        if (params[4] == 0)\n          s += \"Value\";\n        else\n        {\n          s += \"Key\";\n          if (params[4] & 2)\n            s += \" /ifempty\";\n          // TODO: /ifnosubkeys, /ifnovalues\n        }\n        AddRegRoot(params[1]);\n        AddParam(params[2]);\n        AddOptionalParam(params[3]);\n        break;\n      }\n\n      case EW_WRITEREG:\n      {\n        const char *s2 = NULL;\n        switch (params[4])\n        {\n          case 1: s2 = \"Str\"; break;\n          case 2: s2 = \"ExpandStr\"; break; // maybe unused\n          case 3: s2 = \"Bin\"; break;\n          case 4: s2 = \"DWORD\"; break;\n          default:\n            s += '?';\n            Add_UInt(params[4]);\n        }\n        if (params[4] == 1 && params[5] == 2)\n          s2 = \"ExpandStr\";\n        if (params[4] == 3 && params[5] == 7)\n          s2 = \"MultiStr\"; // v3.02+\n        if (s2)\n          s += s2;\n        AddRegRoot(params[0]);\n        AddParams(params + 1, 2); // keyName, valueName\n        if (params[4] != 3)\n          AddParam(params[3]); // value\n        else\n        {\n          // Binary data.\n          Space();\n          UInt32 offset = params[3];\n          bool isSupported = false;\n          if (AfterHeaderSize >= 4\n              && bhData.Offset <= AfterHeaderSize - 4\n              && offset <= AfterHeaderSize - 4 - bhData.Offset)\n          {\n            // we support it for solid archives.\n            const Byte *p2 = _afterHeader + bhData.Offset + offset;\n            UInt32 size = Get32(p2);\n            if (size <= AfterHeaderSize - 4 - bhData.Offset - offset)\n            {\n              for (UInt32 i = 0; i < size; i++)\n              {\n                Byte b = (p2 + 4)[i];\n                unsigned t;\n                t = (b >> 4); s += (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));\n                t = (b & 15); s += (char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))));\n              }\n              isSupported = true;\n            }\n          }\n          if (!isSupported)\n          {\n            // we must read from file here;\n            s += \"data[\";\n            Add_UInt(offset);\n            s += \" ... ]\";\n            s += \"  ; !!! Unsupported\";\n          }\n        }\n        break;\n      }\n\n      case EW_READREGSTR:\n      {\n        s += (params[4] == 1) ? \"DWORD\" : \"Str\";\n        AddParam_Var(params[0]);\n        AddRegRoot(params[1]);\n        AddParams(params + 2, 2);\n        break;\n      }\n\n      case EW_REGENUM:\n      {\n        s += (params[4] != 0) ? \"Key\" : \"Value\";\n        AddParam_Var(params[0]);\n        AddRegRoot(params[1]);\n        AddParams(params + 2, 2);\n        break;\n      }\n\n      case EW_FCLOSE:\n      case EW_FINDCLOSE:\n      {\n        AddParam_Var(params[0]);\n        break;\n      }\n\n    #endif\n\n      case EW_FOPEN:\n      {\n        /*\n          the pattern for empty files is following:\n          FileOpen $0 \"file_name\" w\n          FileClose $0\n        */\n\n        const UInt32 acc = params[1]; // dwDesiredAccess\n        const UInt32 creat = params[2]; // dwCreationDisposition\n        if (creat == Z7_NSIS_WIN_CREATE_ALWAYS && acc == Z7_NSIS_WIN_GENERIC_WRITE)\n        {\n          if (kkk + 1 < bh.Num)\n          if (Get32(p + kCmdSize) == EW_FCLOSE)\n          if (Get32(p + kCmdSize + 4) == params[0])\n          {\n            CItem &item = Items.AddNew();\n            item.IsEmptyFile = true;\n            SetItemName(item, params[3]);\n          }\n        }\n\n      #ifdef NSIS_SCRIPT\n\n        AddParam_Var(params[0]);\n        AddParam(params[3]);\n        if (acc == 0 && creat == 0)\n          break;\n        char cc = 0;\n             if (creat == Z7_NSIS_WIN_OPEN_EXISTING && acc == Z7_NSIS_WIN_GENERIC_READ)\n          cc = 'r';\n        else if (creat == Z7_NSIS_WIN_CREATE_ALWAYS && acc == Z7_NSIS_WIN_GENERIC_WRITE)\n          cc = 'w';\n        else if (creat == Z7_NSIS_WIN_OPEN_ALWAYS && (acc == (Z7_NSIS_WIN_GENERIC_WRITE | Z7_NSIS_WIN_GENERIC_READ)))\n          cc = 'a';\n        // cc = 0;\n        if (cc != 0)\n        {\n          Space();\n          s += cc;\n          break;\n        }\n\n        if (acc & Z7_NSIS_WIN_GENERIC_READ)     s += \" GENERIC_READ\";\n        if (acc & Z7_NSIS_WIN_GENERIC_WRITE)    s += \" GENERIC_WRITE\";\n        if (acc & Z7_NSIS_WIN_GENERIC_EXECUTE)  s += \" GENERIC_EXECUTE\";\n        if (acc & Z7_NSIS_WIN_GENERIC_ALL)      s += \" GENERIC_ALL\";\n        \n        const char *s2 = NULL;\n        switch (creat)\n        {\n          case Z7_NSIS_WIN_CREATE_NEW:        s2 = \"CREATE_NEW\"; break;\n          case Z7_NSIS_WIN_CREATE_ALWAYS:     s2 = \"CREATE_ALWAYS\"; break;\n          case Z7_NSIS_WIN_OPEN_EXISTING:     s2 = \"OPEN_EXISTING\"; break;\n          case Z7_NSIS_WIN_OPEN_ALWAYS:       s2 = \"OPEN_ALWAYS\"; break;\n          case Z7_NSIS_WIN_TRUNCATE_EXISTING: s2 = \"TRUNCATE_EXISTING\"; break;\n        }\n        Space();\n        if (s2)\n          s += s2;\n        else\n          Add_UInt(creat);\n      #endif\n\n        break;\n      }\n\n    #ifdef NSIS_SCRIPT\n      \n      case EW_FPUTS:\n      case EW_FPUTWS:\n      {\n        if (commandId == EW_FPUTWS)\n          s += (params[2] == 0) ? \"UTF16LE\" : \"Word\";\n        else if (params[2] != 0)\n          s += \"Byte\";\n        if (params[2] == 0 && params[3])\n          s += \" /BOM\"; // v3.0b3+\n        AddParam_Var(params[0]);\n        AddParam(params[1]);\n        break;\n      }\n\n      case EW_FGETS:\n      case EW_FGETWS:\n      {\n        if (commandId == EW_FPUTWS)\n          s += (params[3] == 0) ? \"UTF16LE\" : \"Word\";\n        if (params[3] != 0)\n          s += \"Byte\";\n        AddParam_Var(params[0]);\n        AddParam_Var(params[1]);\n        AString maxLenStr;\n        ReadString2(maxLenStr, params[2]);\n        UInt32 maxLen;\n        if (StringToUInt32(maxLenStr, maxLen))\n        {\n          if (maxLen == 1 && params[3] != 0)\n            break;\n          if (maxLen == 1023 && params[3] == 0) // NSIS_MAX_STRLEN - 1; can be other value!!\n            break;\n        }\n        SpaceQuStr(maxLenStr);\n        break;\n      }\n\n      case EW_FSEEK:\n      {\n        AddParam_Var(params[0]);\n        AddParam(params[2]);\n        if (params[3] == 1) s += \" CUR\"; // FILE_CURRENT\n        if (params[3] == 2) s += \" END\"; // FILE_END\n        if ((Int32)params[1] >= 0)\n        {\n          if (params[3] == 0) s += \" SET\"; // FILE_BEGIN\n          AddParam_Var(params[1]);\n        }\n        break;\n      }\n\n      case EW_FINDNEXT:\n      {\n        AddParam_Var(params[1]);\n        AddParam_Var(params[0]);\n        break;\n      }\n\n      case EW_FINDFIRST:\n      {\n        AddParam_Var(params[1]);\n        AddParam_Var(params[0]);\n        AddParam(params[2]);\n        break;\n      }\n\n      case EW_LOG:\n      {\n        if (params[0] != 0)\n        {\n          s += \"Set \";\n          s += (params[1] == 0) ? \"off\" : \"on\";\n        }\n        else\n        {\n          s += \"Text\";\n          AddParam(params[1]);\n        }\n        break;\n      }\n\n      case EW_SECTIONSET:\n      {\n        if ((Int32)params[2] >= 0)\n        {\n          s += \"Get\";\n          Add_SectOp(params[2]);\n          AddParam(params[0]);\n          AddParam_Var(params[1]);\n        }\n        else\n        {\n          s += \"Set\";\n          const UInt32 t = (UInt32)(-(Int32)params[2] - 1);\n          Add_SectOp(t);\n          AddParam(params[0]);\n          AddParam(params[t == 0 ? 4 : 1]);\n\n          // params[3] != 0 means call SectionFlagsChanged in installer\n          // used by SECTIONSETFLAGS command\n        }\n        break;\n      }\n\n      case EW_INSTTYPESET:\n      {\n        unsigned numQwParams = 0;\n        const char *s2;\n        if (params[3] == 0)\n        {\n          if (params[2] == 0)\n          {\n            s2 = \"InstTypeGetText\";\n            numQwParams = 1;\n          }\n          else\n          {\n            s2 = \"InstTypeSetText\";\n            numQwParams = 2;\n          }\n        }\n        else\n        {\n          if (params[2] == 0)\n            s2 = \"GetCurInstType\";\n          else\n          {\n            s2 = \"SetCurInstType\";\n            numQwParams = 1;\n          }\n        }\n        s += s2;\n        AddParams(params, numQwParams);\n        if (params[2] == 0)\n          AddParam_Var(params[1]);\n        break;\n      }\n\n      case EW_GETOSINFO:\n      {\n        if (IsNsis3_OrHigher())\n        {\n          // v3.06+\n          if (params[3] == 0) // GETOSINFO_KNOWNFOLDER\n          {\n            s += \"GetKnownFolderPath\";\n            AddParam_Var(params[1]);\n            AddParam(params[2]);\n            break;\n          }\n          else if (params[3] == 1) // GETOSINFO_READMEMORY\n          {\n            s += \"ReadMemory\";\n            AddParam_Var(params[1]);\n            AddParam(params[2]);\n            AddParam(params[4]);\n            // if (params[2].IsEqualTo(\"0\")) AddCommentAndString(\"GetWinVer\");\n          }\n          else\n            s += \"GetOsInfo\";\n          break;\n        }\n        s += \"GetLabelAddr\"; //  before v3.06+\n        break;\n      }\n      \n      case EW_LOCKWINDOW:\n      {\n        s += (params[0] == 0) ? \" on\" : \" off\";\n        break;\n      }\n\n      case EW_FINDPROC:\n      {\n        AddParam_Var(params[0]);\n        AddParam(params[1]);\n        break;\n      }\n\n      default:\n      {\n        numSkipParams = 0;\n      }\n      #endif\n    }\n    \n    #ifdef NSIS_SCRIPT\n\n    unsigned numParams = kNumCommandParams;\n\n    for (; numParams > 0; numParams--)\n      if (params[numParams - 1] != 0)\n        break;\n\n    if (numParams > numSkipParams)\n    {\n      s += \" ; !!!! Unknown Params: \";\n      unsigned i;\n      for (i = 0; i < numParams; i++)\n        AddParam(params[i]);\n\n      s += \"   ;\";\n      \n      for (i = 0; i < numParams; i++)\n      {\n        Space();\n        UInt32 v = params[i];\n        if (v > 0xFFF00000)\n          Add_SignedInt(s, (Int32)v);\n        else\n          Add_UInt(v);\n      }\n    }\n\n    NewLine();\n    \n    #endif\n  }\n\n  #ifdef NSIS_SCRIPT\n\n  if (sectionIsOpen)\n  {\n    if (curSectionIndex < bhSections.Num)\n    {\n      const CSection &sect = Sections[curSectionIndex];\n      if (sect.StartCmdIndex + sect.NumCommands + 1 == kkk)\n      {\n        PrintSectionEnd();\n        sectionIsOpen = false;\n        // lastSectionEndCmd = kkk;\n        curSectionIndex++;\n      }\n    }\n  }\n  \n  while (curSectionIndex < bhSections.Num)\n  {\n    const CSection &sect = Sections[curSectionIndex];\n    if (sectionIsOpen)\n    {\n      if (sect.StartCmdIndex + sect.NumCommands != kkk)\n        AddErrorLF(\"SECTION ERROR\");\n      PrintSectionEnd();\n      sectionIsOpen = false;\n      curSectionIndex++;\n    }\n    else\n    {\n      if (PrintSectionBegin(sect, curSectionIndex))\n        curSectionIndex++;\n      else\n        sectionIsOpen = true;\n    }\n  }\n  \n  #endif\n\n  return S_OK;\n}\n\nstatic int CompareItems(void *const *p1, void *const *p2, void *param)\n{\n  const CItem &i1 = **(const CItem *const *)p1;\n  const CItem &i2 = **(const CItem *const *)p2;\n  RINOZ(MyCompare(i1.Pos, i2.Pos))\n\n  /* In another code we check CItem::Pos after each solid item.\n     So here we place empty files before all non empty files */\n  if (i1.IsEmptyFile)\n  {\n    if (!i2.IsEmptyFile)\n      return -1;\n  }\n  else if (i2.IsEmptyFile)\n    return 1;\n\n  const CInArchive *inArchive = (const CInArchive *)param;\n  if (inArchive->IsUnicode)\n  {\n    if (i1.Prefix != i2.Prefix)\n    {\n      if (i1.Prefix < 0) return -1;\n      if (i2.Prefix < 0) return 1;\n      RINOZ(\n          inArchive->UPrefixes[i1.Prefix].Compare(\n          inArchive->UPrefixes[i2.Prefix]))\n    }\n    RINOZ(i1.NameU.Compare(i2.NameU))\n  }\n  else\n  {\n    if (i1.Prefix != i2.Prefix)\n    {\n      if (i1.Prefix < 0) return -1;\n      if (i2.Prefix < 0) return 1;\n      RINOZ(strcmp(\n          inArchive->APrefixes[i1.Prefix],\n          inArchive->APrefixes[i2.Prefix]))\n    }\n    RINOZ(strcmp(i1.NameA, i2.NameA))\n  }\n  return 0;\n}\n\nHRESULT CInArchive::SortItems()\n{\n  {\n    Items.Sort(CompareItems, (void *)this);\n    unsigned i;\n\n    for (i = 0; i + 1 < Items.Size(); i++)\n    {\n      const CItem &i1 = Items[i];\n      if (i1.IsEmptyFile)\n        continue;\n      const CItem &i2 = Items[i + 1];\n      if (i1.Pos != i2.Pos)\n        continue;\n\n      if (IsUnicode)\n      {\n        if (i1.NameU != i2.NameU) continue;\n        if (i1.Prefix != i2.Prefix)\n        {\n          if (i1.Prefix < 0 || i2.Prefix < 0) continue;\n          if (UPrefixes[i1.Prefix] != UPrefixes[i2.Prefix]) continue;\n        }\n      }\n      else\n      {\n        if (i1.NameA != i2.NameA) continue;\n        if (i1.Prefix != i2.Prefix)\n        {\n          if (i1.Prefix < 0 || i2.Prefix < 0) continue;\n          if (APrefixes[i1.Prefix] != APrefixes[i2.Prefix]) continue;\n        }\n      }\n      Items.Delete(i + 1);\n      i--;\n    }\n    \n    for (i = 0; i < Items.Size(); i++)\n    {\n      CItem &item = Items[i];\n      if (item.IsEmptyFile)\n        continue;\n      const UInt32 curPos = item.Pos + 4;\n      for (unsigned nextIndex = i + 1; nextIndex < Items.Size(); nextIndex++)\n      {\n        const CItem &nextItem = Items[nextIndex];\n        // if (nextItem.IsEmptyFile) continue;\n        const UInt32 nextPos = nextItem.Pos;\n        if (curPos <= nextPos)\n        {\n          item.EstimatedSize_Defined = true;\n          item.EstimatedSize = nextPos - curPos;\n          break;\n        }\n      }\n    }\n    \n    if (!IsSolid)\n    {\n      for (i = 0; i < Items.Size(); i++)\n      {\n        CItem &item = Items[i];\n        if (item.IsEmptyFile)\n          continue;\n        RINOK(SeekToNonSolidItem(i))\n        const UInt32 kSigSize = 4 + 1 + 1 + 4; // size,[flag],prop,dict\n        BYTE sig[kSigSize];\n        size_t processedSize = kSigSize;\n        RINOK(ReadStream(_stream, sig, &processedSize))\n        if (processedSize < 4)\n          return S_FALSE;\n        UInt32 size = Get32(sig);\n        if ((size & kMask_IsCompressed) != 0)\n        {\n          item.IsCompressed = true;\n          size &= ~kMask_IsCompressed;\n          if (Method == NMethodType::kLZMA)\n          {\n            if (processedSize < 9)\n              return S_FALSE;\n            /*\n            if (FilterFlag)\n              item.UseFilter = (sig[4] != 0);\n            */\n            item.DictionarySize = Get32(sig + 4 + 1 + (FilterFlag ? 1 : 0));\n          }\n        }\n        else\n        {\n          item.IsCompressed = false;\n          item.Size = size;\n          item.Size_Defined = true;\n        }\n        item.CompressedSize = size;\n        item.CompressedSize_Defined = true;\n      }\n    }\n  }\n  return S_OK;\n}\n\n#ifdef NSIS_SCRIPT\n// Flags for common_header.flags\n// #define CH_FLAGS_DETAILS_SHOWDETAILS 1\n// #define CH_FLAGS_DETAILS_NEVERSHOW 2\n#define CH_FLAGS_PROGRESS_COLORED 4\n#define CH_FLAGS_SILENT 8\n#define CH_FLAGS_SILENT_LOG 16\n#define CH_FLAGS_AUTO_CLOSE 32\n// #define CH_FLAGS_DIR_NO_SHOW 64  // unused now\n#define CH_FLAGS_NO_ROOT_DIR 128\n#define CH_FLAGS_COMP_ONLY_ON_CUSTOM 256\n#define CH_FLAGS_NO_CUSTOM 512\n\nstatic const char * const k_PostStrings[] =\n{\n    \"install_directory_auto_append\"\n  , \"uninstchild\"     // NSIS 2.25+, used by uninstaller:\n  , \"uninstcmd\"       // NSIS 2.25+, used by uninstaller:\n  , \"wininit\"         // NSIS 2.25+, used by move file on reboot\n};\n#endif\n\n\nvoid CBlockHeader::Parse(const Byte *p, unsigned bhoSize)\n{\n  if (bhoSize == 12)\n  {\n    // UInt64 a = GetUi64(p);\n    if (GetUi32(p + 4) != 0)\n      throw 1;\n  }\n  Offset = GetUi32(p);\n  Num = GetUi32(p + bhoSize - 4);\n}\n\n#define PARSE_BH(k, bh) bh.Parse (p1 + 4 + bhoSize * k, bhoSize)\n\n\nHRESULT CInArchive::Parse()\n{\n  // UInt32 offset = ReadUInt32();\n  // ???? offset == FirstHeader.HeaderSize\n  const Byte * const p1 = _data;\n\n  if (_size < 4 + 12 * 8)\n    Is64Bit = false;\n  else\n  {\n    Is64Bit = true;\n    // here we test high 32-bit of possible UInt64 CBlockHeader::Offset field\n    for (int k = 0; k < 8; k++)\n      if (GetUi32(p1 + 4 + 12 * k + 4) != 0)\n        Is64Bit = false;\n  }\n\n  const unsigned bhoSize = Is64Bit ? 12 : 8;\n  if (_size < 4 + bhoSize * 8)\n    return S_FALSE;\n\n  CBlockHeader bhEntries, bhStrings, bhLangTables;\n\n  PARSE_BH (2, bhEntries);\n  PARSE_BH (3, bhStrings);\n  PARSE_BH (4, bhLangTables);\n\n  #ifdef NSIS_SCRIPT\n\n  CBlockHeader bhFont;\n  PARSE_BH (0, bhPages);\n  PARSE_BH (1, bhSections);\n  PARSE_BH (5, bhCtlColors);\n  PARSE_BH (6, bhFont);\n  PARSE_BH (7, bhData);\n\n  #endif\n\n  _stringsPos = bhStrings.Offset;\n  if (_stringsPos > _size\n      || bhLangTables.Offset > _size\n      || bhEntries.Offset > _size)\n    return S_FALSE;\n  {\n    if (bhLangTables.Offset < bhStrings.Offset)\n      return S_FALSE;\n    const UInt32 stringTableSize = bhLangTables.Offset - bhStrings.Offset;\n    if (stringTableSize < 2)\n      return S_FALSE;\n    const Byte *strData = _data + _stringsPos;\n    if (strData[stringTableSize - 1] != 0)\n      return S_FALSE;\n    IsUnicode = (Get16(strData) == 0);\n    NumStringChars = stringTableSize;\n    if (IsUnicode)\n    {\n      if ((stringTableSize & 1) != 0)\n        return S_FALSE;\n      NumStringChars >>= 1;\n      if (strData[stringTableSize - 2] != 0)\n        return S_FALSE;\n    }\n  }\n\n  if (bhEntries.Num > (1 << 25))\n    return S_FALSE;\n  if (bhEntries.Num * kCmdSize > _size - bhEntries.Offset)\n    return S_FALSE;\n\n  DetectNsisType(bhEntries, _data + bhEntries.Offset);\n\n  Decoder.IsNsisDeflate = (NsisType != k_NsisType_Nsis3);\n  \n  // some NSIS files (that are not detected as k_NsisType_Nsis3)\n  // use original (non-NSIS) Deflate\n  // How to detect these cases?\n\n  // Decoder.IsNsisDeflate = false;\n\n\n  #ifdef NSIS_SCRIPT\n\n  {\n    AddCommentAndString(\"NSIS script\");\n    if (IsUnicode)\n      Script += \" (UTF-8)\";\n    Space();\n    Script += GetFormatDescription();\n    AddLF();\n  }\n  {\n    AddCommentAndString(IsInstaller ? \"Install\" : \"Uninstall\");\n    AddLF();\n  }\n\n  AddLF();\n  if (Is64Bit)\n    AddStringLF(\"Target AMD64-Unicode\"); // TODO: Read PE machine type and use the correct CPU type\n  else if (IsUnicode)\n    AddStringLF(\"Unicode true\");\n  else if (IsNsis3_OrHigher())\n    AddStringLF(\"Unicode false\"); // Unicode is the default in 3.07+\n\n  if (Method != NMethodType::kCopy)\n  {\n    const char *m = NULL;\n    switch ((int)Method)\n    {\n      case NMethodType::kDeflate: m = \"zlib\"; break;\n      case NMethodType::kBZip2: m = \"bzip2\"; break;\n      case NMethodType::kLZMA: m = \"lzma\"; break;\n      default: break;\n    }\n    Script += \"SetCompressor\";\n    if (IsSolid)\n      Script += \" /SOLID\";\n    if (m)\n    {\n      Space();\n      Script += m;\n    }\n    AddLF();\n  }\n  if (Method == NMethodType::kLZMA)\n  {\n    // if (DictionarySize != (8 << 20))\n    {\n      Script += \"SetCompressorDictSize\";\n      AddParam_UInt(DictionarySize >> 20);\n      AddLF();\n    }\n  }\n\n  Separator();\n  PrintNumComment(\"HEADER SIZE\", FirstHeader.HeaderSize);\n  // if (bhPages.Offset != 300 && bhPages.Offset != 288)\n  if (bhPages.Offset != 0)\n  {\n    PrintNumComment(\"START HEADER SIZE\", bhPages.Offset);\n  }\n\n  if (bhSections.Num > 0)\n  {\n    if (bhEntries.Offset < bhSections.Offset)\n      return S_FALSE;\n    SectionSize = (bhEntries.Offset - bhSections.Offset) / bhSections.Num;\n    if (bhSections.Offset + bhSections.Num * SectionSize != bhEntries.Offset)\n      return S_FALSE;\n    if (SectionSize < kSectionSize_base)\n      return S_FALSE;\n    UInt32 maxStringLen = SectionSize - kSectionSize_base;\n    if (IsUnicode)\n    {\n      if ((maxStringLen & 1) != 0)\n        return S_FALSE;\n      maxStringLen >>= 1;\n    }\n    // if (maxStringLen != 1024)\n    {\n      if (maxStringLen == 0)\n        PrintNumComment(\"SECTION SIZE\", SectionSize);\n      else\n        PrintNumComment(\"MAX STRING LENGTH\", maxStringLen);\n    }\n  }\n  \n  PrintNumComment(\"STRING CHARS\", NumStringChars);\n  // PrintNumComment(\"LANG TABLE SIZE\", bhCtlColors.Offset - bhLangTables.Offset);\n  \n  if (bhCtlColors.Offset > _size)\n    AddErrorLF(\"Bad COLORS TABLE\");\n  // PrintNumComment(\"COLORS TABLE SIZE\", bhFont.Offset - bhCtlColors.Offset);\n  if (bhCtlColors.Num != 0)\n    PrintNumComment(\"COLORS Num\", bhCtlColors.Num);\n\n  // bhData uses offset in _afterHeader (not in _data)\n  // PrintNumComment(\"FONT TABLE SIZE\", bhData.Offset - bhFont.Offset);\n  if (bhFont.Num != 0)\n    PrintNumComment(\"FONTS Num\", bhFont.Num);\n\n  // PrintNumComment(\"DATA SIZE\", FirstHeader.HeaderSize - bhData.Offset);\n  if (bhData.Num != 0)\n    PrintNumComment(\"DATA NUM\", bhData.Num);\n\n  AddLF();\n\n  AddStringLF(\"OutFile [NSIS].exe\");\n  AddStringLF(\"!include WinMessages.nsh\");\n\n  AddLF();\n\n  strUsed.Alloc(NumStringChars);\n  memset(strUsed, 0, NumStringChars);\n\n  {\n    UInt32 ehFlags = Get32(p1);\n    UInt32 showDetails = ehFlags & 3;// CH_FLAGS_DETAILS_SHOWDETAILS & CH_FLAGS_DETAILS_NEVERSHOW;\n    if (showDetails >= 1 && showDetails <= 2)\n    {\n      Script += IsInstaller ? \"ShowInstDetails\" : \"ShowUninstDetails\";\n      Script += (showDetails == 1) ? \" show\" : \" nevershow\";\n      AddLF();\n    }\n    if (ehFlags & CH_FLAGS_PROGRESS_COLORED) AddStringLF(\"InstProgressFlags colored\" );\n    if ((ehFlags & (CH_FLAGS_SILENT | CH_FLAGS_SILENT_LOG)) != 0)\n    {\n      Script += IsInstaller ? \"SilentInstall \" : \"SilentUnInstall \";\n      Script += (ehFlags & CH_FLAGS_SILENT_LOG) ? \"silentlog\" : \"silent\";\n      AddLF();\n    }\n    if (ehFlags & CH_FLAGS_AUTO_CLOSE) AddStringLF(\"AutoCloseWindow true\");\n    if ((ehFlags & CH_FLAGS_NO_ROOT_DIR) == 0) AddStringLF(\"AllowRootDirInstall true\");\n    if (ehFlags & CH_FLAGS_NO_CUSTOM) AddStringLF(\"InstType /NOCUSTOM\");\n    if (ehFlags & CH_FLAGS_COMP_ONLY_ON_CUSTOM) AddStringLF(\"InstType /COMPONENTSONLYONCUSTOM\");\n  }\n\n  // Separator();\n  // AddLF();\n\n  Int32 licenseLangIndex = -1;\n  {\n    const Byte *pp = _data + bhPages.Offset;\n\n    for (UInt32 pageIndex = 0; pageIndex < bhPages.Num; pageIndex++, pp += kPageSize)\n    {\n      UInt32 wndProcID = Get32(pp + 4);\n      UInt32 param1 = Get32(pp + 44 + 4 * 1);\n      if (wndProcID != PWP_LICENSE || param1 == 0)\n        continue;\n      if ((Int32)param1 < 0)\n        licenseLangIndex = - ((Int32)param1 + 1);\n      else\n        noParseStringIndexes.AddToUniqueSorted(param1);\n    }\n  }\n\n  unsigned paramsOffset;\n  {\n    unsigned numBhs = 8;\n    // probably its for old NSIS?\n    if (bhoSize == 8 && bhPages.Offset == 276)\n      numBhs = 7;\n    paramsOffset = 4 + bhoSize * numBhs;\n  }\n\n  const Byte *p2 = p1 + paramsOffset;\n\n  {\n    UInt32 rootKey = Get32(p2); // (rootKey = -1) in uninstaller by default (the bug in NSIS)\n    UInt32 subKey = Get32(p2 + 4);\n    UInt32 value = Get32(p2 + 8);\n    if ((rootKey != 0 && rootKey != (UInt32)(Int32)-1) || subKey != 0 || value != 0)\n    {\n      Script += \"InstallDirRegKey\";\n      AddRegRoot(rootKey);\n      AddParam(subKey);\n      AddParam(value);\n      AddLF();\n    }\n  }\n\n\n  {\n    UInt32 bg_color1 = Get32(p2 + 12);\n    UInt32 bg_color2 = Get32(p2 + 16);\n    UInt32 bg_textcolor = Get32(p2 + 20);\n    if (bg_color1 != (UInt32)(Int32)-1 || bg_color2 != (UInt32)(Int32)-1 || bg_textcolor != (UInt32)(Int32)-1)\n    {\n      Script += \"BGGradient\";\n      if (bg_color1 != 0 || bg_color2 != 0xFF0000 || bg_textcolor != (UInt32)(Int32)-1)\n      {\n        Add_ColorParam(bg_color1);\n        Add_ColorParam(bg_color2);\n        if (bg_textcolor != (UInt32)(Int32)-1)\n          Add_ColorParam(bg_textcolor);\n      }\n      AddLF();\n    }\n  }\n\n  {\n    UInt32 lb_bg = Get32(p2 + 24);\n    UInt32 lb_fg = Get32(p2 + 28);\n    if ((lb_bg != (UInt32)(Int32)-1 || lb_fg != (UInt32)(Int32)-1) &&\n      (lb_bg != 0 || lb_fg != 0xFF00))\n    {\n      Script += \"InstallColors\";\n      Add_ColorParam(lb_fg);\n      Add_ColorParam(lb_bg);\n      AddLF();\n    }\n  }\n\n  UInt32 license_bg = Get32(p2 + 36);\n  if (license_bg != (UInt32)(Int32)-1 &&\n      license_bg != (UInt32)(Int32)-15) // COLOR_BTNFACE\n  {\n    Script += \"LicenseBkColor\";\n    if ((Int32)license_bg == -5)  // COLOR_WINDOW\n      Script += \" /windows\";\n    /*\n    else if ((Int32)license_bg == -15)\n      Script += \" /grey\";\n    */\n    else\n      Add_ColorParam(license_bg);\n    AddLF();\n  }\n\n  if (bhLangTables.Num > 0)\n  {\n    const UInt32 langtable_size = Get32(p2 + 32);\n\n    if (langtable_size == (UInt32)(Int32)-1)\n      return E_NOTIMPL; // maybe it's old NSIS archive()\n\n    if (langtable_size < 10)\n      return S_FALSE;\n    if (bhLangTables.Num > (_size - bhLangTables.Offset) / langtable_size)\n      return S_FALSE;\n\n    const UInt32 numStrings = (langtable_size - 10) / 4;\n    _numLangStrings = numStrings;\n    AddLF();\n    Separator();\n    PrintNumComment(\"LANG TABLES\", bhLangTables.Num);\n    PrintNumComment(\"LANG STRINGS\", numStrings);\n    AddLF();\n\n    if (licenseLangIndex >= 0 && (unsigned)licenseLangIndex < numStrings)\n    {\n      for (UInt32 i = 0; i < bhLangTables.Num; i++)\n      {\n        const Byte * const p = _data + bhLangTables.Offset + langtable_size * i;\n        const UInt16 langID = Get16(p);\n        UInt32 val = Get32(p + 10 + (UInt32)licenseLangIndex * 4);\n        if (val != 0)\n        {\n          Script += \"LicenseLangString \";\n          Add_LangStr_Simple((UInt32)licenseLangIndex);\n          AddParam_UInt(langID);\n          AddLicense(val, langID);\n          noParseStringIndexes.AddToUniqueSorted(val);\n          NewLine();\n        }\n      }\n      AddLF();\n    }\n    \n    UInt32 names[3] = { 0 };\n\n    UInt32 i;\n    for (i = 0; i < bhLangTables.Num; i++)\n    {\n      const Byte * const p = _data + bhLangTables.Offset + langtable_size * i;\n      const UInt16 langID = Get16(p);\n      if (i == 0 || langID == 1033)\n        _mainLang = p + 10;\n      for (unsigned k = 0; k < Z7_ARRAY_SIZE(names) && k < numStrings; k++)\n      {\n        UInt32 v = Get32(p + 10 + k * 4);\n        if (v != 0 && (langID == 1033 || names[k] == 0))\n          names[k] = v;\n      }\n    }\n\n    const UInt32 name = names[2];\n    if (name != 0)\n    {\n      Script += \"Name\";\n      AddParam(name);\n      NewLine();\n\n      ReadString2(Name, name);\n    }\n    \n    /*\n    const UInt32 caption = names[1];\n    if (caption != 0)\n    {\n      Script += \"Caption\";\n      AddParam(caption);\n      NewLine();\n    }\n    */\n    \n    const UInt32 brandingText = names[0];\n    if (brandingText != 0)\n    {\n      Script += \"BrandingText\";\n      AddParam(brandingText);\n      NewLine();\n\n      ReadString2(BrandingText, brandingText);\n    }\n\n    for (i = 0; i < bhLangTables.Num; i++)\n    {\n      const Byte * const p = _data + bhLangTables.Offset + langtable_size * i;\n      const UInt16 langID = Get16(p);\n      \n      AddLF();\n      AddCommentAndString(\"LANG:\");\n      AddParam_UInt(langID);\n      /*\n      Script += \" (\";\n      LangId_To_String(Script, langID);\n      Script += ')';\n      */\n      AddLF();\n      // UInt32 dlg_offset = Get32(p + 2);\n      // UInt32 g_exec_flags_rtl = Get32(p + 6);\n      \n      \n      for (UInt32 j = 0; j < numStrings; j++)\n      {\n        UInt32 val = Get32(p + 10 + j * 4);\n        if (val != 0)\n        {\n          if ((Int32)j != licenseLangIndex)\n          {\n            Script += \"LangString \";\n            Add_LangStr_Simple(j);\n            AddParam_UInt(langID);\n            AddParam(val);\n            AddLF();\n          }\n        }\n      }\n      AddLF();\n    }\n    ClearLangComment();\n  }\n\n  {\n    unsigned numInternalVars = GET_NUM_INTERNAL_VARS;\n    UInt32 numUsedVars = GetNumUsedVars();\n    if (numUsedVars > numInternalVars)\n    {\n      Separator();\n      PrintNumComment(\"VARIABLES\", numUsedVars - numInternalVars);\n      AddLF();\n      AString temp;\n      for (UInt32 i = numInternalVars; i < numUsedVars; i++)\n      {\n        Script += \"Var \";\n        temp.Empty();\n        GetVar2(temp, i);\n        AddStringLF(temp);\n      }\n      AddLF();\n    }\n  }\n\n  onFuncOffset = paramsOffset + 40;\n  numOnFunc = Z7_ARRAY_SIZE(kOnFunc);\n  if (bhPages.Offset == 276)\n    numOnFunc--;\n  p2 += 40 + numOnFunc * 4;\n  \n  #define NSIS_MAX_INST_TYPES 32\n\n  AddLF();\n\n  UInt32 i;\n  for (i = 0; i < NSIS_MAX_INST_TYPES + 1; i++, p2 += 4)\n  {\n    UInt32 instType = Get32(p2);\n    if (instType != 0)\n    {\n      Script += \"InstType\";\n      AString s2;\n      if (!IsInstaller)\n        s2 += \"un.\";\n      ReadString2(s2, instType);\n      SpaceQuStr(s2);\n      NewLine();\n    }\n  }\n  \n  {\n    UInt32 installDir = Get32(p2);\n    p2 += 4;\n    if (installDir != 0)\n    {\n      Script += \"InstallDir\";\n      AddParam(installDir);\n      NewLine();\n    }\n  }\n\n  if (bhPages.Offset >= 288)\n    for (i = 0; i < 4; i++)\n    {\n      if (i != 0 && bhPages.Offset < 300)\n        break;\n      UInt32 param = Get32(p2 + 4 * i);\n      if (param == 0 || param == (UInt32)(Int32)-1)\n        continue;\n      \n      /*\n      uninstaller:\n      UInt32 uninstChild = Get32(p2 + 8); // \"$TEMP\\\\$1u_.exe\"\n      UInt32 uninstCmd = Get32(p2 + 12); // \"\\\"$TEMP\\\\$1u_.exe\\\" $0 _?=$INSTDIR\\\\\"\n      int str_wininit = Get32(p2 + 16); // \"$WINDIR\\\\wininit.ini\"\n      */\n      \n      AddCommentAndString(k_PostStrings[i]);\n      Script += \" =\";\n      AddParam(param);\n      NewLine();\n    }\n\n  AddLF();\n\n  #endif\n\n  RINOK(ReadEntries(bhEntries))\n\n  #ifdef NSIS_SCRIPT\n\n  Separator();\n  AddCommentAndString(\"UNREFERENCED STRINGS:\");\n  AddLF();\n  AddLF();\n  CommentOpen();\n\n  for (i = 0; i < NumStringChars;)\n  {\n    if (!strUsed[i] && i != 0)\n    // Script += \"!!! \";\n    {\n      Add_UInt(i);\n      AddParam(i);\n      NewLine();\n    }\n    if (IsUnicode)\n      i += GetUi16Str_Len((const Byte *)_data + _stringsPos + i * 2);\n    else\n      i += (UInt32)strlen((const char *)(const Byte *)_data + _stringsPos + i);\n    i++;\n  }\n  CommentClose();\n  #endif\n\n  return SortItems();\n}\n\nstatic bool IsLZMA(const Byte *p, UInt32 &dictionary)\n{\n  dictionary = Get32(p + 1);\n  return (p[0] == 0x5D &&\n      p[1] == 0x00 && p[2] == 0x00 &&\n      p[5] == 0x00 && (p[6] & 0x80) == 0x00);\n}\n\nstatic bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)\n{\n  if (IsLZMA(p, dictionary))\n  {\n    thereIsFlag = false;\n    return true;\n  }\n  if (p[0] <= 1 && IsLZMA(p + 1, dictionary))\n  {\n    thereIsFlag = true;\n    return true;\n  }\n  return false;\n}\n\nstatic bool IsBZip2(const Byte *p)\n{\n  return (p[0] == 0x31 && p[1] < 14);\n}\n\nHRESULT CInArchive::Open2(const Byte *sig, size_t size)\n{\n  const UInt32 kSigSize = 4 + 1 + 5 + 2; // size, flag, 5 - lzma props, 2 - lzma first bytes\n  if (size < kSigSize)\n    return S_FALSE;\n\n  _headerIsCompressed = true;\n  IsSolid = true;\n  FilterFlag = false;\n  UseFilter = false;\n  DictionarySize = 1;\n\n  #ifdef NSIS_SCRIPT\n  AfterHeaderSize = 0;\n  #endif\n\n  UInt32 compressedHeaderSize = Get32(sig);\n  \n\n  /*\n    XX XX XX XX             XX XX XX XX == FirstHeader.HeaderSize, nonsolid, uncompressed\n    5D 00 00 dd dd 00       solid LZMA\n    00 5D 00 00 dd dd 00    solid LZMA, empty filter (there are no such archives)\n    01 5D 00 00 dd dd 00    solid LZMA, BCJ filter   (only 7-Zip installer used that format)\n    \n    SS SS SS 80 00 5D 00 00 dd dd 00     non-solid LZMA, empty filter\n    SS SS SS 80 01 5D 00 00 dd dd 00     non-solid LZMA, BCJ filte\n    SS SS SS 80 01 tt         non-solid BZip (tt < 14\n    SS SS SS 80               non-solid  deflate\n\n    01 tt         solid BZip (tt < 14\n    other         solid Deflate\n  */\n\n  if (compressedHeaderSize == FirstHeader.HeaderSize)\n  {\n    _headerIsCompressed = false;\n    IsSolid = false;\n    Method = NMethodType::kCopy;\n  }\n  else if (IsLZMA(sig, DictionarySize, FilterFlag))\n    Method = NMethodType::kLZMA;\n  else if (sig[3] == 0x80)\n  {\n    IsSolid = false;\n    if (IsLZMA(sig + 4, DictionarySize, FilterFlag) && sig[3] == 0x80)\n      Method = NMethodType::kLZMA;\n    else if (IsBZip2(sig + 4))\n      Method = NMethodType::kBZip2;\n    else\n      Method = NMethodType::kDeflate;\n  }\n  else if (IsBZip2(sig))\n    Method = NMethodType::kBZip2;\n  else\n    Method = NMethodType::kDeflate;\n\n  if (IsSolid)\n  {\n    RINOK(SeekTo_DataStreamOffset())\n  }\n  else\n  {\n    _headerIsCompressed = ((compressedHeaderSize & kMask_IsCompressed) != 0);\n    compressedHeaderSize &= ~kMask_IsCompressed;\n    _nonSolidStartOffset = compressedHeaderSize;\n    RINOK(SeekTo(DataStreamOffset + 4))\n  }\n\n  if (FirstHeader.HeaderSize == 0)\n    return S_FALSE;\n\n  _data.Alloc(FirstHeader.HeaderSize);\n  _size = (size_t)FirstHeader.HeaderSize;\n\n  Decoder.Method = Method;\n  Decoder.FilterFlag = FilterFlag;\n  Decoder.Solid = IsSolid;\n  \n  Decoder.IsNsisDeflate = true; // we need some smart check that NSIS is not NSIS3 here.\n  \n  Decoder.InputStream = _stream;\n  Decoder.Buffer.Alloc(kInputBufSize);\n  Decoder.StreamPos = 0;\n\n  if (_headerIsCompressed)\n  {\n    RINOK(Decoder.Init(_stream, UseFilter))\n    if (IsSolid)\n    {\n      size_t processedSize = 4;\n      Byte buf[4];\n      RINOK(Decoder.Read(buf, &processedSize))\n      if (processedSize != 4)\n        return S_FALSE;\n      if (Get32((const Byte *)buf) != FirstHeader.HeaderSize)\n        return S_FALSE;\n    }\n    {\n      size_t processedSize = FirstHeader.HeaderSize;\n      RINOK(Decoder.Read(_data, &processedSize))\n      if (processedSize != FirstHeader.HeaderSize)\n        return S_FALSE;\n    }\n    \n    #ifdef NSIS_SCRIPT\n    if (IsSolid)\n    {\n      /* we need additional bytes for data for WriteRegBin */\n      AfterHeaderSize = (1 << 12);\n      _afterHeader.Alloc(AfterHeaderSize);\n      size_t processedSize = AfterHeaderSize;\n      RINOK(Decoder.Read(_afterHeader, &processedSize))\n      AfterHeaderSize = (UInt32)processedSize;\n    }\n    #endif\n  }\n  else\n  {\n    size_t processedSize = FirstHeader.HeaderSize;\n    RINOK(ReadStream(_stream, (Byte *)_data, &processedSize))\n    if (processedSize < FirstHeader.HeaderSize)\n      return S_FALSE;\n  }\n\n  #ifdef NUM_SPEED_TESTS\n  for (unsigned i = 0; i < NUM_SPEED_TESTS; i++)\n  {\n    RINOK(Parse());\n    Clear2();\n  }\n  #endif\n\n  return Parse();\n}\n\n/*\nNsisExe =\n{\n  ExeStub\n  Archive  // must start from 512 * N\n  #ifndef NSIS_CONFIG_CRC_ANAL\n  {\n    Some additional data\n  }\n}\n\nArchive\n{\n  FirstHeader\n  Data\n  #ifdef NSIS_CONFIG_CRC_SUPPORT && FirstHeader.ThereIsCrc()\n  {\n    CRC\n  }\n}\n\nFirstHeader\n{\n  UInt32 Flags;\n  Byte Signature[16];\n  // points to the header+sections+entries+stringtable in the datablock\n  UInt32 HeaderSize;\n  UInt32 ArcSize;\n}\n*/\n\n\n// ---------- PE (EXE) parsing ----------\n\nstatic const unsigned k_PE_StartSize = 0x40;\nstatic const unsigned k_PE_HeaderSize = 4 + 20;\nstatic const unsigned k_PE_OptHeader32_Size_MIN = 96;\n\nstatic inline bool CheckPeOffset(UInt32 pe)\n{\n  return (pe >= 0x40 && pe <= 0x1000 && (pe & 7) == 0);\n}\n\n\nstatic bool IsArc_Pe(const Byte *p, size_t size)\n{\n  if (size < 2)\n    return false;\n  if (p[0] != 'M' || p[1] != 'Z')\n    return false;\n  if (size < k_PE_StartSize)\n    return false; // k_IsArc_Res_NEED_MORE;\n  UInt32 pe = Get32(p + 0x3C);\n  if (!CheckPeOffset(pe))\n    return false;\n  if (pe + k_PE_HeaderSize > size)\n    return false; // k_IsArc_Res_NEED_MORE;\n\n  p += pe;\n  if (Get32(p) != 0x00004550)\n    return false;\n  return Get16(p + 4 + 16) >= k_PE_OptHeader32_Size_MIN;\n}\n\nHRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition)\n{\n  Clear();\n  \n  RINOK(InStream_GetPos(inStream, StartOffset))\n  \n  const UInt32 kStartHeaderSize = 4 * 7;\n  const unsigned kStep = 512; // nsis start is aligned for 512\n  Byte buf[kStep];\n  UInt64 pos = StartOffset;\n  size_t bufSize = 0;\n  UInt64 pePos = (UInt64)(Int64)-1;\n  \n  for (;;)\n  {\n    bufSize = kStep;\n    RINOK(ReadStream(inStream, buf, &bufSize))\n    if (bufSize < kStartHeaderSize)\n      return S_FALSE;\n    if (memcmp(buf + 4, kSignature, kSignatureSize) == 0)\n      break;\n    if (IsArc_Pe(buf, bufSize))\n      pePos = pos;\n    pos += kStep;\n    UInt64 proc = pos - StartOffset;\n    if (maxCheckStartPosition && proc > *maxCheckStartPosition)\n    {\n      if (pePos == 0)\n      {\n        if (proc > (1 << 20))\n          return S_FALSE;\n      }\n      else\n        return S_FALSE;\n    }\n  }\n  \n  if (pePos == (UInt64)(Int64)-1)\n  {\n    UInt64 posCur = StartOffset;\n    for (;;)\n    {\n      if (posCur < kStep)\n        break;\n      posCur -= kStep;\n      if (pos - posCur > (1 << 20))\n        break;\n      bufSize = kStep;\n      RINOK(InStream_SeekSet(inStream, posCur))\n      RINOK(ReadStream(inStream, buf, &bufSize))\n      if (bufSize < kStep)\n        break;\n      if (IsArc_Pe(buf, bufSize))\n      {\n        pePos = posCur;\n        break;\n      }\n    }\n\n    // restore buf to nsis header\n    bufSize = kStep;\n    RINOK(InStream_SeekSet(inStream, pos))\n    RINOK(ReadStream(inStream, buf, &bufSize))\n    if (bufSize < kStartHeaderSize)\n      return S_FALSE;\n  }\n\n  StartOffset = pos;\n  UInt32 peSize = 0;\n  \n  if (pePos != (UInt64)(Int64)-1)\n  {\n    UInt64 peSize64 = (pos - pePos);\n    if (peSize64 < (1 << 20))\n    {\n      peSize = (UInt32)peSize64;\n      StartOffset = pePos;\n    }\n  }\n\n  DataStreamOffset = pos + kStartHeaderSize;\n  FirstHeader.Flags = Get32(buf);\n  if ((FirstHeader.Flags & (~kFlagsMask)) != 0)\n  {\n    // return E_NOTIMPL;\n    return S_FALSE;\n  }\n  IsInstaller = (FirstHeader.Flags & NFlags::kUninstall) == 0;\n\n  FirstHeader.HeaderSize = Get32(buf + kSignatureSize + 4);\n  FirstHeader.ArcSize = Get32(buf + kSignatureSize + 8);\n  if (FirstHeader.ArcSize <= kStartHeaderSize)\n    return S_FALSE;\n\n  /*\n  if ((FirstHeader.Flags & NFlags::k_BI_ExternalFileSupport) != 0)\n  {\n    UInt32 datablock_low = Get32(buf + kSignatureSize + 12);\n    UInt32 datablock_high = Get32(buf + kSignatureSize + 16);\n  }\n  */\n  \n  RINOK(InStream_GetSize_SeekToEnd(inStream, _fileSize))\n\n  IsArc = true;\n\n  if (peSize != 0)\n  {\n    ExeStub.Alloc(peSize);\n    RINOK(InStream_SeekSet(inStream, pePos))\n    RINOK(ReadStream_FALSE(inStream, ExeStub, peSize))\n  }\n\n  HRESULT res = S_FALSE;\n  try\n  {\n    CLimitedInStream *_limitedStreamSpec = new CLimitedInStream;\n    _stream = _limitedStreamSpec;\n    _limitedStreamSpec->SetStream(inStream);\n    _limitedStreamSpec->InitAndSeek(pos, FirstHeader.ArcSize);\n    DataStreamOffset -= pos;\n    res = Open2(buf + kStartHeaderSize, bufSize - kStartHeaderSize);\n  }\n  catch(...)\n  {\n    _stream.Release();\n    throw;\n    // res = S_FALSE;\n  }\n  if (res != S_OK)\n  {\n    _stream.Release();\n    // Clear();\n  }\n  return res;\n}\n\nUString CInArchive::ConvertToUnicode(const AString &s) const\n{\n  if (IsUnicode)\n  {\n    UString res;\n    // if (\n      ConvertUTF8ToUnicode(s, res);\n      return res;\n  }\n  return MultiByteToUnicodeString(s);\n}\n\nvoid CInArchive::Clear2()\n{\n  IsUnicode = false;\n  NsisType = k_NsisType_Nsis2;\n  IsNsis225 = false;\n  IsNsis200 = false;\n  LogCmdIsEnabled = false;\n  BadCmd = -1;\n  Is64Bit = false;\n\n  #ifdef NSIS_SCRIPT\n  Name.Empty();\n  BrandingText.Empty();\n  Script.Empty();\n  LicenseFiles.Clear();\n  _numRootLicenses = 0;\n  _numLangStrings = 0;\n  langStrIDs.Clear();\n  LangComment.Empty();\n  noParseStringIndexes.Clear();\n  #endif\n\n  APrefixes.Clear();\n  UPrefixes.Clear();\n  Items.Clear();\n  IsUnicode = false;\n  ExeStub.Free();\n}\n\nvoid CInArchive::Clear()\n{\n  Clear2();\n  IsArc = false;\n  _stream.Release();\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/NsisIn.h",
    "content": "﻿// NsisIn.h\n\n#ifndef ZIP7_INC_ARCHIVE_NSIS_IN_H\n#define ZIP7_INC_ARCHIVE_NSIS_IN_H\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/DynLimBuf.h\"\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../Common/StreamUtils.h\"\n\n#include \"NsisDecode.h\"\n\n/* If NSIS_SCRIPT is defined, it will decompile NSIS script to [NSIS].nsi file.\n   The code is much larger in that case. */\n \n// #define NSIS_SCRIPT\n\nnamespace NArchive {\nnamespace NNsis {\n\nconst size_t kScriptSizeLimit = 1 << 27;\n\nconst unsigned kSignatureSize = 16;\nextern const Byte kSignature[kSignatureSize];\n#define NSIS_SIGNATURE { 0xEF, 0xBE, 0xAD, 0xDE, 'N', 'u', 'l', 'l', 's', 'o', 'f', 't', 'I', 'n', 's', 't' }\n\nconst UInt32 kFlagsMask = 0xF;\nnamespace NFlags\n{\n  const UInt32 kUninstall = 1;\n  const UInt32 kSilent = 2;\n  const UInt32 kNoCrc = 4;\n  const UInt32 kForceCrc = 8;\n  // NSISBI fork flags:\n  const UInt32 k_BI_LongOffset = 16;\n  const UInt32 k_BI_ExternalFileSupport = 32;\n  const UInt32 k_BI_ExternalFile = 64;\n  const UInt32 k_BI_IsStubInstaller = 128;\n}\n\nstruct CFirstHeader\n{\n  UInt32 Flags;\n  UInt32 HeaderSize;\n  UInt32 ArcSize;\n\n  bool ThereIsCrc() const\n  {\n    return\n        (Flags & NFlags::kForceCrc) != 0 ||\n        (Flags & NFlags::kNoCrc) == 0;\n  }\n\n  UInt32 GetDataSize() const { return ArcSize - (ThereIsCrc() ? 4 : 0); }\n};\n\n\nstruct CBlockHeader\n{\n  UInt32 Offset;\n  UInt32 Num;\n\n  void Parse(const Byte *p, unsigned bhoSize);\n};\n\nstruct CItem\n{\n  bool IsEmptyFile;\n  bool IsCompressed;\n  bool Size_Defined;\n  bool CompressedSize_Defined;\n  bool EstimatedSize_Defined;\n  bool Attrib_Defined;\n  bool IsUninstaller;\n  // bool UseFilter;\n  \n  UInt32 Attrib;\n  UInt32 Pos;       // = 0, if (IsEmptyFile == true)\n  UInt32 Size;\n  UInt32 CompressedSize;\n  UInt32 EstimatedSize;\n  UInt32 DictionarySize;\n  UInt32 PatchSize; // for Uninstaller.exe\n  int Prefix; // - 1 means no prefix\n\n  FILETIME MTime;\n  AString NameA;\n  UString NameU;\n  \n  bool Is_PatchedUninstaller() const { return PatchSize != 0; }\n  \n  CItem():\n      IsEmptyFile(false),\n      IsCompressed(true),\n      Size_Defined(false),\n      CompressedSize_Defined(false),\n      EstimatedSize_Defined(false),\n      Attrib_Defined(false),\n      IsUninstaller(false),\n      // UseFilter(false),\n      Attrib(0),\n      Pos(0),\n      Size(0),\n      CompressedSize(0),\n      EstimatedSize(0),\n      DictionarySize(1),\n      PatchSize(0),\n      Prefix(-1)\n  {\n    MTime.dwLowDateTime = 0;\n    MTime.dwHighDateTime = 0;\n  }\n\n  /*\n  bool IsINSTDIR() const\n  {\n    return (PrefixA.Len() >= 3 || PrefixU.Len() >= 3);\n  }\n  */\n};\n\nenum ENsisType\n{\n  k_NsisType_Nsis2,\n  k_NsisType_Nsis3,\n  k_NsisType_Park1, // Park 2.46.1-\n  k_NsisType_Park2, // Park 2.46.2  : GetFontVersion\n  k_NsisType_Park3  // Park 2.46.3+ : GetFontName\n};\n\n#ifdef NSIS_SCRIPT\n\nstruct CSection\n{\n  UInt32 InstallTypes; // bits set for each of the different install_types, if any.\n  UInt32 Flags; // SF_* - defined above\n  UInt32 StartCmdIndex; // code;\n  UInt32 NumCommands; // code_size;\n  UInt32 SizeKB;\n  UInt32 Name;\n\n  void Parse(const Byte *data);\n};\n\nstruct CLicenseFile\n{\n  UInt32 Offset;\n  UInt32 Size;\n  AString Name;\n  CByteBuffer Text;\n};\n\n#endif\n\nclass CInArchive\n{\npublic:\n  #ifdef NSIS_SCRIPT\n  CDynLimBuf Script;\n  #endif\n  CByteBuffer _data;\n  CObjectVector<CItem> Items;\n  bool IsUnicode;\n  bool Is64Bit;\nprivate:\n  UInt32 _stringsPos;     // relative to _data\n  UInt32 NumStringChars;\n  size_t _size;           // it's Header Size\n\n  AString Raw_AString;\n  UString Raw_UString;\n\n  ENsisType NsisType;\n  bool IsNsis200; // NSIS 2.03 and before\n  bool IsNsis225; // NSIS 2.25 and before\n  bool LogCmdIsEnabled;\n  int BadCmd; // -1: no bad command; in another cases lowest bad command id\n\n  bool IsPark() const { return NsisType >= k_NsisType_Park1; }\n  bool IsNsis3_OrHigher() const { return NsisType == k_NsisType_Nsis3; }\n\n  UInt64 _fileSize;\n  \n  bool _headerIsCompressed;\n  UInt32 _nonSolidStartOffset;\n\n  #ifdef NSIS_SCRIPT\n  \n  CByteBuffer strUsed;\n\n  CBlockHeader bhPages;\n  CBlockHeader bhSections;\n  CBlockHeader bhCtlColors;\n  CBlockHeader bhData;\n  UInt32 AfterHeaderSize;\n  CByteBuffer _afterHeader;\n\n  UInt32 SectionSize;\n  const Byte *_mainLang;\n  UInt32 _numLangStrings;\n  AString LangComment;\n  CRecordVector<UInt32> langStrIDs;\n  UInt32 numOnFunc;\n  UInt32 onFuncOffset;\n  // CRecordVector<UInt32> OnFuncs;\n  unsigned _numRootLicenses;\n  CRecordVector<UInt32> noParseStringIndexes;\n  AString _tempString_for_GetVar;\n  AString _tempString_for_AddFuncName;\n  AString _tempString;\n\n  #endif\n\n\npublic:\n  CMyComPtr<IInStream> _stream; // it's limited stream that contains only NSIS archive\n  UInt64 StartOffset;           // offset in original stream.\n  UInt64 DataStreamOffset;      // = sizeof(FirstHeader) = offset of Header in _stream\n\n  bool IsArc;\n\n  CDecoder Decoder;\n  CByteBuffer ExeStub;\n  CFirstHeader FirstHeader;\n  NMethodType::EEnum Method;\n  UInt32 DictionarySize;\n  bool IsSolid;\n  bool UseFilter;\n  bool FilterFlag;\n  \n  bool IsInstaller;\n  AString Name;\n  AString BrandingText;\n  UStringVector UPrefixes;\n  AStringVector APrefixes;\n\n  #ifdef NSIS_SCRIPT\n  CObjectVector<CLicenseFile> LicenseFiles;\n  #endif\n\nprivate:\n  void GetShellString(AString &s, unsigned index1, unsigned index2);\n  void GetNsisString_Raw(const Byte *s);\n  void GetNsisString_Unicode_Raw(const Byte *s);\n  void ReadString2_Raw(UInt32 pos);\n  bool IsGoodString(UInt32 param) const;\n  bool AreTwoParamStringsEqual(UInt32 param1, UInt32 param2) const;\n\n  void Add_LangStr(AString &res, UInt32 id);\n\n  #ifdef NSIS_SCRIPT\n\n  void Add_UInt(UInt32 v);\n  void AddLicense(UInt32 param, Int32 langID);\n\n  void Add_LangStr_Simple(UInt32 id);\n  void Add_FuncName(const UInt32 *labels, UInt32 index);\n  void AddParam_Func(const UInt32 *labels, UInt32 index);\n  void Add_LabelName(UInt32 index);\n\n  void Add_Color2(UInt32 v);\n  void Add_ColorParam(UInt32 v);\n  void Add_Color(UInt32 index);\n\n  void Add_ButtonID(UInt32 buttonID);\n\n  void Add_ShowWindow_Cmd(UInt32 cmd);\n  void Add_TypeFromList(const char * const *table, unsigned tableSize, UInt32 type);\n  void Add_ExecFlags(UInt32 flagsType);\n  void Add_SectOp(UInt32 opType);\n\n  void Add_Var(UInt32 index);\n  void AddParam_Var(UInt32 value);\n  void AddParam_UInt(UInt32 value);\n\n  void Add_GotoVar(UInt32 param);\n  void Add_GotoVar1(UInt32 param);\n  void Add_GotoVars2(const UInt32 *params);\n\n\n \n  bool PrintSectionBegin(const CSection &sect, unsigned index);\n  void PrintSectionEnd();\n\n  void GetNsisString(AString &res, const Byte *s);\n  void GetNsisString_Unicode(AString &res, const Byte *s);\n  UInt32 GetNumUsedVars() const;\n  void ReadString2(AString &s, UInt32 pos);\n\n  void MessageBox_MB_Part(UInt32 param);\n  void AddParam(UInt32 pos);\n  void AddOptionalParam(UInt32 pos);\n  void AddParams(const UInt32 *params, unsigned num);\n  void AddPageOption1(UInt32 param, const char *name);\n  void AddPageOption(const UInt32 *params, unsigned num, const char *name);\n  void AddOptionalParams(const UInt32 *params, unsigned num);\n  void AddRegRoot(UInt32 value);\n\n \n  void ClearLangComment();\n  void Separator();\n  void Space();\n  void Tab();\n  void Tab(bool commented);\n  void BigSpaceComment();\n  void SmallSpaceComment();\n  void AddCommentAndString(const char *s);\n  void AddError(const char *s);\n  void AddErrorLF(const char *s);\n  void CommentOpen();\n  void CommentClose();\n  void AddLF();\n  void AddQuotes();\n  void TabString(const char *s);\n  void AddStringLF(const char *s);\n  void NewLine();\n  void PrintNumComment(const char *name, UInt32 value);\n  void Add_QuStr(const AString &s);\n  void SpaceQuStr(const AString &s);\n  bool CompareCommands(const Byte *rawCmds, const Byte *sequence, size_t numCommands);\n\n  #endif\n\n  #ifdef NSIS_SCRIPT\n  unsigned GetNumSupportedCommands() const;\n  #endif\n\n  UInt32 GetCmd(UInt32 a);\n  void FindBadCmd(const CBlockHeader &bh, const Byte *);\n  void DetectNsisType(const CBlockHeader &bh, const Byte *);\n\n  HRESULT ReadEntries(const CBlockHeader &bh);\n  HRESULT SortItems();\n  HRESULT Parse();\n  HRESULT Open2(const Byte *data, size_t size);\n  void Clear2();\n\n  void GetVar2(AString &res, UInt32 index);\n  void GetVar(AString &res, UInt32 index);\n  Int32 GetVarIndex(UInt32 strPos) const;\n  Int32 GetVarIndex(UInt32 strPos, UInt32 &resOffset) const;\n  Int32 GetVarIndexFinished(UInt32 strPos, Byte endChar, UInt32 &resOffset) const;\n  bool IsVarStr(UInt32 strPos, UInt32 varIndex) const;\n  bool IsAbsolutePathVar(UInt32 strPos) const;\n  void SetItemName(CItem &item, UInt32 strPos);\n\npublic:\n  HRESULT Open(IInStream *inStream, const UInt64 *maxCheckStartPosition);\n  AString GetFormatDescription() const;\n  HRESULT InitDecoder()\n  {\n    bool useFilter;\n    return Decoder.Init(_stream, useFilter);\n  }\n\n  HRESULT SeekTo(UInt64 pos)\n  {\n    return InStream_SeekSet(_stream, pos);\n  }\n\n  HRESULT SeekTo_DataStreamOffset()\n  {\n    return SeekTo(DataStreamOffset);\n  }\n\n  HRESULT SeekToNonSolidItem(unsigned index)\n  {\n    return SeekTo(GetPosOfNonSolidItem(index));\n  }\n\n  void Clear();\n\n  bool IsDirectString_Equal(UInt32 offset, const char *s) const;\n  /*\n  UInt64 GetDataPos(unsigned index)\n  {\n    const CItem &item = Items[index];\n    return GetOffset() + FirstHeader.HeaderSize + item.Pos;\n  }\n  */\n\n  UInt64 GetPosOfSolidItem(unsigned index) const\n  {\n    const CItem &item = Items[index];\n    return 4 + (UInt64)FirstHeader.HeaderSize + item.Pos;\n  }\n  \n  UInt64 GetPosOfNonSolidItem(unsigned index) const\n  {\n    const CItem &item = Items[index];\n    return DataStreamOffset + _nonSolidStartOffset + 4 + item.Pos;\n  }\n\n  void Release()\n  {\n    Decoder.Release();\n  }\n\n  bool IsTruncated() const { return (_fileSize - StartOffset < FirstHeader.ArcSize); }\n\n  UString GetReducedName(unsigned index) const\n  {\n    const CItem &item = Items[index];\n\n    UString s;\n    if (item.Prefix >= 0)\n    {\n      if (IsUnicode)\n        s = UPrefixes[item.Prefix];\n      else\n        s = MultiByteToUnicodeString(APrefixes[item.Prefix]);\n      if (s.Len() > 0)\n        if (s.Back() != L'\\\\')\n          s.Add_Char('\\\\');\n    }\n\n    if (IsUnicode)\n    {\n      s += item.NameU;\n      if (item.NameU.IsEmpty())\n        s += \"file\";\n    }\n    else\n    {\n      s += MultiByteToUnicodeString(item.NameA);\n      if (item.NameA.IsEmpty())\n        s += \"file\";\n    }\n    \n    const char * const kRemoveStr = \"$INSTDIR\\\\\";\n    if (s.IsPrefixedBy_Ascii_NoCase(kRemoveStr))\n    {\n      s.Delete(0, MyStringLen(kRemoveStr));\n      if (s[0] == L'\\\\')\n        s.DeleteFrontal(1);\n    }\n    if (item.Is_PatchedUninstaller() && ExeStub.Size() == 0)\n      s += \".nsis\";\n    return s;\n  }\n\n  UString ConvertToUnicode(const AString &s) const;\n\n  CInArchive()\n    #ifdef NSIS_SCRIPT\n      : Script(kScriptSizeLimit)\n    #endif\n    {}\n};\n\n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/NsisRegister.cpp",
    "content": "﻿// NsisRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/RegisterArc.h\"\n\n#include \"NsisHandler.h\"\n\nnamespace NArchive {\nnamespace NNsis {\n\nREGISTER_ARC_I(\n  \"Nsis\", \"nsis\", NULL, 0x9,\n  kSignature,\n  4,\n  NArcInfoFlags::kFindSignature |\n  NArcInfoFlags::kUseGlobalOffset,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Nsis/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/NtfsHandler.cpp",
    "content": "﻿// NtfsHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n// #define SHOW_DEBUG_INFO2\n\n#if defined(SHOW_DEBUG_INFO) || defined(SHOW_DEBUG_INFO2)\n#include <stdio.h>\n#endif\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyCom.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/MethodProps.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/DummyOutStream.h\"\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#define PRF_UTF16(x) PRF(printf(\"%S\", x))\n#else\n#define PRF(x)\n#define PRF_UTF16(x)\n#endif\n\n#ifdef SHOW_DEBUG_INFO2\n#define PRF2(x) x\n#else\n#define PRF2(x)\n#endif\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define G16(p, dest) dest = Get16(p)\n#define G32(p, dest) dest = Get32(p)\n#define G64(p, dest) dest = Get64(p)\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace Ntfs {\n\nstatic const wchar_t * const kVirtualFolder_System = L\"[SYSTEM]\";\nstatic const wchar_t * const kVirtualFolder_Lost_Normal = L\"[LOST]\";\nstatic const wchar_t * const kVirtualFolder_Lost_Deleted = L\"[UNKNOWN]\";\n\nstatic const unsigned kNumSysRecs = 16;\n\nstatic const unsigned kRecIndex_Volume    = 3;\nstatic const unsigned kRecIndex_RootDir   = 5;\nstatic const unsigned kRecIndex_BadClus   = 8;\nstatic const unsigned kRecIndex_Security  = 9;\n\nstruct CHeader\n{\n  unsigned SectorSizeLog;\n  unsigned ClusterSizeLog;\n  unsigned MftRecordSizeLog;\n  // Byte MediaType;\n  // UInt32 NumHiddenSectors;\n  UInt64 NumSectors;\n  UInt64 NumClusters;\n  UInt64 MftCluster;\n  UInt64 SerialNumber;\n  // UInt16 SectorsPerTrack;\n  // UInt16 NumHeads;\n\n  UInt64 GetPhySize_Clusters() const { return NumClusters << ClusterSizeLog; }\n  UInt64 GetPhySize_Max() const { return (NumSectors + 1) << SectorSizeLog; }\n  UInt32 ClusterSize() const { return (UInt32)1 << ClusterSizeLog; }\n  bool Parse(const Byte *p);\n};\n\nstatic int GetLog(UInt32 num)\n{\n  for (int i = 0; i < 31; i++)\n    if (((UInt32)1 << i) == num)\n      return i;\n  return -1;\n}\n\nbool CHeader::Parse(const Byte *p)\n{\n  if (p[0x1FE] != 0x55 || p[0x1FF] != 0xAA)\n    return false;\n\n  // int codeOffset = 0;\n  switch (p[0])\n  {\n    case 0xE9: /* codeOffset = 3 + (Int16)Get16(p + 1); */ break;\n    case 0xEB: if (p[2] != 0x90) return false; /* codeOffset = 2 + (int)(signed char)p[1]; */ break;\n    default: return false;\n  }\n  unsigned sectorsPerClusterLog;\n\n  if (memcmp(p + 3, \"NTFS    \", 8) != 0)\n    return false;\n  {\n    {\n      const int t = GetLog(Get16(p + 11));\n      if (t < 9 || t > 12)\n        return false;\n      SectorSizeLog = (unsigned)t;\n    }\n    {\n      const unsigned v = p[13];\n      if (v <= 0x80)\n      {\n        const int t = GetLog(v);\n        if (t < 0)\n          return false;\n        sectorsPerClusterLog = (unsigned)t;\n      }\n      else\n        sectorsPerClusterLog = 0x100 - v;\n      ClusterSizeLog = SectorSizeLog + sectorsPerClusterLog;\n      if (ClusterSizeLog > 30)\n        return false;\n    }\n  }\n\n  for (int i = 14; i < 21; i++)\n    if (p[i] != 0)\n      return false;\n\n  // F8 : a hard disk\n  // F0 : high-density 3.5-inch floppy disk\n  if (p[21] != 0xF8) // MediaType = Fixed_Disk\n    return false;\n  if (Get16(p + 22) != 0) // NumFatSectors\n    return false;\n  // G16(p + 24, SectorsPerTrack); // 63 usually\n  // G16(p + 26, NumHeads); // 255\n  // G32(p + 28, NumHiddenSectors); // 63 (XP) / 2048 (Vista and win7) / (0 on media that are not partitioned ?)\n  if (Get32(p + 32) != 0) // NumSectors32\n    return false;\n\n  // DriveNumber = p[0x24];\n  if (p[0x25] != 0) // CurrentHead\n    return false;\n  /*\n  NTFS-HDD:   p[0x26] = 0x80\n  NTFS-FLASH: p[0x26] = 0\n  */\n  if (p[0x26] != 0x80 && p[0x26] != 0) // ExtendedBootSig\n    return false;\n  if (p[0x27] != 0) // reserved\n    return false;\n  \n  NumSectors = Get64(p + 0x28);\n  if (NumSectors >= ((UInt64)1 << (62 - SectorSizeLog)))\n    return false;\n\n  NumClusters = NumSectors >> sectorsPerClusterLog;\n\n  G64(p + 0x30, MftCluster);   // $MFT.\n  // G64(p + 0x38, Mft2Cluster);\n  G64(p + 0x48, SerialNumber); // $MFTMirr\n\n  /*\n    numClusters_per_MftRecord:\n    numClusters_per_IndexBlock:\n    only low byte from 4 bytes is used. Another 3 high bytes are zeros.\n      If the number is positive (number < 0x80),\n          then it represents the number of clusters.\n      If the number is negative (number >= 0x80),\n          then the size of the file record is 2 raised to the absolute value of this number.\n          example: (0xF6 == -10) means 2^10 = 1024 bytes.\n  */\n  {\n    UInt32 numClusters_per_MftRecord;\n    G32(p + 0x40, numClusters_per_MftRecord);\n    if (numClusters_per_MftRecord >= 0x100 || numClusters_per_MftRecord == 0)\n      return false;\n    if (numClusters_per_MftRecord < 0x80)\n    {\n      const int t = GetLog(numClusters_per_MftRecord);\n      if (t < 0)\n        return false;\n      MftRecordSizeLog = (unsigned)t + ClusterSizeLog;\n    }\n    else\n      MftRecordSizeLog = 0x100 - numClusters_per_MftRecord;\n    // what exact MFT record sizes are possible and supported by Windows?\n    // do we need to change this limit here?\n    const unsigned k_MftRecordSizeLog_MAX = 12;\n    if (MftRecordSizeLog > k_MftRecordSizeLog_MAX)\n      return false;\n    if (MftRecordSizeLog < SectorSizeLog)\n      return false;\n  }\n  {\n    UInt32 numClusters_per_IndexBlock;\n    G32(p + 0x44, numClusters_per_IndexBlock);\n    return (numClusters_per_IndexBlock < 0x100);\n  }\n}\n\nstruct CMftRef\n{\n  UInt64 Val;\n  \n  UInt64 GetIndex() const { return Val & (((UInt64)1 << 48) - 1); }\n  UInt16 GetNumber() const { return (UInt16)(Val >> 48); }\n  bool IsBaseItself() const { return Val == 0; }\n\n  CMftRef(): Val(0) {}\n};\n\n#define ATNAME(n) ATTR_TYPE_ ## n\n#define DEF_ATTR_TYPE(v, n) ATNAME(n) = v\n\nenum\n{\n  DEF_ATTR_TYPE(0x00, UNUSED),\n  DEF_ATTR_TYPE(0x10, STANDARD_INFO),\n  DEF_ATTR_TYPE(0x20, ATTRIBUTE_LIST),\n  DEF_ATTR_TYPE(0x30, FILE_NAME),\n  DEF_ATTR_TYPE(0x40, OBJECT_ID),\n  DEF_ATTR_TYPE(0x50, SECURITY_DESCRIPTOR),\n  DEF_ATTR_TYPE(0x60, VOLUME_NAME),\n  DEF_ATTR_TYPE(0x70, VOLUME_INFO),\n  DEF_ATTR_TYPE(0x80, DATA),\n  DEF_ATTR_TYPE(0x90, INDEX_ROOT),\n  DEF_ATTR_TYPE(0xA0, INDEX_ALLOCATION),\n  DEF_ATTR_TYPE(0xB0, BITMAP),\n  DEF_ATTR_TYPE(0xC0, REPARSE_POINT),\n  DEF_ATTR_TYPE(0xD0, EA_INFO),\n  DEF_ATTR_TYPE(0xE0, EA),\n  DEF_ATTR_TYPE(0xF0, PROPERTY_SET),\n  DEF_ATTR_TYPE(0x100, LOGGED_UTILITY_STREAM),\n  DEF_ATTR_TYPE(0x1000, FIRST_USER_DEFINED_ATTRIBUTE)\n};\n\n\n/* WinXP-64:\n    Probably only one short name (dos name) per record is allowed.\n    There are no short names for hard links.\n   The pair (Win32,Dos) can be in any order.\n   Posix name can be after or before Win32 name\n*/\n\n// static const Byte kFileNameType_Posix     = 0; // for hard links\nstatic const Byte kFileNameType_Win32     = 1; // after Dos name\nstatic const Byte kFileNameType_Dos       = 2; // short name\nstatic const Byte kFileNameType_Win32Dos  = 3; // short and full name are same\n\nstruct CFileNameAttr\n{\n  CMftRef ParentDirRef;\n\n  // Probably these timestamps don't contain some useful timestamps. So we don't use them\n  // UInt64 CTime;\n  // UInt64 MTime;\n  // UInt64 ThisRecMTime;  // xp-64: the time of previous name change (not last name change. why?)\n  // UInt64 ATime;\n  // UInt64 AllocatedSize;\n  // UInt64 DataSize;\n  // UInt16 PackedEaSize;\n  UString2 Name;\n  UInt32 Attrib;\n  Byte NameType;\n  \n  bool IsDos() const { return NameType == kFileNameType_Dos; }\n  bool IsWin32() const { return (NameType == kFileNameType_Win32); }\n\n  bool Parse(const Byte *p, unsigned size);\n\n  CFileNameAttr():\n      Attrib(0),\n      NameType(0)\n      {}\n};\n\nstatic void GetString(const Byte *p, const unsigned len, UString2 &res)\n{\n  if (len == 0 && res.IsEmpty())\n    return;\n  wchar_t *s = res.GetBuf(len);\n  unsigned i;\n  for (i = 0; i < len; i++)\n  {\n    const wchar_t c = Get16(p + i * 2);\n    if (c == 0)\n      break;\n    s[i] = c;\n  }\n  s[i] = 0;\n  res.ReleaseBuf_SetLen(i);\n}\n\nbool CFileNameAttr::Parse(const Byte *p, unsigned size)\n{\n  if (size < 0x42)\n    return false;\n  G64(p + 0x00, ParentDirRef.Val);\n  // G64(p + 0x08, CTime);\n  // G64(p + 0x10, MTime);\n  // G64(p + 0x18, ThisRecMTime);\n  // G64(p + 0x20, ATime);\n  // G64(p + 0x28, AllocatedSize);\n  // G64(p + 0x30, DataSize);\n  G32(p + 0x38, Attrib);\n  // G16(p + 0x3C, PackedEaSize);\n  NameType = p[0x41];\n  const unsigned len = p[0x40];\n  if (0x42 + len * 2 > size)\n    return false;\n  if (len != 0)\n    GetString(p + 0x42, len, Name);\n  return true;\n}\n\nstruct CSiAttr\n{\n  UInt64 CTime;\n  UInt64 MTime;\n  UInt64 ThisRecMTime;\n  UInt64 ATime;\n  UInt32 Attrib;\n\n  /*\n  UInt32 MaxVersions;\n  UInt32 Version;\n  UInt32 ClassId;\n  UInt32 OwnerId;\n  */\n  UInt32 SecurityId; // SecurityId = 0 is possible ?\n  // UInt64 QuotaCharged;\n\n  bool Parse(const Byte *p, unsigned size);\n\n  CSiAttr():\n      CTime(0),\n      MTime(0),\n      ThisRecMTime(0),\n      ATime(0),\n      Attrib(0),\n      SecurityId(0)\n      {}\n};\n\n\nbool CSiAttr::Parse(const Byte *p, unsigned size)\n{\n  if (size < 0x24)\n    return false;\n  G64(p + 0x00, CTime);\n  G64(p + 0x08, MTime);\n  G64(p + 0x10, ThisRecMTime);\n  G64(p + 0x18, ATime);\n  G32(p + 0x20, Attrib);\n  SecurityId = 0;\n  if (size >= 0x38)\n    G32(p + 0x34, SecurityId);\n  return true;\n}\n\nstatic const UInt64 kEmptyExtent = (UInt64)(Int64)-1;\n\nstruct CExtent\n{\n  UInt64 Virt;\n  UInt64 Phy;\n\n  bool IsEmpty() const { return Phy == kEmptyExtent; }\n};\n\nstruct CVolInfo\n{\n  Byte MajorVer;\n  Byte MinorVer;\n  // UInt16 Flags;\n\n  bool Parse(const Byte *p, unsigned size);\n};\n\nbool CVolInfo::Parse(const Byte *p, unsigned size)\n{\n  if (size < 12)\n    return false;\n  MajorVer = p[8];\n  MinorVer = p[9];\n  // Flags = Get16(p + 10);\n  return true;\n}\n\nstruct CAttr\n{\n  UInt32 Type;\n\n  Byte NonResident;\n\n  // Non-Resident\n  Byte CompressionUnit;\n\n  // UInt32 Len;\n  UString2 Name;\n  // UInt16 Flags;\n  // UInt16 Instance;\n  CByteBuffer Data;\n\n  // Non-Resident\n  UInt64 LowVcn;\n  UInt64 HighVcn;\n  UInt64 AllocatedSize;\n  UInt64 Size;\n  UInt64 PackSize;\n  UInt64 InitializedSize;\n\n  // Resident\n  // UInt16 ResidentFlags;\n\n  bool IsCompressionUnitSupported() const { return CompressionUnit == 0 || CompressionUnit == 4; }\n\n  UInt32 Parse(const Byte *p, unsigned size);\n  bool ParseFileName(CFileNameAttr &a) const { return a.Parse(Data, (unsigned)Data.Size()); }\n  bool ParseSi(CSiAttr &a) const { return a.Parse(Data, (unsigned)Data.Size()); }\n  bool ParseVolInfo(CVolInfo &a) const { return a.Parse(Data, (unsigned)Data.Size()); }\n  bool ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, unsigned compressionUnit) const;\n  UInt64 GetSize() const { return NonResident ? Size : Data.Size(); }\n  UInt64 GetPackSize() const\n  {\n    if (!NonResident)\n      return Data.Size();\n    if (CompressionUnit != 0)\n      return PackSize;\n    return AllocatedSize;\n  }\n};\n\n#define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }\n\nstatic int CompareAttr(void *const *elem1, void *const *elem2, void *)\n{\n  const CAttr &a1 = *(*((const CAttr *const *)elem1));\n  const CAttr &a2 = *(*((const CAttr *const *)elem2));\n  RINOZ(MyCompare(a1.Type, a2.Type))\n  if (a1.Name.IsEmpty())\n  {\n    if (!a2.Name.IsEmpty())\n      return -1;\n  }\n  else if (a2.Name.IsEmpty())\n    return 1;\n  else\n  {\n    RINOZ(a1.Name.Compare(a2.Name.GetRawPtr()))\n  }\n  return MyCompare(a1.LowVcn, a2.LowVcn);\n}\n\nUInt32 CAttr::Parse(const Byte *p, unsigned size)\n{\n  if (size < 4)\n    return 0;\n  G32(p, Type);\n  if (Type == 0xFFFFFFFF)\n    return 8; // required size is 4, but attributes are 8 bytes aligned. So we return 8\n  if (size < 0x18)\n    return 0;\n\n  PRF(printf(\" T=%2X\", Type));\n  \n  UInt32 len = Get32(p + 4);\n  PRF(printf(\" L=%3d\", len));\n  if (len > size)\n    return 0;\n  if ((len & 7) != 0)\n    return 0;\n  NonResident = p[8];\n  {\n    unsigned nameLen = p[9];\n    UInt32 nameOffset = Get16(p + 0x0A);\n    if (nameLen != 0)\n    {\n      if (nameOffset + nameLen * 2 > len)\n        return 0;\n      GetString(p + nameOffset, nameLen, Name);\n      PRF(printf(\" N=\"));\n      PRF_UTF16(Name);\n    }\n  }\n\n  // G16(p + 0x0C, Flags);\n  // G16(p + 0x0E, Instance);\n  // PRF(printf(\" F=%4X\", Flags));\n  // PRF(printf(\" Inst=%d\", Instance));\n\n  UInt32 dataSize;\n  UInt32 offs;\n  \n  if (NonResident)\n  {\n    if (len < 0x40)\n      return 0;\n    PRF(printf(\" NR\"));\n    G64(p + 0x10, LowVcn);\n    G64(p + 0x18, HighVcn);\n    G64(p + 0x28, AllocatedSize);\n    G64(p + 0x30, Size);\n    G64(p + 0x38, InitializedSize);\n    G16(p + 0x20, offs);\n    CompressionUnit = p[0x22];\n\n    PackSize = Size;\n    if (CompressionUnit != 0)\n    {\n      if (len < 0x48)\n        return 0;\n      G64(p + 0x40, PackSize);\n      PRF(printf(\" PS=%I64x\", PackSize));\n    }\n\n    // PRF(printf(\"\\n\"));\n    PRF(printf(\" ASize=%4I64d\", AllocatedSize));\n    PRF(printf(\" Size=%I64d\", Size));\n    PRF(printf(\" IS=%I64d\", InitializedSize));\n    PRF(printf(\" Low=%I64d\", LowVcn));\n    PRF(printf(\" High=%I64d\", HighVcn));\n    PRF(printf(\" CU=%d\", (unsigned)CompressionUnit));\n    dataSize = len - offs;\n  }\n  else\n  {\n    if (len < 0x18)\n      return 0;\n    G32(p + 0x10, dataSize);\n    G16(p + 0x14, offs);\n    // G16(p + 0x16, ResidentFlags);\n    PRF(printf(\" RES\"));\n    PRF(printf(\" dataSize=%3d\", dataSize));\n    // PRF(printf(\" ResFlags=%4X\", ResidentFlags));\n  }\n  \n  if (offs > len || dataSize > len || len - dataSize < offs)\n    return 0;\n  \n  Data.CopyFrom(p + offs, dataSize);\n  \n  #ifdef SHOW_DEBUG_INFO\n  PRF(printf(\"  : \"));\n  for (unsigned i = 0; i < Data.Size(); i++)\n  {\n    PRF(printf(\" %02X\", (unsigned)Data[i]));\n  }\n  #endif\n  \n  return len;\n}\n\n\nbool CAttr::ParseExtents(CRecordVector<CExtent> &extents, UInt64 numClustersMax, unsigned compressionUnit) const\n{\n  const Byte *p = Data;\n  unsigned size = (unsigned)Data.Size();\n  UInt64 vcn = LowVcn;\n  UInt64 lcn = 0;\n  const UInt64 highVcn1 = HighVcn + 1;\n  \n  if (LowVcn != extents.Back().Virt || highVcn1 > (UInt64)1 << 63)\n    return false;\n\n  extents.DeleteBack();\n\n  PRF2(printf(\"\\n# ParseExtents # LowVcn = %4I64X # HighVcn = %4I64X\", LowVcn, HighVcn));\n\n  while (size > 0)\n  {\n    const unsigned b = *p++;\n    size--;\n    if (b == 0)\n      break;\n    unsigned num = b & 0xF;\n    if (num == 0 || num > 8 || num > size)\n      return false;\n\n    UInt64 vSize = 0;\n    {\n      unsigned i = num;\n      do vSize = (vSize << 8) | p[--i]; while (i);\n    }\n    if (vSize == 0)\n      return false;\n    p += num;\n    size -= num;\n    if ((highVcn1 - vcn) < vSize)\n      return false;\n\n    CExtent e;\n    e.Virt = vcn;\n    vcn += vSize;\n\n    num = b >> 4;\n    if (num > 8 || num > size)\n      return false;\n    \n    if (num == 0)\n    {\n      // Sparse\n      \n      /* if Unit is compressed, it can have many Elements for each compressed Unit:\n         and last Element for unit MUST be without LCN.\n           Element 0: numCompressedClusters2, LCN_0\n           Element 1: numCompressedClusters2, LCN_1\n           ...\n           Last Element : (16 - total_clusters_in_previous_elements), no LCN\n      */\n      \n      // sparse is not allowed for (compressionUnit == 0) ? Why ?\n      if (compressionUnit == 0)\n        return false;\n\n      e.Phy = kEmptyExtent;\n    }\n    else\n    {\n      Int64 v = (signed char)p[num - 1];\n      {\n        for (unsigned i = num - 1; i != 0;)\n          v = (v << 8) | p[--i];\n      }\n      p += num;\n      size -= num;\n      lcn = (UInt64)((Int64)lcn + v);\n      if (lcn > numClustersMax)\n        return false;\n      e.Phy = lcn;\n    }\n    \n    extents.Add(e);\n  }\n\n  CExtent e;\n  e.Phy = kEmptyExtent;\n  e.Virt = vcn;\n  extents.Add(e);\n  return (highVcn1 == vcn);\n}\n\n\nstatic const UInt64 kEmptyTag = (UInt64)(Int64)-1;\n\nstatic const unsigned kNumCacheChunksLog = 1;\nstatic const size_t kNumCacheChunks = (size_t)1 << kNumCacheChunksLog;\n\nZ7_CLASS_IMP_IInStream(\n  CInStream\n)\n  UInt64 _virtPos;\n  UInt64 _physPos;\n  UInt64 _curRem;\n  bool _sparseMode;\npublic:\n  bool InUse;\nprivate:\n  unsigned _chunkSizeLog;\n  CByteBuffer _inBuf;\n  CByteBuffer _outBuf;\npublic:\n  UInt64 Size;\n  UInt64 InitializedSize;\n  unsigned BlockSizeLog;\n  unsigned CompressionUnit;\n  CRecordVector<CExtent> Extents;\n  CMyComPtr<IInStream> Stream;\nprivate:\n  UInt64 _tags[kNumCacheChunks];\n\n  HRESULT SeekToPhys() { return InStream_SeekSet(Stream, _physPos); }\n  UInt32 GetCuSize() const { return (UInt32)1 << (BlockSizeLog + CompressionUnit); }\npublic:\n  HRESULT InitAndSeek(unsigned compressionUnit)\n  {\n    CompressionUnit = compressionUnit;\n    _chunkSizeLog = BlockSizeLog + CompressionUnit;\n    if (compressionUnit != 0)\n    {\n      UInt32 cuSize = GetCuSize();\n      _inBuf.Alloc(cuSize);\n      _outBuf.Alloc(kNumCacheChunks << _chunkSizeLog);\n    }\n    for (size_t i = 0; i < kNumCacheChunks; i++)\n      _tags[i] = kEmptyTag;\n\n    _sparseMode = false;\n    _curRem = 0;\n    _virtPos = 0;\n    _physPos = 0;\n    const CExtent &e = Extents[0];\n    if (!e.IsEmpty())\n      _physPos = e.Phy << BlockSizeLog;\n    return SeekToPhys();\n  }\n};\n\nstatic size_t Lznt1Dec(Byte *dest, size_t outBufLim, size_t destLen, const Byte *src, size_t srcLen)\n{\n  size_t destSize = 0;\n  while (destSize < destLen)\n  {\n    if (srcLen < 2 || (destSize & 0xFFF) != 0)\n      break;\n    UInt32 comprSize;\n    {\n      const UInt32 v = Get16(src);\n      if (v == 0)\n        break;\n      src += 2;\n      srcLen -= 2;\n      comprSize = (v & 0xFFF) + 1;\n      if (comprSize > srcLen)\n        break;\n      srcLen -= comprSize;\n      if ((v & 0x8000) == 0)\n      {\n        if (comprSize != (1 << 12))\n          break;\n        memcpy(dest + destSize, src, comprSize);\n        src += comprSize;\n        destSize += comprSize;\n        continue;\n      }\n    }\n    {\n      if (destSize + (1 << 12) > outBufLim || (src[0] & 1) != 0)\n        return 0;\n      unsigned numDistBits = 4;\n      UInt32 sbOffset = 0;\n      UInt32 pos = 0;\n\n      do\n      {\n        comprSize--;\n        for (UInt32 mask = src[pos++] | 0x100; mask > 1 && comprSize > 0; mask >>= 1)\n        {\n          if ((mask & 1) == 0)\n          {\n            if (sbOffset >= (1 << 12))\n              return 0;\n            dest[destSize++] = src[pos++];\n            sbOffset++;\n            comprSize--;\n          }\n          else\n          {\n            if (comprSize < 2)\n              return 0;\n            const UInt32 v = Get16(src + pos);\n            pos += 2;\n            comprSize -= 2;\n\n            while (((sbOffset - 1) >> numDistBits) != 0)\n              numDistBits++;\n\n            UInt32 len = (v & (0xFFFF >> numDistBits)) + 3;\n            if (sbOffset + len > (1 << 12))\n              return 0;\n            UInt32 dist = (v >> (16 - numDistBits));\n            if (dist >= sbOffset)\n              return 0;\n            const size_t offs = 1 + dist;\n            Byte *p = dest + destSize - offs;\n            destSize += len;\n            sbOffset += len;\n            const Byte *lim = p + len;\n            p[offs] = *p; ++p;\n            p[offs] = *p; ++p;\n            do\n              p[offs] = *p;\n            while (++p != lim);\n          }\n        }\n      }\n      while (comprSize > 0);\n      src += pos;\n    }\n  }\n  return destSize;\n}\n\nZ7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= Size)\n    return (Size == _virtPos) ? S_OK: E_FAIL;\n  if (size == 0)\n    return S_OK;\n  {\n    const UInt64 rem = Size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n\n  if (_virtPos >= InitializedSize)\n  {\n    memset((Byte *)data, 0, size);\n    _virtPos += size;\n    *processedSize = size;\n    return S_OK;\n  }\n\n  {\n    const UInt64 rem = InitializedSize - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n\n  while (_curRem == 0)\n  {\n    const UInt64 cacheTag = _virtPos >> _chunkSizeLog;\n    const size_t cacheIndex = (size_t)cacheTag & (kNumCacheChunks - 1);\n    \n    if (_tags[cacheIndex] == cacheTag)\n    {\n      const size_t chunkSize = (size_t)1 << _chunkSizeLog;\n      const size_t offset = (size_t)_virtPos & (chunkSize - 1);\n      size_t cur = chunkSize - offset;\n      if (cur > size)\n        cur = size;\n      memcpy(data, _outBuf + (cacheIndex << _chunkSizeLog) + offset, cur);\n      *processedSize = (UInt32)cur;\n      _virtPos += cur;\n      return S_OK;\n    }\n\n    PRF2(printf(\"\\nVirtPos = %6d\", _virtPos));\n    \n    const UInt32 comprUnitSize = (UInt32)1 << CompressionUnit;\n    const UInt64 virtBlock = _virtPos >> BlockSizeLog;\n    const UInt64 virtBlock2 = virtBlock & ~((UInt64)comprUnitSize - 1);\n    \n    unsigned left = 0, right = Extents.Size();\n    for (;;)\n    {\n      unsigned mid = (left + right) / 2;\n      if (mid == left)\n        break;\n      if (virtBlock2 < Extents[mid].Virt)\n        right = mid;\n      else\n        left = mid;\n    }\n    \n    bool isCompressed = false;\n    const UInt64 virtBlock2End = virtBlock2 + comprUnitSize;\n    if (CompressionUnit != 0)\n      for (unsigned i = left; i < Extents.Size(); i++)\n      {\n        const CExtent &e = Extents[i];\n        if (e.Virt >= virtBlock2End)\n          break;\n        if (e.IsEmpty())\n        {\n          isCompressed = true;\n          break;\n        }\n      }\n\n    unsigned i;\n    for (i = left; Extents[i + 1].Virt <= virtBlock; i++);\n    \n    _sparseMode = false;\n    if (!isCompressed)\n    {\n      const CExtent &e = Extents[i];\n      UInt64 newPos = (e.Phy << BlockSizeLog) + _virtPos - (e.Virt << BlockSizeLog);\n      if (newPos != _physPos)\n      {\n        _physPos = newPos;\n        RINOK(SeekToPhys())\n      }\n      UInt64 next = Extents[i + 1].Virt;\n      if (next > virtBlock2End)\n        next &= ~((UInt64)comprUnitSize - 1);\n      next <<= BlockSizeLog;\n      if (next > Size)\n        next = Size;\n      _curRem = next - _virtPos;\n      break;\n    }\n    \n    bool thereArePhy = false;\n    \n    for (unsigned i2 = left; i2 < Extents.Size(); i2++)\n    {\n      const CExtent &e = Extents[i2];\n      if (e.Virt >= virtBlock2End)\n        break;\n      if (!e.IsEmpty())\n      {\n        thereArePhy = true;\n        break;\n      }\n    }\n    \n    if (!thereArePhy)\n    {\n      _curRem = (Extents[i + 1].Virt << BlockSizeLog) - _virtPos;\n      _sparseMode = true;\n      break;\n    }\n    \n    size_t offs = 0;\n    UInt64 curVirt = virtBlock2;\n    \n    for (i = left; i < Extents.Size(); i++)\n    {\n      const CExtent &e = Extents[i];\n      if (e.IsEmpty())\n        break;\n      if (e.Virt >= virtBlock2End)\n        return S_FALSE;\n      const UInt64 newPos = (e.Phy + (curVirt - e.Virt)) << BlockSizeLog;\n      if (newPos != _physPos)\n      {\n        _physPos = newPos;\n        RINOK(SeekToPhys())\n      }\n      UInt64 numChunks = Extents[i + 1].Virt - curVirt;\n      if (curVirt + numChunks > virtBlock2End)\n        numChunks = virtBlock2End - curVirt;\n      const size_t compressed = (size_t)numChunks << BlockSizeLog;\n      RINOK(ReadStream_FALSE(Stream, _inBuf + offs, compressed))\n      curVirt += numChunks;\n      _physPos += compressed;\n      offs += compressed;\n    }\n    \n    const size_t destLenMax = GetCuSize();\n    size_t destLen = destLenMax;\n    const UInt64 rem = Size - (virtBlock2 << BlockSizeLog);\n    if (destLen > rem)\n      destLen = (size_t)rem;\n\n    Byte *dest = _outBuf + (cacheIndex << _chunkSizeLog);\n    const size_t destSizeRes = Lznt1Dec(dest, destLenMax, destLen, _inBuf, offs);\n    _tags[cacheIndex] = cacheTag;\n\n    // some files in Vista have destSize > destLen\n    if (destSizeRes < destLen)\n    {\n      memset(dest, 0, destLenMax);\n      if (InUse)\n        return S_FALSE;\n    }\n  }\n  \n  if (size > _curRem)\n    size = (UInt32)_curRem;\n  HRESULT res = S_OK;\n  if (_sparseMode)\n    memset(data, 0, size);\n  else\n  {\n    res = Stream->Read(data, size, &size);\n    _physPos += size;\n  }\n  if (processedSize)\n    *processedSize = size;\n  _virtPos += size;\n  _curRem -= size;\n  return res;\n}\n \nZ7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  if (_virtPos != (UInt64)offset)\n  {\n    _curRem = 0;\n    _virtPos = (UInt64)offset;\n  }\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\nstatic HRESULT DataParseExtents(unsigned clusterSizeLog, const CObjectVector<CAttr> &attrs,\n    unsigned attrIndex, unsigned attrIndexLim, UInt64 numPhysClusters, CRecordVector<CExtent> &Extents)\n{\n  {\n    CExtent e;\n    e.Virt = 0;\n    e.Phy = kEmptyExtent;\n    Extents.Add(e);\n  }\n  \n  const CAttr &attr0 = attrs[attrIndex];\n\n  /*\n  if (attrs[attrIndexLim - 1].HighVcn + 1 != (attr0.AllocatedSize >> clusterSizeLog))\n  {\n  }\n  */\n\n  if (attr0.AllocatedSize < attr0.Size ||\n      (attrs[attrIndexLim - 1].HighVcn + 1) != (attr0.AllocatedSize >> clusterSizeLog) ||\n      (attr0.AllocatedSize & ((1 << clusterSizeLog) - 1)) != 0)\n    return S_FALSE;\n  \n  for (unsigned i = attrIndex; i < attrIndexLim; i++)\n    if (!attrs[i].ParseExtents(Extents, numPhysClusters, attr0.CompressionUnit))\n      return S_FALSE;\n\n  UInt64 packSizeCalc = 0;\n  FOR_VECTOR (k, Extents)\n  {\n    CExtent &e = Extents[k];\n    if (!e.IsEmpty())\n      packSizeCalc += (Extents[k + 1].Virt - e.Virt) << clusterSizeLog;\n    PRF2(printf(\"\\nSize = %4I64X\", Extents[k + 1].Virt - e.Virt));\n    PRF2(printf(\"  Pos = %4I64X\", e.Phy));\n  }\n  \n  if (attr0.CompressionUnit != 0)\n  {\n    if (packSizeCalc != attr0.PackSize)\n      return S_FALSE;\n  }\n  else\n  {\n    if (packSizeCalc != attr0.AllocatedSize)\n      return S_FALSE;\n  }\n  return S_OK;\n}\n\nstruct CDataRef\n{\n  unsigned Start;\n  unsigned Num;\n};\n\nstatic const UInt32 kMagic_FILE = 0x454C4946;\nstatic const UInt32 kMagic_BAAD = 0x44414142;\n\n// 22.02: we support some rare case magic values:\nstatic const UInt32 kMagic_INDX = 0x58444e49;\nstatic const UInt32 kMagic_HOLE = 0x454c4f48;\nstatic const UInt32 kMagic_RSTR = 0x52545352;\nstatic const UInt32 kMagic_RCRD = 0x44524352;\nstatic const UInt32 kMagic_CHKD = 0x444b4843;\nstatic const UInt32 kMagic_FFFFFFFF = 0xFFFFFFFF;\n\n\nstruct CMftRec\n{\n  UInt32 Magic;\n  // UInt64 Lsn;\n  UInt16 SeqNumber;  // Number of times this mft record has been reused\n  UInt16 Flags;\n  // UInt16 LinkCount;\n  // UInt16 NextAttrInstance;\n  CMftRef BaseMftRef;\n  // UInt32 ThisRecNumber;\n  \n  UInt32 MyNumNameLinks;\n  int MyItemIndex; // index in Items[] of main item  for that record, or -1 if there is no item for that record\n\n  CObjectVector<CAttr> DataAttrs;\n  CObjectVector<CFileNameAttr> FileNames;\n  CRecordVector<CDataRef> DataRefs;\n  // CAttr SecurityAttr;\n\n  CSiAttr SiAttr;\n  \n  CByteBuffer ReparseData;\n\n  int FindWin32Name_for_DosName(unsigned dosNameIndex) const\n  {\n    const CFileNameAttr &cur = FileNames[dosNameIndex];\n    if (cur.IsDos())\n      for (unsigned i = 0; i < FileNames.Size(); i++)\n      {\n        const CFileNameAttr &next = FileNames[i];\n        if (next.IsWin32() && cur.ParentDirRef.Val == next.ParentDirRef.Val)\n          return (int)i;\n      }\n    return -1;\n  }\n\n  int FindDosName(unsigned nameIndex) const\n  {\n    const CFileNameAttr &cur = FileNames[nameIndex];\n    if (cur.IsWin32())\n      for (unsigned i = 0; i < FileNames.Size(); i++)\n      {\n        const CFileNameAttr &next = FileNames[i];\n        if (next.IsDos() && cur.ParentDirRef.Val == next.ParentDirRef.Val)\n          return (int)i;\n      }\n    return -1;\n  }\n\n  /*\n  bool IsAltStream(int dataIndex) const\n  {\n    return dataIndex >= 0 && (\n      (IsDir() ||\n      !DataAttrs[DataRefs[dataIndex].Start].Name.IsEmpty()));\n  }\n  */\n\n  void MoveAttrsFrom(CMftRec &src)\n  {\n    DataAttrs += src.DataAttrs;\n    FileNames += src.FileNames;\n    src.DataAttrs.ClearAndFree();\n    src.FileNames.ClearAndFree();\n  }\n\n  UInt64 GetPackSize() const\n  {\n    UInt64 res = 0;\n    FOR_VECTOR (i, DataRefs)\n      res += DataAttrs[DataRefs[i].Start].GetPackSize();\n    return res;\n  }\n\n  bool Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 recNumber, CObjectVector<CAttr> *attrs);\n\n  bool Is_Magic_Empty() const\n  {\n    // what exact Magic values are possible for empty and unused records?\n    const UInt32 k_Magic_Unused_MAX = 5; // 22.02\n    return (Magic <= k_Magic_Unused_MAX);\n  }\n  bool Is_Magic_FILE() const { return (Magic == kMagic_FILE); }\n  // bool Is_Magic_BAAD() const { return (Magic == kMagic_BAAD); }\n  bool Is_Magic_CanIgnore() const\n  {\n    return Is_Magic_Empty()\n        || Magic == kMagic_BAAD\n        || Magic == kMagic_INDX\n        || Magic == kMagic_HOLE\n        || Magic == kMagic_RSTR\n        || Magic == kMagic_RCRD\n        || Magic == kMagic_CHKD\n        || Magic == kMagic_FFFFFFFF;\n  }\n\n  bool InUse() const { return (Flags & 1) != 0; }\n  bool IsDir() const { return (Flags & 2) != 0; }\n\n  void ParseDataNames();\n  HRESULT GetStream(IInStream *mainStream, int dataIndex,\n      unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **stream) const;\n  unsigned GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 numPhysClusters) const;\n\n  UInt64 GetSize(unsigned dataIndex) const { return DataAttrs[DataRefs[dataIndex].Start].GetSize(); }\n\n  CMftRec():\n      SeqNumber(0),\n      Flags(0),\n      MyNumNameLinks(0),\n      MyItemIndex(-1) {}\n};\n\nvoid CMftRec::ParseDataNames()\n{\n  DataRefs.Clear();\n  DataAttrs.Sort(CompareAttr, NULL);\n\n  for (unsigned i = 0; i < DataAttrs.Size();)\n  {\n    CDataRef ref;\n    ref.Start = i;\n    for (i++; i < DataAttrs.Size(); i++)\n      if (DataAttrs[ref.Start].Name != DataAttrs[i].Name)\n        break;\n    ref.Num = i - ref.Start;\n    DataRefs.Add(ref);\n  }\n}\n\nHRESULT CMftRec::GetStream(IInStream *mainStream, int dataIndex,\n    unsigned clusterSizeLog, UInt64 numPhysClusters, IInStream **destStream) const\n{\n  *destStream = NULL;\n  CBufferInStream *streamSpec = new CBufferInStream;\n  CMyComPtr<IInStream> streamTemp = streamSpec;\n\n  if (dataIndex >= 0)\n  if ((unsigned)dataIndex < DataRefs.Size())\n  {\n    const CDataRef &ref = DataRefs[dataIndex];\n    unsigned numNonResident = 0;\n    unsigned i;\n    for (i = ref.Start; i < ref.Start + ref.Num; i++)\n      if (DataAttrs[i].NonResident)\n        numNonResident++;\n\n    const CAttr &attr0 = DataAttrs[ref.Start];\n      \n    if (numNonResident != 0 || ref.Num != 1)\n    {\n      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())\n        return S_FALSE;\n      CInStream *ss = new CInStream;\n      CMyComPtr<IInStream> streamTemp2 = ss;\n      RINOK(DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, ss->Extents))\n      ss->Size = attr0.Size;\n      ss->InitializedSize = attr0.InitializedSize;\n      ss->Stream = mainStream;\n      ss->BlockSizeLog = clusterSizeLog;\n      ss->InUse = InUse();\n      RINOK(ss->InitAndSeek(attr0.CompressionUnit))\n      *destStream = streamTemp2.Detach();\n      return S_OK;\n    }\n  \n    streamSpec->Buf = attr0.Data;\n  }\n\n  streamSpec->Init();\n  *destStream = streamTemp.Detach();\n  return S_OK;\n}\n\nunsigned CMftRec::GetNumExtents(int dataIndex, unsigned clusterSizeLog, UInt64 numPhysClusters) const\n{\n  if (dataIndex < 0)\n    return 0;\n  {\n    const CDataRef &ref = DataRefs[dataIndex];\n    unsigned numNonResident = 0;\n    unsigned i;\n    for (i = ref.Start; i < ref.Start + ref.Num; i++)\n      if (DataAttrs[i].NonResident)\n        numNonResident++;\n\n    const CAttr &attr0 = DataAttrs[ref.Start];\n      \n    if (numNonResident != 0 || ref.Num != 1)\n    {\n      if (numNonResident != ref.Num || !attr0.IsCompressionUnitSupported())\n        return 0; // error;\n      CRecordVector<CExtent> extents;\n      if (DataParseExtents(clusterSizeLog, DataAttrs, ref.Start, ref.Start + ref.Num, numPhysClusters, extents) != S_OK)\n        return 0; // error;\n      return extents.Size() - 1;\n    }\n    // if (attr0.Data.Size() != 0)\n    //   return 1;\n    return 0;\n  }\n}\n\nbool CMftRec::Parse(Byte *p, unsigned sectorSizeLog, UInt32 numSectors, UInt32 recNumber,\n    CObjectVector<CAttr> *attrs)\n{\n  G32(p, Magic);\n  if (!Is_Magic_FILE())\n    return Is_Magic_CanIgnore();\n  \n  {\n    UInt32 usaOffset;\n    UInt32 numUsaItems;\n    G16(p + 0x04, usaOffset);\n    G16(p + 0x06, numUsaItems);\n      \n    /* NTFS stores (usn) to 2 last bytes in each sector (before writing record to disk).\n       Original values of these two bytes are stored in table.\n       So we restore original data from table */\n\n    if ((usaOffset & 1) != 0\n        || usaOffset + numUsaItems * 2 > ((UInt32)1 << sectorSizeLog) - 2\n        || numUsaItems == 0\n        || numUsaItems - 1 != numSectors)\n      return false;\n\n    if (usaOffset >= 0x30) // NTFS 3.1+\n    {\n      UInt32 iii = Get32(p + 0x2C);\n      if (iii != recNumber)\n      {\n        // ntfs-3g probably writes 0 (that probably is incorrect value) to this field for unused records.\n        // so we support that \"bad\" case.\n        if (iii != 0)\n          return false;\n      }\n    }\n    \n    UInt16 usn = Get16(p + usaOffset);\n    // PRF(printf(\"\\nusn = %d\", usn));\n    for (UInt32 i = 1; i < numUsaItems; i++)\n    {\n      void *pp = p + (i << sectorSizeLog) - 2;\n      if (Get16(pp) != usn)\n        return false;\n      SetUi16(pp, Get16(p + usaOffset + i * 2))\n    }\n  }\n\n  // G64(p + 0x08, Lsn);\n  G16(p + 0x10, SeqNumber);\n  // G16(p + 0x12, LinkCount);\n  // PRF(printf(\" L=%d\", LinkCount));\n  const UInt32 attrOffs = Get16(p + 0x14);\n  G16(p + 0x16, Flags);\n  PRF(printf(\" F=%4X\", Flags));\n\n  const UInt32 bytesInUse = Get32(p + 0x18);\n  const UInt32 bytesAlloc = Get32(p + 0x1C);\n  G64(p + 0x20, BaseMftRef.Val);\n  if (BaseMftRef.Val != 0)\n  {\n    PRF(printf(\"  BaseRef=%d\", (int)BaseMftRef.Val));\n    // return false; // Check it;\n  }\n  // G16(p + 0x28, NextAttrInstance);\n\n  UInt32 limit = numSectors << sectorSizeLog;\n  if (attrOffs >= limit\n      || (attrOffs & 7) != 0\n      || (bytesInUse & 7) != 0\n      || bytesInUse > limit\n      || bytesAlloc != limit)\n    return false;\n\n  limit = bytesInUse;\n\n  for (UInt32 t = attrOffs;;)\n  {\n    if (t >= limit)\n      return false;\n\n    CAttr attr;\n    // PRF(printf(\"\\n  %2d:\", Attrs.Size()));\n    PRF(printf(\"\\n\"));\n    UInt32 len = attr.Parse(p + t, limit - t);\n    if (len == 0 || limit - t < len)\n      return false;\n    t += len;\n    if (attr.Type == 0xFFFFFFFF)\n    {\n      if (t != limit)\n        return false;\n      break;\n    }\n    switch (attr.Type)\n    {\n      case ATTR_TYPE_FILE_NAME:\n      {\n        CFileNameAttr fna;\n        if (!attr.ParseFileName(fna))\n          return false;\n        FileNames.Add(fna);\n        PRF(printf(\"  flags = %4x\\n  \", (int)fna.NameType));\n        PRF_UTF16(fna.Name);\n        break;\n      }\n      case ATTR_TYPE_STANDARD_INFO:\n        if (!attr.ParseSi(SiAttr))\n          return false;\n        break;\n      case ATTR_TYPE_DATA:\n        DataAttrs.Add(attr);\n        break;\n      case ATTR_TYPE_REPARSE_POINT:\n        ReparseData = attr.Data;\n        break;\n      /*\n      case ATTR_TYPE_SECURITY_DESCRIPTOR:\n        SecurityAttr = attr;\n        break;\n      */\n      default:\n        if (attrs)\n          attrs->Add(attr);\n        break;\n    }\n  }\n\n  return true;\n}\n\n/*\n  NTFS probably creates empty DATA_ATTRIBUTE for empty file,\n  But it doesn't do it for\n    $Secure (:$SDS),\n    $Extend\\$Quota\n    $Extend\\$ObjId\n    $Extend\\$Reparse\n*/\n  \nstatic const int k_Item_DataIndex_IsEmptyFile = -1; // file without unnamed data stream\nstatic const int k_Item_DataIndex_IsDir = -2;\n\n// static const int k_ParentFolderIndex_Root = -1;\nstatic const int k_ParentFolderIndex_Lost = -2;\nstatic const int k_ParentFolderIndex_Deleted = -3;\n\nstruct CItem\n{\n  unsigned RecIndex;  // index in Recs array\n  unsigned NameIndex; // index in CMftRec::FileNames\n\n  int DataIndex;      /* index in CMftRec::DataRefs\n                         -1: file without unnamed data stream\n                         -2: for directories */\n                         \n  int ParentFolder;   /* index in Items array\n                         -1: for root items\n                         -2: [LOST] folder\n                         -3: [UNKNOWN] folder (deleted lost) */\n  int ParentHost;     /* index in Items array, if it's AltStream\n                         -1: if it's not AltStream */\n  \n  CItem(): DataIndex(k_Item_DataIndex_IsDir), ParentFolder(-1), ParentHost(-1) {}\n  \n  bool IsAltStream() const { return ParentHost != -1; }\n  bool IsDir() const { return DataIndex == k_Item_DataIndex_IsDir; }\n        // check it !!!\n        // probably NTFS for empty file still creates empty DATA_ATTRIBUTE\n        // But it doesn't do it for $Secure:$SDS\n};\n\nstruct CDatabase\n{\n  CRecordVector<CItem> Items;\n  CObjectVector<CMftRec> Recs;\n  CMyComPtr<IInStream> InStream;\n  CHeader Header;\n  UInt64 PhySize;\n\n  IArchiveOpenCallback *OpenCallback;\n\n  CByteBuffer ByteBuf;\n\n  CObjectVector<CAttr> VolAttrs;\n\n  CByteBuffer SecurData;\n  CRecordVector<size_t> SecurOffsets;\n\n  // bool _headerWarning;\n  bool ThereAreAltStreams;\n\n  bool _showSystemFiles;\n  bool _showDeletedFiles;\n  CObjectVector<UString2> VirtFolderNames;\n  UString EmptyString;\n\n  int _systemFolderIndex;\n  int _lostFolderIndex_Normal;\n  int _lostFolderIndex_Deleted;\n\n  void InitProps()\n  {\n    _showSystemFiles = true;\n    // we show SystemFiles by default since it's difficult to track $Extend\\* system files\n    // it must be fixed later\n    _showDeletedFiles = false;\n  }\n\n  CDatabase() { InitProps(); }\n  ~CDatabase() { ClearAndClose(); }\n\n  void Clear();\n  void ClearAndClose();\n\n  void GetItemPath(unsigned index, NCOM::CPropVariant &path) const;\n  HRESULT Open();\n\n  HRESULT SeekToCluster(UInt64 cluster);\n\n  int Find_DirItem_For_MftRec(UInt64 recIndex) const\n  {\n    if (recIndex >= Recs.Size())\n      return -1;\n    const CMftRec &rec = Recs[(unsigned)recIndex];\n    if (!rec.IsDir())\n      return -1;\n    return rec.MyItemIndex;\n    /*\n    unsigned left = 0, right = Items.Size();\n    while (left != right)\n    {\n      unsigned mid = (left + right) / 2;\n      const CItem &item = Items[mid];\n      UInt64 midValue = item.RecIndex;\n      if (recIndex == midValue)\n      {\n        // if item is not dir (file or alt stream we don't return it)\n        // if (item.DataIndex < 0)\n        if (item.IsDir())\n          return mid;\n        right = mid;\n      }\n      else if (recIndex < midValue)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    return -1;\n    */\n  }\n\n  bool FindSecurityDescritor(UInt32 id, UInt64 &offset, UInt32 &size) const;\n  \n  HRESULT ParseSecuritySDS_2();\n  void ParseSecuritySDS()\n  {\n    HRESULT res = ParseSecuritySDS_2();\n    if (res != S_OK)\n    {\n      SecurOffsets.Clear();\n      SecurData.Free();\n    }\n  }\n\n};\n\nHRESULT CDatabase::SeekToCluster(UInt64 cluster)\n{\n  return InStream_SeekSet(InStream, cluster << Header.ClusterSizeLog);\n}\n\nvoid CDatabase::Clear()\n{\n  Items.Clear();\n  Recs.Clear();\n  SecurOffsets.Clear();\n  SecurData.Free();\n  VirtFolderNames.Clear();\n  _systemFolderIndex = -1;\n  _lostFolderIndex_Normal = -1;\n  _lostFolderIndex_Deleted = -1;\n  ThereAreAltStreams = false;\n  // _headerWarning = false;\n  PhySize = 0;\n}\n\nvoid CDatabase::ClearAndClose()\n{\n  Clear();\n  InStream.Release();\n}\n\n\nstatic void CopyName(wchar_t *dest, const wchar_t *src)\n{\n  for (;;)\n  {\n    wchar_t c = *src++;\n    // 18.06\n    if (c == '\\\\' || c == '/')\n      c = '_';\n    *dest++ = c;\n    if (c == 0)\n      return;\n  }\n}\n\nvoid CDatabase::GetItemPath(unsigned index, NCOM::CPropVariant &path) const\n{\n  const CItem *item = &Items[index];\n  unsigned size = 0;\n  const CMftRec &rec = Recs[item->RecIndex];\n  size += rec.FileNames[item->NameIndex].Name.Len();\n\n  bool isAltStream = item->IsAltStream();\n\n  if (isAltStream)\n  {\n    const CAttr &data = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start];\n    if (item->RecIndex == kRecIndex_RootDir)\n    {\n      wchar_t *s = path.AllocBstr(data.Name.Len() + 1);\n      s[0] = L':';\n      if (!data.Name.IsEmpty())\n        CopyName(s + 1, data.Name.GetRawPtr());\n      return;\n    }\n\n    size += data.Name.Len();\n    size++;\n  }\n\n  for (unsigned i = 0;; i++)\n  {\n    if (i > 256)\n    {\n      path = \"[TOO-LONG]\";\n      return;\n    }\n    const wchar_t *servName;\n    if (item->RecIndex < kNumSysRecs\n        /* && item->RecIndex != kRecIndex_RootDir */)\n      servName = kVirtualFolder_System;\n    else\n    {\n      int index2 = item->ParentFolder;\n      if (index2 >= 0)\n      {\n        item = &Items[index2];\n        size += Recs[item->RecIndex].FileNames[item->NameIndex].Name.Len() + 1;\n        continue;\n      }\n      if (index2 == -1)\n        break;\n      servName = (index2 == k_ParentFolderIndex_Lost) ?\n          kVirtualFolder_Lost_Normal :\n          kVirtualFolder_Lost_Deleted;\n    }\n    size += MyStringLen(servName) + 1;\n    break;\n  }\n\n  wchar_t *s = path.AllocBstr(size);\n  \n  item = &Items[index];\n\n  bool needColon = false;\n  if (isAltStream)\n  {\n    const UString2 &name = rec.DataAttrs[rec.DataRefs[item->DataIndex].Start].Name;\n    if (!name.IsEmpty())\n    {\n      size -= name.Len();\n      CopyName(s + size, name.GetRawPtr());\n    }\n    s[--size] = ':';\n    needColon = true;\n  }\n\n  {\n    const UString2 &name = rec.FileNames[item->NameIndex].Name;\n    unsigned len = name.Len();\n    if (len != 0)\n      CopyName(s + size - len, name.GetRawPtr());\n    if (needColon)\n      s[size] =  ':';\n    size -= len;\n  }\n\n  for (;;)\n  {\n    const wchar_t *servName;\n    if (item->RecIndex < kNumSysRecs\n        /* && && item->RecIndex != kRecIndex_RootDir */)\n      servName = kVirtualFolder_System;\n    else\n    {\n      int index2 = item->ParentFolder;\n      if (index2 >= 0)\n      {\n        item = &Items[index2];\n        const UString2 &name = Recs[item->RecIndex].FileNames[item->NameIndex].Name;\n        unsigned len = name.Len();\n        size--;\n        if (len != 0)\n        {\n          size -= len;\n          CopyName(s + size, name.GetRawPtr());\n        }\n        s[size + len] = WCHAR_PATH_SEPARATOR;\n        continue;\n      }\n      if (index2 == -1)\n        break;\n      servName = (index2 == k_ParentFolderIndex_Lost) ?\n          kVirtualFolder_Lost_Normal :\n          kVirtualFolder_Lost_Deleted;\n    }\n    MyStringCopy(s, servName);\n    s[MyStringLen(servName)] = WCHAR_PATH_SEPARATOR;\n    break;\n  }\n}\n\nbool CDatabase::FindSecurityDescritor(UInt32 item, UInt64 &offset, UInt32 &size) const\n{\n  offset = 0;\n  size = 0;\n  unsigned left = 0, right = SecurOffsets.Size();\n  while (left != right)\n  {\n    unsigned mid = (left + right) / 2;\n    size_t offs = SecurOffsets[mid];\n    UInt32 midValue = Get32(((const Byte *)SecurData) + offs + 4);\n    if (item == midValue)\n    {\n      offset = Get64((const Byte *)SecurData + offs + 8) + 20;\n      size = Get32((const Byte *)SecurData + offs + 16) - 20;\n      return true;\n    }\n    if (item < midValue)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  return false;\n}\n\n/*\nstatic int CompareIDs(const size_t *p1, const size_t *p2, void *data)\n{\n  UInt32 id1 = Get32(((const Byte *)data) + *p1 + 4);\n  UInt32 id2 = Get32(((const Byte *)data) + *p2 + 4);\n  return MyCompare(id1, id2);\n}\n*/\n\n// security data contains duplication copy after each 256 KB.\nstatic const unsigned kSecureDuplicateStepBits = 18;\n\nHRESULT CDatabase::ParseSecuritySDS_2()\n{\n  const Byte *p = SecurData;\n  size_t size = SecurData.Size();\n  const size_t kDuplicateStep = (size_t)1 << kSecureDuplicateStepBits;\n  const size_t kDuplicateMask = kDuplicateStep - 1;\n  size_t lim = MyMin(size, kDuplicateStep);\n  UInt32 idPrev = 0;\n  for (size_t pos = 0; pos < size && size - pos >= 20;)\n  {\n    UInt32 id = Get32(p + pos + 4);\n    UInt64 offs = Get64(p + pos + 8);\n    UInt32 entrySize = Get32(p + pos + 16);\n    if (offs == pos && entrySize >= 20 && lim - pos >= entrySize)\n    {\n      if (id <= idPrev)\n        return S_FALSE;\n      idPrev = id;\n      SecurOffsets.Add(pos);\n      pos += entrySize;\n      pos = (pos + 0xF) & ~(size_t)0xF;\n      if ((pos & kDuplicateMask) != 0)\n        continue;\n    }\n    else\n      pos = (pos + kDuplicateStep) & ~kDuplicateMask;\n    pos += kDuplicateStep;\n    lim = pos + kDuplicateStep;\n    if (lim >= size)\n      lim = size;\n  }\n  // we checked that IDs are sorted, so we don't need Sort\n  // SecurOffsets.Sort(CompareIDs, (void *)p);\n  return S_OK;\n}\n\nHRESULT CDatabase::Open()\n{\n  Clear();\n\n  /* NTFS layout:\n     1) main part (as specified by NumClusters). Only that part is available, if we open \"\\\\.\\c:\"\n     2) additional empty sectors (as specified by NumSectors)\n     3) the copy of first sector (boot sector)\n    \n     We support both cases:\n      - the file with only main part\n      - full file (as raw data on partition), including the copy\n        of first sector (boot sector) at the end of data\n     \n     We don't support the case, when only the copy of boot sector\n     at the end was detected as NTFS signature.\n  */\n  \n  {\n    const UInt32 kHeaderSize = 512;\n    Byte buf[kHeaderSize];\n    RINOK(ReadStream_FALSE(InStream, buf, kHeaderSize))\n    if (!Header.Parse(buf))\n      return S_FALSE;\n    \n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(InStream, fileSize))\n    PhySize = Header.GetPhySize_Clusters();\n    if (fileSize < PhySize)\n      return S_FALSE;\n    \n    UInt64 phySizeMax = Header.GetPhySize_Max();\n    if (fileSize >= phySizeMax)\n    {\n      RINOK(InStream_SeekSet(InStream, Header.NumSectors << Header.SectorSizeLog))\n      Byte buf2[kHeaderSize];\n      if (ReadStream_FALSE(InStream, buf2, kHeaderSize) == S_OK)\n      {\n        if (memcmp(buf, buf2, kHeaderSize) == 0)\n          PhySize = phySizeMax;\n        // else _headerWarning = true;\n      }\n    }\n  }\n \n  SeekToCluster(Header.MftCluster);\n\n  // we use ByteBuf for records reading.\n  // so the size of ByteBuf must be >= mftRecordSize\n  const size_t recSize = (size_t)1 << Header.MftRecordSizeLog;\n  const size_t kBufSize = MyMax((size_t)(1 << 15), recSize);\n  ByteBuf.Alloc(kBufSize);\n  RINOK(ReadStream_FALSE(InStream, ByteBuf, recSize))\n  {\n    const UInt32 allocSize = Get32(ByteBuf + 0x1C);\n    if (allocSize != recSize)\n      return S_FALSE;\n  }\n  // MftRecordSizeLog >= SectorSizeLog\n  const UInt32 numSectorsInRec = 1u << (Header.MftRecordSizeLog - Header.SectorSizeLog);\n  CMyComPtr<IInStream> mftStream;\n  CMftRec mftRec;\n  {\n    if (!mftRec.Parse(ByteBuf, Header.SectorSizeLog, numSectorsInRec, 0, NULL))\n      return S_FALSE;\n    if (!mftRec.Is_Magic_FILE())\n      return S_FALSE;\n    mftRec.ParseDataNames();\n    if (mftRec.DataRefs.IsEmpty())\n      return S_FALSE;\n    RINOK(mftRec.GetStream(InStream, 0, Header.ClusterSizeLog, Header.NumClusters, &mftStream))\n    if (!mftStream)\n      return S_FALSE;\n  }\n\n  // CObjectVector<CAttr> SecurityAttrs;\n\n  const UInt64 mftSize = mftRec.DataAttrs[0].Size;\n  if ((mftSize >> 4) > Header.GetPhySize_Clusters())\n    return S_FALSE;\n\n  {\n    const UInt64 numFiles = mftSize >> Header.MftRecordSizeLog;\n    if (numFiles > (1 << 30))\n      return S_FALSE;\n    if (OpenCallback)\n    {\n      RINOK(OpenCallback->SetTotal(&numFiles, &mftSize))\n    }\n    Recs.ClearAndReserve((unsigned)numFiles);\n  }\n  \n  for (UInt64 pos64 = 0;;)\n  {\n    if (OpenCallback)\n    {\n      const UInt64 numFiles = Recs.Size();\n      if ((numFiles & 0x3FFF) == 0)\n      {\n        RINOK(OpenCallback->SetCompleted(&numFiles, &pos64))\n      }\n    }\n    size_t readSize = kBufSize;\n    {\n      const UInt64 rem = mftSize - pos64;\n      if (readSize > rem)\n        readSize = (size_t)rem;\n    }\n    if (readSize < recSize)\n      break;\n    RINOK(ReadStream_FALSE(mftStream, ByteBuf, readSize))\n    pos64 += readSize;\n\n    for (size_t i = 0; readSize >= recSize; i += recSize, readSize -= recSize)\n    {\n      PRF(printf(\"\\n---------------------\"));\n      PRF(printf(\"\\n%5d:\", Recs.Size()));\n      \n      Byte *p = ByteBuf + i;\n      CMftRec rec;\n\n      CObjectVector<CAttr> *attrs = NULL;\n      unsigned recIndex = Recs.Size();\n      switch (recIndex)\n      {\n        case kRecIndex_Volume: attrs = &VolAttrs; break;\n        // case kRecIndex_Security: attrs = &SecurityAttrs; break;\n      }\n\n      if (!rec.Parse(p, Header.SectorSizeLog, numSectorsInRec, (UInt32)Recs.Size(), attrs))\n        return S_FALSE;\n      Recs.Add(rec);\n    }\n  }\n\n  /*\n  // that code looks too complex. And we can get security info without index parsing\n  for (i = 0; i < SecurityAttrs.Size(); i++)\n  {\n    const CAttr &attr = SecurityAttrs[i];\n    if (attr.Name.IsEqualTo(\"$SII\"))\n    {\n      if (attr.Type == ATTR_TYPE_INDEX_ROOT)\n      {\n        const Byte *data = attr.Data;\n        size_t size = attr.Data.Size();\n\n        // Index Root\n        UInt32 attrType = Get32(data);\n        UInt32 collationRule = Get32(data + 4);\n        UInt32 indexAllocationEtrySizeSize = Get32(data + 8);\n        UInt32 clustersPerIndexRecord = Get32(data + 0xC);\n        data += 0x10;\n\n        // Index Header\n        UInt32 firstEntryOffset = Get32(data);\n        UInt32 totalSize = Get32(data + 4);\n        UInt32 allocSize = Get32(data + 8);\n        UInt32 flags = Get32(data + 0xC);\n\n        int num = 0;\n        for (int j = 0 ; j < num; j++)\n        {\n          if (Get32(data) != 0x1414 || // offset and size\n              Get32(data + 4) != 0 ||\n              Get32(data + 8) != 0x428) // KeySize / EntrySize\n            break;\n          UInt32 flags = Get32(data + 12);\n          UInt32 id = Get32(data + 0x10);\n          if (id = Get32(data + 0x18))\n            break;\n          UInt32 descriptorOffset = Get64(data + 0x1C);\n          UInt32 descriptorSize = Get64(data + 0x24);\n          data += 0x28;\n        }\n        // break;\n      }\n    }\n  }\n  */\n\n  unsigned i;\n  \n  for (i = 0; i < Recs.Size(); i++)\n  {\n    CMftRec &rec = Recs[i];\n    if (!rec.Is_Magic_FILE())\n      continue;\n\n    if (!rec.BaseMftRef.IsBaseItself())\n    {\n      const UInt64 refIndex = rec.BaseMftRef.GetIndex();\n      if (refIndex >= Recs.Size())\n        return S_FALSE;\n      CMftRec &refRec = Recs[(unsigned)refIndex];\n      if (!refRec.Is_Magic_FILE())\n        continue;\n\n      bool moveAttrs = (refRec.SeqNumber == rec.BaseMftRef.GetNumber() && refRec.BaseMftRef.IsBaseItself());\n      if (rec.InUse() && refRec.InUse())\n      {\n        if (!moveAttrs)\n          return S_FALSE;\n      }\n      else if (rec.InUse() || refRec.InUse())\n        moveAttrs = false;\n      if (moveAttrs)\n        refRec.MoveAttrsFrom(rec);\n    }\n  }\n\n  for (i = 0; i < Recs.Size(); i++)\n  {\n    CMftRec &rec = Recs[i];\n    if (!rec.Is_Magic_FILE())\n      continue;\n    rec.ParseDataNames();\n  }\n  \n  for (i = 0; i < Recs.Size(); i++)\n  {\n    CMftRec &rec = Recs[i];\n    if (!rec.Is_Magic_FILE() || !rec.BaseMftRef.IsBaseItself())\n      continue;\n    if (i < kNumSysRecs && !_showSystemFiles)\n      continue;\n    if (!rec.InUse() && !_showDeletedFiles)\n      continue;\n\n    rec.MyNumNameLinks = rec.FileNames.Size();\n    \n    // printf(\"\\n%4d: \", i);\n    \n    /* Actually DataAttrs / DataRefs are sorted by name.\n       It can not be more than one unnamed stream in DataRefs\n       And indexOfUnnamedStream <= 0.\n    */\n\n    int indexOfUnnamedStream = -1;\n    if (!rec.IsDir())\n    {\n      FOR_VECTOR (di, rec.DataRefs)\n        if (rec.DataAttrs[rec.DataRefs[di].Start].Name.IsEmpty())\n        {\n          indexOfUnnamedStream = (int)di;\n          break;\n        }\n    }\n\n    if (rec.FileNames.IsEmpty())\n    {\n      bool needShow = true;\n      if (i < kNumSysRecs)\n      {\n        needShow = false;\n        FOR_VECTOR (di, rec.DataRefs)\n          if (rec.GetSize(di) != 0)\n          {\n            needShow = true;\n            break;\n          }\n      }\n      if (needShow)\n      {\n        CFileNameAttr &fna = rec.FileNames.AddNew();\n        // we set incorrect ParentDirRef, that will place item to [LOST] folder\n        fna.ParentDirRef.Val = (UInt64)(Int64)-1;\n        char s[16 + 16];\n        ConvertUInt32ToString(i, MyStpCpy(s, \"[NONAME]-\"));\n        fna.Name.SetFromAscii(s);\n        fna.NameType = kFileNameType_Win32Dos;\n        fna.Attrib = 0;\n      }\n    }\n\n    // bool isMainName = true;\n\n    FOR_VECTOR (t, rec.FileNames)\n    {\n      #ifdef SHOW_DEBUG_INFO\n      const CFileNameAttr &fna = rec.FileNames[t];\n      #endif\n      PRF(printf(\"\\n %4d \", (int)fna.NameType));\n      PRF_UTF16(fna.Name);\n      // PRF(printf(\"  | \"));\n\n      if (rec.FindWin32Name_for_DosName(t) >= 0)\n      {\n        rec.MyNumNameLinks--;\n        continue;\n      }\n      \n      CItem item;\n      item.NameIndex = t;\n      item.RecIndex = i;\n      item.DataIndex = rec.IsDir() ?\n          k_Item_DataIndex_IsDir :\n            (indexOfUnnamedStream < 0 ?\n          k_Item_DataIndex_IsEmptyFile :\n          indexOfUnnamedStream);\n      \n      if (rec.MyItemIndex < 0)\n        rec.MyItemIndex = (int)Items.Size();\n      item.ParentHost = (int)Items.Add(item);\n      \n      /* we can use that code to reduce the number of alt streams:\n         it will not show how alt streams for hard links. */\n      // if (!isMainName) continue; isMainName = false;\n\n      // unsigned numAltStreams = 0;\n\n      FOR_VECTOR (di, rec.DataRefs)\n      {\n        if (!rec.IsDir() && (int)di == indexOfUnnamedStream)\n          continue;\n\n        const UString2 &subName = rec.DataAttrs[rec.DataRefs[di].Start].Name;\n        \n        PRF(printf(\"\\n alt stream: \"));\n        PRF_UTF16(subName);\n\n        {\n          // $BadClus:$Bad is sparse file for all clusters. So we skip it.\n          if (i == kRecIndex_BadClus && subName == L\"$Bad\")\n            continue;\n        }\n\n        // numAltStreams++;\n        ThereAreAltStreams = true;\n        item.DataIndex = (int)di;\n        Items.Add(item);\n      }\n    }\n  }\n  \n  if (Recs.Size() > kRecIndex_Security)\n  {\n    const CMftRec &rec = Recs[kRecIndex_Security];\n    FOR_VECTOR (di, rec.DataRefs)\n    {\n      const CAttr &attr = rec.DataAttrs[rec.DataRefs[di].Start];\n      if (attr.Name == L\"$SDS\")\n      {\n        CMyComPtr<IInStream> sdsStream;\n        RINOK(rec.GetStream(InStream, (int)di, Header.ClusterSizeLog, Header.NumClusters, &sdsStream))\n        if (sdsStream)\n        {\n          const UInt64 size64 = attr.GetSize();\n          if (size64 < (UInt32)1 << 29)\n          {\n            size_t size = (size_t)size64;\n            if ((((size + 1) >> kSecureDuplicateStepBits) & 1) != 0)\n            {\n              size -= (1 << kSecureDuplicateStepBits);\n              SecurData.Alloc(size);\n              if (ReadStream_FALSE(sdsStream, SecurData, size) == S_OK)\n              {\n                ParseSecuritySDS();\n                break;\n              }\n            }\n          }\n        }\n        break;\n      }\n    }\n  }\n\n  bool thereAreUnknownFolders_Normal = false;\n  bool thereAreUnknownFolders_Deleted = false;\n\n  for (i = 0; i < Items.Size(); i++)\n  {\n    CItem &item = Items[i];\n    const CMftRec &rec = Recs[item.RecIndex];\n    const CFileNameAttr &fn = rec.FileNames[item.NameIndex];\n    const CMftRef &parentDirRef = fn.ParentDirRef;\n    const UInt64 refIndex = parentDirRef.GetIndex();\n    if (refIndex == kRecIndex_RootDir)\n      item.ParentFolder = -1;\n    else\n    {\n      int index = Find_DirItem_For_MftRec(refIndex);\n      if (index < 0 ||\n          Recs[Items[index].RecIndex].SeqNumber != parentDirRef.GetNumber())\n      {\n        if (Recs[item.RecIndex].InUse())\n        {\n          thereAreUnknownFolders_Normal = true;\n          index = k_ParentFolderIndex_Lost;\n        }\n        else\n        {\n          thereAreUnknownFolders_Deleted = true;\n          index = k_ParentFolderIndex_Deleted;\n        }\n      }\n      item.ParentFolder = index;\n    }\n  }\n  \n  unsigned virtIndex = Items.Size();\n  if (_showSystemFiles)\n  {\n    _systemFolderIndex = (int)(virtIndex++);\n    VirtFolderNames.Add(kVirtualFolder_System);\n  }\n  if (thereAreUnknownFolders_Normal)\n  {\n    _lostFolderIndex_Normal = (int)(virtIndex++);\n    VirtFolderNames.Add(kVirtualFolder_Lost_Normal);\n  }\n  if (thereAreUnknownFolders_Deleted)\n  {\n    _lostFolderIndex_Deleted = (int)(virtIndex++);\n    VirtFolderNames.Add(kVirtualFolder_Lost_Deleted);\n  }\n\n  return S_OK;\n}\n\nZ7_class_CHandler_final:\n  public IInArchive,\n  public IArchiveGetRawProps,\n  public IInArchiveGetStream,\n  public ISetProperties,\n  public CMyUnknownImp,\n  public CDatabase\n{\n  Z7_IFACES_IMP_UNK_4(\n      IInArchive,\n      IArchiveGetRawProps,\n      IInArchiveGetStream,\n      ISetProperties)\n};\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = 2;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))\n{\n  *name = NULL;\n  *propID = index == 0 ? kpidNtReparse : kpidNtSecure;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  *parentType = NParentType::kDir;\n  int par = -1;\n\n  if (index < Items.Size())\n  {\n    const CItem &item = Items[index];\n    \n    if (item.ParentHost >= 0)\n    {\n      *parentType = NParentType::kAltStream;\n      par = (item.RecIndex == kRecIndex_RootDir ? -1 : item.ParentHost);\n    }\n    else if (item.RecIndex < kNumSysRecs)\n    {\n      if (_showSystemFiles)\n        par = _systemFolderIndex;\n    }\n    else if (item.ParentFolder >= 0)\n      par = item.ParentFolder;\n    else if (item.ParentFolder == k_ParentFolderIndex_Lost)\n      par = _lostFolderIndex_Normal;\n    else if (item.ParentFolder == k_ParentFolderIndex_Deleted)\n      par = _lostFolderIndex_Deleted;\n  }\n  *parent = (UInt32)(Int32)par;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n\n  if (propID == kpidName)\n  {\n    #ifdef MY_CPU_LE\n    const UString2 *s;\n    if (index >= Items.Size())\n      s = &VirtFolderNames[index - Items.Size()];\n    else\n    {\n      const CItem &item = Items[index];\n      const CMftRec &rec = Recs[item.RecIndex];\n      if (item.IsAltStream())\n        s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;\n      else\n        s = &rec.FileNames[item.NameIndex].Name;\n    }\n    if (s->IsEmpty())\n      *data = (const wchar_t *)EmptyString;\n    else\n      *data = s->GetRawPtr();\n    *dataSize = (s->Len() + 1) * (UInt32)sizeof(wchar_t);\n    *propType = PROP_DATA_TYPE_wchar_t_PTR_Z_LE;\n    #endif\n    return S_OK;\n  }\n\n  if (propID == kpidNtReparse)\n  {\n    if (index >= Items.Size())\n      return S_OK;\n    const CItem &item = Items[index];\n    const CMftRec &rec = Recs[item.RecIndex];\n    const CByteBuffer &reparse = rec.ReparseData;\n\n    if (reparse.Size() != 0)\n    {\n      *dataSize = (UInt32)reparse.Size();\n      *propType = NPropDataType::kRaw;\n      *data = (const Byte *)reparse;\n    }\n  }\n\n  if (propID == kpidNtSecure)\n  {\n    if (index >= Items.Size())\n      return S_OK;\n    const CItem &item = Items[index];\n    const CMftRec &rec = Recs[item.RecIndex];\n    if (rec.SiAttr.SecurityId > 0)\n    {\n      UInt64 offset;\n      UInt32 size;\n      if (FindSecurityDescritor(rec.SiAttr.SecurityId, offset, size))\n      {\n        *dataSize = size;\n        *propType = NPropDataType::kRaw;\n        *data = (const Byte *)SecurData + offset;\n      }\n    }\n  }\n  \n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  if (index >= Items.Size())\n    return S_OK;\n  IInStream *stream2;\n  const CItem &item = Items[index];\n  const CMftRec &rec = Recs[item.RecIndex];\n  HRESULT res = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &stream2);\n  *stream = (ISequentialInStream *)stream2;\n  return res;\n  COM_TRY_END\n}\n\n/*\nenum\n{\n  kpidLink2 = kpidUserDefined,\n  kpidLinkType,\n  kpidRecMTime,\n  kpidRecMTime2,\n  kpidMTime2,\n  kpidCTime2,\n  kpidATime2\n};\n\nstatic const CStatProp kProps[] =\n{\n  { NULL, kpidPath, VT_BSTR},\n  { NULL, kpidSize, VT_UI8},\n  { NULL, kpidPackSize, VT_UI8},\n\n  // { NULL, kpidLink, VT_BSTR},\n  \n  // { \"Link 2\", kpidLink2, VT_BSTR},\n  // { \"Link Type\", kpidLinkType, VT_UI2},\n  { NULL, kpidINode, VT_UI8},\n \n  { NULL, kpidMTime, VT_FILETIME},\n  { NULL, kpidCTime, VT_FILETIME},\n  { NULL, kpidATime, VT_FILETIME},\n  \n  // { \"Record Modified\", kpidRecMTime, VT_FILETIME},\n\n  // { \"Modified 2\", kpidMTime2, VT_FILETIME},\n  // { \"Created 2\", kpidCTime2, VT_FILETIME},\n  // { \"Accessed 2\", kpidATime2, VT_FILETIME},\n  // { \"Record Modified 2\", kpidRecMTime2, VT_FILETIME},\n\n  { NULL, kpidAttrib, VT_UI4},\n  { NULL, kpidNumBlocks, VT_UI4},\n  { NULL, kpidIsDeleted, VT_BOOL},\n};\n*/\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidChangeTime,\n  kpidAttrib,\n  kpidLinks,\n  kpidINode,\n  kpidNumBlocks,\n  kpidNumAltStreams,\n  kpidIsAltStream,\n  kpidShortName,\n  kpidIsDeleted\n};\n\nenum\n{\n  kpidRecordSize = kpidUserDefined\n};\n\nstatic const CStatProp kArcProps[] =\n{\n  { NULL, kpidVolumeName, VT_BSTR},\n  { NULL, kpidFileSystem, VT_BSTR},\n  { NULL, kpidClusterSize, VT_UI4},\n  { NULL, kpidSectorSize, VT_UI4},\n  { \"MFT Record Size\", kpidRecordSize, VT_UI4},\n  { NULL, kpidHeadersSize, VT_UI8},\n  { NULL, kpidCTime, VT_FILETIME},\n  { NULL, kpidId, VT_UI8},\n};\n\n/*\nstatic const Byte kArcProps[] =\n{\n  kpidVolumeName,\n  kpidFileSystem,\n  kpidClusterSize,\n  kpidHeadersSize,\n  kpidCTime,\n\n  kpidSectorSize,\n  kpidId\n  // kpidSectorsPerTrack,\n  // kpidNumHeads,\n  // kpidHiddenSectors\n};\n*/\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\nstatic void NtfsTimeToProp(UInt64 t, NCOM::CPropVariant &prop)\n{\n  FILETIME ft;\n  ft.dwLowDateTime = (DWORD)t;\n  ft.dwHighDateTime = (DWORD)(t >> 32);\n  prop = ft;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CMftRec *volRec = (Recs.Size() > kRecIndex_Volume ? &Recs[kRecIndex_Volume] : NULL);\n\n  switch (propID)\n  {\n    case kpidClusterSize: prop = Header.ClusterSize(); break;\n    case kpidPhySize: prop = PhySize; break;\n    /*\n    case kpidHeadersSize:\n    {\n      UInt64 val = 0;\n      for (unsigned i = 0; i < kNumSysRecs; i++)\n      {\n        printf(\"\\n%2d: %8I64d \", i, Recs[i].GetPackSize());\n        if (i == 8)\n          i = i\n        val += Recs[i].GetPackSize();\n      }\n      prop = val;\n      break;\n    }\n    */\n    case kpidCTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.CTime, prop); break;\n    case kpidMTime: if (volRec) NtfsTimeToProp(volRec->SiAttr.MTime, prop); break;\n    case kpidShortComment:\n    case kpidVolumeName:\n    {\n      FOR_VECTOR (i, VolAttrs)\n      {\n        const CAttr &attr = VolAttrs[i];\n        if (attr.Type == ATTR_TYPE_VOLUME_NAME)\n        {\n          UString2 name;\n          GetString(attr.Data, (unsigned)attr.Data.Size() / 2, name);\n          if (!name.IsEmpty())\n            prop = name.GetRawPtr();\n          break;\n        }\n      }\n      break;\n    }\n    case kpidFileSystem:\n    {\n      AString s (\"NTFS\");\n      FOR_VECTOR (i, VolAttrs)\n      {\n        const CAttr &attr = VolAttrs[i];\n        if (attr.Type == ATTR_TYPE_VOLUME_INFO)\n        {\n          CVolInfo vi;\n          if (attr.ParseVolInfo(vi))\n          {\n            s.Add_Space();\n            s.Add_UInt32(vi.MajorVer);\n            s.Add_Dot();\n            s.Add_UInt32(vi.MinorVer);\n          }\n          break;\n        }\n      }\n      prop = s;\n      break;\n    }\n    case kpidSectorSize: prop = (UInt32)1 << Header.SectorSizeLog; break;\n    case kpidRecordSize: prop = (UInt32)1 << Header.MftRecordSizeLog; break;\n    case kpidId: prop = Header.SerialNumber; break;\n\n    case kpidIsTree: prop = true; break;\n    case kpidIsDeleted: prop = _showDeletedFiles; break;\n    case kpidIsAltStream: prop = ThereAreAltStreams; break;\n    case kpidIsAux: prop = true; break;\n    case kpidINode: prop = true; break;\n\n    case kpidWarning:\n      if (_lostFolderIndex_Normal >= 0)\n        prop = \"There are lost files\";\n      break;\n\n    /*\n    case kpidWarningFlags:\n    {\n      UInt32 flags = 0;\n      if (_headerWarning)\n        flags |= k_ErrorFlags_HeadersError;\n      if (flags != 0)\n        prop = flags;\n      break;\n    }\n    */\n      \n    // case kpidMediaType: prop = Header.MediaType; break;\n    // case kpidSectorsPerTrack: prop = Header.SectorsPerTrack; break;\n    // case kpidNumHeads: prop = Header.NumHeads; break;\n    // case kpidHiddenSectors: prop = Header.NumHiddenSectors; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  if (index >= Items.Size())\n  {\n    switch (propID)\n    {\n      case kpidName:\n      case kpidPath:\n        prop = VirtFolderNames[index - Items.Size()].GetRawPtr();\n        break;\n      case kpidIsDir: prop = true; break;\n      case kpidIsAux: prop = true; break;\n      case kpidIsDeleted:\n        if ((int)index == _lostFolderIndex_Deleted)\n          prop = true;\n        break;\n    }\n    prop.Detach(value);\n    return S_OK;\n  }\n\n  const CItem &item = Items[index];\n  const CMftRec &rec = Recs[item.RecIndex];\n\n  const CAttr *data= NULL;\n  if (item.DataIndex >= 0)\n    data = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];\n\n  // const CFileNameAttr *fn = &rec.FileNames[item.NameIndex];\n  /*\n  if (rec.FileNames.Size() > 0)\n    fn = &rec.FileNames[0];\n  */\n\n  switch (propID)\n  {\n    case kpidPath:\n      GetItemPath(index, prop);\n      break;\n\n    /*\n    case kpidLink:\n      if (!rec.ReparseAttr.SubsName.IsEmpty())\n      {\n        prop = rec.ReparseAttr.SubsName;\n      }\n      break;\n    case kpidLink2:\n      if (!rec.ReparseAttr.PrintName.IsEmpty())\n      {\n        prop = rec.ReparseAttr.PrintName;\n      }\n      break;\n\n    case kpidLinkType:\n      if (rec.ReparseAttr.Tag != 0)\n      {\n        prop = (rec.ReparseAttr.Tag & 0xFFFF);\n      }\n      break;\n    */\n    \n    case kpidINode:\n    {\n      // const CMftRec &rec = Recs[item.RecIndex];\n      // prop = ((UInt64)rec.SeqNumber << 48) | item.RecIndex;\n      prop = (UInt32)item.RecIndex;\n      break;\n    }\n    case kpidStreamId:\n    {\n      if (item.DataIndex >= 0)\n        prop = ((UInt64)item.RecIndex << 32) | (unsigned)item.DataIndex;\n      break;\n    }\n\n    case kpidName:\n    {\n      const UString2 *s;\n      if (item.IsAltStream())\n        s = &rec.DataAttrs[rec.DataRefs[item.DataIndex].Start].Name;\n      else\n        s = &rec.FileNames[item.NameIndex].Name;\n      if (s->IsEmpty())\n        prop = (const wchar_t *)EmptyString;\n      else\n        prop = s->GetRawPtr();\n      break;\n    }\n\n    case kpidShortName:\n    {\n      if (!item.IsAltStream())\n      {\n        int dosNameIndex = rec.FindDosName(item.NameIndex);\n        if (dosNameIndex >= 0)\n        {\n          const UString2 &s = rec.FileNames[dosNameIndex].Name;\n          if (s.IsEmpty())\n            prop = (const wchar_t *)EmptyString;\n          else\n            prop = s.GetRawPtr();\n        }\n      }\n      break;\n    }\n\n    case kpidIsDir: prop = item.IsDir(); break;\n    case kpidIsAltStream: prop = item.IsAltStream(); break;\n    case kpidIsDeleted: prop = !rec.InUse(); break;\n    case kpidIsAux: prop = false; break;\n\n    case kpidMTime: NtfsTimeToProp(rec.SiAttr.MTime, prop); break;\n    case kpidCTime: NtfsTimeToProp(rec.SiAttr.CTime, prop); break;\n    case kpidATime: NtfsTimeToProp(rec.SiAttr.ATime, prop); break;\n    case kpidChangeTime: NtfsTimeToProp(rec.SiAttr.ThisRecMTime, prop); break;\n\n    /*\n    case kpidMTime2: if (fn) NtfsTimeToProp(fn->MTime, prop); break;\n    case kpidCTime2: if (fn) NtfsTimeToProp(fn->CTime, prop); break;\n    case kpidATime2: if (fn) NtfsTimeToProp(fn->ATime, prop); break;\n    case kpidRecMTime2: if (fn) NtfsTimeToProp(fn->ThisRecMTime, prop); break;\n    */\n      \n    case kpidAttrib:\n    {\n      UInt32 attrib;\n      /* WinXP-64: The CFileNameAttr::Attrib is not updated  after some changes. Why?\n         CSiAttr:attrib is updated better. So we use CSiAttr:Sttrib */\n      /*\n      if (fn)\n        attrib = fn->Attrib;\n      else\n      */\n        attrib = rec.SiAttr.Attrib;\n      if (item.IsDir())\n        attrib |= FILE_ATTRIBUTE_DIRECTORY;\n\n      /* some system entries can contain extra flags (Index View).\n      // 0x10000000   (Directory)\n      // 0x20000000   FILE_ATTR_VIEW_INDEX_PRESENT MFT_RECORD_IS_VIEW_INDEX (Index View)\n      But we don't need them */\n      attrib &= 0xFFFF;\n\n      prop = attrib;\n      break;\n    }\n    case kpidLinks: if (rec.MyNumNameLinks != 1) prop = rec.MyNumNameLinks; break;\n    \n    case kpidNumAltStreams:\n    {\n      if (!item.IsAltStream())\n      {\n        unsigned num = rec.DataRefs.Size();\n        if (num > 0)\n        {\n          if (!rec.IsDir() && rec.DataAttrs[rec.DataRefs[0].Start].Name.IsEmpty())\n            num--;\n          if (num > 0)\n            prop = (UInt32)num;\n        }\n      }\n      break;\n    }\n    \n    case kpidSize: if (data) prop = data->GetSize(); else if (!item.IsDir()) prop = (UInt64)0; break;\n    case kpidPackSize: if (data) prop = data->GetPackSize(); else if (!item.IsDir()) prop = (UInt64)0; break;\n    case kpidNumBlocks: if (data) prop = (UInt32)rec.GetNumExtents(item.DataIndex, Header.ClusterSizeLog, Header.NumClusters); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    OpenCallback = callback;\n    InStream = stream;\n    HRESULT res;\n    try\n    {\n      res = CDatabase::Open();\n      if (res == S_OK)\n        return S_OK;\n    }\n    catch(...)\n    {\n      Close();\n      throw;\n    }\n    Close();\n    return res;\n  }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  ClearAndClose();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = Items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt32 i;\n  UInt64 totalSize = 0;\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n    if (index >= (UInt32)Items.Size())\n      continue;\n    const CItem &item = Items[allFilesMode ? i : indices[i]];\n    const CMftRec &rec = Recs[item.RecIndex];\n    if (item.DataIndex >= 0)\n      totalSize += rec.GetSize((unsigned)item.DataIndex);\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 totalPackSize;\n  totalSize = totalPackSize = 0;\n  \n  UInt32 clusterSize = Header.ClusterSize();\n  CByteBuffer buf(clusterSize);\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = totalPackSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    if (index >= (UInt32)Items.Size() || Items[index].IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    const CItem &item = Items[index];\n\n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    outStream->SetStream(realOutStream);\n    realOutStream.Release();\n    outStream->Init();\n\n    const CMftRec &rec = Recs[item.RecIndex];\n\n    int res = NExtract::NOperationResult::kDataError;\n    {\n      CMyComPtr<IInStream> inStream;\n      HRESULT hres = rec.GetStream(InStream, item.DataIndex, Header.ClusterSizeLog, Header.NumClusters, &inStream);\n      if (hres == S_FALSE)\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n      else\n      {\n        RINOK(hres)\n        if (inStream)\n        {\n          hres = copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps);\n          if (hres != S_OK &&  hres != S_FALSE)\n          {\n            RINOK(hres)\n          }\n          if (/* copyCoderSpec->TotalSize == item.GetSize() && */ hres == S_OK)\n            res = NExtract::NOperationResult::kOK;\n        }\n      }\n    }\n    if (item.DataIndex >= 0)\n    {\n      const CAttr &data = rec.DataAttrs[rec.DataRefs[item.DataIndex].Start];\n      totalPackSize += data.GetPackSize();\n      totalSize += data.GetSize();\n    }\n    outStream->ReleaseStream();\n    RINOK(extractCallback->SetOperationResult(res))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = Items.Size() + VirtFolderNames.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  InitProps();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const wchar_t *name = names[i];\n    const PROPVARIANT &prop = values[i];\n\n    if (StringsAreEqualNoCase_Ascii(name, \"ld\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, _showDeletedFiles))\n    }\n    else if (StringsAreEqualNoCase_Ascii(name, \"ls\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, _showSystemFiles))\n    }\n    else if (IsString1PrefixedByString2_NoCase_Ascii(name, \"mt\"))\n    {\n    }\n    else if (IsString1PrefixedByString2_NoCase_Ascii(name, \"memuse\"))\n    {\n    }\n    else\n      return E_INVALIDARG;\n  }\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = { 'N', 'T', 'F', 'S', ' ', ' ', ' ', ' ', 0 };\n\nREGISTER_ARC_I(\n  \"NTFS\", \"ntfs img\", NULL, 0xD9,\n  k_Signature,\n  3,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/PeHandler.cpp",
    "content": "﻿// PeHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/DynamicBuffer.h\"\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define G16(offs, v) v = Get16(p + (offs))\n#define G32(offs, v) v = Get32(p + (offs))\n#define G32_signed(offs, v) v = (Int32)Get32(p + (offs))\n#define G64(offs, v) v = Get64(p + (offs))\n\n#define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NPe {\n\nstatic const UInt32 k_Signature32 = 0x00004550;\n\nstatic HRESULT CalcCheckSum(ISequentialInStream *stream, UInt32 size, UInt32 excludePos, UInt32 &res)\n{\n  const UInt32 kBufSizeMax = (UInt32)1 << 15;\n  UInt32 bufSize = kBufSizeMax;\n  CByteBuffer buffer(bufSize);\n  Byte *buf = buffer;\n  UInt32 sum = 0;\n  UInt32 pos = 0;\n  for (;;)\n  {\n    UInt32 rem = size - pos;\n    if (rem > bufSize)\n      rem = bufSize;\n    if (rem == 0)\n      break;\n    size_t processed = rem;\n    RINOK(ReadStream(stream, buf, &processed))\n    \n    for (unsigned j = 0; j < 4; j++)\n    {\n      UInt32 e = excludePos + j;\n      if (pos <= e)\n      {\n        e -= pos;\n        if (e < processed)\n          buf[e] = 0;\n      }\n    }\n\n    const unsigned kStep = (1 << 4);\n    {\n      for (size_t i = processed; (i & (kStep - 1)) != 0; i++)\n        buf[i] = 0;\n    }\n    {\n      const Byte *buf2 = buf;\n      const Byte *bufLimit = buf + processed;\n      UInt64 sum2 = 0;\n      for (; buf2 < bufLimit; buf2 += kStep)\n      {\n        UInt64 sum3 = (UInt64)Get32(buf2)\n            + Get32(buf2 + 4)\n            + Get32(buf2 + 8)\n            + Get32(buf2 + 12);\n        sum2 += sum3;\n      }\n      sum2 = (UInt32)(sum2) + (UInt64)(sum2 >> 32);\n      UInt32 sum3 = ((UInt32)sum2 + (UInt32)(sum2 >> 32));\n      sum += (sum3 & 0xFFFF) + (sum3 >> 16);\n      sum = (sum & 0xFFFF) + (sum >> 16);\n      sum = (sum & 0xFFFF) + (sum >> 16);\n    }\n\n    pos += (UInt32)processed;\n    if (rem != processed)\n      break;\n  }\n  res = sum + pos;\n  return S_OK;\n}\n\n\nstruct CVersion\n{\n  UInt16 Major;\n  UInt16 Minor;\n\n  void Parse(const Byte *p)\n  {\n    G16(0, Major);\n    G16(2, Minor);\n  }\n  void ToProp(NCOM::CPropVariant &prop);\n};\n\nvoid CVersion::ToProp(NCOM::CPropVariant &prop)\n{\n  char sz[32];\n  ConvertUInt32ToString(Major, sz);\n  unsigned len = MyStringLen(sz);\n  sz[len] = '.';\n  ConvertUInt32ToString(Minor, sz + len + 1);\n  prop = sz;\n}\n\nstatic const unsigned kCoffHeaderSize = 20;\nstatic const unsigned kPeHeaderSize = 4 + kCoffHeaderSize;\nstatic const unsigned k_OptHeader32_Size_MIN = 96;\nstatic const unsigned k_OptHeader64_Size_MIN = 112;\n\nstatic const UInt32 PE_IMAGE_FILE_DLL  = (1 << 13);\n\nstruct CHeader\n{\n  UInt16 Machine;\n  UInt16 NumSections;\n  UInt32 Time;\n  UInt32 PointerToSymbolTable;\n  UInt32 NumSymbols;\n  UInt16 OptHeaderSize;\n  UInt16 Flags;\n\n  void ParseBase(const Byte *p);\n  bool ParseCoff(const Byte *p);\n  bool ParsePe(const Byte *p);\n  bool IsDll() const { return (Flags & PE_IMAGE_FILE_DLL) != 0; }\n};\n\nvoid CHeader::ParseBase(const Byte *p)\n{\n  G16( 0, Machine);\n  G16( 2, NumSections);\n  G32( 4, Time);\n  G32( 8, PointerToSymbolTable);\n  G32(12, NumSymbols);\n  G16(16, OptHeaderSize);\n  G16(18, Flags);\n}\n\nbool CHeader::ParsePe(const Byte *p)\n{\n  if (Get32(p) != k_Signature32)\n    return false;\n  ParseBase(p + 4);\n  return OptHeaderSize >= k_OptHeader32_Size_MIN;\n}\n\nstruct CDirLink\n{\n  UInt32 Va;\n  UInt32 Size;\n  \n  CDirLink(): Va(0), Size(0) {}\n  void Parse(const Byte *p)\n  {\n    G32(0, Va);\n    G32(4, Size);\n  }\n};\n\n\n// IMAGE_DIRECTORY_ENTRY_*\nstatic const char * const g_Dir_Names[] =\n{\n    \"EXPORT\"\n  , \"IMPORT\"\n  , \"RESOURCE\"\n  , \"EXCEPTION\"\n  , \"SECURITY\"\n  , \"BASERELOC\"\n  , \"DEBUG\"\n  , \"ARCHITECTURE\" // \"COPYRIGHT\"\n  , \"GLOBALPTR\"\n  , \"TLS\"\n  , \"LOAD_CONFIG\"\n  , \"BOUND_IMPORT\"\n  , \"IAT\"\n  , \"DELAY_IMPORT\"\n  , \"COM_DESCRIPTOR\"\n};\n\nenum\n{\n  kDirLink_EXCEPTION = 3,\n  kDirLink_Certificate = 4,\n  kDirLink_BASERELOC = 5,\n  kDirLink_Debug = 6\n};\n\nstatic const UInt32 kNumDirItemsMax = 16;\n\nstruct CDebugEntry\n{\n  UInt32 Flags;\n  UInt32 Time;\n  CVersion Ver;\n  UInt32 Type;\n  UInt32 Size;\n  UInt32 Va;\n  UInt32 Pa;\n  \n  void Parse(const Byte *p)\n  {\n    G32(0, Flags);\n    G32(4, Time);\n    Ver.Parse(p + 8);\n    G32(12, Type);\n    G32(16, Size);\n    G32(20, Va);\n    G32(24, Pa);\n  }\n};\n\nstatic const UInt32 k_CheckSum_Field_Offset = 64;\n\nstatic const UInt32 PE_OptHeader_Magic_32 = 0x10B;\nstatic const UInt32 PE_OptHeader_Magic_64 = 0x20B;\n\nstatic const UInt32 k_SubSystems_EFI_First = 10;\nstatic const UInt32 k_SubSystems_EFI_Last = 13;\n\nstruct COptHeader\n{\n  UInt16 Magic;\n  Byte LinkerVerMajor;\n  Byte LinkerVerMinor;\n\n  UInt32 CodeSize;\n  UInt32 InitDataSize;\n  UInt32 UninitDataSize;\n  \n  // UInt32 AddressOfEntryPoint;\n  // UInt32 BaseOfCode; //  VA(.text) == 0x1000 in most cases\n  // UInt32 BaseOfData32;\n  UInt64 ImageBase;\n\n  UInt32 SectAlign;\n  UInt32 FileAlign;\n\n  CVersion OsVer;\n  CVersion ImageVer;\n  CVersion SubsysVer;\n  \n  UInt32 ImageSize;\n  UInt32 HeadersSize;\n  UInt32 CheckSum;\n  UInt16 SubSystem;\n  UInt16 DllCharacts;\n\n  UInt64 StackReserve;\n  UInt64 StackCommit;\n  UInt64 HeapReserve;\n  UInt64 HeapCommit;\n\n  UInt32 NumDirItems;\n  CDirLink DirItems[kNumDirItemsMax];\n\n  bool Is64Bit() const { return Magic == PE_OptHeader_Magic_64; }\n  bool Parse(const Byte *p, UInt32 size);\n\n  int GetNumFileAlignBits() const\n  {\n    for (unsigned i = 0; i < 32; i++)\n      if (((UInt32)1 << i) == FileAlign)\n        return (int)i;\n    return -1;\n  }\n\n  bool IsSybSystem_EFI() const\n  {\n    return\n        SubSystem >= k_SubSystems_EFI_First &&\n        SubSystem <= k_SubSystems_EFI_Last;\n  }\n};\n\n// size is 16-bit\nbool COptHeader::Parse(const Byte *p, UInt32 size)\n{\n  if (size < k_OptHeader32_Size_MIN)\n    return false;\n  Magic = Get16(p);\n  switch (Magic)\n  {\n    case PE_OptHeader_Magic_32:\n    case PE_OptHeader_Magic_64:\n      break;\n    default:\n      return false;\n  }\n  LinkerVerMajor = p[2];\n  LinkerVerMinor = p[3];\n  \n  G32( 4, CodeSize);\n  G32( 8, InitDataSize);\n  G32(12, UninitDataSize);\n  // G32(16, AddressOfEntryPoint);\n  // G32(20, BaseOfCode);\n  \n  G32(32, SectAlign);\n  G32(36, FileAlign);\n\n  OsVer.Parse(p + 40);\n  ImageVer.Parse(p + 44);\n  SubsysVer.Parse(p + 48);\n\n  // reserved = Get32(p + 52);\n\n  G32(56, ImageSize);\n  G32(60, HeadersSize);\n  G32(64, CheckSum);\n  G16(68, SubSystem);\n  G16(70, DllCharacts);\n\n  UInt32 pos;\n  if (Is64Bit())\n  {\n    if (size < k_OptHeader64_Size_MIN)\n      return false;\n    // BaseOfData32 = 0;\n    G64(24, ImageBase);\n    G64(72, StackReserve);\n    G64(80, StackCommit);\n    G64(88, HeapReserve);\n    G64(96, HeapCommit);\n    pos = 108;\n  }\n  else\n  {\n    // G32(24, BaseOfData32);\n    G32(28, ImageBase);\n    G32(72, StackReserve);\n    G32(76, StackCommit);\n    G32(80, HeapReserve);\n    G32(84, HeapCommit);\n    pos = 92;\n  }\n\n  UInt32 numDirItems;\n  G32(pos, numDirItems);\n  NumDirItems = numDirItems;\n  if (numDirItems > (1 << 13))\n    return false;\n  pos += 4;\n  if (pos + 8 * numDirItems > size)\n    return false;\n  memset((void *)DirItems, 0, sizeof(DirItems));\n  if (numDirItems > kNumDirItemsMax)\n      numDirItems = kNumDirItemsMax;\n  for (UInt32 i = 0; i < numDirItems; i++)\n    DirItems[i].Parse(p + pos + i * 8);\n  return true;\n}\n\nstatic const UInt32 kSectionSize = 40;\n\nstruct CSection\n{\n  AString Name;\n\n  UInt32 ExtractSize;\n  UInt32 VSize;\n  UInt32 Va;\n  UInt32 PSize;\n  UInt32 Pa;\n  UInt32 Flags;\n  UInt32 Time;\n  // UInt16 NumRelocs; // is set to zero for executable images\n  bool IsRealSect;\n  bool IsDebug;\n  bool IsAdditionalSection;\n\n  CSection():\n    ExtractSize(0),\n    IsRealSect(false),\n    IsDebug(false),\n    IsAdditionalSection(false)\n    // , NumRelocs(0)\n    {}\n\n  void Set_Size_for_all(UInt32 size)\n  {\n    PSize = VSize = ExtractSize = size;\n  }\n\n  UInt32 GetSize_Extract() const\n  {\n    return ExtractSize;\n  }\n\n  void UpdateTotalSize(UInt32 &totalSize) const\n  {\n    const UInt32 t = Pa + PSize;\n    if (totalSize < t)\n        totalSize = t;\n  }\n  \n  void Parse(const Byte *p);\n\n  int Compare(const CSection &s) const\n  {\n    RINOZ(MyCompare(Pa, s.Pa))\n    const UInt32 size1 = GetSize_Extract();\n    const UInt32 size2 = s.GetSize_Extract();\n    return MyCompare(size1, size2);\n  }\n};\n\nstatic const unsigned kNameSize = 8;\n\nstatic void GetName(const Byte *name, AString &res)\n{\n  res.SetFrom_CalcLen((const char *)name, kNameSize);\n}\n\nvoid CSection::Parse(const Byte *p)\n{\n  GetName(p, Name);\n  G32( 8, VSize);\n  G32(12, Va);\n  G32(16, PSize);\n  G32(20, Pa);\n  // G16(32, NumRelocs);\n  G32(36, Flags);\n  // v24.08: we extract only useful data (without extra padding bytes).\n  // VSize == 0 is not expected, but we support that case too.\n  // return (VSize && VSize < PSize) ? VSize : PSize;\n  ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;\n}\n\n\n\n// IMAGE_FILE_*\n\nstatic const CUInt32PCharPair g_HeaderCharacts[] =\n{\n  {  1, \"Executable\" },\n  { 13, \"DLL\" },\n  {  8, \"32-bit\" },\n  {  5, \"LargeAddress\" },\n  {  0, \"NoRelocs\" },\n  {  2, \"NoLineNums\" },\n  {  3, \"NoLocalSyms\" },\n  {  4, \"AggressiveWsTrim\" },\n  {  9, \"NoDebugInfo\" },\n  { 10, \"RemovableRun\" },\n  { 11, \"NetRun\" },\n  { 12, \"System\" },\n  { 14, \"UniCPU\" },\n  {  7, \"Little-Endian\" },\n  { 15, \"Big-Endian\" }\n};\n\n// IMAGE_DLLCHARACTERISTICS_*\n\nstatic const char * const g_DllCharacts[] =\n{\n    NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"HighEntropyVA\"\n  , \"Relocated\"\n  , \"Integrity\"\n  , \"NX-Compatible\"\n  , \"NoIsolation\"\n  , \"NoSEH\"\n  , \"NoBind\"\n  , \"AppContainer\"\n  , \"WDM\"\n  , \"GuardCF\"\n  , \"TerminalServerAware\"\n};\n\n\n// IMAGE_SCN_* constants:\n\nstatic const char * const g_SectFlags[] =\n{\n    NULL\n  , NULL\n  , NULL\n  , \"NoPad\"\n  , NULL\n  , \"Code\"\n  , \"InitializedData\"\n  , \"UninitializedData\"\n  , \"Other\"\n  , \"Comments\"\n  , NULL // OVER\n  , \"Remove\"\n  , \"COMDAT\"\n  , NULL\n  , \"NO_DEFER_SPEC_EXC\"\n  , \"GP\" // MEM_FARDATA\n  , NULL // SYSHEAP\n  , \"PURGEABLE\" // 16BIT\n  , \"LOCKED\"\n  , \"PRELOAD\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"ExtendedRelocations\"\n  , \"Discardable\"\n  , \"NotCached\"\n  , \"NotPaged\"\n  , \"Shared\"\n  , \"Execute\"\n  , \"Read\"\n  , \"Write\"\n};\n\nstatic const CUInt32PCharPair g_MachinePairs[] =\n{\n  { 0x014C, \"x86\" },\n  { 0x014D, \"I860\" },\n  { 0x0162, \"MIPS-R3000\" },\n  { 0x0166, \"MIPS-R4000\" },\n  { 0x0168, \"MIPS-R10000\" },\n  { 0x0169, \"MIPS-V2\" },\n  { 0x0184, \"Alpha\" },\n  { 0x01A2, \"SH3\" },\n  { 0x01A3, \"SH3-DSP\" },\n  { 0x01A4, \"SH3E\" },\n  { 0x01A6, \"SH4\" },\n  { 0x01A8, \"SH5\" },\n  { 0x01C0, \"ARM\" },\n  { 0x01C2, \"ARM-Thumb\" },\n  { 0x01C4, \"ARM-NT\" },\n  { 0x01D3, \"AM33\" },\n  { 0x01F0, \"PPC\" },\n  { 0x01F1, \"PPC-FP\" },\n  { 0x01F2, \"PPC-BE\" },\n  { 0x0200, \"IA-64\" },\n  { 0x0266, \"MIPS-16\" },\n  { 0x0284, \"Alpha-64\" },\n  { 0x0366, \"MIPS-FPU\" },\n  { 0x0466, \"MIPS-FPU16\" },\n  { 0x0520, \"TriCore\" },\n  { 0x0CEF, \"CEF\" },\n  { 0x0EBC, \"EFI\" },\n  { 0x5032, \"RISCV32\" },\n  { 0x5064, \"RISCV64\" },\n//  { 0x5128, \"RISCV128\" },\n  { 0x6232, \"LOONGARCH32\" },\n  { 0x6264, \"LOONGARCH64\" },\n  { 0x8664, \"x64\" },\n  { 0x9041, \"M32R\" },\n  { 0xA641, \"ARM64EC\" },\n  { 0xA64e, \"ARM64X\" },\n  { 0xAA64, \"ARM64\" },\n  { 0xC0EE, \"CEE\" }\n};\n\nstatic const char * const g_SubSystems[] =\n{\n    \"Unknown\"\n  , \"Native\"\n  , \"Windows GUI\"\n  , \"Windows CUI\"\n  , NULL // \"Old Windows CE\"\n  , \"OS2\"\n  , NULL\n  , \"Posix\"\n  , \"Win9x\"\n  , \"Windows CE\"\n  , \"EFI\"\n  , \"EFI Boot\"\n  , \"EFI Runtime\"\n  , \"EFI ROM\"\n  , \"XBOX\"\n  , NULL\n  , \"Windows Boot\"\n  , \"XBOX Catalog\" // 17\n};\n\nstatic const char * const g_ResTypes[] =\n{\n    NULL\n  , \"CURSOR\"\n  , \"BITMAP\"\n  , \"ICON\"\n  , \"MENU\"\n  , \"DIALOG\"\n  , \"STRING\"\n  , \"FONTDIR\"\n  , \"FONT\"\n  , \"ACCELERATOR\"\n  , \"RCDATA\"\n  , \"MESSAGETABLE\"\n  , \"GROUP_CURSOR\"\n  , NULL\n  , \"GROUP_ICON\"\n  , NULL\n  , \"VERSION\"\n  , \"DLGINCLUDE\"\n  , NULL\n  , \"PLUGPLAY\"\n  , \"VXD\"\n  , \"ANICURSOR\"\n  , \"ANIICON\"\n  , \"HTML\"\n  , \"MANIFEST\"\n};\n\nstatic const UInt32 kFlag = (UInt32)1 << 31;\nstatic const UInt32 kMask = ~kFlag;\n\nstruct CTableItem\n{\n  UInt32 Offset;\n  UInt32 ID;\n};\n\n\nstatic const UInt32 kBmpHeaderSize = 14;\nstatic const UInt32 kIconHeaderSize = 22;\n\nstruct CResItem\n{\n  UInt32 Type;\n  UInt32 ID;\n  UInt32 Lang;\n\n  UInt32 Size;\n  UInt32 Offset;\n\n  UInt32 HeaderSize;\n  Byte Header[kIconHeaderSize]; // it must be enough for max size header.\n  bool Enabled;\n\n  bool IsNameEqual(const CResItem &item) const { return Lang == item.Lang; }\n  UInt32 GetSize() const { return Size + HeaderSize; }\n  bool IsBmp() const { return Type == 2; }\n  bool IsIcon() const { return Type == 3; }\n  bool IsString() const { return Type == 6; }\n  bool IsRcData() const { return Type == 10; }\n  bool IsVersion() const { return Type == 16; }\n  bool IsRcDataOrUnknown() const { return IsRcData() || Type > 64; }\n};\n\nstruct CTextFile\n{\n  CByteDynamicBuffer Buf;\n\n  size_t FinalSize() const { return Buf.GetPos(); }\n\n  void AddChar(char c);\n  void AddWChar(UInt16 c);\n  void AddWChar_Smart(UInt16 c);\n  void NewLine();\n  void AddString(const char *s);\n  void AddSpaces(int num);\n  void AddBytes(const Byte *p, size_t size)\n  {\n    Buf.AddData(p, size);\n  }\n  \n  void OpenBlock(int num)\n  {\n    AddSpaces(num);\n    AddChar('{');\n    NewLine();\n  }\n  void CloseBlock(int num)\n  {\n    AddSpaces(num);\n    AddChar('}');\n    NewLine();\n  }\n};\n\nvoid CTextFile::AddChar(char c)\n{\n  Byte *p = Buf.GetCurPtrAndGrow(2);\n  p[0] = (Byte)c;\n  p[1] = 0;\n}\n\nvoid CTextFile::AddWChar(UInt16 c)\n{\n  Byte *p = Buf.GetCurPtrAndGrow(2);\n  SetUi16(p, c)\n}\n\nvoid CTextFile::AddWChar_Smart(UInt16 c)\n{\n  if (c == '\\n')\n  {\n    AddChar('\\\\');\n    c = 'n';\n  }\n  AddWChar(c);\n}\n\nvoid CTextFile::NewLine()\n{\n  AddChar(0x0D);\n  AddChar(0x0A);\n}\n\nvoid CTextFile::AddString(const char *s)\n{\n  for (;; s++)\n  {\n    char c = *s;\n    if (c == 0)\n      return;\n    AddChar(c);\n  }\n}\n\nvoid CTextFile::AddSpaces(int num)\n{\n  for (int i = 0; i < num; i++)\n    AddChar(' ');\n}\n\nstruct CStringItem: public CTextFile\n{\n  UInt32 Lang;\n};\n\nstruct CByteBuffer_WithLang: public CByteBuffer\n{\n  UInt32 Lang;\n};\n\n\nstruct CMixItem\n{\n  int SectionIndex;\n  int ResourceIndex;\n  int StringIndex;\n  int VersionIndex;\n\n  CMixItem(): SectionIndex(-1), ResourceIndex(-1), StringIndex(-1), VersionIndex(-1) {}\n  bool IsSectionItem() const { return ResourceIndex < 0 && StringIndex < 0 && VersionIndex < 0; }\n};\n\nstruct CUsedBitmap\n{\n  CByteBuffer Buf;\npublic:\n  void Alloc(size_t size)\n  {\n    size = (size + 7) / 8;\n    Buf.Alloc(size);\n    memset(Buf, 0, size);\n  }\n  \n  void Free()\n  {\n    Buf.Free();\n  }\n  \n  bool SetRange(size_t from, unsigned size)\n  {\n    for (unsigned i = 0; i < size; i++)\n    {\n      size_t pos = (from + i) >> 3;\n      Byte mask = (Byte)(1 << ((from + i) & 7));\n      Byte b = Buf[pos];\n      if ((b & mask) != 0)\n        return false;\n      Buf[pos] = (Byte)(b | mask);\n    }\n    return true;\n  }\n};\n \nstruct CStringKeyValue\n{\n  UString Key;\n  UString Value;\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_2(\n  IInArchiveGetStream,\n  IArchiveAllowTail\n)\n  CMyComPtr<IInStream> _stream;\n  CObjectVector<CSection> _sections;\n  CHeader _header;\n  UInt32 _totalSize;\n  Int32 _mainSubfile;\n\n  CRecordVector<CMixItem> _mixItems;\n  CRecordVector<CResItem> _items;\n  CObjectVector<CStringItem> _strings;\n  CObjectVector<CByteBuffer_WithLang> _versionFiles;\n  UString _versionFullString;\n  UString _versionShortString;\n  UString _originalFilename;\n  CObjectVector<CStringKeyValue> _versionKeys;\n\n  CByteBuffer _buf;\n  bool _oneLang;\n  UString _resourcesPrefix;\n  CUsedBitmap _usedRes;\n  // bool _parseResources;\n  bool _checksumError;\n  bool _sectionsError;\n\n  bool IsOpt() const { return _header.OptHeaderSize != 0; }\n\n  COptHeader _optHeader;\n\n  bool _coffMode;\n  bool _allowTail;\n\n  HRESULT LoadDebugSections(IInStream *stream, bool &thereIsSection);\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);\n\n  void AddResNameToString(UString &s, UInt32 id) const;\n  void AddLangPrefix(UString &s, UInt32 lang) const;\n  HRESULT ReadString(UInt32 offset, UString &dest) const;\n  HRESULT ReadTable(UInt32 offset, CRecordVector<CTableItem> &items);\n  bool ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size);\n  HRESULT OpenResources(unsigned sectIndex, IInStream *stream, IArchiveOpenCallback *callback);\n  void CloseResources();\n\n\n  bool CheckItem(const CSection &sect, const CResItem &item, size_t offset) const\n  {\n    return item.Offset >= sect.Va && offset <= _buf.Size() && _buf.Size() - offset >= item.Size;\n  }\n\npublic:\n  CHandler(bool coffMode = false):\n        _coffMode(coffMode),\n        _allowTail(coffMode)\n        {}\n};\n\n\nenum\n{\n  kpidSectAlign = kpidUserDefined,\n  kpidFileAlign,\n  kpidLinkerVer,\n  kpidOsVer,\n  kpidImageVer,\n  kpidSubsysVer,\n  kpidCodeSize,\n  kpidImageSize,\n  kpidInitDataSize,\n  kpidUnInitDataSize,\n  kpidHeadersSizeUnInitDataSize,\n  kpidSubSystem,\n  kpidDllCharacts,\n  kpidStackReserve,\n  kpidStackCommit,\n  kpidHeapReserve,\n  kpidHeapCommit\n  // , kpidImageBase\n  // , kpidAddressOfEntryPoint\n  // , kpidBaseOfCode\n  // , kpidBaseOfData32\n};\n\nstatic const CStatProp kArcProps[] =\n{\n  // { NULL, kpidWarning, VT_BSTR},\n  { NULL, kpidCpu, VT_BSTR},\n  { NULL, kpidBit64, VT_BOOL},\n  { NULL, kpidCharacts, VT_BSTR},\n  { NULL, kpidCTime, VT_FILETIME},\n  { NULL, kpidHeadersSize, VT_UI4},\n  { NULL, kpidChecksum, VT_UI4},\n  { NULL, kpidName, VT_BSTR},\n\n  { \"Image Size\", kpidImageSize, VT_UI4},\n  { \"Section Alignment\", kpidSectAlign, VT_UI4},\n  { \"File Alignment\", kpidFileAlign, VT_UI4},\n  { \"Code Size\", kpidCodeSize, VT_UI4},\n  { \"Initialized Data Size\", kpidInitDataSize, VT_UI4},\n  { \"Uninitialized Data Size\", kpidUnInitDataSize, VT_UI4},\n  { \"Linker Version\", kpidLinkerVer, VT_BSTR},\n  { \"OS Version\", kpidOsVer, VT_BSTR},\n  { \"Image Version\", kpidImageVer, VT_BSTR},\n  { \"Subsystem Version\", kpidSubsysVer, VT_BSTR},\n  { \"Subsystem\", kpidSubSystem, VT_BSTR},\n  { \"DLL Characteristics\", kpidDllCharacts, VT_BSTR},\n  { \"Stack Reserve\", kpidStackReserve, VT_UI8},\n  { \"Stack Commit\", kpidStackCommit, VT_UI8},\n  { \"Heap Reserve\", kpidHeapReserve, VT_UI8},\n  { \"Heap Commit\", kpidHeapCommit, VT_UI8},\n  { NULL, kpidVa, VT_UI8 }, // \"Image Base\", kpidImageBase, VT_UI8\n  { NULL, kpidComment, VT_BSTR}\n  \n  // , { \"Address Of Entry Point\", kpidAddressOfEntryPoint, VT_UI8}\n  // , { \"Base Of Code\", kpidBaseOfCode, VT_UI8}\n  // , { \"Base Of Data\", kpidBaseOfData32, VT_UI8}\n};\n\n// #define kpid_NumRelocs 250\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidVirtualSize,\n  kpidCharacts,\n  kpidOffset,\n  kpidVa\n  // , kpid_NumRelocs\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\nstatic void TimeToProp(UInt32 unixTime, NCOM::CPropVariant &prop)\n{\n  if (unixTime != 0)\n    PropVariant_SetFrom_UnixTime(prop, unixTime);\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _totalSize; break;\n    case kpidComment:\n    {\n      UString s (_versionFullString);\n      s.Add_LF();\n      s += \"Data Directories: \";\n      s.Add_UInt32(_optHeader.NumDirItems);\n      s.Add_LF();\n      s.Add_Char('{');\n      s.Add_LF();\n      for (unsigned i = 0; i < _optHeader.NumDirItems\n          && i < Z7_ARRAY_SIZE(_optHeader.DirItems); i++)\n      {\n        const CDirLink &di = _optHeader.DirItems[i];\n        if (di.Va == 0 && di.Size == 0)\n          continue;\n        s += \"index=\";\n        s.Add_UInt32(i);\n\n        if (i < Z7_ARRAY_SIZE(g_Dir_Names))\n        {\n          s += \" name=\";\n          s += g_Dir_Names[i];\n        }\n        s += \" VA=0x\";\n        char temp[16];\n        ConvertUInt32ToHex(di.Va, temp);\n        s += temp;\n        s += \" Size=\";\n        s.Add_UInt32(di.Size);\n        s.Add_LF();\n      }\n      s.Add_Char('}');\n      s.Add_LF();\n      prop = s;\n      break;\n    }\n    case kpidShortComment:\n      if (!_versionShortString.IsEmpty())\n        prop = _versionShortString;\n      else\n      {\n        PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop);\n      }\n      break;\n\n    case kpidName: if (!_originalFilename.IsEmpty()) prop = _originalFilename; break;\n      \n    // case kpidIsSelfExe: prop = !_header.IsDll(); break;\n    // case kpidError:\n    case kpidWarning: if (_checksumError) prop = \"Checksum error\"; break;\n\n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      if (_sectionsError) v |= kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n\n    case kpidCpu: PAIR_TO_PROP(g_MachinePairs, _header.Machine, prop); break;\n    case kpidMTime:\n    case kpidCTime: TimeToProp(_header.Time, prop); break;\n    case kpidCharacts: FLAGS_TO_PROP(g_HeaderCharacts, _header.Flags, prop); break;\n    case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;\n    \n    default:\n    if (IsOpt())\n    switch (propID)\n    {\n\n    case kpidSectAlign: prop = _optHeader.SectAlign; break;\n    case kpidFileAlign: prop = _optHeader.FileAlign; break;\n    case kpidLinkerVer:\n    {\n      CVersion v = { _optHeader.LinkerVerMajor, _optHeader.LinkerVerMinor };\n      v.ToProp(prop);\n      break;\n    }\n  \n    case kpidOsVer: _optHeader.OsVer.ToProp(prop); break;\n    case kpidImageVer: _optHeader.ImageVer.ToProp(prop); break;\n    case kpidSubsysVer: _optHeader.SubsysVer.ToProp(prop); break;\n    case kpidCodeSize: prop = _optHeader.CodeSize; break;\n    case kpidInitDataSize: prop = _optHeader.InitDataSize; break;\n    case kpidUnInitDataSize: prop = _optHeader.UninitDataSize; break;\n    case kpidImageSize: prop = _optHeader.ImageSize; break;\n    case kpidHeadersSize: prop = _optHeader.HeadersSize; break;\n    case kpidChecksum: prop = _optHeader.CheckSum; break;\n\n    case kpidExtension:\n      if (_header.IsDll())\n        prop = \"dll\";\n      else if (_optHeader.IsSybSystem_EFI())\n        prop = \"efi\";\n      break;\n\n    case kpidBit64: if (_optHeader.Is64Bit()) prop = true; break;\n    case kpidSubSystem: TYPE_TO_PROP(g_SubSystems, _optHeader.SubSystem, prop); break;\n\n    case kpidDllCharacts: FLAGS_TO_PROP(g_DllCharacts, _optHeader.DllCharacts, prop); break;\n    case kpidStackReserve: prop = _optHeader.StackReserve; break;\n    case kpidStackCommit: prop = _optHeader.StackCommit; break;\n    case kpidHeapReserve: prop = _optHeader.HeapReserve; break;\n    case kpidHeapCommit: prop = _optHeader.HeapCommit; break;\n    case kpidVa: prop = _optHeader.ImageBase; break; // kpidImageBase:\n    // case kpidAddressOfEntryPoint: prop = _optHeader.AddressOfEntryPoint; break;\n    // case kpidBaseOfCode: prop = _optHeader.BaseOfCode; break;\n    // case kpidBaseOfData32: if (!_optHeader.Is64Bit()) prop = _optHeader.BaseOfData32; break;\n  }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nHRESULT CHandler::ReadString(UInt32 offset, UString &dest) const\n{\n  if ((offset & 1) != 0 || offset >= _buf.Size())\n    return S_FALSE;\n  size_t rem = _buf.Size() - offset;\n  if (rem < 2)\n    return S_FALSE;\n  unsigned len = Get16(_buf + offset);\n  if ((rem - 2) / 2 < len)\n    return S_FALSE;\n  dest.Empty();\n  wchar_t *destBuf = dest.GetBuf(len);\n  offset += 2;\n  const Byte *src = _buf + offset;\n  unsigned i;\n  for (i = 0; i < len; i++)\n  {\n    wchar_t c = (wchar_t)Get16(src + i * 2);\n    if (c == 0)\n      break;\n    destBuf[i] = c;\n  }\n  destBuf[i] = 0;\n  dest.ReleaseBuf_SetLen(i);\n  return S_OK;\n}\n\nvoid CHandler::AddResNameToString(UString &s, UInt32 id) const\n{\n  if ((id & kFlag) != 0)\n  {\n    UString name;\n    if (ReadString(id & kMask, name) == S_OK)\n    {\n      const wchar_t *str = L\"[]\";\n      if (name.Len() > 1 && name[0] == '\"' && name.Back() == '\"')\n      {\n        if (name.Len() != 2)\n        {\n          name.DeleteBack();\n          str = name.Ptr(1);\n        }\n      }\n      else if (!name.IsEmpty())\n        str = name;\n      s += str;\n      return;\n    }\n  }\n  s.Add_UInt32(id);\n}\n\nvoid CHandler::AddLangPrefix(UString &s, UInt32 lang) const\n{\n  if (!_oneLang)\n  {\n    AddResNameToString(s, lang);\n    s.Add_PathSepar();\n  }\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  const CMixItem &mixItem = _mixItems[index];\n  if (mixItem.StringIndex >= 0)\n  {\n    const CStringItem &item = _strings[mixItem.StringIndex];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        UString s = _resourcesPrefix;\n        AddLangPrefix(s, item.Lang);\n        s += \"string.txt\";\n        prop = s;\n        break;\n      }\n      case kpidSize:\n      case kpidPackSize:\n        prop = (UInt64)item.FinalSize(); break;\n    }\n  }\n  else if (mixItem.VersionIndex >= 0)\n  {\n    const CByteBuffer_WithLang &item = _versionFiles[mixItem.VersionIndex];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        UString s = _resourcesPrefix;\n        AddLangPrefix(s, item.Lang);\n        s += \"version.txt\";\n        prop = s;\n        break;\n      }\n      case kpidSize:\n      case kpidPackSize:\n        prop = (UInt64)item.Size(); break;\n    }\n  }\n  else if (mixItem.ResourceIndex >= 0)\n  {\n    const CResItem &item = _items[mixItem.ResourceIndex];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        UString s = _resourcesPrefix;\n        AddLangPrefix(s, item.Lang);\n        {\n          const char *p = NULL;\n          if (item.Type < Z7_ARRAY_SIZE(g_ResTypes))\n            p = g_ResTypes[item.Type];\n          if (p)\n            s += p;\n          else\n            AddResNameToString(s, item.Type);\n        }\n        s.Add_PathSepar();\n        AddResNameToString(s, item.ID);\n        if (item.HeaderSize != 0)\n        {\n          if (item.IsBmp())\n            s += \".bmp\";\n          else if (item.IsIcon())\n            s += \".ico\";\n        }\n        prop = s;\n        break;\n      }\n      case kpidSize: prop = (UInt64)item.GetSize(); break;\n      case kpidPackSize: prop = (UInt64)item.Size; break;\n    }\n  }\n  else\n  {\n    const CSection &item = _sections[mixItem.SectionIndex];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        AString s = item.Name;\n        s.Replace('/', '_');\n        s.Replace('\\\\', '_');\n        prop = MultiByteToUnicodeString(s);\n        break;\n      }\n      case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;\n      // case kpid_NumRelocs: prop = (UInt32)item.NumRelocs; break;\n      case kpidPackSize: prop = (UInt64)item.PSize; break;\n      case kpidVirtualSize: prop = (UInt64)item.VSize; break;\n      case kpidOffset: prop = item.Pa; break;\n      case kpidVa: if (item.IsRealSect) prop = item.Va; break;\n      case kpidMTime:\n      case kpidCTime:\n        TimeToProp(item.IsDebug ? item.Time : _header.Time, prop); break;\n      case kpidCharacts:\n       if (item.IsRealSect)\n       {\n         UInt32 flags = item.Flags;\n         const UInt32 MY_IMAGE_SCN_ALIGN_MASK = 0x00F00000;\n         AString s = FlagsToString(g_SectFlags, Z7_ARRAY_SIZE(g_SectFlags), item.Flags & ~MY_IMAGE_SCN_ALIGN_MASK);\n         const UInt32 align = ((flags >> 20) & 0xF);\n         if (align != 0)\n         {\n           char sz[32];\n           ConvertUInt32ToString(1 << (align - 1), sz);\n           s.Add_Space();\n           s += \"align_\";\n           s += sz;\n         }\n         prop = s;\n       }\n       break;\n      case kpidZerosTailIsAllowed: if (!item.IsRealSect) prop = true; break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nHRESULT CHandler::LoadDebugSections(IInStream *stream, bool &thereIsSection)\n{\n  thereIsSection = false;\n  const CDirLink &debugLink = _optHeader.DirItems[kDirLink_Debug];\n  if (debugLink.Size == 0)\n    return S_OK;\n  const unsigned kEntrySize = 28;\n  UInt32 numItems = debugLink.Size / kEntrySize;\n  if (numItems > 16)\n    return S_FALSE;\n\n  // MAC's EFI file: numItems can be incorrect. Only first CDebugEntry entry is correct.\n  // debugLink.Size = kEntrySize + some_data, pointed by entry[0].\n  if (numItems * kEntrySize != debugLink.Size)\n  {\n    // return S_FALSE;\n    if (numItems > 1)\n      numItems = 1;\n  }\n  \n  UInt64 pa = 0;\n  unsigned i;\n  for (i = 0; i < _sections.Size(); i++)\n  {\n    const CSection &sect = _sections[i];\n    if (sect.Va <= debugLink.Va && debugLink.Va + debugLink.Size <= sect.Va + sect.PSize)\n    {\n      pa = sect.Pa + (debugLink.Va - sect.Va);\n      break;\n    }\n  }\n  if (i == _sections.Size())\n  {\n    // Exe for ARM requires S_OK\n    // return S_FALSE;\n    return S_OK;\n  }\n  \n  CByteBuffer buffer(debugLink.Size);\n  Byte *buf = buffer;\n  \n  RINOK(InStream_SeekSet(stream, pa))\n  RINOK(ReadStream_FALSE(stream, buf, debugLink.Size))\n\n  for (i = 0; i < numItems; i++)\n  {\n    CDebugEntry de;\n    de.Parse(buf);\n\n    if (de.Size == 0)\n      continue;\n    \n    UInt32 totalSize = de.Pa + de.Size;\n    if (totalSize > _totalSize)\n    {\n      _totalSize = totalSize;\n      thereIsSection = true;\n\n      CSection &sect = _sections.AddNew();\n      sect.Name = \".debug\";\n      sect.Name.Add_UInt32(i);\n      sect.IsDebug = true;\n      sect.Time = de.Time;\n      sect.Va = de.Va;\n      sect.Pa = de.Pa;\n      sect.Set_Size_for_all(de.Size);\n    }\n    buf += kEntrySize;\n  }\n\n  return S_OK;\n}\n\nHRESULT CHandler::ReadTable(UInt32 offset, CRecordVector<CTableItem> &items)\n{\n  if ((offset & 3) != 0 || offset >= _buf.Size())\n    return S_FALSE;\n  size_t rem = _buf.Size() - offset;\n  if (rem < 16)\n    return S_FALSE;\n  unsigned numNameItems = Get16(_buf + offset + 12);\n  unsigned numIdItems = Get16(_buf + offset + 14);\n  unsigned numItems = numNameItems + numIdItems;\n  if ((rem - 16) / 8 < numItems)\n    return S_FALSE;\n  if (!_usedRes.SetRange(offset, 16 + numItems * 8))\n    return S_FALSE;\n  offset += 16;\n  items.ClearAndReserve(numItems);\n  for (unsigned i = 0; i < numItems; i++, offset += 8)\n  {\n    const Byte *buf = _buf + offset;\n    CTableItem item;\n    item.ID = Get32(buf + 0);\n    if ((bool)((item.ID & kFlag) != 0) != (bool)(i < numNameItems))\n      return S_FALSE;\n    item.Offset = Get32(buf + 4);\n    items.AddInReserved(item);\n  }\n  return S_OK;\n}\n\nstatic const UInt32 kFileSizeMax = (UInt32)1 << 31;\nstatic const unsigned kNumResItemsMax = (unsigned)1 << 23;\nstatic const unsigned kNumStringLangsMax = 256;\n\n// BITMAPINFOHEADER\nstruct CBitmapInfoHeader\n{\n  // UInt32 HeaderSize;\n  UInt32 XSize;\n  Int32 YSize;\n  UInt16 Planes;\n  UInt16 BitCount;\n  UInt32 Compression;\n  UInt32 SizeImage;\n\n  bool Parse(const Byte *p, size_t size);\n};\n\nstatic const UInt32 kBitmapInfoHeader_Size = 0x28;\n\nbool CBitmapInfoHeader::Parse(const Byte *p, size_t size)\n{\n  if (size < kBitmapInfoHeader_Size || Get32(p) != kBitmapInfoHeader_Size)\n    return false;\n  G32( 4, XSize);\n  G32_signed( 8, YSize);\n  G16(12, Planes);\n  G16(14, BitCount);\n  G32(16, Compression);\n  G32(20, SizeImage);\n  return true;\n}\n\nstatic UInt32 GetImageSize(UInt32 xSize, UInt32 ySize, UInt32 bitCount)\n{\n  return ((xSize * bitCount + 7) / 8 + 3) / 4 * 4 * ySize;\n}\n  \nstatic UInt32 SetBitmapHeader(Byte *dest, const Byte *src, UInt32 size)\n{\n  CBitmapInfoHeader h;\n  if (!h.Parse(src, size))\n    return 0;\n  if (h.YSize < 0)\n    h.YSize = -h.YSize;\n  if (h.XSize > (1 << 26)\n      || h.YSize > (1 << 26)\n      || h.YSize < 0\n      || h.Planes != 1 || h.BitCount > 32)\n    return 0;\n  if (h.SizeImage == 0)\n  {\n    if (h.Compression != 0) // BI_RGB\n      return 0;\n    h.SizeImage = GetImageSize(h.XSize, (UInt32)h.YSize, h.BitCount);\n  }\n  UInt32 totalSize = kBmpHeaderSize + size;\n  UInt32 offBits = totalSize - h.SizeImage;\n  // BITMAPFILEHEADER\n  SetUi16(dest, 0x4D42)\n  SetUi32(dest + 2, totalSize)\n  SetUi32(dest + 6, 0)\n  SetUi32(dest + 10, offBits)\n  return kBmpHeaderSize;\n}\n\nstatic UInt32 SetIconHeader(Byte *dest, const Byte *src, UInt32 size)\n{\n  CBitmapInfoHeader h;\n  if (!h.Parse(src, size))\n    return 0;\n  if (h.YSize < 0)\n    h.YSize = -h.YSize;\n  if (h.XSize > (1 << 26)\n      || h.YSize > (1 << 26)\n      || h.YSize < 0\n      || h.Planes != 1\n      || h.Compression != 0) // BI_RGB\n    return 0;\n\n  const UInt32 numBitCount = h.BitCount;\n  if (numBitCount != 1 &&\n      numBitCount != 4 &&\n      numBitCount != 8 &&\n      numBitCount != 24 &&\n      numBitCount != 32)\n    return 0;\n\n  if ((h.YSize & 1) != 0)\n    return 0;\n  h.YSize /= 2;\n  if (h.XSize > 0x100 || h.YSize > 0x100)\n    return 0;\n\n  UInt32 imageSize;\n  // imageSize is not correct if AND mask array contains zeros\n  // in this case it is equal image1Size\n\n  // UInt32 imageSize = h.SizeImage;\n  // if (imageSize == 0)\n  // {\n    const UInt32 image1Size = GetImageSize(h.XSize, (UInt32)h.YSize, h.BitCount);\n    const UInt32 image2Size = GetImageSize(h.XSize, (UInt32)h.YSize, 1);\n    imageSize = image1Size + image2Size;\n  // }\n  UInt32 numColors = 0;\n  if (numBitCount < 16)\n    numColors = 1 << numBitCount;\n\n  SetUi16(dest, 0) // Reserved\n  SetUi16(dest + 2, 1) // RES_ICON\n  SetUi16(dest + 4, 1) // ResCount\n\n  dest[6] = (Byte)h.XSize; // Width\n  dest[7] = (Byte)h.YSize; // Height\n  dest[8] = (Byte)numColors; // ColorCount\n  dest[9] = 0; // Reserved\n  \n  SetUi32(dest + 10, 0) // Reserved1 / Reserved2\n\n  UInt32 numQuadsBytes = numColors * 4;\n  UInt32 BytesInRes = kBitmapInfoHeader_Size + numQuadsBytes + imageSize;\n  SetUi32(dest + 14, BytesInRes)\n  SetUi32(dest + 18, kIconHeaderSize)\n\n  /*\n  Description = DWORDToString(xSize) +\n      kDelimiterChar + DWORDToString(ySize) +\n      kDelimiterChar + DWORDToString(numBitCount);\n  */\n  return kIconHeaderSize;\n}\n\nbool CHandler::ParseStringRes(UInt32 id, UInt32 lang, const Byte *src, UInt32 size)\n{\n  if ((size & 1) != 0)\n    return false;\n\n  unsigned i;\n  for (i = 0; i < _strings.Size(); i++)\n    if (_strings[i].Lang == lang)\n      break;\n  if (i == _strings.Size())\n  {\n    if (_strings.Size() >= kNumStringLangsMax)\n      return false;\n    CStringItem &item = _strings.AddNew();\n    item.Lang = lang;\n  }\n  \n  CStringItem &item = _strings[i];\n  id = (id - 1) << 4;\n  UInt32 pos = 0;\n  for (i = 0; i < 16; i++)\n  {\n    if (size - pos < 2)\n      return false;\n    UInt32 len = Get16(src + pos);\n    pos += 2;\n    if (len != 0)\n    {\n      if (size - pos < len * 2)\n        return false;\n      char temp[32];\n      ConvertUInt32ToString(id + i, temp);\n      size_t tempLen = strlen(temp);\n      size_t j;\n      for (j = 0; j < tempLen; j++)\n        item.AddChar(temp[j]);\n      item.AddChar('\\t');\n      for (j = 0; j < len; j++, pos += 2)\n        item.AddWChar_Smart(Get16(src + pos));\n      item.NewLine();\n    }\n  }\n  if (size == pos)\n    return true;\n  \n  // Some rare case files have additional ZERO.\n  if (size == pos + 2 && Get16(src + pos) == 0)\n    return true;\n  \n  return false;\n}\n\n\n// ---------- VERSION ----------\n\nstatic const UInt32 kMy_VS_FFI_SIGNATURE = 0xFEEF04BD;\n\nstruct CMy_VS_FIXEDFILEINFO\n{\n  // UInt32 Signature;\n  // UInt32 StrucVersion;\n  UInt32 VersionMS;\n  UInt32 VersionLS;\n  UInt32 ProductVersionMS;\n  UInt32 ProductVersionLS;\n  UInt32 FlagsMask;\n  UInt32 Flags;\n  UInt32 OS;\n  UInt32 Type;\n  UInt32 Subtype;\n  UInt32 DateMS;\n  UInt32 DateLS;\n\n  bool Parse(const Byte *p);\n  void PrintToTextFile(CTextFile &f, CObjectVector<CStringKeyValue> &keys);\n};\n\nbool CMy_VS_FIXEDFILEINFO::Parse(const Byte *p)\n{\n  if (Get32(p) != kMy_VS_FFI_SIGNATURE) // signature;\n    return false;\n  // G32(0x04, StrucVersion);\n  G32(0x08, VersionMS);\n  G32(0x0C, VersionLS);\n  G32(0x10, ProductVersionMS);\n  G32(0x14, ProductVersionLS);\n  G32(0x18, FlagsMask);\n  G32(0x1C, Flags);\n  G32(0x20, OS);\n  G32(0x24, Type);\n  G32(0x28, Subtype);\n  G32(0x2C, DateMS);\n  G32(0x40, DateLS);\n  return true;\n}\n\nstatic void PrintUInt32(CTextFile &f, UInt32 v)\n{\n  char s[16];\n  ConvertUInt32ToString(v, s);\n  f.AddString(s);\n}\n\nstatic inline void PrintUInt32(UString &dest, UInt32 v)\n{\n  dest.Add_UInt32(v);\n}\n\nstatic void PrintHex(CTextFile &f, UInt32 val)\n{\n  char temp[16];\n  temp[0] = '0';\n  temp[1] = 'x';\n  ConvertUInt32ToHex(val, temp + 2);\n  f.AddString(temp);\n}\n\nstatic void PrintVersion(CTextFile &f, UInt32 ms, UInt32 ls)\n{\n  PrintUInt32(f, HIWORD(ms));  f.AddChar(',');\n  PrintUInt32(f, LOWORD(ms));  f.AddChar(',');\n  PrintUInt32(f, HIWORD(ls));  f.AddChar(',');\n  PrintUInt32(f, LOWORD(ls));\n}\n\nstatic void PrintVersion(UString &s, UInt32 ms, UInt32 ls)\n{\n  PrintUInt32(s, HIWORD(ms));  s.Add_Dot();\n  PrintUInt32(s, LOWORD(ms));  s.Add_Dot();\n  PrintUInt32(s, HIWORD(ls));  s.Add_Dot();\n  PrintUInt32(s, LOWORD(ls));\n}\n\nstatic const char * const k_VS_FileFlags[] =\n{\n    \"DEBUG\"\n  , \"PRERELEASE\"\n  , \"PATCHED\"\n  , \"PRIVATEBUILD\"\n  , \"INFOINFERRED\"\n  , \"SPECIALBUILD\"\n};\n\nstatic const CUInt32PCharPair k_VS_FileOS[] =\n{\n  {  0x10001, \"VOS_DOS_WINDOWS16\" },\n  {  0x10004, \"VOS_DOS_WINDOWS32\" },\n  {  0x20002, \"VOS_OS216_PM16\" },\n  {  0x30003, \"VOS_OS232_PM32\" },\n  {  0x40004, \"VOS_NT_WINDOWS32\" }\n};\n\nstatic const char * const k_VS_FileOS_High[] =\n{\n    \"VOS_UNKNOWN\"\n  , \"VOS_DOS\"\n  , \"VOS_OS216\"\n  , \"VOS_OS232\"\n  , \"VOS_NT\"\n  , \"VOS_WINCE\"\n};\n\nstatic const UInt32 kMY_VFT_DRV  = 3;\nstatic const UInt32 kMY_VFT_FONT = 4;\n\nstatic const char * const k_VS_FileOS_Low[] =\n{\n    \"VOS__BASE\"\n  , \"VOS__WINDOWS16\"\n  , \"VOS__PM16\"\n  , \"VOS__PM32\"\n  , \"VOS__WINDOWS32\"\n};\n\nstatic const char * const k_VS_FileType[] =\n{\n    \"VFT_UNKNOWN\"\n  , \"VFT_APP\"\n  , \"VFT_DLL\"\n  , \"VFT_DRV\"\n  , \"VFT_FONT\"\n  , \"VFT_VXD\"\n  , \"0x6\"\n  , \"VFT_STATIC_LIB\"\n};\n\n// Subtype for VFT_DRV Type\nstatic const char * const k_VS_FileSubType_DRV[] =\n{\n    \"0\"\n  , \"PRINTER\"\n  , \"KEYBOARD\"\n  , \"LANGUAGE\"\n  , \"DISPLAY\"\n  , \"MOUSE\"\n  , \"NETWORK\"\n  , \"SYSTEM\"\n  , \"INSTALLABLE\"\n  , \"SOUND\"\n  , \"COMM\"\n  , \"INPUTMETHOD\"\n  , \"VERSIONED_PRINTER\"\n};\n\n// Subtype for VFT_FONT Type\nstatic const char * const k_VS_FileSubType_FONT[] =\n{\n    \"0\"\n  , \"VFT2_FONT_RASTER\"\n  , \"VFT2_FONT_VECTOR\"\n  , \"VFT2_FONT_TRUETYPE\"\n};\n\nstatic int FindKey(CObjectVector<CStringKeyValue> &v, const char *key)\n{\n  FOR_VECTOR (i, v)\n    if (v[i].Key.IsEqualTo(key))\n      return (int)i;\n  return -1;\n}\n\nstatic void AddToUniqueUStringVector(CObjectVector<CStringKeyValue> &v, const UString &key, const UString &value)\n{\n  bool needInsert = false;\n  unsigned i;\n  for (i = 0; i < v.Size(); i++)\n  {\n    if (v[i].Key == key)\n    {\n      if (v[i].Value == value)\n        return;\n      needInsert = true;\n    }\n    else if (needInsert)\n      break;\n  }\n  CStringKeyValue &pair = v.InsertNew(i);\n  pair.Key = key;\n  pair.Value = value;\n}\n\nvoid CMy_VS_FIXEDFILEINFO::PrintToTextFile(CTextFile &f, CObjectVector<CStringKeyValue> &keys)\n{\n  f.AddString(\"FILEVERSION    \");\n  PrintVersion(f, VersionMS, VersionLS);\n  f.NewLine();\n\n  f.AddString(\"PRODUCTVERSION \");\n  PrintVersion(f, ProductVersionMS, ProductVersionLS);\n  f.NewLine();\n\n  {\n    UString s;\n    PrintVersion(s, VersionMS, VersionLS);\n    AddToUniqueUStringVector(keys, L\"FileVersion\", s);\n  }\n  {\n    UString s;\n    PrintVersion(s, ProductVersionMS, ProductVersionLS);\n    AddToUniqueUStringVector(keys, L\"ProductVersion\", s);\n  }\n \n  f.AddString(\"FILEFLAGSMASK  \");\n  PrintHex(f, FlagsMask);\n  f.NewLine();\n\n  f.AddString(\"FILEFLAGS      \");\n  {\n    bool wasPrinted = false;\n    for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_VS_FileFlags); i++)\n    {\n      if ((Flags & ((UInt32)1 << i)) != 0)\n      {\n        if (wasPrinted)\n          f.AddString(\" | \");\n        f.AddString(\"VS_FF_\");\n        f.AddString(k_VS_FileFlags[i]);\n        wasPrinted = true;\n      }\n    }\n    UInt32 v = Flags & ~(((UInt32)1 << Z7_ARRAY_SIZE(k_VS_FileFlags)) - 1);\n    if (v != 0 || !wasPrinted)\n    {\n      if (wasPrinted)\n        f.AddString(\" | \");\n      PrintHex(f, v);\n    }\n  }\n  f.NewLine();\n\n  // OS = 0x111230;\n  f.AddString(\"FILEOS         \");\n  unsigned i;\n  for (i = 0; i < Z7_ARRAY_SIZE(k_VS_FileOS); i++)\n  {\n    const CUInt32PCharPair &pair = k_VS_FileOS[i];\n    if (OS == pair.Value)\n    {\n      // continue;\n      // f.AddString(\"VOS_\");\n      f.AddString(pair.Name);\n      break;\n    }\n  }\n  if (i == Z7_ARRAY_SIZE(k_VS_FileOS))\n  {\n    UInt32 high = OS >> 16;\n    if (high < Z7_ARRAY_SIZE(k_VS_FileOS_High))\n      f.AddString(k_VS_FileOS_High[high]);\n    else\n      PrintHex(f, high << 16);\n    UInt32 low = OS & 0xFFFF;\n    if (low != 0)\n    {\n      f.AddString(\" | \");\n      if (low < Z7_ARRAY_SIZE(k_VS_FileOS_Low))\n        f.AddString(k_VS_FileOS_Low[low]);\n      else\n        PrintHex(f, low);\n    }\n  }\n  f.NewLine();\n\n  f.AddString(\"FILETYPE       \");\n  if (Type < Z7_ARRAY_SIZE(k_VS_FileType))\n    f.AddString(k_VS_FileType[Type]);\n  else\n    PrintHex(f, Type);\n  f.NewLine();\n\n  f.AddString(\"FILESUBTYPE    \");\n  bool needPrintSubType = true;\n  if (Type == kMY_VFT_DRV)\n  {\n    if (Subtype != 0 && Subtype < Z7_ARRAY_SIZE(k_VS_FileSubType_DRV))\n    {\n      f.AddString(\"VFT2_DRV_\");\n      f.AddString(k_VS_FileSubType_DRV[Subtype]);\n      needPrintSubType = false;\n    }\n  }\n  else if (Type == kMY_VFT_FONT)\n  {\n    if (Subtype != 0 && Subtype < Z7_ARRAY_SIZE(k_VS_FileSubType_FONT))\n    {\n      f.AddString(k_VS_FileSubType_FONT[Subtype]);\n      needPrintSubType = false;\n    }\n  }\n  if (needPrintSubType)\n    PrintHex(f, Subtype);\n  f.NewLine();\n}\n\nstatic void CopyToUString(const Byte *p, UString &s)\n{\n  for (;;)\n  {\n    const wchar_t c = (wchar_t)Get16(p);\n    p += 2;\n    if (c == 0)\n      return;\n    s += c;\n  }\n}\n\nstatic void CopyToUString_ByLen16(const Byte *p, unsigned numChars16, UString &s)\n{\n  for (; numChars16; numChars16--)\n  {\n    const wchar_t c = (wchar_t)Get16(p);\n    p += 2;\n    s += c;\n  }\n}\n\nstatic bool CompareWStrStrings(const Byte *p, const char *s)\n{\n  unsigned pos = 0;\n  for (;;)\n  {\n    const Byte c = (Byte)*s++;\n    if (Get16(p + pos) != c)\n      return false;\n    pos += 2;\n    if (c == 0)\n      return true;\n  }\n}\n\nstruct CVersionBlock\n{\n  UInt32 TotalLen;\n  UInt32 ValueLen;\n  unsigned IsTextValue;\n  unsigned StrSize;\n\n  bool Parse(const Byte *p, UInt32 size);\n};\n\nstatic int Get_Utf16Str_Len_InBytes(const Byte *p, size_t size)\n{\n  unsigned pos = 0;\n  for (;;)\n  {\n    if (pos + 1 >= size)\n      return -1;\n    if (Get16(p + pos) == 0)\n      return (int)pos;\n    pos += 2;\n  }\n}\n\nstatic int Get_Utf16Str_Len_InBytes_AllowNonZeroTail(const Byte *p, size_t size)\n{\n  unsigned pos = 0;\n  for (;;)\n  {\n    if (pos + 1 >= size)\n    {\n      if (pos == size)\n        return (int)pos;\n      return -1;\n    }\n    if (Get16(p + pos) == 0)\n      return (int)pos;\n    pos += 2;\n  }\n}\n\nstatic const unsigned k_ResoureBlockHeader_Size = 6;\n\nbool CVersionBlock::Parse(const Byte *p, UInt32 size)\n{\n  if (size < k_ResoureBlockHeader_Size)\n    return false;\n  TotalLen = Get16(p);\n  ValueLen = Get16(p + 2);\n  if (TotalLen < k_ResoureBlockHeader_Size || TotalLen > size)\n    return false;\n  IsTextValue = Get16(p + 4);\n  if (IsTextValue > 1)\n    return false;\n  StrSize = 0;\n  const int t = Get_Utf16Str_Len_InBytes(p + k_ResoureBlockHeader_Size,\n      TotalLen - k_ResoureBlockHeader_Size);\n  if (t < 0)\n    return false;\n  StrSize = (unsigned)t;\n  return true;\n}\n\nstatic void AddParamString(CTextFile &f, const Byte *p, size_t sLen)\n{\n  f.AddChar(' ');\n  f.AddChar('\\\"');\n  f.AddBytes(p, sLen);\n  f.AddChar('\\\"');\n}\n\nstatic bool ParseVersion(const Byte *p, UInt32 size, CTextFile &f, CObjectVector<CStringKeyValue> &keys)\n{\n  UInt32 pos;\n  {\n    const unsigned k_sizeof_VS_FIXEDFILEINFO = 13 * 4;\n\n    CVersionBlock vb;\n    if (!vb.Parse(p, size))\n      return false;\n    if (vb.ValueLen != k_sizeof_VS_FIXEDFILEINFO) // maybe 0 is allowed here?\n      return false;\n    if (vb.IsTextValue)\n      return false;\n    pos = k_ResoureBlockHeader_Size;\n    if (!CompareWStrStrings(p + pos, \"VS_VERSION_INFO\"))\n      return false;\n    pos += vb.StrSize + 2;\n    pos += (4 - pos) & 3;\n    if (pos + vb.ValueLen > vb.TotalLen)\n      return false;\n    /* sometimes resource contains zeros in remainder.\n       So we don't check that size != vb.TotalLen\n    // if (size != vb.TotalLen) return false;\n    */\n    if (size > vb.TotalLen)\n        size = vb.TotalLen;\n    CMy_VS_FIXEDFILEINFO FixedFileInfo;\n    if (!FixedFileInfo.Parse(p + pos))\n      return false;\n    FixedFileInfo.PrintToTextFile(f, keys);\n    pos += vb.ValueLen;\n  }\n  \n  f.OpenBlock(0);\n  \n  for (;;)\n  {\n    pos += (4 - pos) & 3;\n    if (pos >= size)\n      break;\n    \n    CVersionBlock vb;\n    if (!vb.Parse(p + pos, size - pos))\n      return false;\n    if (vb.ValueLen != 0)\n      return false;\n    const UInt32 endPos = pos + vb.TotalLen;\n    pos += k_ResoureBlockHeader_Size;\n    \n    f.AddSpaces(2);\n    f.AddString(\"BLOCK\");\n    AddParamString(f, p + pos, vb.StrSize);\n    \n    f.NewLine();\n    f.OpenBlock(2);\n    \n    if (CompareWStrStrings(p + pos, \"VarFileInfo\"))\n    {\n      pos += vb.StrSize + 2;\n      for (;;)\n      {\n        pos += (4 - pos) & 3;\n        if (pos >= endPos)\n          break;\n        CVersionBlock vb2;\n        if (!vb2.Parse(p + pos, endPos - pos))\n          return false;\n        const UInt32 endPos2 = pos + vb2.TotalLen;\n        if (vb2.IsTextValue)\n          return false;\n        pos += k_ResoureBlockHeader_Size;\n        f.AddSpaces(4);\n        f.AddString(\"VALUE\");\n        AddParamString(f, p + pos, vb2.StrSize);\n        if (!CompareWStrStrings(p + pos, \"Translation\"))\n          return false;\n        pos += vb2.StrSize + 2;\n        pos += (4 - pos) & 3;\n        if (pos + vb2.ValueLen != endPos2)\n          return false;\n        if ((vb2.ValueLen & 3) != 0)\n          return false;\n        UInt32 num = (vb2.ValueLen >> 2);\n        for (; num != 0; num--, pos += 4)\n        {\n          const UInt32 dw = Get32(p + pos);\n          const UInt32 lang = LOWORD(dw);\n          const UInt32 codePage = HIWORD(dw);\n\n          f.AddString(\", \");\n          PrintHex(f, lang);\n          f.AddString(\", \");\n          PrintUInt32(f, codePage);\n        }\n        f.NewLine();\n      }\n    }\n    else\n    {\n      if (!CompareWStrStrings(p + pos, \"StringFileInfo\"))\n        return false;\n      pos += vb.StrSize + 2;\n      for (;;)\n      {\n        pos += (4 - pos) & 3;\n        if (pos >= endPos)\n          break;\n        CVersionBlock vb2;\n        if (!vb2.Parse(p + pos, endPos - pos))\n          return false;\n        const UInt32 endPos2 = pos + vb2.TotalLen;\n        if (vb2.ValueLen != 0)\n          return false;\n        pos += k_ResoureBlockHeader_Size;\n\n        f.AddSpaces(4);\n        f.AddString(\"BLOCK\");\n        AddParamString(f, p + pos, vb2.StrSize);\n        pos += vb2.StrSize + 2;\n\n        f.NewLine();\n        f.OpenBlock(4);\n\n        for (;;)\n        {\n          pos += (4 - pos) & 3;\n          if (pos >= endPos2)\n            break;\n\n          CVersionBlock vb3;\n          if (!vb3.Parse(p + pos, endPos2 - pos))\n            return false;\n          // ValueLen is a number of 16-bit characters (usually it includes zero tail character).\n          const UInt32 endPos3 = pos + vb3.TotalLen;\n          pos += k_ResoureBlockHeader_Size;\n\n          // we don't write string if it's not text\n          if (vb3.IsTextValue)\n          {\n            f.AddSpaces(6);\n            f.AddString(\"VALUE\");\n            AddParamString(f, p + pos, vb3.StrSize);\n            UString key;\n            UString value;\n            CopyToUString(p + pos, key);\n            pos += vb3.StrSize + 2;\n\n            pos += (4 - pos) & 3;\n            if (vb3.ValueLen != 0 && pos /* + 2 */ <= endPos3)\n            {\n              f.AddChar(',');\n              f.AddSpaces((34 - (int)vb3.StrSize) / 2);\n              // vb3.TotalLen for some PE files (not from msvc) doesn't include tail zero at the end of Value string.\n              // we allow that minor error.\n              const int sLen = Get_Utf16Str_Len_InBytes_AllowNonZeroTail(p + pos, endPos3 - pos);\n              if (sLen < 0)\n                return false;\n              /*\n              if (vb3.ValueLen - 1 != (unsigned)sLen / 2 &&\n                  vb3.ValueLen     != (unsigned)sLen / 2)\n                return false;\n              */\n              AddParamString(f, p + pos, (unsigned)sLen);\n              CopyToUString_ByLen16(p + pos, (unsigned)sLen / 2, value);\n              // pos += (unsigned)sLen + 2;\n            }\n            AddToUniqueUStringVector(keys, key, value);\n          }\n          pos = endPos3;\n          f.NewLine();\n        }\n        pos = endPos2;\n        f.CloseBlock(4);\n      }\n    }\n    f.CloseBlock(2);\n    pos = endPos;\n  }\n\n  f.CloseBlock(0);\n  return true;\n}\n\n\nHRESULT CHandler::OpenResources(unsigned sectionIndex, IInStream *stream, IArchiveOpenCallback *callback)\n{\n  const CSection &sect = _sections[sectionIndex];\n  size_t fileSize = sect.PSize;\n  {\n    size_t fileSizeMin = sect.PSize;\n    \n    if (sect.VSize < sect.PSize)\n    {\n      fileSize = fileSizeMin = sect.VSize;\n      const int numBits = _optHeader.GetNumFileAlignBits();\n      if (numBits > 0)\n      {\n        const UInt32 mask = ((UInt32)1 << numBits) - 1;\n        const size_t end = (size_t)((sect.VSize + mask) & (UInt32)~mask);\n        if (end > sect.VSize)\n        {\n          if (end <= sect.PSize)\n            fileSize = end;\n          else\n            fileSize = sect.PSize;\n        }\n      }\n    }\n\n    if (fileSize > kFileSizeMax)\n      return S_FALSE;\n\n    {\n      const UInt64 fileSize64 = fileSize;\n      if (callback)\n        RINOK(callback->SetTotal(NULL, &fileSize64))\n    }\n    \n    RINOK(InStream_SeekSet(stream, sect.Pa))\n    \n    _buf.Alloc(fileSize);\n    \n    size_t pos;\n    \n    for (pos = 0; pos < fileSize;)\n    {\n      {\n        const UInt64 offset64 = pos;\n        if (callback)\n          RINOK(callback->SetCompleted(NULL, &offset64))\n      }\n      size_t rem = MyMin(fileSize - pos, (size_t)(1 << 22));\n      RINOK(ReadStream(stream, _buf + pos, &rem))\n      if (rem == 0)\n      {\n        if (pos < fileSizeMin)\n          return S_FALSE;\n        break;\n      }\n      pos += rem;\n    }\n    \n    if (pos < fileSize)\n      memset(_buf + pos, 0, fileSize - pos);\n  }\n  \n  _usedRes.Alloc(fileSize);\n  CRecordVector<CTableItem> specItems;\n  RINOK(ReadTable(0, specItems))\n\n  _oneLang = true;\n  bool stringsOk = true;\n  size_t maxOffset = 0;\n  \n  FOR_VECTOR (i, specItems)\n  {\n    const CTableItem &item1 = specItems[i];\n    if ((item1.Offset & kFlag) == 0)\n      return S_FALSE;\n\n    CRecordVector<CTableItem> specItems2;\n    RINOK(ReadTable(item1.Offset & kMask, specItems2))\n\n    FOR_VECTOR (j, specItems2)\n    {\n      const CTableItem &item2 = specItems2[j];\n      if ((item2.Offset & kFlag) == 0)\n        return S_FALSE;\n      \n      CRecordVector<CTableItem> specItems3;\n      RINOK(ReadTable(item2.Offset & kMask, specItems3))\n      \n      CResItem item;\n      item.Type = item1.ID;\n      item.ID = item2.ID;\n      \n      FOR_VECTOR (k, specItems3)\n      {\n        if (_items.Size() >= kNumResItemsMax)\n          return S_FALSE;\n        const CTableItem &item3 = specItems3[k];\n        if ((item3.Offset & kFlag) != 0)\n          return S_FALSE;\n        if (item3.Offset >= _buf.Size() || _buf.Size() - item3.Offset < 16)\n          return S_FALSE;\n        const Byte *buf = _buf + item3.Offset;\n        item.Lang = item3.ID;\n        item.Offset = Get32(buf + 0);\n        item.Size = Get32(buf + 4);\n        // UInt32 codePage = Get32(buf + 8);\n        if (Get32(buf + 12) != 0)\n          return S_FALSE;\n        if (!_items.IsEmpty() && _oneLang && !item.IsNameEqual(_items.Back()))\n          _oneLang = false;\n\n        item.HeaderSize = 0;\n      \n        size_t offset = item.Offset - sect.Va;\n        if (offset > maxOffset)\n          maxOffset = offset;\n        if (offset + item.Size > maxOffset)\n          maxOffset = offset + item.Size;\n\n        if (CheckItem(sect, item, offset))\n        {\n          const Byte *data = _buf + offset;\n          if (item.IsBmp())\n            item.HeaderSize = SetBitmapHeader(item.Header, data, item.Size);\n          else if (item.IsIcon())\n            item.HeaderSize = SetIconHeader(item.Header, data, item.Size);\n          else if (item.IsString())\n          {\n            if (stringsOk)\n              stringsOk = ParseStringRes(item.ID, item.Lang, data, item.Size);\n          }\n        }\n\n        if (item.IsVersion())\n        {\n          if (offset > _buf.Size() || _buf.Size() - offset < item.Size)\n            continue;\n          CTextFile f;\n          if (ParseVersion((const Byte *)_buf + offset, item.Size, f, _versionKeys))\n          {\n            CMixItem mixItem;\n            mixItem.VersionIndex = (int)_versionFiles.Size();\n            mixItem.SectionIndex = (int)sectionIndex; // check it !!!!\n            CByteBuffer_WithLang &vf = _versionFiles.AddNew();\n            vf.Lang = item.Lang;\n            vf.CopyFrom(f.Buf, f.Buf.GetPos());\n            _mixItems.Add(mixItem);\n            continue;\n          }\n          // PrintError(\"ver.Parse error\");\n        }\n  \n        item.Enabled = true;\n        _items.Add(item);\n      }\n    }\n  }\n  \n  if (stringsOk && !_strings.IsEmpty())\n  {\n    unsigned i;\n    for (i = 0; i < _items.Size(); i++)\n    {\n      CResItem &item = _items[i];\n      if (item.IsString())\n        item.Enabled = false;\n    }\n    for (i = 0; i < _strings.Size(); i++)\n    {\n      if (_strings[i].FinalSize() == 0)\n        continue;\n      CMixItem mixItem;\n      mixItem.StringIndex = (int)i;\n      mixItem.SectionIndex = (int)sectionIndex;\n      _mixItems.Add(mixItem);\n    }\n  }\n\n  _usedRes.Free();\n\n  {\n    // PSize can be much larger than VSize in some exe installers.\n    // it contains archive data after PE resources.\n    // So we need to use PSize here!\n    if (maxOffset < sect.PSize)\n    {\n      size_t end = fileSize;\n\n      // we skip Zeros to start of aligned block\n      size_t i;\n      for (i = maxOffset; i < end; i++)\n        if (_buf[i] != 0)\n          break;\n      if (i == end)\n        maxOffset = end;\n      \n      CSection sect2;\n      sect2.Flags = 0;\n      sect2.Pa = sect.Pa + (UInt32)maxOffset;\n      sect2.Va = sect.Va + (UInt32)maxOffset;\n\n      // 9.29: we use sect.PSize instead of sect.VSize to support some CAB-SFX\n      // the code for .rsrc_2 is commented.\n      sect2.PSize = sect.PSize - (UInt32)maxOffset;\n\n      if (sect2.PSize != 0)\n      {\n        sect2.ExtractSize = sect2.VSize = sect2.PSize;\n        sect2.Name = \".rsrc_1\";\n        sect2.Time = 0;\n        sect2.IsAdditionalSection = true;\n        _sections.Add(sect2);\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\nbool CHeader::ParseCoff(const Byte *p)\n{\n  ParseBase(p);\n  if (PointerToSymbolTable < kCoffHeaderSize)\n    return false;\n  if (NumSymbols >= (1 << 24))\n    return false;\n  if (OptHeaderSize != 0 && OptHeaderSize < k_OptHeader32_Size_MIN)\n    return false;\n\n  // 18.04: we reduce false detections\n  if (NumSections == 0 && OptHeaderSize == 0)\n    return false;\n\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_MachinePairs); i++)\n    if (Machine == g_MachinePairs[i].Value)\n      return true;\n  if (Machine == 0)\n    return true;\n\n  return false;\n}\n\n\nstatic inline bool CheckPeOffset(UInt32 pe)\n{\n  // ((pe & 7) == 0) is for most PE files. But there is unusual EFI-PE file that uses unaligned pe value.\n  return pe >= 0x40 && pe <= 0x1000 /* && (pe & 7) == 0 */ ;\n}\n\nstatic const unsigned kStartSize = 0x40;\n\nAPI_FUNC_static_IsArc IsArc_Pe(const Byte *p, size_t size)\n{\n  if (size < 2)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != 'M' || p[1] != 'Z')\n    return k_IsArc_Res_NO;\n  if (size < kStartSize)\n    return k_IsArc_Res_NEED_MORE;\n  UInt32 pe = Get32(p + 0x3C);\n  if (!CheckPeOffset(pe))\n    return k_IsArc_Res_NO;\n  if (pe + kPeHeaderSize > size)\n    return k_IsArc_Res_NEED_MORE;\n  CHeader header;\n  if (!header.ParsePe(p + pe))\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)\n{\n  UInt32 coffOffset = 0;\n  if (_coffMode)\n  {\n    Byte h[kCoffHeaderSize];\n    RINOK(ReadStream_FALSE(stream, h, kCoffHeaderSize))\n    if (!_header.ParseCoff(h))\n      return S_FALSE;\n  }\n  else\n  {\n    UInt32 _peOffset;\n    {\n      Byte h[kStartSize];\n      RINOK(ReadStream_FALSE(stream, h, kStartSize))\n      if (h[0] != 'M' || h[1] != 'Z')\n        return S_FALSE;\n        /* most of PE files contain 0x0090 at offset 2.\n        But some rare PE files contain another values. So we don't use that check.\n      if (Get16(h + 2) != 0x90) return false; */\n      _peOffset = Get32(h + 0x3C);\n      if (!CheckPeOffset(_peOffset))\n        return S_FALSE;\n      coffOffset = _peOffset + 4;\n    }\n    {\n      Byte h[kPeHeaderSize];\n      RINOK(InStream_SeekSet(stream, _peOffset))\n      RINOK(ReadStream_FALSE(stream, h, kPeHeaderSize))\n      if (!_header.ParsePe(h))\n        return S_FALSE;\n    }\n  }\n\n  const UInt32 optStart = coffOffset + kCoffHeaderSize;\n  const UInt32 bufSize = _header.OptHeaderSize + (UInt32)_header.NumSections * kSectionSize;\n  _totalSize = optStart + bufSize;\n  CByteBuffer buffer(bufSize);\n\n  RINOK(ReadStream_FALSE(stream, buffer, bufSize))\n  \n  // memset((void *)&_optHeader, 0, sizeof(_optHeader));\n  if (_header.OptHeaderSize != 0)\n  if (!_optHeader.Parse(buffer, _header.OptHeaderSize))\n    return S_FALSE;\n\n  UInt32 pos = _header.OptHeaderSize;\n  unsigned i;\n  for (i = 0; i < _header.NumSections; i++, pos += kSectionSize)\n  {\n    CSection &sect = _sections.AddNew();\n    sect.Parse(buffer + pos);\n    sect.IsRealSect = true;\n    if (sect.Name.IsEqualTo(\".reloc\"))\n    {\n      const CDirLink &dl = _optHeader.DirItems[kDirLink_BASERELOC];\n      if (dl.Va == sect.Va &&\n          dl.Size <= sect.PSize)\n        sect.ExtractSize = dl.Size;\n    }\n    else if (sect.Name.IsEqualTo(\".pdata\"))\n    {\n      const CDirLink &dl = _optHeader.DirItems[kDirLink_EXCEPTION];\n      if (dl.Va == sect.Va &&\n          dl.Size <= sect.PSize)\n        sect.ExtractSize = dl.Size;\n    }\n    \n    /* PE pre-file in .hxs file has errors:\n         PSize of resource is larger than real size.\n         So it overlaps next \".its\" section.\n       7-zip before 22.02: we corrected it.\n\n       22.02: another bad case is possible in incorrect pe (exe) file:\n         PSize in .rsrc section is correct,\n         but next .reloc section has incorrect (Pa) that overlaps with .rsrc.\n    */\n\n    if (i != 0)\n    {\n      const CSection &prev = _sections[i - 1];\n      if (prev.Pa < sect.Pa\n          && prev.Pa + prev.PSize > sect.Pa\n          && sect.PSize != 0\n          && prev.PSize != 0)\n      {\n        _sectionsError = true;\n        // PRF(printf(\"\\n !!!! Section correction: %s\\n \", prev.Name));\n\n        /* we corrected that case in 7-zip before 22.02: */\n        // prev.PSize = sect.Pa - prev.Pa;\n\n        /* 22.02: here we can try to change bad section position to expected postion.\n           but original Windows code probably will not do same things. */\n        // if (prev.PSize <= sect.Va - prev.Va) sect.Pa = prev.Pa + prev.PSize;\n      }\n    }\n    /* last \".its\" section in hxs file has incorrect sect.PSize.\n       7-zip before 22.02: we reduced section to real sect.VSize */\n    /*\n    if (sect.VSize == 24 && sect.PSize == 512 && i == (unsigned)_header.NumSections - 1)\n      sect.PSize = sect.VSize;\n    */\n  }\n\n  for (i = 0; i < _sections.Size(); i++)\n    _sections[i].UpdateTotalSize(_totalSize);\n\n  bool thereISDebug = false;\n  if (IsOpt())\n  {\n  RINOK(LoadDebugSections(stream, thereISDebug))\n\n  const CDirLink &certLink = _optHeader.DirItems[kDirLink_Certificate];\n  if (certLink.Size != 0)\n  {\n    CSection &sect = _sections.AddNew();\n    sect.Name = \"CERTIFICATE\";\n    sect.Va = 0;\n    sect.Pa = certLink.Va;\n    sect.Set_Size_for_all(certLink.Size);\n    sect.UpdateTotalSize(_totalSize);\n  }\n\n  if (thereISDebug)\n  {\n    /* sometime there is some data after debug section.\n       We don't see any reference in exe file to that data.\n       But we suppose that it's part of EXE file */\n\n    const UInt32 kAlign = 1 << 12;\n    UInt32 alignPos = _totalSize & (kAlign - 1);\n    if (alignPos != 0)\n    {\n      UInt32 size = kAlign - alignPos;\n      RINOK(InStream_SeekSet(stream, _totalSize))\n      buffer.Alloc(kAlign);\n      Byte *buf = buffer;\n      size_t processed = size;\n      RINOK(ReadStream(stream, buf, &processed))\n\n      /*\n      if (processed != 0)\n      {\n        printf(\"\\ndata after debug %d, %d \\n\", (int)size, (int)processed);\n        fflush(stdout);\n      }\n      */\n\n      size_t k;\n      for (k = 0; k < processed; k++)\n        if (buf[k] != 0)\n          break;\n      if (processed < size && processed < 100)\n        _totalSize += (UInt32)processed;\n      else if (((_totalSize + k) & 0x1FF) == 0 || processed < size)\n        _totalSize += (UInt32)k;\n    }\n  }\n  }\n\n  if (_header.NumSymbols > 0 && _header.PointerToSymbolTable >= optStart)\n  {\n    if (_header.NumSymbols >= (1 << 24))\n      return S_FALSE;\n    UInt32 size = _header.NumSymbols * 18;\n    RINOK(InStream_SeekSet(stream, (UInt64)_header.PointerToSymbolTable + size))\n    Byte buf[4];\n    RINOK(ReadStream_FALSE(stream, buf, 4))\n    UInt32 size2 = Get32(buf);\n    if (size2 >= (1 << 28))\n      return S_FALSE;\n    size += size2;\n\n    CSection &sect = _sections.AddNew();\n    sect.Name = \"COFF_SYMBOLS\";\n    sect.Va = 0;\n    sect.Pa = _header.PointerToSymbolTable;\n    sect.Set_Size_for_all(size);\n    sect.UpdateTotalSize(_totalSize);\n  }\n\n  {\n    CObjectVector<CSection> sections = _sections;\n    sections.Sort();\n    UInt32 limit = (1 << 12);\n    unsigned num = 0;\n    FOR_VECTOR (k, sections)\n    {\n      const CSection &s = sections[k];\n      if (s.Pa > limit)\n      {\n        CSection &s2 = _sections.AddNew();\n        s2.Pa = s2.Va = limit;\n        s2.Set_Size_for_all(s.Pa - limit);\n        s2.IsAdditionalSection = true;\n        s2.Name.Add_Char('[');\n        s2.Name.Add_UInt32(num++);\n        s2.Name.Add_Char(']');\n        limit = s.Pa;\n      }\n      UInt32 next = s.Pa + s.PSize;\n      if (next < s.Pa)\n        break;\n      if (next >= limit)\n        limit = next;\n    }\n  }\n\n\n  if (IsOpt())\n  if (_optHeader.CheckSum != 0)\n  {\n    RINOK(InStream_SeekToBegin(stream))\n    UInt32 checkSum = 0;\n    RINOK(CalcCheckSum(stream, _totalSize, optStart + k_CheckSum_Field_Offset, checkSum))\n    _checksumError = (checkSum != _optHeader.CheckSum);\n  }\n\n\n  if (!_allowTail)\n  {\n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))\n    if (fileSize > _totalSize)\n      return S_FALSE;\n  }\n\n  bool _parseResources = true;\n  // _parseResources = false; // for debug\n\n  UInt64 mainSize = 0, mainSize2 = 0;\n\n  for (i = 0; i < _sections.Size(); i++)\n  {\n    const CSection &sect = _sections[i];\n    if (IsOpt())\n    if (_parseResources && sect.Name.IsEqualTo(\".rsrc\"))\n    {\n      // 20.01: we try to parse only first copy of .rsrc section.\n      _parseResources = false;\n      const unsigned numMixItems = _mixItems.Size();\n      HRESULT res = OpenResources(i, stream, callback);\n      if (res == S_OK)\n      {\n        _resourcesPrefix = sect.Name.Ptr();\n        _resourcesPrefix.Add_PathSepar();\n        FOR_VECTOR (j, _items)\n        {\n          const CResItem &item = _items[j];\n          if (item.Enabled)\n          {\n            CMixItem mixItem;\n            mixItem.SectionIndex = (int)i;\n            mixItem.ResourceIndex = (int)j;\n            if (item.IsRcDataOrUnknown())\n            {\n              if (item.Size >= mainSize)\n              {\n                mainSize2 = mainSize;\n                mainSize = item.Size;\n                _mainSubfile = (Int32)(int)_mixItems.Size();\n              }\n              else if (item.Size >= mainSize2)\n                mainSize2 = item.Size;\n            }\n            _mixItems.Add(mixItem);\n          }\n        }\n        // 9.29: .rsrc_2 code was commented.\n        // .rsrc_1 now must include that .rsrc_2 block.\n        /*\n        if (sect.PSize > sect.VSize)\n        {\n          int numBits = _optHeader.GetNumFileAlignBits();\n          if (numBits >= 0)\n          {\n            UInt32 mask = (1 << numBits) - 1;\n            UInt32 end = ((sect.VSize + mask) & ~mask);\n\n            if (sect.PSize > end)\n            {\n              CSection &sect2 = _sections.AddNew();\n              sect2.Flags = 0;\n              sect2.Pa = sect.Pa + end;\n              sect2.Va = sect.Va + end;\n              sect2.PSize = sect.PSize - end;\n              sect2.VSize = sect2.PSize;\n              sect2.Name = \".rsrc_2\";\n              sect2.Time = 0;\n              sect2.IsAdditionalSection = true;\n            }\n          }\n        }\n        */\n        continue;\n      }\n      if (res != S_FALSE)\n        return res;\n      _mixItems.DeleteFrom(numMixItems);\n      CloseResources();\n    }\n\n    if (sect.IsAdditionalSection)\n    {\n      if (sect.PSize >= mainSize)\n      {\n        mainSize2 = mainSize;\n        mainSize = sect.PSize;\n        _mainSubfile = (Int32)(int)_mixItems.Size();\n      }\n      else if (sect.PSize >= mainSize2)\n        mainSize2 = sect.PSize;\n    }\n    \n    CMixItem mixItem;\n    mixItem.SectionIndex = (int)i;\n    _mixItems.Add(mixItem);\n  }\n  \n  if (mainSize2 >= (1 << 20) && mainSize < mainSize2 * 2)\n    _mainSubfile = -1;\n\n  for (i = 0; i < _mixItems.Size(); i++)\n  {\n    const CMixItem &mixItem = _mixItems[i];\n    if (mixItem.StringIndex < 0 && mixItem.ResourceIndex < 0 && _sections[mixItem.SectionIndex].Name.IsEqualTo(\"_winzip_\"))\n    {\n      _mainSubfile = (Int32)(int)i;\n      break;\n    }\n  }\n\n  for (i = 0; i < _versionKeys.Size(); i++)\n  {\n    if (i != 0)\n      _versionFullString.Add_LF();\n    const CStringKeyValue &k = _versionKeys[i];\n    _versionFullString += k.Key;\n    _versionFullString += \": \";\n    _versionFullString += k.Value;\n  }\n\n  {\n    int keyIndex = FindKey(_versionKeys, \"OriginalFilename\");\n    if (keyIndex >= 0)\n      _originalFilename = _versionKeys[keyIndex].Value;\n  }\n  {\n    int keyIndex = FindKey(_versionKeys, \"FileDescription\");\n    if (keyIndex >= 0)\n      _versionShortString = _versionKeys[keyIndex].Value;\n  }\n  {\n    int keyIndex = FindKey(_versionKeys, \"FileVersion\");\n    if (keyIndex >= 0)\n    {\n      _versionShortString.Add_Space();\n      _versionShortString += _versionKeys[keyIndex].Value;\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  Close();\n  RINOK(Open2(inStream, callback))\n  _stream = inStream;\n  return S_OK;\n  COM_TRY_END\n}\n\nvoid CHandler::CloseResources()\n{\n  _usedRes.Free();\n  _items.Clear();\n  _strings.Clear();\n  _versionFiles.Clear();\n  _buf.Free();\n  _versionFullString.Empty();\n  _versionShortString.Empty();\n  _originalFilename.Empty();\n  _versionKeys.Clear();\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalSize = 0;\n  _checksumError = false;\n  _sectionsError = false;\n  _mainSubfile = -1;\n\n  _stream.Release();\n  _sections.Clear();\n  _mixItems.Clear();\n  CloseResources();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _mixItems.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _mixItems.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const CMixItem &mixItem = _mixItems[allFilesMode ? i : indices[i]];\n    UInt64 size;\n    if (mixItem.StringIndex >= 0)\n      size = _strings[mixItem.StringIndex].FinalSize();\n    else if (mixItem.VersionIndex >= 0)\n      size = _versionFiles[mixItem.VersionIndex].Size();\n    else if (mixItem.ResourceIndex >= 0)\n      size = _items[mixItem.ResourceIndex].GetSize();\n    else\n      size = _sections[mixItem.SectionIndex].GetSize_Extract();\n    totalSize += size;\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_stream);\n\n  totalSize = 0;\n  UInt64 currentItemSize;\n  \n  for (i = 0;; i++, totalSize += currentItemSize)\n  {\n    lps->InSize = lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n\n    CMyComPtr<ISequentialOutStream> outStream;\n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n    const CMixItem &mixItem = _mixItems[index];\n\n    const CSection &sect = _sections[mixItem.SectionIndex];\n    bool isOk = true;\n    if (mixItem.StringIndex >= 0)\n    {\n      const CStringItem &item = _strings[mixItem.StringIndex];\n      currentItemSize = item.FinalSize();\n      if (!testMode && !outStream)\n        continue;\n\n      RINOK(extractCallback->PrepareOperation(askMode))\n      if (outStream)\n        RINOK(WriteStream(outStream, item.Buf, item.FinalSize()))\n    }\n    else if (mixItem.VersionIndex >= 0)\n    {\n      const CByteBuffer &item = _versionFiles[mixItem.VersionIndex];\n      currentItemSize = item.Size();\n      if (!testMode && !outStream)\n        continue;\n\n      RINOK(extractCallback->PrepareOperation(askMode))\n      if (outStream)\n        RINOK(WriteStream(outStream, item, item.Size()))\n    }\n    else if (mixItem.ResourceIndex >= 0)\n    {\n      const CResItem &item = _items[mixItem.ResourceIndex];\n      currentItemSize = item.GetSize();\n      if (!testMode && !outStream)\n        continue;\n\n      RINOK(extractCallback->PrepareOperation(askMode))\n      size_t offset = item.Offset - sect.Va;\n      if (!CheckItem(sect, item, offset))\n        isOk = false;\n      else if (outStream)\n      {\n        if (item.HeaderSize != 0)\n          RINOK(WriteStream(outStream, item.Header, item.HeaderSize))\n        RINOK(WriteStream(outStream, _buf + offset, item.Size))\n      }\n    }\n    else\n    {\n      currentItemSize = sect.GetSize_Extract();\n      if (!testMode && !outStream)\n        continue;\n      \n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(InStream_SeekSet(_stream, sect.Pa))\n      inStream->Init(currentItemSize);\n      RINOK(copyCoder.Interface()->Code(inStream, outStream, NULL, NULL, lps))\n      isOk = (copyCoder->TotalSize == currentItemSize);\n    }\n    \n    outStream.Release();\n    RINOK(extractCallback->SetOperationResult(isOk ?\n        NExtract::NOperationResult::kOK :\n        NExtract::NOperationResult::kDataError))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n\n  const CMixItem &mixItem = _mixItems[index];\n  const CSection &sect = _sections[mixItem.SectionIndex];\n  if (mixItem.IsSectionItem())\n    return CreateLimitedInStream(_stream, sect.Pa, sect.GetSize_Extract(), stream);\n\n  CBufInStream *inStreamSpec = new CBufInStream;\n  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;\n  CReferenceBuf *referenceBuf = new CReferenceBuf;\n  CMyComPtr<IUnknown> ref = referenceBuf;\n  if (mixItem.StringIndex >= 0)\n  {\n    const CStringItem &item = _strings[mixItem.StringIndex];\n    referenceBuf->Buf.CopyFrom(item.Buf, item.FinalSize());\n  }\n  else if (mixItem.VersionIndex >= 0)\n  {\n    const CByteBuffer &item = _versionFiles[mixItem.VersionIndex];\n    referenceBuf->Buf.CopyFrom(item, item.Size());\n  }\n  else\n  {\n    const CResItem &item = _items[mixItem.ResourceIndex];\n    size_t offset = item.Offset - sect.Va;\n    if (!CheckItem(sect, item, offset))\n      return S_FALSE;\n    if (item.HeaderSize == 0)\n    {\n      CBufInStream *streamSpec = new CBufInStream;\n      CMyComPtr<IInStream> streamTemp2 = streamSpec;\n      streamSpec->Init(_buf + offset, item.Size, (IInArchive *)this);\n      *stream = streamTemp2.Detach();\n      return S_OK;\n    }\n    referenceBuf->Buf.Alloc(item.HeaderSize + item.Size);\n    memcpy(referenceBuf->Buf, item.Header, item.HeaderSize);\n    if (item.Size != 0)\n      memcpy(referenceBuf->Buf + item.HeaderSize, _buf + offset, item.Size);\n  }\n  inStreamSpec->Init(referenceBuf);\n\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail))\n{\n  _allowTail = IntToBool(allowTail);\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = { 'M', 'Z' };\n\nREGISTER_ARC_I(\n  \"PE\", \"exe dll sys\", NULL, 0xDD,\n  k_Signature,\n  0,\n  NArcInfoFlags::kPreArc,\n  IsArc_Pe)\n\n}\n\nnamespace NCoff {\n\nAPI_FUNC_static_IsArc IsArc_Coff(const Byte *p, size_t size)\n{\n  if (size < NPe::kCoffHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  NPe::CHeader header;\n  if (!header.ParseCoff(p))\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\n/*\nstatic const Byte k_Signature[] =\n{\n    2, 0x4C, 0x01, // x86\n    2, 0x64, 0x86, // x64\n    2, 0x64, 0xAA  // ARM64\n};\nREGISTER_ARC_I_CLS(\n*/\n\nREGISTER_ARC_I_CLS_NO_SIG(\n  NPe::CHandler(true),\n  \"COFF\", \"obj\", NULL, 0xC6,\n  // k_Signature,\n  0,\n  // NArcInfoFlags::kMultiSignature |\n  NArcInfoFlags::kStartOpen,\n  IsArc_Coff)\n}\n\n\nnamespace NTe {\n\n// Terse Executable (TE) image\n\nstruct CDataDir\n{\n  UInt32 Va;\n  UInt32 Size;\n\n  void Parse(const Byte *p)\n  {\n    G32(0, Va);\n    G32(4, Size);\n  }\n};\n\nstatic const UInt32 kHeaderSize = 40;\n\nstatic bool FindValue(const CUInt32PCharPair *pairs, unsigned num, UInt32 value)\n{\n  for (unsigned i = 0; i < num; i++)\n    if (pairs[i].Value == value)\n      return true;\n  return false;\n}\n\n#define MY_FIND_VALUE(pairs, val) FindValue(pairs, Z7_ARRAY_SIZE(pairs), val)\n#define MY_FIND_VALUE_2(strings, val) (val < Z7_ARRAY_SIZE(strings) && strings[val])\n \nstatic const UInt32 kNumSection_MAX = 32;\n\nstruct CHeader\n{\n  UInt16 Machine;\n  Byte NumSections;\n  Byte SubSystem;\n  UInt16 StrippedSize;\n  /*\n  UInt32 AddressOfEntryPoint;\n  UInt32 BaseOfCode;\n  UInt64 ImageBase;\n  */\n  CDataDir DataDir[2]; // base relocation and debug directory\n\n  bool ConvertPa(UInt32 &pa) const\n  {\n    if (pa < StrippedSize)\n      return false;\n    pa = pa - StrippedSize + kHeaderSize;\n    return true;\n  }\n  bool Parse(const Byte *p);\n};\n\nbool CHeader::Parse(const Byte *p)\n{\n  NumSections = p[4];\n  if (NumSections > kNumSection_MAX)\n    return false;\n  SubSystem = p[5];\n  G16(2, Machine);\n  G16(6, StrippedSize);\n  /*\n  G32(8, AddressOfEntryPoint);\n  G32(12, BaseOfCode);\n  G64(16, ImageBase);\n  */\n  for (unsigned i = 0; i < 2; i++)\n  {\n    CDataDir &dd = DataDir[i];\n    dd.Parse(p + 24 + i * 8);\n    if (dd.Size >= ((UInt32)1 << 28))\n      return false;\n  }\n  return\n      MY_FIND_VALUE(NPe::g_MachinePairs, Machine) &&\n      MY_FIND_VALUE_2(NPe::g_SubSystems, SubSystem);\n}\n\nAPI_FUNC_static_IsArc IsArc_Te(const Byte *p, size_t size)\n{\n  if (size < 2)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != 'V' || p[1] != 'Z')\n    return k_IsArc_Res_NO;\n  if (size < kHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  \n  CHeader h;\n  if (!h.Parse(p))\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\n\nstruct CSection\n{\n  Byte Name[NPe::kNameSize];\n\n  UInt32 ExtractSize;\n  UInt32 VSize;\n  UInt32 Va;\n  UInt32 PSize;\n  UInt32 Pa;\n  UInt32 Flags;\n  // UInt16 NumRelocs;\n\n  void Parse(const Byte *p)\n  {\n    memcpy(Name, p, NPe::kNameSize);\n    G32(8, VSize);\n    G32(12, Va);\n    G32(16, PSize);\n    G32(20, Pa);\n    // G32(p + 32, NumRelocs);\n    G32(36, Flags);\n    ExtractSize = (VSize && VSize < PSize) ? VSize : PSize;\n  }\n\n  bool Check() const\n  {\n    return\n        Pa <= ((UInt32)1 << 30) &&\n        PSize <= ((UInt32)1 << 30);\n  }\n\n  UInt32 GetSize_Extract() const\n  {\n    return ExtractSize;\n  }\n\n  void UpdateTotalSize(UInt32 &totalSize)\n  {\n    const UInt32 t = Pa + PSize;\n    if (totalSize < t)\n        totalSize = t;\n  }\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_2(\n  IInArchiveGetStream,\n  IArchiveAllowTail\n)\n  CRecordVector<CSection> _items;\n  CMyComPtr<IInStream> _stream;\n  UInt32 _totalSize;\n  bool _allowTail;\n  CHeader _h;\n  \n  HRESULT Open2(IInStream *stream);\npublic:\n  CHandler(): _allowTail(false) {}\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidVirtualSize,\n  kpidCharacts,\n  kpidOffset,\n  kpidVa\n};\n\nenum\n{\n  kpidSubSystem = kpidUserDefined\n  // , kpidImageBase\n};\n\nstatic const CStatProp kArcProps[] =\n{\n  // { NULL, kpidHeadersSize, VT_UI4 },\n  { NULL, kpidCpu, VT_BSTR},\n  { \"Subsystem\", kpidSubSystem, VT_BSTR },\n  // { \"Image Base\", kpidImageBase, VT_UI8 }\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _totalSize; break;\n    case kpidCpu: PAIR_TO_PROP(NPe::g_MachinePairs, _h.Machine, prop); break;\n    case kpidSubSystem: TYPE_TO_PROP(NPe::g_SubSystems, _h.SubSystem, prop); break;\n    /*\n    case kpidImageBase: prop = _h.ImageBase; break;\n    case kpidAddressOfEntryPoint: prop = _h.AddressOfEntryPoint; break;\n    case kpidBaseOfCode: prop = _h.BaseOfCode; break;\n    */\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  {\n    const CSection &item = _items[index];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        AString name;\n        NPe::GetName(item.Name, name);\n        prop = MultiByteToUnicodeString(name);\n        break;\n      }\n      case kpidSize: prop = (UInt64)item.GetSize_Extract(); break;\n      case kpidPackSize: prop = (UInt64)item.PSize; break;\n      case kpidVirtualSize: prop = (UInt64)item.VSize; break;\n      case kpidOffset: prop = item.Pa; break;\n      case kpidVa: prop = item.Va; break;\n      case kpidCharacts: FLAGS_TO_PROP(NPe::g_SectFlags, item.Flags, prop); break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  Byte h[kHeaderSize];\n  RINOK(ReadStream_FALSE(stream, h, kHeaderSize))\n  if (h[0] != 'V' || h[1] != 'Z')\n    return S_FALSE;\n  if (!_h.Parse(h))\n    return S_FALSE;\n\n  UInt32 headerSize = NPe::kSectionSize * (UInt32)_h.NumSections;\n  CByteArr buf(headerSize);\n  RINOK(ReadStream_FALSE(stream, buf, headerSize))\n  headerSize += kHeaderSize;\n\n  _totalSize = headerSize;\n  _items.ClearAndReserve(_h.NumSections);\n  for (UInt32 i = 0; i < _h.NumSections; i++)\n  {\n    CSection sect;\n    sect.Parse(buf + i * NPe::kSectionSize);\n    if (!_h.ConvertPa(sect.Pa))\n      return S_FALSE;\n    if (sect.Pa < headerSize)\n      return S_FALSE;\n    if (!sect.Check())\n      return S_FALSE;\n    _items.AddInReserved(sect);\n    sect.UpdateTotalSize(_totalSize);\n  }\n\n  if (!_allowTail)\n  {\n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(stream, fileSize))\n    if (fileSize > _totalSize)\n      return S_FALSE;\n  }\n  \n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  Close();\n  // try\n  {\n    if (Open2(inStream) != S_OK)\n      return S_FALSE;\n    _stream = inStream;\n  }\n  // catch(...) { return S_FALSE; }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalSize = 0;\n  _stream.Release();\n  _items.Clear();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _items[allFilesMode ? i : indices[i]].GetSize_Extract();\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(_stream);\n\n  totalSize = 0;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    int opRes;\n    {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CSection &item = _items[index];\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n    const UInt32 size = item.GetSize_Extract();\n    totalSize += size;\n    \n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n    RINOK(InStream_SeekSet(_stream, item.Pa))\n    inStream->Init(size);\n    RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n\n      opRes = (copyCoder->TotalSize == size) ?\n          NExtract::NOperationResult::kOK : (copyCoder->TotalSize < size) ?\n          NExtract::NOperationResult::kUnexpectedEnd :\n          NExtract::NOperationResult::kDataError;\n    }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  const CSection &item = _items[index];\n  return CreateLimitedInStream(_stream, item.Pa, item.GetSize_Extract(), stream);\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::AllowTail(Int32 allowTail))\n{\n  _allowTail = IntToBool(allowTail);\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = { 'V', 'Z' };\n\nREGISTER_ARC_I(\n  \"TE\", \"te\", NULL, 0xCF,\n  k_Signature,\n  0,\n  NArcInfoFlags::kPreArc,\n  IsArc_Te)\n\n}\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/PpmdHandler.cpp",
    "content": "﻿/* PpmdHandler.cpp -- PPMd format handler\n2020 : Igor Pavlov : Public domain\nThis code is based on:\n  PPMd var.H (2001) / var.I (2002): Dmitry Shkarin : Public domain\n  Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/Ppmd7.h\"\n#include \"../../../C/Ppmd8.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/CWrappers.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NPpmd {\n\nstatic const UInt32 kBufSize = (1 << 20);\n\nstruct CBuf\n{\n  Byte *Buf;\n  \n  CBuf(): Buf(NULL) {}\n  ~CBuf() { ::MidFree(Buf); }\n  bool Alloc()\n  {\n    if (!Buf)\n      Buf = (Byte *)::MidAlloc(kBufSize);\n    return (Buf != NULL);\n  }\n};\n\nstatic const UInt32 kHeaderSize = 16;\nstatic const UInt32 kSignature = 0x84ACAF8F;\nstatic const unsigned kNewHeaderVer = 8;\n\nstruct CItem\n{\n  UInt32 Attrib;\n  UInt32 Time;\n  AString Name;\n  \n  unsigned Order;\n  unsigned MemInMB;\n  unsigned Ver;\n  unsigned Restor;\n\n  HRESULT ReadHeader(ISequentialInStream *s, UInt32 &headerSize);\n  bool IsSupported() const\n  {\n    return (Ver == 7 && Order >= PPMD7_MIN_ORDER)\n        || (Ver == 8 && Order >= PPMD8_MIN_ORDER && Restor < PPMD8_RESTORE_METHOD_UNSUPPPORTED);\n  }\n};\n\nHRESULT CItem::ReadHeader(ISequentialInStream *s, UInt32 &headerSize)\n{\n  Byte h[kHeaderSize];\n  RINOK(ReadStream_FALSE(s, h, kHeaderSize))\n  if (GetUi32(h) != kSignature)\n    return S_FALSE;\n  Attrib = GetUi32(h + 4);\n  Time = GetUi32(h + 12);\n  const unsigned info = GetUi16(h + 8);\n  Order = (info & 0xF) + 1;\n  MemInMB = ((info >> 4) & 0xFF) + 1;\n  Ver = info >> 12;\n\n  if (Ver < 6 || Ver > 11) return S_FALSE;\n \n  UInt32 nameLen = GetUi16(h + 10);\n  Restor = nameLen >> 14;\n  if (Restor > 2)\n    return S_FALSE;\n  if (Ver >= kNewHeaderVer)\n    nameLen &= 0x3FFF;\n  if (nameLen > (1 << 9))\n    return S_FALSE;\n  char *name = Name.GetBuf(nameLen);\n  const HRESULT res = ReadStream_FALSE(s, name, nameLen);\n  Name.ReleaseBuf_CalcLen(nameLen);\n  headerSize = kHeaderSize + nameLen;\n  return res;\n}\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IArchiveOpenSeq\n)\n  CItem _item;\n  UInt32 _headerSize;\n  bool _packSize_Defined;\n  UInt64 _packSize;\n  CMyComPtr<ISequentialInStream> _stream;\n\n  void GetVersion(NCOM::CPropVariant &prop);\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidMTime,\n  kpidAttrib,\n  kpidMethod\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidMethod\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nvoid CHandler::GetVersion(NCOM::CPropVariant &prop)\n{\n  AString s (\"PPMd\");\n  s.Add_Char((char)('A' + _item.Ver));\n  s += \":o\";\n  s.Add_UInt32(_item.Order);\n  s += \":mem\";\n  s.Add_UInt32(_item.MemInMB);\n  s.Add_Char('m');\n  if (_item.Ver >= kNewHeaderVer && _item.Restor != 0)\n  {\n    s += \":r\";\n    s.Add_UInt32(_item.Restor);\n  }\n  prop = s;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidMethod: GetVersion(prop); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPath: prop = MultiByteToUnicodeString(_item.Name, CP_ACP); break;\n    case kpidMTime:\n    {\n      // time can be in Unix format ???\n      FILETIME utc;\n      if (NTime::DosTime_To_FileTime(_item.Time, utc))\n        prop = utc;\n      break;\n    }\n    case kpidAttrib: prop = _item.Attrib; break;\n    case kpidPackSize: if (_packSize_Defined) prop = _packSize; break;\n    case kpidMethod: GetVersion(prop); break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  return OpenSeq(stream);\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  COM_TRY_BEGIN\n  HRESULT res;\n  try\n  {\n    Close();\n    res = _item.ReadHeader(stream, _headerSize);\n  }\n  catch(...) { res = S_FALSE; }\n  if (res == S_OK)\n    _stream = stream;\n  else\n    Close();\n  return res;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _packSize = 0;\n  _packSize_Defined = false;\n  _stream.Release();\n  return S_OK;\n}\n\n\n\nstruct CPpmdCpp\n{\n  unsigned Ver;\n  CPpmd7 _ppmd7;\n  CPpmd8 _ppmd8;\n  \n  CPpmdCpp(unsigned version)\n  {\n    Ver = version;\n    Ppmd7_Construct(&_ppmd7);\n    Ppmd8_Construct(&_ppmd8);\n  }\n\n  ~CPpmdCpp()\n  {\n    Ppmd7_Free(&_ppmd7, &g_BigAlloc);\n    Ppmd8_Free(&_ppmd8, &g_BigAlloc);\n  }\n\n  bool Alloc(UInt32 memInMB)\n  {\n    memInMB <<= 20;\n    if (Ver == 7)\n      return Ppmd7_Alloc(&_ppmd7, memInMB, &g_BigAlloc) != 0;\n    return Ppmd8_Alloc(&_ppmd8, memInMB, &g_BigAlloc) != 0;\n  }\n\n  void Init(unsigned order, unsigned restor)\n  {\n    if (Ver == 7)\n      Ppmd7_Init(&_ppmd7, order);\n    else\n      Ppmd8_Init(&_ppmd8, order, restor);\n  }\n    \n  bool InitRc(CByteInBufWrap *inStream)\n  {\n    if (Ver == 7)\n    {\n      _ppmd7.rc.dec.Stream = &inStream->vt;\n      return (Ppmd7a_RangeDec_Init(&_ppmd7.rc.dec) != 0);\n    }\n    else\n    {\n      _ppmd8.Stream.In = &inStream->vt;\n      return Ppmd8_Init_RangeDec(&_ppmd8) != 0;\n    }\n  }\n\n  bool IsFinishedOK()\n  {\n    if (Ver == 7)\n      return Ppmd7z_RangeDec_IsFinishedOK(&_ppmd7.rc.dec);\n    return Ppmd8_RangeDec_IsFinishedOK(&_ppmd8);\n  }\n};\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  // extractCallback->SetTotal(_packSize);\n  UInt64 currentTotalPacked = 0;\n  RINOK(extractCallback->SetCompleted(&currentTotalPacked))\n  Int32 opRes;\n{\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  CByteInBufWrap inBuf;\n  if (!inBuf.Alloc(1 << 20))\n    return E_OUTOFMEMORY;\n  inBuf.Stream = _stream;\n\n  CBuf outBuf;\n  if (!outBuf.Alloc())\n    return E_OUTOFMEMORY;\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, true);\n\n  CPpmdCpp ppmd(_item.Ver);\n  if (!ppmd.Alloc(_item.MemInMB))\n    return E_OUTOFMEMORY;\n  \n  opRes = NExtract::NOperationResult::kUnsupportedMethod;\n\n  if (_item.IsSupported())\n  {\n    opRes = NExtract::NOperationResult::kDataError;\n    \n    ppmd.Init(_item.Order, _item.Restor);\n    inBuf.Init();\n    UInt64 outSize = 0;\n    \n    if (ppmd.InitRc(&inBuf) && !inBuf.Extra && inBuf.Res == S_OK)\n    for (;;)\n    {\n      lps->InSize = _packSize = inBuf.GetProcessed();\n      lps->OutSize = outSize;\n      RINOK(lps->SetCur())\n\n      size_t i;\n      int sym = 0;\n\n      Byte *buf = outBuf.Buf;\n      if (ppmd.Ver == 7)\n      {\n        for (i = 0; i < kBufSize; i++)\n        {\n          sym = Ppmd7a_DecodeSymbol(&ppmd._ppmd7);\n          if (inBuf.Extra || sym < 0)\n            break;\n          buf[i] = (Byte)sym;\n        }\n      }\n      else\n      {\n        for (i = 0; i < kBufSize; i++)\n        {\n          sym = Ppmd8_DecodeSymbol(&ppmd._ppmd8);\n          if (inBuf.Extra || sym < 0)\n            break;\n          buf[i] = (Byte)sym;\n        }\n      }\n\n      outSize += i;\n      _packSize = _headerSize + inBuf.GetProcessed();\n      _packSize_Defined = true;\n      if (realOutStream)\n      {\n        RINOK(WriteStream(realOutStream, outBuf.Buf, i))\n      }\n\n      if (inBuf.Extra)\n      {\n        opRes = NExtract::NOperationResult::kUnexpectedEnd;\n        break;\n      }\n\n      if (sym < 0)\n      {\n        if (sym == -1 && ppmd.IsFinishedOK())\n          opRes = NExtract::NOperationResult::kOK;\n        break;\n      }\n    }\n    \n    RINOK(inBuf.Res)\n  }\n}\n  return extractCallback->SetOperationResult(opRes);\n}\n\n\nstatic const Byte k_Signature[] = { 0x8F, 0xAF, 0xAC, 0x84 };\n\nREGISTER_ARC_I(\n  \"Ppmd\", \"pmd\", NULL, 0xD,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/QcowHandler.cpp",
    "content": "﻿// QcowHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer2.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/DeflateDecoder.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get32(p) GetBe32a(p)\n#define Get64(p) GetBe64a(p)\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NQcow {\n\nstatic const Byte k_Signature[] =  { 'Q', 'F', 'I', 0xFB, 0, 0, 0 };\n\n/*\nVA to PA maps:\n  high bits (L1) :              : index in L1 (_dir) : _dir[high_index] points to Table.\n  mid bits  (L2) : _numMidBits  : index in Table, Table[index] points to cluster start offset in arc file.\n  low bits       : _clusterBits : offset inside cluster.\n*/\n\nZ7_class_CHandler_final: public CHandlerImg\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Img)\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n\n  unsigned _clusterBits;\n  unsigned _numMidBits;\n  UInt64 _compressedFlag;\n\n  CObjArray2<UInt32> _dir;\n  CAlignedBuffer _table;\n  CByteBuffer _cache;\n  CByteBuffer _cacheCompressed;\n  UInt64 _cacheCluster;\n\n  UInt64 _comprPos;\n  size_t _comprSize;\n\n  bool _needCompression;\n  bool _isArc;\n  bool _unsupported;\n  Byte _compressionType;\n\n  UInt64 _phySize;\n\n  CMyComPtr2<ISequentialInStream, CBufInStream> _bufInStream;\n  CMyComPtr2<ISequentialOutStream, CBufPtrSeqOutStream> _bufOutStream;\n  CMyComPtr2<ICompressCoder, NCompress::NDeflate::NDecoder::CCOMCoder> _deflateDecoder;\n\n  UInt32 _version;\n  UInt32 _cryptMethod;\n  UInt64 _incompatFlags;\n  \n  HRESULT Seek2(UInt64 offset)\n  {\n    _posInArc = offset;\n    return InStream_SeekSet(Stream, offset);\n  }\n\n  HRESULT InitAndSeek()\n  {\n    _virtPos = 0;\n    return Seek2(0);\n  }\n\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) Z7_override;\n};\n\n\nstatic const UInt32 kEmptyDirItem = (UInt32)0 - 1;\n\nZ7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  // printf(\"\\nRead _virtPos = %6d  size = %6d\\n\", (UInt32)_virtPos, size);\n  if (_virtPos >= _size)\n    return S_OK;\n  {\n    const UInt64 rem = _size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n    if (size == 0)\n      return S_OK;\n  }\n \n  for (;;)\n  {\n    const UInt64 cluster = _virtPos >> _clusterBits;\n    const size_t clusterSize = (size_t)1 << _clusterBits;\n    const size_t lowBits = (size_t)_virtPos & (clusterSize - 1);\n    {\n      const size_t rem = clusterSize - lowBits;\n      if (size > rem)\n        size = (UInt32)rem;\n    }\n    if (cluster == _cacheCluster)\n    {\n      memcpy(data, _cache + lowBits, size);\n      break;\n    }\n   \n    const UInt64 high = cluster >> _numMidBits;\n \n    if (high < _dir.Size())\n    {\n      const UInt32 tabl = _dir[(size_t)high];\n      if (tabl != kEmptyDirItem)\n      {\n        const size_t midBits = (size_t)cluster & (((size_t)1 << _numMidBits) - 1);\n        const Byte *p = _table + ((((size_t)tabl << _numMidBits) + midBits) << 3);\n        UInt64 v = Get64(p);\n        \n        if (v)\n        {\n          if (v & _compressedFlag)\n          {\n            if (_version <= 1)\n              return E_FAIL;\n            /*\n            the example of table record for 12-bit clusters (4KB uncompressed):\n              2 bits : isCompressed status\n              (4 == _clusterBits - 8) bits : (num_sectors - 1)\n                  packSize = num_sectors * 512;\n                  it uses one additional bit over unpacked cluster_bits.\n              (49 == 61 - _clusterBits) bits : offset of 512-byte sector\n              9 bits : offset in 512-byte sector\n            */\n            const unsigned numOffsetBits = 62 - (_clusterBits - 8);\n            const UInt64 offset = v & (((UInt64)1 << 62) - 1);\n            const size_t dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;\n            UInt64 sectorOffset = offset & (((UInt64)1 << numOffsetBits) - (1 << 9));\n            const UInt64 offset2inCache = sectorOffset - _comprPos;\n            \n            // _comprPos is aligned for 512-bytes\n            // we try to use previous _cacheCompressed that contains compressed data\n            // that was read for previous unpacking\n\n            if (sectorOffset >= _comprPos && offset2inCache < _comprSize)\n            {\n              if (offset2inCache)\n              {\n                _comprSize -= (size_t)offset2inCache;\n                memmove(_cacheCompressed, _cacheCompressed + (size_t)offset2inCache, _comprSize);\n                _comprPos = sectorOffset;\n              }\n              sectorOffset += _comprSize;\n            }\n            else\n            {\n              _comprPos = sectorOffset;\n              _comprSize = 0;\n            }\n            \n            if (dataSize > _comprSize)\n            {\n              if (sectorOffset != _posInArc)\n              {\n                // printf(\"\\nDeflate-Seek %12I64x %12I64x\\n\", sectorOffset, sectorOffset - _posInArc);\n                RINOK(Seek2(sectorOffset))\n              }\n              if (_cacheCompressed.Size() < dataSize)\n                return E_FAIL;\n              const size_t dataSize3 = dataSize - _comprSize;\n              size_t dataSize2 = dataSize3;\n              // printf(\"\\n\\n=======\\nReadStream = %6d _comprPos = %6d \\n\", (UInt32)dataSize2, (UInt32)_comprPos);\n              const HRESULT hres = ReadStream(Stream, _cacheCompressed + _comprSize, &dataSize2);\n              _posInArc += dataSize2;\n              RINOK(hres)\n              if (dataSize2 != dataSize3)\n                return E_FAIL;\n              _comprSize += dataSize2;\n            }\n            \n            const size_t kSectorMask = (1 << 9) - 1;\n            const size_t offsetInSector = (size_t)offset & kSectorMask;\n            _bufInStream->Init(_cacheCompressed + offsetInSector, dataSize - offsetInSector);\n            _cacheCluster = (UInt64)(Int64)-1;\n            if (_cache.Size() < clusterSize)\n              return E_FAIL;\n            _bufOutStream->Init(_cache, clusterSize);\n            // Do we need to use smaller block than clusterSize for last cluster?\n            const UInt64 blockSize64 = clusterSize;\n            HRESULT res = _deflateDecoder.Interface()->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);\n            /*\n            if (_bufOutStreamSpec->GetPos() != clusterSize)\n              memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());\n            */\n            if (res == S_OK)\n              if (!_deflateDecoder->IsFinished()\n                  || _bufOutStream->GetPos() != clusterSize)\n                res = S_FALSE;\n            RINOK(res)\n            _cacheCluster = cluster;\n            continue;\n            /*\n            memcpy(data, _cache + lowBits, size);\n            break;\n            */\n          }\n\n          // version_3 supports zero clusters\n          if (((UInt32)v & 511) != 1)\n          {\n            v &= _compressedFlag - 1;\n            v += lowBits;\n            if (v != _posInArc)\n            {\n              // printf(\"\\n%12I64x\\n\", v - _posInArc);\n              RINOK(Seek2(v))\n            }\n            const HRESULT res = Stream->Read(data, size, &size);\n            _posInArc += size;\n            _virtPos += size;\n            if (processedSize)\n              *processedSize = size;\n            return res;\n          }\n        }\n      }\n    }\n    \n    memset(data, 0, size);\n    break;\n  }\n\n  _virtPos += size;\n  if (processedSize)\n    *processedSize = size;\n  return S_OK;\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidClusterSize,\n  kpidSectorSize, // actually we need variable to show table size\n  kpidHeadersSize,\n  kpidUnpackVer,\n  kpidMethod,\n  kpidCharacts\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic const CUInt32PCharPair g_IncompatFlags_Characts[] =\n{\n  {  0, \"Dirty\" },\n  {  1, \"Corrupt\" },\n  {  2, \"External_Data_File\" },\n  {  3, \"Compression\" },\n  {  4, \"Extended_L2\" }\n};\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidClusterSize: prop = (UInt32)1 << _clusterBits; break;\n    case kpidSectorSize: prop = (UInt32)1 << (_numMidBits + 3); break;\n    case kpidHeadersSize: prop = _table.Size() + (UInt64)_dir.Size() * 8; break;\n    case kpidPhySize: if (_phySize) prop = _phySize; break;\n    case kpidUnpackVer: prop = _version; break;\n    case kpidCharacts:\n    {\n      if (_incompatFlags)\n      {\n        AString s (\"incompatible: \");\n        // we need to show also high 32-bits.\n        s += FlagsToString(g_IncompatFlags_Characts,\n            Z7_ARRAY_SIZE(g_IncompatFlags_Characts), (UInt32)_incompatFlags);\n        prop = s;\n      }\n      break;\n    }\n    case kpidMethod:\n    {\n      AString s;\n\n      if (_compressionType)\n      {\n        if (_compressionType == 1)\n          s += \"ZSTD\";\n        else\n        {\n          s += \"Compression:\";\n          s.Add_UInt32(_compressionType);\n        }\n      }\n      else if (_needCompression)\n        s.Add_OptSpaced(\"Deflate\");\n\n      if (_cryptMethod)\n      {\n        s.Add_Space_if_NotEmpty();\n        if (_cryptMethod == 1)\n          s += \"AES\";\n        if (_cryptMethod == 2)\n          s += \"LUKS\";\n        else\n        {\n          s += \"Encryption:\";\n          s.Add_UInt32(_cryptMethod);\n        }\n      }\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;\n      // if (_headerError) v |= kpv_ErrorFlags_HeadersError;\n      if (!Stream && v == 0)\n        v = kpv_ErrorFlags_HeadersError;\n      if (v)\n        prop = v;\n      break;\n    }\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidSize: prop = _size; break;\n    case kpidPackSize: prop = _phySize; break;\n    case kpidExtension: prop = (_imgExt ? _imgExt : \"img\"); break;\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)\n{\n  UInt64 buf64[0x70 / 8];\n  RINOK(ReadStream_FALSE(stream, buf64, sizeof(buf64)))\n  const void *buf = (const void *)buf64;\n  // signature: { 'Q', 'F', 'I', 0xFB }\n  if (*(const UInt32 *)buf != Z7_CONV_BE_TO_NATIVE_CONST32(0x514649fb))\n    return S_FALSE;\n  _version = Get32((const Byte *)(const void *)buf64 + 4);\n  if (_version < 1 || _version > 3)\n    return S_FALSE;\n  \n  const UInt64 k_UncompressedSize_MAX = (UInt64)1 << 60;\n  const UInt64 k_CompressedSize_MAX   = (UInt64)1 << 60;\n\n  _size = Get64((const Byte *)(const void *)buf64 + 0x18);\n  if (_size > k_UncompressedSize_MAX)\n    return S_FALSE;\n  size_t l1Size;\n  UInt32 headerSize;\n\n  if (_version == 1)\n  {\n    // _mTime = Get32((const Byte *)(const void *)buf64 + 0x14); // is unused in most images\n    _clusterBits = ((const Byte *)(const void *)buf64)[0x20];\n    _numMidBits  = ((const Byte *)(const void *)buf64)[0x21];\n    if (_clusterBits < 9 || _clusterBits > 30)\n      return S_FALSE;\n    if (_numMidBits < 1 || _numMidBits > 28)\n      return S_FALSE;\n    _cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x24);\n    const unsigned numBits2 = _clusterBits + _numMidBits;\n    const UInt64 l1Size64 = (_size + (((UInt64)1 << numBits2) - 1)) >> numBits2;\n    if (l1Size64 > ((UInt32)1 << 31))\n      return S_FALSE;\n    l1Size = (size_t)l1Size64;\n    headerSize = 0x30;\n  }\n  else\n  {\n    _clusterBits = Get32((const Byte *)(const void *)buf64 + 0x14);\n    if (_clusterBits < 9 || _clusterBits > 30)\n      return S_FALSE;\n    _numMidBits = _clusterBits - 3;\n    _cryptMethod = Get32((const Byte *)(const void *)buf64 + 0x20);\n    l1Size = Get32((const Byte *)(const void *)buf64 + 0x24);\n    headerSize = 0x48;\n    if (_version >= 3)\n    {\n      _incompatFlags = Get64((const Byte *)(const void *)buf64 + 0x48);\n      // const UInt64 CompatFlags    = Get64((const Byte *)(const void *)buf64 + 0x50);\n      // const UInt64 AutoClearFlags = Get64((const Byte *)(const void *)buf64 + 0x58);\n      // const UInt32 RefCountOrder = Get32((const Byte *)(const void *)buf64 + 0x60);\n      headerSize = 0x68;\n      const UInt32 headerSize2  = Get32((const Byte *)(const void *)buf64 + 0x64);\n      if (headerSize2 > (1u << 30))\n        return S_FALSE;\n      if (headerSize < headerSize2)\n          headerSize = headerSize2;\n      if (headerSize2 >= 0x68 + 1)\n        _compressionType = ((const Byte *)(const void *)buf64)[0x68];\n    }\n\n    const UInt64 refOffset = Get64((const Byte *)(const void *)buf64 + 0x30); // must be aligned for cluster\n    const UInt32 refClusters = Get32((const Byte *)(const void *)buf64 + 0x38);\n    // UInt32 numSnapshots = Get32((const Byte *)(const void *)buf64 + 0x3C);\n    // UInt64 snapshotsOffset = Get64((const Byte *)(const void *)buf64 + 0x40); // must be aligned for cluster\n    /*\n    if (numSnapshots)\n      return S_FALSE;\n    */\n    if (refClusters)\n    {\n      if (refOffset > k_CompressedSize_MAX)\n        return S_FALSE;\n      const UInt64 numBytes = (UInt64)refClusters << _clusterBits;\n      const UInt64 end = refOffset + numBytes;\n      if (end > k_CompressedSize_MAX)\n        return S_FALSE;\n      /*\n      CByteBuffer refs;\n      refs.Alloc(numBytes);\n      RINOK(InStream_SeekSet(stream, refOffset))\n      RINOK(ReadStream_FALSE(stream, refs, numBytes));\n      */\n      if (_phySize < end)\n          _phySize = end;\n      /*\n      for (size_t i = 0; i < numBytes; i += 2)\n      {\n        UInt32 v = GetBe16((const Byte *)refs + (size_t)i);\n        if (v == 0)\n          continue;\n      }\n      */\n    }\n  }\n\n  const UInt64 l1Offset = Get64((const Byte *)(const void *)buf64 + 0x28); // must be aligned for cluster ?\n  if (l1Offset < headerSize || l1Offset > k_CompressedSize_MAX)\n    return S_FALSE;\n  if (_phySize < headerSize)\n      _phySize = headerSize;\n\n  // we use 32 MiB limit for L1 size, as QEMU with QCOW_MAX_L1_SIZE limit.\n  if (l1Size > (1u << 22)) // if (l1Size > (1u << (sizeof(size_t) * 8 - 4)))\n    return S_FALSE;\n\n  _isArc = true;\n  {\n    const UInt64 backOffset = Get64((const Byte *)(const void *)buf64 + 8);\n    // UInt32 backSize = Get32((const Byte *)(const void *)buf64 + 0x10);\n    if (backOffset)\n    {\n      _unsupported = true;\n      return S_FALSE;\n    }\n  }\n\n  UInt64 fileSize = 0;\n  RINOK(InStream_GetSize_SeekToBegin(stream, fileSize))\n\n  const size_t clusterSize = (size_t)1 << _clusterBits;\n  const size_t t1SizeBytes = (size_t)l1Size << 3;\n  {\n    const UInt64 end = l1Offset + t1SizeBytes;\n    if (end > k_CompressedSize_MAX)\n      return S_FALSE;\n    // we need to use align end for empty qcow files\n    // some files has no cluster alignment padding at the end\n    // but has sector alignment\n    // end = (end + clusterSize - 1) >> _clusterBits << _clusterBits;\n    if (_phySize < end)\n        _phySize = end;\n    if (end > fileSize)\n      return S_FALSE;\n    if (_phySize < fileSize)\n    {\n      const UInt64 end2 = (end + 511) & ~(UInt64)511;\n      if (end2 == fileSize)\n        _phySize = end2;\n    }\n  }\n  CObjArray<UInt64> table64(l1Size);\n  {\n    RINOK(InStream_SeekSet(stream, l1Offset))\n    RINOK(ReadStream_FALSE(stream, table64, t1SizeBytes))\n  }\n\n  _compressedFlag = (_version <= 1) ? ((UInt64)1 << 63) : ((UInt64)1 << 62);\n  const UInt64 offsetMask = _compressedFlag - 1;\n  const size_t midSize = (size_t)1 << (_numMidBits + 3);\n  size_t numTables = 0;\n  size_t i;\n\n  for (i = 0; i < l1Size; i++)\n  {\n    const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;\n    if (!v)\n      continue;\n    numTables++;\n    const UInt64 end = v + midSize;\n    if (end > k_CompressedSize_MAX)\n      return S_FALSE;\n    if (_phySize < end)\n        _phySize = end;\n    if (end > fileSize)\n      return S_FALSE;\n  }\n\n  if (numTables)\n  {\n    const size_t size = (size_t)numTables << (_numMidBits + 3);\n    if (size >> (_numMidBits + 3) != numTables)\n      return E_OUTOFMEMORY;\n    _table.Alloc(size);\n    if (!_table.IsAllocated())\n      return E_OUTOFMEMORY;\n    if (openCallback)\n    {\n      const UInt64 totalBytes = size;\n      RINOK(openCallback->SetTotal(NULL, &totalBytes))\n    }\n  }\n\n  _dir.SetSize((unsigned)l1Size);\n\n  UInt32 curTable = 0;\n\n  for (i = 0; i < l1Size; i++)\n  {\n    Byte *buf2;\n    {\n      const UInt64 v = Get64(table64 + (size_t)i) & offsetMask;\n      if (v == 0)\n      {\n        _dir[i] = kEmptyDirItem;\n        continue;\n      }\n      _dir[i] = curTable;\n      const size_t tableOffset = (size_t)curTable << (_numMidBits + 3);\n      buf2 = (Byte *)_table + tableOffset;\n      curTable++;\n      if (openCallback && (tableOffset & 0xFFFFF) == 0)\n      {\n        const UInt64 numBytes = tableOffset;\n        RINOK(openCallback->SetCompleted(NULL, &numBytes))\n      }\n      RINOK(InStream_SeekSet(stream, v))\n      RINOK(ReadStream_FALSE(stream, buf2, midSize))\n    }\n\n    for (size_t k = 0; k < midSize; k += 8)\n    {\n      const UInt64 v = Get64((const Byte *)buf2 + (size_t)k);\n      if (v == 0)\n        continue;\n      UInt64 offset = v & offsetMask;\n      size_t dataSize = clusterSize;\n      \n      if (v & _compressedFlag)\n      {\n        if (_version <= 1)\n        {\n          const unsigned numOffsetBits = 63 - _clusterBits;\n          dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;\n          offset &= ((UInt64)1 << numOffsetBits) - 1;\n          dataSize = 0; // why ?\n          // offset &= ~(((UInt64)1 << 9) - 1);\n        }\n        else\n        {\n          const unsigned numOffsetBits = 62 - (_clusterBits - 8);\n          dataSize = ((size_t)(offset >> numOffsetBits) + 1) << 9;\n          offset &= ((UInt64)1 << numOffsetBits) - (1 << 9);\n        }\n        _needCompression = true;\n      }\n      else\n      {\n        const UInt32 low = (UInt32)v & 511;\n        if (low)\n        {\n          // version_3 supports zero clusters\n          if (_version < 3 || low != 1)\n          {\n            _unsupported = true;\n            return S_FALSE;\n          }\n        }\n      }\n      \n      const UInt64 end = offset + dataSize;\n      if (_phySize < end)\n          _phySize = end;\n    }\n  }\n\n  if (curTable != numTables)\n    return E_FAIL;\n\n  if (_cryptMethod)\n    _unsupported = true;\n  if (_needCompression && _version <= 1) // that case was not implemented\n    _unsupported = true;\n  if (_compressionType)\n    _unsupported = true;\n\n  Stream = stream;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _table.Free();\n  _dir.Free();\n  // _cache.Free();\n  // _cacheCompressed.Free();\n  _phySize = 0;\n\n  _cacheCluster = (UInt64)(Int64)-1;\n  _comprPos = 0;\n  _comprSize = 0;\n\n  _needCompression = false;\n  _isArc = false;\n  _unsupported = false;\n\n  _compressionType = 0;\n  _incompatFlags = 0;\n\n  // CHandlerImg:\n  Clear_HandlerImg_Vars();\n  Stream.Release();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  if (_unsupported || !Stream)\n    return S_FALSE;\n  if (_needCompression)\n  {\n    if (_version <= 1 || _compressionType)\n      return S_FALSE;\n    _bufInStream.Create_if_Empty();\n    _bufOutStream.Create_if_Empty();\n    _deflateDecoder.Create_if_Empty();\n    _deflateDecoder->Set_NeedFinishInput(true);\n    const size_t clusterSize = (size_t)1 << _clusterBits;\n    _cache.AllocAtLeast(clusterSize);\n    _cacheCompressed.AllocAtLeast(clusterSize * 2);\n  }\n  CMyComPtr<ISequentialInStream> streamTemp = this;\n  RINOK(InitAndSeek())\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\nREGISTER_ARC_I(\n  \"QCOW\", \"qcow qcow2 qcow2c\", NULL, 0xCA,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/Rar5Handler.cpp",
    "content": "﻿// Rar5Handler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/7zCrc.h\"\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/MyBuffer2.h\"\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../../Windows/PropVariantUtils.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../IPassword.h\"\n\n#include \"../../Common/FilterCoder.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/MethodProps.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/RegisterArc.h\"\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Common/RegisterCodec.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"../../Crypto/Rar5Aes.h\"\n\n#include \"../../Archive/Common/FindSignature.h\"\n#include \"../../Archive/Common/ItemNameUtils.h\"\n#include \"../../Archive/Common/HandlerOut.h\"\n\n#include \"../../Archive/HandlerCont.h\"\n\n#include \"../../Archive/Rar/RarVol.h\"\n#include \"Rar5Handler.h\"\n\nusing namespace NWindows;\n\n#define Get32(p) GetUi32(p)\n\nnamespace NArchive {\nnamespace NRar5 {\n\nstatic const unsigned kMarkerSize = 8;\n\nstatic const Byte kMarker[kMarkerSize] =\n  { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0 };\n\n// Comment length is limited to 256 KB in rar-encoder.\n// So we use same limitation\nstatic const size_t kCommentSize_Max = (size_t)1 << 18;\n\n\nstatic const char * const kHostOS[] =\n{\n    \"Windows\"\n  , \"Unix\"\n};\n\n\nstatic const char * const k_ArcFlags[] =\n{\n    \"Volume\"\n  , \"VolumeField\"\n  , \"Solid\"\n  , \"Recovery\"\n  , \"Lock\" // 4\n};\n\n\nstatic const char * const k_FileFlags[] =\n{\n    \"Dir\"\n  , \"UnixTime\"\n  , \"CRC\"\n  , \"UnknownSize\"\n};\n\n\nstatic const char * const g_ExtraTypes[] =\n{\n    \"0\"\n  , \"Crypto\"\n  , \"Hash\"\n  , \"Time\"\n  , \"Version\"\n  , \"Link\"\n  , \"UnixOwner\"\n  , \"Subdata\"\n};\n\n\nstatic const char * const g_LinkTypes[] =\n{\n    \"0\"\n  , \"UnixSymLink\"\n  , \"WinSymLink\"\n  , \"WinJunction\"\n  , \"HardLink\"\n  , \"FileCopy\"\n};\n\n\nstatic const char g_ExtraTimeFlags[] = { 'u', 'M', 'C', 'A', 'n' };\n\n\nstatic\nZ7_NO_INLINE\nunsigned ReadVarInt(const Byte *p, size_t maxSize, UInt64 *val_ptr)\n{\n  if (maxSize > 10)\n      maxSize = 10;\n  UInt64 val = 0;\n  unsigned i;\n  for (i = 0; i < maxSize;)\n  {\n    const unsigned b = p[i];\n    val |= (UInt64)(b & 0x7F) << (7 * i);\n    i++;\n    if ((b & 0x80) == 0)\n    {\n      *val_ptr = val;\n      return i;\n    }\n  }\n  *val_ptr = 0;\n#if 1\n  return 0; // 7zip-unrar : strict check of error\n#else\n  return i; // original-unrar : ignore error\n#endif\n}\n\n\n#define PARSE_VAR_INT(p, size, dest) \\\n{ const unsigned num_ = ReadVarInt(p, size, &dest);  \\\n  if (num_ == 0) return false; \\\n  p += num_; \\\n  size -= num_; \\\n}\n\n\nbool CLinkInfo::Parse(const Byte *p, unsigned size)\n{\n  const Byte *pStart = p;\n  UInt64 len;\n  PARSE_VAR_INT(p, size, Type)\n  PARSE_VAR_INT(p, size, Flags)\n  PARSE_VAR_INT(p, size, len)\n  if (size != len)\n    return false;\n  NameLen = (unsigned)len;\n  NameOffset = (unsigned)(size_t)(p - pStart);\n  return true;\n}\n\n\nstatic void AddHex64(AString &s, UInt64 v)\n{\n  char sz[32];\n  sz[0] = '0';\n  sz[1] = 'x';\n  ConvertUInt64ToHex(v, sz + 2);\n  s += sz;\n}\n\n\nstatic void PrintType(AString &s, const char * const table[], unsigned num, UInt64 val)\n{\n  char sz[32];\n  const char *p = NULL;\n  if (val < num)\n    p = table[(unsigned)val];\n  if (!p)\n  {\n    ConvertUInt64ToString(val, sz);\n    p = sz;\n  }\n  s += p;\n}\n\n\nint CItem::FindExtra(unsigned extraID, unsigned &recordDataSize) const\n{\n  recordDataSize = 0;\n  size_t offset = 0;\n\n  for (;;)\n  {\n    size_t rem = Extra.Size() - offset;\n    if (rem == 0)\n      return -1;\n    \n    {\n      UInt64 size;\n      const unsigned num = ReadVarInt(Extra + offset, rem, &size);\n      if (num == 0)\n        return -1;\n      offset += num;\n      rem -= num;\n      if (size > rem)\n        return -1;\n      rem = (size_t)size;\n    }\n    {\n      UInt64 id;\n      const unsigned num = ReadVarInt(Extra + offset, rem, &id);\n      if (num == 0)\n        return -1;\n      offset += num;\n      rem -= num;\n\n      // There was BUG in RAR 5.21- : it stored (size-1) instead of (size)\n      // for Subdata record in Service header.\n      // That record always was last in bad archives, so we can fix that case.\n      if (id == NExtraID::kSubdata\n          && RecordType == NHeaderType::kService\n          && rem + 1 == Extra.Size() - offset)\n        rem++;\n\n      if (id == extraID)\n      {\n        recordDataSize = (unsigned)rem;\n        return (int)offset;\n      }\n\n      offset += rem;\n    }\n  }\n}\n\n\nvoid CItem::PrintInfo(AString &s) const\n{\n  size_t offset = 0;\n\n  for (;;)\n  {\n    size_t rem = Extra.Size() - offset;\n    if (rem == 0)\n      return;\n    \n    {\n      UInt64 size;\n      unsigned num = ReadVarInt(Extra + offset, rem, &size);\n      if (num == 0)\n        return;\n      offset += num;\n      rem -= num;\n      if (size > rem)\n        break;\n      rem = (size_t)size;\n    }\n    {\n      UInt64 id;\n      {\n        unsigned num = ReadVarInt(Extra + offset, rem, &id);\n        if (num == 0)\n          break;\n        offset += num;\n        rem -= num;\n      }\n\n      // There was BUG in RAR 5.21- : it stored (size-1) instead of (size)\n      // for Subdata record in Service header.\n      // That record always was last in bad archives, so we can fix that case.\n      if (id == NExtraID::kSubdata\n          && RecordType == NHeaderType::kService\n          && rem + 1 == Extra.Size() - offset)\n        rem++;\n\n      s.Add_Space_if_NotEmpty();\n      PrintType(s, g_ExtraTypes, Z7_ARRAY_SIZE(g_ExtraTypes), id);\n\n      if (id == NExtraID::kTime)\n      {\n        const Byte *p = Extra + offset;\n        UInt64 flags;\n        const unsigned num = ReadVarInt(p, rem, &flags);\n        if (num != 0)\n        {\n          s.Add_Colon();\n          for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExtraTimeFlags); i++)\n            if ((flags & ((UInt64)1 << i)) != 0)\n              s.Add_Char(g_ExtraTimeFlags[i]);\n          flags &= ~(((UInt64)1 << Z7_ARRAY_SIZE(g_ExtraTimeFlags)) - 1);\n          if (flags != 0)\n          {\n            s.Add_Char('_');\n            AddHex64(s, flags);\n          }\n        }\n      }\n      else if (id == NExtraID::kLink)\n      {\n        CLinkInfo linkInfo;\n        if (linkInfo.Parse(Extra + offset, (unsigned)rem))\n        {\n          s.Add_Colon();\n          PrintType(s, g_LinkTypes, Z7_ARRAY_SIZE(g_LinkTypes), linkInfo.Type);\n          UInt64 flags = linkInfo.Flags;\n          if (flags != 0)\n          {\n            s.Add_Colon();\n            if (flags & NLinkFlags::kTargetIsDir)\n            {\n              s.Add_Char('D');\n              flags &= ~((UInt64)NLinkFlags::kTargetIsDir);\n            }\n            if (flags != 0)\n            {\n              s.Add_Char('_');\n              AddHex64(s, flags);\n            }\n          }\n        }\n      }\n\n      offset += rem;\n    }\n  }\n\n  s.Add_OptSpaced(\"ERROR\");\n}\n\n\nbool CCryptoInfo::Parse(const Byte *p, size_t size)\n{\n  Algo = 0;\n  Flags = 0;\n  Cnt = 0;\n  PARSE_VAR_INT(p, size, Algo)\n  PARSE_VAR_INT(p, size, Flags)\n  if (size > 0)\n    Cnt = p[0];\n  if (size != 1 + 16 + 16 + (unsigned)(IsThereCheck() ? 12 : 0))\n    return false;\n  return true;\n}\n\n\nbool CItem::FindExtra_Version(UInt64 &version) const\n{\n  unsigned size;\n  const int offset = FindExtra(NExtraID::kVersion, size);\n  if (offset < 0)\n    return false;\n  const Byte *p = Extra + (unsigned)offset;\n\n  UInt64 flags;\n  PARSE_VAR_INT(p, size, flags)\n  PARSE_VAR_INT(p, size, version)\n  return size == 0;\n}\n\nbool CItem::FindExtra_Link(CLinkInfo &link) const\n{\n  unsigned size;\n  const int offset = FindExtra(NExtraID::kLink, size);\n  if (offset < 0)\n    return false;\n  if (!link.Parse(Extra + (unsigned)offset, size))\n    return false;\n  link.NameOffset += (unsigned)offset;\n  return true;\n}\n\nbool CItem::Is_CopyLink() const\n{\n  CLinkInfo link;\n  return FindExtra_Link(link) && link.Type == NLinkType::kFileCopy;\n}\n\nbool CItem::Is_HardLink() const\n{\n  CLinkInfo link;\n  return FindExtra_Link(link) && link.Type == NLinkType::kHardLink;\n}\n\nbool CItem::Is_CopyLink_or_HardLink() const\n{\n  CLinkInfo link;\n  return FindExtra_Link(link) && (link.Type == NLinkType::kFileCopy || link.Type == NLinkType::kHardLink);\n}\n\nvoid CItem::Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const\n{\n  CLinkInfo link;\n  if (!FindExtra_Link(link))\n    return;\n\n  bool isWindows = (HostOS == kHost_Windows);\n  if (link.Type != linkType)\n  {\n    if (linkType != NLinkType::kUnixSymLink)\n      return;\n    switch ((unsigned)link.Type)\n    {\n      case NLinkType::kUnixSymLink:\n        isWindows = false;\n        break;\n      case NLinkType::kWinSymLink:\n      case NLinkType::kWinJunction:\n        isWindows = true;\n        break;\n      default: return;\n    }\n  }\n\n  AString s;\n  s.SetFrom_CalcLen((const char *)(Extra + link.NameOffset), link.NameLen);\n  UString unicode;\n  ConvertUTF8ToUnicode(s, unicode);\n  // rar5.0  used '\\\\' separator for windows symlinks and \\??\\ prefix for abs paths.\n  // rar5.1+ uses '/'  separator for windows symlinks and /??/ prefix for abs paths.\n  // v25.00: we convert Windows slashes to Linux slashes:\n  if (isWindows)\n    unicode.Replace(L'\\\\', L'/');\n  prop = unicode;\n  // prop = NItemName::GetOsPath(unicode);\n}\n\nbool CItem::GetAltStreamName(AString &name) const\n{\n  name.Empty();\n  unsigned size;\n  const int offset = FindExtra(NExtraID::kSubdata, size);\n  if (offset < 0)\n    return false;\n  name.SetFrom_CalcLen((const char *)(Extra + (unsigned)offset), size);\n  return true;\n}\n\n\nclass CHash\n{\n  bool _calcCRC;\n  UInt32 _crc;\n  int _blakeOffset;\n  CAlignedBuffer1 _buf;\n  // CBlake2sp _blake;\n  CBlake2sp *BlakeObj() { return (CBlake2sp *)(void *)(Byte *)_buf; }\npublic:\n  CHash():\n    _buf(sizeof(CBlake2sp))\n    {}\n\n  void Init_NoCalc()\n  {\n    _calcCRC = false;\n    _crc = CRC_INIT_VAL;\n    _blakeOffset = -1;\n  }\n\n  void Init(const CItem &item);\n  void Update(const void *data, size_t size);\n  UInt32 GetCRC() const { return CRC_GET_DIGEST(_crc); }\n\n  bool Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoder);\n};\n\nvoid CHash::Init(const CItem &item)\n{\n  _crc = CRC_INIT_VAL;\n  _calcCRC = item.Has_CRC();\n  _blakeOffset = item.FindExtra_Blake();\n  if (_blakeOffset >= 0)\n    Blake2sp_Init(BlakeObj());\n}\n\nvoid CHash::Update(const void *data, size_t size)\n{\n  if (_calcCRC)\n    _crc = CrcUpdate(_crc, data, size);\n  if (_blakeOffset >= 0)\n    Blake2sp_Update(BlakeObj(), (const Byte *)data, size);\n}\n\nbool CHash::Check(const CItem &item, NCrypto::NRar5::CDecoder *cryptoDecoder)\n{\n  if (_calcCRC)\n  {\n    UInt32 crc = GetCRC();\n    if (cryptoDecoder)\n      crc = cryptoDecoder->Hmac_Convert_Crc32(crc);\n    if (crc != item.CRC)\n      return false;\n  }\n  if (_blakeOffset >= 0)\n  {\n    UInt32 digest[Z7_BLAKE2S_DIGEST_SIZE / sizeof(UInt32)];\n    Blake2sp_Final(BlakeObj(), (Byte *)(void *)digest);\n    if (cryptoDecoder)\n      cryptoDecoder->Hmac_Convert_32Bytes((Byte *)(void *)digest);\n    if (memcmp(digest, item.Extra + (unsigned)_blakeOffset, Z7_BLAKE2S_DIGEST_SIZE) != 0)\n      return false;\n  }\n  return true;\n}\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithHash\n  , ISequentialOutStream\n)\n  bool _size_Defined;\n  ISequentialOutStream *_stream;\n  UInt64 _pos;\n  UInt64 _size;\n  Byte *_destBuf;\npublic:\n  CHash _hash;\n\n  COutStreamWithHash(): _destBuf(NULL) {}\n\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void Init(const CItem &item, Byte *destBuf, bool needChecksumCheck)\n  {\n    _size_Defined = false;\n    _size = 0;\n    _destBuf = NULL;\n    if (!item.Is_UnknownSize())\n    {\n      _size_Defined = true;\n      _size = item.Size;\n      _destBuf = destBuf;\n    }\n    _pos = 0;\n    if (needChecksumCheck)\n      _hash.Init(item);\n    else\n      _hash.Init_NoCalc();\n  }\n  UInt64 GetPos() const { return _pos; }\n};\n\n\nZ7_COM7F_IMF(COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_size_Defined)\n  {\n    const UInt64 rem = _size - _pos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  if (_destBuf)\n    memcpy(_destBuf + (size_t)_pos, data, size);\n  _hash.Update(data, size);\n  _pos += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\n\n\n\n\nclass CInArchive\n{\n  CAlignedBuffer _buf;\n  size_t _bufSize;\n  size_t _bufPos;\n  ISequentialInStream *_stream;\n\n  CMyComPtr2<ICompressFilter, NCrypto::NRar5::CDecoder> m_CryptoDecoder;\n\n  Z7_CLASS_NO_COPY(CInArchive)\n\n  HRESULT ReadStream_Check(void *data, size_t size);\n\npublic:\n  bool m_CryptoMode;\n\n  bool WrongPassword;\n  bool IsArc;\n  bool UnexpectedEnd;\n\n  UInt64 StreamStartPosition;\n  UInt64 Position;\n    \n  size_t Get_Buf_RemainSize() const { return _bufSize - _bufPos; }\n  bool Is_Buf_Finished() const { return _bufPos == _bufSize; }\n  const Byte *Get_Buf_Data() const { return _buf + _bufPos; }\n  void Move_BufPos(size_t num) { _bufPos += num; }\n  bool ReadVar(UInt64 &val);\n\n  struct CHeader\n  {\n    UInt64 Type;\n    UInt64 Flags;\n    size_t ExtraSize;\n    UInt64 DataSize;\n  };\n\n  CInArchive() {}\n\n  HRESULT ReadBlockHeader(CHeader &h);\n  bool ReadFileHeader(const CHeader &header, CItem &item);\n  void AddToSeekValue(UInt64 addValue)\n  {\n    Position += addValue;\n  }\n\n  HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,\n      CInArcInfo &info);\n};\n  \n\nstatic HRESULT MySetPassword(ICryptoGetTextPassword *getTextPassword, NCrypto::NRar5::CDecoder *cryptoDecoder)\n{\n  CMyComBSTR_Wipe password;\n  RINOK(getTextPassword->CryptoGetTextPassword(&password))\n  AString_Wipe utf8;\n  const unsigned kPasswordLen_MAX = 127;\n  UString_Wipe unicode;\n  unicode.SetFromBstr(password);\n  if (unicode.Len() > kPasswordLen_MAX)\n    unicode.DeleteFrom(kPasswordLen_MAX);\n  ConvertUnicodeToUTF8(unicode, utf8);\n  cryptoDecoder->SetPassword((const Byte *)(const char *)utf8, utf8.Len());\n  return S_OK;\n}\n\n\nbool CInArchive::ReadVar(UInt64 &val)\n{\n  const unsigned offset = ReadVarInt(Get_Buf_Data(), Get_Buf_RemainSize(), &val);\n  Move_BufPos(offset);\n  return (offset != 0);\n}\n\n\nHRESULT CInArchive::ReadStream_Check(void *data, size_t size)\n{\n  size_t size2 = size;\n  RINOK(ReadStream(_stream, data, &size2))\n  if (size2 == size)\n    return S_OK;\n  UnexpectedEnd = true;\n  return S_FALSE;\n}\n\n\nHRESULT CInArchive::ReadBlockHeader(CHeader &h)\n{\n  h.Type = 0;\n  h.Flags = 0;\n  h.ExtraSize = 0;\n  h.DataSize = 0;\n\n  Byte buf[AES_BLOCK_SIZE];\n  unsigned filled;\n  \n  if (m_CryptoMode)\n  {\n    _buf.AllocAtLeast(1 << 12); // at least (AES_BLOCK_SIZE * 2)\n    if (!(Byte *)_buf)\n      return E_OUTOFMEMORY;\n    RINOK(ReadStream_Check(_buf, AES_BLOCK_SIZE * 2))\n    memcpy(m_CryptoDecoder->_iv, _buf, AES_BLOCK_SIZE);\n    RINOK(m_CryptoDecoder->Init())\n    // we call RAR5_AES_Filter with:\n    //   data_ptr  == aligned_ptr + 16\n    //   data_size == 16\n    if (m_CryptoDecoder->Filter(_buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE) != AES_BLOCK_SIZE)\n      return E_FAIL;\n    memcpy(buf, _buf + AES_BLOCK_SIZE, AES_BLOCK_SIZE);\n    filled = AES_BLOCK_SIZE;\n  }\n  else\n  {\n    const unsigned kStartSize = 4 + 3;\n    RINOK(ReadStream_Check(buf, kStartSize))\n    filled = kStartSize;\n  }\n  \n  {\n    UInt64 val;\n    unsigned offset = ReadVarInt(buf + 4, 3, &val);\n    if (offset == 0)\n      return S_FALSE;\n    size_t size = (size_t)val;\n    if (size < 2)\n      return S_FALSE;\n    offset += 4;\n    _bufPos = offset;\n    size += offset;\n    _bufSize = size;\n    if (m_CryptoMode)\n      size = (size + AES_BLOCK_SIZE - 1) & ~(size_t)(AES_BLOCK_SIZE - 1);\n    _buf.AllocAtLeast(size);\n    if (!(Byte *)_buf)\n      return E_OUTOFMEMORY;\n    memcpy(_buf, buf, filled);\n    const size_t rem = size - filled;\n    // if (m_CryptoMode), we add AES_BLOCK_SIZE here, because _iv is not included to size.\n    AddToSeekValue(size + (m_CryptoMode ? AES_BLOCK_SIZE : 0));\n    RINOK(ReadStream_Check(_buf + filled, rem))\n    if (m_CryptoMode)\n    {\n      // we call RAR5_AES_Filter with:\n      //   data_ptr  == aligned_ptr + 16\n      //   (rem) can be big\n      if (m_CryptoDecoder->Filter(_buf + filled, (UInt32)rem) != rem)\n        return E_FAIL;\n#if 1\n      // optional 7zip-unrar check : remainder must contain zeros.\n      const size_t pad = size - _bufSize;\n      const Byte *p = _buf + _bufSize;\n      for (size_t i = 0; i < pad; i++)\n        if (p[i])\n          return S_FALSE;\n#endif\n    }\n  }\n\n  if (CrcCalc(_buf + 4, _bufSize - 4) != Get32(buf))\n    return S_FALSE;\n\n  if (!ReadVar(h.Type)) return S_FALSE;\n  if (!ReadVar(h.Flags)) return S_FALSE;\n\n  if (h.Flags & NHeaderFlags::kExtra)\n  {\n    UInt64 extraSize;\n    if (!ReadVar(extraSize))\n      return S_FALSE;\n    if (extraSize >= (1u << 21))\n      return S_FALSE;\n    h.ExtraSize = (size_t)extraSize;\n  }\n  \n  if (h.Flags & NHeaderFlags::kData)\n  {\n    if (!ReadVar(h.DataSize))\n      return S_FALSE;\n  }\n  \n  if (h.ExtraSize > Get_Buf_RemainSize())\n    return S_FALSE;\n  return S_OK;\n}\n\n\nbool CInArcInfo::CLocator::Parse(const Byte *p, size_t size)\n{\n  Flags = 0;\n  QuickOpen = 0;\n  Recovery = 0;\n\n  PARSE_VAR_INT(p, size, Flags)\n\n  if (Is_QuickOpen())\n  {\n    PARSE_VAR_INT(p, size, QuickOpen)\n  }\n  if (Is_Recovery())\n  {\n    PARSE_VAR_INT(p, size, Recovery)\n  }\n#if 0\n  // another records are possible in future rar formats.\n  if (size != 0)\n    return false;\n#endif\n  return true;\n}\n\n\nbool CInArcInfo::CMetadata::Parse(const Byte *p, size_t size)\n{\n  PARSE_VAR_INT(p, size, Flags)\n  if (Flags & NMetadataFlags::kArcName)\n  {\n    UInt64 nameLen;\n    PARSE_VAR_INT(p, size, nameLen)\n    if (nameLen > size)\n      return false;\n    ArcName.SetFrom_CalcLen((const char *)(const void *)p, (unsigned)nameLen);\n    p += (size_t)nameLen;\n    size -= (size_t)nameLen;\n  }\n  if (Flags & NMetadataFlags::kCTime)\n  {\n    if ((Flags & NMetadataFlags::kUnixTime) &&\n        (Flags & NMetadataFlags::kNanoSec) == 0)\n    {\n      if (size < 4)\n        return false;\n      CTime = GetUi32(p);\n      p += 4;\n      size -= 4;\n    }\n    else\n    {\n      if (size < 8)\n        return false;\n      CTime = GetUi64(p);\n      p += 8;\n      size -= 8;\n    }\n  }\n#if 0\n  // another records are possible in future rar formats.\n  if (size != 0)\n    return false;\n#endif\n  return true;\n}\n\n\nbool CInArcInfo::ParseExtra(const Byte *p, size_t size)\n{\n  for (;;)\n  {\n    if (size == 0)\n      return true;\n    UInt64 recSize64, id;\n    PARSE_VAR_INT(p, size, recSize64)\n    if (recSize64 > size)\n      return false;\n    size_t recSize = (size_t)recSize64;\n    size -= recSize;\n    // READ_VAR_INT(p, recSize, recSize)\n    {\n      const unsigned num = ReadVarInt(p, recSize, &id);\n      if (num == 0)\n        return false;\n      p += num;\n      recSize -= num;\n    }\n    if (id == kArcExtraRecordType_Metadata)\n    {\n      Metadata_Defined = true;\n      if (!Metadata.Parse(p, recSize))\n        Metadata_Error = true;\n    }\n    else if (id == kArcExtraRecordType_Locator)\n    {\n      Locator_Defined = true;\n      if (!Locator.Parse(p, recSize))\n        Locator_Error = true;\n    }\n    else\n      UnknownExtraRecord = true;\n    p += recSize;\n  }\n}\n\n\n\nHRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit, ICryptoGetTextPassword *getTextPassword,\n    CInArcInfo &info)\n{\n  m_CryptoMode = false;\n  \n  WrongPassword = false;\n  IsArc = false;\n  UnexpectedEnd = false;\n\n  Position = StreamStartPosition;\n\n  UInt64 arcStartPos = StreamStartPosition;\n  {\n    Byte marker[kMarkerSize];\n    RINOK(ReadStream_FALSE(stream, marker, kMarkerSize))\n    if (memcmp(marker, kMarker, kMarkerSize) == 0)\n      Position += kMarkerSize;\n    else\n    {\n      if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)\n        return S_FALSE;\n      RINOK(InStream_SeekSet(stream, StreamStartPosition))\n      RINOK(FindSignatureInStream(stream, kMarker, kMarkerSize,\n          searchHeaderSizeLimit, arcStartPos))\n      arcStartPos += StreamStartPosition;\n      Position = arcStartPos + kMarkerSize;\n      RINOK(InStream_SeekSet(stream, Position))\n    }\n  }\n\n  info.StartPos = arcStartPos;\n  _stream = stream;\n\n  CHeader h;\n  RINOK(ReadBlockHeader(h))\n  info.IsEncrypted = false;\n  \n  if (h.Type == NHeaderType::kArcEncrypt)\n  {\n    info.IsEncrypted = true;\n    IsArc = true;\n    if (!getTextPassword)\n      return E_NOTIMPL;\n    m_CryptoMode = true;\n    m_CryptoDecoder.Create_if_Empty();\n    RINOK(m_CryptoDecoder->SetDecoderProps(\n        Get_Buf_Data(), (unsigned)Get_Buf_RemainSize(), false, false))\n    RINOK(MySetPassword(getTextPassword, m_CryptoDecoder.ClsPtr()))\n    if (!m_CryptoDecoder->CalcKey_and_CheckPassword())\n    {\n      WrongPassword = True;\n      return S_FALSE;\n    }\n    RINOK(ReadBlockHeader(h))\n  }\n\n  if (h.Type != NHeaderType::kArc)\n    return S_FALSE;\n\n  IsArc = true;\n  info.VolNumber = 0;\n  \n  if (!ReadVar(info.Flags))\n    return S_FALSE;\n  \n  if (info.Flags & NArcFlags::kVolNumber)\n    if (!ReadVar(info.VolNumber))\n      return S_FALSE;\n  \n  if (h.ExtraSize != Get_Buf_RemainSize())\n    return S_FALSE;\n  if (h.ExtraSize)\n  {\n    if (!info.ParseExtra(Get_Buf_Data(), h.ExtraSize))\n      info.Extra_Error = true;\n  }\n  return S_OK;\n}\n\n\nbool CInArchive::ReadFileHeader(const CHeader &header, CItem &item)\n{\n  item.CommonFlags = (UInt32)header.Flags;\n  item.PackSize = header.DataSize;\n  item.UnixMTime = 0;\n  item.CRC = 0;\n\n  {\n    UInt64 flags64;\n    if (!ReadVar(flags64)) return false;\n    item.Flags = (UInt32)flags64;\n  }\n\n  if (!ReadVar(item.Size)) return false;\n  \n  {\n    UInt64 attrib;\n    if (!ReadVar(attrib)) return false;\n    item.Attrib = (UInt32)attrib;\n  }\n  if (item.Has_UnixMTime())\n  {\n    if (Get_Buf_RemainSize() < 4)\n      return false;\n    item.UnixMTime = Get32(Get_Buf_Data());\n    Move_BufPos(4);\n  }\n  if (item.Has_CRC())\n  {\n    if (Get_Buf_RemainSize() < 4)\n      return false;\n    item.CRC = Get32(Get_Buf_Data());\n    Move_BufPos(4);\n  }\n  {\n    UInt64 method;\n    if (!ReadVar(method)) return false;\n    item.Method = (UInt32)method;\n  }\n\n  if (!ReadVar(item.HostOS)) return false;\n\n  {\n    UInt64 len;\n    if (!ReadVar(len)) return false;\n    if (len > Get_Buf_RemainSize())\n      return false;\n    item.Name.SetFrom_CalcLen((const char *)Get_Buf_Data(), (unsigned)len);\n    Move_BufPos((size_t)len);\n  }\n  \n  item.Extra.Free();\n  const size_t extraSize = header.ExtraSize;\n  if (extraSize != 0)\n  {\n    if (Get_Buf_RemainSize() < extraSize)\n      return false;\n    item.Extra.Alloc(extraSize);\n    memcpy(item.Extra, Get_Buf_Data(), extraSize);\n    Move_BufPos(extraSize);\n  }\n  \n  return Is_Buf_Finished();\n}\n\n\n\nstruct CLinkFile\n{\n  unsigned Index;\n  unsigned NumLinks; // the number of links to Data\n  CByteBuffer Data;\n  HRESULT Res;\n  bool crcOK;\n\n  CLinkFile(): Index(0), NumLinks(0), Res(S_OK), crcOK(true) {}\n};\n\n\nstruct CUnpacker\n{\n  CMyComPtr2<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr<ICompressCoder> LzCoders[2];\n  bool SolidAllowed;\n  bool NeedCrc;\n  CFilterCoder *filterStreamSpec;\n  CMyComPtr<ISequentialInStream> filterStream;\n  CMyComPtr2<ICompressFilter, NCrypto::NRar5::CDecoder> cryptoDecoder;\n  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n  CMyComPtr2<ISequentialOutStream, COutStreamWithHash> outStream;\n\n  CByteBuffer _tempBuf;\n  CLinkFile *linkFile;\n\n  CUnpacker(): linkFile(NULL) { SolidAllowed = false; NeedCrc = true; }\n\n  HRESULT Create(DECL_EXTERNAL_CODECS_LOC_VARS\n      const CItem &item, bool isSolid, bool &wrongPassword);\n\n  HRESULT Code(const CItem &item, const CItem &lastItem, UInt64 packSize,\n      ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress,\n      bool &isCrcOK);\n\n  HRESULT DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS\n      const CItem &item, UInt64 packSize, ISequentialInStream *inStream, CByteBuffer &buffer);\n};\n\n\nstatic const unsigned kLzMethodMax = 5;\n\nHRESULT CUnpacker::Create(DECL_EXTERNAL_CODECS_LOC_VARS\n    const CItem &item, bool isSolid, bool &wrongPassword)\n{\n  wrongPassword = false;\n\n  if (item.Get_AlgoVersion_RawBits() > 1)\n    return E_NOTIMPL;\n\n  outStream.Create_if_Empty();\n\n  const unsigned method = item.Get_Method();\n\n  if (method == 0)\n    copyCoder.Create_if_Empty();\n  else\n  {\n    if (method > kLzMethodMax)\n      return E_NOTIMPL;\n    /*\n    if (item.IsSplitBefore())\n      return S_FALSE;\n    */\n    const unsigned lzIndex = item.IsService() ? 1 : 0;\n    CMyComPtr<ICompressCoder> &lzCoder = LzCoders[lzIndex];\n    if (!lzCoder)\n    {\n      const UInt32 methodID = 0x40305;\n      RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS methodID, false, lzCoder))\n      if (!lzCoder)\n        return E_NOTIMPL;\n    }\n\n    CMyComPtr<ICompressSetDecoderProperties2> csdp;\n    RINOK(lzCoder.QueryInterface(IID_ICompressSetDecoderProperties2, &csdp))\n    if (!csdp)\n      return E_NOTIMPL;\n    const unsigned ver = item.Get_AlgoVersion_HuffRev();\n    if (ver > 1)\n      return E_NOTIMPL;\n    const Byte props[2] =\n    {\n      (Byte)item.Get_DictSize_Main(),\n      (Byte)((item.Get_DictSize_Frac() << 3) + (ver << 1) + (isSolid ? 1 : 0))\n    };\n    RINOK(csdp->SetDecoderProperties2(props, 2))\n  }\n\n  unsigned cryptoSize = 0;\n  const int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);\n\n  if (cryptoOffset >= 0)\n  {\n    if (!filterStream)\n    {\n      filterStreamSpec = new CFilterCoder(false);\n      filterStream = filterStreamSpec;\n    }\n\n    cryptoDecoder.Create_if_Empty();\n\n    RINOK(cryptoDecoder->SetDecoderProps(item.Extra + (unsigned)cryptoOffset, cryptoSize, true, item.IsService()))\n\n    if (!getTextPassword)\n    {\n      wrongPassword = True;\n      return E_NOTIMPL;\n    }\n\n    RINOK(MySetPassword(getTextPassword, cryptoDecoder.ClsPtr()))\n      \n    if (!cryptoDecoder->CalcKey_and_CheckPassword())\n      wrongPassword = True;\n  }\n\n  return S_OK;\n}\n\n\nHRESULT CUnpacker::Code(const CItem &item, const CItem &lastItem, UInt64 packSize,\n    ISequentialInStream *volsInStream, ISequentialOutStream *realOutStream, ICompressProgressInfo *progress,\n    bool &isCrcOK)\n{\n  isCrcOK = true;\n\n  const unsigned method = item.Get_Method();\n  if (method > kLzMethodMax)\n    return E_NOTIMPL;\n\n  const bool needBuf = (linkFile && linkFile->NumLinks != 0);\n\n  if (needBuf && !lastItem.Is_UnknownSize())\n  {\n    const size_t dataSize = (size_t)lastItem.Size;\n    if (dataSize != lastItem.Size)\n      return E_NOTIMPL;\n    linkFile->Data.Alloc(dataSize);\n  }\n\n  bool isCryptoMode = false;\n  ISequentialInStream *inStream;\n\n  if (item.IsEncrypted())\n  {\n    filterStreamSpec->Filter = cryptoDecoder;\n    filterStreamSpec->SetInStream(volsInStream);\n    filterStreamSpec->SetOutStreamSize(NULL);\n    inStream = filterStream;\n    isCryptoMode = true;\n  }\n  else\n    inStream = volsInStream;\n\n  ICompressCoder *commonCoder = (method == 0) ?\n      copyCoder.Interface() :\n      LzCoders[item.IsService() ? 1 : 0].Interface();\n\n  outStream->SetStream(realOutStream);\n  outStream->Init(lastItem, (needBuf ? (Byte *)linkFile->Data : NULL), NeedCrc);\n\n  HRESULT res = S_OK;\n  if (packSize != 0 || lastItem.Is_UnknownSize() || lastItem.Size != 0)\n  {\n    res = commonCoder->Code(inStream, outStream, &packSize,\n      lastItem.Is_UnknownSize() ? NULL : &lastItem.Size, progress);\n    if (!item.IsService())\n      SolidAllowed = true;\n  }\n  else\n  {\n    // res = res;\n  }\n\n  if (isCryptoMode)\n    filterStreamSpec->ReleaseInStream();\n\n  const UInt64 processedSize = outStream->GetPos();\n  if (res == S_OK && !lastItem.Is_UnknownSize() && processedSize != lastItem.Size)\n  {\n    // rar_v7.13-: linux archive contains symLink with (packSize == 0 && lastItem.Size != 0)\n    // v25.02: we ignore such record in rar headers:\n    if (packSize != 0\n        || method != 0\n        || lastItem.HostOS != kHost_Unix\n        || !MY_LIN_S_ISLNK(lastItem.Attrib))\n      res = S_FALSE;\n  }\n\n  // if (res == S_OK)\n  {\n    unsigned cryptoSize = 0;\n    const int cryptoOffset = lastItem.FindExtra(NExtraID::kCrypto, cryptoSize);\n    NCrypto::NRar5::CDecoder *crypto = NULL;\n    if (cryptoOffset >= 0)\n    {\n      CCryptoInfo cryptoInfo;\n      if (cryptoInfo.Parse(lastItem.Extra + (unsigned)cryptoOffset, cryptoSize))\n        if (cryptoInfo.UseMAC())\n          crypto = cryptoDecoder.ClsPtr();\n    }\n    if (NeedCrc)\n      isCrcOK =  outStream->_hash.Check(lastItem, crypto);\n  }\n\n  if (linkFile)\n  {\n    linkFile->Res = res;\n    linkFile->crcOK = isCrcOK;\n    if (needBuf\n        && !lastItem.Is_UnknownSize()\n        && processedSize != lastItem.Size)\n      linkFile->Data.ChangeSize_KeepData((size_t)processedSize, (size_t)processedSize);\n  }\n\n  return res;\n}\n\n\nHRESULT CUnpacker::DecodeToBuf(DECL_EXTERNAL_CODECS_LOC_VARS\n    const CItem &item, UInt64 packSize,\n    ISequentialInStream *inStream,\n    CByteBuffer &buffer)\n{\n  CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> out;\n  _tempBuf.AllocAtLeast((size_t)item.Size);\n  out->Init(_tempBuf, (size_t)item.Size);\n\n  bool wrongPassword;\n\n  if (item.IsSolid())\n    return E_NOTIMPL;\n\n  HRESULT res = Create(EXTERNAL_CODECS_LOC_VARS item, item.IsSolid(), wrongPassword);\n  \n  if (res == S_OK)\n  {\n    if (wrongPassword)\n      return S_FALSE;\n\n    CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> limitedStream;\n    limitedStream->SetStream(inStream);\n    limitedStream->Init(packSize);\n\n    bool crcOK = true;\n    res = Code(item, item, packSize, limitedStream, out, NULL, crcOK);\n    if (res == S_OK)\n    {\n      if (!crcOK || out->GetPos() != item.Size)\n        res = S_FALSE;\n      else\n        buffer.CopyFrom(_tempBuf, (size_t)item.Size);\n    }\n  }\n  \n  return res;\n}\n\n\nstruct CTempBuf\n{\n  CByteBuffer _buf;\n  size_t _offset;\n  bool _isOK;\n\n  void Clear()\n  {\n    _offset = 0;\n    _isOK = true;\n  }\n\n  CTempBuf() { Clear(); }\n\n  HRESULT Decode(DECL_EXTERNAL_CODECS_LOC_VARS\n      const CItem &item,\n      ISequentialInStream *inStream,\n      CUnpacker &unpacker,\n      CByteBuffer &destBuf);\n};\n\n\nHRESULT CTempBuf::Decode(DECL_EXTERNAL_CODECS_LOC_VARS\n    const CItem &item,\n    ISequentialInStream *inStream,\n    CUnpacker &unpacker,\n    CByteBuffer &destBuf)\n{\n  const size_t kPackSize_Max = (1 << 24);\n  if (item.Size > (1 << 24)\n      || item.Size == 0\n      || item.PackSize >= kPackSize_Max)\n  {\n    Clear();\n    return S_OK;\n  }\n\n  if (item.IsSplit() /* && _isOK */)\n  {\n    size_t packSize = (size_t)item.PackSize;\n    if (packSize > kPackSize_Max - _offset)\n      return S_OK;\n    size_t newSize = _offset + packSize;\n    if (newSize > _buf.Size())\n      _buf.ChangeSize_KeepData(newSize, _offset);\n    \n    Byte *data = (Byte *)_buf + _offset;\n    RINOK(ReadStream_FALSE(inStream, data, packSize))\n    \n    _offset += packSize;\n    \n    if (item.IsSplitAfter())\n    {\n      CHash hash;\n      hash.Init(item);\n      hash.Update(data, packSize);\n      _isOK = hash.Check(item, NULL); // RAR5 doesn't use HMAC for packed part\n    }\n  }\n  \n  if (_isOK)\n  {\n    if (!item.IsSplitAfter())\n    {\n      if (_offset == 0)\n      {\n        RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS\n            item, item.PackSize, inStream, destBuf))\n      }\n      else\n      {\n        CMyComPtr2_Create<ISequentialInStream, CBufInStream> bufInStream;\n        bufInStream->Init(_buf, _offset);\n        RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_LOC_VARS\n            item, _offset, bufInStream, destBuf))\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidAttrib,\n  // kpidPosixAttrib, // for debug\n\n  kpidIsAltStream,\n  kpidEncrypted,\n  kpidSolid,\n  kpidSplitBefore,\n  kpidSplitAfter,\n  kpidCRC,\n  kpidHostOS,\n  kpidMethod,\n  kpidCharacts,\n  kpidSymLink,\n  kpidHardLink,\n  kpidCopyLink,\n\n  kpidVolumeIndex\n};\n\n\nstatic const Byte kArcProps[] =\n{\n  kpidTotalPhySize,\n  kpidCharacts,\n  kpidEncrypted,\n  kpidSolid,\n  kpidNumBlocks,\n  kpidMethod,\n  kpidIsVolume,\n  kpidVolumeIndex,\n  kpidNumVolumes,\n  kpidName,\n  kpidCTime,\n  kpidComment\n};\n\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\n\nUInt64 CHandler::GetPackSize(unsigned refIndex) const\n{\n  UInt64 size = 0;\n  unsigned index = _refs[refIndex].Item;\n  for (;;)\n  {\n    const CItem &item = _items[index];\n    size += item.PackSize;\n    if (item.NextItem < 0)\n      return size;\n    index = (unsigned)item.NextItem;\n  }\n}\n\nstatic char *PrintDictSize(char *s, UInt64 w)\n{\n  char                               c = 'K'; w >>= 10;\n  if ((w & ((1 << 10) - 1)) == 0)  { c = 'M'; w >>= 10;\n  if ((w & ((1 << 10) - 1)) == 0)  { c = 'G'; w >>= 10; }}\n  s = ConvertUInt64ToString(w, s);\n  *s++ = c;\n  *s = 0;\n  return s;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n\n  NCOM::CPropVariant prop;\n\n  const CInArcInfo *arcInfo = NULL;\n  if (!_arcs.IsEmpty())\n    arcInfo = &_arcs[0].Info;\n\n  switch (propID)\n  {\n    case kpidVolumeIndex: if (arcInfo && arcInfo->IsVolume()) prop = arcInfo->GetVolIndex(); break;\n    case kpidSolid: if (arcInfo) prop = arcInfo->IsSolid(); break;\n    case kpidCharacts:\n    {\n      AString s;\n      if (arcInfo)\n      {\n        s = FlagsToString(k_ArcFlags, Z7_ARRAY_SIZE(k_ArcFlags), (UInt32)arcInfo->Flags);\n        if (arcInfo->Extra_Error)\n          s.Add_OptSpaced(\"Extra-ERROR\");\n        if (arcInfo->UnsupportedFeature)\n          s.Add_OptSpaced(\"unsupported-feature\");\n        if (arcInfo->Metadata_Defined)\n        {\n          s.Add_OptSpaced(\"Metadata\");\n          if (arcInfo->Metadata_Error)\n            s += \"-ERROR\";\n          else\n          {\n            if (arcInfo->Metadata.Flags & NMetadataFlags::kArcName)\n              s.Add_OptSpaced(\"arc-name\");\n            if (arcInfo->Metadata.Flags & NMetadataFlags::kCTime)\n            {\n              s.Add_OptSpaced(\"ctime-\");\n              s +=\n                (arcInfo->Metadata.Flags & NMetadataFlags::kUnixTime) ?\n                (arcInfo->Metadata.Flags & NMetadataFlags::kNanoSec) ?\n                    \"1ns\" : \"1s\" : \"win\";\n            }\n          }\n        }\n        if (arcInfo->Locator_Defined)\n        {\n          s.Add_OptSpaced(\"Locator\");\n          if (arcInfo->Locator_Error)\n            s += \"-ERROR\";\n          else\n          {\n            if (arcInfo->Locator.Is_QuickOpen())\n            {\n              s.Add_OptSpaced(\"QuickOpen:\");\n              s.Add_UInt64(arcInfo->Locator.QuickOpen);\n            }\n            if (arcInfo->Locator.Is_Recovery())\n            {\n              s.Add_OptSpaced(\"Recovery:\");\n              s.Add_UInt64(arcInfo->Locator.Recovery);\n            }\n          }\n        }\n        if (arcInfo->UnknownExtraRecord)\n          s.Add_OptSpaced(\"Unknown-Extra-Record\");\n\n      }\n      if (_comment_WasUsedInArc)\n      {\n        s.Add_OptSpaced(\"Comment\");\n        // s.Add_UInt32((UInt32)_comment.Size());\n      }\n      //\n      if (_acls.Size() != 0)\n      {\n        s.Add_OptSpaced(\"ACL\");\n        // s.Add_UInt32(_acls.Size());\n      }\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n    case kpidEncrypted: if (arcInfo) prop = arcInfo->IsEncrypted; break; // it's for encrypted names.\n    case kpidIsVolume: if (arcInfo) prop = arcInfo->IsVolume(); break;\n    case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break;\n    case kpidOffset: if (arcInfo && arcInfo->StartPos != 0) prop = arcInfo->StartPos; break;\n\n    case kpidTotalPhySize:\n    {\n      if (_arcs.Size() > 1)\n      {\n        UInt64 sum = 0;\n        FOR_VECTOR (v, _arcs)\n          sum += _arcs[v].Info.GetPhySize();\n        prop = sum;\n      }\n      break;\n    }\n\n    case kpidPhySize:\n    {\n      if (arcInfo)\n        prop = arcInfo->GetPhySize();\n      break;\n    }\n\n    case kpidName:\n      if (arcInfo)\n      if (!arcInfo->Metadata_Error\n          && !arcInfo->Metadata.ArcName.IsEmpty())\n      {\n        UString s;\n        if (ConvertUTF8ToUnicode(arcInfo->Metadata.ArcName, s))\n          prop = s;\n      }\n      break;\n\n    case kpidCTime:\n      if (arcInfo)\n      if (!arcInfo->Metadata_Error\n          && (arcInfo->Metadata.Flags & NMetadataFlags::kCTime))\n      {\n        const UInt64 ct = arcInfo->Metadata.CTime;\n        if (arcInfo->Metadata.Flags & NMetadataFlags::kUnixTime)\n        {\n          if (arcInfo->Metadata.Flags & NMetadataFlags::kNanoSec)\n          {\n            const UInt64 sec = ct / 1000000000;\n            const UInt64 ns  = ct % 1000000000;\n            UInt64 wt = NTime::UnixTime64_To_FileTime64((Int64)sec);\n            wt += ns / 100;\n            const unsigned ns100 = (unsigned)(ns % 100);\n            FILETIME ft;\n            ft.dwLowDateTime = (DWORD)(UInt32)wt;\n            ft.dwHighDateTime = (DWORD)(UInt32)(wt >> 32);\n            prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100);\n          }\n          else\n          {\n            const UInt64 wt = NTime::UnixTime64_To_FileTime64((Int64)ct);\n            prop.SetAsTimeFrom_Ft64_Prec(wt, k_PropVar_TimePrec_Unix);\n          }\n        }\n        else\n          prop.SetAsTimeFrom_Ft64_Prec(ct, k_PropVar_TimePrec_100ns);\n      }\n      break;\n\n    case kpidComment:\n    {\n      // if (!_arcs.IsEmpty())\n      {\n        // const CArc &arc = _arcs[0];\n        const CByteBuffer &cmt = _comment;\n        if (cmt.Size() != 0 /* && cmt.Size() < (1 << 16) */)\n        {\n          AString s;\n          s.SetFrom_CalcLen((const char *)(const Byte *)cmt, (unsigned)cmt.Size());\n          UString unicode;\n          ConvertUTF8ToUnicode(s, unicode);\n          prop = unicode;\n        }\n      }\n      break;\n    }\n\n    case kpidNumBlocks:\n    {\n      prop = (UInt32)_numBlocks;\n      break;\n    }\n\n    case kpidMethod:\n    {\n      AString s;\n\n      UInt64 algo = _algo_Mask;\n      for (unsigned v = 0; algo != 0; v++, algo >>= 1)\n      {\n        if ((algo & 1) == 0)\n          continue;\n        s.Add_OptSpaced(\"v\");\n        s.Add_UInt32(v + 6);\n        if (v < Z7_ARRAY_SIZE(_methodMasks))\n        {\n          const UInt64 dict = _dictMaxSizes[v];\n          if (dict)\n          {\n            char temp[24];\n            temp[0] = ':';\n            PrintDictSize(temp + 1, dict);\n            s += temp;\n          }\n          unsigned method = _methodMasks[v];\n          for (unsigned m = 0; method; m++, method >>= 1)\n          {\n            if ((method & 1) == 0)\n              continue;\n            s += \":m\";\n            s.Add_UInt32(m);\n          }\n        }\n      }\n      if (_rar5comapt_mask & 2)\n      {\n        s += \":c\";\n        if (_rar5comapt_mask & 1)\n          s.Add_Char('n');\n      }\n      prop = s;\n      break;\n    }\n    \n    case kpidError:\n    {\n      if (/* &_missingVol || */ !_missingVolName.IsEmpty())\n      {\n        UString s (\"Missing volume : \");\n        s += _missingVolName;\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = _errorFlags;\n      if (!_isArc)\n        v |= kpv_ErrorFlags_IsNotArc;\n      if (_error_in_ACL)\n        v |= kpv_ErrorFlags_HeadersError;\n      if (_split_Error)\n        v |= kpv_ErrorFlags_HeadersError;\n      prop = v;\n      break;\n    }\n\n    /*\n    case kpidWarningFlags:\n    {\n      if (_warningFlags != 0)\n        prop = _warningFlags;\n      break;\n    }\n    */\n\n    case kpidExtension:\n      if (_arcs.Size() == 1)\n      {\n        if (arcInfo->IsVolume())\n        {\n          AString s (\"part\");\n          UInt32 v = (UInt32)arcInfo->GetVolIndex() + 1;\n          if (v < 10)\n            s.Add_Char('0');\n          s.Add_UInt32(v);\n          s += \".rar\";\n          prop = s;\n        }\n      }\n      break;\n\n    case kpidIsAltStream: prop = true; break;\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  \n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = (UInt32)_refs.Size();\n  return S_OK;\n}\n\n\nstatic const Byte kRawProps[] =\n{\n  kpidChecksum,\n  kpidNtSecure\n};\n\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = Z7_ARRAY_SIZE(kRawProps);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))\n{\n  *propID = kRawProps[index];\n  *name = NULL;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  *parentType = NParentType::kDir;\n  *parent = (UInt32)(Int32)-1;\n\n  if (index >= _refs.Size())\n    return S_OK;\n\n  const CRefItem &ref = _refs[index];\n  const CItem &item = _items[ref.Item];\n\n  if (item.Is_STM() && ref.Parent >= 0)\n  {\n    *parent = (UInt32)ref.Parent;\n    *parentType = NParentType::kAltStream;\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n\n  if (index >= _refs.Size())\n    return E_INVALIDARG;\n\n  const CItem &item = _items[_refs[index].Item];\n\n  if (propID == kpidNtSecure)\n  {\n    if (item.ACL >= 0)\n    {\n      const CByteBuffer &buf = _acls[item.ACL];\n      *dataSize = (UInt32)buf.Size();\n      *propType = NPropDataType::kRaw;\n      *data = (const Byte *)buf;\n    }\n    return S_OK;\n  }\n  \n  if (propID == kpidChecksum)\n  {\n    const int hashRecOffset = item.FindExtra_Blake();\n    if (hashRecOffset >= 0)\n    {\n      *dataSize = Z7_BLAKE2S_DIGEST_SIZE;\n      *propType = NPropDataType::kRaw;\n      *data = item.Extra + (unsigned)hashRecOffset;\n    }\n    /*\n    else if (item.Has_CRC() && item.IsEncrypted())\n    {\n      *dataSize = 4;\n      *propType = NPropDataType::kRaw;\n      *data = &item->CRC; // we must show same value for big/little endian here\n    }\n    */\n    return S_OK;\n  }\n  \n  return S_OK;\n}\n\n\nstatic void TimeRecordToProp(const CItem &item, unsigned stampIndex, NCOM::CPropVariant &prop)\n{\n  unsigned size;\n  const int offset = item.FindExtra(NExtraID::kTime, size);\n  if (offset < 0)\n    return;\n\n  const Byte *p = item.Extra + (unsigned)offset;\n  UInt64 flags;\n  // PARSE_VAR_INT(p, size, flags)\n  {\n    const unsigned num = ReadVarInt(p, size, &flags);\n    if (num == 0)\n      return;\n    p += num;\n    size -= num;\n  }\n\n  if ((flags & (NTimeRecord::NFlags::kMTime << stampIndex)) == 0)\n    return;\n  \n  unsigned numStamps = 0;\n  unsigned curStamp = 0;\n\n  for (unsigned i = 0; i < 3; i++)\n    if ((flags & (NTimeRecord::NFlags::kMTime << i)) != 0)\n    {\n      if (i == stampIndex)\n        curStamp = numStamps;\n      numStamps++;\n    }\n\n  FILETIME ft;\n\n  unsigned timePrec = 0;\n  unsigned ns100 = 0;\n\n  if ((flags & NTimeRecord::NFlags::kUnixTime) != 0)\n  {\n    curStamp *= 4;\n    if (curStamp + 4 > size)\n      return;\n    p += curStamp;\n    UInt64 val = NTime::UnixTime_To_FileTime64(Get32(p));\n    numStamps *= 4;\n    timePrec = k_PropVar_TimePrec_Unix;\n    if ((flags & NTimeRecord::NFlags::kUnixNs) != 0 && numStamps * 2 <= size)\n    {\n      const UInt32 ns = Get32(p + numStamps) & 0x3FFFFFFF;\n      if (ns < 1000000000)\n      {\n        val += ns / 100;\n        ns100 = (unsigned)(ns % 100);\n        timePrec = k_PropVar_TimePrec_1ns;\n      }\n    }\n    ft.dwLowDateTime = (DWORD)val;\n    ft.dwHighDateTime = (DWORD)(val >> 32);\n  }\n  else\n  {\n    curStamp *= 8;\n    if (curStamp + 8 > size)\n      return;\n    p += curStamp;\n    ft.dwLowDateTime = Get32(p);\n    ft.dwHighDateTime = Get32(p + 4);\n  }\n  \n  prop.SetAsTimeFrom_FT_Prec_Ns100(ft, timePrec, ns100);\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  \n  NCOM::CPropVariant prop;\n  const CRefItem &ref = _refs[index];\n  const CItem &item = _items[ref.Item];\n  const CItem &lastItem = _items[ref.Last];\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      UString unicodeName;\n      \n      if (item.Is_STM())\n      {\n        AString s;\n        if (ref.Parent >= 0)\n        {\n          const CItem &mainItem = _items[_refs[ref.Parent].Item];\n          s = mainItem.Name;\n        }\n\n        AString name;\n        item.GetAltStreamName(name);\n        if (name[0] != ':')\n          s.Add_Colon();\n        s += name;\n        ConvertUTF8ToUnicode(s, unicodeName);\n      }\n      else\n      {\n        ConvertUTF8ToUnicode(item.Name, unicodeName);\n\n        if (item.Version_Defined)\n        {\n          char temp[32];\n          // temp[0] = ';';\n          // ConvertUInt64ToString(item.Version, temp + 1);\n          // unicodeName += temp;\n          ConvertUInt64ToString(item.Version, temp);\n          UString s2 (\"[VER]\" STRING_PATH_SEPARATOR);\n          s2 += temp;\n          s2.Add_PathSepar();\n          unicodeName.Insert(0, s2);\n        }\n      }\n      \n      NItemName::ReplaceToOsSlashes_Remove_TailSlash(unicodeName);\n      prop = unicodeName;\n\n      break;\n    }\n    \n    case kpidIsDir: prop = item.IsDir(); break;\n    case kpidSize: if (!lastItem.Is_UnknownSize()) prop = lastItem.Size; break;\n    case kpidPackSize: prop = GetPackSize((unsigned)index); break;\n    \n    case kpidMTime:\n    {\n      TimeRecordToProp(item, NTimeRecord::k_Index_MTime, prop);\n      if (prop.vt == VT_EMPTY && item.Has_UnixMTime())\n        PropVariant_SetFrom_UnixTime(prop, item.UnixMTime);\n      if (prop.vt == VT_EMPTY && ref.Parent >= 0)\n      {\n        const CItem &baseItem = _items[_refs[ref.Parent].Item];\n        TimeRecordToProp(baseItem, NTimeRecord::k_Index_MTime, prop);\n        if (prop.vt == VT_EMPTY && baseItem.Has_UnixMTime())\n          PropVariant_SetFrom_UnixTime(prop, baseItem.UnixMTime);\n      }\n      break;\n    }\n    case kpidCTime: TimeRecordToProp(item, NTimeRecord::k_Index_CTime, prop); break;\n    case kpidATime: TimeRecordToProp(item, NTimeRecord::k_Index_ATime, prop); break;\n\n    case kpidName:\n    {\n      if (item.Is_STM())\n      {\n        AString name;\n        item.GetAltStreamName(name);\n        if (name[0] == ':')\n        {\n          name.DeleteFrontal(1);\n          UString unicodeName;\n          ConvertUTF8ToUnicode(name, unicodeName);\n          prop = unicodeName;\n        }\n      }\n      break;\n    }\n\n    case kpidIsAltStream: prop = item.Is_STM(); break;\n\n    case kpidSymLink: item.Link_to_Prop(NLinkType::kUnixSymLink, prop); break;\n    case kpidHardLink: item.Link_to_Prop(NLinkType::kHardLink, prop); break;\n    case kpidCopyLink: item.Link_to_Prop(NLinkType::kFileCopy, prop); break;\n\n    case kpidAttrib: prop = item.GetWinAttrib(); break;\n    case kpidPosixAttrib:\n      if (item.HostOS == kHost_Unix)\n        prop = (UInt32)item.Attrib;\n      break;\n\n    case kpidEncrypted: prop = item.IsEncrypted(); break;\n    case kpidSolid: prop = item.IsSolid(); break;\n\n    case kpidSplitBefore: prop = item.IsSplitBefore(); break;\n    case kpidSplitAfter: prop = lastItem.IsSplitAfter(); break;\n\n    case kpidVolumeIndex:\n    {\n      if (item.VolIndex < _arcs.Size())\n      {\n        const CInArcInfo &arcInfo = _arcs[item.VolIndex].Info;\n        if (arcInfo.IsVolume())\n          prop = (UInt64)arcInfo.GetVolIndex();\n      }\n      break;\n    }\n\n    case kpidCRC:\n    {\n      const CItem *item2 = (lastItem.IsSplitAfter() ? &item : &lastItem);\n      // we don't want to show crc for encrypted file here,\n      // because crc is also encrrypted.\n      if (item2->Has_CRC() && !item2->IsEncrypted())\n        prop = item2->CRC;\n      break;\n    }\n\n    case kpidMethod:\n    {\n      char temp[128];\n      const unsigned algo = item.Get_AlgoVersion_RawBits();\n      char *s = temp;\n      // if (algo != 0)\n      {\n        *s++ = 'v';\n        s = ConvertUInt32ToString((UInt32)algo + 6, s);\n        if (item.Is_Rar5_Compat())\n          *s++ = 'c';\n        *s++ = ':';\n      }\n      {\n        const unsigned m = item.Get_Method();\n        *s++ = 'm';\n        *s++ = (char)(m + '0');\n        if (!item.IsDir())\n        {\n          *s++ = ':';\n          const unsigned dictMain = item.Get_DictSize_Main();\n          const unsigned frac = item.Get_DictSize_Frac();\n          /*\n          if (frac == 0 && algo == 0)\n            s = ConvertUInt32ToString(dictMain + 17, s);\n          else\n          */\n          s = PrintDictSize(s, (UInt64)(32 + frac) << (12 + dictMain));\n          if (item.Is_Rar5_Compat())\n          {\n            *s++ = ':';\n            *s++ = 'c';\n          }\n        }\n      }\n      unsigned cryptoSize = 0;\n      const int cryptoOffset = item.FindExtra(NExtraID::kCrypto, cryptoSize);\n      if (cryptoOffset >= 0)\n      {\n        *s++ = ' ';\n        CCryptoInfo cryptoInfo;\n        const bool isOK = cryptoInfo.Parse(item.Extra + (unsigned)cryptoOffset, cryptoSize);\n        if (cryptoInfo.Algo == 0)\n          s = MyStpCpy(s, \"AES\");\n        else\n        {\n          s = MyStpCpy(s, \"Crypto_\");\n          s = ConvertUInt64ToString(cryptoInfo.Algo, s);\n        }\n        if (isOK)\n        {\n          *s++ = ':';\n          s = ConvertUInt32ToString(cryptoInfo.Cnt, s);\n          *s++ = ':';\n          s = ConvertUInt64ToString(cryptoInfo.Flags, s);\n        }\n      }\n      *s = 0;\n      prop = temp;\n      break;\n    }\n    \n    case kpidCharacts:\n    {\n      AString s;\n\n      if (item.ACL >= 0)\n        s.Add_OptSpaced(\"ACL\");\n\n      const UInt32 flags = item.Flags;\n      if (flags != 0)\n      {\n        const AString s2 = FlagsToString(k_FileFlags, Z7_ARRAY_SIZE(k_FileFlags), flags);\n        if (!s2.IsEmpty())\n          s.Add_OptSpaced(s2);\n      }\n\n      item.PrintInfo(s);\n    \n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n\n    case kpidHostOS:\n      if (item.HostOS < Z7_ARRAY_SIZE(kHostOS))\n        prop = kHostOS[(size_t)item.HostOS];\n      else\n        prop = (UInt64)item.HostOS;\n      break;\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  \n  COM_TRY_END\n}\n\n\n\n// ---------- Copy Links ----------\n\nstatic int CompareItemsPaths(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)\n{\n  const CItem &item1 = handler._items[handler._refs[p1].Item];\n  const CItem &item2 = handler._items[handler._refs[p2].Item];\n  \n  if (item1.Version_Defined)\n  {\n    if (!item2.Version_Defined)\n      return -1;\n    const int res = MyCompare(item1.Version, item2.Version);\n    if (res != 0)\n      return res;\n  }\n  else if (item2.Version_Defined)\n    return 1;\n\n  if (!name1)\n    name1 = &item1.Name;\n  return strcmp(*name1, item2.Name);\n}\n\nstatic int CompareItemsPaths2(const CHandler &handler, unsigned p1, unsigned p2, const AString *name1)\n{\n  const int res = CompareItemsPaths(handler, p1, p2, name1);\n  if (res != 0)\n    return res;\n  return MyCompare(p1, p2);\n}\n\nstatic int CompareItemsPaths_Sort(const unsigned *p1, const unsigned *p2, void *param)\n{\n  return CompareItemsPaths2(*(const CHandler *)param, *p1, *p2, NULL);\n}\n\nstatic int FindLink(const CHandler &handler, const CUIntVector &sorted,\n    const AString &s, unsigned index)\n{\n  unsigned left = 0, right = sorted.Size();\n  for (;;)\n  {\n    if (left == right)\n    {\n      if (left > 0)\n      {\n        const unsigned refIndex = sorted[left - 1];\n        if (CompareItemsPaths(handler, index, refIndex, &s) == 0)\n          return (int)refIndex;\n      }\n      if (right < sorted.Size())\n      {\n        const unsigned refIndex = sorted[right];\n        if (CompareItemsPaths(handler, index, refIndex, &s) == 0)\n          return (int)refIndex;\n      }\n      return -1;\n    }\n\n    const unsigned mid = (left + right) / 2;\n    const unsigned refIndex = sorted[mid];\n    const int compare = CompareItemsPaths2(handler, index, refIndex, &s);\n    if (compare == 0)\n      return (int)refIndex;\n    if (compare < 0)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n}\n\nvoid CHandler::FillLinks()\n{\n  unsigned i;\n\n  bool need_FillLinks = false;\n\n  for (i = 0; i < _refs.Size(); i++)\n  {\n    const CItem &item = _items[_refs[i].Item];\n    if (!item.IsDir()\n        && !item.IsService()\n        && item.NeedUse_as_CopyLink())\n      need_FillLinks = true;\n\n    if (!item.IsSolid())\n      _numBlocks++;\n\n    const unsigned algo = item.Get_AlgoVersion_RawBits();\n    _algo_Mask |= (UInt64)1 << algo;\n    _rar5comapt_mask |= 1u << item.Get_Rar5_CompatBit();\n    if (!item.IsDir() && algo < Z7_ARRAY_SIZE(_methodMasks))\n    {\n      _methodMasks[algo] |= 1u << (item.Get_Method());\n      UInt64 d = 32 + item.Get_DictSize_Frac();\n      d <<= (12 + item.Get_DictSize_Main());\n      if (_dictMaxSizes[algo] < d)\n          _dictMaxSizes[algo] = d;\n    }\n  }\n\n  if (!need_FillLinks)\n    return;\n  \n  CUIntVector sorted;\n  for (i = 0; i < _refs.Size(); i++)\n  {\n    const CItem &item = _items[_refs[i].Item];\n    if (!item.IsDir() && !item.IsService())\n      sorted.Add(i);\n  }\n  \n  if (sorted.IsEmpty())\n    return;\n  \n  sorted.Sort(CompareItemsPaths_Sort, (void *)this);\n  \n  AString link;\n  \n  for (i = 0; i < _refs.Size(); i++)\n  {\n    CRefItem &ref = _refs[i];\n    const CItem &item = _items[ref.Item];\n    if (item.IsDir() || item.IsService() || item.PackSize != 0)\n      continue;\n    CLinkInfo linkInfo;\n    if (!item.FindExtra_Link(linkInfo) || linkInfo.Type != NLinkType::kFileCopy)\n      continue;\n    link.SetFrom_CalcLen((const char *)(item.Extra + linkInfo.NameOffset), linkInfo.NameLen);\n    const int linkIndex = FindLink(*this, sorted, link, i);\n    if (linkIndex < 0)\n      continue;\n    if ((unsigned)linkIndex >= i)\n      continue; // we don't support forward links that can lead to loops\n    const CRefItem &linkRef = _refs[linkIndex];\n    const CItem &linkItem = _items[linkRef.Item];\n    if (linkItem.Size == item.Size)\n    {\n      if (linkRef.Link >= 0)\n        ref.Link = linkRef.Link;\n      else if (!linkItem.NeedUse_as_CopyLink())\n        ref.Link = linkIndex;\n    }\n  }\n}\n\n\n\nHRESULT CHandler::Open2(IInStream *stream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *openCallback)\n{\n  CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\n  // CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n  NRar::CVolumeName seqName;\n  CTempBuf tempBuf;\n  CUnpacker unpacker;\n  \n  if (openCallback)\n  {\n    openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\n    openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword);\n  }\n  // unpacker.getTextPassword = getTextPassword;\n  \n  CInArchive arch;\n  int prevSplitFile = -1;\n  int prevMainFile = -1;\n  UInt64 totalBytes = 0;\n  UInt64 curBytes = 0;\n  bool nextVol_is_Required = false;\n  \n  for (;;)\n  {\n    CMyComPtr<IInStream> inStream;\n    \n    if (_arcs.IsEmpty())\n      inStream = stream;\n    else\n    {\n      if (!openVolumeCallback)\n        break;\n      if (_arcs.Size() == 1)\n      {\n        UString baseName;\n        {\n          NCOM::CPropVariant prop;\n          RINOK(openVolumeCallback->GetProperty(kpidName, &prop))\n          if (prop.vt != VT_BSTR)\n            break;\n          baseName = prop.bstrVal;\n        }\n        if (!seqName.InitName(baseName))\n          break;\n      }\n      const UString volName = seqName.GetNextName();\n      const HRESULT result = openVolumeCallback->GetStream(volName, &inStream);\n      if (result != S_OK && result != S_FALSE)\n        return result;\n      if (!inStream || result != S_OK)\n      {\n        if (nextVol_is_Required)\n          _missingVolName = volName;\n        break;\n      }\n    }\n    \n    UInt64 endPos = 0;\n    RINOK(InStream_GetPos_GetSize(inStream, arch.StreamStartPosition, endPos))\n    \n    if (openCallback)\n    {\n      totalBytes += endPos;\n      RINOK(openCallback->SetTotal(NULL, &totalBytes))\n    }\n    \n    CInArcInfo arcInfo_Open;\n    {\n      const HRESULT res = arch.Open(inStream, maxCheckStartPosition, unpacker.getTextPassword, arcInfo_Open);\n      if (arch.IsArc && arch.UnexpectedEnd)\n        _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_arcs.IsEmpty())\n        _isArc = arch.IsArc;\n      if (res != S_OK)\n      {\n        if (res != S_FALSE)\n          return res;\n        if (_arcs.IsEmpty())\n          return res;\n        break;\n      }\n    }\n    \n    CArc &arc = _arcs.AddNew();\n    CInArcInfo &arcInfo = arc.Info;\n    arcInfo = arcInfo_Open;\n    arc.Stream = inStream;\n    \n    CItem item;\n    \n    for (;;)\n    {\n      item.Clear();\n      \n      arcInfo.EndPos = arch.Position;\n      if (arch.Position > endPos)\n      {\n        _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;\n        break;\n      }\n      RINOK(InStream_SeekSet(inStream, arch.Position))\n      \n      {\n        CInArchive::CHeader h;\n        const HRESULT res = arch.ReadBlockHeader(h);\n        if (res != S_OK)\n        {\n          if (res != S_FALSE)\n            return res;\n          if (arch.UnexpectedEnd)\n          {\n            _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;\n            if (arcInfo.EndPos < arch.Position)\n                arcInfo.EndPos = arch.Position;\n            if (arcInfo.EndPos < endPos)\n                arcInfo.EndPos = endPos;\n          }\n          else\n            _errorFlags |= kpv_ErrorFlags_HeadersError;\n          break;\n        }\n        \n        if (h.Type == NHeaderType::kEndOfArc)\n        {\n          arcInfo.EndPos = arch.Position;\n          arcInfo.EndOfArchive_was_Read = true;\n          if (!arch.ReadVar(arcInfo.EndFlags))\n            _errorFlags |= kpv_ErrorFlags_HeadersError;\n          if (!arch.Is_Buf_Finished() || h.ExtraSize || h.DataSize)\n            arcInfo.UnsupportedFeature = true;\n          if (arcInfo.IsVolume())\n          {\n            // for multivolume archives RAR can add ZERO bytes at the end for alignment.\n            // We must skip these bytes to prevent phySize warning.\n            RINOK(InStream_SeekSet(inStream, arcInfo.EndPos))\n            bool areThereNonZeros;\n            UInt64 numZeros;\n            const UInt64 maxSize = 1 << 12;\n            RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize))\n            if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)\n              arcInfo.EndPos += numZeros;\n          }\n          break;\n        }\n        \n        if (h.Type != NHeaderType::kFile &&\n            h.Type != NHeaderType::kService)\n        {\n          _errorFlags |= kpv_ErrorFlags_UnsupportedFeature;\n          break;\n        }\n        \n        item.RecordType = (Byte)h.Type;\n        if (!arch.ReadFileHeader(h, item))\n        {\n          _errorFlags |= kpv_ErrorFlags_HeadersError;\n          break;\n        }\n        item.DataPos = arch.Position;\n      }\n      \n      bool isOk_packSize = true;\n      {\n        arcInfo.EndPos = arch.Position;\n        if (arch.Position + item.PackSize < arch.Position)\n        {\n          isOk_packSize = false;\n          _errorFlags |= kpv_ErrorFlags_HeadersError;\n          if (arcInfo.EndPos < endPos)\n              arcInfo.EndPos = endPos;\n        }\n        else\n        {\n          arch.AddToSeekValue(item.PackSize); // Position points to next header;\n          arcInfo.EndPos = arch.Position;\n        }\n      }\n\n      bool needAdd = true;\n\n      if (!_comment_WasUsedInArc\n          && _comment.Size() == 0\n          && item.Is_CMT())\n      {\n        _comment_WasUsedInArc = true;\n        if (   item.PackSize <= kCommentSize_Max\n            && item.PackSize == item.Size\n            && item.PackSize != 0\n            && item.Get_Method() == 0\n            && !item.IsSplit())\n        {\n          RINOK(unpacker.DecodeToBuf(EXTERNAL_CODECS_VARS item, item.PackSize, inStream, _comment))\n          needAdd = false;\n          // item.RecordType = (Byte)NHeaderType::kFile; // for debug\n        }\n      }\n\n      CRefItem ref;\n      ref.Item = _items.Size();\n      ref.Last = ref.Item;\n      ref.Parent = -1;\n      ref.Link = -1;\n      \n      if (needAdd)\n      {\n        if (item.IsService())\n        {\n          if (item.Is_STM())\n          {\n            if (prevMainFile >= 0)\n              ref.Parent = prevMainFile;\n          }\n          else\n          {\n            needAdd = false;\n            if (item.Is_ACL())\n            {\n              _acl_Used = true;\n              if (item.IsEncrypted() && !arch.m_CryptoMode)\n                _error_in_ACL = true;\n              else if (item.IsSolid()\n                  || prevMainFile < 0\n                  || item.Size >= (1 << 24)\n                  || item.Size == 0)\n                _error_in_ACL = true;\n              if (prevMainFile >= 0 && item.Size < (1 << 24) && item.Size != 0)\n              {\n                CItem &mainItem = _items[_refs[prevMainFile].Item];\n                \n                if (mainItem.ACL < 0)\n                {\n                  CByteBuffer acl;\n                  const HRESULT res = tempBuf.Decode(EXTERNAL_CODECS_VARS item, inStream, unpacker, acl);\n                  if (!item.IsSplitAfter())\n                    tempBuf.Clear();\n                  if (res != S_OK)\n                  {\n                    tempBuf.Clear();\n                    if (res != S_FALSE && res != E_NOTIMPL)\n                      return res;\n                    _error_in_ACL = true;\n                  }\n                  else if (acl.Size() != 0)\n                  {\n                    if (_acls.IsEmpty() || acl != _acls.Back())\n                      _acls.Add(acl);\n                    mainItem.ACL = (int)_acls.Size() - 1;\n                  }\n                }\n              }\n            }\n          }\n        } // item.IsService()\n        \n        if (needAdd)\n        {\n          if (item.IsSplitBefore())\n          {\n            if (prevSplitFile >= 0)\n            {\n              CRefItem &ref2 = _refs[prevSplitFile];\n              CItem &prevItem = _items[ref2.Last];\n              if (item.IsNextForItem(prevItem))\n              {\n                ref2.Last = _items.Size();\n                prevItem.NextItem = (int)ref2.Last;\n                needAdd = false;\n              }\n            }\n            else\n              _split_Error = true;\n          }\n        }\n        \n        if (needAdd)\n        {\n          if (item.IsSplitAfter())\n            prevSplitFile = (int)_refs.Size();\n          if (!item.IsService())\n            prevMainFile = (int)_refs.Size();\n        }\n      }\n      \n      {\n        UInt64 version;\n        if (item.FindExtra_Version(version))\n        {\n          item.Version_Defined = true;\n          item.Version = version;\n        }\n      }\n      \n      item.VolIndex = _arcs.Size() - 1;\n      _items.Add(item);\n      if (needAdd)\n        _refs.Add(ref);\n      \n      if (openCallback && (_items.Size() & 0xFF) == 0)\n      {\n        const UInt64 numFiles = _refs.Size(); // _items.Size()\n        const UInt64 numBytes = curBytes + item.DataPos;\n        RINOK(openCallback->SetCompleted(&numFiles, &numBytes))\n      }\n\n      if (!isOk_packSize)\n        break;\n    }\n      \n    curBytes += endPos;\n\n    nextVol_is_Required = false;\n\n    if (!arcInfo.IsVolume())\n      break;\n\n    if (arcInfo.EndOfArchive_was_Read)\n    {\n      if (!arcInfo.AreMoreVolumes())\n        break;\n      nextVol_is_Required = true;\n    }\n  }\n\n  FillLinks();\n  return S_OK;\n}\n\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *openCallback))\n{\n  COM_TRY_BEGIN\n  Close();\n  return Open2(stream, maxCheckStartPosition, openCallback);\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  COM_TRY_BEGIN\n  _missingVolName.Empty();\n  _errorFlags = 0;\n  // _warningFlags = 0;\n  _isArc = false;\n  _comment_WasUsedInArc = false;\n  _acl_Used = false;\n  _error_in_ACL = false;\n  _split_Error = false;\n  _numBlocks = 0;\n  _rar5comapt_mask = 0;\n  _algo_Mask = 0; // (UInt64)0u - 1;\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(_methodMasks); i++)\n  {\n    _methodMasks[i] = 0;\n    _dictMaxSizes[i] = 0;\n  }\n\n  _refs.Clear();\n  _items.Clear();\n  _arcs.Clear();\n  _acls.Clear();\n  _comment.Free();\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CVolsInStream\n  , ISequentialInStream\n)\n  UInt64 _rem;\n  ISequentialInStream *_stream;\n  const CObjectVector<CArc> *_arcs;\n  const CObjectVector<CItem> *_items;\n  int _itemIndex;\npublic:\n  bool CrcIsOK;\nprivate:\n  CHash _hash;\npublic:\n  void Init(const CObjectVector<CArc> *arcs,\n      const CObjectVector<CItem> *items,\n      unsigned itemIndex)\n  {\n    _arcs = arcs;\n    _items = items;\n    _itemIndex = (int)itemIndex;\n    _stream = NULL;\n    CrcIsOK = true;\n  }\n};\n\nZ7_COM7F_IMF(CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  UInt32 realProcessedSize = 0;\n\n  while (size != 0)\n  {\n    if (!_stream)\n    {\n      if (_itemIndex < 0)\n        break;\n      const CItem &item = (*_items)[_itemIndex];\n      IInStream *s = (*_arcs)[item.VolIndex].Stream;\n      RINOK(InStream_SeekSet(s, item.GetDataPosition()))\n      _stream = s;\n      if (CrcIsOK && item.IsSplitAfter())\n        _hash.Init(item);\n      else\n        _hash.Init_NoCalc();\n      _rem = item.PackSize;\n    }\n    {\n      UInt32 cur = size;\n      if (cur > _rem)\n        cur = (UInt32)_rem;\n      const UInt32 num = cur;\n      HRESULT res = _stream->Read(data, cur, &cur);\n      _hash.Update(data, cur);\n      realProcessedSize += cur;\n      if (processedSize)\n        *processedSize = realProcessedSize;\n      data = (Byte *)data + cur;\n      size -= cur;\n      _rem -= cur;\n      if (_rem == 0)\n      {\n        const CItem &item = (*_items)[_itemIndex];\n        _itemIndex = item.NextItem;\n        if (!_hash.Check(item, NULL)) // RAR doesn't use MAC here\n          CrcIsOK = false;\n        _stream = NULL;\n      }\n      if (res != S_OK)\n        return res;\n      if (realProcessedSize != 0)\n        return S_OK;\n      if (cur == 0 && num != 0)\n        return S_OK;\n    }\n  }\n  \n  return S_OK;\n}\n\n\nstatic int FindLinkBuf(CObjectVector<CLinkFile> &linkFiles, unsigned index)\n{\n  unsigned left = 0, right = linkFiles.Size();\n  for (;;)\n  {\n    if (left == right)\n      return -1;\n    const unsigned mid = (left + right) / 2;\n    const unsigned linkIndex = linkFiles[mid].Index;\n    if (index == linkIndex)\n      return (int)mid;\n    if (index < linkIndex)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n}\n\n\nstatic inline int DecoderRes_to_OpRes(HRESULT res, bool crcOK)\n{\n  if (res == E_NOTIMPL)\n    return NExtract::NOperationResult::kUnsupportedMethod;\n  // if (res == S_FALSE)\n  if (res != S_OK)\n    return NExtract::NOperationResult::kDataError;\n  return crcOK ?\n    NExtract::NOperationResult::kOK :\n    NExtract::NOperationResult::kCRCError;\n}\n\n\nstatic HRESULT CopyData_with_Progress(const Byte *data, size_t size,\n    ISequentialOutStream *outStream, ICompressProgressInfo *progress)\n{\n  UInt64 pos64 = 0;\n  while (size)\n  {\n    const UInt32 kStepSize = (UInt32)1 << 24;\n    UInt32 cur = kStepSize;\n    if (cur > size)\n      cur = (UInt32)size;\n    RINOK(outStream->Write(data, cur, &cur))\n    if (cur == 0)\n      return E_FAIL;\n    size -= cur;\n    data += cur;\n    pos64 += cur;\n    if (progress)\n    {\n      RINOK(progress->SetRatioInfo(&pos64, &pos64))\n    }\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = (UInt32)_refs.Size();\n  if (numItems == 0)\n    return S_OK;\n  \n  CByteArr extractStatuses(_refs.Size());\n  memset(extractStatuses, 0, _refs.Size());\n\n  // we don't want to use temp buffer for big link files.\n  const size_t k_CopyLinkFile_MaxSize = (size_t)1 << (28 + sizeof(size_t) / 2);\n\n  const Byte kStatus_Extract = 1 << 0;\n  const Byte kStatus_Skip = 1 << 1;\n  const Byte kStatus_Link = 1 << 2;\n\n  /*\n    In original RAR:\n    1) service streams are not allowed to be solid,\n        and solid flag must be ignored for service streams.\n    2) If RAR creates new solid block and first file in solid block is Link file,\n         then it can clear solid flag for Link file and\n         clear solid flag for first non-Link file after Link file.\n  */\n\n  CObjectVector<CLinkFile> linkFiles;\n\n  {\n    UInt64 total = 0;\n    bool isThereUndefinedSize = false;\n    bool thereAreLinks = false;\n    {\n      unsigned solidLimit = 0;\n      for (UInt32 t = 0; t < numItems; t++)\n      {\n        const unsigned index = (unsigned)(allFilesMode ? t : indices[t]);\n        const CRefItem &ref = _refs[index];\n        const CItem &item = _items[ref.Item];\n        const CItem &lastItem = _items[ref.Last];\n        \n        extractStatuses[index] |= kStatus_Extract;\n\n        if (!lastItem.Is_UnknownSize())\n          total += lastItem.Size;\n        else\n          isThereUndefinedSize = true;\n        \n        if (ref.Link >= 0)\n        {\n          // 18.06 fixed: we use links for Test mode too\n          // if (!testMode)\n          {\n            if ((unsigned)ref.Link < index)\n            {\n              const CRefItem &linkRef = _refs[(unsigned)ref.Link];\n              const CItem &linkItem = _items[linkRef.Item];\n              if (linkItem.IsSolid())\n              if (testMode || linkItem.Size <= k_CopyLinkFile_MaxSize)\n              {\n                if (extractStatuses[(unsigned)ref.Link] == 0)\n                {\n                  const CItem &lastLinkItem = _items[linkRef.Last];\n                  if (!lastLinkItem.Is_UnknownSize())\n                    total += lastLinkItem.Size;\n                  else\n                    isThereUndefinedSize = true;\n                }\n                extractStatuses[(unsigned)ref.Link] |= kStatus_Link;\n                thereAreLinks = true;\n              }\n            }\n          }\n          continue;\n        }\n        \n        if (item.IsService())\n          continue;\n        \n        if (item.IsSolid())\n        {\n          unsigned j = index;\n          \n          while (j > solidLimit)\n          {\n            j--;\n            const CRefItem &ref2 = _refs[j];\n            const CItem &item2 = _items[ref2.Item];\n            if (!item2.IsService())\n            {\n              if (extractStatuses[j] == 0)\n              {\n                const CItem &lastItem2 = _items[ref2.Last];\n                if (!lastItem2.Is_UnknownSize())\n                  total += lastItem2.Size;\n                else\n                  isThereUndefinedSize = true;\n              }\n              extractStatuses[j] |= kStatus_Skip;\n              if (!item2.IsSolid())\n                break;\n            }\n          }\n        }\n        \n        solidLimit = index + 1;\n      }\n    }\n\n    if (thereAreLinks)\n    {\n      unsigned solidLimit = 0;\n\n      FOR_VECTOR (i, _refs)\n      {\n        if ((extractStatuses[i] & kStatus_Link) == 0)\n          continue;\n\n        // We use CLinkFile for testMode too.\n        // So we can show errors for copy files.\n        // if (!testMode)\n        {\n          CLinkFile &linkFile = linkFiles.AddNew();\n          linkFile.Index = i;\n        }\n\n        const CItem &item = _items[_refs[i].Item];\n        /*\n        if (item.IsService())\n          continue;\n        */\n        \n        if (item.IsSolid())\n        {\n          unsigned j = i;\n          \n          while (j > solidLimit)\n          {\n            j--;\n            const CRefItem &ref2 = _refs[j];\n            const CItem &item2 = _items[ref2.Item];\n            if (!item2.IsService())\n            {\n              if (extractStatuses[j] != 0)\n                break;\n              extractStatuses[j] = kStatus_Skip;\n              {\n                const CItem &lastItem2 = _items[ref2.Last];\n                if (!lastItem2.Is_UnknownSize())\n                  total += lastItem2.Size;\n                else\n                  isThereUndefinedSize = true;\n              }\n              if (!item2.IsSolid())\n                break;\n            }\n          }\n        }\n        \n        solidLimit = i + 1;\n      }\n\n      if (!testMode)\n      for (UInt32 t = 0; t < numItems; t++)\n      {\n        const unsigned index = (unsigned)(allFilesMode ? t : indices[t]);\n        const CRefItem &ref = _refs[index];\n       \n        const int linkIndex = ref.Link;\n        if (linkIndex < 0 || (unsigned)linkIndex >= index)\n          continue;\n        const CItem &linkItem = _items[_refs[(unsigned)linkIndex].Item];\n        if (!linkItem.IsSolid() || linkItem.Size > k_CopyLinkFile_MaxSize)\n          continue;\n        const int bufIndex = FindLinkBuf(linkFiles, (unsigned)linkIndex);\n        if (bufIndex < 0)\n          return E_FAIL;\n        linkFiles[bufIndex].NumLinks++;\n      }\n    }\n    \n    if (total != 0 || !isThereUndefinedSize)\n    {\n      RINOK(extractCallback->SetTotal(total))\n    }\n  }\n\n\n  \n  // ---------- MEMORY REQUEST ----------\n  {\n    UInt64 dictMaxSize = 0;\n    for (UInt32 i = 0; i < _refs.Size(); i++)\n    {\n      if (extractStatuses[i] == 0)\n        continue;\n      const CRefItem &ref = _refs[i];\n      const CItem &item = _items[ref.Item];\n/*\n      if (!item.IsDir() && !item.IsService() && item.NeedUse_as_CopyLink())\n      {\n      }\n*/\n      const unsigned algo = item.Get_AlgoVersion_RawBits();\n      if (!item.IsDir() && algo < Z7_ARRAY_SIZE(_methodMasks))\n      {\n        const UInt64 d = item.Get_DictSize64();\n        if (dictMaxSize < d)\n            dictMaxSize = d;\n      }\n    }\n    // we use callback, if dict exceeds (1 GB), because\n    // client code can set low limit (1 GB) for allowed memory usage.\n    const UInt64 k_MemLimit_for_Callback = (UInt64)1 << 30;\n    if (dictMaxSize > (_memUsage_WasSet ?\n        _memUsage_Decompress : k_MemLimit_for_Callback))\n    {\n      {\n        CMyComPtr<IArchiveRequestMemoryUseCallback> requestMem;\n        extractCallback->QueryInterface(IID_IArchiveRequestMemoryUseCallback, (void **)&requestMem);\n        if (!requestMem)\n        {\n          if (_memUsage_WasSet)\n            return E_OUTOFMEMORY;\n        }\n        else\n        {\n          UInt64 allowedSize = _memUsage_WasSet ?\n              _memUsage_Decompress :\n              (UInt64)1 << 32; // 4 GB is default allowed limit for RAR7\n          \n          const UInt32 flags = (_memUsage_WasSet ?\n                NRequestMemoryUseFlags::k_AllowedSize_WasForced |\n                NRequestMemoryUseFlags::k_MLimit_Exceeded :\n            (dictMaxSize > allowedSize) ?\n                NRequestMemoryUseFlags::k_DefaultLimit_Exceeded:\n                0)\n             |  NRequestMemoryUseFlags::k_SkipArc_IsExpected\n             // |  NRequestMemoryUseFlags::k_NoErrorMessage // for debug\n             ;\n\n          // we set \"Allow\" for default case, if requestMem doesn't process anything.\n          UInt32 answerFlags =\n              (_memUsage_WasSet && dictMaxSize > allowedSize) ?\n                NRequestMemoryAnswerFlags::k_Limit_Exceeded\n              | NRequestMemoryAnswerFlags::k_SkipArc\n              : NRequestMemoryAnswerFlags::k_Allow;\n\n          RINOK(requestMem->RequestMemoryUse(\n              flags,\n              NEventIndexType::kNoIndex,\n              // NEventIndexType::kInArcIndex, // for debug\n              0,    // index\n              NULL, // path\n              dictMaxSize, &allowedSize, &answerFlags))\n          if ( (answerFlags & NRequestMemoryAnswerFlags::k_Allow) == 0\n            || (answerFlags & NRequestMemoryAnswerFlags::k_Stop)\n            || (answerFlags & NRequestMemoryAnswerFlags::k_SkipArc)\n            )\n          {\n            return E_OUTOFMEMORY;\n          }\n/*\n          if ((answerFlags & NRequestMemoryAnswerFlags::k_AskForBigFile) == 0 &&\n              (answerFlags & NRequestMemoryAnswerFlags::k_ReportForBigFile) == 0)\n          {\n            // requestMem.Release();\n          }\n*/\n        }\n      }\n    }\n  }\n\n\n\n  // ---------- UNPACK ----------\n\n  UInt64 totalUnpacked = 0;\n  UInt64 totalPacked = 0;\n  UInt64 curUnpackSize;\n  UInt64 curPackSize;\n\n  CUnpacker unpacker;\n  unpacker.NeedCrc = _needChecksumCheck;\n  CMyComPtr2_Create<ISequentialInStream, CVolsInStream> volsInStream;\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n/*\n  bool prevSolidWasSkipped = false;\n  UInt64 solidDictSize_Skip = 0;\n*/\n\n  for (unsigned i = 0;; i++,\n      totalUnpacked += curUnpackSize,\n      totalPacked += curPackSize)\n  {\n    lps->InSize = totalPacked;\n    lps->OutSize = totalUnpacked;\n    RINOK(lps->SetCur())\n    {\n      const unsigned num = _refs.Size();\n      if (i >= num)\n        break;\n      for (;;)\n      {\n        if (extractStatuses[i] != 0)\n          break;\n        i++;\n        if (i >= num)\n          break;\n      }\n      if (i >= num)\n        break;\n    }\n    curUnpackSize = 0;\n    curPackSize = 0;\n    \n    // isExtract means that we don't skip that item. So we need read data.\n    const bool isExtract = ((extractStatuses[i] & kStatus_Extract) != 0);\n    Int32 askMode =\n        isExtract ? (testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract) :\n          NExtract::NAskMode::kSkip;\n\n    unpacker.linkFile = NULL;\n\n    // if (!testMode)\n    if ((extractStatuses[i] & kStatus_Link) != 0)\n    {\n      const int bufIndex = FindLinkBuf(linkFiles, i);\n      if (bufIndex < 0)\n        return E_FAIL;\n      unpacker.linkFile = &linkFiles[bufIndex];\n    }\n\n    const unsigned index = i;\n    const CRefItem *ref = &_refs[index];\n    const CItem *item = &_items[ref->Item];\n    const CItem &lastItem = _items[ref->Last];\n\n    curUnpackSize = 0;\n    if (!lastItem.Is_UnknownSize())\n      curUnpackSize = lastItem.Size;\n\n    curPackSize = GetPackSize(index);\n\n    bool isSolid = false;\n    if (!item->IsService())\n    {\n      if (item->IsSolid())\n        isSolid = unpacker.SolidAllowed;\n      unpacker.SolidAllowed = isSolid;\n    }\n\n\n    // ----- request mem -----\n/*\n    // link files are complicated cases. (ref->Link >= 0)\n    // link file can refer to non-solid file that can have big dictionary\n    // link file can refer to solid files that requres buffer\n    if (!item->IsDir() && requestMem && ref->Link < 0)\n    {\n      bool needSkip = false;\n      if (isSolid)\n        needSkip = prevSolidWasSkipped;\n      else\n      {\n        // isSolid == false\n        const unsigned algo = item->Get_AlgoVersion_RawBits();\n        // const unsigned m = item.Get_Method();\n        if (algo < Z7_ARRAY_SIZE(_methodMasks))\n        {\n          solidDictSize_Skip = item->Get_DictSize64();\n          if (solidDictSize_Skip > allowedSize)\n            needSkip = true;\n        }\n      }\n      if (needSkip)\n      {\n        UInt32 answerFlags = 0;\n        UInt64 allowedSize_File = allowedSize;\n        RINOK(requestMem->RequestMemoryUse(\n                  NRequestMemoryUseFlags::k_Limit_Exceeded |\n                  NRequestMemoryUseFlags::k_IsReport,\n              NEventIndexType::kInArcIndex,\n              index,\n              NULL, // path\n              solidDictSize_Skip, &allowedSize_File, &answerFlags))\n        if (!item->IsService())\n          prevSolidWasSkipped = true;\n        continue;\n      }\n    }\n    if (!item->IsService() && item->IsDir())\n      prevSolidWasSkipped = false;\n*/\n    \n    CMyComPtr<ISequentialOutStream> realOutStream;\n    RINOK(extractCallback->GetStream((UInt32)index, &realOutStream, askMode))\n\n    if (item->IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    const int index2 = ref->Link;\n\n    int bufIndex = -1;\n\n    if (index2 >= 0)\n    {\n      const CRefItem &ref2 = _refs[index2];\n      const CItem &item2 = _items[ref2.Item];\n      const CItem &lastItem2 = _items[ref2.Last];\n      if (!item2.IsSolid())\n      {\n        item = &item2;\n        ref = &ref2;\n        if (!lastItem2.Is_UnknownSize())\n          curUnpackSize = lastItem2.Size;\n        else\n          curUnpackSize = 0;\n        curPackSize = GetPackSize((unsigned)index2);\n      }\n      else\n      {\n        if ((unsigned)index2 < index)\n          bufIndex = FindLinkBuf(linkFiles, (unsigned)index2);\n      }\n    }\n\n    bool needCallback = true;\n\n    if (!realOutStream)\n    {\n      if (testMode)\n      {\n        if (item->NeedUse_as_CopyLink_or_HardLink())\n        {\n          Int32 opRes = NExtract::NOperationResult::kOK;\n          if (bufIndex >= 0)\n          {\n            const CLinkFile &linkFile = linkFiles[bufIndex];\n            opRes = DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK);\n          }\n\n          RINOK(extractCallback->PrepareOperation(askMode))\n          RINOK(extractCallback->SetOperationResult(opRes))\n          continue;\n        }\n      }\n      else\n      {\n        if (item->IsService())\n          continue;\n\n        needCallback = false;\n\n        if (!item->NeedUse_as_HardLink())\n        if (index2 < 0)\n\n        for (unsigned n = i + 1; n < _refs.Size(); n++)\n        {\n          const CItem &nextItem = _items[_refs[n].Item];\n          if (nextItem.IsService())\n            continue;\n          if (!nextItem.IsSolid())\n            break;\n          if (extractStatuses[i] != 0)\n          {\n            needCallback = true;\n            break;\n          }\n        }\n        \n        askMode = NExtract::NAskMode::kSkip;\n      }\n    }\n\n    if (needCallback)\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n    }\n\n    if (bufIndex >= 0)\n    {\n      CLinkFile &linkFile = linkFiles[bufIndex];\n     \n      if (isExtract)\n      {\n        if (linkFile.NumLinks == 0)\n          return E_FAIL;\n       \n        if (needCallback)\n        if (realOutStream)\n        {\n          RINOK(CopyData_with_Progress(linkFile.Data, linkFile.Data.Size(), realOutStream, lps))\n        }\n      \n        if (--linkFile.NumLinks == 0)\n          linkFile.Data.Free();\n      }\n      \n      if (needCallback)\n      {\n        RINOK(extractCallback->SetOperationResult(DecoderRes_to_OpRes(linkFile.Res, linkFile.crcOK)))\n      }\n      continue;\n    }\n\n    if (!needCallback)\n      continue;\n    \n    if (item->NeedUse_as_CopyLink())\n    {\n      const int opRes = realOutStream ?\n          NExtract::NOperationResult::kUnsupportedMethod:\n          NExtract::NOperationResult::kOK;\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(opRes))\n      continue;\n    }\n\n    volsInStream->Init(&_arcs, &_items, ref->Item);\n\n    const UInt64 packSize = curPackSize;\n\n    if (item->IsEncrypted())\n      if (!unpacker.getTextPassword)\n        extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&unpacker.getTextPassword);\n\n    bool wrongPassword;\n    HRESULT result = unpacker.Create(EXTERNAL_CODECS_VARS *item, isSolid, wrongPassword);\n\n    if (wrongPassword)\n    {\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kWrongPassword))\n      continue;\n    }\n        \n    bool crcOK = true;\n    if (result == S_OK)\n      result = unpacker.Code(*item, _items[ref->Last], packSize, volsInStream, realOutStream, lps, crcOK);\n    realOutStream.Release();\n    if (!volsInStream->CrcIsOK)\n      crcOK = false;\n\n    int opRes = crcOK ?\n        NExtract::NOperationResult::kOK:\n        NExtract::NOperationResult::kCRCError;\n\n    if (result != S_OK)\n    {\n      if (result == S_FALSE)\n        opRes = NExtract::NOperationResult::kDataError;\n      else if (result == E_NOTIMPL)\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      else\n        return result;\n    }\n\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n\n  {\n    FOR_VECTOR (k, linkFiles)\n      if (linkFiles[k].NumLinks != 0)\n        return E_FAIL;\n  }\n\n  return S_OK;\n  COM_TRY_END\n}\n\n\nCHandler::CHandler()\n{\n  InitDefaults();\n}\n\nvoid CHandler::InitDefaults()\n{\n  _needChecksumCheck = true;\n  _memUsage_WasSet = false;\n  _memUsage_Decompress = (UInt64)1 << 32;\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  InitDefaults();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    UString name = names[i];\n    name.MakeLower_Ascii();\n    if (name.IsEmpty())\n      return E_INVALIDARG;\n\n    const PROPVARIANT &prop = values[i];\n\n    if (name.IsPrefixedBy_Ascii_NoCase(\"mt\"))\n    {\n    }\n    else if (name.IsPrefixedBy_Ascii_NoCase(\"memx\"))\n    {\n      size_t memAvail;\n      if (!NWindows::NSystem::GetRamSize(memAvail))\n        memAvail = (size_t)sizeof(size_t) << 28;\n      UInt64 v;\n      if (!ParseSizeString(name.Ptr(4), prop, memAvail, v))\n        return E_INVALIDARG;\n      _memUsage_Decompress = v;\n      _memUsage_WasSet = true;\n    }\n    else if (name.IsPrefixedBy_Ascii_NoCase(\"crc\"))\n    {\n      name.Delete(0, 3);\n      UInt32 crcSize = 1;\n      RINOK(ParsePropToUInt32(name, prop, crcSize))\n      _needChecksumCheck = (crcSize != 0);\n    }\n    else\n    {\n      return E_INVALIDARG;\n    }\n  }\n  return S_OK;\n}\n\n\nIMPL_ISetCompressCodecsInfo\n\nREGISTER_ARC_I(\n  \"Rar5\", \"rar r00\", NULL, 0xCC,\n  kMarker,\n  0,\n  NArcInfoFlags::kFindSignature,\n  NULL)\n\n}}\n\n\nZ7_CLASS_IMP_COM_2(\n  CBlake2spHasher\n  , IHasher\n  , ICompressSetCoderProperties\n)\n  CAlignedBuffer1 _buf;\n  // CBlake2sp _blake;\n  #define Z7_BLACK2S_ALIGN_OBJECT_OFFSET 0\n  CBlake2sp *Obj() { return (CBlake2sp *)(void *)((Byte *)_buf + Z7_BLACK2S_ALIGN_OBJECT_OFFSET); }\npublic:\n  Byte _mtDummy[1 << 7];  // it's public to eliminate clang warning: unused private field\n  CBlake2spHasher():\n    _buf(sizeof(CBlake2sp) + Z7_BLACK2S_ALIGN_OBJECT_OFFSET)\n  {\n    Blake2sp_SetFunction(Obj(), 0);\n    Blake2sp_InitState(Obj());\n  }\n};\n\nZ7_COM7F_IMF2(void, CBlake2spHasher::Init())\n{\n  Blake2sp_InitState(Obj());\n}\n\nZ7_COM7F_IMF2(void, CBlake2spHasher::Update(const void *data, UInt32 size))\n{\n#if 1\n  Blake2sp_Update(Obj(), (const Byte *)data, (size_t)size);\n#else\n  // for debug:\n  for (;;)\n  {\n    if (size == 0)\n      return;\n    UInt32 size2 = (size * 0x85EBCA87) % size / 800;\n    // UInt32 size2 = size / 2;\n    if (size2 == 0)\n      size2 = 1;\n    Blake2sp_Update(Obj(), (const Byte *)data, size2);\n    data = (const void *)((const Byte *)data + size2);\n    size -= size2;\n  }\n#endif\n}\n\nZ7_COM7F_IMF2(void, CBlake2spHasher::Final(Byte *digest))\n{\n  Blake2sp_Final(Obj(), digest);\n}\n\nZ7_COM7F_IMF(CBlake2spHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  unsigned algo = 0;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    if (propIDs[i] == NCoderPropID::kDefaultProp)\n    {\n      const PROPVARIANT &prop = coderProps[i];\n      if (prop.vt != VT_UI4)\n        return E_INVALIDARG;\n      /*\n      if (prop.ulVal > Z7_BLAKE2S_ALGO_MAX)\n        return E_NOTIMPL;\n      */\n      algo = (unsigned)prop.ulVal;\n    }\n  }\n  if (!Blake2sp_SetFunction(Obj(), algo))\n    return E_NOTIMPL;\n  return S_OK;\n}\n\nREGISTER_HASHER(CBlake2spHasher, 0x202, \"BLAKE2sp\", Z7_BLAKE2S_DIGEST_SIZE)\n\nstatic struct CBlake2sp_Prepare { CBlake2sp_Prepare() { z7_Black2sp_Prepare(); } } g_Blake2sp_Prepare;\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/Rar5Handler.h",
    "content": "﻿// Rar5Handler.h\n\n#ifndef ZIP7_INC_RAR5_HANDLER_H\n#define ZIP7_INC_RAR5_HANDLER_H\n\n#include \"../../../../C/Blake2.h\"\n\n#include \"../../../Common/MyBuffer.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"../../Common/CreateCoder.h\"\n\n#include \"../IArchive.h\"\n\nnamespace NArchive {\nnamespace NRar5 {\n\nnamespace NHeaderFlags\n{\n  const unsigned kExtra   = 1 << 0;\n  const unsigned kData    = 1 << 1;\n  // const unsigned kUnknown = 1 << 2;\n  const unsigned kPrevVol = 1 << 3;\n  const unsigned kNextVol = 1 << 4;\n  // const unsigned kIsChild = 1 << 5;\n  // const unsigned kPreserveChild = 1 << 6;\n}\n  \nnamespace NHeaderType\n{\n  enum\n  {\n    kArc = 1,\n    kFile,\n    kService,\n    kArcEncrypt,\n    kEndOfArc\n  };\n}\n\nnamespace NArcFlags\n{\n  const unsigned kVol       = 1 << 0;\n  const unsigned kVolNumber = 1 << 1;\n  const unsigned kSolid     = 1 << 2;\n  // const unsigned kRecovery  = 1 << 3;\n  // const unsigned kLocked    = 1 << 4;\n}\n\nconst unsigned kArcExtraRecordType_Locator  = 1;\nconst unsigned kArcExtraRecordType_Metadata = 2;\n\nnamespace NLocatorFlags\n{\n  const unsigned kQuickOpen  = 1 << 0;\n  const unsigned kRecovery   = 1 << 1;\n}\n\nnamespace NMetadataFlags\n{\n  const unsigned kArcName   = 1 << 0;\n  const unsigned kCTime     = 1 << 1;\n  const unsigned kUnixTime  = 1 << 2;\n  const unsigned kNanoSec   = 1 << 3;\n}\n\nnamespace NFileFlags\n{\n  const unsigned kIsDir    = 1 << 0;\n  const unsigned kUnixTime = 1 << 1;\n  const unsigned kCrc32    = 1 << 2;\n  const unsigned kUnknownSize = 1 << 3;\n}\n\nnamespace NMethodFlags\n{\n  // const unsigned kVersionMask = 0x3F;\n  const unsigned kSolid = 1 << 6;\n  const unsigned kRar5_Compat = 1u << 20;\n}\n\nnamespace NArcEndFlags\n{\n  const unsigned kMoreVols = 1 << 0;\n}\n\nenum EHostOS\n{\n  kHost_Windows = 0,\n  kHost_Unix\n};\n\n\n\n// ---------- Extra ----------\n\nnamespace NExtraID\n{\n  enum\n  {\n    kCrypto = 1,\n    kHash,\n    kTime,\n    kVersion,\n    kLink,\n    kUnixOwner,\n    kSubdata\n  };\n}\n\nconst unsigned kCryptoAlgo_AES = 0;\n\nnamespace NCryptoFlags\n{\n  const unsigned kPswCheck = 1 << 0;\n  const unsigned kUseMAC   = 1 << 1;\n}\n\nstruct CCryptoInfo\n{\n  UInt64 Algo;\n  UInt64 Flags;\n  Byte Cnt;\n\n  bool UseMAC()       const { return (Flags & NCryptoFlags::kUseMAC) != 0; }\n  bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; }\n  bool Parse(const Byte *p, size_t size);\n};\n\nconst unsigned kHashID_Blake2sp = 0;\n\nnamespace NTimeRecord\n{\n  enum\n  {\n    k_Index_MTime = 0,\n    k_Index_CTime,\n    k_Index_ATime\n  };\n  \n  namespace NFlags\n  {\n    const unsigned kUnixTime = 1 << 0;\n    const unsigned kMTime    = 1 << 1;\n    const unsigned kCTime    = 1 << 2;\n    const unsigned kATime    = 1 << 3;\n    const unsigned kUnixNs   = 1 << 4;\n  }\n}\n\nnamespace NLinkType\n{\n  enum\n  {\n    kUnixSymLink = 1,\n    kWinSymLink,\n    kWinJunction,\n    kHardLink,\n    kFileCopy\n  };\n}\n\nnamespace NLinkFlags\n{\n  const unsigned kTargetIsDir = 1 << 0;\n}\n\n\nstruct CLinkInfo\n{\n  UInt64 Type;\n  UInt64 Flags;\n  unsigned NameOffset;\n  unsigned NameLen;\n  \n  bool Parse(const Byte *p, unsigned size);\n};\n\n\nstruct CItem\n{\n  UInt32 CommonFlags;\n  UInt32 Flags;\n\n  Byte RecordType;\n  bool Version_Defined;\n\n  int ACL;\n\n  AString Name;\n\n  unsigned VolIndex;\n  int NextItem;        // in _items{}\n\n  UInt32 UnixMTime;\n  UInt32 CRC;\n  UInt32 Attrib;\n  UInt32 Method;\n\n  CByteBuffer Extra;\n\n  UInt64 Size;\n  UInt64 PackSize;\n  UInt64 HostOS;\n  \n  UInt64 DataPos;\n  UInt64 Version;\n\n  CItem() { Clear(); }\n\n  void Clear()\n  {\n    // CommonFlags = 0;\n    // Flags = 0;\n    \n    // UnixMTime = 0;\n    // CRC = 0;\n\n    VolIndex = 0;\n    NextItem = -1;\n\n    Version_Defined = false;\n    Version = 0;\n\n    Name.Empty();\n    Extra.Free();\n    ACL = -1;\n  }\n\n  bool IsSplitBefore()  const { return (CommonFlags & NHeaderFlags::kPrevVol) != 0; }\n  bool IsSplitAfter()   const { return (CommonFlags & NHeaderFlags::kNextVol) != 0; }\n  bool IsSplit()        const { return (CommonFlags & (NHeaderFlags::kPrevVol | NHeaderFlags::kNextVol)) != 0; }\n\n  bool IsDir()          const { return (Flags & NFileFlags::kIsDir) != 0; }\n  bool Has_UnixMTime()  const { return (Flags & NFileFlags::kUnixTime) != 0; }\n  bool Has_CRC()        const { return (Flags & NFileFlags::kCrc32) != 0; }\n  bool Is_UnknownSize() const { return (Flags & NFileFlags::kUnknownSize) != 0; }\n\n  bool IsNextForItem(const CItem &prev) const\n  {\n    return !IsDir() && !prev.IsDir() && IsSplitBefore() && prev.IsSplitAfter() && (Name == prev.Name);\n      // && false;\n  }\n\n  // rar docs: Solid flag can be set only for file headers and is never set for service headers.\n  bool IsSolid()        const { return ((UInt32)Method & NMethodFlags::kSolid) != 0; }\n  bool Is_Rar5_Compat() const { return ((UInt32)Method & NMethodFlags::kRar5_Compat) != 0; }\n  unsigned Get_Rar5_CompatBit() const { return ((UInt32)Method >> 20) & 1; }\n\n  unsigned Get_AlgoVersion_RawBits() const { return (unsigned)Method & 0x3F; }\n  unsigned Get_AlgoVersion_HuffRev() const\n  {\n    unsigned w = (unsigned)Method & 0x3F;\n    if (w == 1 && Is_Rar5_Compat())\n      w = 0;\n    return w;\n  }\n  unsigned Get_Method() const { return ((unsigned)Method >> 7) & 0x7; }\n\n  unsigned Get_DictSize_Main() const\n    { return ((UInt32)Method >> 10) & (Get_AlgoVersion_RawBits() == 0 ? 0xf : 0x1f); }\n  unsigned Get_DictSize_Frac() const\n  {\n    // original-unrar ignores Frac, if (algo==0) (rar5):\n    if (Get_AlgoVersion_RawBits() == 0)\n      return 0;\n    return ((UInt32)Method >> 15) & 0x1f;\n  }\n  UInt64 Get_DictSize64() const\n  {\n    // ver 6.* check\n    // return (((UInt32)Method >> 10) & 0xF);\n    UInt64 winSize = 0;\n    const unsigned algo = Get_AlgoVersion_RawBits();\n    if (algo <= 1)\n    {\n      UInt32 w = 32;\n      if (algo == 1)\n        w += Get_DictSize_Frac();\n      winSize = (UInt64)w << (12 + Get_DictSize_Main());\n    }\n    return winSize;\n  }\n\n\n  bool IsService() const { return RecordType == NHeaderType::kService; }\n  \n  bool Is_STM() const { return IsService() && Name.IsEqualTo(\"STM\"); }\n  bool Is_CMT() const { return IsService() && Name.IsEqualTo(\"CMT\"); }\n  bool Is_ACL() const { return IsService() && Name.IsEqualTo(\"ACL\"); }\n  // bool Is_QO()  const { return IsService() && Name.IsEqualTo(\"QO\"); }\n\n  int FindExtra(unsigned extraID, unsigned &recordDataSize) const;\n  void PrintInfo(AString &s) const;\n\n\n  bool IsEncrypted() const\n  {\n    unsigned size;\n    return FindExtra(NExtraID::kCrypto, size) >= 0;\n  }\n\n  int FindExtra_Blake() const\n  {\n    unsigned size = 0;\n    const int offset = FindExtra(NExtraID::kHash, size);\n    if (offset >= 0\n        && size == Z7_BLAKE2S_DIGEST_SIZE + 1\n        && Extra[(unsigned)offset] == kHashID_Blake2sp)\n      return offset + 1;\n    return -1;\n  }\n\n  bool FindExtra_Version(UInt64 &version) const;\n\n  bool FindExtra_Link(CLinkInfo &link) const;\n  void Link_to_Prop(unsigned linkType, NWindows::NCOM::CPropVariant &prop) const;\n  bool Is_CopyLink() const;\n  bool Is_HardLink() const;\n  bool Is_CopyLink_or_HardLink() const;\n\n  bool NeedUse_as_CopyLink() const { return PackSize == 0 && Is_CopyLink(); }\n  bool NeedUse_as_HardLink() const { return PackSize == 0 && Is_HardLink(); }\n  bool NeedUse_as_CopyLink_or_HardLink() const { return PackSize == 0 && Is_CopyLink_or_HardLink(); }\n\n  bool GetAltStreamName(AString &name) const;\n\n  UInt32 GetWinAttrib() const\n  {\n    UInt32 a;\n    switch (HostOS)\n    {\n      case kHost_Windows:\n          a = Attrib;\n          break;\n      case kHost_Unix:\n          a = Attrib << 16;\n          a |= 0x8000; // add posix mode marker\n          break;\n      default:\n          a = 0;\n    }\n    if (IsDir()) a |= FILE_ATTRIBUTE_DIRECTORY;\n    return a;\n  }\n\n  UInt64 GetDataPosition() const { return DataPos; }\n};\n\n\nstruct CInArcInfo\n{\n  UInt64 Flags;\n  UInt64 VolNumber;\n  UInt64 StartPos;\n  UInt64 EndPos;\n\n  UInt64 EndFlags;\n  bool EndOfArchive_was_Read;\n\n  bool IsEncrypted;\n  bool Locator_Defined;\n  bool Locator_Error;\n  bool Metadata_Defined;\n  bool Metadata_Error;\n  bool UnknownExtraRecord;\n  bool Extra_Error;\n  bool UnsupportedFeature;\n\n  struct CLocator\n  {\n    UInt64 Flags;\n    UInt64 QuickOpen;\n    UInt64 Recovery;\n    \n    bool Is_QuickOpen() const { return (Flags & NLocatorFlags::kQuickOpen) != 0; }\n    bool Is_Recovery() const { return (Flags & NLocatorFlags::kRecovery) != 0; }\n\n    bool Parse(const Byte *p, size_t size);\n    CLocator():\n      Flags(0),\n      QuickOpen(0),\n      Recovery(0)\n      {}\n  };\n\n  struct CMetadata\n  {\n    UInt64 Flags;\n    UInt64 CTime;\n    AString ArcName;\n\n    bool Parse(const Byte *p, size_t size);\n    CMetadata():\n      Flags(0),\n      CTime(0)\n      {}\n  };\n\n  CLocator Locator;\n  CMetadata Metadata;\n\n  bool ParseExtra(const Byte *p, size_t size);\n\n  CInArcInfo():\n    Flags(0),\n    VolNumber(0),\n    StartPos(0),\n    EndPos(0),\n    EndFlags(0),\n    EndOfArchive_was_Read(false),\n    IsEncrypted(false),\n    Locator_Defined(false),\n    Locator_Error(false),\n    Metadata_Defined(false),\n    Metadata_Error(false),\n    UnknownExtraRecord(false),\n    Extra_Error(false),\n    UnsupportedFeature(false)\n      {}\n\n  /*\n  void Clear()\n  {\n    Flags = 0;\n    VolNumber = 0;\n    StartPos = 0;\n    EndPos = 0;\n    EndFlags = 0;\n    EndOfArchive_was_Read = false;\n  }\n  */\n\n  UInt64 GetPhySize() const { return EndPos - StartPos; }\n\n  bool AreMoreVolumes()  const { return (EndFlags & NArcEndFlags::kMoreVols) != 0; }\n\n  bool IsVolume()             const { return (Flags & NArcFlags::kVol) != 0; }\n  bool IsSolid()              const { return (Flags & NArcFlags::kSolid) != 0; }\n  bool Is_VolNumber_Defined() const { return (Flags & NArcFlags::kVolNumber) != 0; }\n\n  UInt64 GetVolIndex() const { return Is_VolNumber_Defined() ? VolNumber : 0; }\n};\n\n\nstruct CRefItem\n{\n  unsigned Item;   // First item in _items[]\n  unsigned Last;   // Last  item in _items[]\n  int Parent;      // in _refs[], if alternate stream\n  int Link;        // in _refs[]\n};\n\n\nstruct CArc\n{\n  CMyComPtr<IInStream> Stream;\n  CInArcInfo Info;\n};\n\n\nclass CHandler Z7_final:\n  public IInArchive,\n  public IArchiveGetRawProps,\n  public ISetProperties,\n  Z7_PUBLIC_ISetCompressCodecsInfo_IFEC\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IInArchive)\n  Z7_COM_QI_ENTRY(IArchiveGetRawProps)\n  Z7_COM_QI_ENTRY(ISetProperties)\n  Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n  \n  Z7_IFACE_COM7_IMP(IInArchive)\n  Z7_IFACE_COM7_IMP(IArchiveGetRawProps)\n  Z7_IFACE_COM7_IMP(ISetProperties)\n  DECL_ISetCompressCodecsInfo\n\n  void InitDefaults();\n\n  bool _isArc;\n  bool _needChecksumCheck;\n  bool _memUsage_WasSet;\n  bool _comment_WasUsedInArc;\n  bool _acl_Used;\n  bool _error_in_ACL;\n  bool _split_Error;\npublic:\n  CRecordVector<CRefItem> _refs;\n  CObjectVector<CItem> _items;\n\n  CHandler();\nprivate:\n  CObjectVector<CArc> _arcs;\n  CObjectVector<CByteBuffer> _acls;\n\n  UInt32 _errorFlags;\n  // UInt32 _warningFlags;\n\n  UInt32 _numBlocks;\n  unsigned _rar5comapt_mask;\n  unsigned _methodMasks[2];\n  UInt64 _algo_Mask;\n  UInt64 _dictMaxSizes[2];\n\n  CByteBuffer _comment;\n  UString _missingVolName;\n\n  UInt64 _memUsage_Decompress;\n\n  DECL_EXTERNAL_CODECS_VARS\n\n  UInt64 GetPackSize(unsigned refIndex) const;\n  \n  void FillLinks();\n  \n  HRESULT Open2(IInStream *stream,\n      const UInt64 *maxCheckStartPosition,\n      IArchiveOpenCallback *openCallback);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/RarHandler.cpp",
    "content": "﻿// RarHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/MyBuffer2.h\"\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../../Windows/PropVariantUtils.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../IPassword.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/FilterCoder.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/MethodId.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/RegisterArc.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"../../Crypto/Rar20Crypto.h\"\n#include \"../../Crypto/RarAes.h\"\n\n#include \"../Common/FindSignature.h\"\n#include \"../Common/ItemNameUtils.h\"\n#include \"../Common/OutStreamWithCRC.h\"\n\n#include \"../HandlerCont.h\"\n\n#include \"RarVol.h\"\n#include \"RarHandler.h\"\n\nusing namespace NWindows;\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n\nnamespace NArchive {\nnamespace NRar {\n\nstatic const Byte kMarker[NHeader::kMarkerSize] =\n  { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };\n\nconst unsigned kPasswordLen_MAX = 127;\n      \nbool CItem::IgnoreItem() const\n{\n  switch (HostOS)\n  {\n    case NHeader::NFile::kHostMSDOS:\n    case NHeader::NFile::kHostOS2:\n    case NHeader::NFile::kHostWin32:\n      return ((Attrib & NHeader::NFile::kLabelFileAttribute) != 0);\n  }\n  return false;\n}\n\nbool CItem::IsDir() const\n{\n  if (GetDictSize() == NHeader::NFile::kDictDirectoryValue)\n    return true;\n  switch (HostOS)\n  {\n    case NHeader::NFile::kHostMSDOS:\n    case NHeader::NFile::kHostOS2:\n    case NHeader::NFile::kHostWin32:\n      if (Attrib & FILE_ATTRIBUTE_DIRECTORY)\n        return true;\n      break;\n    case NHeader::NFile::kHostUnix:\n    case NHeader::NFile::kHostBeOS:\n      if (MY_LIN_S_ISDIR(Attrib))\n        return true;\n      break;\n  }\n  return false;\n}\n\nUInt32 CItem::GetWinAttrib() const\n{\n  UInt32 a;\n  switch (HostOS)\n  {\n    case NHeader::NFile::kHostMSDOS:\n    case NHeader::NFile::kHostOS2:\n    case NHeader::NFile::kHostWin32:\n      a = Attrib;\n      break;\n    case NHeader::NFile::kHostUnix:\n    case NHeader::NFile::kHostBeOS:\n      a = Attrib << 16;\n      a |= 0x8000; // add posix mode marker\n      break;\n    // case NHeader::NFile::kHostMacOS:\n    // kHostMacOS was used only by some very old rare case rar.\n    // New rar4-rar7 for macos probably uses kHostUnix.\n    // So we process kHostMacOS without attribute parsing:\n    default:\n      a = 0;\n  }\n  if (IsDir())\n    a |= FILE_ATTRIBUTE_DIRECTORY;\n  return a;\n}\n  \nstatic const char * const kHostOS[] =\n{\n    \"MS DOS\"\n  , \"OS/2\"\n  , \"Win32\"\n  , \"Unix\"\n  , \"Mac OS\"\n  , \"BeOS\"\n};\n\nstatic const char * const k_Flags[] =\n{\n    \"Volume\"\n  , \"Comment\"\n  , \"Lock\"\n  , \"Solid\"\n  , \"NewVolName\" // pack_comment in old versuons\n  , \"Authenticity\"\n  , \"Recovery\"\n  , \"BlockEncryption\"\n  , \"FirstVolume\"\n  , \"EncryptVer\" // 9\n};\n\nenum EErrorType\n{\n  k_ErrorType_OK,\n  k_ErrorType_Corrupted,\n  k_ErrorType_UnexpectedEnd,\n  k_ErrorType_DecryptionError\n};\n\nclass CInArchive\n{\n  IInStream *m_Stream;\n  UInt64 m_StreamStartPosition;\n  UString _unicodeNameBuffer;\n  CByteBuffer _comment;\n  CByteBuffer m_FileHeaderData;\n  NHeader::NBlock::CBlock m_BlockHeader;\n  NCrypto::NRar3::CDecoder *m_RarAESSpec;\n  CMyComPtr<ICompressFilter> m_RarAES;\n  CAlignedBuffer m_DecryptedDataAligned;\n  UInt32 m_DecryptedDataSize;\n  bool m_CryptoMode;\n  UInt32 m_CryptoPos;\n\n\n  HRESULT ReadBytesSpec(void *data, size_t *size);\n  bool ReadBytesAndTestSize(void *data, UInt32 size);\n  void ReadName(const Byte *p, unsigned nameSize, CItem &item);\n  bool ReadHeaderReal(const Byte *p, unsigned size, CItem &item);\n  \n  HRESULT Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit);\n\n  void AddToSeekValue(UInt64 addValue)\n  {\n    m_Position += addValue;\n  }\n\n  void FinishCryptoBlock()\n  {\n    if (m_CryptoMode)\n      while ((m_CryptoPos & 0xF) != 0)\n      {\n        m_CryptoPos++;\n        m_Position++;\n      }\n  }\n\npublic:\n  UInt64 m_Position;\n  CInArcInfo ArcInfo;\n  bool HeaderErrorWarning;\n\n  HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);\n  HRESULT GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPassword,\n      bool &filled, EErrorType &error);\n};\n  \nstatic bool CheckHeaderCrc(const Byte *header, size_t headerSize)\n{\n  return Get16(header) == (UInt16)(CrcCalc(header + 2, headerSize - 2) & 0xFFFF);\n}\n\nHRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)\n{\n  HeaderErrorWarning = false;\n  m_CryptoMode = false;\n  RINOK(InStream_GetPos_GetSize(stream, m_StreamStartPosition, ArcInfo.FileSize))\n  m_Position = m_StreamStartPosition;\n\n  UInt64 arcStartPos = m_StreamStartPosition;\n  {\n    Byte marker[NHeader::kMarkerSize];\n    RINOK(ReadStream_FALSE(stream, marker, NHeader::kMarkerSize))\n    if (memcmp(marker, kMarker, NHeader::kMarkerSize) == 0)\n      m_Position += NHeader::kMarkerSize;\n    else\n    {\n      if (searchHeaderSizeLimit && *searchHeaderSizeLimit == 0)\n        return S_FALSE;\n      RINOK(InStream_SeekSet(stream, m_StreamStartPosition))\n      RINOK(FindSignatureInStream(stream, kMarker, NHeader::kMarkerSize,\n          searchHeaderSizeLimit, arcStartPos))\n      m_Position = arcStartPos + NHeader::kMarkerSize;\n      RINOK(InStream_SeekSet(stream, m_Position))\n    }\n  }\n  Byte buf[NHeader::NArchive::kArchiveHeaderSize + 1];\n\n  RINOK(ReadStream_FALSE(stream, buf, NHeader::NArchive::kArchiveHeaderSize))\n  AddToSeekValue(NHeader::NArchive::kArchiveHeaderSize);\n\n\n  const UInt32 blockSize = Get16(buf + 5);\n\n  ArcInfo.EncryptVersion = 0;\n  ArcInfo.Flags = Get16(buf + 3);\n\n  UInt32 headerSize = NHeader::NArchive::kArchiveHeaderSize;\n  \n  /*\n  if (ArcInfo.IsThereEncryptVer())\n  {\n    if (blockSize <= headerSize)\n      return S_FALSE;\n    RINOK(ReadStream_FALSE(stream, buf + NHeader::NArchive::kArchiveHeaderSize, 1));\n    AddToSeekValue(1);\n    ArcInfo.EncryptVersion = buf[NHeader::NArchive::kArchiveHeaderSize];\n    headerSize += 1;\n  }\n  */\n  \n  if (blockSize < headerSize\n      || buf[2] != NHeader::NBlockType::kArchiveHeader\n      || !CheckHeaderCrc(buf, headerSize))\n    return S_FALSE;\n\n  size_t commentSize = blockSize - headerSize;\n  _comment.Alloc(commentSize);\n  RINOK(ReadStream_FALSE(stream, _comment, commentSize))\n  AddToSeekValue(commentSize);\n  m_Stream = stream;\n  ArcInfo.StartPos = arcStartPos;\n  return S_OK;\n}\n\nHRESULT CInArchive::ReadBytesSpec(void *data, size_t *resSize)\n{\n  if (m_CryptoMode)\n  {\n    size_t size = *resSize;\n    *resSize = 0;\n    const Byte *bufData = m_DecryptedDataAligned;\n    UInt32 bufSize = m_DecryptedDataSize;\n    size_t i;\n    for (i = 0; i < size && m_CryptoPos < bufSize; i++)\n      ((Byte *)data)[i] = bufData[m_CryptoPos++];\n    *resSize = i;\n    return S_OK;\n  }\n  return ReadStream(m_Stream, data, resSize);\n}\n\nbool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)\n{\n  size_t processed = size;\n  if (ReadBytesSpec(data, &processed) != S_OK)\n    return false;\n  return processed == size;\n}\n\n\nstatic unsigned DecodeUnicodeFileName(const Byte *name, const Byte *encName,\n    unsigned encSize, wchar_t *unicodeName, unsigned maxDecSize)\n{\n  unsigned encPos = 0;\n  unsigned decPos = 0;\n  unsigned flagBits = 0;\n  Byte flags = 0;\n\n  if (encPos >= encSize)\n    return 0; // error\n  const unsigned highBits = ((unsigned)encName[encPos++]) << 8;\n  \n  while (encPos < encSize && decPos < maxDecSize)\n  {\n    if (flagBits == 0)\n    {\n      flags = encName[encPos++];\n      flagBits = 8;\n    }\n    \n    if (encPos >= encSize)\n      break; // error\n    unsigned len = encName[encPos++];\n\n    flagBits -= 2;\n    const unsigned mode = (flags >> flagBits) & 3;\n    \n    if (mode != 3)\n    {\n      if (mode == 1)\n        len += highBits;\n      else if (mode == 2)\n      {\n        if (encPos >= encSize)\n          break; // error\n        len += ((unsigned)encName[encPos++] << 8);\n      }\n      unicodeName[decPos++] = (wchar_t)len;\n    }\n    else\n    {\n      if (len & 0x80)\n      {\n        if (encPos >= encSize)\n          break; // error\n        Byte correction = encName[encPos++];\n        for (len = (len & 0x7f) + 2; len > 0 && decPos < maxDecSize; len--, decPos++)\n          unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + highBits);\n      }\n      else\n        for (len += 2; len > 0 && decPos < maxDecSize; len--, decPos++)\n          unicodeName[decPos] = name[decPos];\n    }\n  }\n  \n  return decPos < maxDecSize ? decPos : maxDecSize - 1;\n}\n\n\nvoid CInArchive::ReadName(const Byte *p, unsigned nameSize, CItem &item)\n{\n  item.UnicodeName.Empty();\n  if (nameSize > 0)\n  {\n    unsigned i;\n    for (i = 0; i < nameSize && p[i] != 0; i++);\n    item.Name.SetFrom((const char *)p, i);\n\n    if (item.HasUnicodeName())\n    {\n      if (i < nameSize)\n      {\n        i++;\n        unsigned uNameSizeMax = MyMin(nameSize, (unsigned)0x400);\n        unsigned len = DecodeUnicodeFileName(p, p + i, nameSize - i, _unicodeNameBuffer.GetBuf(uNameSizeMax), uNameSizeMax);\n        _unicodeNameBuffer.ReleaseBuf_SetEnd(len);\n        item.UnicodeName = _unicodeNameBuffer;\n      }\n      else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))\n        item.UnicodeName.Empty();\n    }\n  }\n  else\n    item.Name.Empty();\n}\n\nstatic int ReadTime(const Byte *p, unsigned size, Byte mask, CRarTime &rarTime)\n{\n  rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);\n  const unsigned numDigits = (mask & 3);\n  rarTime.SubTime[0] =\n  rarTime.SubTime[1] =\n  rarTime.SubTime[2] = 0;\n  if (numDigits > size)\n    return -1;\n  for (unsigned i = 0; i < numDigits; i++)\n    rarTime.SubTime[3 - numDigits + i] = p[i];\n  return (int)numDigits;\n}\n\n#define READ_TIME(_mask_, _ttt_) \\\n  { int size2 = ReadTime(p, size, _mask_, _ttt_); if (size2 < 0) return false; p += (unsigned)size2, size -= (unsigned)size2; }\n\n#define READ_TIME_2(_mask_, _def_, _ttt_) \\\n    _def_ = ((_mask_ & 8) != 0); if (_def_) \\\n    { if (size < 4) return false; \\\n      _ttt_ .DosTime = Get32(p); p += 4; size -= 4; \\\n      READ_TIME(_mask_, _ttt_); } \\\n\n\nbool CInArchive::ReadHeaderReal(const Byte *p, unsigned size, CItem &item)\n{\n  const Byte *pStart = p;\n\n  item.Clear();\n  item.Flags = m_BlockHeader.Flags;\n\n  const unsigned kFileHeaderSize = 25;\n\n  if (size < kFileHeaderSize)\n    return false;\n\n  item.PackSize = Get32(p);\n  item.Size = Get32(p + 4);\n  item.HostOS = p[8];\n  item.FileCRC = Get32(p + 9);\n  item.MTime.DosTime = Get32(p + 13);\n  item.UnPackVersion = p[17];\n  item.Method = p[18];\n  unsigned nameSize = Get16(p + 19);\n  item.Attrib = Get32(p + 21);\n\n  item.MTime.LowSecond = 0;\n  item.MTime.SubTime[0] =\n  item.MTime.SubTime[1] =\n  item.MTime.SubTime[2] = 0;\n\n  p += kFileHeaderSize;\n  size -= kFileHeaderSize;\n  if ((item.Flags & NHeader::NFile::kSize64Bits) != 0)\n  {\n    if (size < 8)\n      return false;\n    item.PackSize |= ((UInt64)Get32(p) << 32);\n    if (item.PackSize >= ((UInt64)1 << 63))\n      return false;\n    item.Size |= ((UInt64)Get32(p + 4) << 32);\n    p += 8;\n    size -= 8;\n  }\n  if (nameSize > size)\n    return false;\n  ReadName(p, nameSize, item);\n  p += nameSize;\n  size -= nameSize;\n\n  /*\n  // It was commented, since it's difficult to support alt Streams for solid archives.\n  if (m_BlockHeader.Type == NHeader::NBlockType::kSubBlock)\n  {\n    if (item.HasSalt())\n    {\n      if (size < sizeof(item.Salt))\n        return false;\n      size -= sizeof(item.Salt);\n      p += sizeof(item.Salt);\n    }\n    if (item.Name.IsEqualTo(\"ACL\") && size == 0)\n    {\n      item.IsAltStream = true;\n      item.Name.Empty();\n      item.UnicodeName.SetFromAscii(\".ACL\");\n    }\n    else if (item.Name.IsEqualTo(\"STM\") && size != 0 && (size & 1) == 0)\n    {\n      item.IsAltStream = true;\n      item.Name.Empty();\n      for (UInt32 i = 0; i < size; i += 2)\n      {\n        wchar_t c = Get16(p + i);\n        if (c == 0)\n          return false;\n        item.UnicodeName += c;\n      }\n    }\n  }\n  */\n\n  if (item.HasSalt())\n  {\n    if (size < sizeof(item.Salt))\n      return false;\n    for (unsigned i = 0; i < sizeof(item.Salt); i++)\n      item.Salt[i] = p[i];\n    p += sizeof(item.Salt);\n    size -= (unsigned)sizeof(item.Salt);\n  }\n\n  // some rar archives have HasExtTime flag without field.\n  if (size >= 2 && item.HasExtTime())\n  {\n    Byte aMask = (Byte)(p[0] >> 4);\n    Byte b = p[1];\n    p += 2;\n    size -= 2;\n    Byte mMask = (Byte)(b >> 4);\n    Byte cMask = (Byte)(b & 0xF);\n    if ((mMask & 8) != 0)\n    {\n      READ_TIME(mMask, item.MTime)\n    }\n    READ_TIME_2(cMask, item.CTimeDefined, item.CTime)\n    READ_TIME_2(aMask, item.ATimeDefined, item.ATime)\n  }\n\n  unsigned fileHeaderWithNameSize = 7 + (unsigned)(p - pStart);\n  \n  item.Position = m_Position;\n  item.MainPartSize = fileHeaderWithNameSize;\n  item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);\n\n  if (m_CryptoMode)\n    item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);\n  else\n    item.AlignSize = 0;\n  AddToSeekValue(m_BlockHeader.HeadSize);\n  \n  // return (m_BlockHeader.Type != NHeader::NBlockType::kSubBlock || item.IsAltStream);\n  return true;\n}\n\nHRESULT CInArchive::GetNextItem(CItem &item, ICryptoGetTextPassword *getTextPassword, bool &filled, EErrorType &error)\n{\n  filled = false;\n  error = k_ErrorType_OK;\n  for (;;)\n  {\n    RINOK(InStream_SeekSet(m_Stream, m_Position))\n    ArcInfo.EndPos = m_Position;\n    if (!m_CryptoMode && (ArcInfo.Flags &\n        NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)\n    {\n      m_CryptoMode = false;\n      if (!getTextPassword)\n      {\n        error = k_ErrorType_DecryptionError;\n        return S_OK; // return S_FALSE;\n      }\n      if (!m_RarAES)\n      {\n        m_RarAESSpec = new NCrypto::NRar3::CDecoder;\n        m_RarAES = m_RarAESSpec;\n      }\n      // m_RarAESSpec->SetRar350Mode(ArcInfo.IsEncryptOld());\n\n      {\n        // Salt\n        const UInt32 kSaltSize = 8;\n        Byte salt[kSaltSize];\n        if (!ReadBytesAndTestSize(salt, kSaltSize))\n          return S_FALSE;\n        m_Position += kSaltSize;\n        RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))\n      }\n\n      {\n        // Password\n        CMyComBSTR_Wipe password;\n        RINOK(getTextPassword->CryptoGetTextPassword(&password))\n        unsigned len = 0;\n        if (password)\n          len = MyStringLen(password);\n        if (len > kPasswordLen_MAX)\n          len = kPasswordLen_MAX;\n        \n        CByteBuffer_Wipe buffer(len * 2);\n        for (unsigned i = 0; i < len; i++)\n        {\n          wchar_t c = password[i];\n          ((Byte *)buffer)[i * 2] = (Byte)c;\n          ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);\n        }\n        \n        m_RarAESSpec->SetPassword((const Byte *)buffer, len * 2);\n      }\n\n      const UInt32 kDecryptedBufferSize = (1 << 12);\n      if (m_DecryptedDataAligned.Size() == 0)\n      {\n        // const UInt32 kAlign = 16;\n        m_DecryptedDataAligned.AllocAtLeast(kDecryptedBufferSize);\n        if (!m_DecryptedDataAligned.IsAllocated())\n          return E_OUTOFMEMORY;\n      }\n      RINOK(m_RarAES->Init())\n      size_t decryptedDataSizeT = kDecryptedBufferSize;\n      RINOK(ReadStream(m_Stream, m_DecryptedDataAligned, &decryptedDataSizeT))\n      m_DecryptedDataSize = (UInt32)decryptedDataSizeT;\n      m_DecryptedDataSize = m_RarAES->Filter(m_DecryptedDataAligned, m_DecryptedDataSize);\n\n      m_CryptoMode = true;\n      m_CryptoPos = 0;\n    }\n\n    m_FileHeaderData.AllocAtLeast(7);\n    size_t processed = 7;\n    RINOK(ReadBytesSpec((Byte *)m_FileHeaderData, &processed))\n    if (processed != 7)\n    {\n      if (processed != 0)\n        error = k_ErrorType_UnexpectedEnd;\n      ArcInfo.EndPos = m_Position + processed; // test it\n      return S_OK;\n    }\n\n    const Byte *p = m_FileHeaderData;\n    m_BlockHeader.CRC = Get16(p + 0);\n    m_BlockHeader.Type = p[2];\n    m_BlockHeader.Flags = Get16(p + 3);\n    m_BlockHeader.HeadSize = Get16(p + 5);\n\n    if (m_BlockHeader.HeadSize < 7)\n    {\n      error = k_ErrorType_Corrupted;\n      return S_OK;\n      // ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);\n    }\n\n    if (m_BlockHeader.Type < NHeader::NBlockType::kFileHeader ||\n        m_BlockHeader.Type > NHeader::NBlockType::kEndOfArchive)\n    {\n      error = m_CryptoMode ?\n          k_ErrorType_DecryptionError :\n          k_ErrorType_Corrupted;\n      return S_OK;\n    }\n\n    if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)\n    {\n      bool footerError = false;\n\n      unsigned expectHeadLen = 7;\n      if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_DataCRC)\n        expectHeadLen += 4;\n      if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_VolNumber)\n        expectHeadLen += 2;\n      if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_RevSpace)\n        expectHeadLen += 7;\n\n      // rar 5.0 beta 1 writes incorrect RevSpace and headSize\n\n      if (m_BlockHeader.HeadSize < expectHeadLen)\n        HeaderErrorWarning = true;\n        \n      if (m_BlockHeader.HeadSize > 7)\n      {\n        /* We suppose that EndOfArchive header is always small.\n           It's only 20 bytes for multivolume\n           Fix the limit, if larger footers are possible */\n        if (m_BlockHeader.HeadSize > (1 << 8))\n          footerError = true;\n        else\n        {\n          if (m_FileHeaderData.Size() < m_BlockHeader.HeadSize)\n            m_FileHeaderData.ChangeSize_KeepData(m_BlockHeader.HeadSize, 7);\n          UInt32 afterSize = m_BlockHeader.HeadSize - 7;\n          if (ReadBytesAndTestSize(m_FileHeaderData + 7, afterSize))\n            processed += afterSize;\n          else\n          {\n            if (!m_CryptoMode)\n            {\n              error = k_ErrorType_UnexpectedEnd;\n              return S_OK;\n            }\n            footerError = true;\n          }\n        }\n      }\n      \n      if (footerError || !CheckHeaderCrc(m_FileHeaderData, m_BlockHeader.HeadSize))\n      {\n        error = m_CryptoMode ?\n          k_ErrorType_DecryptionError :\n          k_ErrorType_Corrupted;\n      }\n      else\n      {\n        ArcInfo.EndFlags = m_BlockHeader.Flags;\n        UInt32 offset = 7;\n        \n        if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_DataCRC)\n        {\n          if (processed < offset + 4)\n            error = k_ErrorType_Corrupted;\n          else\n            ArcInfo.DataCRC = Get32(m_FileHeaderData + offset);\n          offset += 4;\n        }\n        \n        if (m_BlockHeader.Flags & NHeader::NArchive::kEndOfArc_Flags_VolNumber)\n        {\n          if (processed < offset + 2)\n            error = k_ErrorType_Corrupted;\n          else\n            ArcInfo.VolNumber = (UInt32)Get16(m_FileHeaderData + offset);\n        }\n\n        ArcInfo.EndOfArchive_was_Read = true;\n      }\n\n      m_Position += processed;\n      FinishCryptoBlock();\n      ArcInfo.EndPos = m_Position;\n      return S_OK;\n    }\n\n    if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader\n        /* || m_BlockHeader.Type == NHeader::NBlockType::kSubBlock */)\n    {\n      if (m_FileHeaderData.Size() < m_BlockHeader.HeadSize)\n        m_FileHeaderData.ChangeSize_KeepData(m_BlockHeader.HeadSize, 7);\n      // m_CurData = (Byte *)m_FileHeaderData;\n      // m_PosLimit = m_BlockHeader.HeadSize;\n      if (!ReadBytesAndTestSize(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7))\n      {\n        error = k_ErrorType_UnexpectedEnd;\n        return S_OK;\n      }\n\n      bool okItem = ReadHeaderReal(m_FileHeaderData + 7, m_BlockHeader.HeadSize - 7, item);\n      if (okItem)\n      {\n        if (!CheckHeaderCrc(m_FileHeaderData, (unsigned)m_BlockHeader.HeadSize - item.CommentSize))\n        {\n          error = k_ErrorType_Corrupted; // ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);\n          return S_OK;\n        }\n        filled = true;\n      }\n\n      FinishCryptoBlock();\n      m_CryptoMode = false;\n      // Move Position to compressed Data;\n      RINOK(InStream_SeekSet(m_Stream, m_Position))\n      AddToSeekValue(item.PackSize);  // m_Position points to next header;\n      // if (okItem)\n        return S_OK;\n      /*\n      else\n        continue;\n      */\n    }\n    \n    if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 10))\n    {\n      error = k_ErrorType_DecryptionError;\n      return S_OK;\n    }\n    \n    if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)\n    {\n      if (m_FileHeaderData.Size() < 7 + 4)\n        m_FileHeaderData.ChangeSize_KeepData(7 + 4, 7);\n      if (!ReadBytesAndTestSize(m_FileHeaderData + 7, 4))\n      {\n        error = k_ErrorType_UnexpectedEnd;\n        return S_OK;\n      }\n      UInt32 dataSize = Get32(m_FileHeaderData + 7);\n      AddToSeekValue(dataSize);\n      if (m_CryptoMode && dataSize > (1 << 27))\n      {\n        error = k_ErrorType_DecryptionError;\n        return S_OK;\n      }\n      m_CryptoPos = m_BlockHeader.HeadSize;\n    }\n    else\n      m_CryptoPos = 0;\n    \n    {\n      UInt64 newPos = m_Position + m_BlockHeader.HeadSize;\n      if (newPos > ArcInfo.FileSize)\n      {\n        error = k_ErrorType_UnexpectedEnd;\n        return S_OK;\n      }\n    }\n    AddToSeekValue(m_BlockHeader.HeadSize);\n    FinishCryptoBlock();\n    m_CryptoMode = false;\n  }\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidAttrib,\n\n  kpidEncrypted,\n  kpidSolid,\n  kpidCommented,\n  kpidSplitBefore,\n  kpidSplitAfter,\n  kpidCRC,\n  kpidHostOS,\n  kpidMethod,\n  kpidUnpackVer,\n\n  kpidVolumeIndex\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidTotalPhySize,\n  kpidCharacts,\n  kpidSolid,\n  kpidNumBlocks,\n  // kpidEncrypted,\n  kpidIsVolume,\n  kpidVolumeIndex,\n  kpidNumVolumes\n  // kpidCommented\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nUInt64 CHandler::GetPackSize(unsigned refIndex) const\n{\n  const CRefItem &refItem = _refItems[refIndex];\n  UInt64 totalPackSize = 0;\n  for (unsigned i = 0; i < refItem.NumItems; i++)\n    totalPackSize += _items[refItem.ItemIndex + i].PackSize;\n  return totalPackSize;\n}\n\nbool CHandler::IsSolid(unsigned refIndex) const\n{\n  const CItem &item = _items[_refItems[refIndex].ItemIndex];\n  if (item.UnPackVersion < 20)\n  {\n    if (_arcInfo.IsSolid())\n      return (refIndex > 0);\n    return false;\n  }\n  return item.IsSolid();\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidVolumeIndex: if (_arcInfo.Is_VolNumber_Defined()) prop = (UInt32)_arcInfo.VolNumber; break;\n    case kpidSolid: prop = _arcInfo.IsSolid(); break;\n    case kpidCharacts:\n    {\n      AString s (FlagsToString(k_Flags, Z7_ARRAY_SIZE(k_Flags), _arcInfo.Flags));\n      // FLAGS_TO_PROP(k_Flags, _arcInfo.Flags, prop);\n      if (_arcInfo.Is_DataCRC_Defined())\n      {\n        s.Add_Space_if_NotEmpty();\n        s += \"VolCRC\";\n      }\n      prop = s;\n      break;\n    }\n    // case kpidEncrypted: prop = _arcInfo.IsEncrypted(); break; // it's for encrypted names.\n    case kpidIsVolume: prop = _arcInfo.IsVolume(); break;\n    case kpidNumVolumes: prop = (UInt32)_arcs.Size(); break;\n    case kpidOffset: if (_arcs.Size() == 1 && _arcInfo.StartPos != 0) prop = _arcInfo.StartPos; break;\n\n    case kpidTotalPhySize:\n    {\n      if (_arcs.Size() > 1)\n      {\n        UInt64 sum = 0;\n        FOR_VECTOR (v, _arcs)\n          sum += _arcs[v].PhySize;\n        prop = sum;\n      }\n      break;\n    }\n\n    case kpidPhySize:\n    {\n      if (_arcs.Size() != 0)\n        prop = _arcInfo.GetPhySize();\n      break;\n    }\n\n    // case kpidCommented: prop = _arcInfo.IsCommented(); break;\n\n    case kpidNumBlocks:\n    {\n      UInt32 numBlocks = 0;\n      FOR_VECTOR (i, _refItems)\n        if (!IsSolid(i))\n          numBlocks++;\n      prop = (UInt32)numBlocks;\n      break;\n    }\n    \n    \n    case kpidError:\n    {\n      // if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;\n\n      if (/* &_missingVol || */ !_missingVolName.IsEmpty())\n      {\n        UString s (\"Missing volume : \");\n        s += _missingVolName;\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = _errorFlags;\n      if (!_isArc)\n        v |= kpv_ErrorFlags_IsNotArc;\n      prop = v;\n      break;\n    }\n\n    case kpidWarningFlags:\n    {\n      if (_warningFlags != 0)\n        prop = _warningFlags;\n      break;\n    }\n\n    case kpidExtension:\n      if (_arcs.Size() == 1)\n      {\n        if (_arcInfo.Is_VolNumber_Defined())\n        {\n          AString s (\"part\");\n          UInt32 v = (UInt32)_arcInfo.VolNumber + 1;\n          if (v < 10)\n            s += '0';\n          s.Add_UInt32(v);\n          s += \".rar\";\n          prop = s;\n        }\n      }\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _refItems.Size();\n  return S_OK;\n}\n\nstatic bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &ft)\n{\n  if (!NTime::DosTime_To_FileTime(rarTime.DosTime, ft))\n    return false;\n  UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;\n  v += (UInt32)rarTime.LowSecond * 10000000;\n  v +=\n      ((UInt32)rarTime.SubTime[2] << 16) +\n      ((UInt32)rarTime.SubTime[1] << 8) +\n      ((UInt32)rarTime.SubTime[0]);\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n  return true;\n}\n\nstatic void RarTimeToProp(const CRarTime &rarTime, NCOM::CPropVariant &prop)\n{\n  FILETIME localFileTime, utc;\n  if (RarTimeToFileTime(rarTime, localFileTime)\n      && LocalFileTimeToFileTime(&localFileTime, &utc))\n    prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_100ns);\n  /*\n  else\n    utc.dwHighDateTime = utc.dwLowDateTime = 0;\n  // prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_100ns);\n  */\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  const CRefItem &refItem = _refItems[index];\n  const CItem &item = _items[refItem.ItemIndex];\n  const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];\n\n  /*\n  const CItem *mainItem = &item;\n  if (item.BaseFileIndex >= 0)\n    mainItem = &_items[_refItems[item.BaseFileIndex].ItemIndex];\n  */\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      /*\n      UString u;\n      if (item.BaseFileIndex >= 0)\n        u = mainItem->GetName();\n      u += item.GetName();\n      */\n      prop = (const wchar_t *)NItemName::WinPathToOsPath(item.GetName());\n      break;\n    }\n    case kpidIsDir: prop = item.IsDir(); break;\n    case kpidSize: if (lastItem.Is_Size_Defined()) prop = lastItem.Size; break;\n    case kpidPackSize: prop = GetPackSize(index); break;\n    case kpidMTime: RarTimeToProp(item.MTime, prop); break;\n    case kpidCTime: if (item.CTimeDefined) RarTimeToProp(item.CTime, prop); break;\n    case kpidATime: if (item.ATimeDefined) RarTimeToProp(item.ATime, prop); break;\n    case kpidAttrib: prop = item.GetWinAttrib(); break;\n    case kpidEncrypted: prop = item.IsEncrypted(); break;\n    case kpidSolid: prop = IsSolid(index); break;\n    case kpidCommented: prop = item.IsCommented(); break;\n    case kpidSplitBefore: prop = item.IsSplitBefore(); break;\n    case kpidSplitAfter: prop = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter(); break;\n    \n    case kpidVolumeIndex:\n      if (_arcInfo.Is_VolNumber_Defined())\n        prop = (UInt32)(_arcInfo.VolNumber + refItem.VolumeIndex);\n      break;\n\n    case kpidCRC:\n    {\n      prop = ((lastItem.IsSplitAfter()) ? item.FileCRC : lastItem.FileCRC);\n      break;\n    }\n    case kpidUnpackVer: prop = item.UnPackVersion; break;\n    case kpidMethod:\n    {\n      char s[16];\n      Byte m = item.Method;\n      if (m < (Byte)'0' || m > (Byte)'5')\n        ConvertUInt32ToString(m, s);\n      else\n      {\n        s[0] = 'm';\n        s[1] = (char)m;\n        s[2] = 0;\n        if (!item.IsDir())\n        {\n          s[2] = ':';\n          ConvertUInt32ToString(16 + item.GetDictSize(), &s[3]);\n        }\n      }\n      prop = s;\n      break;\n    }\n    case kpidHostOS:\n      TYPE_TO_PROP(kHostOS, item.HostOS, prop);\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *openCallback)\n{\n  {\n    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\n    CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n    \n    CVolumeName seqName;\n\n    UInt64 totalBytes = 0;\n    UInt64 curBytes = 0;\n\n    if (openCallback)\n    {\n      openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\n      openCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);\n    }\n\n    bool nextVol_is_Required = false;\n\n    CInArchive archive;\n\n    for (;;)\n    {\n      CMyComPtr<IInStream> inStream;\n      if (!_arcs.IsEmpty())\n      {\n        if (!openVolumeCallback)\n          break;\n        \n        if (_arcs.Size() == 1)\n        {\n          if (!_arcInfo.IsVolume())\n            break;\n          UString baseName;\n          {\n            NCOM::CPropVariant prop;\n            RINOK(openVolumeCallback->GetProperty(kpidName, &prop))\n            if (prop.vt != VT_BSTR)\n              break;\n            baseName = prop.bstrVal;\n          }\n          if (!seqName.InitName(baseName, _arcInfo.HaveNewVolumeName()))\n            break;\n          /*\n          if (_arcInfo.HaveNewVolumeName() && !_arcInfo.IsFirstVolume())\n          {\n            seqName.MakeBeforeFirstName();\n          }\n          */\n        }\n\n        const UString volName = seqName.GetNextName();\n        \n        HRESULT result = openVolumeCallback->GetStream(volName, &inStream);\n\n        if (result != S_OK && result != S_FALSE)\n          return result;\n\n        if (!inStream || result != S_OK)\n        {\n          if (nextVol_is_Required)\n            _missingVolName = volName;\n          break;\n        }\n      }\n      else\n        inStream = stream;\n\n      UInt64 endPos;\n      RINOK(InStream_AtBegin_GetSize(inStream, endPos))\n      if (openCallback)\n      {\n        totalBytes += endPos;\n        RINOK(openCallback->SetTotal(NULL, &totalBytes))\n      }\n      \n      RINOK(archive.Open(inStream, maxCheckStartPosition))\n      _isArc = true;\n      CItem item;\n      \n      for (;;)\n      {\n        if (archive.m_Position > endPos)\n        {\n          _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;\n          break;\n        }\n        \n        EErrorType error;\n        // bool decryptionError;\n        // AString errorMessageLoc;\n        bool filled;\n        HRESULT result = archive.GetNextItem(item, getTextPassword, filled, error);\n        \n        if (error != k_ErrorType_OK)\n        {\n          if (error == k_ErrorType_UnexpectedEnd)\n            _errorFlags |= kpv_ErrorFlags_UnexpectedEnd;\n          else if (error == k_ErrorType_Corrupted)\n            _errorFlags |= kpv_ErrorFlags_HeadersError;\n          else if (error == k_ErrorType_DecryptionError)\n            _errorFlags |= kpv_ErrorFlags_EncryptedHeadersError;\n\n          // AddErrorMessage(errorMessageLoc);\n        }\n        RINOK(result)\n        \n        if (!filled)\n        {\n          if (error == k_ErrorType_DecryptionError && _items.IsEmpty())\n            return S_FALSE;\n\n          if (archive.ArcInfo.ExtraZeroTail_is_Possible())\n          {\n            /* if there is recovery record for multivolume archive,\n               RAR adds 18 bytes (ZERO bytes) at the end for alignment.\n               We must skip these bytes to prevent phySize warning. */\n            RINOK(InStream_SeekSet(inStream, archive.ArcInfo.EndPos))\n            bool areThereNonZeros;\n            UInt64 numZeros;\n            const UInt64 maxSize = 1 << 12;\n            RINOK(ReadZeroTail(inStream, areThereNonZeros, numZeros, maxSize))\n            if (!areThereNonZeros && numZeros != 0 && numZeros <= maxSize)\n              archive.ArcInfo.EndPos += numZeros;\n          }\n          break;\n        }\n        \n        if (item.IgnoreItem())\n          continue;\n\n        bool needAdd = true;\n        \n        if (item.IsSplitBefore())\n        {\n          if (!_refItems.IsEmpty())\n          {\n            CRefItem &refItem = _refItems.Back();\n            refItem.NumItems++;\n            needAdd = false;\n          }\n        }\n        \n        if (needAdd)\n        {\n          CRefItem refItem;\n          refItem.ItemIndex = _items.Size();\n          refItem.NumItems = 1;\n          refItem.VolumeIndex = _arcs.Size();\n          _refItems.Add(refItem);\n        }\n\n        _items.Add(item);\n        \n        if (openCallback && _items.Size() % 100 == 0)\n        {\n          UInt64 numFiles = _items.Size();\n          UInt64 numBytes = curBytes + item.Position;\n          RINOK(openCallback->SetCompleted(&numFiles, &numBytes))\n        }\n      }\n\n      if (archive.HeaderErrorWarning)\n        _warningFlags |= kpv_ErrorFlags_HeadersError;\n\n      /*\n      if (archive.m_Position < endPos)\n        _warningFlags |= kpv_ErrorFlags_DataAfterEnd;\n      */\n      if (_arcs.IsEmpty())\n        _arcInfo = archive.ArcInfo;\n      // _arcInfo.EndPos = archive.EndPos;\n\n      curBytes += endPos;\n      {\n        CArc &arc = _arcs.AddNew();\n        arc.PhySize = archive.ArcInfo.GetPhySize();\n        arc.Stream = inStream;\n      }\n\n      nextVol_is_Required = false;\n\n      if (!archive.ArcInfo.IsVolume())\n        break;\n\n      if (archive.ArcInfo.EndOfArchive_was_Read)\n      {\n        if (!archive.ArcInfo.AreMoreVolumes())\n          break;\n        nextVol_is_Required = true;\n      }\n    }\n  }\n\n  /*\n  int baseFileIndex = -1;\n  for (unsigned i = 0; i < _refItems.Size(); i++)\n  {\n    CItem &item = _items[_refItems[i].ItemIndex];\n    if (item.IsAltStream)\n      item.BaseFileIndex = baseFileIndex;\n    else\n      baseFileIndex = i;\n  }\n  */\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *openCallback))\n{\n  COM_TRY_BEGIN\n  Close();\n  // try\n  {\n    HRESULT res = Open2(stream, maxCheckStartPosition, openCallback);\n    /*\n    if (res != S_OK)\n      Close();\n    */\n\n    return res;\n  }\n  // catch(const CInArchiveException &) { Close(); return S_FALSE; }\n  // catch(...) { Close(); throw; }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  COM_TRY_BEGIN\n  // _errorMessage.Empty();\n  _missingVolName.Empty();\n  _errorFlags = 0;\n  _warningFlags = 0;\n  _isArc = false;\n  _refItems.Clear();\n  _items.Clear();\n  _arcs.Clear();\n  return S_OK;\n  COM_TRY_END\n}\n\nstruct CMethodItem\n{\n  Byte RarUnPackVersion;\n  CMyComPtr<ICompressCoder> Coder;\n};\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CVolsInStream\n  , ISequentialInStream\n)\n  UInt64 _rem;\n  ISequentialInStream *_stream;\n  const CObjectVector<CArc> *_arcs;\n  const CObjectVector<CItem> *_items;\n  CRefItem _refItem;\n  unsigned _curIndex;\n  UInt32 _crc;\n  bool _calcCrc;\n\npublic:\n  void Init(const CObjectVector<CArc> *arcs,\n      const CObjectVector<CItem> *items,\n      const CRefItem &refItem)\n  {\n    _arcs = arcs;\n    _items = items;\n    _refItem = refItem;\n    _curIndex = 0;\n    _stream = NULL;\n    CrcIsOK = true;\n  }\n\n  bool CrcIsOK;\n};\n\n\nZ7_COM7F_IMF(CVolsInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  UInt32 realProcessedSize = 0;\n\n  while (size != 0)\n  {\n    if (!_stream)\n    {\n      if (_curIndex >= _refItem.NumItems)\n        break;\n      const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];\n      unsigned volIndex = _refItem.VolumeIndex + _curIndex;\n      if (volIndex >= _arcs->Size())\n      {\n        return S_OK;\n        // return S_FALSE;\n      }\n      IInStream *s = (*_arcs)[volIndex].Stream;\n      RINOK(InStream_SeekSet(s, item.GetDataPosition()))\n      _stream = s;\n      _calcCrc = (CrcIsOK && item.IsSplitAfter());\n      _crc = CRC_INIT_VAL;\n      _rem = item.PackSize;\n    }\n    {\n      UInt32 cur = size;\n      if (cur > _rem)\n        cur = (UInt32)_rem;\n      UInt32 num = cur;\n      HRESULT res = _stream->Read(data, cur, &cur);\n      if (_calcCrc)\n        _crc = CrcUpdate(_crc, data, cur);\n      realProcessedSize += cur;\n      if (processedSize)\n        *processedSize = realProcessedSize;\n      data = (Byte *)data + cur;\n      size -= cur;\n      _rem -= cur;\n      if (_rem == 0)\n      {\n        const CItem &item = (*_items)[_refItem.ItemIndex + _curIndex];\n        _curIndex++;\n        if (_calcCrc && CRC_GET_DIGEST(_crc) != item.FileCRC)\n          CrcIsOK = false;\n        _stream = NULL;\n      }\n      if (res != S_OK)\n        return res;\n      if (realProcessedSize != 0)\n        return S_OK;\n      if (cur == 0 && num != 0)\n        return S_OK;\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n  UInt64 // censoredTotalUnPacked = 0,\n        // censoredTotalPacked = 0,\n        importantTotalUnPacked = 0;\n        // importantTotalPacked = 0;\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _refItems.Size();\n  if (numItems == 0)\n    return S_OK;\n  unsigned lastIndex = 0;\n  CRecordVector<unsigned> importantIndexes;\n  CRecordVector<bool> extractStatuses;\n\n  bool isThereUndefinedSize = false;\n\n  for (UInt32 t = 0; t < numItems; t++)\n  {\n    unsigned index = allFilesMode ? t : indices[t];\n    \n    {\n      const CRefItem &refItem = _refItems[index];\n      const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1];\n      \n      if (item.Is_Size_Defined())\n      {\n        // censoredTotalUnPacked += item.Size;\n      }\n      else\n        isThereUndefinedSize = true;\n      \n      // censoredTotalPacked += item.PackSize;\n    }\n    \n    unsigned j;\n    for (j = lastIndex; j <= index; j++)\n      // if (!_items[_refItems[j].ItemIndex].IsSolid())\n      if (!IsSolid(j))\n        lastIndex = j;\n  \n    for (j = lastIndex; j <= index; j++)\n    {\n      const CRefItem &refItem = _refItems[j];\n      const CItem &item = _items[refItem.ItemIndex + refItem.NumItems - 1];\n\n      if (item.Is_Size_Defined())\n        importantTotalUnPacked += item.Size;\n      else\n        isThereUndefinedSize = true;\n      // importantTotalPacked += item.PackSize;\n      importantIndexes.Add(j);\n      extractStatuses.Add(j == index);\n    }\n\n    lastIndex = index + 1;\n  }\n\n  if (importantTotalUnPacked != 0 || !isThereUndefinedSize)\n  {\n    RINOK(extractCallback->SetTotal(importantTotalUnPacked))\n  }\n\n  UInt64 currentImportantTotalUnPacked = 0;\n  UInt64 currentImportantTotalPacked = 0;\n  UInt64 currentUnPackSize, currentPackSize;\n\n  CObjectVector<CMethodItem> methodItems;\n\n  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\n  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\n\n  CFilterCoder *filterStreamSpec = new CFilterCoder(false);\n  CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;\n\n  NCrypto::NRar2::CDecoder *rar20CryptoDecoderSpec = NULL;\n  CMyComPtr<ICompressFilter> rar20CryptoDecoder;\n  NCrypto::NRar3::CDecoder *rar3CryptoDecoderSpec = NULL;\n  CMyComPtr<ICompressFilter> rar3CryptoDecoder;\n\n  CVolsInStream *volsInStreamSpec = NULL;\n  CMyComPtr<ISequentialInStream> volsInStream;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  bool solidStart = true;\n  \n  for (unsigned i = 0;;\n      i++,\n      currentImportantTotalUnPacked += currentUnPackSize,\n      currentImportantTotalPacked += currentPackSize)\n  {\n    lps->InSize = currentImportantTotalPacked;\n    lps->OutSize = currentImportantTotalUnPacked;\n    RINOK(lps->SetCur())\n\n    if (i >= importantIndexes.Size())\n      break;\n\n    CMyComPtr<ISequentialOutStream> realOutStream;\n\n    Int32 askMode;\n    if (extractStatuses[i])\n      askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n    else\n      askMode = NExtract::NAskMode::kSkip;\n\n    UInt32 index = importantIndexes[i];\n\n    const CRefItem &refItem = _refItems[index];\n    const CItem &item = _items[refItem.ItemIndex];\n    const CItem &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];\n    \n    UInt64 outSize = (UInt64)(Int64)-1;\n    currentUnPackSize = 0;\n    if (lastItem.Is_Size_Defined())\n    {\n      outSize = lastItem.Size;\n      currentUnPackSize = outSize;\n    }\n\n    currentPackSize = GetPackSize(index);\n\n    if (item.IgnoreItem())\n      continue;\n\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    if (!IsSolid(index))\n      solidStart = true;\n    if (item.IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    bool mustBeProcessedAnywhere = false;\n    if (i < importantIndexes.Size() - 1)\n    {\n      // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];\n      // const CItem &nextItemInfo = _items[nextRefItem.ItemIndex];\n      // mustBeProcessedAnywhere = nextItemInfo.IsSolid();\n      mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]);\n    }\n    \n    if (!mustBeProcessedAnywhere && !testMode && !realOutStream)\n      continue;\n    \n    if (!realOutStream && !testMode)\n      askMode = NExtract::NAskMode::kSkip;\n\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;\n    CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n    outStreamSpec->SetStream(realOutStream);\n    outStreamSpec->Init();\n    realOutStream.Release();\n    \n    if (!volsInStream)\n    {\n      volsInStreamSpec = new CVolsInStream;\n      volsInStream = volsInStreamSpec;\n    }\n\n    volsInStreamSpec->Init(&_arcs, &_items, refItem);\n\n    UInt64 packSize = currentPackSize;\n\n    // packedPos += item.PackSize;\n    // unpackedPos += 0;\n    \n    CMyComPtr<ISequentialInStream> inStream;\n    \n    if (item.IsEncrypted())\n    {\n      // CMyComPtr<ICryptoSetPassword> cryptoSetPassword;\n      \n      if (item.UnPackVersion >= 29)\n      {\n        if (!rar3CryptoDecoder)\n        {\n          rar3CryptoDecoderSpec = new NCrypto::NRar3::CDecoder;\n          rar3CryptoDecoder = rar3CryptoDecoderSpec;\n        }\n        // rar3CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);\n        /*\n        CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;\n        RINOK(rar3CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,\n            &cryptoProperties));\n        */\n        RINOK(rar3CryptoDecoderSpec->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0))\n        filterStreamSpec->Filter = rar3CryptoDecoder;\n      }\n      else if (item.UnPackVersion >= 20)\n      {\n        if (!rar20CryptoDecoder)\n        {\n          rar20CryptoDecoderSpec = new NCrypto::NRar2::CDecoder;\n          rar20CryptoDecoder = rar20CryptoDecoderSpec;\n        }\n        filterStreamSpec->Filter = rar20CryptoDecoder;\n      }\n      else\n      {\n        outStream.Release();\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))\n        continue;\n      }\n      \n      // RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));\n\n      if (!getTextPassword)\n        extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);\n\n      if (!getTextPassword)\n      {\n        outStream.Release();\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))\n        continue;\n      }\n\n      // if (getTextPassword)\n      {\n        CMyComBSTR_Wipe password;\n        RINOK(getTextPassword->CryptoGetTextPassword(&password))\n        \n        if (item.UnPackVersion >= 29)\n        {\n          unsigned len = 0;\n          if (password)\n            len = MyStringLen(password);\n          if (len > kPasswordLen_MAX)\n            len = kPasswordLen_MAX;\n          CByteBuffer_Wipe buffer(len * 2);\n          for (unsigned k = 0; k < len; k++)\n          {\n            wchar_t c = password[k];\n            ((Byte *)buffer)[k * 2] = (Byte)c;\n            ((Byte *)buffer)[k * 2 + 1] = (Byte)(c >> 8);\n          }\n          rar3CryptoDecoderSpec->SetPassword((const Byte *)buffer, len * 2);\n        }\n        else\n        {\n          AString_Wipe oemPassword;\n          if (password)\n          {\n            UString_Wipe unicode;\n            unicode.SetFromBstr(password);\n            if (unicode.Len() > kPasswordLen_MAX)\n              unicode.DeleteFrom(kPasswordLen_MAX);\n            UnicodeStringToMultiByte2(oemPassword, unicode, CP_OEMCP);\n          }\n          rar20CryptoDecoderSpec->SetPassword((const Byte *)(const char *)oemPassword, oemPassword.Len());\n        }\n      }\n      /*\n      else\n      {\n        RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));\n      }\n      */\n      \n      filterStreamSpec->SetInStream(volsInStream);\n      filterStreamSpec->SetOutStreamSize(NULL);\n      inStream = filterStream;\n    }\n    else\n    {\n      inStream = volsInStream;\n    }\n    \n    CMyComPtr<ICompressCoder> commonCoder;\n    \n    switch (item.Method)\n    {\n      case '0':\n      {\n        commonCoder = copyCoder;\n        break;\n      }\n      case '1':\n      case '2':\n      case '3':\n      case '4':\n      case '5':\n      {\n        unsigned m;\n        for (m = 0; m < methodItems.Size(); m++)\n          if (methodItems[m].RarUnPackVersion == item.UnPackVersion)\n            break;\n        if (m == methodItems.Size())\n        {\n          CMethodItem mi;\n          mi.RarUnPackVersion = item.UnPackVersion;\n\n          mi.Coder.Release();\n          if (item.UnPackVersion <= 40)\n          {\n            UInt32 methodID = 0x40300;\n            if (item.UnPackVersion < 20)\n              methodID += 1;\n            else if (item.UnPackVersion < 29)\n              methodID += 2;\n            else\n              methodID += 3;\n            RINOK(CreateCoder_Id(EXTERNAL_CODECS_VARS methodID, false, mi.Coder))\n          }\n         \n          if (!mi.Coder)\n          {\n            outStream.Release();\n            RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))\n            continue;\n          }\n\n          m = methodItems.Add(mi);\n        }\n        CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder;\n\n        CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;\n        RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2,\n            &compressSetDecoderProperties))\n        \n        Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);\n        if (solidStart)\n        {\n          isSolid = 0;\n          solidStart = false;\n        }\n\n\n        RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1))\n          \n        commonCoder = decoder;\n        break;\n      }\n      default:\n        outStream.Release();\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnsupportedMethod))\n        continue;\n    }\n    \n    HRESULT result = commonCoder->Code(inStream, outStream, &packSize, &outSize, progress);\n    \n    if (item.IsEncrypted())\n      filterStreamSpec->ReleaseInStream();\n    \n    if (outSize == (UInt64)(Int64)-1)\n      currentUnPackSize = outStreamSpec->GetSize();\n\n    int opRes = (volsInStreamSpec->CrcIsOK && outStreamSpec->GetCRC() == lastItem.FileCRC) ?\n        NExtract::NOperationResult::kOK:\n        NExtract::NOperationResult::kCRCError;\n    outStream.Release();\n\n    if (result != S_OK)\n    {\n      if (result == S_FALSE)\n        opRes = NExtract::NOperationResult::kDataError;\n      else if (result == E_NOTIMPL)\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      else\n        return result;\n    }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  \n  return S_OK;\n  COM_TRY_END\n}\n\nIMPL_ISetCompressCodecsInfo\n\nREGISTER_ARC_I(\n  \"Rar\", \"rar r00\", NULL, 3,\n  kMarker,\n  0,\n  NArcInfoFlags::kFindSignature,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/RarHandler.h",
    "content": "﻿// RarHandler.h\n\n#ifndef ZIP7_INC_RAR_HANDLER_H\n#define ZIP7_INC_RAR_HANDLER_H\n\n#include \"../IArchive.h\"\n\n#include \"../../Common/CreateCoder.h\"\n\n#include \"RarItem.h\"\n\nnamespace NArchive {\nnamespace NRar {\n\nstruct CInArcInfo\n{\n  UInt32 Flags;\n  Byte EncryptVersion;\n  \n  UInt64 StartPos;\n  UInt64 EndPos;\n  UInt64 FileSize;\n\n  UInt32 EndFlags;\n  UInt32 VolNumber;\n  UInt32 DataCRC;\n  bool EndOfArchive_was_Read;\n\n  CInArcInfo(): EndFlags(0), VolNumber(0), EndOfArchive_was_Read(false) {}\n\n  UInt64 GetPhySize() const { return EndPos - StartPos; }\n\n  bool ExtraZeroTail_is_Possible() const { return IsVolume() && IsRecovery() && EndOfArchive_was_Read; }\n\n  bool IsVolume()           const { return (Flags & NHeader::NArchive::kVolume) != 0; }\n  bool IsCommented()        const { return (Flags & NHeader::NArchive::kComment) != 0; }\n  // kLock\n  bool IsSolid()            const { return (Flags & NHeader::NArchive::kSolid) != 0; }\n  bool HaveNewVolumeName()  const { return (Flags & NHeader::NArchive::kNewVolName) != 0; }\n  // kAuthenticity\n  bool IsRecovery()         const { return (Flags & NHeader::NArchive::kRecovery) != 0; }\n  bool IsEncrypted()        const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }\n  bool IsFirstVolume()      const { return (Flags & NHeader::NArchive::kFirstVolume) != 0; }\n\n  // bool IsThereEncryptVer()  const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }\n  // bool IsEncryptOld()       const { return (!IsThereEncryptVer() || EncryptVersion < 36); }\n\n  bool AreMoreVolumes()       const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_NextVol) != 0; }\n  bool Is_VolNumber_Defined() const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_VolNumber) != 0; }\n  bool Is_DataCRC_Defined()   const { return (EndFlags & NHeader::NArchive::kEndOfArc_Flags_DataCRC) != 0; }\n};\n\nstruct CArc\n{\n  CMyComPtr<IInStream> Stream;\n  UInt64 PhySize;\n  // CByteBuffer Comment;\n\n  CArc(): PhySize(0) {}\n  ISequentialInStream *CreateLimitedStream(UInt64 offset, UInt64 size) const;\n};\n\nstruct CRefItem\n{\n  unsigned VolumeIndex;\n  unsigned ItemIndex;\n  unsigned NumItems;\n};\n\nclass CHandler Z7_final:\n  public IInArchive,\n  Z7_PUBLIC_ISetCompressCodecsInfo_IFEC\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IInArchive)\n  Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n  \n  Z7_IFACE_COM7_IMP(IInArchive)\n  DECL_ISetCompressCodecsInfo\n\n  bool _isArc;\n\n  CRecordVector<CRefItem> _refItems;\n  CObjectVector<CItem> _items;\n  CObjectVector<CArc> _arcs;\n  NArchive::NRar::CInArcInfo _arcInfo;\n  // AString _errorMessage;\n  UInt32 _errorFlags;\n  UInt32 _warningFlags;\n  UString _missingVolName;\n\n  DECL_EXTERNAL_CODECS_VARS\n\n  UInt64 GetPackSize(unsigned refIndex) const;\n  bool IsSolid(unsigned refIndex) const;\n  \n  /*\n  void AddErrorMessage(const AString &s)\n  {\n    if (!_errorMessage.IsEmpty())\n      _errorMessage.Add_LF();\n    _errorMessage += s;\n  }\n  */\n\n  HRESULT Open2(IInStream *stream,\n      const UInt64 *maxCheckStartPosition,\n      IArchiveOpenCallback *openCallback);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/RarHeader.h",
    "content": "﻿// Archive/RarHeader.h\n\n#ifndef ZIP7_INC_ARCHIVE_RAR_HEADER_H\n#define ZIP7_INC_ARCHIVE_RAR_HEADER_H\n\n#include \"../../../Common/MyTypes.h\"\n\nnamespace NArchive {\nnamespace NRar {\nnamespace NHeader {\n\nconst unsigned kMarkerSize = 7;\n  \nconst unsigned kArchiveSolid = 0x1;\n\nnamespace NBlockType\n{\n  enum EBlockType\n  {\n    kMarker = 0x72,\n    kArchiveHeader,\n    kFileHeader,\n    kCommentHeader,\n    kOldAuthenticity,\n    kOldSubBlock,\n    kRecoveryRecord,\n    kAuthenticity,\n    kSubBlock,\n    kEndOfArchive\n  };\n}\n\nnamespace NArchive\n{\n  const UInt16 kVolume  = 1;\n  const UInt16 kComment = 2;\n  const UInt16 kLock    = 4;\n  const UInt16 kSolid   = 8;\n  const UInt16 kNewVolName = 0x10; // ('volname.partN.rar')\n  const UInt16 kAuthenticity  = 0x20;\n  const UInt16 kRecovery = 0x40;\n  const UInt16 kBlockEncryption  = 0x80;\n  const UInt16 kFirstVolume = 0x100; // (set only by RAR 3.0 and later)\n\n  // const UInt16 kEncryptVer = 0x200; // RAR 3.6 : that feature was discarded by origial RAR\n\n  const UInt16 kEndOfArc_Flags_NextVol   = 1;\n  const UInt16 kEndOfArc_Flags_DataCRC   = 2;\n  const UInt16 kEndOfArc_Flags_RevSpace  = 4;\n  const UInt16 kEndOfArc_Flags_VolNumber = 8;\n\n  const unsigned kHeaderSizeMin = 7;\n  \n  const unsigned kArchiveHeaderSize = 13;\n\n  const unsigned kBlockHeadersAreEncrypted = 0x80;\n}\n\nnamespace NFile\n{\n  const unsigned kSplitBefore = 1 << 0;\n  const unsigned kSplitAfter  = 1 << 1;\n  const unsigned kEncrypted   = 1 << 2;\n  const unsigned kComment     = 1 << 3;\n  const unsigned kSolid       = 1 << 4;\n  \n  const unsigned kDictBitStart     = 5;\n  const unsigned kNumDictBits  = 3;\n  const unsigned kDictMask         = (1 << kNumDictBits) - 1;\n  const unsigned kDictDirectoryValue  = 0x7;\n  \n  const unsigned kSize64Bits    = 1 << 8;\n  const unsigned kUnicodeName   = 1 << 9;\n  const unsigned kSalt          = 1 << 10;\n  const unsigned kOldVersion    = 1 << 11;\n  const unsigned kExtTime       = 1 << 12;\n  // const unsigned kExtFlags      = 1 << 13;\n  // const unsigned kSkipIfUnknown = 1 << 14;\n\n  const unsigned kLongBlock    = 1 << 15;\n  \n  /*\n  struct CBlock\n  {\n    // UInt16 HeadCRC;\n    // Byte Type;\n    // UInt16 Flags;\n    // UInt16 HeadSize;\n    UInt32 PackSize;\n    UInt32 UnPackSize;\n    Byte HostOS;\n    UInt32 FileCRC;\n    UInt32 Time;\n    Byte UnPackVersion;\n    Byte Method;\n    UInt16 NameSize;\n    UInt32 Attributes;\n  };\n  */\n\n  /*\n  struct CBlock32\n  {\n    UInt16 HeadCRC;\n    Byte Type;\n    UInt16 Flags;\n    UInt16 HeadSize;\n    UInt32 PackSize;\n    UInt32 UnPackSize;\n    Byte HostOS;\n    UInt32 FileCRC;\n    UInt32 Time;\n    Byte UnPackVersion;\n    Byte Method;\n    UInt16 NameSize;\n    UInt32 Attributes;\n    UInt16 GetRealCRC(const void *aName, UInt32 aNameSize,\n        bool anExtraDataDefined = false, Byte *anExtraData = 0) const;\n  };\n  struct CBlock64\n  {\n    UInt16 HeadCRC;\n    Byte Type;\n    UInt16 Flags;\n    UInt16 HeadSize;\n    UInt32 PackSizeLow;\n    UInt32 UnPackSizeLow;\n    Byte HostOS;\n    UInt32 FileCRC;\n    UInt32 Time;\n    Byte UnPackVersion;\n    Byte Method;\n    UInt16 NameSize;\n    UInt32 Attributes;\n    UInt32 PackSizeHigh;\n    UInt32 UnPackSizeHigh;\n    UInt16 GetRealCRC(const void *aName, UInt32 aNameSize) const;\n  };\n  */\n  \n  const unsigned kLabelFileAttribute            = 0x08;\n  const unsigned kWinFileDirectoryAttributeMask = 0x10;\n  \n  enum CHostOS\n  {\n    kHostMSDOS = 0,\n    kHostOS2   = 1,\n    kHostWin32 = 2,\n    kHostUnix  = 3,\n    kHostMacOS = 4,\n    kHostBeOS  = 5\n  };\n}\n\nnamespace NBlock\n{\n  const UInt16 kLongBlock = 1 << 15;\n  struct CBlock\n  {\n    UInt16 CRC;\n    Byte Type;\n    UInt16 Flags;\n    UInt16 HeadSize;\n    //  UInt32 DataSize;\n  };\n}\n\n/*\nstruct CSubBlock\n{\n  UInt16 HeadCRC;\n  Byte HeadType;\n  UInt16 Flags;\n  UInt16 HeadSize;\n  UInt32 DataSize;\n  UInt16 SubType;\n  Byte Level; // Reserved : Must be 0\n};\n\nstruct CCommentBlock\n{\n  UInt16 HeadCRC;\n  Byte HeadType;\n  UInt16 Flags;\n  UInt16 HeadSize;\n  UInt16 UnpSize;\n  Byte UnpVer;\n  Byte Method;\n  UInt16 CommCRC;\n};\n\n\nstruct CProtectHeader\n{\n  UInt16 HeadCRC;\n  Byte HeadType;\n  UInt16 Flags;\n  UInt16 HeadSize;\n  UInt32 DataSize;\n  Byte Version;\n  UInt16 RecSectors;\n  UInt32 TotalBlocks;\n  Byte Mark[8];\n};\n*/\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/RarItem.h",
    "content": "﻿// RarItem.h\n\n#ifndef ZIP7_INC_ARCHIVE_RAR_ITEM_H\n#define ZIP7_INC_ARCHIVE_RAR_ITEM_H\n\n#include \"../../../Common/StringConvert.h\"\n\n#include \"RarHeader.h\"\n\nnamespace NArchive {\nnamespace NRar {\n\nstruct CRarTime\n{\n  UInt32 DosTime;\n  Byte LowSecond;\n  Byte SubTime[3];\n};\n\nstruct CItem\n{\n  UInt64 Size;\n  UInt64 PackSize;\n  \n  CRarTime CTime;\n  CRarTime ATime;\n  CRarTime MTime;\n\n  UInt32 FileCRC;\n  UInt32 Attrib;\n\n  UInt16 Flags;\n  Byte HostOS;\n  Byte UnPackVersion;\n  Byte Method;\n\n  bool CTimeDefined;\n  bool ATimeDefined;\n\n  AString Name;\n  UString UnicodeName;\n\n  Byte Salt[8];\n  \n  bool Is_Size_Defined() const { return Size != (UInt64)(Int64)-1; }\n\n  bool IsEncrypted()   const { return (Flags & NHeader::NFile::kEncrypted) != 0; }\n  bool IsSolid()       const { return (Flags & NHeader::NFile::kSolid) != 0; }\n  bool IsCommented()   const { return (Flags & NHeader::NFile::kComment) != 0; }\n  bool IsSplitBefore() const { return (Flags & NHeader::NFile::kSplitBefore) != 0; }\n  bool IsSplitAfter()  const { return (Flags & NHeader::NFile::kSplitAfter) != 0; }\n  bool HasSalt()       const { return (Flags & NHeader::NFile::kSalt) != 0; }\n  bool HasExtTime()    const { return (Flags & NHeader::NFile::kExtTime) != 0; }\n  bool HasUnicodeName()const { return (Flags & NHeader::NFile::kUnicodeName) != 0; }\n  bool IsOldVersion()  const { return (Flags & NHeader::NFile::kOldVersion) != 0; }\n  \n  UInt32 GetDictSize() const { return (Flags >> NHeader::NFile::kDictBitStart) & NHeader::NFile::kDictMask; }\n  bool IsDir() const;\n  bool IgnoreItem() const;\n  UInt32 GetWinAttrib() const;\n\n  UInt64 Position;\n  unsigned MainPartSize;\n  UInt16 CommentSize;\n  UInt16 AlignSize;\n\n  // int BaseFileIndex;\n  // bool IsAltStream;\n\n  UString GetName() const\n  {\n    if (( /* IsAltStream || */ HasUnicodeName()) && !UnicodeName.IsEmpty())\n      return UnicodeName;\n    return MultiByteToUnicodeString(Name, CP_OEMCP);\n  }\n\n  void Clear()\n  {\n    CTimeDefined = false;\n    ATimeDefined = false;\n    Name.Empty();\n    UnicodeName.Empty();\n    // IsAltStream = false;\n    // BaseFileIndex = -1;\n  }\n\n  CItem() { Clear(); }\n\n  UInt64 GetFullSize()  const { return MainPartSize + CommentSize + AlignSize + PackSize; }\n  //  DWORD GetHeaderWithCommentSize()  const { return MainPartSize + CommentSize; }\n  UInt64 GetCommentPosition() const { return Position + MainPartSize; }\n  UInt64 GetDataPosition()    const { return GetCommentPosition() + CommentSize + AlignSize; }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/RarVol.h",
    "content": "﻿// RarVol.h\n\n#ifndef ZIP7_INC_ARCHIVE_RAR_VOL_H\n#define ZIP7_INC_ARCHIVE_RAR_VOL_H\n\n#include \"../../../Common/StringConvert.h\"\n\n#include \"RarHeader.h\"\n\nnamespace NArchive {\nnamespace NRar {\n\ninline bool IsDigit(wchar_t c)\n{\n  return c >= L'0' && c <= L'9';\n}\n\nclass CVolumeName\n{\n  bool _needChangeForNext;\n  UString _before;\n  UString _changed;\n  UString _after;\npublic:\n  CVolumeName(): _needChangeForNext(true) {}\n\n  bool InitName(const UString &name, bool newStyle = true)\n  {\n    _needChangeForNext = true;\n    _after.Empty();\n    UString base (name);\n    const int dotPos = name.ReverseFind_Dot();\n\n    if (dotPos >= 0)\n    {\n      const UString ext (name.Ptr(dotPos + 1));\n      if (ext.IsEqualTo_Ascii_NoCase(\"rar\"))\n      {\n        _after = name.Ptr(dotPos);\n        base.DeleteFrom(dotPos);\n      }\n      else if (ext.IsEqualTo_Ascii_NoCase(\"exe\"))\n      {\n        _after = \".rar\";\n        base.DeleteFrom(dotPos);\n      }\n      else if (!newStyle)\n      {\n        if (ext.IsEqualTo_Ascii_NoCase(\"000\") ||\n            ext.IsEqualTo_Ascii_NoCase(\"001\") ||\n            ext.IsEqualTo_Ascii_NoCase(\"r00\") ||\n            ext.IsEqualTo_Ascii_NoCase(\"r01\"))\n        {\n          _changed = ext;\n          _before.SetFrom(name.Ptr(), (unsigned)dotPos + 1);\n          return true;\n        }\n      }\n    }\n\n    if (newStyle)\n    {\n      unsigned k = base.Len();\n\n      for (; k != 0; k--)\n        if (IsDigit(base[k - 1]))\n          break;\n\n      unsigned i = k;\n\n      for (; i != 0; i--)\n        if (!IsDigit(base[i - 1]))\n          break;\n\n      if (i != k)\n      {\n        _before.SetFrom(base.Ptr(), i);\n        _changed.SetFrom(base.Ptr(i), k - i);\n        _after.Insert(0, base.Ptr(k));\n        return true;\n      }\n    }\n    \n    _after.Empty();\n    _before = base;\n    _before.Add_Dot();\n    _changed = \"r00\";\n    _needChangeForNext = false;\n    return true;\n  }\n\n  /*\n  void MakeBeforeFirstName()\n  {\n    unsigned len = _changed.Len();\n    _changed.Empty();\n    for (unsigned i = 0; i < len; i++)\n      _changed += L'0';\n  }\n  */\n\n  UString GetNextName()\n  {\n    if (_needChangeForNext)\n    {\n      unsigned i = _changed.Len();\n      if (i == 0)\n        return UString();\n      for (;;)\n      {\n        wchar_t c = _changed[--i];\n        if (c == L'9')\n        {\n          c = L'0';\n          _changed.ReplaceOneCharAtPos(i, c);\n          if (i == 0)\n          {\n            _changed.InsertAtFront(L'1');\n            break;\n          }\n          continue;\n        }\n        c++;\n        _changed.ReplaceOneCharAtPos(i, c);\n        break;\n      }\n    }\n    \n    _needChangeForNext = true;\n    return _before + _changed + _after;\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Rar/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/RpmHandler.cpp",
    "content": "﻿// RpmHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/StringConvert.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n// #define Z7_RPM_SHOW_METADATA\n\nusing namespace NWindows;\n\n#define Get16(p) GetBe16(p)\n#define Get32(p) GetBe32(p)\n\nnamespace NArchive {\nnamespace NRpm {\n\nstatic const unsigned kNameSize = 66;\nstatic const unsigned kLeadSize = kNameSize + 30;\nstatic const unsigned k_HeaderSig_Size = 16;\nstatic const unsigned k_Entry_Size = 16;\n\n#define RPMSIG_NONE         0  // Old signature\n#define RPMSIG_PGP262_1024  1  // Old signature\n#define RPMSIG_HEADERSIG    5  // New signature\n\nenum\n{\n  kRpmType_Bin = 0,\n  kRpmType_Src = 1\n};\n\n// There are two sets of TAGs: signature tags and header tags\n\n// ----- Signature TAGs -----\n\n#define RPMSIGTAG_SIZE 1000 // Header + Payload size (32bit)\n\n// ----- Header TAGs -----\n\n#define RPMTAG_NAME       1000\n#define RPMTAG_VERSION    1001\n#define RPMTAG_RELEASE    1002\n#define RPMTAG_BUILDTIME  1006\n#define RPMTAG_OS         1021  // string (old version used int?)\n#define RPMTAG_ARCH       1022  // string (old version used int?)\n#define RPMTAG_PAYLOADFORMAT      1124\n#define RPMTAG_PAYLOADCOMPRESSOR  1125\n// #define RPMTAG_PAYLOADFLAGS       1126\n\nenum\n{\n  k_EntryType_NULL,\n  k_EntryType_CHAR,\n  k_EntryType_INT8,\n  k_EntryType_INT16,\n  k_EntryType_INT32,\n  k_EntryType_INT64,\n  k_EntryType_STRING,\n  k_EntryType_BIN,\n  k_EntryType_STRING_ARRAY,\n  k_EntryType_I18NSTRING\n};\n\nstatic const char * const k_CPUs[] =\n{\n    \"noarch\"\n  , \"i386\"\n  , \"alpha\"\n  , \"sparc\"\n  , \"mips\"\n  , \"ppc\"\n  , \"m68k\"\n  , \"sgi\"\n  , \"rs6000\"\n  , \"ia64\"\n  , \"sparc64\"  // 10 ???\n  , \"mipsel\"\n  , \"arm\"\n  , \"m68kmint\"\n  , \"s390\"\n  , \"s390x\"\n  , \"ppc64\"\n  , \"sh\"\n  , \"xtensa\"\n  , \"aarch64\"       // 19\n  , \"mipsr6\"        // 20\n  , \"mips64r6\"      // 21\n  , \"riscv64\"       // 22\n  , \"loongarch64\"   // 23\n  // , \"24\"\n  // , \"25\"\n  // , \"loongarch64\"   // 26  : why 23 and 26 for loongarch64?\n  // 255 for some non specified arch\n};\n\nstatic const char * const k_OS[] =\n{\n    \"0\"\n  , \"Linux\"\n  , \"Irix\"\n  , \"solaris\"\n  , \"SunOS\"\n  , \"AmigaOS\" // AIX\n  , \"HP-UX\"\n  , \"osf\"\n  , \"FreeBSD\"\n  , \"SCO_SV\"\n  , \"Irix64\"\n  , \"NextStep\"\n  , \"bsdi\"\n  , \"machten\"\n  , \"cygwin32-NT\"\n  , \"cygwin32-95\"\n  , \"MP_RAS\"\n  , \"MiNT\"\n  , \"OS/390\"\n  , \"VM/ESA\"\n  , \"Linux/390\"  // \"Linux/ESA\"\n  , \"Darwin\" // \"MacOSX\" 21\n};\n\nstruct CLead\n{\n  Byte Major;\n  // Byte Minor;\n  UInt16 Type;\n  UInt16 Cpu;\n  UInt16 Os;\n  UInt16 SignatureType;\n  char Name[kNameSize];\n  // char Reserved[16];\n\n  void Parse(const Byte *p)\n  {\n    Major = p[4];\n    // Minor = p[5];\n    Type = Get16(p + 6);\n    Cpu= Get16(p + 8);\n    memcpy(Name, p + 10, kNameSize);\n    p += 10 + kNameSize;\n    Os = Get16(p);\n    SignatureType = Get16(p + 2);\n  }\n\n  bool IsSupported() const { return Major >= 3 && Type <= 1; }\n};\n\nstruct CEntry\n{\n  UInt32 Tag;\n  UInt32 Type;\n  UInt32 Offset;\n  UInt32 Count;\n  \n  void Parse(const Byte *p)\n  {\n    Tag = Get32(p + 0);\n    Type = Get32(p + 4);\n    Offset = Get32(p + 8);\n    Count = Get32(p + 12);\n  }\n};\n\n\n#ifdef Z7_RPM_SHOW_METADATA\nstruct CMetaFile\n{\n  UInt32 Tag;\n  UInt32 Offset;\n  UInt32 Size;\n};\n#endif\n\nZ7_class_CHandler_final: public CHandlerCont\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Cont)\n\n  UInt64 _headersSize; // is equal to start offset of payload data\n  UInt64 _payloadSize;\n  UInt64 _size;\n    // _size = _payloadSize, if (_payloadSize_Defined)\n    // _size = (fileSize - _headersSize), if (!_payloadSize_Defined)\n  UInt64 _phySize; // _headersSize + _payloadSize, if (_phySize_Defined)\n  UInt32 _headerPlusPayload_Size;\n  UInt32 _buildTime;\n  \n  bool _payloadSize_Defined;\n  bool _phySize_Defined;\n  bool _headerPlusPayload_Size_Defined;\n  bool _time_Defined;\n\n  Byte _payloadSig[6]; // start data of payload\n\n  AString _name;    // p7zip\n  AString _version; // 9.20.1\n  AString _release; // 8.1.1\n  AString _arch;    // x86_64\n  AString _os;      // linux\n  \n  AString _format;      // cpio\n  AString _compressor;  // xz, gzip, bzip2, lzma, zstd\n\n  CLead _lead;\n\n  #ifdef Z7_RPM_SHOW_METADATA\n  AString _metadata;\n  CRecordVector<CMetaFile> _metaFiles;\n  #endif\n\n  void SetTime(NCOM::CPropVariant &prop) const\n  {\n    if (_time_Defined && _buildTime != 0)\n      PropVariant_SetFrom_UnixTime(prop, _buildTime);\n  }\n\n  void SetStringProp(const AString &s, NCOM::CPropVariant &prop) const\n  {\n    UString us;\n    if (!ConvertUTF8ToUnicode(s, us))\n      us = GetUnicodeString(s);\n    if (!us.IsEmpty())\n      prop = us;\n  }\n\n  void AddCPU(AString &s) const;\n  AString GetBaseName() const;\n  void AddSubFileExtension(AString &res) const;\n\n  HRESULT ReadHeader(ISequentialInStream *stream, bool isMainHeader);\n  HRESULT Open2(ISequentialInStream *stream);\n\n  virtual int GetItem_ExtractInfo(UInt32 /* index */, UInt64 &pos, UInt64 &size) const Z7_override\n  {\n    pos = _headersSize;\n    size = _size;\n    return NExtract::NOperationResult::kOK;\n  }\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidHeadersSize,\n  kpidCpu,\n  kpidHostOS,\n  kpidCTime\n  #ifdef Z7_RPM_SHOW_METADATA\n  , kpidComment\n  #endif\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidCTime\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nvoid CHandler::AddCPU(AString &s) const\n{\n  if (!_arch.IsEmpty())\n    s += _arch;\n  else\n  {\n    if (_lead.Type == kRpmType_Bin)\n    {\n      if (_lead.Cpu < Z7_ARRAY_SIZE(k_CPUs))\n        s += k_CPUs[_lead.Cpu];\n      else\n        s.Add_UInt32(_lead.Cpu);\n    }\n  }\n}\n\nAString CHandler::GetBaseName() const\n{\n  AString s;\n  if (!_name.IsEmpty())\n  {\n    s = _name;\n    if (!_version.IsEmpty())\n    {\n      s.Add_Minus();\n      s += _version;\n    }\n    if (!_release.IsEmpty())\n    {\n      s.Add_Minus();\n      s += _release;\n    }\n  }\n  else\n    s.SetFrom_CalcLen(_lead.Name, kNameSize);\n\n  s.Add_Dot();\n  if (_lead.Type == kRpmType_Src)\n    s += \"src\";\n  else\n    AddCPU(s);\n  return s;\n}\n\nvoid CHandler::AddSubFileExtension(AString &res) const\n{\n  if (!_format.IsEmpty())\n    res += _format;\n  else\n    res += \"cpio\";\n  res.Add_Dot();\n  \n  const char *s;\n  \n  if (!_compressor.IsEmpty())\n  {\n    s = _compressor;\n    if (_compressor.IsEqualTo(\"bzip2\"))\n      s = \"bz2\";\n    else if (_compressor.IsEqualTo(\"gzip\"))\n      s = \"gz\";\n    else if (_compressor.IsEqualTo(\"zstd\"))\n      s = \"zst\";\n  }\n  else\n  {\n    const Byte *p = _payloadSig;\n    if (p[0] == 0x1F && p[1] == 0x8B && p[2] == 8)\n      s = \"gz\";\n    else if (p[0] == 0xFD && p[1] == '7' && p[2] == 'z' && p[3] == 'X' && p[4] == 'Z' && p[5] == 0)\n      s = \"xz\";\n    else if (p[0] == 'B' && p[1] == 'Z' && p[2] == 'h' && p[3] >= '1' && p[3] <= '9')\n      s = \"bz2\";\n    else if (p[0] == 0x28 && p[1] == 0xb5 && p[2] == 0x2f && p[3] == 0xfd)\n      s = \"zst\";\n    else\n      s = \"lzma\";\n  }\n  \n  res += s;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    \n    case kpidHeadersSize: prop = _headersSize; break;\n    case kpidPhySize: if (_phySize_Defined) prop = _phySize; break;\n    \n    case kpidMTime:\n    case kpidCTime:\n      SetTime(prop);\n      break;\n\n    case kpidCpu:\n      {\n        AString s;\n        AddCPU(s);\n        /*\n        if (_lead.Type == kRpmType_Src)\n          s = \"src\";\n        */\n        SetStringProp(s, prop);\n        break;\n      }\n\n    case kpidHostOS:\n      {\n        if (!_os.IsEmpty())\n          SetStringProp(_os, prop);\n        else\n        {\n          TYPE_TO_PROP(k_OS, _lead.Os, prop);\n        }\n        break;\n      }\n\n    #ifdef Z7_RPM_SHOW_METADATA\n    // case kpidComment: SetStringProp(_metadata, prop); break;\n    #endif\n\n    case kpidName:\n    {\n      SetStringProp(GetBaseName() + \".rpm\", prop);\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  if (index == 0)\n  switch (propID)\n  {\n    case kpidSize:\n    case kpidPackSize:\n      prop = _size;\n      break;\n\n    case kpidMTime:\n    case kpidCTime:\n      SetTime(prop);\n      break;\n\n    case kpidPath:\n    {\n      AString s (GetBaseName());\n      s.Add_Dot();\n      AddSubFileExtension(s);\n      SetStringProp(s, prop);\n      break;\n    }\n\n    /*\n    case kpidExtension:\n    {\n      prop = GetSubFileExtension();\n      break;\n    }\n    */\n  }\n  #ifdef Z7_RPM_SHOW_METADATA\n  else\n  {\n    index--;\n    if (index > _metaFiles.Size())\n      return E_INVALIDARG;\n    const CMetaFile &meta = _metaFiles[index];\n    switch (propID)\n    {\n      case kpidSize:\n      case kpidPackSize:\n        prop = meta.Size;\n        break;\n      \n      case kpidMTime:\n      case kpidCTime:\n        SetTime(prop);\n        break;\n      \n      case kpidPath:\n      {\n        AString s (\"[META]\");\n        s.Add_PathSepar();\n        s.Add_UInt32(meta.Tag);\n        prop = s;\n        break;\n      }\n    }\n  }\n  #endif\n\n  prop.Detach(value);\n  return S_OK;\n}\n\n\nHRESULT CHandler::ReadHeader(ISequentialInStream *stream, bool isMainHeader)\n{\n  UInt32 numEntries;\n  UInt32 dataLen;\n  {\n    char buf[k_HeaderSig_Size];\n    RINOK(ReadStream_FALSE(stream, buf, k_HeaderSig_Size))\n    if (Get32(buf) != 0x8EADE801) // buf[3] = 0x01 - is version\n      return S_FALSE;\n    // reserved = Get32(buf + 4);\n    numEntries = Get32(buf + 8);\n    dataLen = Get32(buf + 12);\n    if (numEntries >= 1 << 24)\n      return S_FALSE;\n  }\n  size_t indexSize = (size_t)numEntries * k_Entry_Size;\n  size_t headerSize = indexSize + dataLen;\n  if (headerSize < dataLen)\n    return S_FALSE;\n  CByteBuffer buffer(headerSize);\n  RINOK(ReadStream_FALSE(stream, buffer, headerSize))\n  \n  for (UInt32 i = 0; i < numEntries; i++)\n  {\n    CEntry entry;\n\n    entry.Parse(buffer + (size_t)i * k_Entry_Size);\n    if (entry.Offset > dataLen)\n      return S_FALSE;\n\n    const Byte *p = buffer + indexSize + entry.Offset;\n    size_t rem = dataLen - entry.Offset;\n    \n    if (!isMainHeader)\n    {\n      if (entry.Tag == RPMSIGTAG_SIZE &&\n          entry.Type == k_EntryType_INT32)\n      {\n        if (rem < 4 || entry.Count != 1)\n          return S_FALSE;\n        _headerPlusPayload_Size = Get32(p);\n        _headerPlusPayload_Size_Defined = true;\n      }\n    }\n    else\n    {\n      #ifdef Z7_RPM_SHOW_METADATA\n      {\n        _metadata.Add_UInt32(entry.Tag);\n        _metadata += \": \";\n      }\n      #endif\n\n      if (entry.Type == k_EntryType_STRING)\n      {\n        if (entry.Count != 1)\n          return S_FALSE;\n        size_t j;\n        for (j = 0; j < rem && p[j] != 0; j++);\n        if (j == rem)\n          return S_FALSE;\n        AString s((const char *)p);\n        switch (entry.Tag)\n        {\n          case RPMTAG_NAME: _name = s; break;\n          case RPMTAG_VERSION: _version = s; break;\n          case RPMTAG_RELEASE: _release = s; break;\n          case RPMTAG_ARCH: _arch = s; break;\n          case RPMTAG_OS: _os = s; break;\n          case RPMTAG_PAYLOADFORMAT: _format = s; break;\n          case RPMTAG_PAYLOADCOMPRESSOR: _compressor = s; break;\n        }\n\n        #ifdef Z7_RPM_SHOW_METADATA\n        _metadata += s;\n        #endif\n      }\n      else if (entry.Type == k_EntryType_INT32)\n      {\n        if (rem / 4 < entry.Count)\n          return S_FALSE;\n        if (entry.Tag == RPMTAG_BUILDTIME)\n        {\n          if (entry.Count != 1)\n            return S_FALSE;\n          _buildTime = Get32(p);\n          _time_Defined = true;\n        }\n        \n        #ifdef Z7_RPM_SHOW_METADATA\n        for (UInt32 t = 0; t < entry.Count; t++)\n        {\n          if (t != 0)\n            _metadata.Add_Space();\n          _metadata.Add_UInt32(Get32(p + t * 4));\n        }\n        #endif\n      }\n\n      #ifdef Z7_RPM_SHOW_METADATA\n\n      else if (\n          entry.Type == k_EntryType_STRING_ARRAY ||\n          entry.Type == k_EntryType_I18NSTRING)\n      {\n        const Byte *p2 = p;\n        size_t rem2 = rem;\n        for (UInt32 t = 0; t < entry.Count; t++)\n        {\n          if (rem2 == 0)\n            return S_FALSE;\n          if (t != 0)\n            _metadata.Add_LF();\n          size_t j;\n          for (j = 0; j < rem2 && p2[j] != 0; j++);\n          if (j == rem2)\n            return S_FALSE;\n          _metadata += (const char *)p2;\n          j++;\n          p2 += j;\n          rem2 -= j;\n        }\n      }\n      else if (entry.Type == k_EntryType_INT16)\n      {\n        if (rem / 2 < entry.Count)\n          return S_FALSE;\n        for (UInt32 t = 0; t < entry.Count; t++)\n        {\n          if (t != 0)\n            _metadata.Add_Space();\n          _metadata.Add_UInt32(Get16(p + t * 2));\n        }\n      }\n      else if (entry.Type == k_EntryType_BIN)\n      {\n        if (rem < entry.Count)\n          return S_FALSE;\n        for (UInt32 t = 0; t < entry.Count; t++)\n        {\n          const unsigned b = p[t];\n          _metadata += GET_HEX_CHAR_UPPER(b >> 4);\n          _metadata += GET_HEX_CHAR_UPPER(b & 0xF);\n        }\n      }\n      else\n      {\n        // p = p;\n      }\n\n      _metadata.Add_LF();\n      #endif\n    }\n    \n    #ifdef Z7_RPM_SHOW_METADATA\n    CMetaFile meta;\n    meta.Offset = entry.Offset;\n    meta.Tag = entry.Tag;\n    meta.Size = entry.Count;\n    _metaFiles.Add(meta);\n    #endif\n  }\n\n  headerSize += k_HeaderSig_Size;\n  _headersSize += headerSize;\n  if (isMainHeader && _headerPlusPayload_Size_Defined)\n  {\n    if (_headerPlusPayload_Size < headerSize)\n      return S_FALSE;\n    _payloadSize = _headerPlusPayload_Size - headerSize;\n    _size = _payloadSize;\n    _phySize = _headersSize + _payloadSize;\n    _payloadSize_Defined = true;\n    _phySize_Defined = true;\n  }\n  return S_OK;\n}\n\nHRESULT CHandler::Open2(ISequentialInStream *stream)\n{\n  {\n    Byte buf[kLeadSize];\n    RINOK(ReadStream_FALSE(stream, buf, kLeadSize))\n    if (Get32(buf) != 0xEDABEEDB)\n      return S_FALSE;\n    _lead.Parse(buf);\n    if (!_lead.IsSupported())\n      return S_FALSE;\n  }\n\n  _headersSize = kLeadSize;\n\n  if (_lead.SignatureType == RPMSIG_NONE)\n  {\n\n  }\n  else if (_lead.SignatureType == RPMSIG_PGP262_1024)\n  {\n    Byte temp[256];\n    RINOK(ReadStream_FALSE(stream, temp, sizeof(temp)))\n  }\n  else if (_lead.SignatureType == RPMSIG_HEADERSIG)\n  {\n    RINOK(ReadHeader(stream, false))\n    unsigned pos = (unsigned)_headersSize & 7;\n    if (pos != 0)\n    {\n      Byte temp[8];\n      unsigned num = 8 - pos;\n      RINOK(ReadStream_FALSE(stream, temp, num))\n      _headersSize += num;\n    }\n  }\n  else\n    return S_FALSE;\n\n  return ReadHeader(stream, true);\n}\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    RINOK(Open2(inStream))\n\n    // start of payload is allowed to be unaligned\n    RINOK(ReadStream_FALSE(inStream, _payloadSig, sizeof(_payloadSig)))\n\n    if (!_payloadSize_Defined)\n    {\n      UInt64 endPos;\n      RINOK(InStream_GetSize_SeekToEnd(inStream, endPos))\n      _size = endPos - _headersSize;\n    }\n    _stream = inStream;\n    return S_OK;\n  }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _headersSize = 0;\n  _payloadSize = 0;\n  _size = 0;\n  _phySize = 0;\n  _headerPlusPayload_Size = 0;\n\n  _payloadSize_Defined = false;\n  _phySize_Defined = false;\n  _headerPlusPayload_Size_Defined = false;\n  _time_Defined = false;\n\n  _name.Empty();\n  _version.Empty();\n  _release.Empty();\n  _arch.Empty();\n  _os.Empty();\n  \n  _format.Empty();\n  _compressor.Empty();\n\n  #ifdef Z7_RPM_SHOW_METADATA\n  _metadata.Empty();\n  _metaFiles.Size();\n  #endif\n\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1\n  #ifdef Z7_RPM_SHOW_METADATA\n    + _metaFiles.Size()\n  #endif\n  ;\n\n  return S_OK;\n}\n\nstatic const Byte k_Signature[] = { 0xED, 0xAB, 0xEE, 0xDB};\n\nREGISTER_ARC_I(\n  \"Rpm\", \"rpm\", NULL, 0xEB,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/SparseHandler.cpp",
    "content": "﻿// SparseHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n\n#define G16(_offs_, dest) dest = Get16(p + (_offs_));\n#define G32(_offs_, dest) dest = Get32(p + (_offs_));\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NSparse {\n\n// libsparse and simg2img\n\nstruct CHeader\n{\n  // UInt32 magic;          /* 0xed26ff3a */\n  // UInt16 major_version;  /* (0x1) - reject images with higher major versions */\n  // UInt16 minor_version;  /* (0x0) - allow images with higer minor versions */\n  UInt16 file_hdr_sz;    /* 28 bytes for first revision of the file format */\n  UInt16 chunk_hdr_sz;   /* 12 bytes for first revision of the file format */\n  UInt32 BlockSize;      /* block size in bytes, must be a multiple of 4 (4096) */\n  UInt32 NumBlocks;      /* total blocks in the non-sparse output image */\n  UInt32 NumChunks;      /* total chunks in the sparse input image */\n  // UInt32 image_checksum; /* CRC32 checksum of the original data, counting \"don't care\" as 0. */\n\n  void Parse(const Byte *p)\n  {\n    // G16 (4, major_version);\n    // G16 (6, minor_version);\n    G16 (8, file_hdr_sz)\n    G16 (10, chunk_hdr_sz)\n    G32 (12, BlockSize)\n    G32 (16, NumBlocks)\n    G32 (20, NumChunks)\n    // G32 (24, image_checksum);\n  }\n};\n \n// #define SPARSE_HEADER_MAGIC 0xed26ff3a\n\n#define CHUNK_TYPE_RAW        0xCAC1\n#define CHUNK_TYPE_FILL       0xCAC2\n#define CHUNK_TYPE_DONT_CARE  0xCAC3\n#define CHUNK_TYPE_CRC32      0xCAC4\n\n#define MY_CHUNK_TYPE_FILL       0\n#define MY_CHUNK_TYPE_DONT_CARE  1\n#define MY_CHUNK_TYPE_RAW_START 2\n\nstatic const char * const g_Methods[] =\n{\n    \"RAW\"\n  , \"FILL\"\n  , \"SPARSE\" // \"DONT_CARE\"\n  , \"CRC32\"\n};\n\nstatic const unsigned kFillSize = 4;\n\nstruct CChunk\n{\n  UInt32 VirtBlock;\n  Byte Fill [kFillSize];\n  UInt64 PhyOffset;\n\n  CChunk()\n  {\n    Fill[0] =\n    Fill[1] =\n    Fill[2] =\n    Fill[3] =\n      0;\n  }\n};\n\nstatic const Byte k_Signature[] = { 0x3a, 0xff, 0x26, 0xed, 1, 0 };\n\n\nZ7_class_CHandler_final: public CHandlerImg\n{\n  Z7_IFACE_COM7_IMP(IInArchive_Img)\n\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n\n  CRecordVector<CChunk> Chunks;\n  UInt64 _virtSize_fromChunks;\n  unsigned _blockSizeLog;\n  UInt32 _chunkIndexPrev;\n\n  UInt64 _packSizeProcessed;\n  UInt64 _phySize;\n  UInt32 _methodFlags;\n  bool _isArc;\n  bool _headersError;\n  bool _unexpectedEnd;\n  // bool _unsupported;\n  UInt32 NumChunks; // from header\n\n  HRESULT Seek2(UInt64 offset)\n  {\n    _posInArc = offset;\n    return InStream_SeekSet(Stream, offset);\n  }\n\n  void InitSeekPositions()\n  {\n    /* (_virtPos) and (_posInArc) is used only in Read() (that calls ReadPhy()).\n       So we must reset these variables before first call of Read() */\n    Reset_VirtPos();\n    Reset_PosInArc();\n    _chunkIndexPrev = 0;\n    _packSizeProcessed = 0;\n  }\n\n  // virtual functions\n  bool Init_PackSizeProcessed() Z7_override\n  {\n    _packSizeProcessed = 0;\n    return true;\n  }\n  bool Get_PackSizeProcessed(UInt64 &size) Z7_override\n  {\n    size = _packSizeProcessed;\n    return true;\n  }\n\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) Z7_override;\n  HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size, UInt32 &processed);\n};\n\n\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidClusterSize,\n  kpidNumBlocks,\n  kpidMethod\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidClusterSize: prop = (UInt32)((UInt32)1 << _blockSizeLog); break;\n    case kpidNumBlocks: prop = (UInt32)NumChunks; break;\n    case kpidPhySize: if (_phySize != 0) prop = _phySize; break;\n\n    case kpidMethod:\n    {\n      FLAGS_TO_PROP(g_Methods, _methodFlags, prop);\n      break;\n    }\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc)        v |= kpv_ErrorFlags_IsNotArc;\n      if (_headersError)  v |= kpv_ErrorFlags_HeadersError;\n      if (_unexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;\n      // if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;\n      if (!Stream && v == 0 && _isArc)\n        v = kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidSize: prop = _size; break;\n    case kpidPackSize: prop = _phySize; break;\n    case kpidExtension: prop = (_imgExt ? _imgExt : \"img\"); break;\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nstatic unsigned GetLogSize(UInt32 size)\n{\n  unsigned k;\n  for (k = 0; k < 32; k++)\n    if (((UInt32)1 << k) == size)\n      return k;\n  return k;\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)\n{\n  const unsigned kHeaderSize = 28;\n  const unsigned kChunkHeaderSize = 12;\n  CHeader h;\n  {\n    Byte buf[kHeaderSize];\n    RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))\n    if (memcmp(buf, k_Signature, 6) != 0)\n      return S_FALSE;\n    h.Parse(buf);\n  }\n\n  if (h.file_hdr_sz != kHeaderSize ||\n      h.chunk_hdr_sz != kChunkHeaderSize)\n    return S_FALSE;\n\n  NumChunks = h.NumChunks;\n\n  const unsigned logSize = GetLogSize(h.BlockSize);\n  if (logSize < 2 || logSize >= 32)\n    return S_FALSE;\n  _blockSizeLog = logSize;\n\n  _size = (UInt64)h.NumBlocks << logSize;\n\n  if (h.NumChunks >= (UInt32)(Int32)-2) // it's our limit\n    return S_FALSE;\n\n  _isArc = true;\n  Chunks.Reserve(h.NumChunks + 1);\n  UInt64 offset = kHeaderSize;\n  UInt32 virtBlock = 0;\n  UInt32 i;\n\n  for (i = 0; i < h.NumChunks; i++)\n  {\n    {\n      const UInt32 mask = ((UInt32)1 << 16) - 1;\n      if ((i & mask) == mask && openCallback)\n      {\n        RINOK(openCallback->SetCompleted(NULL, &offset))\n      }\n    }\n    Byte buf[kChunkHeaderSize];\n    {\n      size_t processed = kChunkHeaderSize;\n      RINOK(ReadStream(stream, buf, &processed))\n      if (kChunkHeaderSize != processed)\n      {\n        offset += kChunkHeaderSize;\n        break;\n      }\n    }\n    const UInt32 type = Get32(&buf[0]);\n    const UInt32 numBlocks = Get32(&buf[4]);\n    UInt32 size = Get32(&buf[8]);\n\n    if (type < CHUNK_TYPE_RAW ||\n        type > CHUNK_TYPE_CRC32)\n      return S_FALSE;\n    if (size < kChunkHeaderSize)\n      return S_FALSE;\n    CChunk c;\n    c.PhyOffset = offset + kChunkHeaderSize;\n    c.VirtBlock = virtBlock;\n    offset += size;\n    size -= kChunkHeaderSize;\n    _methodFlags |= ((UInt32)1 << (type - CHUNK_TYPE_RAW));\n\n    if (numBlocks > h.NumBlocks - virtBlock)\n      return S_FALSE;\n    \n    if (type == CHUNK_TYPE_CRC32)\n    {\n      // crc chunk must be last chunk (i == h.NumChunks -1);\n      if (size != kFillSize || numBlocks != 0)\n        return S_FALSE;\n      {\n        size_t processed = kFillSize;\n        RINOK(ReadStream(stream, c.Fill, &processed))\n        if (kFillSize != processed)\n          break;\n      }\n      continue;\n    }\n    // else\n    {\n      if (numBlocks == 0)\n        return S_FALSE;\n      \n      if (type == CHUNK_TYPE_DONT_CARE)\n      {\n        if (size != 0)\n          return S_FALSE;\n        c.PhyOffset = MY_CHUNK_TYPE_DONT_CARE;\n      }\n      else if (type == CHUNK_TYPE_FILL)\n      {\n        if (size != kFillSize)\n          return S_FALSE;\n        c.PhyOffset = MY_CHUNK_TYPE_FILL;\n        size_t processed = kFillSize;\n        RINOK(ReadStream(stream, c.Fill, &processed))\n        if (kFillSize != processed)\n          break;\n      }\n      else if (type == CHUNK_TYPE_RAW)\n      {\n        /* Here we require (size == virtSize).\n           Probably original decoder also requires it.\n           But maybe size of last chunk can be non-aligned with blockSize ? */\n        const UInt32 virtSize = (numBlocks << _blockSizeLog);\n        if (size != virtSize || numBlocks != (virtSize >> _blockSizeLog))\n          return S_FALSE;\n      }\n      else\n        return S_FALSE;\n\n      virtBlock += numBlocks;\n      Chunks.AddInReserved(c);\n      if (type == CHUNK_TYPE_RAW)\n        RINOK(InStream_SeekSet(stream, offset))\n    }\n  }\n\n  if (i != h.NumChunks)\n    _unexpectedEnd = true;\n  else if (virtBlock != h.NumBlocks)\n    _headersError = true;\n\n  _phySize = offset;\n\n  {\n    CChunk c;\n    c.VirtBlock = virtBlock;\n    c.PhyOffset = offset;\n    Chunks.AddInReserved(c);\n  }\n  _virtSize_fromChunks = (UInt64)virtBlock << _blockSizeLog;\n\n  Stream = stream;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  Chunks.Clear();\n  _isArc = false;\n  _virtSize_fromChunks = 0;\n  // _unsupported = false;\n  _headersError = false;\n  _unexpectedEnd = false;\n  _phySize = 0;\n  _methodFlags = 0;\n\n  _chunkIndexPrev = 0;\n  _packSizeProcessed = 0;\n\n  // CHandlerImg:\n  Clear_HandlerImg_Vars();\n  Stream.Release();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  if (Chunks.Size() < 1)\n    return S_FALSE;\n  if (Chunks.Size() < 2 && _virtSize_fromChunks != 0)\n    return S_FALSE;\n  // if (_unsupported) return S_FALSE;\n  InitSeekPositions();\n  CMyComPtr<ISequentialInStream> streamTemp = this;\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\n\nHRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size, UInt32 &processed)\n{\n  processed = 0;\n  if (offset > _phySize || offset + size > _phySize)\n  {\n    // we don't expect these cases, if (_phySize) was set correctly.\n    return S_FALSE;\n  }\n  if (offset != _posInArc)\n  {\n    const HRESULT res = Seek2(offset);\n    if (res != S_OK)\n    {\n      Reset_PosInArc(); // we don't trust seek_pos in case of error\n      return res;\n    }\n  }\n  {\n    size_t size2 = size;\n    const HRESULT res = ReadStream(Stream, data, &size2);\n    processed = (UInt32)size2;\n    _packSizeProcessed += size2;\n    _posInArc += size2;\n    if (res != S_OK)\n      Reset_PosInArc(); // we don't trust seek_pos in case of reading error\n    return res;\n  }\n}\n\n\nZ7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  // const unsigned kLimit = (1 << 16) + 1; if (size > kLimit) size = kLimit; // for debug\n  if (_virtPos >= _virtSize_fromChunks)\n    return S_OK;\n  {\n    const UInt64 rem = _virtSize_fromChunks - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n    if (size == 0)\n      return S_OK;\n  }\n\n  UInt32 chunkIndex = _chunkIndexPrev;\n  if (chunkIndex + 1 >= Chunks.Size())\n    return S_FALSE;\n  {\n    const UInt32 blockIndex = (UInt32)(_virtPos >> _blockSizeLog);\n    if (blockIndex <  Chunks[chunkIndex    ].VirtBlock ||\n        blockIndex >= Chunks[chunkIndex + 1].VirtBlock)\n    {\n      unsigned left = 0, right = Chunks.Size() - 1;\n      for (;;)\n      {\n        const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n        if (mid == left)\n          break;\n        if (blockIndex < Chunks[mid].VirtBlock)\n          right = mid;\n        else\n          left = mid;\n      }\n      chunkIndex = left;\n      _chunkIndexPrev = chunkIndex;\n    }\n  }\n\n  const CChunk &c = Chunks[chunkIndex];\n  const UInt64 offset = _virtPos - ((UInt64)c.VirtBlock << _blockSizeLog);\n  {\n    const UInt32 numBlocks = Chunks[chunkIndex + 1].VirtBlock - c.VirtBlock;\n    const UInt64 rem = ((UInt64)numBlocks << _blockSizeLog) - offset;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n\n  const UInt64 phyOffset = c.PhyOffset;\n  \n  if (phyOffset >= MY_CHUNK_TYPE_RAW_START)\n  {\n    UInt32 processed = 0;\n    const HRESULT res = ReadPhy(phyOffset + offset, data, size, processed);\n    if (processedSize)\n      *processedSize = processed;\n    _virtPos += processed;\n    return res;\n  }\n\n  Byte b = 0;\n  \n  if (phyOffset == MY_CHUNK_TYPE_FILL)\n  {\n    const Byte b0 = c.Fill [0];\n    const Byte b1 = c.Fill [1];\n    const Byte b2 = c.Fill [2];\n    const Byte b3 = c.Fill [3];\n    if (b0 != b1 ||\n        b0 != b2 ||\n        b0 != b3)\n    {\n      if (processedSize)\n        *processedSize = size;\n      _virtPos += size;\n      Byte *dest = (Byte *)data;\n      while (size >= 4)\n      {\n        dest[0] = b0;\n        dest[1] = b1;\n        dest[2] = b2;\n        dest[3] = b3;\n        dest += 4;\n        size -= 4;\n      }\n      if (size > 0) dest[0] = b0;\n      if (size > 1) dest[1] = b1;\n      if (size > 2) dest[2] = b2;\n      return S_OK;\n    }\n    b = b0;\n  }\n  else if (phyOffset != MY_CHUNK_TYPE_DONT_CARE)\n    return S_FALSE;\n  \n  memset(data, b, size);\n  _virtPos += size;\n  if (processedSize)\n    *processedSize = size;\n  return S_OK;\n}\n\nREGISTER_ARC_I(\n  \"Sparse\", \"simg img\", NULL, 0xc2,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/SplitHandler.cpp",
    "content": "﻿// SplitHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n\n#include \"Common/MultiStream.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NSplit {\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumVolumes,\n  kpidTotalPhySize\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CObjectVector<CMyComPtr<IInStream> > _streams;\n  CRecordVector<UInt64> _sizes;\n  UString _subName;\n  UInt64 _totalSize;\n\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidPhySize: if (!_sizes.IsEmpty()) prop = _sizes[0]; break;\n    case kpidTotalPhySize: prop = _totalSize; break;\n    case kpidNumVolumes: prop = (UInt32)_streams.Size(); break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nstruct CSeqName\n{\n  UString _unchangedPart;\n  UString _changedPart;\n  bool _splitStyle;\n  \n  bool GetNextName(UString &s)\n  {\n    {\n      unsigned i = _changedPart.Len();\n      for (;;)\n      {\n        wchar_t c = _changedPart[--i];\n        \n        if (_splitStyle)\n        {\n          if (c == 'z')\n          {\n            _changedPart.ReplaceOneCharAtPos(i, L'a');\n            if (i == 0)\n              return false;\n            continue;\n          }\n          else if (c == 'Z')\n          {\n            _changedPart.ReplaceOneCharAtPos(i, L'A');\n            if (i == 0)\n              return false;\n            continue;\n          }\n        }\n        else\n        {\n          if (c == '9')\n          {\n            _changedPart.ReplaceOneCharAtPos(i, L'0');\n            if (i == 0)\n            {\n              _changedPart.InsertAtFront(L'1');\n              break;\n            }\n            continue;\n          }\n        }\n\n        c++;\n        _changedPart.ReplaceOneCharAtPos(i, c);\n        break;\n      }\n    }\n    \n    s = _unchangedPart + _changedPart;\n    return true;\n  }\n};\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)\n{\n  Close();\n  if (!callback)\n    return S_FALSE;\n\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveOpenVolumeCallback,\n      volumeCallback, callback)\n  if (!volumeCallback)\n    return S_FALSE;\n  \n  UString name;\n  {\n    NCOM::CPropVariant prop;\n    RINOK(volumeCallback->GetProperty(kpidName, &prop))\n    if (prop.vt != VT_BSTR)\n      return S_FALSE;\n    name = prop.bstrVal;\n  }\n  \n  const int dotPos = name.ReverseFind_Dot();\n  const UString prefix = name.Left((unsigned)(dotPos + 1));\n  const UString ext = name.Ptr((unsigned)(dotPos + 1));\n  UString ext2 = ext;\n  ext2.MakeLower_Ascii();\n  \n  CSeqName seqName;\n  \n  unsigned numLetters = 2;\n  bool splitStyle = false;\n  \n  if (ext2.Len() >= 2 && StringsAreEqual_Ascii(ext2.RightPtr(2), \"aa\"))\n  {\n    splitStyle = true;\n    while (numLetters < ext2.Len())\n    {\n      if (ext2[ext2.Len() - numLetters - 1] != 'a')\n        break;\n      numLetters++;\n    }\n  }\n  else if (ext2.Len() >= 2 && (\n         StringsAreEqual_Ascii(ext2.RightPtr(2), \"01\")\n      || StringsAreEqual_Ascii(ext2.RightPtr(2), \"00\")\n      ))\n  {\n    while (numLetters < ext2.Len())\n    {\n      if (ext2[ext2.Len() - numLetters - 1] != '0')\n        break;\n      numLetters++;\n    }\n    if (numLetters != ext2.Len())\n      return S_FALSE;\n  }\n  else\n    return S_FALSE;\n  \n  seqName._unchangedPart = prefix + ext.Left(ext2.Len() - numLetters);\n  seqName._changedPart = ext.RightPtr(numLetters);\n  seqName._splitStyle = splitStyle;\n  \n  if (prefix.Len() < 1)\n    _subName = \"file\";\n  else\n    _subName.SetFrom(prefix, prefix.Len() - 1);\n  \n  UInt64 size;\n  {\n    /*\n    NCOM::CPropVariant prop;\n    RINOK(volumeCallback->GetProperty(kpidSize, &prop))\n    if (prop.vt != VT_UI8)\n      return E_INVALIDARG;\n    size = prop.uhVal.QuadPart;\n    */\n  }\n  RINOK(InStream_AtBegin_GetSize(stream, size))\n  \n  _totalSize += size;\n  _sizes.Add(size);\n  _streams.Add(stream);\n  \n  {\n    const UInt64 numFiles = _streams.Size();\n    RINOK(callback->SetCompleted(&numFiles, NULL))\n  }\n  \n  for (;;)\n  {\n    UString fullName;\n    if (!seqName.GetNextName(fullName))\n      break;\n    CMyComPtr<IInStream> nextStream;\n    const HRESULT result = volumeCallback->GetStream(fullName, &nextStream);\n    if (result == S_FALSE)\n      break;\n    if (result != S_OK)\n      return result;\n    if (!nextStream)\n      break;\n    RINOK(InStream_AtBegin_GetSize(nextStream, size))\n    _totalSize += size;\n    _sizes.Add(size);\n    _streams.Add(nextStream);\n    {\n      const UInt64 numFiles = _streams.Size();\n      RINOK(callback->SetCompleted(&numFiles, NULL))\n    }\n  }\n\n  if (_streams.Size() == 1)\n  {\n    if (splitStyle)\n      return S_FALSE;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  const HRESULT res = Open2(stream, callback);\n  if (res != S_OK)\n    Close();\n  return res;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _totalSize = 0;\n  _subName.Empty();\n  _streams.Clear();\n  _sizes.Clear();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _streams.IsEmpty() ? 0 : 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPath: prop = _subName; break;\n    case kpidSize:\n    case kpidPackSize:\n      prop = _totalSize;\n      break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  UInt64 currentTotalSize = 0;\n  RINOK(extractCallback->SetTotal(_totalSize))\n  CMyComPtr<ISequentialOutStream> outStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &outStream, askMode))\n  if (!testMode && !outStream)\n    return S_OK;\n  RINOK(extractCallback->PrepareOperation(askMode))\n  \n  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\n  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  for (unsigned i = 0;; i++)\n  {\n    lps->InSize = lps->OutSize = currentTotalSize;\n    RINOK(lps->SetCur())\n    if (i == _streams.Size())\n      break;\n    IInStream *inStream = _streams[i];\n    RINOK(InStream_SeekToBegin(inStream))\n    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))\n    currentTotalSize += copyCoderSpec->TotalSize;\n  }\n  outStream.Release();\n  return extractCallback->SetOperationResult(NExtract::NOperationResult::kOK);\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  if (index != 0)\n    return E_INVALIDARG;\n  *stream = NULL;\n  CMultiStream *streamSpec = new CMultiStream;\n  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\n  FOR_VECTOR (i, _streams)\n  {\n    CMultiStream::CSubStreamInfo subStreamInfo;\n    subStreamInfo.Stream = _streams[i];\n    subStreamInfo.Size = _sizes[i];\n    streamSpec->Streams.Add(subStreamInfo);\n  }\n  streamSpec->Init();\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\nREGISTER_ARC_I_NO_SIG(\n  \"Split\", \"001\", NULL, 0xEA,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/SquashfsHandler.cpp",
    "content": "﻿// SquashfsHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/LzmaDec.h\"\n#include \"../../../C/Xz.h\"\n// **************** 7-Zip ZS Modification Start ****************\n// #include \"../../../C/ZstdDec.h\"\n#include <lz4.h>\n// **************** 7-Zip ZS Modification End ****************\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyLinux.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/StringConvert.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/CWrappers.h\"\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/ZlibDecoder.h\"\n// #include \"../Compress/LzmaDecoder.h\"\n// **************** 7-Zip ZS Modification Start ****************\n#include \"../../../../Extensions/ZSCodecs/ZstdDecoder.h\"\n// **************** 7-Zip ZS Modification End ****************\n\nnamespace NArchive {\nnamespace NSquashfs {\n\nstatic const UInt32 kNumFilesMax = 1 << 28;\nstatic const unsigned kNumDirLevelsMax = 1 << 10;\n\n// Layout: Header, Data, inodes, Directories, Fragments, UIDs, GIDs\n\n/*\n#define Get16(p) (be ? GetBe16(p) : GetUi16(p))\n#define Get32(p) (be ? GetBe32(p) : GetUi32(p))\n#define Get64(p) (be ? GetBe64(p) : GetUi64(p))\n*/\n\nstatic UInt16 Get16b(const Byte *p, bool be) { return be ? GetBe16(p) : GetUi16(p); }\nstatic UInt32 Get32b(const Byte *p, bool be) { return be ? GetBe32(p) : GetUi32(p); }\nstatic UInt64 Get64b(const Byte *p, bool be) { return be ? GetBe64(p) : GetUi64(p); }\n\n#define Get16(p) Get16b(p, be)\n#define Get32(p) Get32b(p, be)\n#define Get64(p) Get64b(p, be)\n\n#define LE_16(offs, dest) dest = GetUi16(p + (offs))\n#define LE_32(offs, dest) dest = GetUi32(p + (offs))\n#define LE_64(offs, dest) dest = GetUi64(p + (offs))\n\n#define GET_16(offs, dest) dest = Get16(p + (offs))\n#define GET_32(offs, dest) dest = Get32(p + (offs))\n#define GET_64(offs, dest) dest = Get64(p + (offs))\n\nstatic const UInt32 kSignature32_LE = 0x73717368;\nstatic const UInt32 kSignature32_BE = 0x68737173;\nstatic const UInt32 kSignature32_LZ = 0x71736873;\nstatic const UInt32 kSignature32_B2 = 0x73687371;\n\n#define kMethod_ZLIB 1\n#define kMethod_LZMA 2\n#define kMethod_LZO  3\n#define kMethod_XZ   4\n// #define kMethod_LZ4  5\n// **************** 7-Zip ZS Modification Start ****************\n#define kMethod_LZ4  5\n// **************** 7-Zip ZS Modification End ****************\n#define kMethod_ZSTD 6\n\nstatic const char * const k_Methods[] =\n{\n    \"0\"\n  , \"ZLIB\"\n  , \"LZMA\"\n  , \"LZO\"\n  , \"XZ\"\n  , \"LZ4\"\n  , \"ZSTD\"\n};\n\nstatic const unsigned kMetadataBlockSizeLog = 13;\nstatic const UInt32 kMetadataBlockSize = (1 << kMetadataBlockSizeLog);\n\nenum\n{\n  kType_IPC,\n  kType_DIR,\n  kType_FILE,\n  kType_LNK,\n  kType_BLK,\n  kType_CHR,\n  kType_FIFO,\n  kType_SOCK\n};\n\nstatic const UInt32 k_TypeToMode[] =\n{\n  0,\n  MY_LIN_S_IFDIR, MY_LIN_S_IFREG, MY_LIN_S_IFLNK, MY_LIN_S_IFBLK, MY_LIN_S_IFCHR, MY_LIN_S_IFIFO, MY_LIN_S_IFSOCK,\n  MY_LIN_S_IFDIR, MY_LIN_S_IFREG, MY_LIN_S_IFLNK, MY_LIN_S_IFBLK, MY_LIN_S_IFCHR, MY_LIN_S_IFIFO, MY_LIN_S_IFSOCK\n};\n\n\nenum\n{\n  kFlag_UNC_INODES,\n  kFlag_UNC_DATA,\n  kFlag_CHECK,\n  kFlag_UNC_FRAGS,\n  kFlag_NO_FRAGS,\n  kFlag_ALWAYS_FRAG,\n  kFlag_DUPLICATE,\n  kFlag_EXPORT\n};\n\nstatic const char * const k_Flags[] =\n{\n    \"UNCOMPRESSED_INODES\"\n  , \"UNCOMPRESSED_DATA\"\n  , \"CHECK\"\n  , \"UNCOMPRESSED_FRAGMENTS\"\n  , \"NO_FRAGMENTS\"\n  , \"ALWAYS_FRAGMENTS\"\n  , \"DUPLICATES_REMOVED\"\n  , \"EXPORTABLE\"\n  , \"UNCOMPRESSED_XATTRS\"\n  , \"NO_XATTRS\"\n  , \"COMPRESSOR_OPTIONS\"\n  , \"UNCOMPRESSED_IDS\"\n};\n\nstatic const UInt32 kNotCompressedBit16 = 1 << 15;\nstatic const UInt32 kNotCompressedBit32 = 1 << 24;\n\n#define GET_COMPRESSED_BLOCK_SIZE(size) ((size) & ~kNotCompressedBit32)\n#define IS_COMPRESSED_BLOCK(size) (((size) & kNotCompressedBit32) == 0)\n\n// static const UInt32 kHeaderSize1 = 0x33;\n// static const UInt32 kHeaderSize2 = 0x3F;\nstatic const UInt32 kHeaderSize3 = 0x77;\n// static const UInt32 kHeaderSize4 = 0x60;\n\nstruct CHeader\n{\n  bool be;\n  bool SeveralMethods;\n  Byte NumUids;\n  Byte NumGids;\n\n  UInt32 NumInodes;\n  UInt32 CTime;\n  UInt32 BlockSize;\n  UInt32 NumFrags;\n  UInt16 Method;\n  UInt16 BlockSizeLog;\n  UInt16 Flags;\n  UInt16 NumIDs;\n  UInt16 Major;\n  UInt16 Minor;\n  UInt64 RootInode;\n  UInt64 Size;\n  UInt64 UidTable;\n  UInt64 GidTable;\n  UInt64 XattrIdTable;\n  UInt64 InodeTable;\n  UInt64 DirTable;\n  UInt64 FragTable;\n  UInt64 LookupTable;\n\n  void Parse3(const Byte *p)\n  {\n    Method = kMethod_ZLIB;\n    GET_32 (0x08, Size);\n    GET_32 (0x0C, UidTable);\n    GET_32 (0x10, GidTable);\n    GET_32 (0x14, InodeTable);\n    GET_32 (0x18, DirTable);\n    GET_16 (0x20, BlockSize);\n    GET_16 (0x22, BlockSizeLog);\n    Flags   = p[0x24];\n    NumUids = p[0x25];\n    NumGids = p[0x26];\n    GET_32 (0x27, CTime);\n    GET_64 (0x2B, RootInode);\n    NumFrags = 0;\n    FragTable = UidTable;\n\n    if (Major >= 2)\n    {\n      GET_32 (0x33, BlockSize);\n      GET_32 (0x37, NumFrags);\n      GET_32 (0x3B, FragTable);\n      if (Major == 3)\n      {\n        GET_64 (0x3F, Size);\n        GET_64 (0x47, UidTable);\n        GET_64 (0x4F, GidTable);\n        GET_64 (0x57, InodeTable);\n        GET_64 (0x5F, DirTable);\n        GET_64 (0x67, FragTable);\n        GET_64 (0x6F, LookupTable);\n      }\n    }\n  }\n\n  void Parse4(const Byte *p)\n  {\n    LE_32 (0x08, CTime);\n    LE_32 (0x0C, BlockSize);\n    LE_32 (0x10, NumFrags);\n    LE_16 (0x14, Method);\n    LE_16 (0x16, BlockSizeLog);\n    LE_16 (0x18, Flags);\n    LE_16 (0x1A, NumIDs);\n    LE_64 (0x20, RootInode);\n    LE_64 (0x28, Size);\n    LE_64 (0x30, UidTable);\n    LE_64 (0x38, XattrIdTable);\n    LE_64 (0x40, InodeTable);\n    LE_64 (0x48, DirTable);\n    LE_64 (0x50, FragTable);\n    LE_64 (0x58, LookupTable);\n    GidTable = 0;\n  }\n\n  bool Parse(const Byte *p)\n  {\n    be = false;\n    SeveralMethods = false;\n    switch (GetUi32(p))\n    {\n      case kSignature32_LE: break;\n      case kSignature32_BE: be = true; break;\n      case kSignature32_LZ: SeveralMethods = true; break;\n      case kSignature32_B2: SeveralMethods = true; be = true; break;\n      default: return false;\n    }\n    GET_32 (4, NumInodes);\n    GET_16 (0x1C, Major);\n    GET_16 (0x1E, Minor);\n    if (Major <= 3)\n      Parse3(p);\n    else\n    {\n      if (be)\n        return false;\n      Parse4(p);\n    }\n    return\n      InodeTable < DirTable &&\n      DirTable <= FragTable &&\n      FragTable <= Size &&\n      UidTable <= Size &&\n      BlockSizeLog >= 12 &&\n      BlockSizeLog < 31 &&\n      BlockSize == ((UInt32)1 << BlockSizeLog);\n  }\n\n  bool IsSupported() const { return Major > 0 && Major <= 4 && BlockSizeLog <= 23; }\n  bool IsOldVersion() const { return Major < 4; }\n  bool NeedCheckData() const { return (Flags & (1 << kFlag_CHECK)) != 0; }\n  unsigned GetFileNameOffset() const { return Major <= 2 ? 3 : (Major == 3 ? 5 : 8); }\n  unsigned GetSymLinkOffset() const { return Major <= 1 ? 5: (Major <= 2 ? 6: (Major == 3 ? 18 : 24)); }\n  unsigned GetSpecGuidIndex() const { return Major <= 1 ? 0xF: 0xFF; }\n};\n\nstatic const UInt32 kFrag_Empty = (UInt32)(Int32)-1;\n// static const UInt32 kXattr_Empty = (UInt32)(Int32)-1;\n\nstruct CNode\n{\n  UInt16 Type;\n  UInt16 Mode;\n  UInt16 Uid;\n  UInt16 Gid;\n  UInt32 Frag;\n  UInt32 Offset;\n  // UInt32 MTime;\n  // UInt32 Number;\n  // UInt32 NumLinks;\n  // UInt32 RDev;\n  // UInt32 Xattr;\n  // UInt32 Parent;\n  \n  UInt64 FileSize;\n  UInt64 StartBlock;\n  // UInt64 Sparse;\n  \n  UInt32 Parse1(const Byte *p, UInt32 size, const CHeader &_h);\n  UInt32 Parse2(const Byte *p, UInt32 size, const CHeader &_h);\n  UInt32 Parse3(const Byte *p, UInt32 size, const CHeader &_h);\n  UInt32 Parse4(const Byte *p, UInt32 size, const CHeader &_h);\n  \n  bool IsDir() const { return (Type == kType_DIR || Type == kType_DIR + 7); }\n  bool IsLink() const { return (Type == kType_LNK || Type == kType_LNK + 7); }\n  UInt64 GetSize() const { return IsDir() ? 0 : FileSize; }\n  \n  bool ThereAreFrags() const { return Frag != kFrag_Empty; }\n  UInt64 GetNumBlocks(const CHeader &_h) const\n  {\n    return (FileSize >> _h.BlockSizeLog) +\n      (!ThereAreFrags() && (FileSize & (_h.BlockSize - 1)) != 0);\n  }\n};\n\nUInt32 CNode::Parse1(const Byte *p, UInt32 size, const CHeader &_h)\n{\n  const bool be = _h.be;\n  if (size < 4)\n    return 0;\n  {\n    const UInt32 t = Get16(p);\n    if (be)\n    {\n      Type = (UInt16)(t >> 12);\n      Mode = (UInt16)(t & 0xFFF);\n      Uid = (UInt16)(p[2] >> 4);\n      Gid = (UInt16)(p[2] & 0xF);\n    }\n    else\n    {\n      Type = (UInt16)(t & 0xF);\n      Mode = (UInt16)(t >> 4);\n      Uid = (UInt16)(p[2] & 0xF);\n      Gid = (UInt16)(p[2] >> 4);\n    }\n  }\n\n  // Xattr = kXattr_Empty;\n  // MTime = 0;\n  FileSize = 0;\n  StartBlock = 0;\n  Frag = kFrag_Empty;\n\n  if (Type == 0)\n  {\n    Byte t = p[3];\n    if (be)\n    {\n      Type = (UInt16)(t >> 4);\n      Offset = (UInt16)(t & 0xF);\n    }\n    else\n    {\n      Type = (UInt16)(t & 0xF);\n      Offset = (UInt16)(t >> 4);\n    }\n    return (Type == kType_FIFO || Type == kType_SOCK) ? 4 : 0;\n  }\n\n  Type--;\n  Uid = (UInt16)(Uid + (Type / 5) * 16);\n  Type = (UInt16)((Type % 5) + 1);\n\n  if (Type == kType_FILE)\n  {\n    if (size < 15)\n      return 0;\n    // GET_32 (3, MTime);\n    GET_32 (7, StartBlock);\n    UInt32 t;\n    GET_32 (11, t);\n    FileSize = t;\n    UInt32 numBlocks = t >> _h.BlockSizeLog;\n    if ((t & (_h.BlockSize - 1)) != 0)\n      numBlocks++;\n    UInt32 pos = numBlocks * 2 + 15;\n    return (pos <= size) ? pos : 0;\n  }\n  \n  if (Type == kType_DIR)\n  {\n    if (size < 14)\n      return 0;\n    UInt32 t = Get32(p + 3);\n    if (be)\n    {\n      FileSize = t >> 13;\n      Offset = t & 0x1FFF;\n    }\n    else\n    {\n      FileSize = t & 0x7FFFF;\n      Offset = t >> 19;\n    }\n    // GET_32 (7, MTime);\n    GET_32 (10, StartBlock);\n    if (be)\n      StartBlock &= 0xFFFFFF;\n    else\n      StartBlock >>= 8;\n    return 14;\n  }\n  \n  if (size < 5)\n    return 0;\n\n  if (Type == kType_LNK)\n  {\n    UInt32 len;\n    GET_16 (3, len);\n    FileSize = len;\n    len += 5;\n    return (len <= size) ? len : 0;\n  }\n\n  // GET_32 (3, RDev);\n  return 5;\n}\n\nUInt32 CNode::Parse2(const Byte *p, UInt32 size, const CHeader &_h)\n{\n  const bool be = _h.be;\n  if (size < 4)\n    return 0;\n  {\n    const UInt32 t = Get16(p);\n    if (be)\n    {\n      Type = (UInt16)(t >> 12);\n      Mode = (UInt16)(t & 0xFFF);\n    }\n    else\n    {\n      Type = (UInt16)(t & 0xF);\n      Mode = (UInt16)(t >> 4);\n    }\n  }\n\n  Uid = p[2];\n  Gid = p[3];\n\n  // Xattr = kXattr_Empty;\n\n  if (Type == kType_FILE)\n  {\n    if (size < 24)\n      return 0;\n    // GET_32 (4, MTime);\n    GET_32 (8, StartBlock);\n    GET_32 (12, Frag);\n    GET_32 (16, Offset);\n    UInt32 t;\n    GET_32 (20, t);\n    FileSize = t;\n    UInt32 numBlocks = t >> _h.BlockSizeLog;\n    if (!ThereAreFrags() && (t & (_h.BlockSize - 1)) != 0)\n      numBlocks++;\n    UInt32 pos = numBlocks * 4 + 24;\n    return (pos <= size) ? (UInt32)pos : 0;\n  }\n\n  FileSize = 0;\n  // MTime = 0;\n  StartBlock = 0;\n  Frag = kFrag_Empty;\n  \n  if (Type == kType_DIR)\n  {\n    if (size < 15)\n      return 0;\n    UInt32 t = Get32(p + 4);\n    if (be)\n    {\n      FileSize = t >> 13;\n      Offset = t & 0x1FFF;\n    }\n    else\n    {\n      FileSize = t & 0x7FFFF;\n      Offset = t >> 19;\n    }\n    // GET_32 (8, MTime);\n    GET_32 (11, StartBlock);\n    if (be)\n      StartBlock &= 0xFFFFFF;\n    else\n      StartBlock >>= 8;\n    return 15;\n  }\n  \n  if (Type == kType_DIR + 7)\n  {\n    if (size < 18)\n      return 0;\n    UInt32 t = Get32(p + 4);\n    UInt32 t2 = Get16(p + 7);\n    if (be)\n    {\n      FileSize = t >> 5;\n      Offset = t2 & 0x1FFF;\n    }\n    else\n    {\n      FileSize = t & 0x7FFFFFF;\n      Offset = t2 >> 3;\n    }\n    // GET_32 (9, MTime);\n    GET_32 (12, StartBlock);\n    if (be)\n      StartBlock &= 0xFFFFFF;\n    else\n      StartBlock >>= 8;\n    UInt32 iCount;\n    GET_16 (16, iCount);\n    UInt32 pos = 18;\n    for (UInt32 i = 0; i < iCount; i++)\n    {\n      // 27 bits: index\n      // 29 bits: startBlock\n      if (pos + 8 > size)\n        return 0;\n      pos += 8 + (UInt32)p[pos + 7] + 1; // nameSize\n      if (pos > size)\n        return 0;\n    }\n    return pos;\n  }\n\n  if (Type == kType_FIFO || Type == kType_SOCK)\n    return 4;\n\n  if (size < 6)\n    return 0;\n  \n  if (Type == kType_LNK)\n  {\n    UInt32 len;\n    GET_16 (4, len);\n    FileSize = len;\n    len += 6;\n    return (len <= size) ? len : 0;\n  }\n  \n  if (Type == kType_BLK || Type == kType_CHR)\n  {\n    // GET_16 (4, RDev);\n    return 6;\n  }\n  \n  return 0;\n}\n\nUInt32 CNode::Parse3(const Byte *p, UInt32 size, const CHeader &_h)\n{\n  const bool be = _h.be;\n  if (size < 12)\n    return 0;\n  \n  {\n    const UInt32 t = Get16(p);\n    if (be)\n    {\n      Type = (UInt16)(t >> 12);\n      Mode = (UInt16)(t & 0xFFF);\n    }\n    else\n    {\n      Type = (UInt16)(t & 0xF);\n      Mode = (UInt16)(t >> 4);\n    }\n  }\n\n  Uid = p[2];\n  Gid = p[3];\n  // GET_32 (4, MTime);\n  // GET_32 (8, Number);\n  // Xattr = kXattr_Empty;\n  FileSize = 0;\n  StartBlock = 0;\n  \n  if (Type == kType_FILE || Type == kType_FILE + 7)\n  {\n    UInt32 offset;\n    if (Type == kType_FILE)\n    {\n      if (size < 32)\n        return 0;\n      GET_64 (12, StartBlock);\n      GET_32 (20, Frag);\n      GET_32 (24, Offset);\n      GET_32 (28, FileSize);\n      offset = 32;\n    }\n    else\n    {\n      if (size < 40)\n        return 0;\n      // GET_32 (12, NumLinks);\n      GET_64 (16, StartBlock);\n      GET_32 (24, Frag);\n      GET_32 (28, Offset);\n      GET_64 (32, FileSize);\n      offset = 40;\n    }\n    UInt64 pos = GetNumBlocks(_h) * 4 + offset;\n    return (pos <= size) ? (UInt32)pos : 0;\n  }\n\n  if (size < 16)\n    return 0;\n  // GET_32 (12, NumLinks);\n \n  if (Type == kType_DIR)\n  {\n    if (size < 28)\n      return 0;\n    UInt32 t = Get32(p + 16);\n    if (be)\n    {\n      FileSize = t >> 13;\n      Offset = t & 0x1FFF;\n    }\n    else\n    {\n      FileSize = t & 0x7FFFF;\n      Offset = t >> 19;\n    }\n    GET_32 (20, StartBlock);\n    // GET_32 (24, Parent);\n    return 28;\n  }\n  \n  if (Type == kType_DIR + 7)\n  {\n    if (size < 31)\n      return 0;\n    UInt32 t = Get32(p + 16);\n    UInt32 t2 = Get16(p + 19);\n    if (be)\n    {\n      FileSize = t >> 5;\n      Offset = t2 & 0x1FFF;\n    }\n    else\n    {\n      FileSize = t & 0x7FFFFFF;\n      Offset = t2 >> 3;\n    }\n    GET_32 (21, StartBlock);\n    UInt32 iCount;\n    GET_16 (25, iCount);\n    // GET_32 (27, Parent);\n    UInt32 pos = 31;\n    for (UInt32 i = 0; i < iCount; i++)\n    {\n      // UInt32 index\n      // UInt32 startBlock\n      if (pos + 9 > size)\n        return 0;\n      pos += 9 + (unsigned)p[pos + 8] + 1; // nameSize\n      if (pos > size)\n        return 0;\n    }\n    return pos;\n  }\n\n  if (Type == kType_FIFO || Type == kType_SOCK)\n    return 16;\n  \n  if (size < 18)\n    return 0;\n  if (Type == kType_LNK)\n  {\n    UInt32 len;\n    GET_16 (16, len);\n    FileSize = len;\n    len += 18;\n    return (len <= size) ? len : 0;\n  }\n\n  if (Type == kType_BLK || Type == kType_CHR)\n  {\n    // GET_16 (16, RDev);\n    return 18;\n  }\n  \n  return 0;\n}\n\nUInt32 CNode::Parse4(const Byte *p, UInt32 size, const CHeader &_h)\n{\n  if (size < 20)\n    return 0;\n  LE_16 (0, Type);\n  LE_16 (2, Mode);\n  LE_16 (4, Uid);\n  LE_16 (6, Gid);\n  // LE_32 (8, MTime);\n  // LE_32 (12, Number);\n  \n  // Xattr = kXattr_Empty;\n  FileSize = 0;\n  StartBlock = 0;\n  \n  if (Type == kType_FILE || Type == kType_FILE + 7)\n  {\n    UInt32 offset;\n    if (Type == kType_FILE)\n    {\n      if (size < 32)\n        return 0;\n      LE_32 (16, StartBlock);\n      LE_32 (20, Frag);\n      LE_32 (24, Offset);\n      LE_32 (28, FileSize);\n      offset = 32;\n    }\n    else\n    {\n      if (size < 56)\n        return 0;\n      LE_64 (16, StartBlock);\n      LE_64 (24, FileSize);\n      // LE_64 (32, Sparse);\n      // LE_32 (40, NumLinks);\n      LE_32 (44, Frag);\n      LE_32 (48, Offset);\n      // LE_32 (52, Xattr);\n      offset = 56;\n    }\n    UInt64 pos = GetNumBlocks(_h) * 4 + offset;\n    return (pos <= size) ? (UInt32)pos : 0;\n  }\n  \n  if (Type == kType_DIR)\n  {\n    if (size < 32)\n      return 0;\n    LE_32 (16, StartBlock);\n    // LE_32 (20, NumLinks);\n    LE_16 (24, FileSize);\n    LE_16 (26, Offset);\n    // LE_32 (28, Parent);\n    return 32;\n  }\n  \n  // LE_32 (16, NumLinks);\n\n  if (Type == kType_DIR + 7)\n  {\n    if (size < 40)\n      return 0;\n    LE_32 (20, FileSize);\n    LE_32 (24, StartBlock);\n    // LE_32 (28, Parent);\n    UInt32 iCount;\n    LE_16 (32, iCount);\n    LE_16 (34, Offset);\n    // LE_32 (36, Xattr);\n\n    UInt32 pos = 40;\n    for (UInt32 i = 0; i < iCount; i++)\n    {\n      // UInt32 index\n      // UInt32 startBlock\n      if (pos + 12 > size)\n        return 0;\n      UInt32 nameLen = GetUi32(p + pos + 8);\n      pos += 12 + nameLen + 1;\n      if (pos > size || nameLen > (1 << 10))\n        return 0;\n    }\n    return pos;\n  }\n  \n  unsigned offset = 20;\n  switch (Type)\n  {\n    case kType_FIFO: case kType_FIFO + 7:\n    case kType_SOCK: case kType_SOCK + 7:\n      break;\n    case kType_LNK: case kType_LNK + 7:\n    {\n      if (size < 24)\n        return 0;\n      UInt32 len;\n      LE_32 (20, len);\n      FileSize = len;\n      offset = len + 24;\n      if (size < offset || len > (1 << 30))\n        return 0;\n      break;\n    }\n    case kType_BLK: case kType_BLK + 7:\n    case kType_CHR: case kType_CHR + 7:\n      if (size < 24)\n        return 0;\n      // LE_32 (20, RDev);\n      offset = 24;\n      break;\n    default:\n      return 0;\n  }\n  \n  if (Type >= 8)\n  {\n    if (size < offset + 4)\n      return 0;\n    // LE_32 (offset, Xattr);\n    offset += 4;\n  }\n  return offset;\n}\n\nstruct CItem\n{\n  int Node;\n  int Parent;\n  UInt32 Ptr;\n\n  CItem(): Node(-1), Parent(-1), Ptr(0) {}\n};\n\nstruct CData\n{\n  CByteBuffer Data;\n  CRecordVector<UInt32> PackPos;\n  CRecordVector<UInt32> UnpackPos; // additional item at the end contains TotalUnpackSize\n  \n  UInt32 GetNumBlocks() const { return PackPos.Size(); }\n  void Clear()\n  {\n    Data.Free();\n    PackPos.Clear();\n    UnpackPos.Clear();\n  }\n};\n\nstruct CFrag\n{\n  UInt64 StartBlock;\n  UInt32 Size;\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  bool _noPropsLZMA;\n  bool _needCheckLzma;\n\n  CRecordVector<CItem> _items;\n  CRecordVector<CNode> _nodes;\n  CRecordVector<UInt32> _nodesPos;\n  CRecordVector<UInt32> _blockToNode;\n  CData _inodesData;\n  CData _dirs;\n  CRecordVector<CFrag> _frags;\n  CByteBuffer _uids;\n  CByteBuffer _gids;\n  CHeader _h;\n  \n  UInt64 _sizeCalculated;\n  CMyComPtr<IInStream> _stream;\n\n  IArchiveOpenCallback *_openCallback;\n\n  UInt32 _openCodePage;\n  int _nodeIndex;\n  CRecordVector<bool> _blockCompressed;\n  CRecordVector<UInt64> _blockOffsets;\n  \n  CByteBuffer _cachedBlock;\n  UInt64 _cachedBlockStartPos;\n  UInt32 _cachedPackBlockSize;\n  UInt32 _cachedUnpackBlockSize;\n\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> _limitedInStream;\n  CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> _outStream;\n  CMyComPtr2_Create<ISequentialOutStream, CDynBufSeqOutStream> _dynOutStream;\n\n  // CMyComPtr2<ICompressCoder, NCompress::NLzma::CDecoder> _lzmaDecoder;\n  CMyComPtr2<ICompressCoder, NCompress::NZlib::CDecoder> _zlibDecoder;\n\n  // **************** 7-Zip ZS Modification Start ****************\n  NCompress::NZSTD::CDecoder* _zstdDecoderSpec;\n  CMyComPtr<ICompressCoder> _zstdDecoder;\n  // **************** 7-Zip ZS Modification End ****************\n  \n  CXzUnpacker _xz;\n  // **************** 7-Zip ZS Modification Start ****************\n  // CZstdDecHandle _zstd;\n  // **************** 7-Zip ZS Modification End ****************\n\n  CByteBuffer _inputBuffer;\n\n  void ClearCache()\n  {\n    _cachedBlockStartPos = 0;\n    _cachedPackBlockSize = 0;\n    _cachedUnpackBlockSize = 0;\n  }\n\n  HRESULT Seek2(UInt64 offset)\n  {\n    return InStream_SeekSet(_stream, offset);\n  }\n\n  HRESULT Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize,\n      UInt32 inSize, UInt32 outSizeMax);\n  HRESULT ReadMetadataBlock(UInt32 &packSize);\n  HRESULT ReadMetadataBlock2();\n  HRESULT ReadData(CData &data, UInt64 start, UInt64 end);\n\n  HRESULT OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex);\n  HRESULT ScanInodes(UInt64 ptr);\n  HRESULT ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids);\n  HRESULT Open2(IInStream *inStream);\n  AString GetPath(unsigned index) const;\n  bool GetPackSize(unsigned index, UInt64 &res, bool fillOffsets);\n\npublic:\n  CHandler();\n  ~CHandler()\n  {\n    XzUnpacker_Free(&_xz);\n    // **************** 7-Zip ZS Modification Start ****************\n    // if (_zstd)\n    //   ZstdDec_Destroy(_zstd);\n    // **************** 7-Zip ZS Modification End ****************\n  }\n\n  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize);\n};\n\n// **************** 7-Zip ZS Modification Start ****************\n// CHandler::CHandler():\n//     _zstd(NULL)\nCHandler::CHandler()\n// **************** 7-Zip ZS Modification End ****************\n{\n  XzUnpacker_Construct(&_xz, &g_Alloc);\n}\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidPosixAttrib,\n  kpidUserId,\n  kpidGroupId\n  // kpidLinks,\n  // kpidOffset\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidHeadersSize,\n  kpidFileSystem,\n  kpidMethod,\n  kpidClusterSize,\n  kpidBigEndian,\n  kpidCTime,\n  kpidCharacts,\n  kpidCodePage\n  // kpidNumBlocks\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic HRESULT LzoDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)\n{\n  SizeT destRem = *destLen;\n  SizeT srcRem = *srcLen;\n  *destLen = 0;\n  *srcLen = 0;\n  const Byte *destStart = dest;\n  const Byte *srcStart = src;\n  unsigned mode = 0;\n\n  {\n    if (srcRem == 0)\n      return S_FALSE;\n    UInt32 b = *src;\n    if (b > 17)\n    {\n      src++;\n      srcRem--;\n      b -= 17;\n      mode = (b < 4 ? 1 : 4);\n      if (b > srcRem || b > destRem)\n        return S_FALSE;\n      srcRem -= b;\n      destRem -= b;\n      do\n        *dest++ = *src++;\n      while (--b);\n    }\n  }\n\n  for (;;)\n  {\n    if (srcRem < 3)\n      return S_FALSE;\n    UInt32 b = *src++;\n    srcRem--;\n    UInt32 len, back;\n    \n    if (b >= 64)\n    {\n      srcRem--;\n      back = ((b >> 2) & 7) + ((UInt32)*src++ << 3);\n      len = (b >> 5) + 1;\n    }\n    else if (b < 16)\n    {\n      if (mode == 0)\n      {\n        if (b == 0)\n        {\n          for (b = 15;; b += 255)\n          {\n            if (srcRem == 0)\n              return S_FALSE;\n            UInt32 b2 = *src++;\n            srcRem--;\n            if (b2 != 0)\n            {\n              b += b2;\n              break;\n            }\n          }\n        }\n      \n        b += 3;\n        if (b > srcRem || b > destRem)\n          return S_FALSE;\n        srcRem -= b;\n        destRem -= b;\n        mode = 4;\n        do\n          *dest++ = *src++;\n        while (--b);\n        continue;\n      }\n      \n      srcRem--;\n      back = (b >> 2) + ((UInt32)*src++ << 2);\n      len = 2;\n      if (mode == 4)\n      {\n        back += (1 << 11);\n        len = 3;\n      }\n    }\n    else\n    {\n      UInt32 bOld = b;\n      b = (b < 32 ? 7 : 31);\n      len = bOld & b;\n      \n      if (len == 0)\n      {\n        for (len = b;; len += 255)\n        {\n          if (srcRem == 0)\n            return S_FALSE;\n          UInt32 b2 = *src++;\n          srcRem--;\n          if (b2 != 0)\n          {\n            len += b2;\n            break;\n          }\n        }\n      }\n      \n      len += 2;\n      if (srcRem < 2)\n        return S_FALSE;\n      b = *src;\n      back = (b >> 2) + ((UInt32)src[1] << 6);\n      src += 2;\n      srcRem -= 2;\n      if (bOld < 32)\n      {\n        back += ((bOld & 8) << 11);\n        if (back == 0)\n        {\n          *destLen = (size_t)(dest - destStart);\n          *srcLen = (size_t)(src - srcStart);\n          return S_OK;\n        }\n        back += (1 << 14) - 1;\n      }\n    }\n    \n    back++;\n    if (len > destRem || (size_t)(dest - destStart) < back)\n      return S_FALSE;\n    destRem -= len;\n    Byte *destTemp = dest - back;\n    dest += len;\n    \n    do\n    {\n      *(destTemp + back) = *destTemp;\n      destTemp++;\n    }\n    while (--len);\n    \n    b &= 3;\n    mode = b;\n    if (b == 0)\n      continue;\n    if (b > srcRem || b > destRem)\n      return S_FALSE;\n    srcRem -= b;\n    destRem -= b;\n    *dest++ = *src++;\n    if (b > 1)\n    {\n      *dest++ = *src++;\n      if (b > 2)\n        *dest++ = *src++;\n    }\n  }\n}\n\n// **************** 7-Zip ZS Modification Start ****************\nstatic HRESULT Lz4Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen)\n{\n  const char *Src = (const char *)src;\n  char *Dst = (char *)dest;\n  int compressedSize = (int)*srcLen;\n  int dstCapacity = (int)*destLen;\n  // int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);\n  int rv = LZ4_decompress_safe(Src, Dst, compressedSize, dstCapacity);\n  if (rv == 0)\n    return S_FALSE;\n\n  *destLen = rv;\n  return S_OK;\n}\n// **************** 7-Zip ZS Modification End ****************\n\nHRESULT CHandler::Decompress(ISequentialOutStream *outStream, Byte *outBuf, bool *outBufWasWritten, UInt32 *outBufWasWrittenSize, UInt32 inSize, UInt32 outSizeMax)\n{\n  if (outBuf)\n  {\n    *outBufWasWritten = false;\n    *outBufWasWrittenSize = 0;\n  }\n  UInt32 method = _h.Method;\n  if (_h.SeveralMethods)\n  {\n    Byte b;\n    RINOK(ReadStream_FALSE(_stream, &b, 1))\n    RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL))\n    method = (b == 0x5D ? kMethod_LZMA : kMethod_ZLIB);\n  }\n\n  if (method == kMethod_ZLIB && _needCheckLzma)\n  {\n    Byte b;\n    RINOK(ReadStream_FALSE(_stream, &b, 1))\n    RINOK(_stream->Seek(-1, STREAM_SEEK_CUR, NULL))\n    if (b == 0)\n    {\n      _noPropsLZMA = true;\n      method = _h.Method = kMethod_LZMA;\n    }\n    _needCheckLzma = false;\n  }\n  \n  if (method == kMethod_ZLIB)\n  {\n    _zlibDecoder.Create_if_Empty();\n    RINOK(_zlibDecoder.Interface()->Code(_limitedInStream, outStream, NULL, NULL, NULL))\n    if (inSize != _zlibDecoder->GetInputProcessedSize())\n      return S_FALSE;\n  }\n  // **************** 7-Zip ZS Modification Start ****************\n  else if (method == kMethod_ZSTD)\n  {\n    if (!_zstdDecoder)\n    {\n      _zstdDecoderSpec = new NCompress::NZSTD::CDecoder();\n      _zstdDecoder = _zstdDecoderSpec;\n    }\n    RINOK(_zstdDecoder->Code(_limitedInStream, outStream, NULL, NULL, NULL));\n    if (inSize != _zstdDecoderSpec->GetInputProcessedSize())\n      return S_FALSE;\n  }\n  // **************** 7-Zip ZS Modification End ****************\n  /*\n  else if (method == kMethod_LZMA)\n  {\n    _lzmaDecoder.Create_if_Empty();\n    // _lzmaDecoder->FinishStream = true;\n    const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;\n    Byte props[kPropsSize];\n    UInt32 propsSize;\n    UInt64 outSize;\n    if (_noPropsLZMA)\n    {\n      props[0] = 0x5D;\n      SetUi32(&props[1], _h.BlockSize);\n      propsSize = 0;\n      outSize = outSizeMax;\n    }\n    else\n    {\n      RINOK(ReadStream_FALSE(_limitedInStream, props, kPropsSize));\n      propsSize = kPropsSize;\n      outSize = GetUi64(&props[LZMA_PROPS_SIZE]);\n      if (outSize > outSizeMax)\n        return S_FALSE;\n    }\n    RINOK(_lzmaDecoderSpec->SetDecoderProperties2(props, LZMA_PROPS_SIZE));\n    RINOK(_lzmaDecoder->Code(_limitedInStream, outStream, NULL, &outSize, NULL));\n    if (inSize != propsSize + _lzmaDecoderSpec->GetInputProcessedSize())\n      return S_FALSE;\n  }\n  */\n  else\n  {\n    if (_inputBuffer.Size() < inSize)\n      _inputBuffer.Alloc(inSize);\n    RINOK(ReadStream_FALSE(_stream, _inputBuffer, inSize))\n\n    Byte *dest = outBuf;\n    if (!outBuf)\n    {\n      dest = _dynOutStream->GetBufPtrForWriting(outSizeMax);\n      if (!dest)\n        return E_OUTOFMEMORY;\n    }\n    \n    SizeT destLen = outSizeMax, srcLen = inSize;\n\n    if (method == kMethod_LZO)\n    {\n      RINOK(LzoDecode(dest, &destLen, _inputBuffer, &srcLen))\n    }\n    // **************** 7-Zip ZS Modification Start ****************\n    else if (method == kMethod_LZ4)\n    {\n      RINOK(Lz4Decode(dest, &destLen, _inputBuffer, &srcLen));\n    }\n    // **************** 7-Zip ZS Modification End ****************\n    else if (method == kMethod_LZMA)\n    {\n      Byte props[5];\n      const Byte *src = _inputBuffer;\n\n      if (_noPropsLZMA)\n      {\n        props[0] = 0x5D;\n        SetUi32(&props[1], _h.BlockSize)\n      }\n      else\n      {\n        const UInt32 kPropsSize = LZMA_PROPS_SIZE + 8;\n        if (inSize < kPropsSize)\n          return S_FALSE;\n        memcpy(props, src, LZMA_PROPS_SIZE);\n        UInt64 outSize = GetUi64(src + LZMA_PROPS_SIZE);\n        if (outSize > outSizeMax)\n          return S_FALSE;\n        destLen = (SizeT)outSize;\n        src += kPropsSize;\n        inSize -= kPropsSize;\n        srcLen = inSize;\n      }\n\n      ELzmaStatus status;\n      SRes res = LzmaDecode(dest, &destLen,\n          src, &srcLen,\n          props, LZMA_PROPS_SIZE,\n          LZMA_FINISH_END,\n          &status, &g_Alloc);\n      if (res != 0)\n        return SResToHRESULT(res);\n      if (status != LZMA_STATUS_FINISHED_WITH_MARK\n          && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)\n        return S_FALSE;\n    }\n    // **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n    else if (method == kMethod_ZSTD)\n    {\n      const Byte *src = _inputBuffer;\n\n      if (!_zstd)\n      {\n        _zstd = ZstdDec_Create(&g_AlignedAlloc, &g_AlignedAlloc);\n        if (!_zstd)\n          return E_OUTOFMEMORY;\n      }\n\n      CZstdDecState state;\n      ZstdDecState_Clear(&state);\n\n      state.inBuf = src;\n      state.inLim = srcLen; //  + 1; for debug\n      // state.outStep = outSizeMax;\n      \n      state.outBuf_fromCaller = dest;\n      state.outBufSize_fromCaller = outSizeMax;\n      // state.mustBeFinished = True;\n\n      ZstdDec_Init(_zstd);\n      SRes sres;\n      for (;;)\n      {\n        sres = ZstdDec_Decode(_zstd, &state);\n        if (sres != SZ_OK)\n          break;\n        if (state.inLim == state.inPos\n            && (state.status == ZSTD_STATUS_NEEDS_MORE_INPUT ||\n                state.status == ZSTD_STATUS_FINISHED_FRAME))\n          break;\n        // sres = sres;\n        // break; // for debug\n      }\n\n      CZstdDecResInfo info;\n      // ZstdDecInfo_Clear(&stat);\n      // stat->InSize = state.inPos;\n      ZstdDec_GetResInfo(_zstd, &state, sres, &info);\n      sres = info.decode_SRes;\n      if (sres == SZ_OK)\n      {\n        if (state.status != ZSTD_STATUS_FINISHED_FRAME\n            // ||stat.UnexpededEnd\n            || info.extraSize != 0\n            || state.inLim != state.inPos)\n          sres = SZ_ERROR_DATA;\n      }\n      if (sres != SZ_OK)\n        return SResToHRESULT(sres);\n      if (state.winPos > outSizeMax)\n        return E_FAIL;\n      // memcpy(dest, state.dic, state.dicPos);\n      destLen = state.winPos;\n    }\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n    // **************** 7-Zip ZS Modification End ****************\n    else\n    {\n      ECoderStatus status;\n      const SRes res = XzUnpacker_CodeFull(&_xz,\n          dest, &destLen,\n          _inputBuffer, &srcLen,\n          CODER_FINISH_END, &status);\n      if (res != 0)\n        return SResToHRESULT(res);\n      if (status != CODER_STATUS_NEEDS_MORE_INPUT || !XzUnpacker_IsStreamWasFinished(&_xz))\n        return S_FALSE;\n    }\n    \n    if (inSize != srcLen)\n      return S_FALSE;\n    if (outBuf)\n    {\n      *outBufWasWritten = true;\n      *outBufWasWrittenSize = (UInt32)destLen;\n    }\n    else\n      _dynOutStream->UpdateSize(destLen);\n  }\n  return S_OK;\n}\n\nHRESULT CHandler::ReadMetadataBlock(UInt32 &packSize)\n{\n  Byte temp[3];\n  const unsigned offset = _h.NeedCheckData() ? 3 : 2;\n  if (offset > packSize)\n    return S_FALSE;\n  RINOK(ReadStream_FALSE(_stream, temp, offset))\n  // if (NeedCheckData && Major < 4) checkByte must be = 0xFF\n  const bool be = _h.be;\n  UInt32 size = Get16(temp);\n  const bool isCompressed = ((size & kNotCompressedBit16) == 0);\n  if (size != kNotCompressedBit16)\n    size &= ~kNotCompressedBit16;\n\n  if (size > kMetadataBlockSize || offset + size > packSize)\n    return S_FALSE;\n  packSize = offset + size;\n  if (isCompressed)\n  {\n    _limitedInStream->Init(size);\n    RINOK(Decompress(_dynOutStream, NULL, NULL, NULL, size, kMetadataBlockSize))\n  }\n  else\n  {\n    // size != 0 here\n    Byte *buf = _dynOutStream->GetBufPtrForWriting(size);\n    if (!buf)\n      return E_OUTOFMEMORY;\n    RINOK(ReadStream_FALSE(_stream, buf, size))\n    _dynOutStream->UpdateSize(size);\n  }\n  return S_OK;\n}\n\n\nHRESULT CHandler::ReadMetadataBlock2()\n{\n  _dynOutStream->Init();\n  UInt32 packSize = kMetadataBlockSize + 3; // check it\n  return ReadMetadataBlock(packSize);\n}\n\nHRESULT CHandler::ReadData(CData &data, UInt64 start, UInt64 end)\n{\n  if (end < start || end - start >= ((UInt64)1 << 32))\n    return S_FALSE;\n  const UInt32 size = (UInt32)(end - start);\n  RINOK(Seek2(start))\n  _dynOutStream->Init();\n  UInt32 packPos = 0;\n  while (packPos != size)\n  {\n    data.PackPos.Add(packPos);\n    data.UnpackPos.Add((UInt32)_dynOutStream->GetSize());\n    if (packPos > size)\n      return S_FALSE;\n    UInt32 packSize = size - packPos;\n    RINOK(ReadMetadataBlock(packSize))\n    {\n      const size_t tSize = _dynOutStream->GetSize();\n      if (tSize != (UInt32)tSize)\n        return S_FALSE;\n    }\n    packPos += packSize;\n  }\n  data.UnpackPos.Add((UInt32)_dynOutStream->GetSize());\n  _dynOutStream->CopyToBuffer(data.Data);\n  return S_OK;\n}\n\nstruct CTempItem\n{\n  UInt32 StartBlock;\n  // UInt32 iNodeNumber1;\n  UInt32 Offset;\n  // UInt16 iNodeNumber2;\n  UInt16 Type;\n};\n  \nHRESULT CHandler::OpenDir(int parent, UInt32 startBlock, UInt32 offset, unsigned level, int &nodeIndex)\n{\n  if (level > kNumDirLevelsMax)\n    return S_FALSE;\n\n  int blockIndex = _inodesData.PackPos.FindInSorted(startBlock);\n  if (blockIndex < 0)\n    return S_FALSE;\n  UInt32 unpackPos = _inodesData.UnpackPos[blockIndex] + offset;\n  if (unpackPos < offset)\n    return S_FALSE;\n\n  nodeIndex = _nodesPos.FindInSorted(unpackPos, _blockToNode[blockIndex], _blockToNode[blockIndex + 1]);\n  // nodeIndex = _nodesPos.FindInSorted(unpackPos);\n  if (nodeIndex < 0)\n    return S_FALSE;\n  \n  const CNode &n = _nodes[nodeIndex];\n  if (!n.IsDir())\n    return S_OK;\n  blockIndex = _dirs.PackPos.FindInSorted((UInt32)n.StartBlock);\n  if (blockIndex < 0)\n    return S_FALSE;\n  unpackPos = _dirs.UnpackPos[blockIndex] + n.Offset;\n  if (unpackPos < n.Offset || unpackPos > _dirs.Data.Size())\n    return S_FALSE;\n\n  UInt32 rem = (UInt32)_dirs.Data.Size() - unpackPos;\n  const Byte *p = _dirs.Data + unpackPos;\n  UInt32 fileSize = (UInt32)n.FileSize;\n\n  // for some squashfs files: fileSize = rem + 3  !!!\n  if (_h.Major >= 3)\n  {\n    if (fileSize < 3)\n      return S_FALSE;\n    fileSize -= 3;\n  }\n  if (fileSize > rem)\n    return S_FALSE;\n  rem = fileSize;\n\n  AString tempString;\n\n  CRecordVector<CTempItem> tempItems;\n  while (rem != 0)\n  {\n    const bool be = _h.be;\n    UInt32 count;\n    CTempItem tempItem;\n    if (_h.Major <= 2)\n    {\n      if (rem < 4)\n        return S_FALSE;\n      count = p[0];\n      tempItem.StartBlock = Get32(p);\n      if (be)\n        tempItem.StartBlock &= 0xFFFFFF;\n      else\n        tempItem.StartBlock >>= 8;\n      p += 4;\n      rem -= 4;\n    }\n    else\n    {\n      if (_h.Major == 3)\n      {\n        if (rem < 9)\n          return S_FALSE;\n        count = p[0];\n        p += 1;\n        rem -= 1;\n      }\n      else\n      {\n        if (rem < 12)\n          return S_FALSE;\n        count = GetUi32(p);\n        p += 4;\n        rem -= 4;\n      }\n      GET_32 (0, tempItem.StartBlock);\n      // GET_32 (4, tempItem.iNodeNumber1);\n      p += 8;\n      rem -= 8;\n    }\n    count++;\n    \n    for (UInt32 i = 0; i < count; i++)\n    {\n      if (rem == 0)\n        return S_FALSE;\n\n      UInt32 nameOffset = _h.GetFileNameOffset();\n      if (rem < nameOffset)\n        return S_FALSE;\n\n      if (_items.Size() >= kNumFilesMax)\n        return S_FALSE;\n      if (_openCallback)\n      {\n        UInt64 numFiles = _items.Size();\n        if ((numFiles & 0xFFFF) == 0)\n        {\n          RINOK(_openCallback->SetCompleted(&numFiles, NULL))\n        }\n      }\n      \n      CItem item;\n      item.Ptr = (UInt32)(p - (const Byte *)_dirs.Data);\n\n      UInt32 size;\n      if (_h.IsOldVersion())\n      {\n        UInt32 t = Get16(p);\n        if (be)\n        {\n          tempItem.Offset = t >> 3;\n          tempItem.Type = (UInt16)(t & 0x7);\n        }\n        else\n        {\n          tempItem.Offset = t & 0x1FFF;\n          tempItem.Type = (UInt16)(t >> 13);\n        }\n        size = (UInt32)p[2];\n        /*\n        if (_h.Major > 2)\n          tempItem.iNodeNumber2 = Get16(p + 3);\n        */\n      }\n      else\n      {\n        GET_16 (0, tempItem.Offset);\n        // GET_16 (2, tempItem.iNodeNumber2);\n        GET_16 (4, tempItem.Type);\n        GET_16 (6, size);\n      }\n      p += nameOffset;\n      rem -= nameOffset;\n      size++;\n      if (rem < size)\n        return S_FALSE;\n\n      if (_openCodePage == CP_UTF8)\n      {\n        tempString.SetFrom_CalcLen((const char *)p, size);\n        if (!CheckUTF8_AString(tempString))\n          _openCodePage = CP_OEMCP;\n      }\n\n      p += size;\n      rem -= size;\n      item.Parent = parent;\n      _items.Add(item);\n      tempItems.Add(tempItem);\n    }\n  }\n\n  const unsigned startItemIndex = _items.Size() - tempItems.Size();\n  FOR_VECTOR (i, tempItems)\n  {\n    const CTempItem &tempItem = tempItems[i];\n    const unsigned index = startItemIndex + i;\n    CItem &item = _items[index];\n    RINOK(OpenDir((int)index, tempItem.StartBlock, tempItem.Offset, level + 1, item.Node))\n  }\n\n  return S_OK;\n}\n\nHRESULT CHandler::ReadUids(UInt64 start, UInt32 num, CByteBuffer &ids)\n{\n  const size_t size = (size_t)num * 4;\n  ids.Alloc(size);\n  if (num == 0)\n    return S_OK;\n  RINOK(Seek2(start))\n  return ReadStream_FALSE(_stream, ids, size);\n}\n\nHRESULT CHandler::Open2(IInStream *inStream)\n{\n  {\n    Byte buf[kHeaderSize3];\n    RINOK(ReadStream_FALSE(inStream, buf, kHeaderSize3))\n    if (!_h.Parse(buf))\n      return S_FALSE;\n    if (!_h.IsSupported())\n      return E_NOTIMPL;\n    \n    _noPropsLZMA = false;\n    _needCheckLzma = false;\n    switch (_h.Method)\n    {\n      case kMethod_ZLIB: _needCheckLzma = true; break;\n      case kMethod_LZMA:\n      case kMethod_LZO:\n      case kMethod_XZ:\n      // **************** 7-Zip ZS Modification Start ****************\n      case kMethod_LZ4:\n      // **************** 7-Zip ZS Modification End ****************\n      case kMethod_ZSTD:\n        break;\n      default:\n        return E_NOTIMPL;\n    }\n  }\n\n  _stream = inStream;\n\n  if (_h.NumFrags != 0)\n  {\n    if (_h.NumFrags > kNumFilesMax)\n      return S_FALSE;\n    _frags.ClearAndReserve(_h.NumFrags);\n    const unsigned bigFrag = (_h.Major > 2);\n    \n    const unsigned fragPtrsInBlockLog = kMetadataBlockSizeLog - (3 + bigFrag);\n    const UInt32 numBlocks = (_h.NumFrags + (1 << fragPtrsInBlockLog) - 1) >> fragPtrsInBlockLog;\n    const size_t numBlocksBytes = (size_t)numBlocks << (2 + bigFrag);\n    CByteBuffer data(numBlocksBytes);\n    RINOK(Seek2(_h.FragTable))\n    RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes))\n    const bool be = _h.be;\n    \n    for (UInt32 i = 0; i < numBlocks; i++)\n    {\n      const UInt64 offset = bigFrag ? Get64(data + i * 8) : Get32(data + i * 4);\n      RINOK(Seek2(offset))\n      RINOK(ReadMetadataBlock2())\n      const UInt32 unpackSize = (UInt32)_dynOutStream->GetSize();\n      if (unpackSize != kMetadataBlockSize)\n        if (i != numBlocks - 1 || unpackSize != ((_h.NumFrags << (3 + bigFrag)) & (kMetadataBlockSize - 1)))\n          return S_FALSE;\n      const Byte *buf = _dynOutStream->GetBuffer();\n      for (UInt32 j = 0; j < kMetadataBlockSize && j < unpackSize;)\n      {\n        CFrag frag;\n        if (bigFrag)\n        {\n          frag.StartBlock = Get64(buf + j);\n          frag.Size = Get32(buf + j + 8);\n          // some archives contain nonzero in unused (buf + j + 12)\n          j += 16;\n        }\n        else\n        {\n          frag.StartBlock = Get32(buf + j);\n          frag.Size = Get32(buf + j + 4);\n          j += 8;\n        }\n        _frags.Add(frag);\n      }\n    }\n    if ((UInt32)_frags.Size() != _h.NumFrags)\n      return S_FALSE;\n  }\n\n  RINOK(ReadData(_inodesData, _h.InodeTable, _h.DirTable))\n  RINOK(ReadData(_dirs, _h.DirTable, _h.FragTable))\n\n  UInt64 absOffset = _h.RootInode >> 16;\n  if (absOffset >= ((UInt64)1 << 32))\n    return S_FALSE;\n  {\n    UInt32 pos = 0;\n    UInt32 totalSize = (UInt32)_inodesData.Data.Size();\n    const unsigned kMinNodeParseSize = 4;\n    if (_h.NumInodes > totalSize / kMinNodeParseSize)\n      return S_FALSE;\n    _nodesPos.ClearAndReserve(_h.NumInodes);\n    _nodes.ClearAndReserve(_h.NumInodes);\n    // we use _blockToNode for binary search seed optimizations\n    _blockToNode.ClearAndReserve(_inodesData.GetNumBlocks() + 1);\n    unsigned curBlock = 0;\n    for (UInt32 i = 0; i < _h.NumInodes; i++)\n    {\n      CNode n;\n      const Byte *p = _inodesData.Data + pos;\n      UInt32 size = totalSize - pos;\n\n      switch (_h.Major)\n      {\n        case 1:  size = n.Parse1(p, size, _h); break;\n        case 2:  size = n.Parse2(p, size, _h); break;\n        case 3:  size = n.Parse3(p, size, _h); break;\n        default: size = n.Parse4(p, size, _h); break;\n      }\n      if (size == 0)\n        return S_FALSE;\n      while (pos >= _inodesData.UnpackPos[curBlock])\n      {\n        _blockToNode.Add(_nodesPos.Size());\n        curBlock++;\n      }\n      _nodesPos.AddInReserved(pos);\n      _nodes.AddInReserved(n);\n      pos += size;\n    }\n    _blockToNode.Add(_nodesPos.Size());\n    if (pos != totalSize)\n      return S_FALSE;\n  }\n  int rootNodeIndex;\n  RINOK(OpenDir(-1, (UInt32)absOffset, (UInt32)_h.RootInode & 0xFFFF, 0, rootNodeIndex))\n\n  if (_h.Major < 4)\n  {\n    RINOK(ReadUids(_h.UidTable, _h.NumUids, _uids))\n    RINOK(ReadUids(_h.GidTable, _h.NumGids, _gids))\n  }\n  else\n  {\n    const UInt32 size = (UInt32)_h.NumIDs * 4;\n    _uids.Alloc(size);\n\n    const UInt32 numBlocks = (size + kMetadataBlockSize - 1) / kMetadataBlockSize;\n    const UInt32 numBlocksBytes = numBlocks << 3;\n    CByteBuffer data(numBlocksBytes);\n    RINOK(Seek2(_h.UidTable))\n    RINOK(ReadStream_FALSE(inStream, data, numBlocksBytes))\n\n    for (UInt32 i = 0; i < numBlocks; i++)\n    {\n      const UInt64 offset = GetUi64(data + i * 8);\n      RINOK(Seek2(offset))\n      // RINOK(ReadMetadataBlock(NULL, _uids + kMetadataBlockSize * i, packSize, unpackSize));\n      RINOK(ReadMetadataBlock2())\n      const size_t unpackSize = _dynOutStream->GetSize();\n      const UInt32 remSize = (i == numBlocks - 1)  ?\n          (size & (kMetadataBlockSize - 1)) : kMetadataBlockSize;\n      if (unpackSize != remSize)\n        return S_FALSE;\n      memcpy(_uids + kMetadataBlockSize * i, _dynOutStream->GetBuffer(), remSize);\n    }\n  }\n\n  {\n    const UInt32 alignSize = 1 << 12;\n    Byte buf[alignSize];\n    RINOK(Seek2(_h.Size))\n    UInt32 rem = (UInt32)(0 - _h.Size) & (alignSize - 1);\n    _sizeCalculated = _h.Size;\n    if (rem != 0)\n    {\n      if (ReadStream_FALSE(_stream, buf, rem) == S_OK)\n      {\n        size_t i;\n        for (i = 0; i < rem && buf[i] == 0; i++);\n        if (i == rem)\n          _sizeCalculated = _h.Size + rem;\n      }\n    }\n  }\n  return S_OK;\n}\n\nAString CHandler::GetPath(unsigned index) const\n{\n  unsigned len = 0;\n  const unsigned indexMem = index;\n  const bool be = _h.be;\n  for (;;)\n  {\n    const CItem &item = _items[index];\n    const Byte *p = _dirs.Data + item.Ptr;\n    const unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;\n    p += _h.GetFileNameOffset();\n    unsigned i;\n    for (i = 0; i < size && p[i]; i++);\n    len += i + 1;\n    index = (unsigned)item.Parent;\n    if (item.Parent < 0)\n      break;\n  }\n  len--;\n\n  AString path;\n  char *dest = path.GetBuf_SetEnd(len) + len;\n  index = indexMem;\n  for (;;)\n  {\n    const CItem &item = _items[index];\n    const Byte *p = _dirs.Data + item.Ptr;\n    const unsigned size = (_h.IsOldVersion() ? (unsigned)p[2] : (unsigned)Get16(p + 6)) + 1;\n    p += _h.GetFileNameOffset();\n    unsigned i;\n    for (i = 0; i < size && p[i]; i++);\n    dest -= i;\n    memcpy(dest, p, i);\n    index = (unsigned)item.Parent;\n    if (item.Parent < 0)\n      break;\n    *(--dest) = CHAR_PATH_SEPARATOR;\n  }\n  return path;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    _limitedInStream->SetStream(stream);\n    HRESULT res;\n    try\n    {\n      _openCallback = callback;\n      res = Open2(stream);\n    }\n    catch(...)\n    {\n      Close();\n      throw;\n    }\n    if (res != S_OK)\n    {\n      Close();\n      return res;\n    }\n    _stream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _openCodePage = CP_UTF8;\n  _sizeCalculated = 0;\n\n  _limitedInStream->ReleaseStream();\n  _stream.Release();\n\n  _items.Clear();\n  _nodes.Clear();\n  _nodesPos.Clear();\n  _blockToNode.Clear();\n  _frags.Clear();\n  _inodesData.Clear();\n  _dirs.Clear();\n\n  _uids.Free();\n  _gids.Free();\n\n  _cachedBlock.Free();\n  ClearCache();\n\n  return S_OK;\n}\n\nbool CHandler::GetPackSize(unsigned index, UInt64 &totalPack, bool fillOffsets)\n{\n  totalPack = 0;\n  const CItem &item = _items[index];\n  const CNode &node = _nodes[item.Node];\n  const UInt32 ptr = _nodesPos[item.Node];\n  const Byte *p = _inodesData.Data + ptr;\n  const bool be = _h.be;\n\n  const UInt32 type = node.Type;\n  UInt32 offset;\n  if (node.IsLink() || node.FileSize == 0)\n  {\n    totalPack = node.FileSize;\n    return true;\n  }\n\n  const UInt32 numBlocks = (UInt32)node.GetNumBlocks(_h);\n\n  if (fillOffsets)\n  {\n    _blockOffsets.Clear();\n    _blockCompressed.Clear();\n    _blockOffsets.Add(totalPack);\n  }\n\n  if (_h.Major <= 1)\n  {\n    offset = 15;\n    p += offset;\n    \n    for (UInt32 i = 0; i < numBlocks; i++)\n    {\n      UInt32 t = Get16(p + i * 2);\n      if (fillOffsets)\n        _blockCompressed.Add((t & kNotCompressedBit16) == 0);\n      if (t != kNotCompressedBit16)\n        t &= ~kNotCompressedBit16;\n      totalPack += t;\n      if (fillOffsets)\n        _blockOffsets.Add(totalPack);\n    }\n  }\n  else\n  {\n    if (_h.Major <= 2)\n      offset = 24;\n    else if (type == kType_FILE)\n      offset = 32;\n    else if (type == kType_FILE + 7)\n      offset = (_h.Major <= 3 ? 40 : 56);\n    else\n      return false;\n    \n    p += offset;\n    \n    for (UInt64 i = 0; i < numBlocks; i++)\n    {\n      UInt32 t = Get32(p + i * 4);\n      if (fillOffsets)\n        _blockCompressed.Add(IS_COMPRESSED_BLOCK(t));\n      UInt32 size = GET_COMPRESSED_BLOCK_SIZE(t);\n      if (size > _h.BlockSize)\n        return false;\n      totalPack += size;\n      if (fillOffsets)\n        _blockOffsets.Add(totalPack);\n    }\n\n    if (node.ThereAreFrags())\n    {\n      if (node.Frag >= (UInt32)_frags.Size())\n        return false;\n      const CFrag &frag = _frags[node.Frag];\n      if (node.Offset == 0)\n      {\n        UInt32 size = GET_COMPRESSED_BLOCK_SIZE(frag.Size);\n        if (size > _h.BlockSize)\n          return false;\n        totalPack += size;\n      }\n    }\n  }\n  return true;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMethod:\n    {\n      char sz[16];\n      const char *s;\n      if (_noPropsLZMA)\n        s = \"LZMA Spec\";\n      else if (_h.SeveralMethods)\n        s = \"LZMA ZLIB\";\n      else\n      {\n        s = NULL;\n        if (_h.Method < Z7_ARRAY_SIZE(k_Methods))\n          s = k_Methods[_h.Method];\n        if (!s)\n        {\n          ConvertUInt32ToString(_h.Method, sz);\n          s = sz;\n        }\n      }\n      prop = s;\n      break;\n    }\n    case kpidFileSystem:\n    {\n      AString res (\"SquashFS\");\n      if (_h.SeveralMethods)\n        res += \"-LZMA\";\n      res.Add_Space();\n      res.Add_UInt32(_h.Major);\n      res.Add_Dot();\n      res.Add_UInt32(_h.Minor);\n      prop = res;\n      break;\n    }\n    case kpidClusterSize: prop = _h.BlockSize; break;\n    case kpidBigEndian: prop = _h.be; break;\n    case kpidCTime:\n      if (_h.CTime != 0)\n        PropVariant_SetFrom_UnixTime(prop, _h.CTime);\n      break;\n    case kpidCharacts: FLAGS_TO_PROP(k_Flags, _h.Flags, prop); break;\n    // case kpidNumBlocks: prop = _h.NumFrags; break;\n    case kpidPhySize: prop = _sizeCalculated; break;\n    case kpidHeadersSize:\n      if (_sizeCalculated >= _h.InodeTable)\n        prop = _sizeCalculated - _h.InodeTable;\n      break;\n\n    case kpidCodePage:\n    {\n      char sz[16];\n      const char *name = NULL;\n      switch (_openCodePage)\n      {\n        case CP_OEMCP: name = \"OEM\"; break;\n        case CP_UTF8: name = \"UTF-8\"; break;\n      }\n      if (!name)\n      {\n        ConvertUInt32ToString(_openCodePage, sz);\n        name = sz;\n      }\n      prop = name;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CItem &item = _items[index];\n  const CNode &node = _nodes[item.Node];\n  const bool isDir = node.IsDir();\n  const bool be = _h.be;\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      AString path (GetPath(index));\n      UString s;\n      if (_openCodePage == CP_UTF8)\n        ConvertUTF8ToUnicode(path, s);\n      else\n        MultiByteToUnicodeString2(s, path, _openCodePage);\n      prop = s;\n      break;\n    }\n    case kpidIsDir: prop = isDir; break;\n    // case kpidOffset: if (!node.IsLink()) prop = (UInt64)node.StartBlock; break;\n    case kpidSize: if (!isDir) prop = node.GetSize(); break;\n    case kpidPackSize:\n      if (!isDir)\n      {\n        UInt64 size;\n        if (GetPackSize(index, size, false))\n          prop = size;\n      }\n      break;\n    case kpidMTime:\n    {\n      UInt32 offset = 0;\n      switch (_h.Major)\n      {\n        case 1:\n          if (node.Type == kType_FILE)\n            offset = 3;\n          else if (node.Type == kType_DIR)\n            offset = 7;\n          break;\n        case 2:\n          if (node.Type == kType_FILE)\n            offset = 4;\n          else if (node.Type == kType_DIR)\n            offset = 8;\n          else if (node.Type == kType_DIR + 7)\n            offset = 9;\n          break;\n        case 3: offset = 4; break;\n        case 4: offset = 8; break;\n      }\n      if (offset != 0)\n      {\n        const Byte *p = _inodesData.Data + _nodesPos[item.Node] + offset;\n        PropVariant_SetFrom_UnixTime(prop, Get32(p));\n      }\n      break;\n    }\n    case kpidPosixAttrib:\n    {\n      if (node.Type != 0 && node.Type < Z7_ARRAY_SIZE(k_TypeToMode))\n        prop = (UInt32)(node.Mode & 0xFFF) | k_TypeToMode[node.Type];\n      break;\n    }\n    case kpidUserId:\n    case kpidGroupId:\n    {\n      UInt32 id = node.Uid;\n      const CByteBuffer *ids = &_uids;\n      if (propID == kpidGroupId)\n      {\n        id = node.Gid;\n        if (_h.Major < 4)\n        {\n          if (id == _h.GetSpecGuidIndex())\n            id = node.Uid;\n          else\n            ids = &_gids;\n        }\n      }\n      const UInt32 offset = (UInt32)id * 4;\n      if (offset < ids->Size())\n        prop = (UInt32)Get32(*ids + offset);\n      break;\n    }\n    /*\n    case kpidLinks:\n      if (_h.Major >= 3 && node.Type != kType_FILE)\n        prop = node.NumLinks;\n      break;\n    */\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nclass CSquashfsInStream: public CCachedInStream\n{\n  HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) Z7_override;\npublic:\n  CHandler *Handler;\n};\n\nHRESULT CSquashfsInStream::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\n{\n  return Handler->ReadBlock(blockIndex, dest, blockSize);\n}\n\nHRESULT CHandler::ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize)\n{\n  const CNode &node = _nodes[_nodeIndex];\n  UInt64 blockOffset;\n  UInt32 packBlockSize;\n  UInt32 offsetInBlock = 0;\n  bool compressed;\n  if (blockIndex < _blockCompressed.Size())\n  {\n    compressed = _blockCompressed[(unsigned)blockIndex];\n    blockOffset = _blockOffsets[(unsigned)blockIndex];\n    packBlockSize = (UInt32)(_blockOffsets[(unsigned)blockIndex + 1] - blockOffset);\n    blockOffset += node.StartBlock;\n  }\n  else\n  {\n    if (!node.ThereAreFrags())\n      return S_FALSE;\n    const CFrag &frag = _frags[node.Frag];\n    offsetInBlock = node.Offset;\n    blockOffset = frag.StartBlock;\n    packBlockSize = GET_COMPRESSED_BLOCK_SIZE(frag.Size);\n    compressed = IS_COMPRESSED_BLOCK(frag.Size);\n  }\n\n  if (packBlockSize == 0)\n  {\n    // sparse file ???\n    memset(dest, 0, blockSize);\n    return S_OK;\n  }\n\n  if (blockOffset != _cachedBlockStartPos ||\n      packBlockSize != _cachedPackBlockSize)\n  {\n    ClearCache();\n    RINOK(Seek2(blockOffset))\n    _limitedInStream->Init(packBlockSize);\n    \n    if (compressed)\n    {\n      _outStream->Init((Byte *)_cachedBlock, _h.BlockSize);\n      bool outBufWasWritten;\n      UInt32 outBufWasWrittenSize;\n      HRESULT res = Decompress(_outStream, _cachedBlock, &outBufWasWritten, &outBufWasWrittenSize, packBlockSize, _h.BlockSize);\n      RINOK(res)\n      if (outBufWasWritten)\n        _cachedUnpackBlockSize = outBufWasWrittenSize;\n      else\n        _cachedUnpackBlockSize = (UInt32)_outStream->GetPos();\n    }\n    else\n    {\n      if (packBlockSize > _h.BlockSize)\n        return S_FALSE;\n      RINOK(ReadStream_FALSE(_limitedInStream, _cachedBlock, packBlockSize))\n      _cachedUnpackBlockSize = packBlockSize;\n    }\n    _cachedBlockStartPos = blockOffset;\n    _cachedPackBlockSize = packBlockSize;\n  }\n  if (offsetInBlock + blockSize > _cachedUnpackBlockSize)\n    return S_FALSE;\n  if (blockSize != 0)\n    memcpy(dest, _cachedBlock + offsetInBlock, blockSize);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const CItem &item = _items[allFilesMode ? i : indices[i]];\n    const CNode &node = _nodes[item.Node];\n    totalSize += node.GetSize();\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 totalPackSize;\n  totalSize = totalPackSize = 0;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = totalPackSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    int res;\n   {\n    CMyComPtr<ISequentialOutStream> outStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItem &item = _items[index];\n    const CNode &node = _nodes[item.Node];\n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n    // const Byte *p = _data + item.Offset;\n\n    if (node.IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    const UInt64 unpackSize = node.GetSize();\n    totalSize += unpackSize;\n    UInt64 packSize;\n    if (GetPackSize(index, packSize, false))\n      totalPackSize += packSize;\n\n    if (!testMode && !outStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    res = NExtract::NOperationResult::kDataError;\n    {\n      CMyComPtr<ISequentialInStream> inSeqStream;\n      HRESULT hres = GetStream(index, &inSeqStream);\n      if (hres == S_FALSE || !inSeqStream)\n      {\n        if (hres == E_OUTOFMEMORY)\n          return hres;\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n      }\n      else\n      {\n        RINOK(hres)\n        {\n          hres = copyCoder.Interface()->Code(inSeqStream, outStream, NULL, NULL, lps);\n          if (hres == S_OK)\n          {\n            if (copyCoder->TotalSize == unpackSize)\n              res = NExtract::NOperationResult::kOK;\n          }\n          else if (hres == E_NOTIMPL)\n          {\n            res = NExtract::NOperationResult::kUnsupportedMethod;\n          }\n          else if (hres != S_FALSE)\n          {\n            RINOK(hres)\n          }\n        }\n      }\n    }\n   }\n    RINOK(extractCallback->SetOperationResult(res))\n  }\n  \n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n\n  const CItem &item = _items[index];\n  const CNode &node = _nodes[item.Node];\n\n  if (node.IsDir())\n    return E_FAIL;\n\n  const Byte *p = _inodesData.Data + _nodesPos[item.Node];\n\n  if (node.FileSize == 0 || node.IsLink())\n  {\n    CBufInStream *streamSpec = new CBufInStream;\n    CMyComPtr<IInStream> streamTemp = streamSpec;\n    if (node.IsLink())\n      streamSpec->Init(p + _h.GetSymLinkOffset(), (size_t)node.FileSize);\n    else\n      streamSpec->Init(NULL, 0);\n    *stream = streamTemp.Detach();\n    return S_OK;\n  }\n\n  UInt64 packSize;\n  if (!GetPackSize(index, packSize, true))\n    return S_FALSE;\n\n  _nodeIndex = item.Node;\n\n  size_t cacheSize = _h.BlockSize;\n  if (_cachedBlock.Size() != cacheSize)\n  {\n    ClearCache();\n    _cachedBlock.Alloc(cacheSize);\n  }\n\n  CSquashfsInStream *streamSpec = new CSquashfsInStream;\n  CMyComPtr<IInStream> streamTemp = streamSpec;\n  streamSpec->Handler = this;\n  unsigned cacheSizeLog = 22;\n  if (cacheSizeLog <= _h.BlockSizeLog)\n    cacheSizeLog = _h.BlockSizeLog + 1;\n  if (!streamSpec->Alloc(_h.BlockSizeLog, cacheSizeLog - _h.BlockSizeLog))\n    return E_OUTOFMEMORY;\n  streamSpec->Init(node.FileSize);\n  *stream = streamTemp.Detach();\n\n  return S_OK;\n\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = {\n    4, 'h', 's', 'q', 's',\n    4, 's', 'q', 's', 'h',\n    4, 's', 'h', 's', 'q',\n    4, 'q', 's', 'h', 's' };\n\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\nREGISTER_ARC_I(\n  \"SquashFS\", \"squashfs\", NULL, 0xD2,\n  k_Signature,\n  0,\n  NArcInfoFlags::kMultiSignature,\n  NULL)\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\nREGISTER_ARC_I(\n  \"SquashFS\", \"sfs squashfs\", NULL, 0xD2,\n  k_Signature,\n  0,\n  NArcInfoFlags::kMultiSignature,\n  NULL)\n// **************** 7-Zip ZS Modification End ****************\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/SwfHandler.cpp",
    "content": "﻿// SwfHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/InBuffer.h\"\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/LzmaDecoder.h\"\n#include \"../Compress/ZlibDecoder.h\"\n\n#include \"Common/DummyOutStream.h\"\n\n// #define Z7_SWF_UPDATE\n\n#ifdef Z7_SWF_UPDATE\n\n#include \"../Compress/LzmaEncoder.h\"\n#include \"../Compress/ZlibEncoder.h\"\n\n#include \"Common/HandlerOut.h\"\n \n#endif\n\nusing namespace NWindows;\n\nnamespace NArchive {\n\nstatic const UInt32 kFileSizeMax = (UInt32)1 << 29;\n\nnamespace NSwfc {\n\nstatic const unsigned kHeaderBaseSize = 8;\nstatic const unsigned kHeaderLzmaSize = 17;\n\nstatic const Byte SWF_UNCOMPRESSED = 'F';\nstatic const Byte SWF_COMPRESSED_ZLIB = 'C';\nstatic const Byte SWF_COMPRESSED_LZMA = 'Z';\n\nstatic const Byte SWF_MIN_COMPRESSED_ZLIB_VER = 6;\nstatic const Byte SWF_MIN_COMPRESSED_LZMA_VER = 13;\n\nstatic const Byte kVerLim = 64;\n\nAPI_FUNC_static_IsArc IsArc_Swf(const Byte *p, size_t size)\n{\n  if (size < kHeaderBaseSize)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != SWF_UNCOMPRESSED ||\n      p[1] != 'W' ||\n      p[2] != 'S' ||\n      p[3] >= kVerLim)\n    return k_IsArc_Res_NO;\n  UInt32 uncompressedSize = GetUi32(p + 4);\n  if (uncompressedSize > kFileSizeMax)\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\nAPI_FUNC_static_IsArc IsArc_Swfc(const Byte *p, size_t size)\n{\n  if (size < kHeaderBaseSize + 2 + 1) // 2 + 1 (for zlib check)\n    return k_IsArc_Res_NEED_MORE;\n  if ((p[0] != SWF_COMPRESSED_ZLIB &&\n      p[0] != SWF_COMPRESSED_LZMA) ||\n      p[1] != 'W' ||\n      p[2] != 'S' ||\n      p[3] >= kVerLim)\n    return k_IsArc_Res_NO;\n  UInt32 uncompressedSize = GetUi32(p + 4);\n  if (uncompressedSize > kFileSizeMax)\n    return k_IsArc_Res_NO;\n\n  if (p[0] == SWF_COMPRESSED_ZLIB)\n  {\n    if (!NCompress::NZlib::IsZlib_3bytes(p + 8))\n      return k_IsArc_Res_NO;\n  }\n  else\n  {\n    if (size < kHeaderLzmaSize + 2)\n      return k_IsArc_Res_NEED_MORE;\n    if (p[kHeaderLzmaSize] != 0 ||\n        (p[kHeaderLzmaSize + 1] & 0x80) != 0)\n      return k_IsArc_Res_NO;\n    UInt32 lzmaPackSize = GetUi32(p + 8);\n    UInt32 lzmaProp = p[12];\n    UInt32 lzmaDicSize = GetUi32(p + 13);\n    if (lzmaProp > 5 * 5 * 9 ||\n        lzmaDicSize > ((UInt32)1 << 28) ||\n        lzmaPackSize < 5 ||\n        lzmaPackSize > ((UInt32)1 << 28))\n      return k_IsArc_Res_NO;\n  }\n\n  return k_IsArc_Res_YES;\n}\n}\n\nstruct CItem\n{\n  Byte Buf[kHeaderLzmaSize];\n  unsigned HeaderSize;\n\n  UInt32 GetSize() const { return GetUi32(Buf + 4); }\n  UInt32 GetLzmaPackSize() const { return GetUi32(Buf + 8); }\n  UInt32 GetLzmaDicSize() const { return GetUi32(Buf + 13); }\n\n  bool IsSwf() const { return (Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < kVerLim); }\n  bool IsUncompressed() const { return Buf[0] == SWF_UNCOMPRESSED; }\n  bool IsZlib() const { return Buf[0] == SWF_COMPRESSED_ZLIB; }\n  bool IsLzma() const { return Buf[0] == SWF_COMPRESSED_LZMA; }\n\n  void MakeUncompressed()\n  {\n    Buf[0] = SWF_UNCOMPRESSED;\n    HeaderSize = kHeaderBaseSize;\n  }\n  void MakeZlib()\n  {\n    Buf[0] = SWF_COMPRESSED_ZLIB;\n    if (Buf[3] < SWF_MIN_COMPRESSED_ZLIB_VER)\n      Buf[3] = SWF_MIN_COMPRESSED_ZLIB_VER;\n  }\n  void MakeLzma(UInt32 packSize)\n  {\n    Buf[0] = SWF_COMPRESSED_LZMA;\n    if (Buf[3] < SWF_MIN_COMPRESSED_LZMA_VER)\n      Buf[3] = SWF_MIN_COMPRESSED_LZMA_VER;\n    SetUi32(Buf + 8, packSize)\n    HeaderSize = kHeaderLzmaSize;\n  }\n\n  HRESULT ReadHeader(ISequentialInStream *stream)\n  {\n    HeaderSize = kHeaderBaseSize;\n    return ReadStream_FALSE(stream, Buf, kHeaderBaseSize);\n  }\n  HRESULT WriteHeader(ISequentialOutStream *stream)\n  {\n    return WriteStream(stream, Buf, HeaderSize);\n  }\n};\n\n\nZ7_class_CHandler_final:\n  public IInArchive,\n  public IArchiveOpenSeq,\n #ifdef Z7_SWF_UPDATE\n  public IOutArchive,\n  public ISetProperties,\n #endif\n  public CMyUnknownImp\n{\n #ifdef Z7_SWF_UPDATE\n  Z7_IFACES_IMP_UNK_4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)\n #else\n  Z7_IFACES_IMP_UNK_2(IInArchive, IArchiveOpenSeq)\n #endif\n\n  CItem _item;\n  UInt64 _packSize;\n  bool _packSizeDefined;\n  CMyComPtr<ISequentialInStream> _seqStream;\n  CMyComPtr<IInStream> _stream;\n\n#ifdef Z7_SWF_UPDATE\n  CSingleMethodProps _props;\n  bool _lzmaMode;\n#endif\n\npublic:\n #ifdef Z7_SWF_UPDATE\n  CHandler(): _lzmaMode(false) {}\n #endif\n};\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize,\n  kpidMethod\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break;\n    case kpidIsNotArcType: prop = true; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nstatic void DicSizeToString(char *s, UInt32 val)\n{\n  char c = 0;\n  unsigned i;\n  for (i = 0; i < 32; i++)\n    if (((UInt32)1 << i) == val)\n    {\n      val = i;\n      break;\n    }\n  if (i == 32)\n  {\n    c = 'b';\n    if      ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }\n    else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }\n  }\n  ::ConvertUInt32ToString(val, s);\n  unsigned pos = MyStringLen(s);\n  s[pos++] = c;\n  s[pos] = 0;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidSize: prop = (UInt64)_item.GetSize(); break;\n    case kpidPackSize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break;\n    case kpidMethod:\n    {\n      char s[32];\n      if (_item.IsZlib())\n        MyStringCopy(s, \"zlib\");\n      else\n      {\n        MyStringCopy(s, \"LZMA:\");\n        DicSizeToString(s + 5, _item.GetLzmaDicSize());\n      }\n      prop = s;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))\n{\n  RINOK(OpenSeq(stream))\n  _stream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  RINOK(_item.ReadHeader(stream))\n  if (!_item.IsSwf())\n    return S_FALSE;\n  if (_item.IsLzma())\n  {\n    RINOK(ReadStream_FALSE(stream, _item.Buf + kHeaderBaseSize, kHeaderLzmaSize - kHeaderBaseSize))\n    _item.HeaderSize = kHeaderLzmaSize;\n    _packSize = _item.GetLzmaPackSize();\n    _packSizeDefined = true;\n  }\n  else if (!_item.IsZlib())\n    return S_FALSE;\n  if (_item.GetSize() < _item.HeaderSize)\n    return S_FALSE;\n  _seqStream = stream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _packSize = 0;\n  _packSizeDefined = false;\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_CLASS_IMP_COM_1(\n  CCompressProgressInfoImp,\n  ICompressProgressInfo\n)\n  CMyComPtr<IArchiveOpenCallback> Callback;\npublic:\n  UInt64 Offset;\n  void Init(IArchiveOpenCallback *callback) { Callback = callback; }\n};\n\nZ7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))\n{\n  if (Callback)\n  {\n    const UInt64 files = 0;\n    const UInt64 value = Offset + *inSize;\n    return Callback->SetCompleted(&files, &value);\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  RINOK(extractCallback->SetTotal(_item.GetSize()))\n  Int32 opRes;\n{\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;\n  outStream->SetStream(realOutStream);\n  outStream->Init();\n  // realOutStream.Release();\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  lps->InSize = _item.HeaderSize;\n  lps->OutSize = outStream->GetSize();\n  RINOK(lps->SetCur())\n  \n  CItem item = _item;\n  item.MakeUncompressed();\n  if (_stream)\n    RINOK(InStream_SeekSet(_stream, _item.HeaderSize))\n  NCompress::NZlib::CDecoder *_decoderZlibSpec = NULL;\n  NCompress::NLzma::CDecoder *_decoderLzmaSpec = NULL;\n  CMyComPtr<ICompressCoder> _decoder;\n\n  CMyComPtr<ISequentialInStream> inStream2;\n\n  const UInt64 unpackSize = _item.GetSize() - (UInt32)8;\n  if (_item.IsZlib())\n  {\n    _decoderZlibSpec = new NCompress::NZlib::CDecoder;\n    _decoder = _decoderZlibSpec;\n    inStream2 = _seqStream;\n  }\n  else\n  {\n    /* Some .swf files with lzma contain additional 8 bytes at the end\n       in uncompressed stream.\n       What does that data mean ???\n       We don't decompress these additional 8 bytes */\n    \n    // unpackSize = _item.GetSize();\n    // SetUi32(item.Buf + 4, (UInt32)(unpackSize + 8));\n    CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream;\n    inStream2 = limitedStreamSpec;\n    limitedStreamSpec->SetStream(_seqStream);\n    limitedStreamSpec->Init(_item.GetLzmaPackSize());\n\n    _decoderLzmaSpec = new NCompress::NLzma::CDecoder;\n    _decoder = _decoderLzmaSpec;\n    // _decoderLzmaSpec->FinishStream = true;\n\n    Byte props[5];\n    memcpy(props, _item.Buf + 12, 5);\n    UInt32 dicSize = _item.GetLzmaDicSize();\n    if (dicSize > (UInt32)unpackSize)\n    {\n      dicSize = (UInt32)unpackSize;\n      SetUi32(props + 1, dicSize)\n    }\n    RINOK(_decoderLzmaSpec->SetDecoderProperties2(props, 5))\n  }\n  RINOK(item.WriteHeader(outStream))\n  const HRESULT result = _decoder->Code(inStream2, outStream, NULL, &unpackSize, lps);\n  opRes = NExtract::NOperationResult::kDataError;\n  if (result == S_OK)\n  {\n    if (item.GetSize() == outStream->GetSize())\n    {\n      if (_item.IsZlib())\n      {\n        _packSizeDefined = true;\n        _packSize = _decoderZlibSpec->GetInputProcessedSize();\n        opRes = NExtract::NOperationResult::kOK;\n      }\n      else\n      {\n        // if (_decoderLzmaSpec->GetInputProcessedSize() == _packSize)\n          opRes = NExtract::NOperationResult::kOK;\n      }\n    }\n  }\n  else if (result != S_FALSE)\n    return result;\n\n  // outStream.Release();\n }\n  return extractCallback->SetOperationResult(opRes);\n  COM_TRY_END\n}\n\n\n#ifdef Z7_SWF_UPDATE\n\nstatic HRESULT UpdateArchive(ISequentialOutStream *outStream, UInt64 size,\n    bool lzmaMode, const CSingleMethodProps &props,\n    IArchiveUpdateCallback *updateCallback)\n{\n  UInt64 complexity = 0;\n  RINOK(updateCallback->SetTotal(size))\n  RINOK(updateCallback->SetCompleted(&complexity))\n\n  CMyComPtr<ISequentialInStream> fileInStream;\n  RINOK(updateCallback->GetStream(0, &fileInStream))\n\n  /*\n  CDummyOutStream *outStreamSpec = new CDummyOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n  outStreamSpec->SetStream(realOutStream);\n  outStreamSpec->Init();\n  realOutStream.Release();\n  */\n\n  CItem item;\n  const HRESULT res = item.ReadHeader(fileInStream);\n  if (res == S_FALSE)\n    return E_INVALIDARG;\n  RINOK(res)\n  if (!item.IsSwf() || !item.IsUncompressed() || size != item.GetSize())\n    return E_INVALIDARG;\n\n  NCompress::NZlib::CEncoder *encoderZlibSpec = NULL;\n  NCompress::NLzma::CEncoder *encoderLzmaSpec = NULL;\n  CMyComPtr<ICompressCoder> encoder;\n  CMyComPtr<IOutStream> outSeekStream;\n  if (lzmaMode)\n  {\n    outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream);\n    if (!outSeekStream)\n      return E_NOTIMPL;\n    encoderLzmaSpec = new NCompress::NLzma::CEncoder;\n    encoder = encoderLzmaSpec;\n    RINOK(props.SetCoderProps(encoderLzmaSpec, &size))\n    item.MakeLzma((UInt32)0xFFFFFFFF);\n    CBufPtrSeqOutStream *propStreamSpec = new CBufPtrSeqOutStream;\n    CMyComPtr<ISequentialOutStream> propStream = propStreamSpec;\n    propStreamSpec->Init(item.Buf + 12, 5);\n    RINOK(encoderLzmaSpec->WriteCoderProperties(propStream))\n  }\n  else\n  {\n    encoderZlibSpec = new NCompress::NZlib::CEncoder;\n    encoder = encoderZlibSpec;\n    encoderZlibSpec->Create();\n    RINOK(props.SetCoderProps(encoderZlibSpec->DeflateEncoderSpec, NULL))\n    item.MakeZlib();\n  }\n  RINOK(item.WriteHeader(outStream))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(updateCallback, true);\n  \n  RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, lps))\n  UInt64 inputProcessed;\n  if (lzmaMode)\n  {\n    UInt64 curPos = 0;\n    RINOK(outSeekStream->Seek(0, STREAM_SEEK_CUR, &curPos))\n    const UInt64 packSize = curPos - kHeaderLzmaSize;\n    if (packSize > (UInt32)0xFFFFFFFF)\n      return E_INVALIDARG;\n    item.MakeLzma((UInt32)packSize);\n    RINOK(outSeekStream->Seek(0, STREAM_SEEK_SET, NULL))\n    RINOK(item.WriteHeader(outStream))\n    inputProcessed = encoderLzmaSpec->GetInputProcessedSize();\n  }\n  else\n  {\n    inputProcessed = encoderZlibSpec->GetInputProcessedSize();\n  }\n  if (inputProcessed + kHeaderBaseSize != size)\n    return E_INVALIDARG;\n  return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);\n}\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))\n{\n  *timeType = NFileTimeType::kUnix;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))\n\n  if (IntToBool(newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))\n      if (prop.vt == VT_BOOL)\n      {\n        if (prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n      }\n      else if (prop.vt != VT_EMPTY)\n        return E_INVALIDARG;\n    }\n  }\n\n  if (IntToBool(newData))\n  {\n    UInt64 size;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop))\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      size = prop.uhVal.QuadPart;\n    }\n    return UpdateArchive(outStream, size, _lzmaMode, _props, updateCallback);\n  }\n    \n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  if (!_seqStream)\n    return E_NOTIMPL;\n\n  if (_stream)\n  {\n    RINOK(InStream_SeekToBegin(_stream))\n  }\n  else\n    _item.WriteHeader(outStream);\n  return NCompress::CopyStream(_seqStream, outStream, NULL);\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  _lzmaMode = false;\n  RINOK(_props.SetProperties(names, values, numProps))\n  const AString &m = _props.MethodName;\n  if (m.IsEqualTo_Ascii_NoCase(\"lzma\"))\n  {\n    return E_NOTIMPL;\n    // _lzmaMode = true;\n  }\n  else if (m.IsEqualTo_Ascii_NoCase(\"Deflate\") || m.IsEmpty())\n    _lzmaMode = false;\n  else\n    return E_INVALIDARG;\n  return S_OK;\n}\n\n#endif\n\n\nstatic const Byte k_Signature[] = {\n    3, 'C', 'W', 'S',\n    3, 'Z', 'W', 'S' };\n\nREGISTER_ARC_I(\n  \"SWFc\", \"swf\", \"~.swf\", 0xD8,\n  k_Signature,\n  0,\n  NArcInfoFlags::kMultiSignature,\n  IsArc_Swfc)\n\n}\n\nnamespace NSwf {\n\nstatic const unsigned kNumTagsMax = 1 << 23;\n\nstruct CTag\n{\n  UInt32 Type;\n  CByteBuffer Buf;\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IArchiveOpenSeq\n)\n  CObjectVector<CTag> _tags;\n  NSwfc::CItem _item;\n  UInt64 _phySize;\n\n  HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback);\n  HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback);\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidComment,\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _phySize; break;\n    case kpidIsNotArcType: prop = true; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _tags.Size();\n  return S_OK;\n}\n\nstatic const char * const g_TagDesc[92] =\n{\n    \"End\"\n  , \"ShowFrame\"\n  , \"DefineShape\"\n  , NULL\n  , \"PlaceObject\"\n  , \"RemoveObject\"\n  , \"DefineBits\"\n  , \"DefineButton\"\n  , \"JPEGTables\"\n  , \"SetBackgroundColor\"\n  , \"DefineFont\"\n  , \"DefineText\"\n  , \"DoAction\"\n  , \"DefineFontInfo\"\n  , \"DefineSound\"\n  , \"StartSound\"\n  , NULL\n  , \"DefineButtonSound\"\n  , \"SoundStreamHead\"\n  , \"SoundStreamBlock\"\n  , \"DefineBitsLossless\"\n  , \"DefineBitsJPEG2\"\n  , \"DefineShape2\"\n  , \"DefineButtonCxform\"\n  , \"Protect\"\n  , NULL\n  , \"PlaceObject2\"\n  , NULL\n  , \"RemoveObject2\"\n  , NULL\n  , NULL\n  , NULL\n  , \"DefineShape3\"\n  , \"DefineText2\"\n  , \"DefineButton2\"\n  , \"DefineBitsJPEG3\"\n  , \"DefineBitsLossless2\"\n  , \"DefineEditText\"\n  , NULL\n  , \"DefineSprite\"\n  , NULL\n  , \"41\"\n  , NULL\n  , \"FrameLabel\"\n  , NULL\n  , \"SoundStreamHead2\"\n  , \"DefineMorphShape\"\n  , NULL\n  , \"DefineFont2\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"ExportAssets\"\n  , \"ImportAssets\"\n  , \"EnableDebugger\"\n  , \"DoInitAction\"\n  , \"DefineVideoStream\"\n  , \"VideoFrame\"\n  , \"DefineFontInfo2\"\n  , NULL\n  , \"EnableDebugger2\"\n  , \"ScriptLimits\"\n  , \"SetTabIndex\"\n  , NULL\n  , NULL\n  , \"FileAttributes\"\n  , \"PlaceObject3\"\n  , \"ImportAssets2\"\n  , NULL\n  , \"DefineFontAlignZones\"\n  , \"CSMTextSettings\"\n  , \"DefineFont3\"\n  , \"SymbolClass\"\n  , \"Metadata\"\n  , \"DefineScalingGrid\"\n  , NULL\n  , NULL\n  , NULL\n  , \"DoABC\"\n  , \"DefineShape4\"\n  , \"DefineMorphShape2\"\n  , NULL\n  , \"DefineSceneAndFrameLabelData\"\n  , \"DefineBinaryData\"\n  , \"DefineFontName\"\n  , \"StartSound2\"\n  , \"DefineBitsJPEG4\"\n  , \"DefineFont4\"\n};\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  const CTag &tag = _tags[index];\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      char s[32];\n      ConvertUInt32ToString(index, s);\n      size_t i = strlen(s);\n      s[i++] = '.';\n      ConvertUInt32ToString(tag.Type, s + i);\n      prop = s;\n      break;\n    }\n    case kpidSize:\n    case kpidPackSize:\n      prop = (UInt64)tag.Buf.Size(); break;\n    case kpidComment:\n      TYPE_TO_PROP(g_TagDesc, tag.Type, prop);\n      break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  return OpenSeq2(stream, callback);\n}\n\nstatic UInt16 Read16(CInBuffer &stream)\n{\n  UInt32 res = 0;\n  for (unsigned i = 0; i < 2; i++)\n  {\n    Byte b;\n    if (!stream.ReadByte(b))\n      throw 1;\n    res |= (UInt32)b << (i * 8);\n  }\n  return (UInt16)res;\n}\n\nstatic UInt32 Read32(CInBuffer &stream)\n{\n  UInt32 res = 0;\n  for (unsigned i = 0; i < 4; i++)\n  {\n    Byte b;\n    if (!stream.ReadByte(b))\n      throw 1;\n    res |= (UInt32)b << (i * 8);\n  }\n  return res;\n}\n\nstruct CBitReader\n{\n  CInBuffer *stream;\n  unsigned NumBits;\n  Byte Val;\n\n  CBitReader(): NumBits(0), Val(0) {}\n\n  UInt32 ReadBits(unsigned numBits);\n};\n\nUInt32 CBitReader::ReadBits(unsigned numBits)\n{\n  UInt32 res = 0;\n  while (numBits > 0)\n  {\n    if (NumBits == 0)\n    {\n      Val = stream->ReadByte();\n      NumBits = 8;\n    }\n    if (numBits <= NumBits)\n    {\n      res <<= numBits;\n      NumBits -= numBits;\n      res |= (Val >> NumBits);\n      Val = (Byte)(Val & (((unsigned)1 << NumBits) - 1));\n      break;\n    }\n    else\n    {\n      res <<= NumBits;\n      res |= Val;\n      numBits -= NumBits;\n      NumBits = 0;\n    }\n  }\n  return res;\n}\n\nHRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback)\n{\n  RINOK(_item.ReadHeader(stream))\n  if (!_item.IsSwf() || !_item.IsUncompressed())\n    return S_FALSE;\n  const UInt32 uncompressedSize = _item.GetSize();\n  if (uncompressedSize > kFileSizeMax)\n    return S_FALSE;\n\n  \n  CInBuffer s;\n  if (!s.Create(1 << 20))\n    return E_OUTOFMEMORY;\n  s.SetStream(stream);\n  s.Init();\n  {\n    CBitReader br;\n    br.stream = &s;\n    const unsigned numBits = br.ReadBits(5);\n    /* UInt32 xMin = */ br.ReadBits(numBits);\n    /* UInt32 xMax = */ br.ReadBits(numBits);\n    /* UInt32 yMin = */ br.ReadBits(numBits);\n    /* UInt32 yMax = */ br.ReadBits(numBits);\n  }\n  /* UInt32 frameDelay = */ Read16(s);\n  /* UInt32 numFrames =  */ Read16(s);\n\n  _tags.Clear();\n  UInt64 offsetPrev = 0;\n  for (;;)\n  {\n    const UInt32 pair = Read16(s);\n    const UInt32 type = pair >> 6;\n    UInt32 length = pair & 0x3F;\n    if (length == 0x3F)\n      length = Read32(s);\n    if (type == 0)\n      break;\n    const UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderBaseSize + length;\n    if (offset > uncompressedSize || _tags.Size() >= kNumTagsMax)\n      return S_FALSE;\n    CTag &tag = _tags.AddNew();\n    tag.Type = type;\n    tag.Buf.Alloc(length);\n    if (s.ReadBytes(tag.Buf, length) != length)\n      return S_FALSE;\n    if (callback && offset >= offsetPrev + (1 << 20))\n    {\n      const UInt64 numItems = _tags.Size();\n      RINOK(callback->SetCompleted(&numItems, &offset))\n      offsetPrev = offset;\n    }\n  }\n  _phySize = s.GetProcessedSize() + NSwfc::kHeaderBaseSize;\n  if (_phySize != uncompressedSize)\n  {\n    // do we need to support files extracted from SFW-LZMA with additional 8 bytes?\n    return S_FALSE;\n  }\n  return S_OK;\n}\n\nHRESULT CHandler::OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback)\n{\n  HRESULT res;\n  try { res = OpenSeq3(stream, callback); }\n  catch(...) { res = S_FALSE; }\n  return res;\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  return OpenSeq2(stream, NULL);\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _phySize = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _tags.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _tags[allFilesMode ? i : indices[i]].Buf.Size();\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  totalSize = 0;\n\n  for (i = 0; i < numItems; i++)\n  {\n    lps->InSize = lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CByteBuffer &buf = _tags[index].Buf;\n    totalSize += buf.Size();\n\n    CMyComPtr<ISequentialOutStream> outStream;\n    RINOK(extractCallback->GetStream(index, &outStream, askMode))\n    if (!testMode && !outStream)\n      continue;\n      \n    RINOK(extractCallback->PrepareOperation(askMode))\n    if (outStream)\n      RINOK(WriteStream(outStream, buf, buf.Size()))\n    outStream.Release();\n    RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = { 'F', 'W', 'S' };\n\nREGISTER_ARC_I(\n  \"SWF\", \"swf\", NULL, 0xD7,\n  k_Signature,\n  0,\n  NArcInfoFlags::kKeepName,\n  NSwfc::IsArc_Swf)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarHandler.cpp",
    "content": "﻿// TarHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/MethodProps.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"TarHandler.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NTar {\n\n// 21.02: we use UTF8 code page by default, even if some files show error\n// before 21.02 : CP_OEMCP;\n// static const UINT k_DefaultCodePage = CP_UTF8;\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidPosixAttrib,\n#if 0\n  kpidAttrib,\n#endif\n  kpidUser,\n  kpidGroup,\n  kpidUserId,\n  kpidGroupId,\n  kpidSymLink,\n  kpidHardLink,\n  kpidCharacts,\n  kpidComment\n  , kpidDeviceMajor\n  , kpidDeviceMinor\n  // , kpidDevice\n  // , kpidHeadersSize // for debug\n  // , kpidOffset // for debug\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidHeadersSize,\n  kpidCodePage,\n  kpidCharacts,\n  kpidComment\n};\n\nstatic const char * const k_Characts_Prefix = \"PREFIX\";\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize:     if (_arc._phySize_Defined) prop = _arc._phySize; break;\n    case kpidHeadersSize: if (_arc._phySize_Defined) prop = _arc._headersSize; break;\n    case kpidErrorFlags:\n    {\n      UInt32 flags = 0;\n      if (!_isArc)\n        flags |= kpv_ErrorFlags_IsNotArc;\n      else switch ((int)_arc._error)\n      {\n        case k_ErrorType_UnexpectedEnd: flags = kpv_ErrorFlags_UnexpectedEnd; break;\n        case k_ErrorType_Corrupted: flags = kpv_ErrorFlags_HeadersError; break;\n        // case k_ErrorType_OK: break;\n        // case k_ErrorType_Warning: break;\n        // case k_ErrorType_OK:\n        default: break;\n      }\n      if (flags != 0)\n        prop = flags;\n      break;\n    }\n\n    case kpidWarningFlags:\n    {\n      if (_arc._is_Warning)\n        prop = kpv_ErrorFlags_HeadersError;\n      break;\n    }\n\n    case kpidCodePage:\n    {\n      char sz[16];\n      const char *name = NULL;\n      switch (_openCodePage)\n      {\n        case CP_OEMCP: name = \"OEM\"; break;\n        case CP_UTF8: name = \"UTF-8\"; break;\n        default: break;\n      }\n      if (!name)\n      {\n        ConvertUInt32ToString(_openCodePage, sz);\n        name = sz;\n      }\n      prop = name;\n      break;\n    }\n\n    case kpidCharacts:\n    {\n      AString s;\n      if (_arc._are_Gnu) s.Add_OptSpaced(\"GNU\");\n      if (_arc._are_Posix) s.Add_OptSpaced(\"POSIX\");\n      if (_arc._are_Pax_Items) s.Add_OptSpaced(\"PAX_ITEM\");\n      if (_arc._pathPrefix_WasUsed) s.Add_OptSpaced(k_Characts_Prefix);\n      if (_arc._are_LongName) s.Add_OptSpaced(\"LongName\");\n      if (_arc._are_LongLink) s.Add_OptSpaced(\"LongLink\");\n      if (_arc._are_Pax) s.Add_OptSpaced(\"PAX\");\n      if (_arc._are_pax_path) s.Add_OptSpaced(\"path\");\n      if (_arc._are_pax_link) s.Add_OptSpaced(\"linkpath\");\n      if (_arc._are_mtime) s.Add_OptSpaced(\"mtime\");\n      if (_arc._are_atime) s.Add_OptSpaced(\"atime\");\n      if (_arc._are_ctime) s.Add_OptSpaced(\"ctime\");\n      if (_arc._are_SCHILY_fflags) s.Add_OptSpaced(\"SCHILY.fflags\");\n      if (_arc._is_PaxGlobal_Error) s.Add_OptSpaced(\"PAX_GLOBAL_ERROR\");\n      s.Add_OptSpaced(_encodingCharacts.GetCharactsString());\n      prop = s;\n      break;\n    }\n\n    case kpidComment:\n    {\n      if (_arc.PaxGlobal_Defined)\n      {\n        AString s;\n        _arc.PaxGlobal.Print_To_String(s);\n        if (!s.IsEmpty())\n          prop = s;\n      }\n      break;\n    }\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n\nvoid CEncodingCharacts::Check(const AString &s)\n{\n  IsAscii = s.IsAscii();\n  if (!IsAscii)\n  {\n    /*\n    {\n      Oem_Checked = true;\n      UString u;\n      MultiByteToUnicodeString2(u, s, CP_OEMCP);\n      Oem_Ok = (u.Find((wchar_t)0xfffd) <= 0);\n    }\n    Utf_Checked = true;\n    */\n    UtfCheck.Check_AString(s);\n  }\n}\n\n\nAString CEncodingCharacts::GetCharactsString() const\n{\n  AString s;\n  if (IsAscii)\n  {\n    s += \"ASCII\";\n  }\n  /*\n  if (Oem_Checked)\n  {\n    s.Add_Space_if_NotEmpty();\n    s += (Oem_Ok ? \"oem-ok\" : \"oem-error\");\n  }\n  if (Utf_Checked)\n  */\n  else\n  {\n    s.Add_Space_if_NotEmpty();\n    s += (UtfCheck.IsOK() ? \"UTF8\" : \"UTF8-ERROR\"); // \"UTF8-error\"\n    {\n      AString s2;\n      UtfCheck.PrintStatus(s2);\n      s.Add_Space_if_NotEmpty();\n      s += s2;\n    }\n  }\n  return s;\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *callback)\n{\n  UInt64 endPos;\n  {\n    RINOK(InStream_AtBegin_GetSize(stream, endPos))\n  }\n  \n  _arc._phySize_Defined = true;\n  \n  // bool utf8_OK = true;\n\n  _arc.SeqStream = stream;\n  _arc.InStream = stream;\n  _arc.OpenCallback = callback;\n\n  CItemEx item;\n  for (;;)\n  {\n    _arc.NumFiles = _items.Size();\n    RINOK(_arc.ReadItem(item))\n    if (!_arc.filled)\n      break;\n\n    _isArc = true;\n\n    /*\n    if (!_forceCodePage)\n    {\n      if (utf8_OK) utf8_OK = CheckUTF8(item.Name, item.NameCouldBeReduced);\n      if (utf8_OK) utf8_OK = CheckUTF8(item.LinkName, item.LinkNameCouldBeReduced);\n      if (utf8_OK) utf8_OK = CheckUTF8(item.User);\n      if (utf8_OK) utf8_OK = CheckUTF8(item.Group);\n    }\n    */\n \n    item.EncodingCharacts.Check(item.Name);\n    _encodingCharacts.Update(item.EncodingCharacts);\n\n    _items.Add(item);\n\n    RINOK(stream->Seek((Int64)item.Get_PackSize_Aligned(), STREAM_SEEK_CUR, &_arc._phySize))\n    if (_arc._phySize > endPos)\n    {\n      _arc._error = k_ErrorType_UnexpectedEnd;\n      break;\n    }\n    /*\n    if (_phySize == endPos)\n    {\n      _errorMessage = \"There are no trailing zero-filled records\";\n      break;\n    }\n    */\n    /*\n    if (callback)\n    {\n      if (_items.Size() == 1)\n      {\n        RINOK(callback->SetTotal(NULL, &endPos));\n      }\n      if ((_items.Size() & 0x3FF) == 0)\n      {\n        const UInt64 numFiles = _items.Size();\n        RINOK(callback->SetCompleted(&numFiles, &_phySize));\n      }\n    }\n    */\n  }\n\n  /*\n  if (!_forceCodePage)\n  {\n    if (!utf8_OK)\n      _curCodePage = k_DefaultCodePage;\n  }\n  */\n  _openCodePage = _curCodePage;\n\n  if (_items.Size() == 0)\n  {\n    if (_arc._error != k_ErrorType_OK)\n    {\n      _isArc = false;\n      return S_FALSE;\n    }\n    if (!callback)\n      return S_FALSE;\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IArchiveOpenVolumeCallback,\n        openVolumeCallback, callback)\n    if (!openVolumeCallback)\n      return S_FALSE;\n    NCOM::CPropVariant prop;\n    if (openVolumeCallback->GetProperty(kpidName, &prop) != S_OK)\n      return S_FALSE;\n    if (prop.vt != VT_BSTR)\n      return S_FALSE;\n    unsigned len = MyStringLen(prop.bstrVal);\n    if (len < 4 || MyStringCompareNoCase(prop.bstrVal + len - 4, L\".tar\") != 0)\n      return S_FALSE;\n  }\n\n  _isArc = true;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *openArchiveCallback))\n{\n  COM_TRY_BEGIN\n  // for (int i = 0; i < 10; i++) // for debug\n  {\n    Close();\n    RINOK(Open2(stream, openArchiveCallback))\n    _stream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _seqStream = stream;\n  _isArc = true;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _isArc = false;\n\n  _arc.Clear();\n\n  _curIndex = 0;\n  _latestIsRead = false;\n  _encodingCharacts.Clear();\n  _items.Clear();\n  _seqStream.Release();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = (_stream ? _items.Size() : (UInt32)(Int32)-1);\n  return S_OK;\n}\n\nCHandler::CHandler()\n{\n  // copyCoder = new NCompress::CCopyCoder();\n  // copyCoder = copyCoder;\n  _openCodePage = CP_UTF8;\n  Init();\n}\n\nHRESULT CHandler::SkipTo(UInt32 index)\n{\n  while (_curIndex < index || !_latestIsRead)\n  {\n    if (_latestIsRead)\n    {\n      const UInt64 packSize = _latestItem.Get_PackSize_Aligned();\n      RINOK(copyCoder.Interface()->Code(_seqStream, NULL, &packSize, &packSize, NULL))\n      _arc._phySize += copyCoder->TotalSize;\n      if (copyCoder->TotalSize != packSize)\n      {\n        _arc._error = k_ErrorType_UnexpectedEnd;\n        return S_FALSE;\n      }\n      _latestIsRead = false;\n      _curIndex++;\n    }\n    else\n    {\n      _arc.SeqStream = _seqStream;\n      _arc.InStream = NULL;\n      RINOK(_arc.ReadItem(_latestItem))\n      if (!_arc.filled)\n      {\n        _arc._phySize_Defined = true;\n        return E_INVALIDARG;\n      }\n      _latestIsRead = true;\n    }\n  }\n  return S_OK;\n}\n\nvoid CHandler::TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant &prop, bool toOs) const\n{\n  UString dest;\n  if (_curCodePage == CP_UTF8)\n    ConvertUTF8ToUnicode(s, dest);\n  else\n    MultiByteToUnicodeString2(dest, s, _curCodePage);\n  if (toOs)\n    NItemName::ReplaceToOsSlashes_Remove_TailSlash(dest,\n        true); // useBackslashReplacement\n  prop = dest;\n}\n\n\n// CPaxTime is defined (NumDigits >= 0)\nstatic void PaxTimeToProp(const CPaxTime &pt, NWindows::NCOM::CPropVariant &prop)\n{\n  UInt64 v;\n  if (!NTime::UnixTime64_To_FileTime64(pt.Sec, v))\n    return;\n  if (pt.Ns != 0)\n    v += pt.Ns / 100;\n  FILETIME ft;\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n  prop.SetAsTimeFrom_FT_Prec_Ns100(ft,\n      k_PropVar_TimePrec_Base + (unsigned)pt.NumDigits, pt.Ns % 100);\n}\n\n\nstatic void AddSpecCharToString(const char c, AString &s)\n{\n  if ((Byte)c <= 0x20 || (Byte)c > 127)\n  {\n    s.Add_Char('[');\n    s.Add_Char(GET_HEX_CHAR_LOWER((Byte)c >> 4));\n    s.Add_Char(GET_HEX_CHAR_LOWER(c & 15));\n    s.Add_Char(']');\n  }\n  else\n    s.Add_Char(c);\n}\n\nstatic void AddSpecUInt64(AString &s, const char *name, UInt64 v)\n{\n  if (v != 0)\n  {\n    s.Add_OptSpaced(name);\n    if (v > 1)\n    {\n      s.Add_Colon();\n      s.Add_UInt64(v);\n    }\n  }\n}\n\nstatic void AddSpecBools(AString &s, const char *name, bool b1, bool b2)\n{\n  if (b1)\n  {\n    s.Add_OptSpaced(name);\n    if (b2)\n      s.Add_Char('*');\n  }\n}\n\n\n#if 0\nstatic bool Parse_Attrib_from_SCHILY_fflags(const AString &s, UInt32 &attribRes)\n{\n  UInt32 attrib = 0;\n  attribRes = attrib;\n  unsigned pos = 0;\n  while (pos < s.Len())\n  {\n    int pos2 = s.Find(',', pos);\n    if (pos2 < 0)\n      pos2 = (int)s.Len();\n    const AString str = s.Mid(pos, (unsigned)pos2 - pos);\n          if (str.IsEqualTo(\"hidden\"))  attrib |= FILE_ATTRIBUTE_HIDDEN;\n    else  if (str.IsEqualTo(\"rdonly\"))  attrib |= FILE_ATTRIBUTE_READONLY;\n    else  if (str.IsEqualTo(\"system\"))  attrib |= FILE_ATTRIBUTE_SYSTEM;\n    else\n      return false;\n    pos = (unsigned)pos2 + 1;\n  }\n  attribRes = attrib;\n  return true;\n}\n#endif\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CItemEx *item;\n  if (_stream)\n    item = &_items[index];\n  else\n  {\n    if (index < _curIndex)\n      return E_INVALIDARG;\n    else\n    {\n      RINOK(SkipTo(index))\n      item = &_latestItem;\n    }\n  }\n\n  switch (propID)\n  {\n    case kpidPath: TarStringToUnicode(item->Name, prop, true); break;\n    case kpidIsDir: prop = item->IsDir(); break;\n    case kpidSize: prop = item->Get_UnpackSize(); break;\n    case kpidPackSize: prop = item->Get_PackSize_Aligned(); break;\n    case kpidMTime:\n    {\n      /*\n      // for debug:\n      PropVariant_SetFrom_UnixTime(prop, 1 << 30);\n      prop.wReserved1 = k_PropVar_TimePrec_Base + 1;\n      prop.wReserved2 = 12;\n      break;\n      */\n\n      if (item->PaxTimes.MTime.IsDefined())\n        PaxTimeToProp(item->PaxTimes.MTime, prop);\n      else\n      // if (item->MTime != 0)\n      {\n        // we allow (item->MTime == 0)\n        FILETIME ft;\n        if (NTime::UnixTime64_To_FileTime(item->MTime, ft))\n        {\n          unsigned prec = k_PropVar_TimePrec_Unix;\n          if (item->MTime_IsBin)\n          {\n            /* we report here that it's Int64-UnixTime\n               instead of basic UInt32-UnixTime range */\n            prec = k_PropVar_TimePrec_Base;\n          }\n          prop.SetAsTimeFrom_FT_Prec(ft, prec);\n        }\n      }\n      break;\n    }\n    case kpidATime:\n      if (item->PaxTimes.ATime.IsDefined())\n        PaxTimeToProp(item->PaxTimes.ATime, prop);\n      break;\n    case kpidCTime:\n      if (item->PaxTimes.CTime.IsDefined())\n        PaxTimeToProp(item->PaxTimes.CTime, prop);\n      break;\n    case kpidPosixAttrib: prop = item->Get_Combined_Mode(); break;\n\n    // kpidAttrib has priority over kpidPosixAttrib in 7-Zip.\n    // but if we want kpidPosixAttrib priority for TAR, we disable kpidAttrib.\n#if 0\n    case kpidAttrib:\n    {\n      if (!item->SCHILY_fflags.IsEmpty())\n      {\n        UInt32 attrib = 0;\n        if (Parse_Attrib_from_SCHILY_fflags(item->SCHILY_fflags, attrib))\n        {\n          if (attrib != 0)\n          {\n            if (item->IsDir())\n              attrib |= FILE_ATTRIBUTE_DIRECTORY;\n            attrib |= ((UInt32)item->Get_Combined_Mode() << 16) | 0x8000; // FILE_ATTRIBUTE_UNIX_EXTENSION;\n            prop = attrib;\n          }\n        }\n      }\n      break;\n    }\n#endif\n      \n    case kpidUser:\n      if (!item->User.IsEmpty())\n        TarStringToUnicode(item->User, prop);\n      break;\n    case kpidGroup:\n      if (!item->Group.IsEmpty())\n        TarStringToUnicode(item->Group, prop);\n      break;\n\n    case kpidUserId:\n      // if (item->UID != 0)\n        prop = (UInt32)item->UID;\n      break;\n    case kpidGroupId:\n      // if (item->GID != 0)\n        prop = (UInt32)item->GID;\n      break;\n\n    case kpidDeviceMajor:\n      if (item->DeviceMajor_Defined)\n      // if (item->DeviceMajor != 0)\n        prop = (UInt32)item->DeviceMajor;\n      break;\n\n    case kpidDeviceMinor:\n      if (item->DeviceMinor_Defined)\n      // if (item->DeviceMinor != 0)\n        prop = (UInt32)item->DeviceMinor;\n      break;\n    /*\n    case kpidDevice:\n      if (item->DeviceMajor_Defined)\n      if (item->DeviceMinor_Defined)\n        prop = (UInt64)MY_dev_makedev(item->DeviceMajor, item->DeviceMinor);\n      break;\n    */\n\n    case kpidSymLink:\n      if (item->Is_SymLink())\n        if (!item->LinkName.IsEmpty())\n          TarStringToUnicode(item->LinkName, prop);\n      break;\n    case kpidHardLink:\n      if (item->Is_HardLink())\n        if (!item->LinkName.IsEmpty())\n          TarStringToUnicode(item->LinkName, prop);\n      break;\n\n    case kpidCharacts:\n    {\n      AString s;\n      {\n        s.Add_Space_if_NotEmpty();\n        AddSpecCharToString(item->LinkFlag, s);\n      }\n      if (item->IsMagic_GNU())\n        s.Add_OptSpaced(\"GNU\");\n      else if (item->IsMagic_Posix_ustar_00())\n        s.Add_OptSpaced(\"POSIX\");\n      else\n      {\n        s.Add_Space_if_NotEmpty();\n        for (unsigned i = 0; i < sizeof(item->Magic); i++)\n          AddSpecCharToString(item->Magic[i], s);\n      }\n\n      if (item->IsSignedChecksum)\n        s.Add_OptSpaced(\"SignedChecksum\");\n\n      if (item->Prefix_WasUsed)\n        s.Add_OptSpaced(k_Characts_Prefix);\n\n      s.Add_OptSpaced(item->EncodingCharacts.GetCharactsString());\n\n      // AddSpecUInt64(s, \"LongName\", item->Num_LongName_Records);\n      // AddSpecUInt64(s, \"LongLink\", item->Num_LongLink_Records);\n      AddSpecBools(s, \"LongName\", item->LongName_WasUsed, item->LongName_WasUsed_2);\n      AddSpecBools(s, \"LongLink\", item->LongLink_WasUsed, item->LongLink_WasUsed_2);\n\n      if (item->MTime_IsBin)\n        s.Add_OptSpaced(\"bin_mtime\");\n      if (item->PackSize_IsBin)\n        s.Add_OptSpaced(\"bin_psize\");\n      if (item->Size_IsBin)\n        s.Add_OptSpaced(\"bin_size\");\n      \n      AddSpecUInt64(s, \"PAX\", item->Num_Pax_Records);\n\n      if (item->PaxTimes.MTime.IsDefined()) s.Add_OptSpaced(\"mtime\");\n      if (item->PaxTimes.ATime.IsDefined()) s.Add_OptSpaced(\"atime\");\n      if (item->PaxTimes.CTime.IsDefined()) s.Add_OptSpaced(\"ctime\");\n\n      if (item->pax_path_WasUsed)\n        s.Add_OptSpaced(\"pax_path\");\n      if (item->pax_link_WasUsed)\n        s.Add_OptSpaced(\"pax_linkpath\");\n      if (item->pax_size_WasUsed)\n        s.Add_OptSpaced(\"pax_size\");\n      if (!item->SCHILY_fflags.IsEmpty())\n      {\n        s.Add_OptSpaced(\"SCHILY.fflags=\");\n        s += item->SCHILY_fflags;\n      }\n      if (item->Is_Sparse())\n        s.Add_OptSpaced(\"SPARSE\");\n      if (item->IsThereWarning())\n        s.Add_OptSpaced(\"WARNING\");\n      if (item->HeaderError)\n        s.Add_OptSpaced(\"ERROR\");\n      if (item->Method_Error)\n        s.Add_OptSpaced(\"METHOD_ERROR\");\n      if (item->Pax_Error)\n        s.Add_OptSpaced(\"PAX_error\");\n      if (!item->PaxExtra.RawLines.IsEmpty())\n        s.Add_OptSpaced(\"PAX_unsupported_line\");\n      if (item->Pax_Overflow)\n        s.Add_OptSpaced(\"PAX_overflow\");\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n    case kpidComment:\n    {\n      AString s;\n      item->PaxExtra.Print_To_String(s);\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n    // case kpidHeadersSize: prop = item->HeaderSize; break; // for debug\n    // case kpidOffset: prop = item->HeaderPos; break; // for debug\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  ISequentialInStream *stream = _seqStream;\n  const bool seqMode = (_stream == NULL);\n  if (!seqMode)\n    stream = _stream;\n\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (_stream && numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _items[allFilesMode ? i : indices[i]].Get_UnpackSize();\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 totalPackSize;\n  totalSize = totalPackSize = 0;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n  inStream->SetStream(stream);\n  CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStreamSpec;\n\n  for (i = 0; ; i++)\n  {\n    lps->InSize = totalPackSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems && !seqMode)\n      break;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CItemEx *item;\n    if (seqMode)\n    {\n      const HRESULT res = SkipTo(index);\n      if (res == E_INVALIDARG)\n        break;\n      RINOK(res)\n      item = &_latestItem;\n    }\n    else\n      item = &_items[index];\n\n    Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n    const UInt64 unpackSize = item->Get_UnpackSize();\n    totalSize += unpackSize;\n    totalPackSize += item->Get_PackSize_Aligned();\n    if (item->IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      // realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    bool skipMode = false;\n    if (!testMode && !realOutStream)\n    {\n      if (!seqMode)\n      {\n        /*\n        // GetStream() creates link.\n        // so we can show extracting info in GetStream() instead\n        if (item->Is_HardLink() ||\n            item->Is_SymLink())\n        {\n          RINOK(extractCallback->PrepareOperation(askMode))\n          RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        }\n        */\n        continue;\n      }\n      skipMode = true;\n      askMode = NExtract::NAskMode::kSkip;\n    }\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    outStreamSpec->SetStream(realOutStream);\n    realOutStream.Release();\n    outStreamSpec->Init(skipMode ? 0 : unpackSize, true);\n\n    Int32 opRes = NExtract::NOperationResult::kOK;\n    CMyComPtr<ISequentialInStream> inStream2;\n    if (!item->Is_Sparse())\n      inStream2 = inStream;\n    else\n    {\n      const HRESULT hres = GetStream(index, &inStream2);\n      if (hres == E_NOTIMPL)\n        opRes = NExtract::NOperationResult::kHeadersError; // kUnsupportedMethod\n      else if (!inStream2)\n      {\n        opRes = NExtract::NOperationResult::kDataError;\n        // return E_FAIL;\n      }\n    }\n    if (opRes == NExtract::NOperationResult::kOK)\n    {\n      if (item->Is_SymLink())\n      {\n        RINOK(WriteStream(outStreamSpec, (const char *)item->LinkName, item->LinkName.Len()))\n      }\n      else\n      {\n        if (!seqMode)\n        {\n          RINOK(InStream_SeekSet(_stream, item->Get_DataPos()))\n        }\n        inStream->Init(item->Get_PackSize_Aligned());\n        RINOK(copyCoder.Interface()->Code(inStream2, outStreamSpec, NULL, NULL, lps))\n      }\n      if (outStreamSpec->GetRem() != 0)\n        opRes = NExtract::NOperationResult::kDataError;\n    }\n    if (seqMode)\n    {\n      _latestIsRead = false;\n      _curIndex++;\n    }\n    outStreamSpec->ReleaseStream();\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_CLASS_IMP_IInStream(\n  CSparseStream\n)\n  UInt64 _phyPos;\n  UInt64 _virtPos;\n  bool _needStartSeek;\n\npublic:\n  unsigned ItemIndex;\n  CHandler *Handler;\n  CMyComPtr<IUnknown> HandlerRef;\n  CRecordVector<UInt64> PhyOffsets;\n\n  void Init()\n  {\n    _virtPos = 0;\n    _phyPos = 0;\n    _needStartSeek = true;\n  }\n};\n\n\nZ7_COM7F_IMF(CSparseStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  const CItemEx &item = Handler->_items[ItemIndex];\n  if (_virtPos >= item.Size)\n    return S_OK;\n  {\n    const UInt64 rem = item.Size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  \n  HRESULT res = S_OK;\n\n  if (item.SparseBlocks.IsEmpty())\n    memset(data, 0, size);\n  else\n  {\n    unsigned left = 0, right = item.SparseBlocks.Size();\n    for (;;)\n    {\n      const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      if (mid == left)\n        break;\n      if (_virtPos < item.SparseBlocks[mid].Offset)\n        right = mid;\n      else\n        left = mid;\n    }\n    \n    const CSparseBlock &sb = item.SparseBlocks[left];\n    const UInt64 relat = _virtPos - sb.Offset;\n    \n    if (_virtPos >= sb.Offset && relat < sb.Size)\n    {\n      const UInt64 rem = sb.Size - relat;\n      if (size > rem)\n        size = (UInt32)rem;\n      const UInt64 phyPos = PhyOffsets[left] + relat;\n      if (_needStartSeek || _phyPos != phyPos)\n      {\n        RINOK(InStream_SeekSet(Handler->_stream, item.Get_DataPos() + phyPos))\n        _needStartSeek = false;\n        _phyPos = phyPos;\n      }\n      res = Handler->_stream->Read(data, size, &size);\n      _phyPos += size;\n    }\n    else\n    {\n      UInt64 next = item.Size;\n      if (_virtPos < sb.Offset)\n        next = sb.Offset;\n      else if (left + 1 < item.SparseBlocks.Size())\n        next = item.SparseBlocks[left + 1].Offset;\n      const UInt64 rem = next - _virtPos;\n      if (size > rem)\n        size = (UInt32)rem;\n      memset(data, 0, size);\n    }\n  }\n  \n  _virtPos += size;\n  if (processedSize)\n    *processedSize = size;\n  return res;\n}\n\nZ7_COM7F_IMF(CSparseStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Handler->_items[ItemIndex].Size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = _virtPos;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  \n  const CItemEx &item = _items[index];\n\n  if (item.Is_Sparse())\n  {\n    if (item.Method_Error)\n      return E_NOTIMPL; // S_FALSE\n    CSparseStream *streamSpec = new CSparseStream;\n    CMyComPtr<IInStream> streamTemp = streamSpec;\n    streamSpec->Init();\n    streamSpec->Handler = this;\n    streamSpec->HandlerRef = (IInArchive *)this;\n    streamSpec->ItemIndex = index;\n    streamSpec->PhyOffsets.Reserve(item.SparseBlocks.Size());\n    UInt64 offs = 0;\n    FOR_VECTOR(i, item.SparseBlocks)\n    {\n      const CSparseBlock &sb = item.SparseBlocks[i];\n      streamSpec->PhyOffsets.AddInReserved(offs);\n      offs += sb.Size;\n    }\n    *stream = streamTemp.Detach();\n    return S_OK;\n  }\n  \n  if (item.Is_SymLink())\n  {\n    Create_BufInStream_WithReference((const Byte *)(const char *)item.LinkName, item.LinkName.Len(), (IInArchive *)this, stream);\n    return S_OK;\n  }\n  \n  return CreateLimitedInStream(_stream, item.Get_DataPos(), item.PackSize, stream);\n  \n  COM_TRY_END\n}\n\n\nvoid CHandler::Init()\n{\n  _forceCodePage = false;\n  _curCodePage = _specifiedCodePage = CP_UTF8;  // CP_OEMCP;\n  _posixMode = false;\n  _posixMode_WasForced = false;\n  // TimeOptions.Clear();\n  _handlerTimeOptions.Init();\n  // _handlerTimeOptions.Write_MTime.Val = true; // it's default already\n}\n\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  Init();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    UString name = names[i];\n    name.MakeLower_Ascii();\n    if (name.IsEmpty())\n      return E_INVALIDARG;\n\n    const PROPVARIANT &prop = values[i];\n\n    if (name[0] == L'x')\n    {\n      // some clients write 'x' property. So we support it\n      UInt32 level = 0;\n      RINOK(ParsePropToUInt32(name.Ptr(1), prop, level))\n    }\n    else if (name.IsEqualTo(\"cp\"))\n    {\n      UInt32 cp = CP_OEMCP;\n      RINOK(ParsePropToUInt32(L\"\", prop, cp))\n      _forceCodePage = true;\n      _curCodePage = _specifiedCodePage = cp;\n    }\n    else if (name.IsPrefixedBy_Ascii_NoCase(\"mt\"))\n    {\n    }\n    else if (name.IsPrefixedBy_Ascii_NoCase(\"memuse\"))\n    {\n    }\n    else if (name.IsEqualTo(\"m\"))\n    {\n      if (prop.vt != VT_BSTR)\n        return E_INVALIDARG;\n      const UString s = prop.bstrVal;\n      if (s.IsEqualTo_Ascii_NoCase(\"pax\") ||\n          s.IsEqualTo_Ascii_NoCase(\"posix\"))\n        _posixMode = true;\n      else if (s.IsEqualTo_Ascii_NoCase(\"gnu\"))\n        _posixMode = false;\n      else\n        return E_INVALIDARG;\n      _posixMode_WasForced = true;\n    }\n    else\n    {\n      /*\n      if (name.IsPrefixedBy_Ascii_NoCase(\"td\"))\n      {\n        name.Delete(0, 3);\n        if (prop.vt == VT_EMPTY)\n        {\n          if (name.IsEqualTo_Ascii_NoCase(\"n\"))\n          {\n            // TimeOptions.UseNativeDigits = true;\n          }\n          else if (name.IsEqualTo_Ascii_NoCase(\"r\"))\n          {\n            // TimeOptions.RemoveZeroDigits = true;\n          }\n          else\n            return E_INVALIDARG;\n        }\n        else\n        {\n          UInt32 numTimeDigits = 0;\n          RINOK(ParsePropToUInt32(name, prop, numTimeDigits));\n          TimeOptions.NumDigits_WasForced = true;\n          TimeOptions.NumDigits = numTimeDigits;\n        }\n      }\n      */\n      bool processed = false;\n      RINOK(_handlerTimeOptions.Parse(name, prop, processed))\n      if (processed)\n        continue;\n      return E_INVALIDARG;\n    }\n  }\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarHandler.h",
    "content": "﻿// TarHandler.h\n\n#ifndef ZIP7_INC_TAR_HANDLER_H\n#define ZIP7_INC_TAR_HANDLER_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"../Common/HandlerOut.h\"\n\n#include \"TarIn.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nZ7_CLASS_IMP_CHandler_IInArchive_4(\n    IArchiveOpenSeq\n  , IInArchiveGetStream\n  , ISetProperties\n  , IOutArchive\n)\npublic:\n  CObjectVector<CItemEx> _items;\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\nprivate:\n  bool _isArc;\n  bool _posixMode_WasForced;\n  bool _posixMode;\n  bool _forceCodePage;\n  UInt32 _specifiedCodePage;\n  UInt32 _curCodePage;\n  UInt32 _openCodePage;\n  // CTimeOptions TimeOptions;\n  CHandlerTimeOptions _handlerTimeOptions;\n  CEncodingCharacts _encodingCharacts;\n\n  UInt32 _curIndex;\n  bool _latestIsRead;\n  CItemEx _latestItem;\n\n  CArchive _arc;\n\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *callback);\n  HRESULT SkipTo(UInt32 index);\n  void TarStringToUnicode(const AString &s, NWindows::NCOM::CPropVariant &prop, bool toOs = false) const;\npublic:\n  void Init();\n  CHandler();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarHandlerOut.cpp",
    "content": "﻿// TarHandlerOut.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"TarHandler.h\"\n#include \"TarUpdate.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NTar {\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  UInt32 t = NFileTimeType::kUnix;\n  const UInt32 prec = _handlerTimeOptions.Prec;\n  if (prec != (UInt32)(Int32)-1)\n  {\n    t = NFileTimeType::kWindows;\n    if (prec == k_PropVar_TimePrec_0 ||\n        prec == k_PropVar_TimePrec_100ns)\n      t = NFileTimeType::kWindows;\n    else if (prec == k_PropVar_TimePrec_HighPrec)\n      t = k_PropVar_TimePrec_1ns;\n    else if (prec >= k_PropVar_TimePrec_Base)\n      t = prec;\n  }\n  // 7-Zip before 22.00 fails, if unknown typeType.\n  *type = t;\n  return S_OK;\n}\n\n\nvoid Get_AString_From_UString(const UString &s, AString &res,\n    UINT codePage, unsigned utfFlags)\n{\n  if (codePage == CP_UTF8)\n    ConvertUnicodeToUTF8_Flags(s, res, utfFlags);\n  else\n    UnicodeStringToMultiByte2(res, s, codePage);\n}\n\n\nHRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res,\n    UINT codePage, unsigned utfFlags, bool convertSlash)\n{\n  NCOM::CPropVariant prop;\n  RINOK(callback->GetProperty(index, propId, &prop))\n  \n  if (prop.vt == VT_BSTR)\n  {\n    UString s = prop.bstrVal;\n    if (convertSlash)\n      NItemName::ReplaceSlashes_OsToUnix(s);\n    Get_AString_From_UString(s, res, codePage, utfFlags);\n  }\n  else if (prop.vt != VT_EMPTY)\n    return E_INVALIDARG;\n\n  return S_OK;\n}\n\n\n// sort old files with original order.\n\nstatic int CompareUpdateItems(void *const *p1, void *const *p2, void *)\n{\n  const CUpdateItem &u1 = *(*((const CUpdateItem *const *)p1));\n  const CUpdateItem &u2 = *(*((const CUpdateItem *const *)p2));\n  if (!u1.NewProps)\n  {\n    if (u2.NewProps)\n      return -1;\n    return MyCompare(u1.IndexInArc, u2.IndexInArc);\n  }\n  if (!u2.NewProps)\n    return 1;\n  return MyCompare(u1.IndexInClient, u2.IndexInClient);\n}\n\n\nstatic HRESULT GetTime(UInt32 i, UInt32 pid, IArchiveUpdateCallback *callback,\n    CPaxTime &pt)\n{\n  pt.Clear();\n  NCOM::CPropVariant prop;\n  RINOK(callback->GetProperty(i, pid, &prop))\n  return Prop_To_PaxTime(prop, pt);\n}\n\n\n/*\nstatic HRESULT GetDevice(IArchiveUpdateCallback *callback, UInt32 i,\n    UInt32 &majo, UInt32 &mino, bool &majo_defined, bool &mino_defined)\n{\n  NWindows::NCOM::CPropVariant prop;\n  RINOK(callback->GetProperty(i, kpidDevice, &prop));\n  if (prop.vt == VT_EMPTY)\n    return S_OK;\n  if (prop.vt != VT_UI8)\n    return E_INVALIDARG;\n  {\n    const UInt64 v = prop.uhVal.QuadPart;\n    majo = MY_dev_major(v);\n    mino = MY_dev_minor(v);\n    majo_defined = true;\n    mino_defined = true;\n  }\n  return S_OK;\n}\n*/\n\nstatic HRESULT GetDevice(IArchiveUpdateCallback *callback, UInt32 i,\n    UInt32 pid, UInt32 &id, bool &defined)\n{\n  defined = false;\n  NWindows::NCOM::CPropVariant prop;\n  RINOK(callback->GetProperty(i, pid, &prop))\n  if (prop.vt == VT_EMPTY)\n    return S_OK;\n  if (prop.vt == VT_UI4)\n  {\n    id = prop.ulVal;\n    defined = true;\n    return S_OK;\n  }\n  return E_INVALIDARG;\n}\n\n\nstatic HRESULT GetUser(IArchiveUpdateCallback *callback, UInt32 i,\n    UInt32 pidName, UInt32 pidId, AString &name, UInt32 &id,\n    UINT codePage, unsigned utfFlags)\n{\n  // printf(\"\\ncallback->GetProperty(i, pidId, &prop))\\n\");\n   \n  bool isSet = false;\n  {\n    NWindows::NCOM::CPropVariant prop;\n    RINOK(callback->GetProperty(i, pidId, &prop))\n    if (prop.vt == VT_UI4)\n    {\n      isSet = true;\n      id = prop.ulVal;\n      // printf(\"\\ncallback->GetProperty(i, pidId, &prop)); = %d \\n\", (unsigned)id);\n      name.Empty();\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  {\n    NWindows::NCOM::CPropVariant prop;\n    RINOK(callback->GetProperty(i, pidName, &prop))\n    if (prop.vt == VT_BSTR)\n    {\n      const UString s = prop.bstrVal;\n      Get_AString_From_UString(s, name, codePage, utfFlags);\n      if (!isSet)\n        id = 0;\n    }\n    else if (prop.vt == VT_UI4)\n    {\n      id = prop.ulVal;\n      name.Empty();\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  return S_OK;\n}\n\n\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *callback))\n{\n  COM_TRY_BEGIN\n\n  if ((_stream && (_arc._error != k_ErrorType_OK || _arc._is_Warning\n      /* || _isSparse */\n      )) || _seqStream)\n    return E_NOTIMPL;\n  CObjectVector<CUpdateItem> updateItems;\n  const UINT codePage = (_forceCodePage ? _specifiedCodePage : _openCodePage);\n  const unsigned utfFlags = g_Unicode_To_UTF8_Flags;\n  /*\n  // for debug only:\n  unsigned utfFlags = 0;\n  utfFlags |= Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE;\n  utfFlags |= Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR;\n  */\n\n  for (UInt32 i = 0; i < numItems; i++)\n  {\n    CUpdateItem ui;\n    Int32 newData;\n    Int32 newProps;\n    UInt32 indexInArc;\n    \n    if (!callback)\n      return E_FAIL;\n    \n    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc))\n    \n    ui.NewProps = IntToBool(newProps);\n    ui.NewData = IntToBool(newData);\n    ui.IndexInArc = (int)indexInArc;\n    ui.IndexInClient = i;\n\n    if (IntToBool(newProps))\n    {\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidIsDir, &prop))\n        if (prop.vt == VT_EMPTY)\n          ui.IsDir = false;\n        else if (prop.vt != VT_BOOL)\n          return E_INVALIDARG;\n        else\n          ui.IsDir = (prop.boolVal != VARIANT_FALSE);\n      }\n\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidPosixAttrib, &prop))\n        if (prop.vt == VT_EMPTY)\n          ui.Mode =\n                MY_LIN_S_IRWXO\n              | MY_LIN_S_IRWXG\n              | MY_LIN_S_IRWXU\n              | (ui.IsDir ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG);\n        else if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n        else\n          ui.Mode = prop.ulVal;\n        // 21.07 : we clear high file type bits as GNU TAR.\n        // we will clear it later\n        // ui.Mode &= ~(UInt32)MY_LIN_S_IFMT;\n      }\n\n      if (_handlerTimeOptions.Write_MTime.Val)\n        RINOK(GetTime(i, kpidMTime, callback, ui.PaxTimes.MTime))\n      if (_handlerTimeOptions.Write_ATime.Val)\n        RINOK(GetTime(i, kpidATime, callback, ui.PaxTimes.ATime))\n      if (_handlerTimeOptions.Write_CTime.Val)\n        RINOK(GetTime(i, kpidCTime, callback, ui.PaxTimes.CTime))\n\n      RINOK(GetPropString(callback, i, kpidPath, ui.Name, codePage, utfFlags, true))\n      if (ui.IsDir && !ui.Name.IsEmpty() && ui.Name.Back() != '/')\n        ui.Name.Add_Slash();\n      // ui.Name.Add_Slash(); // for debug\n\n      if (_posixMode)\n      {\n        RINOK(GetDevice(callback, i, kpidDeviceMajor, ui.DeviceMajor, ui.DeviceMajor_Defined))\n        RINOK(GetDevice(callback, i, kpidDeviceMinor, ui.DeviceMinor, ui.DeviceMinor_Defined))\n      }\n\n      RINOK(GetUser(callback, i, kpidUser,  kpidUserId,  ui.User,  ui.UID, codePage, utfFlags))\n      RINOK(GetUser(callback, i, kpidGroup, kpidGroupId, ui.Group, ui.GID, codePage, utfFlags))\n    }\n\n    if (IntToBool(newData))\n    {\n      NCOM::CPropVariant prop;\n      RINOK(callback->GetProperty(i, kpidSize, &prop))\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      ui.Size = prop.uhVal.QuadPart;\n      /*\n      // now we support GNU extension for big files\n      if (ui.Size >= ((UInt64)1 << 33))\n        return E_INVALIDARG;\n      */\n    }\n    \n    updateItems.Add(ui);\n  }\n  \n  if (_arc._are_Pax_Items)\n  {\n    // we restore original order of files, if there are pax items\n    updateItems.Sort(CompareUpdateItems, NULL);\n  }\n\n  CUpdateOptions options;\n\n  options.CodePage = codePage;\n  options.UtfFlags = utfFlags;\n  options.PosixMode = _posixMode;\n  \n  options.Write_MTime = _handlerTimeOptions.Write_MTime;\n  options.Write_ATime = _handlerTimeOptions.Write_ATime;\n  options.Write_CTime = _handlerTimeOptions.Write_CTime;\n  \n  // options.TimeOptions = TimeOptions;\n  \n  const UInt32 prec = _handlerTimeOptions.Prec;\n  if (prec != (UInt32)(Int32)-1)\n  {\n    unsigned numDigits = 0;\n    if (prec == 0)\n      numDigits = 7;\n    else if (prec == k_PropVar_TimePrec_HighPrec\n          || prec >= k_PropVar_TimePrec_1ns)\n      numDigits = 9;\n    else if (prec >= k_PropVar_TimePrec_Base)\n      numDigits = prec - k_PropVar_TimePrec_Base;\n    options.TimeOptions.NumDigitsMax = numDigits;\n    // options.TimeOptions.RemoveZeroMode =\n        // k_PaxTimeMode_DontRemoveZero; // pure for debug\n        // k_PaxTimeMode_RemoveZero_if_PureSecondOnly; // optimized code\n        // k_PaxTimeMode_RemoveZero_Always; // original pax code\n  }\n\n  return UpdateArchive(_stream, outStream, _items, updateItems,\n      options, callback);\n  \n  COM_TRY_END\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarHeader.cpp",
    "content": "﻿// Archive/TarHeader.cpp\n\n#include \"StdAfx.h\"\n\n#include \"TarHeader.h\"\n\nnamespace NArchive {\nnamespace NTar {\nnamespace NFileHeader {\n\n  const char * const kLongLink = \"././@LongLink\";\n  const char * const kLongLink2 = \"@LongLink\";\n\n  // The magic field is filled with this if uname and gname are valid.\n  namespace NMagic\n  {\n    // const char * const kUsTar  = \"ustar\";   // 5 chars\n    // const char * const kGNUTar = \"GNUtar \"; // 7 chars and a null\n    // const char * const kEmpty = \"\\0\\0\\0\\0\\0\\0\\0\\0\";\n    // 7-Zip used kUsTar_00 before 21.07:\n    const char k_Posix_ustar_00[8]  = { 'u', 's', 't', 'a', 'r', 0, '0', '0' } ;\n    // GNU TAR uses such header:\n    const char k_GNU_ustar[8] = { 'u', 's', 't', 'a', 'r', ' ', ' ', 0 } ;\n  }\n\n/*\npre-POSIX.1-1988 (i.e. v7) tar header:\n-----\nLink indicator:\n'0' or 0 : Normal file\n'1' : Hard link\n'2' : Symbolic link\nSome pre-POSIX.1-1988 tar implementations indicated a directory by having\na trailing slash (/) in the name.\n\nNumeric values : octal with leading zeroes.\nFor historical reasons, a final NUL or space character should also be used.\nThus only 11 octal digits can be stored from 12 bytes field.\n\n2001 star : introduced a base-256 coding that is indicated by\nsetting the high-order bit of the leftmost byte of a numeric field.\nGNU-tar and BSD-tar followed this idea.\n \nversions of tar from before the first POSIX standard from 1988\npad the values with spaces instead of zeroes.\n\nUStar\n-----\nUStar (Unix Standard TAR) : POSIX IEEE P1003.1 : 1988.\n    257 signature: \"ustar\", 0, \"00\"\n    265 32  Owner user name\n    297 32  Owner group name\n    329 8 Device major number\n    337 8 Device minor number\n    345 155 Filename prefix\n\nPOSIX.1-2001/pax\n----\nformat is known as extended tar format or pax format\nvendor-tagged vendor-specific enhancements.\ntags Defined by the POSIX standard:\n  atime, mtime, path, linkpath, uname, gname, size, uid, gid, ...\n\n\nPAX EXTENSION\n-----------\nHard links\nA further difference from the ustar header block is that data blocks\nfor files of typeflag 1 (hard link) may be included,\nwhich means that the size field may be greater than zero.\nArchives created by pax -o linkdata shall include these data\nblocks with the hard links.\n*\n\ncompatiblity\n------------\n  7-Zip 16.03 supports \"PaxHeader/\"\n  7-Zip 20.01 supports \"PaxHeaders.X/\" with optional \"./\"\n  7-Zip 21.02 supports \"@PaxHeader\" with optional \"./\" \"./\"\n\n  GNU tar --format=posix uses \"PaxHeaders/\" in folder of file\n  \n\nGNU TAR format\n==============\nv7      - Unix V7\noldgnu  - GNU tar <=1.12  : writes zero in last character in name\ngnu     - GNU tar 1.13    : doesn't write  zero in last character in name\n                            as 7-zip 21.07\nustar       - POSIX.1-1988\nposix (pax) - POSIX.1-2001\n\n  gnu tar:\n  if (S_ISCHR (st->stat.st_mode) || S_ISBLK (st->stat.st_mode)) {\n      major_t devmajor = major (st->stat.st_rdev);\n      minor_t devminor = minor (st->stat.st_rdev); }\n*/\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarHeader.h",
    "content": "﻿// Archive/TarHeader.h\n\n#ifndef ZIP7_INC_ARCHIVE_TAR_HEADER_H\n#define ZIP7_INC_ARCHIVE_TAR_HEADER_H\n\n#include \"../../../Common/MyTypes.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nnamespace NFileHeader\n{\n  const unsigned kRecordSize = 512;\n  const unsigned kNameSize = 100;\n  const unsigned kUserNameSize = 32;\n  const unsigned kGroupNameSize = 32;\n  const unsigned kPrefixSize = 155;\n\n  const unsigned kUstarMagic_Offset = 257;\n\n  /*\n  struct CHeader\n  {\n    char Name[kNameSize];\n    char Mode[8];\n    char UID[8];\n    char GID[8];\n    char Size[12];\n    char ModificationTime[12];\n    char CheckSum[8];\n    char LinkFlag;\n    char LinkName[kNameSize];\n    char Magic[8];\n    char UserName[kUserNameSize];\n    char GroupName[kGroupNameSize];\n    char DeviceMajor[8];\n    char DeviceMinor[8];\n    char Prefix[155];\n  };\n  union CRecord\n  {\n    CHeader Header;\n    Byte Padding[kRecordSize];\n  };\n  */\n\n  namespace NLinkFlag\n  {\n    const char kOldNormal    = 0;   // Normal disk file, Unix compatible\n    const char kNormal       = '0'; // Normal disk file\n    const char kHardLink     = '1'; // Link to previously dumped file\n    const char kSymLink      = '2'; // Symbolic link\n    const char kCharacter    = '3'; // Character special file\n    const char kBlock        = '4'; // Block special file\n    const char kDirectory    = '5'; // Directory\n    const char kFIFO         = '6'; // FIFO special file\n    const char kContiguous   = '7'; // Contiguous file\n    const char kGnu_LongLink = 'K';\n    const char kGnu_LongName = 'L';\n    const char kSparse       = 'S';\n    const char kLabel        = 'V';\n    const char kPax          = 'x'; // Extended header with meta data for the next file in the archive (POSIX.1-2001)\n    const char kPax_2        = 'X';\n    const char kGlobal       = 'g'; //  Global extended header with meta data (POSIX.1-2001)\n    const char kDumpDir      = 'D'; /* GNUTYPE_DUMPDIR.\n      data: list of files created by the --incremental (-G) option\n      Each file name is preceded by either\n        - 'Y' (file should be in this archive)\n        - 'N' (file is a directory, or is not stored in the archive.)\n        Each file name is terminated by a null + an additional null after\n        the last file name. */\n    // 'A'-'Z'  Vendor specific extensions (POSIX.1-1988)\n  }\n\n  extern const char * const kLongLink;  //   = \"././@LongLink\";\n  extern const char * const kLongLink2; //   = \"@LongLink\";\n\n  namespace NMagic\n  {\n    // extern const char * const kUsTar;  //  = \"ustar\"; // 5 chars\n    // extern const char * const kGNUTar; //  = \"GNUtar \"; // 7 chars and a null\n    // extern const char * const kEmpty;  //  = \"\\0\\0\\0\\0\\0\\0\\0\\0\"\n    extern const char k_Posix_ustar_00[8];\n    extern const char k_GNU_ustar[8];\n  }\n}\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarIn.cpp",
    "content": "﻿// TarIn.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/StringToInt.h\"\n\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../IArchive.h\"\n\n#include \"TarIn.h\"\n\n#define NUM_UNROLL_BYTES (8 * 4)\n\nZ7_NO_INLINE static bool IsBufNonZero(const void *data, size_t size);\nZ7_NO_INLINE static bool IsBufNonZero(const void *data, size_t size)\n{\n  const Byte *p = (const Byte *)data;\n\n  for (; size != 0 && ((unsigned)(ptrdiff_t)p & (NUM_UNROLL_BYTES - 1)) != 0; size--)\n    if (*p++ != 0)\n      return true;\n\n  if (size >= NUM_UNROLL_BYTES)\n  {\n    const Byte *lim = p + size;\n    size &= (NUM_UNROLL_BYTES - 1);\n    lim -= size;\n    do\n    {\n      if (*(const UInt64 *)(const void *)(p        ) != 0) return true;\n      if (*(const UInt64 *)(const void *)(p + 8 * 1) != 0) return true;\n      if (*(const UInt64 *)(const void *)(p + 8 * 2) != 0) return true;\n      if (*(const UInt64 *)(const void *)(p + 8 * 3) != 0) return true;\n      // if (*(const UInt32 *)(const void *)(p        ) != 0) return true;\n      // if (*(const UInt32 *)(const void *)(p + 4 * 1) != 0) return true;\n      // if (*(const UInt32 *)(const void *)(p + 4 * 2) != 0) return true;\n      // if (*(const UInt32 *)(const void *)(p + 4 * 3) != 0) return true;\n      p += NUM_UNROLL_BYTES;\n    }\n    while (p != lim);\n  }\n  \n  for (; size != 0; size--)\n    if (*p++ != 0)\n      return true;\n\n  return false;\n}\n\n\nnamespace NArchive {\nnamespace NTar {\n \nstatic void MyStrNCpy(char *dest, const char *src, unsigned size)\n{\n  for (unsigned i = 0; i < size; i++)\n  {\n    char c = src[i];\n    dest[i] = c;\n    if (c == 0)\n      break;\n  }\n}\n\nstatic bool OctalToNumber(const char *srcString, unsigned size, UInt64 &res, bool allowEmpty = false)\n{\n  res = 0;\n  char sz[32];\n  MyStrNCpy(sz, srcString, size);\n  sz[size] = 0;\n  const char *end;\n  unsigned i;\n  for (i = 0; sz[i] == ' '; i++);\n  if (sz[i] == 0)\n    return allowEmpty;\n  res = ConvertOctStringToUInt64(sz + i, &end);\n  return (*end == ' ' || *end == 0);\n}\n\nstatic bool OctalToNumber32(const char *srcString, UInt32 &res, bool allowEmpty = false)\n{\n  const unsigned kSize = 8;\n  UInt64 res64;\n  if (!OctalToNumber(srcString, kSize, res64, allowEmpty))\n    return false;\n  res = (UInt32)res64;\n  return (res64 <= 0xFFFFFFFF);\n}\n\n#define RIF(x) { if (!(x)) return S_OK; }\n\nstatic void ReadString(const char *s, unsigned size, AString &result)\n{\n  result.SetFrom_CalcLen(s, size);\n}\n\nstatic bool ParseInt64(const char *p, Int64 &val, bool &isBin)\n{\n  const UInt32 h = GetBe32(p);\n  val = (Int64)GetBe64(p + 4);\n  isBin = true;\n  if (h == (UInt32)1 << 31)\n    return ((val >> 63) & 1) == 0;\n  if (h == (UInt32)(Int32)-1)\n    return ((val >> 63) & 1) != 0;\n  isBin = false;\n  UInt64 u;\n  const bool res = OctalToNumber(p, 12, u);\n  val = (Int64)u;\n  return res;\n}\n\nstatic bool ParseInt64_MTime(const char *p, Int64 &val, bool &isBin)\n{\n  // rare case tar : ZEROs in Docker-Windows TARs\n  // rare case tar : spaces\n  isBin = false;\n  if (GetUi32(p) != 0)\n  for (unsigned i = 0; i < 12; i++)\n    if (p[i] != ' ')\n      return ParseInt64(p, val, isBin);\n  val = 0;\n  return true;\n}\n\nstatic bool ParseSize(const char *p, UInt64 &val, bool &isBin)\n{\n  if (GetBe32(p) == (UInt32)1 << 31)\n  {\n    // GNU extension\n    isBin = true;\n    val = GetBe64(p + 4);\n    return ((val >> 63) & 1) == 0;\n  }\n  isBin = false;\n  return OctalToNumber(p, 12, val,\n      true // 20.03: allow empty size for 'V' Label entry\n      );\n}\n\nstatic bool ParseSize(const char *p, UInt64 &val)\n{\n  bool isBin;\n  return ParseSize(p, val, isBin);\n}\n\n#define CHECK(x) { if (!(x)) return k_IsArc_Res_NO; }\n\nAPI_FUNC_IsArc IsArc_Tar(const Byte *p2, size_t size)\n{\n  if (size < NFileHeader::kRecordSize)\n    return k_IsArc_Res_NEED_MORE;\n\n  const char *p = (const char *)p2;\n  p += NFileHeader::kNameSize;\n\n  UInt32 mode;\n  // we allow empty Mode value for LongName prefix items\n  CHECK(OctalToNumber32(p, mode, true)) p += 8;\n\n  // if (!OctalToNumber32(p, item.UID)) item.UID = 0;\n  p += 8;\n  // if (!OctalToNumber32(p, item.GID)) item.GID = 0;\n  p += 8;\n\n  UInt64 packSize;\n  Int64 time;\n  UInt32 checkSum;\n  bool isBin;\n  CHECK(ParseSize(p, packSize, isBin)) p += 12;\n  CHECK(ParseInt64_MTime(p, time, isBin)) p += 12;\n  CHECK(OctalToNumber32(p, checkSum))\n  return k_IsArc_Res_YES;\n}\n\n\nHRESULT CArchive::GetNextItemReal(CItemEx &item)\n{\n  char buf[NFileHeader::kRecordSize];\n\n  item.Method_Error = false;\n  error = k_ErrorType_OK;\n  filled = false;\n\n  bool thereAreEmptyRecords = false;\n  for (;;)\n  {\n    size_t processedSize = NFileHeader::kRecordSize;\n    RINOK(ReadStream(SeqStream, buf, &processedSize))\n    if (processedSize == 0)\n    {\n      if (!thereAreEmptyRecords)\n        error = k_ErrorType_UnexpectedEnd; // \"There are no trailing zero-filled records\";\n      return S_OK;\n    }\n    if (processedSize != NFileHeader::kRecordSize)\n    {\n      if (!thereAreEmptyRecords)\n        error = k_ErrorType_UnexpectedEnd; // error = \"There is no correct record at the end of archive\";\n      else\n      {\n        /*\n        if (IsEmptyData(buf, processedSize))\n          error = k_ErrorType_UnexpectedEnd;\n        else\n        {\n          // extraReadSize = processedSize;\n          // error = k_ErrorType_Corrupted; // some data after the end tail zeros\n        }\n        */\n      }\n\n      return S_OK;\n    }\n    if (IsBufNonZero(buf, NFileHeader::kRecordSize))\n      break;\n    item.HeaderSize += NFileHeader::kRecordSize;\n    thereAreEmptyRecords = true;\n    RINOK(Progress(item, 0))\n  }\n  if (thereAreEmptyRecords)\n  {\n    // error = \"There are data after end of archive\";\n    return S_OK;\n  }\n  \n  char *p = buf;\n\n  error = k_ErrorType_Corrupted;\n\n  // ReadString(p, NFileHeader::kNameSize, item.Name);\n  p += NFileHeader::kNameSize;\n\n  /*\n  item.Name_CouldBeReduced =\n      (item.Name.Len() == NFileHeader::kNameSize ||\n       item.Name.Len() == NFileHeader::kNameSize - 1);\n  */\n\n  // we allow empty Mode value for LongName prefix items\n  RIF(OctalToNumber32(p, item.Mode, true)) p += 8;\n\n  if (!OctalToNumber32(p, item.UID)) { item.UID = 0; }  p += 8;\n  if (!OctalToNumber32(p, item.GID)) { item.GID = 0; }  p += 8;\n\n  RIF(ParseSize(p, item.PackSize, item.PackSize_IsBin))\n  item.Size = item.PackSize;\n  item.Size_IsBin = item.PackSize_IsBin;\n  p += 12;\n  RIF(ParseInt64_MTime(p, item.MTime, item.MTime_IsBin)) p += 12;\n  \n  UInt32 checkSum;\n  RIF(OctalToNumber32(p, checkSum))\n  memset(p, ' ', 8); p += 8;\n\n  item.LinkFlag = *p++;\n\n  ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;\n  \n  /*\n  item.LinkName_CouldBeReduced =\n      (item.LinkName.Len() == NFileHeader::kNameSize ||\n       item.LinkName.Len() == NFileHeader::kNameSize - 1);\n  */\n\n  memcpy(item.Magic, p, 8); p += 8;\n\n  ReadString(p, NFileHeader::kUserNameSize, item.User); p += NFileHeader::kUserNameSize;\n  ReadString(p, NFileHeader::kGroupNameSize, item.Group); p += NFileHeader::kGroupNameSize;\n\n  item.DeviceMajor_Defined = (p[0] != 0); if (item.DeviceMajor_Defined) { RIF(OctalToNumber32(p, item.DeviceMajor)) } p += 8;\n  item.DeviceMinor_Defined = (p[0] != 0); if (item.DeviceMinor_Defined) { RIF(OctalToNumber32(p, item.DeviceMinor)) } p += 8;\n\n  if (p[0] != 0\n      && item.IsMagic_ustar_5chars()\n      && (item.LinkFlag != 'L' ))\n  {\n    item.Prefix_WasUsed = true;\n    ReadString(p, NFileHeader::kPrefixSize, item.Name);\n    item.Name.Add_Slash();\n    unsigned i;\n    for (i = 0; i < NFileHeader::kNameSize; i++)\n      if (buf[i] == 0)\n        break;\n    item.Name.AddFrom(buf, i);\n  }\n  else\n    ReadString(buf, NFileHeader::kNameSize, item.Name);\n  \n  p += NFileHeader::kPrefixSize;\n\n  if (item.LinkFlag == NFileHeader::NLinkFlag::kHardLink)\n  {\n    item.PackSize = 0;\n    item.Size = 0;\n  }\n\n  if (item.LinkFlag == NFileHeader::NLinkFlag::kDirectory)\n  {\n    // GNU tar ignores Size field, if LinkFlag is kDirectory\n    // 21.02 : we set PackSize = 0 to be more compatible with GNU tar\n    item.PackSize = 0;\n    // item.Size = 0;\n  }\n\n  /*\n    TAR standard requires sum of unsigned byte values.\n    But some old TAR programs use sum of signed byte values.\n    So we check both values.\n  */\n  // for (int y = 0; y < 100; y++) // for debug\n  {\n    UInt32 sum0 = 0;\n    {\n      for (unsigned i = 0; i < NFileHeader::kRecordSize; i++)\n        sum0 += (Byte)buf[i];\n    }\n    if (sum0 != checkSum)\n    {\n      Int32 sum = 0;\n      for (unsigned i = 0; i < NFileHeader::kRecordSize; i++)\n        sum += (signed char)buf[i];\n      if ((UInt32)sum != checkSum)\n        return S_OK;\n      item.IsSignedChecksum = true;\n    }\n  }\n\n  item.HeaderSize += NFileHeader::kRecordSize;\n\n  if (item.LinkFlag == NFileHeader::NLinkFlag::kSparse)\n  {\n    // OLD GNU format: parse sparse file information:\n    // PackSize = cumulative size of all non-empty blocks of the file.\n    // We read actual file size from 'realsize' member of oldgnu_header:\n    RIF(ParseSize(buf + 483, item.Size, item.Size_IsBin))\n    if (item.Size < item.PackSize) // additional check\n      return S_OK;\n\n    p = buf + 386;\n    \n    UInt64 end = 0, packSum = 0;\n    unsigned numRecords = 4;\n    unsigned isExtended = (Byte)p[4 * 24]; // (Byte)p[numRecords * 24];\n    // the list of blocks contains non-empty blocks. All another data is empty.\n\n    for (;;)\n    {\n      // const unsigned isExtended = (Byte)p[numRecords * 24];\n      if (isExtended > 1)\n        return S_OK;\n      do\n      {\n        if (GetBe32(p) == 0)\n        {\n          if (isExtended)\n            return S_OK;\n          break;\n        }\n        CSparseBlock sb;\n        RIF(ParseSize(p, sb.Offset))\n        RIF(ParseSize(p + 12, sb.Size))\n        p += 24;\n        /* for all non-last blocks we expect :\n             ((sb.Size & 0x1ff) == 0) && ((sb.Offset & 0x1ff) == 0)\n           for last block : (sb.Size == 0) is possible.\n        */\n        if (sb.Offset < end\n            || item.Size < sb.Offset\n            || item.Size - sb.Offset < sb.Size)\n          return S_OK;\n        // optional check:\n        if (sb.Size && ((end & 0x1ff) || (sb.Offset & 0x1ff)))\n        {\n          item.Method_Error = true; // relaxed check\n          // return S_OK;\n        }\n        end = sb.Offset + sb.Size;\n        packSum += sb.Size;\n        item.SparseBlocks.Add(sb);\n      }\n      while (--numRecords);\n\n      if (!isExtended)\n        break;\n\n      size_t processedSize = NFileHeader::kRecordSize;\n      RINOK(ReadStream(SeqStream, buf, &processedSize))\n      if (processedSize != NFileHeader::kRecordSize)\n      {\n        error = k_ErrorType_UnexpectedEnd;\n        return S_OK;\n      }\n      item.HeaderSize += NFileHeader::kRecordSize;\n      RINOK(Progress(item, 0))\n      p = buf;\n      numRecords = 21;\n      isExtended = (Byte)p[21 * 24]; // (Byte)p[numRecords * 24];\n    }\n    // optional checks for strict size consistency:\n    if (end != item.Size || packSum != item.PackSize)\n    {\n      item.Method_Error = true; // relaxed check\n      // return S_OK;\n    }\n  }\n \n  if (item.PackSize >= (UInt64)1 << 63) // optional check. It was checked in ParseSize() already\n    return S_OK;\n  filled = true;\n  error = k_ErrorType_OK;\n  return S_OK;\n}\n\n\nHRESULT CArchive::Progress(const CItemEx &item, UInt64 posOffset)\n{\n  if (!OpenCallback)\n    return S_OK;\n  const UInt64 pos = item.Get_DataPos() + posOffset;\n  if (NumFiles - NumFiles_Prev < (1 << 16)\n      // && NumRecords - NumRecords_Prev < (1 << 16)\n      && pos - Pos_Prev < ((UInt32)1 << 28))\n    return S_OK;\n  {\n    Pos_Prev = pos;\n    NumFiles_Prev = NumFiles;\n    // NumRecords_Prev = NumRecords;\n    // Sleep(100); // for debug\n    return OpenCallback->SetCompleted(&NumFiles, &pos);\n  }\n}\n\n\nHRESULT CArchive::ReadDataToBuffer(const CItemEx &item,\n    CTempBuffer &tb, size_t stringLimit)\n{\n  tb.Init();\n  UInt64 packSize = item.Get_PackSize_Aligned();\n  if (packSize == 0)\n    return S_OK;\n\n  UInt64 pos;\n\n  {\n    size_t size = stringLimit;\n    if (size > packSize)\n      size = (size_t)packSize;\n    tb.Buffer.AllocAtLeast(size);\n    size_t processedSize = size;\n    const HRESULT res = ReadStream(SeqStream, tb.Buffer, &processedSize);\n    pos = processedSize;\n    if (processedSize != size)\n    {\n      error = k_ErrorType_UnexpectedEnd;\n      return res;\n    }\n    RINOK(res)\n\n    packSize -= size;\n   \n    size_t i;\n    const Byte *p = tb.Buffer;\n    for (i = 0; i < size; i++)\n      if (p[i] == 0)\n        break;\n    if (i >= item.PackSize)\n      tb.StringSize_IsConfirmed = true;\n    if (i > item.PackSize)\n    {\n      tb.StringSize = (size_t)item.PackSize;\n      tb.IsNonZeroTail = true;\n    }\n    else\n    {\n      tb.StringSize = i;\n      if (i != size)\n      {\n        tb.StringSize_IsConfirmed = true;\n        if (IsBufNonZero(p + i, size - i))\n          tb.IsNonZeroTail = true;\n      }\n    }\n   \n    if (packSize == 0)\n      return S_OK;\n  }\n\n  if (InStream)\n  {\n    RINOK(InStream->Seek((Int64)packSize, STREAM_SEEK_CUR, NULL))\n    return S_OK;\n  }\n  const unsigned kBufSize = 1 << 15;\n  Buffer.AllocAtLeast(kBufSize);\n\n  do\n  {\n    RINOK(Progress(item, pos))\n\n    unsigned size = kBufSize;\n    if (size > packSize)\n      size = (unsigned)packSize;\n    size_t processedSize = size;\n    const HRESULT res = ReadStream(SeqStream, Buffer, &processedSize);\n    if (processedSize != size)\n    {\n      error = k_ErrorType_UnexpectedEnd;\n      return res;\n    }\n    if (!tb.IsNonZeroTail)\n    {\n      if (IsBufNonZero(Buffer, size))\n        tb.IsNonZeroTail = true;\n    }\n    packSize -= size;\n    pos += size;\n  }\n  while (packSize != 0);\n  return S_OK;\n}\n \n\n\nstruct CPaxInfo: public CPaxTimes\n{\n  bool DoubleTagError;\n  bool TagParsingError;\n  bool UnknownLines_Overflow;\n  bool Size_Defined;\n  bool UID_Defined;\n  bool GID_Defined;\n  bool Path_Defined;\n  bool Link_Defined;\n  bool User_Defined;\n  bool Group_Defined;\n  bool SCHILY_fflags_Defined;\n  \n  UInt64 Size;\n  UInt32 UID;\n  UInt32 GID;\n\n  AString Path;\n  AString Link;\n  AString User;\n  AString Group;\n  AString UnknownLines;\n  AString SCHILY_fflags;\n  \n  bool ParseID(const AString &val, bool &defined, UInt32 &res)\n  {\n    if (defined)\n      DoubleTagError = true;\n    if (val.IsEmpty())\n      return false;\n    const char *end2;\n    res = ConvertStringToUInt32(val.Ptr(), &end2);\n    if (*end2 != 0)\n      return false;\n    defined = true;\n    return true;\n  }\n\n  bool ParsePax(const CTempBuffer &tb, bool isFile);\n};\n\n\nstatic bool ParsePaxTime(const AString &src, CPaxTime &pt, bool &doubleTagError)\n{\n  if (pt.IsDefined())\n    doubleTagError = true;\n  pt.Clear();\n  const char *s = src.Ptr();\n  bool isNegative = false;\n  if (*s == '-')\n  {\n    isNegative = true;\n    s++;\n  }\n  const char *end;\n  {\n    UInt64 sec = ConvertStringToUInt64(s, &end);\n    if (s == end)\n      return false;\n    if (sec >= ((UInt64)1 << 63))\n      return false;\n    if (isNegative)\n      sec = (UInt64)-(Int64)sec;\n    pt.Sec = (Int64)sec;\n  }\n  if (*end == 0)\n  {\n    pt.Ns = 0;\n    pt.NumDigits = 0;\n    return true;\n  }\n  if (*end != '.')\n    return false;\n  s = end + 1;\n\n  UInt32 ns = 0;\n  unsigned i;\n  const unsigned kNsDigits = 9;\n  for (i = 0;; i++)\n  {\n    const char c = s[i];\n    if (c == 0)\n      break;\n    if (c < '0' || c > '9')\n      return false;\n    // we ignore digits after 9 digits as GNU TAR\n    if (i < kNsDigits)\n    {\n      ns *= 10;\n      ns += (unsigned)(c - '0');\n    }\n  }\n  pt.NumDigits = (int)(i < kNsDigits ? i : kNsDigits);\n  while (i < kNsDigits)\n  {\n    ns *= 10;\n    i++;\n  }\n  if (isNegative && ns != 0)\n  {\n    pt.Sec--;\n    ns = (UInt32)1000 * 1000 * 1000 - ns;\n  }\n  pt.Ns = ns;\n  return true;\n}\n\n\nbool CPaxInfo::ParsePax(const CTempBuffer &tb, bool isFile)\n{\n  DoubleTagError = false;\n  TagParsingError = false;\n  UnknownLines_Overflow = false;\n  Size_Defined = false;\n  UID_Defined = false;\n  GID_Defined = false;\n  Path_Defined = false;\n  Link_Defined = false;\n  User_Defined = false;\n  Group_Defined = false;\n  SCHILY_fflags_Defined = false;\n  \n  // CPaxTimes::Clear();\n\n  const char *s = (const char *)(const void *)(const Byte *)tb.Buffer;\n  size_t rem = tb.StringSize;\n\n  Clear();\n\n  AString name, val;\n\n  while (rem != 0)\n  {\n    unsigned i;\n    for (i = 0;; i++)\n    {\n      if (i > 24 || i >= rem) // we use limitation for size of (size) field\n        return false;\n      if (s[i] == ' ')\n        break;\n    }\n    if (i == 0)\n      return false;\n    const char *end;\n    const UInt32 size = ConvertStringToUInt32(s, &end);\n    const unsigned offset = (unsigned)(end - s) + 1;\n    if (size > rem\n        || size <= offset + 1\n        || offset != i + 1\n        || s[size - 1] != '\\n')\n      return false;\n\n    for (i = offset; i < size; i++)\n      if (s[i] == 0)\n        return false;\n\n    for (i = offset; i < size - 1; i++)\n      if (s[i] == '=')\n        break;\n    if (i == size - 1)\n      return false;\n\n    name.SetFrom(s + offset, i - offset);\n    val.SetFrom(s + i + 1, (unsigned)(size - 1 - (i + 1)));\n    \n    bool parsed = false;\n    if (isFile)\n    {\n      bool isDetectedName = true;\n      // only lower case (name) is supported\n      if (name.IsEqualTo(\"path\"))\n      {\n        if (Path_Defined)\n          DoubleTagError = true;\n        Path = val;\n        Path_Defined = true;\n        parsed = true;\n      }\n      else if (name.IsEqualTo(\"linkpath\"))\n      {\n        if (Link_Defined)\n          DoubleTagError = true;\n        Link = val;\n        Link_Defined = true;\n        parsed = true;\n      }\n      else if (name.IsEqualTo(\"uname\"))\n      {\n        if (User_Defined)\n          DoubleTagError = true;\n        User = val;\n        User_Defined = true;\n        parsed = true;\n      }\n      else if (name.IsEqualTo(\"gname\"))\n      {\n        if (Group_Defined)\n          DoubleTagError = true;\n        Group = val;\n        Group_Defined = true;\n        parsed = true;\n      }\n      else if (name.IsEqualTo(\"uid\"))\n      {\n        parsed = ParseID(val, UID_Defined, UID);\n      }\n      else if (name.IsEqualTo(\"gid\"))\n      {\n        parsed = ParseID(val, GID_Defined, GID);\n      }\n      else if (name.IsEqualTo(\"size\"))\n      {\n        if (Size_Defined)\n          DoubleTagError = true;\n        Size_Defined = false;\n        if (!val.IsEmpty())\n        {\n          const char *end2;\n          Size = ConvertStringToUInt64(val.Ptr(), &end2);\n          if (*end2 == 0)\n          {\n            Size_Defined = true;\n            parsed = true;\n          }\n        }\n      }\n      else if (name.IsEqualTo(\"mtime\"))\n        { parsed = ParsePaxTime(val, MTime, DoubleTagError); }\n      else if (name.IsEqualTo(\"atime\"))\n        { parsed = ParsePaxTime(val, ATime, DoubleTagError); }\n      else if (name.IsEqualTo(\"ctime\"))\n        { parsed = ParsePaxTime(val, CTime, DoubleTagError); }\n      else if (name.IsEqualTo(\"SCHILY.fflags\"))\n      {\n        if (SCHILY_fflags_Defined)\n          DoubleTagError = true;\n        SCHILY_fflags = val;\n        SCHILY_fflags_Defined = true;\n        parsed = true;\n      }\n      else\n        isDetectedName = false;\n      if (isDetectedName && !parsed)\n        TagParsingError = true;\n    }\n    if (!parsed)\n    {\n      if (!UnknownLines_Overflow)\n      {\n        const unsigned addSize = size - offset;\n        if (UnknownLines.Len() + addSize < (1 << 16))\n          UnknownLines.AddFrom(s + offset, addSize);\n        else\n          UnknownLines_Overflow = true;\n      }\n    }\n\n    s += size;\n    rem -= size;\n  }\n  return true;\n}\n\n\nHRESULT CArchive::ReadItem2(CItemEx &item)\n{\n  // CItem\n  \n  item.SparseBlocks.Clear();\n  item.PaxTimes.Clear();\n\n  // CItemEx\n\n  item.HeaderSize = 0;\n  item.Num_Pax_Records = 0;\n\n  item.LongName_WasUsed = false;\n  item.LongName_WasUsed_2 = false;\n\n  item.LongLink_WasUsed = false;\n  item.LongLink_WasUsed_2 = false;\n\n  item.HeaderError = false;\n  item.Method_Error = false;\n  item.IsSignedChecksum = false;\n  item.Prefix_WasUsed = false;\n  \n  item.Pax_Error = false;\n  item.Pax_Overflow = false;\n  item.pax_path_WasUsed = false;\n  item.pax_link_WasUsed = false;\n  item.pax_size_WasUsed = false;\n  \n  item.PaxExtra.Clear();\n  item.SCHILY_fflags.Empty();\n\n  item.EncodingCharacts.Clear();\n  \n  // CArchive temp variable\n\n  NameBuf.Init();\n  LinkBuf.Init();\n  PaxBuf.Init();\n  PaxBuf_global.Init();\n  \n  UInt64 numExtraRecords = 0;\n\n  for (;;)\n  {\n    RINOK(Progress(item, 0))\n    RINOK(GetNextItemReal(item))\n    // NumRecords++;\n\n    if (!filled)\n    {\n      if (error == k_ErrorType_OK)\n      if (numExtraRecords != 0\n          || item.LongName_WasUsed\n          || item.LongLink_WasUsed\n          || item.Num_Pax_Records != 0)\n        error = k_ErrorType_Corrupted;\n      return S_OK;\n    }\n    if (error != k_ErrorType_OK)\n      return S_OK;\n\n    numExtraRecords++;\n\n    const char lf = item.LinkFlag;\n    if (lf == NFileHeader::NLinkFlag::kGnu_LongName ||\n        lf == NFileHeader::NLinkFlag::kGnu_LongLink)\n    {\n      // GNU tar ignores item.Name after LinkFlag test\n      // 22.00 : now we also ignore item.Name here\n      /*\n      if (item.Name != NFileHeader::kLongLink &&\n          item.Name != NFileHeader::kLongLink2)\n      {\n        break;\n        // return S_OK;\n      }\n      */\n\n      CTempBuffer *tb =\n          lf == NFileHeader::NLinkFlag::kGnu_LongName ?\n          &NameBuf :\n          &LinkBuf;\n      \n      /*\n      if (item.PackSize > (1 << 29))\n      {\n        // break;\n        return S_OK;\n      }\n      */\n\n      const unsigned kLongNameSizeMax = (unsigned)1 << 14;\n      RINOK(ReadDataToBuffer(item, *tb, kLongNameSizeMax))\n      if (error != k_ErrorType_OK)\n        return S_OK;\n\n      if (lf == NFileHeader::NLinkFlag::kGnu_LongName)\n      {\n        item.LongName_WasUsed_2 =\n        item.LongName_WasUsed;\n        item.LongName_WasUsed = true;\n      }\n      else\n      {\n        item.LongLink_WasUsed_2 =\n        item.LongLink_WasUsed;\n        item.LongLink_WasUsed = true;\n      }\n\n      if (!tb->StringSize_IsConfirmed)\n        tb->StringSize = 0;\n      item.HeaderSize += item.Get_PackSize_Aligned();\n      if (tb->StringSize == 0 ||\n          tb->StringSize + 1 != item.PackSize)\n        item.HeaderError = true;\n      if (tb->IsNonZeroTail)\n        item.HeaderError = true;\n      continue;\n    }\n\n    if (lf == NFileHeader::NLinkFlag::kGlobal ||\n        lf == NFileHeader::NLinkFlag::kPax ||\n        lf == NFileHeader::NLinkFlag::kPax_2)\n    {\n      // GNU tar ignores item.Name after LinkFlag test\n      // 22.00 : now we also ignore item.Name here\n      /*\n      if (item.PackSize > (UInt32)1 << 26)\n      {\n        break; // we don't want big PaxBuf files\n        // return S_OK;\n      }\n      */\n      const unsigned kParsingPaxSizeMax = (unsigned)1 << 26;\n\n      const bool isStartHeader = (item.HeaderSize == NFileHeader::kRecordSize);\n\n      CTempBuffer *tb = (lf == NFileHeader::NLinkFlag::kGlobal ? &PaxBuf_global : &PaxBuf);\n\n      RINOK(ReadDataToBuffer(item, *tb, kParsingPaxSizeMax))\n      if (error != k_ErrorType_OK)\n        return S_OK;\n\n      item.HeaderSize += item.Get_PackSize_Aligned();\n\n      if (tb->StringSize != item.PackSize\n          || tb->StringSize == 0\n          || tb->IsNonZeroTail)\n        item.Pax_Error = true;\n\n      item.Num_Pax_Records++;\n      if (lf != NFileHeader::NLinkFlag::kGlobal)\n      {\n        item.PaxExtra.RecordPath = item.Name;\n        continue;\n      }\n      // break; // for debug\n      {\n        if (PaxGlobal_Defined)\n          _is_PaxGlobal_Error = true;\n        CPaxInfo paxInfo;\n        if (paxInfo.ParsePax(PaxBuf_global, false))\n        {\n          PaxGlobal.RawLines = paxInfo.UnknownLines;\n          PaxGlobal.RecordPath = item.Name;\n          PaxGlobal_Defined = true;\n        }\n        else\n          _is_PaxGlobal_Error = true;\n        \n        if (isStartHeader\n            && item.Num_Pax_Records == 1\n            && numExtraRecords == 1)\n        {\n          // we skip global pax header info after parsing\n          item.HeaderPos += item.HeaderSize;\n          item.HeaderSize = 0;\n          item.Num_Pax_Records = 0;\n          numExtraRecords = 0;\n        }\n        else\n          _is_PaxGlobal_Error = true;\n      }\n      continue;\n    }\n    \n    /*\n    if (lf == NFileHeader::NLinkFlag::kDumpDir ||\n        lf == NFileHeader::NLinkFlag::kSparse)\n    {\n      // GNU Extensions to the Archive Format\n      break;\n    }\n    if (lf > '7' || (lf < '0' && lf != 0))\n    {\n      break;\n      // return S_OK;\n    }\n    */\n    break;\n  }\n    \n  // we still use name from main header, if long_name is bad\n  if (item.LongName_WasUsed && NameBuf.StringSize != 0)\n  {\n    NameBuf.CopyToString(item.Name);\n    // item.Name_CouldBeReduced = false;\n  }\n  \n  if (item.LongLink_WasUsed)\n  {\n    // we use empty link, if long_link is bad\n    LinkBuf.CopyToString(item.LinkName);\n    // item.LinkName_CouldBeReduced = false;\n  }\n  \n  error = k_ErrorType_OK;\n  \n  if (PaxBuf.StringSize != 0)\n  {\n    CPaxInfo paxInfo;\n    if (!paxInfo.ParsePax(PaxBuf, true))\n      item.Pax_Error = true;\n    else\n    {\n      if (paxInfo.Path_Defined) //  if (!paxInfo.Path.IsEmpty())\n      {\n        item.Name = paxInfo.Path;\n        item.pax_path_WasUsed = true;\n      }\n      if (paxInfo.Link_Defined) // (!paxInfo.Link.IsEmpty())\n      {\n        item.LinkName = paxInfo.Link;\n        item.pax_link_WasUsed = true;\n      }\n      if (paxInfo.User_Defined)\n      {\n        item.User = paxInfo.User;\n        // item.pax_uname_WasUsed = true;\n      }\n      if (paxInfo.Group_Defined)\n      {\n        item.Group = paxInfo.Group;\n        // item.pax_gname_WasUsed = true;\n      }\n      if (paxInfo.SCHILY_fflags_Defined)\n      {\n        item.SCHILY_fflags = paxInfo.SCHILY_fflags;\n        // item.SCHILY_fflags_WasUsed = true;\n      }\n      if (paxInfo.UID_Defined)\n      {\n        item.UID = (UInt32)paxInfo.UID;\n      }\n      if (paxInfo.GID_Defined)\n      {\n        item.GID = (UInt32)paxInfo.GID;\n      }\n      \n      if (paxInfo.Size_Defined)\n      {\n        const UInt64 piSize = paxInfo.Size;\n        // GNU TAR ignores (item.Size) in that case\n        if (item.Size != 0 && item.Size != piSize)\n          item.Pax_Error = true;\n        if (piSize >= ((UInt64)1 << 63))\n          item.Pax_Error = true;\n        else\n        {\n          item.Size = piSize;\n          item.PackSize = piSize;\n          item.pax_size_WasUsed = true;\n        }\n      }\n      \n      item.PaxTimes = paxInfo;\n      item.PaxExtra.RawLines = paxInfo.UnknownLines;\n      if (paxInfo.UnknownLines_Overflow)\n        item.Pax_Overflow = true;\n      if (paxInfo.TagParsingError)\n        item.Pax_Error = true;\n      if (paxInfo.DoubleTagError)\n        item.Pax_Error = true;\n    }\n  }\n\n  return S_OK;\n}\n\n\n\nHRESULT CArchive::ReadItem(CItemEx &item)\n{\n  item.HeaderPos = _phySize;\n  \n  const HRESULT res = ReadItem2(item);\n  \n  /*\n  if (error == k_ErrorType_Warning)\n    _is_Warning = true;\n  else\n  */\n  \n  if (error != k_ErrorType_OK)\n    _error = error;\n  \n  RINOK(res)\n\n  if (filled)\n  {\n    if (item.IsMagic_GNU())\n      _are_Gnu = true;\n    else if (item.IsMagic_Posix_ustar_00())\n      _are_Posix = true;\n    \n    if (item.Num_Pax_Records != 0)\n      _are_Pax = true;\n\n    if (item.PaxTimes.MTime.IsDefined())  _are_mtime = true;\n    if (item.PaxTimes.ATime.IsDefined())  _are_atime = true;\n    if (item.PaxTimes.CTime.IsDefined())  _are_ctime = true;\n    if (!item.SCHILY_fflags.IsEmpty())  _are_SCHILY_fflags = true;\n\n    if (item.pax_path_WasUsed)\n      _are_pax_path = true;\n    if (item.pax_link_WasUsed)\n      _are_pax_link = true;\n    if (item.LongName_WasUsed)\n      _are_LongName = true;\n    if (item.LongLink_WasUsed)\n      _are_LongLink = true;\n    if (item.Prefix_WasUsed)\n      _pathPrefix_WasUsed = true;\n    /*\n    if (item.IsSparse())\n      _isSparse = true;\n    */\n    if (item.Is_PaxExtendedHeader())\n      _are_Pax_Items = true;\n    if (item.IsThereWarning()\n        || item.HeaderError\n        || item.Pax_Error)\n      _is_Warning = true;\n  }\n\n  const UInt64 headerEnd = item.HeaderPos + item.HeaderSize;\n  // _headersSize += headerEnd - _phySize;\n  // we don't count skipped records\n  _headersSize += item.HeaderSize;\n  _phySize = headerEnd;\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarIn.h",
    "content": "﻿// TarIn.h\n\n#ifndef ZIP7_INC_ARCHIVE_TAR_IN_H\n#define ZIP7_INC_ARCHIVE_TAR_IN_H\n\n#include \"../IArchive.h\"\n\n#include \"TarItem.h\"\n\nnamespace NArchive {\nnamespace NTar {\n  \nenum EErrorType\n{\n  k_ErrorType_OK,\n  k_ErrorType_Corrupted,\n  k_ErrorType_UnexpectedEnd\n  // , k_ErrorType_Warning\n};\n\n\nstruct CTempBuffer\n{\n  CByteBuffer Buffer;\n  size_t StringSize; // num characters before zero Byte (StringSize <= item.PackSize)\n  bool IsNonZeroTail;\n  bool StringSize_IsConfirmed;\n\n  void CopyToString(AString &s)\n  {\n    s.Empty();\n    if (StringSize != 0)\n      s.SetFrom((const char *)(const void *)(const Byte *)Buffer, (unsigned)StringSize);\n  }\n\n  void Init()\n  {\n    StringSize = 0;\n    IsNonZeroTail = false;\n    StringSize_IsConfirmed = false;\n  }\n};\n\n\nclass CArchive\n{\npublic:\n  bool _phySize_Defined;\n  bool _is_Warning;\n  bool PaxGlobal_Defined;\n  bool _is_PaxGlobal_Error;\n  bool _are_Pax_Items;\n  bool _are_Gnu;\n  bool _are_Posix;\n  bool _are_Pax;\n  bool _are_mtime;\n  bool _are_atime;\n  bool _are_ctime;\n  bool _are_pax_path;\n  bool _are_pax_link;\n  bool _are_LongName;\n  bool _are_LongLink;\n  bool _pathPrefix_WasUsed;\n  bool _are_SCHILY_fflags;\n  // bool _isSparse;\n\n  // temp internal vars for ReadItem():\n  bool filled;\nprivate:\n  EErrorType error;\n\npublic:\n  UInt64 _phySize;\n  UInt64 _headersSize;\n  EErrorType _error;\n\n  ISequentialInStream *SeqStream;\n  IInStream *InStream;\n  IArchiveOpenCallback *OpenCallback;\n  UInt64 NumFiles;\n  UInt64 NumFiles_Prev;\n  UInt64 Pos_Prev;\n  // UInt64 NumRecords;\n  // UInt64 NumRecords_Prev;\n\n  CPaxExtra PaxGlobal;\n\n  void Clear()\n  {\n    SeqStream = NULL;\n    InStream = NULL;\n    OpenCallback = NULL;\n    NumFiles = 0;\n    NumFiles_Prev = 0;\n    Pos_Prev = 0;\n    // NumRecords = 0;\n    // NumRecords_Prev = 0;\n\n    PaxGlobal.Clear();\n    PaxGlobal_Defined = false;\n    _is_PaxGlobal_Error = false;\n    _are_Pax_Items = false; // if there are final paxItems\n    _are_Gnu = false;\n    _are_Posix = false;\n    _are_Pax = false;\n    _are_mtime = false;\n    _are_atime = false;\n    _are_ctime = false;\n    _are_pax_path = false;\n    _are_pax_link = false;\n    _are_LongName = false;\n    _are_LongLink = false;\n    _pathPrefix_WasUsed = false;\n    _are_SCHILY_fflags = false;\n    // _isSparse = false;\n\n    _is_Warning = false;\n    _error = k_ErrorType_OK;\n\n    _phySize_Defined = false;\n    _phySize = 0;\n    _headersSize = 0;\n  }\n\nprivate:\n  CTempBuffer NameBuf;\n  CTempBuffer LinkBuf;\n  CTempBuffer PaxBuf;\n  CTempBuffer PaxBuf_global;\n\n  CByteBuffer Buffer;\n\n  HRESULT ReadDataToBuffer(const CItemEx &item, CTempBuffer &tb, size_t stringLimit);\n  HRESULT Progress(const CItemEx &item, UInt64 posOffset);\n  HRESULT GetNextItemReal(CItemEx &item);\n  HRESULT ReadItem2(CItemEx &itemInfo);\npublic:\n  CArchive()\n  {\n    // we will call Clear() in CHandler::Close().\n    // Clear(); // it's not required here\n  }\n  HRESULT ReadItem(CItemEx &itemInfo);\n};\n\n\nAPI_FUNC_IsArc IsArc_Tar(const Byte *p, size_t size);\n\n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarItem.h",
    "content": "﻿// TarItem.h\n\n#ifndef ZIP7_INC_ARCHIVE_TAR_ITEM_H\n#define ZIP7_INC_ARCHIVE_TAR_ITEM_H\n\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"TarHeader.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nstruct CSparseBlock\n{\n  UInt64 Offset;\n  UInt64 Size;\n};\n\n\nenum EPaxTimeRemoveZeroMode\n{\n  k_PaxTimeMode_DontRemoveZero,\n  k_PaxTimeMode_RemoveZero_if_PureSecondOnly,\n  k_PaxTimeMode_RemoveZero_Always\n};\n\nstruct CTimeOptions\n{\n  EPaxTimeRemoveZeroMode RemoveZeroMode;\n  unsigned NumDigitsMax;\n\n  void Init()\n  {\n    RemoveZeroMode = k_PaxTimeMode_RemoveZero_if_PureSecondOnly;\n    NumDigitsMax = 0;\n  }\n  CTimeOptions() { Init(); }\n};\n\n\nstruct CPaxTime\n{\n  Int32 NumDigits; // -1 means undefined\n  UInt32 Ns;  // it's smaller than 1G. Even if (Sec < 0), larger (Ns) value means newer files.\n  Int64 Sec;  // can be negative\n\n  Int64 GetSec() const { return NumDigits != -1 ? Sec : 0; }\n\n  bool IsDefined() const { return NumDigits != -1; }\n  // bool IsDefined_And_nonZero() const { return NumDigits != -1 && (Sec != 0 || Ns != 0); }\n  \n  void Clear()\n  {\n    NumDigits = -1;\n    Ns = 0;\n    Sec = 0;\n  }\n  CPaxTime() { Clear(); }\n\n  /*\n  void ReducePrecison(int numDigits)\n  {\n    // we don't use this->NumDigits here\n    if (numDigits > 0)\n    {\n      if (numDigits >= 9)\n        return;\n      UInt32 r = 1;\n      for (unsigned i = numDigits; i < 9; i++)\n        r *= 10;\n      Ns /= r;\n      Ns *= r;\n      return;\n    }\n    Ns = 0;\n    if (numDigits == 0)\n      return;\n    UInt32 r;\n         if (numDigits == -1) r = 60;\n    else if (numDigits == -2) r = 60 * 60;\n    else if (numDigits == -3) r = 60 * 60 * 24;\n    else return;\n    Sec /= r;\n    Sec *= r;\n  }\n  */\n};\n\n\nstruct CPaxTimes\n{\n  CPaxTime MTime;\n  CPaxTime ATime;\n  CPaxTime CTime;\n  \n  void Clear()\n  {\n    MTime.Clear();\n    ATime.Clear();\n    CTime.Clear();\n  }\n\n  /*\n  void ReducePrecison(int numDigits)\n  {\n    MTime.ReducePrecison(numDigits);\n    CTime.ReducePrecison(numDigits);\n    ATime.ReducePrecison(numDigits);\n  }\n  */\n};\n\n\nstruct CItem\n{\n  UInt64 PackSize;\n  UInt64 Size;\n  Int64 MTime;\n\n  char LinkFlag;\n  bool DeviceMajor_Defined;\n  bool DeviceMinor_Defined;\n\n  UInt32 Mode;\n  UInt32 UID;\n  UInt32 GID;\n  UInt32 DeviceMajor;\n  UInt32 DeviceMinor;\n\n  AString Name;\n  AString LinkName;\n  AString User;\n  AString Group;\n\n  char Magic[8];\n\n  CPaxTimes PaxTimes;\n\n  CRecordVector<CSparseBlock> SparseBlocks;\n\n  void SetMagic_Posix(bool posixMode)\n  {\n    memcpy(Magic, posixMode ?\n        NFileHeader::NMagic::k_Posix_ustar_00 :\n        NFileHeader::NMagic::k_GNU_ustar,\n        8);\n  }\n\n  bool Is_SymLink()  const { return LinkFlag == NFileHeader::NLinkFlag::kSymLink && (Size == 0); }\n  bool Is_HardLink() const { return LinkFlag == NFileHeader::NLinkFlag::kHardLink; }\n  bool Is_Sparse()   const { return LinkFlag == NFileHeader::NLinkFlag::kSparse; }\n  \n  UInt64 Get_UnpackSize() const { return Is_SymLink() ? LinkName.Len() : Size; }\n  \n  bool Is_PaxExtendedHeader() const\n  {\n    switch (LinkFlag)\n    {\n      case NFileHeader::NLinkFlag::kPax:\n      case NFileHeader::NLinkFlag::kPax_2:\n      case NFileHeader::NLinkFlag::kGlobal:\n        return true;\n      default: break;\n    }\n    return false;\n  }\n\n  UInt32 Get_Combined_Mode() const\n  {\n    return (Mode & ~(UInt32)MY_LIN_S_IFMT) | Get_FileTypeMode_from_LinkFlag();\n  }\n\n  void Set_LinkFlag_for_File(UInt32 mode)\n  {\n    char                            lf = NFileHeader::NLinkFlag::kNormal;\n         if (MY_LIN_S_ISCHR(mode))  lf = NFileHeader::NLinkFlag::kCharacter;\n    else if (MY_LIN_S_ISBLK(mode))  lf = NFileHeader::NLinkFlag::kBlock;\n    else if (MY_LIN_S_ISFIFO(mode)) lf = NFileHeader::NLinkFlag::kFIFO;\n    // else if (MY_LIN_S_ISDIR(mode))  lf = NFileHeader::NLinkFlag::kDirectory;\n    // else if (MY_LIN_S_ISLNK(mode))  lf = NFileHeader::NLinkFlag::kSymLink;\n    LinkFlag = lf;\n  }\n  \n  UInt32 Get_FileTypeMode_from_LinkFlag() const\n  {\n    switch (LinkFlag)\n    {\n      /*\n      case NFileHeader::NLinkFlag::kDirectory:\n      case NFileHeader::NLinkFlag::kDumpDir:\n        return MY_LIN_S_IFDIR;\n      */\n      case NFileHeader::NLinkFlag::kSymLink:    return MY_LIN_S_IFLNK;\n      case NFileHeader::NLinkFlag::kBlock:      return MY_LIN_S_IFBLK;\n      case NFileHeader::NLinkFlag::kCharacter:  return MY_LIN_S_IFCHR;\n      case NFileHeader::NLinkFlag::kFIFO:       return MY_LIN_S_IFIFO;\n      // case return MY_LIN_S_IFSOCK;\n      default: break;\n    }\n\n    if (IsDir())\n      return MY_LIN_S_IFDIR;\n    return MY_LIN_S_IFREG;\n  }\n\n  bool IsDir() const\n  {\n    switch (LinkFlag)\n    {\n      case NFileHeader::NLinkFlag::kDirectory:\n      case NFileHeader::NLinkFlag::kDumpDir:\n        return true;\n      case NFileHeader::NLinkFlag::kOldNormal:\n      case NFileHeader::NLinkFlag::kNormal:\n      case NFileHeader::NLinkFlag::kSymLink:\n        if (Name.IsEmpty())\n          return false;\n        // GNU TAR uses last character as directory marker\n        // we also do it\n        return Name.Back() == '/';\n        // return NItemName::HasTailSlash(Name, CP_OEMCP);\n      default: break;\n    }\n    return false;\n  }\n\n  bool IsMagic_ustar_5chars() const\n  {\n    for (unsigned i = 0; i < 5; i++)\n      if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar[i])\n        return false;\n    return true;\n  }\n\n  bool IsMagic_Posix_ustar_00() const\n  {\n    for (unsigned i = 0; i < 8; i++)\n      if (Magic[i] != NFileHeader::NMagic::k_Posix_ustar_00[i])\n        return false;\n    return true;\n  }\n\n  bool IsMagic_GNU() const\n  {\n    for (unsigned i = 0; i < 8; i++)\n      if (Magic[i] != NFileHeader::NMagic::k_GNU_ustar[i])\n        return false;\n    return true;\n  }\n\n  UInt64 Get_PackSize_Aligned() const { return (PackSize + 0x1FF) & (~((UInt64)0x1FF)); }\n\n  bool IsThereWarning() const\n  {\n    // that Header Warning is possible if (Size != 0) for dir item\n    return (PackSize < Size) && (LinkFlag == NFileHeader::NLinkFlag::kDirectory);\n  }\n};\n\n\n\nstruct CEncodingCharacts\n{\n  bool IsAscii;\n  // bool Oem_Checked;\n  // bool Oem_Ok;\n  // bool Utf_Checked;\n  CUtf8Check UtfCheck;\n  \n  void Clear()\n  {\n    IsAscii = true;\n    // Oem_Checked = false;\n    // Oem_Ok = false;\n    // Utf_Checked = false;\n    UtfCheck.Clear();\n  }\n\n  void Update(const CEncodingCharacts &ec)\n  {\n    if (!ec.IsAscii)\n      IsAscii = false;\n\n    // if (ec.Utf_Checked)\n    {\n      UtfCheck.Update(ec.UtfCheck);\n      // Utf_Checked = true;\n    }\n  }\n\n  CEncodingCharacts() { Clear(); }\n  void Check(const AString &s);\n  AString GetCharactsString() const;\n};\n\n\nstruct CPaxExtra\n{\n  AString RecordPath;\n  AString RawLines;\n\n  void Clear()\n  {\n    RecordPath.Empty();\n    RawLines.Empty();\n  }\n\n  void Print_To_String(AString &s) const\n  {\n    if (!RecordPath.IsEmpty())\n    {\n      s += RecordPath;\n      s.Add_LF();\n    }\n    if (!RawLines.IsEmpty())\n      s += RawLines;\n  }\n};\n\n\nstruct CItemEx: public CItem\n{\n  bool HeaderError;\n  bool Method_Error;\n  \n  bool IsSignedChecksum;\n  bool Prefix_WasUsed;\n\n  bool Pax_Error;\n  bool Pax_Overflow;\n  bool pax_path_WasUsed;\n  bool pax_link_WasUsed;\n  bool pax_size_WasUsed;\n\n  bool MTime_IsBin;\n  bool PackSize_IsBin;\n  bool Size_IsBin;\n\n  bool LongName_WasUsed;\n  bool LongName_WasUsed_2;\n\n  bool LongLink_WasUsed;\n  bool LongLink_WasUsed_2;\n\n  // bool Name_CouldBeReduced;\n  // bool LinkName_CouldBeReduced;\n\n  UInt64 HeaderPos;\n  UInt64 HeaderSize;\n  \n  UInt64 Num_Pax_Records;\n  CPaxExtra PaxExtra;\n  AString SCHILY_fflags;\n\n  CEncodingCharacts EncodingCharacts;\n\n  UInt64 Get_DataPos() const { return HeaderPos + HeaderSize; }\n  // UInt64 GetFullSize() const { return HeaderSize + PackSize; }\n  UInt64 Get_FullSize_Aligned() const { return HeaderSize + Get_PackSize_Aligned(); }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarOut.cpp",
    "content": "﻿// TarOut.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/7zCrc.h\"\n\n#include \"../../../Common/IntToString.h\"\n\n#include \"../../Common/StreamUtils.h\"\n\n#include \"TarOut.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nusing namespace NFileHeader;\n\n// it's path prefix assigned by 7-Zip to show that file path was cut\n#define K_PREFIX_PATH_CUT \"@PathCut\"\n\nstatic const UInt32 k_7_oct_digits_Val_Max = ((UInt32)1 << (7 * 3)) - 1;\n\nstatic void WriteOctal_8(char *s, UInt32 val)\n{\n  const unsigned kNumDigits = 8 - 1;\n  if (val >= ((UInt32)1 << (kNumDigits * 3)))\n  {\n    val = 0;\n    // return false;\n  }\n  for (unsigned i = 0; i < kNumDigits; i++)\n  {\n    s[kNumDigits - 1 - i] = (char)('0' + (val & 7));\n    val >>= 3;\n  }\n  // return true;\n}\n\nstatic void WriteBin_64bit(char *s, UInt64 val)\n{\n  for (unsigned i = 0; i < 8; i++, val <<= 8)\n    s[i] = (char)(val >> 56);\n}\n\nstatic void WriteOctal_12(char *s, UInt64 val)\n{\n  const unsigned kNumDigits = 12 - 1;\n  if (val >= ((UInt64)1 << (kNumDigits * 3)))\n  {\n    // GNU extension;\n    s[0] = (char)(Byte)0x80;\n    s[1] = s[2] = s[3] = 0;\n    WriteBin_64bit(s + 4, val);\n    return;\n  }\n  for (unsigned i = 0; i < kNumDigits; i++)\n  {\n    s[kNumDigits - 1 - i] = (char)('0' + (val & 7));\n    val >>= 3;\n  }\n}\n\nstatic void WriteOctal_12_Signed(char *s, const Int64 val)\n{\n  if (val >= 0)\n  {\n    WriteOctal_12(s, (UInt64)val);\n    return;\n  }\n  s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF;\n  WriteBin_64bit(s + 4, (UInt64)val);\n}\n\nstatic void CopyString(char *dest, const AString &src, const unsigned maxSize)\n{\n  unsigned len = src.Len();\n  if (len == 0)\n    return;\n  // 21.07: new gnu : we don't require additional 0 character at the end\n  // if (len >= maxSize)\n  if (len > maxSize)\n  {\n    len = maxSize;\n    /*\n    // oldgnu needs 0 character at the end\n    len = maxSize - 1;\n    dest[len] = 0;\n    */\n  }\n  memcpy(dest, src.Ptr(), len);\n}\n\n// #define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_INVALIDARG; }\n#define RETURN_IF_NOT_TRUE(x) { x; }\n\n#define COPY_STRING_CHECK(dest, src, size) \\\n    CopyString(dest, src, size);   dest += (size);\n\n#define WRITE_OCTAL_8_CHECK(dest, src) \\\n    RETURN_IF_NOT_TRUE(WriteOctal_8(dest, src))\n    \n\nHRESULT COutArchive::WriteHeaderReal(const CItem &item, bool isPax\n    // , bool zero_PackSize\n    // , bool zero_MTime\n    )\n{\n  /*\n    if (isPax) { we don't use Glob_Name and Prefix }\n    if (!isPax)\n    {\n      we use Glob_Name if it's not empty\n      we use Prefix    if it's not empty\n    }\n  */\n  char record[kRecordSize];\n  memset(record, 0, kRecordSize);\n  char *cur = record;\n\n  COPY_STRING_CHECK (cur,\n      (!isPax && !Glob_Name.IsEmpty()) ? Glob_Name : item.Name,\n      kNameSize)\n\n  WRITE_OCTAL_8_CHECK (cur, item.Mode)  cur += 8; // & k_7_oct_digits_Val_Max\n  WRITE_OCTAL_8_CHECK (cur, item.UID)   cur += 8;\n  WRITE_OCTAL_8_CHECK (cur, item.GID)   cur += 8;\n\n  WriteOctal_12 (cur, /* zero_PackSize ? 0 : */ item.PackSize); cur += 12;\n  WriteOctal_12_Signed (cur, /* zero_MTime ? 0 : */ item.MTime); cur += 12;\n  \n  // we will use binary init for checksum instead of memset\n  // checksum field:\n  // memset(cur, ' ', 8);\n  cur += 8;\n\n  *cur++ = item.LinkFlag;\n\n  COPY_STRING_CHECK (cur, item.LinkName, kNameSize)\n\n  memcpy(cur, item.Magic, 8);\n  cur += 8;\n\n  COPY_STRING_CHECK (cur, item.User, kUserNameSize)\n  COPY_STRING_CHECK (cur, item.Group, kGroupNameSize)\n\n  const bool needDevice = (IsPosixMode && !isPax);\n  \n  if (item.DeviceMajor_Defined)\n    WRITE_OCTAL_8_CHECK (cur, item.DeviceMajor)\n  else if (needDevice)\n    WRITE_OCTAL_8_CHECK (cur, 0)\n  cur += 8;\n  \n  if (item.DeviceMinor_Defined)\n    WRITE_OCTAL_8_CHECK (cur, item.DeviceMinor)\n  else if (needDevice)\n    WRITE_OCTAL_8_CHECK (cur, 0)\n  cur += 8;\n\n  if (!isPax && !Prefix.IsEmpty())\n  {\n    COPY_STRING_CHECK (cur, Prefix, kPrefixSize)\n  }\n\n  if (item.Is_Sparse())\n  {\n    record[482] = (char)(item.SparseBlocks.Size() > 4 ? 1 : 0);\n    WriteOctal_12(record + 483, item.Size);\n    for (unsigned i = 0; i < item.SparseBlocks.Size() && i < 4; i++)\n    {\n      const CSparseBlock &sb = item.SparseBlocks[i];\n      char *p = record + 386 + 24 * i;\n      WriteOctal_12(p, sb.Offset);\n      WriteOctal_12(p + 12, sb.Size);\n    }\n  }\n\n  {\n    UInt32 sum = (unsigned)(' ') * 8; // we use binary init\n    {\n      for (unsigned i = 0; i < kRecordSize; i++)\n        sum += (Byte)record[i];\n    }\n    /* checksum field is formatted differently from the\n       other fields: it has [6] digits, a null, then a space. */\n    // WRITE_OCTAL_8_CHECK(record + 148, sum);\n    const unsigned kNumDigits = 6;\n    for (unsigned i = 0; i < kNumDigits; i++)\n    {\n      record[148 + kNumDigits - 1 - i] = (char)('0' + (sum & 7));\n      sum >>= 3;\n    }\n    // record[148 + 6] = 0; // we need it, if we use memset(' ') init\n    record[148 + 7] = ' '; // we need it, if we use binary init\n  }\n\n  RINOK(Write_Data(record, kRecordSize))\n\n  if (item.Is_Sparse())\n  {\n    for (unsigned i = 4; i < item.SparseBlocks.Size();)\n    {\n      memset(record, 0, kRecordSize);\n      for (unsigned t = 0; t < 21 && i < item.SparseBlocks.Size(); t++, i++)\n      {\n        const CSparseBlock &sb = item.SparseBlocks[i];\n        char *p = record + 24 * t;\n        WriteOctal_12(p, sb.Offset);\n        WriteOctal_12(p + 12, sb.Size);\n      }\n      record[21 * 24] = (char)(i < item.SparseBlocks.Size() ? 1 : 0);\n      RINOK(Write_Data(record, kRecordSize))\n    }\n  }\n\n  return S_OK;\n}\n\n\nstatic void AddPaxLine(AString &s, const char *name, const AString &val)\n{\n  // s.Add_LF(); // for debug\n  const unsigned len = 3 + (unsigned)strlen(name) + val.Len();\n  AString n;\n  for (unsigned numDigits = 1;; numDigits++)\n  {\n    n.Empty();\n    n.Add_UInt32(numDigits + len);\n    if (numDigits == n.Len())\n      break;\n  }\n  s += n;\n  s.Add_Space();\n  s += name;\n  s.Add_Char('=');\n  s += val;\n  s.Add_LF();\n}\n\n// pt is defined : (pt.NumDigits >= 0)\nstatic void AddPaxTime(AString &s, const char *name, const CPaxTime &pt,\n    const CTimeOptions &options)\n{\n  unsigned numDigits = (unsigned)pt.NumDigits;\n  if (numDigits > options.NumDigitsMax)\n    numDigits = options.NumDigitsMax;\n\n  bool needNs = false;\n  UInt32 ns = 0;\n  if (numDigits != 0)\n  {\n    ns = pt.Ns;\n    // if (ns != 0) before reduction, we show all digits after digits reduction\n    needNs = (ns != 0 || options.RemoveZeroMode == k_PaxTimeMode_DontRemoveZero);\n    UInt32 d = 1;\n    for (unsigned k = numDigits; k < 9; k++)\n      d *= 10;\n    ns /= d;\n    ns *= d;\n  }\n\n  AString v;\n  {\n    Int64 sec = pt.Sec;\n    if (pt.Sec < 0)\n    {\n      sec = -sec;\n      v.Add_Minus();\n      if (ns != 0)\n      {\n        ns = 1000*1000*1000 - ns;\n        sec--;\n      }\n    }\n    v.Add_UInt64((UInt64)sec);\n  }\n  \n  if (needNs)\n  {\n    AString d;\n    d.Add_UInt32(ns);\n    while (d.Len() < 9)\n      d.InsertAtFront('0');\n    // here we have precision\n    while (d.Len() > (unsigned)numDigits)\n      d.DeleteBack();\n    // GNU TAR reduces '0' digits.\n    if (options.RemoveZeroMode == k_PaxTimeMode_RemoveZero_Always)\n    while (!d.IsEmpty() && d.Back() == '0')\n      d.DeleteBack();\n\n    if (!d.IsEmpty())\n    {\n      v.Add_Dot();\n      v += d;\n      // v += \"1234567009999\"; // for debug\n      // for (int y = 0; y < 1000; y++) v += '8'; // for debug\n    }\n  }\n\n  AddPaxLine(s, name, v);\n}\n\n\nstatic void AddPax_UInt32_ifBig(AString &s, const char *name, const UInt32 &v)\n{\n  if (v > k_7_oct_digits_Val_Max)\n  {\n    AString s2;\n    s2.Add_UInt32(v);\n    AddPaxLine(s, name, s2);\n  }\n}\n  \n\n/* OLD_GNU_TAR: writes name with zero at the end\n   NEW_GNU_TAR: can write name filled with all kNameSize characters */\n\nstatic const unsigned kNameSize_Max =\n    kNameSize;     // NEW_GNU_TAR / 7-Zip 21.07\n    // kNameSize - 1; // OLD_GNU_TAR / old 7-Zip\n\n#define DOES_NAME_FIT_IN_FIELD(name) ((name).Len() <= kNameSize_Max)\n\n\nHRESULT COutArchive::WriteHeader(const CItem &item)\n{\n  Glob_Name.Empty();\n  Prefix.Empty();\n\n  unsigned namePos = 0;\n  bool needPathCut = false;\n  bool allowPrefix = false;\n\n  if (!DOES_NAME_FIT_IN_FIELD(item.Name))\n  {\n    const char *s = item.Name;\n    const char *p = s + item.Name.Len() - 1;\n    for (; *p == '/' && p != s; p--)\n      {}\n    for (; p != s && p[-1] != '/'; p--)\n      {}\n    namePos = (unsigned)(p - s);\n    needPathCut = true;\n  }\n\n  if (IsPosixMode)\n  {\n    AString s;\n    \n    if (needPathCut)\n    {\n      const unsigned nameLen = item.Name.Len() - namePos;\n      if (   item.LinkFlag >= NLinkFlag::kNormal\n          && item.LinkFlag <= NLinkFlag::kDirectory\n          && namePos > 1\n          && nameLen != 0\n          // && IsPrefixAllowed\n          && item.IsMagic_Posix_ustar_00())\n      {\n        /* GNU TAR decoder supports prefix field, only if (magic)\n           signature matches 6-bytes \"ustar\\0\".\n           so here we use prefix field only in posix mode with posix signature */\n\n        allowPrefix = true;\n        // allowPrefix = false; // for debug\n        if (namePos <= kPrefixSize + 1 && nameLen <= kNameSize_Max)\n        {\n          needPathCut = false;\n          /* we will set Prefix and Glob_Name later, for such conditions:\n             if (!DOES_NAME_FIT_IN_FIELD(item.Name) && !needPathCut) */\n        }\n      }\n\n      if (needPathCut)\n        AddPaxLine(s, \"path\", item.Name);\n    }\n    \n    // AddPaxLine(s, \"testname\", AString(\"testval\")); // for debug\n    \n    if (item.LinkName.Len() > kNameSize_Max)\n      AddPaxLine(s, \"linkpath\", item.LinkName);\n    \n    const UInt64 kPaxSize_Limit = ((UInt64)1 << 33);\n    // const UInt64 kPaxSize_Limit = ((UInt64)1 << 1); // for debug\n    // bool zero_PackSize = false;\n    if (item.PackSize >= kPaxSize_Limit)\n    {\n      /* GNU TAR in pax mode sets PackSize = 0 in main record, if pack_size >= 8 GiB\n         But old 7-Zip doesn't detect \"size\" property from pax header.\n         So we write real size (>= 8 GiB) to main record in binary format,\n         and old 7-Zip can decode size correctly */\n      // zero_PackSize = true;\n      AString v;\n      v.Add_UInt64(item.PackSize);\n      AddPaxLine(s, \"size\", v);\n    }\n\n    /* GNU TAR encoder can set \"devmajor\" / \"devminor\" attributes,\n       but GNU TAR decoder doesn't parse \"devmajor\" / \"devminor\" */\n    if (item.DeviceMajor_Defined)\n      AddPax_UInt32_ifBig(s, \"devmajor\", item.DeviceMajor);\n    if (item.DeviceMinor_Defined)\n      AddPax_UInt32_ifBig(s, \"devminor\", item.DeviceMinor);\n\n    AddPax_UInt32_ifBig(s, \"uid\", item.UID);\n    AddPax_UInt32_ifBig(s, \"gid\", item.GID);\n    \n    const UInt64 kPax_MTime_Limit = ((UInt64)1 << 33);\n    const bool zero_MTime = (\n        item.MTime < 0 ||\n        item.MTime >= (Int64)kPax_MTime_Limit);\n\n    const CPaxTime &mtime = item.PaxTimes.MTime;\n    if (mtime.IsDefined())\n    {\n      bool needPax = false;\n      if (zero_MTime)\n        needPax = true;\n      else if (TimeOptions.NumDigitsMax > 0)\n        if (mtime.Ns != 0 ||\n            (mtime.NumDigits != 0 &&\n            TimeOptions.RemoveZeroMode == k_PaxTimeMode_DontRemoveZero))\n          needPax = true;\n      if (needPax)\n        AddPaxTime(s, \"mtime\", mtime, TimeOptions);\n    }\n    \n    if (item.PaxTimes.ATime.IsDefined())\n      AddPaxTime(s, \"atime\", item.PaxTimes.ATime, TimeOptions);\n    if (item.PaxTimes.CTime.IsDefined())\n      AddPaxTime(s, \"ctime\", item.PaxTimes.CTime, TimeOptions);\n\n    if (item.User.Len() > kUserNameSize)\n      AddPaxLine(s, \"uname\", item.User);\n    if (item.Group.Len() > kGroupNameSize)\n      AddPaxLine(s, \"gname\", item.Group);\n\n    /*\n    // for debug\n    AString a (\"11\"); for (int y = 0; y < (1 << 24); y++) AddPaxLine(s, \"temp\", a);\n    */\n\n    const unsigned paxSize = s.Len();\n    if (paxSize != 0)\n    {\n      CItem mi = item;\n      mi.LinkName.Empty();\n      // SparseBlocks will be ignored by Is_Sparse()\n      // mi.SparseBlocks.Clear();\n      //  we use \"PaxHeader/*\" for compatibility with previous 7-Zip decoder\n\n      // GNU TAR writes empty for these fields;\n      mi.User.Empty();\n      mi.Group.Empty();\n      mi.UID = 0;\n      mi.GID = 0;\n\n      mi.DeviceMajor_Defined = false;\n      mi.DeviceMinor_Defined = false;\n\n      mi.Name = \"PaxHeader/@PaxHeader\";\n      mi.Mode = 0644; // octal\n      if (zero_MTime)\n        mi.MTime = 0;\n      mi.LinkFlag = NLinkFlag::kPax;\n      // mi.LinkFlag = 'Z'; // for debug\n      mi.PackSize = paxSize;\n      // for (unsigned y = 0; y < 1; y++) { // for debug\n      RINOK(WriteHeaderReal(mi, true)) // isPax\n      RINOK(Write_Data_And_Residual(s, paxSize))\n      // } // for debug\n      /*\n        we can send (zero_MTime) for compatibility with gnu tar output.\n        we can send (zero_MTime = false) for better compatibility with old 7-Zip\n      */\n      // return WriteHeaderReal(item);\n      /*\n      false, // isPax\n      false, // zero_PackSize\n      false); // zero_MTime\n      */\n    }\n  }\n  else // !PosixMode\n  if (!DOES_NAME_FIT_IN_FIELD(item.Name) ||\n      !DOES_NAME_FIT_IN_FIELD(item.LinkName))\n  {\n    // here we can get all fields from main (item) or create new empty item\n    /*\n    CItem mi;\n    mi.SetDefaultWriteFields();\n    */\n    CItem mi = item;\n    mi.LinkName.Empty();\n    // SparseBlocks will be ignored by Is_Sparse()\n    // mi.SparseBlocks.Clear();\n    mi.Name = kLongLink;\n    // mi.Name = \"././@BAD_LONG_LINK_TEST\"; // for debug\n    // 21.07 : we set Mode and MTime props as in GNU TAR:\n    mi.Mode = 0644; // octal\n    mi.MTime = 0;\n\n    mi.User.Empty();\n    mi.Group.Empty();\n    /*\n      gnu tar sets \"root\" for such items:\n        uid_to_uname (0, &uname);\n        gid_to_gname (0, &gname);\n    */\n    /*\n    mi.User = \"root\";\n    mi.Group = \"root\";\n    */\n    mi.UID = 0;\n    mi.GID = 0;\n    mi.DeviceMajor_Defined = false;\n    mi.DeviceMinor_Defined = false;\n\n    \n    for (unsigned i = 0; i < 2; i++)\n    {\n      const AString *name;\n      // We suppose that GNU TAR also writes item for long link before item for LongName?\n      if (i == 0)\n      {\n        mi.LinkFlag = NLinkFlag::kGnu_LongLink;\n        name = &item.LinkName;\n      }\n      else\n      {\n        mi.LinkFlag = NLinkFlag::kGnu_LongName;\n        name = &item.Name;\n      }\n      if (DOES_NAME_FIT_IN_FIELD(*name))\n        continue;\n      // GNU TAR writes null character after NAME to file. We do same here:\n      const unsigned nameStreamSize = name->Len() + 1;\n      mi.PackSize = nameStreamSize;\n      // for (unsigned y = 0; y < 3; y++) { // for debug\n      RINOK(WriteHeaderReal(mi))\n      RINOK(Write_Data_And_Residual(name->Ptr(), nameStreamSize))\n      // }\n      \n      // for debug\n      /*\n      const unsigned kSize = (1 << 29) + 16;\n      CByteBuffer buf;\n      buf.Alloc(kSize);\n      memset(buf, 0, kSize);\n      memcpy(buf, name->Ptr(), name->Len());\n      const unsigned nameStreamSize = kSize;\n      mi.PackSize = nameStreamSize;\n      // for (unsigned y = 0; y < 3; y++) { // for debug\n      RINOK(WriteHeaderReal(mi));\n      RINOK(WriteBytes(buf, nameStreamSize));\n      RINOK(FillDataResidual(nameStreamSize));\n      */\n    }\n  }\n\n  // bool fals = false; if (fals) // for debug: for bit-to-bit output compatibility with GNU TAR\n\n  if (!DOES_NAME_FIT_IN_FIELD(item.Name))\n  {\n    const unsigned nameLen = item.Name.Len() - namePos;\n    if (!needPathCut)\n      Prefix.SetFrom(item.Name, namePos - 1);\n    else\n    {\n      Glob_Name = K_PREFIX_PATH_CUT \"/_pc_\";\n      \n      if (namePos == 0)\n        Glob_Name += \"root\";\n      else\n      {\n        Glob_Name += \"crc32/\";\n        char temp[12];\n        ConvertUInt32ToHex8Digits(CrcCalc(item.Name, namePos - 1), temp);\n        Glob_Name += temp;\n      }\n      \n      if (!allowPrefix || Glob_Name.Len() + 1 + nameLen <= kNameSize_Max)\n        Glob_Name.Add_Slash();\n      else\n      {\n        Prefix = Glob_Name;\n        Glob_Name.Empty();\n      }\n    }\n    Glob_Name.AddFrom(item.Name.Ptr(namePos), nameLen);\n  }\n\n  return WriteHeaderReal(item);\n}\n\n\nHRESULT COutArchive::Write_Data(const void *data, unsigned size)\n{\n  Pos += size;\n  return WriteStream(Stream, data, size);\n}\n\nHRESULT COutArchive::Write_AfterDataResidual(UInt64 dataSize)\n{\n  const unsigned v = ((unsigned)dataSize & (kRecordSize - 1));\n  if (v == 0)\n    return S_OK;\n  const unsigned rem = kRecordSize - v;\n  Byte buf[kRecordSize];\n  memset(buf, 0, rem);\n  return Write_Data(buf, rem);\n}\n\n\nHRESULT COutArchive::Write_Data_And_Residual(const void *data, unsigned size)\n{\n  RINOK(Write_Data(data, size))\n  return Write_AfterDataResidual(size);\n}\n\n\nHRESULT COutArchive::WriteFinishHeader()\n{\n  Byte record[kRecordSize];\n  memset(record, 0, kRecordSize);\n\n  const unsigned kNumFinishRecords = 2;\n\n  /* GNU TAR by default uses --blocking-factor=20 (512 * 20 = 10 KiB)\n     we also can use cluster alignment:\n  const unsigned numBlocks = (unsigned)(Pos / kRecordSize) + kNumFinishRecords;\n  const unsigned kNumClusterBlocks = (1 << 3); // 8 blocks = 4 KiB\n  const unsigned numFinishRecords = kNumFinishRecords + ((kNumClusterBlocks - numBlocks) & (kNumClusterBlocks - 1));\n  */\n  \n  for (unsigned i = 0; i < kNumFinishRecords; i++)\n  {\n    RINOK(Write_Data(record, kRecordSize))\n  }\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarOut.h",
    "content": "﻿// Archive/TarOut.h\n\n#ifndef ZIP7_INC_ARCHIVE_TAR_OUT_H\n#define ZIP7_INC_ARCHIVE_TAR_OUT_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../IStream.h\"\n\n#include \"TarItem.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nclass COutArchive\n{\n  CMyComPtr<ISequentialOutStream> Stream;\n\n  AString Glob_Name;\n  AString Prefix;\n\n  HRESULT WriteHeaderReal(const CItem &item, bool isPax = false\n      // , bool zero_PackSize = false\n      // , bool zero_MTime = false\n      );\n\n  HRESULT Write_Data(const void *data, unsigned size);\n  HRESULT Write_Data_And_Residual(const void *data, unsigned size);\n\npublic:\n  UInt64 Pos;\n  bool IsPosixMode;\n  // bool IsPrefixAllowed; // it's used only if (IsPosixMode == true)\n  CTimeOptions TimeOptions;\n\n  void Create(ISequentialOutStream *outStream)\n  {\n    Stream = outStream;\n  }\n  HRESULT WriteHeader(const CItem &item);\n  HRESULT Write_AfterDataResidual(UInt64 dataSize);\n  HRESULT WriteFinishHeader();\n\n  COutArchive():\n      Pos(0),\n      IsPosixMode(false)\n      // , IsPrefixAllowed(true)\n      {}\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarRegister.cpp",
    "content": "﻿// TarRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/RegisterArc.h\"\n\n#include \"TarHandler.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nstatic const Byte k_Signature[] = { 'u', 's', 't', 'a', 'r' };\n\nREGISTER_ARC_IO(\n  \"tar\", \"tar ova\", NULL, 0xEE,\n  k_Signature,\n  NFileHeader::kUstarMagic_Offset,\n    NArcInfoFlags::kStartOpen\n  | NArcInfoFlags::kSymLinks\n  | NArcInfoFlags::kHardLinks\n  | NArcInfoFlags::kMTime\n  | NArcInfoFlags::kMTime_Default\n  // | NArcInfoTimeFlags::kCTime\n  // | NArcInfoTimeFlags::kATime\n  , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kWindows)\n  | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix)\n  | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::k1ns)\n  | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kUnix)\n  , IsArc_Tar)\n \n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarUpdate.cpp",
    "content": "﻿// TarUpdate.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"TarOut.h\"\n#include \"TarUpdate.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nstatic void FILETIME_To_PaxTime(const FILETIME &ft, CPaxTime &pt)\n{\n  UInt32 ns;\n  pt.Sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, ns);\n  pt.Ns = ns * 100;\n  pt.NumDigits = 7;\n}\n\n\nHRESULT Prop_To_PaxTime(const NWindows::NCOM::CPropVariant &prop, CPaxTime &pt)\n{\n  pt.Clear();\n  if (prop.vt == VT_EMPTY)\n  {\n    // pt.Sec = 0;\n    return S_OK;\n  }\n  if (prop.vt != VT_FILETIME)\n    return E_INVALIDARG;\n  {\n    UInt32 ns;\n    pt.Sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(prop.filetime, ns);\n    ns *= 100;\n    pt.NumDigits = 7;\n    const unsigned prec = prop.wReserved1;\n    if (prec >= k_PropVar_TimePrec_Base)\n    {\n      pt.NumDigits = (int)(prec - k_PropVar_TimePrec_Base);\n      if (prop.wReserved2 < 100)\n        ns += prop.wReserved2;\n    }\n    pt.Ns = ns;\n    return S_OK;\n  }\n}\n\n\nstatic HRESULT GetTime(IStreamGetProp *getProp, UInt32 pid, CPaxTime &pt)\n{\n  pt.Clear();\n  NWindows::NCOM::CPropVariant prop;\n  RINOK(getProp->GetProperty(pid, &prop))\n  return Prop_To_PaxTime(prop, pt);\n}\n\n\nstatic HRESULT GetUser(IStreamGetProp *getProp,\n    UInt32 pidName, UInt32 pidId, AString &name, UInt32 &id,\n    UINT codePage, unsigned utfFlags)\n{\n  // printf(\"\\nGetUser\\n\");\n  // we keep  old values, if both   GetProperty() return VT_EMPTY\n  // we clear old values, if any of GetProperty() returns non-VT_EMPTY;\n  bool isSet = false;\n  {\n    NWindows::NCOM::CPropVariant prop;\n    RINOK(getProp->GetProperty(pidId, &prop))\n    if (prop.vt == VT_UI4)\n    {\n      isSet = true;\n      id = prop.ulVal;\n      name.Empty();\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  {\n    NWindows::NCOM::CPropVariant prop;\n    RINOK(getProp->GetProperty(pidName, &prop))\n    if (prop.vt == VT_BSTR)\n    {\n      const UString s = prop.bstrVal;\n      Get_AString_From_UString(s, name, codePage, utfFlags);\n      // printf(\"\\ngetProp->GetProperty(pidName, &prop) : %s\" , name.Ptr());\n      if (!isSet)\n        id = 0;\n    }\n    else if (prop.vt == VT_UI4)\n    {\n      id = prop.ulVal;\n      name.Empty();\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  return S_OK;\n}\n\n\n/*\nstatic HRESULT GetDevice(IStreamGetProp *getProp,\n    UInt32 &majo, UInt32 &mino, bool &majo_defined, bool &mino_defined)\n{\n  NWindows::NCOM::CPropVariant prop;\n  RINOK(getProp->GetProperty(kpidDevice, &prop));\n  if (prop.vt == VT_EMPTY)\n    return S_OK;\n  if (prop.vt != VT_UI8)\n    return E_INVALIDARG;\n  {\n    printf(\"\\nTarUpdate.cpp :: GetDevice()\\n\");\n    const UInt64 v = prop.uhVal.QuadPart;\n    majo = MY_dev_major(v);\n    mino = MY_dev_minor(v);\n    majo_defined = true;\n    mino_defined = true;\n  }\n  return S_OK;\n}\n*/\n\nstatic HRESULT GetDevice(IStreamGetProp *getProp,\n    UInt32 pid, UInt32 &id, bool &defined)\n{\n  defined = false;\n  NWindows::NCOM::CPropVariant prop;\n  RINOK(getProp->GetProperty(pid, &prop))\n  if (prop.vt == VT_EMPTY)\n    return S_OK;\n  if (prop.vt == VT_UI4)\n  {\n    id = prop.ulVal;\n    defined = true;\n    return S_OK;\n  }\n  return E_INVALIDARG;\n}\n\n\nHRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,\n    const CObjectVector<NArchive::NTar::CItemEx> &inputItems,\n    const CObjectVector<CUpdateItem> &updateItems,\n    const CUpdateOptions &options,\n    IArchiveUpdateCallback *updateCallback)\n{\n  COutArchive outArchive;\n  outArchive.Create(outStream);\n  outArchive.Pos = 0;\n  outArchive.IsPosixMode = options.PosixMode;\n  outArchive.TimeOptions = options.TimeOptions;\n\n  Z7_DECL_CMyComPtr_QI_FROM(IOutStream, outSeekStream, outStream)\n  Z7_DECL_CMyComPtr_QI_FROM(IStreamSetRestriction, setRestriction, outStream)\n  Z7_DECL_CMyComPtr_QI_FROM(IArchiveUpdateCallbackFile, opCallback, outStream)\n\n  if (outSeekStream)\n  {\n    /*\n    // for debug\n    Byte buf[1 << 14];\n    memset (buf, 0, sizeof(buf));\n    RINOK(outStream->Write(buf, sizeof(buf), NULL));\n    */\n    // we need real outArchive.Pos, if outSeekStream->SetSize() will be used.\n    RINOK(outSeekStream->Seek(0, STREAM_SEEK_CUR, &outArchive.Pos))\n  }\n  if (setRestriction)\n    RINOK(setRestriction->SetRestriction(0, 0))\n\n  UInt64 complexity = 0;\n\n  unsigned i;\n  for (i = 0; i < updateItems.Size(); i++)\n  {\n    const CUpdateItem &ui = updateItems[i];\n    if (ui.NewData)\n    {\n      if (ui.Size == (UInt64)(Int64)-1)\n        break;\n      complexity += ui.Size;\n    }\n    else\n      complexity += inputItems[(unsigned)ui.IndexInArc].Get_FullSize_Aligned();\n  }\n\n  if (i == updateItems.Size())\n    RINOK(updateCallback->SetTotal(complexity))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(updateCallback, true);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStreamLimited;\n  inStreamLimited->SetStream(inStream);\n\n  complexity = 0;\n\n  // const int kNumReduceDigits = -1; // for debug\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = lps->OutSize = complexity;\n    RINOK(lps->SetCur())\n\n    if (i == updateItems.Size())\n    {\n      if (outSeekStream && setRestriction)\n        RINOK(setRestriction->SetRestriction(0, 0))\n      return outArchive.WriteFinishHeader();\n    }\n\n    const CUpdateItem &ui = updateItems[i];\n    CItem item;\n  \n    if (ui.NewProps)\n    {\n      item.SetMagic_Posix(options.PosixMode);\n      item.Name = ui.Name;\n      item.User = ui.User;\n      item.Group = ui.Group;\n      item.UID = ui.UID;\n      item.GID = ui.GID;\n      item.DeviceMajor = ui.DeviceMajor;\n      item.DeviceMinor = ui.DeviceMinor;\n      item.DeviceMajor_Defined = ui.DeviceMajor_Defined;\n      item.DeviceMinor_Defined = ui.DeviceMinor_Defined;\n      \n      if (ui.IsDir)\n      {\n        item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;\n        item.PackSize = 0;\n      }\n      else\n      {\n        item.PackSize = ui.Size;\n        item.Set_LinkFlag_for_File(ui.Mode);\n      }\n\n      // 22.00\n      item.Mode = ui.Mode & ~(UInt32)MY_LIN_S_IFMT;\n      item.PaxTimes = ui.PaxTimes;\n      // item.PaxTimes.ReducePrecison(kNumReduceDigits); // for debug\n      item.MTime = ui.PaxTimes.MTime.GetSec();\n    }\n    else\n      item = inputItems[(unsigned)ui.IndexInArc];\n\n    AString symLink;\n    if (ui.NewData || ui.NewProps)\n    {\n      RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidSymLink, symLink,\n          options.CodePage, options.UtfFlags, true))\n      if (!symLink.IsEmpty())\n      {\n        item.LinkFlag = NFileHeader::NLinkFlag::kSymLink;\n        item.LinkName = symLink;\n      }\n    }\n\n    if (ui.NewData)\n    {\n      item.SparseBlocks.Clear();\n      item.PackSize = ui.Size;\n      item.Size = ui.Size;\n#if 0\n      if (ui.Size == (UInt64)(Int64)-1)\n        return E_INVALIDARG;\n#endif\n      CMyComPtr<ISequentialInStream> fileInStream;\n\n      bool needWrite = true;\n      \n      if (!symLink.IsEmpty())\n      {\n        item.PackSize = 0;\n        item.Size = 0;\n      }\n      else\n      {\n        const HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);\n        \n        if (res == S_FALSE)\n          needWrite = false;\n        else\n        {\n          RINOK(res)\n          \n          if (!fileInStream)\n          {\n            item.PackSize = 0;\n            item.Size = 0;\n          }\n          else\n          {\n            Z7_DECL_CMyComPtr_QI_FROM(IStreamGetProp, getProp, fileInStream)\n            if (getProp)\n            {\n              if (options.Write_MTime.Val) RINOK(GetTime(getProp, kpidMTime, item.PaxTimes.MTime))\n              if (options.Write_ATime.Val) RINOK(GetTime(getProp, kpidATime, item.PaxTimes.ATime))\n              if (options.Write_CTime.Val) RINOK(GetTime(getProp, kpidCTime, item.PaxTimes.CTime))\n\n              if (options.PosixMode)\n              {\n                /*\n                RINOK(GetDevice(getProp, item.DeviceMajor, item.DeviceMinor,\n                    item.DeviceMajor_Defined, item.DeviceMinor_Defined));\n                */\n                bool defined = false;\n                UInt32 val = 0;\n                RINOK(GetDevice(getProp, kpidDeviceMajor, val, defined))\n                if (defined)\n                {\n                  item.DeviceMajor = val;\n                  item.DeviceMajor_Defined = true;\n                  item.DeviceMinor = 0;\n                  item.DeviceMinor_Defined = false;\n                  RINOK(GetDevice(getProp, kpidDeviceMinor, item.DeviceMinor, item.DeviceMinor_Defined))\n                }\n              }\n\n              RINOK(GetUser(getProp, kpidUser,  kpidUserId,  item.User,  item.UID, options.CodePage, options.UtfFlags))\n              RINOK(GetUser(getProp, kpidGroup, kpidGroupId, item.Group, item.GID, options.CodePage, options.UtfFlags))\n\n              {\n                NWindows::NCOM::CPropVariant prop;\n                RINOK(getProp->GetProperty(kpidPosixAttrib, &prop))\n                if (prop.vt == VT_EMPTY)\n                  item.Mode =\n                    MY_LIN_S_IRWXO\n                  | MY_LIN_S_IRWXG\n                  | MY_LIN_S_IRWXU\n                  | (ui.IsDir ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG);\n                else if (prop.vt != VT_UI4)\n                  return E_INVALIDARG;\n                else\n                  item.Mode = prop.ulVal;\n                // 21.07 : we clear high file type bits as GNU TAR.\n                item.Set_LinkFlag_for_File(item.Mode);\n                item.Mode &= ~(UInt32)MY_LIN_S_IFMT;\n              }\n\n              {\n                NWindows::NCOM::CPropVariant prop;\n                RINOK(getProp->GetProperty(kpidSize, &prop))\n                if (prop.vt != VT_UI8)\n                  return E_INVALIDARG;\n                const UInt64 size = prop.uhVal.QuadPart;\n                // printf(\"\\nTAR after GetProperty(kpidSize size = %8d\\n\", (unsigned)size);\n                item.PackSize = size;\n                item.Size = size;\n              }\n              /*\n              printf(\"\\nNum digits = %d %d\\n\",\n                  (int)item.PaxTimes.MTime.NumDigits,\n                  (int)item.PaxTimes.MTime.Ns);\n              */\n            }\n            else\n            {\n              Z7_DECL_CMyComPtr_QI_FROM(IStreamGetProps, getProps, fileInStream)\n              if (getProps)\n              {\n                FILETIME mTime, aTime, cTime;\n                UInt64 size2;\n                if (getProps->GetProps(&size2,\n                    options.Write_CTime.Val ? &cTime : NULL,\n                    options.Write_ATime.Val ? &aTime : NULL,\n                    options.Write_MTime.Val ? &mTime : NULL,\n                    NULL) == S_OK)\n                {\n                  item.PackSize = size2;\n                  item.Size = size2;\n                  if (options.Write_MTime.Val) FILETIME_To_PaxTime(mTime, item.PaxTimes.MTime);\n                  if (options.Write_ATime.Val) FILETIME_To_PaxTime(aTime, item.PaxTimes.ATime);\n                  if (options.Write_CTime.Val) FILETIME_To_PaxTime(cTime, item.PaxTimes.CTime);\n                }\n              }\n            }\n          }\n\n          {\n            // we must request kpidHardLink after updateCallback->GetStream()\n            AString hardLink;\n            RINOK(GetPropString(updateCallback, ui.IndexInClient, kpidHardLink, hardLink,\n                options.CodePage, options.UtfFlags, true))\n            if (!hardLink.IsEmpty())\n            {\n              item.LinkFlag = NFileHeader::NLinkFlag::kHardLink;\n              item.LinkName = hardLink;\n              item.PackSize = 0;\n              item.Size = 0;\n              fileInStream.Release();\n            }\n          }\n        }\n      }\n\n      // item.PaxTimes.ReducePrecison(kNumReduceDigits); // for debug\n\n      if (ui.NewProps)\n        item.MTime = item.PaxTimes.MTime.GetSec();\n\n      if (needWrite)\n      {\n        if (fileInStream)\n        // if (item.PackSize == (UInt64)(Int64)-1)\n        if (item.Size == (UInt64)(Int64)-1)\n          return E_INVALIDARG;\n\n        const UInt64 headerPos = outArchive.Pos;\n        // item.PackSize = ((UInt64)1 << 33); // for debug\n\n        if (outSeekStream && setRestriction)\n          RINOK(setRestriction->SetRestriction(outArchive.Pos, (UInt64)(Int64)-1))\n\n        RINOK(outArchive.WriteHeader(item))\n        if (fileInStream)\n        {\n          for (unsigned numPasses = 0;; numPasses++)\n          {\n            // printf(\"\\nTAR numPasses = %d\" \" old size = %8d\\n\", numPasses, (unsigned)item.PackSize);\n            /* we support 2 attempts to write header:\n                pass-0: main pass:\n                pass-1: additional pass, if size_of_file and size_of_header are changed */\n            if (numPasses >= 2)\n            {\n              // opRes = NArchive::NUpdate::NOperationResult::kError_FileChanged;\n              // break;\n              return E_FAIL;\n            }\n            \n            const UInt64 dataPos = outArchive.Pos;\n            RINOK(copyCoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))\n            outArchive.Pos += copyCoder->TotalSize;\n            RINOK(outArchive.Write_AfterDataResidual(copyCoder->TotalSize))\n            // printf(\"\\nTAR after Code old size = %8d copyCoder->TotalSize = %8d \\n\", (unsigned)item.PackSize, (unsigned)copyCoder->TotalSize);\n            // if (numPasses >= 10) // for debug\n            if (copyCoder->TotalSize == item.PackSize)\n              break;\n            \n            if (opCallback)\n            {\n              RINOK(opCallback->ReportOperation(\n                  NEventIndexType::kOutArcIndex, (UInt32)ui.IndexInClient,\n                  NUpdateNotifyOp::kInFileChanged))\n            }\n            \n            if (!outSeekStream)\n              return E_FAIL;\n            const UInt64 nextPos = outArchive.Pos;\n            RINOK(outSeekStream->Seek(-(Int64)(nextPos - headerPos), STREAM_SEEK_CUR, NULL))\n            outArchive.Pos = headerPos;\n            item.PackSize = copyCoder->TotalSize;\n            \n            RINOK(outArchive.WriteHeader(item))\n            \n            // if (numPasses >= 10) // for debug\n            if (outArchive.Pos == dataPos)\n            {\n              const UInt64 alignedSize = nextPos - dataPos;\n              if (alignedSize != 0)\n              {\n                RINOK(outSeekStream->Seek((Int64)alignedSize, STREAM_SEEK_CUR, NULL))\n                outArchive.Pos += alignedSize;\n              }\n              break;\n            }\n            \n            // size of header was changed.\n            // we remove data after header and try new attempt, if required\n            Z7_DECL_CMyComPtr_QI_FROM(IInStream, fileSeekStream, fileInStream)\n            if (!fileSeekStream)\n              return E_FAIL;\n            RINOK(InStream_SeekToBegin(fileSeekStream))\n            RINOK(outSeekStream->SetSize(outArchive.Pos))\n            if (item.PackSize == 0)\n              break;\n          }\n        }\n      }\n      \n      complexity += item.PackSize;\n      fileInStream.Release();\n      RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))\n    }\n    else\n    {\n      // (ui.NewData == false)\n\n      if (opCallback)\n      {\n        RINOK(opCallback->ReportOperation(\n            NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,\n            NUpdateNotifyOp::kReplicate))\n      }\n\n      const CItemEx &existItem = inputItems[(unsigned)ui.IndexInArc];\n      UInt64 size, pos;\n      \n      if (ui.NewProps)\n      {\n        // memcpy(item.Magic, NFileHeader::NMagic::kEmpty, 8);\n        \n        if (!symLink.IsEmpty())\n        {\n          item.PackSize = 0;\n          item.Size = 0;\n        }\n        else\n        {\n          if (ui.IsDir == existItem.IsDir())\n            item.LinkFlag = existItem.LinkFlag;\n        \n          item.SparseBlocks = existItem.SparseBlocks;\n          item.Size = existItem.Size;\n          item.PackSize = existItem.PackSize;\n        }\n        \n        item.DeviceMajor_Defined = existItem.DeviceMajor_Defined;\n        item.DeviceMinor_Defined = existItem.DeviceMinor_Defined;\n        item.DeviceMajor = existItem.DeviceMajor;\n        item.DeviceMinor = existItem.DeviceMinor;\n        item.UID = existItem.UID;\n        item.GID = existItem.GID;\n        \n        RINOK(outArchive.WriteHeader(item))\n        size = existItem.Get_PackSize_Aligned();\n        pos = existItem.Get_DataPos();\n      }\n      else\n      {\n        size = existItem.Get_FullSize_Aligned();\n        pos = existItem.HeaderPos;\n      }\n\n      if (size != 0)\n      {\n        RINOK(InStream_SeekSet(inStream, pos))\n        inStreamLimited->Init(size);\n        if (outSeekStream && setRestriction)\n          RINOK(setRestriction->SetRestriction(0, 0))\n        // 22.00 : we copy Residual data from old archive to new archive instead of zeroing\n        RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))\n        if (copyCoder->TotalSize != size)\n          return E_FAIL;\n        outArchive.Pos += size;\n        // RINOK(outArchive.Write_AfterDataResidual(existItem.PackSize));\n        complexity += size;\n      }\n    }\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Tar/TarUpdate.h",
    "content": "﻿// TarUpdate.h\n\n#ifndef ZIP7_INC_TAR_UPDATE_H\n#define ZIP7_INC_TAR_UPDATE_H\n\n#include \"../IArchive.h\"\n\n#include \"TarItem.h\"\n\nnamespace NArchive {\nnamespace NTar {\n\nstruct CUpdateItem\n{\n  int IndexInArc;\n  unsigned IndexInClient;\n  UInt64 Size;\n  // Int64 MTime;\n  UInt32 Mode;\n  bool NewData;\n  bool NewProps;\n  bool IsDir;\n  bool DeviceMajor_Defined;\n  bool DeviceMinor_Defined;\n  UInt32 UID;\n  UInt32 GID;\n  UInt32 DeviceMajor;\n  UInt32 DeviceMinor;\n  AString Name;\n  AString User;\n  AString Group;\n\n  CPaxTimes PaxTimes;\n\n  CUpdateItem():\n      Size(0),\n      IsDir(false),\n      DeviceMajor_Defined(false),\n      DeviceMinor_Defined(false),\n      UID(0),\n      GID(0)\n      {}\n};\n\n\nstruct CUpdateOptions\n{\n  UINT CodePage;\n  unsigned UtfFlags;\n  bool PosixMode;\n  CBoolPair Write_MTime;\n  CBoolPair Write_ATime;\n  CBoolPair Write_CTime;\n  CTimeOptions TimeOptions;\n};\n\n\nHRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,\n    const CObjectVector<CItemEx> &inputItems,\n    const CObjectVector<CUpdateItem> &updateItems,\n    const CUpdateOptions &options,\n    IArchiveUpdateCallback *updateCallback);\n\nHRESULT GetPropString(IArchiveUpdateCallback *callback, UInt32 index, PROPID propId, AString &res,\n    UINT codePage, unsigned utfFlags, bool convertSlash);\n\nHRESULT Prop_To_PaxTime(const NWindows::NCOM::CPropVariant &prop, CPaxTime &pt);\n\nvoid Get_AString_From_UString(const UString &s, AString &res,\n    UINT codePage, unsigned utfFlags);\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Udf/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Udf/UdfHandler.cpp",
    "content": "﻿// UdfHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/RegisterArc.h\"\n#include \"../../Common/StreamObjects.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"UdfHandler.h\"\n\nnamespace NArchive {\nnamespace NUdf {\n\nstatic void UdfTimeToFileTime(const CTime &t, NWindows::NCOM::CPropVariant &prop)\n{\n  UInt64 numSecs;\n  const Byte *d = t.Data;\n  if (!NWindows::NTime::GetSecondsSince1601(t.GetYear(), d[4], d[5], d[6], d[7], d[8], numSecs))\n    return;\n  if (t.IsLocal())\n    numSecs = (UInt64)((Int64)numSecs - (Int64)((Int32)t.GetMinutesOffset() * 60));\n  const UInt32 m0 = d[9];\n  const UInt32 m1 = d[10];\n  const UInt32 m2 = d[11];\n  unsigned numDigits = 0;\n  UInt64 v = numSecs * 10000000;\n  if (m0 < 100 && m1 < 100 && m2 < 100)\n  {\n    v += m0 * 100000 + m1 * 1000 + m2 * 10;\n    numDigits = 6;\n  }\n  prop.SetAsTimeFrom_Ft64_Prec(v, k_PropVar_TimePrec_Base + numDigits);\n}\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidATime,\n  kpidCTime,\n  kpidChangeTime,\n  // kpidUserId,\n  // kpidGroupId,\n  // kpidPosixAttrib,\n  kpidLinks\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidUnpackVer,\n  kpidClusterSize,\n  kpidSectorSize,\n  kpidCTime,\n  kpidMTime,\n  kpidComment\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySize: prop = _archive.PhySize; break;\n\n    case kpidUnpackVer:\n    {\n      if (_archive.LogVols.Size() == 1)\n      {\n        UString s;\n        const CLogVol &vol = _archive.LogVols[0];\n        vol.DomainId.AddUdfVersionTo(s);\n        if (!s.IsEmpty())\n          prop = s;\n      }\n      break;\n    }\n    case kpidComment:\n    {\n      UString comment = _archive.GetComment();\n      if (!comment.IsEmpty())\n        prop = comment;\n      break;\n    }\n\n    case kpidClusterSize:\n      if (_archive.LogVols.Size() > 0)\n      {\n        UInt32 blockSize = _archive.LogVols[0].BlockSize;\n        unsigned i;\n        for (i = 1; i < _archive.LogVols.Size(); i++)\n          if (_archive.LogVols[i].BlockSize != blockSize)\n            break;\n        if (i == _archive.LogVols.Size())\n          prop = blockSize;\n      }\n      break;\n\n    case kpidSectorSize: prop = ((UInt32)1 << _archive.SecLogSize); break;\n\n    case kpidCTime:\n      if (_archive.LogVols.Size() == 1)\n      {\n        const CLogVol &vol = _archive.LogVols[0];\n        if (vol.FileSets.Size() >= 1)\n          UdfTimeToFileTime(vol.FileSets[0].RecordingTime, prop);\n      }\n      break;\n    case kpidMTime:\n      if (_archive.PrimeVols.Size() == 1)\n      {\n        const CPrimeVol &pv = _archive.PrimeVols[0];\n        UdfTimeToFileTime(pv.RecordingTime, prop);\n      }\n      break;\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_archive.Unsupported) v |= kpv_ErrorFlags_UnsupportedFeature;\n      if (_archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_archive.NoEndAnchor) v |= kpv_ErrorFlags_HeadersError;\n      prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nclass CProgressImp Z7_final: public CProgressVirt\n{\n  CMyComPtr<IArchiveOpenCallback> _callback;\n  UInt64 _numFiles;\n  UInt64 _numBytes;\npublic:\n  HRESULT SetTotal(UInt64 numBytes) Z7_override;\n  HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes) Z7_override;\n  HRESULT SetCompleted() Z7_override;\n  CProgressImp(IArchiveOpenCallback *callback): _callback(callback), _numFiles(0), _numBytes(0) {}\n};\n\nHRESULT CProgressImp::SetTotal(UInt64 numBytes)\n{\n  if (_callback)\n    return _callback->SetTotal(NULL, &numBytes);\n  return S_OK;\n}\n\nHRESULT CProgressImp::SetCompleted(UInt64 numFiles, UInt64 numBytes)\n{\n  _numFiles = numFiles;\n  _numBytes = numBytes;\n  return SetCompleted();\n}\n\nHRESULT CProgressImp::SetCompleted()\n{\n  if (_callback)\n    return _callback->SetCompleted(&_numFiles, &_numBytes);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    CProgressImp progressImp(callback);\n    RINOK(_archive.Open(stream, &progressImp))\n    bool showVolName = (_archive.LogVols.Size() > 1);\n    FOR_VECTOR (volIndex, _archive.LogVols)\n    {\n      const CLogVol &vol = _archive.LogVols[volIndex];\n      bool showFileSetName = (vol.FileSets.Size() > 1);\n      // showFileSetName = true; // for debug\n      FOR_VECTOR (fsIndex, vol.FileSets)\n      {\n        const CFileSet &fs = vol.FileSets[fsIndex];\n        for (unsigned i = ((showVolName || showFileSetName) ? 0 : 1); i < fs.Refs.Size(); i++)\n        {\n          CRef2 ref2;\n          ref2.Vol = volIndex;\n          ref2.Fs = fsIndex;\n          ref2.Ref = i;\n          _refs2.Add(ref2);\n        }\n      }\n    }\n    _inStream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _inStream.Release();\n  _archive.Clear();\n  _refs2.Clear();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _refs2.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  {\n    const CRef2 &ref2 = _refs2[index];\n    const CLogVol &vol = _archive.LogVols[ref2.Vol];\n    const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref];\n    const CFile &file = _archive.Files[ref.FileIndex];\n    const CItem &item = _archive.Items[file.ItemIndex];\n    switch (propID)\n    {\n      case kpidPath:  prop = _archive.GetItemPath(ref2.Vol, ref2.Fs, ref2.Ref,\n            _archive.LogVols.Size() > 1, vol.FileSets.Size() > 1); break;\n      case kpidIsDir:  prop = item.IsDir(); break;\n      case kpidSize:      if (!item.IsDir()) prop = (UInt64)item.Size; break;\n      case kpidPackSize:  if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break;\n      case kpidMTime:  UdfTimeToFileTime(item.MTime, prop); break;\n      case kpidATime:  UdfTimeToFileTime(item.ATime, prop); break;\n      case kpidCTime:\n        if (item.IsExtended)\n            UdfTimeToFileTime(item.CreateTime, prop);\n        break;\n      case kpidChangeTime:  UdfTimeToFileTime(item.AttribTime, prop); break;\n      // case kpidUserId: prop = item.Uid; break;\n      // case kpidGroupId: prop = item.Gid; break;\n      // case kpidPosixAttrib: prop = (UInt32)item.Permissions; break;\n      case kpidLinks: prop = (UInt32)item.FileLinkCount; break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  *stream = NULL;\n\n  const CRef2 &ref2 = _refs2[index];\n  const CLogVol &vol = _archive.LogVols[ref2.Vol];\n  const CRef &ref = vol.FileSets[ref2.Fs].Refs[ref2.Ref];\n  const CFile &file = _archive.Files[ref.FileIndex];\n  const CItem &item = _archive.Items[file.ItemIndex];\n  UInt64 size = item.Size;\n\n  if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || ! _archive.CheckItemExtents(ref2.Vol, item))\n    return E_NOTIMPL;\n\n  if (item.IsInline)\n  {\n    Create_BufInStream_WithNewBuffer(item.InlineData, stream);\n    return S_OK;\n  }\n\n  CExtentsStream *extentStreamSpec = new CExtentsStream();\n  CMyComPtr<ISequentialInStream> extentStream = extentStreamSpec;\n  \n  extentStreamSpec->Stream = _inStream;\n\n  UInt64 virtOffset = 0;\n  FOR_VECTOR (extentIndex, item.Extents)\n  {\n    const CMyExtent &extent = item.Extents[extentIndex];\n    UInt32 len = extent.GetLen();\n    if (len == 0)\n      continue;\n    if (size < len)\n      return S_FALSE;\n      \n    const unsigned partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex;\n    UInt32 logBlockNumber = extent.Pos;\n    const CPartition &partition = _archive.Partitions[partitionIndex];\n    UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) +\n      (UInt64)logBlockNumber * vol.BlockSize;\n      \n    CSeekExtent se;\n    se.Phy = offset;\n    se.Virt = virtOffset;\n    virtOffset += len;\n    extentStreamSpec->Extents.Add(se);\n\n    size -= len;\n  }\n  if (size != 0)\n    return S_FALSE;\n  CSeekExtent se;\n  se.Phy = 0;\n  se.Virt = virtOffset;\n  extentStreamSpec->Extents.Add(se);\n  extentStreamSpec->Init();\n  *stream = extentStream.Detach();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _refs2.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = (allFilesMode ? i : indices[i]);\n    const CRef2 &ref2 = _refs2[index];\n    const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref];\n    const CFile &file = _archive.Files[ref.FileIndex];\n    const CItem &item = _archive.Items[file.ItemIndex];\n    if (!item.IsDir())\n      totalSize += item.Size;\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  UInt64 currentTotalSize = 0;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStream;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = lps->OutSize = currentTotalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    \n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    const CRef2 &ref2 = _refs2[index];\n    const CRef &ref = _archive.LogVols[ref2.Vol].FileSets[ref2.Fs].Refs[ref2.Ref];\n    const CFile &file = _archive.Files[ref.FileIndex];\n    const CItem &item = _archive.Items[file.ItemIndex];\n\n    if (item.IsDir())\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n    currentTotalSize += item.Size;\n\n    if (!testMode && !realOutStream)\n      continue;\n\n    RINOK(extractCallback->PrepareOperation(askMode))\n    outStream->SetStream(realOutStream);\n    realOutStream.Release();\n    outStream->Init(item.Size);\n    Int32 opRes;\n    {\n      CMyComPtr<ISequentialInStream> udfInStream;\n      const HRESULT res = GetStream(index, &udfInStream);\n      if (res == E_NOTIMPL)\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      else if (res != S_OK)\n        opRes = NExtract::NOperationResult::kDataError;\n      else\n      {\n        RINOK(copyCoder.Interface()->Code(udfInStream, outStream, NULL, NULL, lps))\n        opRes = outStream->IsFinishedOK() ?\n            NExtract::NOperationResult::kOK:\n            NExtract::NOperationResult::kDataError;\n      }\n    }\n    outStream->ReleaseStream();\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic const UInt32 kIsoStartPos = 0x8000;\n\n//  5, { 0, 'N', 'S', 'R', '0' },\n\nstatic const Byte k_Signature[] =\n{\n  8,    0, 'B', 'E', 'A', '0', '1', 1, 0,\n  6,    1, 'C', 'D', '0', '0', '1'\n};\n\nREGISTER_ARC_I(\n  \"Udf\", \"udf iso img\", NULL, 0xE0,\n  k_Signature,\n  kIsoStartPos,\n  NArcInfoFlags::kMultiSignature |\n  NArcInfoFlags::kStartOpen,\n  IsArc_Udf)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Udf/UdfHandler.h",
    "content": "﻿// UdfHandler.h\n\n#ifndef ZIP7_INC_UDF_HANDLER_H\n#define ZIP7_INC_UDF_HANDLER_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../IArchive.h\"\n\n#include \"UdfIn.h\"\n\nnamespace NArchive {\nnamespace NUdf {\n\nstruct CRef2\n{\n  unsigned Vol;\n  unsigned Fs;\n  unsigned Ref;\n};\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\n  CRecordVector<CRef2> _refs2;\n  CMyComPtr<IInStream> _inStream;\n  CInArchive _archive;\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Udf/UdfIn.cpp",
    "content": "﻿// Archive/UdfIn.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Windows/PropVariantUtils.h\"\n\n#include \"../../Common/RegisterArc.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"UdfIn.h\"\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define G16(_offs_, dest) dest = Get16(p + (_offs_))\n#define G32(_offs_, dest) dest = Get32(p + (_offs_))\n#define G64(_offs_, dest) dest = Get64(p + (_offs_))\n\nnamespace NArchive {\nnamespace NUdf {\n\nstatic const unsigned kNumPartitionsMax = 64;\nstatic const unsigned kNumLogVolumesMax = 64;\nstatic const unsigned kNumRecursionLevelsMax = 1 << 10;\nstatic const unsigned kNumItemsMax = 1 << 27;\nstatic const unsigned kNumFilesMax = 1 << 28;\nstatic const unsigned kNumRefsMax = 1 << 28;\nstatic const UInt32 kNumExtentsMax = (UInt32)1 << 30;\nstatic const UInt64 kFileNameLengthTotalMax = (UInt64)1 << 33;\nstatic const UInt64 kInlineExtentsSizeMax = (UInt64)1 << 33;\n\n#define CRC16_INIT_VAL 0\n#define CRC16_UPDATE_BYTE(crc, b) ((UInt16)(g_Crc16Table[(((crc) >> 8) ^ (b)) & 0xFF] ^ ((crc) << 8)))\n\n#define kCrc16Poly 0x1021\nstatic UInt16 g_Crc16Table[256];\n\nstatic void Z7_FASTCALL Crc16GenerateTable(void)\n{\n  UInt32 i;\n  for (i = 0; i < 256; i++)\n  {\n    UInt32 r = (i << 8);\n    for (unsigned j = 0; j < 8; j++)\n      r = ((r << 1) ^ (kCrc16Poly & ((UInt32)0 - (r >> 15)))) & 0xFFFF;\n    g_Crc16Table[i] = (UInt16)r;\n  }\n}\n\nstatic UInt32 Z7_FASTCALL Crc16Calc(const void *data, size_t size)\n{\n  UInt32 v = CRC16_INIT_VAL;\n  const Byte *p = (const Byte *)data;\n  const Byte *pEnd = p + size;\n  for (; p != pEnd; p++)\n    v = CRC16_UPDATE_BYTE(v, *p);\n  return v;\n}\n\nstatic struct CCrc16TableInit { CCrc16TableInit() { Crc16GenerateTable(); } } g_Crc16TableInit;\n\n\n// ---------- ECMA Part 1 ----------\n\nvoid CDString::Parse(const Byte *p, unsigned size)\n{\n  Data.CopyFrom(p, size);\n}\n\nstatic UString ParseDString(const Byte *data, unsigned size)\n{\n  UString res;\n  if (size != 0)\n  {\n    wchar_t *p;\n    const Byte type = *data++;\n    size--;\n    if (type == 8)\n    {\n      p = res.GetBuf(size);\n      for (unsigned i = 0; i < size; i++)\n      {\n        const wchar_t c = data[i];\n        if (c == 0)\n          break;\n        *p++ = c;\n      }\n    }\n    else if (type == 16)\n    {\n      size &= ~(unsigned)1;\n      p = res.GetBuf(size / 2);\n      for (unsigned i = 0; i < size; i += 2)\n      {\n        const wchar_t c = GetBe16(data + i);\n        if (c == 0)\n          break;\n        *p++ = c;\n      }\n    }\n    else\n      return UString(\"[unknown]\");\n    *p = 0;\n    res.ReleaseBuf_SetLen((unsigned)(p - (const wchar_t *)res));\n  }\n  return res;\n}\n\nUString CDString32::GetString() const\n{\n  const unsigned size = Data[sizeof(Data) - 1];\n  return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1)));\n}\n\nUString CDString128::GetString() const\n{\n  const unsigned size = Data[sizeof(Data) - 1];\n  return ParseDString(Data, MyMin(size, (unsigned)(sizeof(Data) - 1)));\n}\n\nUString CDString::GetString() const { return ParseDString(Data, (unsigned)Data.Size()); }\n\nvoid CTime::Parse(const Byte *p) { memcpy(Data, p, sizeof(Data)); }\n\n\nstatic void AddCommentChars(UString &dest, const char *s, size_t size)\n{\n  for (size_t i = 0; i < size; i++)\n  {\n    char c = s[i];\n    if (c == 0)\n      break;\n    if (c < 0x20)\n      c = '_';\n    dest += (wchar_t)c;\n  }\n}\n\n\nvoid CRegId::Parse(const Byte *p)\n{\n  Flags = p[0];\n  memcpy(Id, p + 1, sizeof(Id));\n  memcpy(Suffix, p + 24, sizeof(Suffix));\n}\n\nvoid CRegId::AddCommentTo(UString &s) const\n{\n  AddCommentChars(s, Id, sizeof(Id));\n}\n\nvoid CRegId::AddUdfVersionTo(UString &s) const\n{\n  // use it only for \"Domain Identifier Suffix\" and \"UDF Identifier Suffix\"\n  // UDF 2.1.5.3\n  // Revision in hex (3 digits)\n  const Byte minor = Suffix[0];\n  const Byte major = Suffix[1];\n  if (major != 0 || minor != 0)\n  {\n    char temp[16];\n    ConvertUInt32ToHex(major, temp);\n    s += temp;\n    s.Add_Dot();\n    ConvertUInt32ToHex8Digits(minor, temp);\n    s += &temp[8 - 2];\n  }\n}\n\n\n// ---------- ECMA Part 3: Volume Structure ----------\n\nvoid CExtent::Parse(const Byte *p)\n{\n  /* Len shall be less than < 2^30.\n     Unless otherwise specified, the length shall be an integral multiple of the logical sector size.\n     If (Len == 0), no extent is specified and (Pos) shall contain 0 */\n  G32 (0, Len);\n  G32 (4, Pos);\n}\n\n\n// ECMA 3/7.2\n\nstruct CTag\n{\n  UInt16 Id;\n  // UInt16 Version;\n  // Byte Checksum;\n  // UInt16 SerialNumber;\n  // UInt16 Crc;\n  UInt16 CrcLen;\n  // UInt32 TagLocation; // the number of the logical sector\n  \n  HRESULT Parse(const Byte *p, size_t size);\n};\n\nHRESULT CTag::Parse(const Byte *p, size_t size)\n{\n  if (size < 16)\n    return S_FALSE;\n  {\n    unsigned sum = 0;\n    for (unsigned i = 0; i < 16; i++)\n      sum = sum + p[i];\n    if ((Byte)(sum - p[4]) != p[4] || p[5] != 0)\n      return S_FALSE;\n  }\n  Id = Get16(p);\n  const UInt16 Version = Get16(p + 2);\n  if (Version != 2 && Version != 3)\n    return S_FALSE;\n  // SerialNumber = Get16(p + 6);\n  const UInt32 crc = Get16(p + 8);\n  CrcLen = Get16(p + 10);\n  // TagLocation = Get32(p + 12);\n\n  if (size >= 16 + (size_t)CrcLen)\n    if (crc == Crc16Calc(p + 16, (size_t)CrcLen))\n      return S_OK;\n  return S_FALSE;\n}\n\n// ECMA 3/7.2.1\n\nenum EDescriptorType\n{\n  DESC_TYPE_SpoaringTable       = 0, // UDF\n  DESC_TYPE_PrimVol             = 1,\n  DESC_TYPE_AnchorVolPtr        = 2,\n  DESC_TYPE_VolPtr              = 3,\n  DESC_TYPE_ImplUseVol          = 4,\n  DESC_TYPE_Partition           = 5,\n  DESC_TYPE_LogicalVol          = 6,\n  DESC_TYPE_UnallocSpace        = 7,\n  DESC_TYPE_Terminating         = 8,\n  DESC_TYPE_LogicalVolIntegrity = 9,\n  DESC_TYPE_FileSet             = 256,\n  DESC_TYPE_FileId              = 257,\n  DESC_TYPE_AllocationExtent    = 258,\n  DESC_TYPE_Indirect            = 259,\n  DESC_TYPE_Terminal            = 260,\n  DESC_TYPE_File                = 261,\n  DESC_TYPE_ExtendedAttrHeader  = 262,\n  DESC_TYPE_UnallocatedSpaceEntry = 263,\n  DESC_TYPE_SpaceBitmap         = 264,\n  DESC_TYPE_PartitionIntegrity  = 265,\n  DESC_TYPE_ExtendedFile        = 266\n};\n\n\nvoid CLogBlockAddr::Parse(const Byte *p)\n{\n  G32 (0, Pos);\n  G16 (4, PartitionRef);\n}\n\nvoid CShortAllocDesc::Parse(const Byte *p)\n{\n  G32 (0, Len);\n  G32 (4, Pos);\n}\n\n/*\nvoid CADImpUse::Parse(const Byte *p)\n{\n  G16 (0, Flags);\n  G32 (2, UdfUniqueId);\n}\n*/\n\nvoid CLongAllocDesc::Parse(const Byte *p)\n{\n  G32 (0, Len);\n  Location.Parse(p + 4);\n  // memcpy(ImplUse, p + 10, sizeof(ImplUse));\n  // adImpUse.Parse(ImplUse);\n}\n\n\nvoid CPrimeVol::Parse(const Byte *p)\n{\n  // G32 (16, VolumeDescriptorSequenceNumber);\n  G32 (20, PrimaryVolumeDescriptorNumber);\n  VolumeId.Parse(p + 24);\n  G16 (56, VolumeSequenceNumber);\n  G16 (58, MaximumVolumeSequenceNumber);\n  // G16 (60, InterchangeLevel);\n  // G16 (62, MaximumInterchangeLevel);\n  // G32 (64, CharacterSetList)\n  // G32 (68, MaximumCharacterSetList)\n  VolumeSetId.Parse(p + 72);\n  // 200 64 Descriptor Character Set charspec (1/7.2.1)\n  // 264 64 Explanatory Character Set charspec (1/7.2.1)\n  // VolumeAbstract.Parse(p + 328);\n  // VolumeCopyrightNotice.Parse(p + 336);\n  ApplicationId.Parse(p + 344);\n  RecordingTime.Parse(p + 376);\n  ImplId.Parse(p + 388);\n  // 420 64 Implementation Use bytes\n  // G32 (484, PredecessorVolumeDescriptorSequenceLocation);\n  // G16 (488, Flags);\n}\n\n\n\nbool CInArchive::CheckExtent(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len) const\n{\n  const CLogVol &vol = LogVols[volIndex];\n  if (partitionRef >= vol.PartitionMaps.Size())\n    return false;\n  const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];\n  return ((UInt64)blockPos * vol.BlockSize + len) <= ((UInt64)partition.Len << SecLogSize);\n}\n\nbool CInArchive::CheckItemExtents(unsigned volIndex, const CItem &item) const\n{\n  FOR_VECTOR (i, item.Extents)\n  {\n    const CMyExtent &e = item.Extents[i];\n    if (!CheckExtent(volIndex, e.PartitionRef, e.Pos, e.GetLen()))\n      return false;\n  }\n  return true;\n}\n\nHRESULT CInArchive::Read(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len, Byte *buf)\n{\n  if (!CheckExtent(volIndex, partitionRef, blockPos, len))\n    return S_FALSE;\n  const CLogVol &vol = LogVols[volIndex];\n  const CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];\n  UInt64 offset = ((UInt64)partition.Pos << SecLogSize) + (UInt64)blockPos * vol.BlockSize;\n  RINOK(InStream_SeekSet(_stream, offset))\n  offset += len;\n  UpdatePhySize(offset);\n  const HRESULT res = ReadStream_FALSE(_stream, buf, len);\n  if (res == S_FALSE && offset > FileSize)\n    UnexpectedEnd = true;\n  return res;\n}\n\nHRESULT CInArchive::ReadLad(unsigned volIndex, const CLongAllocDesc &lad, Byte *buf)\n{\n  return Read(volIndex, lad.Location.PartitionRef, lad.Location.Pos, lad.GetLen(), (Byte *)buf);\n}\n\nHRESULT CInArchive::ReadFromFile(unsigned volIndex, const CItem &item, CByteBuffer &buf)\n{\n  if (item.Size >= (UInt32)1 << 30)\n    return S_FALSE;\n  if (item.IsInline)\n  {\n    buf = item.InlineData;\n    return S_OK;\n  }\n  buf.Alloc((size_t)item.Size);\n  size_t pos = 0;\n  FOR_VECTOR (i, item.Extents)\n  {\n    const CMyExtent &e = item.Extents[i];\n    const UInt32 len = e.GetLen();\n    RINOK(Read(volIndex, e.PartitionRef, e.Pos, len, (Byte *)buf + pos))\n    pos += len;\n  }\n  return S_OK;\n}\n\n\nvoid CIcbTag::Parse(const Byte *p)\n{\n  // G32 (0, PriorDirectNum);\n  // G16 (4, StrategyType);\n  // G16 (6, StrategyParam);\n  // G16 (8, MaxNumOfEntries);\n  FileType = p[11];\n  // ParentIcb.Parse(p + 12);\n  G16 (18, Flags);\n}\n\n\n// ECMA 4/14.9 File Entry\n// UDF FileEntry 2.3.6\n\n// ECMA 4/14.17 Extended File Entry\n\nvoid CItem::Parse(const Byte *p)\n{\n  // (-1) can be stored in Uid/Gid.\n  // G32 (36, Uid);\n  // G32 (40, Gid);\n  // G32 (44, Permissions);\n  G16 (48, FileLinkCount);\n  // RecordFormat = p[50];\n  // RecordDisplayAttr = p[51];\n  // G32 (52, RecordLen);\n  G64 (56, Size);\n  if (IsExtended)\n  {\n    // The sum of all Information Length fields for all streams of a file (including the default stream). If this file has no\n    // streams, the Object Size shall be equal to the Information Length.\n    // G64 (64, ObjectSize);\n    p += 8;\n  }\n  G64 (64, NumLogBlockRecorded);\n  ATime.Parse(p + 72);\n  MTime.Parse(p + 84);\n  if (IsExtended)\n  {\n    CreateTime.Parse(p + 96);\n    p += 12;\n  }\n  AttribTime.Parse(p + 96);\n  // G32 (108, CheckPoint);\n  /*\n  if (IsExtended)\n  {\n    // Get32(p + 112); // reserved\n    p += 4;\n  }\n  // ExtendedAttrIcb.Parse(p + 112);\n  if (IsExtended)\n  {\n    StreamDirectoryIcb.Parse(p + 128);\n    p += 16;\n  }\n  */\n  \n  // ImplId.Parse(p + 128);\n  // G64 (160, UniqueId);\n}\n\n\n// ECMA 4/14.4\n// UDF 2.3.4\n\n/*\nFile Characteristics:\nDeleted bit:\n  ECMA: If set to ONE, shall mean this File Identifier Descriptor\n        identifies a file that has been deleted;\n  UDF:  If the space for the file or directory is deallocated,\n        the implementation shall set the ICB field to zero.\n    ECMA 167 4/8.6 requires that the File Identifiers of all FIDs in a directory shall be unique.\n    The implementations shall follow these rules when a Deleted bit is set:\n    rewrire the compression ID of the File Identifier: 8 -> 254, 16 -> 255.\n*/\n\nstruct CFileId\n{\n  // UInt16 FileVersion;\n  Byte FileCharacteristics;\n  // CByteBuffer ImplUse;\n  CDString Id;\n  CLongAllocDesc Icb;\n\n  bool IsItLink_Dir    () const { return (FileCharacteristics & FILEID_CHARACS_Dir)     != 0; }\n  bool IsItLink_Deleted() const { return (FileCharacteristics & FILEID_CHARACS_Deleted) != 0; }\n  bool IsItLink_Parent () const { return (FileCharacteristics & FILEID_CHARACS_Parent)  != 0; }\n\n  size_t Parse(const Byte *p, size_t size);\n};\n\nsize_t CFileId::Parse(const Byte *p, size_t size)\n{\n  size_t processed = 0;\n  if (size < 38)\n    return 0;\n  CTag tag;\n  if (tag.Parse(p, size) != S_OK)\n    return 0;\n  if (tag.Id != DESC_TYPE_FileId)\n    return 0;\n  // FileVersion = Get16(p + 16);\n  // UDF: There shall be only one version of a file as specified below with the value being set to 1.\n\n  FileCharacteristics = p[18];\n  const unsigned idLen = p[19];\n  Icb.Parse(p + 20);\n  const unsigned impLen = Get16(p + 36);\n  if (size < 38 + idLen + impLen)\n    return 0;\n  processed = 38;\n  // ImplUse.CopyFrom(p + processed, impLen);\n  processed += impLen;\n  Id.Parse(p + processed, idLen);\n  processed += idLen;\n  // const size_t processed2 = processed;\n  for (;(processed & 3) != 0; processed++)\n    if (p[processed] != 0)\n      return 0;\n  // some program can create non-standard UDF file where CrcLen doesn't include Padding data\n  if ((size_t)tag.CrcLen + 16 != processed\n      // && (size_t)tag.CrcLen + 16 != processed2 // we can enable this check to support non-standard UDF\n      )\n    return 0;\n  return (processed <= size) ? processed : 0;\n}\n\n\n\nHRESULT CInArchive::ReadFileItem(unsigned volIndex, unsigned fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed)\n{\n  if (Files.Size() % 100 == 0)\n    RINOK(_progress->SetCompleted(Files.Size(), _processedProgressBytes))\n  if (numRecurseAllowed-- == 0)\n    return S_FALSE;\n  CFile &file = Files.Back();\n  const CLogVol &vol = LogVols[volIndex];\n  const unsigned partitionRef = lad.Location.PartitionRef;\n  if (partitionRef >= vol.PartitionMaps.Size())\n    return S_FALSE;\n  CPartition &partition = Partitions[vol.PartitionMaps[partitionRef].PartitionIndex];\n\n  const UInt32 key = lad.Location.Pos;\n  UInt32 value;\n  const UInt32 kRecursedErrorValue = (UInt32)(Int32)-1;\n  if (partition.Map.Find(key, value))\n  {\n    if (value == kRecursedErrorValue)\n      return S_FALSE;\n    file.ItemIndex = (int)(Int32)value;\n  }\n  else\n  {\n    value = Items.Size();\n    file.ItemIndex = (int)(Int32)value;\n    if (partition.Map.Set(key, kRecursedErrorValue))\n      return S_FALSE;\n    RINOK(ReadItem(volIndex, (int)fsIndex, lad, isDir, numRecurseAllowed))\n    if (!partition.Map.Set(key, value))\n      return S_FALSE;\n  }\n  return S_OK;\n}\n\n\n// (fsIndex = -1) means that it's metadata file\n\nHRESULT CInArchive::ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed)\n{\n  if (Items.Size() >= kNumItemsMax)\n    return S_FALSE;\n  CItem &item = Items.AddNew();\n  \n  const CLogVol &vol = LogVols[volIndex];\n \n  const size_t size = lad.GetLen();\n  if (size != vol.BlockSize)\n    return S_FALSE;\n\n  CByteBuffer buf(size);\n  RINOK(ReadLad(volIndex, lad, buf))\n\n  CTag tag;\n  const Byte *p = buf;\n  RINOK(tag.Parse(p, size))\n\n  item.IsExtended = (tag.Id == DESC_TYPE_ExtendedFile);\n  const size_t kExtendOffset = item.IsExtended ? 40 : 0;\n\n  if (size < kExtendOffset + 176)\n    return S_FALSE;\n  if (tag.Id != DESC_TYPE_File &&\n      tag.Id != DESC_TYPE_ExtendedFile)\n    return S_FALSE;\n\n  item.IcbTag.Parse(p + 16);\n\n  // maybe another FileType values are possible in rare cases.\n  // Shoud we ignore FileType here?\n  if (fsIndex < 0)\n  {\n    // if (item.IcbTag.FileType == ICB_FILE_TYPE_DIR) return S_FALSE;\n    if (item.IcbTag.FileType != ICB_FILE_TYPE_METADATA &&\n        item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_MIRROR &&\n        item.IcbTag.FileType != ICB_FILE_TYPE_METADATA_BITMAP)\n      return S_FALSE;\n  }\n  else if (\n      item.IcbTag.FileType != ICB_FILE_TYPE_DIR &&\n      item.IcbTag.FileType != ICB_FILE_TYPE_FILE &&\n      item.IcbTag.FileType != ICB_FILE_TYPE_REAL_TIME_FILE) // M2TS files in /BDMV/STREAM/ in Blu-ray movie\n    return S_FALSE;\n\n  item.Parse(p);\n\n  _processedProgressBytes += (UInt64)item.NumLogBlockRecorded * vol.BlockSize + size;\n\n  const UInt32 extendedAttrLen = Get32(p + 168 + kExtendOffset);\n  const UInt32 allocDescriptorsLen = Get32(p + 172 + kExtendOffset);\n\n  if ((extendedAttrLen & 3) != 0)\n    return S_FALSE;\n  size_t pos = 176 + kExtendOffset;\n  if (extendedAttrLen > size - pos)\n    return S_FALSE;\n  /*\n  if (extendedAttrLen != 16)\n  {\n    if (extendedAttrLen < 24)\n      return S_FALSE;\n    CTag attrTag;\n    RINOK(attrTag.Parse(p + pos, size));\n    if (attrTag.Id != DESC_TYPE_ExtendedAttrHeader)\n      return S_FALSE;\n    // UInt32 implAttrLocation = Get32(p + pos + 16);\n    // UInt32 applicationlAttrLocation = Get32(p + pos + 20);\n  }\n  */\n  pos += extendedAttrLen;\n\n  const int descType = item.IcbTag.GetDescriptorType();\n  if (allocDescriptorsLen > size - pos)\n    return S_FALSE;\n  if (descType == ICB_DESC_TYPE_INLINE)\n  {\n    item.IsInline = true;\n    item.InlineData.CopyFrom(p + pos, allocDescriptorsLen);\n  }\n  else\n  {\n    item.IsInline = false;\n    if (descType != ICB_DESC_TYPE_SHORT && descType != ICB_DESC_TYPE_LONG)\n      return S_FALSE;\n    for (UInt32 i = 0; i < allocDescriptorsLen;)\n    {\n      CMyExtent e;\n      if (descType == ICB_DESC_TYPE_SHORT)\n      {\n        if (i + 8 > allocDescriptorsLen)\n          return S_FALSE;\n        CShortAllocDesc sad;\n        sad.Parse(p + pos + i);\n        e.Pos = sad.Pos;\n        e.Len = sad.Len;\n        e.PartitionRef = lad.Location.PartitionRef;\n        i += 8;\n      }\n      else\n      {\n        if (i + 16 > allocDescriptorsLen)\n          return S_FALSE;\n        CLongAllocDesc ladNew;\n        ladNew.Parse(p + pos + i);\n        e.Pos = ladNew.Location.Pos;\n        e.PartitionRef = ladNew.Location.PartitionRef;\n        e.Len = ladNew.Len;\n        i += 16;\n      }\n      item.Extents.Add(e);\n    }\n  }\n\n  if (isDir != item.IcbTag.IsDir())\n    return S_FALSE;\n\n  if (item.IcbTag.IsDir())\n  {\n    if (fsIndex < 0)\n      return S_FALSE;\n\n    if (!item.CheckChunkSizes() || !CheckItemExtents(volIndex, item))\n      return S_FALSE;\n    CByteBuffer buf2;\n    RINOK(ReadFromFile(volIndex, item, buf2))\n    item.Size = 0;\n    item.Extents.ClearAndFree();\n    item.InlineData.Free();\n\n    const Byte *p2 = buf2;\n    size_t size2 = buf2.Size();\n    while (size2 != 0)\n    {\n      CFileId fileId;\n      {\n        const size_t cur = fileId.Parse(p2, size2);\n        if (cur == 0)\n          return S_FALSE;\n        p2 += cur;\n        size2 -= cur;\n      }\n      if (fileId.IsItLink_Parent())\n        continue;\n      if (fileId.IsItLink_Deleted())\n        continue;\n      {\n        CFile file;\n        // file.FileVersion = fileId.FileVersion;\n        // file.FileCharacteristics = fileId.FileCharacteristics;\n        // file.ImplUse = fileId.ImplUse;\n        file.Id = fileId.Id;\n        \n        _fileNameLengthTotal += file.Id.Data.Size();\n        if (_fileNameLengthTotal > kFileNameLengthTotalMax)\n          return S_FALSE;\n        \n        item.SubFiles.Add(Files.Size());\n        if (Files.Size() >= kNumFilesMax)\n          return S_FALSE;\n        Files.Add(file);\n        RINOK(ReadFileItem(volIndex, (unsigned)fsIndex, fileId.Icb,\n            fileId.IsItLink_Dir(), numRecurseAllowed))\n      }\n    }\n  }\n  else\n  {\n    if ((UInt32)item.Extents.Size() > kNumExtentsMax - _numExtents)\n      return S_FALSE;\n    _numExtents += item.Extents.Size();\n\n    if (item.InlineData.Size() > kInlineExtentsSizeMax - _inlineExtentsSize)\n      return S_FALSE;\n    _inlineExtentsSize += item.InlineData.Size();\n  }\n\n  return S_OK;\n}\n\n\nHRESULT CInArchive::FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed)\n{\n  if ((_numRefs & 0xFFF) == 0)\n  {\n    RINOK(_progress->SetCompleted())\n  }\n  if (numRecurseAllowed-- == 0)\n    return S_FALSE;\n  if (_numRefs >= kNumRefsMax)\n    return S_FALSE;\n  _numRefs++;\n  CRef ref;\n  ref.FileIndex = fileIndex;\n  ref.Parent = parent;\n  parent = (int)fs.Refs.Size();\n  fs.Refs.Add(ref);\n  const CItem &item = Items[Files[fileIndex].ItemIndex];\n  FOR_VECTOR (i, item.SubFiles)\n  {\n    RINOK(FillRefs(fs, item.SubFiles[i], parent, numRecurseAllowed))\n  }\n  return S_OK;\n}\n\n\nAPI_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size)\n{\n  UInt32 res = k_IsArc_Res_NO;\n  unsigned SecLogSize;\n  for (SecLogSize = 11;; SecLogSize -= 2)\n  {\n    if (SecLogSize < 9)\n      return res;\n    const UInt32 offset = (UInt32)256 << SecLogSize;\n    const UInt32 bufSize = (UInt32)1 << SecLogSize;\n    if (offset + bufSize > size)\n      res = k_IsArc_Res_NEED_MORE;\n    else\n    {\n      CTag tag;\n      if (tag.Parse(p + offset, bufSize) == S_OK)\n        if (tag.Id == DESC_TYPE_AnchorVolPtr)\n        {\n          if (Get32(p + offset + 12) == 256 &&  // TagLocation\n              tag.CrcLen >= 16)\n            return k_IsArc_Res_YES;\n        }\n    }\n  }\n}\n\n\nHRESULT CInArchive::Open2()\n{\n  Clear();\n  UInt64 fileSize;\n  RINOK(InStream_GetSize_SeekToEnd(_stream, fileSize))\n  FileSize = fileSize;\n\n  // Some UDFs contain additional pad zeros (2 KB).\n  // Seek to STREAM_SEEK_END for direct DVD reading can return 8 KB more, so we check last 16 KB.\n  // And when we read last block, result read size can be smaller than required size.\n\n  /*\n  const size_t kBufSize = 1 << 14;\n  Byte buf[kBufSize];\n  size_t readSize = (fileSize < kBufSize) ? (size_t)fileSize : kBufSize;\n  RINOK(InStream_SeekSet(_stream, fileSize - readSize))\n  RINOK(ReadStream(_stream, buf, &readSize));\n  size_t i = readSize;\n  for (;;)\n  {\n    const size_t kSecSizeMin = 1 << 8;\n    if (i < kSecSizeMin)\n      return S_FALSE;\n    i -= kSecSizeMin;\n    SecLogSize = (readSize - i < ((size_t)1 << 11)) ? 8 : 11;\n    CTag tag;\n    if (tag.Parse(buf + i, (1 << SecLogSize)) == S_OK)\n      if (tag.Id == DESC_TYPE_AnchorVolPtr)\n        break;\n  }\n  PhySize = fileSize;\n  CExtent extentVDS;\n  extentVDS.Parse(buf + i + 16);\n  */\n\n  /*\n  An Anchor Volume Descriptor Pointer structure shall be recorded in at\n  least 2 of the following 3 locations on the media:\n      Logical Sector 256.\n      Logical Sector (N - 256).\n      N\n  */\n\n  const size_t kBufSize = 1 << 11;\n  Byte buf[kBufSize];\n  \n  for (SecLogSize = 11;; SecLogSize -= 2)\n  {\n    // Windows 10 uses unusual (SecLogSize = 9)\n    if (SecLogSize < 9)\n      return S_FALSE;\n    const UInt32 offset = (UInt32)256 << SecLogSize;\n    if (offset >= fileSize)\n      continue;\n    RINOK(InStream_SeekSet(_stream, offset))\n    const size_t bufSize = (size_t)1 << SecLogSize;\n    size_t readSize = bufSize;\n    RINOK(ReadStream(_stream, buf, &readSize))\n    if (readSize == bufSize)\n    {\n      CTag tag;\n      if (tag.Parse(buf, readSize) == S_OK)\n        if (tag.Id == DESC_TYPE_AnchorVolPtr)\n        {\n          if (Get32(buf + 12) == 256 &&\n            tag.CrcLen >= 16) // TagLocation\n            break;\n        }\n    }\n  }\n  \n  PhySize = (UInt32)(256 + 1) << SecLogSize;\n  IsArc = true;\n\n  // UDF 2.2.3  AnchorVolumeDescriptorPointer\n\n  CExtent extentVDS;\n  extentVDS.Parse(buf + 16);\n  {\n    CExtent extentVDS2;\n    extentVDS2.Parse(buf + 24);\n    UpdatePhySize(extentVDS);\n    UpdatePhySize(extentVDS2);\n  }\n\n  for (UInt32 location = 0; ; location++)\n  {\n    if (location >= (extentVDS.Len >> SecLogSize))\n      return S_FALSE;\n\n    const size_t bufSize = (size_t)1 << SecLogSize;\n    {\n      const UInt64 offs = ((UInt64)extentVDS.Pos + location) << SecLogSize;\n      RINOK(InStream_SeekSet(_stream, offs))\n      const HRESULT res = ReadStream_FALSE(_stream, buf, bufSize);\n      if (res == S_FALSE && offs + bufSize > FileSize)\n        UnexpectedEnd = true;\n      RINOK(res)\n    }\n\n    CTag tag;\n    RINOK(tag.Parse(buf, bufSize))\n\n    if (tag.Id == DESC_TYPE_Terminating)\n      break;\n\n    if (tag.Id == DESC_TYPE_PrimVol)\n    {\n      CPrimeVol &pm = PrimeVols.AddNew();\n      pm.Parse(buf);\n      continue;\n    }\n\n    if (tag.Id == DESC_TYPE_Partition)\n    {\n      // Partition Descriptor\n      // ECMA 3/10.5\n      // UDF 2.2.14\n      if (Partitions.Size() >= kNumPartitionsMax)\n        return S_FALSE;\n      CPartition partition;\n      // const UInt32 volDescSeqNumer = Get32(buf + 16);\n      partition.Flags = Get16(buf + 20);\n      partition.Number = Get16(buf + 22);\n      partition.ContentsId.Parse(buf + 24);\n      \n      // memcpy(partition.ContentsUse, buf + 56, sizeof(partition.ContentsUse));\n      // ContentsUse contains Partition Header Description.\n      // ECMA 4/14.3\n      // UDF PartitionHeaderDescriptor 2.3.3\n\n      partition.AccessType = Get32(buf + 184);\n      partition.Pos = Get32(buf + 188);\n      partition.Len = Get32(buf + 192);\n      partition.ImplId.Parse(buf + 196);\n      // memcpy(partition.ImplUse, buf + 228, sizeof(partition.ImplUse));\n\n      PRF(printf(\"\\nPartition number = %2d   pos = %d   len = %d\", partition.Number, partition.Pos, partition.Len));\n      Partitions.Add(partition);\n      continue;\n    }\n    \n    if (tag.Id == DESC_TYPE_LogicalVol)\n    {\n      /* Logical Volume Descriptor\n          ECMA 3/10.6\n          UDF 2.60 2.2.4 */\n\n      if (LogVols.Size() >= kNumLogVolumesMax)\n        return S_FALSE;\n      CLogVol &vol = LogVols.AddNew();\n\n      vol.Id.Parse(buf + 84);\n      vol.BlockSize = Get32(buf + 212);\n      if (vol.BlockSize != ((UInt32)1 << SecLogSize))\n      {\n        // UDF 2.2.4.2 LogicalBlockSize\n        // UDF probably doesn't allow different sizes\n        return S_FALSE;\n      }\n      /*\n      if (vol.BlockSize < 512 || vol.BlockSize > ((UInt32)1 << 30))\n        return S_FALSE;\n      */\n\n      vol.DomainId.Parse(buf + 216);\n\n      // ECMA 4/3.1\n      // UDF 2.2.4.4 LogicalVolumeContentsUse\n      /* the extent in which the first File Set Descriptor Sequence\n         of the logical volume is recorded */\n      vol.FileSetLocation.Parse(buf + 248);\n      // memcpy(vol.ContentsUse, buf + 248, sizeof(vol.ContentsUse));\n\n      vol.ImplId.Parse(buf + 272);\n      // memcpy(vol.ImplUse, buf + 304, sizeof(vol.ImplUse));\n      // vol.IntegritySequenceExtent.Parse(buf + 432);\n\n      const UInt32 mapTableLen = Get32(buf + 264);\n      const UInt32 numPartitionMaps = Get32(buf + 268);\n      if (numPartitionMaps > kNumPartitionsMax)\n        return S_FALSE;\n\n      PRF(printf(\"\\nLogicalVol numPartitionMaps = %2d\", numPartitionMaps));\n\n      size_t pos = 440;\n      if (mapTableLen > bufSize - pos)\n        return S_FALSE;\n      const size_t posLimit = pos + mapTableLen;\n      \n      for (UInt32 i = 0; i < numPartitionMaps; i++)\n      {\n        // ECMA 3/10.7 Partition maps\n        if (pos + 2 > posLimit)\n          return S_FALSE;\n        CPartitionMap pm;\n        pm.Type = buf[pos + 0];\n        // pm.Length = buf[pos + 1];\n        const Byte len = buf[pos + 1];\n        if (pos + len > posLimit)\n          return S_FALSE;\n        \n        // memcpy(pm.Data, buf + pos + 2, pm.Length - 2);\n        if (pm.Type == 1)\n        {\n          // ECMA 3/10.7.2\n          if (len != 6)\n            return S_FALSE;\n          pm.VolumeSequenceNumber = Get16(buf + pos + 2);\n          pm.PartitionNumber = Get16(buf + pos + 4);\n          PRF(printf(\"\\nPartitionMap type 1 PartitionNumber = %2d\", pm.PartitionNumber));\n        }\n        else if (pm.Type == 2)\n        {\n          if (len != 64)\n            return S_FALSE;\n          /* ECMA 10.7.3 / Type 2 Partition Map\n             62 bytes: Partition Identifier. */\n\n          /* UDF\n              2.2.8   \"*UDF Virtual Partition\"\n              2.2.9   \"*UDF Sparable Partition\"\n              2.2.10  \"*UDF Metadata Partition\"\n          */\n\n          if (Get16(buf + pos + 2) != 0) // reserved\n            return S_FALSE;\n\n          pm.PartitionTypeId.Parse(buf + pos + 4);\n          pm.VolumeSequenceNumber = Get16(buf + pos + 36);\n          pm.PartitionNumber = Get16(buf + pos + 38);\n\n          if (memcmp(pm.PartitionTypeId.Id, \"*UDF Metadata Partition\", 23) != 0)\n            return S_FALSE;\n\n          // UDF 2.2.10 Metadata Partition Map\n          pm.MetadataFileLocation = Get32(buf + pos + 40);\n          // pm.MetadataMirrorFileLocation = Get32(buf + pos + 44);\n          // pm.MetadataBitmapFileLocation = Get32(buf + pos + 48);\n          // pm.AllocationUnitSize = Get32(buf + pos + 52);\n          // pm.AlignmentUnitSize = Get16(buf + pos + 56);\n          // pm.Flags = buf[pos + 58];\n\n          PRF(printf(\"\\nPartitionMap type 2 PartitionNumber = %2d\", pm.PartitionNumber));\n          // Unsupported = true;\n          // return S_FALSE;\n        }\n        else\n          return S_FALSE;\n        pos += len;\n        vol.PartitionMaps.Add(pm);\n      }\n      continue;\n    }\n    \n    /*\n    if (tag.Id == DESC_TYPE_UnallocSpace)\n    {\n      // UInt32 volDescSeqNumer = Get32(buf + 16);\n      const UInt32 numAlocDescs = Get32(buf + 20);\n      // we need examples for (numAlocDescs != 0) case\n      if (numAlocDescs > (bufSize - 24) / 8)\n        return S_FALSE;\n      for (UInt32 i = 0; i < numAlocDescs; i++)\n      {\n        CExtent e;\n        e.Parse(buf + 24 + i * 8);\n      }\n      continue;\n    }\n    else\n      continue;\n    */\n  }\n\n  UInt64 totalSize = 0;\n\n  unsigned volIndex;\n  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)\n  {\n    CLogVol &vol = LogVols[volIndex];\n    FOR_VECTOR (pmIndex, vol.PartitionMaps)\n    {\n      CPartitionMap &pm = vol.PartitionMaps[pmIndex];\n      for (unsigned i = 0;; i++)\n      {\n        if (i == Partitions.Size())\n          return S_FALSE;\n        CPartition &part = Partitions[i];\n        if (part.Number == pm.PartitionNumber)\n        {\n          pm.PartitionIndex = i;\n          if (pm.Type == 2)\n            break;\n          \n          /*\n          if (part.VolIndex >= 0)\n          {\n            // it's for 2.60. Fix it\n            if (part.VolIndex != (int)volIndex)\n              return S_FALSE;\n            // return S_FALSE;\n          }\n          part.VolIndex = volIndex;\n          */\n\n          totalSize += (UInt64)part.Len << SecLogSize;\n          break;\n        }\n      }\n    }\n  }\n\n  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)\n  {\n    CLogVol &vol = LogVols[volIndex];\n    FOR_VECTOR (pmIndex, vol.PartitionMaps)\n    {\n      CPartitionMap &pm = vol.PartitionMaps[pmIndex];\n      if (pm.Type != 2)\n        continue;\n\n      {\n        CLongAllocDesc lad;\n        lad.Len = vol.BlockSize;\n        lad.Location.Pos = pm.MetadataFileLocation;\n        // lad.Location.Pos = pm.MetadataMirrorFileLocation;\n\n        lad.Location.PartitionRef = (UInt16)pmIndex;\n\n        /* we need correct PartitionMaps[lad.Location.PartitionRef].PartitionIndex.\n           so we can use pmIndex or find (Type==1) PartitionMap */\n        FOR_VECTOR (pmIndex2, vol.PartitionMaps)\n        {\n          const CPartitionMap &pm2 = vol.PartitionMaps[pmIndex2];\n          if (pm2.PartitionNumber == pm.PartitionNumber && pm2.Type == 1)\n          {\n            lad.Location.PartitionRef = (UInt16)pmIndex2;\n            break;\n          }\n        }\n        \n        RINOK(ReadItem(volIndex,\n            -1, // (fsIndex = -1) means that it's metadata\n            lad,\n            false, // isDir\n            1)) // numRecurseAllowed\n      }\n      {\n        const CItem &item = Items.Back();\n        if (!CheckItemExtents(volIndex, item))\n          return S_FALSE;\n        if (item.Extents.Size() != 1)\n        {\n          if (item.Extents.Size() < 1)\n            return S_FALSE;\n          /* Windows 10 writes empty record item.Extents[1].\n             we ignore such extent here */\n          for (unsigned k = 1; k < item.Extents.Size(); k++)\n          {\n            const CMyExtent &e = item.Extents[k];\n            if (e.GetLen() != 0)\n              return S_FALSE;\n          }\n        }\n\n        const CMyExtent &e = item.Extents[0];\n        const CPartition &part = Partitions[pm.PartitionIndex];\n        CPartition mp = part;\n        mp.IsMetadata = true;\n        // mp.Number = part.Number;\n        mp.Pos = part.Pos + e.Pos;\n        mp.Len = e.Len >> SecLogSize;\n        pm.PartitionIndex = Partitions.Add(mp);\n      }\n      // Items.DeleteBack(); // we can delete that metadata item\n\n      /*\n      // short version of code to read metadata file.\n      RINOK(CInArchive::Read(volIndex, pmIndex, pm.MetadataFileLocation, 224, buf));\n      CTag tag;\n      RINOK(tag.Parse(buf, 224));\n      if (tag.Id != DESC_TYPE_ExtendedFile)\n        return S_FALSE;\n      CShortAllocDesc sad;\n      sad.Parse(buf + 216);\n      const CPartition &part = Partitions[pm.PartitionIndex];\n      CPartition mp = part;\n      mp.IsMetadata = true;\n      // mp.Number = part.Number;\n      mp.Pos = part.Pos + sad.Pos;\n      mp.Len = sad.Len >> SecLogSize;\n      pm.PartitionIndex = Partitions.Add(mp);\n      */\n    }\n  }\n\n  RINOK(_progress->SetTotal(totalSize))\n\n  PRF(printf(\"\\n Read files\"));\n\n  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)\n  {\n    CLogVol &vol = LogVols[volIndex];\n\n    PRF(printf(\"\\nLogVol %2d\", volIndex));\n\n    CLongAllocDesc nextExtent = vol.FileSetLocation;\n    // while (nextExtent.ExtentLen != 0)\n    // for (int i = 0; i < 1; i++)\n    {\n      if (nextExtent.GetLen() < 512)\n        return S_FALSE;\n      CByteBuffer buf2(nextExtent.GetLen());\n      RINOK(ReadLad(volIndex, nextExtent, buf2))\n      const Byte *p = buf2;\n      const size_t size = nextExtent.GetLen();\n\n      CTag tag;\n      RINOK(tag.Parse(p, size))\n\n      /*\n      // commented in 22.01\n      if (tag.Id == DESC_TYPE_ExtendedFile)\n      {\n        // ECMA 4 / 14.17\n        // 2.60 ??\n        return S_FALSE;\n      }\n      */\n\n      if (tag.Id != DESC_TYPE_FileSet)\n        return S_FALSE;\n      \n      PRF(printf(\"\\n FileSet\"));\n      CFileSet fs;\n      fs.RecordingTime.Parse(p + 16);\n      // fs.InterchangeLevel = Get16(p + 18);\n      // fs.MaxInterchangeLevel = Get16(p + 20);\n      fs.FileSetNumber = Get32(p + 40);\n      fs.FileSetDescNumber = Get32(p + 44);\n      \n      fs.LogicalVolumeId.Parse(p + 112);\n      fs.Id.Parse(p + 304);\n      fs.CopyrightId.Parse(p + 336);\n      fs.AbstractId.Parse(p + 368);\n      \n      fs.RootDirICB.Parse(p + 400);\n      fs.DomainId.Parse(p + 416);\n      \n      // fs.SystemStreamDirICB.Parse(p + 464);\n      \n      vol.FileSets.Add(fs);\n\n      // nextExtent.Parse(p + 448);\n    }\n\n    FOR_VECTOR (fsIndex, vol.FileSets)\n    {\n      CFileSet &fs = vol.FileSets[fsIndex];\n      const unsigned fileIndex = Files.Size();\n      Files.AddNew();\n      RINOK(ReadFileItem(volIndex, fsIndex, fs.RootDirICB,\n          true, // isDir\n          kNumRecursionLevelsMax))\n      RINOK(FillRefs(fs, fileIndex, -1, kNumRecursionLevelsMax))\n    }\n  }\n\n\n  for (volIndex = 0; volIndex < LogVols.Size(); volIndex++)\n  {\n    const CLogVol &vol = LogVols[volIndex];\n    // bool showFileSetName = (vol.FileSets.Size() > 1);\n    FOR_VECTOR (fsIndex, vol.FileSets)\n    {\n      const CFileSet &fs = vol.FileSets[fsIndex];\n      for (unsigned i =\n          // ((showVolName || showFileSetName) ? 0 : 1)\n            0; i < fs.Refs.Size(); i++)\n      {\n        const CRef &ref = vol.FileSets[fsIndex].Refs[i];\n        const CFile &file = Files[ref.FileIndex];\n        const CItem &item = Items[file.ItemIndex];\n        UInt64 size = item.Size;\n\n        if (!item.IsRecAndAlloc() || !item.CheckChunkSizes() || !CheckItemExtents(volIndex, item))\n          continue;\n\n        FOR_VECTOR (extentIndex, item.Extents)\n        {\n          const CMyExtent &extent = item.Extents[extentIndex];\n          const UInt32 len = extent.GetLen();\n          if (len == 0)\n            continue;\n          if (size < len)\n            break;\n          \n          const unsigned partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex;\n          const UInt32 logBlockNumber = extent.Pos;\n          const CPartition &partition = Partitions[partitionIndex];\n          const UInt64 offset = ((UInt64)partition.Pos << SecLogSize) +\n              (UInt64)logBlockNumber * vol.BlockSize;\n          UpdatePhySize(offset + len);\n        }\n      }\n    }\n  }\n\n  {\n    const UInt32 secMask = ((UInt32)1 << SecLogSize) - 1;\n    PhySize = (PhySize + secMask) & ~(UInt64)secMask;\n  }\n  \n  NoEndAnchor = true;\n\n  if (PhySize < fileSize)\n  {\n    UInt64 rem = fileSize - PhySize;\n    const size_t secSize = (size_t)1 << SecLogSize;\n\n    RINOK(InStream_SeekSet(_stream, PhySize))\n\n    // some UDF images contain ZEROs before \"Anchor Volume Descriptor Pointer\" at the end\n\n    for (unsigned sec = 0; sec < 1024; sec++)\n    {\n      if (rem == 0)\n        break;\n      \n      size_t readSize = secSize;\n      if (readSize > rem)\n        readSize = (size_t)rem;\n      \n      RINOK(ReadStream(_stream, buf, &readSize))\n      \n      if (readSize == 0)\n        break;\n      \n      // some udf contain many EndAnchors\n      if (readSize == secSize /* && NoEndAnchor */)\n      {\n        CTag tag;\n        if (tag.Parse(buf, readSize) == S_OK\n            && tag.Id == DESC_TYPE_AnchorVolPtr\n            && Get32(buf + 12) == (UInt32)((fileSize - rem) >> SecLogSize))\n        {\n          NoEndAnchor = false;\n          rem -= readSize;\n          PhySize = fileSize - rem;\n          continue;\n        }\n      }\n      \n      size_t i;\n      for (i = 0; i < readSize && buf[i] == 0; i++);\n      if (i != readSize)\n        break;\n      rem -= readSize;\n    }\n\n    if (rem == 0)\n      PhySize = fileSize;\n  }\n\n  return S_OK;\n}\n\n\nHRESULT CInArchive::Open(IInStream *inStream, CProgressVirt *progress)\n{\n  _progress = progress;\n  _stream = inStream;\n  HRESULT res = Open2();\n  if (res == S_FALSE && IsArc && !UnexpectedEnd)\n    Unsupported = true;\n  return res;\n\n  /*\n  HRESULT res;\n  try\n  {\n    res = Open2();\n  }\n  catch(...)\n  {\n    // Clear();\n    // res = S_FALSE;\n    _stream.Release();\n    throw;\n  }\n  _stream.Release();\n  return res;\n  */\n}\n\nvoid CInArchive::Clear()\n{\n  IsArc = false;\n  Unsupported = false;\n  UnexpectedEnd = false;\n  NoEndAnchor = false;\n\n  PhySize = 0;\n  FileSize = 0;\n\n  Partitions.Clear();\n  LogVols.Clear();\n  PrimeVols.Clear();\n  Items.Clear();\n  Files.Clear();\n  _fileNameLengthTotal = 0;\n  _numRefs = 0;\n  _numExtents = 0;\n  _inlineExtentsSize = 0;\n  _processedProgressBytes = 0;\n}\n\n\nstatic const char * const g_PartitionTypes[] =\n{\n    \"Pseudo-Overwritable\" // UDF\n  , \"Read-Only\"\n  , \"Write-Once\"\n  , \"Rewritable\"\n  , \"Overwritable\"\n};\n\n\nstatic void AddComment_Align(UString &s)\n{\n  s += \"  \";\n}\n\nstatic void AddComment_PropName(UString &s, const char *name)\n{\n  AddComment_Align(s);\n  s += name;\n  s += \": \";\n}\n\nstatic void AddComment_UInt32(UString &s, const char *name, UInt32 val)\n{\n  AddComment_PropName(s, name);\n  s.Add_UInt32(val);\n  s.Add_LF();\n}\n\nstatic void AddComment_UInt32_2(UString &s, const char *name, UInt32 val)\n{\n  AddComment_Align(s);\n  AddComment_UInt32(s, name, val);\n}\n\n\nstatic void AddComment_UInt64(UString &s, const char *name, UInt64 val)\n{\n  AddComment_PropName(s, name);\n  s.Add_UInt64(val);\n  s.Add_LF();\n}\n\nstatic void AddComment_RegId(UString &s, const char *name, const CRegId &ri)\n{\n  AddComment_PropName(s, name);\n  ri.AddCommentTo(s);\n  s.Add_LF();\n}\n\nstatic void AddComment_RegId_Domain(UString &s, const char *name, const CRegId &ri)\n{\n  AddComment_PropName(s, name);\n  ri.AddCommentTo(s);\n  {\n    UString s2;\n    ri.AddUdfVersionTo(s2);\n    if (!s2.IsEmpty())\n    {\n      s += \"::\";\n      s += s2;\n    }\n  }\n  s.Add_LF();\n}\n\n\n// UDF 6.3.1 OS Class\n\nstatic const char * const g_OsClasses[] =\n{\n    NULL\n  , \"DOS\"\n  , \"OS/2\"\n  , \"Macintosh OS\"\n  , \"UNIX\"\n  , \"Windows 9x\"\n  , \"Windows NT\"\n  , \"OS/400\"\n  , \"BeOS\"\n  , \"Windows CE\"\n};\n\n// UDF 6.3.2 OS Identifier\n\nstatic const char * const g_OsIds_Unix[] =\n{\n    NULL // \"Generic\"\n  , \"AIX\"\n  , \"SUN OS / Solaris\"\n  , \"HP/UX\"\n  , \"Silicon Graphics Irix\"\n  , \"Linux\"\n  , \"MKLinux\"\n  , \"FreeBSD\"\n  , \"NetBSD\"\n};\n\nstatic void AddOs_Class_Id(UString &s, const Byte *p)\n{\n  // UDF 2.1.5.3 Implementation Identifier Suffix\n  // Appendix 6.3 Operating System Identifiers.\n  const Byte osClass = p[0];\n  if (osClass != 0)\n  {\n    s += \"::\";\n    s += TypeToString(g_OsClasses, Z7_ARRAY_SIZE(g_OsClasses), osClass);\n  }\n  const Byte osId = p[1];\n  if (osId != 0)\n  {\n    s += \"::\";\n    if (osClass == 4) // unix\n    {\n      s += TypeToString(g_OsIds_Unix, Z7_ARRAY_SIZE(g_OsIds_Unix), osId);\n    }\n    else\n      s.Add_UInt32(osId);\n  }\n}\n\n\nstatic void AddComment_RegId_Impl(UString &s, const char *name, const CRegId &ri)\n{\n  AddComment_PropName(s, name);\n  ri.AddCommentTo(s);\n  {\n    AddOs_Class_Id(s, ri.Suffix);\n  }\n  s.Add_LF();\n}\n\n\nstatic void AddComment_RegId_UdfId(UString &s, const char *name, const CRegId &ri)\n{\n  AddComment_PropName(s, name);\n  ri.AddCommentTo(s);\n  {\n    // UDF 2.1.5.3\n    // UDF Identifier Suffix format\n    UString s2;\n    ri.AddUdfVersionTo(s2);\n    if (!s2.IsEmpty())\n    {\n      s += \"::\";\n      s += s2;\n    }\n    AddOs_Class_Id(s, &ri.Suffix[2]);\n  }\n  s.Add_LF();\n}\n\nstatic void AddComment_DString32(UString &s, const char *name, const CDString32 &d)\n{\n  AddComment_Align(s);\n  AddComment_PropName(s, name);\n  s += d.GetString();\n  s.Add_LF();\n}\n\nUString CInArchive::GetComment() const\n{\n  UString s;\n  {\n    s += \"Primary Volumes:\";\n    s.Add_LF();\n    FOR_VECTOR (i, PrimeVols)\n    {\n      if (i != 0)\n        s.Add_LF();\n      const CPrimeVol &pv = PrimeVols[i];\n      // AddComment_UInt32(s, \"VolumeDescriptorSequenceNumber\", pv.VolumeDescriptorSequenceNumber);\n      // if (PrimeVols.Size() != 1 || pv.PrimaryVolumeDescriptorNumber != 0)\n        AddComment_UInt32(s, \"PrimaryVolumeDescriptorNumber\", pv.PrimaryVolumeDescriptorNumber);\n      // if (pv.MaximumVolumeSequenceNumber != 1 || pv.VolumeSequenceNumber != 1)\n        AddComment_UInt32(s, \"VolumeSequenceNumber\", pv.VolumeSequenceNumber);\n      if (pv.MaximumVolumeSequenceNumber != 1)\n        AddComment_UInt32(s, \"MaximumVolumeSequenceNumber\", pv.MaximumVolumeSequenceNumber);\n      AddComment_PropName(s, \"VolumeId\");\n      s += pv.VolumeId.GetString();\n      s.Add_LF();\n      AddComment_PropName(s, \"VolumeSetId\");\n      s += pv.VolumeSetId.GetString();\n      s.Add_LF();\n      // AddComment_UInt32(s, \"InterchangeLevel\", pv.InterchangeLevel);\n      // AddComment_UInt32(s, \"MaximumInterchangeLevel\", pv.MaximumInterchangeLevel);\n      AddComment_RegId(s, \"ApplicationId\", pv.ApplicationId);\n      AddComment_RegId_Impl(s, \"ImplementationId\", pv.ImplId);\n    }\n  }\n  {\n    s += \"Partitions:\";\n    s.Add_LF();\n    FOR_VECTOR (i, Partitions)\n    {\n      if (i != 0)\n        s.Add_LF();\n      const CPartition &part = Partitions[i];\n      AddComment_UInt32(s, \"PartitionIndex\", i);\n      AddComment_UInt32(s, \"PartitionNumber\", part.Number);\n      if (part.IsMetadata)\n        AddComment_UInt32(s, \"IsMetadata\", 1);\n      else\n      {\n        AddComment_RegId(s, \"ContentsId\", part.ContentsId);\n        AddComment_RegId_Impl(s, \"ImplementationId\", part.ImplId);\n        AddComment_PropName(s, \"AccessType\");\n        s += TypeToString(g_PartitionTypes, Z7_ARRAY_SIZE(g_PartitionTypes), part.AccessType);\n        s.Add_LF();\n      }\n      AddComment_UInt64(s, \"Size\", (UInt64)part.Len << SecLogSize);\n      AddComment_UInt64(s, \"Pos\", (UInt64)part.Pos << SecLogSize);\n    }\n  }\n  s += \"Logical Volumes:\";\n  s.Add_LF();\n  {\n    FOR_VECTOR (i, LogVols)\n    {\n      if (i != 0)\n        s.Add_LF();\n      const CLogVol &vol = LogVols[i];\n      if (LogVols.Size() != 1)\n        AddComment_UInt32(s, \"Number\", i);\n      AddComment_PropName(s, \"Id\");\n      s += vol.Id.GetString();\n      s.Add_LF();\n      AddComment_UInt32(s, \"BlockSize\", vol.BlockSize);\n      AddComment_RegId_Domain(s, \"DomainId\", vol.DomainId);\n      AddComment_RegId_Impl(s, \"ImplementationId\", vol.ImplId);\n      // AddComment_UInt64(s, \"IntegritySequenceExtent_Len\", vol.IntegritySequenceExtent.Len);\n      // AddComment_UInt64(s, \"IntegritySequenceExtent_Pos\", (UInt64)vol.IntegritySequenceExtent.Pos << SecLogSize);\n\n      s += \"  Partition Maps:\";\n      s.Add_LF();\n      {\n        FOR_VECTOR (j, vol.PartitionMaps)\n        {\n          if (j != 0)\n            s.Add_LF();\n          const CPartitionMap &pm = vol.PartitionMaps[j];\n          AddComment_UInt32_2(s, \"PartitionMap\", j);\n          AddComment_UInt32_2(s, \"Type\", pm.Type);\n          AddComment_UInt32_2(s, \"VolumeSequenceNumber\", pm.VolumeSequenceNumber);\n          AddComment_UInt32_2(s, \"PartitionNumber\", pm.PartitionNumber);\n          if (pm.Type == 2)\n          {\n            AddComment_UInt32_2(s, \"MetadataFileLocation\", pm.MetadataFileLocation);\n            // AddComment_UInt32_2(s, \"MetadataMirrorFileLocation\", pm.MetadataMirrorFileLocation);\n            // AddComment_UInt32_2(s, \"MetadataBitmapFileLocation\", pm.MetadataBitmapFileLocation);\n            // AddComment_UInt32_2(s, \"AllocationUnitSize\", pm.AllocationUnitSize);\n            // AddComment_UInt32_2(s, \"AlignmentUnitSize\", pm.AlignmentUnitSize);\n            // AddComment_UInt32_2(s, \"Flags\", pm.Flags);\n            AddComment_Align(s); AddComment_RegId_UdfId(s, \"PartitionTypeId\", pm.PartitionTypeId);\n          }\n        }\n      }\n      s += \"  File Sets:\";\n      s.Add_LF();\n      {\n        FOR_VECTOR (j, vol.FileSets)\n        {\n          if (j != 0)\n            s.Add_LF();\n          const CFileSet &fs = vol.FileSets[j];\n          AddComment_Align(s); AddComment_UInt32(s, \"FileSetNumber\", fs.FileSetNumber);\n          AddComment_Align(s); AddComment_UInt32(s, \"FileSetDescNumber\", fs.FileSetDescNumber);\n\n          AddComment_Align(s);\n          AddComment_PropName(s, \"LogicalVolumeId\");\n          s += fs.LogicalVolumeId.GetString();\n          s.Add_LF();\n\n          AddComment_DString32(s, \"Id\", fs.Id);\n          AddComment_DString32(s, \"CopyrightId\", fs.CopyrightId);\n          AddComment_DString32(s, \"AbstractId\", fs.AbstractId);\n          \n          AddComment_Align(s);\n          AddComment_RegId_Domain(s, \"DomainId\", fs.DomainId);\n        }\n      }\n    }\n  }\n  return s;\n}\n\nstatic UString GetSpecName(const UString &name)\n{\n  UString name2 = name;\n  name2.Trim();\n  if (name2.IsEmpty())\n    return UString(\"[]\");\n  return name;\n}\n\nstatic void UpdateWithName(UString &res, const UString &addString)\n{\n  if (res.IsEmpty())\n    res = addString;\n  else\n    res.Insert(0, addString + WCHAR_PATH_SEPARATOR);\n}\n\nUString CInArchive::GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned refIndex,\n    bool showVolName, bool showFsName) const\n{\n  // showVolName = true;\n  const CLogVol &vol = LogVols[volIndex];\n  const CFileSet &fs = vol.FileSets[fsIndex];\n\n  UString name;\n\n  for (;;)\n  {\n    const CRef &ref = fs.Refs[refIndex];\n    // we break on root file (that probably has empty name)\n    if (ref.Parent < 0)\n      break;\n    refIndex = (unsigned)ref.Parent;\n    UpdateWithName(name, GetSpecName(Files[ref.FileIndex].GetName()));\n  }\n\n  if (showFsName)\n  {\n    UString newName (\"File Set \");\n    newName.Add_UInt32(fsIndex);\n    UpdateWithName(name, newName);\n  }\n\n  if (showVolName)\n  {\n    UString newName;\n    newName.Add_UInt32(volIndex);\n    UString newName2 = vol.GetName();\n    if (newName2.IsEmpty())\n      newName2 = \"Volume\";\n    newName.Add_Minus();\n    newName += newName2;\n    UpdateWithName(name, newName);\n  }\n  return name;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Udf/UdfIn.h",
    "content": "﻿// Archive/UdfIn.h -- UDF / ECMA-167\n\n#ifndef ZIP7_INC_ARCHIVE_UDF_IN_H\n#define ZIP7_INC_ARCHIVE_UDF_IN_H\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/MyMap.h\"\n#include \"../../../Common/MyString.h\"\n\n#include \"../../IStream.h\"\n\nnamespace NArchive {\nnamespace NUdf {\n\n// ---------- ECMA Part 1 ----------\n\n// ECMA 1/7.2.12\n// UDF 2.1.3\n\nstruct CDString32\n{\n  Byte Data[32];\n  \n  void Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }\n  UString GetString() const;\n};\n\nstruct CDString128\n{\n  Byte Data[128];\n  \n  void Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }\n  UString GetString() const;\n};\n\nstruct CDString\n{\n  CByteBuffer Data;\n  \n  void Parse(const Byte *p, unsigned size);\n  UString GetString() const;\n};\n\n\n// ECMA 1/7.3\n// UDF 2.1.4 timestamp\n\nstruct CTime\n{\n  Byte Data[12];\n\n  unsigned GetType() const { return Data[1] >> 4; }\n  bool IsLocal() const { return GetType() == 1; }\n  int GetMinutesOffset() const\n  {\n    int t = (Data[0] | ((unsigned)Data[1] << 8)) & 0xFFF;\n    if ((t >> 11) != 0)\n      t -= (1 << 12);\n    return (t > (60 * 24) || t < -(60 * 24)) ? 0 : t;\n  }\n  unsigned GetYear() const { return (Data[2] | ((unsigned)Data[3] << 8)); }\n  void Parse(const Byte *buf);\n};\n\n\n// ECMA 1/7.4 regid\n// UDF 2.1.5 EntityID\n\nstruct CRegId\n{\n  Byte Flags;\n  char Id[23];\n  Byte Suffix[8];\n\n  void Parse(const Byte *buf);\n  void AddCommentTo(UString &s) const;\n  void AddUdfVersionTo(UString &s) const;\n};\n\n\n\n// ---------- ECMA Part 3: Volume Structure ----------\n\n// ECMA 3/7.1\n\nstruct CExtent\n{\n  UInt32 Len;\n  UInt32 Pos; // logical sector number\n\n  void Parse(const Byte *p);\n};\n\n\n// ECMA 3/10.1\n// UDF 2.2.2 PrimaryVolumeDescriptor\n\nstruct CPrimeVol\n{\n  // UInt32 VolumeDescriptorSequenceNumber;\n  UInt32 PrimaryVolumeDescriptorNumber;\n  CDString32 VolumeId;\n  UInt16 VolumeSequenceNumber;\n  UInt16 MaximumVolumeSequenceNumber;\n  // UInt16 InterchangeLevel;\n  // UInt16 MaximumInterchangeLevel;\n  // UInt32 CharacterSetList;\n  // UInt32 MaximumCharacterSetList;\n  CDString128 VolumeSetId;\n  // charspec DescriptorCharacterSet; // (1/7.2.1)\n  // charspec ExplanatoryCharacterSet; // (1/7.2.1)\n  // CExtent VolumeAbstract;\n  // CExtent VolumeCopyrightNotice;\n  CRegId ApplicationId;\n  CTime RecordingTime;\n  CRegId ImplId;\n  // bytes ImplementationUse\n  // UInt32 PredecessorVolumeDescriptorSequenceLocation;\n  // UInt16 Flags;\n\n  void Parse(const Byte *p);\n};\n\n\n// ECMA 3/10.5\n// UDF 2.2.14 PartitionDescriptor\n\nstruct CPartition\n{\n  UInt32 Pos;\n  UInt32 Len;\n\n  UInt16 Flags;\n  UInt16 Number;\n  CRegId ContentsId;\n  // Byte ContentsUse[128];\n  UInt32 AccessType;\n\n  CRegId ImplId;\n  // Byte ImplUse[128];\n\n  // int VolIndex;\n  CMap32 Map;\n\n  bool IsMetadata;\n\n  CPartition():\n    //  VolIndex(-1),\n    IsMetadata(false) {}\n\n  // bool IsNsr() const { return (strncmp(ContentsId.Id, \"+NSR0\", 5) == 0); }\n  // bool IsAllocated() const { return ((Flags & 1) != 0); }\n};\n\n\n// ECMA 4/7.1 lb_addr\n\nstruct CLogBlockAddr\n{\n  UInt32 Pos;\n  UInt16 PartitionRef;\n  \n  void Parse(const Byte *p);\n};\n\n\nenum EShortAllocDescType\n{\n  SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0,\n  SHORT_ALLOC_DESC_TYPE_NotRecordedButAllocated = 1,\n  SHORT_ALLOC_DESC_TYPE_NotRecordedAndNotAllocated = 2,\n  SHORT_ALLOC_DESC_TYPE_NextExtent = 3\n};\n\n\n// ECMA 4/14.14.1 short_ad\n\nstruct CShortAllocDesc\n{\n  UInt32 Len;\n  UInt32 Pos;\n\n  // UInt32 GetLen() const { return Len & 0x3FFFFFFF; }\n  // UInt32 GetType() const { return Len >> 30; }\n  // bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }\n  void Parse(const Byte *p);\n};\n\n/*\nstruct CADImpUse\n{\n  UInt16 Flags;\n  UInt32 UdfUniqueId;\n  void Parse(const Byte *p);\n};\n*/\n\n// ECMA 4/14.14.2 long_ad\n// UDF 2.3.10.1\n\nstruct CLongAllocDesc\n{\n  UInt32 Len;\n  CLogBlockAddr Location;\n  \n  // Byte ImplUse[6];\n  // CADImpUse adImpUse; // UDF\n  \n  UInt32 GetLen() const { return Len & 0x3FFFFFFF; }\n  UInt32 GetType() const { return Len >> 30; }\n  bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }\n  void Parse(const Byte *p);\n};\n\n\n// ECMA 3/10.7 Partition maps\n// UDF 2.2.8-2.2.10 Partition Maps\n\nstruct CPartitionMap\n{\n  unsigned PartitionIndex;\n\n  Byte Type;\n  // Byte Len;\n\n  // ECMA 10.7.2\n  UInt16 VolumeSequenceNumber;\n  UInt16 PartitionNumber;\n  \n  CRegId PartitionTypeId;\n\n  // UDF 2.2.10 Metadata Partition Map\n  UInt32 MetadataFileLocation;\n  // UInt32 MetadataMirrorFileLocation;\n  // UInt32 MetadataBitmapFileLocation;\n  // UInt32 AllocationUnitSize; // (Blocks)\n  // UInt16 AlignmentUnitSize; // (Blocks)\n  // Byte Flags;\n\n  // Byte Data[256];\n  // CPartitionMap(): PartitionIndex(-1) {}\n};\n\n\n// ECMA 4/14.6.6\n\nenum EIcbFileType\n{\n  ICB_FILE_TYPE_DIR = 4,\n  ICB_FILE_TYPE_FILE = 5,\n  ICB_FILE_TYPE_REAL_TIME_FILE  = 249, // 2.3.5.2.1\n  ICB_FILE_TYPE_METADATA        = 250, // 2.2.13.1\n  ICB_FILE_TYPE_METADATA_MIRROR = 251, // 2.2.13.1\n  ICB_FILE_TYPE_METADATA_BITMAP = 252  // 2.2.13.2\n};\n\nenum EIcbDescriptorType\n{\n  ICB_DESC_TYPE_SHORT = 0,\n  ICB_DESC_TYPE_LONG = 1,\n  ICB_DESC_TYPE_EXTENDED = 2,\n  ICB_DESC_TYPE_INLINE = 3\n};\n\n// ECMA 4/14.6\n// UDF 3.3.2\n\nstruct CIcbTag\n{\n  // UInt32 PriorDirectNum;\n  // UInt16 StrategyType;\n  // UInt16 StrategyParam;\n  // UInt16 MaxNumOfEntries;\n  Byte FileType;\n  // CLogBlockAddr ParentIcb;\n  UInt16 Flags;\n\n  bool IsDir() const { return FileType == ICB_FILE_TYPE_DIR; }\n  int GetDescriptorType() const { return Flags & 3; }\n  void Parse(const Byte *p);\n};\n\n\n// ECMA 4/14.4.3\n// UDF 2.3.4.2 FileCharacteristics\n\n// const Byte FILEID_CHARACS_Existance = (1 << 0);\nconst Byte FILEID_CHARACS_Dir     = (1 << 1);\nconst Byte FILEID_CHARACS_Deleted = (1 << 2);\nconst Byte FILEID_CHARACS_Parent  = (1 << 3);\n// const Byte FILEID_CHARACS_Metadata = (1 << 4);\n\nstruct CFile\n{\n  int ItemIndex;\n  // UInt16 FileVersion;\n  // Byte FileCharacteristics;\n  // CByteBuffer ImplUse;\n  CDString Id;\n\n  CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {}\n  UString GetName() const { return Id.GetString(); }\n};\n\n\nstruct CMyExtent\n{\n  UInt32 Pos;\n  UInt32 Len;\n  unsigned PartitionRef; // index in CLogVol::PartitionMaps\n  \n  UInt32 GetLen() const { return Len & 0x3FFFFFFF; }\n  UInt32 GetType() const { return Len >> 30; }\n  bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }\n};\n\n\nstruct CItem\n{\n  CIcbTag IcbTag;\n\n  // UInt32 Uid;\n  // UInt32 Gid;\n  // UInt32 Permissions;\n  UInt16 FileLinkCount;\n  // Byte RecordFormat;\n  // Byte RecordDisplayAttr;\n  // UInt32 RecordLen;\n  UInt64 Size;\n  UInt64 NumLogBlockRecorded;\n  // UInt64 ObjectSize;\n\n  CTime ATime;\n  CTime MTime;\n  CTime AttribTime; // Attribute time : most recent date and time of the day of file creation or modification of the attributes of.\n  CTime CreateTime;\n  // UInt32 CheckPoint;\n  // CLongAllocDesc ExtendedAttrIcb;\n  // CRegId ImplId;\n  // UInt64 UniqueId;\n\n  bool IsExtended;\n  bool IsInline;\n  CByteBuffer InlineData;\n  CRecordVector<CMyExtent> Extents;\n  CUIntVector SubFiles;\n\n  void Parse(const Byte *p);\n\n  bool IsRecAndAlloc() const\n  {\n    FOR_VECTOR (i, Extents)\n      if (!Extents[i].IsRecAndAlloc())\n        return false;\n    return true;\n  }\n\n  UInt64 GetChunksSumSize() const\n  {\n    if (IsInline)\n      return InlineData.Size();\n    UInt64 size = 0;\n    FOR_VECTOR (i, Extents)\n      size += Extents[i].GetLen();\n    return size;\n  }\n\n  bool CheckChunkSizes() const  {  return GetChunksSumSize() == Size; }\n\n  bool IsDir() const { return IcbTag.IsDir(); }\n};\n \n\nstruct CRef\n{\n  unsigned FileIndex;\n  int Parent;\n};\n\n\n// ECMA 4 / 14.1\nstruct CFileSet\n{\n  CRecordVector<CRef> Refs;\n\n  CTime RecordingTime;\n  // UInt16 InterchangeLevel;\n  // UInt16 MaxInterchangeLevel;\n  UInt32 FileSetNumber;\n  UInt32 FileSetDescNumber;\n  CDString128 LogicalVolumeId;\n  CDString32 Id;\n  CDString32 CopyrightId;\n  CDString32 AbstractId;\n\n  CLongAllocDesc RootDirICB;\n  CRegId DomainId;\n  // CLongAllocDesc SystemStreamDirICB;\n};\n\n\n/* 8.3 Volume descriptors\n8.4\nA Volume Descriptor Sequence:\n shall contain one or more Primary Volume Descriptors.\n*/\n\n// ECMA 3/10.6\n// UDF 2.2.4  LogicalVolumeDescriptor\n\nstruct CLogVol\n{\n  CObjectVector<CPartitionMap> PartitionMaps;\n  CObjectVector<CFileSet> FileSets;\n\n  UInt32 BlockSize;\n  CDString128 Id;\n  CRegId DomainId;\n  \n  // Byte ContentsUse[16];\n  CLongAllocDesc FileSetLocation; // UDF\n\n  CRegId ImplId;\n  // Byte ImplUse[128];\n  // CExtent IntegritySequenceExtent;\n\n  UString GetName() const { return Id.GetString(); }\n};\n\n\nZ7_PURE_INTERFACES_BEGIN\nstruct Z7_DECLSPEC_NOVTABLE CProgressVirt\n{\n  virtual HRESULT SetTotal(UInt64 numBytes) =0; \\\n  virtual HRESULT SetCompleted(UInt64 numFiles, UInt64 numBytes) =0; \\\n  virtual HRESULT SetCompleted() =0; \\\n};\nZ7_PURE_INTERFACES_END\n\nclass CInArchive\n{\npublic:\n  CObjectVector<CLogVol> LogVols;\n  CObjectVector<CItem> Items;\n  CObjectVector<CFile> Files;\n  CObjectVector<CPartition> Partitions;\n\n  unsigned SecLogSize;\n  UInt64 PhySize;\n  UInt64 FileSize;\n\n  bool IsArc;\n  bool Unsupported;\n  bool UnexpectedEnd;\n  bool NoEndAnchor;\n\n  CObjectVector<CPrimeVol> PrimeVols;\n\n  HRESULT Open(IInStream *inStream, CProgressVirt *progress);\n  void Clear();\n\n  UString GetComment() const;\n  UString GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned refIndex,\n      bool showVolName, bool showFsName) const;\n\n  bool CheckItemExtents(unsigned volIndex, const CItem &item) const;\n\nprivate:\n  IInStream *_stream;\n  CProgressVirt *_progress;\n\n  HRESULT Read(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len, Byte *buf);\n  HRESULT ReadLad(unsigned volIndex, const CLongAllocDesc &lad, Byte *buf);\n  HRESULT ReadFromFile(unsigned volIndex, const CItem &item, CByteBuffer &buf);\n\n  HRESULT ReadFileItem(unsigned volIndex, unsigned fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed);\n  HRESULT ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDesc &lad, bool isDir, int numRecurseAllowed);\n\n  HRESULT Open2();\n  HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed);\n\n  UInt64 _processedProgressBytes;\n\n  UInt64 _fileNameLengthTotal;\n  unsigned _numRefs;\n  UInt32 _numExtents;\n  UInt64 _inlineExtentsSize;\n  bool CheckExtent(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len) const;\n\n  void UpdatePhySize(UInt64 val)\n  {\n    if (PhySize < val)\n      PhySize = val;\n  }\n\n  void UpdatePhySize(const CExtent &e)\n  {\n    UpdatePhySize(((UInt64)e.Pos << SecLogSize) + e.Len);\n  }\n};\n\nAPI_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size);\n\n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/UefiHandler.cpp",
    "content": "﻿// UefiHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#include \"../../../C/7zCrc.h\"\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/LzmaDec.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/AutoPtr.h\"\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/StringConvert.h\"\n\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/LzhDecoder.h\"\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n#define Get24(p) (Get32(p) & 0xFFFFFF)\n\nnamespace NArchive {\nnamespace NUefi {\n\nstatic const size_t kBufTotalSizeMax = 1 << 29;\nstatic const unsigned kNumFilesMax = 1 << 18;\nstatic const unsigned kLevelMax = 64;\n\nstatic const Byte k_IntelMeSignature[] =\n{\n  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,\n  0x5A, 0xA5, 0xF0, 0x0F\n};\n\nstatic bool IsIntelMe(const Byte *p)\n{\n  return memcmp(p, k_IntelMeSignature, sizeof(k_IntelMeSignature)) == 0;\n}\n\nstatic const unsigned kFvHeaderSize = 0x38;\n\nstatic const unsigned kGuidSize = 16;\n\n#define CAPSULE_SIGNATURE   0xBD,0x86,0x66,0x3B,0x76,0x0D,0x30,0x40,0xB7,0x0E,0xB5,0x51,0x9E,0x2F,0xC5,0xA0\n#define CAPSULE2_SIGNATURE  0x8B,0xA6,0x3C,0x4A,0x23,0x77,0xFB,0x48,0x80,0x3D,0x57,0x8C,0xC1,0xFE,0xC4,0x4D\n#define CAPSULE_UEFI_SIGNATURE  0xB9,0x82,0x91,0x53,0xB5,0xAB,0x91,0x43,0xB6,0x9A,0xE3,0xA9,0x43,0xF7,0x2F,0xCC\n/*\n  6dcbd5ed-e82d-4c44-bda1-7194199ad92a : Firmware Management `\n*/\n\nstatic const Byte k_Guids_Capsules[][kGuidSize] =\n{\n  { CAPSULE_SIGNATURE },\n  { CAPSULE2_SIGNATURE },\n  { CAPSULE_UEFI_SIGNATURE }\n};\n\n\nstatic const unsigned kFfsGuidOffset = 16;\n\n#define FFS1_SIGNATURE  0xD9,0x54,0x93,0x7A,0x68,0x04,0x4A,0x44,0x81,0xCE,0x0B,0xF6,0x17,0xD8,0x90,0xDF\n#define FFS2_SIGNATURE  0x78,0xE5,0x8C,0x8C,0x3D,0x8A,0x1C,0x4F,0x99,0x35,0x89,0x61,0x85,0xC3,0x2D,0xD3\n#define MACFS_SIGNATURE 0xAD,0xEE,0xAD,0x04,0xFF,0x61,0x31,0x4D,0xB6,0xBA,0x64,0xF8,0xBF,0x90,0x1F,0x5A\n// APPLE_BOOT\n/*\n  \"FFS3\":        \"5473c07a-3dcb-4dca-bd6f-1e9689e7349a\",\n  \"NVRAM_EVSA\":  \"fff12b8d-7696-4c8b-a985-2747075b4f50\",\n  \"NVRAM_NVAR\":  \"cef5b9a3-476d-497f-9fdc-e98143e0422c\",\n  \"NVRAM_EVSA2\": \"00504624-8a59-4eeb-bd0f-6b36e96128e0\",\nstatic const Byte k_NVRAM_NVAR_Guid[kGuidSize] =\n  { 0xA3,0xB9,0xF5,0xCE,0x6D,0x47,0x7F,0x49,0x9F,0xDC,0xE9,0x81,0x43,0xE0,0x42,0x2C };\n*/\n\nstatic const Byte k_Guids_FS[][kGuidSize] =\n{\n  { FFS1_SIGNATURE },\n  { FFS2_SIGNATURE },\n  { MACFS_SIGNATURE }\n};\n\n\nstatic const UInt32 kFvSignature = 0x4856465F; // \"_FVH\"\n\nstatic const Byte kGuids[][kGuidSize] =\n{\n  { 0xB0,0xCD,0x1B,0xFC,0x31,0x7D,0xAA,0x49,0x93,0x6A,0xA4,0x60,0x0D,0x9D,0xD0,0x83 },\n  { 0x2E,0x06,0xA0,0x1B,0x79,0xC7,0x82,0x45,0x85,0x66,0x33,0x6A,0xE8,0xF7,0x8F,0x09 },\n  { 0x25,0x4E,0x37,0x7E,0x01,0x8E,0xEE,0x4F,0x87,0xf2,0x39,0x0C,0x23,0xC6,0x06,0xCD },\n  { 0x97,0xE5,0x1B,0x16,0xC5,0xE9,0xDB,0x49,0xAE,0x50,0xC4,0x62,0xAB,0x54,0xEE,0xDA },\n  { 0xDB,0x7F,0xAD,0x77,0x2A,0xDF,0x02,0x43,0x88,0x98,0xC7,0x2E,0x4C,0xDB,0xD0,0xF4 },\n  { 0xAB,0x71,0xCF,0xF5,0x4B,0xB0,0x7E,0x4B,0x98,0x8A,0xD8,0xA0,0xD4,0x98,0xE6,0x92 },\n  { 0x91,0x45,0x53,0x7A,0xCE,0x37,0x81,0x48,0xB3,0xC9,0x71,0x38,0x14,0xF4,0x5D,0x6B },\n  { 0x84,0xE6,0x7A,0x36,0x5D,0x33,0x71,0x46,0xA1,0x6D,0x89,0x9D,0xBF,0xEA,0x6B,0x88 },\n  { 0x98,0x07,0x40,0x24,0x07,0x38,0x42,0x4A,0xB4,0x13,0xA1,0xEC,0xEE,0x20,0x5D,0xD8 },\n  { 0xEE,0xA2,0x3F,0x28,0x2C,0x53,0x4D,0x48,0x93,0x83,0x9F,0x93,0xB3,0x6F,0x0B,0x7E },\n  { 0x9B,0xD5,0xB8,0x98,0xBA,0xE8,0xEE,0x48,0x98,0xDD,0xC2,0x95,0x39,0x2F,0x1E,0xDB },\n  { 0x09,0x6D,0xE3,0xC3,0x94,0x82,0x97,0x4B,0xA8,0x57,0xD5,0x28,0x8F,0xE3,0x3E,0x28 },\n  { 0x18,0x88,0x53,0x4A,0xE0,0x5A,0xB2,0x4E,0xB2,0xEB,0x48,0x8B,0x23,0x65,0x70,0x22 }\n};\n\nstatic const Byte k_Guid_LZMA_COMPRESSED[kGuidSize] =\n  { 0x98,0x58,0x4E,0xEE,0x14,0x39,0x59,0x42,0x9D,0x6E,0xDC,0x7B,0xD7,0x94,0x03,0xCF };\n\nstatic const char * const kGuidNames[] =\n{\n    \"CRC\"\n  , \"VolumeTopFile\"\n  , \"ACPI\"\n  , \"ACPI2\"\n  , \"Main\"\n  , \"Intel32\"\n  , \"Intel64\"\n  , \"Intel32c\"\n  , \"Intel64c\"\n  , \"MacVolume\"\n  , \"MacUpdate.txt\"\n  , \"MacName\"\n  , \"Insyde\"\n};\n\nenum\n{\n  kGuidIndex_CRC = 0\n};\n\nstruct CSigExtPair\n{\n  const char *ext;\n  unsigned sigSize;\n  Byte sig[16];\n};\n\nstatic const CSigExtPair g_Sigs[] =\n{\n  { \"bmp\",  2, { 'B','M' } },\n  { \"riff\", 4, { 'R','I','F','F' } },\n  { \"pe\",   2, { 'M','Z'} },\n  { \"gif\",  6, { 'G','I','F','8','9', 'a' } },\n  { \"png\",  8, { 0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A } },\n  { \"jpg\", 10, { 0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46 } },\n  { \"rom\",  2, { 0x55,0xAA } }\n};\n\nenum\n{\n  kSig_BMP,\n  kSig_RIFF,\n  kSig_PE\n};\n\nstatic const char *FindExt(const Byte *p, size_t size)\n{\n  unsigned i;\n  for (i = 0; i < Z7_ARRAY_SIZE(g_Sigs); i++)\n  {\n    const CSigExtPair &pair = g_Sigs[i];\n    if (size >= pair.sigSize)\n      if (memcmp(p, pair.sig, pair.sigSize) == 0)\n        break;\n  }\n  if (i == Z7_ARRAY_SIZE(g_Sigs))\n    return NULL;\n  switch (i)\n  {\n    case kSig_BMP:\n      if (GetUi32(p + 2) > size || GetUi32(p + 0xA) > size)\n        return NULL;\n      break;\n    case kSig_RIFF:\n      if (GetUi32(p + 8) == 0x45564157 || GetUi32(p + 0xC) == 0x20746D66 )\n        return \"wav\";\n      break;\n    case kSig_PE:\n    {\n      if (size < 512)\n        return NULL;\n      UInt32 peOffset = GetUi32(p + 0x3C);\n      if (peOffset >= 0x1000 || peOffset + 512 > size || (peOffset & 7) != 0)\n        return NULL;\n      if (GetUi32(p + peOffset) != 0x00004550)\n        return NULL;\n      break;\n    }\n  }\n  return g_Sigs[i].ext;\n}\n\nstatic bool AreGuidsEq(const Byte *p1, const Byte *p2)\n{\n  return memcmp(p1, p2, kGuidSize) == 0;\n}\n\nstatic int FindGuid(const Byte *p)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(kGuids); i++)\n    if (AreGuidsEq(p, kGuids[i]))\n      return (int)i;\n  return -1;\n}\n \nstatic bool IsFfs(const Byte *p)\n{\n  if (Get32(p + 0x28) != kFvSignature)\n    return false;\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_Guids_FS); i++)\n    if (AreGuidsEq(p + kFfsGuidOffset, k_Guids_FS[i]))\n      return true;\n  return false;\n}\n\n#define FVB_ERASE_POLARITY  (1 << 11)\n\n/*\nstatic const CUInt32PCharPair g_FV_Attribs[] =\n{\n  {  0, \"ReadDisabledCap\" },\n  {  1, \"ReadEnabledCap\" },\n  {  2, \"ReadEnabled\" },\n  {  3, \"WriteDisabledCap\" },\n  {  4, \"WriteEnabledCap\" },\n  {  5, \"WriteEnabled\" },\n  {  6, \"LockCap\" },\n  {  7, \"Locked\" },\n\n  {  9, \"StickyWrite\" },\n  { 10, \"MemoryMapped\" },\n  { 11, \"ErasePolarity\" },\n  \n  { 12, \"ReadLockCap\" },\n  { 13, \"WriteLockCap\" },\n  { 14, \"WriteLockCap\" }\n};\n*/\n\nenum\n{\n  FV_FILETYPE_ALL,\n  FV_FILETYPE_RAW,\n  FV_FILETYPE_FREEFORM,\n  FV_FILETYPE_SECURITY_CORE,\n  FV_FILETYPE_PEI_CORE,\n  FV_FILETYPE_DXE_CORE,\n  FV_FILETYPE_PEIM,\n  FV_FILETYPE_DRIVER,\n  FV_FILETYPE_COMBINED_PEIM_DRIVER,\n  FV_FILETYPE_APPLICATION,\n  // The value 0x0A is reserved and should not be used\n  FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B,\n  // types 0xF0 - 0xFF are FFS file types\n  FV_FILETYPE_FFS_PAD = 0xF0\n};\n\nstatic const char * const g_FileTypes[] =\n{\n    \"ALL\"\n  , \"RAW\"\n  , \"FREEFORM\"\n  , \"SECURITY_CORE\"\n  , \"PEI_CORE\"\n  , \"DXE_CORE\"\n  , \"PEIM\"\n  , \"DRIVER\"\n  , \"COMBINED_PEIM_DRIVER\"\n  , \"APPLICATION\"\n  , \"0xA\"\n  , \"VOLUME\"\n};\n\n// typedef Byte FFS_FILE_ATTRIBUTES;\n// FFS File Attributes\n#define FFS_ATTRIB_TAIL_PRESENT 0x01\n// #define FFS_ATTRIB_RECOVERY 0x02\n// #define FFS_ATTRIB_HEADER_EXTENSION 0x04\n// #define FFS_ATTRIB_DATA_ALIGNMENT 0x38\n#define FFS_ATTRIB_CHECKSUM 0x40\n\nstatic const CUInt32PCharPair g_FFS_FILE_ATTRIBUTES[] =\n{\n  { 0, \"\" /* \"TAIL\" */ },\n  { 1, \"RECOVERY\" },\n  // { 2, \"HEADER_EXTENSION\" }, // reserved for future\n  { 6, \"\" /* \"CHECKSUM\" */ }\n};\n\n// static const Byte g_Allignment[8] = { 3, 4, 7, 9, 10, 12, 15, 16 };\n\n// typedef Byte FFS_FILE_STATE;\n\n// Look also FVB_ERASE_POLARITY.\n// Lower-order State bits are superceded by higher-order State bits.\n\n// #define FILE_HEADER_CONSTRUCTION  0x01\n// #define FILE_HEADER_VALID         0x02\n#define FILE_DATA_VALID           0x04\n// #define FILE_MARKED_FOR_UPDATE    0x08\n// #define FILE_DELETED              0x10\n// #define FILE_HEADER_INVALID       0x20\n\n// SECTION_TYPE\n\n// #define SECTION_ALL 0x00\n\n#define SECTION_COMPRESSION  0x01\n#define SECTION_GUID_DEFINED 0x02\n\n// Leaf section Type values\n// #define SECTION_PE32      0x10\n// #define SECTION_PIC       0x11\n// #define SECTION_TE        0x12\n#define SECTION_DXE_DEPEX 0x13\n#define SECTION_VERSION   0x14\n#define SECTION_USER_INTERFACE 0x15\n// #define SECTION_COMPATIBILITY16 0x16\n#define SECTION_FIRMWARE_VOLUME_IMAGE 0x17\n#define SECTION_FREEFORM_SUBTYPE_GUID 0x18\n#define SECTION_RAW       0x19\n#define SECTION_PEI_DEPEX 0x1B\n\n\n// #define GUIDED_SECTION_PROCESSING_REQUIRED 0x01\n// #define GUIDED_SECTION_AUTH_STATUS_VALID 0x02\n\nstatic const CUInt32PCharPair g_GUIDED_SECTION_ATTRIBUTES[] =\n{\n  { 0, \"PROCESSING_REQUIRED\" },\n  { 1, \"AUTH\" }\n};\n\nstatic const CUInt32PCharPair g_SECTION_TYPE[] =\n{\n  { 0x01, \"COMPRESSION\" },\n  { 0x02, \"GUID\" },\n  { 0x10, \"efi\" },\n  { 0x11, \"PIC\" },\n  { 0x12, \"te\" },\n  { 0x13, \"DXE_DEPEX\" },\n  { 0x14, \"VERSION\" },\n  { 0x15, \"USER_INTERFACE\" },\n  { 0x16, \"COMPATIBILITY16\" },\n  { 0x17, \"VOLUME\" },\n  { 0x18, \"FREEFORM_SUBTYPE_GUID\" },\n  { 0x19, \"raw\" },\n  { 0x1B, \"PEI_DEPEX\" }\n};\n\n#define COMPRESSION_TYPE_NONE 0\n#define COMPRESSION_TYPE_LZH  1\n#define COMPRESSION_TYPE_LZMA 2\n\nstatic const char * const g_Methods[] =\n{\n    \"COPY\"\n  , \"LZH\"\n  , \"LZMA\"\n};\n\n\nstatic void AddGuid(AString &dest, const Byte *p, bool full)\n{\n  char s[64];\n  ::RawLeGuidToString(p, s);\n  // MyStringUpper_Ascii(s);\n  if (!full)\n    s[8] = 0;\n  dest += s;\n}\n\nstatic const char * const kExpressionCommands[] =\n{\n  \"BEFORE\", \"AFTER\", \"PUSH\", \"AND\", \"OR\", \"NOT\", \"TRUE\", \"FALSE\", \"END\", \"SOR\"\n};\n\nstatic bool ParseDepedencyExpression(const Byte *p, UInt32 size, AString &res)\n{\n  res.Empty();\n  for (UInt32 i = 0; i < size;)\n  {\n    unsigned command = p[i++];\n    if (command > Z7_ARRAY_SIZE(kExpressionCommands))\n      return false;\n    res += kExpressionCommands[command];\n    if (command < 3)\n    {\n      if (i + kGuidSize > size)\n        return false;\n      res.Add_Space();\n      AddGuid(res, p + i, false);\n      i += kGuidSize;\n    }\n    res += \"; \";\n  }\n  return true;\n}\n\nstatic bool ParseUtf16zString(const Byte *p, UInt32 size, UString &res)\n{\n  if ((size & 1) != 0)\n    return false;\n  res.Empty();\n  UInt32 i;\n  for (i = 0; i < size; i += 2)\n  {\n    wchar_t c = Get16(p + i);\n    if (c == 0)\n      break;\n    res += c;\n  }\n  return (i == size - 2);\n}\n\nstatic bool ParseUtf16zString2(const Byte *p, UInt32 size, AString &res)\n{\n  UString s;\n  if (!ParseUtf16zString(p, size, s))\n    return false;\n  res = UnicodeStringToMultiByte(s);\n  return true;\n}\n\n#define FLAGS_TO_STRING(pairs, value) FlagsToString(pairs, Z7_ARRAY_SIZE(pairs), value)\n#define TYPE_TO_STRING(table, value) TypeToString(table, Z7_ARRAY_SIZE(table), value)\n#define TYPE_PAIR_TO_STRING(table, value) TypePairToString(table, Z7_ARRAY_SIZE(table), value)\n\nstatic const UInt32 kFileHeaderSize = 24;\n\nstatic void AddSpaceAndString(AString &res, const AString &newString)\n{\n  if (!newString.IsEmpty())\n  {\n    res.Add_Space_if_NotEmpty();\n    res += newString;\n  }\n}\n\nclass CFfsFileHeader\n{\nPRF(public:)\n  Byte CheckHeader;\n  Byte CheckFile;\n  Byte Attrib;\n  Byte State;\n\n  UInt16 GetTailReference() const { return (UInt16)(CheckHeader | ((UInt16)CheckFile << 8)); }\n  UInt32 GetTailSize() const { return IsThereTail() ? 2 : 0; }\n  bool IsThereFileChecksum() const { return (Attrib & FFS_ATTRIB_CHECKSUM) != 0; }\n  bool IsThereTail() const { return (Attrib & FFS_ATTRIB_TAIL_PRESENT) != 0; }\npublic:\n  Byte GuidName[kGuidSize];\n  Byte Type;\n  UInt32 Size;\n  \n  bool Parse(const Byte *p)\n  {\n    unsigned i;\n    for (i = 0; i < kFileHeaderSize; i++)\n      if (p[i] != 0xFF)\n        break;\n    if (i == kFileHeaderSize)\n      return false;\n    memcpy(GuidName, p, kGuidSize);\n    CheckHeader = p[0x10];\n    CheckFile = p[0x11];\n    Type = p[0x12];\n    Attrib = p[0x13];\n    Size = Get24(p + 0x14);\n    State = p[0x17];\n    return true;\n  }\n\n  UInt32 GetDataSize() const { return Size - kFileHeaderSize - GetTailSize(); }\n  UInt32 GetDataSize2(UInt32 rem) const { return rem - kFileHeaderSize - GetTailSize(); }\n\n  bool Check(const Byte *p, UInt32 size)\n  {\n    if (Size > size)\n      return false;\n    UInt32 tailSize = GetTailSize();\n    if (Size < kFileHeaderSize + tailSize)\n      return false;\n    \n    {\n      unsigned checkSum = 0;\n      for (UInt32 i = 0; i < kFileHeaderSize; i++)\n        checkSum += p[i];\n      checkSum -= p[0x17];\n      checkSum -= p[0x11];\n      if ((Byte)checkSum != 0)\n        return false;\n    }\n    \n    if (IsThereFileChecksum())\n    {\n      unsigned checkSum = 0;\n      UInt32 checkSize = Size - tailSize;\n      for (UInt32 i = 0; i < checkSize; i++)\n        checkSum += p[i];\n      checkSum -= p[0x17];\n      if ((Byte)checkSum != 0)\n        return false;\n    }\n    \n    if (IsThereTail())\n      if (GetTailReference() != (UInt16)~Get16(p + Size - 2))\n        return false;\n\n    int polarity = 0;\n    int i;\n    for (i = 5; i >= 0; i--)\n      if (((State >> i) & 1) == polarity)\n      {\n        // AddSpaceAndString(s, g_FFS_FILE_STATE_Flags[i]);\n        if ((1 << i) != FILE_DATA_VALID)\n          return false;\n        break;\n      }\n    if (i < 0)\n      return false;\n\n    return true;\n  }\n\n  AString GetCharacts() const\n  {\n    AString s;\n    if (Type == FV_FILETYPE_FFS_PAD)\n      s += \"PAD\";\n    else\n      s += TYPE_TO_STRING(g_FileTypes, Type);\n    AddSpaceAndString(s, FLAGS_TO_STRING(g_FFS_FILE_ATTRIBUTES, Attrib & 0xC7));\n    /*\n    int align = (Attrib >> 3) & 7;\n    if (align != 0)\n    {\n      s += \" Align:\";\n      s.Add_UInt32((UInt32)1 << g_Allignment[align]);\n    }\n    */\n    return s;\n  }\n};\n\n#define G32(_offs_, dest) dest = Get32(p + (_offs_))\n#define G16(_offs_, dest) dest = Get16(p + (_offs_))\n\nstruct CCapsuleHeader\n{\n  UInt32 HeaderSize;\n  UInt32 Flags;\n  UInt32 CapsuleImageSize;\n  UInt32 SequenceNumber;\n  // Guid InstanceId;\n  UInt32 OffsetToSplitInformation;\n  UInt32 OffsetToCapsuleBody;\n  UInt32 OffsetToOemDefinedHeader;\n  UInt32 OffsetToAuthorInformation;\n  UInt32 OffsetToRevisionInformation;\n  UInt32 OffsetToShortDescription;\n  UInt32 OffsetToLongDescription;\n  UInt32 OffsetToApplicableDevices;\n\n  void Clear() { memset(this, 0, sizeof(*this)); }\n\n  bool Parse(const Byte *p)\n  {\n    Clear();\n    G32(0x10, HeaderSize);\n    G32(0x14, Flags);\n    G32(0x18, CapsuleImageSize);\n    if (HeaderSize < 0x1C)\n      return false;\n    if (AreGuidsEq(p, k_Guids_Capsules[0]))\n    {\n      const unsigned kHeaderSize = 80;\n      if (HeaderSize != kHeaderSize)\n        return false;\n      G32(0x1C, SequenceNumber);\n      G32(0x30, OffsetToSplitInformation);\n      G32(0x34, OffsetToCapsuleBody);\n      G32(0x38, OffsetToOemDefinedHeader);\n      G32(0x3C, OffsetToAuthorInformation);\n      G32(0x40, OffsetToRevisionInformation);\n      G32(0x44, OffsetToShortDescription);\n      G32(0x48, OffsetToLongDescription);\n      G32(0x4C, OffsetToApplicableDevices);\n      return true;\n    }\n    else if (AreGuidsEq(p, k_Guids_Capsules[1]))\n    {\n      // capsule v2\n      G16(0x1C, OffsetToCapsuleBody);\n      G16(0x1E, OffsetToOemDefinedHeader);\n      return true;\n    }\n    else if (AreGuidsEq(p, k_Guids_Capsules[2]))\n    {\n      OffsetToCapsuleBody = HeaderSize;\n      return true;\n    }\n    else\n    {\n      // here we must check for another capsule types\n      return false;\n    }\n  }\n};\n\n\nstruct CItem\n{\n  AString Name;\n  AString Characts;\n  int Parent;\n  int Method;\n  int NameIndex;\n  unsigned NumChilds;\n  bool IsDir;\n  bool Skip;\n  bool ThereAreSubDirs;\n  bool ThereIsUniqueName;\n  bool KeepName;\n\n  unsigned BufIndex;\n  UInt32 Offset;\n  UInt32 Size;\n\n  CItem(): Parent(-1), Method(-1), NameIndex(-1), NumChilds(0),\n      IsDir(false), Skip(false), ThereAreSubDirs(false), ThereIsUniqueName(false), KeepName(true) {}\n  void SetGuid(const Byte *guidName, bool full = false);\n  AString GetName(int numChildsInParent) const;\n};\n\nvoid CItem::SetGuid(const Byte *guidName, bool full)\n{\n  ThereIsUniqueName = true;\n  int index = FindGuid(guidName);\n  if (index >= 0)\n    Name = kGuidNames[(unsigned)index];\n  else\n  {\n    Name.Empty();\n    AddGuid(Name, guidName, full);\n  }\n}\n\nAString CItem::GetName(int numChildsInParent) const\n{\n  if (numChildsInParent <= 1 || NameIndex < 0)\n    return Name;\n  char sz[32];\n  char sz2[32];\n  ConvertUInt32ToString((unsigned)NameIndex, sz);\n  ConvertUInt32ToString((unsigned)numChildsInParent - 1, sz2);\n  const int numZeros = (int)strlen(sz2) - (int)strlen(sz);\n  AString res;\n  for (int i = 0; i < numZeros; i++)\n    res += '0';\n  res += sz;\n  res.Add_Dot();\n  res += Name;\n  return res;\n}\n\nstruct CItem2\n{\n  AString Name;\n  AString Characts;\n  unsigned MainIndex;\n  int Parent;\n\n  CItem2(): Parent(-1) {}\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n    IInArchiveGetStream\n)\n  CObjectVector<CItem> _items;\n  CObjectVector<CItem2> _items2;\n  CObjectVector<CByteBuffer> _bufs;\n  UString _comment;\n  UInt32 _methodsMask;\n  bool _capsuleMode;\n  bool _headersError;\n\n  size_t _totalBufsSize;\n  CCapsuleHeader _h;\n  UInt64 _phySize;\n\n  void AddCommentString(const char *name, UInt32 pos);\n  unsigned AddItem(const CItem &item);\n  unsigned AddFileItemWithIndex(CItem &item);\n  unsigned AddDirItem(CItem &item);\n  unsigned AddBuf(size_t size);\n\n  HRESULT DecodeLzma(const Byte *data, size_t inputSize);\n\n  HRESULT ParseSections(unsigned bufIndex, UInt32 pos,\n      UInt32 size,\n      int parent, int method, unsigned level,\n      bool &error);\n  \n  HRESULT ParseIntelMe(unsigned bufIndex, UInt32 posBase,\n      UInt32 exactSize, UInt32 limitSize,\n      int parent, int method, unsigned level);\n\n  HRESULT ParseVolume(unsigned bufIndex, UInt32 posBase,\n      UInt32 exactSize, UInt32 limitSize,\n      int parent, int method, unsigned level);\n\n  HRESULT OpenCapsule(IInStream *stream);\n  HRESULT OpenFv(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);\n  HRESULT Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback);\npublic:\n  CHandler(bool capsuleMode): _capsuleMode(capsuleMode) {}\n};\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  // kpidOffset,\n  kpidMethod,\n  kpidCharacts\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidComment,\n  kpidMethod,\n  kpidCharacts\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CItem2 &item2 = _items2[index];\n  const CItem &item = _items[item2.MainIndex];\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      AString path (item2.Name);\n      int cur = item2.Parent;\n      while (cur >= 0)\n      {\n        const CItem2 &item3 = _items2[cur];\n        path.InsertAtFront(CHAR_PATH_SEPARATOR);\n        path.Insert(0, item3.Name);\n        cur = item3.Parent;\n      }\n      prop = path;\n      break;\n    }\n    case kpidIsDir: prop = item.IsDir; break;\n    case kpidMethod: if (item.Method >= 0) prop = g_Methods[(unsigned)item.Method]; break;\n    case kpidCharacts: if (!item2.Characts.IsEmpty()) prop = item2.Characts; break;\n    case kpidSize: if (!item.IsDir) prop = (UInt64)item.Size; break;\n    // case kpidOffset: if (!item.IsDir) prop = item.Offset; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nvoid CHandler::AddCommentString(const char *name, UInt32 pos)\n{\n  UString s;\n  if (pos < _h.HeaderSize)\n    return;\n  if (pos >= _h.OffsetToCapsuleBody)\n    return;\n  UInt32 limit = (_h.OffsetToCapsuleBody - pos) & ~(UInt32)1;\n  const Byte *buf = _bufs[0] + pos;\n  for (UInt32 i = 0;;)\n  {\n    if (s.Len() > (1 << 16) || i >= limit)\n      return;\n    wchar_t c = Get16(buf + i);\n    i += 2;\n    if (c == 0)\n    {\n      if (i >= limit)\n        return;\n      c = Get16(buf + i);\n      i += 2;\n      if (c == 0)\n        break;\n      s.Add_LF();\n    }\n    s += c;\n  }\n  if (s.IsEmpty())\n    return;\n  _comment.Add_LF();\n  _comment += name;\n  _comment += \": \";\n  _comment += s;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMethod:\n    {\n      AString s;\n      for (unsigned i = 0; i < 32; i++)\n        if ((_methodsMask & ((UInt32)1 << i)) != 0)\n          AddSpaceAndString(s, (AString)g_Methods[i]);\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n    case kpidComment: if (!_comment.IsEmpty()) prop = _comment; break;\n    case kpidPhySize: prop = (UInt64)_phySize; break;\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (_headersError) v |= kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n#ifdef SHOW_DEBUG_INFO\nstatic void PrintLevel(unsigned level)\n{\n  PRF(printf(\"\\n\"));\n  for (unsigned i = 0; i < level; i++)\n    PRF(printf(\"  \"));\n}\nstatic void MyPrint(UInt32 posBase, UInt32 size, unsigned level, const char *name)\n{\n  PrintLevel(level);\n  PRF(printf(\"%s, pos = %6x, size = %6x\", name, posBase, size));\n}\n#else\n#define PrintLevel(level)\n#define MyPrint(posBase, size, level, name)\n#endif\n\n\n\nunsigned CHandler::AddItem(const CItem &item)\n{\n  if (_items.Size() >= kNumFilesMax)\n    throw 2;\n  return _items.Add(item);\n}\n\nunsigned CHandler::AddFileItemWithIndex(CItem &item)\n{\n  unsigned nameIndex = _items.Size();\n  if (item.Parent >= 0)\n    nameIndex = _items[item.Parent].NumChilds++;\n  item.NameIndex = (int)nameIndex;\n  return AddItem(item);\n}\n\nunsigned CHandler::AddDirItem(CItem &item)\n{\n  if (item.Parent >= 0)\n    _items[item.Parent].ThereAreSubDirs = true;\n  item.IsDir = true;\n  item.Size = 0;\n  return AddItem(item);\n}\n\nunsigned CHandler::AddBuf(size_t size)\n{\n  if (size > kBufTotalSizeMax - _totalBufsSize)\n    throw 1;\n  _totalBufsSize += size;\n  unsigned index = _bufs.Size();\n  _bufs.AddNew().Alloc(size);\n  return index;\n}\n\n\nHRESULT CHandler::DecodeLzma(const Byte *data, size_t inputSize)\n{\n  if (inputSize < 5 + 8)\n    return S_FALSE;\n  const UInt64 unpackSize = Get64(data + 5);\n  if (unpackSize > ((UInt32)1 << 30))\n    return S_FALSE;\n  SizeT destLen = (SizeT)unpackSize;\n  const unsigned newBufIndex = AddBuf((size_t)unpackSize);\n  CByteBuffer &buf = _bufs[newBufIndex];\n  ELzmaStatus status;\n  SizeT srcLen = inputSize - (5 + 8);\n  const SizeT srcLen2 = srcLen;\n  SRes res = LzmaDecode(buf, &destLen, data + 13, &srcLen,\n      data, 5, LZMA_FINISH_END, &status, &g_Alloc);\n  if (res != 0)\n    return S_FALSE;\n  if (srcLen != srcLen2 || destLen != unpackSize || (\n      status != LZMA_STATUS_FINISHED_WITH_MARK &&\n      status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))\n    return S_FALSE;\n  return S_OK;\n}\n\n\nHRESULT CHandler::ParseSections(unsigned bufIndex, UInt32 posBase, UInt32 size, int parent, int method, unsigned level, bool &error)\n{\n  error = false;\n\n  if (level > kLevelMax)\n    return S_FALSE;\n  MyPrint(posBase, size, level, \"Sections\");\n  level++;\n  const Byte *bufData = _bufs[bufIndex];\n  UInt32 pos = 0;\n  for (;;)\n  {\n    if (size == pos)\n      return S_OK;\n    PrintLevel(level);\n    PRF(printf(\"%s, abs = %6x, relat = %6x\", \"Sect\", posBase + pos, pos));\n    pos = (pos + 3) & ~(UInt32)3;\n    if (pos > size)\n      return S_FALSE;\n    UInt32 rem = size - pos;\n    if (rem == 0)\n      return S_OK;\n    if (rem < 4)\n      return S_FALSE;\n    \n    const Byte *p = bufData + posBase + pos;\n    \n    const UInt32 sectSize = Get24(p);\n    const Byte type = p[3];\n    \n    // PrintLevel(level);\n    PRF(printf(\" type = %2x, sectSize = %6x\", type, sectSize));\n\n    if (sectSize > rem || sectSize < 4)\n    {\n      _headersError = true;\n      error = true;\n      return S_OK;\n      // return S_FALSE;\n    }\n\n    CItem item;\n    item.Method = method;\n    item.BufIndex = bufIndex;\n    item.Parent = parent;\n    item.Offset = posBase + pos + 4;\n    UInt32 sectDataSize = sectSize - 4;\n    item.Size = sectDataSize;\n    item.Name = TYPE_PAIR_TO_STRING(g_SECTION_TYPE, type);\n\n    if (type == SECTION_COMPRESSION)\n    {\n      if (sectSize < 4 + 5)\n        return S_FALSE;\n      const UInt32 uncompressedSize = Get32(p + 4);\n      const Byte compressionType = p[8];\n\n      UInt32 newSectSize = sectSize - 9;\n      UInt32 newOffset = posBase + pos + 9;\n      const Byte *pStart = p + 9;\n\n      item.KeepName = false;\n      if (compressionType > 2)\n      {\n        // AddFileItemWithIndex(item);\n        return S_FALSE;\n      }\n      else\n      {\n        item.Name = g_Methods[compressionType];\n        // int parent = AddDirItem(item);\n        if (compressionType == COMPRESSION_TYPE_NONE)\n        {\n          bool error2;\n          RINOK(ParseSections(bufIndex, newOffset, newSectSize, parent, method, level, error2))\n        }\n        else if (compressionType == COMPRESSION_TYPE_LZH)\n        {\n          const unsigned newBufIndex = AddBuf(uncompressedSize);\n          CByteBuffer &buf = _bufs[newBufIndex];\n          CMyUniquePtr<NCompress::NLzh::NDecoder::CCoder> lzhDecoder;\n          lzhDecoder.Create_if_Empty();\n          {\n            const Byte *src = pStart;\n            if (newSectSize < 8)\n              return S_FALSE;\n            UInt32 packSize = Get32(src);\n            const UInt32 unpackSize = Get32(src + 4);\n\n            PRF(printf(\" LZH packSize = %6x, unpackSize = %6x\", packSize, unpackSize));\n\n            if (uncompressedSize != unpackSize || newSectSize - 8 != packSize)\n              return S_FALSE;\n            if (packSize < 1)\n              return S_FALSE;\n            packSize--;\n            src += 8;\n            if (src[packSize] != 0)\n              return S_FALSE;\n\n            CMyComPtr2_Create<IInStream, CBufInStream> inStream;\n            CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;\n            // const UInt64 uncompressedSize64 = uncompressedSize;\n            // lzhDecoder->FinishMode = true;\n            /*\n              EFI 1.1 probably used LZH with small dictionary and (pbit = 4). It was named \"Efi compression\".\n              New version of compression code (named Tiano) uses LZH with (1 << 19) dictionary.\n              But maybe LZH decoder in UEFI decoder supports larger than (1 << 19) dictionary.\n              We check both LZH versions: Tiano and then Efi.\n            */\n            HRESULT res = S_FALSE;\n            for (unsigned m = 0 ; m < 2; m++)\n            {\n              inStream->Init(src, packSize);\n              outStream->Init(buf, uncompressedSize);\n              lzhDecoder->SetDictSize(m == 0 ? ((UInt32)1 << 19) : ((UInt32)1 << 14));\n              res = lzhDecoder->Code(inStream, outStream, uncompressedSize, NULL);\n              if (res == S_OK)\n                break;\n            }\n            RINOK(res)\n          }\n          bool error2;\n          RINOK(ParseSections(newBufIndex, 0, uncompressedSize, parent, compressionType, level, error2))\n        }\n        else\n        {\n          if (newSectSize < 4 + 5 + 8)\n            return S_FALSE;\n          unsigned addSize = 4;\n          if (pStart[0] == 0x5d && pStart[1] == 0 && pStart[2] == 0 && pStart[3] == 0x80 && pStart[4] == 0)\n          {\n            addSize = 0;\n            // some archives have such header\n          }\n          else\n          {\n            // normal BIOS contains uncompressed size here\n            // UInt32 uncompressedSize2 = Get24(pStart);\n            // Byte firstSectType = p[9 + 3];\n            // firstSectType can be 0 in some archives\n          }\n          pStart += addSize;\n\n          RINOK(DecodeLzma(pStart, newSectSize - addSize))\n          const size_t lzmaUncompressedSize = _bufs.Back().Size();\n          // if (lzmaUncompressedSize != uncompressedSize)\n          if (lzmaUncompressedSize < uncompressedSize)\n            return S_FALSE;\n          bool error2;\n          RINOK(ParseSections(_bufs.Size() - 1, 0, (UInt32)lzmaUncompressedSize, parent, compressionType, level, error2))\n        }\n        _methodsMask |= (1 << compressionType);\n      }\n    }\n    else if (type == SECTION_GUID_DEFINED)\n    {\n      const unsigned kHeaderSize = 4 + kGuidSize + 4;\n      if (sectSize < kHeaderSize)\n        return S_FALSE;\n      item.SetGuid(p + 4);\n      const UInt32 dataOffset = Get16(p + 4 + kGuidSize);\n      const UInt32 attrib = Get16(p + 4 + kGuidSize + 2);\n      if (dataOffset > sectSize || dataOffset < kHeaderSize)\n        return S_FALSE;\n      UInt32 newSectSize = sectSize - dataOffset;\n      item.Size = newSectSize;\n      UInt32 newOffset = posBase + pos + dataOffset;\n      item.Offset = newOffset;\n      const UInt32 propsSize = dataOffset - kHeaderSize;\n      AddSpaceAndString(item.Characts, FLAGS_TO_STRING(g_GUIDED_SECTION_ATTRIBUTES, attrib));\n\n      bool needDir = true;\n      unsigned newBufIndex = bufIndex;\n      int newMethod = method;\n  \n      if (AreGuidsEq(p + 0x4, k_Guid_LZMA_COMPRESSED))\n      {\n        // item.Name = \"guid.lzma\";\n        // AddItem(item);\n        const Byte *pStart = bufData + newOffset;\n        // do we need correct pStart here for lzma steram offset?\n        RINOK(DecodeLzma(pStart, newSectSize))\n        _methodsMask |= (1 << COMPRESSION_TYPE_LZMA);\n        newBufIndex = _bufs.Size() - 1;\n        newOffset = 0;\n        newSectSize = (UInt32)_bufs.Back().Size();\n        newMethod = COMPRESSION_TYPE_LZMA;\n      }\n      else if (AreGuidsEq(p + 0x4, kGuids[kGuidIndex_CRC]) && propsSize == 4)\n      {\n        needDir = false;\n        item.KeepName = false;\n        if (CrcCalc(bufData + newOffset, newSectSize) != Get32(p + kHeaderSize))\n          return S_FALSE;\n      }\n      else\n      {\n        if (propsSize != 0)\n        {\n          CItem item2 = item;\n          item2.Name += \".prop\";\n          item2.Size = propsSize;\n          item2.Offset = posBase + pos + kHeaderSize;\n          AddItem(item2);\n        }\n      }\n\n      int newParent = parent;\n      if (needDir)\n        newParent = (int)AddDirItem(item);\n      bool error2;\n      RINOK(ParseSections(newBufIndex, newOffset, newSectSize, newParent, newMethod, level, error2))\n    }\n    else if (type == SECTION_FIRMWARE_VOLUME_IMAGE)\n    {\n      item.KeepName = false;\n      const int newParent = (int)AddDirItem(item);\n      RINOK(ParseVolume(bufIndex, posBase + pos + 4,\n          sectSize - 4,\n          sectSize - 4,\n          newParent, method, level))\n    }\n    else\n    {\n      bool needAdd = true;\n      switch (type)\n      {\n        case SECTION_RAW:\n        {\n          const UInt32 kInsydeOffset = 12;\n          if (sectDataSize >= kFvHeaderSize + kInsydeOffset)\n          {\n            if (IsFfs(p + 4 + kInsydeOffset) &&\n                sectDataSize - kInsydeOffset == Get64(p + 4 + kInsydeOffset + 0x20))\n            {\n              needAdd = false;\n              item.Name = \"vol\";\n              const unsigned newParent = AddDirItem(item);\n              RINOK(ParseVolume(bufIndex, posBase + pos + 4 + kInsydeOffset,\n                  sectDataSize - kInsydeOffset,\n                  sectDataSize - kInsydeOffset,\n                  (int)newParent, method, level))\n            }\n            \n            if (needAdd)\n            {\n              const char *ext = FindExt(p + 4, sectDataSize);\n              if (ext)\n                item.Name = ext;\n            }\n          }\n          break;\n        }\n        case SECTION_DXE_DEPEX:\n        case SECTION_PEI_DEPEX:\n        {\n          AString s;\n          if (ParseDepedencyExpression(p + 4, sectDataSize, s))\n          {\n            if (s.Len() < (1 << 9))\n            {\n              s.InsertAtFront('[');\n              s += ']';\n              AddSpaceAndString(_items[item.Parent].Characts, s);\n              needAdd = false;\n            }\n            else\n            {\n              item.BufIndex = AddBuf(s.Len());\n              CByteBuffer &buf0 = _bufs[item.BufIndex];\n              if (s.Len() != 0)\n                memcpy(buf0, s, s.Len());\n              item.Offset = 0;\n              item.Size = s.Len();\n            }\n          }\n          break;\n        }\n        case SECTION_VERSION:\n        {\n          if (sectDataSize > 2)\n          {\n            AString s;\n            if (ParseUtf16zString2(p + 6, sectDataSize - 2, s))\n            {\n              AString s2 (\"ver:\");\n              s2.Add_UInt32(Get16(p + 4));\n              s2.Add_Space();\n              s2 += s;\n              AddSpaceAndString(_items[item.Parent].Characts, s2);\n              needAdd = false;\n            }\n          }\n          break;\n        }\n        case SECTION_USER_INTERFACE:\n        {\n          AString s;\n          if (ParseUtf16zString2(p + 4, sectDataSize, s))\n          {\n            _items[parent].Name = s;\n            needAdd = false;\n          }\n          break;\n        }\n        case SECTION_FREEFORM_SUBTYPE_GUID:\n        {\n          if (sectDataSize >= kGuidSize)\n          {\n            item.SetGuid(p + 4);\n            item.Size = sectDataSize - kGuidSize;\n            item.Offset = posBase + pos + 4 + kGuidSize;\n          }\n          break;\n        }\n      }\n    \n      if (needAdd)\n        AddFileItemWithIndex(item);\n    }\n\n    pos += sectSize;\n  }\n}\n\nstatic UInt32 Count_FF_Bytes(const Byte *p, UInt32 size)\n{\n  UInt32 i;\n  for (i = 0; i < size && p[i] == 0xFF; i++);\n  return i;\n}\n\nstatic bool Is_FF_Stream(const Byte *p, UInt32 size)\n{\n  return (Count_FF_Bytes(p, size) == size);\n}\n\nstruct CVolFfsHeader\n{\n  UInt32 HeaderLen;\n  UInt64 VolSize;\n  \n  bool Parse(const Byte *p);\n};\n\nbool CVolFfsHeader::Parse(const Byte *p)\n{\n  if (Get32(p + 0x28) != kFvSignature)\n    return false;\n\n  UInt32 attribs = Get32(p + 0x2C);\n  if ((attribs & FVB_ERASE_POLARITY) == 0)\n    return false;\n  VolSize = Get64(p + 0x20);\n  HeaderLen = Get16(p + 0x30);\n  if (HeaderLen < kFvHeaderSize || (HeaderLen & 0x7) != 0 || VolSize < HeaderLen)\n    return false;\n  return true;\n}\n\n\nHRESULT CHandler::ParseVolume(\n    unsigned bufIndex, UInt32 posBase,\n    UInt32 exactSize, UInt32 limitSize,\n    int parent, int method, unsigned level)\n{\n  if (level > kLevelMax)\n    return S_FALSE;\n  MyPrint(posBase, exactSize, level, \"Volume\");\n  level++;\n  if (exactSize < kFvHeaderSize)\n    return S_FALSE;\n  const Byte *p = _bufs[bufIndex] + posBase;\n  // first 16 bytes must be zeros, but they are not zeros sometimes.\n  if (!IsFfs(p))\n  {\n    CItem item;\n    item.Method = method;\n    item.BufIndex = bufIndex;\n    item.Parent = parent;\n    item.Offset = posBase;\n    item.Size = exactSize;\n    if (!Is_FF_Stream(p + kFfsGuidOffset, 16))\n      item.SetGuid(p + kFfsGuidOffset);\n    // if (item.Name.IsEmpty())\n    item.Name += \"[VOL]\";\n    AddItem(item);\n    return S_OK;\n  }\n  \n  CVolFfsHeader ffsHeader;\n  if (!ffsHeader.Parse(p))\n    return S_FALSE;\n  // if (parent >= 0) AddSpaceAndString(_items[parent].Characts, FLAGS_TO_STRING(g_FV_Attribs, attribs));\n  \n  // VolSize > exactSize (fh.Size) for some UEFI archives (is it correct UEFI?)\n  // so we check VolSize for limitSize instead.\n\n  if (ffsHeader.HeaderLen > limitSize || ffsHeader.VolSize > limitSize)\n    return S_FALSE;\n  \n  {\n    UInt32 checkCalc = 0;\n    for (UInt32 i = 0; i < ffsHeader.HeaderLen; i += 2)\n      checkCalc += Get16(p + i);\n    if ((checkCalc & 0xFFFF) != 0)\n      return S_FALSE;\n  }\n  \n  // 3 reserved bytes are not zeros sometimes.\n  // UInt16 ExtHeaderOffset; // in new SPECIFICATION?\n  // Byte revision = p[0x37];\n  \n  UInt32 pos = kFvHeaderSize;\n  for (;;)\n  {\n    if (pos >= ffsHeader.HeaderLen)\n      return S_FALSE;\n    UInt32 numBlocks = Get32(p + pos);\n    UInt32 length = Get32(p + pos + 4);\n    pos += 8;\n    if (numBlocks == 0 && length == 0)\n      break;\n  }\n  if (pos != ffsHeader.HeaderLen)\n    return S_FALSE;\n  \n  CRecordVector<UInt32> guidsVector;\n  \n  for (;;)\n  {\n    UInt32 rem = (UInt32)ffsHeader.VolSize - pos;\n    if (rem < kFileHeaderSize)\n      break;\n    pos = (pos + 7) & ~7u;\n    rem = (UInt32)ffsHeader.VolSize - pos;\n    if (rem < kFileHeaderSize)\n      break;\n\n    CItem item;\n    item.Method = method;\n    item.BufIndex = bufIndex;\n    item.Parent = parent;\n\n    const Byte *pFile = p + pos;\n    CFfsFileHeader fh;\n    if (!fh.Parse(pFile))\n    {\n      UInt32 num_FF_bytes = Count_FF_Bytes(pFile, rem);\n      if (num_FF_bytes != rem)\n      {\n        item.Name = \"[junk]\";\n        item.Offset = posBase + pos + num_FF_bytes;\n        item.Size = rem - num_FF_bytes;\n        AddItem(item);\n      }\n      PrintLevel(level); PRF(printf(\"== FF FF reminder\"));\n\n      break;\n    }\n\n    PrintLevel(level); PRF(printf(\"%s, type = %3d,  pos = %7x, size = %7x\", \"FILE\", fh.Type, posBase + pos, fh.Size));\n    \n    if (!fh.Check(pFile, rem))\n      return S_FALSE;\n    \n    UInt32 offset = posBase + pos + kFileHeaderSize;\n    UInt32 sectSize = fh.GetDataSize();\n    item.Offset = offset;\n    item.Size = sectSize;\n\n    pos += fh.Size;\n\n    if (fh.Type == FV_FILETYPE_FFS_PAD)\n      if (Is_FF_Stream(pFile + kFileHeaderSize, sectSize))\n        continue;\n    \n    UInt32 guid32 = Get32(fh.GuidName);\n    bool full = true;\n    if (guidsVector.FindInSorted(guid32) < 0)\n    {\n      guidsVector.AddToUniqueSorted(guid32);\n      full = false;\n    }\n    item.SetGuid(fh.GuidName, full);\n    \n    item.Characts = fh.GetCharacts();\n    // PrintLevel(level);\n    PRF(printf(\" : %s\", item.Characts));\n\n    {\n      PRF(printf(\" attrib = %2d State = %3d \", (unsigned)fh.Attrib, (unsigned)fh.State));\n      PRF(char s[64]);\n      PRF(RawLeGuidToString(fh.GuidName, s));\n      PRF(printf(\" : %s \", s));\n    }\n\n    if (fh.Type == FV_FILETYPE_FFS_PAD ||\n        fh.Type == FV_FILETYPE_RAW)\n    {\n      bool isVolume = false;\n      if (fh.Type == FV_FILETYPE_RAW)\n      {\n        if (sectSize >= kFvHeaderSize)\n          if (IsFfs(pFile + kFileHeaderSize))\n            isVolume = true;\n      }\n      if (isVolume)\n      {\n        const unsigned newParent = AddDirItem(item);\n        const UInt32 limSize = fh.GetDataSize2(rem);\n        // volume.VolSize > fh.Size for some UEFI archives (is it correct UEFI?)\n        // so we will check VolSize for limitSize instead.\n        RINOK(ParseVolume(bufIndex, offset, sectSize, limSize, (int)newParent, method, level))\n      }\n      else\n        AddItem(item);\n    }\n    else\n    {\n      /*\n      if (fh.Type == FV_FILETYPE_FREEFORM)\n      {\n        // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections)\n        // AddItem(item);\n      }\n      else\n      */\n      {\n        const unsigned newParent = AddDirItem(item);\n        bool error2;\n        RINOK(ParseSections(bufIndex, offset, sectSize, (int)newParent, method, level + 1, error2))\n        if (error2)\n        {\n          // in intel bio example: one FV_FILETYPE_FREEFORM file is wav file (not sections)\n          item.IsDir = false;\n          item.Size = sectSize;\n          item.Name.Insert(0, \"[ERROR]\");\n          AddItem(item);\n        }\n      }\n    }\n  }\n  \n  return S_OK;\n}\n\n\nstatic const char * const kRegionName[] =\n{\n    \"Descriptor\"\n  , \"BIOS\"\n  , \"ME\"\n  , \"GbE\"\n  , \"PDR\"\n  , \"Region5\"\n  , \"Region6\"\n  , \"Region7\"\n};\n\n\nHRESULT CHandler::ParseIntelMe(\n    unsigned bufIndex, UInt32 posBase,\n    UInt32 exactSize, UInt32 limitSize,\n    int parent, int method, unsigned /* level */)\n{\n  UNUSED_VAR(limitSize)\n  // level++;\n\n  const Byte *p = _bufs[bufIndex] + posBase;\n  if (exactSize < 16 + 16)\n    return S_FALSE;\n  if (!IsIntelMe(p))\n    return S_FALSE;\n\n  UInt32 v0 = GetUi32(p + 20);\n  // UInt32 numRegions = (v0 >> 24) & 0x7;\n  UInt32 regAddr = (v0 >> 12) & 0xFF0;\n  // UInt32 numComps  = (v0 >> 8) & 0x3;\n  // UInt32 fcba = (v0 <<  4) & 0xFF0;\n  \n  // (numRegions == 0) in header in some new images.\n  // So we don't use the value from header\n  UInt32 numRegions = 7;\n\n  for (unsigned i = 0; i <= numRegions; i++)\n  {\n    UInt32 offset = regAddr + i * 4;\n    if (offset + 4 > exactSize)\n      break;\n    UInt32 val = GetUi32(p + offset);\n\n    // only 12 bits probably are OK.\n    // How does it work for files larger than 16 MB?\n    const UInt32 kMask = 0xFFF;\n    // const UInt32 kMask = 0xFFFF; // 16-bit is more logical\n    const UInt32 lim  = (val >> 16) & kMask;\n    const UInt32 base = (val & kMask);\n\n    /*\n      strange combinations:\n        PDR:   base = 0x1FFF lim = 0;\n        empty: base = 0xFFFF lim = 0xFFFF;\n\n        PDR:   base = 0x7FFF lim = 0;\n        empty: base = 0x7FFF lim = 0;\n    */\n    if (base == kMask && lim == 0)\n      continue; // unused\n\n    if (lim < base)\n      continue; // unused\n\n    CItem item;\n    item.Name = kRegionName[i];\n    item.Method = method;\n    item.BufIndex = bufIndex;\n    item.Parent = parent;\n    item.Offset = posBase + (base << 12);\n    if (item.Offset > exactSize)\n      continue;\n    item.Size = (lim + 1 - base) << 12;\n    // item.SetGuid(p + kFfsGuidOffset);\n    // item.Name += \" [VOLUME]\";\n    AddItem(item);\n  }\n  return S_OK;\n}\n\n\nHRESULT CHandler::OpenCapsule(IInStream *stream)\n{\n  const unsigned kHeaderSize = 80;\n  Byte buf[kHeaderSize];\n  RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))\n  if (!_h.Parse(buf))\n    return S_FALSE;\n  if (_h.CapsuleImageSize < kHeaderSize\n       || _h.CapsuleImageSize < _h.HeaderSize\n       || _h.OffsetToCapsuleBody < _h.HeaderSize\n       || _h.OffsetToCapsuleBody > _h.CapsuleImageSize\n       || _h.CapsuleImageSize > (1u << 30) // to reduce false detection\n       || _h.HeaderSize > (1u << 28) // to reduce false detection\n      )\n    return S_FALSE;\n  _phySize = _h.CapsuleImageSize;\n\n  if (_h.SequenceNumber != 0 ||\n      _h.OffsetToSplitInformation != 0 )\n    return E_NOTIMPL;\n\n  const unsigned bufIndex = AddBuf(_h.CapsuleImageSize);\n  CByteBuffer &buf0 = _bufs[bufIndex];\n  memcpy(buf0, buf, kHeaderSize);\n  ReadStream_FALSE(stream, buf0 + kHeaderSize, _h.CapsuleImageSize - kHeaderSize);\n\n  AddCommentString(\"Author\", _h.OffsetToAuthorInformation);\n  AddCommentString(\"Revision\", _h.OffsetToRevisionInformation);\n  AddCommentString(\"Short Description\", _h.OffsetToShortDescription);\n  AddCommentString(\"Long Description\", _h.OffsetToLongDescription);\n\n\n  const UInt32 size = _h.CapsuleImageSize - _h.OffsetToCapsuleBody;\n\n  if (size >= 32 && IsIntelMe(buf0 + _h.OffsetToCapsuleBody))\n    return ParseIntelMe(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0);\n\n  return ParseVolume(bufIndex, _h.OffsetToCapsuleBody, size, size, -1, -1, 0);\n}\n\n\nHRESULT CHandler::OpenFv(IInStream *stream, const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback * /* callback */)\n{\n  Byte buf[kFvHeaderSize];\n  RINOK(ReadStream_FALSE(stream, buf, kFvHeaderSize))\n  if (!IsFfs(buf))\n    return S_FALSE;\n  CVolFfsHeader ffsHeader;\n  if (!ffsHeader.Parse(buf))\n    return S_FALSE;\n  if (ffsHeader.VolSize > ((UInt32)1 << 30))\n    return S_FALSE;\n  _phySize = ffsHeader.VolSize;\n  RINOK(InStream_SeekToBegin(stream))\n  UInt32 fvSize32 = (UInt32)ffsHeader.VolSize;\n  unsigned bufIndex = AddBuf(fvSize32);\n  RINOK(ReadStream_FALSE(stream, _bufs[bufIndex], fvSize32))\n  return ParseVolume(bufIndex, 0, fvSize32, fvSize32, -1, -1, 0);\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)\n{\n  if (_capsuleMode)\n  {\n    RINOK(OpenCapsule(stream))\n  }\n  else\n  {\n    RINOK(OpenFv(stream, maxCheckStartPosition, callback))\n  }\n\n  const unsigned num = _items.Size();\n  CIntArr numChilds(num);\n  \n  unsigned i;\n  \n  for (i = 0; i < num; i++)\n    numChilds[i] = 0;\n  \n  for (i = 0; i < num; i++)\n  {\n    const int parent = _items[i].Parent;\n    if (parent >= 0)\n      numChilds[(unsigned)parent]++;\n  }\n\n  for (i = 0; i < num; i++)\n  {\n    const CItem &item = _items[i];\n    const int parent = item.Parent;\n    if (parent >= 0)\n    {\n      CItem &parentItem = _items[(unsigned)parent];\n      if (numChilds[(unsigned)parent] == 1)\n        if (!item.ThereIsUniqueName || !parentItem.ThereIsUniqueName || !parentItem.ThereAreSubDirs)\n          parentItem.Skip = true;\n    }\n  }\n\n  CUIntVector mainToReduced;\n  \n  for (i = 0; i < _items.Size(); i++)\n  {\n    mainToReduced.Add(_items2.Size());\n    const CItem &item = _items[i];\n    if (item.Skip)\n      continue;\n    AString name;\n    int numItems = -1;\n    int parent = item.Parent;\n    if (parent >= 0)\n      numItems = numChilds[(unsigned)parent];\n    AString name2 (item.GetName(numItems));\n    AString characts2 (item.Characts);\n    if (item.KeepName)\n      name = name2;\n    \n    while (parent >= 0)\n    {\n      const CItem &item3 = _items[(unsigned)parent];\n      if (!item3.Skip)\n        break;\n      if (item3.KeepName)\n      {\n        AString name3 (item3.GetName(-1));\n        if (name.IsEmpty())\n          name = name3;\n        else\n          name = name3 + '.' + name;\n      }\n      AddSpaceAndString(characts2, item3.Characts);\n      parent = item3.Parent;\n    }\n    \n    if (name.IsEmpty())\n      name = name2;\n    \n    CItem2 item2;\n    item2.MainIndex = i;\n    item2.Name = name;\n    item2.Characts = characts2;\n    if (parent >= 0)\n      item2.Parent = (int)mainToReduced[(unsigned)parent];\n    _items2.Add(item2);\n    /*\n    CItem2 item2;\n    item2.MainIndex = i;\n    item2.Name = item.Name;\n    item2.Parent = item.Parent;\n    _items2.Add(item2);\n    */\n  }\n  \n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  Close();\n  {\n    HRESULT res = Open2(inStream, maxCheckStartPosition, callback);\n    if (res == E_NOTIMPL)\n      res = S_FALSE;\n    return res;\n  }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _phySize = 0;\n  _totalBufsSize = 0;\n  _methodsMask = 0;\n  _items.Clear();\n  _items2.Clear();\n  _bufs.Clear();\n  _comment.Empty();\n  _headersError = false;\n  _h.Clear();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items2.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items2.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _items[_items2[allFilesMode ? i : indices[i]].MainIndex].Size;\n  RINOK(extractCallback->SetTotal(totalSize))\n  totalSize = 0;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  for (i = 0;; i++)\n  {\n    lps->InSize = lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n    Int32 opRes;\n    {\n      CMyComPtr<ISequentialOutStream> realOutStream;\n      const Int32 askMode = testMode ?\n          NExtract::NAskMode::kTest :\n          NExtract::NAskMode::kExtract;\n      const UInt32 index = allFilesMode ? i : indices[i];\n      const CItem &item = _items[_items2[index].MainIndex];\n      RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n      totalSize += item.Size;\n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      if (testMode || item.IsDir)\n        opRes = NExtract::NOperationResult::kOK;\n      else\n      {\n        opRes = NExtract::NOperationResult::kDataError;\n        CMyComPtr<ISequentialInStream> inStream;\n        GetStream(index, &inStream);\n        if (inStream)\n        {\n          RINOK(copyCoder.Interface()->Code(inStream, realOutStream, NULL, NULL, lps))\n          if (copyCoder->TotalSize == item.Size)\n            opRes = NExtract::NOperationResult::kOK;\n        }\n      }\n    }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  const CItem &item = _items[_items2[index].MainIndex];\n  if (item.IsDir)\n    return S_FALSE;\n  CBufInStream *streamSpec = new CBufInStream;\n  CMyComPtr<IInStream> streamTemp = streamSpec;\n  const CByteBuffer &buf = _bufs[item.BufIndex];\n  if (item.Offset > buf.Size())\n    return S_FALSE;\n  size_t size = buf.Size() - item.Offset;\n  if (size > item.Size)\n    size = item.Size;\n  streamSpec->Init(buf + item.Offset, size, (IInArchive *)this);\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\nnamespace UEFIc {\n  \nstatic const Byte k_Capsule_Signatures[] =\n{\n   16, CAPSULE_SIGNATURE,\n   16, CAPSULE2_SIGNATURE,\n   16, CAPSULE_UEFI_SIGNATURE\n};\n\nREGISTER_ARC_I_CLS(\n  CHandler(true),\n  \"UEFIc\", \"scap\", NULL, 0xD0,\n  k_Capsule_Signatures,\n  0,\n  NArcInfoFlags::kMultiSignature |\n  NArcInfoFlags::kFindSignature,\n  NULL)\n  \n}\n\nnamespace UEFIf {\n  \nstatic const Byte k_FFS_Signatures[] =\n{\n   16, FFS1_SIGNATURE,\n   16, FFS2_SIGNATURE\n};\n\n\nREGISTER_ARC_I_CLS(\n  CHandler(false),\n  \"UEFIf\", \"uefif\", NULL, 0xD1,\n  k_FFS_Signatures,\n  kFfsGuidOffset,\n  NArcInfoFlags::kMultiSignature |\n  NArcInfoFlags::kFindSignature,\n  NULL)\n\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/VdiHandler.cpp",
    "content": "﻿// VdiHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NVdi {\n\nstatic const Byte k_Signature[] = { 0x7F, 0x10, 0xDA, 0xBE };\n\nstatic const unsigned k_ClusterBits = 20;\nstatic const UInt32 k_ClusterSize = (UInt32)1 << k_ClusterBits;\n\n\n/*\nVDI_IMAGE_BLOCK_FREE = (~0) // returns any random data\nVDI_IMAGE_BLOCK_ZERO = (~1) // returns zeros\n*/\n\n// static const UInt32 k_ClusterType_Free  = 0xffffffff;\nstatic const UInt32 k_ClusterType_Zero  = 0xfffffffe;\n\n#define IS_CLUSTER_ALLOCATED(v) ((UInt32)(v) < k_ClusterType_Zero)\n\n\n// static const UInt32 kDiskType_Dynamic = 1;\n// static const UInt32 kDiskType_Static = 2;\n\nstatic const char * const kDiskTypes[] =\n{\n    \"0\"\n  , \"Dynamic\"\n  , \"Static\"\n  , \"Undo\"\n  , \"Diff\"\n};\n\n\nenum EGuidType\n{\n  k_GuidType_Creat,\n  k_GuidType_Modif,\n  k_GuidType_Link,\n  k_GuidType_PModif\n};\n\nstatic const unsigned kNumGuids = 4;\nstatic const char * const kGuidNames[kNumGuids] =\n{\n    \"Creat \"\n  , \"Modif \"\n  , \"Link  \"\n  , \"PModif\"\n};\n\nstatic bool IsEmptyGuid(const Byte *data)\n{\n  for (unsigned i = 0; i < 16; i++)\n    if (data[i] != 0)\n      return false;\n  return true;\n}\n\n\n\nZ7_class_CHandler_final: public CHandlerImg\n{\n  UInt32 _dataOffset;\n  CByteBuffer _table;\n  UInt64 _phySize;\n  UInt32 _imageType;\n  bool _isArc;\n  bool _unsupported;\n\n  Byte Guids[kNumGuids][16];\n\n  HRESULT Seek2(UInt64 offset)\n  {\n    _posInArc = offset;\n    return InStream_SeekSet(Stream, offset);\n  }\n\n  HRESULT InitAndSeek()\n  {\n    _virtPos = 0;\n    return Seek2(0);\n  }\n\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) Z7_override;\n\npublic:\n  Z7_IFACE_COM7_IMP(IInArchive_Img)\n\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n};\n\n\nZ7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= _size)\n    return S_OK;\n  {\n    UInt64 rem = _size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n    if (size == 0)\n      return S_OK;\n  }\n \n  {\n    UInt64 cluster = _virtPos >> k_ClusterBits;\n    UInt32 lowBits = (UInt32)_virtPos & (k_ClusterSize - 1);\n    {\n      UInt32 rem = k_ClusterSize - lowBits;\n      if (size > rem)\n        size = rem;\n    }\n\n    cluster <<= 2;\n    if (cluster < _table.Size())\n    {\n      const Byte *p = (const Byte *)_table + (size_t)cluster;\n      const UInt32 v = Get32(p);\n      if (IS_CLUSTER_ALLOCATED(v))\n      {\n        UInt64 offset = _dataOffset + ((UInt64)v << k_ClusterBits);\n        offset += lowBits;\n        if (offset != _posInArc)\n        {\n          RINOK(Seek2(offset))\n        }\n        HRESULT res = Stream->Read(data, size, &size);\n        _posInArc += size;\n        _virtPos += size;\n        if (processedSize)\n          *processedSize = size;\n        return res;\n      }\n    }\n    \n    memset(data, 0, size);\n    _virtPos += size;\n    if (processedSize)\n      *processedSize = size;\n    return S_OK;\n  }\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidHeadersSize,\n  kpidMethod,\n  kpidComment,\n  kpidName\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidPhySize: if (_phySize != 0) prop = _phySize; break;\n    case kpidHeadersSize: prop = _dataOffset; break;\n    \n    case kpidMethod:\n    {\n      TYPE_TO_PROP(kDiskTypes, _imageType, prop);\n      break;\n    }\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;\n      // if (_headerError) v |= kpv_ErrorFlags_HeadersError;\n      if (!Stream && v == 0 && _isArc)\n        v = kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n\n    case kpidComment:\n    {\n      AString s;\n      for (unsigned i = 0; i < kNumGuids; i++)\n      {\n        const Byte *guid = Guids[i];\n        if (!IsEmptyGuid(guid))\n        {\n          s.Add_LF();\n          s += kGuidNames[i];\n          s += \" : \";\n          char temp[64];\n          RawLeGuidToString_Braced(guid, temp);\n          MyStringLower_Ascii(temp);\n          s += temp;\n        }\n      }\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidName:\n    {\n      const Byte *guid = Guids[k_GuidType_Creat];\n      if (!IsEmptyGuid(guid))\n      {\n        char temp[64];\n        RawLeGuidToString_Braced(guid, temp);\n        MyStringLower_Ascii(temp);\n        MyStringCat(temp, \".vdi\");\n        prop = temp;\n      }\n      break;\n    }\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidSize: prop = _size; break;\n    case kpidPackSize: prop = _phySize - _dataOffset; break;\n    case kpidExtension: prop = (_imgExt ? _imgExt : \"img\"); break;\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback * /* openCallback */)\n{\n  const unsigned kHeaderSize = 512;\n  Byte buf[kHeaderSize];\n  RINOK(ReadStream_FALSE(stream, buf, kHeaderSize))\n\n  if (memcmp(buf + 0x40, k_Signature, sizeof(k_Signature)) != 0)\n    return S_FALSE;\n\n  const UInt32 version = Get32(buf + 0x44);\n  if (version >= 0x20000)\n    return S_FALSE;\n  if (version < 0x10000)\n  {\n    _unsupported = true;\n    return S_FALSE;\n  }\n  \n  const unsigned kHeaderOffset = 0x48;\n  const unsigned kGuidsOffsets = 0x188;\n  const UInt32 headerSize = Get32(buf + kHeaderOffset);\n  if (headerSize < kGuidsOffsets - kHeaderOffset || headerSize > 0x200 - kHeaderOffset)\n    return S_FALSE;\n\n  _imageType = Get32(buf + 0x4C);\n  // Int32 flags = Get32(buf + 0x50);\n  // Byte Comment[0x100]\n\n  const UInt32 tableOffset = Get32(buf + 0x154);\n  if (tableOffset < 0x200)\n    return S_FALSE;\n\n  _dataOffset = Get32(buf + 0x158);\n\n  // UInt32 geometry[3];\n  \n  const UInt32 sectorSize = Get32(buf + 0x168);\n  if (sectorSize != 0x200)\n    return S_FALSE;\n\n  _size = Get64(buf + 0x170);\n  const UInt32 blockSize = Get32(buf + 0x178);\n  const UInt32 totalBlocks = Get32(buf + 0x180);\n  const UInt32 numAllocatedBlocks = Get32(buf + 0x184);\n  \n  _isArc = true;\n\n  if (_dataOffset < tableOffset)\n    return S_FALSE;\n\n  if (_imageType > 4)\n    _unsupported = true;\n\n  if (blockSize != k_ClusterSize)\n  {\n    _unsupported = true;\n    return S_FALSE;\n  }\n\n  if (headerSize >= kGuidsOffsets + kNumGuids * 16 - kHeaderOffset)\n  {\n    for (unsigned i = 0; i < kNumGuids; i++)\n      memcpy(Guids[i], buf + kGuidsOffsets + 16 * i, 16);\n\n    if (!IsEmptyGuid(Guids[k_GuidType_Link]) ||\n        !IsEmptyGuid(Guids[k_GuidType_PModif]))\n      _unsupported = true;\n  }\n\n  {\n    UInt64 size2 = (UInt64)totalBlocks << k_ClusterBits;\n    if (size2 < _size)\n    {\n      _unsupported = true;\n      return S_FALSE;\n    }\n    /*\n    if (size2 > _size)\n      _size = size2;\n    */\n  }\n\n  {\n    UInt32 tableReserved = _dataOffset - tableOffset;\n    if ((tableReserved >> 2) < totalBlocks)\n      return S_FALSE;\n  }\n\n  _phySize = _dataOffset + ((UInt64)numAllocatedBlocks << k_ClusterBits);\n\n  const size_t numBytes = (size_t)totalBlocks * 4;\n  if ((numBytes >> 2) != totalBlocks)\n  {\n    _unsupported = true;\n    return E_OUTOFMEMORY;\n  }\n\n  _table.Alloc(numBytes);\n  RINOK(InStream_SeekSet(stream, tableOffset))\n  RINOK(ReadStream_FALSE(stream, _table, numBytes))\n    \n  const Byte *data = _table;\n  for (UInt32 i = 0; i < totalBlocks; i++)\n  {\n    const UInt32 v = Get32(data + (size_t)i * 4);\n    if (!IS_CLUSTER_ALLOCATED(v))\n      continue;\n    if (v >= numAllocatedBlocks)\n    {\n      _unsupported = true;\n      return S_FALSE;\n    }\n  }\n  \n  Stream = stream;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _table.Free();\n  _phySize = 0;\n  _isArc = false;\n  _unsupported = false;\n\n  for (unsigned i = 0; i < kNumGuids; i++)\n    memset(Guids[i], 0, 16);\n\n  // CHandlerImg:\n  Clear_HandlerImg_Vars();\n  Stream.Release();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  if (_unsupported)\n    return S_FALSE;\n  CMyComPtr<ISequentialInStream> streamTemp = this;\n  RINOK(InitAndSeek())\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\nREGISTER_ARC_I(\n  \"VDI\", \"vdi\", NULL, 0xC9,\n  k_Signature,\n  0x40,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/VhdHandler.cpp",
    "content": "﻿// VhdHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get16(p) GetBe16(p)\n#define Get32(p) GetBe32(p)\n#define Get64(p) GetBe64(p)\n\n#define G32(_offs_, dest) dest = Get32(p + (_offs_))\n#define G64(_offs_, dest) dest = Get64(p + (_offs_))\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NVhd {\n\nstatic const unsigned kSignatureSize = 10;\nstatic const Byte kSignature[kSignatureSize] =\n  { 'c', 'o', 'n', 'e', 'c', 't', 'i', 'x', 0, 0 };\n\nstatic const UInt32 kUnusedBlock = 0xFFFFFFFF;\n\nstatic const UInt32 kDiskType_Fixed = 2;\nstatic const UInt32 kDiskType_Dynamic = 3;\nstatic const UInt32 kDiskType_Diff = 4;\n\nstatic const char * const kDiskTypes[] =\n{\n    \"0\"\n  , \"1\"\n  , \"Fixed\"\n  , \"Dynamic\"\n  , \"Differencing\"\n};\n\nstruct CFooter\n{\n  // UInt32 Features;\n  // UInt32 FormatVersion;\n  UInt64 DataOffset;\n  UInt32 CTime;\n  UInt32 CreatorApp;\n  UInt32 CreatorVersion;\n  UInt32 CreatorHostOS;\n  // UInt64 OriginalSize;\n  UInt64 CurrentSize;\n  UInt32 DiskGeometry;\n  UInt32 Type;\n  Byte Id[16];\n  Byte SavedState;\n\n  bool IsFixed() const { return Type == kDiskType_Fixed; }\n  bool ThereIsDynamic() const { return Type == kDiskType_Dynamic || Type == kDiskType_Diff; }\n  // bool IsSupported() const { return Type == kDiskType_Fixed || Type == kDiskType_Dynamic || Type == kDiskType_Diff; }\n  UInt32 NumCyls() const { return DiskGeometry >> 16; }\n  UInt32 NumHeads() const { return (DiskGeometry >> 8) & 0xFF; }\n  UInt32 NumSectorsPerTrack() const { return DiskGeometry & 0xFF; }\n  void AddTypeString(AString &s) const;\n  bool Parse(const Byte *p);\n};\n\nvoid CFooter::AddTypeString(AString &s) const\n{\n  if (Type < Z7_ARRAY_SIZE(kDiskTypes))\n    s += kDiskTypes[Type];\n  else\n    s.Add_UInt32(Type);\n}\n\nstatic bool CheckBlock(const Byte *p, unsigned size, unsigned checkSumOffset, unsigned zeroOffset)\n{\n  UInt32 sum = 0;\n  unsigned i;\n  for (i = 0; i < checkSumOffset; i++)\n    sum += p[i];\n  for (i = checkSumOffset + 4; i < size; i++)\n    sum += p[i];\n  if (~sum != Get32(p + checkSumOffset))\n    return false;\n  for (i = zeroOffset; i < size; i++)\n    if (p[i] != 0)\n      return false;\n  return true;\n}\n\nstatic const unsigned kSectorSize_Log = 9;\nstatic const unsigned kSectorSize = 1 << kSectorSize_Log;\nstatic const unsigned kHeaderSize = 512;\n\nbool CFooter::Parse(const Byte *p)\n{\n  if (memcmp(p, kSignature, kSignatureSize) != 0)\n    return false;\n  // G32(0x08, Features);\n  // G32(0x0C, FormatVersion);\n  G64(0x10, DataOffset);\n  G32(0x18, CTime);\n  G32(0x1C, CreatorApp);\n  G32(0x20, CreatorVersion);\n  G32(0x24, CreatorHostOS);\n  // G64(0x28, OriginalSize);\n  G64(0x30, CurrentSize);\n  G32(0x38, DiskGeometry);\n  G32(0x3C, Type);\n  if (Type < kDiskType_Fixed ||\n      Type > kDiskType_Diff)\n    return false;\n  memcpy(Id, p + 0x44, 16);\n  SavedState = p[0x54];\n  // if (DataOffset > ((UInt64)1 << 62)) return false;\n  // if (CurrentSize > ((UInt64)1 << 62)) return false;\n  return CheckBlock(p, kHeaderSize, 0x40, 0x55);\n}\n\nstruct CParentLocatorEntry\n{\n  UInt32 Code;\n  UInt32 DataSpace;\n  UInt32 DataLen;\n  UInt64 DataOffset;\n\n  bool Parse(const Byte *p)\n  {\n    G32(0x00, Code);\n    G32(0x04, DataSpace);\n    G32(0x08, DataLen);\n    G64(0x10, DataOffset);\n    return Get32(p + 0x0C) == 0; // Reserved\n  }\n};\n\nstruct CDynHeader\n{\n  // UInt64 DataOffset;\n  UInt64 TableOffset;\n  // UInt32 HeaderVersion;\n  UInt32 NumBlocks;\n  unsigned BlockSizeLog;\n  UInt32 ParentTime;\n  Byte ParentId[16];\n  bool RelativeNameWasUsed;\n  UString ParentName;\n  UString RelativeParentNameFromLocator;\n  CParentLocatorEntry ParentLocators[8];\n\n  bool Parse(const Byte *p);\n  UInt32 NumBitMapSectors() const\n  {\n    UInt32 numSectorsInBlock = (1 << (BlockSizeLog - kSectorSize_Log));\n    return (numSectorsInBlock + kSectorSize * 8 - 1) / (kSectorSize * 8);\n  }\n  void Clear()\n  {\n    RelativeNameWasUsed = false;\n    ParentName.Empty();\n    RelativeParentNameFromLocator.Empty();\n  }\n};\n\nbool CDynHeader::Parse(const Byte *p)\n{\n  if (memcmp(p, \"cxsparse\", 8) != 0)\n    return false;\n  // G64(0x08, DataOffset);\n  G64(0x10, TableOffset);\n  // G32(0x18, HeaderVersion);\n  G32(0x1C, NumBlocks);\n  {\n    UInt32 blockSize = Get32(p + 0x20);\n    unsigned i;\n    for (i = kSectorSize_Log;; i++)\n    {\n      if (i > 31)\n        return false;\n      if (((UInt32)1 << i) == blockSize)\n        break;\n    }\n    BlockSizeLog = i;\n  }\n  G32(0x38, ParentTime);\n  if (Get32(p + 0x3C) != 0) // reserved\n    return false;\n  memcpy(ParentId, p + 0x28, 16);\n  {\n    const unsigned kNameLen = 256;\n    wchar_t *s = ParentName.GetBuf(kNameLen);\n    unsigned i;\n    for (i = 0; i < kNameLen; i++)\n    {\n      wchar_t c = Get16(p + 0x40 + i * 2);\n      if (c == 0)\n        break;\n      s[i] = c;\n    }\n    s[i] = 0;\n    ParentName.ReleaseBuf_SetLen(i);\n  }\n  for (unsigned i = 0; i < 8; i++)\n    if (!ParentLocators[i].Parse(p + 0x240 + i * 24))\n      return false;\n  return CheckBlock(p, 1024, 0x24, 0x240 + 8 * 24);\n}\n\nZ7_class_CHandler_final: public CHandlerImg\n{\n  UInt64 _posInArcLimit;\n  UInt64 _startOffset;\n  UInt64 _phySize;\n\n  CFooter Footer;\n  CDynHeader Dyn;\n  CRecordVector<UInt32> Bat;\n  CByteBuffer BitMap;\n  UInt32 BitMapTag;\n  UInt32 NumUsedBlocks;\n  CMyComPtr<IInStream> ParentStream;\n  CHandler *Parent;\n  UInt64 NumLevels;\n  UString _errorMessage;\n  // bool _unexpectedEnd;\n\n  void AddErrorMessage(const char *message, const wchar_t *name = NULL)\n  {\n    if (!_errorMessage.IsEmpty())\n      _errorMessage.Add_LF();\n    _errorMessage += message;\n    if (name)\n      _errorMessage += name;\n  }\n\n  void UpdatePhySize(UInt64 value)\n  {\n    if (_phySize < value)\n      _phySize = value;\n  }\n\n  HRESULT Seek2(UInt64 offset);\n  HRESULT InitAndSeek();\n  HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size);\n\n  bool NeedParent() const { return Footer.Type == kDiskType_Diff; }\n  UInt64 GetPackSize() const\n    { return Footer.ThereIsDynamic() ? ((UInt64)NumUsedBlocks << Dyn.BlockSizeLog) : Footer.CurrentSize; }\n\n  UString GetParentSequence() const\n  {\n    const CHandler *p = this;\n    UString res;\n    while (p && p->NeedParent())\n    {\n      if (!res.IsEmpty())\n        res += \" -> \";\n      UString mainName;\n      UString anotherName;\n      if (Dyn.RelativeNameWasUsed)\n      {\n        mainName = p->Dyn.RelativeParentNameFromLocator;\n        anotherName = p->Dyn.ParentName;\n      }\n      else\n      {\n        mainName = p->Dyn.ParentName;\n        anotherName = p->Dyn.RelativeParentNameFromLocator;\n      }\n      res += mainName;\n      if (mainName != anotherName && !anotherName.IsEmpty())\n      {\n        res.Add_Space();\n        res.Add_Char('(');\n        res += anotherName;\n        res.Add_Char(')');\n      }\n      p = p->Parent;\n    }\n    return res;\n  }\n\n  bool AreParentsOK() const\n  {\n    const CHandler *p = this;\n    while (p->NeedParent())\n    {\n      p = p->Parent;\n      if (!p)\n        return false;\n    }\n    return true;\n  }\n\n  HRESULT Open3();\n  HRESULT Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, unsigned level);\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback) Z7_override\n  {\n    return Open2(stream, NULL, openArchiveCallback, 0);\n  }\n  void CloseAtError() Z7_override;\n\npublic:\n  Z7_IFACE_COM7_IMP(IInArchive_Img)\n\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n};\n\nHRESULT CHandler::Seek2(UInt64 offset) { return InStream_SeekSet(Stream, _startOffset + offset); }\n\nHRESULT CHandler::InitAndSeek()\n{\n  if (ParentStream)\n  {\n    RINOK(Parent->InitAndSeek())\n  }\n  _virtPos = _posInArc = 0;\n  BitMapTag = kUnusedBlock;\n  BitMap.Alloc(Dyn.NumBitMapSectors() << kSectorSize_Log);\n  return Seek2(0);\n}\n\nHRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size)\n{\n  if (offset + size > _posInArcLimit)\n    return S_FALSE;\n  if (offset != _posInArc)\n  {\n    _posInArc = offset;\n    RINOK(Seek2(offset))\n  }\n  HRESULT res = ReadStream_FALSE(Stream, data, size);\n  if (res == S_OK)\n    _posInArc += size;\n  else\n    Reset_PosInArc();\n  return res;\n}\n\nHRESULT CHandler::Open3()\n{\n  // Fixed archive uses only footer\n\n  UInt64 startPos;\n  RINOK(InStream_GetPos(Stream, startPos))\n  _startOffset = startPos;\n  Byte header[kHeaderSize];\n  RINOK(ReadStream_FALSE(Stream, header, kHeaderSize))\n  bool headerIsOK = Footer.Parse(header);\n  _size = Footer.CurrentSize;\n\n  if (headerIsOK && !Footer.ThereIsDynamic())\n  {\n    // fixed archive\n    if (startPos < Footer.CurrentSize)\n      return S_FALSE;\n    _posInArcLimit = Footer.CurrentSize;\n    _phySize = Footer.CurrentSize + kHeaderSize;\n    _startOffset = startPos - Footer.CurrentSize;\n    _posInArc = _phySize;\n    return S_OK;\n  }\n\n  UInt64 fileSize;\n  RINOK(InStream_GetSize_SeekToEnd(Stream, fileSize))\n  if (fileSize < kHeaderSize)\n    return S_FALSE;\n\n  const UInt32 kDynSize = 1024;\n  Byte buf[kDynSize];\n\n  RINOK(InStream_SeekSet(Stream, fileSize - kHeaderSize))\n  RINOK(ReadStream_FALSE(Stream, buf, kHeaderSize))\n\n  if (!headerIsOK)\n  {\n    if (!Footer.Parse(buf))\n      return S_FALSE;\n    _size = Footer.CurrentSize;\n    if (Footer.ThereIsDynamic())\n      return S_FALSE; // we can't open Dynamic Archive backward.\n    // fixed archive\n    _posInArcLimit = Footer.CurrentSize;\n    _phySize = Footer.CurrentSize + kHeaderSize;\n    _startOffset = fileSize - kHeaderSize - Footer.CurrentSize;\n    _posInArc = _phySize;\n    return S_OK;\n  }\n\n  _phySize = kHeaderSize;\n  _posInArc = fileSize - startPos;\n  _posInArcLimit = _posInArc - kHeaderSize;\n\n  bool headerAndFooterAreEqual = false;\n  if (memcmp(header, buf, kHeaderSize) == 0)\n  {\n    headerAndFooterAreEqual = true;\n    _phySize = fileSize - _startOffset;\n  }\n\n  RINOK(ReadPhy(Footer.DataOffset, buf, kDynSize))\n  if (!Dyn.Parse(buf))\n    return S_FALSE;\n\n  UpdatePhySize(Footer.DataOffset + kDynSize);\n\n  for (int i = 0; i < 8; i++)\n  {\n    const CParentLocatorEntry &locator = Dyn.ParentLocators[i];\n    const UInt32 kNameBufSizeMax = 1024;\n    if (locator.DataLen < kNameBufSizeMax &&\n        locator.DataOffset < _posInArcLimit &&\n        locator.DataOffset + locator.DataLen <= _posInArcLimit)\n    {\n      if (locator.Code == 0x57327275 && (locator.DataLen & 1) == 0)\n      {\n        // \"W2ru\" locator\n        // Path is encoded as little-endian UTF-16\n        Byte nameBuf[kNameBufSizeMax];\n        UString tempString;\n        unsigned len = (locator.DataLen >> 1);\n        {\n          wchar_t *s = tempString.GetBuf(len);\n          RINOK(ReadPhy(locator.DataOffset, nameBuf, locator.DataLen))\n          unsigned j;\n          for (j = 0; j < len; j++)\n          {\n            wchar_t c = GetUi16(nameBuf + j * 2);\n            if (c == 0)\n              break;\n            s[j] = c;\n          }\n          s[j] = 0;\n          tempString.ReleaseBuf_SetLen(j);\n        }\n        if (tempString[0] == L'.' && tempString[1] == L'\\\\')\n          tempString.DeleteFrontal(2);\n        Dyn.RelativeParentNameFromLocator = tempString;\n      }\n    }\n    if (locator.DataLen != 0)\n      UpdatePhySize(locator.DataOffset + locator.DataLen);\n  }\n  \n  if (Dyn.NumBlocks >= (UInt32)1 << 31)\n    return S_FALSE;\n  if (Footer.CurrentSize == 0)\n  {\n    if (Dyn.NumBlocks != 0)\n      return S_FALSE;\n  }\n  else if (((Footer.CurrentSize - 1) >> Dyn.BlockSizeLog) + 1 != Dyn.NumBlocks)\n    return S_FALSE;\n\n  Bat.ClearAndReserve(Dyn.NumBlocks);\n\n  UInt32 bitmapSize = Dyn.NumBitMapSectors() << kSectorSize_Log;\n\n  while ((UInt32)Bat.Size() < Dyn.NumBlocks)\n  {\n    RINOK(ReadPhy(Dyn.TableOffset + (UInt64)Bat.Size() * 4, buf, kSectorSize))\n    UpdatePhySize(Dyn.TableOffset + kSectorSize);\n    for (UInt32 j = 0; j < kSectorSize; j += 4)\n    {\n      UInt32 v = Get32(buf + j);\n      if (v != kUnusedBlock)\n      {\n        UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog;\n        UpdatePhySize(((UInt64)v << kSectorSize_Log) + bitmapSize + blockSize);\n        NumUsedBlocks++;\n      }\n      Bat.AddInReserved(v);\n      if ((UInt32)Bat.Size() >= Dyn.NumBlocks)\n        break;\n    }\n  }\n\n  if (headerAndFooterAreEqual)\n    return S_OK;\n\n  if (_startOffset + _phySize + kHeaderSize > fileSize)\n  {\n    // _unexpectedEnd = true;\n    _posInArcLimit = _phySize;\n    _phySize += kHeaderSize;\n    return S_OK;\n  }\n\n  RINOK(ReadPhy(_phySize, buf, kHeaderSize))\n  if (memcmp(header, buf, kHeaderSize) == 0)\n  {\n    _posInArcLimit = _phySize;\n    _phySize += kHeaderSize;\n    return S_OK;\n  }\n\n  if (_phySize == 0x800)\n  {\n    /* WHY does empty archive contain additional empty sector?\n       We skip that sector and check footer again. */\n    unsigned i;\n    for (i = 0; i < kSectorSize && buf[i] == 0; i++);\n    if (i == kSectorSize)\n    {\n      RINOK(ReadPhy(_phySize + kSectorSize, buf, kHeaderSize))\n      if (memcmp(header, buf, kHeaderSize) == 0)\n      {\n        _phySize += kSectorSize;\n        _posInArcLimit = _phySize;\n        _phySize += kHeaderSize;\n        return S_OK;\n      }\n    }\n  }\n  _posInArcLimit = _phySize;\n  _phySize += kHeaderSize;\n  AddErrorMessage(\"Can't find footer\");\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= Footer.CurrentSize)\n    return S_OK;\n  {\n    const UInt64 rem = Footer.CurrentSize - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  if (size == 0)\n    return S_OK;\n\n  if (Footer.IsFixed())\n  {\n    if (_virtPos > _posInArcLimit)\n      return S_FALSE;\n    {\n      const UInt64 rem = _posInArcLimit - _virtPos;\n      if (size > rem)\n        size = (UInt32)rem;\n    }\n    HRESULT res = S_OK;\n    if (_virtPos != _posInArc)\n    {\n      _posInArc = _virtPos;\n      res = Seek2(_virtPos);\n    }\n    if (res == S_OK)\n    {\n      UInt32 processedSize2 = 0;\n      res = Stream->Read(data, size, &processedSize2);\n      if (processedSize)\n        *processedSize = processedSize2;\n      _posInArc += processedSize2;\n    }\n    if (res != S_OK)\n      Reset_PosInArc();\n    return res;\n  }\n\n  const UInt32 blockIndex = (UInt32)(_virtPos >> Dyn.BlockSizeLog);\n  if (blockIndex >= Bat.Size())\n    return E_FAIL; // it's some unexpected case\n  const UInt32 blockSectIndex = Bat[blockIndex];\n  const UInt32 blockSize = (UInt32)1 << Dyn.BlockSizeLog;\n  UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);\n  size = MyMin(blockSize - offsetInBlock, size);\n\n  HRESULT res = S_OK;\n  if (blockSectIndex == kUnusedBlock)\n  {\n    if (ParentStream)\n    {\n      RINOK(InStream_SeekSet(ParentStream, _virtPos))\n      res = ParentStream->Read(data, size, &size);\n    }\n    else\n      memset(data, 0, size);\n  }\n  else\n  {\n    const UInt64 newPos = (UInt64)blockSectIndex << kSectorSize_Log;\n    if (BitMapTag != blockIndex)\n    {\n      RINOK(ReadPhy(newPos, BitMap, (UInt32)BitMap.Size()))\n      BitMapTag = blockIndex;\n    }\n    RINOK(ReadPhy(newPos + BitMap.Size() + offsetInBlock, data, size))\n    for (UInt32 cur = 0; cur < size;)\n    {\n      const UInt32 rem = MyMin(0x200 - (offsetInBlock & 0x1FF), size - cur);\n      const UInt32 bmi = offsetInBlock >> kSectorSize_Log;\n      if (((BitMap[bmi >> 3] >> (7 - (bmi & 7))) & 1) == 0)\n      {\n        if (ParentStream)\n        {\n          RINOK(InStream_SeekSet(ParentStream, _virtPos + cur))\n          RINOK(ReadStream_FALSE(ParentStream, (Byte *)data + cur, rem))\n        }\n        else\n        {\n          const Byte *p = (const Byte *)data + cur;\n          for (UInt32 i = 0; i < rem; i++)\n            if (p[i] != 0)\n              return S_FALSE;\n        }\n      }\n      offsetInBlock += rem;\n      cur += rem;\n    }\n  }\n  if (processedSize)\n    *processedSize = size;\n  _virtPos += size;\n  return res;\n}\n\n\nenum\n{\n  kpidParent = kpidUserDefined,\n  kpidSavedState\n};\n\nstatic const CStatProp kArcProps[] =\n{\n  { NULL, kpidOffset, VT_UI8},\n  { NULL, kpidCTime, VT_FILETIME},\n  { NULL, kpidClusterSize, VT_UI8},\n  { NULL, kpidMethod, VT_BSTR},\n  { NULL, kpidNumVolumes, VT_UI4},\n  { NULL, kpidTotalPhySize, VT_UI8},\n  { \"Parent\", kpidParent, VT_BSTR},\n  { NULL, kpidCreatorApp, VT_BSTR},\n  { NULL, kpidHostOS, VT_BSTR},\n  { \"Saved State\", kpidSavedState, VT_BOOL},\n  { NULL, kpidId, VT_BSTR}\n };\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize,\n  kpidCTime\n  \n  /*\n  { kpidNumCyls, VT_UI4},\n  { kpidNumHeads, VT_UI4},\n  { kpidSectorsPerTrack, VT_UI4}\n  */\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\n// VHD start time: 2000-01-01\nstatic const UInt64 kVhdTimeStartValue = (UInt64)3600 * 24 * (399 * 365 + 24 * 4);\n\nstatic void VhdTimeToFileTime(UInt32 vhdTime, NCOM::CPropVariant &prop)\n{\n  FILETIME ft, utc;\n  UInt64 v = (kVhdTimeStartValue + vhdTime) * 10000000;\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n  // specification says that it's UTC time, but Virtual PC 6 writes local time. Why?\n  LocalFileTimeToFileTime(&ft, &utc);\n  prop = utc;\n}\n\nstatic void StringToAString(char *dest, UInt32 val)\n{\n  for (int i = 24; i >= 0; i -= 8)\n  {\n    const Byte b = (Byte)((val >> i) & 0xFF);\n    if (b < 0x20 || b > 0x7F)\n      break;\n    *dest++ = (char)b;\n  }\n  *dest = 0;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;\n    case kpidClusterSize: if (Footer.ThereIsDynamic()) prop = (UInt32)1 << Dyn.BlockSizeLog; break;\n    case kpidShortComment:\n    case kpidMethod:\n    {\n      AString s;\n      Footer.AddTypeString(s);\n      if (NeedParent())\n      {\n        s += \" -> \";\n        const CHandler *p = this;\n        while (p && p->NeedParent())\n          p = p->Parent;\n        if (!p)\n          s += '?';\n        else\n          p->Footer.AddTypeString(s);\n      }\n      prop = s;\n      break;\n    }\n    case kpidCreatorApp:\n    {\n      char s[16];\n      StringToAString(s, Footer.CreatorApp);\n      AString res (s);\n      res.Trim();\n      res.Add_Space();\n      res.Add_UInt32(Footer.CreatorVersion >> 16);\n      res.Add_Dot();\n      res.Add_UInt32(Footer.CreatorVersion & 0xFFFF);\n      prop = res;\n      break;\n    }\n    case kpidHostOS:\n    {\n      if (Footer.CreatorHostOS == 0x5769326B)\n        prop = \"Windows\";\n      else\n      {\n        char s[16];\n        StringToAString(s, Footer.CreatorHostOS);\n        prop = s;\n      }\n      break;\n    }\n    case kpidId:\n    {\n      char s[sizeof(Footer.Id) * 2 + 2];\n      ConvertDataToHex_Upper(s, Footer.Id, sizeof(Footer.Id));\n      prop = s;\n      break;\n    }\n    case kpidSavedState: prop = Footer.SavedState ? true : false; break;\n    case kpidParent: if (NeedParent()) prop = GetParentSequence(); break;\n    case kpidOffset: prop = _startOffset; break;\n    case kpidPhySize: prop = _phySize; break;\n    case kpidTotalPhySize:\n    {\n      const CHandler *p = this;\n      UInt64 sum = 0;\n      do\n      {\n        sum += p->_phySize;\n        p = p->Parent;\n      }\n      while (p);\n      prop = sum;\n      break;\n    }\n    case kpidNumVolumes: if (NumLevels != 1) prop = (UInt32)NumLevels; break;\n\n    /*\n    case kpidErrorFlags:\n    {\n      UInt32 flags = 0;\n      if (_unexpectedEnd)\n        flags |= kpv_ErrorFlags_UnexpectedEndOfArc;\n      if (flags != 0)\n        prop = flags;\n      break;\n    }\n    */\n    case kpidError: if (!_errorMessage.IsEmpty()) prop = _errorMessage; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream, CHandler *child, IArchiveOpenCallback *openArchiveCallback, unsigned level)\n{\n  Close();\n  Stream = stream;\n  if (level > (1 << 12)) // Maybe we need to increase that limit\n    return S_FALSE;\n  \n  RINOK(Open3())\n  \n  NumLevels = 1;\n  if (child && memcmp(child->Dyn.ParentId, Footer.Id, 16) != 0)\n    return S_FALSE;\n  if (Footer.Type != kDiskType_Diff)\n    return S_OK;\n\n  bool useRelative;\n  UString name;\n  \n  if (!Dyn.RelativeParentNameFromLocator.IsEmpty())\n  {\n    useRelative = true;\n    name = Dyn.RelativeParentNameFromLocator;\n  }\n  else\n  {\n    useRelative = false;\n    name = Dyn.ParentName;\n  }\n  \n  Dyn.RelativeNameWasUsed = useRelative;\n\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveOpenVolumeCallback,\n      openVolumeCallback, openArchiveCallback)\n  \n  if (openVolumeCallback)\n  {\n    CMyComPtr<IInStream> nextStream;\n    HRESULT res = openVolumeCallback->GetStream(name, &nextStream);\n    \n    if (res == S_FALSE)\n    {\n      if (useRelative && Dyn.ParentName != Dyn.RelativeParentNameFromLocator)\n      {\n        res = openVolumeCallback->GetStream(Dyn.ParentName, &nextStream);\n        if (res == S_OK)\n          Dyn.RelativeNameWasUsed = false;\n      }\n    }\n\n    if (res != S_OK && res != S_FALSE)\n      return res;\n    \n    if (res == S_FALSE || !nextStream)\n    {\n      AddErrorMessage(\"Missing volume : \", name);\n      return S_OK;\n    }\n    \n    Parent = new CHandler;\n    ParentStream = Parent;\n    \n    res = Parent->Open2(nextStream, this, openArchiveCallback, level + 1);\n\n    if (res != S_OK)\n    {\n      Parent = NULL;\n      ParentStream.Release();\n      if (res == E_ABORT)\n        return res;\n      if (res != S_FALSE)\n      {\n        // we must show that error code\n      }\n    }\n    if (res == S_OK)\n    {\n      NumLevels = Parent->NumLevels + 1;\n    }\n  }\n  {\n    const CHandler *p = this;\n    while (p->NeedParent())\n    {\n      p = p->Parent;\n      if (!p)\n      {\n        AddErrorMessage(\"Can't open parent VHD file : \", Dyn.ParentName);\n        break;\n      }\n    }\n  }\n  return S_OK;\n}\n\n\nvoid CHandler::CloseAtError()\n{\n  // CHandlerImg:\n  Stream.Release();\n  Clear_HandlerImg_Vars();\n\n  _phySize = 0;\n  NumLevels = 0;\n  Bat.Clear();\n  NumUsedBlocks = 0;\n  Parent = NULL;\n  ParentStream.Release();\n  Dyn.Clear();\n  _errorMessage.Empty();\n  // _unexpectedEnd = false;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  CloseAtError();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidSize: prop = Footer.CurrentSize; break;\n    case kpidPackSize: prop = GetPackSize(); break;\n    case kpidCTime: VhdTimeToFileTime(Footer.CTime, prop); break;\n    case kpidExtension: prop = (_imgExt ? _imgExt : \"img\"); break;\n\n    /*\n    case kpidNumCyls: prop = Footer.NumCyls(); break;\n    case kpidNumHeads: prop = Footer.NumHeads(); break;\n    case kpidSectorsPerTrack: prop = Footer.NumSectorsPerTrack(); break;\n    */\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  if (Footer.IsFixed())\n  {\n    CMyComPtr2<ISequentialInStream, CLimitedInStream> streamSpec;\n    streamSpec.Create_if_Empty();\n    streamSpec->SetStream(Stream);\n    // fixme : check (startOffset = 0)\n    streamSpec->InitAndSeek(_startOffset, Footer.CurrentSize);\n    RINOK(streamSpec->SeekToStart())\n    *stream = streamSpec.Detach();\n    return S_OK;\n  }\n  if (!Footer.ThereIsDynamic() || !AreParentsOK())\n    return S_FALSE;\n  CMyComPtr<ISequentialInStream> streamTemp = this;\n  RINOK(InitAndSeek())\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"VHD\", \"vhd\", NULL, 0xDC,\n  kSignature,\n  0,\n  NArcInfoFlags::kUseGlobalOffset,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/VhdxHandler.cpp",
    "content": "﻿// VhdxHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/StringToInt.h\"\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"HandlerCont.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define G32(_offs_, dest) dest = Get32(p + (_offs_))\n#define G64(_offs_, dest) dest = Get64(p + (_offs_))\n\nusing namespace NWindows;\n\n\nEXTERN_C_BEGIN\n\n// CRC-32C (Castagnoli) : reversed for poly 0x1EDC6F41\n#define k_Crc32c_Poly 0x82f63b78\n\nMY_ALIGN(64)\nstatic UInt32 g_Crc32c_Table[256];\n\nstatic void Z7_FASTCALL Crc32c_GenerateTable()\n{\n  UInt32 i;\n  for (i = 0; i < 256; i++)\n  {\n    UInt32 r = i;\n    unsigned j;\n    for (j = 0; j < 8; j++)\n      r = (r >> 1) ^ (k_Crc32c_Poly & ((UInt32)0 - (r & 1)));\n    g_Crc32c_Table[i] = r;\n  }\n}\n\n\n#define CRC32C_INIT_VAL 0xFFFFFFFF\n\n#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))\n\n// UInt32 Z7_FASTCALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table);\nstatic UInt32 Z7_FASTCALL CrcUpdateT1_vhdx(UInt32 v, const void *data, size_t size, const UInt32 *table)\n{\n  const Byte *p = (const Byte *)data;\n  const Byte *pEnd = p + size;\n  for (; p != pEnd; p++)\n    v = CRC_UPDATE_BYTE_2(v, *p);\n  return v;\n}\n\nstatic UInt32 Z7_FASTCALL Crc32c_Calc(const void *data, size_t size)\n{\n  return CrcUpdateT1_vhdx(CRC32C_INIT_VAL, data, size, g_Crc32c_Table) ^ CRC32C_INIT_VAL;\n}\n\nEXTERN_C_END\n\n\nnamespace NArchive {\nnamespace NVhdx {\n\nstatic struct C_CRC32c_TableInit { C_CRC32c_TableInit() { Crc32c_GenerateTable(); } } g_CRC32c_TableInit;\n\nstatic const unsigned kSignatureSize = 8;\nstatic const Byte kSignature[kSignatureSize] =\n  { 'v', 'h', 'd', 'x', 'f', 'i', 'l', 'e' };\n\nstatic const unsigned kBitmapSize_Log = 20;\nstatic const size_t kBitmapSize = (size_t)1 << kBitmapSize_Log;\n\n\nstatic bool IsZeroArr(const Byte *p, size_t size)\n{\n  for (size_t i = 0; i < size; i++)\n    if (p[i] != 0)\n      return false;\n  return true;\n}\n\n\n\nZ7_FORCE_INLINE\nstatic int DecodeFrom2HexChars(const wchar_t *s)\n{\n  unsigned v0 = (unsigned)s[0];  Z7_PARSE_HEX_DIGIT(v0, return -1;)\n  unsigned v1 = (unsigned)s[1];  Z7_PARSE_HEX_DIGIT(v1, return -1;)\n  return (int)((v0 << 4) | v1);\n}\n\n\nstruct CGuid\n{\n  Byte Data[16];\n\n  bool IsZero() const { return IsZeroArr(Data, 16); }\n  bool IsEqualTo(const Byte *a) const { return memcmp(Data, a, 16) == 0; }\n  bool IsEqualTo(const CGuid &g) const { return IsEqualTo(g.Data); }\n  void AddHexToString(UString &s) const;\n\n  void SetFrom(const Byte *p) { memcpy(Data, p, 16); }\n\n  bool ParseFromFormatedHexString(const UString &s)\n  {\n    const unsigned kLen = 16 * 2 + 4 + 2;\n    if (s.Len() != kLen || s[0] != '{' || s[kLen - 1] != '}')\n      return false;\n    unsigned pos = 0;\n    for (unsigned i = 1; i < kLen - 1;)\n    {\n      if (i == 9 || i == 14 || i == 19 || i == 24)\n      {\n        if (s[i] != '-')\n          return false;\n        i++;\n        continue;\n      }\n      const int v = DecodeFrom2HexChars(s.Ptr(i));\n      if (v < 0)\n        return false;\n      unsigned pos2 = pos;\n      if (pos < 8)\n        pos2 ^= (pos < 4 ? 3 : 1);\n      Data[pos2] = (Byte)v;\n      pos++;\n      i += 2;\n    }\n    return true; // pos == 16;\n  }\n};\n\nvoid CGuid::AddHexToString(UString &s) const\n{\n  char temp[sizeof(Data) * 2 + 2];\n  ConvertDataToHex_Lower(temp, Data, sizeof(Data));\n  s += temp;\n}\n\n\n#define IS_NON_ALIGNED(v) (((v) & 0xFFFFF) != 0)\n\nstatic const unsigned kHeader_GUID_Index_FileWriteGuid = 0;\nstatic const unsigned kHeader_GUID_Index_DataWriteGuid = 1;\nstatic const unsigned kHeader_GUID_Index_LogGuid = 2;\n\nstruct CHeader\n{\n  UInt64 SequenceNumber;\n  // UInt16 LogVersion;\n  // UInt16 Version;\n  UInt32 LogLength;\n  UInt64 LogOffset;\n  CGuid Guids[3];\n\n  bool IsEqualTo(const CHeader &h) const\n  {\n    if (SequenceNumber != h.SequenceNumber)\n      return false;\n    if (LogLength != h.LogLength)\n      return false;\n    if (LogOffset != h.LogOffset)\n      return false;\n    for (unsigned i = 0; i < 3; i++)\n      if (!Guids[i].IsEqualTo(h.Guids[i]))\n        return false;\n    return true;\n  }\n\n  bool Parse(Byte *p);\n};\n\nstatic const unsigned kHeader2Size = 1 << 12;\n\nbool CHeader::Parse(Byte *p)\n{\n  if (Get32(p) != 0x64616568) // \"head\"\n    return false;\n  const UInt32 crc = Get32(p + 4);\n  SetUi32(p + 4, 0)\n  if (Crc32c_Calc(p, kHeader2Size) != crc)\n    return false;\n  G64(8, SequenceNumber);\n  for (unsigned i = 0; i < 3; i++)\n    Guids[i].SetFrom(p + 0x10 + 0x10 * i);\n  // LogVersion = Get16(p + 0x40);\n  /* LogVersion MUST be set to zero, for known log format\n     but we don't parse log so we ignore it */\n  G32(0x44, LogLength);\n  G64(0x48, LogOffset);\n  if (Get16(p + 0x42) != 1) // Header format Version\n    return false;\n  if (IS_NON_ALIGNED(LogLength))\n    return false;\n  if (IS_NON_ALIGNED(LogOffset))\n    return false;\n  return true;\n  // return IsZeroArr(p + 0x50, kHeader2Size - 0x50);\n}\n\n\n\nstatic const Byte kBat[16] =\n  { 0x66,0x77,0xC2,0x2D,0x23,0xF6,0x00,0x42,0x9D,0x64,0x11,0x5E,0x9B,0xFD,0x4A,0x08 };\nstatic const Byte kMetadataRegion[16] =\n  { 0x06,0xA2,0x7C,0x8B,0x90,0x47,0x9A,0x4B,0xB8,0xFE,0x57,0x5F,0x05,0x0F,0x88,0x6E };\n\nstruct CRegionEntry\n{\n  // CGuid Guid;\n  UInt64 Offset;\n  UInt32 Len;\n  UInt32 Required;\n\n  UInt64 GetEndPos() const { return Offset + Len; }\n  bool Parse(const Byte *p);\n};\n\nbool CRegionEntry::Parse(const Byte *p)\n{\n  // Guid.SetFrom(p);\n  G64(0x10, Offset);\n  G32(0x18, Len);\n  G32(0x1c, Required);\n  if (IS_NON_ALIGNED(Offset))\n    return false;\n  if (IS_NON_ALIGNED(Len))\n    return false;\n  if (Offset + Len < Offset)\n    return false;\n  return true;\n}\n  \n\nstruct CRegion\n{\n  bool Bat_Defined;\n  bool Meta_Defined;\n  UInt64 EndPos;\n  UInt64 DataSize;\n\n  CRegionEntry BatEntry;\n  CRegionEntry MetaEntry;\n\n  bool Parse(Byte *p);\n};\n\n\nstatic const size_t kRegionSize = 1 << 16;\nstatic const unsigned kNumRegionEntriesMax = (1 << 11) - 1;\n\nbool CRegion::Parse(Byte *p)\n{\n  Bat_Defined = false;\n  Meta_Defined = false;\n  EndPos = 0;\n  DataSize = 0;\n\n  if (Get32(p) != 0x69676572) // \"regi\"\n    return false;\n  const UInt32 crc = Get32(p + 4);\n  SetUi32(p + 4, 0)\n  const UInt32 crc_calced = Crc32c_Calc(p, kRegionSize);\n  if (crc_calced != crc)\n    return false;\n  \n  const UInt32 EntryCount = Get32(p + 8);\n  if (Get32(p + 12) != 0) // reserved field must be set to 0.\n    return false;\n  if (EntryCount > kNumRegionEntriesMax)\n    return false;\n  for (UInt32 i = 0; i < EntryCount; i++)\n  {\n    CRegionEntry e;\n    const Byte *p2 = p + 0x10 + 0x20 * (size_t)i;\n    if (!e.Parse(p2))\n      return false;\n    DataSize += e.Len;\n    const UInt64 endPos = e.GetEndPos();\n    if (EndPos < endPos)\n      EndPos = endPos;\n    CGuid Guid;\n    Guid.SetFrom(p2);\n    if (Guid.IsEqualTo(kBat))\n    {\n      if (Bat_Defined)\n        return false;\n      BatEntry = e;\n      Bat_Defined = true;\n    }\n    else if (Guid.IsEqualTo(kMetadataRegion))\n    {\n      if (Meta_Defined)\n        return false;\n      MetaEntry = e;\n      Meta_Defined = true;\n    }\n    else\n    {\n      if (e.Required != 0)\n        return false;\n      // it's allowed to ignore unknown non-required region entries\n    }\n  }\n  /*\n  const size_t k = 0x10 + 0x20 * EntryCount;\n  return IsZeroArr(p + k, kRegionSize - k);\n  */\n  return true;\n}\n\n\n\n\nstruct CMetaEntry\n{\n  CGuid Guid;\n  UInt32 Offset;\n  UInt32 Len;\n  UInt32 Flags0;\n  // UInt32 Flags1;\n\n  bool IsUser()        const { return (Flags0 & 1) != 0; }\n  bool IsVirtualDisk() const { return (Flags0 & 2) != 0; }\n  bool IsRequired()    const { return (Flags0 & 4) != 0; }\n\n  bool CheckLimit(size_t regionSize) const\n  {\n    return Offset <= regionSize && Len <= regionSize - Offset;\n  }\n\n  bool Parse(const Byte *p);\n};\n\n\nbool CMetaEntry::Parse(const Byte *p)\n{\n  Guid.SetFrom(p);\n  \n  G32(0x10, Offset);\n  G32(0x14, Len);\n  G32(0x18, Flags0);\n  UInt32 Flags1;\n  G32(0x1C, Flags1);\n\n  if (Offset != 0 && Offset < (1 << 16))\n    return false;\n  if (Len > (1 << 20))\n    return false;\n  if (Len == 0 && Offset != 0)\n    return false;\n  if ((Flags0 >> 3) != 0) // Reserved\n    return false;\n  if ((Flags1 & 3) != 0) // Reserved2\n    return false;\n  return true;\n}\n  \n\nstruct CParentPair\n{\n  UString Key;\n  UString Value;\n};\n\n\nstruct CMetaHeader\n{\n  // UInt16 EntryCount;\n  bool Guid_Defined;\n  bool VirtualDiskSize_Defined;\n  bool Locator_Defined;\n\n  unsigned BlockSize_Log;\n  unsigned LogicalSectorSize_Log;\n  unsigned PhysicalSectorSize_Log;\n\n  UInt32 Flags;\n  UInt64 VirtualDiskSize;\n  CGuid Guid;\n  // CGuid LocatorType;\n\n  CObjectVector<CParentPair> ParentPairs;\n\n  int FindParentKey(const char *name) const\n  {\n    FOR_VECTOR (i, ParentPairs)\n    {\n      const CParentPair &pair = ParentPairs[i];\n      if (pair.Key.IsEqualTo(name))\n        return (int)i;\n    }\n    return -1;\n  }\n\n  bool Is_LeaveBlockAllocated() const { return (Flags & 1) != 0; }\n  bool Is_HasParent() const { return (Flags & 2) != 0; }\n\n  void Clear()\n  {\n    Guid_Defined = false;\n    VirtualDiskSize_Defined = false;\n    Locator_Defined = false;\n    BlockSize_Log = 0;\n    LogicalSectorSize_Log = 0;\n    PhysicalSectorSize_Log = 0;\n    Flags = 0;\n    VirtualDiskSize = 0;\n    ParentPairs.Clear();\n  }\n\n  bool Parse(const Byte *p, size_t size);\n};\n\n\nstatic unsigned GetLogSize(UInt32 size)\n{\n  unsigned k;\n  for (k = 0; k < 32; k++)\n    if (((UInt32)1 << k) == size)\n      return k;\n  return k;\n}\n\n \nstatic const unsigned kMetadataSize = 8;\nstatic const Byte kMetadata[kMetadataSize] =\n  { 'm','e','t','a','d','a','t','a' };\n\nstatic const unsigned k_Num_MetaEntries_Max = (1 << 11) - 1;\n\nstatic const Byte kFileParameters[16] =\n  { 0x37,0x67,0xa1,0xca,0x36,0xfa,0x43,0x4d,0xb3,0xb6,0x33,0xf0,0xaa,0x44,0xe7,0x6b };\nstatic const Byte kVirtualDiskSize[16] =\n  { 0x24,0x42,0xa5,0x2f,0x1b,0xcd,0x76,0x48,0xb2,0x11,0x5d,0xbe,0xd8,0x3b,0xf4,0xb8 };\nstatic const Byte kVirtualDiskID[16] =\n  { 0xab,0x12,0xca,0xbe,0xe6,0xb2,0x23,0x45,0x93,0xef,0xc3,0x09,0xe0,0x00,0xc7,0x46 };\nstatic const Byte kLogicalSectorSize[16] =\n  { 0x1d,0xbf,0x41,0x81,0x6f,0xa9,0x09,0x47,0xba,0x47,0xf2,0x33,0xa8,0xfa,0xab,0x5f };\nstatic const Byte kPhysicalSectorSize[16] =\n  { 0xc7,0x48,0xa3,0xcd,0x5d,0x44,0x71,0x44,0x9c,0xc9,0xe9,0x88,0x52,0x51,0xc5,0x56 };\nstatic const Byte kParentLocator[16] =\n  { 0x2d,0x5f,0xd3,0xa8,0x0b,0xb3,0x4d,0x45,0xab,0xf7,0xd3,0xd8,0x48,0x34,0xab,0x0c };\n\nstatic bool GetString16(UString &s, const Byte *p, size_t size)\n{\n  s.Empty();\n  if (size & 1)\n    return false;\n  for (size_t i = 0; i < size; i += 2)\n  {\n    const wchar_t c = Get16(p + i);\n    if (c == 0)\n      return false;\n    s += c;\n  }\n  return true;\n}\n\n\nbool CMetaHeader::Parse(const Byte *p, size_t size)\n{\n  if (memcmp(p, kMetadata, kMetadataSize) != 0)\n    return false;\n  if (Get16(p + 8) != 0) // Reserved\n    return false;\n  const UInt32 EntryCount = Get16(p + 10);\n  if (EntryCount > k_Num_MetaEntries_Max)\n    return false;\n  if (!IsZeroArr(p + 12, 20)) // Reserved\n    return false;\n\n  for (unsigned i = 0; i < EntryCount; i++)\n  {\n    CMetaEntry e;\n    if (!e.Parse(p + 32 + 32 * (size_t)i))\n      return false;\n    if (!e.CheckLimit(size))\n      return false;\n    const Byte *p2 = p + e.Offset;\n    \n    if (e.Guid.IsEqualTo(kFileParameters))\n    {\n      if (BlockSize_Log != 0)\n        return false;\n      if (e.Len != 8)\n        return false;\n      const UInt32 v = Get32(p2);\n      Flags = Get32(p2 + 4);\n      BlockSize_Log = GetLogSize(v);\n      if (BlockSize_Log < 20 || BlockSize_Log > 28) // specification from 1 MB to 256 MB\n        return false;\n      if ((Flags >> 2) != 0) // reserved\n        return false;\n    }\n    else if (e.Guid.IsEqualTo(kVirtualDiskSize))\n    {\n      if (VirtualDiskSize_Defined)\n        return false;\n      if (e.Len != 8)\n        return false;\n      VirtualDiskSize = Get64(p2);\n      VirtualDiskSize_Defined = true;\n    }\n    else if (e.Guid.IsEqualTo(kVirtualDiskID))\n    {\n      if (e.Len != 16)\n        return false;\n      Guid.SetFrom(p2);\n      Guid_Defined = true;\n    }\n    else if (e.Guid.IsEqualTo(kLogicalSectorSize))\n    {\n      if (LogicalSectorSize_Log != 0)\n        return false;\n      if (e.Len != 4)\n        return false;\n      const UInt32 v = Get32(p2);\n      LogicalSectorSize_Log = GetLogSize(v);\n      if (LogicalSectorSize_Log != 9 && LogicalSectorSize_Log != 12)\n        return false;\n    }\n    else if (e.Guid.IsEqualTo(kPhysicalSectorSize))\n    {\n      if (PhysicalSectorSize_Log != 0)\n        return false;\n      if (e.Len != 4)\n        return false;\n      const UInt32 v = Get32(p2);\n      PhysicalSectorSize_Log = GetLogSize(v);\n      if (PhysicalSectorSize_Log != 9 && PhysicalSectorSize_Log != 12)\n        return false;\n    }\n    else if (e.Guid.IsEqualTo(kParentLocator))\n    {\n      if (Locator_Defined)\n        return false;\n      if (e.Len < 20)\n        return false;\n      // LocatorType.SetFrom(p2);\n      /* Specifies the type of the parent virtual disk.\n         is different for each type: VHDX, VHD or iSCSI.\n         only \"B04AEFB7-D19E-4A81-B789-25B8E9445913\" (for VHDX) is supported now\n      */\n      Locator_Defined = true;\n      if (Get16(p2 + 16) != 0) // reserved\n        return false;\n      const UInt32 KeyValueCount = Get16(p2 + 18);\n      if (20 + (UInt32)KeyValueCount * 12 > e.Len)\n        return false;\n      for (unsigned k = 0; k < KeyValueCount; k++)\n      {\n        const Byte *p3 = p2 + 20 + (size_t)k * 12;\n        const UInt32 KeyOffset   = Get32(p3);\n        const UInt32 ValueOffset = Get32(p3 + 4);\n        const UInt32 KeyLength   = Get16(p3 + 8);\n        const UInt32 ValueLength = Get16(p3 + 10);\n        if (KeyOffset > e.Len || KeyLength > e.Len - KeyOffset)\n          return false;\n        if (ValueOffset > e.Len || ValueLength > e.Len - ValueOffset)\n          return false;\n        CParentPair pair;\n        if (!GetString16(pair.Key, p2 + KeyOffset, KeyLength))\n          return false;\n        if (!GetString16(pair.Value, p2 + ValueOffset, ValueLength))\n          return false;\n        ParentPairs.Add(pair);\n      }\n    }\n    else\n    {\n      if (e.IsRequired())\n        return false;\n      // return false; // unknown metadata;\n    }\n  }\n\n  // some properties are required for correct processing\n\n  if (BlockSize_Log == 0)\n    return false;\n  if (LogicalSectorSize_Log == 0)\n    return false;\n  if (!VirtualDiskSize_Defined)\n    return false;\n  if (((UInt32)VirtualDiskSize & ((UInt32)1 << LogicalSectorSize_Log)) != 0)\n    return false;\n\n  // vhdx specification sets limit for 64 TB.\n  // do we need to check over same limit ?\n  const UInt64 kVirtualDiskSize_Max = (UInt64)1 << 46;\n  if (VirtualDiskSize > kVirtualDiskSize_Max)\n    return false;\n\n  return true;\n}\n\n\n\nstruct CBat\n{\n  CByteBuffer Data;\n\n  void Clear() { Data.Free(); }\n  UInt64 GetItem(size_t n) const\n  {\n    return Get64(Data + n * 8);\n  }\n};\n\n\n\nZ7_class_CHandler_final: public CHandlerImg\n{\n  UInt64 _phySize;\n\n  CBat Bat;\n  CObjectVector<CByteBuffer> BitMaps;\n\n  unsigned ChunkRatio_Log;\n  size_t ChunkRatio;\n  size_t TotalBatEntries;\n\n  CMetaHeader Meta;\n  CHeader Header;\n\n  UInt32 NumUsedBlocks;\n  UInt32 NumUsedBitMaps;\n  UInt64 HeadersSize;\n\n  UInt32 NumLevels;\n  UInt64 PackSize_Total;\n\n  /*\n  UInt64 NumUsed_1MB_Blocks; // data and bitmaps\n  bool NumUsed_1MB_Blocks_Defined;\n  */\n\n  CMyComPtr<IInStream> ParentStream;\n  CHandler *Parent;\n  UString _errorMessage;\n  UString _creator;\n\n  bool _nonEmptyLog;\n  bool _isDataContiguous;\n  // bool _batOverlap;\n\n  CGuid _parentGuid;\n  bool _parentGuid_IsDefined;\n  UStringVector ParentNames;\n  UString ParentName_Used;\n\n  const CHandler *_child;\n  unsigned _level;\n  bool _isCyclic;\n  bool _isCyclic_or_CyclicParent;\n\n  void AddErrorMessage(const char *message);\n  void AddErrorMessage(const char *message, const wchar_t *name);\n\n  void UpdatePhySize(UInt64 value)\n  {\n    if (_phySize < value)\n      _phySize = value;\n  }\n\n  HRESULT Seek2(UInt64 offset);\n  HRESULT Read_FALSE(Byte *data, size_t size)\n  {\n    return ReadStream_FALSE(Stream, data, size);\n  }\n  HRESULT ReadToBuf_FALSE(CByteBuffer &buf, size_t size)\n  {\n    buf.Alloc(size);\n    return ReadStream_FALSE(Stream, buf, size);\n  }\n  \n  void InitSeekPositions();\n  HRESULT ReadPhy(UInt64 offset, void *data, UInt32 size, UInt32 &processed);\n\n  bool IsDiff() const\n  {\n    // here we suppose that only HasParent() flag is mandatory for Diff archive type\n    return Meta.Is_HasParent();\n    // return _parentGuid_IsDefined;\n  }\n\n  void AddTypeString(AString &s) const\n  {\n    if (IsDiff())\n      s += \"Differencing\";\n    else\n    {\n      if (Meta.Is_LeaveBlockAllocated())\n        s +=  _isDataContiguous ? \"fixed\" : \"fixed-non-cont\";\n      else\n        s += \"dynamic\";\n    }\n  }\n\n  void AddComment(UString &s) const;\n\n  UInt64 GetPackSize() const\n  {\n    return (UInt64)NumUsedBlocks << Meta.BlockSize_Log;\n  }\n\n  UString GetParentSequence() const\n  {\n    const CHandler *p = this;\n    UString res;\n    while (p && p->IsDiff())\n    {\n      if (!res.IsEmpty())\n        res += \" -> \";\n      res += ParentName_Used;\n      p = p->Parent;\n    }\n    return res;\n  }\n\n  bool AreParentsOK() const\n  {\n    if (_isCyclic_or_CyclicParent)\n      return false;\n    const CHandler *p = this;\n    while (p->IsDiff())\n    {\n      p = p->Parent;\n      if (!p)\n        return false;\n    }\n    return true;\n  }\n\n  // bool ParseLog(CByteBuffer &log);\n  bool ParseBat();\n  bool CheckBat();\n\n  HRESULT Open3();\n  HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback) Z7_override;\n  HRESULT OpenParent(IArchiveOpenCallback *openArchiveCallback, bool &_parentFileWasOpen);\n  virtual void CloseAtError() Z7_override;\n\npublic:\n  Z7_IFACE_COM7_IMP(IInArchive_Img)\n\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n\n  CHandler():\n    _child(NULL),\n    _level(0),\n    _isCyclic(false),\n    _isCyclic_or_CyclicParent(false)\n    {}\n};\n\n\nHRESULT CHandler::Seek2(UInt64 offset)\n{\n  return InStream_SeekSet(Stream, offset);\n}\n\n\nvoid CHandler::InitSeekPositions()\n{\n  /* (_virtPos) and (_posInArc) is used only in Read() (that calls ReadPhy()).\n     So we must reset these variables before first call of Read() */\n  Reset_VirtPos();\n  Reset_PosInArc();\n  if (ParentStream)\n    Parent->InitSeekPositions();\n}\n\n\nHRESULT CHandler::ReadPhy(UInt64 offset, void *data, UInt32 size, UInt32 &processed)\n{\n  processed = 0;\n  if (offset > _phySize\n      || offset + size > _phySize)\n  {\n    // we don't expect these cases, if (_phySize) was set correctly.\n    return S_FALSE;\n  }\n  if (offset != _posInArc)\n  {\n    const HRESULT res = Seek2(offset);\n    if (res != S_OK)\n    {\n      Reset_PosInArc(); // we don't trust seek_pos in case of error\n      return res;\n    }\n    _posInArc = offset;\n  }\n  {\n    size_t size2 = size;\n    const HRESULT res = ReadStream(Stream, data, &size2);\n    processed = (UInt32)size2;\n    _posInArc += size2;\n    if (res != S_OK)\n      Reset_PosInArc(); // we don't trust seek_pos in case of reading error\n    return res;\n  }\n}\n\n\n#define PAYLOAD_BLOCK_NOT_PRESENT   0\n#define PAYLOAD_BLOCK_UNDEFINED     1\n#define PAYLOAD_BLOCK_ZERO          2\n#define PAYLOAD_BLOCK_UNMAPPED      3\n#define PAYLOAD_BLOCK_FULLY_PRESENT 6\n#define PAYLOAD_BLOCK_PARTIALLY_PRESENT 7\n\n#define SB_BLOCK_NOT_PRESENT 0\n#define SB_BLOCK_PRESENT     6\n\n#define BAT_GET_OFFSET(v) ((v) & ~(UInt64)0xFFFFF)\n#define BAT_GET_STATE(v)  ((UInt32)(v) & 7)\n\n/* The log contains only   updates to metadata, bat and region tables\n   The log doesn't contain updates to start header, and 2 headers (first 192 KB of file).\n   The log is array of 4 KB blocks and each block has 4-byte signature.\n   So it's possible to scan whole log to find the latest entry sequence (and header for replay).\n*/\n\n/*\nstruct CLogEntry\n{\n  UInt32 EntryLength;\n  UInt32 Tail;\n  UInt64 SequenceNumber;\n  CGuid LogGuid;\n  UInt32 DescriptorCount;\n  UInt64 FlushedFileOffset;\n  UInt64 LastFileOffset;\n  \n  bool Parse(const Byte *p);\n};\n\nbool CLogEntry::Parse(const Byte *p)\n{\n  G32 (8, EntryLength);\n  G32 (12,Tail);\n  G64 (16, SequenceNumber);\n  G32 (24, DescriptorCount); // it's 32-bit, but specification says 64-bit\n  if (Get32(p + 28) != 0) // reserved\n    return false;\n  LogGuid.SetFrom(p + 32);\n  G64 (48, FlushedFileOffset);\n  G64 (56, LastFileOffset);\n\n  if (SequenceNumber == 0)\n    return false;\n  if ((Tail & 0xfff) != 0)\n    return false;\n  if (IS_NON_ALIGNED(FlushedFileOffset))\n    return false;\n  if (IS_NON_ALIGNED(LastFileOffset))\n    return false;\n  return true;\n}\n\n\nbool CHandler::ParseLog(CByteBuffer &log)\n{\n  CLogEntry lastEntry;\n  lastEntry.SequenceNumber = 0;\n  bool lastEntry_found = false;\n  size_t lastEntry_Offset = 0;\n  for (size_t i = 0; i < log.Size(); i += 1 << 12)\n  {\n    Byte *p = (Byte *)(log + i);\n\n    if (Get32(p) != 0x65676F6C) // \"loge\"\n      continue;\n    const UInt32 crc = Get32(p + 4);\n\n    CLogEntry e;\n    if (!e.Parse(p))\n    {\n      return false;\n      continue;\n    }\n    const UInt32 entryLength = Get32(p + 8);\n    if (e.EntryLength > log.Size() || (e.EntryLength & 0xFFF) != 0 || e.EntryLength == 0)\n    {\n      return false;\n      continue;\n    }\n    SetUi32(p + 4, 0);\n    const UInt32 crc_calced = Crc32c_Calc(p, entryLength);\n    SetUi32(p + 4, crc); // we must restore crc if we want same data in log\n    if (crc_calced != crc)\n      continue;\n    if (!lastEntry_found || lastEntry.SequenceNumber < e.SequenceNumber)\n    {\n      lastEntry = e;\n      lastEntry_found = true;\n      lastEntry_Offset = i;\n    }\n  }\n\n  return true;\n}\n*/\n\n\nbool CHandler::ParseBat()\n{\n  ChunkRatio_Log = kBitmapSize_Log + 3 + Meta.LogicalSectorSize_Log - Meta.BlockSize_Log;\n  ChunkRatio = (size_t)1 << (ChunkRatio_Log);\n  \n  UInt64 totalBatEntries64;\n  const bool isDiff = IsDiff();\n  const UInt32 blockSize = (UInt32)1 << Meta.BlockSize_Log;\n  {\n    const UInt64 up = Meta.VirtualDiskSize + blockSize - 1;\n    if (up < Meta.VirtualDiskSize)\n      return false;\n    const UInt64 numDataBlocks = up >> Meta.BlockSize_Log;\n    \n    if (isDiff)\n    {\n      // differencing table must be finished with bitmap entry\n      const UInt64 numBitmaps = (numDataBlocks + ChunkRatio - 1) >> ChunkRatio_Log;\n      totalBatEntries64 = numBitmaps * (ChunkRatio + 1);\n    }\n    else\n    {\n      // we don't need last Bitmap entry\n      totalBatEntries64 = numDataBlocks + ((numDataBlocks - 1) >> ChunkRatio_Log);\n    }\n  }\n  \n  if (totalBatEntries64 > Bat.Data.Size() / 8)\n    return false;\n\n  const size_t totalBatEntries = (size_t)totalBatEntries64;\n  TotalBatEntries = totalBatEntries;\n  \n  bool isCont = (!isDiff && Meta.Is_LeaveBlockAllocated());\n  UInt64 prevBlockOffset = 0;\n  UInt64 maxBlockOffset = 0;\n\n  size_t remEntries = ChunkRatio + 1;\n  \n  size_t i;\n  for (i = 0; i < totalBatEntries; i++)\n  {\n    const UInt64 v = Bat.GetItem(i);\n    if ((v & 0xFFFF8) != 0)\n      return false;\n    const UInt64 offset = BAT_GET_OFFSET(v);\n    const unsigned state = BAT_GET_STATE(v);\n    \n    /*\n    UInt64 index64 = v >> 20;\n    printf(\"\\n%7d\", i);\n    printf(\"%10d, \", (unsigned)index64);\n    printf(\"%4x, \", (unsigned)state);\n    */\n    \n    remEntries--;\n    if (remEntries == 0)\n    {\n      // printf(\" ========\");\n      // printf(\"\\n\");\n      remEntries = ChunkRatio + 1;\n      if (state == SB_BLOCK_PRESENT)\n      {\n        isCont = false;\n        if (!isDiff)\n          return false;\n        if (offset == 0)\n          return false;\n        const UInt64 lim = offset + kBitmapSize;\n        if (lim < offset)\n          return false;\n        if (_phySize < lim)\n          _phySize = lim;\n        NumUsedBitMaps++;\n      }\n      else if (state != SB_BLOCK_NOT_PRESENT)\n        return false;\n    }\n    else\n    {\n      if (state == PAYLOAD_BLOCK_FULLY_PRESENT\n          || state == PAYLOAD_BLOCK_PARTIALLY_PRESENT)\n      {\n        if (offset == 0)\n          return false;\n        if (maxBlockOffset < offset)\n          maxBlockOffset = offset;\n\n        if (state == PAYLOAD_BLOCK_PARTIALLY_PRESENT)\n        {\n          isCont = false;\n          if (!isDiff)\n            return false;\n        }\n        else if (isCont)\n        {\n          if (prevBlockOffset != 0 && prevBlockOffset + blockSize != offset)\n            isCont = false;\n          else\n            prevBlockOffset = offset;\n        }\n\n        NumUsedBlocks++;\n      }\n      else if (state == PAYLOAD_BLOCK_UNMAPPED)\n      {\n        isCont = false;\n        // non-empty (offset) is allowed\n      }\n      else if (state == PAYLOAD_BLOCK_NOT_PRESENT\n          || state == PAYLOAD_BLOCK_UNDEFINED\n          || state == PAYLOAD_BLOCK_ZERO)\n      {\n        isCont = false;\n        /* (offset) is reserved and (offset == 0) is expected here,\n           but we ignore (offset) here */\n        // if (offset != 0) return false;\n      }\n      else\n        return false;\n    }\n  }\n\n  _isDataContiguous = isCont;\n\n  if (maxBlockOffset != 0)\n  {\n    const UInt64 lim = maxBlockOffset + blockSize;\n    if (lim < maxBlockOffset)\n      return false;\n    if (_phySize < lim)\n      _phySize = lim;\n    const UInt64 kPhyLimit = (UInt64)1 << 62;\n    if (maxBlockOffset >= kPhyLimit)\n      return false;\n  }\n  return true;\n}\n    \n\nbool CHandler::CheckBat()\n{\n  const UInt64 upSize = _phySize + kBitmapSize * 8 - 1;\n  if (upSize < _phySize)\n    return false;\n  const UInt64 useMapSize64 = upSize >> (kBitmapSize_Log + 3);\n  const size_t useMapSize = (size_t)useMapSize64;\n  \n  const UInt32 blockSizeMB = (UInt32)1 << (Meta.BlockSize_Log - kBitmapSize_Log);\n\n  // we don't check useMap, if it's too big.\n  if (useMapSize != useMapSize64)\n    return true;\n  if (useMapSize == 0 || useMapSize > ((size_t)1 << 28))\n    return true;\n\n  CByteArr useMap;\n  useMap.Alloc(useMapSize);\n  memset(useMap, 0, useMapSize);\n  // useMap[0] = (Byte)(1 << 0); // first 1 MB is used by headers\n  // we can also update useMap for log, and region data.\n  \n  const size_t totalBatEntries = TotalBatEntries;\n  size_t remEntries = ChunkRatio + 1;\n  \n  size_t i;\n  for (i = 0; i < totalBatEntries; i++)\n  {\n    const UInt64 v = Bat.GetItem(i);\n    const UInt64 offset = BAT_GET_OFFSET(v);\n    const unsigned state = BAT_GET_STATE(v);\n    const UInt64 index = offset >> kBitmapSize_Log;\n    UInt32 numBlocks = 1;\n    remEntries--;\n    if (remEntries == 0)\n    {\n      remEntries = ChunkRatio + 1;\n      if (state != SB_BLOCK_PRESENT)\n        continue;\n    }\n    else\n    {\n      if (state != PAYLOAD_BLOCK_FULLY_PRESENT &&\n          state != PAYLOAD_BLOCK_PARTIALLY_PRESENT)\n        continue;\n      numBlocks = blockSizeMB;\n    }\n    \n    for (unsigned k = 0; k < numBlocks; k++)\n    {\n      const UInt64 index2 = index + k;\n      const unsigned flag = (unsigned)1 << ((unsigned)index2 & 7);\n      const size_t byteIndex = (size_t)(index2 >> 3);\n      if (byteIndex >= useMapSize)\n        return false;\n      const unsigned m = useMap[byteIndex];\n      if (m & flag)\n        return false;\n      useMap[byteIndex] = (Byte)(m | flag);\n    }\n  }\n\n  /*\n  UInt64 num = 0;\n  for (i = 0; i < useMapSize; i++)\n  {\n    Byte b = useMap[i];\n    unsigned t = 0;\n    t += (b & 1);  b >>= 1;\n    t += (b & 1);  b >>= 1;\n    t += (b & 1);  b >>= 1;\n    t += (b & 1);  b >>= 1;\n    t += (b & 1);  b >>= 1;\n    t += (b & 1);  b >>= 1;\n    t += (b & 1);  b >>= 1;\n    t += (b & 1);\n    num += t;\n  }\n  NumUsed_1MB_Blocks = num;\n  NumUsed_1MB_Blocks_Defined = true;\n  */\n  \n  return true;\n}\n\n\n\nHRESULT CHandler::Open3()\n{\n  {\n    const unsigned kHeaderSize = 512; // + 8\n    Byte header[kHeaderSize];\n    \n    RINOK(Read_FALSE(header, kHeaderSize))\n\n    if (memcmp(header, kSignature, kSignatureSize) != 0)\n      return S_FALSE;\n\n    const Byte *p = &header[0];\n    for (unsigned i = kSignatureSize; i < kHeaderSize; i += 2)\n    {\n      const wchar_t c = Get16(p + i);\n      if (c < 0x20 || c > 0x7F)\n        break;\n      _creator += c;\n    }\n  }\n\n  HeadersSize = (UInt32)1 << 20;\n  CHeader headers[2];\n  {\n    Byte header[kHeader2Size];\n    for (unsigned i = 0; i < 2; i++)\n    {\n      RINOK(Seek2((1 << 16) * (1 + i)))\n      RINOK(Read_FALSE(header, kHeader2Size))\n      bool headerIsOK = headers[i].Parse(header);\n      if (!headerIsOK)\n        return S_FALSE;\n    }\n  }\n  unsigned mainIndex;\n       if (headers[0].SequenceNumber > headers[1].SequenceNumber) mainIndex = 0;\n  else if (headers[0].SequenceNumber < headers[1].SequenceNumber) mainIndex = 1;\n  else\n  {\n    /* Disk2vhd v2.02 can create image with 2 full copies of headers.\n       It's violation of VHDX specification:\n          \"A header is current if it is the only valid header\n           or if it is valid and its SequenceNumber field is\n           greater than the other header's SequenceNumber\".\n       but we support such Disk2vhd archives. */\n    if (!headers[0].IsEqualTo(headers[1]))\n      return S_FALSE;\n    mainIndex = 0;\n  }\n\n  const CHeader &h = headers[mainIndex];\n  Header = h;\n  if (h.LogLength != 0)\n  {\n    HeadersSize += h.LogLength;\n    UpdatePhySize(h.LogOffset + h.LogLength);\n    if (!h.Guids[kHeader_GUID_Index_LogGuid].IsZero())\n    {\n      _nonEmptyLog = true;\n      AddErrorMessage(\"non-empty LOG was not replayed\");\n      /*\n      if (h.LogVersion != 0)\n        AddErrorMessage(\"unknown LogVresion\");\n      else\n      {\n        CByteBuffer log;\n        RINOK(Seek2(h.LogOffset));\n        RINOK(ReadToBuf_FALSE(log, h.LogLength));\n        if (!ParseLog(log))\n        {\n          return S_FALSE;\n        }\n      }\n      */\n    }\n  }\n  CRegion regions[2];\n  int correctRegionIndex = -1;\n\n  {\n    CByteBuffer temp;\n    temp.Alloc(kRegionSize * 2);\n    RINOK(Seek2((1 << 16) * 3))\n    RINOK(Read_FALSE(temp, kRegionSize * 2))\n    unsigned numTables = 1;\n    if (memcmp(temp, temp + kRegionSize, kRegionSize) != 0)\n    {\n      AddErrorMessage(\"Region tables mismatch\");\n      numTables = 2;\n    }\n\n    for (unsigned i = 0; i < numTables; i++)\n    {\n      // RINOK(Seek2((1 << 16) * (3 + i)));\n      // RINOK(Read_FALSE(temp, kRegionSize));\n      if (regions[i].Parse(temp))\n      {\n        if (correctRegionIndex < 0)\n          correctRegionIndex = (int)i;\n      }\n      else\n      {\n        AddErrorMessage(\"Incorrect region table\");\n      }\n    }\n    if (correctRegionIndex < 0)\n      return S_FALSE;\n    /*\n    if (!regions[0].IsEqualTo(regions[1]))\n      return S_FALSE;\n    */\n  }\n  \n  // UpdatePhySize((1 << 16) * 5);\n  UpdatePhySize(1 << 20);\n  \n  {\n    const CRegion &region = regions[correctRegionIndex];\n    HeadersSize += region.DataSize;\n    UpdatePhySize(region.EndPos);\n    {\n      if (!region.Meta_Defined)\n        return S_FALSE;\n      const CRegionEntry &e = region.MetaEntry;\n      if (e.Len == 0)\n        return S_FALSE;\n      {\n        // static const kMetaTableSize = 1 << 16;\n        CByteBuffer temp;\n        {\n          RINOK(Seek2(e.Offset))\n          RINOK(ReadToBuf_FALSE(temp, e.Len))\n        }\n        if (!Meta.Parse(temp, temp.Size()))\n          return S_FALSE;\n      }\n      // UpdatePhySize(e.GetEndPos());\n    }\n    {\n      if (!region.Bat_Defined)\n        return S_FALSE;\n      const CRegionEntry &e = region.BatEntry;\n      if (e.Len == 0)\n        return S_FALSE;\n      // UpdatePhySize(e.GetEndPos());\n      {\n        RINOK(Seek2(e.Offset))\n        RINOK(ReadToBuf_FALSE(Bat.Data, e.Len))\n      }\n      if (!ParseBat())\n        return S_FALSE;\n      if (!CheckBat())\n      {\n        AddErrorMessage(\"BAT overlap\");\n        // _batOverlap = true;\n        // return S_FALSE;\n      }\n    }\n  }\n\n  {\n    // do we need to check \"parent_linkage2\" also?\n    FOR_VECTOR (i, Meta.ParentPairs)\n    {\n      const CParentPair &pair = Meta.ParentPairs[i];\n      if (pair.Key.IsEqualTo(\"parent_linkage\"))\n      {\n        _parentGuid_IsDefined = _parentGuid.ParseFromFormatedHexString(pair.Value);\n        break;\n      }\n    }\n  }\n\n  {\n    // absolute paths for parent stream can be rejected later in client callback\n    // the order of check by specification:\n    const char * const g_ParentKeys[] =\n    {\n        \"relative_path\"       // \"..\\..\\path2\\sub3\\parent.vhdx\"\n      , \"volume_path\"         // \"\\\\?\\Volume{26A21BDA-A627-11D7-9931-806E6F6E6963}\\path2\\sub3\\parent.vhdx\")\n      , \"absolute_win32_path\" // \"d:\\path2\\sub3\\parent.vhdx\"\n    };\n    for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ParentKeys); i++)\n    {\n      const int index = Meta.FindParentKey(g_ParentKeys[i]);\n      if (index < 0)\n        continue;\n      ParentNames.Add(Meta.ParentPairs[index].Value);\n    }\n  }\n\n  if (Meta.Is_HasParent())\n  {\n    if (!Meta.Locator_Defined)\n      AddErrorMessage(\"Parent locator is not defined\");\n    else\n    {\n      if (!_parentGuid_IsDefined)\n        AddErrorMessage(\"Parent GUID is not defined\");\n      if (ParentNames.IsEmpty())\n        AddErrorMessage(\"Parent VHDX file name is not defined\");\n    }\n  }\n  else\n  {\n    if (Meta.Locator_Defined)\n      AddErrorMessage(\"Unexpected parent locator\");\n  }\n\n  // here we suppose that and locator can be used only with HasParent flag\n    \n  // return S_FALSE;\n\n  _size = Meta.VirtualDiskSize; // CHandlerImg\n\n  // _posInArc = 0;\n  // Reset_PosInArc();\n  // RINOK(InStream_SeekToBegin(Stream))\n\n  return S_OK;\n}\n\n\n/*\nstatic UInt32 g_NumCalls = 0;\nstatic UInt32 g_NumCalls2 = 0;\nstatic struct CCounter { ~CCounter()\n{\n  printf(\"\\nNumCalls = %10u\\n\", g_NumCalls);\n  printf(\"NumCalls2 = %10u\\n\", g_NumCalls2);\n} } g_Counter;\n*/\n\nZ7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  // g_NumCalls++;\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= Meta.VirtualDiskSize)\n    return S_OK;\n  {\n    const UInt64 rem = Meta.VirtualDiskSize - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  if (size == 0)\n    return S_OK;\n  const size_t blockIndex = (size_t)(_virtPos >> Meta.BlockSize_Log);\n  const size_t chunkIndex = blockIndex >> ChunkRatio_Log;\n  const size_t chunkRatio = (size_t)1 << ChunkRatio_Log;\n  const size_t blockIndex2 = chunkIndex * (chunkRatio + 1) + (blockIndex & (chunkRatio - 1));\n  const UInt64 blockSectVal = Bat.GetItem(blockIndex2);\n  const UInt64 blockOffset = BAT_GET_OFFSET(blockSectVal);\n  const UInt32 blockState = BAT_GET_STATE(blockSectVal);\n\n  const UInt32 blockSize = (UInt32)1 << Meta.BlockSize_Log;\n  const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);\n  size = MyMin(blockSize - offsetInBlock, size);\n\n  bool needParent = false;\n  bool needRead = false;\n  \n  if (blockState == PAYLOAD_BLOCK_FULLY_PRESENT)\n    needRead = true;\n  else if (blockState == PAYLOAD_BLOCK_NOT_PRESENT)\n  {\n    /* for a differencing VHDX: parent virtual disk SHOULD be\n         inspected to determine the associated contents (SPECIFICATION).\n         we suppose that we should not check BitMap.\n       for fixed or dynamic VHDX files: the block contents are undefined and\n         can contain arbitrary data (SPECIFICATION). NTFS::pagefile.sys can use such state. */\n    if (IsDiff())\n      needParent = true;\n  }\n  else if (blockState == PAYLOAD_BLOCK_PARTIALLY_PRESENT)\n  {\n    // only allowed for differencing VHDX files.\n    // associated sector bitmap block MUST be valid\n    if (chunkIndex >= BitMaps.Size())\n      return S_FALSE;\n    // else\n    {\n      const CByteBuffer &bitmap = BitMaps[(unsigned)chunkIndex];\n      const Byte *p = (const Byte *)bitmap;\n      if (!p)\n        return S_FALSE;\n      // else\n      {\n        // g_NumCalls2++;\n        const UInt64 sectorIndex = _virtPos >> Meta.LogicalSectorSize_Log;\n\n        #define BIT_MAP_UNIT_LOG  3 // it's for small block (4 KB)\n        // #define BIT_MAP_UNIT_LOG  5 // speed optimization for large blocks (16 KB)\n\n        const size_t offs = (size_t)(sectorIndex >> 3) &\n            (\n              (kBitmapSize - 1)\n              & ~(((UInt32)1 << (BIT_MAP_UNIT_LOG - 3)) - 1)\n            );\n\n        unsigned sector2 = (unsigned)sectorIndex & ((1 << BIT_MAP_UNIT_LOG) - 1);\n      #if BIT_MAP_UNIT_LOG == 5\n        UInt32 v = GetUi32(p + offs) >> sector2;\n      #else\n        unsigned v = (unsigned)p[offs] >> sector2;\n      #endif\n        // UInt32 v = GetUi32(p + offs) >> sector2;\n        const UInt32 sectorSize = (UInt32)1 << Meta.LogicalSectorSize_Log;\n        const UInt32 offsetInSector = (UInt32)_virtPos & (sectorSize - 1);\n        const unsigned bit = (unsigned)(v & 1);\n        if (bit)\n          needRead = true;\n        else\n          needParent = true; // zero - from the parent VHDX file\n        UInt32 rem = sectorSize - offsetInSector;\n        for (sector2++; sector2 < (1 << BIT_MAP_UNIT_LOG); sector2++)\n        {\n          v >>= 1;\n          if (bit != (v & 1))\n            break;\n          rem += sectorSize;\n        }\n        if (size > rem)\n          size = rem;\n      }\n    }\n  }\n\n  bool needZero = true;\n\n  HRESULT res = S_OK;\n\n  if (needParent)\n  {\n    if (!ParentStream)\n      return S_FALSE;\n    // if (ParentStream)\n    {\n      RINOK(InStream_SeekSet(ParentStream, _virtPos))\n      size_t processed = size;\n      res = ReadStream(ParentStream, (Byte *)data, &processed);\n      size = (UInt32)processed;\n      needZero = false;\n    }\n  }\n  else if (needRead)\n  {\n    UInt32 processed = 0;\n    res = ReadPhy(blockOffset + offsetInBlock, data, size, processed);\n    size = processed;\n    needZero = false;\n  }\n\n  if (needZero)\n    memset(data, 0, size);\n\n  if (processedSize)\n    *processedSize = size;\n\n  _virtPos += size;\n  return res;\n}\n\n\nenum\n{\n  kpidParent = kpidUserDefined\n};\n\nstatic const CStatProp kArcProps[] =\n{\n  { NULL, kpidClusterSize, VT_UI4},\n  { NULL, kpidSectorSize, VT_UI4},\n  { NULL, kpidMethod, VT_BSTR},\n  { NULL, kpidNumVolumes, VT_UI4},\n  { NULL, kpidTotalPhySize, VT_UI8},\n  { \"Parent\", kpidParent, VT_BSTR},\n  { NULL, kpidCreatorApp, VT_BSTR},\n  { NULL, kpidComment, VT_BSTR},\n  { NULL, kpidId, VT_BSTR}\n };\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\n\nvoid CHandler::AddErrorMessage(const char *message)\n{\n  if (!_errorMessage.IsEmpty())\n    _errorMessage.Add_LF();\n  _errorMessage += message;\n}\n\nvoid CHandler::AddErrorMessage(const char *message, const wchar_t *name)\n{\n  AddErrorMessage(message);\n  _errorMessage += name;\n}\n\n\nstatic void AddComment_Name(UString &s, const char *name)\n{\n  s += name;\n  s += \": \";\n}\n\nstatic void AddComment_Bool(UString &s, const char *name, bool val)\n{\n  AddComment_Name(s, name);\n  s.Add_Char(val ? '+' : '-');\n  s.Add_LF();\n}\n\nstatic void AddComment_UInt64(UString &s, const char *name, UInt64 v, bool showMB = false)\n{\n  AddComment_Name(s, name);\n  s.Add_UInt64(v);\n  if (showMB)\n  {\n    s += \" (\";\n    s.Add_UInt64(v >> 20);\n    s += \" MiB)\";\n  }\n  s.Add_LF();\n}\n\nstatic void AddComment_BlockSize(UString &s, const char *name, unsigned logSize)\n{\n  if (logSize != 0)\n    AddComment_UInt64(s, name, ((UInt64)1 << logSize));\n}\n\n\nvoid CHandler::AddComment(UString &s) const\n{\n  AddComment_UInt64(s, \"VirtualDiskSize\", Meta.VirtualDiskSize);\n  AddComment_UInt64(s, \"PhysicalSize\", _phySize);\n\n  if (!_errorMessage.IsEmpty())\n  {\n    AddComment_Name(s, \"Error\");\n    s += _errorMessage;\n    s.Add_LF();\n  }\n\n  if (Meta.Guid_Defined)\n  {\n    AddComment_Name(s, \"Id\");\n    Meta.Guid.AddHexToString(s);\n    s.Add_LF();\n  }\n  \n  AddComment_UInt64(s, \"SequenceNumber\", Header.SequenceNumber);\n  AddComment_UInt64(s, \"LogLength\", Header.LogLength, true);\n  \n  for (unsigned i = 0; i < 3; i++)\n  {\n    const CGuid &g = Header.Guids[i];\n    if (g.IsZero())\n      continue;\n    if (i == 0)\n      s += \"FileWrite\";\n    else if (i == 1)\n      s += \"DataWrite\";\n    else\n      s += \"Log\";\n    AddComment_Name(s, \"Guid\");\n    g.AddHexToString(s);\n    s.Add_LF();\n  }\n\n  AddComment_Bool(s, \"HasParent\", Meta.Is_HasParent());\n  AddComment_Bool(s, \"Fixed\", Meta.Is_LeaveBlockAllocated());\n  if (Meta.Is_LeaveBlockAllocated())\n    AddComment_Bool(s, \"DataContiguous\", _isDataContiguous);\n  \n  AddComment_BlockSize(s, \"BlockSize\", Meta.BlockSize_Log);\n  AddComment_BlockSize(s, \"LogicalSectorSize\", Meta.LogicalSectorSize_Log);\n  AddComment_BlockSize(s, \"PhysicalSectorSize\", Meta.PhysicalSectorSize_Log);\n\n  {\n    const UInt64 packSize = GetPackSize();\n    AddComment_UInt64(s, \"PackSize\", packSize, true);\n    const UInt64 headersSize = HeadersSize + ((UInt64)NumUsedBitMaps << kBitmapSize_Log);\n    AddComment_UInt64(s, \"HeadersSize\", headersSize, true);\n    AddComment_UInt64(s, \"FreeSpace\", _phySize - packSize - headersSize, true);\n    /*\n    if (NumUsed_1MB_Blocks_Defined)\n      AddComment_UInt64(s, \"used2\", (NumUsed_1MB_Blocks << 20));\n    */\n  }\n\n  if (Meta.ParentPairs.Size() != 0)\n  {\n    s += \"Parent:\";\n    s.Add_LF();\n    FOR_VECTOR(i, Meta.ParentPairs)\n    {\n      const CParentPair &pair = Meta.ParentPairs[i];\n      s += \"  \";\n      s += pair.Key;\n      s += \": \";\n      s += pair.Value;\n      s.Add_LF();\n    }\n    s.Add_LF();\n  }\n}\n\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidClusterSize: prop = (UInt32)1 << Meta.BlockSize_Log; break;\n    case kpidSectorSize: prop = (UInt32)1 << Meta.LogicalSectorSize_Log; break;\n    case kpidShortComment:\n    case kpidMethod:\n    {\n      AString s;\n      AddTypeString(s);\n      if (IsDiff())\n      {\n        s += \" -> \";\n        const CHandler *p = this;\n        while (p && p->IsDiff())\n          p = p->Parent;\n        if (!p)\n          s += '?';\n        else\n          p->AddTypeString(s);\n      }\n      prop = s;\n      break;\n    }\n    case kpidComment:\n    {\n      UString s;\n      {\n        if (NumLevels > 1)\n        {\n          AddComment_UInt64(s, \"NumVolumeLevels\", NumLevels);\n          AddComment_UInt64(s, \"PackSizeTotal\", PackSize_Total, true);\n          s += \"----\";\n          s.Add_LF();\n        }\n\n        const CHandler *p = this;\n        for (;;)\n        {\n          if (p->_level != 0 || p->Parent)\n            AddComment_UInt64(s, \"VolumeLevel\", p->_level + 1);\n          p->AddComment(s);\n          if (!p->Parent)\n            break;\n          s += \"----\";\n          s.Add_LF();\n          {\n            s.Add_LF();\n            if (!p->ParentName_Used.IsEmpty())\n            {\n              AddComment_Name(s, \"Name\");\n              s += p->ParentName_Used;\n              s.Add_LF();\n            }\n          }\n          p = p->Parent;\n        }\n      }\n      prop = s;\n      break;\n    }\n    case kpidCreatorApp:\n    {\n      if (!_creator.IsEmpty())\n        prop = _creator;\n      break;\n    }\n    case kpidId:\n    {\n      if (Meta.Guid_Defined)\n      {\n        UString s;\n        Meta.Guid.AddHexToString(s);\n        prop = s;\n      }\n      break;\n    }\n    case kpidName:\n    {\n      if (Meta.Guid_Defined)\n      {\n        UString s;\n        Meta.Guid.AddHexToString(s);\n        s += \".vhdx\";\n        prop = s;\n      }\n      break;\n    }\n    case kpidParent: if (IsDiff()) prop = GetParentSequence(); break;\n    case kpidPhySize: prop = _phySize; break;\n    case kpidTotalPhySize:\n    {\n      const CHandler *p = this;\n      UInt64 sum = 0;\n      do\n      {\n        sum += p->_phySize;\n        p = p->Parent;\n      }\n      while (p);\n      prop = sum;\n      break;\n    }\n    case kpidNumVolumes: if (NumLevels != 1) prop = (UInt32)NumLevels; break;\n    case kpidError:\n    {\n      UString s;\n      const CHandler *p = this;\n      do\n      {\n        if (!p->_errorMessage.IsEmpty())\n        {\n          if (!s.IsEmpty())\n            s.Add_LF();\n          s += p->_errorMessage;\n        }\n        p = p->Parent;\n      }\n      while (p);\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openArchiveCallback)\n{\n  Stream = stream;\n  if (_level >= (1 << 20))\n    return S_FALSE;\n\n  RINOK(Open3())\n\n  NumLevels = 1;\n  PackSize_Total = GetPackSize();\n\n  if (_child)\n  {\n    if (!_child->_parentGuid.IsEqualTo(Header.Guids[kHeader_GUID_Index_DataWriteGuid]))\n      return S_FALSE;\n    const CHandler *child = _child;\n    do\n    {\n      /* We suppose that only FileWriteGuid is unique.\n         Another IDs must be identical in in difference and parent archives. */\n      if (Header.Guids[kHeader_GUID_Index_FileWriteGuid].IsEqualTo(\n              child->Header.Guids[kHeader_GUID_Index_FileWriteGuid])\n          && _phySize == child->_phySize)\n      {\n        _isCyclic = true;\n        _isCyclic_or_CyclicParent = true;\n        AddErrorMessage(\"Cyclic parent archive was blocked\");\n        return S_OK;\n      }\n      child = child->_child;\n    }\n    while (child);\n  }\n\n  if (!Meta.Is_HasParent())\n    return S_OK;\n\n  if (!Meta.Locator_Defined\n      || !_parentGuid_IsDefined\n      || ParentNames.IsEmpty())\n  {\n    return S_OK;\n  }\n\n  ParentName_Used = ParentNames.Front();\n\n  HRESULT res;\n  const unsigned kNumLevelsMax = (1 << 8);  // Maybe we need to increase that limit\n  if (_level >= kNumLevelsMax - 1)\n  {\n    AddErrorMessage(\"Too many parent levels\");\n    return S_OK;\n  }\n  \n  bool _parentFileWasOpen = false;\n  \n  if (!openArchiveCallback)\n    res = S_FALSE;\n  else\n    res = OpenParent(openArchiveCallback, _parentFileWasOpen);\n  \n  if (res != S_OK)\n  {\n    if (res != S_FALSE)\n      return res;\n    \n    if (_parentFileWasOpen)\n      AddErrorMessage(\"Can't parse parent VHDX file : \", ParentName_Used);\n    else\n      AddErrorMessage(\"Missing parent VHDX file : \", ParentName_Used);\n  }\n\n\n  return S_OK;\n}\n\n\nHRESULT CHandler::OpenParent(IArchiveOpenCallback *openArchiveCallback, bool &_parentFileWasOpen)\n{\n  _parentFileWasOpen = false;\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveOpenVolumeCallback,\n      openVolumeCallback, openArchiveCallback)\n  if (!openVolumeCallback)\n    return S_FALSE;\n  {\n    CMyComPtr<IInStream> nextStream;\n    HRESULT res = S_FALSE;\n    UString name;\n    \n    FOR_VECTOR (i, ParentNames)\n    {\n      name = ParentNames[i];\n      \n      // we remove prefix \".\\\\', but client already can support any variant\n      if (name[0] == L'.' && name[1] == L'\\\\')\n        name.DeleteFrontal(2);\n\n      res = openVolumeCallback->GetStream(name, &nextStream);\n\n      if (res == S_OK && nextStream)\n        break;\n         \n      if (res != S_OK && res != S_FALSE)\n        return res;\n    }\n    \n    if (res == S_FALSE || !nextStream)\n      return S_FALSE;\n    \n    ParentName_Used = name;\n    _parentFileWasOpen = true;\n\n    Parent = new CHandler;\n    ParentStream = Parent;\n\n    try\n    {\n      Parent->_level = _level + 1;\n      Parent->_child = this;\n      /* we could call CHandlerImg::Open() here.\n         but we don't need (_imgExt) in (Parent). So we call Open2() here */\n      Parent->Close();\n      res = Parent->Open2(nextStream, openArchiveCallback);\n    }\n    catch(...)\n    {\n      Parent = NULL;\n      ParentStream.Release();\n      res = S_FALSE;\n      throw;\n    }\n\n    if (res != S_OK)\n    {\n      Parent = NULL;\n      ParentStream.Release();\n      if (res == E_ABORT)\n        return res;\n      if (res != S_FALSE)\n      {\n        // we must show that error code\n      }\n    }\n\n    if (res == S_OK)\n    {\n      if (Parent->_isCyclic_or_CyclicParent)\n        _isCyclic_or_CyclicParent = true;\n\n      NumLevels = Parent->NumLevels + 1;\n      PackSize_Total += Parent->GetPackSize();\n\n      // we read BitMaps only if Parent was open\n\n      UInt64 numBytes = (UInt64)NumUsedBitMaps << kBitmapSize_Log;\n      if (openArchiveCallback && numBytes != 0)\n      {\n        RINOK(openArchiveCallback->SetTotal(NULL, &numBytes))\n      }\n      numBytes = 0;\n      for (size_t i = ChunkRatio; i < TotalBatEntries; i += ChunkRatio + 1)\n      {\n        const UInt64 v = Bat.GetItem(i);\n        const UInt64 offset = BAT_GET_OFFSET(v);\n        const unsigned state = BAT_GET_STATE(v);\n\n        CByteBuffer &buf = BitMaps.AddNew();\n        if (state == SB_BLOCK_PRESENT)\n        {\n          if (openArchiveCallback)\n          {\n            RINOK(openArchiveCallback->SetCompleted(NULL, &numBytes))\n          }\n          numBytes += kBitmapSize;\n          buf.Alloc(kBitmapSize);\n          RINOK(Seek2(offset))\n          RINOK(Read_FALSE(buf, kBitmapSize))\n          /*\n          for (unsigned i = 0; i < (1 << 20); i+=4)\n          {\n            UInt32 v = GetUi32(buf + i);\n            if (v != 0 && v != (UInt32)(Int32)-1)\n              printf(\"\\n%7d %8x\", i, v);\n          }\n          */\n        }\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\nvoid CHandler::CloseAtError()\n{\n  // CHandlerImg\n  Clear_HandlerImg_Vars();\n  Stream.Release();\n\n  _phySize = 0;\n  Bat.Clear();\n  BitMaps.Clear();\n  NumUsedBlocks = 0;\n  NumUsedBitMaps = 0;\n  HeadersSize = 0;\n  /*\n  NumUsed_1MB_Blocks = 0;\n  NumUsed_1MB_Blocks_Defined = false;\n  */\n\n  Parent = NULL;\n  ParentStream.Release();\n  _errorMessage.Empty();\n  _creator.Empty();\n  _nonEmptyLog = false;\n  _parentGuid_IsDefined = false;\n  _isDataContiguous = false;\n  // _batOverlap = false;\n\n  ParentNames.Clear();\n  ParentName_Used.Empty();\n\n  Meta.Clear();\n\n  ChunkRatio_Log = 0;\n  ChunkRatio = 0;\n  TotalBatEntries = 0;\n  NumLevels = 0;\n  PackSize_Total = 0;\n\n  _isCyclic = false;\n  _isCyclic_or_CyclicParent = false;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  CloseAtError();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidSize: prop = Meta.VirtualDiskSize; break;\n    case kpidPackSize: prop = PackSize_Total; break;\n    case kpidExtension: prop = (_imgExt ? _imgExt : \"img\"); break;\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n  // if some prarent is not OK, we don't create stream\n  if (!AreParentsOK())\n    return S_FALSE;\n  InitSeekPositions();\n  CMyComPtr<ISequentialInStream> streamTemp = this;\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\nREGISTER_ARC_I(\n  \"VHDX\", \"vhdx avhdx\", NULL, 0xc4,\n  kSignature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/VmdkHandler.cpp",
    "content": "﻿// VmdkHandler.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/StringConvert.h\"\n#include \"../../Common/StringToInt.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/ZlibDecoder.h\"\n\n#include \"HandlerCont.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NVmdk {\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define LE_16(offs, dest) dest = Get16(p + (offs))\n#define LE_32(offs, dest) dest = Get32(p + (offs))\n#define LE_64(offs, dest) dest = Get64(p + (offs))\n\n\nstatic const Byte k_Signature[] = { 'K', 'D', 'M', 'V' };\n\nstatic const UInt32 k_Flags_NL         = (UInt32)1 << 0;\n// static const UInt32 k_Flags_RGD        = (UInt32)1 << 1;\nstatic const UInt32 k_Flags_ZeroGrain  = (UInt32)1 << 2;\nstatic const UInt32 k_Flags_Compressed = (UInt32)1 << 16;\nstatic const UInt32 k_Flags_Marker     = (UInt32)1 << 17;\n\nstatic const unsigned k_NumMidBits = 9; // num bits for index in Grain Table\n\nstruct CHeader\n{\n  UInt32 flags;\n  UInt32 version;\n\n  UInt64 capacity;\n  UInt64 grainSize;\n  UInt64 descriptorOffset;\n  UInt64 descriptorSize;\n\n  UInt32 numGTEsPerGT;\n  UInt16 algo;\n  // Byte uncleanShutdown;\n  // UInt64 rgdOffset;\n  UInt64 gdOffset;\n  UInt64 overHead;\n\n  bool Is_NL()         const { return (flags & k_Flags_NL) != 0; }\n  bool Is_ZeroGrain()  const { return (flags & k_Flags_ZeroGrain) != 0; }\n  bool Is_Compressed() const { return (flags & k_Flags_Compressed) != 0; }\n  bool Is_Marker()     const { return (flags & k_Flags_Marker) != 0; }\n\n  bool Parse(const Byte *p);\n\n  bool IsSameImageFor(const CHeader &h) const\n  {\n    return flags == h.flags\n        && version == h.version\n        && capacity == h.capacity\n        && grainSize == h.grainSize\n        && algo == h.algo;\n  }\n};\n\nbool CHeader::Parse(const Byte *p)\n{\n  if (memcmp(p, k_Signature, sizeof(k_Signature)) != 0)\n    return false;\n\n  LE_32 (0x04, version);\n  LE_32 (0x08, flags);\n  LE_64 (0x0C, capacity);\n  LE_64 (0x14, grainSize);\n  LE_64 (0x1C, descriptorOffset);\n  LE_64 (0x24, descriptorSize);\n  LE_32 (0x2C, numGTEsPerGT);\n  // LE_64 (0x30, rgdOffset);\n  LE_64 (0x38, gdOffset);\n  LE_64 (0x40, overHead);\n  // uncleanShutdown = buf[0x48];\n  LE_16(0x4D, algo);\n\n  if (Is_NL() && Get32(p + 0x49) != 0x0A0D200A) // do we need Is_NL() check here?\n    return false;\n\n  return (numGTEsPerGT == (1 << k_NumMidBits)) && (version <= 3);\n}\n\n\nenum\n{\n  k_Marker_END_OF_STREAM = 0,\n  k_Marker_GRAIN_TABLE   = 1,\n  k_Marker_GRAIN_DIR     = 2,\n  k_Marker_FOOTER        = 3\n};\n\nstruct CMarker\n{\n  UInt64 NumSectors;\n  UInt32 SpecSize; // = 0 for metadata sectors\n  UInt32 Type;\n\n  void Parse(const Byte *p)\n  {\n    LE_64 (0, NumSectors);\n    LE_32 (8, SpecSize);\n    LE_32 (12, Type);\n  }\n};\n\n\nstatic bool Str_to_ValName(const AString &s, AString &name, AString &val)\n{\n  name.Empty();\n  val.Empty();\n  int qu = s.Find('\"');\n  int eq = s.Find('=');\n  if (eq < 0 || (qu >= 0 && eq > qu))\n    return false;\n  name.SetFrom(s.Ptr(), eq);\n  name.Trim();\n  val = s.Ptr(eq + 1);\n  val.Trim();\n  return true;\n}\n\nstatic inline bool IsSpaceChar(char c)\n{\n  return (c == ' ' || c == '\\t');\n}\n\nstatic const char *SkipSpaces(const char *s)\n{\n  for (;; s++)\n  {\n    char c = *s;\n    if (c == 0 || !IsSpaceChar(c))\n      return s;\n  }\n}\n\n#define SKIP_SPACES(s) s = SkipSpaces(s);\n\nstatic const char *GetNextWord(const char *s, AString &dest)\n{\n  dest.Empty();\n  SKIP_SPACES(s)\n  const char *start = s;\n  for (;; s++)\n  {\n    char c = *s;\n    if (c == 0 || IsSpaceChar(c))\n    {\n      dest.SetFrom(start, (unsigned)(s - start));\n      return s;\n    }\n  }\n}\n\nstatic const char *GetNextNumber(const char *s, UInt64 &val)\n{\n  SKIP_SPACES(s)\n  if (*s == 0)\n    return s;\n  const char *end;\n  val = ConvertStringToUInt64(s, &end);\n  char c = *end;\n  if (c != 0 && !IsSpaceChar(c))\n    return NULL;\n  return end;\n}\n\n\nstruct CExtentInfo\n{\n  AString Access;    // RW, RDONLY, or NOACCESS\n  UInt64 NumSectors; // 512 bytes sectors\n  AString Type;      // FLAT, SPARSE, ZERO, VMFS, VMFSSPARSE, VMFSRDM, VMFSRAW\n  AString FileName;\n  UInt64 StartSector; // used for FLAT\n\n  // for VMWare Player 9:\n  // PartitionUUID\n  // DeviceIdentifier\n\n  bool IsType_ZERO() const { return Type.IsEqualTo(\"ZERO\"); }\n  // bool IsType_FLAT() const { return Type.IsEqualTo(\"FLAT\"); }\n  bool IsType_Flat() const\n    { return Type.IsEqualTo(\"FLAT\")\n          || Type.IsEqualTo(\"VMFS\")\n          || Type.IsEqualTo(\"VMFSRAW\"); }\n  \n  bool Parse(const char *s);\n};\n\nbool CExtentInfo::Parse(const char *s)\n{\n  NumSectors = 0;\n  StartSector = 0;\n  Access.Empty();\n  Type.Empty();\n  FileName.Empty();\n\n  s = GetNextWord(s, Access);\n  s = GetNextNumber(s, NumSectors);\n  if (!s)\n    return false;\n  s = GetNextWord(s, Type);\n\n  if (Type.IsEmpty())\n    return false;\n\n  SKIP_SPACES(s)\n\n  if (IsType_ZERO())\n    return (*s == 0);\n\n  if (*s != '\\\"')\n    return false;\n  s++;\n  {\n    const char *s2 = strchr(s, '\\\"');\n    if (!s2)\n      return false;\n    FileName.SetFrom(s, (unsigned)(s2 - s));\n    s = s2 + 1;\n  }\n  SKIP_SPACES(s)\n  if (*s == 0)\n    return true;\n\n  s = GetNextNumber(s, StartSector);\n  if (!s)\n    return false;\n  return true;\n  // SKIP_SPACES(s);\n  // return (*s == 0);\n}\n\n\nstruct CDescriptor\n{\n  AString CID;\n  AString parentCID;\n  AString createType;\n  // AString encoding; // UTF-8, windows-1252 - default is UTF-8\n\n  CObjectVector<CExtentInfo> Extents;\n\n  static void GetUnicodeName(const AString &s, UString &res)\n  {\n    if (!ConvertUTF8ToUnicode(s, res))\n      MultiByteToUnicodeString2(res, s);\n  }\n\n  void Clear()\n  {\n    CID.Empty();\n    parentCID.Empty();\n    createType.Empty();\n    Extents.Clear();\n  }\n\n  bool IsThere_Parent() const\n  {\n    return !parentCID.IsEmpty() && !parentCID.IsEqualTo_Ascii_NoCase(\"ffffffff\");\n  }\n\n  bool Parse(const Byte *p, size_t size);\n};\n\n\nbool CDescriptor::Parse(const Byte *p, size_t size)\n{\n  Clear();\n\n  AString s;\n  AString name;\n  AString val;\n  \n  for (;;)\n  {\n    Byte c = 0;\n    if (size != 0)\n    {\n      size--;\n      c = *p++;\n    }\n    if (c == 0 || c == 0xA || c == 0xD)\n    {\n      if (!s.IsEmpty() && s[0] != '#')\n      {\n        if (Str_to_ValName(s, name, val))\n        {\n          if (name.IsEqualTo_Ascii_NoCase(\"CID\"))\n            CID = val;\n          else if (name.IsEqualTo_Ascii_NoCase(\"parentCID\"))\n            parentCID = val;\n          else if (name.IsEqualTo_Ascii_NoCase(\"createType\"))\n            createType = val;\n        }\n        else\n        {\n          CExtentInfo ei;\n          if (!ei.Parse(s))\n            return false;\n          Extents.Add(ei);\n        }\n      }\n      \n      s.Empty();\n      if (c == 0)\n        return true;\n    }\n    else\n      s += (char)c;\n  }\n}\n\n\nstruct CExtent\n{\n  bool IsOK;\n  bool IsArc;\n  bool NeedDeflate;\n  bool Unsupported;\n  bool IsZero;\n  bool IsFlat;\n  bool DescriptorOK;\n  bool HeadersError;\n\n  unsigned ClusterBits;\n  UInt32 ZeroSector;\n\n  CObjectVector<CByteBuffer> Tables;\n\n  CMyComPtr<IInStream> Stream;\n  UInt64 PosInArc;\n  \n  UInt64 PhySize;\n  UInt64 VirtSize;     // from vmdk header of volume\n\n  UInt64 StartOffset;  // virtual offset of this extent\n  UInt64 NumBytes;     // from main descriptor, if multi-vol\n  UInt64 FlatOffset;   // in Stream\n\n  CByteBuffer DescriptorBuf;\n  CDescriptor Descriptor;\n\n  CHeader h;\n\n  UInt64 GetEndOffset() const { return StartOffset + NumBytes; }\n  \n  bool IsVmdk() const { return !IsZero && !IsFlat; }\n  // if (IsOK && IsVmdk()), then VMDK header of this extent was read\n  \n  CExtent():\n      IsOK(false),\n      IsArc(false),\n      NeedDeflate(false),\n      Unsupported(false),\n      IsZero(false),\n      IsFlat(false),\n      DescriptorOK(false),\n      HeadersError(false),\n\n      ClusterBits(0),\n      ZeroSector(0),\n      \n      PosInArc(0),\n      \n      PhySize(0),\n      VirtSize(0),\n\n      StartOffset(0),\n      NumBytes(0),\n      FlatOffset(0)\n        {}\n    \n\n  HRESULT ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors);\n  HRESULT Open3(IInStream *stream, IArchiveOpenCallback *openCallback,\n        unsigned numVols, unsigned volIndex, UInt64 &complexity);\n\n  HRESULT Seek(UInt64 offset)\n  {\n    PosInArc = offset;\n    return InStream_SeekSet(Stream, offset);\n  }\n\n  HRESULT InitAndSeek()\n  {\n    if (Stream)\n      return Seek(0);\n    return S_OK;\n  }\n\n  HRESULT Read(void *data, size_t *size)\n  {\n    HRESULT res = ReadStream(Stream, data, size);\n    PosInArc += *size;\n    return res;\n  }\n};\n  \n\nZ7_class_CHandler_final: public CHandlerImg\n{\n  bool _isArc;\n  bool _unsupported;\n  bool _unsupportedSome;\n  bool _headerError;\n  bool _missingVol;\n  bool _isMultiVol;\n  bool _needDeflate;\n\n  UInt64 _cacheCluster;\n  unsigned _cacheExtent;\n  CByteBuffer _cache;\n  CByteBuffer _cacheCompressed;\n  \n  unsigned _clusterBitsMax;\n  UInt64 _phySize;\n\n  CObjectVector<CExtent> _extents;\n\n  CBufInStream *_bufInStreamSpec;\n  CMyComPtr<ISequentialInStream> _bufInStream;\n\n  CBufPtrSeqOutStream *_bufOutStreamSpec;\n  CMyComPtr<ISequentialOutStream> _bufOutStream;\n\n  NCompress::NZlib::CDecoder *_zlibDecoderSpec;\n  CMyComPtr<ICompressCoder> _zlibDecoder;\n\n  CByteBuffer _descriptorBuf;\n  CDescriptor _descriptor;\n\n  UString _missingVolName;\n  \n  void InitAndSeekMain()\n  {\n    _virtPos = 0;\n  }\n\n  virtual HRESULT Open2(IInStream *stream, IArchiveOpenCallback *openCallback) Z7_override;\n  virtual void CloseAtError() Z7_override;\npublic:\n  Z7_IFACE_COM7_IMP(IInArchive_Img)\n\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n};\n\n\nZ7_COM7F_IMF(CHandler::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= _size)\n    return S_OK;\n  {\n    UInt64 rem = _size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n    if (size == 0)\n      return S_OK;\n  }\n\n  unsigned extentIndex;\n  {\n    unsigned left = 0, right = _extents.Size();\n    for (;;)\n    {\n      unsigned mid = (left + right) / 2;\n      if (mid == left)\n        break;\n      if (_virtPos < _extents[mid].StartOffset)\n        right = mid;\n      else\n        left = mid;\n    }\n    extentIndex = left;\n  }\n  \n  CExtent &extent = _extents[extentIndex];\n\n  {\n    const UInt64 vir = _virtPos - extent.StartOffset;\n    if (vir >= extent.NumBytes)\n    {\n      return E_FAIL;\n      /*\n      if (vir > extent.NumBytes)\n        _stream_dataError = true;\n      memset(data, 0, size);\n      _virtPos += size;\n      if (processedSize)\n        *processedSize = size;\n      return S_OK;\n      */\n    }\n\n    {\n      const UInt64 rem = extent.NumBytes - vir;\n      if (size > rem)\n        size = (UInt32)rem;\n    }\n\n    if (vir >= extent.VirtSize)\n    {\n      // if vmdk's VirtSize is smaller than VirtSize from main multi-volume descriptor\n      _stream_dataError = true;\n      return S_FALSE;\n      /*\n      memset(data, 0, size);\n      _virtPos += size;\n      if (processedSize)\n        *processedSize = size;\n      return S_OK;\n      */\n    }\n\n    {\n      const UInt64 rem = extent.VirtSize - vir;\n      if (size > rem)\n        size = (UInt32)rem;\n    }\n\n    if (extent.IsZero || !extent.IsOK || !extent.Stream || extent.Unsupported)\n    {\n      if (extent.Unsupported)\n      {\n        _stream_unsupportedMethod = true;\n        return S_FALSE;\n      }\n      if (!extent.IsOK || !extent.Stream)\n      {\n        _stream_unavailData = true;\n        return S_FALSE;\n      }\n      memset(data, 0, size);\n      _virtPos += size;\n      if (processedSize)\n        *processedSize = size;\n      return S_OK;\n    }\n\n    if (extent.IsFlat)\n    {\n      UInt64 offset = extent.FlatOffset + vir;\n      if (offset != extent.PosInArc)\n      {\n        RINOK(extent.Seek(offset))\n      }\n      UInt32 size2 = 0;\n      HRESULT res = extent.Stream->Read(data, size, &size2);\n      if (res == S_OK && size2 == 0)\n      {\n        _stream_unavailData = true;\n        /*\n        memset(data, 0, size);\n        _virtPos += size;\n        if (processedSize)\n          *processedSize = size;\n        return S_OK;\n        */\n      }\n      // _stream_PackSize += size2;\n      extent.PosInArc += size2;\n      _virtPos += size2;\n      if (processedSize)\n        *processedSize = size2;\n      return res;\n    }\n  }\n\n  \n  for (;;)\n  {\n    const UInt64 vir = _virtPos - extent.StartOffset;\n    const unsigned clusterBits = extent.ClusterBits;\n    const UInt64 cluster = vir >> clusterBits;\n    const size_t clusterSize = (size_t)1 << clusterBits;\n    const size_t lowBits = (size_t)vir & (clusterSize - 1);\n    {\n      size_t rem = clusterSize - lowBits;\n      if (size > rem)\n        size = (UInt32)rem;\n    }\n\n    if (extentIndex == _cacheExtent && cluster == _cacheCluster)\n    {\n      memcpy(data, _cache + lowBits, size);\n      _virtPos += size;\n      if (processedSize)\n        *processedSize = size;\n      return S_OK;\n    }\n    \n    const UInt64 high = cluster >> k_NumMidBits;\n \n    if (high < extent.Tables.Size())\n    {\n      const CByteBuffer &table = extent.Tables[(unsigned)high];\n    \n      if (table.Size() != 0)\n      {\n        const size_t midBits = (size_t)cluster & ((1 << k_NumMidBits) - 1);\n        const Byte *p = (const Byte *)table + (midBits << 2);\n        const UInt32 v = Get32(p);\n        \n        if (v != 0 && v != extent.ZeroSector)\n        {\n          UInt64 offset = (UInt64)v << 9;\n          if (extent.NeedDeflate)\n          {\n            if (offset != extent.PosInArc)\n            {\n              // printf(\"\\n%12x %12x\\n\", (unsigned)offset, (unsigned)(offset - extent.PosInArc));\n              RINOK(extent.Seek(offset))\n            }\n            \n            const size_t kStartSize = 1 << 9;\n            {\n              size_t curSize = kStartSize;\n              RINOK(extent.Read(_cacheCompressed, &curSize))\n              // _stream_PackSize += curSize;\n              if (curSize != kStartSize)\n                return S_FALSE;\n            }\n\n            if (Get64(_cacheCompressed) != (cluster << (clusterBits - 9)))\n              return S_FALSE;\n\n            UInt32 dataSize = Get32(_cacheCompressed + 8);\n            if (dataSize > ((UInt32)1 << 31))\n              return S_FALSE;\n\n            size_t dataSize2 = (size_t)dataSize + 12;\n            \n            if (dataSize2 > kStartSize)\n            {\n              dataSize2 = (dataSize2 + 511) & ~(size_t)511;\n              if (dataSize2 > _cacheCompressed.Size())\n                return S_FALSE;\n              size_t curSize = dataSize2 - kStartSize;\n              const size_t curSize2 = curSize;\n              RINOK(extent.Read(_cacheCompressed + kStartSize, &curSize))\n              // _stream_PackSize += curSize;\n              if (curSize != curSize2)\n                return S_FALSE;\n            }\n\n            _bufInStreamSpec->Init(_cacheCompressed + 12, dataSize);\n            \n            _cacheCluster = (UInt64)(Int64)-1;\n            _cacheExtent = (unsigned)(int)-1;\n\n            if (_cache.Size() < clusterSize)\n              return E_FAIL;\n            _bufOutStreamSpec->Init(_cache, clusterSize);\n            \n            // Do we need to use smaller block than clusterSize for last cluster?\n            const UInt64 blockSize64 = clusterSize;\n            HRESULT res = _zlibDecoder->Code(_bufInStream, _bufOutStream, NULL, &blockSize64, NULL);\n\n            /*\n            if (_bufOutStreamSpec->GetPos() != clusterSize)\n            {\n              _stream_dataError = true;\n              memset(_cache + _bufOutStreamSpec->GetPos(), 0, clusterSize - _bufOutStreamSpec->GetPos());\n            }\n            */\n\n              if (_bufOutStreamSpec->GetPos() != clusterSize\n                  || _zlibDecoderSpec->GetInputProcessedSize() != dataSize)\n              {\n                _stream_dataError = true;\n                if (res == S_OK)\n                  res = S_FALSE;\n              }\n\n            RINOK(res)\n            \n            _cacheCluster = cluster;\n            _cacheExtent = extentIndex;\n            \n            continue;\n            /*\n            memcpy(data, _cache + lowBits, size);\n            _virtPos += size;\n            if (processedSize)\n              *processedSize = size;\n            return S_OK;\n            */\n          }\n          {\n            offset += lowBits;\n            if (offset != extent.PosInArc)\n            {\n              // printf(\"\\n%12x %12x\\n\", (unsigned)offset, (unsigned)(offset - extent.PosInArc));\n              RINOK(extent.Seek(offset))\n            }\n            UInt32 size2 = 0;\n            HRESULT res = extent.Stream->Read(data, size, &size2);\n            if (res == S_OK && size2 == 0)\n            {\n              _stream_unavailData = true;\n              /*\n              memset(data, 0, size);\n              _virtPos += size;\n              if (processedSize)\n                *processedSize = size;\n              return S_OK;\n              */\n            }\n            extent.PosInArc += size2;\n            // _stream_PackSize += size2;\n            _virtPos += size2;\n            if (processedSize)\n              *processedSize = size2;\n            return res;\n          }\n        }\n      }\n    }\n    \n    memset(data, 0, size);\n    _virtPos += size;\n    if (processedSize)\n      *processedSize = size;\n    return S_OK;\n  }\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidNumVolumes,\n  kpidTotalPhySize,\n  kpidMethod,\n  kpidClusterSize,\n  kpidHeadersSize,\n  kpidId,\n  kpidName,\n  kpidComment\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  \n  const CExtent *e = NULL;\n  const CDescriptor *desc = NULL;\n  \n  if (_isMultiVol)\n    desc = &_descriptor;\n  else if (_extents.Size() == 1)\n  {\n    e = &_extents[0];\n    desc = &e->Descriptor;\n  }\n\n  switch (propID)\n  {\n    case kpidMainSubfile: prop = (UInt32)0; break;\n    case kpidPhySize: if (_phySize != 0) prop = _phySize; break;\n    case kpidTotalPhySize:\n    {\n      UInt64 sum = _phySize;\n      if (_isMultiVol)\n      {\n        FOR_VECTOR (i, _extents)\n          sum += _extents[i].PhySize;\n      }\n      prop = sum;\n      break;\n    }\n    case kpidClusterSize: prop = (UInt32)((UInt32)1 << _clusterBitsMax); break;\n    case kpidHeadersSize: if (e) prop = (e->h.overHead << 9); break;\n    case kpidMethod:\n    {\n      AString s;\n\n      if (desc && !desc->createType.IsEmpty())\n        s = desc->createType;\n\n      bool zlib = false;\n      bool marker = false;\n      Int32 algo = -1;\n\n      FOR_VECTOR (i, _extents)\n      {\n        const CExtent &extent = _extents[i];\n        if (!extent.IsOK || !extent.IsVmdk())\n          continue;\n\n        const CHeader &h = extent.h;\n\n        if (h.algo != 0)\n        {\n          if (h.algo == 1)\n            zlib = true;\n          else if (algo != h.algo)\n          {\n            s.Add_Space_if_NotEmpty();\n            s.Add_UInt32(h.algo);\n            algo = h.algo;\n          }\n        }\n        \n        if (h.Is_Marker())\n          marker = true;\n      }\n\n      if (zlib)\n        s.Add_OptSpaced(\"zlib\");\n\n      if (marker)\n        s.Add_OptSpaced(\"Marker\");\n      \n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n    \n    case kpidComment:\n    {\n      if (e && e->DescriptorBuf.Size() != 0)\n      {\n        AString s;\n        s.SetFrom_CalcLen((const char *)(const Byte *)e->DescriptorBuf, (unsigned)e->DescriptorBuf.Size());\n        if (!s.IsEmpty() && s.Len() <= (1 << 16))\n          prop = s;\n      }\n      break;\n    }\n    \n    case kpidId:\n    {\n      if (desc && !desc->CID.IsEmpty())\n      {\n        prop = desc->CID;\n      }\n      break;\n    }\n\n    case kpidName:\n    {\n      if (!_isMultiVol && desc && desc->Extents.Size() == 1)\n      {\n        const CExtentInfo &ei = desc->Extents[0];\n        if (!ei.FileName.IsEmpty())\n        {\n          UString u;\n          CDescriptor::GetUnicodeName(ei.FileName, u);\n          if (!u.IsEmpty())\n            prop = u;\n        }\n      }\n      break;\n    }\n\n    case kpidNumVolumes: if (_isMultiVol) prop = (UInt32)_extents.Size(); break;\n\n    case kpidError:\n    {\n      if (_missingVol || !_missingVolName.IsEmpty())\n      {\n        UString s (\"Missing volume : \");\n        if (!_missingVolName.IsEmpty())\n          s += _missingVolName;\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!_isArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (_unsupported) v |= kpv_ErrorFlags_UnsupportedMethod;\n      if (_unsupportedSome) v |= kpv_ErrorFlags_UnsupportedMethod;\n      if (_headerError) v |= kpv_ErrorFlags_HeadersError;\n      // if (_missingVol)  v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  switch (propID)\n  {\n    case kpidSize: prop = _size; break;\n    case kpidPackSize:\n    {\n      UInt64 packSize = 0;\n      FOR_VECTOR (i, _extents)\n      {\n        const CExtent &e = _extents[i];\n        if (!e.IsOK)\n          continue;\n        if (e.IsVmdk() && !_isMultiVol)\n        {\n          UInt64 ov = (e.h.overHead << 9);\n          if (e.PhySize >= ov)\n            packSize += e.PhySize - ov;\n        }\n        else\n          packSize += e.PhySize;\n      }\n      prop = packSize;\n      break;\n    }\n    case kpidExtension: prop = (_imgExt ? _imgExt : \"img\"); break;\n  }\n  \n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nstatic int inline GetLog(UInt64 num)\n{\n  for (int i = 0; i < 64; i++)\n    if (((UInt64)1 << i) == num)\n      return i;\n  return -1;\n}\n\n\nHRESULT CExtent::ReadForHeader(IInStream *stream, UInt64 sector, void *data, size_t numSectors)\n{\n  sector <<= 9;\n  RINOK(InStream_SeekSet(stream, sector))\n  size_t size = numSectors << 9;\n  RINOK(ReadStream_FALSE(stream, data, size))\n  UInt64 end = sector + size;\n  if (PhySize < end)\n    PhySize = end;\n  return S_OK;\n}\n\n\nvoid CHandler::CloseAtError()\n{\n  _extents.Clear();\n  CHandlerImg::CloseAtError();\n}\n\n\nstatic const char * const kSignature_Descriptor = \"# Disk DescriptorFile\";\n\n\nHRESULT CHandler::Open2(IInStream *stream, IArchiveOpenCallback *openCallback)\n{\n  const unsigned kSectoreSize = 512;\n  Byte buf[kSectoreSize];\n  size_t headerSize = kSectoreSize;\n  RINOK(ReadStream(stream, buf, &headerSize))\n\n  if (headerSize < sizeof(k_Signature))\n    return S_FALSE;\n\n  CMyComPtr<IArchiveOpenVolumeCallback> volumeCallback;\n\n  if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)\n  {\n    const size_t k_SigDesc_Size = strlen(kSignature_Descriptor);\n    if (headerSize < k_SigDesc_Size)\n      return S_FALSE;\n    if (memcmp(buf, kSignature_Descriptor, k_SigDesc_Size) != 0)\n      return S_FALSE;\n\n    UInt64 endPos;\n    RINOK(InStream_GetSize_SeekToEnd(stream, endPos))\n    if (endPos > (1 << 20))\n      return S_FALSE;\n    const size_t numBytes = (size_t)endPos;\n    _descriptorBuf.Alloc(numBytes);\n    RINOK(InStream_SeekToBegin(stream))\n    RINOK(ReadStream_FALSE(stream, _descriptorBuf, numBytes))\n\n    if (!_descriptor.Parse(_descriptorBuf, _descriptorBuf.Size()))\n      return S_FALSE;\n    _isMultiVol = true;\n    _isArc = true;\n    _phySize = numBytes;\n    if (_descriptor.IsThere_Parent())\n      _unsupported = true;\n\n    if (openCallback)\n    {\n      openCallback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volumeCallback);\n    }\n    if (!volumeCallback)\n    {\n      _unsupported = true;\n      return E_NOTIMPL;\n    }\n\n    /*\n    UInt64 totalVirtSize = 0;\n    FOR_VECTOR (i, _descriptor.Extents)\n    {\n      const CExtentInfo &ei = _descriptor.Extents[i];\n      if (ei.NumSectors >= ((UInt64)1 << (63 - 9)))\n        return S_FALSE;\n      totalVirtSize += ei.NumSectors;\n      if (totalVirtSize >= ((UInt64)1 << (63 - 9)))\n        return S_FALSE;\n    }\n    totalVirtSize <<= 9;\n    */\n\n    if (_descriptor.Extents.Size() > 1)\n    {\n      const UInt64 numFiles = _descriptor.Extents.Size();\n      RINOK(openCallback->SetTotal(&numFiles, NULL))\n    }\n  }\n\n  UInt64 complexity = 0;\n\n  for (;;)\n  {\n    CExtent *e = NULL;\n    CMyComPtr<IInStream> nextStream;\n    \n    if (_isMultiVol)\n    {\n      const unsigned extentIndex = _extents.Size();\n      if (extentIndex >= _descriptor.Extents.Size())\n        break;\n      const CExtentInfo &ei = _descriptor.Extents[extentIndex];\n      e = &_extents.AddNew();\n      e->StartOffset = 0;\n      if (ei.NumSectors >= ((UInt64)1 << (62 - 9)) ||\n          ei.StartSector >= ((UInt64)1 << (62 - 9)))\n        return S_FALSE;\n      e->NumBytes = ei.NumSectors << 9;\n      e->IsZero = ei.IsType_ZERO();\n      if (extentIndex != 0)\n        e->StartOffset = _extents[extentIndex - 1].GetEndOffset();\n      if (e->GetEndOffset() < e->StartOffset)\n        return S_FALSE;\n\n      e->VirtSize = e->NumBytes;\n      if (e->IsZero)\n      {\n        e->IsOK = true;\n        continue;\n      }\n\n      e->IsFlat = ei.IsType_Flat();\n      e->FlatOffset = ei.StartSector << 9;\n\n      UString u;\n      CDescriptor::GetUnicodeName(ei.FileName, u);\n      if (u.IsEmpty())\n      {\n        _missingVol = true;\n        continue;\n      }\n\n      HRESULT result = volumeCallback->GetStream(u, &nextStream);\n\n      if (result != S_OK && result != S_FALSE)\n        return result;\n      \n      if (!nextStream || result != S_OK)\n      {\n        if (_missingVolName.IsEmpty())\n          _missingVolName = u;\n        _missingVol = true;\n        continue;\n      }\n\n      if (e->IsFlat)\n      {\n        e->IsOK = true;\n        e->Stream = nextStream;\n        e->PhySize = e->NumBytes;\n        continue;\n      }\n\n      stream = nextStream;\n\n      headerSize = kSectoreSize;\n      RINOK(ReadStream(stream, buf, &headerSize))\n\n      if (headerSize != kSectoreSize)\n        continue;\n      if (memcmp(buf, k_Signature, sizeof(k_Signature)) != 0)\n        continue;\n    }\n    else\n    {\n      if (headerSize != kSectoreSize)\n        return S_FALSE;\n      e = &_extents.AddNew();\n      e->StartOffset = 0;\n    }\n\n    HRESULT res = S_FALSE;\n    if (e->h.Parse(buf))\n      res = e->Open3(stream, openCallback, _isMultiVol ? _descriptor.Extents.Size() : 1, _extents.Size() - 1, complexity);\n    \n    if (!_isMultiVol)\n    {\n      _isArc = e->IsArc;\n      _phySize = e->PhySize;\n      _unsupported = e->Unsupported;\n    }\n\n    if (e->Unsupported)\n      _unsupportedSome = true;\n    if (e->HeadersError)\n      _headerError = true;\n\n    if (res != S_OK)\n    {\n      if (res != S_FALSE)\n        return res;\n      if (!_isMultiVol)\n        return res;\n      continue;\n    }\n\n    e->Stream = stream;\n    e->IsOK = true;\n    \n    if (!_isMultiVol)\n    {\n      e->NumBytes = e->VirtSize;\n      break;\n    }\n\n    if (e->NumBytes != e->VirtSize)\n      _headerError = true;\n  }\n\n  if (!_extents.IsEmpty())\n    _size = _extents.Back().GetEndOffset();\n\n  _needDeflate = false;\n  _clusterBitsMax = 0;\n  \n  // unsigned numOKs = 0;\n  unsigned numUnsupported = 0;\n\n  FOR_VECTOR (i, _extents)\n  {\n    const CExtent &e = _extents[i];\n    if (e.Unsupported)\n      numUnsupported++;\n    if (!e.IsOK)\n      continue;\n    // numOKs++;\n    if (e.IsVmdk())\n    {\n      if (e.NeedDeflate)\n        _needDeflate = true;\n      if (_clusterBitsMax < e.ClusterBits)\n        _clusterBitsMax = e.ClusterBits;\n    }\n  }\n\n  if (numUnsupported != 0 && numUnsupported == _extents.Size())\n    _unsupported = true;\n\n  return S_OK;\n}\n\n\nHRESULT CExtent::Open3(IInStream *stream, IArchiveOpenCallback *openCallback,\n    unsigned numVols, unsigned volIndex, UInt64 &complexity)\n{\n  if (h.descriptorSize != 0)\n  {\n    if (h.descriptorOffset == 0 ||\n        h.descriptorSize > (1 << 10))\n      return S_FALSE;\n    DescriptorBuf.Alloc((size_t)h.descriptorSize << 9);\n    RINOK(ReadForHeader(stream, h.descriptorOffset, DescriptorBuf, (size_t)h.descriptorSize))\n    if (h.descriptorOffset == 1 && h.Is_Marker() && Get64(DescriptorBuf) == 0)\n    {\n      // We check data as end marker.\n      // and if probably it's footer's copy of header, we don't want to open it.\n      return S_FALSE;\n    }\n\n    DescriptorOK = Descriptor.Parse(DescriptorBuf, DescriptorBuf.Size());\n    if (!DescriptorOK)\n      HeadersError = true;\n    if (Descriptor.IsThere_Parent())\n      Unsupported = true;\n  }\n\n  if (h.gdOffset == (UInt64)(Int64)-1)\n  {\n    // Grain Dir is at end of file\n    UInt64 endPos;\n    RINOK(InStream_GetSize_SeekToEnd(stream, endPos))\n    if ((endPos & 511) != 0)\n      return S_FALSE;\n\n    const size_t kEndSize = 512 * 3;\n    Byte buf2[kEndSize];\n    if (endPos < kEndSize)\n      return S_FALSE;\n    RINOK(InStream_SeekSet(stream, endPos - kEndSize))\n    RINOK(ReadStream_FALSE(stream, buf2, kEndSize))\n    \n    CHeader h2;\n    if (!h2.Parse(buf2 + 512))\n      return S_FALSE;\n    if (!h.IsSameImageFor(h2))\n      return S_FALSE;\n\n    h = h2;\n\n    CMarker m;\n    m.Parse(buf2);\n    if (m.NumSectors != 1 || m.SpecSize != 0 || m.Type != k_Marker_FOOTER)\n      return S_FALSE;\n    m.Parse(buf2 + 512 * 2);\n    if (m.NumSectors != 0 || m.SpecSize != 0 || m.Type != k_Marker_END_OF_STREAM)\n      return S_FALSE;\n    PhySize = endPos;\n  }\n\n  const int grainSize_Log = GetLog(h.grainSize);\n  if (grainSize_Log < 3 || grainSize_Log > 30 - 9) // grain size must be >= 4 KB\n    return S_FALSE;\n  if (h.capacity >= ((UInt64)1 << (63 - 9)))\n    return S_FALSE;\n  if (h.overHead >= ((UInt64)1 << (63 - 9)))\n    return S_FALSE;\n\n  IsArc = true;\n  ClusterBits = (9 + (unsigned)grainSize_Log);\n  VirtSize = h.capacity << 9;\n  NeedDeflate = (h.algo >= 1);\n\n  if (h.Is_Compressed() ? (h.algo > 1 || !h.Is_Marker()) : (h.algo != 0))\n  {\n    Unsupported = true;\n    PhySize = 0;\n    return S_FALSE;\n  }\n\n  {\n    const UInt64 overHeadBytes = h.overHead << 9;\n    if (PhySize < overHeadBytes)\n      PhySize = overHeadBytes;\n  }\n\n  ZeroSector = 0;\n  if (h.Is_ZeroGrain())\n    ZeroSector = 1;\n\n  const UInt64 numSectorsPerGde = (UInt64)1 << ((unsigned)grainSize_Log + k_NumMidBits);\n  const UInt64 numGdeEntries = (h.capacity + numSectorsPerGde - 1) >> ((unsigned)grainSize_Log + k_NumMidBits);\n  CByteBuffer table;\n  \n  if (numGdeEntries != 0)\n  {\n    if (h.gdOffset == 0)\n      return S_FALSE;\n\n    size_t numSectors = (size_t)((numGdeEntries + ((1 << (9 - 2)) - 1)) >> (9 - 2));\n    size_t t1SizeBytes = numSectors << 9;\n    if ((t1SizeBytes >> 2) < numGdeEntries)\n      return S_FALSE;\n    table.Alloc(t1SizeBytes);\n\n    if (h.Is_Marker())\n    {\n      Byte buf2[1 << 9];\n      if (ReadForHeader(stream, h.gdOffset - 1, buf2, 1) != S_OK)\n        return S_FALSE;\n      {\n        CMarker m;\n        m.Parse(buf2);\n        if (m.Type != k_Marker_GRAIN_DIR\n            || m.NumSectors != numSectors\n            || m.SpecSize != 0)\n          return S_FALSE;\n      }\n    }\n\n    RINOK(ReadForHeader(stream, h.gdOffset, table, numSectors))\n  }\n\n  const size_t clusterSize = (size_t)1 << ClusterBits;\n\n  const UInt64 complexityStart = complexity;\n\n  if (openCallback)\n  {\n    complexity += (UInt64)numGdeEntries << (k_NumMidBits + 2);\n    {\n      const UInt64 numVols2 = numVols;\n      RINOK(openCallback->SetTotal((numVols == 1) ? NULL : &numVols2, &complexity))\n    }\n    if (numVols != 1)\n    {\n      const UInt64 volIndex2 = volIndex;\n      RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &complexityStart))\n    }\n  }\n\n  UInt64 lastSector = 0;\n  UInt64 lastVirtCluster = 0;\n  size_t numProcessed_Prev = 0;\n\n  for (size_t i = 0; i < numGdeEntries; i++)\n  {\n    const size_t k_NumSectors = (size_t)1 << (k_NumMidBits - 9 + 2);\n    const size_t k_NumMidItems = (size_t)1 << k_NumMidBits;\n\n    CByteBuffer &buf = Tables.AddNew();\n\n    {\n      const UInt32 v = Get32((const Byte *)table + (size_t)i * 4);\n      if (v == 0 || v == ZeroSector)\n        continue;\n      if (openCallback && (i - numProcessed_Prev) >= 1024)\n      {\n        const UInt64 comp = complexityStart + ((UInt64)i << (k_NumMidBits + 2));\n        const UInt64 volIndex2 = volIndex;\n        RINOK(openCallback->SetCompleted(numVols == 1 ? NULL : &volIndex2, &comp))\n        numProcessed_Prev = i;\n      }\n      \n      if (h.Is_Marker())\n      {\n        Byte buf2[1 << 9];\n        if (ReadForHeader(stream, v - 1, buf2, 1) != S_OK)\n          return S_FALSE;\n        {\n          CMarker m;\n          m.Parse(buf2);\n          if (m.Type != k_Marker_GRAIN_TABLE\n            || m.NumSectors != k_NumSectors\n            || m.SpecSize != 0)\n            return S_FALSE;\n        }\n      }\n      \n      buf.Alloc(k_NumMidItems * 4);\n      RINOK(ReadForHeader(stream, v, buf, k_NumSectors))\n    }\n\n    for (size_t k = 0; k < k_NumMidItems; k++)\n    {\n      const UInt32 v = Get32((const Byte *)buf + (size_t)k * 4);\n      if (v == 0 || v == ZeroSector)\n        continue;\n      if (v < h.overHead)\n        return S_FALSE;\n      if (lastSector < v)\n      {\n        lastSector = v;\n        if (NeedDeflate)\n          lastVirtCluster = ((UInt64)i << k_NumMidBits) + k;\n      }\n    }\n  }\n\n  if (!NeedDeflate)\n  {\n    UInt64 end = ((UInt64)lastSector << 9) + clusterSize;\n    if (PhySize < end)\n      PhySize = end;\n  }\n  else if (lastSector != 0)\n  {\n    Byte buf[1 << 9];\n    if (ReadForHeader(stream, lastSector, buf, 1) == S_OK)\n    {\n      UInt64 lba = Get64(buf);\n      if (lba == (lastVirtCluster << (ClusterBits - 9)))\n      {\n        UInt32 dataSize = Get32(buf + 8);\n        size_t dataSize2 = (size_t)dataSize + 12;\n        dataSize2 = (dataSize2 + 511) & ~(size_t)511;\n        UInt64 end = ((UInt64)lastSector << 9) + dataSize2;\n        if (PhySize < end)\n          PhySize = end;\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _phySize = 0;\n  \n  _cacheCluster = (UInt64)(Int64)-1;\n  _cacheExtent = (unsigned)(int)-1;\n\n  _clusterBitsMax = 0;\n\n  _isArc = false;\n  _unsupported = false;\n  _unsupportedSome = false;\n  _headerError = false;\n  _missingVol = false;\n  _isMultiVol = false;\n  _needDeflate = false;\n\n  _missingVolName.Empty();\n\n  _descriptorBuf.Free();\n  _descriptor.Clear();\n\n  // CHandlerImg:\n  Clear_HandlerImg_Vars();\n  Stream.Release();\n\n  _extents.Clear();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 /* index */, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  *stream = NULL;\n\n  if (_unsupported)\n    return S_FALSE;\n\n  ClearStreamVars();\n  // _stream_UsePackSize = true;\n\n  if (_needDeflate)\n  {\n    if (!_bufInStream)\n    {\n      _bufInStreamSpec = new CBufInStream;\n      _bufInStream = _bufInStreamSpec;\n    }\n    \n    if (!_bufOutStream)\n    {\n      _bufOutStreamSpec = new CBufPtrSeqOutStream();\n      _bufOutStream = _bufOutStreamSpec;\n    }\n\n    if (!_zlibDecoder)\n    {\n      _zlibDecoderSpec = new NCompress::NZlib::CDecoder;\n      _zlibDecoder = _zlibDecoderSpec;\n    }\n    \n    const size_t clusterSize = (size_t)1 << _clusterBitsMax;\n    _cache.AllocAtLeast(clusterSize);\n    _cacheCompressed.AllocAtLeast(clusterSize * 2);\n  }\n\n  FOR_VECTOR (i, _extents)\n  {\n    RINOK(_extents[i].InitAndSeek())\n  }\n\n  CMyComPtr<ISequentialInStream> streamTemp = this;\n  InitAndSeekMain();\n  *stream = streamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\nREGISTER_ARC_I(\n  \"VMDK\", \"vmdk\", NULL, 0xC8,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Wim/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Wim/WimHandler.cpp",
    "content": "﻿// WimHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n\n#include \"../../Common/MethodProps.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"WimHandler.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NWim {\n\n#define FILES_DIR_NAME \"[DELETED]\"\n\n// #define WIM_DETAILS\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidAttrib,\n  kpidMethod,\n  kpidSolid,\n  kpidShortName,\n  kpidINode,\n  kpidLinks,\n  kpidIsAltStream,\n  kpidNumAltStreams,\n  \n  #ifdef WIM_DETAILS\n  , kpidVolume\n  , kpidOffset\n  #endif\n};\n\nenum\n{\n  kpidNumImages = kpidUserDefined,\n  kpidBootImage\n};\n\nstatic const CStatProp kArcProps[] =\n{\n  { NULL, kpidSize, VT_UI8},\n  { NULL, kpidPackSize, VT_UI8},\n  { NULL, kpidMethod, VT_BSTR},\n  { NULL, kpidClusterSize, VT_UI4},\n  { NULL, kpidCTime, VT_FILETIME},\n  { NULL, kpidMTime, VT_FILETIME},\n  { NULL, kpidComment, VT_BSTR},\n  { NULL, kpidUnpackVer, VT_BSTR},\n  { NULL, kpidIsVolume, VT_BOOL},\n  { NULL, kpidVolume, VT_UI4},\n  { NULL, kpidNumVolumes, VT_UI4},\n  { \"Images\", kpidNumImages, VT_UI4},\n  { \"Boot Image\", kpidBootImage, VT_UI4}\n};\n\n\nstatic const char * const k_Methods[] =\n{\n    \"Copy\"\n  , \"XPress\"\n  , \"LZX\"\n  , \"LZMS\"\n};\n\n\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_WITH_NAME\n\nstatic void AddErrorMessage(AString &s, const char *message)\n{\n  if (!s.IsEmpty())\n    s += \". \";\n  s += message;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CImageInfo *image = NULL;\n  if (_xmls.Size() == 1)\n  {\n    const CWimXml &xml = _xmls[0];\n    if (xml.Images.Size() == 1)\n      image = &xml.Images[0];\n  }\n\n  switch (propID)\n  {\n    case kpidPhySize:  prop = _phySize; break;\n    case kpidSize: prop = _db.GetUnpackSize(); break;\n    case kpidPackSize: prop = _db.GetPackSize(); break;\n    \n    case kpidCTime:\n      if (_xmls.Size() == 1)\n      {\n        const CWimXml &xml = _xmls[0];\n        int index = -1;\n        FOR_VECTOR (i, xml.Images)\n        {\n          const CImageInfo &image2 = xml.Images[i];\n          if (image2.CTimeDefined)\n            if (index < 0 || ::CompareFileTime(&image2.CTime, &xml.Images[index].CTime) < 0)\n              index = (int)i;\n        }\n        if (index >= 0)\n          prop = xml.Images[index].CTime;\n      }\n      break;\n\n    case kpidMTime:\n      if (_xmls.Size() == 1)\n      {\n        const CWimXml &xml = _xmls[0];\n        int index = -1;\n        FOR_VECTOR (i, xml.Images)\n        {\n          const CImageInfo &image2 = xml.Images[i];\n          if (image2.MTimeDefined)\n            if (index < 0 || ::CompareFileTime(&image2.MTime, &xml.Images[index].MTime) > 0)\n              index = (int)i;\n        }\n        if (index >= 0)\n          prop = xml.Images[index].MTime;\n      }\n      break;\n\n    case kpidComment:\n      if (image)\n      {\n        if (_xmlInComments)\n        {\n          UString s;\n          _xmls[0].ToUnicode(s);\n          prop = s;\n        }\n        else if (image->NameDefined)\n          prop = image->Name;\n      }\n      break;\n\n    case kpidUnpackVer:\n    {\n      UInt32 ver1 = _version >> 16;\n      UInt32 ver2 = (_version >> 8) & 0xFF;\n      UInt32 ver3 = (_version) & 0xFF;\n\n      AString res;\n      res.Add_UInt32(ver1);\n      res.Add_Dot();\n      res.Add_UInt32(ver2);\n      if (ver3 != 0)\n      {\n        res.Add_Dot();\n        res.Add_UInt32(ver3);\n      }\n      prop = res;\n      break;\n    }\n\n    case kpidIsVolume:\n      if (_xmls.Size() > 0)\n      {\n        UInt16 volIndex = _xmls[0].VolIndex;\n        if (volIndex < _volumes.Size())\n          prop = (_volumes[volIndex].Header.NumParts > 1);\n      }\n      break;\n    case kpidVolume:\n      if (_xmls.Size() > 0)\n      {\n        UInt16 volIndex = _xmls[0].VolIndex;\n        if (volIndex < _volumes.Size())\n          prop = (UInt32)_volumes[volIndex].Header.PartNumber;\n      }\n      break;\n    case kpidNumVolumes: if (_volumes.Size() > 0) prop = (UInt32)(_volumes.Size() - 1); break;\n    \n    case kpidClusterSize:\n      if (_xmls.Size() > 0)\n      {\n        UInt16 volIndex = _xmls[0].VolIndex;\n        if (volIndex < _volumes.Size())\n        {\n          const CHeader &h = _volumes[volIndex].Header;\n          prop = (UInt32)1 << h.ChunkSizeBits;\n        }\n      }\n      break;\n\n    case kpidName:\n      if (_firstVolumeIndex >= 0)\n      {\n        const CHeader &h = _volumes[_firstVolumeIndex].Header;\n        if (GetUi32(h.Guid) != 0)\n        {\n          char temp[64];\n          RawLeGuidToString(h.Guid, temp);\n          temp[8] = 0; // for reduced GUID\n          AString s (temp);\n          const char *ext = \".wim\";\n          if (h.NumParts != 1)\n          {\n            s += '_';\n            if (h.PartNumber != 1)\n              s.Add_UInt32(h.PartNumber);\n            ext = \".swm\";\n          }\n          s += ext;\n          prop = s;\n        }\n      }\n      break;\n\n    case kpidExtension:\n      if (_firstVolumeIndex >= 0)\n      {\n        const CHeader &h = _volumes[_firstVolumeIndex].Header;\n        if (h.NumParts > 1)\n        {\n          AString s;\n          if (h.PartNumber != 1)\n          {\n            s.Add_UInt32(h.PartNumber);\n            s.Add_Dot();\n          }\n          s += \"swm\";\n          prop = s;\n        }\n      }\n      break;\n\n    case kpidNumImages: prop = (UInt32)_db.Images.Size(); break;\n    case kpidBootImage: if (_bootIndex != 0) prop = (UInt32)_bootIndex; break;\n    \n    case kpidMethod:\n    {\n      UInt32 methodUnknown = 0;\n      UInt32 methodMask = 0;\n      unsigned chunkSizeBits = 0;\n      \n      {\n        FOR_VECTOR (i, _xmls)\n        {\n          const CHeader &header = _volumes[_xmls[i].VolIndex].Header;\n          unsigned method = header.GetMethod();\n          if (method < Z7_ARRAY_SIZE(k_Methods))\n            methodMask |= ((UInt32)1 << method);\n          else\n            methodUnknown = method;\n          if (chunkSizeBits < header.ChunkSizeBits)\n            chunkSizeBits = header.ChunkSizeBits;\n        }\n      }\n\n      AString res;\n\n      unsigned numMethods = 0;\n\n      for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_Methods); i++)\n      {\n        if (methodMask & ((UInt32)1 << i))\n        {\n          res.Add_Space_if_NotEmpty();\n          res += k_Methods[i];\n          numMethods++;\n        }\n      }\n\n      if (methodUnknown != 0)\n      {\n        res.Add_Space_if_NotEmpty();\n        res.Add_UInt32(methodUnknown);\n        numMethods++;\n      }\n\n      if (numMethods == 1 && chunkSizeBits != 0)\n      {\n        res.Add_Colon();\n        res.Add_UInt32((UInt32)chunkSizeBits);\n      }\n\n      prop = res;\n      break;\n    }\n    \n    case kpidIsTree: prop = true; break;\n    case kpidIsAltStream: prop = _db.ThereAreAltStreams; break;\n    case kpidIsAux: prop = true; break;\n    // WIM uses special prefix to represent deleted items\n    // case kpidIsDeleted: prop = _db.ThereAreDeletedStreams; break;\n    case kpidINode: prop = true; break;\n\n    case kpidErrorFlags:\n    {\n      UInt32 flags = 0;\n      if (!_isArc) flags |= kpv_ErrorFlags_IsNotArc;\n      if (_db.HeadersError) flags |= kpv_ErrorFlags_HeadersError;\n      if (_unsupported) flags |= kpv_ErrorFlags_UnsupportedMethod;\n      prop = flags;\n      break;\n    }\n\n    case kpidWarning:\n    {\n      AString s;\n      if (_xmlError)\n        AddErrorMessage(s, \"XML error\");\n      if (_db.RefCountError)\n        AddErrorMessage(s, \"Some files have incorrect reference count\");\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidReadOnly:\n    {\n      bool readOnly = !IsUpdateSupported();\n      if (readOnly)\n        prop = readOnly;\n      break;\n    }\n  }\n\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nstatic void GetFileTime(const Byte *p, NCOM::CPropVariant &prop)\n{\n  prop.vt = VT_FILETIME;\n  prop.filetime.dwLowDateTime = Get32(p);\n  prop.filetime.dwHighDateTime = Get32(p + 4);\n  prop.Set_FtPrec(k_PropVar_TimePrec_100ns);\n}\n\n\nstatic void MethodToProp(int method, int chunksSizeBits, NCOM::CPropVariant &prop)\n{\n  if (method >= 0)\n  {\n    char temp[32];\n    \n    if ((unsigned)method < Z7_ARRAY_SIZE(k_Methods))\n      MyStringCopy(temp, k_Methods[(unsigned)method]);\n    else\n      ConvertUInt32ToString((UInt32)(unsigned)method, temp);\n    \n    if (chunksSizeBits >= 0)\n    {\n      size_t pos = strlen(temp);\n      temp[pos++] = ':';\n      ConvertUInt32ToString((unsigned)chunksSizeBits, temp + pos);\n    }\n    \n    prop = temp;\n  }\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  if (index < _db.SortedItems.Size())\n  {\n    unsigned realIndex = _db.SortedItems[index];\n    const CItem &item = _db.Items[realIndex];\n    const CStreamInfo *si = NULL;\n    const CVolume *vol = NULL;\n    if (item.StreamIndex >= 0)\n    {\n      si = &_db.DataStreams[item.StreamIndex];\n      vol = &_volumes[si->PartNumber];\n    }\n\n    const CItem *mainItem = &item;\n    if (item.IsAltStream)\n      mainItem = &_db.Items[item.Parent];\n    const Byte *metadata = NULL;\n    if (mainItem->ImageIndex >= 0)\n      metadata = _db.Images[mainItem->ImageIndex].Meta + mainItem->Offset;\n\n    switch (propID)\n    {\n      case kpidPath:\n        if (item.ImageIndex >= 0)\n          _db.GetItemPath(realIndex, _showImageNumber, prop);\n        else\n        {\n          /*\n          while (s.Len() < _nameLenForStreams)\n            s = '0' + s;\n          */\n          /*\n          if (si->Resource.IsFree())\n            s = (AString)(\"[Free]\" STRING_PATH_SEPARATOR) + sz;\n          else\n          */\n          AString s (FILES_DIR_NAME STRING_PATH_SEPARATOR);\n          s.Add_UInt32((UInt32)(Int32)item.StreamIndex);\n          prop = s;\n        }\n        break;\n      \n      case kpidName:\n        if (item.ImageIndex >= 0)\n          _db.GetItemName(realIndex, prop);\n        else\n        {\n          char sz[16];\n          ConvertUInt32ToString((UInt32)(Int32)item.StreamIndex, sz);\n          /*\n          AString s = sz;\n          while (s.Len() < _nameLenForStreams)\n            s = '0' + s;\n          */\n          prop = sz;\n        }\n        break;\n\n      case kpidShortName:\n        if (item.ImageIndex >= 0 && !item.IsAltStream)\n          _db.GetShortName(realIndex, prop);\n        break;\n\n      case kpidPackSize:\n      {\n        if (si)\n        {\n          if (!si->Resource.IsSolidSmall())\n            prop = si->Resource.PackSize;\n          else\n          {\n            if (si->Resource.SolidIndex >= 0)\n            {\n              const CSolid &ss = _db.Solids[(unsigned)si->Resource.SolidIndex];\n              if (ss.FirstSmallStream == item.StreamIndex)\n                prop = _db.DataStreams[ss.StreamIndex].Resource.PackSize;\n            }\n          }\n        }\n        else if (!item.IsDir)\n          prop = (UInt64)0;\n\n        break;\n      }\n\n      case kpidSize:\n      {\n        if (si)\n        {\n          if (si->Resource.IsSolid())\n          {\n            if (si->Resource.IsSolidBig())\n            {\n              if (si->Resource.SolidIndex >= 0)\n              {\n                const CSolid &ss = _db.Solids[(unsigned)si->Resource.SolidIndex];\n                prop = ss.UnpackSize;\n              }\n            }\n            else\n              prop = si->Resource.PackSize;\n          }\n          else\n            prop = si->Resource.UnpackSize;\n        }\n        else if (!item.IsDir)\n          prop = (UInt64)0;\n\n        break;\n      }\n      \n      case kpidIsDir: prop = item.IsDir; break;\n      case kpidIsAltStream: prop = item.IsAltStream; break;\n      case kpidNumAltStreams:\n      {\n        if (!item.IsAltStream && mainItem->HasMetadata())\n        {\n          UInt32 dirRecordSize = _db.IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;\n          UInt32 numAltStreams = Get16(metadata + dirRecordSize - 6);\n          if (numAltStreams != 0)\n          {\n            if (!item.IsDir)\n              numAltStreams--;\n            prop = numAltStreams;\n          }\n        }\n        break;\n      }\n\n      case kpidAttrib:\n        if (!item.IsAltStream && mainItem->ImageIndex >= 0)\n        {\n          /*\n          if (fileNameLen == 0 && isDir && !item.HasStream())\n            item.Attrib = 0x10; // some swm archives have system/hidden attributes for root\n          */\n          prop = (UInt32)Get32(metadata + 8);\n        }\n        break;\n      case kpidCTime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x18: 0x28), prop); break;\n      case kpidATime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x20: 0x30), prop); break;\n      case kpidMTime: if (mainItem->HasMetadata()) GetFileTime(metadata + (_db.IsOldVersion ? 0x28: 0x38), prop); break;\n\n      case kpidINode:\n        if (mainItem->HasMetadata() && !_isOldVersion)\n        {\n          UInt32 attrib = (UInt32)Get32(metadata + 8);\n          if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0)\n          {\n            // we don't know about that field in OLD WIM format\n            unsigned offset = 0x58; // (_db.IsOldVersion ? 0x30: 0x58);\n            UInt64 val = Get64(metadata + offset);\n            if (val != 0)\n              prop = val;\n          }\n        }\n        break;\n\n      case kpidStreamId:\n        if (item.StreamIndex >= 0)\n          prop = (UInt32)item.StreamIndex;\n        break;\n\n      case kpidMethod:\n          if (si)\n          {\n            const CResource &r = si->Resource;\n            if (r.IsSolid())\n            {\n              if (r.SolidIndex >= 0)\n              {\n                CSolid &ss = _db.Solids[r.SolidIndex];\n                MethodToProp(ss.Method, (int)ss.ChunkSizeBits, prop);\n              }\n            }\n            else\n            {\n              int method = 0;\n              int chunkSizeBits = -1;\n              if (r.IsCompressed())\n              {\n                method = (int)vol->Header.GetMethod();\n                chunkSizeBits = (int)vol->Header.ChunkSizeBits;\n              }\n              MethodToProp(method, chunkSizeBits, prop);\n            }\n          }\n          break;\n\n      case kpidSolid: if (si) prop = si->Resource.IsSolid(); break;\n      case kpidLinks: if (si) prop = (UInt32)si->RefCount; break;\n      #ifdef WIM_DETAILS\n      case kpidVolume: if (si) prop = (UInt32)si->PartNumber; break;\n      case kpidOffset: if (si)  prop = (UInt64)si->Resource.Offset; break;\n      #endif\n    }\n  }\n  else\n  {\n    index -= _db.SortedItems.Size();\n    if (index < _numXmlItems)\n    {\n      switch (propID)\n      {\n        case kpidPath:\n        case kpidName: prop = _xmls[index].FileName; break;\n        case kpidIsDir: prop = false; break;\n        case kpidPackSize:\n        case kpidSize: prop = (UInt64)_xmls[index].Data.Size(); break;\n        case kpidMethod: /* prop = k_Method_Copy; */ break;\n      }\n    }\n    else\n    {\n      index -= _numXmlItems;\n      switch (propID)\n      {\n        case kpidPath:\n        case kpidName:\n          if (index < (UInt32)_db.VirtualRoots.Size())\n            prop = _db.Images[_db.VirtualRoots[index]].RootName;\n          else\n            prop = FILES_DIR_NAME;\n          break;\n        case kpidIsDir: prop = true; break;\n        case kpidIsAux: prop = true; break;\n      }\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetRootProp(PROPID propID, PROPVARIANT *value))\n{\n  // COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  if (_db.Images.Size() != 0 && _db.NumExcludededItems != 0)\n  {\n    const CImage &image = _db.Images[_db.IndexOfUserImage];\n    const CItem &item = _db.Items[image.StartItem];\n    if (!item.IsDir || item.ImageIndex != _db.IndexOfUserImage)\n      return E_FAIL;\n    const Byte *metadata = image.Meta + item.Offset;\n\n    switch (propID)\n    {\n      case kpidIsDir: prop = true; break;\n      case kpidAttrib: prop = (UInt32)Get32(metadata + 8); break;\n      case kpidCTime: GetFileTime(metadata + (_db.IsOldVersion ? 0x18: 0x28), prop); break;\n      case kpidATime: GetFileTime(metadata + (_db.IsOldVersion ? 0x20: 0x30), prop); break;\n      case kpidMTime: GetFileTime(metadata + (_db.IsOldVersion ? 0x28: 0x38), prop); break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  // COM_TRY_END\n}\n\nHRESULT CHandler::GetSecurity(UInt32 realIndex, const void **data, UInt32 *dataSize, UInt32 *propType)\n{\n  const CItem &item = _db.Items[realIndex];\n  if (item.IsAltStream || item.ImageIndex < 0)\n    return S_OK;\n  const CImage &image = _db.Images[item.ImageIndex];\n  const Byte *metadata = image.Meta + item.Offset;\n  UInt32 securityId = Get32(metadata + 0xC);\n  if (securityId == (UInt32)(Int32)-1)\n    return S_OK;\n  if (securityId >= (UInt32)image.SecurOffsets.Size())\n    return E_FAIL;\n  UInt32 offs = image.SecurOffsets[securityId];\n  UInt32 len = image.SecurOffsets[securityId + 1] - offs;\n  const CByteBuffer &buf = image.Meta;\n  if (offs <= buf.Size() && buf.Size() - offs >= len)\n  {\n    *data = buf + offs;\n    *dataSize = len;\n    *propType = NPropDataType::kRaw;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRootRawProp(PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n  if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExcludededItems != 0)\n  {\n    const CImage &image = _db.Images[_db.IndexOfUserImage];\n    const CItem &item = _db.Items[image.StartItem];\n    if (!item.IsDir || item.ImageIndex != _db.IndexOfUserImage)\n      return E_FAIL;\n    return GetSecurity(image.StartItem, data, dataSize, propType);\n  }\n  return S_OK;\n}\n\nstatic const Byte kRawProps[] =\n{\n  kpidSha1,\n  kpidNtReparse,\n  kpidNtSecure\n};\n\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = Z7_ARRAY_SIZE(kRawProps);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))\n{\n  *propID = kRawProps[index];\n  *name = NULL;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  *parentType = NParentType::kDir;\n  *parent = (UInt32)(Int32)-1;\n  if (index >= _db.SortedItems.Size())\n    return S_OK;\n\n  const CItem &item = _db.Items[_db.SortedItems[index]];\n  \n  if (item.ImageIndex >= 0)\n  {\n    *parentType = item.IsAltStream ? NParentType::kAltStream : NParentType::kDir;\n    if (item.Parent >= 0)\n    {\n      if (_db.ExludedItem != item.Parent)\n        *parent = (unsigned)_db.Items[item.Parent].IndexInSorted;\n    }\n    else\n    {\n      CImage &image = _db.Images[item.ImageIndex];\n      if (image.VirtualRootIndex >= 0)\n        *parent = _db.SortedItems.Size() + _numXmlItems + (unsigned)image.VirtualRootIndex;\n    }\n  }\n  else\n    *parent = _db.SortedItems.Size() + _numXmlItems + _db.VirtualRoots.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n\n  if (propID == kpidName)\n  {\n    if (index < _db.SortedItems.Size())\n    {\n      const CItem &item = _db.Items[_db.SortedItems[index]];\n      if (item.ImageIndex < 0)\n        return S_OK;\n      const CImage &image = _db.Images[item.ImageIndex];\n      *propType = NPropDataType::kUtf16z;\n      if (image.NumEmptyRootItems != 0 && item.Parent < 0)\n      {\n        const CByteBuffer &buf = _db.Images[item.ImageIndex].RootNameBuf;\n        *data = (void *)(const Byte *)buf;\n        *dataSize = (UInt32)buf.Size();\n        return S_OK;\n      }\n      const Byte *meta = image.Meta + item.Offset +\n          (item.IsAltStream ?\n          (_isOldVersion ? 0x10 : 0x24) :\n          (_isOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2));\n      *data = (const void *)(meta + 2);\n      *dataSize = (UInt32)Get16(meta) + 2;\n      return S_OK;\n    }\n    {\n      index -= _db.SortedItems.Size();\n      if (index < _numXmlItems)\n        return S_OK;\n      index -= _numXmlItems;\n      if (index >= (UInt32)_db.VirtualRoots.Size())\n        return S_OK;\n      const CByteBuffer &buf = _db.Images[_db.VirtualRoots[index]].RootNameBuf;\n      *data = (void *)(const Byte *)buf;\n      *dataSize = (UInt32)buf.Size();\n      *propType = NPropDataType::kUtf16z;\n      return S_OK;\n    }\n  }\n\n  if (index >= _db.SortedItems.Size())\n    return S_OK;\n\n  unsigned index2 = _db.SortedItems[index];\n  \n  if (propID == kpidNtSecure)\n  {\n    return GetSecurity(index2, data, dataSize, propType);\n  }\n  \n  const CItem &item = _db.Items[index2];\n  if (propID == kpidSha1)\n  {\n    if (item.StreamIndex >= 0)\n      *data = _db.DataStreams[item.StreamIndex].Hash;\n    else\n    {\n      if (_isOldVersion)\n        return S_OK;\n      const Byte *sha1 = _db.Images[item.ImageIndex].Meta + item.Offset + (item.IsAltStream ? 0x10 : 0x40);\n      if (IsEmptySha(sha1))\n        return S_OK;\n      *data = sha1;\n    }\n    *dataSize = kHashSize;\n    *propType = NPropDataType::kRaw;\n    return S_OK;\n  }\n  \n  if (propID == kpidNtReparse && !_isOldVersion)\n  {\n    // we don't know about Reparse field in OLD WIM format\n\n    if (item.StreamIndex < 0)\n      return S_OK;\n    if (index2 >= _db.ItemToReparse.Size())\n      return S_OK;\n    int reparseIndex = _db.ItemToReparse[index2];\n    if (reparseIndex < 0)\n      return S_OK;\n    const CByteBuffer &buf = _db.ReparseItems[reparseIndex];\n    if (buf.Size() == 0)\n      return S_OK;\n    *data = buf;\n    *dataSize = (UInt32)buf.Size();\n    *propType = NPropDataType::kRaw;\n    return S_OK;\n  }\n\n  return S_OK;\n}\n\nclass CVolumeName\n{\n  UString _before;\n  UString _after;\npublic:\n  void InitName(const UString &name)\n  {\n    int dotPos = name.ReverseFind_Dot();\n    if (dotPos < 0)\n      dotPos = (int)name.Len();\n    _before.SetFrom(name.Ptr(), (unsigned)dotPos);\n    _after = name.Ptr(dotPos);\n  }\n\n  UString GetNextName(UInt32 index) const\n  {\n    UString s = _before;\n    s.Add_UInt32(index);\n    s += _after;\n    return s;\n  }\n};\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n\n  Close();\n  {\n    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;\n    \n    CVolumeName seqName;\n    if (callback)\n      callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&openVolumeCallback);\n\n    UInt32 numVolumes = 1;\n    \n    for (UInt32 i = 1; i <= numVolumes; i++)\n    {\n      CMyComPtr<IInStream> curStream;\n      \n      if (i == 1)\n        curStream = inStream;\n      else\n      {\n        if (!openVolumeCallback)\n          continue;\n        const UString fullName = seqName.GetNextName(i);\n        const HRESULT result = openVolumeCallback->GetStream(fullName, &curStream);\n        if (result == S_FALSE)\n          continue;\n        if (result != S_OK)\n          return result;\n        if (!curStream)\n          break;\n      }\n      \n      CHeader header;\n      HRESULT res = NWim::ReadHeader(curStream, header, _phySize);\n      \n      if (res != S_OK)\n      {\n        if (i != 1 && res == S_FALSE)\n          continue;\n        return res;\n      }\n      \n      _isArc = true;\n      _bootIndex = header.BootIndex;\n      _version = header.Version;\n      _isOldVersion = header.IsOldVersion();\n      if (_firstVolumeIndex >= 0)\n        if (!header.AreFromOnArchive(_volumes[_firstVolumeIndex].Header))\n          break;\n      if (_volumes.Size() > header.PartNumber && _volumes[header.PartNumber].Stream)\n        break;\n      CWimXml xml;\n      xml.VolIndex = header.PartNumber;\n      res = _db.OpenXml(curStream, header, xml.Data);\n      \n      if (res == S_OK)\n      {\n        if (!xml.Parse())\n          _xmlError = true;\n\n        if (xml.IsEncrypted)\n        {\n          _unsupported = true;\n          return S_FALSE;\n        }\n\n        UInt64 totalFiles = xml.GetTotalFilesAndDirs() + xml.Images.Size();\n        totalFiles += 16 + xml.Images.Size() * 4; // we reserve some additional items\n        if (totalFiles >= ((UInt32)1 << 30))\n          totalFiles = 0;\n        res = _db.Open(curStream, header, (unsigned)totalFiles, callback);\n      }\n      \n      if (res != S_OK)\n      {\n        if (i != 1 && res == S_FALSE)\n          continue;\n        return res;\n      }\n      \n      while (_volumes.Size() <= header.PartNumber)\n        _volumes.AddNew();\n      CVolume &volume = _volumes[header.PartNumber];\n      volume.Header = header;\n      volume.Stream = curStream;\n      \n      _firstVolumeIndex = header.PartNumber;\n      \n      if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data)\n      {\n        xml.FileName = '[';\n        xml.FileName.Add_UInt32(xml.VolIndex);\n        xml.FileName += \"].xml\";\n        _xmls.Add(xml);\n      }\n      \n      if (i == 1)\n      {\n        if (header.PartNumber != 1)\n          break;\n        if (!openVolumeCallback)\n          break;\n        numVolumes = header.NumParts;\n        {\n          NCOM::CPropVariant prop;\n          RINOK(openVolumeCallback->GetProperty(kpidName, &prop))\n          if (prop.vt != VT_BSTR)\n            break;\n          seqName.InitName(prop.bstrVal);\n        }\n      }\n    }\n\n    RINOK(_db.FillAndCheck(_volumes))\n    int defaultImageIndex = (int)_defaultImageNumber - 1;\n    \n    bool showImageNumber = (_db.Images.Size() != 1 && defaultImageIndex < 0);\n    if (!showImageNumber && _set_use_ShowImageNumber)\n      showImageNumber = _set_showImageNumber;\n\n    if (!showImageNumber && _keepMode_ShowImageNumber)\n      showImageNumber = true;\n\n    _showImageNumber = showImageNumber;\n\n    RINOK(_db.GenerateSortedItems(defaultImageIndex, showImageNumber))\n    RINOK(_db.ExtractReparseStreams(_volumes, callback))\n\n    /*\n    wchar_t sz[16];\n    ConvertUInt32ToString(_db.DataStreams.Size(), sz);\n    _nameLenForStreams = MyStringLen(sz);\n    */\n\n    _xmlInComments = !_showImageNumber;\n    _numXmlItems = (_xmlInComments ? 0 : _xmls.Size());\n    _numIgnoreItems = _db.ThereAreDeletedStreams ? 1 : 0;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _firstVolumeIndex = -1;\n  _phySize = 0;\n  _db.Clear();\n  _volumes.Clear();\n  _xmls.Clear();\n  // _nameLenForStreams = 0;\n  _xmlInComments = false;\n  _numXmlItems = 0;\n  _numIgnoreItems = 0;\n  _xmlError = false;\n  _isArc = false;\n  _unsupported = false;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n\n  if (allFilesMode)\n    numItems = _db.SortedItems.Size() + _numXmlItems + _db.VirtualRoots.Size() + _numIgnoreItems;\n  if (numItems == 0)\n    return S_OK;\n\n  UInt32 i;\n  UInt64 totalSize = 0;\n\n  for (i = 0; i < numItems; i++)\n  {\n    UInt32 index = allFilesMode ? i : indices[i];\n    if (index < _db.SortedItems.Size())\n    {\n      int streamIndex = _db.Items[_db.SortedItems[index]].StreamIndex;\n      if (streamIndex >= 0)\n      {\n        const CStreamInfo &si = _db.DataStreams[streamIndex];\n        totalSize += _db.Get_UnpackSize_of_Resource(si.Resource);\n      }\n    }\n    else\n    {\n      index -= _db.SortedItems.Size();\n      if (index < _numXmlItems)\n        totalSize += _xmls[index].Data.Size();\n    }\n  }\n\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  totalSize = 0;\n  UInt64 currentItemUnPacked;\n  \n  int prevSuccessStreamIndex = -1;\n\n  CUnpacker unpacker;\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  for (i = 0;; i++,\n      totalSize += currentItemUnPacked)\n  {\n    currentItemUnPacked = 0;\n    lps->InSize = unpacker.TotalPacked;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    UInt32 index = allFilesMode ? i : indices[i];\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    if (index >= _db.SortedItems.Size())\n    {\n      if (!testMode && !realOutStream)\n        continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      index -= _db.SortedItems.Size();\n      if (index < _numXmlItems)\n      {\n        const CByteBuffer &data = _xmls[index].Data;\n        currentItemUnPacked = data.Size();\n        if (realOutStream)\n        {\n          RINOK(WriteStream(realOutStream, (const Byte *)data, data.Size()))\n          realOutStream.Release();\n        }\n      }\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    const CItem &item = _db.Items[_db.SortedItems[index]];\n    const int streamIndex = item.StreamIndex;\n    if (streamIndex < 0)\n    {\n      if (!item.IsDir)\n        if (!testMode && !realOutStream)\n          continue;\n      RINOK(extractCallback->PrepareOperation(askMode))\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(!item.IsDir && _db.ItemHasStream(item) ?\n          NExtract::NOperationResult::kDataError :\n          NExtract::NOperationResult::kOK))\n      continue;\n    }\n\n    const CStreamInfo &si = _db.DataStreams[streamIndex];\n    currentItemUnPacked = _db.Get_UnpackSize_of_Resource(si.Resource);\n    // currentItemPacked = _db.Get_PackSize_of_Resource(streamIndex);\n\n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n    Int32 opRes = NExtract::NOperationResult::kOK;\n    \n    if (streamIndex != prevSuccessStreamIndex || realOutStream)\n    {\n      Byte digest[kHashSize];\n      const CVolume &vol = _volumes[si.PartNumber];\n      const bool needDigest = !si.IsEmptyHash() && !_disable_Sha1Check;\n      const HRESULT res = unpacker.Unpack(vol.Stream, si.Resource, vol.Header, &_db,\n          realOutStream, lps, needDigest ? digest : NULL);\n      \n      if (res == S_OK)\n      {\n        if (!needDigest || memcmp(digest, si.Hash, kHashSize) == 0)\n          prevSuccessStreamIndex = streamIndex;\n        else\n          opRes = NExtract::NOperationResult::kCRCError;\n      }\n      else if (res == S_FALSE)\n        opRes = NExtract::NOperationResult::kDataError;\n      else if (res == E_NOTIMPL)\n        opRes = NExtract::NOperationResult::kUnsupportedMethod;\n      else\n        return res;\n    }\n    \n    realOutStream.Release();\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  \n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _db.SortedItems.Size() +\n      _numXmlItems +\n      _db.VirtualRoots.Size() +\n      _numIgnoreItems;\n  return S_OK;\n}\n\nCHandler::CHandler()\n{\n  _keepMode_ShowImageNumber = false;\n  InitDefaults();\n  _xmlError = false;\n}\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  InitDefaults();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    UString name = names[i];\n    name.MakeLower_Ascii();\n    if (name.IsEmpty())\n      return E_INVALIDARG;\n\n    const PROPVARIANT &prop = values[i];\n\n    if (name[0] == L'x')\n    {\n      // some clients write 'x' property. So we support it\n      UInt32 level = 0;\n      RINOK(ParsePropToUInt32(name.Ptr(1), prop, level))\n    }\n    else if (name.IsEqualTo(\"is\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, _set_showImageNumber))\n      _set_use_ShowImageNumber = true;\n    }\n    else if (name.IsEqualTo(\"im\"))\n    {\n      UInt32 image = 9;\n      RINOK(ParsePropToUInt32(L\"\", prop, image))\n      _defaultImageNumber = (int)image;\n    }\n    else if (name.IsPrefixedBy_Ascii_NoCase(\"mt\"))\n    {\n    }\n    else if (name.IsPrefixedBy_Ascii_NoCase(\"memuse\"))\n    {\n    }\n    else if (name.IsPrefixedBy_Ascii_NoCase(\"crc\"))\n    {\n      name.Delete(0, 3);\n      UInt32 crcSize = 1;\n      RINOK(ParsePropToUInt32(name, prop, crcSize))\n      _disable_Sha1Check = (crcSize == 0);\n    }\n    else\n    {\n      bool processed = false;\n      RINOK(_timeOptions.Parse(name, prop, processed))\n      if (!processed)\n        return E_INVALIDARG;\n    }\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::KeepModeForNextOpen())\n{\n  _keepMode_ShowImageNumber = _showImageNumber;\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Wim/WimHandler.h",
    "content": "﻿// WimHandler.h\n\n#ifndef ZIP7_INC_ARCHIVE_WIM_HANDLER_H\n#define ZIP7_INC_ARCHIVE_WIM_HANDLER_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../Common/HandlerOut.h\"\n\n#include \"WimIn.h\"\n\nnamespace NArchive {\nnamespace NWim {\n\nconst Int32 kNumImagesMaxUpdate = 1 << 10;\n\nZ7_CLASS_IMP_CHandler_IInArchive_5(\n    IArchiveGetRawProps\n  , IArchiveGetRootProps\n  , IArchiveKeepModeForNextOpen\n  , ISetProperties\n  , IOutArchive\n)\n  CDatabase _db;\n  UInt32 _version;\n  UInt32 _bootIndex;\n\n  CObjectVector<CVolume> _volumes;\n  CObjectVector<CWimXml> _xmls;\n  // unsigned _nameLenForStreams;\n \n  unsigned _numXmlItems;\n  unsigned _numIgnoreItems;\n\n  bool _isOldVersion;\n  bool _xmlInComments;\n\n  bool _xmlError;\n  bool _isArc;\n  bool _unsupported;\n\n  bool _set_use_ShowImageNumber;\n  bool _set_showImageNumber;\n  int _defaultImageNumber;\n\n  bool _showImageNumber;\n  bool _keepMode_ShowImageNumber;\n  bool _disable_Sha1Check;\n\n  UInt64 _phySize;\n  Int32 _firstVolumeIndex;\n\n  CHandlerTimeOptions _timeOptions;\n\n  void InitDefaults()\n  {\n    _disable_Sha1Check = false;\n    _set_use_ShowImageNumber = false;\n    _set_showImageNumber = false;\n    _defaultImageNumber = -1;\n    _timeOptions.Init();\n  }\n\n  bool IsUpdateSupported() const\n  {\n    if (ThereIsError()) return false;\n    if (_db.Images.Size() > kNumImagesMaxUpdate) return false;\n\n    // Solid format is complicated. So we disable updating now.\n    if (!_db.Solids.IsEmpty()) return false;\n\n    if (_volumes.Size() == 0)\n      return true;\n    \n    if (_volumes.Size() != 2) return false;\n    if (_volumes[0].Stream) return false;\n    if (_version != k_Version_NonSolid\n        // && _version != k_Version_Solid\n        ) return false;\n    \n    return true;\n  }\n\n  bool ThereIsError() const { return _xmlError || _db.ThereIsError(); }\n  HRESULT GetSecurity(UInt32 realIndex, const void **data, UInt32 *dataSize, UInt32 *propType);\n\n  HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value);\n  HRESULT        GetTime(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, FILETIME &ft);\npublic:\n  CHandler();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Wim/WimHandlerOut.cpp",
    "content": "﻿// WimHandlerOut.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/MyBuffer2.h\"\n#include \"../../../Common/StringToInt.h\"\n#include \"../../../Common/UTFConvert.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamUtils.h\"\n#include \"../../Common/UniqBlocks.h\"\n\n#include \"../../Crypto/RandGen.h\"\n#include \"../../Crypto/Sha1Cls.h\"\n\n#include \"../Common/OutStreamWithSha1.h\"\n\n#include \"WimHandler.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NWim {\n\nstatic const unsigned k_NumSubVectors_Bits = 12; // must be <= 16\n\nstruct CSortedIndex\n{\n  CObjectVector<CUIntVector> Vectors;\n\n  CSortedIndex()\n  {\n    const unsigned k_NumSubVectors = 1 << k_NumSubVectors_Bits;\n    Vectors.ClearAndReserve(k_NumSubVectors);\n    for (unsigned i = 0; i < k_NumSubVectors; i++)\n      Vectors.AddNew();\n  }\n};\n\nstatic int AddUniqHash(const CStreamInfo *streams, CSortedIndex &sorted2, const Byte *h, int streamIndexForInsert)\n{\n  const unsigned hash = (((unsigned)h[0] << 8) | (unsigned)h[1]) >> (16 - k_NumSubVectors_Bits);\n  CUIntVector &sorted = sorted2.Vectors[hash];\n  unsigned left = 0, right = sorted.Size();\n  while (left != right)\n  {\n    const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n    const unsigned index = sorted[mid];\n    const Byte *hash2 = streams[index].Hash;\n    \n    unsigned i;\n    for (i = 0; i < kHashSize; i++)\n      if (h[i] != hash2[i])\n        break;\n    \n    if (i == kHashSize)\n      return (int)index;\n  \n    if (h[i] < hash2[i])\n      right = mid;\n    else\n      left = mid + 1;\n  }\n\n  if (streamIndexForInsert != -1)\n    sorted.Insert(left, (unsigned)streamIndexForInsert);\n \n  return -1;\n}\n\n\nstruct CAltStream\n{\n  int UpdateIndex;\n  int HashIndex;\n  UInt64 Size;\n  UString Name;\n  bool Skip;\n\n  CAltStream(): UpdateIndex(-1), HashIndex(-1), Skip(false) {}\n};\n\n\nstruct CMetaItem\n{\n  int UpdateIndex;\n  int HashIndex;\n  \n  UInt64 Size;\n  FILETIME CTime;\n  FILETIME ATime;\n  FILETIME MTime;\n  UInt64 FileID;\n  UInt64 VolID;\n\n  UString Name;\n  UString ShortName;\n\n  UInt32 Attrib;\n  int SecurityId;       // -1: means no secutity ID\n  bool IsDir;\n  bool Skip;\n  unsigned NumSkipAltStreams;\n  CObjectVector<CAltStream> AltStreams;\n\n  CByteBuffer Reparse;\n\n  unsigned GetNumAltStreams() const { return AltStreams.Size() - NumSkipAltStreams; }\n  CMetaItem():\n        UpdateIndex(-1)\n      , HashIndex(-1)\n      , Size(0)\n      , FileID(0)\n      , VolID(0)\n      , Attrib(0)\n      , SecurityId(-1)\n      , IsDir(false)\n      , Skip(false)\n      , NumSkipAltStreams(0)\n  {\n    FILETIME_Clear(CTime);\n    FILETIME_Clear(ATime);\n    FILETIME_Clear(MTime);\n  }\n};\n\n\nstatic int Compare_HardLink_MetaItems(const CMetaItem &a1, const CMetaItem &a2)\n{\n  if (a1.VolID < a2.VolID) return -1;\n  if (a1.VolID > a2.VolID) return 1;\n  if (a1.FileID < a2.FileID) return -1;\n  if (a1.FileID > a2.FileID) return 1;\n  if (a1.Size < a2.Size) return -1;\n  if (a1.Size > a2.Size) return 1;\n  return ::CompareFileTime(&a1.MTime, &a2.MTime);\n}\n\n\nstatic int AddToHardLinkList(const CObjectVector<CMetaItem> &metaItems, unsigned indexOfItem, CUIntVector &indexes)\n{\n  const CMetaItem &mi = metaItems[indexOfItem];\n  unsigned left = 0, right = indexes.Size();\n  while (left != right)\n  {\n    const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n    const unsigned index = indexes[mid];\n    const int comp = Compare_HardLink_MetaItems(mi, metaItems[index]);\n    if (comp == 0)\n      return (int)index;\n    if (comp < 0)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  indexes.Insert(left, indexOfItem);\n  return -1;\n}\n\n\nstruct CUpdateItem\n{\n  unsigned CallbackIndex; // index in callback\n  \n  int MetaIndex;          // index in in MetaItems[]\n  \n  int AltStreamIndex;     // index in CMetaItem::AltStreams vector\n                          // -1: if not alt stream?\n  \n  int InArcIndex;         // >= 0, if we use OLD Data\n                          //   -1, if we use NEW Data\n \n  CUpdateItem(): MetaIndex(-1), AltStreamIndex(-1), InArcIndex(-1) {}\n};\n\n\nstruct CDir\n{\n  int MetaIndex;\n  CObjectVector<CDir> Dirs;\n  CUIntVector Files; // indexes in MetaItems[]\n\n  CDir(): MetaIndex(-1) {}\n  unsigned GetNumDirs() const;\n  unsigned GetNumFiles() const;\n  UInt64 GetTotalSize(const CObjectVector<CMetaItem> &metaItems) const;\n  bool FindDir(const CObjectVector<CMetaItem> &items, const UString &name, unsigned &index);\n};\n\n/* imagex counts Junctions as files (not as dirs).\n   We suppose that it's not correct */\n\nunsigned CDir::GetNumDirs() const\n{\n  unsigned num = Dirs.Size();\n  FOR_VECTOR (i, Dirs)\n    num += Dirs[i].GetNumDirs();\n  return num;\n}\n\nunsigned CDir::GetNumFiles() const\n{\n  unsigned num = Files.Size();\n  FOR_VECTOR (i, Dirs)\n    num += Dirs[i].GetNumFiles();\n  return num;\n}\n\nUInt64 CDir::GetTotalSize(const CObjectVector<CMetaItem> &metaItems) const\n{\n  UInt64 sum = 0;\n  unsigned i;\n  for (i = 0; i < Files.Size(); i++)\n    sum += metaItems[Files[i]].Size;\n  for (i = 0; i < Dirs.Size(); i++)\n    sum += Dirs[i].GetTotalSize(metaItems);\n  return sum;\n}\n\nbool CDir::FindDir(const CObjectVector<CMetaItem> &items, const UString &name, unsigned &index)\n{\n  unsigned left = 0, right = Dirs.Size();\n  while (left != right)\n  {\n    const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n    const int comp = CompareFileNames(name, items[Dirs[mid].MetaIndex].Name);\n    if (comp == 0)\n    {\n      index = mid;\n      return true;\n    }\n    if (comp < 0)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  index = left;\n  return false;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *type))\n{\n  *type = NFileTimeType::kWindows;\n  return S_OK;\n}\n\n\nHRESULT CHandler::GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value)\n{\n  if (arcIndex != -1)\n    return GetProperty((UInt32)arcIndex, propID, value);\n  return callback->GetProperty(callbackIndex, propID, value);\n}\n\n\nHRESULT CHandler::GetTime(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, FILETIME &ft)\n{\n  ft.dwLowDateTime = ft.dwHighDateTime = 0;\n  NCOM::CPropVariant prop;\n  RINOK(GetOutProperty(callback, callbackIndex, arcIndex, propID, &prop))\n  if (prop.vt == VT_FILETIME)\n    ft = prop.filetime;\n  else if (prop.vt != VT_EMPTY)\n    return E_INVALIDARG;\n  return S_OK;\n}\n\n\nstatic HRESULT GetRootTime(\n    IArchiveGetRootProps *callback,\n    IArchiveGetRootProps *arcRoot,\n    PROPID propID, FILETIME &ft)\n{\n  NCOM::CPropVariant prop;\n  if (callback)\n  {\n    RINOK(callback->GetRootProp(propID, &prop))\n    if (prop.vt == VT_FILETIME)\n    {\n      ft = prop.filetime;\n      return S_OK;\n    }\n    if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  if (arcRoot)\n  {\n    RINOK(arcRoot->GetRootProp(propID, &prop))\n    if (prop.vt == VT_FILETIME)\n    {\n      ft = prop.filetime;\n      return S_OK;\n    }\n    if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  return S_OK;\n}\n\n#define Set16(p, d) SetUi16(p, d)\n#define Set32(p, d) SetUi32(p, d)\n#define Set64(p, d) SetUi64(p, d)\n\nvoid CResource::WriteTo(Byte *p) const\n{\n  Set64(p, PackSize)\n  p[7] = Flags;\n  Set64(p + 8, Offset)\n  Set64(p + 16, UnpackSize)\n}\n\n\nvoid CHeader::WriteTo(Byte *p) const\n{\n  memcpy(p, kSignature, kSignatureSize);\n  Set32(p + 8, kHeaderSizeMax)\n  Set32(p + 0xC, Version)\n  Set32(p + 0x10, Flags)\n  Set32(p + 0x14, ChunkSize)\n  memcpy(p + 0x18, Guid, 16);\n  Set16(p + 0x28, PartNumber)\n  Set16(p + 0x2A, NumParts)\n  Set32(p + 0x2C, NumImages)\n  OffsetResource.WriteTo(p + 0x30);\n  XmlResource.WriteTo(p + 0x48);\n  MetadataResource.WriteTo(p + 0x60);\n  IntegrityResource.WriteTo(p + 0x7C);\n  Set32(p + 0x78, BootIndex)\n  memset(p + 0x94, 0, 60);\n}\n\n\nvoid CStreamInfo::WriteTo(Byte *p) const\n{\n  Resource.WriteTo(p);\n  Set16(p + 0x18, PartNumber)\n  Set32(p + 0x1A, RefCount)\n  memcpy(p + 0x1E, Hash, kHashSize);\n}\n\n\nstatic void SetFileTimeToMem(Byte *p, const FILETIME &ft)\n{\n  Set32(p, ft.dwLowDateTime)\n  Set32(p + 4, ft.dwHighDateTime)\n}\n\nstatic size_t WriteItem_Dummy(const CMetaItem &item)\n{\n  if (item.Skip)\n    return 0;\n  unsigned fileNameLen = item.Name.Len() * 2;\n  // we write fileNameLen + 2 + 2 to be same as original WIM.\n  unsigned fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2);\n\n  const unsigned shortNameLen = item.ShortName.Len() * 2;\n  const unsigned shortNameLen2 = (shortNameLen == 0 ? 2 : shortNameLen + 4);\n\n  size_t totalLen = ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~(unsigned)7);\n  if (item.GetNumAltStreams() != 0)\n  {\n    if (!item.IsDir)\n    {\n      const UInt32 curLen = (((0x26 + 0) + 6) & ~(unsigned)7);\n      totalLen += curLen;\n    }\n    FOR_VECTOR (i, item.AltStreams)\n    {\n      const CAltStream &ss = item.AltStreams[i];\n      if (ss.Skip)\n        continue;\n      fileNameLen = ss.Name.Len() * 2;\n      fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2 + 2);\n      const UInt32 curLen = (((0x26 + fileNameLen2) + 6) & ~(unsigned)7);\n      totalLen += curLen;\n    }\n  }\n  return totalLen;\n}\n\n\nstatic size_t WriteItem(const CStreamInfo *streams, const CMetaItem &item, Byte *p)\n{\n  if (item.Skip)\n    return 0;\n  unsigned fileNameLen = item.Name.Len() * 2;\n  unsigned fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2);\n  unsigned shortNameLen = item.ShortName.Len() * 2;\n  unsigned shortNameLen2 = (shortNameLen == 0 ? 2 : shortNameLen + 4);\n\n  size_t totalLen = ((kDirRecordSize + fileNameLen2 + shortNameLen2 + 6) & ~(unsigned)7);\n  \n  memset(p, 0, totalLen);\n  Set64(p, totalLen)\n  Set64(p + 8, item.Attrib)\n  Set32(p + 0xC, (UInt32)(Int32)item.SecurityId)\n  SetFileTimeToMem(p + 0x28, item.CTime);\n  SetFileTimeToMem(p + 0x30, item.ATime);\n  SetFileTimeToMem(p + 0x38, item.MTime);\n  \n  /* WIM format probably doesn't support hard links to symbolic links.\n     In these cases it just stores symbolic links (REPARSE TAGS).\n     Check it in new versions of WIM software form MS !!!\n     We also follow that scheme */\n\n  if (item.Reparse.Size() != 0)\n  {\n    UInt32 tag = GetUi32(item.Reparse);\n    Set32(p + 0x58, tag)\n    // Set32(p + 0x5C, 0); // probably it's always ZERO\n  }\n  else if (item.FileID != 0)\n  {\n    Set64(p + 0x58, item.FileID)\n  }\n  \n  Set16(p + 0x62, (UInt16)shortNameLen)\n  Set16(p + 0x64, (UInt16)fileNameLen)\n  unsigned i;\n  for (i = 0; i * 2 < fileNameLen; i++)\n    Set16(p + kDirRecordSize + i * 2, (UInt16)item.Name[i])\n  for (i = 0; i * 2 < shortNameLen; i++)\n    Set16(p + kDirRecordSize + fileNameLen2 + i * 2, (UInt16)item.ShortName[i])\n  \n  if (item.GetNumAltStreams() == 0)\n  {\n    if (item.HashIndex >= 0)\n      memcpy(p + 0x40, streams[item.HashIndex].Hash, kHashSize);\n  }\n  else\n  {\n    Set16(p + 0x60, (UInt16)(item.GetNumAltStreams() + (item.IsDir ? 0 : 1)))\n    p += totalLen;\n    \n    if (!item.IsDir)\n    {\n      const UInt32 curLen = (((0x26 + 0) + 6) & ~(unsigned)7);\n      memset(p, 0, curLen);\n      Set64(p, curLen)\n      if (item.HashIndex >= 0)\n        memcpy(p + 0x10, streams[item.HashIndex].Hash, kHashSize);\n      totalLen += curLen;\n      p += curLen;\n    }\n    \n    FOR_VECTOR (si, item.AltStreams)\n    {\n      const CAltStream &ss = item.AltStreams[si];\n      if (ss.Skip)\n        continue;\n      \n      fileNameLen = ss.Name.Len() * 2;\n      fileNameLen2 = (fileNameLen == 0 ? 0 : fileNameLen + 2 + 2);\n      UInt32 curLen = (((0x26 + fileNameLen2) + 6) & ~(unsigned)7);\n      memset(p, 0, curLen);\n      \n      Set64(p, curLen)\n      if (ss.HashIndex >= 0)\n        memcpy(p + 0x10, streams[ss.HashIndex].Hash, kHashSize);\n      Set16(p + 0x24, (UInt16)fileNameLen)\n      for (i = 0; i * 2 < fileNameLen; i++)\n        Set16(p + 0x26 + i * 2, (UInt16)ss.Name[i])\n      totalLen += curLen;\n      p += curLen;\n    }\n  }\n  \n  return totalLen;\n}\n\n\nstruct CDb\n{\n  CMetaItem DefaultDirItem;\n  const CStreamInfo *Hashes;\n  CObjectVector<CMetaItem> MetaItems;\n  CRecordVector<CUpdateItem> UpdateItems;\n  CUIntVector UpdateIndexes; /* indexes in UpdateItems in order of writing data streams\n                                to disk (the order of tree items). */\n\n  size_t WriteTree_Dummy(const CDir &tree) const;\n  void WriteTree(const CDir &tree, Byte *dest, size_t &pos)  const;\n  void WriteOrderList(const CDir &tree);\n};\n\n\nsize_t CDb::WriteTree_Dummy(const CDir &tree) const\n{\n  unsigned i;\n  size_t pos = 0;\n  for (i = 0; i < tree.Files.Size(); i++)\n    pos += WriteItem_Dummy(MetaItems[tree.Files[i]]);\n  for (i = 0; i < tree.Dirs.Size(); i++)\n  {\n    const CDir &subDir = tree.Dirs[i];\n    pos += WriteItem_Dummy(MetaItems[subDir.MetaIndex]);\n    pos += WriteTree_Dummy(subDir);\n  }\n  return pos + 8;\n}\n\n\nvoid CDb::WriteTree(const CDir &tree, Byte *dest, size_t &pos) const\n{\n  unsigned i;\n  for (i = 0; i < tree.Files.Size(); i++)\n    pos += WriteItem(Hashes, MetaItems[tree.Files[i]], dest + pos);\n\n  size_t posStart = pos;\n  for (i = 0; i < tree.Dirs.Size(); i++)\n    pos += WriteItem_Dummy(MetaItems[tree.Dirs[i].MetaIndex]);\n\n  Set64(dest + pos, 0)\n\n  pos += 8;\n\n  for (i = 0; i < tree.Dirs.Size(); i++)\n  {\n    const CDir &subDir = tree.Dirs[i];\n    const CMetaItem &metaItem = MetaItems[subDir.MetaIndex];\n    bool needCreateTree = (metaItem.Reparse.Size() == 0)\n        || !subDir.Files.IsEmpty()\n        || !subDir.Dirs.IsEmpty();\n    size_t len = WriteItem(Hashes, metaItem, dest + posStart);\n    posStart += len;\n    if (needCreateTree)\n    {\n      Set64(dest + posStart - len + 0x10, pos) // subdirOffset\n      WriteTree(subDir, dest, pos);\n    }\n  }\n}\n\n\nvoid CDb::WriteOrderList(const CDir &tree)\n{\n  if (tree.MetaIndex >= 0)\n  {\n    const CMetaItem &mi = MetaItems[tree.MetaIndex];\n    if (mi.UpdateIndex >= 0)\n      UpdateIndexes.Add((unsigned)mi.UpdateIndex);\n    FOR_VECTOR (si, mi.AltStreams)\n      UpdateIndexes.Add((unsigned)mi.AltStreams[si].UpdateIndex);\n  }\n\n  unsigned i;\n  for (i = 0; i < tree.Files.Size(); i++)\n  {\n    const CMetaItem &mi = MetaItems[tree.Files[i]];\n    UpdateIndexes.Add((unsigned)mi.UpdateIndex);\n    FOR_VECTOR (si, mi.AltStreams)\n      UpdateIndexes.Add((unsigned)mi.AltStreams[si].UpdateIndex);\n  }\n\n  for (i = 0; i < tree.Dirs.Size(); i++)\n    WriteOrderList(tree.Dirs[i]);\n}\n\n\nstatic void AddTag_ToString(AString &s, const char *name, const char *value)\n{\n  s.Add_Char('<');\n  s += name;\n  s.Add_Char('>');\n  s += value;\n  s.Add_Char('<');\n  s.Add_Slash();\n  s += name;\n  s.Add_Char('>');\n}\n\n\nstatic void AddTagUInt64_ToString(AString &s, const char *name, UInt64 value)\n{\n  char temp[32];\n  ConvertUInt64ToString(value, temp);\n  AddTag_ToString(s, name, temp);\n}\n\n\nstatic CXmlItem &AddUniqueTag(CXmlItem &parentItem, const char *name)\n{\n  const int index = parentItem.FindSubTag(name);\n  if (index < 0)\n  {\n    CXmlItem &subItem = parentItem.SubItems.AddNew();\n    subItem.IsTag = true;\n    subItem.Name = name;\n    return subItem;\n  }\n  CXmlItem &subItem = parentItem.SubItems[index];\n  subItem.SubItems.Clear();\n  return subItem;\n}\n\n\nstatic void AddTag_UInt64_2(CXmlItem &item, UInt64 value)\n{\n  CXmlItem &subItem = item.SubItems.AddNew();\n  subItem.IsTag = false;\n  char temp[32];\n  ConvertUInt64ToString(value, temp);\n  subItem.Name = temp;\n}\n\n\nstatic void AddTag_UInt64(CXmlItem &parentItem, const char *name, UInt64 value)\n{\n  AddTag_UInt64_2(AddUniqueTag(parentItem, name), value);\n}\n\n\nstatic void AddTag_Hex(CXmlItem &item, const char *name, UInt32 value)\n{\n  item.IsTag = true;\n  item.Name = name;\n  char temp[16];\n  temp[0] = '0';\n  temp[1] = 'x';\n  ConvertUInt32ToHex8Digits(value, temp + 2);\n  CXmlItem &subItem = item.SubItems.AddNew();\n  subItem.IsTag = false;\n  subItem.Name = temp;\n}\n\n\nstatic void AddTag_Time_2(CXmlItem &item, const FILETIME &ft)\n{\n  AddTag_Hex(item.SubItems.AddNew(), \"HIGHPART\", ft.dwHighDateTime);\n  AddTag_Hex(item.SubItems.AddNew(), \"LOWPART\", ft.dwLowDateTime);\n}\n\n\nstatic void AddTag_Time(CXmlItem &parentItem, const char *name, const FILETIME &ft)\n{\n  AddTag_Time_2(AddUniqueTag(parentItem, name), ft);\n}\n\n\nstatic void AddTag_String_IfEmpty(CXmlItem &parentItem, const char *name, const char *value)\n{\n  if (parentItem.FindSubTag(name) >= 0)\n    return;\n  CXmlItem &tag = parentItem.SubItems.AddNew();\n  tag.IsTag = true;\n  tag.Name = name;\n  CXmlItem &subItem = tag.SubItems.AddNew();\n  subItem.IsTag = false;\n  subItem.Name = value;\n}\n\n\nvoid CHeader::SetDefaultFields(bool useLZX)\n{\n  Version = k_Version_NonSolid;\n  Flags = NHeaderFlags::kReparsePointFixup;\n  ChunkSize = 0;\n  if (useLZX)\n  {\n    Flags |= NHeaderFlags::kCompression | NHeaderFlags::kLZX;\n    ChunkSize = kChunkSize;\n    ChunkSizeBits = kChunkSizeBits;\n  }\n  MY_RAND_GEN(Guid, 16);\n  PartNumber = 1;\n  NumParts = 1;\n  NumImages = 1;\n  BootIndex = 0;\n  OffsetResource.Clear();\n  XmlResource.Clear();\n  MetadataResource.Clear();\n  IntegrityResource.Clear();\n}\n\n\nstatic void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaItems, const CMetaItem &ri, int curTreeIndex)\n{\n  while (curTreeIndex >= (int)trees.Size())\n    trees.AddNew().Dirs.AddNew().MetaIndex = (int)metaItems.Add(ri);\n}\n\n\n#define IS_LETTER_CHAR(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))\n\n\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback))\n{\n  COM_TRY_BEGIN\n\n  if (!IsUpdateSupported())\n    return E_NOTIMPL;\n\n  bool isUpdate = (_volumes.Size() != 0);\n  int defaultImageIndex = _defaultImageNumber - 1;\n  bool showImageNumber;\n\n  if (isUpdate)\n  {\n    showImageNumber = _showImageNumber;\n    if (!showImageNumber)\n      defaultImageIndex = _db.IndexOfUserImage;\n  }\n  else\n  {\n    showImageNumber = (_set_use_ShowImageNumber && _set_showImageNumber);\n    if (!showImageNumber)\n      defaultImageIndex = 0;\n  }\n\n  if (defaultImageIndex >= kNumImagesMaxUpdate)\n    return E_NOTIMPL;\n\n  CMyComPtr<IOutStream> outStream;\n  RINOK(outSeqStream->QueryInterface(IID_IOutStream, (void **)&outStream))\n  if (!outStream)\n    return E_NOTIMPL;\n  if (!callback)\n    return E_FAIL;\n\n  CDb db;\n  CObjectVector<CDir> trees;\n\n  CMetaItem ri; // default DIR item\n  FILETIME ftCur;\n  NTime::GetCurUtcFileTime(ftCur);\n  // ri.MTime = ri.ATime = ri.CTime = ftCur;\n  ri.Attrib = FILE_ATTRIBUTE_DIRECTORY;\n  ri.IsDir = true;\n\n\n  // ---------- Detect changed images ----------\n\n  unsigned i;\n  CBoolVector isChangedImage;\n  {\n    CUIntVector numUnchangedItemsInImage;\n    for (i = 0; i < _db.Images.Size(); i++)\n    {\n      numUnchangedItemsInImage.Add(0);\n      isChangedImage.Add(false);\n    }\n    \n    for (i = 0; i < numItems; i++)\n    {\n      UInt32 indexInArchive;\n      Int32 newData, newProps;\n      RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive))\n      if (newProps == 0)\n      {\n        if (indexInArchive >= _db.SortedItems.Size())\n          continue;\n        const CItem &item = _db.Items[_db.SortedItems[indexInArchive]];\n        if (newData == 0)\n        {\n          if (item.ImageIndex >= 0)\n            numUnchangedItemsInImage[item.ImageIndex]++;\n        }\n        else\n        {\n          // oldProps & newData. Current version of 7-Zip doesn't use it\n          if (item.ImageIndex >= 0)\n            isChangedImage[item.ImageIndex] = true;\n        }\n      }\n      else if (!showImageNumber)\n      {\n        if (defaultImageIndex >= 0 && defaultImageIndex < (int)isChangedImage.Size())\n          isChangedImage[defaultImageIndex] = true;\n      }\n      else\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidPath, &prop))\n        \n        if (prop.vt != VT_BSTR)\n          return E_INVALIDARG;\n        const wchar_t *path = prop.bstrVal;\n        if (!path)\n          return E_INVALIDARG;\n\n        const wchar_t *end;\n        UInt64 val = ConvertStringToUInt64(path, &end);\n        if (end == path)\n          return E_INVALIDARG;\n        if (val == 0 || val > kNumImagesMaxUpdate)\n          return E_INVALIDARG;\n        wchar_t c = *end;\n        if (c != 0 && c != ':' && c != L'/' && c != WCHAR_PATH_SEPARATOR)\n          return E_INVALIDARG;\n        unsigned imageIndex = (unsigned)val - 1;\n        if (imageIndex < _db.Images.Size())\n          isChangedImage[imageIndex] = true;\n        if (_defaultImageNumber > 0 && val != (unsigned)_defaultImageNumber)\n          return E_INVALIDARG;\n      }\n    }\n    \n    for (i = 0; i < _db.Images.Size(); i++)\n      if (!isChangedImage[i])\n        isChangedImage[i] = _db.GetNumUserItemsInImage(i) != numUnchangedItemsInImage[i];\n  }\n\n  if (defaultImageIndex >= 0)\n  {\n    for (i = 0; i < _db.Images.Size(); i++)\n      if ((int)i != defaultImageIndex)\n        isChangedImage[i] = false;\n  }\n\n  CMyComPtr<IArchiveGetRawProps> getRawProps;\n  callback->QueryInterface(IID_IArchiveGetRawProps, (void **)&getRawProps);\n\n  CMyComPtr<IArchiveGetRootProps> getRootProps;\n  callback->QueryInterface(IID_IArchiveGetRootProps, (void **)&getRootProps);\n\n  CObjectVector<CUniqBlocks> secureBlocks;\n\n  if (!showImageNumber && (getRootProps || isUpdate) &&\n      (\n        defaultImageIndex >= (int)isChangedImage.Size()\n        || defaultImageIndex < 0 // test it\n        || isChangedImage[defaultImageIndex]\n      ))\n  {\n    // Fill Root Item: Metadata and security\n    CMetaItem rootItem = ri;\n    {\n      const void *data = NULL;\n      UInt32 dataSize = 0;\n      UInt32 propType = 0;\n      if (getRootProps)\n      {\n        RINOK(getRootProps->GetRootRawProp(kpidNtSecure, &data, &dataSize, &propType))\n      }\n      if (dataSize == 0 && isUpdate)\n      {\n        RINOK(GetRootRawProp(kpidNtSecure, &data, &dataSize, &propType))\n      }\n      if (dataSize != 0)\n      {\n        if (propType != NPropDataType::kRaw)\n          return E_FAIL;\n        while (defaultImageIndex >= (int)secureBlocks.Size())\n          secureBlocks.AddNew();\n        CUniqBlocks &secUniqBlocks = secureBlocks[defaultImageIndex];\n        rootItem.SecurityId = (int)secUniqBlocks.AddUniq((const Byte *)data, dataSize);\n      }\n    }\n    \n    IArchiveGetRootProps *thisGetRoot = isUpdate ? this : NULL;\n    \n    if (_timeOptions.Write_CTime.Val) RINOK(GetRootTime(getRootProps, thisGetRoot, kpidCTime, rootItem.CTime))\n    if (_timeOptions.Write_ATime.Val) RINOK(GetRootTime(getRootProps, thisGetRoot, kpidATime, rootItem.ATime))\n    if (_timeOptions.Write_MTime.Val) RINOK(GetRootTime(getRootProps, thisGetRoot, kpidMTime, rootItem.MTime))\n    \n    {\n      NCOM::CPropVariant prop;\n      if (getRootProps)\n      {\n        RINOK(getRootProps->GetRootProp(kpidAttrib, &prop))\n        if (prop.vt == VT_UI4)\n          rootItem.Attrib = prop.ulVal;\n        else if (prop.vt != VT_EMPTY)\n          return E_INVALIDARG;\n      }\n      if (prop.vt == VT_EMPTY && thisGetRoot)\n      {\n        RINOK(GetRootProp(kpidAttrib, &prop))\n        if (prop.vt == VT_UI4)\n          rootItem.Attrib = prop.ulVal;\n        else if (prop.vt != VT_EMPTY)\n          return E_INVALIDARG;\n      }\n      rootItem.Attrib |= FILE_ATTRIBUTE_DIRECTORY;\n    }\n    \n    AddTrees(trees, db.MetaItems, ri, defaultImageIndex);\n    db.MetaItems[trees[defaultImageIndex].Dirs[0].MetaIndex] = rootItem;\n  }\n\n  // ---------- Request Metadata for changed items ----------\n\n  UString fileName;\n  \n  for (i = 0; i < numItems; i++)\n  {\n    CUpdateItem ui;\n    UInt32 indexInArchive;\n    Int32 newData, newProps;\n    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive))\n\n    if (newData == 0 || newProps == 0)\n    {\n      if (indexInArchive >= _db.SortedItems.Size())\n        continue;\n      \n      const CItem &item = _db.Items[_db.SortedItems[indexInArchive]];\n      \n      if (item.ImageIndex >= 0)\n      {\n        if (!isChangedImage[item.ImageIndex])\n        {\n          if (newData == 0 && newProps == 0)\n            continue;\n          return E_FAIL;\n        }\n      }\n      else\n      {\n        // if deleted item was not renamed, we just skip it\n        if (newProps == 0)\n          continue;\n        if (item.StreamIndex >= 0)\n        {\n          // we don't support property change for SolidBig streams\n          if (_db.DataStreams[item.StreamIndex].Resource.IsSolidBig())\n            return E_NOTIMPL;\n        }\n      }\n    \n      if (newData == 0)\n        ui.InArcIndex = (Int32)indexInArchive;\n    }\n\n    // we set arcIndex only if we must use old props\n    const Int32 arcIndex = (newProps ? -1 : (Int32)indexInArchive);\n\n    bool isDir = false;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(GetOutProperty(callback, i, arcIndex, kpidIsDir, &prop))\n      if (prop.vt == VT_BOOL)\n        isDir = (prop.boolVal != VARIANT_FALSE);\n      else if (prop.vt != VT_EMPTY)\n        return E_INVALIDARG;\n    }\n\n    bool isAltStream = false;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(GetOutProperty(callback, i, arcIndex, kpidIsAltStream, &prop))\n      if (prop.vt == VT_BOOL)\n        isAltStream = (prop.boolVal != VARIANT_FALSE);\n      else if (prop.vt != VT_EMPTY)\n        return E_INVALIDARG;\n    }\n\n    if (isDir && isAltStream)\n      return E_INVALIDARG;\n\n    UInt64 size = 0;\n    UInt64 iNode = 0;\n\n    if (!isDir)\n    {\n      if (!newData)\n      {\n        NCOM::CPropVariant prop;\n        GetProperty(indexInArchive, kpidINode, &prop);\n        if (prop.vt == VT_UI8)\n          iNode = prop.uhVal.QuadPart;\n      }\n\n      NCOM::CPropVariant prop;\n      \n      if (newData)\n      {\n        RINOK(callback->GetProperty(i, kpidSize, &prop))\n      }\n      else\n      {\n        RINOK(GetProperty(indexInArchive, kpidSize, &prop))\n      }\n     \n      if (prop.vt == VT_UI8)\n        size = prop.uhVal.QuadPart;\n      else if (prop.vt != VT_EMPTY)\n        return E_INVALIDARG;\n    }\n\n    {\n      NCOM::CPropVariant propPath;\n      const wchar_t *path = NULL;\n      RINOK(GetOutProperty(callback, i, arcIndex, kpidPath, &propPath))\n      if (propPath.vt == VT_BSTR)\n        path = propPath.bstrVal;\n      else if (propPath.vt != VT_EMPTY)\n        return E_INVALIDARG;\n    \n    if (!path)\n      return E_INVALIDARG;\n\n    CDir *curItem = NULL;\n    bool isRootImageDir = false;\n    fileName.Empty();\n\n    int imageIndex;\n    \n    if (!showImageNumber)\n    {\n      imageIndex = defaultImageIndex;\n      AddTrees(trees, db.MetaItems, ri, imageIndex);\n      curItem = &trees[imageIndex].Dirs[0];\n    }\n    else\n    {\n      const wchar_t *end;\n      UInt64 val = ConvertStringToUInt64(path, &end);\n      if (end == path)\n        return E_INVALIDARG;\n      if (val == 0 || val > kNumImagesMaxUpdate)\n        return E_INVALIDARG;\n      \n      imageIndex = (int)val - 1;\n      if (imageIndex < (int)isChangedImage.Size())\n       if (!isChangedImage[imageIndex])\n          return E_FAIL;\n\n      AddTrees(trees, db.MetaItems, ri, imageIndex);\n      curItem = &trees[imageIndex].Dirs[0];\n      wchar_t c = *end;\n      \n      if (c == 0)\n      {\n        if (!isDir || isAltStream)\n          return E_INVALIDARG;\n        ui.MetaIndex = curItem->MetaIndex;\n        isRootImageDir = true;\n      }\n      else if (c == ':')\n      {\n        if (isDir || !isAltStream)\n          return E_INVALIDARG;\n        ui.MetaIndex = curItem->MetaIndex;\n        CAltStream ss;\n        ss.Size = size;\n        ss.Name = end + 1;\n        ss.UpdateIndex = (int)db.UpdateItems.Size();\n        ui.AltStreamIndex = (int)db.MetaItems[ui.MetaIndex].AltStreams.Add(ss);\n      }\n      else if (c == WCHAR_PATH_SEPARATOR || c == L'/')\n      {\n        path = end + 1;\n        if (*path == 0)\n          return E_INVALIDARG;\n      }\n      else\n        return E_INVALIDARG;\n    }\n      \n    if (ui.MetaIndex < 0)\n    {\n      for (;;)\n      {\n        const wchar_t c = *path++;\n        if (c == 0)\n          break;\n        if (c == WCHAR_PATH_SEPARATOR || c == L'/')\n        {\n          unsigned indexOfDir;\n          if (!curItem->FindDir(db.MetaItems, fileName, indexOfDir))\n          {\n            CDir &dir = curItem->Dirs.InsertNew(indexOfDir);\n            dir.MetaIndex = (int)db.MetaItems.Add(ri);\n            db.MetaItems.Back().Name = fileName;\n          }\n          curItem = &curItem->Dirs[indexOfDir];\n          fileName.Empty();\n        }\n        else\n        {\n          /*\n          #if WCHAR_MAX > 0xffff\n          if (c >= 0x10000)\n          {\n            c -= 0x10000;\n\n            if (c < (1 << 20))\n            {\n              wchar_t c0 = 0xd800 + ((c >> 10) & 0x3FF);\n              fileName += c0;\n              c = 0xdc00 + (c & 0x3FF);\n            }\n            else\n              c = '_'; // we change character unsupported by UTF16\n          }\n          #endif\n          */\n\n          fileName += c;\n        }\n      }\n\n      if (isAltStream)\n      {\n        int colonPos = fileName.Find(L':');\n        if (colonPos < 0)\n          return E_INVALIDARG;\n        \n        // we want to support cases of c::substream, where c: is drive name\n        if (colonPos == 1 && fileName[2] == L':' && IS_LETTER_CHAR(fileName[0]))\n          colonPos = 2;\n        const UString mainName = fileName.Left((unsigned)colonPos);\n        unsigned indexOfDir;\n        \n        if (mainName.IsEmpty())\n          ui.MetaIndex = curItem->MetaIndex;\n        else if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))\n          ui.MetaIndex = curItem->Dirs[indexOfDir].MetaIndex;\n        else\n        {\n          for (int j = (int)curItem->Files.Size() - 1; j >= 0; j--)\n          {\n            const unsigned metaIndex = curItem->Files[j];\n            const CMetaItem &mi = db.MetaItems[metaIndex];\n            if (CompareFileNames(mainName, mi.Name) == 0)\n            {\n              ui.MetaIndex = (int)metaIndex;\n              break;\n            }\n          }\n        }\n        \n        if (ui.MetaIndex >= 0)\n        {\n          CAltStream ss;\n          ss.Size = size;\n          ss.Name = fileName.Ptr(colonPos + 1);\n          ss.UpdateIndex = (int)db.UpdateItems.Size();\n          ui.AltStreamIndex = (int)db.MetaItems[ui.MetaIndex].AltStreams.Add(ss);\n        }\n      }\n    }\n\n\n    if (ui.MetaIndex < 0 || isRootImageDir)\n    {\n      if (!isRootImageDir)\n      {\n        ui.MetaIndex = (int)db.MetaItems.Size();\n        db.MetaItems.AddNew();\n      }\n    \n      CMetaItem &mi = db.MetaItems[ui.MetaIndex];\n      mi.Size = size;\n      mi.IsDir = isDir;\n      mi.Name = fileName;\n      mi.UpdateIndex = (int)db.UpdateItems.Size();\n      {\n        NCOM::CPropVariant prop;\n        RINOK(GetOutProperty(callback, i, arcIndex, kpidAttrib, &prop))\n        if (prop.vt == VT_EMPTY)\n          mi.Attrib = 0;\n        else if (prop.vt == VT_UI4)\n          mi.Attrib = prop.ulVal;\n        else\n          return E_INVALIDARG;\n        if (isDir)\n          mi.Attrib |= FILE_ATTRIBUTE_DIRECTORY;\n      }\n\n      if (arcIndex != -1 || _timeOptions.Write_CTime.Val)\n        RINOK(GetTime(callback, i, arcIndex, kpidCTime, mi.CTime))\n      if (arcIndex != -1 || _timeOptions.Write_ATime.Val)\n        RINOK(GetTime(callback, i, arcIndex, kpidATime, mi.ATime))\n      if (arcIndex != -1 || _timeOptions.Write_MTime.Val)\n        RINOK(GetTime(callback, i, arcIndex, kpidMTime, mi.MTime))\n\n      {\n        NCOM::CPropVariant prop;\n        RINOK(GetOutProperty(callback, i, arcIndex, kpidShortName, &prop))\n        if (prop.vt == VT_BSTR)\n          mi.ShortName.SetFromBstr(prop.bstrVal);\n        else if (prop.vt != VT_EMPTY)\n          return E_INVALIDARG;\n      }\n\n      while (imageIndex >= (int)secureBlocks.Size())\n        secureBlocks.AddNew();\n      \n      if (!isAltStream && (getRawProps || arcIndex >= 0))\n      {\n        CUniqBlocks &secUniqBlocks = secureBlocks[imageIndex];\n        const void *data;\n        UInt32 dataSize;\n        UInt32 propType;\n        \n        data = NULL;\n        dataSize = 0;\n        propType = 0;\n        \n        if (arcIndex >= 0)\n        {\n          GetRawProp((UInt32)arcIndex, kpidNtSecure, &data, &dataSize, &propType);\n        }\n        else\n        {\n          getRawProps->GetRawProp(i, kpidNtSecure, &data, &dataSize, &propType);\n        }\n        \n        if (dataSize != 0)\n        {\n          if (propType != NPropDataType::kRaw)\n            return E_FAIL;\n          mi.SecurityId = (int)secUniqBlocks.AddUniq((const Byte *)data, dataSize);\n        }\n\n        data = NULL;\n        dataSize = 0;\n        propType = 0;\n        \n        if (arcIndex >= 0)\n        {\n          GetRawProp((UInt32)arcIndex, kpidNtReparse, &data, &dataSize, &propType);\n        }\n        else\n        {\n          getRawProps->GetRawProp(i, kpidNtReparse, &data, &dataSize, &propType);\n        }\n      \n        if (dataSize != 0)\n        {\n          if (propType != NPropDataType::kRaw)\n            return E_FAIL;\n          mi.Reparse.CopyFrom((const Byte *)data, dataSize);\n        }\n      }\n\n      if (!isRootImageDir)\n      {\n        if (isDir)\n        {\n          unsigned indexOfDir;\n          if (curItem->FindDir(db.MetaItems, fileName, indexOfDir))\n            curItem->Dirs[indexOfDir].MetaIndex = ui.MetaIndex;\n          else\n            curItem->Dirs.InsertNew(indexOfDir).MetaIndex = ui.MetaIndex;\n        }\n        else\n          curItem->Files.Add((unsigned)ui.MetaIndex);\n      }\n    }\n    \n    }\n    \n    if (iNode != 0 && ui.MetaIndex >= 0 && ui.AltStreamIndex < 0)\n      db.MetaItems[ui.MetaIndex].FileID = iNode;\n\n    ui.CallbackIndex = i;\n    db.UpdateItems.Add(ui);\n  }\n\n  unsigned numNewImages = trees.Size();\n  for (i = numNewImages; i < isChangedImage.Size(); i++)\n    if (!isChangedImage[i])\n      numNewImages = i + 1;\n\n  AddTrees(trees, db.MetaItems, ri, (int)numNewImages - 1);\n\n  for (i = 0; i < trees.Size(); i++)\n    if (i >= isChangedImage.Size() || isChangedImage[i])\n      db.WriteOrderList(trees[i]);\n\n\n  UInt64 complexity = 0;\n\n  unsigned numDataStreams = _db.DataStreams.Size();\n  CUIntArr streamsRefs(numDataStreams);\n  for (i = 0; i < numDataStreams; i++)\n    streamsRefs[i] = 0;\n\n  // ---------- Calculate Streams Refs Counts in unchanged images\n\n  for (i = 0; i < _db.Images.Size(); i++)\n  {\n    if (isChangedImage[i])\n      continue;\n    complexity += _db.MetaStreams[i].Resource.PackSize;\n    const CImage &image = _db.Images[i];\n    unsigned endItem = image.StartItem + image.NumItems;\n    for (unsigned k = image.StartItem; k < endItem; k++)\n    {\n      const CItem &item = _db.Items[k];\n      if (item.StreamIndex >= 0)\n        streamsRefs[(unsigned)item.StreamIndex]++;\n    }\n  }\n\n\n  // ---------- Update Streams Refs Counts in changed images\n\n  for (i = 0; i < db.UpdateIndexes.Size(); i++)\n  {\n    const CUpdateItem &ui = db.UpdateItems[db.UpdateIndexes[i]];\n    \n    if (ui.InArcIndex >= 0)\n    {\n      if ((unsigned)ui.InArcIndex >= _db.SortedItems.Size())\n        continue;\n      const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]];\n      if (item.StreamIndex >= 0)\n        streamsRefs[(unsigned)item.StreamIndex]++;\n    }\n    else\n    {\n      const CMetaItem &mi = db.MetaItems[ui.MetaIndex];\n      UInt64 size;\n      if (ui.AltStreamIndex < 0)\n        size = mi.Size;\n      else\n        size = mi.AltStreams[ui.AltStreamIndex].Size;\n      complexity += size;\n    }\n  }\n\n  // Clear ref counts for SolidBig streams\n  \n  for (i = 0; i < _db.DataStreams.Size(); i++)\n    if (_db.DataStreams[i].Resource.IsSolidBig())\n      streamsRefs[i] = 0;\n\n  // Set ref counts for SolidBig streams\n  \n  for (i = 0; i < _db.DataStreams.Size(); i++)\n    if (streamsRefs[i] != 0)\n    {\n      const CResource &rs = _db.DataStreams[i].Resource;\n      if (rs.IsSolidSmall())\n        streamsRefs[_db.Solids[rs.SolidIndex].StreamIndex] = 1;\n    }\n\n  for (i = 0; i < _db.DataStreams.Size(); i++)\n    if (streamsRefs[i] != 0)\n    {\n      const CResource &rs = _db.DataStreams[i].Resource;\n      if (!rs.IsSolidSmall())\n        complexity += rs.PackSize;\n    }\n      \n  RINOK(callback->SetTotal(complexity))\n  UInt64 totalComplexity = complexity;\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(callback, true);\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n\n  complexity = 0;\n\n  // bool useResourceCompression = false;\n  // use useResourceCompression only if CHeader::Flags compression is also set\n\n  CHeader header;\n  header.SetDefaultFields(false);\n\n  if (isUpdate)\n  {\n    const CHeader &srcHeader = _volumes[1].Header;\n    header.Flags = srcHeader.Flags;\n    header.Version = srcHeader.Version;\n    header.ChunkSize = srcHeader.ChunkSize;\n    header.ChunkSizeBits = srcHeader.ChunkSizeBits;\n  }\n\n  CMyComPtr<IStreamSetRestriction> setRestriction;\n  outSeqStream->QueryInterface(IID_IStreamSetRestriction, (void **)&setRestriction);\n  if (setRestriction)\n    RINOK(setRestriction->SetRestriction(0, kHeaderSizeMax))\n\n  {\n    Byte buf[kHeaderSizeMax];\n    header.WriteTo(buf);\n    RINOK(WriteStream(outStream, buf, kHeaderSizeMax))\n  }\n\n  UInt64 curPos = kHeaderSizeMax;\n\n  CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha1> inShaStream;\n\n  CLimitedSequentialInStream *inStreamLimitedSpec = NULL;\n  CMyComPtr<ISequentialInStream> inStreamLimited;\n  if (_volumes.Size() == 2)\n  {\n    inStreamLimitedSpec = new CLimitedSequentialInStream;\n    inStreamLimited = inStreamLimitedSpec;\n    inStreamLimitedSpec->SetStream(_volumes[1].Stream);\n  }\n\n  \n  CRecordVector<CStreamInfo> streams;\n  CSortedIndex sortedHashes; // indexes to streams, sorted by SHA1\n  \n  // ---------- Copy unchanged data streams ----------\n\n  UInt64 solidRunOffset = 0;\n  UInt64 curSolidSize = 0;\n\n  for (i = 0; i < _db.DataStreams.Size(); i++)\n  {\n    const CStreamInfo &siOld = _db.DataStreams[i];\n    const CResource &rs = siOld.Resource;\n    \n    const unsigned numRefs = streamsRefs[i];\n\n    if (numRefs == 0)\n    {\n      if (!rs.IsSolidSmall())\n        continue;\n      if (streamsRefs[_db.Solids[rs.SolidIndex].StreamIndex] == 0)\n        continue;\n    }\n\n    lps->InSize = lps->OutSize = complexity;\n    RINOK(lps->SetCur())\n\n    const unsigned streamIndex = streams.Size();\n    CStreamInfo s;\n    s.Resource = rs;\n    s.PartNumber = 1;\n    s.RefCount = numRefs;\n\n    memcpy(s.Hash, siOld.Hash, kHashSize);\n\n    if (rs.IsSolid())\n    {\n      CSolid &ss = _db.Solids[rs.SolidIndex];\n      if (rs.IsSolidSmall())\n      {\n        UInt64 oldOffset = ss.SolidOffset;\n        if (rs.Offset < oldOffset)\n          return E_FAIL;\n        UInt64 relatOffset = rs.Offset - oldOffset;\n        s.Resource.Offset = solidRunOffset + relatOffset;\n      }\n      else\n      {\n        // IsSolidBig\n        solidRunOffset += curSolidSize;\n        curSolidSize = ss.UnpackSize;\n      }\n    }\n    else\n    {\n      solidRunOffset = 0;\n      curSolidSize = 0;\n    }\n     \n    if (!rs.IsSolid() || rs.IsSolidSmall())\n    {\n      const int find = AddUniqHash(streams.ConstData(), sortedHashes, siOld.Hash, (int)streamIndex);\n      if (find != -1)\n        return E_FAIL; // two streams with same SHA-1\n    }\n   \n    if (!rs.IsSolid() || rs.IsSolidBig())\n    {\n      RINOK(InStream_SeekSet(_volumes[siOld.PartNumber].Stream, rs.Offset))\n      inStreamLimitedSpec->Init(rs.PackSize);\n      RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))\n      if (copyCoder->TotalSize != rs.PackSize)\n        return E_FAIL;\n      s.Resource.Offset = curPos;\n      curPos += rs.PackSize;\n      lps->ProgressOffset += rs.PackSize;\n    }\n\n    streams.Add(s);\n  }\n\n  \n  // ---------- Write new items ----------\n\n  CUIntVector hlIndexes; // sorted indexes for hard link items\n\n  for (i = 0; i < db.UpdateIndexes.Size(); i++)\n  {\n    lps->InSize = lps->OutSize = complexity;\n    RINOK(lps->SetCur())\n    const CUpdateItem &ui = db.UpdateItems[db.UpdateIndexes[i]];\n    CMetaItem &mi = db.MetaItems[ui.MetaIndex];\n    UInt64 size = 0;\n    \n    if (ui.AltStreamIndex >= 0)\n    {\n      if (mi.Skip)\n        continue;\n      size = mi.AltStreams[ui.AltStreamIndex].Size;\n    }\n    else\n    {\n      size = mi.Size;\n      if (mi.IsDir)\n      {\n        // we support LINK files here\n        if (mi.Reparse.Size() == 0)\n          continue;\n      }\n    }\n\n    if (ui.InArcIndex >= 0)\n    {\n      // data streams with OLD Data were written already\n      // we just need to find HashIndex in hashes.\n\n      if ((unsigned)ui.InArcIndex >= _db.SortedItems.Size())\n        return E_FAIL;\n      \n      const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]];\n      \n      if (item.StreamIndex < 0)\n      {\n        if (size == 0)\n          continue;\n        // if (_db.ItemHasStream(item))\n        return E_FAIL;\n      }\n\n      // We support empty file (size = 0, but with stream and SHA-1) from old archive\n      \n      const CStreamInfo &siOld = _db.DataStreams[item.StreamIndex];\n\n      const int index = AddUniqHash(streams.ConstData(), sortedHashes, siOld.Hash, -1);\n      // we must have written that stream already\n      if (index == -1)\n        return E_FAIL;\n\n      if (ui.AltStreamIndex < 0)\n        mi.HashIndex = index;\n      else\n        mi.AltStreams[ui.AltStreamIndex].HashIndex = index;\n      \n      continue;\n    }\n\n    CMyComPtr<ISequentialInStream> fileInStream;\n    HRESULT res = callback->GetStream(ui.CallbackIndex, &fileInStream);\n    \n    if (res == S_FALSE)\n    {\n      if (ui.AltStreamIndex >= 0)\n      {\n        mi.NumSkipAltStreams++;\n        mi.AltStreams[ui.AltStreamIndex].Skip = true;\n      }\n      else\n        mi.Skip = true;\n    }\n    else\n    {\n      RINOK(res)\n\n      int miIndex = -1;\n      \n      if (!fileInStream)\n      {\n        if (!mi.IsDir)\n          return E_INVALIDARG;\n      }\n      else if (ui.AltStreamIndex < 0)\n      {\n        CMyComPtr<IStreamGetProps2> getProps2;\n        fileInStream->QueryInterface(IID_IStreamGetProps2, (void **)&getProps2);\n        if (getProps2)\n        {\n          CStreamFileProps props;\n          if (getProps2->GetProps2(&props) == S_OK)\n          {\n            mi.Attrib = props.Attrib;\n            if (_timeOptions.Write_CTime.Val) mi.CTime = props.CTime;\n            if (_timeOptions.Write_ATime.Val) mi.ATime = props.ATime;\n            if (_timeOptions.Write_MTime.Val) mi.MTime = props.MTime;\n            mi.FileID = props.FileID_Low;\n            if (props.NumLinks <= 1)\n              mi.FileID = 0;\n            mi.VolID = props.VolID;\n            if (mi.FileID != 0)\n              miIndex = AddToHardLinkList(db.MetaItems, (unsigned)ui.MetaIndex, hlIndexes);\n\n            if (props.Size != size && props.Size != (UInt64)(Int64)-1)\n            {\n              const Int64 delta = (Int64)props.Size - (Int64)size;\n              const Int64 newComplexity = (Int64)totalComplexity + delta;\n              if (newComplexity > 0)\n              {\n                totalComplexity = (UInt64)newComplexity;\n                callback->SetTotal(totalComplexity);\n              }\n              mi.Size = props.Size;\n              size = props.Size;\n            }\n          }\n        }\n      }\n      \n      if (miIndex >= 0)\n      {\n        mi.HashIndex = db.MetaItems[miIndex].HashIndex;\n        if (mi.HashIndex >= 0)\n          streams[mi.HashIndex].RefCount++;\n        // fix for future: maybe we need to check also that real size is equal to size from IStreamGetProps2\n      }\n      else if (ui.AltStreamIndex < 0 && mi.Reparse.Size() != 0)\n      {\n        if (mi.Reparse.Size() < 8)\n          return E_FAIL;\n        NCrypto::NSha1::CContext sha1;\n        sha1.Init();\n        const size_t packSize = mi.Reparse.Size() - 8;\n        sha1.Update((const Byte *)mi.Reparse + 8, packSize);\n        Byte hash[kHashSize];\n        sha1.Final(hash);\n        \n        int index = AddUniqHash(streams.ConstData(), sortedHashes, hash, (int)streams.Size());\n\n        if (index != -1)\n          streams[index].RefCount++;\n        else\n        {\n          index = (int)streams.Size();\n          RINOK(WriteStream(outStream, (const Byte *)mi.Reparse + 8, packSize))\n          CStreamInfo s;\n          s.Resource.PackSize = packSize;\n          s.Resource.Offset = curPos;\n          s.Resource.UnpackSize = packSize;\n          s.Resource.Flags = 0; // check it\n          /*\n            if (useResourceCompression)\n              s.Resource.Flags = NResourceFlags::Compressed;\n          */\n          s.PartNumber = 1;\n          s.RefCount = 1;\n          memcpy(s.Hash, hash, kHashSize);\n          curPos += packSize;\n\n          streams.Add(s);\n        }\n        \n        mi.HashIndex = index;\n      }\n      else\n      {\n        inShaStream->SetStream(fileInStream);\n\n        CMyComPtr<IInStream> inSeekStream;\n        fileInStream.QueryInterface(IID_IInStream, (void **)&inSeekStream);\n        \n        fileInStream.Release();\n        inShaStream->Init();\n        UInt64 offsetBlockSize = 0;\n        /*\n        if (useResourceCompression)\n        {\n          for (UInt64 t = kChunkSize; t < size; t += kChunkSize)\n          {\n            Byte buf[8];\n            SetUi32(buf, (UInt32)t);\n            RINOK(WriteStream(outStream, buf, 4));\n            offsetBlockSize += 4;\n          }\n        }\n        */\n\n        // 22.02: we use additional read-only pass to calculate SHA-1\n        bool needWritePass = true;\n        int index = -1;\n        \n        if (inSeekStream /* && !sortedHashes.IsEmpty() */)\n        {\n          RINOK(copyCoder.Interface()->Code(inShaStream, NULL, NULL, NULL, lps))\n          size = copyCoder->TotalSize;\n          if (size == 0)\n            needWritePass = false;\n          else\n          {\n            Byte hash[kHashSize];\n            inShaStream->Final(hash);\n\n            index = AddUniqHash(streams.ConstData(), sortedHashes, hash, -1);\n            if (index != -1)\n            {\n              streams[index].RefCount++;\n              needWritePass = false;\n            }\n            else\n            {\n              RINOK(InStream_SeekToBegin(inSeekStream))\n              inShaStream->Init();\n            }\n          }\n        }\n        \n        if (needWritePass)\n        {\n          RINOK(copyCoder.Interface()->Code(inShaStream, outStream, NULL, NULL, lps))\n          size = copyCoder->TotalSize;\n        }\n       \n        if (size != 0)\n        {\n          if (needWritePass)\n          {\n            Byte hash[kHashSize];\n            const UInt64 packSize = offsetBlockSize + size;\n            inShaStream->Final(hash);\n            \n            index = AddUniqHash(streams.ConstData(), sortedHashes, hash, (int)streams.Size());\n            \n            if (index != -1)\n            {\n              streams[index].RefCount++;\n              outStream->Seek(-(Int64)packSize, STREAM_SEEK_CUR, &curPos);\n              outStream->SetSize(curPos);\n            }\n            else\n            {\n              index = (int)streams.Size();\n              CStreamInfo s;\n              s.Resource.PackSize = packSize;\n              s.Resource.Offset = curPos;\n              s.Resource.UnpackSize = size;\n              s.Resource.Flags = 0;\n              /*\n              if (useResourceCompression)\n              s.Resource.Flags = NResourceFlags::Compressed;\n              */\n              s.PartNumber = 1;\n              s.RefCount = 1;\n              memcpy(s.Hash, hash, kHashSize);\n              curPos += packSize;\n              \n              streams.Add(s);\n            }\n          } // needWritePass\n          if (ui.AltStreamIndex < 0)\n            mi.HashIndex = index;\n          else\n            mi.AltStreams[ui.AltStreamIndex].HashIndex = index;\n        } // (size != 0)\n      }\n    }\n    fileInStream.Release();\n    complexity += size;\n    RINOK(callback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))\n  }\n\n  while (secureBlocks.Size() < numNewImages)\n    secureBlocks.AddNew();\n\n  \n  \n  // ---------- Write Images ----------\n\n  for (i = 0; i < numNewImages; i++)\n  {\n    lps->InSize = lps->OutSize = complexity;\n    RINOK(lps->SetCur())\n    if (i < isChangedImage.Size() && !isChangedImage[i])\n    {\n      CStreamInfo s = _db.MetaStreams[i];\n      \n      RINOK(InStream_SeekSet(_volumes[1].Stream, s.Resource.Offset))\n      inStreamLimitedSpec->Init(s.Resource.PackSize);\n      RINOK(copyCoder.Interface()->Code(inStreamLimited, outStream, NULL, NULL, lps))\n      if (copyCoder->TotalSize != s.Resource.PackSize)\n        return E_FAIL;\n\n      s.Resource.Offset = curPos;\n      s.PartNumber = 1;\n      s.RefCount = 1;\n      streams.Add(s);\n\n      if (_bootIndex != 0 && _bootIndex == (UInt32)i + 1)\n      {\n        header.MetadataResource = s.Resource;\n        header.BootIndex = _bootIndex;\n      }\n\n      lps->ProgressOffset += s.Resource.PackSize;\n      curPos += s.Resource.PackSize;\n      // printf(\"\\nWrite old image %x\\n\", i + 1);\n      continue;\n    }\n\n    const CDir &tree = trees[i];\n    const UInt32 kSecuritySize = 8;\n    \n    size_t pos = kSecuritySize;\n\n    const CUniqBlocks &secUniqBlocks = secureBlocks[i];\n    const CObjectVector<CByteBuffer> &secBufs = secUniqBlocks.Bufs;\n    pos += (size_t)secUniqBlocks.GetTotalSizeInBytes();\n    pos += secBufs.Size() * 8;\n    pos = (pos + 7) & ~(size_t)7;\n    \n    db.DefaultDirItem = ri;\n    pos += db.WriteTree_Dummy(tree);\n    \n    CByteArr meta(pos);\n    \n    Set32((Byte *)meta + 4, secBufs.Size()) // num security entries\n    pos = kSecuritySize;\n    \n    if (secBufs.Size() == 0)\n    {\n      // we can write 0 here only if there is no security data, imageX does it,\n      // but some programs expect size = 8\n      Set32((Byte *)meta, 8) // size of security data\n      // Set32((Byte *)meta, 0);\n    }\n    else\n    {\n      unsigned k;\n      for (k = 0; k < secBufs.Size(); k++, pos += 8)\n      {\n        Set64(meta + pos, secBufs[k].Size())\n      }\n      for (k = 0; k < secBufs.Size(); k++)\n      {\n        const CByteBuffer &buf = secBufs[k];\n        size_t size = buf.Size();\n        if (size != 0)\n        {\n          memcpy(meta + pos, buf, size);\n          pos += size;\n        }\n      }\n      while ((pos & 7) != 0)\n        meta[pos++] = 0;\n      Set32((Byte *)meta, (UInt32)pos) // size of security data\n    }\n    \n    db.Hashes = streams.ConstData();\n    db.WriteTree(tree, (Byte *)meta, pos);\n\n    {\n      NCrypto::NSha1::CContext sha;\n      sha.Init();\n      sha.Update((const Byte *)meta, pos);\n\n      Byte digest[kHashSize];\n      sha.Final(digest);\n      \n      CStreamInfo s;\n      s.Resource.PackSize = pos;\n      s.Resource.Offset = curPos;\n      s.Resource.UnpackSize = pos;\n      s.Resource.Flags = NResourceFlags::kMetadata;\n      s.PartNumber = 1;\n      s.RefCount = 1;\n      memcpy(s.Hash, digest, kHashSize);\n      streams.Add(s);\n\n      if (_bootIndex != 0 && _bootIndex == (UInt32)i + 1)\n      {\n        header.MetadataResource = s.Resource;\n        header.BootIndex = _bootIndex;\n      }\n\n      RINOK(WriteStream(outStream, (const Byte *)meta, pos))\n      meta.Free();\n      curPos += pos;\n    }\n  }\n\n  lps->InSize = lps->OutSize = complexity;\n  RINOK(lps->SetCur())\n\n  header.OffsetResource.UnpackSize = header.OffsetResource.PackSize = (UInt64)streams.Size() * kStreamInfoSize;\n  header.OffsetResource.Offset = curPos;\n  header.OffsetResource.Flags = NResourceFlags::kMetadata;\n\n  \n  \n  // ---------- Write Streams Info Tables ----------\n\n  for (i = 0; i < streams.Size(); i++)\n  {\n    Byte buf[kStreamInfoSize];\n    streams[i].WriteTo(buf);\n    RINOK(WriteStream(outStream, buf, kStreamInfoSize))\n    curPos += kStreamInfoSize;\n  }\n\n  AString xml (\"<WIM>\");\n  AddTagUInt64_ToString(xml, \"TOTALBYTES\", curPos);\n  for (i = 0; i < trees.Size(); i++)\n  {\n    const CDir &tree = trees[i];\n\n    CXmlItem item;\n    if (_xmls.Size() == 1)\n    {\n      const CWimXml &_oldXml = _xmls[0];\n      if (i < _oldXml.Images.Size())\n      {\n        // int ttt = _oldXml.Images[i].ItemIndexInXml;\n        item = _oldXml.Xml.Root.SubItems[_oldXml.Images[i].ItemIndexInXml];\n      }\n    }\n    if (i >= isChangedImage.Size() || isChangedImage[i])\n    {\n      char temp[16];\n      if (item.Name.IsEmpty())\n      {\n        ConvertUInt32ToString(i + 1, temp);\n        item.Name = \"IMAGE\";\n        item.IsTag = true;\n        CXmlProp &prop = item.Props.AddNew();\n        prop.Name = \"INDEX\";\n        prop.Value = temp;\n      }\n      \n      AddTag_String_IfEmpty(item, \"NAME\", temp);\n      AddTag_UInt64(item, \"DIRCOUNT\", tree.GetNumDirs() - 1);\n      AddTag_UInt64(item, \"FILECOUNT\", tree.GetNumFiles());\n      AddTag_UInt64(item, \"TOTALBYTES\", tree.GetTotalSize(db.MetaItems));\n      \n      AddTag_Time(item, \"CREATIONTIME\", ftCur);\n      AddTag_Time(item, \"LASTMODIFICATIONTIME\", ftCur);\n    }\n\n    item.AppendTo(xml);\n  }\n  xml += \"</WIM>\";\n\n  size_t xmlSize;\n  {\n    UString utf16;\n    if (!ConvertUTF8ToUnicode(xml, utf16))\n      return S_FALSE;\n    xmlSize = ((size_t)utf16.Len() + 1) * 2;\n\n    CByteArr xmlBuf(xmlSize);\n    Set16((Byte *)xmlBuf, 0xFEFF)\n    for (i = 0; i < (unsigned)utf16.Len(); i++)\n    {\n      Set16((Byte *)xmlBuf + 2 + (size_t)i * 2, (UInt16)utf16[i])\n    }\n    RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize))\n  }\n  \n  header.XmlResource.UnpackSize =\n  header.XmlResource.PackSize = xmlSize;\n  header.XmlResource.Offset = curPos;\n  header.XmlResource.Flags = NResourceFlags::kMetadata;\n\n  outStream->Seek(0, STREAM_SEEK_SET, NULL);\n  header.NumImages = trees.Size();\n  {\n    Byte buf[kHeaderSizeMax];\n    header.WriteTo(buf);\n    RINOK(WriteStream(outStream, buf, kHeaderSizeMax))\n  }\n\n  if (setRestriction)\n    RINOK(setRestriction->SetRestriction(0, 0))\n\n  return S_OK;\n\n  COM_TRY_END\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Wim/WimIn.cpp",
    "content": "﻿// Archive/WimIn.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringToInt.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/XpressDecoder.h\"\n\n#include \"../Common/OutStreamWithSha1.h\"\n\n#include \"WimIn.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\nnamespace NArchive {\nnamespace NWim {\n\nstatic bool inline GetLog_val_min_dest(const UInt32 val, unsigned i, unsigned &dest)\n{\n  UInt32 v = (UInt32)1 << i;\n  for (; i < 32; i++)\n  {\n    if (v == val)\n    {\n      dest = i;\n      return true;\n    }\n    v += v;\n  }\n  return false;\n}\n\n\nHRESULT CUnpacker::UnpackChunk(\n    ISequentialInStream *inStream,\n    unsigned method, unsigned chunkSizeBits,\n    size_t inSize, size_t outSize,\n    ISequentialOutStream *outStream)\n{\n  if (inSize == outSize)\n  {\n  }\n  else if (method == NMethod::kXPRESS)\n  {\n  }\n  else if (method == NMethod::kLZX)\n  {\n    lzxDecoder.Create_if_Empty();\n    lzxDecoder->Set_WimMode(true);\n  }\n  else if (method == NMethod::kLZMS)\n  {\n    lzmsDecoder.Create_if_Empty();\n  }\n  else\n    return E_NOTIMPL;\n\n  const size_t chunkSize = (size_t)1 << chunkSizeBits;\n\n  {\n    const unsigned\n        kAdditionalOutputBufSize = MyMax(NCompress::NLzx::\n        kAdditionalOutputBufSize,        NCompress::NXpress::\n        kAdditionalOutputBufSize);\n    unpackBuf.EnsureCapacity(chunkSize + kAdditionalOutputBufSize);\n    if (!unpackBuf.Data)\n      return E_OUTOFMEMORY;\n  }\n  \n  HRESULT res = S_FALSE;\n  size_t unpackedSize = 0;\n  \n  if (inSize == outSize)\n  {\n    unpackedSize = outSize;\n    res = ReadStream(inStream, unpackBuf.Data, &unpackedSize);\n    TotalPacked += unpackedSize;\n  }\n  else if (inSize < chunkSize)\n  {\n    const unsigned kAdditionalInputSize = 32;\n    packBuf.EnsureCapacity(chunkSize + kAdditionalInputSize);\n    if (!packBuf.Data)\n      return E_OUTOFMEMORY;\n    \n    RINOK(ReadStream_FALSE(inStream, packBuf.Data, inSize))\n    memset(packBuf.Data + inSize, 0xff, kAdditionalInputSize);\n\n    TotalPacked += inSize;\n    \n    if (method == NMethod::kXPRESS)\n    {\n      res = NCompress::NXpress::Decode_WithExceedWrite(packBuf.Data, inSize, unpackBuf.Data, outSize);\n      if (res == S_OK)\n        unpackedSize = outSize;\n    }\n    else if (method == NMethod::kLZX)\n    {\n      res = lzxDecoder->Set_ExternalWindow_DictBits(unpackBuf.Data, chunkSizeBits);\n      if (res != S_OK)\n        return E_NOTIMPL;\n      lzxDecoder->Set_KeepHistoryForNext(false);\n      lzxDecoder->Set_KeepHistory(false);\n      res = lzxDecoder->Code_WithExceedReadWrite(packBuf.Data, inSize, (UInt32)outSize);\n      unpackedSize = lzxDecoder->GetUnpackSize();\n      if (res == S_OK && !lzxDecoder->WasBlockFinished())\n        res = S_FALSE;\n    }\n    else\n    {\n      res = lzmsDecoder->Code(packBuf.Data, inSize, unpackBuf.Data, outSize);\n      unpackedSize = lzmsDecoder->GetUnpackSize();\n    }\n  }\n  \n  if (unpackedSize != outSize)\n  {\n    if (res == S_OK)\n      res = S_FALSE;\n    \n    if (unpackedSize > outSize)\n      res = S_FALSE;\n    else\n      memset(unpackBuf.Data + unpackedSize, 0, outSize - unpackedSize);\n  }\n  \n  if (outStream)\n  {\n    RINOK(WriteStream(outStream, unpackBuf.Data, outSize))\n  }\n  \n  return res;\n}\n\n\nHRESULT CUnpacker::Unpack2(\n    IInStream *inStream,\n    const CResource &resource,\n    const CHeader &header,\n    const CDatabase *db,\n    ISequentialOutStream *outStream,\n    ICompressProgressInfo *progress)\n{\n  if (!resource.IsCompressed() && !resource.IsSolid())\n  {\n    copyCoder.Create_if_Empty();\n\n    CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> limitedStream;\n    limitedStream->SetStream(inStream);\n    \n    RINOK(InStream_SeekSet(inStream, resource.Offset))\n    if (resource.PackSize != resource.UnpackSize)\n      return S_FALSE;\n\n    limitedStream->Init(resource.PackSize);\n    TotalPacked += resource.PackSize;\n    \n    HRESULT res = copyCoder.Interface()->Code(limitedStream, outStream, NULL, NULL, progress);\n    \n    if (res == S_OK && copyCoder->TotalSize != resource.UnpackSize)\n      res = S_FALSE;\n    return res;\n  }\n  \n  if (resource.IsSolid())\n  {\n    if (!db || resource.SolidIndex < 0)\n      return E_NOTIMPL;\n    if (resource.IsCompressed())\n      return E_NOTIMPL;\n\n    const CSolid &ss = db->Solids[resource.SolidIndex];\n    \n    const unsigned chunkSizeBits = ss.ChunkSizeBits;\n    const size_t chunkSize = (size_t)1 << chunkSizeBits;\n    \n    size_t chunkIndex = 0;\n    UInt64 rem = ss.UnpackSize;\n    size_t offsetInChunk = 0;\n    \n    if (resource.IsSolidSmall())\n    {\n      UInt64 offs = resource.Offset;\n      if (offs < ss.SolidOffset)\n        return E_NOTIMPL;\n      offs -= ss.SolidOffset;\n      if (offs > ss.UnpackSize)\n        return E_NOTIMPL;\n      rem = resource.PackSize;\n      if (rem > ss.UnpackSize - offs)\n        return E_NOTIMPL;\n      chunkIndex = (size_t)(offs >> chunkSizeBits);\n      offsetInChunk = (size_t)offs & (chunkSize - 1);\n    }\n    \n    UInt64 packProcessed = 0;\n    UInt64 outProcessed = 0;\n    \n    if (_solidIndex == resource.SolidIndex && _unpackedChunkIndex == chunkIndex)\n    {\n      size_t cur = chunkSize - offsetInChunk;\n      if (cur > rem)\n        cur = (size_t)rem;\n      RINOK(WriteStream(outStream, unpackBuf.Data + offsetInChunk, cur))\n      outProcessed += cur;\n      rem -= cur;\n      offsetInChunk = 0;\n      chunkIndex++;\n    }\n    \n    for (;;)\n    {\n      if (rem == 0)\n        return S_OK;\n    \n      const UInt64 offset = ss.Chunks[chunkIndex];\n      const UInt64 packSize = ss.GetChunkPackSize(chunkIndex);\n      const CResource &rs = db->DataStreams[ss.StreamIndex].Resource;\n      RINOK(InStream_SeekSet(inStream, rs.Offset + ss.HeadersSize + offset))\n      \n      size_t cur = chunkSize;\n      const UInt64 unpackRem = ss.UnpackSize - ((UInt64)chunkIndex << chunkSizeBits);\n      if (cur > unpackRem)\n        cur = (size_t)unpackRem;\n      \n      _solidIndex = -1;\n      _unpackedChunkIndex = 0;\n      \n      const HRESULT res = UnpackChunk(inStream, (unsigned)ss.Method, chunkSizeBits, (size_t)packSize, cur, NULL);\n      \n      if (res != S_OK)\n      {\n        // We ignore data errors in solid stream. SHA will show what files are bad.\n        if (res != S_FALSE)\n          return res;\n      }\n      \n      _solidIndex = resource.SolidIndex;\n      _unpackedChunkIndex = chunkIndex;\n\n      if (cur < offsetInChunk)\n        return E_FAIL;\n      \n      cur -= offsetInChunk;\n        \n      if (cur > rem)\n        cur = (size_t)rem;\n      \n      RINOK(WriteStream(outStream, unpackBuf.Data + offsetInChunk, cur))\n      \n      if (progress)\n      {\n        RINOK(progress->SetRatioInfo(&packProcessed, &outProcessed))\n        packProcessed += packSize;\n        outProcessed += cur;\n      }\n      \n      rem -= cur;\n      offsetInChunk = 0;\n      chunkIndex++;\n    }\n  }\n\n\n  // ---------- NON Solid ----------\n\n  const UInt64 unpackSize = resource.UnpackSize;\n  if (unpackSize == 0)\n  {\n    if (resource.PackSize == 0)\n      return S_OK;\n    return S_FALSE;\n  }\n\n  if (unpackSize > ((UInt64)1 << 63))\n    return E_NOTIMPL;\n\n  const unsigned chunkSizeBits = header.ChunkSizeBits;\n  const unsigned entrySizeShifts = (resource.UnpackSize < ((UInt64)1 << 32) ? 2 : 3);\n\n  UInt64 baseOffset = resource.Offset;\n  UInt64 packDataSize;\n  size_t numChunks;\n  {\n    const UInt64 numChunks64 = (unpackSize + (((UInt32)1 << chunkSizeBits) - 1)) >> chunkSizeBits;\n    const UInt64 sizesBufSize64 = (numChunks64 - 1) << entrySizeShifts;\n    if (sizesBufSize64 > resource.PackSize)\n      return S_FALSE;\n    packDataSize = resource.PackSize - sizesBufSize64;\n    const size_t sizesBufSize = (size_t)sizesBufSize64;\n    if (sizesBufSize != sizesBufSize64)\n      return E_OUTOFMEMORY;\n    sizesBuf.AllocAtLeast(sizesBufSize);\n    RINOK(InStream_SeekSet(inStream, baseOffset))\n    RINOK(ReadStream_FALSE(inStream, sizesBuf, sizesBufSize))\n    baseOffset += sizesBufSize64;\n    numChunks = (size_t)numChunks64;\n  }\n\n  _solidIndex = -1;\n  _unpackedChunkIndex = 0;\n\n  UInt64 outProcessed = 0;\n  UInt64 offset = 0;\n  \n  for (size_t i = 0; i < numChunks; i++)\n  {\n    UInt64 nextOffset = packDataSize;\n    \n    if (i + 1 < numChunks)\n    {\n      const Byte *p = (const Byte *)sizesBuf + (i << entrySizeShifts);\n      nextOffset = (entrySizeShifts == 2) ? Get32(p): Get64(p);\n    }\n    \n    if (nextOffset < offset)\n      return S_FALSE;\n\n    UInt64 inSize64 = nextOffset - offset;\n    size_t inSize = (size_t)inSize64;\n    if (inSize != inSize64)\n      return S_FALSE;\n\n    RINOK(InStream_SeekSet(inStream, baseOffset + offset))\n\n    if (progress)\n    {\n      RINOK(progress->SetRatioInfo(&offset, &outProcessed))\n    }\n    \n    size_t outSize = (size_t)1 << chunkSizeBits;\n    const UInt64 rem = unpackSize - outProcessed;\n    if (outSize > rem)\n      outSize = (size_t)rem;\n\n    RINOK(UnpackChunk(inStream, header.GetMethod(), chunkSizeBits, inSize, outSize, outStream))\n\n    outProcessed += outSize;\n    offset = nextOffset;\n  }\n  \n  return S_OK;\n}\n\n\nHRESULT CUnpacker::Unpack(IInStream *inStream, const CResource &resource, const CHeader &header, const CDatabase *db,\n    ISequentialOutStream *outStream, ICompressProgressInfo *progress, Byte *digest)\n{\n  CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha1> shaStream;\n  // outStream can be NULL, so we use COutStreamWithSha1 even if sha1 is not required\n  shaStream->SetStream(outStream);\n  shaStream->Init(digest != NULL);\n  const HRESULT res = Unpack2(inStream, resource, header, db, shaStream, progress);\n  if (digest)\n    shaStream->Final(digest);\n  return res;\n}\n\n\nHRESULT CUnpacker::UnpackData(IInStream *inStream,\n    const CResource &resource, const CHeader &header,\n    const CDatabase *db,\n    CByteBuffer &buf, Byte *digest)\n{\n  // if (resource.IsSolid()) return E_NOTIMPL;\n  UInt64 unpackSize64 = resource.UnpackSize;\n  if (db)\n    unpackSize64 = db->Get_UnpackSize_of_Resource(resource);\n  const size_t size = (size_t)unpackSize64;\n  if (size != unpackSize64)\n    return E_OUTOFMEMORY;\n  buf.Alloc(size);\n\n  CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;\n  outStream->Init((Byte *)buf, size);\n  return Unpack(inStream, resource, header, db, outStream, NULL, digest);\n}\n\n\nvoid CResource::Parse(const Byte *p)\n{\n  Flags = p[7];\n  PackSize = Get64(p) & (((UInt64)1 << 56) - 1);\n  Offset = Get64(p + 8);\n  UnpackSize = Get64(p + 16);\n  KeepSolid = false;\n  SolidIndex = -1;\n}\n\n#define GET_RESOURCE(_p_, res) res.ParseAndUpdatePhySize(_p_, phySize)\n\nstatic inline void ParseStream(bool oldVersion, const Byte *p, CStreamInfo &s)\n{\n  s.Resource.Parse(p);\n  if (oldVersion)\n  {\n    s.PartNumber = 1;\n    s.Id = Get32(p + 24);\n    p += 28;\n  }\n  else\n  {\n    s.PartNumber = Get16(p + 24);\n    p += 26;\n  }\n  s.RefCount = Get32(p);\n  memcpy(s.Hash, p + 4, kHashSize);\n}\n\n\n#define kLongPath \"[LongPath]\"\n\nvoid CDatabase::GetShortName(unsigned index, NWindows::NCOM::CPropVariant &name) const\n{\n  const CItem &item = Items[index];\n  const CImage &image = Images[item.ImageIndex];\n  if (item.Parent < 0 && image.NumEmptyRootItems != 0)\n  {\n    name.Clear();\n    return;\n  }\n  const Byte *meta = image.Meta + item.Offset +\n      (IsOldVersion ? kDirRecordSizeOld : kDirRecordSize);\n  UInt32 fileNameLen = Get16(meta - 2);\n  UInt32 shortLen = Get16(meta - 4) / 2;\n  wchar_t *s = name.AllocBstr(shortLen);\n  if (fileNameLen != 0)\n    meta += fileNameLen + 2;\n  for (UInt32 i = 0; i < shortLen; i++)\n    s[i] = Get16(meta + i * 2);\n  s[shortLen] = 0;\n  // empty shortName has no ZERO at the end ?\n}\n\n\nvoid CDatabase::GetItemName(unsigned index, NWindows::NCOM::CPropVariant &name) const\n{\n  const CItem &item = Items[index];\n  const CImage &image = Images[item.ImageIndex];\n  if (item.Parent < 0 && image.NumEmptyRootItems != 0)\n  {\n    name = image.RootName;\n    return;\n  }\n  const Byte *meta = image.Meta + item.Offset +\n      (item.IsAltStream ?\n      (IsOldVersion ? 0x10 : 0x24) :\n      (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2));\n  UInt32 len = Get16(meta) / 2;\n  wchar_t *s = name.AllocBstr(len);\n  meta += 2;\n  len++;\n  for (UInt32 i = 0; i < len; i++)\n    s[i] = Get16(meta + i * 2);\n}\n\n\nvoid CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCOM::CPropVariant &path) const\n{\n  unsigned size = 0;\n  int index = (int)index1;\n  const int imageIndex = Items[index].ImageIndex;\n  const CImage &image = Images[imageIndex];\n  \n  unsigned newLevel = 0;\n  bool needColon = false;\n\n  for (;;)\n  {\n    const CItem &item = Items[index];\n    index = item.Parent;\n    if (index >= 0 || image.NumEmptyRootItems == 0)\n    {\n      const Byte *meta = image.Meta + item.Offset;\n      meta += item.IsAltStream ?\n          (IsOldVersion ? 0x10 : 0x24) :\n          (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);\n      needColon = item.IsAltStream;\n      size += Get16(meta) / 2;\n      size += newLevel;\n      newLevel = 1;\n      if (size >= ((UInt32)1 << 15))\n      {\n        path = kLongPath;\n        return;\n      }\n    }\n    if (index < 0)\n      break;\n  }\n\n  if (showImageNumber)\n  {\n    size += image.RootName.Len();\n    size += newLevel;\n  }\n  else if (needColon)\n    size++;\n\n  wchar_t *s = path.AllocBstr(size);\n  s[size] = 0;\n  \n  if (showImageNumber)\n  {\n    MyStringCopy(s, (const wchar_t *)image.RootName);\n    if (newLevel)\n      s[image.RootName.Len()] = (wchar_t)(needColon ? L':' : WCHAR_PATH_SEPARATOR);\n  }\n  else if (needColon)\n    s[0] = L':';\n\n  index = (int)index1;\n  wchar_t separator = 0;\n  \n  for (;;)\n  {\n    const CItem &item = Items[index];\n    index = item.Parent;\n    if (index >= 0 || image.NumEmptyRootItems == 0)\n    {\n      if (separator != 0)\n        s[--size] = separator;\n      const Byte *meta = image.Meta + item.Offset;\n      meta += (item.IsAltStream) ?\n          (IsOldVersion ? 0x10: 0x24) :\n          (IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);\n      unsigned len = Get16(meta) / 2;\n      size -= len;\n      wchar_t *dest = s + size;\n      meta += 2;\n      for (unsigned i = 0; i < len; i++)\n      {\n        wchar_t c = Get16(meta + i * 2);\n        if (c == L'/')\n          c = L'_';\n        #if WCHAR_PATH_SEPARATOR != L'/'\n        else if (c == L'\\\\')\n          c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // 22.00 : WSL scheme\n        #endif\n        dest[i] = c;\n      }\n    }\n    if (index < 0)\n      return;\n    separator = item.IsAltStream ? L':' : WCHAR_PATH_SEPARATOR;\n  }\n}\n\n\n// if (ver <= 1.10), root folder contains real items.\n// if (ver >= 1.12), root folder contains only one folder with empty name.\n\nHRESULT CDatabase::ParseDirItem(size_t pos, int parent)\n{\n  const unsigned align = GetDirAlignMask();\n  if ((pos & align) != 0)\n    return S_FALSE;\n\n  for (unsigned numItems = 0;; numItems++)\n  {\n    if (OpenCallback && (Items.Size() & 0xFFFF) == 0)\n    {\n      UInt64 numFiles = Items.Size();\n      RINOK(OpenCallback->SetCompleted(&numFiles, NULL))\n    }\n    \n    const size_t rem = DirSize - pos;\n    if (pos < DirStartOffset || pos > DirSize || rem < 8)\n      return S_FALSE;\n\n    const Byte *p = DirData + pos;\n\n    UInt64 len = Get64(p);\n    if (len == 0)\n    {\n      DirProcessed += 8;\n      return S_OK;\n    }\n    \n    if ((len & align) != 0 || rem < len)\n      return S_FALSE;\n    \n    DirProcessed += (size_t)len;\n    if (DirProcessed > DirSize)\n      return S_FALSE;\n\n    const unsigned dirRecordSize = IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;\n    if (len < dirRecordSize)\n      return S_FALSE;\n\n    CItem item;\n    UInt32 attrib = Get32(p + 8);\n    item.IsDir = ((attrib & 0x10) != 0);\n    UInt64 subdirOffset = Get64(p + 0x10);\n\n    const UInt32 numAltStreams = Get16(p + dirRecordSize - 6);\n    const UInt32 shortNameLen = Get16(p + dirRecordSize - 4);\n    const UInt32 fileNameLen = Get16(p + dirRecordSize - 2);\n    if ((shortNameLen & 1) != 0 || (fileNameLen & 1) != 0)\n      return S_FALSE;\n    const UInt32 shortNameLen2 = (shortNameLen == 0 ? shortNameLen : shortNameLen + 2);\n    const UInt32 fileNameLen2 = (fileNameLen == 0 ? fileNameLen : fileNameLen + 2);\n    if (((dirRecordSize + fileNameLen2 + shortNameLen2 + align) & ~align) > len)\n      return S_FALSE;\n    \n    p += dirRecordSize;\n    \n    {\n      if (*(const UInt16 *)(const void *)(p + fileNameLen) != 0)\n        return S_FALSE;\n      for (UInt32 j = 0; j < fileNameLen; j += 2)\n        if (*(const UInt16 *)(const void *)(p + j) == 0)\n          return S_FALSE;\n    }\n\n    // PRF(printf(\"\\n%S\", p));\n\n    if (shortNameLen != 0)\n    {\n      // empty shortName has no ZERO at the end ?\n      const Byte *p2 = p + fileNameLen2;\n      if (*(const UInt16 *)(const void *)(p2 + shortNameLen) != 0)\n        return S_FALSE;\n      for (UInt32 j = 0; j < shortNameLen; j += 2)\n        if (*(const UInt16 *)(const void *)(p2 + j) == 0)\n          return S_FALSE;\n    }\n      \n    item.Offset = pos;\n    item.Parent = parent;\n    item.ImageIndex = (int)Images.Size() - 1;\n    \n    const unsigned prevIndex = Items.Add(item);\n\n    pos += (size_t)len;\n\n    for (UInt32 i = 0; i < numAltStreams; i++)\n    {\n      const size_t rem2 = DirSize - pos;\n      if (pos < DirStartOffset || pos > DirSize || rem2 < 8)\n        return S_FALSE;\n      const Byte *p2 = DirData + pos;\n      const UInt64 len2 = Get64(p2);\n      if ((len2 & align) != 0 || rem2 < len2\n          || len2 < (unsigned)(IsOldVersion ? 0x18 : 0x28))\n        return S_FALSE;\n     \n      DirProcessed += (size_t)len2;\n      if (DirProcessed > DirSize)\n        return S_FALSE;\n\n      unsigned extraOffset = 0;\n      \n      if (IsOldVersion)\n        extraOffset = 0x10;\n      else\n      {\n        if (Get64(p2 + 8) != 0)\n          return S_FALSE;\n        extraOffset = 0x24;\n      }\n      \n      const UInt32 fileNameLen111 = Get16(p2 + extraOffset);\n      if ((fileNameLen111 & 1) != 0)\n        return S_FALSE;\n      /* Probably different versions of ImageX can use different number of\n         additional ZEROs. So we don't use exact check. */\n      const UInt32 fileNameLen222 = (fileNameLen111 == 0 ? fileNameLen111 : fileNameLen111 + 2);\n      if (((extraOffset + 2 + fileNameLen222 + align) & ~align) > len2)\n        return S_FALSE;\n      \n      {\n        const Byte *p3 = p2 + extraOffset + 2;\n        if (*(const UInt16 *)(const void *)(p3 + fileNameLen111) != 0)\n          return S_FALSE;\n        for (UInt32 j = 0; j < fileNameLen111; j += 2)\n          if (*(const UInt16 *)(const void *)(p3 + j) == 0)\n            return S_FALSE;\n  \n        // PRF(printf(\"\\n  %S\", p3));\n      }\n\n\n      /* wim uses alt sreams list, if there is at least one alt stream.\n         And alt stream without name is main stream. */\n\n      // Why wimlib writes two alt streams for REPARSE_POINT, with empty second alt stream?\n      \n      Byte *prevMeta = DirData + item.Offset;\n\n      if (fileNameLen111 == 0 &&\n          ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) || !item.IsDir)\n          && (IsOldVersion || IsEmptySha(prevMeta + 0x40)))\n      {\n        if (IsOldVersion)\n          memcpy(prevMeta + 0x10, p2 + 8, 4); // It's 32-bit Id\n        else if (!IsEmptySha(p2 + 0x10))\n        {\n          // if (IsEmptySha(prevMeta + 0x40))\n            memcpy(prevMeta + 0x40, p2 + 0x10, kHashSize);\n          // else HeadersError = true;\n        }\n      }\n      else\n      {\n        ThereAreAltStreams = true;\n        CItem item2;\n        item2.Offset = pos;\n        item2.IsAltStream = true;\n        item2.Parent = (int)prevIndex;\n        item2.ImageIndex = (int)Images.Size() - 1;\n        Items.Add(item2);\n      }\n\n      pos += (size_t)len2;\n    }\n\n    if (parent < 0 && numItems == 0 && shortNameLen == 0 && fileNameLen == 0 && item.IsDir)\n    {\n      const Byte *p2 = DirData + pos;\n      if (DirSize - pos >= 8 && Get64(p2) == 0)\n      {\n        CImage &image = Images.Back();\n        image.NumEmptyRootItems = 1;\n\n        if (subdirOffset != 0\n            && DirSize - pos >= 16\n            && Get64(p2 + 8) != 0\n            && pos + 8 < subdirOffset)\n        {\n          // Longhorn.4093 contains hidden files after empty root folder and before items of next folder. Why?\n          // That code shows them. If we want to ignore them, we need to update DirProcessed.\n          // DirProcessed += (size_t)(subdirOffset - (pos + 8));\n          // printf(\"\\ndirOffset = %5d hiddenOffset = %5d\\n\", (int)subdirOffset, (int)pos + 8);\n          subdirOffset = pos + 8;\n          // return S_FALSE;\n        }\n      }\n    }\n\n    if (item.IsDir && subdirOffset != 0)\n    {\n      RINOK(ParseDirItem((size_t)subdirOffset, (int)prevIndex))\n    }\n  }\n}\n\n\nHRESULT CDatabase::ParseImageDirs(CByteBuffer &buf, int parent)\n{\n  DirData = buf;\n  DirSize = buf.Size();\n  if (DirSize < 8)\n    return S_FALSE;\n  const Byte *p = DirData;\n  size_t pos = 0;\n  CImage &image = Images.Back();\n\n  if (IsOldVersion)\n  {\n    UInt32 numEntries = Get32(p + 4);\n\n    if (numEntries > (1 << 28) ||\n        numEntries > (DirSize >> 3))\n      return S_FALSE;\n\n    UInt32 sum = 8;\n    if (numEntries != 0)\n      sum = numEntries * 8;\n\n    image.SecurOffsets.ClearAndReserve(numEntries + 1);\n    image.SecurOffsets.AddInReserved(sum);\n\n    for (UInt32 i = 0; i < numEntries; i++)\n    {\n      const Byte *pp = p + (size_t)i * 8;\n      UInt32 len = Get32(pp);\n      if (i != 0 && Get32(pp + 4) != 0)\n        return S_FALSE;\n      if (len > DirSize - sum)\n        return S_FALSE;\n      sum += len;\n      if (sum < len)\n        return S_FALSE;\n      image.SecurOffsets.AddInReserved(sum);\n    }\n\n    pos = sum;\n\n    const size_t align = GetDirAlignMask();\n    pos = (pos + align) & ~(size_t)align;\n  }\n  else\n  {\n    UInt32 totalLen = Get32(p);\n    if (totalLen == 0)\n      pos = 8;\n    else\n    {\n      if (totalLen < 8)\n        return S_FALSE;\n      UInt32 numEntries = Get32(p + 4);\n      pos = 8;\n      if (totalLen > DirSize || numEntries > ((totalLen - 8) >> 3))\n        return S_FALSE;\n      UInt32 sum = (UInt32)pos + numEntries * 8;\n      image.SecurOffsets.ClearAndReserve(numEntries + 1);\n      image.SecurOffsets.AddInReserved(sum);\n      \n      for (UInt32 i = 0; i < numEntries; i++, pos += 8)\n      {\n        UInt64 len = Get64(p + pos);\n        if (len > totalLen - sum)\n          return S_FALSE;\n        sum += (UInt32)len;\n        image.SecurOffsets.AddInReserved(sum);\n      }\n      \n      pos = sum;\n      pos = (pos + 7) & ~(size_t)7;\n      if (pos != (((size_t)totalLen + 7) & ~(size_t)7))\n        return S_FALSE;\n    }\n  }\n  \n  if (pos > DirSize)\n    return S_FALSE;\n  \n  DirStartOffset = DirProcessed = pos;\n  image.StartItem = Items.Size();\n\n  RINOK(ParseDirItem(pos, parent))\n  \n  image.NumItems = Items.Size() - image.StartItem;\n  if (DirProcessed == DirSize)\n    return S_OK;\n\n  /* Original program writes additional 8 bytes (END_OF_ROOT_FOLDER),\n     but the reference to that folder is empty */\n\n  // we can't use DirProcessed - DirStartOffset == 112 check if there is alt stream in root\n  if (DirProcessed == DirSize - 8 && Get64(p + DirSize - 8) != 0)\n    return S_OK;\n\n  // 18.06: we support cases, when some old dism can capture images\n  // where DirProcessed much smaller than DirSize\n  HeadersError = true;\n  return S_OK;\n  // return S_FALSE;\n}\n\n\nHRESULT CHeader::Parse(const Byte *p, UInt64 &phySize)\n{\n  UInt32 headerSize = Get32(p + 8);\n  phySize = headerSize;\n  Version = Get32(p + 0x0C);\n  Flags = Get32(p + 0x10);\n  if (!IsSupported())\n    return S_FALSE;\n  \n  {\n    ChunkSize = Get32(p + 0x14);\n    ChunkSizeBits = kChunkSizeBits;\n    if (ChunkSize != 0)\n    {\n      if (!GetLog_val_min_dest(ChunkSize, 12, ChunkSizeBits))\n        return S_FALSE;\n    }\n  }\n\n  _isOldVersion = false;\n  _isNewVersion = false;\n  \n  if (IsSolidVersion())\n    _isNewVersion = true;\n  else\n  {\n    if (Version < 0x010900)\n      return S_FALSE;\n    _isOldVersion = (Version <= 0x010A00);\n    // We don't know details about 1.11 version. So we use headerSize to guess exact features.\n    if (Version == 0x010B00 && headerSize == 0x60)\n      _isOldVersion = true;\n    _isNewVersion = (Version >= 0x010D00);\n  }\n\n  unsigned offset;\n  \n  if (IsOldVersion())\n  {\n    if (headerSize != 0x60)\n      return S_FALSE;\n    memset(Guid, 0, 16);\n    offset = 0x18;\n    PartNumber = 1;\n    NumParts = 1;\n  }\n  else\n  {\n    if (headerSize < 0x74)\n      return S_FALSE;\n    memcpy(Guid, p + 0x18, 16);\n    PartNumber = Get16(p + 0x28);\n    NumParts = Get16(p + 0x2A);\n    if (PartNumber == 0 || PartNumber > NumParts)\n      return S_FALSE;\n    offset = 0x2C;\n    if (IsNewVersion())\n    {\n      // if (headerSize < 0xD0)\n      if (headerSize != 0xD0)\n        return S_FALSE;\n      NumImages = Get32(p + offset);\n      offset += 4;\n    }\n  }\n  \n  GET_RESOURCE(p + offset       , OffsetResource);\n  GET_RESOURCE(p + offset + 0x18, XmlResource);\n  GET_RESOURCE(p + offset + 0x30, MetadataResource);\n  BootIndex = 0;\n  \n  if (IsNewVersion())\n  {\n    BootIndex = Get32(p + offset + 0x48);\n    GET_RESOURCE(p + offset + 0x4C, IntegrityResource);\n  }\n\n  return S_OK;\n}\n\n\nconst Byte kSignature[kSignatureSize] = { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 };\n\nHRESULT ReadHeader(IInStream *inStream, CHeader &h, UInt64 &phySize)\n{\n  Byte p[kHeaderSizeMax];\n  RINOK(ReadStream_FALSE(inStream, p, kHeaderSizeMax))\n  if (memcmp(p, kSignature, kSignatureSize) != 0)\n    return S_FALSE;\n  return h.Parse(p, phySize);\n}\n\n\nstatic HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)\n{\n  CByteBuffer offsetBuf;\n  \n  CUnpacker unpacker;\n  RINOK(unpacker.UnpackData(inStream, h.OffsetResource, h, NULL, offsetBuf, NULL))\n  \n  const size_t streamInfoSize = h.IsOldVersion() ? kStreamInfoSize + 2 : kStreamInfoSize;\n  {\n    const unsigned numItems = (unsigned)(offsetBuf.Size() / streamInfoSize);\n    if ((size_t)numItems * streamInfoSize != offsetBuf.Size())\n      return S_FALSE;\n    const unsigned numItems2 = db.DataStreams.Size() + numItems;\n    if (numItems2 < numItems)\n      return S_FALSE;\n    db.DataStreams.Reserve(numItems2);\n  }\n\n  bool keepSolid = false;\n\n  for (size_t i = 0; i < offsetBuf.Size(); i += streamInfoSize)\n  {\n    CStreamInfo s;\n    ParseStream(h.IsOldVersion(), (const Byte *)offsetBuf + i, s);\n\n    PRF(printf(\"\\n\"));\n    PRF(printf(s.Resource.IsMetadata() ? \"### META\" : \"    DATA\"));\n    PRF(printf(\" %2X\", s.Resource.Flags));\n    PRF(printf(\" %9I64X\", s.Resource.Offset));\n    PRF(printf(\" %9I64X\", s.Resource.PackSize));\n    PRF(printf(\" %9I64X\", s.Resource.UnpackSize));\n    PRF(printf(\" %d\", s.RefCount));\n    \n    if (s.PartNumber != h.PartNumber)\n      continue;\n\n    if (s.Resource.IsSolid())\n    {\n      s.Resource.KeepSolid = keepSolid;\n      keepSolid = true;\n    }\n    else\n    {\n      s.Resource.KeepSolid = false;\n      keepSolid = false;\n    }\n\n    if (!s.Resource.IsMetadata())\n      db.DataStreams.AddInReserved(s);\n    else\n    {\n      if (s.Resource.IsSolid())\n        return E_NOTIMPL;\n      if (s.RefCount == 0)\n      {\n        // some wims have such (deleted?) metadata stream.\n        // examples: boot.wim in VistaBeta2, WinPE.wim from WAIK.\n        // db.DataStreams.Add(s);\n        // we can show these delete images, if we comment \"continue\" command;\n        continue;\n      }\n      \n      if (s.RefCount > 1)\n      {\n        return S_FALSE;\n        // s.RefCount--;\n        // db.DataStreams.Add(s);\n      }\n\n      db.MetaStreams.Add(s);\n    }\n  }\n  \n  PRF(printf(\"\\n\"));\n  \n  return S_OK;\n}\n\n\nHRESULT CDatabase::OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml)\n{\n  CUnpacker unpacker;\n  return unpacker.UnpackData(inStream, h.XmlResource, h, this, xml, NULL);\n}\n\nstatic void SetRootNames(CImage &image, unsigned value)\n{\n  wchar_t temp[16];\n  ConvertUInt32ToString(value, temp);\n  image.RootName = temp;\n  image.RootNameBuf.Alloc(image.RootName.Len() * 2 + 2);\n  Byte *p = image.RootNameBuf;\n  unsigned len = image.RootName.Len() + 1;\n  for (unsigned k = 0; k < len; k++)\n  {\n    p[k * 2] = (Byte)temp[k];\n    p[k * 2 + 1] = 0;\n  }\n}\n\n\nHRESULT CDatabase::Open(IInStream *inStream, const CHeader &h, unsigned numItemsReserve, IArchiveOpenCallback *openCallback)\n{\n  OpenCallback = openCallback;\n  IsOldVersion = h.IsOldVersion();\n  IsOldVersion9 = (h.Version == 0x10900);\n\n  RINOK(ReadStreams(inStream, h, *this))\n\n  bool needBootMetadata = !h.MetadataResource.IsEmpty();\n  unsigned numNonDeletedImages = 0;\n\n  CUnpacker unpacker;\n\n  FOR_VECTOR (i, MetaStreams)\n  {\n    const CStreamInfo &si = MetaStreams[i];\n\n    if (h.PartNumber != 1 || si.PartNumber != h.PartNumber)\n      continue;\n\n    const unsigned userImage = Images.Size() + GetStartImageIndex();\n    CImage &image = Images.AddNew();\n    SetRootNames(image, userImage);\n    \n    CByteBuffer &metadata = image.Meta;\n    Byte hash[kHashSize];\n    \n    RINOK(unpacker.UnpackData(inStream, si.Resource, h, this, metadata, hash))\n   \n    if (memcmp(hash, si.Hash, kHashSize) != 0 &&\n        !(h.IsOldVersion() && IsEmptySha(si.Hash)))\n      return S_FALSE;\n    \n    image.NumEmptyRootItems = 0;\n    \n    if (Items.IsEmpty())\n      Items.ClearAndReserve(numItemsReserve);\n\n    RINOK(ParseImageDirs(metadata, -1))\n    \n    if (needBootMetadata)\n    {\n      bool sameRes = (h.MetadataResource.Offset == si.Resource.Offset);\n      if (sameRes)\n        needBootMetadata = false;\n      if (h.IsNewVersion())\n      {\n        if (si.RefCount == 1)\n        {\n          numNonDeletedImages++;\n          bool isBootIndex = (h.BootIndex == numNonDeletedImages);\n          if (sameRes && !isBootIndex)\n            return S_FALSE;\n          if (isBootIndex && !sameRes)\n            return S_FALSE;\n        }\n      }\n    }\n  }\n  \n  if (needBootMetadata)\n    return S_FALSE;\n  return S_OK;\n}\n\n\nbool CDatabase::ItemHasStream(const CItem &item) const\n{\n  if (item.ImageIndex < 0)\n    return true;\n  const Byte *meta = Images[item.ImageIndex].Meta + item.Offset;\n  if (IsOldVersion)\n  {\n    // old wim use same field for file_id and dir_offset;\n    if (item.IsDir)\n      return false;\n    meta += (item.IsAltStream ? 0x8 : 0x10);\n    UInt32 id = GetUi32(meta);\n    return id != 0;\n  }\n  meta += (item.IsAltStream ? 0x10 : 0x40);\n  return !IsEmptySha(meta);\n}\n\n\n#define RINOZ(x) { int _tt_ = (x); if (_tt_ != 0) return _tt_; }\n\nstatic int CompareStreamsByPos(const CStreamInfo *p1, const CStreamInfo *p2, void * /* param */)\n{\n  RINOZ(MyCompare(p1->PartNumber, p2->PartNumber))\n  RINOZ(MyCompare(p1->Resource.Offset, p2->Resource.Offset))\n  return MyCompare(p1->Resource.PackSize, p2->Resource.PackSize);\n}\n\nstatic int CompareIDs(const unsigned *p1, const unsigned *p2, void *param)\n{\n  const CStreamInfo *streams = (const CStreamInfo *)param;\n  return MyCompare(streams[*p1].Id, streams[*p2].Id);\n}\n\nstatic int CompareHashRefs(const unsigned *p1, const unsigned *p2, void *param)\n{\n  const CStreamInfo *streams = (const CStreamInfo *)param;\n  return memcmp(streams[*p1].Hash, streams[*p2].Hash, kHashSize);\n}\n\nstatic int FindId(const CStreamInfo *streams, const CUIntVector &sorted, UInt32 id)\n{\n  unsigned left = 0, right = sorted.Size();\n  while (left != right)\n  {\n    const unsigned mid = (left + right) / 2;\n    const unsigned streamIndex = sorted[mid];\n    const UInt32 id2 = streams[streamIndex].Id;\n    if (id == id2)\n      return (int)streamIndex;\n    if (id < id2)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  return -1;\n}\n\nstatic int FindHash(const CStreamInfo *streams, const CUIntVector &sorted, const Byte *hash)\n{\n  unsigned left = 0, right = sorted.Size();\n  while (left != right)\n  {\n    const unsigned mid = (left + right) / 2;\n    const unsigned streamIndex = sorted[mid];\n    const Byte *hash2 = streams[streamIndex].Hash;\n    unsigned i;\n    for (i = 0; i < kHashSize; i++)\n      if (hash[i] != hash2[i])\n        break;\n    if (i == kHashSize)\n      return (int)streamIndex;\n    if (hash[i] < hash2[i])\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  return -1;\n}\n\nstatic int CompareItems(const unsigned *a1, const unsigned *a2, void *param)\n{\n  const CRecordVector<CItem> &items = ((CDatabase *)param)->Items;\n  const CItem &i1 = items[*a1];\n  const CItem &i2 = items[*a2];\n\n  if (i1.IsDir != i2.IsDir)\n    return i1.IsDir ? -1 : 1;\n  if (i1.IsAltStream != i2.IsAltStream)\n    return i1.IsAltStream ? 1 : -1;\n  RINOZ(MyCompare(i1.StreamIndex, i2.StreamIndex))\n  RINOZ(MyCompare(i1.ImageIndex, i2.ImageIndex))\n  return MyCompare(i1.Offset, i2.Offset);\n}\n\n\nHRESULT CDatabase::FillAndCheck(const CObjectVector<CVolume> &volumes)\n{\n  CUIntVector sortedByHash;\n  sortedByHash.Reserve(DataStreams.Size());\n  {\n    CByteBuffer sizesBuf;\n\n    for (unsigned iii = 0; iii < DataStreams.Size();)\n    {\n      {\n        const CResource &r = DataStreams[iii].Resource;\n        if (!r.IsSolid())\n        {\n          sortedByHash.AddInReserved(iii++);\n          continue;\n        }\n      }\n\n      UInt64 solidRunOffset = 0;\n      unsigned k;\n      unsigned numSolidsStart = Solids.Size();\n\n      for (k = iii; k < DataStreams.Size(); k++)\n      {\n        CStreamInfo &si = DataStreams[k];\n        CResource &r = si.Resource;\n\n        if (!r.IsSolid())\n          break;\n        if (!r.KeepSolid && k != iii)\n          break;\n\n        if (r.Flags != NResourceFlags::kSolid)\n          return S_FALSE;\n\n        if (!r.IsSolidBig())\n          continue;\n\n        if (!si.IsEmptyHash())\n          return S_FALSE;\n        if (si.RefCount != 1)\n          return S_FALSE;\n\n        r.SolidIndex = (int)Solids.Size();\n\n        CSolid &ss = Solids.AddNew();\n        ss.StreamIndex = k;\n        ss.SolidOffset = solidRunOffset;\n        {\n          const size_t kSolidHeaderSize = 8 + 4 + 4;\n          Byte header[kSolidHeaderSize];\n\n          if (si.PartNumber >= volumes.Size())\n            return S_FALSE;\n\n          const CVolume &vol = volumes[si.PartNumber];\n          IInStream *inStream = vol.Stream;\n          RINOK(InStream_SeekSet(inStream, r.Offset))\n          RINOK(ReadStream_FALSE(inStream, (Byte *)header, kSolidHeaderSize))\n          \n          ss.UnpackSize = GetUi64(header);\n\n          if (ss.UnpackSize > ((UInt64)1 << 63))\n            return S_FALSE;\n\n          solidRunOffset += ss.UnpackSize;\n          if (solidRunOffset < ss.UnpackSize)\n            return S_FALSE;\n\n          const UInt32 solidChunkSize = GetUi32(header + 8);\n          if (!GetLog_val_min_dest(solidChunkSize, 8, ss.ChunkSizeBits))\n            return S_FALSE;\n          ss.Method = (Int32)GetUi32(header + 12);\n          \n          const UInt64 numChunks64 = (ss.UnpackSize + (((UInt32)1 << ss.ChunkSizeBits) - 1)) >> ss.ChunkSizeBits;\n          const UInt64 sizesBufSize64 = 4 * numChunks64;\n          ss.HeadersSize = kSolidHeaderSize + sizesBufSize64;\n          const size_t sizesBufSize = (size_t)sizesBufSize64;\n          if (sizesBufSize != sizesBufSize64)\n            return E_OUTOFMEMORY;\n          sizesBuf.AllocAtLeast(sizesBufSize);\n          \n          RINOK(ReadStream_FALSE(inStream, sizesBuf, sizesBufSize))\n          \n          const size_t numChunks = (size_t)numChunks64;\n          ss.Chunks.Alloc(numChunks + 1);\n\n          UInt64 offset = 0;\n          \n          size_t c;\n          for (c = 0; c < numChunks; c++)\n          {\n            ss.Chunks[c] = offset;\n            UInt32 packSize = GetUi32((const Byte *)sizesBuf + c * 4);\n            offset += packSize;\n            if (offset < packSize)\n              return S_FALSE;\n          }\n          ss.Chunks[c] = offset;\n\n          if (ss.Chunks[0] != 0)\n            return S_FALSE;\n          if (ss.HeadersSize + offset != r.PackSize)\n            return S_FALSE;\n        }\n      }\n      \n      unsigned solidLim = k;\n\n      for (k = iii; k < solidLim; k++)\n      {\n        CStreamInfo &si = DataStreams[k];\n        CResource &r = si.Resource;\n\n        if (!r.IsSolidSmall())\n          continue;\n\n        if (si.IsEmptyHash())\n          return S_FALSE;\n\n        unsigned solidIndex;\n        {\n          UInt64 offset = r.Offset;\n          for (solidIndex = numSolidsStart;; solidIndex++)\n          {\n            if (solidIndex == Solids.Size())\n              return S_FALSE;\n            UInt64 unpackSize = Solids[solidIndex].UnpackSize;\n            if (offset < unpackSize)\n              break;\n            offset -= unpackSize;\n          }\n        }\n        CSolid &ss = Solids[solidIndex];\n        if (r.Offset < ss.SolidOffset)\n          return S_FALSE;\n        const UInt64 relat = r.Offset - ss.SolidOffset;\n        if (relat > ss.UnpackSize)\n          return S_FALSE;\n        if (r.PackSize > ss.UnpackSize - relat)\n          return S_FALSE;\n        r.SolidIndex = (int)solidIndex;\n        if (ss.FirstSmallStream < 0)\n          ss.FirstSmallStream = (int)k;\n\n        sortedByHash.AddInReserved(k);\n        // ss.NumRefs++;\n      }\n      \n      iii = solidLim;\n    }\n  }\n\n  if (Solids.IsEmpty())\n  {\n    /* We want to check that streams layout is OK.\n       So we need resources sorted by offset.\n       Another code can work with non-sorted streams.\n       NOTE: all WIM programs probably create wim archives with\n         sorted data streams. So it doesn't call Sort() here. */\n       \n    {\n      unsigned i;\n      for (i = 1; i < DataStreams.Size(); i++)\n      {\n        const CStreamInfo &s0 = DataStreams[i - 1];\n        const CStreamInfo &s1 = DataStreams[i];\n        if (s0.PartNumber < s1.PartNumber) continue;\n        if (s0.PartNumber > s1.PartNumber) break;\n        if (s0.Resource.Offset < s1.Resource.Offset) continue;\n        if (s0.Resource.Offset > s1.Resource.Offset) break;\n        if (s0.Resource.PackSize > s1.Resource.PackSize) break;\n      }\n      \n      if (i < DataStreams.Size())\n      {\n        // return E_FAIL;\n        DataStreams.Sort(CompareStreamsByPos, NULL);\n      }\n    }\n\n    for (unsigned i = 1; i < DataStreams.Size(); i++)\n    {\n      const CStreamInfo &s0 = DataStreams[i - 1];\n      const CStreamInfo &s1 = DataStreams[i];\n      if (s0.PartNumber == s1.PartNumber)\n        if (s0.Resource.GetEndLimit() > s1.Resource.Offset)\n          return S_FALSE;\n    }\n  }\n  \n  {\n    {\n      const CStreamInfo *streams = DataStreams.ConstData();\n\n      if (IsOldVersion)\n      {\n        sortedByHash.Sort(CompareIDs, (void *)streams);\n        \n        for (unsigned i = 1; i < sortedByHash.Size(); i++)\n          if (streams[sortedByHash[i - 1]].Id >=\n              streams[sortedByHash[i]].Id)\n            return S_FALSE;\n      }\n      else\n      {\n        sortedByHash.Sort(CompareHashRefs, (void *)streams);\n\n        if (!sortedByHash.IsEmpty())\n        {\n          if (IsEmptySha(streams[sortedByHash[0]].Hash))\n            HeadersError = true;\n          \n          for (unsigned i = 1; i < sortedByHash.Size(); i++)\n            if (memcmp(\n                streams[sortedByHash[i - 1]].Hash,\n                streams[sortedByHash[i]].Hash,\n                kHashSize) >= 0)\n              return S_FALSE;\n        }\n      }\n    }\n    \n    FOR_VECTOR (i, Items)\n    {\n      CItem &item = Items[i];\n      item.StreamIndex = -1;\n      const Byte *hash = Images[item.ImageIndex].Meta + item.Offset;\n      if (IsOldVersion)\n      {\n        if (!item.IsDir)\n        {\n          hash += (item.IsAltStream ? 0x8 : 0x10);\n          UInt32 id = GetUi32(hash);\n          if (id != 0)\n            item.StreamIndex = FindId(DataStreams.ConstData(), sortedByHash, id);\n        }\n      }\n      /*\n      else if (item.IsDir)\n      {\n        // reparse points can have dirs some dir\n      }\n      */\n      else\n      {\n        hash += (item.IsAltStream ? 0x10 : 0x40);\n        if (!IsEmptySha(hash))\n        {\n          item.StreamIndex = FindHash(DataStreams.ConstData(), sortedByHash, hash);\n        }\n      }\n    }\n  }\n  {\n    CUIntVector refCounts;\n    refCounts.ClearAndSetSize(DataStreams.Size());\n    unsigned i;\n\n    for (i = 0; i < DataStreams.Size(); i++)\n    {\n      UInt32 startVal = 0;\n      // const CStreamInfo &s = DataStreams[i];\n      /*\n      if (s.Resource.IsMetadata() && s.PartNumber == 1)\n        startVal = 1;\n      */\n      refCounts[i] = startVal;\n    }\n    \n    for (i = 0; i < Items.Size(); i++)\n    {\n      const int streamIndex = Items[i].StreamIndex;\n      if (streamIndex >= 0)\n        refCounts[streamIndex]++;\n    }\n    \n    for (i = 0; i < DataStreams.Size(); i++)\n    {\n      const CStreamInfo &s = DataStreams[i];\n      if (s.RefCount != refCounts[i]\n          && !s.Resource.IsSolidBig())\n      {\n        /*\n        printf(\"\\ni=%5d  si.Ref=%2d  realRefs=%2d size=%8d offset=%8x id=%4d \",\n          i, s.RefCount, refCounts[i], (unsigned)s.Resource.UnpackSize, (unsigned)s.Resource.Offset, s.Id);\n        */\n        RefCountError = true;\n      }\n      \n      if (refCounts[i] == 0)\n      {\n        const CResource &r = DataStreams[i].Resource;\n        if (!r.IsSolidBig() || Solids[r.SolidIndex].FirstSmallStream < 0)\n        {\n          CItem item;\n          item.Offset = 0;\n          item.StreamIndex = (int)i;\n          item.ImageIndex = -1;\n          Items.Add(item);\n          ThereAreDeletedStreams = true;\n        }\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\nHRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)\n{\n  SortedItems.Clear();\n  VirtualRoots.Clear();\n  IndexOfUserImage = imageIndex;\n  NumExcludededItems = 0;\n  ExludedItem = -1;\n\n  if (Images.Size() != 1 && imageIndex < 0)\n    showImageNumber = true;\n\n  unsigned startItem = 0;\n  unsigned endItem = 0;\n  \n  if (imageIndex < 0)\n  {\n    endItem = Items.Size();\n    if (Images.Size() == 1)\n    {\n      IndexOfUserImage = 0;\n      const CImage &image = Images[0];\n      if (!showImageNumber)\n        NumExcludededItems = image.NumEmptyRootItems;\n    }\n  }\n  else if ((unsigned)imageIndex < Images.Size())\n  {\n    const CImage &image = Images[imageIndex];\n    startItem = image.StartItem;\n    endItem = startItem + image.NumItems;\n    if (!showImageNumber)\n      NumExcludededItems = image.NumEmptyRootItems;\n  }\n  \n  if (NumExcludededItems != 0)\n  {\n    ExludedItem = (int)startItem;\n    startItem += NumExcludededItems;\n  }\n\n  unsigned num = endItem - startItem;\n  SortedItems.ClearAndSetSize(num);\n  unsigned i;\n  for (i = 0; i < num; i++)\n    SortedItems[i] = startItem + i;\n\n  SortedItems.Sort(CompareItems, this);\n  for (i = 0; i < SortedItems.Size(); i++)\n    Items[SortedItems[i]].IndexInSorted = (int)i;\n\n  if (showImageNumber)\n    for (i = 0; i < Images.Size(); i++)\n    {\n      CImage &image = Images[i];\n      if (image.NumEmptyRootItems != 0)\n        continue;\n      image.VirtualRootIndex = (int)VirtualRoots.Size();\n      VirtualRoots.Add(i);\n    }\n\n  return S_OK;\n}\n\n\nstatic void IntVector_SetMinusOne_IfNeed(CIntVector &v, unsigned size)\n{\n  if (v.Size() == size)\n    return;\n  v.ClearAndSetSize(size);\n  int *vals = &v[0];\n  for (unsigned i = 0; i < size; i++)\n    vals[i] = -1;\n}\n\n\nHRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback)\n{\n  ItemToReparse.Clear();\n  ReparseItems.Clear();\n  \n  // we don't know about Reparse field for OLD WIM format\n  if (IsOldVersion)\n    return S_OK;\n\n  CIntVector streamToReparse;\n  CUnpacker unpacker;\n  UInt64 totalPackedPrev = 0;\n\n  FOR_VECTOR(indexInSorted, SortedItems)\n  {\n    // we use sorted items for faster access\n    unsigned itemIndex = SortedItems[indexInSorted];\n    const CItem &item = Items[itemIndex];\n    \n    if (!item.HasMetadata() || item.IsAltStream)\n      continue;\n    \n    if (item.ImageIndex < 0)\n      continue;\n    \n    const Byte *metadata = Images[item.ImageIndex].Meta + item.Offset;\n    \n    const UInt32 attrib = Get32(metadata + 8);\n    if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0)\n      continue;\n    \n    if (item.StreamIndex < 0)\n      continue; // it's ERROR\n    \n    const CStreamInfo &si = DataStreams[item.StreamIndex];\n    if (si.Resource.UnpackSize >= (1 << 16))\n      continue; // reparse data can not be larger than 64 KB\n\n    IntVector_SetMinusOne_IfNeed(streamToReparse, DataStreams.Size());\n    IntVector_SetMinusOne_IfNeed(ItemToReparse, Items.Size());\n    \n    const unsigned offset = 0x58; // we don't know about Reparse field for OLD WIM format\n    UInt32 tag = Get32(metadata + offset);\n    int reparseIndex = streamToReparse[item.StreamIndex];\n    CByteBuffer buf;\n\n    if (openCallback)\n    {\n      if ((unpacker.TotalPacked - totalPackedPrev) >= ((UInt32)1 << 16))\n      {\n        UInt64 numFiles = Items.Size();\n        RINOK(openCallback->SetCompleted(&numFiles, &unpacker.TotalPacked))\n        totalPackedPrev = unpacker.TotalPacked;\n      }\n    }\n\n    if (reparseIndex >= 0)\n    {\n      const CByteBuffer &reparse = ReparseItems[reparseIndex];\n      if (tag == Get32(reparse))\n      {\n        ItemToReparse[itemIndex] = reparseIndex;\n        continue;\n      }\n      buf = reparse;\n      // we support that strange and unusual situation with different tags and same reparse data.\n    }\n    else\n    {\n      /*\n      if (si.PartNumber >= volumes.Size())\n        continue;\n      */\n      const CVolume &vol = volumes[si.PartNumber];\n      /*\n      if (!vol.Stream)\n        continue;\n      */\n      \n      Byte digest[kHashSize];\n      HRESULT res = unpacker.UnpackData(vol.Stream, si.Resource, vol.Header, this, buf, digest);\n\n      if (res == S_FALSE)\n        continue;\n\n      RINOK(res)\n      \n      if (memcmp(digest, si.Hash, kHashSize) != 0\n        // && !(h.IsOldVersion() && IsEmptySha(si.Hash))\n        )\n      {\n        // setErrorStatus;\n        continue;\n      }\n    }\n    \n    CByteBuffer &reparse = ReparseItems.AddNew();\n    reparse.Alloc(8 + buf.Size());\n    Byte *dest = (Byte *)reparse;\n    SetUi32(dest, tag)\n    SetUi32(dest + 4, (UInt32)buf.Size())\n    if (buf.Size() != 0)\n      memcpy(dest + 8, buf, buf.Size());\n    ItemToReparse[itemIndex] = (int)ReparseItems.Size() - 1;\n  }\n\n  return S_OK;\n}\n\n\n\nstatic bool ParseNumber64(const AString &s, UInt64 &res)\n{\n  const char *end;\n  if (s.IsPrefixedBy(\"0x\"))\n  {\n    if (s.Len() == 2)\n      return false;\n    res = ConvertHexStringToUInt64(s.Ptr(2), &end);\n  }\n  else\n  {\n    if (s.IsEmpty())\n      return false;\n    res = ConvertStringToUInt64(s, &end);\n  }\n  return *end == 0;\n}\n\n\nstatic bool ParseNumber32(const AString &s, UInt32 &res)\n{\n  UInt64 res64;\n  if (!ParseNumber64(s, res64) || res64 >= ((UInt64)1 << 32))\n    return false;\n  res = (UInt32)res64;\n  return true;\n}\n\n\nstatic bool ParseTime(const CXmlItem &item, FILETIME &ft, const char *tag)\n{\n  const CXmlItem *timeItem = item.FindSubTag_GetPtr(tag);\n  if (timeItem)\n  {\n    UInt32 low = 0, high = 0;\n    if (ParseNumber32(timeItem->GetSubStringForTag(\"LOWPART\"), low) &&\n        ParseNumber32(timeItem->GetSubStringForTag(\"HIGHPART\"), high))\n    {\n      ft.dwLowDateTime = low;\n      ft.dwHighDateTime = high;\n      return true;\n    }\n  }\n  return false;\n}\n\n\nvoid CImageInfo::Parse(const CXmlItem &item)\n{\n  CTimeDefined = ParseTime(item, CTime, \"CREATIONTIME\");\n  MTimeDefined = ParseTime(item, MTime, \"LASTMODIFICATIONTIME\");\n  NameDefined = true;\n  ConvertUTF8ToUnicode(item.GetSubStringForTag(\"NAME\"), Name);\n\n  ParseNumber64(item.GetSubStringForTag(\"DIRCOUNT\"), DirCount);\n  ParseNumber64(item.GetSubStringForTag(\"FILECOUNT\"), FileCount);\n  IndexDefined = ParseNumber32(item.GetPropVal(\"INDEX\"), Index);\n}\n\nvoid CWimXml::ToUnicode(UString &s)\n{\n  size_t size = Data.Size();\n  if (size < 2 || (size & 1) != 0 || size > (1 << 24))\n    return;\n  const Byte *p = Data;\n  if (Get16(p) != 0xFEFF)\n    return;\n  wchar_t *chars = s.GetBuf((unsigned)(size / 2));\n  for (size_t i = 2; i < size; i += 2)\n  {\n    wchar_t c = Get16(p + i);\n    if (c == 0)\n      break;\n    *chars++ = c;\n  }\n  *chars = 0;\n  s.ReleaseBuf_SetLen((unsigned)(chars - (const wchar_t *)s));\n}\n\n\nbool CWimXml::Parse()\n{\n  IsEncrypted = false;\n  AString utf;\n  {\n    UString s;\n    ToUnicode(s);\n    // if (!ConvertUnicodeToUTF8(s, utf)) return false;\n    ConvertUnicodeToUTF8(s, utf);\n  }\n\n  if (!Xml.Parse(utf))\n    return false;\n  if (!Xml.Root.Name.IsEqualTo(\"WIM\"))\n    return false;\n\n  FOR_VECTOR (i, Xml.Root.SubItems)\n  {\n    const CXmlItem &item = Xml.Root.SubItems[i];\n    \n    if (item.IsTagged(\"IMAGE\"))\n    {\n      CImageInfo imageInfo;\n      imageInfo.Parse(item);\n      if (!imageInfo.IndexDefined)\n        return false;\n\n      if (imageInfo.Index != (UInt32)Images.Size() + 1)\n      {\n        // old wim (1.09) uses zero based image index\n        if (imageInfo.Index != (UInt32)Images.Size())\n          return false;\n      }\n\n      imageInfo.ItemIndexInXml = (int)i;\n      Images.Add(imageInfo);\n    }\n\n    if (item.IsTagged(\"ESD\"))\n    {\n      FOR_VECTOR (k, item.SubItems)\n      {\n        const CXmlItem &item2 = item.SubItems[k];\n        if (item2.IsTagged(\"ENCRYPTED\"))\n          IsEncrypted = true;\n      }\n    }\n  }\n\n  return true;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Wim/WimIn.h",
    "content": "﻿// Archive/WimIn.h\n\n#ifndef ZIP7_INC_ARCHIVE_WIM_IN_H\n#define ZIP7_INC_ARCHIVE_WIM_IN_H\n\n#include \"../../../../C/Alloc.h\"\n\n#include \"../../../Common/AutoPtr.h\"\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyXml.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n#include \"../../Compress/LzmsDecoder.h\"\n#include \"../../Compress/LzxDecoder.h\"\n\n#include \"../IArchive.h\"\n\nnamespace NArchive {\nnamespace NWim {\n\n/*\nWIM versions:\nhexVer : headerSize : ver\n : 1.07.01 - 1.08.01 : Longhorn.4001-4015 - another header, no signature, CAB compression\n10900 : 60 : 1.09 : Longhorn.4029-4039 (2003)\n10A00 : 60 : 1.10 : Longhorn.4083 (2004) image starting from 1\n10B00 : ?? : 1.11 : ??\n10C00 : 74 : 1.12 : Longhorn.4093 - VistaBeta1.5112 (2005) - (Multi-Part, SHA1)\n10D00 : D0 : 1.13 : VistaBeta2 - Win10, (NumImages, BootIndex, IntegrityResource)\n00E00 : D0 : 0.14 : LZMS, solid, esd, dism\n*/\n\nconst unsigned kDirRecordSizeOld = 62;\nconst unsigned kDirRecordSize = 102;\n\n/*\n  There is error in WIM specification about dwReparseTag, dwReparseReserved and liHardLink fields.\n\n  Correct DIRENTRY structure:\n  {\n    hex offset\n     0    UInt64  Len;\n     8    UInt32  Attrib;\n     C    UInt32  SecurityId;\n    \n    10    UInt64  SubdirOffset; // = 0 for files\n\n    18    UInt64  unused1; // = 0?\n    20    UInt64  unused2; // = 0?\n    \n    28    UInt64  CTime;\n    30    UInt64  ATime;\n    38    UInt64  MTime;\n    \n    40    Byte    Sha1[20];\n    \n    54    UInt32  Unknown1; // is it 0 always?\n\n       \n    union\n    {\n    58    UInt64  NtNodeId;\n        {\n    58    UInt32  ReparseTag;\n    5C    UInt32  ReparseFlags; // is it 0 always? Check with new imagex.\n        }\n    }\n\n    60    UInt16  Streams;\n    \n    62    UInt16  ShortNameLen;\n    64    UInt16  FileNameLen;\n    \n    66    UInt16  Name[];\n          UInt16  ShortName[];\n  }\n\n  // DIRENTRY for WIM_VERSION <= 1.10\n  DIRENTRY_OLD structure:\n  {\n    hex offset\n     0    UInt64  Len;\n     8    UInt32  Attrib;\n     C    UInt32  SecurityId;\n\n    union\n    {\n    10    UInt64  SubdirOffset; //\n\n    10    UInt32  OldWimFileId; // used for files in old WIMs\n    14    UInt32  OldWimFileId_Reserved; // = 0\n    }\n\n    18    UInt64  CTime;\n    20    UInt64  ATime;\n    28    UInt64  MTime;\n    \n    30    UInt64  Unknown; // NtNodeId ?\n\n    38    UInt16  Streams;\n    3A    UInt16  ShortNameLen;\n    3C    UInt16  FileNameLen;\n    3E    UInt16  FileName[];\n          UInt16  ShortName[];\n  }\n\n  ALT_STREAM structure:\n  {\n    hex offset\n     0    UInt64  Len;\n     8    UInt64  Unused;\n    10    Byte    Sha1[20];\n    24    UInt16  FileNameLen;\n    26    UInt16  FileName[];\n  }\n\n  ALT_STREAM_OLD structure:\n  {\n    hex offset\n     0    UInt64  Len;\n     8    UInt64  StreamId; // 32-bit value\n    10    UInt16  FileNameLen;\n    12    UInt16  FileName[];\n  }\n\n  If item is file (not Directory) and there are alternative streams,\n  there is additional ALT_STREAM item of main \"unnamed\" stream in Streams array.\n\n*/\n\n\nnamespace NResourceFlags\n{\n  // const Byte kFree = 1 << 0;\n  const Byte kMetadata = 1 << 1;\n  const Byte kCompressed = 1 << 2;\n  // const Byte kSpanned = 1 << 3;\n  const Byte kSolid = 1 << 4;\n}\n\nconst UInt64 k_SolidBig_Resource_Marker = (UInt64)1 << 32;\n\nstruct CResource\n{\n  UInt64 PackSize;\n  UInt64 Offset;\n  UInt64 UnpackSize;\n  Byte Flags;\n  bool KeepSolid;\n  int SolidIndex;\n\n  void Clear()\n  {\n    PackSize = 0;\n    Offset = 0;\n    UnpackSize = 0;\n    Flags = 0;\n    KeepSolid = false;\n    SolidIndex = -1;\n  }\n\n  UInt64 GetEndLimit() const { return Offset + PackSize; }\n  void Parse(const Byte *p);\n  void ParseAndUpdatePhySize(const Byte *p, UInt64 &phySize)\n  {\n    Parse(p);\n    UInt64 v = GetEndLimit();\n    if (phySize < v)\n      phySize = v;\n  }\n\n  void WriteTo(Byte *p) const;\n\n  bool IsMetadata() const { return (Flags & NResourceFlags::kMetadata) != 0; }\n  bool IsCompressed() const { return (Flags & NResourceFlags::kCompressed) != 0; }\n  bool IsSolid() const { return (Flags & NResourceFlags::kSolid) != 0; }\n  bool IsSolidBig() const { return IsSolid() && UnpackSize == k_SolidBig_Resource_Marker; }\n  bool IsSolidSmall() const { return IsSolid() && UnpackSize == 0; }\n\n  bool IsEmpty() const { return (UnpackSize == 0); }\n};\n\n\nstruct CSolid\n{\n  unsigned StreamIndex;\n  // unsigned NumRefs;\n  int FirstSmallStream;\n  \n  UInt64 SolidOffset;\n  \n  UInt64 UnpackSize;\n  int Method;\n  unsigned ChunkSizeBits;\n\n  UInt64 HeadersSize;\n  // size_t NumChunks;\n  CObjArray<UInt64> Chunks; // [NumChunks + 1] (start offset)\n\n  UInt64 GetChunkPackSize(size_t chunkIndex) const { return Chunks[chunkIndex + 1] - Chunks[chunkIndex]; }\n\n  CSolid():\n      FirstSmallStream(-1),\n      // NumRefs(0),\n      Method(-1)\n      {}\n};\n\n\nnamespace NHeaderFlags\n{\n  const UInt32 kCompression  = 1 << 1;\n  const UInt32 kReadOnly     = 1 << 2;\n  const UInt32 kSpanned      = 1 << 3;\n  const UInt32 kResourceOnly = 1 << 4;\n  const UInt32 kMetadataOnly = 1 << 5;\n  const UInt32 kWriteInProgress = 1 << 6;\n  const UInt32 kReparsePointFixup = 1 << 7;\n  \n  const UInt32 kXPRESS       = (UInt32)1 << 17;\n  const UInt32 kLZX          = (UInt32)1 << 18;\n  const UInt32 kLZMS         = (UInt32)1 << 19;\n  const UInt32 kXPRESS2      = (UInt32)1 << 21; // XPRESS with nonstandard chunk size ?\n\n  const UInt32 kMethodMask   = 0xFFFE0000;\n}\n\n\nnamespace NMethod\n{\n  const UInt32 kXPRESS = 1;\n  const UInt32 kLZX    = 2;\n  const UInt32 kLZMS   = 3;\n}\n\n\nconst UInt32 k_Version_NonSolid = 0x10D00;\nconst UInt32 k_Version_Solid = 0xE00;\n\nconst unsigned kHeaderSizeMax = 0xD0;\nconst unsigned kSignatureSize = 8;\nextern const Byte kSignature[kSignatureSize];\n\nconst unsigned kChunkSizeBits = 15;\nconst UInt32 kChunkSize = (UInt32)1 << kChunkSizeBits;\n\n\nstruct CHeader\n{\n  UInt32 Version;\n  UInt32 Flags;\n  UInt32 ChunkSize;\n  unsigned ChunkSizeBits;\n  Byte Guid[16];\n  UInt16 PartNumber;\n  UInt16 NumParts;\n  UInt32 NumImages;\n  UInt32 BootIndex;\n\n  bool _isOldVersion; // 1.10-\n  bool _isNewVersion; // 1.13+ or 0.14\n\n  CResource OffsetResource;\n  CResource XmlResource;\n  CResource MetadataResource;\n  CResource IntegrityResource;\n\n  void SetDefaultFields(bool useLZX);\n\n  void WriteTo(Byte *p) const;\n  HRESULT Parse(const Byte *p, UInt64 &phySize);\n  \n  bool IsCompressed() const { return (Flags & NHeaderFlags::kCompression) != 0; }\n  \n  bool IsSupported() const\n  {\n    return (!IsCompressed()\n        || (Flags & NHeaderFlags::kLZX) != 0\n        || (Flags & NHeaderFlags::kXPRESS) != 0\n        || (Flags & NHeaderFlags::kLZMS) != 0\n        || (Flags & NHeaderFlags::kXPRESS2) != 0);\n  }\n  \n  unsigned GetMethod() const\n  {\n    if (!IsCompressed())\n      return 0;\n    UInt32 mask = (Flags & NHeaderFlags::kMethodMask);\n    if (mask == 0) return 0;\n    if (mask == NHeaderFlags::kXPRESS) return NMethod::kXPRESS;\n    if (mask == NHeaderFlags::kLZX) return NMethod::kLZX;\n    if (mask == NHeaderFlags::kLZMS) return NMethod::kLZMS;\n    if (mask == NHeaderFlags::kXPRESS2) return NMethod::kXPRESS;\n    return mask;\n  }\n\n  bool IsOldVersion() const { return _isOldVersion; }\n  bool IsNewVersion() const { return _isNewVersion; }\n  bool IsSolidVersion() const { return (Version == k_Version_Solid); }\n\n  bool AreFromOnArchive(const CHeader &h)\n  {\n    return (memcmp(Guid, h.Guid, sizeof(Guid)) == 0) && (h.NumParts == NumParts);\n  }\n};\n\n\nconst unsigned kHashSize = 20;\n\ninline bool IsEmptySha(const Byte *data)\n{\n  for (unsigned i = 0; i < kHashSize; i++)\n    if (data[i] != 0)\n      return false;\n  return true;\n}\n\nconst unsigned kStreamInfoSize = 24 + 2 + 4 + kHashSize;\n\nstruct CStreamInfo\n{\n  CResource Resource;\n  UInt16 PartNumber;      // for NEW WIM format, we set it to 1 for OLD WIM format\n  UInt32 RefCount;\n  UInt32 Id;              // for OLD WIM format\n  Byte Hash[kHashSize];\n\n  bool IsEmptyHash() const { return IsEmptySha(Hash); }\n  \n  void WriteTo(Byte *p) const;\n};\n\n\nstruct CItem\n{\n  size_t Offset;\n  int IndexInSorted;\n  int StreamIndex;\n  int Parent;\n  int ImageIndex; // -1 means that file is unreferenced in Images (deleted item?)\n  bool IsDir;\n  bool IsAltStream;\n\n  bool HasMetadata() const { return ImageIndex >= 0; }\n\n  CItem():\n    IndexInSorted(-1),\n    StreamIndex(-1),\n    Parent(-1),\n    IsDir(false),\n    IsAltStream(false)\n    {}\n};\n\nstruct CImage\n{\n  CByteBuffer Meta;\n  CRecordVector<UInt32> SecurOffsets;\n  unsigned StartItem;\n  unsigned NumItems;\n  unsigned NumEmptyRootItems;\n  int VirtualRootIndex; // index in CDatabase::VirtualRoots[]\n  UString RootName;\n  CByteBuffer RootNameBuf;\n\n  CImage(): VirtualRootIndex(-1) {}\n};\n\n\nstruct CImageInfo\n{\n  bool CTimeDefined;\n  bool MTimeDefined;\n  bool NameDefined;\n  bool IndexDefined;\n  \n  FILETIME CTime;\n  FILETIME MTime;\n  UString Name;\n\n  UInt64 DirCount;\n  UInt64 FileCount;\n  UInt32 Index;\n\n  int ItemIndexInXml;\n\n  UInt64 GetTotalFilesAndDirs() const { return DirCount + FileCount; }\n  \n  CImageInfo(): CTimeDefined(false), MTimeDefined(false), NameDefined(false),\n      IndexDefined(false), ItemIndexInXml(-1) {}\n  void Parse(const CXmlItem &item);\n};\n\n\nstruct CWimXml\n{\n  CByteBuffer Data;\n  CXml Xml;\n\n  UInt16 VolIndex;\n  CObjectVector<CImageInfo> Images;\n\n  UString FileName;\n  bool IsEncrypted;\n\n  UInt64 GetTotalFilesAndDirs() const\n  {\n    UInt64 sum = 0;\n    FOR_VECTOR (i, Images)\n      sum += Images[i].GetTotalFilesAndDirs();\n    return sum;\n  }\n\n  void ToUnicode(UString &s);\n  bool Parse();\n\n  CWimXml(): IsEncrypted(false) {}\n};\n\n\nstruct CVolume\n{\n  CHeader Header;\n  CMyComPtr<IInStream> Stream;\n};\n\n\nclass CDatabase\n{\n  Byte *DirData;\n  size_t DirSize;\n  size_t DirProcessed;\n  size_t DirStartOffset;\n  IArchiveOpenCallback *OpenCallback;\n\n  HRESULT ParseDirItem(size_t pos, int parent);\n  HRESULT ParseImageDirs(CByteBuffer &buf, int parent);\n\npublic:\n  CRecordVector<CStreamInfo> DataStreams;\n  CRecordVector<CStreamInfo> MetaStreams;\n\n  CObjectVector<CSolid> Solids;\n  \n  CRecordVector<CItem> Items;\n  CObjectVector<CByteBuffer> ReparseItems;\n  CIntVector ItemToReparse; // from index_in_Items to index_in_ReparseItems\n                            // -1 means no reparse;\n  \n  CObjectVector<CImage> Images;\n  \n  bool IsOldVersion9;\n  bool IsOldVersion;\n  bool ThereAreDeletedStreams;\n  bool ThereAreAltStreams;\n  bool RefCountError;\n  bool HeadersError;\n\n  unsigned GetStartImageIndex() const { return IsOldVersion9 ? 0 : 1; }\n  unsigned GetDirAlignMask() const { return IsOldVersion9 ? 3 : 7; }\n  \n  // User Items can contain all images or just one image from all.\n  CUIntVector SortedItems;\n  int IndexOfUserImage;    // -1 : if more than one images was filled to Sorted Items\n  \n  unsigned NumExcludededItems;\n  int ExludedItem;          // -1 : if there are no exclude items\n  CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives\n\n  bool ThereIsError() const { return RefCountError || HeadersError; }\n\n  unsigned GetNumUserItemsInImage(unsigned imageIndex) const\n  {\n    if (IndexOfUserImage >= 0 && imageIndex != (unsigned)IndexOfUserImage)\n      return 0;\n    if (imageIndex >= Images.Size())\n      return 0;\n    return Images[imageIndex].NumItems - NumExcludededItems;\n  }\n\n  bool ItemHasStream(const CItem &item) const;\n\n  UInt64 Get_UnpackSize_of_Resource(const CResource &r) const\n  {\n    if (!r.IsSolid())\n      return r.UnpackSize;\n    if (r.IsSolidSmall())\n      return r.PackSize;\n    if (r.IsSolidBig() && r.SolidIndex >= 0)\n      return Solids[(unsigned)r.SolidIndex].UnpackSize;\n    return 0;\n  }\n\n  UInt64 Get_PackSize_of_Resource(unsigned streamIndex) const\n  {\n    const CResource &r = DataStreams[streamIndex].Resource;\n    if (!r.IsSolidSmall())\n      return r.PackSize;\n    if (r.SolidIndex >= 0)\n    {\n      const CSolid &ss = Solids[(unsigned)r.SolidIndex];\n      if (ss.FirstSmallStream == (int)streamIndex)\n        return DataStreams[ss.StreamIndex].Resource.PackSize;\n    }\n    return 0;\n  }\n\n  UInt64 GetUnpackSize() const\n  {\n    UInt64 res = 0;\n    FOR_VECTOR (i, DataStreams)\n      res += DataStreams[i].Resource.UnpackSize;\n    return res;\n  }\n\n  UInt64 GetPackSize() const\n  {\n    UInt64 res = 0;\n    FOR_VECTOR (i, DataStreams)\n      res += DataStreams[i].Resource.PackSize;\n    return res;\n  }\n\n  void Clear()\n  {\n    DataStreams.Clear();\n    MetaStreams.Clear();\n    Solids.Clear();\n    \n    Items.Clear();\n    ReparseItems.Clear();\n    ItemToReparse.Clear();\n\n    SortedItems.Clear();\n    \n    Images.Clear();\n    VirtualRoots.Clear();\n\n    IsOldVersion = false;\n    ThereAreDeletedStreams = false;\n    ThereAreAltStreams = false;\n    RefCountError = false;\n    HeadersError = false;\n  }\n\n  CDatabase():\n    RefCountError(false),\n    HeadersError(false)\n    {}\n\n  void GetShortName(unsigned index, NWindows::NCOM::CPropVariant &res) const;\n  void GetItemName(unsigned index1, NWindows::NCOM::CPropVariant &res) const;\n  void GetItemPath(unsigned index, bool showImageNumber, NWindows::NCOM::CPropVariant &res) const;\n\n  HRESULT OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml);\n  HRESULT Open(IInStream *inStream, const CHeader &h, unsigned numItemsReserve, IArchiveOpenCallback *openCallback);\n  HRESULT FillAndCheck(const CObjectVector<CVolume> &volumes);\n\n  /*\n    imageIndex showImageNumber NumImages\n         *        true           *       Show Image_Number\n        -1           *          >1       Show Image_Number\n        -1        false          1       Don't show Image_Number\n         N        false          *       Don't show Image_Number\n  */\n  HRESULT GenerateSortedItems(int imageIndex, bool showImageNumber);\n\n  HRESULT ExtractReparseStreams(const CObjectVector<CVolume> &volumes, IArchiveOpenCallback *openCallback);\n};\n\nHRESULT ReadHeader(IInStream *inStream, CHeader &header, UInt64 &phySize);\n\n\nstruct CMidBuf\n{\n  Byte *Data;\n  size_t _size;\n\n  CMidBuf(): Data(NULL), _size(0) {}\n\n  void EnsureCapacity(size_t size)\n  {\n    if (size > _size)\n    {\n      ::z7_AlignedFree(Data);\n      _size = 0;\n      Data = (Byte *)::z7_AlignedAlloc(size);\n      if (Data)\n        _size = size;\n    }\n  }\n\n  ~CMidBuf() { ::z7_AlignedFree(Data); }\n};\n\n\nclass CUnpacker\n{\n  CMyComPtr2<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyUniquePtr<NCompress::NLzx::CDecoder> lzxDecoder;\n  CMyUniquePtr<NCompress::NLzms::CDecoder> lzmsDecoder;\n\n  CByteBuffer sizesBuf;\n\n  CMidBuf packBuf;\n  CMidBuf unpackBuf;\n\n  // solid resource\n  int _solidIndex;\n  size_t _unpackedChunkIndex;\n\n  HRESULT UnpackChunk(\n      ISequentialInStream *inStream,\n      unsigned method, unsigned chunkSizeBits,\n      size_t inSize, size_t outSize,\n      ISequentialOutStream *outStream);\n\n  HRESULT Unpack2(\n      IInStream *inStream,\n      const CResource &res,\n      const CHeader &header,\n      const CDatabase *db,\n      ISequentialOutStream *outStream,\n      ICompressProgressInfo *progress);\n\npublic:\n  UInt64 TotalPacked;\n\n  CUnpacker():\n      lzmsDecoder(NULL),\n      _solidIndex(-1),\n      _unpackedChunkIndex(0),\n      TotalPacked(0)\n      {}\n\n  HRESULT Unpack(\n      IInStream *inStream,\n      const CResource &res,\n      const CHeader &header,\n      const CDatabase *db,\n      ISequentialOutStream *outStream,\n      ICompressProgressInfo *progress,\n      Byte *digest);\n\n  HRESULT UnpackData(IInStream *inStream,\n      const CResource &resource, const CHeader &header,\n      const CDatabase *db,\n      CByteBuffer &buf, Byte *digest);\n};\n\n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Wim/WimRegister.cpp",
    "content": "﻿// WimRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/RegisterArc.h\"\n\n#include \"WimHandler.h\"\n\nnamespace NArchive {\nnamespace NWim {\n\nREGISTER_ARC_IO(\n    \"wim\", \"wim swm esd ppkg\", NULL, 0xE6\n  , kSignature, 0\n  , NArcInfoFlags::kAltStreams\n  | NArcInfoFlags::kNtSecure\n  | NArcInfoFlags::kSymLinks\n  | NArcInfoFlags::kHardLinks\n  | NArcInfoFlags::kCTime\n  // | NArcInfoFlags::kCTime_Default\n  | NArcInfoFlags::kATime\n  // | NArcInfoFlags::kATime_Default\n  | NArcInfoFlags::kMTime\n  | NArcInfoFlags::kMTime_Default\n  , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kWindows)\n  | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kWindows)\n  , NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/XarHandler.cpp",
    "content": "﻿// XarHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Sha256.h\"\n#include \"../../../C/Sha512.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyLinux.h\"\n#include \"../../Common/MyXml.h\"\n#include \"../../Common/StringToInt.h\"\n#include \"../../Common/UTFConvert.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/TimeUtils.h\"\n\n#include \"../Common/LimitedStreams.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamObjects.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/BZip2Decoder.h\"\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/ZlibDecoder.h\"\n\n#include \"Common/OutStreamWithSha1.h\"\n\nusing namespace NWindows;\n\n#define XAR_SHOW_RAW\n\n#define Get16(p) GetBe16(p)\n#define Get32(p) GetBe32(p)\n#define Get64(p) GetBe64(p)\n\nnamespace NArchive {\nnamespace NXar {\n\nZ7_CLASS_IMP_NOQIB_1(\n  CInStreamWithSha256\n  , ISequentialInStream\n)\n  bool _sha512Mode;\n  CMyComPtr<ISequentialInStream> _stream;\n  CAlignedBuffer1 _sha256;\n  CAlignedBuffer1 _sha512;\n  UInt64 _size;\n\n  CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; }\n  CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; }\npublic:\n  CInStreamWithSha256():\n      _sha256(sizeof(CSha256)),\n      _sha512(sizeof(CSha512))\n      {}\n  void SetStream(ISequentialInStream *stream) { _stream = stream;  }\n  void Init(bool sha512Mode)\n  {\n    _sha512Mode = sha512Mode;\n    _size = 0;\n    if (sha512Mode)\n      Sha512_Init(Sha512(), SHA512_DIGEST_SIZE);\n    else\n      Sha256_Init(Sha256());\n  }\n  void ReleaseStream() { _stream.Release(); }\n  UInt64 GetSize() const { return _size; }\n  void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); }\n  void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); }\n};\n\nZ7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize;\n  const HRESULT result = _stream->Read(data, size, &realProcessedSize);\n  _size += realProcessedSize;\n  if (_sha512Mode)\n    Sha512_Update(Sha512(), (const Byte *)data, realProcessedSize);\n  else\n    Sha256_Update(Sha256(), (const Byte *)data, realProcessedSize);\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return result;\n}\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithSha256\n  , ISequentialOutStream\n)\n  bool _sha512Mode;\n  CMyComPtr<ISequentialOutStream> _stream;\n  CAlignedBuffer1 _sha256;\n  CAlignedBuffer1 _sha512;\n  UInt64 _size;\n\n  CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; }\n  CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; }\npublic:\n  COutStreamWithSha256():\n      _sha256(sizeof(CSha256)),\n      _sha512(sizeof(CSha512))\n      {}\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init(bool sha512Mode)\n  {\n    _sha512Mode = sha512Mode;\n    _size = 0;\n    if (sha512Mode)\n      Sha512_Init(Sha512(), SHA512_DIGEST_SIZE);\n    else\n      Sha256_Init(Sha256());\n  }\n  UInt64 GetSize() const { return _size; }\n  void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); }\n  void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); }\n};\n\nZ7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  // if (_calculate)\n  if (_sha512Mode)\n    Sha512_Update(Sha512(), (const Byte *)data, size);\n  else\n    Sha256_Update(Sha256(), (const Byte *)data, size);\n  _size += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\n// we limit supported xml sizes:\n// ((size_t)1 << (sizeof(size_t) / 2 + 28)) - (1u << 14);\nstatic const size_t kXmlSizeMax = ((size_t)1 << 30) - (1u << 14);\nstatic const size_t kXmlPackSizeMax = kXmlSizeMax;\n\n#define XAR_CKSUM_NONE    0\n#define XAR_CKSUM_SHA1    1\n#define XAR_CKSUM_MD5     2\n#define XAR_CKSUM_SHA256  3\n#define XAR_CKSUM_SHA512  4\n// #define XAR_CKSUM_OTHER   3\n// fork version of xar can use (3) as special case,\n// where name of hash is stored as string at the end of header\n// we do not support such hash still.\n\nstatic const char * const k_ChecksumNames[] =\n{\n    \"NONE\"\n  , \"SHA1\"\n  , \"MD5\"\n  , \"SHA256\"\n  , \"SHA512\"\n};\n\nstatic unsigned GetHashSize(int algo)\n{\n  if (algo <= XAR_CKSUM_NONE || algo > XAR_CKSUM_SHA512)\n    return 0;\n  if (algo == XAR_CKSUM_SHA1)\n    return SHA1_DIGEST_SIZE;\n  return (16u >> XAR_CKSUM_MD5) << algo;\n}\n\n#define METHOD_NAME_ZLIB  \"zlib\"\n\nstatic int Find_ChecksumId_for_Name(const AString &style)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ChecksumNames); i++)\n  {\n    // old xars used upper case in \"style\"\n    // new xars use  lower case in \"style\"\n    if (style.IsEqualTo_Ascii_NoCase(k_ChecksumNames[i]))\n      return (int)i;\n  }\n  return -1;\n}\n\n\nstruct CCheckSum\n{\n  int AlgoNumber;\n  bool Error;\n  CByteBuffer Data;\n  AString Style;\n  \n  CCheckSum(): AlgoNumber(-1), Error(false) {}\n  void AddNameToString(AString &s) const;\n};\n\nvoid CCheckSum::AddNameToString(AString &s) const\n{\n  if (Style.IsEmpty())\n    s.Add_OptSpaced(\"NO-CHECKSUM\");\n  else\n  {\n    s.Add_OptSpaced(Style);\n    if (Error)\n      s += \"-ERROR\";\n  }\n}\n\n\nstruct CFile\n{\n  bool IsDir;\n  bool Is_SymLink;\n  bool HasData;\n  bool Mode_Defined;\n  bool INode_Defined;\n  bool UserId_Defined;\n  bool GroupId_Defined;\n  // bool Device_Defined;\n  bool Id_Defined;\n\n  int Parent;\n  UInt32 Mode;\n\n  UInt64 Size;\n  UInt64 PackSize;\n  UInt64 Offset;\n  UInt64 MTime;\n  UInt64 CTime;\n  UInt64 ATime;\n  UInt64 INode;\n  UInt64 UserId;\n  UInt64 GroupId;\n  // UInt64 Device;\n\n  AString Name;\n  AString Method;\n  AString User;\n  AString Group;\n  // AString Id;\n  AString Type;\n  AString Link;\n  // AString LinkType;\n  // AString LinkFrom;\n  \n  UInt64 Id;\n  CCheckSum extracted_checksum;\n  CCheckSum archived_checksum;\n\n  CFile(int parent):\n      IsDir(false),\n      Is_SymLink(false),\n      HasData(false),\n      Mode_Defined(false),\n      INode_Defined(false),\n      UserId_Defined(false),\n      GroupId_Defined(false),\n      // Device_Defined(false),\n      Id_Defined(false),\n      Parent(parent),\n      Mode(0),\n      Size(0), PackSize(0), Offset(0),\n      MTime(0), CTime(0), ATime(0),\n      INode(0)\n      {}\n\n  bool IsCopyMethod() const\n  {\n    return Method.IsEmpty() || Method.IsEqualTo(\"octet-stream\");\n  }\n\n  void UpdateTotalPackSize(UInt64 &totalSize) const\n  {\n    const UInt64 t = Offset + PackSize;\n    if (t >= Offset)\n    if (totalSize < t)\n        totalSize = t;\n  }\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_2(\n    IArchiveGetRawProps,\n    IInArchiveGetStream\n)\n  bool _is_pkg;\n  bool _toc_CrcError;\n  CObjectVector<CFile> _files;\n  CMyComPtr<IInStream> _inStream;\n  UInt64 _dataStartPos;\n  UInt64 _phySize;\n  CAlignedBuffer _xmlBuf;\n  size_t _xmlLen;\n  // UInt64 CreationTime;\n  AString CreationTime_String;\n  UInt32 _checkSumAlgo;\n  Int32 _mainSubfile;\n\n  HRESULT Open2(IInStream *stream);\n};\n\n\nstatic const Byte kArcProps[] =\n{\n  kpidSubType,\n  // kpidHeadersSize,\n  kpidMethod,\n  kpidCTime\n};\n\n// #define kpidLinkType 250\n// #define kpidLinkFrom 251\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidPosixAttrib,\n  kpidType,\n  kpidUser,\n  kpidGroup,\n  kpidUserId,\n  kpidGroupId,\n  kpidINode,\n  // kpidDeviceMajor,\n  // kpidDeviceMinor,\n  kpidSymLink,\n  // kpidLinkType,\n  // kpidLinkFrom,\n  kpidMethod,\n  kpidId,\n  kpidOffset\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res)\n{\n  const AString s (item.GetSubStringForTag(name));\n  if (s.IsEmpty())\n    return false;\n  const char *end;\n  res = ConvertStringToUInt64(s, &end);\n  return *end == 0;\n}\n\n\n#define PARSE_NUM(_num_, _dest_) \\\n    { const char *end; _dest_ = ConvertStringToUInt32(p, &end); \\\n    if ((unsigned)(end - p) != _num_) return 0; \\\n    p += _num_ + 1; }\n\nstatic UInt64 ParseTime(const CXmlItem &item, const char *name /* , bool z_isRequired */ )\n{\n  const AString s (item.GetSubStringForTag(name));\n  if (s.Len() < 20 /* (z_isRequired ? 20u : 19u) */)\n    return 0;\n  const char *p = s;\n  if (p[ 4] != '-' ||\n      p[ 7] != '-' ||\n      p[10] != 'T' ||\n      p[13] != ':' ||\n      p[16] != ':')\n    return 0;\n  // if (z_isRequired)\n  if (p[19] != 'Z')\n    return 0;\n  UInt32 year, month, day, hour, min, sec;\n  PARSE_NUM(4, year)\n  PARSE_NUM(2, month)\n  PARSE_NUM(2, day)\n  PARSE_NUM(2, hour)\n  PARSE_NUM(2, min)\n  PARSE_NUM(2, sec)\n  UInt64 numSecs;\n  if (!NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs))\n    return 0;\n  return numSecs * 10000000;\n}\n\n\nstatic void ParseChecksum(const CXmlItem &item, const char *name, CCheckSum &checksum)\n{\n  const CXmlItem *checkItem = item.FindSubTag_GetPtr(name);\n  if (!checkItem)\n    return; // false;\n  checksum.Style = checkItem->GetPropVal(\"style\");\n  const AString s (checkItem->GetSubString());\n  if ((s.Len() & 1) == 0 && s.Len() <= (2u << 7)) // 1024-bit max\n  {\n    const size_t size = s.Len() / 2;\n    CByteBuffer temp(size);\n    if ((size_t)(ParseHexString(s, temp) - temp) == size)\n    {\n      checksum.Data = temp;\n      const int index = Find_ChecksumId_for_Name(checksum.Style);\n      if (index >= 0 && checksum.Data.Size() == GetHashSize(index))\n      {\n        checksum.AlgoNumber = index;\n        return;\n      }\n    }\n  }\n  checksum.Error = true;\n}\n\n\nstatic bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent, int level)\n{\n  if (!item.IsTag)\n    return true;\n  if (level >= 1024)\n    return false;\n  if (item.Name.IsEqualTo(\"file\"))\n  {\n    CFile file(parent);\n    parent = (int)files.Size();\n    {\n      const AString id = item.GetPropVal(\"id\");\n      const char *end;\n      file.Id = ConvertStringToUInt64(id, &end);\n      if (*end == 0)\n        file.Id_Defined = true;\n    }\n    file.Name = item.GetSubStringForTag(\"name\");\n    z7_xml_DecodeString(file.Name);\n    {\n      const CXmlItem *typeItem = item.FindSubTag_GetPtr(\"type\");\n      if (typeItem)\n      {\n        file.Type = typeItem->GetSubString();\n        // file.LinkFrom = typeItem->GetPropVal(\"link\");\n        if (file.Type.IsEqualTo(\"directory\"))\n          file.IsDir = true;\n        else\n        {\n          // file.IsDir = false;\n          /*\n          else if (file.Type.IsEqualTo(\"file\"))\n          {}\n          else if (file.Type.IsEqualTo(\"hardlink\"))\n          {}\n          else\n          */\n          if (file.Type.IsEqualTo(\"symlink\"))\n            file.Is_SymLink = true;\n          // file.IsDir = false;\n        }\n      }\n    }\n    {\n      const CXmlItem *linkItem = item.FindSubTag_GetPtr(\"link\");\n      if (linkItem)\n      {\n        // file.LinkType = linkItem->GetPropVal(\"type\");\n        file.Link = linkItem->GetSubString();\n        z7_xml_DecodeString(file.Link);\n      }\n    }\n\n    const CXmlItem *dataItem = item.FindSubTag_GetPtr(\"data\");\n    if (dataItem && !file.IsDir)\n    {\n      file.HasData = true;\n      if (!ParseUInt64(*dataItem, \"size\", file.Size))\n        return false;\n      if (!ParseUInt64(*dataItem, \"length\", file.PackSize))\n        return false;\n      if (!ParseUInt64(*dataItem, \"offset\", file.Offset))\n        return false;\n      ParseChecksum(*dataItem, \"extracted-checksum\", file.extracted_checksum);\n      ParseChecksum(*dataItem, \"archived-checksum\",  file.archived_checksum);\n      const CXmlItem *encodingItem = dataItem->FindSubTag_GetPtr(\"encoding\");\n      if (encodingItem)\n      {\n        AString s (encodingItem->GetPropVal(\"style\"));\n        if (!s.IsEmpty())\n        {\n          const AString appl (\"application/\");\n          if (s.IsPrefixedBy(appl))\n          {\n            s.DeleteFrontal(appl.Len());\n            const AString xx (\"x-\");\n            if (s.IsPrefixedBy(xx))\n            {\n              s.DeleteFrontal(xx.Len());\n              if (s.IsEqualTo(\"gzip\"))\n                s = METHOD_NAME_ZLIB;\n            }\n          }\n          file.Method = s;\n        }\n      }\n    }\n\n    file.INode_Defined = ParseUInt64(item, \"inode\", file.INode);\n    file.UserId_Defined = ParseUInt64(item, \"uid\", file.UserId);\n    file.GroupId_Defined = ParseUInt64(item, \"gid\", file.GroupId);\n    // file.Device_Defined = ParseUInt64(item, \"deviceno\", file.Device);\n    file.MTime = ParseTime(item, \"mtime\"); // z_IsRequied = true\n    file.CTime = ParseTime(item, \"ctime\");\n    file.ATime = ParseTime(item, \"atime\");\n    {\n      const AString s (item.GetSubStringForTag(\"mode\"));\n      if (s[0] == '0')\n      {\n        const char *end;\n        file.Mode = ConvertOctStringToUInt32(s, &end);\n        file.Mode_Defined = (*end == 0);\n      }\n    }\n    file.User = item.GetSubStringForTag(\"user\");\n    file.Group = item.GetSubStringForTag(\"group\");\n\n    files.Add(file);\n  }\n\n  FOR_VECTOR (i, item.SubItems)\n    if (!AddItem(item.SubItems[i], files, parent, level + 1))\n      return false;\n  return true;\n}\n\n\n\nstruct CInStreamWithHash\n{\n  CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha1> inStreamSha1;\n  CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha256> inStreamSha256;\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStreamLim;\n\n  void SetStreamAndInit(ISequentialInStream *stream, int algo);\n  bool CheckHash(int algo, const Byte *digest_from_arc) const;\n};\n\n\nvoid CInStreamWithHash::SetStreamAndInit(ISequentialInStream *stream, int algo)\n{\n  if (algo == XAR_CKSUM_SHA1)\n  {\n    inStreamSha1->SetStream(stream);\n    inStreamSha1->Init();\n    stream = inStreamSha1;\n  }\n  else if (algo == XAR_CKSUM_SHA256\n        || algo == XAR_CKSUM_SHA512)\n  {\n    inStreamSha256->SetStream(stream);\n    inStreamSha256->Init(algo == XAR_CKSUM_SHA512);\n    stream = inStreamSha256;\n  }\n  inStreamLim->SetStream(stream);\n}\n\nbool CInStreamWithHash::CheckHash(int algo, const Byte *digest_from_arc) const\n{\n  if (algo == XAR_CKSUM_SHA1)\n  {\n    Byte digest[SHA1_DIGEST_SIZE];\n    inStreamSha1->Final(digest);\n    if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0)\n      return false;\n  }\n  else if (algo == XAR_CKSUM_SHA256)\n  {\n    Byte digest[SHA256_DIGEST_SIZE];\n    inStreamSha256->Final256(digest);\n    if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0)\n      return false;\n  }\n  else if (algo == XAR_CKSUM_SHA512)\n  {\n    Byte digest[SHA512_DIGEST_SIZE];\n    inStreamSha256->Final512(digest);\n    if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0)\n      return false;\n  }\n  return true;\n}\n\n\nHRESULT CHandler::Open2(IInStream *stream)\n{\n  const unsigned kHeaderSize = 28;\n  UInt32 buf32[kHeaderSize / sizeof(UInt32)];\n  RINOK(ReadStream_FALSE(stream, buf32, kHeaderSize))\n  const unsigned headerSize = Get16((const Byte *)(const void *)buf32 + 4);\n  // xar library now writes 1 to version field.\n  // some old xars could have version == 0 ?\n  // specification allows (headerSize != 28),\n  // but we don't expect big value in (headerSize).\n  // so we restrict (headerSize) with 64 bytes to reduce false open.\n  const unsigned kHeaderSize_MAX = 64;\n  if (Get32(buf32) != 0x78617221  // signature: \"xar!\"\n      || headerSize < kHeaderSize\n      || headerSize > kHeaderSize_MAX\n      || Get16((const Byte *)(const void *)buf32 + 6) > 1 // version\n      )\n    return S_FALSE;\n  _checkSumAlgo = Get32(buf32 + 6);\n  const UInt64 packSize = Get64(buf32 + 2);\n  const UInt64 unpackSize = Get64(buf32 + 4);\n  if (packSize >= kXmlPackSizeMax ||\n      unpackSize >= kXmlSizeMax)\n    return S_FALSE;\n  /* some xar archives can have padding bytes at offset 28,\n     or checksum algorithm name at offset 28 (in xar fork, if cksum_alg==3)\n     But we didn't see such xar archives.\n  */\n  if (headerSize != kHeaderSize)\n  {\n    RINOK(InStream_SeekSet(stream, headerSize))\n  }\n  _dataStartPos = headerSize + packSize;\n  _phySize = _dataStartPos;\n\n  _xmlBuf.Alloc((size_t)unpackSize + 1);\n  if (!_xmlBuf.IsAllocated())\n    return E_OUTOFMEMORY;\n  _xmlLen = (size_t)unpackSize;\n  \n  CInStreamWithHash hashStream;\n  {\n    CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> zlibCoder;\n    hashStream.SetStreamAndInit(stream, (int)(unsigned)_checkSumAlgo);\n    hashStream.inStreamLim->Init(packSize);\n    CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamLim;\n    outStreamLim->Init(_xmlBuf, (size_t)unpackSize);\n    RINOK(zlibCoder.Interface()->Code(hashStream.inStreamLim, outStreamLim, NULL, &unpackSize, NULL))\n    if (outStreamLim->GetPos() != (size_t)unpackSize)\n      return S_FALSE;\n  }\n  _xmlBuf[(size_t)unpackSize] = 0;\n  if (strlen((const char *)(const Byte *)_xmlBuf) != (size_t)unpackSize)\n    return S_FALSE;\n  CXml xml;\n  if (!xml.Parse((const char *)(const Byte *)_xmlBuf))\n    return S_FALSE;\n  \n  if (!xml.Root.IsTagged(\"xar\") || xml.Root.SubItems.Size() != 1)\n    return S_FALSE;\n  const CXmlItem &toc = xml.Root.SubItems[0];\n  if (!toc.IsTagged(\"toc\"))\n    return S_FALSE;\n\n  // CreationTime = ParseTime(toc, \"creation-time\", false); // z_IsRequied\n  CreationTime_String = toc.GetSubStringForTag(\"creation-time\");\n  {\n    // we suppose that offset of checksum is always 0;\n    // but [TOC].xml contains exact offset value in <checksum> block.\n    const UInt64 offset = 0;\n    const unsigned hashSize = GetHashSize((int)(unsigned)_checkSumAlgo);\n    if (hashSize)\n    {\n      /*\n      const CXmlItem *csItem = toc.FindSubTag_GetPtr(\"checksum\");\n      if (csItem)\n      {\n        const int checkSumAlgo2 = Find_ChecksumId_for_Name(csItem->GetPropVal(\"style\"));\n        UInt64 csSize, csOffset;\n        if (ParseUInt64(*csItem, \"size\", csSize) &&\n            ParseUInt64(*csItem, \"offset\", csOffset)  &&\n            csSize == hashSize &&\n            (unsigned)checkSumAlgo2 == _checkSumAlgo)\n          offset = csOffset;\n      }\n      */\n      CByteBuffer digest_from_arc(hashSize);\n      RINOK(InStream_SeekSet(stream, _dataStartPos + offset))\n      RINOK(ReadStream_FALSE(stream, digest_from_arc, hashSize))\n      if (!hashStream.CheckHash((int)(unsigned)_checkSumAlgo, digest_from_arc))\n        _toc_CrcError = true;\n    }\n  }\n    \n  if (!AddItem(toc, _files,\n      -1, // parent\n      0)) // level\n    return S_FALSE;\n\n  UInt64 totalPackSize = 0;\n  unsigned numMainFiles = 0;\n  \n  FOR_VECTOR (i, _files)\n  {\n    const CFile &file = _files[i];\n    file.UpdateTotalPackSize(totalPackSize);\n    if (file.Parent == -1)\n    {\n      if (file.Name.IsEqualTo(\"Payload\") ||\n          file.Name.IsEqualTo(\"Content\"))\n      {\n        _mainSubfile = (Int32)(int)i;\n        numMainFiles++;\n      }\n      else if (file.Name.IsEqualTo(\"PackageInfo\"))\n        _is_pkg = true;\n    }\n  }\n\n  if (numMainFiles > 1)\n    _mainSubfile = -1;\n\n  const UInt64 k_PhySizeLim = (UInt64)1 << 62;\n  _phySize = (totalPackSize > k_PhySizeLim - _dataStartPos) ?\n      k_PhySizeLim :\n      _dataStartPos + totalPackSize;\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    RINOK(Open2(stream))\n    _inStream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _phySize = 0;\n  _dataStartPos = 0;\n  _inStream.Release();\n  _files.Clear();\n  _xmlLen = 0;\n  _xmlBuf.Free();\n  _mainSubfile = -1;\n  _is_pkg = false;\n  _toc_CrcError = false;\n  _checkSumAlgo = 0;\n  // CreationTime = 0;\n  CreationTime_String.Empty();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _files.Size()\n#ifdef XAR_SHOW_RAW\n    + 1\n#endif\n  ;\n  return S_OK;\n}\n\nstatic void TimeToProp(UInt64 t, NCOM::CPropVariant &prop)\n{\n  if (t != 0)\n  {\n    FILETIME ft;\n    ft.dwLowDateTime = (UInt32)(t);\n    ft.dwHighDateTime = (UInt32)(t >> 32);\n    prop = ft;\n  }\n}\n\nstatic void Utf8StringToProp(const AString &s, NCOM::CPropVariant &prop)\n{\n  if (!s.IsEmpty())\n  {\n    UString us;\n    ConvertUTF8ToUnicode(s, us);\n    prop = us;\n  }\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    // case kpidHeadersSize: prop = _dataStartPos; break;\n    case kpidPhySize: prop = _phySize; break;\n    case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break;\n    case kpidSubType: if (_is_pkg) prop = \"pkg\"; break;\n    case kpidExtension: prop = _is_pkg ? \"pkg\" : \"xar\"; break;\n    case kpidCTime:\n    {\n      // it's local time. We can transfer it to UTC time, if we use FILETIME.\n      // TimeToProp(CreationTime, prop); break;\n      if (!CreationTime_String.IsEmpty())\n        prop = CreationTime_String;\n      break;\n    }\n    case kpidMethod:\n    {\n      AString s;\n      if (_checkSumAlgo < Z7_ARRAY_SIZE(k_ChecksumNames))\n        s = k_ChecksumNames[_checkSumAlgo];\n      else\n      {\n        s += \"Checksum\";\n        s.Add_UInt32(_checkSumAlgo);\n      }\n      prop = s;\n      break;\n    }\n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      if (_toc_CrcError) v |= kpv_ErrorFlags_CrcError;\n      prop = v;\n      break;\n    }\n    case kpidINode: prop = true; break;\n    case kpidIsTree: prop = true; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\n/*\ninline UInt32 MY_dev_major(UInt64 dev)\n{\n  return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff);\n}\ninline UInt32 MY_dev_minor(UInt64 dev)\n{\n  return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~(UInt32)0xff);\n}\n*/\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  \n#ifdef XAR_SHOW_RAW\n  if (index >= _files.Size())\n  {\n    switch (propID)\n    {\n      case kpidName:\n      case kpidPath:\n        prop = \"[TOC].xml\"; break;\n      case kpidSize:\n      case kpidPackSize: prop = (UInt64)_xmlLen; break;\n    }\n  }\n  else\n#endif\n  {\n    const CFile &item = _files[index];\n    switch (propID)\n    {\n      case kpidPath:\n      {\n        AString path;\n        unsigned cur = index;\n        for (;;)\n        {\n          const CFile &item2 = _files[cur];\n          if (!path.IsEmpty())\n            path.InsertAtFront(CHAR_PATH_SEPARATOR);\n// #define XAR_EMPTY_NAME_REPLACEMENT \"[]\"\n          if (item2.Name.IsEmpty())\n          {\n            AString s('[');\n            s.Add_UInt32(cur);\n            s.Add_Char(']');\n            path.Insert(0, s);\n          }\n          else\n            path.Insert(0, item2.Name);\n          if (item2.Parent < 0)\n            break;\n          cur = (unsigned)item2.Parent;\n        }\n        Utf8StringToProp(path, prop);\n        break;\n      }\n\n      case kpidName:\n      {\n        if (item.Name.IsEmpty())\n        {\n          AString s('[');\n          s.Add_UInt32(index);\n          s.Add_Char(']');\n          prop = s;\n        }\n        else\n          Utf8StringToProp(item.Name, prop);\n        break;\n      }\n\n      case kpidIsDir: prop = item.IsDir; break;\n      \n      case kpidSize:     if (item.HasData && !item.IsDir) prop = item.Size; break;\n      case kpidPackSize: if (item.HasData && !item.IsDir) prop = item.PackSize; break;\n\n      case kpidMethod:\n      {\n        if (item.HasData)\n        {\n          AString s = item.Method;\n          item.extracted_checksum.AddNameToString(s);\n          item.archived_checksum.AddNameToString(s);\n          Utf8StringToProp(s, prop);\n        }\n        break;\n      }\n        \n      case kpidMTime: TimeToProp(item.MTime, prop); break;\n      case kpidCTime: TimeToProp(item.CTime, prop); break;\n      case kpidATime: TimeToProp(item.ATime, prop); break;\n      \n      case kpidPosixAttrib:\n        if (item.Mode_Defined)\n        {\n          UInt32 mode = item.Mode;\n          if ((mode & MY_LIN_S_IFMT) == 0)\n            mode |= (\n                item.Is_SymLink ? MY_LIN_S_IFLNK :\n                item.IsDir      ? MY_LIN_S_IFDIR :\n                                  MY_LIN_S_IFREG);\n          prop = mode;\n        }\n        break;\n      \n      case kpidType:  Utf8StringToProp(item.Type, prop); break;\n      case kpidUser:  Utf8StringToProp(item.User, prop); break;\n      case kpidGroup: Utf8StringToProp(item.Group, prop); break;\n      case kpidSymLink: if (item.Is_SymLink) Utf8StringToProp(item.Link, prop); break;\n      \n      case kpidUserId:  if (item.UserId_Defined)  prop = item.UserId;   break;\n      case kpidGroupId: if (item.GroupId_Defined) prop = item.GroupId;  break;\n      case kpidINode:   if (item.INode_Defined)   prop = item.INode;    break;\n      case kpidId:      if (item.Id_Defined)      prop = item.Id;       break;\n      // Utf8StringToProp(item.Id, prop);\n      /*\n      case kpidDeviceMajor: if (item.Device_Defined) prop = (UInt32)MY_dev_major(item.Device);  break;\n      case kpidDeviceMinor: if (item.Device_Defined) prop = (UInt32)MY_dev_minor(item.Device);  break;\n      case kpidLinkType:\n        if (!item.LinkType.IsEmpty())\n          Utf8StringToProp(item.LinkType, prop);\n        break;\n      case kpidLinkFrom:\n        if (!item.LinkFrom.IsEmpty())\n          Utf8StringToProp(item.LinkFrom, prop);\n        break;\n      */\n      case kpidOffset:\n        if (item.HasData)\n          prop = _dataStartPos + item.Offset;\n        break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\n// for debug:\n// #define Z7_XAR_SHOW_CHECKSUM_PACK\n\n#ifdef Z7_XAR_SHOW_CHECKSUM_PACK\nenum\n{\n  kpidChecksumPack = kpidUserDefined\n};\n#endif\n\nstatic const Byte kRawProps[] =\n{\n  kpidChecksum\n#ifdef Z7_XAR_SHOW_CHECKSUM_PACK\n  , kpidCRC // instead of kpidUserDefined / kpidCRC\n#endif\n};\n\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps))\n{\n  *numProps = Z7_ARRAY_SIZE(kRawProps);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID))\n{\n  *propID = kRawProps[index];\n  *name = NULL;\n\n#ifdef Z7_XAR_SHOW_CHECKSUM_PACK\n  if (index != 0)\n  {\n    *propID = kpidChecksumPack;\n    *name = NWindows::NCOM::AllocBstrFromAscii(\"archived-checksum\");\n  }\n#endif\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType))\n{\n  *parentType = NParentType::kDir;\n  *parent = (UInt32)(Int32)-1;\n#ifdef XAR_SHOW_RAW\n  if (index >= _files.Size())\n    return S_OK;\n#endif\n  {\n    const CFile &item = _files[index];\n    *parent = (UInt32)(Int32)item.Parent;\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType))\n{\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n\n  // COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  if (propID == kpidChecksum)\n  {\n#ifdef XAR_SHOW_RAW\n    if (index >= _files.Size())\n    {\n      // case kpidPath: prop = \"[TOC].xml\"; break;\n    }\n    else\n#endif\n    {\n      const CFile &item = _files[index];\n      const size_t size = item.extracted_checksum.Data.Size();\n      if (size != 0)\n      {\n        *dataSize = (UInt32)size;\n        *propType = NPropDataType::kRaw;\n        *data = item.extracted_checksum.Data;\n      }\n    }\n  }\n\n#ifdef Z7_XAR_SHOW_CHECKSUM_PACK\n  if (propID == kpidChecksumPack)\n  {\n#ifdef XAR_SHOW_RAW\n    if (index >= _files.Size())\n    {\n      // we can show digest check sum here\n    }\n    else\n#endif\n    {\n      const CFile &item = _files[index];\n      const size_t size = (UInt32)item.archived_checksum.Data.Size();\n      if (size != 0)\n      {\n        *dataSize = (UInt32)size;\n        *propType = NPropDataType::kRaw;\n        *data = item.archived_checksum.Data;\n      }\n    }\n  }\n#endif\n  return S_OK;\n}\n\n\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _files.Size()\n#ifdef XAR_SHOW_RAW\n    + 1\n#endif\n    ;\n  if (numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 index = allFilesMode ? i : indices[i];\n#ifdef XAR_SHOW_RAW\n    if (index >= _files.Size())\n      totalSize += _xmlLen;\n    else\n#endif\n      totalSize += _files[index].Size;\n  }\n  RINOK(extractCallback->SetTotal(totalSize))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n  CInStreamWithHash inHashStream;\n  CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha1> outStreamSha1;\n  CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha256> outStreamSha256;\n  CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStreamLim;\n  CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder;\n  CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> zlibCoder;\n  CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CDecoder> bzip2Coder;\n  bzip2Coder->FinishMode = true;\n  \n  UInt64 cur_PackSize, cur_UnpSize;\n\n  for (i = 0;; i++,\n      lps->InSize += cur_PackSize,\n      lps->OutSize += cur_UnpSize)\n  {\n    cur_PackSize = 0;\n    cur_UnpSize = 0;\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      break;\n\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n    \n    if (index < _files.Size())\n    {\n      const CFile &item = _files[index];\n      if (item.IsDir)\n      {\n        RINOK(extractCallback->PrepareOperation(askMode))\n        realOutStream.Release();\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n        continue;\n      }\n    }\n\n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    Int32 opRes = NExtract::NOperationResult::kOK;\n\n#ifdef XAR_SHOW_RAW\n    if (index >= _files.Size())\n    {\n      cur_PackSize = cur_UnpSize = _xmlLen;\n      if (realOutStream)\n        RINOK(WriteStream(realOutStream, _xmlBuf, _xmlLen))\n      realOutStream.Release();\n    }\n    else\n#endif\n    {\n      const CFile &item = _files[index];\n      if (!item.HasData)\n        realOutStream.Release();\n      else\n      {\n        cur_PackSize = item.PackSize;\n        cur_UnpSize = item.Size;\n        \n        RINOK(InStream_SeekSet(_inStream, _dataStartPos + item.Offset))\n\n        inHashStream.SetStreamAndInit(_inStream, item.archived_checksum.AlgoNumber);\n        inHashStream.inStreamLim->Init(item.PackSize);\n\n        const int checksum_method = item.extracted_checksum.AlgoNumber;\n        if (checksum_method == XAR_CKSUM_SHA1)\n        {\n          outStreamLim->SetStream(outStreamSha1);\n          outStreamSha1->SetStream(realOutStream);\n          outStreamSha1->Init();\n        }\n        else if (checksum_method == XAR_CKSUM_SHA256\n              || checksum_method == XAR_CKSUM_SHA512)\n        {\n          outStreamLim->SetStream(outStreamSha256);\n          outStreamSha256->SetStream(realOutStream);\n          outStreamSha256->Init(checksum_method == XAR_CKSUM_SHA512);\n        }\n        else\n          outStreamLim->SetStream(realOutStream);\n\n        realOutStream.Release();\n\n        // outStreamSha1->Init(item.Sha1IsDefined);\n\n        outStreamLim->Init(item.Size);\n        HRESULT res = S_OK;\n        \n        ICompressCoder *coder = NULL;\n        if (item.IsCopyMethod())\n        {\n          if (item.PackSize == item.Size)\n            coder = copyCoder;\n          else\n            opRes = NExtract::NOperationResult::kUnsupportedMethod;\n        }\n        else if (item.Method.IsEqualTo(METHOD_NAME_ZLIB))\n          coder = zlibCoder;\n        else if (item.Method.IsEqualTo(\"bzip2\"))\n          coder = bzip2Coder;\n        else\n          opRes = NExtract::NOperationResult::kUnsupportedMethod;\n        \n        if (coder)\n          res = coder->Code(inHashStream.inStreamLim, outStreamLim, NULL, &item.Size, lps);\n        \n        if (res != S_OK)\n        {\n          if (!outStreamLim->IsFinishedOK())\n            opRes = NExtract::NOperationResult::kDataError;\n          else if (res != S_FALSE)\n            return res;\n          if (opRes == NExtract::NOperationResult::kOK)\n            opRes = NExtract::NOperationResult::kDataError;\n        }\n\n        if (opRes == NExtract::NOperationResult::kOK)\n        {\n          if (outStreamLim->IsFinishedOK())\n          {\n            if (checksum_method == XAR_CKSUM_SHA1)\n            {\n              Byte digest[SHA1_DIGEST_SIZE];\n              outStreamSha1->Final(digest);\n              if (memcmp(digest, item.extracted_checksum.Data, SHA1_DIGEST_SIZE) != 0)\n                opRes = NExtract::NOperationResult::kCRCError;\n            }\n            else if (checksum_method == XAR_CKSUM_SHA256)\n            {\n              Byte digest[SHA256_DIGEST_SIZE];\n              outStreamSha256->Final256(digest);\n              if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0)\n                opRes = NExtract::NOperationResult::kCRCError;\n            }\n            else if (checksum_method == XAR_CKSUM_SHA512)\n            {\n              Byte digest[SHA512_DIGEST_SIZE];\n              outStreamSha256->Final512(digest);\n              if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0)\n                opRes = NExtract::NOperationResult::kCRCError;\n            }\n            if (opRes == NExtract::NOperationResult::kOK)\n              if (!inHashStream.CheckHash(\n                    item.archived_checksum.AlgoNumber,\n                    item.archived_checksum.Data))\n                opRes = NExtract::NOperationResult::kCRCError;\n          }\n          else\n            opRes = NExtract::NOperationResult::kDataError;\n        }\n        if (checksum_method == XAR_CKSUM_SHA1)\n          outStreamSha1->ReleaseStream();\n        else if (checksum_method == XAR_CKSUM_SHA256)\n          outStreamSha256->ReleaseStream();\n      }\n      outStreamLim->ReleaseStream();\n    }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  *stream = NULL;\n  COM_TRY_BEGIN\n#ifdef XAR_SHOW_RAW\n  if (index >= _files.Size())\n  {\n    Create_BufInStream_WithNewBuffer(_xmlBuf, _xmlLen, stream);\n    return S_OK;\n  }\n  else\n#endif\n  {\n    const CFile &item = _files[index];\n    if (item.HasData && item.IsCopyMethod() && item.PackSize == item.Size)\n      return CreateLimitedInStream(_inStream, _dataStartPos + item.Offset, item.Size, stream);\n  }\n  return S_FALSE;\n  COM_TRY_END\n}\n\n// 0x1c == 28 is expected header size value for most archives.\n// but we want to support another (rare case) headers sizes.\n// so we must reduce signature to 4 or 5 bytes.\nstatic const Byte k_Signature[] =\n//  { 'x', 'a', 'r', '!', 0, 0x1C, 0 };\n    { 'x', 'a', 'r', '!', 0 };\n\nREGISTER_ARC_I(\n  \"Xar\", \"xar pkg xip\", NULL, 0xE1,\n  k_Signature,\n  0,\n  0,\n  NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/XzHandler.cpp",
    "content": "﻿// XzHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/Defs.h\"\n#include \"../../Common/IntToString.h\"\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/StringToInt.h\"\n\n#include \"../../Windows/PropVariant.h\"\n#include \"../../Windows/System.h\"\n\n#include \"../Common/CWrappers.h\"\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/CopyCoder.h\"\n#include \"../Compress/XzDecoder.h\"\n#include \"../Compress/XzEncoder.h\"\n\n#include \"IArchive.h\"\n\n#include \"Common/HandlerOut.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NXz {\n\n#define k_LZMA2_Name \"LZMA2\"\n\n\nstruct CBlockInfo\n{\n  unsigned StreamFlags;\n  UInt64 PackPos;\n  UInt64 PackSize; // pure value from Index record, it doesn't include pad zeros\n  UInt64 UnpackPos;\n};\n\n\nZ7_class_CHandler_final:\n  public IInArchive,\n  public IArchiveOpenSeq,\n  public IInArchiveGetStream,\n  public ISetProperties,\n #ifndef Z7_EXTRACT_ONLY\n  public IOutArchive,\n #endif\n  public CMyUnknownImp,\n #ifndef Z7_EXTRACT_ONLY\n  public CMultiMethodProps\n #else\n  public CCommonMethodProps\n #endif\n{\n  Z7_COM_QI_BEGIN2(IInArchive)\n  Z7_COM_QI_ENTRY(IArchiveOpenSeq)\n  Z7_COM_QI_ENTRY(IInArchiveGetStream)\n  Z7_COM_QI_ENTRY(ISetProperties)\n #ifndef Z7_EXTRACT_ONLY\n  Z7_COM_QI_ENTRY(IOutArchive)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(IInArchive)\n  Z7_IFACE_COM7_IMP(IArchiveOpenSeq)\n  Z7_IFACE_COM7_IMP(IInArchiveGetStream)\n  Z7_IFACE_COM7_IMP(ISetProperties)\n #ifndef Z7_EXTRACT_ONLY\n  Z7_IFACE_COM7_IMP(IOutArchive)\n #endif\n\n  bool _stat_defined;\n  bool _stat2_defined;\n  bool _isArc;\n  bool _needSeekToStart;\n  bool _firstBlockWasRead;\n  SRes _stat2_decode_SRes;\n\n  CXzStatInfo _stat;    // it's stat from backward parsing\n  CXzStatInfo _stat2;   // it's data from forward parsing, if the decoder was called\n\n  const CXzStatInfo *GetStat() const\n  {\n    if (_stat_defined) return &_stat;\n    if (_stat2_defined) return &_stat2;\n    return NULL;\n  }\n  \n  AString _methodsString;\n\n\n  #ifndef Z7_EXTRACT_ONLY\n\n  UInt32 _filterId;\n  UInt64 _numSolidBytes;\n\n  void InitXz()\n  {\n    _filterId = 0;\n    _numSolidBytes = XZ_PROPS_BLOCK_SIZE_AUTO;\n  }\n\n  #endif\n\n\n  void Init()\n  {\n    #ifndef Z7_EXTRACT_ONLY\n      InitXz();\n      CMultiMethodProps::Init();\n    #else\n      CCommonMethodProps::InitCommon();\n    #endif\n  }\n  \n  HRESULT SetProperty(const wchar_t *name, const PROPVARIANT &value);\n\n  HRESULT Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback);\n\n  HRESULT Decode(NCompress::NXz::CDecoder &decoder,\n      ISequentialInStream *seqInStream,\n      ISequentialOutStream *outStream,\n      ICompressProgressInfo *progress)\n  {\n    #ifndef Z7_ST\n    decoder._numThreads = _numThreads;\n    #endif\n    decoder._memUsage = _memUsage_Decompress;\n\n    const HRESULT hres = decoder.Decode(seqInStream, outStream,\n        NULL, // *outSizeLimit\n        true, // finishStream\n        progress);\n    \n    if (decoder.MainDecodeSRes_wasUsed\n        && decoder.MainDecodeSRes != SZ_ERROR_MEM\n        && decoder.MainDecodeSRes != SZ_ERROR_UNSUPPORTED)\n    {\n      // if (!_stat2_defined)\n      {\n        _stat2_decode_SRes = decoder.MainDecodeSRes;\n        _stat2 = decoder.Stat;\n        _stat2_defined = true;\n      }\n    }\n\n    if (hres == S_OK && progress)\n    {\n      // RINOK(\n      progress->SetRatioInfo(&decoder.Stat.InSize, &decoder.Stat.OutSize);\n    }\n    return hres;\n  }\n\npublic:\n  CBlockInfo *_blocks;\n  size_t _blocksArraySize;\n  UInt64 _maxBlocksSize;\n  CMyComPtr<IInStream> _stream;\n  CMyComPtr<ISequentialInStream> _seqStream;\n\n  CXzBlock _firstBlock;\n\n  CHandler();\n  ~CHandler();\n\n  HRESULT SeekToPackPos(UInt64 pos)\n  {\n    return InStream_SeekSet(_stream, pos);\n  }\n};\n\n\nCHandler::CHandler():\n    _blocks(NULL),\n    _blocksArraySize(0)\n{\n  #ifndef Z7_EXTRACT_ONLY\n  InitXz();\n  #endif\n}\n\nCHandler::~CHandler()\n{\n  MyFree(_blocks);\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidSize,\n  kpidPackSize,\n  kpidMethod\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidMethod,\n  kpidNumStreams,\n  kpidNumBlocks,\n  kpidClusterSize,\n  kpidCharacts\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nstatic void Lzma2PropToString(AString &s, unsigned prop)\n{\n  char c = 0;\n  UInt32 size;\n  if ((prop & 1) == 0)\n    size = prop / 2 + 12;\n  else\n  {\n    c = 'k';\n    size = (UInt32)(2 | (prop & 1)) << (prop / 2 + 1);\n    if (prop > 17)\n    {\n      size >>= 10;\n      c = 'm';\n    }\n  }\n  s.Add_UInt32(size);\n  if (c != 0)\n    s.Add_Char(c);\n}\n\nstruct CMethodNamePair\n{\n  UInt32 Id;\n  const char *Name;\n};\n\nstatic const CMethodNamePair g_NamePairs[] =\n{\n  { XZ_ID_Subblock, \"SB\" },\n  { XZ_ID_Delta, \"Delta\" },\n  { XZ_ID_X86, \"BCJ\" },\n  { XZ_ID_PPC, \"PPC\" },\n  { XZ_ID_IA64, \"IA64\" },\n  { XZ_ID_ARM, \"ARM\" },\n  { XZ_ID_ARMT, \"ARMT\" },\n  { XZ_ID_SPARC, \"SPARC\" },\n  { XZ_ID_ARM64, \"ARM64\" },\n  { XZ_ID_RISCV, \"RISCV\" },\n  { XZ_ID_LZMA2, \"LZMA2\" }\n};\n\nstatic void AddMethodString(AString &s, const CXzFilter &f)\n{\n  const char *p = NULL;\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++)\n    if (g_NamePairs[i].Id == f.id)\n    {\n      p = g_NamePairs[i].Name;\n      break;\n    }\n  char temp[32];\n  if (!p)\n  {\n    ::ConvertUInt64ToString(f.id, temp);\n    p = temp;\n  }\n\n  s += p;\n\n  if (f.propsSize > 0)\n  {\n    s.Add_Colon();\n    if (f.id == XZ_ID_LZMA2 && f.propsSize == 1)\n      Lzma2PropToString(s, f.props[0]);\n    else if (f.id == XZ_ID_Delta && f.propsSize == 1)\n      s.Add_UInt32((UInt32)f.props[0] + 1);\n    else if (f.id == XZ_ID_ARM64 && f.propsSize == 1)\n      s.Add_UInt32((UInt32)f.props[0] + 16 + 2);\n    else\n    {\n      s.Add_Char('[');\n      for (UInt32 bi = 0; bi < f.propsSize; bi++)\n      {\n        const unsigned v = f.props[bi];\n        s.Add_Char(GET_HEX_CHAR_UPPER(v >> 4));\n        s.Add_Char(GET_HEX_CHAR_UPPER(v & 15));\n      }\n      s.Add_Char(']');\n    }\n  }\n}\n\nstatic const char * const kChecks[] =\n{\n    \"NoCheck\"\n  , \"CRC32\"\n  , NULL\n  , NULL\n  , \"CRC64\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"SHA256\"\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n};\n\nstatic void AddCheckString(AString &s, const CXzs &xzs)\n{\n  size_t i;\n  UInt32 mask = 0;\n  for (i = 0; i < xzs.num; i++)\n    mask |= ((UInt32)1 << XzFlags_GetCheckType(xzs.streams[i].flags));\n  for (i = 0; i <= XZ_CHECK_MASK; i++)\n    if (((mask >> i) & 1) != 0)\n    {\n      s.Add_Space_if_NotEmpty();\n      if (kChecks[i])\n        s += kChecks[i];\n      else\n      {\n        s += \"Check-\";\n        s.Add_UInt32((UInt32)i);\n      }\n    }\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CXzStatInfo *stat = GetStat();\n  \n  switch (propID)\n  {\n    case kpidPhySize: if (stat) prop = stat->InSize; break;\n    case kpidNumStreams: if (stat && stat->NumStreams_Defined) prop = stat->NumStreams; break;\n    case kpidNumBlocks: if (stat && stat->NumBlocks_Defined) prop = stat->NumBlocks; break;\n    case kpidUnpackSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break;\n    case kpidClusterSize: if (_stat_defined && _stat.NumBlocks_Defined && stat->NumBlocks > 1) prop = _maxBlocksSize; break;\n    case kpidCharacts:\n      if (_firstBlockWasRead)\n      {\n        AString s;\n        if (XzBlock_HasPackSize(&_firstBlock))\n          s.Add_OptSpaced(\"BlockPackSize\");\n        if (XzBlock_HasUnpackSize(&_firstBlock))\n          s.Add_OptSpaced(\"BlockUnpackSize\");\n        if (!s.IsEmpty())\n          prop = s;\n      }\n      break;\n        \n\n    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      SRes sres = _stat2_decode_SRes;\n      if (!_isArc)                      v |= kpv_ErrorFlags_IsNotArc;\n      if (sres == SZ_ERROR_INPUT_EOF)   v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (_stat2_defined && _stat2.DataAfterEnd) v |= kpv_ErrorFlags_DataAfterEnd;\n      if (sres == SZ_ERROR_ARCHIVE)     v |= kpv_ErrorFlags_HeadersError;\n      if (sres == SZ_ERROR_UNSUPPORTED) v |= kpv_ErrorFlags_UnsupportedMethod;\n      if (sres == SZ_ERROR_DATA)        v |= kpv_ErrorFlags_DataError;\n      if (sres == SZ_ERROR_CRC)         v |= kpv_ErrorFlags_CrcError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n\n    case kpidMainSubfile:\n    {\n      // debug only, comment it:\n      // if (_blocks) prop = (UInt32)0;\n      break;\n    }\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  const CXzStatInfo *stat = GetStat();\n  NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidSize: if (stat && stat->UnpackSize_Defined) prop = stat->OutSize; break;\n    case kpidPackSize: if (stat) prop = stat->InSize; break;\n    case kpidMethod: if (!_methodsString.IsEmpty()) prop = _methodsString; break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nstruct COpenCallbackWrap\n{\n  ICompressProgress vt;\n  IArchiveOpenCallback *OpenCallback;\n  HRESULT Res;\n  \n  // new clang shows \"non-POD\" warning for offsetof(), if we use constructor instead of Init()\n  void Init(IArchiveOpenCallback *progress);\n};\n\nstatic SRes OpenCallbackProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 /* outSize */)\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(COpenCallbackWrap)\n  if (p->OpenCallback)\n    p->Res = p->OpenCallback->SetCompleted(NULL, &inSize);\n  return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);\n}\n\nvoid COpenCallbackWrap::Init(IArchiveOpenCallback *callback)\n{\n  vt.Progress = OpenCallbackProgress;\n  OpenCallback = callback;\n  Res = SZ_OK;\n}\n\n\nstruct CXzsCPP\n{\n  CXzs p;\n  CXzsCPP() { Xzs_CONSTRUCT(&p) }\n  ~CXzsCPP() { Xzs_Free(&p, &g_Alloc); }\n};\n\n#define kInputBufSize ((size_t)1 << 10)\n\nstruct CLookToRead2_CPP: public CLookToRead2\n{\n  CLookToRead2_CPP()\n  {\n    buf = NULL;\n    LookToRead2_CreateVTable(this,\n        True // Lookahead ?\n        );\n  }\n  void Alloc(size_t allocSize)\n  {\n    buf = (Byte *)MyAlloc(allocSize);\n    if (buf)\n      this->bufSize = allocSize;\n  }\n  ~CLookToRead2_CPP()\n  {\n    MyFree(buf);\n  }\n};\n\n\nstatic HRESULT SRes_to_Open_HRESULT(SRes res)\n{\n  switch (res)\n  {\n    case SZ_OK: return S_OK;\n    case SZ_ERROR_MEM: return E_OUTOFMEMORY;\n    case SZ_ERROR_PROGRESS: return E_ABORT;\n    /*\n    case SZ_ERROR_UNSUPPORTED:\n    case SZ_ERROR_CRC:\n    case SZ_ERROR_DATA:\n    case SZ_ERROR_ARCHIVE:\n    case SZ_ERROR_NO_ARCHIVE:\n      return S_FALSE;\n    */\n    default: break;\n  }\n  return S_FALSE;\n}\n\n\n\nHRESULT CHandler::Open2(IInStream *inStream, /* UInt32 flags, */ IArchiveOpenCallback *callback)\n{\n  _needSeekToStart = true;\n\n  {\n    CXzStreamFlags st;\n    CSeqInStreamWrap inStreamWrap;\n    \n    inStreamWrap.Init(inStream);\n\n    SRes res = Xz_ReadHeader(&st, &inStreamWrap.vt);\n    \n    if (inStreamWrap.Res != S_OK)\n      return inStreamWrap.Res;\n    if (res != SZ_OK)\n      return SRes_to_Open_HRESULT(res);\n\n    {\n      CXzBlock block;\n      BoolInt isIndex;\n      UInt32 headerSizeRes;\n    \n      SRes res2 = XzBlock_ReadHeader(&block, &inStreamWrap.vt, &isIndex, &headerSizeRes);\n      \n      if (inStreamWrap.Res != S_OK)\n        return inStreamWrap.Res;\n      \n      if (res2 != SZ_OK)\n      {\n        if (res2 == SZ_ERROR_INPUT_EOF)\n        {\n          _stat2_decode_SRes = res2;\n          _stream = inStream;\n          _seqStream = inStream;\n          _isArc = true;\n          return S_OK;\n        }\n\n        if (res2 == SZ_ERROR_ARCHIVE)\n          return S_FALSE;\n        // what codes are possible here ?\n        // ?? res2 == SZ_ERROR_MEM           : is possible here\n        // ?? res2 == SZ_ERROR_UNSUPPORTED   : is possible here\n      }\n      else if (!isIndex)\n      {\n        _firstBlockWasRead = true;\n        _firstBlock = block;\n\n        unsigned numFilters = XzBlock_GetNumFilters(&block);\n        for (unsigned i = 0; i < numFilters; i++)\n        {\n          _methodsString.Add_Space_if_NotEmpty();\n          AddMethodString(_methodsString, block.filters[i]);\n        }\n      }\n    }\n  }\n\n  RINOK(InStream_GetSize_SeekToEnd(inStream, _stat.InSize))\n  if (callback)\n  {\n    RINOK(callback->SetTotal(NULL, &_stat.InSize))\n  }\n\n  CSeekInStreamWrap inStreamImp;\n  \n  inStreamImp.Init(inStream);\n\n  CLookToRead2_CPP lookStream;\n\n  lookStream.Alloc(kInputBufSize);\n  \n  if (!lookStream.buf)\n    return E_OUTOFMEMORY;\n\n  lookStream.realStream = &inStreamImp.vt;\n  LookToRead2_INIT(&lookStream)\n\n  COpenCallbackWrap openWrap;\n  openWrap.Init(callback);\n\n  CXzsCPP xzs;\n  Int64 startPosition;\n  SRes res = Xzs_ReadBackward(&xzs.p, &lookStream.vt, &startPosition, &openWrap.vt, &g_Alloc);\n  if (res == SZ_ERROR_PROGRESS)\n    return (openWrap.Res == S_OK) ? E_FAIL : openWrap.Res;\n  /*\n  if (res == SZ_ERROR_NO_ARCHIVE && xzs.p.num > 0)\n    res = SZ_OK;\n  */\n  if (res == SZ_OK && startPosition == 0)\n  {\n    _stat_defined = true;\n\n    _stat.OutSize = Xzs_GetUnpackSize(&xzs.p);\n    _stat.UnpackSize_Defined = true;\n\n    _stat.NumStreams = xzs.p.num;\n    _stat.NumStreams_Defined = true;\n    \n    _stat.NumBlocks = Xzs_GetNumBlocks(&xzs.p);\n    _stat.NumBlocks_Defined = true;\n\n    AddCheckString(_methodsString, xzs.p);\n\n    const size_t numBlocks = (size_t)_stat.NumBlocks + 1;\n    const size_t bytesAlloc = numBlocks * sizeof(CBlockInfo);\n    \n    if (bytesAlloc / sizeof(CBlockInfo) == _stat.NumBlocks + 1)\n    {\n      _blocks = (CBlockInfo *)MyAlloc(bytesAlloc);\n      if (_blocks)\n      {\n        unsigned blockIndex = 0;\n        UInt64 unpackPos = 0;\n        \n        for (size_t si = xzs.p.num; si != 0;)\n        {\n          si--;\n          const CXzStream &str = xzs.p.streams[si];\n          UInt64 packPos = str.startOffset + XZ_STREAM_HEADER_SIZE;\n          \n          for (size_t bi = 0; bi < str.numBlocks; bi++)\n          {\n            const CXzBlockSizes &bs = str.blocks[bi];\n            const UInt64 packSizeAligned = bs.totalSize + ((0 - (unsigned)bs.totalSize) & 3);\n            \n            if (bs.unpackSize != 0)\n            {\n              if (blockIndex >= _stat.NumBlocks)\n                return E_FAIL;\n\n              CBlockInfo &block = _blocks[blockIndex++];\n              block.StreamFlags = str.flags;\n              block.PackSize = bs.totalSize; // packSizeAligned;\n              block.PackPos = packPos;\n              block.UnpackPos = unpackPos;\n            }\n            packPos += packSizeAligned;\n            unpackPos += bs.unpackSize;\n            if (_maxBlocksSize < bs.unpackSize)\n              _maxBlocksSize = bs.unpackSize;\n          }\n        }\n    \n        /*\n        if (blockIndex != _stat.NumBlocks)\n        {\n          // there are Empty blocks;\n        }\n        */\n        if (_stat.OutSize != unpackPos)\n          return E_FAIL;\n        CBlockInfo &block = _blocks[blockIndex++];\n        block.StreamFlags = 0;\n        block.PackSize = 0;\n        block.PackPos = 0;\n        block.UnpackPos = unpackPos;\n        _blocksArraySize = blockIndex;\n      }\n    }\n  }\n  else\n  {\n    res = SZ_OK;\n  }\n\n  RINOK(SRes_to_Open_HRESULT(res))\n\n  _stream = inStream;\n  _seqStream = inStream;\n  _isArc = true;\n  return S_OK;\n}\n\n\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    return Open2(inStream, callback);\n  }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))\n{\n  Close();\n  _seqStream = stream;\n  _isArc = true;\n  _needSeekToStart = false;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  XzStatInfo_Clear(&_stat);\n  XzStatInfo_Clear(&_stat2);\n  _stat_defined = false;\n  _stat2_defined = false;\n  _stat2_decode_SRes = SZ_OK;\n\n  _isArc = false;\n  _needSeekToStart = false;\n  _firstBlockWasRead = false;\n\n   _methodsString.Empty();\n  _stream.Release();\n  _seqStream.Release();\n\n  MyFree(_blocks);\n  _blocks = NULL;\n  _blocksArraySize = 0;\n  _maxBlocksSize = 0;\n\n  return S_OK;\n}\n\n\nstruct CXzUnpackerCPP2\n{\n  Byte *InBuf;\n  // Byte *OutBuf;\n  CXzUnpacker p;\n  \n  CXzUnpackerCPP2();\n  ~CXzUnpackerCPP2();\n};\n\nCXzUnpackerCPP2::CXzUnpackerCPP2(): InBuf(NULL)\n  // , OutBuf(NULL)\n{\n  XzUnpacker_Construct(&p, &g_Alloc);\n}\n\nCXzUnpackerCPP2::~CXzUnpackerCPP2()\n{\n  XzUnpacker_Free(&p);\n  MidFree(InBuf);\n  // MidFree(OutBuf);\n}\n\n\nZ7_CLASS_IMP_IInStream(\n  CInStream\n)\n\n  UInt64 _virtPos;\npublic:\n  UInt64 Size;\n  UInt64 _cacheStartPos;\n  size_t _cacheSize;\n  CByteBuffer _cache;\n  // UInt64 _startPos;\n  CXzUnpackerCPP2 xz;\n\n  void InitAndSeek()\n  {\n    _virtPos = 0;\n    _cacheStartPos = 0;\n    _cacheSize = 0;\n    // _startPos = startPos;\n  }\n\n  CMyComPtr2<IInArchive, CHandler> _handlerSpec;\n  // ~CInStream();\n};\n\n/*\nCInStream::~CInStream()\n{\n  // _cache.Free();\n}\n*/\n\nstatic size_t FindBlock(const CBlockInfo *blocks, size_t numBlocks, UInt64 pos)\n{\n  size_t left = 0, right = numBlocks;\n  for (;;)\n  {\n    size_t mid = (left + right) / 2;\n    if (mid == left)\n      return left;\n    if (pos < blocks[mid].UnpackPos)\n      right = mid;\n    else\n      left = mid;\n  }\n}\n\n\n\nstatic HRESULT DecodeBlock(CXzUnpackerCPP2 &xzu,\n    ISequentialInStream *seqInStream,\n    unsigned streamFlags,\n    UInt64 packSize, // pure size from Index record, it doesn't include pad zeros\n    size_t unpackSize, Byte *dest\n    // , ICompressProgressInfo *progress\n    )\n{\n  const size_t kInBufSize = (size_t)1 << 16;\n\n  XzUnpacker_Init(&xzu.p);\n\n  if (!xzu.InBuf)\n  {\n    xzu.InBuf = (Byte *)MidAlloc(kInBufSize);\n    if (!xzu.InBuf)\n      return E_OUTOFMEMORY;\n  }\n  \n  xzu.p.streamFlags = (UInt16)streamFlags;\n  XzUnpacker_PrepareToRandomBlockDecoding(&xzu.p);\n\n  XzUnpacker_SetOutBuf(&xzu.p, dest, unpackSize);\n\n  const UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);\n  UInt64 packRem = packSizeAligned;\n\n  UInt32 inSize = 0;\n  SizeT inPos = 0;\n  SizeT outPos = 0;\n\n  HRESULT readRes = S_OK;\n\n  for (;;)\n  {\n    if (inPos == inSize && readRes == S_OK)\n    {\n      inPos = 0;\n      inSize = 0;\n      UInt32 rem = kInBufSize;\n      if (rem > packRem)\n        rem = (UInt32)packRem;\n      if (rem != 0)\n        readRes = seqInStream->Read(xzu.InBuf, rem, &inSize);\n    }\n\n    SizeT inLen = inSize - inPos;\n    SizeT outLen = unpackSize - outPos;\n    \n    ECoderStatus status;\n\n    const SRes res = XzUnpacker_Code(&xzu.p,\n        // dest + outPos,\n        NULL,\n        &outLen,\n        xzu.InBuf + inPos, &inLen,\n        (inLen == 0), // srcFinished\n        CODER_FINISH_END, &status);\n\n    // return E_OUTOFMEMORY;\n    // res = SZ_ERROR_CRC;\n\n    if (res != SZ_OK)\n    {\n      if (res == SZ_ERROR_CRC)\n        return S_FALSE;\n      return SResToHRESULT(res);\n    }\n\n    inPos += inLen;\n    outPos += outLen;\n\n    packRem -= inLen;\n  \n    const BoolInt blockFinished = XzUnpacker_IsBlockFinished(&xzu.p);\n\n    if ((inLen == 0 && outLen == 0) || blockFinished)\n    {\n      if (packRem != 0 || !blockFinished || unpackSize != outPos)\n        return S_FALSE;\n      if (XzUnpacker_GetPackSizeForIndex(&xzu.p) != packSize)\n        return S_FALSE;\n      return S_OK;\n    }\n  }\n}\n\n\nZ7_COM7F_IMF(CInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  COM_TRY_BEGIN\n\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n\n  {\n    if (_virtPos >= Size)\n      return S_OK; // (Size == _virtPos) ? S_OK: E_FAIL;\n    {\n      UInt64 rem = Size - _virtPos;\n      if (size > rem)\n        size = (UInt32)rem;\n    }\n  }\n\n  if (size == 0)\n    return S_OK;\n\n  if (_virtPos < _cacheStartPos || _virtPos >= _cacheStartPos + _cacheSize)\n  {\n    const size_t bi = FindBlock(_handlerSpec->_blocks, _handlerSpec->_blocksArraySize, _virtPos);\n    const CBlockInfo &block = _handlerSpec->_blocks[bi];\n    const UInt64 unpackSize = _handlerSpec->_blocks[bi + 1].UnpackPos - block.UnpackPos;\n    if (_cache.Size() < unpackSize)\n      return E_FAIL;\n\n    _cacheSize = 0;\n\n    RINOK(_handlerSpec->SeekToPackPos(block.PackPos))\n    RINOK(DecodeBlock(xz, _handlerSpec->_seqStream, block.StreamFlags, block.PackSize,\n        (size_t)unpackSize, _cache))\n    _cacheStartPos = block.UnpackPos;\n    _cacheSize = (size_t)unpackSize;\n  }\n\n  {\n    const size_t offset = (size_t)(_virtPos - _cacheStartPos);\n    const size_t rem = _cacheSize - offset;\n    if (size > rem)\n      size = (UInt32)rem;\n    memcpy(data, _cache.ConstData() + offset, size);\n    _virtPos += size;\n    if (processedSize)\n      *processedSize = size;\n    return S_OK;\n  }\n\n  COM_TRY_END\n}\n \n\nZ7_COM7F_IMF(CInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\n\n\nstatic const UInt64 kMaxBlockSize_for_GetStream = (UInt64)1 << 40;\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n\n  *stream = NULL;\n\n  if (index != 0)\n    return E_INVALIDARG;\n\n  if (!_stat.UnpackSize_Defined\n      || _maxBlocksSize == 0 // 18.02\n      || _maxBlocksSize > kMaxBlockSize_for_GetStream\n      || _maxBlocksSize != (size_t)_maxBlocksSize)\n    return S_FALSE;\n\n  size_t memSize;\n  if (!NSystem::GetRamSize(memSize))\n    memSize = (size_t)sizeof(size_t) << 28;\n  {\n    if (_maxBlocksSize > memSize / 4)\n      return S_FALSE;\n  }\n\n  CMyComPtr2<ISequentialInStream, CInStream> spec;\n  spec.Create_if_Empty();\n  spec->_cache.Alloc((size_t)_maxBlocksSize);\n  spec->_handlerSpec.SetFromCls(this);\n  // spec->_handler = (IInArchive *)this;\n  spec->Size = _stat.OutSize;\n  spec->InitAndSeek();\n\n  *stream = spec.Detach();\n  return S_OK;\n  \n  COM_TRY_END\n}\n\n\nstatic Int32 Get_Extract_OperationResult(const NCompress::NXz::CDecoder &decoder)\n{\n  Int32 opRes;\n  SRes sres = decoder.MainDecodeSRes;\n  if (sres == SZ_ERROR_NO_ARCHIVE) // (!IsArc)\n    opRes = NExtract::NOperationResult::kIsNotArc;\n  else if (sres == SZ_ERROR_INPUT_EOF) // (UnexpectedEnd)\n    opRes = NExtract::NOperationResult::kUnexpectedEnd;\n  else if (decoder.Stat.DataAfterEnd)\n    opRes = NExtract::NOperationResult::kDataAfterEnd;\n  else if (sres == SZ_ERROR_CRC) // (CrcError)\n    opRes = NExtract::NOperationResult::kCRCError;\n  else if (sres == SZ_ERROR_UNSUPPORTED) // (Unsupported)\n    opRes = NExtract::NOperationResult::kUnsupportedMethod;\n  else if (sres == SZ_ERROR_ARCHIVE) //  (HeadersError)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (sres == SZ_ERROR_DATA)  // (DataError)\n    opRes = NExtract::NOperationResult::kDataError;\n  else if (sres != SZ_OK)\n    opRes = NExtract::NOperationResult::kDataError;\n  else\n    opRes = NExtract::NOperationResult::kOK;\n  return opRes;\n}\n\n\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n\n  const CXzStatInfo *stat = GetStat();\n\n  if (stat)\n    RINOK(extractCallback->SetTotal(stat->InSize))\n\n  UInt64 currentTotalPacked = 0;\n  RINOK(extractCallback->SetCompleted(&currentTotalPacked))\n  Int32 opRes;\n {\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  \n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n  \n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, true);\n\n  if (_needSeekToStart)\n  {\n    if (!_stream)\n      return E_FAIL;\n    RINOK(InStream_SeekToBegin(_stream))\n  }\n  else\n    _needSeekToStart = true;\n\n\n  NCompress::NXz::CDecoder decoder;\n\n  const HRESULT hres = Decode(decoder, _seqStream, realOutStream, lps);\n\n  if (!decoder.MainDecodeSRes_wasUsed)\n    return hres == S_OK ? E_FAIL : hres;\n\n  opRes = Get_Extract_OperationResult(decoder);\n  if (opRes == NExtract::NOperationResult::kOK\n      && hres != S_OK)\n    opRes = NExtract::NOperationResult::kDataError;\n\n  // realOutStream.Release();\n }\n  return extractCallback->SetOperationResult(opRes);\n  COM_TRY_END\n}\n\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))\n{\n  *timeType = GET_FileTimeType_NotDefined_for_GetFileTimeType;\n  // *timeType = NFileTimeType::kUnix;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *updateCallback))\n{\n  COM_TRY_BEGIN\n\n  if (numItems == 0)\n  {\n    CSeqOutStreamWrap seqOutStream;\n    seqOutStream.Init(outStream);\n    SRes res = Xz_EncodeEmpty(&seqOutStream.vt);\n    return SResToHRESULT(res);\n  }\n  \n  if (numItems != 1)\n    return E_INVALIDARG;\n\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IStreamSetRestriction,\n        setRestriction, outStream)\n    if (setRestriction)\n      RINOK(setRestriction->SetRestriction(0, 0))\n  }\n\n  Int32 newData, newProps;\n  UInt32 indexInArchive;\n  if (!updateCallback)\n    return E_FAIL;\n  RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))\n\n  if (IntToBool(newProps))\n  {\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))\n      if (prop.vt != VT_EMPTY)\n        if (prop.vt != VT_BOOL || prop.boolVal != VARIANT_FALSE)\n          return E_INVALIDARG;\n    }\n  }\n\n  if (IntToBool(newData))\n  {\n    UInt64 dataSize;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(updateCallback->GetProperty(0, kpidSize, &prop))\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      dataSize = prop.uhVal.QuadPart;\n    }\n\n    CMyComPtr2_Create<ICompressCoder, NCompress::NXz::CEncoder> encoder;\n\n    CXzProps &xzProps = encoder->xzProps;\n    CLzma2EncProps &lzma2Props = xzProps.lzma2Props;\n\n    lzma2Props.lzmaProps.level = GetLevel();\n\n    xzProps.reduceSize = dataSize;\n    /*\n    {\n      NCOM::CPropVariant prop = (UInt64)dataSize;\n      RINOK(encoder->SetCoderProp(NCoderPropID::kReduceSize, prop))\n    }\n    */\n\n    #ifndef Z7_ST\n\n#ifdef _WIN32\n    // we don't use chunk multithreading inside lzma2 stream.\n    // so we don't set xzProps.lzma2Props.numThreadGroups.\n    if (_numThreadGroups > 1)\n      xzProps.numThreadGroups = _numThreadGroups;\n#endif\n    \n    UInt32 numThreads = _numThreads;\n\n    const UInt32 kNumThreads_Max = 1024;\n    if (numThreads > kNumThreads_Max)\n      numThreads = kNumThreads_Max;\n\n    if (!_numThreads_WasForced\n        && _numThreads >= 1\n        && _memUsage_WasSet)\n    {\n      COneMethodInfo oneMethodInfo;\n      if (!_methods.IsEmpty())\n        oneMethodInfo = _methods[0];\n\n      SetGlobalLevelTo(oneMethodInfo);\n\n      const bool numThreads_WasSpecifiedInMethod = (oneMethodInfo.Get_NumThreads() >= 0);\n      if (!numThreads_WasSpecifiedInMethod)\n      {\n        // here we set the (NCoderPropID::kNumThreads) property in each method, only if there is no such property already\n        CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(oneMethodInfo, numThreads);\n      }\n\n      // printf(\"\\n====== GetProcessGroupAffinity : \\n\");\n\n      UInt64 cs = _numSolidBytes;\n      if (cs != XZ_PROPS_BLOCK_SIZE_AUTO)\n        oneMethodInfo.AddProp_BlockSize2(cs);\n      cs = oneMethodInfo.Get_Xz_BlockSize();\n\n      if (cs != XZ_PROPS_BLOCK_SIZE_AUTO &&\n          cs != XZ_PROPS_BLOCK_SIZE_SOLID)\n      {\n        const UInt32 lzmaThreads = oneMethodInfo.Get_Lzma_NumThreads();\n        const UInt32 numBlockThreads_Original = numThreads / lzmaThreads;\n\n        if (numBlockThreads_Original > 1)\n        {\n          UInt32 numBlockThreads = numBlockThreads_Original;\n          {\n            const UInt64 lzmaMemUsage = oneMethodInfo.Get_Lzma_MemUsage(false);\n            for (; numBlockThreads > 1; numBlockThreads--)\n            {\n              UInt64 size = numBlockThreads * (lzmaMemUsage + cs);\n              UInt32 numPackChunks = numBlockThreads + (numBlockThreads / 8) + 1;\n              if (cs < ((UInt32)1 << 26)) numPackChunks++;\n              if (cs < ((UInt32)1 << 24)) numPackChunks++;\n              if (cs < ((UInt32)1 << 22)) numPackChunks++;\n              size += numPackChunks * cs;\n              // printf(\"\\nnumBlockThreads = %d, size = %d\\n\", (unsigned)(numBlockThreads), (unsigned)(size >> 20));\n              if (size <= _memUsage_Compress)\n                break;\n            }\n          }\n          if (numBlockThreads == 0)\n            numBlockThreads = 1;\n          if (numBlockThreads != numBlockThreads_Original)\n            numThreads = numBlockThreads * lzmaThreads;\n        }\n      }\n    }\n    xzProps.numTotalThreads = (int)numThreads;\n\n    #endif // Z7_ST\n\n\n    xzProps.blockSize = _numSolidBytes;\n    if (_numSolidBytes == XZ_PROPS_BLOCK_SIZE_SOLID)\n    {\n      xzProps.lzma2Props.blockSize = LZMA2_ENC_PROPS_BLOCK_SIZE_SOLID;\n    }\n\n    RINOK(encoder->SetCheckSize(_crcSize))\n\n    {\n      CXzFilterProps &filter = xzProps.filterProps;\n      \n      if (_filterId == XZ_ID_Delta)\n      {\n        bool deltaDefined = false;\n        FOR_VECTOR (j, _filterMethod.Props)\n        {\n          const CProp &prop = _filterMethod.Props[j];\n          if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)\n          {\n            UInt32 delta = (UInt32)prop.Value.ulVal;\n            if (delta < 1 || delta > 256)\n              return E_INVALIDARG;\n            filter.delta = delta;\n            deltaDefined = true;\n          }\n          else\n            return E_INVALIDARG;\n        }\n        if (!deltaDefined)\n          return E_INVALIDARG;\n      }\n      filter.id = _filterId;\n    }\n\n    FOR_VECTOR (i, _methods)\n    {\n      COneMethodInfo &m = _methods[i];\n\n      FOR_VECTOR (j, m.Props)\n      {\n        const CProp &prop = m.Props[j];\n        RINOK(encoder->SetCoderProp(prop.Id, prop.Value))\n      }\n    }\n\n    {\n      CMyComPtr<ISequentialInStream> fileInStream;\n      RINOK(updateCallback->GetStream(0, &fileInStream))\n      if (!fileInStream)\n        return S_FALSE;\n      {\n        CMyComPtr<IStreamGetSize> streamGetSize;\n        fileInStream.QueryInterface(IID_IStreamGetSize, &streamGetSize);\n        if (streamGetSize)\n        {\n          UInt64 size;\n          if (streamGetSize->GetSize(&size) == S_OK)\n            dataSize = size;\n        }\n      }\n      RINOK(updateCallback->SetTotal(dataSize))\n      CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n      lps->Init(updateCallback, true);\n      RINOK(encoder.Interface()->Code(fileInStream, outStream, NULL, NULL, lps))\n    }\n      \n    return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);\n  }\n\n  if (indexInArchive != 0)\n    return E_INVALIDARG;\n\n  Z7_DECL_CMyComPtr_QI_FROM(\n      IArchiveUpdateCallbackFile,\n      opCallback, updateCallback)\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(NEventIndexType::kInArcIndex, 0, NUpdateNotifyOp::kReplicate))\n  }\n\n  if (_stream)\n  {\n    const CXzStatInfo *stat = GetStat();\n    if (stat)\n    {\n      RINOK(updateCallback->SetTotal(stat->InSize))\n    }\n    RINOK(InStream_SeekToBegin(_stream))\n  }\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(updateCallback, true);\n\n  return NCompress::CopyStream(_stream, outStream, lps);\n\n  COM_TRY_END\n}\n\n#endif\n\n\nHRESULT CHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)\n{\n  UString name = nameSpec;\n  name.MakeLower_Ascii();\n  if (name.IsEmpty())\n    return E_INVALIDARG;\n  \n  #ifndef Z7_EXTRACT_ONLY\n\n  if (name[0] == L's')\n  {\n    const wchar_t *s = name.Ptr(1);\n    if (*s == 0)\n    {\n      bool useStr = false;\n      bool isSolid;\n      switch (value.vt)\n      {\n        case VT_EMPTY: isSolid = true; break;\n        case VT_BOOL: isSolid = (value.boolVal != VARIANT_FALSE); break;\n        case VT_BSTR:\n          if (!StringToBool(value.bstrVal, isSolid))\n            useStr = true;\n          break;\n        default: return E_INVALIDARG;\n      }\n      if (!useStr)\n      {\n        _numSolidBytes = (isSolid ? XZ_PROPS_BLOCK_SIZE_SOLID : XZ_PROPS_BLOCK_SIZE_AUTO);\n        return S_OK;\n      }\n    }\n    return ParseSizeString(s, value,\n        0, // percentsBase\n        _numSolidBytes) ? S_OK: E_INVALIDARG;\n  }\n\n  return CMultiMethodProps::SetProperty(name, value);\n\n  #else\n\n  {\n    HRESULT hres;\n    if (SetCommonProperty(name, value, hres))\n      return hres;\n  }\n\n  return E_INVALIDARG;\n  \n  #endif\n}\n\n\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  COM_TRY_BEGIN\n\n  Init();\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    RINOK(SetProperty(names[i], values[i]))\n  }\n\n  #ifndef Z7_EXTRACT_ONLY\n\n  if (!_filterMethod.MethodName.IsEmpty())\n  {\n    unsigned k;\n    for (k = 0; k < Z7_ARRAY_SIZE(g_NamePairs); k++)\n    {\n      const CMethodNamePair &pair = g_NamePairs[k];\n      if (StringsAreEqualNoCase_Ascii(_filterMethod.MethodName, pair.Name))\n      {\n        _filterId = pair.Id;\n        break;\n      }\n    }\n    if (k == Z7_ARRAY_SIZE(g_NamePairs))\n      return E_INVALIDARG;\n  }\n\n  _methods.DeleteFrontal(GetNumEmptyMethods());\n  if (_methods.Size() > 1)\n    return E_INVALIDARG;\n  if (_methods.Size() == 1)\n  {\n    AString &methodName = _methods[0].MethodName;\n    if (methodName.IsEmpty())\n      methodName = k_LZMA2_Name;\n    else if (\n        !methodName.IsEqualTo_Ascii_NoCase(k_LZMA2_Name)\n        && !methodName.IsEqualTo_Ascii_NoCase(\"xz\"))\n      return E_INVALIDARG;\n  }\n  \n  #endif\n\n  return S_OK;\n\n  COM_TRY_END\n}\n\n\nREGISTER_ARC_IO(\n  \"xz\", \"xz txz\", \"* .tar\", 0xC,\n  XZ_SIG, 0\n  , NArcInfoFlags::kKeepName\n  , 0\n  , NULL)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/XzHandler.h",
    "content": "﻿// XzHandler.h\n\n#ifndef ZIP7_INC_XZ_HANDLER_H\n#define ZIP7_INC_XZ_HANDLER_H\n\nnamespace NArchive {\nnamespace NXz {\n \n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/ZHandler.cpp",
    "content": "﻿// ZHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../Common/ProgressUtils.h\"\n#include \"../Common/RegisterArc.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"../Compress/ZDecoder.h\"\n\n#include \"Common/DummyOutStream.h\"\n\nnamespace NArchive {\nnamespace NZ {\n\nZ7_CLASS_IMP_CHandler_IInArchive_0\n\n  CMyComPtr<IInStream> _stream;\n  UInt64 _packSize;\n  // UInt64 _unpackSize;\n  // bool _unpackSize_Defined;\n};\n\nstatic const Byte kProps[] =\n{\n  kpidPackSize\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO_Table\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = 1;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidPhySizeCantBeDetected: prop = true; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))\n{\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    // case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;\n    case kpidPackSize: prop = _packSize; break;\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n/*\nZ7_CLASS_IMP_COM_1(\n  CCompressProgressInfoImp\n  , ICompressProgressInfo\n)\n  CMyComPtr<IArchiveOpenCallback> Callback;\npublic:\n  void Init(IArchiveOpenCallback *callback) { Callback = callback; }\n};\n\nZ7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  outSize = outSize;\n  if (Callback)\n  {\n    const UInt64 files = 1;\n    return Callback->SetCompleted(&files, inSize);\n  }\n  return S_OK;\n}\n*/\n\nAPI_FUNC_static_IsArc IsArc_Z(const Byte *p, size_t size)\n{\n  if (size < 3)\n    return k_IsArc_Res_NEED_MORE;\n  if (size > NCompress::NZ::kRecommendedCheckSize)\n      size = NCompress::NZ::kRecommendedCheckSize;\n  if (!NCompress::NZ::CheckStream(p, size))\n    return k_IsArc_Res_NO;\n  return k_IsArc_Res_YES;\n}\n}\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream,\n    const UInt64 * /* maxCheckStartPosition */,\n    IArchiveOpenCallback * /* openCallback */))\n{\n  COM_TRY_BEGIN\n  {\n    // RINOK(InStream_GetPos(stream, _streamStartPosition));\n    Byte buffer[NCompress::NZ::kRecommendedCheckSize];\n    // Byte buffer[1500];\n    size_t size = NCompress::NZ::kRecommendedCheckSize;\n    // size = 700;\n    RINOK(ReadStream(stream, buffer, &size))\n    if (!NCompress::NZ::CheckStream(buffer, size))\n      return S_FALSE;\n\n    UInt64 endPos;\n    RINOK(InStream_GetSize_SeekToEnd(stream, endPos))\n    _packSize = endPos;\n  \n    /*\n    bool fullCheck = false;\n    if (fullCheck)\n    {\n      CCompressProgressInfoImp *compressProgressSpec = new CCompressProgressInfoImp;\n      CMyComPtr<ICompressProgressInfo> compressProgress = compressProgressSpec;\n      compressProgressSpec->Init(openCallback);\n\n      NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;\n      CMyComPtr<ICompressCoder> decoder = decoderSpec;\n\n      CDummyOutStream *outStreamSpec = new CDummyOutStream;\n      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n      outStreamSpec->SetStream(NULL);\n      outStreamSpec->Init();\n      decoderSpec->SetProp(_prop);\n      if (openCallback)\n      {\n        UInt64 files = 1;\n        RINOK(openCallback->SetTotal(&files, &endPos));\n      }\n      RINOK(InStream_SeekSet(stream, _streamStartPosition + kSignatureSize))\n      HRESULT res = decoder->Code(stream, outStream, NULL, NULL, openCallback ? compressProgress : NULL);\n      if (res != S_OK)\n        return S_FALSE;\n      _packSize = decoderSpec->PackSize;\n    }\n    */\n    _stream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _packSize = 0;\n  // _unpackSize_Defined = false;\n  _stream.Release();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  if (numItems == 0)\n    return S_OK;\n  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))\n    return E_INVALIDARG;\n  RINOK(extractCallback->SetTotal(_packSize))\n  UInt64 currentTotalPacked = 0;\n  RINOK(extractCallback->SetCompleted(&currentTotalPacked))\n  \n  int opRes;\n  {\n  CMyComPtr<ISequentialOutStream> realOutStream;\n  const Int32 askMode = testMode ?\n      NExtract::NAskMode::kTest :\n      NExtract::NAskMode::kExtract;\n  \n  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))\n    \n  if (!testMode && !realOutStream)\n    return S_OK;\n\n  RINOK(extractCallback->PrepareOperation(askMode))\n\n  CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;\n  outStream->SetStream(realOutStream);\n  outStream->Init();\n  // realOutStream.Release();\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, true);\n  \n  RINOK(InStream_SeekToBegin(_stream))\n\n  NCompress::NZ::CDecoder decoder;\n  {\n    const HRESULT hres = decoder.Code(_stream, outStream, lps);\n    if (hres == S_FALSE)\n      opRes = NExtract::NOperationResult::kDataError;\n    else\n    {\n      RINOK(hres)\n      opRes = NExtract::NOperationResult::kOK;\n    }\n  }\n  // _unpackSize = outStreamSpec->GetSize();\n  // _unpackSize_Defined = true;\n  // outStream.Release();\n  }\n  return extractCallback->SetOperationResult(opRes);\n  COM_TRY_END\n}\n\nstatic const Byte k_Signature[] = { 0x1F, 0x9D };\n\nREGISTER_ARC_I(\n  \"Z\", \"z taz\", \"* .tar\", 5,\n  k_Signature,\n  0,\n  0,\n  IsArc_Z)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipAddCommon.cpp",
    "content": "﻿// ZipAddCommon.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/7zCrc.h\"\n#include \"../../../../C/Alloc.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"../../ICoder.h\"\n#include \"../../IPassword.h\"\n#include \"../../MyVersion.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/LzmaEncoder.h\"\n#include \"../../Compress/PpmdZip.h\"\n#include \"../../Compress/XzEncoder.h\"\n// **************** 7-Zip ZS Modification Start ****************\n#include \"../../../../../Extensions/ZSCodecs/ZstdEncoder.h\"\n// **************** 7-Zip ZS Modification End ****************\n\n#include \"../Common/InStreamWithCRC.h\"\n\n#include \"ZipAddCommon.h\"\n#include \"ZipHeader.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nusing namespace NFileHeader;\n\n\nstatic const unsigned kLzmaPropsSize = 5;\nstatic const unsigned kLzmaHeaderSize = 4 + kLzmaPropsSize;\n\nZ7_CLASS_IMP_NOQIB_3(\n  CLzmaEncoder\n  , ICompressCoder\n  , ICompressSetCoderProperties\n  , ICompressSetCoderPropertiesOpt\n)\npublic:\n  CMyComPtr2<ICompressCoder, NCompress::NLzma::CEncoder> Encoder;\n  Byte Header[kLzmaHeaderSize];\n};\n\nZ7_COM7F_IMF(CLzmaEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\n{\n  Encoder.Create_if_Empty();\n  CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStream;\n  outStream->Init(Header + 4, kLzmaPropsSize);\n  RINOK(Encoder->SetCoderProperties(propIDs, props, numProps))\n  RINOK(Encoder->WriteCoderProperties(outStream))\n  if (outStream->GetPos() != kLzmaPropsSize)\n    return E_FAIL;\n  Header[0] = MY_VER_MAJOR;\n  Header[1] = MY_VER_MINOR;\n  Header[2] = kLzmaPropsSize;\n  Header[3] = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CLzmaEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\n{\n  return Encoder->SetCoderPropertiesOpt(propIDs, props, numProps);\n}\n\nZ7_COM7F_IMF(CLzmaEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  RINOK(WriteStream(outStream, Header, kLzmaHeaderSize))\n  return Encoder.Interface()->Code(inStream, outStream, inSize, outSize, progress);\n}\n\n\nCAddCommon::CAddCommon():\n    _isLzmaEos(false),\n    _buf(NULL)\n    {}\n\nvoid CAddCommon::SetOptions(const CCompressionMethodMode &options)\n{\n  _options = options;\n}\n\nCAddCommon::~CAddCommon()\n{\n  MidFree(_buf);\n}\n\nstatic const UInt32 kBufSize = ((UInt32)1 << 16);\n\nHRESULT CAddCommon::CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC)\n{\n  if (!_buf)\n  {\n    _buf = (Byte *)MidAlloc(kBufSize);\n    if (!_buf)\n      return E_OUTOFMEMORY;\n  }\n\n  UInt32 crc = CRC_INIT_VAL;\n  for (;;)\n  {\n    UInt32 processed;\n    RINOK(inStream->Read(_buf, kBufSize, &processed))\n    if (processed == 0)\n    {\n      resultCRC = CRC_GET_DIGEST(crc);\n      return S_OK;\n    }\n    crc = CrcUpdate(crc, _buf, (size_t)processed);\n  }\n}\n\n\nHRESULT CAddCommon::Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,\n    CCompressingResult &opRes) const\n{\n  // We use Zip64, if unPackSize size is larger than 0xF8000000 to support\n  // cases when compressed size can be about 3% larger than uncompressed size\n\n  const UInt32 kUnpackZip64Limit = 0xF8000000;\n  \n  opRes.UnpackSize = unpackSize;\n  opRes.PackSize = (UInt64)1 << 60; // we use big value to force Zip64 mode.\n\n  if (unpackSize < kUnpackZip64Limit)\n    opRes.PackSize = (UInt32)0xFFFFFFFF - 1; // it will not use Zip64 for that size\n\n  if (opRes.PackSize < unpackSize)\n    opRes.PackSize = unpackSize;\n\n  const Byte method = _options.MethodSequence[0];\n\n  if (method == NCompressionMethod::kStore && !_options.Password_Defined)\n    opRes.PackSize = unpackSize;\n\n  opRes.CRC = 0;\n\n  opRes.LzmaEos = false;\n\n  opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;\n  opRes.DescriptorMode = outSeqMode;\n  \n  if (_options.Password_Defined)\n  {\n    opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;\n    if (_options.IsAesMode)\n      opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;\n    else\n    {\n      if (inSeqMode)\n        opRes.DescriptorMode = true;\n    }\n  }\n  \n  opRes.Method = method;\n  Byte ver = 0;\n  \n  switch (method)\n  {\n    case NCompressionMethod::kStore: break;\n    case NCompressionMethod::kDeflate: ver = NCompressionMethod::kExtractVersion_Deflate; break;\n    case NCompressionMethod::kDeflate64: ver = NCompressionMethod::kExtractVersion_Deflate64; break;\n    case NCompressionMethod::kXz   : ver = NCompressionMethod::kExtractVersion_Xz; break;\n    case NCompressionMethod::kPPMd : ver = NCompressionMethod::kExtractVersion_PPMd; break;\n    case NCompressionMethod::kBZip2: ver = NCompressionMethod::kExtractVersion_BZip2; break;\n    // **************** 7-Zip ZS Modification Start ****************\n    case NCompressionMethod::kZstd: ver = NCompressionMethod::kExtractVersion_Zstd; break;\n    // **************** 7-Zip ZS Modification End ****************\n    case NCompressionMethod::kLZMA :\n    {\n      ver = NCompressionMethod::kExtractVersion_LZMA;\n      const COneMethodInfo *oneMethodMain = &_options._methods[0];\n      opRes.LzmaEos = oneMethodMain->Get_Lzma_Eos();\n      break;\n    }\n    default: break;\n  }\n  if (opRes.ExtractVersion < ver)\n      opRes.ExtractVersion = ver;\n\n  return S_OK;\n}\n\n\nHRESULT CAddCommon::Compress(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    ISequentialInStream *inStream, IOutStream *outStream,\n    bool inSeqMode, bool outSeqMode,\n    UInt32 fileTime,\n    UInt64 expectedDataSize, bool expectedDataSize_IsConfirmed,\n    ICompressProgressInfo *progress, CCompressingResult &opRes)\n{\n  // opRes.LzmaEos = false;\n\n  if (!inStream)\n  {\n    // We can create empty stream here. But it was already implemented in caller code in 9.33+\n    return E_INVALIDARG;\n  }\n\n  CMyComPtr2_Create<ISequentialInStream, CSequentialInStreamWithCRC> inCrcStream;\n  \n  CMyComPtr<IInStream> inStream2;\n  if (!inSeqMode)\n  {\n    inStream->QueryInterface(IID_IInStream, (void **)&inStream2);\n    if (!inStream2)\n    {\n      // inSeqMode = true;\n      // inSeqMode must be correct before\n      return E_FAIL;\n    }\n  }\n\n  inCrcStream->SetStream(inStream);\n  inCrcStream->SetFullSize(expectedDataSize_IsConfirmed ? expectedDataSize : (UInt64)(Int64)-1);\n  // inCrcStream->Init();\n\n  unsigned numTestMethods = _options.MethodSequence.Size();\n  // numTestMethods != 0\n\n  bool descriptorMode = outSeqMode;\n  \n  // ZipCrypto without descriptor requires additional reading pass for\n  // inStream to calculate CRC for password check field.\n  // The descriptor allows to use ZipCrypto check field without CRC (InfoZip's modification).\n\n  if (!outSeqMode)\n    if (inSeqMode && _options.Password_Defined && !_options.IsAesMode)\n      descriptorMode = true;\n  opRes.DescriptorMode = descriptorMode;\n\n  if (numTestMethods > 1)\n    if (inSeqMode || outSeqMode || !inStream2)\n      numTestMethods = 1;\n\n  UInt32 crc = 0;\n  bool crc_IsCalculated = false;\n  \n  CFilterCoder::C_OutStream_Releaser outStreamReleaser;\n  // opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;\n  \n  for (unsigned i = 0; i < numTestMethods; i++)\n  {\n    inCrcStream->Init();\n\n    if (i != 0)\n    {\n      // if (inStream2)\n      {\n        RINOK(InStream_SeekToBegin(inStream2))\n      }\n      RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL))\n      RINOK(outStream->SetSize(0))\n    }\n\n    opRes.LzmaEos = false;\n    opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Default;\n\n    const Byte method = _options.MethodSequence[i];\n    if (method == NCompressionMethod::kStore && descriptorMode)\n    {\n      // we still can create descriptor_mode archives with \"Store\" method, but they are not good for 100%\n      return E_NOTIMPL;\n    }\n    \n    bool needCode = true;\n    \n    if (_options.Password_Defined)\n    {\n      opRes.ExtractVersion = NCompressionMethod::kExtractVersion_ZipCrypto;\n\n      if (!_cryptoStream.IsDefined())\n        _cryptoStream.SetFromCls(new CFilterCoder(true));\n      \n      if (_options.IsAesMode)\n      {\n        opRes.ExtractVersion = NCompressionMethod::kExtractVersion_Aes;\n        if (!_cryptoStream->Filter)\n        {\n          _cryptoStream->Filter = _filterAesSpec = new NCrypto::NWzAes::CEncoder;\n          _filterAesSpec->SetKeyMode(_options.AesKeyMode);\n          RINOK(_filterAesSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len()))\n        }\n        RINOK(_filterAesSpec->WriteHeader(outStream))\n      }\n      else\n      {\n        if (!_cryptoStream->Filter)\n        {\n          _cryptoStream->Filter = _filterSpec = new NCrypto::NZip::CEncoder;\n          _filterSpec->CryptoSetPassword((const Byte *)(const char *)_options.Password, _options.Password.Len());\n        }\n        \n        UInt32 check;\n        \n        if (descriptorMode)\n        {\n          // it's Info-ZIP modification for stream_mode descriptor_mode (bit 3 of the general purpose bit flag is set)\n          check = (fileTime & 0xFFFF);\n        }\n        else\n        {\n          if (!crc_IsCalculated)\n          {\n            RINOK(CalcStreamCRC(inStream, crc))\n            crc_IsCalculated = true;\n            RINOK(InStream_SeekToBegin(inStream2))\n            inCrcStream->Init();\n          }\n          check = (crc >> 16);\n        }\n        \n        RINOK(_filterSpec->WriteHeader_Check16(outStream, (UInt16)check))\n      }\n      \n      if (method == NCompressionMethod::kStore)\n      {\n        needCode = false;\n        RINOK(_cryptoStream->Code(inCrcStream, outStream, NULL, NULL, progress))\n      }\n      else\n      {\n        RINOK(_cryptoStream->SetOutStream(outStream))\n        RINOK(_cryptoStream->InitEncoder())\n        outStreamReleaser.FilterCoder = _cryptoStream.ClsPtr();\n      }\n    }\n\n    if (needCode)\n    {\n      switch (method)\n      {\n      case NCompressionMethod::kStore:\n      {\n        _copyCoder.Create_if_Empty();\n        CMyComPtr<ISequentialOutStream> outStreamNew;\n        if (_options.Password_Defined)\n          outStreamNew = _cryptoStream;\n        else\n          outStreamNew = outStream;\n        RINOK(_copyCoder.Interface()->Code(inCrcStream, outStreamNew, NULL, NULL, progress))\n        break;\n      }\n      \n      default:\n      {\n        if (!_compressEncoder)\n        {\n          CLzmaEncoder *_lzmaEncoder = NULL;\n          if (method == NCompressionMethod::kLZMA)\n          {\n            _compressExtractVersion = NCompressionMethod::kExtractVersion_LZMA;\n            _lzmaEncoder = new CLzmaEncoder();\n            _compressEncoder = _lzmaEncoder;\n          }\n          // **************** 7-Zip ZS Modification Start ****************\n          else if (method == NCompressionMethod::kZstd)\n          {\n            _compressExtractVersion = NCompressionMethod::kExtractVersion_Zstd;\n            NCompress::NZSTD::CEncoder *encoder = new NCompress::NZSTD::CEncoder();\n            _compressEncoder = encoder;\n          }\n          // **************** 7-Zip ZS Modification End ****************\n          else if (method == NCompressionMethod::kXz)\n          {\n            _compressExtractVersion = NCompressionMethod::kExtractVersion_Xz;\n            NCompress::NXz::CEncoder *encoder = new NCompress::NXz::CEncoder();\n              _compressEncoder = encoder;\n          }\n          else if (method == NCompressionMethod::kPPMd)\n          {\n            _compressExtractVersion = NCompressionMethod::kExtractVersion_PPMd;\n            NCompress::NPpmdZip::CEncoder *encoder = new NCompress::NPpmdZip::CEncoder();\n            _compressEncoder = encoder;\n          }\n          else\n          {\n          CMethodId methodId;\n          switch (method)\n          {\n            case NCompressionMethod::kBZip2:\n              methodId = kMethodId_BZip2;\n              _compressExtractVersion = NCompressionMethod::kExtractVersion_BZip2;\n              break;\n            default:\n              _compressExtractVersion = ((method == NCompressionMethod::kDeflate64) ?\n                  NCompressionMethod::kExtractVersion_Deflate64 :\n                  NCompressionMethod::kExtractVersion_Deflate);\n              methodId = kMethodId_ZipBase + method;\n              break;\n          }\n          RINOK(CreateCoder_Id(\n              EXTERNAL_CODECS_LOC_VARS\n              methodId, true, _compressEncoder))\n          if (!_compressEncoder)\n            return E_NOTIMPL;\n\n          if (method == NCompressionMethod::kDeflate ||\n              method == NCompressionMethod::kDeflate64)\n          {\n          }\n          else if (method == NCompressionMethod::kBZip2)\n          {\n          }\n          }\n          {\n            CMyComPtr<ICompressSetCoderProperties> setCoderProps;\n            _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProps);\n            if (setCoderProps)\n            {\n              if (!_options._methods.IsEmpty())\n              {\n                COneMethodInfo *oneMethodMain = &_options._methods[0];\n\n                RINOK(oneMethodMain->SetCoderProps(setCoderProps,\n                    _options.DataSizeReduce_Defined ? &_options.DataSizeReduce : NULL))\n              }\n            }\n          }\n          if (method == NCompressionMethod::kLZMA)\n            _isLzmaEos = _lzmaEncoder->Encoder->IsWriteEndMark();\n        }\n\n        if (method == NCompressionMethod::kLZMA)\n          opRes.LzmaEos = _isLzmaEos;\n\n        CMyComPtr<ISequentialOutStream> outStreamNew;\n        if (_options.Password_Defined)\n          outStreamNew = _cryptoStream;\n        else\n          outStreamNew = outStream;\n        if (_compressExtractVersion > opRes.ExtractVersion)\n          opRes.ExtractVersion = _compressExtractVersion;\n\n        {\n          CMyComPtr<ICompressSetCoderPropertiesOpt> optProps;\n          _compressEncoder->QueryInterface(IID_ICompressSetCoderPropertiesOpt, (void **)&optProps);\n          if (optProps)\n          {\n            const PROPID propID = NCoderPropID::kExpectedDataSize;\n            NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;\n            RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))\n          }\n        }\n        \n        try {\n        RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress))\n        } catch (...) { return E_FAIL; }\n        break;\n      }\n      } // switch end\n\n      if (_options.Password_Defined)\n      {\n        RINOK(_cryptoStream->OutStreamFinish())\n      }\n    }\n\n    if (_options.Password_Defined)\n    {\n      if (_options.IsAesMode)\n      {\n        RINOK(_filterAesSpec->WriteFooter(outStream))\n      }\n    }\n    \n    RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &opRes.PackSize))\n\n    {\n      opRes.CRC = inCrcStream->GetCRC();\n      opRes.UnpackSize = inCrcStream->GetSize();\n      opRes.Method = method;\n    }\n\n    if (!inCrcStream->WasFinished())\n      return E_FAIL;\n\n    if (_options.Password_Defined)\n    {\n      if (opRes.PackSize < opRes.UnpackSize +\n          (_options.IsAesMode ? _filterAesSpec->GetAddPackSize() : NCrypto::NZip::kHeaderSize))\n        break;\n    }\n    else if (opRes.PackSize < opRes.UnpackSize)\n      break;\n  }\n\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipAddCommon.h",
    "content": "﻿// ZipAddCommon.h\n\n#ifndef ZIP7_INC_ZIP_ADD_COMMON_H\n#define ZIP7_INC_ZIP_ADD_COMMON_H\n\n#include \"../../ICoder.h\"\n#include \"../../IProgress.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/FilterCoder.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"../../Crypto/ZipCrypto.h\"\n#include \"../../Crypto/WzAes.h\"\n\n#include \"ZipCompressionMode.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nstruct CCompressingResult\n{\n  UInt64 UnpackSize;\n  UInt64 PackSize;\n  UInt32 CRC;\n  UInt16 Method;\n  Byte ExtractVersion;\n  bool DescriptorMode;\n  bool LzmaEos;\n\n  CCompressingResult()\n  {\n    // for GCC:\n    UnpackSize = 0;\n  }\n};\n\nclass CAddCommon  MY_UNCOPYABLE\n{\n  CCompressionMethodMode _options;\n  CMyComPtr2<ICompressCoder, NCompress::CCopyCoder> _copyCoder;\n\n  CMyComPtr<ICompressCoder> _compressEncoder;\n  Byte _compressExtractVersion;\n  bool _isLzmaEos;\n\n  CMyComPtr2<ISequentialOutStream, CFilterCoder> _cryptoStream;\n\n  NCrypto::NZip::CEncoder *_filterSpec;\n  NCrypto::NWzAes::CEncoder *_filterAesSpec;\n\n  Byte *_buf;\n  \n  HRESULT CalcStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC);\npublic:\n  // CAddCommon(const CCompressionMethodMode &options);\n  CAddCommon();\n  void SetOptions(const CCompressionMethodMode &options);\n  ~CAddCommon();\n\n  HRESULT Set_Pre_CompressionResult(bool inSeqMode, bool outSeqMode, UInt64 unpackSize,\n      CCompressingResult &opRes) const;\n  \n  HRESULT Compress(\n      DECL_EXTERNAL_CODECS_LOC_VARS\n      ISequentialInStream *inStream, IOutStream *outStream,\n      bool inSeqMode, bool outSeqMode,\n      UInt32 fileTime,\n      UInt64 expectedDataSize, bool expectedDataSize_IsConfirmed,\n      ICompressProgressInfo *progress, CCompressingResult &opRes);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipCompressionMode.h",
    "content": "﻿// CompressionMode.h\n\n#ifndef ZIP7_INC_ZIP_COMPRESSION_MODE_H\n#define ZIP7_INC_ZIP_COMPRESSION_MODE_H\n\n#include \"../../../Common/MyString.h\"\n\n#ifndef Z7_ST\n#include \"../../../Windows/System.h\"\n#endif\n\n#include \"../Common/HandlerOut.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nconst CMethodId kMethodId_ZipBase = 0x040100;\nconst CMethodId kMethodId_BZip2   = 0x040202;\n\nstruct CBaseProps: public CMultiMethodProps\n{\n  bool IsAesMode;\n  Byte AesKeyMode;\n\n  void Init()\n  {\n    CMultiMethodProps::Init();\n    \n    IsAesMode = false;\n    AesKeyMode = 3;\n  }\n};\n\nstruct CCompressionMethodMode: public CBaseProps\n{\n  CRecordVector<Byte> MethodSequence;\n  AString Password; // _Wipe\n  bool Password_Defined;\n  bool Force_SeqOutMode;\n  bool DataSizeReduce_Defined;\n  UInt64 DataSizeReduce;\n\n  bool IsRealAesMode() const { return Password_Defined && IsAesMode; }\n\n  CCompressionMethodMode()\n  {\n    Password_Defined = false;\n    Force_SeqOutMode = false;\n    DataSizeReduce_Defined = false;\n    DataSizeReduce = 0;\n  }\n\n#ifdef Z7_CPP_IS_SUPPORTED_default\n  CCompressionMethodMode(const CCompressionMethodMode &) = default;\n  CCompressionMethodMode& operator =(const CCompressionMethodMode &) = default;\n#endif\n  ~CCompressionMethodMode() { Password.Wipe_and_Empty(); }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipHandler.cpp",
    "content": "﻿// ZipHandler.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/PropVariantUtils.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../IPassword.h\"\n\n#include \"../../Common/FilterCoder.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamObjects.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n#ifndef Z7_ZIP_LZFSE_DISABLE\n#include \"../../Compress/LzfseDecoder.h\"\n#endif\n#include \"../../Compress/LzmaDecoder.h\"\n#include \"../../Compress/ImplodeDecoder.h\"\n#include \"../../Compress/PpmdZip.h\"\n#include \"../../Compress/ShrinkDecoder.h\"\n#include \"../../Compress/XzDecoder.h\"\n// **************** 7-Zip ZS Modification Start ****************\n// #include \"../../Compress/ZstdDecoder.h\"\n// **************** 7-Zip ZS Modification End ****************\n#include \"../../../../../Extensions/ZSCodecs/ZstdDecoder.h\"\n\n#include \"../../Crypto/WzAes.h\"\n#include \"../../Crypto/ZipCrypto.h\"\n#include \"../../Crypto/ZipStrong.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n#include \"../Common/OutStreamWithCRC.h\"\n\n\n#include \"ZipHandler.h\"\n\nusing namespace NWindows;\n\nnamespace NArchive {\nnamespace NZip {\n\nstatic const char * const kHostOS[] =\n{\n    \"FAT\"\n  , \"AMIGA\"\n  , \"VMS\"\n  , \"Unix\"\n  , \"VM/CMS\"\n  , \"Atari\"\n  , \"HPFS\"\n  , \"Macintosh\"\n  , \"Z-System\"\n  , \"CP/M\"\n  , \"TOPS-20\"\n  , \"NTFS\"\n  , \"SMS/QDOS\"\n  , \"Acorn\"\n  , \"VFAT\"\n  , \"MVS\"\n  , \"BeOS\"\n  , \"Tandem\"\n  , \"OS/400\"\n  , \"OS/X\"\n};\n\n\nconst char * const kMethodNames1[kNumMethodNames1] =\n{\n    \"Store\"\n  , \"Shrink\"\n  , \"Reduce1\"\n  , \"Reduce2\"\n  , \"Reduce3\"\n  , \"Reduce4\"\n  , \"Implode\"\n  , NULL // \"Tokenize\"\n  , \"Deflate\"\n  , \"Deflate64\"\n  , \"PKImploding\"\n  , NULL\n  , \"BZip2\"\n  , NULL\n  , \"LZMA\"\n  /*\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , NULL\n  , \"zstd-pk\" // deprecated\n  */\n};\n\n\nconst char * const kMethodNames2[kNumMethodNames2] =\n{\n    \"zstd\"\n  , \"MP3\"\n  , \"xz\"\n  , \"Jpeg\"\n  , \"WavPack\"\n  , \"PPMd\"\n  , \"LZFSE\" // , \"WzAES\"\n};\n\n#define kMethod_AES \"AES\"\n#define kMethod_ZipCrypto \"ZipCrypto\"\n#define kMethod_StrongCrypto \"StrongCrypto\"\n\nstatic const char * const kDeflateLevels[4] =\n{\n    \"Normal\"\n  , \"Maximum\"\n  , \"Fast\"\n  , \"Fastest\"\n};\n\n\nstatic const CUInt32PCharPair g_HeaderCharacts[] =\n{\n  { 0, \"Encrypt\" },\n  { 3, \"Descriptor\" },\n  // { 4, \"Enhanced\" },\n  // { 5, \"Patched\" },\n  { 6, kMethod_StrongCrypto },\n  { 11, \"UTF8\" },\n  { 14, \"Alt\" }\n};\n\nstruct CIdToNamePair\n{\n  unsigned Id;\n  const char *Name;\n};\n\n\nstatic const CIdToNamePair k_StrongCryptoPairs[] =\n{\n  { NStrongCrypto_AlgId::kDES, \"DES\" },\n  { NStrongCrypto_AlgId::kRC2old, \"RC2a\" },\n  { NStrongCrypto_AlgId::k3DES168, \"3DES-168\" },\n  { NStrongCrypto_AlgId::k3DES112, \"3DES-112\" },\n  { NStrongCrypto_AlgId::kAES128, \"pkAES-128\" },\n  { NStrongCrypto_AlgId::kAES192, \"pkAES-192\" },\n  { NStrongCrypto_AlgId::kAES256, \"pkAES-256\" },\n  { NStrongCrypto_AlgId::kRC2, \"RC2\" },\n  { NStrongCrypto_AlgId::kBlowfish, \"Blowfish\" },\n  { NStrongCrypto_AlgId::kTwofish, \"Twofish\" },\n  { NStrongCrypto_AlgId::kRC4, \"RC4\" }\n};\n\nstatic const char *FindNameForId(const CIdToNamePair *pairs, unsigned num, unsigned id)\n{\n  for (unsigned i = 0; i < num; i++)\n  {\n    const CIdToNamePair &pair = pairs[i];\n    if (id == pair.Id)\n      return pair.Name;\n  }\n  return NULL;\n}\n\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidMTime,\n  kpidCTime,\n  kpidATime,\n  kpidAttrib,\n  // kpidPosixAttrib,\n  kpidEncrypted,\n  kpidComment,\n  kpidCRC,\n  kpidMethod,\n  kpidCharacts,\n  kpidHostOS,\n  kpidUnpackVer,\n  kpidVolumeIndex,\n  kpidOffset\n  // kpidIsAltStream\n  // , kpidChangeTime // for debug\n  // , 255  // for debug\n};\n\nstatic const Byte kArcProps[] =\n{\n  kpidEmbeddedStubSize,\n  kpidBit64,\n  kpidComment,\n  kpidCharacts,\n  kpidTotalPhySize,\n  kpidIsVolume,\n  kpidVolumeIndex,\n  kpidNumVolumes\n};\n\nCHandler::CHandler()\n{\n  InitMethodProps();\n}\n\nstatic AString BytesToString(const CByteBuffer &data)\n{\n  AString s;\n  s.SetFrom_CalcLen((const char *)(const Byte *)data, (unsigned)data.Size());\n  return s;\n}\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps\n\nZ7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  switch (propID)\n  {\n    case kpidBit64:  if (m_Archive.IsZip64) prop = m_Archive.IsZip64; break;\n    case kpidComment:  if (m_Archive.ArcInfo.Comment.Size() != 0) prop = MultiByteToUnicodeString(BytesToString(m_Archive.ArcInfo.Comment), CP_ACP); break;\n\n    case kpidPhySize:  prop = m_Archive.GetPhySize(); break;\n    case kpidOffset:  prop = m_Archive.GetOffset(); break;\n\n    case kpidEmbeddedStubSize:\n    {\n      UInt64 stubSize = m_Archive.GetEmbeddedStubSize();\n      if (stubSize != 0)\n        prop = stubSize;\n      break;\n    }\n\n    case kpidTotalPhySize: if (m_Archive.IsMultiVol) prop = m_Archive.Vols.TotalBytesSize; break;\n    case kpidVolumeIndex: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.StartVolIndex; break;\n    case kpidIsVolume: if (m_Archive.IsMultiVol) prop = true; break;\n    case kpidNumVolumes: if (m_Archive.IsMultiVol) prop = (UInt32)m_Archive.Vols.Streams.Size(); break;\n\n    case kpidCharacts:\n    {\n      AString s;\n      \n      if (m_Archive.LocalsWereRead)\n      {\n        s.Add_OptSpaced(\"Local\");\n\n        if (m_Archive.LocalsCenterMerged)\n          s.Add_OptSpaced(\"Central\");\n      }\n\n      if (m_Archive.IsZip64)\n        s.Add_OptSpaced(\"Zip64\");\n\n      if (m_Archive.IsCdUnsorted)\n        s.Add_OptSpaced(\"Unsorted_CD\");\n\n      if (m_Archive.IsApk)\n        s.Add_OptSpaced(\"apk\");\n\n      if (m_Archive.ExtraMinorError)\n        s.Add_OptSpaced(\"Minor_Extra_ERROR\");\n\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidWarningFlags:\n    {\n      UInt32 v = 0;\n      // if (m_Archive.ExtraMinorError) v |= kpv_ErrorFlags_HeadersError;\n      if (m_Archive.HeadersWarning) v |= kpv_ErrorFlags_HeadersError;\n      if (v != 0)\n        prop = v;\n      break;\n    }\n\n    case kpidWarning:\n    {\n      AString s;\n      if (m_Archive.Overflow32bit)\n        s.Add_OptSpaced(\"32-bit overflow in headers\");\n      if (m_Archive.Cd_NumEntries_Overflow_16bit)\n        s.Add_OptSpaced(\"16-bit overflow for number of files in headers\");\n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidError:\n    {\n      if (!m_Archive.Vols.MissingName.IsEmpty())\n      {\n        UString s(\"Missing volume : \");\n        s += m_Archive.Vols.MissingName;\n        prop = s;\n      }\n      break;\n    }\n\n    case kpidErrorFlags:\n    {\n      UInt32 v = 0;\n      if (!m_Archive.IsArc) v |= kpv_ErrorFlags_IsNotArc;\n      if (m_Archive.HeadersError) v |= kpv_ErrorFlags_HeadersError;\n      if (m_Archive.UnexpectedEnd) v |= kpv_ErrorFlags_UnexpectedEnd;\n      if (m_Archive.ArcInfo.Base < 0)\n      {\n        /* We try to support case when we have sfx-zip with embedded stub,\n           but the stream has access only to zip part.\n           In that case we ignore UnavailableStart error.\n           maybe we must show warning in that case. */\n        UInt64 stubSize = m_Archive.GetEmbeddedStubSize();\n        if (stubSize < (UInt64)-m_Archive.ArcInfo.Base)\n          v |= kpv_ErrorFlags_UnavailableStart;\n      }\n      if (m_Archive.NoCentralDir) v |= kpv_ErrorFlags_UnconfirmedStart;\n      prop = v;\n      break;\n    }\n\n    case kpidReadOnly:\n    {\n      if (m_Archive.IsOpen())\n        if (!m_Archive.CanUpdate())\n          prop = true;\n      break;\n    }\n\n    // case kpidIsAltStream: prop = true; break;\n    default: break;\n  }\n  return prop.Detach(value);\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = m_Items.Size();\n  return S_OK;\n}\n\n\nstatic bool NtfsUnixTimeToProp(bool fromCentral,\n    const CExtraBlock &extra,\n    unsigned ntfsIndex, unsigned unixIndex, NWindows::NCOM::CPropVariant &prop)\n{\n  {\n    FILETIME ft;\n    if (extra.GetNtfsTime(ntfsIndex, ft))\n    {\n      PropVariant_SetFrom_NtfsTime(prop, ft);\n      return true;\n    }\n  }\n  {\n    UInt32 unixTime = 0;\n    if (!extra.GetUnixTime(fromCentral, unixIndex, unixTime))\n      return false;\n    /*\n    // we allow unixTime == 0\n    if (unixTime == 0)\n      return false;\n    */\n    PropVariant_SetFrom_UnixTime(prop, unixTime);\n    return true;\n  }\n}\n\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NWindows::NCOM::CPropVariant prop;\n  const CItemEx &item = m_Items[index];\n  const CExtraBlock &extra = item.GetMainExtra();\n  \n  switch (propID)\n  {\n    case kpidPath:\n    {\n      UString res;\n      item.GetUnicodeString(res, item.Name, false, _forceCodePage, _specifiedCodePage);\n      NItemName::ReplaceToOsSlashes_Remove_TailSlash(res,\n          item.Is_MadeBy_Unix() // useBackslashReplacement\n          );\n      /*\n      if (item.ParentOfAltStream >= 0)\n      {\n        const CItemEx &prevItem = m_Items[item.ParentOfAltStream];\n        UString prevName;\n        prevItem.GetUnicodeString(prevName, prevItem.Name, false, _forceCodePage, _specifiedCodePage);\n        NItemName::ReplaceToOsSlashes_Remove_TailSlash(prevName);\n        if (res.IsPrefixedBy(prevName))\n          if (IsString1PrefixedByString2(res.Ptr(prevName.Len()), k_SpecName_NTFS_STREAM))\n          {\n            res.Delete(prevName.Len(), (unsigned)strlen(k_SpecName_NTFS_STREAM));\n            res.Insert(prevName.Len(), L\":\");\n          }\n      }\n      */\n      prop = res;\n      break;\n    }\n    \n    case kpidIsDir:  prop = item.IsDir(); break;\n    case kpidSize:\n    {\n      if (!item.IsBadDescriptor())\n        prop = item.Size;\n      break;\n    }\n\n    case kpidPackSize:  prop = item.PackSize; break;\n    \n    case kpidCTime:\n      NtfsUnixTimeToProp(item.FromCentral, extra,\n          NFileHeader::NNtfsExtra::kCTime,\n          NFileHeader::NUnixTime::kCTime, prop);\n      break;\n    \n    case kpidATime:\n      NtfsUnixTimeToProp(item.FromCentral, extra,\n          NFileHeader::NNtfsExtra::kATime,\n          NFileHeader::NUnixTime::kATime, prop);\n      break;\n    \n    case kpidMTime:\n    {\n      if (!NtfsUnixTimeToProp(item.FromCentral, extra,\n          NFileHeader::NNtfsExtra::kMTime,\n          NFileHeader::NUnixTime::kMTime, prop))\n      {\n        if (item.Time != 0)\n          PropVariant_SetFrom_DosTime(prop, item.Time);\n      }\n      break;\n    }\n\n    case kpidTimeType:\n    {\n      FILETIME ft;\n      UInt32 unixTime;\n      UInt32 type;\n      if (extra.GetNtfsTime(NFileHeader::NNtfsExtra::kMTime, ft))\n        type = NFileTimeType::kWindows;\n      else if (extra.GetUnixTime(item.FromCentral, NFileHeader::NUnixTime::kMTime, unixTime))\n        type = NFileTimeType::kUnix;\n      else\n        type = NFileTimeType::kDOS;\n      prop = type;\n      break;\n    }\n    \n    /*\n    // for debug to get Dos time values:\n    case kpidChangeTime: if (item.Time != 0) PropVariant_SetFrom_DosTime(prop, item.Time); break;\n    // for debug\n    // time difference (dos - utc)\n    case 255:\n    {\n      if (NtfsUnixTimeToProp(item.FromCentral, extra,\n          NFileHeader::NNtfsExtra::kMTime,\n          NFileHeader::NUnixTime::kMTime, prop))\n      {\n        FILETIME localFileTime;\n        if (item.Time != 0 && NTime::DosTime_To_FileTime(item.Time, localFileTime))\n        {\n          UInt64 t1 = FILETIME_To_UInt64(prop.filetime);\n          UInt64 t2 = FILETIME_To_UInt64(localFileTime);\n          prop.Set_Int64(t2 - t1);\n        }\n      }\n      break;\n    }\n    */\n    \n    case kpidAttrib:  prop = item.GetWinAttrib(); break;\n    \n    case kpidPosixAttrib:\n    {\n      UInt32 attrib;\n      if (item.GetPosixAttrib(attrib))\n        prop = attrib;\n      break;\n    }\n    \n    case kpidEncrypted:  prop = item.IsEncrypted(); break;\n    \n    case kpidComment:\n    {\n      if (item.Comment.Size() != 0)\n      {\n        UString res;\n        item.GetUnicodeString(res, BytesToString(item.Comment), true, _forceCodePage, _specifiedCodePage);\n        prop = res;\n      }\n      break;\n    }\n    \n    case kpidCRC:  if (item.IsThereCrc()) prop = item.Crc; break;\n    \n    case kpidMethod:\n    {\n      AString m;\n      bool isWzAes = false;\n      unsigned id = item.Method;\n\n      if (id == NFileHeader::NCompressionMethod::kWzAES)\n      {\n        CWzAesExtra aesField;\n        if (extra.GetWzAes(aesField))\n        {\n          m += kMethod_AES;\n          m.Add_Minus();\n          m.Add_UInt32(((unsigned)aesField.Strength + 1) * 64);\n          id = aesField.Method;\n          isWzAes = true;\n        }\n      }\n      \n      if (item.IsEncrypted())\n      if (!isWzAes)\n      {\n        if (item.IsStrongEncrypted())\n        {\n          CStrongCryptoExtra f;\n          f.AlgId = 0;\n          if (extra.GetStrongCrypto(f))\n          {\n            const char *s = FindNameForId(k_StrongCryptoPairs, Z7_ARRAY_SIZE(k_StrongCryptoPairs), f.AlgId);\n            if (s)\n              m += s;\n            else\n            {\n              m += kMethod_StrongCrypto;\n              m.Add_Colon();\n              m.Add_UInt32(f.AlgId);\n            }\n            if (f.CertificateIsUsed())\n              m += \"-Cert\";\n          }\n          else\n            m += kMethod_StrongCrypto;\n        }\n        else\n          m += kMethod_ZipCrypto;\n      }\n\n      m.Add_Space_if_NotEmpty();\n      \n      {\n        const char *s = NULL;\n        if (id < kNumMethodNames1)\n          s = kMethodNames1[id];\n        else\n        {\n          const int id2 = (int)id - (int)kMethodNames2Start;\n          if (id2 >= 0 && (unsigned)id2 < kNumMethodNames2)\n            s = kMethodNames2[id2];\n        }\n        if (s)\n          m += s;\n        else\n          m.Add_UInt32(id);\n      }\n      {\n        unsigned level = item.GetDeflateLevel();\n        if (level != 0)\n        {\n          if (id == NFileHeader::NCompressionMethod::kLZMA)\n          {\n            if (level & 1)\n              m += \":eos\";\n            level &= ~(unsigned)1;\n          }\n          else if (id == NFileHeader::NCompressionMethod::kDeflate)\n          {\n            m.Add_Colon();\n            m += kDeflateLevels[level];\n            level = 0;\n          }\n\n          if (level != 0)\n          {\n            m += \":v\";\n            m.Add_UInt32(level);\n          }\n        }\n      }\n      \n      prop = m;\n      break;\n    }\n\n    case kpidCharacts:\n    {\n      AString s;\n      \n      if (item.FromLocal)\n      {\n        s.Add_OptSpaced(\"Local\");\n\n        item.LocalExtra.PrintInfo(s);\n\n        if (item.FromCentral)\n        {\n          s.Add_OptSpaced(\":\");\n          s.Add_OptSpaced(\"Central\");\n        }\n      }\n\n      if (item.FromCentral)\n      {\n        item.CentralExtra.PrintInfo(s);\n      }\n\n      UInt32 flags = item.Flags;\n      flags &= ~(unsigned)6; // we don't need compression related bits here.\n\n      if (flags != 0)\n      {\n        const AString s2 = FlagsToString(g_HeaderCharacts, Z7_ARRAY_SIZE(g_HeaderCharacts), flags);\n        if (!s2.IsEmpty())\n        {\n          if (!s.IsEmpty())\n            s.Add_OptSpaced(\":\");\n          s.Add_OptSpaced(s2);\n        }\n      }\n\n      if (item.IsBadDescriptor())\n        s.Add_OptSpaced(\"Descriptor_ERROR\");\n    \n      if (!s.IsEmpty())\n        prop = s;\n      break;\n    }\n\n    case kpidHostOS:\n    {\n      if (item.FromCentral)\n      {\n        // 18.06: now we use HostOS only from Central::MadeByVersion\n        const Byte hostOS = item.MadeByVersion.HostOS;\n        TYPE_TO_PROP(kHostOS, hostOS, prop);\n      }\n      break;\n    }\n    \n    case kpidUnpackVer:\n      prop = (UInt32)item.ExtractVersion.Version;\n      break;\n\n    case kpidVolumeIndex:\n      prop = item.Disk;\n      break;\n\n    case kpidOffset:\n      prop = item.LocalHeaderPos;\n      break;\n\n    /*\n    case kpidIsAltStream:\n      prop = (bool)(item.ParentOfAltStream >= 0); // item.IsAltStream();\n      break;\n\n    case kpidName:\n      if (item.ParentOfAltStream >= 0)\n      {\n        // extract name of stream here\n      }\n      break;\n    */\n    default: break;\n  }\n  \n  return prop.Detach(value);\n  COM_TRY_END\n}\n\n\n\n/*\nZ7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps)\n{\n  *numProps = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)\n{\n  UNUSED_VAR(index);\n  *propID = 0;\n  *name = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)\n{\n  *parentType = NParentType::kDir;\n  *parent = (UInt32)(Int32)-1;\n  if (index >= m_Items.Size())\n    return S_OK;\n  const CItemEx &item = m_Items[index];\n\n  if (item.ParentOfAltStream >= 0)\n  {\n    *parentType = NParentType::kAltStream;\n    *parent = item.ParentOfAltStream;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)\n{\n  UNUSED_VAR(index);\n  UNUSED_VAR(propID);\n  *data = NULL;\n  *dataSize = 0;\n  *propType = 0;\n  return S_OK;\n}\n\n\nvoid CHandler::MarkAltStreams(CObjectVector<CItemEx> &items)\n{\n  int prevIndex = -1;\n  UString prevName;\n  UString name;\n\n  for (unsigned i = 0; i < items.Size(); i++)\n  {\n    CItemEx &item = m_Items[i];\n    if (item.IsAltStream())\n    {\n      if (prevIndex == -1)\n        continue;\n      if (prevName.IsEmpty())\n      {\n        const CItemEx &prevItem = m_Items[prevIndex];\n        prevItem.GetUnicodeString(prevName, prevItem.Name, false, _forceCodePage, _specifiedCodePage);\n        NItemName::ReplaceToOsSlashes_Remove_TailSlash(prevName);\n      }\n      name.Empty();\n      item.GetUnicodeString(name, item.Name, false, _forceCodePage, _specifiedCodePage);\n      NItemName::ReplaceToOsSlashes_Remove_TailSlash(name);\n      \n      if (name.IsPrefixedBy(prevName))\n        if (IsString1PrefixedByString2(name.Ptr(prevName.Len()), k_SpecName_NTFS_STREAM))\n          item.ParentOfAltStream = prevIndex;\n    }\n    else\n    {\n      prevIndex = i;\n      prevName.Empty();\n    }\n  }\n}\n*/\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *inStream,\n    const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback))\n{\n  COM_TRY_BEGIN\n  try\n  {\n    Close();\n    m_Archive.Force_ReadLocals_Mode = _force_OpenSeq;\n    // m_Archive.Disable_VolsRead = _force_OpenSeq;\n    // m_Archive.Disable_FindMarker = _force_OpenSeq;\n    HRESULT res = m_Archive.Open(inStream, maxCheckStartPosition, callback, m_Items);\n    if (res != S_OK)\n    {\n      m_Items.Clear();\n      m_Archive.ClearRefs(); // we don't want to clear error flags\n    }\n    // MarkAltStreams(m_Items);\n    return res;\n  }\n  catch(...) { Close(); throw; }\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  m_Items.Clear();\n  m_Archive.Close();\n  return S_OK;\n}\n\n\nZ7_CLASS_IMP_NOQIB_3(\n  CLzmaDecoder\n  , ICompressCoder\n  , ICompressSetFinishMode\n  , ICompressGetInStreamProcessedSize\n)\npublic:\n  CMyComPtr2_Create<ICompressCoder, NCompress::NLzma::CDecoder> Decoder;\n};\n\nstatic const unsigned kZipLzmaPropsSize = 4 + LZMA_PROPS_SIZE;\n\nZ7_COM7F_IMF(CLzmaDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  Byte buf[kZipLzmaPropsSize];\n  RINOK(ReadStream_FALSE(inStream, buf, kZipLzmaPropsSize))\n  if (buf[2] != LZMA_PROPS_SIZE || buf[3] != 0)\n    return E_NOTIMPL;\n  RINOK(Decoder->SetDecoderProperties2(buf + 4, LZMA_PROPS_SIZE))\n  UInt64 inSize2 = 0;\n  if (inSize)\n  {\n    inSize2 = *inSize;\n    if (inSize2 < kZipLzmaPropsSize)\n      return S_FALSE;\n    inSize2 -= kZipLzmaPropsSize;\n  }\n  return Decoder.Interface()->Code(inStream, outStream, inSize ? &inSize2 : NULL, outSize, progress);\n}\n\nZ7_COM7F_IMF(CLzmaDecoder::SetFinishMode(UInt32 finishMode))\n{\n  Decoder->FinishStream = (finishMode != 0);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CLzmaDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = Decoder->GetInputProcessedSize() + kZipLzmaPropsSize;\n  return S_OK;\n}\n\n\n\n\n\n\n\nstruct CMethodItem\n{\n  unsigned ZipMethod;\n  CMyComPtr<ICompressCoder> Coder;\n};\n\n\n\nclass CZipDecoder\n{\n  CMyComPtr2<ICompressFilter, NCrypto::NZip::CDecoder> _zipCryptoDecoder;\n  CMyComPtr2<ICompressFilter, NCrypto::NZipStrong::CDecoder> _pkAesDecoder;\n  CMyComPtr2<ICompressFilter, NCrypto::NWzAes::CDecoder> _wzAesDecoder;\n\n  CMyComPtr2<ISequentialInStream, CFilterCoder> filterStream;\n  CMyComPtr<ICryptoGetTextPassword> getTextPassword;\n  CObjectVector<CMethodItem> methodItems;\n\n  CLzmaDecoder *lzmaDecoderSpec;\npublic:\n  CZipDecoder():\n      lzmaDecoderSpec(NULL)\n    {}\n\n  HRESULT Decode(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CInArchive &archive, const CItemEx &item,\n    ISequentialOutStream *realOutStream,\n    IArchiveExtractCallback *extractCallback,\n    ICompressProgressInfo *compressProgress,\n    #ifndef Z7_ST\n    UInt32 numThreads, UInt64 memUsage,\n    #endif\n    Int32 &res);\n};\n\n\nstatic HRESULT SkipStreamData(ISequentialInStream *stream,\n    ICompressProgressInfo *progress, UInt64 packSize, UInt64 unpackSize,\n    bool &thereAreData)\n{\n  thereAreData = false;\n  const size_t kBufSize = 1 << 12;\n  Byte buf[kBufSize];\n  UInt64 prev = packSize;\n  for (;;)\n  {\n    size_t size = kBufSize;\n    RINOK(ReadStream(stream, buf, &size))\n    if (size == 0)\n      return S_OK;\n    thereAreData = true;\n    packSize += size;\n    if ((packSize - prev) >= (1 << 22))\n    {\n      prev = packSize;\n      RINOK(progress->SetRatioInfo(&packSize, &unpackSize))\n    }\n  }\n}\n\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithPadPKCS7\n  , ISequentialOutStream\n)\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\n  UInt64 _padPos;\n  UInt32 _padSize;\n  bool _padFailure;\npublic:\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n\n  // padSize == 0 means (no_pad Mode)\n  void Init(UInt64 padPos, UInt32 padSize)\n  {\n    _padPos = padPos;\n    _padSize = padSize;\n    _size = 0;\n    _padFailure = false;\n  }\n  UInt64 GetSize() const { return _size; }\n  bool WasPadFailure() const { return _padFailure; }\n};\n\n\nZ7_COM7F_IMF(COutStreamWithPadPKCS7::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 written = 0;\n  HRESULT result = S_OK;\n  if (_size < _padPos)\n  {\n    const UInt64 rem = _padPos - _size;\n    UInt32 num = size;\n    if (num > rem)\n      num = (UInt32)rem;\n    result = _stream->Write(data, num, &written);\n    _size += written;\n    if (processedSize)\n      *processedSize = written;\n    if (_size != _padPos || result != S_OK)\n      return result;\n    size -= written;\n    data = ((const Byte *)data) + written;\n  }\n  _size += size;\n  written += size;\n  if (processedSize)\n    *processedSize = written;\n  if (_padSize != 0)\n  for (; size != 0; size--)\n  {\n    if (*(const Byte *)data != _padSize)\n      _padFailure = true;\n    data = ((const Byte *)data) + 1;\n  }\n  return result;\n}\n\n\n\nHRESULT CZipDecoder::Decode(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CInArchive &archive, const CItemEx &item,\n    ISequentialOutStream *realOutStream,\n    IArchiveExtractCallback *extractCallback,\n    ICompressProgressInfo *compressProgress,\n    #ifndef Z7_ST\n    UInt32 numThreads, UInt64 memUsage,\n    #endif\n    Int32 &res)\n{\n  res = NExtract::NOperationResult::kHeadersError;\n  \n  CFilterCoder::C_InStream_Releaser inStreamReleaser;\n  CFilterCoder::C_Filter_Releaser filterReleaser;\n\n  bool needCRC = true;\n  bool wzAesMode = false;\n  bool pkAesMode = false;\n\n  bool badDescriptor = item.IsBadDescriptor();\n  if (badDescriptor)\n    needCRC = false;\n\n  \n  unsigned id = item.Method;\n\n  CWzAesExtra aesField;\n  // LZFSE and WinZip's AES use same id - kWzAES.\n\n  if (id == NFileHeader::NCompressionMethod::kWzAES)\n  {\n    if (item.GetMainExtra().GetWzAes(aesField))\n    {\n      if (!item.IsEncrypted())\n      {\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n        return S_OK;\n      }\n      wzAesMode = true;\n      needCRC = aesField.NeedCrc();\n    }\n  }\n\n  if (!wzAesMode)\n  if (item.IsEncrypted())\n  {\n    if (item.IsStrongEncrypted())\n    {\n      CStrongCryptoExtra f;\n      if (!item.CentralExtra.GetStrongCrypto(f))\n      {\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n        return S_OK;\n      }\n      pkAesMode = true;\n    }\n  }\n\n  CMyComPtr2_Create<ISequentialOutStream, COutStreamWithCRC> outStream;\n  outStream->SetStream(realOutStream);\n  outStream->Init(needCRC);\n  \n  CMyComPtr<ISequentialInStream> packStream;\n  CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStream;\n\n  {\n    UInt64 packSize = item.PackSize;\n    if (wzAesMode)\n    {\n      if (packSize < NCrypto::NWzAes::kMacSize)\n        return S_OK;\n      packSize -= NCrypto::NWzAes::kMacSize;\n    }\n    RINOK(archive.GetItemStream(item, true, packStream))\n    if (!packStream)\n    {\n      res = NExtract::NOperationResult::kUnavailable;\n      return S_OK;\n    }\n    inStream->SetStream(packStream);\n    inStream->Init(packSize);\n  }\n\n  \n  res = NExtract::NOperationResult::kDataError;\n  \n  CMyComPtr<ICompressFilter> cryptoFilter;\n  \n  if (item.IsEncrypted())\n  {\n    if (wzAesMode)\n    {\n      id = aesField.Method;\n      _wzAesDecoder.Create_if_Empty();\n      cryptoFilter = _wzAesDecoder;\n      if (!_wzAesDecoder->SetKeyMode(aesField.Strength))\n      {\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n        return S_OK;\n      }\n    }\n    else if (pkAesMode)\n    {\n      _pkAesDecoder.Create_if_Empty();\n      cryptoFilter = _pkAesDecoder;\n    }\n    else\n    {\n      _zipCryptoDecoder.Create_if_Empty();\n      cryptoFilter = _zipCryptoDecoder;\n    }\n    \n    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;\n    RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword))\n    if (!cryptoSetPassword)\n      return E_FAIL;\n    \n    if (!getTextPassword)\n      extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword);\n    \n    if (getTextPassword)\n    {\n      CMyComBSTR_Wipe password;\n      RINOK(getTextPassword->CryptoGetTextPassword(&password))\n      AString_Wipe charPassword;\n      if (password)\n      {\n#if 0 && defined(_WIN32)\n        // do we need UTF-8 passwords here ?\n        if (item.GetHostOS() == NFileHeader::NHostOS::kUnix // 24.05\n            // || item.IsUtf8() // 22.00\n            )\n        {\n          // throw 1;\n          ConvertUnicodeToUTF8((LPCOLESTR)password, charPassword);\n        }\n        else\n#endif\n        {\n          UnicodeStringToMultiByte2(charPassword, (LPCOLESTR)password, CP_ACP);\n        }\n        /*\n        if (wzAesMode || pkAesMode)\n        {\n        }\n        else\n        {\n          // PASSWORD encoding for ZipCrypto:\n          // pkzip25 / WinZip / Windows probably use ANSI\n          // 7-Zip <  4.43 creates ZIP archives with OEM encoding in password\n          // 7-Zip >= 4.43 creates ZIP archives only with ASCII characters in password\n          // 7-Zip <  17.00 uses CP_OEMCP for password decoding\n          // 7-Zip >= 17.00 uses CP_ACP   for password decoding\n        }\n        */\n      }\n      HRESULT result = cryptoSetPassword->CryptoSetPassword(\n        (const Byte *)(const char *)charPassword, charPassword.Len());\n      if (result != S_OK)\n      {\n        res = NExtract::NOperationResult::kWrongPassword;\n        return S_OK;\n      }\n    }\n    else\n    {\n      res = NExtract::NOperationResult::kWrongPassword;\n      return S_OK;\n      // RINOK(cryptoSetPassword->CryptoSetPassword(NULL, 0));\n    }\n  }\n  \n  unsigned m;\n  for (m = 0; m < methodItems.Size(); m++)\n    if (methodItems[m].ZipMethod == id)\n      break;\n\n  if (m == methodItems.Size())\n  {\n    CMethodItem mi;\n    mi.ZipMethod = id;\n    if (id == NFileHeader::NCompressionMethod::kStore)\n      mi.Coder = new NCompress::CCopyCoder;\n    else if (id == NFileHeader::NCompressionMethod::kShrink)\n      mi.Coder = new NCompress::NShrink::CDecoder;\n    else if (id == NFileHeader::NCompressionMethod::kImplode)\n      mi.Coder = new NCompress::NImplode::NDecoder::CCoder;\n    else if (id == NFileHeader::NCompressionMethod::kLZMA)\n    {\n      lzmaDecoderSpec = new CLzmaDecoder;\n      mi.Coder = lzmaDecoderSpec;\n    }\n    else if (id == NFileHeader::NCompressionMethod::kXz)\n      mi.Coder = new NCompress::NXz::CComDecoder;\n    else if (id == NFileHeader::NCompressionMethod::kPPMd)\n      mi.Coder = new NCompress::NPpmdZip::CDecoder(true);\n    // **************** 7-Zip ZS Modification Start ****************\n    //else if (id == NFileHeader::NCompressionMethod::kZstdWz)\n    //  mi.Coder = new NCompress::NZstd::CDecoder();\n    else if (id == NFileHeader::NCompressionMethod::kZstd)\n      mi.Coder = new NCompress::NZSTD::CDecoder();\n    // **************** 7-Zip ZS Modification End ****************\n#ifndef Z7_ZIP_LZFSE_DISABLE\n    else if (id == NFileHeader::NCompressionMethod::kWzAES)\n      mi.Coder = new NCompress::NLzfse::CDecoder;\n#endif\n    else\n    {\n      CMethodId szMethodID;\n      if (id == NFileHeader::NCompressionMethod::kBZip2)\n        szMethodID = kMethodId_BZip2;\n      else\n      {\n        if (id > 0xFF)\n        {\n          res = NExtract::NOperationResult::kUnsupportedMethod;\n          return S_OK;\n        }\n        szMethodID = kMethodId_ZipBase + (Byte)id;\n      }\n\n      RINOK(CreateCoder_Id(EXTERNAL_CODECS_LOC_VARS szMethodID, false, mi.Coder))\n\n      if (!mi.Coder)\n      {\n        res = NExtract::NOperationResult::kUnsupportedMethod;\n        return S_OK;\n      }\n    }\n    m = methodItems.Add(mi);\n  }\n\n  const CMethodItem &mi = methodItems[m];\n  ICompressCoder *coder = mi.Coder;\n\n  \n  #ifndef Z7_ST\n  {\n    CMyComPtr<ICompressSetCoderMt> setCoderMt;\n    coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);\n    if (setCoderMt)\n    {\n      RINOK(setCoderMt->SetNumberOfThreads(numThreads))\n    }\n  }\n  // if (memUsage != 0)\n  {\n    CMyComPtr<ICompressSetMemLimit> setMemLimit;\n    coder->QueryInterface(IID_ICompressSetMemLimit, (void **)&setMemLimit);\n    if (setMemLimit)\n    {\n      RINOK(setMemLimit->SetMemLimit(memUsage))\n    }\n  }\n  #endif\n\n  {\n    CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;\n    coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);\n    if (setDecoderProperties)\n    {\n      Byte properties = (Byte)item.Flags;\n      RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1))\n    }\n  }\n  \n  \n  bool isFullStreamExpected = (!item.HasDescriptor() || item.PackSize != 0);\n  bool needReminderCheck = false;\n\n  bool dataAfterEnd = false;\n  bool truncatedError = false;\n  bool lzmaEosError = false;\n  bool headersError  = false;\n  bool padError = false;\n  bool readFromFilter = false;\n\n  const bool useUnpackLimit = (id == NFileHeader::NCompressionMethod::kStore\n      || !item.HasDescriptor()\n      || item.Size >= ((UInt64)1 << 32)\n      || item.LocalExtra.IsZip64\n      || item.CentralExtra.IsZip64\n      );\n\n  {\n    HRESULT result = S_OK;\n    if (item.IsEncrypted())\n    {\n      if (!filterStream.IsDefined())\n        filterStream.SetFromCls(new CFilterCoder(false));\n     \n      filterReleaser.FilterCoder = filterStream.ClsPtr();\n      filterStream->Filter = cryptoFilter;\n      \n      if (wzAesMode)\n      {\n        result = _wzAesDecoder->ReadHeader(inStream);\n        if (result == S_OK)\n        {\n          if (!_wzAesDecoder->Init_and_CheckPassword())\n          {\n            res = NExtract::NOperationResult::kWrongPassword;\n            return S_OK;\n          }\n        }\n      }\n      else if (pkAesMode)\n      {\n        isFullStreamExpected = false;\n        result = _pkAesDecoder->ReadHeader(inStream, item.Crc, item.Size);\n        if (result == S_OK)\n        {\n          bool passwOK;\n          result = _pkAesDecoder->Init_and_CheckPassword(passwOK);\n          if (result == S_OK && !passwOK)\n          {\n            res = NExtract::NOperationResult::kWrongPassword;\n            return S_OK;\n          }\n        }\n      }\n      else\n      {\n        result = _zipCryptoDecoder->ReadHeader(inStream);\n        if (result == S_OK)\n        {\n          _zipCryptoDecoder->Init_BeforeDecode();\n          \n          /* Info-ZIP modification to ZipCrypto format:\n               if bit 3 of the general purpose bit flag is set,\n               it uses high byte of 16-bit File Time.\n             Info-ZIP code probably writes 2 bytes of File Time.\n             We check only 1 byte. */\n\n          // UInt32 v1 = GetUi16(_zipCryptoDecoder->_header + NCrypto::NZip::kHeaderSize - 2);\n          // UInt32 v2 = (item.HasDescriptor() ? (item.Time & 0xFFFF) : (item.Crc >> 16));\n\n          Byte v1 = _zipCryptoDecoder->_header[NCrypto::NZip::kHeaderSize - 1];\n          Byte v2 = (Byte)(item.HasDescriptor() ? (item.Time >> 8) : (item.Crc >> 24));\n\n          if (v1 != v2)\n          {\n            res = NExtract::NOperationResult::kWrongPassword;\n            return S_OK;\n          }\n        }\n      }\n    }\n\n    if (result == S_OK)\n    {\n      CMyComPtr<ICompressSetFinishMode> setFinishMode;\n      coder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);\n      if (setFinishMode)\n      {\n        RINOK(setFinishMode->SetFinishMode(BoolToUInt(true)))\n      }\n      \n      const UInt64 coderPackSize = inStream->GetRem();\n\n      if (id == NFileHeader::NCompressionMethod::kStore && item.IsEncrypted())\n      {\n        // for debug : we can disable this code (kStore + 50), if we want to test CopyCoder+Filter\n        // here we use filter without CopyCoder\n        readFromFilter = false;\n        \n        COutStreamWithPadPKCS7 *padStreamSpec = NULL;\n        CMyComPtr<ISequentialOutStream> padStream;\n        UInt32 padSize = 0;\n        \n        if (pkAesMode)\n        {\n          padStreamSpec = new COutStreamWithPadPKCS7;\n          padStream = padStreamSpec;\n          padSize = _pkAesDecoder->GetPadSize((UInt32)item.Size);\n          padStreamSpec->SetStream(outStream);\n          padStreamSpec->Init(item.Size, padSize);\n        }\n\n        // Here we decode minimal required size, including padding\n        const UInt64 expectedSize = item.Size + padSize;\n        UInt64 size = coderPackSize;\n        if (item.Size > coderPackSize)\n          headersError = true;\n        else if (expectedSize != coderPackSize)\n        {\n          headersError = true;\n          if (coderPackSize > expectedSize)\n            size = expectedSize;\n        }\n\n        result = filterStream->Code(inStream, padStream ?\n            padStream.Interface() :\n            outStream.Interface(),\n            NULL, &size, compressProgress);\n\n        if (outStream->GetSize() != item.Size)\n          truncatedError = true;\n\n        if (pkAesMode)\n        {\n          if (padStreamSpec->GetSize() != size)\n            truncatedError = true;\n          if (padStreamSpec->WasPadFailure())\n            padError = true;\n        }\n      }\n      else\n      {\n        if (item.IsEncrypted())\n        {\n          readFromFilter = true;\n          inStreamReleaser.FilterCoder = filterStream.ClsPtr();\n          RINOK(filterStream->SetInStream(inStream))\n          \n          /* IFilter::Init() does nothing in all zip crypto filters.\n          So we can call any Initialize function in CFilterCoder. */\n          \n          RINOK(filterStream->Init_NoSubFilterInit())\n          // RINOK(filterStream->SetOutStreamSize(NULL));\n        }\n\n        try {\n        result = coder->Code(readFromFilter ?\n              filterStream.Interface() :\n              inStream.Interface(),\n            outStream,\n            isFullStreamExpected ? &coderPackSize : NULL,\n            // NULL,\n            useUnpackLimit ? &item.Size : NULL,\n            compressProgress);\n        } catch (...) { return E_FAIL; }\n\n        if (result == S_OK)\n        {\n        CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;\n        coder->QueryInterface(IID_ICompressGetInStreamProcessedSize, (void **)&getInStreamProcessedSize);\n        if (getInStreamProcessedSize && setFinishMode)\n        {\n          UInt64 processed;\n          RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&processed))\n          if (processed != (UInt64)(Int64)-1)\n          {\n            if (pkAesMode)\n            {\n              const UInt32 padSize = _pkAesDecoder->GetPadSize((UInt32)processed);\n              if (processed + padSize > coderPackSize)\n                truncatedError = true;\n              else if (processed + padSize < coderPackSize)\n                dataAfterEnd = true;\n              else\n              {\n                {\n                  // here we check PKCS7 padding data from reminder (it can be inside stream buffer in coder).\n                  CMyComPtr<ICompressReadUnusedFromInBuf> readInStream;\n                  coder->QueryInterface(IID_ICompressReadUnusedFromInBuf, (void **)&readInStream);\n                  // CCopyCoder() for kStore doesn't read data outside of (item.Size)\n                  if (readInStream || id == NFileHeader::NCompressionMethod::kStore)\n                  {\n                    // change pad size, if we support another block size in ZipStrong.\n                    // here we request more data to detect error with data after end.\n                    const UInt32 kBufSize = NCrypto::NZipStrong::kAesPadAllign + 16;\n                    Byte buf[kBufSize];\n                    UInt32 processedSize = 0;\n                    if (readInStream)\n                    {\n                      RINOK(readInStream->ReadUnusedFromInBuf(buf, kBufSize, &processedSize))\n                    }\n                    if (processedSize > padSize)\n                      dataAfterEnd = true;\n                    else\n                    {\n                      size_t processedSize2 = kBufSize - processedSize;\n                      result = ReadStream(filterStream, buf + processedSize, &processedSize2);\n                      if (result == S_OK)\n                      {\n                        processedSize2 += processedSize;\n                        if (processedSize2 > padSize)\n                          dataAfterEnd = true;\n                        else if (processedSize2 < padSize)\n                          truncatedError = true;\n                        else\n                          for (unsigned i = 0; i < padSize; i++)\n                            if (buf[i] != padSize)\n                              padError = true;\n                      }\n                    }\n                  }\n                }\n              }\n            }\n            else\n            {\n              if (processed < coderPackSize)\n              {\n                if (isFullStreamExpected)\n                  dataAfterEnd = true;\n              }\n              else if (processed > coderPackSize)\n              {\n                // that case is additional check, that can show the bugs in code (coder)\n                truncatedError = true;\n              }\n              needReminderCheck = isFullStreamExpected;\n            }\n          }\n        }\n        }\n      }\n\n      if (result == S_OK && id == NFileHeader::NCompressionMethod::kLZMA)\n        if (!lzmaDecoderSpec->Decoder->CheckFinishStatus(item.IsLzmaEOS()))\n          lzmaEosError = true;\n    }\n    \n    if (result == S_FALSE)\n      return S_OK;\n    \n    if (result == E_NOTIMPL)\n    {\n      res = NExtract::NOperationResult::kUnsupportedMethod;\n      return S_OK;\n    }\n\n    RINOK(result)\n  }\n\n  bool crcOK = true;\n  bool authOk = true;\n  if (needCRC)\n    crcOK = (outStream->GetCRC() == item.Crc);\n\n  if (useUnpackLimit)\n    if (outStream->GetSize() != item.Size)\n      truncatedError = true;\n  \n  if (wzAesMode)\n  {\n    const UInt64 unpackSize = outStream->GetSize();\n    const UInt64 packSize = inStream->GetSize();\n    bool thereAreData = false;\n    // read to the end from filter or from packed stream\n    if (SkipStreamData(readFromFilter ?\n          filterStream.Interface() :\n          inStream.Interface(),\n        compressProgress, packSize, unpackSize, thereAreData) != S_OK)\n      authOk = false;\n    if (needReminderCheck && thereAreData)\n      dataAfterEnd = true;\n\n    if (inStream->GetRem() != 0)\n      truncatedError = true;\n    else\n    {\n      inStream->Init(NCrypto::NWzAes::kMacSize);\n      if (_wzAesDecoder->CheckMac(inStream, authOk) != S_OK)\n        authOk = false;\n    }\n  }\n\n  res = NExtract::NOperationResult::kCRCError;\n\n  if (crcOK && authOk)\n  {\n    res = NExtract::NOperationResult::kOK;\n\n    if (dataAfterEnd)\n      res = NExtract::NOperationResult::kDataAfterEnd;\n    else if (padError)\n      res = NExtract::NOperationResult::kCRCError;\n    else if (truncatedError)\n      res = NExtract::NOperationResult::kUnexpectedEnd;\n    else if (headersError)\n      res = NExtract::NOperationResult::kHeadersError;\n    else if (lzmaEosError)\n      res = NExtract::NOperationResult::kHeadersError;\n    else if (badDescriptor)\n      res = NExtract::NOperationResult::kUnexpectedEnd;\n\n    // CheckDescriptor() supports only data descriptor with signature and\n    // it doesn't support \"old\" pkzip's data descriptor without signature.\n    // So we disable that check.\n    /*\n    if (item.HasDescriptor() && archive.CheckDescriptor(item) != S_OK)\n      res = NExtract::NOperationResult::kHeadersError;\n    */\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = m_Items.Size();\n  if (numItems == 0)\n    return S_OK;\n  UInt64 total = 0; // , totalPacked = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n  {\n    const CItemEx &item = m_Items[allFilesMode ? i : indices[i]];\n    total += item.Size;\n    // totalPacked += item.PackSize;\n  }\n  RINOK(extractCallback->SetTotal(total))\n\n  CZipDecoder myDecoder;\n  UInt64 cur_Unpacked, cur_Packed;\n  \n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;\n  lps->Init(extractCallback, false);\n\n  for (i = 0;; i++,\n      lps->OutSize += cur_Unpacked,\n      lps->InSize += cur_Packed)\n  {\n    RINOK(lps->SetCur())\n    if (i >= numItems)\n      return S_OK;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    CItemEx item = m_Items[index];\n    cur_Unpacked = item.Size;\n    cur_Packed = item.PackSize;\n\n    const bool isLocalOffsetOK = m_Archive.IsLocalOffsetOK(item);\n    const bool skip = !isLocalOffsetOK && !item.IsDir();\n    const Int32 askMode = skip ?\n        NExtract::NAskMode::kSkip : testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n\n    Int32 opRes;\n    {\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n\n    if (!isLocalOffsetOK)\n    {\n      RINOK(extractCallback->PrepareOperation(askMode))\n      realOutStream.Release();\n      RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnavailable))\n      continue;\n    }\n\n    bool headersError = false;\n    \n    if (!item.FromLocal)\n    {\n      bool isAvail = true;\n      const HRESULT hres = m_Archive.Read_LocalItem_After_CdItem(item, isAvail, headersError);\n      if (hres == S_FALSE)\n      {\n        if (item.IsDir() || realOutStream || testMode)\n        {\n          RINOK(extractCallback->PrepareOperation(askMode))\n          realOutStream.Release();\n          RINOK(extractCallback->SetOperationResult(\n              isAvail ?\n                NExtract::NOperationResult::kHeadersError :\n                NExtract::NOperationResult::kUnavailable))\n        }\n        continue;\n      }\n      RINOK(hres)\n    }\n\n    if (item.IsDir())\n    {\n      // if (!testMode)\n      {\n        RINOK(extractCallback->PrepareOperation(askMode))\n        realOutStream.Release();\n        RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))\n      }\n      continue;\n    }\n\n    if (!testMode && !realOutStream)\n      continue;\n\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    const HRESULT hres = myDecoder.Decode(\n        EXTERNAL_CODECS_VARS\n        m_Archive, item, realOutStream, extractCallback,\n        lps,\n        #ifndef Z7_ST\n        _props._numThreads, _props._memUsage_Decompress,\n        #endif\n        opRes);\n    \n    RINOK(hres)\n    // realOutStream.Release();\n    \n    if (opRes == NExtract::NOperationResult::kOK && headersError)\n      opRes = NExtract::NOperationResult::kHeadersError;\n    }\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n\n  COM_TRY_END\n}\n\nIMPL_ISetCompressCodecsInfo\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipHandler.h",
    "content": "﻿// Zip/Handler.h\n\n#ifndef ZIP7_INC_ZIP_HANDLER_H\n#define ZIP7_INC_ZIP_HANDLER_H\n\n#include \"../../../Common/DynamicBuffer.h\"\n#include \"../../ICoder.h\"\n#include \"../IArchive.h\"\n\n#include \"../../Common/CreateCoder.h\"\n\n#include \"ZipCompressionMode.h\"\n#include \"ZipIn.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nconst unsigned kNumMethodNames1 = NFileHeader::NCompressionMethod::kZstdPk + 1;\n// **************** 7-Zip ZS Modification Start ****************\n// const unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kZstdWz;\nconst unsigned kMethodNames2Start = NFileHeader::NCompressionMethod::kZstd;\n// **************** 7-Zip ZS Modification End ****************\nconst unsigned kNumMethodNames2 = NFileHeader::NCompressionMethod::kWzAES + 1 - kMethodNames2Start;\n\nextern const char * const kMethodNames1[kNumMethodNames1];\nextern const char * const kMethodNames2[kNumMethodNames2];\n\n\nclass CHandler Z7_final:\n  public IInArchive,\n  // public IArchiveGetRawProps,\n  public IOutArchive,\n  public ISetProperties,\n  Z7_PUBLIC_ISetCompressCodecsInfo_IFEC\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IInArchive)\n  // Z7_COM_QI_ENTRY(IArchiveGetRawProps)\n  Z7_COM_QI_ENTRY(IOutArchive)\n  Z7_COM_QI_ENTRY(ISetProperties)\n  Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(IInArchive)\n  // Z7_IFACE_COM7_IMP(IArchiveGetRawProps)\n  Z7_IFACE_COM7_IMP(IOutArchive)\n  Z7_IFACE_COM7_IMP(ISetProperties)\n  DECL_ISetCompressCodecsInfo\n\nprivate:\n  CObjectVector<CItemEx> m_Items;\n  CInArchive m_Archive;\n\n  CBaseProps _props;\n  CHandlerTimeOptions TimeOptions;\n\n  int m_MainMethod;\n  bool m_ForceAesMode;\n\n  bool _removeSfxBlock;\n  bool m_ForceLocal;\n  bool m_ForceUtf8;\n  bool _force_SeqOutMode; // for creation\n  bool _force_OpenSeq;\n  bool _forceCodePage;\n  UInt32 _specifiedCodePage;\n\n  DECL_EXTERNAL_CODECS_VARS\n\n  void InitMethodProps()\n  {\n    _props.Init();\n    TimeOptions.Init();\n    TimeOptions.Prec = k_PropVar_TimePrec_0;\n    m_MainMethod = -1;\n    m_ForceAesMode = false;\n    _removeSfxBlock = false;\n    m_ForceLocal = false;\n    // **************** 7-Zip ZS Modification Start ****************\n    // m_ForceUtf8 = false;\n    m_ForceUtf8 = true;\n    // **************** 7-Zip ZS Modification End ****************\n    _force_SeqOutMode = false;\n    _force_OpenSeq = false;\n    _forceCodePage = false;\n    _specifiedCodePage = CP_OEMCP;\n  }\n\n  // void MarkAltStreams(CObjectVector<CItemEx> &items);\n\n  HRESULT GetOutProperty(IArchiveUpdateCallback *callback, UInt32 callbackIndex, Int32 arcIndex, PROPID propID, PROPVARIANT *value);\n\npublic:\n  CHandler();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp",
    "content": "﻿// ZipHandlerOut.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/StringToInt.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../IPassword.h\"\n\n#include \"../../Common/OutBuffer.h\"\n\n#include \"../../Crypto/WzAes.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n#include \"../Common/ParseProperties.h\"\n\n#include \"ZipHandler.h\"\n#include \"ZipUpdate.h\"\n\nusing namespace NWindows;\nusing namespace NCOM;\nusing namespace NTime;\n\nnamespace NArchive {\nnamespace NZip {\n\nZ7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))\n{\n  *timeType = TimeOptions.Prec;\n  return S_OK;\n}\n\nstatic bool IsSimpleAsciiString(const wchar_t *s)\n{\n  for (;;)\n  {\n    wchar_t c = *s++;\n    if (c == 0)\n      return true;\n    if (c < 0x20 || c > 0x7F)\n      return false;\n  }\n}\n\n\nstatic int FindZipMethod(const char *s, const char * const *names, unsigned num)\n{\n  for (unsigned i = 0; i < num; i++)\n  {\n    const char *name = names[i];\n    if (name && StringsAreEqualNoCase_Ascii(s, name))\n      return (int)i;\n  }\n  return -1;\n}\n\nstatic int FindZipMethod(const char *s)\n{\n  int k = FindZipMethod(s, kMethodNames1, kNumMethodNames1);\n  if (k >= 0)\n    return k;\n  k = FindZipMethod(s, kMethodNames2, kNumMethodNames2);\n  if (k >= 0)\n    return (int)kMethodNames2Start + k;\n  return -1;\n}\n\n\n#define COM_TRY_BEGIN2 try {\n#define COM_TRY_END2 } \\\ncatch(const CSystemException &e) { return e.ErrorCode; } \\\ncatch(...) { return E_OUTOFMEMORY; }\n\nstatic HRESULT GetTime(IArchiveUpdateCallback *callback, unsigned index, PROPID propID, FILETIME &filetime)\n{\n  filetime.dwHighDateTime = filetime.dwLowDateTime = 0;\n  NCOM::CPropVariant prop;\n  RINOK(callback->GetProperty(index, propID, &prop))\n  if (prop.vt == VT_FILETIME)\n    filetime = prop.filetime;\n  else if (prop.vt != VT_EMPTY)\n    return E_INVALIDARG;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,\n    IArchiveUpdateCallback *callback))\n{\n  COM_TRY_BEGIN2\n  \n  if (m_Archive.IsOpen())\n  {\n    if (!m_Archive.CanUpdate())\n      return E_NOTIMPL;\n  }\n\n  CObjectVector<CUpdateItem> updateItems;\n  updateItems.ClearAndReserve(numItems);\n\n  bool thereAreAesUpdates = false;\n  UInt64 largestSize = 0;\n  bool largestSizeDefined = false;\n\n  #ifdef _WIN32\n  const UINT oemCP = GetOEMCP();\n  #endif\n\n  UString name;\n  CUpdateItem ui;\n\n  for (UInt32 i = 0; i < numItems; i++)\n  {\n    Int32 newData;\n    Int32 newProps;\n    UInt32 indexInArc;\n    \n    if (!callback)\n      return E_FAIL;\n    \n    RINOK(callback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArc))\n    \n    name.Empty();\n    ui.Clear();\n\n    ui.NewProps = IntToBool(newProps);\n    ui.NewData = IntToBool(newData);\n    ui.IndexInArc = (int)indexInArc;\n    ui.IndexInClient = i;\n    \n    bool existInArchive = (indexInArc != (UInt32)(Int32)-1);\n    if (existInArchive)\n    {\n      const CItemEx &inputItem = m_Items[indexInArc];\n      if (inputItem.IsAesEncrypted())\n        thereAreAesUpdates = true;\n      if (!IntToBool(newProps))\n        ui.IsDir = inputItem.IsDir();\n      // ui.IsAltStream = inputItem.IsAltStream();\n    }\n\n    if (IntToBool(newProps))\n    {\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidAttrib, &prop))\n        if (prop.vt == VT_EMPTY)\n          ui.Attrib = 0;\n        else if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n        else\n          ui.Attrib = prop.ulVal;\n      }\n\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidPath, &prop))\n        if (prop.vt == VT_EMPTY)\n        {\n          // name.Empty();\n        }\n        else if (prop.vt != VT_BSTR)\n          return E_INVALIDARG;\n        else\n          name = prop.bstrVal;\n      }\n\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidIsDir, &prop))\n        if (prop.vt == VT_EMPTY)\n          ui.IsDir = false;\n        else if (prop.vt != VT_BOOL)\n          return E_INVALIDARG;\n        else\n          ui.IsDir = (prop.boolVal != VARIANT_FALSE);\n      }\n\n      /*\n      {\n        bool isAltStream = false;\n        {\n          NCOM::CPropVariant prop;\n          RINOK(callback->GetProperty(i, kpidIsAltStream, &prop));\n          if (prop.vt == VT_BOOL)\n            isAltStream = (prop.boolVal != VARIANT_FALSE);\n          else if (prop.vt != VT_EMPTY)\n            return E_INVALIDARG;\n        }\n      \n        if (isAltStream)\n        {\n          if (ui.IsDir)\n            return E_INVALIDARG;\n          int delim = name.ReverseFind(L':');\n          if (delim >= 0)\n          {\n            name.Delete(delim, 1);\n            name.Insert(delim, UString(k_SpecName_NTFS_STREAM));\n            ui.IsAltStream = true;\n          }\n        }\n      }\n      */\n\n      // 22.00 : kpidTimeType is useless here : the code was disabled\n      /*\n      {\n        CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidTimeType, &prop));\n        if (prop.vt == VT_UI4)\n          ui.NtfsTime_IsDefined = (prop.ulVal == NFileTimeType::kWindows);\n        else\n          ui.NtfsTime_IsDefined = _Write_NtfsTime;\n      }\n      */\n\n      if (TimeOptions.Write_MTime.Val) RINOK (GetTime (callback, i, kpidMTime, ui.Ntfs_MTime))\n      if (TimeOptions.Write_ATime.Val) RINOK (GetTime (callback, i, kpidATime, ui.Ntfs_ATime))\n      if (TimeOptions.Write_CTime.Val) RINOK (GetTime (callback, i, kpidCTime, ui.Ntfs_CTime))\n\n      if (TimeOptions.Prec != k_PropVar_TimePrec_DOS)\n      {\n        if (TimeOptions.Prec == k_PropVar_TimePrec_Unix ||\n            TimeOptions.Prec == k_PropVar_TimePrec_Base)\n          ui.Write_UnixTime = ! FILETIME_IsZero (ui.Ntfs_MTime);\n        else\n        {\n          /*\n          // if we want to store zero timestamps as zero timestamp, use the following:\n            ui.Write_NtfsTime =\n            _Write_MTime ||\n            _Write_ATime ||\n            _Write_CTime;\n          */\n          \n          // We treat zero timestamp as no timestamp\n          ui.Write_NtfsTime =\n            ! FILETIME_IsZero (ui.Ntfs_MTime) ||\n            ! FILETIME_IsZero (ui.Ntfs_ATime) ||\n            ! FILETIME_IsZero (ui.Ntfs_CTime);\n        }\n      }\n\n      /*\n        how 0 in dos time works:\n            win10 explorer extract : some random date 1601-04-25.\n            winrar 6.10 : write time.\n            7zip : MTime of archive is used\n          how 0 in tar works:\n            winrar 6.10 : 1970\n        0 in dos field can show that there is no timestamp.\n        we write correct 1970-01-01 in dos field, to support correct extraction in Win10.\n      */\n\n      UtcFileTime_To_LocalDosTime(ui.Ntfs_MTime, ui.Time);\n\n      NItemName::ReplaceSlashes_OsToUnix(name);\n      \n      bool needSlash = ui.IsDir;\n      const wchar_t kSlash = L'/';\n      if (!name.IsEmpty())\n      {\n        if (name.Back() == kSlash)\n        {\n          if (!ui.IsDir)\n            return E_INVALIDARG;\n          needSlash = false;\n        }\n      }\n      if (needSlash)\n        name += kSlash;\n\n      const UINT codePage = _forceCodePage ? _specifiedCodePage : CP_OEMCP;\n      bool tryUtf8 = true;\n\n      /*\n        Windows 10 allows users to set UTF-8 in Region Settings via option:\n        \"Beta: Use Unicode UTF-8 for worldwide language support\"\n        In that case Windows uses CP_UTF8 when we use CP_OEMCP.\n        21.02 fixed:\n          we set UTF-8 mark for non-latin files for such UTF-8 mode in Windows.\n          we write additional Info-Zip Utf-8 FileName Extra for non-latin names/\n      */\n\n      if ((codePage != CP_UTF8) &&\n        #ifdef _WIN32\n          (m_ForceLocal || !m_ForceUtf8) && (oemCP != CP_UTF8)\n        #else\n          (m_ForceLocal && !m_ForceUtf8)\n        #endif\n        )\n      {\n        bool defaultCharWasUsed;\n        ui.Name = UnicodeStringToMultiByte(name, codePage, '_', defaultCharWasUsed);\n        tryUtf8 = (!m_ForceLocal && (defaultCharWasUsed ||\n          MultiByteToUnicodeString(ui.Name, codePage) != name));\n      }\n\n      const bool isNonLatin = !name.IsAscii();\n\n      if (tryUtf8)\n      {\n        ui.IsUtf8 = isNonLatin;\n        ConvertUnicodeToUTF8(name, ui.Name);\n\n        #ifndef _WIN32\n        if (ui.IsUtf8 && !CheckUTF8_AString(ui.Name))\n        {\n          // if it's non-Windows and there are non-UTF8 characters we clear UTF8-flag\n          ui.IsUtf8 = false;\n        }\n        #endif\n      }\n      else if (isNonLatin)\n        Convert_Unicode_To_UTF8_Buf(name, ui.Name_Utf);\n\n      if (ui.Name.Len() >= (1 << 16)\n          || ui.Name_Utf.Size() >= (1 << 16) - 128)\n        return E_INVALIDARG;\n\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidComment, &prop))\n        if (prop.vt == VT_EMPTY)\n        {\n          // ui.Comment.Free();\n        }\n        else if (prop.vt != VT_BSTR)\n          return E_INVALIDARG;\n        else\n        {\n          UString s = prop.bstrVal;\n          AString a;\n          if (ui.IsUtf8)\n            ConvertUnicodeToUTF8(s, a);\n          else\n          {\n            bool defaultCharWasUsed;\n            a = UnicodeStringToMultiByte(s, codePage, '_', defaultCharWasUsed);\n          }\n          if (a.Len() >= (1 << 16))\n            return E_INVALIDARG;\n          ui.Comment.CopyFrom((const Byte *)(const char *)a, a.Len());\n        }\n      }\n\n\n      /*\n      if (existInArchive)\n      {\n        const CItemEx &itemInfo = m_Items[indexInArc];\n        // ui.Commented = itemInfo.IsCommented();\n        ui.Commented = false;\n        if (ui.Commented)\n        {\n          ui.CommentRange.Position = itemInfo.GetCommentPosition();\n          ui.CommentRange.Size  = itemInfo.CommentSize;\n        }\n      }\n      else\n        ui.Commented = false;\n      */\n    }\n    \n    \n    if (IntToBool(newData))\n    {\n      UInt64 size = 0;\n      if (!ui.IsDir)\n      {\n        NCOM::CPropVariant prop;\n        RINOK(callback->GetProperty(i, kpidSize, &prop))\n        if (prop.vt != VT_UI8)\n          return E_INVALIDARG;\n        size = prop.uhVal.QuadPart;\n        if (largestSize < size)\n          largestSize = size;\n        largestSizeDefined = true;\n      }\n      ui.Size = size;\n    }\n\n    updateItems.Add(ui);\n  }\n\n\n  CMyComPtr<ICryptoGetTextPassword2> getTextPassword;\n  {\n    CMyComPtr<IArchiveUpdateCallback> udateCallBack2(callback);\n    udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);\n  }\n  CCompressionMethodMode options;\n  (CBaseProps &)options = _props;\n  options.DataSizeReduce = largestSize;\n  options.DataSizeReduce_Defined = largestSizeDefined;\n\n  options.Password_Defined = false;\n  options.Password.Wipe_and_Empty();\n  if (getTextPassword)\n  {\n    CMyComBSTR_Wipe password;\n    Int32 passwordIsDefined;\n    RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password))\n    options.Password_Defined = IntToBool(passwordIsDefined);\n    if (options.Password_Defined)\n    {\n      if (!m_ForceAesMode)\n        options.IsAesMode = thereAreAesUpdates;\n\n      if (!IsSimpleAsciiString(password))\n        return E_INVALIDARG;\n      if (password)\n        UnicodeStringToMultiByte2(options.Password, (LPCOLESTR)password, CP_OEMCP);\n      if (options.IsAesMode)\n      {\n        if (options.Password.Len() > NCrypto::NWzAes::kPasswordSizeMax)\n          return E_INVALIDARG;\n      }\n    }\n  }\n\n  \n  int mainMethod = m_MainMethod;\n  \n  if (mainMethod < 0)\n  {\n    if (!_props._methods.IsEmpty())\n    {\n      const AString &methodName = _props._methods.Front().MethodName;\n      if (!methodName.IsEmpty())\n      {\n        mainMethod = FindZipMethod(methodName);\n        if (mainMethod < 0)\n        {\n          CMethodId methodId;\n          UInt32 numStreams;\n          bool isFilter;\n          if (FindMethod_Index(EXTERNAL_CODECS_VARS methodName, true,\n              methodId, numStreams, isFilter) < 0)\n            return E_NOTIMPL;\n          if (numStreams != 1)\n            return E_NOTIMPL;\n          if (methodId == kMethodId_BZip2)\n            mainMethod = NFileHeader::NCompressionMethod::kBZip2;\n          else\n          {\n            if (methodId < kMethodId_ZipBase)\n              return E_NOTIMPL;\n            methodId -= kMethodId_ZipBase;\n            if (methodId > 0xFF)\n              return E_NOTIMPL;\n            mainMethod = (int)methodId;\n          }\n        }\n      }\n    }\n  }\n\n  if (mainMethod < 0)\n    mainMethod = (Byte)(((_props.GetLevel() == 0) ?\n        NFileHeader::NCompressionMethod::kStore :\n        NFileHeader::NCompressionMethod::kDeflate));\n  else\n    mainMethod = (Byte)mainMethod;\n  \n  options.MethodSequence.Add((Byte)mainMethod);\n  \n  if (mainMethod != NFileHeader::NCompressionMethod::kStore)\n    options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStore);\n\n  options.Force_SeqOutMode = _force_SeqOutMode;\n\n  CUpdateOptions uo;\n  uo.Write_MTime = TimeOptions.Write_MTime.Val;\n  uo.Write_ATime = TimeOptions.Write_ATime.Val;\n  uo.Write_CTime = TimeOptions.Write_CTime.Val;\n  /*\n  uo.Write_NtfsTime = _Write_NtfsTime &&\n    (_Write_MTime || _Write_ATime  || _Write_CTime);\n  uo.Write_UnixTime = _Write_UnixTime;\n  */\n\n  return Update(\n      EXTERNAL_CODECS_VARS\n      m_Items, updateItems, outStream,\n      m_Archive.IsOpen() ? &m_Archive : NULL, _removeSfxBlock,\n      uo, options, callback);\n \n  COM_TRY_END2\n}\n\n\n\nZ7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))\n{\n  InitMethodProps();\n  \n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    UString name = names[i];\n    name.MakeLower_Ascii();\n    if (name.IsEmpty())\n      return E_INVALIDARG;\n\n    const PROPVARIANT &prop = values[i];\n\n    if (name.IsEqualTo_Ascii_NoCase(\"em\"))\n    {\n      if (prop.vt != VT_BSTR)\n        return E_INVALIDARG;\n      {\n        const wchar_t *m = prop.bstrVal;\n        if (IsString1PrefixedByString2_NoCase_Ascii(m, \"AES\"))\n        {\n          m += 3;\n          UInt32 v = 3;\n          if (*m != 0)\n          {\n            if (*m == '-')\n              m++;\n            const wchar_t *end;\n            v = ConvertStringToUInt32(m,  &end);\n            if (*end != 0 || v % 64 != 0)\n              return E_INVALIDARG;\n            v /= 64;\n            v -= 2;\n            if (v >= 3)\n              return E_INVALIDARG;\n            v++;\n          }\n          _props.AesKeyMode = (Byte)v;\n          _props.IsAesMode = true;\n          m_ForceAesMode = true;\n        }\n        else if (StringsAreEqualNoCase_Ascii(m, \"ZipCrypto\"))\n        {\n          _props.IsAesMode = false;\n          m_ForceAesMode = true;\n        }\n        else\n          return E_INVALIDARG;\n      }\n    }\n    \n\n   \n    else if (name.IsEqualTo(\"cl\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, m_ForceLocal))\n      if (m_ForceLocal)\n        m_ForceUtf8 = false;\n    }\n    else if (name.IsEqualTo(\"cu\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, m_ForceUtf8))\n      if (m_ForceUtf8)\n        m_ForceLocal = false;\n    }\n    else if (name.IsEqualTo(\"cp\"))\n    {\n      UInt32 cp = CP_OEMCP;\n      RINOK(ParsePropToUInt32(L\"\", prop, cp))\n      _forceCodePage = true;\n      _specifiedCodePage = cp;\n    }\n    else if (name.IsEqualTo(\"rsfx\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, _removeSfxBlock))\n    }\n    else if (name.IsEqualTo(\"rws\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, _force_SeqOutMode))\n    }\n    else if (name.IsEqualTo(\"ros\"))\n    {\n      RINOK(PROPVARIANT_to_bool(prop, _force_OpenSeq))\n    }\n    else\n    {\n      if (name.IsEqualTo_Ascii_NoCase(\"m\") && prop.vt == VT_UI4)\n      {\n        UInt32 id = prop.ulVal;\n        if (id > 0xFF)\n          return E_INVALIDARG;\n        m_MainMethod = (int)id;\n      }\n      else\n      {\n        bool processed = false;\n        RINOK(TimeOptions.Parse(name, prop, processed))\n        if (!processed)\n        {\n          RINOK(_props.SetProperty(name, prop))\n        }\n      }\n      // RINOK(_props.MethodInfo.ParseParamsFromPROPVARIANT(name, prop));\n    }\n  }\n\n  _props._methods.DeleteFrontal(_props.GetNumEmptyMethods());\n  if (_props._methods.Size() > 1)\n    return E_INVALIDARG;\n  if (_props._methods.Size() == 1)\n  {\n    const AString &methodName = _props._methods[0].MethodName;\n\n    if (!methodName.IsEmpty())\n    {\n      const char *end;\n      UInt32 id = ConvertStringToUInt32(methodName, &end);\n      if (*end == 0 && id <= 0xFF)\n        m_MainMethod = (int)id;\n      else if (methodName.IsEqualTo_Ascii_NoCase(\"Copy\")) // it's alias for \"Store\"\n        m_MainMethod = 0;\n    }\n  }\n  \n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipHeader.h",
    "content": "﻿// ZipHeader.h\n\n#ifndef ZIP7_INC_ARCHIVE_ZIP_HEADER_H\n#define ZIP7_INC_ARCHIVE_ZIP_HEADER_H\n\n#include \"../../../Common/MyTypes.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nconst unsigned kMarkerSize = 4;\n\nnamespace NSignature\n{\n  const UInt32 kLocalFileHeader   = 0x04034B50;\n  const UInt32 kDataDescriptor    = 0x08074B50;\n  const UInt32 kCentralFileHeader = 0x02014B50;\n  const UInt32 kEcd               = 0x06054B50;\n  const UInt32 kEcd64             = 0x06064B50;\n  const UInt32 kEcd64Locator      = 0x07064B50;\n  const UInt32 kSpan              = 0x08074B50;\n  const UInt32 kNoSpan            = 0x30304B50; // PK00, replaces kSpan, if there is only 1 segment\n}\n\nconst unsigned kLocalHeaderSize = 4 + 26; // including signature\nconst unsigned kDataDescriptorSize32 = 4 + 4 + 4 * 2;  // including signature\nconst unsigned kDataDescriptorSize64 = 4 + 4 + 8 * 2;  // including signature\nconst unsigned kCentralHeaderSize = 4 + 42; // including signature\n\nconst unsigned kEcdSize = 22; // including signature\nconst unsigned kEcd64_MainSize = 44;\nconst unsigned kEcd64_FullSize = 12 + kEcd64_MainSize;\nconst unsigned kEcd64Locator_Size = 20;\n\nnamespace NFileHeader\n{\n  namespace NCompressionMethod\n  {\n    enum EType\n    {\n      kStore = 0,\n      kShrink = 1,\n      kReduce1 = 2,\n      kReduce2 = 3,\n      kReduce3 = 4,\n      kReduce4 = 5,\n      kImplode = 6,\n      kTokenize = 7,\n      kDeflate = 8,\n      kDeflate64 = 9,\n      kPKImploding = 10,\n\n      // **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n      kBZip2 = 12,\n      \n      kLZMA = 14,\n      \n      kTerse = 18,\n      kLz77 = 19,\n      kZstdPk = 20,\n      \n      kZstdWz = 93,\n      kMP3 = 94,\n      kXz = 95,\n      kJpeg = 96,\n      kWavPack = 97,\n      kPPMd = 98,\n      kWzAES = 99\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n      kBZip2 = 12,   // File is compressed using BZIP2 algorithm\n\n      kLZMA = 14,    // LZMA\n\n      kTerse = 18,   // File is compressed using IBM TERSE (new)\n      kLz77 = 19,    // IBM LZ77 z Architecture\n      kZstdPk = 20,  // deprecated (use method 93 for zstd)\n\n      kZstd = 93,    // Zstandard (zstd) Compression\n      kMP3 = 94,     // MP3 Compression\n      kXz = 95,      // XZ Compression\n      kJpeg = 96,    // JPEG variant\n      kWavPack = 97, // WavPack compressed data\n      kPPMd = 98,    // PPMd version I, Rev 1\n      kWzAES = 99    // AE-x encryption marker (see APPENDIX E)\n      // **************** 7-Zip ZS Modification End ****************\n    };\n\n    const Byte kMadeByProgramVersion = 63;\n    \n    const Byte kExtractVersion_Default = 10;\n    const Byte kExtractVersion_Dir = 20;\n    const Byte kExtractVersion_ZipCrypto = 20;\n    const Byte kExtractVersion_Deflate = 20;\n    const Byte kExtractVersion_Deflate64 = 21;\n    const Byte kExtractVersion_Zip64 = 45;\n    const Byte kExtractVersion_BZip2 = 46;\n    const Byte kExtractVersion_Aes = 51;\n    const Byte kExtractVersion_LZMA = 63;\n    const Byte kExtractVersion_PPMd = 63;\n    const Byte kExtractVersion_Xz = 20; // test it\n    // **************** 7-Zip ZS Modification Start ****************\n    const Byte kExtractVersion_Zstd = 20; // WinZip mark it\n    // **************** 7-Zip ZS Modification End ****************\n  }\n\n  namespace NExtraID\n  {\n    enum\n    {\n      kZip64 = 0x01,\n      kNTFS = 0x0A,\n      kUnix0 = 0x0D,                // Info-ZIP : (UNIX) PK\n      kStrongEncrypt = 0x17,\n      kIzNtSecurityDescriptor = 0x4453,\n      kUnixTime = 0x5455,           // \"UT\" (time) Info-ZIP\n      kUnix1 = 0x5855,              // Info-ZIP\n      kIzUnicodeComment = 0x6375,\n      kIzUnicodeName = 0x7075,\n      kUnix2 = 0x7855,              // Info-ZIP\n      kUnixN = 0x7875,              // Info-ZIP\n      kWzAES = 0x9901,\n      kApkAlign = 0xD935\n    };\n  }\n\n  namespace NNtfsExtra\n  {\n    const UInt16 kTagTime = 1;\n    enum\n    {\n      kMTime = 0,\n      kATime,\n      kCTime\n    };\n  }\n\n  namespace NUnixTime\n  {\n    enum\n    {\n      kMTime = 0,\n      kATime,\n      kCTime\n    };\n  }\n\n  namespace NUnixExtra\n  {\n    enum\n    {\n      kATime = 0,\n      kMTime\n    };\n  }\n\n  namespace NFlags\n  {\n    const unsigned kEncrypted = 1 << 0;\n    const unsigned kLzmaEOS = 1 << 1;\n    const unsigned kDescriptorUsedMask = 1 << 3;\n    const unsigned kStrongEncrypted = 1 << 6;\n    const unsigned kUtf8 = 1 << 11;\n    const unsigned kAltStream = 1 << 14;\n\n    const unsigned kImplodeDictionarySizeMask = 1 << 1;\n    const unsigned kImplodeLiteralsOnMask     = 1 << 2;\n    \n    /*\n    const unsigned kDeflateTypeBitStart = 1;\n    const unsigned kNumDeflateTypeBits = 2;\n    const unsigned kNumDeflateTypes = (1 << kNumDeflateTypeBits);\n    const unsigned kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1;\n    */\n  }\n  \n  namespace NHostOS\n  {\n    enum EEnum\n    {\n      kFAT      =  0,\n      kAMIGA    =  1,\n      kVMS      =  2,  // VAX/VMS\n      kUnix     =  3,\n      kVM_CMS   =  4,\n      kAtari    =  5,  // what if it's a minix filesystem? [cjh]\n      kHPFS     =  6,  // filesystem used by OS/2 (and NT 3.x)\n      kMac      =  7,\n      kZ_System =  8,\n      kCPM      =  9,\n      kTOPS20   = 10,  // pkzip 2.50 NTFS\n      kNTFS     = 11,  // filesystem used by Windows NT\n      kQDOS     = 12,  // SMS/QDOS\n      kAcorn    = 13,  // Archimedes Acorn RISC OS\n      kVFAT     = 14,  // filesystem used by Windows 95, NT\n      kMVS      = 15,\n      kBeOS     = 16,  // hybrid POSIX/database filesystem\n      kTandem   = 17,\n      kOS400    = 18,\n      kOSX      = 19\n    };\n  }\n\n\n  namespace NAmigaAttrib\n  {\n    const UInt32 kIFMT     = 06000;    // Amiga file type mask\n    const UInt32 kIFDIR    = 04000;    // Amiga directory\n    const UInt32 kIFREG    = 02000;    // Amiga regular file\n    const UInt32 kIHIDDEN  = 00200;    // to be supported in AmigaDOS 3.x\n    const UInt32 kISCRIPT  = 00100;    // executable script (text command file)\n    const UInt32 kIPURE    = 00040;    // allow loading into resident memory\n    const UInt32 kIARCHIVE = 00020;    // not modified since bit was last set\n    const UInt32 kIREAD    = 00010;    // can be opened for reading\n    const UInt32 kIWRITE   = 00004;    // can be opened for writing\n    const UInt32 kIEXECUTE = 00002;    // executable image, a loadable runfile\n    const UInt32 kIDELETE  = 00001;    // can be deleted\n  }\n}\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipIn.cpp",
    "content": "﻿// Archive/ZipIn.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../Common/DynamicBuffer.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/MyException.h\"\n#include \"../../../Common/StringToInt.h\"\n\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"../IArchive.h\"\n\n#include \"ZipIn.h\"\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n#define Get64(p) GetUi64(p)\n\n#define G16(offs, v) v = Get16(p + (offs))\n#define G32(offs, v) v = Get32(p + (offs))\n#define G64(offs, v) v = Get64(p + (offs))\n\nnamespace NArchive {\nnamespace NZip {\n\n/* we try to use same size of Buffer (1 << 17) for all tasks.\n   it allow to avoid reallocations and cache clearing. */\n\nstatic const size_t kSeqBufferSize = (size_t)1 << 17;\n\n/*\nOpen()\n{\n  _inBufMode = false;\n  ReadVols()\n    FindCd();\n      TryEcd64()\n  SeekToVol()\n  FindMarker()\n    _inBufMode = true;\n  ReadHeaders()\n    _inBufMode = false;\n    ReadCd()\n      FindCd()\n        TryEcd64()\n      TryReadCd()\n      {\n        SeekToVol();\n        _inBufMode = true;\n      }\n    _inBufMode = true;\n    ReadLocals()\n    ReadCdItem()\n    ....\n}\nFindCd() writes to Buffer without touching (_inBufMode)\n*/\n\n/*\n  if (not defined ZIP_SELF_CHECK) : it reads CD and if error in first pass CD reading, it reads LOCALS-CD-MODE\n  if (    defined ZIP_SELF_CHECK) : it always reads CD and LOCALS-CD-MODE\n  use ZIP_SELF_CHECK to check LOCALS-CD-MODE for any zip archive\n*/\n\n// #define ZIP_SELF_CHECK\n\n\nstruct CEcd\n{\n  UInt16 ThisDisk;\n  UInt16 CdDisk;\n  UInt16 NumEntries_in_ThisDisk;\n  UInt16 NumEntries;\n  UInt32 Size;\n  UInt32 Offset;\n  UInt16 CommentSize;\n  \n  bool IsEmptyArc() const\n  {\n    return ThisDisk == 0\n        && CdDisk == 0\n        && NumEntries_in_ThisDisk == 0\n        && NumEntries == 0\n        && Size == 0\n        && Offset == 0 // test it\n    ;\n  }\n\n  void Parse(const Byte *p); // (p) doesn't include signature\n};\n\nvoid CEcd::Parse(const Byte *p)\n{\n  // (p) doesn't include signature\n  G16(0, ThisDisk);\n  G16(2, CdDisk);\n  G16(4, NumEntries_in_ThisDisk);\n  G16(6, NumEntries);\n  G32(8, Size);\n  G32(12, Offset);\n  G16(16, CommentSize);\n}\n\n\nvoid CCdInfo::ParseEcd32(const Byte *p)\n{\n  IsFromEcd64 = false;\n  // (p) includes signature\n  p += 4;\n  G16(0, ThisDisk);\n  G16(2, CdDisk);\n  G16(4, NumEntries_in_ThisDisk);\n  G16(6, NumEntries);\n  G32(8, Size);\n  G32(12, Offset);\n  G16(16, CommentSize);\n}\n\nvoid CCdInfo::ParseEcd64e(const Byte *p)\n{\n  IsFromEcd64 = true;\n  // (p) exclude signature\n  G16(0, VersionMade);\n  G16(2, VersionNeedExtract);\n  G32(4, ThisDisk);\n  G32(8, CdDisk);\n\n  G64(12, NumEntries_in_ThisDisk);\n  G64(20, NumEntries);\n  G64(28, Size);\n  G64(36, Offset);\n}\n\n\nstruct CLocator\n{\n  UInt32 Ecd64Disk;\n  UInt32 NumDisks;\n  UInt64 Ecd64Offset;\n  \n  CLocator(): Ecd64Disk(0), NumDisks(0), Ecd64Offset(0) {}\n\n  void Parse(const Byte *p)\n  {\n    G32(0, Ecd64Disk);\n    G64(4, Ecd64Offset);\n    G32(12, NumDisks);\n  }\n\n  bool IsEmptyArc() const\n  {\n    return Ecd64Disk == 0 && NumDisks == 0 && Ecd64Offset == 0;\n  }\n};\n\n  \n\n\nvoid CInArchive::ClearRefs()\n{\n  StreamRef.Release();\n  Stream = NULL;\n  StartStream = NULL;\n  Callback = NULL;\n\n  Vols.Clear();\n}\n\nvoid CInArchive::Close()\n{\n  _cnt = 0;\n  DisableBufMode();\n\n  IsArcOpen = false;\n\n  IsArc = false;\n  IsZip64 = false;\n  \n  IsApk = false;\n  IsCdUnsorted = false;\n\n  HeadersError = false;\n  HeadersWarning = false;\n  ExtraMinorError = false;\n  \n  UnexpectedEnd = false;\n  LocalsWereRead = false;\n  LocalsCenterMerged = false;\n  NoCentralDir = false;\n  Overflow32bit = false;\n  Cd_NumEntries_Overflow_16bit = false;\n  \n  MarkerIsFound = false;\n  MarkerIsSafe = false;\n\n  IsMultiVol = false;\n  UseDisk_in_SingleVol = false;\n  EcdVolIndex = 0;\n \n  ArcInfo.Clear();\n\n  ClearRefs();\n}\n\n\n\nHRESULT CInArchive::Seek_SavePos(UInt64 offset)\n{\n  // InitBuf();\n  // if (!Stream) return S_FALSE;\n  return Stream->Seek((Int64)offset, STREAM_SEEK_SET, &_streamPos);\n}\n\n\n/* SeekToVol() will keep the cached mode, if new volIndex is\n   same Vols.StreamIndex volume, and offset doesn't go out of cached region */\n\nHRESULT CInArchive::SeekToVol(int volIndex, UInt64 offset)\n{\n  if (volIndex != Vols.StreamIndex)\n  {\n    if (IsMultiVol && volIndex >= 0)\n    {\n      if ((unsigned)volIndex >= Vols.Streams.Size())\n        return S_FALSE;\n      if (!Vols.Streams[(unsigned)volIndex].Stream)\n        return S_FALSE;\n      Stream = Vols.Streams[(unsigned)volIndex].Stream;\n    }\n    else if (volIndex == -2)\n    {\n      if (!Vols.ZipStream)\n        return S_FALSE;\n      Stream = Vols.ZipStream;\n    }\n    else\n      Stream = StartStream;\n    Vols.StreamIndex = volIndex;\n  }\n  else\n  {\n    if (offset <= _streamPos)\n    {\n      const UInt64 back = _streamPos - offset;\n      if (back <= _bufCached)\n      {\n        _bufPos = _bufCached - (size_t)back;\n        return S_OK;\n      }\n    }\n  }\n  InitBuf();\n  return Seek_SavePos(offset);\n}\n\n\nHRESULT CInArchive::AllocateBuffer(size_t size)\n{\n  if (size <= Buffer.Size())\n    return S_OK;\n  /* in cached mode virtual_pos is not equal to phy_pos (_streamPos)\n     so we change _streamPos and do Seek() to virtual_pos before cache clearing */\n  if (_bufPos != _bufCached)\n  {\n    RINOK(Seek_SavePos(GetVirtStreamPos()))\n  }\n  InitBuf();\n  Buffer.AllocAtLeast(size);\n  if (!Buffer.IsAllocated())\n    return E_OUTOFMEMORY;\n  return S_OK;\n}\n\n// ---------- ReadFromCache ----------\n// reads from cache and from Stream\n// move to next volume can be allowed if (CanStartNewVol) and only before first byte reading\n\nHRESULT CInArchive::ReadFromCache(Byte *data, unsigned size, unsigned &processed)\n{\n  HRESULT result = S_OK;\n  processed = 0;\n\n  for (;;)\n  {\n    if (size == 0)\n      return S_OK;\n    \n    const size_t avail = GetAvail();\n\n    if (avail != 0)\n    {\n      unsigned cur = size;\n      if (cur > avail)\n        cur = (unsigned)avail;\n      memcpy(data, (const Byte *)Buffer + _bufPos, cur);\n\n      data += cur;\n      size -= cur;\n      processed += cur;\n\n      _bufPos += cur;\n      _cnt += cur;\n\n      CanStartNewVol = false;\n      \n      continue;\n    }\n\n    InitBuf();\n\n    if (_inBufMode)\n    {\n      UInt32 cur = 0;\n      result = Stream->Read(Buffer, (UInt32)Buffer.Size(), &cur);\n      _bufPos = 0;\n      _bufCached = cur;\n      _streamPos += cur;\n      if (cur != 0)\n        CanStartNewVol = false;\n      if (result != S_OK)\n        break;\n      if (cur != 0)\n        continue;\n    }\n    else\n    {\n      size_t cur = size;\n      result = ReadStream(Stream, data, &cur);\n      data += cur;\n      size -= (unsigned)cur;\n      processed += (unsigned)cur;\n      _streamPos += cur;\n      _cnt += cur;\n      if (cur != 0)\n      {\n        CanStartNewVol = false;\n        break;\n      }\n      if (result != S_OK)\n        break;\n    }\n\n    if (   !IsMultiVol\n        || !CanStartNewVol\n        || Vols.StreamIndex < 0\n        || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())\n      break;\n\n    const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1];\n    if (!s.Stream)\n      break;\n    result = s.SeekToStart();\n    if (result != S_OK)\n      break;\n    Vols.StreamIndex++;\n    _streamPos = 0;\n    // Vols.NeedSeek = false;\n\n    Stream = s.Stream;\n  }\n\n  return result;\n}\n\n\nHRESULT CInArchive::ReadFromCache_FALSE(Byte *data, unsigned size)\n{\n  unsigned processed;\n  HRESULT res = ReadFromCache(data, size, processed);\n  if (res == S_OK && size != processed)\n    return S_FALSE;\n  return res;\n}\n\n\nstatic bool CheckDosTime(UInt32 dosTime)\n{\n  if (dosTime == 0)\n    return true;\n  unsigned month = (dosTime >> 21) & 0xF;\n  unsigned day = (dosTime >> 16) & 0x1F;\n  unsigned hour = (dosTime >> 11) & 0x1F;\n  unsigned min = (dosTime >> 5) & 0x3F;\n  unsigned sec = (dosTime & 0x1F) * 2;\n  if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)\n    return false;\n  return true;\n}\n\nAPI_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size)\n{\n  if (size < 8)\n    return k_IsArc_Res_NEED_MORE;\n  if (p[0] != 'P')\n    return k_IsArc_Res_NO;\n\n  UInt32 sig = Get32(p);\n\n  if (sig == NSignature::kNoSpan || sig == NSignature::kSpan)\n  {\n    p += 4;\n    size -= 4;\n  }\n\n  sig = Get32(p);\n\n  if (sig == NSignature::kEcd64)\n  {\n    if (size < kEcd64_FullSize)\n      return k_IsArc_Res_NEED_MORE;\n\n    const UInt64 recordSize = Get64(p + 4);\n    if (   recordSize < kEcd64_MainSize\n        || recordSize > kEcd64_MainSize + (1 << 20))\n      return k_IsArc_Res_NO;\n    CCdInfo cdInfo;\n    cdInfo.ParseEcd64e(p + 12);\n    if (!cdInfo.IsEmptyArc())\n      return k_IsArc_Res_NO;\n    return k_IsArc_Res_YES; // k_IsArc_Res_YES_2;\n  }\n\n  if (sig == NSignature::kEcd)\n  {\n    if (size < kEcdSize)\n      return k_IsArc_Res_NEED_MORE;\n    CEcd ecd;\n    ecd.Parse(p + 4);\n    // if (ecd.cdSize != 0)\n    if (!ecd.IsEmptyArc())\n      return k_IsArc_Res_NO;\n    return k_IsArc_Res_YES; // k_IsArc_Res_YES_2;\n  }\n \n  if (sig != NSignature::kLocalFileHeader)\n    return k_IsArc_Res_NO;\n\n  if (size < kLocalHeaderSize)\n    return k_IsArc_Res_NEED_MORE;\n  \n  p += 4;\n\n  {\n    const unsigned kPureHeaderSize = kLocalHeaderSize - 4;\n    unsigned i;\n    for (i = 0; i < kPureHeaderSize && p[i] == 0; i++);\n    if (i == kPureHeaderSize)\n      return k_IsArc_Res_NEED_MORE;\n  }\n\n  /*\n  if (p[0] >= 128) // ExtractVersion.Version;\n    return k_IsArc_Res_NO;\n  */\n\n  // ExtractVersion.Version = p[0];\n  // ExtractVersion.HostOS = p[1];\n  // Flags = Get16(p + 2);\n  // Method = Get16(p + 4);\n  /*\n  // 9.33: some zip archives contain incorrect value in timestamp. So we don't check it now\n  UInt32 dosTime = Get32(p + 6);\n  if (!CheckDosTime(dosTime))\n    return k_IsArc_Res_NO;\n  */\n  // Crc = Get32(p + 10);\n  // PackSize = Get32(p + 14);\n  // Size = Get32(p + 18);\n  const unsigned nameSize = Get16(p + 22);\n  unsigned extraSize = Get16(p + 24);\n  const UInt32 extraOffset = kLocalHeaderSize + (UInt32)nameSize;\n  \n  /*\n  // 21.02: fixed. we don't use the following check\n  if (extraOffset + extraSize > (1 << 16))\n    return k_IsArc_Res_NO;\n  */\n\n  p -= 4;\n\n  {\n    size_t rem = size - kLocalHeaderSize;\n    if (rem > nameSize)\n      rem = nameSize;\n    const Byte *p2 = p + kLocalHeaderSize;\n    for (size_t i = 0; i < rem; i++)\n      if (p2[i] == 0)\n      {\n        // we support some \"bad\" zip archives that contain zeros after name\n        for (size_t k = i + 1; k < rem; k++)\n          if (p2[k] != 0)\n            return k_IsArc_Res_NO;\n        break;\n        /*\n        if (i != nameSize - 1)\n          return k_IsArc_Res_NO;\n        */\n      }\n  }\n\n  if (size < extraOffset)\n    return k_IsArc_Res_NEED_MORE;\n\n  if (extraSize > 0)\n  {\n    p += extraOffset;\n    size -= extraOffset;\n    while (extraSize != 0)\n    {\n      if (extraSize < 4)\n      {\n        // 7-Zip before 9.31 created incorrect WzAES Extra in folder's local headers.\n        // so we return k_IsArc_Res_YES to support such archives.\n        // return k_IsArc_Res_NO; // do we need to support such extra ?\n        return k_IsArc_Res_YES;\n      }\n      if (size < 4)\n        return k_IsArc_Res_NEED_MORE;\n      unsigned dataSize = Get16(p + 2);\n      size -= 4;\n      extraSize -= 4;\n      p += 4;\n      if (dataSize > extraSize)\n      {\n        // It can be error on header.\n        // We want to support such rare case bad archives.\n        // We use additional checks to reduce false-positive probability.\n        if (nameSize == 0\n            || nameSize > (1 << 9)\n            || extraSize > (1 << 9))\n          return k_IsArc_Res_NO;\n        return k_IsArc_Res_YES;\n      }\n      if (dataSize > size)\n        return k_IsArc_Res_NEED_MORE;\n      size -= dataSize;\n      extraSize -= dataSize;\n      p += dataSize;\n    }\n  }\n  \n  return k_IsArc_Res_YES;\n}\n\nstatic UInt32 IsArc_Zip_2(const Byte *p, size_t size, bool isFinal)\n{\n  UInt32 res = IsArc_Zip(p, size);\n  if (res == k_IsArc_Res_NEED_MORE && isFinal)\n    return k_IsArc_Res_NO;\n  return res;\n}\n\n\n  \n/* FindPK_4() is allowed to access data up to and including &limit[3].\n   limit[4] access is not allowed.\n  return:\n    (return_ptr <  limit) : \"PK\" was found at (return_ptr)\n    (return_ptr >= limit) : limit was reached or crossed. So no \"PK\" found before limit\n*/\nZ7_NO_INLINE\nstatic const Byte *FindPK_4(const Byte *p, const Byte *limit)\n{\n  for (;;)\n  {\n    for (;;)\n    {\n      if (p >= limit)\n        return limit;\n      Byte b = p[1];\n      if (b == 0x4B) { if (p[0] == 0x50) { return p;     } p += 1; break; }\n      if (b == 0x50) { if (p[2] == 0x4B) { return p + 1; } p += 2; break; }\n      b = p[3];\n      p += 4;\n      if (b == 0x4B) { if (p[-2]== 0x50) { return p - 2; } p -= 1; break; }\n      if (b == 0x50) { if (p[0] == 0x4B) { return p - 1; }         break; }\n    }\n  }\n  /*\n  for (;;)\n  {\n    for (;;)\n    {\n      if (p >= limit)\n        return limit;\n      if (*p++ == 0x50) break;\n      if (*p++ == 0x50) break;\n      if (*p++ == 0x50) break;\n      if (*p++ == 0x50) break;\n    }\n    if (*p == 0x4B)\n      return p - 1;\n  }\n  */\n}\n\n\n/*\n---------- FindMarker ----------\nreturns:\n  S_OK:\n    ArcInfo.MarkerVolIndex : volume of marker\n    ArcInfo.MarkerPos   : Pos of first signature\n    ArcInfo.MarkerPos2  : Pos of main signature (local item signature in most cases)\n    _streamPos          : stream pos\n    _cnt                : The number of virtal Bytes after start of search to offset after signature\n    _signature          : main signature\n \n  S_FALSE: can't find marker, or there is some non-zip data after marker\n\n  Error code: stream reading error.\n*/\n\nHRESULT CInArchive::FindMarker(const UInt64 *searchLimit)\n{\n  ArcInfo.MarkerPos = GetVirtStreamPos();\n  ArcInfo.MarkerPos2 = ArcInfo.MarkerPos;\n  ArcInfo.MarkerVolIndex = Vols.StreamIndex;\n\n  _cnt = 0;\n\n  CanStartNewVol = false;\n\n  if (searchLimit && *searchLimit == 0)\n  {\n    Byte startBuf[kMarkerSize];\n    RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize))\n\n    UInt32 marker = Get32(startBuf);\n    _signature = marker;\n\n    if (   marker == NSignature::kNoSpan\n        || marker == NSignature::kSpan)\n    {\n      RINOK(ReadFromCache_FALSE(startBuf, kMarkerSize))\n      _signature = Get32(startBuf);\n    }\n      \n    if (   _signature != NSignature::kEcd\n        && _signature != NSignature::kEcd64\n        && _signature != NSignature::kLocalFileHeader)\n      return S_FALSE;\n\n    ArcInfo.MarkerPos2 = GetVirtStreamPos() - 4;\n    ArcInfo.IsSpanMode = (marker == NSignature::kSpan);\n\n    // we use weak test in case of (*searchLimit == 0)\n    // since error will be detected later in Open function\n    return S_OK;\n  }\n\n  // zip specification: (_zip_header_size < (1 << 16))\n  // so we need such size to check header\n  const size_t kCheckSize = (size_t)1 << 16;\n  const size_t kBufSize   = (size_t)1 << 17; // (kBufSize must be > kCheckSize)\n\n  RINOK(AllocateBuffer(kBufSize))\n\n  _inBufMode = true;\n\n  UInt64 progressPrev = 0;\n\n  for (;;)\n  {\n    RINOK(LookAhead(kBufSize))\n    \n    const size_t avail = GetAvail();\n    \n    size_t limitPos;\n    // (avail > kBufSize) is possible, if (Buffer.Size() > kBufSize)\n    const bool isFinished = (avail < kBufSize);\n    if (isFinished)\n    {\n      const unsigned kMinAllowed = 4;\n      if (avail <= kMinAllowed)\n      {\n        if (   !IsMultiVol\n            || Vols.StreamIndex < 0\n            || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())\n          break;\n\n        SkipLookahed(avail);\n\n        const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1];\n        if (!s.Stream)\n          break;\n        \n        RINOK(s.SeekToStart())\n        \n        InitBuf();\n        Vols.StreamIndex++;\n        _streamPos = 0;\n        Stream = s.Stream;\n        continue;\n      }\n      limitPos = avail - kMinAllowed;\n    }\n    else\n      limitPos = (avail - kCheckSize);\n\n    // we don't check at (limitPos) for good fast aligned operations\n\n    if (searchLimit)\n    {\n      if (_cnt > *searchLimit)\n        break;\n      UInt64 rem = *searchLimit - _cnt;\n      if (limitPos > rem)\n        limitPos = (size_t)rem + 1;\n    }\n\n    if (limitPos == 0)\n      break;\n\n    const Byte * const pStart = Buffer + _bufPos;\n    const Byte * p = pStart;\n    const Byte * const limit = pStart + limitPos;\n   \n    for (;; p++)\n    {\n      p = FindPK_4(p, limit);\n      if (p >= limit)\n        break;\n      size_t rem = (size_t)(pStart + avail - p);\n      /* 22.02 : we limit check size with kCheckSize to be consistent for\n         any different combination of _bufPos in Buffer and size of Buffer. */\n      if (rem > kCheckSize)\n        rem = kCheckSize;\n      const UInt32 res = IsArc_Zip_2(p, rem, isFinished);\n      if (res != k_IsArc_Res_NO)\n      {\n        if (rem < kMarkerSize)\n          return S_FALSE;\n        _signature = Get32(p);\n        SkipLookahed((size_t)(p - pStart));\n        ArcInfo.MarkerVolIndex = Vols.StreamIndex;\n        ArcInfo.MarkerPos = GetVirtStreamPos();\n        ArcInfo.MarkerPos2 = ArcInfo.MarkerPos;\n        SkipLookahed(4);\n        if (   _signature == NSignature::kNoSpan\n            || _signature == NSignature::kSpan)\n        {\n          if (rem < kMarkerSize * 2)\n            return S_FALSE;\n          ArcInfo.IsSpanMode = (_signature == NSignature::kSpan);\n          _signature = Get32(p + 4);\n          ArcInfo.MarkerPos2 += 4;\n          SkipLookahed(4);\n        }\n        return S_OK;\n      }\n    }\n\n    if (!IsMultiVol && isFinished)\n      break;\n\n    SkipLookahed((size_t)(p - pStart));\n\n    if (Callback && (_cnt - progressPrev) >= ((UInt32)1 << 23))\n    {\n      progressPrev = _cnt;\n      // const UInt64 numFiles64 = 0;\n      RINOK(Callback->SetCompleted(NULL, &_cnt))\n    }\n  }\n  \n  return S_FALSE;\n}\n\n\n/*\n---------- IncreaseRealPosition ----------\nmoves virtual offset in virtual stream.\nchanging to new volumes is allowed\n*/\n\nHRESULT CInArchive::IncreaseRealPosition(UInt64 offset, bool &isFinished)\n{\n  isFinished = false;\n\n  for (;;)\n  {\n    const size_t avail = GetAvail();\n    \n    if (offset <= avail)\n    {\n      _bufPos += (size_t)offset;\n      _cnt += offset;\n      return S_OK;\n    }\n    \n    _cnt += avail;\n    offset -= avail;\n    \n    _bufCached = 0;\n    _bufPos = 0;\n    \n    if (!_inBufMode)\n      break;\n  \n    CanStartNewVol = true;\n    LookAhead(1);\n\n    if (GetAvail() == 0)\n      return S_OK;\n  }\n\n  // cache is empty\n\n  if (!IsMultiVol)\n  {\n    _cnt += offset;\n    return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos);\n  }\n\n  for (;;)\n  {\n    if (offset == 0)\n      return S_OK;\n    \n    if (Vols.StreamIndex < 0)\n      return S_FALSE;\n    if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())\n    {\n      isFinished = true;\n      return S_OK;\n    }\n    {\n      const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex];\n      if (!s.Stream)\n      {\n        isFinished = true;\n        return S_OK;\n      }\n      if (_streamPos > s.Size)\n        return S_FALSE;\n      const UInt64 rem = s.Size - _streamPos;\n      if ((UInt64)offset <= rem)\n      {\n        _cnt += offset;\n        return Stream->Seek((Int64)offset, STREAM_SEEK_CUR, &_streamPos);\n      }\n      RINOK(Seek_SavePos(s.Size))\n      offset -= rem;\n      _cnt += rem;\n    }\n    \n    Stream = NULL;\n    _streamPos = 0;\n    Vols.StreamIndex++;\n    if ((unsigned)Vols.StreamIndex >= Vols.Streams.Size())\n    {\n      isFinished = true;\n      return S_OK;\n    }\n    const CVols::CSubStreamInfo &s2 = Vols.Streams[(unsigned)Vols.StreamIndex];\n    if (!s2.Stream)\n    {\n      isFinished = true;\n      return S_OK;\n    }\n    Stream = s2.Stream;\n    RINOK(Seek_SavePos(0))\n  }\n}\n\n\n\n/*\n---------- LookAhead ----------\nReads data to buffer, if required.\n\nIt can read from volumes as long as Buffer.Size().\nBut it moves to new volume, only if it's required to provide minRequired bytes in buffer.\n\nin:\n  (minRequired <= Buffer.Size())\n\nreturn:\n  S_OK : if (GetAvail() < minRequired) after function return, it's end of stream(s) data, or no new volume stream.\n  Error codes: IInStream::Read() error or IInStream::Seek() error for multivol\n*/\n\nHRESULT CInArchive::LookAhead(size_t minRequired)\n{\n  for (;;)\n  {\n    const size_t avail = GetAvail();\n\n    if (minRequired <= avail)\n      return S_OK;\n    \n    if (_bufPos != 0)\n    {\n      if (avail != 0)\n        memmove(Buffer, Buffer + _bufPos, avail);\n      _bufPos = 0;\n      _bufCached = avail;\n    }\n\n    const size_t pos = _bufCached;\n    UInt32 processed = 0;\n    HRESULT res = Stream->Read(Buffer + pos, (UInt32)(Buffer.Size() - pos), &processed);\n    _streamPos += processed;\n    _bufCached += processed;\n\n    if (res != S_OK)\n      return res;\n\n    if (processed != 0)\n      continue;\n\n    if (   !IsMultiVol\n        || !CanStartNewVol\n        || Vols.StreamIndex < 0\n        || (unsigned)Vols.StreamIndex + 1 >= Vols.Streams.Size())\n      return S_OK;\n\n    const CVols::CSubStreamInfo &s = Vols.Streams[(unsigned)Vols.StreamIndex + 1];\n    if (!s.Stream)\n      return S_OK;\n    \n    RINOK(s.SeekToStart())\n\n    Vols.StreamIndex++;\n    _streamPos = 0;\n    Stream = s.Stream;\n    // Vols.NeedSeek = false;\n  }\n}\n\n\nclass CUnexpectEnd {};\n\n\n/*\n---------- SafeRead ----------\n\nreads data of exact size from stream(s)\n\nin:\n  _inBufMode\n  if (CanStartNewVol) it can go to next volume before first byte reading, if there is end of volume data.\n\nin, out:\n  _streamPos  :  position in Stream\n  Stream\n  Vols  :  if (IsMultiVol)\n  _cnt\n\nout:\n  (CanStartNewVol == false), if some data was read\n\nreturn:\n  S_OK : success reading of requested data\n\nexceptions:\n  CSystemException() - stream reading error\n  CUnexpectEnd()  :  could not read data of requested size\n*/\n\nvoid CInArchive::SafeRead(Byte *data, unsigned size)\n{\n  unsigned processed;\n  HRESULT result = ReadFromCache(data, size, processed);\n  if (result != S_OK)\n    throw CSystemException(result);\n  if (size != processed)\n    throw CUnexpectEnd();\n}\n\nvoid CInArchive::ReadBuffer(CByteBuffer &buffer, unsigned size)\n{\n  buffer.Alloc(size);\n  if (size != 0)\n    SafeRead(buffer, size);\n}\n\n// Byte CInArchive::ReadByte  () { Byte b;      SafeRead(&b, 1); return b; }\n// UInt16 CInArchive::ReadUInt16() { Byte buf[2]; SafeRead(buf, 2); return Get16(buf); }\nUInt32 CInArchive::ReadUInt32() { Byte buf[4]; SafeRead(buf, 4); return Get32(buf); }\nUInt64 CInArchive::ReadUInt64() { Byte buf[8]; SafeRead(buf, 8); return Get64(buf); }\n\nvoid CInArchive::ReadSignature()\n{\n  CanStartNewVol = true;\n  _signature = ReadUInt32();\n  // CanStartNewVol = false; // it's already changed in SafeRead\n}\n\n\n// we Skip() inside headers only, so no need for stream change in multivol.\n\nvoid CInArchive::Skip(size_t num)\n{\n  while (num != 0)\n  {\n    const unsigned kBufSize = (size_t)1 << 10;\n    Byte buf[kBufSize];\n    unsigned step = kBufSize;\n    if (step > num)\n      step = (unsigned)num;\n    SafeRead(buf, step);\n    num -= step;\n  }\n}\n\n/*\nHRESULT CInArchive::Callback_Completed(unsigned numFiles)\n{\n  const UInt64 numFiles64 = numFiles;\n  return Callback->SetCompleted(&numFiles64, &_cnt);\n}\n*/\n\nHRESULT CInArchive::Skip64(UInt64 num, unsigned numFiles)\n{\n  if (num == 0)\n    return S_OK;\n\n  for (;;)\n  {\n    size_t step = (size_t)1 << 24;\n    if (step > num)\n      step = (size_t)num;\n    Skip(step);\n    num -= step;\n    if (num == 0)\n      return S_OK;\n    if (Callback)\n    {\n      const UInt64 numFiles64 = numFiles;\n      RINOK(Callback->SetCompleted(&numFiles64, &_cnt))\n    }\n  }\n}\n\n\nbool CInArchive::ReadFileName(unsigned size, AString &s)\n{\n  if (size == 0)\n  {\n    s.Empty();\n    return true;\n  }\n  char *p = s.GetBuf(size);\n  SafeRead((Byte *)p, size);\n  unsigned i = size;\n  do\n  {\n    if (p[i - 1] != 0)\n      break;\n  }\n  while (--i);\n  s.ReleaseBuf_CalcLen(size);\n  return s.Len() == i;\n}\n\n\n#define ZIP64_IS_32_MAX(n) ((n) == 0xFFFFFFFF)\n#define ZIP64_IS_16_MAX(n) ((n) == 0xFFFF)\n\n\nbool CInArchive::ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra,\n    UInt64 &unpackSize, UInt64 &packSize,\n    CItem *cdItem)\n{\n  extra.Clear();\n  \n  while (extraSize >= 4)\n  {\n    CExtraSubBlock subBlock;\n    const UInt32 pair = ReadUInt32();\n    subBlock.ID = (pair & 0xFFFF);\n    unsigned size = (unsigned)(pair >> 16);\n    // const unsigned origSize = size;\n    \n    extraSize -= 4;\n    \n    if (size > extraSize)\n    {\n      // it's error in extra\n      HeadersWarning = true;\n      extra.Error = true;\n      Skip(extraSize);\n      return false;\n    }\n \n    extraSize -= size;\n    \n    if (subBlock.ID == NFileHeader::NExtraID::kZip64)\n    {\n      extra.IsZip64 = true;\n      bool isOK = true;\n\n      if (!cdItem\n          && size == 16\n          && !ZIP64_IS_32_MAX(unpackSize)\n          && !ZIP64_IS_32_MAX(packSize))\n      {\n        /* Win10 Explorer's \"Send to Zip\" for big (3500 MiB) files\n           creates Zip64 Extra in local file header.\n           But if both uncompressed and compressed sizes are smaller than 4 GiB,\n           Win10 doesn't store 0xFFFFFFFF in 32-bit fields as expected by zip specification.\n           21.04: we ignore these minor errors in Win10 zip archives. */\n        if (ReadUInt64() != unpackSize)\n          isOK = false;\n        if (ReadUInt64() != packSize)\n          isOK = false;\n        size = 0;\n      }\n      else\n      {\n        if (ZIP64_IS_32_MAX(unpackSize))\n          { if (size < 8) isOK = false; else { size -= 8; unpackSize = ReadUInt64(); }}\n      \n        if (isOK && ZIP64_IS_32_MAX(packSize))\n          { if (size < 8) isOK = false; else { size -= 8; packSize = ReadUInt64(); }}\n      \n        if (cdItem)\n        {\n          if (isOK)\n          {\n            if (ZIP64_IS_32_MAX(cdItem->LocalHeaderPos))\n              { if (size < 8) isOK = false; else { size -= 8; cdItem->LocalHeaderPos = ReadUInt64(); }}\n            /*\n            else if (size == 8)\n            {\n              size -= 8;\n              const UInt64 v = ReadUInt64();\n              // soong_zip, an AOSP tool (written in the Go) writes incorrect value.\n              // we can ignore that minor error here\n              if (v != cdItem->LocalHeaderPos)\n                isOK = false; // ignore error\n              // isOK = false; // force error\n            }\n            */\n          }\n         \n          if (isOK && ZIP64_IS_16_MAX(cdItem->Disk))\n            { if (size < 4) isOK = false; else { size -= 4; cdItem->Disk = ReadUInt32(); }}\n        }\n      }\n    \n      // we can ignore errors, when some zip archiver still write all fields to zip64 extra in local header\n      // if (&& (cdItem || !isOK || origSize != 8 * 3 + 4 || size != 8 * 1 + 4))\n      if (!isOK || size != 0)\n      {\n        HeadersWarning = true;\n        extra.Error = true;\n        extra.IsZip64_Error = true;\n      }\n      Skip(size);\n    }\n    else\n    {\n      ReadBuffer(subBlock.Data, size);\n      extra.SubBlocks.Add(subBlock);\n      if (subBlock.ID == NFileHeader::NExtraID::kIzUnicodeName)\n      {\n        if (!subBlock.CheckIzUnicode(item.Name))\n          extra.Error = true;\n      }\n    }\n  }\n\n  if (extraSize != 0)\n  {\n    ExtraMinorError = true;\n    extra.MinorError = true;\n    // 7-Zip before 9.31 created incorrect WzAES Extra in folder's local headers.\n    // so we don't return false, but just set warning flag\n    // return false;\n    Skip(extraSize);\n  }\n\n  return true;\n}\n\n\nbool CInArchive::ReadLocalItem(CItemEx &item)\n{\n  item.Disk = 0;\n  if (IsMultiVol && Vols.StreamIndex >= 0)\n    item.Disk = (UInt32)Vols.StreamIndex;\n  const unsigned kPureHeaderSize = kLocalHeaderSize - 4;\n  Byte p[kPureHeaderSize];\n  SafeRead(p, kPureHeaderSize);\n  {\n    unsigned i;\n    for (i = 0; i < kPureHeaderSize && p[i] == 0; i++);\n    if (i == kPureHeaderSize)\n      return false;\n  }\n\n  item.ExtractVersion.Version = p[0];\n  item.ExtractVersion.HostOS = p[1];\n  G16(2, item.Flags);\n  G16(4, item.Method);\n  G32(6, item.Time);\n  G32(10, item.Crc);\n  G32(14, item.PackSize);\n  G32(18, item.Size);\n  const unsigned nameSize = Get16(p + 22);\n  const unsigned extraSize = Get16(p + 24);\n  bool isOkName = ReadFileName(nameSize, item.Name);\n  item.LocalFullHeaderSize = kLocalHeaderSize + (UInt32)nameSize + extraSize;\n  item.DescriptorWasRead = false;\n\n  /*\n  if (item.IsDir())\n    item.Size = 0; // check It\n  */\n\n  if (extraSize > 0)\n  {\n    if (!ReadExtra(item, extraSize, item.LocalExtra, item.Size, item.PackSize, NULL))\n    {\n      /* Most of archives are OK for Extra. But there are some rare cases\n         that have error. And if error in first item, it can't open archive.\n         So we ignore that error */\n      // return false;\n    }\n  }\n  \n  if (!CheckDosTime(item.Time))\n  {\n    HeadersWarning = true;\n    // return false;\n  }\n  \n  if (item.Name.Len() != nameSize)\n  {\n    // we support some \"bad\" zip archives that contain zeros after name\n    if (!isOkName)\n      return false;\n    HeadersWarning = true;\n  }\n  \n  // return item.LocalFullHeaderSize <= ((UInt32)1 << 16);\n  return true;\n}\n\n\nstatic bool FlagsAreSame(const CItem &i1, const CItem &i2_cd)\n{\n  if (i1.Method != i2_cd.Method)\n    return false;\n  \n  UInt32 mask = i1.Flags ^ i2_cd.Flags;\n  if (mask == 0)\n    return true;\n  switch (i1.Method)\n  {\n    case NFileHeader::NCompressionMethod::kDeflate:\n      mask &= 0x7FF9;\n      break;\n    default:\n      if (i1.Method <= NFileHeader::NCompressionMethod::kImplode)\n        mask &= 0x7FFF;\n  }\n\n  // we can ignore utf8 flag, if name is ascii, or if only cdItem has utf8 flag\n  if (mask & NFileHeader::NFlags::kUtf8)\n    if ((i1.Name.IsAscii() && i2_cd.Name.IsAscii())\n        || (i2_cd.Flags & NFileHeader::NFlags::kUtf8))\n      mask &= ~NFileHeader::NFlags::kUtf8;\n\n  // some bad archive in rare case can use descriptor without descriptor flag in Central Dir\n  // if (i1.HasDescriptor())\n  mask &= ~NFileHeader::NFlags::kDescriptorUsedMask;\n  \n  return (mask == 0);\n}\n\n\n// #ifdef _WIN32\nstatic bool AreEqualPaths_IgnoreSlashes(const char *s1, const char *s2)\n{\n  for (;;)\n  {\n    char c1 = *s1++;\n    char c2 = *s2++;\n    if (c1 == c2)\n    {\n      if (c1 == 0)\n        return true;\n    }\n    else\n    {\n      if (c1 == '\\\\') c1 = '/';\n      if (c2 == '\\\\') c2 = '/';\n      if (c1 != c2)\n        return false;\n    }\n  }\n}\n// #endif\n\n\nstatic bool AreItemsEqual(const CItemEx &localItem, const CItemEx &cdItem)\n{\n  if (!FlagsAreSame(localItem, cdItem))\n    return false;\n  if (!localItem.HasDescriptor())\n  {\n    if (cdItem.PackSize != localItem.PackSize\n        || cdItem.Size != localItem.Size\n        || (cdItem.Crc != localItem.Crc && cdItem.Crc != 0)) // some program writes 0 to crc field in central directory\n      return false;\n  }\n  /* pkzip 2.50 creates incorrect archives. It uses\n       - WIN encoding for name in local header\n       - OEM encoding for name in central header\n     We don't support these strange items. */\n\n  /* if (cdItem.Name.Len() != localItem.Name.Len())\n    return false;\n  */\n  if (cdItem.Name != localItem.Name)\n  {\n    // #ifdef _WIN32\n    // some xap files use backslash in central dir items.\n    // we can ignore such errors in windows, where all slashes are converted to backslashes\n    unsigned hostOs = cdItem.GetHostOS();\n    \n    if (hostOs == NFileHeader::NHostOS::kFAT ||\n        hostOs == NFileHeader::NHostOS::kNTFS)\n    {\n      if (!AreEqualPaths_IgnoreSlashes(cdItem.Name, localItem.Name))\n      {\n        // pkzip 2.50 uses DOS encoding in central dir and WIN encoding in local header.\n        // so we ignore that error\n        if (hostOs != NFileHeader::NHostOS::kFAT\n            || cdItem.MadeByVersion.Version < 25\n            || cdItem.MadeByVersion.Version > 40)\n          return false;\n      }\n    }\n    /*\n    else\n    #endif\n      return false;\n    */\n  }\n  return true;\n}\n\n\nHRESULT CInArchive::Read_LocalItem_After_CdItem(CItemEx &item, bool &isAvail, bool &headersError)\n{\n  isAvail = true;\n  headersError = false;\n  if (item.FromLocal)\n    return S_OK;\n  try\n  {\n    UInt64 offset = item.LocalHeaderPos;\n\n    if (IsMultiVol)\n    {\n      if (item.Disk >= Vols.Streams.Size())\n      {\n        isAvail = false;\n        return S_FALSE;\n      }\n      Stream = Vols.Streams[item.Disk].Stream;\n      Vols.StreamIndex = (int)item.Disk;\n      if (!Stream)\n      {\n        isAvail = false;\n        return S_FALSE;\n      }\n    }\n    else\n    {\n      if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex)\n      {\n        isAvail = false;\n        return S_FALSE;\n      }\n      Stream = StreamRef;\n\n      offset = (UInt64)((Int64)offset + ArcInfo.Base);\n      if (ArcInfo.Base < 0 && (Int64)offset < 0)\n      {\n        isAvail = false;\n        return S_FALSE;\n      }\n    }\n\n    _inBufMode = false;\n    RINOK(Seek_SavePos(offset))\n    InitBuf();\n    /*\n    // we can use buf mode with small buffer to reduce\n    // the number of Read() calls in ReadLocalItem()\n    _inBufMode = true;\n    Buffer.Alloc(1 << 10);\n    if (!Buffer.IsAllocated())\n      return E_OUTOFMEMORY;\n    */\n\n    CItemEx localItem;\n    if (ReadUInt32() != NSignature::kLocalFileHeader)\n      return S_FALSE;\n    ReadLocalItem(localItem);\n    if (!AreItemsEqual(localItem, item))\n      return S_FALSE;\n    item.LocalFullHeaderSize = localItem.LocalFullHeaderSize;\n    item.LocalExtra = localItem.LocalExtra;\n    if (item.Crc != localItem.Crc && !localItem.HasDescriptor())\n    {\n      item.Crc = localItem.Crc;\n      headersError = true;\n    }\n    if ((item.Flags ^ localItem.Flags) & NFileHeader::NFlags::kDescriptorUsedMask)\n    {\n      item.Flags = (UInt16)(item.Flags ^ NFileHeader::NFlags::kDescriptorUsedMask);\n      headersError = true;\n    }\n    item.FromLocal = true;\n  }\n  catch(...) { return S_FALSE; }\n  return S_OK;\n}\n\n\n/*\n---------- FindDescriptor ----------\n\nin:\n  _streamPos : position in Stream\n  Stream :\n  Vols : if (IsMultiVol)\n\naction:\n  searches descriptor in input stream(s).\n  sets\n    item.DescriptorWasRead = true;\n    item.Size\n    item.PackSize\n    item.Crc\n  if descriptor was found\n\nout:\n  S_OK:\n      if ( item.DescriptorWasRead) : if descriptor was found\n      if (!item.DescriptorWasRead) : if descriptor was not found : unexpected end of stream(s)\n\n  S_FALSE: if no items or there is just one item with strange properies that doesn't look like real archive.\n\n  another error code: Callback error.\n\nexceptions :\n  CSystemException() : stream reading error\n*/\n\nHRESULT CInArchive::FindDescriptor(CItemEx &item, unsigned numFiles)\n{\n  // const size_t kBufSize = (size_t)1 << 5; // don't increase it too much. It reads data look ahead.\n\n  // Buffer.Alloc(kBufSize);\n  // Byte *buf = Buffer;\n  \n  UInt64 packedSize = 0;\n  \n  UInt64 progressPrev = _cnt;\n\n  for (;;)\n  {\n    /* appnote specification claims that we must use 64-bit descriptor, if there is zip64 extra.\n       But some old third-party xps archives used 64-bit descriptor without zip64 extra. */\n    // unsigned descriptorSize = kDataDescriptorSize64 + kNextSignatureSize;\n    \n    // const unsigned kNextSignatureSize = 0;  // we can disable check for next signatuire\n    const unsigned kNextSignatureSize = 4;  // we check also for signature for next File headear\n\n    const unsigned descriptorSize4 = item.GetDescriptorSize() + kNextSignatureSize;\n\n    if (descriptorSize4 > Buffer.Size()) return E_FAIL;\n\n    // size_t processedSize;\n    CanStartNewVol = true;\n    RINOK(LookAhead(descriptorSize4))\n    const size_t avail = GetAvail();\n    \n    if (avail < descriptorSize4)\n    {\n      // we write to packSize all these available bytes.\n      // later it's simpler to work with such value than with 0\n      // if (item.PackSize == 0)\n        item.PackSize = packedSize + avail;\n      if (item.Method == 0)\n        item.Size = item.PackSize;\n      SkipLookahed(avail);\n      return S_OK;\n    }\n\n    const Byte * const pStart = Buffer + _bufPos;\n    const Byte * p = pStart;\n    const Byte * const limit = pStart + (avail - descriptorSize4);\n    \n    for (; p <= limit; p++)\n    {\n      // descriptor signature field is Info-ZIP's extension to pkware Zip specification.\n      // New ZIP specification also allows descriptorSignature.\n      \n      p = FindPK_4(p, limit + 1);\n      if (p > limit)\n        break;\n\n      /*\n      if (*p != 0x50)\n        continue;\n      */\n\n      if (Get32(p) != NSignature::kDataDescriptor)\n        continue;\n\n      // we check next signatuire after descriptor\n      // maybe we need check only 2 bytes \"PK\" instead of 4 bytes, if some another type of header is possible after descriptor\n      const UInt32 sig = Get32(p + descriptorSize4 - kNextSignatureSize);\n      if (   sig != NSignature::kLocalFileHeader\n          && sig != NSignature::kCentralFileHeader)\n        continue;\n\n      const UInt64 packSizeCur = packedSize + (size_t)(p - pStart);\n      if (descriptorSize4 == kDataDescriptorSize64 + kNextSignatureSize) // if (item.LocalExtra.IsZip64)\n      {\n        const UInt64 descriptorPackSize = Get64(p + 8);\n        if (descriptorPackSize != packSizeCur)\n          continue;\n        item.Size = Get64(p + 16);\n      }\n      else\n      {\n        const UInt32 descriptorPackSize = Get32(p + 8);\n        if (descriptorPackSize != (UInt32)packSizeCur)\n          continue;\n        item.Size = Get32(p + 12);\n        // that item.Size can be truncated to 32-bit value here\n      }\n      // We write calculated 64-bit packSize, even if descriptor64 was not used\n      item.PackSize = packSizeCur;\n      \n      item.DescriptorWasRead = true;\n      item.Crc = Get32(p + 4);\n\n      const size_t skip = (size_t)(p - pStart) + descriptorSize4 - kNextSignatureSize;\n\n      SkipLookahed(skip);\n\n      return S_OK;\n    }\n    \n    const size_t skip = (size_t)(p - pStart);\n    SkipLookahed(skip);\n\n    packedSize += skip;\n\n    if (Callback)\n    if (_cnt - progressPrev >= ((UInt32)1 << 22))\n    {\n      progressPrev = _cnt;\n      const UInt64 numFiles64 = numFiles;\n      RINOK(Callback->SetCompleted(&numFiles64, &_cnt))\n    }\n  }\n}\n\n\nHRESULT CInArchive::CheckDescriptor(const CItemEx &item)\n{\n  if (!item.HasDescriptor())\n    return S_OK;\n  \n  // pkzip's version without descriptor signature is not supported\n  \n  bool isFinished = false;\n  RINOK(IncreaseRealPosition(item.PackSize, isFinished))\n  if (isFinished)\n    return S_FALSE;\n\n  /*\n  if (!IsMultiVol)\n  {\n    RINOK(Seek_SavePos(ArcInfo.Base + item.GetDataPosition() + item.PackSize));\n  }\n  */\n  \n  Byte buf[kDataDescriptorSize64];\n  try\n  {\n    CanStartNewVol = true;\n    SafeRead(buf, item.GetDescriptorSize());\n  }\n  catch (const CSystemException &e) { return e.ErrorCode; }\n  // catch (const CUnexpectEnd &)\n  catch(...)\n  {\n    return S_FALSE;\n  }\n  // RINOK(ReadStream_FALSE(Stream, buf, item.GetDescriptorSize()));\n\n  if (Get32(buf) != NSignature::kDataDescriptor)\n    return S_FALSE;\n  UInt32 crc = Get32(buf + 4);\n  UInt64 packSize, unpackSize;\n  \n  if (item.LocalExtra.IsZip64)\n  {\n    packSize = Get64(buf + 8);\n    unpackSize = Get64(buf + 16);\n  }\n  else\n  {\n    packSize = Get32(buf + 8);\n    unpackSize = Get32(buf + 12);\n  }\n  \n  if (crc != item.Crc || item.PackSize != packSize || item.Size != unpackSize)\n    return S_FALSE;\n  return S_OK;\n}\n\n\nHRESULT CInArchive::Read_LocalItem_After_CdItem_Full(CItemEx &item)\n{\n  if (item.FromLocal)\n    return S_OK;\n  try\n  {\n    bool isAvail = true;\n    bool headersError = false;\n    RINOK(Read_LocalItem_After_CdItem(item, isAvail, headersError))\n    if (headersError)\n      return S_FALSE;\n    if (item.HasDescriptor())\n      return CheckDescriptor(item);\n  }\n  catch(...) { return S_FALSE; }\n  return S_OK;\n}\n  \n\nHRESULT CInArchive::ReadCdItem(CItemEx &item)\n{\n  item.FromCentral = true;\n  Byte p[kCentralHeaderSize - 4];\n  SafeRead(p, kCentralHeaderSize - 4);\n\n  item.MadeByVersion.Version = p[0];\n  item.MadeByVersion.HostOS = p[1];\n  item.ExtractVersion.Version = p[2];\n  item.ExtractVersion.HostOS = p[3];\n  G16(4, item.Flags);\n  G16(6, item.Method);\n  G32(8, item.Time);\n  G32(12, item.Crc);\n  G32(16, item.PackSize);\n  G32(20, item.Size);\n  const unsigned nameSize = Get16(p + 24);\n  const unsigned extraSize = Get16(p + 26);\n  const unsigned commentSize = Get16(p + 28);\n  G16(30, item.Disk);\n  G16(32, item.InternalAttrib);\n  G32(34, item.ExternalAttrib);\n  G32(38, item.LocalHeaderPos);\n  ReadFileName(nameSize, item.Name);\n  \n  if (extraSize > 0)\n    ReadExtra(item, extraSize, item.CentralExtra, item.Size, item.PackSize, &item);\n\n  // May be these strings must be deleted\n  /*\n  if (item.IsDir())\n    item.Size = 0;\n  */\n  \n  ReadBuffer(item.Comment, commentSize);\n  return S_OK;\n}\n\n\n/*\nTryEcd64()\n  (_inBufMode == false) is expected here\n  so TryEcd64() can't change the Buffer.\n  if (Ecd64 is not covered by cached region),\n    TryEcd64() can change cached region ranges (_bufCached, _bufPos) and _streamPos.\n*/\n\nHRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo)\n{\n  if (offset >= ((UInt64)1 << 63))\n    return S_FALSE;\n  Byte buf[kEcd64_FullSize];\n\n  RINOK(SeekToVol(Vols.StreamIndex, offset))\n  RINOK(ReadFromCache_FALSE(buf, kEcd64_FullSize))\n\n  if (Get32(buf) != NSignature::kEcd64)\n    return S_FALSE;\n  UInt64 mainSize = Get64(buf + 4);\n  if (mainSize < kEcd64_MainSize || mainSize > ((UInt64)1 << 40))\n    return S_FALSE;\n  cdInfo.ParseEcd64e(buf + 12);\n  return S_OK;\n}\n\n\n/* FindCd() doesn't use previous cached region,\n   but it uses Buffer. So it sets new cached region */\n\nHRESULT CInArchive::FindCd(bool checkOffsetMode)\n{\n  // There are no useful data in cache in most cases here.\n  // So here we don't use cache data from previous operations.\n  InitBuf();\n  UInt64 endPos;\n  RINOK(InStream_GetSize_SeekToEnd(Stream, endPos))\n  _streamPos = endPos;\n  const size_t kBufSizeMax = (size_t)1 << 17; // must be larger than\n      // (1 << 16) + kEcdSize + kEcd64Locator_Size + kEcd64_FullSize\n  const size_t bufSize = (endPos < kBufSizeMax) ? (size_t)endPos : kBufSizeMax;\n  if (bufSize < kEcdSize)\n    return S_FALSE;\n  RINOK(AllocateBuffer(kBufSizeMax))\n  {\n    RINOK(Seek_SavePos(endPos - bufSize))\n    size_t processed = bufSize;\n    const HRESULT res = ReadStream(Stream, Buffer, &processed);\n    _streamPos += processed;\n    _bufCached = processed;\n    _bufPos = 0;\n    _cnt += processed;\n    if (res != S_OK)\n      return res;\n    if (processed != bufSize)\n      return S_FALSE;\n  }\n\n  CCdInfo &cdInfo = Vols.ecd;\n  \n  for (size_t i = bufSize - kEcdSize + 1;;)\n  {\n    const Byte *buf = Buffer;\n    {\n      const Byte *p = buf + i;\n      do\n        if (p == buf)\n          return S_FALSE;\n      while (*(--p) != 0x50);\n\n      i = (size_t)(p - buf);\n      if (Get32(p) != NSignature::kEcd)\n        continue;\n      cdInfo.ParseEcd32(p);\n    }\n    \n    if (i >= kEcd64Locator_Size)\n    {\n      const size_t locatorIndex = i - kEcd64Locator_Size;\n      if (Get32(buf + locatorIndex) == NSignature::kEcd64Locator)\n      {\n        CLocator locator;\n        locator.Parse(buf + locatorIndex + 4);\n        UInt32 numDisks = locator.NumDisks;\n        // we ignore the error, where some zip creators use (NumDisks == 0)\n        if (numDisks == 0)\n          numDisks = 1;\n        if ((cdInfo.ThisDisk == numDisks - 1 || ZIP64_IS_16_MAX(cdInfo.ThisDisk))\n            && locator.Ecd64Disk < numDisks)\n        {\n          if (locator.Ecd64Disk != cdInfo.ThisDisk && !ZIP64_IS_16_MAX(cdInfo.ThisDisk))\n            return E_NOTIMPL;\n          \n          // Most of the zip64 use fixed size Zip64 ECD\n          // we try relative backward reading.\n          const UInt64 absEcd64 = endPos - bufSize + i - (kEcd64Locator_Size + kEcd64_FullSize);\n          \n          if (locatorIndex >= kEcd64_FullSize)\n          if (checkOffsetMode || absEcd64 == locator.Ecd64Offset)\n          {\n            const Byte *ecd64 = buf + locatorIndex - kEcd64_FullSize;\n            if (Get32(ecd64) == NSignature::kEcd64 &&\n                Get64(ecd64 + 4) == kEcd64_MainSize)\n            {\n              cdInfo.ParseEcd64e(ecd64 + 12);\n              ArcInfo.Base = (Int64)(absEcd64 - locator.Ecd64Offset);\n              // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;\n              return S_OK;\n            }\n          }\n          \n          // some zip64 use variable size Zip64 ECD.\n          // we try to use absolute offset from locator.\n          if (absEcd64 != locator.Ecd64Offset)\n          {\n            if (TryEcd64(locator.Ecd64Offset, cdInfo) == S_OK)\n            {\n              ArcInfo.Base = 0;\n              // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;\n              return S_OK;\n            }\n          }\n          \n          // for variable Zip64 ECD with for archives with offset != 0.\n\n          if (checkOffsetMode\n              && ArcInfo.MarkerPos != 0\n              && ArcInfo.MarkerPos + locator.Ecd64Offset != absEcd64)\n          {\n            if (TryEcd64(ArcInfo.MarkerPos + locator.Ecd64Offset, cdInfo) == S_OK)\n            {\n              ArcInfo.Base = (Int64)ArcInfo.MarkerPos;\n              // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;\n              return S_OK;\n            }\n          }\n        }\n      }\n    }\n    \n    // bool isVolMode = (Vols.EndVolIndex != -1);\n    // UInt32 searchDisk = (isVolMode ? Vols.EndVolIndex : 0);\n    \n    if (/* searchDisk == thisDisk && */ cdInfo.CdDisk <= cdInfo.ThisDisk)\n    {\n      // if (isVolMode)\n      {\n        if (cdInfo.CdDisk != cdInfo.ThisDisk)\n          return S_OK;\n      }\n      \n      UInt64 absEcdPos = endPos - bufSize + i;\n      UInt64 cdEnd = cdInfo.Size + cdInfo.Offset;\n      ArcInfo.Base = 0;\n      // ArcInfo.BaseVolIndex = cdInfo.ThisDisk;\n      if (absEcdPos != cdEnd)\n      {\n        /*\n        if (cdInfo.Offset <= 16 && cdInfo.Size != 0)\n        {\n          // here we support some rare ZIP files with Central directory at the start\n          ArcInfo.Base = 0;\n        }\n        else\n        */\n        ArcInfo.Base = (Int64)(absEcdPos - cdEnd);\n      }\n      return S_OK;\n    }\n  }\n}\n\n\nHRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize)\n{\n  items.Clear();\n  IsCdUnsorted = false;\n  \n  if ((Int64)cdOffset < 0)\n    return S_FALSE;\n\n  // _startLocalFromCd_Disk = (UInt32)(Int32)-1;\n  // _startLocalFromCd_Offset = (UInt64)(Int64)-1;\n\n  RINOK(SeekToVol(IsMultiVol ? (int)cdInfo.CdDisk : -1, cdOffset))\n\n  _inBufMode = true;\n  _cnt = 0;\n\n  if (Callback)\n  {\n    RINOK(Callback->SetTotal(&cdInfo.NumEntries, IsMultiVol ? &Vols.TotalBytesSize : NULL))\n  }\n  UInt64 numFileExpected = cdInfo.NumEntries;\n  const UInt64 *totalFilesPtr = &numFileExpected;\n  bool isCorrect_NumEntries = (cdInfo.IsFromEcd64 || numFileExpected >= ((UInt32)1 << 16));\n\n  while (_cnt < cdSize)\n  {\n    CanStartNewVol = true;\n    if (ReadUInt32() != NSignature::kCentralFileHeader)\n      return S_FALSE;\n    CanStartNewVol = false;\n    {\n      CItemEx cdItem;\n      RINOK(ReadCdItem(cdItem))\n      \n      /*\n      if (cdItem.Disk < _startLocalFromCd_Disk ||\n          cdItem.Disk == _startLocalFromCd_Disk &&\n          cdItem.LocalHeaderPos < _startLocalFromCd_Offset)\n      {\n        _startLocalFromCd_Disk = cdItem.Disk;\n        _startLocalFromCd_Offset = cdItem.LocalHeaderPos;\n      }\n      */\n\n      if (items.Size() > 0 && !IsCdUnsorted)\n      {\n        const CItemEx &prev = items.Back();\n        if (cdItem.Disk < prev.Disk\n            || (cdItem.Disk == prev.Disk &&\n            cdItem.LocalHeaderPos < prev.LocalHeaderPos))\n          IsCdUnsorted = true;\n      }\n\n      items.Add(cdItem);\n    }\n    if (Callback && (items.Size() & 0xFFF) == 0)\n    {\n      const UInt64 numFiles = items.Size();\n\n      if (numFiles > numFileExpected && totalFilesPtr)\n      {\n        if (isCorrect_NumEntries)\n          totalFilesPtr = NULL;\n        else\n          while (numFiles > numFileExpected)\n            numFileExpected += (UInt32)1 << 16;\n        RINOK(Callback->SetTotal(totalFilesPtr, NULL))\n      }\n\n      RINOK(Callback->SetCompleted(&numFiles, &_cnt))\n    }\n  }\n\n  CanStartNewVol = true;\n\n  return (_cnt == cdSize) ? S_OK : S_FALSE;\n}\n\n\n/*\nstatic int CompareCdItems(void *const *elem1, void *const *elem2, void *)\n{\n  const CItemEx *i1 = *(const CItemEx **)elem1;\n  const CItemEx *i2 = *(const CItemEx **)elem2;\n\n  if (i1->Disk < i2->Disk) return -1;\n  if (i1->Disk > i2->Disk) return 1;\n  if (i1->LocalHeaderPos < i2->LocalHeaderPos) return -1;\n  if (i1->LocalHeaderPos > i2->LocalHeaderPos) return 1;\n  if (i1 < i2) return -1;\n  if (i1 > i2) return 1;\n  return 0;\n}\n*/\n\nHRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize)\n{\n  bool checkOffsetMode = true;\n  \n  if (IsMultiVol)\n  {\n    if (Vols.EndVolIndex == -1)\n      return S_FALSE;\n    Stream = Vols.Streams[(unsigned)Vols.EndVolIndex].Stream;\n    if (!Vols.StartIsZip)\n      checkOffsetMode = false;\n  }\n  else\n    Stream = StartStream;\n\n  if (!Vols.ecd_wasRead)\n  {\n    RINOK(FindCd(checkOffsetMode))\n  }\n\n  CCdInfo &cdInfo = Vols.ecd;\n  \n  HRESULT res = S_FALSE;\n  \n  cdSize = cdInfo.Size;\n  cdOffset = cdInfo.Offset;\n  cdDisk = cdInfo.CdDisk;\n\n  if (!IsMultiVol)\n  {\n    if (cdInfo.ThisDisk != cdInfo.CdDisk)\n      return S_FALSE;\n  }\n\n  const UInt64 base = (IsMultiVol ? 0 : (UInt64)ArcInfo.Base);\n  res = TryReadCd(items, cdInfo, base + cdOffset, cdSize);\n  \n  if (res == S_FALSE && !IsMultiVol && base != ArcInfo.MarkerPos)\n  {\n    // do we need that additional attempt to read cd?\n    res = TryReadCd(items, cdInfo, ArcInfo.MarkerPos + cdOffset, cdSize);\n    if (res == S_OK)\n      ArcInfo.Base = (Int64)ArcInfo.MarkerPos;\n  }\n  \n  // Some rare case files are unsorted\n  // items.Sort(CompareCdItems, NULL);\n  return res;\n}\n\n\nstatic int FindItem(const CObjectVector<CItemEx> &items, const CItemEx &item)\n{\n  unsigned left = 0, right = items.Size();\n  for (;;)\n  {\n    if (left >= right)\n      return -1;\n    const unsigned index = (unsigned)(((size_t)left + (size_t)right) / 2);\n    const CItemEx &item2 = items[index];\n    if (item.Disk < item2.Disk)\n      right = index;\n    else if (item.Disk > item2.Disk)\n      left = index + 1;\n    else if (item.LocalHeaderPos == item2.LocalHeaderPos)\n      return (int)index;\n    else if (item.LocalHeaderPos < item2.LocalHeaderPos)\n      right = index;\n    else\n      left = index + 1;\n  }\n}\n\nstatic bool IsStrangeItem(const CItem &item)\n{\n  return item.Name.Len() > (1 << 14) || item.Method > (1 << 8);\n}\n\n\n\n/*\n  ---------- ReadLocals ----------\n\nin:\n  (_signature == NSignature::kLocalFileHeader)\n  VirtStreamPos : after _signature : position in Stream\n  Stream :\n  Vols : if (IsMultiVol)\n  (_inBufMode == false)\n\naction:\n  it parses local items.\n\n  if ( IsMultiVol) it writes absolute offsets to CItemEx::LocalHeaderPos\n  if (!IsMultiVol) it writes relative (from ArcInfo.Base) offsets to CItemEx::LocalHeaderPos\n               later we can correct CItemEx::LocalHeaderPos values, if\n               some new value for ArcInfo.Base will be detected\nout:\n  S_OK:\n    (_signature != NSignature::kLocalFileHeade)\n    _streamPos : after _signature\n\n  S_FALSE: if no items or there is just one item with strange properies that doesn't look like real archive.\n\n  another error code: stream reading error or Callback error.\n\n  CUnexpectEnd() exception : it's not fatal exception here.\n      It means that reading was interrupted by unexpected end of input stream,\n      but some CItemEx items were parsed OK.\n      We can stop further archive parsing.\n      But we can use all filled CItemEx items.\n*/\n\nHRESULT CInArchive::ReadLocals(CObjectVector<CItemEx> &items)\n{\n  items.Clear();\n\n  UInt64 progressPrev = _cnt;\n  \n  if (Callback)\n  {\n    RINOK(Callback->SetTotal(NULL, IsMultiVol ? &Vols.TotalBytesSize : NULL))\n  }\n\n  while (_signature == NSignature::kLocalFileHeader)\n  {\n    CItemEx item;\n\n    item.LocalHeaderPos = GetVirtStreamPos() - 4;\n    if (!IsMultiVol)\n      item.LocalHeaderPos = (UInt64)((Int64)item.LocalHeaderPos - ArcInfo.Base);\n    \n    try\n    {\n      ReadLocalItem(item);\n      item.FromLocal = true;\n      bool isFinished = false;\n\n      if (item.HasDescriptor())\n      {\n        RINOK(FindDescriptor(item, items.Size()))\n        isFinished = !item.DescriptorWasRead;\n      }\n      else\n      {\n        if (item.PackSize >= ((UInt64)1 << 62))\n          throw CUnexpectEnd();\n        RINOK(IncreaseRealPosition(item.PackSize, isFinished))\n      }\n   \n      items.Add(item);\n      \n      if (isFinished)\n        throw CUnexpectEnd();\n\n      ReadSignature();\n    }\n    catch (CUnexpectEnd &)\n    {\n      if (items.IsEmpty() || (items.Size() == 1 && IsStrangeItem(items[0])))\n        return S_FALSE;\n      throw;\n    }\n\n\n    if (Callback)\n    if ((items.Size() & 0xFF) == 0\n        || _cnt - progressPrev >= ((UInt32)1 << 22))\n    {\n      progressPrev = _cnt;\n      const UInt64 numFiles = items.Size();\n      RINOK(Callback->SetCompleted(&numFiles, &_cnt))\n    }\n  }\n\n  if (items.Size() == 1 && _signature != NSignature::kCentralFileHeader)\n    if (IsStrangeItem(items[0]))\n      return S_FALSE;\n  \n  return S_OK;\n}\n\n\n\nHRESULT CVols::ParseArcName(IArchiveOpenVolumeCallback *volCallback)\n{\n  UString name;\n  {\n    NWindows::NCOM::CPropVariant prop;\n    RINOK(volCallback->GetProperty(kpidName, &prop))\n    if (prop.vt != VT_BSTR)\n      return S_OK;\n    name = prop.bstrVal;\n  }\n\n  const int dotPos = name.ReverseFind_Dot();\n  if (dotPos < 0)\n    return S_OK;\n  const UString ext = name.Ptr((unsigned)(dotPos + 1));\n  name.DeleteFrom((unsigned)(dotPos + 1));\n\n  StartVolIndex = (Int32)(-1);\n\n  if (ext.IsEmpty())\n    return S_OK;\n  {\n    wchar_t c = ext[0];\n    IsUpperCase = (c >= 'A' && c <= 'Z');\n    if (ext.IsEqualTo_Ascii_NoCase(\"zip\"))\n    {\n      BaseName = name;\n      StartIsZ = true;\n      StartIsZip = true;\n      return S_OK;\n    }\n    else if (ext.IsEqualTo_Ascii_NoCase(\"exe\"))\n    {\n      /* possible cases:\n         - exe with zip inside\n         - sfx: a.exe, a.z02, a.z03,... , a.zip\n                a.exe is start volume.\n         - zip renamed to exe\n      */\n\n      StartIsExe = true;\n      BaseName = name;\n      StartVolIndex = 0;\n      /* sfx-zip can use both arc.exe and arc.zip\n         We can open arc.zip, if it was requesed to open arc.exe.\n         But it's possible that arc.exe and arc.zip are not parts of same archive.\n         So we can disable such operation */\n\n      // 18.04: we still want to open zip renamed to exe.\n      /*\n      {\n        UString volName = name;\n        volName += IsUpperCase ? \"Z01\" : \"z01\";\n        {\n          CMyComPtr<IInStream> stream;\n          HRESULT res2 = volCallback->GetStream(volName, &stream);\n          if (res2 == S_OK)\n            DisableVolsSearch = true;\n        }\n      }\n      */\n      DisableVolsSearch = true;\n      return S_OK;\n    }\n    else if (ext[0] == 'z' || ext[0] == 'Z')\n    {\n      if (ext.Len() < 3)\n        return S_OK;\n      const wchar_t *end = NULL;\n      UInt32 volNum = ConvertStringToUInt32(ext.Ptr(1), &end);\n      if (*end != 0 || volNum < 1 || volNum > ((UInt32)1 << 30))\n        return S_OK;\n      StartVolIndex = (Int32)(volNum - 1);\n      BaseName = name;\n      StartIsZ = true;\n    }\n    else\n      return S_OK;\n  }\n\n  UString volName = BaseName;\n  volName += (IsUpperCase ? \"ZIP\" : \"zip\");\n  \n  HRESULT res = volCallback->GetStream(volName, &ZipStream);\n  \n  if (res == S_FALSE || !ZipStream)\n  {\n    if (MissingName.IsEmpty())\n    {\n      MissingZip = true;\n      MissingName = volName;\n    }\n    return S_OK;\n  }\n\n  return res;\n}\n\n\nHRESULT CInArchive::ReadVols2(IArchiveOpenVolumeCallback *volCallback,\n    unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols)\n{\n  if (Vols.DisableVolsSearch)\n    return S_OK;\n\n  numMissingVols = 0;\n\n  for (unsigned i = start;; i++)\n  {\n    if (lastDisk >= 0 && i >= (unsigned)lastDisk)\n      break;\n    \n    if (i < Vols.Streams.Size())\n      if (Vols.Streams[i].Stream)\n        continue;\n\n    CMyComPtr<IInStream> stream;\n\n    if ((int)i == zipDisk)\n    {\n      stream = Vols.ZipStream;\n    }\n    else if ((int)i == Vols.StartVolIndex)\n    {\n      stream = StartStream;\n    }\n    else\n    {\n      UString volName = Vols.BaseName;\n      {\n        volName.Add_Char(Vols.IsUpperCase ? 'Z' : 'z');\n        const unsigned v = i + 1;\n        if (v < 10)\n          volName.Add_Char('0');\n        volName.Add_UInt32(v);\n      }\n        \n      HRESULT res = volCallback->GetStream(volName, &stream);\n      if (res != S_OK && res != S_FALSE)\n        return res;\n      if (res == S_FALSE || !stream)\n      {\n        if (i == 0)\n        {\n          UString volName_exe = Vols.BaseName;\n          volName_exe += (Vols.IsUpperCase ? \"EXE\" : \"exe\");\n          \n          HRESULT res2 = volCallback->GetStream(volName_exe, &stream);\n          if (res2 != S_OK && res2 != S_FALSE)\n            return res2;\n          res = res2;\n        }\n      }\n      if (res == S_FALSE || !stream)\n      {\n        if (i == 1 && Vols.StartIsExe)\n          return S_OK;\n        if (Vols.MissingName.IsEmpty())\n          Vols.MissingName = volName;\n        numMissingVols++;\n        if (numMissingVols > numMissingVolsMax)\n          return S_OK;\n        if (lastDisk == -1 && numMissingVols != 0)\n          return S_OK;\n        continue;\n      }\n    }\n\n    UInt64 pos, size;\n    RINOK(InStream_GetPos_GetSize(stream, pos, size))\n\n    while (i >= Vols.Streams.Size())\n      Vols.Streams.AddNew();\n    \n    CVols::CSubStreamInfo &ss = Vols.Streams[i];\n    Vols.NumVols++;\n    Vols.TotalBytesSize += size;\n\n    ss.Stream = stream;\n    ss.Size = size;\n\n    if ((int)i == zipDisk)\n    {\n      Vols.EndVolIndex = (int)(Vols.Streams.Size() - 1);\n      break;\n    }\n  }\n\n  return S_OK;\n}\n\n\nHRESULT CInArchive::ReadVols()\n{\n  CMyComPtr<IArchiveOpenVolumeCallback> volCallback;\n\n  Callback->QueryInterface(IID_IArchiveOpenVolumeCallback, (void **)&volCallback);\n  if (!volCallback)\n    return S_OK;\n\n  RINOK(Vols.ParseArcName(volCallback))\n\n  // const int startZIndex = Vols.StartVolIndex;\n\n  if (!Vols.StartIsZ)\n  {\n    if (!Vols.StartIsExe)\n      return S_OK;\n  }\n\n  int zipDisk = -1;\n  int cdDisk = -1;\n\n  if (Vols.StartIsZip)\n    Vols.ZipStream = StartStream;\n\n  if (Vols.ZipStream)\n  {\n    Stream = Vols.ZipStream;\n    \n    if (Vols.StartIsZip)\n      Vols.StreamIndex = -1;\n    else\n    {\n      Vols.StreamIndex = -2;\n      InitBuf();\n    }\n\n    HRESULT res = FindCd(true);\n\n    CCdInfo &ecd = Vols.ecd;\n    if (res == S_OK)\n    {\n      zipDisk = (int)ecd.ThisDisk;\n      Vols.ecd_wasRead = true;\n\n      // if is not multivol or bad multivol, we return to main single stream code\n      if (ecd.ThisDisk == 0\n          || ecd.ThisDisk >= ((UInt32)1 << 30)\n          || ecd.ThisDisk < ecd.CdDisk)\n        return S_OK;\n      \n      cdDisk = (int)ecd.CdDisk;\n      if (Vols.StartVolIndex < 0)\n        Vols.StartVolIndex = (Int32)ecd.ThisDisk;\n      else if ((UInt32)Vols.StartVolIndex >= ecd.ThisDisk)\n        return S_OK;\n\n      // Vols.StartVolIndex = ecd.ThisDisk;\n      // Vols.EndVolIndex = ecd.ThisDisk;\n      unsigned numMissingVols;\n      if (cdDisk != zipDisk)\n      {\n        // get volumes required for cd.\n        RINOK(ReadVols2(volCallback, (unsigned)cdDisk, zipDisk, zipDisk, 0, numMissingVols))\n        if (numMissingVols != 0)\n        {\n          // cdOK = false;\n        }\n      }\n    }\n    else if (res != S_FALSE)\n      return res;\n  }\n\n  if (Vols.StartVolIndex < 0)\n  {\n    // is not mutivol;\n    return S_OK;\n  }\n\n  /*\n  if (!Vols.Streams.IsEmpty())\n    IsMultiVol = true;\n  */\n  \n  unsigned numMissingVols;\n\n  if (cdDisk != 0)\n  {\n    // get volumes that were no requested still\n    const unsigned kNumMissingVolsMax = 1 << 12;\n    RINOK(ReadVols2(volCallback, 0, cdDisk < 0 ? -1 : cdDisk, zipDisk, kNumMissingVolsMax, numMissingVols))\n  }\n\n  // if (Vols.StartVolIndex >= 0)\n  {\n    if (Vols.Streams.IsEmpty())\n      if (Vols.StartVolIndex > (1 << 20))\n        return S_OK;\n    if ((unsigned)Vols.StartVolIndex >= Vols.Streams.Size()\n        || !Vols.Streams[(unsigned)Vols.StartVolIndex].Stream)\n    {\n      // we get volumes starting from StartVolIndex, if they we not requested before know the volume index (if FindCd() was ok)\n      RINOK(ReadVols2(volCallback, (unsigned)Vols.StartVolIndex, zipDisk, zipDisk, 0, numMissingVols))\n    }\n  }\n\n  if (Vols.ZipStream)\n  {\n    // if there is no another volumes and volumeIndex is too big, we don't use multivol mode\n    if (Vols.Streams.IsEmpty())\n      if (zipDisk > (1 << 10))\n        return S_OK;\n    if (zipDisk >= 0)\n    {\n      // we create item in Streams for ZipStream, if we know the volume index (if FindCd() was ok)\n      RINOK(ReadVols2(volCallback, (unsigned)zipDisk, zipDisk + 1, zipDisk, 0, numMissingVols))\n    }\n  }\n\n  if (!Vols.Streams.IsEmpty())\n  {\n    IsMultiVol = true;\n    /*\n    if (cdDisk)\n      IsMultiVol = true;\n    */\n    const int startZIndex = Vols.StartVolIndex;\n    if (startZIndex >= 0)\n    {\n      // if all volumes before start volume are OK, we can start parsing from 0\n      // if there are missing volumes before startZIndex, we start parsing in current startZIndex\n      if ((unsigned)startZIndex < Vols.Streams.Size())\n      {\n        for (unsigned i = 0; i <= (unsigned)startZIndex; i++)\n          if (!Vols.Streams[i].Stream)\n          {\n            Vols.StartParsingVol = startZIndex;\n            break;\n          }\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n\n\nHRESULT CVols::Read(void *data, UInt32 size, UInt32 *processedSize)\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n\n  for (;;)\n  {\n    if (StreamIndex < 0)\n      return S_OK;\n    if ((unsigned)StreamIndex >= Streams.Size())\n      return S_OK;\n    const CVols::CSubStreamInfo &s = Streams[(unsigned)StreamIndex];\n    if (!s.Stream)\n      return S_FALSE;\n    if (NeedSeek)\n    {\n      RINOK(s.SeekToStart())\n      NeedSeek = false;\n    }\n    UInt32 realProcessedSize = 0;\n    HRESULT res = s.Stream->Read(data, size, &realProcessedSize);\n    if (processedSize)\n      *processedSize = realProcessedSize;\n    if (res != S_OK)\n      return res;\n    if (realProcessedSize != 0)\n      return res;\n    StreamIndex++;\n    NeedSeek = true;\n  }\n}\n\nZ7_COM7F_IMF(CVolStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  return Vols->Read(data, size, processedSize);\n}\n\n\n\n\n#define COPY_ECD_ITEM_16(n) if (!isZip64 || !ZIP64_IS_16_MAX(ecd. n))     cdInfo. n = ecd. n;\n#define COPY_ECD_ITEM_32(n) if (!isZip64 || !ZIP64_IS_32_MAX(ecd. n)) cdInfo. n = ecd. n;\n\n\nHRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items)\n{\n  // buffer that can be used for cd reading\n  RINOK(AllocateBuffer(kSeqBufferSize))\n\n  // here we can read small records. So we switch off _inBufMode.\n  _inBufMode = false;\n\n  HRESULT res = S_OK;\n\n  bool localsWereRead = false;\n\n  /* we try to open archive with the following modes:\n     1) CD-MODE        : fast mode : we read backward ECD and CD, compare CD items with first Local item.\n     2) LOCALS-CD-MODE : slow mode, if CD-MODE fails : we sequentially read all Locals and then CD.\n     Then we read sequentially ECD64, Locator, ECD again at the end.\n\n     - in LOCALS-CD-MODE we use use the following\n         variables (with real cd properties) to set Base archive offset\n         and check real cd properties with values from ECD/ECD64.\n  */\n\n  UInt64 cdSize = 0;\n  UInt64 cdRelatOffset = 0;\n  UInt32 cdDisk = 0;\n\n  UInt64 cdAbsOffset = 0;   // absolute cd offset, for LOCALS-CD-MODE only.\n\nif (Force_ReadLocals_Mode)\n{\n  IsArc = true;\n  res = S_FALSE; // we will use LOCALS-CD-MODE mode\n}\nelse\n{\n  if (!MarkerIsFound || !MarkerIsSafe)\n  {\n    IsArc = true;\n    res = ReadCd(items, cdDisk, cdRelatOffset, cdSize);\n    if (res == S_OK)\n      ReadSignature();\n    else if (res != S_FALSE)\n      return res;\n  }\n  else  // (MarkerIsFound && MarkerIsSafe)\n  {\n \n  // _signature must be kLocalFileHeader or kEcd or kEcd64\n\n  SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2 + 4);\n\n  CanStartNewVol = false;\n\n  if (_signature == NSignature::kEcd64)\n  {\n    // UInt64 ecd64Offset = GetVirtStreamPos() - 4;\n    IsZip64 = true;\n\n    {\n      const UInt64 recordSize = ReadUInt64();\n      if (recordSize < kEcd64_MainSize)\n        return S_FALSE;\n      if (recordSize >= ((UInt64)1 << 62))\n        return S_FALSE;\n      \n      {\n        const unsigned kBufSize = kEcd64_MainSize;\n        Byte buf[kBufSize];\n        SafeRead(buf, kBufSize);\n        CCdInfo cdInfo;\n        cdInfo.ParseEcd64e(buf);\n        if (!cdInfo.IsEmptyArc())\n          return S_FALSE;\n      }\n      \n      RINOK(Skip64(recordSize - kEcd64_MainSize, 0))\n    }\n\n    ReadSignature();\n    if (_signature != NSignature::kEcd64Locator)\n      return S_FALSE;\n\n    {\n      const unsigned kBufSize = 16;\n      Byte buf[kBufSize];\n      SafeRead(buf, kBufSize);\n      CLocator locator;\n      locator.Parse(buf);\n      if (!locator.IsEmptyArc())\n        return S_FALSE;\n    }\n\n    ReadSignature();\n    if (_signature != NSignature::kEcd)\n      return S_FALSE;\n  }\n  \n  if (_signature == NSignature::kEcd)\n  {\n    // It must be empty archive or backware archive\n    // we don't support backware archive still\n    \n    const unsigned kBufSize = kEcdSize - 4;\n    Byte buf[kBufSize];\n    SafeRead(buf, kBufSize);\n    CEcd ecd;\n    ecd.Parse(buf);\n    // if (ecd.cdSize != 0)\n    // Do we need also to support the case where empty zip archive with PK00 uses cdOffset = 4 ??\n    if (!ecd.IsEmptyArc())\n      return S_FALSE;\n\n    ArcInfo.Base = (Int64)ArcInfo.MarkerPos;\n    IsArc = true; // check it: we need more tests?\n\n    RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2))\n    ReadSignature();\n  }\n  else\n  {\n    CItemEx firstItem;\n    try\n    {\n      try\n      {\n        if (!ReadLocalItem(firstItem))\n          return S_FALSE;\n      }\n      catch(CUnexpectEnd &)\n      {\n        return S_FALSE;\n      }\n\n      IsArc = true;\n      res = ReadCd(items, cdDisk, cdRelatOffset, cdSize);\n      if (res == S_OK)\n        ReadSignature();\n    }\n    catch(CUnexpectEnd &) { res = S_FALSE; }\n    \n    if (res != S_FALSE && res != S_OK)\n      return res;\n\n    if (res == S_OK && items.Size() == 0)\n      res = S_FALSE;\n\n    if (res == S_OK)\n    {\n      // we can't read local items here to keep _inBufMode state\n      if ((Int64)ArcInfo.MarkerPos2 < ArcInfo.Base)\n        res = S_FALSE;\n      else\n      {\n        firstItem.LocalHeaderPos = (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base);\n        int index = -1;\n\n        UInt32 min_Disk = (UInt32)(Int32)-1;\n        UInt64 min_LocalHeaderPos = (UInt64)(Int64)-1;\n\n        if (!IsCdUnsorted)\n          index = FindItem(items, firstItem);\n        else\n        {\n          FOR_VECTOR (i, items)\n          {\n            const CItemEx &cdItem = items[i];\n            if (cdItem.Disk == firstItem.Disk\n                && (cdItem.LocalHeaderPos == firstItem.LocalHeaderPos))\n              index = (int)i;\n            \n            if (i == 0\n                || cdItem.Disk < min_Disk\n                || (cdItem.Disk == min_Disk && cdItem.LocalHeaderPos < min_LocalHeaderPos))\n            {\n              min_Disk = cdItem.Disk;\n              min_LocalHeaderPos = cdItem.LocalHeaderPos;\n            }\n          }\n        }\n\n        if (index == -1)\n          res = S_FALSE;\n        else if (!AreItemsEqual(firstItem, items[(unsigned)index]))\n          res = S_FALSE;\n        else\n        {\n          ArcInfo.CdWasRead = true;\n          if (IsCdUnsorted)\n            ArcInfo.FirstItemRelatOffset = min_LocalHeaderPos;\n          else\n            ArcInfo.FirstItemRelatOffset = items[0].LocalHeaderPos;\n\n          // ArcInfo.FirstItemRelatOffset = _startLocalFromCd_Offset;\n        }\n      }\n    }\n  }\n  } // (MarkerIsFound && MarkerIsSafe)\n\n} // (!onlyLocalsMode)\n\n\n  CObjectVector<CItemEx> cdItems;\n\n  bool needSetBase = false; // we set needSetBase only for LOCALS_CD_MODE\n  unsigned numCdItems = items.Size();\n  \n  #ifdef ZIP_SELF_CHECK\n  res = S_FALSE; // if uncommented, it uses additional LOCALS-CD-MODE mode to check the code\n  #endif\n\n  if (res != S_OK)\n  {\n    // ---------- LOCALS-CD-MODE ----------\n    // CD doesn't match firstItem,\n    // so we clear items and read Locals and CD.\n\n    items.Clear();\n    localsWereRead = true;\n    \n    HeadersError = false;\n    HeadersWarning = false;\n    ExtraMinorError = false;\n\n    /* we can use any mode: with buffer and without buffer\n         without buffer : skips packed data : fast for big files : slow for small files\n         with    buffer : reads packed data : slow for big files : fast for small files\n       Buffer mode is more effective. */\n    // _inBufMode = false;\n    _inBufMode = true;\n    // we could change the buffer size here, if we want smaller Buffer.\n    // RINOK(ReAllocateBuffer(kSeqBufferSize));\n    // InitBuf()\n    \n    ArcInfo.Base = 0;\n\n   if (!Disable_FindMarker)\n   {\n    if (!MarkerIsFound)\n    {\n      if (!IsMultiVol)\n        return S_FALSE;\n      if (Vols.StartParsingVol != 0)\n        return S_FALSE;\n      // if (StartParsingVol == 0) and we didn't find marker, we use default zero marker.\n      // so we suppose that there is no sfx stub\n      RINOK(SeekToVol(0, ArcInfo.MarkerPos2))\n    }\n    else\n    {\n      if (ArcInfo.MarkerPos != 0)\n      {\n        /*\n        If multi-vol or there is (No)Span-marker at start of stream, we set (Base) as 0.\n        In another caes:\n          (No)Span-marker is supposed as false positive. So we set (Base) as main marker (MarkerPos2).\n          The (Base) can be corrected later after ECD reading.\n          But sfx volume with stub and (No)Span-marker in (!IsMultiVol) mode will have incorrect (Base) here.\n        */\n        ArcInfo.Base = (Int64)ArcInfo.MarkerPos2;\n      }\n      RINOK(SeekToVol(ArcInfo.MarkerVolIndex, ArcInfo.MarkerPos2))\n    }\n   }\n    _cnt = 0;\n\n    ReadSignature();\n    \n    LocalsWereRead = true;\n\n    RINOK(ReadLocals(items))\n\n    if (_signature != NSignature::kCentralFileHeader)\n    {\n      // GetVirtStreamPos() - 4\n      if (items.IsEmpty())\n        return S_FALSE;\n\n      bool isError = true;\n\n      const UInt32 apkSize = _signature;\n      const unsigned kApkFooterSize = 16 + 8;\n      if (apkSize >= kApkFooterSize && apkSize <= (1 << 20))\n      {\n        if (ReadUInt32() == 0)\n        {\n          CByteBuffer apk;\n          apk.Alloc(apkSize);\n          SafeRead(apk, apkSize);\n          ReadSignature();\n          const Byte *footer = apk + apkSize - kApkFooterSize;\n          if (_signature == NSignature::kCentralFileHeader)\n          if (GetUi64(footer) == apkSize)\n          if (memcmp(footer + 8, \"APK Sig Block 42\", 16) == 0)\n          {\n            isError = false;\n            IsApk = true;\n          }\n        }\n      }\n      \n      if (isError)\n      {\n        NoCentralDir = true;\n        HeadersError = true;\n        return S_OK;\n      }\n    }\n    \n    _inBufMode = true;\n\n    cdAbsOffset = GetVirtStreamPos() - 4;\n    cdDisk = (UInt32)Vols.StreamIndex;\n\n    #ifdef ZIP_SELF_CHECK\n    if (!IsMultiVol && _cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2)\n      return E_FAIL;\n    #endif\n\n    const UInt64 processedCnt_start = _cnt;\n\n    for (;;)\n    {\n      CItemEx cdItem;\n      \n      RINOK(ReadCdItem(cdItem))\n      \n      cdItems.Add(cdItem);\n      if (Callback && (cdItems.Size() & 0xFFF) == 0)\n      {\n        const UInt64 numFiles = items.Size();\n        const UInt64 numBytes = _cnt;\n        RINOK(Callback->SetCompleted(&numFiles, &numBytes))\n      }\n      ReadSignature();\n      if (_signature != NSignature::kCentralFileHeader)\n        break;\n    }\n    \n    cdSize = _cnt - processedCnt_start;\n\n    #ifdef ZIP_SELF_CHECK\n    if (!IsMultiVol)\n    {\n      if (_cnt != GetVirtStreamPos() - ArcInfo.MarkerPos2)\n        return E_FAIL;\n      if (cdSize != (GetVirtStreamPos() - 4) - cdAbsOffset)\n        return E_FAIL;\n    }\n    #endif\n\n    needSetBase = true;\n    numCdItems = cdItems.Size();\n    cdRelatOffset = (UInt64)((Int64)cdAbsOffset - ArcInfo.Base);\n\n    if (!cdItems.IsEmpty())\n    {\n      ArcInfo.CdWasRead = true;\n      ArcInfo.FirstItemRelatOffset = cdItems[0].LocalHeaderPos;\n    }\n  }\n\n  \n  \n  CCdInfo cdInfo;\n  CLocator locator;\n  bool isZip64 = false;\n  const UInt64 ecd64AbsOffset = GetVirtStreamPos() - 4;\n  int ecd64Disk = -1;\n  \n  if (_signature == NSignature::kEcd64)\n  {\n    ecd64Disk = Vols.StreamIndex;\n\n    IsZip64 = isZip64 = true;\n\n    {\n      const UInt64 recordSize = ReadUInt64();\n      if (recordSize < kEcd64_MainSize\n          || recordSize >= ((UInt64)1 << 62))\n      {\n        HeadersError = true;\n        return S_OK;\n      }\n\n      {\n        const unsigned kBufSize = kEcd64_MainSize;\n        Byte buf[kBufSize];\n        SafeRead(buf, kBufSize);\n        cdInfo.ParseEcd64e(buf);\n      }\n      \n      RINOK(Skip64(recordSize - kEcd64_MainSize, items.Size()))\n    }\n\n\n    ReadSignature();\n\n    if (_signature != NSignature::kEcd64Locator)\n    {\n      HeadersError = true;\n      return S_OK;\n    }\n  \n    {\n      const unsigned kBufSize = 16;\n      Byte buf[kBufSize];\n      SafeRead(buf, kBufSize);\n      locator.Parse(buf);\n      // we ignore the error, where some zip creators use (NumDisks == 0)\n      // if (locator.NumDisks == 0) HeadersWarning = true;\n    }\n\n    ReadSignature();\n  }\n  \n  \n  if (_signature != NSignature::kEcd)\n  {\n    HeadersError = true;\n    return S_OK;\n  }\n\n  \n  CanStartNewVol = false;\n\n  // ---------- ECD ----------\n\n  CEcd ecd;\n  {\n    const unsigned kBufSize = kEcdSize - 4;\n    Byte buf[kBufSize];\n    SafeRead(buf, kBufSize);\n    ecd.Parse(buf);\n  }\n\n  COPY_ECD_ITEM_16(ThisDisk)\n  COPY_ECD_ITEM_16(CdDisk)\n  COPY_ECD_ITEM_16(NumEntries_in_ThisDisk)\n  COPY_ECD_ITEM_16(NumEntries)\n  COPY_ECD_ITEM_32(Size)\n  COPY_ECD_ITEM_32(Offset)\n\n  bool cdOK = true;\n\n  if ((UInt32)cdInfo.Size != (UInt32)cdSize)\n  {\n    // return S_FALSE;\n    cdOK = false;\n  }\n\n  if (isZip64)\n  {\n    if (cdInfo.NumEntries != numCdItems\n        || cdInfo.Size != cdSize)\n    {\n      cdOK = false;\n    }\n  }\n\n\n  if (IsMultiVol)\n  {\n    if (cdDisk != cdInfo.CdDisk)\n      HeadersError = true;\n  }\n  else if (needSetBase && cdOK)\n  {\n    const UInt64 oldBase = (UInt64)ArcInfo.Base;\n    // localsWereRead == true\n    // ArcInfo.Base == ArcInfo.MarkerPos2\n    // cdRelatOffset == (cdAbsOffset - ArcInfo.Base)\n\n    if (isZip64)\n    {\n      if (ecd64Disk == Vols.StartVolIndex)\n      {\n        const Int64 newBase = (Int64)ecd64AbsOffset - (Int64)locator.Ecd64Offset;\n        if (newBase <= (Int64)ecd64AbsOffset)\n        {\n          if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2)\n          {\n            ArcInfo.Base = newBase;\n            cdRelatOffset = (UInt64)((Int64)cdAbsOffset - newBase);\n          }\n          else\n            cdOK = false;\n        }\n      }\n    }\n    else if (numCdItems != 0) // we can't use ecd.Offset in empty archive?\n    {\n      if ((int)cdDisk == Vols.StartVolIndex)\n      {\n        const Int64 newBase = (Int64)cdAbsOffset - (Int64)cdInfo.Offset;\n        if (newBase <= (Int64)cdAbsOffset)\n        {\n          if (!localsWereRead || newBase <= (Int64)ArcInfo.MarkerPos2)\n          {\n            // cd can be more accurate, when it points before Locals\n            // so we change Base and cdRelatOffset\n            ArcInfo.Base = newBase;\n            cdRelatOffset = cdInfo.Offset;\n          }\n          else\n          {\n            // const UInt64 delta = ((UInt64)cdRelatOffset - cdInfo.Offset);\n            const UInt64 delta = ((UInt64)(newBase - ArcInfo.Base));\n            if ((UInt32)delta == 0)\n            {\n              // we set Overflow32bit mode, only if there is (x<<32) offset\n              // between real_CD_offset_from_MarkerPos and CD_Offset_in_ECD.\n              // Base and cdRelatOffset unchanged\n              Overflow32bit = true;\n            }\n            else\n              cdOK = false;\n          }\n        }\n        else\n          cdOK = false;\n      }\n    }\n    // cdRelatOffset = cdAbsOffset - ArcInfo.Base;\n\n    if (localsWereRead)\n    {\n      const UInt64 delta = (UInt64)((Int64)oldBase - ArcInfo.Base);\n      if (delta != 0)\n      {\n        FOR_VECTOR (i, items)\n          items[i].LocalHeaderPos += delta;\n      }\n    }\n  }\n\n  if (!cdOK)\n    HeadersError = true;\n\n  EcdVolIndex = cdInfo.ThisDisk;\n\n  if (!IsMultiVol)\n  {\n    if (EcdVolIndex == 0 && Vols.MissingZip && Vols.StartIsExe)\n    {\n      Vols.MissingName.Empty();\n      Vols.MissingZip = false;\n    }\n\n    if (localsWereRead)\n    {\n      if (EcdVolIndex != 0)\n      {\n        FOR_VECTOR (i, items)\n          items[i].Disk = EcdVolIndex;\n      }\n    }\n\n    UseDisk_in_SingleVol = true;\n  }\n\n  if (isZip64)\n  {\n    if ((cdInfo.ThisDisk == 0 && ecd64AbsOffset != (UInt64)(ArcInfo.Base + (Int64)locator.Ecd64Offset))\n        // || cdInfo.NumEntries_in_ThisDisk != numCdItems\n        || cdInfo.NumEntries != numCdItems\n        || cdInfo.Size != cdSize\n        || (cdInfo.Offset != cdRelatOffset && !items.IsEmpty()))\n    {\n      HeadersError = true;\n      return S_OK;\n    }\n  }\n\n  if (cdOK && !cdItems.IsEmpty())\n  {\n    // ---------- merge Central Directory Items ----------\n  \n    CRecordVector<unsigned> items2;\n\n    int nextLocalIndex = 0;\n\n    LocalsCenterMerged = true;\n\n    FOR_VECTOR (i, cdItems)\n    {\n      if (Callback)\n      if ((i & 0x3FFF) == 0)\n      {\n        const UInt64 numFiles64 = items.Size() + items2.Size();\n        RINOK(Callback->SetCompleted(&numFiles64, &_cnt))\n      }\n\n      const CItemEx &cdItem = cdItems[i];\n      \n      int index = -1;\n      \n      if (nextLocalIndex != -1)\n      {\n        if ((unsigned)nextLocalIndex < items.Size())\n        {\n          CItemEx &item = items[(unsigned)nextLocalIndex];\n          if (item.Disk == cdItem.Disk &&\n              (item.LocalHeaderPos == cdItem.LocalHeaderPos\n              || (Overflow32bit && (UInt32)item.LocalHeaderPos == cdItem.LocalHeaderPos)))\n            index = nextLocalIndex++;\n          else\n            nextLocalIndex = -1;\n        }\n      }\n\n      if (index == -1)\n        index = FindItem(items, cdItem);\n\n      // index = -1;\n\n      if (index == -1)\n      {\n        items2.Add(i);\n        HeadersError = true;\n        continue;\n      }\n\n      CItemEx &item = items[(unsigned)index];\n      if (item.Name != cdItem.Name\n          // || item.Name.Len() != cdItem.Name.Len()\n          || item.PackSize != cdItem.PackSize\n          || item.Size != cdItem.Size\n          // item.ExtractVersion != cdItem.ExtractVersion\n          || !FlagsAreSame(item, cdItem)\n          || item.Crc != cdItem.Crc)\n      {\n        HeadersError = true;\n        continue;\n      }\n\n      // item.Name = cdItem.Name;\n      item.MadeByVersion = cdItem.MadeByVersion;\n      item.CentralExtra = cdItem.CentralExtra;\n      item.InternalAttrib = cdItem.InternalAttrib;\n      item.ExternalAttrib = cdItem.ExternalAttrib;\n      item.Comment = cdItem.Comment;\n      item.FromCentral = cdItem.FromCentral;\n      // 22.02: we force utf8 flag, if central header has utf8 flag\n      if (cdItem.Flags & NFileHeader::NFlags::kUtf8)\n        item.Flags |= NFileHeader::NFlags::kUtf8;\n    }\n\n    FOR_VECTOR (k, items2)\n      items.Add(cdItems[items2[k]]);\n  }\n\n  if (ecd.NumEntries < ecd.NumEntries_in_ThisDisk)\n    HeadersError = true;\n\n  if (ecd.ThisDisk == 0)\n  {\n    // if (isZip64)\n    {\n      if (ecd.NumEntries != ecd.NumEntries_in_ThisDisk)\n        HeadersError = true;\n    }\n  }\n\n  if (isZip64)\n  {\n    if (cdInfo.NumEntries != items.Size()\n        || (ecd.NumEntries != items.Size() && ecd.NumEntries != 0xFFFF))\n      HeadersError = true;\n  }\n  else\n  {\n    // old 7-zip could store 32-bit number of CD items to 16-bit field.\n    // if (ecd.NumEntries != items.Size())\n    if (ecd.NumEntries > items.Size())\n      HeadersError = true;\n\n    if (cdInfo.NumEntries != numCdItems)\n    {\n      if ((UInt16)cdInfo.NumEntries != (UInt16)numCdItems)\n        HeadersError = true;\n      else\n        Cd_NumEntries_Overflow_16bit = true;\n    }\n  }\n\n  ReadBuffer(ArcInfo.Comment, ecd.CommentSize);\n\n  _inBufMode = false;\n\n  // DisableBufMode();\n  // Buffer.Free();\n  /* we can't clear buf varibles. we need them to calculate PhySize of archive */\n\n  if ((UInt16)cdInfo.NumEntries != (UInt16)numCdItems\n      || (UInt32)cdInfo.Size != (UInt32)cdSize\n      || ((UInt32)cdInfo.Offset != (UInt32)cdRelatOffset && !items.IsEmpty()))\n  {\n    // return S_FALSE;\n    HeadersError = true;\n  }\n\n  #ifdef ZIP_SELF_CHECK\n  if (localsWereRead)\n  {\n    const UInt64 endPos = ArcInfo.MarkerPos2 + _cnt;\n    if (endPos != (IsMultiVol ? Vols.TotalBytesSize : ArcInfo.FileEndPos))\n    {\n      // there are some data after the end of archive or error in code;\n      return E_FAIL;\n    }\n  }\n  #endif\n       \n  // printf(\"\\nOpen OK\");\n  return S_OK;\n}\n\n\n\nHRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchLimit,\n    IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items)\n{\n  items.Clear();\n  \n  Close();\n\n  UInt64 startPos;\n  RINOK(InStream_GetPos(stream, startPos))\n  RINOK(InStream_GetSize_SeekToEnd(stream, ArcInfo.FileEndPos))\n  _streamPos = ArcInfo.FileEndPos;\n\n  StartStream = stream;\n  Stream = stream;\n  Callback = callback;\n\n  DisableBufMode();\n  \n  bool volWasRequested = false;\n\n  if (!Disable_VolsRead)\n  if (callback\n      && (startPos == 0 || !searchLimit || *searchLimit != 0))\n  {\n    // we try to read volumes only if it's first call (offset == 0) or scan is allowed.\n    volWasRequested = true;\n    RINOK(ReadVols())\n  }\n\n  if (Disable_FindMarker)\n  {\n    RINOK(SeekToVol(-1, startPos))\n    StreamRef = stream;\n    Stream = stream;\n    MarkerIsFound = true;\n    MarkerIsSafe = true;\n    ArcInfo.MarkerPos = startPos;\n    ArcInfo.MarkerPos2 = startPos;\n  }\n  else\n  if (IsMultiVol && Vols.StartParsingVol == 0 && (unsigned)Vols.StartParsingVol < Vols.Streams.Size())\n  {\n    // only StartParsingVol = 0 is safe search.\n    RINOK(SeekToVol(0, 0))\n    // if (Stream)\n    {\n      // UInt64 limit = 1 << 22; // for sfx\n      UInt64 limit = 0; // without sfx\n    \n      HRESULT res = FindMarker(&limit);\n      \n      if (res == S_OK)\n      {\n        MarkerIsFound = true;\n        MarkerIsSafe = true;\n      }\n      else if (res != S_FALSE)\n        return res;\n    }\n  }\n  else\n  {\n    // printf(\"\\nOpen offset = %u\\n\", (unsigned)startPos);\n    if (IsMultiVol\n        && (unsigned)Vols.StartParsingVol < Vols.Streams.Size()\n        && Vols.Streams[(unsigned)Vols.StartParsingVol].Stream)\n    {\n      RINOK(SeekToVol(Vols.StartParsingVol, Vols.StreamIndex == Vols.StartVolIndex ? startPos : 0))\n    }\n    else\n    {\n      RINOK(SeekToVol(-1, startPos))\n    }\n    \n    // UInt64 limit = 1 << 22;\n    // HRESULT res = FindMarker(&limit);\n\n    HRESULT res = FindMarker(searchLimit);\n    \n    // const UInt64 curPos = GetVirtStreamPos();\n    const UInt64 curPos = ArcInfo.MarkerPos2 + 4;\n\n    if (res == S_OK)\n      MarkerIsFound = true;\n    else if (!IsMultiVol)\n    {\n      /*\n      // if (startPos != 0), probably CD could be already tested with another call with (startPos == 0).\n      // so we don't want to try to open CD again in that case.\n      if (startPos != 0)\n        return res;\n      // we can try to open CD, if there is no Marker and (startPos == 0).\n      // is it OK to open such files as ZIP, or big number of false positive, when CD can be find in end of file ?\n      */\n      return res;\n    }\n    \n    if (ArcInfo.IsSpanMode && !volWasRequested)\n    {\n      RINOK(ReadVols())\n      if (IsMultiVol && MarkerIsFound && ArcInfo.MarkerVolIndex < 0)\n        ArcInfo.MarkerVolIndex = Vols.StartVolIndex;\n    }\n\n    MarkerIsSafe = !IsMultiVol\n        || (ArcInfo.MarkerVolIndex == 0 && ArcInfo.MarkerPos == 0)\n        ;\n    \n\n    if (IsMultiVol)\n    {\n      if ((unsigned)Vols.StartVolIndex < Vols.Streams.Size())\n      {\n        Stream = Vols.Streams[(unsigned)Vols.StartVolIndex].Stream;\n        if (Stream)\n        {\n          RINOK(Seek_SavePos(curPos))\n        }\n        else\n          IsMultiVol = false;\n      }\n      else\n        IsMultiVol = false;\n    }\n\n    if (!IsMultiVol)\n    {\n      if (Vols.StreamIndex != -1)\n      {\n        Stream = StartStream;\n        Vols.StreamIndex = -1;\n        InitBuf();\n        RINOK(Seek_SavePos(curPos))\n      }\n\n      ArcInfo.MarkerVolIndex = -1;\n      StreamRef = stream;\n      Stream = stream;\n    }\n  }\n\n\n  if (!IsMultiVol)\n    Vols.ClearRefs();\n\n  {\n    HRESULT res;\n    try\n    {\n      res = ReadHeaders(items);\n    }\n    catch (const CSystemException &e) { res = e.ErrorCode; }\n    catch (const CUnexpectEnd &)\n    {\n      if (items.IsEmpty())\n        return S_FALSE;\n      UnexpectedEnd = true;\n      res = S_OK;\n    }\n    catch (...)\n    {\n      DisableBufMode();\n      throw;\n    }\n    \n    if (IsMultiVol)\n    {\n      ArcInfo.FinishPos = ArcInfo.FileEndPos;\n      if ((unsigned)Vols.StreamIndex < Vols.Streams.Size())\n        if (GetVirtStreamPos() < Vols.Streams[(unsigned)Vols.StreamIndex].Size)\n          ArcInfo.ThereIsTail = true;\n    }\n    else\n    {\n      ArcInfo.FinishPos = GetVirtStreamPos();\n      ArcInfo.ThereIsTail = (ArcInfo.FileEndPos > ArcInfo.FinishPos);\n    }\n\n    DisableBufMode();\n\n    IsArcOpen = true;\n    if (!IsMultiVol)\n      Vols.Streams.Clear();\n    return res;\n  }\n}\n\n\nHRESULT CInArchive::GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream)\n{\n  stream.Release();\n\n  UInt64 pos = item.LocalHeaderPos;\n  if (seekPackData)\n    pos += item.LocalFullHeaderSize;\n\n  if (!IsMultiVol)\n  {\n    if (UseDisk_in_SingleVol && item.Disk != EcdVolIndex)\n      return S_OK;\n    pos = (UInt64)((Int64)pos + ArcInfo.Base);\n    RINOK(InStream_SeekSet(StreamRef, pos))\n    stream = StreamRef;\n    return S_OK;\n  }\n\n  if (item.Disk >= Vols.Streams.Size())\n    return S_OK;\n    \n  IInStream *str2 = Vols.Streams[item.Disk].Stream;\n  if (!str2)\n    return S_OK;\n  RINOK(InStream_SeekSet(str2, pos))\n    \n  Vols.NeedSeek = false;\n  Vols.StreamIndex = (int)item.Disk;\n    \n  CVolStream *volsStreamSpec = new CVolStream;\n  volsStreamSpec->Vols = &Vols;\n  stream = volsStreamSpec;\n  \n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipIn.h",
    "content": "﻿// Archive/ZipIn.h\n\n#ifndef ZIP7_INC_ZIP_IN_H\n#define ZIP7_INC_ZIP_IN_H\n\n#include \"../../../Common/MyBuffer2.h\"\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../Common/StreamUtils.h\"\n#include \"../../IStream.h\"\n\n#include \"ZipHeader.h\"\n#include \"ZipItem.h\"\n\nAPI_FUNC_IsArc IsArc_Zip(const Byte *p, size_t size);\n\nnamespace NArchive {\nnamespace NZip {\n  \nclass CItemEx: public CItem\n{\npublic:\n  UInt32 LocalFullHeaderSize; // including Name and Extra\n  // int ParentOfAltStream; // -1, if not AltStream\n  \n  bool DescriptorWasRead;\n\n  CItemEx():\n    // ParentOfAltStream(-1),\n    DescriptorWasRead(false) {}\n\n  UInt64 GetLocalFullSize() const\n    { return LocalFullHeaderSize + GetPackSizeWithDescriptor(); }\n  UInt64 GetDataPosition() const\n    { return LocalHeaderPos + LocalFullHeaderSize; }\n\n  bool IsBadDescriptor() const\n  {\n    return !FromCentral && FromLocal && HasDescriptor() && !DescriptorWasRead;\n  }\n};\n\n\nstruct CInArchiveInfo\n{\n  Int64 Base; /* Base offset of start of archive in stream.\n                 Offsets in headers must be calculated from that Base.\n                 Base is equal to MarkerPos for normal ZIPs.\n                 Base can point to PE stub for some ZIP SFXs.\n                 if CentralDir was read,\n                   Base can be negative, if start of data is not available,\n                 if CentralDirs was not read,\n                   Base = ArcInfo.MarkerPos; */\n\n  /* The following *Pos variables contain absolute offsets in Stream */\n\n  UInt64 MarkerPos;  /* Pos of first signature, it can point to kSpan/kNoSpan signature\n                        = MarkerPos2      in most archives\n                        = MarkerPos2 - 4  if there is kSpan/kNoSpan signature */\n  UInt64 MarkerPos2; // Pos of first local item signature in stream\n  UInt64 FinishPos;  // Finish pos of archive data in starting volume\n  UInt64 FileEndPos; // Finish pos of stream\n\n  UInt64 FirstItemRelatOffset; /* Relative offset of first local (read from cd) (relative to Base).\n                                  = 0 in most archives\n                                  = size of stub for some SFXs */\n\n\n  int MarkerVolIndex;\n\n  bool CdWasRead;\n  bool IsSpanMode;\n  bool ThereIsTail;\n\n  // UInt32 BaseVolIndex;\n\n  CByteBuffer Comment;\n\n\n  CInArchiveInfo():\n      Base(0),\n      MarkerPos(0),\n      MarkerPos2(0),\n      FinishPos(0),\n      FileEndPos(0),\n      FirstItemRelatOffset(0),\n      MarkerVolIndex(-1),\n      CdWasRead(false),\n      IsSpanMode(false),\n      ThereIsTail(false)\n      // BaseVolIndex(0)\n      {}\n  \n  void Clear()\n  {\n    // BaseVolIndex = 0;\n    Base = 0;\n    MarkerPos = 0;\n    MarkerPos2 = 0;\n    FinishPos = 0;\n    FileEndPos = 0;\n    MarkerVolIndex = -1;\n    ThereIsTail = false;\n\n    FirstItemRelatOffset = 0;\n\n    CdWasRead = false;\n    IsSpanMode = false;\n\n    Comment.Free();\n  }\n};\n\n\nstruct CCdInfo\n{\n  bool IsFromEcd64;\n  \n  UInt16 CommentSize;\n  \n  // 64\n  UInt16 VersionMade;\n  UInt16 VersionNeedExtract;\n\n  // old zip\n  UInt32 ThisDisk;\n  UInt32 CdDisk;\n  UInt64 NumEntries_in_ThisDisk;\n  UInt64 NumEntries;\n  UInt64 Size;\n  UInt64 Offset;\n\n  CCdInfo() { memset(this, 0, sizeof(*this)); IsFromEcd64 = false; }\n\n  void ParseEcd32(const Byte *p);   // (p) includes signature\n  void ParseEcd64e(const Byte *p);  // (p) exclude signature\n\n  bool IsEmptyArc() const\n  {\n    return ThisDisk == 0\n        && CdDisk == 0\n        && NumEntries_in_ThisDisk == 0\n        && NumEntries == 0\n        && Size == 0\n        && Offset == 0 // test it\n    ;\n  }\n};\n\n\nstruct CVols\n{\n  struct CSubStreamInfo\n  {\n    CMyComPtr<IInStream> Stream;\n    UInt64 Size;\n\n    HRESULT SeekToStart() const { return InStream_SeekToBegin(Stream); }\n\n    CSubStreamInfo(): Size(0) {}\n  };\n  \n  CObjectVector<CSubStreamInfo> Streams;\n  \n  int StreamIndex;   // -1 for StartStream\n                     // -2 for ZipStream at multivol detection code\n                     // >=0 volume index in multivol\n  \n  bool NeedSeek;\n\n  bool DisableVolsSearch;\n  bool StartIsExe;  // is .exe\n  bool StartIsZ;    // is .zip or .zNN\n  bool StartIsZip;  // is .zip\n  bool IsUpperCase;\n  bool MissingZip;\n\n  bool ecd_wasRead;\n\n  Int32 StartVolIndex; // -1, if unknown vol index\n                       // = (NN - 1), if StartStream is .zNN\n                       // = 0, if start vol is exe\n\n  Int32 StartParsingVol; // if we need local parsing, we must use that stream\n  unsigned NumVols;\n\n  int EndVolIndex; // index of last volume (ecd volume),\n                   // -1, if is not multivol\n\n  UString BaseName; // name of archive including '.'\n  UString MissingName;\n\n  CMyComPtr<IInStream> ZipStream;\n\n  CCdInfo ecd;\n\n  UInt64 TotalBytesSize; // for MultiVol only\n\n  void ClearRefs()\n  {\n    Streams.Clear();\n    ZipStream.Release();\n    TotalBytesSize = 0;\n  }\n\n  void Clear()\n  {\n    StreamIndex = -1;\n    NeedSeek = false;\n\n    DisableVolsSearch = false;\n    StartIsExe = false;\n    StartIsZ = false;\n    StartIsZip = false;\n    IsUpperCase = false;\n\n    StartVolIndex = -1;\n    StartParsingVol = 0;\n    NumVols = 0;\n    EndVolIndex = -1;\n\n    BaseName.Empty();\n    MissingName.Empty();\n\n    MissingZip = false;\n    ecd_wasRead = false;\n\n    ClearRefs();\n  }\n\n  HRESULT ParseArcName(IArchiveOpenVolumeCallback *volCallback);\n\n  HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);\n};\n\n\nZ7_CLASS_IMP_COM_1(\n  CVolStream\n  , ISequentialInStream\n)\npublic:\n  CVols *Vols;\n};\n\n\nclass CInArchive\n{\n  CMidBuffer Buffer;\n  size_t _bufPos;\n  size_t _bufCached;\n\n  UInt64 _streamPos;\n  UInt64 _cnt;\n\n  // UInt32 _startLocalFromCd_Disk;\n  // UInt64 _startLocalFromCd_Offset;\n\n  size_t GetAvail() const { return _bufCached - _bufPos; }\n\n  void InitBuf() { _bufPos = 0; _bufCached = 0; }\n  void DisableBufMode() { InitBuf(); _inBufMode = false; }\n\n  void SkipLookahed(size_t skip)\n  {\n    _bufPos += skip;\n    _cnt += skip;\n  }\n\n  HRESULT AllocateBuffer(size_t size);\n\n  UInt64 GetVirtStreamPos() { return _streamPos - _bufCached + _bufPos; }\n\n  bool _inBufMode;\n\n  bool IsArcOpen;\n  bool CanStartNewVol;\n\n  UInt32 _signature;\n\n  CMyComPtr<IInStream> StreamRef;\n  IInStream *Stream;\n  IInStream *StartStream;\n  IArchiveOpenCallback *Callback;\n\n  HRESULT Seek_SavePos(UInt64 offset);\n  HRESULT SeekToVol(int volIndex, UInt64 offset);\n\n  HRESULT ReadFromCache(Byte *data, unsigned size, unsigned &processed);\n  HRESULT ReadFromCache_FALSE(Byte *data, unsigned size);\n\n  HRESULT ReadVols2(IArchiveOpenVolumeCallback *volCallback,\n      unsigned start, int lastDisk, int zipDisk, unsigned numMissingVolsMax, unsigned &numMissingVols);\n  HRESULT ReadVols();\n\n  HRESULT FindMarker(const UInt64 *searchLimit);\n  HRESULT IncreaseRealPosition(UInt64 addValue, bool &isFinished);\n\n  HRESULT LookAhead(size_t minRequiredInBuffer);\n  void SafeRead(Byte *data, unsigned size);\n  void ReadBuffer(CByteBuffer &buffer, unsigned size);\n  // Byte ReadByte();\n  // UInt16 ReadUInt16();\n  UInt32 ReadUInt32();\n  UInt64 ReadUInt64();\n\n  void ReadSignature();\n\n  void Skip(size_t num);\n  HRESULT Skip64(UInt64 num, unsigned numFiles);\n\n  bool ReadFileName(unsigned nameSize, AString &dest);\n\n  bool ReadExtra(const CLocalItem &item, unsigned extraSize, CExtraBlock &extra,\n      UInt64 &unpackSize, UInt64 &packSize, CItem *cdItem);\n  bool ReadLocalItem(CItemEx &item);\n  HRESULT FindDescriptor(CItemEx &item, unsigned numFiles);\n  HRESULT ReadCdItem(CItemEx &item);\n  HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo);\n  HRESULT FindCd(bool checkOffsetMode);\n  HRESULT TryReadCd(CObjectVector<CItemEx> &items, const CCdInfo &cdInfo, UInt64 cdOffset, UInt64 cdSize);\n  HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt32 &cdDisk, UInt64 &cdOffset, UInt64 &cdSize);\n  HRESULT ReadLocals(CObjectVector<CItemEx> &localItems);\n\n  HRESULT ReadHeaders(CObjectVector<CItemEx> &items);\n\n  HRESULT GetVolStream(unsigned vol, UInt64 pos, CMyComPtr<ISequentialInStream> &stream);\n\npublic:\n  CInArchiveInfo ArcInfo;\n  \n  bool IsArc;\n  bool IsZip64;\n\n  bool IsApk;\n  bool IsCdUnsorted;\n  \n  bool HeadersError;\n  bool HeadersWarning;\n  bool ExtraMinorError;\n  bool UnexpectedEnd;\n  bool LocalsWereRead;\n  bool LocalsCenterMerged;\n  bool NoCentralDir;\n  bool Overflow32bit; // = true, if zip without Zip64 extension support and it has some fields values truncated to 32-bits.\n  bool Cd_NumEntries_Overflow_16bit; // = true, if no Zip64 and 16-bit ecd:NumEntries was overflowed.\n\n  bool MarkerIsFound;\n  bool MarkerIsSafe;\n\n  bool IsMultiVol;\n  bool UseDisk_in_SingleVol;\n  UInt32 EcdVolIndex;\n\n  CVols Vols;\n\n  bool Force_ReadLocals_Mode;\n  bool Disable_VolsRead;\n  bool Disable_FindMarker;\n \n  CInArchive():\n      IsArcOpen(false),\n      Stream(NULL),\n      StartStream(NULL),\n      Callback(NULL),\n      Force_ReadLocals_Mode(false),\n      Disable_VolsRead(false),\n      Disable_FindMarker(false)\n      {}\n\n  UInt64 GetPhySize() const\n  {\n    if (IsMultiVol)\n      return ArcInfo.FinishPos;\n    else\n      return (UInt64)((Int64)ArcInfo.FinishPos - ArcInfo.Base);\n  }\n\n  UInt64 GetOffset() const\n  {\n    if (IsMultiVol)\n      return 0;\n    else\n      return (UInt64)ArcInfo.Base;\n  }\n\n  \n  void ClearRefs();\n  void Close();\n  HRESULT Open(IInStream *stream, const UInt64 *searchLimit, IArchiveOpenCallback *callback, CObjectVector<CItemEx> &items);\n\n  bool IsOpen() const { return IsArcOpen; }\n  \n  bool AreThereErrors() const\n  {\n    return HeadersError\n        || UnexpectedEnd\n        || !Vols.MissingName.IsEmpty();\n  }\n\n  bool IsLocalOffsetOK(const CItemEx &item) const\n  {\n    if (item.FromLocal)\n      return true;\n    return (Int64)GetOffset() + (Int64)item.LocalHeaderPos >= 0;\n  }\n\n  UInt64 GetEmbeddedStubSize() const\n  {\n    // it's possible that first item in CD doesn refers to first local item\n    // so FirstItemRelatOffset is not first local item\n\n    if (ArcInfo.CdWasRead)\n      return ArcInfo.FirstItemRelatOffset;\n    if (IsMultiVol)\n      return 0;\n    return (UInt64)((Int64)ArcInfo.MarkerPos2 - ArcInfo.Base);\n  }\n\n\n  HRESULT CheckDescriptor(const CItemEx &item);\n  HRESULT Read_LocalItem_After_CdItem(CItemEx &item, bool &isAvail, bool &headersError);\n  HRESULT Read_LocalItem_After_CdItem_Full(CItemEx &item);\n\n  HRESULT GetItemStream(const CItemEx &item, bool seekPackData, CMyComPtr<ISequentialInStream> &stream);\n\n  IInStream *GetBaseStream() { return StreamRef; }\n\n  bool CanUpdate() const\n  {\n    if (AreThereErrors()\n       || IsMultiVol\n       || ArcInfo.Base < 0\n       || (Int64)ArcInfo.MarkerPos2 < ArcInfo.Base\n       || ArcInfo.ThereIsTail\n       || GetEmbeddedStubSize() != 0\n       || IsApk\n       || IsCdUnsorted)\n      return false;\n   \n    // 7-zip probably can update archives with embedded stubs.\n    // we just disable that feature for more safety.\n\n    return true;\n  }\n};\n  \n}}\n  \n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipItem.cpp",
    "content": "﻿// Archive/ZipItem.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n#include \"../../../../C/7zCrc.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/PropVariantUtils.h\"\n\n#include \"../Common/ItemNameUtils.h\"\n\n#include \"ZipItem.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nusing namespace NFileHeader;\n\n\n/*\nconst char *k_SpecName_NTFS_STREAM = \"@@NTFS@STREAM@\";\nconst char *k_SpecName_MAC_RESOURCE_FORK = \"@@MAC@RESOURCE-FORK@\";\n*/\n\nstatic const CUInt32PCharPair g_ExtraTypes[] =\n{\n  { NExtraID::kZip64, \"Zip64\" },\n  { NExtraID::kNTFS, \"NTFS\" },\n  { NExtraID::kUnix0, \"UNIX\" },\n  { NExtraID::kStrongEncrypt, \"StrongCrypto\" },\n  { NExtraID::kUnixTime, \"UT\" },\n  { NExtraID::kUnix1, \"UX\" },\n  { NExtraID::kUnix2, \"Ux\" },\n  { NExtraID::kUnixN, \"ux\" },\n  { NExtraID::kIzUnicodeComment, \"uc\" },\n  { NExtraID::kIzUnicodeName, \"up\" },\n  { NExtraID::kIzNtSecurityDescriptor, \"SD\" },\n  { NExtraID::kWzAES, \"WzAES\" },\n  { NExtraID::kApkAlign, \"ApkAlign\" }\n};\n\nvoid CExtraSubBlock::PrintInfo(AString &s) const\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ExtraTypes); i++)\n  {\n    const CUInt32PCharPair &pair = g_ExtraTypes[i];\n    if (pair.Value == ID)\n    {\n      s += pair.Name;\n      if (ID == NExtraID::kUnixTime)\n      {\n        if (Data.Size() >= 1)\n        {\n          s.Add_Colon();\n          const Byte flags = Data[0];\n          if (flags & 1) s.Add_Char('M');\n          if (flags & 2) s.Add_Char('A');\n          if (flags & 4) s.Add_Char('C');\n          const UInt32 size = (UInt32)(Data.Size()) - 1;\n          if (size % 4 == 0)\n          {\n            s.Add_Colon();\n            s.Add_UInt32(size / 4);\n          }\n        }\n      }\n      /*\n      if (ID == NExtraID::kApkAlign && Data.Size() >= 2)\n      {\n        char sz[32];\n        sz[0] = ':';\n        ConvertUInt32ToHex(GetUi16(Data), sz + 1);\n        s += sz;\n        for (unsigned j = 2; j < Data.Size(); j++)\n        {\n          char sz[32];\n          sz[0] = '-';\n          ConvertUInt32ToHex(Data[j], sz + 1);\n          s += sz;\n        }\n      }\n      */\n      return;\n    }\n  }\n  {\n    char sz[16];\n    sz[0] = '0';\n    sz[1] = 'x';\n    ConvertUInt32ToHex(ID, sz + 2);\n    s += sz;\n  }\n}\n\n\nvoid CExtraBlock::PrintInfo(AString &s) const\n{\n  if (Error)\n    s.Add_OptSpaced(\"Extra_ERROR\");\n\n  if (MinorError)\n    s.Add_OptSpaced(\"Minor_Extra_ERROR\");\n\n  if (IsZip64 || IsZip64_Error)\n  {\n    s.Add_OptSpaced(\"Zip64\");\n    if (IsZip64_Error)\n      s += \"_ERROR\";\n  }\n\n  FOR_VECTOR (i, SubBlocks)\n  {\n    s.Add_Space_if_NotEmpty();\n    SubBlocks[i].PrintInfo(s);\n  }\n}\n\n\nbool CExtraSubBlock::ExtractNtfsTime(unsigned index, FILETIME &ft) const\n{\n  ft.dwHighDateTime = ft.dwLowDateTime = 0;\n  UInt32 size = (UInt32)Data.Size();\n  if (ID != NExtraID::kNTFS || size < 32)\n    return false;\n  const Byte *p = (const Byte *)Data;\n  p += 4; // for reserved\n  size -= 4;\n  while (size > 4)\n  {\n    UInt16 tag = GetUi16(p);\n    unsigned attrSize = GetUi16(p + 2);\n    p += 4;\n    size -= 4;\n    if (attrSize > size)\n      attrSize = size;\n    \n    if (tag == NNtfsExtra::kTagTime && attrSize >= 24)\n    {\n      p += 8 * index;\n      ft.dwLowDateTime = GetUi32(p);\n      ft.dwHighDateTime = GetUi32(p + 4);\n      return true;\n    }\n    p += attrSize;\n    size -= attrSize;\n  }\n  return false;\n}\n\nbool CExtraSubBlock::Extract_UnixTime(bool isCentral, unsigned index, UInt32 &res) const\n{\n  /* Info-Zip :\n     The central-header extra field contains the modification\n     time only, or no timestamp at all.\n     Size of Data is used to flag its presence or absence\n     If \"Flags\" indicates that Modtime is present in the local header\n     field, it MUST be present in the central header field, too\n  */\n\n  res = 0;\n  UInt32 size = (UInt32)Data.Size();\n  if (ID != NExtraID::kUnixTime || size < 5)\n    return false;\n  const Byte *p = (const Byte *)Data;\n  const Byte flags = *p++;\n  size--;\n  if (isCentral)\n  {\n    if (index != NUnixTime::kMTime ||\n        (flags & (1 << NUnixTime::kMTime)) == 0 ||\n        size < 4)\n      return false;\n    res = GetUi32(p);\n    return true;\n  }\n  for (unsigned i = 0; i < 3; i++)\n    if ((flags & (1 << i)) != 0)\n    {\n      if (size < 4)\n        return false;\n      if (index == i)\n      {\n        res = GetUi32(p);\n        return true;\n      }\n      p += 4;\n      size -= 4;\n    }\n  return false;\n}\n\n\n// Info-ZIP's abandoned \"Unix1 timestamps & owner ID info\"\n\nbool CExtraSubBlock::Extract_Unix01_Time(unsigned index, UInt32 &res) const\n{\n  res = 0;\n  const unsigned offset = index * 4;\n  if (Data.Size() < offset + 4)\n    return false;\n  if (ID != NExtraID::kUnix0 &&\n      ID != NExtraID::kUnix1)\n    return false;\n  const Byte *p = (const Byte *)Data + offset;\n  res = GetUi32(p);\n  return true;\n}\n\n/*\n// PKWARE's Unix \"extra\" is similar to Info-ZIP's abandoned \"Unix1 timestamps\"\nbool CExtraSubBlock::Extract_Unix_Time(unsigned index, UInt32 &res) const\n{\n  res = 0;\n  const unsigned offset = index * 4;\n  if (ID != NExtraID::kUnix0 || Data.Size() < offset)\n    return false;\n  const Byte *p = (const Byte *)Data + offset;\n  res = GetUi32(p);\n  return true;\n}\n*/\n\nbool CExtraBlock::GetNtfsTime(unsigned index, FILETIME &ft) const\n{\n  FOR_VECTOR (i, SubBlocks)\n  {\n    const CExtraSubBlock &sb = SubBlocks[i];\n    if (sb.ID == NFileHeader::NExtraID::kNTFS)\n      return sb.ExtractNtfsTime(index, ft);\n  }\n  return false;\n}\n\nbool CExtraBlock::GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const\n{\n  {\n    FOR_VECTOR (i, SubBlocks)\n    {\n      const CExtraSubBlock &sb = SubBlocks[i];\n      if (sb.ID == NFileHeader::NExtraID::kUnixTime)\n        return sb.Extract_UnixTime(isCentral, index, res);\n    }\n  }\n  \n  switch (index)\n  {\n    case NUnixTime::kMTime: index = NUnixExtra::kMTime; break;\n    case NUnixTime::kATime: index = NUnixExtra::kATime; break;\n    default: return false;\n  }\n  \n  {\n    FOR_VECTOR (i, SubBlocks)\n    {\n      const CExtraSubBlock &sb = SubBlocks[i];\n      if (sb.ID == NFileHeader::NExtraID::kUnix0 ||\n          sb.ID == NFileHeader::NExtraID::kUnix1)\n        return sb.Extract_Unix01_Time(index, res);\n    }\n  }\n  return false;\n}\n\n\nbool CLocalItem::IsDir() const\n{\n  return NItemName::HasTailSlash(Name, GetCodePage());\n}\n\nbool CItem::IsDir() const\n{\n  // FIXME: we can check InfoZip UTF-8 name at first.\n  if (NItemName::HasTailSlash(Name, GetCodePage()))\n    return true;\n  \n  Byte hostOS = GetHostOS();\n\n  if (Size == 0 && PackSize == 0 && !Name.IsEmpty() && Name.Back() == '\\\\')\n  {\n    // do we need to use CharPrevExA?\n    // .NET Framework 4.5 : System.IO.Compression::CreateFromDirectory() probably writes backslashes to headers?\n    // so we support that case\n    switch (hostOS)\n    {\n      case NHostOS::kFAT:\n      case NHostOS::kNTFS:\n      case NHostOS::kHPFS:\n      case NHostOS::kVFAT:\n        return true;\n      default: break;\n    }\n  }\n\n  if (!FromCentral)\n    return false;\n  \n  UInt16 highAttrib = (UInt16)((ExternalAttrib >> 16 ) & 0xFFFF);\n\n  switch (hostOS)\n  {\n    case NHostOS::kAMIGA:\n      switch (highAttrib & NAmigaAttrib::kIFMT)\n      {\n        case NAmigaAttrib::kIFDIR: return true;\n        case NAmigaAttrib::kIFREG: return false;\n        default: return false; // change it throw kUnknownAttributes;\n      }\n    case NHostOS::kFAT:\n    case NHostOS::kNTFS:\n    case NHostOS::kHPFS:\n    case NHostOS::kVFAT:\n      return ((ExternalAttrib & FILE_ATTRIBUTE_DIRECTORY) != 0);\n    case NHostOS::kAtari:\n    case NHostOS::kMac:\n    case NHostOS::kVMS:\n    case NHostOS::kVM_CMS:\n    case NHostOS::kAcorn:\n    case NHostOS::kMVS:\n      return false; // change it throw kUnknownAttributes;\n    case NHostOS::kUnix:\n      return MY_LIN_S_ISDIR(highAttrib);\n    default:\n      return false;\n  }\n}\n\nUInt32 CItem::GetWinAttrib() const\n{\n  UInt32 winAttrib = 0;\n  switch (GetHostOS())\n  {\n    case NHostOS::kFAT:\n    case NHostOS::kNTFS:\n      if (FromCentral)\n        winAttrib = ExternalAttrib;\n      break;\n    case NHostOS::kUnix:\n      // do we need to clear 16 low bits in this case?\n      if (FromCentral)\n      {\n        /*\n          Some programs write posix attributes in high 16 bits of ExternalAttrib\n          Also some programs can write additional marker flag:\n            0x8000 - p7zip\n            0x4000 - Zip in MacOS\n            no marker - Info-Zip\n\n          Client code has two options to detect posix field:\n            1) check 0x8000 marker. In that case we must add 0x8000 marker here.\n            2) check that high 4 bits (file type bits in posix field) of attributes are not zero.\n        */\n        \n        winAttrib = ExternalAttrib & 0xFFFF0000;\n        \n        // #ifndef _WIN32\n        winAttrib |= 0x8000; // add posix mode marker\n        // #endif\n      }\n      break;\n    default: break;\n  }\n  if (IsDir()) // test it;\n    winAttrib |= FILE_ATTRIBUTE_DIRECTORY;\n  return winAttrib;\n}\n\nbool CItem::GetPosixAttrib(UInt32 &attrib) const\n{\n  // some archivers can store PosixAttrib in high 16 bits even with HostOS=FAT.\n  if (FromCentral && GetHostOS() == NHostOS::kUnix)\n  {\n    attrib = ExternalAttrib >> 16;\n    return (attrib != 0);\n  }\n  attrib = 0;\n  if (IsDir())\n    attrib = MY_LIN_S_IFDIR;\n  return false;\n}\n\n\nbool CExtraSubBlock::CheckIzUnicode(const AString &s) const\n{\n  size_t size = Data.Size();\n  if (size < 1 + 4)\n    return false;\n  const Byte *p = (const Byte *)Data;\n  if (p[0] > 1)\n    return false;\n  if (CrcCalc(s, s.Len()) != GetUi32(p + 1))\n    return false;\n  size -= 5;\n  p += 5;\n  for (size_t i = 0; i < size; i++)\n    if (p[i] == 0)\n      return false;\n  return Check_UTF8_Buf((const char *)(const void *)p, size, false);\n}\n  \n\nvoid CItem::GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const\n{\n  bool isUtf8 = IsUtf8();\n  // bool ignore_Utf8_Errors = true;\n  \n  if (!isUtf8)\n  {\n    {\n      const unsigned id = isComment ?\n          NFileHeader::NExtraID::kIzUnicodeComment:\n          NFileHeader::NExtraID::kIzUnicodeName;\n      const CObjectVector<CExtraSubBlock> &subBlocks = GetMainExtra().SubBlocks;\n      \n      FOR_VECTOR (i, subBlocks)\n      {\n        const CExtraSubBlock &sb = subBlocks[i];\n        if (sb.ID == id)\n        {\n          if (sb.CheckIzUnicode(s))\n          {\n            // const unsigned kIzUnicodeHeaderSize = 5;\n            if (Convert_UTF8_Buf_To_Unicode(\n                (const char *)(const void *)(const Byte *)sb.Data + 5,\n                sb.Data.Size() - 5, res))\n              return;\n          }\n          break;\n        }\n      }\n    }\n    \n    if (useSpecifiedCodePage)\n      isUtf8 = (codePage == CP_UTF8);\n    #ifdef _WIN32\n    else if (GetHostOS() == NFileHeader::NHostOS::kUnix)\n    {\n      /* Some ZIP archives in Unix use UTF-8 encoding without Utf8 flag in header.\n         We try to get name as UTF-8.\n         Do we need to do it in POSIX version also? */\n      isUtf8 = true;\n\n      /* 21.02: we want to ignore UTF-8 errors to support file paths that are mixed\n          of UTF-8 and non-UTF-8 characters. */\n      // ignore_Utf8_Errors = false;\n      // ignore_Utf8_Errors = true;\n    }\n    #endif\n  }\n  \n  \n  if (isUtf8)\n  {\n    ConvertUTF8ToUnicode(s, res);\n    return;\n  }\n  \n  MultiByteToUnicodeString2(res, s, useSpecifiedCodePage ? codePage : GetCodePage());\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipItem.h",
    "content": "﻿// Archive/ZipItem.h\n\n#ifndef ZIP7_INC_ARCHIVE_ZIP_ITEM_H\n#define ZIP7_INC_ARCHIVE_ZIP_ITEM_H\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyString.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"ZipHeader.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\n/*\nextern const char *k_SpecName_NTFS_STREAM;\nextern const char *k_SpecName_MAC_RESOURCE_FORK;\n*/\n\nstruct CVersion\n{\n  Byte Version;\n  Byte HostOS;\n};\n\nstruct CExtraSubBlock\n{\n  UInt32 ID;\n  CByteBuffer Data;\n\n  bool ExtractNtfsTime(unsigned index, FILETIME &ft) const;\n  bool Extract_UnixTime(bool isCentral, unsigned index, UInt32 &res) const;\n  bool Extract_Unix01_Time(unsigned index, UInt32 &res) const;\n  // bool Extract_Unix_Time(unsigned index, UInt32 &res) const;\n\n  bool CheckIzUnicode(const AString &s) const;\n\n  void PrintInfo(AString &s) const;\n};\n\nconst unsigned k_WzAesExtra_Size = 7;\n\nstruct CWzAesExtra\n{\n  UInt16 VendorVersion; // 1: AE-1, 2: AE-2,\n  // UInt16 VendorId; // 'A' 'E'\n  Byte Strength; // 1: 128-bit, 2: 192-bit, 3: 256-bit\n  UInt16 Method;\n\n  CWzAesExtra(): VendorVersion(2), Strength(3), Method(0) {}\n\n  bool NeedCrc() const { return (VendorVersion == 1); }\n\n  bool ParseFromSubBlock(const CExtraSubBlock &sb)\n  {\n    if (sb.ID != NFileHeader::NExtraID::kWzAES)\n      return false;\n    if (sb.Data.Size() < k_WzAesExtra_Size)\n      return false;\n    const Byte *p = (const Byte *)sb.Data;\n    VendorVersion = GetUi16(p);\n    if (p[2] != 'A' || p[3] != 'E')\n      return false;\n    Strength = p[4];\n    // 9.31: The BUG was fixed:\n    Method = GetUi16(p + 5);\n    return true;\n  }\n  \n  void SetSubBlock(CExtraSubBlock &sb) const\n  {\n    sb.Data.Alloc(k_WzAesExtra_Size);\n    sb.ID = NFileHeader::NExtraID::kWzAES;\n    Byte *p = (Byte *)sb.Data;\n    p[0] = (Byte)VendorVersion;\n    p[1] = (Byte)(VendorVersion >> 8);\n    p[2] = 'A';\n    p[3] = 'E';\n    p[4] = Strength;\n    p[5] = (Byte)Method;\n    p[6] = (Byte)(Method >> 8);\n  }\n};\n\nnamespace NStrongCrypto_AlgId\n{\n  const UInt16 kDES = 0x6601;\n  const UInt16 kRC2old = 0x6602;\n  const UInt16 k3DES168 = 0x6603;\n  const UInt16 k3DES112 = 0x6609;\n  const UInt16 kAES128 = 0x660E;\n  const UInt16 kAES192 = 0x660F;\n  const UInt16 kAES256 = 0x6610;\n  const UInt16 kRC2 = 0x6702;\n  const UInt16 kBlowfish = 0x6720;\n  const UInt16 kTwofish = 0x6721;\n  const UInt16 kRC4 = 0x6801;\n}\n\nstruct CStrongCryptoExtra\n{\n  UInt16 Format;\n  UInt16 AlgId;\n  UInt16 BitLen;\n  UInt16 Flags;\n\n  bool ParseFromSubBlock(const CExtraSubBlock &sb)\n  {\n    if (sb.ID != NFileHeader::NExtraID::kStrongEncrypt)\n      return false;\n    const Byte *p = (const Byte *)sb.Data;\n    if (sb.Data.Size() < 8)\n      return false;\n    Format = GetUi16(p + 0);\n    AlgId  = GetUi16(p + 2);\n    BitLen = GetUi16(p + 4);\n    Flags  = GetUi16(p + 6);\n    return (Format == 2);\n  }\n\n  bool CertificateIsUsed() const { return (Flags > 0x0001); }\n};\n\n\nstruct CExtraBlock\n{\n  CObjectVector<CExtraSubBlock> SubBlocks;\n  bool Error;\n  bool MinorError;\n  bool IsZip64;\n  bool IsZip64_Error;\n  \n  CExtraBlock(): Error(false), MinorError(false), IsZip64(false), IsZip64_Error(false) {}\n\n  void Clear()\n  {\n    SubBlocks.Clear();\n    IsZip64 = false;\n  }\n  \n  size_t GetSize() const\n  {\n    size_t res = 0;\n    FOR_VECTOR (i, SubBlocks)\n      res += SubBlocks[i].Data.Size() + 2 + 2;\n    return res;\n  }\n  \n  bool GetWzAes(CWzAesExtra &e) const\n  {\n    FOR_VECTOR (i, SubBlocks)\n      if (e.ParseFromSubBlock(SubBlocks[i]))\n        return true;\n    return false;\n  }\n\n  bool HasWzAes() const\n  {\n    CWzAesExtra e;\n    return GetWzAes(e);\n  }\n\n  bool GetStrongCrypto(CStrongCryptoExtra &e) const\n  {\n    FOR_VECTOR (i, SubBlocks)\n      if (e.ParseFromSubBlock(SubBlocks[i]))\n        return true;\n    return false;\n  }\n\n  /*\n  bool HasStrongCrypto() const\n  {\n    CStrongCryptoExtra e;\n    return GetStrongCrypto(e);\n  }\n  */\n\n  bool GetNtfsTime(unsigned index, FILETIME &ft) const;\n  bool GetUnixTime(bool isCentral, unsigned index, UInt32 &res) const;\n\n  void PrintInfo(AString &s) const;\n\n  void RemoveUnknownSubBlocks()\n  {\n    for (unsigned i = SubBlocks.Size(); i != 0;)\n    {\n      i--;\n      switch (SubBlocks[i].ID)\n      {\n        case NFileHeader::NExtraID::kStrongEncrypt:\n        case NFileHeader::NExtraID::kWzAES:\n          break;\n        default:\n          SubBlocks.Delete(i);\n      }\n    }\n  }\n};\n\n\nclass CLocalItem\n{\npublic:\n  UInt16 Flags;\n  UInt16 Method;\n  \n  /*\n    Zip specification doesn't mention that ExtractVersion field uses HostOS subfield.\n    18.06: 7-Zip now doesn't use ExtractVersion::HostOS to detect codePage\n  */\n\n  CVersion ExtractVersion;\n\n  UInt64 Size;\n  UInt64 PackSize;\n  UInt32 Time;\n  UInt32 Crc;\n\n  UInt32 Disk;\n  \n  AString Name;\n\n  CExtraBlock LocalExtra;\n\n  unsigned GetDescriptorSize() const { return LocalExtra.IsZip64 ? kDataDescriptorSize64 : kDataDescriptorSize32; }\n\n  UInt64 GetPackSizeWithDescriptor() const\n    { return PackSize + (HasDescriptor() ? GetDescriptorSize() : 0); }\n\n  bool IsUtf8() const { return (Flags & NFileHeader::NFlags::kUtf8) != 0; }\n  bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kEncrypted) != 0; }\n  bool IsStrongEncrypted() const { return IsEncrypted() && (Flags & NFileHeader::NFlags::kStrongEncrypted) != 0; }\n  bool IsAesEncrypted() const { return IsEncrypted() && (IsStrongEncrypted() || Method == NFileHeader::NCompressionMethod::kWzAES); }\n  bool IsLzmaEOS() const { return (Flags & NFileHeader::NFlags::kLzmaEOS) != 0; }\n  bool HasDescriptor() const { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }\n  // bool IsAltStream() const { return (Flags & NFileHeader::NFlags::kAltStream) != 0; }\n\n  unsigned GetDeflateLevel() const { return (Flags >> 1) & 3; }\n  \n  bool IsDir() const;\n\n  /*\n  void GetUnicodeString(const AString &s, UString &res) const\n  {\n    bool isUtf8 = IsUtf8();\n    if (isUtf8)\n      if (ConvertUTF8ToUnicode(s, res))\n        return;\n    MultiByteToUnicodeString2(res, s, GetCodePage());\n  }\n  */\n\nprivate:\n\n  void SetFlag(unsigned bitMask, bool enable)\n  {\n    if (enable)\n      Flags = (UInt16)(Flags | bitMask);\n    else\n      Flags = (UInt16)(Flags & ~bitMask);\n  }\n\npublic:\n\n  void ClearFlags() { Flags = 0; }\n  void SetEncrypted(bool encrypted) { SetFlag(NFileHeader::NFlags::kEncrypted, encrypted); }\n  void SetUtf8(bool isUtf8) { SetFlag(NFileHeader::NFlags::kUtf8, isUtf8); }\n  // void SetFlag_AltStream(bool isAltStream) { SetFlag(NFileHeader::NFlags::kAltStream, isAltStream); }\n  void SetDescriptorMode(bool useDescriptor) { SetFlag(NFileHeader::NFlags::kDescriptorUsedMask, useDescriptor); }\n\n  UINT GetCodePage() const\n  {\n    if (IsUtf8())\n      return CP_UTF8;\n    return CP_OEMCP;\n  }\n};\n\n\nclass CItem: public CLocalItem\n{\npublic:\n  CVersion MadeByVersion;\n  UInt16 InternalAttrib;\n  UInt32 ExternalAttrib;\n  \n  UInt64 LocalHeaderPos;\n  \n  CExtraBlock CentralExtra;\n  CByteBuffer Comment;\n\n  bool FromLocal;\n  bool FromCentral;\n  \n  // CItem can be used as CLocalItem. So we must clear unused fields\n  CItem():\n      InternalAttrib(0),\n      ExternalAttrib(0),\n      FromLocal(false),\n      FromCentral(false)\n  {\n    MadeByVersion.Version = 0;\n    MadeByVersion.HostOS = 0;\n  }\n\n  const CExtraBlock &GetMainExtra() const { return *(FromCentral ? &CentralExtra : &LocalExtra); }\n\n  bool IsDir() const;\n  UInt32 GetWinAttrib() const;\n  bool GetPosixAttrib(UInt32 &attrib) const;\n\n  // 18.06: 0 instead of ExtractVersion.HostOS for local item\n  Byte GetHostOS() const { return FromCentral ? MadeByVersion.HostOS : (Byte)0; }\n\n  void GetUnicodeString(UString &res, const AString &s, bool isComment, bool useSpecifiedCodePage, UINT codePage) const;\n\n  bool IsThereCrc() const\n  {\n    if (Method == NFileHeader::NCompressionMethod::kWzAES)\n    {\n      CWzAesExtra aesField;\n      if (GetMainExtra().GetWzAes(aesField))\n        return aesField.NeedCrc();\n    }\n    return (Crc != 0 || !IsDir());\n  }\n\n  bool Is_MadeBy_Unix() const\n  {\n    if (!FromCentral)\n      return false;\n    return (MadeByVersion.HostOS == NFileHeader::NHostOS::kUnix);\n  }\n  \n  UINT GetCodePage() const\n  {\n    // 18.06: now we use HostOS only from Central::MadeByVersion\n    if (IsUtf8())\n      return CP_UTF8;\n    if (!FromCentral)\n      return CP_OEMCP;\n    Byte hostOS = MadeByVersion.HostOS;\n    return (UINT)((\n           hostOS == NFileHeader::NHostOS::kFAT\n        || hostOS == NFileHeader::NHostOS::kNTFS\n        || hostOS == NFileHeader::NHostOS::kUnix // do we need it?\n        ) ? CP_OEMCP : CP_ACP);\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipOut.cpp",
    "content": "﻿// ZipOut.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/7zCrc.h\"\n\n#include \"../../../Windows/TimeUtils.h\"\n#include \"../../Common/OffsetStream.h\"\n\n#include \"ZipOut.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nHRESULT COutArchive::ClearRestriction()\n{\n  if (SetRestriction)\n    return SetRestriction->SetRestriction(0, 0);\n  return S_OK;\n}\n\nHRESULT COutArchive::SetRestrictionFromCurrent()\n{\n  if (SetRestriction)\n    return SetRestriction->SetRestriction(m_Base + m_CurPos, (UInt64)(Int64)-1);\n  return S_OK;\n}\n\nHRESULT COutArchive::Create(IOutStream *outStream)\n{\n  m_CurPos = 0;\n  if (!m_OutBuffer.Create(1 << 16))\n    return E_OUTOFMEMORY;\n  m_Stream = outStream;\n  m_OutBuffer.SetStream(outStream);\n  m_OutBuffer.Init();\n\n  return m_Stream->Seek(0, STREAM_SEEK_CUR, &m_Base);\n}\n\nvoid COutArchive::SeekToCurPos()\n{\n  HRESULT res = m_Stream->Seek((Int64)(m_Base + m_CurPos), STREAM_SEEK_SET, NULL);\n  if (res != S_OK)\n    throw CSystemException(res);\n}\n\n#define DOES_NEED_ZIP64(v) (v >= (UInt32)0xFFFFFFFF)\n// #define DOES_NEED_ZIP64(v) (v >= 0)\n\n\nZ7_NO_INLINE\nvoid COutArchive::WriteBytes(const void *data, size_t size)\n{\n  m_OutBuffer.WriteBytes(data, size);\n  m_CurPos += size;\n}\n\nZ7_NO_INLINE\nvoid COutArchive::Write8(Byte b)\n{\n  m_OutBuffer.WriteByte(b);\n  m_CurPos++;\n}\n\nZ7_NO_INLINE\nvoid COutArchive::Write16(UInt16 val)\n{\n  Write8((Byte)val);\n  Write8((Byte)(val >> 8));\n}\n\nZ7_NO_INLINE\nvoid COutArchive::Write32(UInt32 val)\n{\n  for (int i = 0; i < 4; i++)\n  {\n    // Write8((Byte)val);\n    m_OutBuffer.WriteByte((Byte)val);\n    val >>= 8;\n  }\n  m_CurPos += 4;\n}\n\n#define WRITE_CONST_PAIR_16_16(a, b)  { Write32((a) | ((UInt32)(b) << 16)); }\n\nZ7_NO_INLINE\nvoid COutArchive::Write64(UInt64 val)\n{\n  for (int i = 0; i < 8; i++)\n  {\n    // Write8((Byte)val);\n    m_OutBuffer.WriteByte((Byte)val);\n    val >>= 8;\n  }\n  m_CurPos += 8;\n}\n\nZ7_NO_INLINE\nvoid COutArchive::WriteExtra(const CExtraBlock &extra)\n{\n  FOR_VECTOR (i, extra.SubBlocks)\n  {\n    const CExtraSubBlock &subBlock = extra.SubBlocks[i];\n    Write16((UInt16)subBlock.ID);\n    Write16((UInt16)subBlock.Data.Size());\n    WriteBytes(subBlock.Data, (UInt16)subBlock.Data.Size());\n  }\n}\n\nvoid COutArchive::WriteCommonItemInfo(const CLocalItem &item, bool isZip64)\n{\n  {\n    Byte ver = item.ExtractVersion.Version;\n    if (isZip64 && ver < NFileHeader::NCompressionMethod::kExtractVersion_Zip64)\n      ver = NFileHeader::NCompressionMethod::kExtractVersion_Zip64;\n    Write8(ver);\n  }\n  Write8(item.ExtractVersion.HostOS);\n  Write16(item.Flags);\n  Write16(item.Method);\n  Write32(item.Time);\n}\n\n\n#define WRITE_32_VAL_SPEC(_v_, _isZip64_) Write32((_isZip64_) ? 0xFFFFFFFF : (UInt32)(_v_));\n\n\nvoid COutArchive::WriteUtfName(const CItemOut &item)\n{\n  if (item.Name_Utf.Size() == 0)\n    return;\n  Write16(NFileHeader::NExtraID::kIzUnicodeName);\n  Write16((UInt16)(5 + item.Name_Utf.Size()));\n  Write8(1); // (1 = version) of that extra field\n  Write32(CrcCalc(item.Name.Ptr(), item.Name.Len()));\n  WriteBytes(item.Name_Utf, (UInt16)item.Name_Utf.Size());\n}\n\n\nstatic const unsigned k_Ntfs_ExtraSize = 4 + 2 + 2 + (3 * 8);\nstatic const unsigned k_UnixTime_ExtraSize = 1 + (1 * 4);\n\nvoid COutArchive::WriteTimeExtra(const CItemOut &item, bool writeNtfs)\n{\n  if (writeNtfs)\n  {\n    // windows explorer ignores that extra\n    WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kNTFS, k_Ntfs_ExtraSize)\n    Write32(0); // reserved\n    WRITE_CONST_PAIR_16_16(NFileHeader::NNtfsExtra::kTagTime, 8 * 3)\n    WriteNtfsTime(item.Ntfs_MTime);\n    WriteNtfsTime(item.Ntfs_ATime);\n    WriteNtfsTime(item.Ntfs_CTime);\n  }\n\n  if (item.Write_UnixTime)\n  {\n    // windows explorer ignores that extra\n    // by specification : should we write to local header also?\n    WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kUnixTime, k_UnixTime_ExtraSize)\n    const Byte flags = (Byte)((unsigned)1 << NFileHeader::NUnixTime::kMTime);\n    Write8(flags);\n    UInt32 unixTime;\n    NWindows::NTime::FileTime_To_UnixTime(item.Ntfs_MTime, unixTime);\n    Write32(unixTime);\n  }\n}\n\n\nvoid COutArchive::WriteLocalHeader(CItemOut &item, bool needCheck)\n{\n  m_LocalHeaderPos = m_CurPos;\n  item.LocalHeaderPos = m_CurPos;\n  \n  bool isZip64 =\n      DOES_NEED_ZIP64(item.PackSize) ||\n      DOES_NEED_ZIP64(item.Size);\n\n  if (needCheck && m_IsZip64)\n    isZip64 = true;\n\n  // Why don't we write NTFS timestamps to local header?\n  // Probably we want to reduce size of archive?\n  const bool writeNtfs = false; // do not write NTFS timestamp to local header\n  // const bool writeNtfs = item.Write_NtfsTime; // write NTFS time to local header\n  const UInt32 localExtraSize = (UInt32)(\n      (isZip64 ? (4 + 8 + 8): 0)\n      + (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0)\n      + (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0)\n      + item.Get_UtfName_ExtraSize()\n      + item.LocalExtra.GetSize());\n  if ((UInt16)localExtraSize != localExtraSize)\n    throw CSystemException(E_FAIL);\n  if (needCheck && m_ExtraSize != localExtraSize)\n    throw CSystemException(E_FAIL);\n\n  m_IsZip64 = isZip64;\n  m_ExtraSize = localExtraSize;\n\n  item.LocalExtra.IsZip64 = isZip64;\n\n  Write32(NSignature::kLocalFileHeader);\n  \n  WriteCommonItemInfo(item, isZip64);\n  \n  Write32(item.HasDescriptor() ? 0 : item.Crc);\n\n  UInt64 packSize = item.PackSize;\n  UInt64 size = item.Size;\n  \n  if (item.HasDescriptor())\n  {\n    packSize = 0;\n    size = 0;\n  }\n  \n  WRITE_32_VAL_SPEC(packSize, isZip64)\n  WRITE_32_VAL_SPEC(size, isZip64)\n\n  Write16((UInt16)item.Name.Len());\n\n  Write16((UInt16)localExtraSize);\n  \n  WriteBytes((const char *)item.Name, (UInt16)item.Name.Len());\n\n  if (isZip64)\n  {\n    WRITE_CONST_PAIR_16_16(NFileHeader::NExtraID::kZip64, 8 + 8)\n    Write64(size);\n    Write64(packSize);\n  }\n\n  WriteTimeExtra(item, writeNtfs);\n\n  WriteUtfName(item);\n\n  WriteExtra(item.LocalExtra);\n\n  const UInt32 localFileHeaderSize = (UInt32)(m_CurPos - m_LocalHeaderPos);\n  if (needCheck && m_LocalFileHeaderSize != localFileHeaderSize)\n    throw CSystemException(E_FAIL);\n  m_LocalFileHeaderSize = localFileHeaderSize;\n\n  m_OutBuffer.FlushWithCheck();\n}\n\n\nvoid COutArchive::WriteLocalHeader_Replace(CItemOut &item)\n{\n  m_CurPos = m_LocalHeaderPos + m_LocalFileHeaderSize + item.PackSize;\n\n  if (item.HasDescriptor())\n  {\n    WriteDescriptor(item);\n    m_OutBuffer.FlushWithCheck();\n    return;\n    // we don't replace local header, if we write Descriptor.\n    // so local header with Descriptor flag must be written to local header before.\n  }\n\n  const UInt64 nextPos = m_CurPos;\n  m_CurPos = m_LocalHeaderPos;\n  SeekToCurPos();\n  WriteLocalHeader(item, true);\n  m_CurPos = nextPos;\n  SeekToCurPos();\n}\n\n\nvoid COutArchive::WriteDescriptor(const CItemOut &item)\n{\n  Byte buf[kDataDescriptorSize64];\n  SetUi32(buf, NSignature::kDataDescriptor)\n  SetUi32(buf + 4, item.Crc)\n  unsigned descriptorSize;\n  if (m_IsZip64)\n  {\n    SetUi64(buf + 8, item.PackSize)\n    SetUi64(buf + 16, item.Size)\n    descriptorSize = kDataDescriptorSize64;\n  }\n  else\n  {\n    SetUi32(buf + 8, (UInt32)item.PackSize)\n    SetUi32(buf + 12, (UInt32)item.Size)\n    descriptorSize = kDataDescriptorSize32;\n  }\n  WriteBytes(buf, descriptorSize);\n}\n\n\n\nvoid COutArchive::WriteCentralHeader(const CItemOut &item)\n{\n  const bool isUnPack64 = DOES_NEED_ZIP64(item.Size);\n  const bool isPack64 = DOES_NEED_ZIP64(item.PackSize);\n  const bool isPosition64 = DOES_NEED_ZIP64(item.LocalHeaderPos);\n  const bool isZip64 = isPack64 || isUnPack64 || isPosition64;\n  \n  Write32(NSignature::kCentralFileHeader);\n  Write8(item.MadeByVersion.Version);\n  Write8(item.MadeByVersion.HostOS);\n  \n  WriteCommonItemInfo(item, isZip64);\n  Write32(item.Crc);\n\n  WRITE_32_VAL_SPEC(item.PackSize, isPack64)\n  WRITE_32_VAL_SPEC(item.Size, isUnPack64)\n\n  Write16((UInt16)item.Name.Len());\n  \n  const UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0));\n  const bool writeNtfs = item.Write_NtfsTime;\n  const size_t centralExtraSize =\n      (isZip64 ? 4 + zip64ExtraSize : 0)\n      + (writeNtfs ? 4 + k_Ntfs_ExtraSize : 0)\n      + (item.Write_UnixTime ? 4 + k_UnixTime_ExtraSize : 0)\n      + item.Get_UtfName_ExtraSize()\n      + item.CentralExtra.GetSize();\n\n  const UInt16 centralExtraSize16 = (UInt16)centralExtraSize;\n  if (centralExtraSize16 != centralExtraSize)\n    throw CSystemException(E_FAIL);\n\n  Write16(centralExtraSize16);\n\n  const UInt16 commentSize = (UInt16)item.Comment.Size();\n  \n  Write16(commentSize);\n  Write16(0); // DiskNumberStart\n  Write16(item.InternalAttrib);\n  Write32(item.ExternalAttrib);\n  WRITE_32_VAL_SPEC(item.LocalHeaderPos, isPosition64)\n  WriteBytes((const char *)item.Name, item.Name.Len());\n  \n  if (isZip64)\n  {\n    Write16(NFileHeader::NExtraID::kZip64);\n    Write16(zip64ExtraSize);\n    if (isUnPack64)\n      Write64(item.Size);\n    if (isPack64)\n      Write64(item.PackSize);\n    if (isPosition64)\n      Write64(item.LocalHeaderPos);\n  }\n  \n  WriteTimeExtra(item, writeNtfs);\n  WriteUtfName(item);\n  \n  WriteExtra(item.CentralExtra);\n  if (commentSize != 0)\n    WriteBytes(item.Comment, commentSize);\n}\n\nHRESULT COutArchive::WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment)\n{\n  RINOK(ClearRestriction())\n  \n  const UInt64 cdOffset = GetCurPos();\n  FOR_VECTOR (i, items)\n    WriteCentralHeader(items[i]);\n  const UInt64 cd64EndOffset = GetCurPos();\n  const UInt64 cdSize = cd64EndOffset - cdOffset;\n  const bool cdOffset64 = DOES_NEED_ZIP64(cdOffset);\n  const bool cdSize64 = DOES_NEED_ZIP64(cdSize);\n  const bool need_Items_64 = items.Size() >= 0xFFFF;\n  const unsigned items16 = (UInt16)(need_Items_64 ? 0xFFFF: items.Size());\n  const bool isZip64 = (cdOffset64 || cdSize64 || need_Items_64);\n  \n  // isZip64 = true; // to test Zip64\n\n  if (isZip64)\n  {\n    Write32(NSignature::kEcd64);\n    Write64(kEcd64_MainSize);\n    \n    // to test extra block:\n    // const UInt32 extraSize = 1 << 26;\n    // Write64(kEcd64_MainSize + extraSize);\n\n    WRITE_CONST_PAIR_16_16(45, // made by version\n        45) // extract version\n    Write32(0); // ThisDiskNumber\n    Write32(0); // StartCentralDirectoryDiskNumber\n    Write64((UInt64)items.Size());\n    Write64((UInt64)items.Size());\n    Write64((UInt64)cdSize);\n    Write64((UInt64)cdOffset);\n\n    // for (UInt32 iii = 0; iii < extraSize; iii++) Write8(1);\n\n    Write32(NSignature::kEcd64Locator);\n    Write32(0); // number of the disk with the start of the zip64 end of central directory\n    Write64(cd64EndOffset);\n    Write32(1); // total number of disks\n  }\n  \n  Write32(NSignature::kEcd);\n  WRITE_CONST_PAIR_16_16(0, 0)  // ThisDiskNumber, StartCentralDirectoryDiskNumber\n  Write16((UInt16)items16);\n  Write16((UInt16)items16);\n  \n  WRITE_32_VAL_SPEC(cdSize, cdSize64)\n  WRITE_32_VAL_SPEC(cdOffset, cdOffset64)\n\n  const UInt16 commentSize = (UInt16)(comment ? comment->Size() : 0);\n  Write16((UInt16)commentSize);\n  if (commentSize != 0)\n    WriteBytes((const Byte *)*comment, commentSize);\n  m_OutBuffer.FlushWithCheck();\n  return S_OK;\n}\n\nvoid COutArchive::CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream)\n{\n  COffsetOutStream *streamSpec = new COffsetOutStream;\n  outStream = streamSpec;\n  streamSpec->Init(m_Stream, m_Base + m_CurPos);\n}\n\nvoid COutArchive::CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream)\n{\n  outStream = m_Stream;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipOut.h",
    "content": "﻿// ZipOut.h\n\n#ifndef ZIP7_INC_ZIP_OUT_H\n#define ZIP7_INC_ZIP_OUT_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../Common/OutBuffer.h\"\n\n#include \"ZipItem.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nclass CItemOut: public CItem\n{\npublic:\n  FILETIME Ntfs_MTime;\n  FILETIME Ntfs_ATime;\n  FILETIME Ntfs_CTime;\n  bool Write_NtfsTime;\n  bool Write_UnixTime;\n\n  // It's possible that NtfsTime is not defined, but there is NtfsTime in Extra.\n  \n  CByteBuffer Name_Utf; // for Info-Zip (kIzUnicodeName) Extra\n\n  size_t Get_UtfName_ExtraSize() const\n  {\n    const size_t size = Name_Utf.Size();\n    if (size == 0)\n      return 0;\n    return 4 + 5 + size;\n  }\n\n  CItemOut():\n      Write_NtfsTime(false),\n      Write_UnixTime(false)\n      {}\n};\n\n\n// COutArchive can throw CSystemException and COutBufferException\n\nclass COutArchive\n{\n  COutBuffer m_OutBuffer;\n  CMyComPtr<IOutStream> m_Stream;\n\n  UInt64 m_Base; // Base of archive (offset in output Stream)\n  UInt64 m_CurPos; // Curent position in archive (relative from m_Base)\n  UInt64 m_LocalHeaderPos; // LocalHeaderPos (relative from m_Base) for last WriteLocalHeader() call\n\n  UInt32 m_LocalFileHeaderSize;\n  UInt32 m_ExtraSize;\n  bool m_IsZip64;\n\n  void WriteBytes(const void *data, size_t size);\n  void Write8(Byte b);\n  void Write16(UInt16 val);\n  void Write32(UInt32 val);\n  void Write64(UInt64 val);\n  void WriteNtfsTime(const FILETIME &ft)\n  {\n    Write32(ft.dwLowDateTime);\n    Write32(ft.dwHighDateTime);\n  }\n\n  void WriteTimeExtra(const CItemOut &item, bool writeNtfs);\n  void WriteUtfName(const CItemOut &item);\n  void WriteExtra(const CExtraBlock &extra);\n  void WriteCommonItemInfo(const CLocalItem &item, bool isZip64);\n  void WriteCentralHeader(const CItemOut &item);\n\n  void SeekToCurPos();\npublic:\n  CMyComPtr<IStreamSetRestriction> SetRestriction;\n\n  HRESULT ClearRestriction();\n  HRESULT SetRestrictionFromCurrent();\n  HRESULT Create(IOutStream *outStream);\n  \n  UInt64 GetCurPos() const { return m_CurPos; }\n\n  void MoveCurPos(UInt64 distanceToMove)\n  {\n    m_CurPos += distanceToMove;\n  }\n\n  void WriteLocalHeader(CItemOut &item, bool needCheck = false);\n  void WriteLocalHeader_Replace(CItemOut &item);\n\n  void WriteDescriptor(const CItemOut &item);\n\n  HRESULT WriteCentralDir(const CObjectVector<CItemOut> &items, const CByteBuffer *comment);\n\n  void CreateStreamForCompressing(CMyComPtr<IOutStream> &outStream);\n  void CreateStreamForCopying(CMyComPtr<ISequentialOutStream> &outStream);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipRegister.cpp",
    "content": "﻿// ZipRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/RegisterArc.h\"\n\n#include \"ZipHandler.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\nstatic const Byte k_Signature[] = {\n    4, 0x50, 0x4B, 0x03, 0x04,               // Local\n    4, 0x50, 0x4B, 0x05, 0x06,               // Ecd\n    4, 0x50, 0x4B, 0x06, 0x06,               // Ecd64\n    6, 0x50, 0x4B, 0x07, 0x08, 0x50, 0x4B,   // Span / Descriptor\n    6, 0x50, 0x4B, 0x30, 0x30, 0x50, 0x4B }; // NoSpan\n\nREGISTER_ARC_IO(\n  \"zip\", \"zip z01 zipx jar xpi odt ods docx xlsx epub ipa apk appx\", NULL, 1,\n  k_Signature,\n  0,\n    NArcInfoFlags::kFindSignature\n  | NArcInfoFlags::kMultiSignature\n  | NArcInfoFlags::kUseGlobalOffset\n  | NArcInfoFlags::kCTime\n  // | NArcInfoFlags::kCTime_Default\n  | NArcInfoFlags::kATime\n  // | NArcInfoFlags::kATime_Default\n  | NArcInfoFlags::kMTime\n  | NArcInfoFlags::kMTime_Default\n  , TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kWindows)\n  | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kUnix)\n  | TIME_PREC_TO_ARC_FLAGS_MASK (NFileTimeType::kDOS)\n  | TIME_PREC_TO_ARC_FLAGS_TIME_DEFAULT (NFileTimeType::kWindows)\n  , IsArc_Zip)\n \n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipUpdate.cpp",
    "content": "﻿// ZipUpdate.cpp\n\n#include \"StdAfx.h\"\n\n// #define DEBUG_CACHE\n\n#ifdef DEBUG_CACHE\n#include <stdio.h>\n  #define PRF(x) x\n#else\n  #define PRF(x)\n#endif\n\n#include \"../../../../C/Alloc.h\"\n\n#include \"../../../Common/AutoPtr.h\"\n#include \"../../../Common/Defs.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/TimeUtils.h\"\n#include \"../../../Windows/Thread.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/OutMemStream.h\"\n#include \"../../Common/ProgressUtils.h\"\n#ifndef Z7_ST\n#include \"../../Common/ProgressMt.h\"\n#endif\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n// #include \"../../Compress/ZstdEncoderProps.h\"\n\n#include \"ZipAddCommon.h\"\n#include \"ZipOut.h\"\n#include \"ZipUpdate.h\"\n\nusing namespace NWindows;\nusing namespace NSynchronization;\n\nnamespace NArchive {\nnamespace NZip {\n\nstatic const Byte kHostOS =\n  #ifdef _WIN32\n  NFileHeader::NHostOS::kFAT;\n  #else\n  NFileHeader::NHostOS::kUnix;\n  #endif\n\nstatic const Byte kMadeByHostOS = kHostOS;\n\n// 18.06: now we always write zero to high byte of ExtractVersion field.\n// Previous versions of p7zip wrote (NFileHeader::NHostOS::kUnix) there, that is not correct\nstatic const Byte kExtractHostOS = 0;\n\nstatic const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStore;\n\n\nstatic void AddAesExtra(CItem &item, Byte aesKeyMode, UInt16 method)\n{\n  CWzAesExtra wzAesField;\n  wzAesField.Strength = aesKeyMode;\n  wzAesField.Method = method;\n  item.Method = NFileHeader::NCompressionMethod::kWzAES;\n  item.Crc = 0;\n  CExtraSubBlock sb;\n  wzAesField.SetSubBlock(sb);\n  item.LocalExtra.SubBlocks.Add(sb);\n  item.CentralExtra.SubBlocks.Add(sb);\n}\n\n\nstatic void Copy_From_UpdateItem_To_ItemOut(const CUpdateItem &ui, CItemOut &item)\n{\n  item.Name = ui.Name;\n  item.Name_Utf = ui.Name_Utf;\n  item.Comment = ui.Comment;\n  item.SetUtf8(ui.IsUtf8);\n  // item.SetFlag_AltStream(ui.IsAltStream);\n  // item.ExternalAttrib = ui.Attrib;\n  item.Time = ui.Time;\n  item.Ntfs_MTime = ui.Ntfs_MTime;\n  item.Ntfs_ATime = ui.Ntfs_ATime;\n  item.Ntfs_CTime = ui.Ntfs_CTime;\n\n  item.Write_UnixTime = ui.Write_UnixTime;\n  item.Write_NtfsTime = ui.Write_NtfsTime;\n}\n\nstatic void SetFileHeader(\n    const CCompressionMethodMode &options,\n    const CUpdateItem &ui,\n    bool useDescriptor,\n    CItemOut &item)\n{\n  item.Size = ui.Size;\n  const bool isDir = ui.IsDir;\n\n  item.ClearFlags();\n\n  if (ui.NewProps)\n  {\n    Copy_From_UpdateItem_To_ItemOut(ui, item);\n    // item.SetFlag_AltStream(ui.IsAltStream);\n    item.ExternalAttrib = ui.Attrib;\n  }\n  /*\n  else\n    isDir = item.IsDir();\n  */\n\n  item.MadeByVersion.HostOS = kMadeByHostOS;\n  item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;\n  \n  item.ExtractVersion.HostOS = kExtractHostOS;\n\n  item.InternalAttrib = 0; // test it\n  item.SetEncrypted(!isDir && options.Password_Defined);\n  item.SetDescriptorMode(useDescriptor);\n\n  if (isDir)\n  {\n    item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;\n    item.Method = kMethodForDirectory;\n    item.PackSize = 0;\n    item.Size = 0;\n    item.Crc = 0;\n  }\n\n  item.LocalExtra.Clear();\n  item.CentralExtra.Clear();\n\n  if (isDir)\n  {\n    item.ExtractVersion.Version = NFileHeader::NCompressionMethod::kExtractVersion_Dir;\n    item.Method = kMethodForDirectory;\n    item.PackSize = 0;\n    item.Size = 0;\n    item.Crc = 0;\n  }\n  else if (options.IsRealAesMode())\n    AddAesExtra(item, options.AesKeyMode, (Byte)(options.MethodSequence.IsEmpty() ? 8 : options.MethodSequence[0]));\n}\n\n\n// we call SetItemInfoFromCompressingResult() after SetFileHeader()\n\nstatic void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult,\n    bool isAesMode, Byte aesKeyMode, CItem &item)\n{\n  item.ExtractVersion.Version = compressingResult.ExtractVersion;\n  item.Method = compressingResult.Method;\n  if (compressingResult.Method == NFileHeader::NCompressionMethod::kLZMA && compressingResult.LzmaEos)\n    item.Flags |= NFileHeader::NFlags::kLzmaEOS;\n  item.Crc = compressingResult.CRC;\n  item.Size = compressingResult.UnpackSize;\n  item.PackSize = compressingResult.PackSize;\n\n  item.LocalExtra.Clear();\n  item.CentralExtra.Clear();\n\n  if (isAesMode)\n    AddAesExtra(item, aesKeyMode, compressingResult.Method);\n}\n\n\n#ifndef Z7_ST\n\nstruct CMtSem\n{\n  NWindows::NSynchronization::CSemaphore Semaphore;\n  NWindows::NSynchronization::CCriticalSection CS;\n  CIntVector Indexes;\n  int Head;\n\n  void ReleaseItem(unsigned index)\n  {\n    {\n      CCriticalSectionLock lock(CS);\n      Indexes[index] = Head;\n      Head = (int)index;\n    }\n    Semaphore.Release();\n  }\n\n  int GetFreeItem()\n  {\n    int i;\n    {\n      CCriticalSectionLock lock(CS);\n      i = Head;\n      Head = Indexes[(unsigned)i];\n    }\n    return i;\n  }\n};\n\nstatic THREAD_FUNC_DECL CoderThread(void *threadCoderInfo);\n\nstruct CThreadInfo\n{\n  DECL_EXTERNAL_CODECS_LOC_VARS_DECL\n\n  NWindows::CThread Thread;\n  NWindows::NSynchronization::CAutoResetEvent CompressEvent;\n  CMtSem *MtSem;\n  unsigned ThreadIndex;\n\n  bool ExitThread;\n\n  CMtCompressProgress *ProgressSpec;\n  CMyComPtr<ICompressProgressInfo> Progress;\n\n  COutMemStream *OutStreamSpec;\n  CMyComPtr<IOutStream> OutStream;\n  CMyComPtr<ISequentialInStream> InStream;\n\n  CAddCommon Coder;\n  HRESULT Result;\n  CCompressingResult CompressingResult;\n\n  bool IsFree;\n  bool InSeqMode;\n  bool OutSeqMode;\n  bool ExpectedDataSize_IsConfirmed;\n\n  UInt32 UpdateIndex;\n  UInt32 FileTime;\n  UInt64 ExpectedDataSize;\n\n  CThreadInfo():\n      MtSem(NULL),\n      ExitThread(false),\n      ProgressSpec(NULL),\n      OutStreamSpec(NULL),\n      IsFree(true),\n      InSeqMode(false),\n      OutSeqMode(false),\n      ExpectedDataSize_IsConfirmed(false),\n      FileTime(0),\n      ExpectedDataSize((UInt64)(Int64)-1)\n  {}\n\n  void SetOptions(const CCompressionMethodMode &options)\n  {\n    Coder.SetOptions(options);\n  }\n  \n  HRESULT CreateEvents()\n  {\n    const WRes wres = CompressEvent.CreateIfNotCreated_Reset();\n    return HRESULT_FROM_WIN32(wres);\n  }\n  \n  // (group < 0) means no_group.\n  HRESULT CreateThread_with_group(\n#ifdef _WIN32\n      int group\n#endif\n      )\n  {\n    // tested in win10: If thread is created by another thread,\n    // child thread probably uses same group as parent thread.\n    // So we don't need to send (group) to encoder in created thread.\n    const WRes wres =\n#ifdef _WIN32\n      group >= 0 ?\n        Thread.Create_With_Group(CoderThread, this, (unsigned)group) :\n#endif\n        Thread.Create(CoderThread, this);\n    return HRESULT_FROM_WIN32(wres);\n  }\n\n  void WaitAndCode();\n\n  void StopWait_Close()\n  {\n    ExitThread = true;\n    if (OutStreamSpec)\n      OutStreamSpec->StopWriting(E_ABORT);\n    if (CompressEvent.IsCreated())\n      CompressEvent.Set();\n    Thread.Wait_Close();\n  }\n};\n\nvoid CThreadInfo::WaitAndCode()\n{\n  for (;;)\n  {\n    CompressEvent.Lock();\n    if (ExitThread)\n      return;\n\n    Result = Coder.Compress(\n        EXTERNAL_CODECS_LOC_VARS\n        InStream, OutStream,\n        InSeqMode, OutSeqMode, FileTime, ExpectedDataSize,\n        ExpectedDataSize_IsConfirmed,\n        Progress, CompressingResult);\n    \n    if (Result == S_OK && Progress)\n      Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize);\n    \n    MtSem->ReleaseItem(ThreadIndex);\n  }\n}\n\nstatic THREAD_FUNC_DECL CoderThread(void *threadCoderInfo)\n{\n  ((CThreadInfo *)threadCoderInfo)->WaitAndCode();\n  return 0;\n}\n\nclass CThreads\n{\npublic:\n  CObjectVector<CThreadInfo> Threads;\n  ~CThreads()\n  {\n    FOR_VECTOR (i, Threads)\n      Threads[i].StopWait_Close();\n  }\n};\n\nstruct CMemBlocks2: public CMemLockBlocks\n{\n  bool Skip;\n  bool InSeqMode;\n  bool PreDescriptorMode;\n  bool Finished;\n  CCompressingResult CompressingResult;\n  \n  CMemBlocks2(): Skip(false), InSeqMode(false), PreDescriptorMode(false), Finished(false),\n    CompressingResult() {}\n};\n\nclass CMemRefs\n{\npublic:\n  CMemBlockManagerMt *Manager;\n  CObjectVector<CMemBlocks2> Refs;\n  CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {}\n  ~CMemRefs()\n  {\n    FOR_VECTOR (i, Refs)\n      Refs[i].FreeOpt(Manager);\n  }\n};\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CMtProgressMixer2\n  , ICompressProgressInfo\n)\n  UInt64 ProgressOffset;\n  UInt64 InSizes[2];\n  UInt64 OutSizes[2];\n  CMyComPtr<IProgress> Progress;\n  CMyComPtr<ICompressProgressInfo> RatioProgress;\n  bool _inSizeIsMain;\npublic:\n  NWindows::NSynchronization::CCriticalSection CriticalSection;\n  void Create(IProgress *progress, bool inSizeIsMain);\n  void SetProgressOffset(UInt64 progressOffset);\n  void SetProgressOffset_NoLock(UInt64 progressOffset);\n  HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);\n};\n\nvoid CMtProgressMixer2::Create(IProgress *progress, bool inSizeIsMain)\n{\n  Progress = progress;\n  Progress.QueryInterface(IID_ICompressProgressInfo, &RatioProgress);\n  _inSizeIsMain = inSizeIsMain;\n  ProgressOffset = InSizes[0] = InSizes[1] = OutSizes[0] = OutSizes[1] = 0;\n}\n\nvoid CMtProgressMixer2::SetProgressOffset_NoLock(UInt64 progressOffset)\n{\n  InSizes[1] = OutSizes[1] = 0;\n  ProgressOffset = progressOffset;\n}\n\nvoid CMtProgressMixer2::SetProgressOffset(UInt64 progressOffset)\n{\n  CriticalSection.Enter();\n  SetProgressOffset_NoLock(progressOffset);\n  CriticalSection.Leave();\n}\n\nHRESULT CMtProgressMixer2::SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize)\n{\n  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\n  if (index == 0 && RatioProgress)\n  {\n    RINOK(RatioProgress->SetRatioInfo(inSize, outSize))\n  }\n  if (inSize)\n    InSizes[index] = *inSize;\n  if (outSize)\n    OutSizes[index] = *outSize;\n  UInt64 v = ProgressOffset + (_inSizeIsMain  ?\n      (InSizes[0] + InSizes[1]) :\n      (OutSizes[0] + OutSizes[1]));\n  return Progress->SetCompleted(&v);\n}\n\nZ7_COM7F_IMF(CMtProgressMixer2::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  return SetRatioInfo(0, inSize, outSize);\n}\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CMtProgressMixer\n  , ICompressProgressInfo\n)\npublic:\n  CMtProgressMixer2 *Mixer2;\n  CMyComPtr<ICompressProgressInfo> RatioProgress;\n  void Create(IProgress *progress, bool inSizeIsMain);\n};\n\nvoid CMtProgressMixer::Create(IProgress *progress, bool inSizeIsMain)\n{\n  Mixer2 = new CMtProgressMixer2;\n  RatioProgress = Mixer2;\n  Mixer2->Create(progress, inSizeIsMain);\n}\n\nZ7_COM7F_IMF(CMtProgressMixer::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  return Mixer2->SetRatioInfo(1, inSize, outSize);\n}\n\n\n#endif\n\nstatic HRESULT UpdateItemOldData(\n    COutArchive &archive,\n    CInArchive *inArchive,\n    const CItemEx &itemEx,\n    const CUpdateItem &ui,\n    CItemOut &item,\n    /* bool izZip64, */\n    ICompressProgressInfo *progress,\n    IArchiveUpdateCallbackFile *opCallback,\n    UInt64 &complexity)\n{\n  if (opCallback)\n  {\n    RINOK(opCallback->ReportOperation(\n        NEventIndexType::kInArcIndex, (UInt32)ui.IndexInArc,\n        NUpdateNotifyOp::kReplicate))\n  }\n\n  UInt64 rangeSize;\n\n  RINOK(archive.ClearRestriction())\n\n  if (ui.NewProps)\n  {\n    if (item.HasDescriptor())\n    {\n      // we know compressed / uncompressed sizes and crc.\n      // so we remove descriptor here\n      item.Flags = (UInt16)(item.Flags & ~NFileHeader::NFlags::kDescriptorUsedMask);\n      // return E_NOTIMPL;\n    }\n    // we keep ExternalAttrib and some another properties from old archive\n    // item.ExternalAttrib = ui.Attrib;\n    // if we don't change Comment, we keep Comment from OldProperties\n    Copy_From_UpdateItem_To_ItemOut(ui, item);\n    // item.SetFlag_AltStream(ui.IsAltStream);\n\n    item.CentralExtra.RemoveUnknownSubBlocks();\n    item.LocalExtra.RemoveUnknownSubBlocks();\n\n    archive.WriteLocalHeader(item);\n    rangeSize = item.GetPackSizeWithDescriptor();\n  }\n  else\n  {\n    item.LocalHeaderPos = archive.GetCurPos();\n    rangeSize = itemEx.GetLocalFullSize();\n  }\n\n  CMyComPtr<ISequentialInStream> packStream;\n\n  RINOK(inArchive->GetItemStream(itemEx, ui.NewProps, packStream))\n  if (!packStream)\n    return E_NOTIMPL;\n\n  complexity += rangeSize;\n\n  CMyComPtr<ISequentialOutStream> outStream;\n  archive.CreateStreamForCopying(outStream);\n  HRESULT res = NCompress::CopyStream_ExactSize(packStream, outStream, rangeSize, progress);\n  archive.MoveCurPos(rangeSize);\n  return res;\n}\n\n\nstatic HRESULT WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options,\n    const CUpdateItem &ui, CItemOut &item)\n{\n  SetFileHeader(*options, ui, false, item);\n  RINOK(archive.ClearRestriction())\n  archive.WriteLocalHeader(item);\n  return S_OK;\n}\n\n\nstatic void UpdatePropsFromStream(\n    const CUpdateOptions &options,\n    CUpdateItem &item, ISequentialInStream *fileInStream,\n    IArchiveUpdateCallback *updateCallback, UInt64 &totalComplexity)\n{\n  CMyComPtr<IStreamGetProps> getProps;\n  fileInStream->QueryInterface(IID_IStreamGetProps, (void **)&getProps);\n  UInt64 size = (UInt64)(Int64)-1;\n  bool size_WasSet = false;\n  \n  if (getProps)\n  {\n    FILETIME cTime, aTime, mTime;\n    UInt32 attrib;\n    if (getProps->GetProps(&size, &cTime, &aTime, &mTime, &attrib) == S_OK)\n    {\n      if (options.Write_MTime)\n        if (!FILETIME_IsZero(mTime))\n        {\n          item.Ntfs_MTime = mTime;\n          NTime::UtcFileTime_To_LocalDosTime(mTime, item.Time);\n        }\n        \n      if (options.Write_CTime) if (!FILETIME_IsZero(cTime)) item.Ntfs_CTime = cTime;\n      if (options.Write_ATime) if (!FILETIME_IsZero(aTime)) item.Ntfs_ATime = aTime;\n        \n      item.Attrib = attrib;\n      size_WasSet = true;\n    }\n  }\n\n  if (!size_WasSet)\n  {\n    CMyComPtr<IStreamGetSize> streamGetSize;\n    fileInStream->QueryInterface(IID_IStreamGetSize, (void **)&streamGetSize);\n    if (streamGetSize)\n    {\n      if (streamGetSize->GetSize(&size) == S_OK)\n        size_WasSet = true;\n    }\n  }\n\n  if (size_WasSet && size != (UInt64)(Int64)-1)\n  {\n    item.Size_WasSetFromStream = true;\n    if (size != item.Size)\n    {\n      const Int64 newComplexity = (Int64)totalComplexity + ((Int64)size - (Int64)item.Size);\n      if (newComplexity > 0)\n      {\n        totalComplexity = (UInt64)newComplexity;\n        updateCallback->SetTotal(totalComplexity);\n      }\n      item.Size = size;\n    }\n  }\n}\n\n\n/*\nstatic HRESULT ReportProps(\n    IArchiveUpdateCallbackArcProp *reportArcProp,\n    UInt32 index,\n    const CItemOut &item,\n    bool isAesMode)\n{\n  PROPVARIANT prop;\n  prop.vt = VT_EMPTY;\n  prop.wReserved1 = 0;\n  \n  NCOM::PropVarEm_Set_UInt64(&prop, item.Size);\n  RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidSize, &prop));\n  \n  NCOM::PropVarEm_Set_UInt64(&prop, item.PackSize);\n  RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidPackSize, &prop));\n\n  if (!isAesMode)\n  {\n    NCOM::PropVarEm_Set_UInt32(&prop, item.Crc);\n    RINOK(reportArcProp->ReportProp(NEventIndexType::kOutArcIndex, index, kpidCRC, &prop));\n  }\n\n  RINOK(reportArcProp->ReportFinished(NEventIndexType::kOutArcIndex, index, NUpdate::NOperationResult::kOK));\n\n  // if (opCallback) RINOK(opCallback->ReportOperation(NEventIndexType::kOutArcIndex, index, NUpdateNotifyOp::kOpFinished))\n\n  return S_OK;\n}\n*/\n\n/*\nstruct CTotalStats\n{\n  UInt64 Size;\n  UInt64 PackSize;\n\n  void UpdateWithItem(const CItemOut &item)\n  {\n    Size += item.Size;\n    PackSize += item.PackSize;\n  }\n};\n\nstatic HRESULT ReportArcProps(IArchiveUpdateCallbackArcProp *reportArcProp,\n    CTotalStats &st)\n{\n  PROPVARIANT prop;\n  prop.vt = VT_EMPTY;\n  prop.wReserved1 = 0;\n  {\n    NWindows::NCOM::PropVarEm_Set_UInt64(&prop, st.Size);\n    RINOK(reportArcProp->ReportProp(\n      NEventIndexType::kArcProp, 0, kpidSize, &prop));\n  }\n  {\n    NWindows::NCOM::PropVarEm_Set_UInt64(&prop, st.PackSize);\n    RINOK(reportArcProp->ReportProp(\n      NEventIndexType::kArcProp, 0, kpidPackSize, &prop));\n  }\n  return S_OK;\n}\n*/\n\n\nstatic HRESULT Update2St(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    COutArchive &archive,\n    CInArchive *inArchive,\n    const CObjectVector<CItemEx> &inputItems,\n    CObjectVector<CUpdateItem> &updateItems,\n    const CUpdateOptions &updateOptions,\n    const CCompressionMethodMode *options, bool outSeqMode,\n    const CByteBuffer *comment,\n    IArchiveUpdateCallback *updateCallback,\n    UInt64 &totalComplexity,\n    IArchiveUpdateCallbackFile *opCallback\n    // , IArchiveUpdateCallbackArcProp *reportArcProp\n    )\n{\n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(updateCallback, true);\n\n  CAddCommon compressor;\n  compressor.SetOptions(*options);\n  \n  CObjectVector<CItemOut> items;\n  UInt64 unpackSizeTotal = 0, packSizeTotal = 0;\n\n  FOR_VECTOR (itemIndex, updateItems)\n  {\n    lps->InSize = unpackSizeTotal;\n    lps->OutSize = packSizeTotal;\n    RINOK(lps->SetCur())\n    CUpdateItem &ui = updateItems[itemIndex];\n    CItemEx itemEx;\n    CItemOut item;\n\n    if (!ui.NewProps || !ui.NewData)\n    {\n      // Note: for (ui.NewProps && !ui.NewData) it copies Props from old archive,\n      // But we will rewrite all important properties later. But we can keep some properties like Comment\n      itemEx = inputItems[(unsigned)ui.IndexInArc];\n      if (inArchive->Read_LocalItem_After_CdItem_Full(itemEx) != S_OK)\n        return E_NOTIMPL;\n      (CItem &)item = itemEx;\n    }\n\n    if (ui.NewData)\n    {\n      // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());\n      bool isDir = ui.IsDir;\n      if (isDir)\n      {\n        RINOK(WriteDirHeader(archive, options, ui, item))\n      }\n      else\n      {\n       CMyComPtr<ISequentialInStream> fileInStream;\n       {\n        HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);\n        if (res == S_FALSE)\n        {\n          lps->ProgressOffset += ui.Size;\n          RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))\n          continue;\n        }\n        RINOK(res)\n        if (!fileInStream)\n          return E_INVALIDARG;\n\n        bool inSeqMode = false;\n        if (!inSeqMode)\n        {\n          CMyComPtr<IInStream> inStream2;\n          fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2);\n          inSeqMode = (inStream2 == NULL);\n        }\n        // seqMode = true; // to test seqMode\n\n        UpdatePropsFromStream(updateOptions, ui, fileInStream, updateCallback, totalComplexity);\n\n        CCompressingResult compressingResult;\n        \n        RINOK(compressor.Set_Pre_CompressionResult(\n            inSeqMode, outSeqMode,\n            ui.Size,\n            compressingResult))\n\n        SetFileHeader(*options, ui, compressingResult.DescriptorMode, item);\n\n        // file Size can be 64-bit !!!\n\n        SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);\n\n        RINOK(archive.SetRestrictionFromCurrent())\n        archive.WriteLocalHeader(item);\n\n        CMyComPtr<IOutStream> outStream;\n        archive.CreateStreamForCompressing(outStream);\n        \n        RINOK(compressor.Compress(\n            EXTERNAL_CODECS_LOC_VARS\n            fileInStream, outStream,\n            inSeqMode, outSeqMode,\n            ui.Time,\n            ui.Size, ui.Size_WasSetFromStream,\n            progress, compressingResult))\n        \n        if (item.HasDescriptor() != compressingResult.DescriptorMode)\n          return E_FAIL;\n\n        SetItemInfoFromCompressingResult(compressingResult, options->IsRealAesMode(), options->AesKeyMode, item);\n\n        archive.WriteLocalHeader_Replace(item);\n       }\n       // if (reportArcProp) RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options->IsRealAesMode()))\n       RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))\n       unpackSizeTotal += item.Size;\n       packSizeTotal += item.PackSize;\n      }\n    }\n    else\n    {\n      UInt64 complexity = 0;\n      lps->SendRatio = false;\n\n      RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity))\n\n      lps->SendRatio = true;\n      lps->ProgressOffset += complexity;\n    }\n  \n    items.Add(item);\n    lps->ProgressOffset += kLocalHeaderSize;\n  }\n\n  lps->InSize = unpackSizeTotal;\n  lps->OutSize = packSizeTotal;\n  RINOK(lps->SetCur())\n\n  RINOK(archive.WriteCentralDir(items, comment))\n\n  /*\n  CTotalStats stat;\n  stat.Size = unpackSizeTotal;\n  stat.PackSize = packSizeTotal;\n  if (reportArcProp)\n    RINOK(ReportArcProps(reportArcProp, stat))\n  */\n\n  lps->ProgressOffset += kCentralHeaderSize * updateItems.Size() + 1;\n  return lps->SetCur();\n}\n\n#ifndef Z7_ST\n\n\nstatic const size_t kBlockSize = 1 << 16;\n// kMemPerThread must be >= kBlockSize\n//\nstatic const size_t kMemPerThread = (size_t)sizeof(size_t) << 23;\n// static const size_t kMemPerThread = (size_t)sizeof(size_t) << 16; // for debug\n// static const size_t kMemPerThread = (size_t)1 << 16; // for debug\n\n/*\nin:\n   nt_Zip >= 1:  the starting maximum number of ZIP threads for search\nout:\n   nt_Zip:  calculated number of ZIP threads\n   returns: calculated number of ZSTD threads\n*/\n/*\nstatic UInt32 CalcThreads_for_ZipZstd(CZstdEncProps *zstdProps,\n    UInt64 memLimit, UInt32 totalThreads,\n    UInt32 &nt_Zip)\n{\n  for (; nt_Zip > 1; nt_Zip--)\n  {\n    UInt64 mem1 = memLimit / nt_Zip;\n    if (mem1 <= kMemPerThread)\n      continue;\n    mem1 -= kMemPerThread;\n    UInt32 n_ZSTD = ZstdEncProps_GetNumThreads_for_MemUsageLimit(\n        zstdProps, mem1, totalThreads / nt_Zip);\n    // we don't allow (nbWorkers == 1) here\n    if (n_ZSTD <= 1)\n      n_ZSTD = 0;\n    zstdProps->nbWorkers = n_ZSTD;\n    mem1 = ZstdEncProps_GetMemUsage(zstdProps);\n    if ((mem1 + kMemPerThread) * nt_Zip <= memLimit)\n      return n_ZSTD;\n  }\n  return ZstdEncProps_GetNumThreads_for_MemUsageLimit(\n      zstdProps, memLimit, totalThreads);\n}\n\n\nstatic UInt32 SetZstdThreads(\n    const CCompressionMethodMode &options,\n    COneMethodInfo *oneMethodMain,\n    UInt32 numThreads,\n    UInt32 numZipThreads_limit,\n    UInt64 numFilesToCompress,\n    UInt64 numBytesToCompress)\n{\n  // **************** 7-Zip ZS Modification Start ****************\n  // NCompress::NZstd::CEncoderProps encoderProps;\n  NCompress::NZSTD::CEncoderProps encoderProps;\n  // **************** 7-Zip ZS Modification End ****************\n  RINOK(encoderProps.SetFromMethodProps(*oneMethodMain));\n  CZstdEncProps &zstdProps = encoderProps.EncProps;\n  ZstdEncProps_NormalizeFull(&zstdProps);\n  if (oneMethodMain->FindProp(NCoderPropID::kNumThreads) >= 0)\n  {\n    // threads for ZSTD are fixed\n    if (zstdProps.nbWorkers > 1)\n      numThreads /= zstdProps.nbWorkers;\n    if (numThreads > numZipThreads_limit)\n      numThreads = numZipThreads_limit;\n    if (options._memUsage_WasSet\n        && !options._numThreads_WasForced)\n    {\n      const UInt64 mem1 = ZstdEncProps_GetMemUsage(&zstdProps);\n      const UInt64 numZipThreads = options._memUsage_Compress / (mem1 + kMemPerThread);\n      if (numThreads > numZipThreads)\n        numThreads = (UInt32)numZipThreads;\n    }\n    return numThreads;\n  }\n  {\n    // threads for ZSTD are not fixed\n\n    // calculate estimated required number of ZST threads per file size statistics\n    UInt32 t = MY_ZSTDMT_NBWORKERS_MAX;\n    {\n      UInt64 averageNumberOfBlocks = 0;\n      const UInt64 averageSize = numBytesToCompress / numFilesToCompress;\n      const UInt64 jobSize = zstdProps.jobSize;\n      if (jobSize != 0)\n        averageNumberOfBlocks = averageSize / jobSize + 0;\n      if (t > averageNumberOfBlocks)\n        t = (UInt32)averageNumberOfBlocks;\n    }\n    if (t > numThreads)\n      t = numThreads;\n\n    // calculate the nuber of zip threads\n    UInt32 numZipThreads = numThreads;\n    if (t > 1)\n      numZipThreads = numThreads / t;\n    if (numZipThreads > numZipThreads_limit)\n      numZipThreads = numZipThreads_limit;\n    if (numZipThreads < 1)\n      numZipThreads = 1;\n    {\n      // recalculate the number of ZSTD threads via the number of ZIP threads\n      const UInt32 t2 = numThreads / numZipThreads;\n      if (t < t2)\n        t = t2;\n    }\n    \n    if (options._memUsage_WasSet\n        && !options._numThreads_WasForced)\n    {\n      t = CalcThreads_for_ZipZstd(&zstdProps,\n          options._memUsage_Compress, numThreads, numZipThreads);\n      numThreads = numZipThreads;\n    }\n    // we don't use (nbWorkers = 1) here\n    if (t <= 1)\n      t = 0;\n    oneMethodMain->AddProp_NumThreads(t);\n    return numThreads;\n  }\n}\n*/\n\n#endif\n\n\n\n\nstatic HRESULT Update2(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    COutArchive &archive,\n    CInArchive *inArchive,\n    const CObjectVector<CItemEx> &inputItems,\n    CObjectVector<CUpdateItem> &updateItems,\n    const CUpdateOptions &updateOptions,\n    const CCompressionMethodMode &options, bool outSeqMode,\n    const CByteBuffer *comment,\n    IArchiveUpdateCallback *updateCallback)\n{\n  CMyComPtr<IArchiveUpdateCallbackFile> opCallback;\n  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackFile, (void **)&opCallback);\n\n  /*\n  CMyComPtr<IArchiveUpdateCallbackArcProp> reportArcProp;\n  updateCallback->QueryInterface(IID_IArchiveUpdateCallbackArcProp, (void **)&reportArcProp);\n  */\n\n  bool unknownComplexity = false;\n  UInt64 complexity = 0;\n #ifndef Z7_ST\n  UInt64 numFilesToCompress = 0;\n  UInt64 numBytesToCompress = 0;\n #endif\n \n  unsigned i;\n  \n  for (i = 0; i < updateItems.Size(); i++)\n  {\n    const CUpdateItem &ui = updateItems[i];\n    if (ui.NewData)\n    {\n      if (ui.Size == (UInt64)(Int64)-1)\n        unknownComplexity = true;\n      else\n        complexity += ui.Size;\n     #ifndef Z7_ST\n      numBytesToCompress += ui.Size;\n      numFilesToCompress++;\n     #endif\n      /*\n      if (ui.Commented)\n        complexity += ui.CommentRange.Size;\n      */\n    }\n    else\n    {\n      CItemEx inputItem = inputItems[(unsigned)ui.IndexInArc];\n      if (inArchive->Read_LocalItem_After_CdItem_Full(inputItem) != S_OK)\n        return E_NOTIMPL;\n      complexity += inputItem.GetLocalFullSize();\n      // complexity += inputItem.GetCentralExtraPlusCommentSize();\n    }\n    complexity += kLocalHeaderSize;\n    complexity += kCentralHeaderSize;\n  }\n\n  if (comment)\n    complexity += comment->Size();\n  complexity++; // end of central\n  \n  if (!unknownComplexity)\n    updateCallback->SetTotal(complexity);\n\n  UInt64 totalComplexity = complexity;\n\n  CCompressionMethodMode options2 = options;\n\n  if (options2._methods.IsEmpty())\n  {\n    // we need method item, if default method was used\n    options2._methods.AddNew();\n  }\n\n  CAddCommon compressor;\n  compressor.SetOptions(options2);\n  \n  complexity = 0;\n  \n  const Byte method = options.MethodSequence.FrontItem();\n\n  COneMethodInfo *oneMethodMain = NULL;\n  if (!options2._methods.IsEmpty())\n    oneMethodMain = &options2._methods[0];\n\n  {\n    FOR_VECTOR (mi, options2._methods)\n    {\n      options2.SetGlobalLevelTo(options2._methods[mi]);\n    }\n  }\n\n  if (oneMethodMain)\n  {\n    // appnote recommends to use EOS marker for LZMA.\n    if (method == NFileHeader::NCompressionMethod::kLZMA)\n      oneMethodMain->AddProp_EndMarker_if_NotFound(true);\n  }\n\n\n  #ifndef Z7_ST\n\n  UInt32 numThreads = options._numThreads;\n#ifdef _WIN32\n  const UInt32 numThreadGroups = options._numThreadGroups;\n#endif\n\n  UInt32 numZipThreads_limit = numThreads;\n  if (numZipThreads_limit > numFilesToCompress)\n    numZipThreads_limit = (UInt32)numFilesToCompress;\n\n  if (numZipThreads_limit > 1)\n  {\n    const unsigned numFiles_OPEN_MAX = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks();\n    // printf(\"\\nzip:numFiles_OPEN_MAX =%d\\n\", (unsigned)numFiles_OPEN_MAX);\n    if (numZipThreads_limit > numFiles_OPEN_MAX)\n      numZipThreads_limit = (UInt32)numFiles_OPEN_MAX;\n  }\n\n  {\n    // we reduce number of threads for 32-bit to reduce memory usege to 256 MB\n    const UInt32 kNumMaxThreads =\n        // _WIN32 (64-bit) supports only 64 threads in one group.\n        8 << (sizeof(size_t) / 2); // 32 threads for 32-bit : 128 threads for 64-bit\n    if (numThreads > kNumMaxThreads)\n      numThreads = kNumMaxThreads;\n  }\n  /*\n  if (numThreads > MAXIMUM_WAIT_OBJECTS) // is 64 in Windows\n    numThreads = MAXIMUM_WAIT_OBJECTS;\n  */\n\n\n  /*\n  // zstd supports (numThreads == 0);\n  if (numThreads < 1)\n    numThreads = 1;\n  */\n\n  bool mtMode = (numThreads > 1);\n\n  if (numFilesToCompress <= 1)\n    mtMode = false;\n\n  // mtMode = true; // debug: to test mtMode\n\n  if (!mtMode)\n  {\n    // if (oneMethodMain) {\n    /*\n    // **************** 7-Zip ZS Modification Start ****************\n    // if (method == NFileHeader::NCompressionMethod::kZstdWz)\n    if (method == NFileHeader::NCompressionMethod::kZstd)\n    {\n      if (oneMethodMain->FindProp(NCoderPropID::kNumThreads) < 0)\n      {\n        // numZstdThreads was not forced in oneMethodMain\n        if (numThreads >= 1\n            && options._memUsage_WasSet\n            && !options._numThreads_WasForced)\n        {\n          // **************** 7-Zip ZS Modification Start ****************\n          // NCompress::NZstd::CEncoderProps encoderProps;\n          NCompress::NZSTD::CEncoderProps encoderProps;\n          // **************** 7-Zip ZS Modification End ****************\n          RINOK(encoderProps.SetFromMethodProps(*oneMethodMain))\n          CZstdEncProps &zstdProps = encoderProps.EncProps;\n          ZstdEncProps_NormalizeFull(&zstdProps);\n          numThreads = ZstdEncProps_GetNumThreads_for_MemUsageLimit(\n              &zstdProps, options._memUsage_Compress, numThreads);\n          // we allow (nbWorkers = 1) here.\n        }\n        oneMethodMain->AddProp_NumThreads(numThreads);\n      }\n    // **************** 7-Zip ZS Modification Start ****************\n    // } // kZstdWz\n    } // kZstd\n    // **************** 7-Zip ZS Modification End ****************\n    */\n    // } // oneMethodMain\n\n    FOR_VECTOR (mi, options2._methods)\n    {\n      COneMethodInfo &onem = options2._methods[mi];\n\n      if (onem.FindProp(NCoderPropID::kNumThreads) < 0)\n      {\n        // fixme: we should check the number of threads for xz method also\n        // fixed for 9.31. bzip2 default is just one thread.\n        onem.AddProp_NumThreads(numThreads);\n      }\n    }\n  }\n  else // mtMode\n  {\n    if (method == NFileHeader::NCompressionMethod::kStore && !options.Password_Defined)\n      numThreads = 1;\n    \n   if (oneMethodMain)\n   {\n\n    if (method == NFileHeader::NCompressionMethod::kBZip2)\n    {\n      bool fixedNumber;\n      UInt32 numBZip2Threads = oneMethodMain->Get_BZip2_NumThreads(fixedNumber);\n      if (!fixedNumber)\n      {\n        const UInt64 averageSize = numBytesToCompress / numFilesToCompress;\n        const UInt32 blockSize = oneMethodMain->Get_BZip2_BlockSize();\n        const UInt64 averageNumberOfBlocks = averageSize / blockSize + 1;\n        numBZip2Threads = 64;\n        if (numBZip2Threads > averageNumberOfBlocks)\n          numBZip2Threads = (UInt32)averageNumberOfBlocks;\n        if (numBZip2Threads > numThreads)\n          numBZip2Threads = numThreads;\n        oneMethodMain->AddProp_NumThreads(numBZip2Threads);\n      }\n      numThreads /= numBZip2Threads;\n    }\n    else if (method == NFileHeader::NCompressionMethod::kXz)\n    {\n      UInt32 numLzmaThreads = 1;\n      int numXzThreads = oneMethodMain->Get_Xz_NumThreads(numLzmaThreads);\n      if (numXzThreads < 0)\n      {\n        // numXzThreads is unknown\n        const UInt64 averageSize = numBytesToCompress / numFilesToCompress;\n        const UInt64 blockSize = oneMethodMain->Get_Xz_BlockSize();\n        UInt64 averageNumberOfBlocks = 1;\n        if (blockSize != (UInt64)(Int64)-1)\n          averageNumberOfBlocks = averageSize / blockSize + 1;\n        UInt32 t = 256;\n        if (t > averageNumberOfBlocks)\n          t = (UInt32)averageNumberOfBlocks;\n        t *= numLzmaThreads;\n        if (t > numThreads)\n          t = numThreads;\n        oneMethodMain->AddProp_NumThreads(t);\n        numXzThreads = (int)t;\n      }\n      numThreads /= (unsigned)numXzThreads;\n    }\n    /*\n    // **************** 7-Zip ZS Modification Start ****************\n    // else if (method == NFileHeader::NCompressionMethod::kZstdWz)\n    else if (method == NFileHeader::NCompressionMethod::kZstd)\n    // **************** 7-Zip ZS Modification End ****************\n    {\n      numThreads = SetZstdThreads(options,\n          oneMethodMain, numThreads,\n          numZipThreads_limit,\n          numFilesToCompress, numBytesToCompress);\n    }\n    */\n    else if (\n           method == NFileHeader::NCompressionMethod::kDeflate\n        || method == NFileHeader::NCompressionMethod::kDeflate64\n        || method == NFileHeader::NCompressionMethod::kPPMd)\n    {\n      if (numThreads > 1\n          && options._memUsage_WasSet\n          && !options._numThreads_WasForced)\n      {\n        UInt64 methodMemUsage;\n        if (method == NFileHeader::NCompressionMethod::kPPMd)\n          methodMemUsage = oneMethodMain->Get_Ppmd_MemSize();\n        else\n          methodMemUsage = (4 << 20); // for deflate\n        const UInt64 threadMemUsage = kMemPerThread + methodMemUsage;\n        const UInt64 numThreads64 = options._memUsage_Compress / threadMemUsage;\n        if (numThreads64 < numThreads)\n          numThreads = (UInt32)numThreads64;\n      }\n    }\n    else if (method == NFileHeader::NCompressionMethod::kLZMA)\n    {\n      // we suppose that default LZMA is 2 thread. So we don't change it\n      const UInt32 numLZMAThreads = oneMethodMain->Get_Lzma_NumThreads();\n      numThreads /= numLZMAThreads;\n\n      if (numThreads > 1\n          && options._memUsage_WasSet\n          && !options._numThreads_WasForced)\n      {\n        const UInt64 methodMemUsage = oneMethodMain->Get_Lzma_MemUsage(true);\n        const UInt64 threadMemUsage = kMemPerThread + methodMemUsage;\n        const UInt64 numThreads64 = options._memUsage_Compress / threadMemUsage;\n        if (numThreads64 < numThreads)\n          numThreads = (UInt32)numThreads64;\n      }\n    }\n   } // (oneMethodMain)\n\n    if (numThreads > numZipThreads_limit)\n      numThreads = numZipThreads_limit;\n    if (numThreads <= 1)\n    {\n      mtMode = false;\n      numThreads = 1;\n    }\n  }\n\n  // mtMode = true; // to test mtMode for seqMode\n\n  if (!mtMode)\n  #endif\n    return Update2St(\n        EXTERNAL_CODECS_LOC_VARS\n        archive, inArchive,\n        inputItems, updateItems,\n        updateOptions,\n        &options2, outSeqMode,\n        comment, updateCallback, totalComplexity,\n        opCallback\n        // , reportArcProp\n        );\n\n\n  #ifndef Z7_ST\n\n  /*\n  CTotalStats stat;\n  stat.Size = 0;\n  stat.PackSize = 0;\n  */\n  if (numThreads < 1)\n    numThreads = 1;\n\n  CObjectVector<CItemOut> items;\n\n  CMtProgressMixer *mtProgressMixerSpec = new CMtProgressMixer;\n  CMyComPtr<ICompressProgressInfo> progress = mtProgressMixerSpec;\n  mtProgressMixerSpec->Create(updateCallback, true);\n\n  CMtCompressProgressMixer mtCompressProgressMixer;\n  mtCompressProgressMixer.Init(numThreads, mtProgressMixerSpec->RatioProgress);\n\n  CMemBlockManagerMt memManager(kBlockSize);\n  CMemRefs refs(&memManager);\n\n  CMtSem mtSem;\n  CThreads threads;\n  mtSem.Head = -1;\n  mtSem.Indexes.ClearAndSetSize(numThreads);\n  {\n    WRes wres = mtSem.Semaphore.Create(0, numThreads);\n    if (wres != 0)\n      return HRESULT_FROM_WIN32(wres);\n  }\n\n  CUIntVector threadIndices;  // list threads in order of updateItems\n\n  {\n    RINOK(memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize)))\n    for (i = 0; i < updateItems.Size(); i++)\n      refs.Refs.Add(CMemBlocks2());\n\n    for (i = 0; i < numThreads; i++)\n    {\n      threads.Threads.AddNew();\n      // mtSem.Indexes[i] = -1; // actually we don't use these values\n    }\n\n    for (i = 0; i < numThreads; i++)\n    {\n      CThreadInfo &threadInfo = threads.Threads[i];\n      threadInfo.ThreadIndex = i;\n      threadInfo.SetOptions(options2);\n      #ifdef Z7_EXTERNAL_CODECS\n      threadInfo._externalCodecs = _externalCodecs;\n      #endif\n      RINOK(threadInfo.CreateEvents())\n      threadInfo.OutStreamSpec = new COutMemStream(&memManager);\n      RINOK(threadInfo.OutStreamSpec->CreateEvents(SYNC_WFMO(&memManager.Synchro)))\n      threadInfo.OutStream = threadInfo.OutStreamSpec;\n      threadInfo.ProgressSpec = new CMtCompressProgress();\n      threadInfo.Progress = threadInfo.ProgressSpec;\n      threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, i);\n      threadInfo.MtSem = &mtSem;\n      const HRESULT hres =\n        threadInfo.CreateThread_with_group(\n#ifdef _WIN32\n          (numThreadGroups > 1 && numThreads > 1) ?\n            (int)(i % numThreadGroups) : -1\n#endif\n        );\n      RINOK(hres)\n    }\n  }\n\n  unsigned mtItemIndex = 0;\n  unsigned itemIndex = 0;\n  int lastRealStreamItemIndex = -1;\n\n  \n  while (itemIndex < updateItems.Size())\n  {\n    if (threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size())\n    {\n      // we start ahead the threads for compressing\n      // also we set refs.Refs[itemIndex].SeqMode that is used later\n      // don't move that code block\n      \n      CUpdateItem &ui = updateItems[mtItemIndex++];\n      if (!ui.NewData)\n        continue;\n      CItemEx itemEx;\n      CItemOut item;\n      \n      if (ui.NewProps)\n      {\n        if (ui.IsDir)\n          continue;\n      }\n      else\n      {\n        itemEx = inputItems[(unsigned)ui.IndexInArc];\n        if (inArchive->Read_LocalItem_After_CdItem_Full(itemEx) != S_OK)\n          return E_NOTIMPL;\n        (CItem &)item = itemEx;\n        if (item.IsDir() != ui.IsDir)\n          return E_NOTIMPL;\n        if (ui.IsDir)\n          continue;\n      }\n      \n      CMyComPtr<ISequentialInStream> fileInStream;\n      \n      CMemBlocks2 &memRef2 = refs.Refs[mtItemIndex - 1];\n\n      {\n        NWindows::NSynchronization::CCriticalSectionLock lock(mtProgressMixerSpec->Mixer2->CriticalSection);\n        const HRESULT res = updateCallback->GetStream(ui.IndexInClient, &fileInStream);\n        if (res == S_FALSE)\n        {\n          complexity += ui.Size;\n          complexity += kLocalHeaderSize;\n          mtProgressMixerSpec->Mixer2->SetProgressOffset_NoLock(complexity);\n          RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))\n          memRef2.Skip = true;\n          continue;\n        }\n        RINOK(res)\n        if (!fileInStream)\n          return E_INVALIDARG;\n        UpdatePropsFromStream(updateOptions, ui, fileInStream, updateCallback, totalComplexity);\n        RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK))\n      }\n\n      UInt32 k;\n      for (k = 0; k < numThreads; k++)\n        if (threads.Threads[k].IsFree)\n          break;\n\n      if (k == numThreads)\n        return E_FAIL;\n      {\n        {\n          CThreadInfo &threadInfo = threads.Threads[k];\n          threadInfo.IsFree = false;\n          threadInfo.InStream = fileInStream;\n\n          bool inSeqMode = false;\n\n          if (!inSeqMode)\n          {\n            CMyComPtr<IInStream> inStream2;\n            fileInStream->QueryInterface(IID_IInStream, (void **)&inStream2);\n            inSeqMode = (inStream2 == NULL);\n          }\n          memRef2.InSeqMode = inSeqMode;\n\n          // !!!!! we must release ref before sending event\n          // BUG was here in v4.43 and v4.44. It could change ref counter in two threads in same time\n          fileInStream.Release();\n\n          threadInfo.OutStreamSpec->Init();\n          threadInfo.ProgressSpec->Reinit();\n          \n          threadInfo.UpdateIndex = mtItemIndex - 1;\n          threadInfo.InSeqMode = inSeqMode;\n          threadInfo.OutSeqMode = outSeqMode;\n          threadInfo.FileTime = ui.Time; // FileTime is used for ZipCrypto only in seqMode\n          threadInfo.ExpectedDataSize = ui.Size;\n          threadInfo.ExpectedDataSize_IsConfirmed = ui.Size_WasSetFromStream;\n\n          threadInfo.CompressEvent.Set();\n          \n          threadIndices.Add(k);\n        }\n      }\n \n      continue;\n    }\n    \n    if (refs.Refs[itemIndex].Skip)\n    {\n      itemIndex++;\n      continue;\n    }\n\n    const CUpdateItem &ui = updateItems[itemIndex];\n\n    CItemEx itemEx;\n    CItemOut item;\n    \n    if (!ui.NewProps || !ui.NewData)\n    {\n      itemEx = inputItems[(unsigned)ui.IndexInArc];\n      if (inArchive->Read_LocalItem_After_CdItem_Full(itemEx) != S_OK)\n        return E_NOTIMPL;\n      (CItem &)item = itemEx;\n    }\n\n    if (ui.NewData)\n    {\n      // bool isDir = ((ui.NewProps) ? ui.IsDir : item.IsDir());\n      const bool isDir = ui.IsDir;\n      \n      if (isDir)\n      {\n        RINOK(WriteDirHeader(archive, &options, ui, item))\n      }\n      else\n      {\n        CMemBlocks2 &memRef = refs.Refs[itemIndex];\n        \n        if (memRef.Finished)\n        {\n          if (lastRealStreamItemIndex < (int)itemIndex)\n            lastRealStreamItemIndex = (int)itemIndex;\n\n          SetFileHeader(options, ui, memRef.CompressingResult.DescriptorMode, item);\n\n          // the BUG was fixed in 9.26:\n          // SetItemInfoFromCompressingResult must be after SetFileHeader\n          // to write correct Size.\n\n          SetItemInfoFromCompressingResult(memRef.CompressingResult,\n              options.IsRealAesMode(), options.AesKeyMode, item);\n          RINOK(archive.ClearRestriction())\n          archive.WriteLocalHeader(item);\n          // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));\n          CMyComPtr<ISequentialOutStream> outStream;\n          archive.CreateStreamForCopying(outStream);\n          memRef.WriteToStream(memManager.GetBlockSize(), outStream);\n          // v23: we fixed the bug: we need to write descriptor also\n          if (item.HasDescriptor())\n          {\n            /* that function doesn't rewrite local header, if item.HasDescriptor().\n               it just writes descriptor */\n            archive.WriteLocalHeader_Replace(item);\n          }\n          else\n            archive.MoveCurPos(item.PackSize);\n          memRef.FreeOpt(&memManager);\n          /*\n          if (reportArcProp)\n          {\n            stat.UpdateWithItem(item);\n            RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options.IsRealAesMode()));\n          }\n          */\n        }\n        else\n        {\n          // current file was not finished\n\n          if (lastRealStreamItemIndex < (int)itemIndex)\n          {\n            // LocalHeader was not written for current itemIndex still\n\n            lastRealStreamItemIndex = (int)itemIndex;\n\n            // thread was started before for that item already, and memRef.SeqMode was set\n\n            CCompressingResult compressingResult;\n            RINOK(compressor.Set_Pre_CompressionResult(\n                memRef.InSeqMode, outSeqMode,\n                ui.Size,\n                compressingResult))\n\n            memRef.PreDescriptorMode = compressingResult.DescriptorMode;\n            SetFileHeader(options, ui, compressingResult.DescriptorMode, item);\n\n            SetItemInfoFromCompressingResult(compressingResult, options.IsRealAesMode(), options.AesKeyMode, item);\n\n            // file Size can be 64-bit !!!\n            RINOK(archive.SetRestrictionFromCurrent())\n            archive.WriteLocalHeader(item);\n          }\n\n          {\n            CThreadInfo &thread = threads.Threads[threadIndices.FrontItem()];\n            if (!thread.OutStreamSpec->WasUnlockEventSent())\n            {\n              CMyComPtr<IOutStream> outStream;\n              archive.CreateStreamForCompressing(outStream);\n              thread.OutStreamSpec->SetOutStream(outStream);\n              thread.OutStreamSpec->SetRealStreamMode();\n            }\n          }\n\n          const WRes wres = mtSem.Semaphore.Lock();\n          if (wres != 0)\n            return HRESULT_FROM_WIN32(wres);\n\n          const int ti = mtSem.GetFreeItem();\n          if (ti < 0)\n            return E_FAIL;\n\n          CThreadInfo &threadInfo = threads.Threads[(unsigned)ti];\n          threadInfo.InStream.Release();\n          threadInfo.IsFree = true;\n          RINOK(threadInfo.Result)\n\n          unsigned t = 0;\n\n          for (;;)\n          {\n            if (t == threadIndices.Size())\n              return E_FAIL;\n            if (threadIndices[t] == (unsigned)ti)\n              break;\n            t++;\n          }\n          threadIndices.Delete(t);\n          \n          if (t == 0)\n          {\n            // if thread for current file was finished.\n            if (threadInfo.UpdateIndex != itemIndex)\n              return E_FAIL;\n\n            if (memRef.PreDescriptorMode != threadInfo.CompressingResult.DescriptorMode)\n              return E_FAIL;\n\n            RINOK(threadInfo.OutStreamSpec->WriteToRealStream())\n            threadInfo.OutStreamSpec->ReleaseOutStream();\n            SetFileHeader(options, ui, threadInfo.CompressingResult.DescriptorMode, item);\n            SetItemInfoFromCompressingResult(threadInfo.CompressingResult,\n                options.IsRealAesMode(), options.AesKeyMode, item);\n\n            archive.WriteLocalHeader_Replace(item);\n\n            /*\n            if (reportArcProp)\n            {\n              stat.UpdateWithItem(item);\n              RINOK(ReportProps(reportArcProp, ui.IndexInClient, item, options.IsRealAesMode()));\n            }\n            */\n          }\n          else\n          {\n            // it's not current file. So we must store information in array\n            CMemBlocks2 &memRef2 = refs.Refs[threadInfo.UpdateIndex];\n            threadInfo.OutStreamSpec->DetachData(memRef2);\n            memRef2.CompressingResult = threadInfo.CompressingResult;\n            // memRef2.SeqMode = threadInfo.SeqMode; // it was set before\n            memRef2.Finished = true;\n            continue;\n          }\n        }\n      }\n    }\n    else\n    {\n      RINOK(UpdateItemOldData(archive, inArchive, itemEx, ui, item, progress, opCallback, complexity))\n    }\n \n    items.Add(item);\n    complexity += kLocalHeaderSize;\n    mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);\n    itemIndex++;\n  }\n  \n  RINOK(mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL))\n\n  RINOK(archive.WriteCentralDir(items, comment))\n\n  /*\n  if (reportArcProp)\n  {\n    RINOK(ReportArcProps(reportArcProp, stat));\n  }\n  */\n\n  complexity += kCentralHeaderSize * updateItems.Size() + 1;\n  mtProgressMixerSpec->Mixer2->SetProgressOffset(complexity);\n  return mtCompressProgressMixer.SetRatioInfo(0, NULL, NULL);\n\n  #endif\n}\n\n/*\n// we need CSeekOutStream, if we need Seek(0, STREAM_SEEK_CUR) for seqential stream\nZ7_CLASS_IMP_COM_1(\n  CSeekOutStream\n  , IOutStream\n)\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\n\n  CMyComPtr<ISequentialOutStream> _seqStream;\n  UInt64 _size;\npublic:\n  void Init(ISequentialOutStream *seqStream)\n  {\n    _size = 0;\n    _seqStream = seqStream;\n  }\n};\n\nZ7_COM7F_IMF(CSeekOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize;\n  const HRESULT result = _seqStream->Write(data, size, &realProcessedSize);\n  _size += realProcessedSize;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return result;\n}\n\nZ7_COM7F_IMF(CSeekOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  if (seekOrigin != STREAM_SEEK_CUR || offset != 0)\n    return E_NOTIMPL;\n  if (newPosition)\n    *newPosition = (UInt64)_size;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CSeekOutStream::SetSize(UInt64 newSize))\n{\n  UNUSED_VAR(newSize)\n  return E_NOTIMPL;\n}\n*/\n\nstatic const size_t kCacheBlockSize = 1 << 20;\nstatic const size_t kCacheSize = kCacheBlockSize << 2;\nstatic const size_t kCacheMask = kCacheSize - 1;\n\nZ7_CLASS_IMP_NOQIB_2(\n  CCacheOutStream\n  , IOutStream\n  , IStreamSetRestriction\n)\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\n\n  HRESULT _hres;\n  CMyComPtr<ISequentialOutStream> _seqStream;\n  CMyComPtr<IOutStream> _stream;\n  CMyComPtr<IStreamSetRestriction> _setRestriction;\n  Byte *_cache;\n  size_t _cachedSize;\n  UInt64 _cachedPos;\n  UInt64 _virtPos;\n  UInt64 _virtSize;\n  UInt64 _phyPos;\n  UInt64 _phySize;\n  UInt64 _restrict_begin;\n  UInt64 _restrict_end;\n\n  HRESULT FlushFromCache(size_t size);\n  HRESULT FlushNonRestrictedBlocks();\n  HRESULT FlushCache();\n  HRESULT SetRestriction_ForWrite(size_t writeSize) const;\n\n  HRESULT SeekPhy(UInt64 pos)\n  {\n    if (pos == _phyPos)\n      return S_OK;\n    if (!_stream)\n      return E_NOTIMPL;\n    _hres = _stream->Seek((Int64)pos, STREAM_SEEK_SET, &_phyPos);\n    if (_hres == S_OK && _phyPos != pos)\n      _hres = E_FAIL;\n    return _hres;\n  }\n\npublic:\n  CCacheOutStream(): _cache(NULL) {}\n  ~CCacheOutStream();\n  bool Allocate()\n  {\n    if (!_cache)\n      _cache = (Byte *)::MidAlloc(kCacheSize);\n    return _cache != NULL;\n  }\n  HRESULT Init(ISequentialOutStream *seqStream, IOutStream *stream, IStreamSetRestriction *setRestriction);\n  HRESULT FinalFlush();\n};\n\nCCacheOutStream::~CCacheOutStream()\n{\n  ::MidFree(_cache);\n}\n\n\nHRESULT CCacheOutStream::Init(ISequentialOutStream *seqStream, IOutStream *stream, IStreamSetRestriction *setRestriction)\n{\n  _hres = S_OK;\n  _cachedSize = 0;\n  _cachedPos = 0;\n  _virtPos = 0;\n  _virtSize = 0;\n  // by default we have no restriction\n  _restrict_begin = 0;\n  _restrict_end = 0;\n  _seqStream = seqStream;\n  _stream = stream;\n  _setRestriction = setRestriction;\n  if (_stream)\n  {\n    RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &_virtPos))\n    RINOK(_stream->Seek(0, STREAM_SEEK_END, &_virtSize))\n    RINOK(_stream->Seek((Int64)_virtPos, STREAM_SEEK_SET, &_virtPos))\n  }\n  _phyPos = _virtPos;\n  _phySize = _virtSize;\n  return S_OK;\n}\n\n\n/* we call SetRestriction_ForWrite() just before Write() from cache.\n   (_phyPos == _cachedPos)\n   (writeSize != 0)\n*/\nHRESULT CCacheOutStream::SetRestriction_ForWrite(size_t writeSize) const\n{\n  if (!_setRestriction)\n    return S_OK;\n  PRF(printf(\"\\n-- CCacheOutStream::SetRestriction_ForWrite _cachedPos = 0x%x, writeSize = %d\\n\", (unsigned)_cachedPos, (unsigned)writeSize));\n  UInt64 begin = _restrict_begin;\n  UInt64 end = _restrict_end;\n  const UInt64 phyPos = _phyPos;\n  if (phyPos != _cachedPos) return E_FAIL;\n  if (phyPos == _phySize)\n  {\n    // The writing will be to the end of phy stream.\n    // So we will try to use non-restricted write, if possible.\n    if (begin == end)\n      begin = _virtPos; // _virtSize; // it's supposed that (_virtSize == _virtPos)\n    if (phyPos + writeSize <= begin)\n    {\n      // the write is not restricted\n      PRF(printf(\"\\n+++ write is not restricted \\n\"));\n      begin = 0;\n      end = 0;\n    }\n    else\n    {\n      if (begin > phyPos)\n        begin = phyPos;\n      end = (UInt64)(Int64)-1;\n    }\n  }\n  else\n  {\n    // (phyPos != _phySize)\n    if (begin == end || begin > phyPos)\n      begin = phyPos;\n    end = (UInt64)(Int64)-1;\n  }\n  return _setRestriction->SetRestriction(begin, end);\n}\n\n\n/* it writes up to (size) bytes from cache.\n   (size > _cachedSize) is allowed\n*/\nHRESULT CCacheOutStream::FlushFromCache(size_t size)\n{\n  PRF(printf(\"\\n-- CCacheOutStream::FlushFromCache %u\\n\", (unsigned)size));\n  if (_hres != S_OK)\n    return _hres;\n  if (size > _cachedSize)\n      size = _cachedSize;\n  // (size <= _cachedSize)\n  if (size == 0)\n    return S_OK;\n  RINOK(SeekPhy(_cachedPos))\n  for (;;)\n  {\n    // (_phyPos == _cachedPos)\n    const size_t pos = (size_t)_cachedPos & kCacheMask;\n    const size_t cur = MyMin(kCacheSize - pos, size);\n    _hres = SetRestriction_ForWrite(cur);\n    RINOK(_hres)\n    PRF(printf(\"\\n-- CCacheOutStream::WriteFromCache _phyPos = 0x%x, size = %d\\n\", (unsigned)_phyPos, (unsigned)cur));\n    _hres = WriteStream(_seqStream, _cache + pos, cur);\n    RINOK(_hres)\n    _phyPos += cur;\n    if (_phySize < _phyPos)\n      _phySize = _phyPos;\n    _cachedPos += cur;\n    _cachedSize -= cur;\n    size -= cur;\n    if (size == 0)\n      return S_OK;\n  }\n}\n\n\nHRESULT CCacheOutStream::FlushNonRestrictedBlocks()\n{\n  for (;;)\n  {\n    const size_t size = kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1));\n    if (_cachedSize < size)\n      break;\n    UInt64 begin = _restrict_begin;\n    if (begin == _restrict_end)\n      begin = _virtPos;\n    // we don't flush the data to restricted area\n    if (_cachedPos + size > begin)\n      break;\n    RINOK(FlushFromCache(size))\n  }\n  return S_OK;\n}\n\n\nHRESULT CCacheOutStream::FlushCache()\n{\n  return FlushFromCache(_cachedSize);\n}\n\nHRESULT CCacheOutStream::FinalFlush()\n{\n  _restrict_begin = 0;\n  _restrict_end = 0;\n  RINOK(FlushCache())\n  if (_stream && _hres == S_OK)\n  {\n    if (_virtSize != _phySize)\n    {\n      // it's unexpected\n      RINOK(_stream->SetSize(_virtSize))\n      _phySize = _virtSize;\n    }\n    _hres = SeekPhy(_virtPos);\n  }\n  return _hres;\n}\n\n\nZ7_COM7F_IMF(CCacheOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  PRF(printf(\"\\n==== CCacheOutStream::Write virtPos=0x%x, %u\\n\", (unsigned)_virtPos, (unsigned)size));\n\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (_hres != S_OK)\n    return _hres;\n\n  if (_cachedSize != 0)\n  if (_virtPos < _cachedPos ||\n      _virtPos > _cachedPos + _cachedSize)\n  {\n    RINOK(FlushCache())\n  }\n\n  if (_cachedSize == 0)\n    _cachedPos = _virtPos;\n\n  const size_t pos = (size_t)_virtPos & kCacheMask;\n  {\n    const size_t blockRem = kCacheBlockSize - ((size_t)_virtPos & (kCacheBlockSize - 1));\n    if (size > blockRem)\n      size = (UInt32)blockRem;\n  }\n  // _cachedPos <= _virtPos <= _cachedPos + _cachedSize\n  const UInt64 cachedRem = _cachedPos + _cachedSize - _virtPos;\n  if (cachedRem)\n  {\n    // _virtPos < _cachedPos + _cachedSize\n    // we rewrite only existing data in cache. So _cachedSize will be not changed\n    if (size > cachedRem)\n      size = (UInt32)cachedRem;\n  }\n  else\n  {\n    // _virtPos == _cachedPos + _cachedSize\n    // so we need to add new data to the end of cache\n    if (_cachedSize == kCacheSize)\n    {\n      // cache is full. So we need to flush some part of cache.\n      // we flush only one block, but we are allowed to flush any size here\n      RINOK(FlushFromCache(kCacheBlockSize - ((size_t)_cachedPos & (kCacheBlockSize - 1))))\n    }\n    // _cachedSize != kCacheSize\n    // so we have some space for new data in cache\n    if (_cachedSize == 0)\n    {\n      /* this code is optional (for optimization):\n         we write data directly without cache,\n         if there is no restriction and we have full block. */\n      if (_restrict_begin == _restrict_end\n          && size == kCacheBlockSize)\n      {\n        RINOK(SeekPhy(_virtPos))\n        if (_setRestriction)\n        {\n          _hres = _setRestriction->SetRestriction(_restrict_begin, _restrict_end);\n          RINOK(_hres)\n        }\n        PRF(printf(\"\\n-- CCacheOutStream::WriteDirectly _phyPos = 0x%x, size = %d\\n\", (unsigned)_phyPos, (unsigned)size));\n        _hres = WriteStream(_seqStream, data, size);\n        RINOK(_hres)\n        if (processedSize)\n          *processedSize = size;\n        _virtPos += size;\n        if (_virtSize < _virtPos)\n          _virtSize = _virtPos;\n        _phyPos += size;\n        if (_phySize < _phyPos)\n          _phySize = _phyPos;\n        return S_OK;\n      }\n    }\n    else // (_cachedSize != 0)\n    {\n      const size_t startPos = (size_t)_cachedPos & kCacheMask;\n      // we don't allow new data to overwrite old start data in cache.\n      // (startPos == pos) here means that cache is empty.\n      // (startPos == pos) is not possible here.\n      if (startPos > pos)\n        size = (UInt32)MyMin((size_t)size, (size_t)(startPos - pos));\n    }\n    // _virtPos == (_cachedPos + _cachedSize) still\n    _cachedSize += size;\n  }\n  \n  memcpy(_cache + pos, data, size);\n  if (processedSize)\n    *processedSize = size;\n  _virtPos += size;\n  if (_virtSize < _virtPos)\n    _virtSize = _virtPos;\n  return FlushNonRestrictedBlocks();\n}\n\n\nZ7_COM7F_IMF(CCacheOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  PRF(printf(\"\\n==== CCacheOutStream::Seek seekOrigin=%d Seek =%u\\n\", seekOrigin, (unsigned)offset));\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += _virtSize; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCacheOutStream::SetSize(UInt64 newSize))\n{\n  if (_hres != S_OK)\n    return _hres;\n\n  if (newSize <= _cachedPos || _cachedSize == 0)\n  {\n    _cachedSize = 0;\n    _cachedPos = newSize;\n  }\n  else\n  {\n    // _cachedSize != 0\n    // newSize > _cachedPos\n    const UInt64 offset = newSize - _cachedPos;\n    if (offset <= _cachedSize)\n    {\n      // newSize is inside cached block or is touching cached block.\n      // so we reduce cache\n      _cachedSize = (size_t)offset;\n      if (_phySize <= newSize)\n      {\n        // _phySize will be restored later after cache flush\n        _virtSize = newSize;\n        return S_OK;\n      }\n      // (_phySize > newSize)\n      // so we must reduce phyStream size to (newSize) or to (_cachedPos)\n      // newPhySize = _cachedPos; // optional reduce to _cachedPos\n    }\n    else\n    {\n      // newSize > _cachedPos + _cachedSize\n      /* It's possible that we need to write zeros,\n         if new size is larger than old size.\n         We don't optimize for possible cases here.\n         So we just flush the cache. */\n      _hres = FlushCache();\n    }\n  }\n\n  _virtSize = newSize;\n\n  if (_hres != S_OK)\n    return _hres;\n\n  if (newSize != _phySize)\n  {\n    if (!_stream)\n      return E_NOTIMPL;\n    // if (_phyPos > newSize)\n    RINOK(SeekPhy(newSize))\n    if (_setRestriction)\n    {\n      UInt64 begin = _restrict_begin;\n      UInt64 end = _restrict_end;\n      if (_cachedSize != 0)\n      {\n        if (begin > _cachedPos)\n          begin = _cachedPos;\n        end = (UInt64)(Int64)-1;\n      }\n      _hres = _setRestriction->SetRestriction(begin, end);\n      RINOK(_hres)\n    }\n    _hres = _stream->SetSize(newSize);\n    RINOK(_hres)\n    _phySize = newSize;\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCacheOutStream::SetRestriction(UInt64 begin, UInt64 end))\n{\n  PRF(printf(\"\\n============ CCacheOutStream::SetRestriction 0x%x, %u\\n\", (unsigned)begin, (unsigned)end));\n  _restrict_begin = begin;\n  _restrict_end = end;\n  return FlushNonRestrictedBlocks();\n}\n\n\n\nHRESULT Update(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const CObjectVector<CItemEx> &inputItems,\n    CObjectVector<CUpdateItem> &updateItems,\n    ISequentialOutStream *seqOutStream,\n    CInArchive *inArchive, bool removeSfx,\n    const CUpdateOptions &updateOptions,\n    const CCompressionMethodMode &compressionMethodMode,\n    IArchiveUpdateCallback *updateCallback)\n{\n  /*\n  // it was tested before\n  if (inArchive)\n  {\n    if (!inArchive->CanUpdate())\n      return E_NOTIMPL;\n  }\n  */\n\n  CMyComPtr<IStreamSetRestriction> setRestriction;\n  seqOutStream->QueryInterface(IID_IStreamSetRestriction, (void **)&setRestriction);\n  if (setRestriction)\n  {\n    RINOK(setRestriction->SetRestriction(0, 0))\n  }\n\n  CMyComPtr<IOutStream> outStream;\n  CCacheOutStream *cacheStream;\n  bool outSeqMode;\n\n  {\n    CMyComPtr<IOutStream> outStreamReal;\n\n    if (!compressionMethodMode.Force_SeqOutMode)\n    {\n      seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStreamReal);\n      /*\n      if (!outStreamReal)\n        return E_NOTIMPL;\n      */\n    }\n\n    if (inArchive)\n    {\n      if (!inArchive->IsMultiVol && inArchive->ArcInfo.Base > 0 && !removeSfx)\n      {\n        IInStream *baseStream = inArchive->GetBaseStream();\n        RINOK(InStream_SeekToBegin(baseStream))\n        RINOK(NCompress::CopyStream_ExactSize(baseStream, seqOutStream, (UInt64)inArchive->ArcInfo.Base, NULL))\n      }\n    }\n\n    outSeqMode = (outStreamReal == NULL);\n    if (outSeqMode)\n      setRestriction.Release();\n    /* CCacheOutStream works as non-restricted by default.\n       So we use (setRestriction == NULL) for outSeqMode */\n    // bool use_cacheStream = true;\n    // if (use_cacheStream)\n    {\n      cacheStream = new CCacheOutStream();\n      outStream = cacheStream;\n      if (!cacheStream->Allocate())\n        return E_OUTOFMEMORY;\n      RINOK(cacheStream->Init(seqOutStream, outStreamReal, setRestriction))\n      setRestriction.Release();\n      if (!outSeqMode)\n        setRestriction = cacheStream;\n    }\n    /*\n    else if (!outStreamReal)\n    {\n      CSeekOutStream *seekOutStream = new CSeekOutStream();\n      outStream = seekOutStream;\n      seekOutStream->Init(seqOutStream);\n    }\n    else\n      outStream = outStreamReal;\n    */\n  }\n\n  COutArchive outArchive;\n  outArchive.SetRestriction = setRestriction;\n\n  RINOK(outArchive.Create(outStream))\n\n  if (inArchive)\n  {\n    if (!inArchive->IsMultiVol && (Int64)inArchive->ArcInfo.MarkerPos2 > inArchive->ArcInfo.Base)\n    {\n      IInStream *baseStream = inArchive->GetBaseStream();\n      RINOK(InStream_SeekSet(baseStream, (UInt64)inArchive->ArcInfo.Base))\n      const UInt64 embStubSize = (UInt64)((Int64)inArchive->ArcInfo.MarkerPos2 - inArchive->ArcInfo.Base);\n      RINOK(NCompress::CopyStream_ExactSize(baseStream, outStream, embStubSize, NULL))\n      outArchive.MoveCurPos(embStubSize);\n    }\n  }\n\n  RINOK (Update2(\n      EXTERNAL_CODECS_LOC_VARS\n      outArchive, inArchive,\n      inputItems, updateItems,\n      updateOptions,\n      compressionMethodMode, outSeqMode,\n      inArchive ? &inArchive->ArcInfo.Comment : NULL,\n      updateCallback))\n\n  return cacheStream->FinalFlush();\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Archive/Zip/ZipUpdate.h",
    "content": "﻿// ZipUpdate.h\n\n#ifndef ZIP7_INC_ZIP_UPDATE_H\n#define ZIP7_INC_ZIP_UPDATE_H\n\n#include \"../../ICoder.h\"\n#include \"../IArchive.h\"\n\n#include \"../../Common/CreateCoder.h\"\n\n#include \"ZipCompressionMode.h\"\n#include \"ZipIn.h\"\n\nnamespace NArchive {\nnamespace NZip {\n\n/*\nstruct CUpdateRange\n{\n  UInt64 Position;\n  UInt64 Size;\n  \n  // CUpdateRange() {}\n  CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {}\n};\n*/\n\nstruct CUpdateItem\n{\n  bool NewData;\n  bool NewProps;\n  bool IsDir;\n  bool Write_NtfsTime;\n  bool Write_UnixTime;\n  // bool Write_UnixTime_ATime;\n  bool IsUtf8;\n  bool Size_WasSetFromStream;\n  // bool IsAltStream;\n  int IndexInArc;\n  unsigned IndexInClient;\n  UInt32 Attrib;\n  UInt32 Time;\n  UInt64 Size;\n  AString Name;\n  CByteBuffer Name_Utf;    // for Info-Zip (kIzUnicodeName) Extra\n  CByteBuffer Comment;\n  // bool Commented;\n  // CUpdateRange CommentRange;\n  FILETIME Ntfs_MTime;\n  FILETIME Ntfs_ATime;\n  FILETIME Ntfs_CTime;\n\n  void Clear()\n  {\n    IsDir = false;\n    \n    Write_NtfsTime = false;\n    Write_UnixTime = false;\n\n    IsUtf8 = false;\n    Size_WasSetFromStream = false;\n    // IsAltStream = false;\n    Time = 0;\n    Size = 0;\n    Name.Empty();\n    Name_Utf.Free();\n    Comment.Free();\n\n    FILETIME_Clear(Ntfs_MTime);\n    FILETIME_Clear(Ntfs_ATime);\n    FILETIME_Clear(Ntfs_CTime);\n  }\n\n  CUpdateItem():\n    IsDir(false),\n    Write_NtfsTime(false),\n    Write_UnixTime(false),\n    IsUtf8(false),\n    Size_WasSetFromStream(false),\n    // IsAltStream(false),\n    Time(0),\n    Size(0)\n    {}\n};\n\n\nstruct CUpdateOptions\n{\n  bool Write_MTime;\n  bool Write_ATime;\n  bool Write_CTime;\n};\n\n\nHRESULT Update(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const CObjectVector<CItemEx> &inputItems,\n    CObjectVector<CUpdateItem> &updateItems,\n    ISequentialOutStream *seqOutStream,\n    CInArchive *inArchive, bool removeSfx,\n    const CUpdateOptions &updateOptions,\n    const CCompressionMethodMode &compressionMethodMode,\n    IArchiveUpdateCallback *updateCallback);\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXCon/SfxCon.cpp",
    "content": "﻿// Main.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n#include \"../../../../C/DllSecur.h\"\n\n#include \"../../../Common/MyWindows.h\"\n#include \"../../../Common/MyInitGuid.h\"\n\n#include \"../../../Common/CommandLineParser.h\"\n#include \"../../../Common/MyException.h\"\n\n#ifdef _WIN32\n#include \"../../../Windows/DLL.h\"\n#else\n#include \"../../../Common/StringConvert.h\"\n#endif\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileName.h\"\n\n#include \"../../UI/Common/ExitCode.h\"\n#include \"../../UI/Common/Extract.h\"\n\n#include \"../../UI/Console/ExtractCallbackConsole.h\"\n#include \"../../UI/Console/List.h\"\n#include \"../../UI/Console/OpenCallbackConsole.h\"\n\n// **************** NanaZip Modification Start ****************\n//#include \"../../MyVersion.h\"\n#include <Mile.Project.Version.h>\n// **************** NanaZip Modification End ****************\n\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\nusing namespace NCommandLineParser;\n\n#ifdef _WIN32\nextern\nHINSTANCE g_hInstance;\nHINSTANCE g_hInstance = NULL;\n#endif\nextern\nint g_CodePage;\nint g_CodePage = -1;\nextern CStdOutStream *g_StdStream;\n\n// **************** NanaZip Modification Start ****************\n//static const char * const kCopyrightString =\n//\"\\n7-Zip SFX \" MY_VERSION_CPU \" : \" MY_COPYRIGHT_DATE \"\\n\";\nstatic const char* const kCopyrightString =\n\"\\nNanaZip SFX \" MILE_PROJECT_VERSION_UTF8_STRING \" (\" MY_CPU_NAME \")\"\n\" : \" \"(c) M2-Team and Contributors. All rights reserved.\" \"\\n\";\n// **************** NanaZip Modification End ****************\n\nstatic const int kNumSwitches = 6;\n\nnamespace NKey {\nenum Enum\n{\n  kHelp1 = 0,\n  kHelp2,\n  kDisablePercents,\n  kYes,\n  kPassword,\n  kOutputDir\n};\n\n}\n\nnamespace NRecursedType {\nenum EEnum\n{\n  kRecursed,\n  kWildcardOnlyRecursed,\n  kNonRecursed\n};\n}\n/*\nstatic const char kRecursedIDChar = 'R';\n\nnamespace NRecursedPostCharIndex {\n  enum EEnum\n  {\n    kWildcardRecursionOnly = 0,\n    kNoRecursion = 1\n  };\n}\n\nstatic const char kFileListID = '@';\nstatic const char kImmediateNameID = '!';\n\nstatic const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be\nstatic const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be\n*/\n\n#define SWFRM_3(t, mu, mi) t, mu, mi, NULL\n#define SWFRM_1(t)     SWFRM_3(t, false, 0)\n#define SWFRM_SIMPLE   SWFRM_1(NSwitchType::kSimple)\n#define SWFRM_STRING_SINGL(mi) SWFRM_3(NSwitchType::kString, false, mi)\n\nstatic const CSwitchForm kSwitchForms[kNumSwitches] =\n{\n  { \"?\",  SWFRM_SIMPLE },\n  { \"H\",  SWFRM_SIMPLE },\n  { \"BD\", SWFRM_SIMPLE },\n  { \"Y\",  SWFRM_SIMPLE },\n  { \"P\",  SWFRM_STRING_SINGL(1) },\n  { \"O\",  SWFRM_STRING_SINGL(1) },\n};\n\nstatic const int kNumCommandForms = 3;\n\nstatic const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =\n{\n  NRecursedType::kRecursed\n};\n\n// static const bool kTestExtractRecursedDefault = true;\n// static const bool kAddRecursedDefault = false;\n\nstatic const char * const kUniversalWildcard = \"*\";\n\nstatic const char * const kHelpString =\n    // **************** NanaZip Modification Start ****************\n    //\"\\nUsage: 7zSFX [<command>] [<switches>...] [<file_name>...]\\n\"\n    \"\\nUsage: NanaZip.Core.Console [<command>] [<switches>...] [<file_name>...]\\n\"\n    // **************** NanaZip Modification End ****************\n    \"\\n\"\n    \"<Commands>\\n\"\n    // \"  l: List contents of archive\\n\"\n    \"  t: Test integrity of archive\\n\"\n    \"  x: eXtract files with full pathname (default)\\n\"\n    \"<Switches>\\n\"\n    // \"  -bd Disable percentage indicator\\n\"\n    \"  -o{Directory}: set Output directory\\n\"\n    \"  -p{Password}: set Password\\n\"\n    \"  -y: assume Yes on all queries\\n\";\n\n\n// ---------------------------\n// exception messages\n\nstatic const char * const kUserErrorMessage  = \"Incorrect command line\"; // NExitCode::kUserError\n// static const char * const kIncorrectListFile = \"Incorrect wildcard in listfile\";\nstatic const char * const kIncorrectWildcardInCommandLine  = \"Incorrect wildcard in command line\";\n\n// static const CSysString kFileIsNotArchiveMessageBefore = \"File \\\"\";\n// static const CSysString kFileIsNotArchiveMessageAfter = \"\\\" is not archive\";\n\n// static const char * const kProcessArchiveMessage = \" archive: \";\n\nstatic const char * const kCantFindSFX = \" cannot find sfx\";\n\nnamespace NCommandType\n{\n  enum EEnum\n  {\n    kTest = 0,\n    kFullExtract,\n    kList\n  };\n}\n\nstatic const char * const g_Commands = \"txl\";\n\nstruct CArchiveCommand\n{\n  NCommandType::EEnum CommandType;\n\n  NRecursedType::EEnum DefaultRecursedType() const;\n};\n\nstatic bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)\n{\n  UString s = commandString;\n  s.MakeLower_Ascii();\n  if (s.Len() != 1)\n    return false;\n  if (s[0] >= 0x80)\n    return false;\n  int index = FindCharPosInString(g_Commands, (char)s[0]);\n  if (index < 0)\n    return false;\n  command.CommandType = (NCommandType::EEnum)index;\n  return true;\n}\n\nNRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const\n{\n  return kCommandRecursedDefault[CommandType];\n}\n\nstatic void PrintHelp(void)\n{\n  g_StdOut << kHelpString;\n}\n\nZ7_ATTR_NORETURN\nstatic void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code)\n{\n  g_StdOut << message << endl;\n  throw code;\n}\n\nZ7_ATTR_NORETURN\nstatic void PrintHelpAndExit() // yyy\n{\n  PrintHelp();\n  ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);\n}\n\n// ------------------------------------------------------------------\n// filenames functions\n\nstatic bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,\n    const UString &name, bool include, NRecursedType::EEnum type)\n{\n  /*\n  if (!IsWildcardFilePathLegal(name))\n    return false;\n  */\n  const bool isWildcard = DoesNameContainWildcard(name);\n  bool recursed = false;\n\n  switch (type)\n  {\n    case NRecursedType::kWildcardOnlyRecursed:\n      recursed = isWildcard;\n      break;\n    case NRecursedType::kRecursed:\n      recursed = true;\n      break;\n    case NRecursedType::kNonRecursed:\n      recursed = false;\n      break;\n  }\n\n  NWildcard::CCensorPathProps props;\n  props.Recursive = recursed;\n  wildcardCensor.AddPreItem(include, name, props);\n  return true;\n}\n\nstatic void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor,\n    const UString &name, bool include, NRecursedType::EEnum type)\n{\n  if (!AddNameToCensor(wildcardCensor, name, include, type))\n    ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError);\n}\n\n\n#ifndef _WIN32\nstatic void GetArguments(int numArgs, char *args[], UStringVector &parts)\n{\n  parts.Clear();\n  for (int i = 0; i < numArgs; i++)\n  {\n    UString s = MultiByteToUnicodeString(args[i]);\n    parts.Add(s);\n  }\n}\n#endif\n\n\nint Main2(\n  #ifndef _WIN32\n  int numArgs, char *args[]\n  #endif\n);\nint Main2(\n  #ifndef _WIN32\n  int numArgs, char *args[]\n  #endif\n)\n{\n  #ifdef _WIN32\n  // do we need load Security DLLs for console program?\n  LoadSecurityDlls();\n  #endif\n\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  SetFileApisToOEM();\n  #endif\n  \n  #ifdef ENV_HAVE_LOCALE\n  MY_SetLocale();\n  #endif\n\n  g_StdOut << kCopyrightString;\n\n  UStringVector commandStrings;\n  #ifdef _WIN32\n  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);\n  #else\n  GetArguments(numArgs, args, commandStrings);\n  #endif\n\n  #ifdef _WIN32\n  \n  FString arcPath;\n  {\n    FString path;\n    NDLL::MyGetModuleFileName(path);\n    if (!MyGetFullPathName(path, arcPath))\n    {\n      g_StdOut << \"GetFullPathName Error\";\n      return NExitCode::kFatalError;\n    }\n  }\n\n  #else\n\n  if (commandStrings.IsEmpty())\n    return NExitCode::kFatalError;\n\n  const FString arcPath = us2fs(commandStrings.Front());\n\n  #endif\n\n  #ifndef UNDER_CE\n  if (commandStrings.Size() > 0)\n    commandStrings.Delete(0);\n  #endif\n\n  NCommandLineParser::CParser parser;\n  \n  try\n  {\n    if (!parser.ParseStrings(kSwitchForms, kNumSwitches, commandStrings))\n    {\n      g_StdOut << \"Command line error:\" << endl\n          << parser.ErrorMessage << endl\n          << parser.ErrorLine << endl;\n      return NExitCode::kUserError;\n    }\n  }\n  catch(...)\n  {\n    PrintHelpAndExit();\n  }\n\n  if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)\n  {\n    PrintHelp();\n    return 0;\n  }\n  \n  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;\n\n  unsigned curCommandIndex = 0;\n\n  CArchiveCommand command;\n  if (nonSwitchStrings.IsEmpty())\n    command.CommandType = NCommandType::kFullExtract;\n  else\n  {\n    const UString &cmd = nonSwitchStrings[curCommandIndex];\n    if (!ParseArchiveCommand(cmd, command))\n    {\n      g_StdOut << \"ERROR: Unknown command:\" << endl << cmd << endl;\n      return NExitCode::kUserError;\n    }\n    curCommandIndex = 1;\n  }\n\n\n  NRecursedType::EEnum recursedType;\n  recursedType = command.DefaultRecursedType();\n\n  NWildcard::CCensor wildcardCensor;\n  \n  {\n    if (nonSwitchStrings.Size() == curCommandIndex)\n      AddCommandLineWildcardToCensor(wildcardCensor, (UString)kUniversalWildcard, true, recursedType);\n    for (; curCommandIndex < nonSwitchStrings.Size(); curCommandIndex++)\n    {\n      const UString &s = nonSwitchStrings[curCommandIndex];\n      if (s.IsEmpty())\n        throw \"Empty file path\";\n      AddCommandLineWildcardToCensor(wildcardCensor, s, true, recursedType);\n    }\n  }\n\n  const bool yesToAll = parser[NKey::kYes].ThereIs;\n\n  // NExtractMode::EEnum extractMode;\n  // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode);\n\n  const bool passwordEnabled = parser[NKey::kPassword].ThereIs;\n\n  UString password;\n  if (passwordEnabled)\n    password = parser[NKey::kPassword].PostStrings[0];\n\n  if (!NFind::DoesFileExist_FollowLink(arcPath))\n    throw kCantFindSFX;\n  \n  FString outputDir;\n  if (parser[NKey::kOutputDir].ThereIs)\n  {\n    outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);\n    NName::NormalizeDirPathPrefix(outputDir);\n  }\n\n\n  wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath);\n  \n  {\n    UStringVector v1, v2;\n    v1.Add(fs2us(arcPath));\n    v2.Add(fs2us(arcPath));\n    const NWildcard::CCensorNode &wildcardCensorHead =\n      wildcardCensor.Pairs.Front().Head;\n\n    CCodecs *codecs = new CCodecs;\n    CMyComPtr<\n      #ifdef Z7_EXTERNAL_CODECS\n      ICompressCodecsInfo\n      #else\n      IUnknown\n      #endif\n      > compressCodecsInfo = codecs;\n    {\n      HRESULT result = codecs->Load();\n      if (result != S_OK)\n        throw CSystemException(result);\n    }\n\n    if (command.CommandType != NCommandType::kList)\n    {\n      CExtractCallbackConsole *ecs = new CExtractCallbackConsole;\n      CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;\n      ecs->Init(g_StdStream, &g_StdErr, g_StdStream, false);\n\n      #ifndef Z7_NO_CRYPTO\n      ecs->PasswordIsDefined = passwordEnabled;\n      ecs->Password = password;\n      #endif\n\n      /*\n      COpenCallbackConsole openCallback;\n      openCallback.Init(g_StdStream, g_StdStream);\n\n      #ifndef Z7_NO_CRYPTO\n      openCallback.PasswordIsDefined = passwordEnabled;\n      openCallback.Password = password;\n      #endif\n      */\n\n      CExtractOptions eo;\n      eo.StdOutMode = false;\n      eo.YesToAll = yesToAll;\n      eo.TestMode = command.CommandType == NCommandType::kTest;\n      eo.PathMode = NExtract::NPathMode::kFullPaths;\n      eo.OverwriteMode = yesToAll ?\n          NExtract::NOverwriteMode::kOverwrite :\n          NExtract::NOverwriteMode::kAsk;\n      eo.OutputDir = outputDir;\n\n      UString errorMessage;\n      CDecompressStat stat;\n      HRESULT result = Extract(\n          codecs, CObjectVector<COpenType>(), CIntVector(),\n          v1, v2,\n          wildcardCensorHead,\n          eo,\n          ecs, ecs, ecs,\n          // NULL, // hash\n          errorMessage, stat);\n\n      ecs->ClosePercents();\n\n      if (!errorMessage.IsEmpty())\n      {\n        (*g_StdStream) << endl << \"Error: \" << errorMessage;\n        if (result == S_OK)\n          result = E_FAIL;\n      }\n\n      if (   0 != ecs->NumCantOpenArcs\n          || 0 != ecs->NumArcsWithError\n          || 0 != ecs->NumFileErrors\n          || 0 != ecs->NumOpenArcErrors)\n      {\n        if (ecs->NumCantOpenArcs != 0)\n          (*g_StdStream) << endl << \"Can't open as archive\" << endl;\n        if (ecs->NumArcsWithError != 0)\n          (*g_StdStream) << endl << \"Archive Errors\" << endl;\n        if (ecs->NumFileErrors != 0)\n          (*g_StdStream) << endl << \"Sub items Errors: \" << ecs->NumFileErrors << endl;\n        if (ecs->NumOpenArcErrors != 0)\n          (*g_StdStream) << endl << \"Open Errors: \" << ecs->NumOpenArcErrors << endl;\n        return NExitCode::kFatalError;\n      }\n      if (result != S_OK)\n        throw CSystemException(result);\n    }\n    else\n    {\n      throw CSystemException(E_NOTIMPL);\n\n      /*\n      UInt64 numErrors = 0;\n      UInt64 numWarnings = 0;\n      HRESULT result = ListArchives(\n          codecs, CObjectVector<COpenType>(), CIntVector(),\n          false, // stdInMode\n          v1, v2,\n          true, // processAltStreams\n          false, // showAltStreams\n          wildcardCensorHead,\n          true, // enableHeaders\n          false, // techMode\n          #ifndef Z7_NO_CRYPTO\n          passwordEnabled, password,\n          #endif\n          numErrors, numWarnings);\n      if (numErrors > 0)\n      {\n        g_StdOut << endl << \"Errors: \" << numErrors;\n        return NExitCode::kFatalError;\n      }\n      if (result != S_OK)\n        throw CSystemException(result);\n      */\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXCon/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.cpp",
    "content": "﻿// ExtractCallbackSfx.h\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"ExtractCallbackSfx.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\nstatic LPCSTR const kCantDeleteFile = \"Cannot delete output file\";\nstatic LPCSTR const kCantOpenFile = \"Cannot open output file\";\nstatic LPCSTR const kUnsupportedMethod = \"Unsupported Method\";\n\nvoid CExtractCallbackImp::Init(IInArchive *archiveHandler,\n    const FString &directoryPath,\n    const UString &itemDefaultName,\n    const FILETIME &defaultMTime,\n    UInt32 defaultAttributes)\n{\n  _message.Empty();\n  _isCorrupt = false;\n  _itemDefaultName = itemDefaultName;\n  _defaultMTime = defaultMTime;\n  _defaultAttributes = defaultAttributes;\n  _archiveHandler = archiveHandler;\n  _directoryPath = directoryPath;\n  NName::NormalizeDirPathPrefix(_directoryPath);\n}\n\nHRESULT CExtractCallbackImp::Open_CheckBreak()\n{\n  #ifndef _NO_PROGRESS\n  return ProgressDialog.Sync.ProcessStopAndPause();\n  #else\n  return S_OK;\n  #endif\n}\n\nHRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\n{\n  return S_OK;\n}\n\nHRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 * /* numFiles */, const UInt64 * /* numBytes */)\n{\n  #ifndef _NO_PROGRESS\n  return ProgressDialog.Sync.ProcessStopAndPause();\n  #else\n  return S_OK;\n  #endif\n}\n\nHRESULT CExtractCallbackImp::Open_Finished()\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetTotal(UInt64 size))\n{\n  #ifndef _NO_PROGRESS\n  ProgressDialog.Sync.SetProgress(size, 0);\n  #endif\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetCompleted(const UInt64 *completeValue))\n{\n  #ifndef _NO_PROGRESS\n  RINOK(ProgressDialog.Sync.ProcessStopAndPause())\n  if (completeValue != NULL)\n    ProgressDialog.Sync.SetPos(*completeValue);\n  #endif\n  return S_OK;\n}\n\nvoid CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)\n{\n  FString fullPath = _directoryPath;\n  FOR_VECTOR (i, dirPathParts)\n  {\n    fullPath += us2fs(dirPathParts[i]);\n    CreateDir(fullPath);\n    fullPath.Add_PathSepar();\n  }\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::GetStream(UInt32 index,\n    ISequentialOutStream **outStream, Int32 askExtractMode))\n{\n  #ifndef _NO_PROGRESS\n  if (ProgressDialog.Sync.GetStopped())\n    return E_ABORT;\n  #endif\n  _outFileStream.Release();\n\n  UString fullPath;\n  {\n    NCOM::CPropVariant prop;\n    RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop))\n    if (prop.vt == VT_EMPTY)\n      fullPath = _itemDefaultName;\n    else\n    {\n      if (prop.vt != VT_BSTR)\n        return E_FAIL;\n      fullPath.SetFromBstr(prop.bstrVal);\n    }\n    _filePath = fullPath;\n  }\n\n  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract)\n  {\n    NCOM::CPropVariant prop;\n    RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop))\n    if (prop.vt == VT_EMPTY)\n      _processedFileInfo.Attributes = _defaultAttributes;\n    else\n    {\n      if (prop.vt != VT_UI4)\n        return E_FAIL;\n      _processedFileInfo.Attributes = prop.ulVal;\n    }\n\n    RINOK(_archiveHandler->GetProperty(index, kpidIsDir, &prop))\n    _processedFileInfo.IsDir = VARIANT_BOOLToBool(prop.boolVal);\n\n    bool isAnti = false;\n    {\n      NCOM::CPropVariant propTemp;\n      RINOK(_archiveHandler->GetProperty(index, kpidIsAnti, &propTemp))\n      if (propTemp.vt == VT_BOOL)\n        isAnti = VARIANT_BOOLToBool(propTemp.boolVal);\n    }\n\n    RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop))\n    switch (prop.vt)\n    {\n      case VT_EMPTY: _processedFileInfo.MTime = _defaultMTime; break;\n      case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; break;\n      default: return E_FAIL;\n    }\n\n    UStringVector pathParts;\n    SplitPathToParts(fullPath, pathParts);\n    if (pathParts.IsEmpty())\n      return E_FAIL;\n\n    UString processedPath = fullPath;\n\n    if (!_processedFileInfo.IsDir)\n      pathParts.DeleteBack();\n    if (!pathParts.IsEmpty())\n    {\n      if (!isAnti)\n        CreateComplexDirectory(pathParts);\n    }\n\n    FString fullProcessedPath = _directoryPath + us2fs(processedPath);\n\n    if (_processedFileInfo.IsDir)\n    {\n      _diskFilePath = fullProcessedPath;\n\n      if (isAnti)\n        RemoveDir(_diskFilePath);\n      else\n        SetDirTime(_diskFilePath, NULL, NULL, &_processedFileInfo.MTime);\n      return S_OK;\n    }\n\n    NFind::CFileInfo fileInfo;\n    if (fileInfo.Find(fullProcessedPath))\n    {\n      if (!DeleteFileAlways(fullProcessedPath))\n      {\n        _message = kCantDeleteFile;\n        return E_FAIL;\n      }\n    }\n\n    if (!isAnti)\n    {\n      _outFileStreamSpec = new COutFileStream;\n      CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);\n      if (!_outFileStreamSpec->Create_ALWAYS(fullProcessedPath))\n      {\n        _message = kCantOpenFile;\n        return E_FAIL;\n      }\n      _outFileStream = outStreamLoc;\n      *outStream = outStreamLoc.Detach();\n    }\n    _diskFilePath = fullProcessedPath;\n  }\n  else\n  {\n    *outStream = NULL;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::PrepareOperation(Int32 askExtractMode))\n{\n  _extractMode = (askExtractMode == NArchive::NExtract::NAskMode::kExtract);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetOperationResult(Int32 resultEOperationResult))\n{\n  switch (resultEOperationResult)\n  {\n    case NArchive::NExtract::NOperationResult::kOK:\n      break;\n\n    default:\n    {\n      _outFileStream.Release();\n      switch (resultEOperationResult)\n      {\n        case NArchive::NExtract::NOperationResult::kUnsupportedMethod:\n          _message = kUnsupportedMethod;\n          break;\n        default:\n          _isCorrupt = true;\n      }\n      return E_FAIL;\n    }\n  }\n  if (_outFileStream != NULL)\n  {\n    _outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);\n    RINOK(_outFileStreamSpec->Close())\n  }\n  _outFileStream.Release();\n  if (_extractMode)\n    SetFileAttrib(_diskFilePath, _processedFileInfo.Attributes);\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXSetup/ExtractCallbackSfx.h",
    "content": "﻿// ExtractCallbackSfx.h\n\n#ifndef ZIP7_INC_EXTRACT_CALLBACK_SFX_H\n#define ZIP7_INC_EXTRACT_CALLBACK_SFX_H\n\n#include \"resource.h\"\n\n#include \"../../../Windows/ResourceString.h\"\n\n#include \"../../Archive/IArchive.h\"\n\n#include \"../../Common/FileStreams.h\"\n#include \"../../ICoder.h\"\n\n#include \"../../UI/FileManager/LangUtils.h\"\n\n#ifndef _NO_PROGRESS\n#include \"../../UI/FileManager/ProgressDialog.h\"\n#endif\n#include \"../../UI/Common/ArchiveOpenCallback.h\"\n\nclass CExtractCallbackImp Z7_final:\n  public IArchiveExtractCallback,\n  public IOpenCallbackUI,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_0\n  Z7_IFACE_COM7_IMP(IProgress)\n  Z7_IFACE_COM7_IMP(IArchiveExtractCallback)\n  Z7_IFACE_IMP(IOpenCallbackUI)\n\n  CMyComPtr<IInArchive> _archiveHandler;\n  FString _directoryPath;\n  UString _filePath;\n  FString _diskFilePath;\n\n  bool _extractMode;\n  struct CProcessedFileInfo\n  {\n    FILETIME MTime;\n    bool IsDir;\n    UInt32 Attributes;\n  } _processedFileInfo;\n\n  COutFileStream *_outFileStreamSpec;\n  CMyComPtr<ISequentialOutStream> _outFileStream;\n\n  UString _itemDefaultName;\n  FILETIME _defaultMTime;\n  UInt32 _defaultAttributes;\n\n  void CreateComplexDirectory(const UStringVector &dirPathParts);\npublic:\n  #ifndef _NO_PROGRESS\n  CProgressDialog ProgressDialog;\n  #endif\n\n  bool _isCorrupt;\n  UString _message;\n\n  void Init(IInArchive *archiveHandler,\n    const FString &directoryPath,\n    const UString &itemDefaultName,\n    const FILETIME &defaultMTime,\n    UInt32 defaultAttributes);\n\n  #ifndef _NO_PROGRESS\n  HRESULT StartProgressDialog(const UString &title, NWindows::CThread &thread)\n  {\n    ProgressDialog.Create(title, thread, NULL);\n    {\n      ProgressDialog.SetText(LangString(IDS_PROGRESS_EXTRACTING));\n    }\n\n    ProgressDialog.Show(SW_SHOWNORMAL);\n    return S_OK;\n  }\n  ~CExtractCallbackImp() { ProgressDialog.Destroy(); }\n  #endif\n\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXSetup/ExtractEngine.cpp",
    "content": "﻿// ExtractEngine.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/Thread.h\"\n\n#include \"../../UI/Common/OpenArchive.h\"\n\n#include \"../../UI/FileManager/FormatUtils.h\"\n#include \"../../UI/FileManager/LangUtils.h\"\n\n#include \"ExtractCallbackSfx.h\"\n#include \"ExtractEngine.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\nstatic LPCSTR const kCantFindArchive = \"Cannot find archive file\";\nstatic LPCSTR const kCantOpenArchive = \"Cannot open the file as archive\";\n\nstruct CThreadExtracting\n{\n  CCodecs *Codecs;\n  FString FileName;\n  FString DestFolder;\n\n  CExtractCallbackImp *ExtractCallbackSpec;\n  CMyComPtr<IArchiveExtractCallback> ExtractCallback;\n\n  CArchiveLink ArchiveLink;\n  HRESULT Result;\n  UString ErrorMessage;\n\n  void Process2()\n  {\n    NFind::CFileInfo fi;\n    if (!fi.Find(FileName))\n    {\n      ErrorMessage = kCantFindArchive;\n      Result = E_FAIL;\n      return;\n    }\n\n    CObjectVector<COpenType> incl;\n    CIntVector excl;\n    COpenOptions options;\n    options.codecs = Codecs;\n    options.types = &incl;\n    options.excludedFormats = &excl;\n    options.filePath = fs2us(FileName);\n    \n    Result = ArchiveLink.Open2(options, ExtractCallbackSpec);\n    if (Result != S_OK)\n    {\n      ErrorMessage = kCantOpenArchive;\n      return;\n    }\n\n    FString dirPath = DestFolder;\n    NName::NormalizeDirPathPrefix(dirPath);\n    \n    if (!CreateComplexDir(dirPath))\n    {\n      ErrorMessage = MyFormatNew(IDS_CANNOT_CREATE_FOLDER, fs2us(dirPath));\n      Result = E_FAIL;\n      return;\n    }\n\n    ExtractCallbackSpec->Init(ArchiveLink.GetArchive(), dirPath, (UString)\"Default\", fi.MTime, 0);\n\n    Result = ArchiveLink.GetArchive()->Extract(NULL, (UInt32)(Int32)-1 , BoolToInt(false), ExtractCallback);\n  }\n\n  void Process()\n  {\n    try\n    {\n      #ifndef _NO_PROGRESS\n      CProgressCloser closer(ExtractCallbackSpec->ProgressDialog);\n      #endif\n      Process2();\n    }\n    catch(...) { Result = E_FAIL; }\n  }\n  \n  static THREAD_FUNC_DECL MyThreadFunction(void *param)\n  {\n    ((CThreadExtracting *)param)->Process();\n    return 0;\n  }\n};\n\nHRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,\n    bool showProgress, bool &isCorrupt, UString &errorMessage)\n{\n  isCorrupt = false;\n  CThreadExtracting t;\n\n  t.Codecs = codecs;\n  t.FileName = fileName;\n  t.DestFolder = destFolder;\n\n  t.ExtractCallbackSpec = new CExtractCallbackImp;\n  t.ExtractCallback = t.ExtractCallbackSpec;\n  \n  #ifndef _NO_PROGRESS\n\n  if (showProgress)\n  {\n    t.ExtractCallbackSpec->ProgressDialog.IconID = IDI_ICON;\n    NWindows::CThread thread;\n    const WRes wres = thread.Create(CThreadExtracting::MyThreadFunction, &t);\n    if (wres != 0)\n      return HRESULT_FROM_WIN32(wres);\n    \n    UString title;\n    LangString(IDS_PROGRESS_EXTRACTING, title);\n    t.ExtractCallbackSpec->StartProgressDialog(title, thread);\n  }\n  else\n\n  #endif\n  {\n    t.Process2();\n  }\n\n  errorMessage = t.ErrorMessage;\n  if (errorMessage.IsEmpty())\n    errorMessage = t.ExtractCallbackSpec->_message;\n  isCorrupt = t.ExtractCallbackSpec->_isCorrupt;\n  return t.Result;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXSetup/ExtractEngine.h",
    "content": "﻿// ExtractEngine.h\n\n#ifndef ZIP7_INC_EXTRACT_ENGINE_H\n#define ZIP7_INC_EXTRACT_ENGINE_H\n\n#include \"../../UI/Common/LoadCodecs.h\"\n\nHRESULT ExtractArchive(CCodecs *codecs, const FString &fileName, const FString &destFolder,\n    bool showProgress, bool &isCorrupt, UString &errorMessage);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXSetup/SfxSetup.cpp",
    "content": "﻿// Main.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/DllSecur.h\"\n\n#include \"../../../Common/MyWindows.h\"\n#include \"../../../Common/MyInitGuid.h\"\n\n#include \"../../../Common/CommandLineParser.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/TextConfig.h\"\n\n#include \"../../../Windows/DLL.h\"\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/FileIO.h\"\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/NtCheck.h\"\n#include \"../../../Windows/ResourceString.h\"\n\n#include \"../../UI/Explorer/MyMessages.h\"\n\n#include \"ExtractEngine.h\"\n\n#include \"resource.h\"\n\n// **************** NanaZip Modification Start ****************\n#include \"../../IPassword.h\" // Only for passing the compilation.\n#include <K7Base.h>\n#include <K7User.h>\n#include <Mile.Helpers.h>\n// **************** NanaZip Modification End ****************\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\nextern\nHINSTANCE g_hInstance;\nHINSTANCE g_hInstance;\nextern\nbool g_DisableUserQuestions;\nbool g_DisableUserQuestions;\n\nstatic CFSTR const kTempDirPrefix = FTEXT(\"7zS\");\n\n#define MY_SHELL_EXECUTE\n\nstatic bool ReadDataString(CFSTR fileName, LPCSTR startID,\n    LPCSTR endID, AString &stringResult)\n{\n  stringResult.Empty();\n  NIO::CInFile inFile;\n  if (!inFile.Open(fileName))\n    return false;\n  const size_t kBufferSize = 1 << 12;\n\n  Byte buffer[kBufferSize];\n  const size_t signatureStartSize = MyStringLen(startID + 1);\n  const size_t signatureEndSize = MyStringLen(endID + 1);\n  \n  size_t numBytesPrev = 0;\n  bool writeMode = false;\n  UInt32 posTotal = 0;\n  for (;;)\n  {\n    const size_t numReadBytes = kBufferSize - numBytesPrev;\n    size_t processedSize;\n    if (!inFile.ReadFull(buffer + numBytesPrev, numReadBytes, processedSize))\n      return false;\n    if (processedSize == 0)\n      return true;\n    numBytesPrev += processedSize;\n    size_t pos = 0;\n    for (;;)\n    {\n      if (writeMode)\n      {\n        // **************** 7-Zip ZS Modification Start ****************\n        //if (pos + signatureEndSize > numBytesPrev)\n        if (pos + signatureEndSize >= numBytesPrev)\n        // **************** 7-Zip ZS Modification End ****************\n          break;\n        const Byte b = buffer[pos++];\n        if (b == 0)\n          return false;\n        if (b == ';' && memcmp(buffer + pos, endID + 1, signatureEndSize) == 0)\n          return true;\n        stringResult += (char)b;\n      }\n      else\n      {\n        // **************** 7-Zip ZS Modification Start ****************\n        //if (pos + signatureStartSize > numBytesPrev)\n        if (pos + signatureStartSize >= numBytesPrev)\n        // **************** 7-Zip ZS Modification End ****************\n          break;\n        const Byte b = buffer[pos++];\n        if (b == ';' && memcmp(buffer + pos, startID + 1, signatureStartSize) == 0)\n        {\n          writeMode = true;\n          pos += signatureStartSize;\n        }\n      }\n    }\n    posTotal += (UInt32)pos;\n    if (posTotal > (1 << 21))\n      return stringResult.IsEmpty();\n    numBytesPrev -= pos;\n    memmove(buffer, buffer + pos, numBytesPrev);\n  }\n}\n\nstatic const char * const kStartID = \",!@Install@!UTF-8!\";\nstatic const char * const kEndID   = \",!@InstallEnd@!\";\n\n#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)\n#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L\"Unsupported Windows version\"); return 1;\n#endif\n\nstatic void ShowErrorMessageSpec(const UString &name)\n{\n  UString message = NError::MyFormatMessage(::GetLastError());\n  const int pos = message.Find(L\"%1\");\n  if (pos >= 0)\n  {\n    message.Delete((unsigned)pos, 2);\n    message.Insert((unsigned)pos, name);\n  }\n  ShowErrorMessage(NULL, message);\n}\n\n// **************** NanaZip Modification Start ****************\nvoid NanaZipInitialize()\n{\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseInitialize())\n    {\n        ::ShowErrorMessage(L\"K7BaseInitialize Failed\");\n        ::ExitProcess(1);\n    }\n\n    if (MO_RESULT_SUCCESS_OK != ::K7UserInitializeDarkModeSupport())\n    {\n        ::ShowErrorMessage(L\"K7UserInitializeDarkModeSupport Failed\");\n    }\n\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseDisableDynamicCodeGeneration())\n    {\n        ::ShowErrorMessage(L\"K7BaseDisableDynamicCodeGeneration Failed\");\n    }\n}\n// **************** NanaZip Modification End ****************\n\nint APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,\n    #ifdef UNDER_CE\n    LPWSTR\n    #else\n    LPSTR\n    #endif\n    /* lpCmdLine */,int /* nCmdShow */)\n{\n  g_hInstance = (HINSTANCE)hInstance;\n\n  NT_CHECK\n\n  // **************** NanaZip Modification Start ****************\n  ::NanaZipInitialize();\n  // **************** NanaZip Modification End ****************\n\n  #ifdef _WIN32\n  LoadSecurityDlls();\n  #endif\n\n  // InitCommonControls();\n\n  UString archiveName, switches;\n  #ifdef MY_SHELL_EXECUTE\n  UString executeFile, executeParameters;\n  #endif\n  NCommandLineParser::SplitCommandLine(GetCommandLineW(), archiveName, switches);\n\n  FString fullPath;\n  NDLL::MyGetModuleFileName(fullPath);\n\n  switches.Trim();\n  bool assumeYes = false;\n  if (switches.IsPrefixedBy_Ascii_NoCase(\"-y\"))\n  {\n    assumeYes = true;\n    switches = switches.Ptr(2);\n    switches.Trim();\n  }\n\n  AString config;\n  if (!ReadDataString(fullPath, kStartID, kEndID, config))\n  {\n    if (!assumeYes)\n      ShowErrorMessage(L\"Can't load config info\");\n    return 1;\n  }\n\n  UString dirPrefix (\".\" STRING_PATH_SEPARATOR);\n  UString appLaunched;\n  bool showProgress = true;\n  if (!config.IsEmpty())\n  {\n    CObjectVector<CTextConfigPair> pairs;\n    if (!GetTextConfig(config, pairs))\n    {\n      if (!assumeYes)\n        ShowErrorMessage(L\"Config failed\");\n      return 1;\n    }\n    const UString friendlyName = GetTextConfigValue(pairs, \"Title\");\n    const UString installPrompt = GetTextConfigValue(pairs, \"BeginPrompt\");\n    const UString progress = GetTextConfigValue(pairs, \"Progress\");\n    if (progress.IsEqualTo_Ascii_NoCase(\"no\"))\n      showProgress = false;\n    const int index = FindTextConfigItem(pairs, \"Directory\");\n    if (index >= 0)\n      dirPrefix = pairs[index].String;\n    if (!installPrompt.IsEmpty() && !assumeYes)\n    {\n      if (MessageBoxW(NULL, installPrompt, friendlyName, MB_YESNO |\n          MB_ICONQUESTION) != IDYES)\n        return 0;\n    }\n    appLaunched = GetTextConfigValue(pairs, \"RunProgram\");\n    \n    #ifdef MY_SHELL_EXECUTE\n    executeFile = GetTextConfigValue(pairs, \"ExecuteFile\");\n    executeParameters = GetTextConfigValue(pairs, \"ExecuteParameters\");\n    #endif\n  }\n\n  CTempDir tempDir;\n  if (!tempDir.Create(kTempDirPrefix))\n  {\n    if (!assumeYes)\n      ShowErrorMessage(L\"Cannot create temp folder archive\");\n    return 1;\n  }\n\n  CCodecs *codecs = new CCodecs;\n  CMyComPtr<IUnknown> compressCodecsInfo = codecs;\n  {\n    const HRESULT result = codecs->Load();\n    if (result != S_OK)\n    {\n      ShowErrorMessage(L\"Cannot load codecs\");\n      return 1;\n    }\n  }\n\n  const FString tempDirPath = tempDir.GetPath();\n  // tempDirPath = \"M:\\\\1\\\\\"; // to test low disk space\n  {\n    bool isCorrupt = false;\n    UString errorMessage;\n    HRESULT result = ExtractArchive(codecs, fullPath, tempDirPath, showProgress,\n      isCorrupt, errorMessage);\n    \n    if (result != S_OK)\n    {\n      if (!assumeYes)\n      {\n        if (result == S_FALSE || isCorrupt)\n        {\n          NWindows::MyLoadString(IDS_EXTRACTION_ERROR_MESSAGE, errorMessage);\n          result = E_FAIL;\n        }\n        if (result != E_ABORT)\n        {\n          if (errorMessage.IsEmpty())\n            errorMessage = NError::MyFormatMessage(result);\n          ::MessageBoxW(NULL, errorMessage, NWindows::MyLoadString(IDS_EXTRACTION_ERROR_TITLE), MB_ICONERROR);\n        }\n      }\n      return 1;\n    }\n  }\n\n  #ifndef UNDER_CE\n  CCurrentDirRestorer currentDirRestorer;\n  if (!SetCurrentDir(tempDirPath))\n    return 1;\n  #endif\n  \n  HANDLE hProcess = NULL;\n#ifdef MY_SHELL_EXECUTE\n  if (!executeFile.IsEmpty())\n  {\n    CSysString filePath (GetSystemString(executeFile));\n    SHELLEXECUTEINFO execInfo;\n    execInfo.cbSize = sizeof(execInfo);\n    execInfo.fMask = SEE_MASK_NOCLOSEPROCESS\n      #ifndef UNDER_CE\n      | SEE_MASK_FLAG_DDEWAIT\n      #endif\n      ;\n    execInfo.hwnd = NULL;\n    execInfo.lpVerb = NULL;\n    execInfo.lpFile = filePath;\n\n    if (!switches.IsEmpty())\n    {\n      executeParameters.Add_Space_if_NotEmpty();\n      executeParameters += switches;\n    }\n\n    const CSysString parametersSys (GetSystemString(executeParameters));\n    if (parametersSys.IsEmpty())\n      execInfo.lpParameters = NULL;\n    else\n      execInfo.lpParameters = parametersSys;\n\n    execInfo.lpDirectory = NULL;\n    execInfo.nShow = SW_SHOWNORMAL;\n    execInfo.hProcess = NULL;\n    /* BOOL success = */ ::ShellExecuteEx(&execInfo);\n    UINT32 result = (UINT32)(UINT_PTR)execInfo.hInstApp;\n    if (result <= 32)\n    {\n      if (!assumeYes)\n        ShowErrorMessage(L\"Cannot open file\");\n      return 1;\n    }\n    hProcess = execInfo.hProcess;\n  }\n  else\n#endif\n  {\n    if (appLaunched.IsEmpty())\n    {\n      appLaunched = \"setup.exe\";\n      if (!NFind::DoesFileExist_FollowLink(us2fs(appLaunched)))\n      {\n        if (!assumeYes)\n          ShowErrorMessage(L\"Cannot find setup.exe\");\n        return 1;\n      }\n    }\n    \n    {\n      FString s2 = tempDirPath;\n      NName::NormalizeDirPathPrefix(s2);\n      appLaunched.Replace(L\"%%T\" WSTRING_PATH_SEPARATOR, fs2us(s2));\n    }\n    \n    const UString appNameForError = appLaunched; // actually we need to rtemove parameters also\n\n    appLaunched.Replace(L\"%%T\", fs2us(tempDirPath));\n\n    if (!switches.IsEmpty())\n    {\n      appLaunched.Add_Space();\n      appLaunched += switches;\n    }\n    STARTUPINFO startupInfo;\n    startupInfo.cb = sizeof(startupInfo);\n    startupInfo.lpReserved = NULL;\n    startupInfo.lpDesktop = NULL;\n    startupInfo.lpTitle = NULL;\n    startupInfo.dwFlags = 0;\n    startupInfo.cbReserved2 = 0;\n    startupInfo.lpReserved2 = NULL;\n    \n    PROCESS_INFORMATION processInformation;\n    \n    const CSysString appLaunchedSys (GetSystemString(dirPrefix + appLaunched));\n    \n    const BOOL createResult = CreateProcess(NULL,\n        appLaunchedSys.Ptr_non_const(),\n        NULL, NULL, FALSE, 0, NULL, NULL /*tempDir.GetPath() */,\n        &startupInfo, &processInformation);\n    if (createResult == 0)\n    {\n      if (!assumeYes)\n      {\n        // we print name of exe file, if error message is\n        // ERROR_BAD_EXE_FORMAT: \"%1 is not a valid Win32 application\".\n        ShowErrorMessageSpec(appNameForError);\n      }\n      return 1;\n    }\n    ::CloseHandle(processInformation.hThread);\n    hProcess = processInformation.hProcess;\n  }\n  if (hProcess)\n  {\n    WaitForSingleObject(hProcess, INFINITE);\n    ::CloseHandle(hProcess);\n  }\n  return 0;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXSetup/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#if _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../UI/FileManager/StdAfx.h\"\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXSetup/resource.h",
    "content": "﻿#define IDI_ICON  1\n\n#define IDS_EXTRACTION_ERROR_TITLE       7\n#define IDS_EXTRACTION_ERROR_MESSAGE     8\n#define IDS_CANNOT_CREATE_FOLDER      3003\n#define IDS_PROGRESS_EXTRACTING       3300\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXWin/SfxWin.cpp",
    "content": "﻿// Main.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/MyWindows.h\"\n\n#if defined(__MINGW32__) || defined(__MINGW64__)\n#include <shlwapi.h>\n#else\n#include <Shlwapi.h>\n#endif\n\n#include \"../../../../C/DllSecur.h\"\n\n#include \"../../../Common/MyInitGuid.h\"\n\n#include \"../../../Common/CommandLineParser.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/DLL.h\"\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/NtCheck.h\"\n#include \"../../../Windows/ResourceString.h\"\n\n#include \"../../ICoder.h\"\n#include \"../../IPassword.h\"\n#include \"../../Archive/IArchive.h\"\n#include \"../../UI/Common/Extract.h\"\n#include \"../../UI/Common/ExitCode.h\"\n#include \"../../UI/Explorer/MyMessages.h\"\n#include \"../../UI/FileManager/MyWindowsNew.h\"\n#include \"../../UI/GUI/ExtractGUI.h\"\n#include \"../../UI/GUI/ExtractRes.h\"\n\n// **************** NanaZip Modification Start ****************\n#include <K7Base.h>\n#include <Mile.Helpers.h>\n#include <K7User.h>\n// **************** NanaZip Modification End ****************\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\nextern\nHINSTANCE g_hInstance;\nHINSTANCE g_hInstance;\nextern\nbool g_DisableUserQuestions;\nbool g_DisableUserQuestions;\n\n#ifndef UNDER_CE\n\n#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // win2000\n#define Z7_USE_DYN_ComCtl32Version\n#endif\n\n#ifdef Z7_USE_DYN_ComCtl32Version\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\nstatic DWORD GetDllVersion(LPCTSTR dllName)\n{\n  DWORD dwVersion = 0;\n  const HINSTANCE hinstDll = LoadLibrary(dllName);\n  if (hinstDll)\n  {\n    const\n    DLLGETVERSIONPROC func_DllGetVersion = Z7_GET_PROC_ADDRESS(\n    DLLGETVERSIONPROC, hinstDll, \"DllGetVersion\");\n    if (func_DllGetVersion)\n    {\n      DLLVERSIONINFO dvi;\n      ZeroMemory(&dvi, sizeof(dvi));\n      dvi.cbSize = sizeof(dvi);\n      const HRESULT hr = func_DllGetVersion(&dvi);\n      if (SUCCEEDED(hr))\n        dwVersion = (DWORD)MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion);\n    }\n    FreeLibrary(hinstDll);\n  }\n  return dwVersion;\n}\n\n#endif\n#endif\n\nextern\nbool g_LVN_ITEMACTIVATE_Support;\nbool g_LVN_ITEMACTIVATE_Support = true;\n\nstatic const wchar_t * const kUnknownExceptionMessage = L\"ERROR: Unknown Error!\";\n\nstatic void ErrorMessageForHRESULT(HRESULT res)\n{\n  ShowErrorMessage(HResultToMessage(res));\n}\n\nstatic int APIENTRY WinMain2()\n{\n  // OleInitialize is required for ProgressBar in TaskBar.\n#ifndef UNDER_CE\n  OleInitialize(NULL);\n#endif\n\n#ifndef UNDER_CE\n#ifdef Z7_USE_DYN_ComCtl32Version\n  {\n    const DWORD g_ComCtl32Version = ::GetDllVersion(TEXT(\"comctl32.dll\"));\n    g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4));\n  }\n#endif\n#endif\n\n  UString password;\n  bool assumeYes = false;\n  bool outputFolderDefined = false;\n  FString outputFolder;\n  UStringVector commandStrings;\n  NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);\n\n  #ifndef UNDER_CE\n  if (commandStrings.Size() > 0)\n    commandStrings.Delete(0);\n  #endif\n\n  FOR_VECTOR (i, commandStrings)\n  {\n    const UString &s = commandStrings[i];\n    if (s.Len() > 1 && s[0] == '-')\n    {\n      const wchar_t c = MyCharLower_Ascii(s[1]);\n      if (c == 'y')\n      {\n        assumeYes = true;\n        if (s.Len() != 2)\n        {\n          ShowErrorMessage(L\"Bad command\");\n          return 1;\n        }\n      }\n      else if (c == 'o')\n      {\n        outputFolder = us2fs(s.Ptr(2));\n        NName::NormalizeDirPathPrefix(outputFolder);\n        outputFolderDefined = !outputFolder.IsEmpty();\n      }\n      else if (c == 'p')\n      {\n        password = s.Ptr(2);\n      }\n    }\n  }\n\n  g_DisableUserQuestions = assumeYes;\n\n  FString path;\n  NDLL::MyGetModuleFileName(path);\n\n  FString fullPath;\n  if (!MyGetFullPathName(path, fullPath))\n  {\n    ShowErrorMessage(L\"Error 1329484\");\n    return 1;\n  }\n\n  CCodecs *codecs = new CCodecs;\n  CMyComPtr<IUnknown> compressCodecsInfo = codecs;\n  HRESULT result = codecs->Load();\n  if (result != S_OK)\n  {\n    ErrorMessageForHRESULT(result);\n    return 1;\n  }\n\n  // COpenCallbackGUI openCallback;\n\n  // openCallback.PasswordIsDefined = !password.IsEmpty();\n  // openCallback.Password = password;\n\n  CExtractCallbackImp *ecs = new CExtractCallbackImp;\n  CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;\n  ecs->Init();\n\n  #ifndef Z7_NO_CRYPTO\n  ecs->PasswordIsDefined = !password.IsEmpty();\n  ecs->Password = password;\n  #endif\n\n  CExtractOptions eo;\n\n  FString dirPrefix;\n  if (!GetOnlyDirPrefix(path, dirPrefix))\n  {\n    ShowErrorMessage(L\"Error 1329485\");\n    return 1;\n  }\n\n  eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix;\n  eo.YesToAll = assumeYes;\n  eo.OverwriteMode = assumeYes ?\n      NExtract::NOverwriteMode::kOverwrite :\n      NExtract::NOverwriteMode::kAsk;\n  eo.PathMode = NExtract::NPathMode::kFullPaths;\n  eo.TestMode = false;\n\n  UStringVector v1, v2;\n  v1.Add(fs2us(fullPath));\n  v2.Add(fs2us(fullPath));\n  NWildcard::CCensorNode wildcardCensor;\n  wildcardCensor.Add_Wildcard();\n\n  bool messageWasDisplayed = false;\n  result = ExtractGUI(codecs,\n      CObjectVector<COpenType>(), CIntVector(),\n      v1, v2,\n      wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs);\n\n  if (result == S_OK)\n  {\n    if (!ecs->IsOK())\n      return NExitCode::kFatalError;\n    return 0;\n  }\n  if (result == E_ABORT)\n    return NExitCode::kUserBreak;\n  if (!messageWasDisplayed)\n  {\n    if (result == S_FALSE)\n      ShowErrorMessage(L\"Error in archive\");\n    else\n      ErrorMessageForHRESULT(result);\n  }\n  if (result == E_OUTOFMEMORY)\n    return NExitCode::kMemoryError;\n  return NExitCode::kFatalError;\n}\n\n#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)\n#define NT_CHECK_FAIL_ACTION ShowErrorMessage(L\"Unsupported Windows version\"); return NExitCode::kFatalError;\n#endif\n\n// **************** NanaZip Modification Start ****************\nvoid NanaZipInitialize()\n{\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseInitialize())\n    {\n        ::ShowErrorMessage(L\"K7BaseInitialize Failed\");\n        ::ExitProcess(1);\n    }\n\n    if (MO_RESULT_SUCCESS_OK != ::K7UserInitializeDarkModeSupport())\n    {\n        ::ShowErrorMessage(L\"K7UserInitializeDarkModeSupport Failed\");\n    }\n\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseDisableDynamicCodeGeneration())\n    {\n        ::ShowErrorMessage(L\"K7BaseDisableDynamicCodeGeneration Failed\");\n    }\n\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseDisableChildProcessCreation())\n    {\n        ::ShowErrorMessage(L\"K7BaseDisableChildProcessCreation Failed\");\n    }\n}\n// **************** NanaZip Modification End ****************\n\nint APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,\n  #ifdef UNDER_CE\n  LPWSTR\n  #else\n  LPSTR\n  #endif\n  /* lpCmdLine */, int /* nCmdShow */)\n{\n  g_hInstance = (HINSTANCE)hInstance;\n\n  NT_CHECK\n\n  // **************** NanaZip Modification Start ****************\n  ::NanaZipInitialize();\n  // **************** NanaZip Modification End ****************\n\n  try\n  {\n    #ifdef _WIN32\n    LoadSecurityDlls();\n    #endif\n\n    return WinMain2();\n  }\n  catch(const CNewException &)\n  {\n    ErrorMessageForHRESULT(E_OUTOFMEMORY);\n    return NExitCode::kMemoryError;\n  }\n  catch(...)\n  {\n    ShowErrorMessage(kUnknownExceptionMessage);\n    return NExitCode::kFatalError;\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXWin/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#if _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../UI/FileManager/StdAfx.h\"\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Bundles/SFXWin/resource.h",
    "content": "﻿#define IDI_ICON  1\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/CWrappers.cpp",
    "content": "﻿// CWrappers.c\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"CWrappers.h\"\n\n#include \"StreamUtils.h\"\n\nSRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw()\n{\n  switch (res)\n  {\n    case S_OK: return SZ_OK;\n    case E_OUTOFMEMORY: return SZ_ERROR_MEM;\n    case E_INVALIDARG: return SZ_ERROR_PARAM;\n    case E_ABORT: return SZ_ERROR_PROGRESS;\n    case S_FALSE: return SZ_ERROR_DATA;\n    case E_NOTIMPL: return SZ_ERROR_UNSUPPORTED;\n    default: break;\n  }\n  return defaultRes;\n}\n\n\nHRESULT SResToHRESULT(SRes res) throw()\n{\n  switch (res)\n  {\n    case SZ_OK: return S_OK;\n    \n    case SZ_ERROR_DATA:\n    case SZ_ERROR_CRC:\n    case SZ_ERROR_INPUT_EOF:\n    case SZ_ERROR_ARCHIVE:\n    case SZ_ERROR_NO_ARCHIVE:\n      return S_FALSE;\n    \n    case SZ_ERROR_MEM: return E_OUTOFMEMORY;\n    case SZ_ERROR_PARAM: return E_INVALIDARG;\n    case SZ_ERROR_PROGRESS: return E_ABORT;\n    case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;\n    // case SZ_ERROR_OUTPUT_EOF:\n    // case SZ_ERROR_READ:\n    // case SZ_ERROR_WRITE:\n    // case SZ_ERROR_THREAD:\n    // case SZ_ERROR_ARCHIVE:\n    // case SZ_ERROR_NO_ARCHIVE:\n    // return E_FAIL;\n    default: break;\n  }\n  if (res < 0)\n    return res;\n  return E_FAIL;\n}\n\n\n#define PROGRESS_UNKNOWN_VALUE ((UInt64)(Int64)-1)\n\n#define CONVERT_PR_VAL(x) (x == PROGRESS_UNKNOWN_VALUE ? NULL : &x)\n\n\nstatic SRes CompressProgress(ICompressProgressPtr pp, UInt64 inSize, UInt64 outSize) throw()\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CCompressProgressWrap)\n  p->Res = p->Progress->SetRatioInfo(CONVERT_PR_VAL(inSize), CONVERT_PR_VAL(outSize));\n  return HRESULT_To_SRes(p->Res, SZ_ERROR_PROGRESS);\n}\n\nvoid CCompressProgressWrap::Init(ICompressProgressInfo *progress) throw()\n{\n  vt.Progress = CompressProgress;\n  Progress = progress;\n  Res = SZ_OK;\n}\n\nstatic const UInt32 kStreamStepSize = (UInt32)1 << 31;\n\nstatic SRes MyRead(ISeqInStreamPtr pp, void *data, size_t *size) throw()\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqInStreamWrap)\n  UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);\n  p->Res = (p->Stream->Read(data, curSize, &curSize));\n  *size = curSize;\n  p->Processed += curSize;\n  if (p->Res == S_OK)\n    return SZ_OK;\n  return HRESULT_To_SRes(p->Res, SZ_ERROR_READ);\n}\n\nstatic size_t MyWrite(ISeqOutStreamPtr pp, const void *data, size_t size) throw()\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeqOutStreamWrap)\n  if (p->Stream)\n  {\n    p->Res = WriteStream(p->Stream, data, size);\n    if (p->Res != 0)\n      return 0;\n  }\n  else\n    p->Res = S_OK;\n  p->Processed += size;\n  return size;\n}\n\n\nvoid CSeqInStreamWrap::Init(ISequentialInStream *stream) throw()\n{\n  vt.Read = MyRead;\n  Stream = stream;\n  Processed = 0;\n  Res = S_OK;\n}\n\nvoid CSeqOutStreamWrap::Init(ISequentialOutStream *stream) throw()\n{\n  vt.Write = MyWrite;\n  Stream = stream;\n  Res = SZ_OK;\n  Processed = 0;\n}\n\n\nstatic SRes InStreamWrap_Read(ISeekInStreamPtr pp, void *data, size_t *size) throw()\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeekInStreamWrap)\n  UInt32 curSize = ((*size < kStreamStepSize) ? (UInt32)*size : kStreamStepSize);\n  p->Res = p->Stream->Read(data, curSize, &curSize);\n  *size = curSize;\n  return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;\n}\n\nstatic SRes InStreamWrap_Seek(ISeekInStreamPtr pp, Int64 *offset, ESzSeek origin) throw()\n{\n  Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CSeekInStreamWrap)\n  UInt32 moveMethod;\n  /* we need (int)origin to eliminate the clang warning:\n     default label in switch which covers all enumeration values\n     [-Wcovered-switch-default */\n  switch ((int)origin)\n  {\n    case SZ_SEEK_SET: moveMethod = STREAM_SEEK_SET; break;\n    case SZ_SEEK_CUR: moveMethod = STREAM_SEEK_CUR; break;\n    case SZ_SEEK_END: moveMethod = STREAM_SEEK_END; break;\n    default: return SZ_ERROR_PARAM;\n  }\n  UInt64 newPosition;\n  p->Res = p->Stream->Seek(*offset, moveMethod, &newPosition);\n  *offset = (Int64)newPosition;\n  return (p->Res == S_OK) ? SZ_OK : SZ_ERROR_READ;\n}\n\nvoid CSeekInStreamWrap::Init(IInStream *stream) throw()\n{\n  Stream = stream;\n  vt.Read = InStreamWrap_Read;\n  vt.Seek = InStreamWrap_Seek;\n  Res = S_OK;\n}\n\n\n/* ---------- CByteInBufWrap ---------- */\n\nvoid CByteInBufWrap::Free() throw()\n{\n  ::MidFree(Buf);\n  Buf = NULL;\n}\n\nbool CByteInBufWrap::Alloc(UInt32 size) throw()\n{\n  if (!Buf || size != Size)\n  {\n    Free();\n    Lim = Cur = Buf = (Byte *)::MidAlloc((size_t)size);\n    Size = size;\n  }\n  return (Buf != NULL);\n}\n\nByte CByteInBufWrap::ReadByteFromNewBlock() throw()\n{\n  if (!Extra && Res == S_OK)\n  {\n    UInt32 avail;\n    Res = Stream->Read(Buf, Size, &avail);\n    Processed += (size_t)(Cur - Buf);\n    Cur = Buf;\n    Lim = Buf + avail;\n    if (avail != 0)\n      return *Cur++;\n  }\n  Extra = true;\n  return 0;\n}\n\n// #pragma GCC diagnostic ignored \"-Winvalid-offsetof\"\n\nstatic Byte Wrap_ReadByte(IByteInPtr pp) throw()\n{\n  CByteInBufWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteInBufWrap, vt);\n  // Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteInBufWrap)\n  if (p->Cur != p->Lim)\n    return *p->Cur++;\n  return p->ReadByteFromNewBlock();\n}\n\nCByteInBufWrap::CByteInBufWrap() throw(): Buf(NULL)\n{\n  vt.Read = Wrap_ReadByte;\n}\n\n\n\n/* ---------- CByteOutBufWrap ---------- */\n\n/*\nvoid CLookToSequentialWrap::Free() throw()\n{\n  ::MidFree(BufBase);\n  BufBase = NULL;\n}\n\nbool CLookToSequentialWrap::Alloc(UInt32 size) throw()\n{\n  if (!BufBase || size != Size)\n  {\n    Free();\n    BufBase = (Byte *)::MidAlloc((size_t)size);\n    Size = size;\n  }\n  return (BufBase != NULL);\n}\n*/\n\n/*\nEXTERN_C_BEGIN\n\nvoid CLookToSequentialWrap_Look(ILookInSeqStreamPtr pp)\n{\n  CLookToSequentialWrap *p = (CLookToSequentialWrap *)pp->Obj;\n\n  if (p->Extra || p->Res != S_OK)\n    return;\n  {\n    UInt32 avail;\n    p->Res = p->Stream->Read(p->BufBase, p->Size, &avail);\n    p->Processed += avail;\n    pp->Buf = p->BufBase;\n    pp->Limit = pp->Buf + avail;\n    if (avail == 0)\n      p->Extra = true;\n  }\n}\n\nEXTERN_C_END\n*/\n\n\n/* ---------- CByteOutBufWrap ---------- */\n\nvoid CByteOutBufWrap::Free() throw()\n{\n  ::MidFree(Buf);\n  Buf = NULL;\n}\n\nbool CByteOutBufWrap::Alloc(size_t size) throw()\n{\n  if (!Buf || size != Size)\n  {\n    Free();\n    Buf = (Byte *)::MidAlloc(size);\n    Size = size;\n  }\n  return (Buf != NULL);\n}\n\nHRESULT CByteOutBufWrap::Flush() throw()\n{\n  if (Res == S_OK)\n  {\n    const size_t size = (size_t)(Cur - Buf);\n    Res = WriteStream(Stream, Buf, size);\n    if (Res == S_OK)\n      Processed += size;\n    // else throw 11;\n  }\n  Cur = Buf; // reset pointer for later Wrap_WriteByte()\n  return Res;\n}\n\nstatic void Wrap_WriteByte(IByteOutPtr pp, Byte b) throw()\n{\n  CByteOutBufWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteOutBufWrap, vt);\n  // Z7_CONTAINER_FROM_VTBL_TO_DECL_VAR_pp_vt_p(CByteOutBufWrap)\n  Byte *dest = p->Cur;\n  *dest = b;\n  p->Cur = ++dest;\n  if (dest == p->Lim)\n    p->Flush();\n}\n\nCByteOutBufWrap::CByteOutBufWrap() throw(): Buf(NULL), Size(0)\n{\n  vt.Write = Wrap_WriteByte;\n}\n\n\n/* ---------- CLookOutWrap ---------- */\n\n/*\nvoid CLookOutWrap::Free() throw()\n{\n  ::MidFree(Buf);\n  Buf = NULL;\n}\n\nbool CLookOutWrap::Alloc(size_t size) throw()\n{\n  if (!Buf || size != Size)\n  {\n    Free();\n    Buf = (Byte *)::MidAlloc(size);\n    Size = size;\n  }\n  return (Buf != NULL);\n}\n\nstatic size_t LookOutWrap_GetOutBuf(ILookOutStreamPtr pp, void **buf) throw()\n{\n  CLookOutWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt);\n  *buf = p->Buf;\n  return p->Size;\n}\n\nstatic size_t LookOutWrap_Write(ILookOutStreamPtr pp, size_t size) throw()\n{\n  CLookOutWrap *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CLookOutWrap, vt);\n  if (p->Res == S_OK && size != 0)\n  {\n    p->Res = WriteStream(p->Stream, p->Buf, size);\n    if (p->Res == S_OK)\n    {\n      p->Processed += size;\n      return size;\n    }\n  }\n  return 0;\n}\n\nCLookOutWrap::CLookOutWrap() throw(): Buf(NULL), Size(0)\n{\n  vt.GetOutBuf = LookOutWrap_GetOutBuf;\n  vt.Write = LookOutWrap_Write;\n}\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/CWrappers.h",
    "content": "﻿// CWrappers.h\n\n#ifndef ZIP7_INC_C_WRAPPERS_H\n#define ZIP7_INC_C_WRAPPERS_H\n\n#include \"../ICoder.h\"\n#include \"../../Common/MyCom.h\"\n\nSRes HRESULT_To_SRes(HRESULT res, SRes defaultRes) throw();\nHRESULT SResToHRESULT(SRes res) throw();\n\nstruct CCompressProgressWrap\n{\n  ICompressProgress vt;\n  ICompressProgressInfo *Progress;\n  HRESULT Res;\n  \n  void Init(ICompressProgressInfo *progress) throw();\n};\n\n\nstruct CSeqInStreamWrap\n{\n  ISeqInStream vt;\n  ISequentialInStream *Stream;\n  HRESULT Res;\n  UInt64 Processed;\n  \n  void Init(ISequentialInStream *stream) throw();\n};\n\n\nstruct CSeekInStreamWrap\n{\n  ISeekInStream vt;\n  IInStream *Stream;\n  HRESULT Res;\n  \n  void Init(IInStream *stream) throw();\n};\n\n\nstruct CSeqOutStreamWrap\n{\n  ISeqOutStream vt;\n  ISequentialOutStream *Stream;\n  HRESULT Res;\n  UInt64 Processed;\n  \n  void Init(ISequentialOutStream *stream) throw();\n};\n\n\nstruct CByteInBufWrap\n{\n  IByteIn vt;\n  const Byte *Cur;\n  const Byte *Lim;\n  Byte *Buf;\n  UInt32 Size;\n  ISequentialInStream *Stream;\n  UInt64 Processed;\n  bool Extra;\n  HRESULT Res;\n  \n  CByteInBufWrap() throw();\n  ~CByteInBufWrap() { Free(); }\n  void Free() throw();\n  bool Alloc(UInt32 size) throw();\n  void Init()\n  {\n    Lim = Cur = Buf;\n    Processed = 0;\n    Extra = false;\n    Res = S_OK;\n  }\n  UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); }\n  Byte ReadByteFromNewBlock() throw();\n  Byte ReadByte()\n  {\n    if (Cur != Lim)\n      return *Cur++;\n    return ReadByteFromNewBlock();\n  }\n};\n\n\n/*\nstruct CLookToSequentialWrap\n{\n  Byte *BufBase;\n  UInt32 Size;\n  ISequentialInStream *Stream;\n  UInt64 Processed;\n  bool Extra;\n  HRESULT Res;\n  \n  CLookToSequentialWrap(): BufBase(NULL) {}\n  ~CLookToSequentialWrap() { Free(); }\n  void Free() throw();\n  bool Alloc(UInt32 size) throw();\n  void Init()\n  {\n    // Lim = Cur = Buf;\n    Processed = 0;\n    Extra = false;\n    Res = S_OK;\n  }\n  // UInt64 GetProcessed() const { return Processed + (Cur - Buf); }\n\n  Byte ReadByteFromNewBlock() throw();\n  Byte ReadByte()\n  {\n    if (Cur != Lim)\n      return *Cur++;\n    return ReadByteFromNewBlock();\n  }\n};\n\nEXTERN_C_BEGIN\n// void CLookToSequentialWrap_Look(ILookInSeqStream *pp);\nEXTERN_C_END\n*/\n\n\n\nstruct CByteOutBufWrap\n{\n  IByteOut vt;\n  Byte *Cur;\n  const Byte *Lim;\n  Byte *Buf;\n  size_t Size;\n  ISequentialOutStream *Stream;\n  UInt64 Processed;\n  HRESULT Res;\n  \n  CByteOutBufWrap() throw();\n  ~CByteOutBufWrap() { Free(); }\n  void Free() throw();\n  bool Alloc(size_t size) throw();\n  void Init()\n  {\n    Cur = Buf;\n    Lim = Buf + Size;\n    Processed = 0;\n    Res = S_OK;\n  }\n  UInt64 GetProcessed() const { return Processed + (size_t)(Cur - Buf); }\n  HRESULT Flush() throw();\n  void WriteByte(Byte b)\n  {\n    *Cur++ = b;\n    if (Cur == Lim)\n      Flush();\n  }\n};\n\n\n/*\nstruct CLookOutWrap\n{\n  ILookOutStream vt;\n  Byte *Buf;\n  size_t Size;\n  ISequentialOutStream *Stream;\n  UInt64 Processed;\n  HRESULT Res;\n  \n  CLookOutWrap() throw();\n  ~CLookOutWrap() { Free(); }\n  void Free() throw();\n  bool Alloc(size_t size) throw();\n  void Init()\n  {\n    Processed = 0;\n    Res = S_OK;\n  }\n};\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/CreateCoder.cpp",
    "content": "﻿// CreateCoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Windows/Defs.h\"\n#include \"../../Windows/PropVariant.h\"\n\n#include \"CreateCoder.h\"\n\n#include \"FilterCoder.h\"\n#include \"RegisterCodec.h\"\n\n// **************** NanaZip Modification Start ****************\n#ifndef Z7_SFX\n#include <K7Base.h>\n#endif\n\n// static const unsigned kNumCodecsMax = 64;\nstatic const unsigned kNumCodecsMax = 256;\n// **************** NanaZip Modification End ****************\nextern\nunsigned g_NumCodecs;\nunsigned g_NumCodecs = 0;\nextern\nconst CCodecInfo *g_Codecs[];\nconst CCodecInfo *g_Codecs[kNumCodecsMax];\n\n// We use g_ExternalCodecs in other stages.\n#ifdef Z7_EXTERNAL_CODECS\n/*\nextern CExternalCodecs g_ExternalCodecs;\n#define CHECK_GLOBAL_CODECS \\\n    if (!_externalCodecs || !_externalCodecs->IsSet()) _externalCodecs = &g_ExternalCodecs;\n*/\n#define CHECK_GLOBAL_CODECS\n#endif\n\n\nvoid RegisterCodec(const CCodecInfo *codecInfo) throw()\n{\n#ifndef Z7_SFX\n  if (!::K7BaseGetAllowedCodecPolicy(codecInfo->Name))\n  {\n    return;\n  }\n#endif\n\n  if (g_NumCodecs < kNumCodecsMax)\n    g_Codecs[g_NumCodecs++] = codecInfo;\n}\n\n// **************** NanaZip Modification Start ****************\n// static const unsigned kNumHashersMax = 32;\nstatic const unsigned kNumHashersMax = 256;\n// **************** NanaZip Modification End ****************\nextern\nunsigned g_NumHashers;\nunsigned g_NumHashers = 0;\nextern\nconst CHasherInfo *g_Hashers[];\nconst CHasherInfo *g_Hashers[kNumHashersMax];\n\nvoid RegisterHasher(const CHasherInfo *hashInfo) throw()\n{\n  if (g_NumHashers < kNumHashersMax)\n    g_Hashers[g_NumHashers++] = hashInfo;\n}\n\n\n#ifdef Z7_EXTERNAL_CODECS\n\nstatic HRESULT ReadNumberOfStreams(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, UInt32 &res)\n{\n  NWindows::NCOM::CPropVariant prop;\n  RINOK(codecsInfo->GetProperty(index, propID, &prop))\n  if (prop.vt == VT_EMPTY)\n    res = 1;\n  else if (prop.vt == VT_UI4)\n    res = prop.ulVal;\n  else\n    return E_INVALIDARG;\n  return S_OK;\n}\n\nstatic HRESULT ReadIsAssignedProp(ICompressCodecsInfo *codecsInfo, UInt32 index, PROPID propID, bool &res)\n{\n  NWindows::NCOM::CPropVariant prop;\n  RINOK(codecsInfo->GetProperty(index, propID, &prop))\n  if (prop.vt == VT_EMPTY)\n    res = true;\n  else if (prop.vt == VT_BOOL)\n    res = VARIANT_BOOLToBool(prop.boolVal);\n  else\n    return E_INVALIDARG;\n  return S_OK;\n}\n\nHRESULT CExternalCodecs::Load()\n{\n  Codecs.Clear();\n  Hashers.Clear();\n\n  if (GetCodecs)\n  {\n    CCodecInfoEx info;\n    \n    UString s;\n    UInt32 num;\n    RINOK(GetCodecs->GetNumMethods(&num))\n    \n    for (UInt32 i = 0; i < num; i++)\n    {\n      NWindows::NCOM::CPropVariant prop;\n      \n      RINOK(GetCodecs->GetProperty(i, NMethodPropID::kID, &prop))\n      if (prop.vt != VT_UI8)\n        continue; // old Interface\n      info.Id = prop.uhVal.QuadPart;\n      \n      prop.Clear();\n      \n      info.Name.Empty();\n      RINOK(GetCodecs->GetProperty(i, NMethodPropID::kName, &prop))\n      if (prop.vt == VT_BSTR)\n        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);\n      else if (prop.vt != VT_EMPTY)\n        continue;\n      \n      RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kPackStreams, info.NumStreams))\n      {\n        UInt32 numUnpackStreams = 1;\n        RINOK(ReadNumberOfStreams(GetCodecs, i, NMethodPropID::kUnpackStreams, numUnpackStreams))\n        if (numUnpackStreams != 1)\n          continue;\n      }\n      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kEncoderIsAssigned, info.EncoderIsAssigned))\n      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kDecoderIsAssigned, info.DecoderIsAssigned))\n      RINOK(ReadIsAssignedProp(GetCodecs, i, NMethodPropID::kIsFilter, info.IsFilter))\n      \n      Codecs.Add(info);\n    }\n  }\n  \n  if (GetHashers)\n  {\n    UInt32 num = GetHashers->GetNumHashers();\n    CHasherInfoEx info;\n    \n    for (UInt32 i = 0; i < num; i++)\n    {\n      NWindows::NCOM::CPropVariant prop;\n\n      RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kID, &prop))\n      if (prop.vt != VT_UI8)\n        continue;\n      info.Id = prop.uhVal.QuadPart;\n      \n      prop.Clear();\n      \n      info.Name.Empty();\n      RINOK(GetHashers->GetHasherProp(i, NMethodPropID::kName, &prop))\n      if (prop.vt == VT_BSTR)\n        info.Name.SetFromWStr_if_Ascii(prop.bstrVal);\n      else if (prop.vt != VT_EMPTY)\n        continue;\n      \n      Hashers.Add(info);\n    }\n  }\n  \n  return S_OK;\n}\n\n#endif\n\n\nint FindMethod_Index(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const AString &name,\n    bool encode,\n    CMethodId &methodId,\n    UInt32 &numStreams,\n    bool &isFilter)\n{\n  unsigned i;\n  for (i = 0; i < g_NumCodecs; i++)\n  {\n    const CCodecInfo &codec = *g_Codecs[i];\n    if ((encode ? codec.CreateEncoder : codec.CreateDecoder)\n        && StringsAreEqualNoCase_Ascii(name, codec.Name))\n    {\n      methodId = codec.Id;\n      numStreams = codec.NumStreams;\n      isFilter = codec.IsFilter;\n      return (int)i;\n    }\n  }\n  \n  #ifdef Z7_EXTERNAL_CODECS\n  \n  CHECK_GLOBAL_CODECS\n\n  if (_externalCodecs)\n    for (i = 0; i < _externalCodecs->Codecs.Size(); i++)\n    {\n      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];\n      if ((encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned)\n          && StringsAreEqualNoCase_Ascii(name, codec.Name))\n      {\n        methodId = codec.Id;\n        numStreams = codec.NumStreams;\n        isFilter = codec.IsFilter;\n        return (int)(g_NumCodecs + i);\n      }\n    }\n  \n  #endif\n  \n  return -1;\n}\n\n\nstatic int FindMethod_Index(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode)\n{\n  unsigned i;\n  for (i = 0; i < g_NumCodecs; i++)\n  {\n    const CCodecInfo &codec = *g_Codecs[i];\n    if (codec.Id == methodId && (encode ? codec.CreateEncoder : codec.CreateDecoder))\n      return (int)i;\n  }\n  \n  #ifdef Z7_EXTERNAL_CODECS\n  \n  CHECK_GLOBAL_CODECS\n\n  if (_externalCodecs)\n    for (i = 0; i < _externalCodecs->Codecs.Size(); i++)\n    {\n      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];\n      if (codec.Id == methodId && (encode ? codec.EncoderIsAssigned : codec.DecoderIsAssigned))\n        return (int)(g_NumCodecs + i);\n    }\n  \n  #endif\n  \n  return -1;\n}\n\n\nbool FindMethod(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId,\n    AString &name)\n{\n  name.Empty();\n \n  unsigned i;\n  for (i = 0; i < g_NumCodecs; i++)\n  {\n    const CCodecInfo &codec = *g_Codecs[i];\n    if (methodId == codec.Id)\n    {\n      name = codec.Name;\n      return true;\n    }\n  }\n  \n  #ifdef Z7_EXTERNAL_CODECS\n\n  CHECK_GLOBAL_CODECS\n\n  if (_externalCodecs)\n    for (i = 0; i < _externalCodecs->Codecs.Size(); i++)\n    {\n      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];\n      if (methodId == codec.Id)\n      {\n        name = codec.Name;\n        return true;\n      }\n    }\n  \n  #endif\n  \n  return false;\n}\n\nbool FindHashMethod(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const AString &name,\n    CMethodId &methodId)\n{\n  unsigned i;\n  for (i = 0; i < g_NumHashers; i++)\n  {\n    const CHasherInfo &codec = *g_Hashers[i];\n    if (StringsAreEqualNoCase_Ascii(name, codec.Name))\n    {\n      methodId = codec.Id;\n      return true;\n    }\n  }\n  \n  #ifdef Z7_EXTERNAL_CODECS\n\n  CHECK_GLOBAL_CODECS\n\n  if (_externalCodecs)\n    for (i = 0; i < _externalCodecs->Hashers.Size(); i++)\n    {\n      const CHasherInfoEx &codec = _externalCodecs->Hashers[i];\n      if (StringsAreEqualNoCase_Ascii(name, codec.Name))\n      {\n        methodId = codec.Id;\n        return true;\n      }\n    }\n  \n  #endif\n  \n  return false;\n}\n\nvoid GetHashMethods(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CRecordVector<CMethodId> &methods)\n{\n  methods.ClearAndSetSize(g_NumHashers);\n  unsigned i;\n  for (i = 0; i < g_NumHashers; i++)\n    methods[i] = (*g_Hashers[i]).Id;\n  \n  #ifdef Z7_EXTERNAL_CODECS\n  \n  CHECK_GLOBAL_CODECS\n\n  if (_externalCodecs)\n    for (i = 0; i < _externalCodecs->Hashers.Size(); i++)\n      methods.Add(_externalCodecs->Hashers[i].Id);\n  \n  #endif\n}\n\n\n\nHRESULT CreateCoder_Index(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    unsigned i, bool encode,\n    CMyComPtr<ICompressFilter> &filter,\n    CCreatedCoder &cod)\n{\n  cod.IsExternal = false;\n  cod.IsFilter = false;\n  cod.NumStreams = 1;\n\n  if (i < g_NumCodecs)\n  {\n    const CCodecInfo &codec = *g_Codecs[i];\n    // if (codec.Id == methodId)\n    {\n      if (encode)\n      {\n        if (codec.CreateEncoder)\n        {\n          void *p = codec.CreateEncoder();\n          if (codec.IsFilter) filter = (ICompressFilter *)p;\n          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;\n          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }\n          return S_OK;\n        }\n      }\n      else\n        if (codec.CreateDecoder)\n        {\n          void *p = codec.CreateDecoder();\n          if (codec.IsFilter) filter = (ICompressFilter *)p;\n          else if (codec.NumStreams == 1) cod.Coder = (ICompressCoder *)p;\n          else { cod.Coder2 = (ICompressCoder2 *)p; cod.NumStreams = codec.NumStreams; }\n          return S_OK;\n        }\n    }\n  }\n\n  #ifdef Z7_EXTERNAL_CODECS\n\n  CHECK_GLOBAL_CODECS\n  \n  if (_externalCodecs)\n  {\n    i -= g_NumCodecs;\n    cod.IsExternal = true;\n    if (i < _externalCodecs->Codecs.Size())\n    {\n      const CCodecInfoEx &codec = _externalCodecs->Codecs[i];\n      // if (codec.Id == methodId)\n      {\n        if (encode)\n        {\n          if (codec.EncoderIsAssigned)\n          {\n            if (codec.NumStreams == 1)\n            {\n              const HRESULT res = _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder, (void **)&cod.Coder);\n              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)\n                return res;\n              if (cod.Coder)\n                return res;\n              return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressFilter, (void **)&filter);\n            }\n            cod.NumStreams = codec.NumStreams;\n            return _externalCodecs->GetCodecs->CreateEncoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);\n          }\n        }\n        else\n          if (codec.DecoderIsAssigned)\n          {\n            if (codec.NumStreams == 1)\n            {\n              const HRESULT res = _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder, (void **)&cod.Coder);\n              if (res != S_OK && res != E_NOINTERFACE && res != CLASS_E_CLASSNOTAVAILABLE)\n                return res;\n              if (cod.Coder)\n                return res;\n              return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressFilter, (void **)&filter);\n            }\n            cod.NumStreams = codec.NumStreams;\n            return _externalCodecs->GetCodecs->CreateDecoder(i, &IID_ICompressCoder2, (void **)&cod.Coder2);\n          }\n      }\n    }\n  }\n  #endif\n\n  return S_OK;\n}\n\n\nHRESULT CreateCoder_Index(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    unsigned index, bool encode,\n    CCreatedCoder &cod)\n{\n  CMyComPtr<ICompressFilter> filter;\n  const HRESULT res = CreateCoder_Index(\n      EXTERNAL_CODECS_LOC_VARS\n      index, encode,\n      filter, cod);\n  \n  if (filter)\n  {\n    cod.IsFilter = true;\n    CFilterCoder *coderSpec = new CFilterCoder(encode);\n    cod.Coder = coderSpec;\n    coderSpec->Filter = filter;\n  }\n  \n  return res;\n}\n\n\nHRESULT CreateCoder_Id(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CMyComPtr<ICompressFilter> &filter,\n    CCreatedCoder &cod)\n{\n  const int index = FindMethod_Index(EXTERNAL_CODECS_LOC_VARS methodId, encode);\n  if (index < 0)\n    return S_OK;\n  return CreateCoder_Index(EXTERNAL_CODECS_LOC_VARS (unsigned)index, encode, filter, cod);\n}\n\n\nHRESULT CreateCoder_Id(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CCreatedCoder &cod)\n{\n  CMyComPtr<ICompressFilter> filter;\n  const HRESULT res = CreateCoder_Id(\n      EXTERNAL_CODECS_LOC_VARS\n      methodId, encode,\n      filter, cod);\n  \n  if (filter)\n  {\n    cod.IsFilter = true;\n    CFilterCoder *coderSpec = new CFilterCoder(encode);\n    cod.Coder = coderSpec;\n    coderSpec->Filter = filter;\n  }\n  \n  return res;\n}\n\n\nHRESULT CreateCoder_Id(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CMyComPtr<ICompressCoder> &coder)\n{\n  CCreatedCoder cod;\n  const HRESULT res = CreateCoder_Id(\n      EXTERNAL_CODECS_LOC_VARS\n      methodId, encode,\n      cod);\n  coder = cod.Coder;\n  return res;\n}\n\nHRESULT CreateFilter(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CMyComPtr<ICompressFilter> &filter)\n{\n  CCreatedCoder cod;\n  return CreateCoder_Id(\n      EXTERNAL_CODECS_LOC_VARS\n      methodId, encode,\n      filter, cod);\n}\n\n\nHRESULT CreateHasher(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId,\n    AString &name,\n    CMyComPtr<IHasher> &hasher)\n{\n  name.Empty();\n\n  unsigned i;\n  for (i = 0; i < g_NumHashers; i++)\n  {\n    const CHasherInfo &codec = *g_Hashers[i];\n    if (codec.Id == methodId)\n    {\n      hasher = codec.CreateHasher();\n      name = codec.Name;\n      break;\n    }\n  }\n\n  #ifdef Z7_EXTERNAL_CODECS\n\n  CHECK_GLOBAL_CODECS\n\n  if (!hasher && _externalCodecs)\n    for (i = 0; i < _externalCodecs->Hashers.Size(); i++)\n    {\n      const CHasherInfoEx &codec = _externalCodecs->Hashers[i];\n      if (codec.Id == methodId)\n      {\n        name = codec.Name;\n        return _externalCodecs->GetHashers->CreateHasher((UInt32)i, &hasher);\n      }\n    }\n\n  #endif\n\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/CreateCoder.h",
    "content": "﻿// CreateCoder.h\n\n#ifndef ZIP7_INC_CREATE_CODER_H\n#define ZIP7_INC_CREATE_CODER_H\n\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../ICoder.h\"\n\n#include \"MethodId.h\"\n\n/*\n  if Z7_EXTERNAL_CODECS is not defined, the code supports only codecs that\n      are statically linked at compile-time and link-time.\n\n  if Z7_EXTERNAL_CODECS is defined, the code supports also codecs from another\n      executable modules, that can be linked dynamically at run-time:\n        - EXE module can use codecs from external DLL files.\n        - DLL module can use codecs from external EXE and DLL files.\n     \n      CExternalCodecs contains information about codecs and interfaces to create them.\n  \n  The order of codecs:\n    1) Internal codecs\n    2) External codecs\n*/\n\n#ifdef Z7_EXTERNAL_CODECS\n\nstruct CCodecInfoEx\n{\n  CMethodId Id;\n  AString Name;\n  UInt32 NumStreams;\n  bool EncoderIsAssigned;\n  bool DecoderIsAssigned;\n  bool IsFilter; // it's unused\n  \n  CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false), IsFilter(false) {}\n};\n\nstruct CHasherInfoEx\n{\n  CMethodId Id;\n  AString Name;\n};\n\n#define Z7_PUBLIC_ISetCompressCodecsInfo_IFEC \\\n    public ISetCompressCodecsInfo,\n#define Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC \\\n    Z7_COM_QI_ENTRY(ISetCompressCodecsInfo)\n#define DECL_ISetCompressCodecsInfo \\\n    Z7_COM7F_IMP(SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo))\n#define IMPL_ISetCompressCodecsInfo2(cls) \\\n    Z7_COM7F_IMF(cls::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo)) \\\n    { COM_TRY_BEGIN _externalCodecs.GetCodecs = compressCodecsInfo; \\\n    return _externalCodecs.Load(); COM_TRY_END }\n#define IMPL_ISetCompressCodecsInfo  IMPL_ISetCompressCodecsInfo2(CHandler)\n\nstruct CExternalCodecs\n{\n  CMyComPtr<ICompressCodecsInfo> GetCodecs;\n  CMyComPtr<IHashers> GetHashers;\n\n  CObjectVector<CCodecInfoEx> Codecs;\n  CObjectVector<CHasherInfoEx> Hashers;\n\n  bool IsSet() const { return GetCodecs != NULL || GetHashers != NULL; }\n\n  HRESULT Load();\n\n  void ClearAndRelease()\n  {\n    Hashers.Clear();\n    Codecs.Clear();\n    GetHashers.Release();\n    GetCodecs.Release();\n  }\n\n  ~CExternalCodecs()\n  {\n    GetHashers.Release();\n    GetCodecs.Release();\n  }\n};\n\nextern CExternalCodecs g_ExternalCodecs;\n\n#define EXTERNAL_CODECS_VARS2   (_externalCodecs.IsSet() ? &_externalCodecs : &g_ExternalCodecs)\n#define EXTERNAL_CODECS_VARS2_L (&_externalCodecs)\n#define EXTERNAL_CODECS_VARS2_G (&g_ExternalCodecs)\n\n#define DECL_EXTERNAL_CODECS_VARS CExternalCodecs _externalCodecs;\n\n#define EXTERNAL_CODECS_VARS   EXTERNAL_CODECS_VARS2,\n#define EXTERNAL_CODECS_VARS_L EXTERNAL_CODECS_VARS2_L,\n#define EXTERNAL_CODECS_VARS_G EXTERNAL_CODECS_VARS2_G,\n\n#define DECL_EXTERNAL_CODECS_LOC_VARS2      const CExternalCodecs *_externalCodecs\n#define DECL_EXTERNAL_CODECS_LOC_VARS       DECL_EXTERNAL_CODECS_LOC_VARS2,\n#define DECL_EXTERNAL_CODECS_LOC_VARS_DECL  DECL_EXTERNAL_CODECS_LOC_VARS2;\n\n#define EXTERNAL_CODECS_LOC_VARS2   _externalCodecs\n#define EXTERNAL_CODECS_LOC_VARS    EXTERNAL_CODECS_LOC_VARS2,\n\n#else\n\n#define Z7_PUBLIC_ISetCompressCodecsInfo_IFEC\n#define Z7_COM_QI_ENTRY_ISetCompressCodecsInfo_IFEC\n#define DECL_ISetCompressCodecsInfo\n#define IMPL_ISetCompressCodecsInfo\n#define EXTERNAL_CODECS_VARS2\n#define DECL_EXTERNAL_CODECS_VARS\n#define EXTERNAL_CODECS_VARS\n#define EXTERNAL_CODECS_VARS_L\n#define EXTERNAL_CODECS_VARS_G\n#define DECL_EXTERNAL_CODECS_LOC_VARS2\n#define DECL_EXTERNAL_CODECS_LOC_VARS\n#define DECL_EXTERNAL_CODECS_LOC_VARS_DECL\n#define EXTERNAL_CODECS_LOC_VARS2\n#define EXTERNAL_CODECS_LOC_VARS\n\n#endif\n\nint FindMethod_Index(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const AString &name,\n    bool encode,\n    CMethodId &methodId,\n    UInt32 &numStreams,\n    bool &isFilter);\n\nbool FindMethod(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId,\n    AString &name);\n\nbool FindHashMethod(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const AString &name,\n    CMethodId &methodId);\n\nvoid GetHashMethods(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CRecordVector<CMethodId> &methods);\n\n\nstruct CCreatedCoder\n{\n  CMyComPtr<ICompressCoder> Coder;\n  CMyComPtr<ICompressCoder2> Coder2;\n  \n  bool IsExternal;\n  bool IsFilter; // = true, if Coder was created from filter\n  UInt32 NumStreams;\n\n  // CCreatedCoder(): IsExternal(false), IsFilter(false), NumStreams(1) {}\n};\n\n\nHRESULT CreateCoder_Index(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    unsigned codecIndex, bool encode,\n    CMyComPtr<ICompressFilter> &filter,\n    CCreatedCoder &cod);\n\nHRESULT CreateCoder_Index(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    unsigned index, bool encode,\n    CCreatedCoder &cod);\n\nHRESULT CreateCoder_Id(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CMyComPtr<ICompressFilter> &filter,\n    CCreatedCoder &cod);\n\nHRESULT CreateCoder_Id(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CCreatedCoder &cod);\n\nHRESULT CreateCoder_Id(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CMyComPtr<ICompressCoder> &coder);\n\nHRESULT CreateFilter(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId, bool encode,\n    CMyComPtr<ICompressFilter> &filter);\n\nHRESULT CreateHasher(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    CMethodId methodId,\n    AString &name,\n    CMyComPtr<IHasher> &hasher);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/FilePathAutoRename.cpp",
    "content": "﻿// FilePathAutoRename.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Windows/FileFind.h\"\n\n#include \"FilePathAutoRename.h\"\n\nusing namespace NWindows;\n\nstatic bool MakeAutoName(const FString &name,\n    const FString &extension, UInt32 value, FString &path)\n{\n  path = name;\n  path.Add_UInt32(value);\n  path += extension;\n  return NFile::NFind::DoesFileOrDirExist(path);\n}\n\nbool AutoRenamePath(FString &path)\n{\n  const int dotPos = path.ReverseFind_Dot();\n  const int slashPos = path.ReverseFind_PathSepar();\n\n  FString name = path;\n  FString extension;\n  if (dotPos > slashPos + 1)\n  {\n    name.DeleteFrom((unsigned)dotPos);\n    extension = path.Ptr((unsigned)dotPos);\n  }\n  name.Add_Char('_');\n  \n  FString temp;\n\n  UInt32 left = 1, right = (UInt32)1 << 30;\n  while (left != right)\n  {\n    const UInt32 mid = (left + right) / 2;\n    if (MakeAutoName(name, extension, mid, temp))\n      left = mid + 1;\n    else\n      right = mid;\n  }\n  return !MakeAutoName(name, extension, right, path);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/FilePathAutoRename.h",
    "content": "﻿// FilePathAutoRename.h\n\n#ifndef ZIP7_INC_FILE_PATH_AUTO_RENAME_H\n#define ZIP7_INC_FILE_PATH_AUTO_RENAME_H\n\n#include \"../../Common/MyString.h\"\n\nbool AutoRenamePath(FString &fullProcessedPath);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/FileStreams.cpp",
    "content": "﻿// FileStreams.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#ifndef _WIN32\n#include <fcntl.h>\n#include <unistd.h>\n#include <errno.h>\n#include <grp.h>\n#include <pwd.h>\n\n/*\ninclusion of <sys/sysmacros.h> by <sys/types.h> is deprecated since glibc 2.25.\nSince glibc 2.3.3, macros have been aliases for three GNU-specific\nfunctions: gnu_dev_makedev(), gnu_dev_major(), and gnu_dev_minor()\n\nWarning in GCC:\nIn the GNU C Library, \"major\" is defined by <sys/sysmacros.h>.\nFor historical compatibility, it is currently defined by\n<sys/types.h> as well, but we plan to remove this soon.\nTo use \"major\", include <sys/sysmacros.h> directly.\nIf you did not intend to use a system-defined macro \"major\",\nyou should undefine it after including <sys/types.h>\n*/\n// for major()/minor():\n#if defined(__APPLE__) || defined(__DragonFly__) || \\\n    defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)\n#include <sys/types.h>\n#else\n#include <sys/sysmacros.h>\n#endif\n\n#endif // _WIN32\n\n#include \"../../Windows/FileFind.h\"\n\n#ifdef Z7_DEVICE_FILE\n#include \"../../../C/Alloc.h\"\n#include \"../../Common/Defs.h\"\n#endif\n\n#include \"../PropID.h\"\n\n#include \"FileStreams.h\"\n\nstatic inline HRESULT GetLastError_HRESULT()\n{\n  DWORD lastError = ::GetLastError();\n  if (lastError == 0)\n    return E_FAIL;\n  return HRESULT_FROM_WIN32(lastError);\n}\n\nstatic inline HRESULT ConvertBoolToHRESULT(bool result)\n{\n  if (result)\n    return S_OK;\n  return GetLastError_HRESULT();\n}\n\n\n#ifdef Z7_DEVICE_FILE\nstatic const UInt32 kClusterSize = 1 << 18;\n#endif\n\nCInFileStream::CInFileStream():\n #ifdef Z7_DEVICE_FILE\n  VirtPos(0),\n  PhyPos(0),\n  Buf(NULL),\n  BufSize(0),\n #endif\n #ifndef _WIN32\n  _uid(0),\n  _gid(0),\n  StoreOwnerId(false),\n  StoreOwnerName(false),\n #endif\n  _info_WasLoaded(false),\n  SupportHardLinks(false),\n  Callback(NULL),\n  CallbackRef(0)\n{\n}\n\nCInFileStream::~CInFileStream()\n{\n  #ifdef Z7_DEVICE_FILE\n  MidFree(Buf);\n  #endif\n\n  if (Callback)\n    Callback->InFileStream_On_Destroy(this, CallbackRef);\n}\n\nZ7_COM7F_IMF(CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  // printf(\"\\nCInFileStream::Read size=%d, VirtPos=%8d\\n\", (unsigned)size, (int)VirtPos);\n\n  #ifdef Z7_FILE_STREAMS_USE_WIN_FILE\n  \n  #ifdef Z7_DEVICE_FILE\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (File.IsDeviceFile)\n  {\n    if (File.SizeDefined)\n    {\n      if (VirtPos >= File.Size)\n        return VirtPos == File.Size ? S_OK : E_FAIL;\n      const UInt64 rem = File.Size - VirtPos;\n      if (size > rem)\n        size = (UInt32)rem;\n    }\n    for (;;)\n    {\n      const UInt32 mask = kClusterSize - 1;\n      const UInt64 mask2 = ~(UInt64)mask;\n      const UInt64 alignedPos = VirtPos & mask2;\n      if (BufSize > 0 && BufStartPos == alignedPos)\n      {\n        const UInt32 pos = (UInt32)VirtPos & mask;\n        if (pos >= BufSize)\n          return S_OK;\n        const UInt32 rem = MyMin(BufSize - pos, size);\n        memcpy(data, Buf + pos, rem);\n        VirtPos += rem;\n        if (processedSize)\n          *processedSize += rem;\n        return S_OK;\n      }\n      \n      bool useBuf = false;\n      if ((VirtPos & mask) != 0 || ((size_t)(ptrdiff_t)data & mask) != 0 )\n        useBuf = true;\n      else\n      {\n        UInt64 end = VirtPos + size;\n        if ((end & mask) != 0)\n        {\n          end &= mask2;\n          if (end <= VirtPos)\n            useBuf = true;\n          else\n            size = (UInt32)(end - VirtPos);\n        }\n      }\n      if (!useBuf)\n        break;\n      if (alignedPos != PhyPos)\n      {\n        UInt64 realNewPosition;\n        const bool result = File.Seek((Int64)alignedPos, FILE_BEGIN, realNewPosition);\n        if (!result)\n          return ConvertBoolToHRESULT(result);\n        PhyPos = realNewPosition;\n      }\n\n      BufStartPos = alignedPos;\n      UInt32 readSize = kClusterSize;\n      if (File.SizeDefined)\n        readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize);\n\n      if (!Buf)\n      {\n        Buf = (Byte *)MidAlloc(kClusterSize);\n        if (!Buf)\n          return E_OUTOFMEMORY;\n      }\n      const bool result = File.Read1(Buf, readSize, BufSize);\n      if (!result)\n        return ConvertBoolToHRESULT(result);\n\n      if (BufSize == 0)\n        return S_OK;\n      PhyPos += BufSize;\n    }\n\n    if (VirtPos != PhyPos)\n    {\n      UInt64 realNewPosition;\n      bool result = File.Seek((Int64)VirtPos, FILE_BEGIN, realNewPosition);\n      if (!result)\n        return ConvertBoolToHRESULT(result);\n      PhyPos = VirtPos = realNewPosition;\n    }\n  }\n  #endif\n\n  UInt32 realProcessedSize;\n  const bool result = File.ReadPart(data, size, realProcessedSize);\n  if (processedSize)\n    *processedSize = realProcessedSize;\n\n  #ifdef Z7_DEVICE_FILE\n  VirtPos += realProcessedSize;\n  PhyPos += realProcessedSize;\n  #endif\n\n  if (result)\n    return S_OK;\n\n  #else // Z7_FILE_STREAMS_USE_WIN_FILE\n  \n  if (processedSize)\n    *processedSize = 0;\n  const ssize_t res = File.read_part(data, (size_t)size);\n  if (res != -1)\n  {\n    if (processedSize)\n      *processedSize = (UInt32)res;\n    return S_OK;\n  }\n  #endif // Z7_FILE_STREAMS_USE_WIN_FILE\n\n  {\n    const DWORD error = ::GetLastError();\n#if 0\n    if (File.IsStdStream && error == ERROR_BROKEN_PIPE)\n      return S_OK; // end of stream\n#endif\n    if (Callback)\n      return Callback->InFileStream_On_Error(CallbackRef, error);\n    if (error == 0)\n      return E_FAIL;\n    return HRESULT_FROM_WIN32(error);\n  }\n}\n\n#ifdef UNDER_CE\nZ7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  size_t s2 = fread(data, 1, size, stdin);\n  int error = ferror(stdin);\n  if (processedSize)\n    *processedSize = s2;\n  if (s2 <= size && error == 0)\n    return S_OK;\n  return E_FAIL;\n}\n#else\nZ7_COM7F_IMF(CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  // printf(\"\\nCStdInFileStream::Read size = %d\\n\", (unsigned)size);\n  #ifdef _WIN32\n  \n  DWORD realProcessedSize;\n  UInt32 sizeTemp = (1 << 20);\n  if (sizeTemp > size)\n    sizeTemp = size;\n  /* in GUI mode : GetStdHandle(STD_INPUT_HANDLE) returns NULL,\n     and it doesn't set LastError.  */\n  /*\n  SetLastError(0);\n  const HANDLE h = GetStdHandle(STD_INPUT_HANDLE);\n  if (!h || h == INVALID_HANDLE_VALUE)\n  {\n    if (processedSize)\n      *processedSize = 0;\n    if (GetLastError() == 0)\n      SetLastError(ERROR_INVALID_HANDLE);\n    return GetLastError_noZero_HRESULT();\n  }\n  */\n  BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);\n\n  /*\n  printf(\"\\nCInFileStream::Read: size=%d, processed=%8d res=%d 4rror=%3d\\n\",\n    (unsigned)size, (int)realProcessedSize,\n    (int)res, GetLastError());\n  */\n\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)\n    return S_OK;\n  return ConvertBoolToHRESULT(res != FALSE);\n  \n  #else\n\n  if (processedSize)\n    *processedSize = 0;\n  ssize_t res;\n  do\n  {\n    res = read(0, data, (size_t)size);\n  }\n  while (res < 0 && (errno == EINTR));\n  if (res == -1)\n    return GetLastError_HRESULT();\n  if (processedSize)\n    *processedSize = (UInt32)res;\n  return S_OK;\n  \n  #endif\n}\n  \n#endif\n\n\n/*\nbool CreateStdInStream(CMyComPtr<ISequentialInStream> &str)\n{\n#if 0\n  CInFileStream *inStreamSpec = new CInFileStream;\n  CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);;\n  if (!inStreamSpec->OpenStdIn())\n    return false;\n  if (!inStreamSpec->File.IsStdPipeStream)\n    str = inStreamLoc.Detach();\n  else\n#endif\n  str = new CStdInFileStream;\n  return true;\n}\n*/\n\n#if 0\nbool CInFileStream::OpenStdIn()\n{\n  _info_WasLoaded = false;\n  // Sleep(100);\n  bool res = File.AttachStdIn();\n  if (!res)\n    return false;\n#if 1\n  CStreamFileProps props;\n  if (GetProps2(&props) != S_OK)\n  {\n    // we can ignore that error\n    return false;\n  }\n  // we can't use Size, because Size can be set for pipe streams for some value.\n  // Seek() sees only current chunk in pipe buffer.\n  // So Seek() can move across only current unread chunk.\n  // But after reading that chunk. it can't move position back.\n  // We need safe check that shows that we can use seek (non-pipe mode)\n  // Is it safe check that shows that pipe mode was used?\n  File.IsStdPipeStream = (props.VolID == 0);\n    // && FILETIME_IsZero(props.CTime)\n    // && FILETIME_IsZero(props.ATime)\n    // && FILETIME_IsZero(props.MTime);\n#endif\n  // printf(\"\\n######## pipe=%d\", (unsigned)File.IsStdPipeStream);\n  return true;\n}\n#endif\n\n\nZ7_COM7F_IMF(CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  /*\n  printf(\"\\nCInFileStream::Seek seekOrigin=%d, offset=%8d, VirtPos=%8d\\n\",\n      (unsigned)seekOrigin, (int)offset, (int)VirtPos);\n  */\n  if (seekOrigin >= 3)\n    return STG_E_INVALIDFUNCTION;\n\n  #ifdef Z7_FILE_STREAMS_USE_WIN_FILE\n\n  #ifdef Z7_DEVICE_FILE\n  if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END))\n  {\n    switch (seekOrigin)\n    {\n      case STREAM_SEEK_SET: break;\n      case STREAM_SEEK_CUR: offset += VirtPos; break;\n      case STREAM_SEEK_END: offset += File.Size; break;\n      default: return STG_E_INVALIDFUNCTION;\n    }\n    if (offset < 0)\n      return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n    VirtPos = (UInt64)offset;\n    if (newPosition)\n      *newPosition = (UInt64)offset;\n    return S_OK;\n  }\n  #endif\n  \n  UInt64 realNewPosition = 0;\n  const bool result = File.Seek(offset, seekOrigin, realNewPosition);\n  const HRESULT hres = ConvertBoolToHRESULT(result);\n\n  /* 21.07: new File.Seek() in 21.07 already returns correct (realNewPosition)\n     in case of error. So we don't need additional code below */\n  // if (!result) { realNewPosition = 0; File.GetPosition(realNewPosition); }\n  \n  #ifdef Z7_DEVICE_FILE\n  PhyPos = VirtPos = realNewPosition;\n  #endif\n\n  if (newPosition)\n    *newPosition = realNewPosition;\n\n  return hres;\n  \n  #else\n  \n  const off_t res = File.seek((off_t)offset, (int)seekOrigin);\n  if (res == -1)\n  {\n    const HRESULT hres = GetLastError_HRESULT();\n    if (newPosition)\n      *newPosition = (UInt64)File.seekToCur();\n    return hres;\n  }\n  if (newPosition)\n    *newPosition = (UInt64)res;\n  return S_OK;\n  \n  #endif\n}\n\nZ7_COM7F_IMF(CInFileStream::GetSize(UInt64 *size))\n{\n  return ConvertBoolToHRESULT(File.GetLength(*size));\n}\n\n#ifdef Z7_FILE_STREAMS_USE_WIN_FILE\n\nZ7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))\n{\n  if (!_info_WasLoaded)\n  {\n    RINOK(ReloadProps())\n  }\n  const BY_HANDLE_FILE_INFORMATION &info = _info;\n  /*\n  BY_HANDLE_FILE_INFORMATION info;\n  if (!File.GetFileInformation(&info))\n    return GetLastError_HRESULT();\n  */\n  {\n    if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;\n    if (cTime) *cTime = info.ftCreationTime;\n    if (aTime) *aTime = info.ftLastAccessTime;\n    if (mTime) *mTime = info.ftLastWriteTime;\n    if (attrib) *attrib = info.dwFileAttributes;\n    return S_OK;\n  }\n}\n\nZ7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props))\n{\n  if (!_info_WasLoaded)\n  {\n    RINOK(ReloadProps())\n  }\n  const BY_HANDLE_FILE_INFORMATION &info = _info;\n  /*\n  BY_HANDLE_FILE_INFORMATION info;\n  if (!File.GetFileInformation(&info))\n    return GetLastError_HRESULT();\n  */\n  {\n    props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;\n    props->VolID = info.dwVolumeSerialNumber;\n    props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;\n    props->FileID_High = 0;\n    props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;\n    props->Attrib = info.dwFileAttributes;\n    props->CTime = info.ftCreationTime;\n    props->ATime = info.ftLastAccessTime;\n    props->MTime = info.ftLastWriteTime;\n    return S_OK;\n  }\n}\n\nZ7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value))\n{\n  if (!_info_WasLoaded)\n  {\n    RINOK(ReloadProps())\n  }\n\n  if (!_info_WasLoaded)\n    return S_OK;\n\n  NWindows::NCOM::CPropVariant prop;\n\n #ifdef Z7_DEVICE_FILE\n  if (File.IsDeviceFile)\n  {\n    switch (propID)\n    {\n      case kpidSize:\n        if (File.SizeDefined)\n          prop = File.Size;\n        break;\n      // case kpidAttrib: prop = (UInt32)0; break;\n      case kpidPosixAttrib:\n      {\n        prop = (UInt32)NWindows::NFile::NFind::NAttributes::\n            Get_PosixMode_From_WinAttrib(0);\n        /* GNU TAR by default can't extract file with MY_LIN_S_IFBLK attribute\n           so we don't use MY_LIN_S_IFBLK here */\n        // prop = (UInt32)(MY_LIN_S_IFBLK | 0600); // for debug\n        break;\n      }\n      /*\n      case kpidDeviceMajor:\n        prop = (UInt32)8; // id for SCSI type device (sda)\n        break;\n      case kpidDeviceMinor:\n        prop = (UInt32)0;\n        break;\n      */\n    }\n  }\n  else\n #endif\n  {\n    switch (propID)\n    {\n      case kpidSize:\n      {\n        const UInt64 size = (((UInt64)_info.nFileSizeHigh) << 32) + _info.nFileSizeLow;\n        prop = size;\n        break;\n      }\n      case kpidAttrib:  prop = (UInt32)_info.dwFileAttributes; break;\n      case kpidCTime:  PropVariant_SetFrom_FiTime(prop, _info.ftCreationTime); break;\n      case kpidATime:  PropVariant_SetFrom_FiTime(prop, _info.ftLastAccessTime); break;\n      case kpidMTime:  PropVariant_SetFrom_FiTime(prop, _info.ftLastWriteTime); break;\n      case kpidPosixAttrib:\n        prop = (UInt32)NWindows::NFile::NFind::NAttributes::\n            Get_PosixMode_From_WinAttrib(_info.dwFileAttributes);\n            // | (UInt32)(1 << 21); // for debug\n        break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CInFileStream::ReloadProps())\n{\n #ifdef Z7_DEVICE_FILE\n  if (File.IsDeviceFile)\n  {\n    memset(&_info, 0, sizeof(_info));\n    if (File.SizeDefined)\n    {\n      _info.nFileSizeHigh = (DWORD)(File.Size >> 32);\n      _info.nFileSizeLow = (DWORD)(File.Size);\n    }\n    _info.nNumberOfLinks = 1;\n    _info_WasLoaded = true;\n    return S_OK;\n  }\n #endif\n  _info_WasLoaded = File.GetFileInformation(&_info);\n  if (!_info_WasLoaded)\n    return GetLastError_HRESULT();\n#ifdef _WIN32\n#if 0\n  printf(\n    \"\\ndwFileAttributes = %8x\"\n    \"\\nftCreationTime   = %8x\"\n    \"\\nftLastAccessTime = %8x\"\n    \"\\nftLastWriteTime  = %8x\"\n    \"\\ndwVolumeSerialNumber  = %8x\"\n    \"\\nnFileSizeHigh  = %8x\"\n    \"\\nnFileSizeLow   = %8x\"\n    \"\\nnNumberOfLinks  = %8x\"\n    \"\\nnFileIndexHigh  = %8x\"\n    \"\\nnFileIndexLow   = %8x \\n\",\n      (unsigned)_info.dwFileAttributes,\n      (unsigned)_info.ftCreationTime.dwHighDateTime,\n      (unsigned)_info.ftLastAccessTime.dwHighDateTime,\n      (unsigned)_info.ftLastWriteTime.dwHighDateTime,\n      (unsigned)_info.dwVolumeSerialNumber,\n      (unsigned)_info.nFileSizeHigh,\n      (unsigned)_info.nFileSizeLow,\n      (unsigned)_info.nNumberOfLinks,\n      (unsigned)_info.nFileIndexHigh,\n      (unsigned)_info.nFileIndexLow);\n#endif\n#endif\n  return S_OK;\n}\n\n\n#elif !defined(_WIN32)\n\nZ7_COM7F_IMF(CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))\n{\n  // printf(\"\\nCInFileStream::GetProps VirtPos = %8d\\n\", (int)VirtPos);\n  if (!_info_WasLoaded)\n  {\n    RINOK(ReloadProps())\n  }\n  const struct stat &st = _info;\n  /*\n  struct stat st;\n  if (File.my_fstat(&st) != 0)\n    return GetLastError_HRESULT();\n  */\n  \n  if (size) *size = (UInt64)st.st_size;\n  if (cTime) FiTime_To_FILETIME (ST_CTIME(st), *cTime);\n  if (aTime) FiTime_To_FILETIME (ST_ATIME(st), *aTime);\n  if (mTime) FiTime_To_FILETIME (ST_MTIME(st), *mTime);\n  if (attrib) *attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode);\n\n  return S_OK;\n}\n\n// #include <stdio.h>\n\nZ7_COM7F_IMF(CInFileStream::GetProps2(CStreamFileProps *props))\n{\n  // printf(\"\\nCInFileStream::GetProps2 VirtPos = %8d\\n\", (int)VirtPos);\n  if (!_info_WasLoaded)\n  {\n    RINOK(ReloadProps())\n  }\n  const struct stat &st = _info;\n  /*\n  struct stat st;\n  if (File.my_fstat(&st) != 0)\n    return GetLastError_HRESULT();\n  */\n\n  props->Size = (UInt64)st.st_size;\n  /*\n    dev_t stat::st_dev:\n       GCC:Linux  long unsigned int :  __dev_t\n       Mac:       int\n  */\n  props->VolID = (UInt64)(Int64)st.st_dev;\n  props->FileID_Low = st.st_ino;\n  props->FileID_High = 0;\n  props->NumLinks = (UInt32)st.st_nlink; // we reduce to UInt32 from (nlink_t) that is (unsigned long)\n  props->Attrib = NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode);\n\n  FiTime_To_FILETIME (ST_CTIME(st), props->CTime);\n  FiTime_To_FILETIME (ST_ATIME(st), props->ATime);\n  FiTime_To_FILETIME (ST_MTIME(st), props->MTime);\n\n  /*\n  printf(\"\\nGetProps2() NumLinks=%d = st_dev=%d st_ino = %d\\n\"\n      , (unsigned)(props->NumLinks)\n      , (unsigned)(st.st_dev)\n      , (unsigned)(st.st_ino)\n      );\n  */\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CInFileStream::GetProperty(PROPID propID, PROPVARIANT *value))\n{\n  // printf(\"\\nCInFileStream::GetProperty VirtPos = %8d propID = %3d\\n\", (int)VirtPos, propID);\n  if (!_info_WasLoaded)\n  {\n    RINOK(ReloadProps())\n  }\n\n  if (!_info_WasLoaded)\n    return S_OK;\n\n  const struct stat &st = _info;\n\n  NWindows::NCOM::CPropVariant prop;\n  {\n    switch (propID)\n    {\n      case kpidSize: prop = (UInt64)st.st_size; break;\n      case kpidAttrib:\n        prop = (UInt32)NWindows::NFile::NFind::Get_WinAttribPosix_From_PosixMode(st.st_mode);\n        break;\n      case kpidCTime:  PropVariant_SetFrom_FiTime(prop, ST_CTIME(st)); break;\n      case kpidATime:  PropVariant_SetFrom_FiTime(prop, ST_ATIME(st)); break;\n      case kpidMTime:  PropVariant_SetFrom_FiTime(prop, ST_MTIME(st)); break;\n      case kpidPosixAttrib: prop = (UInt32)st.st_mode; break;\n\n        #if defined(__APPLE__)\n        #pragma GCC diagnostic push\n        #pragma GCC diagnostic ignored \"-Wsign-conversion\"\n        #endif\n\n      case kpidDeviceMajor:\n      {\n        // printf(\"\\nst.st_rdev = %d\\n\", st.st_rdev);\n        if (S_ISCHR(st.st_mode) ||\n            S_ISBLK(st.st_mode))\n          prop = (UInt32)(major(st.st_rdev)); //  + 1000);\n        // prop = (UInt32)12345678; // for debug\n        break;\n      }\n        \n      case kpidDeviceMinor:\n        if (S_ISCHR(st.st_mode) ||\n            S_ISBLK(st.st_mode))\n          prop = (UInt32)(minor(st.st_rdev)); // + 100);\n        // prop = (UInt32)(st.st_rdev); // for debug\n        // printf(\"\\nst.st_rdev = %d\\n\", st.st_rdev);\n        // prop = (UInt32)123456789; // for debug\n        break;\n\n        #if defined(__APPLE__)\n        #pragma GCC diagnostic pop\n        #endif\n\n      /*\n      case kpidDevice:\n        if (S_ISCHR(st.st_mode) ||\n            S_ISBLK(st.st_mode))\n          prop = (UInt64)(st.st_rdev);\n        break;\n      */\n\n      case kpidUserId:\n      {\n        if (StoreOwnerId)\n          prop = (UInt32)st.st_uid;\n        break;\n      }\n      case kpidGroupId:\n      {\n        if (StoreOwnerId)\n          prop = (UInt32)st.st_gid;\n        break;\n      }\n      case kpidUser:\n      {\n        if (StoreOwnerName)\n        {\n          const uid_t uid = st.st_uid;\n          {\n            if (!OwnerName.IsEmpty() && _uid == uid)\n              prop = OwnerName;\n            else\n            {\n              const passwd *pw = getpwuid(uid);\n              if (pw)\n              {\n                // we can use utf-8 here.\n                // prop = pw->pw_name;\n              }\n            }\n          }\n        }\n        break;\n      }\n      case kpidGroup:\n      {\n        if (StoreOwnerName)\n        {\n          const gid_t gid = st.st_gid;\n          {\n            if (!OwnerGroup.IsEmpty() && _gid == gid)\n              prop = OwnerGroup;\n            else\n            {\n              const group *gr = getgrgid(gid);\n              if (gr)\n              {\n                // we can use utf-8 here.\n                // prop = gr->gr_name;\n              }\n            }\n          }\n        }\n        break;\n      }\n      default: break;\n    }\n  }\n  prop.Detach(value);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CInFileStream::ReloadProps())\n{\n  _info_WasLoaded = (File.my_fstat(&_info) == 0);\n  if (!_info_WasLoaded)\n    return GetLastError_HRESULT();\n  return S_OK;\n}\n\n#endif\n\n\n\n\n//////////////////////////\n// COutFileStream\n\nHRESULT COutFileStream::Close()\n{\n  return ConvertBoolToHRESULT(File.Close());\n}\n\nZ7_COM7F_IMF(COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  #ifdef Z7_FILE_STREAMS_USE_WIN_FILE\n\n  UInt32 realProcessedSize;\n  const bool result = File.Write(data, size, realProcessedSize);\n  ProcessedSize += realProcessedSize;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return ConvertBoolToHRESULT(result);\n  \n  #else\n  \n  if (processedSize)\n    *processedSize = 0;\n  size_t realProcessedSize;\n  const ssize_t res = File.write_full(data, (size_t)size, realProcessedSize);\n  ProcessedSize += realProcessedSize;\n  if (processedSize)\n    *processedSize = (UInt32)realProcessedSize;\n  if (res == -1)\n    return GetLastError_HRESULT();\n  return S_OK;\n  \n  #endif\n}\n  \nZ7_COM7F_IMF(COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  if (seekOrigin >= 3)\n    return STG_E_INVALIDFUNCTION;\n  \n  #ifdef Z7_FILE_STREAMS_USE_WIN_FILE\n\n  UInt64 realNewPosition = 0;\n  const bool result = File.Seek(offset, seekOrigin, realNewPosition);\n  if (newPosition)\n    *newPosition = realNewPosition;\n  return ConvertBoolToHRESULT(result);\n  \n  #else\n  \n  const off_t res = File.seek((off_t)offset, (int)seekOrigin);\n  if (res == -1)\n    return GetLastError_HRESULT();\n  if (newPosition)\n    *newPosition = (UInt64)res;\n  return S_OK;\n  \n  #endif\n}\n\nZ7_COM7F_IMF(COutFileStream::SetSize(UInt64 newSize))\n{\n  return ConvertBoolToHRESULT(File.SetLength_KeepPosition(newSize));\n}\n\nHRESULT COutFileStream::GetSize(UInt64 *size)\n{\n  return ConvertBoolToHRESULT(File.GetLength(*size));\n}\n\n#ifdef UNDER_CE\n\nZ7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  size_t s2 = fwrite(data, 1, size, stdout);\n  if (processedSize)\n    *processedSize = s2;\n  return (s2 == size) ? S_OK : E_FAIL;\n}\n\n#else\n\nZ7_COM7F_IMF(CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n\n  #ifdef _WIN32\n\n  UInt32 realProcessedSize;\n  BOOL res = TRUE;\n  if (size > 0)\n  {\n    // Seems that Windows doesn't like big amounts writing to stdout.\n    // So we limit portions by 32KB.\n    UInt32 sizeTemp = (1 << 15);\n    if (sizeTemp > size)\n      sizeTemp = size;\n    res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),\n        data, sizeTemp, (DWORD *)&realProcessedSize, NULL);\n    _size += realProcessedSize;\n    size -= realProcessedSize;\n    data = (const void *)((const Byte *)data + realProcessedSize);\n    if (processedSize)\n      *processedSize += realProcessedSize;\n  }\n  return ConvertBoolToHRESULT(res != FALSE);\n\n  #else\n  \n  ssize_t res;\n\n  do\n  {\n    res = write(1, data, (size_t)size);\n  }\n  while (res < 0 && (errno == EINTR));\n  \n  if (res == -1)\n    return GetLastError_HRESULT();\n\n  _size += (size_t)res;\n  if (processedSize)\n    *processedSize = (UInt32)res;\n  return S_OK;\n  \n  #endif\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/FileStreams.h",
    "content": "﻿// FileStreams.h\n\n#ifndef ZIP7_INC_FILE_STREAMS_H\n#define ZIP7_INC_FILE_STREAMS_H\n\n#ifdef _WIN32\n#define Z7_FILE_STREAMS_USE_WIN_FILE\n#endif\n\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/MyString.h\"\n\n#include \"../../Windows/FileIO.h\"\n\n#include \"../IStream.h\"\n\n#include \"UniqBlocks.h\"\n\n\nclass CInFileStream;\n\nZ7_PURE_INTERFACES_BEGIN\nDECLARE_INTERFACE(IInFileStream_Callback)\n{\n  virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) = 0;\n  virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) = 0;\n};\nZ7_PURE_INTERFACES_END\n\n\n/*\nZ7_CLASS_IMP_COM_5(\n  CInFileStream\n  , IInStream\n  , IStreamGetSize\n  , IStreamGetProps\n  , IStreamGetProps2\n  , IStreamGetProp\n)\n*/\nZ7_class_final(CInFileStream) :\n  public IInStream,\n  public IStreamGetSize,\n  public IStreamGetProps,\n  public IStreamGetProps2,\n  public IStreamGetProp,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_6(\n      IInStream,\n      ISequentialInStream,\n      IStreamGetSize,\n      IStreamGetProps,\n      IStreamGetProps2,\n      IStreamGetProp)\n\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n  Z7_IFACE_COM7_IMP(IInStream)\npublic:\n  Z7_IFACE_COM7_IMP(IStreamGetSize)\nprivate:\n  Z7_IFACE_COM7_IMP(IStreamGetProps)\npublic:\n  Z7_IFACE_COM7_IMP(IStreamGetProps2)\n  Z7_IFACE_COM7_IMP(IStreamGetProp)\n\nprivate:\n  NWindows::NFile::NIO::CInFile File;\npublic:\n\n  #ifdef Z7_FILE_STREAMS_USE_WIN_FILE\n  \n  #ifdef Z7_DEVICE_FILE\n  UInt64 VirtPos;\n  UInt64 PhyPos;\n  UInt64 BufStartPos;\n  Byte *Buf;\n  UInt32 BufSize;\n  #endif\n\n  #endif\n\n #ifdef _WIN32\n  BY_HANDLE_FILE_INFORMATION _info;\n #else\n  struct stat _info;\n  uid_t _uid; // uid_t can be unsigned or signed int\n  gid_t _gid;\n  UString OwnerName;\n  UString OwnerGroup;\n  bool StoreOwnerId;\n  bool StoreOwnerName;\n #endif\n\n  bool _info_WasLoaded;\n  bool SupportHardLinks;\n  IInFileStream_Callback *Callback;\n  UINT_PTR CallbackRef;\n\n  CInFileStream();\n  ~CInFileStream();\n    \n  void Set_PreserveATime(bool v)\n  {\n    File.PreserveATime = v;\n  }\n\n  bool GetLength(UInt64 &length) const throw()\n  {\n    return File.GetLength(length);\n  }\n\n#if 0\n  bool OpenStdIn();\n#endif\n  \n  bool Open(CFSTR fileName)\n  {\n    _info_WasLoaded = false;\n    return File.Open(fileName);\n  }\n  \n  bool OpenShared(CFSTR fileName, bool shareForWrite)\n  {\n    _info_WasLoaded = false;\n    return File.OpenShared(fileName, shareForWrite);\n  }\n};\n\n// bool CreateStdInStream(CMyComPtr<ISequentialInStream> &str);\n\nZ7_CLASS_IMP_NOQIB_1(\n  CStdInFileStream\n  , ISequentialInStream\n)\n};\n\n\nZ7_CLASS_IMP_COM_1(\n  COutFileStream\n  , IOutStream\n)\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\npublic:\n\n  NWindows::NFile::NIO::COutFile File;\n\n  bool Create_NEW(CFSTR fileName)\n  {\n    ProcessedSize = 0;\n    return File.Create_NEW(fileName);\n  }\n\n  bool Create_ALWAYS(CFSTR fileName)\n  {\n    ProcessedSize = 0;\n    return File.Create_ALWAYS(fileName);\n  }\n\n  bool Open_EXISTING(CFSTR fileName)\n  {\n    ProcessedSize = 0;\n    return File.Open_EXISTING(fileName);\n  }\n\n  bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways)\n  {\n    ProcessedSize = 0;\n    return File.Create_ALWAYS_or_Open_ALWAYS(fileName, createAlways);\n  }\n\n  HRESULT Close();\n  \n  UInt64 ProcessedSize;\n\n  bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)\n  {\n    return File.SetTime(cTime, aTime, mTime);\n  }\n  bool SetMTime(const CFiTime *mTime) {  return File.SetMTime(mTime); }\n\n  bool SeekToBegin_bool()\n  {\n    #ifdef Z7_FILE_STREAMS_USE_WIN_FILE\n    return File.SeekToBegin();\n    #else\n    return File.seekToBegin() == 0;\n    #endif\n  }\n\n  HRESULT GetSize(UInt64 *size);\n};\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CStdOutFileStream\n  , ISequentialOutStream\n)\n  UInt64 _size;\npublic:\n  UInt64 GetSize() const { return _size; }\n  CStdOutFileStream(): _size(0) {}\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/FilterCoder.cpp",
    "content": "﻿// FilterCoder.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../Common/Defs.h\"\n\n#include \"FilterCoder.h\"\n#include \"StreamUtils.h\"\n\n#ifdef _WIN32\n  #define alignedMidBuffer_Alloc g_MidAlloc\n#else\n  #define alignedMidBuffer_Alloc g_AlignedAlloc\n#endif\n\nCAlignedMidBuffer::~CAlignedMidBuffer()\n{\n  ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf);\n}\n\nvoid CAlignedMidBuffer::AllocAligned(size_t size)\n{\n  ISzAlloc_Free(&alignedMidBuffer_Alloc, _buf);\n  _buf = (Byte *)ISzAlloc_Alloc(&alignedMidBuffer_Alloc, size);\n}\n\n/*\n  AES filters need 16-bytes alignment for HARDWARE-AES instructions.\n  So we call IFilter::Filter(, size), where (size != 16 * N) only for last data block.\n\n  AES-CBC filters need data size aligned for 16-bytes.\n  So the encoder can add zeros to the end of original stream.\n\n  Some filters (BCJ and others) don't process data at the end of stream in some cases.\n  So the encoder and decoder write such last bytes without change.\n\n  Most filters process all data, if we send aligned size to filter.\n     But  BCJ filter can process up 4 bytes less than sent size.\n     And ARMT filter can process    2 bytes less than sent size.\n*/\n\n\nstatic const UInt32 kBufSize = 1 << 21;\n\nZ7_COM7F_IMF(CFilterCoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; }\nZ7_COM7F_IMF(CFilterCoder::SetOutBufSize(UInt32 , UInt32 size)) { _outBufSize = size; return S_OK; }\n\nHRESULT CFilterCoder::Alloc()\n{\n  UInt32 size = MyMin(_inBufSize, _outBufSize);\n  /* minimal bufSize is 16 bytes for AES and IA64 filter.\n     bufSize for AES must be aligned for 16 bytes.\n     We use (1 << 12) min size to support future aligned filters. */\n  const UInt32 kMinSize = 1 << 12;\n  size &= ~(UInt32)(kMinSize - 1);\n  if (size < kMinSize)\n    size = kMinSize;\n  // size = (1 << 12); // + 117; // for debug\n  if (!_buf || _bufSize != size)\n  {\n    AllocAligned(size);\n    if (!_buf)\n      return E_OUTOFMEMORY;\n    _bufSize = size;\n  }\n  return S_OK;\n}\n\nHRESULT CFilterCoder::Init_and_Alloc()\n{\n  RINOK(Filter->Init())\n  return Alloc();\n}\n\nCFilterCoder::CFilterCoder(bool encodeMode):\n    _bufSize(0),\n    _inBufSize(kBufSize),\n    _outBufSize(kBufSize),\n    _encodeMode(encodeMode),\n    _outSize_Defined(false),\n    _outSize(0),\n    _nowPos64(0)\n  {}\n\n\nZ7_COM7F_IMF(CFilterCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  RINOK(Init_and_Alloc())\n\n  /*\n     It's expected that BCJ/ARMT filter can process up to 4 bytes less\n     than sent data size. For such BCJ/ARMT cases with non-filtered data we:\n       - write some filtered data to output stream\n       - move non-written data (filtered and non-filtered data) to start of buffer\n       - read more new data from input stream to position after end of non-filtered data\n       - call Filter() for concatenated data in buffer.\n\n     For all cases, even for cases with partial filtering (BCJ/ARMT),\n     we try to keep real/virtual alignment for all operations\n       (memmove, Read(), Filter(), Write()).\n     We use (kAlignSize=64) alignmnent that is larger than (16-bytes)\n     required for AES filter alignment.\n\n     AES-CBC uses 16-bytes blocks, that is simple case for processing here,\n     if we call Filter() for aligned size for all calls except of last call (last block).\n     And now there are no filters that use blocks with non-power2 size,\n     but we try to support such non-power2 filters too here at Code().\n  */\n    \n  UInt64 prev = 0;\n  UInt64 nowPos64 = 0;\n  bool inputFinished = false;\n  UInt32 readPos = 0;\n  UInt32 filterPos = 0;\n\n  while (!outSize || nowPos64 < *outSize)\n  {\n    HRESULT hres = S_OK;\n    if (!inputFinished)\n    {\n      size_t processedSize = _bufSize - readPos;\n      /* for AES filters we need at least max(16, kAlignSize) bytes in buffer.\n         But we try to read full buffer to reduce the number of Filter() and Write() calls.\n      */\n      hres = ReadStream(inStream, _buf + readPos, &processedSize);\n      readPos += (UInt32)processedSize;\n      inputFinished = (readPos != _bufSize);\n      if (hres != S_OK)\n      {\n        // do we need to stop encoding after reading error?\n        // if (_encodeMode) return hres;\n        inputFinished = true;\n      }\n    }\n\n    if (readPos == 0)\n      return hres;\n\n    /* we set (needMoreInput = true), if it's block-filter (like AES-CBC)\n         that needs more data for current block filtering:\n       We read full input buffer with Read(), and _bufSize is aligned,\n       So the possible cases when we set (needMoreInput = true) are:\n         1) decode : filter needs more data after the end of input stream.\n           another cases are possible for non-power2-block-filter,\n           because buffer size is not aligned for filter_non_power2_block_size:\n         2) decode/encode : filter needs more data from non-finished input stream\n         3) encode        : filter needs more space for zeros after the end of input stream\n    */\n    bool needMoreInput = false;\n\n    while (readPos != filterPos)\n    {\n      /* Filter() is allowed to process part of data.\n         Here we use the loop to filter as max as possible.\n         when we call Filter(data, size):\n         if (size < 16), AES-CTR filter uses internal 16-byte buffer.\n         new (since v23.00) AES-CTR filter allows (size < 16) for non-last block,\n         but it will work less efficiently than calls with aligned (size).\n         We still support old (before v23.00) AES-CTR filters here.\n         We have aligned (size) for AES-CTR, if it's not last block.\n         We have aligned (readPos) for any filter, if (!inputFinished).\n         We also meet the requirements for (data) pointer in Filter() call:\n         {\n           (virtual_stream_offset % aligment_size) == (data_ptr % aligment_size)\n           (aligment_size == 2^N)\n           (aligment_size  >= 16)\n         }\n      */\n      const UInt32 cur = Filter->Filter(_buf + filterPos, readPos - filterPos);\n      if (cur == 0)\n        break;\n      const UInt32 f = filterPos + cur;\n      if (cur > readPos - filterPos)\n      {\n        // AES-CBC\n        if (hres != S_OK)\n          break;\n\n        if (!_encodeMode\n            || cur > _bufSize - filterPos\n            || !inputFinished)\n        {\n          /* (cur > _bufSize - filterPos) is unexpected for AES filter, if _bufSize is multiply of 16.\n             But we support this case, if some future filter will use block with non-power2-size.\n          */\n          needMoreInput = true;\n          break;\n        }\n\n        /* (_encodeMode && inputFinished).\n           We add zero bytes as pad in current block after the end of read data. */\n        Byte *buf = _buf;\n        do\n          buf[readPos] = 0;\n        while (++readPos != f);\n        // (readPos) now is (size_of_real_input_data + size_of_zero_pad)\n        if (cur != Filter->Filter(buf + filterPos, cur))\n          return E_FAIL;\n      }\n      filterPos = f;\n    }\n\n    UInt32 size = filterPos;\n    if (hres == S_OK)\n    {\n      /* If we need more Read() or Filter() calls, then we need to Write()\n         some data and move unwritten data to get additional space in buffer.\n         We try to keep alignment for data moves, Read(), Filter() and Write() calls.\n      */\n      const UInt32 kAlignSize = 1 << 6;\n      const UInt32 alignedFiltered = filterPos & ~(kAlignSize - 1);\n      if (inputFinished)\n      {\n        if (!needMoreInput)\n          size = readPos; // for risc/bcj filters in last block we write data after filterPos.\n        else if (_encodeMode)\n          size = alignedFiltered; // for non-power2-block-encode-filter\n      }\n      else\n        size = alignedFiltered;\n    }\n\n    {\n      UInt32 writeSize = size;\n      if (outSize)\n      {\n        const UInt64 rem = *outSize - nowPos64;\n        if (writeSize > rem)\n          writeSize = (UInt32)rem;\n      }\n      RINOK(WriteStream(outStream, _buf, writeSize))\n      nowPos64 += writeSize;\n    }\n\n    if (hres != S_OK)\n      return hres;\n\n    if (inputFinished)\n    {\n      if (readPos == size)\n        return hres;\n      if (!_encodeMode)\n      {\n        // block-decode-filter (AES-CBS) has non-full last block\n        // we don't want unaligned data move for more iterations with this error case.\n        return S_FALSE;\n      }\n    }\n\n    if (size == 0)\n    {\n      // it's unexpected that we have no any move in this iteration.\n      return E_FAIL;\n    }\n    // if (size != 0)\n    {\n      if (filterPos < size)\n        return E_FAIL; // filterPos = 0; else\n      filterPos -= size;\n      readPos -= size;\n      if (readPos != 0)\n        memmove(_buf, _buf + size, readPos);\n    }\n    // printf(\"\\nnowPos64=%x, readPos=%x, filterPos=%x\\n\", (unsigned)nowPos64, (unsigned)readPos, (unsigned)filterPos);\n\n    if (progress && (nowPos64 - prev) >= (1 << 22))\n    {\n      prev = nowPos64;\n      RINOK(progress->SetRatioInfo(&nowPos64, &nowPos64))\n    }\n  }\n\n  return S_OK;\n}\n\n\n\n// ---------- Write to Filter ----------\n\nZ7_COM7F_IMF(CFilterCoder::SetOutStream(ISequentialOutStream *outStream))\n{\n  _outStream = outStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CFilterCoder::ReleaseOutStream())\n{\n  _outStream.Release();\n  return S_OK;\n}\n\nHRESULT CFilterCoder::Flush2()\n{\n  while (_convSize != 0)\n  {\n    UInt32 num = _convSize;\n    if (_outSize_Defined)\n    {\n      const UInt64 rem = _outSize - _nowPos64;\n      if (num > rem)\n        num = (UInt32)rem;\n      if (num == 0)\n        return k_My_HRESULT_WritingWasCut;\n    }\n    \n    UInt32 processed = 0;\n    const HRESULT res = _outStream->Write(_buf + _convPos, num, &processed);\n    if (processed == 0)\n      return res != S_OK ? res : E_FAIL;\n    \n    _convPos += processed;\n    _convSize -= processed;\n    _nowPos64 += processed;\n    RINOK(res)\n  }\n    \n  const UInt32 convPos = _convPos;\n  if (convPos != 0)\n  {\n    const UInt32 num = _bufPos - convPos;\n    Byte *buf = _buf;\n    for (UInt32 i = 0; i < num; i++)\n      buf[i] = buf[convPos + i];\n    _bufPos = num;\n    _convPos = 0;\n  }\n    \n  return S_OK;\n}\n\nZ7_COM7F_IMF(CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  \n  while (size != 0)\n  {\n    RINOK(Flush2())\n\n    // _convSize is 0\n    // _convPos is 0\n    // _bufPos is small\n\n    if (_bufPos != _bufSize)\n    {\n      UInt32 num = MyMin(size, _bufSize - _bufPos);\n      memcpy(_buf + _bufPos, data, num);\n      size -= num;\n      data = (const Byte *)data + num;\n      if (processedSize)\n        *processedSize += num;\n      _bufPos += num;\n      if (_bufPos != _bufSize)\n        continue;\n    }\n\n    // _bufPos == _bufSize\n    _convSize = Filter->Filter(_buf, _bufPos);\n    \n    if (_convSize == 0)\n      break;\n    if (_convSize > _bufPos)\n    {\n      // that case is not possible.\n      _convSize = 0;\n      return E_FAIL;\n    }\n  }\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CFilterCoder::OutStreamFinish())\n{\n  for (;;)\n  {\n    RINOK(Flush2())\n    if (_bufPos == 0)\n      break;\n    const UInt32 convSize = Filter->Filter(_buf, _bufPos);\n    _convSize = convSize;\n    UInt32 bufPos = _bufPos;\n    if (convSize == 0)\n      _convSize = bufPos;\n    else if (convSize > bufPos)\n    {\n      // AES\n      if (convSize > _bufSize)\n      {\n        _convSize = 0;\n        return E_FAIL;\n      }\n      if (!_encodeMode)\n      {\n        _convSize = 0;\n        return S_FALSE;\n      }\n      Byte *buf = _buf;\n      for (; bufPos < convSize; bufPos++)\n        buf[bufPos] = 0;\n      _bufPos = bufPos;\n      _convSize = Filter->Filter(_buf, bufPos);\n      if (_convSize != _bufPos)\n        return E_FAIL;\n    }\n  }\n  \n  CMyComPtr<IOutStreamFinish> finish;\n  _outStream.QueryInterface(IID_IOutStreamFinish, &finish);\n  if (finish)\n    return finish->OutStreamFinish();\n  return S_OK;\n}\n\n// ---------- Init functions ----------\n\nZ7_COM7F_IMF(CFilterCoder::InitEncoder())\n{\n  InitSpecVars();\n  return Init_and_Alloc();\n}\n\nHRESULT CFilterCoder::Init_NoSubFilterInit()\n{\n  InitSpecVars();\n  return Alloc();\n}\n\nZ7_COM7F_IMF(CFilterCoder::SetOutStreamSize(const UInt64 *outSize))\n{\n  InitSpecVars();\n  if (outSize)\n  {\n    _outSize = *outSize;\n    _outSize_Defined = true;\n  }\n  return Init_and_Alloc();\n}\n\n// ---------- Read from Filter ----------\n\nZ7_COM7F_IMF(CFilterCoder::SetInStream(ISequentialInStream *inStream))\n{\n  _inStream = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CFilterCoder::ReleaseInStream())\n{\n  _inStream.Release();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  \n  while (size != 0)\n  {\n    if (_convSize != 0)\n    {\n      if (size > _convSize)\n        size = _convSize;\n      if (_outSize_Defined)\n      {\n        const UInt64 rem = _outSize - _nowPos64;\n        if (size > rem)\n          size = (UInt32)rem;\n      }\n      memcpy(data, _buf + _convPos, size);\n      _convPos += size;\n      _convSize -= size;\n      _nowPos64 += size;\n      if (processedSize)\n        *processedSize = size;\n      break;\n    }\n  \n    const UInt32 convPos = _convPos;\n    if (convPos != 0)\n    {\n      const UInt32 num = _bufPos - convPos;\n      Byte *buf = _buf;\n      for (UInt32 i = 0; i < num; i++)\n        buf[i] = buf[convPos + i];\n      _bufPos = num;\n      _convPos = 0;\n    }\n    \n    {\n      size_t readSize = _bufSize - _bufPos;\n      const HRESULT res = ReadStream(_inStream, _buf + _bufPos, &readSize);\n      _bufPos += (UInt32)readSize;\n      RINOK(res)\n    }\n    \n    const UInt32 convSize = Filter->Filter(_buf, _bufPos);\n    _convSize = convSize;\n    \n    UInt32 bufPos = _bufPos;\n\n    if (convSize == 0)\n    {\n      if (bufPos == 0)\n        break;\n      // BCJ\n      _convSize = bufPos;\n      continue;\n    }\n    \n    if (convSize > bufPos)\n    {\n      // AES\n      if (convSize > _bufSize)\n        return E_FAIL;\n      if (!_encodeMode)\n        return S_FALSE;\n      Byte *buf = _buf;\n      do\n        buf[bufPos] = 0;\n      while (++bufPos != convSize);\n      _bufPos = bufPos;\n      _convSize = Filter->Filter(_buf, convSize);\n      if (_convSize != _bufPos)\n        return E_FAIL;\n    }\n  }\n \n  return S_OK;\n}\n\n\n#ifndef Z7_NO_CRYPTO\n\nZ7_COM7F_IMF(CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size))\n  { return _setPassword->CryptoSetPassword(data, size); }\n\nZ7_COM7F_IMF(CFilterCoder::SetKey(const Byte *data, UInt32 size))\n  { return _cryptoProperties->SetKey(data, size); }\n\nZ7_COM7F_IMF(CFilterCoder::SetInitVector(const Byte *data, UInt32 size))\n  { return _cryptoProperties->SetInitVector(data, size); }\n\n#endif\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nZ7_COM7F_IMF(CFilterCoder::SetCoderProperties(const PROPID *propIDs,\n    const PROPVARIANT *properties, UInt32 numProperties))\n  { return _setCoderProperties->SetCoderProperties(propIDs, properties, numProperties); }\n\nZ7_COM7F_IMF(CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream))\n  { return _writeCoderProperties->WriteCoderProperties(outStream); }\n\nZ7_COM7F_IMF(CFilterCoder::SetCoderPropertiesOpt(const PROPID *propIDs,\n    const PROPVARIANT *properties, UInt32 numProperties))\n  { return _setCoderPropertiesOpt->SetCoderPropertiesOpt(propIDs, properties, numProperties); }\n\n/*\nZ7_COM7F_IMF(CFilterCoder::ResetSalt()\n  { return _cryptoResetSalt->ResetSalt(); }\n*/\n\nZ7_COM7F_IMF(CFilterCoder::ResetInitVector())\n  { return _cryptoResetInitVector->ResetInitVector(); }\n\n#endif\n\n\nZ7_COM7F_IMF(CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n  { return _setDecoderProperties2->SetDecoderProperties2(data, size); }\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/FilterCoder.h",
    "content": "﻿// FilterCoder.h\n\n#ifndef ZIP7_INC_FILTER_CODER_H\n#define ZIP7_INC_FILTER_CODER_H\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../../Common/MyCom.h\"\n#include \"../ICoder.h\"\n\n#ifndef Z7_NO_CRYPTO\n#include \"../IPassword.h\"\n#endif\n\n#define Z7_COM_QI_ENTRY_AG(i, sub0, sub) else if (iid == IID_ ## i) \\\n  { if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \\\n    *outObject = (void *)(i *)this; }\n\n\nstruct CAlignedMidBuffer\n{\n  Byte *_buf;\n\n  CAlignedMidBuffer(): _buf(NULL) {}\n  ~CAlignedMidBuffer();\n  void AllocAligned(size_t size);\n};\n\n\nclass CFilterCoder Z7_final :\n  public ICompressCoder,\n  \n  public ICompressSetOutStreamSize,\n  public ICompressInitEncoder,\n \n  public ICompressSetInStream,\n  public ISequentialInStream,\n  \n  public ICompressSetOutStream,\n  public ISequentialOutStream,\n  public IOutStreamFinish,\n  \n  public ICompressSetBufSize,\n\n  #ifndef Z7_NO_CRYPTO\n  public ICryptoSetPassword,\n  public ICryptoProperties,\n  #endif\n  \n  #ifndef Z7_EXTRACT_ONLY\n  public ICompressSetCoderProperties,\n  public ICompressWriteCoderProperties,\n  public ICompressSetCoderPropertiesOpt,\n  // public ICryptoResetSalt,\n  public ICryptoResetInitVector,\n  #endif\n  \n  public ICompressSetDecoderProperties2,\n  public CMyUnknownImp,\n  public CAlignedMidBuffer\n{\n  UInt32 _bufSize;\n  UInt32 _inBufSize;\n  UInt32 _outBufSize;\n\n  bool _encodeMode;\n  bool _outSize_Defined;\n  UInt64 _outSize;\n  UInt64 _nowPos64;\n\n  CMyComPtr<ISequentialInStream> _inStream;\n  CMyComPtr<ISequentialOutStream> _outStream;\n  UInt32 _bufPos;\n  UInt32 _convPos;    // current pos in buffer for converted data\n  UInt32 _convSize;   // size of converted data starting from _convPos\n  \n  void InitSpecVars()\n  {\n    _bufPos = 0;\n    _convPos = 0;\n    _convSize = 0;\n\n    _outSize_Defined = false;\n    _outSize = 0;\n    _nowPos64 = 0;\n  }\n\n  HRESULT Alloc();\n  HRESULT Init_and_Alloc();\n  HRESULT Flush2();\n\n  #ifndef Z7_NO_CRYPTO\n  CMyComPtr<ICryptoSetPassword> _setPassword;\n  CMyComPtr<ICryptoProperties> _cryptoProperties;\n  #endif\n\n  #ifndef Z7_EXTRACT_ONLY\n  CMyComPtr<ICompressSetCoderProperties> _setCoderProperties;\n  CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;\n  CMyComPtr<ICompressSetCoderPropertiesOpt> _setCoderPropertiesOpt;\n  // CMyComPtr<ICryptoResetSalt> _cryptoResetSalt;\n  CMyComPtr<ICryptoResetInitVector> _cryptoResetInitVector;\n  #endif\n\n  CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties2;\n\npublic:\n  CMyComPtr<ICompressFilter> Filter;\n\n  CFilterCoder(bool encodeMode);\n\n  struct C_InStream_Releaser\n  {\n    CFilterCoder *FilterCoder;\n    C_InStream_Releaser(): FilterCoder(NULL) {}\n    ~C_InStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }\n  };\n  \n  struct C_OutStream_Releaser\n  {\n    CFilterCoder *FilterCoder;\n    C_OutStream_Releaser(): FilterCoder(NULL) {}\n    ~C_OutStream_Releaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }\n  };\n\n  struct C_Filter_Releaser\n  {\n    CFilterCoder *FilterCoder;\n    C_Filter_Releaser(): FilterCoder(NULL) {}\n    ~C_Filter_Releaser() { if (FilterCoder) FilterCoder->Filter.Release(); }\n  };\n  \nprivate:\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n\n    Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)\n    Z7_COM_QI_ENTRY(ICompressInitEncoder)\n    \n    Z7_COM_QI_ENTRY(ICompressSetInStream)\n    Z7_COM_QI_ENTRY(ISequentialInStream)\n    \n    Z7_COM_QI_ENTRY(ICompressSetOutStream)\n    Z7_COM_QI_ENTRY(ISequentialOutStream)\n    Z7_COM_QI_ENTRY(IOutStreamFinish)\n    \n    Z7_COM_QI_ENTRY(ICompressSetBufSize)\n\n    #ifndef Z7_NO_CRYPTO\n    Z7_COM_QI_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)\n    Z7_COM_QI_ENTRY_AG(ICryptoProperties, Filter, _cryptoProperties)\n    #endif\n\n    #ifndef Z7_EXTRACT_ONLY\n    Z7_COM_QI_ENTRY_AG(ICompressSetCoderProperties, Filter, _setCoderProperties)\n    Z7_COM_QI_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)\n    Z7_COM_QI_ENTRY_AG(ICompressSetCoderPropertiesOpt, Filter, _setCoderPropertiesOpt)\n    // Z7_COM_QI_ENTRY_AG(ICryptoResetSalt, Filter, _cryptoResetSalt)\n    Z7_COM_QI_ENTRY_AG(ICryptoResetInitVector, Filter, _cryptoResetInitVector)\n    #endif\n\n    Z7_COM_QI_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties2)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n  \npublic:\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n  Z7_IFACE_COM7_IMP(ICompressInitEncoder)\n  Z7_IFACE_COM7_IMP(ICompressSetInStream)\nprivate:\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetOutStream)\nprivate:\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\npublic:\n  Z7_IFACE_COM7_IMP(IOutStreamFinish)\nprivate:\n  \n  Z7_IFACE_COM7_IMP(ICompressSetBufSize)\n\n  #ifndef Z7_NO_CRYPTO\n  Z7_IFACE_COM7_IMP(ICryptoSetPassword)\n  Z7_IFACE_COM7_IMP(ICryptoProperties)\n  #endif\n  \n  #ifndef Z7_EXTRACT_ONLY\n  Z7_IFACE_COM7_IMP(ICompressSetCoderProperties)\n  Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties)\n  Z7_IFACE_COM7_IMP(ICompressSetCoderPropertiesOpt)\n  // Z7_IFACE_COM7_IMP(ICryptoResetSalt)\n  Z7_IFACE_COM7_IMP(ICryptoResetInitVector)\n  #endif\n  \npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\n  \n  HRESULT Init_NoSubFilterInit();\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/InBuffer.cpp",
    "content": "﻿// InBuffer.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"InBuffer.h\"\n\nCInBufferBase::CInBufferBase() throw():\n  _buf(NULL),\n  _bufLim(NULL),\n  _bufBase(NULL),\n  _stream(NULL),\n  _processedSize(0),\n  _bufSize(0),\n  _wasFinished(false),\n  NumExtraBytes(0)\n{}\n\nbool CInBuffer::Create(size_t bufSize) throw()\n{\n  const unsigned kMinBlockSize = 1;\n  if (bufSize < kMinBlockSize)\n    bufSize = kMinBlockSize;\n  if (_bufBase != NULL && _bufSize == bufSize)\n    return true;\n  Free();\n  _bufSize = bufSize;\n  _bufBase = (Byte *)::MidAlloc(bufSize);\n  return (_bufBase != NULL);\n}\n\nvoid CInBuffer::Free() throw()\n{\n  ::MidFree(_bufBase);\n  _bufBase = NULL;\n}\n\nvoid CInBufferBase::Init() throw()\n{\n  _processedSize = 0;\n  _buf = _bufBase;\n  _bufLim = _buf;\n  _wasFinished = false;\n  #ifdef Z7_NO_EXCEPTIONS\n  ErrorCode = S_OK;\n  #endif\n  NumExtraBytes = 0;\n}\n\nbool CInBufferBase::ReadBlock()\n{\n  #ifdef Z7_NO_EXCEPTIONS\n  if (ErrorCode != S_OK)\n    return false;\n  #endif\n  if (_wasFinished)\n    return false;\n  _processedSize += (size_t)(_buf - _bufBase);\n  _buf = _bufBase;\n  _bufLim = _bufBase;\n  UInt32 processed;\n  // FIX_ME: we can improve it to support (_bufSize >= (1 << 32))\n  const HRESULT result = _stream->Read(_bufBase, (UInt32)_bufSize, &processed);\n  #ifdef Z7_NO_EXCEPTIONS\n  ErrorCode = result;\n  #else\n  if (result != S_OK)\n    throw CInBufferException(result);\n  #endif\n  _bufLim = _buf + processed;\n  _wasFinished = (processed == 0);\n  return !_wasFinished;\n}\n\nbool CInBufferBase::ReadByte_FromNewBlock(Byte &b)\n{\n  if (!ReadBlock())\n  {\n    // 22.00: we don't increment (NumExtraBytes) here\n    // NumExtraBytes++;\n    b = 0xFF;\n    return false;\n  }\n  b = *_buf++;\n  return true;\n}\n\nByte CInBufferBase::ReadByte_FromNewBlock()\n{\n  if (!ReadBlock())\n  {\n    NumExtraBytes++;\n    return 0xFF;\n  }\n  return *_buf++;\n}\n\nsize_t CInBufferBase::ReadBytesPart(Byte *buf, size_t size)\n{\n  if (size == 0)\n    return 0;\n  size_t rem = (size_t)(_bufLim - _buf);\n  if (rem == 0)\n  {\n    if (!ReadBlock())\n      return 0;\n    rem = (size_t)(_bufLim - _buf);\n  }\n  if (size > rem)\n      size = rem;\n  memcpy(buf, _buf, size);\n  _buf += size;\n  return size;\n}\n\nsize_t CInBufferBase::ReadBytes(Byte *buf, size_t size)\n{\n  size_t num = 0;\n  for (;;)\n  {\n    const size_t rem = (size_t)(_bufLim - _buf);\n    if (size <= rem)\n    {\n      if (size != 0)\n      {\n        memcpy(buf, _buf, size);\n        _buf += size;\n        num += size;\n      }\n      return num;\n    }\n    if (rem != 0)\n    {\n      memcpy(buf, _buf, rem);\n      _buf += rem;\n      buf += rem;\n      num += rem;\n      size -= rem;\n    }\n    if (!ReadBlock())\n      return num;\n  }\n\n  /*\n  if ((size_t)(_bufLim - _buf) >= size)\n  {\n    const Byte *src = _buf;\n    for (size_t i = 0; i < size; i++)\n      buf[i] = src[i];\n    _buf += size;\n    return size;\n  }\n  for (size_t i = 0; i < size; i++)\n  {\n    if (_buf >= _bufLim)\n      if (!ReadBlock())\n        return i;\n    buf[i] = *_buf++;\n  }\n  return size;\n  */\n}\n\nsize_t CInBufferBase::Skip(size_t size)\n{\n  size_t processed = 0;\n  for (;;)\n  {\n    const size_t rem = (size_t)(_bufLim - _buf);\n    if (rem >= size)\n    {\n      _buf += size;\n      return processed + size;\n    }\n    _buf += rem;\n    processed += rem;\n    size -= rem;\n    if (!ReadBlock())\n      return processed;\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/InBuffer.h",
    "content": "﻿// InBuffer.h\n\n#ifndef ZIP7_INC_IN_BUFFER_H\n#define ZIP7_INC_IN_BUFFER_H\n\n#include \"../../Common/MyException.h\"\n#include \"../IStream.h\"\n\n#ifndef Z7_NO_EXCEPTIONS\nstruct CInBufferException: public CSystemException\n{\n  CInBufferException(HRESULT errorCode): CSystemException(errorCode) {}\n};\n#endif\n\nclass CInBufferBase\n{\nprotected:\n  Byte *_buf;\n  Byte *_bufLim;\n  Byte *_bufBase;\n\n  ISequentialInStream *_stream;\n  UInt64 _processedSize;\n  size_t _bufSize; // actually it's number of Bytes for next read. The buf can be larger\n                   // only up to 32-bits values now are supported!\n  bool _wasFinished;\n\n  bool ReadBlock();\n  bool ReadByte_FromNewBlock(Byte &b);\n  Byte ReadByte_FromNewBlock();\n\npublic:\n  #ifdef Z7_NO_EXCEPTIONS\n  HRESULT ErrorCode;\n  #endif\n  UInt32 NumExtraBytes;\n\n  CInBufferBase() throw();\n\n  // the size of portion of data in real stream that was already read from this object\n  // it doesn't include unused data in buffer\n  // it doesn't include virtual Extra bytes after the end of real stream data\n  UInt64 GetStreamSize() const { return _processedSize + (size_t)(_buf - _bufBase); }\n  \n  // the size of virtual data that was read from this object\n  // it doesn't include unused data in buffers\n  // it includes any virtual Extra bytes after the end of real data\n  UInt64 GetProcessedSize() const { return _processedSize + NumExtraBytes + (size_t)(_buf - _bufBase); }\n\n  bool WasFinished() const { return _wasFinished; }\n\n  void SetStream(ISequentialInStream *stream) { _stream = stream; }\n  void ClearStreamPtr() { _stream = NULL; }\n  \n  void SetBuf(Byte *buf, size_t bufSize, size_t end, size_t pos)\n  {\n    _bufBase = buf;\n    _bufSize = bufSize;\n    _processedSize = 0;\n    _buf = buf + pos;\n    _bufLim = buf + end;\n    _wasFinished = false;\n    #ifdef Z7_NO_EXCEPTIONS\n    ErrorCode = S_OK;\n    #endif\n    NumExtraBytes = 0;\n  }\n\n  void Init() throw();\n  \n  Z7_FORCE_INLINE\n  bool ReadByte(Byte &b)\n  {\n    if (_buf >= _bufLim)\n      return ReadByte_FromNewBlock(b);\n    b = *_buf++;\n    return true;\n  }\n\n  Z7_FORCE_INLINE\n  bool ReadByte_FromBuf(Byte &b)\n  {\n    if (_buf >= _bufLim)\n      return false;\n    b = *_buf++;\n    return true;\n  }\n  \n  Z7_FORCE_INLINE\n  Byte ReadByte()\n  {\n    if (_buf >= _bufLim)\n      return ReadByte_FromNewBlock();\n    return *_buf++;\n  }\n  \n  size_t ReadBytesPart(Byte *buf, size_t size);\n  size_t ReadBytes(Byte *buf, size_t size);\n  const Byte *Lookahead(size_t &rem)\n  {\n    rem = (size_t)(_bufLim - _buf);\n    if (!rem)\n    {\n      ReadBlock();\n      rem = (size_t)(_bufLim - _buf);\n    }\n    return _buf;\n  }\n  size_t Skip(size_t size);\n};\n\nclass CInBuffer: public CInBufferBase\n{\npublic:\n  ~CInBuffer() { Free(); }\n  bool Create(size_t bufSize) throw(); // only up to 32-bits values now are supported!\n  void Free() throw();\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/InOutTempBuffer.cpp",
    "content": "﻿// InOutTempBuffer.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"InOutTempBuffer.h\"\n\n#include \"StreamUtils.h\"\n\n#ifdef USE_InOutTempBuffer_FILE\n\n#include \"../../../C/7zCrc.h\"\n\n#define kTempFilePrefixString FTEXT(\"7zt\")\n/*\n  Total buffer size limit, if we use temp file scheme:\n    32-bit:  16 MiB = 1 MiB *   16 buffers\n    64-bit:   4 GiB = 1 MiB * 4096 buffers\n*/\nstatic const size_t kNumBufsMax = (size_t)1 << (sizeof(size_t) * 2 - 4);\n\n#endif\n\nstatic const size_t kBufSize = (size_t)1 << 20;\n\n\nCInOutTempBuffer::CInOutTempBuffer():\n    _size(0),\n    _bufs(NULL),\n    _numBufs(0),\n    _numFilled(0)\n{\n #ifdef USE_InOutTempBuffer_FILE\n  _tempFile_Created = false;\n  _useMemOnly = false;\n  _crc = CRC_INIT_VAL;\n #endif\n}\n\nCInOutTempBuffer::~CInOutTempBuffer()\n{\n  for (size_t i = 0; i < _numBufs; i++)\n    MyFree(_bufs[i]);\n  MyFree(_bufs);\n}\n\n\nvoid *CInOutTempBuffer::GetBuf(size_t index)\n{\n  if (index >= _numBufs)\n  {\n    const size_t num = (_numBufs == 0 ? 16 : _numBufs * 2);\n    void **p = (void **)MyRealloc(_bufs, num * sizeof(void *));\n    if (!p)\n      return NULL;\n    _bufs = p;\n    memset(p + _numBufs, 0, (num - _numBufs) * sizeof(void *));\n    _numBufs = num;\n  }\n  \n  void *buf = _bufs[index];\n  if (!buf)\n  {\n    buf = MyAlloc(kBufSize);\n    if (buf)\n      _bufs[index] = buf;\n  }\n  return buf;\n}\n\n\nHRESULT CInOutTempBuffer::Write_HRESULT(const void *data, UInt32 size)\n{\n  if (size == 0)\n    return S_OK;\n  \n #ifdef USE_InOutTempBuffer_FILE\n  if (!_tempFile_Created)\n #endif\n  for (;;)  // loop for additional attemp to allocate memory after file creation error\n  {\n   #ifdef USE_InOutTempBuffer_FILE\n    bool allocError = false;\n   #endif\n  \n    for (;;)  // loop for writing to buffers\n    {\n      const size_t index = (size_t)(_size / kBufSize);\n      \n     #ifdef USE_InOutTempBuffer_FILE\n      if (index >= kNumBufsMax && !_useMemOnly)\n        break;\n     #endif\n    \n      void *buf = GetBuf(index);\n      if (!buf)\n      {\n       #ifdef USE_InOutTempBuffer_FILE\n        if (!_useMemOnly)\n        {\n          allocError = true;\n          break;\n        }\n       #endif\n        return E_OUTOFMEMORY;\n      }\n      \n      const size_t offset = (size_t)(_size) & (kBufSize - 1);\n      size_t cur = kBufSize - offset;\n      if (cur > size)\n        cur = size;\n      memcpy((Byte *)buf + offset, data, cur);\n      _size += cur;\n      if (index >= _numFilled)\n        _numFilled = index + 1;\n      data = (const void *)((const Byte *)data + cur);\n      size -= (UInt32)cur;\n      if (size == 0)\n        return S_OK;\n    }\n\n   #ifdef USE_InOutTempBuffer_FILE\n   #ifndef _WIN32\n    _outFile.mode_for_Create = 0600;  // only owner will have the rights to access this file\n   #endif\n    if (_tempFile.CreateRandomInTempFolder(kTempFilePrefixString, &_outFile))\n    {\n      _tempFile_Created = true;\n      break;\n    }\n    _useMemOnly = true;\n    if (allocError)\n      return GetLastError_noZero_HRESULT();\n   #endif\n  }\n\n #ifdef USE_InOutTempBuffer_FILE\n  if (!_outFile.WriteFull(data, size))\n    return GetLastError_noZero_HRESULT();\n  _crc = CrcUpdate(_crc, data, size);\n  _size += size;\n  return S_OK;\n #endif\n}\n\n\nHRESULT CInOutTempBuffer::WriteToStream(ISequentialOutStream *stream)\n{\n  UInt64 rem = _size;\n  // if (rem == 0) return S_OK;\n\n  const size_t numFilled = _numFilled;\n  _numFilled = 0;\n\n  for (size_t i = 0; i < numFilled; i++)\n  {\n    if (rem == 0)\n      return E_FAIL;\n    size_t cur = kBufSize;\n    if (cur > rem)\n      cur = (size_t)rem;\n    RINOK(WriteStream(stream, _bufs[i], cur))\n    rem -= cur;\n   #ifdef USE_InOutTempBuffer_FILE\n    // we will use _bufs[0] later for writing from temp file\n    if (i != 0 || !_tempFile_Created)\n   #endif\n    {\n      MyFree(_bufs[i]);\n      _bufs[i] = NULL;\n    }\n  }\n\n\n #ifdef USE_InOutTempBuffer_FILE\n\n  if (rem == 0)\n    return _tempFile_Created ? E_FAIL : S_OK;\n\n  if (!_tempFile_Created)\n    return E_FAIL;\n\n  if (!_outFile.Close())\n    return GetLastError_noZero_HRESULT();\n\n  HRESULT hres;\n  void *buf = GetBuf(0); // index\n  if (!buf)\n    hres = E_OUTOFMEMORY;\n  else\n  {\n    NWindows::NFile::NIO::CInFile inFile;\n    if (!inFile.Open(_tempFile.GetPath()))\n      hres = GetLastError_noZero_HRESULT();\n    else\n    {\n      UInt32 crc = CRC_INIT_VAL;\n      for (;;)\n      {\n        size_t processed;\n        if (!inFile.ReadFull(buf, kBufSize, processed))\n        {\n          hres = GetLastError_noZero_HRESULT();\n          break;\n        }\n        if (processed == 0)\n        {\n          // we compare crc without CRC_GET_DIGEST\n          hres = (_crc == crc ? S_OK : E_FAIL);\n          break;\n        }\n        size_t n = processed;\n        if (n > rem)\n          n = (size_t)rem;\n        hres = WriteStream(stream, buf, n);\n        if (hres != S_OK)\n          break;\n        crc = CrcUpdate(crc, buf, n);\n        rem -= n;\n        if (n != processed)\n        {\n          hres = E_FAIL;\n          break;\n        }\n      }\n    }\n  }\n\n  // _tempFile.DisableDeleting(); // for debug\n  _tempFile.Remove();\n  RINOK(hres)\n\n #endif\n\n  return rem == 0 ? S_OK : E_FAIL;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/InOutTempBuffer.h",
    "content": "﻿// InOutTempBuffer.h\n\n#ifndef ZIP7_INC_IN_OUT_TEMP_BUFFER_H\n#define ZIP7_INC_IN_OUT_TEMP_BUFFER_H\n\n// #ifdef _WIN32\n#define USE_InOutTempBuffer_FILE\n// #endif\n\n#ifdef USE_InOutTempBuffer_FILE\n#include \"../../Windows/FileDir.h\"\n#endif\n\n#include \"../IStream.h\"\n\nclass CInOutTempBuffer\n{\n  UInt64 _size;\n  void **_bufs;\n  size_t _numBufs;\n  size_t _numFilled;\n\n #ifdef USE_InOutTempBuffer_FILE\n  \n  bool _tempFile_Created;\n  bool _useMemOnly;\n  UInt32 _crc;\n  // COutFile object must be declared after CTempFile object for correct destructor order\n  NWindows::NFile::NDir::CTempFile _tempFile;\n  NWindows::NFile::NIO::COutFile _outFile;\n\n #endif\n\n  void *GetBuf(size_t index);\n\n  Z7_CLASS_NO_COPY(CInOutTempBuffer)\npublic:\n  CInOutTempBuffer();\n  ~CInOutTempBuffer();\n  HRESULT Write_HRESULT(const void *data, UInt32 size);\n  HRESULT WriteToStream(ISequentialOutStream *stream);\n  UInt64 GetDataSize() const { return _size; }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/LimitedStreams.cpp",
    "content": "﻿// LimitedStreams.cpp\n\n#include \"StdAfx.h\"\n\n#include <string.h>\n\n#include \"LimitedStreams.h\"\n\nZ7_COM7F_IMF(CLimitedSequentialInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize = 0;\n  {\n    const UInt64 rem = _size - _pos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  HRESULT result = S_OK;\n  if (size != 0)\n  {\n    result = _stream->Read(data, size, &realProcessedSize);\n    _pos += realProcessedSize;\n    if (realProcessedSize == 0)\n      _wasFinished = true;\n  }\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return result;\n}\n\nZ7_COM7F_IMF(CLimitedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= _size)\n  {\n    // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.\n    return S_OK;\n    // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF\n  }\n  {\n    const UInt64 rem = _size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  UInt64 newPos = _startOffset + _virtPos;\n  if (newPos != _physPos)\n  {\n    _physPos = newPos;\n    RINOK(SeekToPhys())\n  }\n  HRESULT res = _stream->Read(data, size, &size);\n  if (processedSize)\n    *processedSize = size;\n  _physPos += size;\n  _virtPos += size;\n  return res;\n}\n\nZ7_COM7F_IMF(CLimitedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += _size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = _virtPos;\n  return S_OK;\n}\n\nHRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream)\n{\n  *resStream = NULL;\n  CLimitedInStream *streamSpec = new CLimitedInStream;\n  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;\n  streamSpec->SetStream(inStream);\n  RINOK(streamSpec->InitAndSeek(pos, size))\n  streamSpec->SeekToStart();\n  *resStream = streamTemp.Detach();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CClusterInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= Size)\n    return S_OK;\n  {\n    UInt64 rem = Size - _virtPos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  if (size == 0)\n    return S_OK;\n\n  if (_curRem == 0)\n  {\n    const UInt32 blockSize = (UInt32)1 << BlockSizeLog;\n    const UInt32 virtBlock = (UInt32)(_virtPos >> BlockSizeLog);\n    const UInt32 offsetInBlock = (UInt32)_virtPos & (blockSize - 1);\n    const UInt32 phyBlock = Vector[virtBlock];\n    \n    UInt64 newPos = StartOffset + ((UInt64)phyBlock << BlockSizeLog) + offsetInBlock;\n    if (newPos != _physPos)\n    {\n      _physPos = newPos;\n      RINOK(SeekToPhys())\n    }\n\n    _curRem = blockSize - offsetInBlock;\n    \n    for (unsigned i = 1; i < 64 && (virtBlock + i) < (UInt32)Vector.Size() && phyBlock + i == Vector[virtBlock + i]; i++)\n      _curRem += (UInt32)1 << BlockSizeLog;\n  }\n  \n  if (size > _curRem)\n    size = _curRem;\n  HRESULT res = Stream->Read(data, size, &size);\n  if (processedSize)\n    *processedSize = size;\n  _physPos += size;\n  _virtPos += size;\n  _curRem -= size;\n  return res;\n}\n \nZ7_COM7F_IMF(CClusterInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  if (_virtPos != (UInt64)offset)\n    _curRem = 0;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CExtentsStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  const UInt64 virt = _virtPos;\n  if (virt >= Extents.Back().Virt)\n    return S_OK;\n  if (size == 0)\n    return S_OK;\n  \n  unsigned left = _prevExtentIndex;\n  if (virt <  Extents[left].Virt ||\n      virt >= Extents[left + 1].Virt)\n  {\n    left = 0;\n    unsigned right = Extents.Size() - 1;\n    for (;;)\n    {\n      const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      if (mid == left)\n        break;\n      if (virt < Extents[mid].Virt)\n        right = mid;\n      else\n        left = mid;\n    }\n    _prevExtentIndex = left;\n  }\n  \n  {\n    const UInt64 rem = Extents[left + 1].Virt - virt;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  \n  const CSeekExtent &extent = Extents[left];\n  \n  if (extent.Is_ZeroFill())\n  {\n    memset(data, 0, size);\n    _virtPos += size;\n    if (processedSize)\n      *processedSize = size;\n    return S_OK;\n  }\n\n  {\n    const UInt64 phy = extent.Phy + (virt - extent.Virt);\n    if (_phyPos != phy)\n    {\n      _phyPos = (UInt64)0 - 1;  // we don't trust seek_pos in case of error\n      RINOK(InStream_SeekSet(Stream, phy))\n      _phyPos = phy;\n    }\n  }\n  \n  const HRESULT res = Stream->Read(data, size, &size);\n  _virtPos += size;\n  if (res == S_OK)\n    _phyPos += size;\n  else\n    _phyPos = (UInt64)0 - 1;  // we don't trust seek_pos in case of error\n  if (processedSize)\n    *processedSize = size;\n  return res;\n}\n\n\nZ7_COM7F_IMF(CExtentsStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += Extents.Back().Virt; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = _virtPos;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CLimitedSequentialOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (processedSize)\n    *processedSize = 0;\n  if (size > _size)\n  {\n    if (_size == 0)\n    {\n      _overflow = true;\n      if (!_overflowIsAllowed)\n        return E_FAIL;\n      if (processedSize)\n        *processedSize = size;\n      return S_OK;\n    }\n    size = (UInt32)_size;\n  }\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  _size -= size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\n\nZ7_COM7F_IMF(CTailInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 cur;\n  HRESULT res = Stream->Read(data, size, &cur);\n  if (processedSize)\n    *processedSize = cur;\n  _virtPos += cur;\n  return res;\n}\n  \nZ7_COM7F_IMF(CTailInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END:\n    {\n      UInt64 pos = 0;\n      RINOK(Stream->Seek(offset, STREAM_SEEK_END, &pos))\n      if (pos < Offset)\n        return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n      _virtPos = pos - Offset;\n      if (newPosition)\n        *newPosition = _virtPos;\n      return S_OK;\n    }\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = _virtPos;\n  return InStream_SeekSet(Stream, Offset + _virtPos);\n}\n\nZ7_COM7F_IMF(CLimitedCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (_virtPos >= _size)\n  {\n    // 9.31: Fixed. Windows doesn't return error in ReadFile and IStream->Read in that case.\n    return S_OK;\n    // return (_virtPos == _size) ? S_OK: E_FAIL; // ERROR_HANDLE_EOF\n  }\n  UInt64 rem = _size - _virtPos;\n  if (rem < size)\n    size = (UInt32)rem;\n\n  UInt64 newPos = _startOffset + _virtPos;\n  UInt64 offsetInCache = newPos - _cachePhyPos;\n  HRESULT res = S_OK;\n  if (newPos >= _cachePhyPos &&\n      offsetInCache <= _cacheSize &&\n      size <= _cacheSize - (size_t)offsetInCache)\n  {\n    if (size != 0)\n      memcpy(data, _cache + (size_t)offsetInCache, size);\n  }\n  else\n  {\n    if (newPos != _physPos)\n    {\n      _physPos = newPos;\n      RINOK(SeekToPhys())\n    }\n    res = _stream->Read(data, size, &size);\n    _physPos += size;\n  }\n  if (processedSize)\n    *processedSize = size;\n  _virtPos += size;\n  return res;\n}\n\nZ7_COM7F_IMF(CLimitedCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += _size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = _virtPos;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CTailOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 cur;\n  HRESULT res = Stream->Write(data, size, &cur);\n  if (processedSize)\n    *processedSize = cur;\n  _virtPos += cur;\n  if (_virtSize < _virtPos)\n    _virtSize = _virtPos;\n  return res;\n}\n  \nZ7_COM7F_IMF(CTailOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _virtPos; break;\n    case STREAM_SEEK_END: offset += _virtSize; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _virtPos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = _virtPos;\n  return Stream->Seek((Int64)(Offset + _virtPos), STREAM_SEEK_SET, NULL);\n}\n\nZ7_COM7F_IMF(CTailOutStream::SetSize(UInt64 newSize))\n{\n  _virtSize = newSize;\n  return Stream->SetSize(Offset + newSize);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/LimitedStreams.h",
    "content": "﻿// LimitedStreams.h\n\n#ifndef ZIP7_INC_LIMITED_STREAMS_H\n#define ZIP7_INC_LIMITED_STREAMS_H\n\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/MyVector.h\"\n#include \"../IStream.h\"\n\n#include \"StreamUtils.h\"\n\nZ7_CLASS_IMP_COM_1(\n  CLimitedSequentialInStream\n  , ISequentialInStream\n)\n  CMyComPtr<ISequentialInStream> _stream;\n  UInt64 _size;\n  UInt64 _pos;\n  bool _wasFinished;\npublic:\n  void SetStream(ISequentialInStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init(UInt64 streamSize)\n  {\n    _size = streamSize;\n    _pos = 0;\n    _wasFinished = false;\n  }\n  UInt64 GetSize() const { return _pos; }\n  UInt64 GetRem() const { return _size - _pos; }\n  bool WasFinished() const { return _wasFinished; }\n};\n\n\nZ7_CLASS_IMP_IInStream(\n  CLimitedInStream\n)\n  CMyComPtr<IInStream> _stream;\n  UInt64 _virtPos;\n  UInt64 _physPos;\n  UInt64 _size;\n  UInt64 _startOffset;\n\n  HRESULT SeekToPhys() { return InStream_SeekSet(_stream, _physPos); }\npublic:\n  void SetStream(IInStream *stream) { _stream = stream; }\n  HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)\n  {\n    _startOffset = startOffset;\n    _physPos = startOffset;\n    _virtPos = 0;\n    _size = size;\n    return SeekToPhys();\n  }\n  HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }\n};\n\nHRESULT CreateLimitedInStream(IInStream *inStream, UInt64 pos, UInt64 size, ISequentialInStream **resStream);\n\n\nZ7_CLASS_IMP_IInStream(\n  CClusterInStream\n)\n  UInt64 _virtPos;\n  UInt64 _physPos;\n  UInt32 _curRem;\npublic:\n  unsigned BlockSizeLog;\n  UInt64 Size;\n  CMyComPtr<IInStream> Stream;\n  CRecordVector<UInt32> Vector;\n  UInt64 StartOffset;\n\n  HRESULT SeekToPhys() { return InStream_SeekSet(Stream, _physPos); }\n\n  HRESULT InitAndSeek()\n  {\n    _curRem = 0;\n    _virtPos = 0;\n    _physPos = StartOffset;\n    if (Vector.Size() > 0)\n    {\n      _physPos = StartOffset + (Vector[0] << BlockSizeLog);\n      return SeekToPhys();\n    }\n    return S_OK;\n  }\n};\n\n\n\nconst UInt64 k_SeekExtent_Phy_Type_ZeroFill = (UInt64)(Int64)-1;\n\nstruct CSeekExtent\n{\n  UInt64 Virt;\n  UInt64 Phy;\n\n  void SetAs_ZeroFill() { Phy = k_SeekExtent_Phy_Type_ZeroFill; }\n  bool Is_ZeroFill() const { return Phy == k_SeekExtent_Phy_Type_ZeroFill; }\n};\n\n\nZ7_CLASS_IMP_IInStream(\n  CExtentsStream\n)\n  UInt64 _virtPos;\n  UInt64 _phyPos;\n  unsigned _prevExtentIndex;\npublic:\n  CMyComPtr<IInStream> Stream;\n  CRecordVector<CSeekExtent> Extents;\n\n  void ReleaseStream() { Stream.Release(); }\n  void Init()\n  {\n    _virtPos = 0;\n    _phyPos = (UInt64)0 - 1; // we need Seek() for Stream\n    _prevExtentIndex = 0;\n  }\n};\n\n\n\nZ7_CLASS_IMP_COM_1(\n  CLimitedSequentialOutStream\n  , ISequentialOutStream\n)\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\n  bool _overflow;\n  bool _overflowIsAllowed;\npublic:\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init(UInt64 size, bool overflowIsAllowed = false)\n  {\n    _size = size;\n    _overflow = false;\n    _overflowIsAllowed = overflowIsAllowed;\n  }\n  bool IsFinishedOK() const { return (_size == 0 && !_overflow); }\n  UInt64 GetRem() const { return _size; }\n};\n\n\nZ7_CLASS_IMP_IInStream(\n  CTailInStream\n)\n  UInt64 _virtPos;\npublic:\n  CMyComPtr<IInStream> Stream;\n  UInt64 Offset;\n\n  void Init()\n  {\n    _virtPos = 0;\n  }\n  HRESULT SeekToStart() { return InStream_SeekSet(Stream, Offset); }\n};\n\n\nZ7_CLASS_IMP_IInStream(\n  CLimitedCachedInStream\n)\n  CMyComPtr<IInStream> _stream;\n  UInt64 _virtPos;\n  UInt64 _physPos;\n  UInt64 _size;\n  UInt64 _startOffset;\n  \n  const Byte *_cache;\n  size_t _cacheSize;\n  size_t _cachePhyPos;\n\n  HRESULT SeekToPhys() { return InStream_SeekSet(_stream, _physPos); }\npublic:\n  CByteBuffer Buffer;\n\n  void SetStream(IInStream *stream) { _stream = stream; }\n  void SetCache(size_t cacheSize, size_t cachePos)\n  {\n    _cache = Buffer;\n    _cacheSize = cacheSize;\n    _cachePhyPos = cachePos;\n  }\n\n  HRESULT InitAndSeek(UInt64 startOffset, UInt64 size)\n  {\n    _startOffset = startOffset;\n    _physPos = startOffset;\n    _virtPos = 0;\n    _size = size;\n    return SeekToPhys();\n  }\n \n  HRESULT SeekToStart() { return Seek(0, STREAM_SEEK_SET, NULL); }\n};\n\n\nclass CTailOutStream Z7_final :\n  public IOutStream,\n  public CMyUnknownImp\n{\n  Z7_IFACES_IMP_UNK_2(ISequentialOutStream, IOutStream)\n\n  UInt64 _virtPos;\n  UInt64 _virtSize;\npublic:\n  CMyComPtr<IOutStream> Stream;\n  UInt64 Offset;\n  \n  void Init()\n  {\n    _virtPos = 0;\n    _virtSize = 0;\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/LockedStream.h",
    "content": "﻿// LockedStream.h\n\n#ifndef ZIP7_INC_LOCKED_STREAM_H\n#define ZIP7_INC_LOCKED_STREAM_H\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/MemBlocks.cpp",
    "content": "﻿// MemBlocks.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"MemBlocks.h\"\n#include \"StreamUtils.h\"\n\nbool CMemBlockManager::AllocateSpace_bool(size_t numBlocks)\n{\n  FreeSpace();\n  if (numBlocks == 0)\n  {\n    return true;\n    // return false;\n  }\n  if (_blockSize < sizeof(void *))\n    return false;\n  const size_t totalSize = numBlocks * _blockSize;\n  if (totalSize / _blockSize != numBlocks)\n    return false;\n  _data = ::MidAlloc(totalSize);\n  if (!_data)\n    return false;\n  Byte *p = (Byte *)_data;\n  for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)\n    *(Byte **)(void *)p = (p + _blockSize);\n  *(Byte **)(void *)p = NULL;\n  _headFree = _data;\n  return true;\n}\n\nvoid CMemBlockManager::FreeSpace()\n{\n  ::MidFree(_data);\n  _data = NULL;\n  _headFree= NULL;\n}\n\nvoid *CMemBlockManager::AllocateBlock()\n{\n  void *p = _headFree;\n  if (p)\n    _headFree = *(void **)p;\n  return p;\n}\n\nvoid CMemBlockManager::FreeBlock(void *p)\n{\n  if (!p)\n    return;\n  *(void **)p = _headFree;\n  _headFree = p;\n}\n\n\n// #include <stdio.h>\n\nHRESULT CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)\n{\n  if (numNoLockBlocks > numBlocks)\n    return E_INVALIDARG;\n  const size_t numLockBlocks = numBlocks - numNoLockBlocks;\n  UInt32 maxCount = (UInt32)numLockBlocks;\n  if (maxCount != numLockBlocks)\n    return E_OUTOFMEMORY;\n  if (!CMemBlockManager::AllocateSpace_bool(numBlocks))\n    return E_OUTOFMEMORY;\n  // we need (maxCount = 1), if we want to create non-use empty Semaphore\n  if (maxCount == 0)\n    maxCount = 1;\n\n  // printf(\"\\n Synchro.Create() \\n\");\n  WRes wres;\n  #ifndef _WIN32\n  Semaphore.Close();\n  wres = Synchro.Create();\n  if (wres != 0)\n    return HRESULT_FROM_WIN32(wres);\n  wres = Semaphore.Create(&Synchro, (UInt32)numLockBlocks, maxCount);\n  #else\n  wres = Semaphore.OptCreateInit((UInt32)numLockBlocks, maxCount);\n  #endif\n  \n  return HRESULT_FROM_WIN32(wres);\n}\n\n\nHRESULT CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)\n{\n  // desiredNumberOfBlocks = 0; // for debug\n  if (numNoLockBlocks > desiredNumberOfBlocks)\n    return E_INVALIDARG;\n  for (;;)\n  {\n    // if (desiredNumberOfBlocks == 0) return E_OUTOFMEMORY;\n    const HRESULT hres = AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks);\n    if (hres != E_OUTOFMEMORY)\n      return hres;\n    if (desiredNumberOfBlocks == numNoLockBlocks)\n      return E_OUTOFMEMORY;\n    desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);\n  }\n}\n\nvoid CMemBlockManagerMt::FreeSpace()\n{\n  Semaphore.Close();\n  CMemBlockManager::FreeSpace();\n}\n\nvoid *CMemBlockManagerMt::AllocateBlock()\n{\n  // Semaphore.Lock();\n  NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\n  return CMemBlockManager::AllocateBlock();\n}\n\nvoid CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)\n{\n  if (!p)\n    return;\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);\n    CMemBlockManager::FreeBlock(p);\n  }\n  if (lockMode)\n    Semaphore.Release();\n}\n\n\n\nvoid CMemBlocks::Free(CMemBlockManagerMt *manager)\n{\n  while (Blocks.Size() > 0)\n  {\n    manager->FreeBlock(Blocks.Back());\n    Blocks.DeleteBack();\n  }\n  TotalSize = 0;\n}\n\nvoid CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)\n{\n  Free(manager);\n  Blocks.ClearAndFree();\n}\n\nHRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const\n{\n  UInt64 totalSize = TotalSize;\n  for (unsigned blockIndex = 0; totalSize > 0; blockIndex++)\n  {\n    size_t curSize = blockSize;\n    if (curSize > totalSize)\n      curSize = (size_t)totalSize;\n    if (blockIndex >= Blocks.Size())\n      return E_FAIL;\n    RINOK(WriteStream(outStream, Blocks[blockIndex], curSize))\n    totalSize -= curSize;\n  }\n  return S_OK;\n}\n\n\nvoid CMemLockBlocks::FreeBlock(unsigned index, CMemBlockManagerMt *memManager)\n{\n  memManager->FreeBlock(Blocks[index], LockMode);\n  Blocks[index] = NULL;\n}\n\nvoid CMemLockBlocks::Free(CMemBlockManagerMt *memManager)\n{\n  while (Blocks.Size() > 0)\n  {\n    FreeBlock(Blocks.Size() - 1, memManager);\n    Blocks.DeleteBack();\n  }\n  TotalSize = 0;\n}\n\n/*\nHRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)\n{\n  if (LockMode)\n  {\n    if (Blocks.Size() > 0)\n    {\n      RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));\n    }\n    LockMode = false;\n  }\n  return 0;\n}\n*/\n\nvoid CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)\n{\n  blocks.Free(memManager);\n  blocks.LockMode = LockMode;\n  UInt64 totalSize = 0;\n  const size_t blockSize = memManager->GetBlockSize();\n  FOR_VECTOR (i, Blocks)\n  {\n    if (totalSize < TotalSize)\n      blocks.Blocks.Add(Blocks[i]);\n    else\n      FreeBlock(i, memManager);\n    Blocks[i] = NULL;\n    totalSize += blockSize;\n  }\n  blocks.TotalSize = TotalSize;\n  Free(memManager);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/MemBlocks.h",
    "content": "﻿// MemBlocks.h\n\n#ifndef ZIP7_INC_MEM_BLOCKS_H\n#define ZIP7_INC_MEM_BLOCKS_H\n\n#include \"../../Common/MyVector.h\"\n\n#include \"../../Windows/Synchronization.h\"\n\n#include \"../IStream.h\"\n\nclass CMemBlockManager\n{\n  void *_data;\n  size_t _blockSize;\n  void *_headFree;\npublic:\n  CMemBlockManager(size_t blockSize = (1 << 20)): _data(NULL), _blockSize(blockSize), _headFree(NULL) {}\n  ~CMemBlockManager() { FreeSpace(); }\n\n  bool AllocateSpace_bool(size_t numBlocks);\n  void FreeSpace();\n  size_t GetBlockSize() const { return _blockSize; }\n  void *AllocateBlock();\n  void FreeBlock(void *p);\n};\n\n\nclass CMemBlockManagerMt: public CMemBlockManager\n{\n  NWindows::NSynchronization::CCriticalSection _criticalSection;\npublic:\n  SYNC_OBJ_DECL(Synchro)\n  NWindows::NSynchronization::CSemaphore_WFMO Semaphore;\n\n  CMemBlockManagerMt(size_t blockSize = (1 << 20)): CMemBlockManager(blockSize) {}\n  ~CMemBlockManagerMt() { FreeSpace(); }\n\n  HRESULT AllocateSpace(size_t numBlocks, size_t numNoLockBlocks);\n  HRESULT AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks = 0);\n  void FreeSpace();\n  void *AllocateBlock();\n  void FreeBlock(void *p, bool lockMode = true);\n  // WRes ReleaseLockedBlocks_WRes(unsigned number) { return Semaphore.Release(number); }\n};\n\n\nclass CMemBlocks\n{\n  void Free(CMemBlockManagerMt *manager);\npublic:\n  CRecordVector<void *> Blocks;\n  UInt64 TotalSize;\n  \n  CMemBlocks(): TotalSize(0) {}\n\n  void FreeOpt(CMemBlockManagerMt *manager);\n  HRESULT WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const;\n};\n\nstruct CMemLockBlocks: public CMemBlocks\n{\n  bool LockMode;\n\n  CMemLockBlocks(): LockMode(true) {}\n  void Free(CMemBlockManagerMt *memManager);\n  void FreeBlock(unsigned index, CMemBlockManagerMt *memManager);\n  // HRESULT SwitchToNoLockMode(CMemBlockManagerMt *memManager);\n  void Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager);\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/MethodId.h",
    "content": "﻿// MethodId.h\n\n#ifndef ZIP7_INC_7Z_METHOD_ID_H\n#define ZIP7_INC_7Z_METHOD_ID_H\n\n#include \"../../Common/MyTypes.h\"\n\ntypedef UInt64 CMethodId;\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/MethodProps.cpp",
    "content": "﻿// MethodProps.cpp\n\n#include \"StdAfx.h\"\n\n// **************** 7-Zip ZS Modification Start ****************\n#include \"../../Windows/System.h\"\n// **************** 7-Zip ZS Modification End ****************\n#include \"../../Common/StringToInt.h\"\n\n#include \"MethodProps.h\"\n\nusing namespace NWindows;\n\nUInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents)\n{\n  // if (percents == 0) return 0;\n  const UInt64 q = percents / 100;\n  const UInt32 r = (UInt32)(percents % 100);\n  UInt64 res = 0;\n  \n  if (q != 0)\n  {\n    if (val > (UInt64)(Int64)-1 / q)\n      return (UInt64)(Int64)-1;\n    res = val * q;\n  }\n\n  if (r != 0)\n  {\n    UInt64 v2;\n    if (val <= (UInt64)(Int64)-1 / r)\n      v2 = val * r / 100;\n    else\n      v2 = val / 100 * r;\n    res += v2;\n    if (res < v2)\n      return (UInt64)(Int64)-1;\n  }\n  \n  return res;\n}\n\n\nbool StringToBool(const wchar_t *s, bool &res)\n{\n  if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, \"ON\"))\n  {\n    res = true;\n    return true;\n  }\n  if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, \"OFF\"))\n  {\n    res = false;\n    return true;\n  }\n  return false;\n}\n\nHRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)\n{\n  switch (prop.vt)\n  {\n    case VT_EMPTY: dest = true; return S_OK;\n    case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;\n    case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;\n    default: break;\n  }\n  return E_INVALIDARG;\n}\n\nunsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)\n{\n  const wchar_t *start = srcString;\n  const wchar_t *end;\n  number = ConvertStringToUInt32(start, &end);\n  return (unsigned)(end - start);\n}\n\nstatic unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)\n{\n  const wchar_t *start = srcString;\n  const wchar_t *end;\n  number = ConvertStringToUInt64(start, &end);\n  return (unsigned)(end - start);\n}\n\nHRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)\n{\n  // =VT_UI4\n  // =VT_EMPTY : it doesn't change (resValue), and returns S_OK\n  // {stringUInt32}=VT_EMPTY\n\n  if (prop.vt == VT_UI4)\n  {\n    if (!name.IsEmpty())\n      return E_INVALIDARG;\n    resValue = prop.ulVal;\n    return S_OK;\n  }\n  if (prop.vt != VT_EMPTY)\n    return E_INVALIDARG;\n  if (name.IsEmpty())\n    return S_OK;\n  UInt32 v;\n  if (ParseStringToUInt32(name, v) != name.Len())\n    return E_INVALIDARG;\n  resValue = v;\n  return S_OK;\n}\n\n\n\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\nHRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force)\n{\n  force = false;\n  UString s;\n  if (name.IsEmpty())\n  {\n    if (prop.vt == VT_UI4)\n    {\n      numThreads = prop.ulVal;\n      force = true;\n      return S_OK;\n    }\n    bool val;\n    HRESULT res = PROPVARIANT_to_bool(prop, val);\n    if (res == S_OK)\n    {\n      if (!val)\n      {\n        numThreads = 1;\n        force = true;\n      }\n      // force = true; for debug\n      // \"(VT_BOOL = VARIANT_TRUE)\" set \"force = false\" and doesn't change numThreads\n      return S_OK;\n    }\n    if (prop.vt != VT_BSTR)\n      return res;\n    s.SetFromBstr(prop.bstrVal);\n    if (s.IsEmpty())\n      return E_INVALIDARG;\n  }\n  else\n  {\n    if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n    s = name;\n  }\n\n  s.MakeLower_Ascii();\n  const wchar_t *start = s;\n  UInt32 v = numThreads;\n\n  /* we force up, if threads number specified\n     only `d` will force it down */\n  bool force_loc = true;\n  for (;;)\n  {\n    const wchar_t c = *start;\n    if (!c)\n      break;\n    if (c == 'd')\n    {\n      force_loc = false;  // force down\n      start++;\n      continue;\n    }\n    if (c == 'u')\n    {\n      force_loc = true;   // force up\n      start++;\n      continue;\n    }\n    bool isPercent = false;\n    if (c == 'p')\n    {\n      isPercent = true;\n      start++;\n    }\n    const wchar_t *end;\n    v = ConvertStringToUInt32(start, &end);\n    if (end == start)\n      return E_INVALIDARG;\n    if (isPercent)\n      v = numThreads * v / 100;\n    start = end;\n  }\n\n  numThreads = v;\n  force = force_loc;\n  return S_OK;\n}\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\nHRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads)\n{\n  UString s;\n  numThreads = numCPUs ? numCPUs : NWindows::NSystem::GetNumberOfProcessors();\n  if (name.IsEmpty())\n  {\n    if (prop.vt == VT_UI4)\n    {\n      numThreads = prop.ulVal;\n      if (numThreads > numCPUs) numThreads = numCPUs;\n      return S_OK;\n    }\n    bool val;\n    HRESULT res = PROPVARIANT_to_bool(prop, val);\n    if (res == S_OK)\n    {\n      // -mmt=off, -mmt-\n      if (!val) {\n        numThreads = 0; /* 0 - single threaded, to differentiate from 1 by encoder like brotli-mt with single CPU */\n      }\n      return S_OK;\n    }\n    if (prop.vt != VT_BSTR)\n      return res;\n    s.SetFromBstr(prop.bstrVal);\n    if (s.IsEmpty())\n      return E_INVALIDARG;\n  }\n  else\n  {\n    if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n    s = name;\n  }\n\n  s.MakeLower_Ascii();\n  const wchar_t *start = s;\n  if (*start == '=') start++;\n  if (*start == 'o') {\n    if (wcscmp(start, L\"on\") == 0) {\n      numThreads = numCPUs; // force on\n      return S_OK;\n    } else if (wcscmp(start, L\"off\") == 0) {\n      numThreads = 0; // force off\n      return S_OK;\n    }\n  }\n  /* we force up, if threads number specified\n     only `d` will force it down */\n  int numTh = (int)numThreads;\n  while (*start)\n  {\n    int forceUD = 0;\n    bool isPercent = false;\n    switch (*start) {\n      case '-':\n        if (!*(start+1)) {\n          numThreads = 0; // force off\n          return S_OK;\n        }\n        // otherwise force down\n        // fall through\n      case 'd':\n        forceUD = -1;  // force down\n        start++;\n        if (*start == 'p') goto percent;\n        break;\n      case '+':\n        if (!*(start+1)) {\n          numThreads = numCPUs; // force on\n          return S_OK;\n        }\n        // otherwise force up\n        // fall through\n      case 'u':\n        forceUD = +1;   // force up\n        start++;\n        if (*start == 'p') goto percent;\n        break;\n      case 'p':\n      percent:\n        isPercent = true;\n        start++;\n        break;\n    }\n    const wchar_t *end;\n    UInt32 v;\n    v = ConvertStringToUInt32(start, &end);\n    if (end == start) {\n      if (!forceUD) {\n        return E_INVALIDARG;\n      }\n      v = 1; // d or u not followed by number (simply -1 or +1)\n    }\n    if (isPercent) {\n      v = numThreads * v / 100;\n    }\n    if (forceUD) {\n      numTh += forceUD * v;\n    } else {\n      numTh = v;\n    }\n    start = end;\n  }\n  if (numTh <= 0) numTh = 1;\n  if (numTh > (int)numCPUs) numTh = (int)numCPUs;\n  numThreads = numTh;\n  return S_OK;\n}\n// **************** 7-Zip ZS Modification End ****************\n\n\n\nstatic HRESULT SetLogSizeProp(UInt64 number, NCOM::CPropVariant &destProp)\n{\n  if (number >= 64)\n    return E_INVALIDARG;\n  UInt32 val32;\n  if (number < 32)\n    val32 = (UInt32)1 << (unsigned)number;\n  /*\n  else if (number == 32 && reduce_4GB_to_32bits)\n    val32 = (UInt32)(Int32)-1;\n  */\n  else\n  {\n    destProp = (UInt64)((UInt64)1 << (unsigned)number);\n    return S_OK;\n  }\n  destProp = (UInt32)val32;\n  return S_OK;\n}\n\n\nstatic HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)\n{\n  /* if (reduce_4GB_to_32bits) we can reduce (4 GiB) property to (4 GiB - 1).\n     to fit the value to UInt32 for clients that do not support 64-bit values */\n\n  const wchar_t *end;\n  const UInt64 number = ConvertStringToUInt64(s, &end);\n  const unsigned numDigits = (unsigned)(end - s.Ptr());\n  if (numDigits == 0 || s.Len() > numDigits + 1)\n    return E_INVALIDARG;\n  \n  if (s.Len() == numDigits)\n    return SetLogSizeProp(number, destProp);\n  \n  unsigned numBits;\n  \n  switch (MyCharLower_Ascii(s[numDigits]))\n  {\n    case 'b': numBits =  0; break;\n    case 'k': numBits = 10; break;\n    case 'm': numBits = 20; break;\n    case 'g': numBits = 30; break;\n    default: return E_INVALIDARG;\n  }\n  \n  const UInt64 range4g = ((UInt64)1 << (32 - numBits));\n  if (number < range4g)\n    destProp = (UInt32)((UInt32)number << numBits);\n  /*\n  else if (number == range4g && reduce_4GB_to_32bits)\n    destProp = (UInt32)(Int32)-1;\n  */\n  else if (numBits == 0)\n    destProp = (UInt64)number;\n  else if (number >= ((UInt64)1 << (64 - numBits)))\n    return E_INVALIDARG;\n  else\n    destProp = (UInt64)((UInt64)number << numBits);\n  return S_OK;\n}\n\n\nstatic HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp)\n{\n  if (prop.vt == VT_UI4)\n    return SetLogSizeProp(prop.ulVal, destProp);\n\n  if (prop.vt == VT_BSTR)\n  {\n    UString s;\n    s = prop.bstrVal;\n    return StringToDictSize(s, destProp);\n  }\n  return E_INVALIDARG;\n}\n\n\nvoid CProps::AddProp32(PROPID propid, UInt32 val)\n{\n  CProp &prop = Props.AddNew();\n  prop.IsOptional = true;\n  prop.Id = propid;\n  prop.Value = (UInt32)val;\n}\n\nvoid CProps::AddPropBool(PROPID propid, bool val)\n{\n  CProp &prop = Props.AddNew();\n  prop.IsOptional = true;\n  prop.Id = propid;\n  prop.Value = val;\n}\n\nclass CCoderProps\n{\n  PROPID *_propIDs;\n  NCOM::CPropVariant *_props;\n  unsigned _numProps;\n  unsigned _numPropsMax;\npublic:\n  CCoderProps(unsigned numPropsMax):\n      _propIDs(NULL),\n      _props(NULL),\n      _numProps(0),\n      _numPropsMax(numPropsMax)\n  {\n    _propIDs = new PROPID[numPropsMax];\n    _props = new NCOM::CPropVariant[numPropsMax];\n  }\n  ~CCoderProps()\n  {\n    delete []_propIDs;\n    delete []_props;\n  }\n  void AddProp(const CProp &prop);\n  HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties)\n  {\n    return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps);\n  }\n};\n\nvoid CCoderProps::AddProp(const CProp &prop)\n{\n  if (_numProps >= _numPropsMax)\n    throw 1;\n  _propIDs[_numProps] = prop.Id;\n  _props[_numProps] = prop.Value;\n  _numProps++;\n}\n\nHRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const\n{\n  return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL, NULL, NULL);\n}\n\nHRESULT CProps::SetCoderProps_DSReduce_Aff(\n    ICompressSetCoderProperties *scp,\n    const UInt64 *dataSizeReduce,\n    const UInt64 *affinity,\n    const UInt32 *affinityGroup,\n    const UInt64 *affinityInGroup) const\n{\n  CCoderProps coderProps(Props.Size()\n      + (dataSizeReduce ? 1 : 0)\n      + (affinity ? 1 : 0)\n      + (affinityGroup ? 1 : 0)\n      + (affinityInGroup ? 1 : 0)\n      );\n  FOR_VECTOR (i, Props)\n    coderProps.AddProp(Props[i]);\n  if (dataSizeReduce)\n  {\n    CProp prop;\n    prop.Id = NCoderPropID::kReduceSize;\n    prop.Value = *dataSizeReduce;\n    coderProps.AddProp(prop);\n  }\n  if (affinity)\n  {\n    CProp prop;\n    prop.Id = NCoderPropID::kAffinity;\n    prop.Value = *affinity;\n    coderProps.AddProp(prop);\n  }\n  if (affinityGroup)\n  {\n    CProp prop;\n    prop.Id = NCoderPropID::kThreadGroup;\n    prop.Value = *affinityGroup;\n    coderProps.AddProp(prop);\n  }\n  if (affinityInGroup)\n  {\n    CProp prop;\n    prop.Id = NCoderPropID::kAffinityInGroup;\n    prop.Value = *affinityInGroup;\n    coderProps.AddProp(prop);\n  }\n  return coderProps.SetProps(scp);\n}\n\n\nint CMethodProps::FindProp(PROPID id) const\n{\n  for (unsigned i = Props.Size(); i != 0;)\n    if (Props[--i].Id == id)\n      return (int)i;\n  return -1;\n}\n\nunsigned CMethodProps::GetLevel() const\n{\n  int i = FindProp(NCoderPropID::kLevel);\n  if (i < 0)\n    return 5;\n  if (Props[(unsigned)i].Value.vt != VT_UI4)\n    return 9;\n  UInt32 level = Props[(unsigned)i].Value.ulVal;\n  // **************** 7-Zip ZS Modification Start ****************\n  // return level > 9 ? 9 : (unsigned)level;\n  return level;\n  // **************** 7-Zip ZS Modification End ****************\n}\n\nstruct CNameToPropID\n{\n  VARTYPE VarType;\n  const char *Name;\n};\n\n\n// the following are related to NCoderPropID::EEnum values\n// NCoderPropID::k_NUM_DEFINED\nstatic const CNameToPropID g_NameToPropID[] =\n{\n  { VT_UI4, \"\" },\n  { VT_UI4, \"d\" },\n  { VT_UI4, \"mem\" },\n  { VT_UI4, \"o\" },\n  { VT_UI8, \"c\" },\n  { VT_UI4, \"pb\" },\n  { VT_UI4, \"lc\" },\n  { VT_UI4, \"lp\" },\n  { VT_UI4, \"fb\" },\n  { VT_BSTR, \"mf\" },\n  { VT_UI4, \"mc\" },\n  { VT_UI4, \"pass\" },\n  { VT_UI4, \"a\" },\n  { VT_UI4, \"mt\" },\n  { VT_BOOL, \"eos\" },\n  { VT_UI4, \"x\" },\n  { VT_UI8, \"reduce\" },\n  { VT_UI8, \"expect\" },\n  { VT_UI8, \"cc\" }, // \"cc\" in v23,  \"b\" in v22.01\n  { VT_UI4, \"check\" },\n  { VT_BSTR, \"filter\" },\n  { VT_UI8, \"memuse\" },\n  { VT_UI8, \"aff\" },\n  { VT_UI4, \"offset\" },\n  { VT_UI4, \"zhb\" },\n  { VT_UI4, \"tgn\" }, // kNumThreadGroups\n  { VT_UI4, \"tgi\" }, // kThreadGroup\n  { VT_UI8, \"tga\" }, // kAffinityInGroup\n  /*\n  ,\n  // { VT_UI4, \"zhc\" },\n  // { VT_UI4, \"zhd\" },\n  // { VT_UI4, \"zcb\" },\n  { VT_UI4, \"dc\" },\n  { VT_UI4, \"zx\" },\n  { VT_UI4, \"zf\" },\n  { VT_UI4, \"zmml\" },\n  { VT_UI4, \"zov\" },\n  { VT_BOOL, \"zmfr\" },\n  { VT_BOOL, \"zle\" }, // long enable\n  // { VT_UI4, \"zldb\" },\n  { VT_UI4, \"zld\" },\n  { VT_UI4, \"zlhb\" },\n  { VT_UI4, \"zlmml\" },\n  { VT_UI4, \"zlbb\" },\n  { VT_UI4, \"zlhrb\" },\n  { VT_BOOL, \"zwus\" },\n  { VT_BOOL, \"zshp\" },\n  { VT_BOOL, \"zshs\" },\n  { VT_BOOL, \"zshe\" },\n  { VT_BOOL, \"zshg\" },\n  { VT_UI4, \"zpsm\" }\n  */\n  // { VT_UI4, \"mcb\" }, // mc log version\n  // { VT_UI4, \"ztlen\" },  // fb ?\n  // **************** 7-Zip ZS Modification Start ****************\n  // zstd props\n  { VT_UI4, \"strat\" },\n  { VT_UI4, \"fast\" },\n  { VT_UI4, \"long\" },\n  { VT_UI4, \"wlog\" },\n  { VT_UI4, \"hlog\" },\n  { VT_UI4, \"clog\" },\n  { VT_UI4, \"slog\" },\n  { VT_UI4, \"slen\" },\n  { VT_UI4, \"tlen\" },\n  { VT_UI4, \"ovlog\" },\n  { VT_UI4, \"ldmhlog\" },\n  { VT_UI4, \"ldmslen\" },\n  { VT_UI4, \"ldmblog\" },\n  { VT_UI4, \"ldmhevery\" },\n  { VT_BOOL, \"max\" }\n  // **************** 7-Zip ZS Modification End ****************\n};\n\n/*\n#if defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 200410L) || (defined(_MSC_VER) && _MSC_VER >= 1600)\n\n#if (defined(__cplusplus) && __cplusplus < 201103L) \\\n    && defined(__clang__) && __clang_major__ >= 4\n#pragma GCC diagnostic ignored \"-Wc11-extensions\"\n#endif\n  static_assert(Z7_ARRAY_SIZE(g_NameToPropID) == NCoderPropID::k_NUM_DEFINED,\n    \"g_NameToPropID doesn't match NCoderPropID enum\");\n#endif\n*/\n// **************** 7-Zip ZS Modification Start ****************\n#if defined(static_assert) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || (_MSC_VER >= 1900)\nstatic_assert(Z7_ARRAY_SIZE(g_NameToPropID) == NCoderPropID::k_NUM_DEFINED,\n    \"g_NameToPropID doesn't match NCoderPropID enum\");\n#endif\n// **************** 7-Zip ZS Modification End ****************\n\nstatic int FindPropIdExact(const UString &name)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NameToPropID); i++)\n    if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name))\n      return (int)i;\n  return -1;\n}\n\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\nstatic bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)\n{\n  if (varType == srcProp.vt)\n  {\n    destProp = srcProp;\n    return true;\n  }\n\n  if (varType == VT_UI8 && srcProp.vt == VT_UI4)\n  {\n    destProp = (UInt64)srcProp.ulVal;\n    return true;\n  }\n\n  if (varType == VT_BOOL)\n  {\n    bool res;\n    if (PROPVARIANT_to_bool(srcProp, res) != S_OK)\n      return false;\n    destProp = res;\n    return true;\n  }\n  if (srcProp.vt == VT_EMPTY)\n  {\n    destProp = srcProp;\n    return true;\n  }\n  return false;\n}\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\nstatic bool ConvertProperty(const UString &name, const PROPVARIANT &srcProp, VARTYPE varType, CProp &destProp)\n{\n  if (varType != srcProp.vt) {\n    // try to convert property from other source type:\n    switch (destProp.Id) {\n      case NCoderPropID::kNumThreads: // on, off or {N}\n        UInt32 val;\n        if (ParseMtProp(name.Ptr(2), srcProp, INT_MAX, val) != S_OK)\n          return false;\n        destProp.Value.ulVal = val;\n        return true;\n      break;\n    }\n  }\n  if (varType == srcProp.vt)\n  {\n    destProp.Value = srcProp;\n    return true;\n  }\n\n  if (varType == VT_UI8 && srcProp.vt == VT_UI4)\n  {\n    destProp.Value = (UInt64)srcProp.ulVal;\n    return true;\n  }\n\n  if (varType == VT_BOOL)\n  {\n    bool res;\n    if (PROPVARIANT_to_bool(srcProp, res) != S_OK)\n      return false;\n    destProp.Value = res;\n    return true;\n  }\n  if (srcProp.vt == VT_EMPTY)\n  {\n    destProp.Value = srcProp;\n    return true;\n  }\n  return false;\n}\n// **************** 7-Zip ZS Modification End ****************\n\nstatic void SplitParams(const UString &srcString, UStringVector &subStrings)\n{\n  subStrings.Clear();\n  UString s;\n  unsigned len = srcString.Len();\n  if (len == 0)\n    return;\n  for (unsigned i = 0; i < len; i++)\n  {\n    wchar_t c = srcString[i];\n    if (c == L':')\n    {\n      subStrings.Add(s);\n      s.Empty();\n    }\n    else\n      s += c;\n  }\n  subStrings.Add(s);\n}\n\nstatic void SplitParam(const UString &param, UString &name, UString &value)\n{\n  int eqPos = param.Find(L'=');\n  if (eqPos >= 0)\n  {\n    name.SetFrom(param, (unsigned)eqPos);\n    value = param.Ptr((unsigned)(eqPos + 1));\n    return;\n  }\n  unsigned i;\n  for (i = 0; i < param.Len(); i++)\n  {\n    wchar_t c = param[i];\n    if (c >= L'0' && c <= L'9')\n      break;\n  }\n  name.SetFrom(param, i);\n  value = param.Ptr(i);\n}\n\nstatic bool IsLogSizeProp(PROPID propid)\n{\n  switch (propid)\n  {\n    case NCoderPropID::kDictionarySize:\n    case NCoderPropID::kUsedMemorySize:\n    case NCoderPropID::kBlockSize:\n    case NCoderPropID::kBlockSize2:\n    /*\n    case NCoderPropID::kChainSize:\n    case NCoderPropID::kLdmWindowSize:\n    */\n    // case NCoderPropID::kReduceSize:\n      return true;\n    default: break;\n  }\n  return false;\n}\n\nHRESULT CMethodProps::SetParam(const UString &name, const UString &value)\n{\n  int index = FindPropIdExact(name);\n  if (index < 0)\n  {\n    // 'b' was used as NCoderPropID::kBlockSize2 before v23\n    if (!name.IsEqualTo_Ascii_NoCase(\"b\") || value.Find(L':') >= 0)\n      return E_INVALIDARG;\n    index = NCoderPropID::kBlockSize2;\n  }\n  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];\n  CProp prop;\n  prop.Id = (unsigned)index;\n\n  if (IsLogSizeProp(prop.Id))\n  {\n    RINOK(StringToDictSize(value, prop.Value))\n  }\n  else\n  {\n    NCOM::CPropVariant propValue;\n    if (nameToPropID.VarType == VT_BSTR)\n      propValue = value;\n    else if (nameToPropID.VarType == VT_BOOL)\n    {\n      bool res;\n      if (!StringToBool(value, res))\n        return E_INVALIDARG;\n      propValue = res;\n    }\n    else if (!value.IsEmpty())\n    {\n      if (nameToPropID.VarType == VT_UI4)\n      {\n        UInt32 number;\n        if (ParseStringToUInt32(value, number) == value.Len())\n          propValue = number;\n        else\n          propValue = value;\n      }\n      else if (nameToPropID.VarType == VT_UI8)\n      {\n        UInt64 number;\n        if (ParseStringToUInt64(value, number) == value.Len())\n          propValue = number;\n        else\n          propValue = value;\n      }\n      else\n        propValue = value;\n    }\n    // **************** 7-Zip ZS Modification Start ****************\n    // if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))\n    if (!ConvertProperty(name, propValue, nameToPropID.VarType, prop))\n    // **************** 7-Zip ZS Modification End ****************\n      return E_INVALIDARG;\n    // **************** 7-Zip ZS Modification Start ****************\n    if (prop.Id == NCoderPropID::kAdvMax && prop.Value.boolVal) {\n      setMaxCompression();\n    }\n    // **************** 7-Zip ZS Modification End ****************\n  }\n  Props.Add(prop);\n  return S_OK;\n}\n\n// **************** 7-Zip ZS Modification Start ****************\nvoid CMethodProps::setMaxCompression()\n{\n  // adjust level (zstd --max), set it to the highest level too (e. g. setting of options.MaxFilter for BCJ2 etc)\n  CProp prop;\n  prop.Id = (unsigned)NCoderPropID::kLevel;\n  prop.Value.vt = VT_UI4;\n  prop.Value.ulVal = Z7_ZSTD_ULTIMATE_LEV;\n  Props.Add(prop);\n}\n// **************** 7-Zip ZS Modification End ****************\n\nHRESULT CMethodProps::ParseParamsFromString(const UString &srcString)\n{\n  UStringVector params;\n  SplitParams(srcString, params);\n  FOR_VECTOR (i, params)\n  {\n    const UString &param = params[i];\n    UString name, value;\n    // **************** 7-Zip ZS Modification Start ****************\n    if (param.IsPrefixedBy_Ascii_NoCase(\"mt\")) { // special handler for mt (to parse correct -mmt-, -mmtd2, -mmtp50u2, etc)\n      UInt32 val;\n      CProp prop;\n      prop.Value.vt = VT_EMPTY;\n      RINOK(ParseMtProp(param.Ptr(2), prop.Value, INT_MAX, val))\n      AddProp32(NCoderPropID::kNumThreads, val);\n      continue;\n    }\n    // **************** 7-Zip ZS Modification End ****************\n    SplitParam(param, name, value);\n    RINOK(SetParam(name, value))\n  }\n  return S_OK;\n}\n\nHRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)\n{\n  if (realName.Len() == 0)\n  {\n    // [empty]=method\n    return E_INVALIDARG;\n  }\n  // **************** 7-Zip ZS Modification Start ****************\n  if (realName.IsPrefixedBy_Ascii_NoCase(\"mt\")) { // special handler for mt (to parse correct -mmt-, -mmtd2, -mmtp50u2, etc)\n    UInt32 val;\n    RINOK(ParseMtProp(realName.Ptr(2), value, INT_MAX, val))\n    AddProp32(NCoderPropID::kNumThreads, val);\n    return S_OK;\n  }\n  // **************** 7-Zip ZS Modification End ****************\n  if (value.vt == VT_EMPTY)\n  {\n    // {realName}=[empty]\n    UString name, valueStr;\n    SplitParam(realName, name, valueStr);\n    return SetParam(name, valueStr);\n  }\n  \n  // {realName}=value\n  const int index = FindPropIdExact(realName);\n  if (index < 0)\n    return E_INVALIDARG;\n  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];\n  CProp prop;\n  prop.Id = (unsigned)index;\n  \n  if (IsLogSizeProp(prop.Id))\n  {\n    RINOK(PROPVARIANT_to_DictSize(value, prop.Value))\n  }\n  else\n  {\n    // **************** 7-Zip ZS Modification Start ****************\n    // if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))\n    if (!ConvertProperty(realName, value, nameToPropID.VarType, prop))\n    // **************** 7-Zip ZS Modification End ****************\n      return E_INVALIDARG;\n    // **************** 7-Zip ZS Modification Start ****************\n    if (prop.Id == NCoderPropID::kAdvMax && prop.Value.boolVal) {\n      setMaxCompression();\n  }\n    // **************** 7-Zip ZS Modification End ****************\n  }\n  Props.Add(prop);\n  return S_OK;\n}\n\n\nstatic UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads)\n{\n  UInt32 hs = dict - 1;\n  hs |= (hs >> 1);\n  hs |= (hs >> 2);\n  hs |= (hs >> 4);\n  hs |= (hs >> 8);\n  hs >>= 1;\n  if (hs >= (1 << 24))\n    hs >>= 1;\n  hs |= (1 << 16) - 1;\n  // if (numHashBytes >= 5)\n  if (!isBt)\n    hs |= (256 << 10) - 1;\n  hs++;\n  UInt64 size1 = (UInt64)hs * 4;\n  size1 += (UInt64)dict * 4;\n  if (isBt)\n    size1 += (UInt64)dict * 4;\n  size1 += (2 << 20);\n  \n  if (numThreads > 1 && isBt)\n    size1 += (2 << 20) + (4 << 20);\n  return size1;\n}\n\nstatic const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28;\n\nUInt64 CMethodProps::Get_Lzma_MemUsage(bool addSlidingWindowSize) const\n{\n  const UInt64 dicSize = Get_Lzma_DicSize();\n  const bool isBt = Get_Lzma_MatchFinder_IsBt();\n  const UInt32 dict32 = (dicSize >= kLzmaMaxDictSize ? kLzmaMaxDictSize : (UInt32)dicSize);\n  const UInt32 numThreads = Get_Lzma_NumThreads();\n  UInt64 size = GetMemoryUsage_LZMA(dict32, isBt, numThreads);\n  \n  if (addSlidingWindowSize)\n  {\n    const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16);\n    UInt64 blockSize = (UInt64)dict32 + (1 << 16)\n        + (numThreads > 1 ? (1 << 20) : 0);\n    blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2));\n    if (blockSize >= kBlockSizeMax)\n      blockSize = kBlockSizeMax;\n    size += blockSize;\n  }\n  return size;\n}\n\n\n\n\nHRESULT COneMethodInfo::ParseMethodFromString(const UString &s)\n{\n  MethodName.Empty();\n  int splitPos = s.Find(L':');\n  {\n    UString temp = s;\n    if (splitPos >= 0)\n      temp.DeleteFrom((unsigned)splitPos);\n    if (!temp.IsAscii())\n      return E_INVALIDARG;\n    MethodName.SetFromWStr_if_Ascii(temp);\n  }\n  if (splitPos < 0)\n    return S_OK;\n  PropsString = s.Ptr((unsigned)(splitPos + 1));\n  return ParseParamsFromString(PropsString);\n}\n\nHRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)\n{\n  // **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n  if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, \"m\"))\n    return ParseParamsFromPROPVARIANT(realName, value);\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n  if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, \"m\")) {\n    if (value.vt == VT_BSTR && StringsAreEqualNoCase_Ascii(realName, \"memuse\")) {\n      // not implemented here (see one of the ParseSizeString variants), \n      // but don't throw error - just return without to restrict mem-usage (handler may do that).\n      return S_OK;\n    }\n    return ParseParamsFromPROPVARIANT(realName, value);\n  }\n  // **************** 7-Zip ZS Modification End ****************\n  // -m{N}=method\n  if (value.vt != VT_BSTR)\n    return E_INVALIDARG;\n  UString s;\n  s = value.bstrVal;\n  return ParseMethodFromString(s);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/MethodProps.h",
    "content": "﻿// MethodProps.h\n\n#ifndef ZIP7_INC_7Z_METHOD_PROPS_H\n#define ZIP7_INC_7Z_METHOD_PROPS_H\n\n#include \"../../Common/MyString.h\"\n#include \"../../Common/Defs.h\"\n\n#include \"../../Windows/Defs.h\"\n\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../ICoder.h\"\n\n// UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads);\n\ninline UInt64 Calc_From_Val_Percents_Less100(UInt64 val, UInt64 percents)\n{\n  if (percents == 0)\n    return 0;\n  if (val <= (UInt64)(Int64)-1 / percents)\n    return val * percents / 100;\n  return val / 100 * percents;\n}\n\nUInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents);\n\nbool StringToBool(const wchar_t *s, bool &res);\nHRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);\nunsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);\n\n/*\nif (name.IsEmpty() && prop.vt == VT_EMPTY), it doesn't change (resValue) and returns S_OK.\n  So you must set (resValue) for default value before calling */\nHRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);\n\n/* input: (numThreads = the_number_of_processors) */\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\nHRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force);\n\ninline HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads)\n{\n  bool forced = false;\n  numThreads = numCPUs;\n  return ParseMtProp2(name, prop, numThreads, forced);\n}\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\nHRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads);\n// **************** 7-Zip ZS Modification End ****************\n\n\nstruct CProp\n{\n  PROPID Id;\n  bool IsOptional;\n  NWindows::NCOM::CPropVariant Value;\n  CProp(): IsOptional(false) {}\n};\n\nstruct CProps\n{\n  CObjectVector<CProp> Props;\n\n  void Clear() { Props.Clear(); }\n\n  bool AreThereNonOptionalProps() const\n  {\n    FOR_VECTOR (i, Props)\n      if (!Props[i].IsOptional)\n        return true;\n    return false;\n  }\n\n  void AddProp32(PROPID propid, UInt32 val);\n  \n  void AddPropBool(PROPID propid, bool val);\n\n  void AddProp_Ascii(PROPID propid, const char *s)\n  {\n    CProp &prop = Props.AddNew();\n    prop.IsOptional = true;\n    prop.Id = propid;\n    prop.Value = s;\n  }\n\n  HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const;\n  HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp,\n      const UInt64 *dataSizeReduce,\n      const UInt64 *affinity,\n      const UInt32 *affinityGroup,\n      const UInt64 *affinityInGroup) const;\n};\n\nclass CMethodProps: public CProps\n{\n  HRESULT SetParam(const UString &name, const UString &value);\n  // **************** 7-Zip ZS Modification Start ****************\n  void setMaxCompression();\n  // **************** 7-Zip ZS Modification End ****************\npublic:\n  unsigned GetLevel() const;\n  int Get_NumThreads() const\n  {\n    const int i = FindProp(NCoderPropID::kNumThreads);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_UI4)\n        return (int)val.ulVal;\n    }\n    return -1;\n  }\n\n  bool Get_DicSize(UInt64 &res) const\n  {\n    res = 0;\n    const int i = FindProp(NCoderPropID::kDictionarySize);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_UI4)\n      {\n        res = val.ulVal;\n        return true;\n      }\n      if (val.vt == VT_UI8)\n      {\n        res = val.uhVal.QuadPart;\n        return true;\n      }\n    }\n    return false;\n  }\n\n  int FindProp(PROPID id) const;\n\n  UInt32 Get_Lzma_Algo() const\n  {\n    const int i = FindProp(NCoderPropID::kAlgorithm);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_UI4)\n        return val.ulVal;\n    }\n    return GetLevel() >= 5 ? 1 : 0;\n  }\n\n  UInt64 Get_Lzma_DicSize() const\n  {\n    UInt64 v;\n    if (Get_DicSize(v))\n      return v;\n    const unsigned level = GetLevel();\n    const UInt32 dictSize = level <= 4 ?\n        (UInt32)1 << (level * 2 + 16) :\n        level <= sizeof(size_t) / 2 + 4 ?\n          (UInt32)1 << (level + 20) :\n          (UInt32)1 << (sizeof(size_t) / 2 + 24);\n    return dictSize;\n  }\n\n  bool Get_Lzma_MatchFinder_IsBt() const\n  {\n    const int i = FindProp(NCoderPropID::kMatchFinder);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_BSTR)\n        return ((val.bstrVal[0] | 0x20) != 'h'); // check for \"hc\"\n    }\n    return GetLevel() >= 5;\n  }\n\n  bool Get_Lzma_Eos() const\n  {\n    const int i = FindProp(NCoderPropID::kEndMarker);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_BOOL)\n        return VARIANT_BOOLToBool(val.boolVal);\n    }\n    return false;\n  }\n\n  bool Are_Lzma_Model_Props_Defined() const\n  {\n    if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true;\n    if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true;\n    if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true;\n    return false;\n  }\n\n  UInt32 Get_Lzma_NumThreads() const\n  {\n    if (Get_Lzma_Algo() == 0)\n      return 1;\n    int numThreads = Get_NumThreads();\n    if (numThreads >= 0)\n      return numThreads < 2 ? 1 : 2;\n    return 2;\n  }\n\n  UInt64 Get_Lzma_MemUsage(bool addSlidingWindowSize) const;\n\n  /* returns -1, if numThreads is unknown */\n  int Get_Xz_NumThreads(UInt32 &lzmaThreads) const\n  {\n    lzmaThreads = 1;\n    int numThreads = Get_NumThreads();\n    if (numThreads >= 0 && numThreads <= 1)\n      return 1;\n    if (Get_Lzma_Algo() != 0)\n      lzmaThreads = 2;\n    return numThreads;\n  }\n\n  UInt64 GetProp_BlockSize(PROPID id) const\n  {\n    const int i = FindProp(id);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_UI4) { return val.ulVal; }\n      if (val.vt == VT_UI8) { return val.uhVal.QuadPart; }\n    }\n    return 0;\n  }\n\n  UInt64 Get_Xz_BlockSize() const\n  {\n    {\n      UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize);\n      UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2);\n      UInt64 minSize = MyMin(blockSize1, blockSize2);\n      if (minSize != 0)\n        return minSize;\n      UInt64 maxSize = MyMax(blockSize1, blockSize2);\n      if (maxSize != 0)\n        return maxSize;\n    }\n    const UInt32 kMinSize = (UInt32)1 << 20;\n    const UInt32 kMaxSize = (UInt32)1 << 28;\n    const UInt64 dictSize = Get_Lzma_DicSize();\n    /* lzma2 code uses fake 4 GiB to calculate ChunkSize. So we do same */\n    UInt64 blockSize = (UInt64)dictSize << 2;\n    if (blockSize < kMinSize) blockSize = kMinSize;\n    if (blockSize > kMaxSize) blockSize = kMaxSize;\n    if (blockSize < dictSize) blockSize = dictSize;\n    blockSize += (kMinSize - 1);\n    blockSize &= ~(UInt64)(kMinSize - 1);\n    return blockSize;\n  }\n\n\n  UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const\n  {\n    fixedNumber = false;\n    int numThreads = Get_NumThreads();\n    if (numThreads >= 0)\n    {\n      fixedNumber = true;\n      if (numThreads < 1) return 1;\n      const unsigned kNumBZip2ThreadsMax = 64;\n      if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax;\n      return (unsigned)numThreads;\n    }\n    return 1;\n  }\n\n  UInt32 Get_BZip2_BlockSize() const\n  {\n    const int i = FindProp(NCoderPropID::kDictionarySize);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_UI4)\n      {\n        UInt32 blockSize = val.ulVal;\n        const UInt32 kDicSizeMin = 100000;\n        const UInt32 kDicSizeMax = 900000;\n        if (blockSize < kDicSizeMin) blockSize = kDicSizeMin;\n        if (blockSize > kDicSizeMax) blockSize = kDicSizeMax;\n        return blockSize;\n      }\n    }\n    const unsigned level = GetLevel();\n    return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));\n  }\n\n  UInt64 Get_Ppmd_MemSize() const\n  {\n    const int i = FindProp(NCoderPropID::kUsedMemorySize);\n    if (i >= 0)\n    {\n      const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;\n      if (val.vt == VT_UI4)\n        return val.ulVal;\n      if (val.vt == VT_UI8)\n        return val.uhVal.QuadPart;\n    }\n    const unsigned level = GetLevel();\n    const UInt32 mem = (UInt32)1 << (level + 19);\n    return mem;\n  }\n\n  void AddProp_Level(UInt32 level)\n  {\n    AddProp32(NCoderPropID::kLevel, level);\n  }\n\n  void AddProp_NumThreads(UInt32 numThreads)\n  {\n    AddProp32(NCoderPropID::kNumThreads, numThreads);\n  }\n\n  void AddProp_EndMarker_if_NotFound(bool eos)\n  {\n    if (FindProp(NCoderPropID::kEndMarker) < 0)\n      AddPropBool(NCoderPropID::kEndMarker, eos);\n  }\n\n  void AddProp_BlockSize2(UInt64 blockSize2)\n  {\n    if (FindProp(NCoderPropID::kBlockSize2) < 0)\n    {\n      CProp &prop = Props.AddNew();\n      prop.IsOptional = true;\n      prop.Id = NCoderPropID::kBlockSize2;\n      prop.Value = blockSize2;\n    }\n  }\n\n  HRESULT ParseParamsFromString(const UString &srcString);\n  HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);\n};\n\nclass COneMethodInfo: public CMethodProps\n{\npublic:\n  AString MethodName;\n  UString PropsString;\n  \n  void Clear()\n  {\n    CMethodProps::Clear();\n    MethodName.Empty();\n    PropsString.Empty();\n  }\n  bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }\n  HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);\n  HRESULT ParseMethodFromString(const UString &s);\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/OffsetStream.cpp",
    "content": "﻿// OffsetStream.cpp\n\n#include \"StdAfx.h\"\n\n#include \"OffsetStream.h\"\n\nHRESULT COffsetOutStream::Init(IOutStream *stream, UInt64 offset)\n{\n  _offset = offset;\n  _stream = stream;\n  return _stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL);\n}\n\nZ7_COM7F_IMF(COffsetOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  return _stream->Write(data, size, processedSize);\n}\n\nZ7_COM7F_IMF(COffsetOutStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  if (seekOrigin == STREAM_SEEK_SET)\n  {\n    if (offset < 0)\n      return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n    offset += _offset;\n  }\n  UInt64 absoluteNewPosition = 0; // =0 for gcc-10\n  const HRESULT result = _stream->Seek(offset, seekOrigin, &absoluteNewPosition);\n  if (newPosition)\n    *newPosition = absoluteNewPosition - _offset;\n  return result;\n}\n\nZ7_COM7F_IMF(COffsetOutStream::SetSize(UInt64 newSize))\n{\n  return _stream->SetSize(_offset + newSize);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/OffsetStream.h",
    "content": "﻿// OffsetStream.h\n\n#ifndef ZIP7_INC_OFFSET_STREAM_H\n#define ZIP7_INC_OFFSET_STREAM_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../IStream.h\"\n\nZ7_CLASS_IMP_NOQIB_1(\n  COffsetOutStream\n  , IOutStream\n)\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\n\n  CMyComPtr<IOutStream> _stream;\n  UInt64 _offset;\npublic:\n  HRESULT Init(IOutStream *stream, UInt64 offset);\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/OutBuffer.cpp",
    "content": "﻿// OutBuffer.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"OutBuffer.h\"\n\nbool COutBuffer::Create(UInt32 bufSize) throw()\n{\n  const UInt32 kMinBlockSize = 1;\n  if (bufSize < kMinBlockSize)\n    bufSize = kMinBlockSize;\n  if (_buf && _bufSize == bufSize)\n    return true;\n  Free();\n  _bufSize = bufSize;\n  _buf = (Byte *)::MidAlloc(bufSize);\n  return (_buf != NULL);\n}\n\nvoid COutBuffer::Free() throw()\n{\n  ::MidFree(_buf);\n  _buf = NULL;\n}\n\nvoid COutBuffer::Init() throw()\n{\n  _streamPos = 0;\n  _limitPos = _bufSize;\n  _pos = 0;\n  _processedSize = 0;\n  _overDict = false;\n  #ifdef Z7_NO_EXCEPTIONS\n  ErrorCode = S_OK;\n  #endif\n}\n\nUInt64 COutBuffer::GetProcessedSize() const throw()\n{\n  UInt64 res = _processedSize + _pos - _streamPos;\n  if (_streamPos > _pos)\n    res += _bufSize;\n  return res;\n}\n\n\nHRESULT COutBuffer::FlushPart() throw()\n{\n  // _streamPos < _bufSize\n  UInt32 size = (_streamPos >= _pos) ? (_bufSize - _streamPos) : (_pos - _streamPos);\n  HRESULT result = S_OK;\n  #ifdef Z7_NO_EXCEPTIONS\n  result = ErrorCode;\n  #endif\n  if (_buf2)\n  {\n    memcpy(_buf2, _buf + _streamPos, size);\n    _buf2 += size;\n  }\n\n  if (_stream\n      #ifdef Z7_NO_EXCEPTIONS\n      && (ErrorCode == S_OK)\n      #endif\n     )\n  {\n    UInt32 processedSize = 0;\n    result = _stream->Write(_buf + _streamPos, size, &processedSize);\n    size = processedSize;\n  }\n  _streamPos += size;\n  if (_streamPos == _bufSize)\n    _streamPos = 0;\n  if (_pos == _bufSize)\n  {\n    _overDict = true;\n    _pos = 0;\n  }\n  _limitPos = (_streamPos > _pos) ? _streamPos : _bufSize;\n  _processedSize += size;\n  return result;\n}\n\nHRESULT COutBuffer::Flush() throw()\n{\n  #ifdef Z7_NO_EXCEPTIONS\n  if (ErrorCode != S_OK)\n    return ErrorCode;\n  #endif\n\n  while (_streamPos != _pos)\n  {\n    const HRESULT result = FlushPart();\n    if (result != S_OK)\n      return result;\n  }\n  return S_OK;\n}\n\nvoid COutBuffer::FlushWithCheck()\n{\n  const HRESULT result = Flush();\n  #ifdef Z7_NO_EXCEPTIONS\n  ErrorCode = result;\n  #else\n  if (result != S_OK)\n    throw COutBufferException(result);\n  #endif\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/OutBuffer.h",
    "content": "﻿// OutBuffer.h\n\n#ifndef ZIP7_INC_OUT_BUFFER_H\n#define ZIP7_INC_OUT_BUFFER_H\n\n#include \"../IStream.h\"\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/MyException.h\"\n\n#ifndef Z7_NO_EXCEPTIONS\nstruct COutBufferException: public CSystemException\n{\n  COutBufferException(HRESULT errorCode): CSystemException(errorCode) {}\n};\n#endif\n\nclass COutBuffer\n{\nprotected:\n  Byte *_buf;\n  UInt32 _pos;\n  UInt32 _limitPos;\n  UInt32 _streamPos;\n  UInt32 _bufSize;\n  ISequentialOutStream *_stream;\n  UInt64 _processedSize;\n  Byte  *_buf2;\n  bool _overDict;\n\n  HRESULT FlushPart() throw();\npublic:\n  #ifdef Z7_NO_EXCEPTIONS\n  HRESULT ErrorCode;\n  #endif\n\n  COutBuffer(): _buf(NULL), _pos(0), _stream(NULL), _buf2(NULL) {}\n  ~COutBuffer() { Free(); }\n  \n  bool Create(UInt32 bufSize) throw();\n  void Free() throw();\n\n  void SetMemStream(Byte *buf) { _buf2 = buf; }\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void Init() throw();\n  HRESULT Flush() throw();\n  void FlushWithCheck();\n\n  Z7_FORCE_INLINE\n  void WriteByte(Byte b)\n  {\n    UInt32 pos = _pos;\n    _buf[pos] = b;\n    pos++;\n    _pos = pos;\n    if (pos == _limitPos)\n      FlushWithCheck();\n  }\n  \n  void WriteBytes(const void *data, size_t size)\n  {\n    while (size)\n    {\n      UInt32 pos = _pos;\n      size_t cur = (size_t)(_limitPos - pos);\n      if (cur >= size)\n        cur = size;\n      size -= cur;\n      Byte *dest = _buf + pos;\n      pos += (UInt32)cur;\n      _pos = pos;\n#if 0\n      memcpy(dest, data, cur);\n      data = (const void *)((const Byte *)data + cur);\n#else\n      const Byte * const lim = (const Byte *)data + cur;\n      do\n      {\n        *dest++ = *(const Byte *)data;\n        data = (const void *)((const Byte *)data + 1);\n      }\n      while (data != lim);\n#endif\n      if (pos == _limitPos)\n        FlushWithCheck();\n    }\n  }\n\n  Byte *GetOutBuffer(size_t &avail)\n  {\n    const UInt32 pos = _pos;\n    avail = (size_t)(_limitPos - pos);\n    return _buf + pos;\n  }\n\n  void SkipWrittenBytes(size_t num)\n  {\n    const UInt32 pos = _pos;\n    const UInt32 rem = _limitPos - pos;\n    if (rem > num)\n    {\n      _pos = pos + (UInt32)num;\n      return;\n    }\n    // (rem <= num)\n    // the caller must not call it with (rem < num)\n    // so (rem == num)\n    _pos = _limitPos;\n    FlushWithCheck();\n  }\n  /*\n  void WriteBytesBig(const void *data, size_t size)\n  {\n    while (size)\n    {\n      UInt32 pos = _pos;\n      UInt32 rem = _limitPos - pos;\n      if (rem > size)\n      {\n        _pos = pos + size;\n        memcpy(_buf + pos, data, size);\n        return;\n      }\n      memcpy(_buf + pos, data, rem);\n      _pos = pos + rem;\n      FlushWithCheck();\n    }\n  }\n  */\n\n  UInt64 GetProcessedSize() const throw();\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/OutMemStream.cpp",
    "content": "﻿// OutMemStream.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"OutMemStream.h\"\n\nvoid COutMemStream::Free()\n{\n  Blocks.Free(_memManager);\n  Blocks.LockMode = true;\n}\n\nvoid COutMemStream::Init()\n{\n  WriteToRealStreamEvent.Reset();\n  _unlockEventWasSent = false;\n  _realStreamMode = false;\n  Free();\n  _curBlockPos = 0;\n  _curBlockIndex = 0;\n}\n\nvoid COutMemStream::DetachData(CMemLockBlocks &blocks)\n{\n  Blocks.Detach(blocks, _memManager);\n  Free();\n}\n\n\nHRESULT COutMemStream::WriteToRealStream()\n{\n  RINOK(Blocks.WriteToStream(_memManager->GetBlockSize(), OutSeqStream))\n  Blocks.Free(_memManager);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(COutMemStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (_realStreamMode)\n    return OutSeqStream->Write(data, size, processedSize);\n  if (processedSize)\n    *processedSize = 0;\n  while (size != 0)\n  {\n    if (_curBlockIndex < Blocks.Blocks.Size())\n    {\n      Byte *p = (Byte *)Blocks.Blocks[_curBlockIndex] + _curBlockPos;\n      size_t curSize = _memManager->GetBlockSize() - _curBlockPos;\n      if (size < curSize)\n        curSize = size;\n      memcpy(p, data, curSize);\n      if (processedSize)\n        *processedSize += (UInt32)curSize;\n      data = (const void *)((const Byte *)data + curSize);\n      size -= (UInt32)curSize;\n      _curBlockPos += curSize;\n\n      const UInt64 pos64 = GetPos();\n      if (pos64 > Blocks.TotalSize)\n        Blocks.TotalSize = pos64;\n      if (_curBlockPos == _memManager->GetBlockSize())\n      {\n        _curBlockIndex++;\n        _curBlockPos = 0;\n      }\n      continue;\n    }\n\n    const NWindows::NSynchronization::CHandle_WFMO events[3] =\n      { StopWritingEvent, WriteToRealStreamEvent, /* NoLockEvent, */ _memManager->Semaphore };\n    const DWORD waitResult = NWindows::NSynchronization::WaitForMultiObj_Any_Infinite(\n        ((Blocks.LockMode /* && _memManager->Semaphore.IsCreated() */) ? 3 : 2), events);\n    \n    // printf(\"\\n 1- outMemStream %d\\n\", waitResult - WAIT_OBJECT_0);\n\n    switch (waitResult)\n    {\n      case (WAIT_OBJECT_0 + 0):\n        return StopWriteResult;\n      case (WAIT_OBJECT_0 + 1):\n      {\n        _realStreamMode = true;\n        RINOK(WriteToRealStream())\n        UInt32 processedSize2;\n        const HRESULT res = OutSeqStream->Write(data, size, &processedSize2);\n        if (processedSize)\n          *processedSize += processedSize2;\n        return res;\n      }\n      case (WAIT_OBJECT_0 + 2):\n      {\n        // it has bug: no write.\n        /*\n        if (!Blocks.SwitchToNoLockMode(_memManager))\n          return E_FAIL;\n        */\n        break;\n      }\n      default:\n      {\n        if (waitResult == WAIT_FAILED)\n        {\n          const DWORD res = ::GetLastError();\n          if (res != 0)\n            return HRESULT_FROM_WIN32(res);\n        }\n        return E_FAIL;\n      }\n    }\n    void *p = _memManager->AllocateBlock();\n    if (!p)\n      return E_FAIL;\n    Blocks.Blocks.Add(p);\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(COutMemStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  if (_realStreamMode)\n  {\n    if (!OutStream)\n      return E_FAIL;\n    return OutStream->Seek(offset, seekOrigin, newPosition);\n  }\n  if (seekOrigin == STREAM_SEEK_CUR)\n  {\n    if (offset != 0)\n      return E_NOTIMPL;\n  }\n  else if (seekOrigin == STREAM_SEEK_SET)\n  {\n    if (offset != 0)\n      return E_NOTIMPL;\n    _curBlockIndex = 0;\n    _curBlockPos = 0;\n  }\n  else\n    return E_NOTIMPL;\n  if (newPosition)\n    *newPosition = GetPos();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(COutMemStream::SetSize(UInt64 newSize))\n{\n  if (_realStreamMode)\n  {\n    if (!OutStream)\n      return E_FAIL;\n    return OutStream->SetSize(newSize);\n  }\n  Blocks.TotalSize = newSize;\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/OutMemStream.h",
    "content": "﻿// OutMemStream.h\n\n#ifndef ZIP7_INC_OUT_MEM_STREAM_H\n#define ZIP7_INC_OUT_MEM_STREAM_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"MemBlocks.h\"\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutMemStream\n  , IOutStream\n)\n  Z7_IFACE_COM7_IMP(ISequentialOutStream)\n\n  CMemBlockManagerMt *_memManager;\n  size_t _curBlockPos;\n  unsigned _curBlockIndex;\n  bool _realStreamMode;\n\n  bool _unlockEventWasSent;\n  NWindows::NSynchronization::CAutoResetEvent_WFMO StopWritingEvent;\n  NWindows::NSynchronization::CAutoResetEvent_WFMO WriteToRealStreamEvent;\n  // NWindows::NSynchronization::CAutoResetEvent NoLockEvent;\n\n  HRESULT StopWriteResult;\n  CMemLockBlocks Blocks;\n\n  CMyComPtr<ISequentialOutStream> OutSeqStream;\n  CMyComPtr<IOutStream> OutStream;\n\n  UInt64 GetPos() const { return (UInt64)_curBlockIndex * _memManager->GetBlockSize() + _curBlockPos; }\n\npublic:\n\n  HRESULT CreateEvents(SYNC_PARAM_DECL(synchro))\n  {\n    WRes wres = StopWritingEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro));\n    if (wres == 0)\n      wres = WriteToRealStreamEvent.CreateIfNotCreated_Reset(SYNC_WFMO(synchro));\n    return HRESULT_FROM_WIN32(wres);\n  }\n\n  void SetOutStream(IOutStream *outStream)\n  {\n    OutStream = outStream;\n    OutSeqStream = outStream;\n  }\n\n  void SetSeqOutStream(ISequentialOutStream *outStream)\n  {\n    OutStream = NULL;\n    OutSeqStream = outStream;\n  }\n\n  void ReleaseOutStream()\n  {\n    OutStream.Release();\n    OutSeqStream.Release();\n  }\n\n  COutMemStream(CMemBlockManagerMt *memManager):\n      _memManager(memManager)\n  {\n    /*\n    #ifndef _WIN32\n    StopWritingEvent._sync       =\n    WriteToRealStreamEvent._sync =  &memManager->Synchro;\n    #endif\n    */\n  }\n\n  ~COutMemStream() { Free(); }\n  void Free();\n\n  void Init();\n  HRESULT WriteToRealStream();\n\n  void DetachData(CMemLockBlocks &blocks);\n\n  bool WasUnlockEventSent() const { return _unlockEventWasSent; }\n\n  void SetRealStreamMode()\n  {\n    _unlockEventWasSent = true;\n    WriteToRealStreamEvent.Set();\n  }\n\n  /*\n  void SetNoLockMode()\n  {\n    _unlockEventWasSent = true;\n    NoLockEvent.Set();\n  }\n  */\n\n  void StopWriting(HRESULT res)\n  {\n    StopWriteResult = res;\n    StopWritingEvent.Set();\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/ProgressMt.cpp",
    "content": "﻿// ProgressMt.h\n\n#include \"StdAfx.h\"\n\n#include \"ProgressMt.h\"\n\nvoid CMtCompressProgressMixer::Init(unsigned numItems, ICompressProgressInfo *progress)\n{\n  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\n  InSizes.Clear();\n  OutSizes.Clear();\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    InSizes.Add(0);\n    OutSizes.Add(0);\n  }\n  TotalInSize = 0;\n  TotalOutSize = 0;\n  _progress = progress;\n}\n\nvoid CMtCompressProgressMixer::Reinit(unsigned index)\n{\n  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\n  InSizes[index] = 0;\n  OutSizes[index] = 0;\n}\n\nHRESULT CMtCompressProgressMixer::SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize)\n{\n  NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);\n  if (inSize)\n  {\n    const UInt64 diff = *inSize - InSizes[index];\n    InSizes[index] = *inSize;\n    TotalInSize += diff;\n  }\n  if (outSize)\n  {\n    const UInt64 diff = *outSize - OutSizes[index];\n    OutSizes[index] = *outSize;\n    TotalOutSize += diff;\n  }\n  if (_progress)\n    return _progress->SetRatioInfo(&TotalInSize, &TotalOutSize);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CMtCompressProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  return _progress->SetRatioInfo(_index, inSize, outSize);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/ProgressMt.h",
    "content": "﻿// ProgressMt.h\n\n#ifndef ZIP7_INC_PROGRESSMT_H\n#define ZIP7_INC_PROGRESSMT_H\n\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/MyVector.h\"\n#include \"../../Windows/Synchronization.h\"\n\n#include \"../ICoder.h\"\n#include \"../IProgress.h\"\n\nclass CMtCompressProgressMixer\n{\n  CMyComPtr<ICompressProgressInfo> _progress;\n  CRecordVector<UInt64> InSizes;\n  CRecordVector<UInt64> OutSizes;\n  UInt64 TotalInSize;\n  UInt64 TotalOutSize;\npublic:\n  NWindows::NSynchronization::CCriticalSection CriticalSection;\n  void Init(unsigned numItems, ICompressProgressInfo *progress);\n  void Reinit(unsigned index);\n  HRESULT SetRatioInfo(unsigned index, const UInt64 *inSize, const UInt64 *outSize);\n};\n\n\nZ7_CLASS_IMP_NOQIB_1(\n  CMtCompressProgress\n  , ICompressProgressInfo\n)\n  unsigned _index;\n  CMtCompressProgressMixer *_progress;\npublic:\n  void Init(CMtCompressProgressMixer *progress, unsigned index)\n  {\n    _progress = progress;\n    _index = index;\n  }\n  void Reinit() { _progress->Reinit(_index); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/ProgressUtils.cpp",
    "content": "﻿// ProgressUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"ProgressUtils.h\"\n\nCLocalProgress::CLocalProgress():\n    SendRatio(true),\n    SendProgress(true),\n    ProgressOffset(0),\n    InSize(0),\n    OutSize(0)\n  {}\n\nvoid CLocalProgress::Init(IProgress *progress, bool inSizeIsMain)\n{\n  _ratioProgress.Release();\n  _progress = progress;\n  _progress.QueryInterface(IID_ICompressProgressInfo, &_ratioProgress);\n  _inSizeIsMain = inSizeIsMain;\n}\n\nZ7_COM7F_IMF(CLocalProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  UInt64 inSize2 = InSize;\n  UInt64 outSize2 = OutSize;\n  \n  if (inSize)\n    inSize2 += (*inSize);\n  if (outSize)\n    outSize2 += (*outSize);\n  \n  if (SendRatio && _ratioProgress)\n  {\n    RINOK(_ratioProgress->SetRatioInfo(&inSize2, &outSize2))\n  }\n  \n  if (SendProgress)\n  {\n    inSize2 += ProgressOffset;\n    outSize2 += ProgressOffset;\n    return _progress->SetCompleted(_inSizeIsMain ? &inSize2 : &outSize2);\n  }\n  \n  return S_OK;\n}\n\nHRESULT CLocalProgress::SetCur()\n{\n  return SetRatioInfo(NULL, NULL);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/ProgressUtils.h",
    "content": "﻿// ProgressUtils.h\n\n#ifndef ZIP7_INC_PROGRESS_UTILS_H\n#define ZIP7_INC_PROGRESS_UTILS_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n#include \"../IProgress.h\"\n\nZ7_CLASS_IMP_COM_1(\n  CLocalProgress\n  , ICompressProgressInfo\n)\npublic:\n  bool SendRatio;\n  bool SendProgress;\nprivate:\n  bool _inSizeIsMain;\n  CMyComPtr<IProgress> _progress;\n  CMyComPtr<ICompressProgressInfo> _ratioProgress;\npublic:\n  UInt64 ProgressOffset;\n  UInt64 InSize;\n  UInt64 OutSize;\n\n  CLocalProgress();\n\n  void Init(IProgress *progress, bool inSizeIsMain);\n  HRESULT SetCur();\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/PropId.cpp",
    "content": "﻿// PropId.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/MyWindows.h\"\n\n#include \"../PropID.h\"\n\n// VARTYPE\nconst Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED] =\n{\n  VT_EMPTY,\n  VT_UI4,\n  VT_UI4,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BOOL,\n  VT_UI8,\n  VT_UI8,\n  VT_UI4,\n  VT_FILETIME,\n  VT_FILETIME,\n  VT_FILETIME,\n  VT_BOOL,\n  VT_BOOL,\n  VT_BOOL,\n  VT_BOOL,\n  VT_BOOL,\n  VT_UI4,\n  VT_UI4,\n  VT_BSTR,\n  VT_BOOL,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR,\n  VT_UI8,\n  VT_BSTR,\n  VT_UI8,\n  VT_BSTR,\n  VT_UI8,\n  VT_UI8,\n  VT_BSTR, // or VT_UI8 kpidUnpackVer\n  VT_UI4, // or VT_UI8 kpidVolume\n  VT_BOOL,\n  VT_UI8,\n  VT_UI8,\n  VT_UI8,\n  VT_UI8,\n  VT_UI4,\n  VT_BOOL,\n  VT_BOOL,\n  VT_BSTR,\n  VT_UI8,\n  VT_UI8,\n  VT_UI4, // kpidChecksum\n  VT_BSTR,\n  VT_UI8,\n  VT_BSTR, // or VT_UI8 kpidId\n  VT_BSTR,\n  VT_BSTR,\n  VT_UI4,\n  VT_UI4,\n  VT_BSTR,\n  VT_BSTR,\n  VT_UI8,\n  VT_UI8,\n  VT_UI4,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR, // kpidNtSecure\n  VT_BOOL,\n  VT_BOOL,\n  VT_BOOL,\n  VT_BOOL,\n  VT_BSTR, // SHA-1\n  VT_BSTR, // SHA-256\n  VT_BSTR,\n  VT_UI8,\n  VT_UI4,\n  VT_UI4,\n  VT_BSTR,\n  VT_UI8,\n  VT_UI8,\n  VT_UI8,\n  VT_UI8,\n  VT_UI8,\n  VT_UI8,\n  VT_UI8,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BOOL,\n  VT_BOOL,\n  VT_BOOL,\n  VT_UI8,\n  VT_UI8,\n  VT_BSTR, // kpidNtReparse\n  VT_BSTR,\n  VT_UI8,\n  VT_UI8,\n  VT_BOOL,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BSTR,\n  VT_BOOL,\n  VT_FILETIME, // kpidChangeTime\n  VT_UI4,\n  VT_UI4,\n  VT_UI4,\n  VT_UI4,\n  VT_UI4,\n  VT_UI4  // kpidDevMinor\n};\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/RegisterArc.h",
    "content": "﻿// RegisterArc.h\n\n#ifndef ZIP7_INC_REGISTER_ARC_H\n#define ZIP7_INC_REGISTER_ARC_H\n\n#include \"../Archive/IArchive.h\"\n\nstruct CArcInfo\n{\n  UInt32 Flags;\n  Byte Id;\n  Byte SignatureSize;\n  UInt16 SignatureOffset;\n  \n  const Byte *Signature;\n  const char *Name;\n  const char *Ext;\n  const char *AddExt;\n  \n  UInt32 TimeFlags;\n\n  Func_CreateInArchive CreateInArchive;\n  Func_CreateOutArchive CreateOutArchive;\n  Func_IsArc IsArc;\n\n  bool IsMultiSignature() const { return (Flags & NArcInfoFlags::kMultiSignature) != 0; }\n};\n\nvoid RegisterArc(const CArcInfo *arcInfo) throw();\n\n\n#define IMP_CreateArcIn_2(c) \\\n  static IInArchive *CreateArc() { return new c; }\n\n#define IMP_CreateArcIn IMP_CreateArcIn_2(CHandler())\n\n#ifdef Z7_EXTRACT_ONLY\n  #define IMP_CreateArcOut\n  #define CreateArcOut NULL\n#else\n  #define IMP_CreateArcOut static IOutArchive *CreateArcOut() { return new CHandler(); }\n#endif\n\n#define REGISTER_ARC_V(n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \\\n  static const CArcInfo g_ArcInfo = { flags, id, sigSize, offs, sig, n, e, ae, tf, crIn, crOut, isArc } ; \\\n\n#define REGISTER_ARC_R(n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \\\n  REGISTER_ARC_V      (n, e, ae, id, sigSize, sig, offs, flags, tf, crIn, crOut, isArc) \\\n  struct CRegisterArc { CRegisterArc() { RegisterArc(&g_ArcInfo); }}; \\\n  static CRegisterArc g_RegisterArc;\n\n\n#define REGISTER_ARC_I_CLS(cls, n, e, ae, id, sig, offs, flags, isArc) \\\n  IMP_CreateArcIn_2(cls) \\\n  REGISTER_ARC_R(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, 0, CreateArc, NULL, isArc)\n\n#define REGISTER_ARC_I_CLS_NO_SIG(cls, n, e, ae, id, offs, flags, isArc) \\\n  IMP_CreateArcIn_2(cls) \\\n  REGISTER_ARC_R(n, e, ae, id, 0, NULL, offs, flags, 0, CreateArc, NULL, isArc)\n\n#define REGISTER_ARC_I(n, e, ae, id, sig, offs, flags, isArc) \\\n  REGISTER_ARC_I_CLS(CHandler(), n, e, ae, id, sig, offs, flags, isArc)\n\n#define REGISTER_ARC_I_NO_SIG(n, e, ae, id, offs, flags, isArc) \\\n  REGISTER_ARC_I_CLS_NO_SIG(CHandler(), n, e, ae, id, offs, flags, isArc)\n\n\n#define REGISTER_ARC_IO(n, e, ae, id, sig, offs, flags, tf, isArc) \\\n  IMP_CreateArcIn \\\n  IMP_CreateArcOut \\\n  REGISTER_ARC_R(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc)\n\n#define REGISTER_ARC_IO_DECREMENT_SIG(n, e, ae, id, sig, offs, flags, tf, isArc) \\\n  IMP_CreateArcIn \\\n  IMP_CreateArcOut \\\n  REGISTER_ARC_V(n, e, ae, id, Z7_ARRAY_SIZE(sig), sig, offs, flags, tf, CreateArc, CreateArcOut, isArc) \\\n  struct CRegisterArcDecSig { CRegisterArcDecSig() { sig[0]--; RegisterArc(&g_ArcInfo); }}; \\\n  static CRegisterArcDecSig g_RegisterArc;\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/RegisterCodec.h",
    "content": "﻿// RegisterCodec.h\n\n#ifndef ZIP7_INC_REGISTER_CODEC_H\n#define ZIP7_INC_REGISTER_CODEC_H\n\n#include \"../Common/MethodId.h\"\n\n#include \"../ICoder.h\"\n\ntypedef void * (*CreateCodecP)();\n\nstruct CCodecInfo\n{\n  CreateCodecP CreateDecoder;\n  CreateCodecP CreateEncoder;\n  CMethodId Id;\n  const char *Name;\n  UInt32 NumStreams;\n  bool IsFilter;\n};\n\nvoid RegisterCodec(const CCodecInfo *codecInfo) throw();\n\n\n#define REGISTER_CODEC_CREATE_2(name, cls, i) static void *name() { return (void *)(i *)(new cls); }\n#define REGISTER_CODEC_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressCoder)\n\n#define REGISTER_CODEC_NAME(x) CRegisterCodec ## x\n#define REGISTER_CODEC_VAR(x) static const CCodecInfo g_CodecInfo_ ## x =\n\n#define REGISTER_CODEC(x) struct REGISTER_CODEC_NAME(x) { \\\n    REGISTER_CODEC_NAME(x)() { RegisterCodec(&g_CodecInfo_ ## x); }}; \\\n    static REGISTER_CODEC_NAME(x) g_RegisterCodec_ ## x;\n\n\n#define REGISTER_CODECS_NAME(x) CRegisterCodecs ## x\n#define REGISTER_CODECS_VAR static const CCodecInfo g_CodecsInfo[] =\n\n#define REGISTER_CODECS(x) struct REGISTER_CODECS_NAME(x) { \\\n    REGISTER_CODECS_NAME(x)() { for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_CodecsInfo); i++) \\\n    RegisterCodec(&g_CodecsInfo[i]); }}; \\\n    static REGISTER_CODECS_NAME(x) g_RegisterCodecs;\n\n\n#define REGISTER_CODEC_2(x, crDec, crEnc, id, name) \\\n    REGISTER_CODEC_VAR(x) \\\n    { crDec, crEnc, id, name, 1, false }; \\\n    REGISTER_CODEC(x)\n\n\n#ifdef Z7_EXTRACT_ONLY\n  #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \\\n    REGISTER_CODEC_CREATE(CreateDec, clsDec) \\\n    REGISTER_CODEC_2(x, CreateDec, NULL, id, name)\n#else\n  #define REGISTER_CODEC_E(x, clsDec, clsEnc, id, name) \\\n    REGISTER_CODEC_CREATE(CreateDec, clsDec) \\\n    REGISTER_CODEC_CREATE(CreateEnc, clsEnc) \\\n    REGISTER_CODEC_2(x, CreateDec, CreateEnc, id, name)\n#endif\n\n\n\n#define REGISTER_FILTER_CREATE(name, cls) REGISTER_CODEC_CREATE_2(name, cls, ICompressFilter)\n\n#define REGISTER_FILTER_ITEM(crDec, crEnc, id, name) \\\n    { crDec, crEnc, id, name, 1, true }\n\n#define REGISTER_FILTER(x, crDec, crEnc, id, name) \\\n    REGISTER_CODEC_VAR(x) \\\n    REGISTER_FILTER_ITEM(crDec, crEnc, id, name); \\\n    REGISTER_CODEC(x)\n\n#ifdef Z7_EXTRACT_ONLY\n  #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \\\n    REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \\\n    REGISTER_FILTER(x, x ## _CreateDec, NULL, id, name)\n#else\n  #define REGISTER_FILTER_E(x, clsDec, clsEnc, id, name) \\\n    REGISTER_FILTER_CREATE(x ## _CreateDec, clsDec) \\\n    REGISTER_FILTER_CREATE(x ## _CreateEnc, clsEnc) \\\n    REGISTER_FILTER(x, x ## _CreateDec, x ## _CreateEnc, id, name)\n#endif\n\n\n\nstruct CHasherInfo\n{\n  IHasher * (*CreateHasher)();\n  CMethodId Id;\n  const char *Name;\n  UInt32 DigestSize;\n};\n\nvoid RegisterHasher(const CHasherInfo *hasher) throw();\n\n#define REGISTER_HASHER_NAME(x) CRegHasher_ ## x\n\n#define REGISTER_HASHER(cls, id, name, size) \\\n    Z7_COM7F_IMF2(UInt32, cls::GetDigestSize()) { return size; } \\\n    static IHasher *CreateHasherSpec() { return new cls(); } \\\n    static const CHasherInfo g_HasherInfo = { CreateHasherSpec, id, name, size }; \\\n    struct REGISTER_HASHER_NAME(cls) { REGISTER_HASHER_NAME(cls)() { RegisterHasher(&g_HasherInfo); }}; \\\n    static REGISTER_HASHER_NAME(cls) g_RegisterHasher;\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/StreamBinder.cpp",
    "content": "﻿// StreamBinder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"StreamBinder.h\"\n\nZ7_CLASS_IMP_COM_1(\n  CBinderInStream\n  , ISequentialInStream\n)\n  CStreamBinder *_binder;\npublic:\n  ~CBinderInStream() { _binder->CloseRead_CallOnce(); }\n  CBinderInStream(CStreamBinder *binder): _binder(binder) {}\n};\n\nZ7_COM7F_IMF(CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n  { return _binder->Read(data, size, processedSize); }\n\n\nZ7_CLASS_IMP_COM_1(\n  CBinderOutStream\n  , ISequentialOutStream\n)\n  CStreamBinder *_binder;\npublic:\n  ~CBinderOutStream() { _binder->CloseWrite(); }\n  CBinderOutStream(CStreamBinder *binder): _binder(binder) {}\n};\n\nZ7_COM7F_IMF(CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n  { return _binder->Write(data, size, processedSize); }\n\n\nstatic HRESULT Event_Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event)\n{\n  const WRes wres = event.CreateIfNotCreated_Reset();\n  return HRESULT_FROM_WIN32(wres);\n}\n\nHRESULT CStreamBinder::Create_ReInit()\n{\n  RINOK(Event_Create_or_Reset(_canRead_Event))\n  // RINOK(Event_Create_or_Reset(_canWrite_Event))\n\n  // _canWrite_Semaphore.Close();\n  // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce()\n  _canWrite_Semaphore.OptCreateInit(0, 3);\n\n  // _readingWasClosed = false;\n  _readingWasClosed2 = false;\n\n  _waitWrite = true;\n  _bufSize = 0;\n  _buf = NULL;\n  ProcessedSize = 0;\n  // WritingWasCut = false;\n  return S_OK;\n}\n\n\nvoid CStreamBinder::CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream)\n{\n  inStream = new CBinderInStream(this);\n  outStream = new CBinderOutStream(this);\n}\n\n// (_canRead_Event && _bufSize == 0) means that stream is finished.\n\nHRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size != 0)\n  {\n    if (_waitWrite)\n    {\n      WRes wres = _canRead_Event.Lock();\n      if (wres != 0)\n        return HRESULT_FROM_WIN32(wres);\n      _waitWrite = false;\n    }\n    if (size > _bufSize)\n      size = _bufSize;\n    if (size != 0)\n    {\n      memcpy(data, _buf, size);\n      _buf = ((const Byte *)_buf) + size;\n      ProcessedSize += size;\n      if (processedSize)\n        *processedSize = size;\n      _bufSize -= size;\n\n      /*\n      if (_bufSize == 0), then we have read whole buffer\n      we have two ways here:\n        - if we       check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs\n        - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading\n      */\n      if (_bufSize == 0)\n      {\n        _waitWrite = true;\n        // _canWrite_Event.Set();\n        _canWrite_Semaphore.Release();\n      }\n    }\n  }\n  return S_OK;\n}\n\n\nHRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n\n  if (!_readingWasClosed2)\n  {\n    _buf = data;\n    _bufSize = size;\n    _canRead_Event.Set();\n    \n    /*\n    _canWrite_Event.Lock();\n    if (_readingWasClosed)\n      _readingWasClosed2 = true;\n    */\n\n    _canWrite_Semaphore.Lock();\n\n    // _bufSize : is remain size that was not read\n    size -= _bufSize;\n\n    // size : is size of data that was read\n    if (size != 0)\n    {\n      // if some data was read, then we report that size and return\n      if (processedSize)\n        *processedSize = size;\n      return S_OK;\n    }\n    _readingWasClosed2 = true;\n  }\n\n  // WritingWasCut = true;\n  return k_My_HRESULT_WritingWasCut;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/StreamBinder.h",
    "content": "﻿// StreamBinder.h\n\n#ifndef ZIP7_INC_STREAM_BINDER_H\n#define ZIP7_INC_STREAM_BINDER_H\n\n#include \"../../Windows/Synchronization.h\"\n\n#include \"../IStream.h\"\n\n/*\nWe can use one from two code versions here: with Event or with Semaphore to unlock Writer thread\nThe difference for cases where Reading must be closed before Writing closing\n\n1) Event Version: _canWrite_Event\n  We call _canWrite_Event.Set() without waiting _canRead_Event in CloseRead() function.\n  The writer thread can get (_readingWasClosed) status in one from two iterations.\n  It's ambiguity of processing flow. But probably it's SAFE to use, if Event functions provide memory barriers.\n  reader thread:\n     _canWrite_Event.Set();\n     _readingWasClosed = true;\n     _canWrite_Event.Set();\n  writer thread:\n     _canWrite_Event.Wait()\n      if (_readingWasClosed)\n\n2) Semaphore Version: _canWrite_Semaphore\n  writer thread always will detect closing of reading in latest iteration after all data processing iterations\n*/\n\nclass CStreamBinder\n{\n  NWindows::NSynchronization::CAutoResetEvent _canRead_Event;\n  // NWindows::NSynchronization::CAutoResetEvent _canWrite_Event;\n  NWindows::NSynchronization::CSemaphore _canWrite_Semaphore;\n\n  // bool _readingWasClosed;  // set it in reader thread and check it in write thread\n  bool _readingWasClosed2; // use it in writer thread\n  // bool WritingWasCut;\n  bool _waitWrite;         // use it in reader thread\n  UInt32 _bufSize;\n  const void *_buf;\npublic:\n  UInt64 ProcessedSize;   // the size that was read by reader thread\n\n  void CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream);\n  \n  HRESULT Create_ReInit();\n  \n  HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);\n  HRESULT Write(const void *data, UInt32 size, UInt32 *processedSize);\n\n  void CloseRead_CallOnce()\n  {\n    // call it only once: for example, in destructor\n    \n    /*\n    _readingWasClosed = true;\n    _canWrite_Event.Set();\n    */\n\n    /*\n    We must relase Semaphore only once !!!\n    we must release at least 2 items of Semaphore:\n      one item to unlock partial Write(), if Read() have read some items\n      then additional item to stop writing (_bufSize will be 0)\n    */\n    _canWrite_Semaphore.Release(2);\n  }\n  \n  void CloseWrite()\n  {\n    _buf = NULL;\n    _bufSize = 0;\n    _canRead_Event.Set();\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/StreamObjects.cpp",
    "content": "﻿// StreamObjects.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"StreamObjects.h\"\n\nZ7_COM7F_IMF(CBufferInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (_pos >= Buf.Size())\n    return S_OK;\n  size_t rem = Buf.Size() - (size_t)_pos;\n  if (rem > size)\n    rem = (size_t)size;\n  memcpy(data, (const Byte *)Buf + (size_t)_pos, rem);\n  _pos += rem;\n  if (processedSize)\n    *processedSize = (UInt32)rem;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CBufferInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _pos; break;\n    case STREAM_SEEK_END: offset += Buf.Size(); break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _pos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CBufInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (_pos >= _size)\n    return S_OK;\n  size_t rem = _size - (size_t)_pos;\n  if (rem > size)\n    rem = (size_t)size;\n  memcpy(data, _data + (size_t)_pos, rem);\n  _pos += rem;\n  if (processedSize)\n    *processedSize = (UInt32)rem;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CBufInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _pos; break;\n    case STREAM_SEEK_END: offset += _size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _pos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n\nvoid Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream)\n{\n  *stream = NULL;\n  CBufInStream *inStreamSpec = new CBufInStream;\n  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;\n  inStreamSpec->Init((const Byte *)data, size, ref);\n  *stream = streamTemp.Detach();\n}\n\nvoid Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream)\n{\n  *stream = NULL;\n  CBufferInStream *inStreamSpec = new CBufferInStream;\n  CMyComPtr<ISequentialInStream> streamTemp = inStreamSpec;\n  inStreamSpec->Buf.CopyFrom((const Byte *)data, size);\n  inStreamSpec->Init();\n  *stream = streamTemp.Detach();\n}\n\nvoid CByteDynBuffer::Free() throw()\n{\n  MyFree(_buf);\n  _buf = NULL;\n  _capacity = 0;\n}\n\nbool CByteDynBuffer::EnsureCapacity(size_t cap) throw()\n{\n  if (cap <= _capacity)\n    return true;\n  const size_t cap2 = _capacity + _capacity / 4;\n  if (cap < cap2)\n    cap = cap2;\n  Byte *buf = (Byte *)MyRealloc(_buf, cap);\n  if (!buf)\n    return false;\n  _buf = buf;\n  _capacity = cap;\n  return true;\n}\n\nByte *CDynBufSeqOutStream::GetBufPtrForWriting(size_t addSize)\n{\n  addSize += _size;\n  if (addSize < _size)\n    return NULL;\n  if (!_buffer.EnsureCapacity(addSize))\n    return NULL;\n  return (Byte *)_buffer + _size;\n}\n\nvoid CDynBufSeqOutStream::CopyToBuffer(CByteBuffer &dest) const\n{\n  dest.CopyFrom((const Byte *)_buffer, _size);\n}\n\nZ7_COM7F_IMF(CDynBufSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  Byte *buf = GetBufPtrForWriting(size);\n  if (!buf)\n    return E_OUTOFMEMORY;\n  memcpy(buf, data, size);\n  UpdateSize(size);\n  if (processedSize)\n    *processedSize = size;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CBufPtrSeqOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  size_t rem = _size - _pos;\n  if (rem > size)\n    rem = (size_t)size;\n  if (rem != 0)\n  {\n    memcpy(_buffer + _pos, data, rem);\n    _pos += rem;\n  }\n  if (processedSize)\n    *processedSize = (UInt32)rem;\n  return (rem != 0 || size == 0) ? S_OK : E_FAIL;\n}\n\nZ7_COM7F_IMF(CSequentialOutStreamSizeCount::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize;\n  HRESULT result = _stream->Write(data, size, &realProcessedSize);\n  _size += realProcessedSize;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return result;\n}\n\nstatic const UInt64 kEmptyTag = (UInt64)(Int64)-1;\n\nvoid CCachedInStream::Free() throw()\n{\n  MyFree(_tags);\n  _tags = NULL;\n  MidFree(_data);\n  _data = NULL;\n}\n\nbool CCachedInStream::Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw()\n{\n  unsigned sizeLog = blockSizeLog + numBlocksLog;\n  if (sizeLog >= sizeof(size_t) * 8)\n    return false;\n  size_t dataSize = (size_t)1 << sizeLog;\n  if (!_data || dataSize != _dataSize)\n  {\n    MidFree(_data);\n    _data = (Byte *)MidAlloc(dataSize);\n    if (!_data)\n      return false;\n    _dataSize = dataSize;\n  }\n  if (!_tags || numBlocksLog != _numBlocksLog)\n  {\n    MyFree(_tags);\n    _tags = (UInt64 *)MyAlloc(sizeof(UInt64) << numBlocksLog);\n    if (!_tags)\n      return false;\n    _numBlocksLog = numBlocksLog;\n  }\n  _blockSizeLog = blockSizeLog;\n  return true;\n}\n\nvoid CCachedInStream::Init(UInt64 size) throw()\n{\n  _size = size;\n  _pos = 0;\n  const size_t numBlocks = (size_t)1 << _numBlocksLog;\n  for (size_t i = 0; i < numBlocks; i++)\n    _tags[i] = kEmptyTag;\n}\n\nZ7_COM7F_IMF(CCachedInStream::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (_pos >= _size)\n    return S_OK;\n\n  {\n    const UInt64 rem = _size - _pos;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n\n  while (size != 0)\n  {\n    const UInt64 cacheTag = _pos >> _blockSizeLog;\n    const size_t cacheIndex = (size_t)cacheTag & (((size_t)1 << _numBlocksLog) - 1);\n    Byte *p = _data + (cacheIndex << _blockSizeLog);\n\n    if (_tags[cacheIndex] != cacheTag)\n    {\n      _tags[cacheIndex] = kEmptyTag;\n      const UInt64 remInBlock = _size - (cacheTag << _blockSizeLog);\n      size_t blockSize = (size_t)1 << _blockSizeLog;\n      if (blockSize > remInBlock)\n        blockSize = (size_t)remInBlock;\n      \n      RINOK(ReadBlock(cacheTag, p, blockSize))\n      \n      _tags[cacheIndex] = cacheTag;\n    }\n    \n    const size_t kBlockSize = (size_t)1 << _blockSizeLog;\n    const size_t offset = (size_t)_pos & (kBlockSize - 1);\n    UInt32 cur = size;\n    const size_t rem = kBlockSize - offset;\n    if (cur > rem)\n      cur = (UInt32)rem;\n    \n    memcpy(data, p + offset, cur);\n    \n    if (processedSize)\n      *processedSize += cur;\n    data = (void *)((const Byte *)data + cur);\n    _pos += cur;\n    size -= cur;\n  }\n\n  return S_OK;\n}\n\n \nZ7_COM7F_IMF(CCachedInStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  switch (seekOrigin)\n  {\n    case STREAM_SEEK_SET: break;\n    case STREAM_SEEK_CUR: offset += _pos; break;\n    case STREAM_SEEK_END: offset += _size; break;\n    default: return STG_E_INVALIDFUNCTION;\n  }\n  if (offset < 0)\n    return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;\n  _pos = (UInt64)offset;\n  if (newPosition)\n    *newPosition = (UInt64)offset;\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/StreamObjects.h",
    "content": "﻿// StreamObjects.h\n\n#ifndef ZIP7_INC_STREAM_OBJECTS_H\n#define ZIP7_INC_STREAM_OBJECTS_H\n\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/MyVector.h\"\n\n#include \"../IStream.h\"\n\nZ7_CLASS_IMP_IInStream(\n  CBufferInStream\n)\n  UInt64 _pos;\npublic:\n  CByteBuffer Buf;\n  void Init() { _pos = 0; }\n};\n\n\nZ7_CLASS_IMP_COM_0(\n  CReferenceBuf\n)\npublic:\n  CByteBuffer Buf;\n};\n\n\nZ7_CLASS_IMP_IInStream(\n  CBufInStream\n)\n  const Byte *_data;\n  UInt64 _pos;\n  size_t _size;\n  CMyComPtr<IUnknown> _ref;\npublic:\n  void Init(const Byte *data, size_t size, IUnknown *ref = NULL)\n  {\n    _data = data;\n    _size = size;\n    _pos = 0;\n    _ref = ref;\n  }\n  void Init(CReferenceBuf *ref) { Init(ref->Buf, ref->Buf.Size(), ref); }\n\n  // Seek() is allowed here. So reading order could be changed\n  bool WasFinished() const { return _pos == _size; }\n};\n\n\nvoid Create_BufInStream_WithReference(const void *data, size_t size, IUnknown *ref, ISequentialInStream **stream);\nvoid Create_BufInStream_WithNewBuffer(const void *data, size_t size, ISequentialInStream **stream);\ninline void Create_BufInStream_WithNewBuffer(const CByteBuffer &buf, ISequentialInStream **stream)\n  { Create_BufInStream_WithNewBuffer(buf, buf.Size(), stream); }\n\n\nclass CByteDynBuffer Z7_final\n{\n  size_t _capacity;\n  Byte *_buf;\n  Z7_CLASS_NO_COPY(CByteDynBuffer)\npublic:\n  CByteDynBuffer(): _capacity(0), _buf(NULL) {}\n  // there is no copy constructor. So don't copy this object.\n  ~CByteDynBuffer() { Free(); }\n  void Free() throw();\n  size_t GetCapacity() const { return _capacity; }\n  operator Byte*() const { return _buf; }\n  operator const Byte*() const { return _buf; }\n  bool EnsureCapacity(size_t capacity) throw();\n};\n\n\nZ7_CLASS_IMP_COM_1(\n  CDynBufSeqOutStream\n  , ISequentialOutStream\n)\n  CByteDynBuffer _buffer;\n  size_t _size;\npublic:\n  CDynBufSeqOutStream(): _size(0) {}\n  void Init() { _size = 0;  }\n  size_t GetSize() const { return _size; }\n  const Byte *GetBuffer() const { return _buffer; }\n  void CopyToBuffer(CByteBuffer &dest) const;\n  Byte *GetBufPtrForWriting(size_t addSize);\n  void UpdateSize(size_t addSize) { _size += addSize; }\n};\n\n\nZ7_CLASS_IMP_COM_1(\n  CBufPtrSeqOutStream\n  , ISequentialOutStream\n)\n  Byte *_buffer;\n  size_t _size;\n  size_t _pos;\npublic:\n  void Init(Byte *buffer, size_t size)\n  {\n    _buffer = buffer;\n    _pos = 0;\n    _size = size;\n  }\n  size_t GetPos() const { return _pos; }\n};\n\n\nZ7_CLASS_IMP_COM_1(\n  CSequentialOutStreamSizeCount\n  , ISequentialOutStream\n)\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\npublic:\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void Init() { _size = 0; }\n  UInt64 GetSize() const { return _size; }\n};\n\n\nclass CCachedInStream:\n  public IInStream,\n  public CMyUnknownImp\n{\n  Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream)\n\n  UInt64 *_tags;\n  Byte *_data;\n  size_t _dataSize;\n  unsigned _blockSizeLog;\n  unsigned _numBlocksLog;\n  UInt64 _size;\n  UInt64 _pos;\nprotected:\n  virtual HRESULT ReadBlock(UInt64 blockIndex, Byte *dest, size_t blockSize) = 0;\npublic:\n  CCachedInStream(): _tags(NULL), _data(NULL) {}\n  virtual ~CCachedInStream() { Free(); } // the destructor must be virtual (Release() calls it) !!!\n  void Free() throw();\n  bool Alloc(unsigned blockSizeLog, unsigned numBlocksLog) throw();\n  void Init(UInt64 size) throw();\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/StreamUtils.cpp",
    "content": "﻿// StreamUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"StreamUtils.h\"\n\nstatic const UInt32 kBlockSize = ((UInt32)1 << 31);\n\n\nHRESULT InStream_SeekToBegin(IInStream *stream) throw()\n{\n  return InStream_SeekSet(stream, 0);\n}\n\n\nHRESULT InStream_AtBegin_GetSize(IInStream *stream, UInt64 &sizeRes) throw()\n{\n#ifdef _WIN32\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IStreamGetSize,\n        streamGetSize, stream)\n    if (streamGetSize && streamGetSize->GetSize(&sizeRes) == S_OK)\n      return S_OK;\n  }\n#endif\n  const HRESULT hres = InStream_GetSize_SeekToEnd(stream, sizeRes);\n  const HRESULT hres2 = InStream_SeekToBegin(stream);\n  return hres != S_OK ? hres : hres2;\n}\n\n\nHRESULT InStream_GetPos_GetSize(IInStream *stream, UInt64 &curPosRes, UInt64 &sizeRes) throw()\n{\n  RINOK(InStream_GetPos(stream, curPosRes))\n#ifdef _WIN32\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IStreamGetSize,\n        streamGetSize, stream)\n    if (streamGetSize && streamGetSize->GetSize(&sizeRes) == S_OK)\n      return S_OK;\n  }\n#endif\n  const HRESULT hres = InStream_GetSize_SeekToEnd(stream, sizeRes);\n  const HRESULT hres2 = InStream_SeekSet(stream, curPosRes);\n  return hres != S_OK ? hres : hres2;\n}\n\n\n\nHRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *processedSize) throw()\n{\n  size_t size = *processedSize;\n  *processedSize = 0;\n  while (size != 0)\n  {\n    UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;\n    UInt32 processedSizeLoc;\n    HRESULT res = stream->Read(data, curSize, &processedSizeLoc);\n    *processedSize += processedSizeLoc;\n    data = (void *)((Byte *)data + processedSizeLoc);\n    size -= processedSizeLoc;\n    RINOK(res)\n    if (processedSizeLoc == 0)\n      return S_OK;\n  }\n  return S_OK;\n}\n\nHRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw()\n{\n  size_t processedSize = size;\n  RINOK(ReadStream(stream, data, &processedSize))\n  return (size == processedSize) ? S_OK : S_FALSE;\n}\n\nHRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw()\n{\n  size_t processedSize = size;\n  RINOK(ReadStream(stream, data, &processedSize))\n  return (size == processedSize) ? S_OK : E_FAIL;\n}\n\nHRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw()\n{\n  while (size != 0)\n  {\n    UInt32 curSize = (size < kBlockSize) ? (UInt32)size : kBlockSize;\n    UInt32 processedSizeLoc;\n    HRESULT res = stream->Write(data, curSize, &processedSizeLoc);\n    data = (const void *)((const Byte *)data + processedSizeLoc);\n    size -= processedSizeLoc;\n    RINOK(res)\n    if (processedSizeLoc == 0)\n      return E_FAIL;\n  }\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/StreamUtils.h",
    "content": "﻿// StreamUtils.h\n\n#ifndef ZIP7_INC_STREAM_UTILS_H\n#define ZIP7_INC_STREAM_UTILS_H\n\n#include \"../IStream.h\"\n\ninline HRESULT InStream_SeekSet(IInStream *stream, UInt64 offset) throw()\n  {  return stream->Seek((Int64)offset, STREAM_SEEK_SET, NULL); }\ninline HRESULT InStream_GetPos(IInStream *stream, UInt64 &curPosRes) throw()\n  {  return stream->Seek(0, STREAM_SEEK_CUR, &curPosRes); }\ninline HRESULT InStream_GetSize_SeekToEnd(IInStream *stream, UInt64 &sizeRes) throw()\n  { return stream->Seek(0, STREAM_SEEK_END, &sizeRes); }\n\nHRESULT InStream_SeekToBegin(IInStream *stream) throw();\nHRESULT InStream_AtBegin_GetSize(IInStream *stream, UInt64 &size) throw();\nHRESULT InStream_GetPos_GetSize(IInStream *stream, UInt64 &curPosRes, UInt64 &sizeRes) throw();\n\ninline HRESULT InStream_GetSize_SeekToBegin(IInStream *stream, UInt64 &sizeRes) throw()\n{\n  RINOK(InStream_SeekToBegin(stream))\n  return InStream_AtBegin_GetSize(stream, sizeRes);\n}\n\n\nHRESULT ReadStream(ISequentialInStream *stream, void *data, size_t *size) throw();\nHRESULT ReadStream_FALSE(ISequentialInStream *stream, void *data, size_t size) throw();\nHRESULT ReadStream_FAIL(ISequentialInStream *stream, void *data, size_t size) throw();\nHRESULT WriteStream(ISequentialOutStream *stream, const void *data, size_t size) throw();\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/UniqBlocks.cpp",
    "content": "﻿// UniqBlocks.cpp\n\n#include \"StdAfx.h\"\n\n#include <string.h>\n\n#include \"UniqBlocks.h\"\n\nunsigned CUniqBlocks::AddUniq(const Byte *data, size_t size)\n{\n  unsigned left = 0, right = Sorted.Size();\n  while (left != right)\n  {\n    const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n    const unsigned index = Sorted[mid];\n    const CByteBuffer &buf = Bufs[index];\n    const size_t sizeMid = buf.Size();\n    if (size < sizeMid)\n      right = mid;\n    else if (size > sizeMid)\n      left = mid + 1;\n    else\n    {\n      if (size == 0)\n        return index;\n      const int cmp = memcmp(data, buf, size);\n      if (cmp == 0)\n        return index;\n      if (cmp < 0)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n  }\n  unsigned index = Bufs.Size();\n  Sorted.Insert(left, index);\n  Bufs.AddNew().CopyFrom(data, size);\n  return index;\n}\n\nUInt64 CUniqBlocks::GetTotalSizeInBytes() const\n{\n  UInt64 size = 0;\n  FOR_VECTOR (i, Bufs)\n    size += Bufs[i].Size();\n  return size;\n}\n\nvoid CUniqBlocks::GetReverseMap()\n{\n  unsigned num = Sorted.Size();\n  BufIndexToSortedIndex.ClearAndSetSize(num);\n  unsigned *p = &BufIndexToSortedIndex[0];\n  const unsigned *sorted = &Sorted[0];\n  for (unsigned i = 0; i < num; i++)\n    p[sorted[i]] = i;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/UniqBlocks.h",
    "content": "﻿// UniqBlocks.h\n\n#ifndef ZIP7_INC_UNIQ_BLOCKS_H\n#define ZIP7_INC_UNIQ_BLOCKS_H\n\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyString.h\"\n\nstruct C_UInt32_UString_Map\n{\n  CRecordVector<UInt32> Numbers;\n  UStringVector Strings;\n  \n  void Add_UInt32(const UInt32 n)\n  {\n    Numbers.AddToUniqueSorted(n);\n  }\n  int Find(const UInt32 n)\n  {\n    return Numbers.FindInSorted(n);\n  }\n};\n\n\nstruct CUniqBlocks\n{\n  CObjectVector<CByteBuffer> Bufs;\n  CUIntVector Sorted;\n  CUIntVector BufIndexToSortedIndex;\n\n  unsigned AddUniq(const Byte *data, size_t size);\n  UInt64 GetTotalSizeInBytes() const;\n  void GetReverseMap();\n\n  bool IsOnlyEmpty() const\n  {\n    return (Bufs.Size() == 0 || (Bufs.Size() == 1 && Bufs[0].Size() == 0));\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/VirtThread.cpp",
    "content": "﻿// VirtThread.cpp\n\n#include \"StdAfx.h\"\n\n#include \"VirtThread.h\"\n\nstatic THREAD_FUNC_DECL CoderThread(void *p)\n{\n  for (;;)\n  {\n    CVirtThread *t = (CVirtThread *)p;\n    t->StartEvent.Lock();\n    if (t->Exit)\n      return THREAD_FUNC_RET_ZERO;\n    t->Execute();\n    t->FinishedEvent.Set();\n  }\n}\n\nWRes CVirtThread::Create()\n{\n  RINOK_WRes(StartEvent.CreateIfNotCreated_Reset())\n  RINOK_WRes(FinishedEvent.CreateIfNotCreated_Reset())\n  // StartEvent.Reset();\n  // FinishedEvent.Reset();\n  Exit = false;\n  if (Thread.IsCreated())\n    return S_OK;\n  return Thread.Create(CoderThread, this);\n}\n\nWRes CVirtThread::Start()\n{\n  Exit = false;\n  return StartEvent.Set();\n}\n\nvoid CVirtThread::WaitThreadFinish()\n{\n  Exit = true;\n  if (StartEvent.IsCreated())\n    StartEvent.Set();\n  if (Thread.IsCreated())\n  {\n    Thread.Wait_Close();\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Common/VirtThread.h",
    "content": "﻿// VirtThread.h\n\n#ifndef ZIP7_INC_VIRT_THREAD_H\n#define ZIP7_INC_VIRT_THREAD_H\n\n#include \"../../Windows/Synchronization.h\"\n#include \"../../Windows/Thread.h\"\n\nstruct CVirtThread\n{\n  NWindows::NSynchronization::CAutoResetEvent StartEvent;\n  NWindows::NSynchronization::CAutoResetEvent FinishedEvent;\n  NWindows::CThread Thread;\n  bool Exit;\n\n  virtual ~CVirtThread() { WaitThreadFinish(); }\n  void WaitThreadFinish(); // call it in destructor of child class !\n  WRes Create();\n  WRes Start();\n  virtual void Execute() = 0;\n  WRes WaitExecuteFinish() { return FinishedEvent.Lock(); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Const.h",
    "content": "﻿// Compress/BZip2Const.h\n\n#ifndef ZIP7_INC_COMPRESS_BZIP2_CONST_H\n#define ZIP7_INC_COMPRESS_BZIP2_CONST_H\n\nnamespace NCompress {\nnamespace NBZip2 {\n\nconst Byte kArSig0 = 'B';\nconst Byte kArSig1 = 'Z';\nconst Byte kArSig2 = 'h';\nconst Byte kArSig3 = '0';\n\nconst Byte kFinSig0 = 0x17;\nconst Byte kFinSig1 = 0x72;\nconst Byte kFinSig2 = 0x45;\nconst Byte kFinSig3 = 0x38;\nconst Byte kFinSig4 = 0x50;\nconst Byte kFinSig5 = 0x90;\n\nconst Byte kBlockSig0 = 0x31;\nconst Byte kBlockSig1 = 0x41;\nconst Byte kBlockSig2 = 0x59;\nconst Byte kBlockSig3 = 0x26;\nconst Byte kBlockSig4 = 0x53;\nconst Byte kBlockSig5 = 0x59;\n\nconst unsigned kNumOrigBits = 24;\n\nconst unsigned kNumTablesBits = 3;\nconst unsigned kNumTablesMin = 2;\nconst unsigned kNumTablesMax = 6;\n\nconst unsigned kNumLevelsBits = 5;\n\nconst unsigned kMaxHuffmanLen = 20; // Check it\n\nconst unsigned kMaxAlphaSize = 258;\n\nconst unsigned kGroupSize = 50;\n\nconst unsigned kBlockSizeMultMin = 1;\nconst unsigned kBlockSizeMultMax = 9;\n\nconst UInt32 kBlockSizeStep = 100000;\nconst UInt32 kBlockSizeMax = kBlockSizeMultMax * kBlockSizeStep;\n\nconst unsigned kNumSelectorsBits = 15;\nconst unsigned kNumSelectorsMax = 2 + kBlockSizeMax / kGroupSize;\n\nconst unsigned kRleModeRepSize = 4;\n\n/*\nThe number of selectors stored in bzip2 block:\n(numSelectors <= 18001) - must work with any decoder.\n(numSelectors == 18002) - works with bzip2 1.0.6 decoder and all derived decoders.\n(numSelectors  > 18002)\n   lbzip2 2.5: encoder can write up to (18001 + 7) selectors.\n\n   7-Zip before 19.03: decoder doesn't support it.\n   7-Zip        19.03: decoder allows 8 additional selector records for lbzip2 compatibility.\n   \n   bzip2 1.0.6: decoder can overflow selector[18002] arrays. But there are another\n               arrays after selector arrays. So the compiled code works.\n   bzip2 1.0.7: decoder doesn't support it.\n   bzip2 1.0.8: decoder allows additional selector records for lbzip2 compatibility.\n*/\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Crc.cpp",
    "content": "﻿// BZip2Crc.cpp\n\n#include \"StdAfx.h\"\n\n#include \"BZip2Crc.h\"\n\nMY_ALIGN(64)\nUInt32 CBZip2Crc::Table[256];\n\nstatic const UInt32 kBZip2CrcPoly = 0x04c11db7;  /* AUTODIN II, Ethernet, & FDDI */\n\nvoid CBZip2Crc::InitTable()\n{\n  for (UInt32 i = 0; i < 256; i++)\n  {\n    UInt32 r = i << 24;\n    for (unsigned j = 0; j < 8; j++)\n      r = (r << 1) ^ (kBZip2CrcPoly & ((UInt32)0 - (r >> 31)));\n    Table[i] = r;\n  }\n}\n\nstatic\nclass CBZip2CrcTableInit\n{\npublic:\n  CBZip2CrcTableInit() { CBZip2Crc::InitTable(); }\n} g_BZip2CrcTableInit;\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Crc.h",
    "content": "﻿// BZip2Crc.h\n\n#ifndef ZIP7_INC_BZIP2_CRC_H\n#define ZIP7_INC_BZIP2_CRC_H\n\n#include \"../../Common/MyTypes.h\"\n\nclass CBZip2Crc\n{\n  UInt32 _value;\n  static UInt32 Table[256];\npublic:\n  static void InitTable();\n  CBZip2Crc(UInt32 initVal = 0xFFFFFFFF): _value(initVal) {}\n  void Init(UInt32 initVal = 0xFFFFFFFF) { _value = initVal; }\n  void UpdateByte(Byte b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }\n  void UpdateByte(unsigned b) { _value = Table[(_value >> 24) ^ b] ^ (_value << 8); }\n  UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; }\n};\n\nclass CBZip2CombinedCrc\n{\n  UInt32 _value;\npublic:\n  CBZip2CombinedCrc(): _value(0) {}\n  void Init() { _value = 0; }\n  void Update(UInt32 v) { _value = ((_value << 1) | (_value >> 31)) ^ v; }\n  UInt32 GetDigest() const { return _value ; }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Decoder.cpp",
    "content": "﻿// BZip2Decoder.cpp\n\n#include \"StdAfx.h\"\n\n// #include \"CopyCoder.h\"\n\n/*\n#include <stdio.h>\n#include \"../../../C/CpuTicks.h\"\n*/\n#define TICKS_START\n#define TICKS_UPDATE(n)\n\n\n/*\n#define PRIN(s) printf(s \"\\n\"); fflush(stdout);\n#define PRIN_VAL(s, val) printf(s \" = %u \\n\", val); fflush(stdout);\n*/\n\n#define PRIN(s)\n#define PRIN_VAL(s, val)\n\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"BZip2Decoder.h\"\n\n\nnamespace NCompress {\nnamespace NBZip2 {\n\n// #undef NO_INLINE\n#define NO_INLINE Z7_NO_INLINE\n\n#define BZIP2_BYTE_MODE\n\n\nstatic const UInt32 kInBufSize = (UInt32)1 << 17;\nstatic const size_t kOutBufSize = (size_t)1 << 20;\n\nstatic const UInt32 kProgressStep = (UInt32)1 << 16;\n\nMY_ALIGN(64)\nstatic const UInt16 kRandNums[512] = {\n   619, 720, 127, 481, 931, 816, 813, 233, 566, 247,\n   985, 724, 205, 454, 863, 491, 741, 242, 949, 214,\n   733, 859, 335, 708, 621, 574, 73, 654, 730, 472,\n   419, 436, 278, 496, 867, 210, 399, 680, 480, 51,\n   878, 465, 811, 169, 869, 675, 611, 697, 867, 561,\n   862, 687, 507, 283, 482, 129, 807, 591, 733, 623,\n   150, 238, 59, 379, 684, 877, 625, 169, 643, 105,\n   170, 607, 520, 932, 727, 476, 693, 425, 174, 647,\n   73, 122, 335, 530, 442, 853, 695, 249, 445, 515,\n   909, 545, 703, 919, 874, 474, 882, 500, 594, 612,\n   641, 801, 220, 162, 819, 984, 589, 513, 495, 799,\n   161, 604, 958, 533, 221, 400, 386, 867, 600, 782,\n   382, 596, 414, 171, 516, 375, 682, 485, 911, 276,\n   98, 553, 163, 354, 666, 933, 424, 341, 533, 870,\n   227, 730, 475, 186, 263, 647, 537, 686, 600, 224,\n   469, 68, 770, 919, 190, 373, 294, 822, 808, 206,\n   184, 943, 795, 384, 383, 461, 404, 758, 839, 887,\n   715, 67, 618, 276, 204, 918, 873, 777, 604, 560,\n   951, 160, 578, 722, 79, 804, 96, 409, 713, 940,\n   652, 934, 970, 447, 318, 353, 859, 672, 112, 785,\n   645, 863, 803, 350, 139, 93, 354, 99, 820, 908,\n   609, 772, 154, 274, 580, 184, 79, 626, 630, 742,\n   653, 282, 762, 623, 680, 81, 927, 626, 789, 125,\n   411, 521, 938, 300, 821, 78, 343, 175, 128, 250,\n   170, 774, 972, 275, 999, 639, 495, 78, 352, 126,\n   857, 956, 358, 619, 580, 124, 737, 594, 701, 612,\n   669, 112, 134, 694, 363, 992, 809, 743, 168, 974,\n   944, 375, 748, 52, 600, 747, 642, 182, 862, 81,\n   344, 805, 988, 739, 511, 655, 814, 334, 249, 515,\n   897, 955, 664, 981, 649, 113, 974, 459, 893, 228,\n   433, 837, 553, 268, 926, 240, 102, 654, 459, 51,\n   686, 754, 806, 760, 493, 403, 415, 394, 687, 700,\n   946, 670, 656, 610, 738, 392, 760, 799, 887, 653,\n   978, 321, 576, 617, 626, 502, 894, 679, 243, 440,\n   680, 879, 194, 572, 640, 724, 926, 56, 204, 700,\n   707, 151, 457, 449, 797, 195, 791, 558, 945, 679,\n   297, 59, 87, 824, 713, 663, 412, 693, 342, 606,\n   134, 108, 571, 364, 631, 212, 174, 643, 304, 329,\n   343, 97, 430, 751, 497, 314, 983, 374, 822, 928,\n   140, 206, 73, 263, 980, 736, 876, 478, 430, 305,\n   170, 514, 364, 692, 829, 82, 855, 953, 676, 246,\n   369, 970, 294, 750, 807, 827, 150, 790, 288, 923,\n   804, 378, 215, 828, 592, 281, 565, 555, 710, 82,\n   896, 831, 547, 261, 524, 462, 293, 465, 502, 56,\n   661, 821, 976, 991, 658, 869, 905, 758, 745, 193,\n   768, 550, 608, 933, 378, 286, 215, 979, 792, 961,\n   61, 688, 793, 644, 986, 403, 106, 366, 905, 644,\n   372, 567, 466, 434, 645, 210, 389, 550, 919, 135,\n   780, 773, 635, 389, 707, 100, 626, 958, 165, 504,\n   920, 176, 193, 713, 857, 265, 203, 50, 668, 108,\n   645, 990, 626, 197, 510, 357, 358, 850, 858, 364,\n   936, 638\n};\n\n\n\nenum EState\n{\n  STATE_STREAM_SIGNATURE,\n  STATE_BLOCK_SIGNATURE,\n\n  STATE_BLOCK_START,\n  STATE_ORIG_BITS,\n  STATE_IN_USE,\n  STATE_IN_USE2,\n  STATE_NUM_TABLES,\n  STATE_NUM_SELECTORS,\n  STATE_SELECTORS,\n  STATE_LEVELS,\n  \n  STATE_BLOCK_SYMBOLS,\n\n  STATE_STREAM_FINISHED\n};\n\n\n#define UPDATE_VAL_2(val, num_bits) { \\\n  val |= (UInt32)(*_buf) << (24 - num_bits); \\\n  num_bits += 8; \\\n _buf++; \\\n}\n\n#define UPDATE_VAL  UPDATE_VAL_2(VAL, NUM_BITS)\n\n#define READ_BITS(res, num) { \\\n  while (_numBits < num) { \\\n    if (_buf == _lim) return SZ_OK; \\\n    UPDATE_VAL_2(_value, _numBits) } \\\n  res = _value >> (32 - num); \\\n  _value <<= num; \\\n  _numBits -= num; \\\n}\n\n#define READ_BITS_8(res, num) { \\\n  if (_numBits < num) { \\\n    if (_buf == _lim) return SZ_OK; \\\n    UPDATE_VAL_2(_value, _numBits) } \\\n  res = _value >> (32 - num); \\\n  _value <<= num; \\\n  _numBits -= num; \\\n}\n\n#define READ_BIT(res) READ_BITS_8(res, 1)\n\n\n\n#define VAL _value2\n// #define NUM_BITS _numBits2\n#define NUM_BITS _numBits\n#define BLOCK_SIZE blockSize2\n#define RUN_COUNTER runCounter2\n\n#define LOAD_LOCAL \\\n    UInt32 VAL = this->_value; \\\n    /* unsigned NUM_BITS = this->_numBits; */ \\\n    UInt32 BLOCK_SIZE = this->blockSize; \\\n    UInt32 RUN_COUNTER = this->runCounter; \\\n\n#define SAVE_LOCAL \\\n    this->_value = VAL; \\\n    /* this->_numBits = NUM_BITS; */ \\\n    this->blockSize = BLOCK_SIZE; \\\n    this->runCounter = RUN_COUNTER; \\\n\n\n\nSRes CBitDecoder::ReadByte(int &b)\n{\n  b = -1;\n  READ_BITS_8(b, 8)\n  return SZ_OK;\n}\n\n\nNO_INLINE\nSRes CBase::ReadStreamSignature2()\n{\n  for (;;)\n  {\n    unsigned b;\n    READ_BITS_8(b, 8)\n\n    if (   (state2 == 0 && b != kArSig0)\n        || (state2 == 1 && b != kArSig1)\n        || (state2 == 2 && b != kArSig2)\n        || (state2 == 3 && (b <= kArSig3 || b > kArSig3 + kBlockSizeMultMax)))\n      return SZ_ERROR_DATA;\n    state2++;\n\n    if (state2 == 4)\n    {\n      blockSizeMax = (UInt32)(b - kArSig3) * kBlockSizeStep;\n      CombinedCrc.Init();\n      state = STATE_BLOCK_SIGNATURE;\n      state2 = 0;\n      return SZ_OK;\n    }\n  }\n}\n\n\nbool IsEndSig(const Byte *p) throw()\n{\n  return\n    p[0] == kFinSig0 &&\n    p[1] == kFinSig1 &&\n    p[2] == kFinSig2 &&\n    p[3] == kFinSig3 &&\n    p[4] == kFinSig4 &&\n    p[5] == kFinSig5;\n}\n\nbool IsBlockSig(const Byte *p) throw()\n{\n  return\n    p[0] == kBlockSig0 &&\n    p[1] == kBlockSig1 &&\n    p[2] == kBlockSig2 &&\n    p[3] == kBlockSig3 &&\n    p[4] == kBlockSig4 &&\n    p[5] == kBlockSig5;\n}\n\n\nNO_INLINE\nSRes CBase::ReadBlockSignature2()\n{\n  while (state2 < 10)\n  {\n    unsigned b;\n    READ_BITS_8(b, 8)\n    temp[state2] = (Byte)b;\n    state2++;\n  }\n\n  crc = 0;\n  for (unsigned i = 0; i < 4; i++)\n  {\n    crc <<= 8;\n    crc |= temp[6 + i];\n  }\n\n  if (IsBlockSig(temp))\n  {\n    if (!IsBz)\n      NumStreams++;\n    NumBlocks++;\n    IsBz = true;\n    CombinedCrc.Update(crc);\n    state = STATE_BLOCK_START;\n    return SZ_OK;\n  }\n  \n  if (!IsEndSig(temp))\n    return SZ_ERROR_DATA;\n\n  if (!IsBz)\n    NumStreams++;\n  IsBz = true;\n\n  if (_value != 0)\n    MinorError = true;\n\n  AlignToByte();\n\n  state = STATE_STREAM_FINISHED;\n  if (crc != CombinedCrc.GetDigest())\n  {\n    StreamCrcError = true;\n    return SZ_ERROR_DATA;\n  }\n  return SZ_OK;\n}\n\n\nNO_INLINE\nSRes CBase::ReadBlock2()\n{\n  if (state != STATE_BLOCK_SYMBOLS) {\n  PRIN(\"ReadBlock2\")\n\n  if (state == STATE_BLOCK_START)\n  {\n    if (Props.randMode)\n    {\n      READ_BIT(Props.randMode)\n    }\n    state = STATE_ORIG_BITS;\n    // g_Tick = GetCpuTicks();\n  }\n\n  if (state == STATE_ORIG_BITS)\n  {\n    READ_BITS(Props.origPtr, kNumOrigBits)\n    if (Props.origPtr >= blockSizeMax)\n      return SZ_ERROR_DATA;\n    state = STATE_IN_USE;\n  }\n  \n  // why original code compares origPtr to (UInt32)(10 + blockSizeMax)) ?\n\n  if (state == STATE_IN_USE)\n  {\n    READ_BITS(state2, 16)\n    state = STATE_IN_USE2;\n    state3 = 0;\n    numInUse = 0;\n    mtf.StartInit();\n  }\n\n  if (state == STATE_IN_USE2)\n  {\n    for (; state3 < 256; state3++)\n      if (state2 & ((UInt32)0x8000 >> (state3 >> 4)))\n      {\n        unsigned b;\n        READ_BIT(b)\n        if (b)\n          mtf.Add(numInUse++, (Byte)state3);\n      }\n    if (numInUse == 0)\n      return SZ_ERROR_DATA;\n    state = STATE_NUM_TABLES;\n  }\n\n  \n  if (state == STATE_NUM_TABLES)\n  {\n    READ_BITS_8(numTables, kNumTablesBits)\n    state = STATE_NUM_SELECTORS;\n    if (numTables < kNumTablesMin || numTables > kNumTablesMax)\n      return SZ_ERROR_DATA;\n  }\n  \n  if (state == STATE_NUM_SELECTORS)\n  {\n    READ_BITS(numSelectors, kNumSelectorsBits)\n    state = STATE_SELECTORS;\n    state2 = 0x543210;\n    state3 = 0;\n    state4 = 0;\n    // lbzip2 can write small number of additional selectors,\n    // 20.01: we allow big number of selectors here like bzip2-1.0.8\n    if (numSelectors == 0\n      // || numSelectors > kNumSelectorsMax_Decoder\n      )\n      return SZ_ERROR_DATA;\n  }\n\n  if (state == STATE_SELECTORS)\n  {\n    const unsigned kMtfBits = 4;\n    const UInt32 kMtfMask = (1 << kMtfBits) - 1;\n    do\n    {\n      for (;;)\n      {\n        unsigned b;\n        READ_BIT(b)\n        if (!b)\n          break;\n        if (++state4 >= numTables)\n          return SZ_ERROR_DATA;\n      }\n      const UInt32 tmp = (state2 >> (kMtfBits * state4)) & kMtfMask;\n      const UInt32 mask = ((UInt32)1 << ((state4 + 1) * kMtfBits)) - 1;\n      state4 = 0;\n      state2 = ((state2 << kMtfBits) & mask) | (state2 & ~mask) | tmp;\n      // 20.01: here we keep compatibility with bzip2-1.0.8 decoder:\n      if (state3 < kNumSelectorsMax)\n        selectors[state3] = (Byte)tmp;\n    }\n    while (++state3 < numSelectors);\n\n    // we allowed additional dummy selector records filled above to support lbzip2's archives.\n    // but we still don't allow to use these additional dummy selectors in the code bellow\n    // bzip2 1.0.8 decoder also has similar restriction.\n\n    if (numSelectors > kNumSelectorsMax)\n      numSelectors = kNumSelectorsMax;\n\n    state = STATE_LEVELS;\n    state2 = 0;\n    state3 = 0;\n  }\n\n  if (state == STATE_LEVELS)\n  {\n    do\n    {\n      if (state3 == 0)\n      {\n        READ_BITS_8(state3, kNumLevelsBits)\n        state4 = 0;\n        state5 = 0;\n      }\n      const unsigned alphaSize = numInUse + 2;\n      for (; state4 < alphaSize; state4++)\n      {\n        for (;;)\n        {\n          if (state3 < 1 || state3 > kMaxHuffmanLen)\n            return SZ_ERROR_DATA;\n          \n          if (state5 == 0)\n          {\n            unsigned b;\n            READ_BIT(b)\n            if (!b)\n              break;\n          }\n\n          state5 = 1;\n          unsigned b;\n          READ_BIT(b)\n\n          state5 = 0;\n          state3++;\n          state3 -= (b << 1);\n        }\n        lens[state4] = (Byte)state3;\n        state5 = 0;\n      }\n      \n      // 19.03: we use non-full Build() to support lbzip2 archives.\n      // lbzip2 2.5 can produce dummy tree, where lens[i] = kMaxHuffmanLen\n      for (unsigned i = state4; i < kMaxAlphaSize; i++)\n        lens[i] = 0;\n      if (!huffs[state2].Build(lens)) // k_BuildMode_Partial\n        return SZ_ERROR_DATA;\n      state3 = 0;\n    }\n    while (++state2 < numTables);\n\n    {\n      UInt32 *counters = this->Counters;\n      for (unsigned i = 0; i < 256; i++)\n        counters[i] = 0;\n    }\n\n    state = STATE_BLOCK_SYMBOLS;\n\n    groupIndex = 0;\n    groupSize = kGroupSize;\n    runPower = 0;\n    runCounter = 0;\n    blockSize = 0;\n  }\n  \n  if (state != STATE_BLOCK_SYMBOLS)\n    return SZ_ERROR_DATA;\n\n  // g_Ticks[3] += GetCpuTicks() - g_Tick;\n\n  }\n\n  {\n    LOAD_LOCAL\n    const CHuffmanDecoder *huf = &huffs[selectors[groupIndex]];\n\n    for (;;)\n    {\n      if (groupSize == 0)\n      {\n        if (++groupIndex >= numSelectors)\n          return SZ_ERROR_DATA;\n        huf = &huffs[selectors[groupIndex]];\n        groupSize = kGroupSize;\n      }\n\n      if (NUM_BITS < kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL\n      if (NUM_BITS < kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL\n      if (NUM_BITS < kMaxHuffmanLen && _buf != _lim) { UPDATE_VAL }}}\n\n      unsigned sym;\n\n      #define MOV_POS(bs, len) \\\n      { \\\n        if (NUM_BITS < len) \\\n        { \\\n          SAVE_LOCAL \\\n          return SZ_OK; \\\n        } \\\n        VAL <<= len; \\\n        NUM_BITS -= (unsigned)len; \\\n      }\n\n      Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huf, kMaxHuffmanLen, kNumTableBits,\n          VAL,\n          Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES,\n          { return SZ_ERROR_DATA; },\n          MOV_POS, {}, bs)\n\n      groupSize--;\n\n      if (sym < 2)\n      {\n        RUN_COUNTER += (UInt32)(sym + 1) << runPower;\n        runPower++;\n        if (blockSizeMax - BLOCK_SIZE < RUN_COUNTER)\n          return SZ_ERROR_DATA;\n        continue;\n      }\n\n      UInt32 *counters = this->Counters;\n      if (RUN_COUNTER != 0)\n      {\n        UInt32 b = (UInt32)(mtf.Buf[0] & 0xFF);\n        counters[b] += RUN_COUNTER;\n        runPower = 0;\n        #ifdef BZIP2_BYTE_MODE\n          Byte *dest = (Byte *)(&counters[256 + kBlockSizeMax]) + BLOCK_SIZE;\n          const Byte *limit = dest + RUN_COUNTER;\n          BLOCK_SIZE += RUN_COUNTER;\n          RUN_COUNTER = 0;\n          do\n          {\n            dest[0] = (Byte)b;\n            dest[1] = (Byte)b;\n            dest[2] = (Byte)b;\n            dest[3] = (Byte)b;\n            dest += 4;\n          }\n          while (dest < limit);\n        #else\n          UInt32 *dest = &counters[256 + BLOCK_SIZE];\n          const UInt32 *limit = dest + RUN_COUNTER;\n          BLOCK_SIZE += RUN_COUNTER;\n          RUN_COUNTER = 0;\n          do\n          {\n            dest[0] = b;\n            dest[1] = b;\n            dest[2] = b;\n            dest[3] = b;\n            dest += 4;\n          }\n          while (dest < limit);\n        #endif\n      }\n      \n      sym -= 1;\n      if (sym < numInUse)\n      {\n        if (BLOCK_SIZE >= blockSizeMax)\n          return SZ_ERROR_DATA;\n\n        // UInt32 b = (UInt32)mtf.GetAndMove((unsigned)sym);\n\n        const unsigned lim = sym >> Z7_MTF_MOVS;\n        const unsigned pos = (sym & Z7_MTF_MASK) << 3;\n        CMtfVar next = mtf.Buf[lim];\n        CMtfVar prev = (next >> pos) & 0xFF;\n        \n        #ifdef BZIP2_BYTE_MODE\n          ((Byte *)(counters + 256 + kBlockSizeMax))[BLOCK_SIZE++] = (Byte)prev;\n        #else\n          (counters + 256)[BLOCK_SIZE++] = (UInt32)prev;\n        #endif\n        counters[prev]++;\n\n        CMtfVar *m = mtf.Buf;\n        CMtfVar *mLim = m + lim;\n        if (lim != 0)\n        {\n          do\n          {\n            CMtfVar n0 = *m;\n            *m = (n0 << 8) | prev;\n            prev = (n0 >> (Z7_MTF_MASK << 3));\n          }\n          while (++m != mLim);\n        }\n\n        CMtfVar mask = (((CMtfVar)0x100 << pos) - 1);\n        *mLim = (next & ~mask) | (((next << 8) | prev) & mask);\n        continue;\n      }\n      \n      if (sym != numInUse)\n        return SZ_ERROR_DATA;\n      break;\n    }\n\n    // we write additional item that will be read in DecodeBlock1 for prefetching\n    #ifdef BZIP2_BYTE_MODE\n      ((Byte *)(Counters + 256 + kBlockSizeMax))[BLOCK_SIZE] = 0;\n    #else\n      (counters + 256)[BLOCK_SIZE] = 0;\n    #endif\n\n    SAVE_LOCAL\n    Props.blockSize = blockSize;\n    state = STATE_BLOCK_SIGNATURE;\n    state2 = 0;\n\n    PRIN_VAL(\"origPtr\", Props.origPtr);\n    PRIN_VAL(\"blockSize\", Props.blockSize);\n\n    return (Props.origPtr < Props.blockSize) ? SZ_OK : SZ_ERROR_DATA;\n  }\n}\n\n\nNO_INLINE\nstatic void DecodeBlock1(UInt32 *counters, UInt32 blockSize)\n{\n  {\n    UInt32 sum = 0;\n    for (UInt32 i = 0; i < 256; i++)\n    {\n      const UInt32 v = counters[i];\n      counters[i] = sum;\n      sum += v;\n    }\n  }\n  \n  UInt32 *tt = counters + 256;\n  // Compute the T^(-1) vector\n\n  // blockSize--;\n\n  #ifdef BZIP2_BYTE_MODE\n\n  unsigned c = ((const Byte *)(tt + kBlockSizeMax))[0];\n  \n  for (UInt32 i = 0; i < blockSize; i++)\n  {\n    unsigned c1 = c;\n    const UInt32 pos = counters[c];\n    c = ((const Byte *)(tt + kBlockSizeMax))[(size_t)i + 1];\n    counters[c1] = pos + 1;\n    tt[pos] = (i << 8) | ((const Byte *)(tt + kBlockSizeMax))[pos];\n  }\n\n  /*\n  // last iteration without next character prefetching\n  {\n    const UInt32 pos = counters[c];\n    counters[c] = pos + 1;\n    tt[pos] = (blockSize << 8) | ((const Byte *)(tt + kBlockSizeMax))[pos];\n  }\n  */\n\n  #else\n\n  unsigned c = (unsigned)(tt[0] & 0xFF);\n  \n  for (UInt32 i = 0; i < blockSize; i++)\n  {\n    unsigned c1 = c;\n    const UInt32 pos = counters[c];\n    c = (unsigned)(tt[(size_t)i + 1] & 0xFF);\n    counters[c1] = pos + 1;\n    tt[pos] |= (i << 8);\n  }\n\n  /*\n  {\n    const UInt32 pos = counters[c];\n    counters[c] = pos + 1;\n    tt[pos] |= (blockSize << 8);\n  }\n  */\n\n  #endif\n\n\n  /*\n  for (UInt32 i = 0; i < blockSize; i++)\n  {\n    #ifdef BZIP2_BYTE_MODE\n      const unsigned c = ((const Byte *)(tt + kBlockSizeMax))[i];\n      const UInt32 pos = counters[c]++;\n      tt[pos] = (i << 8) | ((const Byte *)(tt + kBlockSizeMax))[pos];\n    #else\n      const unsigned c = (unsigned)(tt[i] & 0xFF);\n      const UInt32 pos = counters[c]++;\n      tt[pos] |= (i << 8);\n    #endif\n  }\n  */\n}\n\n\nvoid CSpecState::Init(UInt32 origPtr, unsigned randMode) throw()\n{\n  _tPos = _tt[_tt[origPtr] >> 8];\n   _prevByte = (unsigned)(_tPos & 0xFF);\n  _reps = 0;\n  _randIndex = 0;\n  _randToGo = -1;\n  if (randMode)\n  {\n    _randIndex = 1;\n    _randToGo = kRandNums[0] - 2;\n  }\n  _crc.Init();\n}\n\n\n\nNO_INLINE\nByte * CSpecState::Decode(Byte *data, size_t size) throw()\n{\n  if (size == 0)\n    return data;\n\n  unsigned prevByte = _prevByte;\n  int reps = _reps;\n  CBZip2Crc crc = _crc;\n  const Byte *lim = data + size;\n\n  while (reps > 0)\n  {\n    reps--;\n    *data++ = (Byte)prevByte;\n    crc.UpdateByte(prevByte);\n    if (data == lim)\n      break;\n  }\n\n  UInt32 tPos = _tPos;\n  UInt32 blockSize = _blockSize;\n  const UInt32 *tt = _tt;\n\n  if (data != lim && blockSize)\n\n  for (;;)\n  {\n    unsigned b = (unsigned)(tPos & 0xFF);\n    tPos = tt[tPos >> 8];\n    blockSize--;\n\n    if (_randToGo >= 0)\n    {\n      if (_randToGo == 0)\n      {\n        b ^= 1;\n        _randToGo = kRandNums[_randIndex];\n        _randIndex++;\n        _randIndex &= 0x1FF;\n      }\n      _randToGo--;\n    }\n\n    if (reps != -(int)kRleModeRepSize)\n    {\n      if (b != prevByte)\n        reps = 0;\n      reps--;\n      prevByte = b;\n      *data++ = (Byte)b;\n      crc.UpdateByte(b);\n      if (data == lim || blockSize == 0)\n        break;\n      continue;\n    }\n\n    reps = (int)b;\n    while (reps)\n    {\n      reps--;\n      *data++ = (Byte)prevByte;\n      crc.UpdateByte(prevByte);\n      if (data == lim)\n        break;\n    }\n    if (data == lim)\n      break;\n    if (blockSize == 0)\n      break;\n  }\n\n  if (blockSize == 1 && reps == -(int)kRleModeRepSize)\n  {\n    unsigned b = (unsigned)(tPos & 0xFF);\n    tPos = tt[tPos >> 8];\n    blockSize--;\n\n    if (_randToGo >= 0)\n    {\n      if (_randToGo == 0)\n      {\n        b ^= 1;\n        _randToGo = kRandNums[_randIndex];\n        _randIndex++;\n        _randIndex &= 0x1FF;\n      }\n      _randToGo--;\n    }\n\n    reps = (int)b;\n  }\n\n  _tPos = tPos;\n  _prevByte = prevByte;\n  _reps = reps;\n  _crc = crc;\n  _blockSize = blockSize;\n  \n  return data;\n}\n\n\nHRESULT CDecoder::Flush()\n{\n  if (_writeRes == S_OK)\n  {\n    _writeRes = WriteStream(_outStream, _outBuf, _outPos);\n    _outWritten += _outPos;\n    _outPos = 0;\n  }\n  return _writeRes;\n}\n\n\nNO_INLINE\nHRESULT CDecoder::DecodeBlock(const CBlockProps &props)\n{\n  _calcedBlockCrc = 0;\n  _blockFinished = false;\n\n  CSpecState block;\n\n  block._blockSize = props.blockSize;\n  block._tt = _counters + 256;\n\n  block.Init(props.origPtr, props.randMode);\n\n  for (;;)\n  {\n    Byte *data = _outBuf + _outPos;\n    size_t size = kOutBufSize - _outPos;\n    \n    if (_outSizeDefined)\n    {\n      const UInt64 rem = _outSize - _outPosTotal;\n      if (size >= rem)\n      {\n        size = (size_t)rem;\n        if (size == 0)\n          return FinishMode ? S_FALSE : S_OK;\n      }\n    }\n\n    TICKS_START\n    const size_t processed = (size_t)(block.Decode(data, size) - data);\n    TICKS_UPDATE(2)\n\n    _outPosTotal += processed;\n    _outPos += processed;\n    \n    if (processed >= size)\n    {\n      RINOK(Flush())\n    }\n    \n    if (block.Finished())\n    {\n      _blockFinished = true;\n      _calcedBlockCrc = block._crc.GetDigest();\n      return S_OK;\n    }\n  }\n}\n\n\nCDecoder::CDecoder():\n    _outBuf(NULL),\n    FinishMode(false),\n    _outSizeDefined(false),\n    _counters(NULL),\n    _inBuf(NULL),\n    _inProcessed(0)\n{\n  #ifndef Z7_ST\n  MtMode = false;\n  NeedWaitScout = false;\n  // ScoutRes = S_OK;\n  #endif\n}\n\n\nCDecoder::~CDecoder()\n{\n  PRIN(\"\\n~CDecoder()\");\n\n  #ifndef Z7_ST\n  \n  if (Thread.IsCreated())\n  {\n    WaitScout();\n\n    _block.StopScout = true;\n\n    PRIN(\"\\nScoutEvent.Set()\");\n    ScoutEvent.Set();\n\n    PRIN(\"\\nThread.Wait()()\");\n    Thread.Wait_Close();\n    PRIN(\"\\n after Thread.Wait()()\");\n\n    // if (ScoutRes != S_OK) throw ScoutRes;\n  }\n  \n  #endif\n\n  BigFree(_counters);\n  MidFree(_outBuf);\n  MidFree(_inBuf);\n}\n\n\nHRESULT CDecoder::ReadInput()\n{\n  if (Base._buf != Base._lim || _inputFinished || _inputRes != S_OK)\n    return _inputRes;\n\n  _inProcessed += (size_t)(Base._buf - _inBuf);\n  Base._buf = _inBuf;\n  Base._lim = _inBuf;\n  UInt32 size = 0;\n  _inputRes = Base.InStream->Read(_inBuf, kInBufSize, &size);\n  _inputFinished = (size == 0);\n  Base._lim = _inBuf + size;\n  return _inputRes;\n}\n\n\nvoid CDecoder::StartNewStream()\n{\n  Base.state = STATE_STREAM_SIGNATURE;\n  Base.state2 = 0;\n  Base.IsBz = false;\n}\n\n\nHRESULT CDecoder::ReadStreamSignature()\n{\n  for (;;)\n  {\n    RINOK(ReadInput())\n    SRes res = Base.ReadStreamSignature2();\n    if (res != SZ_OK)\n      return S_FALSE;\n    if (Base.state == STATE_BLOCK_SIGNATURE)\n      return S_OK;\n    if (_inputFinished)\n    {\n      Base.NeedMoreInput = true;\n      return S_FALSE;\n    }\n  }\n}\n\n\nHRESULT CDecoder::StartRead()\n{\n  StartNewStream();\n  return ReadStreamSignature();\n}\n\n\nHRESULT CDecoder::ReadBlockSignature()\n{\n  for (;;)\n  {\n    RINOK(ReadInput())\n    \n    SRes res = Base.ReadBlockSignature2();\n    \n    if (Base.state == STATE_STREAM_FINISHED)\n      Base.FinishedPackSize = GetInputProcessedSize();\n    if (res != SZ_OK)\n      return S_FALSE;\n    if (Base.state != STATE_BLOCK_SIGNATURE)\n      return S_OK;\n    if (_inputFinished)\n    {\n      Base.NeedMoreInput = true;\n      return S_FALSE;\n    }\n  }\n}\n\n\nHRESULT CDecoder::ReadBlock()\n{\n  for (;;)\n  {\n    RINOK(ReadInput())\n\n    SRes res = Base.ReadBlock2();\n\n    if (res != SZ_OK)\n      return S_FALSE;\n    if (Base.state == STATE_BLOCK_SIGNATURE)\n      return S_OK;\n    if (_inputFinished)\n    {\n      Base.NeedMoreInput = true;\n      return S_FALSE;\n    }\n  }\n}\n\n\n\nHRESULT CDecoder::DecodeStreams(ICompressProgressInfo *progress)\n{\n  {\n    #ifndef Z7_ST\n    _block.StopScout = false;\n    #endif\n  }\n\n  RINOK(StartRead())\n\n  UInt64 inPrev = 0;\n  UInt64 outPrev = 0;\n\n  {\n    #ifndef Z7_ST\n    CWaitScout_Releaser waitScout_Releaser(this);\n\n    bool useMt = false;\n    #endif\n\n    bool wasFinished = false;\n\n    UInt32 crc = 0;\n    UInt32 nextCrc = 0;\n    HRESULT nextRes = S_OK;\n\n    UInt64 packPos = 0;\n\n    CBlockProps props;\n\n    props.blockSize = 0;\n\n    for (;;)\n    {\n      if (progress)\n      {\n        const UInt64 outCur = GetOutProcessedSize();\n        if (packPos - inPrev >= kProgressStep || outCur - outPrev >= kProgressStep)\n        {\n          RINOK(progress->SetRatioInfo(&packPos, &outCur))\n          inPrev = packPos;\n          outPrev = outCur;\n        }\n      }\n\n      if (props.blockSize == 0)\n        if (wasFinished || nextRes != S_OK)\n          return nextRes;\n\n      if (\n          #ifndef Z7_ST\n          !useMt &&\n          #endif\n          !wasFinished && Base.state == STATE_BLOCK_SIGNATURE)\n      {\n        nextRes = ReadBlockSignature();\n        nextCrc = Base.crc;\n        packPos = GetInputProcessedSize();\n\n        wasFinished = true;\n\n        if (nextRes != S_OK)\n          continue;\n\n        if (Base.state == STATE_STREAM_FINISHED)\n        {\n          if (!Base.DecodeAllStreams)\n          {\n            wasFinished = true;\n            continue;\n          }\n          \n          nextRes = StartRead();\n         \n          if (Base.NeedMoreInput)\n          {\n            if (Base.state2 == 0)\n              Base.NeedMoreInput = false;\n            wasFinished = true;\n            nextRes = S_OK;\n            continue;\n          }\n          \n          if (nextRes != S_OK)\n            continue;\n\n          wasFinished = false;\n          continue;\n        }\n\n        wasFinished = false;\n\n        #ifndef Z7_ST\n        if (MtMode)\n        if (props.blockSize != 0)\n        {\n          // we start multithreading, if next block is big enough.\n          const UInt32 k_Mt_BlockSize_Threshold = (1 << 12);  // (1 << 13)\n          if (props.blockSize > k_Mt_BlockSize_Threshold)\n          {\n            if (!Thread.IsCreated())\n            {\n              PRIN(\"=== MT_MODE\");\n              RINOK(CreateThread())\n            }\n            useMt = true;\n          }\n        }\n        #endif\n      }\n\n      if (props.blockSize == 0)\n      {\n        crc = nextCrc;\n        \n        #ifndef Z7_ST\n        if (useMt)\n        {\n          PRIN(\"DecoderEvent.Lock()\");\n          {\n            WRes wres = DecoderEvent.Lock();\n            if (wres != 0)\n              return HRESULT_FROM_WIN32(wres);\n          }\n          NeedWaitScout = false;\n          PRIN(\"-- DecoderEvent.Lock()\");\n          props = _block.Props;\n          nextCrc = _block.NextCrc;\n          if (_block.Crc_Defined)\n            crc = _block.Crc;\n          packPos = _block.PackPos;\n          wasFinished = _block.WasFinished;\n          RINOK(_block.Res)\n        }\n        else\n        #endif\n        {\n          if (Base.state != STATE_BLOCK_START)\n            return E_FAIL;\n\n          TICKS_START\n          Base.Props.randMode = 1;\n          RINOK(ReadBlock())\n          TICKS_UPDATE(0)\n          \n          props = Base.Props;\n          continue;\n        }\n      }\n\n      if (props.blockSize != 0)\n      {\n        TICKS_START\n        DecodeBlock1(_counters, props.blockSize);\n        TICKS_UPDATE(1)\n      }\n      \n      #ifndef Z7_ST\n      if (useMt && !wasFinished)\n      {\n        /*\n        if (props.blockSize == 0)\n        {\n          // this codes switches back to single-threadMode\n          useMt = false;\n          PRIN(\"=== ST_MODE\");\n          continue;\n          }\n        */\n        \n        PRIN(\"ScoutEvent.Set()\");\n        {\n          WRes wres = ScoutEvent.Set();\n          if (wres != 0)\n            return HRESULT_FROM_WIN32(wres);\n        }\n        NeedWaitScout = true;\n      }\n      #endif\n        \n      if (props.blockSize == 0)\n        continue;\n\n      RINOK(DecodeBlock(props))\n\n      if (!_blockFinished)\n        return nextRes;\n\n      props.blockSize = 0;\n      if (_calcedBlockCrc != crc)\n      {\n        BlockCrcError = true;\n        return S_FALSE;\n      }\n    }\n  }\n}\n\n\n\n\nbool CDecoder::CreateInputBufer()\n{\n  if (!_inBuf)\n  {\n    _inBuf = (Byte *)MidAlloc(kInBufSize);\n    if (!_inBuf)\n      return false;\n    Base._buf = _inBuf;\n    Base._lim = _inBuf;\n  }\n  if (!_counters)\n  {\n    const size_t size = (256 + kBlockSizeMax) * sizeof(UInt32)\n      #ifdef BZIP2_BYTE_MODE\n        + kBlockSizeMax\n      #endif\n        + 256;\n    _counters = (UInt32 *)::BigAlloc(size);\n    if (!_counters)\n      return false;\n    Base.Counters = _counters;\n  }\n  return true;\n}\n\n\nvoid CDecoder::InitOutSize(const UInt64 *outSize)\n{\n  _outPosTotal = 0;\n  \n  _outSizeDefined = false;\n  _outSize = 0;\n  if (outSize)\n  {\n    _outSize = *outSize;\n    _outSizeDefined = true;\n  }\n  \n  BlockCrcError = false;\n  \n  Base.InitNumStreams2();\n}\n\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  /*\n  {\n    RINOK(SetInStream(inStream));\n    RINOK(SetOutStreamSize(outSize));\n\n    RINOK(CopyStream(this, outStream, progress));\n    return ReleaseInStream();\n  }\n  */\n\n  _inputFinished = false;\n  _inputRes = S_OK;\n  _writeRes = S_OK;\n\n  try {\n\n  InitOutSize(outSize);\n  \n  // we can request data from InputBuffer after Code().\n  // so we init InputBuffer before any function return.\n\n  InitInputBuffer();\n\n  if (!CreateInputBufer())\n    return E_OUTOFMEMORY;\n\n  if (!_outBuf)\n  {\n    _outBuf = (Byte *)MidAlloc(kOutBufSize);\n    if (!_outBuf)\n      return E_OUTOFMEMORY;\n  }\n\n  Base.InStream = inStream;\n  \n  // InitInputBuffer();\n  \n  _outStream = outStream;\n  _outWritten = 0;\n  _outPos = 0;\n\n  HRESULT res = DecodeStreams(progress);\n\n  Flush();\n\n  Base.InStream = NULL;\n  _outStream = NULL;\n\n  /*\n  if (res == S_OK)\n    if (FinishMode && inSize && *inSize != GetInputProcessedSize())\n      res = S_FALSE;\n  */\n\n  if (res != S_OK)\n    return res;\n\n  } catch(...) { return E_FAIL; }\n\n  return _writeRes;\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))\n{\n  FinishMode = (finishMode != 0);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = GetInStreamSize();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize))\n{\n  Base.AlignToByte();\n  UInt32 i;\n  for (i = 0; i < size; i++)\n  {\n    int b;\n    Base.ReadByte(b);\n    if (b < 0)\n      break;\n    ((Byte *)data)[i] = (Byte)b;\n  }\n  if (processedSize)\n    *processedSize = i;\n  return S_OK;\n}\n\n\n#ifndef Z7_ST\n\n#define PRIN_MT(s) PRIN(\"    \" s)\n\n// #define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; }\n\nstatic THREAD_FUNC_DECL RunScout2(void *p) { ((CDecoder *)p)->RunScout(); return 0; }\n\nHRESULT CDecoder::CreateThread()\n{\n  WRes             wres = DecoderEvent.CreateIfNotCreated_Reset();\n  if (wres == 0) { wres = ScoutEvent.CreateIfNotCreated_Reset();\n  if (wres == 0) { wres = Thread.Create(RunScout2, this); }}\n  return HRESULT_FROM_WIN32(wres);\n}\n\nvoid CDecoder::RunScout()\n{\n  for (;;)\n  {\n    {\n      PRIN_MT(\"ScoutEvent.Lock()\")\n      WRes wres = ScoutEvent.Lock();\n      PRIN_MT(\"-- ScoutEvent.Lock()\")\n      if (wres != 0)\n      {\n        // ScoutRes = wres;\n        return;\n      }\n    }\n\n    CBlock &block = _block;\n\n    if (block.StopScout)\n    {\n      // ScoutRes = S_OK;\n      return;\n    }\n\n    block.Res = S_OK;\n    block.WasFinished = false;\n\n    HRESULT res = S_OK;\n\n    try\n    {\n      UInt64 packPos = GetInputProcessedSize();\n\n      block.Props.blockSize = 0;\n      block.Crc_Defined = false;\n      // block.NextCrc_Defined = false;\n      block.NextCrc = 0;\n      \n      for (;;)\n      {\n        if (Base.state == STATE_BLOCK_SIGNATURE)\n        {\n          res = ReadBlockSignature();\n\n          if (res != S_OK)\n            break;\n          \n          if (block.Props.blockSize == 0)\n          {\n            block.Crc = Base.crc;\n            block.Crc_Defined = true;\n          }\n          else\n          {\n            block.NextCrc = Base.crc;\n            // block.NextCrc_Defined = true;\n          }\n\n          continue;\n        }\n\n        if (Base.state == STATE_BLOCK_START)\n        {\n          if (block.Props.blockSize != 0)\n            break;\n\n          Base.Props.randMode = 1;\n\n          res = ReadBlock();\n          \n          PRIN_MT(\"-- Base.ReadBlock\")\n          if (res != S_OK)\n            break;\n          block.Props = Base.Props;\n          continue;\n        }\n\n        if (Base.state == STATE_STREAM_FINISHED)\n        {\n          if (!Base.DecodeAllStreams)\n          {\n            block.WasFinished = true;\n            break;\n          }\n          \n          res = StartRead();\n          \n          if (Base.NeedMoreInput)\n          {\n            if (Base.state2 == 0)\n              Base.NeedMoreInput = false;\n            block.WasFinished = true;\n            res = S_OK;\n            break;\n          }\n          \n          if (res != S_OK)\n            break;\n          \n          if (GetInputProcessedSize() - packPos > 0) // kProgressStep\n            break;\n          continue;\n        }\n        \n        // throw 1;\n        res = E_FAIL;\n        break;\n      }\n    }\n      \n    catch (...) { res = E_FAIL; }\n      \n    if (res != S_OK)\n    {\n      PRIN_MT(\"error\")\n      block.Res = res;\n      block.WasFinished = true;\n    }\n\n    block.PackPos = GetInputProcessedSize();\n    PRIN_MT(\"DecoderEvent.Set()\")\n    WRes wres = DecoderEvent.Set();\n    if (wres != 0)\n    {\n      // ScoutRes = wres;\n      return;\n    }\n  }\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  MtMode = (numThreads > 1);\n\n  #ifndef BZIP2_BYTE_MODE\n  MtMode = false;\n  #endif\n\n  // MtMode = false;\n  return S_OK;\n}\n\n#endif\n\n\n\n#ifndef Z7_NO_READ_FROM_CODER\n\n\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))\n{\n  Base.InStreamRef = inStream;\n  Base.InStream = inStream;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n{\n  Base.InStreamRef.Release();\n  Base.InStream = NULL;\n  return S_OK;\n}\n\n\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))\n{\n  InitOutSize(outSize);\n\n  InitInputBuffer();\n  \n  if (!CreateInputBufer())\n    return E_OUTOFMEMORY;\n\n  // InitInputBuffer();\n\n  StartNewStream();\n\n  _blockFinished = true;\n\n  ErrorResult = S_OK;\n\n  _inputFinished = false;\n  _inputRes = S_OK;\n\n  return S_OK;\n}\n\n\n\nZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  *processedSize = 0;\n\n  try {\n\n  if (ErrorResult != S_OK)\n    return ErrorResult;\n\n  for (;;)\n  {\n    if (Base.state == STATE_STREAM_FINISHED)\n    {\n      if (!Base.DecodeAllStreams)\n        return ErrorResult;\n      StartNewStream();\n      continue;\n    }\n\n    if (Base.state == STATE_STREAM_SIGNATURE)\n    {\n      ErrorResult = ReadStreamSignature();\n\n      if (Base.NeedMoreInput)\n        if (Base.state2 == 0 && Base.NumStreams != 0)\n        {\n          Base.NeedMoreInput = false;\n          ErrorResult = S_OK;\n          return S_OK;\n        }\n      if (ErrorResult != S_OK)\n        return ErrorResult;\n      continue;\n    }\n    \n    if (_blockFinished && Base.state == STATE_BLOCK_SIGNATURE)\n    {\n      ErrorResult = ReadBlockSignature();\n      \n      if (ErrorResult != S_OK)\n        return ErrorResult;\n      \n      continue;\n    }\n\n    if (_outSizeDefined)\n    {\n      const UInt64 rem = _outSize - _outPosTotal;\n      if (size >= rem)\n        size = (UInt32)rem;\n    }\n    if (size == 0)\n      return S_OK;\n    \n    if (_blockFinished)\n    {\n      if (Base.state != STATE_BLOCK_START)\n      {\n        ErrorResult = E_FAIL;\n        return ErrorResult;\n      }\n      \n      Base.Props.randMode = 1;\n      ErrorResult = ReadBlock();\n      \n      if (ErrorResult != S_OK)\n        return ErrorResult;\n      \n      DecodeBlock1(_counters, Base.Props.blockSize);\n      \n      _spec._blockSize = Base.Props.blockSize;\n      _spec._tt = _counters + 256;\n      _spec.Init(Base.Props.origPtr, Base.Props.randMode);\n\n      _blockFinished = false;\n    }\n\n    {\n      Byte *ptr = _spec.Decode((Byte *)data, size);\n      \n      const UInt32 processed = (UInt32)(ptr - (Byte *)data);\n      data = ptr;\n      size -= processed;\n      (*processedSize) += processed;\n      _outPosTotal += processed;\n      \n      if (_spec.Finished())\n      {\n        _blockFinished = true;\n        if (Base.crc != _spec._crc.GetDigest())\n        {\n          BlockCrcError = true;\n          ErrorResult = S_FALSE;\n          return ErrorResult;\n        }\n      }\n    }\n  }\n\n  } catch(...) { ErrorResult = S_FALSE; return S_FALSE; }\n}\n\n\n\n// ---------- NSIS ----------\n\nZ7_COM7F_IMF(CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  *processedSize = 0;\n\n  try {\n\n  if (ErrorResult != S_OK)\n    return ErrorResult;\n    \n  if (Base.state == STATE_STREAM_FINISHED)\n    return S_OK;\n\n  if (Base.state == STATE_STREAM_SIGNATURE)\n  {\n    Base.blockSizeMax = 9 * kBlockSizeStep;\n    Base.state = STATE_BLOCK_SIGNATURE;\n    // Base.state2 = 0;\n  }\n\n  for (;;)\n  {\n    if (_blockFinished && Base.state == STATE_BLOCK_SIGNATURE)\n    {\n      ErrorResult = ReadInput();\n      if (ErrorResult != S_OK)\n        return ErrorResult;\n      \n      int b;\n      Base.ReadByte(b);\n      if (b < 0)\n      {\n        ErrorResult = S_FALSE;\n        return ErrorResult;\n      }\n      \n      if (b == kFinSig0)\n      {\n        /*\n        if (!Base.AreRemainByteBitsEmpty())\n          ErrorResult = S_FALSE;\n        */\n        Base.state = STATE_STREAM_FINISHED;\n        return ErrorResult;\n      }\n      \n      if (b != kBlockSig0)\n      {\n        ErrorResult = S_FALSE;\n        return ErrorResult;\n      }\n      \n      Base.state = STATE_BLOCK_START;\n    }\n\n    if (_outSizeDefined)\n    {\n      const UInt64 rem = _outSize - _outPosTotal;\n      if (size >= rem)\n        size = (UInt32)rem;\n    }\n    if (size == 0)\n      return S_OK;\n    \n    if (_blockFinished)\n    {\n      if (Base.state != STATE_BLOCK_START)\n      {\n        ErrorResult = E_FAIL;\n        return ErrorResult;\n      }\n\n      Base.Props.randMode = 0;\n      ErrorResult = ReadBlock();\n      \n      if (ErrorResult != S_OK)\n        return ErrorResult;\n      \n      DecodeBlock1(_counters, Base.Props.blockSize);\n      \n      _spec._blockSize = Base.Props.blockSize;\n      _spec._tt = _counters + 256;\n      _spec.Init(Base.Props.origPtr, Base.Props.randMode);\n      \n      _blockFinished = false;\n    }\n    \n    {\n      Byte *ptr = _spec.Decode((Byte *)data, size);\n      \n      const UInt32 processed = (UInt32)(ptr - (Byte *)data);\n      data = ptr;\n      size -= processed;\n      (*processedSize) += processed;\n      _outPosTotal += processed;\n      \n      if (_spec.Finished())\n        _blockFinished = true;\n    }\n  }\n\n  } catch(...) { ErrorResult = S_FALSE; return S_FALSE; }\n}\n\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Decoder.h",
    "content": "﻿// Compress/BZip2Decoder.h\n\n#ifndef ZIP7_INC_COMPRESS_BZIP2_DECODER_H\n#define ZIP7_INC_COMPRESS_BZIP2_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n// #define Z7_NO_READ_FROM_CODER\n// #define Z7_ST\n\n#ifndef Z7_ST\n#include \"../../Windows/Synchronization.h\"\n#include \"../../Windows/Thread.h\"\n#endif\n\n#include \"../ICoder.h\"\n\n#include \"BZip2Const.h\"\n#include \"BZip2Crc.h\"\n#include \"HuffmanDecoder.h\"\n#include \"Mtf8.h\"\n\nnamespace NCompress {\nnamespace NBZip2 {\n\nbool IsEndSig(const Byte *p) throw();\nbool IsBlockSig(const Byte *p) throw();\n\nconst unsigned kNumTableBits = 9;\n\ntypedef NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize, kNumTableBits> CHuffmanDecoder;\n\n\nstruct CBlockProps\n{\n  UInt32 blockSize;\n  UInt32 origPtr;\n  unsigned randMode;\n  \n  CBlockProps(): blockSize(0), origPtr(0), randMode(0) {}\n};\n\n\nstruct CBitDecoder\n{\n  unsigned _numBits;\n  UInt32 _value;\n  const Byte *_buf;\n  const Byte *_lim;\n\n  void InitBitDecoder()\n  {\n    _numBits = 0;\n    _value = 0;\n  }\n\n  void AlignToByte()\n  {\n    unsigned bits = _numBits & 7;\n    _numBits -= bits;\n    _value <<= bits;\n  }\n\n  /*\n  bool AreRemainByteBitsEmpty() const\n  {\n    unsigned bits = _numBits & 7;\n    if (bits != 0)\n      return (_value >> (32 - bits)) == 0;\n    return true;\n  }\n  */\n\n  SRes ReadByte(int &b);\n\n  CBitDecoder():\n    _buf(NULL),\n    _lim(NULL)\n  {\n    InitBitDecoder();\n  }\n};\n\n\n// 19.03: we allow additional 8 selectors to support files created by lbzip2.\nconst UInt32 kNumSelectorsMax_Decoder = kNumSelectorsMax + 8;\n\nstruct CBase: public CBitDecoder\n{\n  unsigned numInUse;\n  UInt32 groupIndex;\n  UInt32 groupSize;\n  unsigned runPower;\n  UInt32 runCounter;\n  UInt32 blockSize;\n\n  UInt32 *Counters;\n  UInt32 blockSizeMax;\n\n  unsigned state;\n  UInt32 state2;\n  unsigned state3;\n  unsigned state4;\n  unsigned state5;\n  unsigned numTables;\n  UInt32 numSelectors;\n\n  CBlockProps Props;\n\nprivate:\n  CMtf8Decoder mtf;\n  Byte selectors[kNumSelectorsMax_Decoder];\n  CHuffmanDecoder huffs[kNumTablesMax];\n\n  Byte lens[kMaxAlphaSize];\n\n  Byte temp[10];\n\npublic:\n  UInt32 crc;\n  CBZip2CombinedCrc CombinedCrc;\n  \n  bool IsBz;\n  bool StreamCrcError;\n  bool MinorError;\n  bool NeedMoreInput;\n\n  bool DecodeAllStreams;\n  \n  UInt64 NumStreams;\n  UInt64 NumBlocks;\n  UInt64 FinishedPackSize;\n\n  ISequentialInStream *InStream;\n\n  #ifndef Z7_NO_READ_FROM_CODER\n  CMyComPtr<ISequentialInStream> InStreamRef;\n  #endif\n\n  CBase():\n      StreamCrcError(false),\n      MinorError(false),\n      NeedMoreInput(false),\n\n      DecodeAllStreams(false),\n      \n      NumStreams(0),\n      NumBlocks(0),\n      FinishedPackSize(0)\n      {}\n\n  void InitNumStreams2()\n  {\n    StreamCrcError = false;\n    MinorError = false;\n    NeedMoreInput = 0;\n    NumStreams = 0;\n    NumBlocks = 0;\n    FinishedPackSize = 0;\n  }\n\n  SRes ReadStreamSignature2();\n  SRes ReadBlockSignature2();\n\n  /* ReadBlock2() : Props->randMode:\n       in:  need read randMode bit\n       out: randMode status */\n  SRes ReadBlock2();\n};\n\n\nclass CSpecState\n{\n  UInt32 _tPos;\n  unsigned _prevByte;\n  int _reps;\n\npublic:\n  CBZip2Crc _crc;\n  UInt32 _blockSize;\n  UInt32 *_tt;\n\n  int _randToGo;\n  unsigned _randIndex;\n\n  void Init(UInt32 origPtr, unsigned randMode) throw();\n\n  bool Finished() const { return _reps <= 0 && _blockSize == 0; }\n\n  Byte *Decode(Byte *data, size_t size) throw();\n};\n\n\n  \n \nclass CDecoder:\n  public ICompressCoder,\n  public ICompressSetFinishMode,\n  public ICompressGetInStreamProcessedSize,\n  public ICompressReadUnusedFromInBuf,\n#ifndef Z7_NO_READ_FROM_CODER\n  public ICompressSetInStream,\n  public ICompressSetOutStreamSize,\n  public ISequentialInStream,\n#endif\n#ifndef Z7_ST\n  public ICompressSetCoderMt,\n#endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetFinishMode)\n  Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize)\n  Z7_COM_QI_ENTRY(ICompressReadUnusedFromInBuf)\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM_QI_ENTRY(ICompressSetInStream)\n  Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)\n  Z7_COM_QI_ENTRY(ISequentialInStream)\n#endif\n#ifndef Z7_ST\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n#endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetFinishMode)\n  Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)\n  Z7_IFACE_COM7_IMP(ICompressReadUnusedFromInBuf)\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_IFACE_COM7_IMP(ICompressSetInStream)\n  Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n  Z7_IFACE_COM7_IMP_NONFINAL(ISequentialInStream)\n#endif\npublic:\n#ifndef Z7_ST\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n#endif\n\nprivate:\n  Byte *_outBuf;\n  size_t _outPos;\n  UInt64 _outWritten;\n  ISequentialOutStream *_outStream;\n  HRESULT _writeRes;\n\nprotected:\n  HRESULT ErrorResult; // for ISequentialInStream::Read mode only\n\npublic:\n\n  UInt32 _calcedBlockCrc;\n  bool _blockFinished;\n  bool BlockCrcError;\n\n  bool FinishMode;\n  bool _outSizeDefined;\n  UInt64 _outSize;\n  UInt64 _outPosTotal;\n\n  CSpecState _spec;\n  UInt32 *_counters;\n\n  #ifndef Z7_ST\n\n  struct CBlock\n  {\n    bool StopScout;\n    \n    bool WasFinished;\n    bool Crc_Defined;\n    // bool NextCrc_Defined;\n    \n    UInt32 Crc;\n    UInt32 NextCrc;\n    HRESULT Res;\n    UInt64 PackPos;\n    \n    CBlockProps Props;\n  };\n\n  CBlock _block;\n\n  bool NeedWaitScout;\n  bool MtMode;\n\n  NWindows::CThread Thread;\n  NWindows::NSynchronization::CAutoResetEvent DecoderEvent;\n  NWindows::NSynchronization::CAutoResetEvent ScoutEvent;\n  // HRESULT ScoutRes;\n  \n  Byte MtPad[1 << 7]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.\n\n\n  void RunScout();\n\n  void WaitScout()\n  {\n    if (NeedWaitScout)\n    {\n      DecoderEvent.Lock();\n      NeedWaitScout = false;\n    }\n  }\n\n  class CWaitScout_Releaser\n  {\n    CDecoder *_decoder;\n  public:\n    CWaitScout_Releaser(CDecoder *decoder): _decoder(decoder) {}\n    ~CWaitScout_Releaser() { _decoder->WaitScout(); }\n  };\n\n  HRESULT CreateThread();\n\n  #endif\n\n  Byte *_inBuf;\n  UInt64 _inProcessed;\n  bool _inputFinished;\n  HRESULT _inputRes;\n\n  CBase Base;\n\n  bool GetCrcError() const { return BlockCrcError || Base.StreamCrcError; }\n\n  void InitOutSize(const UInt64 *outSize);\n  \n  bool CreateInputBufer();\n\n  void InitInputBuffer()\n  {\n    // We use InitInputBuffer() before stream init.\n    // So don't read from stream here\n    _inProcessed = 0;\n    Base._buf = _inBuf;\n    Base._lim = _inBuf;\n    Base.InitBitDecoder();\n  }\n\n  UInt64 GetInputProcessedSize() const\n  {\n    // for NSIS case : we need also look the number of bits in bitDecoder\n    return _inProcessed + (size_t)(Base._buf - _inBuf);\n  }\n\n  UInt64 GetInStreamSize() const\n  {\n    return _inProcessed + (size_t)(Base._buf - _inBuf) - (Base._numBits >> 3);\n  }\n\n  UInt64 GetOutProcessedSize() const { return _outWritten + _outPos; }\n\n  HRESULT ReadInput();\n\n  void StartNewStream();\n  \n  HRESULT ReadStreamSignature();\n  HRESULT StartRead();\n\n  HRESULT ReadBlockSignature();\n  HRESULT ReadBlock();\n\n  HRESULT Flush();\n  HRESULT DecodeBlock(const CBlockProps &props);\n  HRESULT DecodeStreams(ICompressProgressInfo *progress);\n\n  UInt64 GetNumStreams() const { return Base.NumStreams; }\n  UInt64 GetNumBlocks() const { return Base.NumBlocks; }\n\n  CDecoder();\n  virtual ~CDecoder();\n};\n\n\n\n#ifndef Z7_NO_READ_FROM_CODER\n\nclass CNsisDecoder Z7_final: public CDecoder\n{\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n};\n\n#endif\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Encoder.cpp",
    "content": "﻿// BZip2Encoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/BwtSort.h\"\n#include \"../../../C/HuffEnc.h\"\n\n#include \"BZip2Encoder.h\"\n\nnamespace NCompress {\nnamespace NBZip2 {\n\n#define HUFFMAN_LEN 16\n#if HUFFMAN_LEN > Z7_HUFFMAN_LEN_MAX\n  #error Stop_Compiling_Bad_HUFFMAN_LEN_BZip2Encoder\n#endif\n  \nstatic const size_t kBufferSize = 1 << 17;\nstatic const unsigned kNumHuffPasses = 4;\n\n\nbool CThreadInfo::Alloc()\n{\n  if (!m_BlockSorterIndex)\n  {\n    m_BlockSorterIndex = (UInt32 *)::BigAlloc(BLOCK_SORT_BUF_SIZE(kBlockSizeMax) * sizeof(UInt32));\n    if (!m_BlockSorterIndex)\n      return false;\n  }\n\n  if (!m_Block_Base)\n  {\n    const unsigned kPadSize = 1 << 7; // we need at least 1 byte backward padding, becuase we use (m_Block - 1) pointer;\n    m_Block_Base = (Byte *)::MidAlloc(kBlockSizeMax * 5\n        + kBlockSizeMax / 10 + (20 << 10)\n        + kPadSize);\n    if (!m_Block_Base)\n      return false;\n    m_Block = m_Block_Base + kPadSize;\n    m_MtfArray = m_Block + kBlockSizeMax;\n    m_TempArray = m_MtfArray + kBlockSizeMax * 2 + 2;\n  }\n  return true;\n}\n\nvoid CThreadInfo::Free()\n{\n  ::BigFree(m_BlockSorterIndex);\n  m_BlockSorterIndex = NULL;\n  ::MidFree(m_Block_Base);\n  m_Block_Base = NULL;\n}\n\n#ifndef Z7_ST\n\nstatic THREAD_FUNC_DECL MFThread(void *threadCoderInfo)\n{\n  return ((CThreadInfo *)threadCoderInfo)->ThreadFunc();\n}\n\nHRESULT CThreadInfo::Create()\n{\n  WRes             wres = StreamWasFinishedEvent.Create();\n  if (wres == 0) { wres = WaitingWasStartedEvent.Create();\n  if (wres == 0) { wres = CanWriteEvent.Create();\n  if (wres == 0)\n  {\n    wres =\n#ifdef _WIN32\n      Encoder->_props.NumThreadGroups > 1 ?\n        Thread.Create_With_Group(MFThread, this, ThreadNextGroup_GetNext(&Encoder->ThreadNextGroup), 0) : // affinity\n#endif\n      Encoder->_props.Affinity != 0 ?\n        Thread.Create_With_Affinity(MFThread, this, (CAffinityMask)Encoder->_props.Affinity) :\n        Thread.Create(MFThread, this);\n  }}}\n  return HRESULT_FROM_WIN32(wres);\n}\n\nvoid CThreadInfo::FinishStream(bool needLeave)\n{\n  Encoder->StreamWasFinished = true;\n  StreamWasFinishedEvent.Set();\n  if (needLeave)\n    Encoder->CS.Leave();\n  Encoder->CanStartWaitingEvent.Lock();\n  WaitingWasStartedEvent.Set();\n}\n\nTHREAD_FUNC_RET_TYPE CThreadInfo::ThreadFunc()\n{\n  for (;;)\n  {\n    Encoder->CanProcessEvent.Lock();\n    Encoder->CS.Enter();\n    if (Encoder->CloseThreads)\n    {\n      Encoder->CS.Leave();\n      return 0;\n    }\n    if (Encoder->StreamWasFinished)\n    {\n      FinishStream(true);\n      continue;\n    }\n    HRESULT res = S_OK;\n    bool needLeave = true;\n    try\n    {\n      const UInt32 blockSize = Encoder->ReadRleBlock(m_Block);\n      m_UnpackSize = Encoder->m_InStream.GetProcessedSize();\n      m_BlockIndex = Encoder->NextBlockIndex;\n      if (++Encoder->NextBlockIndex == Encoder->NumThreads)\n        Encoder->NextBlockIndex = 0;\n      if (blockSize == 0)\n      {\n        FinishStream(true);\n        continue;\n      }\n      Encoder->CS.Leave();\n      needLeave = false;\n      res = EncodeBlock3(blockSize);\n    }\n    catch(const CInBufferException &e)  { res = e.ErrorCode; }\n    catch(const COutBufferException &e) { res = e.ErrorCode; }\n    catch(...) { res = E_FAIL; }\n    if (res != S_OK)\n    {\n      Encoder->Result = res;\n      FinishStream(needLeave);\n      continue;\n    }\n  }\n}\n\n#endif\n\nvoid CEncProps::Normalize(int level)\n{\n  if (level < 0) level = 5;\n  if (level > 9) level = 9;\n  \n  if (NumPasses == (UInt32)(Int32)-1)\n    NumPasses = (level >= 9 ? 7 : (level >= 7 ? 2 : 1));\n  if (NumPasses < 1) NumPasses = 1;\n  if (NumPasses > kNumPassesMax) NumPasses = kNumPassesMax;\n  \n  if (BlockSizeMult == (UInt32)(Int32)-1)\n    BlockSizeMult = (level >= 5 ? 9 : (level >= 1 ? (unsigned)level * 2 - 1: 1));\n  if (BlockSizeMult < kBlockSizeMultMin) BlockSizeMult = kBlockSizeMultMin;\n  if (BlockSizeMult > kBlockSizeMultMax) BlockSizeMult = kBlockSizeMultMax;\n}\n\nCEncoder::CEncoder()\n{\n  _props.Normalize(-1);\n\n  #ifndef Z7_ST\n  ThreadsInfo = NULL;\n  m_NumThreadsPrev = 0;\n  NumThreads = 1;\n  #endif\n}\n\n#ifndef Z7_ST\nCEncoder::~CEncoder()\n{\n  Free();\n}\n\nHRESULT CEncoder::Create()\n{\n  {\n    WRes             wres = CanProcessEvent.CreateIfNotCreated_Reset();\n    if (wres == 0) { wres = CanStartWaitingEvent.CreateIfNotCreated_Reset(); }\n    if (wres != 0)\n      return HRESULT_FROM_WIN32(wres);\n  }\n  \n  if (ThreadsInfo && m_NumThreadsPrev == NumThreads)\n    return S_OK;\n  try\n  {\n    Free();\n    MtMode = (NumThreads > 1);\n    m_NumThreadsPrev = NumThreads;\n    ThreadsInfo = new CThreadInfo[NumThreads];\n    if (!ThreadsInfo)\n      return E_OUTOFMEMORY;\n  }\n  catch(...) { return E_OUTOFMEMORY; }\n  for (UInt32 t = 0; t < NumThreads; t++)\n  {\n    CThreadInfo &ti = ThreadsInfo[t];\n    ti.Encoder = this;\n    if (MtMode)\n    {\n      HRESULT res = ti.Create();\n      if (res != S_OK)\n      {\n        NumThreads = t;\n        Free();\n        return res;\n      }\n    }\n  }\n  return S_OK;\n}\n\nvoid CEncoder::Free()\n{\n  if (!ThreadsInfo)\n    return;\n  CloseThreads = true;\n  CanProcessEvent.Set();\n  for (UInt32 t = 0; t < NumThreads; t++)\n  {\n    CThreadInfo &ti = ThreadsInfo[t];\n    if (MtMode)\n      ti.Thread.Wait_Close();\n    ti.Free();\n  }\n  delete []ThreadsInfo;\n  ThreadsInfo = NULL;\n}\n#endif\n\nstruct CRleEncoder\n{\n  const Byte *_src;\n  const Byte *_srcLim;\n  Byte *_dest;\n  const Byte *_destLim;\n  Byte _prevByte;\n  unsigned _numReps;\n\n  void Encode();\n};\n\nZ7_NO_INLINE\nvoid CRleEncoder::Encode()\n{\n  const Byte *src = _src;\n  const Byte * const srcLim = _srcLim;\n  Byte *dest = _dest;\n  const Byte * const destLim = _destLim;\n  Byte prev = _prevByte;\n  unsigned numReps = _numReps;\n  // (dest < destLim)\n  // src = srcLim; // for debug\n  while (dest < destLim)\n  {\n    if (src == srcLim)\n      break;\n    const Byte b = *src++;\n    if (b != prev)\n    {\n      if (numReps >= kRleModeRepSize)\n        *dest++ = (Byte)(numReps - kRleModeRepSize);\n      *dest++ = b;\n      numReps = 1;\n      prev = b;\n      /*\n      { // speed optimization code:\n        if (dest >= destLim || src == srcLim)\n          break;\n        const Byte b2 = *src++;\n        *dest++ = b2;\n        numReps += (prev == b2);\n        prev = b2;\n      }\n      */\n      continue;\n    }\n    numReps++;\n    if (numReps <= kRleModeRepSize)\n      *dest++ = b;\n    else if (numReps == kRleModeRepSize + 255)\n    {\n      *dest++ = (Byte)(numReps - kRleModeRepSize);\n      numReps = 0;\n    }\n  }\n  _src = src;\n  _dest = dest;\n  _prevByte = prev;\n  _numReps = numReps;\n  // (dest <= destLim + 1)\n}\n\n\n// out: return value is blockSize: size of data filled in buffer[]:\n// (returned_blockSize <= _props.BlockSizeMult * kBlockSizeStep)\nUInt32 CEncoder::ReadRleBlock(Byte *buffer)\n{\n  CRleEncoder rle;\n  UInt32 i = 0;\n  if (m_InStream.ReadByte(rle._prevByte))\n  {\n    NumBlocks++;\n    const UInt32 blockSize = _props.BlockSizeMult * kBlockSizeStep - 1; // -1 for RLE\n    rle._destLim = buffer + blockSize;\n    rle._numReps = 1;\n    buffer[i++] = rle._prevByte;\n    while (i < blockSize)\n    {\n      rle._dest = buffer + i;\n      size_t rem;\n      const Byte * const ptr = m_InStream.Lookahead(rem);\n      if (rem == 0)\n        break;\n      rle._src = ptr;\n      rle._srcLim = ptr + rem;\n      rle.Encode();\n      m_InStream.Skip((size_t)(rle._src - ptr));\n      i = (UInt32)(size_t)(rle._dest - buffer);\n      // (i <= blockSize + 1)\n    }\n    const int n = (int)rle._numReps - (int)kRleModeRepSize;\n    if (n >= 0)\n      buffer[i++] = (Byte)n;\n  }\n  return i;\n}\n\n\n\nZ7_NO_INLINE\nvoid CThreadInfo::WriteBits2(UInt32 value, unsigned numBits)\n  { m_OutStreamCurrent.WriteBits(value, numBits); }\n/*\nZ7_NO_INLINE\nvoid CThreadInfo::WriteByte2(unsigned b)\n  { m_OutStreamCurrent.WriteByte(b); }\n*/\n// void CEncoder::WriteBits(UInt32 value, unsigned numBits) { m_OutStream.WriteBits(value, numBits); }\nZ7_NO_INLINE\nvoid CEncoder::WriteByte(Byte b) { m_OutStream.WriteByte(b); }\n\n\n#define WRITE_BITS_UPDATE(value, numBits) \\\n{ \\\n  numBits -= _bitPos; \\\n  const UInt32 hi = value >> numBits; \\\n  *_buf++ = (Byte)(_curByte | hi); \\\n  value -= hi << numBits; \\\n  _bitPos = 8; \\\n  _curByte = 0; \\\n}\n\n#if HUFFMAN_LEN > 16\n\n#define WRITE_BITS_HUFF(value2, numBits2) \\\n{ \\\n  UInt32 value = value2; \\\n  unsigned numBits = numBits2; \\\n  while (numBits >= _bitPos) { \\\n    WRITE_BITS_UPDATE(value, numBits) \\\n  } \\\n  _bitPos -= numBits; \\\n  _curByte |= (value << _bitPos); \\\n}\n\n#else // HUFFMAN_LEN <= 16\n\n// numBits2 <= 16 is supported\n#define WRITE_BITS_HUFF(value2, numBits2) \\\n{ \\\n  UInt32 value = value2; \\\n  unsigned numBits = numBits2; \\\n  if (numBits >= _bitPos) \\\n  { \\\n    WRITE_BITS_UPDATE(value, numBits) \\\n    if (numBits >= _bitPos) \\\n    { \\\n      numBits -= _bitPos; \\\n      const UInt32 hi = value >> numBits; \\\n      *_buf++ = (Byte)hi; \\\n      value -= hi << numBits; \\\n    } \\\n  } \\\n  _bitPos -= numBits; \\\n  _curByte |= (value << _bitPos); \\\n}\n\n#endif\n\n#define WRITE_BITS_8(value2, numBits2) \\\n{ \\\n  UInt32 value = value2; \\\n  unsigned numBits = numBits2; \\\n  if (numBits >= _bitPos) \\\n  { \\\n    WRITE_BITS_UPDATE(value, numBits) \\\n  } \\\n  _bitPos -= numBits; \\\n  _curByte |= (value << _bitPos); \\\n}\n\n#define WRITE_BIT_PRE \\\n  { _bitPos--; }\n\n#define WRITE_BIT_POST \\\n{ \\\n  if (_bitPos == 0) \\\n  { \\\n    *_buf++ = (Byte)_curByte; \\\n    _curByte = 0; \\\n    _bitPos = 8; \\\n  } \\\n}\n\n#define WRITE_BIT_0 \\\n{ \\\n  WRITE_BIT_PRE \\\n  WRITE_BIT_POST \\\n}\n\n#define WRITE_BIT_1 \\\n{ \\\n  WRITE_BIT_PRE \\\n  _curByte |= 1u << _bitPos; \\\n  WRITE_BIT_POST \\\n}\n\n\n// blockSize > 0\nvoid CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)\n{\n  // WriteBit2(0); // Randomised = false\n  {\n    const UInt32 origPtr = BlockSort(m_BlockSorterIndex, block, blockSize);\n    // if (m_BlockSorterIndex[origPtr] != 0) throw 1;\n    m_BlockSorterIndex[origPtr] = blockSize;\n    WriteBits2(origPtr, kNumOrigBits + 1); // + 1 for additional high bit flag (Randomised = false)\n  }\n  Byte mtfBuf[256];\n  // memset(mtfBuf, 0, sizeof(mtfBuf)); // to disable MSVC warning\n  unsigned numInUse;\n  {\n    Byte inUse[256];\n    Byte inUse16[16];\n    unsigned i;\n    for (i = 0; i < 256; i++)\n      inUse[i] = 0;\n    for (i = 0; i < 16; i++)\n      inUse16[i] = 0;\n    {\n      const Byte *       cur = block;\n      block = block + (size_t)blockSize - 1;\n      if (cur != block)\n      {\n        do\n        {\n          const unsigned b0 = cur[0];\n          const unsigned b1 = cur[1];\n          cur += 2;\n          inUse[b0] = 1;\n          inUse[b1] = 1;\n        }\n        while (cur < block);\n      }\n      if (cur == block)\n        inUse[cur[0]] = 1;\n      block -= blockSize; // block pointer is (original_block - 1)\n    }\n    numInUse = 0;\n    for (i = 0; i < 256; i++)\n      if (inUse[i])\n      {\n        inUse16[i >> 4] = 1;\n        mtfBuf[numInUse++] = (Byte)i;\n      }\n    for (i = 0; i < 16; i++)\n      WriteBit2(inUse16[i]);\n    for (i = 0; i < 256; i++)\n      if (inUse16[i >> 4])\n        WriteBit2(inUse[i]);\n  }\n  const unsigned alphaSize = numInUse + 2;\n\n  UInt32 symbolCounts[kMaxAlphaSize];\n  {\n    for (unsigned i = 0; i < kMaxAlphaSize; i++)\n      symbolCounts[i] = 0;\n    symbolCounts[(size_t)alphaSize - 1] = 1;\n  }\n\n  Byte *mtfs = m_MtfArray;\n  {\n    const UInt32 *bsIndex = m_BlockSorterIndex;\n    const UInt32 *bsIndex_rle = bsIndex;\n    const UInt32 * const bsIndex_end = bsIndex + blockSize;\n    // block--; // backward fix\n    // block pointer is (original_block - 1)\n    do\n    {\n      const Byte v = block[*bsIndex++];\n      Byte a = mtfBuf[0];\n      if (v != a)\n      {\n        mtfBuf[0] = v;\n        {\n          UInt32 rleSize = (UInt32)(size_t)(bsIndex - bsIndex_rle) - 1;\n          bsIndex_rle = bsIndex;\n          while (rleSize)\n          {\n            const unsigned sym = (unsigned)(--rleSize & 1);\n            *mtfs++ = (Byte)sym;\n            symbolCounts[sym]++;\n            rleSize >>= 1;\n          }\n        }\n        unsigned pos1 = 2; // = real_pos + 1\n        Byte b;\n               b = mtfBuf[1];  mtfBuf[1] = a;  if (v != b)\n             { a = mtfBuf[2];  mtfBuf[2] = b;  if (v == a) pos1 = 3;\n        else { b = mtfBuf[3];  mtfBuf[3] = a;  if (v == b) pos1 = 4;\n        else\n        {\n          Byte *m = mtfBuf + 7;\n          for (;;)\n          {\n            a = m[-3];  m[-3] = b;           if (v == a) { pos1 = (unsigned)(size_t)(m - (mtfBuf + 2)); break; }\n            b = m[-2];  m[-2] = a;           if (v == b) { pos1 = (unsigned)(size_t)(m - (mtfBuf + 1)); break; }\n            a = m[-1];  m[-1] = b;           if (v == a) { pos1 = (unsigned)(size_t)(m - (mtfBuf    )); break; }\n            b = m[ 0];  m[ 0] = a;  m += 4;  if (v == b) { pos1 = (unsigned)(size_t)(m - (mtfBuf + 3)); break; }\n          }\n        }}}\n        symbolCounts[pos1]++;\n        if (pos1 >= 0xff)\n        {\n          *mtfs++ = 0xff;\n          // pos1 -= 0xff;\n          pos1++; // we need only low byte\n        }\n        *mtfs++ = (Byte)pos1;\n      }\n    }\n    while (bsIndex < bsIndex_end);\n\n    UInt32 rleSize = (UInt32)(size_t)(bsIndex - bsIndex_rle);\n    while (rleSize)\n    {\n      const unsigned sym = (unsigned)(--rleSize & 1);\n      *mtfs++ = (Byte)sym;\n      symbolCounts[sym]++;\n      rleSize >>= 1;\n    }\n    \n    unsigned d = alphaSize - 1;\n    if (alphaSize >= 256)\n    {\n      *mtfs++ = 0xff;\n      d = alphaSize; // (-256)\n    }\n    *mtfs++ = (Byte)d;\n  }\n\n  const Byte * const mtf_lim = mtfs;\n\n  UInt32 numSymbols = 0;\n  {\n    for (unsigned i = 0; i < kMaxAlphaSize; i++)\n      numSymbols += symbolCounts[i];\n  }\n\n  unsigned bestNumTables = kNumTablesMin;\n  UInt32 bestPrice = 0xFFFFFFFF;\n  const UInt32 startPos = m_OutStreamCurrent.GetPos();\n  const unsigned startCurByte = m_OutStreamCurrent.GetCurByte();\n  for (unsigned nt = kNumTablesMin; nt <= kNumTablesMax + 1; nt++)\n  {\n    unsigned numTables;\n\n    if (m_OptimizeNumTables)\n    {\n      m_OutStreamCurrent.SetPos(startPos);\n      m_OutStreamCurrent.SetCurState(startPos & 7, startCurByte);\n      numTables = (nt <= kNumTablesMax ? nt : bestNumTables);\n    }\n    else\n    {\n           if (numSymbols <  200) numTables = 2;\n      else if (numSymbols <  600) numTables = 3;\n      else if (numSymbols < 1200) numTables = 4;\n      else if (numSymbols < 2400) numTables = 5;\n      else                        numTables = 6;\n    }\n\n    WriteBits2(numTables, kNumTablesBits);\n    const unsigned numSelectors = (numSymbols + kGroupSize - 1) / kGroupSize;\n    WriteBits2((UInt32)numSelectors, kNumSelectorsBits);\n    \n    {\n      UInt32 remFreq = numSymbols;\n      unsigned gs = 0;\n      unsigned t = numTables;\n      do\n      {\n        UInt32 tFreq = remFreq / t;\n        unsigned ge = gs;\n        UInt32 aFreq = 0;\n        while (aFreq < tFreq) //  && ge < alphaSize)\n          aFreq += symbolCounts[ge++];\n        \n        if (ge > gs + 1 && t != numTables && t != 1 && (((numTables - t) & 1) == 1))\n          aFreq -= symbolCounts[--ge];\n        \n        Byte *lens = Lens[(size_t)t - 1];\n        unsigned i = 0;\n        do\n          lens[i] = (Byte)((i >= gs && i < ge) ? 0 : 1);\n        while (++i < alphaSize);\n        gs = ge;\n        remFreq -= aFreq;\n      }\n      while (--t != 0);\n    }\n    \n    \n    for (unsigned pass = 0; pass < kNumHuffPasses; pass++)\n    {\n      memset(Freqs, 0, sizeof(Freqs[0]) * numTables);\n      // memset(Freqs, 0, sizeof(Freqs));\n      {\n        mtfs = m_MtfArray;\n        UInt32 g = 0;\n        do\n        {\n          unsigned symbols[kGroupSize];\n          unsigned i = 0;\n          do\n          {\n            UInt32 symbol = *mtfs++;\n            if (symbol >= 0xFF)\n              symbol += *mtfs++;\n            symbols[i] = symbol;\n          }\n          while (++i < kGroupSize && mtfs < mtf_lim);\n          \n          UInt32 bestPrice2 = 0xFFFFFFFF;\n          unsigned t = 0;\n          do\n          {\n            const Byte *lens = Lens[t];\n            UInt32 price = 0;\n            unsigned j = 0;\n            do\n              price += lens[symbols[j]];\n            while (++j < i);\n            if (price < bestPrice2)\n            {\n              m_Selectors[g] = (Byte)t;\n              bestPrice2 = price;\n            }\n          }\n          while (++t < numTables);\n          UInt32 *freqs = Freqs[m_Selectors[g++]];\n          unsigned j = 0;\n          do\n            freqs[symbols[j]]++;\n          while (++j < i);\n        }\n        while (mtfs < mtf_lim);\n      }\n      \n      unsigned t = 0;\n      do\n      {\n        UInt32 *freqs = Freqs[t];\n        unsigned i = 0;\n        do\n          if (freqs[i] == 0)\n            freqs[i] = 1;\n        while (++i < alphaSize);\n        Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, HUFFMAN_LEN);\n      }\n      while (++t < numTables);\n    }\n    \n    unsigned _bitPos;  // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte\n    unsigned _curByte; // low (_bitPos) bits are zeros\n                       // high (8 - _bitPos) bits are filled\n    Byte *_buf;\n    {\n      Byte mtfSel[kNumTablesMax];\n      {\n        unsigned t = 0;\n        do\n          mtfSel[t] = (Byte)t;\n        while (++t < numTables);\n      }\n\n      _bitPos = m_OutStreamCurrent._bitPos;\n      _curByte = m_OutStreamCurrent._curByte;\n      _buf = m_OutStreamCurrent._buf;\n      // stream.Init_from_Global(m_OutStreamCurrent);\n      \n      const Byte *selectors = m_Selectors;\n      const Byte * const selectors_lim = selectors + numSelectors;\n      Byte prev = 0; // mtfSel[0];\n      do\n      {\n        const Byte sel = *selectors++;\n        if (prev != sel)\n        {\n          Byte *mtfSel_cur = &mtfSel[1];\n          for (;;)\n          {\n            WRITE_BIT_1\n            const Byte next = *mtfSel_cur;\n            *mtfSel_cur++ = prev;\n            prev = next;\n            if (next == sel)\n              break;\n          }\n          // mtfSel[0] = sel;\n        }\n        WRITE_BIT_0\n      }\n      while (selectors != selectors_lim);\n    }\n    {\n      unsigned t = 0;\n      do\n      {\n        const Byte *lens = Lens[t];\n        unsigned len = lens[0];\n        WRITE_BITS_8(len, kNumLevelsBits)\n        unsigned i = 0;\n        do\n        {\n          const unsigned level = lens[i];\n          while (len != level)\n          {\n            WRITE_BIT_1\n            if (len < level)\n            {\n              len++;\n              WRITE_BIT_0\n            }\n            else\n            {\n              len--;\n              WRITE_BIT_1\n            }\n          }\n          WRITE_BIT_0\n        }\n        while (++i < alphaSize);\n      }\n      while (++t < numTables);\n    }\n    {\n      UInt32 groupSize = 1;\n      const Byte *selectors = m_Selectors;\n      const Byte *lens = NULL;\n      const UInt32 *codes = NULL;\n      mtfs = m_MtfArray;\n      do\n      {\n        unsigned symbol = *mtfs++;\n        if (symbol >= 0xFF)\n          symbol += *mtfs++;\n        if (--groupSize == 0)\n        {\n          groupSize = kGroupSize;\n          const unsigned t = *selectors++;\n          lens = Lens[t];\n          codes = Codes[t];\n        }\n        WRITE_BITS_HUFF(codes[symbol], lens[symbol])\n      }\n      while (mtfs < mtf_lim);\n    }\n    // Restore_from_Local:\n    m_OutStreamCurrent._bitPos = _bitPos;\n    m_OutStreamCurrent._curByte = _curByte;\n    m_OutStreamCurrent._buf = _buf;\n\n    if (!m_OptimizeNumTables)\n      break;\n    const UInt32 price = m_OutStreamCurrent.GetPos() - startPos;\n    if (price <= bestPrice)\n    {\n      if (nt == kNumTablesMax)\n        break;\n      bestPrice = price;\n      bestNumTables = nt;\n    }\n  }\n}\n\n\n// blockSize > 0\nUInt32 CThreadInfo::EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize)\n{\n  WriteByte2(kBlockSig0);\n  WriteByte2(kBlockSig1);\n  WriteByte2(kBlockSig2);\n  WriteByte2(kBlockSig3);\n  WriteByte2(kBlockSig4);\n  WriteByte2(kBlockSig5);\n\n  CBZip2Crc crc;\n  const Byte * const lim = block + blockSize;\n  unsigned b = *block++;\n  crc.UpdateByte(b);\n  for (;;)\n  {\n    const unsigned prev = b;\n    if (block >= lim) { break; } b = *block++;  crc.UpdateByte(b);  if (prev != b) continue;\n    if (block >= lim) { break; } b = *block++;  crc.UpdateByte(b);  if (prev != b) continue;\n    if (block >= lim) { break; } b = *block++;  crc.UpdateByte(b);  if (prev != b) continue;\n    if (block >= lim) { break; } b = *block++;  if (b) do crc.UpdateByte(prev); while (--b);\n    if (block >= lim) { break; } b = *block++;  crc.UpdateByte(b);\n  }\n  const UInt32 crcRes = crc.GetDigest();\n  for (int i = 24; i >= 0; i -= 8)\n    WriteByte2((Byte)(crcRes >> i));\n  EncodeBlock(lim - blockSize, blockSize);\n  return crcRes;\n}\n\n\nvoid CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses)\n{\n  const UInt32 numCrcs = m_NumCrcs;\n\n  const UInt32 startBytePos = m_OutStreamCurrent.GetBytePos();\n  const UInt32 startPos = m_OutStreamCurrent.GetPos();\n  const unsigned startCurByte = m_OutStreamCurrent.GetCurByte();\n  unsigned endCurByte = 0;\n  UInt32 endPos = 0; // 0 means no no additional passes\n  if (numPasses > 1 && blockSize >= (1 << 10))\n  {\n    UInt32 bs0 = blockSize / 2;\n    for (; bs0 < blockSize &&\n           (block[        bs0    ] ==\n            block[(size_t)bs0 - 1] ||\n            block[(size_t)bs0 - 1] ==\n            block[(size_t)bs0 - 2]);\n      bs0++)\n    {}\n    \n    if (bs0 < blockSize)\n    {\n      EncodeBlock2(block, bs0, numPasses - 1);\n      EncodeBlock2(block + bs0, blockSize - bs0, numPasses - 1);\n      endPos = m_OutStreamCurrent.GetPos();\n      endCurByte = m_OutStreamCurrent.GetCurByte();\n      // we prepare next byte as identical byte to starting byte for main encoding attempt:\n      if (endPos & 7)\n        WriteBits2(0, 8 - (endPos & 7));\n      m_OutStreamCurrent.SetCurState((startPos & 7), startCurByte);\n    }\n  }\n\n  const UInt32 startBytePos2 = m_OutStreamCurrent.GetBytePos();\n  const UInt32 startPos2 = m_OutStreamCurrent.GetPos();\n  const UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize);\n\n  if (endPos)\n  {\n    const UInt32 size2 = m_OutStreamCurrent.GetPos() - startPos2;\n    if (size2 >= endPos - startPos)\n    {\n      m_OutStreamCurrent.SetPos(endPos);\n      m_OutStreamCurrent.SetCurState((endPos & 7), endCurByte);\n      return;\n    }\n    const UInt32 numBytes = m_OutStreamCurrent.GetBytePos() - startBytePos2;\n    Byte * const buffer = m_OutStreamCurrent.GetStream();\n    memmove(buffer + startBytePos, buffer + startBytePos2, numBytes);\n    m_OutStreamCurrent.SetPos(startPos + size2);\n    // we don't call m_OutStreamCurrent.SetCurState() here because\n    // m_OutStreamCurrent._curByte is correct already\n  }\n  m_CRCs[numCrcs] = crcVal;\n  m_NumCrcs = numCrcs + 1;\n}\n\n\nHRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize)\n{\n  CMsbfEncoderTemp &outStreamTemp = m_OutStreamCurrent;\n  outStreamTemp.SetStream(m_TempArray);\n  outStreamTemp.Init();\n  m_NumCrcs = 0;\n\n  EncodeBlock2(m_Block, blockSize, Encoder->_props.NumPasses);\n\n#ifndef Z7_ST\n  if (Encoder->MtMode)\n    Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock();\n#endif\n\n  for (UInt32 i = 0; i < m_NumCrcs; i++)\n    Encoder->CombinedCrc.Update(m_CRCs[i]);\n  Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetNonFlushedByteBits());\n  HRESULT res = S_OK;\n\n#ifndef Z7_ST\n  if (Encoder->MtMode)\n  {\n    UInt32 blockIndex = m_BlockIndex + 1;\n    if (blockIndex == Encoder->NumThreads)\n      blockIndex = 0;\n    if (Encoder->Progress)\n    {\n      const UInt64 packSize = Encoder->m_OutStream.GetProcessedSize();\n      res = Encoder->Progress->SetRatioInfo(&m_UnpackSize, &packSize);\n    }\n    Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set();\n  }\n#endif\n  return res;\n}\n\nvoid CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, unsigned lastByteBits)\n{\n  m_OutStream.WriteBytes(data, sizeInBits >> 3);\n  sizeInBits &= 7;\n  if (sizeInBits)\n    m_OutStream.WriteBits(lastByteBits, sizeInBits);\n}\n\n\nHRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)\n{\n  NumBlocks = 0;\n#ifndef Z7_ST\n  Progress = progress;\n  ThreadNextGroup_Init(&ThreadNextGroup, _props.NumThreadGroups, 0); // startGroup\n  RINOK(Create())\n  for (UInt32 t = 0; t < NumThreads; t++)\n#endif\n  {\n    #ifndef Z7_ST\n    CThreadInfo &ti = ThreadsInfo[t];\n    if (MtMode)\n    {\n      WRes             wres = ti.StreamWasFinishedEvent.Reset();\n      if (wres == 0) { wres = ti.WaitingWasStartedEvent.Reset();\n      if (wres == 0) { wres = ti.CanWriteEvent.Reset(); }}\n      if (wres != 0)\n        return HRESULT_FROM_WIN32(wres);\n    }\n    #else\n    CThreadInfo &ti = ThreadsInfo;\n    ti.Encoder = this;\n    #endif\n\n    ti.m_OptimizeNumTables = _props.DoOptimizeNumTables();\n\n    if (!ti.Alloc())\n      return E_OUTOFMEMORY;\n  }\n\n\n  if (!m_InStream.Create(kBufferSize))\n    return E_OUTOFMEMORY;\n  if (!m_OutStream.Create(kBufferSize))\n    return E_OUTOFMEMORY;\n\n\n  m_InStream.SetStream(inStream);\n  m_InStream.Init();\n\n  m_OutStream.SetStream(outStream);\n  m_OutStream.Init();\n\n  CombinedCrc.Init();\n  #ifndef Z7_ST\n  NextBlockIndex = 0;\n  StreamWasFinished = false;\n  CloseThreads = false;\n  CanStartWaitingEvent.Reset();\n  #endif\n\n  WriteByte(kArSig0);\n  WriteByte(kArSig1);\n  WriteByte(kArSig2);\n  WriteByte((Byte)(kArSig3 + _props.BlockSizeMult));\n\n  #ifndef Z7_ST\n\n  if (MtMode)\n  {\n    ThreadsInfo[0].CanWriteEvent.Set();\n    Result = S_OK;\n    CanProcessEvent.Set();\n    UInt32 t;\n    for (t = 0; t < NumThreads; t++)\n      ThreadsInfo[t].StreamWasFinishedEvent.Lock();\n    CanProcessEvent.Reset();\n    CanStartWaitingEvent.Set();\n    for (t = 0; t < NumThreads; t++)\n      ThreadsInfo[t].WaitingWasStartedEvent.Lock();\n    CanStartWaitingEvent.Reset();\n    RINOK(Result)\n  }\n  else\n  #endif\n  {\n    for (;;)\n    {\n      CThreadInfo &ti =\n      #ifndef Z7_ST\n          ThreadsInfo[0];\n      #else\n          ThreadsInfo;\n      #endif\n      const UInt32 blockSize = ReadRleBlock(ti.m_Block);\n      if (blockSize == 0)\n        break;\n      RINOK(ti.EncodeBlock3(blockSize))\n      if (progress)\n      {\n        const UInt64 unpackSize = m_InStream.GetProcessedSize();\n        const UInt64 packSize = m_OutStream.GetProcessedSize();\n        RINOK(progress->SetRatioInfo(&unpackSize, &packSize))\n      }\n    }\n  }\n  WriteByte(kFinSig0);\n  WriteByte(kFinSig1);\n  WriteByte(kFinSig2);\n  WriteByte(kFinSig3);\n  WriteByte(kFinSig4);\n  WriteByte(kFinSig5);\n  {\n    const UInt32 v = CombinedCrc.GetDigest();\n    for (int i = 24; i >= 0; i -= 8)\n      WriteByte((Byte)(v >> i));\n  }\n  RINOK(Flush())\n  if (!m_InStream.WasFinished())\n    return E_FAIL;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const COutBufferException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  int level = -1;\n  CEncProps props;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n\n    if (propID == NCoderPropID::kAffinity)\n    {\n      if (prop.vt != VT_UI8)\n        return E_INVALIDARG;\n      props.Affinity = prop.uhVal.QuadPart;\n      continue;\n    }\n\n    if (propID == NCoderPropID::kNumThreadGroups)\n    {\n      if (prop.vt != VT_UI4)\n        return E_INVALIDARG;\n      props.NumThreadGroups = (UInt32)prop.ulVal;\n      continue;\n    }\n\n    if (propID >= NCoderPropID::kReduceSize)\n      continue;\n    if (prop.vt != VT_UI4)\n      return E_INVALIDARG;\n    const UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n      case NCoderPropID::kNumPasses: props.NumPasses = v; break;\n      case NCoderPropID::kDictionarySize: props.BlockSizeMult = v / kBlockSizeStep; break;\n      case NCoderPropID::kLevel: level = (int)v; break;\n      case NCoderPropID::kNumThreads:\n      {\n        #ifndef Z7_ST\n        SetNumberOfThreads(v);\n        #endif\n        break;\n      }\n      default: return E_INVALIDARG;\n    }\n  }\n  props.Normalize(level);\n  _props = props;\n  return S_OK;\n}\n\n#ifndef Z7_ST\nZ7_COM7F_IMF(CEncoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  const UInt32 kNumThreadsMax = 64;\n  if (numThreads < 1) numThreads = 1;\n  if (numThreads > kNumThreadsMax) numThreads = kNumThreadsMax;\n  NumThreads = numThreads;\n  return S_OK;\n}\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Encoder.h",
    "content": "﻿// BZip2Encoder.h\n\n#ifndef ZIP7_INC_COMPRESS_BZIP2_ENCODER_H\n#define ZIP7_INC_COMPRESS_BZIP2_ENCODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#ifndef Z7_ST\n#include \"../../Windows/Synchronization.h\"\n#include \"../../Windows/Thread.h\"\n#endif\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n#include \"../Common/OutBuffer.h\"\n\n#include \"BitmEncoder.h\"\n#include \"BZip2Const.h\"\n#include \"BZip2Crc.h\"\n\nnamespace NCompress {\nnamespace NBZip2 {\n\nconst unsigned kNumPassesMax = 10;\n\nstruct CMsbfEncoderTemp\n{\n  unsigned _bitPos;  // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte\n  unsigned _curByte; // low (_bitPos) bits are zeros\n                     // high (8 - _bitPos) bits are filled\n  Byte *_buf;\n  Byte *_buf_base;\n  void SetStream(Byte *buf) { _buf_base = _buf = buf;  }\n  Byte *GetStream() const { return _buf_base; }\n\n  void Init()\n  {\n    _bitPos = 8;\n    _curByte = 0;\n    _buf = _buf_base;\n  }\n\n  // required condition: (value >> numBits) == 0\n  // numBits == 0 is allowed\n  void WriteBits(UInt32 value, unsigned numBits)\n  {\n    do\n    {\n      unsigned bp = _bitPos;\n      unsigned curByte = _curByte;\n      if (numBits < bp)\n      {\n        bp -= numBits;\n        _curByte = curByte | (value << bp);\n        _bitPos = bp;\n        return;\n      }\n      numBits -= bp;\n      const UInt32 hi = value >> numBits;\n      value -= (hi << numBits);\n      Byte *buf = _buf;\n      _bitPos = 8;\n      _curByte = 0;\n      *buf++ = (Byte)(curByte | hi);\n      _buf = buf;\n    }\n    while (numBits);\n  }\n\n  void WriteBit(unsigned value)\n  {\n    const unsigned bp = _bitPos - 1;\n    const unsigned curByte = _curByte | (value << bp);\n    _curByte = curByte;\n    _bitPos = bp;\n    if (bp == 0)\n    {\n      *_buf++ = (Byte)curByte;\n      _curByte = 0;\n      _bitPos = 8;\n    }\n  }\n\n  void WriteByte(unsigned b)\n  {\n    const unsigned bp = _bitPos;\n    const unsigned a = _curByte | (b >> (8 - bp));\n    _curByte = b << bp;\n    Byte *buf = _buf;\n    *buf++ = (Byte)a;\n    _buf = buf;\n  }\n\n  UInt32 GetBytePos() const { return (UInt32)(size_t)(_buf - _buf_base); }\n  UInt32 GetPos() const { return GetBytePos() * 8 + 8 - _bitPos; }\n  unsigned GetCurByte() const { return _curByte; }\n  unsigned GetNonFlushedByteBits() const { return _curByte >> _bitPos; }\n  void SetPos(UInt32 bitPos)\n  {\n    _buf = _buf_base + (bitPos >> 3);\n    _bitPos = 8 - ((unsigned)bitPos & 7);\n  }\n  void SetCurState(unsigned bitPos, unsigned curByte)\n  {\n    _bitPos = 8 - bitPos;\n    _curByte = curByte;\n  }\n};\n\n\nclass CEncoder;\n\nclass CThreadInfo\n{\nprivate:\n  CMsbfEncoderTemp m_OutStreamCurrent;\npublic:\n  CEncoder *Encoder;\n  Byte *m_Block;\nprivate:\n  Byte *m_MtfArray;\n  Byte *m_TempArray;\n  UInt32 *m_BlockSorterIndex;\n\npublic:\n  bool m_OptimizeNumTables;\n  UInt32 m_NumCrcs;\n  UInt32 m_BlockIndex;\n  UInt64 m_UnpackSize;\n\n  Byte *m_Block_Base;\n\n  Byte Lens[kNumTablesMax][kMaxAlphaSize];\n  UInt32 Freqs[kNumTablesMax][kMaxAlphaSize];\n  UInt32 Codes[kNumTablesMax][kMaxAlphaSize];\n\n  Byte m_Selectors[kNumSelectorsMax];\n\n  UInt32 m_CRCs[1 << kNumPassesMax];\n\n  void WriteBits2(UInt32 value, unsigned numBits);\n  void WriteByte2(unsigned b) { WriteBits2(b, 8); }\n  void WriteBit2(unsigned v)  { m_OutStreamCurrent.WriteBit(v); }\n\n  void EncodeBlock(const Byte *block, UInt32 blockSize);\n  UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize);\n  void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses);\npublic:\n#ifndef Z7_ST\n  NWindows::CThread Thread;\n\n  NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent;\n  NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent;\n\n  // it's not member of this thread. We just need one event per thread\n  NWindows::NSynchronization::CAutoResetEvent CanWriteEvent;\n\npublic:\n  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.\n  HRESULT Create();\n  void FinishStream(bool needLeave);\n  THREAD_FUNC_RET_TYPE ThreadFunc();\n#endif\n\n  CThreadInfo(): m_BlockSorterIndex(NULL), m_Block_Base(NULL) {}\n  ~CThreadInfo() { Free(); }\n  bool Alloc();\n  void Free();\n\n  HRESULT EncodeBlock3(UInt32 blockSize);\n};\n\n\nstruct CEncProps\n{\n  UInt32 BlockSizeMult;\n  UInt32 NumPasses;\n  UInt32 NumThreadGroups;\n  UInt64 Affinity;\n  \n  CEncProps()\n  {\n    BlockSizeMult = (UInt32)(Int32)-1;\n    NumPasses = (UInt32)(Int32)-1;\n    NumThreadGroups = 0;\n    Affinity = 0;\n  }\n  void Normalize(int level);\n  bool DoOptimizeNumTables() const { return NumPasses > 1; }\n};\n\nclass CEncoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetCoderProperties,\n #ifndef Z7_ST\n  public ICompressSetCoderMt,\n #endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetCoderProperties)\n #ifndef Z7_ST\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetCoderProperties)\n #ifndef Z7_ST\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n #endif\n\n #ifndef Z7_ST\n  UInt32 m_NumThreadsPrev;\n #endif\npublic:\n  CInBuffer m_InStream;\n #ifndef Z7_ST\n  Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.\n #endif\n  CBitmEncoder<COutBuffer> m_OutStream;\n  CEncProps _props;\n  CBZip2CombinedCrc CombinedCrc;\n\n #ifndef Z7_ST\n  CThreadInfo *ThreadsInfo;\n  NWindows::NSynchronization::CManualResetEvent CanProcessEvent;\n  NWindows::NSynchronization::CCriticalSection CS;\n  UInt32 NumThreads;\n  bool MtMode;\n  UInt32 NextBlockIndex;\n\n  bool CloseThreads;\n  bool StreamWasFinished;\n  NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent;\n  CThreadNextGroup ThreadNextGroup;\n\n  HRESULT Result;\n  ICompressProgressInfo *Progress;\n #else\n  CThreadInfo ThreadsInfo;\n #endif\n\n  UInt64 NumBlocks;\n\n  UInt64 GetInProcessedSize() const { return m_InStream.GetProcessedSize(); }\n\n  UInt32 ReadRleBlock(Byte *buf);\n  void WriteBytes(const Byte *data, UInt32 sizeInBits, unsigned lastByteBits);\n  void WriteByte(Byte b);\n\n #ifndef Z7_ST\n  HRESULT Create();\n  void Free();\n #endif\n\npublic:\n  CEncoder();\n #ifndef Z7_ST\n  ~CEncoder();\n #endif\n\n  HRESULT Flush() { return m_OutStream.Flush(); }\n  \n  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BZip2Register.cpp",
    "content": "﻿// BZip2Register.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"BZip2Decoder.h\"\n#if !defined(Z7_EXTRACT_ONLY) && !defined(Z7_BZIP2_EXTRACT_ONLY)\n#include \"BZip2Encoder.h\"\n#endif\n\nnamespace NCompress {\nnamespace NBZip2 {\n\nREGISTER_CODEC_CREATE(CreateDec, CDecoder)\n\n#if !defined(Z7_EXTRACT_ONLY) && !defined(Z7_BZIP2_EXTRACT_ONLY)\nREGISTER_CODEC_CREATE(CreateEnc, CEncoder)\n#else\n#define CreateEnc NULL\n#endif\n\nREGISTER_CODEC_2(BZip2, CreateDec, CreateEnc, 0x40202, \"BZip2\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Bcj2Coder.cpp",
    "content": "﻿// Bcj2Coder.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"Bcj2Coder.h\"\n\nnamespace NCompress {\nnamespace NBcj2 {\n\nCBaseCoder::CBaseCoder()\n{\n  for (unsigned i = 0; i < BCJ2_NUM_STREAMS + 1; i++)\n  {\n    _bufs[i] = NULL;\n    _bufsSizes[i] = 0;\n    _bufsSizes_New[i] = (1 << 18);\n  }\n}\n\nCBaseCoder::~CBaseCoder()\n{\n  for (unsigned i = 0; i < BCJ2_NUM_STREAMS + 1; i++)\n    ::MidFree(_bufs[i]);\n}\n\nHRESULT CBaseCoder::Alloc(bool allocForOrig)\n{\n  const unsigned num = allocForOrig ? BCJ2_NUM_STREAMS + 1 : BCJ2_NUM_STREAMS;\n  for (unsigned i = 0; i < num; i++)\n  {\n    UInt32 size = _bufsSizes_New[i];\n    /* buffer sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP streams\n       must be aligned for 4 */\n    size &= ~(UInt32)3;\n    const UInt32 kMinBufSize = 4;\n    if (size < kMinBufSize)\n      size = kMinBufSize;\n    // size = 4 * 100; // for debug\n    // if (BCJ2_IS_32BIT_STREAM(i) == 1) size = 4 * 1; // for debug\n    if (!_bufs[i] || size != _bufsSizes[i])\n    {\n      if (_bufs[i])\n      {\n        ::MidFree(_bufs[i]);\n        _bufs[i] = NULL;\n      }\n      _bufsSizes[i] = 0;\n      Byte *buf = (Byte *)::MidAlloc(size);\n      if (!buf)\n        return E_OUTOFMEMORY;\n      _bufs[i] = buf;\n      _bufsSizes[i] = size;\n    }\n  }\n  return S_OK;\n}\n\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nCEncoder::CEncoder():\n    _relatLim(BCJ2_ENC_RELAT_LIMIT_DEFAULT)\n    // , _excludeRangeBits(BCJ2_RELAT_EXCLUDE_NUM_BITS)\n    {}\nCEncoder::~CEncoder() {}\n\nZ7_COM7F_IMF(CEncoder::SetInBufSize(UInt32, UInt32 size))\n  { _bufsSizes_New[BCJ2_NUM_STREAMS] = size; return S_OK; }\nZ7_COM7F_IMF(CEncoder::SetOutBufSize(UInt32 streamIndex, UInt32 size))\n  { _bufsSizes_New[streamIndex] = size; return S_OK; }\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\n{\n  UInt32 relatLim = BCJ2_ENC_RELAT_LIMIT_DEFAULT;\n  // UInt32 excludeRangeBits = BCJ2_RELAT_EXCLUDE_NUM_BITS;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = props[i];\n    const PROPID propID = propIDs[i];\n    if (propID >= NCoderPropID::kReduceSize\n        // && propID != NCoderPropID::kHashBits\n        )\n      continue;\n    switch (propID)\n    {\n      /*\n      case NCoderPropID::kDefaultProp:\n      {\n        if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n        UInt32 v = prop.ulVal;\n        if (v > 31)\n          return E_INVALIDARG;\n        relatLim = (UInt32)1 << v;\n        break;\n      }\n      case NCoderPropID::kHashBits:\n      {\n        if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n        UInt32 v = prop.ulVal;\n        if (v > 31)\n          return E_INVALIDARG;\n        excludeRangeBits = v;\n        break;\n      }\n      */\n      case NCoderPropID::kDictionarySize:\n      {\n        if (prop.vt != VT_UI4)\n          return E_INVALIDARG;\n        relatLim = prop.ulVal;\n        if (relatLim > BCJ2_ENC_RELAT_LIMIT_MAX)\n          return E_INVALIDARG;\n        break;\n      }\n      case NCoderPropID::kNumThreads:\n      case NCoderPropID::kLevel:\n        continue;\n      default: return E_INVALIDARG;\n    }\n  }\n  _relatLim = relatLim;\n  // _excludeRangeBits = excludeRangeBits;\n  return S_OK;\n}\n\n\nHRESULT CEncoder::CodeReal(\n    ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,\n    ISequentialOutStream * const *outStreams, const UInt64 * const * /* outSizes */, UInt32 numOutStreams,\n    ICompressProgressInfo *progress)\n{\n  if (numInStreams != 1 || numOutStreams != BCJ2_NUM_STREAMS)\n    return E_INVALIDARG;\n\n  RINOK(Alloc())\n\n  CBcj2Enc_ip_unsigned fileSize_minus1 = BCJ2_ENC_FileSizeField_UNLIMITED;\n  if (inSizes && inSizes[0])\n  {\n    const UInt64 inSize = *inSizes[0];\n   #ifdef BCJ2_ENC_FileSize_MAX\n    if (inSize <= BCJ2_ENC_FileSize_MAX)\n   #endif\n      fileSize_minus1 = BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(inSize);\n  }\n\n  Z7_DECL_CMyComPtr_QI_FROM(ICompressGetSubStreamSize, getSubStreamSize, inStreams[0])\n\n  CBcj2Enc enc;\n  enc.src = _bufs[BCJ2_NUM_STREAMS];\n  enc.srcLim = enc.src;\n  {\n    for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++)\n    {\n      enc.bufs[i] = _bufs[i];\n      enc.lims[i] = _bufs[i] + _bufsSizes[i];\n    }\n  }\n  Bcj2Enc_Init(&enc);\n  enc.fileIp64 = 0;\n  enc.fileSize64_minus1 = fileSize_minus1;\n  enc.relatLimit = _relatLim;\n  // enc.relatExcludeBits = _excludeRangeBits;\n  enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;\n\n  // Varibales that correspond processed data in input stream:\n  UInt64 inPos_without_Temp = 0;  // it doesn't include data in enc.temp[]\n  UInt64 inPos_with_Temp = 0;     // it        includes data in enc.temp[]\n\n  UInt64 prevProgress = 0;\n  UInt64 totalRead = 0;  // size read from input stream\n  UInt64 outSizeRc = 0;\n  UInt64 subStream_Index = 0;\n  UInt64 subStream_StartPos = 0; // global start offset of subStreams[subStream_Index]\n  UInt64 subStream_Size = 0;\n  const Byte *srcLim_Read = _bufs[BCJ2_NUM_STREAMS];\n  bool readWasFinished = false;\n  bool isAccurate = false;\n  bool wasUnknownSize = false;\n\n  for (;;)\n  {\n    if (readWasFinished && enc.srcLim == srcLim_Read)\n      enc.finishMode = BCJ2_ENC_FINISH_MODE_END_STREAM;\n\n    // for debug:\n    // for (int y=0;y<100;y++) { CBcj2Enc enc2 = enc; Bcj2Enc_Encode(&enc2); }\n    \n    Bcj2Enc_Encode(&enc);\n\n    inPos_with_Temp = totalRead - (size_t)(srcLim_Read - enc.src);\n    inPos_without_Temp = inPos_with_Temp - Bcj2Enc_Get_AvailInputSize_in_Temp(&enc);\n    \n    // if (inPos_without_Temp != enc.ip64) return E_FAIL;\n\n    if (Bcj2Enc_IsFinished(&enc))\n      break;\n\n    if (enc.state < BCJ2_NUM_STREAMS)\n    {\n      if (enc.bufs[enc.state] != enc.lims[enc.state])\n        return E_FAIL;\n      const size_t curSize = (size_t)(enc.bufs[enc.state] - _bufs[enc.state]);\n      // printf(\"Write stream = %2d %6d\\n\", enc.state, curSize);\n      RINOK(WriteStream(outStreams[enc.state], _bufs[enc.state], curSize))\n      if (enc.state == BCJ2_STREAM_RC)\n        outSizeRc += curSize;\n      enc.bufs[enc.state] = _bufs[enc.state];\n      enc.lims[enc.state] = _bufs[enc.state] + _bufsSizes[enc.state];\n    }\n    else\n    {\n      if (enc.state != BCJ2_ENC_STATE_ORIG)\n        return E_FAIL;\n      // (enc.state == BCJ2_ENC_STATE_ORIG)\n      if (enc.src != enc.srcLim)\n        return E_FAIL;\n      if (enc.finishMode != BCJ2_ENC_FINISH_MODE_CONTINUE\n          && Bcj2Enc_Get_AvailInputSize_in_Temp(&enc) != 0)\n        return E_FAIL;\n\n      if (enc.src == srcLim_Read)\n      {\n        if (readWasFinished)\n          return E_FAIL;\n        UInt32 curSize = _bufsSizes[BCJ2_NUM_STREAMS];\n        RINOK(inStreams[0]->Read(_bufs[BCJ2_NUM_STREAMS], curSize, &curSize))\n        // printf(\"Read %6u bytes\\n\", curSize);\n        if (curSize == 0)\n          readWasFinished = true;\n        totalRead += curSize;\n        enc.src     = _bufs[BCJ2_NUM_STREAMS];\n        srcLim_Read = _bufs[BCJ2_NUM_STREAMS] + curSize;\n      }\n      enc.srcLim = srcLim_Read;\n\n      if (getSubStreamSize)\n      {\n        /* we set base default conversions options that will be used,\n           if subStream related options will be not OK */\n        enc.fileIp64 = 0;\n        enc.fileSize64_minus1 = fileSize_minus1;\n        for (;;)\n        {\n          UInt64 nextPos;\n          if (isAccurate)\n            nextPos = subStream_StartPos + subStream_Size;\n          else\n          {\n            const HRESULT hres = getSubStreamSize->GetSubStreamSize(subStream_Index, &subStream_Size);\n            if (hres != S_OK)\n            {\n              enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;\n              /* if sub-stream size is unknown, we use default settings.\n                 We still can recover to normal mode for next sub-stream,\n                 if GetSubStreamSize() will return S_OK, when current\n                 sub-stream will be finished.\n              */\n              if (hres == S_FALSE)\n              {\n                wasUnknownSize = true;\n                break;\n              }\n              if (hres == E_NOTIMPL)\n              {\n                getSubStreamSize.Release();\n                break;\n              }\n              return hres;\n            }\n            // printf(\"GetSubStreamSize %6u : %6u \\n\", (unsigned)subStream_Index, (unsigned)subStream_Size);\n            nextPos = subStream_StartPos + subStream_Size;\n            if ((Int64)subStream_Size == -1)\n            {\n              /* it's not expected, but (-1) can mean unknown size. */\n              enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;\n              wasUnknownSize = true;\n              break;\n            }\n            if (nextPos < subStream_StartPos)\n              return E_FAIL;\n            isAccurate =\n                 (nextPos <  totalRead\n              || (nextPos <= totalRead && readWasFinished));\n          }\n          \n          /* (nextPos) is estimated end position of current sub_stream.\n             But only (totalRead) and (readWasFinished) values\n             can confirm that this estimated end position is accurate.\n             That end position is accurate, if it can't be changed in\n             further calls of GetSubStreamSize() */\n\n          /* (nextPos < inPos_with_Temp) is unexpected case here, that we\n               can get if from some incorrect ICompressGetSubStreamSize object,\n               where new GetSubStreamSize() call returns smaller size than\n               confirmed by Read() size from previous GetSubStreamSize() call.\n          */\n          if (nextPos < inPos_with_Temp)\n          {\n            if (wasUnknownSize)\n            {\n              /* that case can be complicated for recovering.\n                 so we disable sub-streams requesting. */\n              enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;\n              getSubStreamSize.Release();\n              break;\n            }\n            return E_FAIL; // to stop after failure\n          }\n\n          if (nextPos <= inPos_with_Temp)\n          {\n            // (nextPos == inPos_with_Temp)\n            /* CBcj2Enc encoder requires to finish each [non-empty] block (sub-stream)\n                  with BCJ2_ENC_FINISH_MODE_END_BLOCK\n               or with BCJ2_ENC_FINISH_MODE_END_STREAM for last block:\n               And we send data of new block to CBcj2Enc, only if previous block was finished.\n               So we switch to next sub-stream if after Bcj2Enc_Encode() call we have\n                 && (enc.finishMode != BCJ2_ENC_FINISH_MODE_CONTINUE)\n                 && (nextPos == inPos_with_Temp)\n                 && (enc.state == BCJ2_ENC_STATE_ORIG)\n            */\n            if (enc.finishMode != BCJ2_ENC_FINISH_MODE_CONTINUE)\n            {\n              /* subStream_StartPos is increased only here.\n                   (subStream_StartPos == inPos_with_Temp) : at start\n                   (subStream_StartPos <= inPos_with_Temp) : will be later\n              */\n              subStream_StartPos = nextPos;\n              subStream_Size = 0;\n              wasUnknownSize = false;\n              subStream_Index++;\n              isAccurate = false;\n              // we don't change finishMode here\n              continue;\n            }\n          }\n          \n          enc.finishMode = BCJ2_ENC_FINISH_MODE_CONTINUE;\n          /* for (!isAccurate) case:\n             (totalRead <= real_end_of_subStream)\n             so we can use BCJ2_ENC_FINISH_MODE_CONTINUE up to (totalRead)\n             // we don't change settings at the end of substream, if settings were unknown,\n          */\n         \n          /* if (wasUnknownSize) then we can't trust size of that sub-stream.\n             so we use default settings instead */\n          if (!wasUnknownSize)\n         #ifdef BCJ2_ENC_FileSize_MAX\n          if (subStream_Size <= BCJ2_ENC_FileSize_MAX)\n         #endif\n          {\n            enc.fileIp64 =\n                (CBcj2Enc_ip_unsigned)(\n                (CBcj2Enc_ip_signed)enc.ip64 +\n                (CBcj2Enc_ip_signed)(subStream_StartPos - inPos_without_Temp));\n            Bcj2Enc_SET_FileSize(&enc, subStream_Size)\n          }\n\n          if (isAccurate)\n          {\n            /* (real_end_of_subStream == nextPos <= totalRead)\n               So we can use BCJ2_ENC_FINISH_MODE_END_BLOCK up to (nextPos). */\n            const size_t rem = (size_t)(totalRead - nextPos);\n            if ((size_t)(enc.srcLim - enc.src) < rem)\n              return E_FAIL;\n            enc.srcLim -= rem;\n            enc.finishMode = BCJ2_ENC_FINISH_MODE_END_BLOCK;\n          }\n\n          break;\n        } // for() loop\n      } // getSubStreamSize\n    }\n\n    if (progress && inPos_without_Temp - prevProgress >= (1 << 22))\n    {\n      prevProgress = inPos_without_Temp;\n      const UInt64 outSize2 = inPos_without_Temp + outSizeRc +\n          (size_t)(enc.bufs[BCJ2_STREAM_RC] - _bufs[BCJ2_STREAM_RC]);\n      // printf(\"progress %8u, %8u\\n\", (unsigned)inSize2, (unsigned)outSize2);\n      RINOK(progress->SetRatioInfo(&inPos_without_Temp, &outSize2))\n    }\n  }\n\n  for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++)\n  {\n    RINOK(WriteStream(outStreams[i], _bufs[i], (size_t)(enc.bufs[i] - _bufs[i])))\n  }\n  // if (inPos_without_Temp != subStream_StartPos + subStream_Size) return E_FAIL;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CEncoder::Code(\n    ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,\n    ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,\n    ICompressProgressInfo *progress))\n{\n  try\n  {\n    return CodeReal(inStreams, inSizes, numInStreams, outStreams, outSizes,numOutStreams, progress);\n  }\n  catch(...) { return E_FAIL; }\n}\n\n#endif\n\n\n\n\n\n\nCDecoder::CDecoder():\n    _finishMode(false)\n#ifndef Z7_NO_READ_FROM_CODER\n    , _outSizeDefined(false)\n    , _outSize(0)\n    , _outSize_Processed(0)\n#endif\n{}\n\nZ7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 streamIndex, UInt32 size))\n  { _bufsSizes_New[streamIndex] = size; return S_OK; }\nZ7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32, UInt32 size))\n  { _bufsSizes_New[BCJ2_NUM_STREAMS] = size; return S_OK; }\n\nZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))\n{\n  _finishMode = (finishMode != 0);\n  return S_OK;\n}\n\nvoid CBaseDecoder::InitCommon()\n{\n  for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++)\n  {\n    dec.lims[i] = dec.bufs[i] = _bufs[i];\n    _readRes[i] = S_OK;\n    _extraSizes[i] = 0;\n    _readSizes[i] = 0;\n  }\n  Bcj2Dec_Init(&dec);\n}\n\n\n/* call ReadInStream() only after Bcj2Dec_Decode().\n   input requirement:\n      (dec.state < BCJ2_NUM_STREAMS)\n*/\nvoid CBaseDecoder::ReadInStream(ISequentialInStream *inStream)\n{\n  const unsigned state = dec.state;\n  UInt32 total;\n  {\n    Byte *buf = _bufs[state];\n    const Byte *cur = dec.bufs[state];\n    // if (cur != dec.lims[state]) throw 1; // unexpected case\n    dec.lims[state] =\n    dec.bufs[state] = buf;\n    total = (UInt32)_extraSizes[state];\n    for (UInt32 i = 0; i < total; i++)\n      buf[i] = cur[i];\n  }\n  \n  if (_readRes[state] != S_OK)\n    return;\n  \n  do\n  {\n    UInt32 curSize = _bufsSizes[state] - total;\n    // if (state == 0) curSize = 0; // for debug\n    // curSize = 7; // for debug\n    /* even if we have reached provided inSizes[state] limit,\n       we call Read() with (curSize != 0), because\n       we want the called handler of stream->Read() could\n       execute required Init/Flushing code even for empty stream.\n       In another way we could call Read() with (curSize == 0) for\n       finished streams, but some Read() handlers can ignore Read(size=0) calls.\n    */\n    const HRESULT hres = inStream->Read(_bufs[state] + total, curSize, &curSize);\n    _readRes[state] = hres;\n    if (curSize == 0)\n      break;\n    _readSizes[state] += curSize;\n    total += curSize;\n    if (hres != S_OK)\n      break;\n  }\n  while (total < 4 && BCJ2_IS_32BIT_STREAM(state));\n  \n  /* we exit from decoding loop here, if we can't\n     provide new data for input stream.\n     Usually it's normal exit after full stream decoding. */\n  if (total == 0)\n    return;\n  \n  if (BCJ2_IS_32BIT_STREAM(state))\n  {\n    const unsigned extra = (unsigned)total & 3;\n    _extraSizes[state] = extra;\n    if (total < 4)\n    {\n      if (_readRes[state] == S_OK)\n        _readRes[state] = S_FALSE; // actually it's stream error. So maybe we need another error code.\n      return;\n    }\n    total -= (UInt32)extra;\n  }\n  \n  dec.lims[state] += total; // = _bufs[state] + total;\n}\n\n\nZ7_COM7F_IMF(CDecoder::Code(\n    ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,\n    ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,\n    ICompressProgressInfo *progress))\n{\n  if (numInStreams != BCJ2_NUM_STREAMS || numOutStreams != 1)\n    return E_INVALIDARG;\n\n  RINOK(Alloc())\n  InitCommon();\n\n  dec.destLim = dec.dest = _bufs[BCJ2_NUM_STREAMS];\n  \n  UInt64 outSizeWritten = 0;\n  UInt64 prevProgress = 0;\n\n  HRESULT hres_Crit = S_OK;  // critical hres status (mostly from input stream reading)\n  HRESULT hres_Weak = S_OK;  // first non-critical error code from input stream reading\n\n  for (;;)\n  {\n    if (Bcj2Dec_Decode(&dec) != SZ_OK)\n    {\n      /* it's possible only at start (first 5 bytes in RC stream) */\n      hres_Crit = S_FALSE;\n      break;\n    }\n    if (dec.state < BCJ2_NUM_STREAMS)\n    {\n      ReadInStream(inStreams[dec.state]);\n      const unsigned state = dec.state;\n      const HRESULT hres = _readRes[state];\n      if (dec.lims[state] == _bufs[state])\n      {\n        // we break decoding, if there are no new data in input stream\n        hres_Crit = hres;\n        break;\n      }\n      if (hres != S_OK && hres_Weak == S_OK)\n        hres_Weak = hres;\n    }\n    else  // (BCJ2_DEC_STATE_ORIG_0 <= state <= BCJ2_STATE_ORIG)\n    {\n      {\n        const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]);\n        if (curSize != 0)\n        {\n          outSizeWritten += curSize;\n          RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize))\n        }\n      }\n      {\n        UInt32 rem = _bufsSizes[BCJ2_NUM_STREAMS];\n        if (outSizes && outSizes[0])\n        {\n          const UInt64 outSize = *outSizes[0] - outSizeWritten;\n          if (rem > outSize)\n            rem = (UInt32)outSize;\n        }\n        dec.dest = _bufs[BCJ2_NUM_STREAMS];\n        dec.destLim = dec.dest + rem;\n        /* we exit from decoding loop here,\n           if (outSizes[0]) limit for output stream was reached */\n        if (rem == 0)\n          break;\n      }\n    }\n\n    if (progress)\n    {\n      // here we don't count additional data in dec.temp (up to 4 bytes for output stream)\n      const UInt64 processed = outSizeWritten + (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]);\n      if (processed - prevProgress >= (1 << 24))\n      {\n        prevProgress = processed;\n        const UInt64 inSize = processed +\n            _readSizes[BCJ2_STREAM_RC] - (size_t)(\n              dec.lims[BCJ2_STREAM_RC] -\n              dec.bufs[BCJ2_STREAM_RC]);\n        RINOK(progress->SetRatioInfo(&inSize, &prevProgress))\n      }\n    }\n  }\n\n  {\n    const size_t curSize = (size_t)(dec.dest - _bufs[BCJ2_NUM_STREAMS]);\n    if (curSize != 0)\n    {\n      outSizeWritten += curSize;\n      RINOK(WriteStream(outStreams[0], _bufs[BCJ2_NUM_STREAMS], curSize))\n    }\n  }\n\n  if (hres_Crit == S_OK) hres_Crit = hres_Weak;\n  if (hres_Crit != S_OK) return hres_Crit;\n\n  if (_finishMode)\n  {\n    if (!Bcj2Dec_IsMaybeFinished_code(&dec))\n      return S_FALSE;\n\n    /* here we support two correct ways to finish full stream decoding\n       with one of the following conditions:\n          - the end of input  stream MAIN was reached\n          - the end of output stream ORIG was reached\n       Currently 7-Zip/7z code ends with (state == BCJ2_STREAM_MAIN),\n       because the sizes of MAIN and ORIG streams are known and these\n       sizes are stored in 7z archive headers.\n       And Bcj2Dec_Decode() exits with (state == BCJ2_STREAM_MAIN),\n       if both MAIN and ORIG streams have reached buffers limits.\n       But if the size of MAIN stream is not known or if the\n       size of MAIN stream includes some padding after payload data,\n       then we still can correctly finish decoding with\n       (state == BCJ2_DEC_STATE_ORIG), if we know the exact size\n       of output ORIG stream.\n    */\n    if (dec.state != BCJ2_STREAM_MAIN)\n    if (dec.state != BCJ2_DEC_STATE_ORIG)\n      return S_FALSE;\n\n    /* the caller also will know written size.\n       So the following check is optional: */\n    if (outSizes && outSizes[0] && *outSizes[0] != outSizeWritten)\n      return S_FALSE;\n\n    if (inSizes)\n    {\n      for (unsigned i = 0; i < BCJ2_NUM_STREAMS; i++)\n      {\n        /* if (inSizes[i]) is defined, we do full check for processed stream size. */\n        if (inSizes[i] && *inSizes[i] != GetProcessedSize_ForInStream(i))\n          return S_FALSE;\n      }\n    }\n\n    /* v23.02: we call Read(0) for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP streams,\n       if there were no Read() calls for such stream.\n       So the handlers of these input streams objects can do\n       Init/Flushing even for case when stream is empty:\n    */\n    for (unsigned i = BCJ2_STREAM_CALL; i < BCJ2_STREAM_CALL + 2; i++)\n    {\n      if (_readSizes[i])\n        continue;\n      Byte b;\n      UInt32 processed;\n      RINOK(inStreams[i]->Read(&b, 0, &processed))\n    }\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value))\n{\n  *value = GetProcessedSize_ForInStream(streamIndex);\n  return S_OK;\n}\n\n\n#ifndef Z7_NO_READ_FROM_CODER\n\nZ7_COM7F_IMF(CDecoder::SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream))\n{\n  _inStreams[streamIndex] = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream2(UInt32 streamIndex))\n{\n  _inStreams[streamIndex].Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))\n{\n  _outSizeDefined = (outSize != NULL);\n  _outSize = 0;\n  if (_outSizeDefined)\n    _outSize = *outSize;\n  _outSize_Processed = 0;\n\n  const HRESULT res = Alloc(false); // allocForOrig\n  InitCommon();\n  dec.destLim = dec.dest = NULL;\n  return res;\n}\n\n\nZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n\n  /* Note the case:\n     The output (ORIG) stream can be empty.\n     But BCJ2_STREAM_RC stream always is not empty.\n     And we want to support full data processing for all streams.\n     We disable check (size == 0) here.\n     So if the caller calls this CDecoder::Read() with (size == 0),\n     we execute required Init/Flushing code in this CDecoder object.\n     Also this CDecoder::Read() function will call Read() for input streams.\n     So the handlers of input streams objects also can do Init/Flushing.\n  */\n  // if (size == 0) return S_OK;  // disabled to allow (size == 0) processing\n\n  UInt32 totalProcessed = 0;\n \n  if (_outSizeDefined)\n  {\n    const UInt64 rem = _outSize - _outSize_Processed;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n  dec.dest = (Byte *)data;\n  dec.destLim = (const Byte *)data + size;\n\n  HRESULT res = S_OK;\n\n  for (;;)\n  {\n    if (Bcj2Dec_Decode(&dec) != SZ_OK)\n      return S_FALSE;  // this error can be only at start of stream\n    {\n      const UInt32 curSize = (UInt32)(size_t)(dec.dest - (Byte *)data);\n      if (curSize != 0)\n      {\n        data = (void *)((Byte *)data + curSize);\n        size -= curSize;\n        _outSize_Processed += curSize;\n        totalProcessed += curSize;\n        if (processedSize)\n          *processedSize = totalProcessed;\n      }\n    }\n    if (dec.state >= BCJ2_NUM_STREAMS)\n      break;\n    ReadInStream(_inStreams[dec.state]);\n    if (dec.lims[dec.state] == _bufs[dec.state])\n    {\n      /* we break decoding, if there are no new data in input stream.\n         and we ignore error code, if some data were written to output buffer. */\n      if (totalProcessed == 0)\n        res = _readRes[dec.state];\n      break;\n    }\n  }\n\n  if (res == S_OK)\n  if (_finishMode && _outSizeDefined && _outSize == _outSize_Processed)\n  {\n    if (!Bcj2Dec_IsMaybeFinished_code(&dec))\n      return S_FALSE;\n    if (dec.state != BCJ2_STREAM_MAIN)\n    if (dec.state != BCJ2_DEC_STATE_ORIG)\n      return S_FALSE;\n  }\n\n  return res;\n}\n\n#endif\n\n}}\n\n\n/*\nextern \"C\"\n{\nextern UInt32 bcj2_stats[256 + 2][2];\n}\n\nstatic class CBcj2Stat\n{\npublic:\n  ~CBcj2Stat()\n  {\n    printf(\"\\nBCJ2 stat:\");\n    unsigned sums[2] = { 0, 0 };\n    int i;\n    for (i = 2; i < 256 + 2; i++)\n    {\n      sums[0] += bcj2_stats[i][0];\n      sums[1] += bcj2_stats[i][1];\n    }\n    const unsigned sums2 = sums[0] + sums[1];\n    for (int vi = 0; vi < 256 + 3; vi++)\n    {\n      printf(\"\\n\");\n      UInt32 n0, n1;\n      if (vi < 4)\n        printf(\"\\n\");\n      \n      if (vi < 2)\n        i = vi;\n      else if (vi == 2)\n        i = -1;\n      else\n        i = vi - 1;\n  \n      if (i < 0)\n      {\n        n0 = sums[0];\n        n1 = sums[1];\n        printf(\"calls   :\");\n      }\n      else\n      {\n        if (i == 0)\n          printf(\"jcc     :\");\n        else if (i == 1)\n          printf(\"jump    :\");\n        else\n          printf(\"call %02x :\", i - 2);\n        n0 = bcj2_stats[i][0];\n        n1 = bcj2_stats[i][1];\n      }\n      \n      const UInt32 sum = n0 + n1;\n      printf(\" %10u\", sum);\n\n    #define PRINT_PERC(val, sum) \\\n        { UInt32 _sum  = sum; if (_sum == 0) _sum = 1; \\\n        printf(\" %7.3f %%\", (double)((double)val * (double)100 / (double)_sum )); }\n\n      if (i >= 2 || i < 0)\n      {\n        PRINT_PERC(sum, sums2);\n      }\n      else\n        printf(\"%10s\", \"\");\n\n      printf(\" :%10u\", n0);\n      PRINT_PERC(n0, sum);\n\n      printf(\" :%10u\", n1);\n      PRINT_PERC(n1, sum);\n    }\n    printf(\"\\n\\n\");\n    fflush(stdout);\n  }\n} g_CBcjStat;\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Bcj2Coder.h",
    "content": "﻿// Bcj2Coder.h\n\n#ifndef ZIP7_INC_COMPRESS_BCJ2_CODER_H\n#define ZIP7_INC_COMPRESS_BCJ2_CODER_H\n\n#include \"../../../C/Bcj2.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NBcj2 {\n\nclass CBaseCoder\n{\nprotected:\n  Byte *_bufs[BCJ2_NUM_STREAMS + 1];\n  UInt32 _bufsSizes[BCJ2_NUM_STREAMS + 1];\n  UInt32 _bufsSizes_New[BCJ2_NUM_STREAMS + 1];\n\n  HRESULT Alloc(bool allocForOrig = true);\npublic:\n  CBaseCoder();\n  ~CBaseCoder();\n};\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nclass CEncoder Z7_final:\n  public ICompressCoder2,\n  public ICompressSetCoderProperties,\n  public ICompressSetBufSize,\n  public CMyUnknownImp,\n  public CBaseCoder\n{\n  Z7_IFACES_IMP_UNK_3(\n      ICompressCoder2,\n      ICompressSetCoderProperties,\n      ICompressSetBufSize)\n\n  UInt32 _relatLim;\n  // UInt32 _excludeRangeBits;\n\n  HRESULT CodeReal(\n      ISequentialInStream * const *inStreams, const UInt64 * const *inSizes, UInt32 numInStreams,\n      ISequentialOutStream * const *outStreams, const UInt64 * const *outSizes, UInt32 numOutStreams,\n      ICompressProgressInfo *progress);\npublic:\n  CEncoder();\n  ~CEncoder();\n};\n\n#endif\n\n\n\nclass CBaseDecoder: public CBaseCoder\n{\nprotected:\n  HRESULT _readRes[BCJ2_NUM_STREAMS];\n  unsigned _extraSizes[BCJ2_NUM_STREAMS];\n  UInt64 _readSizes[BCJ2_NUM_STREAMS];\n\n  CBcj2Dec dec;\n\n  UInt64 GetProcessedSize_ForInStream(unsigned i) const\n  {\n    return _readSizes[i] - ((size_t)(dec.lims[i] - dec.bufs[i]) + _extraSizes[i]);\n  }\n  void InitCommon();\n  void ReadInStream(ISequentialInStream *inStream);\n};\n\n\nclass CDecoder Z7_final:\n  public ICompressCoder2,\n  public ICompressSetFinishMode,\n  public ICompressGetInStreamProcessedSize2,\n  public ICompressSetBufSize,\n#ifndef Z7_NO_READ_FROM_CODER\n  public ICompressSetInStream2,\n  public ICompressSetOutStreamSize,\n  public ISequentialInStream,\n#endif\n  public CMyUnknownImp,\n  public CBaseDecoder\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder2)\n    Z7_COM_QI_ENTRY(ICompressSetFinishMode)\n    Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize2)\n    Z7_COM_QI_ENTRY(ICompressSetBufSize)\n  #ifndef Z7_NO_READ_FROM_CODER\n    Z7_COM_QI_ENTRY(ICompressSetInStream2)\n    Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)\n    Z7_COM_QI_ENTRY(ISequentialInStream)\n  #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n  \n  Z7_IFACE_COM7_IMP(ICompressCoder2)\n  Z7_IFACE_COM7_IMP(ICompressSetFinishMode)\n  Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize2)\n  Z7_IFACE_COM7_IMP(ICompressSetBufSize)\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_IFACE_COM7_IMP(ICompressSetInStream2)\n  Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n#endif\n\n  bool _finishMode;\n\n#ifndef Z7_NO_READ_FROM_CODER\n  bool _outSizeDefined;\n  UInt64 _outSize;\n  UInt64 _outSize_Processed;\n  CMyComPtr<ISequentialInStream> _inStreams[BCJ2_NUM_STREAMS];\n#endif\n \npublic:\n  CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Bcj2Register.cpp",
    "content": "﻿// Bcj2Register.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"Bcj2Coder.h\"\n\nnamespace NCompress {\nnamespace NBcj2 {\n\nREGISTER_CODEC_CREATE_2(CreateCodec, CDecoder(), ICompressCoder2)\n#ifndef Z7_EXTRACT_ONLY\nREGISTER_CODEC_CREATE_2(CreateCodecOut, CEncoder(), ICompressCoder2)\n#else\n#define CreateCodecOut NULL\n#endif\n\nREGISTER_CODEC_VAR(BCJ2)\n  { CreateCodec, CreateCodecOut, 0x303011B, \"BCJ2\", 4, false };\n\nREGISTER_CODEC(BCJ2)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BcjCoder.cpp",
    "content": "﻿// BcjCoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"BcjCoder.h\"\n\nnamespace NCompress {\nnamespace NBcj {\n\nZ7_COM7F_IMF(CCoder2::Init())\n{\n  _pc = 0;\n  _state = Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL;\n  return S_OK;\n}\n\nZ7_COM7F_IMF2(UInt32, CCoder2::Filter(Byte *data, UInt32 size))\n{\n  const UInt32 processed = (UInt32)(size_t)(_convFunc(data, size, _pc, &_state) - data);\n  _pc += processed;\n  return processed;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BcjCoder.h",
    "content": "﻿// BcjCoder.h\n\n#ifndef ZIP7_INC_COMPRESS_BCJ_CODER_H\n#define ZIP7_INC_COMPRESS_BCJ_CODER_H\n\n#include \"../../../C/Bra.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NBcj {\n\n/* CCoder in old versions used another constructor parameter CCoder(int encode).\n   And some code called it as CCoder(0).\n   We have changed constructor parameter type.\n   So we have changed the name of class also to CCoder2. */\n\nZ7_CLASS_IMP_COM_1(\n  CCoder2\n  , ICompressFilter\n)\n  UInt32 _pc;\n  UInt32 _state;\n  z7_Func_BranchConvSt _convFunc;\npublic:\n  CCoder2(z7_Func_BranchConvSt convFunc):\n      _pc(0),\n      _state(Z7_BRANCH_CONV_ST_X86_STATE_INIT_VAL),\n      _convFunc(convFunc)\n    {}\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BcjRegister.cpp",
    "content": "﻿// BcjRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"BcjCoder.h\"\n\nnamespace NCompress {\nnamespace NBcj {\n\nREGISTER_FILTER_E(BCJ,\n    CCoder2(z7_BranchConvSt_X86_Dec),\n    CCoder2(z7_BranchConvSt_X86_Enc),\n    0x3030103, \"BCJ\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BitlDecoder.cpp",
    "content": "﻿// BitlDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"BitlDecoder.h\"\n\nnamespace NBitl {\n\n#if defined(Z7_BITL_USE_REVERSE_BITS_TABLE)\n\nMY_ALIGN(64)\nByte kReverseTable[256];\n\nstatic\nstruct CReverseerTableInitializer\n{\n  CReverseerTableInitializer()\n  {\n    for (unsigned i = 0; i < 256; i++)\n    {\n      unsigned\n      x = ((i & 0x55) << 1) | ((i >> 1) & 0x55);\n      x = ((x & 0x33) << 2) | ((x >> 2) & 0x33);\n      kReverseTable[i] = (Byte)((x << 4) | (x >> 4));\n    }\n  }\n} g_ReverseerTableInitializer;\n\n#elif 0\nunsigned ReverseBits8test(unsigned i) { return ReverseBits8(i); }\n#endif\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BitlDecoder.h",
    "content": "﻿// BitlDecoder.h -- the Least Significant Bit of byte is First\n\n#ifndef ZIP7_INC_BITL_DECODER_H\n#define ZIP7_INC_BITL_DECODER_H\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../IStream.h\"\n\nnamespace NBitl {\n\nconst unsigned kNumBigValueBits = 8 * 4;\nconst unsigned kNumValueBytes = 3;\nconst unsigned kNumValueBits = 8 * kNumValueBytes;\nconst UInt32 kMask = (1 << kNumValueBits) - 1;\n\n#if !defined(Z7_BITL_USE_REVERSE_BITS_TABLE)\n#if 1 && defined(MY_CPU_ARM_OR_ARM64) \\\n    && (defined(MY_CPU_ARM64) || defined(__ARM_ARCH_6T2__) \\\n       || defined(__ARM_ARCH) && (__ARM_ARCH >= 7)) \\\n    && (defined(__GNUC__) && (__GNUC__ >= 4) \\\n       || defined(__clang__) && (__clang_major__ >= 4))\n  #define Z7_BITL_USE_REVERSE_BITS_INSTRUCTION\n#elif 1\n  #define Z7_BITL_USE_REVERSE_BITS_TABLE\n#endif\n#endif\n\n#if defined(Z7_BITL_USE_REVERSE_BITS_TABLE)\nextern Byte kReverseTable[256];\n#endif\n\ninline unsigned ReverseBits8(unsigned i)\n{\n#if defined(Z7_BITL_USE_REVERSE_BITS_TABLE)\n  return kReverseTable[i];\n#elif defined(Z7_BITL_USE_REVERSE_BITS_INSTRUCTION)\n  // rbit is available in ARMv6T2 and above\n  asm (\"rbit \"\n#if defined(MY_CPU_ARM)\n    \"%0,%0\"   // it uses default register size,\n              // but we need 32-bit register here.\n              // we must use it only if default register size is 32-bit.\n              // it will work incorrectly for ARM64.\n#else\n    \"%w0,%w0\" // it uses 32-bit registers in ARM64.\n              // compiler for (MY_CPU_ARM) can't compile it.\n#endif\n    : \"+r\" (i));\n  return i >> 24;\n#else\n  unsigned\n      x = ((i & 0x55) << 1) | ((i >> 1) & 0x55);\n      x = ((x & 0x33) << 2) | ((x >> 2) & 0x33);\n  return  ((x & 0x0f) << 4) |  (x >> 4);\n#endif\n}\n\n\n/* TInByte must support \"Extra Bytes\" (bytes that can be read after the end of stream\n   TInByte::ReadByte() returns 0xFF after the end of stream\n   TInByte::NumExtraBytes contains the number \"Extra Bytes\"\n       \n   Bitl decoder can read up to 4 bytes ahead to internal buffer. */\n\ntemplate<class TInByte>\nclass CBaseDecoder\n{\nprotected:\n  unsigned _bitPos;\n  UInt32 _value;\n  TInByte _stream;\npublic:\n  bool Create(UInt32 bufSize) { return _stream.Create(bufSize); }\n  void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream); }\n  void ClearStreamPtr() { _stream.ClearStreamPtr(); }\n  void Init()\n  {\n    _stream.Init();\n    _bitPos = kNumBigValueBits;\n    _value = 0;\n  }\n\n  // the size of portion data in real stream that was already read from this object.\n  // it doesn't include unused data in BitStream object buffer (up to 4 bytes)\n  // it doesn't include unused data in TInByte buffers\n  // it doesn't include virtual Extra bytes after the end of real stream data\n  UInt64 GetStreamSize() const\n  {\n    return ExtraBitsWereRead() ?\n        _stream.GetStreamSize():\n        GetProcessedSize();\n  }\n\n  // the size of virtual data that was read from this object.\n  UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); }\n\n  bool ThereAreDataInBitsBuffer() const { return this->_bitPos != kNumBigValueBits; }\n  \n  Z7_FORCE_INLINE\n  void Normalize()\n  {\n    for (; _bitPos >= 8; _bitPos -= 8)\n      _value = ((UInt32)_stream.ReadByte() << (kNumBigValueBits - _bitPos)) | _value;\n  }\n  \n  Z7_FORCE_INLINE\n  UInt32 ReadBits(unsigned numBits)\n  {\n    Normalize();\n    UInt32 res = _value & ((1 << numBits) - 1);\n    _bitPos += numBits;\n    _value >>= numBits;\n    return res;\n  }\n\n  bool ExtraBitsWereRead() const\n  {\n    return (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3));\n  }\n  \n  bool ExtraBitsWereRead_Fast() const\n  {\n    // full version is not inlined in vc6.\n    // return _stream.NumExtraBytes != 0 && (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3));\n    \n    // (_stream.NumExtraBytes > 4) is fast overread detection. It's possible that\n    // it doesn't return true, if small number of extra bits were read.\n    return (_stream.NumExtraBytes > 4);\n  }\n\n  // it must be fixed !!! with extra bits\n  // UInt32 GetNumExtraBytes() const { return _stream.NumExtraBytes; }\n};\n\ntemplate<class TInByte>\nclass CDecoder: public CBaseDecoder<TInByte>\n{\n  UInt32 _normalValue;\n\npublic:\n  void Init()\n  {\n    CBaseDecoder<TInByte>::Init();\n    _normalValue = 0;\n  }\n  \n  Z7_FORCE_INLINE\n  void Normalize()\n  {\n    for (; this->_bitPos >= 8; this->_bitPos -= 8)\n    {\n      const unsigned b = this->_stream.ReadByte();\n      _normalValue = ((UInt32)b << (kNumBigValueBits - this->_bitPos)) | _normalValue;\n      this->_value = (this->_value << 8) | ReverseBits8(b);\n    }\n  }\n  \n  Z7_FORCE_INLINE\n  UInt32 GetValue(unsigned numBits)\n  {\n    Normalize();\n    return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits);\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue_InHigh32bits()\n  {\n    Normalize();\n    return this->_value << this->_bitPos;\n  }\n  \n  Z7_FORCE_INLINE\n  void MovePos(size_t numBits)\n  {\n    this->_bitPos += (unsigned)numBits;\n    _normalValue >>= numBits;\n  }\n  \n  Z7_FORCE_INLINE\n  UInt32 ReadBits(unsigned numBits)\n  {\n    Normalize();\n    UInt32 res = _normalValue & ((1 << numBits) - 1);\n    MovePos(numBits);\n    return res;\n  }\n\n  void AlignToByte() { MovePos((32 - this->_bitPos) & 7); }\n  \n  Z7_FORCE_INLINE\n  Byte ReadDirectByte() { return this->_stream.ReadByte(); }\n\n  Z7_FORCE_INLINE\n  size_t ReadDirectBytesPart(Byte *buf, size_t size) { return this->_stream.ReadBytesPart(buf, size); }\n  \n  Z7_FORCE_INLINE\n  Byte ReadAlignedByte()\n  {\n    if (this->_bitPos == kNumBigValueBits)\n      return this->_stream.ReadByte();\n    Byte b = (Byte)(_normalValue & 0xFF);\n    MovePos(8);\n    return b;\n  }\n\n  // call it only if the object is aligned for byte.\n  Z7_FORCE_INLINE\n  bool ReadAlignedByte_FromBuf(Byte &b)\n  {\n    if (this->_stream.NumExtraBytes != 0)\n      if (this->_stream.NumExtraBytes >= 4\n          || kNumBigValueBits - this->_bitPos <= (this->_stream.NumExtraBytes << 3))\n        return false;\n    if (this->_bitPos == kNumBigValueBits)\n      return this->_stream.ReadByte_FromBuf(b);\n    b = (Byte)(_normalValue & 0xFF);\n    MovePos(8);\n    return true;\n  }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BitlEncoder.h",
    "content": "﻿// BitlEncoder.h -- the Least Significant Bit of byte is First\n\n#ifndef ZIP7_INC_BITL_ENCODER_H\n#define ZIP7_INC_BITL_ENCODER_H\n\n#include \"../Common/OutBuffer.h\"\n\nclass CBitlEncoder\n{\n  COutBuffer _stream;\n  unsigned _bitPos;\n  Byte _curByte;\npublic:\n  bool Create(UInt32 bufSize) { return _stream.Create(bufSize); }\n  void SetStream(ISequentialOutStream *outStream) { _stream.SetStream(outStream); }\n  // unsigned GetBitPosition() const { return (8 - _bitPos); }\n  UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() + ((8 - _bitPos + 7) >> 3); }\n  void Init()\n  {\n    _stream.Init();\n    _bitPos = 8;\n    _curByte = 0;\n  }\n  HRESULT Flush()\n  {\n    FlushByte();\n    return _stream.Flush();\n  }\n  void FlushByte()\n  {\n    if (_bitPos < 8)\n      _stream.WriteByte(_curByte);\n    _bitPos = 8;\n    _curByte = 0;\n  }\n  Z7_FORCE_INLINE\n  void WriteBits(UInt32 value, unsigned numBits)\n  {\n    while (numBits > 0)\n    {\n      if (numBits < _bitPos)\n      {\n        _curByte |= (Byte)((value & ((1 << numBits) - 1)) << (8 - _bitPos));\n        _bitPos -= numBits;\n        return;\n      }\n      numBits -= _bitPos;\n      _stream.WriteByte((Byte)(_curByte | (value << (8 - _bitPos))));\n      value >>= _bitPos;\n      _bitPos = 8;\n      _curByte = 0;\n    }\n  }\n  void WriteByte(Byte b) { _stream.WriteByte(b);}\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BitmDecoder.h",
    "content": "﻿// BitmDecoder.h -- the Most Significant Bit of byte is First\n\n#ifndef ZIP7_INC_BITM_DECODER_H\n#define ZIP7_INC_BITM_DECODER_H\n\n#include \"../IStream.h\"\n\nnamespace NBitm {\n\nconst unsigned kNumBigValueBits = 8 * 4;\nconst unsigned kNumValueBytes = 3;\nconst unsigned kNumValueBits = 8 * kNumValueBytes;\n\nconst UInt32 kMask = (1 << kNumValueBits) - 1;\n\n// _bitPos - the number of free bits (high bits in _value)\n// (kNumBigValueBits - _bitPos) = (32 - _bitPos) == the number of ready to read bits (low bits of _value)\n\ntemplate<class TInByte>\nclass CDecoder\n{\n  unsigned _bitPos;\n  UInt32 _value;\n  TInByte _stream;\npublic:\n  bool Create(UInt32 bufSize) { return _stream.Create(bufSize); }\n  void SetStream(ISequentialInStream *inStream) { _stream.SetStream(inStream);}\n\n  void Init()\n  {\n    _stream.Init();\n    _bitPos = kNumBigValueBits;\n    _value = 0;\n    Normalize();\n  }\n  \n  UInt64 GetStreamSize() const { return _stream.GetStreamSize(); }\n  UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); }\n\n  bool ExtraBitsWereRead() const\n  {\n    return (_stream.NumExtraBytes > 4 || kNumBigValueBits - _bitPos < (_stream.NumExtraBytes << 3));\n  }\n\n  bool ExtraBitsWereRead_Fast() const\n  {\n    return (_stream.NumExtraBytes > 4);\n  }\n  \n  Z7_FORCE_INLINE\n  void Normalize()\n  {\n    for (; _bitPos >= 8; _bitPos -= 8)\n      _value = (_value << 8) | _stream.ReadByte();\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue(unsigned numBits) const\n  {\n    // return (_value << _bitPos) >> (kNumBigValueBits - numBits);\n    return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits);\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue_InHigh32bits() const\n  {\n    return this->_value << this->_bitPos;\n  }\n\n  Z7_FORCE_INLINE\n  void MovePos(unsigned numBits)\n  {\n    _bitPos += numBits;\n    Normalize();\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 ReadBits(unsigned numBits)\n  {\n    UInt32 res = GetValue(numBits);\n    MovePos(numBits);\n    return res;\n  }\n\n  /*\n  unsigned ReadBit()\n  {\n    UInt32 res = ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - 1);\n    if (++_bitPos >= 8)\n    {\n      _value = (_value << 8) | _stream.ReadByte();\n      _bitPos -= 8;\n    }\n    return (unsigned)res;\n  }\n  */\n\n  void AlignToByte() { MovePos((kNumBigValueBits - _bitPos) & 7); }\n\n  Z7_FORCE_INLINE\n  UInt32 ReadAlignBits() { return ReadBits((kNumBigValueBits - _bitPos) & 7); }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BitmEncoder.h",
    "content": "﻿// BitmEncoder.h -- the Most Significant Bit of byte is First\n\n#ifndef ZIP7_INC_BITM_ENCODER_H\n#define ZIP7_INC_BITM_ENCODER_H\n\n#include \"../IStream.h\"\n\ntemplate<class TOutByte>\nclass CBitmEncoder\n{\n  unsigned _bitPos;  // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte\n  unsigned _curByte; // low (_bitPos) bits are zeros\n                     // high (8 - _bitPos) bits are filled\n  TOutByte _stream;\npublic:\n  bool Create(UInt32 bufferSize) { return _stream.Create(bufferSize); }\n  void SetStream(ISequentialOutStream *outStream) { _stream.SetStream(outStream);}\n  UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() + ((8 - _bitPos + 7) >> 3); }\n  void Init()\n  {\n    _stream.Init();\n    _bitPos = 8;\n    _curByte = 0;\n  }\n  HRESULT Flush()\n  {\n    if (_bitPos < 8)\n    {\n      _stream.WriteByte((Byte)_curByte);\n      _bitPos = 8;\n      _curByte = 0;\n    }\n    return _stream.Flush();\n  }\n\n  // required condition: (value >> numBits) == 0\n  // numBits == 0 is allowed\n  void WriteBits(UInt32 value, unsigned numBits)\n  {\n    do\n    {\n      unsigned bp = _bitPos;\n      unsigned curByte = _curByte;\n      if (numBits < bp)\n      {\n        bp -= numBits;\n        _curByte = curByte | (value << bp);\n        _bitPos = bp;\n        return;\n      }\n      numBits -= bp;\n      const UInt32 hi = (value >> numBits);\n      value -= (hi << numBits);\n      _stream.WriteByte((Byte)(curByte | hi));\n      _bitPos = 8;\n      _curByte = 0;\n    }\n    while (numBits);\n  }\n  void WriteByte(unsigned b)\n  {\n    const unsigned bp = _bitPos;\n    const unsigned a = _curByte | (b >> (8 - bp));\n    _curByte = b << bp;\n   _stream.WriteByte((Byte)a);\n  }\n\n  void WriteBytes(const Byte *data, size_t num)\n  {\n    const unsigned bp = _bitPos;\n#if 1 // 1 for optional speed-optimized code branch\n    if (bp == 8)\n    {\n      _stream.WriteBytes(data, num);\n      return;\n    }\n#endif\n    unsigned c = _curByte;\n    const unsigned bp_rev = 8 - bp;\n    for (size_t i = 0; i < num; i++)\n    {\n      const unsigned b = data[i];\n      _stream.WriteByte((Byte)(c | (b >> bp_rev)));\n      c = b << bp;\n    }\n    _curByte = c;\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BranchMisc.cpp",
    "content": "﻿// BranchMisc.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"BranchMisc.h\"\n\nnamespace NCompress {\nnamespace NBranch {\n\nZ7_COM7F_IMF(CCoder::Init())\n{\n  _pc = 0;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF2(UInt32, CCoder::Filter(Byte *data, UInt32 size))\n{\n  const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data);\n  _pc += processed;\n  return processed;\n}\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nZ7_COM7F_IMF(CEncoder::Init())\n{\n  _pc = _pc_Init;\n  return S_OK;\n}\n\nZ7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size))\n{\n  const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data);\n  _pc += processed;\n  return processed;\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\n{\n  UInt32 pc = 0;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPID propID = propIDs[i];\n    if (propID == NCoderPropID::kDefaultProp ||\n        propID == NCoderPropID::kBranchOffset)\n    {\n      const PROPVARIANT &prop = props[i];\n      if (prop.vt != VT_UI4)\n        return E_INVALIDARG;\n      pc = prop.ulVal;\n      if (pc & _alignment)\n        return E_INVALIDARG;\n    }\n  }\n  _pc_Init = pc;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))\n{\n  if (_pc_Init == 0)\n    return S_OK;\n  UInt32 buf32[1];\n  SetUi32(buf32, _pc_Init)\n  return WriteStream(outStream, buf32, 4);\n}\n\n#endif\n\n\nZ7_COM7F_IMF(CDecoder::Init())\n{\n  _pc = _pc_Init;\n  return S_OK;\n}\n\nZ7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))\n{\n  const UInt32 processed = (UInt32)(size_t)(BraFunc(data, size, _pc) - data);\n  _pc += processed;\n  return processed;\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size))\n{\n  UInt32 val = 0;\n  if (size != 0)\n  {\n    if (size != 4)\n      return E_NOTIMPL;\n    val = GetUi32(props);\n    if (val & _alignment)\n      return E_NOTIMPL;\n  }\n  _pc_Init = val;\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BranchMisc.h",
    "content": "﻿// BranchMisc.h\n\n#ifndef ZIP7_INC_COMPRESS_BRANCH_MISC_H\n#define ZIP7_INC_COMPRESS_BRANCH_MISC_H\n#include \"../../../C/Bra.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NBranch {\n\nZ7_CLASS_IMP_COM_1(\n  CCoder\n  , ICompressFilter\n)\n  UInt32 _pc;\n  z7_Func_BranchConv BraFunc;\npublic:\n  CCoder(z7_Func_BranchConv bra): _pc(0), BraFunc(bra) {}\n};\n\n#ifndef Z7_EXTRACT_ONLY\n\nZ7_CLASS_IMP_COM_3(\n  CEncoder\n  , ICompressFilter\n  , ICompressSetCoderProperties\n  , ICompressWriteCoderProperties\n)\n  UInt32 _pc;\n  UInt32 _pc_Init;\n  UInt32 _alignment;\n  z7_Func_BranchConv BraFunc;\npublic:\n  CEncoder(z7_Func_BranchConv bra, UInt32 alignment):\n      _pc(0), _pc_Init(0), _alignment(alignment), BraFunc(bra) {}\n};\n\n#endif\n\nZ7_CLASS_IMP_COM_2(\n  CDecoder\n  , ICompressFilter\n  , ICompressSetDecoderProperties2\n)\n  UInt32 _pc;\n  UInt32 _pc_Init;\n  UInt32 _alignment;\n  z7_Func_BranchConv BraFunc;\npublic:\n  CDecoder(z7_Func_BranchConv bra, UInt32 alignment):\n      _pc(0), _pc_Init(0), _alignment(alignment), BraFunc(bra) {}\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/BranchRegister.cpp",
    "content": "﻿// BranchRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"BranchMisc.h\"\n\nnamespace NCompress {\nnamespace NBranch {\n\n#ifdef Z7_EXTRACT_ONLY\n#define GET_CREATE_FUNC(x) NULL\n#define CREATE_BRA_E(n)\n#else\n#define GET_CREATE_FUNC(x) x\n#define CREATE_BRA_E(n) \\\n    REGISTER_FILTER_CREATE(CreateBra_Encoder_ ## n, CCoder(Z7_BRANCH_CONV_ENC_2(n)))\n#endif\n\n#define CREATE_BRA(n) \\\n    REGISTER_FILTER_CREATE(CreateBra_Decoder_ ## n, CCoder(Z7_BRANCH_CONV_DEC_2(n))) \\\n    CREATE_BRA_E(n)\n\nCREATE_BRA(BranchConv_PPC)\nCREATE_BRA(BranchConv_IA64)\nCREATE_BRA(BranchConv_ARM)\nCREATE_BRA(BranchConv_ARMT)\nCREATE_BRA(BranchConv_SPARC)\n\n#define METHOD_ITEM(n, id, name) \\\n    REGISTER_FILTER_ITEM( \\\n      CreateBra_Decoder_ ## n, GET_CREATE_FUNC( \\\n      CreateBra_Encoder_ ## n), \\\n      0x3030000 + id, name)\n\nREGISTER_CODECS_VAR\n{\n  METHOD_ITEM(BranchConv_PPC,   0x205, \"PPC\"),\n  METHOD_ITEM(BranchConv_IA64,  0x401, \"IA64\"),\n  METHOD_ITEM(BranchConv_ARM,   0x501, \"ARM\"),\n  METHOD_ITEM(BranchConv_ARMT,  0x701, \"ARMT\"),\n  METHOD_ITEM(BranchConv_SPARC, 0x805, \"SPARC\")\n};\n\nREGISTER_CODECS(Branch)\n\n\n#define REGISTER_FILTER_E_BRANCH(id, n, name, alignment) \\\n    REGISTER_FILTER_E(n, \\\n      CDecoder(Z7_BRANCH_CONV_DEC(n), alignment), \\\n      CEncoder(Z7_BRANCH_CONV_ENC(n), alignment), \\\n      id, name)\n\nREGISTER_FILTER_E_BRANCH(0xa, ARM64, \"ARM64\", 3)\nREGISTER_FILTER_E_BRANCH(0xb, RISCV, \"RISCV\", 1)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ByteSwap.cpp",
    "content": "﻿// ByteSwap.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/SwapBytes.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\nnamespace NCompress {\nnamespace NByteSwap {\n\nZ7_CLASS_IMP_COM_1(CByteSwap2, ICompressFilter) };\nZ7_CLASS_IMP_COM_1(CByteSwap4, ICompressFilter) };\n\nZ7_COM7F_IMF(CByteSwap2::Init()) { return S_OK; }\n\nZ7_COM7F_IMF2(UInt32, CByteSwap2::Filter(Byte *data, UInt32 size))\n{\n  const UInt32 kMask = 2 - 1;\n  size &= ~kMask;\n  /*\n  if ((unsigned)(ptrdiff_t)data & kMask)\n  {\n    if (size == 0)\n      return 0;\n    const Byte *end = data + (size_t)size;\n    do\n    {\n      const Byte b0 = data[0];\n      data[0] = data[1];\n      data[1] = b0;\n      data += kStep;\n    }\n    while (data != end);\n  }\n  else\n  */\n  z7_SwapBytes2((UInt16 *)(void *)data, size >> 1);\n  return size;\n}\n\n\nZ7_COM7F_IMF(CByteSwap4::Init()) { return S_OK; }\n\nZ7_COM7F_IMF2(UInt32, CByteSwap4::Filter(Byte *data, UInt32 size))\n{\n  const UInt32 kMask = 4 - 1;\n  size &= ~kMask;\n  /*\n  if ((unsigned)(ptrdiff_t)data & kMask)\n  {\n    if (size == 0)\n      return 0;\n    const Byte *end = data + (size_t)size;\n    do\n    {\n      const Byte b0 = data[0];\n      const Byte b1 = data[1];\n      data[0] = data[3];\n      data[1] = data[2];\n      data[2] = b1;\n      data[3] = b0;\n      data += kStep;\n    }\n    while (data != end);\n  }\n  else\n  */\n  z7_SwapBytes4((UInt32 *)(void *)data, size >> 2);\n  return size;\n}\n\nstatic struct C_SwapBytesPrepare { C_SwapBytesPrepare() { z7_SwapBytesPrepare(); } } g_SwapBytesPrepare;\n\n\nREGISTER_FILTER_CREATE(CreateFilter2, CByteSwap2())\nREGISTER_FILTER_CREATE(CreateFilter4, CByteSwap4())\n\nREGISTER_CODECS_VAR\n{\n  REGISTER_FILTER_ITEM(CreateFilter2, CreateFilter2, 0x20302, \"Swap2\"),\n  REGISTER_FILTER_ITEM(CreateFilter4, CreateFilter4, 0x20304, \"Swap4\"),\n};\n\nREGISTER_CODECS(ByteSwap)\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/CodecExports.cpp",
    "content": "﻿// CodecExports.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/7zVersion.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyCom.h\"\n\n#include \"../../Windows/Defs.h\"\n#include \"../../Windows/PropVariant.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\nextern unsigned g_NumCodecs;\nextern const CCodecInfo *g_Codecs[];\n\nextern unsigned g_NumHashers;\nextern const CHasherInfo *g_Hashers[];\n\nstatic void SetPropFromAscii(const char *s, PROPVARIANT *prop) throw()\n{\n  const UINT len = (UINT)strlen(s);\n  BSTR dest = ::SysAllocStringLen(NULL, len);\n  if (dest)\n  {\n    for (UINT i = 0; i <= len; i++)\n      dest[i] = (Byte)s[i];\n    prop->bstrVal = dest;\n    prop->vt = VT_BSTR;\n  }\n}\n\nstatic inline HRESULT SetPropGUID(const GUID &guid, PROPVARIANT *value) throw()\n{\n  if ((value->bstrVal = ::SysAllocStringByteLen((const char *)&guid, sizeof(guid))) != NULL)\n    value->vt = VT_BSTR;\n  return S_OK;\n}\n\nstatic HRESULT MethodToClassID(UInt16 typeId, CMethodId id, PROPVARIANT *value) throw()\n{\n  GUID clsId;\n  clsId.Data1 = k_7zip_GUID_Data1;\n  clsId.Data2 = k_7zip_GUID_Data2;\n  clsId.Data3 = typeId;\n  SetUi64(clsId.Data4, id)\n  return SetPropGUID(clsId, value);\n}\n\nstatic HRESULT FindCodecClassId(const GUID *clsid, bool isCoder2, bool isFilter, bool &encode, int &index) throw()\n{\n  index = -1;\n  if (clsid->Data1 != k_7zip_GUID_Data1 ||\n      clsid->Data2 != k_7zip_GUID_Data2)\n    return S_OK;\n  \n  encode = true;\n  \n       if (clsid->Data3 == k_7zip_GUID_Data3_Decoder) encode = false;\n  else if (clsid->Data3 != k_7zip_GUID_Data3_Encoder) return S_OK;\n  \n  const UInt64 id = GetUi64(clsid->Data4);\n  \n  for (unsigned i = 0; i < g_NumCodecs; i++)\n  {\n    const CCodecInfo &codec = *g_Codecs[i];\n    \n    if (id != codec.Id\n        || (encode ? !codec.CreateEncoder : !codec.CreateDecoder)\n        || (isFilter ? !codec.IsFilter : codec.IsFilter))\n      continue;\n\n    if (codec.NumStreams == 1 ? isCoder2 : !isCoder2)\n      return E_NOINTERFACE;\n    \n    index = (int)i;\n    return S_OK;\n  }\n  \n  return S_OK;\n}\n\n/*\n#ifdef __GNUC__\n#ifndef __clang__\n#pragma GCC diagnostic ignored \"-Wduplicated-branches\"\n#endif\n#endif\n*/\n\nstatic HRESULT CreateCoderMain(unsigned index, bool encode, void **coder)\n{\n  COM_TRY_BEGIN\n  \n  const CCodecInfo &codec = *g_Codecs[index];\n  \n  void *c;\n  if (encode)\n    c = codec.CreateEncoder();\n  else\n    c = codec.CreateDecoder();\n  \n  if (c)\n  {\n    IUnknown *unk;\n    unk = (IUnknown *)c;\n    /*\n    if (codec.IsFilter)\n      unk = (IUnknown *)(ICompressFilter *)c;\n    else if (codec.NumStreams != 1)\n      unk = (IUnknown *)(ICompressCoder2 *)c;\n    else\n      unk = (IUnknown *)(ICompressCoder *)c;\n    */\n    unk->AddRef();\n    *coder = c;\n  }\n  return S_OK;\n  \n  COM_TRY_END\n}\n\nstatic HRESULT CreateCoder2(bool encode, UInt32 index, const GUID *iid, void **outObject)\n{\n  *outObject = NULL;\n\n  const CCodecInfo &codec = *g_Codecs[index];\n\n  if (encode ? !codec.CreateEncoder : !codec.CreateDecoder)\n    return CLASS_E_CLASSNOTAVAILABLE;\n\n  if (codec.IsFilter)\n  {\n    if (*iid != IID_ICompressFilter) return E_NOINTERFACE;\n  }\n  else if (codec.NumStreams != 1)\n  {\n    if (*iid != IID_ICompressCoder2) return E_NOINTERFACE;\n  }\n  else\n  {\n    if (*iid != IID_ICompressCoder) return E_NOINTERFACE;\n  }\n  \n  return CreateCoderMain(index, encode, outObject);\n}\n\n\nSTDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);\nSTDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject)\n{\n  return CreateCoder2(false, index, iid, outObject);\n}\n\n\nSTDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);\nSTDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject)\n{\n  return CreateCoder2(true, index, iid, outObject);\n}\n\n\nSTDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject);\nSTDAPI CreateCoder(const GUID *clsid, const GUID *iid, void **outObject)\n{\n  *outObject = NULL;\n\n  bool isFilter = false;\n  bool isCoder2 = false;\n  const bool isCoder = (*iid == IID_ICompressCoder) != 0;\n  if (!isCoder)\n  {\n    isFilter = (*iid == IID_ICompressFilter) != 0;\n    if (!isFilter)\n    {\n      isCoder2 = (*iid == IID_ICompressCoder2) != 0;\n      if (!isCoder2)\n        return E_NOINTERFACE;\n    }\n  }\n  \n  bool encode;\n  int codecIndex;\n  const HRESULT res = FindCodecClassId(clsid, isCoder2, isFilter, encode, codecIndex);\n  if (res != S_OK)\n    return res;\n  if (codecIndex < 0)\n    return CLASS_E_CLASSNOTAVAILABLE;\n\n  return CreateCoderMain((unsigned)codecIndex, encode, outObject);\n}\n \n\nSTDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);\nSTDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)\n{\n  ::VariantClear((VARIANTARG *)value);\n  const CCodecInfo &codec = *g_Codecs[codecIndex];\n  switch (propID)\n  {\n    case NMethodPropID::kID:\n      value->uhVal.QuadPart = (UInt64)codec.Id;\n      value->vt = VT_UI8;\n      break;\n    case NMethodPropID::kName:\n      SetPropFromAscii(codec.Name, value);\n      break;\n    case NMethodPropID::kDecoder:\n      if (codec.CreateDecoder)\n        return MethodToClassID(k_7zip_GUID_Data3_Decoder, codec.Id, value);\n      break;\n    case NMethodPropID::kEncoder:\n      if (codec.CreateEncoder)\n        return MethodToClassID(k_7zip_GUID_Data3_Encoder, codec.Id, value);\n      break;\n    case NMethodPropID::kDecoderIsAssigned:\n        value->vt = VT_BOOL;\n        value->boolVal = BoolToVARIANT_BOOL(codec.CreateDecoder != NULL);\n      break;\n    case NMethodPropID::kEncoderIsAssigned:\n        value->vt = VT_BOOL;\n        value->boolVal = BoolToVARIANT_BOOL(codec.CreateEncoder != NULL);\n      break;\n    case NMethodPropID::kPackStreams:\n      if (codec.NumStreams != 1)\n      {\n        value->vt = VT_UI4;\n        value->ulVal = (ULONG)codec.NumStreams;\n      }\n      break;\n    case NMethodPropID::kIsFilter:\n      {\n        value->vt = VT_BOOL;\n        value->boolVal = BoolToVARIANT_BOOL(codec.IsFilter);\n      }\n      break;\n    /*\n    case NMethodPropID::kDecoderFlags:\n      {\n        value->vt = VT_UI4;\n        value->ulVal = (ULONG)codec.DecoderFlags;\n      }\n      break;\n    case NMethodPropID::kEncoderFlags:\n      {\n        value->vt = VT_UI4;\n        value->ulVal = (ULONG)codec.EncoderFlags;\n      }\n      break;\n    */\n  }\n  return S_OK;\n}\n\n\nSTDAPI GetNumberOfMethods(UInt32 *numCodecs);\nSTDAPI GetNumberOfMethods(UInt32 *numCodecs)\n{\n  *numCodecs = g_NumCodecs;\n  return S_OK;\n}\n\n\n// ---------- Hashers ----------\n\nstatic int FindHasherClassId(const GUID *clsid) throw()\n{\n  if (clsid->Data1 != k_7zip_GUID_Data1 ||\n      clsid->Data2 != k_7zip_GUID_Data2 ||\n      clsid->Data3 != k_7zip_GUID_Data3_Hasher)\n    return -1;\n  const UInt64 id = GetUi64(clsid->Data4);\n  for (unsigned i = 0; i < g_NumCodecs; i++)\n    if (id == g_Hashers[i]->Id)\n      return (int)i;\n  return -1;\n}\n\nstatic HRESULT CreateHasher2(UInt32 index, IHasher **hasher)\n{\n  COM_TRY_BEGIN\n  *hasher = g_Hashers[index]->CreateHasher();\n  if (*hasher)\n    (*hasher)->AddRef();\n  return S_OK;\n  COM_TRY_END\n}\n\nSTDAPI CreateHasher(const GUID *clsid, IHasher **outObject);\nSTDAPI CreateHasher(const GUID *clsid, IHasher **outObject)\n{\n  COM_TRY_BEGIN\n  *outObject = NULL;\n  const int index = FindHasherClassId(clsid);\n  if (index < 0)\n    return CLASS_E_CLASSNOTAVAILABLE;\n  return CreateHasher2((UInt32)(unsigned)index, outObject);\n  COM_TRY_END\n}\n\nSTDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);\nSTDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value)\n{\n  ::VariantClear((VARIANTARG *)value);\n  const CHasherInfo &codec = *g_Hashers[codecIndex];\n  switch (propID)\n  {\n    case NMethodPropID::kID:\n      value->uhVal.QuadPart = (UInt64)codec.Id;\n      value->vt = VT_UI8;\n      break;\n    case NMethodPropID::kName:\n      SetPropFromAscii(codec.Name, value);\n      break;\n    case NMethodPropID::kEncoder:\n      if (codec.CreateHasher)\n        return MethodToClassID(k_7zip_GUID_Data3_Hasher, codec.Id, value);\n      break;\n    case NMethodPropID::kDigestSize:\n      value->ulVal = (ULONG)codec.DigestSize;\n      value->vt = VT_UI4;\n      break;\n  }\n  return S_OK;\n}\n\nZ7_CLASS_IMP_COM_1(CHashers, IHashers) };\n\nSTDAPI GetHashers(IHashers **hashers);\nSTDAPI GetHashers(IHashers **hashers)\n{\n  COM_TRY_BEGIN\n  *hashers = new CHashers;\n  if (*hashers)\n    (*hashers)->AddRef();\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF2(UInt32, CHashers::GetNumHashers())\n{\n  return g_NumHashers;\n}\n\nZ7_COM7F_IMF(CHashers::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  return ::GetHasherProp(index, propID, value);\n}\n\nZ7_COM7F_IMF(CHashers::CreateHasher(UInt32 index, IHasher **hasher))\n{\n  return ::CreateHasher2(index, hasher);\n}\n\n\nSTDAPI GetModuleProp(PROPID propID, PROPVARIANT *value);\nSTDAPI GetModuleProp(PROPID propID, PROPVARIANT *value)\n{\n  ::VariantClear((VARIANTARG *)value);\n  switch (propID)\n  {\n    case NModulePropID::kInterfaceType:\n    {\n      NWindows::NCOM::PropVarEm_Set_UInt32(value, NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule);\n      break;\n    }\n    case NModulePropID::kVersion:\n    {\n      NWindows::NCOM::PropVarEm_Set_UInt32(value, (MY_VER_MAJOR << 16) | MY_VER_MINOR);\n      break;\n    }\n  }\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/CopyCoder.cpp",
    "content": "﻿// Compress/CopyCoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"CopyCoder.h\"\n\nnamespace NCompress {\n\nstatic const UInt32 kBufSize = 1 << 17;\n\nCCopyCoder::~CCopyCoder()\n{\n  ::MidFree(_buf);\n}\n\nZ7_COM7F_IMF(CCopyCoder::SetFinishMode(UInt32 /* finishMode */))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CCopyCoder::Code(ISequentialInStream *inStream,\n    ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 *outSize,\n    ICompressProgressInfo *progress))\n{\n  if (!_buf)\n  {\n    _buf = (Byte *)::MidAlloc(kBufSize);\n    if (!_buf)\n      return E_OUTOFMEMORY;\n  }\n\n  TotalSize = 0;\n  \n  for (;;)\n  {\n    UInt32 size = kBufSize;\n    if (outSize)\n    {\n      const UInt64 rem = *outSize - TotalSize;\n      if (size > rem)\n      {\n        size = (UInt32)rem;\n        if (size == 0)\n        {\n          /* if we enable the following check,\n             we will make one call of Read(_buf, 0) for empty stream */\n          // if (TotalSize != 0)\n          return S_OK;\n        }\n      }\n    }\n    \n    HRESULT readRes;\n    {\n      UInt32 pos = 0;\n      do\n      {\n        const UInt32 curSize = size - pos;\n        UInt32 processed = 0;\n        readRes = inStream->Read(_buf + pos, curSize, &processed);\n        if (processed > curSize)\n          return E_FAIL; // internal code failure\n        pos += processed;\n        if (readRes != S_OK || processed == 0)\n          break;\n      }\n      while (pos < kBufSize);\n      size = pos;\n    }\n\n    if (size == 0)\n      return readRes;\n\n    if (outStream)\n    {\n      UInt32 pos = 0;\n      do\n      {\n        const UInt32 curSize = size - pos;\n        UInt32 processed = 0;\n        const HRESULT res = outStream->Write(_buf + pos, curSize, &processed);\n        if (processed > curSize)\n          return E_FAIL; // internal code failure\n        pos += processed;\n        TotalSize += processed;\n        RINOK(res)\n        if (processed == 0)\n          return E_FAIL;\n      }\n      while (pos < size);\n    }\n    else\n      TotalSize += size;\n\n    RINOK(readRes)\n\n    if (size != kBufSize)\n      return S_OK;\n\n    if (progress && (TotalSize & (((UInt32)1 << 22) - 1)) == 0)\n    {\n      RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize))\n    }\n  }\n}\n\nZ7_COM7F_IMF(CCopyCoder::SetInStream(ISequentialInStream *inStream))\n{\n  _inStream = inStream;\n  TotalSize = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CCopyCoder::ReleaseInStream())\n{\n  _inStream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  UInt32 realProcessedSize = 0;\n  HRESULT res = _inStream->Read(data, size, &realProcessedSize);\n  TotalSize += realProcessedSize;\n  if (processedSize)\n    *processedSize = realProcessedSize;\n  return res;\n}\n\nZ7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = TotalSize;\n  return S_OK;\n}\n\nHRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)\n{\n  CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;\n  return copyCoder->Code(inStream, outStream, NULL, NULL, progress);\n}\n\nHRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)\n{\n  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;\n  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\n  RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress))\n  return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;\n}\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/CopyCoder.h",
    "content": "﻿// Compress/CopyCoder.h\n\n#ifndef ZIP7_INC_COMPRESS_COPY_CODER_H\n#define ZIP7_INC_COMPRESS_COPY_CODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\n\nZ7_CLASS_IMP_COM_5(\n  CCopyCoder\n  , ICompressCoder\n  , ICompressSetInStream\n  , ISequentialInStream\n  , ICompressSetFinishMode\n  , ICompressGetInStreamProcessedSize\n)\n  Byte *_buf;\n  CMyComPtr<ISequentialInStream> _inStream;\npublic:\n  UInt64 TotalSize;\n  \n  CCopyCoder(): _buf(NULL), TotalSize(0) {}\n  ~CCopyCoder();\n};\n\nHRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\nHRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress);\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/CopyRegister.cpp",
    "content": "﻿// CopyRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"CopyCoder.h\"\n\nnamespace NCompress {\n\nREGISTER_CODEC_CREATE(CreateCodec, CCopyCoder())\n\nREGISTER_CODEC_2(Copy, CreateCodec, CreateCodec, 0, \"Copy\")\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Deflate64Register.cpp",
    "content": "﻿// Deflate64Register.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"DeflateDecoder.h\"\n#if !defined(Z7_EXTRACT_ONLY) && !defined(Z7_DEFLATE_EXTRACT_ONLY)\n#include \"DeflateEncoder.h\"\n#endif\n\nnamespace NCompress {\nnamespace NDeflate {\n\nREGISTER_CODEC_CREATE(CreateDec, NDecoder::CCOMCoder64())\n\n#if !defined(Z7_EXTRACT_ONLY) && !defined(Z7_DEFLATE_EXTRACT_ONLY)\nREGISTER_CODEC_CREATE(CreateEnc, NEncoder::CCOMCoder64())\n#else\n#define CreateEnc NULL\n#endif\n\nREGISTER_CODEC_2(Deflate64, CreateDec, CreateEnc, 0x40109, \"Deflate64\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/DeflateConst.h",
    "content": "﻿// DeflateConst.h\n\n#ifndef ZIP7_INC_DEFLATE_CONST_H\n#define ZIP7_INC_DEFLATE_CONST_H\n\nnamespace NCompress {\nnamespace NDeflate {\n\nconst unsigned kNumHuffmanBits = 15;\n\nconst UInt32 kHistorySize32 = (1 << 15);\nconst UInt32 kHistorySize64 = (1 << 16);\n\nconst unsigned kDistTableSize32 = 30;\nconst unsigned kDistTableSize64 = 32;\n  \nconst unsigned kNumLenSymbols32 = 256;\nconst unsigned kNumLenSymbols64 = 255; // don't change it. It must be <= 255.\nconst unsigned kNumLenSymbolsMax = kNumLenSymbols32;\n  \nconst unsigned kNumLenSlots = 29;\n\nconst unsigned kFixedDistTableSize = 32;\nconst unsigned kFixedLenTableSize = 31;\n\nconst unsigned kSymbolEndOfBlock = 0x100;\nconst unsigned kSymbolMatch = kSymbolEndOfBlock + 1;\n\nconst unsigned kMainTableSize = kSymbolMatch + kNumLenSlots;\nconst unsigned kFixedMainTableSize = kSymbolMatch + kFixedLenTableSize;\n\nconst unsigned kLevelTableSize = 19;\n\nconst unsigned kTableDirectLevels = 16;\nconst unsigned kTableLevelRepNumber = kTableDirectLevels;\nconst unsigned kTableLevel0Number = kTableLevelRepNumber + 1;\nconst unsigned kTableLevel0Number2 = kTableLevel0Number + 1;\n\nconst unsigned kLevelMask = 0xF;\n\nconst Byte kLenStart32[kFixedLenTableSize] =\n  {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 255, 0, 0};\nconst Byte kLenStart64[kFixedLenTableSize] =\n  {0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224, 0, 0, 0};\n\nconst Byte kLenDirectBits32[kFixedLenTableSize] =\n  {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,  4,  5,  5,  5,  5, 0, 0, 0};\nconst Byte kLenDirectBits64[kFixedLenTableSize] =\n  {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,  4,  5,  5,  5,  5, 16, 0, 0};\n\nconst UInt32 kDistStart[kDistTableSize64] =\n  {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,\n  1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152};\nconst Byte kDistDirectBits[kDistTableSize64] =\n  {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14};\n\nconst Byte kLevelDirectBits[3] = {2, 3, 7};\n\nconst Byte kCodeLengthAlphabetOrder[kLevelTableSize] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\nconst unsigned kMatchMinLen = 3;\nconst unsigned kMatchMaxLen32 = kNumLenSymbols32 + kMatchMinLen - 1; // 256 + 2\nconst unsigned kMatchMaxLen64 = kNumLenSymbols64 + kMatchMinLen - 1; // 255 + 2\nconst unsigned kMatchMaxLen = kMatchMaxLen32;\n\nconst unsigned kFinalBlockFieldSize = 1;\n\nnamespace NFinalBlockField\n{\n  enum\n  {\n    kNotFinalBlock = 0,\n    kFinalBlock = 1\n  };\n}\n\nconst unsigned kBlockTypeFieldSize = 2;\n\nnamespace NBlockType\n{\n  enum\n  {\n    kStored = 0,\n    kFixedHuffman = 1,\n    kDynamicHuffman = 2\n  };\n}\n\nconst unsigned kNumLenCodesFieldSize = 5;\nconst unsigned kNumDistCodesFieldSize = 5;\nconst unsigned kNumLevelCodesFieldSize = 4;\n\nconst unsigned kNumLitLenCodesMin = 257;\nconst unsigned kNumDistCodesMin = 1;\nconst unsigned kNumLevelCodesMin = 4;\n\nconst unsigned kLevelFieldSize = 3;\n\nconst unsigned kStoredBlockLengthFieldSize = 16;\n\nstruct CLevels\n{\n  Byte litLenLevels[kFixedMainTableSize];\n  Byte distLevels[kFixedDistTableSize];\n\n  void SubClear()\n  {\n    unsigned i;\n    for (i = kNumLitLenCodesMin; i < kFixedMainTableSize; i++)\n      litLenLevels[i] = 0;\n    for (i = 0; i < kFixedDistTableSize; i++)\n      distLevels[i] = 0;\n  }\n\n  void SetFixedLevels()\n  {\n    unsigned i = 0;\n    \n    for (; i < 144; i++) litLenLevels[i] = 8;\n    for (; i < 256; i++) litLenLevels[i] = 9;\n    for (; i < 280; i++) litLenLevels[i] = 7;\n    for (; i < 288; i++) litLenLevels[i] = 8;\n    \n    for (i = 0; i < kFixedDistTableSize; i++)  // test it: InfoZip only uses kDistTableSize\n      distLevels[i] = 5;\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/DeflateDecoder.cpp",
    "content": "﻿// DeflateDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"DeflateDecoder.h\"\n\nnamespace NCompress {\nnamespace NDeflate {\nnamespace NDecoder {\n\nCCoder::CCoder(bool deflate64Mode):\n    _deflateNSIS(false),\n    _deflate64Mode(deflate64Mode),\n    _keepHistory(false),\n    _needFinishInput(false),\n    _needInitInStream(true),\n    _outSizeDefined(false),\n    _outStartPos(0)\n    {}\n\nUInt32 CCoder::ReadBits(unsigned numBits)\n{\n  return m_InBitStream.ReadBits(numBits);\n}\n\nByte CCoder::ReadAlignedByte()\n{\n  return m_InBitStream.ReadAlignedByte();\n}\n\nbool CCoder::DecodeLevels(Byte *levels, unsigned numSymbols)\n{\n  unsigned i = 0;\n  \n  do\n  {\n    unsigned sym = m_LevelDecoder.Decode(&m_InBitStream);\n    if (sym < kTableDirectLevels)\n      levels[i++] = (Byte)sym;\n    else\n    {\n      if (sym >= kLevelTableSize)\n        return false;\n      \n      unsigned num;\n      unsigned numBits;\n      Byte symbol;\n      \n      if (sym == kTableLevelRepNumber)\n      {\n        if (i == 0)\n          return false;\n        numBits = 2;\n        num = 0;\n        symbol = levels[(size_t)i - 1];\n      }\n      else\n      {\n        sym -= kTableLevel0Number;\n        sym <<= 2;\n        numBits = 3 + (unsigned)sym;\n        num = ((unsigned)sym << 1);\n        symbol = 0;\n      }\n      \n      num += i + 3 + ReadBits(numBits);\n      if (num > numSymbols)\n        return false;\n      do\n        levels[i++] = symbol;\n      while (i < num);\n    }\n  }\n  while (i < numSymbols);\n  \n  return true;\n}\n\n#define RIF(x) { if (!(x)) return false; }\n\nbool CCoder::ReadTables(void)\n{\n  m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);\n  if (m_InBitStream.ExtraBitsWereRead())\n    return false;\n  const UInt32 blockType = ReadBits(kBlockTypeFieldSize);\n  if (blockType > NBlockType::kDynamicHuffman)\n    return false;\n  if (m_InBitStream.ExtraBitsWereRead())\n    return false;\n\n  if (blockType == NBlockType::kStored)\n  {\n    m_StoredMode = true;\n    m_InBitStream.AlignToByte();\n    m_StoredBlockSize = ReadAligned_UInt16(); // ReadBits(kStoredBlockLengthFieldSize)\n    if (_deflateNSIS)\n      return true;\n    return (m_StoredBlockSize == (UInt16)~ReadAligned_UInt16());\n  }\n\n  m_StoredMode = false;\n\n  CLevels levels;\n  if (blockType == NBlockType::kFixedHuffman)\n  {\n    levels.SetFixedLevels();\n    _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;\n  }\n  else\n  {\n    const unsigned numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;\n    _numDistLevels = (unsigned)ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;\n    const unsigned numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;\n\n    if (!_deflate64Mode)\n      if (_numDistLevels > kDistTableSize32)\n        return false;\n    \n    const unsigned kLevelTableSize_aligned4 = kLevelTableSize + 1;\n    Byte levelLevels[kLevelTableSize_aligned4];\n    memset (levelLevels, 0, sizeof(levelLevels));\n    unsigned i = 0;\n    do\n      levelLevels[kCodeLengthAlphabetOrder[i++]] = (Byte)ReadBits(kLevelFieldSize);\n    while (i != numLevelCodes);\n    \n    if (m_InBitStream.ExtraBitsWereRead())\n      return false;\n\n    RIF(m_LevelDecoder.Build(levelLevels, false)) // full\n    \n    Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];\n    if (!DecodeLevels(tmpLevels, numLitLenLevels + _numDistLevels))\n      return false;\n    \n    if (m_InBitStream.ExtraBitsWereRead())\n      return false;\n\n    levels.SubClear();\n    memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);\n    memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);\n  }\n  RIF(m_MainDecoder.Build(levels.litLenLevels))\n  return m_DistDecoder.Build(levels.distLevels);\n}\n\n\nHRESULT CCoder::InitInStream(bool needInit)\n{\n  if (needInit)\n  {\n    // for HDD-Windows:\n    // (1 << 15) - best for reading only prefetch\n    // (1 << 22) - best for real reading / writing\n    if (!m_InBitStream.Create(1 << 20))\n      return E_OUTOFMEMORY;\n    m_InBitStream.Init();\n    _needInitInStream = false;\n  }\n  return S_OK;\n}\n\n\nHRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit)\n{\n  if (_remainLen == kLenIdFinished)\n    return S_OK;\n  \n  if (_remainLen == kLenIdNeedInit)\n  {\n    if (!_keepHistory)\n      if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))\n        return E_OUTOFMEMORY;\n    RINOK(InitInStream(_needInitInStream))\n    m_OutWindowStream.Init(_keepHistory);\n  \n    m_FinalBlock = false;\n    _remainLen = 0;\n    _needReadTable = true;\n  }\n\n  // _remainLen >= 0\n  while (_remainLen && curSize)\n  {\n    _remainLen--;\n    const Byte b = m_OutWindowStream.GetByte(_rep0);\n    m_OutWindowStream.PutByte(b);\n    curSize--;\n  }\n\n  UInt64 inputStart = 0;\n  if (inputProgressLimit != 0)\n    inputStart = m_InBitStream.GetProcessedSize();\n\n  while (curSize || finishInputStream)\n  {\n    if (m_InBitStream.ExtraBitsWereRead())\n      return S_FALSE;\n\n    if (_needReadTable)\n    {\n      if (m_FinalBlock)\n      {\n        _remainLen = kLenIdFinished;\n        break;\n      }\n \n      if (inputProgressLimit != 0)\n        if (m_InBitStream.GetProcessedSize() - inputStart >= inputProgressLimit)\n          return S_OK;\n      \n      if (!ReadTables())\n        return S_FALSE;\n      if (m_InBitStream.ExtraBitsWereRead())\n        return S_FALSE;\n      _needReadTable = false;\n    }\n\n    if (m_StoredMode)\n    {\n      if (finishInputStream && curSize == 0 && m_StoredBlockSize != 0)\n        return S_FALSE;\n      /* NSIS version contains some bits in bitl bits buffer.\n         So we must read some first bytes via ReadAlignedByte */\n      UInt32 num = m_StoredBlockSize;\n      if (num > curSize)\n          num = curSize;\n      m_StoredBlockSize -= num;\n      curSize -= num;\n      for (; num && m_InBitStream.ThereAreDataInBitsBuffer(); num--)\n        m_OutWindowStream.PutByte(ReadAlignedByte());\n      if (num)\n      {\n#if 1\n        // fast code\n        do\n        {\n          size_t a;\n          Byte *buf = m_OutWindowStream.GetOutBuffer(a);\n          // a != 0\n          if (a > num)\n              a = num;\n          // a != 0\n          a = m_InBitStream.ReadDirectBytesPart(buf, a);\n          if (a == 0)\n            return S_FALSE;\n          m_OutWindowStream.SkipWrittenBytes(a);\n          num -= (UInt32)a;\n        }\n        while (num);\n#else\n        // slow code:\n        do\n          m_OutWindowStream.PutByte(m_InBitStream.ReadDirectByte());\n        while (--num);\n#endif\n      }\n      _needReadTable = (m_StoredBlockSize == 0);\n      continue;\n    }\n    \n    while (curSize)\n    {\n      if (m_InBitStream.ExtraBitsWereRead_Fast())\n        return S_FALSE;\n      unsigned sym;\n#if 0\n      sym = m_MainDecoder.Decode(&m_InBitStream);\n#else\n      Z7_HUFF_DECODE_CHECK(sym, &m_MainDecoder, kNumHuffmanBits, kNumTableBits_Main, &m_InBitStream, { return S_FALSE; })\n#endif\n\n      if (sym < 0x100)\n      {\n        m_OutWindowStream.PutByte((Byte)sym);\n        curSize--;\n        continue;\n      }\n      if (sym == kSymbolEndOfBlock)\n      {\n        _needReadTable = true;\n        break;\n      }\n#if 0\n      if (sym >= kMainTableSize)\n        return S_FALSE;\n#endif\n      {\n        sym -= kSymbolMatch;\n        UInt32 len;\n        {\n          unsigned numBits;\n          if (_deflate64Mode)\n          {\n            len = kLenStart64[sym];\n            numBits = kLenDirectBits64[sym];\n          }\n          else\n          {\n            len = kLenStart32[sym];\n            numBits = kLenDirectBits32[sym];\n          }\n          len += kMatchMinLen + m_InBitStream.ReadBits(numBits);\n        }\n       \n#if 0\n        sym = m_DistDecoder.Decode(&m_InBitStream);\n        if (sym >= _numDistLevels)\n          return S_FALSE;\n#else\n        Z7_HUFF_DECODE_CHECK(sym, &m_DistDecoder, kNumHuffmanBits, kNumTableBits_Dist, &m_InBitStream, { return S_FALSE; })\n#endif\n\n#if 1\n        sym = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]);\n#else\n        if (sym >= 4)\n        {\n          // sym &= 31;\n          const unsigned numDirectBits = (sym - 2) >> 1;\n          sym = (2u | (sym & 1)) << numDirectBits;\n          sym += m_InBitStream.ReadBits(numDirectBits);\n        }\n#endif\n        UInt32 locLen = len;\n        if (locLen > curSize)\n          locLen = (UInt32)curSize;\n        if (!m_OutWindowStream.CopyBlock(sym, locLen))\n          return S_FALSE;\n        curSize -= locLen;\n        len -= locLen;\n        if (len != 0)\n        {\n          _remainLen = (Int32)len;\n          _rep0 = sym;\n          break;\n        }\n      }\n    }\n    \n    if (finishInputStream && curSize == 0)\n    {\n      if (m_MainDecoder.Decode(&m_InBitStream) != kSymbolEndOfBlock)\n        return S_FALSE;\n      _needReadTable = true;\n    }\n  }\n\n  if (m_InBitStream.ExtraBitsWereRead())\n    return S_FALSE;\n\n  return S_OK;\n}\n\n\n#ifdef Z7_NO_EXCEPTIONS\n\n#define DEFLATE_TRY_BEGIN\n#define DEFLATE_TRY_END(res)\n\n#else\n\n#define DEFLATE_TRY_BEGIN try {\n#define DEFLATE_TRY_END(res) } \\\n  catch(const CSystemException &e) { res = e.ErrorCode; } \\\n  catch(...) { res = S_FALSE; }\n\n  // catch(const CInBufferException &e)  { res = e.ErrorCode; }\n  // catch(const CLzOutWindowException &e)  { res = e.ErrorCode; }\n\n#endif\n\n\nHRESULT CCoder::CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress)\n{\n  HRESULT res;\n  \n  DEFLATE_TRY_BEGIN\n  \n  m_OutWindowStream.SetStream(outStream);\n  CCoderReleaser flusher(this);\n\n  const UInt64 inStart = _needInitInStream ? 0 : m_InBitStream.GetProcessedSize();\n\n  for (;;)\n  {\n    const UInt32 kInputProgressLimit = 1 << 21;\n    UInt32 curSize = 1 << 20;\n    bool finishInputStream = false;\n    if (_outSizeDefined)\n    {\n      const UInt64 rem = _outSize - GetOutProcessedCur();\n      if (curSize >= rem)\n      {\n        curSize = (UInt32)rem;\n        if (_needFinishInput)\n          finishInputStream = true;\n        else if (curSize == 0)\n          break;\n      }\n    }\n    \n    RINOK(CodeSpec(curSize, finishInputStream, progress ? kInputProgressLimit : 0))\n    \n    if (_remainLen == kLenIdFinished)\n      break;\n\n    if (progress)\n    {\n      const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart;\n      const UInt64 nowPos64 = GetOutProcessedCur();\n      RINOK(progress->SetRatioInfo(&inSize, &nowPos64))\n    }\n  }\n  \n  flusher.NeedFlush = false;\n  res = Flush();\n  if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError())\n    return S_FALSE;\n  \n  DEFLATE_TRY_END(res)\n  \n  return res;\n}\n\n\nZ7_COM7F_IMF(CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  SetInStream(inStream);\n  SetOutStreamSize(outSize);\n  const HRESULT res = CodeReal(outStream, progress);\n  ReleaseInStream();\n  /*\n  if (res == S_OK)\n    if (_needFinishInput && inSize && *inSize != m_InBitStream.GetProcessedSize())\n      res = S_FALSE;\n  */\n  return res;\n}\n\n\nZ7_COM7F_IMF(CCoder::SetFinishMode(UInt32 finishMode))\n{\n  Set_NeedFinishInput(finishMode != 0);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = m_InBitStream.GetStreamSize();\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize))\n{\n  AlignToByte();\n  UInt32 i = 0;\n  {\n    for (i = 0; i < size; i++)\n    {\n      if (!m_InBitStream.ReadAlignedByte_FromBuf(((Byte *)data)[i]))\n        break;\n    }\n  }\n  if (processedSize)\n    *processedSize = i;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCoder::SetInStream(ISequentialInStream *inStream))\n{\n  m_InStreamRef = inStream;\n  m_InBitStream.SetStream(inStream);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCoder::ReleaseInStream())\n{\n  m_InStreamRef.Release();\n  m_InBitStream.ClearStreamPtr();\n  return S_OK;\n}\n\n\nvoid CCoder::SetOutStreamSizeResume(const UInt64 *outSize)\n{\n  _outSizeDefined = (outSize != NULL);\n  _outSize = 0;\n  if (_outSizeDefined)\n    _outSize = *outSize;\n  m_OutWindowStream.Init(_keepHistory);\n  _outStartPos = m_OutWindowStream.GetProcessedSize();\n  _remainLen = kLenIdNeedInit;\n}\n\n\nZ7_COM7F_IMF(CCoder::SetOutStreamSize(const UInt64 *outSize))\n{\n  /*\n    18.06:\n    We want to support GetInputProcessedSize() before CCoder::Read()\n    So we call m_InBitStream.Init() even before buffer allocations\n    m_InBitStream.Init() just sets variables to default values\n    But later we will call m_InBitStream.Init() again with real buffer pointers\n  */\n  m_InBitStream.Init();\n  _needInitInStream = true;\n  SetOutStreamSizeResume(outSize);\n  return S_OK;\n}\n\n\n#ifndef Z7_NO_READ_FROM_CODER\n\nZ7_COM7F_IMF(CCoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  const UInt64 outPos = GetOutProcessedCur();\n\n  bool finishInputStream = false;\n  if (_outSizeDefined)\n  {\n    const UInt64 rem = _outSize - outPos;\n    if (size >= rem)\n    {\n      size = (UInt32)rem;\n      if (_needFinishInput)\n        finishInputStream = true;\n    }\n  }\n  if (!finishInputStream && size == 0)\n    return S_OK;\n\n  HRESULT res;\n  DEFLATE_TRY_BEGIN\n  m_OutWindowStream.SetMemStream((Byte *)data);\n  res = CodeSpec(size, finishInputStream);\n  DEFLATE_TRY_END(res)\n  {\n    const HRESULT res2 = Flush();\n    if (res2 != S_OK)\n      res = res2;\n  }\n  if (processedSize)\n    *processedSize = (UInt32)(GetOutProcessedCur() - outPos);\n  m_OutWindowStream.SetMemStream(NULL);\n  return res;\n}\n\n#endif\n\n\nHRESULT CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)\n{\n  SetOutStreamSizeResume(outSize);\n  return CodeReal(outStream, progress);\n}\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/DeflateDecoder.h",
    "content": "﻿// DeflateDecoder.h\n\n#ifndef ZIP7_INC_DEFLATE_DECODER_H\n#define ZIP7_INC_DEFLATE_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n\n#include \"BitlDecoder.h\"\n#include \"DeflateConst.h\"\n#include \"HuffmanDecoder.h\"\n#include \"LzOutWindow.h\"\n\nnamespace NCompress {\nnamespace NDeflate {\nnamespace NDecoder {\n\nconst int kLenIdFinished = -1;\nconst int kLenIdNeedInit = -2;\n\nconst unsigned kNumTableBits_Main = 10;\nconst unsigned kNumTableBits_Dist = 6;\n\nclass CCoder:\n  public ICompressCoder,\n  public ICompressSetFinishMode,\n  public ICompressGetInStreamProcessedSize,\n  public ICompressReadUnusedFromInBuf,\n  public ICompressSetInStream,\n  public ICompressSetOutStreamSize,\n#ifndef Z7_NO_READ_FROM_CODER\n  public ISequentialInStream,\n#endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetFinishMode)\n  Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize)\n  Z7_COM_QI_ENTRY(ICompressReadUnusedFromInBuf)\n  Z7_COM_QI_ENTRY(ICompressSetInStream)\n  Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM_QI_ENTRY(ISequentialInStream)\n#endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetFinishMode)\n  Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressReadUnusedFromInBuf)\n  Z7_IFACE_COM7_IMP(ICompressSetInStream)\nprivate:\n  Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n#ifndef Z7_NO_READ_FROM_CODER\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n#endif\n\n  CLzOutWindow m_OutWindowStream;\n  NBitl::CDecoder<CInBuffer> m_InBitStream;\n  NCompress::NHuffman::CDecoder<kNumHuffmanBits, kFixedMainTableSize, kNumTableBits_Main> m_MainDecoder;\n  NCompress::NHuffman::CDecoder256<kNumHuffmanBits, kFixedDistTableSize, kNumTableBits_Dist> m_DistDecoder;\n  NCompress::NHuffman::CDecoder7b<kLevelTableSize> m_LevelDecoder;\n\n  UInt32 m_StoredBlockSize;\n\n  unsigned _numDistLevels;\n  bool m_FinalBlock;\n  bool m_StoredMode;\n\n  bool _deflateNSIS;\n  bool _deflate64Mode;\n  bool _keepHistory;\n  bool _needFinishInput;\n  \n  bool _needInitInStream;\n  bool _needReadTable;\n  Int32 _remainLen;\n  UInt32 _rep0;\n\n  bool _outSizeDefined;\n  CMyComPtr<ISequentialInStream> m_InStreamRef;\n  UInt64 _outSize;\n  UInt64 _outStartPos;\n\n  void SetOutStreamSizeResume(const UInt64 *outSize);\n  UInt64 GetOutProcessedCur() const { return m_OutWindowStream.GetProcessedSize() - _outStartPos; }\n\n  UInt32 ReadBits(unsigned numBits);\n\n  bool DecodeLevels(Byte *levels, unsigned numSymbols);\n  bool ReadTables();\n  \n  HRESULT Flush() { return m_OutWindowStream.Flush(); }\n  class CCoderReleaser\n  {\n    CCoder *_coder;\n  public:\n    bool NeedFlush;\n    CCoderReleaser(CCoder *coder): _coder(coder), NeedFlush(true) {}\n    ~CCoderReleaser()\n    {\n      if (NeedFlush)\n        _coder->Flush();\n    }\n  };\n  friend class CCoderReleaser;\n\n  HRESULT CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit = 0);\npublic:\n\n  CCoder(bool deflate64Mode);\n  virtual ~CCoder() {}\n\n  void SetNsisMode(bool nsisMode) { _deflateNSIS = nsisMode; }\n\n  void Set_KeepHistory(bool keepHistory) { _keepHistory = keepHistory; }\n  void Set_NeedFinishInput(bool needFinishInput) { _needFinishInput = needFinishInput; }\n\n  bool IsFinished() const { return _remainLen == kLenIdFinished; }\n  bool IsFinalBlock() const { return m_FinalBlock; }\n\n  HRESULT CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n\npublic:\n  HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);\n  HRESULT InitInStream(bool needInit);\n\n  void AlignToByte() { m_InBitStream.AlignToByte(); }\n  Byte ReadAlignedByte();\n  UInt32 ReadAligned_UInt16() // aligned for Byte range\n  {\n    const UInt32 v = m_InBitStream.ReadAlignedByte();\n    return v | ((UInt32)m_InBitStream.ReadAlignedByte() << 8);\n  }\n  bool InputEofError() const { return m_InBitStream.ExtraBitsWereRead(); }\n\n  // size of used real data from input stream\n  UInt64 GetStreamSize() const { return m_InBitStream.GetStreamSize(); }\n\n  // size of virtual input stream processed\n  UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); }\n};\n\nclass CCOMCoder     : public CCoder { public: CCOMCoder(): CCoder(false) {} };\nclass CCOMCoder64   : public CCoder { public: CCOMCoder64(): CCoder(true) {} };\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/DeflateEncoder.cpp",
    "content": "﻿// DeflateEncoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/HuffEnc.h\"\n\n#include \"../../Common/ComTry.h\"\n\n#include \"../Common/CWrappers.h\"\n\n#include \"DeflateEncoder.h\"\n\n#undef NO_INLINE\n\n#ifdef _MSC_VER\n#define NO_INLINE Z7_NO_INLINE\n#else\n#define NO_INLINE\n#endif\n\n#define MAX_HUF_LEN_12  12\n\nnamespace NCompress {\nnamespace NDeflate {\nnamespace NEncoder {\n\nstatic const unsigned k_CodeValue_Len_Is_Literal_Flag = 1u << 15;\n\nstatic const unsigned kNumDivPassesMax = 10; // [0, 16); ratio/speed/ram tradeoff; use big value for better compression ratio.\nstatic const unsigned kNumTables = 1u << kNumDivPassesMax;\n\nstatic const UInt32 kFixedHuffmanCodeBlockSizeMax = (1 << 8); // [0, (1 << 32)); ratio/speed tradeoff; use big value for better compression ratio.\nstatic const UInt32 kDivideCodeBlockSizeMin = (1 << 7); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.\nstatic const UInt32 kDivideBlockSizeMin = (1 << 6); // [1, (1 << 32)); ratio/speed tradeoff; use small value for better compression ratio.\n\nstatic const UInt32 kMaxUncompressedBlockSize = ((1 << 16) - 1) * 1; // [1, (1 << 32))\nstatic const UInt32 kMatchArraySize = kMaxUncompressedBlockSize * 10; // [kMatchMaxLen * 2, (1 << 32))\nstatic const UInt32 kMatchArrayLimit = kMatchArraySize - kMatchMaxLen * 4 * sizeof(UInt16);\nstatic const UInt32 kBlockUncompressedSizeThreshold = kMaxUncompressedBlockSize -\n    kMatchMaxLen - kNumOpts;\n\n// static const unsigned kMaxCodeBitLength = 11;\nstatic const unsigned kMaxLevelBitLength = 7;\n\nstatic const Byte kNoLiteralStatPrice = 11;\nstatic const Byte kNoLenStatPrice = 11;\nstatic const Byte kNoPosStatPrice = 6;\n\nMY_ALIGN(64)\nstatic Byte g_LenSlots[kNumLenSymbolsMax];\n\n#define kNumLogBits 9    // do not change it\nMY_ALIGN(64)\nstatic Byte g_FastPos[1 << kNumLogBits];\n\nclass CFastPosInit\n{\npublic:\n  CFastPosInit()\n  {\n    unsigned i;\n    for (i = 0; i < kNumLenSlots; i++)\n    {\n      unsigned c = kLenStart32[i];\n      const unsigned j = 1u << kLenDirectBits32[i];\n      for (unsigned k = 0; k < j; k++, c++)\n        g_LenSlots[c] = (Byte)i;\n    }\n    \n    const unsigned kFastSlots = kNumLogBits * 2;\n    unsigned c = 0;\n    for (Byte slotFast = 0; slotFast < kFastSlots; slotFast++)\n    {\n      const unsigned k = 1u << kDistDirectBits[slotFast];\n      for (unsigned j = 0; j < k; j++, c++)\n        g_FastPos[c] = slotFast;\n    }\n  }\n};\n\nstatic CFastPosInit g_FastPosInit;\n\ninline unsigned GetPosSlot(UInt32 pos)\n{\n  /*\n  if (pos < 0x200)\n    return g_FastPos[pos];\n  return g_FastPos[pos >> 8] + 16;\n  */\n  // const unsigned zz = (pos < ((UInt32)1 << (kNumLogBits))) ? 0 : 8;\n  /*\n  const unsigned zz = (kNumLogBits - 1) &\n      ((UInt32)0 - (((((UInt32)1 << kNumLogBits) - 1) - pos) >> 31));\n  */\n  const unsigned zz = (kNumLogBits - 1) &\n      (((((UInt32)1 << kNumLogBits) - 1) - pos) >> (31 - 3));\n  return g_FastPos[pos >> zz] + (zz * 2);\n}\n\n\nvoid CEncProps::Normalize()\n{\n  int level = Level;\n  if (level < 0) level = 5;\n  Level = level;\n  if (algo < 0) algo = (level < 5 ? 0 : 1);\n  if (fb < 0) fb = (level < 7 ? 32 : (level < 9 ? 64 : 128));\n  if (btMode < 0) btMode = (algo == 0 ? 0 : 1);\n  if (mc == 0) mc = (16 + ((unsigned)fb >> 1));\n  if (numPasses == (UInt32)(Int32)-1) numPasses = (level < 7 ? 1 : (level < 9 ? 3 : 10));\n}\n\nvoid CCoder::SetProps(const CEncProps *props2)\n{\n  CEncProps props = *props2;\n  props.Normalize();\n\n  m_MatchFinderCycles = props.mc;\n  {\n    unsigned fb = (unsigned)props.fb;\n    if (fb < kMatchMinLen)\n      fb = kMatchMinLen;\n    if (fb > m_MatchMaxLen)\n      fb = m_MatchMaxLen;\n    m_NumFastBytes = fb;\n  }\n  _fastMode = (props.algo == 0);\n  _btMode = (props.btMode != 0);\n\n  m_NumDivPasses = props.numPasses;\n  if (m_NumDivPasses == 0)\n    m_NumDivPasses = 1;\n  if (m_NumDivPasses == 1)\n    m_NumPasses = 1;\n  else if (m_NumDivPasses <= kNumDivPassesMax)\n    m_NumPasses = 2;\n  else\n  {\n    m_NumPasses = 2 + (m_NumDivPasses - kNumDivPassesMax);\n    m_NumDivPasses = kNumDivPassesMax;\n  }\n}\n\nCCoder::CCoder(bool deflate64Mode):\n  m_Values(NULL),\n  m_OnePosMatchesMemory(NULL),\n  m_DistanceMemory(NULL),\n  m_Created(false),\n  m_Deflate64Mode(deflate64Mode),\n  m_Tables(NULL)\n{\n  m_MatchMaxLen = deflate64Mode ? kMatchMaxLen64 : kMatchMaxLen32;\n  m_NumLenCombinations = deflate64Mode ? kNumLenSymbols64 : kNumLenSymbols32;\n  m_LenStart = deflate64Mode ? kLenStart64 : kLenStart32;\n  m_LenDirectBits = deflate64Mode ? kLenDirectBits64 : kLenDirectBits32;\n  {\n    CEncProps props;\n    SetProps(&props);\n  }\n  MatchFinder_Construct(&_lzInWindow);\n}\n\nHRESULT CCoder::Create()\n{\n  // COM_TRY_BEGIN\n  if (!m_Values)\n  {\n    m_Values = (CCodeValue *)MyAlloc(kMaxUncompressedBlockSize * sizeof(CCodeValue));\n    if (!m_Values)\n      return E_OUTOFMEMORY;\n  }\n  if (!m_Tables)\n  {\n    m_Tables = (CTables *)MyAlloc(kNumTables * sizeof(CTables));\n    if (!m_Tables)\n      return E_OUTOFMEMORY;\n  }\n\n  if (m_IsMultiPass)\n  {\n    if (!m_OnePosMatchesMemory)\n    {\n      m_OnePosMatchesMemory = (UInt16 *)::MidAlloc(kMatchArraySize * sizeof(UInt16));\n      if (!m_OnePosMatchesMemory)\n        return E_OUTOFMEMORY;\n    }\n  }\n  else\n  {\n    if (!m_DistanceMemory)\n    {\n      m_DistanceMemory = (UInt16 *)MyAlloc((kMatchMaxLen + 2) * 2 * sizeof(UInt16));\n      if (!m_DistanceMemory)\n        return E_OUTOFMEMORY;\n      m_MatchDistances = m_DistanceMemory;\n    }\n  }\n\n  if (!m_Created)\n  {\n    _lzInWindow.btMode = (Byte)(_btMode ? 1 : 0);\n    _lzInWindow.numHashBytes = 3;\n    _lzInWindow.numHashBytes_Min = 3;\n    if (!MatchFinder_Create(&_lzInWindow,\n        m_Deflate64Mode ? kHistorySize64 : kHistorySize32,\n        kNumOpts + kMaxUncompressedBlockSize,\n        m_NumFastBytes, m_MatchMaxLen - m_NumFastBytes, &g_AlignedAlloc))\n      return E_OUTOFMEMORY;\n    if (!m_OutStream.Create(1 << 20))\n      return E_OUTOFMEMORY;\n  }\n  if (m_MatchFinderCycles != 0)\n    _lzInWindow.cutValue = m_MatchFinderCycles;\n  m_Created = true;\n  return S_OK;\n  // COM_TRY_END\n}\n\nHRESULT CCoder::BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)\n{\n  CEncProps props;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    PROPID propID = propIDs[i];\n    if (propID >= NCoderPropID::kReduceSize)\n      continue;\n    if (prop.vt != VT_UI4)\n      return E_INVALIDARG;\n    UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n      case NCoderPropID::kNumPasses: props.numPasses = v; break;\n      case NCoderPropID::kNumFastBytes: props.fb = (int)v; break;\n      case NCoderPropID::kMatchFinderCycles: props.mc = v; break;\n      case NCoderPropID::kAlgorithm: props.algo = (int)v; break;\n      case NCoderPropID::kLevel: props.Level = (int)v; break;\n      case NCoderPropID::kNumThreads: break;\n      default: return E_INVALIDARG;\n    }\n  }\n  SetProps(&props);\n  return S_OK;\n}\n  \nvoid CCoder::Free()\n{\n  ::MidFree(m_OnePosMatchesMemory); m_OnePosMatchesMemory = NULL;\n  ::MyFree(m_DistanceMemory); m_DistanceMemory = NULL;\n  ::MyFree(m_Values); m_Values = NULL;\n  ::MyFree(m_Tables); m_Tables = NULL;\n}\n\nCCoder::~CCoder()\n{\n  Free();\n  MatchFinder_Free(&_lzInWindow, &g_AlignedAlloc);\n}\n\nNO_INLINE void CCoder::GetMatches()\n{\n  if (m_IsMultiPass)\n  {\n    m_MatchDistances = m_OnePosMatchesMemory + m_Pos;\n    if (m_SecondPass)\n    {\n      m_Pos += *m_MatchDistances + 1;\n      return;\n    }\n  }\n\n  UInt32 distanceTmp[kMatchMaxLen * 2 + 3];\n  \n  const size_t numPairs = (size_t)((_btMode ?\n      Bt3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp):\n      Hc3Zip_MatchFinder_GetMatches(&_lzInWindow, distanceTmp)) - distanceTmp);\n\n  UInt16 *matchDistances = m_MatchDistances;\n  *matchDistances++ = (UInt16)numPairs;\n   \n  if (numPairs != 0)\n  {\n    size_t i;\n    for (i = 0; i < numPairs; i += 2)\n    {\n      matchDistances[0] = (UInt16)distanceTmp[i];\n      matchDistances[1] = (UInt16)distanceTmp[(size_t)i + 1];\n      matchDistances += 2;\n    }\n    UInt32 len = distanceTmp[(size_t)numPairs - 2];\n    if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen)\n    {\n      UInt32 numAvail = Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) + 1;\n      const Byte *pby = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - 1;\n      const Byte *pby2 = pby - (distanceTmp[(size_t)numPairs - 1] + 1);\n      if (numAvail > m_MatchMaxLen)\n        numAvail = m_MatchMaxLen;\n      for (; len < numAvail && pby[len] == pby2[len]; len++);\n      matchDistances[-2] = (UInt16)len;\n    }\n  }\n  if (m_IsMultiPass)\n    m_Pos += (UInt32)numPairs + 1;\n  if (!m_SecondPass)\n    m_AdditionalOffset++;\n}\n\nvoid CCoder::MovePos(UInt32 num)\n{\n  if (!m_SecondPass && num > 0)\n  {\n    if (_btMode)\n      Bt3Zip_MatchFinder_Skip(&_lzInWindow, num);\n    else\n      Hc3Zip_MatchFinder_Skip(&_lzInWindow, num);\n    m_AdditionalOffset += num;\n  }\n}\n\nstatic const UInt32 kIfinityPrice = 0xFFFFFFF;\n\nNO_INLINE UInt32 CCoder::Backward(UInt32 &backRes, UInt32 cur)\n{\n  m_OptimumEndIndex = cur;\n  UInt32 posMem = m_Optimum[cur].PosPrev;\n  UInt16 backMem = m_Optimum[cur].BackPrev;\n  do\n  {\n    UInt32 posPrev = posMem;\n    UInt16 backCur = backMem;\n    backMem = m_Optimum[posPrev].BackPrev;\n    posMem = m_Optimum[posPrev].PosPrev;\n    m_Optimum[posPrev].BackPrev = backCur;\n    m_Optimum[posPrev].PosPrev = (UInt16)cur;\n    cur = posPrev;\n  }\n  while (cur > 0);\n  backRes = m_Optimum[0].BackPrev;\n  m_OptimumCurrentIndex = m_Optimum[0].PosPrev;\n  return m_OptimumCurrentIndex;\n}\n\nNO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)\n{\n  if (m_OptimumEndIndex != m_OptimumCurrentIndex)\n  {\n    UInt32 len = m_Optimum[m_OptimumCurrentIndex].PosPrev - m_OptimumCurrentIndex;\n    backRes = m_Optimum[m_OptimumCurrentIndex].BackPrev;\n    m_OptimumCurrentIndex = m_Optimum[m_OptimumCurrentIndex].PosPrev;\n    return len;\n  }\n  m_OptimumCurrentIndex = m_OptimumEndIndex = 0;\n  \n  GetMatches();\n\n  UInt32 lenEnd;\n  {\n    const UInt32 numDistancePairs = m_MatchDistances[0];\n    if (numDistancePairs == 0)\n      return 1;\n    const UInt16 *matchDistances = m_MatchDistances + 1;\n    lenEnd = matchDistances[(size_t)numDistancePairs - 2];\n    \n    if (lenEnd > m_NumFastBytes)\n    {\n      backRes = matchDistances[(size_t)numDistancePairs - 1];\n      MovePos(lenEnd - 1);\n      return lenEnd;\n    }\n\n    m_Optimum[1].Price = m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset)];\n    m_Optimum[1].PosPrev = 0;\n    \n    m_Optimum[2].Price = kIfinityPrice;\n    m_Optimum[2].PosPrev = 1;\n    \n    UInt32 offs = 0;\n  \n    for (UInt32 i = kMatchMinLen; i <= lenEnd; i++)\n    {\n      UInt32 distance = matchDistances[(size_t)offs + 1];\n      m_Optimum[i].PosPrev = 0;\n      m_Optimum[i].BackPrev = (UInt16)distance;\n      m_Optimum[i].Price = m_LenPrices[(size_t)i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)];\n      if (i == matchDistances[offs])\n        offs += 2;\n    }\n  }\n\n  UInt32 cur = 0;\n\n  for (;;)\n  {\n    ++cur;\n    if (cur == lenEnd || cur == kNumOptsBase || m_Pos >= kMatchArrayLimit)\n      return Backward(backRes, cur);\n    GetMatches();\n    const UInt16 *matchDistances = m_MatchDistances + 1;\n    const UInt32 numDistancePairs = m_MatchDistances[0];\n    UInt32 newLen = 0;\n    if (numDistancePairs != 0)\n    {\n      newLen = matchDistances[(size_t)numDistancePairs - 2];\n      if (newLen > m_NumFastBytes)\n      {\n        UInt32 len = Backward(backRes, cur);\n        m_Optimum[cur].BackPrev = matchDistances[(size_t)numDistancePairs - 1];\n        m_OptimumEndIndex = cur + newLen;\n        m_Optimum[cur].PosPrev = (UInt16)m_OptimumEndIndex;\n        MovePos(newLen - 1);\n        return len;\n      }\n    }\n    UInt32 curPrice = m_Optimum[cur].Price;\n    {\n      const UInt32 curAnd1Price = curPrice + m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) + cur - m_AdditionalOffset)];\n      COptimal &optimum = m_Optimum[(size_t)cur + 1];\n      if (curAnd1Price < optimum.Price)\n      {\n        optimum.Price = curAnd1Price;\n        optimum.PosPrev = (UInt16)cur;\n      }\n    }\n    if (numDistancePairs == 0)\n      continue;\n    while (lenEnd < cur + newLen)\n      m_Optimum[++lenEnd].Price = kIfinityPrice;\n    UInt32 offs = 0;\n    UInt32 distance = matchDistances[(size_t)offs + 1];\n    curPrice += m_PosPrices[GetPosSlot(distance)];\n    for (UInt32 lenTest = kMatchMinLen; ; lenTest++)\n    {\n      UInt32 curAndLenPrice = curPrice + m_LenPrices[(size_t)lenTest - kMatchMinLen];\n      COptimal &optimum = m_Optimum[cur + lenTest];\n      if (curAndLenPrice < optimum.Price)\n      {\n        optimum.Price = curAndLenPrice;\n        optimum.PosPrev = (UInt16)cur;\n        optimum.BackPrev = (UInt16)distance;\n      }\n      if (lenTest == matchDistances[offs])\n      {\n        offs += 2;\n        if (offs == numDistancePairs)\n          break;\n        curPrice -= m_PosPrices[GetPosSlot(distance)];\n        distance = matchDistances[(size_t)offs + 1];\n        curPrice += m_PosPrices[GetPosSlot(distance)];\n      }\n    }\n  }\n}\n\nUInt32 CCoder::GetOptimalFast(UInt32 &backRes)\n{\n  GetMatches();\n  UInt32 numDistancePairs = m_MatchDistances[0];\n  if (numDistancePairs == 0)\n    return 1;\n  UInt32 lenMain = m_MatchDistances[(size_t)numDistancePairs - 1];\n  backRes = m_MatchDistances[numDistancePairs];\n  MovePos(lenMain - 1);\n  return lenMain;\n}\n\nvoid CTables::InitStructures()\n{\n  UInt32 i;\n  for (i = 0; i < 256; i++)\n    litLenLevels[i] = 8;\n  litLenLevels[i++] = 13;\n  for (;i < kFixedMainTableSize; i++)\n    litLenLevels[i] = 5;\n  for (i = 0; i < kFixedDistTableSize; i++)\n    distLevels[i] = 5;\n}\n\nNO_INLINE void CCoder::LevelTableDummy(const Byte *levels, unsigned numLevels, UInt32 *freqs)\n{\n  unsigned prevLen = 0xFF;\n  unsigned nextLen = levels[0];\n  unsigned count = 0;\n  unsigned maxCount = 7;\n  unsigned minCount = 4;\n  \n  if (nextLen == 0)\n  {\n    maxCount = 138;\n    minCount = 3;\n  }\n  \n  for (unsigned n = 0; n < numLevels; n++)\n  {\n    unsigned curLen = nextLen;\n    nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF;\n    count++;\n    if (count < maxCount && curLen == nextLen)\n      continue;\n    \n    if (count < minCount)\n      freqs[curLen] += (UInt32)count;\n    else if (curLen != 0)\n    {\n      if (curLen != prevLen)\n      {\n        freqs[curLen]++;\n        count--;\n      }\n      freqs[kTableLevelRepNumber]++;\n    }\n    else if (count <= 10)\n      freqs[kTableLevel0Number]++;\n    else\n      freqs[kTableLevel0Number2]++;\n\n    count = 0;\n    prevLen = curLen;\n    \n    if (nextLen == 0)\n    {\n      maxCount = 138;\n      minCount = 3;\n    }\n    else if (curLen == nextLen)\n    {\n      maxCount = 6;\n      minCount = 3;\n    }\n    else\n    {\n      maxCount = 7;\n      minCount = 4;\n    }\n  }\n}\n\nNO_INLINE void CCoder::WriteBits(UInt32 value, unsigned numBits)\n{\n  m_OutStream.WriteBits(value, numBits);\n}\n\n#define WRITE_HF2(codes, lens, i) m_OutStream.WriteBits(codes[i], lens[i])\n#define WRITE_HF2_NO_INLINE(codes, lens, i)   WriteBits(codes[i], lens[i])\n#define WRITE_HF(i) WriteBits(codes[i], lens[i])\n\nNO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes)\n{\n  unsigned prevLen = 0xFF;\n  unsigned nextLen = levels[0];\n  unsigned count = 0;\n  unsigned maxCount = 7;\n  unsigned minCount = 4;\n  \n  if (nextLen == 0)\n  {\n    maxCount = 138;\n    minCount = 3;\n  }\n  \n  for (unsigned n = 0; n < numLevels; n++)\n  {\n    unsigned curLen = nextLen;\n    nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF;\n    count++;\n    if (count < maxCount && curLen == nextLen)\n      continue;\n    \n    if (count < minCount)\n      for (unsigned i = 0; i < count; i++)\n        WRITE_HF(curLen);\n    else if (curLen != 0)\n    {\n      if (curLen != prevLen)\n      {\n        WRITE_HF(curLen);\n        count--;\n      }\n      WRITE_HF(kTableLevelRepNumber);\n      WriteBits(count - 3, 2);\n    }\n    else if (count <= 10)\n    {\n      WRITE_HF(kTableLevel0Number);\n      WriteBits(count - 3, 3);\n    }\n    else\n    {\n      WRITE_HF(kTableLevel0Number2);\n      WriteBits(count - 11, 7);\n    }\n\n    count = 0;\n    prevLen = curLen;\n    \n    if (nextLen == 0)\n    {\n      maxCount = 138;\n      minCount = 3;\n    }\n    else if (curLen == nextLen)\n    {\n      maxCount = 6;\n      minCount = 3;\n    }\n    else\n    {\n      maxCount = 7;\n      minCount = 4;\n    }\n  }\n}\n\nNO_INLINE void CCoder::MakeTables(unsigned maxHuffLen)\n{\n  Huffman_Generate(mainFreqs, mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize, maxHuffLen);\n  Huffman_Generate(distFreqs, distCodes, m_NewLevels.distLevels, kDistTableSize64, maxHuffLen);\n}\n\nstatic NO_INLINE UInt32 Huffman_GetPrice(const UInt32 *freqs, const Byte *lens, UInt32 num)\n{\n  UInt32 price = 0;\n  UInt32 i;\n  for (i = 0; i < num; i++)\n    price += lens[i] * freqs[i];\n  return price;\n}\n\nstatic NO_INLINE UInt32 Huffman_GetPrice_Spec(\n    const UInt32 *freqs, const Byte *lens, UInt32 num,\n    const Byte *extraBits, UInt32 extraBase)\n{\n  return\n    Huffman_GetPrice(freqs, lens, num) +\n    Huffman_GetPrice(freqs + extraBase, extraBits, num - extraBase);\n}\n\nNO_INLINE UInt32 CCoder::GetLzBlockPrice() const\n{\n  return\n    Huffman_GetPrice_Spec(mainFreqs, m_NewLevels.litLenLevels,\n        kFixedMainTableSize, m_LenDirectBits, kSymbolMatch) +\n    Huffman_GetPrice_Spec(distFreqs, m_NewLevels.distLevels,\n        kDistTableSize64, kDistDirectBits, 0);\n}\n\nNO_INLINE void CCoder::TryBlock()\n{\n  memset(mainFreqs, 0, sizeof(mainFreqs));\n  memset(distFreqs, 0, sizeof(distFreqs));\n\n  m_ValueIndex = 0;\n  UInt32 blockSize = BlockSizeRes;\n  BlockSizeRes = 0;\n  for (;;)\n  {\n    if (m_OptimumCurrentIndex == m_OptimumEndIndex)\n    {\n      if (m_Pos >= kMatchArrayLimit\n          || BlockSizeRes >= blockSize\n          || (!m_SecondPass && ((Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0) || m_ValueIndex >= m_ValueBlockSize)))\n        break;\n    }\n    UInt32 pos;\n    UInt32 len;\n    if (_fastMode)\n      len = GetOptimalFast(pos);\n    else\n      len = GetOptimal(pos);\n    CCodeValue &codeValue = m_Values[m_ValueIndex++];\n    if (len >= kMatchMinLen)\n    {\n      const UInt32 newLen = len - kMatchMinLen;\n      codeValue.Len = (UInt16)newLen;\n      mainFreqs[kSymbolMatch + (size_t)g_LenSlots[newLen]]++;\n      codeValue.Pos = (UInt16)pos;\n      distFreqs[GetPosSlot(pos)]++;\n    }\n    else\n    {\n      const unsigned b = *(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - m_AdditionalOffset);\n      mainFreqs[b]++;\n      codeValue.Len = k_CodeValue_Len_Is_Literal_Flag;\n      codeValue.Pos = (UInt16)b;\n    }\n    m_AdditionalOffset -= len;\n    BlockSizeRes += len;\n  }\n  mainFreqs[kSymbolEndOfBlock]++;\n  m_AdditionalOffset += BlockSizeRes;\n  m_SecondPass = true;\n}\n\nNO_INLINE void CCoder::SetPrices(const CLevels &levels)\n{\n  if (_fastMode)\n    return;\n  UInt32 i;\n  for (i = 0; i < 256; i++)\n  {\n    Byte price = levels.litLenLevels[i];\n    m_LiteralPrices[i] = ((price != 0) ? price : kNoLiteralStatPrice);\n  }\n  \n  for (i = 0; i < m_NumLenCombinations; i++)\n  {\n    UInt32 slot = g_LenSlots[i];\n    Byte price = levels.litLenLevels[kSymbolMatch + (size_t)slot];\n    m_LenPrices[i] = (Byte)(((price != 0) ? price : kNoLenStatPrice) + m_LenDirectBits[slot]);\n  }\n  \n  for (i = 0; i < kDistTableSize64; i++)\n  {\n    Byte price = levels.distLevels[i];\n    m_PosPrices[i] = (Byte)(((price != 0) ? price: kNoPosStatPrice) + kDistDirectBits[i]);\n  }\n}\n\n#if MAX_HUF_LEN_12 > 12\n// Huffman_ReverseBits() now supports 12-bits values only.\n#error Stop_Compiling_Bad_MAX_HUF_LEN_12\n#endif\nstatic NO_INLINE void Huffman_ReverseBits(UInt32 *codes, const Byte *lens, UInt32 num)\n{\n  const Byte * const lens_lim = lens + num;\n  do\n  {\n    // we should change constants, if lens[*] can be larger than 12.\n    UInt32 x = *codes;\n    x = ((x & (0x555     )) << 2) + (x & (0xAAA     ));\n    x = ((x & (0x333 << 1)) << 4) | (x & (0xCCC << 1));\n    x = ((x & (0xF0F << 3)) << 8) | (x & (0x0F0 << 3));\n    // we can use (x) instead of (x & (0xFF << 7)), if we support garabage data after (*lens) bits.\n    *codes++ = (((x & (0xFF << 7)) << 16) | x) >> (*lens ^ 31);\n  }\n  while (++lens != lens_lim);\n}\n\nNO_INLINE void CCoder::WriteBlock()\n{\n  Huffman_ReverseBits(mainCodes, m_NewLevels.litLenLevels, kFixedMainTableSize);\n  Huffman_ReverseBits(distCodes, m_NewLevels.distLevels, kDistTableSize64);\n\n  CCodeValue *values = m_Values;\n  const CCodeValue * const values_lim = values + m_ValueIndex;\n\n  if (values != values_lim)\n  do\n  {\n    const UInt32 len = values->Len;\n    const UInt32 dist = values->Pos;\n    if (len == k_CodeValue_Len_Is_Literal_Flag)\n      WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, dist);\n    else\n    {\n      const unsigned lenSlot = g_LenSlots[len];\n      WRITE_HF2(mainCodes, m_NewLevels.litLenLevels, kSymbolMatch + lenSlot);\n      m_OutStream.WriteBits(len - m_LenStart[lenSlot], m_LenDirectBits[lenSlot]);\n      const unsigned posSlot = GetPosSlot(dist);\n      WRITE_HF2(distCodes, m_NewLevels.distLevels, posSlot);\n      m_OutStream.WriteBits(dist - kDistStart[posSlot], kDistDirectBits[posSlot]);\n    }\n  }\n  while (++values != values_lim);\n  WRITE_HF2_NO_INLINE(mainCodes, m_NewLevels.litLenLevels, kSymbolEndOfBlock);\n}\n\nstatic UInt32 GetStorePrice(UInt32 blockSize, unsigned bitPosition)\n{\n  UInt32 price = 0;\n  do\n  {\n    UInt32 nextBitPosition = (bitPosition + kFinalBlockFieldSize + kBlockTypeFieldSize) & 7;\n    unsigned numBitsForAlign = nextBitPosition > 0 ? (8 - nextBitPosition): 0;\n    UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;\n    price += kFinalBlockFieldSize + kBlockTypeFieldSize + numBitsForAlign + (2 + 2) * 8 + curBlockSize * 8;\n    bitPosition = 0;\n    blockSize -= curBlockSize;\n  }\n  while (blockSize != 0);\n  return price;\n}\n\nvoid CCoder::WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock)\n{\n  do\n  {\n    UInt32 curBlockSize = (blockSize < (1 << 16)) ? blockSize : (1 << 16) - 1;\n    blockSize -= curBlockSize;\n    WriteBits((finalBlock && (blockSize == 0) ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);\n    WriteBits(NBlockType::kStored, kBlockTypeFieldSize);\n    m_OutStream.FlushByte();\n    WriteBits((UInt16)curBlockSize, kStoredBlockLengthFieldSize);\n    WriteBits((UInt16)~curBlockSize, kStoredBlockLengthFieldSize);\n    const Byte *data = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow)- additionalOffset;\n    for (UInt32 i = 0; i < curBlockSize; i++)\n      m_OutStream.WriteByte(data[i]);\n    additionalOffset -= curBlockSize;\n  }\n  while (blockSize != 0);\n}\n\nNO_INLINE UInt32 CCoder::TryDynBlock(unsigned tableIndex, UInt32 numPasses)\n{\n  CTables &t = m_Tables[tableIndex];\n  BlockSizeRes = t.BlockSizeRes;\n  UInt32 posTemp = t.m_Pos;\n  SetPrices(t);\n\n  for (UInt32 p = 0; p < numPasses; p++)\n  {\n    m_Pos = posTemp;\n    TryBlock();\n    const unsigned numHuffBits =\n        m_ValueIndex > 18000 ? MAX_HUF_LEN_12 :\n        m_ValueIndex >  7000 ? 11 :\n        m_ValueIndex >  2000 ? 10 : 9;\n    MakeTables(numHuffBits);\n    SetPrices(m_NewLevels);\n  }\n\n  (CLevels &)t = m_NewLevels;\n\n  m_NumLitLenLevels = kMainTableSize;\n  while (m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[(size_t)m_NumLitLenLevels - 1] == 0)\n    m_NumLitLenLevels--;\n  \n  m_NumDistLevels = kDistTableSize64;\n  while (m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[(size_t)m_NumDistLevels - 1] == 0)\n    m_NumDistLevels--;\n  \n  UInt32 levelFreqs[kLevelTableSize];\n  memset(levelFreqs, 0, sizeof(levelFreqs));\n\n  LevelTableDummy(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelFreqs);\n  LevelTableDummy(m_NewLevels.distLevels, m_NumDistLevels, levelFreqs);\n  \n  Huffman_Generate(levelFreqs, levelCodes, levelLens, kLevelTableSize, kMaxLevelBitLength);\n  \n  m_NumLevelCodes = kNumLevelCodesMin;\n  for (UInt32 i = 0; i < kLevelTableSize; i++)\n  {\n    Byte level = levelLens[kCodeLengthAlphabetOrder[i]];\n    if (level > 0 && i >= m_NumLevelCodes)\n      m_NumLevelCodes = i + 1;\n    m_LevelLevels[i] = level;\n  }\n  \n  return GetLzBlockPrice() +\n      Huffman_GetPrice_Spec(levelFreqs, levelLens, kLevelTableSize, kLevelDirectBits, kTableDirectLevels) +\n      kNumLenCodesFieldSize + kNumDistCodesFieldSize + kNumLevelCodesFieldSize +\n      m_NumLevelCodes * kLevelFieldSize + kFinalBlockFieldSize + kBlockTypeFieldSize;\n}\n\nNO_INLINE UInt32 CCoder::TryFixedBlock(unsigned tableIndex)\n{\n  CTables &t = m_Tables[tableIndex];\n  BlockSizeRes = t.BlockSizeRes;\n  m_Pos = t.m_Pos;\n  m_NewLevels.SetFixedLevels();\n  SetPrices(m_NewLevels);\n  TryBlock();\n  return kFinalBlockFieldSize + kBlockTypeFieldSize + GetLzBlockPrice();\n}\n\nNO_INLINE UInt32 CCoder::GetBlockPrice(unsigned tableIndex, unsigned numDivPasses)\n{\n  CTables &t = m_Tables[tableIndex];\n  t.StaticMode = false;\n  UInt32 price = TryDynBlock(tableIndex, m_NumPasses);\n  t.BlockSizeRes = BlockSizeRes;\n  UInt32 numValues = m_ValueIndex;\n  UInt32 posTemp = m_Pos;\n  UInt32 additionalOffsetEnd = m_AdditionalOffset;\n  \n  if (m_CheckStatic && m_ValueIndex <= kFixedHuffmanCodeBlockSizeMax)\n  {\n    const UInt32 fixedPrice = TryFixedBlock(tableIndex);\n    t.StaticMode = (fixedPrice < price);\n    if (t.StaticMode)\n      price = fixedPrice;\n  }\n\n  const UInt32 storePrice = GetStorePrice(BlockSizeRes, 0); // bitPosition\n  t.StoreMode = (storePrice <= price);\n  if (t.StoreMode)\n    price = storePrice;\n\n  t.UseSubBlocks = false;\n\n  if (numDivPasses > 1 && numValues >= kDivideCodeBlockSizeMin)\n  {\n    CTables &t0 = m_Tables[(tableIndex << 1)];\n    (CLevels &)t0 = t;\n    t0.BlockSizeRes = t.BlockSizeRes >> 1;\n    t0.m_Pos = t.m_Pos;\n    UInt32 subPrice = GetBlockPrice((tableIndex << 1), numDivPasses - 1);\n\n    UInt32 blockSize2 = t.BlockSizeRes - t0.BlockSizeRes;\n    if (t0.BlockSizeRes >= kDivideBlockSizeMin && blockSize2 >= kDivideBlockSizeMin)\n    {\n      CTables &t1 = m_Tables[(tableIndex << 1) + 1];\n      (CLevels &)t1 = t;\n      t1.BlockSizeRes = blockSize2;\n      t1.m_Pos = m_Pos;\n      m_AdditionalOffset -= t0.BlockSizeRes;\n      subPrice += GetBlockPrice((tableIndex << 1) + 1, numDivPasses - 1);\n      t.UseSubBlocks = (subPrice < price);\n      if (t.UseSubBlocks)\n        price = subPrice;\n    }\n  }\n  \n  m_AdditionalOffset = additionalOffsetEnd;\n  m_Pos = posTemp;\n  return price;\n}\n\nvoid CCoder::CodeBlock(unsigned tableIndex, bool finalBlock)\n{\n  CTables &t = m_Tables[tableIndex];\n  if (t.UseSubBlocks)\n  {\n    CodeBlock((tableIndex << 1), false);\n    CodeBlock((tableIndex << 1) + 1, finalBlock);\n  }\n  else\n  {\n    if (t.StoreMode)\n      WriteStoreBlock(t.BlockSizeRes, m_AdditionalOffset, finalBlock);\n    else\n    {\n      WriteBits((finalBlock ? NFinalBlockField::kFinalBlock: NFinalBlockField::kNotFinalBlock), kFinalBlockFieldSize);\n      if (t.StaticMode)\n      {\n        WriteBits(NBlockType::kFixedHuffman, kBlockTypeFieldSize);\n        TryFixedBlock(tableIndex);\n        unsigned i;\n        const unsigned kMaxStaticHuffLen = 9;\n        for (i = 0; i < kFixedMainTableSize; i++)\n          mainFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.litLenLevels[i]);\n        for (i = 0; i < kFixedDistTableSize; i++)\n          distFreqs[i] = (UInt32)1 << (kMaxStaticHuffLen - m_NewLevels.distLevels[i]);\n        MakeTables(kMaxStaticHuffLen);\n      }\n      else\n      {\n        if (m_NumDivPasses > 1 || m_CheckStatic)\n          TryDynBlock(tableIndex, 1);\n        WriteBits(NBlockType::kDynamicHuffman, kBlockTypeFieldSize);\n        WriteBits(m_NumLitLenLevels - kNumLitLenCodesMin, kNumLenCodesFieldSize);\n        WriteBits(m_NumDistLevels - kNumDistCodesMin, kNumDistCodesFieldSize);\n        WriteBits(m_NumLevelCodes - kNumLevelCodesMin, kNumLevelCodesFieldSize);\n        \n        for (UInt32 i = 0; i < m_NumLevelCodes; i++)\n          WriteBits(m_LevelLevels[i], kLevelFieldSize);\n        \n        Huffman_ReverseBits(levelCodes, levelLens, kLevelTableSize);\n        LevelTableCode(m_NewLevels.litLenLevels, m_NumLitLenLevels, levelLens, levelCodes);\n        LevelTableCode(m_NewLevels.distLevels, m_NumDistLevels, levelLens, levelCodes);\n      }\n      WriteBlock();\n    }\n    m_AdditionalOffset -= t.BlockSizeRes;\n  }\n}\n\n\nHRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */ , const UInt64 * /* outSize */ , ICompressProgressInfo *progress)\n{\n  m_CheckStatic = (m_NumPasses != 1 || m_NumDivPasses != 1);\n  m_IsMultiPass = (m_CheckStatic || (m_NumPasses != 1 || m_NumDivPasses != 1));\n\n  /* we can set stream mode before MatchFinder_Create\n    if default MatchFinder mode was not STREAM_MODE) */\n  // MatchFinder_SET_STREAM_MODE(&_lzInWindow);\n\n  CSeqInStreamWrap _seqInStream;\n  _seqInStream.Init(inStream);\n  MatchFinder_SET_STREAM(&_lzInWindow, &_seqInStream.vt)\n\n  RINOK(Create())\n\n  m_ValueBlockSize = (7 << 10) + (1 << 12) * m_NumDivPasses;\n\n  UInt64 nowPos = 0;\n\n  MatchFinder_Init(&_lzInWindow);\n  m_OutStream.SetStream(outStream);\n  m_OutStream.Init();\n\n  m_OptimumEndIndex = m_OptimumCurrentIndex = 0;\n\n  CTables &t = m_Tables[1];\n  t.m_Pos = 0;\n  t.InitStructures();\n\n  m_AdditionalOffset = 0;\n  do\n  {\n    t.BlockSizeRes = kBlockUncompressedSizeThreshold;\n    m_SecondPass = false;\n    GetBlockPrice(1, m_NumDivPasses);\n    CodeBlock(1, Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) == 0);\n    nowPos += m_Tables[1].BlockSizeRes;\n    if (progress != NULL)\n    {\n      UInt64 packSize = m_OutStream.GetProcessedSize();\n      RINOK(progress->SetRatioInfo(&nowPos, &packSize))\n    }\n  }\n  while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0);\n  \n  if (_seqInStream.Res != S_OK)\n    return _seqInStream.Res;\n\n  if (_lzInWindow.result != SZ_OK)\n    return SResToHRESULT(_lzInWindow.result);\n  return m_OutStream.Flush();\n}\n\nHRESULT CCoder::BaseCode(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\n{\n  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\n  catch(const COutBufferException &e) { return e.ErrorCode; }\n  catch(...) { return E_FAIL; }\n}\n\nZ7_COM7F_IMF(CCOMCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n  { return BaseCode(inStream, outStream, inSize, outSize, progress); }\n\nZ7_COM7F_IMF(CCOMCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\n  { return BaseSetEncoderProperties2(propIDs, props, numProps); }\n\nZ7_COM7F_IMF(CCOMCoder64::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n  { return BaseCode(inStream, outStream, inSize, outSize, progress); }\n\nZ7_COM7F_IMF(CCOMCoder64::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\n  { return BaseSetEncoderProperties2(propIDs, props, numProps); }\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/DeflateEncoder.h",
    "content": "﻿// DeflateEncoder.h\n\n#ifndef ZIP7_INC_DEFLATE_ENCODER_H\n#define ZIP7_INC_DEFLATE_ENCODER_H\n\n#include \"../../../C/LzFind.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"BitlEncoder.h\"\n#include \"DeflateConst.h\"\n\nnamespace NCompress {\nnamespace NDeflate {\nnamespace NEncoder {\n\nstruct CCodeValue\n{\n  UInt16 Len;\n  UInt16 Pos;\n  void SetAsLiteral() { Len = (1 << 15); }\n  bool IsLiteral() const { return (Len >= (1 << 15)); }\n};\n\nstruct COptimal\n{\n  UInt32 Price;\n  UInt16 PosPrev;\n  UInt16 BackPrev;\n};\n\nconst UInt32 kNumOptsBase = 1 << 12;\nconst UInt32 kNumOpts = kNumOptsBase + kMatchMaxLen;\n\nclass CCoder;\n\nstruct CTables: public CLevels\n{\n  bool UseSubBlocks;\n  bool StoreMode;\n  bool StaticMode;\n  UInt32 BlockSizeRes;\n  UInt32 m_Pos;\n  void InitStructures();\n};\n\n\nstruct CEncProps\n{\n  int Level;\n  int algo;\n  int fb;\n  int btMode;\n  UInt32 mc;\n  UInt32 numPasses;\n\n  CEncProps()\n  {\n    Level = -1;\n    mc = 0;\n    algo = fb = btMode = -1;\n    numPasses = (UInt32)(Int32)-1;\n  }\n  void Normalize();\n};\n\nclass CCoder\n{\n  CMatchFinder _lzInWindow;\n  CBitlEncoder m_OutStream;\n\npublic:\n  CCodeValue *m_Values;\n\n  UInt16 *m_MatchDistances;\n  UInt32 m_NumFastBytes;\n  bool _fastMode;\n  bool _btMode;\n\n  UInt16 *m_OnePosMatchesMemory;\n  UInt16 *m_DistanceMemory;\n\n  UInt32 m_Pos;\n\n  unsigned m_NumPasses;\n  unsigned m_NumDivPasses;\n  bool m_CheckStatic;\n  bool m_IsMultiPass;\n  UInt32 m_ValueBlockSize;\n\n  UInt32 m_NumLenCombinations;\n  UInt32 m_MatchMaxLen;\n  const Byte *m_LenStart;\n  const Byte *m_LenDirectBits;\n\n  bool m_Created;\n  bool m_Deflate64Mode;\n\n  Byte m_LevelLevels[kLevelTableSize];\n  unsigned m_NumLitLenLevels;\n  unsigned m_NumDistLevels;\n  UInt32 m_NumLevelCodes;\n  UInt32 m_ValueIndex;\n\n  bool m_SecondPass;\n  UInt32 m_AdditionalOffset;\n\n  UInt32 m_OptimumEndIndex;\n  UInt32 m_OptimumCurrentIndex;\n  \n  Byte  m_LiteralPrices[256];\n  Byte  m_LenPrices[kNumLenSymbolsMax];\n  Byte  m_PosPrices[kDistTableSize64];\n\n  CLevels m_NewLevels;\n  UInt32 mainFreqs[kFixedMainTableSize];\n  UInt32 distFreqs[kDistTableSize64];\n  UInt32 mainCodes[kFixedMainTableSize];\n  UInt32 distCodes[kDistTableSize64];\n  UInt32 levelCodes[kLevelTableSize];\n  Byte levelLens[kLevelTableSize];\n\n  UInt32 BlockSizeRes;\n\n  CTables *m_Tables;\n  COptimal m_Optimum[kNumOpts];\n\n  UInt32 m_MatchFinderCycles;\n\n  void GetMatches();\n  void MovePos(UInt32 num);\n  UInt32 Backward(UInt32 &backRes, UInt32 cur);\n  UInt32 GetOptimal(UInt32 &backRes);\n  UInt32 GetOptimalFast(UInt32 &backRes);\n\n  void LevelTableDummy(const Byte *levels, unsigned numLevels, UInt32 *freqs);\n\n  void WriteBits(UInt32 value, unsigned numBits);\n  void LevelTableCode(const Byte *levels, unsigned numLevels, const Byte *lens, const UInt32 *codes);\n\n  void MakeTables(unsigned maxHuffLen);\n  UInt32 GetLzBlockPrice() const;\n  void TryBlock();\n  UInt32 TryDynBlock(unsigned tableIndex, UInt32 numPasses);\n\n  UInt32 TryFixedBlock(unsigned tableIndex);\n\n  void SetPrices(const CLevels &levels);\n  void WriteBlock();\n\n  HRESULT Create();\n  void Free();\n\n  void WriteStoreBlock(UInt32 blockSize, UInt32 additionalOffset, bool finalBlock);\n  void WriteTables(bool writeMode, bool finalBlock);\n  \n  void WriteBlockData(bool writeMode, bool finalBlock);\n\n  UInt32 GetBlockPrice(unsigned tableIndex, unsigned numDivPasses);\n  void CodeBlock(unsigned tableIndex, bool finalBlock);\n\n  void SetProps(const CEncProps *props2);\npublic:\n  CCoder(bool deflate64Mode = false);\n  ~CCoder();\n\n  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\n\n  HRESULT BaseCode(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\n\n  HRESULT BaseSetEncoderProperties2(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);\n};\n\n\nclass CCOMCoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetCoderProperties,\n  public CMyUnknownImp,\n  public CCoder\n{\n  Z7_IFACES_IMP_UNK_2(ICompressCoder, ICompressSetCoderProperties)\npublic:\n  CCOMCoder(): CCoder(false) {}\n};\n\nclass CCOMCoder64 Z7_final:\n  public ICompressCoder,\n  public ICompressSetCoderProperties,\n  public CMyUnknownImp,\n  public CCoder\n{\n  Z7_IFACES_IMP_UNK_2(ICompressCoder, ICompressSetCoderProperties)\npublic:\n  CCOMCoder64(): CCoder(true) {}\n};\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/DeflateRegister.cpp",
    "content": "﻿// DeflateRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"DeflateDecoder.h\"\n#if !defined(Z7_EXTRACT_ONLY) && !defined(Z7_DEFLATE_EXTRACT_ONLY)\n#include \"DeflateEncoder.h\"\n#endif\n\nnamespace NCompress {\nnamespace NDeflate {\n\nREGISTER_CODEC_CREATE(CreateDec, NDecoder::CCOMCoder)\n\n#if !defined(Z7_EXTRACT_ONLY) && !defined(Z7_DEFLATE_EXTRACT_ONLY)\nREGISTER_CODEC_CREATE(CreateEnc, NEncoder::CCOMCoder)\n#else\n#define CreateEnc NULL\n#endif\n\nREGISTER_CODEC_2(Deflate, CreateDec, CreateEnc, 0x40108, \"Deflate\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/DeltaFilter.cpp",
    "content": "﻿// DeltaFilter.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Delta.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\nnamespace NCompress {\nnamespace NDelta {\n\nstruct CDelta\n{\n  unsigned _delta;\n  Byte _state[DELTA_STATE_SIZE];\n\n  CDelta(): _delta(1) {}\n  void DeltaInit() { Delta_Init(_state); }\n};\n\n\n#ifndef Z7_EXTRACT_ONLY\n\nclass CEncoder Z7_final:\n  public ICompressFilter,\n  public ICompressSetCoderProperties,\n  public ICompressWriteCoderProperties,\n  public CMyUnknownImp,\n  CDelta\n{\n  Z7_IFACES_IMP_UNK_3(\n      ICompressFilter,\n      ICompressSetCoderProperties,\n      ICompressWriteCoderProperties)\n};\n\nZ7_COM7F_IMF(CEncoder::Init())\n{\n  DeltaInit();\n  return S_OK;\n}\n\nZ7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size))\n{\n  Delta_Encode(_state, _delta, data, size);\n  return size;\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\n{\n  unsigned delta = _delta;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = props[i];\n    const PROPID propID = propIDs[i];\n    if (propID >= NCoderPropID::kReduceSize)\n      continue;\n    if (prop.vt != VT_UI4)\n      return E_INVALIDARG;\n    switch (propID)\n    {\n      case NCoderPropID::kDefaultProp:\n        if (prop.ulVal < 1 || prop.ulVal > 256)\n          return E_INVALIDARG;\n        delta = prop.ulVal;\n        break;\n      case NCoderPropID::kNumThreads: break;\n      case NCoderPropID::kLevel: break;\n      default: return E_INVALIDARG;\n    }\n  }\n  _delta = delta;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))\n{\n  const Byte prop = (Byte)(_delta - 1);\n  return outStream->Write(&prop, 1, NULL);\n}\n\n#endif\n\n\nclass CDecoder Z7_final:\n  public ICompressFilter,\n  public ICompressSetDecoderProperties2,\n  public CMyUnknownImp,\n  CDelta\n{\n  Z7_IFACES_IMP_UNK_2(\n      ICompressFilter,\n      ICompressSetDecoderProperties2)\n};\n\nZ7_COM7F_IMF(CDecoder::Init())\n{\n  DeltaInit();\n  return S_OK;\n}\n\nZ7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))\n{\n  Delta_Decode(_state, _delta, data, size);\n  return size;\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size))\n{\n  if (size != 1)\n    return E_INVALIDARG;\n  _delta = (unsigned)props[0] + 1;\n  return S_OK;\n}\n\n\nREGISTER_FILTER_E(Delta,\n    CDecoder(),\n    CEncoder(),\n    3, \"Delta\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/HuffmanDecoder.h",
    "content": "﻿// Compress/HuffmanDecoder.h\n\n#ifndef ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H\n#define ZIP7_INC_COMPRESS_HUFFMAN_DECODER_H\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../Common/MyTypes.h\"\n\nnamespace NCompress {\nnamespace NHuffman {\n\n// const unsigned kNumTableBits_Default = 9;\n\n#if 0 || 0 && defined(MY_CPU_64BIT)\n// for debug or optimization:\n// 64-BIT limit array can be faster for some compilers.\n// for debug or optimization:\n#define Z7_HUFF_USE_64BIT_LIMIT\n#else\n// sizet value variable allows to eliminate some move operation in some compilers.\n// for debug or optimization:\n// #define Z7_HUFF_USE_SIZET_VALUE\n#endif\n\n// v0 must normalized to (32 bits) : (v0 < ((UInt64)1 << 32))\n\n#ifdef Z7_HUFF_USE_64BIT_LIMIT\n  typedef UInt64 CLimitInt;\n  typedef UInt64 CValueInt;\n  // all _limits[*] are normalized and limited by ((UInt64)1 << 32).\n  // we don't use (v1) in this branch\n  #define Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax)  32\n  #define Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1) \\\n      ((NCompress::NHuffman::CLimitInt)v0 >= (huf)->_limits[0])\n  #define Z7_HUFF_GET_VAL_FOR_LIMITS(v0, v1, kNumBitsMax, kNumTableBits)  (v0)\n  #define Z7_HUFF_GET_VAL_FOR_TABLE( v0, v1, kNumBitsMax, kNumTableBits)  ((v0) >> (32 - kNumTableBits))\n  #define Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1)\n#else\n  typedef UInt32 CLimitInt;\n  typedef\n    #ifdef Z7_HUFF_USE_SIZET_VALUE\n      size_t\n    #else\n      UInt32\n    #endif\n      CValueInt;\n  // v1 must be precalculated from v0 in this branch\n  // _limits[0] and (v1) are normalized and limited by (1 << kNumTableBits).\n  // _limits[non_0]      are normalized and limited by (1 << kNumBitsMax).\n  #define Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax)  (kNumBitsMax)\n  #define Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1) \\\n      ((NCompress::NHuffman::CLimitInt)v1 >= (huf)->_limits[0])\n  #define Z7_HUFF_GET_VAL_FOR_LIMITS(v0, v1, kNumBitsMax, kNumTableBits)  ((v0) >> (32 - kNumBitsMax))\n  #define Z7_HUFF_GET_VAL_FOR_TABLE( v0, v1, kNumBitsMax, kNumTableBits)  (v1)\n  #define Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1)  const UInt32 v1 = ((v0) >> (32 - kNumTableBits));\n#endif\n\n\nenum enum_BuildMode\n{\n  k_BuildMode_Partial       = 0,\n  k_BuildMode_Full          = 1,\n  k_BuildMode_Full_or_Empty = 2\n};\n\n\ntemplate <class symType, class symType2, class symType4, unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = kNumTableBits_Default */>\nstruct CDecoderBase\n{\n  CLimitInt _limits[kNumBitsMax + 2 - kNumTableBits];\n  UInt32 _poses[kNumBitsMax - kNumTableBits]; // unsigned\nunion\n{\n  // if  defined(MY_CPU_64BIT), we need 64-bit alignment for _symbols.\n  // if !defined(MY_CPU_64BIT), we need 32-bit alignment for _symbols\n  // but we provide alignment for _lens.\n  // _symbols also will be aligned, if _lens are aligned\n  #if defined(MY_CPU_64BIT)\n    UInt64\n  #else\n    UInt32\n  #endif\n    _pad_align[m_NumSymbols < (1u << sizeof(symType) * 8) ? 1 : -1];\n  /* if symType is Byte, we use 16-bytes padding to avoid cache\n     bank conflict between _lens and _symbols: */\n  Byte _lens[(1 << kNumTableBits) + (sizeof(symType) == 1 ? 16 : 0)];\n} _u;\n  symType _symbols[(1 << kNumTableBits) + m_NumSymbols - (kNumTableBits + 1)];\n\n  /*\n  Z7_FORCE_INLINE\n  bool IsFull() const\n  {\n    return _limits[kNumBitsMax - kNumTableBits] ==\n        (CLimitInt)1u << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax);\n  }\n  Z7_FORCE_INLINE\n  bool IsEmpty() const\n  {\n    return _limits[kNumBitsMax - kNumTableBits] == 0;\n  }\n  Z7_FORCE_INLINE\n  bool Is_Full_or_Empty() const\n  {\n    return 0 == (_limits[kNumBitsMax - kNumTableBits] &\n        ~((CLimitInt)1 << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax)));\n  }\n  */\n\n  Z7_FORCE_INLINE\n  bool Build(const Byte *lens, enum_BuildMode buidMode = k_BuildMode_Partial) throw()\n  {\n    unsigned counts[kNumBitsMax + 1];\n    size_t i;\n    for (i = 0; i <= kNumBitsMax; i++)\n      counts[i] = 0;\n    for (i = 0; i < m_NumSymbols; i++)\n      counts[lens[i]]++;\n    \n    UInt32 sum = 0;\n    for (i = 1; i <= kNumTableBits; i++)\n    {\n      sum <<= 1;\n      sum += counts[i];\n    }\n\n    CLimitInt startPos = (CLimitInt)sum;\n    _limits[0] =\n      #ifdef Z7_HUFF_USE_64BIT_LIMIT\n          startPos << (Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - kNumTableBits);\n      #else\n          startPos;\n      #endif\n\n    for (i = kNumTableBits + 1; i <= kNumBitsMax; i++)\n    {\n      startPos <<= 1;\n      _poses[i - (kNumTableBits + 1)] = (UInt32)(startPos - sum);\n      const unsigned cnt = counts[i];\n      counts[i] = sum;\n      sum += cnt;\n      startPos += cnt;\n      _limits[i - kNumTableBits] = startPos << (Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - i);\n    }\n\n    _limits[kNumBitsMax + 1 - kNumTableBits] =\n        (CLimitInt)1 << Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax);\n\n    if (buidMode == k_BuildMode_Partial)\n    {\n      if (startPos > (1u << kNumBitsMax)) return false;\n    }\n    else\n    {\n      if (buidMode != k_BuildMode_Full && startPos == 0) return true;\n      if (startPos != (1u << kNumBitsMax)) return false;\n    }\n    size_t sum2 = 0;\n    for (i = 1; i <= kNumTableBits; i++)\n    {\n      const unsigned cnt = counts[i] << (kNumTableBits - i);\n      counts[i] = (unsigned)sum2 >> (kNumTableBits - i);\n      memset(_u._lens + sum2, (int)i, cnt);\n      sum2 += cnt;\n    }\n    \n#ifdef MY_CPU_64BIT\n    symType4\n    // UInt64 // for symType = UInt16\n    // UInt32 // for symType = Byte\n#else\n    UInt32\n#endif\n    v = 0;\n    for (i = 0; i < m_NumSymbols; i++,\n      v +=\n          1\n          + (  (UInt32)1 << (sizeof(symType) * 8 * 1))\n          // 0x00010001 // for symType = UInt16\n          // 0x00000101 // for symType = Byte\n#ifdef MY_CPU_64BIT\n          + ((symType4)1 << (sizeof(symType) * 8 * 2))\n          + ((symType4)1 << (sizeof(symType) * 8 * 3))\n          // 0x0001000100010001 // for symType = UInt16\n          // 0x0000000001010101 // for symType = Byte\n#endif\n      )\n    {\n      const unsigned len = lens[i];\n      if (len == 0)\n        continue;\n      const size_t offset = counts[len];\n      counts[len] = (unsigned)offset + 1;\n      if (len >= kNumTableBits)\n        _symbols[offset] = (symType)v;\n      else\n      {\n        Byte *s2 = (Byte *)(void *)_symbols + (offset <<\n            (kNumTableBits + sizeof(symType) / 2 - len));\n        Byte *lim = s2 + ((size_t)1 <<\n            (kNumTableBits + sizeof(symType) / 2 - len));\n        if (len >= kNumTableBits - 2)\n        {\n          *(symType2 *)(void *)(s2                       ) = (symType2)v;\n          *(symType2 *)(void *)(lim - sizeof(symType) * 2) = (symType2)v;\n        }\n        else\n        {\n#ifdef MY_CPU_64BIT\n          symType4 *s = (symType4 *)(void *)s2;\n          do\n          {\n            s[0] = v;  s[1] = v;  s += 2;\n          }\n          while (s != (const symType4 *)(const void *)lim);\n#else\n          symType2 *s = (symType2 *)(void *)s2;\n          do\n          {\n            s[0] = (symType2)v;  s[1] = (symType2)v;  s += 2;\n            s[0] = (symType2)v;  s[1] = (symType2)v;  s += 2;\n          }\n          while (s != (const symType2 *)(const void *)lim);\n#endif\n        }\n      }\n    }\n    return true;\n  }\n\n\n#define Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES(_numBits_, kNumBitsMax, error_op)  if (_numBits_ > kNumBitsMax) { error_op }\n#define Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO( _numBits_, kNumBitsMax, error_op)\n\n  \n#define Z7_HUFF_DECODE_BASE_TREE_BRANCH(sym, huf, kNumBitsMax, kNumTableBits,  \\\n      v0, v1, \\\n      get_val_for_limits, \\\n      check_op, error_op, _numBits_) \\\n{ \\\n    const NHuffman::CValueInt _val = get_val_for_limits(v0, v1, kNumBitsMax, kNumTableBits); \\\n    _numBits_ = kNumTableBits + 1; \\\n    if ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[1]) \\\n    do { _numBits_++; } \\\n    while ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[_numBits_ - kNumTableBits]); \\\n    check_op(_numBits_, kNumBitsMax, error_op) \\\n    sym = (huf)->_symbols[(/* (UInt32) */ (_val >> ((Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - (unsigned)_numBits_)))) \\\n        - (huf)->_poses[_numBits_ - (kNumTableBits + 1)]]; \\\n}\n\n/*\n    Z7_HUFF_DECODE_BASE_TREE_BRANCH(sym, huf, kNumBitsMax, kNumTableBits,  \\\n      v0, v1, \\\n      get_val_for_limits, \\\n      check_op, error_op, _numBits_) \\\n\n*/\n\n#define Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits,  \\\n      v0, v1, \\\n      get_val_for_table, get_val_for_limits, \\\n      check_op, error_op, move_pos_op, after_op, bs) \\\n{ \\\n  if (Z7_HUFF_TABLE_COMPARE(huf, kNumTableBits, v0, v1)) \\\n  { \\\n    const NHuffman::CValueInt _val = get_val_for_limits(v0, v1, kNumBitsMax, kNumTableBits); \\\n    size_t _numBits_ = kNumTableBits + 1; \\\n    if ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[1]) \\\n    do { _numBits_++; } \\\n    while ((NCompress::NHuffman::CLimitInt)_val >= (huf)->_limits[_numBits_ - kNumTableBits]); \\\n    check_op(_numBits_, kNumBitsMax, error_op) \\\n    sym = (huf)->_symbols[(/* (UInt32) */ (_val >> ((Z7_HUFF_NUM_LIMIT_BITS(kNumBitsMax) - (unsigned)_numBits_)))) \\\n        - (huf)->_poses[_numBits_ - (kNumTableBits + 1)]]; \\\n    move_pos_op(bs, _numBits_); \\\n  } \\\n  else \\\n  { \\\n    const size_t _val = get_val_for_table(v0, v1, kNumBitsMax, kNumTableBits); \\\n    const size_t _numBits_ = (huf)->_u._lens[_val]; \\\n    sym = (huf)->_symbols[_val]; \\\n    move_pos_op(bs, _numBits_); \\\n  } \\\n  after_op \\\n}\n\n#define Z7_HUFF_DECODE_10(sym, huf, kNumBitsMax, kNumTableBits,  \\\n      v0, v1, \\\n      check_op, error_op, move_pos_op, after_op, bs) \\\n    Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits,  \\\n      v0, v1, \\\n      Z7_HUFF_GET_VAL_FOR_TABLE, \\\n      Z7_HUFF_GET_VAL_FOR_LIMITS, \\\n      check_op, error_op, move_pos_op, after_op, bs) \\\n\n\n#define Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huf, kNumBitsMax, kNumTableBits,  \\\n      v0, \\\n      check_op, error_op, move_pos_op, after_op, bs) \\\n{ \\\n    Z7_HUFF_PRECALC_V1(kNumTableBits, v0, _v1_temp) \\\n    Z7_HUFF_DECODE_10(sym, huf, kNumBitsMax, kNumTableBits,  \\\n      v0, _v1_temp, \\\n      check_op, error_op, move_pos_op, after_op, bs) \\\n}\n\n#if 0 || defined(Z7_HUFF_USE_64BIT_LIMIT)\n// this branch uses bitStream->GetValue_InHigh32bits().\n#define Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, \\\n      check_op, error_op, move_pos_op) \\\n{ \\\n  const UInt32 v0 = (bitStream)->GetValue_InHigh32bits(); \\\n  Z7_HUFF_PRECALC_V1(kNumTableBits, v0, v1); \\\n  Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \\\n      v0, v1,  \\\n      Z7_HUFF_GET_VAL_FOR_TABLE, \\\n      Z7_HUFF_GET_VAL_FOR_LIMITS, \\\n       check_op, error_op, move_pos_op, {}, bitStream) \\\n}\n#else\n/*\nthis branch uses bitStream->GetValue().\nSo we use SIMPLE versions for v0, v1 calculation:\n  v0 is normalized for kNumBitsMax\n  v1 is normalized for kNumTableBits\n*/\n#define Z7_HUFF_GET_VAL_FOR_LIMITS_SIMPLE(v0, v1, kNumBitsMax, kNumTableBits)  v0\n#define Z7_HUFF_GET_VAL_FOR_TABLE_SIMPLE( v0, v1, kNumBitsMax, kNumTableBits)  v1\n#define Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, move_pos_op) \\\n{ \\\n  const UInt32 v0 = (bitStream)->GetValue(kNumBitsMax); \\\n  const UInt32 v1 = v0 >> (kNumBitsMax - kNumTableBits); \\\n  Z7_HUFF_DECODE_BASE(sym, huf, kNumBitsMax, kNumTableBits, \\\n      v0, v1,  \\\n      Z7_HUFF_GET_VAL_FOR_TABLE_SIMPLE, \\\n      Z7_HUFF_GET_VAL_FOR_LIMITS_SIMPLE, \\\n      check_op, error_op, move_pos_op, {}, bitStream) \\\n}\n#endif\n\n#define Z7_HUFF_bitStream_MovePos(bitStream, numBits)  (bitStream)->MovePos((unsigned)(numBits))\n\n#define Z7_HUFF_DECODE_1(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op) \\\n        Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, \\\n          Z7_HUFF_bitStream_MovePos)\n\n// MovePosCheck\n\n#define Z7_HUFF_DECODE_2(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op) \\\n        Z7_HUFF_DECODE_0(sym, huf, kNumBitsMax, kNumTableBits, bitStream, check_op, error_op, \\\n          Z7_HUFF_bitStream_MovePos)\n\n// MovePosCheck\n\n#define Z7_HUFF_DECODE_CHECK(sym, huf, kNumBitsMax, kNumTableBits, bitStream, error_op) \\\n        Z7_HUFF_DECODE_1(    sym, huf, kNumBitsMax, kNumTableBits, bitStream, \\\n        Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES, error_op)\n\n  template <class TBitDecoder>\n  Z7_FORCE_INLINE\n  bool Decode2(TBitDecoder *bitStream, unsigned &sym) const\n  {\n    Z7_HUFF_DECODE_CHECK(sym, this, kNumBitsMax, kNumTableBits, bitStream,\n      { return false; }\n    )\n    return true;\n  }\n\n  template <class TBitDecoder>\n  Z7_FORCE_INLINE\n  bool Decode_SymCheck_MovePosCheck(TBitDecoder *bitStream, unsigned &sym) const\n  {\n    Z7_HUFF_DECODE_0(sym, this, kNumBitsMax, kNumTableBits, bitStream,\n      Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES,\n      { return false; },\n      { return (bitStream)->MovePosCheck; }\n    )\n  }\n\n  template <class TBitDecoder>\n  Z7_FORCE_INLINE\n  unsigned Decode(TBitDecoder *bitStream) const\n  {\n    unsigned sym;\n    Z7_HUFF_DECODE_CHECK(sym, this, kNumBitsMax, kNumTableBits, bitStream,\n      { return (unsigned)(int)(Int32)0xffffffff; }\n    )\n    return sym;\n  }\n\n  \n  template <class TBitDecoder>\n  Z7_FORCE_INLINE\n  unsigned DecodeFull(TBitDecoder *bitStream) const\n  {\n    /*\n    const UInt32 val = bitStream->GetValue(kNumBitsMax);\n    if (val < _limits[kNumTableBits])\n    {\n      const unsigned pair = _u._lens[(size_t)(val >> (kNumBitsMax - kNumTableBits))];\n      bitStream->MovePos(pair & kPairLenMask);\n      return pair >> kNumPairLenBits;\n    }\n\n    unsigned numBits;\n    for (numBits = kNumTableBits + 1; val >= _limits[numBits]; numBits++);\n    \n    bitStream->MovePos(numBits);\n    return _symbols[_poses[numBits] + (unsigned)\n        ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits))];\n    */\n    unsigned sym;\n    Z7_HUFF_DECODE_2(sym, this, kNumBitsMax, kNumTableBits, bitStream,\n      Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {}\n    )\n    return sym;\n  }\n};\n\n\ntemplate <unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = kNumTableBits_Default */>\nstruct CDecoder: public CDecoderBase\n  <UInt16, UInt32, UInt64, kNumBitsMax, m_NumSymbols, kNumTableBits> {};\n\ntemplate <unsigned kNumBitsMax, unsigned m_NumSymbols, unsigned kNumTableBits /* = 7 */>\nstruct CDecoder256: public CDecoderBase\n  <Byte, UInt16, UInt32, kNumBitsMax, m_NumSymbols, kNumTableBits> {};\n\n\ntemplate <unsigned numSymbols>\nclass CDecoder7b\n{\npublic:\n  Byte _lens[1 << 7];\n\n  bool Build(const Byte *lens, bool full) throw()\n  {\n    const unsigned kNumBitsMax = 7;\n    \n    unsigned counts[kNumBitsMax + 1];\n    unsigned _poses[kNumBitsMax + 1];\n    unsigned _limits[kNumBitsMax + 1];\n    unsigned i;\n    for (i = 0; i <= kNumBitsMax; i++)\n      counts[i] = 0;\n    for (i = 0; i < numSymbols; i++)\n      counts[lens[i]]++;\n    \n    _limits[0] = 0;\n    const unsigned kMaxValue = 1u << kNumBitsMax;\n    unsigned startPos = 0;\n    unsigned sum = 0;\n    \n    for (i = 1; i <= kNumBitsMax; i++)\n    {\n      const unsigned cnt = counts[i];\n      startPos += cnt << (kNumBitsMax - i);\n      _limits[i] = startPos;\n      counts[i] = sum;\n      _poses[i] = sum;\n      sum += cnt;\n    }\n\n    counts[0] = sum;\n    _poses[0] = sum;\n\n    if (full)\n    {\n      if (startPos != kMaxValue)\n        return false;\n    }\n    else\n    {\n      if (startPos > kMaxValue)\n        return false;\n    }\n\n\n    for (i = 0; i < numSymbols; i++)\n    {\n      const unsigned len = lens[i];\n      if (len == 0)\n        continue;\n      const unsigned offset = counts[len]++;\n      {\n        Byte *dest = _lens + _limits[(size_t)len - 1]\n            + ((offset - _poses[len]) << (kNumBitsMax - len));\n        const unsigned num = (unsigned)1 << (kNumBitsMax - len);\n        const unsigned val = (i << 3) + len;\n        for (unsigned k = 0; k < num; k++)\n          dest[k] = (Byte)val;\n      }\n    }\n\n    if (!full)\n    {\n      const unsigned limit = _limits[kNumBitsMax];\n      const unsigned num = ((unsigned)1 << kNumBitsMax) - limit;\n      Byte *dest = _lens + limit;\n      for (unsigned k = 0; k < num; k++)\n        dest[k] = (Byte)\n          // (0x1f << 3);\n          ((0x1f << 3) + 0x7);\n    }\n    \n    return true;\n  }\n\n#define Z7_HUFF_DECODER_7B_DECODE(dest, huf, get_val, move_pos, bs) \\\n  { \\\n    const unsigned pair = huf->_lens[(size_t)get_val(7)]; \\\n    const unsigned numBits = pair & 0x7; \\\n    move_pos(bs, numBits); \\\n    dest = pair >> 3; \\\n  }\n\n  template <class TBitDecoder>\n  unsigned Decode(TBitDecoder *bitStream) const\n  {\n    const unsigned pair = _lens[(size_t)bitStream->GetValue(7)];\n    bitStream->MovePos(pair & 0x7);\n    return pair >> 3;\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ImplodeDecoder.cpp",
    "content": "﻿// ImplodeDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../Common/Defs.h\"\n\n#include \"ImplodeDecoder.h\"\n\nnamespace NCompress {\nnamespace NImplode {\nnamespace NDecoder {\n\nbool CHuffmanDecoder::Build(const Byte *lens, unsigned numSymbols) throw()\n{\n  unsigned counts[kNumHuffmanBits + 1];\n  unsigned i;\n  for (i = 0; i <= kNumHuffmanBits; i++)\n    counts[i] = 0;\n  for (i = 0; i < numSymbols; i++)\n    counts[lens[i]]++;\n\n  const UInt32 kMaxValue = (UInt32)1 << kNumHuffmanBits;\n  // _limits[0] = kMaxValue;\n  UInt32 startPos = kMaxValue;\n  unsigned sum = 0;\n\n  for (i = 1; i <= kNumHuffmanBits; i++)\n  {\n    const unsigned cnt = counts[i];\n    const UInt32 range = (UInt32)cnt << (kNumHuffmanBits - i);\n    if (startPos < range)\n      return false;\n    startPos -= range;\n    _limits[i] = startPos;\n    _poses[i] = sum;\n    sum += cnt;\n    counts[i] = sum;\n  }\n  // counts[0] += sum;\n  if (startPos != 0)\n    return false;\n  for (i = 0; i < numSymbols; i++)\n  {\n    const unsigned len = lens[i];\n    if (len != 0)\n      _symbols[--counts[len]] = (Byte)i;\n  }\n  return true;\n}\n\n\nunsigned CHuffmanDecoder::Decode(CInBit *inStream) const throw()\n{\n  const UInt32 val = inStream->GetValue(kNumHuffmanBits);\n  size_t numBits;\n  for (numBits = 1; val < _limits[numBits]; numBits++);\n  const unsigned sym = _symbols[_poses[numBits]\n      + (unsigned)((val - _limits[numBits]) >> (kNumHuffmanBits - numBits))];\n  inStream->MovePos(numBits);\n  return sym;\n}\n\n\n\nstatic const unsigned kNumLenDirectBits = 8;\n\nstatic const unsigned kNumDistDirectBitsSmall = 6;\nstatic const unsigned kNumDistDirectBitsBig = 7;\n\nstatic const unsigned kLitTableSize = (1 << 8);\nstatic const unsigned kDistTableSize = 64;\nstatic const unsigned kLenTableSize = 64;\n\nstatic const UInt32 kHistorySize = (1 << kNumDistDirectBitsBig) * kDistTableSize; // 8 KB\n\n\nCCoder::CCoder():\n  _flags(0),\n  _fullStreamMode(false)\n{}\n\n\nbool CCoder::BuildHuff(CHuffmanDecoder &decoder, unsigned numSymbols)\n{\n  Byte levels[kMaxHuffTableSize];\n  unsigned numRecords = (unsigned)_inBitStream.ReadAlignedByte() + 1;\n  unsigned index = 0;\n  do\n  {\n    const unsigned b = (unsigned)_inBitStream.ReadAlignedByte();\n    const unsigned level = (b & 0xF) + 1;\n    const unsigned rep = ((unsigned)b >> 4) + 1;\n    if (index + rep > numSymbols)\n      return false;\n    for (unsigned j = 0; j < rep; j++)\n      levels[index++] = (Byte)level;\n  }\n  while (--numRecords);\n\n  if (index != numSymbols)\n    return false;\n  return decoder.Build(levels, numSymbols);\n}\n\n\nHRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\n{\n  if (!_inBitStream.Create(1 << 18))\n    return E_OUTOFMEMORY;\n  if (!_outWindowStream.Create(kHistorySize << 1)) // 16 KB\n    return E_OUTOFMEMORY;\n  if (!outSize)\n    return E_INVALIDARG;\n\n  _outWindowStream.SetStream(outStream);\n  _outWindowStream.Init(false);\n  _inBitStream.SetStream(inStream);\n  _inBitStream.Init();\n\n  const unsigned numDistDirectBits = (_flags & 2) ?\n      kNumDistDirectBitsBig:\n      kNumDistDirectBitsSmall;\n  const bool literalsOn = ((_flags & 4) != 0);\n  const UInt32 minMatchLen = (literalsOn ? 3 : 2);\n\n  if (literalsOn)\n    if (!BuildHuff(_litDecoder, kLitTableSize))\n      return S_FALSE;\n  if (!BuildHuff(_lenDecoder, kLenTableSize))\n    return S_FALSE;\n  if (!BuildHuff(_distDecoder, kDistTableSize))\n    return S_FALSE;\n \n  UInt64 prevProgress = 0;\n  bool moreOut = false;\n  UInt64 pos = 0, unPackSize = *outSize;\n\n  while (pos < unPackSize)\n  {\n    if (pos - prevProgress >= (1u << 18) && progress)\n    {\n      prevProgress = pos;\n      const UInt64 packSize = _inBitStream.GetProcessedSize();\n      RINOK(progress->SetRatioInfo(&packSize, &pos))\n    }\n\n    if (_inBitStream.ReadBits(1) != 0)\n    {\n      Byte b;\n      if (literalsOn)\n      {\n        const unsigned sym = _litDecoder.Decode(&_inBitStream);\n        // if (sym >= kLitTableSize) break;\n        b = (Byte)sym;\n      }\n      else\n        b = (Byte)_inBitStream.ReadBits(8);\n      _outWindowStream.PutByte(b);\n      pos++;\n    }\n    else\n    {\n      const UInt32 lowDistBits = _inBitStream.ReadBits(numDistDirectBits);\n      UInt32 dist = (UInt32)_distDecoder.Decode(&_inBitStream);\n      // if (dist >= kDistTableSize) break;\n      dist = (dist << numDistDirectBits) + lowDistBits;\n      unsigned len = _lenDecoder.Decode(&_inBitStream);\n      // if (len >= kLenTableSize) break;\n      if (len == kLenTableSize - 1)\n        len += _inBitStream.ReadBits(kNumLenDirectBits);\n      len += minMatchLen;\n      {\n        const UInt64 limit = unPackSize - pos;\n        // limit != 0\n        if (len > limit)\n        {\n          moreOut = true;\n          len = (UInt32)limit;\n        }\n      }\n      do\n      {\n        // len != 0\n        if (dist < pos)\n        {\n          _outWindowStream.CopyBlock(dist, len);\n          pos += len;\n          break;\n        }\n        _outWindowStream.PutByte(0);\n        pos++;\n      }\n      while (--len);\n    }\n  }\n\n  HRESULT res = _outWindowStream.Flush();\n\n  if (res == S_OK)\n  {\n    if (_fullStreamMode)\n    {\n      if (moreOut)\n        res = S_FALSE;\n      if (inSize && *inSize != _inBitStream.GetProcessedSize())\n        res = S_FALSE;\n    }\n    if (pos != unPackSize)\n      res = S_FALSE;\n  }\n\n  return res;\n}\n\n\nZ7_COM7F_IMF(CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  try { return CodeReal(inStream, outStream, inSize, outSize, progress);  }\n  // catch(const CInBufferException &e)  { return e.ErrorCode; }\n  // catch(const CLzOutWindowException &e) { return e.ErrorCode; }\n  catch(const CSystemException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\n\nZ7_COM7F_IMF(CCoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n{\n  if (size == 0)\n    return E_NOTIMPL;\n  _flags = data[0];\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCoder::SetFinishMode(UInt32 finishMode))\n{\n  _fullStreamMode = (finishMode != 0);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CCoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = _inBitStream.GetProcessedSize();\n  return S_OK;\n}\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ImplodeDecoder.h",
    "content": "﻿// ImplodeDecoder.h\n\n#ifndef ZIP7_INC_COMPRESS_IMPLODE_DECODER_H\n#define ZIP7_INC_COMPRESS_IMPLODE_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n\n#include \"BitlDecoder.h\"\n#include \"LzOutWindow.h\"\n\nnamespace NCompress {\nnamespace NImplode {\nnamespace NDecoder {\n\ntypedef NBitl::CDecoder<CInBuffer> CInBit;\n\nconst unsigned kNumHuffmanBits = 16;\nconst unsigned kMaxHuffTableSize = 1 << 8;\n\nclass CHuffmanDecoder\n{\n  UInt32 _limits[kNumHuffmanBits + 1];\n  UInt32 _poses[kNumHuffmanBits + 1];\n  Byte _symbols[kMaxHuffTableSize];\npublic:\n  bool Build(const Byte *lens, unsigned numSymbols) throw();\n  unsigned Decode(CInBit *inStream) const throw();\n};\n\n\nZ7_CLASS_IMP_NOQIB_4(\n  CCoder\n  , ICompressCoder\n  , ICompressSetDecoderProperties2\n  , ICompressSetFinishMode\n  , ICompressGetInStreamProcessedSize\n)\n  Byte _flags;\n  bool _fullStreamMode;\n\n  CLzOutWindow _outWindowStream;\n  CInBit _inBitStream;\n  \n  CHuffmanDecoder _litDecoder;\n  CHuffmanDecoder _lenDecoder;\n  CHuffmanDecoder _distDecoder;\n\n  bool BuildHuff(CHuffmanDecoder &table, unsigned numSymbols);\n  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\npublic:\n  CCoder();\n};\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzOutWindow.cpp",
    "content": "﻿// LzOutWindow.cpp\n\n#include \"StdAfx.h\"\n\n#include \"LzOutWindow.h\"\n\nvoid CLzOutWindow::Init(bool solid) throw()\n{\n  if (!solid)\n    COutBuffer::Init();\n  #ifdef Z7_NO_EXCEPTIONS\n  ErrorCode = S_OK;\n  #endif\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzOutWindow.h",
    "content": "﻿// LzOutWindow.h\n\n#ifndef ZIP7_INC_LZ_OUT_WINDOW_H\n#define ZIP7_INC_LZ_OUT_WINDOW_H\n\n#include \"../Common/OutBuffer.h\"\n\n#ifndef Z7_NO_EXCEPTIONS\ntypedef COutBufferException CLzOutWindowException;\n#endif\n\nclass CLzOutWindow: public COutBuffer\n{\npublic:\n  void Init(bool solid = false) throw();\n  \n  // distance >= 0, len > 0,\n  bool CopyBlock(UInt32 distance, UInt32 len)\n  {\n    UInt32 pos = _pos - distance - 1;\n    if (distance >= _pos)\n    {\n      if (!_overDict || distance >= _bufSize)\n        return false;\n      pos += _bufSize;\n    }\n    if (_limitPos - _pos > len && _bufSize - pos > len)\n    {\n      const Byte *src = _buf + pos;\n      Byte *dest = _buf + _pos;\n      _pos += len;\n      do\n        *dest++ = *src++;\n      while (--len != 0);\n    }\n    else do\n    {\n      UInt32 pos2;\n      if (pos == _bufSize)\n        pos = 0;\n      pos2 = _pos;\n      _buf[pos2++] = _buf[pos++];\n      _pos = pos2;\n      if (pos2 == _limitPos)\n        FlushWithCheck();\n    }\n    while (--len != 0);\n    return true;\n  }\n  \n  void PutByte(Byte b)\n  {\n    UInt32 pos = _pos;\n    _buf[pos++] = b;\n    _pos = pos;\n    if (pos == _limitPos)\n      FlushWithCheck();\n  }\n\n  void PutBytes(const Byte *data, UInt32 size)\n  {\n    if (size == 0)\n      return;\n    UInt32 pos = _pos;\n    Byte *buf = _buf;\n    buf[pos++] = *data++;\n    size--;\n    for (;;)\n    {\n      UInt32 limitPos = _limitPos;\n      UInt32 rem = limitPos - pos;\n      if (rem == 0)\n      {\n        _pos = pos;\n        FlushWithCheck();\n        pos = _pos;\n        continue;\n      }\n      \n      if (size == 0)\n        break;\n      \n      if (rem > size)\n        rem = size;\n      size -= rem;\n      do\n        buf[pos++] = *data++;\n      while (--rem);\n    }\n    _pos = pos;\n  }\n  \n  Byte GetByte(UInt32 distance) const\n  {\n    UInt32 pos = _pos - distance - 1;\n    if (distance >= _pos)\n      pos += _bufSize;\n    return _buf[pos];\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzfseDecoder.cpp",
    "content": "﻿// LzfseDecoder.cpp\n\n/*\nThis code implements LZFSE data decompressing.\nThe code from \"LZFSE compression library\" was used.\n\n2018      : Igor Pavlov : BSD 3-clause License : the code in this file\n2015-2017 : Apple Inc   : BSD 3-clause License : original \"LZFSE compression library\" code\n\nThe code in the \"LZFSE compression library\" is licensed under the \"BSD 3-clause License\":\n----\nCopyright (c) 2015-2016, Apple Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1.  Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2.  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer\n    in the documentation and/or other materials provided with the distribution.\n\n3.  Neither the name of the copyright holder(s) nor the names of any contributors may be used to endorse or promote products derived\n    from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\nCOPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\nHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n----\n*/\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"LzfseDecoder.h\"\n\nnamespace NCompress {\nnamespace NLzfse {\n\nstatic const Byte kSignature_LZFSE_V1 = 0x31; // '1'\nstatic const Byte kSignature_LZFSE_V2 = 0x32; // '2'\n\n\nHRESULT CDecoder::GetUInt32(UInt32 &val)\n{\n  Byte b[4];\n  for (unsigned i = 0; i < 4; i++)\n    if (!m_InStream.ReadByte(b[i]))\n      return S_FALSE;\n  val = GetUi32(b);\n  return S_OK;\n}\n\n\n\nHRESULT CDecoder::DecodeUncompressed(UInt32 unpackSize)\n{\n  PRF(printf(\"\\nUncompressed %7u\\n\", unpackSize));\n\n  const unsigned kBufSize = 1 << 8;\n  Byte buf[kBufSize];\n  for (;;)\n  {\n    if (unpackSize == 0)\n      return S_OK;\n    UInt32 cur = unpackSize;\n    if (cur > kBufSize)\n      cur = kBufSize;\n    const UInt32 cur2 = (UInt32)m_InStream.ReadBytes(buf, cur);\n    m_OutWindowStream.PutBytes(buf, cur2);\n    if (cur != cur2)\n      return S_FALSE;\n  }\n}\n\n\n\nHRESULT CDecoder::DecodeLzvn(UInt32 unpackSize, UInt32 packSize)\n{\n  PRF(printf(\"\\nLZVN 0x%07x 0x%07x\\n\", unpackSize, packSize));\n  \n  UInt32 D = 0;\n\n  for (;;)\n  {\n    if (packSize == 0)\n      return S_FALSE;\n    Byte b;\n    if (!m_InStream.ReadByte(b))\n      return S_FALSE;\n    packSize--;\n\n    UInt32 M;\n    UInt32 L;\n\n    if (b >= 0xE0)\n    {\n      /*\n      large L   - 11100000 LLLLLLLL <LITERALS>\n      small L   - 1110LLLL <LITERALS>\n      \n      large Rep - 11110000 MMMMMMMM\n      small Rep - 1111MMMM\n      */\n        \n      M = b & 0xF;\n      if (M == 0)\n      {\n        if (packSize == 0)\n          return S_FALSE;\n        Byte b1;\n        if (!m_InStream.ReadByte(b1))\n          return S_FALSE;\n        packSize--;\n        M = (UInt32)b1 + 16;\n      }\n      L = 0;\n      if ((b & 0x10) == 0)\n      {\n        // Literals only\n        L = M;\n        M = 0;\n      }\n    }\n      \n    // ERROR codes\n    else if ((b & 0xF0) == 0x70) // 0111xxxx\n      return S_FALSE;\n    else if ((b & 0xF0) == 0xD0) // 1101xxxx\n      return S_FALSE;\n    \n    else\n    {\n      if ((b & 0xE0) == 0xA0)\n      {\n        // medium  - 101LLMMM DDDDDDMM DDDDDDDD <LITERALS>\n        if (packSize < 2)\n          return S_FALSE;\n        Byte b1;\n        if (!m_InStream.ReadByte(b1))\n          return S_FALSE;\n        packSize--;\n        \n        Byte b2;\n        if (!m_InStream.ReadByte(b2))\n          return S_FALSE;\n        packSize--;\n        L = (((UInt32)b >> 3) & 3);\n        M = (((UInt32)b & 7) << 2) + (b1 & 3);\n        D = ((UInt32)b1 >> 2) + ((UInt32)b2 << 6);\n      }\n      else\n      {\n        L = (UInt32)b >> 6;\n        M = ((UInt32)b >> 3) & 7;\n        if ((b & 0x7) == 6)\n        {\n          // REP - LLMMM110 <LITERALS>\n          if (L == 0)\n          {\n            // spec\n            if (M == 0)\n              break; // EOS\n            if (M <= 2)\n              continue; // NOP\n            return S_FALSE; // UNDEFINED\n          }\n        }\n        else\n        {\n          if (packSize == 0)\n            return S_FALSE;\n          Byte b1;\n          if (!m_InStream.ReadByte(b1))\n            return S_FALSE;\n          packSize--;\n          \n          // large - LLMMM111 DDDDDDDD DDDDDDDD <LITERALS>\n          // small - LLMMMDDD DDDDDDDD <LITERALS>\n          D  = ((UInt32)b & 7);\n          if (D == 7)\n          {\n            if (packSize == 0)\n              return S_FALSE;\n            Byte b2;\n            if (!m_InStream.ReadByte(b2))\n              return S_FALSE;\n            packSize--;\n            D = b2;\n          }\n          D = (D << 8) + b1;\n        }\n      }\n\n      M += 3;\n    }\n    {\n      for (unsigned i = 0; i < L; i++)\n      {\n        if (packSize == 0 || unpackSize == 0)\n          return S_FALSE;\n        Byte b1;\n        if (!m_InStream.ReadByte(b1))\n          return S_FALSE;\n        packSize--;\n        m_OutWindowStream.PutByte(b1);\n        unpackSize--;\n      }\n    }\n    \n    if (M != 0)\n    {\n      if (unpackSize == 0 || D == 0)\n        return S_FALSE;\n      unsigned cur = M;\n      if (cur > unpackSize)\n        cur = (unsigned)unpackSize;\n      if (!m_OutWindowStream.CopyBlock(D - 1, cur))\n        return S_FALSE;\n      unpackSize -= cur;\n      if (cur != M)\n        return S_FALSE;\n    }\n  }\n\n  if (unpackSize != 0)\n    return S_FALSE;\n\n  // LZVN encoder writes 7 additional zero bytes\n  if (packSize < 7)\n    return S_FALSE;\n  for (unsigned i = 0; i < 7; i++)\n  {\n    Byte b;\n    if (!m_InStream.ReadByte(b))\n      return S_FALSE;\n    if (b != 0)\n      return S_FALSE;\n  }\n  packSize -= 7;\n  if (packSize)\n  {\n    PRF(printf(\"packSize after unused = %u\\n\", packSize));\n    // if (packSize <= 0x100) { Byte buf[0x100]; m_InStream.ReadBytes(buf, packSize); }\n    /* Lzvn block that is used in HFS can contain junk data\n       (at least 256 bytes) after payload data. Why?\n       We ignore that junk data, if it's HFS (LzvnMode) mode. */\n    if (!LzvnMode)\n      return S_FALSE;\n  }\n  return S_OK;\n}\n\n\n\n// ---------- LZFSE ----------\n\n#define MATCHES_PER_BLOCK 10000\n#define LITERALS_PER_BLOCK (4 * MATCHES_PER_BLOCK)\n\n#define NUM_L_SYMBOLS 20\n#define NUM_M_SYMBOLS 20\n#define NUM_D_SYMBOLS 64\n#define NUM_LIT_SYMBOLS 256\n\n#define NUM_SYMBOLS ( \\\n    NUM_L_SYMBOLS + \\\n    NUM_M_SYMBOLS + \\\n    NUM_D_SYMBOLS + \\\n    NUM_LIT_SYMBOLS)\n\n#define NUM_L_STATES (1 << 6)\n#define NUM_M_STATES (1 << 6)\n#define NUM_D_STATES (1 << 8)\n#define NUM_LIT_STATES (1 << 10)\n\n\ntypedef UInt32 CFseState;\n\n\nstatic UInt32 SumFreqs(const UInt16 *freqs, unsigned num)\n{\n  UInt32 sum = 0;\n  for (unsigned i = 0; i < num; i++)\n    sum += (UInt32)freqs[i];\n  return sum;\n}\n\n\nstatic Z7_FORCE_INLINE unsigned CountZeroBits(UInt32 val, UInt32 mask)\n{\n  for (unsigned i = 0;;)\n  {\n    if (val & mask)\n      return i;\n    i++;\n    mask >>= 1;\n  }\n}\n\n\nstatic Z7_FORCE_INLINE void InitLitTable(const UInt16 *freqs, UInt32 *table)\n{\n  for (unsigned i = 0; i < NUM_LIT_SYMBOLS; i++)\n  {\n    unsigned f = freqs[i];\n    if (f == 0)\n      continue;\n\n    //         0 <   f     <= numStates\n    //         0 <=  k     <= numStatesLog\n    // numStates <= (f<<k) <  numStates * 2\n    //         0 <  j0     <= f\n    // (f + j0) = next_power_of_2 for f\n    unsigned k = CountZeroBits(f, NUM_LIT_STATES);\n    unsigned j0 = (((unsigned)NUM_LIT_STATES * 2) >> k) - f;\n\n    /*\n    CEntry\n    {\n      Byte k;\n      Byte symbol;\n      UInt16 delta;\n    };\n    */\n\n    UInt32 e = ((UInt32)i << 8) + k;\n    k += 16;\n    UInt32 d = e + ((UInt32)f << k) - ((UInt32)NUM_LIT_STATES << 16);\n    UInt32 step = (UInt32)1 << k;\n\n    unsigned j = 0;\n    do\n    {\n      *table++ = d;\n      d += step;\n    }\n    while (++j < j0);\n\n    e--;\n    step >>= 1;\n    \n    for (j = j0; j < f; j++)\n    {\n      *table++ = e;\n      e += step;\n    }\n  }\n}\n\n\ntypedef struct\n{\n  Byte totalBits;\n  Byte extraBits;\n  UInt16 delta;\n  UInt32 vbase;\n} CExtraEntry;\n\n\nstatic void InitExtraDecoderTable(unsigned numStates,\n    unsigned numSymbols,\n    const UInt16 *freqs,\n    const Byte *vbits,\n    CExtraEntry *table)\n{\n  UInt32 vbase = 0;\n\n  for (unsigned i = 0; i < numSymbols; i++)\n  {\n    unsigned f = freqs[i];\n    unsigned extraBits = vbits[i];\n\n    if (f != 0)\n    {\n      unsigned k = CountZeroBits(f, numStates);\n      unsigned j0 = ((2 * numStates) >> k) - f;\n      \n      unsigned j = 0;\n      do\n      {\n        CExtraEntry *e = table++;\n        e->totalBits = (Byte)(k + extraBits);\n        e->extraBits = (Byte)extraBits;\n        e->delta = (UInt16)(((f + j) << k) - numStates);\n        e->vbase = vbase;\n      }\n      while (++j < j0);\n      \n      f -= j0;\n      k--;\n      \n      for (j = 0; j < f; j++)\n      {\n        CExtraEntry *e = table++;\n        e->totalBits = (Byte)(k + extraBits);\n        e->extraBits = (Byte)extraBits;\n        e->delta = (UInt16)(j << k);\n        e->vbase = vbase;\n      }\n    }\n\n    vbase += ((UInt32)1 << extraBits);\n  }\n}\n\n\nstatic const Byte k_L_extra[NUM_L_SYMBOLS] =\n{\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 8\n};\n\nstatic const Byte k_M_extra[NUM_M_SYMBOLS] =\n{\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11\n};\n\nstatic const Byte k_D_extra[NUM_D_SYMBOLS] =\n{\n   0,  0,  0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,\n   4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,\n   8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11, 11,\n  12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15\n};\n\n\n\n// ---------- CBitStream ----------\n\ntypedef struct\n{\n  UInt32 accum;\n  unsigned numBits; // [0, 31] - Number of valid bits in (accum), other bits are 0\n} CBitStream;\n\n\nstatic Z7_FORCE_INLINE int FseInStream_Init(CBitStream *s,\n    int n, // [-7, 0], (-n == number_of_unused_bits) in last byte\n    const Byte **pbuf)\n{\n  *pbuf -= 4;\n  s->accum = GetUi32(*pbuf);\n  if (n)\n  {\n    s->numBits = (unsigned)(n + 32);\n    if ((s->accum >> s->numBits) != 0)\n      return -1; // ERROR, encoder should have zeroed the upper bits\n  }\n  else\n  {\n    *pbuf += 1;\n    s->accum >>= 8;\n    s->numBits = 24;\n  }\n  return 0; // OK\n}\n\n\n// 0 <= numBits < 32\n#define mask31(x, numBits) ((x) & (((UInt32)1 << (numBits)) - 1))\n\n#define FseInStream_FLUSH \\\n  { const unsigned nbits = (31 - in.numBits) & (unsigned)-8; \\\n  if (nbits) { \\\n    buf -= (nbits >> 3); \\\n    if (buf < buf_check) return S_FALSE; \\\n    UInt32 v = GetUi32(buf); \\\n    in.accum = (in.accum << nbits) | mask31(v, nbits); \\\n    in.numBits += nbits; }}\n\n\n\nstatic Z7_FORCE_INLINE UInt32 BitStream_Pull(CBitStream *s, unsigned numBits)\n{\n  s->numBits -= numBits;\n  const UInt32 v = s->accum >> s->numBits;\n  s->accum = mask31(s->accum, s->numBits);\n  return v;\n}\n\n\n#define DECODE_LIT(dest, pstate) { \\\n  UInt32 e = lit_decoder[pstate]; \\\n  pstate = (CFseState)((e >> 16) + BitStream_Pull(&in, e & 0xff)); \\\n  dest = (Byte)(e >> 8); }\n\n\nstatic Z7_FORCE_INLINE UInt32 FseDecodeExtra(CFseState *pstate,\n    const CExtraEntry *table,\n    CBitStream *s)\n{\n  const CExtraEntry *e = &table[*pstate];\n  UInt32 v = BitStream_Pull(s, e->totalBits);\n  unsigned extraBits = e->extraBits;\n  *pstate = (CFseState)(e->delta + (v >> extraBits));\n  return e->vbase + mask31(v, extraBits);\n}\n\n\n#define freqs_L (freqs)\n#define freqs_M (freqs_L + NUM_L_SYMBOLS)\n#define freqs_D (freqs_M + NUM_M_SYMBOLS)\n#define freqs_LIT (freqs_D + NUM_D_SYMBOLS)\n\n#define GET_BITS_64(v, offset, num, dest) dest = (UInt32)   ((v >> (offset)) & ((1 << (num)) - 1));\n#define GET_BITS_64_Int32(v, offset, num, dest) dest = (Int32)((v >> (offset)) & ((1 << (num)) - 1));\n#define GET_BITS_32(v, offset, num, dest) dest = (CFseState)((v >> (offset)) & ((1 << (num)) - 1));\n\n\nHRESULT CDecoder::DecodeLzfse(UInt32 unpackSize, Byte version)\n{\n  PRF(printf(\"\\nLZFSE-%d %7u\", version - '0', unpackSize));\n\n  UInt32 numLiterals;\n  UInt32 litPayloadSize;\n  Int32 literal_bits;\n\n  UInt32 lit_state_0;\n  UInt32 lit_state_1;\n  UInt32 lit_state_2;\n  UInt32 lit_state_3;\n\n  UInt32 numMatches;\n  UInt32 lmdPayloadSize;\n  Int32 lmd_bits;\n\n  CFseState l_state;\n  CFseState m_state;\n  CFseState d_state;\n\n  UInt16 freqs[NUM_SYMBOLS];\n\n  if (version == kSignature_LZFSE_V1)\n  {\n    return E_NOTIMPL;\n    // we need examples to test LZFSE-V1 code\n    /*\n    const unsigned k_v1_SubHeaderSize = 7 * 4 + 7 * 2;\n    const unsigned k_v1_HeaderSize = k_v1_SubHeaderSize + NUM_SYMBOLS * 2;\n    _buffer.AllocAtLeast(k_v1_HeaderSize);\n    if (m_InStream.ReadBytes(_buffer, k_v1_HeaderSize) != k_v1_HeaderSize)\n      return S_FALSE;\n\n    const Byte *buf = _buffer;\n    #define GET_32(offs, dest) dest = GetUi32(buf + offs)\n    #define GET_16(offs, dest) dest = GetUi16(buf + offs)\n\n    UInt32 payload_bytes;\n    GET_32(0, payload_bytes);\n    GET_32(4, numLiterals);\n    GET_32(8, numMatches);\n    GET_32(12, litPayloadSize);\n    GET_32(16, lmdPayloadSize);\n    if (litPayloadSize > (1 << 20) || lmdPayloadSize > (1 << 20))\n      return S_FALSE;\n    GET_32(20, literal_bits);\n    if (literal_bits < -7 || literal_bits > 0)\n      return S_FALSE;\n\n    GET_16(24, lit_state_0);\n    GET_16(26, lit_state_1);\n    GET_16(28, lit_state_2);\n    GET_16(30, lit_state_3);\n\n    GET_32(32, lmd_bits);\n    if (lmd_bits < -7 || lmd_bits > 0)\n      return S_FALSE;\n\n    GET_16(36, l_state);\n    GET_16(38, m_state);\n    GET_16(40, d_state);\n\n    for (unsigned i = 0; i < NUM_SYMBOLS; i++)\n      freqs[i] = GetUi16(buf + k_v1_SubHeaderSize + i * 2);\n    */\n  }\n  else\n  {\n    UInt32 headerSize;\n    {\n      const unsigned kPreHeaderSize = 4 * 2; // signature and upackSize\n      const unsigned kHeaderSize = 8 * 3;\n      Byte temp[kHeaderSize];\n      if (m_InStream.ReadBytes(temp, kHeaderSize) != kHeaderSize)\n        return S_FALSE;\n      \n      UInt64 v;\n      \n      v = GetUi64(temp);\n      GET_BITS_64(v,  0, 20, numLiterals)\n      GET_BITS_64(v, 20, 20, litPayloadSize)\n      GET_BITS_64(v, 40, 20, numMatches)\n      GET_BITS_64_Int32(v, 60, 3 + 1, literal_bits) // (NumberOfUsedBits - 1)\n      literal_bits -= 7; // (-NumberOfUnusedBits)\n      if (literal_bits > 0)\n        return S_FALSE;\n      // GET_BITS_64(v, 63, 1, unused);\n      \n      v = GetUi64(temp + 8);\n      GET_BITS_64(v,  0, 10, lit_state_0)\n      GET_BITS_64(v, 10, 10, lit_state_1)\n      GET_BITS_64(v, 20, 10, lit_state_2)\n      GET_BITS_64(v, 30, 10, lit_state_3)\n      GET_BITS_64(v, 40, 20, lmdPayloadSize)\n      GET_BITS_64_Int32(v, 60, 3 + 1, lmd_bits)\n      lmd_bits -= 7;\n      if (lmd_bits > 0)\n        return S_FALSE;\n      // GET_BITS_64(v, 63, 1, unused)\n      \n      UInt32 v32 = GetUi32(temp + 20);\n      // (total header size in bytes; this does not\n      // correspond to a field in the uncompressed header version,\n      // but is required; we wouldn't know the size of the\n      // compresssed header otherwise.\n      GET_BITS_32(v32, 0, 10, l_state)\n      GET_BITS_32(v32, 10, 10, m_state)\n      GET_BITS_32(v32, 20, 10 + 2, d_state)\n      // GET_BITS_64(v, 62, 2, unused)\n      \n      headerSize = GetUi32(temp + 16);\n      if (headerSize <= kPreHeaderSize + kHeaderSize)\n        return S_FALSE;\n      headerSize -= kPreHeaderSize + kHeaderSize;\n    }\n\n    // no freqs case is not allowed ?\n    // memset(freqs, 0, sizeof(freqs));\n    // if (headerSize != 0)\n    {\n      static const Byte numBitsTable[32] =\n      {\n        2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14,\n        2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14\n      };\n  \n      static const Byte valueTable[32] =\n      {\n        0, 2, 1, 4, 0, 3, 1, 8, 0, 2, 1, 5, 0, 3, 1, 24,\n        0, 2, 1, 6, 0, 3, 1, 8, 0, 2, 1, 7, 0, 3, 1, 24\n      };\n\n      UInt32 accum = 0;\n      unsigned numBits = 0;\n\n      for (unsigned i = 0; i < NUM_SYMBOLS; i++)\n      {\n        while (numBits <= 14 && headerSize != 0)\n        {\n          Byte b;\n          if (!m_InStream.ReadByte(b))\n            return S_FALSE;\n          accum |= (UInt32)b << numBits;\n          numBits += 8;\n          headerSize--;\n        }\n        \n        unsigned b = (unsigned)accum & 31;\n        unsigned n = numBitsTable[b];\n        if (numBits < n)\n          return S_FALSE;\n        numBits -= n;\n        UInt32 f = valueTable[b];\n        if (n >= 8)\n          f += ((accum >> 4) & (0x3ff >> (14 - n)));\n        accum >>= n;\n        freqs[i] = (UInt16)f;\n      }\n      \n      if (numBits >= 8 || headerSize != 0)\n        return S_FALSE;\n    }\n  }\n\n  PRF(printf(\" Literals=%6u Matches=%6u\", numLiterals, numMatches));\n\n  if (numLiterals > LITERALS_PER_BLOCK\n      || (numLiterals & 3) != 0\n      || numMatches > MATCHES_PER_BLOCK\n      || lit_state_0 >= NUM_LIT_STATES\n      || lit_state_1 >= NUM_LIT_STATES\n      || lit_state_2 >= NUM_LIT_STATES\n      || lit_state_3 >= NUM_LIT_STATES\n      || l_state >= NUM_L_STATES\n      || m_state >= NUM_M_STATES\n      || d_state >= NUM_D_STATES)\n    return S_FALSE;\n\n  // only full table is allowed ?\n  if (   SumFreqs(freqs_L, NUM_L_SYMBOLS) != NUM_L_STATES\n      || SumFreqs(freqs_M, NUM_M_SYMBOLS) != NUM_M_STATES\n      || SumFreqs(freqs_D, NUM_D_SYMBOLS) != NUM_D_STATES\n      || SumFreqs(freqs_LIT, NUM_LIT_SYMBOLS) != NUM_LIT_STATES)\n    return S_FALSE;\n\n\n  const unsigned kPad = 16;\n\n  // ---------- Decode literals ----------\n\n  {\n    _literals.AllocAtLeast(LITERALS_PER_BLOCK + 16);\n    _buffer.AllocAtLeast(kPad + litPayloadSize);\n    memset(_buffer, 0, kPad);\n   \n    if (m_InStream.ReadBytes(_buffer + kPad, litPayloadSize) != litPayloadSize)\n      return S_FALSE;\n\n    UInt32 lit_decoder[NUM_LIT_STATES];\n    InitLitTable(freqs_LIT, lit_decoder);\n    \n    const Byte *buf_start = _buffer + kPad;\n    const Byte *buf_check = buf_start - 4;\n    const Byte *buf = buf_start + litPayloadSize;\n    CBitStream in;\n    if (FseInStream_Init(&in, literal_bits, &buf) != 0)\n      return S_FALSE;\n    \n    Byte *lit = _literals;\n    const Byte *lit_limit = lit + numLiterals;\n    for (; lit < lit_limit; lit += 4)\n    {\n      FseInStream_FLUSH\n      DECODE_LIT (lit[0], lit_state_0)\n      DECODE_LIT (lit[1], lit_state_1)\n      FseInStream_FLUSH\n      DECODE_LIT (lit[2], lit_state_2)\n      DECODE_LIT (lit[3], lit_state_3)\n    }\n    \n    if ((buf_start - buf) * 8 != (int)in.numBits)\n      return S_FALSE;\n  }\n\n  \n  // ---------- Decode LMD ----------\n\n  _buffer.AllocAtLeast(kPad + lmdPayloadSize);\n  memset(_buffer, 0, kPad);\n  if (m_InStream.ReadBytes(_buffer + kPad, lmdPayloadSize) != lmdPayloadSize)\n    return S_FALSE;\n\n  CExtraEntry l_decoder[NUM_L_STATES];\n  CExtraEntry m_decoder[NUM_M_STATES];\n  CExtraEntry d_decoder[NUM_D_STATES];\n\n  InitExtraDecoderTable(NUM_L_STATES, NUM_L_SYMBOLS, freqs_L, k_L_extra, l_decoder);\n  InitExtraDecoderTable(NUM_M_STATES, NUM_M_SYMBOLS, freqs_M, k_M_extra, m_decoder);\n  InitExtraDecoderTable(NUM_D_STATES, NUM_D_SYMBOLS, freqs_D, k_D_extra, d_decoder);\n\n  const Byte *buf_start = _buffer + kPad;\n  const Byte *buf_check = buf_start - 4;\n  const Byte *buf = buf_start + lmdPayloadSize;\n  CBitStream in;\n  if (FseInStream_Init(&in, lmd_bits, &buf))\n    return S_FALSE;\n    \n  const Byte *lit = _literals;\n  const Byte *lit_limit = lit + numLiterals;\n  \n  UInt32 D = 0;\n\n  for (;;)\n  {\n    if (numMatches == 0)\n      break;\n    numMatches--;\n\n    FseInStream_FLUSH\n\n    unsigned L = (unsigned)FseDecodeExtra(&l_state, l_decoder, &in);\n\n    FseInStream_FLUSH\n    \n    unsigned M = (unsigned)FseDecodeExtra(&m_state, m_decoder, &in);\n\n    FseInStream_FLUSH\n\n    {\n      UInt32 new_D = FseDecodeExtra(&d_state, d_decoder, &in);\n      if (new_D)\n        D = new_D;\n    }\n\n    if (L != 0)\n    {\n      if (L > (size_t)(lit_limit - lit))\n        return S_FALSE;\n      unsigned cur = L;\n      if (cur > unpackSize)\n        cur = (unsigned)unpackSize;\n      m_OutWindowStream.PutBytes(lit, cur);\n      unpackSize -= cur;\n      lit += cur;\n      if (cur != L)\n        return S_FALSE;\n    }\n\n    if (M != 0)\n    {\n      if (unpackSize == 0 || D == 0)\n        return S_FALSE;\n      unsigned cur = M;\n      if (cur > unpackSize)\n        cur = (unsigned)unpackSize;\n      if (!m_OutWindowStream.CopyBlock(D - 1, cur))\n        return S_FALSE;\n      unpackSize -= cur;\n      if (cur != M)\n        return S_FALSE;\n    }\n  }\n\n  if (unpackSize != 0)\n    return S_FALSE;\n\n  // LZFSE encoder writes 8 additional zero bytes before LMD payload\n  // We test it:\n  if ((size_t)(buf - buf_start) * 8 + in.numBits != 64)\n    return S_FALSE;\n  if (GetUi64(buf_start) != 0)\n    return S_FALSE;\n\n  return S_OK;\n}\n\n\nHRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\n{\n  PRF(printf(\"\\n\\nLzfseDecoder %7u %7u\\n\", (unsigned)*outSize, (unsigned)*inSize));\n\n  const UInt32 kLzfseDictSize = 1 << 18;\n  if (!m_OutWindowStream.Create(kLzfseDictSize))\n    return E_OUTOFMEMORY;\n  if (!m_InStream.Create(1 << 18))\n    return E_OUTOFMEMORY;\n\n  m_OutWindowStream.SetStream(outStream);\n  m_OutWindowStream.Init(false);\n  m_InStream.SetStream(inStream);\n  m_InStream.Init();\n  \n  CCoderReleaser coderReleaser(this);\n\n  UInt64 prevOut = 0;\n  UInt64 prevIn = 0;\n\n  if (LzvnMode)\n  {\n    if (!outSize || !inSize)\n      return E_NOTIMPL;\n    const UInt64 unpackSize = *outSize;\n    const UInt64 packSize = *inSize;\n    if (unpackSize > (UInt32)(Int32)-1\n        || packSize > (UInt32)(Int32)-1)\n      return S_FALSE;\n    RINOK(DecodeLzvn((UInt32)unpackSize, (UInt32)packSize))\n  }\n  else\n  for (;;)\n  {\n    const UInt64 pos = m_OutWindowStream.GetProcessedSize();\n    const UInt64 packPos = m_InStream.GetProcessedSize();\n\n    if (progress && ((pos - prevOut) >= (1 << 22) || (packPos - prevIn) >= (1 << 22)))\n    {\n      RINOK(progress->SetRatioInfo(&packPos, &pos))\n      prevIn = packPos;\n      prevOut = pos;\n    }\n\n    UInt32 v;\n    RINOK(GetUInt32(v))\n    if ((v & 0xFFFFFF) != 0x787662) // bvx\n      return S_FALSE;\n    v >>= 24;\n    \n    if (v == 0x24) // '$', end of stream\n      break;\n    \n    UInt32 unpackSize;\n    RINOK(GetUInt32(unpackSize))\n\n    UInt32 cur = unpackSize;\n    if (outSize)\n    {\n      const UInt64 rem = *outSize - pos;\n      if (cur > rem)\n        cur = (UInt32)rem;\n    }\n    unpackSize -= cur;\n    \n    HRESULT res;\n    if (v == kSignature_LZFSE_V1 || v == kSignature_LZFSE_V2)\n      res = DecodeLzfse(cur, (Byte)v);\n    else if (v == 0x6E) // 'n'\n    {\n      UInt32 packSize;\n      res = GetUInt32(packSize);\n      if (res == S_OK)\n        res = DecodeLzvn(cur, packSize);\n    }\n    else if (v == 0x2D) // '-'\n      res = DecodeUncompressed(cur);\n    else\n      return E_NOTIMPL;\n    \n    if (res != S_OK)\n      return res;\n    \n    if (unpackSize != 0)\n      return S_FALSE;\n  }\n  \n  coderReleaser.NeedFlush = false;\n  HRESULT res = m_OutWindowStream.Flush();\n  if (res == S_OK)\n    if ((!LzvnMode && inSize && *inSize != m_InStream.GetProcessedSize())\n        || (outSize && *outSize != m_OutWindowStream.GetProcessedSize()))\n      res = S_FALSE;\n  return res;\n}\n\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\n  catch(...) { return E_OUTOFMEMORY; }\n  // catch(...) { return S_FALSE; }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzfseDecoder.h",
    "content": "﻿// LzfseDecoder.h\n\n#ifndef ZIP7_INC_LZFSE_DECODER_H\n#define ZIP7_INC_LZFSE_DECODER_H\n\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n\n#include \"LzOutWindow.h\"\n\nnamespace NCompress {\nnamespace NLzfse {\n\nZ7_CLASS_IMP_NOQIB_1(\n  CDecoder\n  , ICompressCoder\n)\n  CLzOutWindow m_OutWindowStream;\n  CInBuffer m_InStream;\n  CByteBuffer _literals;\n  CByteBuffer _buffer;\n\n  class CCoderReleaser\n  {\n    CDecoder *m_Coder;\n  public:\n    bool NeedFlush;\n    CCoderReleaser(CDecoder *coder): m_Coder(coder), NeedFlush(true) {}\n    ~CCoderReleaser()\n    {\n      if (NeedFlush)\n        m_Coder->m_OutWindowStream.Flush();\n    }\n  };\n  friend class CCoderReleaser;\n\n  HRESULT GetUInt32(UInt32 &val);\n\n  HRESULT DecodeUncompressed(UInt32 unpackSize);\n  HRESULT DecodeLzvn(UInt32 unpackSize, UInt32 packSize);\n  HRESULT DecodeLzfse(UInt32 unpackSize, Byte version);\n\n  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\npublic:\n  bool LzvnMode;\n\n  CDecoder():\n    LzvnMode(false)\n    {}\n\n  // sizes are checked in Code()\n  // UInt64 GetInputProcessedSize() const { return m_InStream.GetProcessedSize(); }\n  // UInt64 GetOutputProcessedSize() const { return m_OutWindowStream.GetProcessedSize(); }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzhDecoder.cpp",
    "content": "﻿// LzhDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"LzhDecoder.h\"\n\nnamespace NCompress{\nnamespace NLzh {\nnamespace NDecoder {\n\nstatic const UInt32 kWindowSizeMin = 1 << 16;\n\nbool CCoder::ReadTP(unsigned num, unsigned numBits, int spec)\n{\n  _symbolT = -1;\n\n  const unsigned n = (unsigned)_inBitStream.ReadBits(numBits);\n  if (n == 0)\n  {\n    const unsigned s = (unsigned)_inBitStream.ReadBits(numBits);\n    _symbolT = (int)s;\n    return (s < num);\n  }\n  if (n > num)\n    return false;\n\n  {\n    Byte lens[NPT];\n    unsigned i;\n    for (i = 0; i < NPT; i++)\n      lens[i] = 0;\n    i = 0;\n    do\n    {\n      unsigned val = (unsigned)_inBitStream.GetValue(16);\n      unsigned c = val >> 13;\n      unsigned mov = 3;\n      if (c == 7)\n      {\n        while (val & (1 << 12))\n        {\n          val += val;\n          c++;\n        }\n        if (c > 16)\n          return false;\n        mov = c - 3;\n      }\n      lens[i++] = (Byte)c;\n      _inBitStream.MovePos(mov);\n      if ((int)i == spec)\n        i += _inBitStream.ReadBits(2);\n    }\n    while (i < n);\n    \n    return _decoderT.Build(lens, NHuffman::k_BuildMode_Full);\n  }\n}\n\nstatic const unsigned NUM_C_BITS = 9;\n\nbool CCoder::ReadC()\n{\n  _symbolC = -1;\n\n  const unsigned n = (unsigned)_inBitStream.ReadBits(NUM_C_BITS);\n  if (n == 0)\n  {\n    const unsigned s = (unsigned)_inBitStream.ReadBits(NUM_C_BITS);\n    _symbolC = (int)s;\n    return (s < NC);\n  }\n  if (n > NC)\n    return false;\n\n  {\n    Byte lens[NC];\n    unsigned i = 0;\n    do\n    {\n      unsigned c = (unsigned)_symbolT;\n      if (_symbolT < 0)\n        c = _decoderT.DecodeFull(&_inBitStream);\n      \n      if (c <= 2)\n      {\n        if (c == 0)\n          c = 1;\n        else if (c == 1)\n          c = _inBitStream.ReadBits(4) + 3;\n        else\n          c = _inBitStream.ReadBits(NUM_C_BITS) + 20;\n    \n        if (i + c > n)\n          return false;\n        \n        do\n          lens[i++] = 0;\n        while (--c);\n      }\n      else\n        lens[i++] = (Byte)(c - 2);\n    }\n    while (i < n);\n    \n    while (i < NC) lens[i++] = 0;\n    return _decoderC.Build(lens, /* n, */ NHuffman::k_BuildMode_Full);\n  }\n}\n\nHRESULT CCoder::CodeReal(UInt32 rem, ICompressProgressInfo *progress)\n{\n  UInt32 blockSize = 0;\n\n  while (rem != 0)\n  {\n    if (blockSize == 0)\n    {\n      if (_inBitStream.ExtraBitsWereRead())\n        return S_FALSE;\n      if (progress)\n      {\n        const UInt64 packSize = _inBitStream.GetProcessedSize();\n        const UInt64 pos = _outWindow.GetProcessedSize();\n        RINOK(progress->SetRatioInfo(&packSize, &pos))\n      }\n      \n      blockSize = _inBitStream.ReadBits(16);\n      if (blockSize == 0)\n        return S_FALSE;\n      \n      if (!ReadTP(NT, 5, 3))\n        return S_FALSE;\n      if (!ReadC())\n        return S_FALSE;\n      const unsigned pbit = (DictSize <= (1 << 14) ? 4 : 5);\n      if (!ReadTP(NP, pbit, -1))\n        return S_FALSE;\n    }\n  \n    blockSize--;\n\n    unsigned number = (unsigned)_symbolC;\n    if (_symbolC < 0)\n      number = _decoderC.DecodeFull(&_inBitStream);\n\n    if (number < 256)\n    {\n      _outWindow.PutByte((Byte)number);\n      rem--;\n    }\n    else\n    {\n      const unsigned len = number - 256 + kMatchMinLen;\n\n      UInt32 dist = (UInt32)(unsigned)_symbolT;\n      if (_symbolT < 0)\n        dist = (UInt32)_decoderT.DecodeFull(&_inBitStream);\n      \n      if (dist > 1)\n      {\n        dist--;\n        dist = ((UInt32)1 << dist) + _inBitStream.ReadBits((unsigned)dist);\n      }\n      \n      if (dist >= DictSize)\n        return S_FALSE;\n\n      if (len > rem)\n      {\n        // if (FinishMode)\n        return S_FALSE;\n        // len = (unsigned)rem;\n      }\n\n      if (!_outWindow.CopyBlock(dist, len))\n        return S_FALSE;\n      rem -= len;\n    }\n  }\n\n  // if (FinishMode)\n  {\n    if (blockSize != 0)\n      return S_FALSE;\n    if (_inBitStream.ReadAlignBits() != 0)\n      return S_FALSE;\n  }\n  if (_inBitStream.ExtraBitsWereRead())\n    return S_FALSE;\n  return S_OK;\n}\n\n\nHRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt32 outSize, ICompressProgressInfo *progress)\n{\n  try\n  {\n    if (!_outWindow.Create(DictSize > kWindowSizeMin ? DictSize : kWindowSizeMin))\n      return E_OUTOFMEMORY;\n    if (!_inBitStream.Create(1 << 17))\n      return E_OUTOFMEMORY;\n    _outWindow.SetStream(outStream);\n    _outWindow.Init(false);\n    _inBitStream.SetStream(inStream);\n    _inBitStream.Init();\n    {\n      CCoderReleaser coderReleaser(this);\n      RINOK(CodeReal(outSize, progress))\n      coderReleaser.Disable();\n    }\n    return _outWindow.Flush();\n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzhDecoder.h",
    "content": "﻿// LzhDecoder.h\n\n#ifndef ZIP7_INC_COMPRESS_LZH_DECODER_H\n#define ZIP7_INC_COMPRESS_LZH_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n\n#include \"BitmDecoder.h\"\n#include \"HuffmanDecoder.h\"\n#include \"LzOutWindow.h\"\n\nnamespace NCompress {\nnamespace NLzh {\nnamespace NDecoder {\n\nconst unsigned kMatchMinLen = 3;\nconst unsigned kMatchMaxLen = 256;\nconst unsigned NC = 256 + kMatchMaxLen - kMatchMinLen + 1;\nconst unsigned NUM_CODE_BITS = 16;\nconst unsigned NUM_DIC_BITS_MAX = 25;\nconst unsigned NT = NUM_CODE_BITS + 3;\nconst unsigned NP = NUM_DIC_BITS_MAX + 1;\nconst unsigned NPT = NP; // Max(NT, NP)\n\nclass CCoder\n{\n  CLzOutWindow _outWindow;\n  NBitm::CDecoder<CInBuffer> _inBitStream;\n\n  int _symbolT;\n  int _symbolC;\n  UInt32 DictSize;\n  // bool FinishMode;\n\n  NHuffman::CDecoder256<NUM_CODE_BITS, NPT, 7> _decoderT;\n  NHuffman::CDecoder<NUM_CODE_BITS, NC, 10> _decoderC;\n\n  class CCoderReleaser\n  {\n    CCoder *_coder;\n  public:\n    CCoderReleaser(CCoder *coder): _coder(coder) {}\n    void Disable() { _coder = NULL; }\n    ~CCoderReleaser() { if (_coder) _coder->_outWindow.Flush(); }\n  };\n  friend class CCoderReleaser;\n\n  bool ReadTP(unsigned num, unsigned numBits, int spec);\n  bool ReadC();\n\n  HRESULT CodeReal(UInt32 outSize, ICompressProgressInfo *progress);\npublic:\n  CCoder(): DictSize(1 << 16)\n      // , FinishMode(true)\n      {}\n  void SetDictSize(UInt32 dictSize) { DictSize = dictSize; }\n  UInt64 GetInputProcessedSize() const { return _inBitStream.GetProcessedSize(); }\n  HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      UInt32 outSize, ICompressProgressInfo *progress);\n};\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Lzma2Decoder.cpp",
    "content": "﻿// Lzma2Decoder.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/Alloc.h\"\n// #include \"../../../C/CpuTicks.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"Lzma2Decoder.h\"\n\nnamespace NCompress {\nnamespace NLzma2 {\n\nCDecoder::CDecoder():\n      _dec(NULL)\n    , _inProcessed(0)\n    , _prop(0xFF)\n    , _finishMode(false)\n    , _inBufSize(1 << 20)\n    , _outStep(1 << 20)\n    #ifndef Z7_ST\n    , _tryMt(1)\n    , _numThreads(1)\n    , _memUsage((UInt64)(sizeof(size_t)) << 28)\n    #endif\n{}\n\nCDecoder::~CDecoder()\n{\n  if (_dec)\n    Lzma2DecMt_Destroy(_dec);\n}\n\nZ7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size)) { _inBufSize = size; return S_OK; }\nZ7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size)) { _outStep = size; return S_OK; }\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size))\n{\n  if (size != 1)\n    return E_NOTIMPL;\n  if (prop[0] > 40)\n    return E_NOTIMPL;\n  _prop = prop[0];\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))\n{\n  _finishMode = (finishMode != 0);\n  return S_OK;\n}\n\n\n\n#ifndef Z7_ST\n\nstatic UInt64 Get_ExpectedBlockSize_From_Dict(UInt32 dictSize)\n{\n  const UInt32 kMinSize = (UInt32)1 << 20;\n  const UInt32 kMaxSize = (UInt32)1 << 28;\n  UInt64 blockSize = (UInt64)dictSize << 2;\n  if (blockSize < kMinSize) blockSize = kMinSize;\n  if (blockSize > kMaxSize) blockSize = kMaxSize;\n  if (blockSize < dictSize) blockSize = dictSize;\n  blockSize += (kMinSize - 1);\n  blockSize &= ~(UInt64)(kMinSize - 1);\n  return blockSize;\n}\n\n#define LZMA2_DIC_SIZE_FROM_PROP_FULL(p) ((p) == 40 ? 0xFFFFFFFF : (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)))\n\n#endif\n\n#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \\\n  if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;\n\n#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \\\n  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  _inProcessed = 0;\n\n  if (!_dec)\n  {\n    _dec = Lzma2DecMt_Create(\n      // &g_AlignedAlloc,\n      &g_Alloc,\n      &g_MidAlloc);\n    if (!_dec)\n      return E_OUTOFMEMORY;\n  }\n\n  CLzma2DecMtProps props;\n  Lzma2DecMtProps_Init(&props);\n\n  props.inBufSize_ST = _inBufSize;\n  props.outStep_ST = _outStep;\n\n  #ifndef Z7_ST\n  {\n    props.numThreads = 1;\n    UInt32 numThreads = _numThreads;\n\n    if (_tryMt && numThreads >= 1)\n    {\n      const UInt64 useLimit = _memUsage;\n      const UInt32 dictSize = LZMA2_DIC_SIZE_FROM_PROP_FULL(_prop);\n      const UInt64 expectedBlockSize64 = Get_ExpectedBlockSize_From_Dict(dictSize);\n      const size_t expectedBlockSize = (size_t)expectedBlockSize64;\n      const size_t inBlockMax = expectedBlockSize + expectedBlockSize / 16;\n      if (expectedBlockSize == expectedBlockSize64 && inBlockMax >= expectedBlockSize)\n      {\n        props.outBlockMax = expectedBlockSize;\n        props.inBlockMax = inBlockMax;\n        const size_t kOverheadSize = props.inBufSize_MT + (1 << 16);\n        const UInt64 okThreads = useLimit / (props.outBlockMax + props.inBlockMax + kOverheadSize);\n        if (numThreads > okThreads)\n          numThreads = (UInt32)okThreads;\n        if (numThreads == 0)\n          numThreads = 1;\n        props.numThreads = numThreads;\n      }\n    }\n  }\n  #endif\n\n  CSeqInStreamWrap inWrap;\n  CSeqOutStreamWrap outWrap;\n  CCompressProgressWrap progressWrap;\n\n  inWrap.Init(inStream);\n  outWrap.Init(outStream);\n  progressWrap.Init(progress);\n\n  SRes res;\n\n  UInt64 inProcessed = 0;\n  int isMT = False;\n\n  #ifndef Z7_ST\n  isMT = _tryMt;\n  #endif\n\n  // UInt64 cpuTicks = GetCpuTicks();\n\n  res = Lzma2DecMt_Decode(_dec, _prop, &props,\n      &outWrap.vt, outSize, _finishMode,\n      &inWrap.vt,\n      &inProcessed,\n      &isMT,\n      progress ? &progressWrap.vt : NULL);\n\n  /*\n  cpuTicks = GetCpuTicks() - cpuTicks;\n  printf(\"\\n             ticks = %10I64u\\n\", cpuTicks / 1000000);\n  */\n\n\n  #ifndef Z7_ST\n  /* we reset _tryMt, only if p->props.numThreads was changed */\n  if (props.numThreads > 1)\n    _tryMt = isMT;\n  #endif\n\n  _inProcessed = inProcessed;\n\n  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)\n  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)\n  RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)\n\n  if (res == SZ_OK && _finishMode)\n  {\n    if (inSize && *inSize != inProcessed)\n      res = SZ_ERROR_DATA;\n    if (outSize && *outSize != outWrap.Processed)\n      res = SZ_ERROR_DATA;\n  }\n\n  return SResToHRESULT(res);\n}\n\n\nZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = _inProcessed;\n  return S_OK;\n}\n\n\n#ifndef Z7_ST\n\nZ7_COM7F_IMF(CDecoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  // **************** 7-Zip ZS Modification Start ****************\n  //_numThreads = numThreads;\n  _numThreads = numThreads > 1 ? numThreads : 1;\n  // **************** 7-Zip ZS Modification End ****************\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetMemLimit(UInt64 memUsage))\n{\n  _memUsage = memUsage;\n  return S_OK;\n}\n\n#endif\n\n\n#ifndef Z7_NO_READ_FROM_CODER\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))\n{\n  CLzma2DecMtProps props;\n  Lzma2DecMtProps_Init(&props);\n  props.inBufSize_ST = _inBufSize;\n  props.outStep_ST = _outStep;\n\n  _inProcessed = 0;\n\n  if (!_dec)\n  {\n    _dec = Lzma2DecMt_Create(&g_AlignedAlloc, &g_MidAlloc);\n    if (!_dec)\n      return E_OUTOFMEMORY;\n  }\n\n  _inWrap.Init(_inStream);\n\n  const SRes res = Lzma2DecMt_Init(_dec, _prop, &props, outSize, _finishMode, &_inWrap.vt);\n\n  if (res != SZ_OK)\n    return SResToHRESULT(res);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))\n  { _inStream = inStream; return S_OK; }\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n  { _inStream.Release(); return S_OK; }\n  \n\nZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n\n  size_t size2 = size;\n  UInt64 inProcessed = 0;\n\n  const SRes res = Lzma2DecMt_Read(_dec, (Byte *)data, &size2, &inProcessed);\n\n  _inProcessed += inProcessed;\n  if (processedSize)\n    *processedSize = (UInt32)size2;\n  if (res != SZ_OK)\n    return SResToHRESULT(res);\n  return S_OK;\n}\n\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Lzma2Decoder.h",
    "content": "﻿// Lzma2Decoder.h\n\n#ifndef ZIP7_INC_LZMA2_DECODER_H\n#define ZIP7_INC_LZMA2_DECODER_H\n\n#include \"../../../C/Lzma2DecMt.h\"\n\n#include \"../Common/CWrappers.h\"\n\nnamespace NCompress {\nnamespace NLzma2 {\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetFinishMode,\n  public ICompressGetInStreamProcessedSize,\n  public ICompressSetBufSize,\n #ifndef Z7_NO_READ_FROM_CODER\n  public ICompressSetInStream,\n  public ICompressSetOutStreamSize,\n  public ISequentialInStream,\n #endif\n #ifndef Z7_ST\n  public ICompressSetCoderMt,\n  public ICompressSetMemLimit,\n #endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n  Z7_COM_QI_ENTRY(ICompressSetFinishMode)\n  Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize)\n  Z7_COM_QI_ENTRY(ICompressSetBufSize)\n #ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM_QI_ENTRY(ICompressSetInStream)\n  Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)\n  Z7_COM_QI_ENTRY(ISequentialInStream)\n #endif\n #ifndef Z7_ST\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n  Z7_COM_QI_ENTRY(ICompressSetMemLimit)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\n  Z7_IFACE_COM7_IMP(ICompressSetFinishMode)\n  Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)\n  Z7_IFACE_COM7_IMP(ICompressSetBufSize)\n #ifndef Z7_NO_READ_FROM_CODER\n  Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n  Z7_IFACE_COM7_IMP(ICompressSetInStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n #endif\n #ifndef Z7_ST\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n  Z7_IFACE_COM7_IMP(ICompressSetMemLimit)\n #endif\n\n  CLzma2DecMtHandle _dec;\n  UInt64 _inProcessed;\n  Byte _prop;\n  int _finishMode;\n  UInt32 _inBufSize;\n  UInt32 _outStep;\n\n #ifndef Z7_ST\n  int _tryMt;\n  UInt32 _numThreads;\n  UInt64 _memUsage;\n #endif\n\n #ifndef Z7_NO_READ_FROM_CODER\n  CMyComPtr<ISequentialInStream> _inStream;\n  CSeqInStreamWrap _inWrap;\n #endif\n\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Lzma2Encoder.cpp",
    "content": "﻿// Lzma2Encoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/CWrappers.h\"\n#include \"../Common/StreamUtils.h\"\n// **************** 7-Zip ZS Modification Start ****************\n#include \"../../Windows/System.h\"\n// **************** 7-Zip ZS Modification End ****************\n\n#include \"Lzma2Encoder.h\"\n\nnamespace NCompress {\n\nnamespace NLzma {\n\nHRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);\n\n}\n\nnamespace NLzma2 {\n\nCEncoder::CEncoder()\n{\n  _encoder = NULL;\n  _encoder = Lzma2Enc_Create(&g_AlignedAlloc, &g_BigAlloc);\n  if (!_encoder)\n    throw 1;\n}\n\nCEncoder::~CEncoder()\n{\n  if (_encoder)\n    Lzma2Enc_Destroy(_encoder);\n}\n\n\nHRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);\nHRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props)\n{\n  switch (propID)\n  {\n    case NCoderPropID::kBlockSize:\n    {\n      if (prop.vt == VT_UI4)\n        lzma2Props.blockSize = prop.ulVal;\n      else if (prop.vt == VT_UI8)\n        lzma2Props.blockSize = prop.uhVal.QuadPart;\n      else\n        return E_INVALIDARG;\n      break;\n    }\n    case NCoderPropID::kNumThreads:\n    // **************** 7-Zip ZS Modification Start ****************\n    {\n    // **************** 7-Zip ZS Modification End ****************\n      if (prop.vt != VT_UI4)\n        return E_INVALIDARG;\n      // **************** 7-Zip ZS Modification Start ****************\n      // lzma2Props.numTotalThreads = (int)(prop.ulVal);\n      int v = (int)prop.ulVal;\n      lzma2Props.numTotalThreads = v >= 0 ? (v ? v : 1) : NWindows::NSystem::GetNumberOfProcessors();;\n      // **************** 7-Zip ZS Modification End ****************\n      break;\n    // **************** 7-Zip ZS Modification Start ****************\n    }\n    // **************** 7-Zip ZS Modification End ****************\n    case NCoderPropID::kNumThreadGroups:\n      if (prop.vt != VT_UI4)\n        return E_INVALIDARG;\n      // 16-bit value supported by Windows\n      if (prop.ulVal >= (1u << 16))\n        return E_INVALIDARG;\n      lzma2Props.numThreadGroups = (unsigned)prop.ulVal;\n      break;\n    default:\n      RINOK(NLzma::SetLzmaProp(propID, prop, lzma2Props.lzmaProps))\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  CLzma2EncProps lzma2Props;\n  Lzma2EncProps_Init(&lzma2Props);\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    RINOK(SetLzma2Prop(propIDs[i], coderProps[i], lzma2Props))\n  }\n  return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));\n}\n\n\nZ7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    if (propID == NCoderPropID::kExpectedDataSize)\n      if (prop.vt == VT_UI8)\n        Lzma2Enc_SetDataSize(_encoder, prop.uhVal.QuadPart);\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))\n{\n  const Byte prop = Lzma2Enc_WriteProperties(_encoder);\n  return WriteStream(outStream, &prop, 1);\n}\n\n\n#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \\\n  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))\n{\n  CSeqInStreamWrap inWrap;\n  CSeqOutStreamWrap outWrap;\n  CCompressProgressWrap progressWrap;\n\n  inWrap.Init(inStream);\n  outWrap.Init(outStream);\n  progressWrap.Init(progress);\n\n  SRes res = Lzma2Enc_Encode2(_encoder,\n      &outWrap.vt, NULL, NULL,\n      &inWrap.vt, NULL, 0,\n      progress ? &progressWrap.vt : NULL);\n\n  RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)\n  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)\n  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)\n\n  return SResToHRESULT(res);\n}\n  \n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Lzma2Encoder.h",
    "content": "﻿// Lzma2Encoder.h\n\n#ifndef ZIP7_INC_LZMA2_ENCODER_H\n#define ZIP7_INC_LZMA2_ENCODER_H\n\n#include \"../../../C/Lzma2Enc.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NLzma2 {\n\nZ7_CLASS_IMP_COM_4(\n  CEncoder\n  , ICompressCoder\n  , ICompressSetCoderProperties\n  , ICompressWriteCoderProperties\n  , ICompressSetCoderPropertiesOpt\n)\n  CLzma2EncHandle _encoder;\npublic:\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Lzma2Register.cpp",
    "content": "﻿// Lzma2Register.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"Lzma2Decoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"Lzma2Encoder.h\"\n#endif\n\nnamespace NCompress {\nnamespace NLzma2 {\n\nREGISTER_CODEC_E(LZMA2,\n    CDecoder(),\n    CEncoder(),\n    0x21,\n    \"LZMA2\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzmaDecoder.cpp",
    "content": "﻿// LzmaDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"LzmaDecoder.h\"\n\nstatic HRESULT SResToHRESULT(SRes res)\n{\n  switch (res)\n  {\n    case SZ_OK: return S_OK;\n    case SZ_ERROR_MEM: return E_OUTOFMEMORY;\n    case SZ_ERROR_PARAM: return E_INVALIDARG;\n    case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;\n    case SZ_ERROR_DATA: return S_FALSE;\n    default: break;\n  }\n  return E_FAIL;\n}\n\nnamespace NCompress {\nnamespace NLzma {\n\nCDecoder::CDecoder():\n    FinishStream(false),\n    _propsWereSet(false),\n    _outSizeDefined(false),\n    _outStep(1 << 20),\n    _inBufSize(0),\n    _inBufSizeNew(1 << 20),\n    _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED),\n    _inBuf(NULL)\n{\n  _inProcessed = 0;\n  _inPos = _inLim = 0;\n\n  /*\n  AlignOffsetAlloc_CreateVTable(&_alloc);\n  _alloc.numAlignBits = 7;\n  _alloc.offset = 0;\n  */\n  LzmaDec_CONSTRUCT(&_state)\n}\n\nCDecoder::~CDecoder()\n{\n  LzmaDec_Free(&_state, &g_AlignedAlloc); // &_alloc.vt\n  MyFree(_inBuf);\n}\n\nZ7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size))\n  { _inBufSizeNew = size; return S_OK; }\nZ7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size))\n  { _outStep = size; return S_OK; }\n\nHRESULT CDecoder::CreateInputBuffer()\n{\n  if (!_inBuf || _inBufSizeNew != _inBufSize)\n  {\n    MyFree(_inBuf);\n    _inBufSize = 0;\n    _inBuf = (Byte *)MyAlloc(_inBufSizeNew);\n    if (!_inBuf)\n      return E_OUTOFMEMORY;\n    _inBufSize = _inBufSizeNew;\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size))\n{\n  RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_AlignedAlloc))) // &_alloc.vt\n  _propsWereSet = true;\n  return CreateInputBuffer();\n}\n\n\nvoid CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)\n{\n  _outSizeDefined = (outSize != NULL);\n  _outSize = 0;\n  if (_outSizeDefined)\n    _outSize = *outSize;\n  _outProcessed = 0;\n  _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED;\n\n  LzmaDec_Init(&_state);\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))\n{\n  _inProcessed = 0;\n  _inPos = _inLim = 0;\n  SetOutStreamSizeResume(outSize);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))\n{\n  FinishStream = (finishMode != 0);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = _inProcessed;\n  return S_OK;\n}\n\n\nHRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)\n{\n  if (!_inBuf || !_propsWereSet)\n    return S_FALSE;\n  \n  const UInt64 startInProgress = _inProcessed;\n  SizeT wrPos = _state.dicPos;\n  HRESULT readRes = S_OK;\n\n  for (;;)\n  {\n    if (_inPos == _inLim && readRes == S_OK)\n    {\n      _inPos = _inLim = 0;\n      readRes = inStream->Read(_inBuf, _inBufSize, &_inLim);\n    }\n\n    const SizeT dicPos = _state.dicPos;\n    SizeT size;\n    {\n      SizeT next = _state.dicBufSize;\n      if (next - wrPos > _outStep)\n        next = wrPos + _outStep;\n      size = next - dicPos;\n    }\n\n    ELzmaFinishMode finishMode = LZMA_FINISH_ANY;\n    if (_outSizeDefined)\n    {\n      const UInt64 rem = _outSize - _outProcessed;\n      if (size >= rem)\n      {\n        size = (SizeT)rem;\n        if (FinishStream)\n          finishMode = LZMA_FINISH_END;\n      }\n    }\n\n    SizeT inProcessed = _inLim - _inPos;\n    ELzmaStatus status;\n\n    const SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status);\n\n    _lzmaStatus = status;\n    _inPos += (UInt32)inProcessed;\n    _inProcessed += inProcessed;\n    const SizeT outProcessed = _state.dicPos - dicPos;\n    _outProcessed += outProcessed;\n\n    // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0)\n    const bool outFinished = (_outSizeDefined && _outProcessed >= _outSize);\n\n    const bool needStop = (res != 0\n        || (inProcessed == 0 && outProcessed == 0)\n        || status == LZMA_STATUS_FINISHED_WITH_MARK\n        || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT));\n\n    if (needStop || outProcessed >= size)\n    {\n      const HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos);\n\n      if (_state.dicPos == _state.dicBufSize)\n        _state.dicPos = 0;\n      wrPos = _state.dicPos;\n      \n      RINOK(res2)\n\n      if (needStop)\n      {\n        if (res != 0)\n        {\n          // return SResToHRESULT(res);\n          return S_FALSE;\n        }\n\n        if (status == LZMA_STATUS_FINISHED_WITH_MARK)\n        {\n          if (FinishStream)\n            if (_outSizeDefined && _outSize != _outProcessed)\n              return S_FALSE;\n          return readRes;\n        }\n        \n        if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)\n          if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)\n            return readRes;\n          \n        return S_FALSE;\n      }\n    }\n    \n    if (progress)\n    {\n      const UInt64 inSize = _inProcessed - startInProgress;\n      RINOK(progress->SetRatioInfo(&inSize, &_outProcessed))\n    }\n  }\n}\n\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  if (!_inBuf)\n    return E_INVALIDARG;\n  SetOutStreamSize(outSize);\n  HRESULT res = CodeSpec(inStream, outStream, progress);\n  if (res == S_OK)\n    if (FinishStream && inSize && *inSize != _inProcessed)\n      res = S_FALSE;\n  return res;\n}\n\n\n#ifndef Z7_NO_READ_FROM_CODER\n\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))\n  { _inStream = inStream; return S_OK; }\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n  { _inStream.Release(); return S_OK; }\n\nZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n\n  ELzmaFinishMode finishMode = LZMA_FINISH_ANY;\n  if (_outSizeDefined)\n  {\n    const UInt64 rem = _outSize - _outProcessed;\n    if (size >= rem)\n    {\n      size = (UInt32)rem;\n      if (FinishStream)\n        finishMode = LZMA_FINISH_END;\n    }\n  }\n\n  HRESULT readRes = S_OK;\n  \n  for (;;)\n  {\n    if (_inPos == _inLim && readRes == S_OK)\n    {\n      _inPos = _inLim = 0;\n      readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);\n    }\n\n    SizeT inProcessed = _inLim - _inPos;\n    SizeT outProcessed = size;\n    ELzmaStatus status;\n    \n    const SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,\n        _inBuf + _inPos, &inProcessed, finishMode, &status);\n    \n    _lzmaStatus = status;\n    _inPos += (UInt32)inProcessed;\n    _inProcessed += inProcessed;\n    _outProcessed += outProcessed;\n    size -= (UInt32)outProcessed;\n    data = (Byte *)data + outProcessed;\n    if (processedSize)\n      *processedSize += (UInt32)outProcessed;\n\n    if (res != 0)\n      return S_FALSE;\n    \n    /*\n    if (status == LZMA_STATUS_FINISHED_WITH_MARK)\n      return readRes;\n\n    if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)\n    {\n      if (FinishStream\n          && _outSizeDefined && _outProcessed >= _outSize\n          && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)\n        return S_FALSE;\n      return readRes;\n    }\n    */\n\n    if (inProcessed == 0 && outProcessed == 0)\n      return readRes;\n  }\n}\n\n\nHRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)\n{\n  SetOutStreamSizeResume(outSize);\n  return CodeSpec(_inStream, outStream, progress);\n}\n\n\nHRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize)\n{\n  RINOK(CreateInputBuffer())\n  \n  if (processedSize)\n    *processedSize = 0;\n\n  HRESULT readRes = S_OK;\n\n  while (size != 0)\n  {\n    if (_inPos == _inLim)\n    {\n      _inPos = _inLim = 0;\n      if (readRes == S_OK)\n        readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);\n      if (_inLim == 0)\n        break;\n    }\n\n    UInt32 cur = _inLim - _inPos;\n    if (cur > size)\n      cur = size;\n    memcpy(data, _inBuf + _inPos, cur);\n    _inPos += cur;\n    _inProcessed += cur;\n    size -= cur;\n    data = (Byte *)data + cur;\n    if (processedSize)\n      *processedSize += cur;\n  }\n  \n  return readRes;\n}\n\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzmaDecoder.h",
    "content": "﻿// LzmaDecoder.h\n\n#ifndef ZIP7_INC_LZMA_DECODER_H\n#define ZIP7_INC_LZMA_DECODER_H\n\n// #include \"../../../C/Alloc.h\"\n#include \"../../../C/LzmaDec.h\"\n\n#include \"../../Common/MyCom.h\"\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NLzma {\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetFinishMode,\n  public ICompressGetInStreamProcessedSize,\n  public ICompressSetBufSize,\n #ifndef Z7_NO_READ_FROM_CODER\n  public ICompressSetInStream,\n  public ICompressSetOutStreamSize,\n  public ISequentialInStream,\n #endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n  Z7_COM_QI_ENTRY(ICompressSetFinishMode)\n  Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize)\n  Z7_COM_QI_ENTRY(ICompressSetBufSize)\n #ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM_QI_ENTRY(ICompressSetInStream)\n  Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)\n  Z7_COM_QI_ENTRY(ISequentialInStream)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\nprivate:\n  Z7_IFACE_COM7_IMP(ICompressSetFinishMode)\n  Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)\n  // Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n\n  Z7_IFACE_COM7_IMP(ICompressSetBufSize)\n\n #ifndef Z7_NO_READ_FROM_CODER\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetInStream)\nprivate:\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n  Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n #else\n  Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize));\n #endif\n\npublic:\n  bool FinishStream; // set it before decoding, if you need to decode full LZMA stream\nprivate:\n  bool _propsWereSet;\n  bool _outSizeDefined;\n\n  UInt32 _outStep;\n  UInt32 _inBufSize;\n  UInt32 _inBufSizeNew;\n\n  ELzmaStatus _lzmaStatus;\n  UInt32 _inPos;\n  UInt32 _inLim;\n  Byte *_inBuf;\n \n  UInt64 _outSize;\n  UInt64 _inProcessed;\n  UInt64 _outProcessed;\n\n  // CAlignOffsetAlloc _alloc;\n\n  CLzmaDec _state;\n\n  HRESULT CreateInputBuffer();\n  HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);\n  void SetOutStreamSizeResume(const UInt64 *outSize);\n\n #ifndef Z7_NO_READ_FROM_CODER\nprivate:\n  CMyComPtr<ISequentialInStream> _inStream;\npublic:\n  HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);\n  HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize);\n #endif\n\npublic:\n  CDecoder();\n  ~CDecoder();\n\n  UInt64 GetInputProcessedSize() const { return _inProcessed; }\n  UInt64 GetOutputProcessedSize() const { return _outProcessed; }\n  bool NeedsMoreInput() const { return _lzmaStatus == LZMA_STATUS_NEEDS_MORE_INPUT; }\n  bool CheckFinishStatus(bool withEndMark) const\n  {\n    return _lzmaStatus == (withEndMark ?\n        LZMA_STATUS_FINISHED_WITH_MARK :\n        LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK);\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzmaEncoder.cpp",
    "content": "﻿// LzmaEncoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/CWrappers.h\"\n#include \"../Common/StreamUtils.h\"\n// **************** 7-Zip ZS Modification Start ****************\n#include \"../../Windows/System.h\"\n// **************** 7-Zip ZS Modification End ****************\n\n#include \"LzmaEncoder.h\"\n\n// #define LOG_LZMA_THREADS\n\n#ifdef LOG_LZMA_THREADS\n\n#include <stdio.h>\n\n#include \"../../Common/IntToString.h\"\n#include \"../../Windows/TimeUtils.h\"\n\nEXTERN_C_BEGIN\nvoid LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]);\nEXTERN_C_END\n\n#endif\n\nnamespace NCompress {\nnamespace NLzma {\n\nCEncoder::CEncoder()\n{\n  _encoder = NULL;\n  _encoder = LzmaEnc_Create(&g_AlignedAlloc);\n  if (!_encoder)\n    throw 1;\n}\n\nCEncoder::~CEncoder()\n{\n  if (_encoder)\n    LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc);\n}\n\nstatic inline wchar_t GetLowCharFast(wchar_t c)\n{\n  return c |= 0x20;\n}\n\nstatic int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes)\n{\n  const wchar_t c = GetLowCharFast(*s++);\n  if (c == 'h')\n  {\n    if (GetLowCharFast(*s++) != 'c')\n      return 0;\n    const int num = (int)(*s++ - L'0');\n    if (num < 4 || num > 5)\n      return 0;\n    if (*s != 0)\n      return 0;\n    *btMode = 0;\n    *numHashBytes = num;\n    return 1;\n  }\n\n  if (c != 'b')\n    return 0;\n  {\n    if (GetLowCharFast(*s++) != 't')\n      return 0;\n    const int num = (int)(*s++ - L'0');\n    if (num < 2 || num > 5)\n      return 0;\n    if (*s != 0)\n      return 0;\n    *btMode = 1;\n    *numHashBytes = num;\n    return 1;\n  }\n}\n\n#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = (int)v; break;\n#define SET_PROP_32U(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break;\n\nHRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep);\nHRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep)\n{\n  if (propID == NCoderPropID::kMatchFinder)\n  {\n    if (prop.vt != VT_BSTR)\n      return E_INVALIDARG;\n    return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG;\n  }\n\n  if (propID == NCoderPropID::kAffinity)\n  {\n    if (prop.vt == VT_UI8)\n      ep.affinity = prop.uhVal.QuadPart;\n    else\n      return E_INVALIDARG;\n    return S_OK;\n  }\n\n  if (propID == NCoderPropID::kAffinityInGroup)\n  {\n    if (prop.vt == VT_UI8)\n      ep.affinityInGroup = prop.uhVal.QuadPart;\n    else\n      return E_INVALIDARG;\n    return S_OK;\n  }\n\n  if (propID == NCoderPropID::kThreadGroup)\n  {\n    if (prop.vt == VT_UI4)\n      ep.affinityGroup = (Int32)(UInt32)prop.ulVal;\n    else\n      return E_INVALIDARG;\n    return S_OK;\n  }\n\n  if (propID == NCoderPropID::kHashBits)\n  {\n    if (prop.vt == VT_UI4)\n      ep.numHashOutBits = prop.ulVal;\n    else\n      return E_INVALIDARG;\n    return S_OK;\n  }\n\n  if (propID > NCoderPropID::kReduceSize)\n    return S_OK;\n  \n  if (propID == NCoderPropID::kReduceSize)\n  {\n    if (prop.vt == VT_UI8)\n      ep.reduceSize = prop.uhVal.QuadPart;\n    else\n      return E_INVALIDARG;\n    return S_OK;\n  }\n\n  if (propID == NCoderPropID::kDictionarySize)\n  {\n    if (prop.vt == VT_UI8)\n    {\n      // 21.03 : we support 64-bit VT_UI8 for dictionary and (dict == 4 GiB)\n      const UInt64 v = prop.uhVal.QuadPart;\n      if (v > ((UInt64)1 << 32))\n        return E_INVALIDARG;\n      UInt32 dict;\n      if (v == ((UInt64)1 << 32))\n        dict = (UInt32)(Int32)-1;\n      else\n        dict = (UInt32)v;\n      ep.dictSize = dict;\n      return S_OK;\n    }\n  }\n\n  if (prop.vt != VT_UI4)\n    return E_INVALIDARG;\n  const UInt32 v = prop.ulVal;\n  switch (propID)\n  {\n    case NCoderPropID::kDefaultProp:\n      if (v > 32)\n        return E_INVALIDARG;\n      ep.dictSize = (v == 32) ? (UInt32)(Int32)-1 : (UInt32)1 << (unsigned)v;\n      break;\n    SET_PROP_32(kLevel, level)\n    SET_PROP_32(kNumFastBytes, fb)\n    SET_PROP_32U(kMatchFinderCycles, mc)\n    SET_PROP_32(kAlgorithm, algo)\n    SET_PROP_32U(kDictionarySize, dictSize)\n    SET_PROP_32(kPosStateBits, pb)\n    SET_PROP_32(kLitPosBits, lp)\n    SET_PROP_32(kLitContextBits, lc)\n    // **************** 7-Zip ZS Modification Start ****************\n    // SET_PROP_32(kNumThreads, numThreads)\n    case NCoderPropID::kNumThreads:\n      ep.numThreads = (int)v >= 0 ? (int)(v ? v : 1) : NWindows::NSystem::GetNumberOfProcessors(); break;\n    // **************** 7-Zip ZS Modification End ****************\n    default: return E_INVALIDARG;\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  CLzmaEncProps props;\n  LzmaEncProps_Init(&props);\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    switch (propID)\n    {\n      case NCoderPropID::kEndMarker:\n        if (prop.vt != VT_BOOL)\n          return E_INVALIDARG;\n        props.writeEndMark = (prop.boolVal != VARIANT_FALSE);\n        break;\n      default:\n        RINOK(SetLzmaProp(propID, prop, props))\n    }\n  }\n  return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props));\n}\n\n\nZ7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    if (propID == NCoderPropID::kExpectedDataSize)\n      if (prop.vt == VT_UI8)\n        LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))\n{\n  Byte props[LZMA_PROPS_SIZE];\n  SizeT size = LZMA_PROPS_SIZE;\n  RINOK(LzmaEnc_WriteProperties(_encoder, props, &size))\n  return WriteStream(outStream, props, size);\n}\n\n\n#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \\\n  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;\n\n\n\n#ifdef LOG_LZMA_THREADS\n\nstatic inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; }\n\nstatic void PrintNum(UInt64 val, unsigned numDigits, char c = ' ')\n{\n  char temp[64];\n  char *p = temp + 32;\n  ConvertUInt64ToString(val, p);\n  unsigned len = (unsigned)strlen(p);\n  for (; len < numDigits; len++)\n    *--p = c;\n  printf(\"%s\", p);\n}\n\nstatic void PrintTime(const char *s, UInt64 val, UInt64 total)\n{\n  printf(\"  %s :\", s);\n  const UInt32 kFreq = 10000000;\n  UInt64 sec = val / kFreq;\n  PrintNum(sec, 6);\n  printf(\" .\");\n  UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000);\n  PrintNum(ms, 3, '0');\n  \n  while (val > ((UInt64)1 << 56))\n  {\n    val >>= 1;\n    total >>= 1;\n  }\n\n  UInt64 percent = 0;\n  if (total != 0)\n    percent = val * 100 / total;\n  printf(\"  =\");\n  PrintNum(percent, 4);\n  printf(\"%%\");\n}\n\n\nstruct CBaseStat\n{\n  UInt64 kernelTime, userTime;\n  \n  BOOL Get(HANDLE thread, const CBaseStat *prevStat)\n  {\n    FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT;\n    BOOL res = GetThreadTimes(thread\n      , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT);\n    if (res)\n    {\n      kernelTime = GetTime64(kernelTimeFT);\n      userTime = GetTime64(userTimeFT);\n      if (prevStat)\n      {\n        kernelTime -= prevStat->kernelTime;\n        userTime -= prevStat->userTime;\n      }\n    }\n    return res;\n  }\n};\n\n\nstatic void PrintStat(HANDLE thread, UInt64 totalTime, const CBaseStat *prevStat)\n{\n  CBaseStat newStat;\n  if (!newStat.Get(thread, prevStat))\n    return;\n\n  PrintTime(\"K\", newStat.kernelTime, totalTime);\n\n  const UInt64 processTime = newStat.kernelTime + newStat.userTime;\n  \n  PrintTime(\"U\", newStat.userTime, totalTime);\n  PrintTime(\"S\", processTime, totalTime);\n  printf(\"\\n\");\n  // PrintTime(\"G \", totalTime, totalTime);\n}\n\n#endif\n\n\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))\n{\n  CSeqInStreamWrap inWrap;\n  CSeqOutStreamWrap outWrap;\n  CCompressProgressWrap progressWrap;\n\n  inWrap.Init(inStream);\n  outWrap.Init(outStream);\n  progressWrap.Init(progress);\n\n  #ifdef LOG_LZMA_THREADS\n\n  FILETIME startTimeFT;\n  NWindows::NTime::GetCurUtcFileTime(startTimeFT);\n  UInt64 totalTime = GetTime64(startTimeFT);\n  CBaseStat oldStat;\n  if (!oldStat.Get(GetCurrentThread(), NULL))\n    return E_FAIL;\n  \n  #endif\n  \n  \n  SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt,\n      progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc);\n\n  _inputProcessed = inWrap.Processed;\n\n  RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)\n  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)\n  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)\n\n  \n  #ifdef LOG_LZMA_THREADS\n  \n  NWindows::NTime::GetCurUtcFileTime(startTimeFT);\n  totalTime = GetTime64(startTimeFT) - totalTime;\n  HANDLE lz_threads[2];\n  LzmaEnc_GetLzThreads(_encoder, lz_threads);\n  printf(\"\\n\");\n  printf(\"Main: \");  PrintStat(GetCurrentThread(), totalTime, &oldStat);\n  printf(\"Hash: \");  PrintStat(lz_threads[0], totalTime, NULL);\n  printf(\"BinT: \");  PrintStat(lz_threads[1], totalTime, NULL);\n  // PrintTime(\"Total: \", totalTime, totalTime);\n  printf(\"\\n\");\n\n  #endif\n\n  return SResToHRESULT(res);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzmaEncoder.h",
    "content": "﻿// LzmaEncoder.h\n\n#ifndef ZIP7_INC_LZMA_ENCODER_H\n#define ZIP7_INC_LZMA_ENCODER_H\n\n#include \"../../../C/LzmaEnc.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NLzma {\n\nclass CEncoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetCoderProperties,\n  public ICompressWriteCoderProperties,\n  public ICompressSetCoderPropertiesOpt,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_4(\n      ICompressCoder,\n      ICompressSetCoderProperties,\n      ICompressWriteCoderProperties,\n      ICompressSetCoderPropertiesOpt)\n  Z7_IFACE_COM7_IMP(ICompressCoder)\npublic:\n  Z7_IFACE_COM7_IMP(ICompressSetCoderProperties)\n  Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties)\n  Z7_IFACE_COM7_IMP(ICompressSetCoderPropertiesOpt)\n\n  CLzmaEncHandle _encoder;\n  UInt64 _inputProcessed;\n\n  CEncoder();\n  ~CEncoder();\n\n  UInt64 GetInputProcessedSize() const { return _inputProcessed; }\n  bool IsWriteEndMark() const { return LzmaEnc_IsWriteEndMark(_encoder) != 0; }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzmaRegister.cpp",
    "content": "﻿// LzmaRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"LzmaDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"LzmaEncoder.h\"\n#endif\n\nnamespace NCompress {\nnamespace NLzma {\n\nREGISTER_CODEC_E(LZMA,\n    CDecoder(),\n    CEncoder(),\n    0x30101,\n    \"LZMA\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzmsDecoder.cpp",
    "content": "﻿// LzmsDecoder.cpp\n// The code is based on LZMS description from wimlib code\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"LzmsDecoder.h\"\n\nnamespace NCompress {\nnamespace NLzms {\n\nclass CBitDecoder\n{\npublic:\n  const Byte *_buf;\n  unsigned _bitPos;\n\n  void Init(const Byte *buf, size_t size) throw()\n  {\n    _buf = buf + size;\n    _bitPos = 0;\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue(unsigned numBits) const\n  {\n    UInt32 v =\n        ((UInt32)_buf[-1] << 16) |\n        ((UInt32)_buf[-2] << 8) |\n         (UInt32)_buf[-3];\n    v >>= 24 - numBits - _bitPos;\n    return v & ((1u << numBits) - 1);\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue_InHigh32bits()\n  {\n    return GetUi32(_buf - 4) << _bitPos;\n  }\n  \n  void MovePos(unsigned numBits)\n  {\n    _bitPos += numBits;\n    _buf -= (_bitPos >> 3);\n    _bitPos &= 7;\n  }\n\n  UInt32 ReadBits32(unsigned numBits)\n  {\n    UInt32 mask = (((UInt32)1 << numBits) - 1);\n    numBits += _bitPos;\n    const Byte *buf = _buf;\n    UInt32 v = GetUi32(buf - 4);\n    if (numBits > 32)\n    {\n      v <<= (numBits - 32);\n      v |= (UInt32)buf[-5] >> (40 - numBits);\n    }\n    else\n      v >>= (32 - numBits);\n    _buf = buf - (numBits >> 3);\n    _bitPos = numBits & 7;\n    return v & mask;\n  }\n};\n\nstatic UInt32 g_PosBases[k_NumPosSyms /* + 1 */];\n\nstatic Byte g_PosDirectBits[k_NumPosSyms];\n\nstatic const Byte k_PosRuns[31] =\n{\n  8, 0, 9, 7, 10, 15, 15, 20, 20, 30, 33, 40, 42, 45, 60, 73,\n  80, 85, 95, 105, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1\n};\n\nstatic UInt32 g_LenBases[k_NumLenSyms];\n\nstatic const Byte k_LenDirectBits[k_NumLenSyms] =\n{\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,\n  2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 6,\n  7, 8, 9, 10, 16, 30,\n};\n\nstatic struct CInit\n{\n  CInit()\n  {\n    {\n      unsigned sum = 0;\n      for (unsigned i = 0; i < sizeof(k_PosRuns); i++)\n      {\n        unsigned t = k_PosRuns[i];\n        for (unsigned y = 0; y < t; y++)\n          g_PosDirectBits[sum + y] = (Byte)i;\n        sum += t;\n      }\n    }\n    {\n      UInt32 sum = 1;\n      for (unsigned i = 0; i < k_NumPosSyms; i++)\n      {\n        g_PosBases[i] = sum;\n        sum += (UInt32)1 << g_PosDirectBits[i];\n      }\n      // g_PosBases[k_NumPosSyms] = sum;\n    }\n    {\n      UInt32 sum = 1;\n      for (unsigned i = 0; i < k_NumLenSyms; i++)\n      {\n        g_LenBases[i] = sum;\n        sum += (UInt32)1 << k_LenDirectBits[i];\n      }\n    }\n  }\n} g_Init;\n\nstatic unsigned GetNumPosSlots(size_t size)\n{\n  if (size < 2)\n    return 0;\n  \n  size--;\n\n  if (size >= g_PosBases[k_NumPosSyms - 1])\n    return k_NumPosSyms;\n  unsigned left = 0;\n  unsigned right = k_NumPosSyms;\n  for (;;)\n  {\n    const unsigned m = (left + right) / 2;\n    if (left == m)\n      return m + 1;\n    if (size >= g_PosBases[m])\n      left = m;\n    else\n      right = m;\n  }\n}\n\n\nstatic const Int32 k_x86_WindowSize = 65535;\nstatic const Int32 k_x86_TransOffset = 1023;\n\nstatic const size_t k_x86_HistorySize = 1 << 16;\n\nstatic void x86_Filter(Byte *data, UInt32 size, Int32 *history)\n{\n  if (size <= 17)\n    return;\n\n  Byte isCode[256];\n  memset(isCode, 0, 256);\n  isCode[0x48] = 1;\n  isCode[0x4C] = 1;\n  isCode[0xE8] = 1;\n  isCode[0xE9] = 1;\n  isCode[0xF0] = 1;\n  isCode[0xFF] = 1;\n\n  {\n    for (size_t i = 0; i < k_x86_HistorySize; i++)\n      history[i] = -(Int32)k_x86_WindowSize - 1;\n  }\n\n  size -= 16;\n  const unsigned kSave = 6;\n  const Byte savedByte = data[(size_t)size + kSave];\n  data[(size_t)size + kSave] = 0xE8;\n  Int32 last_x86_pos = -k_x86_TransOffset - 1;\n\n  // first byte is ignored\n  Int32 i = 0;\n  \n  for (;;)\n  {\n    Byte *p = data + (UInt32)i;\n\n    for (;;)\n    {\n      if (isCode[*(++p)]) break;\n      if (isCode[*(++p)]) break;\n    }\n    \n    i = (Int32)(p - data);\n    if ((UInt32)i >= size)\n      break;\n\n    UInt32 codeLen;\n\n    Int32 maxTransOffset = k_x86_TransOffset;\n    \n    const Byte b = p[0];\n    \n    if ((b & 0x80) == 0) // REX (0x48 or 0x4c)\n    {\n      const unsigned b2 = p[2] - 0x5; // [RIP + disp32]\n      if (b2 & 0x7)\n        continue;\n      if (p[1] != 0x8d) // LEA\n      {\n        if (p[1] != 0x8b || b != 0x48 || (b2 & 0xf7))\n          continue;\n        // MOV RAX / RCX, [RIP + disp32]\n      }\n      codeLen = 3;\n    }\n    else if (b == 0xE8)\n    {\n      // CALL\n      codeLen = 1;\n      maxTransOffset /= 2;\n    }\n    else if (b == 0xE9)\n    {\n      // JUMP\n      i += 4;\n      continue;\n    }\n    else if (b == 0xF0)\n    {\n      if (p[1] != 0x83 || p[2] != 0x05)\n        continue;\n      // LOCK ADD [RIP + disp32], imm8\n      // LOCK ADD [disp32], imm8\n      codeLen = 3;\n    }\n    else\n    // if (b == 0xFF)\n    {\n      if (p[1] != 0x15)\n        continue;\n      // CALL [RIP + disp32];\n      // CALL [disp32];\n      codeLen = 2;\n    }\n\n    Int32 *target;\n    {\n      Byte *p2 = p + codeLen;\n      UInt32 n = GetUi32(p2);\n      if (i - last_x86_pos <= maxTransOffset)\n      {\n        n = (UInt32)((Int32)n - i);\n        SetUi32(p2, n)\n      }\n      target = history + (((UInt32)i + n) & 0xFFFF);\n    }\n\n    i += (Int32)(codeLen + sizeof(UInt32) - 1);\n\n    if (i - *target <= k_x86_WindowSize)\n      last_x86_pos = i;\n    *target = i;\n  }\n\n  data[(size_t)size + kSave] = savedByte;\n}\n\n\n\n// static const int kLenIdNeedInit = -2;\n\nCDecoder::CDecoder():\n  _x86_history(NULL)\n{\n}\n\nCDecoder::~CDecoder()\n{\n  ::MidFree(_x86_history);\n}\n\n// #define RIF(x) { if (!(x)) return false; }\n\n#define LIMIT_CHECK if (_bs._buf < _rc.cur) return S_FALSE;\n// #define LIMIT_CHECK\n\n#define READ_BITS_CHECK(numDirectBits) \\\n  if (_bs._buf < _rc.cur) return S_FALSE; \\\n  if ((size_t)(_bs._buf - _rc.cur) < (numDirectBits >> 3)) return S_FALSE;\n\n\n#define HUFF_DEC(sym, pp) \\\n    sym = pp.DecodeFull(&_bs); \\\n    pp.Freqs[sym]++; \\\n    if (--pp.RebuildRem == 0) pp.Rebuild();\n\n\nHRESULT CDecoder::CodeReal(const Byte *in, size_t inSize, Byte *_win, size_t outSize)\n{\n  // size_t inSizeT = (size_t)(inSize);\n  // Byte *_win;\n  // size_t _pos;\n  _pos = 0;\n\n  CBitDecoder _bs;\n  CRangeDecoder _rc;\n \n  if (inSize < 8 || (inSize & 1) != 0)\n    return S_FALSE;\n  _rc.Init(in, inSize);\n  if (_rc.code >= _rc.range)\n    return S_FALSE;\n  _bs.Init(in, inSize);\n\n  {\n    {\n      {\n        for (unsigned i = 0 ; i < k_NumReps + 1; i++)\n          _reps[i] = i + 1;\n      }\n\n      {\n        for (unsigned i = 0 ; i < k_NumReps + 1; i++)\n          _deltaReps[i] = i + 1;\n      }\n\n      mainState = 0;\n      matchState = 0;\n\n      { for (size_t i = 0; i < k_NumMainProbs; i++) mainProbs[i].Init(); }\n      { for (size_t i = 0; i < k_NumMatchProbs; i++) matchProbs[i].Init(); }\n\n      {\n        for (size_t k = 0; k < k_NumReps; k++)\n        {\n          lzRepStates[k] = 0;\n          for (size_t i = 0; i < k_NumRepProbs; i++)\n            lzRepProbs[k][i].Init();\n        }\n      }\n      {\n        for (size_t k = 0; k < k_NumReps; k++)\n        {\n          deltaRepStates[k] = 0;\n          for (size_t i = 0; i < k_NumRepProbs; i++)\n            deltaRepProbs[k][i].Init();\n        }\n      }\n\n      m_LitDecoder.Init();\n      m_LenDecoder.Init();\n      m_PowerDecoder.Init();\n      unsigned numPosSyms = GetNumPosSlots(outSize);\n      if (numPosSyms < 2)\n        numPosSyms = 2;\n      m_PosDecoder.Init(numPosSyms);\n      m_DeltaDecoder.Init(numPosSyms);\n    }\n  }\n\n  {\n    unsigned prevType = 0;\n    \n    while (_pos < outSize)\n    {\n      if (_rc.Decode(&mainState, k_NumMainProbs, mainProbs) == 0)\n      {\n        unsigned number;\n        HUFF_DEC(number, m_LitDecoder)\n        LIMIT_CHECK\n        _win[_pos++] = (Byte)number;\n        prevType = 0;\n      }\n      else if (_rc.Decode(&matchState, k_NumMatchProbs, matchProbs) == 0)\n      {\n        UInt32 distance;\n        \n        if (_rc.Decode(&lzRepStates[0], k_NumRepProbs, lzRepProbs[0]) == 0)\n        {\n          unsigned number;\n          HUFF_DEC(number, m_PosDecoder)\n          LIMIT_CHECK\n\n          const unsigned numDirectBits = g_PosDirectBits[number];\n          distance = g_PosBases[number];\n          READ_BITS_CHECK(numDirectBits)\n          distance += _bs.ReadBits32(numDirectBits);\n          // LIMIT_CHECK\n          _reps[3] = _reps[2];\n          _reps[2] = _reps[1];\n          _reps[1] = _reps[0];\n          _reps[0] = distance;\n        }\n        else\n        {\n          if (_rc.Decode(&lzRepStates[1], k_NumRepProbs, lzRepProbs[1]) == 0)\n          {\n            if (prevType != 1)\n              distance = _reps[0];\n            else\n            {\n              distance = _reps[1];\n              _reps[1] = _reps[0];\n              _reps[0] = distance;\n            }\n          }\n          else if (_rc.Decode(&lzRepStates[2], k_NumRepProbs, lzRepProbs[2]) == 0)\n          {\n            if (prevType != 1)\n            {\n              distance = _reps[1];\n              _reps[1] = _reps[0];\n              _reps[0] = distance;\n            }\n            else\n            {\n              distance = _reps[2];\n              _reps[2] = _reps[1];\n              _reps[1] = _reps[0];\n              _reps[0] = distance;\n            }\n          }\n          else\n          {\n            if (prevType != 1)\n            {\n              distance = _reps[2];\n              _reps[2] = _reps[1];\n              _reps[1] = _reps[0];\n              _reps[0] = distance;\n            }\n            else\n            {\n              distance = _reps[3];\n              _reps[3] = _reps[2];\n              _reps[2] = _reps[1];\n              _reps[1] = _reps[0];\n              _reps[0] = distance;\n            }\n          }\n        }\n\n        unsigned lenSlot;\n        HUFF_DEC(lenSlot, m_LenDecoder)\n        LIMIT_CHECK\n\n        UInt32 len = g_LenBases[lenSlot];\n        {\n          const unsigned numDirectBits = k_LenDirectBits[lenSlot];\n          READ_BITS_CHECK(numDirectBits)\n          len += _bs.ReadBits32(numDirectBits);\n        }\n        // LIMIT_CHECK\n\n        if (len > outSize - _pos)\n          return S_FALSE;\n\n        if (distance > _pos)\n          return S_FALSE;\n\n        Byte *dest = _win + _pos;\n        const Byte *src = dest - distance;\n        _pos += len;\n        do\n          *dest++ = *src++;\n        while (--len);\n\n        prevType = 1;\n      }\n      else\n      {\n        UInt64 distance;\n\n        unsigned power;\n        UInt32 distance32;\n        \n        if (_rc.Decode(&deltaRepStates[0], k_NumRepProbs, deltaRepProbs[0]) == 0)\n        {\n          HUFF_DEC(power, m_PowerDecoder)\n          LIMIT_CHECK\n\n          unsigned number;\n          HUFF_DEC(number, m_DeltaDecoder)\n          LIMIT_CHECK\n\n          const unsigned numDirectBits = g_PosDirectBits[number];\n          distance32 = g_PosBases[number];\n          READ_BITS_CHECK(numDirectBits)\n          distance32 += _bs.ReadBits32(numDirectBits);\n          // LIMIT_CHECK\n\n          distance = ((UInt64)power << 32) | distance32;\n\n          _deltaReps[3] = _deltaReps[2];\n          _deltaReps[2] = _deltaReps[1];\n          _deltaReps[1] = _deltaReps[0];\n          _deltaReps[0] = distance;\n        }\n        else\n        {\n          if (_rc.Decode(&deltaRepStates[1], k_NumRepProbs, deltaRepProbs[1]) == 0)\n          {\n            if (prevType != 2)\n              distance = _deltaReps[0];\n            else\n            {\n              distance = _deltaReps[1];\n              _deltaReps[1] = _deltaReps[0];\n              _deltaReps[0] = distance;\n            }\n          }\n          else if (_rc.Decode(&deltaRepStates[2], k_NumRepProbs, deltaRepProbs[2]) == 0)\n          {\n            if (prevType != 2)\n            {\n              distance = _deltaReps[1];\n              _deltaReps[1] = _deltaReps[0];\n              _deltaReps[0] = distance;\n            }\n            else\n            {\n              distance = _deltaReps[2];\n              _deltaReps[2] = _deltaReps[1];\n              _deltaReps[1] = _deltaReps[0];\n              _deltaReps[0] = distance;\n            }\n          }\n          else\n          {\n            if (prevType != 2)\n            {\n              distance = _deltaReps[2];\n              _deltaReps[2] = _deltaReps[1];\n              _deltaReps[1] = _deltaReps[0];\n              _deltaReps[0] = distance;\n            }\n            else\n            {\n              distance = _deltaReps[3];\n              _deltaReps[3] = _deltaReps[2];\n              _deltaReps[2] = _deltaReps[1];\n              _deltaReps[1] = _deltaReps[0];\n              _deltaReps[0] = distance;\n            }\n          }\n          distance32 = (UInt32)_deltaReps[0] & 0xFFFFFFFF;\n          power = (UInt32)(_deltaReps[0] >> 32);\n        }\n\n        const UInt32 dist = (distance32 << power);\n        \n        unsigned lenSlot;\n        HUFF_DEC(lenSlot, m_LenDecoder)\n        LIMIT_CHECK\n\n        UInt32 len = g_LenBases[lenSlot];\n        {\n          const unsigned numDirectBits = k_LenDirectBits[lenSlot];\n          READ_BITS_CHECK(numDirectBits)\n          len += _bs.ReadBits32(numDirectBits);\n        }\n        // LIMIT_CHECK\n\n        if (len > outSize - _pos)\n          return S_FALSE;\n\n        size_t span = (size_t)1 << power;\n        if ((UInt64)dist + span > _pos)\n          return S_FALSE;\n        Byte *dest = _win + _pos - span;\n        const Byte *src = dest - dist;\n        _pos += len;\n        do\n        {\n          *(dest + span) = (Byte)(*(dest) + *(src + span) - *(src));\n          src++;\n          dest++;\n        }\n        while (--len);\n\n        prevType = 2;\n      }\n    }\n  }\n\n  _rc.Normalize();\n  if (_rc.code != 0)\n    return S_FALSE;\n  if (_rc.cur > _bs._buf\n      || (_rc.cur == _bs._buf && _bs._bitPos != 0))\n    return S_FALSE;\n\n  /*\n  int delta = (int)(_bs._buf - _rc.cur);\n  if (_bs._bitPos != 0)\n    delta--;\n  if ((delta & 1))\n    delta--;\n  printf(\"%d \", delta);\n  */\n\n  return S_OK;\n}\n\nHRESULT CDecoder::Code(const Byte *in, size_t inSize, Byte *out, size_t outSize)\n{\n  if (!_x86_history)\n  {\n    _x86_history = (Int32 *)::MidAlloc(sizeof(Int32) * k_x86_HistorySize);\n    if (!_x86_history)\n      return E_OUTOFMEMORY;\n  }\n  HRESULT res;\n  // try\n  {\n    res = CodeReal(in, inSize, out, outSize);\n  }\n  // catch (...) { res = S_FALSE; }\n  x86_Filter(out, (UInt32)_pos, _x86_history);\n  return res;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzmsDecoder.h",
    "content": "﻿// LzmsDecoder.h\n// The code is based on LZMS description from wimlib code\n\n#ifndef ZIP7_INC_LZMS_DECODER_H\n#define ZIP7_INC_LZMS_DECODER_H\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/HuffEnc.h\"\n\n#include \"HuffmanDecoder.h\"\n\nnamespace NCompress {\nnamespace NLzms {\n\nconst unsigned k_NumLitSyms = 256;\nconst unsigned k_NumLenSyms = 54;\nconst unsigned k_NumPosSyms = 799;\nconst unsigned k_NumPowerSyms = 8;\n\nconst unsigned k_NumProbBits = 6;\nconst unsigned k_ProbLimit = 1 << k_NumProbBits;\nconst unsigned k_InitialProb = 48;\nconst UInt32 k_InitialHist = 0x55555555;\n\nconst unsigned k_NumReps = 3;\n\nconst unsigned k_NumMainProbs  = 16;\nconst unsigned k_NumMatchProbs = 32;\nconst unsigned k_NumRepProbs   = 64;\n\nconst unsigned k_NumHuffmanBits = 15;\n\ntemplate <UInt32 m_NumSyms, UInt32 m_RebuildFreq, unsigned numTableBits>\nclass CHuffDecoder: public NCompress::NHuffman::CDecoder<k_NumHuffmanBits, m_NumSyms, numTableBits>\n{\npublic:\n  UInt32 RebuildRem;\n  UInt32 NumSyms;\n  UInt32 Freqs[m_NumSyms];\n\n  void Generate() throw()\n  {\n    UInt32 vals[m_NumSyms];\n    Byte levels[m_NumSyms];\n\n    // We need to check that our algorithm is OK, when optimal Huffman tree uses more than 15 levels !!!\n    Huffman_Generate(Freqs, vals, levels, NumSyms, k_NumHuffmanBits);\n\n    for (UInt32 i = NumSyms; i < m_NumSyms; i++)\n      levels[i] = 0;\n\n    this->Build(levels, /* NumSyms, */ NHuffman::k_BuildMode_Full);\n  }\n  \n  void Rebuild() throw()\n  {\n    Generate();\n    RebuildRem = m_RebuildFreq;\n    const UInt32 num = NumSyms;\n    for (UInt32 i = 0; i < num; i++)\n      Freqs[i] = (Freqs[i] >> 1) + 1;\n  }\n\npublic:\n  void Init(UInt32 numSyms = m_NumSyms) throw()\n  {\n    RebuildRem = m_RebuildFreq;\n    NumSyms = numSyms;\n    for (UInt32 i = 0; i < numSyms; i++)\n      Freqs[i] = 1;\n    // for (; i < m_NumSyms; i++) Freqs[i] = 0;\n    Generate();\n  }\n};\n\n\nstruct CProbEntry\n{\n  UInt32 Prob;\n  UInt64 Hist;\n\n  void Init()\n  {\n    Prob = k_InitialProb;\n    Hist = k_InitialHist;\n  }\n\n  UInt32 GetProb() const throw()\n  {\n    UInt32 prob = Prob;\n    if (prob == 0)\n      prob = 1;\n    else if (prob == k_ProbLimit)\n      prob = k_ProbLimit - 1;\n    return prob;\n  }\n\n  void Update(unsigned bit) throw()\n  {\n    Prob += (UInt32)((Int32)(Hist >> (k_ProbLimit - 1)) - (Int32)bit);\n    Hist = (Hist << 1) | bit;\n  }\n};\n\n\nstruct CRangeDecoder\n{\n  UInt32 range;\n  UInt32 code;\n  const Byte *cur;\n  // const Byte *end;\n\n  void Init(const Byte *data, size_t /* size */) throw()\n  {\n    range = 0xFFFFFFFF;\n    code = (((UInt32)GetUi16(data)) << 16) | GetUi16(data + 2);\n    cur = data + 4;\n    // end = data + size;\n  }\n\n  void Normalize()\n  {\n    if (range <= 0xFFFF)\n    {\n      range <<= 16;\n      code <<= 16;\n      // if (cur >= end) throw 1;\n      code |= GetUi16(cur);\n      cur += 2;\n    }\n  }\n\n  unsigned Decode(UInt32 *state, UInt32 numStates, struct CProbEntry *probs)\n  {\n    UInt32 st = *state;\n    CProbEntry *entry = &probs[st];\n    st = (st << 1) & (numStates - 1);\n\n    const UInt32 prob = entry->GetProb();\n\n    if (range <= 0xFFFF)\n    {\n      range <<= 16;\n      code <<= 16;\n      // if (cur >= end) throw 1;\n      code |= GetUi16(cur);\n      cur += 2;\n    }\n\n    const UInt32 bound = (range >> k_NumProbBits) * prob;\n    \n    if (code < bound)\n    {\n      range = bound;\n      *state = st;\n      entry->Update(0);\n      return 0;\n    }\n    else\n    {\n      range -= bound;\n      code -= bound;\n      *state = st | 1;\n      entry->Update(1);\n      return 1;\n    }\n  }\n};\n\n\nclass CDecoder\n{\n  // CRangeDecoder _rc;\n  size_t _pos;\n\n  UInt32 _reps[k_NumReps + 1];\n  UInt64 _deltaReps[k_NumReps + 1];\n\n  UInt32 mainState;\n  UInt32 matchState;\n  UInt32 lzRepStates[k_NumReps];\n  UInt32 deltaRepStates[k_NumReps];\n\n  struct CProbEntry mainProbs[k_NumMainProbs];\n  struct CProbEntry matchProbs[k_NumMatchProbs];\n  \n  struct CProbEntry lzRepProbs[k_NumReps][k_NumRepProbs];\n  struct CProbEntry deltaRepProbs[k_NumReps][k_NumRepProbs];\n\n  CHuffDecoder<k_NumLitSyms, 1024, 9> m_LitDecoder;\n  CHuffDecoder<k_NumPosSyms, 1024, 9> m_PosDecoder;\n  CHuffDecoder<k_NumLenSyms, 512, 8> m_LenDecoder;\n  CHuffDecoder<k_NumPowerSyms, 512, 6> m_PowerDecoder;\n  CHuffDecoder<k_NumPosSyms, 1024, 9> m_DeltaDecoder;\n\n  Int32 *_x86_history;\n\n  HRESULT CodeReal(const Byte *in, size_t inSize, Byte *out, size_t outSize);\npublic:\n  CDecoder();\n  ~CDecoder();\n\n  HRESULT Code(const Byte *in, size_t inSize, Byte *out, size_t outSize);\n  size_t GetUnpackSize() const { return _pos; }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Lzx.h",
    "content": "﻿// Lzx.h\n\n#ifndef ZIP7_INC_COMPRESS_LZX_H\n#define ZIP7_INC_COMPRESS_LZX_H\n\n#include \"../../Common/MyTypes.h\"\n\nnamespace NCompress {\nnamespace NLzx {\n\nconst unsigned kBlockType_NumBits = 3;\nconst unsigned kBlockType_Verbatim = 1;\nconst unsigned kBlockType_Aligned = 2;\nconst unsigned kBlockType_Uncompressed = 3;\n\nconst unsigned kNumHuffmanBits = 16;\nconst unsigned kNumReps = 3;\n\nconst unsigned kNumLenSlots = 8;\nconst unsigned kMatchMinLen = 2;\nconst unsigned kNumLenSymbols = 249;\nconst unsigned kMatchMaxLen = kMatchMinLen + (kNumLenSlots - 1) + kNumLenSymbols - 1;\n\nconst unsigned kNumAlignLevelBits = 3;\nconst unsigned kNumAlignBits = 3;\nconst unsigned kAlignTableSize = 1 << kNumAlignBits;\n\nconst unsigned kNumPosSlots = 50;\nconst unsigned kNumPosLenSlots = kNumPosSlots * kNumLenSlots;\n\nconst unsigned kMainTableSize = 256 + kNumPosLenSlots;\nconst unsigned kLevelTableSize = 20;\nconst unsigned kMaxTableSize = kMainTableSize;\n\nconst unsigned kNumLevelBits = 4;\n\nconst unsigned kLevelSym_Zero1 = 17;\nconst unsigned kLevelSym_Zero2 = 18;\nconst unsigned kLevelSym_Same = 19;\n\nconst unsigned kLevelSym_Zero1_Start = 4;\nconst unsigned kLevelSym_Zero1_NumBits = 4;\n\nconst unsigned kLevelSym_Zero2_Start = kLevelSym_Zero1_Start + (1 << kLevelSym_Zero1_NumBits);\nconst unsigned kLevelSym_Zero2_NumBits = 5;\n\nconst unsigned kLevelSym_Same_NumBits = 1;\nconst unsigned kLevelSym_Same_Start = 4;\n \nconst unsigned kNumDictBits_Min = 15;\nconst unsigned kNumDictBits_Max = 21;\nconst UInt32 kDictSize_Max = (UInt32)1 << kNumDictBits_Max;\n\nconst unsigned kNumLinearPosSlotBits = 17;\n// const unsigned kNumPowerPosSlots = 38;\n// const unsigned kNumPowerPosSlots = (kNumLinearPosSlotBits + 1) * 2; // non-including two first linear slots.\nconst unsigned kNumPowerPosSlots = (kNumLinearPosSlotBits + 2) * 2; // including two first linear slots.\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzxDecoder.cpp",
    "content": "﻿// LzxDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include <string.h>\n// #include <stdio.h>\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/RotateDefs.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"LzxDecoder.h\"\n\n\n#ifdef MY_CPU_X86_OR_AMD64\n#if defined(MY_CPU_AMD64)  \\\n    || defined(__SSE2__) \\\n    || defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \\\n    || 0 && defined(_MSC_VER) && (_MSC_VER >= 1400) // set (1 &&) for debug\n  \n#if defined(__clang__) && (__clang_major__ >= 2) \\\n    || defined(__GNUC__) && (__GNUC__ >= 4) \\\n    || defined(_MSC_VER) && (_MSC_VER >= 1400)\n#define Z7_LZX_X86_FILTER_USE_SSE2\n#endif\n#endif\n#endif\n\n\n#ifdef Z7_LZX_X86_FILTER_USE_SSE2\n// #ifdef MY_CPU_X86_OR_AMD64\n#include <emmintrin.h> // SSE2\n// #endif\n  #if defined(__clang__) || defined(__GNUC__)\n    typedef int ctz_type;\n    #define MY_CTZ(dest, mask) dest = __builtin_ctz((UInt32)(mask))\n  #else  // #if defined(_MSC_VER)\n    #if (_MSC_VER >= 1600)\n      // #include <intrin.h>\n    #endif\n    typedef unsigned long ctz_type;\n    #define MY_CTZ(dest, mask)  _BitScanForward(&dest, (mask));\n  #endif // _MSC_VER\n#endif\n\n// when window buffer is filled, we must wrap position to zero,\n// and we want to wrap at same points where original-lzx must wrap.\n// But the wrapping is possible in point where chunk is finished.\n// Usually (chunk_size == 32KB), but (chunk_size != 32KB) also is allowed.\n// So we don't use additional buffer space over required (winSize).\n// And we can't use large overwrite after (len) in CopyLzMatch().\n// But we are allowed to write 3 bytes after (len), because\n// (delta <= _winSize - 3).\n\n// #define k_Lz_OverwriteSize  0  // for debug : to disable overwrite\n#define k_Lz_OverwriteSize  3 // = kNumReps\n#if k_Lz_OverwriteSize > 0\n// (k_Lz_OutBufSize_Add >= k_Lz_OverwriteSize) is required\n// we use value 4 to simplify memset() code.\n#define k_Lz_OutBufSize_Add  (k_Lz_OverwriteSize + 1) // == 4\n#else\n#define k_Lz_OutBufSize_Add  0\n#endif\n\n// (len != 0)\n// (0 < delta <= _winSize - 3)\nZ7_FORCE_INLINE\nvoid CopyLzMatch(Byte *dest, const Byte *src, UInt32 len, UInt32 delta)\n{\n  if (delta >= 4)\n  {\n#if k_Lz_OverwriteSize >= 3\n    // optimized code with overwrite to reduce the number of branches\n  #ifdef MY_CPU_LE_UNALIGN\n    *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);\n  #else\n    dest[0] = src[0];\n    dest[1] = src[1];\n    dest[2] = src[2];\n    dest[3] = src[3];\n  #endif\n    len--;\n    src++;\n    dest++;\n    {\n#else\n    // no overwrite in out buffer\n    dest[0] = src[0];\n    {\n      const unsigned m = (unsigned)len & 1;\n      src += m;\n      dest += m;\n    }\n    if (len &= ~(unsigned)1)\n    {\n      dest[0] = src[0];\n      dest[1] = src[1];\n#endif\n      // len == 0 is allowed here\n      {\n        const unsigned m = (unsigned)len & 3;\n        src += m;\n        dest += m;\n      }\n      if (len &= ~(unsigned)3)\n      {\n#ifdef MY_CPU_LE_UNALIGN\n      #if 1\n        *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);\n        {\n          const unsigned m = (unsigned)len & 7;\n          dest += m;\n          src += m;\n        }\n        if (len &= ~(unsigned)7)\n          do\n          {\n            *(UInt32 *)(void *)(dest    ) = *(const UInt32 *)(const void *)(src);\n            *(UInt32 *)(void *)(dest + 4) = *(const UInt32 *)(const void *)(src + 4);\n            src += 8;\n            dest += 8;\n          }\n          while (len -= 8);\n      #else\n        // gcc-11 -O3 for x64 generates incorrect code here\n        do\n        {\n          *(UInt32 *)(void *)(dest) = *(const UInt32 *)(const void *)(src);\n          src += 4;\n          dest += 4;\n        }\n        while (len -= 4);\n      #endif\n#else\n        do\n        {\n          const Byte b0 = src[0];\n          const Byte b1 = src[1];\n          dest[0] = b0;\n          dest[1] = b1;\n          const Byte b2 = src[2];\n          const Byte b3 = src[3];\n          dest[2] = b2;\n          dest[3] = b3;\n          src += 4;\n          dest += 4;\n        }\n        while (len -= 4);\n#endif\n      }\n    }\n  }\n  else // (delta < 4)\n  {\n    const unsigned b0 = *src;\n    *dest = (Byte)b0;\n    if (len >= 2)\n    {\n      if (delta < 2)\n      {\n        dest += (unsigned)len & 1;\n        dest[0] = (Byte)b0;\n        dest[1] = (Byte)b0;\n        dest += (unsigned)len & 2;\n        if (len &= ~(unsigned)3)\n        {\n#ifdef MY_CPU_LE_UNALIGN\n          #ifdef MY_CPU_64BIT\n          const UInt64 a = (UInt64)b0 * 0x101010101010101;\n          *(UInt32 *)(void *)dest = (UInt32)a;\n          dest += (unsigned)len & 7;\n          if (len &= ~(unsigned)7)\n          {\n            // *(UInt64 *)(void *)dest = a;\n            // dest += 8;\n            // len -= 8;\n            // if (len)\n            {\n              // const ptrdiff_t delta = (ptrdiff_t)dest & 7;\n              // dest -= delta;\n              do\n              {\n                *(UInt64 *)(void *)dest = a;\n                dest += 8;\n              }\n              while (len -= 8);\n              // dest += delta - 8;\n              // *(UInt64 *)(void *)dest = a;\n            }\n          }\n          #else\n          const UInt32 a = (UInt32)b0 * 0x1010101;\n          do\n          {\n            *(UInt32 *)(void *)dest = a;\n            dest += 4;\n          }\n          while (len -= 4);\n          #endif\n#else\n          do\n          {\n            dest[0] = (Byte)b0;\n            dest[1] = (Byte)b0;\n            dest[2] = (Byte)b0;\n            dest[3] = (Byte)b0;\n            dest += 4;\n          }\n          while (len -= 4);\n#endif\n        }\n      }\n      else if (delta == 2)\n      {\n        const unsigned m = (unsigned)len & 1;\n        len &= ~(unsigned)1;\n        src += m;\n        dest += m;\n        {\n          const Byte a0 = src[0];\n          const Byte a1 = src[1];\n          do\n          {\n            dest[0] = a0;\n            dest[1] = a1;\n            dest += 2;\n          }\n          while (len -= 2);\n        }\n      }\n      else /* if (delta == 3) */\n      {\n        const unsigned b1 = src[1];\n        dest[1] = (Byte)b1;\n        if (len -= 2)\n        {\n          const unsigned b2 = src[2];\n          dest += 2;\n          do\n          {\n            dest[0] = (Byte)b2;  if (--len == 0) break;\n            dest[1] = (Byte)b0;  if (--len == 0) break;\n            dest[2] = (Byte)b1;\n            dest += 3;\n          }\n          while (--len);\n        }\n      }\n    }\n  }\n}\n\n// #define Z7_LZX_SHOW_STAT\n#ifdef Z7_LZX_SHOW_STAT\n#include <stdio.h>\n#endif\n\nnamespace NCompress {\nnamespace NLzx {\n\n// #define Z7_LZX_SHOW_STAT\n#ifdef Z7_LZX_SHOW_STAT\nstatic UInt32 g_stats_Num_x86[3];\nstatic UInt32 g_stats_NumTables;\nstatic UInt32 g_stats_NumLits;\nstatic UInt32 g_stats_NumAlign;\nstatic UInt32 g_stats_main[kMainTableSize];\nstatic UInt32 g_stats_len[kNumLenSymbols];\nstatic UInt32 g_stats_main_levels[kNumHuffmanBits + 1];\nstatic UInt32 g_stats_len_levels[kNumHuffmanBits + 1];\n#define UPDATE_STAT(a) a\nstatic void PrintVal(UInt32 v)\n{\n  printf(\"\\n    : %9u\", v);\n}\nstatic void PrintStat(const char *name, const UInt32 *a, size_t num)\n{\n  printf(\"\\n\\n==== %s:\", name);\n  UInt32 sum = 0;\n  size_t i;\n  for (i = 0; i < num; i++)\n    sum += a[i];\n  PrintVal(sum);\n  if (sum != 0)\n  {\n    for (i = 0; i < num; i++)\n    {\n      if (i % 8 == 0)\n        printf(\"\\n\");\n      printf(\"\\n%3x : %9u : %5.2f\", (unsigned)i, (unsigned)a[i], (double)a[i] * 100 / sum);\n    }\n  }\n  printf(\"\\n\");\n}\n\nstatic struct CStat\n{\n  ~CStat()\n  {\n    PrintStat(\"x86_filter\", g_stats_Num_x86, Z7_ARRAY_SIZE(g_stats_Num_x86));\n    printf(\"\\nTables:\"); PrintVal(g_stats_NumTables);\n    printf(\"\\nLits:\");   PrintVal(g_stats_NumLits);\n    printf(\"\\nAlign:\");  PrintVal(g_stats_NumAlign);\n    PrintStat(\"Main\", g_stats_main, Z7_ARRAY_SIZE(g_stats_main));\n    PrintStat(\"Len\", g_stats_len, Z7_ARRAY_SIZE(g_stats_len));\n    PrintStat(\"Main Levels\", g_stats_main_levels, Z7_ARRAY_SIZE(g_stats_main_levels));\n    PrintStat(\"Len Levels\", g_stats_len_levels, Z7_ARRAY_SIZE(g_stats_len_levels));\n  }\n} g_stat;\n#else\n#define UPDATE_STAT(a)\n#endif\n\n\n\n/*\n3 p015  : ivb-   : or r32,r32 / add r32,r32\n4 p0156 : hsw+\n5 p0156b: adl+\n2 p0_5  : ivb-   : shl r32,i8\n2 p0__6 : hsw+\n1 p5    : ivb-   : jb\n2 p0__6 : hsw+\n2 p0_5  : wsm-    : SSE2  : pcmpeqb  : _mm_cmpeq_epi8\n2 p_15  : snb-bdw\n2 p01   : skl+\n1 p0              : SSE2  : pmovmskb : _mm_movemask_epi8\n*/\n/*\n  v24.00: the code was fixed for more compatibility with original-ms-cab-decoder.\n  for ((Int32)translationSize >= 0) : LZX specification shows the code with signed Int32.\n  for ((Int32)translationSize <  0) : no specification for that case, but we support that case.\n  We suppose our code now is compatible with original-ms-cab-decoder.\n\n  Starting byte of data stream (real_pos == 0) is special corner case,\n  where we don't need any conversion (as in original-ms-cab-decoder).\n  Our optimization: we use unsigned (UInt32 pos) (pos = -1 - real_pos).\n  So (pos) is always negative: ((Int32)pos < 0).\n  It allows us to use simple comparison (v > pos) instead of more complex comparisons.\n*/\n// (p) will point 5 bytes after 0xe8 byte:\n// pos == -1 - (p - 5 - data_start) == 4 + data_start - p\n// (FILTER_PROCESSED_SIZE_DELTA == 4) is optimized value for better speed in some compilers:\n#define FILTER_PROCESSED_SIZE_DELTA  4\n\n#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_OR_ARM64)\n  // optimized branch:\n  // size_t must be at least 32-bit for this branch.\n  #if 1 // use 1 for simpler code\n    // use integer (low 32 bits of pointer) instead of pointer\n    #define X86_FILTER_PREPARE  processedSize4 = (UInt32)(size_t)(ptrdiff_t)data + \\\n        (UInt32)(4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;\n    #define X86_FILTER_CALC_pos(p)  const UInt32 pos = processedSize4 - (UInt32)(size_t)(ptrdiff_t)p;\n  #else\n    // note: (dataStart) pointer can point out of array ranges:\n    #define X86_FILTER_PREPARE  const Byte *dataStart = data + \\\n                (4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;\n    #define X86_FILTER_CALC_pos(p)  const UInt32 pos = (UInt32)(size_t)(dataStart - p);\n  #endif\n#else\n  // non-optimized branch for unusual platforms (16-bit size_t or unusual size_t):\n    #define X86_FILTER_PREPARE  processedSize4 = \\\n        (UInt32)(4 - FILTER_PROCESSED_SIZE_DELTA) - processedSize4;\n    #define X86_FILTER_CALC_pos(p)  const UInt32 pos = processedSize4 - (UInt32)(size_t)(p - data);\n#endif\n\n#define X86_TRANSLATE_PRE(p) \\\n    UInt32 v = GetUi32((p) - 4);\n\n#define X86_TRANSLATE_POST(p) \\\n  { \\\n    X86_FILTER_CALC_pos(p) \\\n    if (v < translationSize) { \\\n      UPDATE_STAT(g_stats_Num_x86[0]++;) \\\n      v += pos + 1; \\\n      SetUi32((p) - 4, v) \\\n    } \\\n    else if (v > pos) { \\\n      UPDATE_STAT(g_stats_Num_x86[1]++;) \\\n      v += translationSize; \\\n      SetUi32((p) - 4, v) \\\n    } else { UPDATE_STAT(g_stats_Num_x86[2]++;) } \\\n  }\n\n\n/*\n  if (   defined(Z7_LZX_X86_FILTER_USE_SSE2)\n      && defined(Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED))\n    the function can read up to aligned_for_32_up_from(size) bytes in (data).\n*/\n// processedSize < (1 << 30)\nZ7_NO_INLINE\nstatic void x86_Filter4(Byte *data, size_t size, UInt32 processedSize4, UInt32 translationSize)\n{\n  const size_t kResidue = 10;\n  if (size <= kResidue)\n    return;\n  Byte * const lim = data + size - kResidue + 4;\n  const Byte save = lim[0];\n  lim[0] = 0xe8;\n  X86_FILTER_PREPARE\n  Byte *p = data;\n\n#define FILTER_RETURN_IF_LIM(_p_)  if (_p_ > lim) { lim[0] = save; return; }\n\n#ifdef Z7_LZX_X86_FILTER_USE_SSE2\n\n// sse2-aligned/sse2-unaligned provide same speed on real data.\n// but the code is smaller for sse2-unaligned version.\n// for debug : define it to get alternative version with aligned 128-bit reads:\n// #define Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED\n\n#define FILTER_MASK_INT  UInt32\n#define FILTER_NUM_VECTORS_IN_CHUNK   2\n#define FILTER_CHUNK_BYTES_OFFSET     (16 * FILTER_NUM_VECTORS_IN_CHUNK - 5)\n\n#ifdef Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED\n  // aligned version doesn't uses additional space if buf size is aligned for 32\n  #define k_Filter_OutBufSize_Add  0\n  #define k_Filter_OutBufSize_AlignMask  (16 * FILTER_NUM_VECTORS_IN_CHUNK - 1)\n  #define FILTER_LOAD_128(p)  _mm_load_si128 ((const __m128i *)(const void *)(p))\n#else\n  #define k_Filter_OutBufSize_Add  (16 * FILTER_NUM_VECTORS_IN_CHUNK)\n  #define k_Filter_OutBufSize_AlignMask 0\n  #define FILTER_LOAD_128(p)  _mm_loadu_si128((const __m128i *)(const void *)(p))\n#endif\n\n#define GET_E8_MASK(dest, dest1, p) \\\n{ \\\n  __m128i v0 = FILTER_LOAD_128(p); \\\n  __m128i v1 = FILTER_LOAD_128(p + 16); \\\n  p += 16 * FILTER_NUM_VECTORS_IN_CHUNK; \\\n  v0 = _mm_cmpeq_epi8(v0, k_e8_Vector); \\\n  v1 = _mm_cmpeq_epi8(v1, k_e8_Vector); \\\n  dest  = (unsigned)_mm_movemask_epi8(v0); \\\n  dest1 = (unsigned)_mm_movemask_epi8(v1); \\\n}\n\n  const __m128i k_e8_Vector = _mm_set1_epi32((Int32)(UInt32)0xe8e8e8e8);\n  for (;;)\n  {\n      // for debug: define it for smaller code:\n      // #define Z7_LZX_X86_FILTER_CALC_IN_LOOP\n      // without Z7_LZX_X86_FILTER_CALC_IN_LOOP, we can get faster and simpler loop\n    FILTER_MASK_INT mask;\n    {\n      FILTER_MASK_INT mask1;\n      do\n      {\n        GET_E8_MASK(mask, mask1, p)\n        #ifndef Z7_LZX_X86_FILTER_CALC_IN_LOOP\n          mask += mask1;\n        #else\n          mask |= mask1 << 16;\n        #endif\n      }\n      while (!mask);\n     \n      #ifndef Z7_LZX_X86_FILTER_CALC_IN_LOOP\n        mask -= mask1;\n        mask |= mask1 << 16;\n      #endif\n    }\n      \n#ifdef Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED\n    for (;;)\n    {\n      ctz_type index;\n      typedef\n      #ifdef MY_CPU_64BIT\n        UInt64\n      #else\n        UInt32\n      #endif\n        SUPER_MASK_INT;\n      SUPER_MASK_INT superMask;\n      {\n        MY_CTZ(index, mask);\n        Byte *p2 = p - FILTER_CHUNK_BYTES_OFFSET + (unsigned)index;\n        X86_TRANSLATE_PRE(p2)\n        superMask = ~(SUPER_MASK_INT)0x1f << index;\n        FILTER_RETURN_IF_LIM(p2)\n        X86_TRANSLATE_POST(p2)\n        mask &= (UInt32)superMask;\n      }\n      if (mask)\n        continue;\n      if (index <= FILTER_CHUNK_BYTES_OFFSET)\n        break;\n      {\n        FILTER_MASK_INT mask1;\n        GET_E8_MASK(mask, mask1, p)\n        mask &=\n            #ifdef MY_CPU_64BIT\n              (UInt32)(superMask >> 32);\n            #else\n              ((FILTER_MASK_INT)0 - 1) << ((int)index - FILTER_CHUNK_BYTES_OFFSET);\n            #endif\n        mask |= mask1 << 16;\n      }\n      if (!mask)\n        break;\n    }\n#else // ! Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED\n    {\n      // we use simplest version without loop:\n      // for (;;)\n      {\n        ctz_type index;\n        MY_CTZ(index, mask);\n        /*\n        printf(\"\\np=%p, mask=%8x, index = %2d, p + index = %x\\n\",\n            (p - 16 * FILTER_NUM_VECTORS_IN_CHUNK), (unsigned)mask,\n            (unsigned)index, (unsigned)((unsigned)(ptrdiff_t)(p - 16 * FILTER_NUM_VECTORS_IN_CHUNK) + index));\n        */\n        p += (size_t)(unsigned)index - FILTER_CHUNK_BYTES_OFFSET;\n        FILTER_RETURN_IF_LIM(p)\n        // mask &= ~(FILTER_MASK_INT)0x1f << index;  mask >>= index;\n        X86_TRANSLATE_PRE(p)\n        X86_TRANSLATE_POST(p)\n        // if (!mask) break; // p += 16 * FILTER_NUM_VECTORS_IN_CHUNK;\n      }\n    }\n#endif // ! Z7_LZX_X86_FILTER_USE_SSE2_ALIGNED\n  }\n\n#else // ! Z7_LZX_X86_FILTER_USE_SSE2\n\n#define k_Filter_OutBufSize_Add  0\n#define k_Filter_OutBufSize_AlignMask 0\n\n\n  for (;;)\n  {\n    for (;;)\n    {\n      if (p[0] == 0xe8) { p += 5; break; }\n      if (p[1] == 0xe8) { p += 6; break; }\n      if (p[2] == 0xe8) { p += 7; break; }\n      p += 4;\n      if (p[-1] == 0xe8) { p += 4; break; }\n    }\n    FILTER_RETURN_IF_LIM(p)\n    X86_TRANSLATE_PRE(p)\n    X86_TRANSLATE_POST(p)\n  }\n\n#endif // ! Z7_LZX_X86_FILTER_USE_SSE2\n}\n\n\nCDecoder::CDecoder() throw():\n    _win(NULL),\n    _isUncompressedBlock(false),\n    _skipByte(false),\n    _keepHistory(false),\n    _keepHistoryForNext(true),\n    _needAlloc(true),\n    _wimMode(false),\n    _numDictBits(15),\n    _unpackBlockSize(0),\n    _x86_translationSize(0),\n    _x86_buf(NULL),\n    _unpackedData(NULL)\n{\n  {\n    // it's better to get empty virtual entries, if mispredicted value can be used:\n    memset(_reps, 0, kPosSlotOffset * sizeof(_reps[0]));\n    memset(_extra, 0, kPosSlotOffset);\n#define SET_NUM_BITS(i) i // #define NUM_BITS_DELTA 31\n    _extra[kPosSlotOffset + 0] = SET_NUM_BITS(0);\n    _extra[kPosSlotOffset + 1] = SET_NUM_BITS(0);\n    // reps[0] = 0 - (kNumReps - 1);\n    // reps[1] = 1 - (kNumReps - 1);\n    UInt32 a = 2 - (kNumReps - 1);\n    UInt32 delta = 1;\n    unsigned i;\n    for (i = 0; i < kNumLinearPosSlotBits; i++)\n    {\n      _extra[(size_t)i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));\n      _extra[(size_t)i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));\n      _reps [(size_t)i * 2 + 2 + kPosSlotOffset] = a;  a += delta;\n      _reps [(size_t)i * 2 + 3 + kPosSlotOffset] = a;  a += delta;\n      delta += delta;\n    }\n    for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)\n    {\n      _extra[(size_t)i + kPosSlotOffset] = SET_NUM_BITS(kNumLinearPosSlotBits);\n      _reps [(size_t)i + kPosSlotOffset] = a;\n      a += (UInt32)1 << kNumLinearPosSlotBits;\n    }\n  }\n}\n\nCDecoder::~CDecoder() throw()\n{\n  if (_needAlloc)\n    // BigFree\n    z7_AlignedFree\n      (_win);\n  z7_AlignedFree(_x86_buf);\n}\n\nHRESULT CDecoder::Flush() throw()\n{\n  // UInt32 t = _x86_processedSize; for (int y = 0; y < 50; y++) { _x86_processedSize = t; // benchmark: (branch predicted)\n  if (_x86_translationSize != 0)\n  {\n    Byte *destData = _win + _writePos;\n    const UInt32 curSize = _pos - _writePos;\n    if (_keepHistoryForNext)\n    {\n      const size_t kChunkSize = (size_t)1 << 15;\n      if (curSize > kChunkSize)\n        return E_NOTIMPL;\n      if (!_x86_buf)\n      {\n        // (kChunkSize % 32 == 0) is required in some cases, because\n        // the filter can read data by 32-bytes chunks in some cases.\n        // if (chunk_size > (1 << 15)) is possible, then we must the code:\n        const size_t kAllocSize = kChunkSize + k_Filter_OutBufSize_Add;\n        _x86_buf = (Byte *)z7_AlignedAlloc(kAllocSize);\n        if (!_x86_buf)\n          return E_OUTOFMEMORY;\n        #if 0 != k_Filter_OutBufSize_Add || \\\n            0 != k_Filter_OutBufSize_AlignMask\n          // x86_Filter4() can read after curSize.\n          // So we set all data to zero to prevent reading of uninitialized data:\n          memset(_x86_buf, 0, kAllocSize); // optional\n        #endif\n      }\n      // for (int yy = 0; yy < 1; yy++) // for debug\n      memcpy(_x86_buf, destData, curSize);\n      _unpackedData = _x86_buf;\n      destData = _x86_buf;\n    }\n    else\n    {\n      // x86_Filter4() can overread after (curSize),\n      // so we can do memset() after (curSize):\n      // k_Filter_OutBufSize_AlignMask also can be used\n      // if (!_overDict) memset(destData + curSize, 0, k_Filter_OutBufSize_Add);\n    }\n    x86_Filter4(destData, curSize, _x86_processedSize - FILTER_PROCESSED_SIZE_DELTA, _x86_translationSize);\n    _x86_processedSize += (UInt32)curSize;\n    if (_x86_processedSize >= ((UInt32)1 << 30))\n      _x86_translationSize = 0;\n  }\n  // }\n  return S_OK;\n}\n\n\n\n// (NUM_DELTA_BYTES == 2) reduces the code in main loop.\n#if 1\n  #define NUM_DELTA_BYTES  2\n#else\n  #define NUM_DELTA_BYTES  0\n#endif\n\n#define NUM_DELTA_BIT_OFFSET_BITS  (NUM_DELTA_BYTES * 8)\n\n#if NUM_DELTA_BIT_OFFSET_BITS > 0\n  #define DECODE_ERROR_CODE  0\n  #define IS_OVERFLOW_bitOffset(bo)  ((bo) >= 0)\n  // ( >= 0) comparison after bitOffset change gives simpler commands than ( > 0) comparison\n#else\n  #define DECODE_ERROR_CODE  1\n  #define IS_OVERFLOW_bitOffset(bo)  ((bo) >  0)\n#endif\n\n// (numBits != 0)\n#define GET_VAL_BASE(numBits)  (_value >> (32 - (numBits)))\n\n#define Z7_LZX_HUFF_DECODE( sym, huff, kNumTableBits, move_pos_op, check_op, error_op) \\\n    Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, huff, kNumHuffmanBits, kNumTableBits,  \\\n        _value, check_op, error_op, move_pos_op, NORMALIZE, bs)\n\n#define Z7_LZX_HUFF_DECODE_CHECK_YES(sym, huff, kNumTableBits, move_pos_op) \\\n        Z7_LZX_HUFF_DECODE(          sym, huff, kNumTableBits, move_pos_op, \\\n            Z7_HUFF_DECODE_ERROR_SYM_CHECK_YES, { return DECODE_ERROR_CODE; })\n\n#define Z7_LZX_HUFF_DECODE_CHECK_NO( sym, huff, kNumTableBits, move_pos_op) \\\n        Z7_LZX_HUFF_DECODE(          sym, huff, kNumTableBits, move_pos_op, \\\n            Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {})\n\n#define NORMALIZE \\\n{ \\\n  const Byte *ptr = _buf + (_bitOffset >> 4) * 2; \\\n  /* _value = (((UInt32)GetUi16(ptr) << 16) | GetUi16(ptr + 2)) << (_bitOffset & 15); */ \\\n  const UInt32 v = GetUi32(ptr); \\\n  _value = rotlFixed (v, ((int)_bitOffset & 15) + 16); \\\n}\n\n#define MOVE_POS(bs, numBits) \\\n{ \\\n  _bitOffset += numBits; \\\n}\n\n#define MOVE_POS_STAT(bs, numBits) \\\n{ \\\n  UPDATE_STAT(g_stats_len_levels[numBits]++;) \\\n  MOVE_POS(bs, numBits); \\\n}\n\n#define MOVE_POS_CHECK(bs, numBits) \\\n{ \\\n  if (IS_OVERFLOW_bitOffset(_bitOffset += numBits)) return DECODE_ERROR_CODE; \\\n}\n\n#define MOVE_POS_CHECK_STAT(bs, numBits) \\\n{ \\\n  UPDATE_STAT(g_stats_main_levels[numBits]++;) \\\n  MOVE_POS_CHECK(bs, numBits) \\\n}\n\n\n// (numBits == 0) is supported\n\n#ifdef Z7_HUFF_USE_64BIT_LIMIT\n\n#define MACRO_ReadBitsBig_pre(numBits) \\\n{ \\\n  _bitOffset += (numBits); \\\n  _value >>= 32 - (numBits); \\\n}\n\n#else\n\n#define MACRO_ReadBitsBig_pre(numBits) \\\n{ \\\n  _bitOffset += (numBits); \\\n  _value = (UInt32)((UInt32)_value >> 1 >> (31 ^ (numBits))); \\\n}\n\n#endif\n\n\n#define MACRO_ReadBitsBig_add(dest) \\\n  { dest += (UInt32)_value; }\n\n#define MACRO_ReadBitsBig_add3(dest) \\\n  { dest += (UInt32)(_value) << 3; }\n\n\n// (numBits != 0)\n#define MACRO_ReadBits_NonZero(val, numBits) \\\n{ \\\n  val = (UInt32)(_value >> (32 - (numBits))); \\\n  MOVE_POS(bs, numBits); \\\n  NORMALIZE \\\n}\n\n\nstruct CBitDecoder\n{\n  ptrdiff_t _bitOffset;\n  const Byte *_buf;\n\n  Z7_FORCE_INLINE\n  UInt32 GetVal() const\n  {\n    const Byte *ptr = _buf + (_bitOffset >> 4) * 2;\n    const UInt32 v = GetUi32(ptr);\n    return rotlFixed (v, ((int)_bitOffset & 15) + 16);\n  }\n\n  Z7_FORCE_INLINE\n  bool IsOverRead() const\n  {\n    return _bitOffset > (int)(0 - NUM_DELTA_BIT_OFFSET_BITS);\n  }\n\n\n  Z7_FORCE_INLINE\n  bool WasBitStreamFinishedOK() const\n  {\n    // we check that all 0-15 unused bits are zeros:\n    if (_bitOffset == 0 - NUM_DELTA_BIT_OFFSET_BITS)\n      return true;\n    if ((_bitOffset + NUM_DELTA_BIT_OFFSET_BITS + 15) & ~(ptrdiff_t)15)\n      return false;\n    const Byte *ptr = _buf - NUM_DELTA_BYTES - 2;\n    if ((UInt16)(GetUi16(ptr) << (_bitOffset & 15)))\n      return false;\n    return true;\n  }\n\n  // (numBits != 0)\n  Z7_FORCE_INLINE\n  UInt32 ReadBits_NonZero(unsigned numBits) throw()\n  {\n    const UInt32 val = GetVal() >> (32 - numBits);\n    _bitOffset += numBits;\n    return val;\n  }\n};\n\n\nclass CBitByteDecoder: public CBitDecoder\n{\n  size_t _size;\npublic:\n\n  Z7_FORCE_INLINE\n  void Init_ByteMode(const Byte *data, size_t size)\n  {\n    _buf = data;\n    _size = size;\n  }\n\n  Z7_FORCE_INLINE\n  void Init_BitMode(const Byte *data, size_t size)\n  {\n    _size = size & 1;\n    size &= ~(size_t)1;\n    _buf = data + size + NUM_DELTA_BYTES;\n    _bitOffset = 0 - (ptrdiff_t)(size * 8) - NUM_DELTA_BIT_OFFSET_BITS;\n  }\n\n  Z7_FORCE_INLINE\n  void Switch_To_BitMode()\n  {\n    Init_BitMode(_buf, _size);\n  }\n\n  Z7_FORCE_INLINE\n  bool Switch_To_ByteMode()\n  {\n    /* here we check that unused bits in high 16-bits word are zeros.\n       If high word is full (all 16-bits are unused),\n       we check that all 16-bits are zeros.\n       So we check and skip (1-16 bits) unused bits */\n    if ((GetVal() >> (16 + (_bitOffset & 15))) != 0)\n      return false;\n    _bitOffset += 16;\n    _bitOffset &= ~(ptrdiff_t)15;\n    if (_bitOffset > 0 - NUM_DELTA_BIT_OFFSET_BITS)\n      return false;\n    const ptrdiff_t delta = _bitOffset >> 3;\n    _size = (size_t)((ptrdiff_t)(_size) - delta - NUM_DELTA_BYTES);\n    _buf += delta;\n    // _bitOffset = 0; // optional\n    return true;\n  }\n\n  Z7_FORCE_INLINE\n  size_t GetRem() const { return _size; }\n\n  Z7_FORCE_INLINE\n  UInt32 ReadUInt32()\n  {\n    const Byte *ptr = _buf;\n    const UInt32 v = GetUi32(ptr);\n    _buf += 4;\n    _size -= 4;\n    return v;\n  }\n\n  Z7_FORCE_INLINE\n  void CopyTo(Byte *dest, size_t size)\n  {\n    memcpy(dest, _buf, size);\n    _buf += size;\n    _size -= size;\n  }\n\n  Z7_FORCE_INLINE\n  bool IsOneDirectByteLeft() const\n  {\n    return GetRem() == 1;\n  }\n\n  Z7_FORCE_INLINE\n  Byte DirectReadByte()\n  {\n    _size--;\n    return *_buf++;\n  }\n};\n\n\n// numBits != 0\n// Z7_FORCE_INLINE\nZ7_NO_INLINE\nstatic\nUInt32 ReadBits(CBitDecoder &_bitStream, unsigned numBits)\n{\n  return _bitStream.ReadBits_NonZero(numBits);\n}\n\n#define RIF(x) { if (!(x)) return false; }\n\n\n/*\nMSVC compiler adds extra move operation,\n  if we access array with 32-bit index\n    array[calc_index_32_bit(32-bit_var)]\n    where calc_index_32_bit operations are: ((unsigned)a>>cnt), &, ^, |\n  clang is also affected for ((unsigned)a>>cnt) in byte array.\n*/\n\n// it can overread input buffer for 7-17 bytes.\n// (levels != levelsEnd)\nZ7_NO_INLINE\nstatic ptrdiff_t ReadTable(ptrdiff_t _bitOffset, const Byte *_buf, Byte *levels, const Byte *levelsEnd)\n{\n  const unsigned kNumTableBits_Level = 7;\n  NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, kNumTableBits_Level> _levelDecoder;\n  NHuffman::CValueInt _value;\n  // optional check to reduce size of overread zone:\n  if (_bitOffset > (int)0 - (int)NUM_DELTA_BIT_OFFSET_BITS - (int)(kLevelTableSize * kNumLevelBits))\n    return DECODE_ERROR_CODE;\n  NORMALIZE\n  {\n    Byte levels2[kLevelTableSize / 4 * 4];\n    for (size_t i = 0; i < kLevelTableSize / 4 * 4; i += 4)\n    {\n      UInt32 val;\n      MACRO_ReadBits_NonZero(val, kNumLevelBits * 4)\n      levels2[i + 0] = (Byte)((val >> (3 * kNumLevelBits)));\n      levels2[i + 1] = (Byte)((val >> (2 * kNumLevelBits)) & ((1u << kNumLevelBits) - 1));\n      levels2[i + 2] = (Byte)((Byte)val >> (1 * kNumLevelBits));\n      levels2[i + 3] = (Byte)((val) & ((1u << kNumLevelBits) - 1));\n    }\n    RIF(_levelDecoder.Build(levels2, NHuffman::k_BuildMode_Full))\n  }\n  \n  do\n  {\n    unsigned sym;\n    Z7_LZX_HUFF_DECODE_CHECK_NO(sym, &_levelDecoder, kNumTableBits_Level, MOVE_POS_CHECK)\n    // Z7_HUFF_DECODE_CHECK(sym, &_levelDecoder, kNumHuffmanBits, kNumTableBits_Level, &bitStream, return false)\n    // sym = _levelDecoder.Decode(&bitStream);\n    // if (!_levelDecoder.Decode_SymCheck_MovePosCheck(&bitStream, sym)) return false;\n\n    if (sym <= kNumHuffmanBits)\n    {\n      int delta = (int)*levels - (int)sym;\n      delta += delta < 0 ? kNumHuffmanBits + 1 : 0;\n      *levels++ = (Byte)delta;\n      continue;\n    }\n    \n    unsigned num;\n    int symbol;\n\n    if (sym < kLevelSym_Same)\n    {\n      // sym -= kLevelSym_Zero1;\n      MACRO_ReadBits_NonZero(num, kLevelSym_Zero1_NumBits + (sym - kLevelSym_Zero1))\n      num += (sym << kLevelSym_Zero1_NumBits) - (kLevelSym_Zero1 << kLevelSym_Zero1_NumBits) + kLevelSym_Zero1_Start;\n      symbol = 0;\n    }\n    // else if (sym != kLevelSym_Same) return DECODE_ERROR_CODE;\n    else // (sym == kLevelSym_Same)\n    {\n      MACRO_ReadBits_NonZero(num, kLevelSym_Same_NumBits)\n      num += kLevelSym_Same_Start;\n      // + (unsigned)bitStream.ReadBitsSmall(kLevelSym_Same_NumBits);\n      // Z7_HUFF_DECODE_CHECK(sym, &_levelDecoder, kNumHuffmanBits, kNumTableBits_Level, &bitStream, return DECODE_ERROR_CODE)\n      // if (!_levelDecoder.Decode2(&bitStream, sym)) return DECODE_ERROR_CODE;\n      // sym = _levelDecoder.Decode(&bitStream);\n\n      Z7_LZX_HUFF_DECODE_CHECK_NO(sym, &_levelDecoder, kNumTableBits_Level, MOVE_POS)\n\n      if (sym > kNumHuffmanBits) return DECODE_ERROR_CODE;\n      symbol = *levels - (int)sym;\n      symbol += symbol < 0 ? kNumHuffmanBits + 1 : 0;\n    }\n\n    if (num > (size_t)(levelsEnd - levels))\n      return false;\n    const Byte *limit = levels + num;\n    do\n      *levels++ = (Byte)symbol;\n    while (levels != limit);\n  }\n  while (levels != levelsEnd);\n\n  return _bitOffset;\n}\n\n\nstatic const unsigned kPosSlotDelta = 256 / kNumLenSlots - kPosSlotOffset;\n\n\n#define READ_TABLE(_bitStream, levels, levelsEnd) \\\n{ \\\n  _bitStream._bitOffset = ReadTable(_bitStream._bitOffset, _bitStream._buf, levels, levelsEnd); \\\n  if (_bitStream.IsOverRead()) return false; \\\n}\n\n// can over-read input buffer for less than 32 bytes\nbool CDecoder::ReadTables(CBitByteDecoder &_bitStream) throw()\n{\n  UPDATE_STAT(g_stats_NumTables++;)\n  {\n    const unsigned blockType = (unsigned)ReadBits(_bitStream, kBlockType_NumBits);\n    // if (blockType > kBlockType_Uncompressed || blockType == 0)\n    if ((unsigned)(blockType - 1) > kBlockType_Uncompressed - 1)\n      return false;\n    _unpackBlockSize = 1u << 15;\n    if (!_wimMode || ReadBits(_bitStream, 1) == 0)\n    {\n      _unpackBlockSize = ReadBits(_bitStream, 16);\n      // wimlib supports chunks larger than 32KB (unsupported my MS wim).\n      if (!_wimMode || _numDictBits >= 16)\n      {\n        _unpackBlockSize <<= 8;\n        _unpackBlockSize |= ReadBits(_bitStream, 8);\n      }\n    }\n\n    PRF(printf(\"\\nBlockSize = %6d   %s  \", _unpackBlockSize, (_pos & 1) ? \"@@@\" : \"   \"));\n\n    _isUncompressedBlock = (blockType == kBlockType_Uncompressed);\n    _skipByte = false;\n\n    if (_isUncompressedBlock)\n    {\n      _skipByte = ((_unpackBlockSize & 1) != 0);\n      // printf(\"\\n UncompressedBlock %d\", _unpackBlockSize);\n      PRF(printf(\" UncompressedBlock \");)\n      // if (_unpackBlockSize & 1) { PRF(printf(\" ######### \")); }\n      if (!_bitStream.Switch_To_ByteMode())\n        return false;\n      if (_bitStream.GetRem() < kNumReps * 4)\n        return false;\n      for (unsigned i = 0; i < kNumReps; i++)\n      {\n        const UInt32 rep = _bitStream.ReadUInt32();\n        // here we allow only such values for (rep) that can be set also by LZ code:\n        if (rep == 0 || rep > _winSize - kNumReps)\n          return false;\n        _reps[(size_t)i + kPosSlotOffset] = rep;\n      }\n      // printf(\"\\n\");\n      return true;\n    }\n    \n    // _numAlignBits = 64;\n    // const UInt32 k_numAlignBits_PosSlots_MAX = 64 + kPosSlotDelta;\n    // _numAlignBits_PosSlots = k_numAlignBits_PosSlots_MAX;\n    const UInt32 k_numAlignBits_Dist_MAX = (UInt32)(Int32)-1;\n    _numAlignBits_Dist = k_numAlignBits_Dist_MAX;\n    if (blockType == kBlockType_Aligned)\n    {\n      Byte levels[kAlignTableSize];\n      // unsigned not0 = 0;\n      unsigned not3 = 0;\n      for (unsigned i = 0; i < kAlignTableSize; i++)\n      {\n        const unsigned val = ReadBits(_bitStream, kNumAlignLevelBits);\n        levels[i] = (Byte)val;\n        // not0 |= val;\n        not3 |= (val ^ 3);\n      }\n      // static unsigned number = 0, all = 0; all++;\n      // if (!not0) return false; // Build(true) will test this case\n      if (not3)\n      {\n        // _numAlignBits_PosSlots = (kNumAlignBits + 1) * 2 + kPosSlotDelta;\n        // _numAlignBits = kNumAlignBits;\n        _numAlignBits_Dist = (1u << (kNumAlignBits + 1)) - (kNumReps - 1);\n        RIF(_alignDecoder.Build(levels, true)) // full\n      }\n      // else { number++; if (number % 4 == 0) printf(\"\\nnumber= %u : %u%%\", number, number * 100 / all); }\n    }\n    // if (_numAlignBits_PosSlots == k_numAlignBits_PosSlots_MAX)\n    if (_numAlignBits_Dist == k_numAlignBits_Dist_MAX)\n    {\n      size_t i;\n      for (i = 3; i < kNumLinearPosSlotBits; i++)\n      {\n        _extra[i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));\n        _extra[i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i));\n      }\n      for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)\n        _extra[i + kPosSlotOffset] = (Byte)SET_NUM_BITS(kNumLinearPosSlotBits);\n    }\n    else\n    {\n      size_t i;\n      for (i = 3; i < kNumLinearPosSlotBits; i++)\n      {\n        _extra[i * 2 + 2 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i) - 3);\n        _extra[i * 2 + 3 + kPosSlotOffset] = (Byte)(SET_NUM_BITS(i) - 3);\n      }\n      for (i = kNumLinearPosSlotBits * 2 + 2; i < kNumPosSlots; i++)\n        _extra[i + kPosSlotOffset] = (Byte)(SET_NUM_BITS(kNumLinearPosSlotBits) - 3);\n    }\n  }\n\n  READ_TABLE(_bitStream, _mainLevels, _mainLevels + 256)\n  READ_TABLE(_bitStream, _mainLevels + 256, _mainLevels + 256 + _numPosLenSlots)\n  const unsigned end = 256 + _numPosLenSlots;\n  memset(_mainLevels + end, 0, kMainTableSize - end);\n  // #define NUM_CYC 1\n  // unsigned j; for (j = 0; j < NUM_CYC; j++)\n  RIF(_mainDecoder.Build(_mainLevels, NHuffman::k_BuildMode_Full))\n  // if (kNumLenSymols_Big_Start)\n  memset(_lenLevels, 0, kNumLenSymols_Big_Start);\n  READ_TABLE(_bitStream,\n      _lenLevels + kNumLenSymols_Big_Start,\n      _lenLevels + kNumLenSymols_Big_Start + kNumLenSymbols)\n  // for (j = 0; j < NUM_CYC; j++)\n  RIF(_lenDecoder.Build(_lenLevels, NHuffman::k_BuildMode_Full_or_Empty))\n  return true;\n}\n\n\n\nstatic ptrdiff_t CodeLz(CDecoder *dec, size_t next, ptrdiff_t _bitOffset, const Byte *_buf) throw()\n{\n  {\n    Byte *const win = dec->_win;\n    const UInt32 winSize = dec->_winSize;\n    Byte *pos = win + dec->_pos;\n    const Byte * const posEnd = pos + next;\n    NHuffman::CValueInt _value;\n\n    NORMALIZE\n\n#if 1\n  #define HUFF_DEC_PREFIX  dec->\n#else\n    const NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main> _mainDecoder = dec->_mainDecoder;\n    const NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymbols, kNumTableBits_Len> _lenDecoder = dec->_lenDecoder;\n    const NHuffman::CDecoder7b<kAlignTableSize> _alignDecoder = dec->_alignDecoder;\n  #define HUFF_DEC_PREFIX\n#endif\n\n    do\n    {\n      unsigned sym;\n      // printf(\"\\npos = %6u\", pos - win);\n      {\n        const NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main>\n            *mainDecoder = & HUFF_DEC_PREFIX _mainDecoder;\n        Z7_LZX_HUFF_DECODE_CHECK_NO(sym, mainDecoder, kNumTableBits_Main, MOVE_POS_CHECK_STAT)\n      }\n      // if (!_mainDecoder.Decode_SymCheck_MovePosCheck(&bitStream, sym)) return DECODE_ERROR_CODE;\n      // sym = _mainDecoder.Decode(&bitStream);\n      // if (bitStream.WasExtraReadError_Fast()) return DECODE_ERROR_CODE;\n\n      // printf(\" sym = %3x\", sym);\n      UPDATE_STAT(g_stats_main[sym]++;)\n      \n      if (sym < 256)\n      {\n        UPDATE_STAT(g_stats_NumLits++;)\n        *pos++ = (Byte)sym;\n      }\n      else\n      {\n        // sym -= 256;\n        // if (sym >= _numPosLenSlots) return DECODE_ERROR_CODE;\n        const unsigned posSlot = sym / kNumLenSlots;\n        unsigned len = sym % kNumLenSlots + kMatchMinLen;\n        if (len == kNumLenSlots - 1 + kMatchMinLen)\n        {\n          const NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymbols, kNumTableBits_Len>\n              *lenDecoder = & HUFF_DEC_PREFIX _lenDecoder;\n          Z7_LZX_HUFF_DECODE_CHECK_YES(len, lenDecoder, kNumTableBits_Len, MOVE_POS_STAT)\n          // if (!_lenDecoder.Decode2(&bitStream, len)) return DECODE_ERROR_CODE;\n          // len = _lenDecoder.Decode(&bitStream);\n          // if (len >= kNumLenSymbols) return DECODE_ERROR_CODE;\n          UPDATE_STAT(g_stats_len[len - kNumLenSymols_Big_Start]++;)\n          len += kNumLenSlots - 1 + kMatchMinLen - kNumLenSymols_Big_Start;\n        }\n        /*\n        if ((next -= len) < 0)\n          return DECODE_ERROR_CODE;\n        */\n        UInt32 dist;\n        \n        dist = dec->_reps[(size_t)posSlot - kPosSlotDelta];\n        if (posSlot < kNumReps + 256 / kNumLenSlots)\n        {\n          // if (posSlot != kNumReps + kPosSlotDelta)\n          // if (posSlot - (kNumReps + kPosSlotDelta + 1) < 2)\n          dec->_reps[(size_t)posSlot - kPosSlotDelta] = dec->_reps[kPosSlotOffset];\n          /*\n          if (posSlot != kPosSlotDelta)\n          {\n            UInt32 temp = dist;\n            if (posSlot == kPosSlotDelta + 1)\n            {\n              dist = reps[1];\n              reps[1] = temp;\n            }\n            else\n            {\n              dist = reps[2];\n              reps[2] = temp;\n            }\n            // dist = reps[(size_t)(posSlot) - kPosSlotDelta];\n            // reps[(size_t)(posSlot) - kPosSlotDelta] = reps[0];\n            // reps[(size_t)(posSlot) - kPosSlotDelta] = temp;\n          }\n          */\n        }\n        else // if (posSlot != kNumReps + kPosSlotDelta)\n        {\n          unsigned numDirectBits;\n#if 0\n          if (posSlot < kNumPowerPosSlots + kPosSlotDelta)\n          {\n            numDirectBits = (posSlot - 2 - kPosSlotDelta) >> 1;\n            dist = (UInt32)(2 | (posSlot & 1)) << numDirectBits;\n          }\n          else\n          {\n            numDirectBits = kNumLinearPosSlotBits;\n            dist = (UInt32)(posSlot - 0x22 - kPosSlotDelta) << kNumLinearPosSlotBits;\n          }\n          dist -= kNumReps - 1;\n#else\n          numDirectBits = dec->_extra[(size_t)posSlot - kPosSlotDelta];\n          // dist = reps[(size_t)(posSlot) - kPosSlotDelta];\n#endif\n          dec->_reps[kPosSlotOffset + 2] =\n          dec->_reps[kPosSlotOffset + 1];\n          dec->_reps[kPosSlotOffset + 1] =\n          dec->_reps[kPosSlotOffset + 0];\n\n          // dist += val; dist += bitStream.ReadBitsBig(numDirectBits);\n          // if (posSlot >= _numAlignBits_PosSlots)\n          // if (numDirectBits >= _numAlignBits)\n          // if (val >= _numAlignBits_Dist)\n          // UInt32 val; MACRO_ReadBitsBig(val , numDirectBits)\n          // dist += val;\n          // dist += (UInt32)((UInt32)_value >> 1 >> (/* 31 ^ */ (numDirectBits)));\n          // MOVE_POS((numDirectBits ^ 31))\n          MACRO_ReadBitsBig_pre(numDirectBits)\n          // dist += (UInt32)_value;\n          if (dist >= dec->_numAlignBits_Dist)\n          {\n            // if (numDirectBits != _numAlignBits)\n            {\n              // UInt32 val;\n              // dist -= (UInt32)_value;\n              MACRO_ReadBitsBig_add3(dist)\n              NORMALIZE\n              // dist += (val << kNumAlignBits);\n              // dist += bitStream.ReadBitsSmall(numDirectBits - kNumAlignBits) << kNumAlignBits;\n            }\n            {\n              // const unsigned alignTemp = _alignDecoder.Decode(&bitStream);\n              const NHuffman::CDecoder7b<kAlignTableSize> *alignDecoder = & HUFF_DEC_PREFIX _alignDecoder;\n              unsigned alignTemp;\n              UPDATE_STAT(g_stats_NumAlign++;)\n              Z7_HUFF_DECODER_7B_DECODE(alignTemp, alignDecoder, GET_VAL_BASE, MOVE_POS, bs)\n              // NORMALIZE\n              // if (alignTemp >= kAlignTableSize) return DECODE_ERROR_CODE;\n              dist += alignTemp;\n            }\n          }\n          else\n          {\n            {\n              MACRO_ReadBitsBig_add(dist)\n              // dist += bitStream.ReadBitsSmall(numDirectBits - kNumAlignBits) << kNumAlignBits;\n            }\n          }\n          NORMALIZE\n          /*\n          else\n          {\n            UInt32 val;\n            MACRO_ReadBitsBig(val, numDirectBits)\n            dist += val;\n            // dist += bitStream.ReadBitsBig(numDirectBits);\n          }\n          */\n        }\n        dec->_reps[kPosSlotOffset + 0] = dist;\n\n        Byte *dest = pos;\n        if (len > (size_t)(posEnd - pos))\n          return DECODE_ERROR_CODE;\n        Int32 srcPos = (Int32)(pos - win);\n        pos += len;\n        srcPos -= (Int32)dist;\n        if (srcPos < 0) // fast version\n        {\n          if (!dec->_overDict)\n            return DECODE_ERROR_CODE;\n          srcPos &= winSize - 1;\n          UInt32 rem = winSize - (UInt32)srcPos;\n          if (len > rem)\n          {\n            len -= rem;\n            const Byte *src = win + (UInt32)srcPos;\n            do\n              *dest++ = *src++;\n            while (--rem);\n            srcPos = 0;\n          }\n        }\n        CopyLzMatch(dest, win + (UInt32)srcPos, len, dist);\n      }\n    }\n    while (pos != posEnd);\n    \n    return _bitOffset;\n  }\n}\n\n\n\n\n// inSize != 0\n// outSize != 0 ???\nHRESULT CDecoder::CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize) throw()\n{\n  // ((inSize & 1) != 0) case is possible, if current call will be finished with Uncompressed Block.\n  CBitByteDecoder _bitStream;\n  if (_keepHistory && _isUncompressedBlock)\n    _bitStream.Init_ByteMode(inData, inSize);\n  else\n    _bitStream.Init_BitMode(inData, inSize);\n \n  if (!_keepHistory)\n  {\n    _isUncompressedBlock = false;\n    _skipByte = false;\n    _unpackBlockSize = 0;\n    memset(_mainLevels, 0, sizeof(_mainLevels));\n    memset(_lenLevels, 0, sizeof(_lenLevels));\n    {\n      _x86_translationSize = 12000000;\n      if (!_wimMode)\n      {\n        _x86_translationSize = 0;\n        if (ReadBits(_bitStream, 1) != 0)\n        {\n          UInt32 v = ReadBits(_bitStream, 16) << 16;\n          v       |= ReadBits(_bitStream, 16);\n          _x86_translationSize = v;\n        }\n      }\n      _x86_processedSize = 0;\n    }\n    _reps[0 + kPosSlotOffset] = 1;\n    _reps[1 + kPosSlotOffset] = 1;\n    _reps[2 + kPosSlotOffset] = 1;\n  }\n\n  while (outSize)\n  {\n    /*\n    // check it for bit mode only:\n    if (_bitStream.WasExtraReadError_Fast())\n      return S_FALSE;\n    */\n    if (_unpackBlockSize == 0)\n    {\n      if (_skipByte)\n      {\n        if (_bitStream.GetRem() < 1)\n          return S_FALSE;\n        if (_bitStream.DirectReadByte() != 0)\n          return S_FALSE;\n      }\n      if (_isUncompressedBlock)\n        _bitStream.Switch_To_BitMode();\n      if (!ReadTables(_bitStream))\n        return S_FALSE;\n      continue;\n    }\n\n    // _unpackBlockSize != 0\n    UInt32 next = _unpackBlockSize;\n    if (next > outSize)\n        next = outSize;\n    // next != 0\n\n    // PRF(printf(\"\\nnext = %d\", (unsigned)next);)\n    \n    if (_isUncompressedBlock)\n    {\n      if (_bitStream.GetRem() < next)\n        return S_FALSE;\n      _bitStream.CopyTo(_win + _pos, next);\n      _pos += next;\n      _unpackBlockSize -= next;\n    }\n    else\n    {\n      _unpackBlockSize -= next;\n      _bitStream._bitOffset = CodeLz(this, next, _bitStream._bitOffset, _bitStream._buf);\n      if (_bitStream.IsOverRead())\n        return S_FALSE;\n      _pos += next;\n    }\n    outSize -= next;\n  }\n\n  // outSize == 0\n\n  if (_isUncompressedBlock)\n  {\n    /* we don't know where skipByte can be placed, if it's end of chunk:\n        1) in current chunk - there are such cab archives, if chunk is last\n        2) in next chunk - are there such archives ? */\n    if (_unpackBlockSize == 0\n        && _skipByte\n        // && outSize == 0\n        && _bitStream.IsOneDirectByteLeft())\n    {\n      _skipByte = false;\n      if (_bitStream.DirectReadByte() != 0)\n        return S_FALSE;\n    }\n  }\n\n  if (_bitStream.GetRem() != 0)\n    return S_FALSE;\n  if (!_isUncompressedBlock)\n    if (!_bitStream.WasBitStreamFinishedOK())\n      return S_FALSE;\n  return S_OK;\n}\n\n\n#if k_Filter_OutBufSize_Add > k_Lz_OutBufSize_Add\n  #define k_OutBufSize_Add  k_Filter_OutBufSize_Add\n#else\n  #define k_OutBufSize_Add  k_Lz_OutBufSize_Add\n#endif\n\nHRESULT CDecoder::Code_WithExceedReadWrite(const Byte *inData, size_t inSize, UInt32 outSize) throw()\n{\n  if (!_keepHistory)\n  {\n    _pos = 0;\n    _overDict = false;\n  }\n  else if (_pos == _winSize)\n  {\n    _pos = 0;\n    _overDict = true;\n#if k_OutBufSize_Add > 0\n    // data after (_winSize) can be used, because we can use overwrite.\n    // memset(_win + _winSize, 0, k_OutBufSize_Add);\n#endif\n  }\n  _writePos = _pos;\n  _unpackedData = _win + _pos;\n \n  if (outSize > _winSize - _pos)\n    return S_FALSE;\n  \n  PRF(printf(\"\\ninSize = %d\", (unsigned)inSize);)\n  PRF(if ((inSize & 1) != 0) printf(\"---------\");)\n\n  if (inSize == 0)\n    return S_FALSE;\n  const HRESULT res = CodeSpec(inData, inSize, outSize);\n  const HRESULT res2 = Flush();\n  return (res == S_OK ? res2 : res);\n}\n\n\nHRESULT CDecoder::SetParams2(unsigned numDictBits) throw()\n{\n  if (numDictBits < kNumDictBits_Min ||\n      numDictBits > kNumDictBits_Max)\n    return E_INVALIDARG;\n  _numDictBits = (Byte)numDictBits;\n  const unsigned numPosSlots2 = (numDictBits < 20) ?\n      numDictBits : 17 + (1u << (numDictBits - 18));\n  _numPosLenSlots = numPosSlots2 * (kNumLenSlots * 2);\n  return S_OK;\n}\n  \n\nHRESULT CDecoder::Set_DictBits_and_Alloc(unsigned numDictBits) throw()\n{\n  RINOK(SetParams2(numDictBits))\n  const UInt32 newWinSize = (UInt32)1 << numDictBits;\n  if (_needAlloc)\n  {\n    if (!_win || newWinSize != _winSize)\n    {\n      // BigFree\n      z7_AlignedFree\n        (_win);\n      _winSize = 0;\n      const size_t alloc_size = newWinSize + k_OutBufSize_Add;\n      _win = (Byte *)\n          // BigAlloc\n          z7_AlignedAlloc\n          (alloc_size);\n      if (!_win)\n        return E_OUTOFMEMORY;\n      // optional:\n      memset(_win, 0, alloc_size);\n    }\n  }\n  _winSize = newWinSize;\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/LzxDecoder.h",
    "content": "﻿// LzxDecoder.h\n\n#ifndef ZIP7_INC_LZX_DECODER_H\n#define ZIP7_INC_LZX_DECODER_H\n\n#include \"HuffmanDecoder.h\"\n#include \"Lzx.h\"\n\nnamespace NCompress {\nnamespace NLzx {\n\nconst unsigned kAdditionalOutputBufSize = 32 * 2;\n\nconst unsigned kNumTableBits_Main = 11;\nconst unsigned kNumTableBits_Len = 8;\n\n// if (kNumLenSymols_Big <= 256) we can  use NHuffman::CDecoder256\n// if (kNumLenSymols_Big >  256) we must use NHuffman::CDecoder\n// const unsigned kNumLenSymols_Big_Start = kNumLenSlots - 1 + kMatchMinLen;  // 8 - 1 + 2\nconst unsigned kNumLenSymols_Big_Start = 0;\n// const unsigned kNumLenSymols_Big_Start = 0;\nconst unsigned kNumLenSymols_Big = kNumLenSymols_Big_Start + kNumLenSymbols;\n\n#if 1\n  // for smallest structure size:\n  const unsigned kPosSlotOffset = 0;\n#else\n  // use virtual entries for mispredicted branches:\n  const unsigned kPosSlotOffset = 256 / kNumLenSlots;\n#endif\n\nclass CBitByteDecoder;\n\nclass CDecoder\n{\npublic:\n  UInt32 _pos;\n  UInt32 _winSize;\n  Byte *_win;\n\n  bool _overDict;\n  bool _isUncompressedBlock;\n  bool _skipByte;\n  bool _keepHistory;\n  bool _keepHistoryForNext;\n  bool _needAlloc;\n  bool _wimMode;\n  Byte _numDictBits;\n\n  // unsigned _numAlignBits_PosSlots;\n  // unsigned _numAlignBits;\n  UInt32 _numAlignBits_Dist;\nprivate:\n  unsigned _numPosLenSlots;\n  UInt32 _unpackBlockSize;\n\n  UInt32 _writePos;\n\n  UInt32 _x86_translationSize;\n  UInt32 _x86_processedSize;\n  Byte *_x86_buf;\n\n  Byte *_unpackedData;\npublic:\n  Byte  _extra[kPosSlotOffset + kNumPosSlots];\n  UInt32 _reps[kPosSlotOffset + kNumPosSlots];\n\n  NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, kNumTableBits_Main> _mainDecoder;\n  NHuffman::CDecoder256<kNumHuffmanBits, kNumLenSymols_Big, kNumTableBits_Len> _lenDecoder;\n  NHuffman::CDecoder7b<kAlignTableSize> _alignDecoder;\nprivate:\n  Byte _mainLevels[kMainTableSize];\n  Byte _lenLevels[kNumLenSymols_Big];\n\n  HRESULT Flush() throw();\n  bool ReadTables(CBitByteDecoder &_bitStream) throw();\n\n  HRESULT CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize) throw();\n  HRESULT SetParams2(unsigned numDictBits) throw();\npublic:\n  CDecoder() throw();\n  ~CDecoder() throw();\n  \n  void Set_WimMode(bool wimMode) { _wimMode = wimMode; }\n  void Set_KeepHistory(bool keepHistory) { _keepHistory = keepHistory; }\n  void Set_KeepHistoryForNext(bool keepHistoryForNext) { _keepHistoryForNext = keepHistoryForNext; }\n\n  HRESULT Set_ExternalWindow_DictBits(Byte *win, unsigned numDictBits)\n  {\n    _needAlloc = false;\n    _win = win;\n    _winSize = (UInt32)1 << numDictBits;\n    return SetParams2(numDictBits);\n  }\n  HRESULT Set_DictBits_and_Alloc(unsigned numDictBits) throw();\n\n  HRESULT Code_WithExceedReadWrite(const Byte *inData, size_t inSize, UInt32 outSize) throw();\n  \n  bool WasBlockFinished()     const { return _unpackBlockSize == 0; }\n  const Byte *GetUnpackData() const { return _unpackedData; }\n  UInt32 GetUnpackSize()      const { return _pos - _writePos; }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Mtf8.h",
    "content": "﻿// Mtf8.h\n\n#ifndef ZIP7_INC_COMPRESS_MTF8_H\n#define ZIP7_INC_COMPRESS_MTF8_H\n\n#include \"../../../C/CpuArch.h\"\n\nnamespace NCompress {\n\nstruct CMtf8Encoder\n{\n  Byte Buf[256];\n\n  unsigned FindAndMove(Byte v) throw()\n  {\n#if 1\n    Byte b = Buf[0];\n    if (v == b)\n      return 0;\n    Buf[0] = v;\n    for (unsigned pos = 0;;)\n    {\n      Byte a;\n      a = Buf[++pos];  Buf[pos] = b;  if (v == a) return pos;\n      b = Buf[++pos];  Buf[pos] = a;  if (v == b) return pos;\n    }\n#else\n    size_t pos;\n    for (pos = 0; Buf[pos] != v; pos++);\n    const unsigned resPos = (unsigned)pos;\n    for (; pos >= 8; pos -= 8)\n    {\n      Buf[pos] = Buf[pos - 1];\n      Buf[pos - 1] = Buf[pos - 2];\n      Buf[pos - 2] = Buf[pos - 3];\n      Buf[pos - 3] = Buf[pos - 4];\n      Buf[pos - 4] = Buf[pos - 5];\n      Buf[pos - 5] = Buf[pos - 6];\n      Buf[pos - 6] = Buf[pos - 7];\n      Buf[pos - 7] = Buf[pos - 8];\n    }\n    for (; pos != 0; pos--)\n      Buf[pos] = Buf[pos - 1];\n    Buf[0] = v;\n    return resPos;\n#endif\n  }\n};\n\n/*\nstruct CMtf8Decoder\n{\n  Byte Buf[256];\n\n  void StartInit() { memset(Buf, 0, sizeof(Buf)); }\n  void Add(unsigned pos, Byte val) { Buf[pos] = val;  }\n  Byte GetHead() const { return Buf[0]; }\n  Byte GetAndMove(unsigned pos)\n  {\n    Byte res = Buf[pos];\n    for (; pos >= 8; pos -= 8)\n    {\n      Buf[pos] = Buf[pos - 1];\n      Buf[pos - 1] = Buf[pos - 2];\n      Buf[pos - 2] = Buf[pos - 3];\n      Buf[pos - 3] = Buf[pos - 4];\n      Buf[pos - 4] = Buf[pos - 5];\n      Buf[pos - 5] = Buf[pos - 6];\n      Buf[pos - 6] = Buf[pos - 7];\n      Buf[pos - 7] = Buf[pos - 8];\n    }\n    for (; pos > 0; pos--)\n      Buf[pos] = Buf[pos - 1];\n    Buf[0] = res;\n    return res;\n  }\n};\n*/\n\n#ifdef MY_CPU_64BIT\n  typedef UInt64 CMtfVar;\n  #define Z7_MTF_MOVS 3\n#else\n  typedef UInt32 CMtfVar;\n  #define Z7_MTF_MOVS 2\n#endif\n\n#define Z7_MTF_MASK ((1 << Z7_MTF_MOVS) - 1)\n\n\nstruct CMtf8Decoder\n{\n  CMtfVar Buf[256 >> Z7_MTF_MOVS];\n\n  void StartInit() { memset(Buf, 0, sizeof(Buf)); }\n  void Add(unsigned pos, Byte val) { Buf[pos >> Z7_MTF_MOVS] |= ((CMtfVar)val << ((pos & Z7_MTF_MASK) << 3));  }\n  Byte GetHead() const { return (Byte)Buf[0]; }\n\n  Z7_FORCE_INLINE\n  Byte GetAndMove(unsigned pos) throw()\n  {\n    const UInt32 lim = ((UInt32)pos >> Z7_MTF_MOVS);\n    pos = (pos & Z7_MTF_MASK) << 3;\n    CMtfVar prev = (Buf[lim] >> pos) & 0xFF;\n\n    UInt32 i = 0;\n    \n\n    /*\n    if ((lim & 1) != 0)\n    {\n      CMtfVar next = Buf[0];\n      Buf[0] = (next << 8) | prev;\n      prev = (next >> (Z7_MTF_MASK << 3));\n      i = 1;\n      lim -= 1;\n    }\n    for (; i < lim; i += 2)\n    {\n      CMtfVar n0 = Buf[i];\n      CMtfVar n1 = Buf[i + 1];\n      Buf[i    ] = (n0 << 8) | prev;\n      Buf[i + 1] = (n1 << 8) | (n0 >> (Z7_MTF_MASK << 3));\n      prev = (n1 >> (Z7_MTF_MASK << 3));\n    }\n    */\n\n    for (; i < lim; i++)\n    {\n      const CMtfVar n0 = Buf[i];\n      Buf[i    ] = (n0 << 8) | prev;\n      prev = (n0 >> (Z7_MTF_MASK << 3));\n    }\n\n\n    const CMtfVar next = Buf[i];\n    const CMtfVar mask = (((CMtfVar)0x100 << pos) - 1);\n    Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask);\n    return (Byte)Buf[0];\n  }\n};\n\n/*\nconst int kSmallSize = 64;\nclass CMtf8Decoder\n{\n  Byte SmallBuffer[kSmallSize];\n  int SmallSize;\n  int Counts[16];\n  int Size;\npublic:\n  Byte Buf[256];\n\n  Byte GetHead() const\n  {\n    if (SmallSize > 0)\n      return SmallBuffer[kSmallSize - SmallSize];\n    return Buf[0];\n  }\n\n  void Init(int size)\n  {\n    Size = size;\n    SmallSize = 0;\n    for (int i = 0; i < 16; i++)\n    {\n      Counts[i] = ((size >= 16) ? 16 : size);\n      size -= Counts[i];\n    }\n  }\n\n  void Add(unsigned pos, Byte val)\n  {\n    Buf[pos] = val;\n  }\n\n  Byte GetAndMove(int pos)\n  {\n    if (pos < SmallSize)\n    {\n      Byte *p = SmallBuffer + kSmallSize - SmallSize;\n      Byte res = p[pos];\n      for (; pos > 0; pos--)\n        p[pos] = p[pos - 1];\n      SmallBuffer[kSmallSize - SmallSize] = res;\n      return res;\n    }\n    if (SmallSize == kSmallSize)\n    {\n      int i = Size - 1;\n      int g = 16;\n      do\n      {\n        g--;\n        int offset = (g << 4);\n        for (int t = Counts[g] - 1; t >= 0; t--, i--)\n          Buf[i] = Buf[offset + t];\n      }\n      while (g != 0);\n      \n      for (i = kSmallSize - 1; i >= 0; i--)\n        Buf[i] = SmallBuffer[i];\n      Init(Size);\n    }\n    pos -= SmallSize;\n    int g;\n    for (g = 0; pos >= Counts[g]; g++)\n      pos -= Counts[g];\n    int offset = (g << 4);\n    Byte res = Buf[offset + pos];\n    for (pos; pos < 16 - 1; pos++)\n      Buf[offset + pos] = Buf[offset + pos + 1];\n    \n    SmallSize++;\n    SmallBuffer[kSmallSize - SmallSize] = res;\n\n    Counts[g]--;\n    return res;\n  }\n};\n*/\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/PpmdDecoder.cpp",
    "content": "﻿// PpmdDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"PpmdDecoder.h\"\n\nnamespace NCompress {\nnamespace NPpmd {\n\nstatic const UInt32 kBufSize = (1 << 16);\n\nenum\n{\n  kStatus_NeedInit,\n  kStatus_Normal,\n  kStatus_Finished_With_Mark,\n  kStatus_Error\n};\n\nCDecoder::~CDecoder()\n{\n  ::MidFree(_outBuf);\n  Ppmd7_Free(&_ppmd, &g_BigAlloc);\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size))\n{\n  if (size < 5)\n    return E_INVALIDARG;\n  _order = props[0];\n  const UInt32 memSize = GetUi32(props + 1);\n  if (_order < PPMD7_MIN_ORDER ||\n      _order > PPMD7_MAX_ORDER ||\n      memSize < PPMD7_MIN_MEM_SIZE ||\n      memSize > PPMD7_MAX_MEM_SIZE)\n    return E_NOTIMPL;\n  if (!_inStream.Alloc(1 << 20))\n    return E_OUTOFMEMORY;\n  if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))\n    return E_OUTOFMEMORY;\n  return S_OK;\n}\n\n#define MY_rangeDec  _ppmd.rc.dec\n\n#define CHECK_EXTRA_ERROR \\\n    if (_inStream.Extra) { \\\n      _status = kStatus_Error; \\\n      return (_res = (_inStream.Res != SZ_OK ? _inStream.Res: S_FALSE)); }\n\n\nHRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)\n{\n  if (_res != S_OK)\n    return _res;\n  \n  switch (_status)\n  {\n    case kStatus_Finished_With_Mark: return S_OK;\n    case kStatus_Error: return S_FALSE;\n    case kStatus_NeedInit:\n      _inStream.Init();\n      if (!Ppmd7z_RangeDec_Init(&MY_rangeDec))\n      {\n        _status = kStatus_Error;\n        return (_res = S_FALSE);\n      }\n      CHECK_EXTRA_ERROR\n      _status = kStatus_Normal;\n      Ppmd7_Init(&_ppmd, _order);\n      break;\n    default: break;\n  }\n  \n  if (_outSizeDefined)\n  {\n    const UInt64 rem = _outSize - _processedSize;\n    if (size > rem)\n      size = (UInt32)rem;\n  }\n\n  int sym = 0;\n  {\n    Byte *buf = memStream;\n    const Byte *lim = buf + size;\n    for (; buf != lim; buf++)\n    {\n      sym = Ppmd7z_DecodeSymbol(&_ppmd);\n      if (_inStream.Extra || sym < 0)\n        break;\n      *buf = (Byte)sym;\n    }\n    /*\n    buf = Ppmd7z_DecodeSymbols(&_ppmd, buf, lim);\n    sym = _ppmd.LastSymbol;\n    */\n    _processedSize += (size_t)(buf - memStream);\n  }\n\n  CHECK_EXTRA_ERROR\n  \n  if (sym >= 0)\n  {\n    if (!FinishStream\n        || !_outSizeDefined\n        || _outSize != _processedSize\n        || MY_rangeDec.Code == 0)\n      return S_OK;\n    /*\n    // We can decode additional End Marker here:\n    sym = Ppmd7z_DecodeSymbol(&_ppmd);\n    CHECK_EXTRA_ERROR\n    */\n  }\n\n  if (sym != PPMD7_SYM_END || MY_rangeDec.Code != 0)\n  {\n    _status = kStatus_Error;\n    return (_res = S_FALSE);\n  }\n  \n  _status = kStatus_Finished_With_Mark;\n  return S_OK;\n}\n\n\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  if (!_outBuf)\n  {\n    _outBuf = (Byte *)::MidAlloc(kBufSize);\n    if (!_outBuf)\n      return E_OUTOFMEMORY;\n  }\n  \n  _inStream.Stream = inStream;\n  SetOutStreamSize(outSize);\n\n  do\n  {\n    const UInt64 startPos = _processedSize;\n    const HRESULT res = CodeSpec(_outBuf, kBufSize);\n    const size_t processed = (size_t)(_processedSize - startPos);\n    RINOK(WriteStream(outStream, _outBuf, processed))\n    RINOK(res)\n    if (_status == kStatus_Finished_With_Mark)\n      break;\n    if (progress)\n    {\n      const UInt64 inProcessed = _inStream.GetProcessed();\n      RINOK(progress->SetRatioInfo(&inProcessed, &_processedSize))\n    }\n  }\n  while (!_outSizeDefined || _processedSize < _outSize);\n\n  if (FinishStream && inSize && *inSize != _inStream.GetProcessed())\n    return S_FALSE;\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))\n{\n  _outSizeDefined = (outSize != NULL);\n  if (_outSizeDefined)\n    _outSize = *outSize;\n  _processedSize = 0;\n  _status = kStatus_NeedInit;\n  _res = SZ_OK;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))\n{\n  FinishStream = (finishMode != 0);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = _inStream.GetProcessed();\n  return S_OK;\n}\n\n#ifndef Z7_NO_READ_FROM_CODER\n\nZ7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))\n{\n  InSeqStream = inStream;\n  _inStream.Stream = inStream;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::ReleaseInStream())\n{\n  InSeqStream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  const UInt64 startPos = _processedSize;\n  const HRESULT res = CodeSpec((Byte *)data, size);\n  if (processedSize)\n    *processedSize = (UInt32)(_processedSize - startPos);\n  return res;\n}\n\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/PpmdDecoder.h",
    "content": "﻿// PpmdDecoder.h\n\n#ifndef ZIP7_INC_COMPRESS_PPMD_DECODER_H\n#define ZIP7_INC_COMPRESS_PPMD_DECODER_H\n\n#include \"../../../C/Ppmd7.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/CWrappers.h\"\n\nnamespace NCompress {\nnamespace NPpmd {\n\nclass CDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetDecoderProperties2,\n  public ICompressSetFinishMode,\n  public ICompressGetInStreamProcessedSize,\n #ifndef Z7_NO_READ_FROM_CODER\n  public ICompressSetInStream,\n  public ICompressSetOutStreamSize,\n  public ISequentialInStream,\n #endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetDecoderProperties2)\n  Z7_COM_QI_ENTRY(ICompressSetFinishMode)\n  Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize)\n #ifndef Z7_NO_READ_FROM_CODER\n  Z7_COM_QI_ENTRY(ICompressSetInStream)\n  Z7_COM_QI_ENTRY(ICompressSetOutStreamSize)\n  Z7_COM_QI_ENTRY(ISequentialInStream)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\n  Z7_IFACE_COM7_IMP(ICompressSetFinishMode)\n  Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)\n #ifndef Z7_NO_READ_FROM_CODER\n  Z7_IFACE_COM7_IMP(ICompressSetOutStreamSize)\n  Z7_IFACE_COM7_IMP(ICompressSetInStream)\n  Z7_IFACE_COM7_IMP(ISequentialInStream)\n #else\n  Z7_COM7F_IMF(SetOutStreamSize(const UInt64 *outSize));\n #endif\n\n  Byte *_outBuf;\n  CByteInBufWrap _inStream;\n  CPpmd7 _ppmd;\n\n  Byte _order;\n  bool  FinishStream;\n  bool _outSizeDefined;\n  HRESULT _res;\n  int _status;\n  UInt64 _outSize;\n  UInt64 _processedSize;\n\n  HRESULT CodeSpec(Byte *memStream, UInt32 size);\n\npublic:\n\n #ifndef Z7_NO_READ_FROM_CODER\n  CMyComPtr<ISequentialInStream> InSeqStream;\n #endif\n\n  CDecoder():\n      _outBuf(NULL),\n      FinishStream(false),\n      _outSizeDefined(false)\n  {\n    Ppmd7_Construct(&_ppmd);\n    _ppmd.rc.dec.Stream = &_inStream.vt;\n  }\n\n  ~CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/PpmdEncoder.cpp",
    "content": "﻿// PpmdEncoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"PpmdEncoder.h\"\n\nnamespace NCompress {\nnamespace NPpmd {\n\nstatic const UInt32 kBufSize = (1 << 20);\n\nstatic const Byte kOrders[10] = { 3, 4, 4, 5, 5, 6, 8, 16, 24, 32 };\n\nvoid CEncProps::Normalize(int level)\n{\n  if (level < 0) level = 5;\n  if (level > 9) level = 9;\n  if (MemSize == (UInt32)(Int32)-1)\n    MemSize = (UInt32)1 << (level + 19);\n  const unsigned kMult = 16;\n  if (MemSize / kMult > ReduceSize)\n  {\n    for (unsigned i = 16; i < 32; i++)\n    {\n      UInt32 m = (UInt32)1 << i;\n      if (ReduceSize <= m / kMult)\n      {\n        if (MemSize > m)\n          MemSize = m;\n        break;\n      }\n    }\n  }\n  if (Order == -1) Order = kOrders[(unsigned)level];\n}\n\nCEncoder::CEncoder():\n  _inBuf(NULL)\n{\n  _props.Normalize(-1);\n  Ppmd7_Construct(&_ppmd);\n  _ppmd.rc.enc.Stream = &_outStream.vt;\n}\n\nCEncoder::~CEncoder()\n{\n  ::MidFree(_inBuf);\n  Ppmd7_Free(&_ppmd, &g_BigAlloc);\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  int level = -1;\n  CEncProps props;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    if (propID > NCoderPropID::kReduceSize)\n      continue;\n    if (propID == NCoderPropID::kReduceSize)\n    {\n      if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)\n        props.ReduceSize = (UInt32)prop.uhVal.QuadPart;\n      continue;\n    }\n\n    if (propID == NCoderPropID::kUsedMemorySize)\n    {\n      // here we have selected (4 GiB - 1 KiB) as replacement for (4 GiB) MEM_SIZE.\n      const UInt32 kPpmd_Default_4g = (UInt32)0 - ((UInt32)1 << 10);\n      UInt32 v;\n      if (prop.vt == VT_UI8)\n      {\n        // 21.03 : we support 64-bit values (for 4 GiB value)\n        const UInt64 v64 = prop.uhVal.QuadPart;\n        if (v64 > ((UInt64)1 << 32))\n          return E_INVALIDARG;\n        if (v64 == ((UInt64)1 << 32))\n          v = kPpmd_Default_4g;\n        else\n          v = (UInt32)v64;\n      }\n      else if (prop.vt == VT_UI4)\n        v = (UInt32)prop.ulVal;\n      else\n        return E_INVALIDARG;\n      if (v > PPMD7_MAX_MEM_SIZE)\n        v = kPpmd_Default_4g;\n\n      /* here we restrict MEM_SIZE for Encoder.\n         It's for better performance of encoding and decoding.\n         The Decoder still supports more MEM_SIZE values. */\n      if (v < ((UInt32)1 << 16) || (v & 3) != 0)\n        return E_INVALIDARG;\n      // if (v < PPMD7_MIN_MEM_SIZE) return E_INVALIDARG; // (1 << 11)\n      /*\n        Supported MEM_SIZE range :\n        [ (1 << 11) , 0xFFFFFFFF - 12 * 3 ] - current 7-Zip's Ppmd7 constants\n        [ 1824      , 0xFFFFFFFF          ] - real limits of Ppmd7 code\n      */\n      props.MemSize = v;\n      continue;\n    }\n\n    if (prop.vt != VT_UI4)\n      return E_INVALIDARG;\n    const UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n      case NCoderPropID::kOrder:\n        if (v < 2 || v > 32)\n          return E_INVALIDARG;\n        props.Order = (Byte)v;\n        break;\n      // **************** 7-Zip ZS Modification Start ****************\n      case NCoderPropID::kDictionarySize:\n      // **************** 7-Zip ZS Modification End ****************\n      case NCoderPropID::kNumThreads: break;\n      case NCoderPropID::kLevel: level = (int)v; break;\n      default: return E_INVALIDARG;\n    }\n  }\n  props.Normalize(level);\n  _props = props;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))\n{\n  const UInt32 kPropSize = 5;\n  Byte props[kPropSize];\n  props[0] = (Byte)_props.Order;\n  SetUi32(props + 1, _props.MemSize)\n  return WriteStream(outStream, props, kPropSize);\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))\n{\n  if (!_inBuf)\n  {\n    _inBuf = (Byte *)::MidAlloc(kBufSize);\n    if (!_inBuf)\n      return E_OUTOFMEMORY;\n  }\n  if (!_outStream.Alloc(1 << 20))\n    return E_OUTOFMEMORY;\n  if (!Ppmd7_Alloc(&_ppmd, _props.MemSize, &g_BigAlloc))\n    return E_OUTOFMEMORY;\n\n  _outStream.Stream = outStream;\n  _outStream.Init();\n\n  Ppmd7z_Init_RangeEnc(&_ppmd);\n  Ppmd7_Init(&_ppmd, (unsigned)_props.Order);\n\n  UInt64 processed = 0;\n  for (;;)\n  {\n    UInt32 size;\n    RINOK(inStream->Read(_inBuf, kBufSize, &size))\n    if (size == 0)\n    {\n      // We don't write EndMark in PPMD-7z.\n      // Ppmd7z_EncodeSymbol(&_ppmd, -1);\n      Ppmd7z_Flush_RangeEnc(&_ppmd);\n      return _outStream.Flush();\n    }\n    const Byte *buf = _inBuf;\n    const Byte *lim = buf + size;\n    /*\n    for (; buf < lim; buf++)\n    {\n      Ppmd7z_EncodeSymbol(&_ppmd, *buf);\n      RINOK(_outStream.Res);\n    }\n    */\n\n    Ppmd7z_EncodeSymbols(&_ppmd, buf, lim);\n    RINOK(_outStream.Res)\n\n    processed += size;\n    if (progress)\n    {\n      const UInt64 outSize = _outStream.GetProcessed();\n      RINOK(progress->SetRatioInfo(&processed, &outSize))\n    }\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/PpmdEncoder.h",
    "content": "﻿// PpmdEncoder.h\n\n#ifndef ZIP7_INC_COMPRESS_PPMD_ENCODER_H\n#define ZIP7_INC_COMPRESS_PPMD_ENCODER_H\n\n#include \"../../../C/Ppmd7.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/CWrappers.h\"\n\nnamespace NCompress {\nnamespace NPpmd {\n\nstruct CEncProps\n{\n  UInt32 MemSize;\n  UInt32 ReduceSize;\n  int Order;\n  \n  CEncProps()\n  {\n    MemSize = (UInt32)(Int32)-1;\n    ReduceSize = (UInt32)(Int32)-1;\n    Order = -1;\n  }\n  void Normalize(int level);\n};\n\nZ7_CLASS_IMP_COM_3(\n  CEncoder\n  , ICompressCoder\n  , ICompressSetCoderProperties\n  , ICompressWriteCoderProperties\n)\n  Byte *_inBuf;\n  CByteOutBufWrap _outStream;\n  CPpmd7 _ppmd;\n  CEncProps _props;\npublic:\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/PpmdRegister.cpp",
    "content": "﻿// PpmdRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"PpmdDecoder.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"PpmdEncoder.h\"\n#endif\n\nnamespace NCompress {\nnamespace NPpmd {\n\nREGISTER_CODEC_E(PPMD,\n    CDecoder(),\n    CEncoder(),\n    0x30401,\n    \"PPMD\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/PpmdZip.cpp",
    "content": "﻿// PpmdZip.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../Common/RegisterCodec.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"PpmdZip.h\"\n\nnamespace NCompress {\nnamespace NPpmdZip {\n\nstatic const UInt32 kBufSize = 1 << 20;\n\nbool CBuf::Alloc()\n{\n  if (!Buf)\n    Buf = (Byte *)::MidAlloc(kBufSize);\n  return (Buf != NULL);\n}\n\nCDecoder::CDecoder(bool fullFileMode):\n  _fullFileMode(fullFileMode)\n{\n  Ppmd8_Construct(&_ppmd);\n  _ppmd.Stream.In = &_inStream.vt;\n}\n\nCDecoder::~CDecoder()\n{\n  Ppmd8_Free(&_ppmd, &g_BigAlloc);\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  // try {\n\n  if (!_outStream.Alloc())\n    return E_OUTOFMEMORY;\n  if (!_inStream.Alloc(1 << 20))\n    return E_OUTOFMEMORY;\n\n  _inStream.Stream = inStream;\n  _inStream.Init();\n\n  {\n    Byte buf[2];\n    for (int i = 0; i < 2; i++)\n      buf[i] = _inStream.ReadByte();\n    if (_inStream.Extra)\n      return S_FALSE;\n    \n    const UInt32 val = GetUi16(buf);\n    const unsigned order = (val & 0xF) + 1;\n    const UInt32 mem = ((val >> 4) & 0xFF) + 1;\n    const unsigned restor = (val >> 12);\n    if (order < 2 || restor > 2)\n      return S_FALSE;\n    \n    #ifndef PPMD8_FREEZE_SUPPORT\n    if (restor == 2)\n      return E_NOTIMPL;\n    #endif\n    \n    if (!Ppmd8_Alloc(&_ppmd, mem << 20, &g_BigAlloc))\n      return E_OUTOFMEMORY;\n    \n    if (!Ppmd8_Init_RangeDec(&_ppmd))\n      return S_FALSE;\n    Ppmd8_Init(&_ppmd, order, restor);\n  }\n\n  bool wasFinished = false;\n  UInt64 processedSize = 0;\n\n  for (;;)\n  {\n    size_t size = kBufSize;\n    if (outSize)\n    {\n      const UInt64 rem = *outSize - processedSize;\n      if (size > rem)\n      {\n        size = (size_t)rem;\n        if (size == 0)\n          break;\n      }\n    }\n\n    int sym;\n    Byte *buf = _outStream.Buf;\n    const Byte *lim = buf + size;\n    \n    do\n    {\n      sym = Ppmd8_DecodeSymbol(&_ppmd);\n      if (_inStream.Extra || sym < 0)\n        break;\n      *buf++ = (Byte)sym;\n    }\n    while (buf != lim);\n    \n    const size_t cur = (size_t)(buf - _outStream.Buf);\n    processedSize += cur;\n\n    RINOK(WriteStream(outStream, _outStream.Buf, cur))\n\n    RINOK(_inStream.Res)\n    if (_inStream.Extra)\n      return S_FALSE;\n\n    if (sym < 0)\n    {\n      if (sym != -1)\n        return S_FALSE;\n      wasFinished = true;\n      break;\n    }\n    \n    if (progress)\n    {\n      const UInt64 inProccessed = _inStream.GetProcessed();\n      RINOK(progress->SetRatioInfo(&inProccessed, &processedSize))\n    }\n  }\n  \n  RINOK(_inStream.Res)\n  \n  if (_fullFileMode)\n  {\n    if (!wasFinished)\n    {\n      const int res = Ppmd8_DecodeSymbol(&_ppmd);\n      RINOK(_inStream.Res)\n      if (_inStream.Extra || res != -1)\n        return S_FALSE;\n    }\n    if (!Ppmd8_RangeDec_IsFinishedOK(&_ppmd))\n      return S_FALSE;\n\n    if (inSize && *inSize != _inStream.GetProcessed())\n      return S_FALSE;\n  }\n  \n  return S_OK;\n\n  // } catch (...) { return E_FAIL; }\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))\n{\n  _fullFileMode = (finishMode != 0);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = _inStream.GetProcessed();\n  return S_OK;\n}\n\n\n\n// ---------- Encoder ----------\n\nvoid CEncProps::Normalize(int level)\n{\n  if (level < 0) level = 5;\n  if (level == 0) level = 1;\n  if (level > 9) level = 9;\n  if (MemSizeMB == (UInt32)(Int32)-1)\n    MemSizeMB = 1 << (level - 1);\n  const unsigned kMult = 16;\n  for (UInt32 m = 1; m < MemSizeMB; m <<= 1)\n    if (ReduceSize <= (m << 20) / kMult)\n    {\n      MemSizeMB = m;\n      break;\n    }\n  if (Order == -1) Order = 3 + level;\n  if (Restor == -1)\n    Restor = level < 7 ?\n      PPMD8_RESTORE_METHOD_RESTART :\n      PPMD8_RESTORE_METHOD_CUT_OFF;\n}\n\nCEncoder::~CEncoder()\n{\n  Ppmd8_Free(&_ppmd, &g_BigAlloc);\n}\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  int level = -1;\n  CEncProps props;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    if (propID > NCoderPropID::kReduceSize)\n      continue;\n    if (propID == NCoderPropID::kReduceSize)\n    {\n      props.ReduceSize = (UInt32)(Int32)-1;\n      if (prop.vt == VT_UI8 && prop.uhVal.QuadPart < (UInt32)(Int32)-1)\n        props.ReduceSize = (UInt32)prop.uhVal.QuadPart;\n      continue;\n    }\n    if (prop.vt != VT_UI4)\n      return E_INVALIDARG;\n    const UInt32 v = (UInt32)prop.ulVal;\n    switch (propID)\n    {\n      case NCoderPropID::kUsedMemorySize:\n        if (v < (1 << 20) || v > (1 << 28))\n          return E_INVALIDARG;\n        props.MemSizeMB = v >> 20;\n        break;\n      case NCoderPropID::kOrder:\n        if (v < PPMD8_MIN_ORDER || v > PPMD8_MAX_ORDER)\n          return E_INVALIDARG;\n        props.Order = (Byte)v;\n        break;\n      case NCoderPropID::kNumThreads: break;\n      case NCoderPropID::kLevel: level = (int)v; break;\n      case NCoderPropID::kAlgorithm:\n        if (v >= PPMD8_RESTORE_METHOD_UNSUPPPORTED)\n          return E_INVALIDARG;\n        props.Restor = (int)v;\n        break;\n      default: return E_INVALIDARG;\n    }\n  }\n  props.Normalize(level);\n  _props = props;\n  return S_OK;\n}\n\nCEncoder::CEncoder()\n{\n  _props.Normalize(-1);\n  _ppmd.Stream.Out = &_outStream.vt;\n  Ppmd8_Construct(&_ppmd);\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))\n{\n  if (!_inStream.Alloc())\n    return E_OUTOFMEMORY;\n  if (!_outStream.Alloc(1 << 20))\n    return E_OUTOFMEMORY;\n  if (!Ppmd8_Alloc(&_ppmd, _props.MemSizeMB << 20, &g_BigAlloc))\n    return E_OUTOFMEMORY;\n\n  _outStream.Stream = outStream;\n  _outStream.Init();\n\n  Ppmd8_Init_RangeEnc(&_ppmd)\n  Ppmd8_Init(&_ppmd, (unsigned)_props.Order, (unsigned)_props.Restor);\n\n  {\n    const unsigned val =\n           ((unsigned)_props.Order - 1)\n         + (((unsigned)_props.MemSizeMB - 1) << 4)\n         + ((unsigned)_props.Restor << 12);\n    _outStream.WriteByte((Byte)(val & 0xFF));\n    _outStream.WriteByte((Byte)(val >> 8));\n  }\n  RINOK(_outStream.Res)\n\n  UInt64 processed = 0;\n  for (;;)\n  {\n    UInt32 size;\n    RINOK(inStream->Read(_inStream.Buf, kBufSize, &size))\n    if (size == 0)\n    {\n      Ppmd8_EncodeSymbol(&_ppmd, -1);\n      Ppmd8_Flush_RangeEnc(&_ppmd);\n      return _outStream.Flush();\n    }\n\n    processed += size;\n    const Byte *buf = _inStream.Buf;\n    const Byte *lim = buf + size;\n    do\n    {\n      Ppmd8_EncodeSymbol(&_ppmd, *buf);\n      if (_outStream.Res != S_OK)\n        break;\n    }\n    while (++buf != lim);\n\n    RINOK(_outStream.Res)\n\n    if (progress)\n    {\n      const UInt64 outProccessed = _outStream.GetProcessed();\n      RINOK(progress->SetRatioInfo(&processed, &outProccessed))\n    }\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/PpmdZip.h",
    "content": "﻿// PpmdZip.h\n\n#ifndef ZIP7_INC_COMPRESS_PPMD_ZIP_H\n#define ZIP7_INC_COMPRESS_PPMD_ZIP_H\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/Ppmd8.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/CWrappers.h\"\n\nnamespace NCompress {\nnamespace NPpmdZip {\n\nstruct CBuf\n{\n  Byte *Buf;\n  \n  CBuf(): Buf(NULL) {}\n  ~CBuf() { ::MidFree(Buf); }\n  bool Alloc();\n};\n\n\nZ7_CLASS_IMP_NOQIB_3(\n  CDecoder\n  , ICompressCoder\n  , ICompressSetFinishMode\n  , ICompressGetInStreamProcessedSize\n)\n  bool _fullFileMode;\n  CByteInBufWrap _inStream;\n  CBuf _outStream;\n  CPpmd8 _ppmd;\npublic:\n  CDecoder(bool fullFileMode = true);\n  ~CDecoder();\n};\n\n\nstruct CEncProps\n{\n  UInt32 MemSizeMB;\n  UInt32 ReduceSize;\n  int Order;\n  int Restor;\n  \n  CEncProps()\n  {\n    MemSizeMB = (UInt32)(Int32)-1;\n    ReduceSize = (UInt32)(Int32)-1;\n    Order = -1;\n    Restor = -1;\n  }\n  void Normalize(int level);\n};\n\n\nZ7_CLASS_IMP_NOQIB_2(\n  CEncoder\n  , ICompressCoder\n  , ICompressSetCoderProperties\n)\n  CByteOutBufWrap _outStream;\n  CBuf _inStream;\n  CPpmd8 _ppmd;\n  CEncProps _props;\npublic:\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/QuantumDecoder.cpp",
    "content": "﻿// QuantumDecoder.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/Alloc.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/Defs.h\"\n\n#include \"QuantumDecoder.h\"\n\nnamespace NCompress {\nnamespace NQuantum {\n\nstatic const unsigned kNumLenSymbols = 27;\nstatic const unsigned kMatchMinLen = 3;\nstatic const unsigned kNumSimpleLenSlots = 6;\n\nstatic const unsigned kUpdateStep = 8;\nstatic const unsigned kFreqSumMax = 3800;\nstatic const unsigned kReorderCount_Start = 4;\nstatic const unsigned kReorderCount = 50;\n\n\nclass CRangeDecoder\n{\n  UInt32 Low;\n  UInt32 Range;\n  UInt32 Code;\n\n  unsigned _bitOffset;\n  const Byte *_buf;\n  const Byte *_bufLim;\n\npublic:\n\n  Z7_FORCE_INLINE\n  void Init(const Byte *inData, size_t inSize)\n  {\n    Code = ((UInt32)*inData << 8) | inData[1];\n    _buf = inData + 2;\n    _bufLim = inData + inSize;\n    _bitOffset = 0;\n    Low = 0;\n    Range = 0x10000;\n  }\n\n  Z7_FORCE_INLINE\n  bool WasExtraRead() const\n  {\n    return _buf > _bufLim;\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 ReadBits(unsigned numBits) // numBits > 0\n  {\n    unsigned bitOffset = _bitOffset;\n    const Byte *buf = _buf;\n    const UInt32 res = GetBe32(buf) << bitOffset;\n    bitOffset += numBits;\n    _buf = buf + (bitOffset >> 3);\n    _bitOffset = bitOffset & 7;\n    return res >> (32 - numBits);\n  }\n\n  // ---------- Range Decoder functions ----------\n\n  Z7_FORCE_INLINE\n  bool Finish()\n  {\n    const unsigned numBits = 2 + ((16 - 2 - _bitOffset) & 7);\n    if (ReadBits(numBits) != 0)\n      return false;\n    return _buf == _bufLim;\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetThreshold(UInt32 total) const\n  {\n    return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;\n  }\n  \n  Z7_FORCE_INLINE\n  void Decode(UInt32 start, UInt32 end, UInt32 total)\n  {\n    // UInt32 hi = ~(Low + end * Range / total - 1);\n    UInt32 hi = 0 - (Low + end * Range / total);\n    const UInt32 offset = start * Range / total;\n    UInt32 lo = Low + offset;\n    Code -= offset;\n    UInt32 numBits = 0;\n    lo ^= hi;\n    while (lo & (1u << 15))\n    {\n      lo <<= 1;\n      hi <<= 1;\n      numBits++;\n    }\n    lo ^= hi;\n    UInt32 an = lo & hi;\n    while (an & (1u << 14))\n    {\n      an <<= 1;\n      lo <<= 1;\n      hi <<= 1;\n      numBits++;\n    }\n    Low = lo;\n    Range = ((~hi - lo) & 0xffff) + 1;\n    if (numBits)\n      Code = (Code << numBits) + ReadBits(numBits);\n  }\n};\n\n\n// Z7_FORCE_INLINE\nZ7_NO_INLINE\nunsigned CModelDecoder::Decode(CRangeDecoder *rc)\n// Z7_NO_INLINE void CModelDecoder::Normalize()\n{\n  if (Freqs[0] > kFreqSumMax)\n  {\n    if (--ReorderCount == 0)\n    {\n      ReorderCount = kReorderCount;\n      {\n        unsigned i = NumItems;\n        unsigned next = 0;\n        UInt16 *freqs = &Freqs[i];\n        do\n        {\n          const unsigned freq = *--freqs;\n          *freqs = (UInt16)((freq - next + 1) >> 1);\n          next = freq;\n        }\n        while (--i);\n      }\n      {\n        for (unsigned i = 0; i < NumItems - 1; i++)\n        {\n          UInt16 freq = Freqs[i];\n          for (unsigned k = i + 1; k < NumItems; k++)\n            if (freq < Freqs[k])\n            {\n              const UInt16 freq2 = Freqs[k];\n              Freqs[k] = freq;\n              Freqs[i] = freq2;\n              freq = freq2;\n              const Byte val = Vals[i];\n              Vals[i] = Vals[k];\n              Vals[k] = val;\n            }\n        }\n      }\n      unsigned i = NumItems;\n      unsigned freq = 0;\n      UInt16 *freqs = &Freqs[i];\n      do\n      {\n        freq += *--freqs;\n        *freqs = (UInt16)freq;\n      }\n      while (--i);\n    }\n    else\n    {\n      unsigned i = NumItems;\n      unsigned next = 1;\n      UInt16 *freqs = &Freqs[i];\n      do\n      {\n        unsigned freq = *--freqs >> 1;\n        if (freq < next)\n          freq = next;\n        *freqs = (UInt16)freq;\n        next = freq + 1;\n      }\n      while (--i);\n    }\n  }\n  unsigned res;\n  {\n    const unsigned freq0 = Freqs[0];\n    Freqs[0] = (UInt16)(freq0 + kUpdateStep);\n    const unsigned threshold = rc->GetThreshold(freq0);\n    UInt16 *freqs = &Freqs[1];\n    unsigned freq = *freqs;\n    while (freq > threshold)\n    {\n      *freqs++ = (UInt16)(freq + kUpdateStep);\n      freq = *freqs;\n    }\n    res = Vals[freqs - Freqs - 1];\n    rc->Decode(freq, freqs[-1] - kUpdateStep, freq0);\n  }\n  return res;\n}\n\n\nZ7_NO_INLINE\nvoid CModelDecoder::Init(unsigned numItems, unsigned startVal)\n{\n  NumItems = numItems;\n  ReorderCount = kReorderCount_Start;\n  UInt16 *freqs = Freqs;\n  freqs[numItems] = 0;\n  Byte *vals = Vals;\n  do\n  {\n    *freqs++ = (UInt16)numItems;\n    *vals++ = (Byte)startVal;\n    startVal++;\n  }\n  while (--numItems);\n}\n\n\nHRESULT CDecoder::Code(const Byte *inData, size_t inSize, UInt32 outSize, bool keepHistory)\n{\n  if (inSize < 2)\n    return S_FALSE;\n  if (!keepHistory)\n  {\n    _winPos = 0;\n    m_Selector.Init(kNumSelectors, 0);\n    unsigned i;\n    for (i = 0; i < kNumLitSelectors; i++)\n      m_Literals[i].Init(kNumLitSymbols, i * kNumLitSymbols);\n    const unsigned numItems = (_numDictBits == 0 ? 1 : (_numDictBits << 1));\n    // const unsigned kNumPosSymbolsMax[kNumMatchSelectors] = { 24, 36, 42 };\n    for (i = 0; i < kNumMatchSelectors; i++)\n    {\n      const unsigned num = 24 + i * 6 + ((i + 1) & 2) * 3;\n      m_PosSlot[i].Init(MyMin(numItems, num), 0);\n    }\n    m_LenSlot.Init(kNumLenSymbols, kMatchMinLen + kNumMatchSelectors - 1);\n  }\n\n  CRangeDecoder rc;\n  rc.Init(inData, inSize);\n  const UInt32 winSize = _winSize;\n  Byte *pos;\n  {\n    UInt32 winPos = _winPos;\n    if (winPos == winSize)\n    {\n      winPos = 0;\n      _winPos = winPos;\n      _overWin = true;\n    }\n    if (outSize > winSize - winPos)\n      return S_FALSE;\n    pos = _win + winPos;\n  }\n\n  while (outSize != 0)\n  {\n    if (rc.WasExtraRead())\n      return S_FALSE;\n\n    const unsigned selector = m_Selector.Decode(&rc);\n    \n    if (selector < kNumLitSelectors)\n    {\n      const unsigned b = m_Literals[selector].Decode(&rc);\n      *pos++ = (Byte)b;\n      --outSize;\n      // if (--outSize == 0) break;\n    }\n    else\n    {\n      unsigned len = selector - kNumLitSelectors + kMatchMinLen;\n    \n      if (selector == kNumLitSelectors + kNumMatchSelectors - 1)\n      {\n        len = m_LenSlot.Decode(&rc);\n        if (len >= kNumSimpleLenSlots + kMatchMinLen + kNumMatchSelectors - 1)\n        {\n          len -= kNumSimpleLenSlots - 4 + kMatchMinLen + kNumMatchSelectors - 1;\n          const unsigned numDirectBits = (unsigned)(len >> 2);\n          len = ((4 | (len & 3)) << numDirectBits) - (4 << 1)\n              + kNumSimpleLenSlots\n              + kMatchMinLen + kNumMatchSelectors - 1;\n          if (numDirectBits < 6)\n            len += rc.ReadBits(numDirectBits);\n        }\n      }\n      \n      UInt32 dist = m_PosSlot[(size_t)selector - kNumLitSelectors].Decode(&rc);\n      \n      if (dist >= 4)\n      {\n        const unsigned numDirectBits = (unsigned)((dist >> 1) - 1);\n        dist = ((2 | (dist & 1)) << numDirectBits) + rc.ReadBits(numDirectBits);\n      }\n      \n      if ((Int32)(outSize -= len) < 0)\n        return S_FALSE;\n\n      ptrdiff_t srcPos = (ptrdiff_t)(Int32)((pos - _win) - (ptrdiff_t)dist - 1);\n      if (srcPos < 0)\n      {\n        if (!_overWin)\n          return S_FALSE;\n        UInt32 rem = (UInt32)-srcPos;\n        srcPos += winSize;\n        if (rem < len)\n        {\n          const Byte *src = _win + srcPos;\n          len -= rem;\n          do\n            *pos++ = *src++;\n          while (--rem);\n          srcPos = 0;\n        }\n      }\n      const Byte *src = _win + srcPos;\n      do\n        *pos++ = *src++;\n      while (--len);\n      // if (outSize == 0) break;\n    }\n  }\n\n  _winPos = (UInt32)(size_t)(pos - _win);\n  return rc.Finish() ? S_OK : S_FALSE;\n}\n\n\nHRESULT CDecoder::SetParams(unsigned numDictBits)\n{\n  if (numDictBits > 21)\n    return E_INVALIDARG;\n  _numDictBits = numDictBits;\n  _winPos = 0;\n  _overWin = false;\n\n  if (numDictBits < 15)\n      numDictBits = 15;\n  _winSize = (UInt32)1 << numDictBits;\n  if (!_win || _winSize > _winSize_allocated)\n  {\n    MidFree(_win);\n    _win = NULL;\n    _win = (Byte *)MidAlloc(_winSize);\n    if (!_win)\n      return E_OUTOFMEMORY;\n    _winSize_allocated = _winSize;\n  }\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/QuantumDecoder.h",
    "content": "﻿// QuantumDecoder.h\n\n#ifndef ZIP7_INC_COMPRESS_QUANTUM_DECODER_H\n#define ZIP7_INC_COMPRESS_QUANTUM_DECODER_H\n\n#include \"../../Common/MyTypes.h\"\n\nnamespace NCompress {\nnamespace NQuantum {\n\nconst unsigned kNumLitSelectorBits = 2;\nconst unsigned kNumLitSelectors = 1 << kNumLitSelectorBits;\nconst unsigned kNumLitSymbols = 1 << (8 - kNumLitSelectorBits);\nconst unsigned kNumMatchSelectors = 3;\nconst unsigned kNumSelectors = kNumLitSelectors + kNumMatchSelectors;\nconst unsigned kNumSymbolsMax = kNumLitSymbols; // 64\n\nclass CRangeDecoder;\n\nclass CModelDecoder\n{\n  unsigned NumItems;\n  unsigned ReorderCount;\n  Byte Vals[kNumSymbolsMax];\n  UInt16 Freqs[kNumSymbolsMax + 1];\npublic:\n  Byte _pad[64 - 10]; // for structure size alignment\n\n  void Init(unsigned numItems, unsigned startVal);\n  unsigned Decode(CRangeDecoder *rc);\n};\n\n\nclass CDecoder\n{\n  UInt32 _winSize;\n  UInt32 _winPos;\n  UInt32 _winSize_allocated;\n  bool _overWin;\n  Byte *_win;\n  unsigned _numDictBits;\n\n  CModelDecoder m_Selector;\n  CModelDecoder m_Literals[kNumLitSelectors];\n  CModelDecoder m_PosSlot[kNumMatchSelectors];\n  CModelDecoder m_LenSlot;\n\n  void Init();\n  HRESULT CodeSpec(const Byte *inData, size_t inSize, UInt32 outSize);\npublic:\n  HRESULT Code(const Byte *inData, size_t inSize, UInt32 outSize, bool keepHistory);\n  HRESULT SetParams(unsigned numDictBits);\n\n  CDecoder(): _win(NULL), _numDictBits(0) {}\n  const Byte * GetDataPtr() const { return _win + _winPos; }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar1Decoder.cpp",
    "content": "﻿// Rar1Decoder.cpp\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n \n#include \"StdAfx.h\"\n\n#include \"Rar1Decoder.h\"\n\nnamespace NCompress {\nnamespace NRar1 {\n\nstatic const unsigned kNumBits = 12;\n\nstatic const Byte kShortLen1[16 * 3] =\n{\n  0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0,0,\n  1,3,4,4,5,6,7,8,8,4,4,5,6,6,0,0,\n  1,4,4,4,5,6,7,8,8,4,4,5,6,6,4,0\n};\n\nstatic const Byte kShortLen2[16 * 3] =\n{\n  0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0,0,\n  2,3,3,3,4,4,5,6,6,4,4,5,6,6,0,0,\n  2,3,3,4,4,4,5,6,6,4,4,5,6,6,4,0\n};\n\nstatic const Byte PosL1[kNumBits + 1]  = { 0,0,2,1,2,2,4,5,4,4,8,0,224 };\nstatic const Byte PosL2[kNumBits + 1]  = { 0,0,0,5,2,2,4,5,4,4,8,2,220 };\n\nstatic const Byte PosHf0[kNumBits + 1] = { 0,0,0,0,8,8,8,9,0,0,0,0,224 };\nstatic const Byte PosHf1[kNumBits + 1] = { 0,0,0,0,0,4,40,16,16,4,0,47,130 };\nstatic const Byte PosHf2[kNumBits + 1] = { 0,0,0,0,0,2,5,46,64,116,24,0,0 };\nstatic const Byte PosHf3[kNumBits + 1] = { 0,0,0,0,0,0,2,14,202,33,6,0,0 };\nstatic const Byte PosHf4[kNumBits + 1] = { 0,0,0,0,0,0,0,0,255,2,0,0,0 };\n\nstatic const UInt32 kHistorySize = (1 << 16);\n\nCDecoder::CDecoder():\n   _isSolid(false),\n   _solidAllowed(false)\n   {}\n\nUInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); }\n\nHRESULT CDecoder::CopyBlock(UInt32 distance, UInt32 len)\n{\n  if (len == 0)\n    return S_FALSE;\n  if (m_UnpackSize < len)\n    return S_FALSE;\n  m_UnpackSize -= len;\n  return m_OutWindowStream.CopyBlock(distance, len) ? S_OK : S_FALSE;\n}\n\n\nUInt32 CDecoder::DecodeNum(const Byte *numTab)\n{\n  /*\n  {\n    // we can check that tables are correct\n    UInt32 sum = 0;\n    for (unsigned i = 0; i <= kNumBits; i++)\n      sum += ((UInt32)numTab[i] << (kNumBits - i));\n    if (sum != (1 << kNumBits))\n      throw 111;\n  }\n  */\n\n  UInt32 val = m_InBitStream.GetValue(kNumBits);\n  UInt32 sum = 0;\n  unsigned i = 2;\n\n  for (;;)\n  {\n    const UInt32 num = numTab[i];\n    const UInt32 cur = num << (kNumBits - i);\n    if (val < cur)\n      break;\n    i++;\n    val -= cur;\n    sum += num;\n  }\n  m_InBitStream.MovePos(i);\n  return ((val >> (kNumBits - i)) + sum);\n}\n\n\nHRESULT CDecoder::ShortLZ()\n{\n  NumHuf = 0;\n\n  if (LCount == 2)\n  {\n    if (ReadBits(1))\n      return CopyBlock(LastDist, LastLength);\n    LCount = 0;\n  }\n\n  UInt32 bitField = m_InBitStream.GetValue(8);\n\n  UInt32 len, dist;\n  {\n    const Byte *xors = (AvrLn1 < 37) ? kShortLen1 : kShortLen2;\n    const Byte *lens = xors + 16 + Buf60;\n    for (len = 0; ((bitField ^ xors[len]) >> (8 - lens[len])) != 0; len++);\n    m_InBitStream.MovePos(lens[len]);\n  }\n  \n  if (len >= 9)\n  {\n    if (len == 9)\n    {\n      LCount++;\n      return CopyBlock(LastDist, LastLength);\n    }\n\n    LCount = 0;\n\n    if (len == 14)\n    {\n      len = DecodeNum(PosL2) + 5;\n      dist = 0x8000 + ReadBits(15) - 1;\n      LastLength = len;\n      LastDist = dist;\n      return CopyBlock(dist, len);\n    }\n\n    const UInt32 saveLen = len;\n    dist = m_RepDists[(m_RepDistPtr - (len - 9)) & 3];\n    \n    len = DecodeNum(PosL1);\n    \n    if (len == 0xff && saveLen == 10)\n    {\n      Buf60 ^= 16;\n      return S_OK;\n    }\n    if (dist >= 256)\n    {\n      len++;\n      if (dist >= MaxDist3 - 1)\n        len++;\n    }\n  }\n  else\n  {\n    LCount = 0;\n    AvrLn1 += len;\n    AvrLn1 -= AvrLn1 >> 4;\n    \n    unsigned distancePlace = DecodeNum(PosHf2) & 0xff;\n    \n    dist = ChSetA[distancePlace];\n    \n    if (distancePlace != 0)\n    {\n      PlaceA[dist]--;\n      UInt32 lastDistance = ChSetA[(size_t)distancePlace - 1];\n      PlaceA[lastDistance]++;\n      ChSetA[distancePlace] = lastDistance;\n      ChSetA[(size_t)distancePlace - 1] = dist;\n    }\n  }\n\n  m_RepDists[m_RepDistPtr++] = dist;\n  m_RepDistPtr &= 3;\n  len += 2;\n  LastLength = len;\n  LastDist = dist;\n  return CopyBlock(dist, len);\n}\n\n\nHRESULT CDecoder::LongLZ()\n{\n  UInt32 len;\n  UInt32 dist;\n  UInt32 distancePlace, newDistancePlace;\n  UInt32 oldAvr2, oldAvr3;\n\n  NumHuf = 0;\n  Nlzb += 16;\n  if (Nlzb > 0xff)\n  {\n    Nlzb = 0x90;\n    Nhfb >>= 1;\n  }\n  oldAvr2 = AvrLn2;\n\n  if (AvrLn2 >= 64)\n    len = DecodeNum(AvrLn2 < 122 ? PosL1 : PosL2);\n  else\n  {\n    UInt32 bitField = m_InBitStream.GetValue(16);\n    if (bitField < 0x100)\n    {\n      len = bitField;\n      m_InBitStream.MovePos(16);\n    }\n    else\n    {\n      for (len = 0; ((bitField << len) & 0x8000) == 0; len++);\n      \n      m_InBitStream.MovePos(len + 1);\n    }\n  }\n\n  AvrLn2 += len;\n  AvrLn2 -= AvrLn2 >> 5;\n\n  {\n    const Byte *tab;\n         if (AvrPlcB >= 0x2900) tab = PosHf2;\n    else if (AvrPlcB >= 0x0700) tab = PosHf1;\n    else                        tab = PosHf0;\n    distancePlace = DecodeNum(tab); // [0, 256]\n  }\n\n  AvrPlcB += distancePlace;\n  AvrPlcB -= AvrPlcB >> 8;\n\n  distancePlace &= 0xff;\n  \n  for (;;)\n  {\n    dist = ChSetB[distancePlace];\n    newDistancePlace = NToPlB[dist++ & 0xff]++;\n    if (dist & 0xff)\n      break;\n    CorrHuff(ChSetB,NToPlB);\n  }\n\n  ChSetB[distancePlace] = ChSetB[newDistancePlace];\n  ChSetB[newDistancePlace] = dist;\n\n  dist = ((dist & 0xff00) >> 1) | ReadBits(7);\n\n  oldAvr3 = AvrLn3;\n  \n  if (len != 1 && len != 4)\n  {\n    if (len == 0 && dist <= MaxDist3)\n    {\n      AvrLn3++;\n      AvrLn3 -= AvrLn3 >> 8;\n    }\n    else if (AvrLn3 > 0)\n      AvrLn3--;\n  }\n  \n  len += 3;\n  \n  if (dist >= MaxDist3)\n    len++;\n  if (dist <= 256)\n    len += 8;\n  \n  if (oldAvr3 > 0xb0 || (AvrPlc >= 0x2a00 && oldAvr2 < 0x40))\n    MaxDist3 = 0x7f00;\n  else\n    MaxDist3 = 0x2001;\n  \n  m_RepDists[m_RepDistPtr++] = --dist;\n  m_RepDistPtr &= 3;\n  LastLength = len;\n  LastDist = dist;\n  \n  return CopyBlock(dist, len);\n}\n\n\nHRESULT CDecoder::HuffDecode()\n{\n  UInt32 curByte, newBytePlace;\n  UInt32 len;\n  UInt32 dist;\n  unsigned bytePlace;\n  {\n    const Byte *tab;\n    \n    if      (AvrPlc >= 0x7600)  tab = PosHf4;\n    else if (AvrPlc >= 0x5e00)  tab = PosHf3;\n    else if (AvrPlc >= 0x3600)  tab = PosHf2;\n    else if (AvrPlc >= 0x0e00)  tab = PosHf1;\n    else                        tab = PosHf0;\n    \n    bytePlace = DecodeNum(tab); // [0, 256]\n  }\n  \n  if (StMode)\n  {\n    if (bytePlace == 0)\n    {\n      if (ReadBits(1))\n      {\n        NumHuf = 0;\n        StMode = false;\n        return S_OK;\n      }\n      len = ReadBits(1) + 3;\n      dist = DecodeNum(PosHf2);\n      dist = (dist << 5) | ReadBits(5);\n      if (dist == 0)\n        return S_FALSE;\n      return CopyBlock(dist - 1, len);\n    }\n    bytePlace--; // bytePlace is [0, 255]\n  }\n  else if (NumHuf++ >= 16 && FlagsCnt == 0)\n    StMode = true;\n  \n  bytePlace &= 0xff;\n  AvrPlc += bytePlace;\n  AvrPlc -= AvrPlc >> 8;\n  Nhfb += 16;\n  \n  if (Nhfb > 0xff)\n  {\n    Nhfb = 0x90;\n    Nlzb >>= 1;\n  }\n\n  m_UnpackSize--;\n  m_OutWindowStream.PutByte((Byte)(ChSet[bytePlace] >> 8));\n\n  for (;;)\n  {\n    curByte = ChSet[bytePlace];\n    newBytePlace = NToPl[curByte++ & 0xff]++;\n    if ((curByte & 0xff) <= 0xa1)\n      break;\n    CorrHuff(ChSet, NToPl);\n  }\n\n  ChSet[bytePlace] = ChSet[newBytePlace];\n  ChSet[newBytePlace] = curByte;\n  return S_OK;\n}\n\n\nvoid CDecoder::GetFlagsBuf()\n{\n  UInt32 flags, newFlagsPlace;\n  const UInt32 flagsPlace = DecodeNum(PosHf2); // [0, 256]\n\n  if (flagsPlace >= Z7_ARRAY_SIZE(ChSetC))\n    return;\n\n  for (;;)\n  {\n    flags = ChSetC[flagsPlace];\n    FlagBuf = flags >> 8;\n    newFlagsPlace = NToPlC[flags++ & 0xff]++;\n    if ((flags & 0xff) != 0)\n      break;\n    CorrHuff(ChSetC, NToPlC);\n  }\n\n  ChSetC[flagsPlace] = ChSetC[newFlagsPlace];\n  ChSetC[newFlagsPlace] = flags;\n}\n\n\nvoid CDecoder::CorrHuff(UInt32 *CharSet, UInt32 *NumToPlace)\n{\n  int i;\n  for (i = 7; i >= 0; i--)\n    for (unsigned j = 0; j < 32; j++, CharSet++)\n      *CharSet = (*CharSet & ~(UInt32)0xff) | (unsigned)i;\n  memset(NumToPlace, 0, sizeof(NToPl));\n  for (i = 6; i >= 0; i--)\n    NumToPlace[i] = (7 - (unsigned)i) * 32;\n}\n\n\n\nHRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo * /* progress */)\n{\n  if (!inSize || !outSize)\n    return E_INVALIDARG;\n\n  if (_isSolid && !_solidAllowed)\n    return S_FALSE;\n\n  _solidAllowed = false;\n\n  if (!m_OutWindowStream.Create(kHistorySize))\n    return E_OUTOFMEMORY;\n  if (!m_InBitStream.Create(1 << 20))\n    return E_OUTOFMEMORY;\n\n  m_UnpackSize = *outSize;\n\n  m_OutWindowStream.SetStream(outStream);\n  m_OutWindowStream.Init(_isSolid);\n  m_InBitStream.SetStream(inStream);\n  m_InBitStream.Init();\n\n  // InitData\n\n  FlagsCnt = 0;\n  FlagBuf = 0;\n  StMode = false;\n  LCount = 0;\n\n  if (!_isSolid)\n  {\n    AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0;\n    AvrPlc = 0x3500;\n    MaxDist3 = 0x2001;\n    Nhfb = Nlzb = 0x80;\n\n    {\n      // InitStructures\n      for (unsigned i = 0; i < kNumRepDists; i++)\n        m_RepDists[i] = 0;\n      m_RepDistPtr = 0;\n      LastLength = 0;\n      LastDist = 0;\n    }\n    \n    // InitHuff\n    \n    for (UInt32 i = 0; i < 256; i++)\n    {\n      Place[i] = PlaceA[i] = PlaceB[i] = i;\n      UInt32 c = (~i + 1) & 0xff;\n      PlaceC[i] = c;\n      ChSet[i] = ChSetB[i] = i << 8;\n      ChSetA[i] = i;\n      ChSetC[i] = c << 8;\n    }\n    memset(NToPl, 0, sizeof(NToPl));\n    memset(NToPlB, 0, sizeof(NToPlB));\n    memset(NToPlC, 0, sizeof(NToPlC));\n    CorrHuff(ChSetB, NToPlB);\n  }\n   \n  if (m_UnpackSize > 0)\n  {\n    GetFlagsBuf();\n    FlagsCnt = 8;\n  }\n\n  while (m_UnpackSize != 0)\n  {\n    if (!StMode)\n    {\n      if (--FlagsCnt < 0)\n      {\n        GetFlagsBuf();\n        FlagsCnt = 7;\n      }\n      \n      if (FlagBuf & 0x80)\n      {\n        FlagBuf <<= 1;\n        if (Nlzb > Nhfb)\n        {\n          RINOK(LongLZ())\n          continue;\n        }\n      }\n      else\n      {\n        FlagBuf <<= 1;\n        \n        if (--FlagsCnt < 0)\n        {\n          GetFlagsBuf();\n          FlagsCnt = 7;\n        }\n\n        if ((FlagBuf & 0x80) == 0)\n        {\n          FlagBuf <<= 1;\n          RINOK(ShortLZ())\n          continue;\n        }\n        \n        FlagBuf <<= 1;\n        \n        if (Nlzb <= Nhfb)\n        {\n          RINOK(LongLZ())\n          continue;\n        }\n      }\n    }\n\n    RINOK(HuffDecode())\n  }\n  \n  _solidAllowed = true;\n  return m_OutWindowStream.Flush();\n}\n\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n{\n  if (size < 1)\n    return E_INVALIDARG;\n  _isSolid = ((data[0] & 1) != 0);\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar1Decoder.h",
    "content": "﻿// Rar1Decoder.h\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n#ifndef ZIP7_INC_COMPRESS_RAR1_DECODER_H\n#define ZIP7_INC_COMPRESS_RAR1_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n\n#include \"BitmDecoder.h\"\n#include \"LzOutWindow.h\"\n\nnamespace NCompress {\nnamespace NRar1 {\n\nconst unsigned kNumRepDists = 4;\n\nZ7_CLASS_IMP_COM_2(\n  CDecoder\n  , ICompressCoder\n  , ICompressSetDecoderProperties2\n)\n  bool _isSolid;\n  bool _solidAllowed;\n  bool StMode;\n\n  CLzOutWindow m_OutWindowStream;\n  NBitm::CDecoder<CInBuffer> m_InBitStream;\n\n  UInt64 m_UnpackSize;\n\n  UInt32 LastDist;\n  UInt32 LastLength;\n\n  UInt32 m_RepDistPtr;\n  UInt32 m_RepDists[kNumRepDists];\n\n  int FlagsCnt;\n  UInt32 FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3;\n  unsigned Buf60, NumHuf, LCount;\n  UInt32 Nhfb, Nlzb, MaxDist3;\n\n  UInt32 ChSet[256], ChSetA[256], ChSetB[256], ChSetC[256];\n  UInt32 Place[256], PlaceA[256], PlaceB[256], PlaceC[256];\n  UInt32 NToPl[256], NToPlB[256], NToPlC[256];\n\n  UInt32 ReadBits(unsigned numBits);\n  HRESULT CopyBlock(UInt32 distance, UInt32 len);\n  UInt32 DecodeNum(const Byte *numTab);\n  HRESULT ShortLZ();\n  HRESULT LongLZ();\n  HRESULT HuffDecode();\n  void GetFlagsBuf();\n  void CorrHuff(UInt32 *CharSet, UInt32 *NumToPlace);\n  void OldUnpWriteBuf();\n  \n  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\n\npublic:\n  CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar2Decoder.cpp",
    "content": "﻿// Rar2Decoder.cpp\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n \n#include \"StdAfx.h\"\n\n#include <stdlib.h>\n\n#include \"Rar2Decoder.h\"\n\nnamespace NCompress {\nnamespace NRar2 {\n\nnamespace NMultimedia {\n\n#define my_abs(x) (unsigned)abs(x)\n\nByte CFilter::Decode(int &channelDelta, Byte deltaByte)\n{\n  D4 = D3;\n  D3 = D2;\n  D2 = LastDelta - D1;\n  D1 = LastDelta;\n  const int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3);\n\n  const Byte realValue = (Byte)(predictedValue - deltaByte);\n  \n  {\n    const int i = ((int)(signed char)deltaByte) << 3;\n\n    Dif[0] += my_abs(i);\n    Dif[1] += my_abs(i - D1);\n    Dif[2] += my_abs(i + D1);\n    Dif[3] += my_abs(i - D2);\n    Dif[4] += my_abs(i + D2);\n    Dif[5] += my_abs(i - D3);\n    Dif[6] += my_abs(i + D3);\n    Dif[7] += my_abs(i - D4);\n    Dif[8] += my_abs(i + D4);\n    Dif[9] += my_abs(i - channelDelta);\n    Dif[10] += my_abs(i + channelDelta);\n  }\n\n  channelDelta = LastDelta = (signed char)(realValue - LastChar);\n  LastChar = realValue;\n\n  if (((++ByteCount) & 0x1F) == 0)\n  {\n    UInt32 minDif = Dif[0];\n    UInt32 numMinDif = 0;\n    Dif[0] = 0;\n    \n    for (unsigned i = 1; i < Z7_ARRAY_SIZE(Dif); i++)\n    {\n      if (Dif[i] < minDif)\n      {\n        minDif = Dif[i];\n        numMinDif = i;\n      }\n      Dif[i] = 0;\n    }\n    \n    switch (numMinDif)\n    {\n      case 1: if (K1 >= -16) K1--; break;\n      case 2: if (K1 <   16) K1++; break;\n      case 3: if (K2 >= -16) K2--; break;\n      case 4: if (K2 <   16) K2++; break;\n      case 5: if (K3 >= -16) K3--; break;\n      case 6: if (K3 <   16) K3++; break;\n      case 7: if (K4 >= -16) K4--; break;\n      case 8: if (K4 <   16) K4++; break;\n      case 9: if (K5 >= -16) K5--; break;\n      case 10:if (K5 <   16) K5++; break;\n    }\n  }\n  \n  return realValue;\n}\n}\n\nstatic const UInt32 kHistorySize = 1 << 20;\n\n// static const UInt32 kWindowReservSize = (1 << 22) + 256;\n\nCDecoder::CDecoder():\n  _isSolid(false),\n  _solidAllowed(false),\n  m_TablesOK(false)\n{\n}\n\nvoid CDecoder::InitStructures()\n{\n  m_MmFilter.Init();\n  for (unsigned i = 0; i < kNumReps; i++)\n    m_RepDists[i] = 0;\n  m_RepDistPtr = 0;\n  m_LastLength = 0;\n  memset(m_LastLevels, 0, kMaxTableSize);\n}\n\nUInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); }\n\n#define RIF(x) { if (!(x)) return false; }\n\nstatic const unsigned kRepBothNumber = 256;\nstatic const unsigned kRepNumber = kRepBothNumber + 1;\nstatic const unsigned kLen2Number = kRepNumber + kNumReps;\nstatic const unsigned kReadTableNumber = kLen2Number + kNumLen2Symbols;\nstatic const unsigned kMatchNumber = kReadTableNumber + 1;\n\n// static const unsigned kDistTableStart = kMainTableSize;\n// static const unsigned kLenTableStart = kDistTableStart + kDistTableSize;\n\nstatic const UInt32 kDistStart   [kDistTableSize] = {0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};\nstatic const Byte kDistDirectBits[kDistTableSize] = {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5,  6,  6,  7,  7,  8,  8,   9,   9,  10,  10,  11,  11,  12,   12,   13,   13,    14,    14,   15,   15,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16,    16};\n\nstatic const Byte kLen2DistStarts    [kNumLen2Symbols]={0,4,8,16,32,64,128,192};\nstatic const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6,  6,  6};\n\nstatic const UInt32 kDistLimit2 = 0x101 - 1;\nstatic const UInt32 kDistLimit3 = 0x2000 - 1;\nstatic const UInt32 kDistLimit4 = 0x40000 - 1;\n\n// static const UInt32 kMatchMaxLen = 255 + 2;\n// static const UInt32 kMatchMaxLenMax = 255 + 5;\n\n\nbool CDecoder::ReadTables(void)\n{\n  m_TablesOK = false;\n\n  const unsigned kLevelTableSize = 19;\n  Byte levelLevels[kLevelTableSize];\n  Byte lens[kMaxTableSize];\n  \n  m_AudioMode = (ReadBits(1) == 1);\n\n  if (ReadBits(1) == 0)\n    memset(m_LastLevels, 0, kMaxTableSize);\n  \n  unsigned numLevels;\n  \n  if (m_AudioMode)\n  {\n    m_NumChannels = ReadBits(2) + 1;\n    if (m_MmFilter.CurrentChannel >= m_NumChannels)\n      m_MmFilter.CurrentChannel = 0;\n    numLevels = m_NumChannels * k_MM_TableSize;\n  }\n  else\n    numLevels = kHeapTablesSizesSum;\n \n  unsigned i;\n  for (i = 0; i < kLevelTableSize; i++)\n    levelLevels[i] = (Byte)ReadBits(4);\n  NHuffman::CDecoder256<kNumHufBits, kLevelTableSize, 6> m_LevelDecoder;\n  RIF(m_LevelDecoder.Build(levelLevels, NHuffman::k_BuildMode_Full))\n  \n  i = 0;\n  do\n  {\n    const unsigned sym = m_LevelDecoder.DecodeFull(&m_InBitStream);\n    if (sym < 16)\n    {\n      lens[i] = (Byte)((sym + m_LastLevels[i]) & 15);\n      i++;\n    }\n#if 0\n    else if (sym >= kLevelTableSize)\n      return false;\n#endif\n    else\n    {\n      unsigned num;\n      Byte v;\n      if (sym == 16)\n      {\n        if (i == 0)\n          return false;\n        num = ReadBits(2) + 3;\n        v = lens[(size_t)i - 1];\n      }\n      else\n      {\n        num = (sym - 17) * 4;\n        num += num + 3 + ReadBits(3 + num);\n        v = 0;\n      }\n      num += i;\n      if (num > numLevels)\n      {\n        // return false;\n        num = numLevels; // original unRAR\n      }\n      do\n        lens[i++] = v;\n      while (i < num);\n    }\n  }\n  while (i < numLevels);\n\n  if (m_InBitStream.ExtraBitsWereRead())\n    return false;\n\n  if (m_AudioMode)\n    for (i = 0; i < m_NumChannels; i++)\n    {\n      RIF(m_MMDecoders[i].Build(&lens[(size_t)i * k_MM_TableSize]))\n    }\n  else\n  {\n    RIF(m_MainDecoder.Build(&lens[0]))\n    RIF(m_DistDecoder.Build(&lens[kMainTableSize]))\n    RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize]))\n  }\n  \n  memcpy(m_LastLevels, lens, kMaxTableSize);\n\n  m_TablesOK = true;\n  return true;\n}\n\n\nbool CDecoder::ReadLastTables()\n{\n  // it differs a little from pure RAR sources;\n  // UInt64 ttt = m_InBitStream.GetProcessedSize() + 2;\n  // + 2 works for: return 0xFF; in CInBuffer::ReadByte.\n  if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect;\n  // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;\n  {\n    if (m_AudioMode)\n    {\n      const unsigned symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);\n      if (symbol == 256)\n        return ReadTables();\n      if (symbol >= k_MM_TableSize)\n        return false;\n    }\n    else\n    {\n      const unsigned sym = m_MainDecoder.Decode(&m_InBitStream);\n      if (sym == kReadTableNumber)\n        return ReadTables();\n      if (sym >= kMainTableSize)\n        return false;\n    }\n  }\n  return true;\n}\n\n\nbool CDecoder::DecodeMm(UInt32 pos)\n{\n  while (pos-- != 0)\n  {\n    const unsigned symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);\n    if (m_InBitStream.ExtraBitsWereRead())\n      return false;\n    if (symbol >= 256)\n      return symbol == 256;\n    /*\n    Byte byPredict = m_Predictor.Predict();\n    Byte byReal = (Byte)(byPredict - (Byte)symbol);\n    m_Predictor.Update(byReal, byPredict);\n    */\n    const Byte byReal = m_MmFilter.Decode((Byte)symbol);\n    m_OutWindowStream.PutByte(byReal);\n    if (++m_MmFilter.CurrentChannel == m_NumChannels)\n      m_MmFilter.CurrentChannel = 0;\n  }\n  return true;\n}\n\n\ntypedef unsigned CLenType;\n\nstatic inline CLenType SlotToLen(CBitDecoder &_bitStream, CLenType slot)\n{\n  const unsigned numBits = ((unsigned)slot >> 2) - 1;\n  return ((4 | (slot & 3)) << numBits) + (CLenType)_bitStream.ReadBits(numBits);\n}\n\nbool CDecoder::DecodeLz(Int32 pos)\n{\n  while (pos > 0)\n  {\n    unsigned sym = m_MainDecoder.Decode(&m_InBitStream);\n    if (m_InBitStream.ExtraBitsWereRead())\n      return false;\n    UInt32 len, distance;\n    if (sym < 256)\n    {\n      m_OutWindowStream.PutByte(Byte(sym));\n      pos--;\n      continue;\n    }\n    else if (sym >= kMatchNumber)\n    {\n      if (sym >= kMainTableSize)\n        return false;\n      len = sym - kMatchNumber;\n      if (len >= 8)\n        len = SlotToLen(m_InBitStream, len);\n      len += 3;\n\n      sym = m_DistDecoder.Decode(&m_InBitStream);\n      if (sym >= kDistTableSize)\n        return false;\n      distance = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]);\n      if (distance >= kDistLimit3)\n      {\n        len += 2 - ((distance - kDistLimit4) >> 31);\n        // len++;\n        // if (distance >= kDistLimit4)\n        //  len++;\n      }\n    }\n    else if (sym == kRepBothNumber)\n    {\n      len = m_LastLength;\n      if (len == 0)\n        return false;\n      distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3];\n    }\n    else if (sym < kLen2Number)\n    {\n      distance = m_RepDists[(m_RepDistPtr - (sym - kRepNumber + 1)) & 3];\n      len = m_LenDecoder.Decode(&m_InBitStream);\n      if (len >= kLenTableSize)\n        return false;\n      if (len >= 8)\n        len = SlotToLen(m_InBitStream, len);\n      len += 2;\n\n      if (distance >= kDistLimit2)\n      {\n        len++;\n        if (distance >= kDistLimit3)\n        {\n          len += 2 - ((distance - kDistLimit4) >> 31);\n          // len++;\n          // if (distance >= kDistLimit4)\n          //   len++;\n        }\n      }\n    }\n    else if (sym < kReadTableNumber)\n    {\n      sym -= kLen2Number;\n      distance = kLen2DistStarts[sym] +\n        m_InBitStream.ReadBits(kLen2DistDirectBits[sym]);\n      len = 2;\n    }\n    else // (sym == kReadTableNumber)\n      return true;\n\n    m_RepDists[m_RepDistPtr++ & 3] = distance;\n    m_LastLength = len;\n    if (!m_OutWindowStream.CopyBlock(distance, len))\n      return false;\n    pos -= len;\n  }\n  return true;\n}\n\nHRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\n{\n  if (!inSize || !outSize)\n    return E_INVALIDARG;\n\n  if (_isSolid && !_solidAllowed)\n    return S_FALSE;\n  _solidAllowed = false;\n\n  if (!m_OutWindowStream.Create(kHistorySize))\n    return E_OUTOFMEMORY;\n  if (!m_InBitStream.Create(1 << 20))\n    return E_OUTOFMEMORY;\n\n  m_PackSize = *inSize;\n\n  UInt64 pos = 0, unPackSize = *outSize;\n  \n  m_OutWindowStream.SetStream(outStream);\n  m_OutWindowStream.Init(_isSolid);\n  m_InBitStream.SetStream(inStream);\n  m_InBitStream.Init();\n\n  // CCoderReleaser coderReleaser(this);\n  if (!_isSolid)\n  {\n    InitStructures();\n    if (unPackSize == 0)\n    {\n      if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;\n        if (!ReadTables())\n          return S_FALSE;\n      _solidAllowed = true;\n      return S_OK;\n    }\n    ReadTables();\n  }\n\n  if (!m_TablesOK)\n    return S_FALSE;\n\n  const UInt64 startPos = m_OutWindowStream.GetProcessedSize();\n  while (pos < unPackSize)\n  {\n    UInt32 blockSize = 1 << 20;\n    if (blockSize > unPackSize - pos)\n      blockSize = (UInt32)(unPackSize - pos);\n    UInt64 blockStartPos = m_OutWindowStream.GetProcessedSize();\n    if (m_AudioMode)\n    {\n      if (!DecodeMm(blockSize))\n        return S_FALSE;\n    }\n    else\n    {\n      if (!DecodeLz((Int32)blockSize))\n        return S_FALSE;\n    }\n\n    if (m_InBitStream.ExtraBitsWereRead())\n      return S_FALSE;\n\n    const UInt64 globalPos = m_OutWindowStream.GetProcessedSize();\n    pos = globalPos - blockStartPos;\n    if (pos < blockSize)\n      if (!ReadTables())\n        return S_FALSE;\n    pos = globalPos - startPos;\n    if (progress)\n    {\n      const UInt64 packSize = m_InBitStream.GetProcessedSize();\n      RINOK(progress->SetRatioInfo(&packSize, &pos))\n    }\n  }\n  if (pos > unPackSize)\n    return S_FALSE;\n\n  if (!ReadLastTables())\n    return S_FALSE;\n\n  _solidAllowed = true;\n\n  return m_OutWindowStream.Flush();\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const CLzOutWindowException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n{\n  if (size < 1)\n    return E_INVALIDARG;\n  _isSolid = ((data[0] & 1) != 0);\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar2Decoder.h",
    "content": "﻿// Rar2Decoder.h\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n#ifndef ZIP7_INC_COMPRESS_RAR2_DECODER_H\n#define ZIP7_INC_COMPRESS_RAR2_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n\n#include \"BitmDecoder.h\"\n#include \"HuffmanDecoder.h\"\n#include \"LzOutWindow.h\"\n\nnamespace NCompress {\nnamespace NRar2 {\n\nconst unsigned kNumReps = 4;\nconst unsigned kDistTableSize = 48;\nconst unsigned kNumLen2Symbols = 8;\nconst unsigned kLenTableSize = 28;\nconst unsigned kMainTableSize = 256 + 2 + kNumReps + kNumLen2Symbols + kLenTableSize;\nconst unsigned kHeapTablesSizesSum = kMainTableSize + kDistTableSize + kLenTableSize;\nconst unsigned k_MM_TableSize = 256 + 1;\nconst unsigned k_MM_NumChanelsMax = 4;\nconst unsigned k_MM_TablesSizesSum = k_MM_TableSize * k_MM_NumChanelsMax;\nconst unsigned kMaxTableSize = k_MM_TablesSizesSum;\n\nnamespace NMultimedia {\n\nstruct CFilter\n{\n  int K1,K2,K3,K4,K5;\n  int D1,D2,D3,D4;\n  int LastDelta;\n  UInt32 Dif[11];\n  UInt32 ByteCount;\n  int LastChar;\n\n  void Init() { memset(this, 0, sizeof(*this)); }\n  Byte Decode(int &channelDelta, Byte delta);\n};\n\nstruct CFilter2\n{\n  CFilter  m_Filters[k_MM_NumChanelsMax];\n  int m_ChannelDelta;\n  unsigned CurrentChannel;\n\n  void Init() { memset(this, 0, sizeof(*this)); }\n  Byte Decode(Byte delta)\n  {\n    return m_Filters[CurrentChannel].Decode(m_ChannelDelta, delta);\n  }\n};\n\n}\n\ntypedef NBitm::CDecoder<CInBuffer> CBitDecoder;\n\nconst unsigned kNumHufBits = 15;\n\nZ7_CLASS_IMP_NOQIB_2(\n  CDecoder\n  , ICompressCoder\n  , ICompressSetDecoderProperties2\n)\n  bool _isSolid;\n  bool _solidAllowed;\n  bool m_TablesOK;\n  bool m_AudioMode;\n\n  CLzOutWindow m_OutWindowStream;\n  CBitDecoder m_InBitStream;\n\n  UInt32 m_RepDistPtr;\n  UInt32 m_RepDists[kNumReps];\n  UInt32 m_LastLength;\n  unsigned m_NumChannels;\n\n  NHuffman::CDecoder<kNumHufBits, kMainTableSize, 9> m_MainDecoder;\n  NHuffman::CDecoder256<kNumHufBits, kDistTableSize, 7> m_DistDecoder;\n  NHuffman::CDecoder256<kNumHufBits, kLenTableSize, 7> m_LenDecoder;\n  NHuffman::CDecoder<kNumHufBits, k_MM_TableSize, 9> m_MMDecoders[k_MM_NumChanelsMax];\n\n  UInt64 m_PackSize;\n  \n  NMultimedia::CFilter2 m_MmFilter;\n  Byte m_LastLevels[kMaxTableSize];\n\n  void InitStructures();\n  UInt32 ReadBits(unsigned numBits);\n  bool ReadTables();\n  bool ReadLastTables();\n\n  bool DecodeMm(UInt32 pos);\n  bool DecodeLz(Int32 pos);\n\n  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\n\npublic:\n  CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar3Decoder.cpp",
    "content": "﻿// Rar3Decoder.cpp\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\n \n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"Rar3Decoder.h\"\n\nnamespace NCompress {\nnamespace NRar3 {\n\nstatic const UInt32 kNumAlignReps = 15;\n\nstatic const unsigned kSymbolReadTable = 256;\nstatic const unsigned kSymbolRep = 259;\n\nstatic const Byte kDistDirectBits[kDistTableSize] =\n  {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,\n  16,16,16,16,16,16,16,16,16,16,16,16,16,16,\n  18,18,18,18,18,18,18,18,18,18,18,18};\n\nstatic const Byte kLen2DistStarts[kNumLen2Symbols] = {0,4,8,16,32,64,128,192};\nstatic const Byte kLen2DistDirectBits[kNumLen2Symbols] = {2,2,3, 4, 5, 6,  6,  6};\n\nstatic const UInt32 kDistLimit3 = 0x2000 - 2;\nstatic const UInt32 kDistLimit4 = 0x40000 - 2;\n\nstatic const UInt32 kNormalMatchMinLen = 3;\n\nstatic const UInt32 kVmDataSizeMax = 1 << 16;\nstatic const UInt32 kVmCodeSizeMax = 1 << 16;\n\nextern \"C\" {\n\nstatic Byte Wrap_ReadByte(IByteInPtr pp) throw()\n{\n  CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);\n  return p->BitDecoder.Stream.ReadByte();\n}\n\nstatic Byte Wrap_ReadBits8(IByteInPtr pp) throw()\n{\n  CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);\n  return (Byte)p->BitDecoder.ReadByteFromAligned();\n}\n\n}\n\n\nCDecoder::CDecoder():\n  _isSolid(false),\n  _solidAllowed(false),\n  _window(NULL),\n  _winPos(0),\n  _wrPtr(0),\n  _lzSize(0),\n  _writtenFileSize(0),\n  _vmData(NULL),\n  _vmCode(NULL)\n{\n  Ppmd7_Construct(&_ppmd);\n  \n  UInt32 start = 0;\n  for (UInt32 i = 0; i < kDistTableSize; i++)\n  {\n    kDistStart[i] = start;\n    start += ((UInt32)1 << kDistDirectBits[i]);\n  }\n}\n\nCDecoder::~CDecoder()\n{\n  InitFilters();\n  ::MidFree(_vmData);\n  ::MidFree(_window);\n  Ppmd7_Free(&_ppmd, &g_BigAlloc);\n}\n\nHRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)\n{\n  return WriteStream(_outStream, data, size);\n}\n\nHRESULT CDecoder::WriteData(const Byte *data, UInt32 size)\n{\n  HRESULT res = S_OK;\n  if (_writtenFileSize < _unpackSize)\n  {\n    UInt32 curSize = size;\n    UInt64 remain = _unpackSize - _writtenFileSize;\n    if (remain < curSize)\n      curSize = (UInt32)remain;\n    res = WriteDataToStream(data, curSize);\n  }\n  _writtenFileSize += size;\n  return res;\n}\n\nHRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)\n{\n  if (startPtr <= endPtr)\n    return WriteData(_window + startPtr, endPtr - startPtr);\n  RINOK(WriteData(_window + startPtr, kWindowSize - startPtr))\n  return WriteData(_window, endPtr);\n}\n\nvoid CDecoder::ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef)\n{\n  CTempFilter *tempFilter = _tempFilters[tempFilterIndex];\n  tempFilter->InitR[6] = (UInt32)_writtenFileSize;\n  NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);\n  NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));\n  CFilter *filter = _filters[tempFilter->FilterIndex];\n  if (!filter->IsSupported)\n    _unsupportedFilter = true;\n  if (!_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData))\n    _unsupportedFilter = true;\n  delete tempFilter;\n  _tempFilters[tempFilterIndex] = NULL;\n  _numEmptyTempFilters++;\n}\n\nHRESULT CDecoder::WriteBuf()\n{\n  UInt32 writtenBorder = _wrPtr;\n  UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask;\n  FOR_VECTOR (i, _tempFilters)\n  {\n    CTempFilter *filter = _tempFilters[i];\n    if (!filter)\n      continue;\n    if (filter->NextWindow)\n    {\n      filter->NextWindow = false;\n      continue;\n    }\n    UInt32 blockStart = filter->BlockStart;\n    UInt32 blockSize = filter->BlockSize;\n    if (((blockStart - writtenBorder) & kWindowMask) < writeSize)\n    {\n      if (writtenBorder != blockStart)\n      {\n        RINOK(WriteArea(writtenBorder, blockStart))\n        writtenBorder = blockStart;\n        writeSize = (_winPos - writtenBorder) & kWindowMask;\n      }\n      if (blockSize <= writeSize)\n      {\n        UInt32 blockEnd = (blockStart + blockSize) & kWindowMask;\n        if (blockStart < blockEnd || blockEnd == 0)\n          _vm.SetMemory(0, _window + blockStart, blockSize);\n        else\n        {\n          UInt32 tailSize = kWindowSize - blockStart;\n          _vm.SetMemory(0, _window + blockStart, tailSize);\n          _vm.SetMemory(tailSize, _window, blockEnd);\n        }\n        NVm::CBlockRef outBlockRef;\n        ExecuteFilter(i, outBlockRef);\n        while (i + 1 < _tempFilters.Size())\n        {\n          CTempFilter *nextFilter = _tempFilters[i + 1];\n          if (!nextFilter\n              || nextFilter->BlockStart != blockStart\n              || nextFilter->BlockSize != outBlockRef.Size\n              || nextFilter->NextWindow)\n            break;\n          _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);\n          ExecuteFilter(++i, outBlockRef);\n        }\n        WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);\n        _writtenFileSize += outBlockRef.Size;\n        writtenBorder = blockEnd;\n        writeSize = (_winPos - writtenBorder) & kWindowMask;\n      }\n      else\n      {\n        for (unsigned j = i; j < _tempFilters.Size(); j++)\n        {\n          CTempFilter *filter2 = _tempFilters[j];\n          if (filter2 && filter2->NextWindow)\n            filter2->NextWindow = false;\n        }\n        _wrPtr = writtenBorder;\n        return S_OK; // check it\n      }\n    }\n  }\n      \n  _wrPtr = _winPos;\n  return WriteArea(writtenBorder, _winPos);\n}\n\nvoid CDecoder::InitFilters()\n{\n  _lastFilter = 0;\n  _numEmptyTempFilters = 0;\n  unsigned i;\n  for (i = 0; i < _tempFilters.Size(); i++)\n    delete _tempFilters[i];\n  _tempFilters.Clear();\n  for (i = 0; i < _filters.Size(); i++)\n    delete _filters[i];\n  _filters.Clear();\n}\n\nstatic const unsigned MAX_UNPACK_FILTERS = 8192;\n\nbool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)\n{\n  CMemBitDecoder inp;\n  inp.Init(_vmData, codeSize);\n\n  UInt32 filterIndex;\n  \n  if (firstByte & 0x80)\n  {\n    filterIndex = inp.ReadEncodedUInt32();\n    if (filterIndex == 0)\n      InitFilters();\n    else\n      filterIndex--;\n  }\n  else\n    filterIndex = _lastFilter;\n  \n  if (filterIndex > (UInt32)_filters.Size())\n    return false;\n  _lastFilter = filterIndex;\n  bool newFilter = (filterIndex == (UInt32)_filters.Size());\n\n  CFilter *filter;\n  if (newFilter)\n  {\n    // check if too many filters\n    if (filterIndex > MAX_UNPACK_FILTERS)\n      return false;\n    filter = new CFilter;\n    _filters.Add(filter);\n  }\n  else\n  {\n    filter = _filters[filterIndex];\n    filter->ExecCount++;\n  }\n\n  if (_numEmptyTempFilters != 0)\n  {\n    const unsigned num = _tempFilters.Size();\n    CTempFilter **tempFilters = _tempFilters.NonConstData();\n    \n    unsigned w = 0;\n    for (unsigned i = 0; i < num; i++)\n    {\n      CTempFilter *tf = tempFilters[i];\n      if (tf)\n        tempFilters[w++] = tf;\n    }\n\n    _tempFilters.DeleteFrom(w);\n    _numEmptyTempFilters = 0;\n  }\n  \n  if (_tempFilters.Size() > MAX_UNPACK_FILTERS)\n    return false;\n  CTempFilter *tempFilter = new CTempFilter;\n  _tempFilters.Add(tempFilter);\n  tempFilter->FilterIndex = filterIndex;\n \n  UInt32 blockStart = inp.ReadEncodedUInt32();\n  if (firstByte & 0x40)\n    blockStart += 258;\n  tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask;\n  if (firstByte & 0x20)\n    filter->BlockSize = inp.ReadEncodedUInt32();\n  tempFilter->BlockSize = filter->BlockSize;\n  tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart;\n\n  memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR));\n  tempFilter->InitR[3] = NVm::kGlobalOffset;\n  tempFilter->InitR[4] = tempFilter->BlockSize;\n  tempFilter->InitR[5] = filter->ExecCount;\n  if (firstByte & 0x10)\n  {\n    UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs);\n    for (unsigned i = 0; i < NVm::kNumGpRegs; i++)\n      if (initMask & (1 << i))\n        tempFilter->InitR[i] = inp.ReadEncodedUInt32();\n  }\n\n  bool isOK = true;\n  if (newFilter)\n  {\n    UInt32 vmCodeSize = inp.ReadEncodedUInt32();\n    if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0)\n      return false;\n    for (UInt32 i = 0; i < vmCodeSize; i++)\n      _vmCode[i] = (Byte)inp.ReadBits(8);\n    isOK = filter->PrepareProgram(_vmCode, vmCodeSize);\n  }\n\n  {\n    Byte *globalData = &tempFilter->GlobalData[0];\n    for (unsigned i = 0; i < NVm::kNumGpRegs; i++)\n      NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]);\n    NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize);\n    NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why?\n    NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], filter->ExecCount);\n  }\n\n  if (firstByte & 8)\n  {\n    UInt32 dataSize = inp.ReadEncodedUInt32();\n    if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize)\n      return false;\n    CRecordVector<Byte> &globalData = tempFilter->GlobalData;\n    unsigned requiredSize = (unsigned)(dataSize + NVm::kFixedGlobalSize);\n    if (globalData.Size() < requiredSize)\n      globalData.ChangeSize_KeepData(requiredSize);\n    Byte *dest = &globalData[NVm::kFixedGlobalSize];\n    for (UInt32 i = 0; i < dataSize; i++)\n      dest[i] = (Byte)inp.ReadBits(8);\n  }\n  \n  return isOK;\n}\n\nbool CDecoder::ReadVmCodeLZ()\n{\n  UInt32 firstByte = ReadBits(8);\n  UInt32 len = (firstByte & 7) + 1;\n  if (len == 7)\n    len = ReadBits(8) + 7;\n  else if (len == 8)\n    len = ReadBits(16);\n  if (len > kVmDataSizeMax)\n    return false;\n  for (UInt32 i = 0; i < len; i++)\n    _vmData[i] = (Byte)ReadBits(8);\n  return AddVmCode(firstByte, len);\n}\n\n\n// int CDecoder::DecodePpmSymbol() { return Ppmd7a_DecodeSymbol(&_ppmd); }\n#define DecodePpmSymbol() Ppmd7a_DecodeSymbol(&_ppmd)\n\n\nbool CDecoder::ReadVmCodePPM()\n{\n  const int firstByte = DecodePpmSymbol();\n  if (firstByte < 0)\n    return false;\n  UInt32 len = (firstByte & 7) + 1;\n  if (len == 7)\n  {\n    const int b1 = DecodePpmSymbol();\n    if (b1 < 0)\n      return false;\n    len = (unsigned)b1 + 7;\n  }\n  else if (len == 8)\n  {\n    const int b1 = DecodePpmSymbol();\n    if (b1 < 0)\n      return false;\n    const int b2 = DecodePpmSymbol();\n    if (b2 < 0)\n      return false;\n    len = (unsigned)b1 * 256 + (unsigned)b2;\n  }\n  if (len > kVmDataSizeMax)\n    return false;\n  if (InputEofError_Fast())\n    return false;\n  for (UInt32 i = 0; i < len; i++)\n  {\n    const int b = DecodePpmSymbol();\n    if (b < 0)\n      return false;\n    _vmData[i] = (Byte)b;\n  }\n  return AddVmCode((unsigned)firstByte, len);\n}\n\n#define RIF(x) { if (!(x)) return S_FALSE; }\n\nUInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.BitDecoder.ReadBits(numBits); }\n\n// ---------- PPM ----------\n\nHRESULT CDecoder::InitPPM()\n{\n  unsigned maxOrder = (unsigned)ReadBits(7);\n\n  const bool reset = ((maxOrder & 0x20) != 0);\n  UInt32 maxMB = 0;\n  if (reset)\n    maxMB = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);\n  else\n  {\n    if (PpmError || !Ppmd7_WasAllocated(&_ppmd))\n      return S_FALSE;\n  }\n  if (maxOrder & 0x40)\n    PpmEscChar = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);\n\n  _ppmd.rc.dec.Stream = &m_InBitStream.IByteIn_obj;\n  m_InBitStream.IByteIn_obj.Read = Wrap_ReadBits8;\n\n  Ppmd7a_RangeDec_Init(&_ppmd.rc.dec);\n\n  m_InBitStream.IByteIn_obj.Read = Wrap_ReadByte;\n\n  if (reset)\n  {\n    PpmError = true;\n    maxOrder = (maxOrder & 0x1F) + 1;\n    if (maxOrder > 16)\n      maxOrder = 16 + (maxOrder - 16) * 3;\n    if (maxOrder == 1)\n    {\n      Ppmd7_Free(&_ppmd, &g_BigAlloc);\n      return S_FALSE;\n    }\n    if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc))\n      return E_OUTOFMEMORY;\n    Ppmd7_Init(&_ppmd, maxOrder);\n    PpmError = false;\n  }\n  return S_OK;\n}\n\n\nHRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)\n{\n  keepDecompressing = false;\n  if (PpmError)\n    return S_FALSE;\n  do\n  {\n    if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)\n    {\n      RINOK(WriteBuf())\n      if (_writtenFileSize > _unpackSize)\n      {\n        keepDecompressing = false;\n        return S_OK;\n      }\n    }\n    if (InputEofError_Fast())\n      return false;\n    const int c = DecodePpmSymbol();\n    if (c < 0)\n    {\n      PpmError = true;\n      return S_FALSE;\n    }\n    if (c == PpmEscChar)\n    {\n      const int nextCh = DecodePpmSymbol();\n      if (nextCh < 0)\n      {\n        PpmError = true;\n        return S_FALSE;\n      }\n      if (nextCh == 0)\n        return ReadTables(keepDecompressing);\n      if (nextCh == 2 || nextCh == -1)\n        return S_OK;\n      if (nextCh == 3)\n      {\n        if (!ReadVmCodePPM())\n        {\n          PpmError = true;\n          return S_FALSE;\n        }\n        continue;\n      }\n      if (nextCh == 4 || nextCh == 5)\n      {\n        UInt32 dist = 0;\n        UInt32 len = 4;\n        if (nextCh == 4)\n        {\n          for (int i = 0; i < 3; i++)\n          {\n            const int c2 = DecodePpmSymbol();\n            if (c2 < 0)\n            {\n              PpmError = true;\n              return S_FALSE;\n            }\n            dist = (dist << 8) + (Byte)c2;\n          }\n          dist++;\n          len += 28;\n        }\n        const int c2 = DecodePpmSymbol();\n        if (c2 < 0)\n        {\n          PpmError = true;\n          return S_FALSE;\n        }\n        len += (unsigned)c2;\n        if (dist >= _lzSize)\n          return S_FALSE;\n        CopyBlock(dist, len);\n        num -= (Int32)len;\n        continue;\n      }\n    }\n    PutByte((Byte)c);\n    num--;\n  }\n  while (num >= 0);\n  keepDecompressing = true;\n  return S_OK;\n}\n\n// ---------- LZ ----------\n\nHRESULT CDecoder::ReadTables(bool &keepDecompressing)\n{\n  keepDecompressing = true;\n  m_InBitStream.BitDecoder.AlignToByte();\n  if (ReadBits(1) != 0)\n  {\n    _lzMode = false;\n    return InitPPM();\n  }\n\n  TablesRead = false;\n  TablesOK = false;\n\n  _lzMode = true;\n  PrevAlignBits = 0;\n  PrevAlignCount = 0;\n\n  const unsigned kLevelTableSize = 20;\n  Byte levelLevels[kLevelTableSize];\n  Byte lens[kTablesSizesSum];\n\n  if (ReadBits(1) == 0)\n    memset(m_LastLevels, 0, kTablesSizesSum);\n\n  unsigned i;\n\n  for (i = 0; i < kLevelTableSize; i++)\n  {\n    const UInt32 len = ReadBits(4);\n    if (len == 15)\n    {\n      UInt32 zeroCount = ReadBits(4);\n      if (zeroCount != 0)\n      {\n        zeroCount += 2;\n        while (zeroCount-- > 0 && i < kLevelTableSize)\n          levelLevels[i++]=0;\n        i--;\n        continue;\n      }\n    }\n    levelLevels[i] = (Byte)len;\n  }\n  \n  NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, 6> m_LevelDecoder;\n  RIF(m_LevelDecoder.Build(levelLevels, NHuffman::k_BuildMode_Full))\n  \n  i = 0;\n  \n  do\n  {\n    const unsigned sym = m_LevelDecoder.DecodeFull(&m_InBitStream.BitDecoder);\n    if (sym < 16)\n    {\n      lens[i] = Byte((sym + m_LastLevels[i]) & 15);\n      i++;\n    }\n#if 0\n    else if (sym > kLevelTableSize)\n      return S_FALSE;\n#endif\n    else\n    {\n      unsigned num = ((sym /* - 16 */) & 1) * 4;\n      num += num + 3 + (unsigned)ReadBits(num + 3);\n      num += i;\n      if (num > kTablesSizesSum)\n        num = kTablesSizesSum;\n      Byte v = 0;\n      if (sym < 16 + 2)\n      {\n        if (i == 0)\n          return S_FALSE;\n        v = lens[(size_t)i - 1];\n      }\n      do\n        lens[i++] = v;\n      while (i < num);\n    }\n  }\n  while (i < kTablesSizesSum);\n\n  if (InputEofError())\n    return S_FALSE;\n\n  TablesRead = true;\n\n  // original code has check here:\n  /*\n  if (InAddr > ReadTop)\n  {\n    keepDecompressing = false;\n    return true;\n  }\n  */\n\n  RIF(m_MainDecoder.Build(&lens[0]))\n  RIF(m_DistDecoder.Build(&lens[kMainTableSize]))\n  RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize]))\n  RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]))\n\n  memcpy(m_LastLevels, lens, kTablesSizesSum);\n\n  TablesOK = true;\n\n  return S_OK;\n}\n\n/*\nclass CCoderReleaser\n{\n  CDecoder *m_Coder;\npublic:\n  CCoderReleaser(CDecoder *coder): m_Coder(coder) {}\n  ~CCoderReleaser()\n  {\n    m_Coder->ReleaseStreams();\n  }\n};\n*/\n\nHRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)\n{\n  if (ReadBits(1) == 0)\n  {\n    // new file\n    keepDecompressing = false;\n    TablesRead = (ReadBits(1) == 0);\n    return S_OK;\n  }\n  TablesRead = false;\n  return ReadTables(keepDecompressing);\n}\n\n\nHRESULT CDecoder::DecodeLZ(bool &keepDecompressing)\n{\n  UInt32 rep0 = _reps[0];\n  UInt32 rep1 = _reps[1];\n  UInt32 rep2 = _reps[2];\n  UInt32 rep3 = _reps[3];\n  UInt32 len = _lastLength;\n  for (;;)\n  {\n    if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)\n    {\n      RINOK(WriteBuf())\n      if (_writtenFileSize > _unpackSize)\n      {\n        keepDecompressing = false;\n        return S_OK;\n      }\n    }\n    \n    if (InputEofError_Fast())\n      return S_FALSE;\n\n    unsigned sym = m_MainDecoder.Decode(&m_InBitStream.BitDecoder);\n    if (sym < 256)\n    {\n      PutByte((Byte)sym);\n      continue;\n    }\n    else if (sym == kSymbolReadTable)\n    {\n      RINOK(ReadEndOfBlock(keepDecompressing))\n      break;\n    }\n    else if (sym == 257)\n    {\n      if (!ReadVmCodeLZ())\n        return S_FALSE;\n      continue;\n    }\n    else if (sym == 258)\n    {\n      if (len == 0)\n        return S_FALSE;\n    }\n    else if (sym < kSymbolRep + 4)\n    {\n      if (sym != kSymbolRep)\n      {\n        UInt32 dist;\n        if (sym == kSymbolRep + 1)\n          dist = rep1;\n        else\n        {\n          if (sym == kSymbolRep + 2)\n            dist = rep2;\n          else\n          {\n            dist = rep3;\n            rep3 = rep2;\n          }\n          rep2 = rep1;\n        }\n        rep1 = rep0;\n        rep0 = dist;\n      }\n\n      const unsigned sym2 = m_LenDecoder.Decode(&m_InBitStream.BitDecoder);\n      if (sym2 >= kLenTableSize)\n        return S_FALSE;\n      len = 2 + sym2;\n      if (sym2 >= 8)\n      {\n        const unsigned num = (sym2 >> 2) - 1;\n        len = 2 + (UInt32)((4 + (sym2 & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);\n      }\n    }\n    else\n    {\n      rep3 = rep2;\n      rep2 = rep1;\n      rep1 = rep0;\n      if (sym < 271)\n      {\n        sym -= 263;\n        rep0 = kLen2DistStarts[sym] + m_InBitStream.BitDecoder.ReadBits_upto8(kLen2DistDirectBits[sym]);\n        len = 2;\n      }\n      else if (sym < 299)\n      {\n        sym -= 271;\n        len = kNormalMatchMinLen + sym;\n        if (sym >= 8)\n        {\n          const unsigned num = (sym >> 2) - 1;\n          len = kNormalMatchMinLen + (UInt32)((4 + (sym & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);\n        }\n        const unsigned sym2 = m_DistDecoder.Decode(&m_InBitStream.BitDecoder);\n        if (sym2 >= kDistTableSize)\n          return S_FALSE;\n        rep0 = kDistStart[sym2];\n        unsigned numBits = kDistDirectBits[sym2];\n        if (sym2 >= (kNumAlignBits * 2) + 2)\n        {\n          if (numBits > kNumAlignBits)\n            rep0 += (m_InBitStream.BitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);\n          if (PrevAlignCount > 0)\n          {\n            PrevAlignCount--;\n            rep0 += PrevAlignBits;\n          }\n          else\n          {\n            const unsigned sym3 = m_AlignDecoder.Decode(&m_InBitStream.BitDecoder);\n            if (sym3 < (1 << kNumAlignBits))\n            {\n              rep0 += sym3;\n              PrevAlignBits = sym3;\n            }\n            else if (sym3 == (1 << kNumAlignBits))\n            {\n              PrevAlignCount = kNumAlignReps;\n              rep0 += PrevAlignBits;\n            }\n            else\n              return S_FALSE;\n          }\n        }\n        else\n          rep0 += m_InBitStream.BitDecoder.ReadBits_upto8(numBits);\n        len += ((UInt32)(kDistLimit4 - rep0) >> 31) + ((UInt32)(kDistLimit3 - rep0) >> 31);\n      }\n      else\n        return S_FALSE;\n    }\n    if (rep0 >= _lzSize)\n      return S_FALSE;\n    CopyBlock(rep0, len);\n  }\n  _reps[0] = rep0;\n  _reps[1] = rep1;\n  _reps[2] = rep2;\n  _reps[3] = rep3;\n  _lastLength = len;\n\n  return S_OK;\n}\n\n\nHRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)\n{\n  _writtenFileSize = 0;\n  _unsupportedFilter = false;\n  \n  if (!_isSolid)\n  {\n    _lzSize = 0;\n    _winPos = 0;\n    _wrPtr = 0;\n    for (unsigned i = 0; i < kNumReps; i++)\n      _reps[i] = 0;\n    _lastLength = 0;\n    memset(m_LastLevels, 0, kTablesSizesSum);\n    TablesRead = false;\n    PpmEscChar = 2;\n    PpmError = true;\n    InitFilters();\n    // _errorMode = false;\n  }\n\n  /*\n  if (_errorMode)\n    return S_FALSE;\n  */\n\n  if (!_isSolid || !TablesRead)\n  {\n    bool keepDecompressing;\n    RINOK(ReadTables(keepDecompressing))\n    if (!keepDecompressing)\n    {\n      _solidAllowed = true;\n      return S_OK;\n    }\n  }\n\n  for (;;)\n  {\n    bool keepDecompressing;\n    if (_lzMode)\n    {\n      if (!TablesOK)\n        return S_FALSE;\n      RINOK(DecodeLZ(keepDecompressing))\n    }\n    else\n    {\n      RINOK(DecodePPM(1 << 18, keepDecompressing))\n    }\n\n    if (InputEofError())\n      return S_FALSE;\n\n    const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();\n    RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))\n    if (!keepDecompressing)\n      break;\n  }\n\n  _solidAllowed = true;\n\n  RINOK(WriteBuf())\n  const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();\n  RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))\n  if (_writtenFileSize < _unpackSize)\n    return S_FALSE;\n\n  if (_unsupportedFilter)\n    return E_NOTIMPL;\n\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  try\n  {\n    if (!inSize)\n      return E_INVALIDARG;\n\n    if (_isSolid && !_solidAllowed)\n      return S_FALSE;\n    _solidAllowed = false;\n\n    if (!_vmData)\n    {\n      _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);\n      if (!_vmData)\n        return E_OUTOFMEMORY;\n      _vmCode = _vmData + kVmDataSizeMax;\n    }\n    \n    if (!_window)\n    {\n      _window = (Byte *)::MidAlloc(kWindowSize);\n      if (!_window)\n        return E_OUTOFMEMORY;\n    }\n    if (!m_InBitStream.BitDecoder.Create(1 << 20))\n      return E_OUTOFMEMORY;\n    if (!_vm.Create())\n      return E_OUTOFMEMORY;\n\n    \n    m_InBitStream.BitDecoder.SetStream(inStream);\n    m_InBitStream.BitDecoder.Init();\n    _outStream = outStream;\n   \n    // CCoderReleaser coderReleaser(this);\n    _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1;\n    return CodeReal(progress);\n  }\n  catch(const CInBufferException &e)  { /* _errorMode = true; */ return e.ErrorCode; }\n  catch(...) { /* _errorMode = true; */ return S_FALSE; }\n  // CNewException is possible here. But probably CNewException is caused\n  // by error in data stream.\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n{\n  if (size < 1)\n    return E_INVALIDARG;\n  _isSolid = ((data[0] & 1) != 0);\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar3Decoder.h",
    "content": "﻿// Rar3Decoder.h\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n/* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */\n\n#ifndef ZIP7_INC_COMPRESS_RAR3_DECODER_H\n#define ZIP7_INC_COMPRESS_RAR3_DECODER_H\n\n#include \"../../../C/Ppmd7.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"../Common/InBuffer.h\"\n\n#include \"BitmDecoder.h\"\n#include \"HuffmanDecoder.h\"\n#include \"Rar3Vm.h\"\n\nnamespace NCompress {\nnamespace NRar3 {\n\nconst unsigned kNumHuffmanBits = 15;\n\nconst UInt32 kWindowSize = 1 << 22;\nconst UInt32 kWindowMask = kWindowSize - 1;\n\nconst unsigned kNumReps = 4;\nconst unsigned kNumLen2Symbols = 8;\nconst unsigned kLenTableSize = 28;\nconst unsigned kMainTableSize = 256 + 3 + kNumReps + kNumLen2Symbols + kLenTableSize;\nconst unsigned kDistTableSize = 60;\n\nconst unsigned kNumAlignBits = 4;\nconst unsigned kAlignTableSize = (1 << kNumAlignBits) + 1;\n\nconst unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;\n\nclass CBitDecoder\n{\n  UInt32 _value;\n  unsigned _bitPos;\npublic:\n  CInBuffer Stream;\n\n  bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }\n  void SetStream(ISequentialInStream *inStream) { Stream.SetStream(inStream);}\n\n  void Init()\n  {\n    Stream.Init();\n    _bitPos = 0;\n    _value = 0;\n  }\n  \n  bool ExtraBitsWereRead() const\n  {\n    return (Stream.NumExtraBytes > 4 || _bitPos < (Stream.NumExtraBytes << 3));\n  }\n\n  UInt64 GetProcessedSize() const { return Stream.GetProcessedSize() - (_bitPos >> 3); }\n\n  void AlignToByte()\n  {\n    _bitPos &= ~(unsigned)7;\n    _value = _value & ((1 << _bitPos) - 1);\n  }\n  \n  Z7_FORCE_INLINE\n  UInt32 GetValue(unsigned numBits)\n  {\n    if (_bitPos < numBits)\n    {\n      _bitPos += 8;\n      _value = (_value << 8) | Stream.ReadByte();\n      if (_bitPos < numBits)\n      {\n        _bitPos += 8;\n        _value = (_value << 8) | Stream.ReadByte();\n      }\n    }\n    return _value >> (_bitPos - numBits);\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue_InHigh32bits()\n  {\n    return GetValue(kNumHuffmanBits) << (32 - kNumHuffmanBits);\n  }\n\n  \n  Z7_FORCE_INLINE\n  void MovePos(unsigned numBits)\n  {\n    _bitPos -= numBits;\n    _value = _value & ((1 << _bitPos) - 1);\n  }\n  \n  UInt32 ReadBits(unsigned numBits)\n  {\n    const UInt32 res = GetValue(numBits);\n    MovePos(numBits);\n    return res;\n  }\n\n  UInt32 ReadBits_upto8(unsigned numBits)\n  {\n    if (_bitPos < numBits)\n    {\n      _bitPos += 8;\n      _value = (_value << 8) | Stream.ReadByte();\n    }\n    _bitPos -= numBits;\n    const UInt32 res = _value >> _bitPos;\n    _value = _value & ((1 << _bitPos) - 1);\n    return res;\n  }\n\n  Byte ReadByteFromAligned()\n  {\n    if (_bitPos == 0)\n      return Stream.ReadByte();\n    const unsigned bitsPos = _bitPos - 8;\n    const Byte b = (Byte)(_value >> bitsPos);\n    _value = _value & ((1 << bitsPos) - 1);\n    _bitPos = bitsPos;\n    return b;\n  }\n};\n\n\nstruct CByteIn\n{\n  IByteIn IByteIn_obj;\n  CBitDecoder BitDecoder;\n};\n\n\nstruct CFilter: public NVm::CProgram\n{\n  CRecordVector<Byte> GlobalData;\n  UInt32 BlockStart;\n  UInt32 BlockSize;\n  UInt32 ExecCount;\n  \n  CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {}\n};\n\nstruct CTempFilter: public NVm::CProgramInitState\n{\n  UInt32 BlockStart;\n  UInt32 BlockSize;\n  bool NextWindow;\n  \n  UInt32 FilterIndex;\n\n  CTempFilter()\n  {\n    // all filters must contain at least FixedGlobal block\n    AllocateEmptyFixedGlobal();\n  }\n};\n\n\nZ7_CLASS_IMP_NOQIB_2(\n  CDecoder\n  , ICompressCoder\n  , ICompressSetDecoderProperties2\n)\n  bool _isSolid;\n  bool _solidAllowed;\n  // bool _errorMode;\n\n  bool _lzMode;\n  bool _unsupportedFilter;\n\n  CByteIn m_InBitStream;\n  Byte *_window;\n  UInt32 _winPos;\n  UInt32 _wrPtr;\n  UInt64 _lzSize;\n  UInt64 _unpackSize;\n  UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written\n  ISequentialOutStream *_outStream;\n\n  NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, 9> m_MainDecoder;\n  UInt32 kDistStart[kDistTableSize];\n  NHuffman::CDecoder256<kNumHuffmanBits, kDistTableSize, 7> m_DistDecoder;\n  NHuffman::CDecoder256<kNumHuffmanBits, kAlignTableSize, 6> m_AlignDecoder;\n  NHuffman::CDecoder256<kNumHuffmanBits, kLenTableSize, 7> m_LenDecoder;\n\n  UInt32 _reps[kNumReps];\n  UInt32 _lastLength;\n  \n  Byte m_LastLevels[kTablesSizesSum];\n\n  Byte *_vmData;\n  Byte *_vmCode;\n  NVm::CVm _vm;\n  CRecordVector<CFilter *> _filters;\n  CRecordVector<CTempFilter *>  _tempFilters;\n  unsigned _numEmptyTempFilters;\n  UInt32 _lastFilter;\n\n  UInt32 PrevAlignBits;\n  UInt32 PrevAlignCount;\n\n  bool TablesRead;\n  bool TablesOK;\n  bool PpmError;\n\n  int PpmEscChar;\n  CPpmd7 _ppmd;\n  \n  HRESULT WriteDataToStream(const Byte *data, UInt32 size);\n  HRESULT WriteData(const Byte *data, UInt32 size);\n  HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);\n  void ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef);\n  HRESULT WriteBuf();\n\n  void InitFilters();\n  bool AddVmCode(UInt32 firstByte, UInt32 codeSize);\n  bool ReadVmCodeLZ();\n  bool ReadVmCodePPM();\n  \n  UInt32 ReadBits(unsigned numBits);\n\n  HRESULT InitPPM();\n  // int DecodePpmSymbol();\n  HRESULT DecodePPM(Int32 num, bool &keepDecompressing);\n\n  HRESULT ReadTables(bool &keepDecompressing);\n  HRESULT ReadEndOfBlock(bool &keepDecompressing);\n  HRESULT DecodeLZ(bool &keepDecompressing);\n  HRESULT CodeReal(ICompressProgressInfo *progress);\n  \n  bool InputEofError() const { return m_InBitStream.BitDecoder.ExtraBitsWereRead(); }\n  bool InputEofError_Fast() const { return (m_InBitStream.BitDecoder.Stream.NumExtraBytes > 2); }\n\n  void CopyBlock(UInt32 dist, UInt32 len)\n  {\n    _lzSize += len;\n    UInt32 pos = (_winPos - dist - 1) & kWindowMask;\n    Byte *window = _window;\n    UInt32 winPos = _winPos;\n    if (kWindowSize - winPos > len && kWindowSize - pos > len)\n    {\n      const Byte *src = window + pos;\n      Byte *dest = window + winPos;\n      _winPos += len;\n      do\n        *dest++ = *src++;\n      while (--len != 0);\n      return;\n    }\n    do\n    {\n      window[winPos] = window[pos];\n      winPos = (winPos + 1) & kWindowMask;\n      pos = (pos + 1) & kWindowMask;\n    }\n    while (--len != 0);\n    _winPos = winPos;\n  }\n  \n  void PutByte(Byte b)\n  {\n    const UInt32 wp = _winPos;\n    _window[wp] = b;\n    _winPos = (wp + 1) & kWindowMask;\n    _lzSize++;\n  }\n\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar3Vm.cpp",
    "content": "﻿// Rar3Vm.cpp\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n/*\nNote:\n  Due to performance considerations Rar VM may set Flags C incorrectly\n  for some operands (SHL x, 0, ... ).\n  Check implementation of concrete VM command\n  to see if it sets flags right.\n*/\n\n#include \"StdAfx.h\"\n\n#include <stdlib.h>\n\n#include \"../../../C/7zCrc.h\"\n#include \"../../../C/Alloc.h\"\n\n#include \"../../Common/Defs.h\"\n\n#include \"Rar3Vm.h\"\n\nnamespace NCompress {\nnamespace NRar3 {\n\nUInt32 CMemBitDecoder::ReadBits(unsigned numBits)\n{\n  UInt32 res = 0;\n  for (;;)\n  {\n    const unsigned b = _bitPos < _bitSize ? (unsigned)_data[_bitPos >> 3] : 0;\n    const unsigned avail = (unsigned)(8 - (_bitPos & 7));\n    if (numBits <= avail)\n    {\n      _bitPos += numBits;\n      return res | ((b >> (avail - numBits)) & ((1 << numBits) - 1));\n    }\n    numBits -= avail;\n    res |= (UInt32)(b & ((1 << avail) - 1)) << numBits;\n    _bitPos += avail;\n  }\n}\n\nUInt32 CMemBitDecoder::ReadBit() { return ReadBits(1); }\n\nUInt32 CMemBitDecoder::ReadEncodedUInt32()\n{\n  const unsigned v = (unsigned)ReadBits(2);\n  UInt32 res = ReadBits(4u << v);\n  if (v == 1 && res < 16)\n    res = 0xFFFFFF00 | (res << 4) | ReadBits(4);\n  return res;\n}\n\nnamespace NVm {\n\nstatic const UInt32 kStackRegIndex = kNumRegs - 1;\n\n#ifdef Z7_RARVM_VM_ENABLE\n\n#if   defined(Z7_GCC_VERSION)   && (Z7_GCC_VERSION   >= 40400) \\\n   || defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000)\n// enumeration values not explicitly handled in switch\n#pragma GCC diagnostic ignored \"-Wswitch-enum\"\n#endif\n\nstatic const UInt32 FLAG_C = 1;\nstatic const UInt32 FLAG_Z = 2;\nstatic const UInt32 FLAG_S = 0x80000000;\n\nstatic const Byte CF_OP0 = 0;\nstatic const Byte CF_OP1 = 1;\nstatic const Byte CF_OP2 = 2;\nstatic const Byte CF_OPMASK = 3;\nstatic const Byte CF_BYTEMODE = 4;\nstatic const Byte CF_JUMP = 8;\nstatic const Byte CF_PROC = 16;\nstatic const Byte CF_USEFLAGS = 32;\nstatic const Byte CF_CHFLAGS = 64;\n\nstatic const Byte kCmdFlags[]=\n{\n  /* CMD_MOV   */ CF_OP2 | CF_BYTEMODE,\n  /* CMD_CMP   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_ADD   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_SUB   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_JZ    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_JNZ   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_INC   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_DEC   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_JMP   */ CF_OP1 | CF_JUMP,\n  /* CMD_XOR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_AND   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_OR    */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_TEST  */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_JS    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_JNS   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_JB    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_JBE   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_JA    */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_JAE   */ CF_OP1 | CF_JUMP | CF_USEFLAGS,\n  /* CMD_PUSH  */ CF_OP1,\n  /* CMD_POP   */ CF_OP1,\n  /* CMD_CALL  */ CF_OP1 | CF_PROC,\n  /* CMD_RET   */ CF_OP0 | CF_PROC,\n  /* CMD_NOT   */ CF_OP1 | CF_BYTEMODE,\n  /* CMD_SHL   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_SHR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_SAR   */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_NEG   */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS,\n  /* CMD_PUSHA */ CF_OP0,\n  /* CMD_POPA  */ CF_OP0,\n  /* CMD_PUSHF */ CF_OP0 | CF_USEFLAGS,\n  /* CMD_POPF  */ CF_OP0 | CF_CHFLAGS,\n  /* CMD_MOVZX */ CF_OP2,\n  /* CMD_MOVSX */ CF_OP2,\n  /* CMD_XCHG  */ CF_OP2 | CF_BYTEMODE,\n  /* CMD_MUL   */ CF_OP2 | CF_BYTEMODE,\n  /* CMD_DIV   */ CF_OP2 | CF_BYTEMODE,\n  /* CMD_ADC   */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,\n  /* CMD_SBB   */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS ,\n  /* CMD_PRINT */ CF_OP0\n};\n\n#endif\n\n\nCVm::CVm(): Mem(NULL) {}\n\nbool CVm::Create()\n{\n  if (!Mem)\n    Mem = (Byte *)::MyAlloc(kSpaceSize + 4);\n  return (Mem != NULL);\n}\n\nCVm::~CVm()\n{\n  ::MyFree(Mem);\n}\n\n// CVm::Execute can change CProgram object: it clears progarm if VM returns error.\n\nbool CVm::Execute(CProgram *prg, const CProgramInitState *initState,\n    CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData)\n{\n  memcpy(R, initState->InitR, sizeof(initState->InitR));\n  R[kStackRegIndex] = kSpaceSize;\n  R[kNumRegs] = 0;\n  Flags = 0;\n\n  const UInt32 globalSize = MyMin((UInt32)initState->GlobalData.Size(), kGlobalSize);\n  if (globalSize != 0)\n    memcpy(Mem + kGlobalOffset, &initState->GlobalData[0], globalSize);\n  UInt32 staticSize = MyMin((UInt32)prg->StaticData.Size(), kGlobalSize - globalSize);\n  if (staticSize != 0)\n    memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize);\n\n  bool res = true;\n  \n  #ifdef Z7_RARVM_STANDARD_FILTERS\n  if (prg->StandardFilterIndex >= 0)\n    res = ExecuteStandardFilter((unsigned)prg->StandardFilterIndex);\n  else\n  #endif\n  {\n    #ifdef Z7_RARVM_VM_ENABLE\n    res = ExecuteCode(prg);\n    if (!res)\n    {\n      prg->Commands.Clear();\n      prg->Commands.Add(CCommand());\n      prg->Commands.Back().OpCode = CMD_RET;\n    }\n    #else\n    res = false;\n    #endif\n  }\n  \n  UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask;\n  UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask;\n  if (newBlockPos + newBlockSize >= kSpaceSize)\n    newBlockPos = newBlockSize = 0;\n  outBlockRef.Offset = newBlockPos;\n  outBlockRef.Size = newBlockSize;\n\n  outGlobalData.Clear();\n  UInt32 dataSize = GetFixedGlobalValue32(NGlobalOffset::kGlobalMemOutSize);\n  dataSize = MyMin(dataSize, kGlobalSize - kFixedGlobalSize);\n  if (dataSize != 0)\n  {\n    dataSize += kFixedGlobalSize;\n    outGlobalData.ClearAndSetSize(dataSize);\n    memcpy(&outGlobalData[0], Mem + kGlobalOffset, dataSize);\n  }\n\n  return res;\n}\n\n#ifdef Z7_RARVM_VM_ENABLE\n\n#define SET_IP(IP) \\\n  if ((IP) >= numCommands) return true; \\\n  if (--maxOpCount <= 0) return false; \\\n  cmd = commands + (IP);\n\n#define GET_FLAG_S_B(res) (((res) & 0x80) ? FLAG_S : 0)\n#define SET_IP_OP1 { const UInt32 val = GetOperand32(&cmd->Op1); SET_IP(val) }\n#define FLAGS_UPDATE_SZ Flags = res == 0 ? FLAG_Z : res & FLAG_S\n#define FLAGS_UPDATE_SZ_B Flags = (res & 0xFF) == 0 ? FLAG_Z : GET_FLAG_S_B(res)\n\nUInt32 CVm::GetOperand32(const COperand *op) const\n{\n  switch (op->Type)\n  {\n    case OP_TYPE_REG: return R[op->Data];\n    case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]);\n    default: return op->Data;\n  }\n}\n\nvoid CVm::SetOperand32(const COperand *op, UInt32 val)\n{\n  switch (op->Type)\n  {\n    case OP_TYPE_REG: R[op->Data] = val; return;\n    case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return;\n    default: break;\n  }\n}\n\nByte CVm::GetOperand8(const COperand *op) const\n{\n  switch (op->Type)\n  {\n    case OP_TYPE_REG: return (Byte)R[op->Data];\n    case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];\n    default: return (Byte)op->Data;\n  }\n}\n\nvoid CVm::SetOperand8(const COperand *op, Byte val)\n{\n  switch (op->Type)\n  {\n    case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return;\n    case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return;\n    default: break;\n  }\n}\n\nUInt32 CVm::GetOperand(bool byteMode, const COperand *op) const\n{\n  if (byteMode)\n    return GetOperand8(op);\n  return GetOperand32(op);\n}\n\nvoid CVm::SetOperand(bool byteMode, const COperand *op, UInt32 val)\n{\n  if (byteMode)\n    SetOperand8(op, (Byte)(val & 0xFF));\n  else\n    SetOperand32(op, val);\n}\n\nbool CVm::ExecuteCode(const CProgram *prg)\n{\n  Int32 maxOpCount = 25000000;\n  const CCommand *commands = &prg->Commands[0];\n  const CCommand *cmd = commands;\n  const UInt32 numCommands = prg->Commands.Size();\n  if (numCommands == 0)\n    return false;\n\n  for (;;)\n  {\n    switch (cmd->OpCode)\n    {\n      case CMD_MOV:\n        SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2));\n        break;\n      case CMD_MOVB:\n        SetOperand8(&cmd->Op1, GetOperand8(&cmd->Op2));\n        break;\n      case CMD_CMP:\n        {\n          const UInt32 v1 = GetOperand32(&cmd->Op1);\n          const UInt32 res = v1 - GetOperand32(&cmd->Op2);\n          Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);\n        }\n        break;\n      case CMD_CMPB:\n        {\n          const Byte v1 = GetOperand8(&cmd->Op1);\n          const Byte res = (Byte)((v1 - GetOperand8(&cmd->Op2)) & 0xFF);\n          Flags = res == 0 ? FLAG_Z : (res > v1) | GET_FLAG_S_B(res);\n        }\n        break;\n      case CMD_ADD:\n        {\n          const UInt32 v1 = GetOperand32(&cmd->Op1);\n          const UInt32 res = v1 + GetOperand32(&cmd->Op2);\n          SetOperand32(&cmd->Op1, res);\n          Flags = (res < v1) | (res == 0 ? FLAG_Z : (res & FLAG_S));\n        }\n        break;\n      case CMD_ADDB:\n        {\n          const Byte v1 = GetOperand8(&cmd->Op1);\n          const Byte res = (Byte)((v1 + GetOperand8(&cmd->Op2)) & 0xFF);\n          SetOperand8(&cmd->Op1, (Byte)res);\n          Flags = (res < v1) | (res == 0 ? FLAG_Z : GET_FLAG_S_B(res));\n        }\n        break;\n      case CMD_ADC:\n        {\n          const UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);\n          const UInt32 FC = (Flags & FLAG_C);\n          UInt32 res = v1 + GetOperand(cmd->ByteMode, &cmd->Op2) + FC;\n          if (cmd->ByteMode)\n            res &= 0xFF;\n          SetOperand(cmd->ByteMode, &cmd->Op1, res);\n          Flags = (res < v1 || (res == v1 && FC)) | (res == 0 ? FLAG_Z : (res & FLAG_S));\n        }\n        break;\n      case CMD_SUB:\n        {\n          const UInt32 v1 = GetOperand32(&cmd->Op1);\n          const UInt32 res = v1 - GetOperand32(&cmd->Op2);\n          SetOperand32(&cmd->Op1, res);\n          Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);\n        }\n        break;\n      case CMD_SUBB:\n        {\n          const UInt32 v1 = GetOperand8(&cmd->Op1);\n          const UInt32 res = v1 - GetOperand8(&cmd->Op2);\n          SetOperand8(&cmd->Op1, (Byte)res);\n          Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S);\n        }\n        break;\n      case CMD_SBB:\n        {\n          const UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);\n          const UInt32 FC = (Flags & FLAG_C);\n          UInt32 res = v1 - GetOperand(cmd->ByteMode, &cmd->Op2) - FC;\n          // Flags = res == 0 ? FLAG_Z : (res > v1 || res == v1 && FC) | (res & FLAG_S);\n          if (cmd->ByteMode)\n            res &= 0xFF;\n          SetOperand(cmd->ByteMode, &cmd->Op1, res);\n          Flags = (res > v1 || (res == v1 && FC)) | (res == 0 ? FLAG_Z : (res & FLAG_S));\n        }\n        break;\n      case CMD_INC:\n        {\n          const UInt32 res = GetOperand32(&cmd->Op1) + 1;\n          SetOperand32(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ;\n        }\n        break;\n      case CMD_INCB:\n        {\n          const Byte res = (Byte)(GetOperand8(&cmd->Op1) + 1);\n          SetOperand8(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ_B;\n        }\n        break;\n      case CMD_DEC:\n        {\n          const UInt32 res = GetOperand32(&cmd->Op1) - 1;\n          SetOperand32(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ;\n        }\n        break;\n      case CMD_DECB:\n        {\n          const Byte res = (Byte)(GetOperand8(&cmd->Op1) - 1);\n          SetOperand8(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ_B;\n        }\n        break;\n      case CMD_XOR:\n        {\n          const UInt32 res = GetOperand32(&cmd->Op1) ^ GetOperand32(&cmd->Op2);\n          SetOperand32(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ;\n        }\n        break;\n      case CMD_XORB:\n        {\n          const Byte res = (Byte)(GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2));\n          SetOperand8(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ_B;\n        }\n        break;\n      case CMD_AND:\n        {\n          const UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);\n          SetOperand32(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ;\n        }\n        break;\n      case CMD_ANDB:\n        {\n          const Byte res = (Byte)(GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2));\n          SetOperand8(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ_B;\n        }\n        break;\n      case CMD_OR:\n        {\n          const UInt32 res = GetOperand32(&cmd->Op1) | GetOperand32(&cmd->Op2);\n          SetOperand32(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ;\n        }\n        break;\n      case CMD_ORB:\n        {\n          const Byte res = (Byte)(GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2));\n          SetOperand8(&cmd->Op1, res);\n          FLAGS_UPDATE_SZ_B;\n        }\n        break;\n      case CMD_TEST:\n        {\n          const UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2);\n          FLAGS_UPDATE_SZ;\n        }\n        break;\n      case CMD_TESTB:\n        {\n          const Byte res = (Byte)(GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2));\n          FLAGS_UPDATE_SZ_B;\n        }\n        break;\n      case CMD_NOT:\n        SetOperand(cmd->ByteMode, &cmd->Op1, ~GetOperand(cmd->ByteMode, &cmd->Op1));\n        break;\n      case CMD_NEG:\n        {\n          const UInt32 res = 0 - GetOperand32(&cmd->Op1);\n          SetOperand32(&cmd->Op1, res);\n          Flags = res == 0 ? FLAG_Z : FLAG_C | (res & FLAG_S);\n        }\n        break;\n      case CMD_NEGB:\n        {\n          const Byte res = (Byte)(0 - GetOperand8(&cmd->Op1));\n          SetOperand8(&cmd->Op1, res);\n          Flags = res == 0 ? FLAG_Z : FLAG_C | GET_FLAG_S_B(res);\n        }\n        break;\n\n      case CMD_SHL:\n        {\n          const UInt32 v1 = GetOperand32(&cmd->Op1);\n          const int v2 = (int)GetOperand32(&cmd->Op2);\n          const UInt32 res = v1 << v2;\n          SetOperand32(&cmd->Op1, res);\n          Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 << (v2 - 1)) & 0x80000000 ? FLAG_C : 0);\n        }\n        break;\n      case CMD_SHLB:\n        {\n          const Byte v1 = GetOperand8(&cmd->Op1);\n          const int v2 = (int)GetOperand8(&cmd->Op2);\n          const Byte res = (Byte)(v1 << v2);\n          SetOperand8(&cmd->Op1, res);\n          Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 << (v2 - 1)) & 0x80 ? FLAG_C : 0);\n        }\n        break;\n      case CMD_SHR:\n        {\n          const UInt32 v1 = GetOperand32(&cmd->Op1);\n          const int v2 = (int)GetOperand32(&cmd->Op2);\n          const UInt32 res = v1 >> v2;\n          SetOperand32(&cmd->Op1, res);\n          Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);\n        }\n        break;\n      case CMD_SHRB:\n        {\n          const Byte v1 = GetOperand8(&cmd->Op1);\n          const int v2 = (int)GetOperand8(&cmd->Op2);\n          const Byte res = (Byte)(v1 >> v2);\n          SetOperand8(&cmd->Op1, res);\n          Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);\n        }\n        break;\n      case CMD_SAR:\n        {\n          const UInt32 v1 = GetOperand32(&cmd->Op1);\n          const int v2 = (int)GetOperand32(&cmd->Op2);\n          const UInt32 res = UInt32(((Int32)v1) >> v2);\n          SetOperand32(&cmd->Op1, res);\n          Flags= (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C);\n        }\n        break;\n      case CMD_SARB:\n        {\n          const Byte v1 = GetOperand8(&cmd->Op1);\n          const int v2 = (int)GetOperand8(&cmd->Op2);\n          const Byte res = (Byte)(((signed char)v1) >> v2);\n          SetOperand8(&cmd->Op1, res);\n          Flags= (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C);\n        }\n        break;\n\n      case CMD_JMP:\n        SET_IP_OP1\n        continue;\n      case CMD_JZ:\n        if ((Flags & FLAG_Z) != 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      case CMD_JNZ:\n        if ((Flags & FLAG_Z) == 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      case CMD_JS:\n        if ((Flags & FLAG_S) != 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      case CMD_JNS:\n        if ((Flags & FLAG_S) == 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      case CMD_JB:\n        if ((Flags & FLAG_C) != 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      case CMD_JBE:\n        if ((Flags & (FLAG_C | FLAG_Z)) != 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      case CMD_JA:\n        if ((Flags & (FLAG_C | FLAG_Z)) == 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      case CMD_JAE:\n        if ((Flags & FLAG_C) == 0)\n        {\n          SET_IP_OP1\n          continue;\n        }\n        break;\n      \n      case CMD_PUSH:\n        R[kStackRegIndex] -= 4;\n        SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], GetOperand32(&cmd->Op1));\n        break;\n      case CMD_POP:\n        SetOperand32(&cmd->Op1, GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]));\n        R[kStackRegIndex] += 4;\n        break;\n      case CMD_CALL:\n        R[kStackRegIndex] -= 4;\n        SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], (UInt32)(cmd - commands + 1));\n        SET_IP_OP1\n        continue;\n\n      case CMD_PUSHA:\n        {\n          for (UInt32 i = 0, SP = R[kStackRegIndex] - 4; i < kNumRegs; i++, SP -= 4)\n            SetValue32(&Mem[SP & kSpaceMask], R[i]);\n          R[kStackRegIndex] -= kNumRegs * 4;\n        }\n        break;\n      case CMD_POPA:\n        {\n          for (UInt32 i = 0, SP = R[kStackRegIndex]; i < kNumRegs; i++, SP += 4)\n            R[kStackRegIndex - i] = GetValue32(&Mem[SP & kSpaceMask]);\n        }\n        break;\n      case CMD_PUSHF:\n        R[kStackRegIndex] -= 4;\n        SetValue32(&Mem[R[kStackRegIndex]&kSpaceMask], Flags);\n        break;\n      case CMD_POPF:\n        Flags = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);\n        R[kStackRegIndex] += 4;\n        break;\n      \n      case CMD_MOVZX:\n        SetOperand32(&cmd->Op1, GetOperand8(&cmd->Op2));\n        break;\n      case CMD_MOVSX:\n        SetOperand32(&cmd->Op1, (UInt32)(Int32)(signed char)GetOperand8(&cmd->Op2));\n        break;\n      case CMD_XCHG:\n        {\n          const UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1);\n          SetOperand(cmd->ByteMode, &cmd->Op1, GetOperand(cmd->ByteMode, &cmd->Op2));\n          SetOperand(cmd->ByteMode, &cmd->Op2, v1);\n        }\n        break;\n      case CMD_MUL:\n        {\n          const UInt32 res = GetOperand32(&cmd->Op1) * GetOperand32(&cmd->Op2);\n          SetOperand32(&cmd->Op1, res);\n        }\n        break;\n      case CMD_MULB:\n        {\n          const Byte res = (Byte)(GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2));\n          SetOperand8(&cmd->Op1, res);\n        }\n        break;\n      case CMD_DIV:\n        {\n          const UInt32 divider = GetOperand(cmd->ByteMode, &cmd->Op2);\n          if (divider != 0)\n          {\n            const UInt32 res = GetOperand(cmd->ByteMode, &cmd->Op1) / divider;\n            SetOperand(cmd->ByteMode, &cmd->Op1, res);\n          }\n        }\n        break;\n      \n      case CMD_RET:\n        {\n          if (R[kStackRegIndex] >= kSpaceSize)\n            return true;\n          const UInt32 ip = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]);\n          SET_IP(ip)\n          R[kStackRegIndex] += 4;\n          continue;\n        }\n      case CMD_PRINT:\n        break;\n    }\n    cmd++;\n    --maxOpCount;\n  }\n}\n\n//////////////////////////////////////////////////////\n// Read program\n\nstatic void DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode)\n{\n  if (inp.ReadBit())\n  {\n    op.Type = OP_TYPE_REG;\n    op.Data = inp.ReadBits(kNumRegBits);\n  }\n  else if (inp.ReadBit() == 0)\n  {\n    op.Type = OP_TYPE_INT;\n    if (byteMode)\n      op.Data = inp.ReadBits(8);\n    else\n      op.Data = inp.ReadEncodedUInt32();\n  }\n  else\n  {\n    op.Type = OP_TYPE_REGMEM;\n    if (inp.ReadBit() == 0)\n    {\n      op.Data = inp.ReadBits(kNumRegBits);\n      op.Base = 0;\n    }\n    else\n    {\n      if (inp.ReadBit() == 0)\n        op.Data = inp.ReadBits(kNumRegBits);\n      else\n        op.Data = kNumRegs;\n      op.Base = inp.ReadEncodedUInt32();\n    }\n  }\n}\n\nvoid CProgram::ReadProgram(const Byte *code, UInt32 codeSize)\n{\n  CMemBitDecoder inp;\n  inp.Init(code, codeSize);\n\n  StaticData.Clear();\n  \n  if (inp.ReadBit())\n  {\n    const UInt32 dataSize = inp.ReadEncodedUInt32() + 1;\n    for (UInt32 i = 0; inp.Avail() && i < dataSize; i++)\n      StaticData.Add((Byte)inp.ReadBits(8));\n  }\n  \n  while (inp.Avail())\n  {\n    Commands.Add(CCommand());\n    CCommand *cmd = &Commands.Back();\n    \n    unsigned opCode;\n    if (inp.ReadBit() == 0)\n      opCode = inp.ReadBits(3);\n    else\n      opCode = 8 + inp.ReadBits(5);\n    cmd->OpCode = (ECommand)opCode;\n    const unsigned cmdFlags = kCmdFlags[opCode];\n    if (cmdFlags & CF_BYTEMODE)\n      cmd->ByteMode = (inp.ReadBit()) ? true : false;\n    else\n      cmd->ByteMode = 0;\n    \n    const unsigned opNum = (cmdFlags & CF_OPMASK);\n    \n    if (opNum)\n    {\n      DecodeArg(inp, cmd->Op1, cmd->ByteMode);\n      if (opNum == 2)\n        DecodeArg(inp, cmd->Op2, cmd->ByteMode);\n      else\n      {\n        if (cmd->Op1.Type == OP_TYPE_INT && (cmdFlags & (CF_JUMP | CF_PROC)))\n        {\n          Int32 dist = (Int32)cmd->Op1.Data;\n          if (dist >= 256)\n            dist -= 256;\n          else\n          {\n            if (dist >= 136)\n              dist -= 264;\n            else if (dist >= 16)\n              dist -= 8;\n            else if (dist >= 8)\n              dist -= 16;\n            dist += Commands.Size() - 1;\n          }\n          cmd->Op1.Data = (UInt32)dist;\n        }\n      }\n    }\n\n    if (cmd->ByteMode)\n    {\n      switch (cmd->OpCode)\n      {\n        case CMD_MOV: cmd->OpCode = CMD_MOVB; break;\n        case CMD_CMP: cmd->OpCode = CMD_CMPB; break;\n        case CMD_ADD: cmd->OpCode = CMD_ADDB; break;\n        case CMD_SUB: cmd->OpCode = CMD_SUBB; break;\n        case CMD_INC: cmd->OpCode = CMD_INCB; break;\n        case CMD_DEC: cmd->OpCode = CMD_DECB; break;\n        case CMD_XOR: cmd->OpCode = CMD_XORB; break;\n        case CMD_AND: cmd->OpCode = CMD_ANDB; break;\n        case CMD_OR: cmd->OpCode = CMD_ORB; break;\n        case CMD_TEST: cmd->OpCode = CMD_TESTB; break;\n        case CMD_NEG: cmd->OpCode = CMD_NEGB; break;\n        case CMD_SHL: cmd->OpCode = CMD_SHLB; break;\n        case CMD_SHR: cmd->OpCode = CMD_SHRB; break;\n        case CMD_SAR: cmd->OpCode = CMD_SARB; break;\n        case CMD_MUL: cmd->OpCode = CMD_MULB; break;\n        default: break;\n      }\n    }\n  }\n}\n\n#endif\n\n\n#ifdef Z7_RARVM_STANDARD_FILTERS\n\nenum EStandardFilter\n{\n  SF_E8,\n  SF_E8E9,\n  SF_ITANIUM,\n  SF_RGB,\n  SF_AUDIO,\n  SF_DELTA\n  // SF_UPCASE\n};\n\nstatic const struct CStandardFilterSignature\n{\n  UInt32 Length;\n  UInt32 CRC;\n  EStandardFilter Type;\n}\nkStdFilters[]=\n{\n  {  53, 0xad576887, SF_E8 },\n  {  57, 0x3cd7e57e, SF_E8E9 },\n  { 120, 0x3769893f, SF_ITANIUM },\n  {  29, 0x0e06077d, SF_DELTA },\n  { 149, 0x1c2c5dc8, SF_RGB },\n  { 216, 0xbc85e701, SF_AUDIO }\n  // {  40, 0x46b9c560, SF_UPCASE }\n};\n\nstatic int FindStandardFilter(const Byte *code, UInt32 codeSize)\n{\n  // return -1; // for debug VM execution\n  const UInt32 crc = CrcCalc(code, codeSize);\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(kStdFilters); i++)\n  {\n    const CStandardFilterSignature &sfs = kStdFilters[i];\n    if (sfs.CRC == crc && sfs.Length == codeSize)\n      return (int)i;\n  }\n  return -1;\n}\n\n#endif\n\n\nbool CProgram::PrepareProgram(const Byte *code, UInt32 codeSize)\n{\n  IsSupported = false;\n\n  #ifdef Z7_RARVM_VM_ENABLE\n  Commands.Clear();\n  #endif\n  \n  #ifdef Z7_RARVM_STANDARD_FILTERS\n  StandardFilterIndex = -1;\n  #endif\n\n  bool isOK = false;\n\n  Byte xorSum = 0;\n  for (UInt32 i = 0; i < codeSize; i++)\n    xorSum ^= code[i];\n\n  if (xorSum == 0 && codeSize != 0)\n  {\n    IsSupported = true;\n    isOK = true;\n    #ifdef Z7_RARVM_STANDARD_FILTERS\n    StandardFilterIndex = FindStandardFilter(code, codeSize);\n    if (StandardFilterIndex >= 0)\n      return true;\n    #endif\n  \n    #ifdef Z7_RARVM_VM_ENABLE\n    ReadProgram(code + 1, codeSize - 1);\n    #else\n    IsSupported = false;\n    #endif\n  }\n  \n  #ifdef Z7_RARVM_VM_ENABLE\n  Commands.Add(CCommand());\n  Commands.Back().OpCode = CMD_RET;\n  #endif\n  \n  return isOK;\n}\n\nvoid CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize)\n{\n  if (pos < kSpaceSize && data != Mem + pos)\n    memmove(Mem + pos, data, MyMin(dataSize, kSpaceSize - pos));\n}\n\n#ifdef Z7_RARVM_STANDARD_FILTERS\n\nstatic void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)\n{\n  if (dataSize <= 4)\n    return;\n  dataSize -= 4;\n  const UInt32 kFileSize = 0x1000000;\n  const Byte cmpMask = (Byte)(e9 ? 0xFE : 0xFF);\n  for (UInt32 curPos = 0; curPos < dataSize;)\n  {\n    curPos++;\n    if (((*data++) & cmpMask) == 0xE8)\n    {\n      UInt32 offset = curPos + fileOffset;\n      UInt32 addr = GetValue32(data);\n      if (addr < kFileSize)\n        SetValue32(data, addr - offset);\n      else if ((addr & 0x80000000) != 0 && ((addr + offset) & 0x80000000) == 0)\n        SetValue32(data, addr + kFileSize);\n      data += 4;\n      curPos += 4;\n    }\n  }\n}\n\n\nstatic void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)\n{\n  if (dataSize <= 21)\n    return;\n  fileOffset >>= 4;\n  dataSize -= 21;\n  dataSize += 15;\n  dataSize >>= 4;\n  dataSize += fileOffset;\n  do\n  {\n    unsigned m = ((UInt32)0x334B0000 >> (data[0] & 0x1E)) & 3;\n    if (m)\n    {\n      m++;\n      do\n      {\n        Byte *p = data + ((size_t)m * 5 - 8);\n        if (((p[3] >> m) & 15) == 5)\n        {\n          const UInt32 kMask = 0xFFFFF;\n          // UInt32 raw = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);\n          UInt32 raw = GetUi32(p);\n          UInt32 v = raw >> m;\n          v -= fileOffset;\n          v &= kMask;\n          raw &= ~(kMask << m);\n          raw |= (v << m);\n          // p[0] = (Byte)raw; p[1] = (Byte)(raw >> 8); p[2] = (Byte)(raw >> 16);\n          SetUi32(p, raw)\n        }\n      }\n      while (++m <= 4);\n    }\n    data += 16;\n  }\n  while (++fileOffset != dataSize);\n}\n\n\nstatic void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels)\n{\n  UInt32 srcPos = 0;\n  const UInt32 border = dataSize * 2;\n  for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)\n  {\n    Byte prevByte = 0;\n    for (UInt32 destPos = dataSize + curChannel; destPos < border; destPos += numChannels)\n      data[destPos] = (prevByte = (Byte)(prevByte - data[srcPos++]));\n  }\n}\n\nstatic void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR)\n{\n  Byte *destData = srcData + dataSize;\n  const UInt32 kNumChannels = 3;\n  \n  for (UInt32 curChannel = 0; curChannel < kNumChannels; curChannel++)\n  {\n    Byte prevByte = 0;\n    \n    for (UInt32 i = curChannel; i < dataSize; i += kNumChannels)\n    {\n      unsigned predicted;\n      if (i < width)\n        predicted = prevByte;\n      else\n      {\n        const unsigned upperLeftByte = destData[i - width];\n        const unsigned upperByte = destData[i - width + 3];\n        predicted = prevByte + upperByte - upperLeftByte;\n        const int pa = abs((int)(predicted - prevByte));\n        const int pb = abs((int)(predicted - upperByte));\n        const int pc = abs((int)(predicted - upperLeftByte));\n        if (pa <= pb && pa <= pc)\n          predicted = prevByte;\n        else\n          if (pb <= pc)\n            predicted = upperByte;\n          else\n            predicted = upperLeftByte;\n      }\n      destData[i] = prevByte = (Byte)(predicted - *(srcData++));\n    }\n  }\n  if (dataSize < 3)\n    return;\n  const UInt32 border = dataSize - 2;\n  for (UInt32 i = posR; i < border; i += 3)\n  {\n    const Byte g = destData[i + 1];\n    destData[i    ] = (Byte)(destData[i    ] + g);\n    destData[i + 2] = (Byte)(destData[i + 2] + g);\n  }\n}\n\n#define my_abs(x) (unsigned)abs(x)\n\nstatic void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels)\n{\n  Byte *destData = srcData + dataSize;\n  for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++)\n  {\n    UInt32 prevByte = 0, prevDelta = 0, dif[7];\n    Int32 D1 = 0, D2 = 0, D3;\n    Int32 K1 = 0, K2 = 0, K3 = 0;\n    memset(dif, 0, sizeof(dif));\n    \n    for (UInt32 i = curChannel, byteCount = 0; i < dataSize; i += numChannels, byteCount++)\n    {\n      D3 = D2;\n      D2 = (Int32)prevDelta - D1;\n      D1 = (Int32)prevDelta;\n      \n      UInt32 predicted = (UInt32)((Int32)(8 * prevByte) + K1 * D1 + K2 * D2 + K3 * D3);\n      predicted = (predicted >> 3) & 0xFF;\n      \n      const UInt32 curByte = *(srcData++);\n      \n      predicted -= curByte;\n      destData[i] = (Byte)predicted;\n      prevDelta = (UInt32)(Int32)(signed char)(predicted - prevByte);\n      prevByte = predicted;\n      \n      const Int32 D = ((Int32)(signed char)curByte) << 3;\n      \n      dif[0] += my_abs(D);\n      dif[1] += my_abs(D - D1);\n      dif[2] += my_abs(D + D1);\n      dif[3] += my_abs(D - D2);\n      dif[4] += my_abs(D + D2);\n      dif[5] += my_abs(D - D3);\n      dif[6] += my_abs(D + D3);\n      \n      if ((byteCount & 0x1F) == 0)\n      {\n        UInt32 minDif = dif[0], numMinDif = 0;\n        dif[0] = 0;\n        for (unsigned j = 1; j < Z7_ARRAY_SIZE(dif); j++)\n        {\n          if (dif[j] < minDif)\n          {\n            minDif = dif[j];\n            numMinDif = j;\n          }\n          dif[j] = 0;\n        }\n        switch (numMinDif)\n        {\n          case 1: if (K1 >= -16) K1--; break;\n          case 2: if (K1 <   16) K1++; break;\n          case 3: if (K2 >= -16) K2--; break;\n          case 4: if (K2 <   16) K2++; break;\n          case 5: if (K3 >= -16) K3--; break;\n          case 6: if (K3 <   16) K3++; break;\n        }\n      }\n    }\n  }\n}\n\n/*\nstatic UInt32 UpCaseDecode(Byte *data, UInt32 dataSize)\n{\n  UInt32 srcPos = 0, destPos = dataSize;\n  while (srcPos < dataSize)\n  {\n    Byte curByte = data[srcPos++];\n    if (curByte == 2 && (curByte = data[srcPos++]) != 2)\n      curByte -= 32;\n    data[destPos++] = curByte;\n  }\n  return destPos - dataSize;\n}\n*/\n\nbool CVm::ExecuteStandardFilter(unsigned filterIndex)\n{\n  const UInt32 dataSize = R[4];\n  if (dataSize >= kGlobalOffset)\n    return false;\n  EStandardFilter filterType = kStdFilters[filterIndex].Type;\n\n  switch (filterType)\n  {\n    case SF_E8:\n    case SF_E8E9:\n      E8E9Decode(Mem, dataSize, R[6], (filterType == SF_E8E9));\n      break;\n    \n    case SF_ITANIUM:\n      ItaniumDecode(Mem, dataSize, R[6]);\n      break;\n    \n    case SF_DELTA:\n    {\n      if (dataSize >= kGlobalOffset / 2)\n        return false;\n      const UInt32 numChannels = R[0];\n      if (numChannels == 0 || numChannels > 1024) // unrar 5.5.5\n        return false;\n      SetBlockPos(dataSize);\n      DeltaDecode(Mem, dataSize, numChannels);\n      break;\n    }\n    \n    case SF_RGB:\n    {\n      if (dataSize >= kGlobalOffset / 2 || dataSize < 3) // unrar 5.5.5\n        return false;\n      const UInt32 width = R[0];\n      const UInt32 posR = R[1];\n      if (width < 3 || width - 3 > dataSize || posR > 2) // unrar 5.5.5\n        return false;\n      SetBlockPos(dataSize);\n      RgbDecode(Mem, dataSize, width, posR);\n      break;\n    }\n    \n    case SF_AUDIO:\n    {\n      if (dataSize >= kGlobalOffset / 2)\n        return false;\n      const UInt32 numChannels = R[0];\n      if (numChannels == 0 || numChannels > 128) // unrar 5.5.5\n        return false;\n      SetBlockPos(dataSize);\n      AudioDecode(Mem, dataSize, numChannels);\n      break;\n    }\n    \n    /*\n    case SF_UPCASE:\n      if (dataSize >= kGlobalOffset / 2)\n        return false;\n      UInt32 destSize = UpCaseDecode(Mem, dataSize);\n      SetBlockSize(destSize);\n      SetBlockPos(dataSize);\n      break;\n    */\n  }\n  return true;\n}\n\n#endif\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar3Vm.h",
    "content": "﻿// Rar3Vm.h\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n#ifndef ZIP7_INC_COMPRESS_RAR3_VM_H\n#define ZIP7_INC_COMPRESS_RAR3_VM_H\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../../Common/MyVector.h\"\n\n#define Z7_RARVM_STANDARD_FILTERS\n// #define Z7_RARVM_VM_ENABLE\n\nnamespace NCompress {\nnamespace NRar3 {\n\nclass CMemBitDecoder\n{\n  const Byte *_data;\n  UInt32 _bitSize;\n  UInt32 _bitPos;\npublic:\n  void Init(const Byte *data, UInt32 byteSize)\n  {\n    _data = data;\n    _bitSize = (byteSize << 3);\n    _bitPos = 0;\n  }\n  UInt32 ReadBits(unsigned numBits);\n  UInt32 ReadBit();\n  bool Avail() const { return (_bitPos < _bitSize); }\n\n  UInt32 ReadEncodedUInt32();\n};\n\nnamespace NVm {\n\ninline UInt32 GetValue32(const void *addr) { return GetUi32(addr); }\ninline void SetValue32(void *addr, UInt32 value) { SetUi32(addr, value) }\n\nconst unsigned kNumRegBits = 3;\nconst UInt32 kNumRegs = 1 << kNumRegBits;\nconst UInt32 kNumGpRegs = kNumRegs - 1;\n\nconst UInt32 kSpaceSize = 0x40000;\nconst UInt32 kSpaceMask = kSpaceSize - 1;\nconst UInt32 kGlobalOffset = 0x3C000;\nconst UInt32 kGlobalSize = 0x2000;\nconst UInt32 kFixedGlobalSize = 64;\n\nnamespace NGlobalOffset\n{\n  const UInt32 kBlockSize = 0x1C;\n  const UInt32 kBlockPos  = 0x20;\n  const UInt32 kExecCount = 0x2C;\n  const UInt32 kGlobalMemOutSize = 0x30;\n}\n\n\n#ifdef Z7_RARVM_VM_ENABLE\n\nenum ECommand\n{\n  CMD_MOV,  CMD_CMP,  CMD_ADD,  CMD_SUB,  CMD_JZ,   CMD_JNZ,  CMD_INC,  CMD_DEC,\n  CMD_JMP,  CMD_XOR,  CMD_AND,  CMD_OR,   CMD_TEST, CMD_JS,   CMD_JNS,  CMD_JB,\n  CMD_JBE,  CMD_JA,   CMD_JAE,  CMD_PUSH, CMD_POP,  CMD_CALL, CMD_RET,  CMD_NOT,\n  CMD_SHL,  CMD_SHR,  CMD_SAR,  CMD_NEG,  CMD_PUSHA,CMD_POPA, CMD_PUSHF,CMD_POPF,\n  CMD_MOVZX,CMD_MOVSX,CMD_XCHG, CMD_MUL,  CMD_DIV,  CMD_ADC,  CMD_SBB,  CMD_PRINT,\n\n  CMD_MOVB, CMD_CMPB, CMD_ADDB, CMD_SUBB, CMD_INCB, CMD_DECB,\n  CMD_XORB, CMD_ANDB, CMD_ORB,  CMD_TESTB,CMD_NEGB,\n  CMD_SHLB, CMD_SHRB, CMD_SARB, CMD_MULB\n};\n\nenum EOpType {OP_TYPE_REG, OP_TYPE_INT, OP_TYPE_REGMEM, OP_TYPE_NONE};\n\n// Addr in COperand object can link (point) to CVm object!!!\n\nstruct COperand\n{\n  EOpType Type;\n  UInt32 Data;\n  UInt32 Base;\n  COperand(): Type(OP_TYPE_NONE), Data(0), Base(0) {}\n};\n\nstruct CCommand\n{\n  ECommand OpCode;\n  bool ByteMode;\n  COperand Op1, Op2;\n};\n\n#endif\n\n\nstruct CBlockRef\n{\n  UInt32 Offset;\n  UInt32 Size;\n};\n\n\nclass CProgram\n{\n  #ifdef Z7_RARVM_VM_ENABLE\n  void ReadProgram(const Byte *code, UInt32 codeSize);\npublic:\n  CRecordVector<CCommand> Commands;\n  #endif\n  \npublic:\n  #ifdef Z7_RARVM_STANDARD_FILTERS\n  int StandardFilterIndex;\n  #endif\n  \n  bool IsSupported;\n  CRecordVector<Byte> StaticData;\n\n  bool PrepareProgram(const Byte *code, UInt32 codeSize);\n};\n\n\nstruct CProgramInitState\n{\n  UInt32 InitR[kNumGpRegs];\n  CRecordVector<Byte> GlobalData;\n\n  void AllocateEmptyFixedGlobal()\n  {\n    GlobalData.ClearAndSetSize(NVm::kFixedGlobalSize);\n    memset(&GlobalData[0], 0, NVm::kFixedGlobalSize);\n  }\n};\n\n\nclass CVm\n{\n  static UInt32 GetValue(bool byteMode, const void *addr)\n  {\n    if (byteMode)\n      return(*(const Byte *)addr);\n    else\n      return GetUi32(addr);\n  }\n\n  static void SetValue(bool byteMode, void *addr, UInt32 value)\n  {\n    if (byteMode)\n      *(Byte *)addr = (Byte)value;\n    else\n      SetUi32(addr, value)\n  }\n\n  UInt32 GetFixedGlobalValue32(UInt32 globalOffset) { return GetValue(false, &Mem[kGlobalOffset + globalOffset]); }\n\n  void SetBlockSize(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockSize], v); }\n  void SetBlockPos(UInt32 v) { SetValue(&Mem[kGlobalOffset + NGlobalOffset::kBlockPos], v); }\npublic:\n  static void SetValue(void *addr, UInt32 value) { SetValue(false, addr, value); }\n\nprivate:\n\n  #ifdef Z7_RARVM_VM_ENABLE\n  UInt32 GetOperand32(const COperand *op) const;\n  void SetOperand32(const COperand *op, UInt32 val);\n  Byte GetOperand8(const COperand *op) const;\n  void SetOperand8(const COperand *op, Byte val);\n  UInt32 GetOperand(bool byteMode, const COperand *op) const;\n  void SetOperand(bool byteMode, const COperand *op, UInt32 val);\n  bool ExecuteCode(const CProgram *prg);\n  #endif\n  \n  #ifdef Z7_RARVM_STANDARD_FILTERS\n  bool ExecuteStandardFilter(unsigned filterIndex);\n  #endif\n  \n  Byte *Mem;\n  UInt32 R[kNumRegs + 1]; // R[kNumRegs] = 0 always (speed optimization)\n  UInt32 Flags;\n\npublic:\n  CVm();\n  ~CVm();\n  bool Create();\n  void SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize);\n  bool Execute(CProgram *prg, const CProgramInitState *initState,\n      CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData);\n  const Byte *GetDataPointer(UInt32 offset) const { return Mem + offset; }\n};\n\n#endif\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar5Decoder.cpp",
    "content": "﻿// Rar5Decoder.cpp\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n#include \"StdAfx.h\"\n\n#define DICT_SIZE_MAX ((UInt64)1 << DICT_SIZE_BITS_MAX)\n\n// #include <emmintrin.h> // SSE2\n// #endif\n\n#include \"../../../C/CpuArch.h\"\n#if 0\n#include \"../../../C/Bra.h\"\n#endif\n\n#if defined(MY_CPU_ARM64)\n#include <arm_neon.h>\n#endif\n\n// #define Z7_RAR5_SHOW_STAT\n// #include <stdio.h>\n#ifdef Z7_RAR5_SHOW_STAT\n#include <stdio.h>\n#endif\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"Rar5Decoder.h\"\n\n/*\nNote: original-unrar claims that encoder has limitation for Distance:\n  (Distance <= MaxWinSize - MAX_INC_LZ_MATCH)\n  MAX_INC_LZ_MATCH = 0x1001 + 3;\n*/\n\n#define LZ_ERROR_TYPE_NO      0\n#define LZ_ERROR_TYPE_HEADER  1\n// #define LZ_ERROR_TYPE_SYM     1\n#define LZ_ERROR_TYPE_DIST    2\n\nstatic\nvoid My_ZeroMemory(void *p, size_t size)\n{\n  #if defined(MY_CPU_AMD64) && !defined(_M_ARM64EC) \\\n    && defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL <= 1400)\n      // __stosq((UInt64 *)(void *)win, 0, size / 8);\n      /*\n      printf(\"\\n__stosb \\n\");\n      #define STEP_BIG (1 << 28)\n      for (size_t i = 0; i < ((UInt64)1 << 50); i += STEP_BIG)\n      {\n        printf(\"\\n__stosb end %p\\n\", (void *)i);\n        __stosb((Byte *)p + i, 0, STEP_BIG);\n      }\n      */\n      // __stosb((Byte *)p, 0, 0);\n      __stosb((Byte *)p, 0, size);\n  #else\n    // SecureZeroMemory (win, STEP);\n    // ZeroMemory(win, STEP);\n    // memset(win, 0, STEP);\n    memset(p, 0, size);\n  #endif\n}\n\n\n\n#ifdef MY_CPU_LE_UNALIGN\n  #define Z7_RAR5_DEC_USE_UNALIGNED_COPY\n#endif\n\n#ifdef Z7_RAR5_DEC_USE_UNALIGNED_COPY\n\n  #define COPY_CHUNK_SIZE 16\n\n    #define COPY_CHUNK_4_2(dest, src) \\\n    { \\\n      ((UInt32 *)(void *)dest)[0] = ((const UInt32 *)(const void *)src)[0]; \\\n      ((UInt32 *)(void *)dest)[1] = ((const UInt32 *)(const void *)src)[1]; \\\n      src  += 4 * 2; \\\n      dest += 4 * 2; \\\n    }\n\n  /* sse2 doesn't help here in GCC and CLANG.\n     so we disabled sse2 here */\n#if 0\n  #if defined(MY_CPU_AMD64)\n    #define Z7_RAR5_DEC_USE_SSE2\n  #elif defined(MY_CPU_X86)\n    #if defined(_MSC_VER) && _MSC_VER >= 1300 && defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \\\n      || defined(__SSE2__) \\\n      // || 1 == 1  // for debug only\n      #define Z7_RAR5_DEC_USE_SSE2\n    #endif\n  #endif\n#endif\n\n  #if defined(MY_CPU_ARM64)\n\n    #define COPY_OFFSET_MIN  16\n    #define COPY_CHUNK1(dest, src) \\\n    { \\\n      vst1q_u8((uint8_t *)(void *)dest, \\\n      vld1q_u8((const uint8_t *)(const void *)src)); \\\n      src += 16; \\\n      dest += 16; \\\n    }\n    \n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK1(dest, src) \\\n      if (dest >= lim) break; \\\n      COPY_CHUNK1(dest, src) \\\n    }\n\n  #elif defined(Z7_RAR5_DEC_USE_SSE2)\n    #include <emmintrin.h> // sse2\n    #define COPY_OFFSET_MIN  16\n\n    #define COPY_CHUNK1(dest, src) \\\n    { \\\n      _mm_storeu_si128((__m128i *)(void *)dest, \\\n      _mm_loadu_si128((const __m128i *)(const void *)src)); \\\n      src += 16; \\\n      dest += 16; \\\n    }\n\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK1(dest, src) \\\n      if (dest >= lim) break; \\\n      COPY_CHUNK1(dest, src) \\\n    }\n\n  #elif defined(MY_CPU_64BIT)\n    #define COPY_OFFSET_MIN  8\n\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \\\n      src  += 8 * 1; dest += 8 * 1; \\\n      ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \\\n      src  += 8 * 1; dest += 8 * 1; \\\n    }\n\n  #else\n    #define COPY_OFFSET_MIN  4\n\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK_4_2(dest, src); \\\n      COPY_CHUNK_4_2(dest, src); \\\n    }\n\n  #endif\n#endif\n\n\n#ifndef COPY_CHUNK_SIZE\n    #define COPY_OFFSET_MIN  4\n    #define COPY_CHUNK_SIZE  8\n    #define COPY_CHUNK_2(dest, src) \\\n    { \\\n      const Byte a0 = src[0]; \\\n      const Byte a1 = src[1]; \\\n      dest[0] = a0; \\\n      dest[1] = a1; \\\n      src += 2; \\\n      dest += 2; \\\n    }\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK_2(dest, src) \\\n      COPY_CHUNK_2(dest, src) \\\n      COPY_CHUNK_2(dest, src) \\\n      COPY_CHUNK_2(dest, src) \\\n    }\n#endif\n\n\n#define COPY_CHUNKS \\\n{ \\\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \\\n  do { COPY_CHUNK(dest, src) } \\\n  while (dest < lim); \\\n}\n\nnamespace NCompress {\nnamespace NRar5 {\n\ntypedef\n#if 1\n  unsigned\n#else\n  size_t\n#endif\n  CLenType;\n\n// (len != 0)\nstatic\nZ7_FORCE_INLINE\n// Z7_ATTRIB_NO_VECTOR\nvoid CopyMatch(size_t offset, Byte *dest, const Byte *src, const Byte *lim)\n{\n  {\n    // (COPY_OFFSET_MIN >= 4)\n    if (offset >= COPY_OFFSET_MIN)\n    {\n      COPY_CHUNKS\n      // return;\n    }\n    else\n  #if (COPY_OFFSET_MIN > 4)\n    #if COPY_CHUNK_SIZE < 8\n      #error Stop_Compiling_Bad_COPY_CHUNK_SIZE\n    #endif\n    if (offset >= 4)\n    {\n      Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n      do\n      {\n        COPY_CHUNK_4_2(dest, src)\n        #if COPY_CHUNK_SIZE < 16\n          if (dest >= lim) break;\n        #endif\n        COPY_CHUNK_4_2(dest, src)\n      }\n      while (dest < lim);\n      // return;\n    }\n    else\n  #endif\n    {\n      // (offset < 4)\n      const unsigned b0 = src[0];\n      if (offset < 2)\n      {\n      #if defined(Z7_RAR5_DEC_USE_UNALIGNED_COPY) && (COPY_CHUNK_SIZE == 16)\n        #if defined(MY_CPU_64BIT)\n        {\n          const UInt64 v64 = (UInt64)b0 * 0x0101010101010101;\n          Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n          do\n          {\n            ((UInt64 *)(void *)dest)[0] = v64;\n            ((UInt64 *)(void *)dest)[1] = v64;\n            dest += 16;\n          }\n          while (dest < lim);\n        }\n        #else\n        {\n          UInt32 v = b0;\n          v |= v << 8;\n          v |= v << 16;\n          do\n          {\n            ((UInt32 *)(void *)dest)[0] = v;\n            ((UInt32 *)(void *)dest)[1] = v;\n            dest += 8;\n            ((UInt32 *)(void *)dest)[0] = v;\n            ((UInt32 *)(void *)dest)[1] = v;\n            dest += 8;\n          }\n          while (dest < lim);\n        }\n        #endif\n      #else\n        do\n        {\n          dest[0] = (Byte)b0;\n          dest[1] = (Byte)b0;\n          dest += 2;\n          dest[0] = (Byte)b0;\n          dest[1] = (Byte)b0;\n          dest += 2;\n        }\n        while (dest < lim);\n      #endif\n      }\n      else if (offset == 2)\n      {\n        const Byte b1 = src[1];\n        {\n          do\n          {\n            dest[0] = (Byte)b0;\n            dest[1] = b1;\n            dest += 2;\n          }\n          while (dest < lim);\n        }\n      }\n      else // (offset == 3)\n      {\n        const Byte b1 = src[1];\n        const Byte b2 = src[2];\n        do\n        {\n          dest[0] = (Byte)b0;\n          dest[1] = b1;\n          dest[2] = b2;\n          dest += 3;\n        }\n        while (dest < lim);\n      }\n    }\n  }\n}\n\nstatic const size_t kInputBufSize = 1 << 20;\nstatic const UInt32   k_Filter_BlockSize_MAX = 1 << 22;\nstatic const unsigned k_Filter_AfterPad_Size = 64;\n\n#ifdef Z7_RAR5_SHOW_STAT\nstatic const unsigned kNumStats1 = 10;\nstatic const unsigned kNumStats2 = (1 << 12) + 16;\nstatic UInt32 g_stats1[kNumStats1];\nstatic UInt32 g_stats2[kNumStats1][kNumStats2];\n#endif\n\n#if 1\nMY_ALIGN(32)\n// DICT_SIZE_BITS_MAX-1 are required\nstatic const Byte k_LenPlusTable[DICT_SIZE_BITS_MAX] =\n  { 0,0,0,0,0,0,0,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };\n#endif\n\n\n\nclass CBitDecoder\n{\npublic:\n  const Byte *_buf;\n  const Byte *_bufCheck_Block;  // min(ptr for _blockEnd, _bufCheck)\n  unsigned _bitPos;             // = [0 ... 7]\n  bool _wasFinished;\n  bool _minorError;\n  unsigned _blockEndBits7;      // = [0 ... 7] : the number of additional bits in (_blockEnd) poisition.\n  HRESULT _hres;\n  const Byte *_bufCheck;        // relaxed limit (16 bytes before real end of input data in buffer)\n  Byte *_bufLim;                // end if input data\n  Byte *_bufBase;\n  ISequentialInStream *_stream;\n\n  UInt64 _processedSize;\n  UInt64 _blockEnd;     // absolute end of current block\n      // but it doesn't include additional _blockEndBits7 [0 ... 7] bits\n\n  Z7_FORCE_INLINE\n  void CopyFrom(const CBitDecoder &a)\n  {\n    _buf = a._buf;\n    _bufCheck_Block = a._bufCheck_Block;\n    _bitPos = a._bitPos;\n    _wasFinished = a._wasFinished;\n    _blockEndBits7 = a._blockEndBits7;\n    _bufCheck = a._bufCheck;\n    _bufLim = a._bufLim;\n    _bufBase = a._bufBase;\n    \n    _processedSize = a._processedSize;\n    _blockEnd = a._blockEnd;\n  }\n\n  Z7_FORCE_INLINE\n  void RestoreFrom2(const CBitDecoder &a)\n  {\n    _buf = a._buf;\n    _bitPos = a._bitPos;\n  }\n\n  Z7_FORCE_INLINE\n  void SetCheck_forBlock()\n  {\n    _bufCheck_Block = _bufCheck;\n    if (_bufCheck > _buf)\n    {\n      const UInt64 processed = GetProcessedSize_Round();\n      if (_blockEnd < processed)\n        _bufCheck_Block = _buf;\n      else\n      {\n        const UInt64 delta = _blockEnd - processed;\n        if ((size_t)(_bufCheck - _buf) > delta)\n          _bufCheck_Block = _buf + (size_t)delta;\n      }\n    }\n  }\n\n  Z7_FORCE_INLINE\n  bool IsBlockOverRead() const\n  {\n    const UInt64 v = GetProcessedSize_Round();\n    if (v < _blockEnd) return false;\n    if (v > _blockEnd) return true;\n    return _bitPos > _blockEndBits7;\n  }\n\n  /*\n  CBitDecoder() throw():\n      _buf(0),\n      _bufLim(0),\n      _bufBase(0),\n      _stream(0),\n      _processedSize(0),\n      _wasFinished(false)\n      {}\n  */\n\n  Z7_FORCE_INLINE\n  void Init() throw()\n  {\n    _blockEnd = 0;\n    _blockEndBits7 = 0;\n\n    _bitPos = 0;\n    _processedSize = 0;\n    _buf = _bufBase;\n    _bufLim = _bufBase;\n    _bufCheck = _buf;\n    _bufCheck_Block = _buf;\n    _wasFinished = false;\n    _minorError = false;\n  }\n\n  void Prepare2() throw();\n\n  Z7_FORCE_INLINE\n  void Prepare() throw()\n  {\n    if (_buf >= _bufCheck)\n      Prepare2();\n  }\n\n  Z7_FORCE_INLINE\n  bool ExtraBitsWereRead() const\n  {\n    return _buf >= _bufLim && (_buf > _bufLim || _bitPos != 0);\n  }\n\n  Z7_FORCE_INLINE bool InputEofError() const { return ExtraBitsWereRead(); }\n\n  Z7_FORCE_INLINE unsigned GetProcessedBits7() const { return _bitPos; }\n  Z7_FORCE_INLINE UInt64 GetProcessedSize_Round() const { return _processedSize + (size_t)(_buf - _bufBase); }\n  Z7_FORCE_INLINE UInt64 GetProcessedSize() const { return _processedSize + (size_t)(_buf - _bufBase) + ((_bitPos + 7) >> 3); }\n\n  Z7_FORCE_INLINE\n  void AlignToByte()\n  {\n    if (_bitPos != 0)\n    {\n#if 1\n      // optional check of unused bits for strict checking:\n      // original-unrar doesn't check it:\n      const unsigned b = (unsigned)*_buf << _bitPos;\n      if (b & 0xff)\n        _minorError = true;\n#endif\n      _buf++;\n      _bitPos = 0;\n    }\n    // _buf += (_bitPos + 7) >> 3;\n    // _bitPos = 0;\n  }\n\n  Z7_FORCE_INLINE\n  Byte ReadByte_InAligned()\n  {\n    return *_buf++;\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue(unsigned numBits) const\n  {\n    // 0 < numBits <= 17 : supported values\n#if defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE_UNALIGN)\n    UInt32 v = GetBe32(_buf);\n#if 1\n    return (v >> (32 - numBits - _bitPos)) & ((1u << numBits) - 1);\n#else\n    return (v << _bitPos) >> (32 - numBits);\n#endif\n#else\n    UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];\n    v >>= 24 - numBits - _bitPos;\n    return v & ((1 << numBits) - 1);\n#endif\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 GetValue_InHigh32bits() const\n  {\n    // 0 < numBits <= 17 : supported vales\n#if defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_LE_UNALIGN)\n    return GetBe32(_buf) << _bitPos;\n#else\n    const UInt32 v = ((UInt32)_buf[0] << 16) | ((UInt32)_buf[1] << 8) | (UInt32)_buf[2];\n    return v << (_bitPos + 8);\n#endif\n  }\n  \n\n  Z7_FORCE_INLINE\n  void MovePos(unsigned numBits)\n  {\n    numBits += _bitPos;\n    _buf += numBits >> 3;\n    _bitPos = numBits & 7;\n  }\n    \n\n  Z7_FORCE_INLINE\n  UInt32 ReadBits9(unsigned numBits)\n  {\n    const Byte *buf = _buf;\n    UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];\n    v &= (UInt32)0xFFFF >> _bitPos;\n    numBits += _bitPos;\n    v >>= 16 - numBits;\n    _buf = buf + (numBits >> 3);\n    _bitPos = numBits & 7;\n    return v;\n  }\n\n  Z7_FORCE_INLINE\n  UInt32 ReadBits_9fix(unsigned numBits)\n  {\n    const Byte *buf = _buf;\n    UInt32 v = ((UInt32)buf[0] << 8) | (UInt32)buf[1];\n    const UInt32 mask = (1u << numBits) - 1;\n    numBits += _bitPos;\n    v >>= 16 - numBits;\n    _buf = buf + (numBits >> 3);\n    _bitPos = numBits & 7;\n    return v & mask;\n  }\n\n#if 1 && defined(MY_CPU_SIZEOF_POINTER) && (MY_CPU_SIZEOF_POINTER == 8)\n#define Z7_RAR5_USE_64BIT\n#endif\n\n#ifdef Z7_RAR5_USE_64BIT\n#define MAX_DICT_LOG (sizeof(size_t) / 8 * 5 + 31)\n#else\n#define MAX_DICT_LOG 31\n#endif\n\n#ifdef Z7_RAR5_USE_64BIT\n\n  Z7_FORCE_INLINE\n  size_t ReadBits_Big(unsigned numBits, UInt64 v)\n  {\n    const UInt64 mask = ((UInt64)1 << numBits) - 1;\n    numBits += _bitPos;\n    const Byte *buf = _buf;\n    // UInt64 v = GetBe64(buf);\n    v >>= 64 - numBits;\n    _buf = buf + (numBits >> 3);\n    _bitPos = numBits & 7;\n    return (size_t)(v & mask);\n  }\n  #define ReadBits_Big25 ReadBits_Big\n\n#else\n\n  // (numBits <= 25) for 32-bit mode\n  Z7_FORCE_INLINE\n  size_t ReadBits_Big25(unsigned numBits, UInt32 v)\n  {\n    const UInt32 mask = ((UInt32)1 << numBits) - 1;\n    numBits += _bitPos;\n    v >>= 32 - numBits;\n    _buf += numBits >> 3;\n    _bitPos = numBits & 7;\n    return v & mask;\n  }\n\n  // numBits != 0\n  Z7_FORCE_INLINE\n  size_t ReadBits_Big(unsigned numBits, UInt32 v)\n  {\n    const Byte *buf = _buf;\n    // UInt32 v = GetBe32(buf);\n#if 0\n    const UInt32 mask = ((UInt32)1 << numBits) - 1;\n    numBits += _bitPos;\n    if (numBits > 32)\n    {\n      v <<= numBits - 32;\n      v |= (UInt32)buf[4] >> (40 - numBits);\n    }\n    else\n      v >>= 32 - numBits;\n    _buf = buf + (numBits >> 3);\n    _bitPos = numBits & 7;\n    return v & mask;\n#else\n    v <<= _bitPos;\n    v |= (UInt32)buf[4] >> (8 - _bitPos);\n    v >>= 32 - numBits;\n    numBits += _bitPos;\n    _buf = buf + (numBits >> 3);\n    _bitPos = numBits & 7;\n    return v;\n#endif\n  }\n#endif\n};\n\n\nstatic const unsigned kLookaheadSize = 16;\nstatic const unsigned kInputBufferPadZone = kLookaheadSize;\n\nZ7_NO_INLINE\nvoid CBitDecoder::Prepare2() throw()\n{\n  if (_buf > _bufLim)\n    return;\n\n  size_t rem = (size_t)(_bufLim - _buf);\n  if (rem != 0)\n    memmove(_bufBase, _buf, rem);\n\n  _bufLim = _bufBase + rem;\n  _processedSize += (size_t)(_buf - _bufBase);\n  _buf = _bufBase;\n\n  // we do not look ahead more than 16 bytes before limit checks.\n\n  if (!_wasFinished)\n  {\n    while (rem <= kLookaheadSize)\n    {\n      UInt32 processed = (UInt32)(kInputBufSize - rem);\n      // processed = 33; // for debug\n      _hres = _stream->Read(_bufLim, processed, &processed);\n      _bufLim += processed;\n      rem += processed;\n      if (processed == 0 || _hres != S_OK)\n      {\n        _wasFinished = true;\n        // if (_hres != S_OK) throw CInBufferException(result);\n        break;\n      }\n    }\n  }\n\n  // we always fill pad zone here.\n  // so we don't need to call Prepare2() if (_wasFinished == true)\n  memset(_bufLim, 0xFF, kLookaheadSize);\n\n  if (rem < kLookaheadSize)\n  {\n    _bufCheck = _buf;\n    // memset(_bufLim, 0xFF, kLookaheadSize - rem);\n  }\n  else\n    _bufCheck = _bufLim - kLookaheadSize;\n\n  SetCheck_forBlock();\n}\n\n\nenum FilterType\n{\n  FILTER_DELTA = 0,\n  FILTER_E8,\n  FILTER_E8E9,\n  FILTER_ARM\n};\n\nstatic const size_t kWriteStep = (size_t)1 << 18;\n      // (size_t)1 << 22; // original-unrar\n\n// Original unRAR claims that maximum possible filter block size is (1 << 16) now,\n// and (1 << 17) is minimum win size required to support filter.\n// Original unRAR uses (1u << 18) for \"extra safety and possible filter area size expansion\"\n// We can use any win size, but we use same (1u << 18) for compatibility\n// with WinRar\n\n// static const unsigned kWinSize_Log_Min = 17;\nstatic const size_t kWinSize_Min = 1u << 18;\n\nCDecoder::CDecoder():\n    _isSolid(false),\n    _is_v7(false),\n    _wasInit(false),\n    // _dictSizeLog(0),\n    _dictSize(kWinSize_Min),\n    _window(NULL),\n    _winPos(0),\n    _winSize(0),\n    _dictSize_forCheck(0),\n    _lzSize(0),\n    _lzEnd(0),\n    _writtenFileSize(0),\n    _filters(NULL),\n    _winSize_Allocated(0),\n    _inputBuf(NULL)\n{\n#if 1\n  memcpy(m_LenPlusTable, k_LenPlusTable, sizeof(k_LenPlusTable));\n#endif\n  // printf(\"\\nsizeof(CDecoder) == %d\\n\", sizeof(CDecoder));\n}\n\nCDecoder::~CDecoder()\n{\n#ifdef Z7_RAR5_SHOW_STAT\n  printf(\"\\n%4d :\", 0);\n  for (unsigned k = 0; k < kNumStats1; k++)\n    printf(\" %8u\", (unsigned)g_stats1[k]);\n  printf(\"\\n\");\n  for (unsigned i = 0; i < kNumStats2; i++)\n  {\n    printf(\"\\n%4d :\", i);\n    for (unsigned k = 0; k < kNumStats1; k++)\n      printf(\" %8u\", (unsigned)g_stats2[k][i]);\n  }\n  printf(\"\\n\");\n#endif\n\n#define Z7_RAR_FREE_WINDOW ::BigFree(_window);\n  \n  Z7_RAR_FREE_WINDOW\n  z7_AlignedFree(_inputBuf);\n  z7_AlignedFree(_filters);\n}\n\nZ7_NO_INLINE\nvoid CDecoder::DeleteUnusedFilters()\n{\n  if (_numUnusedFilters != 0)\n  {\n    // printf(\"\\nDeleteUnusedFilters _numFilters = %6u\\n\", _numFilters);\n    const unsigned n = _numFilters - _numUnusedFilters;\n    _numFilters = n;\n    memmove(_filters, _filters + _numUnusedFilters, n * sizeof(CFilter));\n    _numUnusedFilters = 0;\n  }\n}\n\n\nZ7_NO_INLINE\nHRESULT CDecoder::WriteData(const Byte *data, size_t size)\n{\n  HRESULT res = S_OK;\n  if (!_unpackSize_Defined || _writtenFileSize < _unpackSize)\n  {\n    size_t cur = size;\n    if (_unpackSize_Defined)\n    {\n      const UInt64 rem = _unpackSize - _writtenFileSize;\n      if (cur > rem)\n        cur = (size_t)rem;\n    }\n    res = WriteStream(_outStream, data, cur);\n    if (res != S_OK)\n      _writeError = true;\n  }\n  _writtenFileSize += size;\n  return res;\n}\n\n\n#if defined(MY_CPU_SIZEOF_POINTER) \\\n    && ( MY_CPU_SIZEOF_POINTER == 4 \\\n      || MY_CPU_SIZEOF_POINTER == 8)\n  #define BR_CONV_USE_OPT_PC_PTR\n#endif\n\n#ifdef BR_CONV_USE_OPT_PC_PTR\n#define BR_PC_INIT(lim_back)  pc -= (UInt32)(SizeT)data;\n#define BR_PC_GET        (pc + (UInt32)(SizeT)data)\n#else\n#define BR_PC_INIT(lim_back)  pc += (UInt32)dataSize - (lim_back);\n#define BR_PC_GET        (pc - (UInt32)(SizeT)(data_lim - data))\n#endif\n\n#ifdef MY_CPU_LE_UNALIGN\n#define Z7_RAR5_FILTER_USE_LE_UNALIGN\n#endif\n\n#ifdef Z7_RAR5_FILTER_USE_LE_UNALIGN\n#define RAR_E8_FILT(mask) \\\n{ \\\n  for (;;) \\\n  { UInt32 v; \\\n    do { \\\n      v = GetUi32(data) ^ (UInt32)0xe8e8e8e8; \\\n      data += 4; \\\n      if ((v & ((UInt32)(mask) << (8 * 0))) == 0) { data -= 3; break; } \\\n      if ((v & ((UInt32)(mask) << (8 * 1))) == 0) { data -= 2; break; } \\\n      if ((v & ((UInt32)(mask) << (8 * 2))) == 0) { data -= 1; break; } } \\\n    while((v & ((UInt32)(mask) << (8 * 3)))); \\\n    if (data > data_lim) break; \\\n    const UInt32 offset = BR_PC_GET & (kFileSize - 1); \\\n    const UInt32 addr = GetUi32(data); \\\n    data += 4; \\\n    if (addr < kFileSize) \\\n      SetUi32(data - 4, addr - offset) \\\n    else if (addr > ~offset) /* if (addr > ((UInt32)0xFFFFFFFF - offset)) */ \\\n      SetUi32(data - 4, addr + kFileSize) \\\n  } \\\n}\n#else\n#define RAR_E8_FILT(get_byte) \\\n{ \\\n  for (;;) \\\n  { \\\n    if ((get_byte) != 0xe8) \\\n    if ((get_byte) != 0xe8) \\\n    if ((get_byte) != 0xe8) \\\n    if ((get_byte) != 0xe8) \\\n      continue; \\\n    { if (data > data_lim) break; \\\n    const UInt32 offset = BR_PC_GET & (kFileSize - 1); \\\n    const UInt32 addr = GetUi32(data); \\\n    data += 4; \\\n    if (addr < kFileSize) \\\n      SetUi32(data - 4, addr - offset) \\\n      else if (addr > ~offset) /* if (addr > ((UInt32)0xFFFFFFFF - offset)) */ \\\n      SetUi32(data - 4, addr + kFileSize) \\\n    } \\\n  } \\\n}\n#endif\n\nHRESULT CDecoder::ExecuteFilter(const CFilter &f)\n{\n  Byte *data = _filterSrc;\n  UInt32 dataSize = f.Size;\n  // printf(\"\\nType = %d offset = %9d  size = %5d\", f.Type, (unsigned)(f.Start - _lzFileStart), dataSize);\n\n  if (f.Type == FILTER_DELTA)\n  {\n    // static unsigned g1 = 0, g2 = 0; g1 += dataSize;\n    // if (g2++ % 100 == 0) printf(\"DELTA  num %8u, size %8u MiB, channels = %2u curSize=%8u\\n\", g2, (g1 >> 20), f.Channels, dataSize);\n    _filterDst.AllocAtLeast_max((size_t)dataSize, k_Filter_BlockSize_MAX);\n    if (!_filterDst.IsAllocated())\n      return E_OUTOFMEMORY;\n    \n    Byte *dest = _filterDst;\n    const unsigned numChannels = f.Channels;\n    unsigned curChannel = 0;\n    do\n    {\n      Byte prevByte = 0;\n      Byte *dest2 = dest + curChannel;\n      const Byte *dest_lim = dest + dataSize;\n      for (; dest2 < dest_lim; dest2 += numChannels)\n        *dest2 = (prevByte = (Byte)(prevByte - *data++));\n    }\n    while (++curChannel != numChannels);\n    // return WriteData(dest, dataSize);\n    data = dest;\n  }\n  else if (f.Type < FILTER_ARM)\n  {\n    // FILTER_E8 or FILTER_E8E9\n    if (dataSize > 4)\n    {\n      UInt32 pc = (UInt32)(f.Start - _lzFileStart);\n      const UInt32 kFileSize = (UInt32)1 << 24;\n      const Byte *data_lim = data + dataSize - 4;\n      BR_PC_INIT(4) // because (data_lim) was moved back for 4 bytes\n      data[dataSize] = 0xe8;\n      if (f.Type == FILTER_E8)\n      {\n        // static unsigned g1 = 0; g1 += dataSize; printf(\"\\n  FILTER_E8   %u\", (g1 >> 20));\n#ifdef Z7_RAR5_FILTER_USE_LE_UNALIGN\n        RAR_E8_FILT (0xff)\n#else\n        RAR_E8_FILT (*data++)\n#endif\n      }\n      else\n      {\n        // static unsigned g1 = 0; g1 += dataSize; printf(\"\\n  FILTER_E8_E9 %u\", (g1 >> 20));\n#ifdef Z7_RAR5_FILTER_USE_LE_UNALIGN\n        RAR_E8_FILT (0xfe)\n#else\n        RAR_E8_FILT (*data++ & 0xfe)\n#endif\n      }\n    }\n    data = _filterSrc;\n  }\n  else if (f.Type == FILTER_ARM)\n  {\n    UInt32 pc = (UInt32)(f.Start - _lzFileStart);\n#if 0\n    // z7_BranchConv_ARM_Dec expects that (fileOffset & 3) == 0;\n    // but even if (fileOffset & 3) then current code\n    // in z7_BranchConv_ARM_Dec works same way as unrar's code still.\n    z7_BranchConv_ARM_Dec(data, dataSize, pc - 8);\n#else\n    dataSize &= ~(UInt32)3;\n    if (dataSize)\n    {\n      Byte *data_lim = data + dataSize;\n      data_lim[3] = 0xeb;\n      BR_PC_INIT(0)\n      pc -= 4;  // because (data) will point to next instruction\n      for (;;) // do\n      {\n        data += 4;\n        if (data[-1] != 0xeb)\n          continue;\n        if (data > data_lim)\n          break;\n        {\n          UInt32 v = GetUi32a(data - 4) - (BR_PC_GET >> 2);\n          v &= 0x00ffffff;\n          v |= 0xeb000000;\n          SetUi32a(data - 4, v)\n        }\n      }\n    }\n#endif\n    data = _filterSrc;\n  }\n  else\n  {\n    _unsupportedFilter = true;\n    My_ZeroMemory(data, dataSize);\n    // return S_OK;  // unrar\n  }\n  // return WriteData(_filterSrc, (size_t)f.Size);\n  return WriteData(data, (size_t)f.Size);\n}\n\n\nHRESULT CDecoder::WriteBuf()\n{\n  DeleteUnusedFilters();\n  const UInt64 lzSize = _lzSize + _winPos;\n\n  for (unsigned i = 0; i < _numFilters;)\n  {\n    const size_t lzAvail = (size_t)(lzSize - _lzWritten);\n    if (lzAvail == 0)\n      break;\n    // (lzAvail != 0)\n    const CFilter &f = _filters[i];\n    const UInt64 blockStart = f.Start;\n    if (blockStart > _lzWritten)\n    {\n      const UInt64 rem = blockStart - _lzWritten;\n      // (rem != 0)\n      size_t size = lzAvail;\n      if (size > rem)\n        size = (size_t)rem;\n      // (size != 0)\n      RINOK(WriteData(_window + _winPos - lzAvail, size))\n      _lzWritten += size;\n      continue;\n    }\n\n    // (blockStart <= _lzWritten)\n    const UInt32 blockSize = f.Size;\n    size_t offset = (size_t)(_lzWritten - blockStart);\n    if (offset == 0)\n    {\n      _filterSrc.AllocAtLeast_max(\n          (size_t)blockSize      + k_Filter_AfterPad_Size,\n          k_Filter_BlockSize_MAX + k_Filter_AfterPad_Size);\n      if (!_filterSrc.IsAllocated())\n        return E_OUTOFMEMORY;\n    }\n    \n    const size_t blockRem = (size_t)blockSize - offset;\n    size_t size = lzAvail;\n    if (size > blockRem)\n        size = blockRem;\n    memcpy(_filterSrc + offset, _window + _winPos - lzAvail, size);\n    _lzWritten += size;\n    offset += size;\n    if (offset != blockSize)\n      return S_OK;\n\n    _numUnusedFilters = ++i;\n    RINOK(ExecuteFilter(f))\n  }\n      \n  DeleteUnusedFilters();\n  if (_numFilters)\n    return S_OK;\n  const size_t lzAvail = (size_t)(lzSize - _lzWritten);\n  RINOK(WriteData(_window + _winPos - lzAvail, lzAvail))\n  _lzWritten += lzAvail;\n  return S_OK;\n}\n\n\nZ7_NO_INLINE\nstatic UInt32 ReadUInt32(CBitDecoder &bi)\n{\n  const unsigned numBits = (unsigned)bi.ReadBits_9fix(2) * 8 + 8;\n  UInt32 v = 0;\n  unsigned i = 0;\n  do\n  {\n    v += (UInt32)bi.ReadBits_9fix(8) << i;\n    i += 8;\n  }\n  while (i != numBits);\n  return v;\n}\n\n\nstatic const unsigned MAX_UNPACK_FILTERS = 8192;\n\nHRESULT CDecoder::AddFilter(CBitDecoder &_bitStream)\n{\n  DeleteUnusedFilters();\n\n  if (_numFilters >= MAX_UNPACK_FILTERS)\n  {\n    RINOK(WriteBuf())\n    DeleteUnusedFilters();\n    if (_numFilters >= MAX_UNPACK_FILTERS)\n    {\n      _unsupportedFilter = true;\n      InitFilters();\n    }\n  }\n\n  _bitStream.Prepare();\n\n  CFilter f;\n  const UInt32 blockStart = ReadUInt32(_bitStream);\n  f.Size = ReadUInt32(_bitStream);\n\n  if (f.Size > k_Filter_BlockSize_MAX)\n  {\n    _unsupportedFilter = true;\n    f.Size = 0;  // unrar 5.5.5\n  }\n\n  f.Type = (Byte)_bitStream.ReadBits_9fix(3);\n  f.Channels = 0;\n  if (f.Type == FILTER_DELTA)\n    f.Channels = (Byte)(_bitStream.ReadBits_9fix(5) + 1);\n  f.Start = _lzSize + _winPos + blockStart;\n\n#if 0\n  static unsigned z_cnt = 0; if (z_cnt++ % 100 == 0)\n    printf (\"\\nFilter %7u : %4u : %8p, st=%8x, size=%8x, type=%u ch=%2u\",\n      z_cnt, (unsigned)_filters.Size(), (void *)(size_t)(_lzSize + _winPos),\n      (unsigned)blockStart, (unsigned)f.Size, (unsigned)f.Type, (unsigned)f.Channels);\n#endif\n\n  if (f.Start < _filterEnd)\n    _unsupportedFilter = true;\n  else\n  {\n    _filterEnd = f.Start + f.Size;\n    if (f.Size != 0)\n    {\n      if (!_filters)\n      {\n        _filters = (CFilter *)z7_AlignedAlloc(MAX_UNPACK_FILTERS * sizeof(CFilter));\n        if (!_filters)\n          return E_OUTOFMEMORY;\n      }\n      // printf(\"\\n_numFilters = %6u\\n\", _numFilters);\n      const unsigned i = _numFilters++;\n      _filters[i] = f;\n    }\n  }\n\n  return S_OK;\n}\n\n\n#define RIF(x) { if (!(x)) return S_FALSE; }\n\n#if 1\n#define PRINT_CNT(name, skip)\n#else\n#define PRINT_CNT(name, skip) \\\n  { static unsigned g_cnt = 0; if (g_cnt++ % skip == 0) printf(\"\\n%16s:  %8u\", name, g_cnt); }\n#endif\n\nHRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)\n{\n  if (_progress)\n  {\n    const UInt64 packSize = _bitStream.GetProcessedSize();\n    if (packSize - _progress_Pack >= (1u << 24)\n        || _writtenFileSize - _progress_Unpack >= (1u << 26))\n    {\n      _progress_Pack = packSize;\n      _progress_Unpack = _writtenFileSize;\n      RINOK(_progress->SetRatioInfo(&_progress_Pack, &_writtenFileSize))\n    }\n    // printf(\"\\ntable read pos=%p packSize=%p _writtenFileSize = %p\\n\", (size_t)_winPos, (size_t)packSize, (size_t)_writtenFileSize);\n  }\n\n  // _bitStream is aligned already\n  _bitStream.Prepare();\n  {\n    const unsigned flags = _bitStream.ReadByte_InAligned();\n    /* ((flags & 20) == 0) in all rar archives now,\n       but (flags & 20) flag can be used as some decoding hint in future versions of original rar.\n       So we ignore that bit here. */\n    unsigned checkSum = _bitStream.ReadByte_InAligned();\n    checkSum ^= flags;\n    const unsigned num = (flags >> 3) & 3;\n    if (num >= 3)\n      return S_FALSE;\n    UInt32 blockSize = _bitStream.ReadByte_InAligned();\n    checkSum ^= blockSize;\n    if (num != 0)\n    {\n      {\n        const unsigned b = _bitStream.ReadByte_InAligned();\n        checkSum ^= b;\n        blockSize += (UInt32)b << 8;\n      }\n      if (num > 1)\n      {\n        const unsigned b = _bitStream.ReadByte_InAligned();\n        checkSum ^= b;\n        blockSize += (UInt32)b << 16;\n      }\n    }\n    if (checkSum != 0x5A)\n      return S_FALSE;\n    unsigned blockSizeBits7 = (flags & 7) + 1;\n    blockSize += (UInt32)(blockSizeBits7 >> 3);\n    if (blockSize == 0)\n    {\n      // it's error in data stream\n      // but original-unrar ignores that error\n      _bitStream._minorError = true;\n#if 1\n      // we ignore that error as original-unrar:\n      blockSizeBits7 = 0;\n      blockSize = 1;\n#else\n      // we can stop decoding:\n      return S_FALSE;\n#endif\n    }\n    blockSize--;\n    blockSizeBits7 &= 7;\n    PRINT_CNT(\"Blocks\", 100)\n    /*\n    {\n      static unsigned g_prev = 0;\n      static unsigned g_cnt = 0;\n      unsigned proc = unsigned(_winPos);\n      if (g_cnt++ % 100 == 0) printf(\"  c_size = %8u  \", blockSize);\n      if (g_cnt++ % 100 == 1) printf(\"  unp_size = %8u\", proc - g_prev);\n      g_prev = proc;\n    }\n    */\n    _bitStream._blockEndBits7 = blockSizeBits7;\n    _bitStream._blockEnd = _bitStream.GetProcessedSize_Round() + blockSize;\n    _bitStream.SetCheck_forBlock();\n    _isLastBlock = ((flags & 0x40) != 0);\n    if ((flags & 0x80) == 0)\n    {\n      if (!_tableWasFilled)\n        // if (blockSize != 0 || blockSizeBits7 != 0)\n        if (blockSize + blockSizeBits7 != 0)\n          return S_FALSE;\n      return S_OK;\n    }\n    _tableWasFilled = false;\n  }\n\n  PRINT_CNT(\"Tables\", 100);\n\n  const unsigned kLevelTableSize = 20;\n  const unsigned k_NumHufTableBits_Level = 6;\n  NHuffman::CDecoder256<kNumHufBits, kLevelTableSize, k_NumHufTableBits_Level> m_LevelDecoder;\n  const unsigned kTablesSizesSum_MAX = kMainTableSize + kDistTableSize_MAX + kAlignTableSize + kLenTableSize;\n  Byte lens[kTablesSizesSum_MAX];\n  {\n    // (kLevelTableSize + 16 < kTablesSizesSum). So we use lens[] array for (Level) table\n    // Byte lens2[kLevelTableSize + 16];\n    unsigned i = 0;\n    do\n    {\n      if (_bitStream._buf >= _bitStream._bufCheck_Block)\n      {\n        _bitStream.Prepare();\n        if (_bitStream.IsBlockOverRead())\n          return S_FALSE;\n      }\n      const unsigned len = (unsigned)_bitStream.ReadBits_9fix(4);\n      if (len == 15)\n      {\n        unsigned num = (unsigned)_bitStream.ReadBits_9fix(4);\n        if (num != 0)\n        {\n          num += 2;\n          num += i;\n          // we are allowed to overwrite to lens[] for extra 16 bytes after kLevelTableSize\n#if 0\n          if (num > kLevelTableSize)\n          {\n            // we ignore this error as original-unrar\n            num = kLevelTableSize;\n            // return S_FALSE;\n          }\n#endif\n          do\n            lens[i++] = 0;\n          while (i < num);\n          continue;\n        }\n      }\n      lens[i++] = (Byte)len;\n    }\n    while (i < kLevelTableSize);\n    if (_bitStream.IsBlockOverRead())\n      return S_FALSE;\n    RIF(m_LevelDecoder.Build(lens, NHuffman::k_BuildMode_Full))\n  }\n\n  unsigned i = 0;\n  const unsigned tableSize = _is_v7 ?\n      kTablesSizesSum_MAX :\n      kTablesSizesSum_MAX - kExtraDistSymbols_v7;\n  do\n  {\n    if (_bitStream._buf >= _bitStream._bufCheck_Block)\n    {\n      // if (_bitStream._buf >= _bitStream._bufCheck)\n      _bitStream.Prepare();\n      if (_bitStream.IsBlockOverRead())\n        return S_FALSE;\n    }\n    const unsigned sym = m_LevelDecoder.DecodeFull(&_bitStream);\n    if (sym < 16)\n      lens[i++] = (Byte)sym;\n#if 0\n    else if (sym > kLevelTableSize)\n      return S_FALSE;\n#endif\n    else\n    {\n      unsigned num = ((sym /* - 16 */) & 1) * 4;\n      num += num + 3 + (unsigned)_bitStream.ReadBits9(num + 3);\n      num += i;\n      if (num > tableSize)\n      {\n        // we ignore this error as original-unrar\n        num = tableSize;\n        // return S_FALSE;\n      }\n      unsigned v = 0;\n      if (sym < 16 + 2)\n      {\n        if (i == 0)\n          return S_FALSE;\n        v = lens[(size_t)i - 1];\n      }\n      do\n        lens[i++] = (Byte)v;\n      while (i < num);\n    }\n  }\n  while (i < tableSize);\n\n  if (_bitStream.IsBlockOverRead())\n    return S_FALSE;\n  if (_bitStream.InputEofError())\n    return S_FALSE;\n\n  /* We suppose that original-rar encoder can create only two cases for Huffman:\n      1) Empty Huffman tree (if num_used_symbols == 0)\n      2) Full  Huffman tree (if num_used_symbols != 0)\n     Usually the block contains at least one symbol for m_MainDecoder.\n     So original-rar-encoder creates full Huffman tree for m_MainDecoder.\n     But we suppose that (num_used_symbols == 0) is possible for m_MainDecoder,\n     because file must be finished with (_isLastBlock) flag,\n     even if there are no symbols in m_MainDecoder.\n     So we use k_BuildMode_Full_or_Empty for m_MainDecoder.\n  */\n  const NHuffman::enum_BuildMode buildMode = NHuffman::\n      k_BuildMode_Full_or_Empty; // strict check\n      // k_BuildMode_Partial;    // non-strict check (ignore errors)\n\n  RIF(m_MainDecoder.Build(&lens[0], buildMode))\n  if (!_is_v7)\n  {\n#if 1\n    /* we use this manual loop to avoid compiler BUG.\n       GCC 4.9.2 compiler has BUG with overlapping memmove() to right in local array. */\n    Byte *dest = lens + kMainTableSize + kDistTableSize_v6 +\n                   kAlignTableSize + kLenTableSize - 1;\n    unsigned num = kAlignTableSize + kLenTableSize;\n    do\n    {\n      dest[kExtraDistSymbols_v7] = dest[0];\n      dest--;\n    }\n    while (--num);\n#else\n    memmove(lens + kMainTableSize + kDistTableSize_v6 + kExtraDistSymbols_v7,\n            lens + kMainTableSize + kDistTableSize_v6,\n            kAlignTableSize + kLenTableSize);\n#endif\n    memset(lens + kMainTableSize + kDistTableSize_v6, 0, kExtraDistSymbols_v7);\n  }\n\n  RIF(m_DistDecoder.Build(&lens[kMainTableSize], buildMode))\n  RIF( m_LenDecoder.Build(&lens[kMainTableSize\n        + kDistTableSize_MAX + kAlignTableSize], buildMode))\n\n  _useAlignBits = false;\n  for (i = 0; i < kAlignTableSize; i++)\n    if (lens[kMainTableSize + kDistTableSize_MAX + (size_t)i] != kNumAlignBits)\n    {\n      RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize_MAX], buildMode))\n      _useAlignBits = true;\n      break;\n    }\n\n  _tableWasFilled = true;\n  return S_OK;\n}\n\nstatic inline CLenType SlotToLen(CBitDecoder &_bitStream, CLenType slot)\n{\n  const unsigned numBits = ((unsigned)slot >> 2) - 1;\n  return ((4 | (slot & 3)) << numBits) + (CLenType)_bitStream.ReadBits9(numBits);\n}\n\n\nstatic const unsigned kSymbolRep = 258;\nstatic const unsigned kMaxMatchLen = 0x1001 + 3;\n\nenum enum_exit_type\n{\n  Z7_RAR_EXIT_TYPE_NONE,\n  Z7_RAR_EXIT_TYPE_ADD_FILTER\n};\n\n\n#define LZ_RESTORE \\\n{ \\\n  _reps[0] = rep0; \\\n  _winPos = (size_t)(winPos - _window); \\\n  _buf_Res = _bitStream._buf; \\\n  _bitPos_Res = _bitStream._bitPos; \\\n}\n\n#define LZ_LOOP_BREAK_OK { break; }\n// #define LZ_LOOP_BREAK_ERROR { _lzError = LZ_ERROR_TYPE_SYM; break; }\n// #define LZ_LOOP_BREAK_ERROR { LZ_RESTORE; return S_FALSE; }\n#define LZ_LOOP_BREAK_ERROR { goto decode_error; }\n// goto decode_error; }\n// #define LZ_LOOP_BREAK_ERROR { break; }\n\n#define Z7_RAR_HUFF_DECODE_CHECK_break(sym, huf, kNumTableBits, bitStream) \\\n  Z7_HUFF_DECODE_CHECK(sym, huf, kNumHufBits, kNumTableBits, bitStream, { LZ_LOOP_BREAK_ERROR })\n\n\n/*\n  DecodeLZ2() will stop decoding if it reaches limit when (_winPos >= _limit)\n  at return:\n    (_winPos < _limit + kMaxMatchLen)\n    also it can write up to (COPY_CHUNK_SIZE - 1) additional junk bytes after (_winPos).\n*/\nHRESULT CDecoder::DecodeLZ2(const CBitDecoder &bitStream) throw()\n{\n#if 0\n  Byte k_LenPlusTable_LOC[DICT_SIZE_BITS_MAX];\n  memcpy(k_LenPlusTable_LOC, k_LenPlusTable, sizeof(k_LenPlusTable));\n#endif\n\n  PRINT_CNT(\"DecodeLZ2\", 2000);\n\n  CBitDecoder _bitStream;\n  _bitStream.CopyFrom(bitStream);\n  // _bitStream._stream = _inStream;\n  // _bitStream._bufBase = _inputBuf;\n  // _bitStream.Init();\n\n  // _reps[*] can be larger than _winSize, if _winSize was reduced in solid stream.\n  size_t rep0 = _reps[0];\n  // size_t rep1 = _reps[1];\n  // Byte *win = _window;\n  Byte *winPos = _window + _winPos;\n  const Byte *limit = _window + _limit;\n  _exitType = Z7_RAR_EXIT_TYPE_NONE;\n\n  for (;;)\n  {\n    if (winPos >= limit)\n      LZ_LOOP_BREAK_OK\n    // (winPos < limit)\n    if (_bitStream._buf >= _bitStream._bufCheck_Block)\n    {\n      if (_bitStream.InputEofError())\n        LZ_LOOP_BREAK_OK\n      if (_bitStream._buf >= _bitStream._bufCheck)\n      {\n        if (!_bitStream._wasFinished)\n          LZ_LOOP_BREAK_OK\n        // _bitStream._wasFinished == true\n        // we don't need Prepare() here, because all data was read\n        // and PadZone (16 bytes) after data was filled.\n      }\n      const UInt64 processed = _bitStream.GetProcessedSize_Round();\n      // some cases are error, but the caller will process such error cases.\n      if (processed >= _bitStream._blockEnd &&\n          (processed > _bitStream._blockEnd\n            || _bitStream.GetProcessedBits7() >= _bitStream._blockEndBits7))\n          LZ_LOOP_BREAK_OK\n      // that check is not required, but it can help, if there is BUG in another code\n      if (!_tableWasFilled)\n        LZ_LOOP_BREAK_ERROR\n    }\n    \n#if 0\n    const unsigned sym = m_MainDecoder.Decode(&_bitStream);\n#else\n    unsigned sym;\n    Z7_RAR_HUFF_DECODE_CHECK_break(sym, &m_MainDecoder, k_NumHufTableBits_Main, &_bitStream)\n#endif\n    \n    if (sym < 256)\n    {\n      *winPos++ = (Byte)sym;\n      // _lzSize++;\n      continue;\n    }\n   \n    CLenType len;\n\n    if (sym < kSymbolRep + kNumReps)\n    {\n      if (sym >= kSymbolRep)\n      {\n        if (sym != kSymbolRep)\n        {\n          size_t dist = _reps[1];\n          _reps[1] = rep0;\n          rep0 = dist;\n          if (sym >= kSymbolRep + 2)\n          {\n            #if 1\n              rep0 = _reps[(size_t)sym - kSymbolRep];\n              _reps[(size_t)sym - kSymbolRep] = _reps[2];\n              _reps[2] = dist;\n            #else\n              if (sym != kSymbolRep + 2)\n              {\n                rep0 = _reps[3];\n                _reps[3] = _reps[2];\n                _reps[2] = dist;\n              }\n              else\n              {\n                rep0 = _reps[2];\n                _reps[2] = dist;\n              }\n            #endif\n          }\n        }\n#if 0\n        len = m_LenDecoder.Decode(&_bitStream);\n        if (len >= kLenTableSize)\n          LZ_LOOP_BREAK_ERROR\n#else\n        Z7_RAR_HUFF_DECODE_CHECK_break(len, &m_LenDecoder, k_NumHufTableBits_Len, &_bitStream)\n#endif\n        if (len >= 8)\n          len = SlotToLen(_bitStream, len);\n        len += 2;\n        // _lastLen = (UInt32)len;\n      }\n      else if (sym != 256)\n      {\n        len = (CLenType)_lastLen;\n        if (len == 0)\n        {\n          // we ignore (_lastLen == 0) case, like original-unrar.\n          // that case can mean error in stream.\n          // lzError = true;\n          // return S_FALSE;\n          continue;\n        }\n      }\n      else\n      {\n        _exitType = Z7_RAR_EXIT_TYPE_ADD_FILTER;\n        LZ_LOOP_BREAK_OK\n      }\n    }\n#if 0\n    else if (sym >= kMainTableSize)\n      LZ_LOOP_BREAK_ERROR\n#endif\n    else\n    {\n      _reps[3] = _reps[2];\n      _reps[2] = _reps[1];\n      _reps[1] = rep0;\n      len = sym - (kSymbolRep + kNumReps);\n      if (len >= 8)\n        len = SlotToLen(_bitStream, len);\n      len += 2;\n      // _lastLen = (UInt32)len;\n      \n#if 0\n      rep0 = (UInt32)m_DistDecoder.Decode(&_bitStream);\n#else\n      Z7_RAR_HUFF_DECODE_CHECK_break(rep0, &m_DistDecoder, k_NumHufTableBits_Dist, &_bitStream)\n#endif\n\n      if (rep0 >= 4)\n      {\n#if 0\n        if (rep0 >= kDistTableSize_MAX)\n          LZ_LOOP_BREAK_ERROR\n#endif\n        const unsigned numBits = ((unsigned)rep0 - 2) >> 1;\n        rep0 = (2 | (rep0 & 1)) << numBits;\n\n        const Byte *buf = _bitStream._buf;\n#ifdef Z7_RAR5_USE_64BIT\n        const UInt64 v = GetBe64(buf);\n#else\n        const UInt32 v = GetBe32(buf);\n#endif\n\n        // _lastLen = (UInt32)len;\n        if (numBits < kNumAlignBits)\n        {\n          rep0 += // _bitStream.ReadBits9(numBits);\n            _bitStream.ReadBits_Big25(numBits, v);\n        }\n        else\n        {\n          #if !defined(MY_CPU_AMD64)\n            len += k_LenPlusTable[numBits];\n          #elif 0\n            len += k_LenPlusTable_LOC[numBits];\n          #elif 1\n            len += m_LenPlusTable[numBits];\n          #elif 1 && defined(MY_CPU_64BIT) && defined(MY_CPU_AMD64)\n            // len += (unsigned)((UInt64)0xfffffffeaa554000 >> (numBits * 2)) & 3;\n            len += (unsigned)((UInt64)0xfffffffffeaa5540 >> (numBits * 2 - 8)) & 3;\n          #elif 1\n            len += 3;\n            len -= (unsigned)(numBits -  7) >> (sizeof(unsigned) * 8 - 1);\n            len -= (unsigned)(numBits - 12) >> (sizeof(unsigned) * 8 - 1);\n            len -= (unsigned)(numBits - 17) >> (sizeof(unsigned) * 8 - 1);\n          #elif 1\n            len += 3;\n            len -= (0x155aabf >> (numBits - 4) >> (numBits - 4)) & 3;\n          #elif 1\n            len += (numBits >= 7);\n            len += (numBits >= 12);\n            len += (numBits >= 17);\n          #endif\n          // _lastLen = (UInt32)len;\n          if (_useAlignBits)\n          {\n            // if (numBits > kNumAlignBits)\n            rep0 += (_bitStream.ReadBits_Big25(numBits - kNumAlignBits, v) << kNumAlignBits);\n#if 0\n            const unsigned a = m_AlignDecoder.Decode(&_bitStream);\n            if (a >= kAlignTableSize)\n              LZ_LOOP_BREAK_ERROR\n#else\n            unsigned a;\n            Z7_RAR_HUFF_DECODE_CHECK_break(a, &m_AlignDecoder, k_NumHufTableBits_Align, &_bitStream)\n#endif\n            rep0 += a;\n          }\n          else\n            rep0 += _bitStream.ReadBits_Big(numBits, v);\n#ifndef Z7_RAR5_USE_64BIT\n          if (numBits >= 30) // we don't want 32-bit overflow case\n            rep0 = (size_t)0 - 1 - 1;\n#endif\n        }\n      }\n      rep0++;\n    }\n\n    {\n      _lastLen = (UInt32)len;\n      // len != 0\n\n#ifdef Z7_RAR5_SHOW_STAT\n      {\n        size_t index = rep0;\n        if (index >= kNumStats1)\n          index = kNumStats1 - 1;\n        g_stats1[index]++;\n        g_stats2[index][len]++;\n      }\n#endif\n\n      Byte *dest = winPos;\n      winPos += len;\n      if (rep0 <= _dictSize_forCheck)\n      {\n        const Byte *src;\n        const size_t winPos_temp = (size_t)(dest - _window);\n        if (rep0 > winPos_temp)\n        {\n          if (_lzSize == 0)\n            goto error_dist;\n          size_t back = rep0 - winPos_temp;\n          // STAT_INC(g_NumOver)\n          src = dest + (_winSize - rep0);\n          if (back < len)\n          {\n            // len -= (CLenType)back;\n            Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n            do\n              *dest++ = *src++;\n            while (--back);\n            src = dest - rep0;\n          }\n        }\n        else\n          src = dest - rep0;\n        CopyMatch(rep0, dest, src, winPos);\n        continue;\n      }\n\nerror_dist:\n      // LZ_LOOP_BREAK_ERROR;\n      _lzError = LZ_ERROR_TYPE_DIST;\n      do\n        *dest++ = 0;\n      while (dest < winPos);\n      continue;\n    }\n  }\n\n  LZ_RESTORE\n  return S_OK;\n\n#if 1\ndecode_error:\n  /*\n  if (_bitStream._hres != S_OK)\n    return _bitStream._hres;\n  */\n  LZ_RESTORE\n  return S_FALSE;\n#endif\n}\n\n\n\n/*\ninput conditions:\n  _winPos < _winSize\nreturn:\n  _winPos <  _winSize is expected, if (return_res == S_OK)\n  _winPos >= _winSize is possible in (return_res != S_OK)\n*/\nHRESULT CDecoder::DecodeLZ()\n{\n  CBitDecoder _bitStream;\n  _bitStream._stream = _inStream;\n  _bitStream._bufBase = _inputBuf;\n  _bitStream.Init();\n\n  // _reps[*] can be larger than _winSize, if _winSize was reduced in solid stream.\n  size_t winPos = _winPos;\n  Byte *win = _window;\n  size_t limit;\n  {\n    size_t rem = _winSize - winPos;\n    if (rem > kWriteStep)\n        rem = kWriteStep;\n    limit = winPos + rem;\n  }\n  \n  for (;;)\n  {\n    if (winPos >= limit)\n    {\n      _winPos = winPos < _winSize ? winPos : _winSize;\n      // _winPos == min(winPos, _winSize)\n      // we will not write data after _winSize\n      RINOK(WriteBuf())\n      if (_unpackSize_Defined && _writtenFileSize > _unpackSize)\n        break; // return S_FALSE;\n      const size_t wp = _winPos;\n      size_t rem = _winSize - wp;\n      if (rem == 0)\n      {\n        _lzSize += wp;\n        winPos -= wp;\n        // (winPos < kMaxMatchLen < _winSize)\n        // so memmove is not required here\n        if (winPos)\n          memcpy(win, win + _winSize, winPos);\n        limit = _winSize;\n        if (limit >= kWriteStep)\n        {\n          limit = kWriteStep;\n          continue;\n        }\n        rem = _winSize - winPos;\n      }\n      if (rem > kWriteStep)\n          rem = kWriteStep;\n      limit = winPos + rem;\n      continue;\n    }\n\n    // (winPos < limit)\n\n    if (_bitStream._buf >= _bitStream._bufCheck_Block)\n    {\n      _winPos = winPos;\n      if (_bitStream.InputEofError())\n        break; // return S_FALSE;\n      _bitStream.Prepare();\n\n      const UInt64 processed = _bitStream.GetProcessedSize_Round();\n      if (processed >= _bitStream._blockEnd)\n      {\n        if (processed > _bitStream._blockEnd)\n          break; // return S_FALSE;\n        {\n          const unsigned bits7 = _bitStream.GetProcessedBits7();\n          if (bits7 >= _bitStream._blockEndBits7)\n          {\n            if (bits7 > _bitStream._blockEndBits7)\n            {\n#if 1\n              // we ignore thar error as original unrar\n              _bitStream._minorError = true;\n#else\n              break; // return S_FALSE;\n#endif\n            }\n            _bitStream.AlignToByte();\n            // if (!_bitStream.AlignToByte()) break;\n            if (_isLastBlock)\n            {\n              if (_bitStream.InputEofError())\n                break;\n              /*\n              // packSize can be 15 bytes larger for encrypted archive\n              if (_packSize_Defined && _packSize < _bitStream.GetProcessedSize())\n                break;\n              */\n              if (_bitStream._minorError)\n                return S_FALSE;\n              return _bitStream._hres;\n              // break;\n            }\n            RINOK(ReadTables(_bitStream))\n            continue;\n          }\n        }\n      }\n\n      // end of block was not reached.\n      // so we must decode more symbols\n      // that check is not required, but it can help, if there is BUG in another code\n      if (!_tableWasFilled)\n        break; // return S_FALSE;\n    }\n\n    _limit = limit;\n    _winPos = winPos;\n    RINOK(DecodeLZ2(_bitStream))\n    _bitStream._buf = _buf_Res;\n    _bitStream._bitPos = _bitPos_Res;\n\n    winPos = _winPos;\n    if (_exitType == Z7_RAR_EXIT_TYPE_ADD_FILTER)\n    {\n      RINOK(AddFilter(_bitStream))\n      continue;\n    }\n  }\n\n  _winPos = winPos;\n  \n  if (_bitStream._hres != S_OK)\n    return _bitStream._hres;\n\n  return S_FALSE;\n}\n\n\n\nHRESULT CDecoder::CodeReal()\n{\n  _unsupportedFilter = false;\n  _writeError = false;\n  /*\n  if (!_isSolid || !_wasInit)\n  {\n    _wasInit = true;\n    // _lzSize = 0;\n    _lzWritten = 0;\n    _winPos = 0;\n    for (unsigned i = 0; i < kNumReps; i++)\n      _reps[i] = (size_t)0 - 1;\n    _lastLen = 0;\n    _tableWasFilled = false;\n  }\n  */\n  _isLastBlock = false;\n\n  InitFilters();\n\n  _filterEnd = 0;\n  _writtenFileSize = 0;\n  const UInt64 lzSize = _lzSize + _winPos;\n  _lzFileStart = lzSize;\n  _lzWritten = lzSize;\n  \n  HRESULT res = DecodeLZ();\n\n  HRESULT res2 = S_OK;\n  if (!_writeError && res != E_OUTOFMEMORY)\n    res2 = WriteBuf();\n  /*\n  if (res == S_OK)\n    if (InputEofError())\n      res = S_FALSE;\n  */\n  if (res == S_OK)\n  {\n    // _solidAllowed = true;\n    res = res2;\n  }\n  if (res == S_OK && _unpackSize_Defined && _writtenFileSize != _unpackSize)\n    return S_FALSE;\n  return res;\n}\n\n\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  _lzError = LZ_ERROR_TYPE_NO;\n/*\n  if file is soild, but decoding of previous file was not finished,\n  we still try to decode new file.\n  We need correct huffman table at starting block.\n  And rar encoder probably writes huffman table at start block, if file is big.\n  So we have good chance to get correct huffman table in some file after corruption.\n  Also we try to recover window by filling zeros, if previous file\n  was decoded to smaller size than required.\n  But if filling size is big, we do full reset of window instead.\n*/\n  #define Z7_RAR_RECOVER_SOLID_LIMIT (1 << 20)\n  // #define Z7_RAR_RECOVER_SOLID_LIMIT 0 // do not fill zeros\n  {\n    // if (_winPos > 100) _winPos -= 100; // for debug: corruption\n    const UInt64 lzSize = _lzSize + _winPos;\n/*\n    if previous file was decoded with error or for some another cases, then\n        (lzSize > _lzEnd)    is possible\n        (_winPos > _winSize) is possible\n        (_winPos < _winSize + kMaxMatchLen)\n*/\n    if (!_window\n        || !_isSolid\n        || !_wasInit\n        || (lzSize < _lzEnd\n#if Z7_RAR_RECOVER_SOLID_LIMIT != 0\n         && lzSize + Z7_RAR_RECOVER_SOLID_LIMIT < _lzEnd\n#endif\n        ))\n    {\n      if (_isSolid)\n        _lzError = LZ_ERROR_TYPE_HEADER;\n      _lzSize = 0;\n      // _lzEnd = 0;     // it will be set later\n      // _lzWritten = 0; // it will be set later\n      _winPos = 0;\n      for (unsigned i = 0; i < kNumReps; i++)\n        _reps[i] = (size_t)0 - 1;\n      _lastLen = 0;\n      _tableWasFilled = false;\n      _wasInit = true;\n    }\n    else\n    {\n      const size_t ws = _winSize;\n      if (_winPos >= ws)\n      {\n        // we must normalize (_winPos) and data in _window,\n        _winPos -= ws;\n        _lzSize += ws;\n        // (_winPos < kMaxMatchLen < _winSize)\n        // if (_window)\n          memcpy(_window, _window + ws, _winPos); // memmove is not required here\n      }\n\n#if Z7_RAR_RECOVER_SOLID_LIMIT != 0\n      if (lzSize < _lzEnd)\n      {\n#if 0\n        return S_FALSE;\n#else\n        // we can report that recovering was made:\n        // _lzError = LZ_ERROR_TYPE_HEADER;\n        // We write zeros to area after corruption:\n        // if (_window)\n        {\n          UInt64 rem = _lzEnd - lzSize;\n          if (rem >= ws)\n          {\n            My_ZeroMemory(_window, ws);\n            _lzSize = ws;\n            _winPos = 0;\n          }\n          else\n          {\n            // rem < _winSize\n            // _winPos <= ws\n            const size_t cur = ws - _winPos;\n            if (cur <= rem)\n            {\n              rem -= cur;\n              My_ZeroMemory(_window + _winPos, cur);\n              _lzSize = ws;\n              _winPos = 0;\n            }\n            My_ZeroMemory(_window + _winPos, (size_t)rem);\n            _winPos += (size_t)rem;\n          }\n        }\n        // else return S_FALSE;\n#endif\n      }\n    }\n#endif\n  }\n\n  // _winPos < _winSize\n  // we don't want _lzSize overflow\n  if (_lzSize >= DICT_SIZE_MAX)\n      _lzSize  = DICT_SIZE_MAX;\n  _lzEnd = _lzSize + _winPos;\n  // _lzSize <= DICT_SIZE_MAX\n  // _lzEnd  <  DICT_SIZE_MAX + _winSize\n\n  size_t newSize = _dictSize;\n  if (newSize < kWinSize_Min)\n      newSize = kWinSize_Min;\n  \n  _unpackSize = 0;\n  _unpackSize_Defined = (outSize != NULL);\n  if (_unpackSize_Defined)\n    _unpackSize = *outSize;\n  \n  if ((Int64)_unpackSize >= 0)\n    _lzEnd += _unpackSize; // known end after current file\n  else\n    _lzEnd = 0; // unknown end\n  \n  if (_isSolid && _window)\n  {\n    // If dictionary was decreased in solid, we use old dictionary.\n    if (newSize > _dictSize_forCheck)\n    {\n      // If dictionary was increased in solid, we don't want grow.\n      return S_FALSE; // E_OUTOFMEMORY\n    }\n    // (newSize <= _dictSize_forCheck)\n  }\n  else\n  {\n    // !_isSolid || !_window\n    _dictSize_forCheck = newSize;\n    {\n      size_t newSize_small = newSize;\n      const size_t k_Win_AlignSize = 1u << 18;\n      /* here we add (1 << 7) instead of (COPY_CHUNK_SIZE - 1), because\n      we want to get same (_winSize) for different COPY_CHUNK_SIZE values. */\n      // newSize += (COPY_CHUNK_SIZE - 1) + (k_Win_AlignSize - 1); // for debug : we can get smallest (_winSize)\n      newSize += (1 << 7) + k_Win_AlignSize;\n      newSize &= ~(size_t)(k_Win_AlignSize - 1);\n      if (newSize < newSize_small)\n        return E_OUTOFMEMORY;\n    }\n    // (!_isSolid || !_window)\n    const size_t allocSize = newSize + kMaxMatchLen + 64;\n    if (allocSize < newSize)\n      return E_OUTOFMEMORY;\n    if (!_window || allocSize > _winSize_Allocated)\n    {\n      Z7_RAR_FREE_WINDOW\n      _window = NULL;\n      _winSize_Allocated = 0;\n      Byte *win = (Byte *)::BigAlloc(allocSize);\n      if (!win)\n        return E_OUTOFMEMORY;\n      _window = win;\n      _winSize_Allocated = allocSize;\n    }\n    _winSize = newSize;\n  }\n  \n  if (!_inputBuf)\n  {\n    _inputBuf = (Byte *)z7_AlignedAlloc(kInputBufSize + kInputBufferPadZone);\n    if (!_inputBuf)\n      return E_OUTOFMEMORY;\n  }\n  \n  _inStream = inStream;\n  _outStream = outStream;\n  _progress = progress;\n  _progress_Pack = 0;\n  _progress_Unpack = 0;\n  \n  const HRESULT res = CodeReal();\n  \n  if (res != S_OK)\n    return res;\n  // _lzError = LZ_ERROR_TYPE_HEADER; // for debug\n  if (_lzError)\n    return S_FALSE;\n  if (_unsupportedFilter)\n    return E_NOTIMPL;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n{\n  if (size != 2)\n    return E_INVALIDARG;\n  const unsigned pow = data[0];\n  const unsigned b1 = data[1];\n  const unsigned frac = b1 >> 3;\n  // unsigned pow = 15 + 8;\n  // unsigned frac = 1;\n  if (pow + ((frac + 31) >> 5) > MAX_DICT_LOG - 17)\n  // if (frac + (pow << 8) >= ((8 * 2 + 7) << 5) + 8 / 8)\n    return E_NOTIMPL;\n  _dictSize = (size_t)(frac + 32) << (pow + 12);\n  _isSolid = (b1 & 1) != 0;\n  _is_v7   = (b1 & 2) != 0;\n  // printf(\"\\ndict size = %p\\n\", (void *)(size_t)_dictSize);\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/Rar5Decoder.h",
    "content": "﻿// Rar5Decoder.h\n// According to unRAR license, this code may not be used to develop\n// a program that creates RAR archives\n\n#ifndef ZIP7_INC_COMPRESS_RAR5_DECODER_H\n#define ZIP7_INC_COMPRESS_RAR5_DECODER_H\n\n#include \"../../Common/MyBuffer2.h\"\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\n#include \"HuffmanDecoder.h\"\n\nnamespace NCompress {\nnamespace NRar5 {\n\nclass CBitDecoder;\n\nstruct CFilter\n{\n  Byte Type;\n  Byte Channels;\n  UInt32 Size;\n  UInt64 Start;\n};\n\n\nconst unsigned kNumReps = 4;\nconst unsigned kLenTableSize = 11 * 4;\nconst unsigned kMainTableSize = 256 + 1 + 1 + kNumReps + kLenTableSize;\nconst unsigned kExtraDistSymbols_v7 = 16;\nconst unsigned kDistTableSize_v6 = 64;\nconst unsigned kDistTableSize_MAX = 64 + kExtraDistSymbols_v7;\nconst unsigned kNumAlignBits = 4;\nconst unsigned kAlignTableSize = 1 << kNumAlignBits;\n\nconst unsigned kNumHufBits = 15;\n\nconst unsigned k_NumHufTableBits_Main = 10;\nconst unsigned k_NumHufTableBits_Dist = 7;\nconst unsigned k_NumHufTableBits_Len = 7;\nconst unsigned k_NumHufTableBits_Align = 6;\n\nconst unsigned DICT_SIZE_BITS_MAX = 40;\n\nZ7_CLASS_IMP_NOQIB_2(\n  CDecoder\n  , ICompressCoder\n  , ICompressSetDecoderProperties2\n)\n  bool _useAlignBits;\n  bool _isLastBlock;\n  bool _unpackSize_Defined;\n  // bool _packSize_Defined;\n  \n  bool _unsupportedFilter;\n  Byte _lzError;\n  bool _writeError;\n\n  bool _isSolid;\n  // bool _solidAllowed;\n  bool _is_v7;\n  bool _tableWasFilled;\n  bool _wasInit;\n\n  Byte _exitType;\n\n  // Byte _dictSizeLog;\n  size_t _dictSize;\n  Byte *_window;\n  size_t _winPos;\n  size_t _winSize;\n  size_t _dictSize_forCheck;\n  size_t _limit;\n  const Byte *_buf_Res;\n  UInt64 _lzSize;\n  size_t _reps[kNumReps];\n  unsigned _bitPos_Res;\n  UInt32 _lastLen;\n\n  // unsigned _numCorrectDistSymbols;\n  unsigned _numUnusedFilters;\n  unsigned _numFilters;\n\n  UInt64 _lzWritten;\n  UInt64 _lzFileStart;\n  UInt64 _unpackSize;\n  // UInt64 _packSize;\n  UInt64 _lzEnd;\n  UInt64 _writtenFileSize;\n  UInt64 _filterEnd;\n  UInt64 _progress_Pack;\n  UInt64 _progress_Unpack;\n  CAlignedBuffer _filterSrc;\n  CAlignedBuffer _filterDst;\n\n  CFilter *_filters;\n  size_t _winSize_Allocated;\n  ISequentialInStream *_inStream;\n  ISequentialOutStream *_outStream;\n  ICompressProgressInfo *_progress;\n  Byte *_inputBuf;\n\n  NHuffman::CDecoder<kNumHufBits, kMainTableSize,  k_NumHufTableBits_Main>  m_MainDecoder;\n  NHuffman::CDecoder256<kNumHufBits, kDistTableSize_MAX,  k_NumHufTableBits_Dist>  m_DistDecoder;\n  NHuffman::CDecoder256<kNumHufBits, kAlignTableSize,     k_NumHufTableBits_Align> m_AlignDecoder;\n  NHuffman::CDecoder256<kNumHufBits, kLenTableSize,       k_NumHufTableBits_Len>   m_LenDecoder;\n  Byte m_LenPlusTable[DICT_SIZE_BITS_MAX];\n\n  void InitFilters()\n  {\n    _numUnusedFilters = 0;\n    _numFilters = 0;\n  }\n  void DeleteUnusedFilters();\n  HRESULT WriteData(const Byte *data, size_t size);\n  HRESULT ExecuteFilter(const CFilter &f);\n  HRESULT WriteBuf();\n  HRESULT AddFilter(CBitDecoder &_bitStream);\n  HRESULT ReadTables(CBitDecoder &_bitStream);\n  HRESULT DecodeLZ2(const CBitDecoder &_bitStream) throw();\n  HRESULT DecodeLZ();\n  HRESULT CodeReal();\npublic:\n  CDecoder();\n  ~CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/RarCodecsRegister.cpp",
    "content": "﻿// RarCodecsRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"Rar1Decoder.h\"\n#include \"Rar2Decoder.h\"\n#include \"Rar3Decoder.h\"\n#include \"Rar5Decoder.h\"\n\nnamespace NCompress {\n\n#define CREATE_CODEC(x) REGISTER_CODEC_CREATE(CreateCodec ## x, NRar ## x::CDecoder())\n\nCREATE_CODEC(1)\nCREATE_CODEC(2)\nCREATE_CODEC(3)\nCREATE_CODEC(5)\n\n#define RAR_CODEC(x, name) { CreateCodec ## x, NULL, 0x40300 + x, \"Rar\" name, 1, false }\n\nREGISTER_CODECS_VAR\n{\n  RAR_CODEC(1, \"1\"),\n  RAR_CODEC(2, \"2\"),\n  RAR_CODEC(3, \"3\"),\n  RAR_CODEC(5, \"5\"),\n};\n\nREGISTER_CODECS(Rar)\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ShrinkDecoder.cpp",
    "content": "﻿// ShrinkDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/InBuffer.h\"\n#include \"../Common/OutBuffer.h\"\n\n#include \"BitlDecoder.h\"\n#include \"ShrinkDecoder.h\"\n\nnamespace NCompress {\nnamespace NShrink {\n\nstatic const UInt32 kEmpty = 256; // kNumItems;\nstatic const UInt32 kBufferSize = (1 << 18);\nstatic const unsigned kNumMinBits = 9;\n\nHRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)\n{\n  NBitl::CBaseDecoder<CInBuffer> inBuffer;\n  COutBuffer outBuffer;\n\n  if (!inBuffer.Create(kBufferSize))\n    return E_OUTOFMEMORY;\n  if (!outBuffer.Create(kBufferSize))\n    return E_OUTOFMEMORY;\n\n  inBuffer.SetStream(inStream);\n  inBuffer.Init();\n\n  outBuffer.SetStream(outStream);\n  outBuffer.Init();\n\n  {\n    for (unsigned i = 0; i < kNumItems; i++)\n      _parents[i] = kEmpty;\n  }\n\n  UInt64 outPrev = 0, inPrev = 0;\n  unsigned numBits = kNumMinBits;\n  unsigned head = 257;\n  int lastSym = -1;\n  Byte lastChar = 0;\n  bool moreOut = false;\n\n  HRESULT res = S_FALSE;\n\n  for (;;)\n  {\n    _inProcessed = inBuffer.GetProcessedSize();\n    const UInt64 nowPos = outBuffer.GetProcessedSize();\n\n    bool eofCheck = false;\n\n    if (outSize && nowPos >= *outSize)\n    {\n      if (!_fullStreamMode || moreOut)\n      {\n        res = S_OK;\n        break;\n      }\n      eofCheck = true;\n      // Is specSym(=256) allowed after end of stream ?\n      // Do we need to read it here ?\n    }\n\n    if (progress)\n    {\n      if (nowPos - outPrev >= (1 << 20) || _inProcessed - inPrev >= (1 << 20))\n      {\n        outPrev = nowPos;\n        inPrev = _inProcessed;\n        res = progress->SetRatioInfo(&_inProcessed, &nowPos);\n        if (res != SZ_OK)\n        {\n          // break;\n          return res;\n        }\n      }\n    }\n\n    UInt32 sym = inBuffer.ReadBits(numBits);\n\n    if (inBuffer.ExtraBitsWereRead())\n    {\n      res = S_OK;\n      break;\n    }\n    \n    if (sym == 256)\n    {\n      sym = inBuffer.ReadBits(numBits);\n\n      if (inBuffer.ExtraBitsWereRead())\n        break;\n\n      if (sym == 1)\n      {\n        if (numBits >= kNumMaxBits)\n          break;\n        numBits++;\n        continue;\n      }\n      if (sym != 2)\n      {\n        break;\n        // continue; // info-zip just ignores such code\n      }\n      {\n        /*\n        ---------- Free leaf nodes ----------\n        Note : that code can mark _parents[lastSym] as free, and next\n        inserted node will be Orphan in that case.\n        */\n\n        unsigned i;\n        for (i = 256; i < kNumItems; i++)\n          _stack[i] = 0;\n        for (i = 257; i < kNumItems; i++)\n        {\n          unsigned par = _parents[i];\n          if (par != kEmpty)\n            _stack[par] = 1;\n        }\n        for (i = 257; i < kNumItems; i++)\n          if (_stack[i] == 0)\n            _parents[i] = kEmpty;\n        head = 257;\n        continue;\n      }\n    }\n\n    if (eofCheck)\n    {\n      // It's can be error case.\n      // That error can be detected later in (*inSize != _inProcessed) check.\n      res = S_OK;\n      break;\n    }\n\n    bool needPrev = false;\n    if (head < kNumItems && lastSym >= 0)\n    {\n      while (head < kNumItems && _parents[head] != kEmpty)\n        head++;\n      if (head < kNumItems)\n      {\n        /*\n        if (head == lastSym), it updates Orphan to self-linked Orphan and creates two problems:\n            1) we must check _stack[i++] overflow in code that walks tree nodes.\n            2) self-linked node can not be removed. So such self-linked nodes can occupy all _parents items.\n        */\n        needPrev = true;\n        _parents[head] = (UInt16)lastSym;\n        _suffixes[head] = (Byte)lastChar;\n        head++;\n      }\n    }\n\n    lastSym = (int)sym;\n    unsigned cur = sym;\n    unsigned i = 0;\n    \n    while (cur >= 256)\n    {\n      _stack[i++] = _suffixes[cur];\n      cur = _parents[cur];\n      // don't change that code:\n      // Orphan Check and self-linked Orphan check (_stack overflow check);\n      if (cur == kEmpty || i >= kNumItems)\n        break;\n    }\n    \n    if (cur == kEmpty || i >= kNumItems)\n      break;\n\n    _stack[i++] = (Byte)cur;\n    lastChar = (Byte)cur;\n\n    if (needPrev)\n      _suffixes[(size_t)head - 1] = (Byte)cur;\n\n    if (outSize)\n    {\n      const UInt64 limit = *outSize - nowPos;\n      if (i > limit)\n      {\n        moreOut = true;\n        i = (unsigned)limit;\n      }\n    }\n\n    do\n      outBuffer.WriteByte(_stack[--i]);\n    while (i);\n  }\n  \n  RINOK(outBuffer.Flush())\n\n  if (res == S_OK)\n    if (_fullStreamMode)\n    {\n      if (moreOut)\n        res = S_FALSE;\n      const UInt64 nowPos = outBuffer.GetProcessedSize();\n      if (outSize && *outSize != nowPos)\n        res = S_FALSE;\n      if (inSize && *inSize != _inProcessed)\n        res = S_FALSE;\n    }\n  \n  return res;\n}\n\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }\n  // catch(const CInBufferException &e) { return e.ErrorCode; }\n  // catch(const COutBufferException &e) { return e.ErrorCode; }\n  catch(const CSystemException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\n\nZ7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))\n{\n  _fullStreamMode = (finishMode != 0);\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = _inProcessed;\n  return S_OK;\n}\n\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ShrinkDecoder.h",
    "content": "﻿// ShrinkDecoder.h\n\n#ifndef ZIP7_INC_COMPRESS_SHRINK_DECODER_H\n#define ZIP7_INC_COMPRESS_SHRINK_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NShrink {\n\nconst unsigned kNumMaxBits = 13;\nconst unsigned kNumItems = 1 << kNumMaxBits;\n\nZ7_CLASS_IMP_NOQIB_3(\n  CDecoder\n  , ICompressCoder\n  , ICompressSetFinishMode\n  , ICompressGetInStreamProcessedSize\n)\n  bool _fullStreamMode;\n  UInt64 _inProcessed;\n\n  UInt16 _parents[kNumItems];\n  Byte _suffixes[kNumItems];\n  Byte _stack[kNumItems];\n\n  HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n      const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/XpressDecoder.cpp",
    "content": "﻿// XpressDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/RotateDefs.h\"\n\n#include \"HuffmanDecoder.h\"\n#include \"XpressDecoder.h\"\n\n#ifdef MY_CPU_LE_UNALIGN\n  #define Z7_XPRESS_DEC_USE_UNALIGNED_COPY\n#endif\n\n#ifdef Z7_XPRESS_DEC_USE_UNALIGNED_COPY\n\n  #define COPY_CHUNK_SIZE 16\n\n    #define COPY_CHUNK_4_2(dest, src) \\\n    { \\\n      ((UInt32 *)(void *)dest)[0] = ((const UInt32 *)(const void *)src)[0]; \\\n      ((UInt32 *)(void *)dest)[1] = ((const UInt32 *)(const void *)src)[1]; \\\n      src += 4 * 2; \\\n      dest += 4 * 2; \\\n    }\n\n  /* sse2 doesn't help here in GCC and CLANG.\n     so we disabled sse2 here */\n#if 0\n  #if defined(MY_CPU_AMD64)\n    #define Z7_XPRESS_DEC_USE_SSE2\n  #elif defined(MY_CPU_X86)\n    #if defined(_MSC_VER) && _MSC_VER >= 1300 && defined(_M_IX86_FP) && (_M_IX86_FP >= 2) \\\n      || defined(__SSE2__) \\\n      // || 1 == 1  // for debug only\n      #define Z7_XPRESS_DEC_USE_SSE2\n    #endif\n  #endif\n#endif\n\n  #if defined(MY_CPU_ARM64)\n  #include <arm_neon.h>\n    #define COPY_OFFSET_MIN  16\n    #define COPY_CHUNK1(dest, src) \\\n    { \\\n      vst1q_u8((uint8_t *)(void *)dest, \\\n      vld1q_u8((const uint8_t *)(const void *)src)); \\\n      src += 16; \\\n      dest += 16; \\\n    }\n    \n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK1(dest, src) \\\n      if (dest >= dest_lim) break; \\\n      COPY_CHUNK1(dest, src) \\\n    }\n\n  #elif defined(Z7_XPRESS_DEC_USE_SSE2)\n    #include <emmintrin.h> // sse2\n    #define COPY_OFFSET_MIN  16\n\n    #define COPY_CHUNK1(dest, src) \\\n    { \\\n      _mm_storeu_si128((__m128i *)(void *)dest, \\\n      _mm_loadu_si128((const __m128i *)(const void *)src)); \\\n      src += 16; \\\n      dest += 16; \\\n    }\n\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK1(dest, src) \\\n      if (dest >= dest_lim) break; \\\n      COPY_CHUNK1(dest, src) \\\n    }\n\n  #elif defined(MY_CPU_64BIT)\n    #define COPY_OFFSET_MIN  8\n\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      ((UInt64 *)(void *)dest)[0] = ((const UInt64 *)(const void *)src)[0]; \\\n      ((UInt64 *)(void *)dest)[1] = ((const UInt64 *)(const void *)src)[1]; \\\n      src += 8 * 2; \\\n      dest += 8 * 2; \\\n    }\n\n  #else\n    #define COPY_OFFSET_MIN  4\n\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK_4_2(dest, src); \\\n      COPY_CHUNK_4_2(dest, src); \\\n    }\n\n  #endif\n#endif\n\n\n#ifndef COPY_CHUNK_SIZE\n    #define COPY_OFFSET_MIN  4\n    #define COPY_CHUNK_SIZE  8\n    #define COPY_CHUNK_2(dest, src) \\\n    { \\\n      const Byte a0 = src[0]; \\\n      const Byte a1 = src[1]; \\\n      dest[0] = a0; \\\n      dest[1] = a1; \\\n      src += 2; \\\n      dest += 2; \\\n    }\n    #define COPY_CHUNK(dest, src) \\\n    { \\\n      COPY_CHUNK_2(dest, src) \\\n      COPY_CHUNK_2(dest, src) \\\n      COPY_CHUNK_2(dest, src) \\\n      COPY_CHUNK_2(dest, src) \\\n    }\n#endif\n\n\n#define COPY_CHUNKS \\\n{ \\\n  Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE \\\n  do { COPY_CHUNK(dest, src) } \\\n  while (dest < dest_lim); \\\n}\n\n\nstatic\nZ7_FORCE_INLINE\n// Z7_ATTRIB_NO_VECTOR\nvoid CopyMatch_1(Byte *dest, const Byte *dest_lim)\n{\n      const unsigned b0 = dest[-1];\n      {\n#if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY) && (COPY_CHUNK_SIZE == 16)\n        #if defined(MY_CPU_64BIT)\n        {\n          const UInt64 v64 = (UInt64)b0 * 0x0101010101010101;\n          Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n          do\n          {\n            ((UInt64 *)(void *)dest)[0] = v64;\n            ((UInt64 *)(void *)dest)[1] = v64;\n            dest += 16;\n          }\n          while (dest < dest_lim);\n        }\n        #else\n        {\n          UInt32 v = b0;\n          v |= v << 8;\n          v |= v << 16;\n          do\n          {\n            ((UInt32 *)(void *)dest)[0] = v;\n            ((UInt32 *)(void *)dest)[1] = v;\n            dest += 8;\n            ((UInt32 *)(void *)dest)[0] = v;\n            ((UInt32 *)(void *)dest)[1] = v;\n            dest += 8;\n          }\n          while (dest < dest_lim);\n        }\n        #endif\n#else\n        do\n        {\n          dest[0] = (Byte)b0;\n          dest[1] = (Byte)b0;\n          dest += 2;\n          dest[0] = (Byte)b0;\n          dest[1] = (Byte)b0;\n          dest += 2;\n        }\n        while (dest < dest_lim);\n#endif\n      }\n}\n\n\n// (offset != 1)\nstatic\nZ7_FORCE_INLINE\n// Z7_ATTRIB_NO_VECTOR\nvoid CopyMatch_Non1(Byte *dest, size_t offset, const Byte *dest_lim)\n{\n  const Byte *src = dest - offset;\n  {\n    // (COPY_OFFSET_MIN >= 4)\n    if (offset >= COPY_OFFSET_MIN)\n    {\n      COPY_CHUNKS\n      // return;\n    }\n    else\n#if (COPY_OFFSET_MIN > 4)\n    #if COPY_CHUNK_SIZE < 8\n      #error Stop_Compiling_Bad_COPY_CHUNK_SIZE\n    #endif\n    if (offset >= 4)\n    {\n      Z7_PRAGMA_OPT_DISABLE_LOOP_UNROLL_VECTORIZE\n      do\n      {\n        COPY_CHUNK_4_2(dest, src)\n        #if COPY_CHUNK_SIZE != 16\n          if (dest >= dest_lim) break;\n        #endif\n        COPY_CHUNK_4_2(dest, src)\n      }\n      while (dest < dest_lim);\n      // return;\n    }\n    else\n#endif\n    {\n      // (offset < 4)\n      if (offset == 2)\n      {\n#if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY)\n        UInt32 w0 = GetUi16(src);\n        w0 += w0 << 16;\n        do\n        {\n          SetUi32(dest, w0)\n          dest += 4;\n        }\n        while (dest < dest_lim);\n#else\n        const unsigned b0 = src[0];\n        const Byte b1 = src[1];\n        do\n        {\n          dest[0] = (Byte)b0;\n          dest[1] = b1;\n          dest += 2;\n        }\n        while (dest < dest_lim);\n#endif\n      }\n      else // (offset == 3)\n      {\n        const unsigned b0 = src[0];\n#if defined(Z7_XPRESS_DEC_USE_UNALIGNED_COPY)\n        const unsigned w1 = GetUi16(src + 1);\n        do\n        {\n          dest[0] = (Byte)b0;\n          SetUi16(dest + 1, (UInt16)w1)\n          dest += 3;\n        }\n        while (dest < dest_lim);\n#else\n        const Byte b1 = src[1];\n        const Byte b2 = src[2];\n        do\n        {\n          dest[0] = (Byte)b0;\n          dest[1] = b1;\n          dest[2] = b2;\n          dest += 3;\n        }\n        while (dest < dest_lim);\n#endif\n      }\n    }\n  }\n}\n\n\nnamespace NCompress {\nnamespace NXpress {\n\n#define BIT_STREAM_NORMALIZE \\\n    if (BitPos > 16) { \\\n      if (in >= lim) return S_FALSE; \\\n      BitPos -= 16; \\\n      Value |= (UInt32)GetUi16(in) << BitPos; \\\n      in += 2; }\n\n#define MOVE_POS(bs, numBits) \\\n    BitPos += (unsigned)numBits; \\\n    Value <<= numBits; \\\n\n\nstatic const unsigned kNumHuffBits = 15;\nstatic const unsigned kNumTableBits = 10;\nstatic const unsigned kNumLenBits = 4;\nstatic const unsigned kLenMask = (1 << kNumLenBits) - 1;\nstatic const unsigned kNumPosSlots = 16;\nstatic const unsigned kNumSyms = 256 + (kNumPosSlots << kNumLenBits);\n\nHRESULT Decode_WithExceedWrite(const Byte *in, size_t inSize, Byte *out, size_t outSize)\n{\n  NCompress::NHuffman::CDecoder<kNumHuffBits, kNumSyms, kNumTableBits> huff;\n  \n  if (inSize < kNumSyms / 2 + 4)\n    return S_FALSE;\n  {\n    Byte levels[kNumSyms];\n    for (unsigned i = 0; i < kNumSyms / 2; i++)\n    {\n      const unsigned b = in[i];\n      levels[(size_t)i * 2    ] = (Byte)(b & 0xf);\n      levels[(size_t)i * 2 + 1] = (Byte)(b >> 4);\n    }\n    if (!huff.Build(levels, NHuffman::k_BuildMode_Full))\n      return S_FALSE;\n  }\n\n  UInt32 Value;\n  unsigned BitPos;  // how many bits in (Value) were processed\n\n  const Byte *lim = in + inSize - 1;  // points to last byte\n  in += kNumSyms / 2;\n#ifdef MY_CPU_LE_UNALIGN\n  Value = GetUi32(in);\n  Value = rotlFixed(Value, 16);\n#else\n  Value = ((UInt32)GetUi16(in) << 16) | GetUi16(in + 2);\n#endif\n    \n  in += 4;\n  BitPos = 0;\n  Byte *dest = out;\n  const Byte *outLim = out + outSize;\n\n  for (;;)\n  {\n    unsigned sym;\n    Z7_HUFF_DECODE_VAL_IN_HIGH32(sym, &huff, kNumHuffBits, kNumTableBits,\n        Value, Z7_HUFF_DECODE_ERROR_SYM_CHECK_NO, {}, MOVE_POS, {}, bs)\n    // 0 < BitPos <= 31\n    BIT_STREAM_NORMALIZE\n    // 0 < BitPos <= 16\n\n    if (dest >= outLim)\n      return (sym == 256 && Value == 0 && in == lim + 1) ? S_OK : S_FALSE;\n\n    if (sym < 256)\n      *dest++ = (Byte)sym;\n    else\n    {\n      const unsigned distBits = (unsigned)(Byte)sym >> kNumLenBits; // (sym - 256) >> kNumLenBits;\n      UInt32 len = (UInt32)(sym & kLenMask);\n      \n      if (len == kLenMask)\n      {\n        if (in > lim)\n          return S_FALSE;\n        // here we read input bytes in out-of-order related to main input stream (bits in Value):\n        len = *in++;\n        if (len == 0xff)\n        {\n          if (in >= lim)\n            return S_FALSE;\n          len = GetUi16(in);\n          in += 2;\n        }\n        else\n          len += kLenMask;\n      }\n\n      len += 3;\n      if (len > (size_t)(outLim - dest))\n        return S_FALSE;\n\n      if (distBits == 0)\n      {\n        // d == 1\n        if (dest == out)\n          return S_FALSE;\n        Byte *destTemp = dest;\n        dest += len;\n        CopyMatch_1(destTemp, dest);\n      }\n      else\n      {\n        unsigned d = (unsigned)(Value >> (32 - distBits));\n        MOVE_POS(bs, distBits)\n        d += 1u << distBits;\n        // 0 < BitPos <= 31\n        BIT_STREAM_NORMALIZE\n        // 0 < BitPos <= 16\n        if (d > (size_t)(dest - out))\n          return S_FALSE;\n        Byte *destTemp = dest;\n        dest += len;\n        CopyMatch_Non1(destTemp, d, dest);\n      }\n    }\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/XpressDecoder.h",
    "content": "﻿// XpressDecoder.h\n\n#ifndef ZIP7_INC_XPRESS_DECODER_H\n#define ZIP7_INC_XPRESS_DECODER_H\n\n#include \"../../Common/MyTypes.h\"\n\nnamespace NCompress {\nnamespace NXpress {\n\n// (out) buffer size must be larger than (outSize) for the following value:\nconst unsigned kAdditionalOutputBufSize = 32;\n\nHRESULT Decode_WithExceedWrite(const Byte *in, size_t inSize, Byte *out, size_t outSize);\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/XzDecoder.cpp",
    "content": "﻿// XzDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/CWrappers.h\"\n\n#include \"XzDecoder.h\"\n\nnamespace NCompress {\nnamespace NXz {\n\n#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \\\n  if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes;\n\n#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \\\n  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;\n\nstatic HRESULT SResToHRESULT_Code(SRes res) throw()\n{\n  if (res < 0)\n    return res;\n  switch (res)\n  {\n    case SZ_OK: return S_OK;\n    case SZ_ERROR_MEM: return E_OUTOFMEMORY;\n    case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;\n    default: break;\n  }\n  return S_FALSE;\n}\n\n\nHRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,\n    const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress)\n{\n  MainDecodeSRes = SZ_OK;\n  MainDecodeSRes_wasUsed = false;\n  XzStatInfo_Clear(&Stat);\n\n  if (!xz)\n  {\n    xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc);\n    if (!xz)\n      return E_OUTOFMEMORY;\n  }\n\n  CXzDecMtProps props;\n  XzDecMtProps_Init(&props);\n\n  int isMT = False;\n\n  #ifndef Z7_ST\n  {\n    props.numThreads = 1;\n    const UInt32 numThreads = _numThreads;\n\n    if (_tryMt && numThreads > 1)\n    {\n      size_t memUsage = (size_t)_memUsage;\n      if (memUsage != _memUsage)\n        memUsage = (size_t)0 - 1;\n      props.memUseMax = memUsage;\n      isMT = (numThreads > 1);\n    }\n\n    props.numThreads = numThreads;\n  }\n  #endif\n\n  CSeqInStreamWrap inWrap;\n  CSeqOutStreamWrap outWrap;\n  CCompressProgressWrap progressWrap;\n\n  inWrap.Init(seqInStream);\n  outWrap.Init(outStream);\n  progressWrap.Init(progress);\n\n  SRes res = XzDecMt_Decode(xz,\n      &props,\n      outSizeLimit, finishStream,\n      &outWrap.vt,\n      &inWrap.vt,\n      &Stat,\n      &isMT,\n      progress ? &progressWrap.vt : NULL);\n\n  MainDecodeSRes = res;\n\n  #ifndef Z7_ST\n  // _tryMt = isMT;\n  #endif\n\n  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)\n  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)\n  RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ)\n\n  // return E_OUTOFMEMORY; // for debug check\n\n  MainDecodeSRes_wasUsed = true;\n\n  if (res == SZ_OK && finishStream)\n  {\n    /*\n    if (inSize && *inSize != Stat.PhySize)\n      res = SZ_ERROR_DATA;\n    */\n    if (outSizeLimit && *outSizeLimit != outWrap.Processed)\n      res = SZ_ERROR_DATA;\n  }\n\n  return SResToHRESULT_Code(res);\n}\n\n\nZ7_COM7F_IMF(CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  return Decode(inStream, outStream, outSize, _finishStream, progress);\n}\n\nZ7_COM7F_IMF(CComDecoder::SetFinishMode(UInt32 finishMode))\n{\n  _finishStream = (finishMode != 0);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CComDecoder::GetInStreamProcessedSize(UInt64 *value))\n{\n  *value = Stat.InSize;\n  return S_OK;\n}\n\n#ifndef Z7_ST\n\nZ7_COM7F_IMF(CComDecoder::SetNumberOfThreads(UInt32 numThreads))\n{\n  // **************** 7-Zip ZS Modification Start ****************\n  // _numThreads = numThreads;\n  _numThreads = numThreads > 1 ? numThreads : 1;\n  // **************** 7-Zip ZS Modification End ****************\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CComDecoder::SetMemLimit(UInt64 memUsage))\n{\n  _memUsage = memUsage;\n  return S_OK;\n}\n\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/XzDecoder.h",
    "content": "﻿// XzDecoder.h\n\n#ifndef ZIP7_INC_XZ_DECODER_H\n#define ZIP7_INC_XZ_DECODER_H\n\n#include \"../../../C/Xz.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NXz {\n\nstruct CDecoder\n{\n  CXzDecMtHandle xz;\n  int _tryMt;\n  UInt32 _numThreads;\n  UInt64 _memUsage;\n\n  SRes MainDecodeSRes; // it's not HRESULT\n  bool MainDecodeSRes_wasUsed;\n  CXzStatInfo Stat;\n\n  CDecoder():\n      xz(NULL),\n      _tryMt(True),\n      _numThreads(1),\n      _memUsage((UInt64)(sizeof(size_t)) << 28),\n      MainDecodeSRes(SZ_OK),\n      MainDecodeSRes_wasUsed(false)\n    {}\n  \n  ~CDecoder()\n  {\n    if (xz)\n      XzDecMt_Destroy(xz);\n  }\n\n  /* Decode() can return S_OK, if there is data after good xz streams, and that data is not new xz stream.\n     check also (Stat.DataAfterEnd) flag */\n\n  HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,\n      const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress);\n};\n\n\nclass CComDecoder Z7_final:\n  public ICompressCoder,\n  public ICompressSetFinishMode,\n  public ICompressGetInStreamProcessedSize,\n #ifndef Z7_ST\n  public ICompressSetCoderMt,\n  public ICompressSetMemLimit,\n #endif\n  public CMyUnknownImp,\n  public CDecoder\n{\n  Z7_COM_QI_BEGIN2(ICompressCoder)\n  Z7_COM_QI_ENTRY(ICompressSetFinishMode)\n  Z7_COM_QI_ENTRY(ICompressGetInStreamProcessedSize)\n #ifndef Z7_ST\n  Z7_COM_QI_ENTRY(ICompressSetCoderMt)\n  Z7_COM_QI_ENTRY(ICompressSetMemLimit)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressCoder)\n  Z7_IFACE_COM7_IMP(ICompressSetFinishMode)\n  Z7_IFACE_COM7_IMP(ICompressGetInStreamProcessedSize)\n #ifndef Z7_ST\n  Z7_IFACE_COM7_IMP(ICompressSetCoderMt)\n  Z7_IFACE_COM7_IMP(ICompressSetMemLimit)\n #endif\n\n  bool _finishStream;\n\npublic:\n  CComDecoder(): _finishStream(false) {}\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/XzEncoder.cpp",
    "content": "﻿// XzEncoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../../Common/MyString.h\"\n#include \"../../Common/StringToInt.h\"\n\n#include \"../Common/CWrappers.h\"\n#include \"../Common/StreamUtils.h\"\n\n#include \"XzEncoder.h\"\n\nnamespace NCompress {\n\nnamespace NLzma2 {\nHRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);\n}\n\nnamespace NXz {\n\nvoid CEncoder::InitCoderProps()\n{\n  XzProps_Init(&xzProps);\n}\n\nCEncoder::CEncoder()\n{\n  XzProps_Init(&xzProps);\n  _encoder = NULL;\n  _encoder = XzEnc_Create(&g_Alloc, &g_BigAlloc);\n  if (!_encoder)\n    throw 1;\n}\n\nCEncoder::~CEncoder()\n{\n  if (_encoder)\n    XzEnc_Destroy(_encoder);\n}\n\n\nstruct CMethodNamePair\n{\n  UInt32 Id;\n  const char *Name;\n};\n\nstatic const CMethodNamePair g_NamePairs[] =\n{\n  { XZ_ID_Delta, \"Delta\" },\n  { XZ_ID_X86, \"BCJ\" },\n  { XZ_ID_PPC, \"PPC\" },\n  { XZ_ID_IA64, \"IA64\" },\n  { XZ_ID_ARM, \"ARM\" },\n  { XZ_ID_ARMT, \"ARMT\" },\n  { XZ_ID_SPARC, \"SPARC\" }\n  // { XZ_ID_LZMA2, \"LZMA2\" }\n};\n\nstatic int FilterIdFromName(const wchar_t *name)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NamePairs); i++)\n  {\n    const CMethodNamePair &pair = g_NamePairs[i];\n    if (StringsAreEqualNoCase_Ascii(name, pair.Name))\n      return (int)pair.Id;\n  }\n  return -1;\n}\n\n\nHRESULT CEncoder::SetCheckSize(UInt32 checkSizeInBytes)\n{\n  unsigned id;\n  switch (checkSizeInBytes)\n  {\n    case  0: id = XZ_CHECK_NO; break;\n    case  4: id = XZ_CHECK_CRC32; break;\n    case  8: id = XZ_CHECK_CRC64; break;\n    case 32: id = XZ_CHECK_SHA256; break;\n    default: return E_INVALIDARG;\n  }\n  xzProps.checkId = id;\n  return S_OK;\n}\n\n\nHRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)\n{\n  if (propID == NCoderPropID::kNumThreads)\n  {\n    if (prop.vt != VT_UI4)\n      return E_INVALIDARG;\n    // **************** 7-Zip ZS Modification Start ****************\n    // xzProps.numTotalThreads = (int)(prop.ulVal);\n    xzProps.numTotalThreads = ((int)prop.ulVal) > 1 ? (int)prop.ulVal : 1;\n    // **************** 7-Zip ZS Modification End ****************\n    return S_OK;\n  }\n\n  if (propID == NCoderPropID::kCheckSize)\n  {\n    if (prop.vt != VT_UI4)\n      return E_INVALIDARG;\n    return SetCheckSize(prop.ulVal);\n  }\n\n  if (propID == NCoderPropID::kBlockSize2)\n  {\n    if (prop.vt == VT_UI4)\n      xzProps.blockSize = prop.ulVal;\n    else if (prop.vt == VT_UI8)\n      xzProps.blockSize = prop.uhVal.QuadPart;\n    else\n      return E_INVALIDARG;\n    return S_OK;\n  }\n\n  if (propID == NCoderPropID::kReduceSize)\n  {\n    if (prop.vt == VT_UI8)\n      xzProps.reduceSize = prop.uhVal.QuadPart;\n    else\n      return E_INVALIDARG;\n    return S_OK;\n  }\n \n  if (propID == NCoderPropID::kFilter)\n  {\n    if (prop.vt == VT_UI4)\n    {\n      const UInt32 id32 = prop.ulVal;\n      if (id32 == XZ_ID_Delta)\n        return E_INVALIDARG;\n      xzProps.filterProps.id = prop.ulVal;\n    }\n    else\n    {\n      if (prop.vt != VT_BSTR)\n        return E_INVALIDARG;\n      \n      const wchar_t *name = prop.bstrVal;\n      const wchar_t *end;\n\n      UInt32 id32 = ConvertStringToUInt32(name, &end);\n      \n      if (end != name)\n        name = end;\n      else\n      {\n        if (IsString1PrefixedByString2_NoCase_Ascii(name, \"Delta\"))\n        {\n          name += 5; // strlen(\"Delta\");\n          id32 = XZ_ID_Delta;\n        }\n        else\n        {\n          const int filterId = FilterIdFromName(prop.bstrVal);\n          if (filterId < 0 /* || filterId == XZ_ID_LZMA2 */)\n            return E_INVALIDARG;\n          id32 = (UInt32)(unsigned)filterId;\n        }\n      }\n      \n      if (id32 == XZ_ID_Delta)\n      {\n        const wchar_t c = *name;\n        if (c != '-' && c != ':')\n          return E_INVALIDARG;\n        name++;\n        const UInt32 delta = ConvertStringToUInt32(name, &end);\n        if (end == name || *end != 0 || delta == 0 || delta > 256)\n          return E_INVALIDARG;\n        xzProps.filterProps.delta = delta;\n      }\n      \n      xzProps.filterProps.id = id32;\n    }\n    \n    return S_OK;\n  }\n\n  return NLzma2::SetLzma2Prop(propID, prop, xzProps.lzma2Props);\n}\n\n\nZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  XzProps_Init(&xzProps);\n\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    RINOK(SetCoderProp(propIDs[i], coderProps[i]))\n  }\n  \n  return S_OK;\n  // return SResToHRESULT(XzEnc_SetProps(_encoder, &xzProps));\n}\n\n\nZ7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs,\n    const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    const PROPVARIANT &prop = coderProps[i];\n    const PROPID propID = propIDs[i];\n    if (propID == NCoderPropID::kExpectedDataSize)\n      if (prop.vt == VT_UI8)\n        XzEnc_SetDataSize(_encoder, prop.uhVal.QuadPart);\n  }\n  return S_OK;\n}\n\n\n#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \\\n  if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes;\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress))\n{\n  CSeqInStreamWrap inWrap;\n  CSeqOutStreamWrap outWrap;\n  CCompressProgressWrap progressWrap;\n\n  inWrap.Init(inStream);\n  outWrap.Init(outStream);\n  progressWrap.Init(progress);\n\n  SRes res = XzEnc_SetProps(_encoder, &xzProps);\n  if (res == SZ_OK)\n    res = XzEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);\n\n  // SRes res = Xz_Encode(&outWrap.vt, &inWrap.vt, &xzProps, progress ? &progressWrap.vt : NULL);\n\n  RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ)\n  RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE)\n  RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS)\n\n  return SResToHRESULT(res);\n}\n  \n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/XzEncoder.h",
    "content": "﻿// XzEncoder.h\n\n#ifndef ZIP7_INC_XZ_ENCODER_H\n#define ZIP7_INC_XZ_ENCODER_H\n\n#include \"../../../C/XzEnc.h\"\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NXz {\n\nZ7_CLASS_IMP_COM_3(\n  CEncoder\n  , ICompressCoder\n  , ICompressSetCoderProperties\n  , ICompressSetCoderPropertiesOpt\n)\n  CXzEncHandle _encoder;\npublic:\n  CXzProps xzProps;\n\n  void InitCoderProps();\n  HRESULT SetCheckSize(UInt32 checkSizeInBytes);\n  HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop);\n\n  CEncoder();\n  ~CEncoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ZDecoder.cpp",
    "content": "﻿// ZDecoder.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"../../../C/Alloc.h\"\n\n#include \"../Common/InBuffer.h\"\n#include \"../Common/OutBuffer.h\"\n\n#include \"ZDecoder.h\"\n\nnamespace NCompress {\nnamespace NZ {\n\nstatic const size_t kBufferSize = 1 << 20;\nstatic const Byte kNumBitsMask = 0x1F;\nstatic const Byte kBlockModeMask = 0x80;\nstatic const unsigned kNumMinBits = 9;\nstatic const unsigned kNumMaxBits = 16;\n\nvoid CDecoder::Free()\n{\n  MyFree(_parents); _parents = NULL;\n  MyFree(_suffixes); _suffixes = NULL;\n  MyFree(_stack); _stack = NULL;\n}\n\nCDecoder::~CDecoder() { Free(); }\n\nHRESULT CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    ICompressProgressInfo *progress)\n{\n  try {\n  // PackSize = 0;\n\n  CInBuffer inBuffer;\n  COutBuffer outBuffer;\n\n  if (!inBuffer.Create(kBufferSize))\n    return E_OUTOFMEMORY;\n  inBuffer.SetStream(inStream);\n  inBuffer.Init();\n\n  if (!outBuffer.Create(kBufferSize))\n    return E_OUTOFMEMORY;\n  outBuffer.SetStream(outStream);\n  outBuffer.Init();\n\n  Byte buf[kNumMaxBits + 4];\n  {\n    if (inBuffer.ReadBytes(buf, 3) < 3)\n      return S_FALSE;\n    if (buf[0] != 0x1F || buf[1] != 0x9D)\n      return S_FALSE;\n  }\n  const Byte prop = buf[2];\n\n  if ((prop & 0x60) != 0)\n    return S_FALSE;\n  const unsigned maxbits = prop & kNumBitsMask;\n  if (maxbits < kNumMinBits || maxbits > kNumMaxBits)\n    return S_FALSE;\n  const UInt32 numItems = (UInt32)1 << maxbits;\n  // Speed optimization: blockSymbol can contain unused velue.\n\n  if (maxbits != _numMaxBits || !_parents || !_suffixes || !_stack)\n  {\n    Free();\n    _parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16)); if (!_parents) return E_OUTOFMEMORY;\n    _suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (!_suffixes) return E_OUTOFMEMORY;\n    _stack = (Byte *)MyAlloc(numItems * sizeof(Byte)); if (!_stack) return E_OUTOFMEMORY;\n    _numMaxBits = maxbits;\n  }\n\n  UInt64 prevPos = 0;\n  const UInt32 blockSymbol = ((prop & kBlockModeMask) != 0) ? 256 : ((UInt32)1 << kNumMaxBits);\n  unsigned numBits = kNumMinBits;\n  UInt32 head = (blockSymbol == 256) ? 257 : 256;\n  bool needPrev = false;\n  unsigned bitPos = 0;\n  unsigned numBufBits = 0;\n\n  _parents[256] = 0; // virus protection\n  _suffixes[256] = 0;\n  HRESULT res = S_OK;\n\n  for (;;)\n  {\n    if (numBufBits == bitPos)\n    {\n      numBufBits = (unsigned)inBuffer.ReadBytes(buf, numBits) * 8;\n      bitPos = 0;\n      const UInt64 nowPos = outBuffer.GetProcessedSize();\n      if (progress && nowPos - prevPos >= (1 << 13))\n      {\n        prevPos = nowPos;\n        const UInt64 packSize = inBuffer.GetProcessedSize();\n        RINOK(progress->SetRatioInfo(&packSize, &nowPos))\n      }\n    }\n    const unsigned bytePos = bitPos >> 3;\n    UInt32 symbol = buf[bytePos] | ((UInt32)buf[(size_t)bytePos + 1] << 8) | ((UInt32)buf[(size_t)bytePos + 2] << 16);\n    symbol >>= (bitPos & 7);\n    symbol &= ((UInt32)1 << numBits) - 1;\n    bitPos += numBits;\n    if (bitPos > numBufBits)\n      break;\n    if (symbol >= head)\n    {\n      res = S_FALSE;\n      break;\n    }\n    if (symbol == blockSymbol)\n    {\n      numBufBits = bitPos = 0;\n      numBits = kNumMinBits;\n      head = 257;\n      needPrev = false;\n      continue;\n    }\n    UInt32 cur = symbol;\n    unsigned i = 0;\n    while (cur >= 256)\n    {\n      _stack[i++] = _suffixes[cur];\n      cur = _parents[cur];\n    }\n    _stack[i++] = (Byte)cur;\n    if (needPrev)\n    {\n      _suffixes[(size_t)head - 1] = (Byte)cur;\n      if (symbol == head - 1)\n        _stack[0] = (Byte)cur;\n    }\n    do\n      outBuffer.WriteByte((_stack[--i]));\n    while (i > 0);\n    if (head < numItems)\n    {\n      needPrev = true;\n      _parents[head++] = (UInt16)symbol;\n      if (head > ((UInt32)1 << numBits))\n      {\n        if (numBits < maxbits)\n        {\n          numBufBits = bitPos = 0;\n          numBits++;\n        }\n      }\n    }\n    else\n      needPrev = false;\n  }\n  // PackSize = inBuffer.GetProcessedSize();\n  const HRESULT res2 = outBuffer.Flush();\n  return (res == S_OK) ? res2 : res;\n \n  }\n  catch(const CInBufferException &e) { return e.ErrorCode; }\n  catch(const COutBufferException &e) { return e.ErrorCode; }\n  catch(...) { return S_FALSE; }\n}\n\n\nbool CheckStream(const Byte *data, size_t size)\n{\n  if (size < 3)\n    return false;\n  if (data[0] != 0x1F || data[1] != 0x9D)\n    return false;\n  const Byte prop = data[2];\n  if ((prop & 0x60) != 0)\n    return false;\n  const unsigned maxbits = prop & kNumBitsMask;\n  if (maxbits < kNumMinBits || maxbits > kNumMaxBits)\n    return false;\n  const UInt32 numItems = (UInt32)1 << maxbits;\n  const UInt32 blockSymbol = ((prop & kBlockModeMask) != 0) ? 256 : ((UInt32)1 << kNumMaxBits);\n  unsigned numBits = kNumMinBits;\n  UInt32 head = (blockSymbol == 256) ? 257 : 256;\n  unsigned bitPos = 0;\n  unsigned numBufBits = 0;\n  Byte buf[kNumMaxBits + 4];\n  data += 3;\n  size -= 3;\n  // printf(\"\\n\\n\");\n  for (;;)\n  {\n    if (numBufBits == bitPos)\n    {\n      const unsigned num = (numBits < size) ? numBits : (unsigned)size;\n      memcpy(buf, data, num);\n      data += num;\n      size -= num;\n      numBufBits = num * 8;\n      bitPos = 0;\n    }\n    const unsigned bytePos = bitPos >> 3;\n    UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16);\n    symbol >>= (bitPos & 7);\n    symbol &= ((UInt32)1 << numBits) - 1;\n    bitPos += numBits;\n    if (bitPos > numBufBits)\n    {\n      // printf(\"  OK\", symbol);\n      return true;\n    }\n    // printf(\"%3X \", symbol);\n    if (symbol >= head)\n      return false;\n    if (symbol == blockSymbol)\n    {\n      numBufBits = bitPos = 0;\n      numBits = kNumMinBits;\n      head = 257;\n      continue;\n    }\n    if (head < numItems)\n    {\n      head++;\n      if (head > ((UInt32)1 << numBits))\n      {\n        if (numBits < maxbits)\n        {\n          numBufBits = bitPos = 0;\n          numBits++;\n        }\n      }\n    }\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ZDecoder.h",
    "content": "﻿// ZDecoder.h\n\n#ifndef ZIP7_INC_COMPRESS_Z_DECODER_H\n#define ZIP7_INC_COMPRESS_Z_DECODER_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCompress {\nnamespace NZ {\n\n// Z decoder decodes Z data stream, including 3 bytes of header.\n  \nclass CDecoder\n{\n  UInt16 *_parents;\n  Byte *_suffixes;\n  Byte *_stack;\n  unsigned _numMaxBits;\n\npublic:\n  CDecoder(): _parents(NULL), _suffixes(NULL), _stack(NULL), /* _prop(0), */ _numMaxBits(0) {}\n  ~CDecoder();\n  void Free();\n  // UInt64 PackSize;\n\n  HRESULT Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    ICompressProgressInfo *progress);\n};\n\n/*\n  There is no end_of_payload_marker in Z stream.\n  Z decoder stops decoding, if it reaches end of input stream.\n   \n  CheckStream function:\n    (size) must be at least 3 bytes (size of Z header).\n    if (size) is larger than size of real Z stream in (data), CheckStream can return false.\n*/\n\nconst unsigned kRecommendedCheckSize = 64;\n\nbool CheckStream(const Byte *data, size_t size);\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ZlibDecoder.cpp",
    "content": "﻿// ZlibDecoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"ZlibDecoder.h\"\n\nnamespace NCompress {\nnamespace NZlib {\n\n#define DEFLATE_TRY_BEGIN try {\n#define DEFLATE_TRY_END } catch(...) { return S_FALSE; }\n\n#define ADLER_MOD 65521\n#define ADLER_LOOP_MAX 5550\n\nUInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size);\nUInt32 Adler32_Update(UInt32 adler, const Byte *data, size_t size)\n{\n  if (size == 0)\n    return adler;\n  UInt32 a = adler & 0xffff;\n  UInt32 b = adler >> 16;\n  do\n  {\n    size_t cur = size;\n    if (cur > ADLER_LOOP_MAX)\n        cur = ADLER_LOOP_MAX;\n    size -= cur;\n    const Byte *lim = data + cur;\n    if (cur >= 4)\n    {\n      lim -= 4 - 1;\n      do\n      {\n        a += data[0];  b += a;\n        a += data[1];  b += a;\n        a += data[2];  b += a;\n        a += data[3];  b += a;\n        data += 4;\n      }\n      while (data < lim);\n      lim += 4 - 1;\n    }\n    if (data != lim) { a += *data++;  b += a;\n    if (data != lim) { a += *data++;  b += a;\n    if (data != lim) { a += *data++;  b += a; }}}\n    a %= ADLER_MOD;\n    b %= ADLER_MOD;\n  }\n  while (size);\n  return (b << 16) + a;\n}\n\nZ7_COM7F_IMF(COutStreamWithAdler::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  _adler = Adler32_Update(_adler, (const Byte *)data, size);\n  _size += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\nZ7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))\n{\n  DEFLATE_TRY_BEGIN\n  _inputProcessedSize_Additional = 0;\n  AdlerStream.Create_if_Empty();\n  DeflateDecoder.Create_if_Empty();\n  DeflateDecoder->Set_NeedFinishInput(true);\n\n  if (inSize && *inSize < 2)\n    return S_FALSE;\n  {\n    Byte buf[2];\n    RINOK(ReadStream_FALSE(inStream, buf, 2))\n    if (!IsZlib(buf))\n      return S_FALSE;\n  }\n  _inputProcessedSize_Additional = 2;\n  AdlerStream->SetStream(outStream);\n  AdlerStream->Init();\n  // NDeflate::NDecoder::Code() ignores inSize\n  /*\n  UInt64 inSize2 = 0;\n  if (inSize)\n    inSize2 = *inSize - 2;\n  */\n  const HRESULT res = DeflateDecoder.Interface()->Code(inStream, AdlerStream,\n      /* inSize ? &inSize2 : */ NULL, outSize, progress);\n  AdlerStream->ReleaseStream();\n\n  if (res == S_OK)\n  {\n    UInt32 footer32[1];\n    UInt32 processedSize;\n    RINOK(DeflateDecoder->ReadUnusedFromInBuf(footer32, 4, &processedSize))\n    if (processedSize != 4)\n    {\n      size_t processedSize2 = 4 - processedSize;\n      RINOK(ReadStream(inStream, (Byte *)(void *)footer32 + processedSize, &processedSize2))\n      _inputProcessedSize_Additional += (Int32)processedSize2;\n      processedSize += (UInt32)processedSize2;\n    }\n    \n    if (processedSize == 4)\n    {\n      const UInt32 adler = GetBe32a(footer32);\n      if (adler != AdlerStream->GetAdler())\n        return S_FALSE; // adler error\n    }\n    else if (!IsAdlerOptional)\n      return S_FALSE; // unexpeced end of stream (can't read adler)\n    else\n    {\n      // IsAdlerOptional == true\n      if (processedSize != 0)\n      {\n         // we exclude adler bytes from processed size:\n        _inputProcessedSize_Additional -= (Int32)processedSize;\n        return S_FALSE;\n      }\n    }\n  }\n  return res;\n  DEFLATE_TRY_END\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ZlibDecoder.h",
    "content": "﻿// ZlibDecoder.h\n\n#ifndef ZIP7_INC_ZLIB_DECODER_H\n#define ZIP7_INC_ZLIB_DECODER_H\n\n#include \"DeflateDecoder.h\"\n\nnamespace NCompress {\nnamespace NZlib {\n\nconst UInt32 ADLER_INIT_VAL = 1;\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithAdler\n  , ISequentialOutStream\n)\n  UInt32 _adler;\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\npublic:\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init() { _adler = ADLER_INIT_VAL; _size = 0; }\n  UInt32 GetAdler() const { return _adler; }\n  UInt64 GetSize() const { return _size; }\n};\n\nZ7_CLASS_IMP_NOQIB_1(\n  CDecoder\n  , ICompressCoder\n)\n  CMyComPtr2<ISequentialOutStream, COutStreamWithAdler> AdlerStream;\n  CMyComPtr2<ICompressCoder, NDeflate::NDecoder::CCOMCoder> DeflateDecoder;\n  Int32 _inputProcessedSize_Additional;\npublic:\n  bool IsAdlerOptional;\n  \n  CDecoder(): IsAdlerOptional(false) {}\n  UInt64 GetInputProcessedSize() const\n  {\n    return (UInt64)(\n      (Int64)DeflateDecoder->GetInputProcessedSize() +\n      (Int64)_inputProcessedSize_Additional);\n  }\n  UInt64 GetOutputProcessedSize() const { return AdlerStream->GetSize(); }\n};\n\nstatic bool inline IsZlib(const Byte *p)\n{\n  if ((p[0] & 0xF) != 8) // method\n    return false;\n  if (((unsigned)p[0] >> 4) > 7) // logar_window_size minus 8.\n    return false;\n  if ((p[1] & 0x20) != 0) // dictPresent\n    return false;\n  if ((((UInt32)p[0] << 8) + p[1]) % 31 != 0)\n    return false;\n  return true;\n}\n\n// IsZlib_3bytes checks 2 bytes of zlib header and starting byte of Deflate stream\n\nstatic bool inline IsZlib_3bytes(const Byte *p)\n{\n  if (!IsZlib(p))\n    return false;\n  const unsigned val = p[2];\n  const unsigned blockType = (val >> 1) & 0x3;\n  if (blockType == 3) // unsupported block type for deflate\n    return false;\n  if (blockType == NCompress::NDeflate::NBlockType::kStored && (val >> 3) != 0)\n    return false;\n  return true;\n}\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ZlibEncoder.cpp",
    "content": "﻿// ZlibEncoder.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"ZlibEncoder.h\"\n\nnamespace NCompress {\nnamespace NZlib {\n\n#define DEFLATE_TRY_BEGIN try {\n#define DEFLATE_TRY_END } catch(...) { return S_FALSE; }\n\nUInt32 Adler32_Update(UInt32 adler, const Byte *buf, size_t size);\n\nZ7_COM7F_IMF(CInStreamWithAdler::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  const HRESULT result = _stream->Read(data, size, &size);\n  _adler = Adler32_Update(_adler, (const Byte *)data, size);\n  _size += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\nvoid CEncoder::Create()\n{\n  if (!DeflateEncoder)\n    DeflateEncoder = DeflateEncoderSpec = new NDeflate::NEncoder::CCOMCoder;\n}\n\nZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,\n    const UInt64 *inSize, const UInt64 * /* outSize */, ICompressProgressInfo *progress))\n{\n  DEFLATE_TRY_BEGIN\n  if (!AdlerStream)\n    AdlerStream = AdlerSpec = new CInStreamWithAdler;\n  Create();\n\n  {\n    Byte buf[2] = { 0x78, 0xDA };\n    RINOK(WriteStream(outStream, buf, 2))\n  }\n\n  AdlerSpec->SetStream(inStream);\n  AdlerSpec->Init();\n  const HRESULT res = DeflateEncoder->Code(AdlerStream, outStream, inSize, NULL, progress);\n  AdlerSpec->ReleaseStream();\n\n  RINOK(res)\n\n  {\n    const UInt32 a = AdlerSpec->GetAdler();\n    const Byte buf[4] = { (Byte)(a >> 24), (Byte)(a >> 16), (Byte)(a >> 8), (Byte)(a) };\n    return WriteStream(outStream, buf, 4);\n  }\n  DEFLATE_TRY_END\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Compress/ZlibEncoder.h",
    "content": "﻿// ZlibEncoder.h\n\n#ifndef ZIP7_INC_ZLIB_ENCODER_H\n#define ZIP7_INC_ZLIB_ENCODER_H\n\n#include \"DeflateEncoder.h\"\n\nnamespace NCompress {\nnamespace NZlib {\n\nZ7_CLASS_IMP_NOQIB_1(\n  CInStreamWithAdler\n  , ISequentialInStream\n)\n  CMyComPtr<ISequentialInStream> _stream;\n  UInt32 _adler;\n  UInt64 _size;\npublic:\n  void SetStream(ISequentialInStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init() { _adler = 1; _size = 0; } // ADLER_INIT_VAL\n  UInt32 GetAdler() const { return _adler; }\n  UInt64 GetSize() const { return _size; }\n};\n\nZ7_CLASS_IMP_NOQIB_1(\n  CEncoder\n  , ICompressCoder\n)\n  CInStreamWithAdler *AdlerSpec;\n  CMyComPtr<ISequentialInStream> AdlerStream;\n  CMyComPtr<ICompressCoder> DeflateEncoder;\npublic:\n  NCompress::NDeflate::NEncoder::CCOMCoder *DeflateEncoderSpec;\n  \n  void Create();\n  UInt64 GetInputProcessedSize() const { return AdlerSpec->GetSize(); }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/7zAes.cpp",
    "content": "﻿// 7zAes.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/Sha256.h\"\n\n#include \"../../Common/ComTry.h\"\n#include \"../../Common/MyBuffer2.h\"\n\n#ifndef Z7_ST\n#include \"../../Windows/Synchronization.h\"\n#endif\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"7zAes.h\"\n#include \"MyAes.h\"\n\n#ifndef Z7_EXTRACT_ONLY\n#include \"RandGen.h\"\n#endif\n\nnamespace NCrypto {\nnamespace N7z {\n\nstatic const unsigned k_NumCyclesPower_Supported_MAX = 24;\n\nbool CKeyInfo::IsEqualTo(const CKeyInfo &a) const\n{\n  if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)\n    return false;\n  for (unsigned i = 0; i < SaltSize; i++)\n    if (Salt[i] != a.Salt[i])\n      return false;\n  return (Password == a.Password);\n}\n\nvoid CKeyInfo::CalcKey()\n{\n  if (NumCyclesPower == 0x3F)\n  {\n    unsigned pos;\n    for (pos = 0; pos < SaltSize; pos++)\n      Key[pos] = Salt[pos];\n    for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++)\n      Key[pos++] = Password[i];\n    for (; pos < kKeySize; pos++)\n      Key[pos] = 0;\n  }\n  else\n  {\n    const unsigned kUnrPow = 6;\n    const UInt32 numUnroll = (UInt32)1 << (NumCyclesPower <= kUnrPow ? (unsigned)NumCyclesPower : kUnrPow);\n\n    const size_t bufSize = 8 + SaltSize + Password.Size();\n    const size_t unrollSize = bufSize * numUnroll;\n\n    // MY_ALIGN (16)\n    // CSha256 sha;\n    const size_t shaAllocSize = sizeof(CSha256) + unrollSize + bufSize * 2;\n    CAlignedBuffer1 sha(shaAllocSize);\n    Byte *buf = sha + sizeof(CSha256);\n\n    memcpy(buf, Salt, SaltSize);\n    memcpy(buf + SaltSize, Password, Password.Size());\n    memset(buf + bufSize - 8, 0, 8);\n    \n    Sha256_Init((CSha256 *)(void *)(Byte *)sha);\n    \n    {\n      {\n        Byte *dest = buf;\n        for (UInt32 i = 1; i < numUnroll; i++)\n        {\n          dest += bufSize;\n          memcpy(dest, buf, bufSize);\n        }\n      }\n\n      const UInt32 numRounds = (UInt32)1 << NumCyclesPower;\n      UInt32 r = 0;\n      do\n      {\n        Byte *dest = buf + bufSize - 8;\n        UInt32 i = r;\n        r += numUnroll;\n        do\n        {\n          SetUi32(dest, i)  i++; dest += bufSize;\n          // SetUi32(dest, i)  i++; dest += bufSize;\n        }\n        while (i < r);\n        Sha256_Update((CSha256 *)(void *)(Byte *)sha, buf, unrollSize);\n      }\n      while (r < numRounds);\n    }\n    /*\n    UInt64 numRounds = (UInt64)1 << NumCyclesPower;\n\n    do\n    {\n      Sha256_Update((CSha256 *)(Byte *)sha, buf, bufSize);\n      for (unsigned i = 0; i < 8; i++)\n        if (++(ctr[i]) != 0)\n          break;\n    }\n    while (--numRounds != 0);\n    */\n\n    Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key);\n    memset(sha, 0, shaAllocSize);\n  }\n}\n\nbool CKeyInfoCache::GetKey(CKeyInfo &key)\n{\n  FOR_VECTOR (i, Keys)\n  {\n    const CKeyInfo &cached = Keys[i];\n    if (key.IsEqualTo(cached))\n    {\n      for (unsigned j = 0; j < kKeySize; j++)\n        key.Key[j] = cached.Key[j];\n      if (i != 0)\n        Keys.MoveToFront(i);\n      return true;\n    }\n  }\n  return false;\n}\n\nvoid CKeyInfoCache::FindAndAdd(const CKeyInfo &key)\n{\n  FOR_VECTOR (i, Keys)\n  {\n    const CKeyInfo &cached = Keys[i];\n    if (key.IsEqualTo(cached))\n    {\n      if (i != 0)\n        Keys.MoveToFront(i);\n      return;\n    }\n  }\n  Add(key);\n}\n\nvoid CKeyInfoCache::Add(const CKeyInfo &key)\n{\n  if (Keys.Size() >= Size)\n    Keys.DeleteBack();\n  Keys.Insert(0, key);\n}\n\nstatic CKeyInfoCache g_GlobalKeyCache(32);\n\n#ifndef Z7_ST\n  static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;\n  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);\n#else\n  #define MT_LOCK\n#endif\n\nCBase::CBase():\n  _cachedKeys(16),\n  _ivSize(0)\n{\n  for (unsigned i = 0; i < sizeof(_iv); i++)\n    _iv[i] = 0;\n}\n\nvoid CBase::PrepareKey()\n{\n  // BCJ2 threads use same password. So we use long lock.\n  MT_LOCK\n  \n  bool finded = false;\n  if (!_cachedKeys.GetKey(_key))\n  {\n    finded = g_GlobalKeyCache.GetKey(_key);\n    if (!finded)\n      _key.CalcKey();\n    _cachedKeys.Add(_key);\n  }\n  if (!finded)\n    g_GlobalKeyCache.FindAndAdd(_key);\n}\n\n#ifndef Z7_EXTRACT_ONLY\n\n/*\nZ7_COM7F_IMF(CEncoder::ResetSalt())\n{\n  _key.SaltSize = 4;\n  g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);\n  return S_OK;\n}\n*/\n\nZ7_COM7F_IMF(CEncoder::ResetInitVector())\n{\n  for (unsigned i = 0; i < sizeof(_iv); i++)\n    _iv[i] = 0;\n  _ivSize = 16;\n  MY_RAND_GEN(_iv, _ivSize);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream))\n{\n  Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)];\n  unsigned propsSize = 1;\n\n  props[0] = (Byte)(_key.NumCyclesPower\n      | (_key.SaltSize == 0 ? 0 : (1 << 7))\n      | (_ivSize       == 0 ? 0 : (1 << 6)));\n\n  if (_key.SaltSize != 0 || _ivSize != 0)\n  {\n    props[1] = (Byte)(\n        ((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4)\n        | (_ivSize      == 0 ? 0 : _ivSize - 1));\n    memcpy(props + 2, _key.Salt, _key.SaltSize);\n    propsSize = 2 + _key.SaltSize;\n    memcpy(props + propsSize, _iv, _ivSize);\n    propsSize += _ivSize;\n  }\n\n  return WriteStream(outStream, props, propsSize);\n}\n\nCEncoder::CEncoder()\n{\n  // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);\n  // _key.NumCyclesPower = 0x3F;\n  _key.NumCyclesPower = 19;\n  _aesFilter = new CAesCbcEncoder(kKeySize);\n}\n\n#endif\n\nCDecoder::CDecoder()\n{\n  _aesFilter = new CAesCbcDecoder(kKeySize);\n}\n\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n{\n  _key.ClearProps();\n \n  _ivSize = 0;\n  unsigned i;\n  for (i = 0; i < sizeof(_iv); i++)\n    _iv[i] = 0;\n  \n  if (size == 0)\n    return S_OK;\n  \n  const unsigned b0 = data[0];\n  _key.NumCyclesPower = b0 & 0x3F;\n  if ((b0 & 0xC0) == 0)\n    return size == 1 ? S_OK : E_INVALIDARG;\n  if (size <= 1)\n    return E_INVALIDARG;\n\n  const unsigned b1 = data[1];\n  const unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);\n  const unsigned ivSize   = ((b0 >> 6) & 1) + (b1 & 0x0F);\n  \n  if (size != 2 + saltSize + ivSize)\n    return E_INVALIDARG;\n  _key.SaltSize = saltSize;\n  data += 2;\n  for (i = 0; i < saltSize; i++)\n    _key.Salt[i] = *data++;\n  for (i = 0; i < ivSize; i++)\n    _iv[i] = *data++;\n  return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX\n      || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL;\n}\n\n\nZ7_COM7F_IMF(CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size))\n{\n  COM_TRY_BEGIN\n  \n  _key.Password.Wipe();\n  _key.Password.CopyFrom(data, (size_t)size);\n  return S_OK;\n  \n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CBaseCoder::Init())\n{\n  COM_TRY_BEGIN\n  \n  PrepareKey();\n  CMyComPtr<ICryptoProperties> cp;\n  RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp))\n  if (!cp)\n    return E_FAIL;\n  RINOK(cp->SetKey(_key.Key, kKeySize))\n  RINOK(cp->SetInitVector(_iv, sizeof(_iv)))\n  return _aesFilter->Init();\n  \n  COM_TRY_END\n}\n\nZ7_COM7F_IMF2(UInt32, CBaseCoder::Filter(Byte *data, UInt32 size))\n{\n  return _aesFilter->Filter(data, size);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/7zAes.h",
    "content": "﻿// 7zAes.h\n\n#ifndef ZIP7_INC_CRYPTO_7Z_AES_H\n#define ZIP7_INC_CRYPTO_7Z_AES_H\n\n#include \"../../Common/MyBuffer.h\"\n#include \"../../Common/MyCom.h\"\n#include \"../../Common/MyVector.h\"\n\n#include \"../ICoder.h\"\n#include \"../IPassword.h\"\n\nnamespace NCrypto {\nnamespace N7z {\n\nconst unsigned kKeySize = 32;\nconst unsigned kSaltSizeMax = 16;\nconst unsigned kIvSizeMax = 16; // AES_BLOCK_SIZE;\n\nclass CKeyInfo\n{\npublic:\n  unsigned NumCyclesPower;\n  unsigned SaltSize;\n  Byte Salt[kSaltSizeMax];\n  CByteBuffer Password;\n  Byte Key[kKeySize];\n\n  bool IsEqualTo(const CKeyInfo &a) const;\n  void CalcKey();\n\n  CKeyInfo() { ClearProps(); }\n  void ClearProps()\n  {\n    NumCyclesPower = 0;\n    SaltSize = 0;\n    for (unsigned i = 0; i < sizeof(Salt); i++)\n      Salt[i] = 0;\n  }\n\n  void Wipe()\n  {\n    Password.Wipe();\n    NumCyclesPower = 0;\n    SaltSize = 0;\n    Z7_memset_0_ARRAY(Salt);\n    Z7_memset_0_ARRAY(Key);\n  }\n\n#ifdef Z7_CPP_IS_SUPPORTED_default\n  CKeyInfo(const CKeyInfo &) = default;\n#endif\n  ~CKeyInfo() { Wipe(); }\n};\n\nclass CKeyInfoCache\n{\n  unsigned Size;\n  CObjectVector<CKeyInfo> Keys;\npublic:\n  CKeyInfoCache(unsigned size): Size(size) {}\n  bool GetKey(CKeyInfo &key);\n  void Add(const CKeyInfo &key);\n  void FindAndAdd(const CKeyInfo &key);\n};\n\nclass CBase\n{\n  CKeyInfoCache _cachedKeys;\nprotected:\n  CKeyInfo _key;\n  Byte _iv[kIvSizeMax];\n  unsigned _ivSize;\n  \n  void PrepareKey();\n  CBase();\n};\n\nclass CBaseCoder:\n  public ICompressFilter,\n  public ICryptoSetPassword,\n  public CMyUnknownImp,\n  public CBase\n{\n  Z7_IFACE_COM7_IMP(ICompressFilter)\n  Z7_IFACE_COM7_IMP(ICryptoSetPassword)\nprotected:\n  virtual ~CBaseCoder() {}\n  CMyComPtr<ICompressFilter> _aesFilter;\n};\n\n#ifndef Z7_EXTRACT_ONLY\n\nclass CEncoder Z7_final:\n  public CBaseCoder,\n  public ICompressWriteCoderProperties,\n  // public ICryptoResetSalt,\n  public ICryptoResetInitVector\n{\n  Z7_COM_UNKNOWN_IMP_4(\n      ICompressFilter,\n      ICryptoSetPassword,\n      ICompressWriteCoderProperties,\n      // ICryptoResetSalt,\n      ICryptoResetInitVector)\n  Z7_IFACE_COM7_IMP(ICompressWriteCoderProperties)\n  // Z7_IFACE_COM7_IMP(ICryptoResetSalt)\n  Z7_IFACE_COM7_IMP(ICryptoResetInitVector)\npublic:\n  CEncoder();\n};\n\n#endif\n\nclass CDecoder Z7_final:\n  public CBaseCoder,\n  public ICompressSetDecoderProperties2\n{\n  Z7_COM_UNKNOWN_IMP_3(\n      ICompressFilter,\n      ICryptoSetPassword,\n      ICompressSetDecoderProperties2)\n  Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\npublic:\n  CDecoder();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/7zAesRegister.cpp",
    "content": "﻿// 7zAesRegister.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"7zAes.h\"\n\nnamespace NCrypto {\nnamespace N7z {\n\nREGISTER_FILTER_E(SzAES,\n    CDecoder,\n    CEncoder,\n    0x6F10701, \"7zAES\")\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/HmacSha1.cpp",
    "content": "﻿// HmacSha1.cpp\n\n#include \"StdAfx.h\"\n\n#include <string.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"HmacSha1.h\"\n\nnamespace NCrypto {\nnamespace NSha1 {\n\nvoid CHmac::SetKey(const Byte *key, size_t keySize)\n{\n  MY_ALIGN (16)\n  UInt32 temp[SHA1_NUM_BLOCK_WORDS];\n  size_t i;\n  \n  for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)\n    temp[i] = 0;\n  \n  if (keySize > kBlockSize)\n  {\n    _sha.Init();\n    _sha.Update(key, keySize);\n    _sha.Final((Byte *)temp);\n  }\n  else\n    memcpy(temp, key, keySize);\n  \n  for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)\n    temp[i] ^= 0x36363636;\n  \n  _sha.Init();\n  _sha.Update((const Byte *)temp, kBlockSize);\n  \n  for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)\n    temp[i] ^= 0x36363636 ^ 0x5C5C5C5C;\n\n  _sha2.Init();\n  _sha2.Update((const Byte *)temp, kBlockSize);\n}\n\n\nvoid CHmac::Final(Byte *mac)\n{\n  _sha.Final(mac);\n  _sha2.Update(mac, kDigestSize);\n  _sha2.Final(mac);\n}\n\n\nvoid CHmac::GetLoopXorDigest1(void *mac, UInt32 numIteration)\n{\n  MY_ALIGN (16)  UInt32 block [SHA1_NUM_BLOCK_WORDS];\n  MY_ALIGN (16)  UInt32 block2[SHA1_NUM_BLOCK_WORDS];\n  MY_ALIGN (16)  UInt32 mac2  [SHA1_NUM_BLOCK_WORDS];\n  \n  _sha. PrepareBlock((Byte *)block,  SHA1_DIGEST_SIZE);\n  _sha2.PrepareBlock((Byte *)block2, SHA1_DIGEST_SIZE);\n\n  block[0] = ((const UInt32 *)mac)[0];\n  block[1] = ((const UInt32 *)mac)[1];\n  block[2] = ((const UInt32 *)mac)[2];\n  block[3] = ((const UInt32 *)mac)[3];\n  block[4] = ((const UInt32 *)mac)[4];\n\n  mac2[0] = block[0];\n  mac2[1] = block[1];\n  mac2[2] = block[2];\n  mac2[3] = block[3];\n  mac2[4] = block[4];\n\n  for (UInt32 i = 0; i < numIteration; i++)\n  {\n    _sha. GetBlockDigest((const Byte *)block,  (Byte *)block2);\n    _sha2.GetBlockDigest((const Byte *)block2, (Byte *)block);\n\n    mac2[0] ^= block[0];\n    mac2[1] ^= block[1];\n    mac2[2] ^= block[2];\n    mac2[3] ^= block[3];\n    mac2[4] ^= block[4];\n  }\n\n  ((UInt32 *)mac)[0] = mac2[0];\n  ((UInt32 *)mac)[1] = mac2[1];\n  ((UInt32 *)mac)[2] = mac2[2];\n  ((UInt32 *)mac)[3] = mac2[3];\n  ((UInt32 *)mac)[4] = mac2[4];\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/HmacSha1.h",
    "content": "﻿// HmacSha1.h\n// Implements HMAC-SHA-1 (RFC2104, FIPS-198)\n\n#ifndef ZIP7_INC_CRYPTO_HMAC_SHA1_H\n#define ZIP7_INC_CRYPTO_HMAC_SHA1_H\n\n#include \"Sha1Cls.h\"\n\nnamespace NCrypto {\nnamespace NSha1 {\n\n// Use:  SetKey(key, keySize); for () Update(data, size); FinalFull(mac);\n\nclass CHmac\n{\n  CContext _sha;\n  CContext _sha2;\npublic:\n  void SetKey(const Byte *key, size_t keySize);\n  void Update(const Byte *data, size_t dataSize) { _sha.Update(data, dataSize); }\n  \n  // Final() : mac is recommended to be aligned for 4 bytes\n  // GetLoopXorDigest1() : mac is required    to be aligned for 4 bytes\n  // The caller can use: UInt32 mac[NSha1::kNumDigestWords] and typecast to (Byte *) and (void *);\n  void Final(Byte *mac);\n  void GetLoopXorDigest1(void *mac, UInt32 numIteration);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/HmacSha256.cpp",
    "content": "﻿// HmacSha256.cpp\n\n#include \"StdAfx.h\"\n\n#include <string.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"HmacSha256.h\"\n\nnamespace NCrypto {\nnamespace NSha256 {\n\nvoid CHmac::SetKey(const Byte *key, size_t keySize)\n{\n  MY_ALIGN (16)\n  UInt32 temp[SHA256_NUM_BLOCK_WORDS];\n  size_t i;\n  \n  for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++)\n    temp[i] = 0;\n  \n  if (keySize > kBlockSize)\n  {\n    Sha256_Init(&_sha);\n    Sha256_Update(&_sha, key, keySize);\n    Sha256_Final(&_sha, (Byte *)temp);\n  }\n  else\n    memcpy(temp, key, keySize);\n  \n  for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++)\n    temp[i] ^= 0x36363636;\n  \n  Sha256_Init(&_sha);\n  Sha256_Update(&_sha, (const Byte *)temp, kBlockSize);\n  \n  for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++)\n    temp[i] ^= 0x36363636 ^ 0x5C5C5C5C;\n\n  Sha256_Init(&_sha2);\n  Sha256_Update(&_sha2, (const Byte *)temp, kBlockSize);\n}\n\n\nvoid CHmac::Final(Byte *mac)\n{\n  Sha256_Final(&_sha, mac);\n  Sha256_Update(&_sha2, mac, SHA256_DIGEST_SIZE);\n  Sha256_Final(&_sha2, mac);\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/HmacSha256.h",
    "content": "﻿// HmacSha256.h\n// Implements HMAC-SHA-256 (RFC2104, FIPS-198)\n\n#ifndef ZIP7_INC_CRYPTO_HMAC_SHA256_H\n#define ZIP7_INC_CRYPTO_HMAC_SHA256_H\n\n#include \"../../../C/Sha256.h\"\n\nnamespace NCrypto {\nnamespace NSha256 {\n\nconst unsigned kBlockSize = SHA256_BLOCK_SIZE;\nconst unsigned kDigestSize = SHA256_DIGEST_SIZE;\n\nclass CHmac\n{\n  CSha256 _sha;\n  CSha256 _sha2;\npublic:\n  void SetKey(const Byte *key, size_t keySize);\n  void Update(const Byte *data, size_t dataSize) { Sha256_Update(&_sha, data, dataSize); }\n  void Final(Byte *mac);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/MyAes.cpp",
    "content": "﻿// Crypto/MyAes.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"MyAes.h\"\n\nnamespace NCrypto {\n\nstatic struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;\n\nCAesCoder::CAesCoder(\n      // bool encodeMode,\n      unsigned keySize\n      // , bool ctrMode\n      ):\n  _keyIsSet(false),\n  // _encodeMode(encodeMode),\n  // _ctrMode(ctrMode),\n  _keySize(keySize),\n  // _ctrPos(0), // _ctrPos =0 will be set in Init()\n  _aes(AES_NUM_IVMRK_WORDS * 4 + AES_BLOCK_SIZE * 2)\n{\n  // _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);\n  memset(_iv, 0, AES_BLOCK_SIZE);\n  /*\n  // we can use the following code to test 32-bit overflow case for AES-CTR\n  for (unsigned i = 0; i < 16; i++) _iv[i] = (Byte)(i + 1);\n  _iv[0] = 0xFE; _iv[1] = _iv[2] = _iv[3] = 0xFF;\n  */\n}\n\nZ7_COM7F_IMF(CAesCoder::Init())\n{\n  _ctrPos = 0;\n  AesCbc_Init(Aes(), _iv);\n  return _keyIsSet ? S_OK : E_NOTIMPL; // E_FAIL\n}\n\nZ7_COM7F_IMF2(UInt32, CAesCoder::Filter(Byte *data, UInt32 size))\n{\n  if (!_keyIsSet)\n    return 0;\n  if (size < AES_BLOCK_SIZE)\n  {\n    if (size == 0)\n      return 0;\n    return AES_BLOCK_SIZE;\n  }\n  size >>= 4;\n  // (data) must be aligned for 16-bytes here\n  _codeFunc(Aes(), data, size);\n  return size << 4;\n}\n\n\nZ7_COM7F_IMF(CAesCoder::SetKey(const Byte *data, UInt32 size))\n{\n  if ((size & 0x7) != 0 || size < 16 || size > 32)\n    return E_INVALIDARG;\n  if (_keySize != 0 && size != _keySize)\n    return E_INVALIDARG;\n  _setKeyFunc(Aes() + 4, data, size);\n  _keyIsSet = true;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CAesCoder::SetInitVector(const Byte *data, UInt32 size))\n{\n  if (size != AES_BLOCK_SIZE)\n    return E_INVALIDARG;\n  memcpy(_iv, data, size);\n  /* we allow SetInitVector() call before SetKey() call.\n     so we ignore possible error in Init() here */\n  CAesCoder::Init(); // don't call virtual function here !!!\n  return S_OK;\n}\n\n\n#ifndef Z7_SFX\n\n/*\nZ7_COM7F_IMF(CAesCtrCoder::Init())\n{\n  _ctrPos = 0;\n  return CAesCoder::Init();\n}\n*/\n\nZ7_COM7F_IMF2(UInt32, CAesCtrCoder::Filter(Byte *data, UInt32 size))\n{\n  if (!_keyIsSet)\n    return 0;\n  if (size == 0)\n    return 0;\n  \n  if (_ctrPos != 0)\n  {\n    /* Optimized caller will not call here */\n    const Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS);\n    unsigned num = 0;\n    for (unsigned i = _ctrPos; i != AES_BLOCK_SIZE; i++)\n    {\n      if (num == size)\n      {\n        _ctrPos = i;\n        return num;\n      }\n      data[num++] ^= ctr[i];\n    }\n    _ctrPos = 0;\n    /* if (num < size) {\n       we can filter more data with _codeFunc().\n       But it's supposed that the caller can work correctly,\n       even if we do only partial filtering here.\n       So we filter data only for current 16-byte block. }\n    */\n    /*\n    size -= num;\n    size >>= 4;\n    // (data) must be aligned for 16-bytes here\n    _codeFunc(Aes(), data + num, size);\n    return num + (size << 4);\n    */\n    return num;\n  }\n  \n  if (size < AES_BLOCK_SIZE)\n  {\n    /* The good optimized caller can call here only in last Filter() call.\n       But we support also non-optimized callers,\n       where another Filter() calls are allowed after this call.\n    */\n    Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS);\n    memset(ctr, 0, AES_BLOCK_SIZE);\n    memcpy(ctr, data, size);\n    _codeFunc(Aes(), ctr, 1);\n    memcpy(data, ctr, size);\n    _ctrPos = size;\n    return size;\n  }\n  \n  size >>= 4;\n  // (data) must be aligned for 16-bytes here\n  _codeFunc(Aes(), data, size);\n  return size << 4;\n}\n\n#endif // Z7_SFX\n\n\n#ifndef Z7_EXTRACT_ONLY\n\n#ifdef MY_CPU_X86_OR_AMD64\n\n  #if defined(__INTEL_COMPILER)\n    #if (__INTEL_COMPILER >= 1110)\n      #define USE_HW_AES\n      #if (__INTEL_COMPILER >= 1900)\n        #define USE_HW_VAES\n      #endif\n    #endif\n  #elif defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \\\n     || defined(Z7_GCC_VERSION)   && (Z7_GCC_VERSION   >= 40400)\n    #define USE_HW_AES\n      #if defined(__clang__) && (__clang_major__ >= 8) \\\n          || defined(__GNUC__) && (__GNUC__ >= 8)\n        #define USE_HW_VAES\n      #endif\n  #elif defined(_MSC_VER)\n    #define USE_HW_AES\n    #define USE_HW_VAES\n  #endif\n\n#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)\n  \n  #if   defined(__ARM_FEATURE_AES) \\\n     || defined(__ARM_FEATURE_CRYPTO)\n    #define USE_HW_AES\n  #else\n    #if  defined(MY_CPU_ARM64) \\\n      || defined(__ARM_ARCH) && (__ARM_ARCH >= 4) \\\n      || defined(Z7_MSC_VER_ORIGINAL)\n    #if  defined(__ARM_FP) && \\\n          (   defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30800) \\\n           || defined(__GNUC__) && (__GNUC__ >= 6) \\\n          ) \\\n      || defined(Z7_MSC_VER_ORIGINAL) && (_MSC_VER >= 1910)\n    #if  defined(MY_CPU_ARM64) \\\n      || !defined(Z7_CLANG_VERSION) \\\n      || defined(__ARM_NEON) && \\\n          (Z7_CLANG_VERSION < 170000 || \\\n           Z7_CLANG_VERSION > 170001)\n      #define USE_HW_AES\n    #endif\n    #endif\n    #endif\n  #endif\n#endif\n\n#ifdef USE_HW_AES\n// #pragma message(\"=== MyAES.c USE_HW_AES === \")\n\n    #define SET_AES_FUNC_2(f2) \\\n      if (algo == 2) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW) \\\n      { f = f2; }\n  #ifdef USE_HW_VAES\n    #define SET_AES_FUNC_23(f2, f3) \\\n      SET_AES_FUNC_2(f2) \\\n      if (algo == 3) if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256) \\\n      { f = f3; }\n  #else  // USE_HW_VAES\n    #define SET_AES_FUNC_23(f2, f3) \\\n      SET_AES_FUNC_2(f2)\n  #endif // USE_HW_VAES\n#else  // USE_HW_AES\n    #define SET_AES_FUNC_23(f2, f3)\n#endif // USE_HW_AES\n\n#define SET_AES_FUNCS(c, f0, f1, f2, f3) \\\n  bool c::SetFunctions(UInt32 algo) { \\\n  _codeFunc = f0; if (algo < 1) return true; \\\n  AES_CODE_FUNC f = NULL; \\\n  if (algo == 1) { f = f1; } \\\n  SET_AES_FUNC_23(f2, f3) \\\n  if (f) { _codeFunc = f; return true; } \\\n  return false; }\n\n\n\n#ifndef Z7_SFX\nSET_AES_FUNCS(\n    CAesCtrCoder,\n  g_AesCtr_Code,\n    AesCtr_Code,\n    AesCtr_Code_HW,\n    AesCtr_Code_HW_256)\n#endif\n\nSET_AES_FUNCS(\n    CAesCbcEncoder,\n  g_AesCbc_Encode,\n    AesCbc_Encode,\n    AesCbc_Encode_HW,\n    AesCbc_Encode_HW)\n\nSET_AES_FUNCS(\n    CAesCbcDecoder,\n  g_AesCbc_Decode,\n    AesCbc_Decode,\n    AesCbc_Decode_HW,\n    AesCbc_Decode_HW_256)\n\nZ7_COM7F_IMF(CAesCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  UInt32 algo = 0;\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    if (propIDs[i] == NCoderPropID::kDefaultProp)\n    {\n      const PROPVARIANT &prop = coderProps[i];\n      if (prop.vt != VT_UI4)\n        return E_INVALIDARG;\n      if (prop.ulVal > 3)\n        return E_NOTIMPL;\n      algo = prop.ulVal;\n    }\n  }\n  if (!SetFunctions(algo))\n    return E_NOTIMPL;\n  return S_OK;\n}\n\n#endif // Z7_EXTRACT_ONLY\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/MyAes.h",
    "content": "﻿// Crypto/MyAes.h\n\n#ifndef ZIP7_INC_CRYPTO_MY_AES_H\n#define ZIP7_INC_CRYPTO_MY_AES_H\n\n#include \"../../../C/Aes.h\"\n\n#include \"../../Common/MyBuffer2.h\"\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCrypto {\n\n#ifdef Z7_EXTRACT_ONLY\n#define Z7_IFACEN_IAesCoderSetFunctions(x)\n#else\n#define Z7_IFACEN_IAesCoderSetFunctions(x) \\\n  virtual bool SetFunctions(UInt32 algo) x\n#endif\n\n\nclass CAesCoder:\n  public ICompressFilter,\n  public ICryptoProperties,\n #ifndef Z7_EXTRACT_ONLY\n  public ICompressSetCoderProperties,\n #endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(ICompressFilter)\n  Z7_COM_QI_ENTRY(ICryptoProperties)\n #ifndef Z7_EXTRACT_ONLY\n  Z7_COM_QI_ENTRY(ICompressSetCoderProperties)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n  \npublic:\n  Z7_IFACE_COM7_IMP_NONFINAL(ICompressFilter)\n  Z7_IFACE_COM7_IMP(ICryptoProperties)\nprivate:\n #ifndef Z7_EXTRACT_ONLY\n  Z7_IFACE_COM7_IMP(ICompressSetCoderProperties)\n #endif\n\nprotected:\n  bool _keyIsSet;\n  // bool _encodeMode;\n  // bool _ctrMode;\n  // unsigned _offset;\n  unsigned _keySize;\n  unsigned _ctrPos; // we need _ctrPos here for Init() / SetInitVector()\n  AES_CODE_FUNC _codeFunc;\n  AES_SET_KEY_FUNC _setKeyFunc;\nprivate:\n  // UInt32 _aes[AES_NUM_IVMRK_WORDS + 3];\n  CAlignedBuffer1 _aes;\n\n  Byte _iv[AES_BLOCK_SIZE];\n\n  // UInt32 *Aes() { return _aes + _offset; }\nprotected:\n  UInt32 *Aes() { return (UInt32 *)(void *)(Byte *)_aes; }\n\n Z7_IFACE_PURE(IAesCoderSetFunctions)\n\npublic:\n  CAesCoder(\n      // bool encodeMode,\n      unsigned keySize\n      // , bool ctrMode\n      );\n  virtual ~CAesCoder() {}   // we need virtual destructor for derived classes\n  void SetKeySize(unsigned size) { _keySize = size; }\n};\n\n\n#ifndef Z7_EXTRACT_ONLY\nstruct CAesCbcEncoder: public CAesCoder\n{\n  CAesCbcEncoder(unsigned keySize = 0): CAesCoder(keySize)\n  {\n    _setKeyFunc = Aes_SetKey_Enc;\n    _codeFunc = g_AesCbc_Encode;\n  }\n  Z7_IFACE_IMP(IAesCoderSetFunctions)\n};\n#endif\n\nstruct CAesCbcDecoder: public CAesCoder\n{\n  CAesCbcDecoder(unsigned keySize = 0): CAesCoder(keySize)\n  {\n    _setKeyFunc = Aes_SetKey_Dec;\n    _codeFunc = g_AesCbc_Decode;\n  }\n  Z7_IFACE_IMP(IAesCoderSetFunctions)\n};\n\n#ifndef Z7_SFX\nstruct CAesCtrCoder: public CAesCoder\n{\nprivate:\n  // unsigned _ctrPos;\n  // Z7_IFACE_COM7_IMP(ICompressFilter)\n  // Z7_COM7F_IMP(Init())\n  Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size))\npublic:\n  CAesCtrCoder(unsigned keySize = 0): CAesCoder(keySize)\n  {\n    _ctrPos = 0;\n    _setKeyFunc = Aes_SetKey_Enc;\n    _codeFunc = g_AesCtr_Code;\n  }\n  Z7_IFACE_IMP(IAesCoderSetFunctions)\n};\n#endif\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/MyAesReg.cpp",
    "content": "﻿// MyAesReg.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/RegisterCodec.h\"\n\n#include \"MyAes.h\"\n\nnamespace NCrypto {\n\n#ifndef Z7_SFX\n\n#define REGISTER_AES_2(name, nameString, keySize) \\\n  REGISTER_FILTER_E(name, \\\n    CAesCbcDecoder(keySize), \\\n    CAesCbcEncoder(keySize), \\\n    0x6F00100 | ((keySize - 16) * 8) | (/* isCtr */ 0 ? 4 : 1), \\\n    nameString) \\\n\n#define REGISTER_AES(name, nameString) \\\n  /* REGISTER_AES_2(AES128 ## name, \"AES128\" nameString, 16) */ \\\n  /* REGISTER_AES_2(AES192 ## name, \"AES192\" nameString, 24) */ \\\n  REGISTER_AES_2(AES256 ## name, \"AES256\" nameString, 32) \\\n\nREGISTER_AES(CBC, \"CBC\")\n\n#endif\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/Pbkdf2HmacSha1.cpp",
    "content": "﻿// Pbkdf2HmacSha1.cpp\n\n#include \"StdAfx.h\"\n\n#include <string.h>\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"HmacSha1.h\"\n#include \"Pbkdf2HmacSha1.h\"\n\nnamespace NCrypto {\nnamespace NSha1 {\n\nvoid Pbkdf2Hmac(const Byte *pwd, size_t pwdSize,\n    const Byte *salt, size_t saltSize,\n    UInt32 numIterations,\n    Byte *key, size_t keySize)\n{\n  MY_ALIGN (16)\n  CHmac baseCtx;\n  baseCtx.SetKey(pwd, pwdSize);\n  \n  for (UInt32 i = 1; keySize != 0; i++)\n  {\n    MY_ALIGN (16)\n    CHmac ctx;\n    ctx = baseCtx;\n    ctx.Update(salt, saltSize);\n  \n    MY_ALIGN (16)\n    UInt32 u[kNumDigestWords];\n    SetBe32(u, i)\n    \n    ctx.Update((const Byte *)u, 4);\n    ctx.Final((Byte *)u);\n\n    ctx = baseCtx;\n    ctx.GetLoopXorDigest1((void *)u, numIterations - 1);\n\n    const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize;\n    memcpy(key, (const Byte *)u, curSize);\n    key += curSize;\n    keySize -= curSize;\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/Pbkdf2HmacSha1.h",
    "content": "﻿// Pbkdf2HmacSha1.h\n// Password-Based Key Derivation Function (RFC 2898, PKCS #5) based on HMAC-SHA-1\n\n#ifndef ZIP7_INC_CRYPTO_PBKDF2_HMAC_SHA1_H\n#define ZIP7_INC_CRYPTO_PBKDF2_HMAC_SHA1_H\n\n#include <stddef.h>\n\n#include \"../../Common/MyTypes.h\"\n\nnamespace NCrypto {\nnamespace NSha1 {\n\nvoid Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize,\n    UInt32 numIterations, Byte *key, size_t keySize);\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/RandGen.cpp",
    "content": "﻿// RandGen.cpp\n\n#include \"StdAfx.h\"\n\n#include \"RandGen.h\"\n\n#ifndef USE_STATIC_SYSTEM_RAND\n\n#ifndef Z7_ST\n#include \"../../Windows/Synchronization.h\"\n#endif\n\n\n#ifdef _WIN32\n\n#ifdef _WIN64\n#define USE_STATIC_RtlGenRandom\n#endif\n\n#ifdef USE_STATIC_RtlGenRandom\n\n// #include <NTSecAPI.h>\n\nEXTERN_C_BEGIN\n#ifndef RtlGenRandom\n  #define RtlGenRandom SystemFunction036\n  BOOLEAN WINAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);\n#endif\nEXTERN_C_END\n\n#else\nEXTERN_C_BEGIN\ntypedef BOOLEAN (WINAPI * Func_RtlGenRandom)(PVOID RandomBuffer, ULONG RandomBufferLength);\nEXTERN_C_END\n#endif\n\n\n#else\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#define USE_POSIX_TIME\n#define USE_POSIX_TIME2\n#endif\n\n#ifdef USE_POSIX_TIME\n#include <time.h>\n#ifdef USE_POSIX_TIME2\n#include <sys/time.h>\n#endif\n#endif\n\n// The seed and first generated data block depend from processID,\n// theadID, timer and system random generator, if available.\n// Other generated data blocks depend from previous state\n\n#define HASH_UPD(x) Sha256_Update(&hash, (const Byte *)&x, sizeof(x));\n\nvoid CRandomGenerator::Init()\n{\n  MY_ALIGN (16)\n  CSha256 hash;\n  Sha256_Init(&hash);\n\n  unsigned numIterations = 1000;\n\n  {\n  #ifndef UNDER_CE\n  const unsigned kNumIterations_Small = 100;\n  const unsigned kBufSize = 32;\n  MY_ALIGN (16)\n  Byte buf[kBufSize];\n  #endif\n\n  #ifdef _WIN32\n\n  DWORD w = ::GetCurrentProcessId();\n  HASH_UPD(w)\n  w = ::GetCurrentThreadId();\n  HASH_UPD(w)\n\n  #ifdef UNDER_CE\n  /*\n  if (CeGenRandom(kBufSize, buf))\n  {\n    numIterations = kNumIterations_Small;\n    Sha256_Update(&hash, buf, kBufSize);\n  }\n  */\n  #elif defined(USE_STATIC_RtlGenRandom)\n  if (RtlGenRandom(buf, kBufSize))\n  {\n    numIterations = kNumIterations_Small;\n    Sha256_Update(&hash, buf, kBufSize);\n  }\n  #else\n  {\n    const HMODULE hModule = ::LoadLibrary(TEXT(\"advapi32.dll\"));\n    if (hModule)\n    {\n      // SystemFunction036() is real name of RtlGenRandom() function\n      const\n      Func_RtlGenRandom\n        my_RtlGenRandom = Z7_GET_PROC_ADDRESS(\n      Func_RtlGenRandom, hModule, \"SystemFunction036\");\n      if (my_RtlGenRandom)\n      {\n        if (my_RtlGenRandom(buf, kBufSize))\n        {\n          numIterations = kNumIterations_Small;\n          Sha256_Update(&hash, buf, kBufSize);\n        }\n      }\n      ::FreeLibrary(hModule);\n    }\n  }\n  #endif\n\n  #else\n  \n  pid_t pid = getpid();\n  HASH_UPD(pid)\n  pid = getppid();\n  HASH_UPD(pid)\n\n  {\n    int f = open(\"/dev/urandom\", O_RDONLY);\n    unsigned numBytes = kBufSize;\n    if (f >= 0)\n    {\n      do\n      {\n        ssize_t n = read(f, buf, numBytes);\n        if (n <= 0)\n          break;\n        Sha256_Update(&hash, buf, (size_t)n);\n        numBytes -= (unsigned)n;\n      }\n      while (numBytes);\n      close(f);\n      if (numBytes == 0)\n        numIterations = kNumIterations_Small;\n    }\n  }\n  /*\n  {\n    int n = getrandom(buf, kBufSize, 0);\n    if (n > 0)\n    {\n      Sha256_Update(&hash, buf, n);\n      if (n == kBufSize)\n        numIterations = kNumIterations_Small;\n    }\n  }\n  */\n\n  #endif\n  }\n\n  #ifdef _DEBUG\n  numIterations = 2;\n  #endif\n\n  do\n  {\n    #ifdef _WIN32\n    LARGE_INTEGER v;\n    if (::QueryPerformanceCounter(&v))\n      HASH_UPD(v.QuadPart)\n    #endif\n\n    #ifdef USE_POSIX_TIME\n    #ifdef USE_POSIX_TIME2\n    timeval v;\n    if (gettimeofday(&v, NULL) == 0)\n    {\n      HASH_UPD(v.tv_sec)\n      HASH_UPD(v.tv_usec)\n    }\n    #endif\n    const time_t v2 = time(NULL);\n    HASH_UPD(v2)\n    #endif\n\n    #ifdef _WIN32\n    const DWORD tickCount = ::GetTickCount();\n    HASH_UPD(tickCount)\n    #endif\n    \n    for (unsigned j = 0; j < 100; j++)\n    {\n      Sha256_Final(&hash, _buff);\n      Sha256_Init(&hash);\n      Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);\n    }\n  }\n  while (--numIterations);\n\n  Sha256_Final(&hash, _buff);\n  _needInit = false;\n}\n\n#ifndef Z7_ST\n  static NWindows::NSynchronization::CCriticalSection g_CriticalSection;\n  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\n#else\n  #define MT_LOCK\n#endif\n\nvoid CRandomGenerator::Generate(Byte *data, unsigned size)\n{\n  MT_LOCK\n\n  if (_needInit)\n    Init();\n  while (size != 0)\n  {\n    MY_ALIGN (16)\n    CSha256 hash;\n    \n    Sha256_Init(&hash);\n    Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);\n    Sha256_Final(&hash, _buff);\n    \n    Sha256_Init(&hash);\n    UInt32 salt = 0xF672ABD1;\n    HASH_UPD(salt)\n    Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);\n    MY_ALIGN (16)\n    Byte buff[SHA256_DIGEST_SIZE];\n    Sha256_Final(&hash, buff);\n    for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--)\n      *data++ = buff[i];\n  }\n}\n\nMY_ALIGN (16)\nCRandomGenerator g_RandomGenerator;\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/RandGen.h",
    "content": "﻿// RandGen.h\n\n#ifndef ZIP7_INC_CRYPTO_RAND_GEN_H\n#define ZIP7_INC_CRYPTO_RAND_GEN_H\n\n#include \"../../../C/Sha256.h\"\n\n#ifdef _WIN64\n// #define USE_STATIC_SYSTEM_RAND\n#endif\n\n#ifdef USE_STATIC_SYSTEM_RAND\n\n#ifdef _WIN32\n#include <ntsecapi.h>\n#define MY_RAND_GEN(data, size) RtlGenRandom(data, size)\n#else\n#define MY_RAND_GEN(data, size) getrandom(data, size, 0)\n#endif\n\n#else\n\nclass CRandomGenerator\n{\n  Byte _buff[SHA256_DIGEST_SIZE];\n  bool _needInit;\n\n  void Init();\npublic:\n  CRandomGenerator(): _needInit(true) {}\n  void Generate(Byte *data, unsigned size);\n};\n\nMY_ALIGN (16)\nextern CRandomGenerator g_RandomGenerator;\n\n#define MY_RAND_GEN(data, size) g_RandomGenerator.Generate(data, size)\n\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/Rar20Crypto.cpp",
    "content": "﻿// Crypto/Rar20Crypto.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/7zCrc.h\"\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/RotateDefs.h\"\n\n#include \"Rar20Crypto.h\"\n\nnamespace NCrypto {\nnamespace NRar2 {\n\nstatic const unsigned kNumRounds = 32;\n\nstatic const Byte g_InitSubstTable[256] = {\n  215, 19,149, 35, 73,197,192,205,249, 28, 16,119, 48,221,  2, 42,\n  232,  1,177,233, 14, 88,219, 25,223,195,244, 90, 87,239,153,137,\n  255,199,147, 70, 92, 66,246, 13,216, 40, 62, 29,217,230, 86,  6,\n   71, 24,171,196,101,113,218,123, 93, 91,163,178,202, 67, 44,235,\n  107,250, 75,234, 49,167,125,211, 83,114,157,144, 32,193,143, 36,\n  158,124,247,187, 89,214,141, 47,121,228, 61,130,213,194,174,251,\n   97,110, 54,229,115, 57,152, 94,105,243,212, 55,209,245, 63, 11,\n  164,200, 31,156, 81,176,227, 21, 76, 99,139,188,127, 17,248, 51,\n  207,120,189,210,  8,226, 41, 72,183,203,135,165,166, 60, 98,  7,\n  122, 38,155,170, 69,172,252,238, 39,134, 59,128,236, 27,240, 80,\n  131,  3, 85,206,145, 79,154,142,159,220,201,133, 74, 64, 20,129,\n  224,185,138,103,173,182, 43, 34,254, 82,198,151,231,180, 58, 10,\n  118, 26,102, 12, 50,132, 22,191,136,111,162,179, 45,  4,148,108,\n  161, 56, 78,126,242,222, 15,175,146, 23, 33,241,181,190, 77,225,\n    0, 46,169,186, 68, 95,237, 65, 53,208,253,168,  9, 18,100, 52,\n  116,184,160, 96,109, 37, 30,106,140,104,150,  5,204,117,112, 84\n};\n\nvoid CData::UpdateKeys(const Byte *data)\n{\n  for (unsigned i = 0; i < 16; i += 4)\n    for (unsigned j = 0; j < 4; j++)\n      Keys[j] ^= g_CrcTable[data[i + j]];\n}\n\nstatic inline void Swap(Byte &b1, Byte &b2)\n{\n  Byte b = b1;\n  b1 = b2;\n  b2 = b;\n}\n\nvoid CData::SetPassword(const Byte *data, unsigned size)\n{\n  Keys[0] = 0xD3A3B879L;\n  Keys[1] = 0x3F6D12F7L;\n  Keys[2] = 0x7515A235L;\n  Keys[3] = 0xA4E7F123L;\n  \n  Byte psw[128];\n  Z7_memset_0_ARRAY(psw);\n  if (size != 0)\n  {\n    if (size >= sizeof(psw))\n      size = sizeof(psw) - 1;\n    memcpy(psw, data, size);\n  }\n\n  memcpy(SubstTable, g_InitSubstTable, sizeof(SubstTable));\n\n  for (unsigned j = 0; j < 256; j++)\n    for (unsigned i = 0; i < size; i += 2)\n    {\n      unsigned n1 = (Byte)g_CrcTable[(psw[i] - j) & 0xFF];\n      unsigned n2 = (Byte)g_CrcTable[(psw[(size_t)i + 1] + j) & 0xFF];\n      for (unsigned k = 1; (n1 & 0xFF) != n2; n1++, k++)\n        Swap(SubstTable[n1 & 0xFF], SubstTable[(n1 + i + k) & 0xFF]);\n    }\n  \n  for (unsigned i = 0; i < size; i += 16)\n    EncryptBlock(psw + i);\n}\n\nvoid CData::CryptBlock(Byte *buf, bool encrypt)\n{\n  Byte inBuf[16];\n  UInt32 A, B, C, D;\n\n  A = GetUi32(buf +  0) ^ Keys[0];\n  B = GetUi32(buf +  4) ^ Keys[1];\n  C = GetUi32(buf +  8) ^ Keys[2];\n  D = GetUi32(buf + 12) ^ Keys[3];\n\n  if (!encrypt)\n    memcpy(inBuf, buf, sizeof(inBuf));\n  \n  for (unsigned i = 0; i < kNumRounds; i++)\n  {\n    UInt32 key = Keys[(encrypt ? i : (kNumRounds - 1 - i)) & 3];\n    UInt32 TA = A ^ SubstLong((C + rotlFixed(D, 11)) ^ key);\n    UInt32 TB = B ^ SubstLong((D ^ rotlFixed(C, 17)) + key);\n    A = C; C = TA;\n    B = D; D = TB;\n  }\n\n  SetUi32(buf +  0, C ^ Keys[0])\n  SetUi32(buf +  4, D ^ Keys[1])\n  SetUi32(buf +  8, A ^ Keys[2])\n  SetUi32(buf + 12, B ^ Keys[3])\n\n  UpdateKeys(encrypt ? buf : inBuf);\n}\n\nZ7_COM7F_IMF(CDecoder::Init())\n{\n  return S_OK;\n}\n\nstatic const UInt32 kBlockSize = 16;\n\nZ7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))\n{\n  if (size == 0)\n    return 0;\n  if (size < kBlockSize)\n    return kBlockSize;\n  size -= kBlockSize;\n  UInt32 i;\n  for (i = 0; i <= size; i += kBlockSize)\n    DecryptBlock(data + i);\n  return i;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/Rar20Crypto.h",
    "content": "﻿// Crypto/Rar20Crypto.h\n\n#ifndef ZIP7_INC_CRYPTO_RAR20_CRYPTO_H\n#define ZIP7_INC_CRYPTO_RAR20_CRYPTO_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n\nnamespace NCrypto {\nnamespace NRar2 {\n\n/* ICompressFilter::Init() does nothing for this filter.\n   Call SetPassword() to initialize filter. */\n\nclass CData\n{\n  Byte SubstTable[256];\n  UInt32 Keys[4];\n  \n  UInt32 SubstLong(UInt32 t) const\n  {\n    return (UInt32)SubstTable[(unsigned)t         & 255]\n        | ((UInt32)SubstTable[(unsigned)(t >>  8) & 255] << 8)\n        | ((UInt32)SubstTable[(unsigned)(t >> 16) & 255] << 16)\n        | ((UInt32)SubstTable[(unsigned)(t >> 24)      ] << 24);\n  }\n  void UpdateKeys(const Byte *data);\n  void CryptBlock(Byte *buf, bool encrypt);\npublic:\n  ~CData() { Wipe(); }\n  void Wipe()\n  {\n    Z7_memset_0_ARRAY(SubstTable);\n    Z7_memset_0_ARRAY(Keys);\n  }\n\n  void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }\n  void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }\n  void SetPassword(const Byte *password, unsigned passwordLen);\n};\n\nclass CDecoder Z7_final:\n  public ICompressFilter,\n  public CMyUnknownImp,\n  public CData\n{\n  Z7_COM_UNKNOWN_IMP_0\n  Z7_IFACE_COM7_IMP(ICompressFilter)\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/Rar5Aes.cpp",
    "content": "﻿// Crypto/Rar5Aes.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#ifndef Z7_ST\n#include \"../../Windows/Synchronization.h\"\n#endif\n\n#include \"HmacSha256.h\"\n#include \"Rar5Aes.h\"\n\n#define MY_ALIGN_FOR_SHA256  MY_ALIGN(16)\n\nnamespace NCrypto {\nnamespace NRar5 {\n\nstatic const unsigned kNumIterationsLog_Max = 24;\nstatic const unsigned kPswCheckCsumSize32 = 1;\nstatic const unsigned kCheckSize32 = kPswCheckSize32 + kPswCheckCsumSize32;\n\nCKey::CKey():\n    _needCalc(true),\n    _numIterationsLog(0)\n{\n  for (unsigned i = 0; i < sizeof(_salt); i++)\n    _salt[i] = 0;\n}\n\nCKey::~CKey()\n{\n  Wipe();\n}\n\nvoid CKey::Wipe()\n{\n  _password.Wipe();\n  Z7_memset_0_ARRAY(_salt);\n  // Z7_memset_0_ARRAY(_key32);\n  // Z7_memset_0_ARRAY(_check_Calced32);\n  // Z7_memset_0_ARRAY(_hashKey32);\n  CKeyBase::Wipe();\n}\n\nCDecoder::CDecoder(): CAesCbcDecoder(kAesKeySize) {}\n\nstatic unsigned ReadVarInt(const Byte *p, unsigned maxSize, UInt64 *val)\n{\n  *val = 0;\n  for (unsigned i = 0; i < maxSize && i < 10;)\n  {\n    const Byte b = p[i];\n    *val |= (UInt64)(b & 0x7F) << (7 * i);\n    i++;\n    if ((b & 0x80) == 0)\n      return i;\n  }\n  return 0;\n}\n\nHRESULT CDecoder::SetDecoderProps(const Byte *p, unsigned size, bool includeIV, bool isService)\n{\n  UInt64 Version;\n  \n  unsigned num = ReadVarInt(p, size, &Version);\n  if (num == 0)\n    return E_NOTIMPL;\n  p += num;\n  size -= num;\n\n  if (Version != 0)\n    return E_NOTIMPL;\n  \n  num = ReadVarInt(p, size, &Flags);\n  if (num == 0)\n    return E_NOTIMPL;\n  p += num;\n  size -= num;\n\n  bool isCheck = IsThereCheck();\n  if (size != 1 + kSaltSize + (includeIV ? AES_BLOCK_SIZE : 0) + (unsigned)(isCheck ? kCheckSize32 * 4 : 0))\n    return E_NOTIMPL;\n\n  if (_numIterationsLog != p[0])\n  {\n    _numIterationsLog = p[0];\n    _needCalc = true;\n  }\n\n  p++;\n    \n  if (memcmp(_salt, p, kSaltSize) != 0)\n  {\n    memcpy(_salt, p, kSaltSize);\n    _needCalc = true;\n  }\n  \n  p += kSaltSize;\n  \n  if (includeIV)\n  {\n    memcpy(_iv, p, AES_BLOCK_SIZE);\n    p += AES_BLOCK_SIZE;\n  }\n  \n  _canCheck = true;\n  \n  if (isCheck)\n  {\n    memcpy(_check32, p, sizeof(_check32));\n    MY_ALIGN_FOR_SHA256\n    CSha256 sha;\n    MY_ALIGN_FOR_SHA256\n    Byte digest[SHA256_DIGEST_SIZE];\n    Sha256_Init(&sha);\n    Sha256_Update(&sha, (const Byte *)_check32, sizeof(_check32));\n    Sha256_Final(&sha, digest);\n    _canCheck = (memcmp(digest, p + sizeof(_check32), kPswCheckCsumSize32 * 4) == 0);\n    if (_canCheck && isService)\n    {\n      // There was bug in RAR 5.21- : PswCheck field in service records (\"QO\") contained zeros.\n      // so we disable password checking for such bad records.\n      _canCheck = false;\n      for (unsigned i = 0; i < kPswCheckSize32 * 4; i++)\n        if (p[i] != 0)\n        {\n          _canCheck = true;\n          break;\n        }\n    }\n  }\n\n  return (_numIterationsLog <= kNumIterationsLog_Max ? S_OK : E_NOTIMPL);\n}\n\n\nvoid CDecoder::SetPassword(const Byte *data, size_t size)\n{\n  if (size != _password.Size() || memcmp(data, _password, size) != 0)\n  {\n    _needCalc = true;\n    _password.Wipe();\n    _password.CopyFrom(data, size);\n  }\n}\n\n\nZ7_COM7F_IMF(CDecoder::Init())\n{\n  CalcKey_and_CheckPassword();\n  RINOK(SetKey((const Byte *)_key32, kAesKeySize))\n  RINOK(SetInitVector(_iv, AES_BLOCK_SIZE))\n  return CAesCoder::Init();\n}\n\n\nUInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const\n{\n  MY_ALIGN_FOR_SHA256\n  NSha256::CHmac ctx;\n  ctx.SetKey((const Byte *)_hashKey32, NSha256::kDigestSize);\n  UInt32 v;\n  SetUi32a(&v, crc)\n  ctx.Update((const Byte *)&v, 4);\n  MY_ALIGN_FOR_SHA256\n  UInt32 h[SHA256_NUM_DIGEST_WORDS];\n  ctx.Final((Byte *)h);\n  crc = 0;\n  for (unsigned i = 0; i < SHA256_NUM_DIGEST_WORDS; i++)\n    crc ^= (UInt32)GetUi32a(h + i);\n  return crc;\n}\n\n\nvoid CDecoder::Hmac_Convert_32Bytes(Byte *data) const\n{\n  MY_ALIGN_FOR_SHA256\n  NSha256::CHmac ctx;\n  ctx.SetKey((const Byte *)_hashKey32, NSha256::kDigestSize);\n  ctx.Update(data, NSha256::kDigestSize);\n  ctx.Final(data);\n}\n\n\nstatic CKey g_Key;\n\n#ifndef Z7_ST\n  static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;\n  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);\n#else\n  #define MT_LOCK\n#endif\n\nbool CDecoder::CalcKey_and_CheckPassword()\n{\n  if (_needCalc)\n  {\n    {\n      MT_LOCK\n      if (!g_Key._needCalc && IsKeyEqualTo(g_Key))\n      {\n        CopyCalcedKeysFrom(g_Key);\n        _needCalc = false;\n      }\n    }\n    \n    if (_needCalc)\n    {\n      MY_ALIGN_FOR_SHA256\n      UInt32 pswCheck[SHA256_NUM_DIGEST_WORDS];\n      {\n        // Pbkdf HMAC-SHA-256\n        MY_ALIGN_FOR_SHA256\n        NSha256::CHmac baseCtx;\n        baseCtx.SetKey(_password, _password.Size());\n        MY_ALIGN_FOR_SHA256\n        NSha256::CHmac ctx;\n        ctx = baseCtx;\n        ctx.Update(_salt, sizeof(_salt));\n        \n        MY_ALIGN_FOR_SHA256\n        UInt32 u[SHA256_NUM_DIGEST_WORDS];\n        MY_ALIGN_FOR_SHA256\n        UInt32 key[SHA256_NUM_DIGEST_WORDS];\n        \n        // u[0] = 0;\n        // u[1] = 0;\n        // u[2] = 0;\n        // u[3] = 1;\n        SetUi32a(u, 0x1000000)\n        \n        ctx.Update((const Byte *)(const void *)u, 4);\n        ctx.Final((Byte *)(void *)u);\n        \n        memcpy(key, u, NSha256::kDigestSize);\n        \n        UInt32 numIterations = ((UInt32)1 << _numIterationsLog) - 1;\n        \n        for (unsigned i = 0; i < 3; i++)\n        {\n          for (; numIterations != 0; numIterations--)\n          {\n            ctx = baseCtx;\n            ctx.Update((const Byte *)(const void *)u, NSha256::kDigestSize);\n            ctx.Final((Byte *)(void *)u);\n            for (unsigned s = 0; s < Z7_ARRAY_SIZE(u); s++)\n              key[s] ^= u[s];\n          }\n          \n          // RAR uses additional iterations for additional keys\n          memcpy(i == 0 ? _key32 : i == 1 ? _hashKey32 : pswCheck,\n              key, NSha256::kDigestSize);\n          numIterations = 16;\n        }\n      }\n     _check_Calced32[0] = pswCheck[0] ^ pswCheck[2] ^ pswCheck[4] ^ pswCheck[6];\n     _check_Calced32[1] = pswCheck[1] ^ pswCheck[3] ^ pswCheck[5] ^ pswCheck[7];\n      _needCalc = false;\n      {\n        MT_LOCK\n        g_Key = *this;\n      }\n    }\n  }\n  \n  if (IsThereCheck() && _canCheck)\n    return memcmp(_check_Calced32, _check32, sizeof(_check32)) == 0;\n  return true;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/Rar5Aes.h",
    "content": "﻿// Crypto/Rar5Aes.h\n\n#ifndef ZIP7_INC_CRYPTO_RAR5_AES_H\n#define ZIP7_INC_CRYPTO_RAR5_AES_H\n\n#include \"../../../C/Sha256.h\"\n\n#include \"../../Common/MyBuffer.h\"\n\n#include \"MyAes.h\"\n\nnamespace NCrypto {\nnamespace NRar5 {\n\nconst unsigned kSaltSize = 16;\nconst unsigned kPswCheckSize32 = 2;\nconst unsigned kAesKeySize = 32;\n\nnamespace NCryptoFlags\n{\n  const unsigned kPswCheck = 1 << 0;\n  const unsigned kUseMAC   = 1 << 1;\n}\n\nstruct CKeyBase\n{\nprotected:\n  UInt32 _key32[kAesKeySize / 4];\n  UInt32 _hashKey32[SHA256_NUM_DIGEST_WORDS];\n  UInt32 _check_Calced32[kPswCheckSize32];\n\n  void Wipe()\n  {\n    memset(this, 0, sizeof(*this));\n  }\n  \n  void CopyCalcedKeysFrom(const CKeyBase &k)\n  {\n    *this = k;\n  }\n};\n\nstruct CKey: public CKeyBase\n{\n  CByteBuffer _password;\n  bool _needCalc;\n  unsigned _numIterationsLog;\n  Byte _salt[kSaltSize];\n  \n  bool IsKeyEqualTo(const CKey &key)\n  {\n    return _numIterationsLog == key._numIterationsLog\n        && memcmp(_salt, key._salt, sizeof(_salt)) == 0\n        && _password == key._password;\n  }\n\n  CKey();\n  ~CKey();\n  \n  void Wipe();\n\n#ifdef Z7_CPP_IS_SUPPORTED_default\n  // CKey(const CKey &) = default;\n  CKey& operator =(const CKey &) = default;\n#endif\n};\n\n\nclass CDecoder Z7_final:\n  public CAesCbcDecoder,\n  public CKey\n{\n  UInt32 _check32[kPswCheckSize32];\n  bool _canCheck;\n  UInt64 Flags;\n\n  bool IsThereCheck() const { return (Flags & NCryptoFlags::kPswCheck) != 0; }\npublic:\n  Byte _iv[AES_BLOCK_SIZE];\n  \n  CDecoder();\n\n  Z7_COM7F_IMP(Init())\n\n  void SetPassword(const Byte *data, size_t size);\n  HRESULT SetDecoderProps(const Byte *data, unsigned size, bool includeIV, bool isService);\n\n  bool CalcKey_and_CheckPassword();\n\n  bool UseMAC() const { return (Flags & NCryptoFlags::kUseMAC) != 0; }\n  UInt32 Hmac_Convert_Crc32(UInt32 crc) const;\n  void Hmac_Convert_32Bytes(Byte *data) const;\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/RarAes.cpp",
    "content": "﻿// Crypto/RarAes.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n#include \"../../../C/RotateDefs.h\"\n\n#include \"RarAes.h\"\n#include \"Sha1Cls.h\"\n\nnamespace NCrypto {\nnamespace NRar3 {\n\nCDecoder::CDecoder():\n    CAesCbcDecoder(kAesKeySize),\n    _thereIsSalt(false),\n    _needCalc(true)\n    // _rar350Mode(false)\n{\n  for (unsigned i = 0; i < sizeof(_salt); i++)\n    _salt[i] = 0;\n}\n\nHRESULT CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)\n{\n  bool prev = _thereIsSalt;\n  _thereIsSalt = false;\n  if (size == 0)\n  {\n    if (!_needCalc && prev)\n      _needCalc = true;\n    return S_OK;\n  }\n  if (size < 8)\n    return E_INVALIDARG;\n  _thereIsSalt = true;\n  bool same = false;\n  if (_thereIsSalt == prev)\n  {\n    same = true;\n    if (_thereIsSalt)\n    {\n      for (unsigned i = 0; i < sizeof(_salt); i++)\n        if (_salt[i] != data[i])\n        {\n          same = false;\n          break;\n        }\n    }\n  }\n  for (unsigned i = 0; i < sizeof(_salt); i++)\n    _salt[i] = data[i];\n  if (!_needCalc && !same)\n    _needCalc = true;\n  return S_OK;\n}\n\nstatic const unsigned kPasswordLen_Bytes_MAX = 127 * 2;\n\nvoid CDecoder::SetPassword(const Byte *data, unsigned size)\n{\n  if (size > kPasswordLen_Bytes_MAX)\n    size = kPasswordLen_Bytes_MAX;\n  bool same = false;\n  if (size == _password.Size())\n  {\n    same = true;\n    for (UInt32 i = 0; i < size; i++)\n      if (data[i] != _password[i])\n      {\n        same = false;\n        break;\n      }\n  }\n  if (!_needCalc && !same)\n    _needCalc = true;\n  _password.Wipe();\n  _password.CopyFrom(data, (size_t)size);\n}\n\nZ7_COM7F_IMF(CDecoder::Init())\n{\n  CalcKey();\n  RINOK(SetKey(_key, kAesKeySize))\n  RINOK(SetInitVector(_iv, AES_BLOCK_SIZE))\n  return CAesCoder::Init();\n}\n\n\n// if (password_size_in_bytes + SaltSize > 64),\n// the original rar code updates password_with_salt buffer\n// with some generated data from SHA1 code.\n \n// #define RAR_SHA1_REDUCE\n\n#ifdef RAR_SHA1_REDUCE\n  #define kNumW 16\n  #define WW(i) W[(i)&15]\n#else\n  #define kNumW 80\n  #define WW(i) W[i]\n#endif\n\nstatic void UpdatePswDataSha1(Byte *data)\n{\n  UInt32 W[kNumW];\n  size_t i;\n  \n  for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)\n    W[i] = GetBe32(data + i * 4);\n  \n  for (i = 16; i < 80; i++)\n  {\n    const UInt32 t = WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16);\n    WW(i) = rotlFixed(t, 1);\n  }\n  \n  for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)\n  {\n    SetUi32(data + i * 4, W[kNumW - SHA1_NUM_BLOCK_WORDS + i])\n  }\n}\n\n\nvoid CDecoder::CalcKey()\n{\n  if (!_needCalc)\n    return;\n\n  const unsigned kSaltSize = 8;\n  \n  MY_ALIGN (16)\n  Byte buf[kPasswordLen_Bytes_MAX + kSaltSize];\n  \n  if (_password.Size() != 0)\n    memcpy(buf, _password, _password.Size());\n  \n  size_t rawSize = _password.Size();\n  \n  if (_thereIsSalt)\n  {\n    memcpy(buf + rawSize, _salt, kSaltSize);\n    rawSize += kSaltSize;\n  }\n  \n  MY_ALIGN (16)\n  NSha1::CContext sha;\n  sha.Init();\n  \n  MY_ALIGN (16)\n  Byte digest[NSha1::kDigestSize];\n  // rar reverts hash for sha.\n  const UInt32 kNumRounds = (UInt32)1 << 18;\n  UInt32 pos = 0;\n  UInt32 i;\n  for (i = 0; i < kNumRounds; i++)\n  {\n    sha.Update(buf, rawSize);\n    // if (_rar350Mode)\n    {\n      const UInt32 kBlockSize = 64;\n      const UInt32 endPos = (pos + (UInt32)rawSize) & ~(kBlockSize - 1);\n      if (endPos > pos + kBlockSize)\n      {\n        UInt32 curPos = pos & ~(kBlockSize - 1);\n        curPos += kBlockSize;\n        do\n        {\n          UpdatePswDataSha1(buf + (curPos - pos));\n          curPos += kBlockSize;\n        }\n        while (curPos != endPos);\n      }\n    }\n    pos += (UInt32)rawSize;\n#if 1\n    UInt32 pswNum;\n    SetUi32a(&pswNum, i)\n    sha.Update((const Byte *)&pswNum, 3);\n#else\n    Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };\n    sha.Update(pswNum, 3);\n#endif\n    pos += 3;\n    if (i % (kNumRounds / 16) == 0)\n    {\n      MY_ALIGN (16)\n      NSha1::CContext shaTemp = sha;\n      shaTemp.Final(digest);\n      _iv[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3];\n    }\n  }\n  \n  sha.Final(digest);\n  for (i = 0; i < 4; i++)\n    for (unsigned j = 0; j < 4; j++)\n      _key[i * 4 + j] = (digest[i * 4 + 3 - j]);\n    \n  _needCalc = false;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/RarAes.h",
    "content": "﻿// Crypto/RarAes.h\n\n#ifndef ZIP7_INC_CRYPTO_RAR_AES_H\n#define ZIP7_INC_CRYPTO_RAR_AES_H\n\n#include \"../../../C/Aes.h\"\n\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../IPassword.h\"\n\n#include \"MyAes.h\"\n\nnamespace NCrypto {\nnamespace NRar3 {\n\nconst unsigned kAesKeySize = 16;\n\nclass CDecoder Z7_final:\n  public CAesCbcDecoder\n{\n  Byte _salt[8];\n  bool _thereIsSalt;\n  bool _needCalc;\n  // bool _rar350Mode;\n  \n  CByteBuffer _password;\n  \n  Byte _key[kAesKeySize];\n  Byte _iv[AES_BLOCK_SIZE];\n\n  void CalcKey();\npublic:\n  Z7_COM7F_IMP(Init())\n  \n  void SetPassword(const Byte *data, unsigned size);\n  HRESULT SetDecoderProperties2(const Byte *data, UInt32 size);\n\n  CDecoder();\n\n  ~CDecoder() Z7_DESTRUCTOR_override { Wipe(); }\n  void Wipe()\n  {\n    _password.Wipe();\n    Z7_memset_0_ARRAY(_salt);\n    Z7_memset_0_ARRAY(_key);\n    Z7_memset_0_ARRAY(_iv);\n  }\n  // void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/Sha1Cls.h",
    "content": "﻿// Crypto/Sha1Cls.h\n\n#ifndef ZIP7_INC_CRYPTO_SHA1_CLS_H\n#define ZIP7_INC_CRYPTO_SHA1_CLS_H\n\n#include \"../../../C/Sha1.h\"\n\nnamespace NCrypto {\nnamespace NSha1 {\n\nconst unsigned kNumBlockWords = SHA1_NUM_BLOCK_WORDS;\nconst unsigned kNumDigestWords = SHA1_NUM_DIGEST_WORDS;\n\nconst unsigned kBlockSize = SHA1_BLOCK_SIZE;\nconst unsigned kDigestSize = SHA1_DIGEST_SIZE;\n\nclass CContext\n{\n  CSha1 _s;\n \npublic:\n  void Init() throw() { Sha1_Init(&_s); }\n  void Update(const Byte *data, size_t size) throw() { Sha1_Update(&_s, data, size); }\n  void Final(Byte *digest) throw() { Sha1_Final(&_s, digest); }\n  void PrepareBlock(Byte *block, unsigned size) const throw()\n  {\n    Sha1_PrepareBlock(&_s, block, size);\n  }\n  void GetBlockDigest(const Byte *blockData, Byte *destDigest) const throw()\n  {\n    Sha1_GetBlockDigest(&_s, blockData, destDigest);\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/WzAes.cpp",
    "content": "﻿// Crypto/WzAes.cpp\n/*\nThis code implements Brian Gladman's scheme\nspecified in \"A Password Based File Encryption Utility\".\n\nNote: you must include MyAes.cpp to project to initialize AES tables\n*/\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/CpuArch.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"Pbkdf2HmacSha1.h\"\n#include \"RandGen.h\"\n#include \"WzAes.h\"\n\nnamespace NCrypto {\nnamespace NWzAes {\n\nconst unsigned kAesKeySizeMax = 32;\n\nstatic const UInt32 kNumKeyGenIterations = 1000;\n\nZ7_COM7F_IMF(CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size))\n{\n  if (size > kPasswordSizeMax)\n    return E_INVALIDARG;\n  _key.Password.Wipe();\n  _key.Password.CopyFrom(data, (size_t)size);\n  return S_OK;\n}\n\nvoid CBaseCoder::Init2()\n{\n  _hmacOverCalc = 0;\n  const unsigned dkSizeMax32 = (2 * kAesKeySizeMax + kPwdVerifSize + 3) / 4;\n  Byte dk[dkSizeMax32 * 4];\n\n  const unsigned keySize = _key.GetKeySize();\n  const unsigned dkSize = 2 * keySize + ((kPwdVerifSize + 3) & ~(unsigned)3);\n  \n  // for (unsigned ii = 0; ii < 1000; ii++)\n  {\n    NSha1::Pbkdf2Hmac(\n        _key.Password, _key.Password.Size(),\n        _key.Salt, _key.GetSaltSize(),\n        kNumKeyGenIterations,\n        dk, dkSize);\n  }\n\n  Hmac()->SetKey(dk + keySize, keySize);\n  memcpy(_key.PwdVerifComputed, dk + 2 * keySize, kPwdVerifSize);\n\n  // Aes_SetKey_Enc(_aes.Aes() + 8, dk, keySize);\n  // AesCtr2_Init(&_aes);\n  _aesCoderSpec->SetKeySize(keySize);\n  if (_aesCoderSpec->SetKey(dk, keySize) != S_OK) throw 2;\n  if (_aesCoderSpec->Init() != S_OK) throw 3;\n}\n\nZ7_COM7F_IMF(CBaseCoder::Init())\n{\n  return S_OK;\n}\n\nHRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream)\n{\n  unsigned saltSize = _key.GetSaltSize();\n  MY_RAND_GEN(_key.Salt, saltSize);\n  Init2();\n  RINOK(WriteStream(outStream, _key.Salt, saltSize))\n  return WriteStream(outStream, _key.PwdVerifComputed, kPwdVerifSize);\n}\n\nHRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream)\n{\n  MY_ALIGN (16)\n  UInt32 mac[NSha1::kNumDigestWords];\n  Hmac()->Final((Byte *)mac);\n  return WriteStream(outStream, mac, kMacSize);\n}\n\n/*\nZ7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))\n{\n  if (size != 1)\n    return E_INVALIDARG;\n  _key.Init();\n  return SetKeyMode(data[0]) ? S_OK : E_INVALIDARG;\n}\n*/\n\nHRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)\n{\n  const unsigned saltSize = _key.GetSaltSize();\n  const unsigned extraSize = saltSize + kPwdVerifSize;\n  Byte temp[kSaltSizeMax + kPwdVerifSize];\n  RINOK(ReadStream_FAIL(inStream, temp, extraSize))\n  unsigned i;\n  for (i = 0; i < saltSize; i++)\n    _key.Salt[i] = temp[i];\n  for (i = 0; i < kPwdVerifSize; i++)\n    _pwdVerifFromArchive[i] = temp[saltSize + i];\n  return S_OK;\n}\n\nstatic inline bool CompareArrays(const Byte *p1, const Byte *p2, unsigned size)\n{\n  for (unsigned i = 0; i < size; i++)\n    if (p1[i] != p2[i])\n      return false;\n  return true;\n}\n\nbool CDecoder::Init_and_CheckPassword()\n{\n  Init2();\n  return CompareArrays(_key.PwdVerifComputed, _pwdVerifFromArchive, kPwdVerifSize);\n}\n\nHRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK)\n{\n  isOK = false;\n  MY_ALIGN (16)\n  Byte mac1[kMacSize];\n  RINOK(ReadStream_FAIL(inStream, mac1, kMacSize))\n  MY_ALIGN (16)\n  UInt32 mac2[NSha1::kNumDigestWords];\n  Hmac()->Final((Byte *)mac2);\n  isOK = CompareArrays(mac1, (const Byte *)mac2, kMacSize);\n  if (_hmacOverCalc)\n    isOK = false;\n  return S_OK;\n}\n\n/*\n\nCAesCtr2::CAesCtr2():\n    aes((4 + AES_NUM_IVMRK_WORDS) * 4)\n{\n  // offset = ((0 - (unsigned)(ptrdiff_t)aes) & 0xF) / sizeof(UInt32);\n  // first 16 bytes are buffer for last block data.\n  // so the ivAES is aligned for (Align + 16).\n}\n\nvoid AesCtr2_Init(CAesCtr2 *p)\n{\n  UInt32 *ctr = p->Aes() + 4;\n  unsigned i;\n  for (i = 0; i < 4; i++)\n    ctr[i] = 0;\n  p->pos = AES_BLOCK_SIZE;\n}\n\n// (size != 16 * N) is allowed only for last call\n\nvoid AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)\n{\n  unsigned pos = p->pos;\n  UInt32 *buf32 = p->Aes();\n  if (size == 0)\n    return;\n  \n  if (pos != AES_BLOCK_SIZE)\n  {\n    const Byte *buf = (const Byte *)buf32;\n    do\n      *data++ ^= buf[pos++];\n    while (--size != 0 && pos != AES_BLOCK_SIZE);\n  }\n\n  // (size == 0 || pos == AES_BLOCK_SIZE)\n  \n  if (size >= 16)\n  {\n    SizeT size2 = size >> 4;\n    g_AesCtr_Code(buf32 + 4, data, size2);\n    size2 <<= 4;\n    data += size2;\n    size -= size2;\n    // (pos == AES_BLOCK_SIZE)\n  }\n\n  // (size < 16)\n  \n  if (size != 0)\n  {\n    unsigned j;\n    const Byte *buf;\n    for (j = 0; j < 4; j++)\n      buf32[j] = 0;\n    g_AesCtr_Code(buf32 + 4, (Byte *)buf32, 1);\n    buf = (const Byte *)buf32;\n    pos = 0;\n    do\n      *data++ ^= buf[pos++];\n    while (--size != 0);\n  }\n  \n  p->pos = pos;\n}\n*/\n\n/* (size != 16 * N) is allowed only for last Filter() call */\n\nZ7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size))\n{\n  // AesCtr2_Code(&_aes, data, size);\n  size = _aesCoder->Filter(data, size);\n  Hmac()->Update(data, size);\n  return size;\n}\n\nZ7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))\n{\n  if (size >= 16)\n    size &= ~(UInt32)15;\n  if (_hmacOverCalc < size)\n  {\n    Hmac()->Update(data + _hmacOverCalc, size - _hmacOverCalc);\n    _hmacOverCalc = size;\n  }\n  // AesCtr2_Code(&_aes, data, size);\n  size = _aesCoder->Filter(data, size);\n  _hmacOverCalc -= size;\n  return size;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/WzAes.h",
    "content": "﻿// Crypto/WzAes.h\n/*\nThis code implements Brian Gladman's scheme\nspecified in \"A Password Based File Encryption Utility\":\n  - AES encryption (128,192,256-bit) in Counter (CTR) mode.\n  - HMAC-SHA1 authentication for encrypted data (10 bytes)\n  - Keys are derived by PPKDF2(RFC2898)-HMAC-SHA1 from ASCII password and\n    Salt (saltSize = aesKeySize / 2).\n  - 2 bytes contain Password Verifier's Code\n*/\n\n#ifndef ZIP7_INC_CRYPTO_WZ_AES_H\n#define ZIP7_INC_CRYPTO_WZ_AES_H\n\n#include \"../../Common/MyBuffer.h\"\n\n#include \"../IPassword.h\"\n\n#include \"HmacSha1.h\"\n#include \"MyAes.h\"\n\nnamespace NCrypto {\nnamespace NWzAes {\n\n/* ICompressFilter::Init() does nothing for this filter.\n\n  Call to init:\n    Encoder:\n      CryptoSetPassword();\n      WriteHeader();\n    Decoder:\n      [CryptoSetPassword();]\n      ReadHeader();\n      [CryptoSetPassword();] Init_and_CheckPassword();\n      [CryptoSetPassword();] Init_and_CheckPassword();\n*/\n\nconst UInt32 kPasswordSizeMax = 99; // 128;\n\nconst unsigned kSaltSizeMax = 16;\nconst unsigned kPwdVerifSize = 2;\nconst unsigned kMacSize = 10;\n\nenum EKeySizeMode\n{\n  kKeySizeMode_AES128 = 1,\n  kKeySizeMode_AES192 = 2,\n  kKeySizeMode_AES256 = 3\n};\n\nstruct CKeyInfo\n{\n  EKeySizeMode KeySizeMode;\n  Byte Salt[kSaltSizeMax];\n  Byte PwdVerifComputed[kPwdVerifSize];\n\n  CByteBuffer Password;\n\n  unsigned GetKeySize()  const { return (8 * KeySizeMode + 8); }\n  unsigned GetSaltSize() const { return (4 * KeySizeMode + 4); }\n  unsigned GetNumSaltWords() const { return (KeySizeMode + 1); }\n\n  CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {}\n\n  void Wipe()\n  {\n    Password.Wipe();\n    Z7_memset_0_ARRAY(Salt);\n    Z7_memset_0_ARRAY(PwdVerifComputed);\n  }\n\n  ~CKeyInfo() { Wipe(); }\n};\n\n/*\nstruct CAesCtr2\n{\n  unsigned pos;\n  CAlignedBuffer aes;\n  UInt32 *Aes() { return (UInt32 *)(Byte *)aes; }\n\n  // unsigned offset;\n  // UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3];\n  // UInt32 *Aes() { return aes + offset; }\n  CAesCtr2();\n};\n\nvoid AesCtr2_Init(CAesCtr2 *p);\nvoid AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size);\n*/\n\nclass CBaseCoder:\n  public ICompressFilter,\n  public ICryptoSetPassword,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_1(ICryptoSetPassword)\n  Z7_COM7F_IMP(Init())\npublic:\n  Z7_IFACE_COM7_IMP(ICryptoSetPassword)\nprotected:\n  CKeyInfo _key;\n\n  // NSha1::CHmac _hmac;\n  // NSha1::CHmac *Hmac() { return &_hmac; }\n  CAlignedBuffer1 _hmacBuf;\n  UInt32 _hmacOverCalc;\n\n  NSha1::CHmac *Hmac() { return (NSha1::CHmac *)(void *)(Byte *)_hmacBuf; }\n\n  // CAesCtr2 _aes;\n  CAesCoder *_aesCoderSpec;\n  CMyComPtr<ICompressFilter> _aesCoder;\n  CBaseCoder():\n    _hmacBuf(sizeof(NSha1::CHmac))\n  {\n    _aesCoderSpec = new CAesCtrCoder(32);\n    _aesCoder = _aesCoderSpec;\n  }\n\n  void Init2();\npublic:\n  unsigned GetHeaderSize() const { return _key.GetSaltSize() + kPwdVerifSize; }\n  unsigned GetAddPackSize() const { return GetHeaderSize() + kMacSize; }\n\n  bool SetKeyMode(unsigned mode)\n  {\n    if (mode < kKeySizeMode_AES128 || mode > kKeySizeMode_AES256)\n      return false;\n    _key.KeySizeMode = (EKeySizeMode)mode;\n    return true;\n  }\n\n  virtual ~CBaseCoder() {}\n};\n\nclass CEncoder Z7_final:\n  public CBaseCoder\n{\n  Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size))\npublic:\n  HRESULT WriteHeader(ISequentialOutStream *outStream);\n  HRESULT WriteFooter(ISequentialOutStream *outStream);\n};\n\nclass CDecoder Z7_final:\n  public CBaseCoder\n  // public ICompressSetDecoderProperties2\n{\n  Byte _pwdVerifFromArchive[kPwdVerifSize];\n  Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size))\npublic:\n  // Z7_IFACE_COM7_IMP(ICompressSetDecoderProperties2)\n  HRESULT ReadHeader(ISequentialInStream *inStream);\n  bool Init_and_CheckPassword();\n  HRESULT CheckMac(ISequentialInStream *inStream, bool &isOK);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/ZipCrypto.cpp",
    "content": "﻿// Crypto/ZipCrypto.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/7zCrc.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"RandGen.h\"\n#include \"ZipCrypto.h\"\n\nnamespace NCrypto {\nnamespace NZip {\n\n#define UPDATE_KEYS(b) { \\\n  key0 = CRC_UPDATE_BYTE(key0, b); \\\n  key1 = (key1 + (key0 & 0xFF)) * 0x8088405 + 1; \\\n  key2 = CRC_UPDATE_BYTE(key2, (Byte)(key1 >> 24)); } \\\n\n#define DECRYPT_BYTE_1 UInt32 temp = key2 | 2;\n#define DECRYPT_BYTE_2 ((Byte)((temp * (temp ^ 1)) >> 8))\n\nZ7_COM7F_IMF(CCipher::CryptoSetPassword(const Byte *data, UInt32 size))\n{\n  UInt32 key0 = 0x12345678;\n  UInt32 key1 = 0x23456789;\n  UInt32 key2 = 0x34567890;\n  \n  for (UInt32 i = 0; i < size; i++)\n    UPDATE_KEYS(data[i])\n\n  KeyMem0 = key0;\n  KeyMem1 = key1;\n  KeyMem2 = key2;\n  \n  return S_OK;\n}\n\nZ7_COM7F_IMF(CCipher::Init())\n{\n  return S_OK;\n}\n\nHRESULT CEncoder::WriteHeader_Check16(ISequentialOutStream *outStream, UInt16 crc)\n{\n  Byte h[kHeaderSize];\n  \n  /* PKZIP before 2.0 used 2 byte CRC check.\n     PKZIP 2.0+ used 1 byte CRC check. It's more secure.\n     We also use 1 byte CRC. */\n\n  MY_RAND_GEN(h, kHeaderSize - 1);\n  // h[kHeaderSize - 2] = (Byte)(crc);\n  h[kHeaderSize - 1] = (Byte)(crc >> 8);\n  \n  RestoreKeys();\n  Filter(h, kHeaderSize);\n  return WriteStream(outStream, h, kHeaderSize);\n}\n\nZ7_COM7F_IMF2(UInt32, CEncoder::Filter(Byte *data, UInt32 size))\n{\n  UInt32 key0 = this->Key0;\n  UInt32 key1 = this->Key1;\n  UInt32 key2 = this->Key2;\n\n  for (UInt32 i = 0; i < size; i++)\n  {\n    Byte b = data[i];\n    DECRYPT_BYTE_1\n    data[i] = (Byte)(b ^ DECRYPT_BYTE_2);\n    UPDATE_KEYS(b)\n  }\n\n  this->Key0 = key0;\n  this->Key1 = key1;\n  this->Key2 = key2;\n\n  return size;\n}\n\nHRESULT CDecoder::ReadHeader(ISequentialInStream *inStream)\n{\n  return ReadStream_FAIL(inStream, _header, kHeaderSize);\n}\n\nvoid CDecoder::Init_BeforeDecode()\n{\n  RestoreKeys();\n  Filter(_header, kHeaderSize);\n}\n\nZ7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))\n{\n  UInt32 key0 = this->Key0;\n  UInt32 key1 = this->Key1;\n  UInt32 key2 = this->Key2;\n  \n  for (UInt32 i = 0; i < size; i++)\n  {\n    DECRYPT_BYTE_1\n    Byte b = (Byte)(data[i] ^ DECRYPT_BYTE_2);\n    UPDATE_KEYS(b)\n    data[i] = b;\n  }\n  \n  this->Key0 = key0;\n  this->Key1 = key1;\n  this->Key2 = key2;\n  \n  return size;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/ZipCrypto.h",
    "content": "﻿// Crypto/ZipCrypto.h\n\n#ifndef ZIP7_INC_CRYPTO_ZIP_CRYPTO_H\n#define ZIP7_INC_CRYPTO_ZIP_CRYPTO_H\n\n#include \"../../Common/MyCom.h\"\n\n#include \"../ICoder.h\"\n#include \"../IPassword.h\"\n\nnamespace NCrypto {\nnamespace NZip {\n\nconst unsigned kHeaderSize = 12;\n\n/* ICompressFilter::Init() does nothing for this filter.\n  Call to init:\n    Encoder:\n      CryptoSetPassword();\n      WriteHeader();\n    Decoder:\n      [CryptoSetPassword();]\n      ReadHeader();\n      [CryptoSetPassword();] Init_and_GetCrcByte();\n      [CryptoSetPassword();] Init_and_GetCrcByte();\n*/\n\nclass CCipher:\n  public ICompressFilter,\n  public ICryptoSetPassword,\n  public CMyUnknownImp\n{\n  Z7_COM_UNKNOWN_IMP_1(ICryptoSetPassword)\n  Z7_COM7F_IMP(Init())\npublic:\n  Z7_IFACE_COM7_IMP(ICryptoSetPassword)\nprotected:\n  UInt32 Key0;\n  UInt32 Key1;\n  UInt32 Key2;\n  \n  UInt32 KeyMem0;\n  UInt32 KeyMem1;\n  UInt32 KeyMem2;\n\n  void RestoreKeys()\n  {\n    Key0 = KeyMem0;\n    Key1 = KeyMem1;\n    Key2 = KeyMem2;\n  }\n\npublic:\n  virtual ~CCipher()\n  {\n    Key0 = KeyMem0 =\n    Key1 = KeyMem1 =\n    Key2 = KeyMem2 = 0;\n  }\n};\n\nclass CEncoder Z7_final: public CCipher\n{\n  Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size))\npublic:\n  HRESULT WriteHeader_Check16(ISequentialOutStream *outStream, UInt16 crc);\n};\n\nclass CDecoder Z7_final: public CCipher\n{\n  Z7_COM7F_IMP2(UInt32, Filter(Byte *data, UInt32 size))\npublic:\n  Byte _header[kHeaderSize];\n  HRESULT ReadHeader(ISequentialInStream *inStream);\n  void Init_BeforeDecode();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/ZipStrong.cpp",
    "content": "﻿// Crypto/ZipStrong.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../C/7zCrc.h\"\n#include \"../../../C/CpuArch.h\"\n\n#include \"../Common/StreamUtils.h\"\n\n#include \"Sha1Cls.h\"\n#include \"ZipStrong.h\"\n\nnamespace NCrypto {\nnamespace NZipStrong {\n\nstatic const UInt16 kAES128 = 0x660E;\n\n/*\n  DeriveKey() function is similar to CryptDeriveKey() from Windows.\n  New version of MSDN contains the following condition in CryptDeriveKey() description:\n    \"If the hash is not a member of the SHA-2 family and the required key is for either 3DES or AES\".\n  Now we support ZipStrong for AES only. And it uses SHA1.\n  Our DeriveKey() code is equal to CryptDeriveKey() in Windows for such conditions: (SHA1 + AES).\n  if (method != AES && method != 3DES), probably we need another code.\n*/\n\nstatic void DeriveKey2(const UInt32 *digest32, Byte c, UInt32 *dest32)\n{\n  const unsigned kBufSize = 64;\n  MY_ALIGN (16)\n  UInt32 buf32[kBufSize / 4];\n  memset(buf32, c, kBufSize);\n  for (unsigned i = 0; i < NSha1::kNumDigestWords; i++)\n    buf32[i] ^= digest32[i];\n  MY_ALIGN (16)\n  NSha1::CContext sha;\n  sha.Init();\n  sha.Update((const Byte *)buf32, kBufSize);\n  sha.Final((Byte *)dest32);\n}\n \nstatic void DeriveKey(NSha1::CContext &sha, Byte *key)\n{\n  MY_ALIGN (16)\n  UInt32 digest32[NSha1::kNumDigestWords];\n  sha.Final((Byte *)digest32);\n  MY_ALIGN (16)\n  UInt32 temp32[NSha1::kNumDigestWords * 2];\n  DeriveKey2(digest32, 0x36, temp32);\n  DeriveKey2(digest32, 0x5C, temp32 + NSha1::kNumDigestWords);\n  memcpy(key, temp32, 32);\n}\n\nvoid CKeyInfo::SetPassword(const Byte *data, UInt32 size)\n{\n  MY_ALIGN (16)\n  NSha1::CContext sha;\n  sha.Init();\n  sha.Update(data, size);\n  DeriveKey(sha, MasterKey);\n}\n\n\n\nCDecoder::CDecoder()\n{\n  CAesCbcDecoder *d = new CAesCbcDecoder();\n  _cbcDecoder = d;\n  _aesFilter = d;\n}\n\nZ7_COM7F_IMF(CDecoder::CryptoSetPassword(const Byte *data, UInt32 size))\n{\n  _key.SetPassword(data, size);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CDecoder::Init())\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF2(UInt32, CDecoder::Filter(Byte *data, UInt32 size))\n{\n  return _aesFilter->Filter(data, size);\n}\n\n\nHRESULT CDecoder::ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize)\n{\n  Byte temp[4];\n  RINOK(ReadStream_FALSE(inStream, temp, 2))\n  _ivSize = GetUi16(temp);\n  if (_ivSize == 0)\n  {\n    memset(_iv, 0, 16);\n    SetUi32(_iv + 0, crc)\n    SetUi64(_iv + 4, unpackSize)\n    _ivSize = 12;\n  }\n  else if (_ivSize == 16)\n  {\n    RINOK(ReadStream_FALSE(inStream, _iv, _ivSize))\n  }\n  else\n    return E_NOTIMPL;\n  RINOK(ReadStream_FALSE(inStream, temp, 4))\n  _remSize = GetUi32(temp);\n  // const UInt32 kAlign = 16;\n  if (_remSize < 16 || _remSize > (1 << 18))\n    return E_NOTIMPL;\n  if (_remSize > _bufAligned.Size())\n  {\n    _bufAligned.AllocAtLeast(_remSize);\n    if (!(Byte *)_bufAligned)\n      return E_OUTOFMEMORY;\n  }\n  return ReadStream_FALSE(inStream, _bufAligned, _remSize);\n}\n\nHRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)\n{\n  passwOK = false;\n  if (_remSize < 16)\n    return E_NOTIMPL;\n  Byte * const p = _bufAligned;\n  const unsigned format = GetUi16a(p);\n  if (format != 3)\n    return E_NOTIMPL;\n  unsigned algId = GetUi16a(p + 2);\n  if (algId < kAES128)\n    return E_NOTIMPL;\n  algId -= kAES128;\n  if (algId > 2)\n    return E_NOTIMPL;\n  const unsigned bitLen = GetUi16a(p + 4);\n  const unsigned flags = GetUi16a(p + 6);\n  if (algId * 64 + 128 != bitLen)\n    return E_NOTIMPL;\n  _key.KeySize = 16 + algId * 8;\n  const bool cert = ((flags & 2) != 0);\n\n  if (flags & 0x4000)\n  {\n    // Use 3DES for rd data\n    return E_NOTIMPL;\n  }\n\n  if (cert)\n  {\n    return E_NOTIMPL;\n  }\n  else\n  {\n    if ((flags & 1) == 0)\n      return E_NOTIMPL;\n  }\n\n  UInt32 rdSize = GetUi16a(p + 8);\n\n  if (rdSize + 16 > _remSize)\n    return E_NOTIMPL;\n\n  const unsigned kPadSize = kAesPadAllign; // is equal to blockSize of cipher for rd\n\n  /*\n  if (cert)\n  {\n    if ((rdSize & 0x7) != 0)\n      return E_NOTIMPL;\n  }\n  else\n  */\n  {\n    // PKCS7 padding\n    if (rdSize < kPadSize)\n      return E_NOTIMPL;\n    if (rdSize & (kPadSize - 1))\n      return E_NOTIMPL;\n  }\n\n  memmove(p, p + 10, rdSize);\n  const Byte *p2 = p + rdSize + 10;\n  UInt32 reserved = GetUi32(p2);\n  p2 += 4;\n  \n  /*\n  if (cert)\n  {\n    UInt32 numRecipients = reserved;\n\n    if (numRecipients == 0)\n      return E_NOTIMPL;\n\n    {\n      UInt32 hashAlg = GetUi16(p2);\n      hashAlg = hashAlg;\n      UInt32 hashSize = GetUi16(p2 + 2);\n      hashSize = hashSize;\n      p2 += 4;\n\n      reserved = reserved;\n      // return E_NOTIMPL;\n\n      for (unsigned r = 0; r < numRecipients; r++)\n      {\n        UInt32 specSize = GetUi16(p2);\n        p2 += 2;\n        p2 += specSize;\n      }\n    }\n  }\n  else\n  */\n  {\n    if (reserved != 0)\n      return E_NOTIMPL;\n  }\n\n  UInt32 validSize = GetUi16(p2);\n  p2 += 2;\n  const size_t validOffset = (size_t)(p2 - p);\n  if ((validSize & 0xF) != 0 || validOffset + validSize != _remSize)\n    return E_NOTIMPL;\n\n  {\n    RINOK(_cbcDecoder->SetKey(_key.MasterKey, _key.KeySize))\n    RINOK(_cbcDecoder->SetInitVector(_iv, 16))\n    // SetInitVector() calls also Init()\n    RINOK(_cbcDecoder->Init()) // it's optional\n    Filter(p, rdSize);\n\n    rdSize -= kPadSize;\n    for (unsigned i = 0; i < kPadSize; i++)\n      if (p[(size_t)rdSize + i] != kPadSize)\n        return S_OK; // passwOK = false;\n  }\n\n  MY_ALIGN (16)\n  Byte fileKey[32];\n  MY_ALIGN (16)\n  NSha1::CContext sha;\n  sha.Init();\n  sha.Update(_iv, _ivSize);\n  sha.Update(p, rdSize);\n  DeriveKey(sha, fileKey);\n  \n  RINOK(_cbcDecoder->SetKey(fileKey, _key.KeySize))\n  RINOK(_cbcDecoder->SetInitVector(_iv, 16))\n  // SetInitVector() calls also Init()\n  RINOK(_cbcDecoder->Init()) // it's optional\n\n  memmove(p, p + validOffset, validSize);\n  Filter(p, validSize);\n\n  if (validSize < 4)\n    return E_NOTIMPL;\n  validSize -= 4;\n  if (GetUi32(p + validSize) != CrcCalc(p, validSize))\n    return S_OK;\n  passwOK = true;\n  return S_OK;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Crypto/ZipStrong.h",
    "content": "﻿// Crypto/ZipStrong.h\n\n#ifndef ZIP7_INC_CRYPTO_ZIP_STRONG_H\n#define ZIP7_INC_CRYPTO_ZIP_STRONG_H\n\n#include \"../../Common/MyBuffer2.h\"\n\n#include \"../IPassword.h\"\n\n#include \"MyAes.h\"\n\nnamespace NCrypto {\nnamespace NZipStrong {\n\n/* ICompressFilter::Init() does nothing for this filter.\n  Call to init:\n    Decoder:\n      [CryptoSetPassword();]\n      ReadHeader();\n      [CryptoSetPassword();] Init_and_CheckPassword();\n      [CryptoSetPassword();] Init_and_CheckPassword();\n*/\n\nstruct CKeyInfo\n{\n  Byte MasterKey[32];\n  UInt32 KeySize;\n  \n  void SetPassword(const Byte *data, UInt32 size);\n\n  void Wipe()\n  {\n    Z7_memset_0_ARRAY(MasterKey);\n  }\n};\n\n\nconst unsigned kAesPadAllign = AES_BLOCK_SIZE;\n\nZ7_CLASS_IMP_COM_2(\n  CDecoder\n  , ICompressFilter\n  , ICryptoSetPassword\n)\n  CAesCbcDecoder *_cbcDecoder;\n  CMyComPtr<ICompressFilter> _aesFilter;\n  CKeyInfo _key;\n  CAlignedBuffer _bufAligned;\n\n  UInt32 _ivSize;\n  Byte _iv[16];\n  UInt32 _remSize;\npublic:\n  HRESULT ReadHeader(ISequentialInStream *inStream, UInt32 crc, UInt64 unpackSize);\n  HRESULT Init_and_CheckPassword(bool &passwOK);\n  UInt32 GetPadSize(UInt32 packSize32) const\n  {\n    // Padding is to align to blockSize of cipher.\n    // Change it, if is not AES\n    return kAesPadAllign - (packSize32 & (kAesPadAllign - 1));\n  }\n  CDecoder();\n  ~CDecoder() { Wipe(); }\n  void Wipe()\n  {\n    Z7_memset_0_ARRAY(_iv);\n    _key.Wipe();\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/GuiCommon.rc",
    "content": "#include <windows.h>\n\n// #include <winnt.h>\n// #include <WinUser.h>\n\n// for Windows CE:\n#include <CommCtrl.h>\n\n\nLANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US\n\n#undef m\n#undef bxs\n#undef bys\n#undef bxsDots\n#undef y\n#undef xc\n#undef yc\n#undef xs\n#undef ys\n#undef bx\n#undef bx1\n#undef bx2\n#undef bx3\n#undef by\n#undef by1\n#undef by2\n#undef by3\n#undef gSpace\n#undef gSize\n#undef marg2\n#undef marg3\n\n#undef MY_DIALOG\n#undef MY_RESIZE_DIALOG\n#undef MY_PAGE\n\n#define m 8\n#define bxs 64\n#define bys 16\n#define bxsDots 20\n\n#define xs (xc + m + m)\n#define ys (yc + m + m)\n\n#define bx1 (xs - m - bxs)\n#define bx2 (bx1 - m - bxs)\n#define bx3 (bx2 - m - bxs)\n#define bx bx1\n\n#define by1 (ys - m - bys)\n#define by2 (by1 - m - bys)\n#define by by1\n\n\n#define MY_MODAL_DIALOG_STYLE  STYLE  DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU\n#define MY_MODAL_RESIZE_DIALOG_STYLE  MY_MODAL_DIALOG_STYLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX | WS_THICKFRAME\n\n#define MY_PAGE_STYLE  STYLE  WS_CHILD | WS_DISABLED | WS_CAPTION\n\n#define MY_FONT  FONT 8, \"MS Shell Dlg\"\n\n#define MY_MODAL_DIALOG_POSTFIX  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT\n\n#define SMALL_PAGE_SIZE_X 120\n\n// #define MY_DIALOG         DIALOG 0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT\n// #define MY_RESIZE_DIALOG  DIALOG 0, 0, xs, ys  MY_MODAL_RESIZE_DIALOG_STYLE  MY_FONT\n#define MY_PAGE_POSTFIX   0, 0, xs, ys  MY_PAGE_STYLE  MY_FONT\n#define MY_PAGE           DIALOG MY_PAGE_POSTFIX\n\n#define OK_CANCEL \\\n  DEFPUSHBUTTON  \"OK\",     IDOK,     bx2, by, bxs, bys \\\n  PUSHBUTTON     \"Cancel\", IDCANCEL, bx1, by, bxs, bys\n\n#define CONTINUE_CANCEL \\\n  DEFPUSHBUTTON  \"Continue\",IDCONTINUE, bx2, by, bxs, bys \\\n  PUSHBUTTON     \"Cancel\",  IDCANCEL,   bx1, by, bxs, bys\n\n#define MY_BUTTON__CLOSE \\\n  DEFPUSHBUTTON  \"&Close\", IDCLOSE,  bx1, by, bxs, bys\n\n\n#define MY_COMBO  CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP\n#define MY_COMBO_SORTED  MY_COMBO | CBS_SORT\n#define MY_COMBO_WITH_EDIT  CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP\n\n#define MY_CHECKBOX \"Button\", BS_AUTOCHECKBOX | WS_TABSTOP\n\n#define cboxColonSize 18\n#define colonString \":\"\n\n#define MY_CONTROL_CHECKBOX(_text,_id,_x,_y,_xsize)  CONTROL _text, _id, MY_CHECKBOX, _x,_y,_xsize,10\n#define MY_CONTROL_CHECKBOX_2LINES(_text,_id,_x,_y,_xsize)  CONTROL _text, _id, MY_CHECKBOX | BS_MULTILINE, _x,_y,_xsize,16\n#define MY_CONTROL_CHECKBOX_COLON(_id,_x,_y)  MY_CONTROL_CHECKBOX( colonString, _id, _x,_y,cboxColonSize)\n\n#define MY_AUTORADIOBUTTON \"Button\", BS_AUTORADIOBUTTON\n#define MY_AUTORADIOBUTTON_GROUP MY_AUTORADIOBUTTON | WS_GROUP\n\n#define MY_CONTROL_AUTORADIOBUTTON(_text,_id,_x,_y,_xsize)  CONTROL _text, _id, MY_AUTORADIOBUTTON, _x,_y,_xsize,10\n#define MY_CONTROL_AUTORADIOBUTTON_GROUP(_text,_id,_x,_y,_xsize)  CONTROL _text, _id, MY_AUTORADIOBUTTON_GROUP, _x,_y,_xsize,10\n\n#define MY_TEXT_NOPREFIX 8, SS_NOPREFIX\n\n\n// WS_EX_CLIENTEDGE\n#define MY_CONTROL_EDIT_WITH_SPIN(_id_edit, _id_spin, _text,  _x, _y, _xSize) \\\n  EDITTEXT _id_edit,  _x, _y, _xSize, 12,  ES_CENTER | ES_NUMBER | ES_AUTOHSCROLL \\\n  CONTROL  _text, _id_spin,  L\"msctls_updown32\", \\\n        UDS_SETBUDDYINT   \\\n      | UDS_ALIGNRIGHT    \\\n      | UDS_AUTOBUDDY     \\\n      | UDS_ARROWKEYS     \\\n      | UDS_NOTHOUSANDS,  \\\n      _x + _xSize, _y, 8, 12  // these values are unused\n\n\n#define OPTIONS_PAGE_XC_SIZE 300\n#define OPTIONS_PAGE_YC_SIZE 280\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/Guid.txt",
    "content": "﻿{23170F69-40C1-278A-0000-00yy00xx0000}\n\n00 IProgress.h\n\n  05  IProgress\n  // 050002  IProgress2\n\n01 IFolderArchive.h\n\n  // 05  IArchiveFolder   // old \n  // 06  IInFolderArchive // old\n  07  IFileExtractCallback.h::IFolderArchiveExtractCallback\n  08  IFileExtractCallback.h::IFolderArchiveExtractCallback2\n  // 0A  IOutFolderArchive\n  0B  IFolderArchiveUpdateCallback\n  0C  Agent.h::IArchiveFolderInternal\n  0D  IArchiveFolder\n  0E  IInFolderArchive\n  0F  IOutFolderArchive\n  10  IFolderArchiveUpdateCallback2\n  11  IFolderScanProgress\n  12  IFolderSetZoneIdMode\n  13  IFolderSetZoneIdFile\n  14  IFolderArchiveUpdateCallback_MoveArc\n  \n  20  IFileExtractCallback.h::IGetProp\n  30  IFileExtractCallback.h::IFolderExtractToStreamCallback (old)\n  31  IFileExtractCallback.h::IFolderExtractToStreamCallback (new 21.04)\n\n03 IStream.h\n\n  01  ISequentialInStream\n  02  ISequentialOutStream\n  03  IInStream\n  04  IOutStream\n\n  06  IStreamGetSize\n  07  IOutStreamFinish\n  08  IStreamGetProps\n  09  IStreamGetProps2\n  0A  IStreamGetProp\n\n  10  IStreamSetRestriction\n\n\n04 ICoder.h\n\n  04  ICompressProgressInfo\n  05  ICompressCoder\n  18  ICompressCoder2\n  1F  ICompressSetCoderPropertiesOpt\n  20  ICompressSetCoderProperties\n  21  ICompressSetDecoderProperties //\n  22  ICompressSetDecoderProperties2\n  23  ICompressWriteCoderProperties\n  24  ICompressGetInStreamProcessedSize\n  25  ICompressSetCoderMt\n  26  ICompressSetFinishMode\n  27  ICompressGetInStreamProcessedSize2\n  28  ICompressSetMemLimit\n  29  ICompressReadUnusedFromInBuf\n\n  30  ICompressGetSubStreamSize\n  31  ICompressSetInStream\n  32  ICompressSetOutStream\n//  33  ICompressSetInStreamSize\n  34  ICompressSetOutStreamSize\n  35  ICompressSetBufSize\n  36  ICompressInitEncoder\n  37  ICompressSetInStream2\n//  38  ICompressSetOutStream2\n//  39  SetInStreamSize2\n//  3A  SetOutStreamSize2\n\n  40  ICompressFilter\n  60  ICompressCodecsInfo\n  61  ISetCompressCodecsInfo\n  80  ICryptoProperties\n  88  ICryptoResetSalt\n  8C  ICryptoResetInitVector\n  90  ICryptoSetPassword\n  A0  ICryptoSetCRC\n  C0  IHasher\n  C1  IHashers\n\n\n05 IPassword.h\n\n  10 ICryptoGetTextPassword\n  11 ICryptoGetTextPassword2\n\n\n06 IArchive.h\n\n  03  ISetProperties\n  04  IArchiveKeepModeForNextOpen\n  05  IArchiveAllowTail\n\n  09  IArchiveRequestMemoryUseCallback\n\n  10  IArchiveOpenCallback\n  \n  20  IArchiveExtractCallback\n  21  IArchiveExtractCallbackMessage  (deprecated in v23)\n  22  IArchiveExtractCallbackMessage2 (new in v23)\n  \n  30  IArchiveOpenVolumeCallback\n  40  IInArchiveGetStream\n  50  IArchiveOpenSetSubArchiveName\n  60  IInArchive\n  61  IArchiveOpenSeq\n  70  IArchiveGetRawProps\n  71  IArchiveGetRootProps\n\n  80  IArchiveUpdateCallback\n  82  IArchiveUpdateCallback2\n  83  IArchiveUpdateCallbackFile\n  84  IArchiveGetDiskProperty\n  85  IArchiveUpdateCallbackArcProp (Reserved)\n\n\n  A0  IOutArchive\n\n\n\n08 IFolder.h\n\n  00 IFolderFolder\n  01 IEnumProperties\n  02 IFolderGetTypeID\n  03 IFolderGetPath\n  04 IFolderWasChanged\n  05 // IFolderReload\n  06 // IFolderOperations old\n  07 IFolderGetSystemIconIndex\n  08 IFolderGetItemFullSize\n  09 IFolderClone\n  0A IFolderSetFlatMode\n  0B IFolderOperationsExtractCallback\n  0C // \n  0D // \n  0E IFolderProperties\n  0F \n  10 IFolderArcProps\n  11 IGetFolderArcProps\n  12 // IFolderOperations\n  13 IFolderOperations\n  14 IFolderCalcItemFullSize\n  15 IFolderCompare\n  16 IFolderGetItemName\n  17 IFolderAltStreams\n\n\n09 IFolder.h :: FOLDER_MANAGER_INTERFACE\n\n  00 - 04 // old IFolderManager\n  05 IFolderManager\n\n\n// 0A PluginInterface.h\n  00 IInitContextMenu\n  01 IPluginOptionsCallback\n  02 IPluginOptions\n\n\nHandler GUIDs:\n\n{23170F69-40C1-278A-1000-000110xx0000}\n\n  01 Zip\n  02 BZip2\n  03 Rar\n  04 Arj\n  05 Z\n  06 Lzh\n  07 7z\n  08 Cab\n  09 Nsis\n  0A lzma\n  0B lzma86\n  0C xz\n  0D ppmd\n  0E zstd\n// **************** 7-Zip ZS Modification Start ****************\n  0F lz4\n  10 lz5\n  11 liz\n  12 Lzip\n// **************** 7-Zip ZS Modification End ****************\n\n  BF LVM\n  C0 AVB\n  C1 LP\n  C2 Sparse\n  C3 APFS\n  C4 Vhdx\n  C5 Base64\n  C6 COFF\n  C7 Ext\n  C8 VMDK\n  C9 VDI\n  CA Qcow\n  CB GPT\n  CC Rar5\n  CD IHex\n  CE Hxs\n  CF TE\n  D0 UEFIc\n  D1 UEFIs\n  D2 SquashFS\n  D3 CramFS\n  D4 APM\n  D5 Mslz\n  D6 Flv\n  D7 Swf\n  D8 Swfc\n  D9 Ntfs\n  DA Fat\n  DB Mbr\n  DC Vhd\n  DD Pe\n  DE Elf\n  DF Mach-O\n  E0 Udf\n  E1 Xar\n  E2 Mub\n  E3 Hfs\n  E4 Dmg\n  E5 Compound\n  E6 Wim\n  E7 Iso\n  E8 \n  E9 Chm\n  EA Split\n  EB Rpm\n  EC Deb\n  ED Cpio\n  EE Tar\n  EF GZip\n\n{23170F69-40C1-278A-1000-000100020000} ContextMenu.h::CZipContextMenu\n\n// {23170F69-40C1-278A-1000-000100030000} // CAgentArchiveHandler\n// {23170F69-40C1-278B- old codecs clsids\n// {23170F69-40C1-278D-1000-000100020000} OptionsDialog.h::CLSID_CSevenZipOptions\n\n{23170F69-40C1-2790-id} Codec Decoders\n{23170F69-40C1-2791-id} Codec Encoders\n{23170F69-40C1-2792-id} Hashers\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/ICoder.h",
    "content": "﻿// ICoder.h\n\n#ifndef ZIP7_INC_ICODER_H\n#define ZIP7_INC_ICODER_H\n\n#include \"IStream.h\"\n\nZ7_PURE_INTERFACES_BEGIN\n\n#define Z7_IFACE_CONSTR_CODER(i, n) \\\n  Z7_DECL_IFACE_7ZIP(i, 4, n) \\\n  { Z7_IFACE_COM7_PURE(i) };\n\n#define Z7_IFACEM_ICompressProgressInfo(x) \\\n  x(SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\nZ7_IFACE_CONSTR_CODER(ICompressProgressInfo, 0x04)\n  /*\n    SetRatioInfo()\n     (inSize)  can be NULL, if unknown\n     (outSize) can be NULL, if unknown\n  returns:\n    S_OK\n    E_ABORT  : Break by user\n    another error codes\n  */\n\n#define Z7_IFACEM_ICompressCoder(x) \\\n  x(Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, \\\n      const UInt64 *inSize, const UInt64 *outSize, \\\n      ICompressProgressInfo *progress))\nZ7_IFACE_CONSTR_CODER(ICompressCoder, 0x05)\n\n#define Z7_IFACEM_ICompressCoder2(x) \\\n  x(Code(ISequentialInStream * const *inStreams, const UInt64  *const *inSizes, UInt32 numInStreams, \\\n      ISequentialOutStream *const *outStreams, const UInt64 *const *outSizes, UInt32 numOutStreams, \\\n      ICompressProgressInfo *progress))\nZ7_IFACE_CONSTR_CODER(ICompressCoder2, 0x18)\n\n/*\n  ICompressCoder::Code\n  ICompressCoder2::Code\n  \n  returns:\n    S_OK     : OK\n    S_FALSE  : data error (for decoders)\n    E_OUTOFMEMORY : memory allocation error\n    E_NOTIMPL : unsupported encoding method (for decoders)\n    another error code : some error. For example, it can be error code received from inStream or outStream function.\n  \n  Parameters:\n    (inStream != NULL)\n    (outStream != NULL)\n\n    if (inSize != NULL)\n    {\n      Encoders in 7-Zip ignore (inSize).\n      Decoder can use (*inSize) to check that stream was decoded correctly.\n      Some decoders in 7-Zip check it, if (full_decoding mode was set via ICompressSetFinishMode)\n    }\n\n    If it's required to limit the reading from input stream (inStream), it can\n      be done with ISequentialInStream implementation.\n\n    if (outSize != NULL)\n    {\n      Encoders in 7-Zip ignore (outSize).\n      Decoder unpacks no more than (*outSize) bytes.\n    }\n    \n    (progress == NULL) is allowed.\n\n\n  Decoding with Code() function\n  -----------------------------\n   \n  You can request some interfaces before decoding\n   - ICompressSetDecoderProperties2\n   - ICompressSetFinishMode\n\n  If you need to decode full stream:\n  {\n    1) try to set full_decoding mode with ICompressSetFinishMode::SetFinishMode(1);\n    2) call the Code() function with specified (inSize) and (outSize), if these sizes are known.\n  }\n\n  If you need to decode only part of stream:\n  {\n    1) try to set partial_decoding mode with ICompressSetFinishMode::SetFinishMode(0);\n    2) Call the Code() function with specified (inSize = NULL) and specified (outSize).\n  }\n\n  Encoding with Code() function\n  -----------------------------\n  \n  You can request some interfaces :\n  - ICompressSetCoderProperties   - use it before encoding to set properties\n  - ICompressWriteCoderProperties - use it before or after encoding to request encoded properties.\n\n  ICompressCoder2 is used when (numInStreams != 1 || numOutStreams != 1)\n     The rules are similar to ICompressCoder rules\n*/\n\n\nnamespace NCoderPropID\n{\n  enum EEnum\n  {\n    kDefaultProp = 0,\n    kDictionarySize,    // VT_UI4\n    kUsedMemorySize,    // VT_UI4\n    kOrder,             // VT_UI4\n    kBlockSize,         // VT_UI4 or VT_UI8\n    kPosStateBits,      // VT_UI4\n    kLitContextBits,    // VT_UI4\n    kLitPosBits,        // VT_UI4\n    kNumFastBytes,      // VT_UI4\n    kMatchFinder,       // VT_BSTR\n    kMatchFinderCycles, // VT_UI4\n    kNumPasses,         // VT_UI4\n    kAlgorithm,         // VT_UI4\n    kNumThreads,        // VT_UI4\n    kEndMarker,         // VT_BOOL\n    kLevel,             // VT_UI4\n    kReduceSize,        // VT_UI8 : it's estimated size of largest data stream that will be compressed\n                        //   encoder can use this value to reduce dictionary size and allocate data buffers\n\n    kExpectedDataSize,  // VT_UI8 : for ICompressSetCoderPropertiesOpt :\n                        //   it's estimated size of current data stream\n                        //   real data size can differ from that size\n                        //   encoder can use this value to optimize encoder initialization\n\n    kBlockSize2,        // VT_UI4 or VT_UI8\n    kCheckSize,         // VT_UI4 : size of digest in bytes\n    kFilter,            // VT_BSTR\n    kMemUse,            // VT_UI8\n    kAffinity,          // VT_UI8\n    kBranchOffset,      // VT_UI4\n    kHashBits,          // VT_UI4\n    kNumThreadGroups,   // VT_UI4\n    kThreadGroup,       // VT_UI4\n    kAffinityInGroup,   // VT_UI8\n    /*\n    // kHash3Bits,          // VT_UI4\n    // kHash2Bits,          // VT_UI4\n    // kChainBits,         // VT_UI4\n    kChainSize,         // VT_UI4\n    kNativeLevel,       // VT_UI4\n    kFast,              // VT_UI4\n    kMinMatch,          // VT_UI4 The minimum slen is 3 and the maximum is 7.\n    kOverlapLog,        // VT_UI4 The minimum ovlog is 0 and the maximum is 9.  (default: 6)\n    kRowMatchFinder,    // VT_BOOL\n    kLdmEnable,         // VT_BOOL\n    // kLdmWindowSizeLog,  // VT_UI4\n    kLdmWindowSize,     // VT_UI4\n    kLdmHashLog,        // VT_UI4 The minimum ldmhlog is 6 and the maximum is 26 (default: 20).\n    kLdmMinMatchLength, // VT_UI4 The minimum ldmslen is 4 and the maximum is 4096 (default: 64).\n    kLdmBucketSizeLog,  // VT_UI4 The minimum ldmblog is 0 and the maximum is 8 (default: 3).\n    kLdmHashRateLog,    // VT_UI4 The default value is wlog - ldmhlog.\n    kWriteUnpackSizeFlag, // VT_BOOL\n    kUsePledged,        // VT_BOOL\n    kUseSizeHintPledgedForSmall, // VT_BOOL\n    kUseSizeHintForEach, // VT_BOOL\n    kUseSizeHintGlobal, // VT_BOOL\n    kParamSelectMode,   // VT_UI4\n    // kSearchLog,         // VT_UI4 The minimum slog is 1 and the maximum is 26\n    // kTargetLen,         // VT_UI4 The minimum tlen is 0 and the maximum is 999.\n    */\n    // **************** 7-Zip ZS Modification Start ****************\n    /* zstd props */\n    kStrategy,          // VT_UI4 1=ZSTD_fast, 2=ZSTD_dfast, 3=ZSTD_greedy, 4=ZSTD_lazy, 5=ZSTD_lazy2, 6=ZSTD_btlazy2, 7=ZSTD_btopt, 8=ZSTD_btultra\n    kFast,              // VT_UI4 The minimum fast is 1 and the maximum is 64 (default: unused)\n    kLong,              // VT_UI4 The minimum long is 10 (1KiB) and the maximum is 30 (1GiB) on x32 and 31 (2GiB) on x64\n    kWindowLog,         // VT_UI4 The minimum long is 10 (1KiB) and the maximum is 30 (1GiB) on x32 and 31 (2GiB) on x64\n    kHashLog,           // VT_UI4 The minimum hlog is 6 (64 B) and the maximum is 26 (128 MiB).\n    kChainLog,          // VT_UI4 The minimum clog is 6 (64 B) and the maximum is 28 (256 MiB)\n    kSearchLog,         // VT_UI4 The minimum slog is 1 and the maximum is 26\n    kMinMatch,          // VT_UI4 The minimum slen is 3 and the maximum is 7.\n    kTargetLen,         // VT_UI4 The minimum tlen is 0 and the maximum is 999.\n    kOverlapLog,        // VT_UI4 The minimum ovlog is 0 and the maximum is 9.  (default: 6)\n    kLdmHashLog,        // VT_UI4 The minimum ldmhlog is 6 and the maximum is 26 (default: 20).\n    kLdmSearchLength,   // VT_UI4 The minimum ldmslen is 4 and the maximum is 4096 (default: 64).\n    kLdmBucketSizeLog,  // VT_UI4 The minimum ldmblog is 0 and the maximum is 8 (default: 3).\n    kLdmHashRateLog,    // VT_UI4 The default value is wlog - ldmhlog.\n    kAdvMax,            // VT_BOOL 1=ZSTD --max (advanced max compression)\n    // **************** 7-Zip ZS Modification End ****************\n    k_NUM_DEFINED\n  };\n}\n\n// **************** 7-Zip ZS Modification Start ****************\n/* level inverter used to wrap to/from fast levels */\n#define Z7_ZSTD_FAST_LEV_INC  32\n\n/* artificial level used to specify max possible level (for ZSTD advanced max compression, equivalent of --max) */\n#define Z7_ZSTD_ULTIMATE_LEV  255\n\n#if !defined (Z7_ZSTD_ADVMAX_ALLOWED) && INTPTR_MAX == INT64_MAX // allowed for 64-bit only\n#define Z7_ZSTD_ADVMAX_ALLOWED 1\n#endif\n// **************** 7-Zip ZS Modification End ****************\n\n#define Z7_IFACEM_ICompressSetCoderPropertiesOpt(x) \\\n  x(SetCoderPropertiesOpt(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\nZ7_IFACE_CONSTR_CODER(ICompressSetCoderPropertiesOpt, 0x1F)\n\n\n#define Z7_IFACEM_ICompressSetCoderProperties(x) \\\n  x(SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps))\nZ7_IFACE_CONSTR_CODER(ICompressSetCoderProperties, 0x20)\n\n/*\n#define Z7_IFACEM_ICompressSetDecoderProperties(x) \\\n  x(SetDecoderProperties(ISequentialInStream *inStream))\nZ7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties, 0x21)\n*/\n\n#define Z7_IFACEM_ICompressSetDecoderProperties2(x) \\\n  x(SetDecoderProperties2(const Byte *data, UInt32 size))\nZ7_IFACE_CONSTR_CODER(ICompressSetDecoderProperties2, 0x22)\n  /* returns:\n    S_OK\n    E_NOTIMP      : unsupported properties\n    E_INVALIDARG  : incorrect (or unsupported) properties\n    E_OUTOFMEMORY : memory allocation error\n  */\n\n\n#define Z7_IFACEM_ICompressWriteCoderProperties(x) \\\n  x(WriteCoderProperties(ISequentialOutStream *outStream))\nZ7_IFACE_CONSTR_CODER(ICompressWriteCoderProperties, 0x23)\n\n#define Z7_IFACEM_ICompressGetInStreamProcessedSize(x) \\\n  x(GetInStreamProcessedSize(UInt64 *value))\nZ7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize, 0x24)\n\n#define Z7_IFACEM_ICompressSetCoderMt(x) \\\n  x(SetNumberOfThreads(UInt32 numThreads))\nZ7_IFACE_CONSTR_CODER(ICompressSetCoderMt, 0x25)\n\n#define Z7_IFACEM_ICompressSetFinishMode(x) \\\n  x(SetFinishMode(UInt32 finishMode))\nZ7_IFACE_CONSTR_CODER(ICompressSetFinishMode, 0x26)\n  /* finishMode:\n    0 : partial decoding is allowed. It's default mode for ICompressCoder::Code(), if (outSize) is defined.\n    1 : full decoding. The stream must be finished at the end of decoding. */\n\n#define Z7_IFACEM_ICompressGetInStreamProcessedSize2(x) \\\n  x(GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value))\nZ7_IFACE_CONSTR_CODER(ICompressGetInStreamProcessedSize2, 0x27)\n\n#define Z7_IFACEM_ICompressSetMemLimit(x) \\\n  x(SetMemLimit(UInt64 memUsage))\nZ7_IFACE_CONSTR_CODER(ICompressSetMemLimit, 0x28)\n\n\n/*\n  ICompressReadUnusedFromInBuf is supported by ICoder object\n  call ReadUnusedFromInBuf() after ICoder::Code(inStream, ...).\n  ICoder::Code(inStream, ...) decodes data, and the ICoder object is allowed\n  to read from inStream to internal buffers more data than minimal data required for decoding.\n  So we can call ReadUnusedFromInBuf() from same ICoder object to read unused input\n  data from the internal buffer.\n  in ReadUnusedFromInBuf(): the Coder is not allowed to use (ISequentialInStream *inStream) object, that was sent to ICoder::Code().\n*/\n#define Z7_IFACEM_ICompressReadUnusedFromInBuf(x) \\\n  x(ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize))\nZ7_IFACE_CONSTR_CODER(ICompressReadUnusedFromInBuf, 0x29)\n\n\n#define Z7_IFACEM_ICompressGetSubStreamSize(x) \\\n  x(GetSubStreamSize(UInt64 subStream, UInt64 *value))\nZ7_IFACE_CONSTR_CODER(ICompressGetSubStreamSize, 0x30)\n  /* returns:\n    S_OK     : (*value) contains the size or estimated size (can be incorrect size)\n    S_FALSE  : size is undefined\n    E_NOTIMP : the feature is not implemented\n  Let's (read_size) is size of data that was already read by ISequentialInStream::Read().\n  The caller should call GetSubStreamSize() after each Read() and check sizes:\n    if (start_of_subStream + *value < read_size)\n    {\n      // (*value) is correct, and it's allowed to call GetSubStreamSize() for next subStream:\n      start_of_subStream += *value;\n      subStream++;\n    }\n  */\n\n#define Z7_IFACEM_ICompressSetInStream(x) \\\n  x(SetInStream(ISequentialInStream *inStream)) \\\n  x(ReleaseInStream())\nZ7_IFACE_CONSTR_CODER(ICompressSetInStream, 0x31)\n\n#define Z7_IFACEM_ICompressSetOutStream(x) \\\n  x(SetOutStream(ISequentialOutStream *outStream)) \\\n  x(ReleaseOutStream())\nZ7_IFACE_CONSTR_CODER(ICompressSetOutStream, 0x32)\n\n/*\n#define Z7_IFACEM_ICompressSetInStreamSize(x) \\\n  x(SetInStreamSize(const UInt64 *inSize)) \\\nZ7_IFACE_CONSTR_CODER(ICompressSetInStreamSize, 0x33)\n*/\n\n#define Z7_IFACEM_ICompressSetOutStreamSize(x) \\\n  x(SetOutStreamSize(const UInt64 *outSize))\nZ7_IFACE_CONSTR_CODER(ICompressSetOutStreamSize, 0x34)\n  /* That function initializes decoder structures.\n     Call this function only for stream version of decoder.\n       if (outSize == NULL), then output size is unknown\n       if (outSize != NULL), then the decoder must stop decoding after (*outSize) bytes. */\n\n#define Z7_IFACEM_ICompressSetBufSize(x) \\\n  x(SetInBufSize(UInt32 streamIndex, UInt32 size)) \\\n  x(SetOutBufSize(UInt32 streamIndex, UInt32 size))\n \nZ7_IFACE_CONSTR_CODER(ICompressSetBufSize, 0x35)\n\n#define Z7_IFACEM_ICompressInitEncoder(x) \\\n  x(InitEncoder())\nZ7_IFACE_CONSTR_CODER(ICompressInitEncoder, 0x36)\n  /* That function initializes encoder structures.\n     Call this function only for stream version of encoder. */\n\n#define Z7_IFACEM_ICompressSetInStream2(x) \\\n  x(SetInStream2(UInt32 streamIndex, ISequentialInStream *inStream)) \\\n  x(ReleaseInStream2(UInt32 streamIndex))\nZ7_IFACE_CONSTR_CODER(ICompressSetInStream2, 0x37)\n\n/*\n#define Z7_IFACEM_ICompressSetOutStream2(x) \\\n  x(SetOutStream2(UInt32 streamIndex, ISequentialOutStream *outStream))\n  x(ReleaseOutStream2(UInt32 streamIndex))\nZ7_IFACE_CONSTR_CODER(ICompressSetOutStream2, 0x38)\n\n#define Z7_IFACEM_ICompressSetInStreamSize2(x) \\\n  x(SetInStreamSize2(UInt32 streamIndex, const UInt64 *inSize))\nZ7_IFACE_CONSTR_CODER(ICompressSetInStreamSize2, 0x39)\n*/\n\n/*\n#define Z7_IFACEM_ICompressInSubStreams(x) \\\n  x(GetNextInSubStream(UInt64 *streamIndexRes, ISequentialInStream **stream))\nZ7_IFACE_CONSTR_CODER(ICompressInSubStreams, 0x3A)\n\n#define Z7_IFACEM_ICompressOutSubStreams(x) \\\n  x(GetNextOutSubStream(UInt64 *streamIndexRes, ISequentialOutStream **stream))\nZ7_IFACE_CONSTR_CODER(ICompressOutSubStreams, 0x3B)\n*/\n\n/*\n  ICompressFilter\n  Filter(Byte *data, UInt32 size)\n  (size)\n     converts as most as possible bytes required for fast processing.\n     Some filters have (smallest_fast_block).\n     For example, (smallest_fast_block == 16) for AES CBC/CTR filters.\n     If data stream is not finished, caller must call Filter() for larger block:\n     where (size >= smallest_fast_block).\n     if (size >= smallest_fast_block)\n     {\n       The filter can leave some bytes at the end of data without conversion:\n       if there are data alignment reasons or speed reasons.\n       The caller can read additional data from stream and call Filter() again.\n     }\n     If data stream was finished, caller can call Filter() for (size < smallest_fast_block)\n\n  (data) parameter:\n     Some filters require alignment for any Filter() call:\n        1) (stream_offset % alignment_size) == (data % alignment_size)\n        2) (alignment_size == 2^N)\n     where (stream_offset) - is the number of bytes that were already filtered before.\n     The callers of Filter() are required to meet these requirements.\n     (alignment_size) can be different:\n           16 : for AES filters\n       4 or 2 : for some branch convert filters\n            1 : for another filters\n     (alignment_size >= 16) is enough for all current filters of 7-Zip.\n     But the caller can use larger (alignment_size).\n     Recommended alignment for (data) of Filter() call is (alignment_size == 64).\n     Also it's recommended to use aligned value for (size):\n       (size % alignment_size == 0),\n     if it's not last call of Filter() for current stream.\n\n  returns: (outSize):\n       if (outSize == 0) : Filter have not converted anything.\n           So the caller can stop processing, if data stream was finished.\n       if (outSize <= size) : Filter have converted outSize bytes\n       if (outSize >  size) : Filter have not converted anything.\n           and it needs at least outSize bytes to convert one block\n           (it's for crypto block algorithms).\n*/\n\n#define Z7_IFACEM_ICompressFilter(x) \\\n  x(Init()) \\\n  x##2(UInt32, Filter(Byte *data, UInt32 size))\nZ7_IFACE_CONSTR_CODER(ICompressFilter, 0x40)\n\n\n#define Z7_IFACEM_ICompressCodecsInfo(x) \\\n  x(GetNumMethods(UInt32 *numMethods)) \\\n  x(GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) \\\n  x(CreateDecoder(UInt32 index, const GUID *iid, void* *coder)) \\\n  x(CreateEncoder(UInt32 index, const GUID *iid, void* *coder))\nZ7_IFACE_CONSTR_CODER(ICompressCodecsInfo, 0x60)\n\n#define Z7_IFACEM_ISetCompressCodecsInfo(x) \\\n  x(SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo))\nZ7_IFACE_CONSTR_CODER(ISetCompressCodecsInfo, 0x61)\n\n#define Z7_IFACEM_ICryptoProperties(x) \\\n  x(SetKey(const Byte *data, UInt32 size)) \\\n  x(SetInitVector(const Byte *data, UInt32 size))\nZ7_IFACE_CONSTR_CODER(ICryptoProperties, 0x80)\n\n/*\n  x(ResetSalt())\nZ7_IFACE_CONSTR_CODER(ICryptoResetSalt, 0x88)\n*/\n\n#define Z7_IFACEM_ICryptoResetInitVector(x) \\\n  x(ResetInitVector())\nZ7_IFACE_CONSTR_CODER(ICryptoResetInitVector, 0x8C)\n  /* Call ResetInitVector() only for encoding.\n     Call ResetInitVector() before encoding and before WriteCoderProperties().\n     Crypto encoder can create random IV in that function. */\n\n#define Z7_IFACEM_ICryptoSetPassword(x) \\\n  x(CryptoSetPassword(const Byte *data, UInt32 size))\nZ7_IFACE_CONSTR_CODER(ICryptoSetPassword, 0x90)\n\n#define Z7_IFACEM_ICryptoSetCRC(x) \\\n  x(CryptoSetCRC(UInt32 crc))\nZ7_IFACE_CONSTR_CODER(ICryptoSetCRC, 0xA0)\n\n\nnamespace NMethodPropID\n{\n  enum EEnum\n  {\n    kID,\n    kName,\n    kDecoder,\n    kEncoder,\n    kPackStreams,\n    kUnpackStreams,\n    kDescription,\n    kDecoderIsAssigned,\n    kEncoderIsAssigned,\n    kDigestSize,\n    kIsFilter\n  };\n}\n\nnamespace NModuleInterfaceType\n{\n  /*\n    virtual destructor in IUnknown:\n    - no  : 7-Zip (Windows)\n    - no  : 7-Zip (Linux) (v23) in default mode\n    - yes : p7zip\n    - yes : 7-Zip (Linux) before v23\n    - yes : 7-Zip (Linux) (v23), if Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN is defined\n  */\n  const UInt32 k_IUnknown_VirtDestructor_No  = 0;\n  const UInt32 k_IUnknown_VirtDestructor_Yes = 1;\n  const UInt32 k_IUnknown_VirtDestructor_ThisModule =\n  #if !defined(_WIN32) && defined(Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN)\n    k_IUnknown_VirtDestructor_Yes;\n  #else\n    k_IUnknown_VirtDestructor_No;\n  #endif\n}\n\nnamespace NModulePropID\n{\n  enum EEnum\n  {\n    kInterfaceType,   // VT_UI4\n    kVersion          // VT_UI4\n  };\n}\n\n\n#define Z7_IFACEM_IHasher(x) \\\n  x##2(void, Init()) \\\n  x##2(void, Update(const void *data, UInt32 size)) \\\n  x##2(void, Final(Byte *digest)) \\\n  x##2(UInt32, GetDigestSize())\nZ7_IFACE_CONSTR_CODER(IHasher, 0xC0)\n\n#define Z7_IFACEM_IHashers(x) \\\n  x##2(UInt32, GetNumHashers()) \\\n  x(GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value)) \\\n  x(CreateHasher(UInt32 index, IHasher **hasher))\nZ7_IFACE_CONSTR_CODER(IHashers, 0xC1)\n\nextern \"C\"\n{\n  typedef HRESULT (WINAPI *Func_GetNumberOfMethods)(UInt32 *numMethods);\n  typedef HRESULT (WINAPI *Func_GetMethodProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);\n  typedef HRESULT (WINAPI *Func_CreateDecoder)(UInt32 index, const GUID *iid, void **outObject);\n  typedef HRESULT (WINAPI *Func_CreateEncoder)(UInt32 index, const GUID *iid, void **outObject);\n\n  typedef HRESULT (WINAPI *Func_GetHashers)(IHashers **hashers);\n  \n  typedef HRESULT (WINAPI *Func_SetCodecs)(ICompressCodecsInfo *compressCodecsInfo);\n  typedef HRESULT (WINAPI *Func_GetModuleProp)(PROPID propID, PROPVARIANT *value);\n}\n\nZ7_PURE_INTERFACES_END\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/IDecl.h",
    "content": "﻿// IDecl.h\n\n#ifndef ZIP7_INC_IDECL_H\n#define ZIP7_INC_IDECL_H\n\n#include \"../Common/Common0.h\"\n#include \"../Common/MyUnknown.h\"\n\n#define k_7zip_GUID_Data1 0x23170F69\n#define k_7zip_GUID_Data2 0x40C1\n// **************** 7-Zip ZS Modification Start ****************\n#define k_7zip_GUID_Data2_ZS 0x20BB\n// **************** 7-Zip ZS Modification End ****************\n\n#define k_7zip_GUID_Data3_Common  0x278A\n\n#define k_7zip_GUID_Data3_Decoder 0x2790\n#define k_7zip_GUID_Data3_Encoder 0x2791\n#define k_7zip_GUID_Data3_Hasher  0x2792\n\n#define Z7_DECL_IFACE_7ZIP_SUB(i, _base, groupId, subId) \\\n  Z7_DEFINE_GUID(IID_ ## i, \\\n    k_7zip_GUID_Data1, \\\n    k_7zip_GUID_Data2, \\\n    k_7zip_GUID_Data3_Common, \\\n    0, 0, 0, (groupId), 0, (subId), 0, 0); \\\n    struct Z7_DECLSPEC_NOVTABLE i: public _base\n \n#define Z7_DECL_IFACE_7ZIP(i,           groupId, subId) \\\n    Z7_DECL_IFACE_7ZIP_SUB(i, IUnknown, groupId, subId)\n\n\n#ifdef COM_DECLSPEC_NOTHROW\n#define Z7_COMWF_B        COM_DECLSPEC_NOTHROW STDMETHODIMP\n#define Z7_COMWF_B_(t)    COM_DECLSPEC_NOTHROW STDMETHODIMP_(t)\n#else\n#define Z7_COMWF_B        STDMETHODIMP\n#define Z7_COMWF_B_(t)    STDMETHODIMP_(t)\n#endif\n\n#if defined(_MSC_VER) && !defined(COM_DECLSPEC_NOTHROW)\n#define Z7_COM7F_B        __declspec(nothrow) STDMETHODIMP\n#define Z7_COM7F_B_(t)    __declspec(nothrow) STDMETHODIMP_(t)\n#else\n#define Z7_COM7F_B        Z7_COMWF_B\n#define Z7_COM7F_B_(t)    Z7_COMWF_B_(t)\n#endif\n\n// #define Z7_COM7F_E            Z7_noexcept\n#define Z7_COM7F_E            throw()\n#define Z7_COM7F_EO           Z7_COM7F_E  Z7_override\n#define Z7_COM7F_EOF          Z7_COM7F_EO Z7_final\n#define Z7_COM7F_IMF(f)       Z7_COM7F_B     f Z7_COM7F_E\n#define Z7_COM7F_IMF2(t, f)   Z7_COM7F_B_(t) f Z7_COM7F_E\n\n#define Z7_COM7F_PURE(f)              virtual Z7_COM7F_IMF(f) =0;\n#define Z7_COM7F_PURE2(t, f)          virtual Z7_COM7F_IMF2(t, f) =0;\n#define Z7_COM7F_IMP(f)               Z7_COM7F_IMF(f)     Z7_override Z7_final;\n#define Z7_COM7F_IMP2(t, f)           Z7_COM7F_IMF2(t, f) Z7_override Z7_final;\n#define Z7_COM7F_IMP_NONFINAL(f)      Z7_COM7F_IMF(f)     Z7_override;\n#define Z7_COM7F_IMP_NONFINAL2(t, f)  Z7_COM7F_IMF2(t, f) Z7_override;\n\n#define Z7_IFACE_PURE(name)               Z7_IFACEN_ ## name(=0;)\n#define Z7_IFACE_IMP(name)                Z7_IFACEN_ ## name(Z7_override Z7_final;)\n\n#define Z7_IFACE_COM7_PURE(name)          Z7_IFACEM_ ## name(Z7_COM7F_PURE)\n#define Z7_IFACE_COM7_IMP(name)           Z7_IFACEM_ ## name(Z7_COM7F_IMP)\n#define Z7_IFACE_COM7_IMP_NONFINAL(name)  Z7_IFACEM_ ## name(Z7_COM7F_IMP_NONFINAL)\n\n\n#define Z7_IFACE_DECL_PURE(name) \\\n    DECLARE_INTERFACE(name) \\\n    { Z7_IFACE_PURE(name) };\n\n#define Z7_IFACE_DECL_PURE_(name, baseiface) \\\n    DECLARE_INTERFACE_(name, baseiface) \\\n    { Z7_IFACE_PURE(name) };\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/IPassword.h",
    "content": "﻿// IPassword.h\n\n#ifndef ZIP7_INC_IPASSWORD_H\n#define ZIP7_INC_IPASSWORD_H\n\n#include \"../Common/MyTypes.h\"\n\n#include \"IDecl.h\"\n\nZ7_PURE_INTERFACES_BEGIN\n\n#define Z7_IFACE_CONSTR_PASSWORD(i, n) \\\n  Z7_DECL_IFACE_7ZIP(i, 5, n) \\\n  { Z7_IFACE_COM7_PURE(i) };\n\n/*\nHow to use output parameter (BSTR *password):\n\nin:  The caller is required to set BSTR value as NULL (no string).\n     The callee (in 7-Zip code) ignores the input value stored in BSTR variable,\n\nout: The callee rewrites BSTR variable (*password) with new allocated string pointer.\n     The caller must free BSTR string with function SysFreeString();\n*/\n\n#define Z7_IFACEM_ICryptoGetTextPassword(x) \\\n  x(CryptoGetTextPassword(BSTR *password))\nZ7_IFACE_CONSTR_PASSWORD(ICryptoGetTextPassword, 0x10)\n\n\n/*\nCryptoGetTextPassword2()\nin:\n  The caller is required to set BSTR value as NULL (no string).\n  The caller is not required to set (*passwordIsDefined) value.\n\nout:\n  Return code: != S_OK : error code\n  Return code:    S_OK : success\n   \n  if (*passwordIsDefined == 1), the variable (*password) contains password string\n    \n  if (*passwordIsDefined == 0), the password is not defined,\n     but the callee still could set (*password) to some allocated string, for example, as empty string.\n  \n  The caller must free BSTR string with function SysFreeString()\n*/\n\n#define Z7_IFACEM_ICryptoGetTextPassword2(x) \\\n  x(CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password))\nZ7_IFACE_CONSTR_PASSWORD(ICryptoGetTextPassword2, 0x11)\n\nZ7_PURE_INTERFACES_END\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/IProgress.h",
    "content": "﻿// IProgress.h\n\n#ifndef ZIP7_INC_IPROGRESS_H\n#define ZIP7_INC_IPROGRESS_H\n\n#include \"../Common/MyTypes.h\"\n\n#include \"IDecl.h\"\n\nZ7_PURE_INTERFACES_BEGIN\n\n#define Z7_IFACEM_IProgress(x) \\\n  x(SetTotal(UInt64 total)) \\\n  x(SetCompleted(const UInt64 *completeValue)) \\\n\nZ7_DECL_IFACE_7ZIP(IProgress, 0, 5)\n  { Z7_IFACE_COM7_PURE(IProgress) };\n\nZ7_PURE_INTERFACES_END\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/IStream.h",
    "content": "﻿// IStream.h\n\n#ifndef ZIP7_INC_ISTREAM_H\n#define ZIP7_INC_ISTREAM_H\n\n#include \"../Common/Common0.h\"\n#include \"../Common/MyTypes.h\"\n#include \"../Common/MyWindows.h\"\n\n#include \"IDecl.h\"\n\nZ7_PURE_INTERFACES_BEGIN\n\n#define Z7_IFACE_CONSTR_STREAM_SUB(i, base, n) \\\n  Z7_DECL_IFACE_7ZIP_SUB(i, base, 3, n) \\\n  { Z7_IFACE_COM7_PURE(i) };\n\n#define Z7_IFACE_CONSTR_STREAM(i, n) \\\n        Z7_IFACE_CONSTR_STREAM_SUB(i, IUnknown, n)\n\n\n/*\nISequentialInStream::Read()\n  The requirement for caller: (processedSize != NULL).\n  The callee can allow (processedSize == NULL) for compatibility reasons.\n\n  if (size == 0), this function returns S_OK and (*processedSize) is set to 0.\n\n  if (size != 0)\n  {\n    Partial read is allowed: (*processedSize <= avail_size && *processedSize <= size),\n      where (avail_size) is the size of remaining bytes in stream.\n    If (avail_size != 0), this function must read at least 1 byte: (*processedSize > 0).\n    You must call Read() in loop, if you need to read exact amount of data.\n  }\n\n  If seek pointer before Read() call was changed to position past the end of stream:\n    if (seek_pointer >= stream_size), this function returns S_OK and (*processedSize) is set to 0.\n\n  ERROR CASES:\n    If the function returns error code, then (*processedSize) is size of\n    data written to (data) buffer (it can be data before error or data with errors).\n    The recommended way for callee to work with reading errors:\n      1) write part of data before error to (data) buffer and return S_OK.\n      2) return error code for further calls of Read().\n*/\n#define Z7_IFACEM_ISequentialInStream(x) \\\n  x(Read(void *data, UInt32 size, UInt32 *processedSize))\nZ7_IFACE_CONSTR_STREAM(ISequentialInStream, 0x01)\n\n\n/*\nISequentialOutStream::Write()\n  The requirement for caller: (processedSize != NULL).\n  The callee can allow (processedSize == NULL) for compatibility reasons.\n\n  if (size != 0)\n  {\n    Partial write is allowed: (*processedSize <= size),\n    but this function must write at least 1 byte: (*processedSize > 0).\n    You must call Write() in loop, if you need to write exact amount of data.\n  }\n\n  ERROR CASES:\n    If the function returns error code, then (*processedSize) is size of\n    data written from (data) buffer.\n*/\n#define Z7_IFACEM_ISequentialOutStream(x) \\\n  x(Write(const void *data, UInt32 size, UInt32 *processedSize))\nZ7_IFACE_CONSTR_STREAM(ISequentialOutStream, 0x02)\n\n\n#ifdef _WIN32\n\n#ifdef __HRESULT_FROM_WIN32\n#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)\n#else\n#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK   HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK)\n#endif\n\n#else\n\n#define HRESULT_WIN32_ERROR_NEGATIVE_SEEK   MY_E_ERROR_NEGATIVE_SEEK\n\n#endif\n\n\n/*\nIInStream::Seek() / IOutStream::Seek()\n  If you seek to position before the beginning of the stream,\n  Seek() function returns error code:\n      Recommended error code is __HRESULT_FROM_WIN32(ERROR_NEGATIVE_SEEK).\n      or STG_E_INVALIDFUNCTION\n  It is allowed to seek past the end of the stream.\n  if Seek() returns error, then the value of *newPosition is undefined.\n*/\n\n#define Z7_IFACEM_IInStream(x) \\\n  x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\nZ7_IFACE_CONSTR_STREAM_SUB(IInStream, ISequentialInStream, 0x03)\n\n#define Z7_IFACEM_IOutStream(x) \\\n  x(Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)) \\\n  x(SetSize(UInt64 newSize))\nZ7_IFACE_CONSTR_STREAM_SUB(IOutStream, ISequentialOutStream, 0x04)\n\n#define Z7_IFACEM_IStreamGetSize(x) \\\n  x(GetSize(UInt64 *size))\nZ7_IFACE_CONSTR_STREAM(IStreamGetSize, 0x06)\n\n#define Z7_IFACEM_IOutStreamFinish(x) \\\n  x(OutStreamFinish())\nZ7_IFACE_CONSTR_STREAM(IOutStreamFinish, 0x07)\n\n#define Z7_IFACEM_IStreamGetProps(x) \\\n  x(GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib))\nZ7_IFACE_CONSTR_STREAM(IStreamGetProps, 0x08)\n\n\nstruct CStreamFileProps\n{\n  UInt64 Size;\n  UInt64 VolID;\n  UInt64 FileID_Low;\n  UInt64 FileID_High;\n  UInt32 NumLinks;\n  UInt32 Attrib;\n  FILETIME CTime;\n  FILETIME ATime;\n  FILETIME MTime;\n};\n\n\n#define Z7_IFACEM_IStreamGetProps2(x) \\\n  x(GetProps2(CStreamFileProps *props))\nZ7_IFACE_CONSTR_STREAM(IStreamGetProps2, 0x09)\n\n#define Z7_IFACEM_IStreamGetProp(x) \\\n  x(GetProperty(PROPID propID, PROPVARIANT *value)) \\\n  x(ReloadProps())\nZ7_IFACE_CONSTR_STREAM(IStreamGetProp, 0x0a)\n\n\n/*\nIStreamSetRestriction::SetRestriction(UInt64 begin, UInt64 end)\n  \n  It sets region of data in output stream that is restricted.\n  For restricted region it's expected (or allowed)\n  that the caller can write to same region with different calls of Write()/SetSize().\n  Another regions of output stream will be supposed as non-restricted:\n    - The callee usually doesn't flush the data in restricted region.\n    - The callee usually can flush data from non-restricted region after writing.\n\nActual restiction rules depend also from current stream position.\nIt's recommended to call SetRestriction() just before the Write() call.\nSo the callee can optimize writing and flushing, if that Write()\noperation is not restricted.\n\nNote: Each new call of SetRestriction() sets new restictions,\nso previous restrction calls has no effect anymore.\n\ninputs:\n \n  (begin > end) is not allowed, and returns E_FAIL;\n  \n  if (begin == end)\n  {\n    No restriction.\n    The caller will call Write() in sequential order.\n    After SetRestriction(begin, begin), but before next call of SetRestriction()\n    {\n      Additional condition:\n        it's expected that current stream seek position is equal to stream size.\n      The callee can make final flushing for any data before current stream seek position.\n      For each Write(size) call:\n        The callee can make final flushing for that new written data.\n    }\n    The pair of values (begin == 0 && end == 0) is recommended to remove write restriction.\n  }\n  \n  if (begin < end)\n  {\n    it means that callee must NOT flush any data in region [begin, end).\n    The caller is allowed to Seek() to that region and rewrite the\n    data in that restriction region.\n    if (end == (UInt64)(Int64)-1)\n    {\n      there is no upper bound for restricted region.\n      So non-restricted region will be [0, begin) in that case\n    }\n  }\n\n returns:\n  - if (begin > end) it return ERROR code (E_FAIL)\n  - S_OK : if no errors.\n  - Also the call of SetRestriction() can initiate the flushing of already written data.\n    So it can return the result of that flushing.\n \n Note: IOutStream::SetSize() also can change the data.\n    So it's not expected the call\n    IOutStream::SetSize() to region that was written before as unrestricted.\n*/\n\n#define Z7_IFACEM_IStreamSetRestriction(x) \\\n  x(SetRestriction(UInt64 begin, UInt64 end)) \\\n\nZ7_IFACE_CONSTR_STREAM(IStreamSetRestriction, 0x10)\n\nZ7_PURE_INTERFACES_END\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/MyVersion.h",
    "content": "﻿#define USE_COPYRIGHT_CR\n#include \"../../C/7zVersion.h\"\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/PropID.h",
    "content": "﻿// PropID.h\n\n#ifndef ZIP7_INC_7ZIP_PROP_ID_H\n#define ZIP7_INC_7ZIP_PROP_ID_H\n\n#include \"../Common/MyTypes.h\"\n\nenum\n{\n  kpidNoProperty = 0,\n  kpidMainSubfile,\n  kpidHandlerItemIndex,\n  kpidPath,\n  kpidName,\n  kpidExtension,\n  kpidIsDir,\n  kpidSize,\n  kpidPackSize,\n  kpidAttrib,\n  kpidCTime,\n  kpidATime,\n  kpidMTime,\n  kpidSolid,\n  kpidCommented,\n  kpidEncrypted,\n  kpidSplitBefore,\n  kpidSplitAfter,\n  kpidDictionarySize,\n  kpidCRC,\n  kpidType,\n  kpidIsAnti,\n  kpidMethod,\n  kpidHostOS,\n  kpidFileSystem,\n  kpidUser,\n  kpidGroup,\n  kpidBlock,\n  kpidComment,\n  kpidPosition,\n  kpidPrefix,\n  kpidNumSubDirs,\n  kpidNumSubFiles,\n  kpidUnpackVer,\n  kpidVolume,\n  kpidIsVolume,\n  kpidOffset,\n  kpidLinks,\n  kpidNumBlocks,\n  kpidNumVolumes,\n  kpidTimeType,\n  kpidBit64,\n  kpidBigEndian,\n  kpidCpu,\n  kpidPhySize,\n  kpidHeadersSize,\n  kpidChecksum,\n  kpidCharacts,\n  kpidVa,\n  kpidId,\n  kpidShortName,\n  kpidCreatorApp,\n  kpidSectorSize,\n  kpidPosixAttrib,\n  kpidSymLink,\n  kpidError,\n  kpidTotalSize,\n  kpidFreeSpace,\n  kpidClusterSize,\n  kpidVolumeName,\n  kpidLocalName,\n  kpidProvider,\n  kpidNtSecure,\n  kpidIsAltStream,\n  kpidIsAux,\n  kpidIsDeleted,\n  kpidIsTree,\n  kpidSha1,\n  kpidSha256,\n  kpidErrorType,\n  kpidNumErrors,\n  kpidErrorFlags,\n  kpidWarningFlags,\n  kpidWarning,\n  kpidNumStreams,\n  kpidNumAltStreams,\n  kpidAltStreamsSize,\n  kpidVirtualSize,\n  kpidUnpackSize,\n  kpidTotalPhySize,\n  kpidVolumeIndex,\n  kpidSubType,\n  kpidShortComment,\n  kpidCodePage,\n  kpidIsNotArcType,\n  kpidPhySizeCantBeDetected,\n  kpidZerosTailIsAllowed,\n  kpidTailSize,\n  kpidEmbeddedStubSize,\n  kpidNtReparse,\n  kpidHardLink,\n  kpidINode,\n  kpidStreamId,\n  kpidReadOnly,\n  kpidOutName,\n  kpidCopyLink,\n  kpidArcFileName,\n  kpidIsHash,\n  kpidChangeTime,\n  kpidUserId,\n  kpidGroupId,\n  kpidDeviceMajor,\n  kpidDeviceMinor,\n  kpidDevMajor,\n  kpidDevMinor,\n\n  kpid_NUM_DEFINED,\n\n  kpidUserDefined = 0x10000\n};\n\nextern const Byte k7z_PROPID_To_VARTYPE[kpid_NUM_DEFINED]; // VARTYPE\n\nconst UInt32 kpv_ErrorFlags_IsNotArc              = 1 << 0;\nconst UInt32 kpv_ErrorFlags_HeadersError          = 1 << 1;\nconst UInt32 kpv_ErrorFlags_EncryptedHeadersError = 1 << 2;\nconst UInt32 kpv_ErrorFlags_UnavailableStart      = 1 << 3;\nconst UInt32 kpv_ErrorFlags_UnconfirmedStart      = 1 << 4;\nconst UInt32 kpv_ErrorFlags_UnexpectedEnd         = 1 << 5;\nconst UInt32 kpv_ErrorFlags_DataAfterEnd          = 1 << 6;\nconst UInt32 kpv_ErrorFlags_UnsupportedMethod     = 1 << 7;\nconst UInt32 kpv_ErrorFlags_UnsupportedFeature    = 1 << 8;\nconst UInt32 kpv_ErrorFlags_DataError             = 1 << 9;\nconst UInt32 kpv_ErrorFlags_CrcError              = 1 << 10;\n// const UInt32 kpv_ErrorFlags_Unsupported           = 1 << 11;\n\n/*\nlinux ctime :\n   file metadata was last changed.\n   changing the file modification time\n   counts as a metadata change, so will also have the side effect of updating the ctime.\n\nPROPVARIANT for timestamps in 7-Zip:\n{\n  vt = VT_FILETIME\n  wReserved1: set precision level\n    0      : base value (backward compatibility value)\n             only filetime is used (7 digits precision).\n             wReserved2 and wReserved3 can contain random data\n    1      : Unix (1 sec)\n    2      : DOS  (2 sec)\n    3      : High Precision (1 ns)\n    16 - 3 : (reserved) = 1 day\n    16 - 2 : (reserved) = 1 hour\n    16 - 1 : (reserved) = 1 minute\n    16 + 0 : 1 sec (0 digits after point)\n    16 + (1,2,3,4,5,6,7,8,9) : set subsecond precision level :\n         (number of decimal digits after point)\n    16 + 9 : 1 ns  (9 digits after point)\n  wReserved2 = ns % 100 : if     (8 or 9 digits pecision)\n             = 0        : if not (8 or 9 digits pecision)\n  wReserved3 = 0;\n  filetime\n}\n\nNOTE: TAR-PAX archives created by GNU TAR don't keep\n  whole information about original level of precision,\n  and timestamp are stored in reduced form, where tail zero\n  digits after point are removed.\n  So 7-Zip can return different precision levels for different items for such TAR archives.\n*/\n\n/*\nTimePrec returned by IOutArchive::GetFileTimeType()\nis used only for updating, when we compare MTime timestamp\nfrom archive with timestamp from directory.\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ArchiveCommandLine.h",
    "content": "﻿// ArchiveCommandLine.h\n\n#ifndef ZIP7_INC_ARCHIVE_COMMAND_LINE_H\n#define ZIP7_INC_ARCHIVE_COMMAND_LINE_H\n\n#include \"../../../Common/CommandLineParser.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"EnumDirItems.h\"\n\n#include \"Extract.h\"\n#include \"HashCalc.h\"\n#include \"Update.h\"\n\ntypedef CMessagePathException CArcCmdLineException;\n\nnamespace NCommandType { enum EEnum\n{\n  kAdd = 0,\n  kUpdate,\n  kDelete,\n  kTest,\n  kExtract,\n  kExtractFull,\n  kList,\n  kBenchmark,\n  kInfo,\n  kHash,\n  kRename\n};}\n\nstruct CArcCommand\n{\n  NCommandType::EEnum CommandType;\n\n  bool IsFromExtractGroup() const;\n  bool IsFromUpdateGroup() const;\n  bool IsTestCommand() const { return CommandType == NCommandType::kTest; }\n  NExtract::NPathMode::EEnum GetPathMode() const;\n};\n\nenum\n{\n  k_OutStream_disabled = 0,\n  k_OutStream_stdout = 1,\n  k_OutStream_stderr = 2\n};\n\nstruct CArcCmdLineOptions\n{\n  bool HelpMode;\n\n  // bool LargePages;\n  bool CaseSensitive_Change;\n  bool CaseSensitive;\n\n  bool IsInTerminal;\n  bool IsStdOutTerminal;\n  bool IsStdErrTerminal;\n  bool StdInMode;\n  bool StdOutMode;\n  bool EnableHeaders;\n  bool DisablePercents;\n\n\n  bool YesToAll;\n  bool ShowDialog;\n  bool TechMode;\n  bool ShowTime;\n  CBoolPair ListPathSeparatorSlash;\n\n  CBoolPair NtSecurity;\n  CBoolPair AltStreams;\n  CBoolPair HardLinks;\n  CBoolPair SymLinks;\n  \n  CBoolPair StoreOwnerId;\n  CBoolPair StoreOwnerName;\n\n  AString ListFields;\n\n  int ConsoleCodePage;\n\n  NWildcard::CCensor Censor;\n\n  CArcCommand Command;\n  UString ArchiveName;\n\n  #ifndef Z7_NO_CRYPTO\n  bool PasswordEnabled;\n  UString Password;\n  #endif\n\n  UStringVector HashMethods;\n  // UString HashFilePath;\n\n  // bool AppendName;\n  // UStringVector ArchivePathsSorted;\n  // UStringVector ArchivePathsFullSorted;\n  NWildcard::CCensor arcCensor;\n  UString ArcName_for_StdInMode;\n\n  CObjectVector<CProperty> Properties;\n\n  CExtractOptionsBase ExtractOptions;\n\n  CUpdateOptions UpdateOptions;\n  CHashOptions HashOptions;\n  UString ArcType;\n  UStringVector ExcludedArcTypes;\n  // **************** NanaZip Modification Start ****************\n  CBoolPair OpenFolder;\n  // **************** NanaZip Modification End ****************\n  \n  unsigned Number_for_Out;\n  unsigned Number_for_Errors;\n  unsigned Number_for_Percents;\n  unsigned LogLevel;\n\n  // bool IsOutAllowed() const { return Number_for_Out != k_OutStream_disabled; }\n\n  // Benchmark\n  UInt32 NumIterations;\n  bool NumIterations_Defined;\n\n  CArcCmdLineOptions():\n      HelpMode(false),\n      // LargePages(false),\n      CaseSensitive_Change(false),\n      CaseSensitive(false),\n\n      IsInTerminal(false),\n      IsStdOutTerminal(false),\n      IsStdErrTerminal(false),\n\n      StdInMode(false),\n      StdOutMode(false),\n\n      EnableHeaders(false),\n      DisablePercents(false),\n      \n      YesToAll(false),\n      ShowDialog(false),\n      TechMode(false),\n      ShowTime(false),\n\n      ConsoleCodePage(-1),\n\n      Number_for_Out(k_OutStream_stdout),\n      Number_for_Errors(k_OutStream_stderr),\n      Number_for_Percents(k_OutStream_stdout),\n\n      LogLevel(0)\n  {\n    ListPathSeparatorSlash.Val =\n#ifdef _WIN32\n        false;\n#else\n        true;\n#endif\n  }\n};\n\nclass CArcCmdLineParser\n{\n  NCommandLineParser::CParser parser;\npublic:\n  UString Parse1Log;\n  void Parse1(const UStringVector &commandStrings, CArcCmdLineOptions &options);\n  void Parse2(CArcCmdLineOptions &options);\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ArchiveExtractCallback.cpp",
    "content": "﻿// ArchiveExtractCallback.cpp\n\n#include \"StdAfx.h\"\n\n#undef sprintf\n#undef printf\n\n// #include <stdio.h>\n\n#include \"../../../../C/Alloc.h\"\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/UTFConvert.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n\n#if defined(_WIN32) && !defined(UNDER_CE)  && !defined(Z7_SFX)\n#define Z7_USE_SECURITY_CODE\n#include \"../../../Windows/SecurityUtils.h\"\n#endif\n\n#include \"../../Common/FilePathAutoRename.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Archive/Common/ItemNameUtils.h\"\n\n#include \"../Common/ExtractingFilePath.h\"\n#include \"../Common/PropIDUtils.h\"\n\n#include \"ArchiveExtractCallback.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\nstatic const char * const kCantAutoRename = \"Cannot create file with auto name\";\nstatic const char * const kCantRenameFile = \"Cannot rename existing file\";\nstatic const char * const kCantDeleteOutputFile = \"Cannot delete output file\";\nstatic const char * const kCantDeleteOutputDir = \"Cannot delete output folder\";\nstatic const char * const kCantOpenOutFile = \"Cannot open output file\";\n#ifndef Z7_SFX\nstatic const char * const kCantOpenInFile = \"Cannot open input file\";\n#endif\nstatic const char * const kCantSetFileLen = \"Cannot set length for output file\";\n#ifdef SUPPORT_LINKS\nstatic const char * const kCantCreateHardLink = \"Cannot create hard link\";\nstatic const char * const kCantCreateSymLink = \"Cannot create symbolic link\";\nstatic const char * const k_HardLink_to_SymLink_Ignored = \"Hard link to symbolic link was ignored\";\nstatic const char * const k_CantDelete_File_for_SymLink = \"Cannot delete file for symbolic link creation\";\nstatic const char * const k_CantDelete_Dir_for_SymLink = \"Cannot delete directory for symbolic link creation\";\n#endif\n\nstatic const unsigned k_LinkDataSize_LIMIT = 1 << 12;\n\n#ifdef SUPPORT_LINKS\n#if WCHAR_PATH_SEPARATOR != L'/'\n  // we convert linux slashes to windows slashes for further processing.\n  // also we convert linux backslashes to BackslashReplacement character.\n  #define REPLACE_SLASHES_from_Linux_to_Sys(s) \\\n    { NArchive::NItemName::ReplaceToWinSlashes(s, true); }  // useBackslashReplacement\n      // { s.Replace(L'/', WCHAR_PATH_SEPARATOR); }\n#else\n  #define REPLACE_SLASHES_from_Linux_to_Sys(s)\n#endif\n#endif\n\n#ifndef Z7_SFX\n\nZ7_COM7F_IMF(COutStreamWithHash::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  HRESULT result = S_OK;\n  if (_stream)\n    result = _stream->Write(data, size, &size);\n  if (_calculate)\n    _hash->Update(data, size);\n  _size += size;\n  if (processedSize)\n    *processedSize = size;\n  return result;\n}\n\n#endif // Z7_SFX\n\n\n#ifdef Z7_USE_SECURITY_CODE\nbool InitLocalPrivileges();\nbool InitLocalPrivileges()\n{\n  NSecurity::CAccessToken token;\n  if (!token.OpenProcessToken(GetCurrentProcess(),\n      TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES))\n    return false;\n\n  TOKEN_PRIVILEGES tp;\n \n  tp.PrivilegeCount = 1;\n  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;\n  \n  if  (!::LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tp.Privileges[0].Luid))\n    return false;\n  if (!token.AdjustPrivileges(&tp))\n    return false;\n  return (GetLastError() == ERROR_SUCCESS);\n}\n#endif // Z7_USE_SECURITY_CODE\n\n\n\n#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n\nstatic const char * const kOfficeExtensions =\n  \" doc dot wbk\"\n  \" docx docm dotx dotm docb wll wwl\"\n  \" xls xlt xlm\"\n  \" xlsx xlsm xltx xltm xlsb xla xlam\"\n  \" ppt pot pps ppa ppam\"\n  \" pptx pptm potx potm ppam ppsx ppsm sldx sldm\"\n    // **************** NanaZip Modification Start ****************\n    // Executable types\n    \" bat cmd com exe hta js jse lnk msi pif ps1 scr vbe vbs wsf\"\n    // Nested archives (subset). Note: only kAll fully works on nested archives!\n    \" 7z iso rar tar vhd vhdx zip\"\n    // **************** NanaZip Modification End ****************\n  \" \";\n\nstatic bool FindExt2(const char *p, const UString &name)\n{\n  const int pathPos = name.ReverseFind_PathSepar();\n  const int dotPos = name.ReverseFind_Dot();\n  if (dotPos < 0\n      || dotPos < pathPos\n      || dotPos == (int)name.Len() - 1)\n    return false;\n\n  AString s;\n  for (unsigned pos = (unsigned)(dotPos + 1);; pos++)\n  {\n    const wchar_t c = name[pos];\n    if (c <= 0)\n      break;\n    if (c >= 0x80)\n      return false;\n    s.Add_Char((char)MyCharLower_Ascii((char)c));\n  }\n  for (unsigned i = 0; p[i] != 0;)\n  {\n    unsigned j;\n    for (j = i; p[j] != ' '; j++);\n    if (s.Len() == j - i && memcmp(p + i, (const char *)s, s.Len()) == 0)\n      return true;\n    i = j + 1;\n  }\n  return false;\n}\n\n\nstatic const char * const k_ZoneId_StreamName_With_Colon_Prefix = \":Zone.Identifier\";\n\nbool Is_ZoneId_StreamName(const wchar_t *s)\n{\n  return StringsAreEqualNoCase_Ascii(s, k_ZoneId_StreamName_With_Colon_Prefix + 1);\n}\n\nvoid ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf)\n{\n  buf.Free();\n  FString path (fileName);\n  path += k_ZoneId_StreamName_With_Colon_Prefix;\n  NIO::CInFile file;\n  if (!file.Open(path))\n    return;\n  UInt64 fileSize;\n  if (!file.GetLength(fileSize))\n    return;\n  if (fileSize == 0 || fileSize >= (1u << 15))\n    return;\n  buf.Alloc((size_t)fileSize);\n  size_t processed;\n  if (file.ReadFull(buf, (size_t)fileSize, processed) && processed == fileSize)\n    return;\n  buf.Free();\n}\n\nbool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf)\n{\n  FString path (fileName);\n  path += k_ZoneId_StreamName_With_Colon_Prefix;\n  NIO::COutFile file;\n  if (!file.Create_ALWAYS(path))\n    return false;\n  return file.WriteFull(buf, buf.Size());\n}\n\n#endif\n\n\n#ifdef SUPPORT_LINKS\n\nint CHardLinkNode::Compare(const CHardLinkNode &a) const\n{\n  if (StreamId < a.StreamId) return -1;\n  if (StreamId > a.StreamId) return 1;\n  return MyCompare(INode, a.INode);\n}\n\nstatic HRESULT Archive_Get_HardLinkNode(IInArchive *archive, UInt32 index, CHardLinkNode &h, bool &defined)\n{\n  h.INode = 0;\n  h.StreamId = (UInt64)(Int64)-1;\n  defined = false;\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidINode, &prop))\n    if (!ConvertPropVariantToUInt64(prop, h.INode))\n      return S_OK;\n  }\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidStreamId, &prop))\n    ConvertPropVariantToUInt64(prop, h.StreamId);\n  }\n  defined = true;\n  return S_OK;\n}\n\n\nHRESULT CArchiveExtractCallback::PrepareHardLinks(const CRecordVector<UInt32> *realIndices)\n{\n  _hardLinks.Clear();\n\n  if (!_arc->Ask_INode)\n    return S_OK;\n  \n  IInArchive * const archive = _arc->Archive;\n  CRecordVector<CHardLinkNode> &hardIDs = _hardLinks.IDs;\n\n  {\n    UInt32 numItems;\n    if (realIndices)\n      numItems = realIndices->Size();\n    else\n    {\n      RINOK(archive->GetNumberOfItems(&numItems))\n    }\n\n    for (UInt32 i = 0; i < numItems; i++)\n    {\n      CHardLinkNode h;\n      bool defined;\n      const UInt32 realIndex = realIndices ? (*realIndices)[i] : i;\n\n      RINOK(Archive_Get_HardLinkNode(archive, realIndex, h, defined))\n      if (defined)\n      {\n        bool isAltStream = false;\n        RINOK(Archive_IsItem_AltStream(archive, realIndex, isAltStream))\n        if (!isAltStream)\n        {\n          bool isDir = false;\n          RINOK(Archive_IsItem_Dir(archive, realIndex, isDir))\n          if (!isDir)\n            hardIDs.Add(h);\n        }\n      }\n    }\n  }\n  \n  hardIDs.Sort2();\n  \n  {\n    // we keep only items that have 2 or more items\n    unsigned k = 0;\n    unsigned numSame = 1;\n    for (unsigned i = 1; i < hardIDs.Size(); i++)\n    {\n      if (hardIDs[i].Compare(hardIDs[i - 1]) != 0)\n        numSame = 1;\n      else if (++numSame == 2)\n      {\n        if (i - 1 != k)\n          hardIDs[k] = hardIDs[i - 1];\n        k++;\n      }\n    }\n    hardIDs.DeleteFrom(k);\n  }\n  \n  _hardLinks.PrepareLinks();\n  return S_OK;\n}\n\n#endif // SUPPORT_LINKS\n\n\nCArchiveExtractCallback::CArchiveExtractCallback():\n    // Write_CTime(true),\n    // Write_ATime(true),\n    // Write_MTime(true),\n    Is_elimPrefix_Mode(false),\n    _arc(NULL),\n    _multiArchives(false)\n{\n  #ifdef Z7_USE_SECURITY_CODE\n  _saclEnabled = InitLocalPrivileges();\n  #endif\n}\n\n\nvoid CArchiveExtractCallback::InitBeforeNewArchive()\n{\n#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n  ZoneBuf.Free();\n#endif\n}\n\nvoid CArchiveExtractCallback::Init(\n    const CExtractNtOptions &ntOptions,\n    const NWildcard::CCensorNode *wildcardCensor,\n    const CArc *arc,\n    IFolderArchiveExtractCallback *extractCallback2,\n    bool stdOutMode, bool testMode,\n    const FString &directoryPath,\n    const UStringVector &removePathParts, bool removePartsForAltStreams,\n    UInt64 packSize)\n{\n  ClearExtractedDirsInfo();\n  _outFileStream.Release();\n  _bufPtrSeqOutStream.Release();\n  \n#ifdef SUPPORT_LINKS\n  _hardLinks.Clear();\n  _postLinks.Clear();\n#endif\n\n#ifdef SUPPORT_ALT_STREAMS\n  _renamedFiles.Clear();\n#endif\n\n  _ntOptions = ntOptions;\n  _wildcardCensor = wildcardCensor;\n  _stdOutMode = stdOutMode;\n  _testMode = testMode;\n  _packTotal = packSize;\n  _progressTotal = packSize;\n  // _progressTotal = 0;\n  // _progressTotal_Defined = false;\n  // _progressTotal_Defined = true;\n  _extractCallback2 = extractCallback2;\n  /*\n  _compressProgress.Release();\n  _extractCallback2.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);\n  _callbackMessage.Release();\n  _extractCallback2.QueryInterface(IID_IArchiveExtractCallbackMessage2, &_callbackMessage);\n  */\n  _folderArchiveExtractCallback2.Release();\n  _extractCallback2.QueryInterface(IID_IFolderArchiveExtractCallback2, &_folderArchiveExtractCallback2);\n\n  #ifndef Z7_SFX\n\n  ExtractToStreamCallback.Release();\n  _extractCallback2.QueryInterface(IID_IFolderExtractToStreamCallback, &ExtractToStreamCallback);\n  if (ExtractToStreamCallback)\n  {\n    Int32 useStreams = 0;\n    if (ExtractToStreamCallback->UseExtractToStream(&useStreams) != S_OK)\n      useStreams = 0;\n    if (useStreams == 0)\n      ExtractToStreamCallback.Release();\n  }\n  \n  #endif\n\n  LocalProgressSpec->Init(extractCallback2, true);\n  LocalProgressSpec->SendProgress = false;\n \n  _removePathParts = removePathParts;\n  _removePartsForAltStreams = removePartsForAltStreams;\n\n  #ifndef Z7_SFX\n  _baseParentFolder = (UInt32)(Int32)-1;\n  _use_baseParentFolder_mode = false;\n  #endif\n\n  _arc = arc;\n  _dirPathPrefix = directoryPath;\n  _dirPathPrefix_Full = directoryPath;\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  if (!NName::IsAltPathPrefix(_dirPathPrefix))\n  #endif\n  {\n    NName::NormalizeDirPathPrefix(_dirPathPrefix);\n    NDir::MyGetFullPathName(directoryPath, _dirPathPrefix_Full);\n    NName::NormalizeDirPathPrefix(_dirPathPrefix_Full);\n  }\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::SetTotal(UInt64 size))\n{\n  COM_TRY_BEGIN\n  _progressTotal = size;\n  // _progressTotal_Defined = true;\n  if (!_multiArchives && _extractCallback2)\n    return _extractCallback2->SetTotal(size);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nstatic void NormalizeVals(UInt64 &v1, UInt64 &v2)\n{\n  const UInt64 kMax = (UInt64)1 << 31;\n  while (v1 > kMax)\n  {\n    v1 >>= 1;\n    v2 >>= 1;\n  }\n}\n\n\nstatic UInt64 MyMultDiv64(UInt64 unpCur, UInt64 unpTotal, UInt64 packTotal)\n{\n  NormalizeVals(packTotal, unpTotal);\n  NormalizeVals(unpCur, unpTotal);\n  if (unpTotal == 0)\n    unpTotal = 1;\n  return unpCur * packTotal / unpTotal;\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue))\n{\n  COM_TRY_BEGIN\n  \n  if (!_extractCallback2)\n    return S_OK;\n\n  UInt64 packCur;\n  if (_multiArchives)\n  {\n    packCur = LocalProgressSpec->InSize;\n    if (completeValue /* && _progressTotal_Defined */)\n      packCur += MyMultDiv64(*completeValue, _progressTotal, _packTotal);\n    completeValue = &packCur;\n  }\n  return _extractCallback2->SetCompleted(completeValue);\n \n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  COM_TRY_BEGIN\n  return LocalProgressSpec.Interface()->SetRatioInfo(inSize, outSize);\n  COM_TRY_END\n}\n\n\nvoid CArchiveExtractCallback::CreateComplexDirectory(\n    const UStringVector &dirPathParts, bool isFinal, FString &fullPath)\n{\n  // we use (_item.IsDir) in this function\n\n  bool isAbsPath = false;\n  \n  if (!dirPathParts.IsEmpty())\n  {\n    const UString &s = dirPathParts[0];\n    if (s.IsEmpty())\n      isAbsPath = true;\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    else\n    {\n      if (NName::IsDrivePath2(s))\n        isAbsPath = true;\n    }\n    #endif\n  }\n  \n  if (_pathMode == NExtract::NPathMode::kAbsPaths && isAbsPath)\n    fullPath.Empty();\n  else\n    fullPath = _dirPathPrefix;\n\n  FOR_VECTOR (i, dirPathParts)\n  {\n    if (i != 0)\n      fullPath.Add_PathSepar();\n    const UString &s = dirPathParts[i];\n    fullPath += us2fs(s);\n\n    const bool isFinalDir = (i == dirPathParts.Size() - 1 && isFinal && _item.IsDir);\n    \n    if (fullPath.IsEmpty())\n    {\n      if (isFinalDir)\n        _itemFailure = true;\n      continue;\n    }\n\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    if (_pathMode == NExtract::NPathMode::kAbsPaths)\n      if (i == 0 && s.Len() == 2 && NName::IsDrivePath2(s))\n      {\n        if (isFinalDir)\n        {\n          // we don't want to call SetAttrib() for root drive path\n          _itemFailure = true;\n        }\n        continue;\n      }\n    #endif\n\n    HRESULT hres = S_OK;\n    if (!CreateDir(fullPath))\n      hres = GetLastError_noZero_HRESULT();\n    if (isFinalDir)\n    {\n      if (!NFile::NFind::DoesDirExist(fullPath))\n      {\n        _itemFailure = true;\n        SendMessageError_with_Error(hres, \"Cannot create folder\", fullPath);\n      }\n    }\n  }\n}\n\n\nHRESULT CArchiveExtractCallback::GetTime(UInt32 index, PROPID propID, CArcTime &ft)\n{\n  ft.Clear();\n  NCOM::CPropVariant prop;\n  RINOK(_arc->Archive->GetProperty(index, propID, &prop))\n  if (prop.vt == VT_FILETIME)\n    ft.Set_From_Prop(prop);\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\n\nHRESULT CArchiveExtractCallback::GetUnpackSize()\n{\n  return _arc->GetItem_Size(_index, _curSize, _curSize_Defined);\n}\n\nstatic void AddPathToMessage(UString &s, const FString &path)\n{\n  s += \" : \";\n  s += fs2us(path);\n}\n\nHRESULT CArchiveExtractCallback::SendMessageError(const char *message, const FString &path) const\n{\n  UString s (message);\n  AddPathToMessage(s, path);\n  return _extractCallback2->MessageError(s);\n}\n\n\nHRESULT CArchiveExtractCallback::SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const\n{\n  UString s (message);\n  if (errorCode != S_OK)\n  {\n    s += \" : \";\n    s += NError::MyFormatMessage(errorCode);\n  }\n  AddPathToMessage(s, path);\n  return _extractCallback2->MessageError(s);\n}\n\nHRESULT CArchiveExtractCallback::SendMessageError_with_LastError(const char *message, const FString &path) const\n{\n  const HRESULT errorCode = GetLastError_noZero_HRESULT();\n  return SendMessageError_with_Error(errorCode, message, path);\n}\n\nHRESULT CArchiveExtractCallback::SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const\n{\n  UString s (message);\n  if (errorCode != 0)\n  {\n    s += \" : \";\n    s += NError::MyFormatMessage(errorCode);\n  }\n  AddPathToMessage(s, path1);\n  AddPathToMessage(s, path2);\n  return _extractCallback2->MessageError(s);\n}\n\nHRESULT CArchiveExtractCallback::SendMessageError2_with_LastError(\n    const char *message, const FString &path1, const FString &path2) const\n{\n  const HRESULT errorCode = GetLastError_noZero_HRESULT();\n  return SendMessageError2(errorCode, message, path1, path2);\n}\n\n#ifndef Z7_SFX\n\nZ7_CLASS_IMP_COM_1(\n  CGetProp\n  , IGetProp\n)\npublic:\n  UInt32 IndexInArc;\n  const CArc *Arc;\n  // UString BaseName; // relative path\n};\n\nZ7_COM7F_IMF(CGetProp::GetProp(PROPID propID, PROPVARIANT *value))\n{\n  /*\n  if (propID == kpidBaseName)\n  {\n    COM_TRY_BEGIN\n    NCOM::CPropVariant prop = BaseName;\n    prop.Detach(value);\n    return S_OK;\n    COM_TRY_END\n  }\n  */\n  return Arc->Archive->GetProperty(IndexInArc, propID, value);\n}\n\n#endif // Z7_SFX\n\n\nstruct CLinkLevelsInfo\n{\n  bool IsAbsolute;\n  bool ParentDirDots_after_NonParent;\n  int LowLevel;\n  int FinalLevel;\n\n  void Parse(const UString &path, bool isWSL);\n};\n\nvoid CLinkLevelsInfo::Parse(const UString &path, bool isWSL)\n{\n  IsAbsolute = isWSL ?\n      IS_PATH_SEPAR(path[0]) :\n      NName::IsAbsolutePath(path);\n  LowLevel = 0;\n  FinalLevel = 0;\n  ParentDirDots_after_NonParent = false;\n  bool nonParentDir = false;\n\n  UStringVector parts;\n  SplitPathToParts(path, parts);\n  int level = 0;\n  \n  FOR_VECTOR (i, parts)\n  {\n    const UString &s = parts[i];\n    if (s.IsEmpty())\n    {\n      if (i == 0)\n        IsAbsolute = true;\n      continue;\n    }\n    if (s.IsEqualTo(\".\"))\n      continue;\n    if (s.IsEqualTo(\"..\"))\n    {\n      if (IsAbsolute || nonParentDir)\n        ParentDirDots_after_NonParent = true;\n      level--;\n      if (LowLevel > level)\n          LowLevel = level;\n    }\n    else\n    {\n      nonParentDir = true;\n      level++;\n    }\n  }\n  \n  FinalLevel = level;\n}\n\n\nstatic bool IsSafePath(const UString &path, bool isWSL)\n{\n  CLinkLevelsInfo levelsInfo;\n  levelsInfo.Parse(path, isWSL);\n  return !levelsInfo.IsAbsolute\n      && levelsInfo.LowLevel >= 0\n      && levelsInfo.FinalLevel > 0;\n}\n\nbool IsSafePath(const UString &path);\nbool IsSafePath(const UString &path)\n{\n  return IsSafePath(path, false); // isWSL\n}\n\nbool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include);\nbool CensorNode_CheckPath2(const NWildcard::CCensorNode &node, const CReadArcItem &item, bool &include)\n{\n  bool found = false;\n\n  // CheckPathVect() doesn't check path to Parent nodes\n  if (node.CheckPathVect(item.PathParts, !item.MainIsDir, include))\n  {\n    if (!include)\n      return true;\n    \n    #ifdef SUPPORT_ALT_STREAMS\n    if (!item.IsAltStream)\n      return true;\n    #endif\n    \n    found = true;\n  }\n  \n  #ifdef SUPPORT_ALT_STREAMS\n\n  if (!item.IsAltStream)\n    return false;\n  \n  UStringVector pathParts2 = item.PathParts;\n  if (pathParts2.IsEmpty())\n    pathParts2.AddNew();\n  UString &back = pathParts2.Back();\n  back.Add_Colon();\n  back += item.AltStreamName;\n  bool include2;\n  \n  if (node.CheckPathVect(pathParts2,\n      true, // isFile,\n      include2))\n  {\n    include = include2;\n    return true;\n  }\n\n  #endif // SUPPORT_ALT_STREAMS\n\n  return found;\n}\n\n\nbool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item)\n{\n  bool include;\n  if (CensorNode_CheckPath2(node, item, include))\n    return include;\n  return false;\n}\n\n\nstatic FString MakePath_from_2_Parts(const FString &prefix, const FString &path)\n{\n  FString s (prefix);\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  if (!path.IsEmpty() && path[0] == ':' && !prefix.IsEmpty() && IsPathSepar(prefix.Back()))\n  {\n    if (!NName::IsDriveRootPath_SuperAllowed(prefix))\n      s.DeleteBack();\n  }\n  #endif\n  s += path;\n  return s;\n}\n\n\n\n#ifdef SUPPORT_LINKS\n\n/*\nstruct CTempMidBuffer\n{\n  void *Buf;\n\n  CTempMidBuffer(size_t size): Buf(NULL) { Buf = ::MidAlloc(size); }\n  ~CTempMidBuffer() { ::MidFree(Buf); }\n};\n\nHRESULT CArchiveExtractCallback::MyCopyFile(ISequentialOutStream *outStream)\n{\n  const size_t kBufSize = 1 << 16;\n  CTempMidBuffer buf(kBufSize);\n  if (!buf.Buf)\n    return E_OUTOFMEMORY;\n  \n  NIO::CInFile inFile;\n  NIO::COutFile outFile;\n  \n  if (!inFile.Open(_copyFile_Path))\n    return SendMessageError_with_LastError(\"Open error\", _copyFile_Path);\n    \n  for (;;)\n  {\n    UInt32 num;\n    \n    if (!inFile.Read(buf.Buf, kBufSize, num))\n      return SendMessageError_with_LastError(\"Read error\", _copyFile_Path);\n      \n    if (num == 0)\n      return S_OK;\n      \n      \n    RINOK(WriteStream(outStream, buf.Buf, num));\n  }\n}\n*/\n\n\nHRESULT CArchiveExtractCallback::ReadLink()\n{\n  IInArchive * const archive = _arc->Archive;\n  const UInt32 index = _index;\n  // _link.Clear(); // _link.Clear() was called already.\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidHardLink, &prop))\n    if (prop.vt == VT_BSTR)\n    {\n      _link.LinkType = k_LinkType_HardLink;\n      _link.isRelative = false; // RAR5, TAR: hard links are from root folder of archive\n      _link.LinkPath.SetFromBstr(prop.bstrVal);\n      // 7-Zip 24-: tar handler returned original path (with linux slash in most case)\n      // 7-Zip 24-: rar5 handler returned path with system slash.\n      // 7-Zip 25+: tar/rar5 handlers return linux path in most cases.\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_FAIL;\n  }\n  /*\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidCopyLink, &prop));\n    if (prop.vt == VT_BSTR)\n    {\n      _link.LinkType = k_LinkType_CopyLink;\n      _link.isRelative = false; // RAR5: copy links are from root folder of archive\n      _link.LinkPath.SetFromBstr(prop.bstrVal);\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_FAIL;\n  }\n  */\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidSymLink, &prop))\n    if (prop.vt == VT_BSTR)\n    {\n      _link.LinkType = k_LinkType_PureSymLink;\n      _link.isRelative = true; // RAR5, TAR: symbolic links are relative by default\n      _link.LinkPath.SetFromBstr(prop.bstrVal);\n      // 7-Zip 24-: (tar, cpio, xar, ext, iso) handlers returned returned original path (with linux slash in most case)\n      // 7-Zip 24-: rar5 handler returned path with system slash.\n      // 7-Zip 25+: all handlers return linux path in most cases.\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_FAIL;\n  }\n\n  // linux path separator in (_link.LinkPath) is expected for most cases,\n  // if new handler code is used, and if data in archive is correct.\n  // NtReparse_Data = NULL;\n  // NtReparse_Size = 0;\n  if (!_link.LinkPath.IsEmpty())\n  {\n    REPLACE_SLASHES_from_Linux_to_Sys(_link.LinkPath)\n  }\n  else if (_arc->GetRawProps)\n  {\n    const void *data;\n    UInt32 dataSize, propType;\n    if (_arc->GetRawProps->GetRawProp(_index, kpidNtReparse, &data, &dataSize, &propType) == S_OK\n        // && dataSize == 1234567 // for debug: unpacking without reparse\n        && dataSize)\n    {\n      if (propType != NPropDataType::kRaw)\n        return E_FAIL;\n      // 21.06: we need kpidNtReparse in linux for wim archives created in Windows\n      // NtReparse_Data = data;\n      // NtReparse_Size = dataSize;\n      // we ignore error code here, if there is failure of parsing:\n      _link.Parse_from_WindowsReparseData((const Byte *)data, dataSize);\n    }\n  }\n\n  if (_link.LinkPath.IsEmpty())\n    return S_OK;\n  // (_link.LinkPath) uses system path separator.\n  // windows: (_link.LinkPath) doesn't contain linux separator (slash).\n  {\n    // _link.LinkPath = \"\\\\??\\\\r:\\\\1\\\\2\"; // for debug\n    // rar5+ returns kpidSymLink absolute link path with \"\\??\\\" prefix.\n    // we normalize such prefix:\n    if (_link.LinkPath.IsPrefixedBy(STRING_PATH_SEPARATOR \"??\" STRING_PATH_SEPARATOR))\n    {\n      _link.isRelative = false;\n       // we normalize prefix from \"\\??\\\" to \"\\\\?\\\":\n      _link.LinkPath.ReplaceOneCharAtPos(1, WCHAR_PATH_SEPARATOR);\n      _link.isWindowsPath = true;\n      if (_link.LinkPath.IsPrefixedBy_Ascii_NoCase(\n          STRING_PATH_SEPARATOR\n          STRING_PATH_SEPARATOR \"?\"\n          STRING_PATH_SEPARATOR \"UNC\"\n          STRING_PATH_SEPARATOR))\n      {\n         // we normalize prefix from \"\\\\?\\UNC\\path\" to \"\\\\path\":\n        _link.LinkPath.DeleteFrontal(6);\n        _link.LinkPath.ReplaceOneCharAtPos(0, WCHAR_PATH_SEPARATOR);\n      }\n      else\n      {\n        const unsigned k_prefix_Size = 4;\n        if (NName::IsDrivePath(_link.LinkPath.Ptr(k_prefix_Size)))\n          _link.LinkPath.DeleteFrontal(k_prefix_Size);\n      }\n    }\n  }\n  _link.Normalize_to_RelativeSafe(_removePathParts);\n  return S_OK;\n}\n\n#endif // SUPPORT_LINKS\n\n\n#ifndef _WIN32\n\nstatic HRESULT GetOwner(IInArchive *archive,\n    UInt32 index, UInt32 pidName, UInt32 pidId, CProcessedFileInfo::COwnerInfo &res)\n{\n  {\n    NWindows::NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, pidId, &prop))\n    if (prop.vt == VT_UI4)\n    {\n      res.Id_Defined = true;\n      res.Id = prop.ulVal;\n      // res.Id++; // for debug\n      // if (pidId == kpidGroupId) res.Id += 7; // for debug\n      // res.Id = 0; // for debug\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  {\n    NWindows::NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, pidName, &prop))\n    if (prop.vt == VT_BSTR)\n    {\n      const UString s = prop.bstrVal;\n      ConvertUnicodeToUTF8(s, res.Name);\n    }\n    else if (prop.vt == VT_UI4)\n    {\n      res.Id_Defined = true;\n      res.Id = prop.ulVal;\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_INVALIDARG;\n  }\n  return S_OK;\n}\n\n#endif\n\n\nHRESULT CArchiveExtractCallback::Read_fi_Props()\n{\n  IInArchive * const archive = _arc->Archive;\n  const UInt32 index = _index;\n\n  _fi.Attrib_Defined = false;\n\n #ifndef _WIN32\n  _fi.Owner.Clear();\n  _fi.Group.Clear();\n #endif\n\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidPosixAttrib, &prop))\n    if (prop.vt == VT_UI4)\n    {\n      _fi.SetFromPosixAttrib(prop.ulVal);\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_FAIL;\n  }\n  \n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidAttrib, &prop))\n    if (prop.vt == VT_UI4)\n    {\n      _fi.Attrib = prop.ulVal;\n      _fi.Attrib_Defined = true;\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_FAIL;\n  }\n\n  RINOK(GetTime(index, kpidCTime, _fi.CTime))\n  RINOK(GetTime(index, kpidATime, _fi.ATime))\n  RINOK(GetTime(index, kpidMTime, _fi.MTime))\n\n #ifndef _WIN32\n  if (_ntOptions.ExtractOwner)\n  {\n    // SendMessageError_with_LastError(\"_ntOptions.ExtractOwner\", _diskFilePath);\n    GetOwner(archive, index, kpidUser, kpidUserId, _fi.Owner);\n    GetOwner(archive, index, kpidGroup, kpidGroupId, _fi.Group);\n  }\n #endif\n\n  return S_OK;\n}\n\n\n\nvoid CArchiveExtractCallback::CorrectPathParts()\n{\n  UStringVector &pathParts = _item.PathParts;\n\n  #ifdef SUPPORT_ALT_STREAMS\n  if (!_item.IsAltStream\n      || !pathParts.IsEmpty()\n      || !(_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt))\n  #endif\n    Correct_FsPath(_pathMode == NExtract::NPathMode::kAbsPaths, _keepAndReplaceEmptyDirPrefixes, pathParts, _item.MainIsDir);\n  \n  #ifdef SUPPORT_ALT_STREAMS\n    \n  if (_item.IsAltStream)\n  {\n    UString s (_item.AltStreamName);\n    Correct_AltStream_Name(s);\n    bool needColon = true;\n    \n    if (pathParts.IsEmpty())\n    {\n      pathParts.AddNew();\n      if (_removePartsForAltStreams || _pathMode == NExtract::NPathMode::kNoPathsAlt)\n        needColon = false;\n    }\n    #ifdef _WIN32\n    else if (_pathMode == NExtract::NPathMode::kAbsPaths &&\n        NWildcard::GetNumPrefixParts_if_DrivePath(pathParts) == pathParts.Size())\n      pathParts.AddNew();\n    #endif\n    \n    UString &name = pathParts.Back();\n    if (needColon)\n      name.Add_Char((char)(_ntOptions.ReplaceColonForAltStream ? '_' : ':'));\n    name += s;\n  }\n    \n  #endif // SUPPORT_ALT_STREAMS\n}\n\n\nstatic void GetFiTimesCAM(const CProcessedFileInfo &fi, CFiTimesCAM &pt, const CArc &arc)\n{\n  pt.CTime_Defined = false;\n  pt.ATime_Defined = false;\n  pt.MTime_Defined = false;\n\n  // if (Write_MTime)\n  {\n    if (fi.MTime.Def)\n    {\n      fi.MTime.Write_To_FiTime(pt.MTime);\n      pt.MTime_Defined = true;\n    }\n    else if (arc.MTime.Def)\n    {\n      arc.MTime.Write_To_FiTime(pt.MTime);\n      pt.MTime_Defined = true;\n    }\n  }\n\n  if (/* Write_CTime && */ fi.CTime.Def)\n  {\n    fi.CTime.Write_To_FiTime(pt.CTime);\n    pt.CTime_Defined = true;\n  }\n\n  if (/* Write_ATime && */ fi.ATime.Def)\n  {\n    fi.ATime.Write_To_FiTime(pt.ATime);\n    pt.ATime_Defined = true;\n  }\n}\n\n\nvoid CArchiveExtractCallback::CreateFolders()\n{\n  // 21.04 : we don't change original (_item.PathParts) here\n  UStringVector pathParts = _item.PathParts;\n\n  bool isFinal = true;\n  // bool is_DirOp = false;\n  if (!pathParts.IsEmpty())\n  {\n    /* v23: if we extract symlink, and we know that it links to dir:\n        Linux:   we don't create dir item (symlink_from_path) here.\n        Windows: SetReparseData() will create dir item, if it doesn't exist,\n                 but if we create dir item here, it's not problem. */\n    if (!_item.IsDir\n        #ifdef SUPPORT_LINKS\n        // #ifndef WIN32\n          || !_link.LinkPath.IsEmpty()\n        // #endif\n        #endif\n       )\n    {\n      pathParts.DeleteBack();\n      isFinal = false; // last path part was excluded\n    }\n    // else is_DirOp = true;\n  }\n    \n  if (pathParts.IsEmpty())\n  {\n    /* if (_some_pathParts_wereRemoved && Is_elimPrefix_Mode),\n       then we can have empty pathParts() here for root folder.\n       v24.00: fixed: we set timestamps for such folder still.\n    */\n    if (!_some_pathParts_wereRemoved ||\n        !Is_elimPrefix_Mode)\n      return;\n    // return; // ignore empty paths case\n  }\n  /*\n  if (is_DirOp)\n  {\n    RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))\n    _op_WasReported = true;\n  }\n  */\n\n  FString fullPathNew;\n  CreateComplexDirectory(pathParts, isFinal, fullPathNew);\n\n  /*\n  if (is_DirOp)\n  {\n    RINOK(SetOperationResult(\n        // _itemFailure ? NArchive::NExtract::NOperationResult::kDataError :\n        NArchive::NExtract::NOperationResult::kOK\n        ))\n  }\n  */\n  \n  if (!_item.IsDir)\n    return;\n  if (fullPathNew.IsEmpty())\n    return;\n\n  if (_itemFailure)\n    return;\n\n  CDirPathTime pt;\n  GetFiTimesCAM(_fi, pt, *_arc);\n \n  if (pt.IsSomeTimeDefined())\n  {\n    pt.Path = fullPathNew;\n    pt.SetDirTime_to_FS_2();\n    _extractedFolders.Add(pt);\n  }\n}\n\n\n\n/*\n  CheckExistFile(fullProcessedPath)\n    it can change: fullProcessedPath, _isRenamed, _overwriteMode\n  (needExit = true) means that we must exit GetStream() even for S_OK result.\n*/\n\nHRESULT CArchiveExtractCallback::CheckExistFile(FString &fullProcessedPath, bool &needExit)\n{\n  needExit = true; // it was set already before\n\n  NFind::CFileInfo fileInfo;\n\n  if (fileInfo.Find(fullProcessedPath))\n  {\n    if (_overwriteMode == NExtract::NOverwriteMode::kSkip)\n      return S_OK;\n    \n    if (_overwriteMode == NExtract::NOverwriteMode::kAsk)\n    {\n      const int slashPos = fullProcessedPath.ReverseFind_PathSepar();\n      const FString realFullProcessedPath = fullProcessedPath.Left((unsigned)(slashPos + 1)) + fileInfo.Name;\n  \n      /* (fileInfo) can be symbolic link.\n         we can show final file properties here. */\n\n      FILETIME ft1;\n      FiTime_To_FILETIME(fileInfo.MTime, ft1);\n\n      Int32 overwriteResult;\n      RINOK(_extractCallback2->AskOverwrite(\n          fs2us(realFullProcessedPath), &ft1, &fileInfo.Size, _item.Path,\n          _fi.MTime.Def ? &_fi.MTime.FT : NULL,\n          _curSize_Defined ? &_curSize : NULL,\n          &overwriteResult))\n          \n      switch (overwriteResult)\n      {\n        case NOverwriteAnswer::kCancel:\n          return E_ABORT;\n        case NOverwriteAnswer::kNo:\n          return S_OK;\n        case NOverwriteAnswer::kNoToAll:\n          _overwriteMode = NExtract::NOverwriteMode::kSkip;\n          return S_OK;\n    \n        case NOverwriteAnswer::kYes:\n          break;\n        case NOverwriteAnswer::kYesToAll:\n          _overwriteMode = NExtract::NOverwriteMode::kOverwrite;\n          break;\n        case NOverwriteAnswer::kAutoRename:\n          _overwriteMode = NExtract::NOverwriteMode::kRename;\n          break;\n        default:\n          return E_FAIL;\n      }\n    } // NExtract::NOverwriteMode::kAsk\n\n    if (_overwriteMode == NExtract::NOverwriteMode::kRename)\n    {\n      if (!AutoRenamePath(fullProcessedPath))\n      {\n        RINOK(SendMessageError(kCantAutoRename, fullProcessedPath))\n        return E_FAIL;\n      }\n      _isRenamed = true;\n    }\n    else if (_overwriteMode == NExtract::NOverwriteMode::kRenameExisting)\n    {\n      FString existPath (fullProcessedPath);\n      if (!AutoRenamePath(existPath))\n      {\n        RINOK(SendMessageError(kCantAutoRename, fullProcessedPath))\n        return E_FAIL;\n      }\n      // MyMoveFile can rename folders. So it's OK to use it for folders too\n      if (!MyMoveFile(fullProcessedPath, existPath))\n      {\n        RINOK(SendMessageError2_with_LastError(kCantRenameFile, existPath, fullProcessedPath))\n        return E_FAIL;\n      }\n    }\n    else // not Rename*\n    {\n      if (fileInfo.IsDir())\n      {\n        // do we need to delete all files in folder?\n        if (!RemoveDir(fullProcessedPath))\n        {\n          RINOK(SendMessageError_with_LastError(kCantDeleteOutputDir, fullProcessedPath))\n          return S_OK;\n        }\n      }\n      else // fileInfo is not Dir\n      {\n        if (NFind::DoesFileExist_Raw(fullProcessedPath))\n          if (!DeleteFileAlways(fullProcessedPath))\n            if (GetLastError() != ERROR_FILE_NOT_FOUND) // check it in linux\n            {\n              RINOK(SendMessageError_with_LastError(kCantDeleteOutputFile, fullProcessedPath))\n              return S_OK;\n              // return E_FAIL;\n            }\n      } // fileInfo is not Dir\n    } // not Rename*\n  }\n  else // not Find(fullProcessedPath)\n  {\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    // we need to clear READ-ONLY of parent before creating alt stream\n    const int colonPos = NName::FindAltStreamColon(fullProcessedPath);\n    if (colonPos >= 0 && fullProcessedPath[(unsigned)colonPos + 1] != 0)\n    {\n      FString parentFsPath (fullProcessedPath);\n      parentFsPath.DeleteFrom((unsigned)colonPos);\n      NFind::CFileInfo parentFi;\n      if (parentFi.Find(parentFsPath))\n      {\n        if (parentFi.IsReadOnly())\n        {\n          _altStream_NeedRestore_Attrib_for_parentFsPath = parentFsPath;\n          _altStream_NeedRestore_AttribVal = parentFi.Attrib;\n          SetFileAttrib(parentFsPath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY);\n        }\n      }\n    }\n    #endif // defined(_WIN32) && !defined(UNDER_CE)\n  }\n  \n  needExit = false;\n  return S_OK;\n}\n\n\n\n/*\nreturn:\n  needExit = false: caller will     use (outStreamLoc) and _hashStreamSpec\n  needExit = true : caller will not use (outStreamLoc) and _hashStreamSpec.\n*/\nHRESULT CArchiveExtractCallback::GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit)\n{\n  needExit = true;\n    \n  RINOK(Read_fi_Props())\n\n  #ifdef SUPPORT_LINKS\n  IInArchive * const archive = _arc->Archive;\n  #endif\n\n  const UInt32 index = _index;\n\n  bool isAnti = false;\n  RINOK(_arc->IsItem_Anti(index, isAnti))\n\n  CorrectPathParts();\n  UString processedPath (MakePathFromParts(_item.PathParts));\n  \n  if (!isAnti)\n  {\n    // 21.04: CreateFolders doesn't change (_item.PathParts)\n    CreateFolders();\n  }\n  \n  FString fullProcessedPath (us2fs(processedPath));\n  if (_pathMode != NExtract::NPathMode::kAbsPaths\n      || !NName::IsAbsolutePath(processedPath))\n  {\n    fullProcessedPath = MakePath_from_2_Parts(_dirPathPrefix, fullProcessedPath);\n  }\n\n  #ifdef SUPPORT_ALT_STREAMS\n  if (_item.IsAltStream && _item.ParentIndex != (UInt32)(Int32)-1)\n  {\n    const int renIndex = _renamedFiles.FindInSorted(CIndexToPathPair(_item.ParentIndex));\n    if (renIndex != -1)\n    {\n      const CIndexToPathPair &pair = _renamedFiles[(unsigned)renIndex];\n      fullProcessedPath = pair.Path;\n      fullProcessedPath.Add_Colon();\n      UString s (_item.AltStreamName);\n      Correct_AltStream_Name(s);\n      fullProcessedPath += us2fs(s);\n    }\n  }\n  #endif // SUPPORT_ALT_STREAMS\n\n  if (_item.IsDir)\n  {\n    _diskFilePath = fullProcessedPath;\n    if (isAnti)\n      RemoveDir(_diskFilePath);\n    #ifdef SUPPORT_LINKS\n    if (_link.LinkPath.IsEmpty())\n    #endif\n    {\n      if (!isAnti)\n        SetAttrib();\n      return S_OK;\n    }\n  }\n  else if (!_isSplit)\n  {\n    RINOK(CheckExistFile(fullProcessedPath, needExit))\n    if (needExit)\n      return S_OK;\n    needExit = true;\n  }\n  \n  _diskFilePath = fullProcessedPath;\n  // **************** 7-Zip ZS Modification Start ****************\n  if (FirstExtractedPath.IsEmpty())\n    FirstExtractedPath = fullProcessedPath;\n  // **************** 7-Zip ZS Modification End ****************\n\n  if (isAnti)\n  {\n    needExit = false;\n    return S_OK;\n  }\n\n  // not anti\n\n  #ifdef SUPPORT_LINKS\n  \n  if (!_link.LinkPath.IsEmpty())\n  {\n    #ifndef UNDER_CE\n    {\n      bool linkWasSet = false;\n      RINOK(SetLink(fullProcessedPath, _link, linkWasSet))\n/*\n      // we don't set attributes for placeholder.\n      if (linkWasSet)\n      {\n        _isSymLinkCreated = _link.Is_AnySymLink();\n        SetAttrib();\n        // printf(\"\\nlinkWasSet %s\\n\", GetAnsiString(_diskFilePath));\n      }\n*/\n    }\n    #endif // UNDER_CE\n\n    // if (_copyFile_Path.IsEmpty())\n    {\n      needExit = false;\n      return S_OK;\n    }\n  }\n\n  if (!_hardLinks.IDs.IsEmpty() && !_item.IsAltStream && !_item.IsDir)\n  {\n    CHardLinkNode h;\n    bool defined;\n    RINOK(Archive_Get_HardLinkNode(archive, index, h, defined))\n    if (defined)\n    {\n      const int linkIndex = _hardLinks.IDs.FindInSorted2(h);\n      if (linkIndex != -1)\n      {\n        FString &hl = _hardLinks.Links[(unsigned)linkIndex];\n        if (hl.IsEmpty())\n          hl = fullProcessedPath;\n        else\n        {\n          bool link_was_Created = false;\n          RINOK(CreateHardLink2(fullProcessedPath, hl, link_was_Created))\n          if (!link_was_Created)\n            return S_OK;\n          // printf(\"\\nHard linkWasSet Archive_Get_HardLinkNode %s\\n\", GetAnsiString(_diskFilePath));\n          // _needSetAttrib = true; // do we need to set attribute ?\n          SetAttrib();\n          /* if we set (needExit = false) here, _hashStreamSpec will be used,\n             and hash will be calulated for all hard links files (it's slower).\n             But \"Test\" operation also calculates hashes.\n          */\n          needExit = false;\n          return S_OK;\n        }\n      }\n    }\n  }\n  \n  #endif // SUPPORT_LINKS\n\n\n  // ---------- CREATE WRITE FILE -----\n\n  _outFileStreamSpec = new COutFileStream;\n  CMyComPtr<IOutStream> outFileStream_Loc(_outFileStreamSpec);\n  \n  if (!_outFileStreamSpec->Create_ALWAYS_or_Open_ALWAYS(fullProcessedPath, !_isSplit))\n  {\n    // if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)\n    {\n      RINOK(SendMessageError_with_LastError(kCantOpenOutFile, fullProcessedPath))\n      return S_OK;\n    }\n  }\n  \n  _needSetAttrib = true;\n\n  bool is_SymLink_in_Data = false;\n\n  if (_curSize_Defined && _curSize && _curSize < k_LinkDataSize_LIMIT)\n  {\n    if (_fi.IsLinuxSymLink())\n    {\n      is_SymLink_in_Data = true;\n      _is_SymLink_in_Data_Linux = true;\n    }\n    else if (_fi.IsReparse())\n    {\n      is_SymLink_in_Data = true;\n      _is_SymLink_in_Data_Linux = false;\n    }\n  }\n\n  if (is_SymLink_in_Data)\n  {\n    _outMemBuf.Alloc((size_t)_curSize);\n    _bufPtrSeqOutStream_Spec = new CBufPtrSeqOutStream;\n    _bufPtrSeqOutStream = _bufPtrSeqOutStream_Spec;\n    _bufPtrSeqOutStream_Spec->Init(_outMemBuf, _outMemBuf.Size());\n    outStreamLoc = _bufPtrSeqOutStream;\n  }\n  else // not reparse\n  {\n    if (_ntOptions.PreAllocateOutFile && !_isSplit && _curSize_Defined && _curSize > (1 << 12))\n    {\n      // UInt64 ticks = GetCpuTicks();\n      _fileLength_that_WasSet = _curSize;\n      bool res = _outFileStreamSpec->File.SetLength(_curSize);\n      _fileLength_WasSet = res;\n      \n      // ticks = GetCpuTicks() - ticks;\n      // printf(\"\\nticks = %10d\\n\", (unsigned)ticks);\n      if (!res)\n      {\n        RINOK(SendMessageError_with_LastError(kCantSetFileLen, fullProcessedPath))\n      }\n      \n      /*\n      _outFileStreamSpec->File.Close();\n      ticks = GetCpuTicks() - ticks;\n      printf(\"\\nticks = %10d\\n\", (unsigned)ticks);\n      return S_FALSE;\n      */\n      \n      /*\n      File.SetLength() on FAT (xp64): is fast, but then File.Close() can be slow,\n      if we don't write any data.\n      File.SetLength() for remote share file (exFAT) can be slow in some cases,\n      and the Windows can return \"network error\" after 1 minute,\n      while remote file still can grow.\n      We need some way to detect such bad cases and disable PreAllocateOutFile mode.\n      */\n      \n      res = _outFileStreamSpec->SeekToBegin_bool();\n      if (!res)\n      {\n        RINOK(SendMessageError_with_LastError(\"Cannot seek to begin of file\", fullProcessedPath))\n      }\n    } // PreAllocateOutFile\n    \n    #ifdef SUPPORT_ALT_STREAMS\n    if (_isRenamed && !_item.IsAltStream)\n    {\n      CIndexToPathPair pair(index, fullProcessedPath);\n      unsigned oldSize = _renamedFiles.Size();\n      unsigned insertIndex = _renamedFiles.AddToUniqueSorted(pair);\n      if (oldSize == _renamedFiles.Size())\n        _renamedFiles[insertIndex].Path = fullProcessedPath;\n    }\n    #endif // SUPPORT_ALT_STREAMS\n    \n    if (_isSplit)\n    {\n      RINOK(outFileStream_Loc->Seek((Int64)_position, STREAM_SEEK_SET, NULL))\n    }\n    outStreamLoc = outFileStream_Loc;\n  } // if not reparse\n\n  _outFileStream = outFileStream_Loc;\n      \n  needExit = false;\n  return S_OK;\n}\n\n\n\nHRESULT CArchiveExtractCallback::GetItem(UInt32 index)\n{\n  #ifndef Z7_SFX\n  _item._use_baseParentFolder_mode = _use_baseParentFolder_mode;\n  if (_use_baseParentFolder_mode)\n  {\n    _item._baseParentFolder = (int)_baseParentFolder;\n    if (_pathMode == NExtract::NPathMode::kFullPaths ||\n        _pathMode == NExtract::NPathMode::kAbsPaths)\n      _item._baseParentFolder = -1;\n  }\n  #endif // Z7_SFX\n\n  #ifdef SUPPORT_ALT_STREAMS\n  _item.WriteToAltStreamIfColon = _ntOptions.WriteToAltStreamIfColon;\n  #endif\n\n  return _arc->GetItem(index, _item);\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode))\n{\n  COM_TRY_BEGIN\n\n  *outStream = NULL;\n\n  #ifndef Z7_SFX\n  if (_hashStream)\n    _hashStreamSpec->ReleaseStream();\n  _hashStreamWasUsed = false;\n  #endif\n\n  _outFileStream.Release();\n  _bufPtrSeqOutStream.Release();\n\n  _encrypted = false;\n  _isSplit = false;\n  _curSize_Defined = false;\n  _fileLength_WasSet = false;\n  _isRenamed = false;\n  // _fi.Clear();\n  _extractMode = false;\n  _is_SymLink_in_Data_Linux = false;\n  _needSetAttrib = false;\n  _isSymLinkCreated = false;\n  _itemFailure = false;\n  _some_pathParts_wereRemoved = false;\n  // _op_WasReported = false;\n\n  _position = 0;\n  _curSize = 0;\n  _fileLength_that_WasSet = 0;\n  _index = index;\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n  _altStream_NeedRestore_AttribVal = 0;\n  _altStream_NeedRestore_Attrib_for_parentFsPath.Empty();\n#endif\n\n  _diskFilePath.Empty();\n\n  #ifdef SUPPORT_LINKS\n  // _copyFile_Path.Empty();\n  _link.Clear();\n  #endif\n\n\n  switch (askExtractMode)\n  {\n    case NArchive::NExtract::NAskMode::kExtract:\n      if (_testMode)\n      {\n        // askExtractMode = NArchive::NExtract::NAskMode::kTest;\n      }\n      else\n        _extractMode = true;\n      break;\n    default: break;\n  }\n\n\n  IInArchive * const archive = _arc->Archive;\n\n  RINOK(GetItem(index))\n\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetProperty(index, kpidPosition, &prop))\n    if (prop.vt != VT_EMPTY)\n    {\n      if (prop.vt != VT_UI8)\n        return E_FAIL;\n      _position = prop.uhVal.QuadPart;\n      _isSplit = true;\n    }\n  }\n\n#ifdef SUPPORT_LINKS\n  RINOK(ReadLink())\n#endif\n  \n  RINOK(Archive_GetItemBoolProp(archive, index, kpidEncrypted, _encrypted))\n\n  RINOK(GetUnpackSize())\n\n  #ifdef SUPPORT_ALT_STREAMS\n  if (!_ntOptions.AltStreams.Val && _item.IsAltStream)\n    return S_OK;\n  #endif // SUPPORT_ALT_STREAMS\n\n  // we can change (_item.PathParts) in this function\n  UStringVector &pathParts = _item.PathParts;\n\n  if (_wildcardCensor)\n  {\n    if (!CensorNode_CheckPath(*_wildcardCensor, _item))\n      return S_OK;\n  }\n\n#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract\n      && !_testMode\n      && _item.IsAltStream\n      && ZoneBuf.Size() != 0\n      && Is_ZoneId_StreamName(_item.AltStreamName))\n    if (ZoneMode != NExtract::NZoneIdMode::kOffice\n        || _item.PathParts.IsEmpty()\n        || FindExt2(kOfficeExtensions, _item.PathParts.Back()))\n      return S_OK;\n#endif\n\n\n  #ifndef Z7_SFX\n  if (_use_baseParentFolder_mode)\n  {\n    if (!pathParts.IsEmpty())\n    {\n      unsigned numRemovePathParts = 0;\n      \n      #ifdef SUPPORT_ALT_STREAMS\n      if (_pathMode == NExtract::NPathMode::kNoPathsAlt && _item.IsAltStream)\n        numRemovePathParts = pathParts.Size();\n      else\n      #endif\n      if (_pathMode == NExtract::NPathMode::kNoPaths ||\n          _pathMode == NExtract::NPathMode::kNoPathsAlt)\n        numRemovePathParts = pathParts.Size() - 1;\n      pathParts.DeleteFrontal(numRemovePathParts);\n    }\n  }\n  else\n  #endif // Z7_SFX\n  {\n    if (pathParts.IsEmpty())\n    {\n      if (_item.IsDir)\n        return S_OK;\n      /*\n      #ifdef SUPPORT_ALT_STREAMS\n      if (!_item.IsAltStream)\n      #endif\n        return E_FAIL;\n      */\n    }\n\n    unsigned numRemovePathParts = 0;\n    \n    switch ((int)_pathMode)\n    {\n      case NExtract::NPathMode::kFullPaths:\n      case NExtract::NPathMode::kCurPaths:\n      {\n        if (_removePathParts.IsEmpty())\n          break;\n        bool badPrefix = false;\n        \n        if (pathParts.Size() < _removePathParts.Size())\n          badPrefix = true;\n        else\n        {\n          if (pathParts.Size() == _removePathParts.Size())\n          {\n            if (_removePartsForAltStreams)\n            {\n              #ifdef SUPPORT_ALT_STREAMS\n              if (!_item.IsAltStream)\n              #endif\n                badPrefix = true;\n            }\n            else\n            {\n              if (!_item.MainIsDir)\n                badPrefix = true;\n            }\n          }\n          \n          if (!badPrefix)\n          FOR_VECTOR (i, _removePathParts)\n          {\n            if (CompareFileNames(_removePathParts[i], pathParts[i]) != 0)\n            {\n              badPrefix = true;\n              break;\n            }\n          }\n        }\n        \n        if (badPrefix)\n        {\n          if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)\n            return E_FAIL;\n        }\n        else\n        {\n          numRemovePathParts = _removePathParts.Size();\n          _some_pathParts_wereRemoved = true;\n        }\n        break;\n      }\n      \n      case NExtract::NPathMode::kNoPaths:\n      {\n        if (!pathParts.IsEmpty())\n          numRemovePathParts = pathParts.Size() - 1;\n        break;\n      }\n      case NExtract::NPathMode::kNoPathsAlt:\n      {\n        #ifdef SUPPORT_ALT_STREAMS\n        if (_item.IsAltStream)\n          numRemovePathParts = pathParts.Size();\n        else\n        #endif\n        if (!pathParts.IsEmpty())\n          numRemovePathParts = pathParts.Size() - 1;\n        break;\n      }\n      case NExtract::NPathMode::kAbsPaths:\n      default:\n        break;\n    }\n    \n    pathParts.DeleteFrontal(numRemovePathParts);\n  }\n\n  \n  #ifndef Z7_SFX\n\n  if (ExtractToStreamCallback)\n  {\n    CMyComPtr2_Create<IGetProp, CGetProp> GetProp;\n    GetProp->Arc = _arc;\n    GetProp->IndexInArc = index;\n    UString name (MakePathFromParts(pathParts));\n    // GetProp->BaseName = name;\n    #ifdef SUPPORT_ALT_STREAMS\n    if (_item.IsAltStream)\n    {\n      if (!pathParts.IsEmpty() || (!_removePartsForAltStreams && _pathMode != NExtract::NPathMode::kNoPathsAlt))\n        name.Add_Colon();\n      name += _item.AltStreamName;\n    }\n    #endif\n\n    return ExtractToStreamCallback->GetStream7(name, BoolToInt(_item.IsDir), outStream, askExtractMode, GetProp);\n  }\n\n  #endif // Z7_SFX\n\n\n  CMyComPtr<ISequentialOutStream> outStreamLoc;\n\n  if (askExtractMode == NArchive::NExtract::NAskMode::kExtract && !_testMode)\n  {\n    if (_stdOutMode)\n      outStreamLoc = new CStdOutFileStream;\n    else\n    {\n      bool needExit = true;\n      RINOK(GetExtractStream(outStreamLoc, needExit))\n      if (needExit)\n        return S_OK;\n    }\n  }\n\n  #ifndef Z7_SFX\n  if (_hashStream)\n  {\n    if (askExtractMode == NArchive::NExtract::NAskMode::kExtract ||\n        askExtractMode == NArchive::NExtract::NAskMode::kTest)\n    {\n      _hashStreamSpec->SetStream(outStreamLoc);\n      outStreamLoc = _hashStream;\n      _hashStreamSpec->Init(true);\n      _hashStreamWasUsed = true;\n    }\n  }\n  #endif // Z7_SFX\n\n  if (outStreamLoc)\n  {\n    /*\n    #ifdef SUPPORT_LINKS\n    if (!_copyFile_Path.IsEmpty())\n    {\n      RINOK(PrepareOperation(askExtractMode));\n      RINOK(MyCopyFile(outStreamLoc));\n      return SetOperationResult(NArchive::NExtract::NOperationResult::kOK);\n    }\n    if (_link.isCopyLink && _testMode)\n      return S_OK;\n    #endif\n    */\n    *outStream = outStreamLoc.Detach();\n  }\n  \n  return S_OK;\n\n  COM_TRY_END\n}\n\n\n\n\n\n\n\n\n\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode))\n{\n  COM_TRY_BEGIN\n\n  #ifndef Z7_SFX\n  // if (!_op_WasReported)\n  if (ExtractToStreamCallback)\n    return ExtractToStreamCallback->PrepareOperation7(askExtractMode);\n  #endif\n  \n  _extractMode = false;\n  \n  switch (askExtractMode)\n  {\n    case NArchive::NExtract::NAskMode::kExtract:\n      if (_testMode)\n        askExtractMode = NArchive::NExtract::NAskMode::kTest;\n      else\n        _extractMode = true;\n      break;\n    default: break;\n  }\n\n  // if (_op_WasReported) return S_OK;\n  \n  return _extractCallback2->PrepareOperation(_item.Path, BoolToInt(_item.IsDir),\n      askExtractMode, _isSplit ? &_position: NULL);\n  \n  COM_TRY_END\n}\n\n\n\n\n\nHRESULT CArchiveExtractCallback::CloseFile()\n{\n  if (!_outFileStream)\n    return S_OK;\n  \n  HRESULT hres = S_OK;\n  \n  const UInt64 processedSize = _outFileStreamSpec->ProcessedSize;\n  if (_fileLength_WasSet && _fileLength_that_WasSet > processedSize)\n  {\n    const bool res = _outFileStreamSpec->File.SetLength(processedSize);\n    _fileLength_WasSet = res;\n    if (!res)\n    {\n      const HRESULT hres2 = SendMessageError_with_LastError(kCantSetFileLen, us2fs(_item.Path));\n      if (hres == S_OK)\n        hres = hres2;\n    }\n  }\n\n  _curSize = processedSize;\n  _curSize_Defined = true;\n\n #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n  if (ZoneBuf.Size() != 0\n      && !_item.IsAltStream)\n  {\n    // if (NFind::DoesFileExist_Raw(tempFilePath))\n    if (ZoneMode != NExtract::NZoneIdMode::kOffice ||\n        FindExt2(kOfficeExtensions, fs2us(_diskFilePath)))\n    {\n      // we must write zone file before setting of timestamps\n      if (!WriteZoneFile_To_BaseFile(_diskFilePath, ZoneBuf))\n      {\n        // we can't write it in FAT\n        // SendMessageError_with_LastError(\"Can't write Zone.Identifier stream\", path);\n      }\n    }\n  }\n #endif\n\n  CFiTimesCAM t;\n  GetFiTimesCAM(_fi, t, *_arc);\n\n  // #ifdef _WIN32\n  if (t.IsSomeTimeDefined())\n    _outFileStreamSpec->SetTime(\n        t.CTime_Defined ? &t.CTime : NULL,\n        t.ATime_Defined ? &t.ATime : NULL,\n        t.MTime_Defined ? &t.MTime : NULL);\n  // #endif\n\n  RINOK(_outFileStreamSpec->Close())\n  _outFileStream.Release();\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n  if (!_altStream_NeedRestore_Attrib_for_parentFsPath.IsEmpty())\n  {\n    SetFileAttrib(_altStream_NeedRestore_Attrib_for_parentFsPath, _altStream_NeedRestore_AttribVal);\n    _altStream_NeedRestore_Attrib_for_parentFsPath.Empty();\n  }\n#endif\n\n  return hres;\n}\n\n\n#ifdef SUPPORT_LINKS\n\nstatic bool CheckLinkPath_in_FS_for_pathParts(const FString &path, const UStringVector &v)\n{\n  FString path2 = path;\n  FOR_VECTOR (i, v)\n  {\n    // if (i == v.Size() - 1) path = path2; // we don't need last part in returned path\n    path2 += us2fs(v[i]);\n    NFind::CFileInfo fi;\n    // printf(\"\\nCheckLinkPath_in_FS_for_pathParts(): %s\\n\", GetOemString(path2).Ptr());\n    if (fi.Find(path2) && fi.IsOsSymLink())\n      return false;\n    path2.Add_PathSepar();\n  }\n  return true;\n}\n\n/*\nlink.isRelative / relative_item_PathPrefix\n   false        / empty\n   true         / item path without last part\n*/\nstatic bool CheckLinkPath_in_FS(\n    const FString &pathPrefix_in_FS,\n    const CPostLink &postLink,\n    const UString &relative_item_PathPrefix)\n{\n  const CLinkInfo &link = postLink.LinkInfo;\n  if (postLink.item_PathParts.IsEmpty() || link.LinkPath.IsEmpty())\n    return false;\n  FString path;\n  {\n    const UString &s = postLink.item_PathParts[0];\n    if (!s.IsEmpty() && !NName::IsAbsolutePath(s))\n      path = pathPrefix_in_FS; // item_PathParts is relative. So we use absolutre prefix\n  }\n  if (!CheckLinkPath_in_FS_for_pathParts(path, postLink.item_PathParts))\n    return false;\n  path += us2fs(relative_item_PathPrefix);\n  UStringVector v;\n  SplitPathToParts(link.LinkPath, v);\n  // we check target paths:\n  return CheckLinkPath_in_FS_for_pathParts(path, v);\n}\n\nstatic const unsigned k_DangLevel_MAX_for_Link_over_Link = 9;\n\nHRESULT CArchiveExtractCallback::CreateHardLink2(\n    const FString &newFilePath, const FString &existFilePath, bool &link_was_Created) const\n{\n  link_was_Created = false;\n  if (_ntOptions.SymLinks_DangerousLevel <= k_DangLevel_MAX_for_Link_over_Link)\n  {\n    NFind::CFileInfo fi;\n    if (fi.Find(existFilePath) && fi.IsOsSymLink())\n      return SendMessageError2(0, k_HardLink_to_SymLink_Ignored, newFilePath, existFilePath);\n  }\n  if (!MyCreateHardLink(newFilePath, existFilePath))\n    return SendMessageError2_with_LastError(kCantCreateHardLink, newFilePath, existFilePath);\n  link_was_Created = true;\n  return S_OK;\n}\n\n\n\nHRESULT CArchiveExtractCallback::SetLink(\n    const FString &fullProcessedPath_from,\n    const CLinkInfo &link,\n    bool &linkWasSet) // placeholder was created\n{\n  linkWasSet = false;\n  if (link.LinkPath.IsEmpty())\n    return S_OK;\n  if (!_ntOptions.SymLinks.Val && link.Is_AnySymLink())\n    return S_OK;\n  CPostLink postLink;\n  postLink.Index_in_Arc = _index;\n  postLink.item_IsDir = _item.IsDir;\n  postLink.item_Path = _item.Path;\n  postLink.item_PathParts = _item.PathParts;\n  postLink.item_FileInfo = _fi;\n  postLink.fullProcessedPath_from = fullProcessedPath_from;\n  postLink.LinkInfo = link;\n  _postLinks.Add(postLink);\n  \n  // file doesn't exist in most cases. So we don't check for error.\n  DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, false); // checkThatFileIsEmpty = false\n\n  NIO::COutFile outFile;\n  if (!outFile.Create_NEW(fullProcessedPath_from))\n    return SendMessageError(\"Cannot create temporary link file\", fullProcessedPath_from);\n#if 0 // 1 for debug\n  // here we can write link path to temporary link file placeholder,\n  // but empty placeholder is better, because we don't want to get any non-eampty data instead of link file.\n  AString s;\n  ConvertUnicodeToUTF8(link.LinkPath, s);\n  outFile.WriteFull(s, s.Len());\n#endif\n  linkWasSet = true;\n  return S_OK;\n}\n\n\n// if file/dir is symbolic link it will remove only link itself\nHRESULT CArchiveExtractCallback::DeleteLinkFileAlways_or_RemoveEmptyDir(\n    const FString &path, bool checkThatFileIsEmpty) const\n{\n  NFile::NFind::CFileInfo fi;\n  if (fi.Find(path)) // followLink = false\n  {\n    if (fi.IsDir())\n    {\n      if (RemoveDirAlways_if_Empty(path))\n        return S_OK;\n    }\n    else\n    {\n      // link file placeholder must be empty\n      if (checkThatFileIsEmpty && !fi.IsOsSymLink() && fi.Size != 0)\n        return SendMessageError(\"Temporary link file is not empty\", path);\n      if (DeleteFileAlways(path))\n        return S_OK;\n    }\n    if (GetLastError() != ERROR_FILE_NOT_FOUND)\n      return SendMessageError_with_LastError(\n          fi.IsDir() ?\n            k_CantDelete_Dir_for_SymLink:\n            k_CantDelete_File_for_SymLink,\n          path);\n  }\n  return S_OK;\n}\n\n\n/*\nin:\n  link.LinkPath : must be relative (non-absolute) path in any case !!!\n  link.isRelative / target path that must stored as created link:\n       == false   / _dirPathPrefix_Full + link.LinkPath\n       == true    / link.LinkPath\n*/\nstatic HRESULT SetLink2(const CArchiveExtractCallback &callback,\n    const CPostLink &postLink, bool &linkWasSet)\n{\n  const CLinkInfo &link = postLink.LinkInfo;\n  const FString &fullProcessedPath_from = postLink.fullProcessedPath_from; // full file path in FS (fullProcessedPath_from)\n\n  const unsigned level = callback._ntOptions.SymLinks_DangerousLevel;\n  if (level < 20)\n  {\n    /*\n    We want to use additional check for links that can link to directory.\n      - linux: all symbolic links are files.\n      - windows: we can have file/directory symbolic link,\n        but file symbolic link works like directory link in windows.\n    So we use additional check for all relative links.\n\n    We don't allow decreasing of final level of link.\n    So if some another extracted file will use this link,\n    then number of real path parts (after link redirection) cannot be\n    smaller than number of requested path parts from archive records.\n    \n    here we check only (link.LinkPath) without (_item.PathParts).\n    */\n    CLinkLevelsInfo li;\n    li.Parse(link.LinkPath, link.Is_WSL());\n    bool isDang;\n    UString relativePathPrefix;\n    if (li.IsAbsolute // unexpected\n        || li.ParentDirDots_after_NonParent\n        || (level <= 5 && link.isRelative && li.FinalLevel < 1) // final level lower\n        || (level <= 5 && link.isRelative && li.LowLevel < 0)   // negative temporary levels\n       )\n      isDang = true;\n    else // if (!isDang)\n    {\n      UString path;\n      if (link.isRelative)\n      {\n        // item_PathParts : parts that will be created in output folder.\n        // we want to get directory prefix of link item.\n        // so we remove file name (last non-empty part) from PathParts:\n        UStringVector v = postLink.item_PathParts;\n        while (!v.IsEmpty())\n        {\n          const unsigned len = v.Back().Len();\n          v.DeleteBack();\n          if (len)\n            break;\n        }\n        path = MakePathFromParts(v);\n        NName::NormalizeDirPathPrefix(path);\n        relativePathPrefix = path;\n      }\n      path += link.LinkPath;\n      /*\n      path is calculated virtual target path of link\n      path is relative to root folder of extracted items\n      if (!link.isRelative), then (path == link.LinkPath)\n      */\n      isDang = false;\n      if (!IsSafePath(path, link.Is_WSL()))\n        isDang = true;\n    }\n    const char *message = NULL;\n    if (isDang)\n      message = \"Dangerous link path was ignored\";\n    else if (level <= k_DangLevel_MAX_for_Link_over_Link\n        && !CheckLinkPath_in_FS(callback._dirPathPrefix_Full,\n            postLink, relativePathPrefix))\n      message = \"Dangerous link via another link was ignored\";\n    if (message)\n       return callback.SendMessageError2(0, // errorCode\n            message, us2fs(postLink.item_Path), us2fs(link.LinkPath));\n  }\n\n  FString target; // target path that will be stored to link field\n  if (link.Is_HardLink() /* || link.IsCopyLink */ || !link.isRelative)\n  {\n    // isRelative == false\n    // all hard links and absolute symbolic links\n    // relatPath == link.LinkPath\n    // we get absolute link path for target:\n    if (!NName::GetFullPath(callback._dirPathPrefix_Full, us2fs(link.LinkPath), target))\n      return callback.SendMessageError(\"Incorrect link path\", us2fs(link.LinkPath));\n    // (target) is (_dirPathPrefix_Full + relatPath)\n  }\n  else\n  {\n    // link.isRelative == true\n    // relative symbolic links only\n    target = us2fs(link.LinkPath);\n  }\n  if (target.IsEmpty())\n    return callback.SendMessageError(\"Empty link\", fullProcessedPath_from);\n\n  if (link.Is_HardLink() /* || link.IsCopyLink */)\n  {\n    // if (link.isHardLink)\n    {\n      RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty\n      {\n        // RINOK(SendMessageError_with_LastError(k_Cant_DeleteTempLinkFile, fullProcessedPath_from))\n      }\n      return callback.CreateHardLink2(fullProcessedPath_from, target, linkWasSet);\n      /*\n      RINOK(PrepareOperation(NArchive::NExtract::NAskMode::kExtract))\n      _op_WasReported = true;\n      RINOK(SetOperationResult(NArchive::NExtract::NOperationResult::kOK))\n      linkWasSet = true;\n      return S_OK;\n      */\n    }\n    /*\n    // IsCopyLink\n    {\n      NFind::CFileInfo fi;\n      if (!fi.Find(target))\n      {\n        RINOK(SendMessageError2(\"Cannot find the file for copying\", target, fullProcessedPath));\n      }\n      else\n      {\n        if (_curSize_Defined && _curSize == fi.Size)\n          _copyFile_Path = target;\n        else\n        {\n          RINOK(SendMessageError2(\"File size collision for file copying\", target, fullProcessedPath));\n        }\n        // RINOK(MyCopyFile(target, fullProcessedPath));\n      }\n    }\n    */\n  }\n\n  // is Symbolic link\n\n  /*\n  if (_item.IsDir && !isRelative)\n  {\n    // Windows before Vista doesn't support symbolic links.\n    // we could convert such symbolic links to Junction Points\n    // isJunction = true;\n  }\n  */\n\n#ifdef _WIN32\n  const bool isDir = (postLink.item_IsDir || link.LinkType == k_LinkType_Junction);\n#endif\n\n \n#ifdef _WIN32\n  CByteBuffer data;\n  // printf(\"\\nFillLinkData(): %s\\n\", GetOemString(target).Ptr());\n  if (link.Is_WSL())\n  {\n    Convert_WinPath_to_WslLinuxPath(target, !link.isRelative);\n    FillLinkData_WslLink(data, fs2us(target));\n  }\n  else\n    FillLinkData_WinLink(data, fs2us(target), link.LinkType != k_LinkType_Junction);\n  if (data.Size() == 0)\n    return callback.SendMessageError(\"Cannot fill link data\", us2fs(postLink.item_Path));\n  /*\n  if (NtReparse_Size != data.Size() || memcmp(NtReparse_Data, data, data.Size()) != 0)\n    SendMessageError(\"reconstructed Reparse is different\", fs2us(target));\n  */\n  {\n    // we check that reparse data is correct, but we ignore attr.MinorError.\n    CReparseAttr attr;\n    if (!attr.Parse(data, data.Size()))\n      return callback.SendMessageError(\"Internal error for symbolic link file\", us2fs(postLink.item_Path));\n  }\n#endif\n\n  RINOK(callback.DeleteLinkFileAlways_or_RemoveEmptyDir(fullProcessedPath_from, true)) // checkThatFileIsEmpty\n#ifdef _WIN32\n  if (!NFile::NIO::SetReparseData(fullProcessedPath_from, isDir, data, (DWORD)data.Size()))\n#else // ! _WIN32\n  if (!NFile::NIO::SetSymLink(fullProcessedPath_from, target))\n#endif // ! _WIN32\n  {\n    return callback.SendMessageError_with_LastError(kCantCreateSymLink, fullProcessedPath_from);\n  }\n  linkWasSet = true;\n  return S_OK;\n}\n\n\n\nbool CLinkInfo::Parse_from_WindowsReparseData(const Byte *data, size_t dataSize)\n{\n  CReparseAttr reparse;\n  if (!reparse.Parse(data, dataSize))\n    return false;\n  // const AString s = GetAnsiString(LinkPath);\n  // printf(\"\\nlinkPath: %s\\n\", s.Ptr());\n  LinkPath = reparse.GetPath();\n  if (reparse.IsSymLink_WSL())\n  {\n    LinkType = k_LinkType_WSL;\n    isRelative = reparse.IsRelative_WSL(); // detected from LinkPath[0]\n    // LinkPath is original raw name converted to UString from AString\n    // Linux separator '/' is expected here.\n    REPLACE_SLASHES_from_Linux_to_Sys(LinkPath)\n  }\n  else\n  {\n    LinkType = reparse.IsMountPoint() ? k_LinkType_Junction : k_LinkType_PureSymLink;\n    isRelative = reparse.IsRelative_Win(); // detected by (Flags == Z7_WIN_SYMLINK_FLAG_RELATIVE)\n    isWindowsPath = true;\n    // LinkPath is original windows link path from raparse data with \\??\\ prefix removed.\n    // windows '\\\\' separator is expected here.\n    // linux '/' separator is not expected here.\n    // we translate both types of separators to system separator.\n    LinkPath.Replace(\n#if WCHAR_PATH_SEPARATOR == L'\\\\'\n        L'/'\n#else\n        L'\\\\'\n#endif\n        , WCHAR_PATH_SEPARATOR);\n  }\n  // (LinkPath) uses system path separator.\n  // windows: (LinkPath) doesn't contain linux separator (slash).\n  return true;\n}\n\n\nbool CLinkInfo::Parse_from_LinuxData(const Byte *data, size_t dataSize)\n{\n  // Clear(); // *this object was cleared by constructor already.\n  LinkType = k_LinkType_PureSymLink;\n  AString utf;\n  if (dataSize >= k_LinkDataSize_LIMIT)\n    return false;\n  utf.SetFrom_CalcLen((const char *)data, (unsigned)dataSize);\n  UString u;\n  if (!ConvertUTF8ToUnicode(utf, u))\n    return false;\n  if (u.IsEmpty())\n    return false;\n  const wchar_t c = u[0];\n  isRelative = (c != L'/');\n  // linux path separator is expected\n  REPLACE_SLASHES_from_Linux_to_Sys(u)\n  LinkPath = u;\n  // (LinkPath) uses system path separator.\n  // windows: (LinkPath) doesn't contain linux separator (slash).\n  return true;\n}\n    \n\n// in/out:          (LinkPath) uses system path separator\n// in/out: windows: (LinkPath) doesn't contain linux separator (slash).\n// out: (LinkPath) is relative path, and LinkPath[0] is not path separator\n// out: isRelative changed to false, if any prefix was removed.\n// note: absolute windows links \"c:\\\" to root will be reduced to empty string:\nvoid CLinkInfo::Remove_AbsPathPrefixes()\n{\n  while (!LinkPath.IsEmpty())\n  {\n    unsigned n = 0;\n    if (!Is_WSL())\n    {\n      n =\n#ifndef _WIN32\n      isWindowsPath ?\n        NName::GetRootPrefixSize_WINDOWS(LinkPath) :\n#endif\n        NName::GetRootPrefixSize(LinkPath);\n/*\n      // \"c:path\" will be ignored later as \"Dangerous absolute path\"\n      // so check is not required\n      if (n == 0\n#ifndef _WIN32\n          && isWindowsPath\n#endif\n          && NName::IsDrivePath2(LinkPath))\n        n = 2;\n*/\n    }\n    if (n == 0)\n    {\n      if (!IS_PATH_SEPAR(LinkPath[0]))\n        break;\n      n = 1;\n    }\n    isRelative = false; // (LinkPath) will be treated as relative to root folder of archive\n    LinkPath.DeleteFrontal(n);\n  }\n}\n\n\n/*\n  it removes redundant separators, if there are double separators,\n  but it keeps double separators at start of string //name/.\n  in/out:    system path separator is used\n    windows: slash character (linux separator) is not treated as separator\n    windows: (path) doesn't contain linux separator (slash).\n*/\nstatic void RemoveRedundantPathSeparators(UString &path)\n{\n  wchar_t *dest = path.GetBuf();\n  const wchar_t * const start = dest;\n  const wchar_t *src = dest;\n  for (;;)\n  {\n    wchar_t c = *src++;\n    if (c == 0)\n      break;\n    // if (IS_PATH_SEPAR(c)) // for Windows: we can change (/) to (\\).\n    if (c == WCHAR_PATH_SEPARATOR)\n    {\n      if (dest - start >= 2 && dest[-1] == WCHAR_PATH_SEPARATOR)\n        continue;\n      // c = WCHAR_PATH_SEPARATOR; // for Windows: we can change (/) to (\\).\n    }\n    *dest++ = c;\n  }\n  *dest = 0;\n  path.ReleaseBuf_SetLen((unsigned)(dest - path.Ptr()));\n}\n\n\n// in/out: (LinkPath) uses system path separator\n// in/out: windows: (LinkPath) doesn't contain linux separator (slash).\n// out: (LinkPath) is relative path, and LinkPath[0] is not path separator\nvoid CLinkInfo::Normalize_to_RelativeSafe(UStringVector &removePathParts)\n{\n  // We WILL NOT WRITE original absolute link path from archive to filesystem.\n  // So here we remove all root prefixes from (LinkPath).\n  // If we see any absolute root prefix, then we suppose that this prefix is virtual prefix\n  // that shows that link is relative to root folder of archive\n  RemoveRedundantPathSeparators(LinkPath);\n  // LinkPath = \"\\\\\\\\?\\\\r:test\\\\test2\"; // for debug\n  Remove_AbsPathPrefixes();\n  // (LinkPath) now is relative:\n  //  if (isRelative == false), then (LinkPath) is relative to root folder of archive\n  //  if (isRelative == true ), then (LinkPath) is relative to current item\n  if (LinkPath.IsEmpty() || isRelative || removePathParts.Size() == 0)\n    return;\n\n  // if LinkPath is prefixed by _removePathParts, we remove these paths\n  UStringVector pathParts;\n  SplitPathToParts(LinkPath, pathParts);\n  bool badPrefix = false;\n  {\n    FOR_VECTOR (i, removePathParts)\n    {\n      if (i >= pathParts.Size()\n        || CompareFileNames(removePathParts[i], pathParts[i]) != 0)\n      {\n        badPrefix = true;\n        break;\n      }\n    }\n  }\n  if (!badPrefix)\n    pathParts.DeleteFrontal(removePathParts.Size());\n  LinkPath = MakePathFromParts(pathParts);\n  Remove_AbsPathPrefixes();\n}\n\n#endif // SUPPORT_LINKS\n\n\nHRESULT CArchiveExtractCallback::CloseReparseAndFile()\n{\n  HRESULT res = S_OK;\n\n#ifdef SUPPORT_LINKS\n\n  size_t reparseSize = 0;\n  bool repraseMode = false;\n  bool needSetReparse = false;\n  CLinkInfo link;\n  \n  if (_bufPtrSeqOutStream)\n  {\n    repraseMode = true;\n    reparseSize = _bufPtrSeqOutStream_Spec->GetPos();\n    if (_curSize_Defined && reparseSize == _outMemBuf.Size())\n    {\n      /*\n      CReparseAttr reparse;\n      DWORD errorCode = 0;\n      needSetReparse = reparse.Parse(_outMemBuf, reparseSize, errorCode);\n      if (needSetReparse)\n      {\n        UString LinkPath = reparse.GetPath();\n        #ifndef _WIN32\n        LinkPath.Replace(L'\\\\', WCHAR_PATH_SEPARATOR);\n        #endif\n      }\n      */\n      needSetReparse = _is_SymLink_in_Data_Linux ?\n          link.Parse_from_LinuxData(_outMemBuf, reparseSize) :\n          link.Parse_from_WindowsReparseData(_outMemBuf, reparseSize);\n      if (!needSetReparse)\n        res = SendMessageError_with_LastError(\"Incorrect reparse stream\", us2fs(_item.Path));\n      // (link.LinkPath) uses system path separator.\n      // windows: (link.LinkPath) doesn't contain linux separator (slash).\n    }\n    else\n    {\n      res = SendMessageError_with_LastError(\"Unknown reparse stream\", us2fs(_item.Path));\n    }\n    if (!needSetReparse && _outFileStream)\n    {\n      const HRESULT res2 = WriteStream(_outFileStream, _outMemBuf, reparseSize);\n      if (res == S_OK)\n        res = res2;\n    }\n    _bufPtrSeqOutStream.Release();\n  }\n\n#endif // SUPPORT_LINKS\n\n  const HRESULT res2 = CloseFile();\n  if (res == S_OK)\n    res = res2;\n  RINOK(res)\n\n#ifdef SUPPORT_LINKS\n  if (repraseMode)\n  {\n    _curSize = reparseSize;\n    _curSize_Defined = true;\n    if (needSetReparse)\n    {\n      // empty file was created so we must delete it.\n      // in Linux   : we must delete empty file before symbolic link creation\n      // in Windows : we can create symbolic link even without file deleting\n      if (!DeleteFileAlways(_diskFilePath))\n      {\n        RINOK(SendMessageError_with_LastError(\"can't delete file\", _diskFilePath))\n      }\n      {\n        bool linkWasSet = false;\n        // link.LinkPath = \"r:\\\\1\\\\2\"; // for debug\n        // link.isJunction = true; // for debug\n        link.Normalize_to_RelativeSafe(_removePathParts);\n        RINOK(SetLink(_diskFilePath, link, linkWasSet))\n/*\n        // we don't set attributes for placeholder.\n        if (linkWasSet)\n          _isSymLinkCreated = true; // link.IsSymLink();\n        else\n*/\n          _needSetAttrib = false;\n      }\n    }\n  }\n#endif // SUPPORT_LINKS\n  return res;\n}\n\n\nstatic void SetAttrib_Base(const FString &path, const CProcessedFileInfo &fi,\n    const CArchiveExtractCallback &callback)\n{\n#ifndef _WIN32\n  if (fi.Owner.Id_Defined &&\n      fi.Group.Id_Defined)\n  {\n    if (my_chown(path, fi.Owner.Id, fi.Group.Id) != 0)\n      callback.SendMessageError_with_LastError(\"Cannot set owner\", path);\n  }\n#endif\n\n  if (fi.Attrib_Defined)\n  {\n    // const AString s = GetAnsiString(_diskFilePath);\n    // printf(\"\\nSetFileAttrib_PosixHighDetect: %s: hex:%x\\n\", s.Ptr(), _fi.Attrib);\n    if (!SetFileAttrib_PosixHighDetect(path, fi.Attrib))\n    {\n      // do we need error message here in Windows and in posix?\n      callback.SendMessageError_with_LastError(\"Cannot set file attribute\", path);\n    }\n  }\n}\n\nvoid CArchiveExtractCallback::SetAttrib() const\n{\n#ifndef _WIN32\n  // Linux now doesn't support permissions for symlinks\n  if (_isSymLinkCreated)\n    return;\n#endif\n\n  if (_itemFailure\n      || _diskFilePath.IsEmpty()\n      || _stdOutMode\n      || !_extractMode)\n    return;\n\n  SetAttrib_Base(_diskFilePath, _fi, *this);\n}\n\n\n#ifdef Z7_USE_SECURITY_CODE\nHRESULT CArchiveExtractCallback::SetSecurityInfo(UInt32 indexInArc, const FString &path) const\n{\n  if (!_stdOutMode && _extractMode && _ntOptions.NtSecurity.Val && _arc->GetRawProps)\n  {\n    const void *data;\n    UInt32 dataSize;\n    UInt32 propType;\n    _arc->GetRawProps->GetRawProp(indexInArc, kpidNtSecure, &data, &dataSize, &propType);\n    if (dataSize != 0)\n    {\n      if (propType != NPropDataType::kRaw)\n        return E_FAIL;\n      if (CheckNtSecure((const Byte *)data, dataSize))\n      {\n        SECURITY_INFORMATION securInfo = DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION;\n        if (_saclEnabled)\n          securInfo |= SACL_SECURITY_INFORMATION;\n        // if (!\n        ::SetFileSecurityW(fs2us(path), securInfo, (PSECURITY_DESCRIPTOR)(void *)(const Byte *)(data));\n        {\n          // RINOK(SendMessageError_with_LastError(\"SetFileSecurity FAILS\", path))\n        }\n      }\n    }\n  }\n  return S_OK;\n}\n#endif // Z7_USE_SECURITY_CODE\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::SetOperationResult(Int32 opRes))\n{\n  COM_TRY_BEGIN\n\n  // printf(\"\\nCArchiveExtractCallback::SetOperationResult: %d %s\\n\", opRes, GetAnsiString(_diskFilePath));\n\n  #ifndef Z7_SFX\n  if (ExtractToStreamCallback)\n  {\n    GetUnpackSize();\n    return ExtractToStreamCallback->SetOperationResult8(opRes, BoolToInt(_encrypted), _curSize);\n  }\n  #endif\n\n  #ifndef Z7_SFX\n\n  if (_hashStreamWasUsed)\n  {\n    _hashStreamSpec->_hash->Final(_item.IsDir,\n        #ifdef SUPPORT_ALT_STREAMS\n          _item.IsAltStream\n        #else\n          false\n        #endif\n        , _item.Path);\n    _curSize = _hashStreamSpec->GetSize();\n    _curSize_Defined = true;\n    _hashStreamSpec->ReleaseStream();\n    _hashStreamWasUsed = false;\n  }\n\n  #endif // Z7_SFX\n\n  RINOK(CloseReparseAndFile())\n  \n#ifdef Z7_USE_SECURITY_CODE\n  RINOK(SetSecurityInfo(_index, _diskFilePath))\n#endif\n\n  if (!_curSize_Defined)\n    GetUnpackSize();\n  \n  if (_curSize_Defined)\n  {\n    #ifdef SUPPORT_ALT_STREAMS\n    if (_item.IsAltStream)\n      AltStreams_UnpackSize += _curSize;\n    else\n    #endif\n      UnpackSize += _curSize;\n  }\n    \n  if (_item.IsDir)\n    NumFolders++;\n  #ifdef SUPPORT_ALT_STREAMS\n  else if (_item.IsAltStream)\n    NumAltStreams++;\n  #endif\n  else\n    NumFiles++;\n\n  if (_needSetAttrib)\n    SetAttrib();\n  \n  RINOK(_extractCallback2->SetOperationResult(opRes, BoolToInt(_encrypted)))\n  \n  return S_OK;\n  \n  COM_TRY_END\n}\n\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::ReportExtractResult(UInt32 indexType, UInt32 index, Int32 opRes))\n{\n  if (_folderArchiveExtractCallback2)\n  {\n    bool isEncrypted = false;\n    UString s;\n    \n    if (indexType == NArchive::NEventIndexType::kInArcIndex && index != (UInt32)(Int32)-1)\n    {\n      CReadArcItem item;\n      RINOK(_arc->GetItem(index, item))\n      s = item.Path;\n      RINOK(Archive_GetItemBoolProp(_arc->Archive, index, kpidEncrypted, isEncrypted))\n    }\n    else\n    {\n      s = '#';\n      s.Add_UInt32(index);\n      // if (indexType == NArchive::NEventIndexType::kBlockIndex) {}\n    }\n    \n    return _folderArchiveExtractCallback2->ReportExtractResult(opRes, isEncrypted, s);\n  }\n\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password))\n{\n  COM_TRY_BEGIN\n  if (!_cryptoGetTextPassword)\n  {\n    RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,\n        &_cryptoGetTextPassword))\n  }\n  return _cryptoGetTextPassword->CryptoGetTextPassword(password);\n  COM_TRY_END\n}\n\n\n#ifndef Z7_SFX\n\n// ---------- HASH functions ----------\n\nFString CArchiveExtractCallback::Hash_GetFullFilePath()\n{\n  // this function changes _item.PathParts.\n  CorrectPathParts();\n  const UStringVector &pathParts = _item.PathParts;\n  const UString processedPath (MakePathFromParts(pathParts));\n  FString fullProcessedPath (us2fs(processedPath));\n  if (_pathMode != NExtract::NPathMode::kAbsPaths\n      || !NName::IsAbsolutePath(processedPath))\n  {\n    fullProcessedPath = MakePath_from_2_Parts(\n        DirPathPrefix_for_HashFiles,\n        // _dirPathPrefix,\n        fullProcessedPath);\n  }\n  return fullProcessedPath;\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::GetDiskProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  if (propID == kpidSize)\n  {\n    RINOK(GetItem(index))\n    const FString fullProcessedPath = Hash_GetFullFilePath();\n    NFile::NFind::CFileInfo fi;\n    if (fi.Find_FollowLink(fullProcessedPath))\n      if (!fi.IsDir())\n        prop = (UInt64)fi.Size;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::GetStream2(UInt32 index, ISequentialInStream **inStream, UInt32 mode))\n{\n  COM_TRY_BEGIN\n  *inStream = NULL;\n  // if (index != _index) return E_FAIL;\n  if (mode != NUpdateNotifyOp::kHashRead)\n    return E_FAIL;\n\n  RINOK(GetItem(index))\n  const FString fullProcessedPath = Hash_GetFullFilePath();\n\n  CInFileStream *inStreamSpec = new CInFileStream;\n  CMyComPtr<ISequentialInStream> inStreamRef = inStreamSpec;\n  inStreamSpec->Set_PreserveATime(_ntOptions.PreserveATime);\n  if (!inStreamSpec->OpenShared(fullProcessedPath, _ntOptions.OpenShareForWrite))\n  {\n    RINOK(SendMessageError_with_LastError(kCantOpenInFile, fullProcessedPath))\n    return S_OK;\n  }\n  *inStream = inStreamRef.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::ReportOperation(\n    UInt32 /* indexType */, UInt32 /* index */, UInt32 /* op */))\n{\n  // COM_TRY_BEGIN\n  return S_OK;\n  // COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CArchiveExtractCallback::RequestMemoryUse(\n    UInt32 flags, UInt32 indexType, UInt32 index, const wchar_t *path,\n    UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))\n{\n  if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)\n  {\n    const UInt64 memLimit = _ntOptions.MemLimit;\n    if (memLimit != (UInt64)(Int64)-1)\n    {\n      // we overwrite allowedSize\n      *allowedSize = memLimit;\n      if (requiredSize <= memLimit)\n      {\n        *answerFlags = NRequestMemoryAnswerFlags::k_Allow;\n        return S_OK;\n      }\n      *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded;\n      if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected)\n        *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc;\n      flags |= NRequestMemoryUseFlags::k_SLimit_Exceeded\n            |  NRequestMemoryUseFlags::k_AllowedSize_WasForced;\n    }\n  }\n\n  if (!_requestMemoryUseCallback)\n  {\n    _extractCallback2.QueryInterface(IID_IArchiveRequestMemoryUseCallback,\n        &_requestMemoryUseCallback);\n    if (!_requestMemoryUseCallback)\n    {\n      // keep default (answerFlags) from caller or (answerFlags) that was set in this function\n      return S_OK;\n    }\n  }\n\n#if 0\n  if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)\n  if (requiredSize <= *allowedSize)\n  {\n    // it's expected, that *answerFlags was set to NRequestMemoryAnswerFlags::k_Allow already,\n    // because it's default answer for (requiredSize <= *allowedSize) case.\n    *answerFlags = NRequestMemoryAnswerFlags::k_Allow; // optional code\n  }\n  else\n  {\n    // we clear *answerFlags, because we want to disable dafault \"Allow\", if it's set.\n    // *answerFlags = 0;\n  /*\n      NRequestMemoryAnswerFlags::k_SkipArc |\n      NRequestMemoryAnswerFlags::k_Limit_Exceeded;\n  */\n  }\n#endif\n  \n  UString s;\n  if (!path\n      && indexType == NArchive::NEventIndexType::kInArcIndex\n      && index != (UInt32)(Int32)-1\n      && _arc)\n  {\n    RINOK(_arc->GetItem_Path(index, s))\n    path = s.Ptr();\n  }\n  \n  return _requestMemoryUseCallback->RequestMemoryUse(\n      flags, indexType, index, path,\n      requiredSize, allowedSize, answerFlags);\n}\n\n#endif // Z7_SFX\n\n\n\n// ------------ After Extracting functions ------------\n\nvoid CDirPathSortPair::SetNumSlashes(const FChar *s)\n{\n  for (unsigned numSlashes = 0;;)\n  {\n    FChar c = *s++;\n    if (c == 0)\n    {\n      Len = numSlashes;\n      return;\n    }\n    if (IS_PATH_SEPAR(c))\n      numSlashes++;\n  }\n}\n\n\nbool CFiTimesCAM::SetDirTime_to_FS(CFSTR path) const\n{\n  // it's same function for dir and for file\n  return NDir::SetDirTime(path,\n      CTime_Defined ? &CTime : NULL,\n      ATime_Defined ? &ATime : NULL,\n      MTime_Defined ? &MTime : NULL);\n}\n\n\n#ifdef SUPPORT_LINKS\n\nbool CFiTimesCAM::SetLinkFileTime_to_FS(CFSTR path) const\n{\n  // it's same function for dir and for file\n  return NDir::SetLinkFileTime(path,\n      CTime_Defined ? &CTime : NULL,\n      ATime_Defined ? &ATime : NULL,\n      MTime_Defined ? &MTime : NULL);\n}\n\nHRESULT CArchiveExtractCallback::SetPostLinks() const\n{\n  FOR_VECTOR (i, _postLinks)\n  {\n    const CPostLink &link = _postLinks[i];\n    bool linkWasSet = false;\n    RINOK(SetLink2(*this, link, linkWasSet))\n    if (linkWasSet)\n    {\n#ifdef _WIN32\n      //  Linux now doesn't support permissions for symlinks\n      SetAttrib_Base(link.fullProcessedPath_from, link.item_FileInfo, *this);\n#endif\n\n      CFiTimesCAM pt;\n      GetFiTimesCAM(link.item_FileInfo, pt, *_arc);\n      if (pt.IsSomeTimeDefined())\n        pt.SetLinkFileTime_to_FS(link.fullProcessedPath_from);\n\n#ifdef Z7_USE_SECURITY_CODE\n      // we set security information after timestamps setting\n      RINOK(SetSecurityInfo(link.Index_in_Arc, link.fullProcessedPath_from))\n#endif\n    }\n  }\n  return S_OK;\n}\n\n#endif\n\n\nHRESULT CArchiveExtractCallback::SetDirsTimes()\n{\n  if (!_arc)\n    return S_OK;\n\n  CRecordVector<CDirPathSortPair> pairs;\n  pairs.ClearAndSetSize(_extractedFolders.Size());\n  unsigned i;\n  \n  for (i = 0; i < _extractedFolders.Size(); i++)\n  {\n    CDirPathSortPair &pair = pairs[i];\n    pair.Index = i;\n    pair.SetNumSlashes(_extractedFolders[i].Path);\n  }\n  \n  pairs.Sort2();\n  \n  HRESULT res = S_OK;\n\n  for (i = 0; i < pairs.Size(); i++)\n  {\n    const CDirPathTime &dpt = _extractedFolders[pairs[i].Index];\n    if (!dpt.SetDirTime_to_FS_2())\n    {\n      // result = E_FAIL;\n      // do we need error message here in Windows and in posix?\n      // SendMessageError_with_LastError(\"Cannot set directory time\", dpt.Path);\n    }\n  }\n\n  /*\n  #ifndef _WIN32\n  for (i = 0; i < _delayedSymLinks.Size(); i++)\n  {\n    const CDelayedSymLink &link = _delayedSymLinks[i];\n    if (!link.Create())\n    {\n      if (res == S_OK)\n        res = GetLastError_noZero_HRESULT();\n      // res = E_FAIL;\n      // do we need error message here in Windows and in posix?\n      SendMessageError_with_LastError(\"Cannot create Symbolic Link\", link._source);\n    }\n  }\n  #endif // _WIN32\n  */\n\n  ClearExtractedDirsInfo();\n  return res;\n}\n\n\nHRESULT CArchiveExtractCallback::CloseArc()\n{\n  // we call CloseReparseAndFile() here because we can have non-closed file in some cases?\n  HRESULT res = CloseReparseAndFile();\n#ifdef SUPPORT_LINKS\n  {\n    const HRESULT res2 = SetPostLinks();\n    if (res == S_OK)\n      res = res2;\n  }\n#endif\n  {\n    const HRESULT res2 = SetDirsTimes();\n    if (res == S_OK)\n      res = res2;\n  }\n  _arc = NULL;\n  return res;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ArchiveExtractCallback.h",
    "content": "﻿// ArchiveExtractCallback.h\n\n#ifndef ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H\n#define ZIP7_INC_ARCHIVE_EXTRACT_CALLBACK_H\n\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/MyLinux.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../IPassword.h\"\n\n#include \"../../Common/FileStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamObjects.h\"\n\n#include \"../../Archive/IArchive.h\"\n\n#include \"ExtractMode.h\"\n#include \"IFileExtractCallback.h\"\n#include \"OpenArchive.h\"\n\n#include \"HashCalc.h\"\n\n#ifndef Z7_SFX\n\nZ7_CLASS_IMP_NOQIB_1(\n  COutStreamWithHash\n  , ISequentialOutStream\n)\n  bool _calculate;\n  CMyComPtr<ISequentialOutStream> _stream;\n  UInt64 _size;\npublic:\n  IHashCalc *_hash;\n\n  void SetStream(ISequentialOutStream *stream) { _stream = stream; }\n  void ReleaseStream() { _stream.Release(); }\n  void Init(bool calculate = true)\n  {\n    InitCRC();\n    _size = 0;\n    _calculate = calculate;\n  }\n  void EnableCalc(bool calculate) { _calculate = calculate; }\n  void InitCRC() { _hash->InitForNewFile(); }\n  UInt64 GetSize() const { return _size; }\n};\n\n#endif\n\nstruct CExtractNtOptions\n{\n  CBoolPair NtSecurity;\n  CBoolPair SymLinks;\n  CBoolPair HardLinks;\n  CBoolPair AltStreams;\n  bool ReplaceColonForAltStream;\n  bool WriteToAltStreamIfColon;\n\n  bool ExtractOwner;\n\n  bool PreAllocateOutFile;\n\n  // used for hash arcs only, when we open external files\n  bool PreserveATime;\n  bool OpenShareForWrite;\n\n  unsigned SymLinks_DangerousLevel;\n\n  UInt64 MemLimit;\n\n  CExtractNtOptions():\n      ReplaceColonForAltStream(false),\n      WriteToAltStreamIfColon(false),\n      ExtractOwner(false),\n      PreserveATime(false),\n      OpenShareForWrite(false),\n      SymLinks_DangerousLevel(5),\n      MemLimit((UInt64)(Int64)-1)\n  {\n    SymLinks.Val = true;\n    HardLinks.Val = true;\n    AltStreams.Val = true;\n\n    PreAllocateOutFile =\n      #ifdef _WIN32\n        true;\n      #else\n        false;\n      #endif\n  }\n};\n\n\n#ifndef Z7_SFX\n#ifndef UNDER_CE\n#define SUPPORT_LINKS\n#endif\n#endif\n\n\n#ifdef SUPPORT_LINKS\n\nstruct CHardLinkNode\n{\n  UInt64 StreamId;\n  UInt64 INode;\n\n  int Compare(const CHardLinkNode &a) const;\n};\n\nclass CHardLinks\n{\npublic:\n  CRecordVector<CHardLinkNode> IDs;\n  CObjectVector<FString> Links;\n\n  void Clear()\n  {\n    IDs.Clear();\n    Links.Clear();\n  }\n\n  void PrepareLinks()\n  {\n    while (Links.Size() < IDs.Size())\n      Links.AddNew();\n  }\n};\n\n#endif\n\n#ifdef SUPPORT_ALT_STREAMS\n\nstruct CIndexToPathPair\n{\n  UInt32 Index;\n  FString Path;\n\n  CIndexToPathPair(UInt32 index): Index(index) {}\n  CIndexToPathPair(UInt32 index, const FString &path): Index(index), Path(path) {}\n\n  int Compare(const CIndexToPathPair &pair) const\n  {\n    return MyCompare(Index, pair.Index);\n  }\n};\n\n#endif\n\n\n\nstruct CFiTimesCAM\n{\n  CFiTime CTime;\n  CFiTime ATime;\n  CFiTime MTime;\n\n  bool CTime_Defined;\n  bool ATime_Defined;\n  bool MTime_Defined;\n\n  bool IsSomeTimeDefined() const\n  {\n    return\n      CTime_Defined |\n      ATime_Defined |\n      MTime_Defined;\n  }\n  bool SetDirTime_to_FS(CFSTR path) const;\n#ifdef SUPPORT_LINKS\n  bool SetLinkFileTime_to_FS(CFSTR path) const;\n#endif\n};\n\nstruct CDirPathTime: public CFiTimesCAM\n{\n  FString Path;\n  \n  bool SetDirTime_to_FS_2() const { return SetDirTime_to_FS(Path); }\n};\n\n\n#ifdef SUPPORT_LINKS\n\nenum ELinkType\n{\n  k_LinkType_HardLink,\n  k_LinkType_PureSymLink,\n  k_LinkType_Junction,\n  k_LinkType_WSL\n  // , k_LinkType_CopyLink;\n};\n\n\nstruct CLinkInfo\n{\n  ELinkType LinkType;\n  bool isRelative;\n    //  if (isRelative == false), then (LinkPath) is relative to root folder of archive\n    //  if (isRelative == true ), then (LinkPath) is relative to current item\n  bool isWindowsPath;\n  UString LinkPath;\n\n  bool Is_HardLink() const { return LinkType == k_LinkType_HardLink; }\n  bool Is_AnySymLink() const { return LinkType != k_LinkType_HardLink; }\n\n  bool Is_WSL() const { return LinkType == k_LinkType_WSL; }\n\n  CLinkInfo():\n    LinkType(k_LinkType_PureSymLink),\n    isRelative(false),\n    isWindowsPath(false)\n    {}\n\n  void Clear()\n  {\n    LinkType = k_LinkType_PureSymLink;\n    isRelative = false;\n    isWindowsPath = false;\n    LinkPath.Empty();\n  }\n\n  bool Parse_from_WindowsReparseData(const Byte *data, size_t dataSize);\n  bool Parse_from_LinuxData(const Byte *data, size_t dataSize);\n  void Normalize_to_RelativeSafe(UStringVector &removePathParts);\nprivate:\n  void Remove_AbsPathPrefixes();\n};\n\n#endif // SUPPORT_LINKS\n\n\n\nstruct CProcessedFileInfo\n{\n  CArcTime CTime;\n  CArcTime ATime;\n  CArcTime MTime;\n  UInt32 Attrib;\n  bool Attrib_Defined;\n  \n#ifndef _WIN32\n\nstruct COwnerInfo\n{\n  bool Id_Defined;\n  UInt32 Id;\n  AString Name;\n\n  void Clear()\n  {\n    Id_Defined = false;\n    Id = 0;\n    Name.Empty();\n  }\n};\n\n  COwnerInfo Owner;\n  COwnerInfo Group;\n#endif\n\n  void Clear()\n  {\n#ifndef _WIN32\n    Attrib_Defined = false;\n    Owner.Clear();\n#endif\n  }\n\n    bool IsReparse() const\n    {\n      return (Attrib_Defined && (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0);\n    }\n    \n    bool IsLinuxSymLink() const\n    {\n      return (Attrib_Defined && MY_LIN_S_ISLNK(Attrib >> 16));\n    }\n\n    void SetFromPosixAttrib(UInt32 a)\n    {\n      // here we set only part of combined attribute required by SetFileAttrib() call\n      #ifdef _WIN32\n      // Windows sets FILE_ATTRIBUTE_NORMAL, if we try to set 0 as attribute.\n      Attrib = MY_LIN_S_ISDIR(a) ?\n          FILE_ATTRIBUTE_DIRECTORY :\n          FILE_ATTRIBUTE_ARCHIVE;\n      if ((a & 0222) == 0) // (& S_IWUSR) in p7zip\n        Attrib |= FILE_ATTRIBUTE_READONLY;\n      // 22.00 : we need type bits for (MY_LIN_S_IFLNK) for IsLinuxSymLink()\n      a &= MY_LIN_S_IFMT;\n      if (a == MY_LIN_S_IFLNK)\n        Attrib |= (a << 16);\n      #else\n      Attrib = (a << 16) | FILE_ATTRIBUTE_UNIX_EXTENSION;\n      #endif\n      Attrib_Defined = true;\n    }\n};\n\n\n#ifdef SUPPORT_LINKS\n\nstruct CPostLink\n{\n  UInt32 Index_in_Arc;\n  bool item_IsDir;                // _item.IsDir\n  UString item_Path;              // _item.Path;\n  UStringVector item_PathParts;   // _item.PathParts;\n  CProcessedFileInfo item_FileInfo; // _fi\n  FString fullProcessedPath_from; // full file path in FS\n  CLinkInfo LinkInfo;\n};\n\n/*\nstruct CPostLinks\n{\n  void Clear()\n  {\n    Links.Clear();\n  }\n};\n*/\n\n#endif // SUPPORT_LINKS\n\n\n\nclass CArchiveExtractCallback Z7_final:\n  public IArchiveExtractCallback,\n  public IArchiveExtractCallbackMessage2,\n  public ICryptoGetTextPassword,\n  public ICompressProgressInfo,\n#ifndef Z7_SFX\n  public IArchiveUpdateCallbackFile,\n  public IArchiveGetDiskProperty,\n  public IArchiveRequestMemoryUseCallback,\n#endif\n  public CMyUnknownImp\n{\n  /* IArchiveExtractCallback, */\n  Z7_COM_QI_BEGIN2(IArchiveExtractCallbackMessage2)\n  Z7_COM_QI_ENTRY(ICryptoGetTextPassword)\n  Z7_COM_QI_ENTRY(ICompressProgressInfo)\n#ifndef Z7_SFX\n  Z7_COM_QI_ENTRY(IArchiveUpdateCallbackFile)\n  Z7_COM_QI_ENTRY(IArchiveGetDiskProperty)\n  Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)\n#endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(IProgress)\n  Z7_IFACE_COM7_IMP(IArchiveExtractCallback)\n  Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2)\n  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)\n  Z7_IFACE_COM7_IMP(ICompressProgressInfo)\n#ifndef Z7_SFX\n  Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile)\n  Z7_IFACE_COM7_IMP(IArchiveGetDiskProperty)\n  Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)\n#endif\n\n  // bool Write_CTime;\n  // bool Write_ATime;\n  // bool Write_MTime;\n  bool _stdOutMode;\n  bool _testMode;\n  bool _removePartsForAltStreams;\npublic:\n  bool Is_elimPrefix_Mode;\nprivate:\n\n  const CArc *_arc;\npublic:\n  CExtractNtOptions _ntOptions;\nprivate:\n  bool _encrypted;\n  bool _isSplit;\n  bool _curSize_Defined;\n  bool _fileLength_WasSet;\n\n  bool _isRenamed;\n  bool _extractMode;\n  bool _is_SymLink_in_Data_Linux; // false = WIN32, true = LINUX.\n      // _is_SymLink_in_Data_Linux is detected from Windows/Linux part of attributes of file.\n  bool _needSetAttrib;\n  bool _isSymLinkCreated;\n  bool _itemFailure;\n  bool _some_pathParts_wereRemoved;\n\n  bool _multiArchives;\n  bool _keepAndReplaceEmptyDirPrefixes; // replace them to \"_\";\n#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n  bool _saclEnabled;\n#endif\n\n  NExtract::NPathMode::EEnum _pathMode;\n  NExtract::NOverwriteMode::EEnum _overwriteMode;\n\n  CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;\n  const NWildcard::CCensorNode *_wildcardCensor; // we need wildcard for single pass mode (stdin)\n  // CMyComPtr<ICompressProgressInfo> _compressProgress;\n  // CMyComPtr<IArchiveExtractCallbackMessage2> _callbackMessage;\n  CMyComPtr<IFolderArchiveExtractCallback2> _folderArchiveExtractCallback2;\n  CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;\n\n  FString _dirPathPrefix;\npublic:\n  FString _dirPathPrefix_Full;\nprivate:\n\n  #ifndef Z7_SFX\n\n  CMyComPtr<IFolderExtractToStreamCallback> ExtractToStreamCallback;\n  CMyComPtr<IArchiveRequestMemoryUseCallback> _requestMemoryUseCallback;\n  \n  #endif\n\n  CReadArcItem _item;\n  FString _diskFilePath;\n\n  CProcessedFileInfo _fi;\n\n  UInt64 _position;\n  UInt64 _curSize;\n  UInt64 _fileLength_that_WasSet;\n  UInt32 _index;\n\n// #ifdef SUPPORT_ALT_STREAMS\n#if defined(_WIN32) && !defined(UNDER_CE)\n  DWORD _altStream_NeedRestore_AttribVal;\n  FString _altStream_NeedRestore_Attrib_for_parentFsPath;\n#endif\n// #endif\n\n  COutFileStream *_outFileStreamSpec;\n  CMyComPtr<ISequentialOutStream> _outFileStream;\n\n  CByteBuffer _outMemBuf;\n  CBufPtrSeqOutStream *_bufPtrSeqOutStream_Spec;\n  CMyComPtr<ISequentialOutStream> _bufPtrSeqOutStream;\n\n #ifndef Z7_SFX\n  COutStreamWithHash *_hashStreamSpec;\n  CMyComPtr<ISequentialOutStream> _hashStream;\n  bool _hashStreamWasUsed;\n  \n  bool _use_baseParentFolder_mode;\n  UInt32 _baseParentFolder;\n #endif\n\n  UStringVector _removePathParts;\n\n  UInt64 _packTotal;\n  UInt64 _progressTotal;\n  // bool _progressTotal_Defined;\n\n  CObjectVector<CDirPathTime> _extractedFolders;\n  \n  #ifndef _WIN32\n  // CObjectVector<NWindows::NFile::NDir::CDelayedSymLink> _delayedSymLinks;\n  #endif\n\n  void CreateComplexDirectory(\n      const UStringVector &dirPathParts, bool isFinal, FString &fullPath);\n  HRESULT GetTime(UInt32 index, PROPID propID, CArcTime &ft);\n  HRESULT GetUnpackSize();\n\n  FString Hash_GetFullFilePath();\n\n  void SetAttrib() const;\n\npublic:\n  HRESULT SendMessageError(const char *message, const FString &path) const;\n  HRESULT SendMessageError_with_Error(HRESULT errorCode, const char *message, const FString &path) const;\n  HRESULT SendMessageError_with_LastError(const char *message, const FString &path) const;\n  HRESULT SendMessageError2(HRESULT errorCode, const char *message, const FString &path1, const FString &path2) const;\n  HRESULT SendMessageError2_with_LastError(const char *message, const FString &path1, const FString &path2) const;\n\n#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n  NExtract::NZoneIdMode::EEnum ZoneMode;\n  CByteBuffer ZoneBuf;\n#endif\n\n  CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> LocalProgressSpec;\n\n  UInt64 NumFolders;\n  UInt64 NumFiles;\n  UInt64 NumAltStreams;\n  UInt64 UnpackSize;\n  UInt64 AltStreams_UnpackSize;\n\n  // **************** 7-Zip ZS Modification Start ****************\n  FString FirstExtractedPath;\n  // **************** 7-Zip ZS Modification End ****************\n  \n  FString DirPathPrefix_for_HashFiles;\n\n  // **************** NanaZip Modification End ****************\n  FString OutDir;\n  // **************** NanaZip Modification End ****************\n\n  CArchiveExtractCallback();\n\n  void InitForMulti(bool multiArchives,\n      NExtract::NPathMode::EEnum pathMode,\n      NExtract::NOverwriteMode::EEnum overwriteMode,\n      NExtract::NZoneIdMode::EEnum zoneMode,\n      bool keepAndReplaceEmptyDirPrefixes)\n  {\n    _multiArchives = multiArchives;\n    _pathMode = pathMode;\n    _overwriteMode = overwriteMode;\n#if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n     ZoneMode = zoneMode;\n#else\n     UNUSED_VAR(zoneMode)\n#endif\n    _keepAndReplaceEmptyDirPrefixes = keepAndReplaceEmptyDirPrefixes;\n    NumFolders = NumFiles = NumAltStreams = UnpackSize = AltStreams_UnpackSize = 0;\n  }\n\n  #ifndef Z7_SFX\n\n  void SetHashMethods(IHashCalc *hash)\n  {\n    if (!hash)\n      return;\n    _hashStreamSpec = new COutStreamWithHash;\n    _hashStream = _hashStreamSpec;\n    _hashStreamSpec->_hash = hash;\n  }\n\n  #endif\n\n  void InitBeforeNewArchive();\n\n  void Init(\n      const CExtractNtOptions &ntOptions,\n      const NWildcard::CCensorNode *wildcardCensor,\n      const CArc *arc,\n      IFolderArchiveExtractCallback *extractCallback2,\n      bool stdOutMode, bool testMode,\n      const FString &directoryPath,\n      const UStringVector &removePathParts, bool removePartsForAltStreams,\n      UInt64 packSize);\n\n\n#ifdef SUPPORT_LINKS\n\nprivate:\n  CHardLinks _hardLinks;\n  CObjectVector<CPostLink> _postLinks;\n  CLinkInfo _link;\n  // const void *NtReparse_Data;\n  // UInt32 NtReparse_Size;\n\n  // FString _copyFile_Path;\n  // HRESULT MyCopyFile(ISequentialOutStream *outStream);\n  HRESULT ReadLink();\n  HRESULT SetLink(\n      const FString &fullProcessedPath_from,\n      const CLinkInfo &linkInfo,\n      bool &linkWasSet);\n  HRESULT SetPostLinks() const;\n\npublic:\n  HRESULT CreateHardLink2(const FString &newFilePath,\n      const FString &existFilePath, bool &link_was_Created) const;\n  HRESULT DeleteLinkFileAlways_or_RemoveEmptyDir(const FString &path, bool checkThatFileIsEmpty) const;\n  HRESULT PrepareHardLinks(const CRecordVector<UInt32> *realIndices);  // NULL means all items\n#endif\n\nprivate:\n\n  #ifdef SUPPORT_ALT_STREAMS\n  CObjectVector<CIndexToPathPair> _renamedFiles;\n  #endif\n\n  // call it after Init()\n\npublic:\n  #ifndef Z7_SFX\n  void SetBaseParentFolderIndex(UInt32 indexInArc)\n  {\n    _baseParentFolder = indexInArc;\n    _use_baseParentFolder_mode = true;\n  }\n  #endif\n\n  HRESULT CloseArc();\n\nprivate:\n  void ClearExtractedDirsInfo()\n  {\n    _extractedFolders.Clear();\n    #ifndef _WIN32\n    // _delayedSymLinks.Clear();\n    #endif\n  }\n\n  HRESULT Read_fi_Props();\n  void CorrectPathParts();\n  void CreateFolders();\n  \n  HRESULT CheckExistFile(FString &fullProcessedPath, bool &needExit);\n  HRESULT GetExtractStream(CMyComPtr<ISequentialOutStream> &outStreamLoc, bool &needExit);\n  HRESULT GetItem(UInt32 index);\n\n  HRESULT CloseFile();\n  HRESULT CloseReparseAndFile();\n  HRESULT SetDirsTimes();\n  HRESULT SetSecurityInfo(UInt32 indexInArc, const FString &path) const;\n};\n\n\nstruct CArchiveExtractCallback_Closer\n{\n  CArchiveExtractCallback *_ref;\n  \n  CArchiveExtractCallback_Closer(CArchiveExtractCallback *ref): _ref(ref) {}\n  \n  HRESULT Close()\n  {\n    HRESULT res = S_OK;\n    if (_ref)\n    {\n      res = _ref->CloseArc();\n      _ref = NULL;\n    }\n    return res;\n  }\n  \n  ~CArchiveExtractCallback_Closer()\n  {\n    Close();\n  }\n};\n\n\nbool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);\n\nbool Is_ZoneId_StreamName(const wchar_t *s);\nvoid ReadZoneFile_Of_BaseFile(CFSTR fileName, CByteBuffer &buf);\nbool WriteZoneFile_To_BaseFile(CFSTR fileName, const CByteBuffer &buf);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp",
    "content": "﻿// ArchiveOpenCallback.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/System.h\"\n\n#include \"../../Common/StreamUtils.h\"\n\n#include \"ArchiveOpenCallback.h\"\n\n// #define DEBUG_VOLUMES\n\n#ifdef DEBUG_VOLUMES\n#include <stdio.h>\n#endif\n\n\n#ifdef DEBUG_VOLUMES\n  #define PRF(x) x\n#else\n  #define PRF(x)\n#endif\n\nusing namespace NWindows;\n\nHRESULT COpenCallbackImp::Init2(const FString &folderPrefix, const FString &fileName)\n{\n  Volumes.Init();\n  FileNames.Clear();\n  FileNames_WasUsed.Clear();\n  FileSizes.Clear();\n  _subArchiveMode = false;\n  // TotalSize = 0;\n  PasswordWasAsked = false;\n  _folderPrefix = folderPrefix;\n  if (!_fileInfo.Find_FollowLink(_folderPrefix + fileName))\n  {\n    // throw 20121118;\n    return GetLastError_noZero_HRESULT();\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(COpenCallbackImp::SetSubArchiveName(const wchar_t *name))\n{\n  _subArchiveMode = true;\n  _subArchiveName = name;\n  // TotalSize = 0;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes))\n{\n  COM_TRY_BEGIN\n  if (ReOpenCallback)\n    return ReOpenCallback->SetTotal(files, bytes);\n  if (!Callback)\n    return S_OK;\n  return Callback->Open_SetTotal(files, bytes);\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes))\n{\n  COM_TRY_BEGIN\n  if (ReOpenCallback)\n    return ReOpenCallback->SetCompleted(files, bytes);\n  if (!Callback)\n    return S_OK;\n  return Callback->Open_SetCompleted(files, bytes);\n  COM_TRY_END\n}\n\n \nZ7_COM7F_IMF(COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n  if (_subArchiveMode)\n    switch (propID)\n    {\n      case kpidName: prop = _subArchiveName; break;\n      // case kpidSize:  prop = _subArchiveSize; break; // we don't use it now\n      default: break;\n    }\n  else\n    switch (propID)\n    {\n      case kpidName:  prop = fs2us(_fileInfo.Name); break;\n      case kpidIsDir:  prop = _fileInfo.IsDir(); break;\n      case kpidSize:  prop = _fileInfo.Size; break;\n      case kpidAttrib:  prop = (UInt32)_fileInfo.GetWinAttrib(); break;\n      case kpidPosixAttrib:  prop = (UInt32)_fileInfo.GetPosixAttrib(); break;\n      case kpidCTime:  PropVariant_SetFrom_FiTime(prop, _fileInfo.CTime); break;\n      case kpidATime:  PropVariant_SetFrom_FiTime(prop, _fileInfo.ATime); break;\n      case kpidMTime:  PropVariant_SetFrom_FiTime(prop, _fileInfo.MTime); break;\n      default: break;\n    }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\n\n// ---------- CInFileStreamVol ----------\n\nZ7_class_final(CInFileStreamVol):\n    public IInStream\n  , public IStreamGetSize\n  , public CMyUnknownImp\n{\n  Z7_IFACES_IMP_UNK_3(\n    IInStream,\n    ISequentialInStream,\n    IStreamGetSize)\npublic:\n  unsigned FileIndex;\n  COpenCallbackImp *OpenCallbackImp;\n  CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;\n\n  HRESULT EnsureOpen()\n  {\n    return OpenCallbackImp->Volumes.EnsureOpen(FileIndex);\n  }\n\n  ~CInFileStreamVol()\n  {\n    if (OpenCallbackRef)\n      OpenCallbackImp->AtCloseFile(FileIndex);\n  }\n};\n\n\nvoid CMultiStreams::InsertToList(unsigned index)\n{\n  {\n    CSubStream &s = Streams[index];\n    s.Next = Head;\n    s.Prev = -1;\n  }\n  if (Head != -1)\n    Streams[(unsigned)Head].Prev = (int)index;\n  else\n  {\n    // if (Tail != -1) throw 1;\n    Tail = (int)index;\n  }\n  Head = (int)index;\n  NumListItems++;\n}\n\n// s must bee in List\nvoid CMultiStreams::RemoveFromList(CSubStream &s)\n{\n  if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev;\n  if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next;\n  s.Next = -1; // optional\n  s.Prev = -1; // optional\n  NumListItems--;\n}\n\nvoid CMultiStreams::CloseFile(unsigned index)\n{\n  CSubStream &s = Streams[index];\n  if (s.Stream)\n  {\n    s.Stream.Release();\n    RemoveFromList(s);\n    // s.InFile->Close();\n    // s.IsOpen = false;\n   #ifdef DEBUG_VOLUMES\n    static int numClosing = 0;\n    numClosing++;\n    printf(\"\\nCloseFile %u, total_closes = %u, num_open_files = %u\\n\", index, numClosing, NumListItems);\n   #endif\n  }\n}\n\nvoid CMultiStreams::Init()\n{\n  Head = -1;\n  Tail = -1;\n  NumListItems = 0;\n  Streams.Clear();\n}\n\nCMultiStreams::CMultiStreams():\n    Head(-1),\n    Tail(-1),\n    NumListItems(0)\n{\n  NumOpenFiles_AllowedMax = NSystem::Get_File_OPEN_MAX_Reduced_for_3_tasks();\n  PRF(printf(\"\\nNumOpenFiles_Limit = %u\\n\", NumOpenFiles_AllowedMax));\n}\n\n\nHRESULT CMultiStreams::PrepareToOpenNew()\n{\n  if (NumListItems < NumOpenFiles_AllowedMax)\n    return S_OK;\n  if (Tail == -1)\n    return E_FAIL;\n  CMultiStreams::CSubStream &tailStream = Streams[(unsigned)Tail];\n  RINOK(InStream_GetPos(tailStream.Stream, tailStream.LocalPos))\n  CloseFile((unsigned)Tail);\n  return S_OK;\n}\n\n\nHRESULT CMultiStreams::EnsureOpen(unsigned index)\n{\n  CMultiStreams::CSubStream &s = Streams[index];\n  if (s.Stream)\n  {\n    if ((int)index != Head)\n    {\n      RemoveFromList(s);\n      InsertToList(index);\n    }\n  }\n  else\n  {\n    RINOK(PrepareToOpenNew())\n    {\n      CInFileStream *inFile = new CInFileStream;\n      CMyComPtr<IInStream> inStreamTemp = inFile;\n      if (!inFile->Open(s.Path))\n        return GetLastError_noZero_HRESULT();\n      s.FileSpec = inFile;\n      s.Stream = s.FileSpec;\n      InsertToList(index);\n    }\n    // s.IsOpen = true;\n    if (s.LocalPos != 0)\n    {\n      RINOK(s.Stream->Seek((Int64)s.LocalPos, STREAM_SEEK_SET, &s.LocalPos))\n    }\n   #ifdef DEBUG_VOLUMES\n    static int numOpens = 0;\n    numOpens++;\n    printf(\"\\n-- %u, ReOpen, total_reopens = %u, num_open_files = %u\\n\", index, numOpens, NumListItems);\n   #endif\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CInFileStreamVol::Read(void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  RINOK(EnsureOpen())\n  CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];\n  PRF(printf(\"\\n== %u, Read =%u \\n\", FileIndex, size));\n  return s.Stream->Read(data, size, processedSize);\n}\n\nZ7_COM7F_IMF(CInFileStreamVol::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))\n{\n  // if (seekOrigin >= 3) return STG_E_INVALIDFUNCTION;\n  RINOK(EnsureOpen())\n  CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];\n  PRF(printf(\"\\n-- %u, Seek seekOrigin=%u Seek =%u\\n\", FileIndex, seekOrigin, (unsigned)offset));\n  return s.Stream->Seek(offset, seekOrigin, newPosition);\n}\n\nZ7_COM7F_IMF(CInFileStreamVol::GetSize(UInt64 *size))\n{\n  RINOK(EnsureOpen())\n  CMultiStreams::CSubStream &s = OpenCallbackImp->Volumes.Streams[FileIndex];\n  return s.FileSpec->GetSize(size);\n}\n\n\n// from ArchiveExtractCallback.cpp\nbool IsSafePath(const UString &path);\n\nZ7_COM7F_IMF(COpenCallbackImp::GetStream(const wchar_t *name, IInStream **inStream))\n{\n  COM_TRY_BEGIN\n  *inStream = NULL;\n  \n  if (_subArchiveMode)\n    return S_FALSE;\n  if (Callback)\n  {\n    RINOK(Callback->Open_CheckBreak())\n  }\n\n  UString name2 = name;\n\n  \n  #ifndef Z7_SFX\n  \n  #ifdef _WIN32\n  name2.Replace(L'/', WCHAR_PATH_SEPARATOR);\n  #endif\n\n  // if (!allowAbsVolPaths)\n  if (!IsSafePath(name2))\n    return S_FALSE;\n\n  #ifdef _WIN32\n  /* WIN32 allows wildcards in Find() function\n     and doesn't allow wildcard in File.Open()\n     so we can work without the following wildcard check here */\n  if (name2.Find(L'*') >= 0)\n    return S_FALSE;\n  {\n    unsigned startPos = 0;\n    if (name2.IsPrefixedBy_Ascii_NoCase(\"\\\\\\\\?\\\\\"))\n      startPos = 3;\n    if (name2.Find(L'?', startPos) >= 0)\n      return S_FALSE;\n  }\n  #endif\n\n  #endif\n\n\n  FString fullPath;\n  if (!NFile::NName::GetFullPath(_folderPrefix, us2fs(name2), fullPath))\n    return S_FALSE;\n  if (!_fileInfo.Find_FollowLink(fullPath))\n    return S_FALSE;\n  if (_fileInfo.IsDir())\n    return S_FALSE;\n\n  CMultiStreams::CSubStream s;\n\n  {\n    CInFileStream *inFile = new CInFileStream;\n    CMyComPtr<IInStream> inStreamTemp = inFile;\n    if (!inFile->Open(fullPath))\n      return GetLastError_noZero_HRESULT();\n    RINOK(Volumes.PrepareToOpenNew())\n    s.FileSpec = inFile;\n    s.Stream = s.FileSpec;\n    s.Path = fullPath;\n    // s.Size = _fileInfo.Size;\n    // s.IsOpen = true;\n  }\n\n  const unsigned fileIndex = Volumes.Streams.Add(s);\n  Volumes.InsertToList(fileIndex);\n\n  FileSizes.Add(_fileInfo.Size);\n  FileNames.Add(name2);\n  FileNames_WasUsed.Add(true);\n\n  CInFileStreamVol *inFile = new CInFileStreamVol;\n  CMyComPtr<IInStream> inStreamTemp = inFile;\n  inFile->FileIndex = fileIndex;\n  inFile->OpenCallbackImp = this;\n  inFile->OpenCallbackRef = this;\n  // TotalSize += _fileInfo.Size;\n  *inStream = inStreamTemp.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\n\n#ifndef Z7_NO_CRYPTO\nZ7_COM7F_IMF(COpenCallbackImp::CryptoGetTextPassword(BSTR *password))\n{\n  COM_TRY_BEGIN\n  if (ReOpenCallback)\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        ICryptoGetTextPassword,\n        getTextPassword, ReOpenCallback)\n    if (getTextPassword)\n      return getTextPassword->CryptoGetTextPassword(password);\n  }\n  if (!Callback)\n    return E_NOTIMPL;\n  PasswordWasAsked = true;\n  return Callback->Open_CryptoGetTextPassword(password);\n  COM_TRY_END\n}\n#endif\n\n// IProgress\nZ7_COM7F_IMF(COpenCallbackImp::SetTotal(const UInt64 /* total */))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(COpenCallbackImp::SetCompleted(const UInt64 * /* completed */))\n{\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ArchiveOpenCallback.h",
    "content": "﻿// ArchiveOpenCallback.h\n\n#ifndef ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H\n#define ZIP7_INC_ARCHIVE_OPEN_CALLBACK_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../../Windows/FileFind.h\"\n\n#include \"../../Common/FileStreams.h\"\n\n#ifndef Z7_NO_CRYPTO\n#include \"../../IPassword.h\"\n#endif\n#include \"../../Archive/IArchive.h\"\n\nZ7_PURE_INTERFACES_BEGIN\n\n#ifdef Z7_NO_CRYPTO\n\n#define Z7_IFACEM_IOpenCallbackUI_Crypto(x)\n\n#else\n\n#define Z7_IFACEM_IOpenCallbackUI_Crypto(x) \\\n  virtual HRESULT Open_CryptoGetTextPassword(BSTR *password) x \\\n  /* virtual HRESULT Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password) x */ \\\n  /* virtual bool Open_WasPasswordAsked() x */ \\\n  /* virtual void Open_Clear_PasswordWasAsked_Flag() x */  \\\n  \n#endif\n\n#define Z7_IFACEN_IOpenCallbackUI(x) \\\n  virtual HRESULT Open_CheckBreak() x \\\n  virtual HRESULT Open_SetTotal(const UInt64 *files, const UInt64 *bytes) x \\\n  virtual HRESULT Open_SetCompleted(const UInt64 *files, const UInt64 *bytes) x \\\n  virtual HRESULT Open_Finished() x \\\n  Z7_IFACEM_IOpenCallbackUI_Crypto(x)\n\nZ7_IFACE_DECL_PURE(IOpenCallbackUI)\n\nZ7_PURE_INTERFACES_END\n\n\nclass CMultiStreams Z7_final\n{\npublic:\n  struct CSubStream\n  {\n    CMyComPtr<IInStream> Stream;\n    CInFileStream *FileSpec;\n    FString Path;\n    // UInt64 Size;\n    UInt64 LocalPos;\n    int Next; // next older\n    int Prev; // prev newer\n    // bool IsOpen;\n\n    CSubStream():\n        FileSpec(NULL),\n        // Size(0),\n        LocalPos(0),\n        Next(-1),\n        Prev(-1)\n        // IsOpen(false)\n        {}\n  };\n\n  CObjectVector<CSubStream> Streams;\nprivate:\n  // we must use critical section here, if we want to access from different volumnes simultaneously\n  int Head; // newest\n  int Tail; // oldest\n  unsigned NumListItems;\n  unsigned NumOpenFiles_AllowedMax;\npublic:\n\n  CMultiStreams();\n  void Init();\n  HRESULT PrepareToOpenNew();\n  void InsertToList(unsigned index);\n  void RemoveFromList(CSubStream &s);\n  void CloseFile(unsigned index);\n  HRESULT EnsureOpen(unsigned index);\n};\n\n\n/*\n  We need COpenCallbackImp class for multivolume processing.\n  Also we use it as proxy from COM interfaces (IArchiveOpenCallback) to internal (IOpenCallbackUI) interfaces.\n  If archive is multivolume:\n    COpenCallbackImp object will exist after Open stage.\n    COpenCallbackImp object will be deleted when last reference\n      from each volume object (CInFileStreamVol) will be closed (when archive will be closed).\n*/\n\nclass COpenCallbackImp Z7_final:\n  public IArchiveOpenCallback,\n  public IArchiveOpenVolumeCallback,\n  public IArchiveOpenSetSubArchiveName,\n #ifndef Z7_NO_CRYPTO\n  public ICryptoGetTextPassword,\n #endif\n  public IProgress, // IProgress is used for 7zFM\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IArchiveOpenCallback)\n  Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback)\n  Z7_COM_QI_ENTRY(IArchiveOpenSetSubArchiveName)\n #ifndef Z7_NO_CRYPTO\n  Z7_COM_QI_ENTRY(ICryptoGetTextPassword)\n #endif\n  // Z7_COM_QI_ENTRY(IProgress) // the code doesn't require it\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n  \n  Z7_IFACE_COM7_IMP(IArchiveOpenCallback)\n  Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback)\n  Z7_IFACE_COM7_IMP(IProgress)\npublic:\n  Z7_IFACE_COM7_IMP(IArchiveOpenSetSubArchiveName)\nprivate:\n #ifndef Z7_NO_CRYPTO\n  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)\n #endif\n\n  bool _subArchiveMode;\n\npublic:\n  bool PasswordWasAsked;\n  UStringVector FileNames;\n  CBoolVector FileNames_WasUsed;\n  CRecordVector<UInt64> FileSizes;\n\n  void AtCloseFile(unsigned fileIndex)\n  {\n    FileNames_WasUsed[fileIndex] = false;\n    Volumes.CloseFile(fileIndex);\n  }\n\n  /* we have two ways to Callback from this object\n      1) IArchiveOpenCallback * ReOpenCallback - for ReOpen function, when IOpenCallbackUI is not available\n      2) IOpenCallbackUI *Callback - for usual callback\n     we can't transfer IOpenCallbackUI pointer via internal interface,\n     so we use ReOpenCallback to callback without IOpenCallbackUI.\n  */\n\n  /* we use Callback/ReOpenCallback only at Open stage.\n     So the CMyComPtr reference counter is not required,\n     and we don't want additional reference to unused object,\n     if COpenCallbackImp is not closed\n  */\n  IArchiveOpenCallback *ReOpenCallback;\n  // CMyComPtr<IArchiveOpenCallback> ReOpenCallback;\n  IOpenCallbackUI *Callback;\n  // CMyComPtr<IUnknown> Callback_Ref;\n\nprivate:\n  FString _folderPrefix;\n  UString _subArchiveName;\n  NWindows::NFile::NFind::CFileInfo _fileInfo;\n\npublic:\n  CMultiStreams Volumes;\n  \n  // UInt64 TotalSize;\n\n  COpenCallbackImp():\n      _subArchiveMode(false),\n      PasswordWasAsked(false),\n      ReOpenCallback(NULL),\n      Callback(NULL)  {}\n  \n  HRESULT Init2(const FString &folderPrefix, const FString &fileName);\n\n  bool SetSecondFileInfo(CFSTR newName)\n  {\n    return _fileInfo.Find_FollowLink(newName) && !_fileInfo.IsDir();\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/DefaultName.cpp",
    "content": "﻿// DefaultName.cpp\n\n#include \"StdAfx.h\"\n\n#include \"DefaultName.h\"\n\nstatic UString GetDefaultName3(const UString &fileName,\n    const UString &extension, const UString &addSubExtension)\n{\n  const unsigned extLen = extension.Len();\n  const unsigned fileNameLen = fileName.Len();\n  \n  if (fileNameLen > extLen + 1)\n  {\n    const unsigned dotPos = fileNameLen - (extLen + 1);\n    if (fileName[dotPos] == '.')\n      if (extension.IsEqualTo_NoCase(fileName.Ptr(dotPos + 1)))\n        return fileName.Left(dotPos) + addSubExtension;\n  }\n  \n  int dotPos = fileName.ReverseFind_Dot();\n  if (dotPos > 0)\n    return fileName.Left((unsigned)dotPos) + addSubExtension;\n\n  if (addSubExtension.IsEmpty())\n    return fileName + L'~';\n  else\n    return fileName + addSubExtension;\n}\n\nUString GetDefaultName2(const UString &fileName,\n    const UString &extension, const UString &addSubExtension)\n{\n  UString name = GetDefaultName3(fileName, extension, addSubExtension);\n  name.TrimRight();\n  return name;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/DefaultName.h",
    "content": "﻿// DefaultName.h\n\n#ifndef ZIP7_INC_DEFAULT_NAME_H\n#define ZIP7_INC_DEFAULT_NAME_H\n\n#include \"../../../Common/MyString.h\"\n\nUString GetDefaultName2(const UString &fileName,\n    const UString &extension, const UString &addSubExtension);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/DirItem.h",
    "content": "﻿// DirItem.h\n\n#ifndef ZIP7_INC_DIR_ITEM_H\n#define ZIP7_INC_DIR_ITEM_H\n\n#ifdef _WIN32\n#include \"../../../Common/MyLinux.h\"\n#endif\n\n#include \"../../../Common/MyString.h\"\n\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/TimeUtils.h\"\n\n#include \"../../Common/UniqBlocks.h\"\n\n#include \"../../Archive/IArchive.h\"\n\nstruct CDirItemsStat\n{\n  UInt64 NumDirs;\n  UInt64 NumFiles;\n  UInt64 NumAltStreams;\n  UInt64 FilesSize;\n  UInt64 AltStreamsSize;\n  \n  UInt64 NumErrors;\n  \n  // UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; }\n  UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; }\n  UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; }\n\n  bool IsEmpty() const { return\n           0 == NumDirs\n        && 0 == NumFiles\n        && 0 == NumAltStreams\n        && 0 == FilesSize\n        && 0 == AltStreamsSize\n        && 0 == NumErrors; }\n  \n  CDirItemsStat():\n      NumDirs(0),\n      NumFiles(0),\n      NumAltStreams(0),\n      FilesSize(0),\n      AltStreamsSize(0),\n      NumErrors(0)\n    {}\n};\n\n\nstruct CDirItemsStat2: public CDirItemsStat\n{\n  UInt64 Anti_NumDirs;\n  UInt64 Anti_NumFiles;\n  UInt64 Anti_NumAltStreams;\n  \n  // UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); }\n  UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); }\n\n  bool IsEmpty() const { return CDirItemsStat::IsEmpty()\n        && 0 == Anti_NumDirs\n        && 0 == Anti_NumFiles\n        && 0 == Anti_NumAltStreams; }\n  \n  CDirItemsStat2():\n      Anti_NumDirs(0),\n      Anti_NumFiles(0),\n      Anti_NumAltStreams(0)\n    {}\n};\n\n\nZ7_PURE_INTERFACES_BEGIN\n\n#define Z7_IFACEN_IDirItemsCallback(x) \\\n  virtual HRESULT ScanError(const FString &path, DWORD systemError) x \\\n  virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x \\\n\nZ7_IFACE_DECL_PURE(IDirItemsCallback)\n\nZ7_PURE_INTERFACES_END\n\n\nstruct CArcTime\n{\n  FILETIME FT;\n  UInt16 Prec;\n  Byte Ns100;\n  bool Def;\n\n  CArcTime()\n  {\n    Clear();\n  }\n\n  void Clear()\n  {\n    FT.dwHighDateTime = FT.dwLowDateTime = 0;\n    Prec = 0;\n    Ns100 = 0;\n    Def = false;\n  }\n\n  bool IsZero() const\n  {\n    return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0;\n  }\n\n  int CompareWith(const CArcTime &a) const\n  {\n    const int res = CompareFileTime(&FT, &a.FT);\n    if (res != 0)\n      return res;\n    if (Ns100 < a.Ns100) return -1;\n    if (Ns100 > a.Ns100) return 1;\n    return 0;\n  }\n\n  UInt64 Get_FILETIME_as_UInt64() const\n  {\n    return (((UInt64)FT.dwHighDateTime) << 32) + FT.dwLowDateTime;\n  }\n\n  UInt32 Get_DosTime() const\n  {\n    FILETIME ft2 = FT;\n    if ((Prec == k_PropVar_TimePrec_Base + 8 ||\n         Prec == k_PropVar_TimePrec_Base + 9)\n        && Ns100 != 0)\n    {\n      UInt64 u64 = Get_FILETIME_as_UInt64();\n      // we round up even small (ns < 100ns) as FileTimeToDosTime()\n      if (u64 % 20000000 == 0)\n      {\n        u64++;\n        ft2.dwHighDateTime = (DWORD)(u64 >> 32);\n        ft2.dwHighDateTime = (DWORD)u64;\n      }\n    }\n    // FileTimeToDosTime() is expected to round up in Windows\n    UInt32 dosTime;\n    // we use simplified code with utctime->dos.\n    // do we need local time instead here?\n    NWindows::NTime::FileTime_To_DosTime(ft2, dosTime);\n    return dosTime;\n  }\n\n  int GetNumDigits() const\n  {\n    if (Prec == k_PropVar_TimePrec_Unix ||\n        Prec == k_PropVar_TimePrec_DOS)\n      return 0;\n    if (Prec == k_PropVar_TimePrec_HighPrec)\n      return 9;\n    if (Prec == k_PropVar_TimePrec_0)\n      return 7;\n    int digits = (int)Prec - (int)k_PropVar_TimePrec_Base;\n    if (digits < 0)\n      digits = 0;\n    return digits;\n  }\n\n  void Write_To_FiTime(CFiTime &dest) const\n  {\n   #ifdef _WIN32\n    dest = FT;\n   #else\n    if (FILETIME_To_timespec(FT, dest))\n    if ((Prec == k_PropVar_TimePrec_Base + 8 ||\n         Prec == k_PropVar_TimePrec_Base + 9)\n        && Ns100 != 0)\n    {\n      dest.tv_nsec += Ns100;\n    }\n   #endif\n  }\n\n  // (Def) is not set\n  void Set_From_FILETIME(const FILETIME &ft)\n  {\n    FT = ft;\n    // Prec = k_PropVar_TimePrec_CompatNTFS;\n    Prec = k_PropVar_TimePrec_Base + 7;\n    Ns100 = 0;\n  }\n\n  // (Def) is not set\n  // it set full form precision: k_PropVar_TimePrec_Base + numDigits\n  void Set_From_FiTime(const CFiTime &ts)\n  {\n   #ifdef _WIN32\n    FT = ts;\n    Prec = k_PropVar_TimePrec_Base + 7;\n    // Prec = k_PropVar_TimePrec_Base; // for debug\n    // Prec = 0; // for debug\n    Ns100 = 0;\n   #else\n    unsigned ns100;\n    FiTime_To_FILETIME_ns100(ts, FT, ns100);\n    Ns100 = (Byte)ns100;\n    Prec = k_PropVar_TimePrec_Base + 9;\n   #endif\n  }\n\n  void Set_From_Prop(const PROPVARIANT &prop)\n  {\n    FT = prop.filetime;\n    unsigned prec = 0;\n    unsigned ns100 = 0;\n    const unsigned prec_Temp = prop.wReserved1;\n    if (prec_Temp != 0\n        && prec_Temp <= k_PropVar_TimePrec_1ns\n        && prop.wReserved3 == 0)\n    {\n      const unsigned ns100_Temp = prop.wReserved2;\n      if (ns100_Temp < 100)\n      {\n        ns100 = ns100_Temp;\n        prec = prec_Temp;\n      }\n    }\n    Prec = (UInt16)prec;\n    Ns100 = (Byte)ns100;\n    Def = true;\n  }\n};\n\n\nstruct CDirItem: public NWindows::NFile::NFind::CFileInfoBase\n{\n  UString Name;\n  \n #ifndef UNDER_CE\n  CByteBuffer ReparseData;\n\n #ifdef _WIN32\n  // UString ShortName;\n  CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format\n  bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; }\n #else\n  bool AreReparseData() const { return ReparseData.Size() != 0; }\n #endif // _WIN32\n\n #endif // !UNDER_CE\n  \n  void Copy_From_FileInfoBase(const NWindows::NFile::NFind::CFileInfoBase &fi)\n  {\n    (NWindows::NFile::NFind::CFileInfoBase &)*this = fi;\n  }\n\n  int PhyParent;\n  int LogParent;\n  int SecureIndex;\n\n #ifdef _WIN32\n #else\n  int OwnerNameIndex;\n  int OwnerGroupIndex;\n #endif\n\n  // bool Attrib_IsDefined;\n\n  CDirItem():\n      PhyParent(-1)\n    , LogParent(-1)\n    , SecureIndex(-1)\n   #ifdef _WIN32\n   #else\n    , OwnerNameIndex(-1)\n    , OwnerGroupIndex(-1)\n   #endif\n    // , Attrib_IsDefined(true)\n  {\n  }\n\n\n  CDirItem(const NWindows::NFile::NFind::CFileInfo &fi,\n      int phyParent, int logParent, int secureIndex):\n    CFileInfoBase(fi)\n    , Name(fs2us(fi.Name))\n   #if defined(_WIN32) && !defined(UNDER_CE)\n    // , ShortName(fs2us(fi.ShortName))\n   #endif\n    , PhyParent(phyParent)\n    , LogParent(logParent)\n    , SecureIndex(secureIndex)\n   #ifdef _WIN32\n   #else\n    , OwnerNameIndex(-1)\n    , OwnerGroupIndex(-1)\n   #endif\n    {}\n};\n\n\n\nclass CDirItems\n{\n  UStringVector Prefixes;\n  CIntVector PhyParents;\n  CIntVector LogParents;\n\n  UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const;\n\n  HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix);\n\npublic:\n  CObjectVector<CDirItem> Items;\n\n  bool SymLinks;\n  bool ScanAltStreams;\n  bool ExcludeDirItems;\n  bool ExcludeFileItems;\n  bool ShareForWrite;\n\n  /* it must be called after anotrher checks */\n  bool CanIncludeItem(bool isDir) const\n  {\n    return isDir ? !ExcludeDirItems : !ExcludeFileItems;\n  }\n \n\n  CDirItemsStat Stat;\n\n  #if !defined(UNDER_CE)\n  HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi,\n      const FString &phyPrefix);\n  #endif\n\n #if defined(_WIN32) && !defined(UNDER_CE)\n\n  CUniqBlocks SecureBlocks;\n  CByteBuffer TempSecureBuf;\n  bool _saclEnabled;\n  bool ReadSecure;\n  \n  HRESULT AddSecurityItem(const FString &path, int &secureIndex);\n  HRESULT FillFixedReparse();\n\n #endif\n\n #ifndef _WIN32\n  \n  C_UInt32_UString_Map OwnerNameMap;\n  C_UInt32_UString_Map OwnerGroupMap;\n  bool StoreOwnerName;\n  \n  HRESULT FillDeviceSizes();\n\n #endif\n\n  IDirItemsCallback *Callback;\n\n  CDirItems();\n\n  void AddDirFileInfo(int phyParent, int logParent, int secureIndex,\n      const NWindows::NFile::NFind::CFileInfo &fi);\n\n  HRESULT AddError(const FString &path, DWORD errorCode);\n  HRESULT AddError(const FString &path);\n\n  HRESULT ScanProgress(const FString &path);\n\n  // unsigned GetNumFolders() const { return Prefixes.Size(); }\n  FString GetPhyPath(unsigned index) const;\n  UString GetLogPath(unsigned index) const;\n\n  unsigned AddPrefix(int phyParent, int logParent, const UString &prefix);\n  void DeleteLastPrefix();\n\n  // HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CDirEntry> &files);\n  HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CFileInfo> &files);\n  \n  HRESULT EnumerateItems2(\n    const FString &phyPrefix,\n    const UString &logPrefix,\n    const FStringVector &filePaths,\n    FStringVector *requestedPaths);\n\n  void ReserveDown();\n};\n\n\n\n\nstruct CArcItem\n{\n  UInt64 Size;\n  UString Name;\n  CArcTime MTime;  // it can be mtime of archive file, if MTime is not defined for item in archive\n  bool IsDir;\n  bool IsAltStream;\n  bool Size_Defined;\n  bool Censored;\n  UInt32 IndexInServer;\n  \n  CArcItem():\n      IsDir(false),\n      IsAltStream(false),\n      Size_Defined(false),\n      Censored(false)\n    {}\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/EnumDirItems.h",
    "content": "﻿// EnumDirItems.h\n\n#ifndef ZIP7_INC_ENUM_DIR_ITEMS_H\n#define ZIP7_INC_ENUM_DIR_ITEMS_H\n\n#include \"../../../Common/Wildcard.h\"\n\n#include \"DirItem.h\"\n\n\nHRESULT EnumerateItems(\n    const NWildcard::CCensor &censor,\n    NWildcard::ECensorPathMode pathMode,\n    const UString &addPathPrefix,\n    CDirItems &dirItems);\n\n\nstruct CMessagePathException: public UString\n{\n  CMessagePathException(const char *a, const wchar_t *u = NULL);\n  CMessagePathException(const wchar_t *a, const wchar_t *u = NULL);\n};\n\n\nHRESULT EnumerateDirItemsAndSort(\n    NWildcard::CCensor &censor,\n    NWildcard::ECensorPathMode pathMode,\n    const UString &addPathPrefix,\n    UStringVector &sortedPaths,\n    UStringVector &sortedFullPaths,\n    CDirItemsStat &st,\n    IDirItemsCallback *callback);\n\n#ifdef _WIN32\nvoid ConvertToLongNames(NWildcard::CCensor &censor);\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ExitCode.h",
    "content": "﻿// ExitCode.h\n\n#ifndef ZIP7_INC_EXIT_CODE_H\n#define ZIP7_INC_EXIT_CODE_H\n\nnamespace NExitCode {\n\nenum EEnum {\n\n  kSuccess       = 0,     // Successful operation\n  kWarning       = 1,     // Non fatal error(s) occurred\n  kFatalError    = 2,     // A fatal error occurred\n  // kCRCError      = 3,     // A CRC error occurred when unpacking\n  // kLockedArchive = 4,     // Attempt to modify an archive previously locked\n  // kWriteError    = 5,     // Write to disk error\n  // kOpenError     = 6,     // Open file error\n  kUserError     = 7,     // Command line option error\n  kMemoryError   = 8,     // Not enough memory for operation\n  // kCreateFileError = 9,     // Create file error\n  \n  kUserBreak     = 255   // User stopped the process\n\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/Extract.cpp",
    "content": "﻿// Extract.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n\n#include \"../Common/ExtractingFilePath.h\"\n#include \"../Common/HashCalc.h\"\n\n#include \"Extract.h\"\n#include \"SetProperties.h\"\n\n// **************** NanaZip Modification Start ****************\n#include <set>\n#include <string>\n// **************** NanaZip Modification End ****************\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\n\nstatic void SetErrorMessage(const char *message,\n    const FString &path, HRESULT errorCode,\n    UString &s)\n{\n  s = message;\n  s += \" : \";\n  s += NError::MyFormatMessage(errorCode);\n  s += \" : \";\n  s += fs2us(path);\n}\n\n\nstatic HRESULT DecompressArchive(\n    CCodecs *codecs,\n    const CArchiveLink &arcLink,\n    UInt64 packSize,\n    const NWildcard::CCensorNode &wildcardCensor,\n    const CExtractOptions &options,\n    bool calcCrc,\n    IExtractCallbackUI *callback,\n    IFolderArchiveExtractCallback *callbackFAE,\n    CArchiveExtractCallback *ecs,\n    UString &errorMessage,\n    UInt64 &stdInProcessed)\n{\n  const CArc &arc = arcLink.Arcs.Back();\n  stdInProcessed = 0;\n  IInArchive *archive = arc.Archive;\n  CRecordVector<UInt32> realIndices;\n  \n  UStringVector removePathParts;\n\n  // **************** NanaZip Modification Start ****************\n  //FString outDir = options.OutputDir;\n  ecs->OutDir = options.OutputDir;\n  // **************** NanaZip Modification End ****************\n  UString replaceName = arc.DefaultName;\n  \n  if (arcLink.Arcs.Size() > 1)\n  {\n    // Most \"pe\" archives have same name of archive subfile \"[0]\" or \".rsrc_1\".\n    // So it extracts different archives to one folder.\n    // We will use top level archive name\n    const CArc &arc0 = arcLink.Arcs[0];\n    if (arc0.FormatIndex >= 0 && StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)arc0.FormatIndex].Name, \"pe\"))\n      replaceName = arc0.DefaultName;\n  }\n\n  // **************** NanaZip Modification Start ****************\n  //outDir.Replace(FString(\"*\"), us2fs(Get_Correct_FsFile_Name(replaceName)));\n  ecs->OutDir.Replace(FString(\"*\"), us2fs(Get_Correct_FsFile_Name(replaceName)));\n  // **************** NanaZip Modification End ****************\n\n  bool elimIsPossible = false;\n  UString elimPrefix; // only pure name without dir delimiter\n  // **************** NanaZip Modification Start ****************\n  //FString outDirReduced = outDir;\n  FString outDirReduced = ecs->OutDir;\n  // **************** NanaZip Modification End ****************\n  \n  if (options.ElimDup.Val && options.PathMode != NExtract::NPathMode::kAbsPaths)\n  {\n    UString dirPrefix;\n    // **************** NanaZip Modification Start ****************\n    //SplitPathToParts_Smart(fs2us(outDir), dirPrefix, elimPrefix);\n    SplitPathToParts_Smart(fs2us(ecs->OutDir), dirPrefix, elimPrefix);\n    // **************** NanaZip Modification End ****************\n    if (!elimPrefix.IsEmpty())\n    {\n      if (IsPathSepar(elimPrefix.Back()))\n        elimPrefix.DeleteBack();\n      if (!elimPrefix.IsEmpty())\n      {\n        outDirReduced = us2fs(dirPrefix);\n        elimIsPossible = true;\n      }\n    }\n  }\n\n  const bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();\n\n  if (!options.StdInMode)\n  {\n    UInt32 numItems;\n    RINOK(archive->GetNumberOfItems(&numItems))\n    \n    CReadArcItem item;\n\n    for (UInt32 i = 0; i < numItems; i++)\n    {\n      if (elimIsPossible\n          || !allFilesAreAllowed\n          || options.ExcludeDirItems\n          || options.ExcludeFileItems)\n      {\n        RINOK(arc.GetItem(i, item))\n        if (item.IsDir ? options.ExcludeDirItems : options.ExcludeFileItems)\n          continue;\n      }\n      else\n      {\n        #ifdef SUPPORT_ALT_STREAMS\n        item.IsAltStream = false;\n        if (!options.NtOptions.AltStreams.Val && arc.Ask_AltStream)\n        {\n          RINOK(Archive_IsItem_AltStream(arc.Archive, i, item.IsAltStream))\n        }\n        #endif\n      }\n\n      #ifdef SUPPORT_ALT_STREAMS\n      if (!options.NtOptions.AltStreams.Val && item.IsAltStream)\n        continue;\n      #endif\n      \n      if (elimIsPossible)\n      {\n        const UString &s =\n          #ifdef SUPPORT_ALT_STREAMS\n            item.MainPath;\n          #else\n            item.Path;\n          #endif\n        if (!IsPath1PrefixedByPath2(s, elimPrefix))\n          elimIsPossible = false;\n        else\n        {\n          wchar_t c = s[elimPrefix.Len()];\n          if (c == 0)\n          {\n            if (!item.MainIsDir)\n              elimIsPossible = false;\n          }\n          else if (!IsPathSepar(c))\n            elimIsPossible = false;\n        }\n      }\n\n      if (!allFilesAreAllowed)\n      {\n        if (!CensorNode_CheckPath(wildcardCensor, item))\n          continue;\n      }\n\n      realIndices.Add(i);\n    }\n    \n    // **************** NanaZip Modification Start ****************\n    if (options.SmartExtract.Val)\n    {\n      std::set<std::wstring> firstLevelSet;\n      for (UInt32 i = 0; i < numItems; i++)\n      {\n        RINOK(arc.GetItem(i, item));\n        const UString &path =\n          #ifdef SUPPORT_ALT_STREAMS\n            item.MainPath;\n          #else\n            item.Path;\n          #endif\n        int slashPos = path.Find(L'/');\n        if (slashPos == -1)\n          slashPos = path.Find(L'\\\\');\n        if (slashPos == -1)\n          firstLevelSet.insert(std::wstring(path.Ptr()));\n        else\n          firstLevelSet.insert(std::wstring(path.Left(slashPos).Ptr()));\n        if (firstLevelSet.size() > 1)\n          break;\n      }\n      if (firstLevelSet.size() > 1)\n        ecs->OutDir += replaceName;\n    }\n    // **************** NanaZip Modification End ****************\n\n    if (realIndices.Size() == 0)\n    {\n      callback->ThereAreNoFiles();\n      return callback->ExtractResult(S_OK);\n    }\n  }\n\n  if (elimIsPossible)\n  {\n    removePathParts.Add(elimPrefix);\n    // outDir = outDirReduced;\n  }\n\n  #ifdef _WIN32\n  // GetCorrectFullFsPath doesn't like \"..\".\n  // outDir.TrimRight();\n  // outDir = GetCorrectFullFsPath(outDir);\n  #endif\n\n  // **************** NanaZip Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n  if (outDir.IsEmpty())\n    outDir = \".\" STRING_PATH_SEPARATOR;\n  /*\n  #ifdef _WIN32\n  else if (NName::IsAltPathPrefix(outDir)) {}\n  #endif\n  */\n  else if (!CreateComplexDir(outDir))\n  {\n    const HRESULT res = GetLastError_noZero_HRESULT();\n    SetErrorMessage(\"Cannot create output directory\", outDir, res, errorMessage);\n    return res;\n  }\n  \n  ecs->Init(\n      options.NtOptions,\n      options.StdInMode ? &wildcardCensor : NULL,\n      &arc,\n      callbackFAE,\n      options.StdOutMode, options.TestMode,\n      outDir,\n      removePathParts, false,\n      packSize);\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n  if (ecs->OutDir.IsEmpty())\n      ecs->OutDir = \".\" STRING_PATH_SEPARATOR;\n  /*\n  #ifdef _WIN32\n  else if (NName::IsAltPathPrefix(outDir)) {}\n  #endif\n  */\n  else if (!CreateComplexDir(ecs->OutDir))\n  {\n    const HRESULT res = GetLastError_noZero_HRESULT();\n    SetErrorMessage(\"Cannot create output directory\", ecs->OutDir, res, errorMessage);\n    return res;\n  }\n  \n  ecs->Init(\n      options.NtOptions,\n      options.StdInMode ? &wildcardCensor : NULL,\n      &arc,\n      callbackFAE,\n      options.StdOutMode, options.TestMode,\n      ecs->OutDir,\n      removePathParts, false,\n      packSize);\n  // **************** NanaZip Modification End ****************\n\n  ecs->Is_elimPrefix_Mode = elimIsPossible;\n\n  \n  #ifdef SUPPORT_LINKS\n  \n  if (!options.StdInMode &&\n      !options.TestMode &&\n      options.NtOptions.HardLinks.Val)\n  {\n    RINOK(ecs->PrepareHardLinks(&realIndices))\n  }\n    \n  #endif\n\n  \n  HRESULT result;\n  const Int32 testMode = (options.TestMode && !calcCrc) ? 1: 0;\n\n  CArchiveExtractCallback_Closer ecsCloser(ecs);\n\n  if (options.StdInMode)\n  {\n    result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, ecs);\n    NCOM::CPropVariant prop;\n    if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)\n      ConvertPropVariantToUInt64(prop, stdInProcessed);\n  }\n  else\n  {\n    // v23.02: we reset completed value that could be set by Open() operation\n    IArchiveExtractCallback *aec = ecs;\n    const UInt64 val = 0;\n    RINOK(aec->SetCompleted(&val))\n    result = archive->Extract(realIndices.ConstData(), realIndices.Size(), testMode, aec);\n  }\n  \n  const HRESULT res2 = ecsCloser.Close();\n  if (result == S_OK)\n    result = res2;\n\n  return callback->ExtractResult(result);\n}\n\n/* v9.31: BUG was fixed:\n   Sorted list for file paths was sorted with case insensitive compare function.\n   But FindInSorted function did binary search via case sensitive compare function */\n\nint Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name);\nint Find_FileName_InSortedVector(const UStringVector &fileNames, const UString &name)\n{\n  unsigned left = 0, right = fileNames.Size();\n  while (left != right)\n  {\n    const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n    const UString &midVal = fileNames[mid];\n    const int comp = CompareFileNames(name, midVal);\n    if (comp == 0)\n      return (int)mid;\n    if (comp < 0)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  return -1;\n}\n\n\n\nHRESULT Extract(\n    // DECL_EXTERNAL_CODECS_LOC_VARS\n    CCodecs *codecs,\n    const CObjectVector<COpenType> &types,\n    const CIntVector &excludedFormats,\n    UStringVector &arcPaths, UStringVector &arcPathsFull,\n    const NWildcard::CCensorNode &wildcardCensor,\n    const CExtractOptions &options,\n    IOpenCallbackUI *openCallback,\n    IExtractCallbackUI *extractCallback,\n    IFolderArchiveExtractCallback *faeCallback,\n    #ifndef Z7_SFX\n    IHashCalc *hash,\n    #endif\n    UString &errorMessage,\n    CDecompressStat &st)\n{\n  st.Clear();\n  UInt64 totalPackSize = 0;\n  CRecordVector<UInt64> arcSizes;\n\n  unsigned numArcs = options.StdInMode ? 1 : arcPaths.Size();\n\n  unsigned i;\n  \n  for (i = 0; i < numArcs; i++)\n  {\n    NFind::CFileInfo fi;\n    fi.Size = 0;\n    if (!options.StdInMode)\n    {\n      const FString arcPath = us2fs(arcPaths[i]);\n      if (!fi.Find_FollowLink(arcPath))\n      {\n        const HRESULT errorCode = GetLastError_noZero_HRESULT();\n        SetErrorMessage(\"Cannot find archive file\", arcPath, errorCode, errorMessage);\n        return errorCode;\n      }\n      if (fi.IsDir())\n      {\n        HRESULT errorCode = E_FAIL;\n        SetErrorMessage(\"The item is a directory\", arcPath, errorCode, errorMessage);\n        return errorCode;\n      }\n    }\n    arcSizes.Add(fi.Size);\n    totalPackSize += fi.Size;\n  }\n\n  CBoolArr skipArcs(numArcs);\n  for (i = 0; i < numArcs; i++)\n    skipArcs[i] = false;\n\n  CArchiveExtractCallback *ecs = new CArchiveExtractCallback;\n  CMyComPtr<IArchiveExtractCallback> ec(ecs);\n  \n  const bool multi = (numArcs > 1);\n  \n  ecs->InitForMulti(multi,\n      options.PathMode,\n      options.OverwriteMode,\n      options.ZoneMode,\n      false // keepEmptyDirParts\n      );\n  #ifndef Z7_SFX\n  ecs->SetHashMethods(hash);\n  #endif\n\n  if (multi)\n  {\n    RINOK(faeCallback->SetTotal(totalPackSize))\n  }\n\n  UInt64 totalPackProcessed = 0;\n  bool thereAreNotOpenArcs = false;\n  \n  for (i = 0; i < numArcs; i++)\n  {\n    if (skipArcs[i])\n      continue;\n\n    ecs->InitBeforeNewArchive();\n\n    const UString &arcPath = arcPaths[i];\n    NFind::CFileInfo fi;\n    if (options.StdInMode)\n    {\n      // do we need ctime and mtime?\n      // fi.ClearBase();\n      // fi.Size = 0; // (UInt64)(Int64)-1;\n      if (!fi.SetAs_StdInFile())\n        return GetLastError_noZero_HRESULT();\n    }\n    else\n    {\n      if (!fi.Find_FollowLink(us2fs(arcPath)) || fi.IsDir())\n      {\n        const HRESULT errorCode = GetLastError_noZero_HRESULT();\n        SetErrorMessage(\"Cannot find archive file\", us2fs(arcPath), errorCode, errorMessage);\n        return errorCode;\n      }\n    }\n\n    /*\n    #ifndef Z7_NO_CRYPTO\n    openCallback->Open_Clear_PasswordWasAsked_Flag();\n    #endif\n    */\n\n    RINOK(extractCallback->BeforeOpen(arcPath, options.TestMode))\n    CArchiveLink arcLink;\n\n    CObjectVector<COpenType> types2 = types;\n    /*\n    #ifndef Z7_SFX\n    if (types.IsEmpty())\n    {\n      int pos = arcPath.ReverseFind(L'.');\n      if (pos >= 0)\n      {\n        UString s = arcPath.Ptr(pos + 1);\n        int index = codecs->FindFormatForExtension(s);\n        if (index >= 0 && s.IsEqualTo(\"001\"))\n        {\n          s = arcPath.Left(pos);\n          pos = s.ReverseFind(L'.');\n          if (pos >= 0)\n          {\n            int index2 = codecs->FindFormatForExtension(s.Ptr(pos + 1));\n            if (index2 >= 0) // && s.CompareNoCase(L\"rar\") != 0\n            {\n              types2.Add(index2);\n              types2.Add(index);\n            }\n          }\n        }\n      }\n    }\n    #endif\n    */\n\n    COpenOptions op;\n    #ifndef Z7_SFX\n    op.props = &options.Properties;\n    #endif\n    op.codecs = codecs;\n    op.types = &types2;\n    op.excludedFormats = &excludedFormats;\n    op.stdInMode = options.StdInMode;\n    op.stream = NULL;\n    op.filePath = arcPath;\n\n    HRESULT result = arcLink.Open_Strict(op, openCallback);\n\n    if (result == E_ABORT)\n      return result;\n\n    // arcLink.Set_ErrorsText();\n    RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, result))\n\n    if (result != S_OK)\n    {\n      thereAreNotOpenArcs = true;\n      if (!options.StdInMode)\n        totalPackProcessed += fi.Size;\n      continue;\n    }\n\n   #if defined(_WIN32) && !defined(UNDER_CE) && !defined(Z7_SFX)\n    if (options.ZoneMode != NExtract::NZoneIdMode::kNone\n        && !options.StdInMode)\n    {\n      ReadZoneFile_Of_BaseFile(us2fs(arcPath), ecs->ZoneBuf);\n    }\n   #endif\n    \n\n    if (arcLink.Arcs.Size() != 0)\n    {\n      if (arcLink.GetArc()->IsHashHandler(op))\n      {\n        if (!options.TestMode)\n        {\n          /* real Extracting to files is possible.\n             But user can think that hash archive contains real files.\n             So we block extracting here. */\n          // v23.00 : we don't break process.\n          RINOK(extractCallback->OpenResult(codecs, arcLink, arcPath, E_NOTIMPL))\n          thereAreNotOpenArcs = true;\n          if (!options.StdInMode)\n            totalPackProcessed += fi.Size;\n          continue;\n          // return E_NOTIMPL; // before v23\n        }\n        FString dirPrefix = us2fs(options.HashDir);\n        if (dirPrefix.IsEmpty())\n        {\n          if (!NFile::NDir::GetOnlyDirPrefix(us2fs(arcPath), dirPrefix))\n          {\n            // return GetLastError_noZero_HRESULT();\n          }\n        }\n        if (!dirPrefix.IsEmpty())\n          NName::NormalizeDirPathPrefix(dirPrefix);\n        ecs->DirPathPrefix_for_HashFiles = dirPrefix;\n      }\n    }\n\n    if (!options.StdInMode)\n    {\n      // numVolumes += arcLink.VolumePaths.Size();\n      // arcLink.VolumesSize;\n\n      // totalPackSize -= DeleteUsedFileNamesFromList(arcLink, i + 1, arcPaths, arcPathsFull, &arcSizes);\n      // numArcs = arcPaths.Size();\n      if (arcLink.VolumePaths.Size() != 0)\n      {\n        Int64 correctionSize = (Int64)arcLink.VolumesSize;\n        FOR_VECTOR (v, arcLink.VolumePaths)\n        {\n          int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);\n          if (index >= 0)\n          {\n            if ((unsigned)index > i)\n            {\n              skipArcs[(unsigned)index] = true;\n              correctionSize -= arcSizes[(unsigned)index];\n            }\n          }\n        }\n        if (correctionSize != 0)\n        {\n          Int64 newPackSize = (Int64)totalPackSize + correctionSize;\n          if (newPackSize < 0)\n            newPackSize = 0;\n          totalPackSize = (UInt64)newPackSize;\n          RINOK(faeCallback->SetTotal(totalPackSize))\n        }\n      }\n    }\n\n    /*\n    // Now openCallback and extractCallback use same object. So we don't need to send password.\n\n    #ifndef Z7_NO_CRYPTO\n    bool passwordIsDefined;\n    UString password;\n    RINOK(openCallback->Open_GetPasswordIfAny(passwordIsDefined, password))\n    if (passwordIsDefined)\n    {\n      RINOK(extractCallback->SetPassword(password))\n    }\n    #endif\n    */\n\n    CArc &arc = arcLink.Arcs.Back();\n    arc.MTime.Def = !options.StdInMode\n        #ifdef _WIN32\n        && !fi.IsDevice\n        #endif\n        ;\n    if (arc.MTime.Def)\n      arc.MTime.Set_From_FiTime(fi.MTime);\n\n    UInt64 packProcessed;\n    const bool calcCrc =\n        #ifndef Z7_SFX\n          (hash != NULL);\n        #else\n          false;\n        #endif\n\n    RINOK(DecompressArchive(\n        codecs,\n        arcLink,\n        fi.Size + arcLink.VolumesSize,\n        wildcardCensor,\n        options,\n        calcCrc,\n        extractCallback, faeCallback, ecs,\n        errorMessage, packProcessed))\n\n    if (!options.StdInMode)\n      packProcessed = fi.Size + arcLink.VolumesSize;\n    totalPackProcessed += packProcessed;\n    ecs->LocalProgressSpec->InSize += packProcessed;\n    ecs->LocalProgressSpec->OutSize = ecs->UnpackSize;\n    if (!errorMessage.IsEmpty())\n      return E_FAIL;\n  }\n\n  if (multi || thereAreNotOpenArcs)\n  {\n    RINOK(faeCallback->SetTotal(totalPackSize))\n    RINOK(faeCallback->SetCompleted(&totalPackProcessed))\n  }\n\n  st.NumFolders = ecs->NumFolders;\n  st.NumFiles = ecs->NumFiles;\n  st.NumAltStreams = ecs->NumAltStreams;\n  st.UnpackSize = ecs->UnpackSize;\n  st.AltStreams_UnpackSize = ecs->AltStreams_UnpackSize;\n  st.NumArchives = arcPaths.Size();\n  st.PackSize = ecs->LocalProgressSpec->InSize;\n  // **************** 7-Zip ZS Modification Start ****************\n  st.FirstExtractedPath = ecs->FirstExtractedPath;\n  // **************** 7-Zip ZS Modification End ****************\n  // **************** NanaZip Modification Start ****************\n  st.OutDir = ecs->OutDir;\n  // **************** NanaZip Modification End ****************\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/Extract.h",
    "content": "﻿// Extract.h\n\n#ifndef ZIP7_INC_EXTRACT_H\n#define ZIP7_INC_EXTRACT_H\n\n#include \"../../../Windows/FileFind.h\"\n\n#include \"../../Archive/IArchive.h\"\n\n#include \"ArchiveExtractCallback.h\"\n#include \"ArchiveOpenCallback.h\"\n#include \"ExtractMode.h\"\n#include \"Property.h\"\n\n#include \"../Common/LoadCodecs.h\"\n\nstruct CExtractOptionsBase\n{\n  CBoolPair ElimDup;\n  // **************** NanaZip Modification Start ****************\n  CBoolPair SmartExtract;\n  // **************** NanaZip Modification End ****************\n\n  bool ExcludeDirItems;\n  bool ExcludeFileItems;\n\n  bool PathMode_Force;\n  bool OverwriteMode_Force;\n  NExtract::NPathMode::EEnum PathMode;\n  NExtract::NOverwriteMode::EEnum OverwriteMode;\n  NExtract::NZoneIdMode::EEnum ZoneMode;\n\n  CExtractNtOptions NtOptions;\n\n  FString OutputDir;\n  UString HashDir;\n\n  CExtractOptionsBase():\n      ExcludeDirItems(false),\n      ExcludeFileItems(false),\n      PathMode_Force(false),\n      OverwriteMode_Force(false),\n      PathMode(NExtract::NPathMode::kFullPaths),\n      OverwriteMode(NExtract::NOverwriteMode::kAsk),\n      // **************** NanaZip Modification Start ****************\n      // ZoneMode(NExtract::NZoneIdMode::kNone)\n      ZoneMode(NExtract::NZoneIdMode::Default)\n      // **************** NanaZip Modification End ****************\n      {}\n};\n\nstruct CExtractOptions: public CExtractOptionsBase\n{\n  bool StdInMode;\n  bool StdOutMode;\n  bool YesToAll;\n  bool TestMode;\n  // **************** NanaZip Modification Start ****************\n  CBoolPair OpenFolder;\n  // **************** NanaZip Modification End ****************\n\n  // bool ShowDialog;\n  // bool PasswordEnabled;\n  // UString Password;\n  #ifndef Z7_SFX\n  CObjectVector<CProperty> Properties;\n  #endif\n\n  /*\n  #ifdef Z7_EXTERNAL_CODECS\n  CCodecs *Codecs;\n  #endif\n  */\n\n  CExtractOptions():\n      StdInMode(false),\n      StdOutMode(false),\n      YesToAll(false),\n      TestMode(false)\n      {}\n};\n\nstruct CDecompressStat\n{\n  UInt64 NumArchives;\n  UInt64 UnpackSize;\n  UInt64 AltStreams_UnpackSize;\n  UInt64 PackSize;\n  UInt64 NumFolders;\n  UInt64 NumFiles;\n  UInt64 NumAltStreams;\n  // **************** 7-Zip ZS Modification Start ****************\n  FString FirstExtractedPath;\n  // **************** 7-Zip ZS Modification End ****************\n  // **************** NanaZip Modification Start ****************\n  FString OutDir;\n  // **************** NanaZip Modification End ****************\n\n  void Clear()\n  {\n    NumArchives = UnpackSize = AltStreams_UnpackSize = PackSize = NumFolders = NumFiles = NumAltStreams = 0;\n    // **************** 7-Zip ZS Modification Start ****************\n    FirstExtractedPath.Empty();\n    // **************** 7-Zip ZS Modification End ****************\n    // **************** NanaZip Modification Start ****************\n    OutDir.Empty();\n    // **************** NanaZip Modification End ****************\n  }\n};\n\nHRESULT Extract(\n    // DECL_EXTERNAL_CODECS_LOC_VARS\n    CCodecs *codecs,\n    const CObjectVector<COpenType> &types,\n    const CIntVector &excludedFormats,\n    UStringVector &archivePaths, UStringVector &archivePathsFull,\n    const NWildcard::CCensorNode &wildcardCensor,\n    const CExtractOptions &options,\n    IOpenCallbackUI *openCallback,\n    IExtractCallbackUI *extractCallback,\n    IFolderArchiveExtractCallback *faeCallback,\n    #ifndef Z7_SFX\n    IHashCalc *hash,\n    #endif\n    UString &errorMessage,\n    CDecompressStat &st);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ExtractMode.h",
    "content": "﻿// ExtractMode.h\n\n#ifndef ZIP7_INC_EXTRACT_MODE_H\n#define ZIP7_INC_EXTRACT_MODE_H\n\nnamespace NExtract {\n  \nnamespace NPathMode\n{\n  enum EEnum\n  {\n    kFullPaths,\n    kCurPaths,\n    kNoPaths,\n    kAbsPaths,\n    kNoPathsAlt // alt streams must be extracted without name of base file\n  };\n}\n\nnamespace NOverwriteMode\n{\n  enum EEnum\n  {\n    kAsk,\n    kOverwrite,\n    kSkip,\n    kRename,\n    kRenameExisting\n  };\n}\n\nnamespace NZoneIdMode\n{\n  enum EEnum\n  {\n    kNone,\n    kAll,\n    kOffice\n  };\n\n  // **************** NanaZip Modification Start ****************\n  static inline const EEnum Default = kAll;\n  // **************** NanaZip Modification End ****************\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ExtractingFilePath.cpp",
    "content": "﻿// ExtractingFilePath.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/FileName.h\"\n\n#include \"ExtractingFilePath.h\"\n\nextern\nbool g_PathTrailReplaceMode;\nbool g_PathTrailReplaceMode =\n    #ifdef _WIN32\n      true\n    #else\n      false\n    #endif\n    ;\n\n\n#ifdef _WIN32\nstatic void ReplaceIncorrectChars(UString &s)\n{\n  {\n    for (unsigned i = 0; i < s.Len(); i++)\n    {\n      wchar_t c = s[i];\n      if (\n          #ifdef _WIN32\n          c == ':' || c == '*' || c == '?' || c < 0x20 || c == '<' || c == '>' || c == '|' || c == '\"'\n          || c == '/'\n          // || c == 0x202E // RLO\n          ||\n          #endif\n          c == WCHAR_PATH_SEPARATOR)\n      {\n       #if WCHAR_PATH_SEPARATOR != L'/'\n        // 22.00 : WSL replacement for backslash\n        if (c == WCHAR_PATH_SEPARATOR)\n          c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT;\n        else\n       #endif\n          c = '_';\n        s.ReplaceOneCharAtPos(i,\n          c\n          // (wchar_t)(0xf000 + c) // 21.02 debug: WSL encoding for unsupported characters\n          );\n      }\n    }\n  }\n  \n  if (g_PathTrailReplaceMode)\n  {\n    /*\n    // if (g_PathTrailReplaceMode == 1)\n    {\n      if (!s.IsEmpty())\n      {\n        wchar_t c = s.Back();\n        if (c == '.' || c == ' ')\n        {\n          // s += (wchar_t)(0x9c); // STRING TERMINATOR\n          s += (wchar_t)'_';\n        }\n      }\n    }\n    else\n    */\n    {\n      unsigned i;\n      for (i = s.Len(); i != 0;)\n      {\n        wchar_t c = s[i - 1];\n        if (c != '.' && c != ' ')\n          break;\n        i--;\n        s.ReplaceOneCharAtPos(i, '_');\n        // s.ReplaceOneCharAtPos(i, (c == ' ' ? (wchar_t)(0x2423) : (wchar_t)0x00B7));\n      }\n      /*\n      if (g_PathTrailReplaceMode > 1 && i != s.Len())\n      {\n        s.DeleteFrom(i);\n      }\n      */\n    }\n  }\n}\n#endif\n\n/* WinXP-64 doesn't support ':', '\\\\' and '/' symbols in name of alt stream.\n   But colon in postfix \":$DATA\" is allowed.\n   WIN32 functions don't allow empty alt stream name \"name:\" */\n\nvoid Correct_AltStream_Name(UString &s)\n{\n  unsigned len = s.Len();\n  const unsigned kPostfixSize = 6;\n  if (s.Len() >= kPostfixSize\n      && StringsAreEqualNoCase_Ascii(s.RightPtr(kPostfixSize), \":$DATA\"))\n    len -= kPostfixSize;\n  for (unsigned i = 0; i < len; i++)\n  {\n    wchar_t c = s[i];\n    if (c == ':' || c == '\\\\' || c == '/'\n        || c == 0x202E // RLO\n        )\n      s.ReplaceOneCharAtPos(i, '_');\n  }\n  if (s.IsEmpty())\n    s = '_';\n}\n\n#ifdef _WIN32\n\nstatic const unsigned g_ReservedWithNum_Index = 4;\n\nstatic const char * const g_ReservedNames[] =\n{\n  \"CON\", \"PRN\", \"AUX\", \"NUL\",\n  \"COM\", \"LPT\"\n};\n\nstatic bool IsSupportedName(const UString &name)\n{\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_ReservedNames); i++)\n  {\n    const char *reservedName = g_ReservedNames[i];\n    unsigned len = MyStringLen(reservedName);\n    if (name.Len() < len)\n      continue;\n    if (!name.IsPrefixedBy_Ascii_NoCase(reservedName))\n      continue;\n    if (i >= g_ReservedWithNum_Index)\n    {\n      wchar_t c = name[len];\n      if (c < L'0' || c > L'9')\n        continue;\n      len++;\n    }\n    for (;;)\n    {\n      wchar_t c = name[len++];\n      if (c == 0 || c == '.')\n        return false;\n      if (c != ' ')\n        break;\n    }\n  }\n  return true;\n}\n\nstatic void CorrectUnsupportedName(UString &name)\n{\n  if (!IsSupportedName(name))\n    name.InsertAtFront(L'_');\n}\n\n#endif\n\nstatic void Correct_PathPart(UString &s)\n{\n  // \".\" and \"..\"\n  if (s.IsEmpty())\n    return;\n\n  if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))\n    s.Empty();\n  #ifdef _WIN32\n  else\n    ReplaceIncorrectChars(s);\n  #endif\n}\n\n// static const char * const k_EmptyReplaceName = \"[]\";\nstatic const char k_EmptyReplaceName = '_';\n\nUString Get_Correct_FsFile_Name(const UString &name)\n{\n  UString res = name;\n  Correct_PathPart(res);\n  \n  #ifdef _WIN32\n  CorrectUnsupportedName(res);\n  #endif\n  \n  if (res.IsEmpty())\n    res = k_EmptyReplaceName;\n  return res;\n}\n\n\nvoid Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir)\n{\n  unsigned i = 0;\n\n  if (absIsAllowed)\n  {\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    bool isDrive = false;\n    #endif\n    \n    if (parts[0].IsEmpty())\n    {\n      i = 1;\n      #if defined(_WIN32) && !defined(UNDER_CE)\n      if (parts.Size() > 1 && parts[1].IsEmpty())\n      {\n        i = 2;\n        if (parts.Size() > 2 && parts[2].IsEqualTo(\"?\"))\n        {\n          i = 3;\n          if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3]))\n          {\n            isDrive = true;\n            i = 4;\n          }\n        }\n      }\n      #endif\n    }\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    else if (NWindows::NFile::NName::IsDrivePath2(parts[0]))\n    {\n      isDrive = true;\n      i = 1;\n    }\n\n    if (isDrive)\n    {\n      // we convert \"c:name\" to \"c:\\name\", if absIsAllowed path.\n      UString &ds = parts[i - 1];\n      if (ds.Len() > 2)\n      {\n        parts.Insert(i, ds.Ptr(2));\n        ds.DeleteFrom(2);\n      }\n    }\n    #endif\n  }\n\n  if (i != 0)\n    keepAndReplaceEmptyPrefixes = false;\n\n  for (; i < parts.Size();)\n  {\n    UString &s = parts[i];\n\n    Correct_PathPart(s);\n\n    if (s.IsEmpty())\n    {\n      if (!keepAndReplaceEmptyPrefixes)\n        if (isDir || i != parts.Size() - 1)\n        {\n          parts.Delete(i);\n          continue;\n        }\n      s = k_EmptyReplaceName;\n    }\n    else\n    {\n      keepAndReplaceEmptyPrefixes = false;\n      #ifdef _WIN32\n      CorrectUnsupportedName(s);\n      #endif\n    }\n    \n    i++;\n  }\n\n  if (!isDir)\n  {\n    if (parts.IsEmpty())\n      parts.Add((UString)k_EmptyReplaceName);\n    else\n    {\n      UString &s = parts.Back();\n      if (s.IsEmpty())\n        s = k_EmptyReplaceName;\n    }\n  }\n}\n\nUString MakePathFromParts(const UStringVector &parts)\n{\n  UString s;\n  FOR_VECTOR (i, parts)\n  {\n    if (i != 0)\n      s.Add_PathSepar();\n    s += parts[i];\n  }\n  return s;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ExtractingFilePath.h",
    "content": "﻿// ExtractingFilePath.h\n\n#ifndef ZIP7_INC_EXTRACTING_FILE_PATH_H\n#define ZIP7_INC_EXTRACTING_FILE_PATH_H\n\n#include \"../../../Common/MyString.h\"\n\n// #ifdef _WIN32\nvoid Correct_AltStream_Name(UString &s);\n// #endif\n\n// replaces unsuported characters, and replaces \".\" , \"..\" and \"\" to \"[]\"\nUString Get_Correct_FsFile_Name(const UString &name);\n\n/*\n  Correct_FsPath() corrects path parts to prepare it for File System operations.\n  It also corrects empty path parts like \"\\\\\\\\\":\n    - frontal empty path parts : it removes them or changes them to \"_\"\n    - another empty path parts : it removes them\n  if (absIsAllowed && path is absolute)  : it removes empty path parts after start absolute path prefix marker\n  else\n  {\n    if (!keepAndReplaceEmptyPrefixes) : it removes empty path parts\n    if ( keepAndReplaceEmptyPrefixes) : it changes each empty frontal path part to \"_\"\n  }\n*/\nvoid Correct_FsPath(bool absIsAllowed, bool keepAndReplaceEmptyPrefixes, UStringVector &parts, bool isDir);\n\nUString MakePathFromParts(const UStringVector &parts);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/HashCalc.h",
    "content": "﻿// HashCalc.h\n\n#ifndef ZIP7_INC_HASH_CALC_H\n#define ZIP7_INC_HASH_CALC_H\n\n#include \"../../../Common/UTFConvert.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../Common/CreateCoder.h\"\n#include \"../../Common/MethodProps.h\"\n\n#include \"DirItem.h\"\n#include \"IFileExtractCallback.h\"\n\nconst unsigned k_HashCalc_DigestSize_Max = 64;\nconst unsigned k_HashCalc_ExtraSize = 8;\nconst unsigned k_HashCalc_NumGroups = 4;\n\n/*\n  if (size <= 8) : upper case : reversed byte order : it shows 32-bit/64-bit number, if data contains little-endian number\n  if (size >  8) : lower case : original byte order (as big-endian byte sequence)\n*/\nvoid HashHexToString(char *dest, const Byte *data, size_t size);\n\nenum\n{\n  k_HashCalc_Index_Current,\n  k_HashCalc_Index_DataSum,\n  k_HashCalc_Index_NamesSum,\n  k_HashCalc_Index_StreamsSum\n};\n\nstruct CHasherState\n{\n  CMyComPtr<IHasher> Hasher;\n  AString Name;\n  UInt32 DigestSize;\n  UInt64 NumSums[k_HashCalc_NumGroups];\n  Byte Digests[k_HashCalc_NumGroups][k_HashCalc_DigestSize_Max + k_HashCalc_ExtraSize];\n\n  void InitDigestGroup(unsigned groupIndex)\n  {\n    NumSums[groupIndex] = 0;\n    memset(Digests[groupIndex], 0, sizeof(Digests[groupIndex]));\n  }\n\n  const Byte *GetExtraData_for_Group(unsigned groupIndex) const\n  {\n    return Digests[groupIndex] + k_HashCalc_DigestSize_Max;\n  }\n\n  unsigned GetNumExtraBytes_for_Group(unsigned groupIndex) const\n  {\n    const Byte *p = GetExtraData_for_Group(groupIndex);\n    // we use little-endian to read extra bytes\n    for (unsigned i = k_HashCalc_ExtraSize; i != 0; i--)\n      if (p[i - 1] != 0)\n        return i;\n    return 0;\n  }\n\n  void AddDigest(unsigned groupIndex, const Byte *data);\n\n  void WriteToString(unsigned digestIndex, char *s) const;\n};\n\n\nZ7_PURE_INTERFACES_BEGIN\n\n\nDECLARE_INTERFACE(IHashCalc)\n{\n  virtual void InitForNewFile() = 0;\n  virtual void Update(const void *data, UInt32 size) = 0;\n  virtual void SetSize(UInt64 size) = 0;\n  virtual void Final(bool isDir, bool isAltStream, const UString &path) = 0;\n};\n\nZ7_PURE_INTERFACES_END\n\nstruct CHashBundle Z7_final: public IHashCalc\n{\n  CObjectVector<CHasherState> Hashers;\n\n  UInt64 NumDirs;\n  UInt64 NumFiles;\n  UInt64 NumAltStreams;\n  UInt64 FilesSize;\n  UInt64 AltStreamsSize;\n  UInt64 NumErrors;\n\n  UInt64 CurSize;\n\n  UString MainName;\n  UString FirstFileName;\n\n  HRESULT SetMethods(DECL_EXTERNAL_CODECS_LOC_VARS const UStringVector &methods);\n  \n  // void Init() {}\n  CHashBundle()\n  {\n    NumDirs = NumFiles = NumAltStreams = FilesSize = AltStreamsSize = NumErrors = 0;\n  }\n\n  void InitForNewFile() Z7_override;\n  void Update(const void *data, UInt32 size) Z7_override;\n  void SetSize(UInt64 size) Z7_override;\n  void Final(bool isDir, bool isAltStream, const UString &path) Z7_override;\n};\n\nZ7_PURE_INTERFACES_BEGIN\n\n// INTERFACE_IDirItemsCallback(x)\n\n#define Z7_IFACEN_IHashCallbackUI(x) \\\n  virtual HRESULT StartScanning() x \\\n  virtual HRESULT FinishScanning(const CDirItemsStat &st) x \\\n  virtual HRESULT SetNumFiles(UInt64 numFiles) x \\\n  virtual HRESULT SetTotal(UInt64 size) x \\\n  virtual HRESULT SetCompleted(const UInt64 *completeValue) x \\\n  virtual HRESULT CheckBreak() x \\\n  virtual HRESULT BeforeFirstFile(const CHashBundle &hb) x \\\n  virtual HRESULT GetStream(const wchar_t *name, bool isFolder) x \\\n  virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x \\\n  virtual HRESULT SetOperationResult(UInt64 fileSize, const CHashBundle &hb, bool showHash) x \\\n  virtual HRESULT AfterLastFile(CHashBundle &hb) x \\\n\nZ7_IFACE_DECL_PURE_(IHashCallbackUI, IDirItemsCallback)\n\nZ7_PURE_INTERFACES_END\n\n\nstruct CHashOptionsLocal\n{\n  CBoolPair HashMode_Zero;\n  CBoolPair HashMode_Tag;\n  CBoolPair HashMode_Dirs;\n  CBoolPair HashMode_OnlyHash;\n  \n  void Init_HashOptionsLocal()\n  {\n    HashMode_Zero.Init();\n    HashMode_Tag.Init();\n    HashMode_Dirs.Init();\n    HashMode_OnlyHash.Init();\n    // HashMode_Dirs = true; // for debug\n  }\n\n  CHashOptionsLocal()\n  {\n    Init_HashOptionsLocal();\n  }\n  \n  bool ParseFlagCharOption(wchar_t c, bool val)\n  {\n    c = MyCharLower_Ascii(c);\n         if (c == 'z') HashMode_Zero.SetVal_as_Defined(val);\n    else if (c == 't') HashMode_Tag.SetVal_as_Defined(val);\n    else if (c == 'd') HashMode_Dirs.SetVal_as_Defined(val);\n    else if (c == 'h') HashMode_OnlyHash.SetVal_as_Defined(val);\n    else return false;\n    return true;\n  }\n\n  bool ParseString(const UString &s)\n  {\n    for (unsigned i = 0; i < s.Len();)\n    {\n      const wchar_t c = s[i++];\n      bool val = true;\n      if (i < s.Len())\n      {\n        const wchar_t next  = s[i];\n        if (next == '-')\n        {\n          val = false;\n          i++;\n        }\n      }\n      if (!ParseFlagCharOption(c, val))\n        return false;\n    }\n    return true;\n  }\n};\n\n\nstruct CHashOptions\n  // : public CHashOptionsLocal\n{\n  UStringVector Methods;\n  // UString HashFilePath;\n\n  bool PreserveATime;\n  bool OpenShareForWrite;\n  bool StdInMode;\n  bool AltStreamsMode;\n  CBoolPair SymLinks;\n\n  NWildcard::ECensorPathMode PathMode;\n\n  CHashOptions():\n      PreserveATime(false),\n      OpenShareForWrite(false),\n      StdInMode(false),\n      AltStreamsMode(false),\n      PathMode(NWildcard::k_RelatPath) {}\n};\n\n\nHRESULT HashCalc(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const NWildcard::CCensor &censor,\n    const CHashOptions &options,\n    AString &errorInfo,\n    IHashCallbackUI *callback);\n\n\n\n#ifndef Z7_SFX\n\nnamespace NHash {\n\nstruct CHashPair\n{\n  CByteBuffer Hash;\n  char Mode;\n  bool IsBSD;\n  bool Escape;\n  bool Size_from_Arc_Defined;\n  bool Size_from_Disk_Defined;\n  AString Method;\n  AString Name;\n  \n  AString FullLine;\n  AString HashString;\n  // unsigned HashLengthInBits;\n\n  // AString MethodName;\n  UInt64 Size_from_Arc;\n  UInt64 Size_from_Disk;\n\n  bool IsDir() const;\n\n  void Get_UString_Path(UString &path) const\n  {\n    path.Empty();\n    if (!ConvertUTF8ToUnicode(Name, path))\n      return;\n  }\n\n  bool ParseCksum(const char *s);\n  bool Parse(const char *s);\n\n  bool IsSupportedMode() const\n  {\n    return Mode != 'U' && Mode != '^';\n  }\n\n  CHashPair():\n      Mode(0)\n      , IsBSD(false)\n      , Escape(false)\n      , Size_from_Arc_Defined(false)\n      , Size_from_Disk_Defined(false)\n      // , HashLengthInBits(0)\n      , Size_from_Arc(0)\n      , Size_from_Disk(0)\n    {}\n};\n\n\nZ7_CLASS_IMP_CHandler_IInArchive_3(\n    IArchiveGetRawProps,\n    /* public IGetArchiveHashHandler, */\n    IOutArchive,\n    ISetProperties\n)\n  bool _isArc;\n  bool _supportWindowsBackslash;\n  bool _crcSize_WasSet;\n  bool _is_CksumMode;\n  bool _is_PgpMethod;\n  bool _is_ZeroMode;\n  bool _are_there_Tags;\n  bool _are_there_Dirs;\n  bool _is_KnownMethod_in_FileName;\n  bool _hashSize_Defined;\n  unsigned _hashSize;\n  UInt32 _crcSize;\n  UInt64 _phySize;\n  CObjectVector<CHashPair> HashPairs;\n  UStringVector _methods;\n  AString _method_from_FileName;\n  AString _pgpMethod;\n  AString _method_for_Extraction;\n  CHashOptionsLocal _options;\n\n  void ClearVars();\n  void InitProps();\n\n  bool CanUpdate() const\n  {\n    if (!_isArc || _is_PgpMethod || _is_CksumMode)\n      return false;\n    return true;\n  }\n\n  HRESULT SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value);\n\npublic:\n  CHandler();\n};\n\n}\n\nvoid Codecs_AddHashArcHandler(CCodecs *codecs);\n\n#endif\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/IFileExtractCallback.h",
    "content": "﻿// IFileExtractCallback.h\n\n#ifndef ZIP7_INC_I_FILE_EXTRACT_CALLBACK_H\n#define ZIP7_INC_I_FILE_EXTRACT_CALLBACK_H\n\n#include \"../../../Common/MyString.h\"\n\n#include \"../../IDecl.h\"\n\n#include \"LoadCodecs.h\"\n#include \"OpenArchive.h\"\n\nZ7_PURE_INTERFACES_BEGIN\n\n#define Z7_IFACE_CONSTR_FOLDERARC_SUB(i, base, n) \\\n  Z7_DECL_IFACE_7ZIP_SUB(i, base, 1, n) \\\n  { Z7_IFACE_COM7_PURE(i) };\n\n#define Z7_IFACE_CONSTR_FOLDERARC(i, n) \\\n        Z7_IFACE_CONSTR_FOLDERARC_SUB(i, IUnknown, n)\n\nnamespace NOverwriteAnswer\n{\n  enum EEnum\n  {\n    kYes,\n    kYesToAll,\n    kNo,\n    kNoToAll,\n    kAutoRename,\n    kCancel\n  };\n}\n\n\n/* ---------- IFolderArchiveExtractCallback ----------\nis implemented by\n  Console/ExtractCallbackConsole.h  CExtractCallbackConsole\n  FileManager/ExtractCallback.h     CExtractCallbackImp\n  FAR/ExtractEngine.cpp             CExtractCallBackImp: (QueryInterface is not supported)\n\nIID_IFolderArchiveExtractCallback is requested by:\n  - Agent/ArchiveFolder.cpp\n      CAgentFolder::CopyTo(..., IFolderOperationsExtractCallback *callback)\n      is sent to IArchiveFolder::Extract()\n\n  - FileManager/PanelCopy.cpp\n      CPanel::CopyTo(), if (options->testMode)\n      is sent to IArchiveFolder::Extract()\n\n IFolderArchiveExtractCallback is used by Common/ArchiveExtractCallback.cpp\n*/\n\n#define Z7_IFACEM_IFolderArchiveExtractCallback(x) \\\n  x(AskOverwrite( \\\n      const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize, \\\n      const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize, \\\n      Int32 *answer)) \\\n  x(PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position)) \\\n  x(MessageError(const wchar_t *message)) \\\n  x(SetOperationResult(Int32 opRes, Int32 encrypted)) \\\n\nZ7_IFACE_CONSTR_FOLDERARC_SUB(IFolderArchiveExtractCallback, IProgress, 0x07)\n\n#define Z7_IFACEM_IFolderArchiveExtractCallback2(x) \\\n  x(ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name)) \\\n\nZ7_IFACE_CONSTR_FOLDERARC(IFolderArchiveExtractCallback2, 0x08)\n\n/* ---------- IExtractCallbackUI ----------\nis implemented by\n  Console/ExtractCallbackConsole.h  CExtractCallbackConsole\n  FileManager/ExtractCallback.h     CExtractCallbackImp\n*/\n\n#ifdef Z7_NO_CRYPTO\n  #define Z7_IFACEM_IExtractCallbackUI_Crypto(px)\n#else\n  #define Z7_IFACEM_IExtractCallbackUI_Crypto(px) \\\n  virtual HRESULT SetPassword(const UString &password) px\n#endif\n\n#define Z7_IFACEN_IExtractCallbackUI(px) \\\n  virtual HRESULT BeforeOpen(const wchar_t *name, bool testMode) px \\\n  virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) px \\\n  virtual HRESULT ThereAreNoFiles() px \\\n  virtual HRESULT ExtractResult(HRESULT result) px \\\n  Z7_IFACEM_IExtractCallbackUI_Crypto(px)\n\n// IExtractCallbackUI - is non-COM interface\n// IFolderArchiveExtractCallback - is COM interface\n// Z7_IFACE_DECL_PURE_(IExtractCallbackUI, IFolderArchiveExtractCallback)\nZ7_IFACE_DECL_PURE(IExtractCallbackUI)\n\n\n\n#define Z7_IFACEM_IGetProp(x) \\\n  x(GetProp(PROPID propID, PROPVARIANT *value)) \\\n\nZ7_IFACE_CONSTR_FOLDERARC(IGetProp, 0x20)\n\n#define Z7_IFACEM_IFolderExtractToStreamCallback(x) \\\n  x(UseExtractToStream(Int32 *res)) \\\n  x(GetStream7(const wchar_t *name, Int32 isDir, ISequentialOutStream **outStream, Int32 askExtractMode, IGetProp *getProp)) \\\n  x(PrepareOperation7(Int32 askExtractMode)) \\\n  x(SetOperationResult8(Int32 resultEOperationResult, Int32 encrypted, UInt64 size)) \\\n\nZ7_IFACE_CONSTR_FOLDERARC(IFolderExtractToStreamCallback, 0x31)\n\nZ7_PURE_INTERFACES_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/LoadCodecs.cpp",
    "content": "﻿// LoadCodecs.cpp\n\n/*\nZ7_EXTERNAL_CODECS\n---------------\n  CCodecs::Load() tries to detect the directory with plugins.\n  It stops the checking, if it can find any of the following items:\n    - 7z.dll file\n    - \"Formats\" subdir\n    - \"Codecs\"  subdir\n  The order of check:\n    1) directory of client executable\n    2) WIN32: directory for REGISTRY item [HKEY_*\\Software\\7-Zip\\Path**]\n       The order for HKEY_* : Path** :\n         - HKEY_CURRENT_USER  : PathXX\n         - HKEY_LOCAL_MACHINE : PathXX\n         - HKEY_CURRENT_USER  : Path\n         - HKEY_LOCAL_MACHINE : Path\n       PathXX is Path32 in 32-bit code\n       PathXX is Path64 in 64-bit code\n\n\nEXPORT_CODECS\n-------------\n  if (Z7_EXTERNAL_CODECS) is defined, then the code exports internal\n  codecs of client from CCodecs object to external plugins.\n  7-Zip doesn't use that feature. 7-Zip uses the scheme:\n    - client application without internal plugins.\n    - 7z.dll module contains all (or almost all) plugins.\n      7z.dll can use codecs from another plugins, if required.\n*/\n\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/StringToInt.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/FileIO.h\"\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"LoadCodecs.h\"\n\n#include \"../../ICoder.h\"\n#include \"../../Common/RegisterArc.h\"\n#include \"../../Common/RegisterCodec.h\"\n\n// **************** NanaZip Modification Start ****************\n#include <Mile.Helpers.Base.h>\n\n#ifndef Z7_SFX\n#include <K7Base.h>\n#endif\n// **************** NanaZip Modification End ****************\n\n#ifdef Z7_EXTERNAL_CODECS\n// #define EXPORT_CODECS\n#endif\n\n#ifdef Z7_EXTERNAL_CODECS\n\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/DLL.h\"\n\n#ifdef _WIN32\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/Registry.h\"\n#endif\n\nusing namespace NWindows;\nusing namespace NFile;\n\n\n#define kCodecsFolderName FTEXT(\"Codecs\")\n#define kFormatsFolderName FTEXT(\"Formats\")\n\n// **************** NanaZip Modification Start ****************\n//static CFSTR const kMainDll =\n//  #ifdef _WIN32\n//    FTEXT(\"7z.dll\");\n//  #else\n//    FTEXT(\"7z.so\");\n//  #endif\nstatic CFSTR const kMainDll =\n  #ifdef _WIN32\n    FTEXT(\"NanaZip.Core.dll\");\n  #else\n    FTEXT(\"NanaZip.Core.so\");\n  #endif\n// **************** NanaZip Modification End ****************\n\n\n#ifdef _WIN32\n\n// **************** NanaZip Modification Start ****************\n//static LPCTSTR const kRegistryPath = TEXT(\"Software\") TEXT(STRING_PATH_SEPARATOR) TEXT(\"7-zip\");\nstatic LPCTSTR const kRegistryPath = TEXT(\"Software\") TEXT(STRING_PATH_SEPARATOR) TEXT(\"NanaZip\");\n// **************** NanaZip Modification End ****************\nstatic LPCWSTR const kProgramPathValue = L\"Path\";\nstatic LPCWSTR const kProgramPath2Value = L\"Path\"\n  #ifdef _WIN64\n  L\"64\";\n  #else\n  L\"32\";\n  #endif\n\nstatic bool ReadPathFromRegistry(HKEY baseKey, LPCWSTR value, FString &path)\n{\n  NRegistry::CKey key;\n  if (key.Open(baseKey, kRegistryPath, KEY_READ) == ERROR_SUCCESS)\n  {\n    UString pathU;\n    if (key.QueryValue(value, pathU) == ERROR_SUCCESS)\n    {\n      path = us2fs(pathU);\n      NName::NormalizeDirPathPrefix(path);\n      return NFind::DoesFileExist_Raw(path + kMainDll);\n    }\n  }\n  return false;\n}\n\n#endif // _WIN32\n\n#endif // Z7_EXTERNAL_CODECS\n\n\nstatic const unsigned kNumArcsMax = 72;\nstatic unsigned g_NumArcs = 0;\nstatic const CArcInfo *g_Arcs[kNumArcsMax];\n\nvoid RegisterArc(const CArcInfo *arcInfo) throw()\n{\n  if (g_NumArcs < kNumArcsMax)\n  {\n    g_Arcs[g_NumArcs] = arcInfo;\n    g_NumArcs++;\n  }\n  // else throw 1;\n}\n\n/*\nstatic void SplitString(const UString &srcString, UStringVector &destStrings)\n{\n  destStrings.Clear();\n  UString s;\n  unsigned len = srcString.Len();\n  if (len == 0)\n    return;\n  for (unsigned i = 0; i < len; i++)\n  {\n    wchar_t c = srcString[i];\n    if (c == L' ')\n    {\n      if (!s.IsEmpty())\n      {\n        destStrings.Add(s);\n        s.Empty();\n      }\n    }\n    else\n      s += c;\n  }\n  if (!s.IsEmpty())\n    destStrings.Add(s);\n}\n*/\n\nint CArcInfoEx::FindExtension(const UString &ext) const\n{\n  FOR_VECTOR (i, Exts)\n    if (ext.IsEqualTo_NoCase(Exts[i].Ext))\n      return (int)i;\n  return -1;\n}\n\nvoid CArcInfoEx::AddExts(const UString &ext, const UString &addExt)\n{\n  UStringVector exts, addExts;\n  SplitString(ext, exts);\n  SplitString(addExt, addExts);\n  FOR_VECTOR (i, exts)\n  {\n    CArcExtInfo extInfo;\n    extInfo.Ext = exts[i];\n    if (i < addExts.Size())\n    {\n      extInfo.AddExt = addExts[i];\n      if (extInfo.AddExt.IsEqualTo(\"*\"))\n        extInfo.AddExt.Empty();\n    }\n    Exts.Add(extInfo);\n  }\n}\n\n#ifndef Z7_SFX\n\nstatic bool ParseSignatures(const Byte *data, unsigned size, CObjectVector<CByteBuffer> &signatures)\n{\n  signatures.Clear();\n  while (size != 0)\n  {\n    const unsigned len = *data++;\n    size--;\n    if (len > size)\n      return false;\n    signatures.AddNew().CopyFrom(data, len);\n    data += len;\n    size -= len;\n  }\n  return true;\n}\n\n#endif // Z7_SFX\n\n// #include <stdio.h>\n\n#ifdef Z7_EXTERNAL_CODECS\n\nstatic FString GetBaseFolderPrefixFromRegistry()\n{\n  FString moduleFolderPrefix = NDLL::GetModuleDirPrefix();\n\n  #ifdef _WIN32\n  if (   !NFind::DoesFileOrDirExist(moduleFolderPrefix + kMainDll)\n      && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kCodecsFolderName)\n      && !NFind::DoesFileOrDirExist(moduleFolderPrefix + kFormatsFolderName))\n  {\n    FString path;\n    if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPath2Value, path)) return path;\n    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPath2Value, path)) return path;\n    if (ReadPathFromRegistry(HKEY_CURRENT_USER,  kProgramPathValue,  path)) return path;\n    if (ReadPathFromRegistry(HKEY_LOCAL_MACHINE, kProgramPathValue,  path)) return path;\n  }\n  #endif\n\n  // printf(\"\\nmoduleFolderPrefix = %s\\n\", (const char *)GetAnsiString(moduleFolderPrefix));\n  return moduleFolderPrefix;\n}\n\n\nstatic HRESULT GetCoderClass(Func_GetMethodProperty getMethodProperty, UInt32 index,\n    PROPID propId, CLSID &clsId, bool &isAssigned)\n{\n  NCOM::CPropVariant prop;\n  isAssigned = false;\n  RINOK(getMethodProperty(index, propId, &prop))\n  if (prop.vt == VT_BSTR)\n  {\n    if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))\n      return E_FAIL;\n    isAssigned = true;\n    clsId = *(const GUID *)(const void *)prop.bstrVal;\n  }\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\n\nstatic HRESULT GetMethodBoolProp(Func_GetMethodProperty getMethodProperty, UInt32 index,\n    PROPID propId, bool &resVal, bool &isAssigned)\n{\n  NCOM::CPropVariant prop;\n  resVal = false;\n  isAssigned = false;\n  RINOK(getMethodProperty(index, propId, &prop))\n  if (prop.vt == VT_BOOL)\n  {\n    isAssigned = true;\n    resVal = VARIANT_BOOLToBool(prop.boolVal);\n  }\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\n// **************** NanaZip Modification Start ****************\nstatic HRESULT GetMethodStringProp(\n    Func_GetMethodProperty GetMethodProperty,\n    UInt32 Index,\n    PROPID PropertyId,\n    UString &Result)\n{\n  NCOM::CPropVariant Property;\n  Result.Empty();\n  RINOK(GetMethodProperty(Index, PropertyId, &Property))\n  if (Property.vt == VT_BSTR)\n  {\n    Result.SetFromBstr(Property.bstrVal);\n  }\n  else if (Property.vt != VT_EMPTY)\n  {\n    return E_FAIL;\n  }\n  return S_OK;\n}\n// **************** NanaZip Modification End ****************\n\n#if defined(__clang__)\n#pragma GCC diagnostic ignored \"-Wc++98-compat-pedantic\"\n#endif\n\n#ifdef _WIN32\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n#endif\n\n#define MY_GET_FUNC(dest, type, lib, func)  \\\n  dest = Z7_GET_PROC_ADDRESS(type, lib.Get_HMODULE(), func);\n// #define MY_GET_FUNC(dest, type, func)  dest = (type)(func);\n\n#define MY_GET_FUNC_LOC(dest, type, lib, func) \\\n  type dest;  MY_GET_FUNC(dest, type, lib, func)\n\nHRESULT CCodecs::LoadCodecs()\n{\n  CCodecLib &lib = Libs.Back();\n\n  MY_GET_FUNC (lib.CreateDecoder,     Func_CreateDecoder,     lib.Lib, \"CreateDecoder\")\n  MY_GET_FUNC (lib.CreateEncoder,     Func_CreateEncoder,     lib.Lib, \"CreateEncoder\")\n  MY_GET_FUNC (lib.GetMethodProperty, Func_GetMethodProperty, lib.Lib, \"GetMethodProperty\")\n\n  if (lib.GetMethodProperty)\n  {\n    UInt32 numMethods = 1;\n    MY_GET_FUNC_LOC (getNumberOfMethods, Func_GetNumberOfMethods, lib.Lib, \"GetNumberOfMethods\")\n    if (getNumberOfMethods)\n    {\n      RINOK(getNumberOfMethods(&numMethods))\n    }\n    for (UInt32 i = 0; i < numMethods; i++)\n    {\n      CDllCodecInfo info;\n      info.LibIndex = Libs.Size() - 1;\n      info.CodecIndex = i;\n\n      // **************** NanaZip Modification Start ****************\n#ifndef Z7_SFX\n      UString CodecNameWide;\n      AString CodecName;\n      RINOK(GetMethodStringProp(lib.GetMethodProperty, i, NMethodPropID::kName, CodecNameWide))\n\n      CodecName.SetFromWStr_if_Ascii(CodecNameWide);\n\n      if (!::K7BaseGetAllowedCodecPolicy(CodecName))\n      {\n        continue;\n      }\n#endif\n      // **************** NanaZip Modification End ****************\n\n      RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned))\n      RINOK(GetCoderClass(lib.GetMethodProperty, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned))\n      RINOK(GetMethodBoolProp(lib.GetMethodProperty, i, NMethodPropID::kIsFilter, info.IsFilter, info.IsFilter_Assigned))\n      Codecs.Add(info);\n    }\n  }\n\n  MY_GET_FUNC_LOC (getHashers, Func_GetHashers, lib.Lib, \"GetHashers\")\n  if (getHashers)\n  {\n    RINOK(getHashers(&lib.ComHashers))\n    if (lib.ComHashers)\n    {\n      UInt32 numMethods = lib.ComHashers->GetNumHashers();\n      for (UInt32 i = 0; i < numMethods; i++)\n      {\n        CDllHasherInfo info;\n        info.LibIndex = Libs.Size() - 1;\n        info.HasherIndex = i;\n        Hashers.Add(info);\n      }\n    }\n  }\n\n  return S_OK;\n}\n\nstatic HRESULT GetProp(\n    Func_GetHandlerProperty getProp,\n    Func_GetHandlerProperty2 getProp2,\n    UInt32 index, PROPID propID, NCOM::CPropVariant &prop)\n{\n  if (getProp2)\n    return getProp2(index, propID, &prop);\n  return getProp(propID, &prop);\n}\n\nstatic HRESULT GetProp_Bool(\n    Func_GetHandlerProperty getProp,\n    Func_GetHandlerProperty2 getProp2,\n    UInt32 index, PROPID propID, bool &res)\n{\n  res = false;\n  NCOM::CPropVariant prop;\n  RINOK(GetProp(getProp, getProp2, index, propID, prop))\n  if (prop.vt == VT_BOOL)\n    res = VARIANT_BOOLToBool(prop.boolVal);\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\nstatic HRESULT GetProp_UInt32(\n    Func_GetHandlerProperty getProp,\n    Func_GetHandlerProperty2 getProp2,\n    UInt32 index, PROPID propID, UInt32 &res, bool &defined)\n{\n  res = 0;\n  defined = false;\n  NCOM::CPropVariant prop;\n  RINOK(GetProp(getProp, getProp2, index, propID, prop))\n  if (prop.vt == VT_UI4)\n  {\n    res = prop.ulVal;\n    defined = true;\n  }\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\nstatic HRESULT GetProp_String(\n    Func_GetHandlerProperty getProp,\n    Func_GetHandlerProperty2 getProp2,\n    UInt32 index, PROPID propID, UString &res)\n{\n  res.Empty();\n  NCOM::CPropVariant prop;\n  RINOK(GetProp(getProp, getProp2, index, propID, prop))\n  if (prop.vt == VT_BSTR)\n    res.SetFromBstr(prop.bstrVal);\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\nstatic HRESULT GetProp_RawData(\n    Func_GetHandlerProperty getProp,\n    Func_GetHandlerProperty2 getProp2,\n    UInt32 index, PROPID propID, CByteBuffer &bb)\n{\n  bb.Free();\n  NCOM::CPropVariant prop;\n  RINOK(GetProp(getProp, getProp2, index, propID, prop))\n  if (prop.vt == VT_BSTR)\n  {\n    UINT len = ::SysStringByteLen(prop.bstrVal);\n    bb.CopyFrom((const Byte *)prop.bstrVal, len);\n  }\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\nstatic const UInt32 kArcFlagsPars[] =\n{\n  NArchive::NHandlerPropID::kKeepName, NArcInfoFlags::kKeepName,\n  NArchive::NHandlerPropID::kAltStreams, NArcInfoFlags::kAltStreams,\n  NArchive::NHandlerPropID::kNtSecure, NArcInfoFlags::kNtSecure\n};\n\nHRESULT CCodecs::LoadFormats()\n{\n  const NDLL::CLibrary &lib = Libs.Back().Lib;\n\n  Func_GetHandlerProperty getProp = NULL;\n  MY_GET_FUNC_LOC (getProp2, Func_GetHandlerProperty2, lib, \"GetHandlerProperty2\")\n  MY_GET_FUNC_LOC (getIsArc, Func_GetIsArc, lib, \"GetIsArc\")\n  // **************** 7-Zip ZS Modification Start ****************\n  MY_GET_FUNC_LOC (getFormatLevelMask, Func_GetFormatLevelMask, lib, \"GetFormatLevelMask\");\n  // **************** 7-Zip ZS Modification End ****************\n\n  UInt32 numFormats = 1;\n\n  if (getProp2)\n  {\n    MY_GET_FUNC_LOC (getNumberOfFormats, Func_GetNumberOfFormats, lib, \"GetNumberOfFormats\")\n    if (getNumberOfFormats)\n    {\n      RINOK(getNumberOfFormats(&numFormats))\n    }\n  }\n  else\n  {\n    MY_GET_FUNC (getProp, Func_GetHandlerProperty, lib, \"GetHandlerProperty\")\n    if (!getProp)\n      return S_OK;\n  }\n\n  for (UInt32 i = 0; i < numFormats; i++)\n  {\n    CArcInfoEx item;\n    item.LibIndex = (int)(Libs.Size() - 1);\n    item.FormatIndex = i;\n\n    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kName, item.Name))\n\n    // **************** NanaZip Modification Start ****************\n#ifndef Z7_SFX\n    AString ItemName;\n    ItemName.SetFromWStr_if_Ascii(item.Name);\n\n    if (!::K7BaseGetAllowedHandlerPolicy(ItemName))\n    {\n      continue;\n    }\n#endif\n    // **************** NanaZip Modification End ****************\n\n    {\n      NCOM::CPropVariant prop;\n      if (GetProp(getProp, getProp2, i, NArchive::NHandlerPropID::kClassID, prop) != S_OK)\n        continue;\n      if (prop.vt != VT_BSTR)\n        continue;\n      if (::SysStringByteLen(prop.bstrVal) != sizeof(GUID))\n        return E_FAIL;\n      item.ClassID = *(const GUID *)(const void *)prop.bstrVal;\n      prop.Clear();\n    }\n\n    UString ext, addExt;\n    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kExtension, ext))\n    RINOK(GetProp_String(getProp, getProp2, i, NArchive::NHandlerPropID::kAddExtension, addExt))\n    item.AddExts(ext, addExt);\n\n    GetProp_Bool(getProp, getProp2, i, NArchive::NHandlerPropID::kUpdate, item.UpdateEnabled);\n    bool flags_Defined = false;\n    RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kFlags, item.Flags, flags_Defined))\n    item.NewInterface = flags_Defined;\n    if (!flags_Defined) // && item.UpdateEnabled\n    {\n      // support for DLL version before 9.31:\n      for (unsigned j = 0; j < Z7_ARRAY_SIZE(kArcFlagsPars); j += 2)\n      {\n        bool val = false;\n        GetProp_Bool(getProp, getProp2, i, kArcFlagsPars[j], val);\n        if (val)\n          item.Flags |= kArcFlagsPars[j + 1];\n      }\n    }\n\n    {\n      bool defined = false;\n      RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kTimeFlags, item.TimeFlags, defined))\n    }\n\n    CByteBuffer sig;\n    RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kSignature, sig))\n    if (sig.Size() != 0)\n      item.Signatures.Add(sig);\n    else\n    {\n      RINOK(GetProp_RawData(getProp, getProp2, i, NArchive::NHandlerPropID::kMultiSignature, sig))\n      ParseSignatures(sig, (unsigned)sig.Size(), item.Signatures);\n    }\n\n    bool signatureOffset_Defined;\n    RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kSignatureOffset, item.SignatureOffset, signatureOffset_Defined))\n\n    // bool version_Defined;\n    // RINOK(GetProp_UInt32(getProp, getProp2, i, NArchive::NHandlerPropID::kVersion, item.Version, version_Defined));\n\n    if (getIsArc)\n      getIsArc(i, &item.IsArcFunc);\n\n    // **************** 7-Zip ZS Modification Start ****************\n    if (getFormatLevelMask)\n      getFormatLevelMask(i, &item.LevelsMask);\n    // **************** 7-Zip ZS Modification End ****************\n\n    Formats.Add(item);\n  }\n  return S_OK;\n}\n\n#ifdef Z7_LARGE_PAGES\nextern \"C\"\n{\n  extern SIZE_T g_LargePageSize;\n}\n#endif\n\n\nvoid CCodecs::AddLastError(const FString &path)\n{\n  const HRESULT res = GetLastError_noZero_HRESULT();\n  CCodecError &error = Errors.AddNew();\n  error.Path = path;\n  error.ErrorCode = res;\n}\n\n\nstatic bool IsSupportedDll(CCodecLib &lib)\n{\n  MY_GET_FUNC_LOC (\n     f_GetModuleProp,\n  Func_GetModuleProp, lib.Lib,\n      \"GetModuleProp\")\n  /* p7zip and 7-Zip before v23 used virtual destructor in IUnknown,\n     if _WIN32 is not defined */\n  UInt32 flags =\n    #ifdef _WIN32\n      NModuleInterfaceType::k_IUnknown_VirtDestructor_No;\n    #else\n      NModuleInterfaceType::k_IUnknown_VirtDestructor_Yes;\n    #endif\n  if (f_GetModuleProp)\n  {\n    {\n      NCOM::CPropVariant prop;\n      if (f_GetModuleProp(NModulePropID::kInterfaceType, &prop) == S_OK)\n      {\n        if (prop.vt == VT_UI4)\n          flags = prop.ulVal;\n        else if (prop.vt != VT_EMPTY)\n          return false;\n      }\n    }\n    {\n      NCOM::CPropVariant prop;\n      if (f_GetModuleProp(NModulePropID::kVersion, &prop) == S_OK)\n      {\n        if (prop.vt == VT_UI4)\n          lib.Version = prop.ulVal;\n      }\n    }\n  }\n  if (\n      flags\n      // (flags & NModuleFlags::kMask)\n      != NModuleInterfaceType::k_IUnknown_VirtDestructor_ThisModule)\n    return false;\n  return true;\n}\n\n\nHRESULT CCodecs::LoadDll(const FString &dllPath, bool needCheckDll, bool *loadedOK)\n{\n  if (loadedOK)\n    *loadedOK = false;\n\n  // needCheckDll = 1;\n\n  #ifdef _WIN32\n  if (needCheckDll)\n  {\n    NDLL::CLibrary lib;\n    if (!lib.LoadEx(dllPath, LOAD_LIBRARY_AS_DATAFILE))\n    {\n      /* if is not win32\n      //  %1 is not a valid Win32 application.\n      //  #define ERROR_BAD_EXE_FORMAT             193L\n      */\n      // return GetLastError_noZero_HRESULT();\n      const DWORD lastError = GetLastError();\n      if (lastError != ERROR_BAD_EXE_FORMAT)\n      {\n        CCodecError &error = Errors.AddNew();\n        error.Path = dllPath;\n        error.Message = \"cannot load file as datafile library\";\n        error.ErrorCode = HRESULT_FROM_WIN32(lastError);\n      }\n      return S_OK;\n    }\n  }\n  #else\n  UNUSED_VAR(needCheckDll)\n  #endif\n\n  Libs.AddNew();\n  CCodecLib &lib = Libs.Back();\n  lib.Path = dllPath;\n  bool used = false;\n  // HRESULT res = S_OK;\n\n if (lib.Lib.Load(dllPath))\n {\n  if (!IsSupportedDll(lib))\n  {\n    CCodecError &error = Errors.AddNew();\n    error.Path = dllPath;\n    error.Message = \"the module is not compatible with program\";\n  }\n  else\n  {\n    if (loadedOK)\n      *loadedOK = true;\n    /*\n    #ifdef NEW_FOLDER_INTERFACE\n    lib.LoadIcons();\n    #endif\n    */\n\n    /*\n    {\n      MY_GET_FUNC_LOC (_libStartup, Func_libStartup, lib.Lib, \"LibStartup\")\n      if (_libStartup)\n      {\n        HRESULT res = _libStartup();\n        if (res != 0)\n        {\n          CCodecError &error = Errors.AddNew();\n          error.Path = dllPath;\n          error.ErrorCode = res;\n        }\n      }\n    }\n    */\n\n    #ifdef Z7_LARGE_PAGES\n    if (g_LargePageSize != 0)\n    {\n      MY_GET_FUNC_LOC (setLargePageMode, Func_SetLargePageMode, lib.Lib, \"SetLargePageMode\")\n      if (setLargePageMode)\n        setLargePageMode();\n    }\n    #endif\n\n    if (CaseSensitive_Change)\n    {\n      MY_GET_FUNC_LOC (setCaseSensitive, Func_SetCaseSensitive, lib.Lib, \"SetCaseSensitive\")\n      if (setCaseSensitive)\n        setCaseSensitive(CaseSensitive ? 1 : 0);\n    }\n\n    /*\n    {\n      MY_GET_FUNC_LOC (setClientVersion, Func_SetClientVersion, lib.Lib, \"SetClientVersion\")\n      if (setClientVersion)\n      {\n        // const UInt32 kVersion = (MY_VER_MAJOR << 16) | MY_VER_MINOR;\n        setClientVersion(g_ClientVersion);\n      }\n    }\n    */\n\n\n    MY_GET_FUNC (lib.CreateObject, Func_CreateObject, lib.Lib, \"CreateObject\")\n    {\n      unsigned startSize = Codecs.Size() + Hashers.Size();\n      HRESULT res = LoadCodecs();\n      if (startSize != Codecs.Size() + Hashers.Size())\n        used = true;\n      if (res == S_OK && lib.CreateObject)\n      {\n        startSize = Formats.Size();\n        res = LoadFormats();\n        if (startSize != Formats.Size())\n          used = true;\n      }\n      if (res != S_OK)\n      {\n        CCodecError &error = Errors.AddNew();\n        error.Path = dllPath;\n        error.ErrorCode = res;\n      }\n    }\n    // plugins can use non-7-zip dlls, so we silently ignore non7zip DLLs\n    /*\n    if (!used)\n    {\n      CCodecError &error = Errors.AddNew();\n      error.Path = dllPath;\n      error.Message = \"no 7-Zip code\";\n    }\n    */\n  }\n }\n else\n  {\n    AddLastError(dllPath);\n  }\n\n  if (!used)\n    Libs.DeleteBack();\n\n  return S_OK;\n}\n\nHRESULT CCodecs::LoadDllsFromFolder(const FString &folderPath)\n{\n  if (!NFile::NFind::DoesDirExist_FollowLink(folderPath))\n  // if (!NFile::NFind::DoesDirExist(folderPath))\n  {\n    // AddLastError(folderPath);\n    return S_OK;\n  }\n\n  FString folderPrefix = folderPath;\n  folderPrefix.Add_PathSepar();\n\n  NFile::NFind::CEnumerator enumerator;\n  enumerator.SetDirPrefix(folderPrefix);\n  NFile::NFind::CDirEntry fi;\n  for (;;)\n  {\n    bool found;\n    if (!enumerator.Next(fi, found))\n    {\n      // it can be wrong Symbolic link to folder here\n      AddLastError(folderPath);\n      break;\n      // return GetLastError_noZero_HRESULT();\n    }\n    if (!found)\n      break;\n    #ifdef _WIN32\n    if (fi.IsDir())\n      continue;\n    #else\n    if (enumerator.DirEntry_IsDir(fi, true)) // followLink\n      continue;\n    #endif\n\n    RINOK(LoadDll(folderPrefix + fi.Name, true))\n  }\n  return S_OK;\n}\n\nvoid CCodecs::CloseLibs()\n{\n  // OutputDebugStringA(\"~CloseLibs start\");\n  /*\n  WIN32: FreeLibrary() (CLibrary::Free()) function doesn't work as expected,\n  if it's called from another FreeLibrary() call.\n  So we need to call FreeLibrary() before global destructors.\n\n  Also we free global links from DLLs to object of this module before CLibrary::Free() call.\n  */\n\n  FOR_VECTOR(i, Libs)\n  {\n    const CCodecLib &lib = Libs[i];\n    if (lib.SetCodecs)\n      lib.SetCodecs(NULL);\n  }\n\n  // OutputDebugStringA(\"~CloseLibs after SetCodecs\");\n  Libs.Clear();\n  // OutputDebugStringA(\"~CloseLibs end\");\n}\n\n#endif // Z7_EXTERNAL_CODECS\n\n\nHRESULT CCodecs::Load()\n{\n  /*\n  #ifdef NEW_FOLDER_INTERFACE\n  InternalIcons.LoadIcons(g_hInstance);\n  #endif\n  */\n\n  Formats.Clear();\n\n  #ifdef Z7_EXTERNAL_CODECS\n    Errors.Clear();\n    MainDll_ErrorPath.Empty();\n    Codecs.Clear();\n    Hashers.Clear();\n  #endif\n\n  for (UInt32 i = 0; i < g_NumArcs; i++)\n  {\n    const CArcInfo &arc = *g_Arcs[i];\n    CArcInfoEx item;\n\n    item.Name = arc.Name;\n    item.CreateInArchive = arc.CreateInArchive;\n    item.IsArcFunc = arc.IsArc;\n    item.Flags = arc.Flags;\n\n    {\n      UString e, ae;\n      if (arc.Ext)\n        e = arc.Ext;\n      if (arc.AddExt)\n        ae = arc.AddExt;\n      item.AddExts(e, ae);\n    }\n\n    #ifndef Z7_SFX\n\n    // **************** NanaZip Modification Start ****************\n    if (!::K7BaseGetAllowedHandlerPolicy(arc.Name))\n    {\n      continue;\n    }\n    // **************** NanaZip Modification End ****************\n\n    item.CreateOutArchive = arc.CreateOutArchive;\n    item.UpdateEnabled = (arc.CreateOutArchive != NULL);\n    item.SignatureOffset = arc.SignatureOffset;\n    // item.Version = MY_VER_MIX;\n    item.NewInterface = true;\n\n    if (arc.IsMultiSignature())\n      ParseSignatures(arc.Signature, arc.SignatureSize, item.Signatures);\n    else\n    {\n      if (arc.SignatureSize != 0) // 21.04\n        item.Signatures.AddNew().CopyFrom(arc.Signature, arc.SignatureSize);\n    }\n\n    #endif\n\n    Formats.Add(item);\n  }\n\n  // printf(\"\\nLoad codecs \\n\");\n\n  #ifdef Z7_EXTERNAL_CODECS\n    const FString baseFolder = GetBaseFolderPrefixFromRegistry();\n    // **************** NanaZip Modification Start ****************\n    {\n      bool loadedOK;\n      RINOK(LoadDll(baseFolder + L\"NanaZip.Codecs.dll\", false, &loadedOK));\n      if (!loadedOK)\n        MainDll_ErrorPath = L\"NanaZip.Codecs.dll\";\n    }\n    // **************** NanaZip Modification End ****************\n    {\n      bool loadedOK;\n      RINOK(LoadDll(baseFolder + kMainDll, false, &loadedOK))\n      if (!loadedOK)\n        MainDll_ErrorPath = kMainDll;\n    }\n    RINOK(LoadDllsFromFolder(baseFolder + kCodecsFolderName))\n    RINOK(LoadDllsFromFolder(baseFolder + kFormatsFolderName))\n\n  NeedSetLibCodecs = true;\n\n  if (Libs.Size() == 0)\n    NeedSetLibCodecs = false;\n  else if (Libs.Size() == 1)\n  {\n    // we don't need to set ISetCompressCodecsInfo, if all arcs and codecs are in one external module.\n    #ifndef EXPORT_CODECS\n    if (g_NumArcs == 0)\n      NeedSetLibCodecs = false;\n    #endif\n  }\n\n  if (NeedSetLibCodecs)\n  {\n    /* 15.00: now we call global function in DLL: SetCompressCodecsInfo(c)\n       old versions called only ISetCompressCodecsInfo::SetCompressCodecsInfo(c) for each archive handler */\n\n    FOR_VECTOR(i, Libs)\n    {\n      CCodecLib &lib = Libs[i];\n      MY_GET_FUNC (lib.SetCodecs, Func_SetCodecs, lib.Lib, \"SetCodecs\")\n      if (lib.SetCodecs)\n      {\n        RINOK(lib.SetCodecs(this))\n      }\n    }\n  }\n\n  #endif\n\n  // we sort Formats to get fixed order of Formats after compilation.\n  Formats.Sort();\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\nint CCodecs::FindFormatForArchiveName(const UString &arcPath) const\n{\n  int dotPos = arcPath.ReverseFind_Dot();\n  if (dotPos <= arcPath.ReverseFind_PathSepar())\n    return -1;\n  const UString ext = arcPath.Ptr((unsigned)(dotPos + 1));\n  if (ext.IsEmpty())\n    return -1;\n  if (ext.IsEqualTo_Ascii_NoCase(\"exe\"))\n    return -1;\n  FOR_VECTOR (i, Formats)\n  {\n    const CArcInfoEx &arc = Formats[i];\n    /*\n    if (!arc.UpdateEnabled)\n      continue;\n    */\n    if (arc.FindExtension(ext) >= 0)\n      return (int)i;\n  }\n  return -1;\n}\n\nint CCodecs::FindFormatForExtension(const UString &ext) const\n{\n  if (ext.IsEmpty())\n    return -1;\n  FOR_VECTOR (i, Formats)\n    if (Formats[i].FindExtension(ext) >= 0)\n      return (int)i;\n  return -1;\n}\n\nint CCodecs::FindFormatForArchiveType(const UString &arcType) const\n{\n  FOR_VECTOR (i, Formats)\n    if (Formats[i].Name.IsEqualTo_NoCase(arcType))\n      return (int)i;\n  return -1;\n}\n\nbool CCodecs::FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const\n{\n  formatIndices.Clear();\n  for (unsigned pos = 0; pos < arcType.Len();)\n  {\n    int pos2 = arcType.Find(L'.', pos);\n    if (pos2 < 0)\n      pos2 = (int)arcType.Len();\n    const UString name = arcType.Mid(pos, (unsigned)pos2 - pos);\n    if (name.IsEmpty())\n      return false;\n    const int index = FindFormatForArchiveType(name);\n    if (index < 0 && !name.IsEqualTo(\"*\"))\n    {\n      formatIndices.Clear();\n      return false;\n    }\n    formatIndices.Add(index);\n    pos = (unsigned)pos2 + 1;\n  }\n  return true;\n}\n\n#endif // Z7_SFX\n\n\n#ifdef Z7_EXTERNAL_CODECS\n\n// #define EXPORT_CODECS\n\n#ifdef EXPORT_CODECS\n\nextern unsigned g_NumCodecs;\nSTDAPI CreateDecoder(UInt32 index, const GUID *iid, void **outObject);\nSTDAPI CreateEncoder(UInt32 index, const GUID *iid, void **outObject);\nSTDAPI GetMethodProperty(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);\n#define NUM_EXPORT_CODECS g_NumCodecs\n\nextern unsigned g_NumHashers;\nSTDAPI CreateHasher(UInt32 index, IHasher **hasher);\nSTDAPI GetHasherProp(UInt32 codecIndex, PROPID propID, PROPVARIANT *value);\n#define NUM_EXPORT_HASHERS g_NumHashers\n\n#else // EXPORT_CODECS\n\n#define NUM_EXPORT_CODECS 0\n#define NUM_EXPORT_HASHERS 0\n\n#endif // EXPORT_CODECS\n\nZ7_COM7F_IMF(CCodecs::GetNumMethods(UInt32 *numMethods))\n{\n  *numMethods = NUM_EXPORT_CODECS\n    #ifdef Z7_EXTERNAL_CODECS\n    + Codecs.Size()\n    #endif\n    ;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CCodecs::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumCodecs)\n    return GetMethodProperty(index, propID, value);\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];\n\n  if (propID == NMethodPropID::kDecoderIsAssigned ||\n      propID == NMethodPropID::kEncoderIsAssigned)\n  {\n    NCOM::CPropVariant prop;\n    prop = (bool)((propID == NMethodPropID::kDecoderIsAssigned) ?\n        ci.DecoderIsAssigned :\n        ci.EncoderIsAssigned);\n    prop.Detach(value);\n    return S_OK;\n  }\n\n  if (propID == NMethodPropID::kIsFilter && ci.IsFilter_Assigned)\n  {\n    NCOM::CPropVariant prop;\n    prop = (bool)ci.IsFilter;\n    prop.Detach(value);\n    return S_OK;\n  }\n\n  const CCodecLib &lib = Libs[ci.LibIndex];\n  return lib.GetMethodProperty(ci.CodecIndex, propID, value);\n  #else\n  return E_FAIL;\n  #endif\n}\n\nZ7_COM7F_IMF(CCodecs::CreateDecoder(UInt32 index, const GUID *iid, void **coder))\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumCodecs)\n    return CreateDecoder(index, iid, coder);\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];\n  if (ci.DecoderIsAssigned)\n  {\n    const CCodecLib &lib = Libs[ci.LibIndex];\n    if (lib.CreateDecoder)\n      return lib.CreateDecoder(ci.CodecIndex, iid, (void **)coder);\n    if (lib.CreateObject)\n      return lib.CreateObject(&ci.Decoder, iid, (void **)coder);\n  }\n  return S_OK;\n  #else\n  return E_FAIL;\n  #endif\n}\n\nZ7_COM7F_IMF(CCodecs::CreateEncoder(UInt32 index, const GUID *iid, void **coder))\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumCodecs)\n    return CreateEncoder(index, iid, coder);\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];\n  if (ci.EncoderIsAssigned)\n  {\n    const CCodecLib &lib = Libs[ci.LibIndex];\n    if (lib.CreateEncoder)\n      return lib.CreateEncoder(ci.CodecIndex, iid, (void **)coder);\n    if (lib.CreateObject)\n      return lib.CreateObject(&ci.Encoder, iid, (void **)coder);\n  }\n  return S_OK;\n  #else\n  return E_FAIL;\n  #endif\n}\n\n\nZ7_COM7F_IMF2(UInt32, CCodecs::GetNumHashers())\n{\n  return NUM_EXPORT_HASHERS\n    #ifdef Z7_EXTERNAL_CODECS\n    + Hashers.Size()\n    #endif\n    ;\n}\n\nZ7_COM7F_IMF(CCodecs::GetHasherProp(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumHashers)\n    return ::GetHasherProp(index, propID, value);\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];\n  return Libs[ci.LibIndex].ComHashers->GetHasherProp(ci.HasherIndex, propID, value);\n  #else\n  return E_FAIL;\n  #endif\n}\n\nZ7_COM7F_IMF(CCodecs::CreateHasher(UInt32 index, IHasher **hasher))\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumHashers)\n    return CreateHasher(index, hasher);\n  #endif\n  #ifdef Z7_EXTERNAL_CODECS\n  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];\n  return Libs[ci.LibIndex].ComHashers->CreateHasher(ci.HasherIndex, hasher);\n  #else\n  return E_FAIL;\n  #endif\n}\n\nint CCodecs::GetCodec_LibIndex(UInt32 index) const\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumCodecs)\n    return -1;\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  const CDllCodecInfo &ci = Codecs[index - NUM_EXPORT_CODECS];\n  return (int)ci.LibIndex;\n  #else\n  return -1;\n  #endif\n}\n\nint CCodecs::GetHasherLibIndex(UInt32 index)\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumHashers)\n    return -1;\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  const CDllHasherInfo &ci = Hashers[index - NUM_EXPORT_HASHERS];\n  return (int)ci.LibIndex;\n  #else\n  return -1;\n  #endif\n}\n\nbool CCodecs::GetCodec_DecoderIsAssigned(UInt32 index) const\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumCodecs)\n  {\n    NCOM::CPropVariant prop;\n    if (GetProperty(index, NMethodPropID::kDecoderIsAssigned, &prop) == S_OK)\n    {\n      if (prop.vt == VT_BOOL)\n        return VARIANT_BOOLToBool(prop.boolVal);\n    }\n    return false;\n  }\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  return Codecs[index - NUM_EXPORT_CODECS].DecoderIsAssigned;\n  #else\n  return false;\n  #endif\n}\n\n\nbool CCodecs::GetCodec_EncoderIsAssigned(UInt32 index) const\n{\n  #ifdef EXPORT_CODECS\n  if (index < g_NumCodecs)\n  {\n    NCOM::CPropVariant prop;\n    if (GetProperty(index, NMethodPropID::kEncoderIsAssigned, &prop) == S_OK)\n    {\n      if (prop.vt == VT_BOOL)\n        return VARIANT_BOOLToBool(prop.boolVal);\n    }\n    return false;\n  }\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  return Codecs[index - NUM_EXPORT_CODECS].EncoderIsAssigned;\n  #else\n  return false;\n  #endif\n}\n\n\nbool CCodecs::GetCodec_IsFilter(UInt32 index, bool &isAssigned) const\n{\n  isAssigned = false;\n  #ifdef EXPORT_CODECS\n  if (index < g_NumCodecs)\n  {\n    NCOM::CPropVariant prop;\n    if (GetProperty(index, NMethodPropID::kIsFilter, &prop) == S_OK)\n    {\n      if (prop.vt == VT_BOOL)\n      {\n        isAssigned = true;\n        return VARIANT_BOOLToBool(prop.boolVal);\n      }\n    }\n    return false;\n  }\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n  {\n    const CDllCodecInfo &c = Codecs[index - NUM_EXPORT_CODECS];\n    isAssigned = c.IsFilter_Assigned;\n    return c.IsFilter;\n  }\n  #else\n  return false;\n  #endif\n}\n\n\nUInt32 CCodecs::GetCodec_NumStreams(UInt32 index)\n{\n  NCOM::CPropVariant prop;\n  if (GetProperty(index, NMethodPropID::kPackStreams, &prop) != S_OK)\n    return 0;\n  if (prop.vt == VT_UI4)\n    return (UInt32)prop.ulVal;\n  if (prop.vt == VT_EMPTY)\n    return 1;\n  return 0;\n}\n\nHRESULT CCodecs::GetCodec_Id(UInt32 index, UInt64 &id)\n{\n  NCOM::CPropVariant prop;\n  RINOK(GetProperty(index, NMethodPropID::kID, &prop))\n  if (prop.vt != VT_UI8)\n    return E_INVALIDARG;\n  id = prop.uhVal.QuadPart;\n  return S_OK;\n}\n\nAString CCodecs::GetCodec_Name(UInt32 index)\n{\n  AString s;\n  NCOM::CPropVariant prop;\n  if (GetProperty(index, NMethodPropID::kName, &prop) == S_OK)\n    if (prop.vt == VT_BSTR)\n      s.SetFromWStr_if_Ascii(prop.bstrVal);\n  return s;\n}\n\nUInt64 CCodecs::GetHasherId(UInt32 index)\n{\n  NCOM::CPropVariant prop;\n  if (GetHasherProp(index, NMethodPropID::kID, &prop) != S_OK)\n    return 0;\n  if (prop.vt != VT_UI8)\n    return 0;\n  return prop.uhVal.QuadPart;\n}\n\nAString CCodecs::GetHasherName(UInt32 index)\n{\n  AString s;\n  NCOM::CPropVariant prop;\n  if (GetHasherProp(index, NMethodPropID::kName, &prop) == S_OK)\n    if (prop.vt == VT_BSTR)\n      s.SetFromWStr_if_Ascii(prop.bstrVal);\n  return s;\n}\n\nUInt32 CCodecs::GetHasherDigestSize(UInt32 index)\n{\n  NCOM::CPropVariant prop;\n  if (GetHasherProp(index, NMethodPropID::kDigestSize, &prop) != S_OK)\n    return 0;\n  if (prop.vt != VT_UI4)\n    return 0;\n  return prop.ulVal;\n}\n\nvoid CCodecs::GetCodecsErrorMessage(UString &s)\n{\n  s.Empty();\n  FOR_VECTOR (i, Errors)\n  {\n    const CCodecError &ce = Errors[i];\n    s += \"Codec Load Error: \";\n    s += fs2us(ce.Path);\n    if (ce.ErrorCode != 0)\n    {\n      s += \" : \";\n      s += NWindows::NError::MyFormatMessage(ce.ErrorCode);\n    }\n    if (!ce.Message.IsEmpty())\n    {\n      s += \" : \";\n      s += ce.Message;\n    }\n    s.Add_LF();\n  }\n}\n\n#endif // Z7_EXTERNAL_CODECS\n\n#ifndef Z7_SFX\n\nextern unsigned g_NumCodecs;\nextern const CCodecInfo *g_Codecs[];\n\nvoid CCodecs::Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v)\n{\n  v.Clear();\n  {\n    for (unsigned i = 0; i < g_NumCodecs; i++)\n    {\n      const CCodecInfo &cod = *g_Codecs[i];\n      CCodecInfoUser &u = v.AddNew();\n      u.EncoderIsAssigned = (cod.CreateEncoder != NULL);\n      u.DecoderIsAssigned = (cod.CreateDecoder != NULL);\n      u.IsFilter_Assigned = true;\n      u.IsFilter = cod.IsFilter;\n      u.NumStreams = cod.NumStreams;\n      u.Name = cod.Name;\n    }\n  }\n\n\n  #ifdef Z7_EXTERNAL_CODECS\n  {\n    UInt32 numMethods;\n    if (GetNumMethods(&numMethods) == S_OK)\n    for (UInt32 j = 0; j < numMethods; j++)\n    {\n      CCodecInfoUser &u = v.AddNew();\n      u.EncoderIsAssigned = GetCodec_EncoderIsAssigned(j);\n      u.DecoderIsAssigned = GetCodec_DecoderIsAssigned(j);\n      u.IsFilter = GetCodec_IsFilter(j, u.IsFilter_Assigned);\n      u.NumStreams = GetCodec_NumStreams(j);\n      u.Name = GetCodec_Name(j);\n    }\n  }\n  #endif\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/LoadCodecs.h",
    "content": "﻿// LoadCodecs.h\n\n#ifndef ZIP7_INC_LOAD_CODECS_H\n#define ZIP7_INC_LOAD_CODECS_H\n\n/*\nClient application uses LoadCodecs.* to load plugins to\nCCodecs object, that contains 3 lists of plugins:\n  1) Formats - internal and external archive handlers\n  2) Codecs  - external codecs\n  3) Hashers - external hashers\n\nZ7_EXTERNAL_CODECS\n---------------\n\n  if Z7_EXTERNAL_CODECS is defined, then the code tries to load external\n  plugins from DLL files (shared libraries).\n\n  There are two types of executables in 7-Zip:\n  \n  1) Executable that uses external plugins must be compiled\n     with Z7_EXTERNAL_CODECS defined:\n       - 7z.exe, 7zG.exe, 7zFM.exe\n    \n     Note: Z7_EXTERNAL_CODECS is used also in CPP/7zip/Common/CreateCoder.h\n           that code is used in plugin module (7z.dll).\n  \n  2) Standalone modules are compiled without Z7_EXTERNAL_CODECS:\n    - SFX modules: 7z.sfx, 7zCon.sfx\n    - standalone versions of console 7-Zip: 7za.exe, 7zr.exe\n\n  if Z7_EXTERNAL_CODECS is defined, CCodecs class implements interfaces:\n    - ICompressCodecsInfo : for Codecs\n    - IHashers            : for Hashers\n  \n  The client application can send CCodecs object to each plugin module.\n  And plugin module can use ICompressCodecsInfo or IHashers interface to access\n  another plugins.\n\n  There are 2 ways to send (ICompressCodecsInfo * compressCodecsInfo) to plugin\n    1) for old versions:\n        a) request ISetCompressCodecsInfo from created archive handler.\n        b) call ISetCompressCodecsInfo::SetCompressCodecsInfo(compressCodecsInfo)\n    2) for new versions:\n        a) request \"SetCodecs\" function from DLL file\n        b) call SetCodecs(compressCodecsInfo) function from DLL file\n*/\n\n#include \"../../../Common/MyBuffer.h\"\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/MyString.h\"\n#include \"../../../Common/ComTry.h\"\n\n#ifdef Z7_EXTERNAL_CODECS\n#include \"../../../Windows/DLL.h\"\n#endif\n\n#include \"../../ICoder.h\"\n\n#include \"../../Archive/IArchive.h\"\n\n\n#ifdef Z7_EXTERNAL_CODECS\n\nstruct CDllCodecInfo\n{\n  unsigned LibIndex;\n  UInt32 CodecIndex;\n  bool EncoderIsAssigned;\n  bool DecoderIsAssigned;\n  bool IsFilter;\n  bool IsFilter_Assigned;\n  CLSID Encoder;\n  CLSID Decoder;\n};\n\nstruct CDllHasherInfo\n{\n  unsigned LibIndex;\n  UInt32 HasherIndex;\n};\n\n#endif\n\nstruct CArcExtInfo\n{\n  UString Ext;\n  UString AddExt;\n  \n  CArcExtInfo() {}\n  CArcExtInfo(const UString &ext): Ext(ext) {}\n  CArcExtInfo(const UString &ext, const UString &addExt): Ext(ext), AddExt(addExt) {}\n};\n\n\nstruct CArcInfoEx\n{\n  UInt32 Flags;\n  UInt32 TimeFlags;\n  \n  Func_CreateInArchive CreateInArchive;\n  Func_IsArc IsArcFunc;\n\n  UString Name;\n  CObjectVector<CArcExtInfo> Exts;\n  \n  #ifndef Z7_SFX\n    Func_CreateOutArchive CreateOutArchive;\n    bool UpdateEnabled;\n    bool NewInterface;\n    // UInt32 Version;\n    UInt32 SignatureOffset;\n    CObjectVector<CByteBuffer> Signatures;\n    /*\n    #ifdef NEW_FOLDER_INTERFACE\n      UStringVector AssociateExts;\n    #endif\n    */\n  #endif\n  \n  #ifdef Z7_EXTERNAL_CODECS\n    int LibIndex;\n    UInt32 FormatIndex;\n    CLSID ClassID;\n  // **************** 7-Zip ZS Modification Start ****************\n    UInt32 LevelsMask;\n  // **************** 7-Zip ZS Modification End ****************\n  #endif\n\n  int Compare(const CArcInfoEx &a) const\n  {\n    const int res = Name.Compare(a.Name);\n    if (res != 0)\n      return res;\n    #ifdef Z7_EXTERNAL_CODECS\n    return MyCompare(LibIndex, a.LibIndex);\n    #else\n    return 0;\n    #endif\n    /*\n    if (LibIndex < a.LibIndex) return -1;\n    if (LibIndex > a.LibIndex) return 1;\n    return 0;\n    */\n  }\n\n  bool Flags_KeepName() const { return (Flags & NArcInfoFlags::kKeepName) != 0; }\n  bool Flags_FindSignature() const { return (Flags & NArcInfoFlags::kFindSignature) != 0; }\n\n  bool Flags_AltStreams() const { return (Flags & NArcInfoFlags::kAltStreams) != 0; }\n  bool Flags_NtSecurity() const { return (Flags & NArcInfoFlags::kNtSecure) != 0; }\n  bool Flags_SymLinks() const { return (Flags & NArcInfoFlags::kSymLinks) != 0; }\n  bool Flags_HardLinks() const { return (Flags & NArcInfoFlags::kHardLinks) != 0; }\n\n  bool Flags_UseGlobalOffset() const { return (Flags & NArcInfoFlags::kUseGlobalOffset) != 0; }\n  bool Flags_StartOpen() const { return (Flags & NArcInfoFlags::kStartOpen) != 0; }\n  bool Flags_BackwardOpen() const { return (Flags & NArcInfoFlags::kBackwardOpen) != 0; }\n  bool Flags_PreArc() const { return (Flags & NArcInfoFlags::kPreArc) != 0; }\n  bool Flags_PureStartOpen() const { return (Flags & NArcInfoFlags::kPureStartOpen) != 0; }\n  bool Flags_ByExtOnlyOpen() const { return (Flags & NArcInfoFlags::kByExtOnlyOpen) != 0; }\n  bool Flags_HashHandler() const { return (Flags & NArcInfoFlags::kHashHandler) != 0; }\n\n  bool Flags_CTime() const { return (Flags & NArcInfoFlags::kCTime) != 0; }\n  bool Flags_ATime() const { return (Flags & NArcInfoFlags::kATime) != 0; }\n  bool Flags_MTime() const { return (Flags & NArcInfoFlags::kMTime) != 0; }\n\n  bool Flags_CTime_Default() const { return (Flags & NArcInfoFlags::kCTime_Default) != 0; }\n  bool Flags_ATime_Default() const { return (Flags & NArcInfoFlags::kATime_Default) != 0; }\n  bool Flags_MTime_Default() const { return (Flags & NArcInfoFlags::kMTime_Default) != 0; }\n\n  UInt32 Get_TimePrecFlags() const\n  {\n    return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Mask_bit_index) &\n      (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Mask_num_bits) - 1);\n  }\n\n  UInt32 Get_DefaultTimePrec() const\n  {\n    return (TimeFlags >> NArcInfoTimeFlags::kTime_Prec_Default_bit_index) &\n      (((UInt32)1 << NArcInfoTimeFlags::kTime_Prec_Default_num_bits) - 1);\n  }\n\n\n  UString GetMainExt() const\n  {\n    if (Exts.IsEmpty())\n      return UString();\n    return Exts[0].Ext;\n  }\n  int FindExtension(const UString &ext) const;\n  \n  bool Is_7z()    const { return Name.IsEqualTo_Ascii_NoCase(\"7z\"); }\n  bool Is_Split() const { return Name.IsEqualTo_Ascii_NoCase(\"Split\"); }\n  bool Is_Xz()    const { return Name.IsEqualTo_Ascii_NoCase(\"xz\"); }\n  bool Is_BZip2() const { return Name.IsEqualTo_Ascii_NoCase(\"bzip2\"); }\n  bool Is_GZip()  const { return Name.IsEqualTo_Ascii_NoCase(\"gzip\"); }\n  bool Is_Tar()   const { return Name.IsEqualTo_Ascii_NoCase(\"tar\"); }\n  bool Is_Zip()   const { return Name.IsEqualTo_Ascii_NoCase(\"zip\"); }\n  bool Is_Rar()   const { return Name.IsEqualTo_Ascii_NoCase(\"rar\"); }\n  bool Is_Zstd()  const { return Name.IsEqualTo_Ascii_NoCase(\"zstd\"); }\n\n  /*\n  UString GetAllExtensions() const\n  {\n    UString s;\n    for (int i = 0; i < Exts.Size(); i++)\n    {\n      if (i > 0)\n        s.Add_Space();\n      s += Exts[i].Ext;\n    }\n    return s;\n  }\n  */\n\n  void AddExts(const UString &ext, const UString &addExt);\n\n\n  CArcInfoEx():\n      Flags(0),\n      TimeFlags(0),\n      CreateInArchive(NULL),\n      IsArcFunc(NULL)\n      #ifndef Z7_SFX\n      , CreateOutArchive(NULL)\n      , UpdateEnabled(false)\n      , NewInterface(false)\n      // , Version(0)\n      , SignatureOffset(0)\n      #endif\n      #ifdef Z7_EXTERNAL_CODECS\n      , LibIndex(-1)\n      // **************** 7-Zip ZS Modification Start ****************\n      , LevelsMask(0xFFFFFFFF)\n      // **************** 7-Zip ZS Modification End ****************\n      #endif\n  {}\n};\n\n\n#ifdef Z7_EXTERNAL_CODECS\n\nstruct CCodecLib\n{\n  NWindows::NDLL::CLibrary Lib;\n  FString Path;\n  \n  Func_CreateObject CreateObject;\n  Func_GetMethodProperty GetMethodProperty;\n  Func_CreateDecoder CreateDecoder;\n  Func_CreateEncoder CreateEncoder;\n  Func_SetCodecs SetCodecs;\n\n  CMyComPtr<IHashers> ComHashers;\n\n  UInt32 Version;\n  \n  /*\n  #ifdef NEW_FOLDER_INTERFACE\n  CCodecIcons CodecIcons;\n  void LoadIcons() { CodecIcons.LoadIcons((HMODULE)Lib); }\n  #endif\n  */\n  \n  CCodecLib():\n      CreateObject(NULL),\n      GetMethodProperty(NULL),\n      CreateDecoder(NULL),\n      CreateEncoder(NULL),\n      SetCodecs(NULL),\n      Version(0)\n      {}\n};\n\n#endif\n\nstruct CCodecError\n{\n  FString Path;\n  HRESULT ErrorCode;\n  AString Message;\n  CCodecError(): ErrorCode(0) {}\n};\n\n\nstruct CCodecInfoUser\n{\n  // unsigned LibIndex;\n  // UInt32 CodecIndex;\n  // UInt64 id;\n  bool EncoderIsAssigned;\n  bool DecoderIsAssigned;\n  bool IsFilter;\n  bool IsFilter_Assigned;\n  UInt32 NumStreams;\n  AString Name;\n};\n\n\nclass CCodecs Z7_final:\n  #ifdef Z7_EXTERNAL_CODECS\n    public ICompressCodecsInfo,\n    public IHashers,\n  #else\n    public IUnknown,\n  #endif\n  public CMyUnknownImp\n{\n#ifdef Z7_EXTERNAL_CODECS\n  Z7_IFACES_IMP_UNK_2(ICompressCodecsInfo, IHashers)\n#else\n  Z7_COM_UNKNOWN_IMP_0\n#endif // Z7_EXTERNAL_CODECS\n\n  Z7_CLASS_NO_COPY(CCodecs)\npublic:\n  #ifdef Z7_EXTERNAL_CODECS\n  \n  CObjectVector<CCodecLib> Libs;\n  FString MainDll_ErrorPath;\n  CObjectVector<CCodecError> Errors;\n  \n  void AddLastError(const FString &path);\n  void CloseLibs();\n\n  class CReleaser\n  {\n    Z7_CLASS_NO_COPY(CReleaser)\n\n    /* CCodecsReleaser object releases CCodecs links.\n         1) CCodecs is COM object that is deleted when all links to that object will be released/\n         2) CCodecs::Libs[i] can hold (ICompressCodecsInfo *) link to CCodecs object itself.\n       To break that reference loop, we must close all CCodecs::Libs in CCodecsReleaser desttructor. */\n\n    CCodecs *_codecs;\n      \n    public:\n    CReleaser(): _codecs(NULL) {}\n    void Set(CCodecs *codecs) { _codecs = codecs; }\n    ~CReleaser() { if (_codecs) _codecs->CloseLibs(); }\n  };\n\n  bool NeedSetLibCodecs; // = false, if we don't need to set codecs for archive handler via ISetCompressCodecsInfo\n\n  HRESULT LoadCodecs();\n  HRESULT LoadFormats();\n  HRESULT LoadDll(const FString &path, bool needCheckDll, bool *loadedOK = NULL);\n  HRESULT LoadDllsFromFolder(const FString &folderPrefix);\n\n  HRESULT CreateArchiveHandler(const CArcInfoEx &ai, bool outHandler, void **archive) const\n  {\n    return Libs[(unsigned)ai.LibIndex].CreateObject(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive);\n  }\n  \n  #endif\n\n  /*\n  #ifdef NEW_FOLDER_INTERFACE\n  CCodecIcons InternalIcons;\n  #endif\n  */\n\n  CObjectVector<CArcInfoEx> Formats;\n  \n  #ifdef Z7_EXTERNAL_CODECS\n  CRecordVector<CDllCodecInfo> Codecs;\n  CRecordVector<CDllHasherInfo> Hashers;\n  #endif\n\n  bool CaseSensitive_Change;\n  bool CaseSensitive;\n\n  CCodecs():\n      #ifdef Z7_EXTERNAL_CODECS\n      NeedSetLibCodecs(true),\n      #endif\n      CaseSensitive_Change(false),\n      CaseSensitive(false)\n      {}\n\n  ~CCodecs()\n  {\n    // OutputDebugStringA(\"~CCodecs\");\n  }\n \n  const wchar_t *GetFormatNamePtr(int formatIndex) const\n  {\n    return formatIndex < 0 ? L\"#\" : (const wchar_t *)Formats[(unsigned)formatIndex].Name;\n  }\n\n  HRESULT Load();\n\n  #ifndef Z7_SFX\n  int FindFormatForArchiveName(const UString &arcPath) const;\n  int FindFormatForExtension(const UString &ext) const;\n  int FindFormatForArchiveType(const UString &arcType) const;\n  bool FindFormatForArchiveType(const UString &arcType, CIntVector &formatIndices) const;\n  #endif\n\n  #ifdef Z7_EXTERNAL_CODECS\n\n  int GetCodec_LibIndex(UInt32 index) const;\n  bool GetCodec_DecoderIsAssigned(UInt32 index) const;\n  bool GetCodec_EncoderIsAssigned(UInt32 index) const;\n  bool GetCodec_IsFilter(UInt32 index, bool &isAssigned) const;\n  UInt32 GetCodec_NumStreams(UInt32 index);\n  HRESULT GetCodec_Id(UInt32 index, UInt64 &id);\n  AString GetCodec_Name(UInt32 index);\n\n  int GetHasherLibIndex(UInt32 index);\n  UInt64 GetHasherId(UInt32 index);\n  AString GetHasherName(UInt32 index);\n  UInt32 GetHasherDigestSize(UInt32 index);\n\n  void GetCodecsErrorMessage(UString &s);\n\n  #endif\n\n  HRESULT CreateInArchive(unsigned formatIndex, CMyComPtr<IInArchive> &archive) const\n  {\n    const CArcInfoEx &ai = Formats[formatIndex];\n    #ifdef Z7_EXTERNAL_CODECS\n    if (ai.LibIndex < 0)\n    #endif\n    {\n      COM_TRY_BEGIN\n      archive = ai.CreateInArchive();\n      return S_OK;\n      COM_TRY_END\n    }\n    #ifdef Z7_EXTERNAL_CODECS\n    return CreateArchiveHandler(ai, false, (void **)&archive);\n    #endif\n  }\n  \n  #ifndef Z7_SFX\n\n  HRESULT CreateOutArchive(unsigned formatIndex, CMyComPtr<IOutArchive> &archive) const\n  {\n    const CArcInfoEx &ai = Formats[formatIndex];\n    #ifdef Z7_EXTERNAL_CODECS\n    if (ai.LibIndex < 0)\n    #endif\n    {\n      COM_TRY_BEGIN\n      archive = ai.CreateOutArchive();\n      return S_OK;\n      COM_TRY_END\n    }\n    \n    #ifdef Z7_EXTERNAL_CODECS\n    return CreateArchiveHandler(ai, true, (void **)&archive);\n    #endif\n  }\n  \n  int FindOutFormatFromName(const UString &name) const\n  {\n    FOR_VECTOR (i, Formats)\n    {\n      const CArcInfoEx &arc = Formats[i];\n      if (!arc.UpdateEnabled)\n        continue;\n      if (arc.Name.IsEqualTo_NoCase(name))\n        return (int)i;\n    }\n    return -1;\n  }\n\n  void Get_CodecsInfoUser_Vector(CObjectVector<CCodecInfoUser> &v);\n\n  #endif // Z7_SFX\n};\n\n#ifdef Z7_EXTERNAL_CODECS\n  #define CREATE_CODECS_OBJECT \\\n    CCodecs *codecs = new CCodecs; \\\n    CExternalCodecs _externalCodecs; \\\n    _externalCodecs.GetCodecs = codecs; \\\n    _externalCodecs.GetHashers = codecs; \\\n    CCodecs::CReleaser codecsReleaser; \\\n    codecsReleaser.Set(codecs);\n#else\n  #define CREATE_CODECS_OBJECT \\\n    CCodecs *codecs = new CCodecs; \\\n    CMyComPtr<IUnknown> _codecsRef = codecs;\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/OpenArchive.cpp",
    "content": "﻿// OpenArchive.cpp\n\n#include \"StdAfx.h\"\n\n// #define SHOW_DEBUG_INFO\n\n#ifdef SHOW_DEBUG_INFO\n#include <stdio.h>\n#endif\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/StringToInt.h\"\n#include \"../../../Common/UTFConvert.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/FileDir.h\"\n\n#include \"../../Common/FileStreams.h\"\n#include \"../../Common/LimitedStreams.h\"\n#include \"../../Common/ProgressUtils.h\"\n#include \"../../Common/StreamUtils.h\"\n\n#include \"../../Compress/CopyCoder.h\"\n\n#include \"DefaultName.h\"\n#include \"OpenArchive.h\"\n\n#ifndef Z7_SFX\n#include \"SetProperties.h\"\n#endif\n\n#ifndef Z7_SFX\n#ifdef SHOW_DEBUG_INFO\n#define PRF(x) x\n#else\n#define PRF(x)\n#endif\n#endif\n\n// increase it, if you need to support larger SFX stubs\nstatic const UInt64 kMaxCheckStartPosition = 1 << 23;\n\n/*\nOpen:\n  - formatIndex >= 0 (exact Format)\n       1) Open with main type. Archive handler is allowed to use archive start finder.\n          Warning, if there is tail.\n  \n  - formatIndex = -1 (Parser:0) (default)\n    - same as #1 but doesn't return Parser\n\n  - formatIndex = -2 (#1)\n    - file has supported extension (like a.7z)\n      Open with that main type (only starting from start of file).\n        - open OK:\n            - if there is no tail - return OK\n            - if there is tail:\n              - archive is not \"Self Exe\" - return OK with Warning, that there is tail\n              - archive is \"Self Exe\"\n                ignore \"Self Exe\" stub, and tries to open tail\n                  - tail can be open as archive - shows that archive and stub size property.\n                  - tail can't be open as archive - shows Parser ???\n        - open FAIL:\n           Try to open with all other types from offset 0 only.\n           If some open type is OK and physical archive size is uequal or larger\n           than file size, then return that archive with warning that cannot be open as [extension type].\n           If extension was EXE, it will try to open as unknown_extension case\n    - file has unknown extension (like a.hhh)\n       It tries to open via parser code.\n         - if there is full archive or tail archive and unknown block or \"Self Exe\"\n           at front, it shows tail archive and stub size property.\n         - in another cases, if there is some archive inside file, it returns parser/\n         - in another cases, it retuens S_FALSE\n\n       \n  - formatIndex = -3 (#2)\n    - same as #1, but\n    - stub (EXE) + archive is open in Parser\n\n  - formatIndex = -4 (#3)\n    - returns only Parser. skip full file archive. And show other sub-archives\n\n  - formatIndex = -5 (#4)\n    - returns only Parser. skip full file archive. And show other sub-archives for each byte pos\n\n*/\n\n\n\n\nusing namespace NWindows;\n\n/*\n#ifdef Z7_SFX\n#define OPEN_PROPS_PARAM\n#else\n#define OPEN_PROPS_PARAM  , props\n#endif\n*/\n\n/*\nCArc::~CArc()\n{\n  GetRawProps.Release();\n  Archive.Release();\n  printf(\"\\nCArc::~CArc()\\n\");\n}\n*/\n\n#ifndef Z7_SFX\n\nnamespace NArchive {\nnamespace NParser {\n\nstruct CParseItem\n{\n  UInt64 Offset;\n  UInt64 Size;\n  // UInt64 OkSize;\n  UString Name;\n  UString Extension;\n  FILETIME FileTime;\n  UString Comment;\n  UString ArcType;\n  \n  bool FileTime_Defined;\n  bool UnpackSize_Defined;\n  bool NumSubDirs_Defined;\n  bool NumSubFiles_Defined;\n\n  bool IsSelfExe;\n  bool IsNotArcType;\n  \n  UInt64 UnpackSize;\n  UInt64 NumSubDirs;\n  UInt64 NumSubFiles;\n\n  int FormatIndex;\n\n  bool LenIsUnknown;\n\n  CParseItem():\n      // OkSize(0),\n      FileTime_Defined(false),\n      UnpackSize_Defined(false),\n      NumSubDirs_Defined(false),\n      NumSubFiles_Defined(false),\n      IsSelfExe(false),\n      IsNotArcType(false),\n      LenIsUnknown(false)\n    {}\n\n  /*\n  bool IsEqualTo(const CParseItem &item) const\n  {\n    return Offset == item.Offset && Size == item.Size;\n  }\n  */\n\n  void NormalizeOffset()\n  {\n    if ((Int64)Offset < 0)\n    {\n      Size += Offset;\n      // OkSize += Offset;\n      Offset = 0;\n    }\n  }\n};\n\nZ7_CLASS_IMP_CHandler_IInArchive_1(\n  IInArchiveGetStream\n)\npublic:\n  CObjectVector<CParseItem> _items;\n  UInt64 _maxEndOffset;\n  CMyComPtr<IInStream> _stream;\n\n  UInt64 GetLastEnd() const\n  {\n    if (_items.IsEmpty())\n      return 0;\n    const CParseItem &back = _items.Back();\n    return back.Offset + back.Size;\n  }\n\n  void AddUnknownItem(UInt64 next);\n  int FindInsertPos(const CParseItem &item) const;\n  void AddItem(const CParseItem &item);\n  \n  CHandler(): _maxEndOffset(0) {}\n};\n\nint CHandler::FindInsertPos(const CParseItem &item) const\n{\n  unsigned left = 0, right = _items.Size();\n  while (left != right)\n  {\n    const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n    const CParseItem &midItem = _items[mid];\n    if (item.Offset < midItem.Offset)\n      right = mid;\n    else if (item.Offset > midItem.Offset)\n      left = mid + 1;\n    else if (item.Size < midItem.Size)\n      right = mid;\n    /*\n    else if (item.Size > midItem.Size)\n      left = mid + 1;\n    */\n    else\n    {\n      left = mid + 1;\n      // return -1;\n    }\n  }\n  return (int)left;\n}\n\nvoid CHandler::AddUnknownItem(UInt64 next)\n{\n  /*\n  UInt64 prevEnd = 0;\n  if (!_items.IsEmpty())\n  {\n    const CParseItem &back = _items.Back();\n    prevEnd = back.Offset + back.Size;\n  }\n  */\n  if (_maxEndOffset < next)\n  {\n    CParseItem item2;\n    item2.Offset = _maxEndOffset;\n    item2.Size = next - _maxEndOffset;\n    _maxEndOffset = next;\n    _items.Add(item2);\n  }\n  else if (_maxEndOffset > next && !_items.IsEmpty())\n  {\n    CParseItem &back = _items.Back();\n    if (back.LenIsUnknown)\n    {\n      back.Size = next - back.Offset;\n      _maxEndOffset = next;\n    }\n  }\n}\n\nvoid CHandler::AddItem(const CParseItem &item)\n{\n  AddUnknownItem(item.Offset);\n  const int pos = FindInsertPos(item);\n  if (pos != -1)\n  {\n    _items.Insert((unsigned)pos, item);\n    UInt64 next = item.Offset + item.Size;\n    if (_maxEndOffset < next)\n      _maxEndOffset = next;\n  }\n}\n\n/*\nstatic const CStatProp kProps[] =\n{\n  { NULL, kpidPath, VT_BSTR},\n  { NULL, kpidSize, VT_UI8},\n  { NULL, kpidMTime, VT_FILETIME},\n  { NULL, kpidType, VT_BSTR},\n  { NULL, kpidComment, VT_BSTR},\n  { NULL, kpidOffset, VT_UI8},\n  { NULL, kpidUnpackSize, VT_UI8},\n//   { NULL, kpidNumSubDirs, VT_UI8},\n};\n*/\n\nstatic const Byte kProps[] =\n{\n  kpidPath,\n  kpidSize,\n  kpidMTime,\n  kpidType,\n  kpidComment,\n  kpidOffset,\n  kpidUnpackSize\n};\n\nIMP_IInArchive_Props\nIMP_IInArchive_ArcProps_NO\n\nZ7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback * /* openArchiveCallback */))\n{\n  COM_TRY_BEGIN\n  {\n    Close();\n    _stream = stream;\n  }\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Close())\n{\n  _items.Clear();\n  _stream.Release();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))\n{\n  *numItems = _items.Size();\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))\n{\n  COM_TRY_BEGIN\n  NCOM::CPropVariant prop;\n\n  const CParseItem &item = _items[index];\n\n  switch (propID)\n  {\n    case kpidPath:\n    {\n      char sz[32];\n      ConvertUInt32ToString(index + 1, sz);\n      UString s(sz);\n      if (!item.Name.IsEmpty())\n      {\n        s.Add_Dot();\n        s += item.Name;\n      }\n      if (!item.Extension.IsEmpty())\n      {\n        s.Add_Dot();\n        s += item.Extension;\n      }\n      prop = s; break;\n    }\n    case kpidSize:\n    case kpidPackSize: prop = item.Size; break;\n    case kpidOffset: prop = item.Offset; break;\n    case kpidUnpackSize: if (item.UnpackSize_Defined) prop = item.UnpackSize; break;\n    case kpidNumSubFiles: if (item.NumSubFiles_Defined) prop = item.NumSubFiles; break;\n    case kpidNumSubDirs: if (item.NumSubDirs_Defined) prop = item.NumSubDirs; break;\n    case kpidMTime: if (item.FileTime_Defined) prop = item.FileTime; break;\n    case kpidComment: if (!item.Comment.IsEmpty()) prop = item.Comment; break;\n    case kpidType: if (!item.ArcType.IsEmpty()) prop = item.ArcType; break;\n    default: break;\n  }\n  prop.Detach(value);\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,\n    Int32 testMode, IArchiveExtractCallback *extractCallback))\n{\n  COM_TRY_BEGIN\n  \n  const bool allFilesMode = (numItems == (UInt32)(Int32)-1);\n  if (allFilesMode)\n    numItems = _items.Size();\n  if (_stream && numItems == 0)\n    return S_OK;\n  UInt64 totalSize = 0;\n  UInt32 i;\n  for (i = 0; i < numItems; i++)\n    totalSize += _items[allFilesMode ? i : indices[i]].Size;\n  extractCallback->SetTotal(totalSize);\n\n  totalSize = 0;\n  \n  CLocalProgress *lps = new CLocalProgress;\n  CMyComPtr<ICompressProgressInfo> progress = lps;\n  lps->Init(extractCallback, false);\n\n  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;\n  CMyComPtr<ISequentialInStream> inStream(streamSpec);\n  streamSpec->SetStream(_stream);\n\n  CLimitedSequentialOutStream *outStreamSpec = new CLimitedSequentialOutStream;\n  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);\n\n  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();\n  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;\n\n  for (i = 0; i < numItems; i++)\n  {\n    lps->InSize = totalSize;\n    lps->OutSize = totalSize;\n    RINOK(lps->SetCur())\n    CMyComPtr<ISequentialOutStream> realOutStream;\n    const Int32 askMode = testMode ?\n        NExtract::NAskMode::kTest :\n        NExtract::NAskMode::kExtract;\n    const UInt32 index = allFilesMode ? i : indices[i];\n    const CParseItem &item = _items[index];\n\n    RINOK(extractCallback->GetStream(index, &realOutStream, askMode))\n    UInt64 unpackSize = item.Size;\n    totalSize += unpackSize;\n    bool skipMode = false;\n    if (!testMode && !realOutStream)\n      continue;\n    RINOK(extractCallback->PrepareOperation(askMode))\n\n    outStreamSpec->SetStream(realOutStream);\n    realOutStream.Release();\n    outStreamSpec->Init(skipMode ? 0 : unpackSize, true);\n\n    Int32 opRes = NExtract::NOperationResult::kOK;\n    RINOK(InStream_SeekSet(_stream, item.Offset))\n    streamSpec->Init(unpackSize);\n    RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress))\n\n    if (outStreamSpec->GetRem() != 0)\n      opRes = NExtract::NOperationResult::kDataError;\n    outStreamSpec->ReleaseStream();\n    RINOK(extractCallback->SetOperationResult(opRes))\n  }\n  \n  return S_OK;\n  \n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream))\n{\n  COM_TRY_BEGIN\n  const CParseItem &item = _items[index];\n  return CreateLimitedInStream(_stream, item.Offset, item.Size, stream);\n  COM_TRY_END\n}\n\n}}\n\n#endif\n\nHRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw()\n{\n  NCOM::CPropVariant prop;\n  result = false;\n  RINOK(arc->GetProperty(index, propID, &prop))\n  if (prop.vt == VT_BOOL)\n    result = VARIANT_BOOLToBool(prop.boolVal);\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\nHRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw()\n{\n  return Archive_GetItemBoolProp(arc, index, kpidIsDir, result);\n}\n\nHRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw()\n{\n  return Archive_GetItemBoolProp(arc, index, kpidIsAux, result);\n}\n\nHRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw()\n{\n  return Archive_GetItemBoolProp(arc, index, kpidIsAltStream, result);\n}\n\nHRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &result) throw()\n{\n  return Archive_GetItemBoolProp(arc, index, kpidIsDeleted, result);\n}\n\nstatic HRESULT Archive_GetArcProp_Bool(IInArchive *arc, PROPID propid, bool &result) throw()\n{\n  NCOM::CPropVariant prop;\n  result = false;\n  RINOK(arc->GetArchiveProperty(propid, &prop))\n  if (prop.vt == VT_BOOL)\n    result = VARIANT_BOOLToBool(prop.boolVal);\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\nstatic HRESULT Archive_GetArcProp_UInt(IInArchive *arc, PROPID propid, UInt64 &result, bool &defined)\n{\n  defined = false;\n  NCOM::CPropVariant prop;\n  RINOK(arc->GetArchiveProperty(propid, &prop))\n  switch (prop.vt)\n  {\n    case VT_UI4: result = prop.ulVal; break;\n    case VT_I4:  result = (UInt64)(Int64)prop.lVal; break;\n    case VT_UI8: result = (UInt64)prop.uhVal.QuadPart; break;\n    case VT_I8:  result = (UInt64)prop.hVal.QuadPart; break;\n    case VT_EMPTY: return S_OK;\n    default: return E_FAIL;\n  }\n  defined = true;\n  return S_OK;\n}\n\nstatic HRESULT Archive_GetArcProp_Int(IInArchive *arc, PROPID propid, Int64 &result, bool &defined)\n{\n  defined = false;\n  NCOM::CPropVariant prop;\n  RINOK(arc->GetArchiveProperty(propid, &prop))\n  switch (prop.vt)\n  {\n    case VT_UI4: result = prop.ulVal; break;\n    case VT_I4:  result = prop.lVal; break;\n    case VT_UI8: result = (Int64)prop.uhVal.QuadPart; break;\n    case VT_I8:  result = (Int64)prop.hVal.QuadPart; break;\n    case VT_EMPTY: return S_OK;\n    default: return E_FAIL;\n  }\n  defined = true;\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\nHRESULT CArc::GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const\n{\n  if (!GetRawProps)\n    return E_FAIL;\n  if (index == parent)\n    return S_OK;\n  UInt32 curIndex = index;\n  \n  UString s;\n  \n  bool prevWasAltStream = false;\n  \n  for (;;)\n  {\n    #ifdef MY_CPU_LE\n    const void *p;\n    UInt32 size;\n    UInt32 propType;\n    RINOK(GetRawProps->GetRawProp(curIndex, kpidName, &p, &size, &propType))\n    if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)\n      s = (const wchar_t *)p;\n    else\n    #endif\n    {\n      NCOM::CPropVariant prop;\n      RINOK(Archive->GetProperty(curIndex, kpidName, &prop))\n      if (prop.vt == VT_BSTR && prop.bstrVal)\n        s.SetFromBstr(prop.bstrVal);\n      else if (prop.vt == VT_EMPTY)\n        s.Empty();\n      else\n        return E_FAIL;\n    }\n\n    UInt32 curParent = (UInt32)(Int32)-1;\n    UInt32 parentType = 0;\n    RINOK(GetRawProps->GetParent(curIndex, &curParent, &parentType))\n\n    // 18.06: fixed : we don't want to split name to parts\n    /*\n    if (parentType != NParentType::kAltStream)\n    {\n      for (;;)\n      {\n        int pos = s.ReverseFind_PathSepar();\n        if (pos < 0)\n        {\n          break;\n        }\n        parts.Insert(0, s.Ptr(pos + 1));\n        s.DeleteFrom(pos);\n      }\n    }\n    */\n    \n    parts.Insert(0, s);\n\n    if (prevWasAltStream)\n    {\n      {\n        UString &s2 = parts[parts.Size() - 2];\n        s2.Add_Colon();\n        s2 += parts.Back();\n      }\n      parts.DeleteBack();\n    }\n\n    if (parent == curParent)\n      return S_OK;\n    \n    prevWasAltStream = false;\n    if (parentType == NParentType::kAltStream)\n      prevWasAltStream = true;\n    \n    if (curParent == (UInt32)(Int32)-1)\n      return E_FAIL;\n    curIndex = curParent;\n  }\n}\n\n#endif\n\n\n\nHRESULT CArc::GetItem_Path(UInt32 index, UString &result) const\n{\n  #ifdef MY_CPU_LE\n  if (GetRawProps)\n  {\n    const void *p;\n    UInt32 size;\n    UInt32 propType;\n    if (!IsTree)\n    {\n      if (GetRawProps->GetRawProp(index, kpidPath, &p, &size, &propType) == S_OK &&\n          propType == NPropDataType::kUtf16z)\n      {\n        unsigned len = size / 2 - 1;\n        // (len) doesn't include null terminator\n\n        /*\n        #if WCHAR_MAX > 0xffff\n        len = (unsigned)Utf16LE__Get_Num_WCHARs(p, len);\n\n        wchar_t *s = result.GetBuf(len);\n        wchar_t *sEnd = Utf16LE__To_WCHARs_Sep(p, len, s);\n        if (s + len != sEnd) return E_FAIL;\n        *sEnd = 0;\n        \n        #else\n        */\n        \n        wchar_t *s = result.GetBuf(len);\n        for (unsigned i = 0; i < len; i++)\n        {\n          wchar_t c = GetUi16(p);\n          p = (const void *)((const Byte *)p + 2);\n\n          #if WCHAR_PATH_SEPARATOR != L'/'\n          if (c == L'/')\n            c = WCHAR_PATH_SEPARATOR;\n          else if (c == L'\\\\')\n            c = WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT; // WSL scheme\n          #endif\n\n          *s++ = c;\n        }\n        *s = 0;\n        \n        // #endif\n        \n        result.ReleaseBuf_SetLen(len);\n\n        Convert_UnicodeEsc16_To_UnicodeEscHigh(result);\n        if (len != 0)\n          return S_OK;\n      }\n    }\n    /*\n    else if (GetRawProps->GetRawProp(index, kpidName, &p, &size, &propType) == S_OK &&\n        p && propType == NPropDataType::kUtf16z)\n    {\n      size -= 2;\n      UInt32 totalSize = size;\n      bool isOK = false;\n      \n      {\n        UInt32 index2 = index;\n        for (;;)\n        {\n          UInt32 parent = (UInt32)(Int32)-1;\n          UInt32 parentType = 0;\n          if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)\n            break;\n          if (parent == (UInt32)(Int32)-1)\n          {\n            if (parentType != 0)\n              totalSize += 2;\n            isOK = true;\n            break;\n          }\n          index2 = parent;\n          UInt32 size2;\n          const void *p2;\n          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK &&\n              p2 && propType == NPropDataType::kUtf16z)\n            break;\n          totalSize += size2;\n        }\n      }\n\n      if (isOK)\n      {\n        wchar_t *sz = result.GetBuf_SetEnd(totalSize / 2);\n        UInt32 pos = totalSize - size;\n        memcpy((Byte *)sz + pos, p, size);\n        UInt32 index2 = index;\n        for (;;)\n        {\n          UInt32 parent = (UInt32)(Int32)-1;\n          UInt32 parentType = 0;\n          if (GetRawProps->GetParent(index2, &parent, &parentType) != S_OK)\n            break;\n          if (parent == (UInt32)(Int32)-1)\n          {\n            if (parentType != 0)\n              sz[pos / 2 - 1] = L':';\n            break;\n          }\n          index2 = parent;\n          UInt32 size2;\n          const void *p2;\n          if (GetRawProps->GetRawProp(index2, kpidName, &p2, &size2, &propType) != S_OK)\n            break;\n          pos -= size2;\n          memcpy((Byte *)sz + pos, p2, size2);\n          sz[(pos + size2 - 2) / 2] = (parentType == 0) ? WCHAR_PATH_SEPARATOR : L':';\n        }\n        #ifdef _WIN32\n        // result.Replace(L'/', WCHAR_PATH_SEPARATOR);\n        #endif\n        return S_OK;\n      }\n    }\n    */\n  }\n  #endif\n  \n  {\n    NCOM::CPropVariant prop;\n    RINOK(Archive->GetProperty(index, kpidPath, &prop))\n    if (prop.vt == VT_BSTR && prop.bstrVal)\n      result.SetFromBstr(prop.bstrVal);\n    else if (prop.vt == VT_EMPTY)\n      result.Empty();\n    else\n      return E_FAIL;\n  }\n  \n  if (result.IsEmpty())\n    return GetItem_DefaultPath(index, result);\n\n  Convert_UnicodeEsc16_To_UnicodeEscHigh(result);\n  return S_OK;\n}\n\nHRESULT CArc::GetItem_DefaultPath(UInt32 index, UString &result) const\n{\n  result.Empty();\n  bool isDir;\n  RINOK(Archive_IsItem_Dir(Archive, index, isDir))\n  if (!isDir)\n  {\n    result = DefaultName;\n    NCOM::CPropVariant prop;\n    RINOK(Archive->GetProperty(index, kpidExtension, &prop))\n    if (prop.vt == VT_BSTR)\n    {\n      result.Add_Dot();\n      result += prop.bstrVal;\n    }\n    else if (prop.vt != VT_EMPTY)\n      return E_FAIL;\n  }\n  return S_OK;\n}\n\nHRESULT CArc::GetItem_Path2(UInt32 index, UString &result) const\n{\n  RINOK(GetItem_Path(index, result))\n  if (Ask_Deleted)\n  {\n    bool isDeleted = false;\n    RINOK(Archive_IsItem_Deleted(Archive, index, isDeleted))\n    if (isDeleted)\n      result.Insert(0, L\"[DELETED]\" WSTRING_PATH_SEPARATOR);\n  }\n  return S_OK;\n}\n\n#ifdef SUPPORT_ALT_STREAMS\n\nint FindAltStreamColon_in_Path(const wchar_t *path)\n{\n  unsigned i = 0;\n  int colonPos = -1;\n  for (;; i++)\n  {\n    wchar_t c = path[i];\n    if (c == 0)\n      return colonPos;\n    if (c == ':')\n    {\n      if (colonPos < 0)\n        colonPos = (int)i;\n      continue;\n    }\n    if (c == WCHAR_PATH_SEPARATOR)\n      colonPos = -1;\n  }\n}\n\n#endif\n\nHRESULT CArc::GetItem(UInt32 index, CReadArcItem &item) const\n{\n  #ifdef SUPPORT_ALT_STREAMS\n  item.IsAltStream = false;\n  item.AltStreamName.Empty();\n  item.MainPath.Empty();\n  #endif\n\n  item.IsDir = false;\n  item.Path.Empty();\n  item.ParentIndex = (UInt32)(Int32)-1;\n  \n  item.PathParts.Clear();\n\n  RINOK(Archive_IsItem_Dir(Archive, index, item.IsDir))\n  item.MainIsDir = item.IsDir;\n\n  RINOK(GetItem_Path2(index, item.Path))\n\n  #ifndef Z7_SFX\n  UInt32 mainIndex = index;\n  #endif\n\n  #ifdef SUPPORT_ALT_STREAMS\n\n  item.MainPath = item.Path;\n  if (Ask_AltStream)\n  {\n    RINOK(Archive_IsItem_AltStream(Archive, index, item.IsAltStream))\n  }\n  \n  bool needFindAltStream = false;\n\n  if (item.IsAltStream)\n  {\n    needFindAltStream = true;\n    if (GetRawProps)\n    {\n      UInt32 parentType = 0;\n      UInt32 parentIndex;\n      RINOK(GetRawProps->GetParent(index, &parentIndex, &parentType))\n      if (parentType == NParentType::kAltStream)\n      {\n        NCOM::CPropVariant prop;\n        RINOK(Archive->GetProperty(index, kpidName, &prop))\n        if (prop.vt == VT_BSTR && prop.bstrVal)\n          item.AltStreamName.SetFromBstr(prop.bstrVal);\n        else if (prop.vt != VT_EMPTY)\n          return E_FAIL;\n        else\n        {\n          // item.IsAltStream = false;\n        }\n        /*\n        if (item.AltStreamName.IsEmpty())\n          item.IsAltStream = false;\n        */\n\n        needFindAltStream = false;\n        item.ParentIndex = parentIndex;\n        mainIndex = parentIndex;\n\n        if (parentIndex == (UInt32)(Int32)-1)\n        {\n          item.MainPath.Empty();\n          item.MainIsDir = true;\n        }\n        else\n        {\n          RINOK(GetItem_Path2(parentIndex, item.MainPath))\n          RINOK(Archive_IsItem_Dir(Archive, parentIndex, item.MainIsDir))\n        }\n      }\n    }\n  }\n\n  if (item.WriteToAltStreamIfColon || needFindAltStream)\n  {\n    /* Good handler must support GetRawProps::GetParent for alt streams.\n       So the following code currently is not used */\n    int colon = FindAltStreamColon_in_Path(item.Path);\n    if (colon >= 0)\n    {\n      item.MainPath.DeleteFrom((unsigned)colon);\n      item.AltStreamName = item.Path.Ptr((unsigned)(colon + 1));\n      item.MainIsDir = (colon == 0 || IsPathSepar(item.Path[(unsigned)colon - 1]));\n      item.IsAltStream = true;\n    }\n  }\n\n  #endif\n  \n  #ifndef Z7_SFX\n  if (item._use_baseParentFolder_mode)\n  {\n    RINOK(GetItem_PathToParent(mainIndex, (unsigned)item._baseParentFolder, item.PathParts))\n    \n    #ifdef SUPPORT_ALT_STREAMS\n    if ((item.WriteToAltStreamIfColon || needFindAltStream) && !item.PathParts.IsEmpty())\n    {\n      int colon;\n      {\n        UString &s = item.PathParts.Back();\n        colon = FindAltStreamColon_in_Path(s);\n        if (colon >= 0)\n        {\n          item.AltStreamName = s.Ptr((unsigned)(colon + 1));\n          item.MainIsDir = (colon == 0 || IsPathSepar(s[(unsigned)colon - 1]));\n          item.IsAltStream = true;\n          s.DeleteFrom((unsigned)colon);\n        }\n      }\n      if (colon == 0)\n        item.PathParts.DeleteBack();\n    }\n    #endif\n    \n  }\n  else\n  #endif\n    SplitPathToParts(\n          #ifdef SUPPORT_ALT_STREAMS\n            item.MainPath\n          #else\n            item.Path\n          #endif\n      , item.PathParts);\n\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\nstatic HRESULT Archive_GetItem_Size(IInArchive *archive, UInt32 index, UInt64 &size, bool &defined)\n{\n  NCOM::CPropVariant prop;\n  defined = false;\n  size = 0;\n  RINOK(archive->GetProperty(index, kpidSize, &prop))\n  switch (prop.vt)\n  {\n    case VT_UI1: size = prop.bVal; break;\n    case VT_UI2: size = prop.uiVal; break;\n    case VT_UI4: size = prop.ulVal; break;\n    case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;\n    case VT_EMPTY: return S_OK;\n    default: return E_FAIL;\n  }\n  defined = true;\n  return S_OK;\n}\n\n#endif\n\nHRESULT CArc::GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const\n{\n  NCOM::CPropVariant prop;\n  defined = false;\n  size = 0;\n  RINOK(Archive->GetProperty(index, kpidSize, &prop))\n  switch (prop.vt)\n  {\n    case VT_UI1: size = prop.bVal; break;\n    case VT_UI2: size = prop.uiVal; break;\n    case VT_UI4: size = prop.ulVal; break;\n    case VT_UI8: size = (UInt64)prop.uhVal.QuadPart; break;\n    case VT_EMPTY: return S_OK;\n    default: return E_FAIL;\n  }\n  defined = true;\n  return S_OK;\n}\n\nHRESULT CArc::GetItem_MTime(UInt32 index, CArcTime &at) const\n{\n  at.Clear();\n  NCOM::CPropVariant prop;\n  RINOK(Archive->GetProperty(index, kpidMTime, &prop))\n  \n  if (prop.vt == VT_FILETIME)\n  {\n    /*\n    // for debug\n    if (FILETIME_IsZero(prop.at) && MTime.Def)\n    {\n      at = MTime;\n      return S_OK;\n    }\n    */\n    at.Set_From_Prop(prop);\n    if (at.Prec == 0)\n    {\n      // (at.Prec == 0) before version 22.\n      // so kpidTimeType is required for that code\n      prop.Clear();\n      RINOK(Archive->GetProperty(index, kpidTimeType, &prop))\n      if (prop.vt == VT_UI4)\n      {\n        UInt32 val = prop.ulVal;\n        if (val == NFileTimeType::kWindows)\n          val = k_PropVar_TimePrec_100ns;\n        /*\n        else if (val > k_PropVar_TimePrec_1ns)\n        {\n          val = k_PropVar_TimePrec_100ns;\n          // val = k_PropVar_TimePrec_1ns;\n          // return E_FAIL; // for debug\n        }\n        */\n        at.Prec = (UInt16)val;\n      }\n    }\n    return S_OK;\n  }\n  \n  if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  if (MTime.Def)\n    at = MTime;\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\nstatic inline bool TestSignature(const Byte *p1, const Byte *p2, size_t size)\n{\n  for (size_t i = 0; i < size; i++)\n    if (p1[i] != p2[i])\n      return false;\n  return true;\n}\n\n\nstatic void MakeCheckOrder(CCodecs *codecs,\n    CIntVector &orderIndices, unsigned numTypes, CIntVector &orderIndices2,\n    const Byte *data, size_t dataSize)\n{\n  for (unsigned i = 0; i < numTypes; i++)\n  {\n    const int index = orderIndices[i];\n    if (index < 0)\n      continue;\n    const CArcInfoEx &ai = codecs->Formats[(unsigned)index];\n    if (ai.SignatureOffset == 0)\n    {\n      if (ai.Signatures.IsEmpty())\n      {\n        if (dataSize != 0) // 21.04: no Signature means Empty Signature\n          continue;\n      }\n      else\n      {\n        unsigned k;\n        const CObjectVector<CByteBuffer> &sigs = ai.Signatures;\n        for (k = 0; k < sigs.Size(); k++)\n        {\n          const CByteBuffer &sig = sigs[k];\n          if (sig.Size() <= dataSize && TestSignature(data, sig, sig.Size()))\n            break;\n        }\n        if (k == sigs.Size())\n          continue;\n      }\n    }\n    orderIndices2.Add(index);\n    orderIndices[i] = -1;\n  }\n}\n\n#ifdef UNDER_CE\n  static const unsigned kNumHashBytes = 1;\n  #define HASH_VAL(buf) ((buf)[0])\n#else\n  static const unsigned kNumHashBytes = 2;\n  // #define HASH_VAL(buf) ((buf)[0] | ((UInt32)(buf)[1] << 8))\n  #define HASH_VAL(buf) GetUi16(buf)\n#endif\n\nstatic bool IsExeExt(const UString &ext)\n{\n  return ext.IsEqualTo_Ascii_NoCase(\"exe\");\n}\n\nstatic const char * const k_PreArcFormats[] =\n{\n    \"pe\"\n  , \"elf\"\n  , \"macho\"\n  , \"mub\"\n  , \"te\"\n};\n\nstatic bool IsNameFromList(const UString &s, const char * const names[], size_t num)\n{\n  for (unsigned i = 0; i < num; i++)\n    if (StringsAreEqualNoCase_Ascii(s, names[i]))\n      return true;\n  return false;\n}\n\n\nstatic bool IsPreArcFormat(const CArcInfoEx &ai)\n{\n  if (ai.Flags_PreArc())\n    return true;\n  return IsNameFromList(ai.Name, k_PreArcFormats, Z7_ARRAY_SIZE(k_PreArcFormats));\n}\n\nstatic const char * const k_Formats_with_simple_signuature[] =\n{\n    \"7z\"\n  , \"xz\"\n  , \"rar\"\n  , \"bzip2\"\n  , \"gzip\"\n  // **************** 7-Zip ZS Modification Start ****************\n  , \"lzip\"\n  // **************** 7-Zip ZS Modification End ****************\n  , \"cab\"\n  , \"wim\"\n  , \"rpm\"\n  , \"vhd\"\n  , \"xar\"\n};\n\nstatic bool IsNewStyleSignature(const CArcInfoEx &ai)\n{\n  // if (ai.Version >= 0x91F)\n  if (ai.NewInterface)\n    return true;\n  return IsNameFromList(ai.Name, k_Formats_with_simple_signuature, Z7_ARRAY_SIZE(k_Formats_with_simple_signuature));\n}\n\n\n\nclass CArchiveOpenCallback_Offset Z7_final:\n  public IArchiveOpenCallback,\n  public IArchiveOpenVolumeCallback,\n #ifndef Z7_NO_CRYPTO\n  public ICryptoGetTextPassword,\n #endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IArchiveOpenCallback)\n  Z7_COM_QI_ENTRY(IArchiveOpenVolumeCallback)\n #ifndef Z7_NO_CRYPTO\n  Z7_COM_QI_ENTRY(ICryptoGetTextPassword)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(IArchiveOpenCallback)\n  Z7_IFACE_COM7_IMP(IArchiveOpenVolumeCallback)\n #ifndef Z7_NO_CRYPTO\n  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)\n #endif\n\npublic:\n  CMyComPtr<IArchiveOpenCallback> Callback;\n  CMyComPtr<IArchiveOpenVolumeCallback> OpenVolumeCallback;\n  UInt64 Files;\n  UInt64 Offset;\n  \n  #ifndef Z7_NO_CRYPTO\n  CMyComPtr<ICryptoGetTextPassword> GetTextPassword;\n  #endif\n};\n\n#ifndef Z7_NO_CRYPTO\nZ7_COM7F_IMF(CArchiveOpenCallback_Offset::CryptoGetTextPassword(BSTR *password))\n{\n  COM_TRY_BEGIN\n  if (GetTextPassword)\n    return GetTextPassword->CryptoGetTextPassword(password);\n  return E_NOTIMPL;\n  COM_TRY_END\n}\n#endif\n\nZ7_COM7F_IMF(CArchiveOpenCallback_Offset::SetTotal(const UInt64 *, const UInt64 *))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CArchiveOpenCallback_Offset::SetCompleted(const UInt64 *, const UInt64 *bytes))\n{\n  if (!Callback)\n    return S_OK;\n  UInt64 value = Offset;\n  if (bytes)\n    value += *bytes;\n  return Callback->SetCompleted(&Files, &value);\n}\n\nZ7_COM7F_IMF(CArchiveOpenCallback_Offset::GetProperty(PROPID propID, PROPVARIANT *value))\n{\n  if (OpenVolumeCallback)\n    return OpenVolumeCallback->GetProperty(propID, value);\n  NCOM::PropVariant_Clear(value);\n  return S_OK;\n  // return E_NOTIMPL;\n}\n\nZ7_COM7F_IMF(CArchiveOpenCallback_Offset::GetStream(const wchar_t *name, IInStream **inStream))\n{\n  if (OpenVolumeCallback)\n    return OpenVolumeCallback->GetStream(name, inStream);\n  return S_FALSE;\n}\n\n#endif\n\n\nUInt32 GetOpenArcErrorFlags(const NCOM::CPropVariant &prop, bool *isDefinedProp)\n{\n  if (isDefinedProp != NULL)\n    *isDefinedProp = false;\n\n  switch (prop.vt)\n  {\n    case VT_UI8: if (isDefinedProp) *isDefinedProp = true; return (UInt32)prop.uhVal.QuadPart;\n    case VT_UI4: if (isDefinedProp) *isDefinedProp = true; return prop.ulVal;\n    case VT_EMPTY: return 0;\n    default: throw 151199;\n  }\n}\n\nvoid CArcErrorInfo::ClearErrors()\n{\n  // ErrorFormatIndex = -1; // we don't need to clear ErrorFormatIndex here !!!\n\n  ThereIsTail = false;\n  UnexpecedEnd = false;\n  IgnoreTail = false;\n  // NonZerosTail = false;\n  ErrorFlags_Defined = false;\n  ErrorFlags = 0;\n  WarningFlags = 0;\n  TailSize = 0;\n\n  ErrorMessage.Empty();\n  WarningMessage.Empty();\n}\n\nHRESULT CArc::ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes)\n{\n  // OkPhySize_Defined = false;\n  PhySize_Defined = false;\n  PhySize = 0;\n  Offset = 0;\n  AvailPhySize = FileSize - startPos;\n\n  ErrorInfo.ClearErrors();\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidErrorFlags, &prop))\n    ErrorInfo.ErrorFlags = GetOpenArcErrorFlags(prop, &ErrorInfo.ErrorFlags_Defined);\n  }\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidWarningFlags, &prop))\n    ErrorInfo.WarningFlags = GetOpenArcErrorFlags(prop);\n  }\n\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidError, &prop))\n    if (prop.vt != VT_EMPTY)\n      ErrorInfo.ErrorMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L\"Unknown error\");\n  }\n  \n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidWarning, &prop))\n    if (prop.vt != VT_EMPTY)\n      ErrorInfo.WarningMessage = (prop.vt == VT_BSTR ? prop.bstrVal : L\"Unknown warning\");\n  }\n  \n  if (openRes == S_OK || ErrorInfo.IsArc_After_NonOpen())\n  {\n    RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, PhySize, PhySize_Defined))\n    /*\n    RINOK(Archive_GetArcProp_UInt(archive, kpidOkPhySize, OkPhySize, OkPhySize_Defined));\n    if (!OkPhySize_Defined)\n    {\n      OkPhySize_Defined = PhySize_Defined;\n      OkPhySize = PhySize;\n    }\n    */\n\n    bool offsetDefined;\n    RINOK(Archive_GetArcProp_Int(archive, kpidOffset, Offset, offsetDefined))\n\n    Int64 globalOffset = (Int64)startPos + Offset;\n    AvailPhySize = (UInt64)((Int64)FileSize - globalOffset);\n    if (PhySize_Defined)\n    {\n      UInt64 endPos = (UInt64)(globalOffset + (Int64)PhySize);\n      if (endPos < FileSize)\n      {\n        AvailPhySize = PhySize;\n        ErrorInfo.ThereIsTail = true;\n        ErrorInfo.TailSize = FileSize - endPos;\n      }\n      else if (endPos > FileSize)\n        ErrorInfo.UnexpecedEnd = true;\n    }\n  }\n\n  return S_OK;\n}\n\n/*\nstatic void PrintNumber(const char *s, int n)\n{\n  char temp[100];\n  sprintf(temp, \"%s %d\", s, n);\n  // OutputDebugStringA(temp);\n  printf(temp);\n}\n*/\n\nHRESULT CArc::PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive)\n{\n  // OutputDebugStringA(\"a1\");\n  // PrintNumber(\"formatIndex\", formatIndex);\n    \n  RINOK(op.codecs->CreateInArchive(formatIndex, archive))\n  // OutputDebugStringA(\"a2\");\n  if (!archive)\n    return S_OK;\n\n  #ifdef Z7_EXTERNAL_CODECS\n  if (op.codecs->NeedSetLibCodecs)\n  {\n    const CArcInfoEx &ai = op.codecs->Formats[formatIndex];\n    if (ai.LibIndex >= 0 ?\n        !op.codecs->Libs[(unsigned)ai.LibIndex].SetCodecs :\n        !op.codecs->Libs.IsEmpty())\n    {\n      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;\n      archive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);\n      if (setCompressCodecsInfo)\n      {\n        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(op.codecs))\n      }\n    }\n  }\n  #endif\n  \n  \n  #ifndef Z7_SFX\n\n  const CArcInfoEx &ai = op.codecs->Formats[formatIndex];\n \n  // OutputDebugStringW(ai.Name);\n  // OutputDebugStringA(\"a3\");\n\n  if (ai.Flags_PreArc())\n  {\n    /* we notify parsers that extract executables, that they don't need\n       to open archive, if there is tail after executable (for SFX cases) */\n    CMyComPtr<IArchiveAllowTail> allowTail;\n    archive.QueryInterface(IID_IArchiveAllowTail, (void **)&allowTail);\n    if (allowTail)\n      allowTail->AllowTail(BoolToInt(true));\n  }\n\n  if (op.props)\n  {\n    /*\n    FOR_VECTOR (y, op.props)\n    {\n      const COptionalOpenProperties &optProps = (*op.props)[y];\n      if (optProps.FormatName.IsEmpty() || optProps.FormatName.CompareNoCase(ai.Name) == 0)\n      {\n        RINOK(SetProperties(archive, optProps.Props));\n        break;\n      }\n    }\n    */\n    RINOK(SetProperties(archive, *op.props))\n  }\n  \n  #endif\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\nstatic HRESULT ReadParseItemProps(IInArchive *archive, const CArcInfoEx &ai, NArchive::NParser::CParseItem &pi)\n{\n  pi.Extension = ai.GetMainExt();\n  pi.FileTime_Defined = false;\n  pi.ArcType = ai.Name;\n  \n  RINOK(Archive_GetArcProp_Bool(archive, kpidIsNotArcType, pi.IsNotArcType))\n\n  // RINOK(Archive_GetArcProp_Bool(archive, kpidIsSelfExe, pi.IsSelfExe));\n  pi.IsSelfExe = ai.Flags_PreArc();\n  \n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidMTime, &prop))\n    if (prop.vt == VT_FILETIME)\n    {\n      pi.FileTime_Defined = true;\n      pi.FileTime = prop.filetime;\n    }\n  }\n  \n  if (!pi.FileTime_Defined)\n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidCTime, &prop))\n    if (prop.vt == VT_FILETIME)\n    {\n      pi.FileTime_Defined = true;\n      pi.FileTime = prop.filetime;\n    }\n  }\n  \n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidName, &prop))\n    if (prop.vt == VT_BSTR)\n    {\n      pi.Name.SetFromBstr(prop.bstrVal);\n      pi.Extension.Empty();\n    }\n    else\n    {\n      RINOK(archive->GetArchiveProperty(kpidExtension, &prop))\n      if (prop.vt == VT_BSTR)\n        pi.Extension.SetFromBstr(prop.bstrVal);\n    }\n  }\n  \n  {\n    NCOM::CPropVariant prop;\n    RINOK(archive->GetArchiveProperty(kpidShortComment, &prop))\n    if (prop.vt == VT_BSTR)\n      pi.Comment.SetFromBstr(prop.bstrVal);\n  }\n\n\n  UInt32 numItems;\n  RINOK(archive->GetNumberOfItems(&numItems))\n  \n  // pi.NumSubFiles = numItems;\n  // RINOK(Archive_GetArcProp_UInt(archive, kpidUnpackSize, pi.UnpackSize, pi.UnpackSize_Defined));\n  // if (!pi.UnpackSize_Defined)\n  {\n    pi.NumSubFiles = 0;\n    pi.NumSubDirs = 0;\n    pi.UnpackSize = 0;\n    for (UInt32 i = 0; i < numItems; i++)\n    {\n      UInt64 size = 0;\n      bool defined = false;\n      Archive_GetItem_Size(archive, i, size, defined);\n      if (defined)\n      {\n        pi.UnpackSize_Defined = true;\n        pi.UnpackSize += size;\n      }\n\n      bool isDir = false;\n      Archive_IsItem_Dir(archive, i, isDir);\n      if (isDir)\n        pi.NumSubDirs++;\n      else\n        pi.NumSubFiles++;\n    }\n    if (pi.NumSubDirs != 0)\n      pi.NumSubDirs_Defined = true;\n    pi.NumSubFiles_Defined = true;\n  }\n\n  return S_OK;\n}\n\n#endif\n\nHRESULT CArc::CheckZerosTail(const COpenOptions &op, UInt64 offset)\n{\n  if (!op.stream)\n    return S_OK;\n  RINOK(InStream_SeekSet(op.stream, offset))\n  const UInt32 kBufSize = 1 << 11;\n  Byte buf[kBufSize];\n  \n  for (;;)\n  {\n    UInt32 processed = 0;\n    RINOK(op.stream->Read(buf, kBufSize, &processed))\n    if (processed == 0)\n    {\n      // ErrorInfo.NonZerosTail = false;\n      ErrorInfo.IgnoreTail = true;\n      return S_OK;\n    }\n    for (size_t i = 0; i < processed; i++)\n    {\n      if (buf[i] != 0)\n      {\n        // ErrorInfo.IgnoreTail = false;\n        // ErrorInfo.NonZerosTail = true;\n        return S_OK;\n      }\n    }\n  }\n}\n\n\n\n#ifndef Z7_SFX\n\nZ7_CLASS_IMP_COM_2(\n  CExtractCallback_To_OpenCallback\n  , IArchiveExtractCallback\n  , ICompressProgressInfo\n)\n  Z7_IFACE_COM7_IMP(IProgress)\npublic:\n  CMyComPtr<IArchiveOpenCallback> Callback;\n  UInt64 Files;\n  UInt64 Offset;\n\n  void Init(IArchiveOpenCallback *callback)\n  {\n    Callback = callback;\n    Files = 0;\n    Offset = 0;\n  }\n};\n\nZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetTotal(UInt64 /* size */))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetCompleted(const UInt64 * /* completeValue */))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))\n{\n  if (Callback)\n  {\n    UInt64 value = Offset;\n    if (inSize)\n      value += *inSize;\n    return Callback->SetCompleted(&Files, &value);\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::GetStream(UInt32 /* index */, ISequentialOutStream **outStream, Int32 /* askExtractMode */))\n{\n  *outStream = NULL;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::PrepareOperation(Int32 /* askExtractMode */))\n{\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallback_To_OpenCallback::SetOperationResult(Int32 /* operationResult */))\n{\n  return S_OK;\n}\n\n\nstatic HRESULT OpenArchiveSpec(IInArchive *archive, bool needPhySize,\n    IInStream *stream, const UInt64 *maxCheckStartPosition,\n    IArchiveOpenCallback *openCallback,\n    IArchiveExtractCallback *extractCallback)\n{\n  /*\n  if (needPhySize)\n  {\n    Z7_DECL_CMyComPtr_QI_FROM(\n        IArchiveOpen2,\n        open2, archive)\n    if (open2)\n      return open2->ArcOpen2(stream, kOpenFlags_RealPhySize, openCallback);\n  }\n  */\n  RINOK(archive->Open(stream, maxCheckStartPosition, openCallback))\n  if (needPhySize)\n  {\n    bool phySize_Defined = false;\n    UInt64 phySize = 0;\n    RINOK(Archive_GetArcProp_UInt(archive, kpidPhySize, phySize, phySize_Defined))\n    if (phySize_Defined)\n      return S_OK;\n\n    bool phySizeCantBeDetected = false;\n    RINOK(Archive_GetArcProp_Bool(archive, kpidPhySizeCantBeDetected, phySizeCantBeDetected))\n\n    if (!phySizeCantBeDetected)\n    {\n      PRF(printf(\"\\n-- !phySize_Defined after Open, call archive->Extract()\"));\n      // It's for bzip2/gz and some xz archives, where Open operation doesn't know phySize.\n      // But the Handler will know phySize after full archive testing.\n      RINOK(archive->Extract(NULL, (UInt32)(Int32)-1, BoolToInt(true), extractCallback))\n      PRF(printf(\"\\n-- OK\"));\n    }\n  }\n  return S_OK;\n}\n\n\n\nstatic int FindFormatForArchiveType(CCodecs *codecs, CIntVector orderIndices, const char *name)\n{\n  FOR_VECTOR (i, orderIndices)\n  {\n    int oi = orderIndices[i];\n    if (oi >= 0)\n      if (StringsAreEqualNoCase_Ascii(codecs->Formats[(unsigned)oi].Name, name))\n        return (int)i;\n  }\n  return -1;\n}\n\n#endif\n\nHRESULT CArc::OpenStream2(const COpenOptions &op)\n{\n  // fprintf(stdout, \"\\nOpen: %S\", Path); fflush(stdout);\n\n  Archive.Release();\n  GetRawProps.Release();\n  GetRootProps.Release();\n\n  ErrorInfo.ClearErrors();\n  ErrorInfo.ErrorFormatIndex = -1;\n\n  IsParseArc = false;\n  ArcStreamOffset = 0;\n  \n  // OutputDebugStringA(\"1\");\n  // OutputDebugStringW(Path);\n\n  const UString fileName = ExtractFileNameFromPath(Path);\n  UString extension;\n  {\n    const int dotPos = fileName.ReverseFind_Dot();\n    if (dotPos >= 0)\n      extension = fileName.Ptr((unsigned)(dotPos + 1));\n  }\n  \n  CIntVector orderIndices;\n  \n  bool searchMarkerInHandler = false;\n  #ifdef Z7_SFX\n    searchMarkerInHandler = true;\n  #endif\n\n  CBoolArr isMainFormatArr(op.codecs->Formats.Size());\n  {\n    FOR_VECTOR(i, op.codecs->Formats)\n      isMainFormatArr[i] = false;\n  }\n\n  const UInt64 maxStartOffset =\n      op.openType.MaxStartOffset_Defined ?\n      op.openType.MaxStartOffset :\n      kMaxCheckStartPosition;\n\n  #ifndef Z7_SFX\n  bool isUnknownExt = false;\n  #endif\n\n  #ifndef Z7_SFX\n  bool isForced = false;\n  #endif\n\n  unsigned numMainTypes = 0;\n  const int formatIndex = op.openType.FormatIndex;\n\n  if (formatIndex >= 0)\n  {\n    #ifndef Z7_SFX\n    isForced = true;\n    #endif\n    orderIndices.Add(formatIndex);\n    numMainTypes = 1;\n    isMainFormatArr[(unsigned)formatIndex] = true;\n\n    searchMarkerInHandler = true;\n  }\n  else\n  {\n    unsigned numFinded = 0;\n    #ifndef Z7_SFX\n    bool isPrearcExt = false;\n    #endif\n    \n    {\n      #ifndef Z7_SFX\n      \n      bool isZip = false;\n      bool isRar = false;\n      \n      const wchar_t c = extension[0];\n      if (c == 'z' || c == 'Z' || c == 'r' || c == 'R')\n      {\n        bool isNumber = false;\n        for (unsigned k = 1;; k++)\n        {\n          const wchar_t d = extension[k];\n          if (d == 0)\n            break;\n          if (d < '0' || d > '9')\n          {\n            isNumber = false;\n            break;\n          }\n          isNumber = true;\n        }\n        if (isNumber)\n        {\n          if (c == 'z' || c == 'Z')\n            isZip = true;\n          else\n            isRar = true;\n        }\n      }\n      \n      #endif\n\n      FOR_VECTOR (i, op.codecs->Formats)\n      {\n        const CArcInfoEx &ai = op.codecs->Formats[i];\n\n        if (IgnoreSplit || !op.openType.CanReturnArc)\n          if (ai.Is_Split())\n            continue;\n        if (op.excludedFormats->FindInSorted((int)i) >= 0)\n          continue;\n\n        #ifndef Z7_SFX\n        if (IsPreArcFormat(ai))\n          isPrearcExt = true;\n        #endif\n\n        if (ai.FindExtension(extension) >= 0\n            #ifndef Z7_SFX\n            || (isZip && ai.Is_Zip())\n            || (isRar && ai.Is_Rar())\n            #endif\n            )\n        {\n          // PrintNumber(\"orderIndices.Insert\", i);\n          orderIndices.Insert(numFinded++, (int)i);\n          isMainFormatArr[i] = true;\n        }\n        else\n          orderIndices.Add((int)i);\n      }\n    }\n  \n    if (!op.stream)\n    {\n      if (numFinded != 1)\n        return E_NOTIMPL;\n      orderIndices.DeleteFrom(1);\n    }\n    // PrintNumber(\"numFinded\", numFinded );\n\n    /*\n    if (op.openOnlySpecifiedByExtension)\n    {\n      if (numFinded != 0 && !IsExeExt(extension))\n        orderIndices.DeleteFrom(numFinded);\n    }\n    */\n\n    #ifndef Z7_SFX\n\n      if (op.stream && orderIndices.Size() >= 2)\n      {\n        RINOK(InStream_SeekToBegin(op.stream))\n        CByteBuffer byteBuffer;\n        CIntVector orderIndices2;\n        if (numFinded == 0 || IsExeExt(extension))\n        {\n          // signature search was here\n        }\n        else if (extension.IsEqualTo(\"000\") || extension.IsEqualTo(\"001\"))\n        {\n          const int i = FindFormatForArchiveType(op.codecs, orderIndices, \"rar\");\n          if (i >= 0)\n          {\n            const size_t kBufSize = (1 << 10);\n            byteBuffer.Alloc(kBufSize);\n            size_t processedSize = kBufSize;\n            RINOK(ReadStream(op.stream, byteBuffer, &processedSize))\n            if (processedSize >= 16)\n            {\n              const Byte *buf = byteBuffer;\n              const Byte kRarHeader[] = { 0x52 , 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 };\n              if (TestSignature(buf, kRarHeader, 7) && buf[9] == 0x73 && (buf[10] & 1) != 0)\n              {\n                orderIndices2.Add(orderIndices[(unsigned)i]);\n                orderIndices[(unsigned)i] = -1;\n                if (i >= (int)numFinded)\n                  numFinded++;\n              }\n            }\n          }\n        }\n        else\n        {\n          const size_t kBufSize = (1 << 10);\n          byteBuffer.Alloc(kBufSize);\n          size_t processedSize = kBufSize;\n          RINOK(ReadStream(op.stream, byteBuffer, &processedSize))\n          if (processedSize == 0)\n            return S_FALSE;\n          \n          /*\n          check type order:\n            0) matched_extension && Backward\n            1) matched_extension && (no_signuature || SignatureOffset != 0)\n            2) matched_extension && (matched_signature)\n            // 3) no signuature\n            // 4) matched signuature\n          */\n          // we move index from orderIndices to orderIndices2 for priority handlers.\n\n          for (unsigned i = 0; i < numFinded; i++)\n          {\n            const int index = orderIndices[i];\n            if (index < 0)\n              continue;\n            const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];\n            if (ai.Flags_BackwardOpen())\n            {\n              // backward doesn't need start signatures\n              orderIndices2.Add(index);\n              orderIndices[i] = -1;\n            }\n          }\n\n          MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, NULL, 0);\n          MakeCheckOrder(op.codecs, orderIndices, numFinded, orderIndices2, byteBuffer, processedSize);\n          // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, NULL, 0);\n          // MakeCheckOrder(op.codecs, orderIndices, orderIndices.Size(), orderIndices2, byteBuffer, processedSize);\n        }\n      \n        FOR_VECTOR (i, orderIndices)\n        {\n          const int val = orderIndices[i];\n          if (val != -1)\n            orderIndices2.Add(val);\n        }\n        orderIndices = orderIndices2;\n      }\n      \n      if (orderIndices.Size() >= 2)\n      {\n        const int iIso = FindFormatForArchiveType(op.codecs, orderIndices, \"iso\");\n        const int iUdf = FindFormatForArchiveType(op.codecs, orderIndices, \"udf\");\n        if (iUdf > iIso && iIso >= 0)\n        {\n          const int isoIndex = orderIndices[(unsigned)iIso];\n          const int udfIndex = orderIndices[(unsigned)iUdf];\n          orderIndices[(unsigned)iUdf] = isoIndex;\n          orderIndices[(unsigned)iIso] = udfIndex;\n        }\n      }\n\n      numMainTypes = numFinded;\n      isUnknownExt = (numMainTypes == 0) || isPrearcExt;\n\n    #else // Z7_SFX\n\n      numMainTypes = orderIndices.Size();\n\n      // we need correct numMainTypes for mutlivolume SFX (if some volume is missing)\n      if (numFinded != 0)\n        numMainTypes = numFinded;\n    \n    #endif\n  }\n\n  UInt64 fileSize = 0;\n  if (op.stream)\n  {\n    RINOK(InStream_GetSize_SeekToBegin(op.stream, fileSize))\n  }\n  FileSize = fileSize;\n\n\n  #ifndef Z7_SFX\n\n  CBoolArr skipFrontalFormat(op.codecs->Formats.Size());\n  {\n    FOR_VECTOR(i, op.codecs->Formats)\n      skipFrontalFormat[i] = false;\n  }\n  \n  #endif\n\n  const COpenType &mode = op.openType;\n\n  \n  \n\n  \n  if (mode.CanReturnArc)\n  {\n    // ---------- OPEN main type by extenssion ----------\n  \n    unsigned numCheckTypes = orderIndices.Size();\n    if (formatIndex >= 0)\n      numCheckTypes = numMainTypes;\n    \n    for (unsigned i = 0; i < numCheckTypes; i++)\n    {\n      FormatIndex = orderIndices[i];\n\n      // orderIndices[] item cannot be negative here\n      \n      bool exactOnly = false;\n\n      #ifndef Z7_SFX\n    \n      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex];\n      // OutputDebugStringW(ai.Name);\n      if (i >= numMainTypes)\n      {\n        // here we allow mismatched extension only for backward handlers\n        if (!ai.Flags_BackwardOpen()\n            // && !ai.Flags_PureStartOpen()\n            )\n          continue;\n        exactOnly = true;\n      }\n\n      #endif\n      \n      // Some handlers do not set total bytes. So we set it here\n      if (op.callback)\n        RINOK(op.callback->SetTotal(NULL, &fileSize))\n\n      if (op.stream)\n      {\n        RINOK(InStream_SeekToBegin(op.stream))\n      }\n      \n      CMyComPtr<IInArchive> archive;\n      \n      RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive))\n      if (!archive)\n        continue;\n      \n      HRESULT result;\n      if (op.stream)\n      {\n        UInt64 searchLimit = (!exactOnly && searchMarkerInHandler) ? maxStartOffset: 0;\n        result = archive->Open(op.stream, &searchLimit, op.callback);\n      }\n      else\n      {\n        CMyComPtr<IArchiveOpenSeq> openSeq;\n        archive.QueryInterface(IID_IArchiveOpenSeq, (void **)&openSeq);\n        if (!openSeq)\n          return E_NOTIMPL;\n        result = openSeq->OpenSeq(op.seqStream);\n      }\n      \n      RINOK(ReadBasicProps(archive, 0, result))\n      \n      if (result == S_FALSE)\n      {\n        bool isArc = ErrorInfo.IsArc_After_NonOpen();\n\n        #ifndef Z7_SFX\n        // if it's archive, we allow another open attempt for parser\n        if (!mode.CanReturnParser || !isArc)\n          skipFrontalFormat[(unsigned)FormatIndex] = true;\n        #endif\n        \n        if (exactOnly)\n          continue;\n        \n        if (i == 0 && numMainTypes == 1)\n        {\n          // we set NonOpenErrorInfo, only if there is only one main format (defined by extension).\n          ErrorInfo.ErrorFormatIndex = FormatIndex;\n          NonOpen_ErrorInfo = ErrorInfo;\n       \n          if (!mode.CanReturnParser && isArc)\n          {\n            // if (formatIndex < 0 && !searchMarkerInHandler)\n            {\n              // if bad archive was detected, we don't need additional open attempts\n              #ifndef Z7_SFX\n              if (!IsPreArcFormat(ai) /* || !mode.SkipSfxStub */)\n              #endif\n                return S_FALSE;\n            }\n          }\n        }\n        \n        /*\n        #ifndef Z7_SFX\n        if (IsExeExt(extension) || ai.Flags_PreArc())\n        {\n        // openOnlyFullArc = false;\n        // canReturnTailArc = true;\n        // limitSignatureSearch = true;\n        }\n        #endif\n        */\n        \n        continue;\n      }\n      \n      RINOK(result)\n      \n      #ifndef Z7_SFX\n\n      bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];\n      const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);\n\n      bool thereIsTail = ErrorInfo.ThereIsTail;\n      if (thereIsTail && mode.ZerosTailIsAllowed)\n      {\n        RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize)))\n        if (ErrorInfo.IgnoreTail)\n          thereIsTail = false;\n      }\n\n      if (Offset > 0)\n      {\n        if (exactOnly\n            || !searchMarkerInHandler\n            || !specFlags.CanReturn_NonStart()\n            || (mode.MaxStartOffset_Defined && (UInt64)Offset > mode.MaxStartOffset))\n          continue;\n      }\n      if (thereIsTail)\n      {\n        if (Offset > 0)\n        {\n          if (!specFlags.CanReturnMid)\n            continue;\n        }\n        else if (!specFlags.CanReturnFrontal)\n          continue;\n      }\n\n      if (Offset > 0 || thereIsTail)\n      {\n        if (formatIndex < 0)\n        {\n          if (IsPreArcFormat(ai))\n          {\n            // openOnlyFullArc = false;\n            // canReturnTailArc = true;\n            /*\n            if (mode.SkipSfxStub)\n            limitSignatureSearch = true;\n            */\n            // if (mode.SkipSfxStub)\n            {\n              // skipFrontalFormat[FormatIndex] = true;\n              continue;\n            }\n          }\n        }\n      }\n     \n      #endif\n\n      Archive = archive;\n      return S_OK;\n    }\n  }\n\n  \n\n  #ifndef Z7_SFX\n\n  if (!op.stream)\n    return S_FALSE;\n\n  if (formatIndex >= 0 && !mode.CanReturnParser)\n  {\n    if (mode.MaxStartOffset_Defined)\n    {\n      if (mode.MaxStartOffset == 0)\n        return S_FALSE;\n    }\n    else\n    {\n      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)formatIndex];\n      if (ai.FindExtension(extension) >= 0)\n      {\n        if (ai.Flags_FindSignature() && searchMarkerInHandler)\n          return S_FALSE;\n      }\n    }\n  }\n\n  NArchive::NParser::CHandler *handlerSpec = new NArchive::NParser::CHandler;\n  CMyComPtr<IInArchive> handler = handlerSpec;\n\n  CExtractCallback_To_OpenCallback *extractCallback_To_OpenCallback_Spec = new CExtractCallback_To_OpenCallback;\n  CMyComPtr<IArchiveExtractCallback> extractCallback_To_OpenCallback = extractCallback_To_OpenCallback_Spec;\n  extractCallback_To_OpenCallback_Spec->Init(op.callback);\n\n  {\n    // ---------- Check all possible START archives ----------\n    // this code is better for full file archives than Parser's code.\n\n    CByteBuffer byteBuffer;\n    bool endOfFile = false;\n    size_t processedSize;\n    {\n      size_t bufSize = 1 << 20; // it must be larger than max signature offset or IsArcFunc offset ((1 << 19) + x for UDF)\n      if (bufSize > fileSize)\n      {\n        bufSize = (size_t)fileSize;\n        endOfFile = true;\n      }\n      byteBuffer.Alloc(bufSize);\n      RINOK(InStream_SeekToBegin(op.stream))\n      processedSize = bufSize;\n      RINOK(ReadStream(op.stream, byteBuffer, &processedSize))\n      if (processedSize == 0)\n        return S_FALSE;\n      if (processedSize < bufSize)\n        endOfFile = true;\n    }\n    CUIntVector sortedFormats;\n\n    unsigned i;\n\n    int splitIndex = -1;\n\n    for (i = 0; i < orderIndices.Size(); i++)\n    {\n      // orderIndices[] item cannot be negative here\n      unsigned form = (unsigned)orderIndices[i];\n      if (skipFrontalFormat[form])\n        continue;\n      \n      const CArcInfoEx &ai = op.codecs->Formats[form];\n      \n      if (ai.Is_Split())\n      {\n        splitIndex = (int)form;\n        continue;\n      }\n\n      if (ai.Flags_ByExtOnlyOpen())\n        continue;\n\n      if (ai.IsArcFunc)\n      {\n        UInt32 isArcRes = ai.IsArcFunc(byteBuffer, processedSize);\n        if (isArcRes == k_IsArc_Res_NO)\n          continue;\n        if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)\n          continue;\n        // if (isArcRes == k_IsArc_Res_YES_LOW_PROB) continue;\n        sortedFormats.Insert(0, form);\n        continue;\n      }\n\n      const bool isNewStyleSignature = IsNewStyleSignature(ai);\n      bool needCheck = !isNewStyleSignature\n          || ai.Signatures.IsEmpty()\n          || ai.Flags_PureStartOpen()\n          || ai.Flags_StartOpen()\n          || ai.Flags_BackwardOpen();\n    \n      if (isNewStyleSignature && !ai.Signatures.IsEmpty())\n      {\n        unsigned k;\n        for (k = 0; k < ai.Signatures.Size(); k++)\n        {\n          const CByteBuffer &sig = ai.Signatures[k];\n          if (processedSize < ai.SignatureOffset + sig.Size())\n          {\n            if (!endOfFile)\n              needCheck = true;\n          }\n          else if (TestSignature(sig, byteBuffer + ai.SignatureOffset, sig.Size()))\n            break;\n        }\n        if (k != ai.Signatures.Size())\n        {\n          sortedFormats.Insert(0, form);\n          continue;\n        }\n      }\n      if (needCheck)\n        sortedFormats.Add(form);\n    }\n\n    if (splitIndex >= 0)\n      sortedFormats.Insert(0, (unsigned)splitIndex);\n\n    for (i = 0; i < sortedFormats.Size(); i++)\n    {\n      FormatIndex = (int)sortedFormats[i];\n      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex];\n\n      if (op.callback)\n        RINOK(op.callback->SetTotal(NULL, &fileSize))\n\n      RINOK(InStream_SeekToBegin(op.stream))\n\n      CMyComPtr<IInArchive> archive;\n      RINOK(PrepareToOpen(op, (unsigned)FormatIndex, archive))\n      if (!archive)\n        continue;\n      \n      PRF(printf(\"\\nSorted Open %S\", (const wchar_t *)ai.Name));\n      HRESULT result;\n      {\n        UInt64 searchLimit = 0;\n        /*\n        if (mode.CanReturnArc)\n          result = archive->Open(op.stream, &searchLimit, op.callback);\n        else\n        */\n        // if (!CanReturnArc), it's ParserMode, and we need phy size\n        result = OpenArchiveSpec(archive,\n            !mode.CanReturnArc, // needPhySize\n            op.stream, &searchLimit, op.callback, extractCallback_To_OpenCallback);\n      }\n      \n      if (result == S_FALSE)\n      {\n        skipFrontalFormat[(unsigned)FormatIndex] = true;\n        // FIXME: maybe we must use LenIsUnknown.\n        // printf(\"  OpenForSize Error\");\n        continue;\n      }\n      RINOK(result)\n\n      RINOK(ReadBasicProps(archive, 0, result))\n\n      if (Offset > 0)\n      {\n        continue; // good handler doesn't return such Offset > 0\n        // but there are some cases like false prefixed PK00 archive, when\n        // we can support it?\n      }\n\n      NArchive::NParser::CParseItem pi;\n      pi.Offset = (UInt64)Offset;\n      pi.Size = AvailPhySize;\n      \n      // bool needScan = false;\n\n      if (!PhySize_Defined)\n      {\n        // it's for Z format\n        pi.LenIsUnknown = true;\n        // needScan = true;\n        // phySize = arcRem;\n        // nextNeedCheckStartOpen = false;\n      }\n\n      /*\n      if (OkPhySize_Defined)\n        pi.OkSize = pi.OkPhySize;\n      else\n        pi.OkSize = pi.Size;\n      */\n\n      pi.NormalizeOffset();\n      // printf(\"  phySize = %8d\", (unsigned)phySize);\n\n\n      if (mode.CanReturnArc)\n      {\n        const bool isMainFormat = isMainFormatArr[(unsigned)FormatIndex];\n        const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);\n        bool openCur = false;\n\n        if (!ErrorInfo.ThereIsTail)\n          openCur = true;\n        else\n        {\n          if (mode.ZerosTailIsAllowed)\n          {\n            RINOK(CheckZerosTail(op, (UInt64)(Offset + (Int64)PhySize)))\n            if (ErrorInfo.IgnoreTail)\n              openCur = true;\n          }\n          if (!openCur)\n          {\n            openCur = specFlags.CanReturnFrontal;\n            if (formatIndex < 0) // format is not forced\n            {\n              if (IsPreArcFormat(ai))\n              {\n                // if (mode.SkipSfxStub)\n                {\n                  openCur = false;\n                }\n              }\n            }\n          }\n        }\n        \n        if (openCur)\n        {\n          InStream = op.stream;\n          Archive = archive;\n          return S_OK;\n        }\n      }\n        \n      skipFrontalFormat[(unsigned)FormatIndex] = true;\n\n\n      // if (!mode.CanReturnArc)\n      /*\n      if (!ErrorInfo.ThereIsTail)\n          continue;\n      */\n      if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)\n        continue;\n\n      // printf(\"\\nAdd offset = %d\", (int)pi.Offset);\n      RINOK(ReadParseItemProps(archive, ai, pi))\n      handlerSpec->AddItem(pi);\n    }\n  }\n\n  \n\n  \n  \n  // ---------- PARSER ----------\n\n  CUIntVector arc2sig; // formatIndex to signatureIndex\n  CUIntVector sig2arc; // signatureIndex to formatIndex;\n  {\n    unsigned sum = 0;\n    FOR_VECTOR (i, op.codecs->Formats)\n    {\n      arc2sig.Add(sum);\n      const CObjectVector<CByteBuffer> &sigs = op.codecs->Formats[i].Signatures;\n      sum += sigs.Size();\n      FOR_VECTOR (k, sigs)\n        sig2arc.Add(i);\n    }\n  }\n  \n  {\n    const size_t kBeforeSize = 1 << 16;\n    const size_t kAfterSize  = 1 << 20;\n    const size_t kBufSize = 1 << 22; // it must be more than kBeforeSize + kAfterSize\n\n    const UInt32 kNumVals = (UInt32)1 << (kNumHashBytes * 8);\n    CByteArr hashBuffer(kNumVals);\n    Byte *hash = hashBuffer;\n    memset(hash, 0xFF, kNumVals);\n    Byte prevs[256];\n    memset(prevs, 0xFF, sizeof(prevs));\n    if (sig2arc.Size() >= 0xFF)\n      return S_FALSE;\n\n    CUIntVector difficultFormats;\n    CBoolArr difficultBools(256);\n    {\n      for (unsigned i = 0; i < 256; i++)\n        difficultBools[i] = false;\n    }\n\n    bool thereAreHandlersForSearch = false;\n\n    // UInt32 maxSignatureEnd = 0;\n    \n    FOR_VECTOR (i, orderIndices)\n    {\n      int index = orderIndices[i];\n      if (index < 0)\n        continue;\n      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)index];\n      if (ai.Flags_ByExtOnlyOpen())\n        continue;\n      bool isDifficult = false;\n      // if (ai.Version < 0x91F) // we don't use parser with old DLL (before 9.31)\n      if (!ai.NewInterface)\n        isDifficult = true;\n      else\n      {\n        if (ai.Flags_StartOpen())\n          isDifficult = true;\n        FOR_VECTOR (k, ai.Signatures)\n        {\n          const CByteBuffer &sig = ai.Signatures[k];\n          /*\n          UInt32 signatureEnd = ai.SignatureOffset + (UInt32)sig.Size();\n          if (maxSignatureEnd < signatureEnd)\n            maxSignatureEnd = signatureEnd;\n          */\n          if (sig.Size() < kNumHashBytes)\n          {\n            isDifficult = true;\n            continue;\n          }\n          thereAreHandlersForSearch = true;\n          UInt32 v = HASH_VAL(sig);\n          unsigned sigIndex = arc2sig[(unsigned)index] + k;\n          prevs[sigIndex] = hash[v];\n          hash[v] = (Byte)sigIndex;\n        }\n      }\n      if (isDifficult)\n      {\n        difficultFormats.Add((unsigned)index);\n        difficultBools[(unsigned)index] = true;\n      }\n    }\n    \n    if (!thereAreHandlersForSearch)\n    {\n      // openOnlyFullArc = true;\n      // canReturnTailArc = true;\n    }\n    \n    RINOK(InStream_SeekToBegin(op.stream))\n\n    CLimitedCachedInStream *limitedStreamSpec = new CLimitedCachedInStream;\n    CMyComPtr<IInStream> limitedStream = limitedStreamSpec;\n    limitedStreamSpec->SetStream(op.stream);\n\n    CArchiveOpenCallback_Offset *openCallback_Offset_Spec = NULL;\n    CMyComPtr<IArchiveOpenCallback> openCallback_Offset;\n    if (op.callback)\n    {\n      openCallback_Offset_Spec = new CArchiveOpenCallback_Offset;\n      openCallback_Offset = openCallback_Offset_Spec;\n      openCallback_Offset_Spec->Callback = op.callback;\n      openCallback_Offset_Spec->Callback.QueryInterface(IID_IArchiveOpenVolumeCallback, &openCallback_Offset_Spec->OpenVolumeCallback);\n      #ifndef Z7_NO_CRYPTO\n      openCallback_Offset_Spec->Callback.QueryInterface(IID_ICryptoGetTextPassword, &openCallback_Offset_Spec->GetTextPassword);\n      #endif\n    }\n\n    if (op.callback)\n      RINOK(op.callback->SetTotal(NULL, &fileSize))\n  \n    CByteBuffer &byteBuffer = limitedStreamSpec->Buffer;\n    byteBuffer.Alloc(kBufSize);\n\n    UInt64 callbackPrev = 0;\n    bool needCheckStartOpen = true; // = true, if we need to test all archives types for current pos.\n\n    bool endOfFile = false;\n    UInt64 bufPhyPos = 0;\n    size_t bytesInBuf = 0;\n    // UInt64 prevPos = 0;\n    \n    // ---------- Main Scan Loop ----------\n\n    UInt64 pos = 0;\n\n    if (!mode.EachPos && handlerSpec->_items.Size() == 1)\n    {\n      NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];\n      if (!pi.LenIsUnknown && pi.Offset == 0)\n        pos = pi.Size;\n    }\n\n    for (;;)\n    {\n      // printf(\"\\nPos = %d\", (int)pos);\n      UInt64 posInBuf = pos - bufPhyPos;\n      \n      // if (pos > ((UInt64)1 << 35)) break;\n      \n      if (!endOfFile)\n      {\n        if (bytesInBuf < kBufSize)\n        {\n          size_t processedSize = kBufSize - bytesInBuf;\n          // printf(\"\\nRead ask = %d\", (unsigned)processedSize);\n          UInt64 seekPos = bufPhyPos + bytesInBuf;\n          RINOK(InStream_SeekSet(op.stream, bufPhyPos + bytesInBuf))\n          RINOK(ReadStream(op.stream, byteBuffer.NonConstData() + bytesInBuf, &processedSize))\n          // printf(\"   processed = %d\", (unsigned)processedSize);\n          if (processedSize == 0)\n          {\n            fileSize = seekPos;\n            endOfFile = true;\n          }\n          else\n          {\n            bytesInBuf += processedSize;\n            limitedStreamSpec->SetCache(processedSize, (size_t)bufPhyPos);\n          }\n          continue;\n        }\n        \n        if (bytesInBuf < posInBuf)\n        {\n          UInt64 skipSize = posInBuf - bytesInBuf;\n          if (skipSize <= kBeforeSize)\n          {\n            size_t keepSize = (size_t)(kBeforeSize - skipSize);\n            // printf(\"\\nmemmove skip = %d\", (int)keepSize);\n            memmove(byteBuffer, byteBuffer.ConstData() + bytesInBuf - keepSize, keepSize);\n            bytesInBuf = keepSize;\n            bufPhyPos = pos - keepSize;\n            continue;\n          }\n          // printf(\"\\nSkip %d\", (int)(skipSize - kBeforeSize));\n          // RINOK(op.stream->Seek(skipSize - kBeforeSize, STREAM_SEEK_CUR, NULL));\n          bytesInBuf = 0;\n          bufPhyPos = pos - kBeforeSize;\n          continue;\n        }\n        \n        if (bytesInBuf - posInBuf < kAfterSize)\n        {\n          size_t beg = (size_t)posInBuf - kBeforeSize;\n          // printf(\"\\nmemmove for after beg = %d\", (int)beg);\n          memmove(byteBuffer, byteBuffer.ConstData() + beg, bytesInBuf - beg);\n          bufPhyPos += beg;\n          bytesInBuf -= beg;\n          continue;\n        }\n      }\n\n      if (bytesInBuf <= (size_t)posInBuf)\n        break;\n\n      bool useOffsetCallback = false;\n      if (openCallback_Offset)\n      {\n        openCallback_Offset_Spec->Files = handlerSpec->_items.Size();\n        openCallback_Offset_Spec->Offset = pos;\n\n        useOffsetCallback = (!op.openType.CanReturnArc || handlerSpec->_items.Size() > 1);\n \n        if (pos >= callbackPrev + (1 << 23))\n        {\n          RINOK(openCallback_Offset->SetCompleted(NULL, NULL))\n          callbackPrev = pos;\n        }\n      }\n\n      {\n        UInt64 endPos = bufPhyPos + bytesInBuf;\n        if (fileSize < endPos)\n        {\n          FileSize = fileSize; // why ????\n          fileSize = endPos;\n        }\n      }\n\n      const size_t availSize = bytesInBuf - (size_t)posInBuf;\n      if (availSize < kNumHashBytes)\n        break;\n      size_t scanSize = availSize -\n          ((availSize >= kAfterSize) ? kAfterSize : kNumHashBytes);\n  \n      {\n        /*\n        UInt64 scanLimit = openOnlyFullArc ?\n            maxSignatureEnd :\n            op.openType.ScanSize + maxSignatureEnd;\n        */\n        if (!mode.CanReturnParser)\n        {\n          if (pos > maxStartOffset)\n            break;\n          UInt64 remScan = maxStartOffset - pos;\n          if (scanSize > remScan)\n            scanSize = (size_t)remScan;\n        }\n      }\n\n      scanSize++;\n\n      const Byte *buf = byteBuffer.ConstData() + (size_t)posInBuf;\n      const Byte *bufLimit = buf + scanSize;\n      size_t ppp = 0;\n      \n      if (!needCheckStartOpen)\n      {\n        for (; buf < bufLimit && hash[HASH_VAL(buf)] == 0xFF; buf++);\n        ppp = (size_t)(buf - (byteBuffer.ConstData() + (size_t)posInBuf));\n        pos += ppp;\n        if (buf == bufLimit)\n          continue;\n      }\n      \n      UInt32 v = HASH_VAL(buf);\n      bool nextNeedCheckStartOpen = true;\n      unsigned i = hash[v];\n      unsigned indexOfDifficult = 0;\n\n      // ---------- Open Loop for Current Pos ----------\n      bool wasOpen = false;\n      \n      for (;;)\n      {\n        unsigned index;\n        bool isDifficult;\n        if (needCheckStartOpen && indexOfDifficult < difficultFormats.Size())\n        {\n          index = difficultFormats[indexOfDifficult++];\n          isDifficult = true;\n        }\n        else\n        {\n          if (i == 0xFF)\n            break;\n          index = sig2arc[i];\n          unsigned sigIndex = i - arc2sig[index];\n          i = prevs[i];\n          if (needCheckStartOpen && difficultBools[index])\n            continue;\n          const CArcInfoEx &ai = op.codecs->Formats[index];\n\n          if (pos < ai.SignatureOffset)\n            continue;\n\n          /*\n          if (openOnlyFullArc)\n            if (pos != ai.SignatureOffset)\n              continue;\n          */\n  \n          const CByteBuffer &sig = ai.Signatures[sigIndex];\n\n          if (ppp + sig.Size() > availSize\n              || !TestSignature(buf, sig, sig.Size()))\n            continue;\n          // printf(\"\\nSignature OK: %10S %8x %5d\", (const wchar_t *)ai.Name, (int)pos, (int)(pos - prevPos));\n          // prevPos = pos;\n          isDifficult = false;\n        }\n\n        const CArcInfoEx &ai = op.codecs->Formats[index];\n\n\n        if ((isDifficult && pos == 0) || ai.SignatureOffset == pos)\n        {\n          // we don't check same archive second time */\n          if (skipFrontalFormat[index])\n            continue;\n        }\n\n        UInt64 startArcPos = pos;\n        if (!isDifficult)\n        {\n          if (pos < ai.SignatureOffset)\n            continue;\n          startArcPos = pos - ai.SignatureOffset;\n          /*\n          // we don't need the check for Z files\n          if (startArcPos < handlerSpec->GetLastEnd())\n            continue;\n          */\n        }\n        \n        if (ai.IsArcFunc && startArcPos >= bufPhyPos)\n        {\n          const size_t offsetInBuf = (size_t)(startArcPos - bufPhyPos);\n          if (offsetInBuf < bytesInBuf)\n          {\n            const UInt32 isArcRes = ai.IsArcFunc(byteBuffer.ConstData() + offsetInBuf, bytesInBuf - offsetInBuf);\n            if (isArcRes == k_IsArc_Res_NO)\n              continue;\n            if (isArcRes == k_IsArc_Res_NEED_MORE && endOfFile)\n              continue;\n            /*\n            if (isArcRes == k_IsArc_Res_YES_LOW_PROB)\n            {\n              // if (pos != ai.SignatureOffset)\n              continue;\n            }\n            */\n          }\n          // printf(\"\\nIsArc OK: %S\", (const wchar_t *)ai.Name);\n        }\n        \n        PRF(printf(\"\\npos = %9I64d : %S\", pos, (const wchar_t *)ai.Name));\n\n        const bool isMainFormat = isMainFormatArr[index];\n        const COpenSpecFlags &specFlags = mode.GetSpec(isForced, isMainFormat, isUnknownExt);\n        \n        CMyComPtr<IInArchive> archive;\n        RINOK(PrepareToOpen(op, index, archive))\n        if (!archive)\n          return E_FAIL;\n        \n        // OutputDebugStringW(ai.Name);\n        \n        const UInt64 rem = fileSize - startArcPos;\n        \n        UInt64 arcStreamOffset = 0;\n\n        if (ai.Flags_UseGlobalOffset())\n        {\n          RINOK(limitedStreamSpec->InitAndSeek(0, fileSize))\n          RINOK(InStream_SeekSet(limitedStream, startArcPos))\n        }\n        else\n        {\n          RINOK(limitedStreamSpec->InitAndSeek(startArcPos, rem))\n          arcStreamOffset = startArcPos;\n        }\n        \n        UInt64 maxCheckStartPosition = 0;\n        \n        if (openCallback_Offset)\n        {\n          openCallback_Offset_Spec->Files = handlerSpec->_items.Size();\n          openCallback_Offset_Spec->Offset = startArcPos;\n        }\n\n        // HRESULT result = archive->Open(limitedStream, &maxCheckStartPosition, openCallback_Offset);\n        extractCallback_To_OpenCallback_Spec->Files = 0;\n        extractCallback_To_OpenCallback_Spec->Offset = startArcPos;\n\n        HRESULT result = OpenArchiveSpec(archive,\n            true, // needPhySize\n            limitedStream, &maxCheckStartPosition,\n            useOffsetCallback ? (IArchiveOpenCallback *)openCallback_Offset : (IArchiveOpenCallback *)op.callback,\n            extractCallback_To_OpenCallback);\n\n        RINOK(ReadBasicProps(archive, ai.Flags_UseGlobalOffset() ? 0 : startArcPos, result))\n\n        bool isOpen = false;\n      \n        if (result == S_FALSE)\n        {\n          if (!mode.CanReturnParser)\n          {\n            if (formatIndex < 0 && ErrorInfo.IsArc_After_NonOpen())\n            {\n              ErrorInfo.ErrorFormatIndex = (int)index;\n              NonOpen_ErrorInfo = ErrorInfo;\n              // if archive was detected, we don't need additional open attempts\n              return S_FALSE;\n            }\n            continue;\n          }\n          if (!ErrorInfo.IsArc_After_NonOpen() || !PhySize_Defined || PhySize == 0)\n            continue;\n        }\n        else\n        {\n          if (PhySize_Defined && PhySize == 0)\n          {\n            PRF(printf(\"  phySize_Defined && PhySize == 0 \"));\n            // we skip that epmty archive case with unusual unexpected (PhySize == 0) from Code function.\n            continue;\n          }\n          isOpen = true;\n          RINOK(result)\n          PRF(printf(\"  OK \"));\n        }\n\n        // fprintf(stderr, \"\\n %8X  %S\", startArcPos, Path);\n        // printf(\"\\nOpen OK: %S\", ai.Name);\n        \n        \n        NArchive::NParser::CParseItem pi;\n        pi.Offset = startArcPos;\n\n        if (ai.Flags_UseGlobalOffset())\n          pi.Offset = (UInt64)Offset;\n        else if (Offset != 0)\n          return E_FAIL;\n\n        const UInt64 arcRem = FileSize - pi.Offset;\n        UInt64 phySize = arcRem;\n        const bool phySize_Defined = PhySize_Defined;\n        if (phySize_Defined)\n        {\n          if (pi.Offset + PhySize > FileSize)\n          {\n            // ErrorInfo.ThereIsTail = true;\n            PhySize = FileSize - pi.Offset;\n          }\n          phySize = PhySize;\n        }\n        if (phySize == 0 || (UInt64)phySize > ((UInt64)1 << 63))\n          return E_FAIL;\n\n        /*\n        if (!ai.UseGlobalOffset)\n        {\n          if (phySize > arcRem)\n          {\n            ThereIsTail = true;\n            phySize = arcRem;\n          }\n        }\n        */\n        \n        bool needScan = false;\n\n \n        if (isOpen && !phySize_Defined)\n        {\n          // it's for Z format, or bzip2,gz,xz with phySize that was not detected\n          pi.LenIsUnknown = true;\n          needScan = true;\n          phySize = arcRem;\n          nextNeedCheckStartOpen = false;\n        }\n\n        pi.Size = phySize;\n        /*\n        if (OkPhySize_Defined)\n          pi.OkSize = OkPhySize;\n        */\n        pi.NormalizeOffset();\n        // printf(\"  phySize = %8d\", (unsigned)phySize);\n\n        /*\n        if (needSkipFullArc)\n          if (pi.Offset == 0 && phySize_Defined && pi.Size >= fileSize)\n            continue;\n        */\n        if (pi.Offset == 0 && !pi.LenIsUnknown && pi.Size >= FileSize)\n        {\n          // it's possible for dmg archives\n          if (!mode.CanReturnArc)\n            continue;\n        }\n\n        if (mode.EachPos)\n          pos++;\n        else if (needScan)\n        {\n          pos++;\n          /*\n          if (!OkPhySize_Defined)\n            pos++;\n          else\n            pos = pi.Offset + pi.OkSize;\n          */\n        }\n        else\n          pos = pi.Offset + pi.Size;\n\n       \n        RINOK(ReadParseItemProps(archive, ai, pi))\n\n        if (pi.Offset < startArcPos && !mode.EachPos /* && phySize_Defined */)\n        {\n          /* It's for DMG format.\n          This code deletes all previous items that are included to current item */\n            \n          while (!handlerSpec->_items.IsEmpty())\n          {\n            {\n              const NArchive::NParser::CParseItem &back = handlerSpec->_items.Back();\n              if (back.Offset < pi.Offset)\n                break;\n              if (back.Offset + back.Size > pi.Offset + pi.Size)\n                break;\n            }\n            handlerSpec->_items.DeleteBack();\n          }\n        }\n        \n\n        if (isOpen && mode.CanReturnArc && phySize_Defined)\n        {\n          // if (pi.Offset + pi.Size >= fileSize)\n          bool openCur = false;\n\n          bool thereIsTail = ErrorInfo.ThereIsTail;\n          if (thereIsTail && mode.ZerosTailIsAllowed)\n          {\n            RINOK(CheckZerosTail(op, (UInt64)((Int64)arcStreamOffset + Offset + (Int64)PhySize)))\n            if (ErrorInfo.IgnoreTail)\n              thereIsTail = false;\n          }\n\n          if (pi.Offset != 0)\n          {\n            if (!pi.IsNotArcType)\n            {\n              if (thereIsTail)\n                openCur = specFlags.CanReturnMid;\n              else\n                openCur = specFlags.CanReturnTail;\n            }\n          }\n          else\n          {\n            if (!thereIsTail)\n              openCur = true;\n            else\n              openCur = specFlags.CanReturnFrontal;\n\n            if (formatIndex >= -2)\n              openCur = true;\n          }\n\n          if (formatIndex < 0 && pi.IsSelfExe /* && mode.SkipSfxStub */)\n            openCur = false;\n\n          // We open file as SFX, if there is front archive or first archive is \"Self Executable\"\n          if (!openCur && !pi.IsSelfExe && !thereIsTail &&\n              (!pi.IsNotArcType || pi.Offset == 0))\n          {\n            if (handlerSpec->_items.IsEmpty())\n            {\n              if (specFlags.CanReturnTail)\n                openCur = true;\n            }\n            else if (handlerSpec->_items.Size() == 1)\n            {\n              if (handlerSpec->_items[0].IsSelfExe)\n              {\n                if (mode.SpecUnknownExt.CanReturnTail)\n                  openCur = true;\n              }\n            }\n          }\n\n          if (openCur)\n          {\n            InStream = op.stream;\n            Archive = archive;\n            FormatIndex = (int)index;\n            ArcStreamOffset = arcStreamOffset;\n            return S_OK;\n          }\n        }\n\n        /*\n        if (openOnlyFullArc)\n        {\n          ErrorInfo.ClearErrors();\n          return S_FALSE;\n        }\n        */\n\n        pi.FormatIndex = (int)index;\n\n        // printf(\"\\nAdd offset = %d\", (int)pi.Offset);\n        handlerSpec->AddItem(pi);\n        wasOpen = true;\n        break;\n      }\n      // ---------- End of Open Loop for Current Pos ----------\n     \n      if (!wasOpen)\n        pos++;\n      needCheckStartOpen = (nextNeedCheckStartOpen && wasOpen);\n    }\n    // ---------- End of Main Scan Loop ----------\n\n    /*\n    if (handlerSpec->_items.Size() == 1)\n    {\n      const NArchive::NParser::CParseItem &pi = handlerSpec->_items[0];\n      if (pi.Size == fileSize && pi.Offset == 0)\n      {\n        Archive = archive;\n        FormatIndex2 = pi.FormatIndex;\n        return S_OK;\n      }\n    }\n    */\n\n    if (mode.CanReturnParser)\n    {\n      bool returnParser = (handlerSpec->_items.Size() == 1); // it's possible if fileSize was not correct at start of parsing\n      handlerSpec->AddUnknownItem(fileSize);\n      if (handlerSpec->_items.Size() == 0)\n        return S_FALSE;\n      if (returnParser || handlerSpec->_items.Size() != 1)\n      {\n        // return S_FALSE;\n        handlerSpec->_stream = op.stream;\n        Archive = handler;\n        ErrorInfo.ClearErrors();\n        IsParseArc = true;\n        FormatIndex = -1; // It's parser\n        Offset = 0;\n        return S_OK;\n      }\n    }\n  }\n\n  #endif\n\n  if (!Archive)\n    return S_FALSE;\n  return S_OK;\n}\n\n\n\n\nHRESULT CArc::OpenStream(const COpenOptions &op)\n{\n  RINOK(OpenStream2(op))\n  // PrintNumber(\"op.formatIndex 3\", op.formatIndex);\n\n  if (Archive)\n  {\n    GetRawProps.Release();\n    GetRootProps.Release();\n    Archive->QueryInterface(IID_IArchiveGetRawProps, (void **)&GetRawProps);\n    Archive->QueryInterface(IID_IArchiveGetRootProps, (void **)&GetRootProps);\n\n    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsTree, IsTree))\n    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsDeleted, Ask_Deleted))\n    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAltStream, Ask_AltStream))\n    RINOK(Archive_GetArcProp_Bool(Archive, kpidIsAux, Ask_Aux))\n    RINOK(Archive_GetArcProp_Bool(Archive, kpidINode, Ask_INode))\n    RINOK(Archive_GetArcProp_Bool(Archive, kpidReadOnly, IsReadOnly))\n\n    const UString fileName = ExtractFileNameFromPath(Path);\n    UString extension;\n    {\n      int dotPos = fileName.ReverseFind_Dot();\n      if (dotPos >= 0)\n        extension = fileName.Ptr((unsigned)(dotPos + 1));\n    }\n    \n    DefaultName.Empty();\n    if (FormatIndex >= 0)\n    {\n      const CArcInfoEx &ai = op.codecs->Formats[(unsigned)FormatIndex];\n      if (ai.Exts.Size() == 0)\n        DefaultName = GetDefaultName2(fileName, UString(), UString());\n      else\n      {\n        int subExtIndex = ai.FindExtension(extension);\n        if (subExtIndex < 0)\n          subExtIndex = 0;\n        const CArcExtInfo &extInfo = ai.Exts[(unsigned)subExtIndex];\n        DefaultName = GetDefaultName2(fileName, extInfo.Ext, extInfo.AddExt);\n      }\n    }\n  }\n\n  return S_OK;\n}\n\n#ifdef Z7_SFX\n\n#ifdef _WIN32\n  #define k_ExeExt \".exe\"\n  static const unsigned k_ExeExt_Len = 4;\n#else\n  #define k_ExeExt \"\"\n  static const unsigned k_ExeExt_Len = 0;\n#endif\n\n#endif\n\nHRESULT CArc::OpenStreamOrFile(COpenOptions &op)\n{\n  CMyComPtr<IInStream> fileStream;\n  CMyComPtr<ISequentialInStream> seqStream;\n  CInFileStream *fileStreamSpec = NULL;\n  \n  if (op.stdInMode)\n  {\n#if 1\n    seqStream = new CStdInFileStream;\n#else\n    if (!CreateStdInStream(seqStream))\n      return GetLastError_noZero_HRESULT();\n#endif\n    op.seqStream = seqStream;\n  }\n  else if (!op.stream)\n  {\n    fileStreamSpec = new CInFileStream;\n    fileStream = fileStreamSpec;\n    Path = filePath;\n    if (!fileStreamSpec->Open(us2fs(Path)))\n      return GetLastError_noZero_HRESULT();\n    op.stream = fileStream;\n    #ifdef Z7_SFX\n    IgnoreSplit = true;\n    #endif\n  }\n\n  /*\n  if (callback)\n  {\n    UInt64 fileSize;\n    RINOK(InStream_GetSize_SeekToEnd(op.stream, fileSize));\n    RINOK(op.callback->SetTotal(NULL, &fileSize))\n  }\n  */\n\n  HRESULT res = OpenStream(op);\n  IgnoreSplit = false;\n  \n  #ifdef Z7_SFX\n  \n  if (res != S_FALSE\n      || !fileStreamSpec\n      || !op.callbackSpec\n      || NonOpen_ErrorInfo.IsArc_After_NonOpen())\n    return res;\n  \n  {\n    if (filePath.Len() > k_ExeExt_Len\n        && StringsAreEqualNoCase_Ascii(filePath.RightPtr(k_ExeExt_Len), k_ExeExt))\n    {\n      const UString path2 = filePath.Left(filePath.Len() - k_ExeExt_Len);\n      FOR_VECTOR (i, op.codecs->Formats)\n      {\n        const CArcInfoEx &ai = op.codecs->Formats[i];\n        if (ai.Is_Split())\n          continue;\n        UString path3 = path2;\n        path3.Add_Dot();\n        path3 += ai.GetMainExt(); // \"7z\"  for SFX.\n        Path = path3;\n        Path += \".001\";\n        bool isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));\n        if (!isOk)\n        {\n          Path = path3;\n          isOk = op.callbackSpec->SetSecondFileInfo(us2fs(Path));\n        }\n        if (isOk)\n        {\n          if (fileStreamSpec->Open(us2fs(Path)))\n          {\n            op.stream = fileStream;\n            NonOpen_ErrorInfo.ClearErrors_Full();\n            if (OpenStream(op) == S_OK)\n              return S_OK;\n          }\n        }\n      }\n    }\n  }\n  \n  #endif\n\n  return res;\n}\n\nvoid CArchiveLink::KeepModeForNextOpen()\n{\n  for (unsigned i = Arcs.Size(); i != 0;)\n  {\n    i--;\n    CMyComPtr<IArchiveKeepModeForNextOpen> keep;\n    Arcs[i].Archive->QueryInterface(IID_IArchiveKeepModeForNextOpen, (void **)&keep);\n    if (keep)\n      keep->KeepModeForNextOpen();\n  }\n}\n\nHRESULT CArchiveLink::Close()\n{\n  for (unsigned i = Arcs.Size(); i != 0;)\n  {\n    i--;\n    RINOK(Arcs[i].Close())\n  }\n  IsOpen = false;\n  // ErrorsText.Empty();\n  return S_OK;\n}\n\nvoid CArchiveLink::Release()\n{\n  // NonOpenErrorFormatIndex = -1;\n  NonOpen_ErrorInfo.ClearErrors();\n  NonOpen_ArcPath.Empty();\n  while (!Arcs.IsEmpty())\n    Arcs.DeleteBack();\n}\n\n/*\nvoid CArchiveLink::Set_ErrorsText()\n{\n  FOR_VECTOR(i, Arcs)\n  {\n    const CArc &arc = Arcs[i];\n    if (!arc.ErrorFlagsText.IsEmpty())\n    {\n      if (!ErrorsText.IsEmpty())\n        ErrorsText.Add_LF();\n      ErrorsText += GetUnicodeString(arc.ErrorFlagsText);\n    }\n    if (!arc.ErrorMessage.IsEmpty())\n    {\n      if (!ErrorsText.IsEmpty())\n        ErrorsText.Add_LF();\n      ErrorsText += arc.ErrorMessage;\n    }\n\n    if (!arc.WarningMessage.IsEmpty())\n    {\n      if (!ErrorsText.IsEmpty())\n        ErrorsText.Add_LF();\n      ErrorsText += arc.WarningMessage;\n    }\n  }\n}\n*/\n\nHRESULT CArchiveLink::Open(COpenOptions &op)\n{\n  Release();\n  if (op.types->Size() >= 32)\n    return E_NOTIMPL;\n  \n  HRESULT resSpec;\n\n  for (;;)\n  {\n    resSpec = S_OK;\n\n    op.openType = COpenType();\n    if (op.types->Size() >= 1)\n    {\n      COpenType latest;\n      if (Arcs.Size() < op.types->Size())\n        latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];\n      else\n      {\n        latest = (*op.types)[0];\n        if (!latest.Recursive)\n          break;\n      }\n      op.openType = latest;\n    }\n    else if (Arcs.Size() >= 32)\n      break;\n\n    /*\n    op.formatIndex = -1;\n    if (op.types->Size() >= 1)\n    {\n      int latest;\n      if (Arcs.Size() < op.types->Size())\n        latest = (*op.types)[op.types->Size() - Arcs.Size() - 1];\n      else\n      {\n        latest = (*op.types)[0];\n        if (latest != -2 && latest != -3)\n          break;\n      }\n      if (latest >= 0)\n        op.formatIndex = latest;\n      else if (latest == -1 || latest == -2)\n      {\n        // default\n      }\n      else if (latest == -3)\n        op.formatIndex = -2;\n      else\n        op.formatIndex = latest + 2;\n    }\n    else if (Arcs.Size() >= 32)\n      break;\n    */\n\n    if (Arcs.IsEmpty())\n    {\n      CArc arc;\n      arc.filePath = op.filePath;\n      arc.Path = op.filePath;\n      arc.SubfileIndex = (UInt32)(Int32)-1;\n      HRESULT result = arc.OpenStreamOrFile(op);\n      if (result != S_OK)\n      {\n        if (result == S_FALSE)\n        {\n          NonOpen_ErrorInfo = arc.NonOpen_ErrorInfo;\n          // NonOpenErrorFormatIndex = arc.ErrorFormatIndex;\n          NonOpen_ArcPath = arc.Path;\n        }\n        return result;\n      }\n      Arcs.Add(arc);\n      continue;\n    }\n    \n    // PrintNumber(\"op.formatIndex 11\", op.formatIndex);\n\n    const CArc &arc = Arcs.Back();\n    \n    if (op.types->Size() > Arcs.Size())\n      resSpec = E_NOTIMPL;\n    \n    UInt32 mainSubfile;\n    {\n      NCOM::CPropVariant prop;\n      RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop))\n      if (prop.vt == VT_UI4)\n        mainSubfile = prop.ulVal;\n      else\n        break;\n      UInt32 numItems;\n      RINOK(arc.Archive->GetNumberOfItems(&numItems))\n      if (mainSubfile >= numItems)\n        break;\n    }\n\n  \n    CMyComPtr<IInArchiveGetStream> getStream;\n    if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)\n      break;\n    \n    CMyComPtr<ISequentialInStream> subSeqStream;\n    if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)\n      break;\n    \n    CMyComPtr<IInStream> subStream;\n    if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)\n      break;\n    \n    CArc arc2;\n    RINOK(arc.GetItem_Path(mainSubfile, arc2.Path))\n\n    bool zerosTailIsAllowed;\n    RINOK(Archive_GetItemBoolProp(arc.Archive, mainSubfile, kpidZerosTailIsAllowed, zerosTailIsAllowed))\n\n\n    if (op.callback)\n    {\n      Z7_DECL_CMyComPtr_QI_FROM(\n          IArchiveOpenSetSubArchiveName,\n          setSubArchiveName, op.callback)\n      if (setSubArchiveName)\n        setSubArchiveName->SetSubArchiveName(arc2.Path);\n    }\n    \n    arc2.SubfileIndex = mainSubfile;\n\n    // CIntVector incl;\n    CIntVector excl;\n\n    COpenOptions op2;\n    #ifndef Z7_SFX\n    op2.props = op.props;\n    #endif\n    op2.codecs = op.codecs;\n    // op2.types = &incl;\n    op2.openType = op.openType;\n    op2.openType.ZerosTailIsAllowed = zerosTailIsAllowed;\n    op2.excludedFormats = &excl;\n    op2.stdInMode = false;\n    op2.stream = subStream;\n    op2.filePath = arc2.Path;\n    op2.callback = op.callback;\n    op2.callbackSpec = op.callbackSpec;\n\n\n    HRESULT result = arc2.OpenStream(op2);\n    resSpec = (op.types->Size() == 0 ? S_OK : S_FALSE);\n    if (result == S_FALSE)\n    {\n      NonOpen_ErrorInfo = arc2.ErrorInfo;\n      NonOpen_ArcPath = arc2.Path;\n      break;\n    }\n    RINOK(result)\n    RINOK(arc.GetItem_MTime(mainSubfile, arc2.MTime))\n    Arcs.Add(arc2);\n  }\n  IsOpen = !Arcs.IsEmpty();\n  return resSpec;\n}\n\nHRESULT CArchiveLink::Open2(COpenOptions &op, IOpenCallbackUI *callbackUI)\n{\n  VolumesSize = 0;\n  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;\n  CMyComPtr<IArchiveOpenCallback> callback = openCallbackSpec;\n  openCallbackSpec->Callback = callbackUI;\n\n  FString prefix, name;\n  \n  if (!op.stream && !op.stdInMode)\n  {\n    NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), prefix, name);\n    RINOK(openCallbackSpec->Init2(prefix, name))\n  }\n  else\n  {\n    openCallbackSpec->SetSubArchiveName(op.filePath);\n  }\n\n  op.callback = callback;\n  op.callbackSpec = openCallbackSpec;\n  \n  HRESULT res = Open(op);\n\n  PasswordWasAsked = openCallbackSpec->PasswordWasAsked;\n  // Password = openCallbackSpec->Password;\n\n  RINOK(res)\n  // VolumePaths.Add(fs2us(prefix + name));\n\n  FOR_VECTOR (i, openCallbackSpec->FileNames_WasUsed)\n  {\n    if (openCallbackSpec->FileNames_WasUsed[i])\n    {\n      VolumePaths.Add(fs2us(prefix) + openCallbackSpec->FileNames[i]);\n      VolumesSize += openCallbackSpec->FileSizes[i];\n    }\n  }\n  // VolumesSize = openCallbackSpec->TotalSize;\n  return S_OK;\n}\n\nHRESULT CArc::ReOpen(const COpenOptions &op, IArchiveOpenCallback *openCallback_Additional)\n{\n  ErrorInfo.ClearErrors();\n  ErrorInfo.ErrorFormatIndex = -1;\n\n  UInt64 fileSize = 0;\n  if (op.stream)\n  {\n    RINOK(InStream_SeekToBegin(op.stream))\n    RINOK(InStream_AtBegin_GetSize(op.stream, fileSize))\n    // RINOK(InStream_GetSize_SeekToBegin(op.stream, fileSize))\n  }\n  FileSize = fileSize;\n\n  CMyComPtr<IInStream> stream2;\n  Int64 globalOffset = GetGlobalOffset();\n  if (globalOffset <= 0)\n    stream2 = op.stream;\n  else\n  {\n    CTailInStream *tailStreamSpec = new CTailInStream;\n    stream2 = tailStreamSpec;\n    tailStreamSpec->Stream = op.stream;\n    tailStreamSpec->Offset = (UInt64)globalOffset;\n    tailStreamSpec->Init();\n    RINOK(tailStreamSpec->SeekToStart())\n  }\n\n  // There are archives with embedded STUBs (like ZIP), so we must support signature scanning\n  // But for another archives we can use 0 here. So the code can be fixed !!!\n  UInt64 maxStartPosition = kMaxCheckStartPosition;\n  IArchiveOpenCallback *openCallback = openCallback_Additional;\n  if (!openCallback)\n    openCallback = op.callback;\n  HRESULT res = Archive->Open(stream2, &maxStartPosition, openCallback);\n  \n  if (res == S_OK)\n  {\n    RINOK(ReadBasicProps(Archive, (UInt64)globalOffset, res))\n    ArcStreamOffset = (UInt64)globalOffset;\n    if (ArcStreamOffset != 0)\n      InStream = op.stream;\n  }\n  return res;\n}\n\nHRESULT CArchiveLink::Open3(COpenOptions &op, IOpenCallbackUI *callbackUI)\n{\n  HRESULT res = Open2(op, callbackUI);\n  if (callbackUI)\n  {\n    RINOK(callbackUI->Open_Finished())\n  }\n  return res;\n}\n\nHRESULT CArchiveLink::ReOpen(COpenOptions &op)\n{\n  if (Arcs.Size() > 1)\n    return E_NOTIMPL;\n\n  CObjectVector<COpenType> inc;\n  CIntVector excl;\n\n  op.types = &inc;\n  op.excludedFormats = &excl;\n  op.stdInMode = false;\n  op.stream = NULL;\n  if (Arcs.Size() == 0) // ???\n    return Open2(op, NULL);\n\n  /* if archive is multivolume (unsupported here still)\n     COpenCallbackImp object will exist after Open stage. */\n  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;\n  CMyComPtr<IArchiveOpenCallback> openCallbackNew = openCallbackSpec;\n\n  openCallbackSpec->Callback = NULL;\n  openCallbackSpec->ReOpenCallback = op.callback;\n  {\n    FString dirPrefix, fileName;\n    NFile::NDir::GetFullPathAndSplit(us2fs(op.filePath), dirPrefix, fileName);\n    RINOK(openCallbackSpec->Init2(dirPrefix, fileName))\n  }\n\n\n  CInFileStream *fileStreamSpec = new CInFileStream;\n  CMyComPtr<IInStream> stream(fileStreamSpec);\n  if (!fileStreamSpec->Open(us2fs(op.filePath)))\n    return GetLastError_noZero_HRESULT();\n  op.stream = stream;\n\n  CArc &arc = Arcs[0];\n  const HRESULT res = arc.ReOpen(op, openCallbackNew);\n\n  openCallbackSpec->ReOpenCallback = NULL;\n  \n  PasswordWasAsked = openCallbackSpec->PasswordWasAsked;\n  // Password = openCallbackSpec->Password;\n  \n  IsOpen = (res == S_OK);\n  return res;\n}\n\n#ifndef Z7_SFX\n\nbool ParseComplexSize(const wchar_t *s, UInt64 &result);\nbool ParseComplexSize(const wchar_t *s, UInt64 &result)\n{\n  result = 0;\n  const wchar_t *end;\n  UInt64 number = ConvertStringToUInt64(s, &end);\n  if (end == s)\n    return false;\n  if (*end == 0)\n  {\n    result = number;\n    return true;\n  }\n  if (end[1] != 0)\n    return false;\n  unsigned numBits;\n  switch (MyCharLower_Ascii(*end))\n  {\n    case 'b': result = number; return true;\n    case 'k': numBits = 10; break;\n    case 'm': numBits = 20; break;\n    case 'g': numBits = 30; break;\n    case 't': numBits = 40; break;\n    default: return false;\n  }\n  if (number >= ((UInt64)1 << (64 - numBits)))\n    return false;\n  result = number << numBits;\n  return true;\n}\n\nstatic bool ParseTypeParams(const UString &s, COpenType &type)\n{\n  if (s[0] == 0)\n    return true;\n  if (s[1] == 0)\n  {\n    switch ((unsigned)(Byte)s[0])\n    {\n      case 'e': type.EachPos = true; return true;\n      case 'a': type.CanReturnArc = true; return true;\n      case 'r': type.Recursive = true; return true;\n      default: break;\n    }\n    return false;\n  }\n  if (s[0] == 's')\n  {\n    UInt64 result;\n    if (!ParseComplexSize(s.Ptr(1), result))\n      return false;\n    type.MaxStartOffset = result;\n    type.MaxStartOffset_Defined = true;\n    return true;\n  }\n\n  return false;\n}\n\nstatic bool ParseType(CCodecs &codecs, const UString &s, COpenType &type)\n{\n  int pos2 = s.Find(L':');\n\n  {\n  UString name;\n  if (pos2 < 0)\n  {\n    name = s;\n    pos2 = (int)s.Len();\n  }\n  else\n  {\n    name = s.Left((unsigned)pos2);\n    pos2++;\n  }\n\n  int index = codecs.FindFormatForArchiveType(name);\n  type.Recursive = false;\n\n  if (index < 0)\n  {\n    if (name[0] == '*')\n    {\n      if (name[1] != 0)\n        return false;\n    }\n    else if (name[0] == '#')\n    {\n      if (name[1] != 0)\n        return false;\n      type.CanReturnArc = false;\n      type.CanReturnParser = true;\n    }\n    else if (name.IsEqualTo_Ascii_NoCase(\"hash\"))\n    {\n      // type.CanReturnArc = false;\n      // type.CanReturnParser = false;\n      type.IsHashType = true;\n    }\n    else\n      return false;\n  }\n  \n  type.FormatIndex = index;\n\n  }\n \n  for (unsigned i = (unsigned)pos2; i < s.Len();)\n  {\n    int next = s.Find(L':', i);\n    if (next < 0)\n      next = (int)s.Len();\n    const UString name = s.Mid(i, (unsigned)next - i);\n    if (name.IsEmpty())\n      return false;\n    if (!ParseTypeParams(name, type))\n      return false;\n    i = (unsigned)next + 1;\n  }\n  \n  return true;\n}\n\nbool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types)\n{\n  types.Clear();\n  bool isHashType = false;\n  for (unsigned pos = 0; pos < s.Len();)\n  {\n    int pos2 = s.Find(L'.', pos);\n    if (pos2 < 0)\n      pos2 = (int)s.Len();\n    UString name = s.Mid(pos, (unsigned)pos2 - pos);\n    if (name.IsEmpty())\n      return false;\n    COpenType type;\n    if (!ParseType(codecs, name, type))\n      return false;\n    if (isHashType)\n      return false;\n    if (type.IsHashType)\n      isHashType = true;\n    types.Add(type);\n    pos = (unsigned)pos2 + 1;\n  }\n  return true;\n}\n\n/*\nbool IsHashType(const CObjectVector<COpenType> &types)\n{\n  if (types.Size() != 1)\n    return false;\n  return types[0].IsHashType;\n}\n*/\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/OpenArchive.h",
    "content": "﻿// OpenArchive.h\n\n#ifndef ZIP7_INC_OPEN_ARCHIVE_H\n#define ZIP7_INC_OPEN_ARCHIVE_H\n\n#include \"../../../Windows/PropVariant.h\"\n\n#include \"ArchiveOpenCallback.h\"\n#include \"LoadCodecs.h\"\n#include \"Property.h\"\n#include \"DirItem.h\"\n\n#ifndef Z7_SFX\n\n#define SUPPORT_ALT_STREAMS\n\n#endif\n\nHRESULT Archive_GetItemBoolProp(IInArchive *arc, UInt32 index, PROPID propID, bool &result) throw();\nHRESULT Archive_IsItem_Dir(IInArchive *arc, UInt32 index, bool &result) throw();\nHRESULT Archive_IsItem_Aux(IInArchive *arc, UInt32 index, bool &result) throw();\nHRESULT Archive_IsItem_AltStream(IInArchive *arc, UInt32 index, bool &result) throw();\nHRESULT Archive_IsItem_Deleted(IInArchive *arc, UInt32 index, bool &deleted) throw();\n\n#ifdef SUPPORT_ALT_STREAMS\nint FindAltStreamColon_in_Path(const wchar_t *path);\n#endif\n\n/*\nstruct COptionalOpenProperties\n{\n  UString FormatName;\n  CObjectVector<CProperty> Props;\n};\n*/\n\n#ifdef Z7_SFX\n#define OPEN_PROPS_DECL\n#else\n#define OPEN_PROPS_DECL const CObjectVector<CProperty> *props;\n// #define OPEN_PROPS_DECL , const CObjectVector<COptionalOpenProperties> *props\n#endif\n\nstruct COpenSpecFlags\n{\n  // bool CanReturnFull;\n  bool CanReturnFrontal;\n  bool CanReturnTail;\n  bool CanReturnMid;\n\n  bool CanReturn_NonStart() const { return CanReturnTail || CanReturnMid; }\n\n  COpenSpecFlags():\n    // CanReturnFull(true),\n    CanReturnFrontal(false),\n    CanReturnTail(false),\n    CanReturnMid(false)\n    {}\n};\n\nstruct COpenType\n{\n  int FormatIndex;\n\n  COpenSpecFlags SpecForcedType;\n  COpenSpecFlags SpecMainType;\n  COpenSpecFlags SpecWrongExt;\n  COpenSpecFlags SpecUnknownExt;\n\n  bool Recursive;\n\n  bool CanReturnArc;\n  bool CanReturnParser;\n  bool IsHashType;\n  bool EachPos;\n\n  // bool SkipSfxStub;\n  // bool ExeAsUnknown;\n\n  bool ZerosTailIsAllowed;\n\n  bool MaxStartOffset_Defined;\n  UInt64 MaxStartOffset;\n\n  const COpenSpecFlags &GetSpec(bool isForced, bool isMain, bool isUnknown) const\n  {\n    return isForced ? SpecForcedType : (isMain ? SpecMainType : (isUnknown ? SpecUnknownExt : SpecWrongExt));\n  }\n\n  COpenType():\n      FormatIndex(-1),\n      Recursive(true),\n      CanReturnArc(true),\n      CanReturnParser(false),\n      IsHashType(false),\n      EachPos(false),\n      // SkipSfxStub(true),\n      // ExeAsUnknown(true),\n      ZerosTailIsAllowed(false),\n      MaxStartOffset_Defined(false),\n      MaxStartOffset(0)\n  {\n    SpecForcedType.CanReturnFrontal = true;\n    SpecForcedType.CanReturnTail = true;\n    SpecForcedType.CanReturnMid = true;\n\n    SpecMainType.CanReturnFrontal = true;\n\n    SpecUnknownExt.CanReturnTail = true; // for sfx\n    SpecUnknownExt.CanReturnMid = true;\n    SpecUnknownExt.CanReturnFrontal = true; // for alt streams of sfx with pad\n\n    // ZerosTailIsAllowed = true;\n  }\n};\n\nstruct COpenOptions\n{\n  CCodecs *codecs;\n  COpenType openType;\n  const CObjectVector<COpenType> *types;\n  const CIntVector *excludedFormats;\n\n  IInStream *stream;\n  ISequentialInStream *seqStream;\n  IArchiveOpenCallback *callback;\n  COpenCallbackImp *callbackSpec; // it's used for SFX only\n  OPEN_PROPS_DECL\n  // bool openOnlySpecifiedByExtension,\n\n  bool stdInMode;\n  UString filePath;\n\n  COpenOptions():\n      codecs(NULL),\n      types(NULL),\n      excludedFormats(NULL),\n      stream(NULL),\n      seqStream(NULL),\n      callback(NULL),\n      callbackSpec(NULL),\n      stdInMode(false)\n    {}\n\n};\n\nUInt32 GetOpenArcErrorFlags(const NWindows::NCOM::CPropVariant &prop, bool *isDefinedProp = NULL);\n\nstruct CArcErrorInfo\n{\n  bool ThereIsTail;\n  bool UnexpecedEnd;\n  bool IgnoreTail; // all are zeros\n  // bool NonZerosTail;\n  bool ErrorFlags_Defined;\n  UInt32 ErrorFlags;\n  UInt32 WarningFlags;\n  int ErrorFormatIndex; // - 1 means no Error.\n                        // if FormatIndex == ErrorFormatIndex, the archive is open with offset\n  UInt64 TailSize;\n\n  /* if CArc is Open OK with some format:\n        - ErrorFormatIndex shows error format index, if extension is incorrect\n        - other variables show message and warnings of archive that is open */\n  \n  UString ErrorMessage;\n  UString WarningMessage;\n\n  // call IsArc_After_NonOpen only if Open returns S_FALSE\n  bool IsArc_After_NonOpen() const\n  {\n    return (ErrorFlags_Defined && (ErrorFlags & kpv_ErrorFlags_IsNotArc) == 0);\n  }\n\n\n  CArcErrorInfo():\n      ThereIsTail(false),\n      UnexpecedEnd(false),\n      IgnoreTail(false),\n      // NonZerosTail(false),\n      ErrorFlags_Defined(false),\n      ErrorFlags(0),\n      WarningFlags(0),\n      ErrorFormatIndex(-1),\n      TailSize(0)\n    {}\n\n  void ClearErrors();\n\n  void ClearErrors_Full()\n  {\n    ErrorFormatIndex = -1;\n    ClearErrors();\n  }\n\n  bool IsThereErrorOrWarning() const\n  {\n    return ErrorFlags != 0\n        || WarningFlags != 0\n        || NeedTailWarning()\n        || UnexpecedEnd\n        || !ErrorMessage.IsEmpty()\n        || !WarningMessage.IsEmpty();\n  }\n\n  bool AreThereErrors() const { return ErrorFlags != 0 || UnexpecedEnd; }\n  bool AreThereWarnings() const { return WarningFlags != 0 || NeedTailWarning(); }\n\n  bool NeedTailWarning() const { return !IgnoreTail && ThereIsTail; }\n\n  UInt32 GetWarningFlags() const\n  {\n    UInt32 a = WarningFlags;\n    if (NeedTailWarning() && (ErrorFlags & kpv_ErrorFlags_DataAfterEnd) == 0)\n      a |= kpv_ErrorFlags_DataAfterEnd;\n    return a;\n  }\n\n  UInt32 GetErrorFlags() const\n  {\n    UInt32 a = ErrorFlags;\n    if (UnexpecedEnd)\n      a |= kpv_ErrorFlags_UnexpectedEnd;\n    return a;\n  }\n};\n\nstruct CReadArcItem\n{\n  UString Path;            // Path from root (including alt stream name, if alt stream)\n  UStringVector PathParts; // without altStream name, path from root or from _baseParentFolder, if _use_baseParentFolder_mode\n\n  #ifdef SUPPORT_ALT_STREAMS\n  UString MainPath;\n                /* MainPath = Path for non-AltStream,\n                   MainPath = Path of parent, if there is parent for AltStream. */\n  UString AltStreamName;\n  bool IsAltStream;\n  bool WriteToAltStreamIfColon;\n  #endif\n\n  bool IsDir;\n  bool MainIsDir;\n  UInt32 ParentIndex; // use it, if IsAltStream\n\n  #ifndef Z7_SFX\n  bool _use_baseParentFolder_mode;\n  int _baseParentFolder;\n  #endif\n\n  CReadArcItem()\n  {\n    #ifdef SUPPORT_ALT_STREAMS\n    WriteToAltStreamIfColon = false;\n    #endif\n\n    #ifndef Z7_SFX\n    _use_baseParentFolder_mode = false;\n    _baseParentFolder = -1;\n    #endif\n  }\n};\n\n\n\n\nclass CArc\n{\n  HRESULT PrepareToOpen(const COpenOptions &op, unsigned formatIndex, CMyComPtr<IInArchive> &archive);\n  HRESULT CheckZerosTail(const COpenOptions &op, UInt64 offset);\n  HRESULT OpenStream2(const COpenOptions &options);\n\n  #ifndef Z7_SFX\n  // parts.Back() can contain alt stream name \"nams:AltName\"\n  HRESULT GetItem_PathToParent(UInt32 index, UInt32 parent, UStringVector &parts) const;\n  #endif\n\npublic:\n  CMyComPtr<IInArchive> Archive;\n  CMyComPtr<IInStream> InStream;\n          // we use InStream in 2 cases (ArcStreamOffset != 0):\n          // 1) if we use additional cache stream\n          // 2) we reopen sfx archive with CTailInStream\n  \n  CMyComPtr<IArchiveGetRawProps> GetRawProps;\n  CMyComPtr<IArchiveGetRootProps> GetRootProps;\n\n  bool IsParseArc;\n\n  bool IsTree;\n  bool IsReadOnly;\n  \n  bool Ask_Deleted;\n  bool Ask_AltStream;\n  bool Ask_Aux;\n  bool Ask_INode;\n\n  bool IgnoreSplit; // don't try split handler\n\n  UString Path;\n  UString filePath;\n  UString DefaultName;\n  int FormatIndex;     // -1 means Parser\n  UInt32 SubfileIndex; // (UInt32)(Int32)-1; means no subfile\n\n  // CFiTime MTime;\n  // bool MTime_Defined;\n  CArcTime MTime;\n  \n  Int64 Offset; // it's offset of start of archive inside stream that is open by Archive Handler\n  UInt64 PhySize;\n  // UInt64 OkPhySize;\n  bool PhySize_Defined;\n  // bool OkPhySize_Defined;\n  UInt64 FileSize;\n  UInt64 AvailPhySize; // PhySize, but it's reduced if exceed end of file\n\n  CArcErrorInfo ErrorInfo; // for OK archives\n  CArcErrorInfo NonOpen_ErrorInfo; // ErrorInfo for mainArchive (false OPEN)\n\n  UInt64 GetEstmatedPhySize() const { return PhySize_Defined ? PhySize : FileSize; }\n\n  UInt64 ArcStreamOffset; // offset of stream that is open by Archive Handler\n  Int64 GetGlobalOffset() const { return (Int64)ArcStreamOffset + Offset; } // it's global offset of archive\n\n  // AString ErrorFlagsText;\n\n  // void Set_ErrorFlagsText();\n\n  CArc():\n    // MTime_Defined(false),\n    IsTree(false),\n    IsReadOnly(false),\n    Ask_Deleted(false),\n    Ask_AltStream(false),\n    Ask_Aux(false),\n    Ask_INode(false),\n    IgnoreSplit(false)\n    {}\n\n  HRESULT ReadBasicProps(IInArchive *archive, UInt64 startPos, HRESULT openRes);\n\n  HRESULT Close()\n  {\n    InStream.Release();\n    return Archive->Close();\n  }\n\n  HRESULT GetItem_Path(UInt32 index, UString &result) const;\n  HRESULT GetItem_DefaultPath(UInt32 index, UString &result) const;\n  \n  // GetItemPath2 adds [DELETED] dir prefix for deleted items.\n  HRESULT GetItem_Path2(UInt32 index, UString &result) const;\n\n  HRESULT GetItem(UInt32 index, CReadArcItem &item) const;\n  \n  HRESULT GetItem_Size(UInt32 index, UInt64 &size, bool &defined) const;\n\n  /* if (GetProperty() returns vt==VT_EMPTY), this function sets\n     timestamp from archive file timestamp (MTime).\n     So (at) will be set in most cases (at.Def == true)\n     if (at.Prec == 0)\n     {\n       it means that (Prec == 0) was returned for (kpidMTime),\n       and no value was returned for (kpidTimeType).\n       it can mean Windows precision or unknown precision.\n     }\n  */\n  HRESULT GetItem_MTime(UInt32 index, CArcTime &at) const;\n\n  HRESULT IsItem_Anti(UInt32 index, bool &result) const\n    { return Archive_GetItemBoolProp(Archive, index, kpidIsAnti, result); }\n\n\n  HRESULT OpenStream(const COpenOptions &options);\n  HRESULT OpenStreamOrFile(COpenOptions &options);\n\n  HRESULT ReOpen(const COpenOptions &options, IArchiveOpenCallback *openCallback_Additional);\n  \n  HRESULT CreateNewTailStream(CMyComPtr<IInStream> &stream);\n\n  bool IsHashHandler(const COpenOptions &options) const\n  {\n    if (FormatIndex < 0)\n      return false;\n    return options.codecs->Formats[(unsigned)FormatIndex].Flags_HashHandler();\n  }\n};\n\nstruct CArchiveLink\n{\n  CObjectVector<CArc> Arcs;\n  UStringVector VolumePaths;\n  UInt64 VolumesSize;\n  bool IsOpen;\n\n  bool PasswordWasAsked;\n  // UString Password;\n\n  // int NonOpenErrorFormatIndex; // - 1 means no Error.\n  UString NonOpen_ArcPath;\n\n  CArcErrorInfo NonOpen_ErrorInfo;\n\n  // UString ErrorsText;\n  // void Set_ErrorsText();\n\n  CArchiveLink():\n      VolumesSize(0),\n      IsOpen(false),\n      PasswordWasAsked(false)\n      {}\n\n  void KeepModeForNextOpen();\n  HRESULT Close();\n  void Release();\n  ~CArchiveLink() { Release(); }\n\n  const CArc *GetArc() const { return &Arcs.Back(); }\n  IInArchive *GetArchive() const { return Arcs.Back().Archive; }\n  IArchiveGetRawProps *GetArchiveGetRawProps() const { return Arcs.Back().GetRawProps; }\n  IArchiveGetRootProps *GetArchiveGetRootProps() const { return Arcs.Back().GetRootProps; }\n\n  /*\n  Open() opens archive and COpenOptions::callback\n  Open2() uses COpenCallbackImp that implements Volumes and password callback\n  Open3() calls Open2() and callbackUI->Open_Finished();\n  Open_Strict() returns S_FALSE also in case, if there is non-open expected nested archive.\n  */\n\n  HRESULT Open(COpenOptions &options);\n  HRESULT Open2(COpenOptions &options, IOpenCallbackUI *callbackUI);\n  HRESULT Open3(COpenOptions &options, IOpenCallbackUI *callbackUI);\n\n  HRESULT Open_Strict(COpenOptions &options, IOpenCallbackUI *callbackUI)\n  {\n    HRESULT result = Open3(options, callbackUI);\n    if (result == S_OK && NonOpen_ErrorInfo.ErrorFormatIndex >= 0)\n      result = S_FALSE;\n    return result;\n  }\n\n  HRESULT ReOpen(COpenOptions &options);\n};\n\nbool ParseOpenTypes(CCodecs &codecs, const UString &s, CObjectVector<COpenType> &types);\n\n// bool IsHashType(const CObjectVector<COpenType> &types);\n\n\nstruct CDirPathSortPair\n{\n  unsigned Len;\n  unsigned Index;\n\n  void SetNumSlashes(const FChar *s);\n  \n  int Compare(const CDirPathSortPair &a) const\n  {\n    // We need sorting order where parent items will be after child items\n    if (Len < a.Len) return 1;\n    if (Len > a.Len) return -1;\n    if (Index < a.Index) return -1;\n    if (Index > a.Index) return 1;\n    return 0;\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/PropIDUtils.cpp",
    "content": "﻿// PropIDUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/FileIO.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n\n#include \"../../PropID.h\"\n\n#include \"PropIDUtils.h\"\n\n#ifndef Z7_SFX\n#define Get16(x) GetUi16(x)\n#define Get32(x) GetUi32(x)\n#endif\n\nusing namespace NWindows;\n\nstatic const unsigned kNumWinAtrribFlags = 30;\nstatic const char g_WinAttribChars[kNumWinAtrribFlags + 1] = \"RHS8DAdNTsLCOIEVvX.PU.M......B\";\n\n/*\nFILE_ATTRIBUTE_\n\n0 READONLY\n1 HIDDEN\n2 SYSTEM\n3 (Volume label - obsolete)\n4 DIRECTORY\n5 ARCHIVE\n6 DEVICE\n7 NORMAL\n8 TEMPORARY\n9 SPARSE_FILE\n10 REPARSE_POINT\n11 COMPRESSED\n12 OFFLINE\n13 NOT_CONTENT_INDEXED (I - Win10 attrib/Explorer)\n14 ENCRYPTED\n15 INTEGRITY_STREAM (V - ReFS Win8/Win2012)\n16 VIRTUAL (reserved)\n17 NO_SCRUB_DATA (X - ReFS Win8/Win2012 attrib)\n18 RECALL_ON_OPEN or EA\n19 PINNED\n20 UNPINNED\n21 STRICTLY_SEQUENTIAL  (10.0.16267)\n22 RECALL_ON_DATA_ACCESS\n29 STRICTLY_SEQUENTIAL  (10.0.17134+) (SMR Blob)\n*/\n\n\nstatic const char kPosixTypes[16] = { '0', 'p', 'c', '3', 'd', '5', 'b', '7', '-', '9', 'l', 'B', 's', 'D', 'E', 'F' };\n#define MY_ATTR_CHAR(a, n, c) (((a) & (1 << (n))) ? c : '-')\n\nstatic void ConvertPosixAttribToString(char *s, UInt32 a) throw()\n{\n  s[0] = kPosixTypes[(a >> 12) & 0xF];\n  for (int i = 6; i >= 0; i -= 3)\n  {\n    s[7 - i] = MY_ATTR_CHAR(a, i + 2, 'r');\n    s[8 - i] = MY_ATTR_CHAR(a, i + 1, 'w');\n    s[9 - i] = MY_ATTR_CHAR(a, i + 0, 'x');\n  }\n  if ((a & 0x800) != 0) s[3] = ((a & (1 << 6)) ? 's' : 'S'); // S_ISUID\n  if ((a & 0x400) != 0) s[6] = ((a & (1 << 3)) ? 's' : 'S'); // S_ISGID\n  if ((a & 0x200) != 0) s[9] = ((a & (1 << 0)) ? 't' : 'T'); // S_ISVTX\n  s[10] = 0;\n  \n  a &= ~(UInt32)0xFFFF;\n  if (a != 0)\n  {\n    s[10] = ' ';\n    ConvertUInt32ToHex8Digits(a, s + 11);\n  }\n}\n\n\nvoid ConvertWinAttribToString(char *s, UInt32 wa) throw()\n{\n  /*\n  some programs store posix attributes in high 16 bits.\n    p7zip - stores additional 0x8000 flag marker.\n    macos - stores additional 0x4000 flag marker.\n    info-zip - no additional marker.\n  But this code works with Attrib from internal 7zip code.\n  So we expect that 0x8000 marker is set, if there are posix attributes.\n  (DT_UNKNOWN == 0) type in high bits is possible in some case for linux files.\n  0x8000 flag is possible also in ReFS (Windows)?\n  */\n\n  const bool isPosix = (\n      (wa & 0x8000) != 0 // FILE_ATTRIBUTE_UNIX_EXTENSION;\n      // && (wa & 0xFFFF0000u) != 0\n      );\n \n  UInt32 posix = 0;\n  if (isPosix)\n  {\n    posix = wa >> 16;\n    if ((wa & 0xF0000000u) != 0)\n      wa &= (UInt32)0x3FFF;\n  }\n\n  for (unsigned i = 0; i < kNumWinAtrribFlags; i++)\n  {\n    const UInt32 flag = (UInt32)1 << i;\n    if (wa & flag)\n    {\n      const char c = g_WinAttribChars[i];\n      if (c != '.')\n      {\n        wa &= ~flag;\n        // if (i != 7) // we can disable N (NORMAL) printing\n        *s++ = c;\n      }\n    }\n  }\n  \n  if (wa != 0)\n  {\n    *s++ = ' ';\n    ConvertUInt32ToHex8Digits(wa, s);\n    s += strlen(s);\n  }\n\n  *s = 0;\n\n  if (isPosix)\n  {\n    *s++ = ' ';\n    ConvertPosixAttribToString(s, posix);\n  }\n}\n\n\nvoid ConvertPropertyToShortString2(char *dest, const PROPVARIANT &prop, PROPID propID, int level) throw()\n{\n  *dest = 0;\n  \n  if (prop.vt == VT_FILETIME)\n  {\n    const FILETIME &ft = prop.filetime;\n    unsigned ns100 = 0;\n    int numDigits = kTimestampPrintLevel_NTFS;\n    const unsigned prec = prop.wReserved1;\n    const unsigned ns100_Temp = prop.wReserved2;\n    if (prec != 0\n        && prec <= k_PropVar_TimePrec_1ns\n        && ns100_Temp < 100\n        && prop.wReserved3 == 0)\n    {\n      ns100 = ns100_Temp;\n      if (prec == k_PropVar_TimePrec_Unix ||\n          prec == k_PropVar_TimePrec_DOS)\n        numDigits = 0;\n      else if (prec == k_PropVar_TimePrec_HighPrec)\n        numDigits = 9;\n      else\n      {\n        numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;\n        if (\n            // numDigits < kTimestampPrintLevel_DAY // for debuf\n            numDigits < kTimestampPrintLevel_SEC\n            )\n\n          numDigits = kTimestampPrintLevel_NTFS;\n      }\n    }\n    if (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0 && ns100 == 0)\n      return;\n    if (level > numDigits)\n      level = numDigits;\n    ConvertUtcFileTimeToString2(ft, ns100, dest, level);\n    return;\n  }\n\n  switch (propID)\n  {\n    case kpidCRC:\n    {\n      if (prop.vt != VT_UI4)\n        break;\n      ConvertUInt32ToHex8Digits(prop.ulVal, dest);\n      return;\n    }\n    case kpidAttrib:\n    {\n      if (prop.vt != VT_UI4)\n        break;\n      const UInt32 a = prop.ulVal;\n\n      /*\n      if ((a & 0x8000) && (a & 0x7FFF) == 0)\n        ConvertPosixAttribToString(dest, a >> 16);\n      else\n      */\n      ConvertWinAttribToString(dest, a);\n      return;\n    }\n    case kpidPosixAttrib:\n    {\n      if (prop.vt != VT_UI4)\n        break;\n      ConvertPosixAttribToString(dest, prop.ulVal);\n      return;\n    }\n    case kpidINode:\n    {\n      if (prop.vt != VT_UI8)\n        break;\n      ConvertUInt32ToString((UInt32)(prop.uhVal.QuadPart >> 48), dest);\n      dest += strlen(dest);\n      *dest++ = '-';\n      const UInt64 low = prop.uhVal.QuadPart & (((UInt64)1 << 48) - 1);\n      ConvertUInt64ToString(low, dest);\n      return;\n    }\n    case kpidVa:\n    {\n      UInt64 v = 0;\n      if (prop.vt == VT_UI4)\n        v = prop.ulVal;\n      else if (prop.vt == VT_UI8)\n        v = (UInt64)prop.uhVal.QuadPart;\n      else\n        break;\n      dest[0] = '0';\n      dest[1] = 'x';\n      ConvertUInt64ToHex(v, dest + 2);\n      return;\n    }\n\n    /*\n    case kpidDevice:\n    {\n      UInt64 v = 0;\n      if (prop.vt == VT_UI4)\n        v = prop.ulVal;\n      else if (prop.vt == VT_UI8)\n        v = (UInt64)prop.uhVal.QuadPart;\n      else\n        break;\n      ConvertUInt32ToString(MY_dev_major(v), dest);\n      dest += strlen(dest);\n      *dest++ = ',';\n      ConvertUInt32ToString(MY_dev_minor(v), dest);\n      return;\n    }\n    */\n    default: break;\n  }\n  \n  ConvertPropVariantToShortString(prop, dest);\n}\n\nvoid ConvertPropertyToString2(UString &dest, const PROPVARIANT &prop, PROPID propID, int level)\n{\n  if (prop.vt == VT_BSTR)\n  {\n    dest.SetFromBstr(prop.bstrVal);\n    return;\n  }\n  char temp[64];\n  ConvertPropertyToShortString2(temp, prop, propID, level);\n  dest = temp;\n}\n\n#ifndef Z7_SFX\n\nstatic inline void AddHexToString(AString &res, unsigned v)\n{\n  res.Add_Char((char)GET_HEX_CHAR_UPPER(v >> 4));\n  res.Add_Char((char)GET_HEX_CHAR_UPPER(v & 15));\n}\n\n/*\nstatic AString Data_To_Hex(const Byte *data, size_t size)\n{\n  AString s;\n  for (size_t i = 0; i < size; i++)\n    AddHexToString(s, data[i]);\n  return s;\n}\n*/\n\nstatic const char * const sidNames[] =\n{\n    \"0\"\n  , \"Dialup\"\n  , \"Network\"\n  , \"Batch\"\n  , \"Interactive\"\n  , \"Logon\"  // S-1-5-5-X-Y\n  , \"Service\"\n  , \"Anonymous\"\n  , \"Proxy\"\n  , \"EnterpriseDC\"\n  , \"Self\"\n  , \"AuthenticatedUsers\"\n  , \"RestrictedCode\"\n  , \"TerminalServer\"\n  , \"RemoteInteractiveLogon\"\n  , \"ThisOrganization\"\n  , \"16\"\n  , \"IUserIIS\"\n  , \"LocalSystem\"\n  , \"LocalService\"\n  , \"NetworkService\"\n  , \"Domains\"\n};\n\nstruct CSecID2Name\n{\n  UInt32 n;\n  const char *sz;\n};\n\nstatic int FindPairIndex(const CSecID2Name * pairs, unsigned num, UInt32 id)\n{\n  for (unsigned i = 0; i < num; i++)\n    if (pairs[i].n == id)\n      return (int)i;\n  return -1;\n}\n\nstatic const CSecID2Name sid_32_Names[] =\n{\n  { 544, \"Administrators\" },\n  { 545, \"Users\" },\n  { 546, \"Guests\" },\n  { 547, \"PowerUsers\" },\n  { 548, \"AccountOperators\" },\n  { 549, \"ServerOperators\" },\n  { 550, \"PrintOperators\" },\n  { 551, \"BackupOperators\" },\n  { 552, \"Replicators\" },\n  { 553, \"Backup Operators\" },\n  { 554, \"PreWindows2000CompatibleAccess\" },\n  { 555, \"RemoteDesktopUsers\" },\n  { 556, \"NetworkConfigurationOperators\" },\n  { 557, \"IncomingForestTrustBuilders\" },\n  { 558, \"PerformanceMonitorUsers\" },\n  { 559, \"PerformanceLogUsers\" },\n  { 560, \"WindowsAuthorizationAccessGroup\" },\n  { 561, \"TerminalServerLicenseServers\" },\n  { 562, \"DistributedCOMUsers\" },\n  { 569, \"CryptographicOperators\" },\n  { 573, \"EventLogReaders\" },\n  { 574, \"CertificateServiceDCOMAccess\" }\n};\n\nstatic const CSecID2Name sid_21_Names[] =\n{\n  { 500, \"Administrator\" },\n  { 501, \"Guest\" },\n  { 502, \"KRBTGT\" },\n  { 512, \"DomainAdmins\" },\n  { 513, \"DomainUsers\" },\n  { 515, \"DomainComputers\" },\n  { 516, \"DomainControllers\" },\n  { 517, \"CertPublishers\" },\n  { 518, \"SchemaAdmins\" },\n  { 519, \"EnterpriseAdmins\" },\n  { 520, \"GroupPolicyCreatorOwners\" },\n  { 553, \"RASandIASServers\" },\n  { 553, \"RASandIASServers\" },\n  { 571, \"AllowedRODCPasswordReplicationGroup\" },\n  { 572, \"DeniedRODCPasswordReplicationGroup\" }\n};\n\nstruct CServicesToName\n{\n  UInt32 n[5];\n  const char *sz;\n};\n\nstatic const CServicesToName services_to_name[] =\n{\n  { { 0x38FB89B5, 0xCBC28419, 0x6D236C5C, 0x6E770057, 0x876402C0 } , \"TrustedInstaller\" }\n};\n\nstatic void ParseSid(AString &s, const Byte *p, size_t lim /* , unsigned &sidSize */)\n{\n  // sidSize = 0;\n  if (lim < 8)\n  {\n    s += \"ERROR\";\n    return;\n  }\n  if (p[0] != 1) // rev\n  {\n    s += \"UNSUPPORTED\";\n    return;\n  }\n  const unsigned num = p[1];\n  const unsigned sidSize_Loc = 8 + num * 4;\n  if (sidSize_Loc > lim)\n  {\n    s += \"ERROR\";\n    return;\n  }\n  // sidSize = sidSize_Loc;\n  const UInt32 authority = GetBe32(p + 4);\n\n  if (p[2] == 0 && p[3] == 0 && authority == 5 && num >= 1)\n  {\n    const UInt32 v0 = Get32(p + 8);\n    if (v0 < Z7_ARRAY_SIZE(sidNames))\n    {\n      s += sidNames[v0];\n      return;\n    }\n    if (v0 == 32 && num == 2)\n    {\n      const UInt32 v1 = Get32(p + 12);\n      const int index = FindPairIndex(sid_32_Names, Z7_ARRAY_SIZE(sid_32_Names), v1);\n      if (index >= 0)\n      {\n        s += sid_32_Names[(unsigned)index].sz;\n        return;\n      }\n    }\n    if (v0 == 21 && num == 5)\n    {\n      UInt32 v4 = Get32(p + 8 + 4 * 4);\n      const int index = FindPairIndex(sid_21_Names, Z7_ARRAY_SIZE(sid_21_Names), v4);\n      if (index >= 0)\n      {\n        s += sid_21_Names[(unsigned)index].sz;\n        return;\n      }\n    }\n    if (v0 == 80 && num == 6)\n    {\n      for (unsigned i = 0; i < Z7_ARRAY_SIZE(services_to_name); i++)\n      {\n        const CServicesToName &sn = services_to_name[i];\n        int j;\n        for (j = 0; j < 5 && sn.n[j] == Get32(p + 8 + 4 + j * 4); j++);\n        if (j == 5)\n        {\n          s += sn.sz;\n          return;\n        }\n      }\n    }\n  }\n  \n  s += \"S-1-\";\n  if (p[2] == 0 && p[3] == 0)\n    s.Add_UInt32(authority);\n  else\n  {\n    s += \"0x\";\n    for (int i = 2; i < 8; i++)\n      AddHexToString(s, p[i]);\n  }\n  for (UInt32 i = 0; i < num; i++)\n  {\n    s.Add_Minus();\n    s.Add_UInt32(Get32(p + 8 + i * 4));\n  }\n}\n\nstatic void ParseOwner(AString &s, const Byte *p, size_t size, UInt32 pos)\n{\n  if (pos > size)\n  {\n    s += \"ERROR\";\n    return;\n  }\n  // unsigned sidSize = 0;\n  ParseSid(s, p + pos, size - pos /* , sidSize */);\n}\n\nstatic void ParseAcl(AString &s, const Byte *p, size_t size, const char *strName, UInt32 flags, UInt32 offset)\n{\n  const unsigned control = Get16(p + 2);\n  if ((flags & control) == 0)\n    return;\n  const UInt32 pos = Get32(p + offset);\n  s.Add_Space();\n  s += strName;\n  if (pos >= size)\n    return;\n  p += pos;\n  size -= (size_t)pos;\n  if (size < 8)\n    return;\n  if (Get16(p) != 2) // revision\n    return;\n  const UInt32 num = Get32(p + 4);\n  s.Add_UInt32(num);\n  \n  /*\n  UInt32 aclSize = Get16(p + 2);\n  if (num >= (1 << 16))\n    return;\n  if (aclSize > size)\n    return;\n  size = aclSize;\n  size -= 8;\n  p += 8;\n  for (UInt32 i = 0 ; i < num; i++)\n  {\n    if (size <= 8)\n      return;\n    // Byte type = p[0];\n    // Byte flags = p[1];\n    // UInt32 aceSize = Get16(p + 2);\n    // UInt32 mask = Get32(p + 4);\n    p += 8;\n    size -= 8;\n\n    UInt32 sidSize = 0;\n    s.Add_Space();\n    ParseSid(s, p, size, sidSize);\n    if (sidSize == 0)\n      return;\n    p += sidSize;\n    size -= sidSize;\n  }\n\n  // the tail can contain zeros. So (size != 0) is not ERROR\n  // if (size != 0) s += \" ERROR\";\n  */\n}\n\n/*\n#define MY_SE_OWNER_DEFAULTED       (0x0001)\n#define MY_SE_GROUP_DEFAULTED       (0x0002)\n*/\n#define MY_SE_DACL_PRESENT          (0x0004)\n/*\n#define MY_SE_DACL_DEFAULTED        (0x0008)\n*/\n#define MY_SE_SACL_PRESENT          (0x0010)\n/*\n#define MY_SE_SACL_DEFAULTED        (0x0020)\n#define MY_SE_DACL_AUTO_INHERIT_REQ (0x0100)\n#define MY_SE_SACL_AUTO_INHERIT_REQ (0x0200)\n#define MY_SE_DACL_AUTO_INHERITED   (0x0400)\n#define MY_SE_SACL_AUTO_INHERITED   (0x0800)\n#define MY_SE_DACL_PROTECTED        (0x1000)\n#define MY_SE_SACL_PROTECTED        (0x2000)\n#define MY_SE_RM_CONTROL_VALID      (0x4000)\n#define MY_SE_SELF_RELATIVE         (0x8000)\n*/\n\nvoid ConvertNtSecureToString(const Byte *data, size_t size, AString &s)\n{\n  s.Empty();\n  if (size < 20 || size > (1 << 18))\n  {\n    s += \"ERROR\";\n    return;\n  }\n  if (Get16(data) != 1) // revision\n  {\n    s += \"UNSUPPORTED\";\n    return;\n  }\n  ParseOwner(s, data, size, Get32(data + 4));\n  s.Add_Space();\n  ParseOwner(s, data, size, Get32(data + 8));\n  ParseAcl(s, data, size, \"s:\", MY_SE_SACL_PRESENT, 12);\n  ParseAcl(s, data, size, \"d:\", MY_SE_DACL_PRESENT, 16);\n  s.Add_Space();\n  s.Add_UInt32((UInt32)size);\n  // s.Add_LF();\n  // s += Data_To_Hex(data, size);\n}\n\n#ifdef _WIN32\n\nstatic bool CheckSid(const Byte *data, size_t size, UInt32 pos) throw()\n{\n  if (pos >= size)\n    return false;\n  size -= pos;\n  if (size < 8)\n    return false;\n  if (data[pos] != 1) // rev\n    return false;\n  const unsigned num = data[pos + 1];\n  return (8 + num * 4 <= size);\n}\n\nstatic bool CheckAcl(const Byte *p, size_t size, UInt32 flags, size_t offset) throw()\n{\n  const unsigned control = Get16(p + 2);\n  if ((flags & control) == 0)\n    return true;\n  const UInt32 pos = Get32(p + offset);\n  if (pos >= size)\n    return false;\n  p += pos;\n  size -= pos;\n  if (size < 8)\n    return false;\n  const unsigned aclSize = Get16(p + 2);\n  return (aclSize <= size);\n}\n\nbool CheckNtSecure(const Byte *data, size_t size) throw()\n{\n  if (size < 20)\n    return false;\n  if (Get16(data) != 1) // revision\n    return true; // windows function can handle such error, so we allow it\n  if (size > (1 << 18))\n    return false;\n  if (!CheckSid(data, size, Get32(data + 4))) return false;\n  if (!CheckSid(data, size, Get32(data + 8))) return false;\n  if (!CheckAcl(data, size, MY_SE_SACL_PRESENT, 12)) return false;\n  if (!CheckAcl(data, size, MY_SE_DACL_PRESENT, 16)) return false;\n  return true;\n}\n\n#endif\n\n\n\n// IO_REPARSE_TAG_*\n\nstatic const CSecID2Name k_ReparseTags[] =\n{\n  { 0xA0000003, \"MOUNT_POINT\" },\n  { 0xC0000004, \"HSM\" },\n  { 0x80000005, \"DRIVE_EXTENDER\" },\n  { 0x80000006, \"HSM2\" },\n  { 0x80000007, \"SIS\" },\n  { 0x80000008, \"WIM\" },\n  { 0x80000009, \"CSV\" },\n  { 0x8000000A, \"DFS\" },\n  { 0x8000000B, \"FILTER_MANAGER\" },\n  { 0xA000000C, \"SYMLINK\" },\n  { 0xA0000010, \"IIS_CACHE\" },\n  { 0x80000012, \"DFSR\" },\n  { 0x80000013, \"DEDUP\" },\n  { 0xC0000014, \"APPXSTRM\" },\n  { 0x80000014, \"NFS\" },\n  { 0x80000015, \"FILE_PLACEHOLDER\" },\n  { 0x80000016, \"DFM\" },\n  { 0x80000017, \"WOF\" },\n  { 0x80000018, \"WCI\" },\n  { 0x8000001B, \"APPEXECLINK\" },\n  { 0xA000001D, \"LX_SYMLINK\" },\n  { 0x80000023, \"AF_UNIX\" },\n  { 0x80000024, \"LX_FIFO\" },\n  { 0x80000025, \"LX_CHR\" },\n  { 0x80000026, \"LX_BLK\" }\n};\n\nbool ConvertNtReparseToString(const Byte *data, size_t size, UString &s)\n{\n  s.Empty();\n  NFile::CReparseAttr attr;\n\n  if (attr.Parse(data, size))\n  {\n    if (attr.IsSymLink_WSL())\n    {\n      s += \"WSL: \";\n      s += attr.GetPath();\n    }\n    else\n    {\n      if (!attr.IsSymLink_Win())\n        s += \"Junction: \";\n      s += attr.GetPath();\n      if (s.IsEmpty())\n        s += \"Link: \";\n      if (!attr.IsOkNamePair())\n      {\n        s += \" : \";\n        s += attr.PrintName;\n      }\n    }\n    if (attr.MinorError)\n      s += \" : MINOR_ERROR\";\n    return true;\n    // s.Add_Space(); // for debug\n  }\n\n  if (size < 8)\n    return false;\n  const UInt32 tag = Get32(data);\n  const UInt32 len = Get16(data + 4);\n  if (len + 8 > size)\n    return false;\n  if (Get16(data + 6) != 0) // padding\n    return false;\n\n  /*\n  #define my_IO_REPARSE_TAG_DEDUP        (0x80000013L)\n  if (tag == my_IO_REPARSE_TAG_DEDUP)\n  {\n  }\n  */\n\n  {\n    const int index = FindPairIndex(k_ReparseTags, Z7_ARRAY_SIZE(k_ReparseTags), tag);\n    if (index >= 0)\n      s += k_ReparseTags[(unsigned)index].sz;\n    else\n    {\n      s += \"REPARSE:\";\n      char hex[16];\n      ConvertUInt32ToHex8Digits(tag, hex);\n      s += hex;\n    }\n  }\n\n  s.Add_Colon();\n  s.Add_UInt32(len);\n\n  if (len != 0)\n  {\n    s.Add_Space();\n    \n    data += 8;\n    \n    for (UInt32 i = 0; i < len; i++)\n    {\n      if (i >= 16)\n      {\n        s += \"...\";\n        break;\n      }\n      const unsigned b = data[i];\n      s.Add_Char((char)GET_HEX_CHAR_UPPER(b >> 4));\n      s.Add_Char((char)GET_HEX_CHAR_UPPER(b & 15));\n    }\n  }\n\n  return true;\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/PropIDUtils.h",
    "content": "﻿// PropIDUtils.h\n\n#ifndef ZIP7_INC_PROPID_UTILS_H\n#define ZIP7_INC_PROPID_UTILS_H\n\n#include \"../../../Common/MyString.h\"\n\n// provide at least 64 bytes for buffer including zero-end\nvoid ConvertPropertyToShortString2(char *dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0) throw();\nvoid ConvertPropertyToString2(UString &dest, const PROPVARIANT &propVariant, PROPID propID, int level = 0);\n\nbool ConvertNtReparseToString(const Byte *data, size_t size, UString &s);\nvoid ConvertNtSecureToString(const Byte *data, size_t size, AString &s);\nbool CheckNtSecure(const Byte *data, size_t size) throw();\n\nvoid ConvertWinAttribToString(char *s, UInt32 wa) throw();\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/Property.h",
    "content": "﻿// Property.h\n\n#ifndef ZIP7_INC_7Z_PROPERTY_H\n#define ZIP7_INC_7Z_PROPERTY_H\n\n#include \"../../../Common/MyString.h\"\n\nstruct CProperty\n{\n  UString Name;\n  UString Value;\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/SetProperties.h",
    "content": "﻿// SetProperties.h\n\n#ifndef ZIP7_INC_SETPROPERTIES_H\n#define ZIP7_INC_SETPROPERTIES_H\n\n#include \"Property.h\"\n\nHRESULT SetProperties(IUnknown *unknown, const CObjectVector<CProperty> &properties);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/SortUtils.cpp",
    "content": "﻿// SortUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/Wildcard.h\"\n\n#include \"SortUtils.h\"\n\nstatic int CompareStrings(const unsigned *p1, const unsigned *p2, void *param)\n{\n  const UStringVector &strings = *(const UStringVector *)param;\n  return CompareFileNames(strings[*p1], strings[*p2]);\n}\n\nvoid SortFileNames(const UStringVector &strings, CUIntVector &indices)\n{\n  const unsigned numItems = strings.Size();\n  indices.ClearAndSetSize(numItems);\n  if (numItems == 0)\n    return;\n  unsigned *vals = &indices[0];\n  for (unsigned i = 0; i < numItems; i++)\n    vals[i] = i;\n  indices.Sort(CompareStrings, (void *)&strings);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/SortUtils.h",
    "content": "﻿// SortUtils.h\n\n#ifndef ZIP7_INC_SORT_UTLS_H\n#define ZIP7_INC_SORT_UTLS_H\n\n#include \"../../../Common/MyString.h\"\n\nvoid SortFileNames(const UStringVector &strings, CUIntVector &indices);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/Update.h",
    "content": "﻿// Update.h\n\n#ifndef ZIP7_INC_COMMON_UPDATE_H\n#define ZIP7_INC_COMMON_UPDATE_H\n\n#include \"../../../Common/Wildcard.h\"\n\n#include \"ArchiveOpenCallback.h\"\n#include \"LoadCodecs.h\"\n#include \"OpenArchive.h\"\n#include \"Property.h\"\n#include \"UpdateAction.h\"\n#include \"UpdateCallback.h\"\n\nenum EArcNameMode\n{\n  k_ArcNameMode_Smart,\n  k_ArcNameMode_Exact,\n  k_ArcNameMode_Add\n};\n\nstruct CArchivePath\n{\n  UString OriginalPath;\n\n  UString Prefix;   // path(folder) prefix including slash\n  UString Name; // base name\n  UString BaseExtension; // archive type extension or \"exe\" extension\n  UString VolExtension;  // archive type extension for volumes\n\n  bool Temp;\n  FString TempPrefix;  // path(folder) for temp location\n  FString TempPostfix;\n\n  CArchivePath(): Temp(false) {}\n  \n  void ParseFromPath(const UString &path, EArcNameMode mode);\n  UString GetPathWithoutExt() const { return Prefix + Name; }\n  UString GetFinalPath() const;\n  UString GetFinalVolPath() const;\n  FString GetTempPath() const;\n};\n\nstruct CUpdateArchiveCommand\n{\n  UString UserArchivePath;\n  CArchivePath ArchivePath;\n  NUpdateArchive::CActionSet ActionSet;\n};\n\nstruct CCompressionMethodMode\n{\n  bool Type_Defined;\n  COpenType Type;\n  CObjectVector<CProperty> Properties;\n  \n  CCompressionMethodMode(): Type_Defined(false) {}\n};\n\nnamespace NRecursedType { enum EEnum\n{\n  kRecursed,\n  kWildcardOnlyRecursed,\n  kNonRecursed\n};}\n\nstruct CRenamePair\n{\n  UString OldName;\n  UString NewName;\n  bool WildcardParsing;\n  NRecursedType::EEnum RecursedType;\n  \n  CRenamePair(): WildcardParsing(true), RecursedType(NRecursedType::kNonRecursed) {}\n\n  bool Prepare();\n  bool GetNewPath(bool isFolder, const UString &src, UString &dest) const;\n};\n\nstruct CUpdateOptions\n{\n  bool UpdateArchiveItself;\n  bool SfxMode;\n\n  bool PreserveATime;\n  bool OpenShareForWrite;\n  bool StopAfterOpenError;\n\n  bool StdInMode;\n  bool StdOutMode;\n\n  bool EMailMode;\n  bool EMailRemoveAfter;\n\n  bool DeleteAfterCompressing;\n  bool SetArcMTime;\n  bool RenameMode;\n\n  CBoolPair NtSecurity;\n  CBoolPair AltStreams;\n  CBoolPair HardLinks;\n  CBoolPair SymLinks;\n\n  CBoolPair StoreOwnerId;\n  CBoolPair StoreOwnerName;\n\n  EArcNameMode ArcNameMode;\n  NWildcard::ECensorPathMode PathMode;\n\n  CCompressionMethodMode MethodMode;\n\n  CObjectVector<CUpdateArchiveCommand> Commands;\n  CArchivePath ArchivePath;\n\n  FString SfxModule;\n  UString StdInFileName;\n  UString EMailAddress;\n  FString WorkingDir;\n  // UString AddPathPrefix;\n\n  CObjectVector<CRenamePair> RenamePairs;\n  CRecordVector<UInt64> VolumesSizes;\n\n  bool InitFormatIndex(const CCodecs *codecs, const CObjectVector<COpenType> &types, const UString &arcPath);\n  bool SetArcPath(const CCodecs *codecs, const UString &arcPath);\n\n  CUpdateOptions():\n    UpdateArchiveItself(true),\n    SfxMode(false),\n\n    PreserveATime(false),\n    OpenShareForWrite(false),\n    StopAfterOpenError(false),\n\n    StdInMode(false),\n    StdOutMode(false),\n\n    EMailMode(false),\n    EMailRemoveAfter(false),\n    \n    DeleteAfterCompressing(false),\n    SetArcMTime(false),\n    RenameMode(false),\n\n    ArcNameMode(k_ArcNameMode_Smart),\n    PathMode(NWildcard::k_RelatPath)\n    \n    {}\n\n  void SetActionCommand_Add()\n  {\n    Commands.Clear();\n    CUpdateArchiveCommand c;\n    c.ActionSet = NUpdateArchive::k_ActionSet_Add;\n    Commands.Add(c);\n  }\n};\n\n\nstruct CUpdateErrorInfo\n{\n  DWORD SystemError; // it's DWORD (WRes) only;\n  AString Message;\n  FStringVector FileNames;\n\n  bool ThereIsError() const { return SystemError != 0 || !Message.IsEmpty() || !FileNames.IsEmpty(); }\n  HRESULT Get_HRESULT_Error() const { return SystemError == 0 ? E_FAIL : HRESULT_FROM_WIN32(SystemError); }\n  void SetFromLastError(const char *message);\n  HRESULT SetFromLastError(const char *message, const FString &fileName);\n  HRESULT SetFromError_DWORD(const char *message, const FString &fileName, DWORD error);\n\n  CUpdateErrorInfo(): SystemError(0) {}\n};\n\nstruct CFinishArchiveStat\n{\n  UInt64 OutArcFileSize;\n  unsigned NumVolumes;\n  bool IsMultiVolMode;\n\n  CFinishArchiveStat(): OutArcFileSize(0), NumVolumes(0), IsMultiVolMode(false) {}\n};\n\nZ7_PURE_INTERFACES_BEGIN\n\n// INTERFACE_IUpdateCallbackUI(x)\n// INTERFACE_IDirItemsCallback(x)\n\n#define Z7_IFACEN_IUpdateCallbackUI2(x) \\\n  virtual HRESULT OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result) x \\\n  virtual HRESULT StartScanning() x \\\n  virtual HRESULT FinishScanning(const CDirItemsStat &st) x \\\n  virtual HRESULT StartOpenArchive(const wchar_t *name) x \\\n  virtual HRESULT StartArchive(const wchar_t *name, bool updating) x \\\n  virtual HRESULT FinishArchive(const CFinishArchiveStat &st) x \\\n  virtual HRESULT DeletingAfterArchiving(const FString &path, bool isDir) x \\\n  virtual HRESULT FinishDeletingAfterArchiving() x \\\n  virtual HRESULT MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode) x \\\n  virtual HRESULT MoveArc_Progress(UInt64 total, UInt64 current) x \\\n  virtual HRESULT MoveArc_Finish() x \\\n\nDECLARE_INTERFACE(IUpdateCallbackUI2):\n    public IUpdateCallbackUI,\n    public IDirItemsCallback\n{\n  Z7_IFACE_PURE(IUpdateCallbackUI2)\n};\nZ7_PURE_INTERFACES_END\n\nHRESULT UpdateArchive(\n    CCodecs *codecs,\n    const CObjectVector<COpenType> &types,\n    const UString &cmdArcPath2,\n    NWildcard::CCensor &censor,\n    CUpdateOptions &options,\n    CUpdateErrorInfo &errorInfo,\n    IOpenCallbackUI *openCallback,\n    IUpdateCallbackUI2 *callback,\n    bool needSetPath);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/UpdateAction.h",
    "content": "﻿// UpdateAction.h\n\n#ifndef ZIP7_INC_UPDATE_ACTION_H\n#define ZIP7_INC_UPDATE_ACTION_H\n\nnamespace NUpdateArchive {\n\n  namespace NPairState\n  {\n    const unsigned kNumValues = 7;\n    enum EEnum\n    {\n      kNotMasked = 0,\n      kOnlyInArchive,\n      kOnlyOnDisk,\n      kNewInArchive,\n      kOldInArchive,\n      kSameFiles,\n      kUnknowNewerFiles\n    };\n  }\n \n  namespace NPairAction\n  {\n    enum EEnum\n    {\n      kIgnore = 0,\n      kCopy,\n      kCompress,\n      kCompressAsAnti\n    };\n  }\n  \n  struct CActionSet\n  {\n    NPairAction::EEnum StateActions[NPairState::kNumValues];\n    \n    bool IsEqualTo(const CActionSet &a) const\n    {\n      for (unsigned i = 0; i < NPairState::kNumValues; i++)\n        if (StateActions[i] != a.StateActions[i])\n          return false;\n      return true;\n    }\n\n    bool NeedScanning() const\n    {\n      unsigned i;\n      for (i = 0; i < NPairState::kNumValues; i++)\n        if (StateActions[i] == NPairAction::kCompress)\n          return true;\n      for (i = 1; i < NPairState::kNumValues; i++)\n        if (StateActions[i] != NPairAction::kIgnore)\n          return true;\n      return false;\n    }\n  };\n  \n  extern const CActionSet k_ActionSet_Add;\n  extern const CActionSet k_ActionSet_Update;\n  extern const CActionSet k_ActionSet_Fresh;\n  extern const CActionSet k_ActionSet_Sync;\n  extern const CActionSet k_ActionSet_Delete;\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/UpdateCallback.h",
    "content": "﻿// UpdateCallback.h\n\n#ifndef ZIP7_INC_UPDATE_CALLBACK_H\n#define ZIP7_INC_UPDATE_CALLBACK_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../Common/FileStreams.h\"\n\n#include \"../../IPassword.h\"\n#include \"../../ICoder.h\"\n\n#include \"../Common/UpdatePair.h\"\n#include \"../Common/UpdateProduce.h\"\n\n#include \"OpenArchive.h\"\n\nstruct CArcToDoStat\n{\n  CDirItemsStat2 NewData;\n  CDirItemsStat2 OldData;\n  CDirItemsStat2 DeleteData;\n\n  UInt64 Get_NumDataItems_Total() const\n  {\n    return NewData.Get_NumDataItems2() + OldData.Get_NumDataItems2();\n  }\n};\n\n\nZ7_PURE_INTERFACES_BEGIN\n\n#define Z7_IFACEN_IUpdateCallbackUI(x) \\\n  virtual HRESULT WriteSfx(const wchar_t *name, UInt64 size) x \\\n  virtual HRESULT SetTotal(UInt64 size) x \\\n  virtual HRESULT SetCompleted(const UInt64 *completeValue) x \\\n  virtual HRESULT SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) x \\\n  virtual HRESULT CheckBreak() x \\\n  /* virtual HRESULT Finalize() x */ \\\n  virtual HRESULT SetNumItems(const CArcToDoStat &stat) x \\\n  virtual HRESULT GetStream(const wchar_t *name, bool isDir, bool isAnti, UInt32 mode) x \\\n  virtual HRESULT OpenFileError(const FString &path, DWORD systemError) x \\\n  virtual HRESULT ReadingFileError(const FString &path, DWORD systemError) x \\\n  virtual HRESULT SetOperationResult(Int32 opRes) x \\\n  virtual HRESULT ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name) x \\\n  virtual HRESULT ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir) x \\\n  /* virtual HRESULT SetPassword(const UString &password) x */ \\\n  virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) x \\\n  virtual HRESULT CryptoGetTextPassword(BSTR *password) x \\\n  virtual HRESULT ShowDeleteFile(const wchar_t *name, bool isDir) x \\\n\n  /*\n  virtual HRESULT ReportProp(UInt32 indexType, UInt32 index, PROPID propID, const PROPVARIANT *value) x \\\n  virtual HRESULT ReportRawProp(UInt32 indexType, UInt32 index, PROPID propID, const void *data, UInt32 dataSize, UInt32 propType) x \\\n  virtual HRESULT ReportFinished(UInt32 indexType, UInt32 index, Int32 opRes) x \\\n  */\n \n  /* virtual HRESULT CloseProgress() { return S_OK; } */\n\nZ7_IFACE_DECL_PURE(IUpdateCallbackUI)\nZ7_PURE_INTERFACES_END\n\nstruct CKeyKeyValPair\n{\n  UInt64 Key1;\n  UInt64 Key2;\n  unsigned Value;\n\n  int Compare(const CKeyKeyValPair &a) const\n  {\n    if (Key1 < a.Key1) return -1;\n    if (Key1 > a.Key1) return 1;\n    return MyCompare(Key2, a.Key2);\n  }\n};\n\n\nclass CArchiveUpdateCallback Z7_final:\n  public IArchiveUpdateCallback2,\n  public IArchiveUpdateCallbackFile,\n  // public IArchiveUpdateCallbackArcProp,\n  public IArchiveExtractCallbackMessage2,\n  public IArchiveGetRawProps,\n  public IArchiveGetRootProps,\n  public ICryptoGetTextPassword2,\n  public ICryptoGetTextPassword,\n  public ICompressProgressInfo,\n  public IInFileStream_Callback,\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IArchiveUpdateCallback2)\n    Z7_COM_QI_ENTRY(IArchiveUpdateCallbackFile)\n    // Z7_COM_QI_ENTRY(IArchiveUpdateCallbackArcProp)\n    Z7_COM_QI_ENTRY(IArchiveExtractCallbackMessage2)\n    Z7_COM_QI_ENTRY(IArchiveGetRawProps)\n    Z7_COM_QI_ENTRY(IArchiveGetRootProps)\n    Z7_COM_QI_ENTRY(ICryptoGetTextPassword2)\n    Z7_COM_QI_ENTRY(ICryptoGetTextPassword)\n    Z7_COM_QI_ENTRY(ICompressProgressInfo)\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(ICompressProgressInfo)\n\n  Z7_IFACE_COM7_IMP(IProgress)\n  Z7_IFACE_COM7_IMP(IArchiveUpdateCallback)\n  Z7_IFACE_COM7_IMP(IArchiveUpdateCallback2)\n  Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackFile)\n  // Z7_IFACE_COM7_IMP(IArchiveUpdateCallbackArcProp)\n  Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage2)\n  Z7_IFACE_COM7_IMP(IArchiveGetRawProps)\n  Z7_IFACE_COM7_IMP(IArchiveGetRootProps)\n  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword2)\n  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)\n\n\n  void UpdateProcessedItemStatus(unsigned dirIndex);\n\npublic:\n  bool PreserveATime;\n  bool ShareForWrite;\n  bool StopAfterOpenError;\n  bool StdInMode;\n\n  bool KeepOriginalItemNames;\n  bool StoreNtSecurity;\n  bool StoreHardLinks;\n  bool StoreSymLinks;\n\n  bool StoreOwnerId;\n  bool StoreOwnerName;\n\n  bool Need_LatestMTime;\n  bool LatestMTime_Defined;\n\n  /*\n  bool Need_ArcMTime_Report;\n  bool ArcMTime_WasReported;\n  */\n\n  CRecordVector<UInt32> _openFiles_Indexes;\n  FStringVector _openFiles_Paths;\n  // CRecordVector< CInFileStream* > _openFiles_Streams;\n\n  bool AreAllFilesClosed() const { return _openFiles_Indexes.IsEmpty(); }\n  virtual HRESULT InFileStream_On_Error(UINT_PTR val, DWORD error) Z7_override;\n  virtual void InFileStream_On_Destroy(CInFileStream *stream, UINT_PTR val) Z7_override;\n\n  IUpdateCallbackUI *Callback;\n\n  const CDirItems *DirItems;\n  const CDirItem *ParentDirItem;\n  \n  const CArc *Arc;\n  CMyComPtr<IInArchive> Archive;\n  const CObjectVector<CArcItem> *ArcItems;\n  const CRecordVector<CUpdatePair2> *UpdatePairs;\n\n  CRecordVector<UInt64> VolumesSizes;\n  FString VolName;\n  FString VolExt;\n  UString ArcFileName; // without path prefix\n  // **************** 7-Zip ZS Modification Start ****************\n  FString VolPrefix;\n  FString VolPostfix;\n  bool VolNumberAfterExt;\n  UInt32 DigitCount;\n  // **************** 7-Zip ZS Modification End ****************\n\n  const UStringVector *NewNames;\n  const UString *Comment;\n  int CommentIndex;\n\n  /*\n  CArcTime Reported_ArcMTime;\n  */\n  CFiTime LatestMTime;\n\n  Byte *ProcessedItemsStatuses;\n\n\n  CArchiveUpdateCallback();\n\n  bool IsDir(const CUpdatePair2 &up) const\n  {\n    if (up.DirIndex >= 0)\n      return DirItems->Items[(unsigned)up.DirIndex].IsDir();\n    else if (up.ArcIndex >= 0)\n      return (*ArcItems)[(unsigned)up.ArcIndex].IsDir;\n    return false;\n  }\n\nprivate:\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  bool _saclEnabled;\n  #endif\n  CRecordVector<CKeyKeyValPair> _map;\n\n  UInt32 _hardIndex_From;\n  UInt32 _hardIndex_To;\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/UpdatePair.h",
    "content": "﻿// UpdatePair.h\n\n#ifndef ZIP7_INC_UPDATE_PAIR_H\n#define ZIP7_INC_UPDATE_PAIR_H\n\n#include \"DirItem.h\"\n#include \"UpdateAction.h\"\n\n#include \"../../Archive/IArchive.h\"\n\nstruct CUpdatePair\n{\n  NUpdateArchive::NPairState::EEnum State;\n  int ArcIndex;\n  int DirIndex;\n  int HostIndex; // >= 0 for alt streams only, contains index of host pair\n\n  CUpdatePair(): ArcIndex(-1), DirIndex(-1), HostIndex(-1) {}\n};\n\nvoid GetUpdatePairInfoList(\n    const CDirItems &dirItems,\n    const CObjectVector<CArcItem> &arcItems,\n    NFileTimeType::EEnum fileTimeType,\n    CRecordVector<CUpdatePair> &updatePairs);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/UpdateProduce.h",
    "content": "﻿// UpdateProduce.h\n\n#ifndef ZIP7_INC_UPDATE_PRODUCE_H\n#define ZIP7_INC_UPDATE_PRODUCE_H\n\n#include \"UpdatePair.h\"\n\nstruct CUpdatePair2\n{\n  bool NewData;\n  bool NewProps;\n  bool UseArcProps; // if (UseArcProps && NewProps), we want to change only some properties.\n  bool IsAnti; // if (!IsAnti) we use other ways to detect Anti status\n  \n  int DirIndex;\n  int ArcIndex;\n  int NewNameIndex;\n\n  bool IsMainRenameItem;\n  bool IsSameTime;\n\n  void SetAs_NoChangeArcItem(unsigned arcIndex) // int\n  {\n    NewData = NewProps = false;\n    UseArcProps = true;\n    IsAnti = false;\n    ArcIndex = (int)arcIndex;\n  }\n\n  bool ExistOnDisk() const { return DirIndex != -1; }\n  bool ExistInArchive() const { return ArcIndex != -1; }\n\n  CUpdatePair2():\n      NewData(false),\n      NewProps(false),\n      UseArcProps(false),\n      IsAnti(false),\n      DirIndex(-1),\n      ArcIndex(-1),\n      NewNameIndex(-1),\n      IsMainRenameItem(false),\n      IsSameTime(false)\n      {}\n};\n\nZ7_PURE_INTERFACES_BEGIN\n\nDECLARE_INTERFACE(IUpdateProduceCallback)\n{\n  virtual HRESULT ShowDeleteFile(unsigned arcIndex) = 0;\n};\nZ7_PURE_INTERFACES_END\n\nvoid UpdateProduce(\n    const CRecordVector<CUpdatePair> &updatePairs,\n    const NUpdateArchive::CActionSet &actionSet,\n    CRecordVector<CUpdatePair2> &operationChain,\n    IUpdateProduceCallback *callback);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Common/ZipRegistry.h",
    "content": "﻿// ZipRegistry.h\n\n#ifndef ZIP7_INC_ZIP_REGISTRY_H\n#define ZIP7_INC_ZIP_REGISTRY_H\n\n#include \"../../../Common/MyTypes.h\"\n#include \"../../../Common/MyString.h\"\n\n#include \"../../Common/MethodProps.h\"\n\n#include \"ExtractMode.h\"\n\n/*\nCBoolPair::Def in writing functions means:\n  if (  CBoolPair::Def ), we write CBoolPair::Val\n  if ( !CBoolPair::Def )\n  {\n    in NCompression functions we delete registry value\n    in another functions we do nothing\n  }\n*/\n\nnamespace NExtract\n{\n  struct CInfo\n  {\n    NPathMode::EEnum PathMode;\n    NOverwriteMode::EEnum OverwriteMode;\n    bool PathMode_Force;\n    bool OverwriteMode_Force;\n    \n    CBoolPair SplitDest;\n    CBoolPair ElimDup;\n    // CBoolPair AltStreams;\n    CBoolPair NtSecurity;\n    CBoolPair ShowPassword;\n    // **************** NanaZip Modification Start ****************\n    CBoolPair OpenFolder;\n    // **************** NanaZip Modification End ****************\n\n    // **************** 7-Zip ZS Modification Start ****************\n    CBoolPair OpnTrgFold;\n    // **************** 7-Zip ZS Modification End ****************\n\n    UStringVector Paths;\n\n    void Save() const;\n    void Load();\n  };\n  \n  void Save_ShowPassword(bool showPassword);\n  bool Read_ShowPassword();\n\n  void Save_LimitGB(UInt32 limit_GB);\n  UInt32 Read_LimitGB();\n}\n\nnamespace NCompression\n{\n  struct CMemUse\n  {\n    // UString Str;\n    bool IsDefined;\n    bool IsPercent;\n    UInt64 Val;\n\n    CMemUse():\n      IsDefined(false),\n      IsPercent(false),\n      Val(0)\n      {}\n\n    void Clear()\n    {\n      // Str.Empty();\n      IsDefined = false;\n      IsPercent = false;\n      Val = 0;\n    }\n\n    UInt64 GetBytes(UInt64 ramSize) const\n    {\n      if (!IsPercent)\n        return Val;\n      return Calc_From_Val_Percents(ramSize, Val);\n    }\n    void Parse(const UString &s);\n  };\n\n  struct CFormatOptions\n  {\n    UInt32 Level;\n    UInt32 Dictionary;\n    // UInt32 DictionaryChain;\n    UInt32 Order;\n    UInt32 BlockLogSize;\n    UInt32 NumThreads;\n    \n    UInt32 TimePrec;\n    CBoolPair MTime;\n    CBoolPair ATime;\n    CBoolPair CTime;\n    CBoolPair SetArcMTime;\n\n    CSysString FormatID;\n    UString Method;\n    UString Options;\n    UString EncryptionMethod;\n    UString MemUse;\n\n    void Reset_TimePrec()\n    {\n      TimePrec = (UInt32)(Int32)-1;\n    }\n\n    bool IsSet_TimePrec() const\n    {\n      return TimePrec != (UInt32)(Int32)-1;\n    }\n\n\n    void Reset_BlockLogSize()\n    {\n      BlockLogSize = (UInt32)(Int32)-1;\n    }\n\n    void ResetForLevelChange()\n    {\n      BlockLogSize = NumThreads = Level = Dictionary = Order = (UInt32)(Int32)-1;\n      // DictionaryChain = (UInt32)(Int32)-1;\n      Method.Empty();\n      // Options.Empty();\n      // EncryptionMethod.Empty();\n    }\n    CFormatOptions()\n    {\n      // TimePrec = 0;\n      Reset_TimePrec();\n      ResetForLevelChange();\n    }\n  };\n\n  struct CInfo\n  {\n    UInt32 Level;\n    bool ShowPassword;\n    bool EncryptHeaders;\n\n    CBoolPair NtSecurity;\n    CBoolPair AltStreams;\n    CBoolPair HardLinks;\n    CBoolPair SymLinks;\n\n    CBoolPair PreserveATime;\n\n    UString ArcType;\n    UStringVector ArcPaths;\n\n    CObjectVector<CFormatOptions> Formats;\n\n    void Save() const;\n    void Load();\n    // **************** 7-Zip ZS Modification Start ****************\n    void LoadAndUpdateFormatByMethod(CFormatOptions& fo);\n    // **************** 7-Zip ZS Modification End ****************\n  };\n}\n\nnamespace NWorkDir\n{\n  namespace NMode\n  {\n    enum EEnum\n    {\n      kSystem,\n      kCurrent,\n      kSpecified\n    };\n  }\n  struct CInfo\n  {\n    NMode::EEnum Mode;\n    bool ForRemovableOnly;\n    FString Path;\n\n    void SetForRemovableOnlyDefault() { ForRemovableOnly = true; }\n    void SetDefault()\n    {\n      Mode = NMode::kSystem;\n      Path.Empty();\n      SetForRemovableOnlyDefault();\n    }\n\n    void Save() const;\n    void Load();\n  };\n}\n\n\nstruct CContextMenuInfo\n{\n  CBoolPair Cascaded;\n  CBoolPair MenuIcons;\n  CBoolPair ElimDup;\n  \n  bool Flags_Def;\n  UInt32 Flags;\n  UInt32 WriteZone;\n\n  // **************** NanaZip Modification Start ****************\n  CBoolPair ExtractOnOpen;\n  // **************** NanaZip Modification End ****************\n\n  /*\n  CContextMenuInfo():\n      Flags_Def(0),\n      WriteZone((UInt32)(Int32)-1),\n      Flags((UInt32)(Int32)-1)\n      {}\n  */\n\n  void Save() const;\n  void Load();\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/ConsoleClose.cpp",
    "content": "﻿// ConsoleClose.cpp\n\n#include \"StdAfx.h\"\n\n#include \"ConsoleClose.h\"\n\n#ifndef UNDER_CE\n\n#ifdef _WIN32\n#include \"../../../Common/MyWindows.h\"\n#else\n#include <stdlib.h>\n#include <signal.h>\n#endif\n\nnamespace NConsoleClose {\n\nunsigned g_BreakCounter = 0;\nstatic const unsigned kBreakAbortThreshold = 3;\n\n#ifdef _WIN32\n\nstatic BOOL WINAPI HandlerRoutine(DWORD ctrlType)\n{\n  if (ctrlType == CTRL_LOGOFF_EVENT)\n  {\n    // printf(\"\\nCTRL_LOGOFF_EVENT\\n\");\n    return TRUE;\n  }\n\n  if (++g_BreakCounter < kBreakAbortThreshold)\n    return TRUE;\n  return FALSE;\n  /*\n  switch (ctrlType)\n  {\n    case CTRL_C_EVENT:\n    case CTRL_BREAK_EVENT:\n      if (g_BreakCounter < kBreakAbortThreshold)\n      return TRUE;\n  }\n  return FALSE;\n  */\n}\n\nCCtrlHandlerSetter::CCtrlHandlerSetter()\n{\n  if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))\n    throw 1019; // \"SetConsoleCtrlHandler fails\";\n}\n\nCCtrlHandlerSetter::~CCtrlHandlerSetter()\n{\n  if (!SetConsoleCtrlHandler(HandlerRoutine, FALSE))\n  {\n    // warning for throw in destructor.\n    // throw \"SetConsoleCtrlHandler fails\";\n  }\n}\n\n#else // _WIN32\n\nstatic void HandlerRoutine(int)\n{\n  if (++g_BreakCounter < kBreakAbortThreshold)\n    return;\n  exit(EXIT_FAILURE);\n}\n\nCCtrlHandlerSetter::CCtrlHandlerSetter()\n{\n  memo_sig_int = signal(SIGINT, HandlerRoutine); // CTRL-C\n  if (memo_sig_int == SIG_ERR)\n    throw \"SetConsoleCtrlHandler fails (SIGINT)\";\n  memo_sig_term = signal(SIGTERM, HandlerRoutine); // for kill -15 (before \"kill -9\")\n  if (memo_sig_term == SIG_ERR)\n    throw \"SetConsoleCtrlHandler fails (SIGTERM)\";\n}\n\nCCtrlHandlerSetter::~CCtrlHandlerSetter()\n{\n  signal(SIGINT, memo_sig_int); // CTRL-C\n  signal(SIGTERM, memo_sig_term); // kill {pid}\n}\n\n#endif // _WIN32\n\n/*\nvoid CheckCtrlBreak()\n{\n  if (TestBreakSignal())\n    throw CCtrlBreakException();\n}\n*/\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/ConsoleClose.h",
    "content": "﻿// ConsoleClose.h\n\n#ifndef ZIP7_INC_CONSOLE_CLOSE_H\n#define ZIP7_INC_CONSOLE_CLOSE_H\n\nnamespace NConsoleClose {\n\n// class CCtrlBreakException {};\n\n#ifdef UNDER_CE\n\ninline bool TestBreakSignal() { return false; }\nstruct CCtrlHandlerSetter {};\n\n#else\n\nextern unsigned g_BreakCounter;\n\ninline bool TestBreakSignal()\n{\n  return (g_BreakCounter != 0);\n}\n\nclass CCtrlHandlerSetter Z7_final\n{\n  #ifndef _WIN32\n  void (*memo_sig_int)(int);\n  void (*memo_sig_term)(int);\n  #endif\npublic:\n  CCtrlHandlerSetter();\n  ~CCtrlHandlerSetter();\n};\n\n#endif\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/ExtractCallbackConsole.cpp",
    "content": "﻿// ExtractCallbackConsole.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/TimeUtils.h\"\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n\n#ifndef Z7_ST\n#include \"../../../Windows/Synchronization.h\"\n#endif\n\n#include \"../../Common/FilePathAutoRename.h\"\n\n#include \"../Common/ExtractingFilePath.h\"\n\n#include \"ConsoleClose.h\"\n#include \"ExtractCallbackConsole.h\"\n#include \"UserInputUtils.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\nstatic HRESULT CheckBreak2()\n{\n  return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;\n}\n\nstatic const char * const kError = \"ERROR: \";\n\n\nvoid CExtractScanConsole::StartScanning()\n{\n  if (NeedPercents())\n    _percent.Command = \"Scan\";\n}\n\nHRESULT CExtractScanConsole::ScanProgress(const CDirItemsStat &st, const FString &path, bool /* isDir */)\n{\n  if (NeedPercents())\n  {\n    _percent.Files = st.NumDirs + st.NumFiles;\n    _percent.Completed = st.GetTotalBytes();\n    _percent.FileName = fs2us(path);\n    _percent.Print();\n  }\n\n  return CheckBreak2();\n}\n\nHRESULT CExtractScanConsole::ScanError(const FString &path, DWORD systemError)\n{\n  // 22.00:\n  // ScanErrors.AddError(path, systemError);\n\n  ClosePercentsAndFlush();\n  \n  if (_se)\n  {\n    *_se << endl << kError << NError::MyFormatMessage(systemError) << endl;\n    _se->NormalizePrint_UString_Path(fs2us(path));\n    *_se << endl << endl;\n    _se->Flush();\n  }\n  return HRESULT_FROM_WIN32(systemError);\n\n  // 22.00: commented\n  // CommonError(path, systemError, true);\n  // return S_OK;\n}\n\n\nvoid Print_UInt64_and_String(AString &s, UInt64 val, const char *name);\nvoid Print_UInt64_and_String(AString &s, UInt64 val, const char *name)\n{\n  char temp[32];\n  ConvertUInt64ToString(val, temp);\n  s += temp;\n  s.Add_Space();\n  s += name;\n}\n\nvoid PrintSize_bytes_Smart(AString &s, UInt64 val);\nvoid PrintSize_bytes_Smart(AString &s, UInt64 val)\n{\n  Print_UInt64_and_String(s, val, \"bytes\");\n\n  if (val == 0)\n    return;\n\n  unsigned numBits = 10;\n  char c = 'K';\n  char temp[4] = { 'K', 'i', 'B', 0 };\n       if (val >= ((UInt64)10 << 30)) { numBits = 30; c = 'G'; }\n  else if (val >= ((UInt64)10 << 20)) { numBits = 20; c = 'M'; }\n  temp[0] = c;\n  s += \" (\";\n  Print_UInt64_and_String(s, ((val + ((UInt64)1 << numBits) - 1) >> numBits), temp);\n  s.Add_Char(')');\n}\n\nstatic void PrintSize_bytes_Smart_comma(AString &s, UInt64 val)\n{\n  if (val == (UInt64)(Int64)-1)\n    return;\n  s += \", \";\n  PrintSize_bytes_Smart(s, val);\n}\n\n\n\nvoid Print_DirItemsStat(AString &s, const CDirItemsStat &st);\nvoid Print_DirItemsStat(AString &s, const CDirItemsStat &st)\n{\n  if (st.NumDirs != 0)\n  {\n    Print_UInt64_and_String(s, st.NumDirs, st.NumDirs == 1 ? \"folder\" : \"folders\");\n    s += \", \";\n  }\n  Print_UInt64_and_String(s, st.NumFiles, st.NumFiles == 1 ? \"file\" : \"files\");\n  PrintSize_bytes_Smart_comma(s, st.FilesSize);\n  if (st.NumAltStreams != 0)\n  {\n    s.Add_LF();\n    Print_UInt64_and_String(s, st.NumAltStreams, \"alternate streams\");\n    PrintSize_bytes_Smart_comma(s, st.AltStreamsSize);\n  }\n}\n\n\nvoid Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st);\nvoid Print_DirItemsStat2(AString &s, const CDirItemsStat2 &st)\n{\n  Print_DirItemsStat(s, (CDirItemsStat &)st);\n  bool needLF = true;\n  if (st.Anti_NumDirs != 0)\n  {\n    if (needLF)\n      s.Add_LF();\n    needLF = false;\n    Print_UInt64_and_String(s, st.Anti_NumDirs, st.Anti_NumDirs == 1 ? \"anti-folder\" : \"anti-folders\");\n  }\n  if (st.Anti_NumFiles != 0)\n  {\n    if (needLF)\n      s.Add_LF();\n    else\n      s += \", \";\n    needLF = false;\n    Print_UInt64_and_String(s, st.Anti_NumFiles, st.Anti_NumFiles == 1 ? \"anti-file\" : \"anti-files\");\n  }\n  if (st.Anti_NumAltStreams != 0)\n  {\n    if (needLF)\n      s.Add_LF();\n    else\n      s += \", \";\n    needLF = false;\n    Print_UInt64_and_String(s, st.Anti_NumAltStreams, \"anti-alternate-streams\");\n  }\n}\n\n\nvoid CExtractScanConsole::PrintStat(const CDirItemsStat &st)\n{\n  if (_so)\n  {\n    AString s;\n    Print_DirItemsStat(s, st);\n    *_so << s << endl;\n  }\n}\n\n\n\n\n\n\n\n#ifndef Z7_ST\nstatic NSynchronization::CCriticalSection g_CriticalSection;\n#define MT_LOCK NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\n#else\n#define MT_LOCK\n#endif\n\n\nstatic const char * const kTestString    =  \"T\";\nstatic const char * const kExtractString =  \"-\";\nstatic const char * const kSkipString    =  \".\";\nstatic const char * const kReadString    =  \"H\";\n\n// static const char * const kCantAutoRename = \"cannot create file with auto name\\n\";\n// static const char * const kCantRenameFile = \"cannot rename existing file\\n\";\n// static const char * const kCantDeleteOutputFile = \"cannot delete output file \";\n\nstatic const char * const kMemoryExceptionMessage = \"Can't allocate required memory!\";\n\nstatic const char * const kExtracting = \"Extracting archive: \";\nstatic const char * const kTesting = \"Testing archive: \";\n\nstatic const char * const kEverythingIsOk = \"Everything is Ok\";\nstatic const char * const kNoFiles = \"No files to process\";\n\nstatic const char * const kUnsupportedMethod = \"Unsupported Method\";\nstatic const char * const kCrcFailed = \"CRC Failed\";\nstatic const char * const kCrcFailedEncrypted = \"CRC Failed in encrypted file. Wrong password?\";\nstatic const char * const kDataError = \"Data Error\";\nstatic const char * const kDataErrorEncrypted = \"Data Error in encrypted file. Wrong password?\";\nstatic const char * const kUnavailableData = \"Unavailable data\";\nstatic const char * const kUnexpectedEnd = \"Unexpected end of data\";\nstatic const char * const kDataAfterEnd = \"There are some data after the end of the payload data\";\nstatic const char * const kIsNotArc = \"Is not archive\";\nstatic const char * const kHeadersError = \"Headers Error\";\nstatic const char * const kWrongPassword = \"Wrong password\";\n\nstatic const char * const k_ErrorFlagsMessages[] =\n{\n    \"Is not archive\"\n  , \"Headers Error\"\n  , \"Headers Error in encrypted archive. Wrong password?\"\n  , \"Unavailable start of archive\"\n  , \"Unconfirmed start of archive\"\n  , \"Unexpected end of archive\"\n  , \"There are data after the end of archive\"\n  , \"Unsupported method\"\n  , \"Unsupported feature\"\n  , \"Data Error\"\n  , \"CRC Error\"\n};\n\nZ7_COM7F_IMF(CExtractCallbackConsole::SetTotal(UInt64 size))\n{\n  MT_LOCK\n\n  if (NeedPercents())\n  {\n    _percent.Total = size;\n    _percent.Print();\n  }\n  return CheckBreak2();\n}\n\nZ7_COM7F_IMF(CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue))\n{\n  MT_LOCK\n\n  if (NeedPercents())\n  {\n    if (completeValue)\n      _percent.Completed = *completeValue;\n    _percent.Print();\n  }\n  return CheckBreak2();\n}\n\nstatic const char * const kTab = \"  \";\n\nstatic void PrintFileInfo(CStdOutStream *_so, const wchar_t *path, const FILETIME *ft, const UInt64 *size)\n{\n  *_so << kTab << \"Path:     \";\n  _so->NormalizePrint_wstr_Path(path);\n  *_so << endl;\n  if (size && *size != (UInt64)(Int64)-1)\n  {\n    AString s;\n    PrintSize_bytes_Smart(s, *size);\n    *_so << kTab << \"Size:     \" << s << endl;\n  }\n  if (ft)\n  {\n    char temp[64];\n    if (ConvertUtcFileTimeToString(*ft, temp, kTimestampPrintLevel_SEC))\n      *_so << kTab << \"Modified: \" << temp << endl;\n  }\n}\n\nZ7_COM7F_IMF(CExtractCallbackConsole::AskOverwrite(\n    const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\n    const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\n    Int32 *answer))\n{\n  MT_LOCK\n  \n  RINOK(CheckBreak2())\n\n  ClosePercentsAndFlush();\n\n  if (_so)\n  {\n    *_so << endl << \"Would you like to replace the existing file:\\n\";\n    PrintFileInfo(_so, existName, existTime, existSize);\n    *_so << \"with the file from archive:\\n\";\n    PrintFileInfo(_so, newName, newTime, newSize);\n  }\n  \n  NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(_so);\n  \n  switch ((int)overwriteAnswer)\n  {\n    case NUserAnswerMode::kQuit:  return E_ABORT;\n    case NUserAnswerMode::kNo:     *answer = NOverwriteAnswer::kNo; break;\n    case NUserAnswerMode::kNoAll:  *answer = NOverwriteAnswer::kNoToAll; break;\n    case NUserAnswerMode::kYesAll: *answer = NOverwriteAnswer::kYesToAll; break;\n    case NUserAnswerMode::kYes:    *answer = NOverwriteAnswer::kYes; break;\n    case NUserAnswerMode::kAutoRenameAll: *answer = NOverwriteAnswer::kAutoRename; break;\n    case NUserAnswerMode::kEof:  return E_ABORT;\n    case NUserAnswerMode::kError:  return E_FAIL;\n    default: return E_FAIL;\n  }\n  \n  if (_so)\n  {\n    *_so << endl;\n    if (NeedFlush)\n      _so->Flush();\n  }\n  \n  return CheckBreak2();\n}\n\nZ7_COM7F_IMF(CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 *position))\n{\n  MT_LOCK\n  \n  _currentName = name;\n  \n  const char *s;\n  unsigned requiredLevel = 1;\n\n  switch (askExtractMode)\n  {\n    case NArchive::NExtract::NAskMode::kExtract: s = kExtractString; break;\n    case NArchive::NExtract::NAskMode::kTest:    s = kTestString; break;\n    case NArchive::NExtract::NAskMode::kSkip:    s = kSkipString; requiredLevel = 2; break;\n    case NArchive::NExtract::NAskMode::kReadExternal: s = kReadString; requiredLevel = 0; break;\n    default: s = \"???\"; requiredLevel = 2;\n  }\n\n  const bool show2 = (LogLevel >= requiredLevel && _so);\n\n  if (show2)\n  {\n    ClosePercents_for_so();\n    \n    _tempA = s;\n    if (name)\n      _tempA.Add_Space();\n    *_so << _tempA;\n\n    _tempU.Empty();\n    if (name)\n    {\n      _tempU = name;\n      _so->Normalize_UString_Path(_tempU);\n      // 21.04\n      if (isFolder)\n      {\n        if (!_tempU.IsEmpty() && _tempU.Back() != WCHAR_PATH_SEPARATOR)\n          _tempU.Add_PathSepar();\n      }\n    }\n    _so->PrintUString(_tempU, _tempA);\n    if (position)\n      *_so << \" <\" << *position << \">\";\n    *_so << endl;\n \n    if (NeedFlush)\n      _so->Flush();\n    // _so->Flush();  // for debug only\n  }\n\n  if (NeedPercents())\n  {\n    if (PercentsNameLevel >= 1)\n    {\n      _percent.FileName.Empty();\n      _percent.Command.Empty();\n      if (PercentsNameLevel > 1 || !show2)\n      {\n        _percent.Command = s;\n        if (name)\n          _percent.FileName = name;\n      }\n    }\n    _percent.Print();\n  }\n\n  return CheckBreak2();\n}\n\nZ7_COM7F_IMF(CExtractCallbackConsole::MessageError(const wchar_t *message))\n{\n  MT_LOCK\n  \n  RINOK(CheckBreak2())\n\n  NumFileErrors_in_Current++;\n  NumFileErrors++;\n\n  ClosePercentsAndFlush();\n  if (_se)\n  {\n    *_se << kError << message << endl;\n    _se->Flush();\n  }\n\n  return CheckBreak2();\n}\n\nvoid SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest);\nvoid SetExtractErrorMessage(Int32 opRes, Int32 encrypted, AString &dest)\n{\n  dest.Empty();\n    const char *s = NULL;\n    \n    switch (opRes)\n    {\n      case NArchive::NExtract::NOperationResult::kUnsupportedMethod:\n        s = kUnsupportedMethod;\n        break;\n      case NArchive::NExtract::NOperationResult::kCRCError:\n        s = (encrypted ? kCrcFailedEncrypted : kCrcFailed);\n        break;\n      case NArchive::NExtract::NOperationResult::kDataError:\n        s = (encrypted ? kDataErrorEncrypted : kDataError);\n        break;\n      case NArchive::NExtract::NOperationResult::kUnavailable:\n        s = kUnavailableData;\n        break;\n      case NArchive::NExtract::NOperationResult::kUnexpectedEnd:\n        s = kUnexpectedEnd;\n        break;\n      case NArchive::NExtract::NOperationResult::kDataAfterEnd:\n        s = kDataAfterEnd;\n        break;\n      case NArchive::NExtract::NOperationResult::kIsNotArc:\n        s = kIsNotArc;\n        break;\n      case NArchive::NExtract::NOperationResult::kHeadersError:\n        s = kHeadersError;\n        break;\n      case NArchive::NExtract::NOperationResult::kWrongPassword:\n        s = kWrongPassword;\n        break;\n      default: break;\n    }\n    \n    dest += kError;\n    if (s)\n      dest += s;\n    else\n    {\n      dest += \"Error #\";\n      dest.Add_UInt32((UInt32)opRes);\n    }\n}\n\nZ7_COM7F_IMF(CExtractCallbackConsole::SetOperationResult(Int32 opRes, Int32 encrypted))\n{\n  MT_LOCK\n  \n  if (opRes == NArchive::NExtract::NOperationResult::kOK)\n  {\n    if (NeedPercents())\n    {\n      _percent.Command.Empty();\n      _percent.FileName.Empty();\n      _percent.Files++;\n    }\n  }\n  else\n  {\n    NumFileErrors_in_Current++;\n    NumFileErrors++;\n    \n    if (_se)\n    {\n      ClosePercentsAndFlush();\n      \n      AString s;\n      SetExtractErrorMessage(opRes, encrypted, s);\n      \n      *_se << s;\n      if (!_currentName.IsEmpty())\n      {\n        *_se << \" : \";\n        _se->NormalizePrint_UString_Path(_currentName);\n      }\n      *_se << endl;\n      _se->Flush();\n    }\n  }\n  \n  return CheckBreak2();\n}\n\nZ7_COM7F_IMF(CExtractCallbackConsole::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name))\n{\n  if (opRes != NArchive::NExtract::NOperationResult::kOK)\n  {\n    _currentName = name;\n    return SetOperationResult(opRes, encrypted);\n  }\n\n  return CheckBreak2();\n}\n\n\n\n#ifndef Z7_NO_CRYPTO\n\nHRESULT CExtractCallbackConsole::SetPassword(const UString &password)\n{\n  PasswordIsDefined = true;\n  Password = password;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password))\n{\n  COM_TRY_BEGIN\n  MT_LOCK\n  return Open_CryptoGetTextPassword(password);\n  COM_TRY_END\n}\n\n#endif\n\n\n#ifndef Z7_SFX\n\nvoid CExtractCallbackConsole::PrintTo_se_Path_WithTitle(const UString &path, const char *title)\n{\n  *_se << title;\n  _se->NormalizePrint_UString_Path(path);\n  *_se << endl;\n}\n\nvoid CExtractCallbackConsole::Add_ArchiveName_Error()\n{\n  if (_needWriteArchivePath)\n  {\n    PrintTo_se_Path_WithTitle(_currentArchivePath, \"Archive: \");\n    _needWriteArchivePath = false;\n  }\n}\n\n\nZ7_COM7F_IMF(CExtractCallbackConsole::RequestMemoryUse(\n    UInt32 flags, UInt32 /* indexType */, UInt32 /* index */, const wchar_t *path,\n    UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))\n{\n  if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0\n      && requiredSize <= *allowedSize)\n  {\n#if 0\n    // it's expected, that *answerFlags was set to NRequestMemoryAnswerFlags::k_Allow already,\n    // because it's default answer for (requiredSize <= *allowedSize) case.\n    // optional code:\n    *answerFlags = NRequestMemoryAnswerFlags::k_Allow;\n#endif\n  }\n  else\n  {\n    if ((flags & NRequestMemoryUseFlags::k_NoErrorMessage) == 0)\n    if (_se)\n    {\n      const UInt64 num_GB_allowed  = (*allowedSize + ((1u << 30) - 1)) >> 30;\n      const UInt64 num_GB_required = (requiredSize + ((1u << 30) - 1)) >> 30;\n      ClosePercentsAndFlush();\n      Add_ArchiveName_Error();\n      if (path)\n        PrintTo_se_Path_WithTitle(path, \"File: \");\n      *_se << \"The extraction operation requires big amount memory (RAM):\" << endl\n        << \"  \" << num_GB_required  << \" GB : required memory usage size\" << endl\n        << \"  \" << num_GB_allowed   << \" GB : allowed memory usage limit\" << endl\n        << \"  Use -smemx{size}g switch to set allowed memory usage limit for extraction.\" << endl;\n      *_se << \"ERROR: Memory usage limit was exceeded.\" << endl;\n      const char *m = NULL;\n      // if (indexType == NArchive::NEventIndexType::kNoIndex)\n           if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) ||\n               (flags & NRequestMemoryUseFlags::k_Report_SkipArc))\n          m = \"Archive unpacking was skipped.\";\n/*\n      else if ((flags & NRequestMemoryUseFlags::k_SkipBigFiles_IsExpected) ||\n               (flags & NRequestMemoryUseFlags::k_Report_SkipBigFiles))\n          m = \"Extraction for some files will be skipped.\";\n      else if ((flags & NRequestMemoryUseFlags::k_SkipBigFile_IsExpected) ||\n               (flags & NRequestMemoryUseFlags::k_Report_SkipBigFile))\n          m = \"File extraction was skipped.\";\n*/\n      if (m)\n        *_se << m;\n      _se->Flush();\n    }\n\n    if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)\n    {\n      // default answer can be k_Allow, if limit was not forced,\n      // so we change answer to non-allowed here.\n      *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded;\n           if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected)\n        *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc;\n/*\n      else if (flags & NRequestMemoryUseFlags::k_SkipBigFile_IsExpected)\n        *answerFlags |= NRequestMemoryAnswerFlags::k_SkipBigFile;\n      else if (flags & NRequestMemoryUseFlags::k_SkipBigFiles_IsExpected)\n        *answerFlags |= NRequestMemoryAnswerFlags::k_SkipBigFiles;\n*/\n    }\n  }\n  return CheckBreak2();\n}\n\n#endif\n\n\nHRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name, bool testMode)\n{\n  _currentArchivePath = name;\n  _needWriteArchivePath = true;\n\n  RINOK(CheckBreak2())\n\n  NumTryArcs++;\n  ThereIsError_in_Current = false;\n  ThereIsWarning_in_Current = false;\n  NumFileErrors_in_Current = 0;\n  \n  ClosePercents_for_so();\n  if (_so)\n  {\n    *_so << endl << (testMode ? kTesting : kExtracting);\n    _so->NormalizePrint_wstr_Path(name);\n    *_so << endl;\n  }\n\n  if (NeedPercents())\n    _percent.Command = \"Open\";\n  return S_OK;\n}\n\nHRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);\nHRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);\n\nstatic AString GetOpenArcErrorMessage(UInt32 errorFlags)\n{\n  AString s;\n  \n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ErrorFlagsMessages); i++)\n  {\n    UInt32 f = (1 << i);\n    if ((errorFlags & f) == 0)\n      continue;\n    const char *m = k_ErrorFlagsMessages[i];\n    if (!s.IsEmpty())\n      s.Add_LF();\n    s += m;\n    errorFlags &= ~f;\n  }\n  \n  if (errorFlags != 0)\n  {\n    char sz[16];\n    sz[0] = '0';\n    sz[1] = 'x';\n    ConvertUInt32ToHex(errorFlags, sz + 2);\n    if (!s.IsEmpty())\n      s.Add_LF();\n    s += sz;\n  }\n  \n  return s;\n}\n\nvoid PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);\nvoid PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags)\n{\n  if (errorFlags == 0)\n    return;\n  so << s << endl << GetOpenArcErrorMessage(errorFlags) << endl;\n}\n\nstatic void Add_Messsage_Pre_ArcType(UString &s, const char *pre, const wchar_t *arcType)\n{\n  s.Add_LF();\n  s += pre;\n  s += \" as [\";\n  s += arcType;\n  s += \"] archive\";\n}\n\nvoid Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc);\nvoid Print_ErrorFormatIndex_Warning(CStdOutStream *_so, const CCodecs *codecs, const CArc &arc)\n{\n  const CArcErrorInfo &er = arc.ErrorInfo;\n  \n  *_so << \"WARNING:\\n\";\n  _so->NormalizePrint_UString_Path(arc.Path);\n  UString s;\n  if (arc.FormatIndex == er.ErrorFormatIndex)\n  {\n    s.Add_LF();\n    s += \"The archive is open with offset\";\n  }\n  else\n  {\n    Add_Messsage_Pre_ArcType(s, \"Cannot open the file\", codecs->GetFormatNamePtr(er.ErrorFormatIndex));\n    Add_Messsage_Pre_ArcType(s, \"The file is open\", codecs->GetFormatNamePtr(arc.FormatIndex));\n  }\n  \n  *_so << s << endl << endl;\n}\n        \n\nHRESULT CExtractCallbackConsole::OpenResult(\n    const CCodecs *codecs, const CArchiveLink &arcLink,\n    const wchar_t *name, HRESULT result)\n{\n  _currentArchivePath = name;\n  _needWriteArchivePath = true;\n\n  ClosePercents();\n\n  if (NeedPercents())\n  {\n    _percent.Files = 0;\n    _percent.Command.Empty();\n    _percent.FileName.Empty();\n  }\n\n \n  ClosePercentsAndFlush();\n\n  FOR_VECTOR (level, arcLink.Arcs)\n  {\n    const CArc &arc = arcLink.Arcs[level];\n    const CArcErrorInfo &er = arc.ErrorInfo;\n    \n    UInt32 errorFlags = er.GetErrorFlags();\n\n    if (errorFlags != 0 || !er.ErrorMessage.IsEmpty())\n    {\n      if (_se)\n      {\n        *_se << endl;\n        if (level != 0)\n        {\n          _se->NormalizePrint_UString_Path(arc.Path);\n          *_se << endl;\n        }\n      }\n      \n      if (errorFlags != 0)\n      {\n        if (_se)\n          PrintErrorFlags(*_se, \"ERRORS:\", errorFlags);\n        NumOpenArcErrors++;\n        ThereIsError_in_Current = true;\n      }\n      \n      if (!er.ErrorMessage.IsEmpty())\n      {\n        if (_se)\n          *_se << \"ERRORS:\" << endl << er.ErrorMessage << endl;\n        NumOpenArcErrors++;\n        ThereIsError_in_Current = true;\n      }\n      \n      if (_se)\n      {\n        *_se << endl;\n        _se->Flush();\n      }\n    }\n    \n    UInt32 warningFlags = er.GetWarningFlags();\n\n    if (warningFlags != 0 || !er.WarningMessage.IsEmpty())\n    {\n      if (_so)\n      {\n        *_so << endl;\n        if (level != 0)\n        {\n          _so->NormalizePrint_UString_Path(arc.Path);\n          *_so << endl;\n        }\n      }\n      \n      if (warningFlags != 0)\n      {\n        if (_so)\n          PrintErrorFlags(*_so, \"WARNINGS:\", warningFlags);\n        NumOpenArcWarnings++;\n        ThereIsWarning_in_Current = true;\n      }\n      \n      if (!er.WarningMessage.IsEmpty())\n      {\n        if (_so)\n          *_so << \"WARNINGS:\" << endl << er.WarningMessage << endl;\n        NumOpenArcWarnings++;\n        ThereIsWarning_in_Current = true;\n      }\n      \n      if (_so)\n      {\n        *_so << endl;\n        if (NeedFlush)\n          _so->Flush();\n      }\n    }\n\n  \n    if (er.ErrorFormatIndex >= 0)\n    {\n      if (_so)\n      {\n        Print_ErrorFormatIndex_Warning(_so, codecs, arc);\n        if (NeedFlush)\n          _so->Flush();\n      }\n      ThereIsWarning_in_Current = true;\n    }\n  }\n      \n  if (result == S_OK)\n  {\n    if (_so)\n    {\n      RINOK(Print_OpenArchive_Props(*_so, codecs, arcLink))\n      *_so << endl;\n    }\n  }\n  else\n  {\n    NumCantOpenArcs++;\n    if (_so)\n      _so->Flush();\n    if (_se)\n    {\n      *_se << kError;\n      _se->NormalizePrint_wstr_Path(name);\n      *_se << endl;\n      const HRESULT res = Print_OpenArchive_Error(*_se, codecs, arcLink);\n      RINOK(res)\n      if (result == S_FALSE)\n      {\n      }\n      else\n      {\n        if (result == E_OUTOFMEMORY)\n          *_se << \"Can't allocate required memory\";\n        else\n          *_se << NError::MyFormatMessage(result);\n        *_se << endl;\n      }\n      _se->Flush();\n    }\n  }\n  \n  \n  return CheckBreak2();\n}\n  \nHRESULT CExtractCallbackConsole::ThereAreNoFiles()\n{\n  ClosePercents_for_so();\n\n  if (_so)\n  {\n    *_so << endl << kNoFiles << endl;\n    if (NeedFlush)\n      _so->Flush();\n  }\n  return CheckBreak2();\n}\n\nHRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)\n{\n  MT_LOCK\n  \n  if (NeedPercents())\n  {\n    _percent.ClosePrint(true);\n    _percent.Command.Empty();\n    _percent.FileName.Empty();\n  }\n\n  if (_so)\n    _so->Flush();\n\n  if (result == S_OK)\n  {\n    if (NumFileErrors_in_Current == 0 && !ThereIsError_in_Current)\n    {\n      if (ThereIsWarning_in_Current)\n        NumArcsWithWarnings++;\n      else\n        NumOkArcs++;\n      if (_so)\n        *_so << kEverythingIsOk << endl;\n    }\n    else\n    {\n      NumArcsWithError++;\n      if (_so)\n      {\n        *_so << endl;\n        if (NumFileErrors_in_Current != 0)\n          *_so << \"Sub items Errors: \" << NumFileErrors_in_Current << endl;\n      }\n    }\n    if (_so && NeedFlush)\n      _so->Flush();\n  }\n  else\n  {\n    // we don't update NumArcsWithError, if error is not related to archive data.\n    if (result == E_ABORT\n        || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL))\n      return result;\n    NumArcsWithError++;\n    \n    if (_se)\n    {\n      *_se << endl << kError;\n      if (result == E_OUTOFMEMORY)\n        *_se << kMemoryExceptionMessage;\n      else\n        *_se << NError::MyFormatMessage(result);\n      *_se << endl;\n      _se->Flush();\n    }\n  }\n\n  return CheckBreak2();\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/ExtractCallbackConsole.h",
    "content": "﻿// ExtractCallbackConsole.h\n\n#ifndef ZIP7_INC_EXTRACT_CALLBACK_CONSOLE_H\n#define ZIP7_INC_EXTRACT_CALLBACK_CONSOLE_H\n\n#include \"../../../Common/StdOutStream.h\"\n\n#include \"../../IPassword.h\"\n\n#include \"../../Archive/IArchive.h\"\n\n#include \"../Common/ArchiveExtractCallback.h\"\n\n#include \"PercentPrinter.h\"\n\n#include \"OpenCallbackConsole.h\"\n\n/*\nstruct CErrorPathCodes2\n{\n  FStringVector Paths;\n  CRecordVector<DWORD> Codes;\n\n  void AddError(const FString &path, DWORD systemError)\n  {\n    Paths.Add(path);\n    Codes.Add(systemError);\n  }\n  void Clear()\n  {\n    Paths.Clear();\n    Codes.Clear();\n  }\n};\n*/\n\nclass CExtractScanConsole Z7_final: public IDirItemsCallback\n{\n  Z7_IFACE_IMP(IDirItemsCallback)\n\n  CStdOutStream *_so;\n  CStdOutStream *_se;\n  CPercentPrinter _percent;\n\n  // CErrorPathCodes2 ScanErrors;\n\n  bool NeedPercents() const { return _percent._so && !_percent.DisablePrint; }\n  \n  void ClosePercentsAndFlush()\n  {\n    if (NeedPercents())\n      _percent.ClosePrint(true);\n    if (_so)\n      _so->Flush();\n  }\n\npublic:\n\n  void Init(\n      CStdOutStream *outStream,\n      CStdOutStream *errorStream,\n      CStdOutStream *percentStream,\n      bool disablePercents)\n  {\n    _so = outStream;\n    _se = errorStream;\n    _percent._so = percentStream;\n    _percent.DisablePrint = disablePercents;\n  }\n  \n  void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }\n\n  void StartScanning();\n  \n  void CloseScanning()\n  {\n    if (NeedPercents())\n      _percent.ClosePrint(true);\n  }\n\n  void PrintStat(const CDirItemsStat &st);\n};\n\n\n\n\nclass CExtractCallbackConsole Z7_final:\n  public IFolderArchiveExtractCallback,\n  public IExtractCallbackUI,\n  // public IArchiveExtractCallbackMessage,\n  public IFolderArchiveExtractCallback2,\n #ifndef Z7_NO_CRYPTO\n  public ICryptoGetTextPassword,\n #endif\n #ifndef Z7_SFX\n  public IArchiveRequestMemoryUseCallback,\n #endif\n\n  public COpenCallbackConsole,\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IFolderArchiveExtractCallback)\n  // Z7_COM_QI_ENTRY(IArchiveExtractCallbackMessage)\n  Z7_COM_QI_ENTRY(IFolderArchiveExtractCallback2)\n #ifndef Z7_NO_CRYPTO\n  Z7_COM_QI_ENTRY(ICryptoGetTextPassword)\n #endif\n #ifndef Z7_SFX\n  Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)\n #endif\n\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_COM7_IMP(IProgress)\n  Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback)\n  Z7_IFACE_IMP(IExtractCallbackUI)\n  // Z7_IFACE_COM7_IMP(IArchiveExtractCallbackMessage)\n  Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback2)\n #ifndef Z7_NO_CRYPTO\n  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)\n #endif\n #ifndef Z7_SFX\n  Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)\n #endif\n\n  bool _needWriteArchivePath;\n\npublic:\n  bool ThereIsError_in_Current;\n  bool ThereIsWarning_in_Current;\n  bool NeedFlush;\n\nprivate:\n  AString _tempA;\n  UString _tempU;\n\n  UString _currentArchivePath;\n  UString _currentName;\n\n#ifndef Z7_SFX\n  void PrintTo_se_Path_WithTitle(const UString &path, const char *title);\n  void Add_ArchiveName_Error();\n#endif\n\n  void ClosePercents_for_so()\n  {\n    if (NeedPercents() && _so == _percent._so)\n      _percent.ClosePrint(false);\n  }\n  \n  void ClosePercentsAndFlush()\n  {\n    if (NeedPercents())\n      _percent.ClosePrint(true);\n    if (_so)\n      _so->Flush();\n  }\npublic:\n  UInt64 NumTryArcs;\n  \n  UInt64 NumOkArcs;\n  UInt64 NumCantOpenArcs;\n  UInt64 NumArcsWithError;\n  UInt64 NumArcsWithWarnings;\n\n  UInt64 NumOpenArcErrors;\n  UInt64 NumOpenArcWarnings;\n  \n  UInt64 NumFileErrors;\n  UInt64 NumFileErrors_in_Current;\n\n  unsigned PercentsNameLevel;\n  unsigned LogLevel;\n\n  CExtractCallbackConsole():\n      _needWriteArchivePath(true),\n      NeedFlush(false),\n      PercentsNameLevel(1),\n      LogLevel(0)\n      {}\n\n  void SetWindowWidth(unsigned width) { _percent.MaxLen = width - 1; }\n\n  void Init(\n      CStdOutStream *outStream,\n      CStdOutStream *errorStream,\n      CStdOutStream *percentStream,\n      bool disablePercents)\n  {\n    COpenCallbackConsole::Init(outStream, errorStream, percentStream, disablePercents);\n\n    NumTryArcs = 0;\n    \n    ThereIsError_in_Current = false;\n    ThereIsWarning_in_Current = false;\n\n    NumOkArcs = 0;\n    NumCantOpenArcs = 0;\n    NumArcsWithError = 0;\n    NumArcsWithWarnings = 0;\n\n    NumOpenArcErrors = 0;\n    NumOpenArcWarnings = 0;\n    \n    NumFileErrors = 0;\n    NumFileErrors_in_Current = 0;\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/List.cpp",
    "content": "﻿// List.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/StdOutStream.h\"\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/UTFConvert.h\"\n\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/PropVariant.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n\n#include \"../Common/OpenArchive.h\"\n#include \"../Common/PropIDUtils.h\"\n\n#include \"ConsoleClose.h\"\n#include \"List.h\"\n#include \"OpenCallbackConsole.h\"\n\nusing namespace NWindows;\nusing namespace NCOM;\n\nextern CStdOutStream *g_StdStream;\nextern CStdOutStream *g_ErrStream;\n\nstatic const char * const kPropIdToName[] =\n{\n    \"0\"\n  , \"1\"\n  , \"2\"\n  , \"Path\"\n  , \"Name\"\n  , \"Extension\"\n  , \"Folder\"\n  , \"Size\"\n  , \"Packed Size\"\n  , \"Attributes\"\n  , \"Created\"\n  , \"Accessed\"\n  , \"Modified\"\n  , \"Solid\"\n  , \"Commented\"\n  , \"Encrypted\"\n  , \"Split Before\"\n  , \"Split After\"\n  , \"Dictionary Size\"\n  , \"CRC\"\n  , \"Type\"\n  , \"Anti\"\n  , \"Method\"\n  , \"Host OS\"\n  , \"File System\"\n  , \"User\"\n  , \"Group\"\n  , \"Block\"\n  , \"Comment\"\n  , \"Position\"\n  , \"Path Prefix\"\n  , \"Folders\"\n  , \"Files\"\n  , \"Version\"\n  , \"Volume\"\n  , \"Multivolume\"\n  , \"Offset\"\n  , \"Links\"\n  , \"Blocks\"\n  , \"Volumes\"\n  , \"Time Type\"\n  , \"64-bit\"\n  , \"Big-endian\"\n  , \"CPU\"\n  , \"Physical Size\"\n  , \"Headers Size\"\n  , \"Checksum\"\n  , \"Characteristics\"\n  , \"Virtual Address\"\n  , \"ID\"\n  , \"Short Name\"\n  , \"Creator Application\"\n  , \"Sector Size\"\n  , \"Mode\"\n  , \"Symbolic Link\"\n  , \"Error\"\n  , \"Total Size\"\n  , \"Free Space\"\n  , \"Cluster Size\"\n  , \"Label\"\n  , \"Local Name\"\n  , \"Provider\"\n  , \"NT Security\"\n  , \"Alternate Stream\"\n  , \"Aux\"\n  , \"Deleted\"\n  , \"Tree\"\n  , \"SHA-1\"\n  , \"SHA-256\"\n  , \"Error Type\"\n  , \"Errors\"\n  , \"Errors\"\n  , \"Warnings\"\n  , \"Warning\"\n  , \"Streams\"\n  , \"Alternate Streams\"\n  , \"Alternate Streams Size\"\n  , \"Virtual Size\"\n  , \"Unpack Size\"\n  , \"Total Physical Size\"\n  , \"Volume Index\"\n  , \"SubType\"\n  , \"Short Comment\"\n  , \"Code Page\"\n  , \"Is not archive type\"\n  , \"Physical Size can't be detected\"\n  , \"Zeros Tail Is Allowed\"\n  , \"Tail Size\"\n  , \"Embedded Stub Size\"\n  , \"Link\"\n  , \"Hard Link\"\n  , \"iNode\"\n  , \"Stream ID\"\n  , \"Read-only\"\n  , \"Out Name\"\n  , \"Copy Link\"\n  , \"ArcFileName\"\n  , \"IsHash\"\n  , \"Metadata Changed\"\n  , \"User ID\"\n  , \"Group ID\"\n  , \"Device Major\"\n  , \"Device Minor\"\n  , \"Dev Major\"\n  , \"Dev Minor\"\n};\n\nstatic const char kEmptyAttribChar = '.';\n\nstatic const char * const kListing = \"Listing archive: \";\n\nstatic const char * const kString_Files = \"files\";\nstatic const char * const kString_Dirs = \"folders\";\nstatic const char * const kString_AltStreams = \"alternate streams\";\nstatic const char * const kString_Streams = \"streams\";\n\nstatic const char * const kError = \"ERROR: \";\n\nstatic void GetAttribString(UInt32 wa, bool isDir, bool allAttribs, char *s)\n{\n  if (isDir)\n    wa |= FILE_ATTRIBUTE_DIRECTORY;\n  if (allAttribs)\n  {\n    ConvertWinAttribToString(s, wa);\n    return;\n  }\n  s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0) ? 'D': kEmptyAttribChar;\n  s[1] = ((wa & FILE_ATTRIBUTE_READONLY)  != 0) ? 'R': kEmptyAttribChar;\n  s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN)    != 0) ? 'H': kEmptyAttribChar;\n  s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM)    != 0) ? 'S': kEmptyAttribChar;\n  s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE)   != 0) ? 'A': kEmptyAttribChar;\n  s[5] = 0;\n}\n\nenum EAdjustment\n{\n  kLeft,\n  kCenter,\n  kRight\n};\n\nstruct CFieldInfo\n{\n  PROPID PropID;\n  bool IsRawProp;\n  UString NameU;\n  AString NameA;\n  EAdjustment TitleAdjustment;\n  EAdjustment TextAdjustment;\n  unsigned PrefixSpacesWidth;\n  unsigned Width;\n};\n\nstruct CFieldInfoInit\n{\n  PROPID PropID;\n  const char *Name;\n  EAdjustment TitleAdjustment;\n  EAdjustment TextAdjustment;\n  unsigned PrefixSpacesWidth;\n  unsigned Width;\n};\n\nstatic const CFieldInfoInit kStandardFieldTable[] =\n{\n  { kpidMTime, \"   Date      Time\", kLeft, kLeft, 0, 19 },\n  { kpidAttrib, \"Attr\", kRight, kCenter, 1, 5 },\n  { kpidSize, \"Size\", kRight, kRight, 1, 12 },\n  { kpidPackSize, \"Compressed\", kRight, kRight, 1, 12 },\n  { kpidPath, \"Name\", kLeft, kLeft, 2, 24 }\n};\n\nstatic const unsigned kNumSpacesMax = 32; // it must be larger than max CFieldInfoInit.Width\nstatic const char * const g_Spaces =\n\"                                \" ;\n\nstatic void PrintSpaces(unsigned numSpaces)\n{\n  if (numSpaces > 0 && numSpaces <= kNumSpacesMax)\n    g_StdOut << g_Spaces + (kNumSpacesMax - numSpaces);\n}\n\nstatic void PrintSpacesToString(char *dest, unsigned numSpaces)\n{\n  unsigned i;\n  for (i = 0; i < numSpaces; i++)\n    dest[i] = ' ';\n  dest[i] = 0;\n}\n\n// extern int g_CodePage;\n\nstatic void PrintUString(EAdjustment adj, unsigned width, const UString &s, AString &temp)\n{\n  /*\n  // we don't need multibyte align.\n  int codePage = g_CodePage;\n  if (codePage == -1)\n    codePage = CP_OEMCP;\n  if (codePage == CP_UTF8)\n    ConvertUnicodeToUTF8(s, temp);\n  else\n    UnicodeStringToMultiByte2(temp, s, (UINT)codePage);\n  */\n\n  unsigned numSpaces = 0;\n\n  if (width > s.Len())\n  {\n    numSpaces = width - s.Len();\n    unsigned numLeftSpaces = 0;\n    switch ((int)adj)\n    {\n      // case kLeft:   numLeftSpaces = 0; break;\n      case kCenter: numLeftSpaces = numSpaces / 2; break;\n      case kRight:  numLeftSpaces = numSpaces; break;\n      // case kLeft:\n      default: break;\n    }\n    PrintSpaces(numLeftSpaces);\n    numSpaces -= numLeftSpaces;\n  }\n  \n  g_StdOut.PrintUString(s, temp);\n  PrintSpaces(numSpaces);\n}\n\nstatic void PrintString(EAdjustment adj, unsigned width, const char *s)\n{\n  unsigned numSpaces = 0;\n  unsigned len = (unsigned)strlen(s);\n\n  if (width > len)\n  {\n    numSpaces = width - len;\n    unsigned numLeftSpaces = 0;\n    switch ((int)adj)\n    {\n      // case kLeft:   numLeftSpaces = 0; break;\n      case kCenter: numLeftSpaces = numSpaces / 2; break;\n      case kRight:  numLeftSpaces = numSpaces; break;\n      // case kLeft:\n      default: break;\n    }\n    PrintSpaces(numLeftSpaces);\n    numSpaces -= numLeftSpaces;\n  }\n  \n  g_StdOut << s;\n  PrintSpaces(numSpaces);\n}\n\nstatic void PrintStringToString(char *dest, EAdjustment adj, unsigned width, const char *textString)\n{\n  unsigned numSpaces = 0;\n  unsigned len = (unsigned)strlen(textString);\n  \n  if (width > len)\n  {\n    numSpaces = width - len;\n    unsigned numLeftSpaces = 0;\n    switch ((int)adj)\n    {\n      // case kLeft:   numLeftSpaces = 0; break;\n      case kCenter: numLeftSpaces = numSpaces / 2; break;\n      case kRight:  numLeftSpaces = numSpaces; break;\n      // case kLeft:\n      default: break;\n    }\n    PrintSpacesToString(dest, numLeftSpaces);\n    dest += numLeftSpaces;\n    numSpaces -= numLeftSpaces;\n  }\n  \n  memcpy(dest, textString, len);\n  dest += len;\n  PrintSpacesToString(dest, numSpaces);\n}\n\nstruct CListUInt64Def\n{\n  UInt64 Val;\n  bool Def;\n\n  CListUInt64Def(): Val(0), Def(false) {}\n  void Add(UInt64 v) { Val += v; Def = true; }\n  void Add(const CListUInt64Def &v) { if (v.Def) Add(v.Val); }\n};\n\n\nstruct CListFileTimeDef: public CArcTime\n{\n  void Update(const CListFileTimeDef &t)\n  {\n    if (t.Def && (!Def || CompareWith(t) < 0))\n      (*this) = t;\n  }\n};\n\n\n\nstruct CListStat\n{\n  CListUInt64Def Size;\n  CListUInt64Def PackSize;\n  CListFileTimeDef MTime;\n  UInt64 NumFiles;\n\n  CListStat(): NumFiles(0) {}\n  void Update(const CListStat &st)\n  {\n    Size.Add(st.Size);\n    PackSize.Add(st.PackSize);\n    MTime.Update(st.MTime);\n    NumFiles += st.NumFiles;\n  }\n  void SetSizeDefIfNoFiles() { if (NumFiles == 0) Size.Def = true; }\n};\n\nstruct CListStat2\n{\n  CListStat MainFiles;\n  CListStat AltStreams;\n  UInt64 NumDirs;\n\n  CListStat2(): NumDirs(0) {}\n\n  void Update(const CListStat2 &st)\n  {\n    MainFiles.Update(st.MainFiles);\n    AltStreams.Update(st.AltStreams);\n    NumDirs += st.NumDirs;\n  }\n  UInt64 GetNumStreams() const { return MainFiles.NumFiles + AltStreams.NumFiles; }\n  CListStat &GetStat(bool altStreamsMode) { return altStreamsMode ? AltStreams : MainFiles; }\n};\n\nclass CFieldPrinter\n{\n  CObjectVector<CFieldInfo> _fields;\n\n  void AddProp(const wchar_t *name, PROPID propID, bool isRawProp);\npublic:\n  const CArc *Arc;\n  bool TechMode;\n  UString FilePath;\n  AString TempAString;\n  UString TempWString;\n  bool IsDir;\n\n  AString LinesString;\n\n  void Clear() { _fields.Clear(); LinesString.Empty(); }\n  void Init(const CFieldInfoInit *standardFieldTable, unsigned numItems);\n\n  HRESULT AddMainProps(IInArchive *archive);\n  HRESULT AddRawProps(IArchiveGetRawProps *getRawProps);\n  \n  void PrintTitle();\n  void PrintTitleLines();\n  HRESULT PrintItemInfo(UInt32 index, const CListStat &st);\n  void PrintSum(const CListStat &st, UInt64 numDirs, const char *str);\n  void PrintSum(const CListStat2 &stat2);\n};\n\nvoid CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, unsigned numItems)\n{\n  Clear();\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    CFieldInfo &f = _fields.AddNew();\n    const CFieldInfoInit &fii = standardFieldTable[i];\n    f.PropID = fii.PropID;\n    f.IsRawProp = false;\n    f.NameA = fii.Name;\n    f.TitleAdjustment = fii.TitleAdjustment;\n    f.TextAdjustment = fii.TextAdjustment;\n    f.PrefixSpacesWidth = fii.PrefixSpacesWidth;\n    f.Width = fii.Width;\n\n    unsigned k;\n    for (k = 0; k < fii.PrefixSpacesWidth; k++)\n      LinesString.Add_Space();\n    for (k = 0; k < fii.Width; k++)\n      LinesString.Add_Minus();\n  }\n}\n\nstatic void GetPropName(PROPID propID, const wchar_t *name, AString &nameA, UString &nameU)\n{\n  if (propID < Z7_ARRAY_SIZE(kPropIdToName))\n  {\n    nameA = kPropIdToName[propID];\n    return;\n  }\n  if (name)\n    nameU = name;\n  else\n  {\n    nameA.Empty();\n    nameA.Add_UInt32(propID);\n  }\n}\n\nvoid CFieldPrinter::AddProp(const wchar_t *name, PROPID propID, bool isRawProp)\n{\n  CFieldInfo f;\n  f.PropID = propID;\n  f.IsRawProp = isRawProp;\n  GetPropName(propID, name, f.NameA, f.NameU);\n  f.NameU += \" = \";\n  if (!f.NameA.IsEmpty())\n    f.NameA += \" = \";\n  else\n  {\n    const UString &s = f.NameU;\n    AString sA;\n    unsigned i;\n    for (i = 0; i < s.Len(); i++)\n    {\n      const wchar_t c = s[i];\n      if (c >= 0x80)\n        break;\n      sA.Add_Char((char)c);\n    }\n    if (i == s.Len())\n      f.NameA = sA;\n  }\n  _fields.Add(f);\n}\n\nHRESULT CFieldPrinter::AddMainProps(IInArchive *archive)\n{\n  UInt32 numProps;\n  RINOK(archive->GetNumberOfProperties(&numProps))\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    CMyComBSTR name;\n    PROPID propID;\n    VARTYPE vt;\n    RINOK(archive->GetPropertyInfo(i, &name, &propID, &vt))\n    AddProp(name, propID, false);\n  }\n  return S_OK;\n}\n\nHRESULT CFieldPrinter::AddRawProps(IArchiveGetRawProps *getRawProps)\n{\n  UInt32 numProps;\n  RINOK(getRawProps->GetNumRawProps(&numProps))\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    CMyComBSTR name;\n    PROPID propID;\n    RINOK(getRawProps->GetRawPropInfo(i, &name, &propID))\n    AddProp(name, propID, true);\n  }\n  return S_OK;\n}\n\nvoid CFieldPrinter::PrintTitle()\n{\n  FOR_VECTOR (i, _fields)\n  {\n    const CFieldInfo &f = _fields[i];\n    PrintSpaces(f.PrefixSpacesWidth);\n    PrintString(f.TitleAdjustment, ((f.PropID == kpidPath) ? 0: f.Width), f.NameA);\n  }\n}\n\nvoid CFieldPrinter::PrintTitleLines()\n{\n  g_StdOut << LinesString;\n}\n\nstatic void PrintTime(char *dest, const CListFileTimeDef &t, bool showNS)\n{\n  *dest = 0;\n  if (t.IsZero())\n    return;\n  int prec = kTimestampPrintLevel_SEC;\n  unsigned flags = 0;\n  if (showNS) // techmode\n  {\n    prec = kTimestampPrintLevel_NTFS;\n    if (t.Prec != 0)\n    {\n      prec = t.GetNumDigits();\n      if (prec < kTimestampPrintLevel_DAY)\n        prec = kTimestampPrintLevel_NTFS;\n    }\n  }\n  else\n  {\n    // we want same default number of characters, so we disable 'Z' marker:\n    flags = kTimestampPrintFlags_DisableZ;\n  }\n\n  ConvertUtcFileTimeToString2(t.FT, t.Ns100, dest, prec, flags);\n}\n\n#ifndef Z7_SFX\n\n#endif\n\n#define MY_ENDL endl\n\ninline bool IsPropId_for_PathString(UInt32 propId)\n{\n  return (propId == kpidPath\n    // || propId == kpidName\n    || propId == kpidSymLink\n    || propId == kpidHardLink\n    || propId == kpidCopyLink);\n}\n\nHRESULT CFieldPrinter::PrintItemInfo(UInt32 index, const CListStat &st)\n{\n  char temp[128];\n  size_t tempPos = 0;\n\n  bool techMode = this->TechMode;\n  /*\n  if (techMode)\n  {\n    g_StdOut << \"Index = \";\n    g_StdOut << (UInt64)index;\n    g_StdOut << endl;\n  }\n  */\n  FOR_VECTOR (i, _fields)\n  {\n    const CFieldInfo &f = _fields[i];\n\n    if (!techMode)\n    {\n      PrintSpacesToString(temp + tempPos, f.PrefixSpacesWidth);\n      tempPos += f.PrefixSpacesWidth;\n    }\n\n    if (techMode)\n    {\n      if (!f.NameA.IsEmpty())\n        g_StdOut << f.NameA;\n      else\n        g_StdOut << f.NameU;\n    }\n    \n    if (f.PropID == kpidPath)\n    {\n      if (!techMode)\n        g_StdOut << temp;\n      g_StdOut.NormalizePrint_UString_Path(FilePath, TempWString, TempAString);\n      if (techMode)\n        g_StdOut << MY_ENDL;\n      continue;\n    }\n\n    const unsigned width = f.Width;\n    \n    if (f.IsRawProp)\n    {\n      #ifndef Z7_SFX\n      \n      const void *data;\n      UInt32 dataSize;\n      UInt32 propType;\n      RINOK(Arc->GetRawProps->GetRawProp(index, f.PropID, &data, &dataSize, &propType))\n      \n      if (dataSize != 0)\n      {\n        bool needPrint = true;\n        \n        if (f.PropID == kpidNtSecure)\n        {\n          if (propType != NPropDataType::kRaw)\n            return E_FAIL;\n          #ifndef Z7_SFX\n          ConvertNtSecureToString((const Byte *)data, dataSize, TempAString);\n          g_StdOut << TempAString;\n          needPrint = false;\n          #endif\n        }\n        else if (f.PropID == kpidNtReparse)\n        {\n          UString s;\n          if (ConvertNtReparseToString((const Byte *)data, dataSize, s))\n          {\n            needPrint = false;\n            g_StdOut.PrintUString(s, TempAString);\n          }\n        }\n      \n        if (needPrint)\n        {\n          if (propType != NPropDataType::kRaw)\n            return E_FAIL;\n          \n          const UInt32 kMaxDataSize = 64;\n          \n          if (dataSize > kMaxDataSize)\n          {\n            g_StdOut << \"data:\";\n            g_StdOut << dataSize;\n          }\n          else\n          {\n            char hexStr[kMaxDataSize * 2 + 4];\n            ConvertDataToHex_Lower(hexStr, (const Byte *)data, dataSize);\n            g_StdOut << hexStr;\n          }\n        }\n      }\n      \n      #endif\n    }\n    else\n    {\n      CPropVariant prop;\n      switch (f.PropID)\n      {\n        case kpidSize: if (st.Size.Def) prop = st.Size.Val; break;\n        case kpidPackSize: if (st.PackSize.Def) prop = st.PackSize.Val; break;\n        case kpidMTime:\n        {\n          const CListFileTimeDef &mtime = st.MTime;\n          if (mtime.Def)\n            prop.SetAsTimeFrom_FT_Prec_Ns100(mtime.FT, mtime.Prec, mtime.Ns100);\n          break;\n        }\n        default:\n          RINOK(Arc->Archive->GetProperty(index, f.PropID, &prop))\n      }\n      if (f.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))\n      {\n        GetAttribString((prop.vt == VT_EMPTY) ? 0 : prop.ulVal, IsDir, techMode, temp + tempPos);\n        if (techMode)\n          g_StdOut << temp + tempPos;\n        else\n          tempPos += strlen(temp + tempPos);\n      }\n      else if (prop.vt == VT_EMPTY)\n      {\n        if (!techMode)\n        {\n          PrintSpacesToString(temp + tempPos, width);\n          tempPos += width;\n        }\n      }\n      else if (prop.vt == VT_FILETIME)\n      {\n        CListFileTimeDef t;\n        t.Set_From_Prop(prop);\n        PrintTime(temp + tempPos, t, techMode);\n        if (techMode)\n          g_StdOut << temp + tempPos;\n        else\n        {\n          size_t len = strlen(temp + tempPos);\n          tempPos += len;\n          if (len < (unsigned)f.Width)\n          {\n            len = f.Width - len;\n            PrintSpacesToString(temp + tempPos, (unsigned)len);\n            tempPos += len;\n          }\n        }\n      }\n      else if (prop.vt == VT_BSTR)\n      {\n        TempWString.SetFromBstr(prop.bstrVal);\n        // do we need multi-line support here ?\n        if (IsPropId_for_PathString(f.PropID))\n          g_StdOut.Normalize_UString_Path(TempWString);\n        else\n          g_StdOut.Normalize_UString(TempWString);\n        if (techMode)\n          g_StdOut.PrintUString(TempWString, TempAString);\n        else\n          PrintUString(f.TextAdjustment, width, TempWString, TempAString);\n      }\n      else\n      {\n        char s[64];\n        ConvertPropertyToShortString2(s, prop, f.PropID);\n        if (techMode)\n          g_StdOut << s;\n        else\n        {\n          PrintStringToString(temp + tempPos, f.TextAdjustment, width, s);\n          tempPos += strlen(temp + tempPos);\n        }\n      }\n    }\n    if (techMode)\n      g_StdOut << MY_ENDL;\n  }\n  g_StdOut << MY_ENDL;\n  return S_OK;\n}\n\nstatic void PrintNumber(EAdjustment adj, unsigned width, const CListUInt64Def &value)\n{\n  char s[32];\n  s[0] = 0;\n  if (value.Def)\n    ConvertUInt64ToString(value.Val, s);\n  PrintString(adj, width, s);\n}\n\nvoid Print_UInt64_and_String(AString &s, UInt64 val, const char *name);\n\nvoid CFieldPrinter::PrintSum(const CListStat &st, UInt64 numDirs, const char *str)\n{\n  FOR_VECTOR (i, _fields)\n  {\n    const CFieldInfo &f = _fields[i];\n    PrintSpaces(f.PrefixSpacesWidth);\n    if (f.PropID == kpidSize)\n      PrintNumber(f.TextAdjustment, f.Width, st.Size);\n    else if (f.PropID == kpidPackSize)\n      PrintNumber(f.TextAdjustment, f.Width, st.PackSize);\n    else if (f.PropID == kpidMTime)\n    {\n      char s[64];\n      s[0] = 0;\n      if (st.MTime.Def)\n        PrintTime(s, st.MTime, false); // showNS\n      PrintString(f.TextAdjustment, f.Width, s);\n    }\n    else if (f.PropID == kpidPath)\n    {\n      AString s;\n      Print_UInt64_and_String(s, st.NumFiles, str);\n      if (numDirs != 0)\n      {\n        s += \", \";\n        Print_UInt64_and_String(s, numDirs, kString_Dirs);\n      }\n      PrintString(f.TextAdjustment, 0, s);\n    }\n    else\n      PrintString(f.TextAdjustment, f.Width, \"\");\n  }\n  g_StdOut << endl;\n}\n\nvoid CFieldPrinter::PrintSum(const CListStat2 &stat2)\n{\n  PrintSum(stat2.MainFiles, stat2.NumDirs, kString_Files);\n  if (stat2.AltStreams.NumFiles != 0)\n  {\n    PrintSum(stat2.AltStreams, 0, kString_AltStreams);\n    CListStat st = stat2.MainFiles;\n    st.Update(stat2.AltStreams);\n    PrintSum(st, 0, kString_Streams);\n  }\n}\n\nstatic HRESULT GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, CListUInt64Def &value)\n{\n  value.Val = 0;\n  value.Def = false;\n  CPropVariant prop;\n  RINOK(archive->GetProperty(index, propID, &prop))\n  value.Def = ConvertPropVariantToUInt64(prop, value.Val);\n  return S_OK;\n}\n\nstatic HRESULT GetItemMTime(IInArchive *archive, UInt32 index, CListFileTimeDef &t)\n{\n  /* maybe we could call CArc::GetItemMTime(UInt32 index, CArcTime &ft, bool &defined) here\n     that can set default timestamp, if not defined */\n  t.Clear();\n  // t.Def = false;\n  CPropVariant prop;\n  RINOK(archive->GetProperty(index, kpidMTime, &prop))\n  if (prop.vt == VT_FILETIME)\n    t.Set_From_Prop(prop);\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\nstatic void PrintPropNameAndNumber(CStdOutStream &so, const char *name, UInt64 val)\n{\n  so << name << \": \" << val << endl;\n}\n\nstatic void PrintPropName_and_Eq(CStdOutStream &so, PROPID propID)\n{\n  const char *s;\n  char temp[16];\n  if (propID < Z7_ARRAY_SIZE(kPropIdToName))\n    s = kPropIdToName[propID];\n  else\n  {\n    ConvertUInt32ToString(propID, temp);\n    s = temp;\n  }\n  so << s << \" = \";\n}\n\nstatic void PrintPropNameAndNumber(CStdOutStream &so, PROPID propID, UInt64 val)\n{\n  PrintPropName_and_Eq(so, propID);\n  so << val << endl;\n}\n\nstatic void PrintPropNameAndNumber_Signed(CStdOutStream &so, PROPID propID, Int64 val)\n{\n  PrintPropName_and_Eq(so, propID);\n  so << val << endl;\n}\n\n\nstatic void UString_Replace_CRLF_to_LF(UString &s)\n{\n  // s.Replace(L\"\\r\\n\", L\"\\n\");\n  wchar_t *src = s.GetBuf();\n  wchar_t *dest = src;\n  for (;;)\n  {\n    wchar_t c = *src++;\n    if (c == 0)\n      break;\n    if (c == '\\r' && *src == '\\n')\n    {\n      src++;\n      c = '\\n';\n    }\n    *dest++ = c;\n  }\n  s.ReleaseBuf_SetEnd((unsigned)(size_t)(dest - s.GetBuf()));\n}\n\nstatic void PrintPropVal_MultiLine(CStdOutStream &so, const wchar_t *val)\n{\n  UString s (val);\n  if (s.Find(L'\\n') >= 0)\n  {\n    so << endl;\n    so << \"{\";\n    so << endl;\n    UString_Replace_CRLF_to_LF(s);\n    UString temp;\n    unsigned start = 0;\n    for (;;)\n    {\n      unsigned size = s.Len() - start;\n      if (size == 0)\n        break;\n      const int next = s.Find(L'\\n', start);\n      if (next >= 0)\n        size = (unsigned)next - start;\n      temp.SetFrom(s.Ptr() + start, size);\n      so.NormalizePrint_UString(temp);\n      so << endl;\n      if (next < 0)\n        break;\n      start = (unsigned)next + 1;\n    }\n    so << \"}\";\n  }\n  else\n  {\n    so.NormalizePrint_UString(s);\n  }\n  so << endl;\n}\n\n\nstatic void PrintPropPair(CStdOutStream &so, const char *name, const wchar_t *val, bool multiLine, bool isPath = false)\n{\n  so << name << \" = \";\n  if (multiLine)\n  {\n    PrintPropVal_MultiLine(so, val);\n    return;\n  }\n  UString s (val);\n  if (isPath)\n    so.Normalize_UString_Path(s);\n  else\n    so.Normalize_UString(s);\n  so << s;\n  so << endl;\n}\n\n\nstatic void PrintPropPair_Path(CStdOutStream &so, const wchar_t *path)\n{\n  PrintPropPair(so, \"Path\", path,\n        false, // multiLine\n        true); // isPath\n}\n\nstatic void PrintPropertyPair2(CStdOutStream &so, PROPID propID, const wchar_t *name, const CPropVariant &prop)\n{\n  UString s;\n  const int levelTopLimit = 9; // 1ns level\n  ConvertPropertyToString2(s, prop, propID, levelTopLimit);\n  if (!s.IsEmpty())\n  {\n    AString nameA;\n    UString nameU;\n    GetPropName(propID, name, nameA, nameU);\n    if (!nameA.IsEmpty())\n      so << nameA;\n    else\n      so << nameU;\n    so << \" = \";\n    PrintPropVal_MultiLine(so, s);\n  }\n}\n\nstatic HRESULT PrintArcProp(CStdOutStream &so, IInArchive *archive, PROPID propID, const wchar_t *name)\n{\n  CPropVariant prop;\n  RINOK(archive->GetArchiveProperty(propID, &prop))\n  PrintPropertyPair2(so, propID, name, prop);\n  return S_OK;\n}\n\nstatic void PrintArcTypeError(CStdOutStream &so, const UString &type, bool isWarning)\n{\n  so << \"Open \" << (isWarning ? \"WARNING\" : \"ERROR\")\n    << \": Cannot open the file as [\"\n    << type\n    << \"] archive\"\n    << endl;\n}\n\nint Find_FileName_InSortedVector(const UStringVector &fileName, const UString& name);\n\nvoid PrintErrorFlags(CStdOutStream &so, const char *s, UInt32 errorFlags);\n\nstatic void ErrorInfo_Print(CStdOutStream &so, const CArcErrorInfo &er)\n{\n  PrintErrorFlags(so, \"ERRORS:\", er.GetErrorFlags());\n  if (!er.ErrorMessage.IsEmpty())\n    PrintPropPair(so, \"ERROR\", er.ErrorMessage, true);\n  \n  PrintErrorFlags(so, \"WARNINGS:\", er.GetWarningFlags());\n  if (!er.WarningMessage.IsEmpty())\n    PrintPropPair(so, \"WARNING\", er.WarningMessage, true);\n}\n\nHRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);\nHRESULT Print_OpenArchive_Props(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)\n{\n  FOR_VECTOR (r, arcLink.Arcs)\n  {\n    const CArc &arc = arcLink.Arcs[r];\n    const CArcErrorInfo &er = arc.ErrorInfo;\n    \n    so << \"--\\n\";\n    PrintPropPair_Path(so, arc.Path);\n    if (er.ErrorFormatIndex >= 0)\n    {\n      if (er.ErrorFormatIndex == arc.FormatIndex)\n        so << \"Warning: The archive is open with offset\" << endl;\n      else\n        PrintArcTypeError(so, codecs->GetFormatNamePtr(er.ErrorFormatIndex), true);\n    }\n    PrintPropPair(so, \"Type\", codecs->GetFormatNamePtr(arc.FormatIndex), false);\n    \n    ErrorInfo_Print(so, er);\n    \n    Int64 offset = arc.GetGlobalOffset();\n    if (offset != 0)\n      PrintPropNameAndNumber_Signed(so, kpidOffset, offset);\n    IInArchive *archive = arc.Archive;\n    RINOK(PrintArcProp(so, archive, kpidPhySize, NULL))\n    if (er.TailSize != 0)\n      PrintPropNameAndNumber(so, kpidTailSize, er.TailSize);\n    {\n      UInt32 numProps;\n      RINOK(archive->GetNumberOfArchiveProperties(&numProps))\n      \n      for (UInt32 j = 0; j < numProps; j++)\n      {\n        CMyComBSTR name;\n        PROPID propID;\n        VARTYPE vt;\n        RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt))\n        RINOK(PrintArcProp(so, archive, propID, name))\n      }\n    }\n    \n    if (r != arcLink.Arcs.Size() - 1)\n    {\n      UInt32 numProps;\n      so << \"----\\n\";\n      if (archive->GetNumberOfProperties(&numProps) == S_OK)\n      {\n        UInt32 mainIndex = arcLink.Arcs[r + 1].SubfileIndex;\n        for (UInt32 j = 0; j < numProps; j++)\n        {\n          CMyComBSTR name;\n          PROPID propID;\n          VARTYPE vt;\n          RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt))\n          CPropVariant prop;\n          RINOK(archive->GetProperty(mainIndex, propID, &prop))\n          PrintPropertyPair2(so, propID, name, prop);\n        }\n      }\n    }\n  }\n  return S_OK;\n}\n\nHRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink);\nHRESULT Print_OpenArchive_Error(CStdOutStream &so, const CCodecs *codecs, const CArchiveLink &arcLink)\n{\n  #ifndef Z7_NO_CRYPTO\n  if (arcLink.PasswordWasAsked)\n    so << \"Cannot open encrypted archive. Wrong password?\";\n  else\n  #endif\n  {\n    if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)\n    {\n      so.NormalizePrint_UString_Path(arcLink.NonOpen_ArcPath);\n      so << endl;\n      PrintArcTypeError(so, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);\n    }\n    else\n      so << \"Cannot open the file as archive\";\n  }\n\n  so << endl;\n  so << endl;\n  ErrorInfo_Print(so, arcLink.NonOpen_ErrorInfo);\n\n  return S_OK;\n}\n\nbool CensorNode_CheckPath(const NWildcard::CCensorNode &node, const CReadArcItem &item);\n\nHRESULT ListArchives(\n    const CListOptions &listOptions,\n    CCodecs *codecs,\n    const CObjectVector<COpenType> &types,\n    const CIntVector &excludedFormats,\n    bool stdInMode,\n    UStringVector &arcPaths, UStringVector &arcPathsFull,\n    bool processAltStreams, bool showAltStreams,\n    const NWildcard::CCensorNode &wildcardCensor,\n    bool enableHeaders, bool techMode,\n    #ifndef Z7_NO_CRYPTO\n    bool &passwordEnabled, UString &password,\n    #endif\n    #ifndef Z7_SFX\n    const CObjectVector<CProperty> *props,\n    #endif\n    UInt64 &numErrors,\n    UInt64 &numWarnings)\n{\n  bool allFilesAreAllowed = wildcardCensor.AreAllAllowed();\n\n  numErrors = 0;\n  numWarnings = 0;\n\n  CFieldPrinter fp;\n  if (!techMode)\n    fp.Init(kStandardFieldTable, Z7_ARRAY_SIZE(kStandardFieldTable));\n\n  CListStat2 stat2total;\n  \n  CBoolArr skipArcs(arcPaths.Size());\n  unsigned arcIndex;\n  for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)\n    skipArcs[arcIndex] = false;\n  UInt64 numVolumes = 0;\n  UInt64 numArcs = 0;\n  UInt64 totalArcSizes = 0;\n\n  HRESULT lastError = 0;\n\n  for (arcIndex = 0; arcIndex < arcPaths.Size(); arcIndex++)\n  {\n    if (skipArcs[arcIndex])\n      continue;\n    const UString &arcPath = arcPaths[arcIndex];\n    UInt64 arcPackSize = 0;\n    \n    if (!stdInMode)\n    {\n      NFile::NFind::CFileInfo fi;\n      if (!fi.Find_FollowLink(us2fs(arcPath)))\n      {\n        DWORD errorCode = GetLastError();\n        if (errorCode == 0)\n          errorCode = ERROR_FILE_NOT_FOUND;\n        lastError = HRESULT_FROM_WIN32(errorCode);\n        g_StdOut.Flush();\n        if (g_ErrStream)\n        {\n          *g_ErrStream << endl << kError << NError::MyFormatMessage(errorCode) << endl;\n          g_ErrStream->NormalizePrint_UString_Path(arcPath);\n          *g_ErrStream << endl << endl;\n        }\n        numErrors++;\n        continue;\n      }\n      if (fi.IsDir())\n      {\n        g_StdOut.Flush();\n        if (g_ErrStream)\n        {\n          *g_ErrStream << endl << kError;\n          g_ErrStream->NormalizePrint_UString_Path(arcPath);\n          *g_ErrStream << \" is not a file\" << endl << endl;\n        }\n        numErrors++;\n        continue;\n      }\n      arcPackSize = fi.Size;\n      totalArcSizes += arcPackSize;\n    }\n\n    CArchiveLink arcLink;\n\n    COpenCallbackConsole openCallback;\n    openCallback.Init(&g_StdOut, g_ErrStream, NULL, listOptions.DisablePercents);\n\n    #ifndef Z7_NO_CRYPTO\n\n    openCallback.PasswordIsDefined = passwordEnabled;\n    openCallback.Password = password;\n\n    #endif\n\n    /*\n    CObjectVector<COptionalOpenProperties> optPropsVector;\n    COptionalOpenProperties &optProps = optPropsVector.AddNew();\n    optProps.Props = *props;\n    */\n    \n    COpenOptions options;\n    #ifndef Z7_SFX\n    options.props = props;\n    #endif\n    options.codecs = codecs;\n    options.types = &types;\n    options.excludedFormats = &excludedFormats;\n    options.stdInMode = stdInMode;\n    options.stream = NULL;\n    options.filePath = arcPath;\n\n    if (enableHeaders)\n    {\n      g_StdOut << endl << kListing;\n      g_StdOut.NormalizePrint_UString_Path(arcPath);\n      g_StdOut << endl << endl;\n    }\n    \n    HRESULT result = arcLink.Open_Strict(options, &openCallback);\n\n    if (result != S_OK)\n    {\n      if (result == E_ABORT)\n        return result;\n      if (result != S_FALSE)\n        lastError = result;\n      g_StdOut.Flush();\n      if (g_ErrStream)\n      {\n        *g_ErrStream << endl << kError;\n        g_ErrStream->NormalizePrint_UString_Path(arcPath);\n        *g_ErrStream << \" : \";\n        if (result == S_FALSE)\n        {\n          Print_OpenArchive_Error(*g_ErrStream, codecs, arcLink);\n        }\n        else\n        {\n          *g_ErrStream << \"opening : \";\n          if (result == E_OUTOFMEMORY)\n            *g_ErrStream << \"Can't allocate required memory\";\n          else\n            *g_ErrStream << NError::MyFormatMessage(result);\n        }\n        *g_ErrStream << endl;\n      }\n      numErrors++;\n      continue;\n    }\n    \n    {\n      FOR_VECTOR (r, arcLink.Arcs)\n      {\n        const CArcErrorInfo &arc = arcLink.Arcs[r].ErrorInfo;\n        if (!arc.WarningMessage.IsEmpty())\n          numWarnings++;\n        if (arc.AreThereWarnings())\n          numWarnings++;\n        if (arc.ErrorFormatIndex >= 0)\n          numWarnings++;\n        if (arc.AreThereErrors())\n        {\n          numErrors++;\n          // break;\n        }\n        if (!arc.ErrorMessage.IsEmpty())\n          numErrors++;\n      }\n    }\n\n    numArcs++;\n    numVolumes++;\n\n    if (!stdInMode)\n    {\n      numVolumes += arcLink.VolumePaths.Size();\n      totalArcSizes += arcLink.VolumesSize;\n      FOR_VECTOR (v, arcLink.VolumePaths)\n      {\n        int index = Find_FileName_InSortedVector(arcPathsFull, arcLink.VolumePaths[v]);\n        if (index >= 0 && (unsigned)index > arcIndex)\n          skipArcs[(unsigned)index] = true;\n      }\n    }\n\n\n    if (enableHeaders)\n    {\n      RINOK(Print_OpenArchive_Props(g_StdOut, codecs, arcLink))\n\n      g_StdOut << endl;\n      if (techMode)\n        g_StdOut << \"----------\\n\";\n    }\n\n    if (enableHeaders && !techMode)\n    {\n      fp.PrintTitle();\n      g_StdOut << endl;\n      fp.PrintTitleLines();\n      g_StdOut << endl;\n    }\n\n    const CArc &arc = arcLink.Arcs.Back();\n    fp.Arc = &arc;\n    fp.TechMode = techMode;\n    IInArchive *archive = arc.Archive;\n    if (techMode)\n    {\n      fp.Clear();\n      RINOK(fp.AddMainProps(archive))\n      if (arc.GetRawProps)\n      {\n        RINOK(fp.AddRawProps(arc.GetRawProps))\n      }\n    }\n    \n    CListStat2 stat2;\n    \n    UInt32 numItems;\n    RINOK(archive->GetNumberOfItems(&numItems))\n \n    CReadArcItem item;\n    UStringVector pathParts;\n    \n    for (UInt32 i = 0; i < numItems; i++)\n    {\n      if (NConsoleClose::TestBreakSignal())\n        return E_ABORT;\n\n      HRESULT res = arc.GetItem_Path2(i, fp.FilePath);\n\n      if (stdInMode && res == E_INVALIDARG)\n        break;\n      RINOK(res)\n\n      if (arc.Ask_Aux)\n      {\n        bool isAux;\n        RINOK(Archive_IsItem_Aux(archive, i, isAux))\n        if (isAux)\n          continue;\n      }\n\n      bool isAltStream = false;\n      if (arc.Ask_AltStream)\n      {\n        RINOK(Archive_IsItem_AltStream(archive, i, isAltStream))\n        if (isAltStream && !processAltStreams)\n          continue;\n      }\n\n      RINOK(Archive_IsItem_Dir(archive, i, fp.IsDir))\n\n      if (fp.IsDir ? listOptions.ExcludeDirItems : listOptions.ExcludeFileItems)\n        continue;\n\n      if (!allFilesAreAllowed)\n      {\n        if (isAltStream)\n        {\n          RINOK(arc.GetItem(i, item))\n          if (!CensorNode_CheckPath(wildcardCensor, item))\n            continue;\n        }\n        else\n        {\n          SplitPathToParts(fp.FilePath, pathParts);\n          bool include;\n          if (!wildcardCensor.CheckPathVect(pathParts, !fp.IsDir, include))\n            continue;\n          if (!include)\n            continue;\n        }\n      }\n      \n      CListStat st;\n      \n      RINOK(GetUInt64Value(archive, i, kpidSize, st.Size))\n      RINOK(GetUInt64Value(archive, i, kpidPackSize, st.PackSize))\n      RINOK(GetItemMTime(archive, i, st.MTime))\n\n      if (fp.IsDir)\n        stat2.NumDirs++;\n      else\n        st.NumFiles = 1;\n      stat2.GetStat(isAltStream).Update(st);\n\n      if (isAltStream && !showAltStreams)\n        continue;\n      RINOK(fp.PrintItemInfo(i, st))\n    }\n\n    UInt64 numStreams = stat2.GetNumStreams();\n    if (!stdInMode\n        && !stat2.MainFiles.PackSize.Def\n        && !stat2.AltStreams.PackSize.Def)\n    {\n      if (arcLink.VolumePaths.Size() != 0)\n        arcPackSize += arcLink.VolumesSize;\n      stat2.MainFiles.PackSize.Add((numStreams == 0) ? 0 : arcPackSize);\n    }\n  \n    stat2.MainFiles.SetSizeDefIfNoFiles();\n    stat2.AltStreams.SetSizeDefIfNoFiles();\n    \n    if (enableHeaders && !techMode)\n    {\n      fp.PrintTitleLines();\n      g_StdOut << endl;\n      fp.PrintSum(stat2);\n    }\n\n    if (enableHeaders)\n    {\n      if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)\n      {\n        g_StdOut << \"----------\\n\";\n        PrintPropPair_Path(g_StdOut, arcLink.NonOpen_ArcPath);\n        PrintArcTypeError(g_StdOut, codecs->Formats[(unsigned)arcLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name, false);\n      }\n    }\n    \n    stat2total.Update(stat2);\n\n    g_StdOut.Flush();\n  }\n  \n  if (enableHeaders && !techMode && (arcPaths.Size() > 1 || numVolumes > 1))\n  {\n    g_StdOut << endl;\n    fp.PrintTitleLines();\n    g_StdOut << endl;\n    fp.PrintSum(stat2total);\n    g_StdOut << endl;\n    PrintPropNameAndNumber(g_StdOut, \"Archives\", numArcs);\n    PrintPropNameAndNumber(g_StdOut, \"Volumes\", numVolumes);\n    PrintPropNameAndNumber(g_StdOut, \"Total archives size\", totalArcSizes);\n  }\n\n  if (numErrors == 1 && lastError != 0)\n    return lastError;\n  \n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/List.h",
    "content": "﻿// List.h\n\n#ifndef ZIP7_INC_LIST_H\n#define ZIP7_INC_LIST_H\n\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../Common/LoadCodecs.h\"\n\nstruct CListOptions\n{\n  bool ExcludeDirItems;\n  bool ExcludeFileItems;\n  bool DisablePercents;\n\n  CListOptions():\n    ExcludeDirItems(false),\n    ExcludeFileItems(false),\n    DisablePercents(false)\n    {}\n};\n\nHRESULT ListArchives(\n    const CListOptions &listOptions,\n    CCodecs *codecs,\n    const CObjectVector<COpenType> &types,\n    const CIntVector &excludedFormats,\n    bool stdInMode,\n    UStringVector &archivePaths, UStringVector &archivePathsFull,\n    bool processAltStreams, bool showAltStreams,\n    const NWildcard::CCensorNode &wildcardCensor,\n    bool enableHeaders, bool techMode,\n  #ifndef Z7_NO_CRYPTO\n    bool &passwordEnabled, UString &password,\n  #endif\n  #ifndef Z7_SFX\n    const CObjectVector<CProperty> *props,\n  #endif\n    UInt64 &errors,\n    UInt64 &numWarnings);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/MainAr.cpp",
    "content": "﻿// MainAr.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef _WIN32\n#include \"../../../../C/DllSecur.h\"\n#endif\n#include \"../../../../C/CpuArch.h\"\n\n#include \"../../../Common/MyException.h\"\n#include \"../../../Common/StdOutStream.h\"\n\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/NtCheck.h\"\n\n#include \"../Common/ArchiveCommandLine.h\"\n#include \"../Common/ExitCode.h\"\n\n#include \"ConsoleClose.h\"\n\n// **************** NanaZip Modification Start ****************\n#include <K7Base.h>\n// **************** NanaZip Modification End ****************\n\nusing namespace NWindows;\n\nextern\nCStdOutStream *g_StdStream;\nCStdOutStream *g_StdStream = NULL;\nextern\nCStdOutStream *g_ErrStream;\nCStdOutStream *g_ErrStream = NULL;\n\nextern int Main2(\n  #ifndef _WIN32\n  int numArgs, char *args[]\n  #endif\n);\n\nstatic const char * const kException_CmdLine_Error_Message = \"Command Line Error:\";\nstatic const char * const kExceptionErrorMessage = \"ERROR:\";\nstatic const char * const kUserBreakMessage  = \"Break signaled\";\nstatic const char * const kMemoryExceptionMessage = \"ERROR: Can't allocate required memory!\";\nstatic const char * const kUnknownExceptionMessage = \"Unknown Error\";\nstatic const char * const kInternalExceptionMessage = \"\\n\\nInternal Error #\";\n\nstatic void FlushStreams()\n{\n  if (g_StdStream)\n    g_StdStream->Flush();\n}\n\nstatic void PrintError(const char *message)\n{\n  FlushStreams();\n  if (g_ErrStream)\n    *g_ErrStream << \"\\n\\n\" << message << endl;\n}\n\n#if defined(_WIN32) && defined(_UNICODE) && !defined(_WIN64) && !defined(UNDER_CE)\n#define NT_CHECK_FAIL_ACTION *g_StdStream << \"Unsupported Windows version\"; return NExitCode::kFatalError;\n#endif\n\nstatic inline bool CheckIsa()\n{\n  // __try\n  {\n    // some compilers (e2k) support SSE/AVX, but cpuid() can be unavailable or return lower isa support\n#ifdef MY_CPU_X86_OR_AMD64\n    #if 0 && (defined(__AVX512F__) && defined(__AVX512VL__))\n      if (!CPU_IsSupported_AVX512F_AVX512VL())\n        return false;\n    #elif defined(__AVX2__)\n      if (!CPU_IsSupported_AVX2())\n        return false;\n    #elif defined(__AVX__)\n      if (!CPU_IsSupported_AVX())\n        return false;\n    #elif defined(__SSE2__) && !defined(MY_CPU_AMD64) || defined(_M_IX86_FP) && (_M_IX86_FP >= 2)\n      if (!CPU_IsSupported_SSE2())\n        return false;\n    #elif defined(__SSE__) && !defined(MY_CPU_AMD64) || defined(_M_IX86_FP) && (_M_IX86_FP >= 1)\n      if (!CPU_IsSupported_SSE() ||\n          !CPU_IsSupported_CMOV())\n        return false;\n    #endif\n#endif\n    /*\n    __asm\n    {\n      _emit 0fH\n      _emit 038H\n      _emit 0cbH\n      _emit (0c0H + 0 * 8 + 0)\n    }\n    */\n    return true;\n  }\n  /*\n  __except (EXCEPTION_EXECUTE_HANDLER)\n  {\n    return false;\n  }\n  */\n}\n\n// **************** NanaZip Modification Start ****************\nvoid NanaZipInitialize()\n{\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseInitialize())\n    {\n        ::FlushStreams();\n        *g_ErrStream\n            << \"K7BaseInitialize Failed\"\n            << ::endl;\n        ::ExitProcess(1);\n    }\n\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseDisableDynamicCodeGeneration())\n    {\n        ::FlushStreams();\n        *g_ErrStream\n            << \"K7BaseDisableDynamicCodeGeneration Failed\"\n            << ::endl;\n    }\n\n    if (MO_RESULT_SUCCESS_OK != ::K7BaseDisableChildProcessCreation())\n    {\n        ::FlushStreams();\n        *g_ErrStream\n            << \"K7BaseDisableChildProcessCreation Failed\"\n            << ::endl;\n    }\n}\n// **************** NanaZip Modification End ****************\n\nint Z7_CDECL main\n(\n  #ifndef _WIN32\n  int numArgs, char *args[]\n  #endif\n)\n{\n  g_ErrStream = &g_StdErr;\n  g_StdStream = &g_StdOut;\n\n  // #if (defined(_MSC_VER) && defined(_M_IX86))\n  if (!CheckIsa())\n  {\n    PrintError(\"ERROR: processor doesn't support required ISA extension\");\n    return NExitCode::kFatalError;\n  }\n  // #endif\n\n  NT_CHECK\n\n  // **************** NanaZip Modification Start ****************\n  ::NanaZipInitialize();\n  // **************** NanaZip Modification End ****************\n\n  NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;\n  int res = 0;\n\n  try\n  {\n    #ifdef _WIN32\n    My_SetDefaultDllDirectories();\n    #endif\n\n    res = Main2(\n    #ifndef _WIN32\n    numArgs, args\n    #endif\n    );\n  }\n  catch(const CNewException &)\n  {\n    PrintError(kMemoryExceptionMessage);\n    return (NExitCode::kMemoryError);\n  }\n/*\n  catch(const NConsoleClose::CCtrlBreakException &)\n  {\n    PrintError(kUserBreakMessage);\n    return (NExitCode::kUserBreak);\n  }\n*/\n  catch(const CMessagePathException &e)\n  {\n    PrintError(kException_CmdLine_Error_Message);\n    if (g_ErrStream)\n      *g_ErrStream << e << endl;\n    return (NExitCode::kUserError);\n  }\n  catch(const CSystemException &systemError)\n  {\n    if (systemError.ErrorCode == E_OUTOFMEMORY)\n    {\n      PrintError(kMemoryExceptionMessage);\n      return (NExitCode::kMemoryError);\n    }\n    if (systemError.ErrorCode == E_ABORT)\n    {\n      PrintError(kUserBreakMessage);\n      return (NExitCode::kUserBreak);\n    }\n    if (g_ErrStream)\n    {\n      PrintError(\"System ERROR:\");\n      *g_ErrStream << NError::MyFormatMessage(systemError.ErrorCode) << endl;\n    }\n    return (NExitCode::kFatalError);\n  }\n  catch(NExitCode::EEnum exitCode)\n  {\n    FlushStreams();\n    if (g_ErrStream)\n      *g_ErrStream << kInternalExceptionMessage << exitCode << endl;\n    return (exitCode);\n  }\n  catch(const UString &s)\n  {\n    if (g_ErrStream)\n    {\n      PrintError(kExceptionErrorMessage);\n      *g_ErrStream << s << endl;\n    }\n    return (NExitCode::kFatalError);\n  }\n  catch(const AString &s)\n  {\n    if (g_ErrStream)\n    {\n      PrintError(kExceptionErrorMessage);\n      *g_ErrStream << s << endl;\n    }\n    return (NExitCode::kFatalError);\n  }\n  catch(const char *s)\n  {\n    if (g_ErrStream)\n    {\n      PrintError(kExceptionErrorMessage);\n      *g_ErrStream << s << endl;\n    }\n    return (NExitCode::kFatalError);\n  }\n  catch(const wchar_t *s)\n  {\n    if (g_ErrStream)\n    {\n      PrintError(kExceptionErrorMessage);\n      *g_ErrStream << s << endl;\n    }\n    return (NExitCode::kFatalError);\n  }\n  catch(int t)\n  {\n    if (g_ErrStream)\n    {\n      FlushStreams();\n      *g_ErrStream << kInternalExceptionMessage << t << endl;\n      return (NExitCode::kFatalError);\n    }\n  }\n  catch(...)\n  {\n    PrintError(kUnknownExceptionMessage);\n    return (NExitCode::kFatalError);\n  }\n\n  return res;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/OpenCallbackConsole.cpp",
    "content": "﻿// OpenCallbackConsole.cpp\n\n#include \"StdAfx.h\"\n\n#include \"OpenCallbackConsole.h\"\n\n#include \"ConsoleClose.h\"\n#include \"UserInputUtils.h\"\n\nstatic HRESULT CheckBreak2()\n{\n  return NConsoleClose::TestBreakSignal() ? E_ABORT : S_OK;\n}\n\nHRESULT COpenCallbackConsole::Open_CheckBreak()\n{\n  return CheckBreak2();\n}\n\nHRESULT COpenCallbackConsole::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)\n{\n  if (!MultiArcMode && NeedPercents())\n  {\n    if (files)\n    {\n      _totalFilesDefined = true;\n      // _totalFiles = *files;\n      _percent.Total = *files;\n    }\n    else\n      _totalFilesDefined = false;\n\n    if (bytes)\n    {\n      // _totalBytesDefined = true;\n      _totalBytes = *bytes;\n      if (!files)\n        _percent.Total = *bytes;\n    }\n    else\n    {\n      // _totalBytesDefined = false;\n      if (!files)\n        _percent.Total = _totalBytes;\n    }\n  }\n\n  return CheckBreak2();\n}\n\nHRESULT COpenCallbackConsole::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)\n{\n  if (!MultiArcMode && NeedPercents())\n  {\n    if (files)\n    {\n      _percent.Files = *files;\n      if (_totalFilesDefined)\n        _percent.Completed = *files;\n    }\n\n    if (bytes)\n    {\n      if (!_totalFilesDefined)\n        _percent.Completed = *bytes;\n    }\n    _percent.Print();\n  }\n\n  return CheckBreak2();\n}\n\nHRESULT COpenCallbackConsole::Open_Finished()\n{\n  ClosePercents();\n  return S_OK;\n}\n\n\n#ifndef Z7_NO_CRYPTO\n\nHRESULT COpenCallbackConsole::Open_CryptoGetTextPassword(BSTR *password)\n{\n  *password = NULL;\n  RINOK(CheckBreak2())\n\n  if (!PasswordIsDefined)\n  {\n    ClosePercents();\n    RINOK(GetPassword_HRESULT(_so, Password))\n    PasswordIsDefined = true;\n  }\n  return StringToBstr(Password, password);\n}\n\n/*\nHRESULT COpenCallbackConsole::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)\n{\n  passwordIsDefined = PasswordIsDefined;\n  password = Password;\n  return S_OK;\n}\n\nbool COpenCallbackConsole::Open_WasPasswordAsked()\n{\n  return PasswordWasAsked;\n}\n\nvoid COpenCallbackConsole::Open_Clear_PasswordWasAsked_Flag ()\n{\n  PasswordWasAsked = false;\n}\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/OpenCallbackConsole.h",
    "content": "﻿// OpenCallbackConsole.h\n\n#ifndef ZIP7_INC_OPEN_CALLBACK_CONSOLE_H\n#define ZIP7_INC_OPEN_CALLBACK_CONSOLE_H\n\n#include \"../../../Common/StdOutStream.h\"\n\n#include \"../Common/ArchiveOpenCallback.h\"\n\n#include \"PercentPrinter.h\"\n\nclass COpenCallbackConsole: public IOpenCallbackUI\n{\nprotected:\n  CPercentPrinter _percent;\n\n  CStdOutStream *_so;\n  CStdOutStream *_se;\n\n  // UInt64 _totalFiles;\n  UInt64 _totalBytes;\n  bool _totalFilesDefined;\n  // bool _totalBytesDefined;\n\n  bool NeedPercents() const { return _percent._so && !_percent.DisablePrint; }\n\npublic:\n\n  bool MultiArcMode;\n\n  void ClosePercents()\n  {\n    if (NeedPercents())\n      _percent.ClosePrint(true);\n  }\n\n  COpenCallbackConsole():\n      _totalBytes(0),\n      _totalFilesDefined(false),\n      // _totalBytesDefined(false),\n      MultiArcMode(false)\n      \n      #ifndef Z7_NO_CRYPTO\n      , PasswordIsDefined(false)\n      // , PasswordWasAsked(false)\n      #endif\n      \n      {}\n\n  virtual ~COpenCallbackConsole() {}\n  \n  void Init(\n      CStdOutStream *outStream,\n      CStdOutStream *errorStream,\n      CStdOutStream *percentStream,\n      bool disablePercents)\n  {\n    _so = outStream;\n    _se = errorStream;\n    _percent._so = percentStream;\n    _percent.DisablePrint = disablePercents;\n  }\n\n  Z7_IFACE_IMP(IOpenCallbackUI)\n  \n  #ifndef Z7_NO_CRYPTO\n  bool PasswordIsDefined;\n  // bool PasswordWasAsked;\n  UString Password;\n  #endif\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/PercentPrinter.cpp",
    "content": "﻿// PercentPrinter.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n\n#include \"PercentPrinter.h\"\n\nstatic const unsigned kPercentsSize = 4;\n\nCPercentPrinter::~CPercentPrinter()\n{\n  ClosePrint(false);\n}\n\nvoid CPercentPrinterState::ClearCurState()\n{\n  Completed = 0;\n  Total = ((UInt64)(Int64)-1);\n  Files = 0;\n  Command.Empty();\n  FileName.Empty();\n}\n\nvoid CPercentPrinter::ClosePrint(bool needFlush)\n{\n  unsigned num = _printedString.Len();\n  if (num != 0)\n  {\n\n  unsigned i;\n    \n  /* '\\r' in old MAC OS means \"new line\".\n     So we can't use '\\r' in some systems */\n    \n  #ifdef _WIN32\n    char *start = _temp.GetBuf(num  + 2);\n    char *p = start;\n    *p++ = '\\r';\n    for (i = 0; i < num; i++) *p++ = ' ';\n    *p++ = '\\r';\n  #else\n    char *start = _temp.GetBuf(num * 3);\n    char *p = start;\n    for (i = 0; i < num; i++) *p++ = '\\b';\n    for (i = 0; i < num; i++) *p++ = ' ';\n    for (i = 0; i < num; i++) *p++ = '\\b';\n  #endif\n    \n  *p = 0;\n  _temp.ReleaseBuf_SetLen((unsigned)(p - start));\n  *_so << _temp;\n  }\n  if (needFlush)\n    _so->Flush();\n  _printedString.Empty();\n}\n\nvoid CPercentPrinter::GetPercents()\n{\n  char s[32];\n  unsigned size;\n  {\n    char c = '%';\n    UInt64 val = 0;\n    if (Total == (UInt64)(Int64)-1 ||\n        (Total == 0 && Completed != 0))\n    {\n      val = Completed >> 20;\n      c = 'M';\n    }\n    else if (Total != 0)\n      val = Completed * 100 / Total;\n    ConvertUInt64ToString(val, s);\n    size = (unsigned)strlen(s);\n    s[size++] = c;\n    s[size] = 0;\n  }\n\n  while (size < kPercentsSize)\n  {\n    _s.Add_Space();\n    size++;\n  }\n\n  _s += s;\n}\n\nvoid CPercentPrinter::Print()\n{\n  if (DisablePrint)\n    return;\n  DWORD tick = 0;\n  if (_tickStep != 0)\n    tick = GetTickCount();\n\n  bool onlyPercentsChanged = false;\n\n  if (!_printedString.IsEmpty())\n  {\n    if (_tickStep != 0 && (UInt32)(tick - _prevTick) < _tickStep)\n      return;\n    \n    CPercentPrinterState &st = *this;\n    if (_printedState.Command == st.Command\n        && _printedState.FileName == st.FileName\n        && _printedState.Files == st.Files)\n    {\n      if (_printedState.Total == st.Total\n          && _printedState.Completed == st.Completed)\n        return;\n      onlyPercentsChanged = true;\n    }\n  }\n\n  _s.Empty();\n\n  GetPercents();\n  \n  if (onlyPercentsChanged && _s == _printedPercents)\n    return;\n\n  _printedPercents = _s;\n\n  if (Files != 0)\n  {\n    char s[32];\n    ConvertUInt64ToString(Files, s);\n    // unsigned size = (unsigned)strlen(s);\n    // for (; size < 3; size++) _s.Add_Space();\n    _s.Add_Space();\n    _s += s;\n    // _s += \"f\";\n  }\n\n\n  if (!Command.IsEmpty())\n  {\n    _s.Add_Space();\n    _s += Command;\n  }\n\n  if (!FileName.IsEmpty() && _s.Len() < MaxLen)\n  {\n    _s.Add_Space();\n\n    _tempU = FileName;\n    _so->Normalize_UString_Path(_tempU);\n    _so->Convert_UString_to_AString(_tempU, _temp);\n    if (_s.Len() + _temp.Len() > MaxLen)\n    {\n      unsigned len = FileName.Len();\n      for (; len != 0;)\n      {\n        unsigned delta = len / 8;\n        if (delta == 0)\n          delta = 1;\n        len -= delta;\n        _tempU = FileName;\n        _tempU.Delete(len / 2, _tempU.Len() - len);\n        _tempU.Insert(len / 2, L\" . \");\n        _so->Normalize_UString_Path(_tempU);\n        _so->Convert_UString_to_AString(_tempU, _temp);\n        if (_s.Len() + _temp.Len() <= MaxLen)\n          break;\n      }\n      if (len == 0)\n        _temp.Empty();\n    }\n    _s += _temp;\n  }\n  \n  if (_printedString != _s)\n  {\n    ClosePrint(false);\n    *_so << _s;\n    if (NeedFlush)\n      _so->Flush();\n    _printedString = _s;\n  }\n\n  _printedState = *this;\n\n  if (_tickStep != 0)\n    _prevTick = tick;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/PercentPrinter.h",
    "content": "﻿// PercentPrinter.h\n\n#ifndef ZIP7_INC_PERCENT_PRINTER_H\n#define ZIP7_INC_PERCENT_PRINTER_H\n\n#include \"../../../Common/StdOutStream.h\"\n\nstruct CPercentPrinterState\n{\n  UInt64 Completed;\n  UInt64 Total;\n  \n  UInt64 Files;\n\n  AString Command;\n  UString FileName;\n\n  void ClearCurState();\n\n  CPercentPrinterState():\n      Completed(0),\n      Total((UInt64)(Int64)-1),\n      Files(0)\n    {}\n};\n\nclass CPercentPrinter: public CPercentPrinterState\n{\npublic:\n  CStdOutStream *_so;\n  bool DisablePrint;\n  bool NeedFlush;\n  unsigned MaxLen;\n  \nprivate:\n  UInt32 _tickStep;\n  DWORD _prevTick;\n\n  AString _s;\n\n  AString _printedString;\n  AString _temp;\n  UString _tempU;\n\n  CPercentPrinterState _printedState;\n  AString _printedPercents;\n\n  void GetPercents();\n\npublic:\n  \n  CPercentPrinter(UInt32 tickStep = 200):\n      DisablePrint(false),\n      NeedFlush(true),\n      MaxLen(80 - 1),\n      _tickStep(tickStep),\n      _prevTick(0)\n  {}\n\n  ~CPercentPrinter();\n\n  void ClosePrint(bool needFlush);\n  void Print();\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/UserInputUtils.cpp",
    "content": "﻿// UserInputUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/StdInStream.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"UserInputUtils.h\"\n\nstatic const char kYes = 'y';\nstatic const char kNo = 'n';\nstatic const char kYesAll = 'a';\nstatic const char kNoAll = 's';\nstatic const char kAutoRenameAll = 'u';\nstatic const char kQuit = 'q';\n\nstatic const char * const kFirstQuestionMessage = \"? \";\nstatic const char * const kHelpQuestionMessage =\n  \"(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? \";\n\n// return true if pressed Quite;\n\nNUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)\n{\n  if (outStream)\n    *outStream << kFirstQuestionMessage;\n  for (;;)\n  {\n    if (outStream)\n    {\n      *outStream << kHelpQuestionMessage;\n      outStream->Flush();\n    }\n    AString scannedString;\n    if (!g_StdIn.ScanAStringUntilNewLine(scannedString))\n      return NUserAnswerMode::kError;\n    if (g_StdIn.Error())\n      return NUserAnswerMode::kError;\n    scannedString.Trim();\n    if (scannedString.IsEmpty() && g_StdIn.Eof())\n      return NUserAnswerMode::kEof;\n\n    if (scannedString.Len() == 1)\n      switch (::MyCharLower_Ascii(scannedString[0]))\n      {\n        case kYes:    return NUserAnswerMode::kYes;\n        case kNo:     return NUserAnswerMode::kNo;\n        case kYesAll: return NUserAnswerMode::kYesAll;\n        case kNoAll:  return NUserAnswerMode::kNoAll;\n        case kAutoRenameAll: return NUserAnswerMode::kAutoRenameAll;\n        case kQuit:   return NUserAnswerMode::kQuit;\n        default: break;\n      }\n  }\n}\n\n#ifdef _WIN32\n#ifndef UNDER_CE\n#define MY_DISABLE_ECHO\n#endif\n#endif\n\nstatic bool GetPassword(CStdOutStream *outStream, UString &psw)\n{\n  if (outStream)\n  {\n    *outStream << \"\\nEnter password\"\n      #ifdef MY_DISABLE_ECHO\n      \" (will not be echoed)\"\n      #endif\n      \":\";\n    outStream->Flush();\n  }\n\n  #ifdef MY_DISABLE_ECHO\n  \n  const HANDLE console = GetStdHandle(STD_INPUT_HANDLE);\n\n  /*\n  GetStdHandle() returns\n    INVALID_HANDLE_VALUE: If the function fails.\n    NULL : If an application does not have associated standard handles,\n           such as a service running on an interactive desktop,\n           and has not redirected them. */\n  bool wasChanged = false;\n  DWORD mode = 0;\n  if (console != INVALID_HANDLE_VALUE && console != NULL)\n    if (GetConsoleMode(console, &mode))\n      wasChanged = (SetConsoleMode(console, mode & ~(DWORD)ENABLE_ECHO_INPUT) != 0);\n  const bool res = g_StdIn.ScanUStringUntilNewLine(psw);\n  if (wasChanged)\n    SetConsoleMode(console, mode);\n  \n  #else\n  \n  const bool res = g_StdIn.ScanUStringUntilNewLine(psw);\n  \n  #endif\n\n  if (outStream)\n  {\n    *outStream << endl;\n    outStream->Flush();\n  }\n\n  return res;\n}\n\nHRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw)\n{\n  if (!GetPassword(outStream, psw))\n    return E_INVALIDARG;\n  if (g_StdIn.Error())\n    return E_FAIL;\n  if (g_StdIn.Eof() && psw.IsEmpty())\n    return E_ABORT;\n  return S_OK;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Console/UserInputUtils.h",
    "content": "﻿// UserInputUtils.h\n\n#ifndef ZIP7_INC_USER_INPUT_UTILS_H\n#define ZIP7_INC_USER_INPUT_UTILS_H\n\n#include \"../../../Common/StdOutStream.h\"\n\nnamespace NUserAnswerMode {\n\nenum EEnum\n{\n  kYes,\n  kNo,\n  kYesAll,\n  kNoAll,\n  kAutoRenameAll,\n  kQuit,\n  kEof,\n  kError\n};\n}\n\nNUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);\n// bool GetPassword(CStdOutStream *outStream, UString &psw);\nHRESULT GetPassword_HRESULT(CStdOutStream *outStream, UString &psw);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Explorer/MyMessages.cpp",
    "content": "﻿// MyMessages.cpp\n\n#include \"StdAfx.h\"\n\n#include \"MyMessages.h\"\n\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/ResourceString.h\"\n\n#include \"../FileManager/LangUtils.h\"\n\nusing namespace NWindows;\n\nextern bool g_DisableUserQuestions;\n\nvoid ShowErrorMessage(HWND window, LPCWSTR message)\n{\n  if (!g_DisableUserQuestions)\n    // **************** NanaZip Modification Start ****************\n    //::MessageBoxW(window, message, L\"7-Zip\", MB_OK | MB_ICONSTOP);\n    ::MessageBoxW(window, message, L\"NanaZip\", MB_OK | MB_ICONSTOP);\n    // **************** NanaZip Modification End ****************\n}\n\nvoid ShowErrorMessageHwndRes(HWND window, UInt32 resID)\n{\n  UString s = LangString(resID);\n  if (s.IsEmpty())\n    s.Add_UInt32(resID);\n  ShowErrorMessage(window, s);\n}\n\nvoid ShowErrorMessageRes(UInt32 resID)\n{\n  ShowErrorMessageHwndRes(NULL, resID);\n}\n\nstatic void ShowErrorMessageDWORD(HWND window, DWORD errorCode)\n{\n  ShowErrorMessage(window, NError::MyFormatMessage(errorCode));\n}\n\nvoid ShowLastErrorMessage(HWND window)\n{\n  ShowErrorMessageDWORD(window, ::GetLastError());\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Explorer/MyMessages.h",
    "content": "﻿// MyMessages.h\n\n#ifndef ZIP7_INC_MY_MESSAGES_H\n#define ZIP7_INC_MY_MESSAGES_H\n\n#include \"../../../Common/MyString.h\"\n\nvoid ShowErrorMessage(HWND window, LPCWSTR message);\ninline void ShowErrorMessage(LPCWSTR message) { ShowErrorMessage(NULL, message); }\n\nvoid ShowErrorMessageHwndRes(HWND window, UInt32 langID);\nvoid ShowErrorMessageRes(UInt32 langID);\n\nvoid ShowLastErrorMessage(HWND window = NULL);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/Explorer/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#if _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../FileManager/StdAfx.h\"\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/BrowseDialog.cpp",
    "content": "﻿// BrowseDialog.cpp\n \n#include \"StdAfx.h\"\n\n#include \"../../../Common/MyWindows.h\"\n\n#include \"../../../Common/IntToString.h\"\n\n#ifndef UNDER_CE\n#include \"../../../Windows/CommonDialog.h\"\n#include \"../../../Windows/Shell.h\"\n#endif\n\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/FileFind.h\"\n\n#ifdef UNDER_CE\n#include <commdlg.h>\n#endif\n\n#include \"BrowseDialog.h\"\n\n#define USE_MY_BROWSE_DIALOG\n\n#ifdef USE_MY_BROWSE_DIALOG\n\n#include \"../../../Common/Defs.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n\n#include \"../../../Windows/Control/ComboBox.h\"\n#include \"../../../Windows/Control/Dialog.h\"\n#include \"../../../Windows/Control/Edit.h\"\n#include \"../../../Windows/Control/ListView.h\"\n\n#include \"BrowseDialogRes.h\"\n#include \"PropertyNameRes.h\"\n#include \"SysIconUtils.h\"\n\n#ifndef Z7_SFX\n#include \"RegistryUtils.h\"\n#endif\n\n#endif // USE_MY_BROWSE_DIALOG\n\n#include \"ComboDialog.h\"\n#include \"LangUtils.h\"\n\n#include \"resource.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NName;\nusing namespace NFind;\n\nstatic void MessageBox_Error_Global(HWND wnd, const wchar_t *message)\n{\n  // **************** NanaZip Modification Start ****************\n  //::MessageBoxW(wnd, message, L\"7-Zip\", MB_ICONERROR);\n  ::MessageBoxW(wnd, message, L\"NanaZip\", MB_ICONERROR);\n  // **************** NanaZip Modification End ****************\n}\n\n#ifdef USE_MY_BROWSE_DIALOG\n\n#if 0\nextern HINSTANCE g_hInstance;\n#endif\nextern bool g_LVN_ITEMACTIVATE_Support;\n\nstatic const int kParentIndex = -1;\nstatic const UINT k_Message_RefreshPathEdit = WM_APP + 1;\n\nextern UString HResultToMessage(HRESULT errorCode);\n\nstatic void MessageBox_HResError(HWND wnd, HRESULT errorCode, const wchar_t *name)\n{\n  UString s = HResultToMessage(errorCode);\n  if (name)\n  {\n    s.Add_LF();\n    s += name;\n  }\n  MessageBox_Error_Global(wnd, s);\n}\n\nclass CBrowseDialog: public NControl::CModalDialog\n{\n  NControl::CListView _list;\n  NControl::CEdit _pathEdit;\n  NControl::CComboBox _filterCombo;\n\n  CObjectVector<CFileInfo> _files;\n\n  CExtToIconMap _extToIconMap;\n  int _sortIndex;\n  bool _ascending;\n #ifndef Z7_SFX\n  bool _showDots;\n #endif\n  UString _topDirPrefix; // we don't open parent of that folder\n  UString DirPrefix;\n\n  virtual bool OnInit() Z7_override;\n  virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override;\n  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override;\n  virtual bool OnNotify(UINT controlID, LPNMHDR header) Z7_override;\n  virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam) Z7_override;\n  virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;\n  virtual void OnOK() Z7_override;\n\n  bool OnKeyDown(LPNMLVKEYDOWN keyDownInfo);\n\n  void Post_RefreshPathEdit() { PostMsg(k_Message_RefreshPathEdit); }\n\n  bool GetParentPath(const UString &path, UString &parentPrefix, UString &name);\n  // Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter\n  HRESULT Reload(const UString &pathPrefix, const UString &selectedName);\n  HRESULT Reload();\n  \n  void OpenParentFolder();\n  void SetPathEditText();\n  void OnCreateDir();\n  void OnItemEnter();\n  void FinishOnOK();\n\n  int GetRealItemIndex(int indexInListView) const\n  {\n    LPARAM param;\n    if (!_list.GetItemParam((unsigned)indexInListView, param))\n      return (int)-1;\n    return (int)param;\n  }\n\npublic:\n\n  bool SaveMode;\n  bool FolderMode;\n  int FilterIndex;  // [in / out]\n  CObjectVector<CBrowseFilterInfo> Filters;\n\n  UString FilePath;   // [in / out]\n  UString Title;\n\n  CBrowseDialog():\n   #ifndef Z7_SFX\n      _showDots(false),\n   #endif\n      SaveMode(false)\n      , FolderMode(false)\n      , FilterIndex(-1)\n    {}\n  INT_PTR Create(HWND parent = NULL) { return CModalDialog::Create(IDD_BROWSE, parent); }\n  int CompareItems(LPARAM lParam1, LPARAM lParam2) const;\n};\n\n\nbool CBrowseDialog::OnInit()\n{\n  #ifdef Z7_LANG\n  LangSetDlgItems(*this, NULL, 0);\n  #endif\n  if (!Title.IsEmpty())\n    SetText(Title);\n  _list.Attach(GetItem(IDL_BROWSE));\n  _filterCombo.Attach(GetItem(IDC_BROWSE_FILTER));\n  _pathEdit.Attach(GetItem(IDE_BROWSE_PATH));\n\n  #ifndef UNDER_CE\n  _list.SetUnicodeFormat();\n  #endif\n\n  #ifndef Z7_SFX\n  CFmSettings st;\n  st.Load();\n  if (st.SingleClick)\n    _list.SetExtendedListViewStyle(LVS_EX_ONECLICKACTIVATE | LVS_EX_TRACKSELECT);\n  _showDots = st.ShowDots;\n  #endif\n\n  {\n    /*\n    Filters.Clear(); // for debug\n    if (Filters.IsEmpty() && !FolderMode)\n    {\n      CBrowseFilterInfo &f = Filters.AddNew();\n      const UString mask(\"*.*\");\n      f.Masks.Add(mask);\n      // f.Description = \"(\";\n      f.Description += mask;\n      // f.Description += \")\";\n    }\n    */\n\n    FOR_VECTOR (i, Filters)\n    {\n      _filterCombo.AddString(Filters[i].Description);\n    }\n\n    if (Filters.Size() <= 1)\n    {\n      if (FolderMode)\n        HideItem(IDC_BROWSE_FILTER);\n      else\n        EnableItem(IDC_BROWSE_FILTER, false);\n    }\n    \n    if (/* FilterIndex >= 0 && */ (unsigned)FilterIndex < Filters.Size())\n      _filterCombo.SetCurSel(FilterIndex);\n  }\n\n  _list.SetImageList(Shell_Get_SysImageList_smallIcons(true), LVSIL_SMALL);\n  _list.SetImageList(Shell_Get_SysImageList_smallIcons(false), LVSIL_NORMAL);\n\n  _list.InsertColumn(0, LangString(IDS_PROP_NAME), 100);\n  _list.InsertColumn(1, LangString(IDS_PROP_MTIME), 100);\n  {\n    LV_COLUMNW column;\n    column.iSubItem = 2;\n    column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;\n    column.fmt = LVCFMT_RIGHT;\n    column.cx = 100;\n    const UString s = LangString(IDS_PROP_SIZE);\n    column.pszText = s.Ptr_non_const();\n    _list.InsertColumn(2, &column);\n  }\n\n  _list.InsertItem(0, L\"12345678901234567\"\n      #ifndef UNDER_CE\n      L\"1234567890\"\n      #endif\n      );\n  _list.SetSubItem(0, 1, L\"2009-09-09\"\n      #ifndef UNDER_CE\n      L\" 09:09\"\n      #endif\n      );\n  _list.SetSubItem(0, 2, L\"9999 MB\");\n  for (int i = 0; i < 3; i++)\n    _list.SetColumnWidthAuto(i);\n  _list.DeleteAllItems();\n\n  _ascending = true;\n  _sortIndex = 0;\n\n  NormalizeSize();\n\n  _topDirPrefix.Empty();\n  {\n    unsigned rootSize = GetRootPrefixSize(FilePath);\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    // We can go up from root folder to drives list\n    if (IsDrivePath(FilePath))\n      rootSize = 0;\n    else if (IsSuperPath(FilePath))\n    {\n      if (IsDrivePath(FilePath.Ptr(kSuperPathPrefixSize)))\n        rootSize = kSuperPathPrefixSize;\n    }\n    #endif\n    _topDirPrefix.SetFrom(FilePath, rootSize);\n  }\n\n  UString name;\n  if (!GetParentPath(FilePath, DirPrefix, name))\n    DirPrefix = _topDirPrefix;\n\n  for (;;)\n  {\n    UString baseFolder = DirPrefix;\n    if (Reload(baseFolder, name) == S_OK)\n      break;\n    name.Empty();\n    if (DirPrefix.IsEmpty())\n      break;\n    UString parent, name2;\n    GetParentPath(DirPrefix, parent, name2);\n    DirPrefix = parent;\n  }\n\n  if (name.IsEmpty())\n    name = FilePath;\n  if (FolderMode)\n    NormalizeDirPathPrefix(name);\n  _pathEdit.SetText(name);\n\n  #ifndef UNDER_CE\n  /* If we clear UISF_HIDEFOCUS, the focus rectangle in ListView will be visible,\n     even if we use mouse for pressing the button to open this dialog. */\n  PostMsg(Z7_WIN_WM_UPDATEUISTATE, MAKEWPARAM(Z7_WIN_UIS_CLEAR, Z7_WIN_UISF_HIDEFOCUS));\n  #endif\n\n#if 0\n  {\n    const HWND hwndTool = GetItem(IDB_BROWSE_CREATE_DIR);\n    if (hwndTool)\n    {\n      // Create the tooltip:\n      const HWND hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,\n          WS_POPUP | TTS_ALWAYSTIP\n          // | TTS_BALLOON\n          , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,\n          *this, NULL, g_hInstance, NULL);\n      if (hwndTip)\n      {\n        // Associate the tooltip with the tool:\n        TOOLINFOW toolInfo;\n        memset(&toolInfo, 0, sizeof(toolInfo));\n        toolInfo.cbSize = sizeof(toolInfo);\n        toolInfo.hwnd = *this;\n        toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;\n        toolInfo.uId = (UINT_PTR)hwndTool;\n        UString s;\n#ifdef Z7_LANG\n        LangString_OnlyFromLangFile(IDM_CREATE_FOLDER, s);\n        s.RemoveChar(L'&');\n        if (s.IsEmpty())\n#endif\n          s = \"Create Folder\";\n        toolInfo.lpszText = s.Ptr_non_const();\n        SendMessage(hwndTip, TTM_ADDTOOLW, 0, (LPARAM)&toolInfo);\n      }\n    }\n  }\n#endif\n  return CModalDialog::OnInit();\n}\n\nbool CBrowseDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\n{\n  int mx, my;\n  {\n    RECT r;\n    GetClientRectOfItem(IDB_BROWSE_PARENT, r);\n    mx = r.left;\n    my = r.top;\n  }\n  InvalidateRect(NULL);\n\n  int xLim = xSize - mx;\n  {\n    RECT r;\n    GetClientRectOfItem(IDT_BROWSE_FOLDER, r);\n    MoveItem(IDT_BROWSE_FOLDER, r.left, r.top, xLim - r.left, RECT_SIZE_Y(r));\n  }\n\n  int bx1, bx2, by;\n  GetItemSizes(IDCANCEL, bx1, by);\n  GetItemSizes(IDOK, bx2, by);\n  int y = ySize - my - by;\n  int x = xLim - bx1;\n  MoveItem(IDCANCEL, x, y, bx1, by);\n  MoveItem(IDOK, x - mx - bx2, y, bx2, by);\n\n  // Y_Size of ComboBox is tricky. So we use Y_Size of _pathEdit instead\n\n  int yPathSize;\n  {\n    RECT r;\n    GetClientRectOfItem(IDE_BROWSE_PATH, r);\n    yPathSize = RECT_SIZE_Y(r);\n    _pathEdit.Move(r.left, y - my - yPathSize - my - yPathSize, xLim - r.left, yPathSize);\n  }\n\n  {\n    RECT r;\n    GetClientRectOfItem(IDC_BROWSE_FILTER, r);\n    _filterCombo.Move(r.left, y - my - yPathSize, xLim - r.left, RECT_SIZE_Y(r));\n  }\n\n  {\n    RECT r;\n    GetClientRectOfItem(IDL_BROWSE, r);\n    _list.Move(r.left, r.top, xLim - r.left, y - my - yPathSize - my - yPathSize - my - r.top);\n  }\n\n  return false;\n}\n\nbool CBrowseDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\n{\n  if (message == k_Message_RefreshPathEdit)\n  {\n    SetPathEditText();\n    return true;\n  }\n  return CModalDialog::OnMessage(message, wParam, lParam);\n}\n\n\nbool CBrowseDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam)\n{\n  if (code == CBN_SELCHANGE)\n  {\n    switch (itemID)\n    {\n      case IDC_BROWSE_FILTER:\n      {\n        Reload();\n        return true;\n      }\n    }\n  }\n  return CModalDialog::OnCommand(code, itemID, lParam);\n}\n\n\nbool CBrowseDialog::OnNotify(UINT /* controlID */, LPNMHDR header)\n{\n  if (header->hwndFrom != _list)\n    return false;\n  switch (header->code)\n  {\n    case LVN_ITEMACTIVATE:\n      if (g_LVN_ITEMACTIVATE_Support)\n        OnItemEnter();\n      break;\n    case NM_DBLCLK:\n    case NM_RETURN: // probably it's unused\n      if (!g_LVN_ITEMACTIVATE_Support)\n        OnItemEnter();\n      break;\n    case LVN_COLUMNCLICK:\n    {\n      const int index = LPNMLISTVIEW(header)->iSubItem;\n      if (index == _sortIndex)\n        _ascending = !_ascending;\n      else\n      {\n        _ascending = (index == 0);\n        _sortIndex = index;\n      }\n      Reload();\n      return false;\n    }\n    case LVN_KEYDOWN:\n    {\n      bool boolResult = OnKeyDown(LPNMLVKEYDOWN(header));\n      Post_RefreshPathEdit();\n      return boolResult;\n    }\n    case NM_RCLICK:\n    case NM_CLICK:\n    case LVN_BEGINDRAG:\n      Post_RefreshPathEdit();\n      break;\n  }\n  return false;\n}\n\nbool CBrowseDialog::OnKeyDown(LPNMLVKEYDOWN keyDownInfo)\n{\n  const bool ctrl = IsKeyDown(VK_CONTROL);\n\n  switch (keyDownInfo->wVKey)\n  {\n    case VK_BACK:\n      OpenParentFolder();\n      return true;\n    case 'R':\n      if (ctrl)\n      {\n        Reload();\n        return true;\n      }\n      return false;\n    case VK_F7:\n      OnCreateDir();\n      return true;\n  }\n  return false;\n}\n\n\nbool CBrowseDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)\n{\n  switch (buttonID)\n  {\n    case IDB_BROWSE_PARENT: OpenParentFolder(); break;\n    case IDB_BROWSE_CREATE_DIR: OnCreateDir(); break;\n    default: return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\n  }\n  _list.SetFocus();\n  return true;\n}\n\nvoid CBrowseDialog::OnOK()\n{\n  /* When we press \"Enter\" in listview, Windows sends message to first Button.\n     We check that message was from ListView; */\n  if (GetFocus() == _list)\n  {\n    OnItemEnter();\n    return;\n  }\n  FinishOnOK();\n}\n\n\nbool CBrowseDialog::GetParentPath(const UString &path, UString &parentPrefix, UString &name)\n{\n  parentPrefix.Empty();\n  name.Empty();\n  if (path.IsEmpty())\n    return false;\n  if (_topDirPrefix == path)\n    return false;\n  UString s = path;\n  if (IS_PATH_SEPAR(s.Back()))\n    s.DeleteBack();\n  if (s.IsEmpty())\n    return false;\n  if (IS_PATH_SEPAR(s.Back()))\n    return false;\n  const unsigned pos1 = (unsigned)(s.ReverseFind_PathSepar() + 1);\n  parentPrefix.SetFrom(s, pos1);\n  name = s.Ptr(pos1);\n  return true;\n}\n\nint CBrowseDialog::CompareItems(LPARAM lParam1, LPARAM lParam2) const\n{\n  if (lParam1 == lParam2)      return 0;\n  if (lParam1 == kParentIndex) return -1;\n  if (lParam2 == kParentIndex) return 1;\n\n  const CFileInfo &f1 = _files[(int)lParam1];\n  const CFileInfo &f2 = _files[(int)lParam2];\n\n  const bool isDir2 = f2.IsDir();\n  if (f1.IsDir())\n  {\n    if (!isDir2) return -1;\n  }\n  else if (isDir2) return 1;\n  \n  int res = 0;\n  switch (_sortIndex)\n  {\n    case 0: res = CompareFileNames(fs2us(f1.Name), fs2us(f2.Name)); break;\n    case 1: res = CompareFileTime(&f1.MTime, &f2.MTime); break;\n    case 2: res = MyCompare(f1.Size, f2.Size); break;\n  }\n  return _ascending ? res: -res;\n}\n\nstatic int CALLBACK CompareItems2(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)\n{\n  return ((CBrowseDialog *)lpData)->CompareItems(lParam1, lParam2);\n}\n\nwchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s);\nwchar_t *Browse_ConvertSizeToString(UInt64 v, wchar_t *s)\n{\n  char c = 0;\n       if (v >= ((UInt64)10000 << 20)) { v >>= 30; c = 'G'; }\n  else if (v >= ((UInt64)10000 << 10)) { v >>= 20; c = 'M'; }\n  else if (v >= ((UInt64)10000 <<  0)) { v >>= 10; c = 'K'; }\n  s = ConvertUInt64ToString(v, s);\n  if (c != 0)\n  {\n    *s++ = ' ';\n    *s++ = (wchar_t)c;\n    *s++ = 'B';\n    *s = 0;\n  }\n  return s;\n}\n\n// Reload changes DirPrefix. Don't send DirPrefix in pathPrefix parameter\n\nHRESULT CBrowseDialog::Reload(const UString &pathPrefix, const UString &selectedName)\n{\n  CObjectVector<CFileInfo> files;\n  \n  #ifndef UNDER_CE\n  bool isDrive = false;\n  if (pathPrefix.IsEmpty() || pathPrefix.IsEqualTo(kSuperPathPrefix))\n  {\n    isDrive = true;\n    FStringVector drives;\n    if (!MyGetLogicalDriveStrings(drives))\n      return GetLastError_noZero_HRESULT();\n    FOR_VECTOR (i, drives)\n    {\n      const FString &d = drives[i];\n      if (d.Len() < 2 || d.Back() != '\\\\')\n        return E_FAIL;\n      CFileInfo &fi = files.AddNew();\n      fi.SetAsDir();\n      fi.Name = d;\n      fi.Name.DeleteBack();\n    }\n  }\n  else\n  #endif\n  {\n    const UStringVector *masks = NULL;\n    if (!Filters.IsEmpty() && _filterCombo.GetCount() > 0)\n    {\n      const int selected = _filterCombo.GetCurSel();\n            // GetItemData_of_CurSel(); // we don't use data field\n      if (/* selected >= 0 && */ (unsigned)selected < Filters.Size())\n      {\n        const UStringVector &m = Filters[selected].Masks;\n        if (m.Size() > 1 || (m.Size() == 1\n              && !m[0].IsEqualTo(\"*.*\")\n              && !m[0].IsEqualTo(\"*\")))\n          masks = &m;\n      }\n    }\n    CEnumerator enumerator;\n    enumerator.SetDirPrefix(us2fs(pathPrefix));\n    CFileInfo fi;\n    for (;;)\n    {\n      bool found;\n      if (!enumerator.Next(fi, found))\n        return GetLastError_noZero_HRESULT();\n      if (!found)\n        break;\n      if (!fi.IsDir())\n      {\n        if (FolderMode)\n          continue;\n        if (masks)\n        {\n          unsigned i;\n          const unsigned numMasks = masks->Size();\n          for (i = 0; i < numMasks; i++)\n            if (DoesWildcardMatchName((*masks)[i], fs2us(fi.Name)))\n              break;\n          if (i == numMasks)\n            continue;\n        }\n      }\n      files.Add(fi);\n    }\n  }\n\n  DirPrefix = pathPrefix;\n\n  _files = files;\n\n  SetItemText(IDT_BROWSE_FOLDER, DirPrefix);\n\n  _list.SetRedraw(false);\n  _list.DeleteAllItems();\n\n  LVITEMW item;\n\n  unsigned index = 0;\n  int cursorIndex = -1;\n\n  #ifndef Z7_SFX\n  if (_showDots && _topDirPrefix != DirPrefix)\n  {\n    item.iItem = (int)index;\n    const UString itemName (\"..\");\n    if (selectedName.IsEmpty())\n      cursorIndex = (int)index;\n    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;\n    unsigned subItem = 0;\n    item.iSubItem = (int)(subItem++);\n    item.lParam = kParentIndex;\n    item.pszText = itemName.Ptr_non_const();\n    item.iImage = _extToIconMap.GetIconIndex(FILE_ATTRIBUTE_DIRECTORY, DirPrefix);\n    if (item.iImage < 0)\n      item.iImage = 0;\n    _list.InsertItem(&item);\n    _list.SetSubItem(index, subItem++, L\"\");\n    _list.SetSubItem(index, subItem++, L\"\");\n    index++;\n  }\n  #endif\n\n  for (unsigned i = 0; i < _files.Size(); i++, index++)\n  {\n    item.iItem = (int)index;\n    const CFileInfo &fi = _files[i];\n    const UString name = fs2us(fi.Name);\n    if (!selectedName.IsEmpty() && CompareFileNames(name, selectedName) == 0)\n      cursorIndex = (int)index;\n    item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;\n    unsigned subItem = 0;\n    item.iSubItem = (int)(subItem++);\n    item.lParam = (LPARAM)i;\n    item.pszText = name.Ptr_non_const();\n\n    const UString fullPath = DirPrefix + name;\n    #ifndef UNDER_CE\n    if (isDrive)\n    {\n      item.iImage = Shell_GetFileInfo_SysIconIndex_for_Path(\n          fi.Name + FCHAR_PATH_SEPARATOR,\n          FILE_ATTRIBUTE_DIRECTORY);\n    }\n    else\n    #endif\n      item.iImage = _extToIconMap.GetIconIndex(fi.Attrib, fullPath);\n    if (item.iImage < 0)\n        item.iImage = 0;\n    _list.InsertItem(&item);\n    wchar_t s[64];\n    {\n      s[0] = 0;\n      if (!FILETIME_IsZero(fi.MTime))\n        ConvertUtcFileTimeToString(fi.MTime, s,\n            #ifndef UNDER_CE\n              kTimestampPrintLevel_MIN\n            #else\n              kTimestampPrintLevel_DAY\n            #endif\n              );\n      _list.SetSubItem(index, subItem++, s);\n    }\n    {\n      s[0] = 0;\n      if (!fi.IsDir())\n        Browse_ConvertSizeToString(fi.Size, s);\n      _list.SetSubItem(index, subItem++, s);\n    }\n  }\n\n  if (_list.GetItemCount() > 0 && cursorIndex >= 0)\n    _list.SetItemState_FocusedSelected(cursorIndex);\n  _list.SortItems(CompareItems2, (LPARAM)this);\n  if (_list.GetItemCount() > 0 && cursorIndex < 0)\n    _list.SetItemState(0, LVIS_FOCUSED, LVIS_FOCUSED);\n  _list.EnsureVisible(_list.GetFocusedItem(), false);\n  _list.SetRedraw(true);\n  _list.InvalidateRect(NULL, true);\n  return S_OK;\n}\n\nHRESULT CBrowseDialog::Reload()\n{\n  UString selected;\n  const int index = _list.GetNextSelectedItem(-1);\n  if (index >= 0)\n  {\n    const int fileIndex = GetRealItemIndex(index);\n    if (fileIndex != kParentIndex)\n      selected = fs2us(_files[fileIndex].Name);\n  }\n  const UString dirPathTemp = DirPrefix;\n  return Reload(dirPathTemp, selected);\n}\n\nvoid CBrowseDialog::OpenParentFolder()\n{\n  UString parent, selected;\n  if (GetParentPath(DirPrefix, parent, selected))\n  {\n    Reload(parent, selected);\n    SetPathEditText();\n  }\n}\n\nvoid CBrowseDialog::SetPathEditText()\n{\n  const int index = _list.GetNextSelectedItem(-1);\n  if (index < 0)\n  {\n    if (FolderMode)\n      _pathEdit.SetText(DirPrefix);\n    return;\n  }\n  const int fileIndex = GetRealItemIndex(index);\n  if (fileIndex == kParentIndex)\n  {\n    if (FolderMode)\n      _pathEdit.SetText(L\"..\" WSTRING_PATH_SEPARATOR);\n    return;\n  }\n  const CFileInfo &file = _files[fileIndex];\n  if (file.IsDir())\n  {\n    if (!FolderMode)\n      return;\n    _pathEdit.SetText(fs2us(file.Name) + WCHAR_PATH_SEPARATOR);\n  }\n  else\n    _pathEdit.SetText(fs2us(file.Name));\n}\n\nvoid CBrowseDialog::OnCreateDir()\n{\n  UString name;\n  {\n    UString enteredName;\n    Dlg_CreateFolder((HWND)*this, enteredName);\n    if (enteredName.IsEmpty())\n      return;\n    if (!CorrectFsPath(DirPrefix, enteredName, name))\n    {\n      MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, name);\n      return;\n    }\n  }\n  if (name.IsEmpty())\n    return;\n\n  FString destPath;\n  if (GetFullPath(us2fs(DirPrefix), us2fs(name), destPath))\n  {\n    if (!NDir::CreateComplexDir(destPath))\n    {\n      MessageBox_HResError((HWND)*this, GetLastError_noZero_HRESULT(), fs2us(destPath));\n    }\n    else\n    {\n      UString tempPath = DirPrefix;\n      Reload(tempPath, name);\n      SetPathEditText();\n    }\n    _list.SetFocus();\n  }\n}\n\nvoid CBrowseDialog::OnItemEnter()\n{\n  const int index = _list.GetNextSelectedItem(-1);\n  if (index < 0)\n    return;\n  const int fileIndex = GetRealItemIndex(index);\n  if (fileIndex == kParentIndex)\n    OpenParentFolder();\n  else\n  {\n    const CFileInfo &file = _files[fileIndex];\n    if (!file.IsDir())\n    {\n      if (!FolderMode)\n        FinishOnOK();\n      /*\n      MessageBox_Error_Global(*this, FolderMode ?\n            L\"You must select some folder\":\n            L\"You must select some file\");\n      */\n      return;\n    }\n    UString s = DirPrefix;\n    s += fs2us(file.Name);\n    s.Add_PathSepar();\n    const HRESULT res = Reload(s, UString());\n    if (res != S_OK)\n      MessageBox_HResError(*this, res, s);\n    SetPathEditText();\n  }\n}\n\nvoid CBrowseDialog::FinishOnOK()\n{\n  UString s;\n  _pathEdit.GetText(s);\n  FString destPath;\n  if (!GetFullPath(us2fs(DirPrefix), us2fs(s), destPath))\n  {\n    MessageBox_HResError((HWND)*this, ERROR_INVALID_NAME, s);\n    return;\n  }\n  FilePath = fs2us(destPath);\n  if (FolderMode)\n    NormalizeDirPathPrefix(FilePath);\n  FilterIndex = _filterCombo.GetCurSel();\n  End(IDOK);\n}\n\n#endif // USE_MY_BROWSE_DIALOG\n\n\n\nbool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath)\n{\n  resultPath.Empty();\n\n  #ifndef UNDER_CE\n\n#ifdef USE_MY_BROWSE_DIALOG\n  if (!IsSuperOrDevicePath(path))\n  if (MyStringLen(path) < MAX_PATH)\n#endif\n    return NShell::BrowseForFolder(owner, title, path, resultPath);\n\n  #endif //  UNDER_CE\n\n  #ifdef USE_MY_BROWSE_DIALOG\n\n  CBrowseDialog dialog;\n  dialog.FolderMode = true;\n  if (title)\n    dialog.Title = title;\n  if (path)\n    dialog.FilePath = path;\n  if (dialog.Create(owner) != IDOK)\n    return false;\n  resultPath = dialog.FilePath;\n  return true;\n\n  #endif\n}\n\n\n// LPCWSTR filterDescription, LPCWSTR filter,\n\nbool CBrowseInfo::BrowseForFile(const CObjectVector<CBrowseFilterInfo> &filters)\n{\n#ifndef UNDER_CE\n#ifdef USE_MY_BROWSE_DIALOG\n  /* win10:\n     GetOpenFileName() for FilePath doesn't support super prefix \"\\\\\\\\?\\\\\"\n     GetOpenFileName() for FilePath doesn't support long path\n  */\n  if (!IsSuperOrDevicePath(FilePath))\n  // if (filters.Size() > 100) // for debug\n#endif\n  {\n    const UString filePath_Store = FilePath;\n    UString dirPrefix;\n    {\n      FString prefix, name;\n      if (NDir::GetFullPathAndSplit(us2fs(FilePath), prefix, name))\n      {\n        dirPrefix = fs2us(prefix);\n        FilePath = fs2us(name);\n      }\n    }\n    UStringVector filters2;\n    FOR_VECTOR (i, filters)\n    {\n      const CBrowseFilterInfo &fi = filters[i];\n      filters2.Add(fi.Description);\n      UString s;\n      FOR_VECTOR (k, fi.Masks)\n      {\n        if (k != 0)\n          s += \";\";\n        s += fi.Masks[k];\n      }\n      filters2.Add(s);\n    }\n    if (CommonDlg_BrowseForFile(!dirPrefix.IsEmpty() ? dirPrefix.Ptr(): NULL, filters2))\n      return true;\n    FilePath = filePath_Store;\n\n  #ifdef UNDER_CE\n    return false;\n  #else\n    // maybe we must use GetLastError in WinCE.\n    const DWORD errorCode = CommDlgExtendedError();\n  #ifdef USE_MY_BROWSE_DIALOG\n    // FNERR_INVALIDFILENAME is expected error, if long path was used\n    if (errorCode != FNERR_INVALIDFILENAME\n        || FilePath.Len() < MAX_PATH)\n  #endif\n    {\n      if (errorCode == 0)  // cancel or close on dialog\n        return false;\n      const char *message = NULL;\n      if (errorCode == FNERR_INVALIDFILENAME)\n        message = \"Invalid file name\";\n      UString s (\"Open Dialog Error:\");\n      s.Add_LF();\n      if (message)\n        s += message;\n      else\n      {\n        char temp[16];\n        ConvertUInt32ToHex8Digits(errorCode, temp);\n        s += \"Error #\";\n        s += temp;\n      }\n      s.Add_LF();\n      s += FilePath;\n      MessageBox_Error_Global(hwndOwner, s);\n    }\n  #endif // UNDER_CE\n  }\n\n#endif // UNDER_CE\n  \n#ifdef USE_MY_BROWSE_DIALOG\n\n  CBrowseDialog dialog;\n\n  dialog.FolderMode = false;\n  dialog.SaveMode = SaveMode;\n  dialog.FilterIndex = FilterIndex;\n  dialog.Filters = filters;\n\n  if (lpstrTitle)\n    dialog.Title = lpstrTitle;\n  dialog.FilePath = FilePath;\n  if (dialog.Create(hwndOwner) != IDOK)\n    return false;\n  FilePath = dialog.FilePath;\n  FilterIndex = dialog.FilterIndex;\n#endif\n\n  return true;\n}\n\n\n#ifdef _WIN32\n\nstatic void RemoveDotsAndSpaces(UString &path)\n{\n  while (!path.IsEmpty())\n  {\n    wchar_t c = path.Back();\n    if (c != ' ' && c != '.')\n      return;\n    path.DeleteBack();\n  }\n}\n\n\nbool CorrectFsPath(const UString &relBase, const UString &path2, UString &result)\n{\n  result.Empty();\n\n  UString path = path2;\n  #ifdef _WIN32\n  path.Replace(L'/', WCHAR_PATH_SEPARATOR);\n  #endif\n  unsigned start = 0;\n  UString base;\n  \n  if (IsAbsolutePath(path))\n  {\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    if (IsSuperOrDevicePath(path))\n    {\n      result = path;\n      return true;\n    }\n    #endif\n    start = GetRootPrefixSize(path);\n  }\n  else\n  {\n    #if defined(_WIN32) && !defined(UNDER_CE)\n    if (IsSuperOrDevicePath(relBase))\n    {\n      result = path;\n      return true;\n    }\n    #endif\n    base = relBase;\n  }\n\n  /* We can't use backward, since we must change only disk paths */\n  /*\n  for (;;)\n  {\n    if (path.Len() <= start)\n      break;\n    if (DoesFileOrDirExist(us2fs(path)))\n      break;\n    if (path.Back() == WCHAR_PATH_SEPARATOR)\n    {\n      path.DeleteBack();\n      result.Insert(0, WCHAR_PATH_SEPARATOR);\n    }\n    int pos = path.ReverseFind(WCHAR_PATH_SEPARATOR) + 1;\n    UString cur = path.Ptr(pos);\n    RemoveDotsAndSpaces(cur);\n    result.Insert(0, cur);\n    path.DeleteFrom(pos);\n  }\n  result.Insert(0, path);\n  return true;\n  */\n\n  result += path.Left(start);\n  bool checkExist = true;\n  UString cur;\n\n  for (;;)\n  {\n    if (start == path.Len())\n      break;\n    const int slashPos = path.Find(WCHAR_PATH_SEPARATOR, start);\n    cur.SetFrom(path.Ptr(start), (slashPos < 0 ? path.Len() : (unsigned)slashPos) - start);\n    if (checkExist)\n    {\n      CFileInfo fi;\n      if (fi.Find(us2fs(base + result + cur)))\n      {\n        if (!fi.IsDir())\n        {\n          result = path;\n          break;\n        }\n      }\n      else\n        checkExist = false;\n    }\n    if (!checkExist)\n      RemoveDotsAndSpaces(cur);\n    result += cur;\n    if (slashPos < 0)\n      break;\n    start = (unsigned)(slashPos + 1);\n    result.Add_PathSepar();\n  }\n  \n  return true;\n}\n\n#else\n\nbool CorrectFsPath(const UString & /* relBase */, const UString &path, UString &result)\n{\n  result = path;\n  return true;\n}\n\n#endif\n\nbool Dlg_CreateFolder(HWND wnd, UString &destName)\n{\n  destName.Empty();\n  CComboDialog dlg;\n  LangString(IDS_CREATE_FOLDER, dlg.Title);\n  LangString(IDS_CREATE_FOLDER_NAME, dlg.Static);\n  LangString(IDS_CREATE_FOLDER_DEFAULT_NAME, dlg.Value);\n  if (dlg.Create(wnd) != IDOK)\n    return false;\n  destName = dlg.Value;\n  return true;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/BrowseDialog.h",
    "content": "﻿// BrowseDialog.h\n\n#ifndef ZIP7_INC_BROWSE_DIALOG_H\n#define ZIP7_INC_BROWSE_DIALOG_H\n\n#include \"../../../Windows/CommonDialog.h\"\n\nbool MyBrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR path, UString &resultPath);\n\nstruct CBrowseFilterInfo\n{\n  UStringVector Masks;\n  UString Description;\n};\n\nstruct CBrowseInfo: public NWindows::CCommonDialogInfo\n{\n  bool BrowseForFile(const CObjectVector<CBrowseFilterInfo> &filters);\n};\n\n\n/* CorrectFsPath removes undesirable characters in names (dots and spaces at the end of file)\n   But it doesn't change \"bad\" name in any of the following cases:\n     - path is Super Path (with \\\\?\\ prefix)\n     - path is relative and relBase is Super Path\n     - there is file or dir in filesystem with specified \"bad\" name */\n\nbool CorrectFsPath(const UString &relBase, const UString &path, UString &result);\n\nbool Dlg_CreateFolder(HWND wnd, UString &destName);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/BrowseDialogRes.h",
    "content": "﻿#define IDD_BROWSE  95\n\n#define IDL_BROWSE         100\n#define IDT_BROWSE_FOLDER  101\n#define IDE_BROWSE_PATH    102\n#define IDC_BROWSE_FILTER  103\n\n#define IDB_BROWSE_PARENT     110\n#define IDB_BROWSE_CREATE_DIR 112\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ComboDialog.cpp",
    "content": "﻿// ComboDialog.cpp\n\n#include \"StdAfx.h\"\n#include \"ComboDialog.h\"\n\n#include \"../../../Windows/Control/Static.h\"\n\n#ifdef Z7_LANG\n#include \"LangUtils.h\"\n#endif\n\nusing namespace NWindows;\n\nbool CComboDialog::OnInit()\n{\n  #ifdef Z7_LANG\n  LangSetDlgItems(*this, NULL, 0);\n  #endif\n  _comboBox.Attach(GetItem(IDC_COMBO));\n\n  /*\n  // why it doesn't work ?\n  DWORD style = _comboBox.GetStyle();\n  if (Sorted)\n    style |= CBS_SORT;\n  else\n    style &= ~CBS_SORT;\n  _comboBox.SetStyle(style);\n  */\n  SetText(Title);\n  \n  NControl::CStatic staticContol;\n  staticContol.Attach(GetItem(IDT_COMBO));\n  staticContol.SetText(Static);\n  _comboBox.SetText(Value);\n  FOR_VECTOR (i, Strings)\n    _comboBox.AddString(Strings[i]);\n  NormalizeSize();\n  return CModalDialog::OnInit();\n}\n\nbool CComboDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\n{\n  int mx, my;\n  GetMargins(8, mx, my);\n  int bx1, bx2, by;\n  GetItemSizes(IDCANCEL, bx1, by);\n  GetItemSizes(IDOK, bx2, by);\n  int y = ySize - my - by;\n  int x = xSize - mx - bx1;\n\n  InvalidateRect(NULL);\n\n  MoveItem(IDCANCEL, x, y, bx1, by);\n  MoveItem(IDOK, x - mx - bx2, y, bx2, by);\n  ChangeSubWindowSizeX(_comboBox, xSize - mx * 2);\n  return false;\n}\n\nvoid CComboDialog::OnOK()\n{\n  _comboBox.GetText(Value);\n  CModalDialog::OnOK();\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ComboDialog.h",
    "content": "﻿// ComboDialog.h\n\n#ifndef ZIP7_INC_COMBO_DIALOG_H\n#define ZIP7_INC_COMBO_DIALOG_H\n\n#include \"../../../Windows/Control/ComboBox.h\"\n#include \"../../../Windows/Control/Dialog.h\"\n\n#include \"ComboDialogRes.h\"\n\nclass CComboDialog: public NWindows::NControl::CModalDialog\n{\n  NWindows::NControl::CComboBox _comboBox;\n  virtual void OnOK() Z7_override;\n  virtual bool OnInit() Z7_override;\n  virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override;\npublic:\n  // bool Sorted;\n  UString Title;\n  UString Static;\n  UString Value;\n  UStringVector Strings;\n  \n  // CComboDialog(): Sorted(false) {};\n  INT_PTR Create(HWND parentWindow = NULL) { return CModalDialog::Create(IDD_COMBO, parentWindow); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ComboDialog.rc",
    "content": "#include \"ComboDialogRes.h\"\n#include \"../../GuiCommon.rc\"\n\n#define xc 240\n#define yc 64\n\nIDD_COMBO  DIALOG  0, 0, xs, ys  MY_MODAL_RESIZE_DIALOG_STYLE  MY_FONT\nCAPTION \"Combo\"\n{\n  LTEXT      \"\", IDT_COMBO, m, m, xc, 8\n  COMBOBOX       IDC_COMBO, m, 20, xc, 65, MY_COMBO_WITH_EDIT\n  OK_CANCEL\n}\n\n#undef xc\n#undef yc\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ComboDialogRes.h",
    "content": "﻿#define IDD_COMBO   98\n\n#define IDT_COMBO  100\n#define IDC_COMBO  101\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/DialogSize.h",
    "content": "﻿// DialogSize.h\n\n#ifndef ZIP7_INC_DIALOG_SIZE_H\n#define ZIP7_INC_DIALOG_SIZE_H\n\n#include \"../../../Windows/Control/Dialog.h\"\n\n#ifdef UNDER_CE\n#define BIG_DIALOG_SIZE(x, y) bool isBig = NWindows::NControl::IsDialogSizeOK(x, y);\n#define SIZED_DIALOG(big) (isBig ? big : big ## _2)\n#else\n#define BIG_DIALOG_SIZE(x, y)\n#define SIZED_DIALOG(big) big\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ExtractCallback.cpp",
    "content": "﻿// ExtractCallback.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/ComTry.h\"\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/Lang.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n\n#include \"../../Common/FilePathAutoRename.h\"\n#include \"../../Common/StreamUtils.h\"\n#include \"../Common/ExtractingFilePath.h\"\n\n#ifndef Z7_SFX\n#include \"../Common/ZipRegistry.h\"\n#endif\n\n#include \"../GUI/ExtractRes.h\"\n#include \"resourceGui.h\"\n\n#include \"ExtractCallback.h\"\n#include \"FormatUtils.h\"\n#include \"LangUtils.h\"\n#include \"MemDialog.h\"\n#include \"OverwriteDialog.h\"\n#ifndef Z7_NO_CRYPTO\n#include \"PasswordDialog.h\"\n#endif\n#include \"PropertyName.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NFind;\n\nextern bool g_DisableUserQuestions;\n\nCExtractCallbackImp::~CExtractCallbackImp() {}\n\nvoid CExtractCallbackImp::Init()\n{\n  LangString(IDS_PROGRESS_EXTRACTING, _lang_Extracting);\n  LangString(IDS_PROGRESS_TESTING, _lang_Testing);\n  LangString(IDS_PROGRESS_SKIPPING, _lang_Skipping);\n  _lang_Reading = \"Reading\";\n\n  NumArchiveErrors = 0;\n  ThereAreMessageErrors = false;\n  #ifndef Z7_SFX\n  NumFolders = NumFiles = 0;\n  NeedAddFile = false;\n  #endif\n}\n\nvoid CExtractCallbackImp::AddError_Message(LPCWSTR s)\n{\n  ThereAreMessageErrors = true;\n  ProgressDialog->Sync.AddError_Message(s);\n}\n\nvoid CExtractCallbackImp::AddError_Message_ShowArcPath(LPCWSTR s)\n{\n  Add_ArchiveName_Error();\n  AddError_Message(s);\n}\n\n\n#ifndef Z7_SFX\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetNumFiles(UInt64 numFiles))\n{\n #ifdef Z7_SFX\n  UNUSED_VAR(numFiles)\n #else\n  ProgressDialog->Sync.Set_NumFilesTotal(numFiles);\n #endif\n  return S_OK;\n}\n\n#endif\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetTotal(UInt64 total))\n{\n  ProgressDialog->Sync.Set_NumBytesTotal(total);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetCompleted(const UInt64 *value))\n{\n  return ProgressDialog->Sync.Set_NumBytesCur(value);\n}\n\nHRESULT CExtractCallbackImp::Open_CheckBreak()\n{\n  return ProgressDialog->Sync.CheckStop();\n}\n\nHRESULT CExtractCallbackImp::Open_SetTotal(const UInt64 *files, const UInt64 *bytes)\n{\n  HRESULT res = S_OK;\n  if (!MultiArcMode)\n  {\n    if (files)\n    {\n      _totalFiles_Defined = true;\n      // res = ProgressDialog->Sync.Set_NumFilesTotal(*files);\n    }\n    else\n      _totalFiles_Defined = false;\n\n    if (bytes)\n    {\n      _totalBytes_Defined = true;\n      ProgressDialog->Sync.Set_NumBytesTotal(*bytes);\n    }\n    else\n      _totalBytes_Defined = false;\n  }\n\n  return res;\n}\n\nHRESULT CExtractCallbackImp::Open_SetCompleted(const UInt64 *files, const UInt64 *bytes)\n{\n  if (!MultiArcMode)\n  {\n    if (files)\n    {\n      ProgressDialog->Sync.Set_NumFilesCur(*files);\n    }\n\n    if (bytes)\n    {\n    }\n  }\n\n  return ProgressDialog->Sync.CheckStop();\n}\n\nHRESULT CExtractCallbackImp::Open_Finished()\n{\n  return ProgressDialog->Sync.CheckStop();\n}\n\n#ifndef Z7_NO_CRYPTO\n\nHRESULT CExtractCallbackImp::Open_CryptoGetTextPassword(BSTR *password)\n{\n  return CryptoGetTextPassword(password);\n}\n\n/*\nHRESULT CExtractCallbackImp::Open_GetPasswordIfAny(bool &passwordIsDefined, UString &password)\n{\n  passwordIsDefined = PasswordIsDefined;\n  password = Password;\n  return S_OK;\n}\n\nbool CExtractCallbackImp::Open_WasPasswordAsked()\n{\n  return PasswordWasAsked;\n}\n\nvoid CExtractCallbackImp::Open_Clear_PasswordWasAsked_Flag()\n{\n  PasswordWasAsked = false;\n}\n*/\n\n#endif\n\n\n#ifndef Z7_SFX\nZ7_COM7F_IMF(CExtractCallbackImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))\n{\n  ProgressDialog->Sync.Set_Ratio(inSize, outSize);\n  return S_OK;\n}\n#endif\n\n/*\nZ7_COM7F_IMF(CExtractCallbackImp::SetTotalFiles(UInt64 total)\n{\n  ProgressDialog->Sync.SetNumFilesTotal(total);\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetCompletedFiles(const UInt64 *value)\n{\n  if (value != NULL)\n    ProgressDialog->Sync.SetNumFilesCur(*value);\n  return S_OK;\n}\n*/\n\nZ7_COM7F_IMF(CExtractCallbackImp::AskOverwrite(\n    const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,\n    const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,\n    Int32 *answer))\n{\n  COverwriteDialog dialog;\n\n  dialog.OldFileInfo.SetTime2(existTime);\n  dialog.OldFileInfo.SetSize2(existSize);\n  dialog.OldFileInfo.Path = existName;\n  dialog.OldFileInfo.Is_FileSystemFile = true;\n\n  dialog.NewFileInfo.SetTime2(newTime);\n  dialog.NewFileInfo.SetSize2(newSize);\n  dialog.NewFileInfo.Path = newName;\n  dialog.NewFileInfo.Is_FileSystemFile = Src_Is_IO_FS_Folder;\n  \n  ProgressDialog->WaitCreating();\n  const INT_PTR writeAnswer = dialog.Create(*ProgressDialog);\n  \n  switch (writeAnswer)\n  {\n    case IDCANCEL:        *answer = NOverwriteAnswer::kCancel; return E_ABORT;\n    case IDYES:           *answer = NOverwriteAnswer::kYes; break;\n    case IDNO:            *answer = NOverwriteAnswer::kNo; break;\n    case IDB_YES_TO_ALL:  *answer = NOverwriteAnswer::kYesToAll; break;\n    case IDB_NO_TO_ALL:   *answer = NOverwriteAnswer::kNoToAll; break;\n    case IDB_AUTO_RENAME: *answer = NOverwriteAnswer::kAutoRename; break;\n    default: return E_FAIL;\n  }\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CExtractCallbackImp::PrepareOperation(const wchar_t *name, Int32 isFolder, Int32 askExtractMode, const UInt64 * /* position */))\n{\n  _isFolder = IntToBool(isFolder);\n  _currentFilePath = name;\n\n  const UString *msg = &_lang_Empty;\n  switch (askExtractMode)\n  {\n    case NArchive::NExtract::NAskMode::kExtract: msg = &_lang_Extracting; break;\n    case NArchive::NExtract::NAskMode::kTest:    msg = &_lang_Testing; break;\n    case NArchive::NExtract::NAskMode::kSkip:    msg = &_lang_Skipping; break;\n    case NArchive::NExtract::NAskMode::kReadExternal: msg = &_lang_Reading; break;\n    // default: s = \"Unknown operation\";\n  }\n\n  return ProgressDialog->Sync.Set_Status2(*msg, name, IntToBool(isFolder));\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::MessageError(const wchar_t *s))\n{\n  AddError_Message(s);\n  return S_OK;\n}\n\nHRESULT CExtractCallbackImp::MessageError(const char *message, const FString &path)\n{\n  ThereAreMessageErrors = true;\n  ProgressDialog->Sync.AddError_Message_Name(GetUnicodeString(message), fs2us(path));\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\nZ7_COM7F_IMF(CExtractCallbackImp::ShowMessage(const wchar_t *s))\n{\n  AddError_Message(s);\n  return S_OK;\n}\n\n#endif\n\nvoid SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);\nvoid SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s)\n{\n  s.Empty();\n\n  if (opRes == NArchive::NExtract::NOperationResult::kOK)\n    return;\n\n #ifndef Z7_SFX\n  UINT messageID = 0;\n #endif\n  UINT id = 0;\n\n  switch (opRes)\n  {\n    case NArchive::NExtract::NOperationResult::kUnsupportedMethod:\n     #ifndef Z7_SFX\n      messageID = IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD;\n     #endif\n      id = IDS_EXTRACT_MSG_UNSUPPORTED_METHOD;\n      break;\n    case NArchive::NExtract::NOperationResult::kDataError:\n     #ifndef Z7_SFX\n      messageID = encrypted ?\n          IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED:\n          IDS_EXTRACT_MESSAGE_DATA_ERROR;\n     #endif\n      id = IDS_EXTRACT_MSG_DATA_ERROR;\n      break;\n    case NArchive::NExtract::NOperationResult::kCRCError:\n     #ifndef Z7_SFX\n      messageID = encrypted ?\n          IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED:\n          IDS_EXTRACT_MESSAGE_CRC_ERROR;\n     #endif\n      id = IDS_EXTRACT_MSG_CRC_ERROR;\n      break;\n    case NArchive::NExtract::NOperationResult::kUnavailable:\n      id = IDS_EXTRACT_MSG_UNAVAILABLE_DATA;\n      break;\n    case NArchive::NExtract::NOperationResult::kUnexpectedEnd:\n      id = IDS_EXTRACT_MSG_UEXPECTED_END;\n      break;\n    case NArchive::NExtract::NOperationResult::kDataAfterEnd:\n      id = IDS_EXTRACT_MSG_DATA_AFTER_END;\n      break;\n    case NArchive::NExtract::NOperationResult::kIsNotArc:\n      id = IDS_EXTRACT_MSG_IS_NOT_ARC;\n      break;\n    case NArchive::NExtract::NOperationResult::kHeadersError:\n      id = IDS_EXTRACT_MSG_HEADERS_ERROR;\n      break;\n    case NArchive::NExtract::NOperationResult::kWrongPassword:\n      id = IDS_EXTRACT_MSG_WRONG_PSW_CLAIM;\n      break;\n    /*\n    default:\n      messageID = IDS_EXTRACT_MESSAGE_UNKNOWN_ERROR;\n      break;\n    */\n  }\n\n  UString msg;\n\n #ifndef Z7_SFX\n  UString msgOld;\n #ifdef Z7_LANG\n  if (id != 0)\n    LangString_OnlyFromLangFile(id, msg);\n  if (messageID != 0 && msg.IsEmpty())\n    LangString_OnlyFromLangFile(messageID, msgOld);\n #endif\n  if (msg.IsEmpty() && !msgOld.IsEmpty())\n    s = MyFormatNew(msgOld, fileName);\n  else\n #endif\n  {\n    if (msg.IsEmpty() && id != 0)\n      LangString(id, msg);\n    if (!msg.IsEmpty())\n      s += msg;\n    else\n    {\n      s += \"Error #\";\n      s.Add_UInt32((UInt32)opRes);\n    }\n\n    if (encrypted && opRes != NArchive::NExtract::NOperationResult::kWrongPassword)\n    {\n      // s += \" : \";\n      // AddLangString(s, IDS_EXTRACT_MSG_ENCRYPTED);\n      s += \" : \";\n      AddLangString(s, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);\n    }\n    s += \" : \";\n    s += fileName;\n  }\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetOperationResult(Int32 opRes, Int32 encrypted))\n{\n  switch (opRes)\n  {\n    case NArchive::NExtract::NOperationResult::kOK:\n      break;\n    default:\n    {\n      UString s;\n      SetExtractErrorMessage(opRes, encrypted, _currentFilePath, s);\n      AddError_Message_ShowArcPath(s);\n    }\n  }\n  \n  _currentFilePath.Empty();\n  #ifndef Z7_SFX\n  if (_isFolder)\n    NumFolders++;\n  else\n    NumFiles++;\n  ProgressDialog->Sync.Set_NumFilesCur(NumFiles);\n  #endif\n  \n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::ReportExtractResult(Int32 opRes, Int32 encrypted, const wchar_t *name))\n{\n  if (opRes != NArchive::NExtract::NOperationResult::kOK)\n  {\n    UString s;\n    SetExtractErrorMessage(opRes, encrypted, name, s);\n    AddError_Message_ShowArcPath(s);\n  }\n  return S_OK;\n}\n\n////////////////////////////////////////\n// IExtractCallbackUI\n\nHRESULT CExtractCallbackImp::BeforeOpen(const wchar_t *name, bool /* testMode */)\n{\n  _currentArchivePath = name;\n  _needWriteArchivePath = true;\n  #ifndef Z7_SFX\n  RINOK(ProgressDialog->Sync.CheckStop())\n  ProgressDialog->Sync.Set_TitleFileName(name);\n  #endif\n  return S_OK;\n}\n\nHRESULT CExtractCallbackImp::SetCurrentFilePath2(const wchar_t *path)\n{\n  _currentFilePath = path;\n  #ifndef Z7_SFX\n  ProgressDialog->Sync.Set_FilePath(path);\n  #endif\n  return S_OK;\n}\n\n#ifndef Z7_SFX\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetCurrentFilePath(const wchar_t *path))\n{\n  #ifndef Z7_SFX\n  if (NeedAddFile)\n    NumFiles++;\n  NeedAddFile = true;\n  ProgressDialog->Sync.Set_NumFilesCur(NumFiles);\n  #endif\n  return SetCurrentFilePath2(path);\n}\n\n#endif\n\nUString HResultToMessage(HRESULT errorCode);\n\nstatic const UInt32 k_ErrorFlagsIds[] =\n{\n  IDS_EXTRACT_MSG_IS_NOT_ARC,\n  IDS_EXTRACT_MSG_HEADERS_ERROR,\n  IDS_EXTRACT_MSG_HEADERS_ERROR,\n  IDS_OPEN_MSG_UNAVAILABLE_START,\n  IDS_OPEN_MSG_UNCONFIRMED_START,\n  IDS_EXTRACT_MSG_UEXPECTED_END,\n  IDS_EXTRACT_MSG_DATA_AFTER_END,\n  IDS_EXTRACT_MSG_UNSUPPORTED_METHOD,\n  IDS_OPEN_MSG_UNSUPPORTED_FEATURE,\n  IDS_EXTRACT_MSG_DATA_ERROR,\n  IDS_EXTRACT_MSG_CRC_ERROR\n};\n\nstatic void AddNewLineString(UString &s, const UString &m)\n{\n  s += m;\n  s.Add_LF();\n}\n\nUString GetOpenArcErrorMessage(UInt32 errorFlags);\nUString GetOpenArcErrorMessage(UInt32 errorFlags)\n{\n  UString s;\n\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ErrorFlagsIds); i++)\n  {\n    const UInt32 f = (UInt32)1 << i;\n    if ((errorFlags & f) == 0)\n      continue;\n    const UInt32 id = k_ErrorFlagsIds[i];\n    UString m = LangString(id);\n    if (m.IsEmpty())\n      continue;\n    if (f == kpv_ErrorFlags_EncryptedHeadersError)\n    {\n      m += \" : \";\n      AddLangString(m, IDS_EXTRACT_MSG_WRONG_PSW_GUESS);\n    }\n    if (!s.IsEmpty())\n      s.Add_LF();\n    s += m;\n    errorFlags &= ~f;\n  }\n  \n  if (errorFlags != 0)\n  {\n    char sz[16];\n    sz[0] = '0';\n    sz[1] = 'x';\n    ConvertUInt32ToHex(errorFlags, sz + 2);\n    if (!s.IsEmpty())\n      s.Add_LF();\n    s += sz;\n  }\n  \n  return s;\n}\n\nstatic void ErrorInfo_Print(UString &s, const CArcErrorInfo &er)\n{\n  const UInt32 errorFlags = er.GetErrorFlags();\n  const UInt32 warningFlags = er.GetWarningFlags();\n\n  if (errorFlags != 0)\n    AddNewLineString(s, GetOpenArcErrorMessage(errorFlags));\n      \n  if (!er.ErrorMessage.IsEmpty())\n    AddNewLineString(s, er.ErrorMessage);\n  \n  if (warningFlags != 0)\n  {\n    s += GetNameOfProperty(kpidWarningFlags, L\"Warnings\");\n    s.Add_Colon();\n    s.Add_LF();\n    AddNewLineString(s, GetOpenArcErrorMessage(warningFlags));\n  }\n  \n  if (!er.WarningMessage.IsEmpty())\n  {\n    s += GetNameOfProperty(kpidWarning, L\"Warning\");\n    s += \": \";\n    s += er.WarningMessage;\n    s.Add_LF();\n  }\n}\n\nstatic UString GetBracedType(const wchar_t *type)\n{\n  UString s ('[');\n  s += type;\n  s.Add_Char(']');\n  return s;\n}\n\nvoid OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result);\nvoid OpenResult_GUI(UString &s, const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)\n{\n  FOR_VECTOR (level, arcLink.Arcs)\n  {\n    const CArc &arc = arcLink.Arcs[level];\n    const CArcErrorInfo &er = arc.ErrorInfo;\n\n    if (!er.IsThereErrorOrWarning() && er.ErrorFormatIndex < 0)\n      continue;\n\n    if (s.IsEmpty())\n    {\n      s += name;\n      s.Add_LF();\n    }\n    \n    if (level != 0)\n    {\n      AddNewLineString(s, arc.Path);\n    }\n      \n    ErrorInfo_Print(s, er);\n\n    if (er.ErrorFormatIndex >= 0)\n    {\n      AddNewLineString(s, GetNameOfProperty(kpidWarning, L\"Warning\"));\n      if (arc.FormatIndex == er.ErrorFormatIndex)\n      {\n        AddNewLineString(s, LangString(IDS_IS_OPEN_WITH_OFFSET));\n      }\n      else\n      {\n        AddNewLineString(s, MyFormatNew(IDS_CANT_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(er.ErrorFormatIndex))));\n        AddNewLineString(s, MyFormatNew(IDS_IS_OPEN_AS_TYPE, GetBracedType(codecs->GetFormatNamePtr(arc.FormatIndex))));\n      }\n    }\n  }\n\n  if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result != S_OK)\n  {\n    s += name;\n    s.Add_LF();\n    if (!arcLink.Arcs.IsEmpty())\n      AddNewLineString(s, arcLink.NonOpen_ArcPath);\n    \n    if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0 || result == S_FALSE)\n    {\n      UINT id = IDS_CANT_OPEN_ARCHIVE;\n      UString param;\n      if (arcLink.PasswordWasAsked)\n        id = IDS_CANT_OPEN_ENCRYPTED_ARCHIVE;\n      else if (arcLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)\n      {\n        id = IDS_CANT_OPEN_AS_TYPE;\n        param = GetBracedType(codecs->GetFormatNamePtr(arcLink.NonOpen_ErrorInfo.ErrorFormatIndex));\n      }\n      UString s2 = MyFormatNew(id, param);\n      s2.Replace(L\" ''\", L\"\");\n      s2.Replace(L\"''\", L\"\");\n      s += s2;\n    }\n    else\n      s += HResultToMessage(result);\n\n    s.Add_LF();\n    ErrorInfo_Print(s, arcLink.NonOpen_ErrorInfo);\n  }\n\n  if (!s.IsEmpty() && s.Back() == '\\n')\n    s.DeleteBack();\n}\n\nHRESULT CExtractCallbackImp::OpenResult(const CCodecs *codecs, const CArchiveLink &arcLink, const wchar_t *name, HRESULT result)\n{\n  _currentArchivePath = name;\n  _needWriteArchivePath = true;\n\n  UString s;\n  OpenResult_GUI(s, codecs, arcLink, name, result);\n  if (!s.IsEmpty())\n  {\n    NumArchiveErrors++;\n    AddError_Message(s);\n    _needWriteArchivePath = false;\n  }\n\n  return S_OK;\n}\n\nHRESULT CExtractCallbackImp::ThereAreNoFiles()\n{\n  return S_OK;\n}\n\nvoid CExtractCallbackImp::Add_ArchiveName_Error()\n{\n  if (_needWriteArchivePath)\n  {\n    if (!_currentArchivePath.IsEmpty())\n      AddError_Message(_currentArchivePath);\n    _needWriteArchivePath = false;\n  }\n}\n\nHRESULT CExtractCallbackImp::ExtractResult(HRESULT result)\n{\n  #ifndef Z7_SFX\n  ProgressDialog->Sync.Set_FilePath(L\"\");\n  #endif\n\n  if (result == S_OK)\n    return result;\n  NumArchiveErrors++;\n  if (result == E_ABORT\n      || result == HRESULT_FROM_WIN32(ERROR_DISK_FULL)\n      )\n    return result;\n\n  Add_ArchiveName_Error();\n  if (!_currentFilePath.IsEmpty())\n    MessageError(_currentFilePath);\n  MessageError(NError::MyFormatMessage(result));\n  return S_OK;\n}\n\n#ifndef Z7_NO_CRYPTO\n\nHRESULT CExtractCallbackImp::SetPassword(const UString &password)\n{\n  PasswordIsDefined = true;\n  Password = password;\n  return S_OK;\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::CryptoGetTextPassword(BSTR *password))\n{\n  PasswordWasAsked = true;\n  if (!PasswordIsDefined)\n  {\n    CPasswordDialog dialog;\n    #ifndef Z7_SFX\n    const bool showPassword = NExtract::Read_ShowPassword();\n    dialog.ShowPassword = showPassword;\n    #endif\n    ProgressDialog->WaitCreating();\n    if (dialog.Create(*ProgressDialog) != IDOK)\n      return E_ABORT;\n    Password = dialog.Password;\n    PasswordIsDefined = true;\n    #ifndef Z7_SFX\n    if (dialog.ShowPassword != showPassword)\n      NExtract::Save_ShowPassword(dialog.ShowPassword);\n    #endif\n  }\n  return StringToBstr(Password, password);\n}\n\n#endif\n\n#ifndef Z7_SFX\n\nZ7_COM7F_IMF(CExtractCallbackImp::AskWrite(\n    const wchar_t *srcPath, Int32 srcIsFolder,\n    const FILETIME *srcTime, const UInt64 *srcSize,\n    const wchar_t *destPath,\n    BSTR *destPathResult,\n    Int32 *writeAnswer))\n{\n  UString destPathResultTemp = destPath;\n\n  // RINOK(StringToBstr(destPath, destPathResult));\n\n  *destPathResult = NULL;\n  *writeAnswer = BoolToInt(false);\n\n  FString destPathSys = us2fs(destPath);\n  const bool srcIsFolderSpec = IntToBool(srcIsFolder);\n  CFileInfo destFileInfo;\n  \n  if (destFileInfo.Find(destPathSys))\n  {\n    if (srcIsFolderSpec)\n    {\n      if (!destFileInfo.IsDir())\n      {\n        RINOK(MessageError(\"Cannot replace file with folder with same name\", destPathSys))\n        return E_ABORT;\n      }\n      *writeAnswer = BoolToInt(false);\n      return S_OK;\n    }\n  \n    if (destFileInfo.IsDir())\n    {\n      RINOK(MessageError(\"Cannot replace folder with file with same name\", destPathSys))\n      *writeAnswer = BoolToInt(false);\n      return S_OK;\n    }\n\n    switch ((int)OverwriteMode)\n    {\n      case NExtract::NOverwriteMode::kSkip:\n        return S_OK;\n      case NExtract::NOverwriteMode::kAsk:\n      {\n        Int32 overwriteResult;\n        UString destPathSpec = destPath;\n        const int slashPos = destPathSpec.ReverseFind_PathSepar();\n        destPathSpec.DeleteFrom((unsigned)(slashPos + 1));\n        destPathSpec += fs2us(destFileInfo.Name);\n\n        RINOK(AskOverwrite(\n            destPathSpec,\n            &destFileInfo.MTime, &destFileInfo.Size,\n            srcPath,\n            srcTime, srcSize,\n            &overwriteResult))\n        \n        switch (overwriteResult)\n        {\n          case NOverwriteAnswer::kCancel: return E_ABORT;\n          case NOverwriteAnswer::kNo: return S_OK;\n          case NOverwriteAnswer::kNoToAll: OverwriteMode = NExtract::NOverwriteMode::kSkip; return S_OK;\n          case NOverwriteAnswer::kYes: break;\n          case NOverwriteAnswer::kYesToAll: OverwriteMode = NExtract::NOverwriteMode::kOverwrite; break;\n          case NOverwriteAnswer::kAutoRename: OverwriteMode = NExtract::NOverwriteMode::kRename; break;\n          default:\n            return E_FAIL;\n        }\n        break;\n      }\n      default:\n        break;\n    }\n    \n    if (OverwriteMode == NExtract::NOverwriteMode::kRename)\n    {\n      if (!AutoRenamePath(destPathSys))\n      {\n        RINOK(MessageError(\"Cannot create name for file\", destPathSys))\n        return E_ABORT;\n      }\n      destPathResultTemp = fs2us(destPathSys);\n    }\n    else\n    {\n      if (NFind::DoesFileExist_Raw(destPathSys))\n      if (!NDir::DeleteFileAlways(destPathSys))\n      if (GetLastError() != ERROR_FILE_NOT_FOUND)\n      {\n        RINOK(MessageError(\"Cannot delete output file\", destPathSys))\n        return E_ABORT;\n      }\n    }\n  }\n  *writeAnswer = BoolToInt(true);\n  return StringToBstr(destPathResultTemp, destPathResult);\n}\n\n\nZ7_COM7F_IMF(CExtractCallbackImp::UseExtractToStream(Int32 *res))\n{\n  *res = BoolToInt(StreamMode);\n  return S_OK;\n}\n\nstatic HRESULT GetTime(IGetProp *getProp, PROPID propID, FILETIME &ft, bool &ftDefined)\n{\n  ftDefined = false;\n  NCOM::CPropVariant prop;\n  RINOK(getProp->GetProp(propID, &prop))\n  if (prop.vt == VT_FILETIME)\n  {\n    ft = prop.filetime;\n    ftDefined = (ft.dwHighDateTime != 0 || ft.dwLowDateTime != 0);\n  }\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\n\nstatic HRESULT GetItemBoolProp(IGetProp *getProp, PROPID propID, bool &result)\n{\n  NCOM::CPropVariant prop;\n  result = false;\n  RINOK(getProp->GetProp(propID, &prop))\n  if (prop.vt == VT_BOOL)\n    result = VARIANT_BOOLToBool(prop.boolVal);\n  else if (prop.vt != VT_EMPTY)\n    return E_FAIL;\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CExtractCallbackImp::GetStream7(const wchar_t *name,\n    Int32 isDir,\n    ISequentialOutStream **outStream, Int32 askExtractMode,\n    IGetProp *getProp))\n{\n  COM_TRY_BEGIN\n  *outStream = NULL;\n  _newVirtFileWasAdded = false;\n  _hashStream_WasUsed = false;\n  _needUpdateStat = false;\n  _isFolder = IntToBool(isDir);\n  _curSize_Defined = false;\n  _curSize = 0;\n\n  if (_hashStream)\n    _hashStream->ReleaseStream();\n\n  _filePath = name;\n\n  UInt64 size = 0;\n  bool size_Defined;\n  {\n    NCOM::CPropVariant prop;\n    RINOK(getProp->GetProp(kpidSize, &prop))\n    size_Defined = ConvertPropVariantToUInt64(prop, size);\n  }\n  if (size_Defined)\n  {\n    _curSize = size;\n    _curSize_Defined = true;\n  }\n\n  GetItemBoolProp(getProp, kpidIsAltStream, _isAltStream);\n  if (!ProcessAltStreams && _isAltStream)\n    return S_OK;\n\n  if (isDir) // we don't support dir items extraction in this code\n    return S_OK;\n\n  if (askExtractMode != NArchive::NExtract::NAskMode::kExtract &&\n      askExtractMode != NArchive::NExtract::NAskMode::kTest)\n    return S_OK;\n\n  _needUpdateStat = true;\n  \n  CMyComPtr<ISequentialOutStream> outStreamLoc;\n  \n  if (VirtFileSystem && askExtractMode == NArchive::NExtract::NAskMode::kExtract)\n  {\n    if (!VirtFileSystemSpec->Files.IsEmpty())\n      VirtFileSystemSpec->MaxTotalAllocSize -= VirtFileSystemSpec->Files.Back().Data.Size();\n    CVirtFile &file = VirtFileSystemSpec->Files.AddNew();\n    _newVirtFileWasAdded = true;\n    // file.IsDir = _isFolder;\n    file.IsAltStream = _isAltStream;\n    file.WrittenSize = 0;\n    file.ExpectedSize = 0;\n    if (size_Defined)\n      file.ExpectedSize = size;\n\n    if (VirtFileSystemSpec->Index_of_MainExtractedFile_in_Files < 0)\n      if (!file.IsAltStream || VirtFileSystemSpec->IsAltStreamFile)\n        VirtFileSystemSpec->Index_of_MainExtractedFile_in_Files =\n            (int)(VirtFileSystemSpec->Files.Size() - 1);\n\n    /* if we open only AltStream, then (name) contains only name without \"fileName:\" prefix */\n    file.BaseName = name;\n\n    if (file.IsAltStream\n        && !VirtFileSystemSpec->IsAltStreamFile\n        && file.BaseName.IsPrefixedBy_NoCase(VirtFileSystemSpec->FileName))\n    {\n      const unsigned colonPos = VirtFileSystemSpec->FileName.Len();\n      if (file.BaseName[colonPos] == ':')\n      {\n        file.ColonWasUsed = true;\n        file.AltStreamName = name + (size_t)colonPos + 1;\n        file.BaseName.DeleteFrom(colonPos);\n        if (Is_ZoneId_StreamName(file.AltStreamName))\n        {\n          if (VirtFileSystemSpec->Index_of_ZoneBuf_AltStream_in_Files < 0)\n            VirtFileSystemSpec->Index_of_ZoneBuf_AltStream_in_Files =\n              (int)(VirtFileSystemSpec->Files.Size() - 1);\n        }\n      }\n    }\n    RINOK(GetTime(getProp, kpidCTime, file.CTime, file.CTime_Defined))\n    RINOK(GetTime(getProp, kpidATime, file.ATime, file.ATime_Defined))\n    RINOK(GetTime(getProp, kpidMTime, file.MTime, file.MTime_Defined))\n    {\n      NCOM::CPropVariant prop;\n      RINOK(getProp->GetProp(kpidAttrib, &prop))\n      if (prop.vt == VT_UI4)\n      {\n        file.Attrib = prop.ulVal;\n        file.Attrib_Defined = true;\n      }\n    }\n    outStreamLoc = VirtFileSystem;\n  }\n\n  if (_hashStream)\n  {\n    _hashStream->SetStream(outStreamLoc);\n    outStreamLoc = _hashStream;\n    _hashStream->Init(true);\n    _hashStream_WasUsed = true;\n  }\n\n  if (outStreamLoc)\n    *outStream = outStreamLoc.Detach();\n  return S_OK;\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::PrepareOperation7(Int32 askExtractMode))\n{\n  COM_TRY_BEGIN\n  _needUpdateStat = (\n         askExtractMode == NArchive::NExtract::NAskMode::kExtract\n      || askExtractMode == NArchive::NExtract::NAskMode::kTest\n      || askExtractMode == NArchive::NExtract::NAskMode::kReadExternal\n      );\n\n  /*\n  _extractMode = false;\n  switch (askExtractMode)\n  {\n    case NArchive::NExtract::NAskMode::kExtract:\n      if (_testMode)\n        askExtractMode = NArchive::NExtract::NAskMode::kTest;\n      else\n        _extractMode = true;\n      break;\n  };\n  */\n  return SetCurrentFilePath2(_filePath);\n  COM_TRY_END\n}\n\nZ7_COM7F_IMF(CExtractCallbackImp::SetOperationResult8(Int32 opRes, Int32 encrypted, UInt64 size))\n{\n  COM_TRY_BEGIN\n  if (VirtFileSystem && _newVirtFileWasAdded)\n  {\n    // FIXME: probably we must request file size from VirtFileSystem\n    // _curSize = VirtFileSystem->GetLastFileSize()\n    // _curSize_Defined = true;\n    RINOK(VirtFileSystemSpec->CloseMemFile())\n  }\n  if (_hashStream && _hashStream_WasUsed)\n  {\n    _hashStream->_hash->Final(_isFolder, _isAltStream, _filePath);\n    _curSize = _hashStream->GetSize();\n    _curSize_Defined = true;\n    _hashStream->ReleaseStream();\n    _hashStream_WasUsed = false;\n  }\n  else if (_hashCalc && _needUpdateStat)\n  {\n    _hashCalc->SetSize(size); // (_curSize) before 21.04\n    _hashCalc->Final(_isFolder, _isAltStream, _filePath);\n  }\n  return SetOperationResult(opRes, encrypted);\n  COM_TRY_END\n}\n\n\nZ7_COM7F_IMF(CExtractCallbackImp::RequestMemoryUse(\n    UInt32 flags, UInt32 indexType, UInt32 /* index */, const wchar_t *path,\n    UInt64 requiredSize, UInt64 *allowedSize, UInt32 *answerFlags))\n{\n  UInt32 limit_GB = (UInt32)((*allowedSize + ((1u << 30) - 1)) >> 30);\n\n  if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)\n  {\n    UInt64 limit_bytes = *allowedSize;\n    const UInt32 limit_GB_Registry = NExtract::Read_LimitGB();\n    if (limit_GB_Registry != 0 && limit_GB_Registry != (UInt32)(Int32)-1)\n    {\n      const UInt64 limit_bytes_Registry = (UInt64)limit_GB_Registry << 30;\n      // registry_WasForced = true;\n      if ((flags & NRequestMemoryUseFlags::k_AllowedSize_WasForced) == 0\n          || limit_bytes < limit_bytes_Registry)\n      {\n        limit_bytes = limit_bytes_Registry;\n        limit_GB = limit_GB_Registry;\n      }\n    }\n    *allowedSize = limit_bytes;\n    if (requiredSize <= limit_bytes)\n    {\n      *answerFlags = NRequestMemoryAnswerFlags::k_Allow;\n      return S_OK;\n    }\n    // default answer can be k_Allow, if limit was not forced,\n    // so we change answer to non-allowed here,\n    // because user has chance to change limit in GUI.\n    *answerFlags = NRequestMemoryAnswerFlags::k_Limit_Exceeded;\n    if (flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected)\n      *answerFlags |= NRequestMemoryAnswerFlags::k_SkipArc;\n  }\n\n  const UInt32 required_GB = (UInt32)((requiredSize + ((1u << 30) - 1)) >> 30);\n\n  CMemDialog dialog;\n  dialog.Limit_GB = limit_GB;\n  dialog.Required_GB = required_GB;\n  dialog.TestMode = TestMode;\n  if (MultiArcMode)\n    dialog.ArcPath = _currentArchivePath;\n  if (path)\n    dialog.FilePath = path;\n  \n  if (!g_DisableUserQuestions\n      && (flags & NRequestMemoryUseFlags::k_IsReport) == 0)\n  {\n    if (_remember)\n      dialog.SkipArc = _skipArc;\n    else\n    {\n      dialog.ShowRemember =\n        (MultiArcMode\n          || indexType != NArchive::NEventIndexType::kNoIndex\n          || path);\n      ProgressDialog->WaitCreating();\n      if (dialog.Create(*ProgressDialog) != IDCONTINUE)\n      {\n        *answerFlags = NRequestMemoryAnswerFlags::k_Stop;\n        return E_ABORT;\n      }\n      if (dialog.NeedSave)\n        NExtract::Save_LimitGB(dialog.Limit_GB);\n      if (dialog.Remember)\n      {\n        _remember = true;\n        _skipArc = dialog.SkipArc;\n      }\n    }\n    \n    *allowedSize = (UInt64)dialog.Limit_GB << 30;\n    if (!dialog.SkipArc)\n    {\n      *answerFlags = NRequestMemoryAnswerFlags::k_Allow;\n      return S_OK;\n    }\n    *answerFlags =\n        NRequestMemoryAnswerFlags::k_SkipArc\n      | NRequestMemoryAnswerFlags::k_Limit_Exceeded;\n    flags |= NRequestMemoryUseFlags::k_Report_SkipArc;\n  }\n  \n  if ((flags & NRequestMemoryUseFlags::k_NoErrorMessage) == 0)\n  {\n    UString s (\"ERROR: \");\n    dialog.AddInfoMessage_To_String(s);\n    s.Add_LF();\n    // if (indexType == NArchive::NEventIndexType::kNoIndex)\n    if ((flags & NRequestMemoryUseFlags::k_SkipArc_IsExpected) ||\n        (flags & NRequestMemoryUseFlags::k_Report_SkipArc))\n      AddLangString(s, IDS_MSG_ARC_UNPACKING_WAS_SKIPPED);\n/*\n    else\n      AddLangString(, IDS_MSG_ARC_FILES_UNPACKING_WAS_SKIPPED);\n*/\n    AddError_Message_ShowArcPath(s);\n  }\n  \n/*\n  if ((flags & NRequestMemoryUseFlags::k_IsReport) == 0)\n    *answerFlags |= NRequestMemoryAnswerFlags::k_Limit_Exceeded;\n*/\n  return S_OK;\n}\n\n\nZ7_COM7F_IMF(CVirtFileSystem::Write(const void *data, UInt32 size, UInt32 *processedSize))\n{\n  if (processedSize)\n    *processedSize = 0;\n  if (size == 0)\n    return S_OK;\n  if (!_wasSwitchedToFsMode)\n  {\n    CVirtFile &file = Files.Back();\n    const size_t rem = file.Data.Size() - file.WrittenSize;\n    bool useMem = true;\n    if (rem < size)\n    {\n      UInt64 b = 0;\n      if (file.Data.Size() == 0)\n        b = file.ExpectedSize;\n      UInt64 a = (UInt64)file.WrittenSize + size;\n      if (b < a)\n        b = a;\n      a = (UInt64)file.Data.Size() * 2;\n      if (b < a)\n        b = a;\n      useMem = false;\n      if (b <= MaxTotalAllocSize)\n        useMem = file.Data.ReAlloc_KeepData((size_t)b, file.WrittenSize);\n    }\n\n#if 0 // 1 for debug : FLUSHING TO FS\n    useMem = false;\n#endif\n\n    if (useMem)\n    {\n      memcpy(file.Data + file.WrittenSize, data, size);\n      file.WrittenSize += size;\n      if (processedSize)\n        *processedSize = (UInt32)size;\n      return S_OK;\n    }\n    _wasSwitchedToFsMode = true;\n  }\n  \n  if (!_newVirtFileStream_IsReadyToWrite) // we check for _newVirtFileStream_IsReadyToWrite to optimize execution\n  {\n    RINOK(FlushToDisk(false))\n  }\n\n  if (_needWriteToRealFile)\n    return _outFileStream.Interface()->Write(data, size, processedSize);\n  if (processedSize)\n    *processedSize = size;\n  return S_OK;\n}\n\n\nHRESULT CVirtFileSystem::FlushToDisk(bool closeLast)\n{\n  while (_numFlushed < Files.Size())\n  {\n    CVirtFile &file = Files[_numFlushed];\n    const FString basePath = DirPrefix + us2fs(Get_Correct_FsFile_Name(file.BaseName));\n    FString path = basePath;\n\n    if (file.ColonWasUsed)\n    {\n      if (ZoneBuf.Size() != 0\n          && Is_ZoneId_StreamName(file.AltStreamName))\n      {\n        // it's expected that\n        // CArchiveExtractCallback::GetStream() have excluded\n        // ZoneId alt stream from extraction already.\n        // But we exclude alt stream extraction here too.\n        _numFlushed++;\n        continue;\n      }\n      path.Add_Colon();\n      path += us2fs(Get_Correct_FsFile_Name(file.AltStreamName));\n    }\n\n    if (!_newVirtFileStream_IsReadyToWrite)\n    {\n      if (file.ColonWasUsed)\n      {\n        NFind::CFileInfo parentFi;\n        if (parentFi.Find(basePath)\n            && parentFi.IsReadOnly())\n        {\n          _altStream_NeedRestore_Attrib_bool = true;\n          _altStream_NeedRestore_AttribVal = parentFi.Attrib;\n          NDir::SetFileAttrib(basePath, parentFi.Attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY);\n        }\n      }\n      _outFileStream.Create_if_Empty();\n      _needWriteToRealFile = _outFileStream->Create_NEW(path);\n      if (!_needWriteToRealFile)\n      {\n        if (!file.ColonWasUsed)\n          return GetLastError_noZero_HRESULT(); // it's main file and we can't ignore such error.\n        // (file.ColonWasUsed == true)\n        // So it's additional alt stream.\n        // And we ignore file creation error for additional alt stream.\n        // ShowErrorMessage(UString(\"Can't create file \") + fs2us(path));\n      }\n      _newVirtFileStream_IsReadyToWrite = true;\n      // _openFilePath = path;\n      HRESULT hres = S_OK;\n      if (_needWriteToRealFile)\n        hres = WriteStream(_outFileStream, file.Data, file.WrittenSize);\n      // we free allocated memory buffer after data flushing:\n      file.WrittenSize = 0;\n      file.Data.Free();\n      RINOK(hres)\n    }\n    \n    if (_numFlushed == Files.Size() - 1 && !closeLast)\n      break;\n    \n    if (_needWriteToRealFile)\n    {\n      if (file.CTime_Defined ||\n          file.ATime_Defined ||\n          file.MTime_Defined)\n        _outFileStream->SetTime(\n          file.CTime_Defined ? &file.CTime : NULL,\n          file.ATime_Defined ? &file.ATime : NULL,\n          file.MTime_Defined ? &file.MTime : NULL);\n      _outFileStream->Close();\n    }\n    \n    _numFlushed++;\n    _newVirtFileStream_IsReadyToWrite = false;\n\n    if (_needWriteToRealFile)\n    {\n      if (!file.ColonWasUsed\n          && ZoneBuf.Size() != 0)\n        WriteZoneFile_To_BaseFile(path, ZoneBuf);\n      if (file.Attrib_Defined)\n        NDir::SetFileAttrib_PosixHighDetect(path, file.Attrib);\n      // _openFilePath.Empty();\n      _needWriteToRealFile = false;\n    }\n      \n    if (_altStream_NeedRestore_Attrib_bool)\n    {\n      _altStream_NeedRestore_Attrib_bool = false;\n      NDir::SetFileAttrib(basePath, _altStream_NeedRestore_AttribVal);\n    }\n  }\n  return S_OK;\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ExtractCallback.h",
    "content": "﻿// ExtractCallback.h\n\n#ifndef ZIP7_INC_EXTRACT_CALLBACK_H\n#define ZIP7_INC_EXTRACT_CALLBACK_H\n\n#include \"../../../../C/Alloc.h\"\n\n#include \"../../../Common/MyCom.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#ifndef Z7_SFX\n#include \"../Agent/IFolderArchive.h\"\n#endif\n\n#include \"../Common/ArchiveExtractCallback.h\"\n#include \"../Common/ArchiveOpenCallback.h\"\n// **************** NanaZip Modification Start ****************\n#include \"../Common/Extract.h\"\n// **************** NanaZip Modification End ****************\n\n#ifndef Z7_NO_CRYPTO\n#include \"../../IPassword.h\"\n#endif\n\n#ifndef Z7_SFX\n#include \"IFolder.h\"\n#endif\n\n#include \"ProgressDialog2.h\"\n\n#ifndef Z7_SFX\n\nclass CGrowBuf\n{\n  Byte *_items;\n  size_t _size;\n\n  Z7_CLASS_NO_COPY(CGrowBuf)\n\npublic:\n  void Free()\n  {\n    MyFree(_items);\n    _items = NULL;\n    _size = 0;\n  }\n\n  // newSize >= keepSize\n  bool ReAlloc_KeepData(size_t newSize, size_t keepSize)\n  {\n    void *buf = NULL;\n    if (newSize)\n    {\n      buf = MyAlloc(newSize);\n      if (!buf)\n        return false;\n    }\n    if (keepSize)\n      memcpy(buf, _items, keepSize);\n    MyFree(_items);\n    _items = (Byte *)buf;\n    _size = newSize;\n    return true;\n  }\n\n  CGrowBuf(): _items(NULL), _size(0) {}\n  ~CGrowBuf() { MyFree(_items); }\n\n  operator Byte *() { return _items; }\n  operator const Byte *() const { return _items; }\n  size_t Size() const { return _size; }\n};\n\n\nstruct CVirtFile\n{\n  CGrowBuf Data;\n  \n  UInt64 ExpectedSize; // size from props request. 0 if unknown\n  size_t WrittenSize;  // size of written data in (Data) buffer\n                       //   use (WrittenSize) only if (CVirtFileSystem::_newVirtFileStream_IsReadyToWrite == false)\n  UString BaseName;    // original name of file inside archive,\n                       // It's not path. So any path separators\n                       // should be treated as part of name (or as incorrect chars)\n  UString AltStreamName;\n\n  bool CTime_Defined;\n  bool ATime_Defined;\n  bool MTime_Defined;\n  bool Attrib_Defined;\n  \n  // bool IsDir;\n  bool IsAltStream;\n  bool ColonWasUsed;\n  DWORD Attrib;\n\n  FILETIME CTime;\n  FILETIME ATime;\n  FILETIME MTime;\n\n  CVirtFile():\n    CTime_Defined(false),\n    ATime_Defined(false),\n    MTime_Defined(false),\n    Attrib_Defined(false),\n    // IsDir(false),\n    IsAltStream(false),\n    ColonWasUsed(false)\n    {}\n};\n\n\n/*\n  We use CVirtFileSystem only for single file extraction:\n  It supports the following cases and names:\n     - \"fileName\" : single file\n     - \"fileName\" item (main base file) and additional \"fileName:altStream\" items\n     - \"altStream\" : single item without \"fileName:\" prefix.\n  If file is flushed to disk, it uses Get_Correct_FsFile_Name(name).\n*/\n \nZ7_CLASS_IMP_NOQIB_1(\n  CVirtFileSystem,\n  ISequentialOutStream\n)\n  unsigned _numFlushed;\npublic:\n  bool IsAltStreamFile; // in:\n      // = true,  if extracting file is alt stream without \"fileName:\" prefix.\n      // = false, if extracting file is normal file, but additional\n      //          alt streams \"fileName:altStream\" items are possible.\nprivate:\n  bool _newVirtFileStream_IsReadyToWrite;    // it can non real file (if can't open alt stream)\n  bool _needWriteToRealFile;  // we need real writing to open file.\n  bool _wasSwitchedToFsMode;\n  bool _altStream_NeedRestore_Attrib_bool;\n  DWORD _altStream_NeedRestore_AttribVal;\n\n  CMyComPtr2<ISequentialOutStream, COutFileStream> _outFileStream;\npublic:\n  CObjectVector<CVirtFile> Files;\n  size_t MaxTotalAllocSize; // remain size, including Files.Back()\n  FString DirPrefix; // files will be flushed to this FS directory.\n  UString FileName; // name of file that will be extracted.\n                    // it can be name of alt stream without \"fileName:\" prefix, if (IsAltStreamFile == trye).\n                    // we use that name to detect altStream part in \"FileName:altStream\".\n  CByteBuffer ZoneBuf;\n  int Index_of_MainExtractedFile_in_Files; // out: index in Files. == -1, if expected file was not extracted\n  int Index_of_ZoneBuf_AltStream_in_Files; // out: index in Files. == -1, if no zonbuf alt stream\n  \n\n  CVirtFileSystem()\n  {\n    _numFlushed = 0;\n    IsAltStreamFile = false;\n    _newVirtFileStream_IsReadyToWrite = false;\n    _needWriteToRealFile = false;\n    _wasSwitchedToFsMode = false;\n    _altStream_NeedRestore_Attrib_bool = false;\n    MaxTotalAllocSize = (size_t)0 - 1;\n    Index_of_MainExtractedFile_in_Files = -1;\n    Index_of_ZoneBuf_AltStream_in_Files = -1;\n  }\n\n  bool WasStreamFlushedToFS() const { return _wasSwitchedToFsMode; }\n\n  HRESULT CloseMemFile()\n  {\n    if (_wasSwitchedToFsMode)\n      return FlushToDisk(true); // closeLast\n    CVirtFile &file = Files.Back();\n    if (file.Data.Size() != file.WrittenSize)\n      file.Data.ReAlloc_KeepData(file.WrittenSize, file.WrittenSize);\n    return S_OK;\n  }\n\n  HRESULT FlushToDisk(bool closeLast);\n};\n\n#endif\n  \n\n\nclass CExtractCallbackImp Z7_final:\n  public IFolderArchiveExtractCallback,\n  /* IExtractCallbackUI:\n       before v23.00 : it         included IFolderArchiveExtractCallback\n       since  v23.00 : it doesn't include  IFolderArchiveExtractCallback\n  */\n  public IExtractCallbackUI, // NON-COM interface since 23.00\n  public IOpenCallbackUI,    // NON-COM interface\n  public IFolderArchiveExtractCallback2,\n #ifndef Z7_SFX\n  public IFolderOperationsExtractCallback,\n  public IFolderExtractToStreamCallback,\n  public ICompressProgressInfo,\n  public IArchiveRequestMemoryUseCallback,\n #endif\n #ifndef Z7_NO_CRYPTO\n  public ICryptoGetTextPassword,\n #endif\n  public CMyUnknownImp\n{\n  Z7_COM_QI_BEGIN2(IFolderArchiveExtractCallback)\n  Z7_COM_QI_ENTRY(IFolderArchiveExtractCallback2)\n #ifndef Z7_SFX\n  Z7_COM_QI_ENTRY(IFolderOperationsExtractCallback)\n  Z7_COM_QI_ENTRY(IFolderExtractToStreamCallback)\n  Z7_COM_QI_ENTRY(ICompressProgressInfo)\n  Z7_COM_QI_ENTRY(IArchiveRequestMemoryUseCallback)\n #endif\n #ifndef Z7_NO_CRYPTO\n  Z7_COM_QI_ENTRY(ICryptoGetTextPassword)\n #endif\n  Z7_COM_QI_END\n  Z7_COM_ADDREF_RELEASE\n\n  Z7_IFACE_IMP(IExtractCallbackUI)\n  Z7_IFACE_IMP(IOpenCallbackUI)\n  Z7_IFACE_COM7_IMP(IProgress)\n  Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback)\n  Z7_IFACE_COM7_IMP(IFolderArchiveExtractCallback2)\n #ifndef Z7_SFX\n  Z7_IFACE_COM7_IMP(IFolderOperationsExtractCallback)\n  Z7_IFACE_COM7_IMP(IFolderExtractToStreamCallback)\n  Z7_IFACE_COM7_IMP(ICompressProgressInfo)\n  Z7_IFACE_COM7_IMP(IArchiveRequestMemoryUseCallback)\n #endif\n #ifndef Z7_NO_CRYPTO\n  Z7_IFACE_COM7_IMP(ICryptoGetTextPassword)\n #endif\n\n  bool _needWriteArchivePath;\n  bool _isFolder;\n  bool _totalFiles_Defined;\n  bool _totalBytes_Defined;\npublic:\n  bool MultiArcMode;\n  bool ProcessAltStreams;\n  bool StreamMode; // set to true, if you want the callee to call GetStream7()\n  bool ThereAreMessageErrors;\n  bool Src_Is_IO_FS_Folder;\n\n#ifndef Z7_NO_CRYPTO\n  bool PasswordIsDefined;\n  bool PasswordWasAsked;\n#endif\n\nprivate:\n#ifndef Z7_SFX\n  bool _needUpdateStat;\n  bool _newVirtFileWasAdded;\n  bool _isAltStream;\n  // bool _extractMode;\n  // bool _testMode;\n  bool _hashStream_WasUsed;\n  bool _curSize_Defined;\n  bool NeedAddFile;\n\n  bool _remember;\n  bool _skipArc;\n#endif\n\npublic:\n  bool YesToAll;\n  bool TestMode;\n\n  UInt32 NumArchiveErrors;\n  NExtract::NOverwriteMode::EEnum OverwriteMode;\n\nprivate:\n  UString _currentArchivePath;\n  UString _currentFilePath;\n  UString _filePath;  // virtual path than will be sent via IFolderExtractToStreamCallback\n\n#ifndef Z7_SFX\n  UInt64 _curSize;\n  CMyComPtr2<ISequentialOutStream, COutStreamWithHash> _hashStream;\n  IHashCalc *_hashCalc; // it's for stat in Test operation\n#endif\n\npublic:\n  CProgressDialog *ProgressDialog;\n\n#ifndef Z7_SFX\n  CVirtFileSystem *VirtFileSystemSpec;\n  CMyComPtr<ISequentialOutStream> VirtFileSystem;\n  UInt64 NumFolders;\n  UInt64 NumFiles;\n#endif\n\n  // **************** NanaZip Modification Start ****************\n  CDecompressStat Stat;\n  // **************** NanaZip Modification End ****************\n\n#ifndef Z7_NO_CRYPTO\n  UString Password;\n#endif\n\n  UString _lang_Extracting;\n  UString _lang_Testing;\n  UString _lang_Skipping;\n  UString _lang_Reading;\n  UString _lang_Empty;\n\n  CExtractCallbackImp():\n      _totalFiles_Defined(false)\n    , _totalBytes_Defined(false)\n    , MultiArcMode(false)\n    , ProcessAltStreams(true)\n    , StreamMode(false)\n    , ThereAreMessageErrors(false)\n    , Src_Is_IO_FS_Folder(false)\n#ifndef Z7_NO_CRYPTO\n    , PasswordIsDefined(false)\n    , PasswordWasAsked(false)\n#endif\n#ifndef Z7_SFX\n    , _remember(false)\n    , _skipArc(false)\n#endif\n    , YesToAll(false)\n    , TestMode(false)\n    , OverwriteMode(NExtract::NOverwriteMode::kAsk)\n#ifndef Z7_SFX\n    , _hashCalc(NULL)\n#endif\n    {}\n   \n  ~CExtractCallbackImp();\n  void Init();\n\n  HRESULT SetCurrentFilePath2(const wchar_t *filePath);\n  void AddError_Message(LPCWSTR message);\n  void AddError_Message_ShowArcPath(LPCWSTR message);\n  HRESULT MessageError(const char *message, const FString &path);\n  void Add_ArchiveName_Error();\n\n  #ifndef Z7_SFX\n  void SetHashCalc(IHashCalc *hashCalc) { _hashCalc = hashCalc; }\n\n  void SetHashMethods(IHashCalc *hash)\n  {\n    if (!hash)\n      return;\n    _hashStream.Create_if_Empty();\n    _hashStream->_hash = hash;\n  }\n  #endif\n\n  bool IsOK() const { return NumArchiveErrors == 0 && !ThereAreMessageErrors; }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/FormatUtils.cpp",
    "content": "﻿// FormatUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n\n#include \"FormatUtils.h\"\n\n#include \"LangUtils.h\"\n\nUString NumberToString(UInt64 number)\n{\n  wchar_t numberString[32];\n  ConvertUInt64ToString(number, numberString);\n  return numberString;\n}\n\nUString MyFormatNew(const UString &format, const UString &argument)\n{\n  UString result = format;\n  result.Replace(L\"{0}\", argument);\n  return result;\n}\n\nUString MyFormatNew(UINT resourceID, const UString &argument)\n{\n  return MyFormatNew(LangString(resourceID), argument);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/FormatUtils.h",
    "content": "﻿// FormatUtils.h\n\n#ifndef ZIP7_INC_FORMAT_UTILS_H\n#define ZIP7_INC_FORMAT_UTILS_H\n\n#include \"../../../Common/MyTypes.h\"\n#include \"../../../Common/MyString.h\"\n\nUString NumberToString(UInt64 number);\n\nUString MyFormatNew(const UString &format, const UString &argument);\nUString MyFormatNew(UINT resourceID, const UString &argument);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/LangUtils.cpp",
    "content": "﻿// LangUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/Lang.h\"\n\n#include \"../../../Windows/DLL.h\"\n#include \"../../../Windows/Synchronization.h\"\n#include \"../../../Windows/Window.h\"\n\n#include \"LangUtils.h\"\n#include \"RegistryUtils.h\"\n\nusing namespace NWindows;\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nUString g_LangID;\n\n// static\nCLang g_Lang;\nstatic bool g_Loaded = false;\nstatic NSynchronization::CCriticalSection g_CriticalSection;\n\nbool LangOpen(CLang &lang, CFSTR fileName);\nbool LangOpen(CLang &lang, CFSTR fileName)\n{\n  // **************** NanaZip Modification Start ****************\n  //return lang.Open(fileName, \"7-Zip\");\n  return lang.Open(fileName, \"NanaZip\");\n  // **************** NanaZip Modification End ****************\n}\n\nFString GetLangDirPrefix()\n{\n  // **************** NanaZip Modification Start ****************\n  //return NDLL::GetModuleDirPrefix() + FTEXT(\"Lang\") FSTRING_PATH_SEPARATOR;\n#ifdef Z7_SFX\n  return L\"\";\n#else\n  return NDLL::GetModuleDirPrefix() + FTEXT(\"Lang\") FSTRING_PATH_SEPARATOR;\n#endif\n  // **************** NanaZip Modification End ****************\n}\n\n#ifdef Z7_LANG\n\nvoid LoadLangOneTime()\n{\n  NSynchronization::CCriticalSectionLock lock(g_CriticalSection);\n  if (g_Loaded)\n    return;\n  g_Loaded = true;\n  ReloadLang();\n}\n\nvoid LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID)\n{\n  const wchar_t *s = g_Lang.Get(langID);\n  if (s)\n  {\n    CWindow window(GetDlgItem(dialog, (int)controlID));\n    window.SetText(s);\n  }\n}\n\n#ifndef IDCONTINUE\n#define IDCONTINUE 11\n#endif\n\nstatic const CIDLangPair kLangPairs[] =\n{\n  { IDOK,     401 },\n  { IDCANCEL, 402 },\n  { IDYES,    406 },\n  { IDNO,     407 },\n  { IDCLOSE,  408 },\n  // **************** NanaZip Modification Start ****************\n  //{ IDHELP,   409 },\n  // **************** NanaZip Modification End ****************\n  { IDCONTINUE, 411 }\n};\n\n\nvoid LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems)\n{\n  unsigned i;\n  for (i = 0; i < Z7_ARRAY_SIZE(kLangPairs); i++)\n  {\n    const CIDLangPair &pair = kLangPairs[i];\n    CWindow window(GetDlgItem(dialog, (int)pair.ControlID));\n    if (window)\n    {\n      const wchar_t *s = g_Lang.Get(pair.LangID);\n      if (s)\n        window.SetText(s);\n    }\n  }\n\n  for (i = 0; i < numItems; i++)\n  {\n    const UInt32 id = ids[i];\n    LangSetDlgItemText(dialog, id, id);\n  }\n}\n\nvoid LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems)\n{\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    const UInt32 id = ids[i];\n    const wchar_t *s = g_Lang.Get(id);\n    if (s)\n    {\n      CWindow window(GetDlgItem(dialog, (int)id));\n      UString s2 = s;\n      s2.Add_Colon();\n      window.SetText(s2);\n    }\n  }\n}\n\nvoid LangSetDlgItems_RemoveColon(HWND dialog, const UInt32 *ids, unsigned numItems)\n{\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    const UInt32 id = ids[i];\n    const wchar_t *s = g_Lang.Get(id);\n    if (s)\n    {\n      CWindow window(GetDlgItem(dialog, (int)id));\n      UString s2 = s;\n      if (!s2.IsEmpty() && s2.Back() == ':')\n        s2.DeleteBack();\n      window.SetText(s2);\n    }\n  }\n}\n\nvoid LangSetWindowText(HWND window, UInt32 langID)\n{\n  const wchar_t *s = g_Lang.Get(langID);\n  if (s)\n    MySetWindowText(window, s);\n}\n\nUString LangString(UInt32 langID)\n{\n  const wchar_t *s = g_Lang.Get(langID);\n  if (s)\n    return s;\n  return MyLoadString(langID);\n}\n\nvoid AddLangString(UString &s, UInt32 langID)\n{\n  s += LangString(langID);\n}\n\nvoid LangString(UInt32 langID, UString &dest)\n{\n  const wchar_t *s = g_Lang.Get(langID);\n  if (s)\n  {\n    dest = s;\n    return;\n  }\n  MyLoadString(langID, dest);\n}\n\nvoid LangString_OnlyFromLangFile(UInt32 langID, UString &dest)\n{\n  dest.Empty();\n  const wchar_t *s = g_Lang.Get(langID);\n  if (s)\n    dest = s;\n}\n\nstatic const char * const kLangs =\n  \"ar.bg.ca.zh.-tw.-cn.cs.da.de.el.en.es.fi.fr.he.hu.is.\"\n  \"it.ja.ko.nl.no.=nb.=nn.pl.pt.-br.rm.ro.ru.sr.=hr.-spl.-spc.=hr.=bs.sk.sq.sv.th.tr.\"\n  \"ur.id.uk.be.sl.et.lv.lt.tg.fa.vi.hy.az.eu.hsb.mk.\"\n  \"st.ts.tn.ve.xh.zu.af.ka.fo.hi.mt.se.ga.yi.ms.kk.\"\n  \"ky.sw.tk.uz.-latn.-cyrl.tt.bn.pa.-in.gu.or.ta.te.kn.ml.as.mr.sa.\"\n  \"mn.=mn.=mng.bo.cy.kh.lo.my.gl.kok..sd.syr.si..iu.am.tzm.\"\n  \"ks.ne.fy.ps.tl.dv..ff.ha..yo.qu.st.ba.lb.kl.\"\n  \"ig.kr.om.ti.gn..la.so.ii..arn..moh..br..\"\n  \"ug.mi.oc.co.\"\n  // \"gsw.sah.qut.rw.wo....prs....\"\n  // \".gd.\"\n  ;\n\nstatic void FindShortNames(UInt32 primeLang, AStringVector &names)\n{\n  UInt32 index = 0;\n  for (const char *p = kLangs; *p != 0;)\n  {\n    const char *p2 = p;\n    for (; *p2 != '.'; p2++);\n    bool isSub = (p[0] == '-' || p[0] == '=');\n    if (!isSub)\n      index++;\n    if (index >= primeLang)\n    {\n      if (index > primeLang)\n        break;\n      AString s;\n      if (isSub)\n      {\n        if (p[0] == '-')\n          s = names[0];\n        else\n          p++;\n      }\n      while (p != p2)\n        s.Add_Char((char)(Byte)*p++);\n      names.Add(s);\n    }\n    p = p2 + 1;\n  }\n}\n\n/*\n#include \"../../../Common/IntToString.h\"\n\nstatic struct CC1Lang\n{\n  CC1Lang()\n  {\n    for (int i = 1; i < 150; i++)\n    {\n      UString s;\n      char ttt[32];\n      ConvertUInt32ToHex(i, ttt);\n      s += ttt;\n      UStringVector names;\n      FindShortNames(i, names);\n\n      FOR_VECTOR (k, names)\n      {\n        s.Add_Space();\n        s += names[k];\n      }\n      OutputDebugStringW(s);\n    }\n  }\n} g_cc1;\n*/\n\n// typedef LANGID (WINAPI *GetUserDefaultUILanguageP)();\n\nvoid Lang_GetShortNames_for_DefaultLang(AStringVector &names, unsigned &subLang)\n{\n  names.Clear();\n  subLang = 0;\n  // Region / Administative / Language for non-Unicode programs:\n  const LANGID sysLang = GetSystemDefaultLangID();\n\n  // Region / Formats / Format:\n  const LANGID userLang = GetUserDefaultLangID();\n\n  if (PRIMARYLANGID(sysLang) !=\n      PRIMARYLANGID(userLang))\n    return;\n  const LANGID langID = userLang;\n\n  // const LANGID langID = MAKELANGID(0x1a, 1); // for debug\n  \n  /*\n  LANGID sysUILang; // english  in XP64\n  LANGID userUILang; // english  in XP64\n\n  GetUserDefaultUILanguageP fn = (GetUserDefaultUILanguageP)GetProcAddress(\n      GetModuleHandle(\"kernel32\"), \"GetUserDefaultUILanguage\");\n  if (fn)\n    userUILang = fn();\n  fn = (GetUserDefaultUILanguageP)GetProcAddress(\n      GetModuleHandle(\"kernel32\"), \"GetSystemDefaultUILanguage\");\n  if (fn)\n    sysUILang = fn();\n  */\n\n  const WORD primLang = (WORD)(PRIMARYLANGID(langID));\n  subLang = SUBLANGID(langID);\n  FindShortNames(primLang, names);\n}\n\n\nstatic void OpenDefaultLang()\n{\n  AStringVector names;\n  unsigned subLang;\n  Lang_GetShortNames_for_DefaultLang(names, subLang);\n  {\n    const FString dirPrefix (GetLangDirPrefix());\n    for (unsigned i = 0; i < 2; i++)\n    {\n      const unsigned index = (i == 0 ? subLang : 0);\n      if (index < names.Size())\n      {\n        const AString &name = names[index];\n        if (!name.IsEmpty())\n        {\n          FString path (dirPrefix);\n          path += name;\n          path += \".txt\";\n          if (LangOpen(g_Lang, path))\n          {\n            g_LangID = name;\n            return;\n          }\n        }\n      }\n    }\n  }\n}\n\nvoid ReloadLang()\n{\n  g_Lang.Clear();\n  // **************** NanaZip Modification Start ****************\n#ifndef Z7_SFX\n  // **************** NanaZip Modification End ****************\n  ReadRegLang(g_LangID);\n  // **************** NanaZip Modification Start ****************\n#endif // !Z7_SFX\n  // **************** NanaZip Modification End ****************\n  if (g_LangID.IsEmpty())\n  {\n#ifndef _UNICODE\n    if (g_IsNT)\n#endif\n      OpenDefaultLang();\n    return;\n  }\n  if (g_LangID.Len() > 1 || g_LangID[0] != L'-')\n  {\n    FString s = us2fs(g_LangID);\n    if (s.ReverseFind_PathSepar() < 0)\n    {\n      if (s.ReverseFind_Dot() < 0)\n        s += \".txt\";\n      s.Insert(0, GetLangDirPrefix());\n      LangOpen(g_Lang, s);\n    }\n  }\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/LangUtils.h",
    "content": "﻿// LangUtils.h\n\n#ifndef ZIP7_INC_LANG_UTILS_H\n#define ZIP7_INC_LANG_UTILS_H\n\n#include \"../../../Common/Lang.h\"\n\n#include \"../../../Windows/ResourceString.h\"\n\nextern UString g_LangID;\nextern CLang g_Lang;\n\n#ifdef Z7_LANG\n\nstruct CIDLangPair\n{\n  UInt32 ControlID;\n  UInt32 LangID;\n};\n\nvoid ReloadLang();\nvoid LoadLangOneTime();\n\nvoid LangSetDlgItemText(HWND dialog, UInt32 controlID, UInt32 langID);\nvoid LangSetDlgItems(HWND dialog, const UInt32 *ids, unsigned numItems);\nvoid LangSetDlgItems_Colon(HWND dialog, const UInt32 *ids, unsigned numItems);\nvoid LangSetDlgItems_RemoveColon(HWND dialog, const UInt32 *ids, unsigned numItems);\nvoid LangSetWindowText(HWND window, UInt32 langID);\n\nUString LangString(UInt32 langID);\nvoid AddLangString(UString &s, UInt32 langID);\nvoid LangString(UInt32 langID, UString &dest);\nvoid LangString_OnlyFromLangFile(UInt32 langID, UString &dest);\n \n#else\n\ninline UString LangString(UInt32 langID) { return NWindows::MyLoadString(langID); }\ninline void LangString(UInt32 langID, UString &dest) { NWindows::MyLoadString(langID, dest); }\ninline void AddLangString(UString &s, UInt32 langID) { s += NWindows::MyLoadString(langID); }\n\n#endif\n\nFString GetLangDirPrefix();\n// bool LangOpen(CLang &lang, CFSTR fileName);\n\nvoid Lang_GetShortNames_for_DefaultLang(AStringVector &names, unsigned &subLang);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/MemDialog.h",
    "content": "﻿// MemDialog.h\n\n#ifndef ZIP7_INC_MEM_DIALOG_H\n#define ZIP7_INC_MEM_DIALOG_H\n\n#include \"../../../Windows/Control/Dialog.h\"\n// #include \"../../../Windows/Control/ComboBox.h\"\n\n#include \"MemDialogRes.h\"\n\nclass CMemDialog: public NWindows::NControl::CModalDialog\n{\n  // NWindows::NControl::CComboBox m_Action;\n  // we can disable default OnOK() when we press Enter\n  // virtual void OnOK() Z7_override { }\n  virtual void OnContinue() Z7_override;\n  virtual bool OnInit() Z7_override;\n  virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;\n  void EnableSpin(bool enable);\n  // int AddAction(UINT id);\npublic:\n  bool NeedSave;\n  bool Remember;\n  bool SkipArc;\n  bool TestMode;\n  bool ShowRemember;\n  // bool ShowSkipFile;\n  UInt32 Required_GB;\n  UInt32 Limit_GB;\n  UString ArcPath;\n  UString FilePath;\n\n  void AddInfoMessage_To_String(UString &s, const UInt32 *ramSize_GB = NULL);\n  \n  CMemDialog():\n    NeedSave(false),\n    Remember(false),\n    SkipArc(false),\n    TestMode(false),\n    ShowRemember(true),\n    // ShowSkipFile(true),\n    Required_GB(4),\n    Limit_GB(4)\n    {}\n  INT_PTR Create(HWND parentWindow = NULL) { return CModalDialog::Create(IDD_MEM, parentWindow); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/MemDialogRes.h",
    "content": "﻿#define IDD_MEM                 7800\n\n#define IDX_MEM_SAVE_LIMIT      7801\n#define IDX_MEM_REMEMBER        7802\n#define IDG_MEM_ACTION          7803\n\n#define IDR_MEM_ACTION_ALLOW    7820\n#define IDR_MEM_ACTION_SKIP_ARC 7821\n\n#define IDT_MEM_MESSAGE         101\n#define IDE_MEM_SPIN_EDIT       110\n#define IDC_MEM_SPIN            111\n#define IDT_MEM_GB              112\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/MyWindowsNew.h",
    "content": "﻿// MyWindowsNew.h\n\n#ifndef ZIP7_INC_MY_WINDOWS_NEW_H\n#define ZIP7_INC_MY_WINDOWS_NEW_H\n\n#if defined(__MINGW32__) || defined(__MINGW64__) || defined(__MINGW32_VERSION)\n#include <shobjidl.h>\n\n#if defined(__MINGW32_VERSION) && !defined(__ITaskbarList3_INTERFACE_DEFINED__)\n// for old mingw\nextern \"C\" {\nDEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF);\nDEFINE_GUID(CLSID_TaskbarList, 0x56fdf344, 0xfd6d, 0x11d0, 0x95,0x8a, 0x00,0x60,0x97,0xc9,0xa0,0x90);\n}\n#endif\n\n#else // is not __MINGW*\n\n#ifndef Z7_OLD_WIN_SDK\n#include <ShObjIdl.h>\n#else\n\n#ifndef HIMAGELIST\nstruct _IMAGELIST;\ntypedef struct _IMAGELIST* HIMAGELIST;\n#endif\n\n#ifndef __ITaskbarList_INTERFACE_DEFINED__\n#define __ITaskbarList_INTERFACE_DEFINED__\nDEFINE_GUID(IID_ITaskbarList, 0x56FDF342, 0xFD6D, 0x11d0, 0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90);\nstruct ITaskbarList: public IUnknown\n{\n  STDMETHOD(HrInit)(void) = 0;\n  STDMETHOD(AddTab)(HWND hwnd) = 0;\n  STDMETHOD(DeleteTab)(HWND hwnd) = 0;\n  STDMETHOD(ActivateTab)(HWND hwnd) = 0;\n  STDMETHOD(SetActiveAlt)(HWND hwnd) = 0;\n};\n#endif // __ITaskbarList_INTERFACE_DEFINED__\n\n#ifndef __ITaskbarList2_INTERFACE_DEFINED__\n#define __ITaskbarList2_INTERFACE_DEFINED__\nDEFINE_GUID(IID_ITaskbarList2, 0x602D4995, 0xB13A, 0x429b, 0xA6, 0x6E, 0x19, 0x35, 0xE4, 0x4F, 0x43, 0x17);\nstruct ITaskbarList2: public ITaskbarList\n{\n  STDMETHOD(MarkFullscreenWindow)(HWND hwnd, BOOL fFullscreen) = 0;\n};\n#endif // __ITaskbarList2_INTERFACE_DEFINED__\n\n#endif // Z7_OLD_WIN_SDK\n\n\n#ifndef __ITaskbarList3_INTERFACE_DEFINED__\n#define __ITaskbarList3_INTERFACE_DEFINED__\n\ntypedef enum THUMBBUTTONFLAGS\n{\n  THBF_ENABLED = 0,\n  THBF_DISABLED = 0x1,\n  THBF_DISMISSONCLICK = 0x2,\n  THBF_NOBACKGROUND = 0x4,\n  THBF_HIDDEN = 0x8,\n  THBF_NONINTERACTIVE = 0x10\n} THUMBBUTTONFLAGS;\n\ntypedef enum THUMBBUTTONMASK\n{\n  THB_BITMAP = 0x1,\n  THB_ICON = 0x2,\n  THB_TOOLTIP = 0x4,\n  THB_FLAGS = 0x8\n} THUMBBUTTONMASK;\n\n// #include <pshpack8.h>\n\ntypedef struct THUMBBUTTON\n{\n  THUMBBUTTONMASK dwMask;\n  UINT iId;\n  UINT iBitmap;\n  HICON hIcon;\n  WCHAR szTip[260];\n  THUMBBUTTONFLAGS dwFlags;\n} THUMBBUTTON;\n\ntypedef struct THUMBBUTTON *LPTHUMBBUTTON;\n\ntypedef enum TBPFLAG\n{\n  TBPF_NOPROGRESS = 0,\n  TBPF_INDETERMINATE = 0x1,\n  TBPF_NORMAL = 0x2,\n  TBPF_ERROR = 0x4,\n  TBPF_PAUSED = 0x8\n} TBPFLAG;\n\nDEFINE_GUID(IID_ITaskbarList3, 0xEA1AFB91, 0x9E28, 0x4B86, 0x90, 0xE9, 0x9E, 0x9F, 0x8A, 0x5E, 0xEF, 0xAF);\n\nstruct ITaskbarList3: public ITaskbarList2\n{\n  STDMETHOD(SetProgressValue)(HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) = 0;\n  STDMETHOD(SetProgressState)(HWND hwnd, TBPFLAG tbpFlags) = 0;\n  STDMETHOD(RegisterTab)(HWND hwndTab, HWND hwndMDI) = 0;\n  STDMETHOD(UnregisterTab)(HWND hwndTab) = 0;\n  STDMETHOD(SetTabOrder)(HWND hwndTab, HWND hwndInsertBefore) = 0;\n  STDMETHOD(SetTabActive)(HWND hwndTab, HWND hwndMDI, DWORD dwReserved) = 0;\n  STDMETHOD(ThumbBarAddButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;\n  STDMETHOD(ThumbBarUpdateButtons)(HWND hwnd, UINT cButtons, LPTHUMBBUTTON pButton) = 0;\n  STDMETHOD(ThumbBarSetImageList)(HWND hwnd, HIMAGELIST himl) = 0;\n  STDMETHOD(SetOverlayIcon)(HWND hwnd, HICON hIcon, LPCWSTR pszDescription) = 0;\n  STDMETHOD(SetThumbnailTooltip)(HWND hwnd, LPCWSTR pszTip) = 0;\n  STDMETHOD(SetThumbnailClip)(HWND hwnd, RECT *prcClip) = 0;\n};\n\n#endif // __ITaskbarList3_INTERFACE_DEFINED__\n\n#endif // __MINGW*\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/OverwriteDialog.cpp",
    "content": "﻿// OverwriteDialog.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/PropVariantConv.h\"\n#include \"../../../Windows/ResourceString.h\"\n\n#include \"../../../Windows/Control/Static.h\"\n\n#include \"FormatUtils.h\"\n#include \"LangUtils.h\"\n#include \"OverwriteDialog.h\"\n\n#include \"PropertyNameRes.h\"\n\nusing namespace NWindows;\n\n#ifdef Z7_LANG\nstatic const UInt32 kLangIDs[] =\n{\n  IDT_OVERWRITE_HEADER,\n  IDT_OVERWRITE_QUESTION_BEGIN,\n  IDT_OVERWRITE_QUESTION_END,\n  IDB_YES_TO_ALL,\n  IDB_NO_TO_ALL,\n  IDB_AUTO_RENAME\n};\n#endif\n\nstatic const unsigned kCurrentFileNameSizeLimit = 72;\n\nvoid COverwriteDialog::ReduceString(UString &s)\n{\n  const unsigned size =\n#ifdef UNDER_CE\n      !_isBig ? 30 : // kCurrentFileNameSizeLimit2\n#endif\n      kCurrentFileNameSizeLimit;\n\n  if (s.Len() > size)\n  {\n    s.Delete(size / 2, s.Len() - size);\n    s.Insert(size / 2, L\" ... \");\n  }\n  if (!s.IsEmpty() && s.Back() == ' ')\n  {\n    // s += (wchar_t)(0x2423); // visible space\n    s.InsertAtFront(L'\\\"');\n    s.Add_Char('\\\"');\n  }\n}\n\n\nvoid COverwriteDialog::SetItemIcon(unsigned iconID, HICON hIcon)\n{\n  NControl::CStatic staticContol;\n  staticContol.Attach(GetItem(iconID));\n  hIcon = staticContol.SetIcon(hIcon);\n  if (hIcon)\n    DestroyIcon(hIcon);\n}\n\nvoid AddSizeValue(UString &s, UInt64 value);\nvoid AddSizeValue(UString &s, UInt64 value)\n{\n  {\n    wchar_t sz[32];\n    ConvertUInt64ToString(value, sz);\n    s += MyFormatNew(IDS_FILE_SIZE, sz);\n  }\n  if (value >= (1 << 10))\n  {\n    char c;\n          if (value >= ((UInt64)10 << 30)) { value >>= 30; c = 'G'; }\n    else  if (value >=         (10 << 20)) { value >>= 20; c = 'M'; }\n    else                                   { value >>= 10; c = 'K'; }\n    s += \" : \";\n    s.Add_UInt64(value);\n    s.Add_Space();\n    s.Add_Char(c);\n    s += \"iB\";\n  }\n}\n\n\nvoid COverwriteDialog::SetFileInfoControl(\n    const NOverwriteDialog::CFileInfo &fileInfo,\n    unsigned textID,\n    unsigned iconID,\n    unsigned iconID_2)\n{\n  {\n    const UString &path = fileInfo.Path;\n    const int slashPos = path.ReverseFind_PathSepar();\n    UString s = path.Left((unsigned)(slashPos + 1));\n    ReduceString(s);\n    s.Add_LF();\n    {\n      UString s2 = path.Ptr((unsigned)(slashPos + 1));\n      ReduceString(s2);\n      s += s2;\n    }\n    s.Add_LF();\n    if (fileInfo.Size_IsDefined)\n      AddSizeValue(s, fileInfo.Size);\n    s.Add_LF();\n    if (fileInfo.Time_IsDefined)\n    {\n      AddLangString(s, IDS_PROP_MTIME);\n      s += \": \";\n      char t[64];\n      ConvertUtcFileTimeToString(fileInfo.Time, t);\n      s += t;\n    }\n    SetItemText(textID, s);\n  }\n/*\n  SHGetFileInfo():\n    DOCs: If uFlags does not contain SHGFI_EXETYPE or SHGFI_SYSICONINDEX,\n          the return value is nonzero if successful, or zero otherwise.\n    We don't use SHGFI_EXETYPE or SHGFI_SYSICONINDEX here.\n  win10: we call with SHGFI_ICON flag set.\n    it returns 0: if error : (shFileInfo::*) members are not set.\n    it returns non_0, if successful, and retrieve:\n      { shFileInfo.hIcon != NULL : the handle to icon (must be destroyed by our code)\n        shFileInfo.iIcon is index of the icon image within the system image list.\n      }\n  Note:\n    If we send path to \".exe\" file,\n    SHGFI_USEFILEATTRIBUTES flag is ignored, and it tries to open file.\n    and return icon from that exe file.\n    So we still need to reduce path, if want to get raw icon of exe file.\n    \n  if (name.Len() >= MAX_PATH))\n  {\n    it can return:\n      return 0.\n      return 1 and:\n        { shFileInfo.hIcon != NULL : is some default icon for file\n          shFileInfo.iIcon == 0\n        }\n    return results (0 or 1) can depend from:\n      - unicode/non-unicode\n      - (SHGFI_USEFILEATTRIBUTES) flag\n      - exact file extension (.exe).\n  }\n*/\n  int iconIndex = -1;\n  for (unsigned i = 0; i < 2; i++)\n  {\n    CSysString name = GetSystemString(fileInfo.Path);\n    if (i != 0)\n    {\n      if (!fileInfo.Is_FileSystemFile)\n        break;\n      if (name.Len() < 4 ||\n          (!StringsAreEqualNoCase_Ascii(name.RightPtr(4), \".exe\") &&\n           !StringsAreEqualNoCase_Ascii(name.RightPtr(4), \".ico\")))\n        break;\n      // if path for \".exe\" file is long, it returns default icon (shFileInfo.iIcon == 0).\n      // We don't want to show that default icon.\n      // But we will check for default icon later instead of MAX_PATH check here.\n      // if (name.Len() >= MAX_PATH) break; // optional\n    }\n    else\n    {\n      // we need only file extension with dot\n      const int separ = name.ReverseFind_PathSepar();\n      name.DeleteFrontal((unsigned)(separ + 1));\n      // if (name.Len() >= MAX_PATH)\n      {\n        const int dot = name.ReverseFind_Dot();\n        if (dot >= 0)\n          name.DeleteFrontal((unsigned)dot);\n        // else name.Empty(); to set default name below\n      }\n      // name.Empty(); // for debug\n    }\n\n    if (name.IsEmpty())\n    {\n      // If we send empty name, SHGetFileInfo() returns some strange icon.\n      // So we use common dummy name without extension,\n      // and SHGetFileInfo() will return default icon (iIcon == 0)\n      name = \"__file__\";\n    }\n\n    DWORD attrib = FILE_ATTRIBUTE_ARCHIVE;\n    if (fileInfo.Is_FileSystemFile)\n    {\n      NFile::NFind::CFileInfo fi;\n      if (fi.Find(us2fs(fileInfo.Path)) && !fi.IsAltStream && !fi.IsDir())\n        attrib = fi.Attrib;\n    }\n\n    SHFILEINFO shFileInfo;\n    // ZeroMemory(&shFileInfo, sizeof(shFileInfo)); // optional\n    shFileInfo.hIcon = NULL; // optional\n    shFileInfo.iIcon = -1;   // optional\n    // memset(&shFileInfo, 1, sizeof(shFileInfo)); // for debug\n    const DWORD_PTR res = ::SHGetFileInfo(name, attrib,\n        &shFileInfo, sizeof(shFileInfo),\n        SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SHELLICONSIZE |\n        // (i == 0 ? SHGFI_USEFILEATTRIBUTES : 0)\n        SHGFI_USEFILEATTRIBUTES\n        // we use SHGFI_USEFILEATTRIBUTES for second icon, because\n        // it still returns real icon from exe files\n        );\n    if (res && shFileInfo.hIcon)\n    {\n      // we don't show second icon, if icon index (iIcon) is same\n      // as first icon index of first shown icon (exe file without icon)\n      if (   shFileInfo.iIcon >= 0\n          && shFileInfo.iIcon != iconIndex\n          && (shFileInfo.iIcon != 0 || i == 0)) // we don't want default icon for second icon\n      {\n        iconIndex = shFileInfo.iIcon;\n        SetItemIcon(i == 0 ? iconID : iconID_2, shFileInfo.hIcon);\n      }\n      else\n        DestroyIcon(shFileInfo.hIcon);\n    }\n  }\n}\n\n\n\nbool COverwriteDialog::OnInit()\n{\n  #ifdef Z7_LANG\n  LangSetWindowText(*this, IDD_OVERWRITE);\n  LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));\n  #endif\n  SetFileInfoControl(OldFileInfo,\n      IDT_OVERWRITE_OLD_FILE_SIZE_TIME,\n      IDI_OVERWRITE_OLD_FILE,\n      IDI_OVERWRITE_OLD_FILE_2);\n  SetFileInfoControl(NewFileInfo,\n      IDT_OVERWRITE_NEW_FILE_SIZE_TIME,\n      IDI_OVERWRITE_NEW_FILE,\n      IDI_OVERWRITE_NEW_FILE_2);\n  NormalizePosition();\n\n  if (!ShowExtraButtons)\n  {\n    HideItem(IDB_YES_TO_ALL);\n    HideItem(IDB_NO_TO_ALL);\n    HideItem(IDB_AUTO_RENAME);\n  }\n\n  if (DefaultButton_is_NO)\n  {\n    PostMsg(DM_SETDEFID, IDNO);\n    HWND h = GetItem(IDNO);\n    PostMsg(WM_NEXTDLGCTL, (WPARAM)h, TRUE);\n    // ::SetFocus(h);\n  }\n\n  return CModalDialog::OnInit();\n}\n\nbool COverwriteDialog::OnDestroy()\n{\n  SetItemIcon(IDI_OVERWRITE_OLD_FILE, NULL);\n  SetItemIcon(IDI_OVERWRITE_OLD_FILE_2, NULL);\n  SetItemIcon(IDI_OVERWRITE_NEW_FILE, NULL);\n  SetItemIcon(IDI_OVERWRITE_NEW_FILE_2, NULL);\n  return false; // we return (false) to perform default dialog operation\n}\n\nbool COverwriteDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)\n{\n  switch (buttonID)\n  {\n    case IDYES:\n    case IDNO:\n    case IDB_YES_TO_ALL:\n    case IDB_NO_TO_ALL:\n    case IDB_AUTO_RENAME:\n      End((INT_PTR)buttonID);\n      return true;\n  }\n  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/OverwriteDialog.h",
    "content": "﻿// OverwriteDialog.h\n\n#ifndef ZIP7_INC_OVERWRITE_DIALOG_H\n#define ZIP7_INC_OVERWRITE_DIALOG_H\n\n#include \"../../../Windows/Control/Dialog.h\"\n\n#include \"DialogSize.h\"\n#include \"OverwriteDialogRes.h\"\n\nnamespace NOverwriteDialog\n{\n  struct CFileInfo\n  {\n    bool Size_IsDefined;\n    bool Time_IsDefined;\n    bool Is_FileSystemFile;\n    UInt64 Size;\n    FILETIME Time;\n    UString Path;\n\n    void SetTime(const FILETIME &t)\n    {\n      Time = t;\n      Time_IsDefined = true;\n    }\n    \n    void SetTime2(const FILETIME *t)\n    {\n      if (!t)\n        Time_IsDefined = false;\n      else\n        SetTime(*t);\n    }\n\n    void SetSize(UInt64 size)\n    {\n      Size = size;\n      Size_IsDefined = true;\n    }\n\n    void SetSize2(const UInt64 *size)\n    {\n      if (!size)\n        Size_IsDefined = false;\n      else\n        SetSize(*size);\n    }\n\n    CFileInfo():\n      Size_IsDefined(false),\n      Time_IsDefined(false),\n      Is_FileSystemFile(false)\n      {}\n  };\n}\n\nclass COverwriteDialog: public NWindows::NControl::CModalDialog\n{\n#ifdef UNDER_CE\n  bool _isBig;\n#endif\n\n  void SetItemIcon(unsigned iconID, HICON hIcon);\n  void SetFileInfoControl(const NOverwriteDialog::CFileInfo &fileInfo, unsigned textID, unsigned iconID, unsigned iconID_2);\n  virtual bool OnInit() Z7_override;\n  virtual bool OnDestroy() Z7_override;\n  virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;\n  void ReduceString(UString &s);\n\npublic:\n  bool ShowExtraButtons;\n  bool DefaultButton_is_NO;\n  NOverwriteDialog::CFileInfo OldFileInfo;\n  NOverwriteDialog::CFileInfo NewFileInfo;\n\n  COverwriteDialog(): ShowExtraButtons(true), DefaultButton_is_NO(false) {}\n\n  INT_PTR Create(HWND parent = NULL)\n  {\n#ifdef UNDER_CE\n    BIG_DIALOG_SIZE(280, 200);\n    _isBig = isBig;\n#endif\n    return CModalDialog::Create(SIZED_DIALOG(IDD_OVERWRITE), parent);\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/OverwriteDialogRes.h",
    "content": "﻿#define IDD_OVERWRITE     3500\n#define IDD_OVERWRITE_2  13500\n\n#define IDT_OVERWRITE_HEADER          3501\n#define IDT_OVERWRITE_QUESTION_BEGIN  3502\n#define IDT_OVERWRITE_QUESTION_END    3503\n#define IDS_FILE_SIZE                 3504\n\n#define IDB_AUTO_RENAME               3505\n#define IDB_YES_TO_ALL                 440\n#define IDB_NO_TO_ALL                  441\n\n#define IDI_OVERWRITE_OLD_FILE             100\n#define IDI_OVERWRITE_OLD_FILE_2           101\n#define IDT_OVERWRITE_OLD_FILE_SIZE_TIME   102\n\n#define IDI_OVERWRITE_NEW_FILE             110\n#define IDI_OVERWRITE_NEW_FILE_2           111\n#define IDT_OVERWRITE_NEW_FILE_SIZE_TIME   112\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/PasswordDialog.cpp",
    "content": "﻿// PasswordDialog.cpp\n\n#include \"StdAfx.h\"\n\n#include \"PasswordDialog.h\"\n\n#ifdef Z7_LANG\n#include \"LangUtils.h\"\n#endif\n\n#ifdef Z7_LANG\nstatic const UInt32 kLangIDs[] =\n{\n  IDT_PASSWORD_ENTER,\n  IDX_PASSWORD_SHOW\n};\n#endif\n\nvoid CPasswordDialog::ReadControls()\n{\n  _passwordEdit.GetText(Password);\n  ShowPassword = IsButtonCheckedBool(IDX_PASSWORD_SHOW);\n}\n\nvoid CPasswordDialog::SetTextSpec()\n{\n  _passwordEdit.SetPasswordChar(ShowPassword ? 0: TEXT('*'));\n  _passwordEdit.SetText(Password);\n}\n\nbool CPasswordDialog::OnInit()\n{\n  #ifdef Z7_LANG\n  LangSetWindowText(*this, IDD_PASSWORD);\n  LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));\n  #endif\n  _passwordEdit.Attach(GetItem(IDE_PASSWORD_PASSWORD));\n  CheckButton(IDX_PASSWORD_SHOW, ShowPassword);\n  SetTextSpec();\n  return CModalDialog::OnInit();\n}\n\nbool CPasswordDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)\n{\n  if (buttonID == IDX_PASSWORD_SHOW)\n  {\n    ReadControls();\n    SetTextSpec();\n    return true;\n  }\n  return CDialog::OnButtonClicked(buttonID, buttonHWND);\n}\n\nvoid CPasswordDialog::OnOK()\n{\n  ReadControls();\n  CModalDialog::OnOK();\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/PasswordDialog.h",
    "content": "﻿// PasswordDialog.h\n\n#ifndef ZIP7_INC_PASSWORD_DIALOG_H\n#define ZIP7_INC_PASSWORD_DIALOG_H\n\n#include \"../../../Windows/Control/Dialog.h\"\n#include \"../../../Windows/Control/Edit.h\"\n\n#include \"PasswordDialogRes.h\"\n\nclass CPasswordDialog: public NWindows::NControl::CModalDialog\n{\n  NWindows::NControl::CEdit _passwordEdit;\n\n  virtual void OnOK() Z7_override;\n  virtual bool OnInit() Z7_override;\n  virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;\n  void SetTextSpec();\n  void ReadControls();\npublic:\n  UString Password;\n  bool ShowPassword;\n  \n  CPasswordDialog(): ShowPassword(false) {}\n  INT_PTR Create(HWND parentWindow = NULL) { return CModalDialog::Create(IDD_PASSWORD, parentWindow); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/PasswordDialog.rc",
    "content": "#include \"PasswordDialogRes.h\"\n#include \"../../GuiCommon.rc\"\n\n#ifdef UNDER_CE\n#define xc 140\n#else\n#define xc 200\n#endif\n#define yc 72\n\nIDD_PASSWORD  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT\nCAPTION \"Enter password\"\nBEGIN\n  LTEXT    \"&Enter password:\", IDT_PASSWORD_ENTER, m, m, xc, 8\n  EDITTEXT  IDE_PASSWORD_PASSWORD, m, 20, xc, 14, ES_PASSWORD | ES_AUTOHSCROLL\n  CONTROL  \"&Show password\", IDX_PASSWORD_SHOW, MY_CHECKBOX, m, 42, xc, 10\n  OK_CANCEL\nEND\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/PasswordDialogRes.h",
    "content": "﻿#define IDD_PASSWORD        3800\n#define IDT_PASSWORD_ENTER  3801\n#define IDX_PASSWORD_SHOW   3803\n\n#define IDE_PASSWORD_PASSWORD  120\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialog.cpp",
    "content": "﻿// ProgressDialog.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n\n#include \"resource.h\"\n\n#include \"ProgressDialog.h\"\n\nusing namespace NWindows;\n\nextern HINSTANCE g_hInstance;\n\nstatic const UINT_PTR kTimerID = 3;\nstatic const UINT kTimerElapse = 100;\n\n#ifdef Z7_LANG\n#include \"LangUtils.h\"\n#endif\n\nHRESULT CProgressSync::ProcessStopAndPause()\n{\n  for (;;)\n  {\n    if (GetStopped())\n      return E_ABORT;\n    if (!GetPaused())\n      break;\n    ::Sleep(100);\n  }\n  return S_OK;\n}\n\n#ifndef Z7_SFX\nCProgressDialog::~CProgressDialog()\n{\n  AddToTitle(L\"\");\n}\nvoid CProgressDialog::AddToTitle(LPCWSTR s)\n{\n  if (MainWindow != 0)\n    MySetWindowText(MainWindow, UString(s) + MainTitle);\n}\n#endif\n\n\n#define UNDEFINED_VAL ((UInt64)(Int64)-1)\n\nbool CProgressDialog::OnInit()\n{\n  _range = UNDEFINED_VAL;\n  _prevPercentValue = UNDEFINED_VAL;\n\n  _wasCreated = true;\n  _dialogCreatedEvent.Set();\n\n  #ifdef Z7_LANG\n  LangSetDlgItems(*this, NULL, 0);\n  #endif\n\n  m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));\n\n  if (IconID >= 0)\n  {\n    HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));\n    SetIcon(ICON_BIG, icon);\n  }\n\n  _timer = SetTimer(kTimerID, kTimerElapse);\n  SetText(_title);\n  CheckNeedClose();\n  return CModalDialog::OnInit();\n}\n\nvoid CProgressDialog::OnCancel() { Sync.SetStopped(true); }\nvoid CProgressDialog::OnOK() { }\n\nvoid CProgressDialog::SetRange(UInt64 range)\n{\n  _range = range;\n  _peviousPos = (UInt64)(Int64)-1;\n  _converter.Init(range);\n  m_ProgressBar.SetRange32(0 , _converter.Count(range)); // Test it for 100%\n}\n\nvoid CProgressDialog::SetPos(UInt64 pos)\n{\n  bool redraw = true;\n  if (pos < _range && pos > _peviousPos)\n  {\n    UInt64 posDelta = pos - _peviousPos;\n    if (posDelta < (_range >> 10))\n      redraw = false;\n  }\n  if (redraw)\n  {\n    m_ProgressBar.SetPos(_converter.Count(pos));  // Test it for 100%\n    _peviousPos = pos;\n  }\n}\n\nbool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)\n{\n  if (Sync.GetPaused())\n    return true;\n\n  CheckNeedClose();\n\n  UInt64 total, completed;\n  Sync.GetProgress(total, completed);\n  if (total != _range)\n    SetRange(total);\n  SetPos(completed);\n\n  if (total == 0)\n    total = 1;\n\n  const UInt64 percentValue = completed * 100 / total;\n  if (percentValue != _prevPercentValue)\n  {\n    wchar_t s[64];\n    ConvertUInt64ToString(percentValue, s);\n    UString title = s;\n    title += \"% \";\n    SetText(title + _title);\n    #ifndef Z7_SFX\n    AddToTitle(title + MainAddTitle);\n    #endif\n    _prevPercentValue = percentValue;\n  }\n  return true;\n}\n\nbool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\n{\n  switch (message)\n  {\n    case kCloseMessage:\n    {\n      if (_timer)\n      {\n        KillTimer(kTimerID);\n        _timer = 0;\n      }\n      if (_inCancelMessageBox)\n      {\n        _externalCloseMessageWasReceived = true;\n        break;\n      }\n      return OnExternalCloseMessage();\n    }\n    /*\n    case WM_SETTEXT:\n    {\n      if (_timer == 0)\n        return true;\n    }\n    */\n  }\n  return CModalDialog::OnMessage(message, wParam, lParam);\n}\n\nbool CProgressDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)\n{\n  switch (buttonID)\n  {\n    case IDCANCEL:\n    {\n      bool paused = Sync.GetPaused();\n      Sync.SetPaused(true);\n      _inCancelMessageBox = true;\n      int res = ::MessageBoxW(*this, L\"Are you sure you want to cancel?\", _title, MB_YESNOCANCEL);\n      _inCancelMessageBox = false;\n      Sync.SetPaused(paused);\n      if (res == IDCANCEL || res == IDNO)\n      {\n        if (_externalCloseMessageWasReceived)\n          OnExternalCloseMessage();\n        return true;\n      }\n      break;\n    }\n  }\n  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\n}\n\nvoid CProgressDialog::CheckNeedClose()\n{\n  if (_needClose)\n  {\n    PostMsg(kCloseMessage);\n    _needClose = false;\n  }\n}\n\nbool CProgressDialog::OnExternalCloseMessage()\n{\n  End(0);\n  return true;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialog.h",
    "content": "﻿// ProgressDialog.h\n\n#ifndef ZIP7_INC_PROGRESS_DIALOG_H\n#define ZIP7_INC_PROGRESS_DIALOG_H\n\n#include \"../../../Windows/Synchronization.h\"\n#include \"../../../Windows/Thread.h\"\n\n#include \"../../../Windows/Control/Dialog.h\"\n#include \"../../../Windows/Control/ProgressBar.h\"\n\n#include \"ProgressDialogRes.h\"\n\nclass CProgressSync\n{\n  NWindows::NSynchronization::CCriticalSection _cs;\n  bool _stopped;\n  bool _paused;\n  UInt64 _total;\n  UInt64 _completed;\npublic:\n  CProgressSync(): _stopped(false), _paused(false), _total(1), _completed(0) {}\n\n  HRESULT ProcessStopAndPause();\n  bool GetStopped()\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    return _stopped;\n  }\n  void SetStopped(bool value)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    _stopped = value;\n  }\n  bool GetPaused()\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    return _paused;\n  }\n  void SetPaused(bool value)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    _paused = value;\n  }\n  void SetProgress(UInt64 total, UInt64 completed)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    _total = total;\n    _completed = completed;\n  }\n  void SetPos(UInt64 completed)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    _completed = completed;\n  }\n  void GetProgress(UInt64 &total, UInt64 &completed)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    total = _total;\n    completed = _completed;\n  }\n};\n\nclass CU64ToI32Converter\n{\n  UInt64 _numShiftBits;\npublic:\n  void Init(UInt64 range)\n  {\n    // Windows CE doesn't like big number here.\n    for (_numShiftBits = 0; range > (1 << 15); _numShiftBits++)\n      range >>= 1;\n  }\n  int Count(UInt64 value) { return int(value >> _numShiftBits); }\n};\n\nclass CProgressDialog: public NWindows::NControl::CModalDialog\n{\nprivate:\n  UINT_PTR _timer;\n\n  UString _title;\n  CU64ToI32Converter _converter;\n  UInt64 _peviousPos;\n  UInt64 _range;\n  NWindows::NControl::CProgressBar m_ProgressBar;\n\n  UInt64 _prevPercentValue;\n\n  bool _wasCreated;\n  bool _needClose;\n  bool _inCancelMessageBox;\n  bool _externalCloseMessageWasReceived;\n\n  virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;\n  virtual bool OnTimer(WPARAM timerID, LPARAM callback) Z7_override;\n  virtual bool OnInit() Z7_override;\n  virtual void OnCancel() Z7_override;\n  virtual void OnOK() Z7_override;\n  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override;\n\n  void SetRange(UInt64 range);\n  void SetPos(UInt64 pos);\n\n  NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;\n  #ifndef Z7_SFX\n  void AddToTitle(LPCWSTR string);\n  #endif\n\n  void WaitCreating() { _dialogCreatedEvent.Lock(); }\n  void CheckNeedClose();\n  bool OnExternalCloseMessage();\npublic:\n  CProgressSync Sync;\n  int IconID;\n\n  #ifndef Z7_SFX\n  HWND MainWindow;\n  UString MainTitle;\n  UString MainAddTitle;\n  ~CProgressDialog();\n  #endif\n\n  CProgressDialog(): _timer(0)\n    #ifndef Z7_SFX\n    ,MainWindow(NULL)\n    #endif\n  {\n    IconID = -1;\n    _wasCreated = false;\n    _needClose = false;\n    _inCancelMessageBox = false;\n    _externalCloseMessageWasReceived = false;\n\n    if (_dialogCreatedEvent.Create() != S_OK)\n      throw 1334987;\n  }\n\n  INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = NULL)\n  {\n    _title = title;\n    INT_PTR res = CModalDialog::Create(IDD_PROGRESS, wndParent);\n    thread.Wait_Close();\n    return res;\n  }\n\n  enum\n  {\n    kCloseMessage = WM_APP + 1\n  };\n\n  void ProcessWasFinished()\n  {\n    WaitCreating();\n    if (_wasCreated)\n      PostMsg(kCloseMessage);\n    else\n      _needClose = true;\n  }\n};\n\n\nclass CProgressCloser\n{\n  CProgressDialog *_p;\npublic:\n  CProgressCloser(CProgressDialog &p) : _p(&p) {}\n  ~CProgressCloser() { _p->ProcessWasFinished(); }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialog.rc",
    "content": "#include \"ProgressDialogRes.h\"\n#include \"../../GuiCommon.rc\"\n\n#define xc 172\n#define yc 44\n\nIDD_PROGRESS  DIALOG  0, 0, xs, ys  MY_MODAL_DIALOG_STYLE  MY_FONT\nCAPTION \"Progress\"\nBEGIN\n  PUSHBUTTON  \"Cancel\", IDCANCEL, bx, by, bxs, bys\n  CONTROL     \"Progress1\", IDC_PROGRESS1, \"msctls_progress32\", PBS_SMOOTH | WS_BORDER, m, m, xc, 14\nEND\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialog2.cpp",
    "content": "﻿// ProgressDialog2.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef Z7_OLD_WIN_SDK\n#include <ShlGuid.h>\n#endif\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/Clipboard.h\"\n#include \"../../../Windows/ErrorMsg.h\"\n\n#include \"../GUI/ExtractRes.h\"\n\n#include \"LangUtils.h\"\n\n#include \"DialogSize.h\"\n#include \"ProgressDialog2.h\"\n#include \"ProgressDialog2Res.h\"\n\nusing namespace NWindows;\n\nextern HINSTANCE g_hInstance;\nextern bool g_DisableUserQuestions;\n\nstatic const UINT_PTR kTimerID = 3;\n\nstatic const UINT kCloseMessage = WM_APP + 1;\n// we can't use WM_USER, since WM_USER can be used by standard Windows procedure for Dialog\n\nstatic const UINT kTimerElapse =\n  #ifdef UNDER_CE\n  500\n  #else\n  200\n  #endif\n  ;\n\nstatic const UINT kCreateDelay =\n  #ifdef UNDER_CE\n  2500\n  #else\n  500\n  #endif\n  ;\n\nstatic const DWORD kPauseSleepTime = 100;\n\n#ifdef Z7_LANG\n\nstatic const UInt32 kLangIDs[] =\n{\n  IDT_PROGRESS_ELAPSED,\n  IDT_PROGRESS_REMAINING,\n  IDT_PROGRESS_TOTAL,\n  IDT_PROGRESS_SPEED,\n  IDT_PROGRESS_PROCESSED,\n  IDT_PROGRESS_RATIO,\n  IDT_PROGRESS_ERRORS,\n  IDB_PROGRESS_BACKGROUND,\n  IDB_PAUSE\n};\n\nstatic const UInt32 kLangIDs_Colon[] =\n{\n  IDT_PROGRESS_PACKED,\n  IDT_PROGRESS_FILES\n};\n\n#endif\n\n\n#define UNDEFINED_VAL         ((UInt64)(Int64)-1)\n#define INIT_AS_UNDEFINED(v)  v = UNDEFINED_VAL;\n#define IS_UNDEFINED_VAL(v)   ((v) == UNDEFINED_VAL)\n#define IS_DEFINED_VAL(v)     ((v) != UNDEFINED_VAL)\n\nCProgressSync::CProgressSync():\n    _stopped(false),\n    _paused(false),\n    _filesProgressMode(false),\n    _isDir(false),\n    _totalBytes(UNDEFINED_VAL), _completedBytes(0),\n    _totalFiles(UNDEFINED_VAL), _curFiles(0),\n    _inSize(UNDEFINED_VAL),\n    _outSize(UNDEFINED_VAL)\n    {}\n\n#define CHECK_STOP  if (_stopped) return E_ABORT; if (!_paused) return S_OK;\n#define CRITICAL_LOCK NSynchronization::CCriticalSectionLock lock(_cs);\n\nbool CProgressSync::Get_Paused()\n{\n  CRITICAL_LOCK\n  return _paused;\n}\n\nHRESULT CProgressSync::CheckStop()\n{\n  for (;;)\n  {\n    {\n      CRITICAL_LOCK\n      CHECK_STOP\n    }\n    ::Sleep(kPauseSleepTime);\n  }\n}\n\nvoid CProgressSync::Clear_Stop_Status()\n{\n  CRITICAL_LOCK\n  if (_stopped)\n    _stopped = false;\n}\n\nHRESULT CProgressSync::ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir)\n{\n  {\n    CRITICAL_LOCK\n    _totalFiles = numFiles;\n    _totalBytes = totalSize;\n    _filePath = fs2us(fileName);\n    _isDir = isDir;\n    // _completedBytes = 0;\n    CHECK_STOP\n  }\n  return CheckStop();\n}\n\nHRESULT CProgressSync::Set_NumFilesTotal(UInt64 val)\n{\n  {\n    CRITICAL_LOCK\n    _totalFiles = val;\n    CHECK_STOP\n  }\n  return CheckStop();\n}\n\nvoid CProgressSync::Set_NumBytesTotal(UInt64 val)\n{\n  CRITICAL_LOCK\n  _totalBytes = val;\n}\n\nvoid CProgressSync::Set_NumFilesCur(UInt64 val)\n{\n  CRITICAL_LOCK\n  _curFiles = val;\n}\n\nHRESULT CProgressSync::Set_NumBytesCur(const UInt64 *val)\n{\n  {\n    CRITICAL_LOCK\n    if (val)\n      _completedBytes = *val;\n    CHECK_STOP\n  }\n  return CheckStop();\n}\n\nHRESULT CProgressSync::Set_NumBytesCur(UInt64 val)\n{\n  {\n    CRITICAL_LOCK\n    _completedBytes = val;\n    CHECK_STOP\n  }\n  return CheckStop();\n}\n\nvoid CProgressSync::Set_Ratio(const UInt64 *inSize, const UInt64 *outSize)\n{\n  CRITICAL_LOCK\n  if (inSize)\n    _inSize = *inSize;\n  if (outSize)\n    _outSize = *outSize;\n}\n\nvoid CProgressSync::Set_TitleFileName(const UString &fileName)\n{\n  CRITICAL_LOCK\n  _titleFileName = fileName;\n}\n\nvoid CProgressSync::Set_Status(const UString &s)\n{\n  CRITICAL_LOCK\n  _status = s;\n}\n\nHRESULT CProgressSync::Set_Status2(const UString &s, const wchar_t *path, bool isDir)\n{\n  {\n    CRITICAL_LOCK\n    _status = s;\n    if (path)\n      _filePath = path;\n    else\n      _filePath.Empty();\n    _isDir = isDir;\n  }\n  return CheckStop();\n}\n\nvoid CProgressSync::Set_FilePath(const wchar_t *path, bool isDir)\n{\n  CRITICAL_LOCK\n  if (path)\n    _filePath = path;\n  else\n    _filePath.Empty();\n  _isDir = isDir;\n}\n\n\nvoid CProgressSync::AddError_Message(const wchar_t *message)\n{\n  CRITICAL_LOCK\n  Messages.Add(message);\n}\n\nvoid CProgressSync::AddError_Message_Name(const wchar_t *message, const wchar_t *name)\n{\n  UString s;\n  if (name && *name != 0)\n    s += name;\n  if (message && *message != 0)\n  {\n    if (!s.IsEmpty())\n      s.Add_LF();\n    s += message;\n    if (!s.IsEmpty() && s.Back() == L'\\n')\n      s.DeleteBack();\n  }\n  AddError_Message(s);\n}\n\nvoid CProgressSync::AddError_Code_Name(HRESULT systemError, const wchar_t *name)\n{\n  UString s = NError::MyFormatMessage(systemError);\n  if (systemError == 0)\n    s = \"Error\";\n  AddError_Message_Name(s, name);\n}\n\nCProgressDialog::CProgressDialog():\n    _isDir(false),\n    _wasCreated(false),\n    _needClose(false),\n    _errorsWereDisplayed(false),\n    _waitCloseByCancelButton(false),\n    _cancelWasPressed(false),\n    _inCancelMessageBox(false),\n    _externalCloseMessageWasReceived(false),\n    _background(false),\n    WaitMode(false),\n    MessagesDisplayed(false),\n    CompressingMode(true),\n    ShowCompressionInfo(true),\n    _numPostedMessages(0),\n    _numAutoSizeMessages(0),\n    _numMessages(0),\n    _timer(0),\n    IconID(-1),\n    MainWindow(NULL)\n{\n\n  if (_dialogCreatedEvent.Create() != S_OK)\n    throw 1334987;\n  if (_createDialogEvent.Create() != S_OK)\n    throw 1334987;\n  // #ifdef __ITaskbarList3_INTERFACE_DEFINED__\n  CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&_taskbarList);\n  if (_taskbarList)\n    _taskbarList->HrInit();\n  // #endif\n}\n\n#ifndef Z7_SFX\n\nCProgressDialog::~CProgressDialog()\n{\n  // #ifdef __ITaskbarList3_INTERFACE_DEFINED__\n  SetTaskbarProgressState(TBPF_NOPROGRESS);\n  // #endif\n  AddToTitle(L\"\");\n}\nvoid CProgressDialog::AddToTitle(LPCWSTR s)\n{\n  if (MainWindow)\n  {\n    CWindow window(MainWindow);\n    window.SetText((UString)s + MainTitle);\n  }\n}\n\n#endif\n\n\nvoid CProgressDialog::SetTaskbarProgressState()\n{\n  // #ifdef __ITaskbarList3_INTERFACE_DEFINED__\n  if (_taskbarList && _hwndForTaskbar)\n  {\n    TBPFLAG tbpFlags;\n    if (Sync.Get_Paused())\n      tbpFlags = TBPF_PAUSED;\n    else\n      tbpFlags = _errorsWereDisplayed ? TBPF_ERROR: TBPF_NORMAL;\n    SetTaskbarProgressState(tbpFlags);\n  }\n  // #endif\n}\n\nstatic const unsigned kTitleFileNameSizeLimit = 36;\nstatic const unsigned kCurrentFileNameSizeLimit = 82;\n\nstatic void ReduceString(UString &s, unsigned size)\n{\n  if (s.Len() <= size)\n    return;\n  s.Delete(size / 2, s.Len() - size);\n  s.Insert(size / 2, L\" ... \");\n}\n\nvoid CProgressDialog::EnableErrorsControls(bool enable)\n{\n  ShowItem_Bool(IDT_PROGRESS_ERRORS, enable);\n  ShowItem_Bool(IDT_PROGRESS_ERRORS_VAL, enable);\n  ShowItem_Bool(IDL_PROGRESS_MESSAGES, enable);\n}\n\nbool CProgressDialog::OnInit()\n{\n  _hwndForTaskbar = MainWindow;\n  if (!_hwndForTaskbar)\n    _hwndForTaskbar = GetParent();\n  if (!_hwndForTaskbar)\n    _hwndForTaskbar = *this;\n\n  INIT_AS_UNDEFINED(_progressBar_Range)\n  INIT_AS_UNDEFINED(_progressBar_Pos)\n\n  INIT_AS_UNDEFINED(_prevPercentValue)\n  INIT_AS_UNDEFINED(_prevElapsedSec)\n  INIT_AS_UNDEFINED(_prevRemainingSec)\n\n  INIT_AS_UNDEFINED(_prevSpeed)\n  _prevSpeed_MoveBits = 0;\n  \n  _prevTime = ::GetTickCount();\n  _elapsedTime = 0;\n\n  INIT_AS_UNDEFINED(_totalBytes_Prev)\n  INIT_AS_UNDEFINED(_processed_Prev)\n  INIT_AS_UNDEFINED(_packed_Prev)\n  INIT_AS_UNDEFINED(_ratio_Prev)\n  \n  _filesStr_Prev.Empty();\n  _filesTotStr_Prev.Empty();\n\n  m_ProgressBar.Attach(GetItem(IDC_PROGRESS1));\n  _messageList.Attach(GetItem(IDL_PROGRESS_MESSAGES));\n  _messageList.SetUnicodeFormat();\n  _messageList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);\n\n  _wasCreated = true;\n  _dialogCreatedEvent.Set();\n\n  #ifdef Z7_LANG\n  LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));\n  LangSetDlgItems_Colon(*this, kLangIDs_Colon, Z7_ARRAY_SIZE(kLangIDs_Colon));\n  #endif\n\n  CWindow window(GetItem(IDB_PROGRESS_BACKGROUND));\n  window.GetText(_background_String);\n  _backgrounded_String = _background_String;\n  _backgrounded_String.RemoveChar(L'&');\n\n  window = GetItem(IDB_PAUSE);\n  window.GetText(_pause_String);\n\n  LangString(IDS_PROGRESS_FOREGROUND, _foreground_String);\n  LangString(IDS_CONTINUE, _continue_String);\n  LangString(IDS_PROGRESS_PAUSED, _paused_String);\n\n  SetText(_title);\n  SetPauseText();\n  SetPriorityText();\n\n  _messageList.InsertColumn(0, L\"\", 40);\n  _messageList.InsertColumn(1, L\"\", 460);\n  _messageList.SetColumnWidthAuto(0);\n  _messageList.SetColumnWidthAuto(1);\n\n  EnableErrorsControls(false);\n\n  GetItemSizes(IDCANCEL, _buttonSizeX, _buttonSizeY);\n  _numReduceSymbols = kCurrentFileNameSizeLimit;\n  NormalizeSize(true);\n\n  if (!ShowCompressionInfo)\n  {\n    HideItem(IDT_PROGRESS_PACKED);\n    HideItem(IDT_PROGRESS_PACKED_VAL);\n    HideItem(IDT_PROGRESS_RATIO);\n    HideItem(IDT_PROGRESS_RATIO_VAL);\n  }\n\n  if (IconID >= 0)\n  {\n    HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IconID));\n    // SetIcon(ICON_SMALL, icon);\n    SetIcon(ICON_BIG, icon);\n  }\n  _timer = SetTimer(kTimerID, kTimerElapse);\n  #ifdef UNDER_CE\n  Foreground();\n  #endif\n\n  CheckNeedClose();\n\n  SetTaskbarProgressState();\n\n  return CModalDialog::OnInit();\n}\n\nstatic const UINT kIDs[] =\n{\n  IDT_PROGRESS_ELAPSED,   IDT_PROGRESS_ELAPSED_VAL,\n  IDT_PROGRESS_REMAINING, IDT_PROGRESS_REMAINING_VAL,\n  IDT_PROGRESS_FILES,     IDT_PROGRESS_FILES_VAL,\n  0,                      IDT_PROGRESS_FILES_TOTAL,\n  IDT_PROGRESS_ERRORS,    IDT_PROGRESS_ERRORS_VAL,\n  \n  IDT_PROGRESS_TOTAL,     IDT_PROGRESS_TOTAL_VAL,\n  IDT_PROGRESS_SPEED,     IDT_PROGRESS_SPEED_VAL,\n  IDT_PROGRESS_PROCESSED, IDT_PROGRESS_PROCESSED_VAL,\n  IDT_PROGRESS_PACKED,    IDT_PROGRESS_PACKED_VAL,\n  IDT_PROGRESS_RATIO,     IDT_PROGRESS_RATIO_VAL\n};\n\nbool CProgressDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)\n{\n  int sY;\n  int sStep;\n  int mx, my;\n  {\n    RECT r;\n    GetClientRectOfItem(IDT_PROGRESS_ELAPSED, r);\n    mx = r.left;\n    my = r.top;\n    sY = RECT_SIZE_Y(r);\n    GetClientRectOfItem(IDT_PROGRESS_REMAINING, r);\n    sStep = r.top - my;\n  }\n\n  InvalidateRect(NULL);\n\n  const int xSizeClient = xSize - mx * 2;\n\n  {\n    unsigned i;\n    for (i = 800; i > 40; i = i * 9 / 10)\n      if (Units_To_Pixels_X((int)i) <= xSizeClient)\n        break;\n    _numReduceSymbols = i / 4;\n  }\n\n  int yPos = ySize - my - _buttonSizeY;\n\n  ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_STATUS), xSize - mx * 2);\n  ChangeSubWindowSizeX(GetItem(IDT_PROGRESS_FILE_NAME), xSize - mx * 2);\n  ChangeSubWindowSizeX(GetItem(IDC_PROGRESS1), xSize - mx * 2);\n\n  int bSizeX = _buttonSizeX;\n  int mx2 = mx;\n  for (;; mx2--)\n  {\n    const int bSize2 = bSizeX * 3 + mx2 * 2;\n    if (bSize2 <= xSizeClient)\n      break;\n    if (mx2 < 5)\n    {\n      bSizeX = (xSizeClient - mx2 * 2) / 3;\n      break;\n    }\n  }\n  if (bSizeX < 2)\n    bSizeX = 2;\n\n  {\n    RECT r;\n    GetClientRectOfItem(IDL_PROGRESS_MESSAGES, r);\n    const int y = r.top;\n    int ySize2 = yPos - my - y;\n    const int kMinYSize = _buttonSizeY + _buttonSizeY * 3 / 4;\n    int xx = xSize - mx * 2;\n    if (ySize2 < kMinYSize)\n    {\n      ySize2 = kMinYSize;\n      if (xx > bSizeX * 2)\n        xx -= bSizeX;\n    }\n\n    _messageList.Move(mx, y, xx, ySize2);\n  }\n\n  {\n    int xPos = xSize - mx;\n    xPos -= bSizeX;\n    MoveItem(IDCANCEL, xPos, yPos, bSizeX, _buttonSizeY);\n    xPos -= (mx2 + bSizeX);\n    MoveItem(IDB_PAUSE, xPos, yPos, bSizeX, _buttonSizeY);\n    xPos -= (mx2 + bSizeX);\n    MoveItem(IDB_PROGRESS_BACKGROUND, xPos, yPos, bSizeX, _buttonSizeY);\n  }\n\n  int valueSize;\n  int labelSize;\n  int padSize;\n\n  labelSize = Units_To_Pixels_X(MY_PROGRESS_LABEL_UNITS_MIN);\n  valueSize = Units_To_Pixels_X(MY_PROGRESS_VAL_UNITS);\n  padSize = Units_To_Pixels_X(MY_PROGRESS_PAD_UNITS);\n  const int requiredSize = (labelSize + valueSize) * 2 + padSize;\n\n  int gSize;\n  {\n    if (requiredSize < xSizeClient)\n    {\n      const int incr = (xSizeClient - requiredSize) / 3;\n      labelSize += incr;\n    }\n    else\n      labelSize = (xSizeClient - valueSize * 2 - padSize) / 2;\n    if (labelSize < 0)\n      labelSize = 0;\n\n    gSize = labelSize + valueSize;\n    padSize = xSizeClient - gSize * 2;\n  }\n\n  labelSize = gSize - valueSize;\n\n  yPos = my;\n  for (unsigned i = 0; i < Z7_ARRAY_SIZE(kIDs); i += 2)\n  {\n    int x = mx;\n    const unsigned kNumColumn1Items = 5 * 2;\n    if (i >= kNumColumn1Items)\n    {\n      if (i == kNumColumn1Items)\n        yPos = my;\n      x = mx + gSize + padSize;\n    }\n    if (kIDs[i] != 0)\n    MoveItem(kIDs[i], x, yPos, labelSize, sY);\n    MoveItem(kIDs[i + 1], x + labelSize, yPos, valueSize, sY);\n    yPos += sStep;\n  }\n  return false;\n}\n\nvoid CProgressDialog::OnCancel() { Sync.Set_Stopped(true); }\nvoid CProgressDialog::OnOK() { }\n\nvoid CProgressDialog::SetProgressRange(UInt64 range)\n{\n  if (range == _progressBar_Range)\n    return;\n  _progressBar_Range = range;\n  INIT_AS_UNDEFINED(_progressBar_Pos)\n  _progressConv.Init(range);\n  m_ProgressBar.SetRange32(0, _progressConv.Count(range));\n}\n\nvoid CProgressDialog::SetProgressPos(UInt64 pos)\n{\n  if (pos >= _progressBar_Range ||\n      pos <= _progressBar_Pos ||\n      pos - _progressBar_Pos >= (_progressBar_Range >> 10))\n  {\n    m_ProgressBar.SetPos(_progressConv.Count(pos));\n    // #ifdef __ITaskbarList3_INTERFACE_DEFINED__\n    if (_taskbarList && _hwndForTaskbar)\n      _taskbarList->SetProgressValue(_hwndForTaskbar, pos, _progressBar_Range);\n    // #endif\n    _progressBar_Pos = pos;\n  }\n}\n\n#define UINT_TO_STR_2(val) { s[0] = (wchar_t)('0' + (val) / 10); s[1] = (wchar_t)('0' + (val) % 10); s += 2; }\n\nvoid GetTimeString(UInt64 timeValue, wchar_t *s);\nvoid GetTimeString(UInt64 timeValue, wchar_t *s)\n{\n  UInt64 hours = timeValue / 3600;\n  UInt32 seconds = (UInt32)(timeValue - hours * 3600);\n  UInt32 minutes = seconds / 60;\n  seconds %= 60;\n  if (hours > 99)\n  {\n    ConvertUInt64ToString(hours, s);\n    for (; *s != 0; s++);\n  }\n  else\n  {\n    UInt32 hours32 = (UInt32)hours;\n    UINT_TO_STR_2(hours32)\n  }\n  *s++ = ':'; UINT_TO_STR_2(minutes)\n  *s++ = ':'; UINT_TO_STR_2(seconds)\n  *s = 0;\n}\n\nstatic void ConvertSizeToString(UInt64 v, wchar_t *s)\n{\n  Byte c = 0;\n       if (v >= ((UInt64)100000 << 20)) { v >>= 30; c = 'G'; }\n  else if (v >= ((UInt64)100000 << 10)) { v >>= 20; c = 'M'; }\n  else if (v >= ((UInt64)100000 <<  0)) { v >>= 10; c = 'K'; }\n  ConvertUInt64ToString(v, s);\n  if (c != 0)\n  {\n    s += MyStringLen(s);\n    *s++ = ' ';\n    *s++ = c;\n    *s++ = 'B';\n    *s++ = 0;\n  }\n}\n\nvoid CProgressDialog::ShowSize(unsigned id, UInt64 val, UInt64 &prev)\n{\n  if (val == prev)\n    return;\n  prev = val;\n  wchar_t s[40];\n  s[0] = 0;\n  if (IS_DEFINED_VAL(val))\n    ConvertSizeToString(val, s);\n  SetItemText(id, s);\n}\n\nstatic void GetChangedString(const UString &newStr, UString &prevStr, bool &hasChanged)\n{\n  hasChanged = !(prevStr == newStr);\n  if (hasChanged)\n    prevStr = newStr;\n}\n\nstatic unsigned GetPower32(UInt32 val)\n{\n  const unsigned kStart = 32;\n  UInt32 mask = ((UInt32)1 << (kStart - 1));\n  for (unsigned i = kStart;; i--)\n  {\n    if (i == 0 || (val & mask) != 0)\n      return i;\n    mask >>= 1;\n  }\n}\n\nstatic unsigned GetPower64(UInt64 val)\n{\n  UInt32 high = (UInt32)(val >> 32);\n  if (high == 0)\n    return GetPower32((UInt32)val);\n  return GetPower32(high) + 32;\n}\n\nstatic UInt64 MyMultAndDiv(UInt64 mult1, UInt64 mult2, UInt64 divider)\n{\n  unsigned pow1 = GetPower64(mult1);\n  unsigned pow2 = GetPower64(mult2);\n  while (pow1 + pow2 > 64)\n  {\n    if (pow1 > pow2) { pow1--; mult1 >>= 1; }\n    else             { pow2--; mult2 >>= 1; }\n    divider >>= 1;\n  }\n  UInt64 res = mult1 * mult2;\n  if (divider != 0)\n    res /= divider;\n  return res;\n}\n\nvoid CProgressDialog::UpdateStatInfo(bool showAll)\n{\n  UInt64 total, completed, totalFiles, completedFiles, inSize, outSize;\n  bool filesProgressMode;\n\n  bool titleFileName_Changed;\n  bool curFilePath_Changed;\n  bool status_Changed;\n  unsigned numErrors;\n  {\n    NSynchronization::CCriticalSectionLock lock(Sync._cs);\n    total = Sync._totalBytes;\n    completed = Sync._completedBytes;\n    totalFiles = Sync._totalFiles;\n    completedFiles = Sync._curFiles;\n    inSize = Sync._inSize;\n    outSize = Sync._outSize;\n    filesProgressMode = Sync._filesProgressMode;\n\n    GetChangedString(Sync._titleFileName, _titleFileName, titleFileName_Changed);\n    GetChangedString(Sync._filePath, _filePath, curFilePath_Changed);\n    GetChangedString(Sync._status, _status, status_Changed);\n    if (_isDir != Sync._isDir)\n    {\n      curFilePath_Changed = true;\n      _isDir = Sync._isDir;\n    }\n    numErrors = Sync.Messages.Size();\n  }\n\n  UInt32 curTime = ::GetTickCount();\n\n  const UInt64 progressTotal = filesProgressMode ? totalFiles : total;\n  const UInt64 progressCompleted = filesProgressMode ? completedFiles : completed;\n  {\n    if (IS_UNDEFINED_VAL(progressTotal))\n    {\n      // SetPos(0);\n      // SetRange(progressCompleted);\n    }\n    else\n    {\n      if (_progressBar_Pos != 0 || progressCompleted != 0 ||\n          (_progressBar_Range == 0 && progressTotal != 0))\n      {\n        SetProgressRange(progressTotal);\n        SetProgressPos(progressCompleted);\n      }\n    }\n  }\n\n  ShowSize(IDT_PROGRESS_TOTAL_VAL, total, _totalBytes_Prev);\n\n  _elapsedTime += (curTime - _prevTime);\n  _prevTime = curTime;\n  UInt64 elapsedSec = _elapsedTime / 1000;\n  bool elapsedChanged = false;\n  if (elapsedSec != _prevElapsedSec)\n  {\n    _prevElapsedSec = elapsedSec;\n    elapsedChanged = true;\n    wchar_t s[40];\n    GetTimeString(elapsedSec, s);\n    SetItemText(IDT_PROGRESS_ELAPSED_VAL, s);\n  }\n\n  bool needSetTitle = false;\n  if (elapsedChanged || showAll)\n  {\n    if (numErrors > _numPostedMessages)\n    {\n      UpdateMessagesDialog();\n      wchar_t s[32];\n      ConvertUInt64ToString(numErrors, s);\n      SetItemText(IDT_PROGRESS_ERRORS_VAL, s);\n      if (!_errorsWereDisplayed)\n      {\n        _errorsWereDisplayed = true;\n        EnableErrorsControls(true);\n        SetTaskbarProgressState();\n      }\n    }\n\n    if (progressCompleted != 0)\n    {\n      if (IS_UNDEFINED_VAL(progressTotal))\n      {\n        if (IS_DEFINED_VAL(_prevRemainingSec))\n        {\n          INIT_AS_UNDEFINED(_prevRemainingSec)\n          SetItemText(IDT_PROGRESS_REMAINING_VAL, L\"\");\n        }\n      }\n      else\n      {\n        UInt64 remainingTime = 0;\n        if (progressCompleted < progressTotal)\n          remainingTime = MyMultAndDiv(_elapsedTime, progressTotal - progressCompleted, progressCompleted);\n        UInt64 remainingSec = remainingTime / 1000;\n        if (remainingSec != _prevRemainingSec)\n        {\n          _prevRemainingSec = remainingSec;\n          wchar_t s[40];\n          GetTimeString(remainingSec, s);\n          SetItemText(IDT_PROGRESS_REMAINING_VAL, s);\n        }\n      }\n      {\n        const UInt64 elapsedTime = (_elapsedTime == 0) ? 1 : _elapsedTime;\n        // 22.02: progressCompleted can be for number of files\n        UInt64 v = (completed * 1000) / elapsedTime;\n        Byte c = 0;\n        unsigned moveBits = 0;\n             if (v >= ((UInt64)10000 << 10)) { moveBits = 20; c = 'M'; }\n        else if (v >= ((UInt64)10000 <<  0)) { moveBits = 10; c = 'K'; }\n        v >>= moveBits;\n        if (moveBits != _prevSpeed_MoveBits || v != _prevSpeed)\n        {\n          _prevSpeed_MoveBits = moveBits;\n          _prevSpeed = v;\n          wchar_t s[40];\n          ConvertUInt64ToString(v, s);\n          unsigned pos = MyStringLen(s);\n          s[pos++] = ' ';\n          if (moveBits != 0)\n            s[pos++] = c;\n          s[pos++] = 'B';\n          s[pos++] = '/';\n          s[pos++] = 's';\n          s[pos++] = 0;\n          SetItemText(IDT_PROGRESS_SPEED_VAL, s);\n        }\n      }\n    }\n\n    {\n      UInt64 percent = 0;\n      {\n        if (IS_DEFINED_VAL(progressTotal))\n        {\n          percent = progressCompleted * 100;\n          if (progressTotal != 0)\n            percent /= progressTotal;\n        }\n      }\n      if (percent != _prevPercentValue)\n      {\n        _prevPercentValue = percent;\n        needSetTitle = true;\n      }\n    }\n    \n    {\n      wchar_t s[64];\n      \n      ConvertUInt64ToString(completedFiles, s);\n      if (_filesStr_Prev != s)\n      {\n        _filesStr_Prev = s;\n        SetItemText(IDT_PROGRESS_FILES_VAL, s);\n      }\n      \n      s[0] = 0;\n      if (IS_DEFINED_VAL(totalFiles))\n      {\n        MyStringCopy(s, L\" / \");\n        ConvertUInt64ToString(totalFiles, s + MyStringLen(s));\n      }\n      if (_filesTotStr_Prev != s)\n      {\n        _filesTotStr_Prev = s;\n        SetItemText(IDT_PROGRESS_FILES_TOTAL, s);\n      }\n    }\n    \n    const UInt64 packSize   = CompressingMode ? outSize : inSize;\n    const UInt64 unpackSize = CompressingMode ? inSize : outSize;\n\n    if (IS_UNDEFINED_VAL(unpackSize) &&\n        IS_UNDEFINED_VAL(packSize))\n    {\n      ShowSize(IDT_PROGRESS_PROCESSED_VAL, completed, _processed_Prev);\n      ShowSize(IDT_PROGRESS_PACKED_VAL, UNDEFINED_VAL, _packed_Prev);\n    }\n    else\n    {\n      ShowSize(IDT_PROGRESS_PROCESSED_VAL, unpackSize, _processed_Prev);\n      ShowSize(IDT_PROGRESS_PACKED_VAL, packSize, _packed_Prev);\n      \n      if (IS_DEFINED_VAL(packSize) &&\n          IS_DEFINED_VAL(unpackSize) &&\n          unpackSize != 0)\n      {\n        wchar_t s[32];\n        UInt64 ratio = packSize * 100 / unpackSize;\n        if (_ratio_Prev != ratio)\n        {\n          _ratio_Prev = ratio;\n          ConvertUInt64ToString(ratio, s);\n          MyStringCat(s, L\"%\");\n          SetItemText(IDT_PROGRESS_RATIO_VAL, s);\n        }\n      }\n    }\n  }\n\n  if (needSetTitle || titleFileName_Changed)\n    SetTitleText();\n\n  if (status_Changed)\n  {\n    UString s = _status;\n    ReduceString(s, _numReduceSymbols);\n    SetItemText(IDT_PROGRESS_STATUS, s);\n  }\n\n  if (curFilePath_Changed)\n  {\n    UString s1, s2;\n    if (_isDir)\n      s1 = _filePath;\n    else\n    {\n      int slashPos = _filePath.ReverseFind_PathSepar();\n      if (slashPos >= 0)\n      {\n        s1.SetFrom(_filePath, (unsigned)(slashPos + 1));\n        s2 = _filePath.Ptr((unsigned)(slashPos + 1));\n      }\n      else\n        s2 = _filePath;\n    }\n    ReduceString(s1, _numReduceSymbols);\n    ReduceString(s2, _numReduceSymbols);\n    s1.Add_LF();\n    s1 += s2;\n    SetItemText(IDT_PROGRESS_FILE_NAME, s1);\n  }\n}\n\nbool CProgressDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)\n{\n  if (Sync.Get_Paused())\n    return true;\n  CheckNeedClose();\n  UpdateStatInfo(false);\n  return true;\n}\n\nstruct CWaitCursor\n{\n  HCURSOR _waitCursor;\n  HCURSOR _oldCursor;\n  CWaitCursor()\n  {\n    _waitCursor = LoadCursor(NULL, IDC_WAIT);\n    if (_waitCursor != NULL)\n      _oldCursor = SetCursor(_waitCursor);\n  }\n  ~CWaitCursor()\n  {\n    if (_waitCursor != NULL)\n      SetCursor(_oldCursor);\n  }\n};\n\nINT_PTR CProgressDialog::Create(const UString &title, NWindows::CThread &thread, HWND wndParent)\n{\n  INT_PTR res = 0;\n  try\n  {\n    if (WaitMode)\n    {\n      CWaitCursor waitCursor;\n      HANDLE h[] = { thread, _createDialogEvent };\n      \n      const DWORD res2 = WaitForMultipleObjects(Z7_ARRAY_SIZE(h), h, FALSE, kCreateDelay);\n      if (res2 == WAIT_OBJECT_0 && !Sync.ThereIsMessage())\n        return 0;\n    }\n    _title = title;\n    BIG_DIALOG_SIZE(360, 192);\n    res = CModalDialog::Create(SIZED_DIALOG(IDD_PROGRESS), wndParent);\n  }\n  catch(...)\n  {\n    _wasCreated = true;\n    _dialogCreatedEvent.Set();\n  }\n  thread.Wait_Close();\n  if (!MessagesDisplayed)\n  if (!g_DisableUserQuestions)\n  {\n    // **************** NanaZip Modification Start ****************\n    //MessageBoxW(wndParent, L\"Progress Error\", L\"7-Zip\", MB_ICONERROR);\n    MessageBoxW(wndParent, L\"Progress Error\", L\"NanaZip\", MB_ICONERROR);\n    // **************** NanaZip Modification End ****************\n  }\n  return res;\n}\n\nbool CProgressDialog::OnExternalCloseMessage()\n{\n  // it doesn't work if there is MessageBox.\n  // #ifdef __ITaskbarList3_INTERFACE_DEFINED__\n  SetTaskbarProgressState(TBPF_NOPROGRESS);\n  // #endif\n  // AddToTitle(L\"Finished \");\n  // SetText(L\"Finished2 \");\n\n  UpdateStatInfo(true);\n  \n  SetItemText(IDCANCEL, LangString(IDS_CLOSE));\n  ::SendMessage(GetItem(IDCANCEL), BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));\n  HideItem(IDB_PROGRESS_BACKGROUND);\n  HideItem(IDB_PAUSE);\n\n  ProcessWasFinished_GuiVirt();\n\n  bool thereAreMessages;\n  CProgressFinalMessage fm;\n  {\n    NSynchronization::CCriticalSectionLock lock(Sync._cs);\n    thereAreMessages = !Sync.Messages.IsEmpty();\n    fm = Sync.FinalMessage;\n  }\n\n  if (!fm.ErrorMessage.Message.IsEmpty())\n  {\n    MessagesDisplayed = true;\n    // **************** NanaZip Modification Start ****************\n    /*if (fm.ErrorMessage.Title.IsEmpty())\n      fm.ErrorMessage.Title = \"7-Zip\";*/\n    if (fm.ErrorMessage.Title.IsEmpty())\n      fm.ErrorMessage.Title = \"NanaZip\";\n    // **************** NanaZip Modification End ****************\n    if (!g_DisableUserQuestions)\n      MessageBoxW(*this, fm.ErrorMessage.Message, fm.ErrorMessage.Title, MB_ICONERROR);\n  }\n  else if (!thereAreMessages)\n  {\n    MessagesDisplayed = true;\n\n    if (!fm.OkMessage.Message.IsEmpty())\n    {\n      // **************** NanaZip Modification Start ****************\n      /*if (fm.OkMessage.Title.IsEmpty())\n        fm.OkMessage.Title = \"7-Zip\";*/\n      if (fm.OkMessage.Title.IsEmpty())\n        fm.OkMessage.Title = \"NanaZip\";\n      // **************** NanaZip Modification End ****************\n      if (!g_DisableUserQuestions)\n        MessageBoxW(*this, fm.OkMessage.Message, fm.OkMessage.Title, MB_OK);\n    }\n  }\n\n  if (!g_DisableUserQuestions)\n  if (thereAreMessages && !_cancelWasPressed)\n  {\n    _waitCloseByCancelButton = true;\n    UpdateMessagesDialog();\n    return true;\n  }\n\n  End(0);\n  return true;\n}\n\nbool CProgressDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\n{\n  switch (message)\n  {\n    case kCloseMessage:\n    {\n      if (_timer)\n      {\n        /* 21.03 : KillTimer(kTimerID) instead of KillTimer(_timer).\n           But (_timer == kTimerID) in Win10. So it worked too */\n        KillTimer(kTimerID);\n        _timer = 0;\n      }\n      if (_inCancelMessageBox)\n      {\n        /* if user is in MessageBox(), we will call OnExternalCloseMessage()\n           later, when MessageBox() will be closed */\n        _externalCloseMessageWasReceived = true;\n        break;\n      }\n      return OnExternalCloseMessage();\n    }\n    /*\n    case WM_SETTEXT:\n    {\n      if (_timer == 0)\n        return true;\n      break;\n    }\n    */\n  }\n  return CModalDialog::OnMessage(message, wParam, lParam);\n}\n\nvoid CProgressDialog::SetTitleText()\n{\n  UString s;\n  if (Sync.Get_Paused())\n  {\n    s += _paused_String;\n    s.Add_Space();\n  }\n  if (IS_DEFINED_VAL(_prevPercentValue))\n  {\n    s.Add_UInt64(_prevPercentValue);\n    s.Add_Char('%');\n  }\n  if (_background)\n  {\n    s.Add_Space();\n    s += _backgrounded_String;\n  }\n\n  s.Add_Space();\n  #ifndef Z7_SFX\n  {\n    unsigned len = s.Len();\n    s += MainAddTitle;\n    AddToTitle(s);\n    s.DeleteFrom(len);\n  }\n  #endif\n\n  s += _title;\n  if (!_titleFileName.IsEmpty())\n  {\n    UString fileName = _titleFileName;\n    ReduceString(fileName, kTitleFileNameSizeLimit);\n    s.Add_Space();\n    s += fileName;\n  }\n  SetText(s);\n}\n\nvoid CProgressDialog::SetPauseText()\n{\n  SetItemText(IDB_PAUSE, Sync.Get_Paused() ? _continue_String : _pause_String);\n  SetTitleText();\n}\n\nvoid CProgressDialog::OnPauseButton()\n{\n  bool paused = !Sync.Get_Paused();\n  Sync.Set_Paused(paused);\n  UInt32 curTime = ::GetTickCount();\n  if (paused)\n    _elapsedTime += (curTime - _prevTime);\n  SetTaskbarProgressState();\n  _prevTime = curTime;\n  SetPauseText();\n}\n\nvoid CProgressDialog::SetPriorityText()\n{\n  SetItemText(IDB_PROGRESS_BACKGROUND, _background ?\n      _foreground_String :\n      _background_String);\n  SetTitleText();\n}\n\nvoid CProgressDialog::OnPriorityButton()\n{\n  _background = !_background;\n  #ifndef UNDER_CE\n  SetPriorityClass(GetCurrentProcess(), _background ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS);\n  #endif\n  SetPriorityText();\n}\n\nvoid CProgressDialog::AddMessageDirect(LPCWSTR message, bool needNumber)\n{\n  wchar_t sz[16];\n  sz[0] = 0;\n  if (needNumber)\n    ConvertUInt32ToString(_numMessages + 1, sz);\n  const unsigned itemIndex = _messageStrings.Size(); // _messageList.GetItemCount();\n  if (_messageList.InsertItem(itemIndex, sz) == (int)itemIndex)\n  {\n    _messageList.SetSubItem(itemIndex, 1, message);\n    _messageStrings.Add(message);\n  }\n}\n\nvoid CProgressDialog::AddMessage(LPCWSTR message)\n{\n  UString s = message;\n  bool needNumber = true;\n  while (!s.IsEmpty())\n  {\n    const int pos = s.Find(L'\\n');\n    if (pos < 0)\n      break;\n    AddMessageDirect(s.Left((unsigned)pos), needNumber);\n    needNumber = false;\n    s.DeleteFrontal((unsigned)pos + 1);\n  }\n  AddMessageDirect(s, needNumber);\n  _numMessages++;\n}\n\nstatic unsigned GetNumDigits(unsigned val)\n{\n  unsigned i = 0;\n  for (;;)\n  {\n    i++;\n    val /= 10;\n    if (val == 0)\n      return i;\n  }\n}\n\nvoid CProgressDialog::UpdateMessagesDialog()\n{\n  UStringVector messages;\n  {\n    NSynchronization::CCriticalSectionLock lock(Sync._cs);\n    const unsigned num = Sync.Messages.Size();\n    if (num > _numPostedMessages)\n    {\n      messages.ClearAndReserve(num - _numPostedMessages);\n      for (unsigned i = _numPostedMessages; i < num; i++)\n        messages.AddInReserved(Sync.Messages[i]);\n      _numPostedMessages = num;\n    }\n  }\n  if (!messages.IsEmpty())\n  {\n    FOR_VECTOR (i, messages)\n      AddMessage(messages[i]);\n    // SetColumnWidthAuto() can be slow for big number of files.\n    if (_numPostedMessages < 1000000 || _numAutoSizeMessages < 100)\n    if (_numAutoSizeMessages < 100 ||\n        GetNumDigits(_numPostedMessages) >\n        GetNumDigits(_numAutoSizeMessages))\n    {\n      _messageList.SetColumnWidthAuto(0);\n      _messageList.SetColumnWidthAuto(1);\n      _numAutoSizeMessages = _numPostedMessages;\n    }\n  }\n}\n\n\nbool CProgressDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)\n{\n  switch (buttonID)\n  {\n    // case IDOK: // if IDCANCEL is not DEFPUSHBUTTON\n    case IDCANCEL:\n    {\n      if (_waitCloseByCancelButton)\n      {\n        MessagesDisplayed = true;\n        End(IDCLOSE);\n        break;\n      }\n      \n      if (_cancelWasPressed)\n        return true;\n        \n      const bool paused = Sync.Get_Paused();\n      \n      if (!paused)\n      {\n        OnPauseButton();\n      }\n\n      _inCancelMessageBox = true;\n      const int res = ::MessageBoxW(*this, LangString(IDS_PROGRESS_ASK_CANCEL), _title, MB_YESNOCANCEL);\n      _inCancelMessageBox = false;\n      if (res == IDYES)\n        _cancelWasPressed = true;\n      \n      if (!paused)\n      {\n        OnPauseButton();\n      }\n\n      if (_externalCloseMessageWasReceived)\n      {\n        /* we have received kCloseMessage while we were in MessageBoxW().\n           so we call OnExternalCloseMessage() here.\n           it can show MessageBox and it can close dialog */\n        OnExternalCloseMessage();\n        return true;\n      }\n\n      if (!_cancelWasPressed)\n        return true;\n\n      MessagesDisplayed = true;\n      // we will call Sync.Set_Stopped(true) in OnButtonClicked() : OnCancel()\n      break;\n    }\n\n    case IDB_PAUSE:\n      OnPauseButton();\n      return true;\n    case IDB_PROGRESS_BACKGROUND:\n      OnPriorityButton();\n      return true;\n  }\n  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\n}\n\nvoid CProgressDialog::CheckNeedClose()\n{\n  if (_needClose)\n  {\n    PostMsg(kCloseMessage);\n    _needClose = false;\n  }\n}\n\nvoid CProgressDialog::ProcessWasFinished()\n{\n  // Set Window title here.\n  if (!WaitMode)\n    WaitCreating();\n  \n  if (_wasCreated)\n    PostMsg(kCloseMessage);\n  else\n    _needClose = true;\n}\n\n\nbool CProgressDialog::OnNotify(UINT /* controlID */, LPNMHDR header)\n{\n  if (header->hwndFrom != _messageList)\n    return false;\n  switch (header->code)\n  {\n    case LVN_KEYDOWN:\n    {\n      LPNMLVKEYDOWN keyDownInfo = LPNMLVKEYDOWN(header);\n      switch (keyDownInfo->wVKey)\n      {\n        case 'A':\n        {\n          if (IsKeyDown(VK_CONTROL))\n          {\n            _messageList.SelectAll();\n            return true;\n          }\n          break;\n        }\n        case VK_INSERT:\n        case 'C':\n        {\n          if (IsKeyDown(VK_CONTROL))\n          {\n            CopyToClipboard();\n            return true;\n          }\n          break;\n        }\n      }\n    }\n  }\n  return false;\n}\n\n\nstatic void ListView_GetSelected(NControl::CListView &listView, CUIntVector &vector)\n{\n  vector.Clear();\n  int index = -1;\n  for (;;)\n  {\n    index = listView.GetNextSelectedItem(index);\n    if (index < 0)\n      break;\n    vector.Add((unsigned)index);\n  }\n}\n\n\nvoid CProgressDialog::CopyToClipboard()\n{\n  CUIntVector indexes;\n  ListView_GetSelected(_messageList, indexes);\n  UString s;\n  unsigned numIndexes = indexes.Size();\n  if (numIndexes == 0)\n    numIndexes = (unsigned)_messageList.GetItemCount();\n  \n  for (unsigned i = 0; i < numIndexes; i++)\n  {\n    const unsigned index = (i < indexes.Size() ? indexes[i] : i);\n    // s.Add_UInt32(index);\n    // s += \": \";\n    s += _messageStrings[index];\n    {\n      s +=\n        #ifdef _WIN32\n          \"\\r\\n\"\n        #else\n          \"\\n\"\n        #endif\n        ;\n    }\n  }\n  \n  ClipboardSetText(*this, s);\n}\n\n\nstatic THREAD_FUNC_DECL MyThreadFunction(void *param)\n{\n  CProgressThreadVirt *p = (CProgressThreadVirt *)param;\n  try\n  {\n    p->Process();\n    p->ThreadFinishedOK = true;\n  }\n  catch (...) { p->Result = E_FAIL; }\n  return 0;\n}\n\n\nHRESULT CProgressThreadVirt::Create(const UString &title, HWND parentWindow)\n{\n  NWindows::CThread thread;\n  const WRes wres = thread.Create(MyThreadFunction, this);\n  if (wres != 0)\n    return HRESULT_FROM_WIN32(wres);\n  CProgressDialog::Create(title, thread, parentWindow);\n  return S_OK;\n}\n\nstatic void AddMessageToString(UString &dest, const UString &src)\n{\n  if (!src.IsEmpty())\n  {\n    if (!dest.IsEmpty())\n      dest.Add_LF();\n    dest += src;\n  }\n}\n\nvoid CProgressThreadVirt::Process()\n{\n  CProgressCloser closer(*this);\n  UString m;\n  try { Result = ProcessVirt(); }\n  catch(const wchar_t *s) { m = s; }\n  catch(const UString &s) { m = s; }\n  catch(const char *s) { m = GetUnicodeString(s); }\n  catch(int v)\n  {\n    m = \"Error #\";\n    m.Add_UInt32((unsigned)v);\n  }\n  catch(...) { m = \"Error\"; }\n  if (Result != E_ABORT)\n  {\n    if (m.IsEmpty() && Result != S_OK)\n      m = HResultToMessage(Result);\n  }\n  AddMessageToString(m, FinalMessage.ErrorMessage.Message);\n\n  {\n    FOR_VECTOR(i, ErrorPaths)\n    {\n      if (i >= 32)\n        break;\n      AddMessageToString(m, fs2us(ErrorPaths[i]));\n    }\n  }\n\n  CProgressSync &sync = Sync;\n  NSynchronization::CCriticalSectionLock lock(sync._cs);\n  if (m.IsEmpty())\n  {\n    if (!FinalMessage.OkMessage.Message.IsEmpty())\n      sync.FinalMessage.OkMessage = FinalMessage.OkMessage;\n  }\n  else\n  {\n    sync.FinalMessage.ErrorMessage.Message = m;\n    if (Result == S_OK)\n      Result = E_FAIL;\n  }\n}\n\nUString HResultToMessage(HRESULT errorCode)\n{\n  if (errorCode == E_OUTOFMEMORY)\n    return LangString(IDS_MEM_ERROR);\n  else\n    return NError::MyFormatMessage(errorCode);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialog2.h",
    "content": "﻿// ProgressDialog2.h\n\n#ifndef ZIP7_INC_PROGRESS_DIALOG_2_H\n#define ZIP7_INC_PROGRESS_DIALOG_2_H\n\n#include \"../../../Common/MyCom.h\"\n\n#include \"../../../Windows/ErrorMsg.h\"\n#include \"../../../Windows/Synchronization.h\"\n#include \"../../../Windows/Thread.h\"\n\n#include \"../../../Windows/Control/Dialog.h\"\n#include \"../../../Windows/Control/ListView.h\"\n#include \"../../../Windows/Control/ProgressBar.h\"\n\n#include \"MyWindowsNew.h\"\n\nstruct CProgressMessageBoxPair\n{\n  UString Title;\n  UString Message;\n};\n\nstruct CProgressFinalMessage\n{\n  CProgressMessageBoxPair ErrorMessage;\n  CProgressMessageBoxPair OkMessage;\n\n  bool ThereIsMessage() const { return !ErrorMessage.Message.IsEmpty() || !OkMessage.Message.IsEmpty(); }\n};\n\nclass CProgressSync\n{\n  bool _stopped;\n  bool _paused;\npublic:\n  bool _filesProgressMode;\n  bool _isDir;\n  UInt64 _totalBytes;\n  UInt64 _completedBytes;\n  UInt64 _totalFiles;\n  UInt64 _curFiles;\n  UInt64 _inSize;\n  UInt64 _outSize;\n  \n  UString _titleFileName;\n  UString _status;\n  UString _filePath;\n\n  UStringVector Messages;\n  CProgressFinalMessage FinalMessage;\n\n  NWindows::NSynchronization::CCriticalSection _cs;\n\n  CProgressSync();\n\n  bool Get_Stopped()\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    return _stopped;\n  }\n  void Set_Stopped(bool val)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    _stopped = val;\n  }\n  \n  bool Get_Paused();\n  void Set_Paused(bool val)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    _paused = val;\n  }\n  \n  void Set_FilesProgressMode(bool filesProgressMode)\n  {\n    NWindows::NSynchronization::CCriticalSectionLock lock(_cs);\n    _filesProgressMode = filesProgressMode;\n  }\n  \n  HRESULT CheckStop();\n  void Clear_Stop_Status();\n  HRESULT ScanProgress(UInt64 numFiles, UInt64 totalSize, const FString &fileName, bool isDir = false);\n\n  HRESULT Set_NumFilesTotal(UInt64 val);\n  void Set_NumBytesTotal(UInt64 val);\n  void Set_NumFilesCur(UInt64 val);\n  HRESULT Set_NumBytesCur(const UInt64 *val);\n  HRESULT Set_NumBytesCur(UInt64 val);\n  void Set_Ratio(const UInt64 *inSize, const UInt64 *outSize);\n\n  void Set_TitleFileName(const UString &fileName);\n  void Set_Status(const UString &s);\n  HRESULT Set_Status2(const UString &s, const wchar_t *path, bool isDir = false);\n  void Set_FilePath(const wchar_t *path, bool isDir = false);\n\n  void AddError_Message(const wchar_t *message);\n  void AddError_Message_Name(const wchar_t *message, const wchar_t *name);\n  // void AddError_Code_Name(DWORD systemError, const wchar_t *name);\n  void AddError_Code_Name(HRESULT systemError, const wchar_t *name);\n\n  bool ThereIsMessage() const { return !Messages.IsEmpty() || FinalMessage.ThereIsMessage(); }\n};\n\n\nclass CProgressDialog: public NWindows::NControl::CModalDialog\n{\n  bool _isDir;\n  bool _wasCreated;\n  bool _needClose;\n  bool _errorsWereDisplayed;\n  bool _waitCloseByCancelButton;\n  bool _cancelWasPressed;\n  bool _inCancelMessageBox;\n  bool _externalCloseMessageWasReceived;\n  bool _background;\npublic:\n  bool WaitMode;\n  bool MessagesDisplayed; // = true if user pressed OK on all messages or there are no messages.\n  bool CompressingMode;\n  bool ShowCompressionInfo;\n\nprivate:\n  unsigned _numPostedMessages;\n  unsigned _numAutoSizeMessages;\n  unsigned _numMessages;\n\n  UString _titleFileName;\n  UString _filePath;\n  UString _status;\n\n  UString _background_String;\n  UString _backgrounded_String;\n  UString _foreground_String;\n  UString _pause_String;\n  UString _continue_String;\n  UString _paused_String;\n\n  int _buttonSizeX;\n  int _buttonSizeY;\n\n  UINT_PTR _timer;\n\n  UString _title;\n\n  class CU64ToI32Converter\n  {\n    unsigned _numShiftBits;\n    UInt64 _range;\n  public:\n    CU64ToI32Converter(): _numShiftBits(0), _range(1) {}\n    void Init(UInt64 range)\n    {\n      _range = range;\n      // Windows CE doesn't like big number for ProgressBar.\n      for (_numShiftBits = 0; range >= ((UInt32)1 << 15); _numShiftBits++)\n        range >>= 1;\n    }\n    int Count(UInt64 val)\n    {\n      int res = (int)(val >> _numShiftBits);\n      if (val == _range)\n        res++;\n      return res;\n    }\n  };\n  \n  CU64ToI32Converter _progressConv;\n  UInt64 _progressBar_Pos;\n  UInt64 _progressBar_Range;\n  \n  NWindows::NControl::CProgressBar m_ProgressBar;\n  NWindows::NControl::CListView _messageList;\n  \n  UStringVector _messageStrings;\n\n  // #ifdef __ITaskbarList3_INTERFACE_DEFINED__\n  CMyComPtr<ITaskbarList3> _taskbarList;\n  // #endif\n  HWND _hwndForTaskbar;\n\n  UInt32 _prevTime;\n  UInt64 _elapsedTime;\n\n  UInt64 _prevPercentValue;\n  UInt64 _prevElapsedSec;\n  UInt64 _prevRemainingSec;\n\n  UInt64 _totalBytes_Prev;\n  UInt64 _processed_Prev;\n  UInt64 _packed_Prev;\n  UInt64 _ratio_Prev;\n\n  UString _filesStr_Prev;\n  UString _filesTotStr_Prev;\n\n  unsigned _numReduceSymbols;\n  unsigned _prevSpeed_MoveBits;\n  UInt64 _prevSpeed;\n\n  // #ifdef __ITaskbarList3_INTERFACE_DEFINED__\n  void SetTaskbarProgressState(TBPFLAG tbpFlags)\n  {\n    if (_taskbarList && _hwndForTaskbar)\n      _taskbarList->SetProgressState(_hwndForTaskbar, tbpFlags);\n  }\n  // #endif\n  void SetTaskbarProgressState();\n\n  void UpdateStatInfo(bool showAll);\n  void SetProgressRange(UInt64 range);\n  void SetProgressPos(UInt64 pos);\n  virtual bool OnTimer(WPARAM timerID, LPARAM callback) Z7_override;\n  virtual bool OnInit() Z7_override;\n  virtual bool OnSize(WPARAM wParam, int xSize, int ySize) Z7_override;\n  virtual void OnCancel() Z7_override;\n  virtual void OnOK() Z7_override;\n  virtual bool OnNotify(UINT /* controlID */, LPNMHDR header) Z7_override;\n  void CopyToClipboard();\n\n  NWindows::NSynchronization::CManualResetEvent _createDialogEvent;\n  NWindows::NSynchronization::CManualResetEvent _dialogCreatedEvent;\n  #ifndef Z7_SFX\n  void AddToTitle(LPCWSTR string);\n  #endif\n\n  void SetPauseText();\n  void SetPriorityText();\n  void OnPauseButton();\n  void OnPriorityButton();\n  bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;\n  bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam) Z7_override;\n\n  void SetTitleText();\n  void ShowSize(unsigned id, UInt64 val, UInt64 &prev);\n\n  void UpdateMessagesDialog();\n\n  void AddMessageDirect(LPCWSTR message, bool needNumber);\n  void AddMessage(LPCWSTR message);\n\n  bool OnExternalCloseMessage();\n  void EnableErrorsControls(bool enable);\n\n  void ShowAfterMessages(HWND wndParent);\n\n  void CheckNeedClose();\n\npublic:\n  CProgressSync Sync;\n  int IconID;\n  HWND MainWindow;\n  #ifndef Z7_SFX\n  UString MainTitle;\n  UString MainAddTitle;\n  ~CProgressDialog() Z7_DESTRUCTOR_override;\n  #endif\n\n  CProgressDialog();\n  void WaitCreating()\n  {\n    _createDialogEvent.Set();\n    _dialogCreatedEvent.Lock();\n  }\n\n  INT_PTR Create(const UString &title, NWindows::CThread &thread, HWND wndParent = NULL);\n\n\n  /* how it works:\n     1) the working thread calls ProcessWasFinished()\n        that sends kCloseMessage message to CProgressDialog (GUI) thread\n     2) CProgressDialog (GUI) thread receives kCloseMessage message and\n        calls ProcessWasFinished_GuiVirt();\n        So we can implement ProcessWasFinished_GuiVirt() and show special\n        results window in GUI thread with CProgressDialog as parent window\n  */\n\n  void ProcessWasFinished();\n  virtual void ProcessWasFinished_GuiVirt() {}\n};\n\n\nclass CProgressCloser\n{\n  CProgressDialog *_p;\npublic:\n  CProgressCloser(CProgressDialog &p) : _p(&p) {}\n  ~CProgressCloser() { _p->ProcessWasFinished(); }\n};\n\n\nclass CProgressThreadVirt: public CProgressDialog\n{\nprotected:\n  FStringVector ErrorPaths;\n  CProgressFinalMessage FinalMessage;\n\n  // error if any of HRESULT, ErrorMessage, ErrorPath\n  virtual HRESULT ProcessVirt() = 0;\npublic:\n  HRESULT Result;\n  bool ThreadFinishedOK; // if there is no fatal exception\n\n  void Process();\n  void AddErrorPath(const FString &path) { ErrorPaths.Add(path); }\n\n  HRESULT Create(const UString &title, HWND parentWindow = NULL);\n  CProgressThreadVirt(): Result(E_FAIL), ThreadFinishedOK(false) {}\n\n  CProgressMessageBoxPair &GetMessagePair(bool isError) { return isError ? FinalMessage.ErrorMessage : FinalMessage.OkMessage; }\n};\n\nUString HResultToMessage(HRESULT errorCode);\n\n/*\nhow it works:\n\nclient code inherits CProgressThreadVirt and calls\nCProgressThreadVirt::Create()\n{\n  it creates new thread that calls CProgressThreadVirt::Process();\n  it creates modal progress dialog window with ProgressDialog.Create()\n}\n\nCProgressThreadVirt::Process()\n{\n  {\n    Result = ProcessVirt(); // virtual function that must implement real work\n  }\n  if (exceptions) or FinalMessage.ErrorMessage.Message\n  {\n    set message to ProgressDialog.Sync.FinalMessage.ErrorMessage.Message\n  }\n  else if (FinalMessage.OkMessage.Message)\n  {\n    set message to ProgressDialog.Sync.FinalMessage.OkMessage\n  }\n\n  PostMsg(kCloseMessage);\n}\n\n\nCProgressDialog::OnExternalCloseMessage()\n{\n  if (ProgressDialog.Sync.FinalMessage)\n  {\n    WorkWasFinishedVirt();\n    Show (ProgressDialog.Sync.FinalMessage)\n    MessagesDisplayed = true;\n  }\n}\n\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialog2Res.h",
    "content": "﻿#define IDD_PROGRESS       97\n#define IDD_PROGRESS_2  10097\n\n#define IDS_CLOSE                  408\n#define IDS_CONTINUE               411\n\n#define IDB_PROGRESS_BACKGROUND    444\n#define IDS_PROGRESS_FOREGROUND    445\n#define IDB_PAUSE                  446\n#define IDS_PROGRESS_PAUSED        447\n#define IDS_PROGRESS_ASK_CANCEL    448\n\n#define IDT_PROGRESS_PACKED       1008\n#define IDT_PROGRESS_FILES        1032\n\n#define IDT_PROGRESS_ELAPSED      3900\n#define IDT_PROGRESS_REMAINING    3901\n#define IDT_PROGRESS_TOTAL        3902\n#define IDT_PROGRESS_SPEED        3903\n#define IDT_PROGRESS_PROCESSED    3904\n#define IDT_PROGRESS_RATIO        3905\n#define IDT_PROGRESS_ERRORS       3906\n\n#define IDC_PROGRESS1              100\n#define IDL_PROGRESS_MESSAGES      101\n#define IDT_PROGRESS_FILE_NAME     102\n#define IDT_PROGRESS_STATUS        103\n\n#define IDT_PROGRESS_PACKED_VAL    110\n#define IDT_PROGRESS_FILES_VAL     111\n#define IDT_PROGRESS_FILES_TOTAL   112\n\n#define IDT_PROGRESS_ELAPSED_VAL   120\n#define IDT_PROGRESS_REMAINING_VAL 121\n#define IDT_PROGRESS_TOTAL_VAL     122\n#define IDT_PROGRESS_SPEED_VAL     123\n#define IDT_PROGRESS_PROCESSED_VAL 124\n#define IDT_PROGRESS_RATIO_VAL     125\n#define IDT_PROGRESS_ERRORS_VAL    126\n\n\n#ifdef UNDER_CE\n#define MY_PROGRESS_VAL_UNITS  44\n#else\n#define MY_PROGRESS_VAL_UNITS  72\n#endif\n#define MY_PROGRESS_LABEL_UNITS_MIN   60\n#define MY_PROGRESS_LABEL_UNITS_START 90\n#define MY_PROGRESS_PAD_UNITS  4\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialog2a.rc",
    "content": "#undef bxs\n#define bxs 80\n\n#define x0s MY_PROGRESS_LABEL_UNITS_START\n#define x1s MY_PROGRESS_VAL_UNITS\n#define x2s MY_PROGRESS_LABEL_UNITS_START\n#define x3s MY_PROGRESS_VAL_UNITS\n\n#define x1 (m + x0s)\n#define x3 (xs - m - x3s)\n#define x2 (x3 - x2s)\n\n#undef y0\n#undef y1\n#undef y2\n#undef y3\n#undef y4\n\n#undef z0\n#undef z1\n#undef z2\n#undef z3\n\n#define y0 m\n#define y1 (y0 + k)\n#define y2 (y1 + k)\n#define y3 (y2 + k)\n#define y4 (y3 + k)\n\n#define z3 (y4 + k + 1)\n\n#define z2 (z3 + k + 1)\n#define z2s 24\n\n#define z1 (z2 + z2s)\n\n#define z0 (z1 + z1s + m)\n#define z0s 48\n\n#define yc (z0 + z0s + bys)\n\n\nDIALOG_ID  DIALOG  0, 0, xs, ys  MY_MODAL_RESIZE_DIALOG_STYLE  MY_FONT\nCAPTION \"Progress\"\n{\n  DEFPUSHBUTTON  \"&Background\", IDB_PROGRESS_BACKGROUND, bx3, by, bxs, bys\n  PUSHBUTTON     \"&Pause\",      IDB_PAUSE,               bx2, by, bxs, bys\n  PUSHBUTTON     \"Cancel\",      IDCANCEL,                bx1, by, bxs, bys\n\n\n  LTEXT  \"Elapsed time:\",      IDT_PROGRESS_ELAPSED,   m, y0, x0s, 8\n  LTEXT  \"Remaining time:\",    IDT_PROGRESS_REMAINING, m, y1, x0s, 8\n  LTEXT  \"Files:\",             IDT_PROGRESS_FILES,     m, y2, x0s, 8\n\n  LTEXT  \"Errors:\",            IDT_PROGRESS_ERRORS,    m, y4, x0s, 8\n\n\n  LTEXT  \"Total size:\",        IDT_PROGRESS_TOTAL,    x2, y0, x2s, 8\n  LTEXT  \"Speed:\",             IDT_PROGRESS_SPEED,    x2, y1, x2s, 8\n  LTEXT  \"Processed:\",         IDT_PROGRESS_PROCESSED,x2, y2, x2s, 8\n  LTEXT  \"Compressed size:\"  , IDT_PROGRESS_PACKED,   x2, y3, x2s, 8\n  LTEXT  \"Compression ratio:\", IDT_PROGRESS_RATIO,    x2, y4, x2s, 8\n\n  \n  RTEXT  \"\",  IDT_PROGRESS_ELAPSED_VAL,   x1, y0, x1s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_REMAINING_VAL, x1, y1, x1s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_FILES_VAL,     x1, y2, x1s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_FILES_TOTAL,   x1, y3, x1s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_ERRORS_VAL,    x1, y4, x1s, MY_TEXT_NOPREFIX\n\n  RTEXT  \"\",  IDT_PROGRESS_TOTAL_VAL,     x3, y0, x3s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_SPEED_VAL,     x3, y1, x3s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_PROCESSED_VAL, x3, y2, x3s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_PACKED_VAL,    x3, y3, x3s, MY_TEXT_NOPREFIX\n  RTEXT  \"\",  IDT_PROGRESS_RATIO_VAL,     x3, y4, x3s, MY_TEXT_NOPREFIX\n\n  LTEXT  \"\", IDT_PROGRESS_STATUS, m, z3, xc, MY_TEXT_NOPREFIX\n  CONTROL  \"\", IDT_PROGRESS_FILE_NAME, \"Static\", SS_NOPREFIX | SS_LEFTNOWORDWRAP, m, z2, xc, z2s\n  \n  CONTROL  \"Progress1\", IDC_PROGRESS1, \"msctls_progress32\", PBS_SMOOTH | WS_BORDER, m, z1, xc, z1s\n\n  CONTROL  \"List1\", IDL_PROGRESS_MESSAGES, \"SysListView32\",\n           LVS_REPORT | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,\n           m, z0, xc, z0s\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/ProgressDialogRes.h",
    "content": "﻿#define IDD_PROGRESS  97\n\n#define IDC_PROGRESS1  100\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/PropertyName.cpp",
    "content": "﻿// PropertyName.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n\n#include \"LangUtils.h\"\n#include \"PropertyName.h\"\n\nUString GetNameOfProperty(PROPID propID, const wchar_t *name)\n{\n  if (propID < 1000)\n  {\n    UString s = LangString(1000 + propID);\n    if (!s.IsEmpty())\n      return s;\n  }\n  if (name)\n    return name;\n  wchar_t temp[16];\n  ConvertUInt32ToString(propID, temp);\n  return temp;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/PropertyName.h",
    "content": "﻿// PropertyName.h\n\n#ifndef ZIP7_INC_PROPERTY_NAME_H\n#define ZIP7_INC_PROPERTY_NAME_H\n\n#include \"../../../Common/MyString.h\"\n\nUString GetNameOfProperty(PROPID propID, const wchar_t *name);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/PropertyNameRes.h",
    "content": "﻿\n\n#define IDS_PROP_PATH             1003\n#define IDS_PROP_NAME             1004\n#define IDS_PROP_EXTENSION        1005\n#define IDS_PROP_IS_FOLDER        1006\n#define IDS_PROP_SIZE             1007\n#define IDS_PROP_PACKED_SIZE      1008\n#define IDS_PROP_ATTRIBUTES       1009\n#define IDS_PROP_CTIME            1010\n#define IDS_PROP_ATIME            1011\n#define IDS_PROP_MTIME            1012\n#define IDS_PROP_SOLID            1013\n#define IDS_PROP_C0MMENTED        1014\n#define IDS_PROP_ENCRYPTED        1015\n#define IDS_PROP_SPLIT_BEFORE     1016\n#define IDS_PROP_SPLIT_AFTER      1017\n#define IDS_PROP_DICTIONARY_SIZE  1018\n#define IDS_PROP_CRC              1019\n#define IDS_PROP_FILE_TYPE        1020\n#define IDS_PROP_ANTI             1021\n#define IDS_PROP_METHOD           1022\n#define IDS_PROP_HOST_OS          1023\n#define IDS_PROP_FILE_SYSTEM      1024\n#define IDS_PROP_USER             1025\n#define IDS_PROP_GROUP            1026\n#define IDS_PROP_BLOCK            1027\n#define IDS_PROP_COMMENT          1028\n#define IDS_PROP_POSITION         1029\n#define IDS_PROP_PREFIX           1030\n#define IDS_PROP_FOLDERS          1031\n#define IDS_PROP_FILES            1032\n#define IDS_PROP_VERSION          1033\n#define IDS_PROP_VOLUME           1034\n#define IDS_PROP_IS_VOLUME        1035\n#define IDS_PROP_OFFSET           1036\n#define IDS_PROP_LINKS            1037\n#define IDS_PROP_NUM_BLOCKS       1038\n#define IDS_PROP_NUM_VOLUMES      1039\n\n#define IDS_PROP_BIT64            1041\n#define IDS_PROP_BIG_ENDIAN       1042\n#define IDS_PROP_CPU              1043\n#define IDS_PROP_PHY_SIZE         1044\n#define IDS_PROP_HEADERS_SIZE     1045\n#define IDS_PROP_CHECKSUM         1046\n#define IDS_PROP_CHARACTS         1047\n#define IDS_PROP_VA               1048\n#define IDS_PROP_ID               1049\n#define IDS_PROP_SHORT_NAME       1050\n#define IDS_PROP_CREATOR_APP      1051\n#define IDS_PROP_SECTOR_SIZE      1052\n#define IDS_PROP_POSIX_ATTRIB     1053\n#define IDS_PROP_SYM_LINK         1054\n#define IDS_PROP_ERROR            1055\n#define IDS_PROP_TOTAL_SIZE       1056\n#define IDS_PROP_FREE_SPACE       1057\n#define IDS_PROP_CLUSTER_SIZE     1058\n#define IDS_PROP_VOLUME_NAME      1059\n#define IDS_PROP_LOCAL_NAME       1060\n#define IDS_PROP_PROVIDER         1061\n#define IDS_PROP_NT_SECURITY      1062\n#define IDS_PROP_ALT_STREAM       1063\n#define IDS_PROP_AUX              1064\n#define IDS_PROP_DELETED          1065\n#define IDS_PROP_IS_TREE          1066\n#define IDS_PROP_SHA1             1067\n#define IDS_PROP_SHA256           1068\n#define IDS_PROP_ERROR_TYPE       1069\n#define IDS_PROP_NUM_ERRORS       1070\n#define IDS_PROP_ERROR_FLAGS      1071\n#define IDS_PROP_WARNING_FLAGS    1072\n#define IDS_PROP_WARNING          1073\n#define IDS_PROP_NUM_STREAMS      1074\n#define IDS_PROP_NUM_ALT_STREAMS  1075\n#define IDS_PROP_ALT_STREAMS_SIZE 1076\n#define IDS_PROP_VIRTUAL_SIZE     1077\n#define IDS_PROP_UNPACK_SIZE      1078\n#define IDS_PROP_TOTAL_PHY_SIZE   1079\n#define IDS_PROP_VOLUME_INDEX     1080\n#define IDS_PROP_SUBTYPE          1081\n#define IDS_PROP_SHORT_COMMENT    1082\n#define IDS_PROP_CODE_PAGE        1083\n#define IDS_PROP_IS_NOT_ARC_TYPE  1084\n#define IDS_PROP_PHY_SIZE_CANT_BE_DETECTED 1085\n#define IDS_PROP_ZEROS_TAIL_IS_ALLOWED 1086\n#define IDS_PROP_TAIL_SIZE        1087\n#define IDS_PROP_EMB_STUB_SIZE    1088\n#define IDS_PROP_NT_REPARSE       1089\n#define IDS_PROP_HARD_LINK        1090\n#define IDS_PROP_INODE            1091\n#define IDS_PROP_STREAM_ID        1092\n#define IDS_PROP_READ_ONLY        1093\n#define IDS_PROP_OUT_NAME         1094\n#define IDS_PROP_COPY_LINK        1095\n#define IDS_PROP_ARC_FILE_NAME    1096\n#define IDS_PROP_IS_HASH          1097\n#define IDS_PROP_CHANGE_TIME      1098\n#define IDS_PROP_USER_ID          1099\n#define IDS_PROP_GROUP_ID         1100\n#define IDS_PROP_DEVICE_MAJOR     1101\n#define IDS_PROP_DEVICE_MINOR     1102\n#define IDS_PROP_DEV_MAJOR        1103\n#define IDS_PROP_DEV_MINOR        1104\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/RegistryUtils.cpp",
    "content": "﻿// RegistryUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n\n#include \"../../../Windows/Registry.h\"\n\n#include \"RegistryUtils.h\"\n\nusing namespace NWindows;\nusing namespace NRegistry;\n\n// **************** NanaZip Modification Start ****************\n//#define REG_PATH_7Z TEXT(\"Software\") TEXT(STRING_PATH_SEPARATOR) TEXT(\"7-Zip\")\n#define REG_PATH_7Z TEXT(\"Software\") TEXT(STRING_PATH_SEPARATOR) TEXT(\"NanaZip\")\n// **************** NanaZip Modification End ****************\n\nstatic LPCTSTR const kCUBasePath = REG_PATH_7Z;\nstatic LPCTSTR const kCU_FMPath = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT(\"FM\");\n// static LPCTSTR const kLM_Path = REG_PATH_7Z TEXT(STRING_PATH_SEPARATOR) TEXT(\"FM\");\n\nstatic LPCWSTR const kLangValueName = L\"Lang\";\n\nstatic LPCWSTR const kViewer = L\"Viewer\";\nstatic LPCWSTR const kEditor = L\"Editor\";\nstatic LPCWSTR const kDiff = L\"Diff\";\nstatic LPCWSTR const kVerCtrlPath = L\"7vc\";\n\nstatic LPCTSTR const kShowDots = TEXT(\"ShowDots\");\nstatic LPCTSTR const kShowRealFileIcons = TEXT(\"ShowRealFileIcons\");\nstatic LPCTSTR const kFullRow = TEXT(\"FullRow\");\nstatic LPCTSTR const kShowGrid = TEXT(\"ShowGrid\");\nstatic LPCTSTR const kSingleClick = TEXT(\"SingleClick\");\nstatic LPCTSTR const kAlternativeSelection = TEXT(\"AlternativeSelection\");\n// static LPCTSTR const kUnderline = TEXT(\"Underline\");\n\nstatic LPCTSTR const kShowSystemMenu = TEXT(\"ShowSystemMenu\");\n\n// static LPCTSTR const kLockMemoryAdd = TEXT(\"LockMemoryAdd\");\nstatic LPCTSTR const kLargePages = TEXT(\"LargePages\");\n\n// **************** 7-Zip ZS Modification Start ****************\n// they default to off (0) in 7-Zip ZS /TR\nstatic LPCTSTR const kArcHistory = TEXT(\"WantArcHistory\");\nstatic LPCTSTR const kPathHistory = TEXT(\"WantPathHistory\");\nstatic LPCTSTR const kCopyHistory = TEXT(\"WantCopyHistory\");\nstatic LPCTSTR const kFolderHistory = TEXT(\"WantFolderHistory\");\nstatic LPCTSTR const kLowercaseHashes = TEXT(\"LowercaseHashes\");\n// **************** 7-Zip ZS Modification End ****************\n\nstatic LPCTSTR const kFlatViewName = TEXT(\"FlatViewArc\");\n// static LPCTSTR const kShowDeletedFiles = TEXT(\"ShowDeleted\");\n\nstatic void SaveCuString(LPCTSTR keyPath, LPCWSTR valuePath, LPCWSTR value)\n{\n  CKey key;\n  key.Create(HKEY_CURRENT_USER, keyPath);\n  key.SetValue(valuePath, value);\n}\n\nstatic void ReadCuString(LPCTSTR keyPath, LPCWSTR valuePath, UString &res)\n{\n  res.Empty();\n  CKey key;\n  if (key.Open(HKEY_CURRENT_USER, keyPath, KEY_READ) == ERROR_SUCCESS)\n    key.QueryValue(valuePath, res);\n}\n\nvoid SaveRegLang(const UString &path) { SaveCuString(kCUBasePath, kLangValueName, path); }\nvoid ReadRegLang(UString &path) { ReadCuString(kCUBasePath, kLangValueName, path); }\n\nvoid SaveRegEditor(bool useEditor, const UString &path) { SaveCuString(kCU_FMPath, useEditor ? kEditor : kViewer, path); }\nvoid ReadRegEditor(bool useEditor, UString &path) { ReadCuString(kCU_FMPath, useEditor ? kEditor : kViewer, path); }\n\nvoid SaveRegDiff(const UString &path) { SaveCuString(kCU_FMPath, kDiff, path); }\nvoid ReadRegDiff(UString &path) { ReadCuString(kCU_FMPath, kDiff, path); }\n\nvoid ReadReg_VerCtrlPath(UString &path) { ReadCuString(kCU_FMPath, kVerCtrlPath, path); }\n\nstatic void Save7ZipOption(LPCTSTR value, bool enabled)\n{\n  CKey key;\n  key.Create(HKEY_CURRENT_USER, kCUBasePath);\n  key.SetValue(value, enabled);\n}\n\nstatic void SaveOption(LPCTSTR value, bool enabled)\n{\n  CKey key;\n  key.Create(HKEY_CURRENT_USER, kCU_FMPath);\n  key.SetValue(value, enabled);\n}\n\nstatic bool Read7ZipOption(LPCTSTR value, bool defaultValue)\n{\n  CKey key;\n  if (key.Open(HKEY_CURRENT_USER, kCUBasePath, KEY_READ) == ERROR_SUCCESS)\n  {\n    bool enabled;\n    if (key.GetValue_bool_IfOk(value, enabled) == ERROR_SUCCESS)\n      return enabled;\n  }\n  return defaultValue;\n}\n\n// **************** 7-Zip ZS Modification Start ****************\nstatic bool ReadFMOption(LPCTSTR value, bool enabled=false)\n{\n  CKey key;\n  if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS)\n  {\n    if (key.QueryValue(value, enabled) == ERROR_SUCCESS)\n      return enabled;\n  }\n  return enabled;\n}\n// **************** 7-Zip ZS Modification End ****************\n\nstatic void ReadOption(CKey &key, LPCTSTR name, bool &dest)\n{\n  key.GetValue_bool_IfOk(name, dest);\n}\n\n/*\nstatic void SaveLmOption(LPCTSTR value, bool enabled)\n{\n  CKey key;\n  key.Create(HKEY_LOCAL_MACHINE, kLM_Path);\n  key.SetValue(value, enabled);\n}\n\nstatic bool ReadLmOption(LPCTSTR value, bool defaultValue)\n{\n  CKey key;\n  if (key.Open(HKEY_LOCAL_MACHINE, kLM_Path, KEY_READ) == ERROR_SUCCESS)\n  {\n    bool enabled;\n    if (key.QueryValue(value, enabled) == ERROR_SUCCESS)\n      return enabled;\n  }\n  return defaultValue;\n}\n*/\n\nvoid CFmSettings::Save() const\n{\n  SaveOption(kShowDots, ShowDots);\n  SaveOption(kShowRealFileIcons, ShowRealFileIcons);\n  SaveOption(kFullRow, FullRow);\n  SaveOption(kShowGrid, ShowGrid);\n  SaveOption(kSingleClick, SingleClick);\n  SaveOption(kAlternativeSelection, AlternativeSelection);\n  // **************** 7-Zip ZS Modification Start ****************\n  SaveOption(kArcHistory, ArcHistory);\n  SaveOption(kPathHistory, PathHistory);\n  SaveOption(kCopyHistory, CopyHistory);\n  SaveOption(kFolderHistory, FolderHistory);\n  SaveOption(kLowercaseHashes, LowercaseHashes);\n  // **************** 7-Zip ZS Modification End ****************\n  // SaveOption(kUnderline, Underline);\n\n  SaveOption(kShowSystemMenu, ShowSystemMenu);\n}\n\nvoid CFmSettings::Load()\n{\n  ShowDots = false;\n  ShowRealFileIcons = false;\n  /* if (FullRow == false), we can use mouse click on another columns\n     to select group of files. We need to implement additional\n     way to select files in any column as in Explorer.\n     Then we can enable (FullRow == true) default mode. */\n  // FullRow = true;\n  FullRow = false;\n  ShowGrid = false;\n  SingleClick = false;\n  AlternativeSelection = false;\n  // **************** 7-Zip ZS Modification Start ****************\n  ArcHistory = true;\n  PathHistory = true;\n  CopyHistory = true;\n  FolderHistory = true;\n  LowercaseHashes = false;\n  // **************** 7-Zip ZS Modification End ****************\n  // Underline = false;\n\n  ShowSystemMenu = false;\n\n  CKey key;\n  if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS)\n  {\n    ReadOption(key, kShowDots, ShowDots);\n    ReadOption(key, kShowRealFileIcons, ShowRealFileIcons);\n    ReadOption(key, kFullRow, FullRow);\n    ReadOption(key, kShowGrid, ShowGrid);\n    ReadOption(key, kSingleClick, SingleClick);\n    ReadOption(key, kAlternativeSelection, AlternativeSelection);\n    // **************** 7-Zip ZS Modification Start ****************\n    ReadOption(key, kArcHistory, ArcHistory);\n    ReadOption(key, kPathHistory, PathHistory);\n    ReadOption(key, kCopyHistory, CopyHistory);\n    ReadOption(key, kFolderHistory, FolderHistory);\n    ReadOption(key, kLowercaseHashes, LowercaseHashes);\n    // **************** 7-Zip ZS Modification End ****************\n    // ReadOption(key, kUnderline, Underline);\n\n    ReadOption(key, kShowSystemMenu, ShowSystemMenu );\n  }\n}\n\n\n// void SaveLockMemoryAdd(bool enable) { SaveLmOption(kLockMemoryAdd, enable); }\n// bool ReadLockMemoryAdd() { return ReadLmOption(kLockMemoryAdd, true); }\n\nvoid SaveLockMemoryEnable(bool enable) { Save7ZipOption(kLargePages, enable); }\nbool ReadLockMemoryEnable() { return Read7ZipOption(kLargePages, false); }\n\n// **************** 7-Zip ZS Modification Start ****************\nbool WantArcHistory() { return ReadFMOption(kArcHistory, true); }\nbool WantPathHistory() { return ReadFMOption(kPathHistory, true); }\nbool WantCopyHistory() { return ReadFMOption(kCopyHistory, true); }\nbool WantFolderHistory() { return ReadFMOption(kFolderHistory, true); }\nbool WantLowercaseHashes() { return ReadFMOption(kLowercaseHashes); }\n// **************** 7-Zip ZS Modification End ****************\n\nstatic CSysString GetFlatViewName(UInt32 panelIndex)\n{\n  TCHAR panelString[16];\n  ConvertUInt32ToString(panelIndex, panelString);\n  return (CSysString)kFlatViewName + panelString;\n}\n\nvoid SaveFlatView(UInt32 panelIndex, bool enable) { SaveOption(GetFlatViewName(panelIndex), enable); }\n\nbool ReadFlatView(UInt32 panelIndex)\n{\n  bool enabled = false;\n  CKey key;\n  if (key.Open(HKEY_CURRENT_USER, kCU_FMPath, KEY_READ) == ERROR_SUCCESS)\n    ReadOption(key, GetFlatViewName(panelIndex), enabled);\n  return enabled;\n}\n\n/*\nvoid Save_ShowDeleted(bool enable) { SaveOption(kShowDeletedFiles, enable); }\nbool Read_ShowDeleted() { return ReadOption(kShowDeletedFiles, false); }\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/RegistryUtils.h",
    "content": "﻿// RegistryUtils.h\n\n#ifndef ZIP7_INC_REGISTRY_UTILS_H\n#define ZIP7_INC_REGISTRY_UTILS_H\n\n#include \"../../../Common/MyTypes.h\"\n#include \"../../../Common/MyString.h\"\n\nvoid SaveRegLang(const UString &path);\nvoid ReadRegLang(UString &path);\n\nvoid SaveRegEditor(bool useEditor, const UString &path);\nvoid ReadRegEditor(bool useEditor, UString &path);\n\nvoid SaveRegDiff(const UString &path);\nvoid ReadRegDiff(UString &path);\n\nvoid ReadReg_VerCtrlPath(UString &path);\n\nstruct CFmSettings\n{\n  bool ShowDots;\n  bool ShowRealFileIcons;\n  bool FullRow;\n  bool ShowGrid;\n  bool SingleClick;\n  bool AlternativeSelection;\n  // **************** 7-Zip ZS Modification Start ****************\n  bool ArcHistory;\n  bool PathHistory;\n  bool CopyHistory;\n  bool FolderHistory;\n  bool LowercaseHashes;\n  // **************** 7-Zip ZS Modification End ****************\n  // bool Underline;\n\n  bool ShowSystemMenu;\n\n  void Save() const;\n  void Load();\n};\n\n// void SaveLockMemoryAdd(bool enable);\n// bool ReadLockMemoryAdd();\n\nbool ReadLockMemoryEnable();\nvoid SaveLockMemoryEnable(bool enable);\n\n// **************** 7-Zip ZS Modification Start ****************\nbool WantArcHistory();\nbool WantPathHistory();\nbool WantCopyHistory();\nbool WantFolderHistory();\nbool WantLowercaseHashes();\n// **************** 7-Zip ZS Modification End ****************\n\nvoid SaveFlatView(UInt32 panelIndex, bool enable);\nbool ReadFlatView(UInt32 panelIndex);\n\n/*\nvoid Save_ShowDeleted(bool enable);\nbool Read_ShowDeleted();\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n\n#include \"../../../Common/Common.h\"\n\n#endif\n\n/*\nWINVER and _WIN32_WINNT\n\nMSVC6 / 2003sdk:\n{\n  <windows.h> doesn't set _WIN32_WINNT\n  if WINVER is not set <windows.h> sets WINVER to value:\n    0x0400 : MSVC6\n    0x0501 : Windows Server 2003 PSDK / 2003 R2 PSDK\n}\n\nSDK for Win7 (and later)\n{\n  <windows.h> sets _WIN32_WINNT if it's not set.\n  <windows.h> sets WINVER if it's not set.\n<windows.h> includes <sdkddkver.h> that does:\n#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)\n  #define _WIN32_WINNT 0x0601  // in win7 sdk\n  #define _WIN32_WINNT 0x0A00  // in win10 sdk\n#endif\n#ifndef WINVER\n #ifdef _WIN32_WINNT\n  #define WINVER _WIN32_WINNT\n else\n  #define WINVER 0x0601 // in win7 sdk\n  #define WINVER 0x0A00 // in win10 sdk\n endif\n#endif\n}\n\nSome GUI structures defined by windows will be larger,\nIf (_WIN32_WINNT) value is larger.\n\nAlso if we send sizeof(win_gui_struct) to some windows function,\nand we compile that code with big (_WIN32_WINNT) value,\nthe window function in old Windows can fail, if that old Windows\ndoesn't understand new big version of (win_gui_struct) compiled\nwith big (_WIN32_WINNT) value.\n\nSo it's better to define smallest (_WIN32_WINNT) value here.\nIn 7-Zip FM we use some functions that require (_WIN32_WINNT == 0x0500).\nSo it's simpler to define (_WIN32_WINNT == 0x0500) here.\nIf we define (_WIN32_WINNT == 0x0400) here, we need some manual\ndeclarations for functions and macros that require (0x0500) functions.\nAlso libs must contain these (0x0500+) functions.\n\nSome code in 7-zip FM uses also CommCtrl.h structures\nthat depend from (_WIN32_IE) value. But default\n(_WIN32_IE) value from <windows.h> probably is OK for us.\nSo we don't set _WIN32_IE here.\ndefault _WIN32_IE value set by <windows.h>:\n  0x501 2003sdk\n  0xa00 win10 sdk\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/SysIconUtils.cpp",
    "content": "﻿// SysIconUtils.cpp\n\n#include \"StdAfx.h\"\n\n#ifndef _UNICODE\n#include \"../../../Common/StringConvert.h\"\n#endif\n\n#include \"../../../Windows/FileDir.h\"\n\n#include \"SysIconUtils.h\"\n\n#if defined(__MINGW32__) || defined(__MINGW64__)\n#include <shlobj.h>\n#else\n#include <ShlObj.h>\n#endif\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nCExtToIconMap g_Ext_to_Icon_Map;\n\nint Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl)\n{\n  LPITEMIDLIST pidl = NULL;\n  SHGetSpecialFolderLocation(NULL, csidl, &pidl);\n  if (pidl)\n  {\n    SHFILEINFO shFileInfo;\n    shFileInfo.iIcon = -1;\n    const DWORD_PTR res = SHGetFileInfo((LPCTSTR)(const void *)(pidl),\n        FILE_ATTRIBUTE_DIRECTORY,\n        &shFileInfo, sizeof(shFileInfo),\n        SHGFI_PIDL | SHGFI_SYSICONINDEX);\n    /*\n    IMalloc *pMalloc;\n    SHGetMalloc(&pMalloc);\n    if (pMalloc)\n    {\n      pMalloc->Free(pidl);\n      pMalloc->Release();\n    }\n    */\n    // we use OLE2.dll function here\n    CoTaskMemFree(pidl);\n    if (res)\n      return shFileInfo.iIcon;\n  }\n  return -1;\n}\n\n#ifndef _UNICODE\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\ntypedef DWORD_PTR (WINAPI * Func_SHGetFileInfoW)(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags);\n\nstatic struct C_SHGetFileInfo_Init\n{\n  Func_SHGetFileInfoW f_SHGetFileInfoW;\n  C_SHGetFileInfo_Init()\n  {\n       f_SHGetFileInfoW = Z7_GET_PROC_ADDRESS(\n    Func_SHGetFileInfoW, ::GetModuleHandleW(L\"shell32.dll\"),\n        \"SHGetFileInfoW\");\n    // f_SHGetFileInfoW = NULL; // for debug\n  }\n} g_SHGetFileInfo_Init;\n#endif\n\n#ifdef _UNICODE\n#define My_SHGetFileInfoW SHGetFileInfoW\n#else\nstatic DWORD_PTR My_SHGetFileInfoW(LPCWSTR pszPath, DWORD attrib, SHFILEINFOW *psfi, UINT cbFileInfo, UINT uFlags)\n{\n  if (!g_SHGetFileInfo_Init.f_SHGetFileInfoW)\n    return 0;\n  return g_SHGetFileInfo_Init.f_SHGetFileInfoW(pszPath, attrib, psfi, cbFileInfo, uFlags);\n}\n#endif\n\nDWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(\n    CFSTR path, DWORD attrib, int &iconIndex)\n{\n#ifndef _UNICODE\n  if (!g_IsNT || !g_SHGetFileInfo_Init.f_SHGetFileInfoW)\n  {\n    SHFILEINFO shFileInfo;\n    // ZeroMemory(&shFileInfo, sizeof(shFileInfo));\n    shFileInfo.iIcon = -1;   // optional\n    const DWORD_PTR res = ::SHGetFileInfo(fs2fas(path),\n        attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,\n        &shFileInfo, sizeof(shFileInfo),\n        SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);\n    iconIndex = shFileInfo.iIcon;\n    return res;\n  }\n  else\n#endif\n  {\n    SHFILEINFOW shFileInfo;\n    // ZeroMemory(&shFileInfo, sizeof(shFileInfo));\n    shFileInfo.iIcon = -1;   // optional\n    const DWORD_PTR res = ::My_SHGetFileInfoW(fs2us(path),\n        attrib ? attrib : FILE_ATTRIBUTE_ARCHIVE,\n        &shFileInfo, sizeof(shFileInfo),\n        SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);\n    // (shFileInfo.iIcon == 0) returned for unknown extensions and files without extension\n    iconIndex = shFileInfo.iIcon;\n    // we use SHGFI_USEFILEATTRIBUTES, and\n    //   (res != 0) is expected for main cases, even if there are no such file.\n    //   (res == 0) for path with kSuperPrefix \"\\\\?\\\"\n    // Also SHGFI_USEFILEATTRIBUTES still returns icon inside exe.\n    // So we can use SHGFI_USEFILEATTRIBUTES for any case.\n    // UString temp = fs2us(path); // for debug\n    // UString tempName = temp.Ptr(temp.ReverseFind_PathSepar() + 1); // for debug\n    // iconIndex = -1; // for debug\n    return res;\n  }\n}\n\nint Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib)\n{\n  int iconIndex = -1;\n  if (!Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(\n      path, attrib, iconIndex))\n    iconIndex = -1;\n  return iconIndex;\n}\n\n\nHRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(\n    CFSTR path, DWORD attrib, Int32 *iconIndex)\n{\n  *iconIndex = -1;\n  int iconIndexTemp;\n  if (Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(\n      path, attrib, iconIndexTemp))\n  {\n    *iconIndex = iconIndexTemp;\n    return S_OK;\n  }\n  return GetLastError_noZero_HRESULT();\n}\n\n/*\nDWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path(const UString &fileName, DWORD attrib, int &iconIndex, UString *typeName)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    SHFILEINFO shFileInfo;\n    shFileInfo.szTypeName[0] = 0;\n    DWORD_PTR res = ::SHGetFileInfoA(GetSystemString(fileName), FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,\n        sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);\n    if (typeName)\n      *typeName = GetUnicodeString(shFileInfo.szTypeName);\n    iconIndex = shFileInfo.iIcon;\n    return res;\n  }\n  else\n  #endif\n  {\n    SHFILEINFOW shFileInfo;\n    shFileInfo.szTypeName[0] = 0;\n    DWORD_PTR res = ::My_SHGetFileInfoW(fileName, FILE_ATTRIBUTE_ARCHIVE | attrib, &shFileInfo,\n        sizeof(shFileInfo), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX | SHGFI_TYPENAME);\n    if (typeName)\n      *typeName = shFileInfo.szTypeName;\n    iconIndex = shFileInfo.iIcon;\n    return res;\n  }\n}\n*/\n\nstatic int FindInSorted_Attrib(const CRecordVector<CAttribIconPair> &vect, DWORD attrib, unsigned &insertPos)\n{\n  unsigned left = 0, right = vect.Size();\n  while (left != right)\n  {\n    const unsigned mid = (left + right) / 2;\n    const DWORD midAttrib = vect[mid].Attrib;\n    if (attrib == midAttrib)\n      return (int)mid;\n    if (attrib < midAttrib)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  insertPos = left;\n  return -1;\n}\n\nstatic int FindInSorted_Ext(const CObjectVector<CExtIconPair> &vect, const wchar_t *ext, unsigned &insertPos)\n{\n  unsigned left = 0, right = vect.Size();\n  while (left != right)\n  {\n    const unsigned mid = (left + right) / 2;\n    const int compare = MyStringCompareNoCase(ext, vect[mid].Ext);\n    if (compare == 0)\n      return (int)mid;\n    if (compare < 0)\n      right = mid;\n    else\n      left = mid + 1;\n  }\n  insertPos = left;\n  return -1;\n}\n\n\n// bool DoItemAlwaysStart(const UString &name);\n\nint CExtToIconMap::GetIconIndex(DWORD attrib, const wchar_t *fileName /*, UString *typeName */)\n{\n  int dotPos = -1;\n  unsigned i;\n  for (i = 0;; i++)\n  {\n    const wchar_t c = fileName[i];\n    if (c == 0)\n      break;\n    if (c == '.')\n      dotPos = (int)i;\n    // we don't need IS_PATH_SEPAR check, because (fileName) doesn't include path prefix.\n    // if (IS_PATH_SEPAR(c) || c == ':') dotPos = -1;\n  }\n\n  /*\n  if (MyStringCompareNoCase(fileName, L\"$Recycle.Bin\") == 0)\n  {\n    char s[256];\n    sprintf(s, \"SPEC i = %3d, attr = %7x\", _attribMap.Size(), attrib);\n    OutputDebugStringA(s);\n    OutputDebugStringW(fileName);\n  }\n  */\n\n  if ((attrib & FILE_ATTRIBUTE_DIRECTORY) || dotPos < 0)\n  for (unsigned k = 0;; k++)\n  {\n    if (k >= 2)\n      return -1;\n    unsigned insertPos = 0;\n    const int index = FindInSorted_Attrib(_attribMap, attrib, insertPos);\n    if (index >= 0)\n    {\n      // if (typeName) *typeName = _attribMap[index].TypeName;\n      return _attribMap[(unsigned)index].IconIndex;\n    }\n    CAttribIconPair pair;\n    pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(\n        #ifdef UNDER_CE\n        FTEXT(\"\\\\\")\n        #endif\n        FTEXT(\"__DIR__\")\n        , attrib\n        // , pair.TypeName\n        );\n    if (_attribMap.Size() < (1u << 16) // we limit cache size\n       || attrib < (1u << 15)) // we want to put all items with basic attribs to cache\n    {\n      /*\n      char s[256];\n      sprintf(s, \"i = %3d, attr = %7x\", _attribMap.Size(), attrib);\n      OutputDebugStringA(s);\n      */\n      pair.Attrib = attrib;\n      _attribMap.Insert(insertPos, pair);\n      // if (typeName) *typeName = pair.TypeName;\n      return pair.IconIndex;\n    }\n    if (pair.IconIndex >= 0)\n      return pair.IconIndex;\n    attrib = (attrib & FILE_ATTRIBUTE_DIRECTORY) ?\n        FILE_ATTRIBUTE_DIRECTORY :\n        FILE_ATTRIBUTE_ARCHIVE;\n  }\n\n  CObjectVector<CExtIconPair> &map =\n      (attrib & FILE_ATTRIBUTE_COMPRESSED) ?\n          _extMap_Compressed : _extMap_Normal;\n  const wchar_t *ext = fileName + dotPos + 1;\n  unsigned insertPos = 0;\n  const int index = FindInSorted_Ext(map, ext, insertPos);\n  if (index >= 0)\n  {\n    const CExtIconPair &pa = map[index];\n    // if (typeName) *typeName = pa.TypeName;\n    return pa.IconIndex;\n  }\n\n  for (i = 0;; i++)\n  {\n    const wchar_t c = ext[i];\n    if (c == 0)\n      break;\n    if (c < L'0' || c > L'9')\n      break;\n  }\n  if (i != 0 && ext[i] == 0)\n  {\n    // Shell_GetFileInfo_SysIconIndex_for_Path is too slow for big number of split extensions: .001, .002, .003\n    if (!SplitIconIndex_Defined)\n    {\n      Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(\n          #ifdef UNDER_CE\n          FTEXT(\"\\\\\")\n          #endif\n          FTEXT(\"__FILE__.001\"), FILE_ATTRIBUTE_ARCHIVE, SplitIconIndex);\n      SplitIconIndex_Defined = true;\n    }\n    return SplitIconIndex;\n  }\n\n  CExtIconPair pair;\n  pair.Ext = ext;\n  pair.IconIndex = Shell_GetFileInfo_SysIconIndex_for_Path(\n      us2fs(fileName + dotPos),\n      attrib & FILE_ATTRIBUTE_COMPRESSED ?\n          FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_COMPRESSED:\n          FILE_ATTRIBUTE_ARCHIVE);\n  if (map.Size() < (1u << 16)  // we limit cache size\n      // || DoItemAlwaysStart(fileName + dotPos) // we want some popular extensions in cache\n      )\n    map.Insert(insertPos, pair);\n  // if (typeName) *typeName = pair.TypeName;\n  return pair.IconIndex;\n}\n\n\nHIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons)\n{\n  SHFILEINFO shFileInfo;\n  // shFileInfo.hIcon = NULL; // optional\n  const DWORD_PTR res = SHGetFileInfo(TEXT(\"\"),\n      /* FILE_ATTRIBUTE_ARCHIVE | */\n      FILE_ATTRIBUTE_DIRECTORY,\n      &shFileInfo, sizeof(shFileInfo),\n      SHGFI_USEFILEATTRIBUTES |\n      SHGFI_SYSICONINDEX |\n      (smallIcons ? SHGFI_SMALLICON : SHGFI_LARGEICON));\n#if 0\n  // (shFileInfo.hIcon == NULL), because we don't use SHGFI_ICON.\n  // so DestroyIcon() is not required\n  if (res && shFileInfo.hIcon) // unexpected\n    DestroyIcon(shFileInfo.hIcon);\n#endif\n  return (HIMAGELIST)res;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/SysIconUtils.h",
    "content": "﻿// SysIconUtils.h\n\n#ifndef ZIP7_INC_SYS_ICON_UTILS_H\n#define ZIP7_INC_SYS_ICON_UTILS_H\n\n#include \"../../../Common/MyWindows.h\"\n\n#include <CommCtrl.h>\n\n#include \"../../../Common/MyString.h\"\n\nstruct CExtIconPair\n{\n  UString Ext;\n  int IconIndex;\n  // UString TypeName;\n  // int Compare(const CExtIconPair &a) const { return MyStringCompareNoCase(Ext, a.Ext); }\n};\n\nstruct CAttribIconPair\n{\n  DWORD Attrib;\n  int IconIndex;\n  // UString TypeName;\n  // int Compare(const CAttribIconPair &a) const { return Ext.Compare(a.Ext); }\n};\n\n\nstruct CExtToIconMap\n{\n  CRecordVector<CAttribIconPair> _attribMap;\n  CObjectVector<CExtIconPair> _extMap_Normal;\n  CObjectVector<CExtIconPair> _extMap_Compressed;\n  int SplitIconIndex;\n  int SplitIconIndex_Defined;\n  \n  CExtToIconMap(): SplitIconIndex_Defined(false) {}\n\n  void Clear()\n  {\n    SplitIconIndex_Defined = false;\n    _extMap_Normal.Clear();\n    _extMap_Compressed.Clear();\n    _attribMap.Clear();\n  }\n  int GetIconIndex_DIR(DWORD attrib = FILE_ATTRIBUTE_DIRECTORY)\n  {\n    return GetIconIndex(attrib, L\"__DIR__\");\n  }\n  int GetIconIndex(DWORD attrib, const wchar_t *fileName /* , UString *typeName */);\n};\n\nextern CExtToIconMap g_Ext_to_Icon_Map;\n\nDWORD_PTR Shell_GetFileInfo_SysIconIndex_for_Path_attrib_iconIndexRef(\n    CFSTR path, DWORD attrib, int &iconIndex);\nHRESULT Shell_GetFileInfo_SysIconIndex_for_Path_return_HRESULT(\n    CFSTR path, DWORD attrib, Int32 *iconIndex);\nint Shell_GetFileInfo_SysIconIndex_for_Path(CFSTR path, DWORD attrib);\n\nint Shell_GetFileInfo_SysIconIndex_for_CSIDL(int csidl);\n\nHIMAGELIST Shell_Get_SysImageList_smallIcons(bool smallIcons);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/resource.h",
    "content": "﻿#include \"resourceGui.h\"\n\n#define IDR_MENUBAR1      70\n#define IDM_MENU          71\n#define IDR_ACCELERATOR1  72\n\n#define IDB_ADD      100\n#define IDB_EXTRACT  101\n#define IDB_TEST     102\n#define IDB_COPY     103\n#define IDB_MOVE     104\n#define IDB_DELETE   105\n#define IDB_INFO     106\n\n#define IDB_ADD2     150\n#define IDB_EXTRACT2 151\n#define IDB_TEST2    152\n#define IDB_COPY2    153\n#define IDB_MOVE2    154\n#define IDB_DELETE2  155\n#define IDB_INFO2    156\n\n#define IDM_HASH_ALL             101\n#define IDM_CRC32                102\n#define IDM_CRC64                103\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n#define IDM_SHA1                 104\n#define IDM_SHA256               105\n#define IDM_SHA384               106\n#define IDM_SHA512               107\n#define IDM_SHA3_256             108\n#define IDM_XXH64                120\n#define IDM_BLAKE2SP             121\n#define IDM_MD5                  122\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n#define IDM_XXH32                104\n#define IDM_XXH64                105\n#define IDM_XXH3_64              106\n#define IDM_XXH3_128             107\n#define IDM_MD2                  108\n#define IDM_MD4                  109\n#define IDM_MD5                  110\n#define IDM_SHA1                 111\n#define IDM_SHA2_224             112\n#define IDM_SHA2_256             113\n#define IDM_SHA2_384             114\n#define IDM_SHA2_512             115\n#define IDM_BLAKE2sp             116\n#define IDM_BLAKE3               117\n#define IDM_SHA3_224             118\n#define IDM_SHA3_256             119\n#define IDM_SHA3_384             120\n#define IDM_SHA3_512             121\n// **************** 7-Zip ZS Modification End ****************\n\n#define IDM_FILE                 500\n#define IDM_EDIT                 501\n#define IDM_VIEW                 502\n#define IDM_FAVORITES            503\n#define IDM_TOOLS                504\n#define IDM_HELP                 505\n\n#define IDM_OPEN                 540\n#define IDM_OPEN_INSIDE          541\n#define IDM_OPEN_OUTSIDE         542\n#define IDM_FILE_VIEW            543\n#define IDM_FILE_EDIT            544\n#define IDM_RENAME               545\n#define IDM_COPY_TO              546\n#define IDM_MOVE_TO              547\n#define IDM_DELETE               548\n#define IDM_SPLIT                549\n#define IDM_COMBINE              550\n#define IDM_PROPERTIES           551\n#define IDM_COMMENT              552\n#define IDM_CRC                  553\n#define IDM_DIFF                 554\n#define IDM_CREATE_FOLDER        555\n#define IDM_CREATE_FILE          556\n// #define IDM_EXIT                 557\n#define IDM_LINK                 558\n#define IDM_ALT_STREAMS          559\n\n#define IDM_VER_EDIT             580\n#define IDM_VER_COMMIT           581\n#define IDM_VER_REVERT           582\n#define IDM_VER_DIFF             583\n\n#define IDM_OPEN_INSIDE_ONE      590\n#define IDM_OPEN_INSIDE_PARSER   591\n\n#define IDM_SELECT_ALL           600\n#define IDM_DESELECT_ALL         601\n#define IDM_INVERT_SELECTION     602\n#define IDM_SELECT               603\n#define IDM_DESELECT             604\n#define IDM_SELECT_BY_TYPE       605\n#define IDM_DESELECT_BY_TYPE     606\n\n#define IDM_VIEW_LARGE_ICONS     700\n#define IDM_VIEW_SMALL_ICONS     701\n#define IDM_VIEW_LIST            702\n#define IDM_VIEW_DETAILS         703\n\n#define IDM_VIEW_ARANGE_BY_NAME  710\n#define IDM_VIEW_ARANGE_BY_TYPE  711\n#define IDM_VIEW_ARANGE_BY_DATE  712\n#define IDM_VIEW_ARANGE_BY_SIZE  713\n\n#define IDM_VIEW_ARANGE_NO_SORT  730\n#define IDM_VIEW_FLAT_VIEW       731\n#define IDM_VIEW_TWO_PANELS      732\n#define IDM_VIEW_TOOLBARS        733\n#define IDM_OPEN_ROOT_FOLDER     734\n#define IDM_OPEN_PARENT_FOLDER   735\n#define IDM_FOLDERS_HISTORY      736\n#define IDM_VIEW_REFRESH         737\n#define IDM_VIEW_AUTO_REFRESH    738\n// #define IDM_VIEW_SHOW_DELETED    739\n// #define IDM_VIEW_SHOW_STREAMS    740\n\n// **************** NanaZip Modification Start ****************\n//#define IDM_VIEW_ARCHIVE_TOOLBAR            750\n//#define IDM_VIEW_STANDARD_TOOLBAR           751\n//#define IDM_VIEW_TOOLBARS_LARGE_BUTTONS     752\n//#define IDM_VIEW_TOOLBARS_SHOW_BUTTONS_TEXT 753\n// **************** NanaZip Modification End ****************\n\n#define IDM_VIEW_TIME_POPUP      760\n#define IDM_VIEW_TIME            761\n#define IDM_VIEW_TIME_UTC        799\n\n#define IDM_ADD_TO_FAVORITES     800\n#define IDS_BOOKMARK             801\n\n#define IDM_OPTIONS              900\n#define IDM_BENCHMARK            901\n#define IDM_BENCHMARK2           902\n#define IDM_TEMP_DIR             910\n\n// **************** NanaZip Modification Start ****************\n//#define IDM_HELP_CONTENTS        960\n// **************** NanaZip Modification End ****************\n#define IDM_ABOUT                961\n\n#define IDS_OPTIONS                     2100\n\n#define IDS_N_SELECTED_ITEMS            3002\n\n#define IDS_FILE_EXIST                  3008\n#define IDS_WANT_UPDATE_MODIFIED_FILE   3009\n#define IDS_CANNOT_UPDATE_FILE          3010\n#define IDS_CANNOT_START_EDITOR         3011\n#define IDS_VIRUS                       3012\n#define IDS_MESSAGE_UNSUPPORTED_OPERATION_FOR_LONG_PATH_FOLDER  3013\n#define IDS_SELECT_ONE_FILE             3014\n#define IDS_SELECT_FILES                3015\n#define IDS_TOO_MANY_ITEMS              3016\n\n#define IDS_COPY                        6000\n#define IDS_MOVE                        6001\n#define IDS_COPY_TO                     6002\n#define IDS_MOVE_TO                     6003\n#define IDS_COPYING                     6004\n// #define IDS_MOVING                      6005\n#define IDS_RENAMING                    6006\n\n#define IDS_OPERATION_IS_NOT_SUPPORTED  6008\n#define IDS_ERROR_RENAMING              6009\n#define IDS_CONFIRM_FILE_COPY           6010\n#define IDS_WANT_TO_COPY_FILES          6011\n\n#define IDS_CONFIRM_FILE_DELETE         6100\n#define IDS_CONFIRM_FOLDER_DELETE       6101\n#define IDS_CONFIRM_ITEMS_DELETE        6102\n#define IDS_WANT_TO_DELETE_FILE         6103\n#define IDS_WANT_TO_DELETE_FOLDER       6104\n#define IDS_WANT_TO_DELETE_ITEMS        6105\n#define IDS_DELETING                    6106\n#define IDS_ERROR_DELETING              6107\n#define IDS_ERROR_LONG_PATH_TO_RECYCLE  6108\n\n#define IDS_CREATE_FOLDER               6300\n#define IDS_CREATE_FILE                 6301\n#define IDS_CREATE_FOLDER_NAME          6302\n#define IDS_CREATE_FILE_NAME            6303\n#define IDS_CREATE_FOLDER_DEFAULT_NAME  6304\n#define IDS_CREATE_FILE_DEFAULT_NAME    6305\n#define IDS_CREATE_FOLDER_ERROR         6306\n#define IDS_CREATE_FILE_ERROR           6307\n\n#define IDS_COMMENT                     6400\n#define IDS_COMMENT2                    6401\n#define IDS_SELECT                      6402\n#define IDS_DESELECT                    6403\n#define IDS_SELECT_MASK                 6404\n\n#define IDS_PROPERTIES                  6600\n#define IDS_FOLDERS_HISTORY             6601\n\n#define IDS_COMPUTER                    7100\n#define IDS_NETWORK                     7101\n#define IDS_DOCUMENTS                   7102\n#define IDS_SYSTEM                      7103\n\n#define IDS_ADD                         7200\n#define IDS_EXTRACT                     7201\n#define IDS_TEST                        7202\n#define IDS_BUTTON_COPY                 7203\n#define IDS_BUTTON_MOVE                 7204\n#define IDS_BUTTON_DELETE               7205\n#define IDS_BUTTON_INFO                 7206\n\n#define IDS_SPLITTING                   7303\n#define IDS_SPLIT_CONFIRM_TITLE         7304\n#define IDS_SPLIT_CONFIRM_MESSAGE       7305\n#define IDS_SPLIT_VOL_MUST_BE_SMALLER   7306\n\n#define IDS_COMBINE                     7400\n#define IDS_COMBINE_TO                  7401\n#define IDS_COMBINING                   7402\n#define IDS_COMBINE_SELECT_ONE_FILE     7403\n#define IDS_COMBINE_CANT_DETECT_SPLIT_FILE 7404\n#define IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART 7405\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/FileManager/resourceGui.h",
    "content": "﻿#define IDI_ICON  1\n\n#define IDS_MESSAGE_NO_ERRORS           3001\n\n#define IDS_PROGRESS_TESTING            3302\n#define IDS_OPENNING                    3303\n#define IDS_SCANNING                    3304\n\n#define IDS_MOVING                      6005\n\n#define IDS_CHECKSUM_CALCULATING        7500\n#define IDS_CHECKSUM_INFORMATION        7501\n#define IDS_CHECKSUM_CRC_DATA           7502\n#define IDS_CHECKSUM_CRC_DATA_NAMES     7503\n#define IDS_CHECKSUM_CRC_STREAMS_NAMES  7504\n\n#define IDS_INCORRECT_VOLUME_SIZE       7307\n\n#define IDS_MEM_REQUIRES_BIG_MEM        7811\n#define IDS_MEM_REQUIRED_MEM_SIZE       7812\n#define IDS_MEM_CURRENT_MEM_LIMIT       7813\n#define IDS_MEM_USAGE_LIMIT_SET_BY_7ZIP 7814\n#define IDS_MEM_RAM_SIZE                7815\n\n#define IDS_MSG_ARC_UNPACKING_WAS_SKIPPED 7822\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/ExtractDialog.cpp",
    "content": "﻿// ExtractDialog.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/StringConvert.h\"\n#include \"../../../Common/Wildcard.h\"\n\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/ResourceString.h\"\n\n// **************** NanaZip Modification Start ****************\n//#ifndef Z7_NO_REGISTRY\n//#include \"../FileManager/HelpUtils.h\"\n//#endif\n// **************** NanaZip Modification End ****************\n\n\n#include \"../FileManager/BrowseDialog.h\"\n#include \"../FileManager/LangUtils.h\"\n#include \"../FileManager/resourceGui.h\"\n\n#include \"ExtractDialog.h\"\n#include \"ExtractDialogRes.h\"\n#include \"ExtractRes.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NName;\n\nextern HINSTANCE g_hInstance;\n\n#ifndef Z7_SFX\n\nstatic const UInt32 kPathMode_IDs[] =\n{\n  IDS_EXTRACT_PATHS_FULL,\n  IDS_EXTRACT_PATHS_NO,\n  IDS_EXTRACT_PATHS_ABS\n};\n\nstatic const UInt32 kOverwriteMode_IDs[] =\n{\n  IDS_EXTRACT_OVERWRITE_ASK,\n  IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT,\n  IDS_EXTRACT_OVERWRITE_SKIP_EXISTING,\n  IDS_EXTRACT_OVERWRITE_RENAME,\n  IDS_EXTRACT_OVERWRITE_RENAME_EXISTING\n};\n\nstatic const\n  // NExtract::NPathMode::EEnum\n  int\n  kPathModeButtonsVals[] =\n{\n  NExtract::NPathMode::kFullPaths,\n  NExtract::NPathMode::kNoPaths,\n  NExtract::NPathMode::kAbsPaths\n};\n\nstatic const\n  int\n  // NExtract::NOverwriteMode::EEnum\n  kOverwriteButtonsVals[] =\n{\n  NExtract::NOverwriteMode::kAsk,\n  NExtract::NOverwriteMode::kOverwrite,\n  NExtract::NOverwriteMode::kSkip,\n  NExtract::NOverwriteMode::kRename,\n  NExtract::NOverwriteMode::kRenameExisting\n};\n\n#endif\n\n#ifdef Z7_LANG\n\nstatic const UInt32 kLangIDs[] =\n{\n  IDT_EXTRACT_EXTRACT_TO,\n  IDT_EXTRACT_PATH_MODE,\n  IDT_EXTRACT_OVERWRITE_MODE,\n  // **************** 7-Zip ZS Modification Start ****************\n  IDX_EXTRACT_OPEN_TRG_FLD,\n  // **************** 7-Zip ZS Modification End ****************\n  // IDX_EXTRACT_ALT_STREAMS,\n  IDX_EXTRACT_NT_SECUR,\n  IDX_EXTRACT_ELIM_DUP,\n  // **************** NanaZip Modification Start ****************\n  IDX_EXTRACT_OPEN_FOLDER,\n  // **************** NanaZip Modification End ****************\n  IDG_PASSWORD,\n  IDX_PASSWORD_SHOW\n};\n#endif\n\n// static const int kWildcardsButtonIndex = 2;\n\n#ifndef Z7_NO_REGISTRY\nstatic const unsigned kHistorySize = 16;\n#endif\n\n#ifndef Z7_SFX\n\n// it's used in CompressDialog also\nvoid AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal);\nvoid AddComboItems(NControl::CComboBox &combo, const UInt32 *langIDs, unsigned numItems, const int *values, int curVal)\n{\n  unsigned curSel = 0;\n  for (unsigned i = 0; i < numItems; i++)\n  {\n    UString s = LangString(langIDs[i]);\n    s.RemoveChar(L'&');\n    combo.AddString_SetItemData(s, (LPARAM)i);\n    if (values[i] == curVal)\n      curSel = i;\n  }\n  combo.SetCurSel(curSel);\n}\n\n// it's used in CompressDialog also\nbool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2);\nbool GetBoolsVal(const CBoolPair &b1, const CBoolPair &b2)\n{\n  if (b1.Def) return b1.Val;\n  if (b2.Def) return b2.Val;\n  return b1.Val;\n}\n\nvoid CExtractDialog::CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2)\n{\n  CheckButton(id, GetBoolsVal(b1, b2));\n}\n\nvoid CExtractDialog::GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2)\n{\n  const bool val = IsButtonCheckedBool(id);\n  const bool oldVal = GetBoolsVal(b1, b2);\n  if (val != oldVal)\n    b1.Def = b2.Def = true;\n  b1.Val = b2.Val = val;\n}\n\n#endif\n\nbool CExtractDialog::OnInit()\n{\n  #ifdef Z7_LANG\n  {\n    UString s;\n    LangString_OnlyFromLangFile(IDD_EXTRACT, s);\n    if (s.IsEmpty())\n      GetText(s);\n    if (!ArcPath.IsEmpty())\n    {\n      s += \" : \";\n      s += ArcPath;\n    }\n    SetText(s);\n    // LangSetWindowText(*this, IDD_EXTRACT);\n    LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));\n  }\n  #endif\n\n  #ifndef Z7_SFX\n  _passwordControl.Attach(GetItem(IDE_EXTRACT_PASSWORD));\n  _passwordControl.SetText(Password);\n  _passwordControl.SetPasswordChar(TEXT('*'));\n  _pathName.Attach(GetItem(IDE_EXTRACT_NAME));\n  #endif\n\n  #ifdef Z7_NO_REGISTRY\n\n  PathMode = NExtract::NPathMode::kFullPaths;\n  OverwriteMode = NExtract::NOverwriteMode::kAsk;\n\n  #else\n\n  _info.Load();\n\n  if (_info.PathMode == NExtract::NPathMode::kCurPaths)\n    _info.PathMode = NExtract::NPathMode::kFullPaths;\n\n  if (!PathMode_Force && _info.PathMode_Force)\n    PathMode = _info.PathMode;\n  if (!OverwriteMode_Force && _info.OverwriteMode_Force)\n    OverwriteMode = _info.OverwriteMode;\n\n  // CheckButton_TwoBools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams);\n  // **************** 7-Zip ZS Modification Start ****************\n  CheckButton_TwoBools(IDX_EXTRACT_OPEN_TRG_FLD, OpnTrgFold, _info.OpnTrgFold);\n  // **************** 7-Zip ZS Modification End ****************\n  CheckButton_TwoBools(IDX_EXTRACT_NT_SECUR,    NtSecurity, _info.NtSecurity);\n  CheckButton_TwoBools(IDX_EXTRACT_ELIM_DUP,    ElimDup,    _info.ElimDup);\n  // **************** NanaZip Modification Start ****************\n  CheckButton_TwoBools(IDX_EXTRACT_OPEN_FOLDER, OpenFolder, _info.OpenFolder);\n  // **************** NanaZip Modification End ****************\n\n  CheckButton(IDX_PASSWORD_SHOW, _info.ShowPassword.Val);\n  UpdatePasswordControl();\n\n  #endif\n\n  _path.Attach(GetItem(IDC_EXTRACT_PATH));\n\n  UString pathPrefix = DirPath;\n\n  #ifndef Z7_SFX\n\n  // **************** NanaZip Modification Start ****************\n  #if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n  if (_info.SplitDest.Val)\n  {\n    CheckButton(IDX_EXTRACT_NAME_ENABLE, true);\n    UString pathName;\n    SplitPathToParts_Smart(DirPath, pathPrefix, pathName);\n    if (pathPrefix.IsEmpty())\n      pathPrefix = pathName;\n    else\n      _pathName.SetText(pathName);\n  }\n  else\n    ShowItem_Bool(IDE_EXTRACT_NAME, false);\n  #endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n  UString pathName;\n  SplitPathToParts_Smart(DirPath, pathPrefix, pathName);\n  if (pathPrefix.IsEmpty())\n    pathPrefix = pathName;\n  else\n    _pathName.SetText(pathName);\n\n  if (_info.SplitDest.Val)\n    CheckButton(IDX_EXTRACT_NAME_ENABLE, true);\n  else\n    ShowItem_Bool(IDE_EXTRACT_NAME, false);\n  // **************** NanaZip Modification End ****************\n\n  #endif\n\n  _path.SetText(pathPrefix);\n\n  #ifndef Z7_NO_REGISTRY\n  for (unsigned i = 0; i < _info.Paths.Size() && i < kHistorySize; i++)\n    _path.AddString(_info.Paths[i]);\n  #endif\n\n  /*\n  if (_info.Paths.Size() > 0)\n    _path.SetCurSel(0);\n  else\n    _path.SetCurSel(-1);\n  */\n\n  #ifndef Z7_SFX\n\n  _pathMode.Attach(GetItem(IDC_EXTRACT_PATH_MODE));\n  _overwriteMode.Attach(GetItem(IDC_EXTRACT_OVERWRITE_MODE));\n\n  AddComboItems(_pathMode, kPathMode_IDs, Z7_ARRAY_SIZE(kPathMode_IDs), kPathModeButtonsVals, PathMode);\n  AddComboItems(_overwriteMode, kOverwriteMode_IDs, Z7_ARRAY_SIZE(kOverwriteMode_IDs), kOverwriteButtonsVals, OverwriteMode);\n\n  #endif\n\n  HICON icon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));\n  SetIcon(ICON_BIG, icon);\n\n  // CWindow filesWindow = GetItem(IDC_EXTRACT_RADIO_FILES);\n  // filesWindow.Enable(_enableFilesButton);\n\n  NormalizePosition();\n\n  return CModalDialog::OnInit();\n}\n\n#ifndef Z7_SFX\nvoid CExtractDialog::UpdatePasswordControl()\n{\n  _passwordControl.SetPasswordChar(IsShowPasswordChecked() ? 0 : TEXT('*'));\n  UString password;\n  _passwordControl.GetText(password);\n  _passwordControl.SetText(password);\n}\n#endif\n\nbool CExtractDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)\n{\n  switch (buttonID)\n  {\n    case IDB_EXTRACT_SET_PATH:\n      OnButtonSetPath();\n      return true;\n    #ifndef Z7_SFX\n    case IDX_EXTRACT_NAME_ENABLE:\n      ShowItem_Bool(IDE_EXTRACT_NAME, IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE));\n      return true;\n    case IDX_PASSWORD_SHOW:\n    {\n      UpdatePasswordControl();\n      return true;\n    }\n    #endif\n  }\n  return CModalDialog::OnButtonClicked(buttonID, buttonHWND);\n}\n\nvoid CExtractDialog::OnButtonSetPath()\n{\n  UString currentPath;\n  _path.GetText(currentPath);\n  UString title = LangString(IDS_EXTRACT_SET_FOLDER);\n  UString resultPath;\n  if (!MyBrowseForFolder(*this, title, currentPath, resultPath))\n    return;\n  #ifndef Z7_NO_REGISTRY\n  _path.SetCurSel(-1);\n  #endif\n  _path.SetText(resultPath);\n}\n\nvoid AddUniqueString(UStringVector &list, const UString &s);\nvoid AddUniqueString(UStringVector &list, const UString &s)\n{\n  FOR_VECTOR (i, list)\n    if (s.IsEqualTo_NoCase(list[i]))\n      return;\n  list.Add(s);\n}\n\nvoid CExtractDialog::OnOK()\n{\n  #ifndef Z7_SFX\n  int pathMode2 = kPathModeButtonsVals[_pathMode.GetCurSel()];\n  if (PathMode != NExtract::NPathMode::kCurPaths ||\n      pathMode2 != NExtract::NPathMode::kFullPaths)\n    PathMode = (NExtract::NPathMode::EEnum)pathMode2;\n\n  OverwriteMode = (NExtract::NOverwriteMode::EEnum)kOverwriteButtonsVals[_overwriteMode.GetCurSel()];\n\n  // _filesMode = (NExtractionDialog::NFilesMode::EEnum)GetFilesMode();\n\n  _passwordControl.GetText(Password);\n\n  #endif\n\n  #ifndef Z7_NO_REGISTRY\n\n  // GetButton_Bools(IDX_EXTRACT_ALT_STREAMS, AltStreams, _info.AltStreams);\n  // **************** 7-Zip ZS Modification Start ****************\n  GetButton_Bools(IDX_EXTRACT_OPEN_TRG_FLD, OpnTrgFold,  _info.OpnTrgFold);\n  // **************** 7-Zip ZS Modification End ****************\n  GetButton_Bools(IDX_EXTRACT_NT_SECUR,    NtSecurity, _info.NtSecurity);\n  GetButton_Bools(IDX_EXTRACT_ELIM_DUP,    ElimDup,    _info.ElimDup);\n  // **************** NanaZip Modification Start ****************\n  GetButton_Bools(IDX_EXTRACT_OPEN_FOLDER, OpenFolder, _info.OpenFolder);\n  // **************** NanaZip Modification End ****************\n\n  bool showPassword = IsShowPasswordChecked();\n  if (showPassword != _info.ShowPassword.Val)\n  {\n    _info.ShowPassword.Def = true;\n    _info.ShowPassword.Val = showPassword;\n  }\n\n  if (_info.PathMode != pathMode2)\n  {\n    _info.PathMode_Force = true;\n    _info.PathMode = (NExtract::NPathMode::EEnum)pathMode2;\n    /*\n    // we allow kAbsPaths in registry.\n    if (_info.PathMode == NExtract::NPathMode::kAbsPaths)\n      _info.PathMode = NExtract::NPathMode::kFullPaths;\n    */\n  }\n\n  if (!OverwriteMode_Force && _info.OverwriteMode != OverwriteMode)\n    _info.OverwriteMode_Force = true;\n  _info.OverwriteMode = OverwriteMode;\n\n\n  #else\n\n  ElimDup.Val = IsButtonCheckedBool(IDX_EXTRACT_ELIM_DUP);\n\n  #endif\n\n  UString s;\n\n  #ifdef Z7_NO_REGISTRY\n\n  _path.GetText(s);\n\n  #else\n\n  int currentItem = _path.GetCurSel();\n  if (currentItem == CB_ERR)\n  {\n    _path.GetText(s);\n    if (_path.GetCount() >= (int)kHistorySize)\n      currentItem = _path.GetCount() - 1;\n  }\n  else\n    _path.GetLBText(currentItem, s);\n\n  #endif\n\n  s.Trim();\n  NName::NormalizeDirPathPrefix(s);\n\n  // **************** 7-Zip ZS Modification Start ****************\n  DirPath = s; // s remains path without subpath (to store it to history below)\n  // **************** 7-Zip ZS Modification End ****************\n  #ifndef Z7_SFX\n\n  const bool splitDest = IsButtonCheckedBool(IDX_EXTRACT_NAME_ENABLE);\n  if (splitDest)\n  {\n    UString pathName;\n    _pathName.GetText(pathName);\n    pathName.Trim();\n    // **************** 7-Zip ZS Modification Start ****************\n    //s += pathName;\n    //NName::NormalizeDirPathPrefix(s);\n    DirPath += pathName;\n    NName::NormalizeDirPathPrefix(DirPath);\n    // **************** 7-Zip ZS Modification End ****************\n  }\n  if (splitDest != _info.SplitDest.Val)\n  {\n    _info.SplitDest.Def = true;\n    _info.SplitDest.Val = splitDest;\n  }\n\n  #endif\n\n  // **************** 7-Zip ZS Modification Start ****************\n  // DirPath = s;\n  // **************** 7-Zip ZS Modification End ****************\n\n  #ifndef Z7_NO_REGISTRY\n  _info.Paths.Clear();\n  #ifndef Z7_SFX\n  AddUniqueString(_info.Paths, s);\n  #endif\n  for (int i = 0; i < _path.GetCount(); i++)\n    if (i != currentItem)\n    {\n      UString sTemp;\n      _path.GetLBText(i, sTemp);\n      sTemp.Trim();\n      AddUniqueString(_info.Paths, sTemp);\n    }\n  _info.Save();\n  #endif\n\n  CModalDialog::OnOK();\n}\n\n// **************** NanaZip Modification Start ****************\n//#ifndef Z7_NO_REGISTRY\n//#define kHelpTopic \"fm/plugins/7-zip/extract.htm\"\n//void CExtractDialog::OnHelp()\n//{\n//  ShowHelpWindow(kHelpTopic);\n//  CModalDialog::OnHelp();\n//}\n//#endif\n// **************** NanaZip Modification End ****************\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/ExtractDialog.h",
    "content": "﻿// ExtractDialog.h\n\n#ifndef ZIP7_INC_EXTRACT_DIALOG_H\n#define ZIP7_INC_EXTRACT_DIALOG_H\n\n#include \"ExtractDialogRes.h\"\n\n#include \"../../../Windows/Control/ComboBox.h\"\n#include \"../../../Windows/Control/Edit.h\"\n\n#include \"../Common/ExtractMode.h\"\n\n#include \"../FileManager/DialogSize.h\"\n\n#ifndef Z7_NO_REGISTRY\n#include \"../Common/ZipRegistry.h\"\n#endif\n\nnamespace NExtractionDialog\n{\n  /*\n  namespace NFilesMode\n  {\n    enum EEnum\n    {\n      kSelected,\n      kAll,\n      kSpecified\n    };\n  }\n  */\n}\n\nclass CExtractDialog: public NWindows::NControl::CModalDialog\n{\n  #ifdef Z7_NO_REGISTRY\n  NWindows::NControl::CDialogChildControl _path;\n  #else\n  NWindows::NControl::CComboBox _path;\n  #endif\n\n  #ifndef Z7_SFX\n  NWindows::NControl::CEdit _pathName;\n  NWindows::NControl::CEdit _passwordControl;\n  NWindows::NControl::CComboBox _pathMode;\n  NWindows::NControl::CComboBox _overwriteMode;\n  #endif\n\n  #ifndef Z7_SFX\n  // int GetFilesMode() const;\n  void UpdatePasswordControl();\n  #endif\n\n  void OnButtonSetPath();\n\n  void CheckButton_TwoBools(UINT id, const CBoolPair &b1, const CBoolPair &b2);\n  void GetButton_Bools(UINT id, CBoolPair &b1, CBoolPair &b2);\n  virtual bool OnInit() Z7_override;\n  virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND) Z7_override;\n  virtual void OnOK() Z7_override;\n\n  #ifndef Z7_NO_REGISTRY\n\n  // **************** NanaZip Modification Start ****************\n  //virtual void OnHelp() Z7_override;\n  // **************** NanaZip Modification End ****************\n\n  NExtract::CInfo _info;\n\n  #endif\n\n  bool IsShowPasswordChecked() const { return IsButtonCheckedBool(IDX_PASSWORD_SHOW); }\npublic:\n  // bool _enableSelectedFilesButton;\n  // bool _enableFilesButton;\n  // NExtractionDialog::NFilesMode::EEnum FilesMode;\n\n  UString DirPath;\n  UString ArcPath;\n\n  #ifndef Z7_SFX\n  UString Password;\n  #endif\n  bool PathMode_Force;\n  bool OverwriteMode_Force;\n  NExtract::NPathMode::EEnum PathMode;\n  NExtract::NOverwriteMode::EEnum OverwriteMode;\n\n  #ifndef Z7_SFX\n  // CBoolPair AltStreams;\n  CBoolPair NtSecurity;\n  // **************** 7-Zip ZS Modification Start ****************\n  CBoolPair OpnTrgFold;\n  // **************** 7-Zip ZS Modification End ****************\n  #endif\n\n  CBoolPair ElimDup;\n  // **************** NanaZip Modification Start ****************\n  CBoolPair OpenFolder;\n  // **************** NanaZip Modification End ****************\n\n  INT_PTR Create(HWND aWndParent = NULL)\n  {\n    #ifdef Z7_SFX\n    BIG_DIALOG_SIZE(240, 64);\n    #else\n    BIG_DIALOG_SIZE(300, 160);\n    #endif\n    return CModalDialog::Create(SIZED_DIALOG(IDD_EXTRACT), aWndParent);\n  }\n\n  CExtractDialog():\n    PathMode_Force(false),\n    OverwriteMode_Force(false)\n  {\n    ElimDup.Val = true;\n  }\n\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/ExtractDialogRes.h",
    "content": "﻿#define IDD_EXTRACT     3400\n#define IDD_EXTRACT_2  13400\n\n#define IDC_EXTRACT_PATH             100\n#define IDB_EXTRACT_SET_PATH         101\n#define IDC_EXTRACT_PATH_MODE        102\n#define IDC_EXTRACT_OVERWRITE_MODE   103\n\n// **************** 7-Zip ZS Modification Start ****************\n#define IDX_EXTRACT_OPEN_TRG_FLD     104\n// **************** 7-Zip ZS Modification End ****************\n\n#define IDE_EXTRACT_PASSWORD         120\n\n#define IDE_EXTRACT_NAME             130\n#define IDX_EXTRACT_NAME_ENABLE      131\n\n\n#define IDT_EXTRACT_EXTRACT_TO      3401\n#define IDT_EXTRACT_PATH_MODE       3410\n#define IDT_EXTRACT_OVERWRITE_MODE  3420\n\n#define IDX_EXTRACT_ELIM_DUP        3430\n#define IDX_EXTRACT_NT_SECUR        3431\n// #define IDX_EXTRACT_ALT_STREAMS     3432\n// **************** NanaZip Modification Start ****************\n#define IDX_EXTRACT_OPEN_FOLDER     3433\n#define IDX_EXTRACT_ON_OPEN         3434\n// **************** NanaZip Modification End ****************\n\n#define IDX_PASSWORD_SHOW           3803\n#define IDG_PASSWORD                3807\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/ExtractGUI.cpp",
    "content": "﻿// ExtractGUI.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../../Common/IntToString.h\"\n#include \"../../../Common/StringConvert.h\"\n\n#include \"../../../Windows/FileDir.h\"\n#include \"../../../Windows/FileFind.h\"\n#include \"../../../Windows/FileName.h\"\n#include \"../../../Windows/Thread.h\"\n\n#include \"../FileManager/ExtractCallback.h\"\n#include \"../FileManager/FormatUtils.h\"\n#include \"../FileManager/LangUtils.h\"\n#include \"../FileManager/resourceGui.h\"\n#include \"../FileManager/OverwriteDialogRes.h\"\n\n#include \"../Common/ArchiveExtractCallback.h\"\n#include \"../Common/PropIDUtils.h\"\n\n#include \"../Explorer/MyMessages.h\"\n\n#include \"resource2.h\"\n#include \"ExtractRes.h\"\n\n#include \"ExtractDialog.h\"\n#include \"ExtractGUI.h\"\n#include \"HashGUI.h\"\n\n#include \"../FileManager/PropertyNameRes.h\"\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NDir;\n\nstatic const wchar_t * const kIncorrectOutDir = L\"Incorrect output directory path\";\n\n#ifndef Z7_SFX\n\nstatic void AddValuePair(UString &s, UINT resourceID, UInt64 value, bool addColon = true)\n{\n  AddLangString(s, resourceID);\n  if (addColon)\n    s.Add_Colon();\n  s.Add_Space();\n  s.Add_UInt64(value);\n  s.Add_LF();\n}\n\nstatic void AddSizePair(UString &s, UINT resourceID, UInt64 value)\n{\n  AddLangString(s, resourceID);\n  s += \": \";\n  AddSizeValue(s, value);\n  s.Add_LF();\n}\n\n#endif\n\nclass CThreadExtracting: public CProgressThreadVirt\n{\n  HRESULT ProcessVirt() Z7_override;\npublic:\n  /*\n  #ifdef Z7_EXTERNAL_CODECS\n  const CExternalCodecs *externalCodecs;\n  #endif\n  */\n\n  CCodecs *codecs;\n  CExtractCallbackImp *ExtractCallbackSpec;\n  const CObjectVector<COpenType> *FormatIndices;\n  const CIntVector *ExcludedFormatIndices;\n\n  UStringVector *ArchivePaths;\n  UStringVector *ArchivePathsFull;\n  const NWildcard::CCensorNode *WildcardCensor;\n  const CExtractOptions *Options;\n\n  #ifndef Z7_SFX\n  CHashBundle *HashBundle;\n  virtual void ProcessWasFinished_GuiVirt() Z7_override;\n  #endif\n\n  CMyComPtr<IFolderArchiveExtractCallback> FolderArchiveExtractCallback;\n  UString Title;\n\n  CPropNameValPairs Pairs;\n\n  // **************** 7-Zip ZS Modification Start ****************\n#ifndef Z7_SFX\n  FString FirstExtractedPath;\n#endif\n  // **************** 7-Zip ZS Modification End ****************\n};\n\n\n#ifndef Z7_SFX\nvoid CThreadExtracting::ProcessWasFinished_GuiVirt()\n{\n  if (HashBundle && !Pairs.IsEmpty())\n    ShowHashResults(Pairs, *this);\n}\n#endif\n\nHRESULT CThreadExtracting::ProcessVirt()\n{\n  // **************** NanaZip Modification Start ****************\n  //CDecompressStat Stat;\n  CDecompressStat &Stat = ExtractCallbackSpec->Stat;\n  // **************** NanaZip Modification End ****************\n  \n  #ifndef Z7_SFX\n  /*\n  if (HashBundle)\n    HashBundle->Init();\n  */\n  #endif\n\n  HRESULT res = Extract(\n      /*\n      #ifdef Z7_EXTERNAL_CODECS\n      externalCodecs,\n      #endif\n      */\n      codecs,\n      *FormatIndices, *ExcludedFormatIndices,\n      *ArchivePaths, *ArchivePathsFull,\n      *WildcardCensor, *Options,\n      ExtractCallbackSpec, ExtractCallbackSpec, FolderArchiveExtractCallback,\n      #ifndef Z7_SFX\n        HashBundle,\n      #endif\n      FinalMessage.ErrorMessage.Message, Stat);\n  \n  #ifndef Z7_SFX\n  if (res == S_OK && ExtractCallbackSpec->IsOK())\n  {\n    // **************** 7-Zip ZS Modification Start ****************\n    FirstExtractedPath = Stat.FirstExtractedPath;\n    // **************** 7-Zip ZS Modification End ****************\n    if (HashBundle)\n    {\n      AddValuePair(Pairs, IDS_ARCHIVES_COLON, Stat.NumArchives);\n      AddSizeValuePair(Pairs, IDS_PROP_PACKED_SIZE, Stat.PackSize);\n      AddHashBundleRes(Pairs, *HashBundle);\n    }\n    else if (Options->TestMode)\n    {\n      UString s;\n    \n      AddValuePair(s, IDS_ARCHIVES_COLON, Stat.NumArchives, false);\n      AddSizePair(s, IDS_PROP_PACKED_SIZE, Stat.PackSize);\n\n      if (Stat.NumFolders != 0)\n        AddValuePair(s, IDS_PROP_FOLDERS, Stat.NumFolders);\n      AddValuePair(s, IDS_PROP_FILES, Stat.NumFiles);\n      AddSizePair(s, IDS_PROP_SIZE, Stat.UnpackSize);\n      if (Stat.NumAltStreams != 0)\n      {\n        s.Add_LF();\n        AddValuePair(s, IDS_PROP_NUM_ALT_STREAMS, Stat.NumAltStreams);\n        AddSizePair(s, IDS_PROP_ALT_STREAMS_SIZE, Stat.AltStreams_UnpackSize);\n      }\n      s.Add_LF();\n      AddLangString(s, IDS_MESSAGE_NO_ERRORS);\n      FinalMessage.OkMessage.Title = Title;\n      FinalMessage.OkMessage.Message = s;\n    }\n  }\n  #endif\n\n  return res;\n}\n\n// **************** 7-Zip ZS Modification Start ****************\n#ifndef Z7_SFX\n#include <shlobj_core.h>\nstatic void BrowseToPath(\n    bool explore,\n    UString &path)\n{\n  if (explore /* || (GetFileAttributes(path.Ptr()) & FILE_ATTRIBUTE_DIRECTORY)*/) {\n    ShellExecute(NULL, L\"explore\", path.Ptr(), NULL, NULL, SW_SHOW);\n  } else {\n  #if (NTDDI_VERSION >= NTDDI_WINXP)\n    LPITEMIDLIST pidl = ILCreateFromPath(path.Ptr());\n    if (pidl) {\n      SHOpenFolderAndSelectItems(pidl,0,0,0);\n      ILFree(pidl);\n    }\n  #else\n    UString args = L\"/n,/select,\\\"\" + path + L\"\\\"\";\n    ShellExecute(NULL, L\"open\", L\"explorer.exe\", args.Ptr(), NULL, SW_SHOW);\n  #endif\n  }\n}\n#endif\n// **************** 7-Zip ZS Modification End ****************\n\nHRESULT ExtractGUI(\n    // DECL_EXTERNAL_CODECS_LOC_VARS\n    CCodecs *codecs,\n    const CObjectVector<COpenType> &formatIndices,\n    const CIntVector &excludedFormatIndices,\n    UStringVector &archivePaths,\n    UStringVector &archivePathsFull,\n    const NWildcard::CCensorNode &wildcardCensor,\n    CExtractOptions &options,\n    #ifndef Z7_SFX\n    CHashBundle *hb,\n    #endif\n    bool showDialog,\n    bool &messageWasDisplayed,\n    CExtractCallbackImp *extractCallback,\n    HWND hwndParent)\n{\n  messageWasDisplayed = false;\n\n  CThreadExtracting extracter;\n  /*\n  #ifdef Z7_EXTERNAL_CODECS\n  extracter.externalCodecs = _externalCodecs;\n  #endif\n  */\n  extracter.codecs = codecs;\n  extracter.FormatIndices = &formatIndices;\n  extracter.ExcludedFormatIndices = &excludedFormatIndices;\n\n  // **************** 7-Zip ZS Modification Start ****************\n#ifndef Z7_SFX\n  bool OpnTrgFold = false;\n#endif\n  // **************** 7-Zip ZS Modification End ****************\n  if (!options.TestMode)\n  {\n    FString outputDir = options.OutputDir;\n    #ifndef UNDER_CE\n    if (outputDir.IsEmpty())\n      GetCurrentDir(outputDir);\n    #endif\n    if (showDialog)\n    {\n      CExtractDialog dialog;\n      FString outputDirFull;\n      if (!MyGetFullPathName(outputDir, outputDirFull))\n      {\n        ShowErrorMessage(kIncorrectOutDir);\n        messageWasDisplayed = true;\n        return E_FAIL;\n      }\n      NName::NormalizeDirPathPrefix(outputDirFull);\n\n      dialog.DirPath = fs2us(outputDirFull);\n\n      dialog.OverwriteMode = options.OverwriteMode;\n      dialog.OverwriteMode_Force = options.OverwriteMode_Force;\n      dialog.PathMode = options.PathMode;\n      dialog.PathMode_Force = options.PathMode_Force;\n      dialog.ElimDup = options.ElimDup;\n      // **************** NanaZip Modification Start ****************\n      dialog.OpenFolder = options.OpenFolder;\n      // **************** NanaZip Modification End ****************\n\n      if (archivePathsFull.Size() == 1)\n        dialog.ArcPath = archivePathsFull[0];\n\n      #ifndef Z7_SFX\n      // dialog.AltStreams = options.NtOptions.AltStreams;\n      dialog.NtSecurity = options.NtOptions.NtSecurity;\n      if (extractCallback->PasswordIsDefined)\n        dialog.Password = extractCallback->Password;\n      #endif\n\n      if (dialog.Create(hwndParent) != IDOK)\n        return E_ABORT;\n\n      outputDir = us2fs(dialog.DirPath);\n\n      options.OverwriteMode = dialog.OverwriteMode;\n      options.PathMode = dialog.PathMode;\n      options.ElimDup = dialog.ElimDup;\n      // **************** NanaZip Modification Start ****************\n      options.OpenFolder = dialog.OpenFolder;\n      // **************** NanaZip Modification End ****************\n      \n      #ifndef Z7_SFX\n      // **************** 7-Zip ZS Modification Start ****************\n      OpnTrgFold = dialog.OpnTrgFold.Val;\n      // **************** 7-Zip ZS Modification End ****************\n      // options.NtOptions.AltStreams = dialog.AltStreams;\n      options.NtOptions.NtSecurity = dialog.NtSecurity;\n      extractCallback->Password = dialog.Password;\n      extractCallback->PasswordIsDefined = !dialog.Password.IsEmpty();\n      #endif\n    }\n    // **************** 7-Zip ZS Modification Start ****************\n    #ifndef Z7_SFX\n    else if (!options.OutputDir.IsEmpty()) // don't open target folder if extract here\n    {\n      // load setting \"open target folder\" from registry saved by previous dialog\n      NExtract::CInfo _info;\n      _info.Load();\n      OpnTrgFold = _info.OpnTrgFold.Val;\n    }\n    #endif\n    // **************** 7-Zip ZS Modification End ****************\n    if (!MyGetFullPathName(outputDir, options.OutputDir))\n    {\n      ShowErrorMessage(kIncorrectOutDir);\n      messageWasDisplayed = true;\n      return E_FAIL;\n    }\n    NName::NormalizeDirPathPrefix(options.OutputDir);\n    \n    /*\n    if (!CreateComplexDirectory(options.OutputDir))\n    {\n      UString s = GetUnicodeString(NError::MyFormatMessage(GetLastError()));\n      UString s2 = MyFormatNew(IDS_CANNOT_CREATE_FOLDER,\n      #ifdef Z7_LANG\n      0x02000603,\n      #endif\n      options.OutputDir);\n      s2.Add_LF();\n      s2 += s;\n      MyMessageBox(s2);\n      return E_FAIL;\n    }\n    */\n  }\n  \n  UString title = LangString(options.TestMode ? IDS_PROGRESS_TESTING : IDS_PROGRESS_EXTRACTING);\n\n  extracter.Title = title;\n  extracter.ExtractCallbackSpec = extractCallback;\n  extracter.ExtractCallbackSpec->ProgressDialog = &extracter;\n  extracter.FolderArchiveExtractCallback = extractCallback;\n  extracter.ExtractCallbackSpec->Init();\n\n  extracter.CompressingMode = false;\n\n  extracter.ArchivePaths = &archivePaths;\n  extracter.ArchivePathsFull = &archivePathsFull;\n  extracter.WildcardCensor = &wildcardCensor;\n  extracter.Options = &options;\n  #ifndef Z7_SFX\n  extracter.HashBundle = hb;\n  #endif\n\n  extracter.IconID = IDI_ICON;\n\n  RINOK(extracter.Create(title, hwndParent))\n  messageWasDisplayed = extracter.ThreadFinishedOK && extracter.MessagesDisplayed;\n  // **************** 7-Zip ZS Modification Start ****************\n#ifndef Z7_SFX\n  // browse/navigate to target path:\n  if (OpnTrgFold && extracter.Result == S_OK) {\n    // obtain path (directory or file) from first extracted:\n    UString extrPath = extracter.FirstExtractedPath;\n    if (extrPath.IsEmpty()) {\n      extrPath = options.OutputDir;\n    }\n    else\n    if (!options.OutputDir.IsEmpty()) {\n      // first subpath relative selected in dialog or given by options.OutputDir:\n      UString outDir = options.OutputDir;\n      if (outDir.Back() != WCHAR_PATH_SEPARATOR)\n        outDir += WCHAR_PATH_SEPARATOR;\n      extrPath = extracter.FirstExtractedPath;\n      if (extrPath.IsPrefixedBy(outDir)) {\n        int subIdx = extrPath.Find(WCHAR_PATH_SEPARATOR, outDir.Len());\n        if (subIdx != -1) {\n          extrPath = extrPath.Left(subIdx-1);\n        }\n      }\n    }\n    if (!extrPath.IsEmpty()) {\n      BrowseToPath(0 /* showDialog */, extrPath);\n    }\n  }\n#endif\n  // **************** 7-Zip ZS Modification End ****************\n  return extracter.Result;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/ExtractGUI.h",
    "content": "﻿// GUI/ExtractGUI.h\n\n#ifndef ZIP7_INC_EXTRACT_GUI_H\n#define ZIP7_INC_EXTRACT_GUI_H\n\n#include \"../Common/Extract.h\"\n\n#include \"../FileManager/ExtractCallback.h\"\n\n/*\n  RESULT can be S_OK, even if there are errors!!!\n  if RESULT == S_OK, check extractCallback->IsOK() after ExtractGUI().\n\n  RESULT = E_ABORT - user break.\n  RESULT != E_ABORT:\n  {\n   messageWasDisplayed = true  - message was displayed already.\n   messageWasDisplayed = false - there was some internal error, so you must show error message.\n  }\n*/\n\nHRESULT ExtractGUI(\n    // DECL_EXTERNAL_CODECS_LOC_VARS\n    CCodecs *codecs,\n    const CObjectVector<COpenType> &formatIndices,\n    const CIntVector &excludedFormatIndices,\n    UStringVector &archivePaths,\n    UStringVector &archivePathsFull,\n    const NWildcard::CCensorNode &wildcardCensor,\n    CExtractOptions &options,\n    #ifndef Z7_SFX\n    CHashBundle *hb,\n    #endif\n    bool showDialog,\n    bool &messageWasDisplayed,\n    CExtractCallbackImp *extractCallback,\n    HWND hwndParent = NULL);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/ExtractRes.h",
    "content": "﻿#define IDS_MEM_ERROR                   3000\n\n#define IDS_CANNOT_CREATE_FOLDER        3003\n#define IDS_UPDATE_NOT_SUPPORTED        3004\n#define IDS_CANT_OPEN_ARCHIVE           3005\n#define IDS_CANT_OPEN_ENCRYPTED_ARCHIVE 3006\n#define IDS_UNSUPPORTED_ARCHIVE_TYPE    3007\n\n#define IDS_CANT_OPEN_AS_TYPE           3017\n#define IDS_IS_OPEN_AS_TYPE             3018\n#define IDS_IS_OPEN_WITH_OFFSET         3019\n\n#define IDS_PROGRESS_EXTRACTING         3300\n\n#define IDS_PROGRESS_SKIPPING           3325\n\n#define IDS_EXTRACT_SET_FOLDER          3402\n\n#define IDS_EXTRACT_PATHS_FULL          3411\n#define IDS_EXTRACT_PATHS_NO            3412\n#define IDS_EXTRACT_PATHS_ABS           3413\n#define IDS_PATH_MODE_RELAT             3414\n\n#define IDS_EXTRACT_OVERWRITE_ASK             3421\n#define IDS_EXTRACT_OVERWRITE_WITHOUT_PROMPT  3422\n#define IDS_EXTRACT_OVERWRITE_SKIP_EXISTING   3423\n#define IDS_EXTRACT_OVERWRITE_RENAME          3424\n#define IDS_EXTRACT_OVERWRITE_RENAME_EXISTING 3425\n\n#define IDS_EXTRACT_MESSAGE_UNSUPPORTED_METHOD    3700\n#define IDS_EXTRACT_MESSAGE_DATA_ERROR            3701\n#define IDS_EXTRACT_MESSAGE_CRC_ERROR             3702\n#define IDS_EXTRACT_MESSAGE_DATA_ERROR_ENCRYPTED  3703\n#define IDS_EXTRACT_MESSAGE_CRC_ERROR_ENCRYPTED   3704\n\n#define IDS_EXTRACT_MSG_WRONG_PSW_GUESS      3710\n// #define IDS_EXTRACT_MSG_ENCRYPTED            3711\n\n#define IDS_EXTRACT_MSG_UNSUPPORTED_METHOD   3721\n#define IDS_EXTRACT_MSG_DATA_ERROR           3722\n#define IDS_EXTRACT_MSG_CRC_ERROR            3723\n#define IDS_EXTRACT_MSG_UNAVAILABLE_DATA     3724\n#define IDS_EXTRACT_MSG_UEXPECTED_END        3725\n#define IDS_EXTRACT_MSG_DATA_AFTER_END       3726\n#define IDS_EXTRACT_MSG_IS_NOT_ARC           3727\n#define IDS_EXTRACT_MSG_HEADERS_ERROR        3728\n#define IDS_EXTRACT_MSG_WRONG_PSW_CLAIM      3729\n\n#define IDS_OPEN_MSG_UNAVAILABLE_START       3763\n#define IDS_OPEN_MSG_UNCONFIRMED_START       3764\n#define IDS_OPEN_MSG_UNSUPPORTED_FEATURE     3768\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/HashGUI.h",
    "content": "﻿// HashGUI.h\n\n#ifndef ZIP7_INC_HASH_GUI_H\n#define ZIP7_INC_HASH_GUI_H\n\n#include \"../Common/HashCalc.h\"\n#include \"../Common/Property.h\"\n\nHRESULT HashCalcGUI(\n    DECL_EXTERNAL_CODECS_LOC_VARS\n    const NWildcard::CCensor &censor,\n    const CHashOptions &options,\n    bool &messageWasDisplayed);\n\ntypedef CObjectVector<CProperty> CPropNameValPairs;\n\nvoid AddValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value);\nvoid AddSizeValue(UString &s, UInt64 value);\nvoid AddSizeValuePair(CPropNameValPairs &pairs, UINT resourceID, UInt64 value);\n\nvoid AddHashBundleRes(CPropNameValPairs &s, const CHashBundle &hb);\nvoid AddHashBundleRes(UString &s, const CHashBundle &hb);\n\nvoid ShowHashResults(const CPropNameValPairs &propPairs, HWND hwnd);\nvoid ShowHashResults(const CHashBundle &hb, HWND hwnd);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#if _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../FileManager/StdAfx.h\"\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/7zip/UI/GUI/resource2.h",
    "content": "﻿#define IDS_PROGRESS_COMPRESSING  3301\n#define IDS_ARCHIVES_COLON        3907\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/AutoPtr.h",
    "content": "﻿// Common/AutoPtr.h\n\n#ifndef ZIP7_INC_COMMON_AUTOPTR_H\n#define ZIP7_INC_COMMON_AUTOPTR_H\n\ntemplate<class T> class CMyUniquePtr\n// CMyAutoPtr\n{\n  T *_p;\n  \n  CMyUniquePtr(CMyUniquePtr<T>& p); // : _p(p.release()) {}\n  CMyUniquePtr<T>& operator=(T *p);\n  CMyUniquePtr<T>& operator=(CMyUniquePtr<T>& p);\n  /*\n  {\n    reset(p.release());\n    return (*this);\n  }\n  */\n  void reset(T* p = NULL)\n  {\n    if (p != _p)\n      delete _p;\n    _p = p;\n  }\npublic:\n  CMyUniquePtr(T *p = NULL) : _p(p) {}\n  ~CMyUniquePtr() { delete _p; }\n  T& operator*() const { return *_p; }\n  T* operator->() const { return _p; }\n  // operator bool() const { return _p != NULL; }\n  T* get() const { return _p; }\n  T* release()\n  {\n    T *tmp = _p;\n    _p = NULL;\n    return tmp;\n  }\n  void Create_if_Empty()\n  {\n    if (!_p)\n      _p = new T;\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/CRC.cpp",
    "content": "﻿// Common/CRC.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/7zCrc.h\"\n\nstatic struct CCRCTableInit { CCRCTableInit() { CrcGenerateTable(); } } g_CRCTableInit;\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/ComTry.h",
    "content": "﻿// ComTry.h\n\n#ifndef ZIP7_INC_COM_TRY_H\n#define ZIP7_INC_COM_TRY_H\n\n#include \"MyWindows.h\"\n// #include \"Exception.h\"\n// #include \"NewHandler.h\"\n\n#define COM_TRY_BEGIN try {\n#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; }\n  \n/*\n#define COM_TRY_END } \\\n  catch(const CNewException &) { return E_OUTOFMEMORY; } \\\n  catch(...) { return HRESULT_FROM_WIN32(ERROR_NOACCESS); } \\\n*/\n  // catch(const CSystemException &e) { return e.ErrorCode; }\n  // catch(...) { return E_FAIL; }\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/CommandLineParser.cpp",
    "content": "﻿// CommandLineParser.cpp\n\n#include \"StdAfx.h\"\n\n#include \"CommandLineParser.h\"\n\n// **************** 7-Zip ZS Modification Start ****************\n#include <ctype.h> // isblank()\n// **************** 7-Zip ZS Modification End ****************\n\nnamespace NCommandLineParser {\n\n// **************** 7-Zip ZS Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n#ifdef _WIN32\n\nbool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)\n{\n  dest1.Empty();\n  dest2.Empty();\n  bool quoteMode = false;\n  unsigned i;\n  for (i = 0; i < src.Len(); i++)\n  {\n    const wchar_t c = src[i];\n    if ((c == L' ' || c == L'\\t') && !quoteMode)\n    {\n      dest2 = src.Ptr(i + 1);\n      return i != 0;\n    }\n    if (c == L'\\\"')\n      quoteMode = !quoteMode;\n    else\n      dest1 += c;\n  }\n  return i != 0;\n}\n\nvoid SplitCommandLine(const UString &s, UStringVector &parts)\n{\n#if 0\n/* we don't use CommandLineToArgvW() because\n   it can remove tail backslash:\n     \"1\\\"\n   converted to\n     1\"\n*/\n  parts.Clear();\n  {\n    int nArgs;\n    LPWSTR *szArgList = CommandLineToArgvW(s, &nArgs);\n    if (szArgList)\n    {\n      for (int i = 0; i < nArgs; i++)\n      {\n        // printf(\"%2d: |%S|\\n\", i, szArglist[i]);\n        parts.Add(szArgList[i]);\n      }\n      LocalFree(szArgList);\n      return;\n    }\n  }\n#endif\n/*\n#ifdef _UNICODE\n  throw 20240406;\n#else\n*/\n  UString sTemp (s);\n  sTemp.Trim();\n  parts.Clear();\n  for (;;)\n  {\n    UString s1, s2;\n    if (SplitCommandLine(sTemp, s1, s2))\n      parts.Add(s1);\n    if (s2.IsEmpty())\n      break;\n    sTemp = s2;\n  }\n// #endif\n}\n#endif\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\nstatic const wchar_t * _SplitCommandLine(const wchar_t* s, UString &dest)\n{\n  unsigned qcount = 0, bcount = 0;\n  wchar_t c; const wchar_t *f, *b;\n\n  dest.Empty();\n\n  // skip spaces:\n  while (isblank(*s)) { s++; };\n  b = f = s;\n\n  while ((c = *s++) != 0)\n  {\n    switch (c)\n    {\n      case L'\\\\':\n        // a backslash - count them up to quote-char or regular char \n        bcount++;\n      break;\n      case L'\"':\n        // check quote char is escaped:\n        if (!(bcount & 1))\n        {\n          // preceded by an even number of '\\', this is half that\n          // number of '\\':\n          dest.AddFrom(f, (unsigned)(s - f - bcount/2 - 1)); f = s;\n          // count quote chars:\n          qcount++;\n        }\n        else\n        {\n          // preceded by an odd number of '\\', this is half that\n          // number of '\\' followed by an escaped '\"':\n          dest.AddFrom(f, (unsigned)(s - f - bcount/2 - 2)); f = s;\n          dest += L'\"';\n        }\n        bcount = 0;\n        // now count the number of consecutive quotes (inclusive\n        // the quote that lead us here):\n        while (*s == L'\"')\n        {\n          s++;\n          if (++qcount == 3)\n          {\n            dest += L'\"';\n            qcount = 0;\n          }\n        }\n        f = s;\n        if (qcount == 2)\n          qcount = 0;\n        break;\n      case L' ':\n        // fall through\n      case L'\\t':\n        // a space (end of arg or regular char):\n        if (!qcount)\n        {\n          // end of argument:\n          dest.AddFrom(f, (unsigned)(s - f - 1)); f = s;\n          // skip to the next one:\n          while (isblank(*s)) { s++; };\n          bcount = 0;\n          goto done;\n        }\n        // fall through\n      // no break - a space as regular char:\n      default:\n        // a regular character, reset backslash counter\n        bcount = 0;\n    }\n  }\n  s--; // back to NTS-zero char\n  dest.AddFrom(f, (unsigned)(s - f));\ndone:\n  // remaining part if argument was found, otherwise NULL:\n  return (dest.Len() || *b) ? s : NULL;\n}\n\nbool SplitCommandLine(const UString& src, UString& dest1, UString& dest2)\n{\n  const wchar_t *s = src.Ptr();\n  s = _SplitCommandLine(s, dest1);\n  if (s) {\n    dest2 = s;\n    return true;\n  } else {\n    dest2.Empty();\n    return false;\n  }\n}\n\nvoid SplitCommandLine(const UString &src, UStringVector &parts)\n{\n  const wchar_t *s = src.Ptr();\n  parts.Clear();\n  for (;;)\n  {\n    UString s1;\n    s = _SplitCommandLine(s, s1);\n    if (s)\n      parts.Add(s1);\n    if (!s || !*s)\n      break;\n  }\n}\n// **************** 7-Zip ZS Modification End ****************\n\nstatic const char * const kStopSwitchParsing = \"--\";\n\nstatic bool inline IsItSwitchChar(wchar_t c)\n{\n  return (c == '-');\n}\n\nCParser::CParser():\n  _switches(NULL),\n  StopSwitchIndex(-1)\n{\n}\n\nCParser::~CParser()\n{\n  delete []_switches;\n}\n\n\n// if (s) contains switch then function updates switch structures\n// out: true, if (s) is a switch\nbool CParser::ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches)\n{\n  if (s.IsEmpty() || !IsItSwitchChar(s[0]))\n    return false;\n\n  unsigned pos = 1;\n  unsigned switchIndex = 0;\n  int maxLen = -1;\n\n  for (unsigned i = 0; i < numSwitches; i++)\n  {\n    const char * const key = switchForms[i].Key;\n    const unsigned switchLen = MyStringLen(key);\n    if ((int)switchLen <= maxLen || pos + switchLen > s.Len())\n      continue;\n    if (IsString1PrefixedByString2_NoCase_Ascii((const wchar_t *)s + pos, key))\n    {\n      switchIndex = i;\n      maxLen = (int)switchLen;\n    }\n  }\n\n  if (maxLen < 0)\n  {\n    ErrorMessage = \"Unknown switch:\";\n    return false;\n  }\n\n  pos += (unsigned)maxLen;\n\n  CSwitchResult &sw = _switches[switchIndex];\n  const CSwitchForm &form = switchForms[switchIndex];\n\n  if (!form.Multi && sw.ThereIs)\n  {\n    ErrorMessage = \"Multiple instances for switch:\";\n    return false;\n  }\n\n  sw.ThereIs = true;\n\n  const unsigned rem = s.Len() - pos;\n  if (rem < form.MinLen)\n  {\n    ErrorMessage = \"Too short switch:\";\n    return false;\n  }\n\n  sw.WithMinus = false;\n  sw.PostCharIndex = -1;\n\n  switch (form.Type)\n  {\n    case NSwitchType::kMinus:\n      if (rem == 1)\n      {\n        sw.WithMinus = (s[pos] == '-');\n        if (sw.WithMinus)\n          return true;\n        ErrorMessage = \"Incorrect switch postfix:\";\n        return false;\n      }\n      break;\n\n    case NSwitchType::kChar:\n      if (rem == 1)\n      {\n        const wchar_t c = s[pos];\n        if (c <= 0x7F)\n        {\n          sw.PostCharIndex = FindCharPosInString(form.PostCharSet, (char)c);\n          if (sw.PostCharIndex >= 0)\n            return true;\n        }\n        ErrorMessage = \"Incorrect switch postfix:\";\n        return false;\n      }\n      break;\n\n    case NSwitchType::kString:\n    {\n      sw.PostStrings.Add(s.Ptr(pos));\n      return true;\n    }\n    // case NSwitchType::kSimple:\n    default: break;\n  }\n\n  if (pos != s.Len())\n  {\n    ErrorMessage = \"Too long switch:\";\n    return false;\n  }\n  return true;\n}\n\n\nbool CParser::ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings)\n{\n  StopSwitchIndex = -1;\n  ErrorMessage.Empty();\n  ErrorLine.Empty();\n  NonSwitchStrings.Clear();\n  delete []_switches;\n  _switches = NULL;\n  _switches = new CSwitchResult[numSwitches];\n\n  FOR_VECTOR (i, commandStrings)\n  {\n    const UString &s = commandStrings[i];\n    if (StopSwitchIndex < 0)\n    {\n      if (s.IsEqualTo(kStopSwitchParsing))\n      {\n        StopSwitchIndex = (int)NonSwitchStrings.Size();\n        continue;\n      }\n      if (!s.IsEmpty() && IsItSwitchChar(s[0]))\n      {\n        if (ParseString(s, switchForms, numSwitches))\n          continue;\n        ErrorLine = s;\n        return false;\n      }\n    }\n    NonSwitchStrings.Add(s);\n  }\n  return true;\n}\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/CommandLineParser.h",
    "content": "﻿// Common/CommandLineParser.h\n\n#ifndef ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H\n#define ZIP7_INC_COMMON_COMMAND_LINE_PARSER_H\n\n#include \"MyString.h\"\n\nnamespace NCommandLineParser {\n\nbool SplitCommandLine(const UString &src, UString &dest1, UString &dest2);\nvoid SplitCommandLine(const UString &s, UStringVector &parts);\n\nnamespace NSwitchType\n{\n  enum EEnum\n  {\n    kSimple,\n    kMinus,\n    kString,\n    kChar\n  };\n}\n\nstruct CSwitchForm\n{\n  const char *Key;\n  Byte Type;\n  bool Multi;\n  Byte MinLen;\n  // int MaxLen;\n  const char *PostCharSet;\n};\n\nstruct CSwitchResult\n{\n  bool ThereIs;\n  bool WithMinus;\n  int PostCharIndex;\n  UStringVector PostStrings;\n  \n  CSwitchResult(): ThereIs(false) {}\n};\n  \nclass CParser\n{\n  CSwitchResult *_switches;\n\n  bool ParseString(const UString &s, const CSwitchForm *switchForms, unsigned numSwitches);\npublic:\n  UStringVector NonSwitchStrings;\n  int StopSwitchIndex;  // NonSwitchStrings[StopSwitchIndex+] are after \"--\"\n  AString ErrorMessage;\n  UString ErrorLine;\n  \n  CParser();\n  ~CParser();\n  bool ParseStrings(const CSwitchForm *switchForms, unsigned numSwitches, const UStringVector &commandStrings);\n  const CSwitchResult& operator[](unsigned index) const { return _switches[index]; }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/Common.h",
    "content": "﻿// Common.h\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n\n#ifndef ZIP7_INC_COMMON_H\n#define ZIP7_INC_COMMON_H\n\n#include \"../../C/Precomp.h\"\n#include \"Common0.h\"\n#include \"MyWindows.h\"\n\n/*\nThis file is included to all cpp files in 7-Zip.\nEach folder contains StdAfx.h file that includes \"Common.h\".\nSo 7-Zip includes \"Common.h\" in both modes:\n  with precompiled StdAfx.h\nand\n  without precompiled StdAfx.h\n\ninclude \"Common.h\" before other h files of 7-zip,\n   if you need predefined macros.\ndo not include \"Common.h\", if you need only interfaces,\n   and you don't need predefined macros.\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/Common0.h",
    "content": "﻿// Common0.h\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n\n#ifndef ZIP7_INC_COMMON0_H\n#define ZIP7_INC_COMMON0_H\n\n#include \"../../C/Compiler.h\"\n\n/*\nThis file contains compiler related things for cpp files.\nThis file is included to all cpp files in 7-Zip via \"Common.h\".\nAlso this file is included in \"IDecl.h\" (that is included in interface files).\nSo external modules can use 7-Zip interfaces without\npredefined macros defined in \"Common.h\".\n*/\n\n#ifdef _MSC_VER\n  #pragma warning(disable : 4710) // function not inlined\n  // 'CUncopyable::CUncopyable':\n  #pragma warning(disable : 4514) // unreferenced inline function has been removed\n  #if _MSC_VER < 1300\n    #pragma warning(disable : 4702) // unreachable code\n    #pragma warning(disable : 4714) // function marked as __forceinline not inlined\n    #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information\n  #endif\n  #if _MSC_VER < 1400\n    #pragma warning(disable : 4511) // copy constructor could not be generated    // #pragma warning(disable : 4512) // assignment operator could not be generated\n    #pragma warning(disable : 4512) // assignment operator could not be generated\n  #endif\n  #if _MSC_VER > 1400 && _MSC_VER <= 1900\n    // #pragma warning(disable : 4996)\n       // strcat: This function or variable may be unsafe\n       // GetVersion was declared deprecated\n  #endif\n\n#if _MSC_VER > 1200\n// -Wall warnings\n\n#if _MSC_VER <= 1600\n#pragma warning(disable : 4917) // 'OLE_HANDLE' : a GUID can only be associated with a class, interface or namespace\n#endif\n\n// #pragma warning(disable : 4061) // enumerator '' in switch of enum '' is not explicitly handled by a case label\n// #pragma warning(disable : 4266) // no override available for virtual member function from base ''; function is hidden\n#pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted\n#pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted\n#if _MSC_VER >= 1600 && _MSC_VER < 1920\n#pragma warning(disable : 4571) // Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught\n#endif\n#if _MSC_VER >= 1600\n#pragma warning(disable : 4365) // 'initializing' : conversion from 'int' to 'unsigned int', signed / unsigned mismatch\n#endif\n#if _MSC_VER < 1800\n// we disable the warning, if we don't use 'final' in class\n#pragma warning(disable : 4265) // class has virtual functions, but destructor is not virtual\n#endif\n\n#if _MSC_VER >= 1900\n#pragma warning(disable : 5026) // move constructor was implicitly defined as deleted\n#pragma warning(disable : 5027) // move assignment operator was implicitly defined as deleted\n#endif\n#if _MSC_VER >= 1912\n#pragma warning(disable : 5039) // pointer or reference to potentially throwing function passed to 'extern \"C\"' function under - EHc.Undefined behavior may occur if this function throws an exception.\n#endif\n#if _MSC_VER >= 1925\n// #pragma warning(disable : 5204) // 'ISequentialInStream' : class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly\n#endif\n#if _MSC_VER >= 1934\n// #pragma warning(disable : 5264) // const variable is not used\n#endif\n\n#endif // _MSC_VER > 1200\n#endif // _MSC_VER\n\n\n#if defined(_MSC_VER) // && !defined(__clang__)\n#define Z7_DECLSPEC_NOTHROW   __declspec(nothrow)\n#elif defined(__clang__) || defined(__GNUC__)\n#define Z7_DECLSPEC_NOTHROW   __attribute__((nothrow))\n#else\n#define Z7_DECLSPEC_NOTHROW\n#endif\n\n/*\n#if defined (_MSC_VER) && _MSC_VER >= 1900 \\\n    || defined(__clang__) && __clang_major__ >= 6 \\\n    || defined(__GNUC__) && __GNUC__ >= 6\n  #define Z7_noexcept noexcept\n#else\n  #define Z7_noexcept throw()\n#endif\n*/\n\n\n#if defined(__clang__)\n\n#if /* defined(_WIN32) && */ __clang_major__ >= 16\n#pragma GCC diagnostic ignored \"-Wc++98-compat-pedantic\"\n#endif\n\n#if __clang_major__ >= 4 && __clang_major__ < 12 && !defined(_WIN32)\n/*\nif compiled with new GCC libstdc++, GCC libstdc++ can use:\n13.2.0/include/c++/\n    <new> : #define _NEW\n    <stdlib.h> : #define _GLIBCXX_STDLIB_H 1\n*/\n#pragma GCC diagnostic ignored \"-Wreserved-id-macro\"\n#endif\n\n// noexcept, final, = delete\n#pragma GCC diagnostic ignored \"-Wc++98-compat\"\n#if __clang_major__ >= 4\n// throw() dynamic exception specifications are deprecated\n#pragma GCC diagnostic ignored \"-Wdeprecated-dynamic-exception-spec\"\n#endif\n\n#if __clang_major__ <= 6 // check it\n#pragma GCC diagnostic ignored \"-Wsign-conversion\"\n#endif\n\n#pragma GCC diagnostic ignored \"-Wold-style-cast\"\n#pragma GCC diagnostic ignored \"-Wglobal-constructors\"\n#pragma GCC diagnostic ignored \"-Wexit-time-destructors\"\n\n#if defined(Z7_LLVM_CLANG_VERSION) && __clang_major__ >= 18 /* 18.1.0RC */ \\\n  || defined(Z7_APPLE_CLANG_VERSION) && __clang_major__ >= 16 // for APPLE=17 (LLVM=19)\n  #pragma GCC diagnostic ignored \"-Wswitch-default\"\n#endif\n// #pragma GCC diagnostic ignored \"-Wunused-private-field\"\n// #pragma GCC diagnostic ignored \"-Wnonportable-system-include-path\"\n// #pragma GCC diagnostic ignored \"-Wsuggest-override\"\n// #pragma GCC diagnostic ignored \"-Wsign-conversion\"\n// #pragma GCC diagnostic ignored \"-Winconsistent-missing-override\"\n// #pragma GCC diagnostic ignored \"-Wsuggest-destructor-override\"\n// #pragma GCC diagnostic ignored \"-Wnon-virtual-dtor\"\n// #pragma GCC diagnostic ignored \"-Wdeprecated-copy-with-user-provided-dtor\"\n// #pragma GCC diagnostic ignored \"-Wdeprecated-copy-dtor\"\n// #ifndef _WIN32\n// #pragma GCC diagnostic ignored \"-Wweak-vtables\"\n// #endif\n/*\n#if   defined(Z7_GCC_VERSION)   && (Z7_GCC_VERSION   >= 40400) \\\n   || defined(Z7_CLANG_VERSION) && (Z7_CLANG_VERSION >= 30000)\n// enumeration values not explicitly handled in switch\n#pragma GCC diagnostic ignored \"-Wswitch-enum\"\n#endif\n*/\n#endif // __clang__\n\n\n#ifdef __GNUC__\n// #pragma GCC diagnostic ignored \"-Wdelete-non-virtual-dtor\"\n#endif\n\n\n/* There is BUG in MSVC 6.0 compiler for operator new[]:\n   It doesn't check overflow, when it calculates size in bytes for allocated array.\n   So we can use Z7_ARRAY_NEW macro instead of new[] operator. */\n\n#if defined(_MSC_VER) && (_MSC_VER == 1200) && !defined(_WIN64)\n  #define Z7_ARRAY_NEW(p, T, size)  p = new T[((size) > 0xFFFFFFFFu / sizeof(T)) ? 0xFFFFFFFFu / sizeof(T) : (size)];\n#else\n  #define Z7_ARRAY_NEW(p, T, size)  p = new T[size];\n#endif\n\n#if (defined(__GNUC__) && (__GNUC__ >= 8))\n  #define Z7_ATTR_NORETURN  __attribute__((noreturn))\n#elif (defined(__clang__) && (__clang_major__ >= 3))\n  #if __has_feature(cxx_attributes)\n    #define Z7_ATTR_NORETURN  [[noreturn]]\n  #else\n    #define Z7_ATTR_NORETURN  __attribute__((noreturn))\n  #endif\n#elif (defined(_MSC_VER) && (_MSC_VER >= 1900))\n  #define Z7_ATTR_NORETURN  [[noreturn]]\n#else\n  #define Z7_ATTR_NORETURN\n#endif\n\n\n// final in \"GCC 4.7.0\"\n// In C++98 and C++03 code the alternative spelling __final can be used instead (this is a GCC extension.)\n\n#if defined (__cplusplus) && __cplusplus >= 201103L \\\n    || defined(_MSC_VER) && _MSC_VER >= 1800 \\\n    || defined(__clang__) && __clang_major__ >= 4 \\\n    /* || defined(__GNUC__) && __GNUC__ >= 9 */\n  #define Z7_final  final\n  #if defined(__clang__) && __cplusplus < 201103L\n    #pragma GCC diagnostic ignored \"-Wc++11-extensions\"\n  #endif\n#elif defined (__cplusplus) && __cplusplus >= 199711L \\\n    && defined(__GNUC__) && __GNUC__ >= 4 && !defined(__clang__)\n  #define Z7_final __final\n#else\n  #define Z7_final\n  #if defined(__clang__) && __clang_major__ >= 4 \\\n     || defined(__GNUC__) && __GNUC__ >= 4\n    #pragma GCC diagnostic ignored \"-Wnon-virtual-dtor\"\n    #pragma GCC diagnostic ignored \"-Wdelete-non-virtual-dtor\"\n  #endif\n#endif\n\n#define Z7_class_final(c)  class c Z7_final\n\n\n#if defined (__cplusplus) && __cplusplus >= 201103L \\\n    || (defined(_MSC_VER) && _MSC_VER >= 1800)\n  #define Z7_CPP_IS_SUPPORTED_default\n  #define Z7_eq_delete  = delete\n  // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c) c(const c& k) = default;\n#else\n  #define Z7_eq_delete\n  // #define Z7_DECL_DEFAULT_COPY_CONSTRUCTOR_IF_SUPPORTED(c)\n#endif\n\n\n#if defined(__cplusplus) && (__cplusplus >= 201103L) \\\n    || defined(_MSC_VER) && (_MSC_VER >= 1400) /* && (_MSC_VER != 1600) */ \\\n    || defined(__clang__) && __clang_major__ >= 4\n  #if defined(_MSC_VER) && (_MSC_VER == 1600) /* && (_MSC_VER != 1600) */\n    #pragma warning(disable : 4481) // nonstandard extension used: override specifier 'override'\n    #define Z7_DESTRUCTOR_override\n  #else\n    #define Z7_DESTRUCTOR_override  override\n  #endif\n  #define Z7_override  override\n#else\n  #define Z7_override\n  #define Z7_DESTRUCTOR_override\n#endif\n\n\n\n#define Z7_CLASS_NO_COPY(cls) \\\n  private: \\\n  cls(const cls &) Z7_eq_delete; \\\n  cls &operator=(const cls &) Z7_eq_delete;\n\nclass CUncopyable\n{\nprotected:\n  CUncopyable() {} // allow constructor\n  // ~CUncopyable() {}\n  Z7_CLASS_NO_COPY(CUncopyable)\n};\n\n#define MY_UNCOPYABLE  :private CUncopyable\n// #define MY_UNCOPYABLE\n\n\n// typedef void (*Z7_void_Function)(void);\n\n#if defined(__clang__) || defined(__GNUC__)\n#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<Z7_void_Function>(e))\n#else\n#define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(reinterpret_cast<void*>(e))\n// #define Z7_CAST_FUNC(t, e) reinterpret_cast<t>(e)\n#endif\n\n#define Z7_GET_PROC_ADDRESS(func_type, hmodule, func_name)  \\\n    Z7_CAST_FUNC(func_type, GetProcAddress(hmodule, func_name))\n\n// || defined(__clang__)\n// || defined(__GNUC__)\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1400)\n#define Z7_DECLSPEC_NOVTABLE __declspec(novtable)\n#else\n#define Z7_DECLSPEC_NOVTABLE\n#endif\n\n#ifdef __clang__\n#define Z7_PURE_INTERFACES_BEGIN \\\n_Pragma(\"GCC diagnostic push\") \\\n_Pragma(\"GCC diagnostic ignored \\\"-Wnon-virtual-dtor\\\"\")\n_Pragma(\"GCC diagnostic ignored \\\"-Wweak-vtables\\\"\")\n#define Z7_PURE_INTERFACES_END \\\n_Pragma(\"GCC diagnostic pop\")\n#else\n#define Z7_PURE_INTERFACES_BEGIN\n#define Z7_PURE_INTERFACES_END\n#endif\n\n// NewHandler.h and NewHandler.cpp redefine operator new() to throw exceptions, if compiled with old MSVC compilers\n#include \"NewHandler.h\"\n\n/*\n// #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))\n#ifndef ARRAY_SIZE\n#define ARRAY_SIZE(a)  Z7_ARRAY_SIZE(a)\n#endif\n*/\n\n#endif // ZIP7_INC_COMMON0_H\n\n\n\n// #define Z7_REDEFINE_NULL\n\n#if defined(Z7_REDEFINE_NULL) /* && (!defined(__clang__) || defined(_MSC_VER)) */\n\n// NULL is defined in <stddef.h>\n#include <stddef.h>\n#undef NULL\n\n#ifdef __cplusplus\n  #if defined (__cplusplus) && __cplusplus >= 201103L \\\n    || (defined(_MSC_VER) && _MSC_VER >= 1800)\n    #define NULL  nullptr\n  #else\n    #define NULL  0\n  #endif\n#else\n  #define NULL  ((void *)0)\n#endif\n\n#else // Z7_REDEFINE_NULL\n\n#if defined(__clang__) && __clang_major__ >= 5\n#pragma GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"\n#endif\n\n#endif // Z7_REDEFINE_NULL\n\n// for precompiler:\n// #include \"MyWindows.h\"\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/CrcReg.cpp",
    "content": "﻿// CrcReg.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/7zCrc.h\"\n#include \"../../C/CpuArch.h\"\n\n#include \"../Common/MyCom.h\"\n\n#include \"../7zip/Common/RegisterCodec.h\"\n\nEXTERN_C_BEGIN\n\nEXTERN_C_END\n\nZ7_CLASS_IMP_COM_2(\n  CCrcHasher\n  , IHasher\n  , ICompressSetCoderProperties\n)\n  UInt32 _crc;\n  Z7_CRC_UPDATE_FUNC _updateFunc;\n\n  Z7_CLASS_NO_COPY(CCrcHasher)\n\n  bool SetFunctions(UInt32 tSize);\npublic:\n  Byte _mtDummy[1 << 7];  // it's public to eliminate clang warning: unused private field\n\n  CCrcHasher(): _crc(CRC_INIT_VAL) { SetFunctions(0); }\n};\n\nbool CCrcHasher::SetFunctions(UInt32 tSize)\n{\n  const Z7_CRC_UPDATE_FUNC f = z7_GetFunc_CrcUpdate(tSize);\n  if (!f)\n  {\n    _updateFunc = CrcUpdate;\n    return false;\n  }\n  _updateFunc = f;\n  return true;\n}\n\nZ7_COM7F_IMF(CCrcHasher::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps))\n{\n  for (UInt32 i = 0; i < numProps; i++)\n  {\n    if (propIDs[i] == NCoderPropID::kDefaultProp)\n    {\n      const PROPVARIANT &prop = coderProps[i];\n      if (prop.vt != VT_UI4)\n        return E_INVALIDARG;\n      if (!SetFunctions(prop.ulVal))\n        return E_NOTIMPL;\n    }\n  }\n  return S_OK;\n}\n\nZ7_COM7F_IMF2(void, CCrcHasher::Init())\n{\n  _crc = CRC_INIT_VAL;\n}\n\nZ7_COM7F_IMF2(void, CCrcHasher::Update(const void *data, UInt32 size))\n{\n  _crc = _updateFunc(_crc, data, size);\n}\n\nZ7_COM7F_IMF2(void, CCrcHasher::Final(Byte *digest))\n{\n  const UInt32 val = CRC_GET_DIGEST(_crc);\n  SetUi32(digest, val)\n}\n\nREGISTER_HASHER(CCrcHasher, 0x1, \"CRC32\", 4)\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/Defs.h",
    "content": "﻿// Common/Defs.h\n\n#ifndef ZIP7_INC_COMMON_DEFS_H\n#define ZIP7_INC_COMMON_DEFS_H\n\ntemplate <class T> inline T MyMin(T a, T b) { return a < b ? a : b; }\ntemplate <class T> inline T MyMax(T a, T b) { return a > b ? a : b; }\n\ntemplate <class T> inline int MyCompare(T a, T b)\n  { return a == b ? 0 : (a < b ? -1 : 1); }\n\ninline int BoolToInt(bool v) { return (v ? 1 : 0); }\ninline unsigned BoolToUInt(bool v) { return (v ? 1u : 0u); }\ninline bool IntToBool(int v) { return (v != 0); }\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/DynLimBuf.cpp",
    "content": "﻿// Common/DynLimBuf.cpp\n\n#include \"StdAfx.h\"\n\n#include \"DynLimBuf.h\"\n#include \"MyString.h\"\n\nCDynLimBuf::CDynLimBuf(size_t limit) throw()\n{\n  _chars = NULL;\n  _pos = 0;\n  _size = 0;\n  _sizeLimit = limit;\n  _error = true;\n  unsigned size = 1 << 4;\n  if (size > limit)\n    size = (unsigned)limit;\n  _chars = (Byte *)MyAlloc(size);\n  if (_chars)\n  {\n    _size = size;\n    _error = false;\n  }\n}\n\nCDynLimBuf & CDynLimBuf::operator+=(char c) throw()\n{\n  if (_error)\n    return *this;\n  if (_size == _pos)\n  {\n    size_t n = _sizeLimit - _size;\n    if (n == 0)\n    {\n      _error = true;\n      return *this;\n    }\n    if (n > _size)\n      n = _size;\n\n    n += _pos;\n\n    Byte *newBuf = (Byte *)MyAlloc(n);\n    if (!newBuf)\n    {\n      _error = true;\n      return *this;\n    }\n    memcpy(newBuf, _chars, _pos);\n    MyFree(_chars);\n    _chars = newBuf;\n    _size = n;\n  }\n  _chars[_pos++] = (Byte)c;\n  return *this;\n}\n\nCDynLimBuf &CDynLimBuf::operator+=(const char *s) throw()\n{\n  if (_error)\n    return *this;\n  unsigned len = MyStringLen(s);\n  size_t rem = _sizeLimit - _pos;\n  if (rem < len)\n  {\n    len = (unsigned)rem;\n    _error = true;\n  }\n  if (_size - _pos < len)\n  {\n    size_t n = _pos + len;\n    if (n - _size < _size)\n    {\n      n = _sizeLimit;\n      if (n - _size > _size)\n        n = _size * 2;\n    }\n\n    Byte *newBuf = (Byte *)MyAlloc(n);\n    if (!newBuf)\n    {\n      _error = true;\n      return *this;\n    }\n    memcpy(newBuf, _chars, _pos);\n    MyFree(_chars);\n    _chars = newBuf;\n    _size = n;\n  }\n  memcpy(_chars + _pos, s, len);\n  _pos += len;\n  return *this;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/DynLimBuf.h",
    "content": "﻿// Common/DynLimBuf.h\n\n#ifndef ZIP7_INC_COMMON_DYN_LIM_BUF_H\n#define ZIP7_INC_COMMON_DYN_LIM_BUF_H\n\n#include <string.h>\n\n#include \"../../C/Alloc.h\"\n\n#include \"MyString.h\"\n\nclass CDynLimBuf\n{\n  Byte *_chars;\n  size_t _pos;\n  size_t _size;\n  size_t _sizeLimit;\n  bool _error;\n\n  CDynLimBuf(const CDynLimBuf &s);\n\n  // ---------- forbidden functions ----------\n  CDynLimBuf &operator+=(wchar_t c);\n\npublic:\n  CDynLimBuf(size_t limit) throw();\n  ~CDynLimBuf() { MyFree(_chars); }\n\n  size_t Len() const { return _pos; }\n  bool IsError() const { return _error; }\n  void Empty() { _pos = 0; _error = false; }\n\n  operator const Byte *() const { return _chars; }\n  // const char *Ptr() const { return _chars; }\n\n  CDynLimBuf &operator+=(char c) throw();\n  CDynLimBuf &operator+=(const char *s) throw();\n};\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/DynamicBuffer.h",
    "content": "﻿// Common/DynamicBuffer.h\n\n#ifndef ZIP7_INC_COMMON_DYNAMIC_BUFFER_H\n#define ZIP7_INC_COMMON_DYNAMIC_BUFFER_H\n\n#include <string.h>\n\n#include \"MyTypes.h\"\n\ntemplate <class T> class CDynamicBuffer\n{\n  T *_items;\n  size_t _size;\n  size_t _pos;\n\n  CDynamicBuffer(const CDynamicBuffer &buffer);\n  void operator=(const CDynamicBuffer &buffer);\n\n  void Grow(size_t size)\n  {\n    size_t delta = _size >= 64 ? _size : 64;\n    if (delta < size)\n      delta = size;\n    size_t newCap = _size + delta;\n    if (newCap < delta)\n    {\n      newCap = _size + size;\n      if (newCap < size)\n        throw 20120116;\n    }\n\n    T *newBuffer = new T[newCap];\n    if (_pos != 0)\n      memcpy(newBuffer, _items, _pos * sizeof(T));\n    delete []_items;\n    _items = newBuffer;\n    _size = newCap;\n  }\n\npublic:\n  CDynamicBuffer(): _items(NULL), _size(0), _pos(0) {}\n  // operator T *() { return _items; }\n  operator const T *() const { return _items; }\n  ~CDynamicBuffer() { delete []_items; }\n\n  void Free()\n  {\n    delete []_items;\n    _items = NULL;\n    _size = 0;\n    _pos = 0;\n  }\n\n  T *GetCurPtrAndGrow(size_t addSize)\n  {\n    size_t rem = _size - _pos;\n    if (rem < addSize)\n      Grow(addSize - rem);\n    T *res = _items + _pos;\n    _pos += addSize;\n    return res;\n  }\n\n  void AddData(const T *data, size_t size)\n  {\n    memcpy(GetCurPtrAndGrow(size), data, size * sizeof(T));\n  }\n\n  size_t GetPos() const { return _pos; }\n\n  // void Empty() { _pos = 0; }\n};\n\ntypedef CDynamicBuffer<Byte> CByteDynamicBuffer;\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/IntToString.cpp",
    "content": "﻿// Common/IntToString.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/CpuArch.h\"\n\n#include \"IntToString.h\"\n\n#define CONVERT_INT_TO_STR(charType, tempSize) \\\n  if (val < 10) \\\n    *s++ = (charType)('0' + (unsigned)val); \\\n  else { \\\n    Byte temp[tempSize]; \\\n    size_t i = 0; \\\n    do { \\\n      temp[++i] = (Byte)('0' + (unsigned)(val % 10)); \\\n      val /= 10; } \\\n    while (val >= 10); \\\n    *s++ = (charType)('0' + (unsigned)val); \\\n    do { *s++ = (charType)temp[i]; } \\\n    while (--i); \\\n  } \\\n  *s = 0; \\\n  return s;\n\nchar * ConvertUInt32ToString(UInt32 val, char *s) throw()\n{\n  CONVERT_INT_TO_STR(char, 16)\n}\n\nchar * ConvertUInt64ToString(UInt64 val, char *s) throw()\n{\n  if (val <= (UInt32)0xFFFFFFFF)\n    return ConvertUInt32ToString((UInt32)val, s);\n  CONVERT_INT_TO_STR(char, 24)\n}\n\nwchar_t * ConvertUInt32ToString(UInt32 val, wchar_t *s) throw()\n{\n  CONVERT_INT_TO_STR(wchar_t, 16)\n}\n\nwchar_t * ConvertUInt64ToString(UInt64 val, wchar_t *s) throw()\n{\n  if (val <= (UInt32)0xFFFFFFFF)\n    return ConvertUInt32ToString((UInt32)val, s);\n  CONVERT_INT_TO_STR(wchar_t, 24)\n}\n\nvoid ConvertInt64ToString(Int64 val, char *s) throw()\n{\n  if (val < 0)\n  {\n    *s++ = '-';\n    val = -val;\n  }\n  ConvertUInt64ToString((UInt64)val, s);\n}\n\nvoid ConvertInt64ToString(Int64 val, wchar_t *s) throw()\n{\n  if (val < 0)\n  {\n    *s++ = L'-';\n    val = -val;\n  }\n  ConvertUInt64ToString((UInt64)val, s);\n}\n\n\nvoid ConvertUInt64ToOct(UInt64 val, char *s) throw()\n{\n  {\n    UInt64 v = val;\n    do\n      s++;\n    while (v >>= 3);\n  }\n  *s = 0;\n  do\n  {\n    const unsigned t = (unsigned)val & 7;\n    *--s = (char)('0' + t);\n  }\n  while (val >>= 3);\n}\n\nMY_ALIGN(16) const char k_Hex_Upper[16] =\n { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };\nMY_ALIGN(16) const char k_Hex_Lower[16] =\n { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };\n\nvoid ConvertUInt32ToHex(UInt32 val, char *s) throw()\n{\n  {\n    UInt32 v = val;\n    do\n      s++;\n    while (v >>= 4);\n  }\n  *s = 0;\n  do\n  {\n    const unsigned t = (unsigned)val & 0xF;\n    *--s = GET_HEX_CHAR_UPPER(t);\n  }\n  while (val >>= 4);\n}\n\nvoid ConvertUInt64ToHex(UInt64 val, char *s) throw()\n{\n  {\n    UInt64 v = val;\n    do\n      s++;\n    while (v >>= 4);\n  }\n  *s = 0;\n  do\n  {\n    const unsigned t = (unsigned)val & 0xF;\n    *--s = GET_HEX_CHAR_UPPER(t);\n  }\n  while (val >>= 4);\n}\n\nvoid ConvertUInt32ToHex8Digits(UInt32 val, char *s) throw()\n{\n  s[8] = 0;\n  int i = 7;\n  do\n  {\n    { const unsigned t = (unsigned)val & 0xF;       s[i--] = GET_HEX_CHAR_UPPER(t); }\n    { const unsigned t = (Byte)val >> 4; val >>= 8; s[i--] = GET_HEX_CHAR_UPPER(t); }\n  }\n  while (i >= 0);\n}\n\n/*\nvoid ConvertUInt32ToHex8Digits(UInt32 val, wchar_t *s)\n{\n  s[8] = 0;\n  for (int i = 7; i >= 0; i--)\n  {\n    const unsigned t = (unsigned)val & 0xF;\n    val >>= 4;\n    s[i] = GET_HEX_CHAR(t);\n  }\n}\n*/\n\n\nMY_ALIGN(16) static const Byte k_Guid_Pos[] =\n  { 6,4,2,0, 11,9, 16,14, 19,21, 24,26,28,30,32,34 };\n\nchar *RawLeGuidToString(const Byte *g, char *s) throw()\n{\n  s[ 8] = '-';\n  s[13] = '-';\n  s[18] = '-';\n  s[23] = '-';\n  s[36] = 0;\n  for (unsigned i = 0; i < 16; i++)\n  {\n    char *s2 = s + k_Guid_Pos[i];\n    const unsigned v = g[i];\n    s2[0] = GET_HEX_CHAR_UPPER(v >> 4);\n    s2[1] = GET_HEX_CHAR_UPPER(v & 0xF);\n  }\n  return s + 36;\n}\n\nchar *RawLeGuidToString_Braced(const Byte *g, char *s) throw()\n{\n  *s++ = '{';\n  s = RawLeGuidToString(g, s);\n  *s++ = '}';\n  *s = 0;\n  return s;\n}\n\n\nvoid ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw()\n{\n  if (size)\n  {\n    const Byte *lim = src + size;\n    do\n    {\n      const unsigned b = *src++;\n      dest[0] = GET_HEX_CHAR_LOWER(b >> 4);\n      dest[1] = GET_HEX_CHAR_LOWER(b & 0xF);\n      dest += 2;\n    }\n    while (src != lim);\n  }\n  *dest = 0;\n}\n\nvoid ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw()\n{\n  if (size)\n  {\n    const Byte *lim = src + size;\n    do\n    {\n      const unsigned b = *src++;\n      dest[0] = GET_HEX_CHAR_UPPER(b >> 4);\n      dest[1] = GET_HEX_CHAR_UPPER(b & 0xF);\n      dest += 2;\n    }\n    while (src != lim);\n  }\n  *dest = 0;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/IntToString.h",
    "content": "﻿// Common/IntToString.h\n\n#ifndef ZIP7_INC_COMMON_INT_TO_STRING_H\n#define ZIP7_INC_COMMON_INT_TO_STRING_H\n\n#include \"MyTypes.h\"\n\n// return: the pointer to the \"terminating\" null character after written characters\n\nchar * ConvertUInt32ToString(UInt32 value, char *s) throw();\nchar * ConvertUInt64ToString(UInt64 value, char *s) throw();\n\nwchar_t * ConvertUInt32ToString(UInt32 value, wchar_t *s) throw();\nwchar_t * ConvertUInt64ToString(UInt64 value, wchar_t *s) throw();\nvoid ConvertInt64ToString(Int64 value, char *s) throw();\nvoid ConvertInt64ToString(Int64 value, wchar_t *s) throw();\n\nvoid ConvertUInt64ToOct(UInt64 value, char *s) throw();\n\nextern const char k_Hex_Upper[16];\nextern const char k_Hex_Lower[16];\n\n#define GET_HEX_CHAR_UPPER(t)  (k_Hex_Upper[t])\n#define GET_HEX_CHAR_LOWER(t)  (k_Hex_Lower[t])\n/*\n// #define GET_HEX_CHAR_UPPER(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10)))))\nstatic inline unsigned GetHex_Lower(unsigned v)\n{\n  const unsigned v0 = v + '0';\n  v += 'a' - 10;\n  if (v < 'a')\n    v = v0;\n  return v;\n}\nstatic inline char GetHex_Upper(unsigned v)\n{\n  return (char)((v < 10) ? ('0' + v) : ('A' + (v - 10)));\n}\n*/\n\n\nvoid ConvertUInt32ToHex(UInt32 value, char *s) throw();\nvoid ConvertUInt64ToHex(UInt64 value, char *s) throw();\nvoid ConvertUInt32ToHex8Digits(UInt32 value, char *s) throw();\n// void ConvertUInt32ToHex8Digits(UInt32 value, wchar_t *s) throw();\n\n// use RawLeGuid only for RAW bytes that contain stored GUID as Little-endian.\nchar *RawLeGuidToString(const Byte *guid, char *s) throw();\nchar *RawLeGuidToString_Braced(const Byte *guid, char *s) throw();\n\nvoid ConvertDataToHex_Lower(char *dest, const Byte *src, size_t size) throw();\nvoid ConvertDataToHex_Upper(char *dest, const Byte *src, size_t size) throw();\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/Lang.cpp",
    "content": "﻿// Common/Lang.cpp\n\n#include \"StdAfx.h\"\n\n#include \"Lang.h\"\n#include \"StringToInt.h\"\n#include \"UTFConvert.h\"\n\n#include \"../Windows/FileIO.h\"\n\n// **************** NanaZip Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n\nvoid CLang::Clear() throw()\n{\n  _ids.Clear();\n  _offsets.Clear();\n  Comments.Clear();\n  delete []_text;\n  _text = NULL;\n}\n\nstatic const char * const kLangSignature = \";!@Lang2@!UTF-8!\\n\";\n\nbool CLang::OpenFromString(const AString &s2)\n{\n  UString su;\n  if (!ConvertUTF8ToUnicode(s2, su))\n    return false;\n  if (su.IsEmpty())\n    return false;\n  const wchar_t *s = su;\n  const wchar_t *sLim = s + su.Len();\n  if (*s == 0xFEFF)\n    s++;\n  for (const char *p = kLangSignature;; s++)\n  {\n    const Byte c = (Byte)(*p++);\n    if (c == 0)\n      break;\n    if (*s != c)\n      return false;\n  }\n\n  wchar_t *text = new wchar_t[(size_t)(sLim - s) + 1];\n  _text = text;\n\n  UString comment;\n  Int32 id = -1024;\n  unsigned pos = 0;\n\n  while (s != sLim)\n  {\n    const unsigned start = pos;\n    do\n    {\n      wchar_t c = *s++;\n      if (c == '\\n')\n        break;\n      if (c == '\\\\')\n      {\n        if (s == sLim)\n          return false;\n        c = *s++;\n        switch (c)\n        {\n          case '\\n': return false;\n          case 'n': c = '\\n'; break;\n          case 't': c = '\\t'; break;\n          case '\\\\': /* c = '\\\\'; */ break;\n          default: text[pos++] = L'\\\\'; break;\n        }\n      }\n      text[pos++] = c;\n    }\n    while (s != sLim);\n\n    {\n      unsigned j = start;\n      for (; j < pos; j++)\n        if (text[j] != ' ' && text[j] != '\\t')\n          break;\n      if (j == pos)\n      {\n        id++;\n        pos = start;\n        continue;\n      }\n    }\n\n    // start != pos\n    text[pos++] = 0;\n\n    if (text[start] == ';')\n    {\n      comment = text + start;\n      comment.TrimRight();\n      if (comment.Len() != 1)\n        Comments.Add(comment);\n      id++;\n      pos = start;\n      continue;\n    }\n\n    const wchar_t *end;\n    const UInt32 id32 = ConvertStringToUInt32(text + start, &end);\n    if (*end == 0)\n    {\n      if (id32 > ((UInt32)1 << 30) || (Int32)id32 < id)\n        return false;\n      id = (Int32)id32;\n      pos = start;\n      continue;\n    }\n\n    if (id < 0)\n      return false;\n    _ids.Add((UInt32)id++);\n    _offsets.Add(start);\n  }\n\n  return true;\n}\n\nbool CLang::Open(CFSTR fileName, const char *id)\n{\n  Clear();\n  NWindows::NFile::NIO::CInFile file;\n  if (!file.Open(fileName))\n    return false;\n  UInt64 length;\n  if (!file.GetLength(length))\n    return false;\n  if (length > (1 << 20))\n    return false;\n  \n  AString s;\n  const unsigned len = (unsigned)length;\n  char *p = s.GetBuf(len);\n  size_t processed;\n  if (!file.ReadFull(p, len, processed))\n    return false;\n  file.Close();\n  if (len != processed)\n    return false;\n\n  char *p2 = p;\n  for (unsigned i = 0; i < len; i++)\n  {\n    const char c = p[i];\n    if (c == 0)\n      break;\n    if (c != 0x0D)\n      *p2++ = c;\n  }\n  *p2 = 0;\n  s.ReleaseBuf_SetLen((unsigned)(p2 - p));\n  \n  if (OpenFromString(s))\n  {\n    const wchar_t *name = Get(0);\n    if (name && StringsAreEqual_Ascii(name, id))\n      return true;\n  }\n  \n  Clear();\n  return false;\n}\n\nconst wchar_t *CLang::Get(UInt32 id) const throw()\n{\n  const int index = _ids.FindInSorted(id);\n  if (index < 0)\n    return NULL;\n  return _text + (size_t)_offsets[(unsigned)index];\n}\n\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n\n#ifdef Z7_SFX\n#include \"../Windows/ResourceString.h\"\n\n#include <mutex>\n#include <map>\nstd::mutex g_LanguageLock;\nstd::map<UInt32, UString> g_LanguageMap;\n#else\n#include <NanaZip.Modern.h>\n#endif\n\nvoid CLang::Clear() throw()\n{\n\n}\n\nbool CLang::OpenFromString(const AString& s2)\n{\n    UNREFERENCED_PARAMETER(s2);\n    return true;\n}\n\nbool CLang::Open(CFSTR fileName, const char* id)\n{\n    UNREFERENCED_PARAMETER(fileName);\n    UNREFERENCED_PARAMETER(id);\n    return true;\n}\n\nconst wchar_t* CLang::Get(UInt32 id) const throw()\n{\n#ifdef Z7_SFX\n    std::lock_guard Lock(g_LanguageLock);\n    auto Iterator = g_LanguageMap.find(id);\n    if (g_LanguageMap.end() == Iterator)\n    {\n        return g_LanguageMap.emplace(\n            id,\n            NWindows::MyLoadString(id)).first->second;\n    }\n    return Iterator->second;\n#else\n    return nullptr;\n#endif\n}\n\n// **************** NanaZip Modification End ****************\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/Lang.h",
    "content": "﻿// Common/Lang.h\n\n#ifndef ZIP7_INC_COMMON_LANG_H\n#define ZIP7_INC_COMMON_LANG_H\n\n#include \"MyString.h\"\n\nclass CLang\n{\n  wchar_t *_text;\n\n  bool OpenFromString(const AString &s);\npublic:\n  CRecordVector<UInt32> _ids;\n  CRecordVector<UInt32> _offsets;\n  UStringVector Comments;\n\n  CLang(): _text(NULL) {}\n  ~CLang() { Clear(); }\n  bool Open(CFSTR fileName, const char *id);\n  void Clear() throw();\n  bool IsEmpty() const { return _ids.IsEmpty(); }\n  const wchar_t *Get(UInt32 id) const throw();\n  const wchar_t *Get_by_index(unsigned index) const throw()\n  {\n    return _text + (size_t)_offsets[index];\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/ListFileUtils.cpp",
    "content": "﻿// Common/ListFileUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/CpuArch.h\"\n\n#include \"ListFileUtils.h\"\n#include \"MyBuffer.h\"\n#include \"StringConvert.h\"\n#include \"UTFConvert.h\"\n\n#include \"../Windows/FileIO.h\"\n\n#define CSysInFile NWindows::NFile::NIO::CInFile\n#define MY_GET_LAST_ERROR ::GetLastError()\n\n\n#define kQuoteChar '\\\"'\n\n\nstatic void AddName(UStringVector &strings, UString &s)\n{\n  s.Trim();\n  if (s.Len() >= 2 && s[0] == kQuoteChar && s.Back() == kQuoteChar)\n  {\n    s.DeleteBack();\n    s.Delete(0);\n  }\n  if (!s.IsEmpty())\n    strings.Add(s);\n}\n\n\nstatic bool My_File_Read(CSysInFile &file, void *data, size_t size, DWORD &lastError)\n{\n  size_t processed;\n  if (!file.ReadFull(data, size, processed))\n  {\n    lastError = MY_GET_LAST_ERROR;\n    return false;\n  }\n  if (processed != size)\n  {\n    lastError = 1; // error: size of listfile was changed\n    return false;\n  }\n  return true;\n}\n\n\nbool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage, DWORD &lastError)\n{\n  lastError = 0;\n  CSysInFile file;\n  if (!file.Open(fileName))\n  {\n    lastError = MY_GET_LAST_ERROR;\n    return false;\n  }\n  UInt64 fileSize;\n  if (!file.GetLength(fileSize))\n  {\n    lastError = MY_GET_LAST_ERROR;\n    return false;\n  }\n  if (fileSize >= ((UInt32)1 << 31) - 32)\n    return false;\n  UString u;\n  if (codePage == Z7_WIN_CP_UTF16 || codePage == Z7_WIN_CP_UTF16BE)\n  {\n    if ((fileSize & 1) != 0)\n      return false;\n    CByteArr buf((size_t)fileSize);\n\n    if (!My_File_Read(file, buf, (size_t)fileSize, lastError))\n      return false;\n\n    file.Close();\n    const size_t num = (size_t)fileSize / 2;\n    wchar_t *p = u.GetBuf((unsigned)num);\n    if (codePage == Z7_WIN_CP_UTF16)\n      for (size_t i = 0; i < num; i++)\n      {\n        const wchar_t c = GetUi16(buf.ConstData() + (size_t)i * 2);\n        if (c == 0)\n          return false;\n        p[i] = c;\n      }\n    else\n      for (size_t i = 0; i < num; i++)\n      {\n        const wchar_t c = (wchar_t)GetBe16(buf.ConstData() + (size_t)i * 2);\n        if (c == 0)\n          return false;\n        p[i] = c;\n      }\n    p[num] = 0;\n    u.ReleaseBuf_SetLen((unsigned)num);\n  }\n  else\n  {\n    AString s;\n    char *p = s.GetBuf((unsigned)fileSize);\n\n    if (!My_File_Read(file, p, (size_t)fileSize, lastError))\n      return false;\n\n    file.Close();\n    s.ReleaseBuf_CalcLen((unsigned)fileSize);\n    if (s.Len() != fileSize)\n      return false;\n    \n    // #ifdef CP_UTF8\n    if (codePage == CP_UTF8)\n    {\n      // we must check UTF8 here, if convert function doesn't check\n      if (!CheckUTF8_AString(s))\n        return false;\n      if (!ConvertUTF8ToUnicode(s, u))\n        return false;\n    }\n    else\n    // #endif\n      MultiByteToUnicodeString2(u, s, codePage);\n  }\n\n  const wchar_t kGoodBOM = 0xFEFF;\n  // const wchar_t kBadBOM  = 0xFFFE;\n  \n  UString s;\n  unsigned i = 0;\n  for (; i < u.Len() && u[i] == kGoodBOM; i++);\n  for (; i < u.Len(); i++)\n  {\n    wchar_t c = u[i];\n    /*\n    if (c == kGoodBOM || c == kBadBOM)\n      return false;\n    */\n    if (c == '\\n' || c == 0xD)\n    {\n      AddName(strings, s);\n      s.Empty();\n    }\n    else\n      s += c;\n  }\n  AddName(strings, s);\n  return true;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/ListFileUtils.h",
    "content": "﻿// Common/ListFileUtils.h\n\n#ifndef ZIP7_INC_COMMON_LIST_FILE_UTILS_H\n#define ZIP7_INC_COMMON_LIST_FILE_UTILS_H\n\n#include \"MyString.h\"\n#include \"MyTypes.h\"\n\n#define Z7_WIN_CP_UTF16   1200\n#define Z7_WIN_CP_UTF16BE 1201\n\n// bool ReadNamesFromListFile(CFSTR fileName, UStringVector &strings, UINT codePage = CP_OEMCP);\n\n // = CP_OEMCP\nbool ReadNamesFromListFile2(CFSTR fileName, UStringVector &strings, UINT codePage,\n    DWORD &lastError);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/LzFindPrepare.cpp",
    "content": "﻿// Sha256Prepare.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/LzFind.h\"\n\nstatic struct CLzFindPrepare { CLzFindPrepare() { LzFindPrepare(); } } g_CLzFindPrepare;\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyBuffer.h",
    "content": "﻿// Common/MyBuffer.h\n\n#ifndef ZIP7_INC_COMMON_MY_BUFFER_H\n#define ZIP7_INC_COMMON_MY_BUFFER_H\n\n#include <string.h>\n\n#include \"Defs.h\"\n#include \"MyTypes.h\"\n\n/* 7-Zip now uses CBuffer only as CByteBuffer.\n   So there is no need to use Z7_ARRAY_NEW macro in CBuffer code. */\n\ntemplate <class T> class CBuffer\n{\n  T *_items;\n  size_t _size;\n\npublic:\n  void Free()\n  {\n    if (_items)\n    {\n      delete []_items;\n      _items = NULL;\n    }\n    _size = 0;\n  }\n  \n  CBuffer(): _items(NULL), _size(0) {}\n  CBuffer(size_t size): _items(NULL), _size(0)\n  {\n    if (size != 0)\n    {\n      _items = new T[size];\n      _size = size;\n    }\n  }\n  CBuffer(const CBuffer &buffer): _items(NULL), _size(0)\n  {\n    const size_t size = buffer._size;\n    if (size != 0)\n    {\n      _items = new T[size];\n      memcpy(_items, buffer._items, size * sizeof(T));\n      _size = size;\n    }\n  }\n\n  ~CBuffer() { delete []_items; }\n\n  operator       T *()       { return _items; }\n  operator const T *() const { return _items; }\n  const T* ConstData()    const { return _items; }\n        T* NonConstData() const { return _items; }\n        T* NonConstData()       { return _items; }\n  // const T* Data() const         { return _items; }\n  //       T* Data()               { return _items; }\n\n  size_t Size() const { return _size; }\n\n  void Alloc(size_t size)\n  {\n    if (size != _size)\n    {\n      Free();\n      if (size != 0)\n      {\n        _items = new T[size];\n        _size = size;\n      }\n    }\n  }\n\n  void AllocAtLeast(size_t size)\n  {\n    if (size > _size)\n    {\n      Free();\n      _items = new T[size];\n      _size = size;\n    }\n  }\n\n  void CopyFrom(const T *data, size_t size)\n  {\n    Alloc(size);\n    if (size != 0)\n      memcpy(_items, data, size * sizeof(T));\n  }\n\n  void ChangeSize_KeepData(size_t newSize, size_t keepSize)\n  {\n    if (newSize == _size)\n      return;\n    T *newBuffer = NULL;\n    if (newSize != 0)\n    {\n      newBuffer = new T[newSize];\n      if (keepSize > _size)\n        keepSize = _size;\n      if (keepSize != 0)\n        memcpy(newBuffer, _items, MyMin(keepSize, newSize) * sizeof(T));\n    }\n    delete []_items;\n    _items = newBuffer;\n    _size = newSize;\n  }\n\n  void Wipe()\n  {\n    if (_size != 0)\n      memset(_items, 0, _size * sizeof(T));\n  }\n\n  CBuffer& operator=(const CBuffer &buffer)\n  {\n    if (&buffer != this)\n      CopyFrom(buffer, buffer._size);\n    return *this;\n  }\n};\n\ntemplate <class T>\nbool operator==(const CBuffer<T>& b1, const CBuffer<T>& b2)\n{\n  size_t size1 = b1.Size();\n  if (size1 != b2.Size())\n    return false;\n  if (size1 == 0)\n    return true;\n  return memcmp(b1, b2, size1 * sizeof(T)) == 0;\n}\n\ntemplate <class T>\nbool operator!=(const CBuffer<T>& b1, const CBuffer<T>& b2)\n{\n  size_t size1 = b1.Size();\n  if (size1 != b2.Size())\n    return true;\n  if (size1 == 0)\n    return false;\n  return memcmp(b1, b2, size1 * sizeof(T)) != 0;\n}\n\n\n// typedef CBuffer<char> CCharBuffer;\n// typedef CBuffer<wchar_t> CWCharBuffer;\ntypedef CBuffer<Byte> CByteBuffer;\n\n\nclass CByteBuffer_Wipe: public CByteBuffer\n{\n  Z7_CLASS_NO_COPY(CByteBuffer_Wipe)\npublic:\n  // CByteBuffer_Wipe(): CBuffer<Byte>() {}\n  CByteBuffer_Wipe(size_t size): CBuffer<Byte>(size) {}\n  ~CByteBuffer_Wipe() { Wipe(); }\n};\n\n\n\ntemplate <class T> class CObjArray\n{\nprotected:\n  T *_items;\nprivate:\n  // we disable copy\n  CObjArray(const CObjArray &buffer);\n  void operator=(const CObjArray &buffer);\npublic:\n  void Free()\n  {\n    delete []_items;\n    _items = NULL;\n  }\n  CObjArray(size_t size): _items(NULL)\n  {\n    if (size != 0)\n    {\n      Z7_ARRAY_NEW(_items, T, size)\n      // _items = new T[size];\n    }\n  }\n  CObjArray(): _items(NULL) {}\n  ~CObjArray() { delete []_items; }\n  \n  operator       T *()       { return _items; }\n  operator const T *() const { return _items; }\n  const T* ConstData()    const { return _items; }\n        T* NonConstData() const { return _items; }\n        T* NonConstData()       { return _items; }\n  // const T* Data() const         { return _items; }\n  //       T* Data()               { return _items; }\n  \n  void Alloc(size_t newSize)\n  {\n    delete []_items;\n    _items = NULL;\n    Z7_ARRAY_NEW(_items, T, newSize)\n    // _items = new T[newSize];\n  }\n};\n\n\n/* CSmallObjArray can be used for Byte arrays\n   or for arrays whose total size in bytes does not exceed size_t ranges.\n   So there is no need to use Z7_ARRAY_NEW macro in CSmallObjArray code. */\ntemplate <class T> class CSmallObjArray\n{\nprotected:\n  T *_items;\nprivate:\n  // we disable copy\n  CSmallObjArray(const CSmallObjArray &buffer);\n  void operator=(const CSmallObjArray &buffer);\npublic:\n  void Free()\n  {\n    delete []_items;\n    _items = NULL;\n  }\n  CSmallObjArray(size_t size): _items(NULL)\n  {\n    if (size != 0)\n    {\n      // Z7_ARRAY_NEW(_items, T, size)\n      _items = new T[size];\n    }\n  }\n  CSmallObjArray(): _items(NULL) {}\n  ~CSmallObjArray() { delete []_items; }\n  \n  operator       T *()       { return _items; }\n  operator const T *() const { return _items; }\n  const T* ConstData()    const { return _items; }\n        T* NonConstData() const { return _items; }\n        T* NonConstData()       { return _items; }\n  // const T* Data() const         { return _items; }\n  //       T* Data()               { return _items; }\n  \n  void Alloc(size_t newSize)\n  {\n    delete []_items;\n    _items = NULL;\n    // Z7_ARRAY_NEW(_items, T, newSize)\n    _items = new T[newSize];\n  }\n};\n\ntypedef CSmallObjArray<Byte> CByteArr;\ntypedef CObjArray<bool> CBoolArr;\ntypedef CObjArray<int> CIntArr;\ntypedef CObjArray<unsigned> CUIntArr;\n\n\ntemplate <class T> class CObjArray2\n{\n  T *_items;\n  unsigned _size;\n\n  // we disable copy\n  CObjArray2(const CObjArray2 &buffer);\n  void operator=(const CObjArray2 &buffer);\npublic:\n  \n  void Free()\n  {\n    delete []_items;\n    _items = NULL;\n    _size = 0;\n  }\n  CObjArray2(): _items(NULL), _size(0) {}\n  /*\n  CObjArray2(const CObjArray2 &buffer): _items(NULL), _size(0)\n  {\n    size_t newSize = buffer._size;\n    if (newSize != 0)\n    {\n      T *newBuffer = new T[newSize];;\n      _items = newBuffer;\n      _size = newSize;\n      const T *src = buffer;\n      for (size_t i = 0; i < newSize; i++)\n        newBuffer[i] = src[i];\n    }\n  }\n  */\n  /*\n  CObjArray2(size_t size): _items(NULL), _size(0)\n  {\n    if (size != 0)\n    {\n      _items = new T[size];\n      _size = size;\n    }\n  }\n  */\n\n  ~CObjArray2() { delete []_items; }\n  \n  operator       T *()       { return _items; }\n  operator const T *() const { return _items; }\n  \n  unsigned Size() const { return (unsigned)_size; }\n  bool IsEmpty() const { return _size == 0; }\n\n  // SetSize doesn't keep old items. It allocates new array if size is not equal\n  void SetSize(unsigned size)\n  {\n    if (size == _size)\n      return;\n    T *newBuffer = NULL;\n    if (size != 0)\n    {\n      Z7_ARRAY_NEW(newBuffer, T, size)\n      // newBuffer = new T[size];\n    }\n    delete []_items;\n    _items = newBuffer;\n    _size = size;\n  }\n\n  /*\n  CObjArray2& operator=(const CObjArray2 &buffer)\n  {\n    Free();\n    size_t newSize = buffer._size;\n    if (newSize != 0)\n    {\n      T *newBuffer = new T[newSize];;\n      _items = newBuffer;\n      _size = newSize;\n      const T *src = buffer;\n      for (size_t i = 0; i < newSize; i++)\n        newBuffer[i] = src[i];\n    }\n    return *this;\n  }\n  */\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyBuffer2.h",
    "content": "﻿// Common/MyBuffer2.h\n\n#ifndef ZIP7_INC_COMMON_MY_BUFFER2_H\n#define ZIP7_INC_COMMON_MY_BUFFER2_H\n\n#include \"../../C/Alloc.h\"\n\n#include \"MyTypes.h\"\n\nclass CMidBuffer\n{\n  Byte *_data;\n  size_t _size;\n\n  Z7_CLASS_NO_COPY(CMidBuffer)\n\npublic:\n  CMidBuffer(): _data(NULL), _size(0) {}\n  ~CMidBuffer() { ::MidFree(_data); }\n\n  void Free() { ::MidFree(_data); _data = NULL; _size = 0; }\n\n  bool IsAllocated() const { return _data != NULL; }\n  operator       Byte *()       { return _data; }\n  operator const Byte *() const { return _data; }\n  size_t Size() const { return _size; }\n\n  void Alloc(size_t size)\n  {\n    if (!_data || size != _size)\n    {\n      ::MidFree(_data);\n      _size = 0;\n      _data = NULL;\n      _data = (Byte *)::MidAlloc(size);\n      if (_data)\n        _size = size;\n    }\n  }\n\n  void AllocAtLeast(size_t size)\n  {\n    if (!_data || size > _size)\n    {\n      ::MidFree(_data);\n      const size_t kMinSize = (size_t)1 << 16;\n      if (size < kMinSize)\n        size = kMinSize;\n      _size = 0;\n      _data = NULL;\n      _data = (Byte *)::MidAlloc(size);\n      if (_data)\n        _size = size;\n    }\n  }\n};\n\n\nclass CAlignedBuffer1\n{\n  Byte *_data;\n\n  Z7_CLASS_NO_COPY(CAlignedBuffer1)\n\npublic:\n  ~CAlignedBuffer1()\n  {\n    z7_AlignedFree(_data);\n  }\n\n  CAlignedBuffer1(size_t size)\n  {\n    _data = NULL;\n    _data = (Byte *)z7_AlignedAlloc(size);\n    if (!_data)\n      throw 1;\n  }\n\n  operator       Byte *()       { return _data; }\n  operator const Byte *() const { return _data; }\n};\n\n\nclass CAlignedBuffer\n{\n  Byte *_data;\n  size_t _size;\n\n  Z7_CLASS_NO_COPY(CAlignedBuffer)\n\npublic:\n  CAlignedBuffer(): _data(NULL), _size(0) {}\n  ~CAlignedBuffer()\n  {\n    z7_AlignedFree(_data);\n  }\n\n  /*\n  CAlignedBuffer(size_t size): _size(0)\n  {\n    _data = NULL;\n    _data = (Byte *)z7_AlignedAlloc(size);\n    if (!_data)\n      throw 1;\n    _size = size;\n  }\n  */\n\n  void Free()\n  {\n    z7_AlignedFree(_data);\n    _data = NULL;\n    _size = 0;\n  }\n\n  bool IsAllocated() const { return _data != NULL; }\n  operator       Byte *()       { return _data; }\n  operator const Byte *() const { return _data; }\n  size_t Size() const { return _size; }\n\n  void Alloc(size_t size)\n  {\n    if (!_data || size != _size)\n    {\n      z7_AlignedFree(_data);\n      _size = 0;\n      _data = NULL;\n      _data = (Byte *)z7_AlignedAlloc(size);\n      if (_data)\n        _size = size;\n    }\n  }\n\n  void AllocAtLeast(size_t size)\n  {\n    if (!_data || size > _size)\n    {\n      z7_AlignedFree(_data);\n      _size = 0;\n      _data = NULL;\n      _data = (Byte *)z7_AlignedAlloc(size);\n      if (_data)\n        _size = size;\n    }\n  }\n\n  // (size <= size_max)\n  void AllocAtLeast_max(size_t size, size_t size_max)\n  {\n    if (!_data || size > _size)\n    {\n      z7_AlignedFree(_data);\n      _size = 0;\n      _data = NULL;\n      if (size_max < size) size_max = size; // optional check\n      const size_t delta = size / 2;\n      size += delta;\n      if (size < delta || size > size_max)\n        size = size_max;\n      _data = (Byte *)z7_AlignedAlloc(size);\n      if (_data)\n        _size = size;\n    }\n  }\n};\n\n/*\n  CMidAlignedBuffer must return aligned pointer.\n   - in Windows it uses CMidBuffer(): MidAlloc() : VirtualAlloc()\n       VirtualAlloc(): Memory allocated is automatically initialized to zero.\n       MidAlloc(0) returns NULL\n   - in non-Windows systems it uses g_AlignedAlloc.\n     g_AlignedAlloc::Alloc(size = 0) can return non NULL.\n*/\n\ntypedef\n#ifdef _WIN32\n  CMidBuffer\n#else\n  CAlignedBuffer\n#endif\n  CMidAlignedBuffer;\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyCom.h",
    "content": "﻿// MyCom.h\n\n#ifndef ZIP7_INC_MY_COM_H\n#define ZIP7_INC_MY_COM_H\n\n#include \"MyWindows.h\"\n#include \"MyTypes.h\"\n\ntemplate <class T>\nclass CMyComPtr\n{\n  T* _p;\npublic:\n  CMyComPtr(): _p(NULL) {}\n  CMyComPtr(T* p) throw() { if ((_p = p) != NULL) p->AddRef(); }\n  CMyComPtr(const CMyComPtr<T>& lp) throw() { if ((_p = lp._p) != NULL) _p->AddRef(); }\n  ~CMyComPtr() { if (_p) _p->Release(); }\n  void Release() { if (_p) { _p->Release(); _p = NULL; } }\n  operator T*() const {  return (T*)_p;  }\n  T* Interface() const {  return (T*)_p;  }\n  // T& operator*() const {  return *_p; }\n  T** operator&() { return &_p; }\n  T* operator->() const { return _p; }\n  T* operator=(T* p)\n  {\n    if (p)\n      p->AddRef();\n    if (_p)\n      _p->Release();\n    _p = p;\n    return p;\n  }\n  T* operator=(const CMyComPtr<T>& lp) { return (*this = lp._p); }\n  bool operator!() const { return (_p == NULL); }\n  // bool operator==(T* pT) const {  return _p == pT; }\n  void Attach(T* p2)\n  {\n    Release();\n    _p = p2;\n  }\n  T* Detach()\n  {\n    T* pt = _p;\n    _p = NULL;\n    return pt;\n  }\n  #ifdef _WIN32\n  HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)\n  {\n    return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p);\n  }\n  #endif\n  /*\n  HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)\n  {\n    CLSID clsid;\n    HRESULT hr = CLSIDFromProgID(szProgID, &clsid);\n    ATLASSERT(_p == NULL);\n    if (SUCCEEDED(hr))\n      hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p);\n    return hr;\n  }\n  */\n  template <class Q>\n  HRESULT QueryInterface(REFGUID iid, Q** pp) const throw()\n  {\n    // if (*pp) throw 20220216; // for debug\n    return _p->QueryInterface(iid, (void**)pp);\n  }\n};\n\n\ntemplate <class iface, class cls>\nclass CMyComPtr2\n{\n  cls* _p;\n  \n  CMyComPtr2(const CMyComPtr2<iface, cls>& lp);\n  CMyComPtr2(cls* p);\n  CMyComPtr2(iface* p);\n  iface* operator=(const CMyComPtr2<iface, cls>& lp);\n  iface* operator=(cls* p);\n  iface* operator=(iface* p);\npublic:\n  CMyComPtr2(): _p(NULL) {}\n  ~CMyComPtr2()\n  {\n    if (_p)\n    {\n      iface *ip = _p;\n      ip->Release();\n    }\n  }\n  // void Release() { if (_p) { (iface *)_p->Release(); _p = NULL; } }\n  cls* operator->() const { return _p; }\n  cls* ClsPtr() const { return _p; }\n  operator iface*() const\n  {\n    iface *ip = _p;\n    return ip;\n  }\n  iface* Interface() const\n  {\n    iface *ip = _p;\n    return ip;\n  }\n  // operator bool() const {  return _p != NULL; }\n  bool IsDefined() const {  return _p != NULL; }\n  void Create_if_Empty()\n  {\n    if (!_p)\n    {\n      _p = new cls;\n      iface *ip = _p;\n      ip->AddRef();\n    }\n  }\n  iface* Detach()\n  {\n    iface *ip = _p;\n    _p = NULL;\n    return ip;\n  }\n  void SetFromCls(cls *src)\n  {\n    if (src)\n    {\n      iface *ip = src;\n      ip->AddRef();\n    }\n    if (_p)\n    {\n      iface *ip = _p;\n      ip->Release();\n    }\n    _p = src;\n  }\n};\n\n\ntemplate <class iface, class cls>\nclass CMyComPtr2_Create\n{\n  cls* _p;\n\n  CMyComPtr2_Create(const CMyComPtr2_Create<iface, cls>& lp);\n  CMyComPtr2_Create(cls* p);\n  CMyComPtr2_Create(iface* p);\n  iface* operator=(const CMyComPtr2_Create<iface, cls>& lp);\n  iface* operator=(cls* p);\n  iface* operator=(iface* p);\npublic:\n  CMyComPtr2_Create(): _p(new cls)\n  {\n    iface *ip = _p;\n    ip->AddRef();\n  }\n  ~CMyComPtr2_Create()\n  {\n    iface *ip = _p;\n    ip->Release();\n  }\n  cls* operator->() const { return _p; }\n  cls* ClsPtr() const { return _p; }\n  operator iface*() const\n  {\n    iface *ip = _p;\n    return ip;\n  }\n  iface* Interface() const\n  {\n    iface *ip = _p;\n    return ip;\n  }\n};\n\n\n#define Z7_DECL_CMyComPtr_QI_FROM(i, v, unk) \\\n  CMyComPtr<i> v; (unk)->QueryInterface(IID_ ## i, (void **)&v);\n\n\n//////////////////////////////////////////////////////////\n\ninline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr)\n{\n  *bstr = ::SysAllocString(src);\n  return (*bstr) ? S_OK : E_OUTOFMEMORY;\n}\n\nclass CMyComBSTR\n{\n  BSTR m_str;\n  Z7_CLASS_NO_COPY(CMyComBSTR)\npublic:\n  CMyComBSTR(): m_str(NULL) {}\n  ~CMyComBSTR() { ::SysFreeString(m_str); }\n  BSTR* operator&() { return &m_str; }\n  operator LPCOLESTR() const { return m_str; }\n  // operator bool() const { return m_str != NULL; }\n  // bool operator!() const { return m_str == NULL; }\n\n  void Wipe_and_Free()\n  {\n    if (m_str)\n    {\n      memset(m_str, 0, ::SysStringLen(m_str) * sizeof(*m_str));\n      Empty();\n    }\n  }\n\nprivate:\n  // operator BSTR() const { return m_str; }\n\n  CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); }\n  // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); }\n  // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize);  }\n  // CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); }\n  \n  /*\n  CMyComBSTR(REFGUID src)\n  {\n    LPOLESTR szGuid;\n    StringFromCLSID(src, &szGuid);\n    m_str = ::SysAllocString(szGuid);\n    CoTaskMemFree(szGuid);\n  }\n  */\n  \n  /*\n  CMyComBSTR& operator=(const CMyComBSTR& src)\n  {\n    if (m_str != src.m_str)\n    {\n      if (m_str)\n        ::SysFreeString(m_str);\n      m_str = src.MyCopy();\n    }\n    return *this;\n  }\n  */\n  \n  CMyComBSTR& operator=(LPCOLESTR src)\n  {\n    ::SysFreeString(m_str);\n    m_str = ::SysAllocString(src);\n    return *this;\n  }\n  \n  unsigned Len() const { return ::SysStringLen(m_str); }\n\n  BSTR MyCopy() const\n  {\n    // We don't support Byte BSTRs here\n    return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));\n    /*\n    UINT byteLen = ::SysStringByteLen(m_str);\n    BSTR res = ::SysAllocStringByteLen(NULL, byteLen);\n    if (res && byteLen != 0 && m_str)\n      memcpy(res, m_str, byteLen);\n    return res;\n    */\n  }\n  \n  /*\n  void Attach(BSTR src) { m_str = src; }\n  BSTR Detach()\n  {\n    BSTR s = m_str;\n    m_str = NULL;\n    return s;\n  }\n  */\n\n  void Empty()\n  {\n    ::SysFreeString(m_str);\n    m_str = NULL;\n  }\n};\n\n\nclass CMyComBSTR_Wipe: public CMyComBSTR\n{\n  Z7_CLASS_NO_COPY(CMyComBSTR_Wipe)\npublic:\n  CMyComBSTR_Wipe(): CMyComBSTR() {}\n  ~CMyComBSTR_Wipe() { Wipe_and_Free(); }\n};\n\n\n\n/*\n  If CMyUnknownImp doesn't use virtual destructor, the code size is smaller.\n  But if some class_1 derived from CMyUnknownImp\n    uses Z7_COM_ADDREF_RELEASE and IUnknown::Release()\n    and some another class_2 is derived from class_1,\n    then class_1 must use virtual destructor:\n      virtual ~class_1();\n    In that case, class_1::Release() calls correct destructor of class_2.\n  We can use virtual ~CMyUnknownImp() to disable warning\n    \"class has virtual functions, but destructor is not virtual\".\n  Also we can use virtual ~IUnknown() {} in MyWindows.h\n*/\n\nclass CMyUnknownImp\n{\n  Z7_CLASS_NO_COPY(CMyUnknownImp)\nprotected:\n  ULONG _m_RefCount;\n  CMyUnknownImp(): _m_RefCount(0) {}\n\n  #ifdef _WIN32\n  #if defined(__GNUC__) || defined(__clang__)\n  // virtual ~CMyUnknownImp() {} // to disable GCC/CLANG varnings\n  #endif\n  #endif\n};\n\n\n\n#define Z7_COM_QI_BEGIN \\\n  private: STDMETHOD(QueryInterface) (REFGUID iid, void **outObject) throw() Z7_override Z7_final \\\n    { *outObject = NULL;\n\n#define Z7_COM_QI_ENTRY(i) \\\n  else if (iid == IID_ ## i) \\\n    { i *ti = this;  *outObject = ti; }\n//   { *outObject = (void *)(i *)this; }\n\n#define Z7_COM_QI_ENTRY_UNKNOWN_0 \\\n  if (iid == IID_IUnknown) \\\n    { IUnknown *tu = this;  *outObject = tu; }\n\n#define Z7_COM_QI_ENTRY_UNKNOWN(i) \\\n  if (iid == IID_IUnknown) \\\n    { i *ti = this;  IUnknown *tu = ti;  *outObject = tu; }\n//    { *outObject = (void *)(IUnknown *)(i *)this; }\n\n#define Z7_COM_QI_BEGIN2(i) \\\n  Z7_COM_QI_BEGIN \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i) \\\n  Z7_COM_QI_ENTRY(i)\n\n\n#define Z7_COM_ADDREF_RELEASE_MT \\\n  private: \\\n  STDMETHOD_(ULONG, AddRef)() Z7_override Z7_final \\\n    { return (ULONG)InterlockedIncrement((LONG *)&_m_RefCount); } \\\n  STDMETHOD_(ULONG, Release)() Z7_override Z7_final \\\n    { const LONG v = InterlockedDecrement((LONG *)&_m_RefCount); \\\n      if (v != 0) return (ULONG)v; \\\n      delete this;  return 0; }\n\n#define Z7_COM_QI_END_MT \\\n  else return E_NOINTERFACE; \\\n  InterlockedIncrement((LONG *)&_m_RefCount); /* AddRef(); */ return S_OK; }\n\n// you can define Z7_COM_USE_ATOMIC,\n// if you want to call Release() from different threads (for example, for .NET code)\n// #define Z7_COM_USE_ATOMIC\n\n#if defined(Z7_COM_USE_ATOMIC) && !defined(Z7_ST)\n\n#ifndef _WIN32\n#if 0\n#include \"../../C/Threads.h\"\n#else\nEXTERN_C_BEGIN\nLONG InterlockedIncrement(LONG volatile *addend);\nLONG InterlockedDecrement(LONG volatile *addend);\nEXTERN_C_END\n#endif\n#endif // _WIN32\n\n#define Z7_COM_ADDREF_RELEASE  Z7_COM_ADDREF_RELEASE_MT\n#define Z7_COM_QI_END          Z7_COM_QI_END_MT\n\n#else // !Z7_COM_USE_ATOMIC\n\n#define Z7_COM_ADDREF_RELEASE \\\n  private: \\\n  STDMETHOD_(ULONG, AddRef)() throw() Z7_override Z7_final \\\n    { return ++_m_RefCount; } \\\n  STDMETHOD_(ULONG, Release)() throw() Z7_override Z7_final \\\n    { if (--_m_RefCount != 0) return _m_RefCount; \\\n      delete this;  return 0; }\n\n#define Z7_COM_QI_END \\\n  else return E_NOINTERFACE; \\\n  ++_m_RefCount; /* AddRef(); */ return S_OK; }\n\n#endif // !Z7_COM_USE_ATOMIC\n\n\n#define Z7_COM_UNKNOWN_IMP_SPEC(i) \\\n  Z7_COM_QI_BEGIN \\\n  i \\\n  Z7_COM_QI_END \\\n  Z7_COM_ADDREF_RELEASE\n\n\n#define Z7_COM_UNKNOWN_IMP_0 \\\n  Z7_COM_QI_BEGIN \\\n  Z7_COM_QI_ENTRY_UNKNOWN_0 \\\n  Z7_COM_QI_END \\\n  Z7_COM_ADDREF_RELEASE\n\n#define Z7_COM_UNKNOWN_IMP_1(i) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i) \\\n  Z7_COM_QI_ENTRY(i) \\\n  )\n\n#define Z7_COM_UNKNOWN_IMP_2(i1, i2) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i1) \\\n  Z7_COM_QI_ENTRY(i1) \\\n  Z7_COM_QI_ENTRY(i2) \\\n  )\n\n#define Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i1) \\\n  Z7_COM_QI_ENTRY(i1) \\\n  Z7_COM_QI_ENTRY(i2) \\\n  Z7_COM_QI_ENTRY(i3) \\\n  )\n\n#define Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i1) \\\n  Z7_COM_QI_ENTRY(i1) \\\n  Z7_COM_QI_ENTRY(i2) \\\n  Z7_COM_QI_ENTRY(i3) \\\n  Z7_COM_QI_ENTRY(i4) \\\n  )\n\n#define Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i1) \\\n  Z7_COM_QI_ENTRY(i1) \\\n  Z7_COM_QI_ENTRY(i2) \\\n  Z7_COM_QI_ENTRY(i3) \\\n  Z7_COM_QI_ENTRY(i4) \\\n  Z7_COM_QI_ENTRY(i5) \\\n  )\n\n#define Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i1) \\\n  Z7_COM_QI_ENTRY(i1) \\\n  Z7_COM_QI_ENTRY(i2) \\\n  Z7_COM_QI_ENTRY(i3) \\\n  Z7_COM_QI_ENTRY(i4) \\\n  Z7_COM_QI_ENTRY(i5) \\\n  Z7_COM_QI_ENTRY(i6) \\\n  )\n\n#define Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i1) \\\n  Z7_COM_QI_ENTRY(i1) \\\n  Z7_COM_QI_ENTRY(i2) \\\n  Z7_COM_QI_ENTRY(i3) \\\n  Z7_COM_QI_ENTRY(i4) \\\n  Z7_COM_QI_ENTRY(i5) \\\n  Z7_COM_QI_ENTRY(i6) \\\n  Z7_COM_QI_ENTRY(i7) \\\n  )\n\n#define Z7_COM_UNKNOWN_IMP_8(i1, i2, i3, i4, i5, i6, i7, i8) \\\n  Z7_COM_UNKNOWN_IMP_SPEC( \\\n  Z7_COM_QI_ENTRY_UNKNOWN(i1) \\\n  Z7_COM_QI_ENTRY(i1) \\\n  Z7_COM_QI_ENTRY(i2) \\\n  Z7_COM_QI_ENTRY(i3) \\\n  Z7_COM_QI_ENTRY(i4) \\\n  Z7_COM_QI_ENTRY(i5) \\\n  Z7_COM_QI_ENTRY(i6) \\\n  Z7_COM_QI_ENTRY(i7) \\\n  Z7_COM_QI_ENTRY(i8) \\\n  )\n\n\n#define Z7_IFACES_IMP_UNK_1(i1) \\\n  Z7_COM_UNKNOWN_IMP_1(i1) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n\n#define Z7_IFACES_IMP_UNK_2(i1, i2) \\\n  Z7_COM_UNKNOWN_IMP_2(i1, i2) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n\n#define Z7_IFACES_IMP_UNK_3(i1, i2, i3) \\\n  Z7_COM_UNKNOWN_IMP_3(i1, i2, i3) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n\n#define Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \\\n  Z7_COM_UNKNOWN_IMP_4(i1, i2, i3, i4) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n  Z7_IFACE_COM7_IMP(i4) \\\n\n#define Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \\\n  Z7_COM_UNKNOWN_IMP_5(i1, i2, i3, i4, i5) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n  Z7_IFACE_COM7_IMP(i4) \\\n  Z7_IFACE_COM7_IMP(i5) \\\n\n#define Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \\\n  Z7_COM_UNKNOWN_IMP_6(i1, i2, i3, i4, i5, i6) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n  Z7_IFACE_COM7_IMP(i4) \\\n  Z7_IFACE_COM7_IMP(i5) \\\n  Z7_IFACE_COM7_IMP(i6) \\\n\n#define Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \\\n  Z7_COM_UNKNOWN_IMP_7(i1, i2, i3, i4, i5, i6, i7) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n  Z7_IFACE_COM7_IMP(i4) \\\n  Z7_IFACE_COM7_IMP(i5) \\\n  Z7_IFACE_COM7_IMP(i6) \\\n  Z7_IFACE_COM7_IMP(i7) \\\n\n\n#define Z7_CLASS_IMP_COM_0(c) \\\n  Z7_class_final(c) : \\\n  public IUnknown, \\\n  public CMyUnknownImp { \\\n  Z7_COM_UNKNOWN_IMP_0 \\\n  private:\n\n#define Z7_CLASS_IMP_COM_1(c, i1) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_1(i1) \\\n  private:\n\n#define Z7_CLASS_IMP_COM_2(c, i1, i2) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_2(i1, i2) \\\n  private:\n\n#define Z7_CLASS_IMP_COM_3(c, i1, i2, i3) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_3(i1, i2, i3) \\\n  private:\n\n#define Z7_CLASS_IMP_COM_4(c, i1, i2, i3, i4) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public i4, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_4(i1, i2, i3, i4) \\\n  private:\n\n#define Z7_CLASS_IMP_COM_5(c, i1, i2, i3, i4, i5) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public i4, \\\n  public i5, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_5(i1, i2, i3, i4, i5) \\\n  private:\n\n#define Z7_CLASS_IMP_COM_6(c, i1, i2, i3, i4, i5, i6) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public i4, \\\n  public i5, \\\n  public i6, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_6(i1, i2, i3, i4, i5, i6) \\\n  private:\n\n\n#define Z7_CLASS_IMP_COM_7(c, i1, i2, i3, i4, i5, i6, i7) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public i4, \\\n  public i5, \\\n  public i6, \\\n  public i7, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_7(i1, i2, i3, i4, i5, i6, i7) \\\n  private:\n\n\n/*\n#define Z7_CLASS_IMP_NOQIB_0(c) \\\n  Z7_class_final(c) : \\\n  public IUnknown, \\\n  public CMyUnknownImp { \\\n  Z7_COM_UNKNOWN_IMP_0 \\\n  private:\n*/\n\n#define Z7_CLASS_IMP_NOQIB_1(c, i1) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public CMyUnknownImp { \\\n  Z7_COM_UNKNOWN_IMP_0 \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  private:\n\n#define Z7_CLASS_IMP_NOQIB_2(c, i1, i2) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public CMyUnknownImp { \\\n  Z7_COM_UNKNOWN_IMP_1(i2) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  private:\n\n#define Z7_CLASS_IMP_NOQIB_3(c, i1, i2, i3) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public CMyUnknownImp { \\\n  Z7_COM_UNKNOWN_IMP_2(i2, i3) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n  private:\n\n#define Z7_CLASS_IMP_NOQIB_4(c, i1, i2, i3, i4) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public i4, \\\n  public CMyUnknownImp { \\\n  Z7_COM_UNKNOWN_IMP_3(i2, i3, i4) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n  Z7_IFACE_COM7_IMP(i4) \\\n\n/*\n#define Z7_CLASS_IMP_NOQIB_5(c, i1, i2, i3, i4, i5) \\\n  Z7_class_final(c) : \\\n  public i1, \\\n  public i2, \\\n  public i3, \\\n  public i4, \\\n  public i5, \\\n  public CMyUnknownImp { \\\n  Z7_COM_UNKNOWN_IMP_4(i2, i3, i4, i5) \\\n  Z7_IFACE_COM7_IMP(i1) \\\n  Z7_IFACE_COM7_IMP(i2) \\\n  Z7_IFACE_COM7_IMP(i3) \\\n  Z7_IFACE_COM7_IMP(i4) \\\n  Z7_IFACE_COM7_IMP(i5) \\\n*/\n\n\n#define Z7_CLASS_IMP_IInStream(c) \\\n  class c Z7_final : \\\n  public IInStream, \\\n  public CMyUnknownImp { \\\n  Z7_IFACES_IMP_UNK_2(ISequentialInStream, IInStream) \\\n\n\n#define k_My_HRESULT_WritingWasCut 0x20000010\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyException.h",
    "content": "﻿// Common/Exception.h\n\n#ifndef ZIP7_INC_COMMON_EXCEPTION_H\n#define ZIP7_INC_COMMON_EXCEPTION_H\n\n#include \"MyWindows.h\"\n\nstruct CSystemException\n{\n  HRESULT ErrorCode;\n  CSystemException(HRESULT errorCode): ErrorCode(errorCode) {}\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyInitGuid.h",
    "content": "﻿// Common/MyInitGuid.h\n\n#ifndef ZIP7_INC_COMMON_MY_INITGUID_H\n#define ZIP7_INC_COMMON_MY_INITGUID_H\n\n/*\nThis file must be included only to one C++ file in project before\ndeclarations of COM interfaces with DEFINE_GUID macro.\n\nEach GUID must be initialized exactly once in project.\nThere are two different versions of the DEFINE_GUID macro in guiddef.h (MyGuidDef.h):\n  - if INITGUID is not defined:  DEFINE_GUID declares an external reference to the symbol name.\n  - if INITGUID is     defined:  DEFINE_GUID initializes the symbol name to the value of the GUID.\n\nAlso we need IID_IUnknown that is initialized in some file for linking:\n  MSVC:  by default the linker uses some lib file that contains IID_IUnknown\n  MinGW: add -luuid switch for linker\n  WinCE: we define IID_IUnknown in this file\n  Other: we define IID_IUnknown in this file\n*/\n\n// #include \"Common.h\"\n/* vc6 without sdk needs <objbase.h> before <initguid.h>,\n   but it doesn't work in new msvc.\n   So we include full \"MyWindows.h\" instead of <objbase.h> */\n// #include <objbase.h>\n#include \"MyWindows.h\"\n\n#ifdef _WIN32\n\n#ifdef __clang__\n  // #pragma GCC diagnostic ignored \"-Wmissing-variable-declarations\"\n#endif\n\n#ifdef UNDER_CE\n#include <basetyps.h>\n#endif\n\n// for vc6 without sdk we must define INITGUID here\n#define INITGUID\n#include <initguid.h>\n\n#ifdef UNDER_CE\nDEFINE_GUID(IID_IUnknown,\n0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);\n#endif\n\n#else // _WIN32\n\n#define INITGUID\n#include \"MyGuidDef.h\"\nDEFINE_GUID(IID_IUnknown,\n0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);\n\n#endif // _WIN32\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyLinux.h",
    "content": "﻿// MyLinux.h\n\n#ifndef ZIP7_INC_COMMON_MY_LINUX_H\n#define ZIP7_INC_COMMON_MY_LINUX_H\n\n// #include \"../../C/7zTypes.h\"\n\n#define MY_LIN_DT_UNKNOWN   0\n#define MY_LIN_DT_FIFO      1\n#define MY_LIN_DT_CHR       2\n#define MY_LIN_DT_DIR       4\n#define MY_LIN_DT_BLK       6\n#define MY_LIN_DT_REG       8\n#define MY_LIN_DT_LNK       10\n#define MY_LIN_DT_SOCK      12\n#define MY_LIN_DT_WHT       14\n\n#define MY_LIN_S_IFMT  00170000\n#define MY_LIN_S_IFSOCK 0140000\n#define MY_LIN_S_IFLNK  0120000\n#define MY_LIN_S_IFREG  0100000\n#define MY_LIN_S_IFBLK  0060000\n#define MY_LIN_S_IFDIR  0040000\n#define MY_LIN_S_IFCHR  0020000\n#define MY_LIN_S_IFIFO  0010000\n\n#define MY_LIN_S_ISLNK(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFLNK)\n#define MY_LIN_S_ISREG(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFREG)\n#define MY_LIN_S_ISDIR(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFDIR)\n#define MY_LIN_S_ISCHR(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFCHR)\n#define MY_LIN_S_ISBLK(m)   (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFBLK)\n#define MY_LIN_S_ISFIFO(m)  (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFIFO)\n#define MY_LIN_S_ISSOCK(m)  (((m) & MY_LIN_S_IFMT) == MY_LIN_S_IFSOCK)\n\n#define MY_LIN_S_ISUID 0004000\n#define MY_LIN_S_ISGID 0002000\n#define MY_LIN_S_ISVTX 0001000\n\n#define MY_LIN_S_IRWXU 00700\n#define MY_LIN_S_IRUSR 00400\n#define MY_LIN_S_IWUSR 00200\n#define MY_LIN_S_IXUSR 00100\n\n#define MY_LIN_S_IRWXG 00070\n#define MY_LIN_S_IRGRP 00040\n#define MY_LIN_S_IWGRP 00020\n#define MY_LIN_S_IXGRP 00010\n\n#define MY_LIN_S_IRWXO 00007\n#define MY_LIN_S_IROTH 00004\n#define MY_LIN_S_IWOTH 00002\n#define MY_LIN_S_IXOTH 00001\n\n/*\n// major/minor encoding for makedev(): MMMMMmmmmmmMMMmm:\n\ninline UInt32 MY_dev_major(UInt64 dev)\n{\n  return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff);\n}\n\ninline UInt32 MY_dev_minor(UInt64 dev)\n{\n  return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~0xff);\n}\n\ninline UInt64 MY_dev_makedev(UInt32 __major, UInt32 __minor)\n{\n  return (__minor & 0xff) | ((__major & 0xfff) << 8)\n      | ((UInt64) (__minor & ~0xff)  << 12)\n      | ((UInt64) (__major & ~0xfff) << 32);\n}\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyMap.cpp",
    "content": "﻿// MyMap.cpp\n\n#include \"StdAfx.h\"\n\n#include \"MyMap.h\"\n\nstatic const unsigned kNumBitsMax = sizeof(UInt32) * 8;\n\nstatic UInt32 GetSubBits(UInt32 value, unsigned startPos, unsigned numBits) throw()\n{\n  if (startPos == sizeof(value) * 8)\n    return 0;\n  value >>= startPos;\n  if (numBits == sizeof(value) * 8)\n    return value;\n  return value & (((UInt32)1 << numBits) - 1);\n}\n\nstatic inline unsigned GetSubBit(UInt32 v, unsigned n) { return (unsigned)(v >> n) & 1; }\n\nbool CMap32::Find(UInt32 key, UInt32 &valueRes) const throw()\n{\n  valueRes = (UInt32)(Int32)-1;\n  if (Nodes.Size() == 0)\n    return false;\n  if (Nodes.Size() == 1)\n  {\n    const CNode &n = Nodes[0];\n    if (n.Len == kNumBitsMax)\n    {\n      valueRes = n.Values[0];\n      return (key == n.Key);\n    }\n  }\n\n  unsigned cur = 0;\n  unsigned bitPos = kNumBitsMax;\n  for (;;)\n  {\n    const CNode &n = Nodes[cur];\n    bitPos -= n.Len;\n    if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))\n      return false;\n    unsigned bit = GetSubBit(key, --bitPos);\n    if (n.IsLeaf[bit])\n    {\n      valueRes = n.Values[bit];\n      return (key == n.Keys[bit]);\n    }\n    cur = (unsigned)n.Keys[bit];\n  }\n}\n\nbool CMap32::Set(UInt32 key, UInt32 value)\n{\n  if (Nodes.Size() == 0)\n  {\n    CNode n;\n    n.Key = n.Keys[0] = n.Keys[1] = key;\n    n.Values[0] = n.Values[1] = value;\n    n.IsLeaf[0] = n.IsLeaf[1] = 1;\n    n.Len = kNumBitsMax;\n    Nodes.Add(n);\n    return false;\n  }\n  if (Nodes.Size() == 1)\n  {\n    CNode &n = Nodes[0];\n    if (n.Len == kNumBitsMax)\n    {\n      if (key == n.Key)\n      {\n        n.Values[0] = n.Values[1] = value;\n        return true;\n      }\n      unsigned i = kNumBitsMax - 1;\n      for (; GetSubBit(key, i) == GetSubBit(n.Key, i); i--);\n      n.Len = (UInt16)(kNumBitsMax - (1 + i));\n      const unsigned newBit = GetSubBit(key, i);\n      n.Values[newBit] = value;\n      n.Keys[newBit] = key;\n      return false;\n    }\n  }\n\n  unsigned cur = 0;\n  unsigned bitPos = kNumBitsMax;\n  for (;;)\n  {\n    CNode &n = Nodes[cur];\n    bitPos -= n.Len;\n    if (GetSubBits(key, bitPos, n.Len) != GetSubBits(n.Key, bitPos, n.Len))\n    {\n      unsigned i = (unsigned)n.Len - 1;\n      for (; GetSubBit(key, bitPos + i) == GetSubBit(n.Key, bitPos + i); i--);\n      \n      CNode e2(n);\n      e2.Len = (UInt16)i;\n\n      n.Len = (UInt16)(n.Len - (1 + i));\n      unsigned newBit = GetSubBit(key, bitPos + i);\n      n.Values[newBit] = value;\n      n.IsLeaf[newBit] = 1;\n      n.IsLeaf[1 - newBit] = 0;\n      n.Keys[newBit] = key;\n      n.Keys[1 - newBit] = (UInt32)Nodes.Size();\n      Nodes.Add(e2);\n      return false;\n    }\n    const unsigned bit = GetSubBit(key, --bitPos);\n\n    if (n.IsLeaf[bit])\n    {\n      if (key == n.Keys[bit])\n      {\n        n.Values[bit] = value;\n        return true;\n      }\n      unsigned i = bitPos - 1;\n      for (; GetSubBit(key, i) == GetSubBit(n.Keys[bit], i); i--);\n     \n      CNode e2;\n      \n      const unsigned newBit = GetSubBit(key, i);\n      e2.Values[newBit] = value;\n      e2.Values[1 - newBit] = n.Values[bit];\n      e2.IsLeaf[newBit] = e2.IsLeaf[1 - newBit] = 1;\n      e2.Keys[newBit] = key;\n      e2.Keys[1 - newBit] = e2.Key = n.Keys[bit];\n      e2.Len = (UInt16)(bitPos - (1 + i));\n\n      n.IsLeaf[bit] = 0;\n      n.Keys[bit] = (UInt32)Nodes.Size();\n\n      Nodes.Add(e2);\n      return false;\n    }\n    cur = (unsigned)n.Keys[bit];\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyMap.h",
    "content": "﻿// MyMap.h\n\n#ifndef ZIP7_INC_COMMON_MY_MAP_H\n#define ZIP7_INC_COMMON_MY_MAP_H\n\n#include \"MyTypes.h\"\n#include \"MyVector.h\"\n\nclass CMap32\n{\n  struct CNode\n  {\n    UInt32 Key;\n    UInt32 Keys[2];\n    UInt32 Values[2];\n    UInt16 Len;\n    Byte IsLeaf[2];\n  };\n  CRecordVector<CNode> Nodes;\n\npublic:\n\n  void Clear() { Nodes.Clear(); }\n  bool Find(UInt32 key, UInt32 &valueRes) const throw();\n  bool Set(UInt32 key, UInt32 value); // returns true, if there is such key already\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyString.cpp",
    "content": "﻿// Common/MyString.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef _WIN32\n#include <wchar.h>\n#else\n#include <ctype.h>\n#endif\n\n#include \"IntToString.h\"\n\n#if !defined(_UNICODE) || !defined(USE_UNICODE_FSTRING)\n#include \"StringConvert.h\"\n#endif\n\n#include \"MyString.h\"\n\n#define MY_STRING_NEW(_T_, _size_) new _T_[_size_]\n// #define MY_STRING_NEW(_T_, _size_) ((_T_ *)my_new((size_t)(_size_) * sizeof(_T_)))\n\n/*\ninline const char* MyStringGetNextCharPointer(const char *p) throw()\n{\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  return CharNextA(p);\n  #else\n  return p + 1;\n  #endif\n}\n*/\n\n#define MY_STRING_NEW_char(_size_) MY_STRING_NEW(char, (_size_))\n#define MY_STRING_NEW_wchar_t(_size_) MY_STRING_NEW(wchar_t, (_size_))\n\n\nint FindCharPosInString(const char *s, char c) throw()\n{\n  for (const char *p = s;; p++)\n  {\n    if (*p == c)\n      return (int)(p - s);\n    if (*p == 0)\n      return -1;\n    // MyStringGetNextCharPointer(p);\n  }\n}\n\nint FindCharPosInString(const wchar_t *s, wchar_t c) throw()\n{\n  for (const wchar_t *p = s;; p++)\n  {\n    if (*p == c)\n      return (int)(p - s);\n    if (*p == 0)\n      return -1;\n  }\n}\n\n/*\nvoid MyStringUpper_Ascii(char *s) throw()\n{\n  for (;;)\n  {\n    const char c = *s;\n    if (c == 0)\n      return;\n    *s++ = MyCharUpper_Ascii(c);\n  }\n}\n\nvoid MyStringUpper_Ascii(wchar_t *s) throw()\n{\n  for (;;)\n  {\n    const wchar_t c = *s;\n    if (c == 0)\n      return;\n    *s++ = MyCharUpper_Ascii(c);\n  }\n}\n*/\n\nvoid MyStringLower_Ascii(char *s) throw()\n{\n  for (;;)\n  {\n    const char c = *s;\n    if (c == 0)\n      return;\n    *s++ = MyCharLower_Ascii(c);\n  }\n}\n\nvoid MyStringLower_Ascii(wchar_t *s) throw()\n{\n  for (;;)\n  {\n    const wchar_t c = *s;\n    if (c == 0)\n      return;\n    *s++ = MyCharLower_Ascii(c);\n  }\n}\n\n#ifdef _WIN32\n\n#ifdef _UNICODE\n\n// wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); }\n// wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); }\n// for WinCE - FString - char\n// const char *MyStringGetPrevCharPointer(const char * /* base */, const char *p) { return p - 1; }\n\n#else\n\n// const char * MyStringGetPrevCharPointer(const char *base, const char *p) throw() { return CharPrevA(base, p); }\n// char * MyStringUpper(char *s) { return CharUpperA(s); }\n// char * MyStringLower(char *s) { return CharLowerA(s); }\n\nwchar_t MyCharUpper_WIN(wchar_t c) throw()\n{\n  wchar_t *res = CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);\n  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\n    return (wchar_t)(unsigned)(UINT_PTR)res;\n  const int kBufSize = 4;\n  char s[kBufSize + 1];\n  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);\n  if (numChars == 0 || numChars > kBufSize)\n    return c;\n  s[numChars] = 0;\n  ::CharUpperA(s);\n  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);\n  return c;\n}\n\n/*\nwchar_t MyCharLower_WIN(wchar_t c)\n{\n  wchar_t *res = CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);\n  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\n    return (wchar_t)(unsigned)(UINT_PTR)res;\n  const int kBufSize = 4;\n  char s[kBufSize + 1];\n  int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufSize, 0, 0);\n  if (numChars == 0 || numChars > kBufSize)\n    return c;\n  s[numChars] = 0;\n  ::CharLowerA(s);\n  ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1);\n  return c;\n}\n*/\n\n/*\nwchar_t * MyStringUpper(wchar_t *s)\n{\n  if (s == 0)\n    return 0;\n  wchar_t *res = CharUpperW(s);\n  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\n    return res;\n  AString a = UnicodeStringToMultiByte(s);\n  a.MakeUpper();\n  MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));\n  return s;\n}\n*/\n\n/*\nwchar_t * MyStringLower(wchar_t *s)\n{\n  if (s == 0)\n    return 0;\n  wchar_t *res = CharLowerW(s);\n  if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)\n    return res;\n  AString a = UnicodeStringToMultiByte(s);\n  a.MakeLower();\n  MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a));\n  return s;\n}\n*/\n\n#endif\n\n#endif\n\nbool IsString1PrefixedByString2(const char *s1, const char *s2) throw()\n{\n  for (;;)\n  {\n    const char c2 = *s2++; if (c2 == 0) return true;\n    const char c1 = *s1++; if (c1 != c2) return false;\n  }\n}\n\nbool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    const wchar_t c1 = *s1++;\n    const wchar_t c2 = *s2++;\n    if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2)) return false;\n    if (c1 == 0) return true;\n  }\n}\n\n// ---------- ASCII ----------\n\nbool StringsAreEqual_Ascii(const char *u, const char *a) throw()\n{\n  for (;;)\n  {\n    const char c = *a;\n    if (c != *u)\n      return false;\n    if (c == 0)\n      return true;\n    a++;\n    u++;\n  }\n}\n\nbool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw()\n{\n  for (;;)\n  {\n    const unsigned char c = (unsigned char)*a;\n    if (c != *u)\n      return false;\n    if (c == 0)\n      return true;\n    a++;\n    u++;\n  }\n}\n\nbool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw()\n{\n  for (;;)\n  {\n    const char c1 = *s1++;\n    const char c2 = *s2++;\n    if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))\n      return false;\n    if (c1 == 0)\n      return true;\n  }\n}\n\nbool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    const wchar_t c1 = *s1++;\n    const wchar_t c2 = *s2++;\n    if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))\n      return false;\n    if (c1 == 0)\n      return true;\n  }\n}\n\nbool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw()\n{\n  for (;;)\n  {\n    const wchar_t c1 = *s1++;\n    const char c2 = *s2++;\n    if (c1 != (unsigned char)c2 && (c1 > 0x7F || MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2)))\n      return false;\n    if (c1 == 0)\n      return true;\n  }\n}\n\nbool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    const wchar_t c2 = *s2++; if (c2 == 0) return true;\n    const wchar_t c1 = *s1++; if (c1 != c2) return false;\n  }\n}\n\nbool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw()\n{\n  for (;;)\n  {\n    const unsigned char c2 = (unsigned char)(*s2++); if (c2 == 0) return true;\n    const wchar_t c1 = *s1++; if (c1 != c2) return false;\n  }\n}\n\nbool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw()\n{\n  for (;;)\n  {\n    const char c2 = *s2++; if (c2 == 0) return true;\n    const char c1 = *s1++;\n    if (c1 != c2 && MyCharLower_Ascii(c1) != MyCharLower_Ascii(c2))\n      return false;\n  }\n}\n\nbool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *s1, const char *s2) throw()\n{\n  for (;;)\n  {\n    const char c2 = *s2++; if (c2 == 0) return true;\n    const wchar_t c1 = *s1++;\n    if (c1 != (unsigned char)c2 && MyCharLower_Ascii(c1) != (unsigned char)MyCharLower_Ascii(c2))\n      return false;\n  }\n}\n\nbool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    const wchar_t c2 = *s2++; if (c2 == 0) return true;\n    const wchar_t c1 = *s1++;\n    if (c1 != c2 && MyCharUpper(c1) != MyCharUpper(c2))\n      return false;\n  }\n}\n\n// NTFS order: uses upper case\nint MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    const wchar_t c1 = *s1++;\n    const wchar_t c2 = *s2++;\n    if (c1 != c2)\n    {\n      const wchar_t u1 = MyCharUpper(c1);\n      const wchar_t u2 = MyCharUpper(c2);\n      if (u1 < u2) return -1;\n      if (u1 > u2) return 1;\n    }\n    if (c1 == 0) return 0;\n  }\n}\n\n/*\nint MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num)\n{\n  for (; num != 0; num--)\n  {\n    wchar_t c1 = *s1++;\n    wchar_t c2 = *s2++;\n    if (c1 != c2)\n    {\n      wchar_t u1 = MyCharUpper(c1);\n      wchar_t u2 = MyCharUpper(c2);\n      if (u1 < u2) return -1;\n      if (u1 > u2) return 1;\n    }\n    if (c1 == 0) return 0;\n  }\n  return 0;\n}\n*/\n\n// ---------- AString ----------\n\nvoid AString::InsertSpace(unsigned &index, unsigned size)\n{\n  Grow(size);\n  MoveItems(index + size, index);\n}\n\n#define k_Alloc_Len_Limit (0x40000000 - 2)\n// #define k_Alloc_Len_Limit (((unsigned)1 << (sizeof(unsigned) * 8 - 2)) - 2)\n\nvoid AString::ReAlloc(unsigned newLimit)\n{\n  // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, (size_t)_len + 1);\n  char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1);\n  memcpy(newBuf, _chars, (size_t)_len + 1);\n  MY_STRING_DELETE(_chars)\n  _chars = newBuf;\n  _limit = newLimit;\n}\n\n#define THROW_STRING_ALLOC_EXCEPTION  { throw 20130220; }\n\n#define CHECK_STRING_ALLOC_LEN(len) \\\n  { if ((len) > k_Alloc_Len_Limit) THROW_STRING_ALLOC_EXCEPTION }\n\nvoid AString::ReAlloc2(unsigned newLimit)\n{\n  CHECK_STRING_ALLOC_LEN(newLimit)\n  // MY_STRING_REALLOC(_chars, char, (size_t)newLimit + 1, 0);\n  char *newBuf = MY_STRING_NEW_char((size_t)newLimit + 1);\n  newBuf[0] = 0;\n  MY_STRING_DELETE(_chars)\n  _chars = newBuf;\n  _limit = newLimit;\n  _len = 0;\n}\n\nvoid AString::SetStartLen(unsigned len)\n{\n  _chars = NULL;\n  _chars = MY_STRING_NEW_char((size_t)len + 1);\n  _len = len;\n  _limit = len;\n}\n\nZ7_NO_INLINE\nvoid AString::Grow_1()\n{\n  unsigned next = _len;\n  next += next / 2;\n  next += 16;\n  next &= ~(unsigned)15;\n  next--;\n  if (next < _len || next > k_Alloc_Len_Limit)\n    next = k_Alloc_Len_Limit;\n  if (next <= _len)\n    THROW_STRING_ALLOC_EXCEPTION\n  ReAlloc(next);\n  // Grow(1);\n}\n\nvoid AString::Grow(unsigned n)\n{\n  const unsigned freeSize = _limit - _len;\n  if (n <= freeSize)\n    return;\n  unsigned next = _len + n;\n  next += next / 2;\n  next += 16;\n  next &= ~(unsigned)15;\n  next--;\n  if (next < _len || next > k_Alloc_Len_Limit)\n    next = k_Alloc_Len_Limit;\n  if (next <= _len || next - _len < n)\n    THROW_STRING_ALLOC_EXCEPTION\n  ReAlloc(next);\n}\n\nAString::AString(unsigned num, const char *s)\n{\n  unsigned len = MyStringLen(s);\n  if (num > len)\n    num = len;\n  SetStartLen(num);\n  memcpy(_chars, s, num);\n  _chars[num] = 0;\n}\n\nAString::AString(unsigned num, const AString &s)\n{\n  if (num > s._len)\n    num = s._len;\n  SetStartLen(num);\n  memcpy(_chars, s._chars, num);\n  _chars[num] = 0;\n}\n\nAString::AString(const AString &s, char c)\n{\n  SetStartLen(s.Len() + 1);\n  char *chars = _chars;\n  unsigned len = s.Len();\n  memcpy(chars, s, len);\n  chars[len] = c;\n  chars[(size_t)len + 1] = 0;\n}\n\nAString::AString(const char *s1, unsigned num1, const char *s2, unsigned num2)\n{\n  SetStartLen(num1 + num2);\n  char *chars = _chars;\n  memcpy(chars, s1, num1);\n  memcpy(chars + num1, s2, num2 + 1);\n}\n\nAString operator+(const AString &s1, const AString &s2) { return AString(s1, s1.Len(), s2, s2.Len()); }\nAString operator+(const AString &s1, const char    *s2) { return AString(s1, s1.Len(), s2, MyStringLen(s2)); }\nAString operator+(const char    *s1, const AString &s2) { return AString(s1, MyStringLen(s1), s2, s2.Len()); }\n\nstatic const unsigned kStartStringCapacity = 4;\n \nAString::AString()\n{\n  _chars = NULL;\n  _chars = MY_STRING_NEW_char(kStartStringCapacity);\n  _len = 0;\n  _limit = kStartStringCapacity - 1;\n  _chars[0] = 0;\n}\n\nAString::AString(char c)\n{\n  SetStartLen(1);\n  char *chars = _chars;\n  chars[0] = c;\n  chars[1] = 0;\n}\n\nAString::AString(const char *s)\n{\n  SetStartLen(MyStringLen(s));\n  MyStringCopy(_chars, s);\n}\n\nAString::AString(const AString &s)\n{\n  SetStartLen(s._len);\n  MyStringCopy(_chars, s._chars);\n}\n\nAString &AString::operator=(char c)\n{\n  if (1 > _limit)\n  {\n    char *newBuf = MY_STRING_NEW_char(1 + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = 1;\n  }\n  _len = 1;\n  char *chars = _chars;\n  chars[0] = c;\n  chars[1] = 0;\n  return *this;\n}\n\nAString &AString::operator=(const char *s)\n{\n  unsigned len = MyStringLen(s);\n  if (len > _limit)\n  {\n    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  _len = len;\n  MyStringCopy(_chars, s);\n  return *this;\n}\n\nAString &AString::operator=(const AString &s)\n{\n  if (&s == this)\n    return *this;\n  unsigned len = s._len;\n  if (len > _limit)\n  {\n    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  _len = len;\n  MyStringCopy(_chars, s._chars);\n  return *this;\n}\n\nvoid AString::SetFromWStr_if_Ascii(const wchar_t *s)\n{\n  unsigned len = 0;\n  {\n    for (;; len++)\n    {\n      wchar_t c = s[len];\n      if (c == 0)\n        break;\n      if (c >= 0x80)\n        return;\n    }\n  }\n  if (len > _limit)\n  {\n    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  _len = len;\n  char *dest = _chars;\n  unsigned i;\n  for (i = 0; i < len; i++)\n    dest[i] = (char)s[i];\n  dest[i] = 0;\n}\n\n/*\nvoid AString::SetFromBstr_if_Ascii(BSTR s)\n{\n  unsigned len = ::SysStringLen(s);\n  {\n    for (unsigned i = 0; i < len; i++)\n      if (s[i] <= 0 || s[i] >= 0x80)\n        return;\n  }\n  if (len > _limit)\n  {\n    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  _len = len;\n  char *dest = _chars;\n  unsigned i;\n  for (i = 0; i < len; i++)\n    dest[i] = (char)s[i];\n  dest[i] = 0;\n}\n*/\n\nvoid AString::Add_Char(char c) { operator+=(c); }\nvoid AString::Add_Space() { operator+=(' '); }\nvoid AString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }\nvoid AString::Add_LF() { operator+=('\\n'); }\nvoid AString::Add_Slash() { operator+=('/'); }\nvoid AString::Add_Dot() { operator+=('.'); }\nvoid AString::Add_Minus() { operator+=('-'); }\nvoid AString::Add_Colon() { operator+=(':'); }\n\nAString &AString::operator+=(const char *s)\n{\n  unsigned len = MyStringLen(s);\n  Grow(len);\n  MyStringCopy(_chars + _len, s);\n  _len += len;\n  return *this;\n}\n\nvoid AString::Add_OptSpaced(const char *s)\n{\n  Add_Space_if_NotEmpty();\n  (*this) += s;\n}\n\nAString &AString::operator+=(const AString &s)\n{\n  Grow(s._len);\n  MyStringCopy(_chars + _len, s._chars);\n  _len += s._len;\n  return *this;\n}\n\nvoid AString::Add_UInt32(UInt32 v)\n{\n  Grow(10);\n  _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);\n}\n\nvoid UString::Add_UInt64(UInt64 v)\n{\n  Grow(20);\n  _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);\n}\n\nvoid AString::AddFrom(const char *s, unsigned len) // no check\n{\n  if (len != 0)\n  {\n    Grow(len);\n    memcpy(_chars + _len, s, len);\n    len += _len;\n    _chars[len] = 0;\n    _len = len;\n  }\n}\n\nvoid AString::SetFrom(const char *s, unsigned len) // no check\n{\n  if (len > _limit)\n  {\n    CHECK_STRING_ALLOC_LEN(len)\n    char *newBuf = MY_STRING_NEW_char((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  if (len != 0)\n    memcpy(_chars, s, len);\n  _chars[len] = 0;\n  _len = len;\n}\n\nvoid AString::SetFrom_Chars_SizeT(const char *s, size_t len)\n{\n  CHECK_STRING_ALLOC_LEN(len)\n  SetFrom(s, (unsigned)len);\n}\n\nvoid AString::SetFrom_CalcLen(const char *s, unsigned len) // no check\n{\n  unsigned i;\n  for (i = 0; i < len; i++)\n    if (s[i] == 0)\n      break;\n  SetFrom(s, i);\n}\n\nint AString::Find(const char *s, unsigned startIndex) const throw()\n{\n  const char *fs = strstr(_chars + startIndex, s);\n  if (!fs)\n    return -1;\n  return (int)(fs - _chars);\n\n  /*\n  if (s[0] == 0)\n    return startIndex;\n  unsigned len = MyStringLen(s);\n  const char *p = _chars + startIndex;\n  for (;; p++)\n  {\n    const char c = *p;\n    if (c != s[0])\n    {\n      if (c == 0)\n        return -1;\n      continue;\n    }\n    unsigned i;\n    for (i = 1; i < len; i++)\n      if (p[i] != s[i])\n        break;\n    if (i == len)\n      return (int)(p - _chars);\n  }\n  */\n}\n\nint AString::ReverseFind(char c) const throw()\n{\n  if (_len == 0)\n    return -1;\n  const char *p = _chars + _len - 1;\n  for (;;)\n  {\n    if (*p == c)\n      return (int)(p - _chars);\n    if (p == _chars)\n      return -1;\n    p--; // p = GetPrevCharPointer(_chars, p);\n  }\n}\n\nint AString::ReverseFind_PathSepar() const throw()\n{\n  if (_len == 0)\n    return -1;\n  const char *p = _chars + _len - 1;\n  for (;;)\n  {\n    const char c = *p;\n    if (IS_PATH_SEPAR(c))\n      return (int)(p - _chars);\n    if (p == _chars)\n      return -1;\n    p--;\n  }\n}\n\nvoid AString::TrimLeft() throw()\n{\n  const char *p = _chars;\n  for (;; p++)\n  {\n    char c = *p;\n    if (c != ' ' && c != '\\n' && c != '\\t')\n      break;\n  }\n  unsigned pos = (unsigned)(p - _chars);\n  if (pos != 0)\n  {\n    MoveItems(0, pos);\n    _len -= pos;\n  }\n}\n\nvoid AString::TrimRight() throw()\n{\n  const char *p = _chars;\n  unsigned i;\n  for (i = _len; i != 0; i--)\n  {\n    char c = p[(size_t)i - 1];\n    if (c != ' ' && c != '\\n' && c != '\\t')\n      break;\n  }\n  if (i != _len)\n  {\n    _chars[i] = 0;\n    _len = i;\n  }\n}\n\nvoid AString::InsertAtFront(char c)\n{\n  if (_limit == _len)\n    Grow_1();\n  MoveItems(1, 0);\n  _chars[0] = c;\n  _len++;\n}\n\n/*\nvoid AString::Insert(unsigned index, char c)\n{\n  InsertSpace(index, 1);\n  _chars[index] = c;\n  _len++;\n}\n*/\n\nvoid AString::Insert(unsigned index, const char *s)\n{\n  unsigned num = MyStringLen(s);\n  if (num != 0)\n  {\n    InsertSpace(index, num);\n    memcpy(_chars + index, s, num);\n    _len += num;\n  }\n}\n\nvoid AString::Insert(unsigned index, const AString &s)\n{\n  unsigned num = s.Len();\n  if (num != 0)\n  {\n    InsertSpace(index, num);\n    memcpy(_chars + index, s, num);\n    _len += num;\n  }\n}\n\nvoid AString::RemoveChar(char ch) throw()\n{\n  char *src = _chars;\n  \n  for (;;)\n  {\n    char c = *src++;\n    if (c == 0)\n      return;\n    if (c == ch)\n      break;\n  }\n\n  char *dest = src - 1;\n  \n  for (;;)\n  {\n    char c = *src++;\n    if (c == 0)\n      break;\n    if (c != ch)\n      *dest++ = c;\n  }\n  \n  *dest = 0;\n  _len = (unsigned)(dest - _chars);\n}\n\n// !!!!!!!!!!!!!!! test it if newChar = '\\0'\nvoid AString::Replace(char oldChar, char newChar) throw()\n{\n  if (oldChar == newChar)\n    return; // 0;\n  // unsigned number = 0;\n  int pos = 0;\n  char *chars = _chars;\n  while ((unsigned)pos < _len)\n  {\n    pos = Find(oldChar, (unsigned)pos);\n    if (pos < 0)\n      break;\n    chars[(unsigned)pos] = newChar;\n    pos++;\n    // number++;\n  }\n  return; //  number;\n}\n\nvoid AString::Replace(const AString &oldString, const AString &newString)\n{\n  if (oldString.IsEmpty())\n    return; // 0;\n  if (oldString == newString)\n    return; // 0;\n  const unsigned oldLen = oldString.Len();\n  const unsigned newLen = newString.Len();\n  // unsigned number = 0;\n  int pos = 0;\n  while ((unsigned)pos < _len)\n  {\n    pos = Find(oldString, (unsigned)pos);\n    if (pos < 0)\n      break;\n    Delete((unsigned)pos, oldLen);\n    Insert((unsigned)pos, newString);\n    pos += newLen;\n    // number++;\n  }\n  // return number;\n}\n\nvoid AString::Delete(unsigned index) throw()\n{\n  MoveItems(index, index + 1);\n  _len--;\n}\n\nvoid AString::Delete(unsigned index, unsigned count) throw()\n{\n  if (index + count > _len)\n    count = _len - index;\n  if (count > 0)\n  {\n    MoveItems(index, index + count);\n    _len -= count;\n  }\n}\n\nvoid AString::DeleteFrontal(unsigned num) throw()\n{\n  if (num != 0)\n  {\n    MoveItems(0, num);\n    _len -= num;\n  }\n}\n\n/*\nAString operator+(const AString &s1, const AString &s2)\n{\n  AString result(s1);\n  result += s2;\n  return result;\n}\n\nAString operator+(const AString &s, const char *chars)\n{\n  AString result(s);\n  result += chars;\n  return result;\n}\n\nAString operator+(const char *chars, const AString &s)\n{\n  AString result(chars);\n  result += s;\n  return result;\n}\n\nAString operator+(const AString &s, char c)\n{\n  AString result(s);\n  result += c;\n  return result;\n}\n*/\n\n/*\nAString operator+(char c, const AString &s)\n{\n  AString result(c);\n  result += s;\n  return result;\n}\n*/\n\n\n\n\n// ---------- UString ----------\n\nvoid UString::InsertSpace(unsigned index, unsigned size)\n{\n  Grow(size);\n  MoveItems(index + size, index);\n}\n\nvoid UString::ReAlloc(unsigned newLimit)\n{\n  // MY_STRING_REALLOC(_chars, wchar_t, (size_t)newLimit + 1, (size_t)_len + 1);\n  wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);\n  wmemcpy(newBuf, _chars, _len + 1);\n  MY_STRING_DELETE(_chars)\n  _chars = newBuf;\n  _limit = newLimit;\n}\n\nvoid UString::ReAlloc2(unsigned newLimit)\n{\n  CHECK_STRING_ALLOC_LEN(newLimit)\n  // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);\n  wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);\n  newBuf[0] = 0;\n  MY_STRING_DELETE(_chars)\n  _chars = newBuf;\n  _limit = newLimit;\n  _len = 0;\n}\n\nvoid UString::SetStartLen(unsigned len)\n{\n  _chars = NULL;\n  _chars = MY_STRING_NEW_wchar_t((size_t)len + 1);\n  _len = len;\n  _limit = len;\n}\n\nZ7_NO_INLINE\nvoid UString::Grow_1()\n{\n  unsigned next = _len;\n  next += next / 2;\n  next += 16;\n  next &= ~(unsigned)15;\n  next--;\n  if (next < _len || next > k_Alloc_Len_Limit)\n    next = k_Alloc_Len_Limit;\n  if (next <= _len)\n    THROW_STRING_ALLOC_EXCEPTION\n  ReAlloc(next);\n}\n\nvoid UString::Grow(unsigned n)\n{\n  const unsigned freeSize = _limit - _len;\n  if (n <= freeSize)\n    return;\n  unsigned next = _len + n;\n  next += next / 2;\n  next += 16;\n  next &= ~(unsigned)15;\n  next--;\n  if (next < _len || next > k_Alloc_Len_Limit)\n    next = k_Alloc_Len_Limit;\n  if (next <= _len || next - _len < n)\n    THROW_STRING_ALLOC_EXCEPTION\n  ReAlloc(next - 1);\n}\n\n\nUString::UString(unsigned num, const wchar_t *s)\n{\n  unsigned len = MyStringLen(s);\n  if (num > len)\n    num = len;\n  SetStartLen(num);\n  wmemcpy(_chars, s, num);\n  _chars[num] = 0;\n}\n\n\nUString::UString(unsigned num, const UString &s)\n{\n  if (num > s._len)\n    num = s._len;\n  SetStartLen(num);\n  wmemcpy(_chars, s._chars, num);\n  _chars[num] = 0;\n}\n\nUString::UString(const UString &s, wchar_t c)\n{\n  SetStartLen(s.Len() + 1);\n  wchar_t *chars = _chars;\n  unsigned len = s.Len();\n  wmemcpy(chars, s, len);\n  chars[len] = c;\n  chars[(size_t)len + 1] = 0;\n}\n\nUString::UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2)\n{\n  SetStartLen(num1 + num2);\n  wchar_t *chars = _chars;\n  wmemcpy(chars, s1, num1);\n  wmemcpy(chars + num1, s2, num2 + 1);\n}\n\nUString operator+(const UString &s1, const UString &s2) { return UString(s1, s1.Len(), s2, s2.Len()); }\nUString operator+(const UString &s1, const wchar_t *s2) { return UString(s1, s1.Len(), s2, MyStringLen(s2)); }\nUString operator+(const wchar_t *s1, const UString &s2) { return UString(s1, MyStringLen(s1), s2, s2.Len()); }\n\nUString::UString()\n{\n  _chars = NULL;\n  _chars = MY_STRING_NEW_wchar_t(kStartStringCapacity);\n  _len = 0;\n  _limit = kStartStringCapacity - 1;\n  _chars[0] = 0;\n}\n\nUString::UString(wchar_t c)\n{\n  SetStartLen(1);\n  wchar_t *chars = _chars;\n  chars[0] = c;\n  chars[1] = 0;\n}\n\nUString::UString(char c)\n{\n  SetStartLen(1);\n  wchar_t *chars = _chars;\n  chars[0] = (unsigned char)c;\n  chars[1] = 0;\n}\n\nUString::UString(const wchar_t *s)\n{\n  const unsigned len = MyStringLen(s);\n  SetStartLen(len);\n  wmemcpy(_chars, s, len + 1);\n}\n\nUString::UString(const char *s)\n{\n  const unsigned len = MyStringLen(s);\n  SetStartLen(len);\n  wchar_t *chars = _chars;\n  for (unsigned i = 0; i < len; i++)\n    chars[i] = (unsigned char)s[i];\n  chars[len] = 0;\n}\n\nUString::UString(const AString &s)\n{\n  const unsigned len = s.Len();\n  SetStartLen(len);\n  wchar_t *chars = _chars;\n  const char *s2 = s.Ptr();\n  for (unsigned i = 0; i < len; i++)\n    chars[i] = (unsigned char)s2[i];\n  chars[len] = 0;\n}\n\nUString::UString(const UString &s)\n{\n  SetStartLen(s._len);\n  wmemcpy(_chars, s._chars, s._len + 1);\n}\n\nUString &UString::operator=(wchar_t c)\n{\n  if (1 > _limit)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = 1;\n  }\n  _len = 1;\n  wchar_t *chars = _chars;\n  chars[0] = c;\n  chars[1] = 0;\n  return *this;\n}\n\nUString &UString::operator=(const wchar_t *s)\n{\n  unsigned len = MyStringLen(s);\n  if (len > _limit)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  _len = len;\n  wmemcpy(_chars, s, len + 1);\n  return *this;\n}\n\nUString &UString::operator=(const UString &s)\n{\n  if (&s == this)\n    return *this;\n  unsigned len = s._len;\n  if (len > _limit)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  _len = len;\n  wmemcpy(_chars, s._chars, len + 1);\n  return *this;\n}\n\n// **************** 7-Zip ZS Modification Start ****************\nvoid UString::AddFrom(const wchar_t *s, unsigned len) // no check\n{\n  if (len) {\n    Grow(len);\n    wmemcpy(_chars + _len, s, len);\n    _len += len;\n    _chars[_len] = 0;\n  }\n}\n// **************** 7-Zip ZS Modification End ****************\n\nvoid UString::SetFrom(const wchar_t *s, unsigned len) // no check\n{\n  if (len > _limit)\n  {\n    CHECK_STRING_ALLOC_LEN(len)\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  if (len != 0)\n    wmemcpy(_chars, s, len);\n  _chars[len] = 0;\n  _len = len;\n}\n\nvoid UString::SetFromBstr(LPCOLESTR s)\n{\n  unsigned len = ::SysStringLen((BSTR)(void *)(s));\n\n  /*\n  #if WCHAR_MAX > 0xffff\n  size_t num_wchars = 0;\n  for (size_t i = 0; i < len;)\n  {\n    wchar_t c = s[i++];\n    if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)\n    {\n      wchar_t c2 = s[i];\n      if (c2 >= 0xdc00 && c2 < 0xe000)\n      {\n        c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);\n        i++;\n      }\n    }\n    num_wchars++;\n  }\n  len = num_wchars;\n  #endif\n  */\n\n  if (len > _limit)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  _len = len;\n\n  /*\n  #if WCHAR_MAX > 0xffff\n\n  wchar_t *chars = _chars;\n  for (size_t i = 0; i <= len; i++)\n  {\n    wchar_t c = *s++;\n    if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)\n    {\n      wchar_t c2 = *s;\n      if (c2 >= 0xdc00 && c2 < 0xe000)\n      {\n        s++;\n        c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);\n      }\n    }\n    chars[i] = c;\n  }\n\n  #else\n  */\n\n  // if (s)\n    wmemcpy(_chars, s, len + 1);\n  \n  // #endif\n}\n\nUString &UString::operator=(const char *s)\n{\n  unsigned len = MyStringLen(s);\n  if (len > _limit)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n    _limit = len;\n  }\n  wchar_t *chars = _chars;\n  for (unsigned i = 0; i < len; i++)\n    chars[i] = (unsigned char)s[i];\n  chars[len] = 0;\n  _len = len;\n  return *this;\n}\n\nvoid UString::Add_Char(char c) { operator+=((wchar_t)(unsigned char)c); }\n// void UString::Add_WChar(wchar_t c) { operator+=(c); }\nvoid UString::Add_Dot() { operator+=(L'.'); }\nvoid UString::Add_Space() { operator+=(L' '); }\nvoid UString::Add_Minus() { operator+=(L'-'); }\nvoid UString::Add_Colon() { operator+=(L':'); }\nvoid UString::Add_LF() { operator+=(L'\\n'); }\nvoid UString::Add_Space_if_NotEmpty() { if (!IsEmpty()) Add_Space(); }\n\nUString &UString::operator+=(const wchar_t *s)\n{\n  unsigned len = MyStringLen(s);\n  Grow(len);\n  wmemcpy(_chars + _len, s, len + 1);\n  _len += len;\n  return *this;\n}\n\nUString &UString::operator+=(const UString &s)\n{\n  Grow(s._len);\n  wmemcpy(_chars + _len, s._chars, s._len + 1);\n  _len += s._len;\n  return *this;\n}\n\nUString &UString::operator+=(const char *s)\n{\n  unsigned len = MyStringLen(s);\n  Grow(len);\n  wchar_t *chars = _chars + _len;\n  for (unsigned i = 0; i < len; i++)\n    chars[i] = (unsigned char)s[i];\n  chars[len] = 0;\n  _len += len;\n  return *this;\n}\n\n\nvoid UString::Add_UInt32(UInt32 v)\n{\n  Grow(10);\n  _len = (unsigned)(ConvertUInt32ToString(v, _chars + _len) - _chars);\n}\n\nvoid AString::Add_UInt64(UInt64 v)\n{\n  Grow(20);\n  _len = (unsigned)(ConvertUInt64ToString(v, _chars + _len) - _chars);\n}\n\n\nint UString::Find(const wchar_t *s, unsigned startIndex) const throw()\n{\n  const wchar_t *fs = wcsstr(_chars + startIndex, s);\n  if (!fs)\n    return -1;\n  return (int)(fs - _chars);\n\n  /*\n  if (s[0] == 0)\n    return startIndex;\n  unsigned len = MyStringLen(s);\n  const wchar_t *p = _chars + startIndex;\n  for (;; p++)\n  {\n    const wchar_t c = *p;\n    if (c != s[0])\n    {\n      if (c == 0)\n        return -1;\n      continue;\n    }\n    unsigned i;\n    for (i = 1; i < len; i++)\n      if (p[i] != s[i])\n        break;\n    if (i == len)\n      return (int)(p - _chars);\n  }\n  */\n}\n\nint UString::ReverseFind(wchar_t c) const throw()\n{\n  if (_len == 0)\n    return -1;\n  const wchar_t *p = _chars + _len;\n  do\n  {\n    if (*(--p) == c)\n      return (int)(p - _chars);\n  }\n  while (p != _chars);\n  return -1;\n}\n\nint UString::ReverseFind_PathSepar() const throw()\n{\n  const wchar_t *p = _chars + _len;\n  while (p != _chars)\n  {\n    const wchar_t c = *(--p);\n    if (IS_PATH_SEPAR(c))\n      return (int)(p - _chars);\n  }\n  return -1;\n}\n\nvoid UString::TrimLeft() throw()\n{\n  const wchar_t *p = _chars;\n  for (;; p++)\n  {\n    wchar_t c = *p;\n    if (c != ' ' && c != '\\n' && c != '\\t')\n      break;\n  }\n  unsigned pos = (unsigned)(p - _chars);\n  if (pos != 0)\n  {\n    MoveItems(0, pos);\n    _len -= pos;\n  }\n}\n\nvoid UString::TrimRight() throw()\n{\n  const wchar_t *p = _chars;\n  unsigned i;\n  for (i = _len; i != 0; i--)\n  {\n    wchar_t c = p[(size_t)i - 1];\n    if (c != ' ' && c != '\\n' && c != '\\t')\n      break;\n  }\n  if (i != _len)\n  {\n    _chars[i] = 0;\n    _len = i;\n  }\n}\n\nvoid UString::InsertAtFront(wchar_t c)\n{\n  if (_limit == _len)\n    Grow_1();\n  MoveItems(1, 0);\n  _chars[0] = c;\n  _len++;\n}\n\n/*\nvoid UString::Insert_wchar_t(unsigned index, wchar_t c)\n{\n  InsertSpace(index, 1);\n  _chars[index] = c;\n  _len++;\n}\n*/\n\nvoid UString::Insert(unsigned index, const wchar_t *s)\n{\n  unsigned num = MyStringLen(s);\n  if (num != 0)\n  {\n    InsertSpace(index, num);\n    wmemcpy(_chars + index, s, num);\n    _len += num;\n  }\n}\n\nvoid UString::Insert(unsigned index, const UString &s)\n{\n  unsigned num = s.Len();\n  if (num != 0)\n  {\n    InsertSpace(index, num);\n    wmemcpy(_chars + index, s, num);\n    _len += num;\n  }\n}\n\nvoid UString::RemoveChar(wchar_t ch) throw()\n{\n  wchar_t *src = _chars;\n  \n  for (;;)\n  {\n    wchar_t c = *src++;\n    if (c == 0)\n      return;\n    if (c == ch)\n      break;\n  }\n\n  wchar_t *dest = src - 1;\n  \n  for (;;)\n  {\n    wchar_t c = *src++;\n    if (c == 0)\n      break;\n    if (c != ch)\n      *dest++ = c;\n  }\n  \n  *dest = 0;\n  _len = (unsigned)(dest - _chars);\n}\n\n// !!!!!!!!!!!!!!! test it if newChar = '\\0'\nvoid UString::Replace(wchar_t oldChar, wchar_t newChar) throw()\n{\n  if (oldChar == newChar)\n    return; // 0;\n  // unsigned number = 0;\n  int pos = 0;\n  wchar_t *chars = _chars;\n  while ((unsigned)pos < _len)\n  {\n    pos = Find(oldChar, (unsigned)pos);\n    if (pos < 0)\n      break;\n    chars[(unsigned)pos] = newChar;\n    pos++;\n    // number++;\n  }\n  return; //  number;\n}\n\nvoid UString::Replace(const UString &oldString, const UString &newString)\n{\n  if (oldString.IsEmpty())\n    return; // 0;\n  if (oldString == newString)\n    return; // 0;\n  unsigned oldLen = oldString.Len();\n  unsigned newLen = newString.Len();\n  // unsigned number = 0;\n  int pos = 0;\n  while ((unsigned)pos < _len)\n  {\n    pos = Find(oldString, (unsigned)pos);\n    if (pos < 0)\n      break;\n    Delete((unsigned)pos, oldLen);\n    Insert((unsigned)pos, newString);\n    pos += newLen;\n    // number++;\n  }\n  // return number;\n}\n\nvoid UString::Delete(unsigned index) throw()\n{\n  MoveItems(index, index + 1);\n  _len--;\n}\n\nvoid UString::Delete(unsigned index, unsigned count) throw()\n{\n  if (index + count > _len)\n    count = _len - index;\n  if (count > 0)\n  {\n    MoveItems(index, index + count);\n    _len -= count;\n  }\n}\n\nvoid UString::DeleteFrontal(unsigned num) throw()\n{\n  if (num != 0)\n  {\n    MoveItems(0, num);\n    _len -= num;\n  }\n}\n\n\n// ---------- UString2 ----------\n\nvoid UString2::ReAlloc2(unsigned newLimit)\n{\n  // wrong (_len) is allowed after this function\n  CHECK_STRING_ALLOC_LEN(newLimit)\n  // MY_STRING_REALLOC(_chars, wchar_t, newLimit + 1, 0);\n  if (_chars)\n  {\n    MY_STRING_DELETE(_chars)\n    _chars = NULL;\n    // _len = 0;\n  }\n  _chars = MY_STRING_NEW_wchar_t((size_t)newLimit + 1);\n  _chars[0] = 0;\n  // _len = newLimit;\n}\n\nvoid UString2::SetStartLen(unsigned len)\n{\n  _chars = NULL;\n  _chars = MY_STRING_NEW_wchar_t((size_t)len + 1);\n  _len = len;\n}\n\n\n/*\nUString2::UString2(wchar_t c)\n{\n  SetStartLen(1);\n  wchar_t *chars = _chars;\n  chars[0] = c;\n  chars[1] = 0;\n}\n*/\n\nUString2::UString2(const wchar_t *s)\n{\n  const unsigned len = MyStringLen(s);\n  SetStartLen(len);\n  wmemcpy(_chars, s, len + 1);\n}\n\nUString2::UString2(const UString2 &s): _chars(NULL), _len(0)\n{\n  if (s._chars)\n  {\n    SetStartLen(s._len);\n    wmemcpy(_chars, s._chars, s._len + 1);\n  }\n}\n\n/*\nUString2 &UString2::operator=(wchar_t c)\n{\n  if (1 > _len)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t(1 + 1);\n    if (_chars)\n      MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n  }\n  _len = 1;\n  wchar_t *chars = _chars;\n  chars[0] = c;\n  chars[1] = 0;\n  return *this;\n}\n*/\n\nUString2 &UString2::operator=(const wchar_t *s)\n{\n  unsigned len = MyStringLen(s);\n  if (len > _len)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    if (_chars)\n      MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n  }\n  _len = len;\n  MyStringCopy(_chars, s);\n  return *this;\n}\n\nvoid UString2::SetFromAscii(const char *s)\n{\n  unsigned len = MyStringLen(s);\n  if (len > _len)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    if (_chars)\n      MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n  }\n  wchar_t *chars = _chars;\n  for (unsigned i = 0; i < len; i++)\n    chars[i] = (unsigned char)s[i];\n  chars[len] = 0;\n  _len = len;\n}\n\nUString2 &UString2::operator=(const UString2 &s)\n{\n  if (&s == this)\n    return *this;\n  unsigned len = s._len;\n  if (len > _len)\n  {\n    wchar_t *newBuf = MY_STRING_NEW_wchar_t((size_t)len + 1);\n    if (_chars)\n      MY_STRING_DELETE(_chars)\n    _chars = newBuf;\n  }\n  _len = len;\n  MyStringCopy(_chars, s._chars);\n  return *this;\n}\n\nbool operator==(const UString2 &s1, const UString2 &s2)\n{\n  return s1.Len() == s2.Len() && (s1.IsEmpty() || wcscmp(s1.GetRawPtr(), s2.GetRawPtr()) == 0);\n}\n\nbool operator==(const UString2 &s1, const wchar_t *s2)\n{\n  if (s1.IsEmpty())\n    return (*s2 == 0);\n  return wcscmp(s1.GetRawPtr(), s2) == 0;\n}\n\nbool operator==(const wchar_t *s1, const UString2 &s2)\n{\n  if (s2.IsEmpty())\n    return (*s1 == 0);\n  return wcscmp(s1, s2.GetRawPtr()) == 0;\n}\n\n\n\n// ----------------------------------------\n\n/*\nint MyStringCompareNoCase(const char *s1, const char *s2)\n{\n  return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2));\n}\n*/\n\n#if !defined(USE_UNICODE_FSTRING) || !defined(_UNICODE)\n\nstatic inline UINT GetCurrentCodePage()\n{\n  #if defined(UNDER_CE) || !defined(_WIN32)\n  return CP_ACP;\n  #else\n  return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;\n  #endif\n}\n\n#endif\n\n#ifdef USE_UNICODE_FSTRING\n\n#ifndef _UNICODE\n\nAString fs2fas(CFSTR s)\n{\n  return UnicodeStringToMultiByte(s, GetCurrentCodePage());\n}\n\nFString fas2fs(const char *s)\n{\n  return MultiByteToUnicodeString(s, GetCurrentCodePage());\n}\n\nFString fas2fs(const AString &s)\n{\n  return MultiByteToUnicodeString(s, GetCurrentCodePage());\n}\n\n#endif //  _UNICODE\n\n#else // USE_UNICODE_FSTRING\n\nUString fs2us(const FChar *s)\n{\n  return MultiByteToUnicodeString(s, GetCurrentCodePage());\n}\n\nUString fs2us(const FString &s)\n{\n  return MultiByteToUnicodeString(s, GetCurrentCodePage());\n}\n\nFString us2fs(const wchar_t *s)\n{\n  return UnicodeStringToMultiByte(s, GetCurrentCodePage());\n}\n\n#endif // USE_UNICODE_FSTRING\n\n\nbool CStringFinder::FindWord_In_LowCaseAsciiList_NoCase(const char *p, const wchar_t *str)\n{\n  _temp.Empty();\n  for (;;)\n  {\n    const wchar_t c = *str++;\n    if (c == 0)\n      break;\n    if (c <= 0x20 || c > 0x7f)\n      return false;\n    _temp.Add_Char((char)MyCharLower_Ascii((char)c));\n  }\n\n  while (*p != 0)\n  {\n    const char *s2 = _temp.Ptr();\n    char c, c2;\n    do\n    {\n      c = *p++;\n      c2 = *s2++;\n    }\n    while (c == c2);\n    \n    if (c == ' ')\n    {\n      if (c2 == 0)\n        return true;\n      continue;\n    }\n    \n    while (*p++ != ' ');\n  }\n  \n  return false;\n}\n\n\nvoid SplitString(const UString &srcString, UStringVector &destStrings)\n{\n  destStrings.Clear();\n  unsigned len = srcString.Len();\n  if (len == 0)\n    return;\n  UString s;\n  for (unsigned i = 0; i < len; i++)\n  {\n    const wchar_t c = srcString[i];\n    if (c == ' ')\n    {\n      if (!s.IsEmpty())\n      {\n        destStrings.Add(s);\n        s.Empty();\n      }\n    }\n    else\n      s += c;\n  }\n  if (!s.IsEmpty())\n    destStrings.Add(s);\n}\n\n// **************** 7-Zip ZS Modification Start ****************\n\n// ----------------------------------------\n\nUString GetQuotedString(const UString &src)\n{\n  UString s2 ('\\\"');\n  unsigned bcount = 0;\n  wchar_t c; const wchar_t *f = src.Ptr(), *s = f, *b = f;\n  // add string considering backslashes before quote (escape them):\n  while (1)\n  {\n    c = *s++;\n    switch (c)\n    {\n      case L'\\\\':\n        // a backslash - save the position and count them up to quote-char or regular char\n        if (!bcount) b = s-1;\n        bcount++;\n      break;\n      case L'\\0':\n        // end of string (it is always quoted, so need to escape backslashes too):\n      case L'\"':\n        // add part before backslash (and unescaped backslashes if some are there):\n        s2.AddFrom(f, (unsigned)(s - f - 1));\n        f = s;\n        if (bcount) {\n          // escape backslashes before quote (same count of BS again):\n          s2.AddFrom(b, (unsigned)(s - b - 1));\n        }\n        // done if end of string\n        if (c == L'\\0') goto done;\n        // escape this quote char:\n        s2 += L\"\\\\\\\"\";\n      break;\n      default:\n        // a regular character, reset backslash counter\n        bcount = 0;\n    }\n  }\n  s2.AddFrom(f, (unsigned)(s - f - 1));\ndone:\n  s2.Add_Char('\\\"');\n  return s2;\n}\n// **************** 7-Zip ZS Modification End ****************\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyString.h",
    "content": "﻿// Common/MyString.h\n\n#ifndef ZIP7_INC_COMMON_MY_STRING_H\n#define ZIP7_INC_COMMON_MY_STRING_H\n\n#include <string.h>\n\n#ifndef _WIN32\n#include <wctype.h>\n#include <wchar.h>\n#endif\n\n#include \"Common.h\"\n#include \"MyWindows.h\"\n#include \"MyTypes.h\"\n#include \"MyVector.h\"\n\n\n/* if (DEBUG_FSTRING_INHERITS_ASTRING is defined), then\n     FString inherits from AString, so we can find bugs related to FString at compile time.\n   DON'T define DEBUG_FSTRING_INHERITS_ASTRING in release code */\n   \n// #define DEBUG_FSTRING_INHERITS_ASTRING\n\n#ifdef DEBUG_FSTRING_INHERITS_ASTRING\nclass FString;\n#endif\n\n\n#ifdef _MSC_VER\n  #ifdef _NATIVE_WCHAR_T_DEFINED\n    #define MY_NATIVE_WCHAR_T_DEFINED\n  #endif\n#else\n    #define MY_NATIVE_WCHAR_T_DEFINED\n#endif\n\n/*\n  native support for wchar_t:\n _MSC_VER == 1600 : /Zc:wchar_t is not supported\n _MSC_VER == 1310 (VS2003)\n ? _MSC_VER == 1400 (VS2005) : wchar_t <- unsigned short\n              /Zc:wchar_t  : wchar_t <- __wchar_t, _WCHAR_T_DEFINED and _NATIVE_WCHAR_T_DEFINED\n _MSC_VER > 1400 (VS2008+)\n              /Zc:wchar_t[-]\n              /Zc:wchar_t is on by default\n*/\n\n#ifdef _WIN32\n#define IS_PATH_SEPAR(c) ((c) == '\\\\' || (c) == '/')\n#else\n#define IS_PATH_SEPAR(c) ((c) == CHAR_PATH_SEPARATOR)\n#endif\n\ninline bool IsPathSepar(char    c) { return IS_PATH_SEPAR(c); }\ninline bool IsPathSepar(wchar_t c) { return IS_PATH_SEPAR(c); }\n\ninline unsigned MyStringLen(const char *s)\n{\n  unsigned i;\n  for (i = 0; s[i] != 0; i++);\n  return i;\n}\n\ninline void MyStringCopy(char *dest, const char *src)\n{\n  while ((*dest++ = *src++) != 0);\n}\n\ninline char *MyStpCpy(char *dest, const char *src)\n{\n  for (;;)\n  {\n    const char c = *src;\n    *dest = c;\n    if (c == 0)\n      return dest;\n    src++;\n    dest++;\n  }\n}\n\ninline void MyStringCat(char *dest, const char *src)\n{\n  for (; *dest != 0; dest++);\n  while ((*dest++ = *src++) != 0);\n  // MyStringCopy(dest + MyStringLen(dest), src);\n}\n\ninline unsigned MyStringLen(const wchar_t *s)\n{\n  unsigned i;\n  for (i = 0; s[i] != 0; i++);\n  return i;\n}\n\ninline void MyStringCopy(wchar_t *dest, const wchar_t *src)\n{\n  while ((*dest++ = *src++) != 0);\n}\n\ninline void MyStringCat(wchar_t *dest, const wchar_t *src)\n{\n  for (; *dest != 0; dest++);\n  while ((*dest++ = *src++) != 0);\n  // MyStringCopy(dest + MyStringLen(dest), src);\n}\n\n\n/*\ninline wchar_t *MyWcpCpy(wchar_t *dest, const wchar_t *src)\n{\n  for (;;)\n  {\n    const wchar_t c = *src;\n    *dest = c;\n    if (c == 0)\n      return dest;\n    src++;\n    dest++;\n  }\n}\n*/\n\nint FindCharPosInString(const char *s, char c) throw();\nint FindCharPosInString(const wchar_t *s, wchar_t c) throw();\n\n#ifdef _WIN32\n  #ifndef _UNICODE\n    #define STRING_UNICODE_THROW\n  #endif\n#endif\n\n#ifndef STRING_UNICODE_THROW\n  #define STRING_UNICODE_THROW throw()\n#endif\n\n\ninline char MyCharUpper_Ascii(char c)\n{\n  if (c >= 'a' && c <= 'z')\n    return (char)((unsigned char)c - 0x20);\n  return c;\n}\n\n/*\ninline wchar_t MyCharUpper_Ascii(wchar_t c)\n{\n  if (c >= 'a' && c <= 'z')\n    return (wchar_t)(c - 0x20);\n  return c;\n}\n*/\n\ninline char MyCharLower_Ascii(char c)\n{\n  if (c >= 'A' && c <= 'Z')\n    return (char)((unsigned char)c + 0x20);\n  return c;\n}\n\ninline wchar_t MyCharLower_Ascii(wchar_t c)\n{\n  if (c >= 'A' && c <= 'Z')\n    return (wchar_t)(c + 0x20);\n  return c;\n}\n\nwchar_t MyCharUpper_WIN(wchar_t c) throw();\n\ninline wchar_t MyCharUpper(wchar_t c) throw()\n{\n  if (c < 'a') return c;\n  if (c <= 'z') return (wchar_t)(c - 0x20);\n  if (c <= 0x7F) return c;\n  #ifdef _WIN32\n    #ifdef _UNICODE\n      return (wchar_t)(unsigned)(UINT_PTR)CharUpperW((LPWSTR)(UINT_PTR)(unsigned)c);\n    #else\n      return (wchar_t)MyCharUpper_WIN(c);\n    #endif\n  #else\n    return (wchar_t)towupper((wint_t)c);\n  #endif\n}\n\n/*\nwchar_t MyCharLower_WIN(wchar_t c) throw();\n\ninline wchar_t MyCharLower(wchar_t c) throw()\n{\n  if (c < 'A') return c;\n  if (c <= 'Z') return (wchar_t)(c + 0x20);\n  if (c <= 0x7F) return c;\n  #ifdef _WIN32\n    #ifdef _UNICODE\n      return (wchar_t)(unsigned)(UINT_PTR)CharLowerW((LPWSTR)(UINT_PTR)(unsigned)c);\n    #else\n      return (wchar_t)MyCharLower_WIN(c);\n    #endif\n  #else\n    return (wchar_t)tolower(c);\n  #endif\n}\n*/\n\n// char *MyStringUpper(char *s) throw();\n// char *MyStringLower(char *s) throw();\n\n// void MyStringUpper_Ascii(char *s) throw();\n// void MyStringUpper_Ascii(wchar_t *s) throw();\nvoid MyStringLower_Ascii(char *s) throw();\nvoid MyStringLower_Ascii(wchar_t *s) throw();\n// wchar_t *MyStringUpper(wchar_t *s) STRING_UNICODE_THROW;\n// wchar_t *MyStringLower(wchar_t *s) STRING_UNICODE_THROW;\n\nbool StringsAreEqualNoCase(const wchar_t *s1, const wchar_t *s2) throw();\n\nbool IsString1PrefixedByString2(const char *s1, const char *s2) throw();\nbool IsString1PrefixedByString2(const wchar_t *s1, const wchar_t *s2) throw();\nbool IsString1PrefixedByString2(const wchar_t *s1, const char *s2) throw();\nbool IsString1PrefixedByString2_NoCase_Ascii(const char *s1, const char *s2) throw();\nbool IsString1PrefixedByString2_NoCase_Ascii(const wchar_t *u, const char *a) throw();\nbool IsString1PrefixedByString2_NoCase(const wchar_t *s1, const wchar_t *s2) throw();\n\n#define MyStringCompare(s1, s2) wcscmp(s1, s2)\nint MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) throw();\n// int MyStringCompareNoCase_N(const wchar_t *s1, const wchar_t *s2, unsigned num) throw();\n\n// ---------- ASCII ----------\n// char values in ASCII strings must be less then 128\nbool StringsAreEqual_Ascii(const char *u, const char *a) throw();\nbool StringsAreEqual_Ascii(const wchar_t *u, const char *a) throw();\nbool StringsAreEqualNoCase_Ascii(const char *s1, const char *s2) throw();\nbool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const char *s2) throw();\nbool StringsAreEqualNoCase_Ascii(const wchar_t *s1, const wchar_t *s2) throw();\n\n#define MY_STRING_DELETE(_p_) { delete [](_p_); }\n// #define MY_STRING_DELETE(_p_) my_delete(_p_);\n\n\n#define FORBID_STRING_OPS_2(cls, t) \\\n  void Find(t) const; \\\n  void Find(t, unsigned startIndex) const; \\\n  void ReverseFind(t) const; \\\n  void InsertAtFront(t); \\\n  void RemoveChar(t); \\\n  void Replace(t, t); \\\n\n#define FORBID_STRING_OPS(cls, t) \\\n  explicit cls(t); \\\n  explicit cls(const t *); \\\n  cls &operator=(t); \\\n  cls &operator=(const t *); \\\n  cls &operator+=(t); \\\n  cls &operator+=(const t *); \\\n  FORBID_STRING_OPS_2(cls, t) \\\n\n/*\n  cls &operator+(t); \\\n  cls &operator+(const t *); \\\n*/\n\n#define FORBID_STRING_OPS_AString(t) FORBID_STRING_OPS(AString, t)\n#define FORBID_STRING_OPS_UString(t) FORBID_STRING_OPS(UString, t)\n#define FORBID_STRING_OPS_UString2(t) FORBID_STRING_OPS(UString2, t)\n\nclass AString\n{\n  char *_chars;\n  unsigned _len;\n  unsigned _limit;\n\n  void MoveItems(unsigned dest, unsigned src)\n  {\n    memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(char));\n  }\n  \n  void InsertSpace(unsigned &index, unsigned size);\n  \n  void ReAlloc(unsigned newLimit);\n  void ReAlloc2(unsigned newLimit);\n  void SetStartLen(unsigned len);\n  \n  Z7_NO_INLINE\n  void Grow_1();\n  void Grow(unsigned n);\n\n  AString(unsigned num, const char *s);\n  AString(unsigned num, const AString &s);\n  AString(const AString &s, char c); // it's for String + char\n  AString(const char *s1, unsigned num1, const char *s2, unsigned num2);\n\n  friend AString operator+(const AString &s, char c) { return AString(s, c); }\n  // friend AString operator+(char c, const AString &s); // is not supported\n\n  friend AString operator+(const AString &s1, const AString &s2);\n  friend AString operator+(const AString &s1, const char    *s2);\n  friend AString operator+(const char    *s1, const AString &s2);\n\n  // ---------- forbidden functions ----------\n\n  #ifdef MY_NATIVE_WCHAR_T_DEFINED\n  FORBID_STRING_OPS_AString(wchar_t)\n  #endif\n\n  FORBID_STRING_OPS_AString(signed char)\n  FORBID_STRING_OPS_AString(unsigned char)\n  FORBID_STRING_OPS_AString(short)\n  FORBID_STRING_OPS_AString(unsigned short)\n  FORBID_STRING_OPS_AString(int)\n  FORBID_STRING_OPS_AString(unsigned)\n  FORBID_STRING_OPS_AString(long)\n  FORBID_STRING_OPS_AString(unsigned long)\n\n #ifdef DEBUG_FSTRING_INHERITS_ASTRING\n  AString(const FString &s);\n  AString &operator=(const FString &s);\n  AString &operator+=(const FString &s);\n #endif\n\npublic:\n  explicit AString();\n  explicit AString(char c);\n  explicit AString(const char *s);\n  AString(const AString &s);\n  ~AString() { MY_STRING_DELETE(_chars) }\n\n  unsigned Len() const { return _len; }\n  bool IsEmpty() const { return _len == 0; }\n  void Empty() { _len = 0; _chars[0] = 0; }\n\n  operator const char *() const { return _chars; }\n  char *Ptr_non_const() const { return _chars; }\n  const char *Ptr() const { return _chars; }\n  const char *Ptr(unsigned pos) const { return _chars + pos; }\n  const char *Ptr(int pos) const { return _chars + (unsigned)pos; }\n  const char *RightPtr(unsigned num) const { return _chars + _len - num; }\n  char Back() const { return _chars[(size_t)_len - 1]; }\n\n  void ReplaceOneCharAtPos(unsigned pos, char c) { _chars[pos] = c; }\n\n  char *GetBuf() { return _chars; }\n  /* GetBuf(minLen): provides the buffer that can store\n     at least (minLen) characters and additional null terminator.\n     9.35: GetBuf doesn't preserve old characters and terminator */\n  char *GetBuf(unsigned minLen)\n  {\n    if (minLen > _limit)\n      ReAlloc2(minLen);\n    return _chars;\n  }\n  char *GetBuf_SetEnd(unsigned minLen)\n  {\n    if (minLen > _limit)\n      ReAlloc2(minLen);\n    char *chars = _chars;\n    chars[minLen] = 0;\n    _len = minLen;\n    return chars;\n  }\n\n  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }\n  void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }\n  void ReleaseBuf_CalcLen(unsigned maxLen)\n  {\n    char *chars = _chars;\n    chars[maxLen] = 0;\n    _len = MyStringLen(chars);\n  }\n\n  AString &operator=(char c);\n  AString &operator=(const char *s);\n  AString &operator=(const AString &s);\n  void SetFromWStr_if_Ascii(const wchar_t *s);\n  // void SetFromBstr_if_Ascii(BSTR s);\n\n// private:\n  Z7_FORCE_INLINE\n  AString &operator+=(char c)\n  {\n    if (_limit == _len)\n      Grow_1();\n    unsigned len = _len;\n    char *chars = _chars;\n    chars[len++] = c;\n    chars[len] = 0;\n    _len = len;\n    return *this;\n  }\npublic:\n  void Add_Space();\n  void Add_Space_if_NotEmpty();\n  void Add_OptSpaced(const char *s);\n  void Add_Char(char c);\n  void Add_LF();\n  void Add_Slash();\n  void Add_Dot();\n  void Add_Minus();\n  void Add_Colon();\n  void Add_PathSepar() { operator+=(CHAR_PATH_SEPARATOR); }\n\n  AString &operator+=(const char *s);\n  AString &operator+=(const AString &s);\n\n  void Add_UInt32(UInt32 v);\n  void Add_UInt64(UInt64 v);\n\n  void AddFrom(const char *s, unsigned len); // no check\n  void SetFrom(const char *s, unsigned len); // no check\n  void SetFrom_Chars_SizeT(const char* s, size_t len); // no check\n  void SetFrom(const char* s, int len) // no check\n  {\n    SetFrom(s, (unsigned)len); // no check\n  }\n  void SetFrom_CalcLen(const char *s, unsigned len);\n\n  AString Mid(unsigned startIndex, unsigned count) const { return AString(count, _chars + startIndex); }\n  AString Left(unsigned count) const { return AString(count, *this); }\n  // void MakeUpper() { MyStringUpper(_chars); }\n  // void MakeLower() { MyStringLower(_chars); }\n  void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }\n\n\n  bool IsEqualTo(const char *s) const { return strcmp(_chars, s) == 0; }\n  bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }\n  // int Compare(const char *s) const { return MyStringCompare(_chars, s); }\n  // int Compare(const AString &s) const { return MyStringCompare(_chars, s._chars); }\n  // int CompareNoCase(const char *s) const { return MyStringCompareNoCase(_chars, s); }\n  // int CompareNoCase(const AString &s) const { return MyStringCompareNoCase(_chars, s._chars); }\n  bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }\n  bool IsPrefixedBy_Ascii_NoCase(const char *s) const { return IsString1PrefixedByString2_NoCase_Ascii(_chars, s); }\n \n  bool IsAscii() const\n  {\n    const unsigned len = Len();\n    const char *s = _chars;\n    for (unsigned i = 0; i < len; i++)\n      if ((unsigned char)s[i] >= 0x80)\n        return false;\n    return true;\n  }\n  int Find(char c) const { return FindCharPosInString(_chars, c); }\n  int Find(char c, unsigned startIndex) const\n  {\n    const int pos = FindCharPosInString(_chars + startIndex, c);\n    return pos < 0 ? -1 : (int)startIndex + pos;\n  }\n  int Find(char c, int startIndex) const\n  {\n    return Find(c, (unsigned)startIndex);\n  }\n  \n  int ReverseFind(char c) const throw();\n  int ReverseFind_Dot() const throw() { return ReverseFind('.'); }\n  int ReverseFind_PathSepar() const throw();\n\n  int Find(const char *s) const { return Find(s, 0); }\n  int Find(const char *s, unsigned startIndex) const throw();\n  \n  void TrimLeft() throw();\n  void TrimRight() throw();\n  void Trim()\n  {\n    TrimRight();\n    TrimLeft();\n  }\n\n  void InsertAtFront(char c);\n  // void Insert(unsigned index, char c);\n  void Insert(unsigned index, const char *s);\n  void Insert(unsigned index, const AString &s);\n\n  void RemoveChar(char ch) throw();\n  \n  void Replace(char oldChar, char newChar) throw();\n  void Replace(const AString &oldString, const AString &newString);\n\n  void Delete(unsigned index) throw();\n  void Delete(unsigned index, unsigned count) throw();\n  void DeleteFrontal(unsigned num) throw();\n  void DeleteBack() { _chars[--_len] = 0; }\n  void DeleteFrom(unsigned index)\n  {\n    if (index < _len)\n    {\n      _len = index;\n      _chars[index] = 0;\n    }\n  }\n  void DeleteFrom(int index)\n  {\n    DeleteFrom((unsigned)index);\n  }\n\n  \n  void Wipe_and_Empty()\n  {\n    if (_chars)\n    {\n      memset(_chars, 0, (_limit + 1) * sizeof(*_chars));\n      _len = 0;\n    }\n  }\n};\n\n\nclass AString_Wipe: public AString\n{\n  Z7_CLASS_NO_COPY(AString_Wipe)\npublic:\n  AString_Wipe(): AString() {}\n  // AString_Wipe(const AString &s): AString(s) {}\n  // AString_Wipe &operator=(const AString &s) { AString::operator=(s); return *this; }\n  // AString_Wipe &operator=(const char *s) { AString::operator=(s); return *this; }\n  ~AString_Wipe() { Wipe_and_Empty(); }\n};\n\n\nbool operator<(const AString &s1, const AString &s2);\nbool operator>(const AString &s1, const AString &s2);\n\n/*\nbool operator==(const AString &s1, const AString &s2);\nbool operator==(const AString &s1, const char    *s2);\nbool operator==(const char    *s1, const AString &s2);\n\nbool operator!=(const AString &s1, const AString &s2);\nbool operator!=(const AString &s1, const char    *s2);\nbool operator!=(const char    *s1, const AString &s2);\n*/\n\ninline bool operator==(const AString &s1, const AString &s2) { return s1.Len() == s2.Len() && strcmp(s1, s2) == 0; }\ninline bool operator==(const AString &s1, const char    *s2) { return strcmp(s1, s2) == 0; }\ninline bool operator==(const char    *s1, const AString &s2) { return strcmp(s1, s2) == 0; }\n\ninline bool operator!=(const AString &s1, const AString &s2) { return s1.Len() != s2.Len() || strcmp(s1, s2) != 0; }\ninline bool operator!=(const AString &s1, const char    *s2) { return strcmp(s1, s2) != 0; }\ninline bool operator!=(const char    *s1, const AString &s2) { return strcmp(s1, s2) != 0; }\n\n// ---------- forbidden functions ----------\n\nvoid operator==(char c1, const AString &s2);\nvoid operator==(const AString &s1, char c2);\n\nvoid operator+(char c, const AString &s); // this function can be OK, but we don't use it\n\nvoid operator+(const AString &s, int c);\nvoid operator+(const AString &s, unsigned c);\nvoid operator+(int c, const AString &s);\nvoid operator+(unsigned c, const AString &s);\nvoid operator-(const AString &s, int c);\nvoid operator-(const AString &s, unsigned c);\n\n\nclass UString\n{\n  wchar_t *_chars;\n  unsigned _len;\n  unsigned _limit;\n\n  void MoveItems(unsigned dest, unsigned src)\n  {\n    memmove(_chars + dest, _chars + src, (size_t)(_len - src + 1) * sizeof(wchar_t));\n  }\n  \n  void InsertSpace(unsigned index, unsigned size);\n  \n  void ReAlloc(unsigned newLimit);\n  void ReAlloc2(unsigned newLimit);\n  void SetStartLen(unsigned len);\n  void Grow_1();\n  void Grow(unsigned n);\n\n  UString(unsigned num, const wchar_t *s); // for Mid\n  UString(unsigned num, const UString &s); // for Left\n  UString(const UString &s, wchar_t c); // it's for String + char\n  UString(const wchar_t *s1, unsigned num1, const wchar_t *s2, unsigned num2);\n\n  friend UString operator+(const UString &s, wchar_t c) { return UString(s, c); }\n  // friend UString operator+(wchar_t c, const UString &s); // is not supported\n\n  friend UString operator+(const UString &s1, const UString &s2);\n  friend UString operator+(const UString &s1, const wchar_t *s2);\n  friend UString operator+(const wchar_t *s1, const UString &s2);\n\n  // ---------- forbidden functions ----------\n  \n  FORBID_STRING_OPS_UString(signed char)\n  FORBID_STRING_OPS_UString(unsigned char)\n  FORBID_STRING_OPS_UString(short)\n  \n  #ifdef MY_NATIVE_WCHAR_T_DEFINED\n  FORBID_STRING_OPS_UString(unsigned short)\n  #endif\n\n  FORBID_STRING_OPS_UString(int)\n  FORBID_STRING_OPS_UString(unsigned)\n  FORBID_STRING_OPS_UString(long)\n  FORBID_STRING_OPS_UString(unsigned long)\n\n  FORBID_STRING_OPS_2(UString, char)\n\n #ifdef DEBUG_FSTRING_INHERITS_ASTRING\n  UString(const FString &s);\n  UString &operator=(const FString &s);\n  UString &operator+=(const FString &s);\n #endif\n\npublic:\n  UString();\n  explicit UString(wchar_t c);\n  explicit UString(char c);\n  explicit UString(const char *s);\n  explicit UString(const AString &s);\n  UString(const wchar_t *s);\n  UString(const UString &s);\n  ~UString() { MY_STRING_DELETE(_chars) }\n\n  unsigned Len() const { return _len; }\n  bool IsEmpty() const { return _len == 0; }\n  void Empty() { _len = 0; _chars[0] = 0; }\n\n  operator const wchar_t *() const { return _chars; }\n  wchar_t *Ptr_non_const() const { return _chars; }\n  const wchar_t *Ptr() const { return _chars; }\n  const wchar_t *Ptr(int pos) const { return _chars + (unsigned)pos; }\n  const wchar_t *Ptr(unsigned pos) const { return _chars + pos; }\n  const wchar_t *RightPtr(unsigned num) const { return _chars + _len - num; }\n  wchar_t Back() const { return _chars[(size_t)_len - 1]; }\n\n  void ReplaceOneCharAtPos(unsigned pos, wchar_t c) { _chars[pos] = c; }\n\n  wchar_t *GetBuf() { return _chars; }\n\n  /*\n  wchar_t *GetBuf_GetMaxAvail(unsigned &availBufLen)\n  {\n    availBufLen = _limit;\n    return _chars;\n  }\n  */\n\n  wchar_t *GetBuf(unsigned minLen)\n  {\n    if (minLen > _limit)\n      ReAlloc2(minLen);\n    return _chars;\n  }\n  wchar_t *GetBuf_SetEnd(unsigned minLen)\n  {\n    if (minLen > _limit)\n      ReAlloc2(minLen);\n    wchar_t *chars = _chars;\n    chars[minLen] = 0;\n    _len = minLen;\n    return chars;\n  }\n\n  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }\n  void ReleaseBuf_SetEnd(unsigned newLen) { _len = newLen; _chars[newLen] = 0; }\n  void ReleaseBuf_CalcLen(unsigned maxLen)\n  {\n    wchar_t *chars = _chars;\n    chars[maxLen] = 0;\n    _len = MyStringLen(chars);\n  }\n\n  UString &operator=(wchar_t c);\n  UString &operator=(char c) { return (*this)=((wchar_t)(unsigned char)c); }\n  UString &operator=(const wchar_t *s);\n  UString &operator=(const UString &s);\n  // **************** 7-Zip ZS Modification Start ****************\n  void AddFrom(const wchar_t *s, unsigned len); // no check\n  // **************** 7-Zip ZS Modification End ****************\n  void SetFrom(const wchar_t *s, unsigned len); // no check\n  void SetFromBstr(LPCOLESTR s);\n  UString &operator=(const char *s);\n  UString &operator=(const AString &s) { return operator=(s.Ptr()); }\n\n// private:\n  Z7_FORCE_INLINE\n  UString &operator+=(wchar_t c)\n  {\n    if (_limit == _len)\n      Grow_1();\n    unsigned len = _len;\n    wchar_t *chars = _chars;\n    chars[len++] = c;\n    chars[len] = 0;\n    _len = len;\n    return *this;\n  }\n\nprivate:\n  UString &operator+=(char c); //  { return (*this)+=((wchar_t)(unsigned char)c); }\npublic:\n  void Add_Char(char c);\n  // void Add_WChar(wchar_t c);\n  void Add_Space();\n  void Add_Space_if_NotEmpty();\n  void Add_LF();\n  void Add_Dot();\n  void Add_Minus();\n  void Add_Colon();\n  void Add_PathSepar() { operator+=(WCHAR_PATH_SEPARATOR); }\n\n  UString &operator+=(const wchar_t *s);\n  UString &operator+=(const UString &s);\n  UString &operator+=(const char *s);\n  UString &operator+=(const AString &s) { return operator+=(s.Ptr()); }\n\n  void Add_UInt32(UInt32 v);\n  void Add_UInt64(UInt64 v);\n\n  UString Mid(unsigned startIndex, unsigned count) const { return UString(count, _chars + startIndex); }\n  UString Left(unsigned count) const { return UString(count, *this); }\n  UString Left(int count) const { return Left((unsigned)count); }\n\n  // void MakeUpper() { MyStringUpper(_chars); }\n  // void MakeUpper() { MyStringUpper_Ascii(_chars); }\n  // void MakeUpper_Ascii() { MyStringUpper_Ascii(_chars); }\n  void MakeLower_Ascii() { MyStringLower_Ascii(_chars); }\n\n  bool IsEqualTo(const char *s) const { return StringsAreEqual_Ascii(_chars, s); }\n  bool IsEqualTo_NoCase(const wchar_t *s) const { return StringsAreEqualNoCase(_chars, s); }\n  bool IsEqualTo_Ascii_NoCase(const char *s) const { return StringsAreEqualNoCase_Ascii(_chars, s); }\n  int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }\n  // int Compare(const UString &s) const { return MyStringCompare(_chars, s._chars); }\n  // int CompareNoCase(const wchar_t *s) const { return MyStringCompareNoCase(_chars, s); }\n  // int CompareNoCase(const UString &s) const { return MyStringCompareNoCase(_chars, s._chars); }\n  bool IsPrefixedBy(const wchar_t *s) const { return IsString1PrefixedByString2(_chars, s); }\n  bool IsPrefixedBy(const char *s) const { return IsString1PrefixedByString2(_chars, s); }\n  bool IsPrefixedBy_NoCase(const wchar_t *s) const { return IsString1PrefixedByString2_NoCase(_chars, s); }\n  bool IsPrefixedBy_Ascii_NoCase(const char *s) const { return IsString1PrefixedByString2_NoCase_Ascii(_chars, s); }\n\n  bool IsAscii() const\n  {\n    const unsigned len = Len();\n    const wchar_t *s = _chars;\n    for (unsigned i = 0; i < len; i++)\n      if ((unsigned)(int)s[i] >= 0x80)\n        return false;\n    return true;\n  }\n  int Find(wchar_t c) const { return FindCharPosInString(_chars, c); }\n  int Find(wchar_t c, unsigned startIndex) const\n  {\n    const int pos = FindCharPosInString(_chars + startIndex, c);\n    return pos < 0 ? -1 : (int)startIndex + pos;\n  }\n\n  int ReverseFind(wchar_t c) const throw();\n  int ReverseFind_Dot() const throw() { return ReverseFind(L'.'); }\n  int ReverseFind_PathSepar() const throw();\n\n  int Find(const wchar_t *s) const { return Find(s, 0); }\n  int Find(const wchar_t *s, unsigned startIndex) const throw();\n\n  void TrimLeft() throw();\n  void TrimRight() throw();\n  void Trim()\n  {\n    TrimRight();\n    TrimLeft();\n  }\n\n  void InsertAtFront(wchar_t c);\n  // void Insert_wchar_t(unsigned index, wchar_t c);\n  void Insert(unsigned index, const wchar_t *s);\n  void Insert(unsigned index, const UString &s);\n\n  void RemoveChar(wchar_t ch) throw();\n  \n  void Replace(wchar_t oldChar, wchar_t newChar) throw();\n  void Replace(const UString &oldString, const UString &newString);\n\n  void Delete(int index) throw() { Delete((unsigned)index); }\n  void Delete(unsigned index) throw();\n  void Delete(unsigned index, unsigned count) throw();\n  void DeleteFrontal(unsigned num) throw();\n  void DeleteBack() { _chars[--_len] = 0; }\n  void DeleteFrom(int index) { DeleteFrom((unsigned)index); }\n  void DeleteFrom(unsigned index)\n  {\n    if (index < _len)\n    {\n      _len = index;\n      _chars[index] = 0;\n    }\n  }\n  \n  void Wipe_and_Empty()\n  {\n    if (_chars)\n    {\n      memset(_chars, 0, (_limit + 1) * sizeof(*_chars));\n      _len = 0;\n    }\n  }\n};\n\n\nclass UString_Wipe: public UString\n{\n  Z7_CLASS_NO_COPY(UString_Wipe)\npublic:\n  UString_Wipe(): UString() {}\n  // UString_Wipe(const UString &s): UString(s) {}\n  // UString_Wipe &operator=(const UString &s) { UString::operator=(s); return *this; }\n  // UString_Wipe &operator=(const wchar_t *s) { UString::operator=(s); return *this; }\n  ~UString_Wipe() { Wipe_and_Empty(); }\n};\n\n\nbool operator<(const UString &s1, const UString &s2);\nbool operator>(const UString &s1, const UString &s2);\n\ninline bool operator==(const UString &s1, const UString &s2) { return s1.Len() == s2.Len() && wcscmp(s1, s2) == 0; }\ninline bool operator==(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) == 0; }\ninline bool operator==(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) == 0; }\n\ninline bool operator!=(const UString &s1, const UString &s2) { return s1.Len() != s2.Len() || wcscmp(s1, s2) != 0; }\ninline bool operator!=(const UString &s1, const wchar_t *s2) { return wcscmp(s1, s2) != 0; }\ninline bool operator!=(const wchar_t *s1, const UString &s2) { return wcscmp(s1, s2) != 0; }\n\n\n// ---------- forbidden functions ----------\n\nvoid operator==(wchar_t c1, const UString &s2);\nvoid operator==(const UString &s1, wchar_t c2);\n\nvoid operator+(wchar_t c, const UString &s); // this function can be OK, but we don't use it\n\nvoid operator+(const AString &s1, const UString &s2);\nvoid operator+(const UString &s1, const AString &s2);\n\nvoid operator+(const UString &s1, const char *s2);\nvoid operator+(const char *s1, const UString &s2);\n\nvoid operator+(const UString &s, char c);\nvoid operator+(const UString &s, unsigned char c);\nvoid operator+(char c, const UString &s);\nvoid operator+(unsigned char c, const UString &s);\nvoid operator-(const UString &s1, wchar_t c);\n\n#ifdef _WIN32\n// can we forbid these functions, if wchar_t is 32-bit ?\nvoid operator+(const UString &s, int c);\nvoid operator+(const UString &s, unsigned c);\nvoid operator+(int c, const UString &s);\nvoid operator+(unsigned c, const UString &s);\nvoid operator-(const UString &s1, int c);\nvoid operator-(const UString &s1, unsigned c);\n#endif\n\n\n\n\n\n\n\nclass UString2\n{\n  wchar_t *_chars;\n  unsigned _len;\n\n  void ReAlloc2(unsigned newLimit);\n  void SetStartLen(unsigned len);\n\n  // ---------- forbidden functions ----------\n  \n  FORBID_STRING_OPS_UString2(char)\n  FORBID_STRING_OPS_UString2(signed char)\n  FORBID_STRING_OPS_UString2(unsigned char)\n  FORBID_STRING_OPS_UString2(short)\n\n  UString2 &operator=(wchar_t c);\n\n  UString2(const AString &s);\n  UString2 &operator=(const AString &s);\n  UString2 &operator+=(const AString &s);\n\n #ifdef DEBUG_FSTRING_INHERITS_ASTRING\n  UString2(const FString &s);\n  UString2 &operator=(const FString &s);\n  UString2 &operator+=(const FString &s);\n #endif\n\npublic:\n  UString2(): _chars(NULL), _len(0) {}\n  UString2(const wchar_t *s);\n  UString2(const UString2 &s);\n  ~UString2() { if (_chars) { MY_STRING_DELETE(_chars) } }\n\n  unsigned Len() const { return _len; }\n  bool IsEmpty() const { return _len == 0; }\n  // void Empty() { _len = 0; _chars[0] = 0; }\n\n  // operator const wchar_t *() const { return _chars; }\n  const wchar_t *GetRawPtr() const { return _chars; }\n\n  int Compare(const wchar_t *s) const { return wcscmp(_chars, s); }\n\n  wchar_t *GetBuf(unsigned minLen)\n  {\n    if (!_chars || minLen > _len)\n      ReAlloc2(minLen);\n    return _chars;\n  }\n  void ReleaseBuf_SetLen(unsigned newLen) { _len = newLen; }\n\n  UString2 &operator=(const wchar_t *s);\n  UString2 &operator=(const UString2 &s);\n  void SetFromAscii(const char *s);\n};\n\nbool operator==(const UString2 &s1, const UString2 &s2);\nbool operator==(const UString2 &s1, const wchar_t *s2);\nbool operator==(const wchar_t *s1, const UString2 &s2);\n\ninline bool operator!=(const UString2 &s1, const UString2 &s2) { return !(s1 == s2); }\ninline bool operator!=(const UString2 &s1, const wchar_t *s2) { return !(s1 == s2); }\ninline bool operator!=(const wchar_t *s1, const UString2 &s2) { return !(s1 == s2); }\n\n\n// ---------- forbidden functions ----------\n\nvoid operator==(wchar_t c1, const UString2 &s2);\nvoid operator==(const UString2 &s1, wchar_t c2);\nbool operator<(const UString2 &s1, const UString2 &s2);\nbool operator>(const UString2 &s1, const UString2 &s2);\n\nvoid operator+(const UString2 &s1, const UString2 &s2);\nvoid operator+(const UString2 &s1, const wchar_t *s2);\nvoid operator+(const wchar_t *s1, const UString2 &s2);\nvoid operator+(wchar_t c, const UString2 &s);\nvoid operator+(const UString2 &s, wchar_t c);\nvoid operator+(const UString2 &s, char c);\nvoid operator+(const UString2 &s, unsigned char c);\nvoid operator+(char c, const UString2 &s);\nvoid operator+(unsigned char c, const UString2 &s);\nvoid operator-(const UString2 &s1, wchar_t c);\n\n\n\n\n\n\ntypedef CObjectVector<AString> AStringVector;\ntypedef CObjectVector<UString> UStringVector;\n\n#ifdef _UNICODE\n  typedef UString CSysString;\n#else\n  typedef AString CSysString;\n#endif\n\ntypedef CObjectVector<CSysString> CSysStringVector;\n\n\n// ---------- FString ----------\n\n#ifndef DEBUG_FSTRING_INHERITS_ASTRING\n#ifdef _WIN32\n  #define USE_UNICODE_FSTRING\n#endif\n#endif\n\n#ifdef USE_UNICODE_FSTRING\n\n  #define MY_FTEXT(quote) L##quote\n\n  typedef wchar_t FChar;\n  typedef UString FString;\n\n  #define fs2us(_x_) (_x_)\n  #define us2fs(_x_) (_x_)\n  FString fas2fs(const char *s);\n  FString fas2fs(const AString &s);\n  AString fs2fas(const FChar *s);\n\n#else // USE_UNICODE_FSTRING\n\n  #define MY_FTEXT(quote) quote\n\n  typedef char FChar;\n\n #ifdef DEBUG_FSTRING_INHERITS_ASTRING\n\n  class FString: public AString\n  {\n    // FString &operator=(const char *s);\n    FString &operator=(const AString &s);\n    // FString &operator+=(const AString &s);\n  public:\n    FString(const AString &s): AString(s.Ptr()) {}\n    FString(const FString &s): AString(s.Ptr()) {}\n    FString(const char *s): AString(s) {}\n    FString() {}\n    FString &operator=(const FString &s)  { AString::operator=((const AString &)s); return *this; }\n    FString &operator=(char c) { AString::operator=(c); return *this; }\n    FString &operator+=(char c) { AString::operator+=(c); return *this; }\n    FString &operator+=(const FString &s) { AString::operator+=((const AString &)s); return *this; }\n    FString Left(unsigned count) const  { return FString(AString::Left(count)); }\n  };\n  void operator+(const AString &s1, const FString &s2);\n  void operator+(const FString &s1, const AString &s2);\n\n  inline FString operator+(const FString &s1, const FString &s2)\n  {\n    AString s =(const AString &)s1 + (const AString &)s2;\n    return FString(s.Ptr());\n    // return FString((const AString &)s1 + (const AString &)s2);\n  }\n  inline FString operator+(const FString &s1, const FChar *s2)\n  {\n    return s1 + (FString)s2;\n  }\n  /*\n  inline FString operator+(const FChar *s1, const FString &s2)\n  {\n    return (FString)s1 + s2;\n  }\n  */\n\n  inline FString fas2fs(const char *s)  { return FString(s); }\n\n #else // DEBUG_FSTRING_INHERITS_ASTRING\n  typedef AString FString;\n  #define fas2fs(_x_) (_x_)\n #endif // DEBUG_FSTRING_INHERITS_ASTRING\n\n  UString fs2us(const FChar *s);\n  UString fs2us(const FString &s);\n  FString us2fs(const wchar_t *s);\n  #define fs2fas(_x_) (_x_)\n\n#endif // USE_UNICODE_FSTRING\n\n#define FTEXT(quote) MY_FTEXT(quote)\n\n#define FCHAR_PATH_SEPARATOR FTEXT(CHAR_PATH_SEPARATOR)\n#define FSTRING_PATH_SEPARATOR FTEXT(STRING_PATH_SEPARATOR)\n\n// #define FCHAR_ANY_MASK FTEXT('*')\n// #define FSTRING_ANY_MASK FTEXT(\"*\")\n\ntypedef const FChar *CFSTR;\n\ntypedef CObjectVector<FString> FStringVector;\n\n\nclass CStringFinder\n{\n  AString _temp;\npublic:\n  // list - is list of low case Ascii strings separated by space \" \".\n  // the function returns true, if it can find exact word (str) in (list).\n  bool FindWord_In_LowCaseAsciiList_NoCase(const char *list, const wchar_t *str);\n};\n\nvoid SplitString(const UString &srcString, UStringVector &destStrings);\n\n// **************** 7-Zip ZS Modification Start ****************\n// #endif\n// **************** 7-Zip ZS Modification End ****************\n\n\n\n#if defined(_WIN32)\n  // #include <wchar.h>\n  // WCHAR_MAX is defined as ((wchar_t)-1)\n  #define Z7_WCHART_IS_16BIT 1\n#elif (defined(WCHAR_MAX) && (WCHAR_MAX <= 0xffff)) \\\n   || (defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ == 2))\n  #define Z7_WCHART_IS_16BIT 1\n#endif\n\n#if WCHAR_PATH_SEPARATOR == L'\\\\'\n// WSL scheme\n#define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT  ((wchar_t)((unsigned)(0xF000) + (unsigned)'\\\\'))\n// #define WCHAR_IN_FILE_NAME_BACKSLASH_REPLACEMENT  '_'\n#endif\n// **************** 7-Zip ZS Modification Start ****************\n\nUString GetQuotedString(const UString &s);\n\n#endif\n// **************** 7-Zip ZS Modification End ****************\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyTypes.h",
    "content": "﻿// Common/MyTypes.h\n\n#ifndef ZIP7_INC_COMMON_MY_TYPES_H\n#define ZIP7_INC_COMMON_MY_TYPES_H\n\n#include \"Common0.h\"\n#include \"../../C/7zTypes.h\"\n\n// typedef int HRes;\n// typedef HRESULT HRes;\n\nstruct CBoolPair\n{\n  bool Val;\n  bool Def;\n\n  CBoolPair(): Val(false), Def(false) {}\n  \n  void Init()\n  {\n    Val = false;\n    Def = false;\n  }\n\n  void SetTrueTrue()\n  {\n    Val = true;\n    Def = true;\n  }\n\n  void SetVal_as_Defined(bool val)\n  {\n    Val = val;\n    Def = true;\n  }\n};\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyUnknown.h",
    "content": "﻿// MyUnknown.h\n\n#ifndef ZIP7_INC_MY_UNKNOWN_H\n#define ZIP7_INC_MY_UNKNOWN_H\n\n#include \"MyWindows.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyVector.h",
    "content": "﻿// Common/MyVector.h\n\n#ifndef ZIP7_INC_COMMON_MY_VECTOR_H\n#define ZIP7_INC_COMMON_MY_VECTOR_H\n\n#include <string.h>\n\n#include \"Common.h\"\n\nconst unsigned k_VectorSizeMax = ((unsigned)1 << 31) - 1;\n\ntemplate <class T>\nclass CRecordVector\n{\n  T *_items;\n  unsigned _size;\n  unsigned _capacity;\n  \n  void MoveItems(unsigned destIndex, unsigned srcIndex)\n  {\n    memmove(_items + destIndex, _items + srcIndex, (size_t)(_size - srcIndex) * sizeof(T));\n  }\n\n  void ReAllocForNewCapacity(const unsigned newCapacity)\n  {\n    T *p;\n    Z7_ARRAY_NEW(p, T, newCapacity)\n    // p = new T[newCapacity];\n    if (_size != 0)\n      memcpy(p, _items, (size_t)_size * sizeof(T));\n    delete []_items;\n    _items = p;\n    _capacity = newCapacity;\n  }\n\npublic:\n\n  void ReserveOnePosition()\n  {\n    if (_size != _capacity)\n      return;\n    if (_capacity >= k_VectorSizeMax)\n      throw 2021;\n    const unsigned rem = k_VectorSizeMax - _capacity;\n    unsigned add = (_capacity >> 2) + 1;\n    if (add > rem)\n      add = rem;\n    ReAllocForNewCapacity(_capacity + add);\n  }\n\n  CRecordVector(): _items(NULL), _size(0), _capacity(0) {}\n  \n  CRecordVector(const CRecordVector &v): _items(NULL), _size(0), _capacity(0)\n  {\n    const unsigned size = v.Size();\n    if (size != 0)\n    {\n      // Z7_ARRAY_NEW(_items, T, size)\n      _items = new T[size];\n      _size = size;\n      _capacity = size;\n      memcpy(_items, v._items, (size_t)size * sizeof(T));\n    }\n  }\n  \n  unsigned Size() const { return _size; }\n  bool IsEmpty() const { return _size == 0; }\n  \n  void ConstructReserve(unsigned size)\n  {\n    if (size != 0)\n    {\n      Z7_ARRAY_NEW(_items, T, size)\n      // _items = new T[size];\n      _capacity = size;\n    }\n  }\n\n  void Reserve(unsigned newCapacity)\n  {\n    if (newCapacity > _capacity)\n    {\n      if (newCapacity > k_VectorSizeMax)\n        throw 2021;\n      ReAllocForNewCapacity(newCapacity);\n    }\n  }\n\n  void ChangeSize_KeepData(unsigned newSize)\n  {\n    Reserve(newSize);\n    _size = newSize;\n  }\n\n  void ClearAndReserve(unsigned newCapacity)\n  {\n    Clear();\n    if (newCapacity > _capacity)\n    {\n      if (newCapacity > k_VectorSizeMax)\n        throw 2021;\n      delete []_items;\n      _items = NULL;\n      _capacity = 0;\n      Z7_ARRAY_NEW(_items, T, newCapacity)\n      // _items = new T[newCapacity];\n      _capacity = newCapacity;\n    }\n  }\n\n  void ClearAndSetSize(unsigned newSize)\n  {\n    ClearAndReserve(newSize);\n    _size = newSize;\n  }\n\n  void ReserveDown()\n  {\n    if (_size == _capacity)\n      return;\n    T *p = NULL;\n    if (_size != 0)\n    {\n      // Z7_ARRAY_NEW(p, T, _size)\n      p = new T[_size];\n      memcpy(p, _items, (size_t)_size * sizeof(T));\n    }\n    delete []_items;\n    _items = p;\n    _capacity = _size;\n  }\n  \n  ~CRecordVector() { delete []_items; }\n  \n  void ClearAndFree()\n  {\n    delete []_items;\n    _items = NULL;\n    _size = 0;\n    _capacity = 0;\n  }\n  \n  void Clear() { _size = 0; }\n\n  void DeleteBack() { _size--; }\n  \n  void DeleteFrom(unsigned index)\n  {\n    // if (index <= _size)\n      _size = index;\n  }\n  \n  void DeleteFrontal(unsigned num)\n  {\n    if (num != 0)\n    {\n      MoveItems(0, num);\n      _size -= num;\n    }\n  }\n\n  void Delete(unsigned index)\n  {\n    MoveItems(index, index + 1);\n    _size -= 1;\n  }\n\n  /*\n  void Delete(unsigned index, unsigned num)\n  {\n    if (num > 0)\n    {\n      MoveItems(index, index + num);\n      _size -= num;\n    }\n  }\n  */\n\n  CRecordVector& operator=(const CRecordVector &v)\n  {\n    if (&v == this)\n      return *this;\n    const unsigned size = v.Size();\n    if (size > _capacity)\n    {\n      delete []_items;\n      _capacity = 0;\n      _size = 0;\n      _items = NULL;\n      _items = new T[size];\n      _capacity = size;\n    }\n    _size = size;\n    if (size != 0)\n      memcpy(_items, v._items, (size_t)size * sizeof(T));\n    return *this;\n  }\n\n  CRecordVector& operator+=(const CRecordVector &v)\n  {\n    const unsigned size = v.Size();\n    if (size != 0)\n    {\n      if (_size >= k_VectorSizeMax || size > k_VectorSizeMax - _size)\n        throw 2021;\n      const unsigned newSize = _size + size;\n      Reserve(newSize);\n      memcpy(_items + _size, v._items, (size_t)size * sizeof(T));\n      _size = newSize;\n    }\n    return *this;\n  }\n  \n  unsigned Add(const T item)\n  {\n    ReserveOnePosition();\n    const unsigned size = _size;\n    _size = size + 1;\n    _items[size] = item;\n    return size;\n  }\n\n  /*\n  unsigned Add2(const T &item)\n  {\n    ReserveOnePosition();\n    const unsigned size = _size;\n    _size = size + 1;\n    _items[size] = item;\n    return size;\n  }\n  */\n\n  unsigned AddInReserved(const T item)\n  {\n    const unsigned size = _size;\n    _size = size + 1;\n    _items[size] = item;\n    return size;\n  }\n\n  void Insert(unsigned index, const T item)\n  {\n    ReserveOnePosition();\n    MoveItems(index + 1, index);\n    _items[index] = item;\n    _size++;\n  }\n\n  void InsertInReserved(unsigned index, const T item)\n  {\n    MoveItems(index + 1, index);\n    _items[index] = item;\n    _size++;\n  }\n\n  void MoveToFront(unsigned index)\n  {\n    if (index != 0)\n    {\n      const T temp = _items[index];\n      memmove(_items + 1, _items, (size_t)index * sizeof(T));\n      _items[0] = temp;\n    }\n  }\n\n  const T& operator[](unsigned index) const { return _items[index]; }\n        T& operator[](unsigned index)       { return _items[index]; }\n  const T& operator[](int index) const { return _items[(unsigned)index]; }\n        T& operator[](int index)       { return _items[(unsigned)index]; }\n\n  const T* ConstData()    const { return _items; }\n        T* NonConstData() const { return _items; }\n        T* NonConstData()       { return _items; }\n\n  const T* Data() const         { return _items; }\n        T* Data()               { return _items; }\n\n  const T& FrontItem() const { return _items[0]; }\n        T& FrontItem()       { return _items[0]; }\n  /*\n  const T Front() const { return _items[0]; }\n        T Front()       { return _items[0]; }\n  const T& Front() const { return _items[0]; }\n        T& Front()       { return _items[0]; }\n  */\n  const T& Back() const  { return _items[(size_t)_size - 1]; }\n        T& Back()        { return _items[(size_t)_size - 1]; }\n\n  /*\n  void Swap(unsigned i, unsigned j)\n  {\n    const T temp = _items[i];\n    _items[i] = _items[j];\n    _items[j] = temp;\n  }\n  */\n\n  int FindInSorted(const T item, unsigned left, unsigned right) const\n  {\n    while (left != right)\n    {\n      // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const unsigned mid = (left + right) / 2;\n      const T midVal = (*this)[mid];\n      if (item == midVal)\n        return (int)mid;\n      if (item < midVal)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    return -1;\n  }\n\n  int FindInSorted2(const T &item, unsigned left, unsigned right) const\n  {\n    while (left != right)\n    {\n      // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const unsigned mid = (left + right) / 2;\n      const T& midVal = (*this)[mid];\n      const int comp = item.Compare(midVal);\n      if (comp == 0)\n        return (int)mid;\n      if (comp < 0)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    return -1;\n  }\n\n  int FindInSorted(const T item) const\n  {\n    return FindInSorted(item, 0, _size);\n  }\n\n  int FindInSorted2(const T &item) const\n  {\n    return FindInSorted2(item, 0, _size);\n  }\n\n  unsigned AddToUniqueSorted(const T item)\n  {\n    unsigned left = 0, right = _size;\n    while (left != right)\n    {\n      // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const unsigned mid = (left + right) / 2;\n      const T midVal = (*this)[mid];\n      if (item == midVal)\n        return mid;\n      if (item < midVal)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    Insert(right, item);\n    return right;\n  }\n\n  unsigned AddToUniqueSorted2(const T &item)\n  {\n    unsigned left = 0, right = _size;\n    while (left != right)\n    {\n      // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const unsigned mid = (left + right) / 2;\n      const T& midVal = (*this)[mid];\n      const int comp = item.Compare(midVal);\n      if (comp == 0)\n        return mid;\n      if (comp < 0)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    Insert(right, item);\n    return right;\n  }\n\n  static void SortRefDown(T* p, unsigned k, unsigned size, int (*compare)(const T*, const T*, void *), void *param)\n  {\n    const T temp = p[k];\n    for (;;)\n    {\n      unsigned s = (k << 1);\n      if (s > size)\n        break;\n      if (s < size && compare(p + s + 1, p + s, param) > 0)\n        s++;\n      if (compare(&temp, p + s, param) >= 0)\n        break;\n      p[k] = p[s];\n      k = s;\n    }\n    p[k] = temp;\n  }\n\n  void Sort(int (*compare)(const T*, const T*, void *), void *param)\n  {\n    unsigned size = _size;\n    if (size <= 1)\n      return;\n    T* p = _items - 1;\n    {\n      unsigned i = size >> 1;\n      do\n        SortRefDown(p, i, size, compare, param);\n      while (--i);\n    }\n    do\n    {\n      const T temp = p[size];\n      p[size--] = p[1];\n      p[1] = temp;\n      SortRefDown(p, 1, size, compare, param);\n    }\n    while (size > 1);\n  }\n\n  static void SortRefDown2(T* p, unsigned k, unsigned size)\n  {\n    const T temp = p[k];\n    for (;;)\n    {\n      unsigned s = (k << 1);\n      if (s > size)\n        break;\n      if (s < size && p[(size_t)s + 1].Compare(p[s]) > 0)\n        s++;\n      if (temp.Compare(p[s]) >= 0)\n        break;\n      p[k] = p[s];\n      k = s;\n    }\n    p[k] = temp;\n  }\n\n  void Sort2()\n  {\n    unsigned size = _size;\n    if (size <= 1)\n      return;\n    T* p = _items - 1;\n    {\n      unsigned i = size >> 1;\n      do\n        SortRefDown2(p, i, size);\n      while (--i);\n    }\n    do\n    {\n      const T temp = p[size];\n      p[size--] = p[1];\n      p[1] = temp;\n      SortRefDown2(p, 1, size);\n    }\n    while (size > 1);\n  }\n};\n\ntypedef CRecordVector<int> CIntVector;\ntypedef CRecordVector<unsigned int> CUIntVector;\ntypedef CRecordVector<bool> CBoolVector;\ntypedef CRecordVector<unsigned char> CByteVector;\ntypedef CRecordVector<void *> CPointerVector;\n\ntemplate <class T>\nclass CObjectVector\n{\n  CPointerVector _v;\npublic:\n  unsigned Size() const { return _v.Size(); }\n  bool IsEmpty() const { return _v.IsEmpty(); }\n  void ReserveDown() { _v.ReserveDown(); }\n  // void Reserve(unsigned newCapacity) { _v.Reserve(newCapacity); }\n  void ClearAndReserve(unsigned newCapacity) { Clear(); _v.ClearAndReserve(newCapacity); }\n\n  CObjectVector() {}\n  CObjectVector(const CObjectVector &v)\n  {\n    const unsigned size = v.Size();\n    _v.ConstructReserve(size);\n    for (unsigned i = 0; i < size; i++)\n      AddInReserved(v[i]);\n  }\n  CObjectVector& operator=(const CObjectVector &v)\n  {\n    if (&v == this)\n      return *this;\n    Clear();\n    const unsigned size = v.Size();\n    _v.Reserve(size);\n    for (unsigned i = 0; i < size; i++)\n      AddInReserved(v[i]);\n    return *this;\n  }\n\n  CObjectVector& operator+=(const CObjectVector &v)\n  {\n    const unsigned addSize = v.Size();\n    if (addSize != 0)\n    {\n      const unsigned size = Size();\n      if (size >= k_VectorSizeMax || addSize > k_VectorSizeMax - size)\n        throw 2021;\n      _v.Reserve(size + addSize);\n      for (unsigned i = 0; i < addSize; i++)\n        AddInReserved(v[i]);\n    }\n    return *this;\n  }\n  \n  const T& operator[](unsigned index) const { return *((T *)_v[index]); }\n        T& operator[](unsigned index)       { return *((T *)_v[index]); }\n  const T& operator[](int index) const { return *((T *)_v[(unsigned)index]); }\n        T& operator[](int index)       { return *((T *)_v[(unsigned)index]); }\n  const T& Front() const { return operator[](0); }\n        T& Front()       { return operator[](0); }\n  const T& Back() const  { return *(T *)_v.Back(); }\n        T& Back()        { return *(T *)_v.Back(); }\n  \n  void MoveToFront(unsigned index) { _v.MoveToFront(index); }\n\n  unsigned Add(const T& item)\n  {\n    _v.ReserveOnePosition();\n    return AddInReserved(item);\n  }\n  \n  unsigned AddInReserved(const T& item)\n  {\n    return _v.AddInReserved(new T(item));\n  }\n\n  void ReserveOnePosition()\n  {\n    _v.ReserveOnePosition();\n  }\n\n  unsigned AddInReserved_Ptr_of_new(T *ptr)\n  {\n    return _v.AddInReserved(ptr);\n  }\n\n  #define VECTOR_ADD_NEW_OBJECT(v, a) \\\n    (v).ReserveOnePosition(); \\\n    (v).AddInReserved_Ptr_of_new(new a);\n  \n  \n  T& AddNew()\n  {\n    _v.ReserveOnePosition();\n    T *p = new T;\n    _v.AddInReserved(p);\n    return *p;\n  }\n  \n  T& AddNewInReserved()\n  {\n    T *p = new T;\n    _v.AddInReserved(p);\n    return *p;\n  }\n  \n  void Insert(unsigned index, const T& item)\n  {\n    _v.ReserveOnePosition();\n    _v.InsertInReserved(index, new T(item));\n  }\n  \n  T& InsertNew(unsigned index)\n  {\n    _v.ReserveOnePosition();\n    T *p = new T;\n    _v.InsertInReserved(index, p);\n    return *p;\n  }\n\n  ~CObjectVector()\n  {\n    for (unsigned i = _v.Size(); i != 0;)\n      delete (T *)_v[--i];\n  }\n  \n  void ClearAndFree()\n  {\n    Clear();\n    _v.ClearAndFree();\n  }\n  \n  void Clear()\n  {\n    for (unsigned i = _v.Size(); i != 0;)\n      delete (T *)_v[--i];\n    _v.Clear();\n  }\n  \n  void DeleteFrom(unsigned index)\n  {\n    const unsigned size = _v.Size();\n    for (unsigned i = index; i < size; i++)\n      delete (T *)_v[i];\n    _v.DeleteFrom(index);\n  }\n\n  void DeleteFrontal(unsigned num)\n  {\n    for (unsigned i = 0; i < num; i++)\n      delete (T *)_v[i];\n    _v.DeleteFrontal(num);\n  }\n\n  void DeleteBack()\n  {\n    delete (T *)_v.Back();\n    _v.DeleteBack();\n  }\n\n  void Delete(unsigned index)\n  {\n    delete (T *)_v[index];\n    _v.Delete(index);\n  }\n  // void Delete(int index) { Delete((unsigned)index); }\n\n  /*\n  void Delete(unsigned index, unsigned num)\n  {\n    for (unsigned i = 0; i < num; i++)\n      delete (T *)_v[index + i];\n    _v.Delete(index, num);\n  }\n  */\n\n  /*\n  int Find(const T& item) const\n  {\n    unsigned size = Size();\n    for (unsigned i = 0; i < size; i++)\n      if (item == (*this)[i])\n        return i;\n    return -1;\n  }\n  */\n  \n  int FindInSorted(const T& item) const\n  {\n    unsigned left = 0, right = Size();\n    while (left != right)\n    {\n      // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const unsigned mid = (left + right) / 2;\n      const T& midVal = (*this)[mid];\n      const int comp = item.Compare(midVal);\n      if (comp == 0)\n        return (int)mid;\n      if (comp < 0)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    return -1;\n  }\n\n  unsigned AddToUniqueSorted(const T& item)\n  {\n    unsigned left = 0, right = Size();\n    while (left != right)\n    {\n      // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const unsigned mid = (left + right) / 2;\n      const T& midVal = (*this)[mid];\n      const int comp = item.Compare(midVal);\n      if (comp == 0)\n        return mid;\n      if (comp < 0)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    Insert(right, item);\n    return right;\n  }\n\n  /*\n  unsigned AddToSorted(const T& item)\n  {\n    unsigned left = 0, right = Size();\n    while (left != right)\n    {\n      // const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);\n      const unsigned mid = (left + right) / 2;\n      const T& midVal = (*this)[mid];\n      const int comp = item.Compare(midVal);\n      if (comp == 0)\n      {\n        right = mid + 1;\n        break;\n      }\n      if (comp < 0)\n        right = mid;\n      else\n        left = mid + 1;\n    }\n    Insert(right, item);\n    return right;\n  }\n  */\n\n  void Sort(int (*compare)(void *const *, void *const *, void *), void *param)\n    { _v.Sort(compare, param); }\n\n  static int CompareObjectItems(void *const *a1, void *const *a2, void * /* param */)\n    { return (*(*((const T *const *)a1))).Compare(*(*((const T *const *)a2))); }\n\n  void Sort() { _v.Sort(CompareObjectItems, NULL); }\n};\n\n#define FOR_VECTOR(_i_, _v_) for (unsigned _i_ = 0; _i_ < (_v_).Size(); _i_++)\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyWindows.h",
    "content": "﻿// MyWindows.h\n\n#ifdef Z7_DEFINE_GUID\n#undef Z7_DEFINE_GUID\n#endif\n\n#ifdef INITGUID\n  #define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\\n    EXTERN_C const GUID name; \\\n    EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }\n#else\n  #define Z7_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \\\n    EXTERN_C const GUID name\n#endif\n\n\n#ifndef ZIP7_INC_MY_WINDOWS_H\n#define ZIP7_INC_MY_WINDOWS_H\n\n#ifdef _WIN32\n\n#include \"../../C/7zWindows.h\"\n\n#else // _WIN32\n\n#include <stddef.h> // for wchar_t\n#include <string.h>\n// #include <stdint.h> // for uintptr_t\n\n#include \"../../C/7zTypes.h\"\n#include \"MyGuidDef.h\"\n\n// WINAPI is __stdcall in Windows-MSVC in windef.h\n#define WINAPI\n\ntypedef char CHAR;\ntypedef unsigned char UCHAR;\n\n#undef BYTE\ntypedef unsigned char BYTE;\n\ntypedef short SHORT;\ntypedef unsigned short USHORT;\n\n#undef WORD\ntypedef unsigned short WORD;\ntypedef short VARIANT_BOOL;\n\n#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff))\n#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16))\n\n// MS uses long for BOOL, but long is 32-bit in MS. So we use int.\n// typedef long BOOL;\ntypedef int BOOL;\n\n#ifndef FALSE\n  #define FALSE 0\n  #define TRUE 1\n#endif\n\n// typedef size_t ULONG_PTR;\n// typedef size_t DWORD_PTR;\n// typedef uintptr_t UINT_PTR;\n// typedef ptrdiff_t UINT_PTR;\n\ntypedef Int64 LONGLONG;\ntypedef UInt64 ULONGLONG;\n\ntypedef struct { LONGLONG QuadPart; } LARGE_INTEGER;\ntypedef struct { ULONGLONG QuadPart; } ULARGE_INTEGER;\n\ntypedef const CHAR *LPCSTR;\ntypedef CHAR TCHAR;\ntypedef const TCHAR *LPCTSTR;\ntypedef wchar_t WCHAR;\ntypedef WCHAR OLECHAR;\ntypedef const WCHAR *LPCWSTR;\ntypedef OLECHAR *BSTR;\ntypedef const OLECHAR *LPCOLESTR;\ntypedef OLECHAR *LPOLESTR;\n\ntypedef struct\n{\n  DWORD dwLowDateTime;\n  DWORD dwHighDateTime;\n} FILETIME;\n\n#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)\n#define FAILED(hr)    ((HRESULT)(hr) < 0)\ntypedef ULONG PROPID;\ntypedef LONG SCODE;\n\n\n#define S_OK    ((HRESULT)0x00000000L)\n#define S_FALSE ((HRESULT)0x00000001L)\n#define E_NOTIMPL     ((HRESULT)0x80004001L)\n#define E_NOINTERFACE ((HRESULT)0x80004002L)\n#define E_ABORT       ((HRESULT)0x80004004L)\n#define E_FAIL        ((HRESULT)0x80004005L)\n#define STG_E_INVALIDFUNCTION     ((HRESULT)0x80030001L)\n#define CLASS_E_CLASSNOTAVAILABLE ((HRESULT)0x80040111L)\n\n\n#ifdef _MSC_VER\n#define STDMETHODCALLTYPE __stdcall\n#define STDAPICALLTYPE    __stdcall\n#else\n// do we need __export here?\n#define STDMETHODCALLTYPE\n#define STDAPICALLTYPE\n#endif\n\n#define STDAPI  EXTERN_C HRESULT STDAPICALLTYPE\n\n#ifndef DECLSPEC_NOTHROW\n#define DECLSPEC_NOTHROW    Z7_DECLSPEC_NOTHROW\n#endif\n\n#ifndef DECLSPEC_NOVTABLE\n#define DECLSPEC_NOVTABLE   Z7_DECLSPEC_NOVTABLE\n#endif\n\n#ifndef COM_DECLSPEC_NOTHROW\n#ifdef COM_STDMETHOD_CAN_THROW\n  #define COM_DECLSPEC_NOTHROW\n#else\n  #define COM_DECLSPEC_NOTHROW  DECLSPEC_NOTHROW\n#endif\n#endif\n\n#define DECLARE_INTERFACE(iface)              struct DECLSPEC_NOVTABLE iface\n#define DECLARE_INTERFACE_(iface, baseiface)  struct DECLSPEC_NOVTABLE iface : public baseiface\n\n#define STDMETHOD_(t, f)  virtual COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE f\n#define STDMETHOD(f)      STDMETHOD_(HRESULT, f)\n#define STDMETHODIMP_(t)  COM_DECLSPEC_NOTHROW t STDMETHODCALLTYPE\n#define STDMETHODIMP      STDMETHODIMP_(HRESULT)\n\n\n#define PURE = 0\n\n// #define MIDL_INTERFACE(x) struct\n\n\n#ifdef __cplusplus\n\n/*\n  p7zip and 7-Zip before v23 used virtual destructor in IUnknown,\n  if _WIN32 is not defined.\n  It used virtual destructor, because some compilers don't like virtual\n  interfaces without virtual destructor.\n  IUnknown in Windows (_WIN32) doesn't use virtual destructor in IUnknown.\n  We still can define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here,\n  if we want to be compatible with old plugin interface of p7zip and 7-Zip before v23.\n\nv23:\n  In new 7-Zip v23 we try to be more compatible with original IUnknown from _WIN32.\n  So we do not define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN here,\n*/\n// #define Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN\n\n#ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN\n#if defined(__clang__)\n#pragma GCC diagnostic ignored \"-Winconsistent-missing-destructor-override\"\n#endif\n#endif\n\nZ7_PURE_INTERFACES_BEGIN\n\nDEFINE_GUID(IID_IUnknown,\n0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);\nstruct IUnknown\n{\n  STDMETHOD(QueryInterface) (REFIID iid, void **outObject) =0;\n  STDMETHOD_(ULONG, AddRef)() =0;\n  STDMETHOD_(ULONG, Release)() =0;\n #ifdef Z7_USE_VIRTUAL_DESTRUCTOR_IN_IUNKNOWN\n  virtual ~IUnknown() {}\n #endif\n};\n\ntypedef IUnknown *LPUNKNOWN;\n\nZ7_PURE_INTERFACES_END\n\n#endif // __cplusplus\n\n#define VARIANT_TRUE ((VARIANT_BOOL)-1)\n#define VARIANT_FALSE ((VARIANT_BOOL)0)\n\nenum VARENUM\n{\n  VT_EMPTY = 0,\n  VT_NULL = 1,\n  VT_I2 = 2,\n  VT_I4 = 3,\n  VT_R4 = 4,\n  VT_R8 = 5,\n  VT_CY = 6,\n  VT_DATE = 7,\n  VT_BSTR = 8,\n  VT_DISPATCH = 9,\n  VT_ERROR = 10,\n  VT_BOOL = 11,\n  VT_VARIANT = 12,\n  VT_UNKNOWN = 13,\n  VT_DECIMAL = 14,\n\n  VT_I1 = 16,\n  VT_UI1 = 17,\n  VT_UI2 = 18,\n  VT_UI4 = 19,\n  VT_I8 = 20,\n  VT_UI8 = 21,\n  VT_INT = 22,\n  VT_UINT = 23,\n  VT_VOID = 24,\n  VT_HRESULT = 25,\n  VT_FILETIME = 64\n};\n\ntypedef unsigned short VARTYPE;\ntypedef WORD PROPVAR_PAD1;\ntypedef WORD PROPVAR_PAD2;\ntypedef WORD PROPVAR_PAD3;\n\ntypedef struct tagPROPVARIANT\n{\n  VARTYPE vt;\n  PROPVAR_PAD1 wReserved1;\n  PROPVAR_PAD2 wReserved2;\n  PROPVAR_PAD3 wReserved3;\n  union\n  {\n    CHAR cVal;\n    UCHAR bVal;\n    SHORT iVal;\n    USHORT uiVal;\n    LONG lVal;\n    ULONG ulVal;\n    INT intVal;\n    UINT uintVal;\n    LARGE_INTEGER hVal;\n    ULARGE_INTEGER uhVal;\n    VARIANT_BOOL boolVal;\n    SCODE scode;\n    FILETIME filetime;\n    BSTR bstrVal;\n  };\n} PROPVARIANT;\n\ntypedef PROPVARIANT tagVARIANT;\ntypedef tagVARIANT VARIANT;\ntypedef VARIANT VARIANTARG;\n\nEXTERN_C HRESULT VariantClear(VARIANTARG *prop);\nEXTERN_C HRESULT VariantCopy(VARIANTARG *dest, const VARIANTARG *src);\n\ntypedef struct tagSTATPROPSTG\n{\n  LPOLESTR lpwstrName;\n  PROPID propid;\n  VARTYPE vt;\n} STATPROPSTG;\n\nEXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len);\nEXTERN_C BSTR SysAllocStringLen(const OLECHAR *sz, UINT len);\nEXTERN_C BSTR SysAllocString(const OLECHAR *sz);\nEXTERN_C void SysFreeString(BSTR bstr);\nEXTERN_C UINT SysStringByteLen(BSTR bstr);\nEXTERN_C UINT SysStringLen(BSTR bstr);\n\nEXTERN_C DWORD GetLastError();\nEXTERN_C void SetLastError(DWORD dwCode);\nEXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2);\n\nEXTERN_C DWORD GetCurrentThreadId();\nEXTERN_C DWORD GetCurrentProcessId();\n\n#define MAX_PATH 1024\n\n#define CP_ACP    0\n#define CP_OEMCP  1\n#define CP_UTF8   65001\n\ntypedef enum tagSTREAM_SEEK\n{\n  STREAM_SEEK_SET = 0,\n  STREAM_SEEK_CUR = 1,\n  STREAM_SEEK_END = 2\n} STREAM_SEEK;\n\n\n\ntypedef struct\n{\n  WORD wYear;\n  WORD wMonth;\n  WORD wDayOfWeek;\n  WORD wDay;\n  WORD wHour;\n  WORD wMinute;\n  WORD wSecond;\n  WORD wMilliseconds;\n} SYSTEMTIME;\n\nBOOL WINAPI FileTimeToLocalFileTime(const FILETIME *fileTime, FILETIME *localFileTime);\nBOOL WINAPI LocalFileTimeToFileTime(const FILETIME *localFileTime, FILETIME *fileTime);\nBOOL WINAPI FileTimeToSystemTime(const FILETIME *fileTime, SYSTEMTIME *systemTime);\n// VOID WINAPI GetSystemTimeAsFileTime(FILETIME *systemTimeAsFileTime);\n\nDWORD GetTickCount();\n\n\n/*\n#define CREATE_NEW          1\n#define CREATE_ALWAYS       2\n#define OPEN_EXISTING       3\n#define OPEN_ALWAYS         4\n#define TRUNCATE_EXISTING   5\n*/\n\n#endif // _WIN32\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyXml.cpp",
    "content": "﻿// MyXml.cpp\n\n#include \"StdAfx.h\"\n\n#include \"MyXml.h\"\n#include \"StringToInt.h\"\n\nstatic bool IsValidChar(char c)\n{\n  return\n    (c >= 'a' && c <= 'z') ||\n    (c >= 'A' && c <= 'Z') ||\n    (c >= '0' && c <= '9') ||\n    c == '-';\n}\n\nstatic bool IsSpaceChar(char c)\n{\n  return (c == ' ' || c == '\\t' || c == 0x0D || c == 0x0A);\n}\n\n#define SKIP_SPACES(s) while (IsSpaceChar(*s)) s++;\n\nint CXmlItem::FindProp(const char *propName) const throw()\n{\n  FOR_VECTOR (i, Props)\n    if (Props[i].Name.IsEqualTo(propName))\n      return (int)i;\n  return -1;\n}\n\nAString CXmlItem::GetPropVal(const char *propName) const\n{\n  const int index = FindProp(propName);\n  if (index >= 0)\n    return Props[(unsigned)index].Value;\n  return AString();\n}\n\nbool CXmlItem::IsTagged(const char *tag) const throw()\n{\n  return (IsTag && Name.IsEqualTo(tag));\n}\n\nint CXmlItem::FindSubTag(const char *tag) const throw()\n{\n  FOR_VECTOR (i, SubItems)\n    if (SubItems[i].IsTagged(tag))\n      return (int)i;\n  return -1;\n}\n\nconst CXmlItem *CXmlItem::FindSubTag_GetPtr(const char *tag) const throw()\n{\n  FOR_VECTOR (i, SubItems)\n  {\n    const CXmlItem *p = &SubItems[i];\n    if (p->IsTagged(tag))\n      return p;\n  }\n  return NULL;\n}\n\nAString CXmlItem::GetSubString() const\n{\n  if (SubItems.Size() == 1)\n  {\n    const CXmlItem &item = SubItems[0];\n    if (!item.IsTag)\n      return item.Name;\n  }\n  return AString();\n}\n\nconst AString * CXmlItem::GetSubStringPtr() const throw()\n{\n  if (SubItems.Size() == 1)\n  {\n    const CXmlItem &item = SubItems[0];\n    if (!item.IsTag)\n      return &item.Name;\n  }\n  return NULL;\n}\n\nAString CXmlItem::GetSubStringForTag(const char *tag) const\n{\n  const CXmlItem *item = FindSubTag_GetPtr(tag);\n  if (item)\n    return item->GetSubString();\n  return AString();\n}\n\nconst char * CXmlItem::ParseItem(const char *s, int numAllowedLevels)\n{\n  SKIP_SPACES(s)\n\n  const char *beg = s;\n  for (;;)\n  {\n    char c;\n    c = *s; if (c == 0 || c == '<') break; s++;\n    c = *s; if (c == 0 || c == '<') break; s++;\n  }\n  if (*s == 0)\n    return NULL;\n  {\n    const size_t num = (size_t)(s - beg);\n    if (num)\n    {\n      IsTag = false;\n      Name.SetFrom_Chars_SizeT(beg, num);\n      return s;\n    }\n  }\n  \n  IsTag = true;\n\n  s++;\n  SKIP_SPACES(s)\n\n  beg = s;\n  for (;; s++)\n    if (!IsValidChar(*s))\n      break;\n  if (s == beg || *s == 0)\n    return NULL;\n  Name.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));\n\n  for (;;)\n  {\n    beg = s;\n    SKIP_SPACES(s)\n    if (*s == '/')\n    {\n      s++;\n      // SKIP_SPACES(s)\n      if (*s != '>')\n        return NULL;\n      return s + 1;\n    }\n    if (*s == '>')\n    {\n      s++;\n      if (numAllowedLevels == 0)\n        return NULL;\n      SubItems.Clear();\n      for (;;)\n      {\n        SKIP_SPACES(s)\n        if (s[0] == '<' && s[1] == '/')\n          break;\n        CXmlItem &item = SubItems.AddNew();\n        s = item.ParseItem(s, numAllowedLevels - 1);\n        if (!s)\n          return NULL;\n      }\n\n      s += 2;\n      const unsigned len = Name.Len();\n      const char *name = Name.Ptr();\n      for (unsigned i = 0; i < len; i++)\n        if (*s++ != *name++)\n          return NULL;\n      // s += len;\n      if (s[0] != '>')\n        return NULL;\n      return s + 1;\n    }\n    if (beg == s)\n      return NULL;\n\n    // ReadProperty\n    CXmlProp &prop = Props.AddNew();\n\n    beg = s;\n    for (;; s++)\n    {\n      char c = *s;\n      if (!IsValidChar(c))\n        break;\n    }\n    if (s == beg)\n      return NULL;\n    prop.Name.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));\n    \n    SKIP_SPACES(s)\n    if (*s != '=')\n      return NULL;\n    s++;\n    SKIP_SPACES(s)\n    if (*s != '\\\"')\n      return NULL;\n    s++;\n    \n    beg = s;\n    for (;;)\n    {\n      char c = *s;\n      if (c == 0)\n        return NULL;\n      if (c == '\\\"')\n        break;\n      s++;\n    }\n    prop.Value.SetFrom_Chars_SizeT(beg, (size_t)(s - beg));\n    s++;\n  }\n}\n\nstatic const char * SkipHeader(const char *s, const char *startString, const char *endString)\n{\n  SKIP_SPACES(s)\n  if (IsString1PrefixedByString2(s, startString))\n  {\n    s = strstr(s, endString);\n    if (!s)\n      return NULL;\n    s += strlen(endString);\n  }\n  return s;\n}\n\nvoid CXmlItem::AppendTo(AString &s) const\n{\n  if (IsTag)\n    s += '<';\n  s += Name;\n  if (IsTag)\n  {\n    FOR_VECTOR (i, Props)\n    {\n      const CXmlProp &prop = Props[i];\n      s.Add_Space();\n      s += prop.Name;\n      s += '=';\n      s += '\\\"';\n      s += prop.Value;\n      s += '\\\"';\n    }\n    s += '>';\n  }\n  FOR_VECTOR (i, SubItems)\n  {\n    const CXmlItem &item = SubItems[i];\n    if (i != 0 && !SubItems[i - 1].IsTag)\n      s.Add_Space();\n    item.AppendTo(s);\n  }\n  if (IsTag)\n  {\n    s += '<';\n    s += '/';\n    s += Name;\n    s += '>';\n  }\n}\n\nbool CXml::Parse(const char *s)\n{\n  s = SkipHeader(s, \"<?xml\",    \"?>\"); if (!s) return false;\n  s = SkipHeader(s, \"<!DOCTYPE\", \">\"); if (!s) return false;\n\n  s = Root.ParseItem(s, 1000);\n  if (!s || !Root.IsTag)\n    return false;\n  SKIP_SPACES(s)\n  return *s == 0;\n}\n\n/*\nvoid CXml::AppendTo(AString &s) const\n{\n  Root.AppendTo(s);\n}\n*/\n\n\nvoid z7_xml_DecodeString(AString &temp)\n{\n  char * const beg = temp.GetBuf();\n  char *dest = beg;\n  const char *p = beg;\n  for (;;)\n  {\n    char c = *p++;\n    if (c == 0)\n      break;\n    if (c == '&')\n    {\n      if (p[0] == '#')\n      {\n        const char *end;\n        const UInt32 number = ConvertStringToUInt32(p + 1, &end);\n        if (*end == ';' && number != 0 && number <= 127)\n        {\n          p = end + 1;\n          c = (char)number;\n        }\n      }\n      else if (\n          p[0] == 'a' &&\n          p[1] == 'm' &&\n          p[2] == 'p' &&\n          p[3] == ';')\n      {\n        p += 4;\n      }\n      else if (\n          p[0] == 'l' &&\n          p[1] == 't' &&\n          p[2] == ';')\n      {\n        p += 3;\n        c = '<';\n      }\n      else if (\n          p[0] == 'g' &&\n          p[1] == 't' &&\n          p[2] == ';')\n      {\n        p += 3;\n        c = '>';\n      }\n      else if (\n          p[0] == 'a' &&\n          p[1] == 'p' &&\n          p[2] == 'o' &&\n          p[3] == 's' &&\n          p[4] == ';')\n      {\n        p += 5;\n        c = '\\'';\n      }\n      else if (\n          p[0] == 'q' &&\n          p[1] == 'u' &&\n          p[2] == 'o' &&\n          p[3] == 't' &&\n          p[4] == ';')\n      {\n        p += 5;\n        c = '\\\"';\n      }\n    }\n    *dest++ = c;\n  }\n  temp.ReleaseBuf_SetEnd((unsigned)(dest - beg));\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/MyXml.h",
    "content": "﻿// MyXml.h\n\n#ifndef ZIP7_INC_MY_XML_H\n#define ZIP7_INC_MY_XML_H\n\n#include \"MyString.h\"\n\nstruct CXmlProp\n{\n  AString Name;\n  AString Value;\n};\n\nclass CXmlItem\n{\npublic:\n  AString Name;\n  bool IsTag;\n  CObjectVector<CXmlProp> Props;\n  CObjectVector<CXmlItem> SubItems;\n  \n  const char * ParseItem(const char *s, int numAllowedLevels);\n\n  bool IsTagged(const char *tag) const throw();\n  int FindProp(const char *propName) const throw();\n  AString GetPropVal(const char *propName) const;\n  AString GetSubString() const;\n  const AString * GetSubStringPtr() const throw();\n  int FindSubTag(const char *tag) const throw();\n  const CXmlItem *FindSubTag_GetPtr(const char *tag) const throw();\n  AString GetSubStringForTag(const char *tag) const;\n  void AppendTo(AString &s) const;\n};\n\nstruct CXml\n{\n  CXmlItem Root;\n\n  bool Parse(const char *s);\n  // void AppendTo(AString &s) const;\n};\n\nvoid z7_xml_DecodeString(AString &s);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/NewHandler.cpp",
    "content": "﻿// NewHandler.cpp\n \n#include \"StdAfx.h\"\n\n#include <stdlib.h>\n\n#include \"NewHandler.h\"\n\n// #define DEBUG_MEMORY_LEAK\n\n#ifndef DEBUG_MEMORY_LEAK\n\n#ifdef Z7_REDEFINE_OPERATOR_NEW\n\n/*\nvoid * my_new(size_t size)\n{\n  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);\n  if (size == 0)\n    size = 1;\n  void *p = ::malloc(size);\n  if (!p)\n    throw CNewException();\n  return p;\n}\n\nvoid my_delete(void *p) throw()\n{\n  // if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p);\n  ::free(p);\n}\n\nvoid * my_Realloc(void *p, size_t newSize, size_t oldSize)\n{\n  void *newBuf = my_new(newSize);\n  if (oldSize != 0)\n    memcpy(newBuf, p, oldSize);\n  my_delete(p);\n  return newBuf;\n}\n*/\n\nvoid *\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator new(size_t size)\n{\n  /* by C++ specification:\n       if (size == 0), operator new(size) returns non_NULL pointer.\n     If (operator new(0) returns NULL), it's out of specification.\n       but some calling code can work correctly even in this case too. */\n  // if (size == 0) return NULL; // for debug only. don't use it\n\n  /* malloc(0) returns non_NULL in main compilers, as we need here.\n     But specification also allows malloc(0) to return NULL.\n     So we change (size=0) to (size=1) here to get real non_NULL pointer */\n  if (size == 0)\n    size = 1;\n  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);\n  // void *p = ::MyAlloc(size);  // note: MyAlloc(0) returns NULL\n  void *p = ::malloc(size);\n  if (!p)\n    throw CNewException();\n  return p;\n}\n\n\n#if defined(_MSC_VER) && _MSC_VER == 1600\n// vs2010 has no throw() by default ?\n#pragma warning(push)\n#pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration\n#endif\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p) throw()\n{\n  // if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p);\n  // MyFree(p);\n  ::free(p);\n}\n\n/* we define operator delete(void *p, size_t n) because\n   vs2022 compiler uses delete(void *p, size_t n), and\n   we want to mix files from different compilers:\n     - old vc6 linker\n     - old vc6 complier\n     - new vs2022 complier\n*/\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p, size_t n) throw()\n{\n  UNUSED_VAR(n)\n  ::free(p);\n}\n\n#if defined(_MSC_VER) && _MSC_VER == 1600\n#pragma warning(pop)\n#endif\n\n/*\nvoid *\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator new[](size_t size)\n{\n  // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size);\n  if (size == 0)\n    size = 1;\n  void *p = ::malloc(size);\n  if (!p)\n    throw CNewException();\n  return p;\n}\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete[](void *p) throw()\n{\n  // if (!p) return; ::HeapFree(::GetProcessHeap(), 0, p);\n  ::free(p);\n}\n*/\n\n#endif\n\n#else\n\n#include <stdio.h>\n\n// #pragma init_seg(lib)\n/*\nconst int kDebugSize = 1000000;\nstatic void *a[kDebugSize];\nstatic int g_index = 0;\n\nclass CC\n{\npublic:\n  CC()\n  {\n    for (int i = 0; i < kDebugSize; i++)\n      a[i] = 0;\n  }\n  ~CC()\n  {\n    printf(\"\\nDestructor: %d\\n\", numAllocs);\n    for (int i = 0; i < kDebugSize; i++)\n      if (a[i] != 0)\n        return;\n  }\n} g_CC;\n*/\n\n#ifdef _WIN32\nstatic bool wasInit = false;\nstatic CRITICAL_SECTION cs;\n#endif\n\nstatic int numAllocs = 0;\n\nvoid *\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator new(size_t size)\n{\n #ifdef _WIN32\n  if (!wasInit)\n  {\n    InitializeCriticalSection(&cs);\n    wasInit = true;\n  }\n  EnterCriticalSection(&cs);\n\n  numAllocs++;\n  int loc = numAllocs;\n  void *p = HeapAlloc(GetProcessHeap(), 0, size);\n  /*\n  if (g_index < kDebugSize)\n  {\n    a[g_index] = p;\n    g_index++;\n  }\n  */\n  printf(\"Alloc %6d, size = %8u\\n\", loc, (unsigned)size);\n  LeaveCriticalSection(&cs);\n  if (!p)\n    throw CNewException();\n  return p;\n #else\n  numAllocs++;\n  int loc = numAllocs;\n  if (size == 0)\n    size = 1;\n  void *p = malloc(size);\n  /*\n  if (g_index < kDebugSize)\n  {\n    a[g_index] = p;\n    g_index++;\n  }\n  */\n  printf(\"Alloc %6d, size = %8u\\n\", loc, (unsigned)size);\n  if (!p)\n    throw CNewException();\n  return p;\n #endif\n}\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p) throw()\n{\n  if (!p)\n    return;\n #ifdef _WIN32\n  EnterCriticalSection(&cs);\n  /*\n  for (int i = 0; i < g_index; i++)\n    if (a[i] == p)\n      a[i] = 0;\n  */\n  HeapFree(GetProcessHeap(), 0, p);\n  // if (numAllocs == 0) numAllocs = numAllocs; // ERROR\n  numAllocs--;\n  // if (numAllocs == 0) numAllocs = numAllocs; // OK: all objects were deleted\n  printf(\"Free %d\\n\", numAllocs);\n  LeaveCriticalSection(&cs);\n #else\n  free(p);\n  numAllocs--;\n  printf(\"Free %d\\n\", numAllocs);\n #endif\n}\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p, size_t n) throw();\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p, size_t n) throw()\n{\n  UNUSED_VAR(n)\n  printf(\"delete_WITH_SIZE=%u, ptr = %p\\n\", (unsigned)n, p);\n  operator delete(p);\n}\n\n/*\nvoid *\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator new[](size_t size)\n{\n  printf(\"operator_new[] : \");\n  return operator new(size);\n}\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p, size_t sz) throw();\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p, size_t sz) throw()\n{\n  if (!p)\n    return;\n  printf(\"operator_delete_size : size=%d  : \", (unsigned)sz);\n  operator delete(p);\n}\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete[](void *p) throw()\n{\n  if (!p)\n    return;\n  printf(\"operator_delete[] : \");\n  operator delete(p);\n}\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete[](void *p, size_t sz) throw();\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete[](void *p, size_t sz) throw()\n{\n  if (!p)\n    return;\n  printf(\"operator_delete_size[] : size=%d  : \", (unsigned)sz);\n  operator delete(p);\n}\n*/\n\n#endif\n\n/*\nint MemErrorVC(size_t)\n{\n  throw CNewException();\n  // return 1;\n}\nCNewHandlerSetter::CNewHandlerSetter()\n{\n  // MemErrorOldVCFunction = _set_new_handler(MemErrorVC);\n}\nCNewHandlerSetter::~CNewHandlerSetter()\n{\n  // _set_new_handler(MemErrorOldVCFunction);\n}\n*/\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/NewHandler.h",
    "content": "﻿// Common/NewHandler.h\n\n#ifndef ZIP7_INC_COMMON_NEW_HANDLER_H\n#define ZIP7_INC_COMMON_NEW_HANDLER_H\n\n/*\nNewHandler.h and NewHandler.cpp allows to solve problem with compilers that\ndon't throw exception in operator new().\n\nThis file must be included before any code that uses operators new() or delete()\nand you must compile and link \"NewHandler.cpp\", if you use some old MSVC compiler.\n\nDOCs:\n  Since ISO C++98, operator new throws std::bad_alloc when memory allocation fails.\n  MSVC 6.0 returned a null pointer on an allocation failure.\n  Beginning in VS2002, operator new conforms to the standard and throws on failure.\n\n  By default, the compiler also generates defensive null checks to prevent\n  these older-style allocators from causing an immediate crash on failure.\n  The /Zc:throwingNew option tells the compiler to leave out these null checks,\n  on the assumption that all linked memory allocators conform to the standard.\n\nThe operator new() in some MSVC versions doesn't throw exception std::bad_alloc.\nMSVC 6.0 (_MSC_VER == 1200) doesn't throw exception.\nThe code produced by some another MSVC compilers also can be linked\nto library that doesn't throw exception.\nWe suppose that code compiled with VS2015+ (_MSC_VER >= 1900) throws exception std::bad_alloc.\nFor older _MSC_VER versions we redefine operator new() and operator delete().\nOur version of operator new() throws CNewException() exception on failure.\n\nIt's still allowed to use redefined version of operator new() from \"NewHandler.cpp\"\nwith any compiler. 7-Zip's code can work with std::bad_alloc and CNewException() exceptions.\nBut if you use some additional code (outside of 7-Zip's code), you must check\nthat redefined version of operator new() is not problem for your code.\n*/\n\n#include <stddef.h>\n\n#ifdef _WIN32\n// We can compile my_new and my_delete with _fastcall\n/*\nvoid * my_new(size_t size);\nvoid my_delete(void *p) throw();\n// void * my_Realloc(void *p, size_t newSize, size_t oldSize);\n*/\n#endif\n\n\n#if defined(_MSC_VER) && (_MSC_VER < 1600)\n  // If you want to use default operator new(), you can disable the following line\n  #define Z7_REDEFINE_OPERATOR_NEW\n#endif\n\n\n#ifdef Z7_REDEFINE_OPERATOR_NEW\n\n// std::bad_alloc can require additional DLL dependency.\n// So we don't define CNewException as std::bad_alloc here.\n\nclass CNewException {};\n\nvoid *\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator new(size_t size);\n\n/*\n#if 0 && defined(_MSC_VER) && _MSC_VER == 1600\n  #define Z7_OPERATOR_DELETE_SPEC_THROW0\n#else\n  #define Z7_OPERATOR_DELETE_SPEC_THROW0 throw()\n#endif\n*/\n#if defined(_MSC_VER) && _MSC_VER == 1600\n#pragma warning(push)\n#pragma warning(disable : 4986) // 'operator delete': exception specification does not match previous declaration\n#endif\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p) throw();\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete(void *p, size_t n) throw();\n\n#if defined(_MSC_VER) && _MSC_VER == 1600\n#pragma warning(pop)\n#endif\n\n\n#else\n\n#include <new>\n\n#define CNewException std::bad_alloc\n\n#endif\n\n/*\n#ifdef _WIN32\nvoid *\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator new[](size_t size);\n\nvoid\n#ifdef _MSC_VER\n__cdecl\n#endif\noperator delete[](void *p) throw();\n#endif\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#include \"Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StdInStream.cpp",
    "content": "﻿// Common/StdInStream.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef _WIN32\n#include <tchar.h>\n#endif\n\n#include \"StdInStream.h\"\n#include \"StringConvert.h\"\n#include \"UTFConvert.h\"\n\n// #define kEOFMessage \"Unexpected end of input stream\"\n// #define kReadErrorMessage \"Error reading input stream\"\n// #define kIllegalCharMessage \"Illegal zero character in input stream\"\n\n\nCStdInStream g_StdIn(stdin);\n\n/*\n#define kFileOpenMode TEXT(\"r\")\n\nbool CStdInStream::Open(LPCTSTR fileName) throw()\n{\n  Close();\n  _stream =\n    #ifdef _WIN32\n      _tfopen\n    #else\n      fopen\n    #endif\n      (fileName, kFileOpenMode);\n  _streamIsOpen = (_stream != 0);\n  return _streamIsOpen;\n}\n\nbool CStdInStream::Close() throw()\n{\n  if (!_streamIsOpen)\n    return true;\n  _streamIsOpen = (fclose(_stream) != 0);\n  return !_streamIsOpen;\n}\n*/\n\nbool CStdInStream::ScanAStringUntilNewLine(AString &s)\n{\n  s.Empty();\n  for (;;)\n  {\n    const int intChar = GetChar();\n    if (intChar == EOF)\n      return true;\n    const char c = (char)intChar;\n    if (c == 0)\n      return false;\n    if (c == '\\n')\n      return true;\n    s.Add_Char(c);\n  }\n}\n\nbool CStdInStream::ScanUStringUntilNewLine(UString &dest)\n{\n  dest.Empty();\n  AString s;\n  const bool res = ScanAStringUntilNewLine(s);\n  int codePage = CodePage;\n  if (codePage == -1)\n    codePage = CP_OEMCP;\n  if ((unsigned)codePage == CP_UTF8)\n    ConvertUTF8ToUnicode(s, dest);\n  else\n    MultiByteToUnicodeString2(dest, s, (UINT)(unsigned)codePage);\n  return res;\n}\n\n/*\nbool CStdInStream::ReadToString(AString &resultString)\n{\n  resultString.Empty();\n  for (;;)\n  {\n    int intChar = GetChar();\n    if (intChar == EOF)\n      return !Error();\n    char c = (char)intChar;\n    if (c == 0)\n      return false;\n    resultString += c;\n  }\n}\n*/\n\nint CStdInStream::GetChar()\n{\n  return fgetc(_stream); // getc() doesn't work in BeOS?\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StdInStream.h",
    "content": "﻿// Common/StdInStream.h\n\n#ifndef ZIP7_INC_COMMON_STD_IN_STREAM_H\n#define ZIP7_INC_COMMON_STD_IN_STREAM_H\n\n#include <stdio.h>\n\n#include \"MyString.h\"\n#include \"MyTypes.h\"\n\nclass CStdInStream\n{\n  FILE *_stream;\n  // bool _streamIsOpen;\npublic:\n  int CodePage;\n\n  CStdInStream(FILE *stream = NULL):\n      _stream(stream),\n      // _streamIsOpen(false),\n      CodePage(-1)\n      {}\n\n  /*\n  ~CStdInStream() { Close(); }\n\n  bool Open(LPCTSTR fileName) throw();\n  bool Close() throw();\n  */\n\n  // returns:\n  //   false, if ZERO character in stream\n  //   true, if EOF or '\\n'\n  bool ScanAStringUntilNewLine(AString &s);\n  bool ScanUStringUntilNewLine(UString &s);\n  // bool ReadToString(AString &resultString);\n\n  bool Eof() const throw() { return (feof(_stream) != 0); }\n  bool Error() const throw() { return (ferror(_stream) != 0); }\n\n  int GetChar();\n};\n\nextern CStdInStream g_StdIn;\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StdOutStream.cpp",
    "content": "﻿// Common/StdOutStream.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef _WIN32\n#include <tchar.h>\n#endif\n\n#include \"IntToString.h\"\n#include \"StdOutStream.h\"\n#include \"StringConvert.h\"\n#include \"UTFConvert.h\"\n\nCStdOutStream g_StdOut(stdout);\nCStdOutStream g_StdErr(stderr);\n\n/*\n// #define kFileOpenMode \"wt\"\n\nbool CStdOutStream::Open(const char *fileName) throw()\n{\n  Close();\n  _stream = fopen(fileName, kFileOpenMode);\n  _streamIsOpen = (_stream != 0);\n  return _streamIsOpen;\n}\n\nbool CStdOutStream::Close() throw()\n{\n  if (!_streamIsOpen)\n    return true;\n  if (fclose(_stream) != 0)\n    return false;\n  _stream = 0;\n  _streamIsOpen = false;\n  return true;\n}\n*/\n\nbool CStdOutStream::Flush() throw()\n{\n  return (fflush(_stream) == 0);\n}\n\nCStdOutStream & endl(CStdOutStream & outStream) throw()\n{\n  return outStream << '\\n';\n}\n\nCStdOutStream & CStdOutStream::operator<<(const wchar_t *s)\n{\n  AString temp;\n  UString s2(s);\n  PrintUString(s2, temp);\n  return *this;\n}\n\nvoid CStdOutStream::PrintUString(const UString &s, AString &temp)\n{\n  Convert_UString_to_AString(s, temp);\n  *this << (const char *)temp;\n}\n\nvoid CStdOutStream::Convert_UString_to_AString(const UString &src, AString &dest)\n{\n  int codePage = CodePage;\n  if (codePage == -1)\n    codePage = CP_OEMCP;\n  if ((unsigned)codePage == CP_UTF8)\n    ConvertUnicodeToUTF8(src, dest);\n  else\n    UnicodeStringToMultiByte2(dest, src, (UINT)(unsigned)codePage);\n}\n\n\nstatic const wchar_t kReplaceChar = '_';\n\n/*\nvoid CStdOutStream::Normalize_UString_LF_Allowed(UString &s)\n{\n  if (!IsTerminalMode)\n    return;\n\n  const unsigned len = s.Len();\n  wchar_t *d = s.GetBuf();\n\n    for (unsigned i = 0; i < len; i++)\n    {\n      const wchar_t c = d[i];\n      if (c == 0x1b || (c <= 13 && c >= 7 && c != '\\n'))\n        d[i] = kReplaceChar;\n    }\n}\n*/\n\nvoid CStdOutStream::Normalize_UString(UString &s)\n{\n  const unsigned len = s.Len();\n  wchar_t *d = s.GetBuf();\n\n  if (IsTerminalMode)\n    for (unsigned i = 0; i < len; i++)\n    {\n      const wchar_t c = d[i];\n      if ((c <= 13 && c >= 7) || c == 0x1b)\n        d[i] = kReplaceChar;\n    }\n  else\n    for (unsigned i = 0; i < len; i++)\n    {\n      const wchar_t c = d[i];\n      if (c == '\\n')\n        d[i] = kReplaceChar;\n    }\n}\n\nvoid CStdOutStream::Normalize_UString_Path(UString &s)\n{\n  if (ListPathSeparatorSlash.Def)\n  {\n#ifdef _WIN32\n    if (ListPathSeparatorSlash.Val)\n      s.Replace(L'\\\\', L'/');\n#else\n    if (!ListPathSeparatorSlash.Val)\n      s.Replace(L'/', L'\\\\');\n#endif\n  }\n  Normalize_UString(s);\n}\n\n\n/*\nvoid CStdOutStream::Normalize_UString(UString &src)\n{\n  const wchar_t *s = src.Ptr();\n  const unsigned len = src.Len();\n  unsigned i;\n  for (i = 0; i < len; i++)\n  {\n    const wchar_t c = s[i];\n#if 0 && !defined(_WIN32)\n    if (c == '\\\\') // IsTerminalMode &&\n      break;\n#endif\n    if ((unsigned)c < 0x20)\n      break;\n  }\n  if (i == len)\n    return;\n\n  UString temp;\n  for (i = 0; i < len; i++)\n  {\n    wchar_t c = s[i];\n#if 0 && !defined(_WIN32)\n    if (c == '\\\\')\n      temp += (wchar_t)L'\\\\';\n    else\n#endif\n    if ((unsigned)c < 0x20)\n    {\n      if (c == '\\n'\n        || (IsTerminalMode && (c == 0x1b || (c <= 13 && c >= 7))))\n      {\n#if 1 || defined(_WIN32)\n        c = (wchar_t)kReplaceChar;\n#else\n        temp += (wchar_t)L'\\\\';\n             if (c == '\\n') c = L'n';\n        else if (c == '\\r') c = L'r';\n        else if (c == '\\a') c = L'a';\n        else if (c == '\\b') c = L'b';\n        else if (c == '\\t') c = L't';\n        else if (c == '\\v') c = L'v';\n        else if (c == '\\f') c = L'f';\n        else\n        {\n          temp += (wchar_t)(L'0' + (unsigned)c / 64);\n          temp += (wchar_t)(L'0' + (unsigned)c / 8 % 8);\n          c     = (wchar_t)(L'0' + (unsigned)c % 8);\n        }\n#endif\n      }\n    }\n    temp += c;\n  }\n  src = temp;\n}\n*/\n\nvoid CStdOutStream::NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA)\n{\n  tempU = s;\n  Normalize_UString_Path(tempU);\n  PrintUString(tempU, tempA);\n}\n\nvoid CStdOutStream::NormalizePrint_UString_Path(const UString &s)\n{\n  UString tempU;\n  AString tempA;\n  NormalizePrint_UString_Path(s, tempU, tempA);\n}\n\nvoid CStdOutStream::NormalizePrint_wstr_Path(const wchar_t *s)\n{\n  UString tempU = s;\n  Normalize_UString_Path(tempU);\n  AString tempA;\n  PrintUString(tempU, tempA);\n}\n\nvoid CStdOutStream::NormalizePrint_UString(const UString &s)\n{\n  UString tempU = s;\n  Normalize_UString(tempU);\n  AString tempA;\n  PrintUString(tempU, tempA);\n}\n\nCStdOutStream & CStdOutStream::operator<<(Int32 number) throw()\n{\n  char s[32];\n  ConvertInt64ToString(number, s);\n  return operator<<(s);\n}\n\nCStdOutStream & CStdOutStream::operator<<(Int64 number) throw()\n{\n  char s[32];\n  ConvertInt64ToString(number, s);\n  return operator<<(s);\n}\n\nCStdOutStream & CStdOutStream::operator<<(UInt32 number) throw()\n{\n  char s[16];\n  ConvertUInt32ToString(number, s);\n  return operator<<(s);\n}\n\nCStdOutStream & CStdOutStream::operator<<(UInt64 number) throw()\n{\n  char s[32];\n  ConvertUInt64ToString(number, s);\n  return operator<<(s);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StdOutStream.h",
    "content": "﻿// Common/StdOutStream.h\n\n#ifndef ZIP7_INC_COMMON_STD_OUT_STREAM_H\n#define ZIP7_INC_COMMON_STD_OUT_STREAM_H\n\n#include <stdio.h>\n\n#include \"MyString.h\"\n#include \"MyTypes.h\"\n\nclass CStdOutStream\n{\n  FILE *_stream;\n  // bool _streamIsOpen;\npublic:\n  bool IsTerminalMode;\n  CBoolPair ListPathSeparatorSlash;\n  int CodePage;\n\n  CStdOutStream(FILE *stream = NULL):\n      _stream(stream),\n      // _streamIsOpen(false),\n      IsTerminalMode(false),\n      CodePage(-1)\n  {\n    ListPathSeparatorSlash.Val =\n#ifdef _WIN32\n        false;\n#else\n        true;\n#endif\n  }\n\n  // ~CStdOutStream() { Close(); }\n\n  // void AttachStdStream(FILE *stream) { _stream  = stream; _streamIsOpen = false; }\n  // bool IsDefined() const { return _stream  != NULL; }\n\n  operator FILE *() { return _stream; }\n  /*\n  bool Open(const char *fileName) throw();\n  bool Close() throw();\n  */\n  bool Flush() throw();\n  \n  CStdOutStream & operator<<(CStdOutStream & (* func)(CStdOutStream  &))\n  {\n    (*func)(*this);\n    return *this;\n  }\n\n  CStdOutStream & operator<<(const char *s) throw()\n  {\n    fputs(s, _stream);\n    return *this;\n  }\n\n  CStdOutStream & operator<<(char c) throw()\n  {\n    fputc((unsigned char)c, _stream);\n    return *this;\n  }\n\n  CStdOutStream & operator<<(Int32 number) throw();\n  CStdOutStream & operator<<(Int64 number) throw();\n  CStdOutStream & operator<<(UInt32 number) throw();\n  CStdOutStream & operator<<(UInt64 number) throw();\n\n  CStdOutStream & operator<<(const wchar_t *s);\n  void PrintUString(const UString &s, AString &temp);\n  void Convert_UString_to_AString(const UString &src, AString &dest);\n\n  void Normalize_UString(UString &s);\n  void Normalize_UString_Path(UString &s);\n\n  void NormalizePrint_UString_Path(const UString &s, UString &tempU, AString &tempA);\n  void NormalizePrint_UString_Path(const UString &s);\n  void NormalizePrint_UString(const UString &s);\n  void NormalizePrint_wstr_Path(const wchar_t *s);\n};\n\nCStdOutStream & endl(CStdOutStream & outStream) throw();\n\nextern CStdOutStream g_StdOut;\nextern CStdOutStream g_StdErr;\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StringConvert.cpp",
    "content": "﻿// Common/StringConvert.cpp\n\n#include \"StdAfx.h\"\n\n#include \"StringConvert.h\"\n\n#ifndef _WIN32\n// #include <stdio.h>\n#include <stdlib.h>\n#endif\n\n#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)\n#include \"UTFConvert.h\"\n#endif\n\n#ifdef ENV_HAVE_LOCALE\n#include <locale.h>\n#endif\n\nstatic const char k_DefultChar = '_';\n\n#ifdef _WIN32\n\n/*\nMultiByteToWideChar(CodePage, DWORD dwFlags,\n    LPCSTR lpMultiByteStr, int cbMultiByte,\n    LPWSTR lpWideCharStr, int cchWideChar)\n\n  if (cbMultiByte == 0)\n    return: 0. ERR: ERROR_INVALID_PARAMETER\n\n  if (cchWideChar == 0)\n    return: the required buffer size in characters.\n\n  if (supplied buffer size was not large enough)\n    return: 0. ERR: ERROR_INSUFFICIENT_BUFFER\n    The number of filled characters in lpWideCharStr can be smaller than cchWideChar (if last character is complex)\n\n  If there are illegal characters:\n    if MB_ERR_INVALID_CHARS is set in dwFlags:\n      - the function stops conversion on illegal character.\n      - Return: 0. ERR: ERROR_NO_UNICODE_TRANSLATION.\n    \n    if MB_ERR_INVALID_CHARS is NOT set in dwFlags:\n      before Vista: illegal character is dropped (skipped). WinXP-64: GetLastError() returns 0.\n      in Vista+:    illegal character is not dropped (MSDN). Undocumented: illegal\n                    character is converted to U+FFFD, which is REPLACEMENT CHARACTER.\n*/\n\n\nvoid MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)\n{\n  dest.Empty();\n  if (src.IsEmpty())\n    return;\n  {\n    /*\n    wchar_t *d = dest.GetBuf(src.Len());\n    const char *s = (const char *)src;\n    unsigned i;\n    \n    for (i = 0;;)\n    {\n      Byte c = (Byte)s[i];\n      if (c >= 0x80 || c == 0)\n        break;\n      d[i++] = (wchar_t)c;\n    }\n\n    if (i != src.Len())\n    {\n      unsigned len = MultiByteToWideChar(codePage, 0, s + i,\n          src.Len() - i, d + i,\n          src.Len() + 1 - i);\n      if (len == 0)\n        throw 282228;\n      i += len;\n    }\n\n    d[i] = 0;\n    dest.ReleaseBuf_SetLen(i);\n    */\n    unsigned len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), NULL, 0);\n    if (len == 0)\n    {\n      if (GetLastError() != 0)\n        throw 282228;\n    }\n    else\n    {\n      len = (unsigned)MultiByteToWideChar(codePage, 0, src, (int)src.Len(), dest.GetBuf(len), (int)len);\n      if (len == 0)\n        throw 282228;\n      dest.ReleaseBuf_SetEnd(len);\n    }\n  }\n}\n\n/*\n  int WideCharToMultiByte(\n      UINT CodePage, DWORD dwFlags,\n      LPCWSTR lpWideCharStr, int cchWideChar,\n      LPSTR lpMultiByteStr, int cbMultiByte,\n      LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar);\n\nif (lpDefaultChar == NULL),\n  - it uses system default value.\n\nif (CodePage == CP_UTF7 || CodePage == CP_UTF8)\n  if (lpDefaultChar != NULL || lpUsedDefaultChar != NULL)\n    return: 0. ERR: ERROR_INVALID_PARAMETER.\n\nThe function operates most efficiently, if (lpDefaultChar == NULL && lpUsedDefaultChar == NULL)\n\n*/\n\nstatic void UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)\n{\n  dest.Empty();\n  defaultCharWasUsed = false;\n  if (src.IsEmpty())\n    return;\n  {\n    /*\n    unsigned numRequiredBytes = src.Len() * 2;\n    char *d = dest.GetBuf(numRequiredBytes);\n    const wchar_t *s = (const wchar_t *)src;\n    unsigned i;\n    \n    for (i = 0;;)\n    {\n      wchar_t c = s[i];\n      if (c >= 0x80 || c == 0)\n        break;\n      d[i++] = (char)c;\n    }\n    \n    if (i != src.Len())\n    {\n      BOOL defUsed = FALSE;\n      defaultChar = defaultChar;\n\n      bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);\n      unsigned len = WideCharToMultiByte(codePage, 0, s + i, src.Len() - i,\n          d + i, numRequiredBytes + 1 - i,\n          (isUtf ? NULL : &defaultChar),\n          (isUtf ? NULL : &defUsed));\n      defaultCharWasUsed = (defUsed != FALSE);\n      if (len == 0)\n        throw 282229;\n      i += len;\n    }\n\n    d[i] = 0;\n    dest.ReleaseBuf_SetLen(i);\n    */\n\n    /*\n    if (codePage != CP_UTF7)\n    {\n      const wchar_t *s = (const wchar_t *)src;\n      unsigned i;\n      for (i = 0;; i++)\n      {\n        wchar_t c = s[i];\n        if (c >= 0x80 || c == 0)\n          break;\n      }\n      \n      if (s[i] == 0)\n      {\n        char *d = dest.GetBuf(src.Len());\n        for (i = 0;;)\n        {\n          wchar_t c = s[i];\n          if (c == 0)\n            break;\n          d[i++] = (char)c;\n        }\n        d[i] = 0;\n        dest.ReleaseBuf_SetLen(i);\n        return;\n      }\n    }\n    */\n\n    unsigned len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(), NULL, 0, NULL, NULL);\n    if (len == 0)\n    {\n      if (GetLastError() != 0)\n        throw 282228;\n    }\n    else\n    {\n      BOOL defUsed = FALSE;\n      bool isUtf = (codePage == CP_UTF8 || codePage == CP_UTF7);\n      // defaultChar = defaultChar;\n      len = (unsigned)WideCharToMultiByte(codePage, 0, src, (int)src.Len(),\n          dest.GetBuf(len), (int)len,\n          (isUtf ? NULL : &defaultChar),\n          (isUtf ? NULL : &defUsed)\n          );\n      if (!isUtf)\n        defaultCharWasUsed = (defUsed != FALSE);\n      if (len == 0)\n        throw 282228;\n      dest.ReleaseBuf_SetEnd(len);\n    }\n  }\n}\n\n/*\n#ifndef UNDER_CE\nAString SystemStringToOemString(const CSysString &src)\n{\n  AString dest;\n  const unsigned len = src.Len() * 2;\n  CharToOem(src, dest.GetBuf(len));\n  dest.ReleaseBuf_CalcLen(len);\n  return dest;\n}\n#endif\n*/\n\n#else // _WIN32\n\n// #include <stdio.h>\n/*\n  if (wchar_t is 32-bit (#if WCHAR_MAX > 0xffff),\n      and utf-8 string contains big unicode character > 0xffff),\n  then we still use 16-bit surrogate pair in UString.\n  It simplifies another code where utf-16 encoding is used.\n  So we use surrogate-conversion code only in is file.\n*/\n\n/*\n   mbstowcs() returns error if there is error in utf-8 stream,\n   mbstowcs() returns error if there is single surrogates point (d800-dfff) in utf-8 stream\n*/\n\n/*\nstatic void MultiByteToUnicodeString2_Native(UString &dest, const AString &src)\n{\n  dest.Empty();\n  if (src.IsEmpty())\n    return;\n\n  const size_t limit = ((size_t)src.Len() + 1) * 2;\n  wchar_t *d = dest.GetBuf((unsigned)limit);\n  const size_t len = mbstowcs(d, src, limit);\n  if (len != (size_t)-1)\n  {\n    dest.ReleaseBuf_SetEnd((unsigned)len);\n    return;\n  }\n  dest.ReleaseBuf_SetEnd(0);\n}\n*/\n\nbool g_ForceToUTF8 = true; // false;\n\nvoid MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage)\n{\n  dest.Empty();\n  if (src.IsEmpty())\n    return;\n\n  if (codePage == CP_UTF8 || g_ForceToUTF8)\n  {\n#if 1\n    ConvertUTF8ToUnicode(src, dest);\n    return;\n#endif\n  }\n\n  const size_t limit = ((size_t)src.Len() + 1) * 2;\n  wchar_t *d = dest.GetBuf((unsigned)limit);\n  const size_t len = mbstowcs(d, src, limit);\n  if (len != (size_t)-1)\n  {\n    dest.ReleaseBuf_SetEnd((unsigned)len);\n\n#if WCHAR_MAX > 0xffff\n    d = dest.GetBuf();\n    for (size_t i = 0;; i++)\n    {\n      wchar_t c = d[i];\n      // printf(\"\\ni=%2d c = %4x\\n\", (unsigned)i, (unsigned)c);\n      if (c == 0)\n        break;\n      if (c >= 0x10000 && c < 0x110000)\n      {\n        UString tempString = d + i;\n        const wchar_t *t = tempString.Ptr();\n\n        for (;;)\n        {\n          wchar_t w = *t++;\n          // printf(\"\\nchar=%x\\n\", w);\n          if (w == 0)\n            break;\n          if (i == limit)\n            break; // unexpected error\n          if (w >= 0x10000 && w < 0x110000)\n          {\n#if 1\n            if (i + 1 == limit)\n              break; // unexpected error\n            w -= 0x10000;\n            d[i++] = (unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff);\n            w = 0xdc00 + (w & 0x3ff);\n#else\n            // w = '_'; // for debug\n#endif\n          }\n          d[i++] = w;\n        }\n        dest.ReleaseBuf_SetEnd((unsigned)i);\n        break;\n      }\n    }\n\n#endif\n \n    /*\n    printf(\"\\nMultiByteToUnicodeString2 (%d) %s\\n\", (int)src.Len(),  src.Ptr());\n    printf(\"char:    \");\n    for (unsigned i = 0; i < src.Len(); i++)\n      printf (\" %02x\", (int)(Byte)src[i]);\n    printf(\"\\n\");\n    printf(\"\\n-> (%d) %ls\\n\", (int)dest.Len(), dest.Ptr());\n    printf(\"wchar_t: \");\n    for (unsigned i = 0; i < dest.Len(); i++)\n    {\n      printf (\" %02x\", (int)dest[i]);\n    }\n    printf(\"\\n\");\n    */\n\n    return;\n  }\n\n  /* if there is mbstowcs() error, we have two ways:\n     \n     1) change 0x80+ characters to some character: '_'\n        in that case we lose data, but we have correct UString()\n        and that scheme can show errors to user in early stages,\n        when file converted back to mbs() cannot be found\n\n     2) transfer bad characters in some UTF-16 range.\n        it can be non-original Unicode character.\n        but later we still can restore original character.\n  */\n\n  \n  // printf(\"\\nmbstowcs  ERROR !!!!!! s=%s\\n\", src.Ptr());\n  {\n    unsigned i;\n    const char *s = (const char *)src;\n    for (i = 0;;)\n    {\n      Byte c = (Byte)s[i];\n      if (c == 0)\n        break;\n      // we can use ascii compatibilty character '_'\n      // if (c > 0x7F) c = '_'; // we replace \"bad: character\n      d[i++] = (wchar_t)c;\n    }\n    d[i] = 0;\n    dest.ReleaseBuf_SetLen(i);\n  }\n}\n\nstatic void UnicodeStringToMultiByte2_Native(AString &dest, const UString &src)\n{\n  dest.Empty();\n  if (src.IsEmpty())\n    return;\n\n  const size_t limit = ((size_t)src.Len() + 1) * 6;\n  char *d = dest.GetBuf((unsigned)limit);\n\n  const size_t len = wcstombs(d, src, limit);\n\n  if (len != (size_t)-1)\n  {\n    dest.ReleaseBuf_SetEnd((unsigned)len);\n    return;\n  }\n  dest.ReleaseBuf_SetEnd(0);\n}\n\n\nstatic void UnicodeStringToMultiByte2(AString &dest, const UString &src2, UINT codePage, char defaultChar, bool &defaultCharWasUsed)\n{\n  // if (codePage == 1234567) // for debug purposes\n  if (codePage == CP_UTF8 || g_ForceToUTF8)\n  {\n#if 1\n    defaultCharWasUsed = false;\n    ConvertUnicodeToUTF8(src2, dest);\n    return;\n#endif\n  }\n\n  UString src = src2;\n#if WCHAR_MAX > 0xffff\n  {\n    src.Empty();\n    for (unsigned i = 0; i < src2.Len();)\n    {\n      wchar_t c = src2[i++];\n      if (c >= 0xd800 && c < 0xdc00 && i != src2.Len())\n      {\n        const wchar_t c2 = src2[i];\n        if (c2 >= 0xdc00 && c2 < 0xe000)\n        {\n#if 1\n          // printf(\"\\nSurragate [%d]: %4x %4x -> \", i, (int)c, (int)c2);\n          c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);\n          // printf(\"%4x\\n\", (int)c);\n          i++;\n#else\n          // c = '_'; // for debug\n#endif\n        }\n      }\n      src += c;\n    }\n  }\n#endif\n\n  dest.Empty();\n  defaultCharWasUsed = false;\n  if (src.IsEmpty())\n    return;\n\n  const size_t len = wcstombs(NULL, src, 0);\n\n  if (len != (size_t)-1)\n  {\n    const unsigned limit = ((unsigned)len);\n    if (limit == len)\n    {\n      char *d = dest.GetBuf(limit);\n\n      /*\n      {\n        printf(\"\\nwcstombs; len = %d %ls \\n\", (int)src.Len(), src.Ptr());\n        for (unsigned i = 0; i < src.Len(); i++)\n          printf (\" %02x\", (int)src[i]);\n        printf(\"\\n\");\n        printf(\"\\ndest Limit = %d \\n\", limit);\n      }\n      */\n\n      const size_t len2 = wcstombs(d, src, len + 1);\n      \n      if (len2 != (size_t)-1 && len2 <= limit)\n      {\n        /*\n        printf(\"\\nOK : destLen = %d : %s\\n\", (int)len, dest.Ptr());\n        for (unsigned i = 0; i < len2; i++)\n          printf(\" %02x\", (int)(Byte)dest[i]);\n        printf(\"\\n\");\n        */\n        dest.ReleaseBuf_SetEnd((unsigned)len2);\n        return;\n      }\n    }\n  }\n\n  {\n    const wchar_t *s = (const wchar_t *)src;\n    char *d = dest.GetBuf(src.Len());\n\n    unsigned i;\n    for (i = 0;;)\n    {\n      wchar_t c = s[i];\n      if (c == 0)\n        break;\n      if (c >=\n            0x100\n            // 0x80\n          )\n      {\n        c = defaultChar;\n        defaultCharWasUsed = true;\n      }\n\n      d[i++] = (char)c;\n    }\n    d[i] = 0;\n    dest.ReleaseBuf_SetLen(i);\n    /*\n    printf(\"\\nUnicodeStringToMultiByte2; len = %d \\n\", (int)src.Len());\n    printf(\"ERROR: %s\\n\", dest.Ptr());\n    */\n  }\n}\n\n#endif // _WIN32\n\n\nUString MultiByteToUnicodeString(const AString &src, UINT codePage)\n{\n  UString dest;\n  MultiByteToUnicodeString2(dest, src, codePage);\n  return dest;\n}\n\nUString MultiByteToUnicodeString(const char *src, UINT codePage)\n{\n  return MultiByteToUnicodeString(AString(src), codePage);\n}\n\n\nvoid UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage)\n{\n  bool defaultCharWasUsed;\n  UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);\n}\n\nAString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed)\n{\n  AString dest;\n  UnicodeStringToMultiByte2(dest, src, codePage, defaultChar, defaultCharWasUsed);\n  return dest;\n}\n\nAString UnicodeStringToMultiByte(const UString &src, UINT codePage)\n{\n  AString dest;\n  bool defaultCharWasUsed;\n  UnicodeStringToMultiByte2(dest, src, codePage, k_DefultChar, defaultCharWasUsed);\n  return dest;\n}\n\n\n\n\n#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)\n\n#ifdef _WIN32\n#define U_to_A(a, b, c)  UnicodeStringToMultiByte2\n// #define A_to_U(a, b, c)  MultiByteToUnicodeString2\n#else\n// void MultiByteToUnicodeString2_Native(UString &dest, const AString &src);\n#define U_to_A(a, b, c)  UnicodeStringToMultiByte2_Native(a, b)\n// #define A_to_U(a, b, c)  MultiByteToUnicodeString2_Native(a, b)\n#endif\n\nbool IsNativeUTF8()\n{\n  UString u;\n  AString a, a2;\n  // for (unsigned c = 0x80; c < (UInt32)0x10000; c += (c >> 9) + 1)\n  for (unsigned c = 0x80; c < (UInt32)0xD000; c += (c >> 2) + 1)\n  {\n    u.Empty();\n    u += (wchar_t)c;\n    /*\n    if (Unicode_Is_There_Utf16SurrogateError(u))\n      continue;\n    #ifndef _WIN32\n    if (Unicode_Is_There_BmpEscape(u))\n      continue;\n    #endif\n    */\n    ConvertUnicodeToUTF8(u, a);\n    U_to_A(a2, u, CP_OEMCP);\n    if (a != a2)\n      return false;\n  }\n  return true;\n}\n\n#endif\n\n\n#ifdef ENV_HAVE_LOCALE\n\nconst char *GetLocale(void)\n{\n  #ifdef ENV_HAVE_LOCALE\n    // printf(\"\\n\\nsetlocale(LC_CTYPE, NULL) : return : \");\n    const char *s = setlocale(LC_CTYPE, NULL);\n    if (!s)\n    {\n      // printf(\"[NULL]\\n\");\n      s = \"C\";\n    }\n    else\n    {\n      // ubuntu returns \"C\" after program start\n      // printf(\"\\\"%s\\\"\\n\", s);\n    }\n    return s;\n  #elif defined(LOCALE_IS_UTF8)\n    return \"utf8\";\n  #else\n    return \"C\";\n  #endif\n}\n\n#ifdef _WIN32\n  static void Set_ForceToUTF8(bool) {}\n#else\n  static void Set_ForceToUTF8(bool val) { g_ForceToUTF8 = val; }\n#endif\n\nstatic bool Is_Default_Basic_Locale(const char *locale)\n{\n  const AString a (locale);\n  if (a.IsEqualTo_Ascii_NoCase(\"\")\n      || a.IsEqualTo_Ascii_NoCase(\"C\")\n      || a.IsEqualTo_Ascii_NoCase(\"POSIX\"))\n      return true;\n  return false;\n}\n\nstatic bool Is_Default_Basic_Locale()\n{\n  return Is_Default_Basic_Locale(GetLocale());\n}\n\n\nvoid MY_SetLocale()\n{\n  #ifdef ENV_HAVE_LOCALE\n  /*\n  {\n    const char *s = GetLocale();\n    printf(\"\\nGetLocale() : returned : \\\"%s\\\"\\n\", s);\n  }\n  */\n  \n  unsigned start = 0;\n  // unsigned lim = 0;\n  unsigned lim = 3;\n\n  /*\n  #define MY_SET_LOCALE_FLAGS__FROM_ENV 1\n  #define MY_SET_LOCALE_FLAGS__TRY_UTF8 2\n\n  unsigned flags =\n      MY_SET_LOCALE_FLAGS__FROM_ENV |\n      MY_SET_LOCALE_FLAGS__TRY_UTF8\n\n  if (flags != 0)\n  {\n    if (flags & MY_SET_LOCALE_FLAGS__FROM_ENV)\n      lim = (flags & MY_SET_LOCALE_FLAGS__TRY_UTF8) ? 3 : 1;\n    else\n    {\n      start = 1;\n      lim = 2;\n    }\n  }\n  */\n\n  for (unsigned i = start; i < lim; i++)\n  {\n    /*\n    man7: \"If locale is an empty string, \"\", each part of the locale that\n    should be modified is set according to the environment variables.\n    for glibc: glibc, first from the user's environment variables:\n      1) the environment variable LC_ALL,\n      2) environment variable with the same name as the category (see the\n      3) the environment variable LANG\n    The locale \"C\" or \"POSIX\" is a portable locale; it exists on all conforming systems.\n    \n    for WIN32 : MSDN :\n      Sets the locale to the default, which is the user-default\n      ANSI code page obtained from the operating system.\n      The locale name is set to the value returned by GetUserDefaultLocaleName.\n      The code page is set to the value returned by GetACP\n  */\n    const char *newLocale = \"\";\n    \n    #ifdef __APPLE__\n    \n    /* look also CFLocale\n       there is no C.UTF-8 in macos\n       macos has UTF-8 locale only with some language like en_US.UTF-8\n       what is best way to set UTF-8 locale in macos? */\n    if (i == 1)\n      newLocale = \"en_US.UTF-8\";\n   \n    /* file open with non-utf8 sequencies return\n      #define EILSEQ    92    // \"Illegal byte sequence\"\n    */\n#else\n    // newLocale = \"C\";\n    if (i == 1)\n    {\n      newLocale = \"C.UTF-8\";    // main UTF-8 locale in ubuntu\n      // newLocale = \".utf8\";    // supported in new Windows 10 build 17134 (April 2018 Update), the Universal C Runtime\n      // newLocale = \"en_US.utf8\"; // supported by ubuntu ?\n      // newLocale = \"en_US.UTF-8\";\n      /* setlocale() in ubuntu allows locales with minor chracter changes in strings\n        \"en_US.UTF-8\" /  \"en_US.utf8\" */\n    }\n    \n#endif\n    \n    // printf(\"\\nsetlocale(LC_ALL, \\\"%s\\\") : returned: \", newLocale);\n    \n    // const char *s =\n    setlocale(LC_ALL, newLocale);\n    \n    /*\n    if (!s)\n      printf(\"NULL: can't set locale\");\n    else\n      printf(\"\\\"%s\\\"\\n\", s);\n    */\n    \n    // request curent locale of program\n    const char *locale = GetLocale();\n    if (locale)\n    {\n      AString a (locale);\n      a.MakeLower_Ascii();\n      // if (a.Find(\"utf\") >= 0)\n      {\n        if (IsNativeUTF8())\n        {\n          Set_ForceToUTF8(true);\n          return;\n        }\n      }\n      if (!Is_Default_Basic_Locale(locale))\n      {\n        // if there is some non-default and non-utf locale, we want to use it\n        break; // comment it for debug\n      }\n    }\n  }\n\n  if (IsNativeUTF8())\n  {\n    Set_ForceToUTF8(true);\n    return;\n  }\n\n  if (Is_Default_Basic_Locale())\n  {\n    Set_ForceToUTF8(true);\n    return;\n  }\n\n  Set_ForceToUTF8(false);\n\n  #elif defined(LOCALE_IS_UTF8)\n    // assume LC_CTYPE=\"utf8\"\n  #else\n    // assume LC_CTYPE=\"C\"\n  #endif\n}\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StringConvert.h",
    "content": "﻿// Common/StringConvert.h\n\n#ifndef ZIP7_INC_COMMON_STRING_CONVERT_H\n#define ZIP7_INC_COMMON_STRING_CONVERT_H\n\n#include \"MyString.h\"\n#include \"MyWindows.h\"\n\nUString MultiByteToUnicodeString(const AString &src, UINT codePage = CP_ACP);\nUString MultiByteToUnicodeString(const char *src, UINT codePage = CP_ACP);\n\n// optimized versions that work faster for ASCII strings\nvoid MultiByteToUnicodeString2(UString &dest, const AString &src, UINT codePage = CP_ACP);\n// void UnicodeStringToMultiByte2(AString &dest, const UString &s, UINT codePage, char defaultChar, bool &defaultCharWasUsed);\nvoid UnicodeStringToMultiByte2(AString &dest, const UString &src, UINT codePage);\n\nAString UnicodeStringToMultiByte(const UString &src, UINT codePage, char defaultChar, bool &defaultCharWasUsed);\nAString UnicodeStringToMultiByte(const UString &src, UINT codePage = CP_ACP);\n\ninline const wchar_t* GetUnicodeString(const wchar_t *u)  { return u; }\ninline const UString& GetUnicodeString(const UString &u)  { return u; }\n\ninline UString GetUnicodeString(const AString &a)  { return MultiByteToUnicodeString(a); }\ninline UString GetUnicodeString(const char *a)     { return MultiByteToUnicodeString(a); }\n\ninline UString GetUnicodeString(const AString &a, UINT codePage)\n  { return MultiByteToUnicodeString(a, codePage); }\ninline UString GetUnicodeString(const char *a, UINT codePage)\n  { return MultiByteToUnicodeString(a, codePage); }\n\ninline const wchar_t* GetUnicodeString(const wchar_t *u, UINT) { return u; }\ninline const UString& GetUnicodeString(const UString &u, UINT) { return u; }\n\ninline const char*    GetAnsiString(const char    *a) { return a; }\ninline const AString& GetAnsiString(const AString &a) { return a; }\n\ninline AString GetAnsiString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }\ninline AString GetAnsiString(const UString &u) { return UnicodeStringToMultiByte(u); }\n\n/*\ninline const char* GetOemString(const char* oem)\n  { return oem; }\ninline const AString& GetOemString(const AString &oem)\n  { return oem; }\n*/\nconst char* GetOemString(const char* oem);\nconst AString& GetOemString(const AString &oem);\ninline AString GetOemString(const UString &u)\n  { return UnicodeStringToMultiByte(u, CP_OEMCP); }\n\n#ifdef _UNICODE\n  inline const wchar_t* GetSystemString(const wchar_t *u) { return u;}\n  inline const UString& GetSystemString(const UString &u) { return u;}\n  inline const wchar_t* GetSystemString(const wchar_t *u, UINT /* codePage */) { return u;}\n  inline const UString& GetSystemString(const UString &u, UINT /* codePage */) { return u;}\n  \n  inline UString GetSystemString(const AString &a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }\n  inline UString GetSystemString(const char    *a, UINT codePage) { return MultiByteToUnicodeString(a, codePage); }\n  inline UString GetSystemString(const AString &a) { return MultiByteToUnicodeString(a); }\n  inline UString GetSystemString(const char    *a) { return MultiByteToUnicodeString(a); }\n#else\n  inline const char*    GetSystemString(const char    *a) { return a; }\n  inline const AString& GetSystemString(const AString &a) { return a; }\n  inline const char*    GetSystemString(const char    *a, UINT) { return a; }\n  inline const AString& GetSystemString(const AString &a, UINT) { return a; }\n  \n  inline AString GetSystemString(const wchar_t *u) { return UnicodeStringToMultiByte(UString(u)); }\n  inline AString GetSystemString(const UString &u) { return UnicodeStringToMultiByte(u); }\n  inline AString GetSystemString(const UString &u, UINT codePage) { return UnicodeStringToMultiByte(u, codePage); }\n\n\n\n  /*\n  inline AString GetSystemString(const wchar_t *u)\n  {\n    UString s;\n    s = u;\n    return UnicodeStringToMultiByte(s);\n  }\n  */\n\n#endif\n\n#ifndef UNDER_CE\nAString SystemStringToOemString(const CSysString &src);\n#endif\n\n\n#ifdef _WIN32\n/* we don't need locale functions in Windows\n   but we can define ENV_HAVE_LOCALE here for debug purposes */\n// #define ENV_HAVE_LOCALE\n#else\n#define ENV_HAVE_LOCALE\n#endif\n\n#ifdef ENV_HAVE_LOCALE\nvoid MY_SetLocale();\nconst char *GetLocale(void);\n#endif\n\n#if !defined(_WIN32) || defined(ENV_HAVE_LOCALE)\nbool IsNativeUTF8();\n#endif\n\n#ifndef _WIN32\nextern bool g_ForceToUTF8;\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StringToInt.cpp",
    "content": "﻿// Common/StringToInt.cpp\n\n#include \"StdAfx.h\"\n\n#include <limits.h>\n#if defined(_MSC_VER) && (_MSC_VER >= 1600)\n#include <stdint.h> // for WCHAR_MAX in vs2022\n#endif\n\n#include \"StringToInt.h\"\n\nstatic const UInt32 k_UInt32_max = 0xFFFFFFFF;\nstatic const UInt64 k_UInt64_max = UINT64_CONST(0xFFFFFFFFFFFFFFFF);\n// static const UInt64 k_UInt64_max = (UInt64)(Int64)-1;\n\n#define DIGIT_TO_VALUE(charTypeUnsigned, digit)   ((unsigned)(charTypeUnsigned)digit - '0')\n// #define DIGIT_TO_VALUE(charTypeUnsigned, digit)   ((unsigned)digit - '0')\n// #define DIGIT_TO_VALUE(charTypeUnsigned, digit)   ((unsigned)(digit - '0'))\n\n#define CONVERT_STRING_TO_UINT_FUNC(uintType, charType, charTypeUnsigned) \\\nuintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \\\n    if (end) *end = s; \\\n    uintType res = 0; \\\n    for (;; s++) { \\\n      const unsigned v = DIGIT_TO_VALUE(charTypeUnsigned, *s); \\\n      if (v > 9) { if (end) *end = s; return res; } \\\n      if (res > (k_ ## uintType ## _max) / 10) return 0; \\\n      res *= 10; \\\n      if (res > (k_ ## uintType ## _max) - v) return 0; \\\n      res += v; }}\n\n// arm-linux-gnueabi GCC compilers give (WCHAR_MAX > UINT_MAX) by some unknown reason\n// so we don't use this branch\n#if 0 && WCHAR_MAX > UINT_MAX\n/*\n   if (sizeof(wchar_t) > sizeof(unsigned)\n      we must use CONVERT_STRING_TO_UINT_FUNC_SLOW\n   But we just stop compiling instead.\n   We need some real cases to test this code.\n*/\n#error Stop_Compiling_WCHAR_MAX_IS_LARGER_THAN_UINT_MAX\n#define CONVERT_STRING_TO_UINT_FUNC_SLOW(uintType, charType, charTypeUnsigned) \\\nuintType ConvertStringTo ## uintType(const charType *s, const charType **end) throw() { \\\n    if (end) *end = s; \\\n    uintType res = 0; \\\n    for (;; s++) { \\\n      const charTypeUnsigned c = (charTypeUnsigned)*s; \\\n      if (c < '0' || c > '9') { if (end) *end = s; return res; } \\\n      if (res > (k_ ## uintType ## _max) / 10) return 0; \\\n      res *= 10; \\\n      const unsigned v = (unsigned)(c - '0'); \\\n      if (res > (k_ ## uintType ## _max) - v) return 0; \\\n      res += v; }}\n#endif\n\n\nCONVERT_STRING_TO_UINT_FUNC(UInt32, char, Byte)\nCONVERT_STRING_TO_UINT_FUNC(UInt32, wchar_t, wchar_t)\nCONVERT_STRING_TO_UINT_FUNC(UInt64, char, Byte)\nCONVERT_STRING_TO_UINT_FUNC(UInt64, wchar_t, wchar_t)\n\nInt32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw()\n{\n  if (end)\n    *end = s;\n  const wchar_t *s2 = s;\n  if (*s == '-')\n    s2++;\n  const wchar_t *end2;\n  UInt32 res = ConvertStringToUInt32(s2, &end2);\n  if (s2 == end2)\n    return 0;\n  if (s != s2)\n  {\n    if (res > (UInt32)1 << (32 - 1))\n      return 0;\n    res = 0 - res;\n  }\n  else\n  {\n    if (res & (UInt32)1 << (32 - 1))\n      return 0;\n  }\n  if (end)\n    *end = end2;\n  return (Int32)res;\n}\n\n\n#define CONVERT_OCT_STRING_TO_UINT_FUNC(uintType) \\\nuintType ConvertOctStringTo ## uintType(const char *s, const char **end) throw() \\\n{ \\\n  if (end) *end = s; \\\n  uintType res = 0; \\\n  for (;; s++) { \\\n    const unsigned c = (unsigned)(Byte)*s - '0'; \\\n    if (c > 7) { \\\n      if (end) \\\n        *end = s; \\\n      return res; \\\n    } \\\n    if (res & (uintType)7 << (sizeof(uintType) * 8 - 3)) \\\n      return 0; \\\n    res <<= 3; \\\n    res |= c; \\\n  } \\\n}\n\nCONVERT_OCT_STRING_TO_UINT_FUNC(UInt32)\nCONVERT_OCT_STRING_TO_UINT_FUNC(UInt64)\n\n\n#define CONVERT_HEX_STRING_TO_UINT_FUNC(uintType) \\\nuintType ConvertHexStringTo ## uintType(const char *s, const char **end) throw() \\\n{ \\\n  if (end) *end = s; \\\n  uintType res = 0; \\\n  for (;; s++) { \\\n    unsigned c = (unsigned)(Byte)*s; \\\n    Z7_PARSE_HEX_DIGIT(c, { if (end) *end = s;  return res; }) \\\n    if (res & (uintType)0xF << (sizeof(uintType) * 8 - 4)) \\\n      return 0; \\\n    res <<= 4; \\\n    res |= c; \\\n  } \\\n}\n\nCONVERT_HEX_STRING_TO_UINT_FUNC(UInt32)\nCONVERT_HEX_STRING_TO_UINT_FUNC(UInt64)\n\nconst char *FindNonHexChar(const char *s) throw()\n{\n  for (;;)\n  {\n    unsigned c = (Byte)*s++; // pointer can go 1 byte after end\n    c -= '0';\n    if (c <= 9)\n      continue;\n    c -= 'A' - '0';\n    c &= ~0x20u;\n    if (c > 5)\n      return s - 1;\n  }\n}\n\nByte *ParseHexString(const char *s, Byte *dest) throw()\n{\n  for (;;)\n  {\n    unsigned v0 = (Byte)s[0];         Z7_PARSE_HEX_DIGIT(v0, return dest;)\n    unsigned v1 = (Byte)s[1]; s += 2; Z7_PARSE_HEX_DIGIT(v1, return dest;)\n    *dest++ = (Byte)(v1 | (v0 << 4));\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/StringToInt.h",
    "content": "﻿// Common/StringToInt.h\n\n#ifndef ZIP7_INC_COMMON_STRING_TO_INT_H\n#define ZIP7_INC_COMMON_STRING_TO_INT_H\n\n#include \"MyTypes.h\"\n\nUInt32 ConvertStringToUInt32(const char *s, const char **end) throw();\nUInt64 ConvertStringToUInt64(const char *s, const char **end) throw();\nUInt32 ConvertStringToUInt32(const wchar_t *s, const wchar_t **end) throw();\nUInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) throw();\n\n// Int32 ConvertStringToInt32(const char *s, const char **end) throw();\nInt32 ConvertStringToInt32(const wchar_t *s, const wchar_t **end) throw();\n\nUInt32 ConvertOctStringToUInt32(const char *s, const char **end) throw();\nUInt64 ConvertOctStringToUInt64(const char *s, const char **end) throw();\n\nUInt32 ConvertHexStringToUInt32(const char *s, const char **end) throw();\nUInt64 ConvertHexStringToUInt64(const char *s, const char **end) throw();\n\n#define Z7_PARSE_HEX_DIGIT(c, err_op) \\\n{ c -= '0'; \\\n  if (c > 9) { \\\n    c -= 'A' - '0'; \\\n    c &= ~0x20u; \\\n    if (c > 5) { err_op } \\\n    c += 10; \\\n  } \\\n}\n\nconst char *FindNonHexChar(const char *s) throw();\n\n// in: (dest != NULL)\n// returns: pointer in dest array after last written byte\nByte *ParseHexString(const char *s, Byte *dest) throw();\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/TextConfig.cpp",
    "content": "﻿// Common/TextConfig.cpp\n\n#include \"StdAfx.h\"\n\n#include \"TextConfig.h\"\n#include \"UTFConvert.h\"\n\nstatic inline bool IsDelimitChar(char c)\n{\n  return (c == ' ' || c == 0x0A || c == 0x0D || c == '\\0' || c == '\\t');\n}\n    \nstatic AString GetIDString(const char *s, unsigned &finishPos)\n{\n  AString result;\n  for (finishPos = 0; ; finishPos++)\n  {\n    const char c = s[finishPos];\n    if (IsDelimitChar(c) || c == '=')\n      break;\n    result += c;\n  }\n  return result;\n}\n\nstatic bool WaitNextLine(const AString &s, unsigned &pos)\n{\n  for (; pos < s.Len(); pos++)\n    if (s[pos] == 0x0A)\n      return true;\n  return false;\n}\n\nstatic bool SkipSpaces(const AString &s, unsigned &pos)\n{\n  for (; pos < s.Len(); pos++)\n  {\n    const char c = s[pos];\n    if (!IsDelimitChar(c))\n    {\n      if (c != ';')\n        return true;\n      if (!WaitNextLine(s, pos))\n        return false;\n    }\n  }\n  return false;\n}\n\nbool GetTextConfig(const AString &s, CObjectVector<CTextConfigPair> &pairs)\n{\n  pairs.Clear();\n  unsigned pos = 0;\n\n  /////////////////////\n  // read strings\n\n  for (;;)\n  {\n    if (!SkipSpaces(s, pos))\n      break;\n    CTextConfigPair pair;\n    unsigned finishPos;\n    const AString temp (GetIDString(((const char *)s) + pos, finishPos));\n    if (!ConvertUTF8ToUnicode(temp, pair.ID))\n      return false;\n    if (finishPos == 0)\n      return false;\n    pos += finishPos;\n    if (!SkipSpaces(s, pos))\n      return false;\n    if (s[pos] != '=')\n      return false;\n    pos++;\n    if (!SkipSpaces(s, pos))\n      return false;\n    if (s[pos] != '\\\"')\n      return false;\n    pos++;\n    AString message;\n    for (;;)\n    {\n      if (pos >= s.Len())\n        return false;\n      char c = s[pos++];\n      if (c == '\\\"')\n        break;\n      if (c == '\\\\')\n      {\n        c = s[pos++];\n        switch (c)\n        {\n          case 'n':  c = '\\n';  break;\n          case 't':  c = '\\t';  break;\n          case '\\\\':  break;\n          case '\\\"':  break;\n          default:  message += '\\\\';  break;\n        }\n      }\n      message += c;\n    }\n    if (!ConvertUTF8ToUnicode(message, pair.String))\n      return false;\n    pairs.Add(pair);\n  }\n  return true;\n}\n\nint FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw()\n{\n  FOR_VECTOR (i, pairs)\n    if (pairs[i].ID.IsEqualTo(id))\n      return (int)i;\n  return -1;\n}\n\nUString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id)\n{\n  const int index = FindTextConfigItem(pairs, id);\n  if (index < 0)\n    return UString();\n  return pairs[index].String;\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/TextConfig.h",
    "content": "﻿// Common/TextConfig.h\n\n#ifndef ZIP7_INC_COMMON_TEXT_CONFIG_H\n#define ZIP7_INC_COMMON_TEXT_CONFIG_H\n\n#include \"MyString.h\"\n\nstruct CTextConfigPair\n{\n  UString ID;\n  UString String;\n};\n\nbool GetTextConfig(const AString &text, CObjectVector<CTextConfigPair> &pairs);\n\nint FindTextConfigItem(const CObjectVector<CTextConfigPair> &pairs, const char *id) throw();\nUString GetTextConfigValue(const CObjectVector<CTextConfigPair> &pairs, const char *id);\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/UTFConvert.cpp",
    "content": "﻿// UTFConvert.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#include \"MyTypes.h\"\n#include \"UTFConvert.h\"\n\n\n#ifndef Z7_WCHART_IS_16BIT\n#ifndef __APPLE__\n  // we define it if the system supports files with non-utf8 symbols:\n  #define MY_UTF8_RAW_NON_UTF8_SUPPORTED\n#endif\n#endif\n\n/*\n  MY_UTF8_START(n) - is a base value for start byte (head), if there are (n) additional bytes after start byte\n  \n  n : MY_UTF8_START(n) : Bits of code point\n\n  0 : 0x80 :    : unused\n  1 : 0xC0 : 11 :\n  2 : 0xE0 : 16 : Basic Multilingual Plane\n  3 : 0xF0 : 21 : Unicode space\n  4 : 0xF8 : 26 :\n  5 : 0xFC : 31 : UCS-4 : wcstombs() in ubuntu is limited to that value\n  6 : 0xFE : 36 : We can use it, if we want to encode any 32-bit value\n  7 : 0xFF :\n*/\n\n#define MY_UTF8_START(n) (0x100 - (1 << (7 - (n))))\n\n#define MY_UTF8_HEAD_PARSE2(n) \\\n    if (c < MY_UTF8_START((n) + 1)) \\\n    { numBytes = (n); val -= MY_UTF8_START(n); }\n\n#ifndef Z7_WCHART_IS_16BIT\n\n/*\n   if (wchar_t is 32-bit), we can support large points in long UTF-8 sequence,\n   when we convert wchar_t strings to UTF-8:\n     (_UTF8_NUM_TAIL_BYTES_MAX == 3) : (21-bits points) - Unicode\n     (_UTF8_NUM_TAIL_BYTES_MAX == 5) : (31-bits points) - UCS-4\n     (_UTF8_NUM_TAIL_BYTES_MAX == 6) : (36-bit hack)\n*/\n\n#define MY_UTF8_NUM_TAIL_BYTES_MAX 5\n#endif\n\n/*\n#define MY_UTF8_HEAD_PARSE \\\n    UInt32 val = c; \\\n         MY_UTF8_HEAD_PARSE2(1) \\\n    else MY_UTF8_HEAD_PARSE2(2) \\\n    else MY_UTF8_HEAD_PARSE2(3) \\\n    else MY_UTF8_HEAD_PARSE2(4) \\\n    else MY_UTF8_HEAD_PARSE2(5) \\\n  #if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6\n    else MY_UTF8_HEAD_PARSE2(6)\n  #endif\n*/\n\n#define MY_UTF8_HEAD_PARSE_MAX_3_BYTES \\\n    UInt32 val = c; \\\n         MY_UTF8_HEAD_PARSE2(1) \\\n    else MY_UTF8_HEAD_PARSE2(2) \\\n    else { numBytes = 3; val -= MY_UTF8_START(3); }\n\n\n#define MY_UTF8_RANGE(n) (((UInt32)1) << ((n) * 5 + 6))\n\n\n#define START_POINT_FOR_SURROGATE 0x10000\n\n\n/* we use 128 bytes block in 16-bit BMP-PLANE to encode non-UTF-8 Escapes\n   Also we can use additional HIGH-PLANE (we use 21-bit points above 0x1f0000)\n   to simplify internal intermediate conversion in Linux:\n   RAW-UTF-8 <-> internal wchar_t utf-16 strings <-> RAW-UTF-UTF-8\n*/\n \n\n#if defined(Z7_WCHART_IS_16BIT)\n\n#define UTF_ESCAPE_PLANE 0\n\n#else\n\n/*\nwe can place 128 ESCAPE chars to\n   ef 80 -    ee be 80 (3-bytes utf-8) : similar to WSL\n   ef ff -    ee bf bf\n\n1f ef 80 - f7 be be 80 (4-bytes utf-8) : last  4-bytes utf-8 plane (out of Unicode)\n1f ef ff - f7 be bf bf (4-bytes utf-8) : last  4-bytes utf-8 plane (out of Unicode)\n*/\n\n// #define UTF_ESCAPE_PLANE_HIGH  (0x1f << 16)\n// #define UTF_ESCAPE_PLANE        UTF_ESCAPE_PLANE_HIGH\n#define UTF_ESCAPE_PLANE 0\n\n/*\n  if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is set)\n  {\n    if (UTF_ESCAPE_PLANE is UTF_ESCAPE_PLANE_HIGH)\n    {\n      we can restore any 8-bit Escape from ESCAPE-PLANE-21 plane.\n      But ESCAPE-PLANE-21 point cannot be stored to utf-16 (7z archive)\n      So we still need a way to extract 8-bit Escapes and BMP-Escapes-8\n      from same BMP-Escapes-16 stored in 7z.\n      And if we want to restore any 8-bit from 7z archive,\n      we still must use Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT for (utf-8 -> utf-16)\n      Also we need additional Conversions to tranform from utf-16 to utf-16-With-Escapes-21\n    }\n    else (UTF_ESCAPE_PLANE == 0)\n    {\n      we must convert original 3-bytes utf-8 BMP-Escape point to sequence\n      of 3 BMP-Escape-16 points with Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT\n      so we can extract original RAW-UTF-8 from UTFD-16 later.\n    }\n  }\n*/\n\n#endif\n\n\n\n#define UTF_ESCAPE_BASE 0xef00\n\n\n#ifdef UTF_ESCAPE_BASE\n#define IS_ESCAPE_POINT(v, plane) (((v) & (UInt32)0xffffff80) == (plane) + UTF_ESCAPE_BASE + 0x80)\n#endif\n\n#define IS_SURROGATE_POINT(v)     (((v) & (UInt32)0xfffff800) == 0xd800)\n#define IS_LOW_SURROGATE_POINT(v) (((v) & (UInt32)0xfffffc00) == 0xdc00)\n\n\n#define UTF_ERROR_UTF8_CHECK \\\n  { NonUtf = true; continue; }\n\nvoid CUtf8Check::Check_Buf(const char *src, size_t size) throw()\n{\n  Clear();\n  // Byte maxByte = 0;\n\n  for (;;)\n  {\n    if (size == 0)\n      break;\n\n    const Byte c = (Byte)(*src++);\n    size--;\n\n    if (c == 0)\n    {\n      ZeroChar = true;\n      continue;\n    }\n\n    /*\n    if (c > maxByte)\n      maxByte = c;\n    */\n\n    if (c < 0x80)\n      continue;\n    \n    if (c < 0xc0 + 2)\n      UTF_ERROR_UTF8_CHECK\n\n    unsigned numBytes;\n    UInt32 val = c;\n         MY_UTF8_HEAD_PARSE2(1)\n    else MY_UTF8_HEAD_PARSE2(2)\n    else MY_UTF8_HEAD_PARSE2(3)\n    else MY_UTF8_HEAD_PARSE2(4)\n    else MY_UTF8_HEAD_PARSE2(5)\n    else\n    {\n      UTF_ERROR_UTF8_CHECK\n    }\n\n    unsigned pos = 0;\n    do\n    {\n      if (pos == size)\n        break;\n      unsigned c2 = (Byte)src[pos];\n      c2 -= 0x80;\n      if (c2 >= 0x40)\n        break;\n      val <<= 6;\n      val |= c2;\n      if (pos == 0)\n        if (val < (((unsigned)1 << 7) >> numBytes))\n          break;\n      pos++;\n    }\n    while (--numBytes);\n\n    if (numBytes != 0)\n    {\n      if (pos == size)\n        Truncated = true;\n      else\n        UTF_ERROR_UTF8_CHECK\n    }\n\n    #ifdef UTF_ESCAPE_BASE\n      if (IS_ESCAPE_POINT(val, 0))\n        Escape = true;\n    #endif\n\n    if (MaxHighPoint < val)\n      MaxHighPoint = val;\n\n    if (IS_SURROGATE_POINT(val))\n      SingleSurrogate = true;\n    \n    src += pos;\n    size -= pos;\n  }\n\n  // MaxByte = maxByte;\n}\n\nbool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw()\n{\n  CUtf8Check check;\n  check.Check_Buf(src, size);\n  return check.IsOK(allowReduced);\n}\n\n/*\nbool CheckUTF8_chars(const char *src, bool allowReduced) throw()\n{\n  CUtf8Check check;\n  check.CheckBuf(src, strlen(src));\n  return check.IsOK(allowReduced);\n}\n*/\n\nbool CheckUTF8_AString(const AString &s) throw()\n{\n  CUtf8Check check;\n  check.Check_AString(s);\n  return check.IsOK();\n}\n\n\n/*\nbool CheckUTF8(const char *src, bool allowReduced) throw()\n{\n  // return Check_UTF8_Buf(src, strlen(src), allowReduced);\n\n  for (;;)\n  {\n    const Byte c = (Byte)(*src++);\n    if (c == 0)\n      return true;\n\n    if (c < 0x80)\n      continue;\n    if (c < 0xC0 + 2 || c >= 0xf5)\n      return false;\n    \n    unsigned numBytes;\n    MY_UTF8_HEAD_PARSE\n    else\n      return false;\n\n    unsigned pos = 0;\n    \n    do\n    {\n      Byte c2 = (Byte)(*src++);\n      if (c2 < 0x80 || c2 >= 0xC0)\n        return allowReduced && c2 == 0;\n      val <<= 6;\n      val |= (c2 - 0x80);\n      pos++;\n    }\n    while (--numBytes);\n\n    if (val < MY_UTF8_RANGE(pos - 1))\n      return false;\n\n    if (val >= 0x110000)\n      return false;\n  }\n}\n*/\n\n// in case of UTF-8 error we have two ways:\n// 21.01- : old : 0xfffd: REPLACEMENT CHARACTER : old version\n// 21.02+ : new : 0xef00 + (c) : similar to WSL scheme for low symbols\n\n#define UTF_REPLACEMENT_CHAR  0xfffd\n\n\n\n#define UTF_ESCAPE(c) \\\n   ((flags & Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE) ? \\\n    UTF_ESCAPE_PLANE + UTF_ESCAPE_BASE + (c) : UTF_REPLACEMENT_CHAR)\n\n/*\n#define UTF_HARD_ERROR_UTF8\n  { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \\\n    destPos++; ok = false; continue; }\n*/\n\n// we ignore utf errors, and don't change (ok) variable!\n\n#define UTF_ERROR_UTF8 \\\n  { if (dest) dest[destPos] = (wchar_t)UTF_ESCAPE(c); \\\n    destPos++; continue; }\n\n// we store UTF-16 in wchar_t strings. So we use surrogates for big unicode points:\n\n// for debug puposes only we can store UTF-32 in wchar_t:\n// #define START_POINT_FOR_SURROGATE ((UInt32)0 - 1)\n\n\n/*\n  WIN32 MultiByteToWideChar(CP_UTF8) emits 0xfffd point, if utf-8 error was found.\n  Ant it can emit single 0xfffd from 2 src bytes.\n  It doesn't emit single 0xfffd from 3-4 src bytes.\n  We can\n    1) emit Escape point for each incorrect byte. So we can data recover later\n    2) emit 0xfffd for each incorrect byte.\n       That scheme is similar to Escape scheme, but we emit 0xfffd\n       instead of each Escape point.\n    3) emit single 0xfffd from 1-2 incorrect bytes, as WIN32 MultiByteToWideChar scheme\n*/\n\nstatic bool Utf8_To_Utf16(wchar_t *dest, size_t *destLen, const char *src, const char *srcLim, unsigned flags) throw()\n{\n  size_t destPos = 0;\n  bool ok = true;\n\n  for (;;)\n  {\n    if (src == srcLim)\n    {\n      *destLen = destPos;\n      return ok;\n    }\n    \n    const Byte c = (Byte)(*src++);\n\n    if (c < 0x80)\n    {\n      if (dest)\n        dest[destPos] = (wchar_t)c;\n      destPos++;\n      continue;\n    }\n    \n    if (c < 0xc0 + 2\n      || c >= 0xf5) // it's limit for 0x140000 unicode codes : win32 compatibility\n    {\n      UTF_ERROR_UTF8\n    }\n\n    unsigned numBytes;\n\n    MY_UTF8_HEAD_PARSE_MAX_3_BYTES\n\n    unsigned pos = 0;\n    do\n    {\n      if (src + pos == srcLim)\n        break;\n      unsigned c2 = (Byte)src[pos];\n      c2 -= 0x80;\n      if (c2 >= 0x40)\n        break;\n      val <<= 6;\n      val |= c2;\n      pos++;\n      if (pos == 1)\n      {\n        if (val < (((unsigned)1 << 7) >> numBytes))\n          break;\n        if (numBytes == 2)\n        {\n          if (flags & Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR)\n            if ((val & (0xF800 >> 6)) == (0xd800 >> 6))\n              break;\n        }\n        else if (numBytes == 3 && val >= (0x110000 >> 12))\n          break;\n      }\n    }\n    while (--numBytes);\n\n    if (numBytes != 0)\n    {\n      if ((flags & Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE) == 0)\n      {\n        // the following code to emit the 0xfffd chars as win32 Utf8 function.\n        // disable the folling line, if you need 0xfffd for each incorrect byte as in Escape mode\n        src += pos;\n      }\n      UTF_ERROR_UTF8\n    }\n\n    /*\n    if (val < MY_UTF8_RANGE(pos - 1))\n      UTF_ERROR_UTF8\n    */\n\n    #ifdef UTF_ESCAPE_BASE\n    \n      if ((flags & Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT)\n          && IS_ESCAPE_POINT(val, 0))\n      {\n        // We will emit 3 utf16-Escape-16-21 points from one Escape-16 point (3 bytes)\n        UTF_ERROR_UTF8\n      }\n    \n    #endif\n\n    /*\n       We don't expect virtual Escape-21 points in UTF-8 stream.\n       And we don't check for Escape-21.\n       So utf8-Escape-21 will be converted to another 3 utf16-Escape-21 points.\n       Maybe we could convert virtual utf8-Escape-21 to one utf16-Escape-21 point in some cases?\n    */\n    \n    if (val < START_POINT_FOR_SURROGATE)\n    {\n      /*\n      if ((flags & Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR)\n          && IS_SURROGATE_POINT(val))\n      {\n        // We will emit 3 utf16-Escape-16-21 points from one Surrogate-16 point (3 bytes)\n        UTF_ERROR_UTF8\n      }\n      */\n      if (dest)\n        dest[destPos] = (wchar_t)val;\n      destPos++;\n    }\n    else\n    {\n      /*\n      if (val >= 0x110000)\n      {\n        // We will emit utf16-Escape-16-21 point from each source byte\n        UTF_ERROR_UTF8\n      }\n      */\n      if (dest)\n      {\n        dest[destPos + 0] = (wchar_t)(0xd800 - (0x10000 >> 10) + (val >> 10));\n        dest[destPos + 1] = (wchar_t)(0xdc00 + (val & 0x3ff));\n      }\n      destPos += 2;\n    }\n    src += pos;\n  }\n}\n\n\n\n#define MY_UTF8_HEAD(n, val) ((char)(MY_UTF8_START(n) + (val >> (6 * (n)))))\n#define MY_UTF8_CHAR(n, val) ((char)(0x80 + (((val) >> (6 * (n))) & 0x3F)))\n\nstatic size_t Utf16_To_Utf8_Calc(const wchar_t *src, const wchar_t *srcLim, unsigned flags)\n{\n  size_t size = (size_t)(srcLim - src);\n  for (;;)\n  {\n    if (src == srcLim)\n      return size;\n    \n    UInt32 val = (UInt32)(*src++);\n   \n    if (val < 0x80)\n      continue;\n\n    if (val < MY_UTF8_RANGE(1))\n    {\n      size++;\n      continue;\n    }\n\n    #ifdef UTF_ESCAPE_BASE\n    \n    #if UTF_ESCAPE_PLANE != 0\n    if (flags & Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE)\n      if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE))\n        continue;\n    #endif\n    \n    if (flags & Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE)\n      if (IS_ESCAPE_POINT(val, 0))\n        continue;\n    \n    #endif\n\n    if (IS_SURROGATE_POINT(val))\n    {\n      // it's hack to UTF-8 encoding\n\n      if (val < 0xdc00 && src != srcLim)\n      {\n        const UInt32 c2 = (UInt32)*src;\n        if (c2 >= 0xdc00 && c2 < 0xe000)\n          src++;\n      }\n      size += 2;\n      continue;\n    }\n\n    #ifdef Z7_WCHART_IS_16BIT\n    \n    size += 2;\n    \n    #else\n\n         if (val < MY_UTF8_RANGE(2)) size += 2;\n    else if (val < MY_UTF8_RANGE(3)) size += 3;\n    else if (val < MY_UTF8_RANGE(4)) size += 4;\n    else if (val < MY_UTF8_RANGE(5)) size += 5;\n    else\n    #if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6\n      size += 6;\n    #else\n      size += 3;\n    #endif\n    \n    #endif\n  }\n}\n\n\nstatic char *Utf16_To_Utf8(char *dest, const wchar_t *src, const wchar_t *srcLim, unsigned flags)\n{\n  for (;;)\n  {\n    if (src == srcLim)\n      return dest;\n    \n    UInt32 val = (UInt32)*src++;\n    \n    if (val < 0x80)\n    {\n      *dest++ = (char)val;\n      continue;\n    }\n\n    if (val < MY_UTF8_RANGE(1))\n    {\n      dest[0] = MY_UTF8_HEAD(1, val);\n      dest[1] = MY_UTF8_CHAR(0, val);\n      dest += 2;\n      continue;\n    }\n\n    #ifdef UTF_ESCAPE_BASE\n    \n    #if UTF_ESCAPE_PLANE != 0\n    /*\n       if (wchar_t is 32-bit)\n            && (Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE is set)\n            && (point is virtual escape plane)\n          we extract 8-bit byte from virtual HIGH-ESCAPE PLANE.\n    */\n    if (flags & Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE)\n      if (IS_ESCAPE_POINT(val, UTF_ESCAPE_PLANE))\n      {\n        *dest++ = (char)(val);\n        continue;\n      }\n    #endif // UTF_ESCAPE_PLANE != 0\n\n    /* if (Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE is defined)\n          we extract 8-bit byte from BMP-ESCAPE PLANE. */\n\n    if (flags & Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE)\n      if (IS_ESCAPE_POINT(val, 0))\n      {\n        *dest++ = (char)(val);\n        continue;\n      }\n    \n    #endif // UTF_ESCAPE_BASE\n\n    if (IS_SURROGATE_POINT(val))\n    {\n      // it's hack to UTF-8 encoding\n      if (val < 0xdc00 && src != srcLim)\n      {\n        const UInt32 c2 = (UInt32)*src;\n        if (IS_LOW_SURROGATE_POINT(c2))\n        {\n          src++;\n          val = (((val - 0xd800) << 10) | (c2 - 0xdc00)) + 0x10000;\n          dest[0] = MY_UTF8_HEAD(3, val);\n          dest[1] = MY_UTF8_CHAR(2, val);\n          dest[2] = MY_UTF8_CHAR(1, val);\n          dest[3] = MY_UTF8_CHAR(0, val);\n          dest += 4;\n          continue;\n        }\n      }\n      if (flags & Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR)\n        val = UTF_REPLACEMENT_CHAR; // WIN32 function does it\n    }\n\n    #ifndef Z7_WCHART_IS_16BIT\n    if (val < MY_UTF8_RANGE(2))\n    #endif\n    {\n      dest[0] = MY_UTF8_HEAD(2, val);\n      dest[1] = MY_UTF8_CHAR(1, val);\n      dest[2] = MY_UTF8_CHAR(0, val);\n      dest += 3;\n      continue;\n    }\n    \n    #ifndef Z7_WCHART_IS_16BIT\n\n    // we don't expect this case. so we can throw exception\n    // throw 20210407;\n   \n    char b;\n    unsigned numBits;\n         if (val < MY_UTF8_RANGE(3)) { numBits = 6 * 3; b = MY_UTF8_HEAD(3, val); }\n    else if (val < MY_UTF8_RANGE(4)) { numBits = 6 * 4; b = MY_UTF8_HEAD(4, val); }\n    else if (val < MY_UTF8_RANGE(5)) { numBits = 6 * 5; b = MY_UTF8_HEAD(5, val); }\n    #if MY_UTF8_NUM_TAIL_BYTES_MAX >= 6\n    else                           { numBits = 6 * 6; b = (char)MY_UTF8_START(6); }\n    #else\n    else\n    {\n      val = UTF_REPLACEMENT_CHAR;\n                                   { numBits = 6 * 3; b = MY_UTF8_HEAD(3, val); }\n    }\n    #endif\n\n    *dest++ = b;\n    \n    do\n    {\n      numBits -= 6;\n      *dest++ = (char)(0x80 + ((val >> numBits) & 0x3F));\n    }\n    while (numBits != 0);\n\n    #endif\n  }\n}\n\nbool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags)\n{\n  dest.Empty();\n  size_t destLen = 0;\n  Utf8_To_Utf16(NULL, &destLen, src, src + srcSize, flags);\n  bool res = Utf8_To_Utf16(dest.GetBuf((unsigned)destLen), &destLen, src, src + srcSize, flags);\n  dest.ReleaseBuf_SetEnd((unsigned)destLen);\n  return res;\n}\n\nbool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags)\n{\n  return Convert_UTF8_Buf_To_Unicode(src, src.Len(), dest,  flags);\n}\n\n\nstatic\nunsigned g_UTF8_To_Unicode_Flags =\n    Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE\n  #ifndef Z7_WCHART_IS_16BIT\n    | Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR\n  #ifdef MY_UTF8_RAW_NON_UTF8_SUPPORTED\n    | Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT\n  #endif\n  #endif\n    ;\n    \n\n/*\nbool ConvertUTF8ToUnicode_boolRes(const AString &src, UString &dest)\n{\n  return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags);\n}\n*/\n\nbool ConvertUTF8ToUnicode(const AString &src, UString &dest)\n{\n  return ConvertUTF8ToUnicode_Flags(src, dest, g_UTF8_To_Unicode_Flags);\n}\n\nvoid Print_UString(const UString &a);\n\nvoid ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags)\n{\n  /*\n  if (src.Len()== 24)\n    throw \"202104\";\n  */\n  dest.Empty();\n  const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags);\n  char *destStart = dest.GetBuf((unsigned)destLen);\n  const char *destEnd = Utf16_To_Utf8(destStart, src, src.Ptr(src.Len()), flags);\n  dest.ReleaseBuf_SetEnd((unsigned)destLen);\n  // printf(\"\\nlen = %d\\n\", src.Len());\n  if (destLen != (size_t)(destEnd - destStart))\n  {\n    /*\n    // dest.ReleaseBuf_SetEnd((unsigned)(destEnd - destStart));\n    printf(\"\\nlen = %d\\n\", (unsigned)destLen);\n    printf(\"\\n(destEnd - destStart) = %d\\n\", (unsigned)(destEnd - destStart));\n    printf(\"\\n\");\n    // Print_UString(src);\n    printf(\"\\n\");\n    // printf(\"\\nlen = %d\\n\", destLen);\n    */\n    throw 20210406;\n  }\n}\n\n\n\nunsigned g_Unicode_To_UTF8_Flags =\n      // Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE\n      0\n  #ifndef _WIN32\n    #ifdef MY_UTF8_RAW_NON_UTF8_SUPPORTED\n      | Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE\n    #else\n      | Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR\n    #endif\n  #endif\n    ;\n\nvoid ConvertUnicodeToUTF8(const UString &src, AString &dest)\n{\n  ConvertUnicodeToUTF8_Flags(src, dest, g_Unicode_To_UTF8_Flags);\n}\n\nvoid Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest)\n{\n  const unsigned flags = g_Unicode_To_UTF8_Flags;\n  dest.Free();\n  const size_t destLen = Utf16_To_Utf8_Calc(src, src.Ptr(src.Len()), flags);\n  dest.Alloc(destLen);\n  const char *destEnd = Utf16_To_Utf8((char *)(void *)(Byte *)dest, src, src.Ptr(src.Len()), flags);\n  if (destLen != (size_t)(destEnd - (char *)(void *)(Byte *)dest))\n    throw 202104;\n}\n\n/*\n\n#ifndef _WIN32\nvoid Convert_UTF16_To_UTF32(const UString &src, UString &dest)\n{\n  dest.Empty();\n  for (size_t i = 0; i < src.Len();)\n  {\n    wchar_t c = src[i++];\n    if (c >= 0xd800 && c < 0xdc00 && i < src.Len())\n    {\n      const wchar_t c2 = src[i];\n      if (c2 >= 0xdc00 && c2 < 0xe000)\n      {\n        // printf(\"\\nSurragate [%d]: %4x %4x -> \", i, (int)c, (int)c2);\n        c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);\n        // printf(\"%4x\\n\", (int)c);\n        i++;\n      }\n    }\n    dest += c;\n  }\n}\n\nvoid Convert_UTF32_To_UTF16(const UString &src, UString &dest)\n{\n  dest.Empty();\n  for (size_t i = 0; i < src.Len();)\n  {\n    wchar_t w = src[i++];\n    if (w >= 0x10000 && w < 0x110000)\n    {\n      w -= 0x10000;\n      dest += (wchar_t)((unsigned)0xd800 + (((unsigned)w >> 10) & 0x3ff));\n      w = 0xdc00 + (w & 0x3ff);\n    }\n    dest += w;\n  }\n}\n\nbool UTF32_IsThere_BigPoint(const UString &src)\n{\n  for (size_t i = 0; i < src.Len();)\n  {\n    const UInt32 c = (UInt32)src[i++];\n    if (c >= 0x110000)\n      return true;\n  }\n  return false;\n}\n\nbool Unicode_IsThere_BmpEscape(const UString &src)\n{\n  for (size_t i = 0; i < src.Len();)\n  {\n    const UInt32 c = (UInt32)src[i++];\n    if (IS_ESCAPE_POINT(c, 0))\n      return true;\n  }\n  return false;\n}\n\n\n#endif\n\nbool Unicode_IsThere_Utf16SurrogateError(const UString &src)\n{\n  for (size_t i = 0; i < src.Len();)\n  {\n    const UInt32 val = (UInt32)src[i++];\n    if (IS_SURROGATE_POINT(val))\n    {\n      // it's hack to UTF-8 encoding\n      if (val >= 0xdc00 || i == src.Len())\n        return true;\n      const UInt32 c2 = (UInt32)*src;\n      if (!IS_LOW_SURROGATE_POINT(c2))\n        return true;\n    }\n  }\n  return false;\n}\n*/\n\n#ifndef Z7_WCHART_IS_16BIT\n\nvoid Convert_UnicodeEsc16_To_UnicodeEscHigh\n#if UTF_ESCAPE_PLANE == 0\n    (UString &) {}\n#else\n    (UString &s)\n{\n  const unsigned len = s.Len();\n  for (unsigned i = 0; i < len; i++)\n  {\n    wchar_t c = s[i];\n    if (IS_ESCAPE_POINT(c, 0))\n    {\n      c += UTF_ESCAPE_PLANE;\n      s.ReplaceOneCharAtPos(i, c);\n    }\n  }\n}\n#endif\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/UTFConvert.h",
    "content": "﻿// Common/UTFConvert.h\n\n#ifndef ZIP7_INC_COMMON_UTF_CONVERT_H\n#define ZIP7_INC_COMMON_UTF_CONVERT_H\n\n#include \"MyBuffer.h\"\n#include \"MyString.h\"\n\nstruct CUtf8Check\n{\n  // Byte MaxByte;     // in original src stream\n  bool NonUtf;\n  bool ZeroChar;\n  bool SingleSurrogate;\n  bool Escape;\n  bool Truncated;\n  UInt32 MaxHighPoint;  // only for points >= 0x80\n\n  CUtf8Check() { Clear(); }\n\n  void Clear()\n  {\n    // MaxByte = 0;\n    NonUtf = false;\n    ZeroChar = false;\n    SingleSurrogate = false;\n    Escape = false;\n    Truncated = false;\n    MaxHighPoint = 0;\n  }\n\n  void Update(const CUtf8Check &c)\n  {\n    if (c.NonUtf) NonUtf = true;\n    if (c.ZeroChar) ZeroChar = true;\n    if (c.SingleSurrogate) SingleSurrogate = true;\n    if (c.Escape) Escape = true;\n    if (c.Truncated) Truncated = true;\n    if (MaxHighPoint < c.MaxHighPoint) MaxHighPoint = c.MaxHighPoint;\n  }\n\n  void PrintStatus(AString &s) const\n  {\n    s.Empty();\n\n    // s.Add_OptSpaced(\"MaxByte=\");\n    // s.Add_UInt32(MaxByte);\n\n    if (NonUtf)          s.Add_OptSpaced(\"non-UTF8\");\n    if (ZeroChar)        s.Add_OptSpaced(\"ZeroChar\");\n    if (SingleSurrogate) s.Add_OptSpaced(\"SingleSurrogate\");\n    if (Escape)          s.Add_OptSpaced(\"Escape\");\n    if (Truncated)       s.Add_OptSpaced(\"Truncated\");\n\n    if (MaxHighPoint != 0)\n    {\n      s.Add_OptSpaced(\"MaxUnicode=\");\n      s.Add_UInt32(MaxHighPoint);\n    }\n  }\n\n\n  bool IsOK(bool allowReduced = false) const\n  {\n    if (NonUtf || SingleSurrogate || ZeroChar)\n      return false;\n    if (MaxHighPoint >= 0x110000)\n      return false;\n    if (Truncated && !allowReduced)\n      return false;\n    return true;\n  }\n\n  // it checks full buffer as specified in (size) and it doesn't stop on zero char\n  void Check_Buf(const char *src, size_t size) throw();\n\n  void Check_AString(const AString &s) throw()\n  {\n    Check_Buf(s.Ptr(), s.Len());\n  }\n};\n\n/*\nif (allowReduced == false) - all UTF-8 character sequences must be finished.\nif (allowReduced == true)  - it allows truncated last character-Utf8-sequence\n*/\n\nbool Check_UTF8_Buf(const char *src, size_t size, bool allowReduced) throw();\nbool CheckUTF8_AString(const AString &s) throw();\n\n#define Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR    (1 << 0)\n#define Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE         (1 << 1)\n#define Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT (1 << 2)\n\n/*\nZ7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR\n\n   if (flag is NOT set)\n   {\n     it processes SINGLE-SURROGATE-8 as valid Unicode point.\n     it converts  SINGLE-SURROGATE-8 to SINGLE-SURROGATE-16\n     Note: some sequencies of two SINGLE-SURROGATE-8 points\n           will generate correct SURROGATE-16-PAIR, and\n           that SURROGATE-16-PAIR later will be converted to correct\n           UTF8-SURROGATE-21 point. So we don't restore original\n           STR-8 sequence in that case.\n   }\n   \n   if (flag is set)\n   {\n     if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is defined)\n        it generates ESCAPE for SINGLE-SURROGATE-8,\n     if (Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE is not defined)\n        it generates U+fffd for SINGLE-SURROGATE-8,\n   }\n\n\nZ7_UTF_FLAG_FROM_UTF8_USE_ESCAPE\n\n   if (flag is NOT set)\n     it generates (U+fffd) code for non-UTF-8 (invalid) characters\n\n   if (flag is set)\n   {\n     It generates (ESCAPE) codes for NON-UTF-8 (invalid) characters.\n     And later we can restore original UTF-8-RAW characters from (ESCAPE-16-21) codes.\n   }\n\nZ7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT\n\n   if (flag is NOT set)\n   {\n     it process ESCAPE-8 points as another Unicode points.\n     In Linux: ESCAPE-16 will mean two different ESCAPE-8 seqences,\n       so we need HIGH-ESCAPE-PLANE-21 to restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW\n   }\n\n   if (flag is set)\n   {\n     it generates ESCAPE-16-21 for ESCAPE-8 points\n     so we can restore UTF-8-RAW -> UTF-16 -> UTF-8-RAW without HIGH-ESCAPE-PLANE-21.\n   }\n\n\nMain USE CASES with UTF-8 <-> UTF-16 conversions:\n\n WIN32:   UTF-16-RAW -> UTF-8 (Archive) -> UTF-16-RAW\n   {\n            set Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE\n     Do NOT set Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR\n     Do NOT set Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT\n     \n     So we restore original SINGLE-SURROGATE-16 from single SINGLE-SURROGATE-8.\n   }\n\n Linux:   UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW\n   {\n     we want restore original UTF-8-RAW sequence later from that ESCAPE-16.\n     Set the flags:\n       Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR\n       Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE\n       Z7_UTF_FLAG_FROM_UTF8_BMP_ESCAPE_CONVERT\n   }\n\n MacOS:   UTF-8-RAW -> UTF-16 (Intermediate / Archive) -> UTF-8-RAW\n   {\n     we want to restore correct UTF-8 without any BMP processing:\n     Set the flags:\n       Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR\n       Z7_UTF_FLAG_FROM_UTF8_USE_ESCAPE\n   }\n\n*/\n\n// zero char is not allowed in (src) buf\nbool Convert_UTF8_Buf_To_Unicode(const char *src, size_t srcSize, UString &dest, unsigned flags = 0);\n\nbool ConvertUTF8ToUnicode_Flags(const AString &src, UString &dest, unsigned flags = 0);\nbool ConvertUTF8ToUnicode(const AString &src, UString &dest);\n\n#define Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR    (1 << 8)\n#define Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE (1 << 9)\n// #define Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE  (1 << 10)\n\n/*\nZ7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR\n\n  if (flag is NOT set)\n  {\n     we extract SINGLE-SURROGATE as normal UTF-8\n     \n     In Windows : for UTF-16-RAW <-> UTF-8 (archive) <-> UTF-16-RAW in .\n     \n     In Linux :\n       use-case-1: UTF-8 -> UTF-16 -> UTF-8  doesn't generate UTF-16 SINGLE-SURROGATE,\n                   if (Z7_UTF_FLAG_FROM_UTF8_SURROGATE_ERROR) is used.\n       use-case 2: UTF-16-7z (with SINGLE-SURROGATE from Windows) -> UTF-8 (Linux)\n                   will generate SINGLE-SURROGATE-UTF-8 here.\n  }\n\n  if (flag is set)\n  {\n     we generate UTF_REPLACEMENT_CHAR (0xfffd) for SINGLE_SURROGATE\n     it can be used for compatibility mode with WIN32 UTF function\n     or if we want UTF-8 stream without any errors\n  }\n\n\nZ7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE\n  \n  if (flag is NOT set) it doesn't extract  raw 8-bit symbol from Escape-Plane-16\n  if (flag is set)     it         extracts raw 8-bit symbol from Escape-Plane-16\n\n  in Linux we need some way to extract NON-UTF8 RAW 8-bits from BMP (UTF-16 7z archive):\n  if (we       use High-Escape-Plane), we can transfer BMP escapes to High-Escape-Plane.\n  if (we don't use High-Escape-Plane), we must use Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE.\n    \n\nZ7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE\n  // that flag affects the code only if (wchar_t is 32-bit)\n  // that mode with high-escape can be disabled now in UTFConvert.cpp\n  if (flag is NOT set)\n     it doesn't extract raw 8-bit symbol from High-Escape-Plane\n  if (flag is set)\n     it        extracts raw 8-bit symbol from High-Escape-Plane\n\nMain use cases:\n\nWIN32 : UTF-16-RAW -> UTF-8 (archive) -> UTF-16-RAW\n   {\n     Do NOT set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE.\n     Do NOT set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR.\n     So we restore original UTF-16-RAW.\n   }\n\nLinix : UTF-8 with Escapes -> UTF-16 (7z archive) -> UTF-8 with Escapes\n     set Z7_UTF_FLAG_TO_UTF8_EXTRACT_BMP_ESCAPE to extract non-UTF from 7z archive\n     set Z7_UTF_FLAG_TO_UTF8_PARSE_HIGH_ESCAPE for intermediate UTF-16.\n     Note: high esacape mode can be ignored now in UTFConvert.cpp\n\nmacOS:\n     the system doesn't support incorrect UTF-8 in file names.\n     set Z7_UTF_FLAG_TO_UTF8_SURROGATE_ERROR\n*/\n\nextern unsigned g_Unicode_To_UTF8_Flags;\n\nvoid ConvertUnicodeToUTF8_Flags(const UString &src, AString &dest, unsigned flags = 0);\nvoid ConvertUnicodeToUTF8(const UString &src, AString &dest);\n\nvoid Convert_Unicode_To_UTF8_Buf(const UString &src, CByteBuffer &dest);\n\n/*\n#ifndef _WIN32\nvoid Convert_UTF16_To_UTF32(const UString &src, UString &dest);\nvoid Convert_UTF32_To_UTF16(const UString &src, UString &dest);\nbool UTF32_IsThere_BigPoint(const UString &src);\nbool Unicode_IsThere_BmpEscape(const UString &src);\n#endif\n\nbool Unicode_IsThere_Utf16SurrogateError(const UString &src);\n*/\n\n#ifdef Z7_WCHART_IS_16BIT\n#define Convert_UnicodeEsc16_To_UnicodeEscHigh(s)\n#else\nvoid Convert_UnicodeEsc16_To_UnicodeEscHigh(UString &s);\n#endif\n\n/*\n// #include \"../../C/CpuArch.h\"\n\n// ---------- Utf16 Little endian functions ----------\n\n// We store 16-bit surrogates even in 32-bit WCHARs in Linux.\n// So now we don't use the following code:\n\n#if WCHAR_MAX > 0xffff\n\n// void *p     : pointer to src bytes stream\n// size_t len  : num Utf16 characters : it can include or not include NULL character\n\ninline size_t Utf16LE__Get_Num_WCHARs(const void *p, size_t len)\n{\n  #if WCHAR_MAX > 0xffff\n  size_t num_wchars = 0;\n  for (size_t i = 0; i < len; i++)\n  {\n    wchar_t c = GetUi16(p);\n    p = (const void *)((const Byte *)p + 2);\n    if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)\n    {\n      wchar_t c2 = GetUi16(p);\n      if (c2 >= 0xdc00 && c2 < 0xe000)\n      {\n        c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);\n        p = (const void *)((const Byte *)p + 2);\n        i++;\n      }\n    }\n    num_wchars++;\n  }\n  return num_wchars;\n  #else\n  UNUSED_VAR(p)\n  return len;\n  #endif\n}\n\n// #include <stdio.h>\n\ninline wchar_t *Utf16LE__To_WCHARs_Sep(const void *p, size_t len, wchar_t *dest)\n{\n  for (size_t i = 0; i < len; i++)\n  {\n    wchar_t c = GetUi16(p);\n    p = (const void *)((const Byte *)p + 2);\n    \n    #if WCHAR_PATH_SEPARATOR != L'/'\n    if (c == L'/')\n      c = WCHAR_PATH_SEPARATOR;\n    #endif\n    \n    #if WCHAR_MAX > 0xffff\n    \n    if (c >= 0xd800 && c < 0xdc00 && i + 1 != len)\n    {\n      wchar_t c2 = GetUi16(p);\n      if (c2 >= 0xdc00 && c2 < 0xe000)\n      {\n        // printf(\"\\nSurragate : %4x %4x -> \", (int)c, (int)c2);\n        c = 0x10000 + ((c & 0x3ff) << 10) + (c2 & 0x3ff);\n        p = (const void *)((const Byte *)p + 2);\n        i++;\n        // printf(\"%4x\\n\", (int)c);\n      }\n    }\n    \n    #endif\n    \n    *dest++ = c;\n  }\n  return dest;\n}\n\n\ninline size_t Get_Num_Utf16_chars_from_wchar_string(const wchar_t *p)\n{\n  size_t num = 0;\n  for (;;)\n  {\n    wchar_t c = *p++;\n    if (c == 0)\n      return num;\n    num += ((c >= 0x10000 && c < 0x110000) ? 2 : 1);\n  }\n  return num;\n}\n\ninline Byte *wchars_to_Utf16LE(const wchar_t *p, Byte *dest)\n{\n  for (;;)\n  {\n    wchar_t c = *p++;\n    if (c == 0)\n      return dest;\n    if (c >= 0x10000 && c < 0x110000)\n    {\n      SetUi16(dest    , (UInt16)(0xd800 + ((c >> 10) & 0x3FF)));\n      SetUi16(dest + 2, (UInt16)(0xdc00 + ( c        & 0x3FF)));\n      dest += 4;\n    }\n    else\n    {\n      SetUi16(dest, c);\n      dest += 2;\n    }\n  }\n}\n\n#endif\n*/\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/Wildcard.cpp",
    "content": "﻿// Common/Wildcard.cpp\n\n#include \"StdAfx.h\"\n\n#include \"Wildcard.h\"\n\nextern\nbool g_CaseSensitive;\nbool g_CaseSensitive =\n  #ifdef _WIN32\n    false;\n  #elif defined (__APPLE__)\n    #ifdef TARGET_OS_IPHONE\n      true;\n    #else\n      false;\n    #endif\n  #else\n    true;\n  #endif\n\n\nbool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2)\n{\n  if (g_CaseSensitive)\n    return IsString1PrefixedByString2(s1, s2);\n  return IsString1PrefixedByString2_NoCase(s1, s2);\n}\n\n// #include <stdio.h>\n\n/*\nstatic int MyStringCompare_PathLinux(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    wchar_t c1 = *s1++;\n    wchar_t c2 = *s2++;\n    if (c1 != c2)\n    {\n      if (c1 == 0) return -1;\n      if (c2 == 0) return 1;\n      if (c1 == '/') c1 = 0;\n      if (c2 == '/') c2 = 0;\n      if (c1 < c2) return -1;\n      if (c1 > c2) return 1;\n      continue;\n    }\n    if (c1 == 0) return 0;\n  }\n}\n*/\n\nstatic int MyStringCompare_Path(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    wchar_t c1 = *s1++;\n    wchar_t c2 = *s2++;\n    if (c1 != c2)\n    {\n      if (c1 == 0) return -1;\n      if (c2 == 0) return 1;\n      if (IS_PATH_SEPAR(c1)) c1 = 0;\n      if (IS_PATH_SEPAR(c2)) c2 = 0;\n      if (c1 < c2) return -1;\n      if (c1 > c2) return 1;\n      continue;\n    }\n    if (c1 == 0) return 0;\n  }\n}\n\nstatic int MyStringCompareNoCase_Path(const wchar_t *s1, const wchar_t *s2) throw()\n{\n  for (;;)\n  {\n    wchar_t c1 = *s1++;\n    wchar_t c2 = *s2++;\n    if (c1 != c2)\n    {\n      if (c1 == 0) return -1;\n      if (c2 == 0) return 1;\n      if (IS_PATH_SEPAR(c1)) c1 = 0;\n      if (IS_PATH_SEPAR(c2)) c2 = 0;\n      c1 = MyCharUpper(c1);\n      c2 = MyCharUpper(c2);\n      if (c1 < c2) return -1;\n      if (c1 > c2) return 1;\n      continue;\n    }\n    if (c1 == 0) return 0;\n  }\n}\n\nint CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW\n{\n  /*\n  printf(\"\\nCompareFileNames\");\n  printf(\"\\n S1: %ls\", s1);\n  printf(\"\\n S2: %ls\", s2);\n  printf(\"\\n\");\n  */\n  // 21.07 : we parse PATH_SEPARATOR so: 0 < PATH_SEPARATOR < 1\n  if (g_CaseSensitive)\n    return MyStringCompare_Path(s1, s2);\n  return MyStringCompareNoCase_Path(s1, s2);\n}\n\n#ifndef USE_UNICODE_FSTRING\nint CompareFileNames(const char *s1, const char *s2)\n{\n  const UString u1 = fs2us(s1);\n  const UString u2 = fs2us(s2);\n  return CompareFileNames(u1, u2);\n}\n#endif\n\n// -----------------------------------------\n// this function compares name with mask\n// ? - any char\n// * - any char or empty\n\nstatic bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)\n{\n  for (;;)\n  {\n    const wchar_t m = *mask;\n    const wchar_t c = *name;\n    if (m == 0)\n      return (c == 0);\n    if (m == '*')\n    {\n      if (EnhancedMaskTest(mask + 1, name))\n        return true;\n      if (c == 0)\n        return false;\n    }\n    else\n    {\n      if (m == '?')\n      {\n        if (c == 0)\n          return false;\n      }\n      else if (m != c)\n        if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))\n          return false;\n      mask++;\n    }\n    name++;\n  }\n}\n\n// --------------------------------------------------\n// Splits path to strings\n\nvoid SplitPathToParts(const UString &path, UStringVector &pathParts)\n{\n  pathParts.Clear();\n  unsigned len = path.Len();\n  if (len == 0)\n    return;\n  UString name;\n  unsigned prev = 0;\n  for (unsigned i = 0; i < len; i++)\n    if (IsPathSepar(path[i]))\n    {\n      name.SetFrom(path.Ptr(prev), i - prev);\n      pathParts.Add(name);\n      prev = i + 1;\n    }\n  name.SetFrom(path.Ptr(prev), len - prev);\n  pathParts.Add(name);\n}\n\nvoid SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name)\n{\n  const wchar_t *start = path;\n  const wchar_t *p = start + path.Len();\n  for (; p != start; p--)\n    if (IsPathSepar(*(p - 1)))\n      break;\n  dirPrefix.SetFrom(path, (unsigned)(p - start));\n  name = p;\n}\n\nvoid SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name)\n{\n  const wchar_t *start = path;\n  const wchar_t *p = start + path.Len();\n  if (p != start)\n  {\n    if (IsPathSepar(*(p - 1)))\n      p--;\n    for (; p != start; p--)\n      if (IsPathSepar(*(p - 1)))\n        break;\n  }\n  dirPrefix.SetFrom(path, (unsigned)(p - start));\n  name = p;\n}\n\n/*\nUString ExtractDirPrefixFromPath(const UString &path)\n{\n  return path.Left(path.ReverseFind_PathSepar() + 1));\n}\n*/\n\nUString ExtractFileNameFromPath(const UString &path)\n{\n  return UString(path.Ptr((unsigned)(path.ReverseFind_PathSepar() + 1)));\n}\n\n\nbool DoesWildcardMatchName(const UString &mask, const UString &name)\n{\n  return EnhancedMaskTest(mask, name);\n}\n\nbool DoesNameContainWildcard(const UString &path)\n{\n  for (unsigned i = 0; i < path.Len(); i++)\n  {\n    wchar_t c = path[i];\n    if (c == '*' || c == '?')\n      return true;\n  }\n  return false;\n}\n\n\n// ----------------------------------------------------------'\n// NWildcard\n\nnamespace NWildcard {\n\n/*\n\nM = MaskParts.Size();\nN = TestNameParts.Size();\n\n                           File                          Dir\nForFile     rec   M<=N  [N-M, N)                          -\n!ForDir  nonrec   M=N   [0, M)                            -\n \nForDir      rec   M<N   [0, M) ... [N-M-1, N-1)  same as ForBoth-File\n!ForFile nonrec         [0, M)                   same as ForBoth-File\n\nForFile     rec   m<=N  [0, M) ... [N-M, N)      same as ForBoth-File\nForDir   nonrec         [0, M)                   same as ForBoth-File\n\n*/\n\nbool CItem::AreAllAllowed() const\n{\n  return ForFile && ForDir && WildcardMatching\n      && PathParts.Size() == 1 && PathParts.Front().IsEqualTo(\"*\");\n}\n\nbool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const\n{\n  if (!isFile && !ForDir)\n    return false;\n\n  /*\n  if (PathParts.IsEmpty())\n  {\n    // PathParts.IsEmpty() means all items (universal wildcard)\n    if (!isFile)\n      return true;\n    if (pathParts.Size() <= 1)\n      return ForFile;\n    return (ForDir || Recursive && ForFile);\n  }\n  */\n\n  int delta = (int)pathParts.Size() - (int)PathParts.Size();\n  if (delta < 0)\n    return false;\n  int start = 0;\n  int finish = 0;\n  \n  if (isFile)\n  {\n    if (!ForDir)\n    {\n      if (Recursive)\n        start = delta;\n      else if (delta !=0)\n        return false;\n    }\n    if (!ForFile && delta == 0)\n      return false;\n  }\n  \n  if (Recursive)\n  {\n    finish = delta;\n    if (isFile && !ForFile)\n      finish = delta - 1;\n  }\n  \n  for (int d = start; d <= finish; d++)\n  {\n    unsigned i;\n    for (i = 0; i < PathParts.Size(); i++)\n    {\n      if (WildcardMatching)\n      {\n        if (!DoesWildcardMatchName(PathParts[i], pathParts[i + (unsigned)d]))\n          break;\n      }\n      else\n      {\n        if (CompareFileNames(PathParts[i], pathParts[i + (unsigned)d]) != 0)\n          break;\n      }\n    }\n    if (i == PathParts.Size())\n      return true;\n  }\n  return false;\n}\n\nbool CCensorNode::AreAllAllowed() const\n{\n  if (!Name.IsEmpty() ||\n      !SubNodes.IsEmpty() ||\n      !ExcludeItems.IsEmpty() ||\n      IncludeItems.Size() != 1)\n    return false;\n  return IncludeItems.Front().AreAllAllowed();\n}\n\nint CCensorNode::FindSubNode(const UString &name) const\n{\n  FOR_VECTOR (i, SubNodes)\n    if (CompareFileNames(SubNodes[i].Name, name) == 0)\n      return (int)i;\n  return -1;\n}\n\nvoid CCensorNode::AddItemSimple(bool include, CItem &item)\n{\n  CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;\n  items.Add(item);\n}\n\nvoid CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex)\n{\n  if (item.PathParts.Size() <= 1)\n  {\n    if (item.PathParts.Size() != 0 && item.WildcardMatching)\n    {\n      if (!DoesNameContainWildcard(item.PathParts.Front()))\n        item.WildcardMatching = false;\n    }\n    AddItemSimple(include, item);\n    return;\n  }\n\n  const UString &front = item.PathParts.Front();\n  \n  // WIN32 doesn't support wildcards in file names\n  if (item.WildcardMatching\n      && ignoreWildcardIndex != 0\n      && DoesNameContainWildcard(front))\n  {\n    AddItemSimple(include, item);\n    return;\n  }\n  CCensorNode &subNode = Find_SubNode_Or_Add_New(front);\n  item.PathParts.Delete(0);\n  subNode.AddItem(include, item, ignoreWildcardIndex - 1);\n}\n\n/*\nvoid CCensorNode::AddItem(bool include, const UString &path, const CCensorPathProps &props)\n{\n  CItem item;\n  SplitPathToParts(path, item.PathParts);\n  item.Recursive = props.Recursive;\n  item.ForFile = props.ForFile;\n  item.ForDir = props.ForDir;\n  item.WildcardMatching = props.WildcardMatching;\n  AddItem(include, item);\n}\n*/\n\nbool CCensorNode::NeedCheckSubDirs() const\n{\n  FOR_VECTOR (i, IncludeItems)\n  {\n    const CItem &item = IncludeItems[i];\n    if (item.Recursive || item.PathParts.Size() > 1)\n      return true;\n  }\n  return false;\n}\n\nbool CCensorNode::AreThereIncludeItems() const\n{\n  if (IncludeItems.Size() > 0)\n    return true;\n  FOR_VECTOR (i, SubNodes)\n    if (SubNodes[i].AreThereIncludeItems())\n      return true;\n  return false;\n}\n\nbool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const\n{\n  const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;\n  FOR_VECTOR (i, items)\n    if (items[i].CheckPath(pathParts, isFile))\n      return true;\n  return false;\n}\n\nbool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const\n{\n  if (CheckPathCurrent(false, pathParts, isFile))\n  {\n    include = false;\n    return true;\n  }\n  if (pathParts.Size() > 1)\n  {\n    int index = FindSubNode(pathParts.Front());\n    if (index >= 0)\n    {\n      UStringVector pathParts2 = pathParts;\n      pathParts2.Delete(0);\n      if (SubNodes[(unsigned)index].CheckPathVect(pathParts2, isFile, include))\n        return true;\n    }\n  }\n  bool finded = CheckPathCurrent(true, pathParts, isFile);\n  include = finded; // if (!finded), then (true) is allowed also\n  return finded;\n}\n\n/*\nbool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const\n{\n  UStringVector pathParts;\n  SplitPathToParts(path, pathParts);\n  if (CheckPathVect(pathParts, isFile, include))\n  {\n    if (!include || !isAltStream)\n      return true;\n  }\n  if (isAltStream && !pathParts.IsEmpty())\n  {\n    UString &back = pathParts.Back();\n    int pos = back.Find(L':');\n    if (pos > 0)\n    {\n      back.DeleteFrom(pos);\n      return CheckPathVect(pathParts, isFile, include);\n    }\n  }\n  return false;\n}\n\nbool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const\n{\n  bool include;\n  if (CheckPath2(isAltStream, path, isFile, include))\n    return include;\n  return false;\n}\n*/\n\nbool CCensorNode::CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const\n{\n  if (CheckPathCurrent(include, pathParts, isFile))\n    return true;\n  if (!Parent)\n    return false;\n  pathParts.Insert(0, Name);\n  return Parent->CheckPathToRoot_Change(include, pathParts, isFile);\n}\n\nbool CCensorNode::CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const\n{\n  if (CheckPathCurrent(include, pathParts, isFile))\n    return true;\n  if (!Parent)\n    return false;\n  UStringVector pathParts2;\n  pathParts2.Add(Name);\n  pathParts2 += pathParts;\n  return Parent->CheckPathToRoot_Change(include, pathParts2, isFile);\n}\n\n/*\nbool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const\n{\n  UStringVector pathParts;\n  SplitPathToParts(path, pathParts);\n  return CheckPathToRoot(include, pathParts, isFile);\n}\n*/\n\nvoid CCensorNode::ExtendExclude(const CCensorNode &fromNodes)\n{\n  ExcludeItems += fromNodes.ExcludeItems;\n  FOR_VECTOR (i, fromNodes.SubNodes)\n  {\n    const CCensorNode &node = fromNodes.SubNodes[i];\n    Find_SubNode_Or_Add_New(node.Name).ExtendExclude(node);\n  }\n}\n\nint CCensor::FindPairForPrefix(const UString &prefix) const\n{\n  FOR_VECTOR (i, Pairs)\n    if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)\n      return (int)i;\n  return -1;\n}\n\n#ifdef _WIN32\n\nbool IsDriveColonName(const wchar_t *s)\n{\n  unsigned c = s[0];\n  c |= 0x20;\n  c -= 'a';\n  return c <= (unsigned)('z' - 'a') && s[1] == ':' && s[2] == 0;\n}\n\nunsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts)\n{\n  if (pathParts.IsEmpty())\n    return 0;\n  \n  unsigned testIndex = 0;\n  if (pathParts[0].IsEmpty())\n  {\n    if (pathParts.Size() < 4\n        || !pathParts[1].IsEmpty()\n        || !pathParts[2].IsEqualTo(\"?\"))\n      return 0;\n    testIndex = 3;\n  }\n  if (NWildcard::IsDriveColonName(pathParts[testIndex]))\n    return testIndex + 1;\n  return 0;\n}\n\n#endif\n\nstatic unsigned GetNumPrefixParts(const UStringVector &pathParts)\n{\n  if (pathParts.IsEmpty())\n    return 0;\n\n  /* empty last part could be removed already from (pathParts),\n     if there was tail path separator (slash) in original full path string. */\n  \n  #ifdef _WIN32\n\n  if (IsDriveColonName(pathParts[0]))\n    return 1;\n  if (!pathParts[0].IsEmpty())\n    return 0;\n\n  if (pathParts.Size() == 1)\n    return 1;\n  if (!pathParts[1].IsEmpty())\n    return 1;\n  if (pathParts.Size() == 2)\n    return 2;\n  if (pathParts[2].IsEqualTo(\".\"))\n    return 3;\n\n  unsigned networkParts = 2;\n  if (pathParts[2].IsEqualTo(\"?\"))\n  {\n    if (pathParts.Size() == 3)\n      return 3;\n    if (IsDriveColonName(pathParts[3]))\n      return 4;\n    if (!pathParts[3].IsEqualTo_Ascii_NoCase(\"UNC\"))\n      return 3;\n    networkParts = 4;\n  }\n\n  networkParts +=\n      // 2; // server/share\n      1; // server\n  if (pathParts.Size() <= networkParts)\n    return pathParts.Size();\n  return networkParts;\n\n  #else\n  \n  return pathParts[0].IsEmpty() ? 1 : 0;\n \n  #endif\n}\n\nvoid CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path,\n    const CCensorPathProps &props)\n{\n  if (path.IsEmpty())\n    throw \"Empty file path\";\n\n  UStringVector pathParts;\n  SplitPathToParts(path, pathParts);\n\n  CCensorPathProps props2 = props;\n\n  bool forFile = true;\n  bool forDir = true;\n  const UString &back = pathParts.Back();\n  if (back.IsEmpty())\n  {\n    // we have tail path separator. So it's directory.\n    // we delete tail path separator here even for \"\\\" and \"c:\\\"\n    forFile = false;\n    pathParts.DeleteBack();\n  }\n  else\n  {\n    if (props.MarkMode == kMark_StrictFile\n        || (props.MarkMode == kMark_StrictFile_IfWildcard\n            && DoesNameContainWildcard(back)))\n      forDir = false;\n  }\n\n  \n  UString prefix;\n  \n  int ignoreWildcardIndex = -1;\n\n  // #ifdef _WIN32\n  // we ignore \"?\" wildcard in \"\\\\?\\\" prefix.\n  if (pathParts.Size() >= 3\n      && pathParts[0].IsEmpty()\n      && pathParts[1].IsEmpty()\n      && pathParts[2].IsEqualTo(\"?\"))\n    ignoreWildcardIndex = 2;\n  // #endif\n\n  if (pathMode != k_AbsPath)\n  {\n    // detection of the number of Skip Parts for prefix\n    ignoreWildcardIndex = -1;\n\n    const unsigned numPrefixParts = GetNumPrefixParts(pathParts);\n    unsigned numSkipParts = numPrefixParts;\n\n    if (pathMode != k_FullPath)\n    {\n      // if absolute path, then all parts before last part will be in prefix\n      if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts)\n        numSkipParts = pathParts.Size() - 1;\n    }\n    {\n      int dotsIndex = -1;\n      for (unsigned i = numPrefixParts; i < pathParts.Size(); i++)\n      {\n        const UString &part = pathParts[i];\n        if (part.IsEqualTo(\"..\") || part.IsEqualTo(\".\"))\n          dotsIndex = (int)i;\n      }\n\n      if (dotsIndex >= 0)\n      {\n        if (dotsIndex == (int)pathParts.Size() - 1)\n          numSkipParts = pathParts.Size();\n        else\n          numSkipParts = pathParts.Size() - 1;\n      }\n    }\n\n    // we split (pathParts) to (prefix) and (pathParts).\n    for (unsigned i = 0; i < numSkipParts; i++)\n    {\n      {\n        const UString &front = pathParts.Front();\n        // WIN32 doesn't support wildcards in file names\n        if (props.WildcardMatching)\n          if (i >= numPrefixParts && DoesNameContainWildcard(front))\n            break;\n        prefix += front;\n        prefix.Add_PathSepar();\n      }\n      pathParts.Delete(0);\n    }\n  }\n\n  int index = FindPairForPrefix(prefix);\n  if (index < 0)\n  {\n    index = (int)Pairs.Size();\n    Pairs.AddNew().Prefix = prefix;\n  }\n\n  if (pathMode != k_AbsPath)\n  {\n    if (pathParts.IsEmpty() || (pathParts.Size() == 1 && pathParts[0].IsEmpty()))\n    {\n      // we create universal item, if we skip all parts as prefix (like \\ or L:\\ )\n      pathParts.Clear();\n      pathParts.Add(UString(\"*\"));\n      forFile = true;\n      forDir = true;\n      props2.WildcardMatching = true;\n      props2.Recursive = false;\n    }\n  }\n\n  /*\n  // not possible now\n  if (!forDir && !forFile)\n  {\n    UString s (\"file path was blocked for files and directories: \");\n    s += path;\n    throw s;\n    // return; // for debug : ignore item (don't create Item)\n  }\n  */\n\n  CItem item;\n  item.PathParts = pathParts;\n  item.ForDir = forDir;\n  item.ForFile = forFile;\n  item.Recursive = props2.Recursive;\n  item.WildcardMatching = props2.WildcardMatching;\n  Pairs[(unsigned)index].Head.AddItem(include, item, ignoreWildcardIndex);\n}\n\n/*\nbool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const\n{\n  bool finded = false;\n  FOR_VECTOR (i, Pairs)\n  {\n    bool include;\n    if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include))\n    {\n      if (!include)\n        return false;\n      finded = true;\n    }\n  }\n  return finded;\n}\n*/\n\nvoid CCensor::ExtendExclude()\n{\n  unsigned i;\n  for (i = 0; i < Pairs.Size(); i++)\n    if (Pairs[i].Prefix.IsEmpty())\n      break;\n  if (i == Pairs.Size())\n    return;\n  unsigned index = i;\n  for (i = 0; i < Pairs.Size(); i++)\n    if (index != i)\n      Pairs[i].Head.ExtendExclude(Pairs[index].Head);\n}\n\nvoid CCensor::AddPathsToCensor(ECensorPathMode censorPathMode)\n{\n  FOR_VECTOR(i, CensorPaths)\n  {\n    const CCensorPath &cp = CensorPaths[i];\n    AddItem(censorPathMode, cp.Include, cp.Path, cp.Props);\n  }\n  CensorPaths.Clear();\n}\n\nvoid CCensor::AddPreItem(bool include, const UString &path, const CCensorPathProps &props)\n{\n  CCensorPath &cp = CensorPaths.AddNew();\n  cp.Path = path;\n  cp.Include = include;\n  cp.Props = props;\n}\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/Wildcard.h",
    "content": "﻿// Common/Wildcard.h\n\n#ifndef ZIP7_INC_COMMON_WILDCARD_H\n#define ZIP7_INC_COMMON_WILDCARD_H\n\n#include \"MyString.h\"\n\nint CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW;\n#ifndef USE_UNICODE_FSTRING\n  int CompareFileNames(const char *s1, const char *s2);\n#endif\n\nbool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2);\n\nvoid SplitPathToParts(const UString &path, UStringVector &pathParts);\nvoid SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name);\nvoid SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name); // ignores dir delimiter at the end of (path)\n\nUString ExtractDirPrefixFromPath(const UString &path);\nUString ExtractFileNameFromPath(const UString &path);\n\nbool DoesNameContainWildcard(const UString &path);\nbool DoesWildcardMatchName(const UString &mask, const UString &name);\n\nnamespace NWildcard {\n\n#ifdef _WIN32\n// returns true, if name is like \"a:\", \"c:\", ...\nbool IsDriveColonName(const wchar_t *s);\nunsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts);\n#endif\n\nstruct CItem\n{\n  UStringVector PathParts;\n  bool Recursive;\n  bool ForFile;\n  bool ForDir;\n  bool WildcardMatching;\n  \n  #ifdef _WIN32\n  bool IsDriveItem() const\n  {\n    return PathParts.Size() == 1 && !ForFile && ForDir && IsDriveColonName(PathParts[0]);\n  }\n  #endif\n\n  // CItem(): WildcardMatching(true) {}\n\n  bool AreAllAllowed() const;\n  bool CheckPath(const UStringVector &pathParts, bool isFile) const;\n};\n\n\n\nconst Byte kMark_FileOrDir = 0;\nconst Byte kMark_StrictFile = 1;\nconst Byte kMark_StrictFile_IfWildcard = 2;\n\nstruct CCensorPathProps\n{\n  bool Recursive;\n  bool WildcardMatching;\n  Byte MarkMode;\n  \n  CCensorPathProps():\n      Recursive(false),\n      WildcardMatching(true),\n      MarkMode(kMark_FileOrDir)\n      {}\n};\n\n\nclass CCensorNode  MY_UNCOPYABLE\n{\n  CCensorNode *Parent;\n  \n  bool CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const;\n  void AddItemSimple(bool include, CItem &item);\npublic:\n  // bool ExcludeDirItems;\n\n  CCensorNode():\n      Parent(NULL)\n      // , ExcludeDirItems(false)\n      {}\n\n  CCensorNode(const UString &name, CCensorNode *parent):\n      Parent(parent)\n      // , ExcludeDirItems(false)\n      , Name(name)\n      {}\n\n  UString Name; // WIN32 doesn't support wildcards in file names\n  CObjectVector<CCensorNode> SubNodes;\n  CObjectVector<CItem> IncludeItems;\n  CObjectVector<CItem> ExcludeItems;\n\n  CCensorNode &Find_SubNode_Or_Add_New(const UString &name)\n  {\n    int i = FindSubNode(name);\n    if (i >= 0)\n      return SubNodes[(unsigned)i];\n    // return SubNodes.Add(CCensorNode(name, this));\n    CCensorNode &node = SubNodes.AddNew();\n    node.Parent = this;\n    node.Name = name;\n    return node;\n  }\n\n  bool AreAllAllowed() const;\n\n  int FindSubNode(const UString &path) const;\n\n  void AddItem(bool include, CItem &item, int ignoreWildcardIndex = -1);\n  // void AddItem(bool include, const UString &path, const CCensorPathProps &props);\n  void Add_Wildcard()\n  {\n    CItem item;\n    item.PathParts.Add(L\"*\");\n    item.Recursive = false;\n    item.ForFile = true;\n    item.ForDir = true;\n    item.WildcardMatching = true;\n    AddItem(\n        true // include\n        , item);\n  }\n\n  // NeedCheckSubDirs() returns true, if there are IncludeItems rules that affect items in subdirs\n  bool NeedCheckSubDirs() const;\n  bool AreThereIncludeItems() const;\n\n  /*\n  CheckPathVect() doesn't check path in Parent CCensorNode\n  so use CheckPathVect() for root CCensorNode\n  OUT:\n    returns (true) && (include = false) - file in exlude list\n    returns (true) && (include = true)  - file in include list and is not in exlude list\n    returns (false)  - file is not in (include/exlude) list\n  */\n  bool CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const;\n\n  // bool CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const;\n  // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;\n\n  // CheckPathToRoot_Change() changes pathParts !!!\n  bool CheckPathToRoot_Change(bool include, UStringVector &pathParts, bool isFile) const;\n  bool CheckPathToRoot(bool include, const UStringVector &pathParts, bool isFile) const;\n\n  // bool CheckPathToRoot(const UString &path, bool isFile, bool include) const;\n  void ExtendExclude(const CCensorNode &fromNodes);\n};\n\n\nstruct CPair  MY_UNCOPYABLE\n{\n  UString Prefix;\n  CCensorNode Head;\n  \n  // CPair(const UString &prefix): Prefix(prefix) { };\n};\n\n\nenum ECensorPathMode\n{\n  k_RelatPath,  // absolute prefix as Prefix, remain path in Tree\n  k_FullPath,   // drive prefix as Prefix, remain path in Tree\n  k_AbsPath     // full path in Tree\n};\n\n\nstruct CCensorPath\n{\n  UString Path;\n  bool Include;\n  CCensorPathProps Props;\n\n  CCensorPath():\n      Include(true)\n      {}\n};\n\n\nclass CCensor  MY_UNCOPYABLE\n{\n  int FindPairForPrefix(const UString &prefix) const;\npublic:\n  CObjectVector<CPair> Pairs;\n\n  bool ExcludeDirItems;\n  bool ExcludeFileItems;\n\n  CCensor():\n      ExcludeDirItems(false),\n      ExcludeFileItems(false)\n      {}\n\n  CObjectVector<NWildcard::CCensorPath> CensorPaths;\n  \n  bool AllAreRelative() const\n    { return (Pairs.Size() == 1 && Pairs.Front().Prefix.IsEmpty()); }\n  \n  void AddItem(ECensorPathMode pathMode, bool include, const UString &path, const CCensorPathProps &props);\n  // bool CheckPath(bool isAltStream, const UString &path, bool isFile) const;\n  void ExtendExclude();\n\n  void AddPathsToCensor(NWildcard::ECensorPathMode censorPathMode);\n  void AddPreItem(bool include, const UString &path, const CCensorPathProps &props);\n\n  void AddPreItem_NoWildcard(const UString &path)\n  {\n    CCensorPathProps props;\n    props.WildcardMatching = false;\n    AddPreItem(\n        true,  // include\n        path, props);\n  }\n  void AddPreItem_Wildcard()\n  {\n    CCensorPathProps props;\n    // props.WildcardMatching = true;\n    AddPreItem(\n        true,  // include\n        UString(\"*\"), props);\n  }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/XzCrc64Init.cpp",
    "content": "﻿// XzCrc64Init.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/XzCrc64.h\"\n\nstatic struct CCrc64Gen { CCrc64Gen() { Crc64GenerateTable(); } } g_Crc64TableInit;\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Common/XzCrc64Reg.cpp",
    "content": "﻿// XzCrc64Reg.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/CpuArch.h\"\n#include \"../../C/XzCrc64.h\"\n\n#include \"../Common/MyCom.h\"\n\n#include \"../7zip/Common/RegisterCodec.h\"\n\nZ7_CLASS_IMP_COM_1(\n  CXzCrc64Hasher\n  , IHasher\n)\n  UInt64 _crc;\npublic:\n  Byte _mtDummy[1 << 7];  // it's public to eliminate clang warning: unused private field\n\n  CXzCrc64Hasher(): _crc(CRC64_INIT_VAL) {}\n};\n\nZ7_COM7F_IMF2(void, CXzCrc64Hasher::Init())\n{\n  _crc = CRC64_INIT_VAL;\n}\n\nZ7_COM7F_IMF2(void, CXzCrc64Hasher::Update(const void *data, UInt32 size))\n{\n  _crc = Crc64Update(_crc, data, size);\n}\n\nZ7_COM7F_IMF2(void, CXzCrc64Hasher::Final(Byte *digest))\n{\n  const UInt64 val = CRC64_GET_DIGEST(_crc);\n  SetUi64(digest, val)\n}\n\nREGISTER_HASHER(CXzCrc64Hasher, 0x4, \"CRC64\", 8)\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/COM.h",
    "content": "﻿// Windows/COM.h\n\n#ifndef ZIP7_INC_WINDOWS_COM_H\n#define ZIP7_INC_WINDOWS_COM_H\n\n// #include \"../Common/MyString.h\"\n\nnamespace NWindows {\nnamespace NCOM {\n\n#ifdef _WIN32\n  \nclass CComInitializer\n{\npublic:\n  CComInitializer()\n  {\n    #ifdef UNDER_CE\n    CoInitializeEx(NULL, COINIT_MULTITHREADED);\n    #else\n    // it's single thread. Do we need multithread?\n    CoInitialize(NULL);\n    #endif\n  }\n  ~CComInitializer() { CoUninitialize(); }\n};\n\n/*\nclass CStgMedium2\n{\n  STGMEDIUM _object;\n  bool _mustBeReleased;\npublic:\n  CStgMedium2(): _mustBeReleased(false) {}\n  ~CStgMedium2() { Free(); }\n  void Free()\n  {\n    if (_mustBeReleased)\n      ReleaseStgMedium(&_object);\n    _mustBeReleased = false;\n  }\n  const STGMEDIUM* operator->() const { return &_object;}\n  STGMEDIUM* operator->() { return &_object;}\n  STGMEDIUM* operator&() { return &_object; }\n};\n*/\n\nstruct CStgMedium: public STGMEDIUM\n{\n  CStgMedium()\n  {\n    tymed = TYMED_NULL; // 0\n    hGlobal = NULL;\n    pUnkForRelease = NULL;\n  }\n  ~CStgMedium()\n  {\n    ReleaseStgMedium(this);\n  }\n};\n\n#endif\n\n/*\n//////////////////////////////////\n// GUID <--> String Conversions\nUString GUIDToStringW(REFGUID guid);\nAString GUIDToStringA(REFGUID guid);\n#ifdef UNICODE\n  #define GUIDToString GUIDToStringW\n#else\n  #define GUIDToString GUIDToStringA\n#endif\n\nHRESULT StringToGUIDW(const wchar_t *string, GUID &classID);\nHRESULT StringToGUIDA(const char *string, GUID &classID);\n#ifdef UNICODE\n  #define StringToGUID StringToGUIDW\n#else\n  #define StringToGUID StringToGUIDA\n#endif\n*/\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Clipboard.cpp",
    "content": "﻿// Windows/Clipboard.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef UNDER_CE\n#include <winuserm.h>\n#endif\n\n#include \"../Common/StringConvert.h\"\n\n#include \"Clipboard.h\"\n#include \"Defs.h\"\n#include \"MemoryGlobal.h\"\n#include \"Shell.h\"\n\nnamespace NWindows {\n\nbool CClipboard::Open(HWND wndNewOwner) throw()\n{\n  m_Open = BOOLToBool(::OpenClipboard(wndNewOwner));\n  return m_Open;\n}\n\nbool CClipboard::Close() throw()\n{\n  if (!m_Open)\n    return true;\n  m_Open = !BOOLToBool(CloseClipboard());\n  return !m_Open;\n}\n\nbool ClipboardIsFormatAvailableHDROP()\n{\n  return BOOLToBool(IsClipboardFormatAvailable(CF_HDROP));\n}\n\n/*\nbool ClipboardGetTextString(AString &s)\n{\n  s.Empty();\n  if (!IsClipboardFormatAvailable(CF_TEXT))\n    return false;\n  CClipboard clipboard;\n\n  if (!clipboard.Open(NULL))\n    return false;\n\n  HGLOBAL h = ::GetClipboardData(CF_TEXT);\n  if (h != NULL)\n  {\n    NMemory::CGlobalLock globalLock(h);\n    const char *p = (const char *)globalLock.GetPointer();\n    if (p != NULL)\n    {\n      s = p;\n      return true;\n    }\n  }\n  return false;\n}\n*/\n\n/*\nbool ClipboardGetFileNames(UStringVector &names)\n{\n  names.Clear();\n  if (!IsClipboardFormatAvailable(CF_HDROP))\n    return false;\n  CClipboard clipboard;\n\n  if (!clipboard.Open(NULL))\n    return false;\n\n  HGLOBAL h = ::GetClipboardData(CF_HDROP);\n  if (h != NULL)\n  {\n    NMemory::CGlobalLock globalLock(h);\n    void *p = (void *)globalLock.GetPointer();\n    if (p != NULL)\n    {\n      NShell::CDrop drop(false);\n      drop.Attach((HDROP)p);\n      drop.QueryFileNames(names);\n      return true;\n    }\n  }\n  return false;\n}\n*/\n\nstatic bool ClipboardSetData(UINT uFormat, const void *data, size_t size) throw()\n{\n  NMemory::CGlobal global;\n  if (!global.Alloc(GMEM_DDESHARE | GMEM_MOVEABLE, size))\n    return false;\n  {\n    NMemory::CGlobalLock globalLock(global);\n    LPVOID p = globalLock.GetPointer();\n    if (!p)\n      return false;\n    memcpy(p, data, size);\n  }\n  if (::SetClipboardData(uFormat, global) == NULL)\n    return false;\n  global.Detach();\n  return true;\n}\n\nbool ClipboardSetText(HWND owner, const UString &s)\n{\n  CClipboard clipboard;\n  if (!clipboard.Open(owner))\n    return false;\n  if (!::EmptyClipboard())\n    return false;\n\n  bool res;\n  res = ClipboardSetData(CF_UNICODETEXT, (const wchar_t *)s, (s.Len() + 1) * sizeof(wchar_t));\n  #ifndef _UNICODE\n  AString a (UnicodeStringToMultiByte(s, CP_ACP));\n  if (ClipboardSetData(CF_TEXT, (const char *)a, (a.Len() + 1) * sizeof(char)))\n    res = true;\n  a = UnicodeStringToMultiByte(s, CP_OEMCP);\n  if (ClipboardSetData(CF_OEMTEXT, (const char *)a, (a.Len() + 1) * sizeof(char)))\n    res = true;\n  #endif\n  return res;\n}\n \n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Clipboard.h",
    "content": "﻿// Windows/Clipboard.h\n\n#ifndef ZIP7_INC_CLIPBOARD_H\n#define ZIP7_INC_CLIPBOARD_H\n\n#include \"../Common/MyString.h\"\n\nnamespace NWindows {\n\nclass CClipboard\n{\n  bool m_Open;\npublic:\n  CClipboard(): m_Open(false) {}\n  ~CClipboard() { Close(); }\n  bool Open(HWND wndNewOwner) throw();\n  bool Close() throw();\n};\n\nbool ClipboardIsFormatAvailableHDROP();\n\n// bool ClipboardGetFileNames(UStringVector &names);\n// bool ClipboardGetTextString(AString &s);\nbool ClipboardSetText(HWND owner, const UString &s);\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/CommonDialog.cpp",
    "content": "﻿// Windows/CommonDialog.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/MyBuffer.h\"\n\n#ifdef UNDER_CE\n#include <commdlg.h>\n#endif\n\n#ifndef _UNICODE\n#include \"../Common/StringConvert.h\"\n#endif\n\n#include \"CommonDialog.h\"\n#include \"Defs.h\"\n// #include \"FileDir.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\n\n/*\n  GetSaveFileName()\n  GetOpenFileName()\n  OPENFILENAME\n\n(lpstrInitialDir) : the initial directory.\nDOCs: the algorithm for selecting the initial directory varies on different platforms:\n{\n  Win2000/XP/Vista:\n    1. If lpstrFile contains a path, that path is the initial directory.\n    2. Otherwise, lpstrInitialDir specifies the initial directory.\n\n  Win7:\n    If lpstrInitialDir has the same value as was passed the first time\n    the application used an Open or Save As dialog box, the path\n    most recently selected by the user is used as the initial directory.\n}\n\nWin10:\n in:\n  function supports (lpstrInitialDir) path with super prefix \"\\\\\\\\?\\\\\"\n  function supports (lpstrInitialDir) path with long path\n  function doesn't support absolute (lpstrFile) path with super prefix \"\\\\\\\\?\\\\\"\n  function doesn't support absolute (lpstrFile) path with long path\n out: the path with super prefix \"\\\\\\\\?\\\\\" will be returned, if selected path is long\n\nWinXP-64 and Win10: if no filters, the system shows all files.\n    but DOCs say: If all three members are zero or NULL,\n        the system does not use any filters and does not\n        show any files in the file list control of the dialog box.\n\nin Win7+: GetOpenFileName() and GetSaveFileName()\n    do not support pstrCustomFilter feature anymore\n*/\n\n#ifdef UNDER_CE\n#define MY_OFN_PROJECT  0x00400000\n#define MY_OFN_SHOW_ALL 0x01000000\n#endif\n\n\n/*\nstructures\n  OPENFILENAMEW\n  OPENFILENAMEA\ncontain additional members:\n#if (_WIN32_WINNT >= 0x0500)\n  void *pvReserved;\n  DWORD dwReserved;\n  DWORD FlagsEx;\n#endif\n\nIf we compile the source code with (_WIN32_WINNT >= 0x0500), some functions\nwill not work at NT 4.0, if we use sizeof(OPENFILENAME).\nWe try to use reduced structure OPENFILENAME_NT4.\n*/\n\n// #if defined(_WIN64) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500)\n#if defined(__GNUC__) && (__GNUC__ <= 9) || defined(Z7_OLD_WIN_SDK)\n  #ifndef _UNICODE\n  #define my_compatib_OPENFILENAMEA       OPENFILENAMEA\n  #endif\n  #define my_compatib_OPENFILENAMEW       OPENFILENAMEW\n\n  // MinGW doesn't support some required macros. So we define them here:\n  #ifndef CDSIZEOF_STRUCT\n  #define CDSIZEOF_STRUCT(structname, member)  (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))\n  #endif\n  #ifndef _UNICODE\n  #ifndef OPENFILENAME_SIZE_VERSION_400A\n  #define OPENFILENAME_SIZE_VERSION_400A  CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)\n  #endif\n  #endif\n  #ifndef OPENFILENAME_SIZE_VERSION_400W\n  #define OPENFILENAME_SIZE_VERSION_400W  CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)\n  #endif\n  \n  #ifndef _UNICODE\n  #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A\n  #endif\n  #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W\n#else\n  #ifndef _UNICODE\n  #define my_compatib_OPENFILENAMEA       OPENFILENAME_NT4A\n  #define my_compatib_OPENFILENAMEA_size  sizeof(my_compatib_OPENFILENAMEA)\n  #endif\n  #define my_compatib_OPENFILENAMEW       OPENFILENAME_NT4W\n  #define my_compatib_OPENFILENAMEW_size  sizeof(my_compatib_OPENFILENAMEW)\n#endif\n/*\n#elif defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500)\n// || !defined(WINVER)\n  #ifndef _UNICODE\n  #define my_compatib_OPENFILENAMEA       OPENFILENAMEA\n  #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA)\n  #endif\n  #define my_compatib_OPENFILENAMEW       OPENFILENAMEW\n  #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW)\n#else\n\n#endif\n*/\n\n#ifndef _UNICODE\n#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; }\n#endif\n\nbool CCommonDialogInfo::CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir, const UStringVector &filters)\n{\n  /* GetSaveFileName() and GetOpenFileName() could change current dir,\n     if OFN_NOCHANGEDIR is not used.\n     We can restore current dir manually, if it's required.\n     22.02: we use OFN_NOCHANGEDIR. So we don't need to restore current dir manually. */\n  // NFile::NDir::CCurrentDirRestorer curDirRestorer;\n\n#ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    AString tempPath;\n    AStringVector f;\n    unsigned i;\n    for (i = 0; i < filters.Size(); i++)\n      f.Add(GetSystemString(filters[i]));\n    unsigned size = f.Size() + 1;\n    for (i = 0; i < f.Size(); i++)\n      size += f[i].Len();\n    CObjArray<char> filterBuf(size);\n    // memset(filterBuf, 0, size * sizeof(char));\n    {\n      char *dest = filterBuf;\n      for (i = 0; i < f.Size(); i++)\n      {\n        const AString &s = f[i];\n        MyStringCopy(dest, s);\n        dest += s.Len() + 1;\n      }\n      *dest = 0;\n    }\n    my_compatib_OPENFILENAMEA p;\n    memset(&p, 0, sizeof(p));\n    p.lStructSize = my_compatib_OPENFILENAMEA_size;\n    p.hwndOwner = hwndOwner;\n    if (size > 1)\n    {\n      p.lpstrFilter = filterBuf;\n      p.nFilterIndex = (DWORD)(FilterIndex + 1);\n    }\n\n    CONV_U_To_A(p.lpstrInitialDir, lpstrInitialDir, initialDir_a)\n    CONV_U_To_A(p.lpstrTitle, lpstrTitle, title_a)\n\n    const AString filePath_a = GetSystemString(FilePath);\n    const unsigned bufSize = MAX_PATH * 8\n        + filePath_a.Len()\n        + initialDir_a.Len();\n    p.nMaxFile = bufSize;\n    p.lpstrFile = tempPath.GetBuf(bufSize);\n    MyStringCopy(p.lpstrFile, filePath_a);\n    p.Flags =\n          OFN_EXPLORER\n        | OFN_HIDEREADONLY\n        | OFN_NOCHANGEDIR;\n    const BOOL b = SaveMode ?\n        ::GetSaveFileNameA((LPOPENFILENAMEA)(void *)&p) :\n        ::GetOpenFileNameA((LPOPENFILENAMEA)(void *)&p);\n    if (!b)\n      return false;\n    {\n      tempPath.ReleaseBuf_CalcLen(bufSize);\n      FilePath = GetUnicodeString(tempPath);\n      FilterIndex = (int)p.nFilterIndex - 1;\n      return true;\n    }\n  }\n  else\n#endif\n  {\n    UString tempPath;\n    unsigned size = filters.Size() + 1;\n    unsigned i;\n    for (i = 0; i < filters.Size(); i++)\n      size += filters[i].Len();\n    CObjArray<wchar_t> filterBuf(size);\n    // memset(filterBuf, 0, size * sizeof(wchar_t));\n    {\n      wchar_t *dest = filterBuf;\n      for (i = 0; i < filters.Size(); i++)\n      {\n        const UString &s = filters[i];\n        MyStringCopy(dest, s);\n        dest += s.Len() + 1;\n      }\n      *dest = 0;\n      // if ((unsigned)(dest + 1 - filterBuf) != size) return false;\n    }\n    my_compatib_OPENFILENAMEW p;\n    memset(&p, 0, sizeof(p));\n    p.lStructSize = my_compatib_OPENFILENAMEW_size;\n    p.hwndOwner = hwndOwner;\n    if (size > 1)\n    {\n      p.lpstrFilter = filterBuf;\n      p.nFilterIndex = (DWORD)(FilterIndex + 1);\n    }\n    unsigned bufSize = MAX_PATH * 8 + FilePath.Len();\n    if (lpstrInitialDir)\n    {\n      p.lpstrInitialDir = lpstrInitialDir;\n      bufSize += MyStringLen(lpstrInitialDir);\n    }\n    p.nMaxFile = bufSize;\n    p.lpstrFile = tempPath.GetBuf(bufSize);\n    MyStringCopy(p.lpstrFile, FilePath);\n    p.lpstrTitle = lpstrTitle;\n    p.Flags =\n          OFN_EXPLORER\n        | OFN_HIDEREADONLY\n        | OFN_NOCHANGEDIR\n        // | OFN_FORCESHOWHIDDEN // Win10 shows hidden items even without this flag\n        // | OFN_PATHMUSTEXIST\n      #ifdef UNDER_CE\n        | (OpenFolderMode ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0)\n      #endif\n        ;\n    const BOOL b = SaveMode ?\n        ::GetSaveFileNameW((LPOPENFILENAMEW)(void *)&p) :\n        ::GetOpenFileNameW((LPOPENFILENAMEW)(void *)&p);\n    /* DOCs: lpstrFile :\n        if the buffer is too small, then:\n        - the function returns FALSE\n        - the CommDlgExtendedError() returns FNERR_BUFFERTOOSMALL\n        - the first two bytes of the lpstrFile buffer contain the\n          required size, in bytes or characters. */\n    if (!b)\n      return false;\n    {\n      tempPath.ReleaseBuf_CalcLen(bufSize);\n      FilePath = tempPath;\n      FilterIndex = (int)p.nFilterIndex - 1;\n      return true;\n    }\n  }\n}\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/CommonDialog.h",
    "content": "﻿// Windows/CommonDialog.h\n\n#ifndef ZIP7_INC_WINDOWS_COMMON_DIALOG_H\n#define ZIP7_INC_WINDOWS_COMMON_DIALOG_H\n\n#include \"../Common/MyString.h\"\n\nnamespace NWindows {\n\nstruct CCommonDialogInfo\n{\n  /* (FilterIndex == -1) means no selected filter.\n       and (-1) also is reserved for unsupported custom filter.\n     if (FilterIndex >= 0), then FilterIndex is index of filter */\n  int FilterIndex;    // [in / out]\n  bool SaveMode;\n #ifdef UNDER_CE\n  bool OpenFolderMode;\n #endif\n  HWND hwndOwner;\n  // LPCWSTR lpstrInitialDir;\n  LPCWSTR lpstrTitle;\n  UString FilePath;   // [in / out]\n\n  CCommonDialogInfo()\n  {\n    FilterIndex = -1;\n    SaveMode = false;\n   #ifdef UNDER_CE\n    OpenFolderMode = false;\n   #endif\n    hwndOwner = NULL;\n    // lpstrInitialDir = NULL;\n    lpstrTitle = NULL;\n  }\n  \n  /* (filters) : 2 sequential vector strings (Description, Masks) represent each filter */\n  bool CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir, const UStringVector &filters);\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/ComboBox.cpp",
    "content": "﻿// Windows/Control/ComboBox.cpp\n\n#include \"StdAfx.h\"\n\n// **************** NanaZip Modification Start ****************\n#include <Shlwapi.h>\n// **************** NanaZip Modification End ****************\n\n#ifndef _UNICODE\n#include \"../../Common/StringConvert.h\"\n#endif\n\n#include \"ComboBox.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\nnamespace NControl {\n\n// **************** NanaZip Modification Start ****************\nvoid CComboBox::Attach(HWND newWindow) {\n    _window = newWindow;\n\n    COMBOBOXINFO ComboBoxInfo = { sizeof(COMBOBOXINFO) };\n    if (GetComboBoxInfo(_window, &ComboBoxInfo) &&\n        ComboBoxInfo.hwndItem != NULL)\n    {\n        ::SHAutoComplete(\n            ComboBoxInfo.hwndItem,\n            SHACF_AUTOAPPEND_FORCE_OFF | SHACF_AUTOSUGGEST_FORCE_OFF);\n    }\n}\n// **************** NanaZip Modification End ****************\n\nLRESULT CComboBox::GetLBText(int index, CSysString &s)\n{\n  s.Empty();\n  LRESULT len = GetLBTextLen(index); // length, excluding the terminating null character\n  if (len == CB_ERR)\n    return len;\n  LRESULT len2 = GetLBText(index, s.GetBuf((unsigned)len));\n  if (len2 == CB_ERR)\n    return len;\n  if (len > len2)\n    len = len2;\n  s.ReleaseBuf_CalcLen((unsigned)len);\n  return len;\n}\n\n#ifndef _UNICODE\nLRESULT CComboBox::AddString(LPCWSTR s)\n{\n  if (g_IsNT)\n    return SendMsgW(CB_ADDSTRING, 0, (LPARAM)s);\n  return AddString(GetSystemString(s));\n}\n\nLRESULT CComboBox::GetLBText(int index, UString &s)\n{\n  s.Empty();\n  if (g_IsNT)\n  {\n    LRESULT len = SendMsgW(CB_GETLBTEXTLEN, MY_int_TO_WPARAM(index), 0);\n    if (len == CB_ERR)\n      return len;\n    LRESULT len2 = SendMsgW(CB_GETLBTEXT, MY_int_TO_WPARAM(index), (LPARAM)s.GetBuf((unsigned)len));\n    if (len2 == CB_ERR)\n      return len;\n    if (len > len2)\n      len = len2;\n    s.ReleaseBuf_CalcLen((unsigned)len);\n    return len;\n  }\n  AString sa;\n  const LRESULT len = GetLBText(index, sa);\n  if (len == CB_ERR)\n    return len;\n  s = GetUnicodeString(sa);\n  return (LRESULT)s.Len();\n}\n#endif\n\nLRESULT CComboBox::AddString_SetItemData(LPCWSTR s, LPARAM lParam)\n{\n  const LRESULT index = AddString(s);\n  // NOTE: SetItemData((int)-1, lParam) works as unexpected.\n  if (index >= 0) // optional check, because (index < 0) is not expected for normal inputs\n    SetItemData((int)index, lParam);\n  return index;\n}\n\n// **************** NanaZip Modification Start ****************\nvoid CComboBoxEx::Attach(HWND newWindow) {\n    _window = newWindow;\n\n    HWND EditControl = this->GetEditControl();\n    if (EditControl != NULL)\n    {\n        ::SHAutoComplete(\n            this->GetEditControl(),\n            SHACF_AUTOAPPEND_FORCE_OFF | SHACF_AUTOSUGGEST_FORCE_OFF);\n    }\n}\n// **************** NanaZip Modification End ****************\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/ComboBox.h",
    "content": "﻿// Windows/Control/ComboBox.h\n\n#ifndef ZIP7_INC_WINDOWS_CONTROL_COMBOBOX_H\n#define ZIP7_INC_WINDOWS_CONTROL_COMBOBOX_H\n\n#include \"../../Common/MyWindows.h\"\n\n#include <CommCtrl.h>\n\n#include \"../Window.h\"\n\nnamespace NWindows {\nnamespace NControl {\n\nclass CComboBox: public CWindow\n{\npublic:\n  // **************** NanaZip Modification Start ****************\n  virtual void Attach(HWND newWindow) override;\n  // **************** NanaZip Modification End ****************\n\n  void ResetContent() { SendMsg(CB_RESETCONTENT, 0, 0); }\n  LRESULT AddString(LPCTSTR s) { return SendMsg(CB_ADDSTRING, 0, (LPARAM)s); }\n  #ifndef _UNICODE\n  LRESULT AddString(LPCWSTR s);\n  #endif\n\n  LRESULT AddString_SetItemData(LPCWSTR s, LPARAM lParam);\n\n  /* If this parameter is -1, any current selection in the list is removed and the edit control is cleared.*/\n  LRESULT SetCurSel(int index) { return SendMsg(CB_SETCURSEL, MY_int_TO_WPARAM(index), 0); }\n  LRESULT SetCurSel(unsigned index) { return SendMsg(CB_SETCURSEL, index, 0); }\n\n  /* If no item is selected, it returns CB_ERR (-1) */\n  int GetCurSel() { return (int)SendMsg(CB_GETCURSEL, 0, 0); }\n  \n  /*  If an error occurs, it is CB_ERR (-1) */\n  int GetCount() { return (int)SendMsg(CB_GETCOUNT, 0, 0); }\n  \n  LRESULT GetLBTextLen(int index) { return SendMsg(CB_GETLBTEXTLEN, MY_int_TO_WPARAM(index), 0); }\n  LRESULT GetLBText(int index, LPTSTR s) { return SendMsg(CB_GETLBTEXT, MY_int_TO_WPARAM(index), (LPARAM)s); }\n  LRESULT GetLBText(int index, CSysString &s);\n  #ifndef _UNICODE\n  LRESULT GetLBText(int index, UString &s);\n  #endif\n\n  LRESULT SetItemData(int index, LPARAM lParam) { return SendMsg(CB_SETITEMDATA, MY_int_TO_WPARAM(index), lParam); }\n  LRESULT GetItemData(int index) { return SendMsg(CB_GETITEMDATA, MY_int_TO_WPARAM(index), 0); }\n  LRESULT GetItemData(unsigned index) { return SendMsg(CB_GETITEMDATA, index, 0); }\n\n  LRESULT GetItemData_of_CurSel() { return GetItemData(GetCurSel()); }\n\n  void ShowDropDown(bool show = true) { SendMsg(CB_SHOWDROPDOWN, show ? TRUE : FALSE, 0);  }\n};\n\n#ifndef UNDER_CE\n\nclass CComboBoxEx: public CComboBox\n{\npublic:\n  // **************** NanaZip Modification Start ****************\n  virtual void Attach(HWND newWindow) override;\n  // **************** NanaZip Modification End ****************\n\n  bool SetUnicodeFormat(bool fUnicode) { return LRESULTToBool(SendMsg(CBEM_SETUNICODEFORMAT, BOOLToBool(fUnicode), 0)); }\n\n  /* Returns:\n      an INT value that represents the number of items remaining in the control.\n      If (index) is invalid, the message returns CB_ERR. */\n  LRESULT DeleteItem(int index) { return SendMsg(CBEM_DELETEITEM, MY_int_TO_WPARAM(index), 0); }\n\n  LRESULT InsertItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_INSERTITEM, 0, (LPARAM)item); }\n  #ifndef _UNICODE\n  LRESULT InsertItem(COMBOBOXEXITEMW *item) { return SendMsg(CBEM_INSERTITEMW, 0, (LPARAM)item); }\n  #endif\n\n  LRESULT SetItem(COMBOBOXEXITEM *item) { return SendMsg(CBEM_SETITEM, 0, (LPARAM)item); }\n  DWORD SetExtendedStyle(DWORD exMask, DWORD exStyle) { return (DWORD)SendMsg(CBEM_SETEXTENDEDSTYLE, exMask, (LPARAM)exStyle); }\n  HWND GetEditControl() { return (HWND)SendMsg(CBEM_GETEDITCONTROL, 0, 0); }\n  HIMAGELIST SetImageList(HIMAGELIST imageList) { return (HIMAGELIST)SendMsg(CBEM_SETIMAGELIST, 0, (LPARAM)imageList); }\n};\n\n#endif\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/Dialog.cpp",
    "content": "﻿// Windows/Control/Dialog.cpp\n\n#include \"StdAfx.h\"\n\n// #include \"../../Windows/DLL.h\"\n\n#ifndef _UNICODE\n#include \"../../Common/StringConvert.h\"\n#endif\n\n#include \"Dialog.h\"\n\n// **************** NanaZip Modification Start ****************\n#include <K7User.h>\n// **************** NanaZip Modification End ****************\n\nextern HINSTANCE g_hInstance;\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\nnamespace NControl {\n\nstatic\n#ifdef Z7_OLD_WIN_SDK\n  BOOL\n#else\n  INT_PTR\n#endif\nAPIENTRY\nDialogProcedure(HWND dialogHWND, UINT message, WPARAM wParam, LPARAM lParam)\n{\n  CWindow tempDialog(dialogHWND);\n  if (message == WM_INITDIALOG)\n    tempDialog.SetUserDataLongPtr(lParam);\n  CDialog *dialog = (CDialog *)(tempDialog.GetUserDataLongPtr());\n  if (dialog == NULL)\n    return FALSE;\n  if (message == WM_INITDIALOG)\n  // **************** NanaZip Modification Start ****************\n  {\n  // **************** NanaZip Modification End ****************\n    dialog->Attach(dialogHWND);\n  // **************** NanaZip Modification Start ****************\n    ::K7UserModernSetForegroundWindow(dialogHWND);\n  }\n  // **************** NanaZip Modification End ****************\n\n  /* MSDN: The dialog box procedure should return\n       TRUE  - if it processed the message\n       FALSE - if it did not process the message\n     If the dialog box procedure returns FALSE,\n     the dialog manager performs the default dialog operation in response to the message.\n  */\n\n  try { return BoolToBOOL(dialog->OnMessage(message, wParam, lParam)); }\n  catch(...) { return TRUE; }\n}\n\nbool CDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\n{\n  switch (message)\n  {\n    case WM_INITDIALOG: return OnInit();\n    case WM_COMMAND: return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam);\n    case WM_NOTIFY: return OnNotify((UINT)wParam, (LPNMHDR) lParam);\n    case WM_TIMER: return OnTimer(wParam, lParam);\n    case WM_SIZE: return OnSize(wParam, LOWORD(lParam), HIWORD(lParam));\n    case WM_DESTROY: return OnDestroy();\n    // **************** NanaZip Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n    case WM_HELP: OnHelp(); return true;\n    /*\n        OnHelp(\n          #ifdef UNDER_CE\n          (void *)\n          #else\n          (LPHELPINFO)\n          #endif\n          lParam);\n        return true;\n    */\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n    // **************** NanaZip Modification End ****************\n    default: return false;\n  }\n}\n\n/*\nbool CDialog::OnCommand2(WPARAM wParam, LPARAM lParam)\n{\n  return OnCommand(HIWORD(wParam), LOWORD(wParam), lParam);\n}\n*/\n\nbool CDialog::OnCommand(unsigned code, unsigned itemID, LPARAM lParam)\n{\n  if (code == BN_CLICKED)\n    return OnButtonClicked(itemID, (HWND)lParam);\n  return false;\n}\n\nbool CDialog::OnButtonClicked(unsigned buttonID, HWND /* buttonHWND */)\n{\n  switch (buttonID)\n  {\n    case IDOK: OnOK(); break;\n    case IDCANCEL: OnCancel(); break;\n    case IDCLOSE: OnClose(); break;\n    case IDCONTINUE: OnContinue(); break;\n    // **************** NanaZip Modification Start ****************\n    //case IDHELP: OnHelp(); break;\n    // **************** NanaZip Modification End ****************\n    default: return false;\n  }\n  return true;\n}\n\n#ifndef UNDER_CE\n/* in win2000/win98 : monitor functions are supported.\n   We need dynamic linking, if we want nt4/win95 support in program.\n   Even if we compile the code with low (WINVER) value, we still\n   want to use monitor functions. So we declare missing functions here */\n// #if (WINVER < 0x0500)\n#ifndef MONITOR_DEFAULTTOPRIMARY\nextern \"C\" {\nDECLARE_HANDLE(HMONITOR);\n#define MONITOR_DEFAULTTOPRIMARY    0x00000001\ntypedef struct tagMONITORINFO\n{\n    DWORD   cbSize;\n    RECT    rcMonitor;\n    RECT    rcWork;\n    DWORD   dwFlags;\n} MONITORINFO, *LPMONITORINFO;\nWINUSERAPI HMONITOR WINAPI MonitorFromWindow(HWND hwnd, DWORD dwFlags);\nWINUSERAPI BOOL WINAPI GetMonitorInfoA(HMONITOR hMonitor, LPMONITORINFO lpmi);\n}\n#endif\n#endif\n\nstatic bool GetWorkAreaRect(RECT *rect, HWND hwnd)\n{\n  if (hwnd)\n  {\n    #ifndef UNDER_CE\n    /* MonitorFromWindow() is supported in Win2000+\n       MonitorFromWindow() : retrieves a handle to the display monitor that has the\n         largest area of intersection with the bounding rectangle of a specified window.\n       dwFlags: Determines the function's return value if the window does not intersect any display monitor.\n         MONITOR_DEFAULTTONEAREST : Returns display that is nearest to the window.\n         MONITOR_DEFAULTTONULL    : Returns NULL.\n         MONITOR_DEFAULTTOPRIMARY : Returns the primary display monitor.\n    */\n    const HMONITOR hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);\n    if (hmon)\n    {\n      MONITORINFO mi;\n      memset(&mi, 0, sizeof(mi));\n      mi.cbSize = sizeof(mi);\n      if (GetMonitorInfoA(hmon, &mi))\n      {\n        *rect = mi.rcWork;\n        return true;\n      }\n    }\n    #endif\n  }\n\n  /* Retrieves the size of the work area on the primary display monitor.\n     The work area is the portion of the screen not obscured\n     by the system taskbar or by application desktop toolbars.\n     Any DPI virtualization mode of the caller has no effect on this output. */\n\n  return BOOLToBool(::SystemParametersInfo(SPI_GETWORKAREA, 0, rect, 0));\n}\n\n\nbool IsDialogSizeOK(int xSize, int ySize, HWND hwnd)\n{\n  // it returns for system font. Real font uses another values\n  const LONG v = GetDialogBaseUnits();\n  const int x = LOWORD(v);\n  const int y = HIWORD(v);\n\n  RECT rect;\n  GetWorkAreaRect(&rect, hwnd);\n  const int wx = RECT_SIZE_X(rect);\n  const int wy = RECT_SIZE_Y(rect);\n  return\n    xSize / 4 * x <= wx &&\n    ySize / 8 * y <= wy;\n}\n\nbool CDialog::GetMargins(int margin, int &x, int &y)\n{\n  x = margin;\n  y = margin;\n  RECT rect;\n  rect.left = 0;\n  rect.top = 0;\n  rect.right = margin;\n  rect.bottom = margin;\n  if (!MapRect(&rect))\n    return false;\n  x = rect.right - rect.left;\n  y = rect.bottom - rect.top;\n  return true;\n}\n\nint CDialog::Units_To_Pixels_X(int units)\n{\n  RECT rect;\n  rect.left = 0;\n  rect.top = 0;\n  rect.right = units;\n  rect.bottom = units;\n  if (!MapRect(&rect))\n    return units * 3 / 2;\n  return rect.right - rect.left;\n}\n\nbool CDialog::GetItemSizes(unsigned id, int &x, int &y)\n{\n  RECT rect;\n  if (!::GetWindowRect(GetItem(id), &rect))\n    return false;\n  x = RECT_SIZE_X(rect);\n  y = RECT_SIZE_Y(rect);\n  return true;\n}\n\nvoid CDialog::GetClientRectOfItem(unsigned id, RECT &rect)\n{\n  ::GetWindowRect(GetItem(id), &rect);\n  ScreenToClient(&rect);\n}\n\nbool CDialog::MoveItem(unsigned id, int x, int y, int width, int height, bool repaint)\n{\n  return BOOLToBool(::MoveWindow(GetItem(id), x, y, width, height, BoolToBOOL(repaint)));\n}\n\n\n/*\ntypedef BOOL (WINAPI * Func_DwmGetWindowAttribute)(\n    HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);\n\nstatic bool GetWindowsRect_DWM(HWND hwnd, RECT *rect)\n{\n  // dll load and free is too slow : 300 calls in second.\n  NDLL::CLibrary dll;\n  if (!dll.Load(FTEXT(\"dwmapi.dll\")))\n    return false;\n  Func_DwmGetWindowAttribute f = (Func_DwmGetWindowAttribute)dll.GetProc(\"DwmGetWindowAttribute\" );\n  if (f)\n  {\n    #define MY__DWMWA_EXTENDED_FRAME_BOUNDS 9\n    // 30000 per second\n    RECT r;\n    if (f(hwnd, MY__DWMWA_EXTENDED_FRAME_BOUNDS, &r, sizeof(RECT)) == S_OK)\n    {\n      *rect = r;\n      return true;\n    }\n  }\n  return false;\n}\n*/\n\n\nstatic bool IsRect_Small_Inside_Big(const RECT &sm, const RECT &big)\n{\n  return sm.left   >= big.left\n      && sm.right  <= big.right\n      && sm.top    >= big.top\n      && sm.bottom <= big.bottom;\n}\n\n\nstatic bool AreRectsOverlapped(const RECT &r1, const RECT &r2)\n{\n  return r1.left   < r2.right\n      && r1.right  > r2.left\n      && r1.top    < r2.bottom\n      && r1.bottom > r2.top;\n}\n\n\nstatic bool AreRectsEqual(const RECT &r1, const RECT &r2)\n{\n  return r1.left   == r2.left\n      && r1.right  == r2.right\n      && r1.top    == r2.top\n      && r1.bottom == r2.bottom;\n}\n\n\nvoid CDialog::NormalizeSize(bool fullNormalize)\n{\n  RECT workRect;\n  if (!GetWorkAreaRect(&workRect, *this))\n    return;\n  RECT rect;\n  if (!GetWindowRect(&rect))\n    return;\n  int xs = RECT_SIZE_X(rect);\n  int ys = RECT_SIZE_Y(rect);\n\n  // we don't want to change size using workRect, if window is outside of WorkArea\n  if (!AreRectsOverlapped(rect, workRect))\n    return;\n\n  /* here rect and workRect are overlapped, but it can be false\n     overlapping of small shadow when window in another display. */\n\n  const int xsW = RECT_SIZE_X(workRect);\n  const int ysW = RECT_SIZE_Y(workRect);\n  if (xs <= xsW && ys <= ysW)\n    return; // size of window is OK\n  if (fullNormalize)\n  {\n    Show(SW_SHOWMAXIMIZED);\n    return;\n  }\n  int x = workRect.left;\n  int y = workRect.top;\n  if (xs < xsW)  x += (xsW - xs) / 2;  else xs = xsW;\n  if (ys < ysW)  y += (ysW - ys) / 2;  else ys = ysW;\n  Move(x, y, xs, ys, true);\n}\n\n\nvoid CDialog::NormalizePosition()\n{\n  RECT workRect;\n  if (!GetWorkAreaRect(&workRect, *this))\n    return;\n\n  RECT rect2 = workRect;\n  bool useWorkArea = true;\n  const HWND parentHWND = GetParent();\n\n  if (parentHWND)\n  {\n    RECT workRectParent;\n    if (!GetWorkAreaRect(&workRectParent, parentHWND))\n      return;\n\n    // if windows are in different monitors, we use only workArea of current window\n\n    if (AreRectsEqual(workRectParent, workRect))\n    {\n      // RECT rect3; if (GetWindowsRect_DWM(parentHWND, &rect3)) {}\n      CWindow wnd(parentHWND);\n      if (wnd.GetWindowRect(&rect2))\n      {\n        // it's same monitor. So we try to use parentHWND rect.\n        /* we don't want to change position, if parent window is not inside work area.\n           In Win10 : parent window rect is 8 pixels larger for each corner than window size for shadow.\n           In maximize mode : window is outside of workRect.\n           if parent window is inside workRect, we will use parent window instead of workRect */\n        if (IsRect_Small_Inside_Big(rect2, workRect))\n          useWorkArea = false;\n      }\n    }\n  }\n\n  RECT rect;\n  if (!GetWindowRect(&rect))\n    return;\n\n  if (useWorkArea)\n  {\n    // we don't want to move window, if it's already inside.\n    if (IsRect_Small_Inside_Big(rect, workRect))\n      return;\n    // we don't want to move window, if it's outside of workArea\n    if (!AreRectsOverlapped(rect, workRect))\n      return;\n    rect2 = workRect;\n  }\n\n  {\n    const int xs = RECT_SIZE_X(rect);\n    const int ys = RECT_SIZE_Y(rect);\n    const int xs2 = RECT_SIZE_X(rect2);\n    const int ys2 = RECT_SIZE_Y(rect2);\n    // we don't want to change position if parent is smaller.\n    if (xs <= xs2 && ys <= ys2)\n    {\n      const int x = rect2.left + (xs2 - xs) / 2;\n      const int y = rect2.top  + (ys2 - ys) / 2;\n\n      if (x != rect.left || y != rect.top)\n        Move(x, y, xs, ys, true);\n      // SetWindowPos(*this, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);\n      return;\n    }\n  }\n}\n\n\n\nbool CModelessDialog::Create(LPCTSTR templateName, HWND parentWindow)\n{\n  const HWND aHWND = CreateDialogParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\n  if (!aHWND)\n    return false;\n  Attach(aHWND);\n  return true;\n}\n\nINT_PTR CModalDialog::Create(LPCTSTR templateName, HWND parentWindow)\n{\n  return DialogBoxParam(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\n}\n\n#ifndef _UNICODE\n\nbool CModelessDialog::Create(LPCWSTR templateName, HWND parentWindow)\n{\n  HWND aHWND;\n  if (g_IsNT)\n    aHWND = CreateDialogParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\n  else\n  {\n    AString name;\n    LPCSTR templateNameA;\n    if (IS_INTRESOURCE(templateName))\n      templateNameA = (LPCSTR)templateName;\n    else\n    {\n      name = GetSystemString(templateName);\n      templateNameA = name;\n    }\n    aHWND = CreateDialogParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);\n  }\n  if (aHWND == 0)\n    return false;\n  Attach(aHWND);\n  return true;\n}\n\nINT_PTR CModalDialog::Create(LPCWSTR templateName, HWND parentWindow)\n{\n  if (g_IsNT)\n    return DialogBoxParamW(g_hInstance, templateName, parentWindow, DialogProcedure, (LPARAM)this);\n  AString name;\n  LPCSTR templateNameA;\n  if (IS_INTRESOURCE(templateName))\n    templateNameA = (LPCSTR)templateName;\n  else\n  {\n    name = GetSystemString(templateName);\n    templateNameA = name;\n  }\n  return DialogBoxParamA(g_hInstance, templateNameA, parentWindow, DialogProcedure, (LPARAM)this);\n}\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/Dialog.h",
    "content": "﻿// Windows/Control/Dialog.h\n\n#ifndef ZIP7_INC_WINDOWS_CONTROL_DIALOG_H\n#define ZIP7_INC_WINDOWS_CONTROL_DIALOG_H\n\n#include \"../Window.h\"\n\nnamespace NWindows {\nnamespace NControl {\n\n#ifndef IDCONTINUE\n#define IDCONTINUE 11\n#endif\n\nclass CDialog: public CWindow\n{\n  // Z7_CLASS_NO_COPY(CDialog)\npublic:\n  CDialog(HWND wnd = NULL): CWindow(wnd) {}\n  virtual ~CDialog() {}\n\n  HWND GetItem(unsigned itemID) const\n    { return GetDlgItem(_window, (int)itemID); }\n\n  bool EnableItem(unsigned itemID, bool enable) const\n    { return BOOLToBool(::EnableWindow(GetItem(itemID), BoolToBOOL(enable))); }\n\n  bool ShowItem(unsigned itemID, int cmdShow) const\n    { return BOOLToBool(::ShowWindow(GetItem(itemID), cmdShow)); }\n\n  bool ShowItem_Bool(unsigned itemID, bool show) const\n    { return ShowItem(itemID, show ? SW_SHOW: SW_HIDE); }\n\n  bool HideItem(unsigned itemID) const { return ShowItem(itemID, SW_HIDE); }\n\n  bool SetItemText(unsigned itemID, LPCTSTR s)\n    { return BOOLToBool(SetDlgItemText(_window, (int)itemID, s)); }\n\n  bool SetItemTextA(unsigned itemID, LPCSTR s)\n    { return BOOLToBool(SetDlgItemTextA(_window, (int)itemID, s)); }\n\n  bool SetItemText_Empty(unsigned itemID)\n    { return SetItemText(itemID, TEXT(\"\")); }\n\n  #ifndef _UNICODE\n  bool SetItemText(unsigned itemID, LPCWSTR s)\n  {\n    CWindow window(GetItem(itemID));\n    return window.SetText(s);\n  }\n  #endif\n\n  UINT GetItemText(unsigned itemID, LPTSTR string, unsigned maxCount)\n    { return GetDlgItemText(_window, (int)itemID, string, (int)maxCount); }\n  #ifndef _UNICODE\n  /*\n  bool GetItemText(unsigned itemID, LPWSTR string, int maxCount)\n  {\n    CWindow window(GetItem(unsigned));\n    return window.GetText(string, maxCount);\n  }\n  */\n  #endif\n\n  bool GetItemText(unsigned itemID, UString &s)\n  {\n    CWindow window(GetItem(itemID));\n    return window.GetText(s);\n  }\n\n/*\n  bool SetItemInt(unsigned itemID, UINT value, bool isSigned)\n    { return BOOLToBool(SetDlgItemInt(_window, (int)itemID, value, BoolToBOOL(isSigned))); }\n*/\n  bool SetItemUInt(unsigned itemID, UINT value)\n    { return BOOLToBool(SetDlgItemInt(_window, (int)itemID, value, FALSE)); }\n/*\n  bool GetItemInt(unsigned itemID, bool isSigned, UINT &value)\n  {\n    BOOL result;\n    value = GetDlgItemInt(_window, (int)itemID, &result, BoolToBOOL(isSigned));\n    return BOOLToBool(result);\n  }\n*/\n  bool GetItemUInt(unsigned itemID, UINT &value)\n  {\n    BOOL result;\n    value = GetDlgItemInt(_window, (int)itemID, &result, FALSE);\n    return BOOLToBool(result);\n  }\n\n  HWND GetNextGroupItem(HWND control, bool previous)\n    { return GetNextDlgGroupItem(_window, control, BoolToBOOL(previous)); }\n  HWND GetNextTabItem(HWND control, bool previous)\n    { return GetNextDlgTabItem(_window, control, BoolToBOOL(previous)); }\n\n  LRESULT SendMsg_NextDlgCtl(WPARAM wParam, LPARAM lParam)\n    { return SendMsg(WM_NEXTDLGCTL, wParam, lParam); }\n  LRESULT SendMsg_NextDlgCtl_HWND(HWND hwnd) { return SendMsg_NextDlgCtl((WPARAM)hwnd, TRUE); }\n  LRESULT SendMsg_NextDlgCtl_CtlId(unsigned id)   { return SendMsg_NextDlgCtl_HWND(GetItem(id)); }\n  LRESULT SendMsg_NextDlgCtl_Next()          { return SendMsg_NextDlgCtl(0, FALSE); }\n  LRESULT SendMsg_NextDlgCtl_Prev()          { return SendMsg_NextDlgCtl(1, FALSE); }\n\n  bool MapRect(LPRECT rect)\n    { return BOOLToBool(MapDialogRect(_window, rect)); }\n\n  bool IsMessage(LPMSG message)\n    { return BOOLToBool(IsDialogMessage(_window, message)); }\n\n  LRESULT SendItemMessage(unsigned itemID, UINT message, WPARAM wParam, LPARAM lParam)\n    { return SendDlgItemMessage(_window, (int)itemID, message, wParam, lParam); }\n\n  bool CheckButton(unsigned buttonID, UINT checkState)\n    { return BOOLToBool(CheckDlgButton(_window, (int)buttonID, checkState)); }\n  bool CheckButton(unsigned buttonID, bool checkState)\n    { return CheckButton(buttonID, UINT(checkState ? BST_CHECKED : BST_UNCHECKED)); }\n\n  UINT IsButtonChecked_BST(unsigned buttonID) const\n    { return IsDlgButtonChecked(_window, (int)buttonID); }\n  bool IsButtonCheckedBool(unsigned buttonID) const\n    { return (IsButtonChecked_BST(buttonID) == BST_CHECKED); }\n\n  bool CheckRadioButton(unsigned firstButtonID, unsigned lastButtonID, unsigned checkButtonID)\n    { return BOOLToBool(::CheckRadioButton(_window,\n        (int)firstButtonID, (int)lastButtonID, (int)checkButtonID)); }\n\n  virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\n  virtual bool OnInit() { return true; }\n  // virtual bool OnCommand2(WPARAM wParam, LPARAM lParam);\n  virtual bool OnCommand(unsigned code, unsigned itemID, LPARAM lParam);\n  virtual bool OnSize(WPARAM /* wParam */, int /* xSize */, int /* ySize */) { return false; }\n  virtual bool OnDestroy() { return false; }\n\n  // **************** NanaZip Modification Start ****************\n#if 0 // ******** Annotated 7-Zip Mainline Source Code snippet Start ********\n  /*\n  #ifdef UNDER_CE\n  virtual void OnHelp(void *) { OnHelp(); }\n  #else\n  virtual void OnHelp(LPHELPINFO) { OnHelp(); }\n  #endif\n  */\n  virtual void OnHelp() {}\n#endif // ******** Annotated 7-Zip Mainline Source Code snippet End ********\n  // **************** NanaZip Modification End ****************\n\n  virtual bool OnButtonClicked(unsigned buttonID, HWND buttonHWND);\n  virtual void OnOK() {}\n  virtual void OnContinue() {}\n  virtual void OnCancel() {}\n  virtual void OnClose() {}\n  virtual bool OnNotify(UINT /* controlID */, LPNMHDR /* lParam */) { return false; }\n  virtual bool OnTimer(WPARAM /* timerID */, LPARAM /* callback */) { return false; }\n\n  LONG_PTR SetMsgResult(LONG_PTR newLongPtr )\n    { return SetLongPtr(DWLP_MSGRESULT, newLongPtr); }\n  LONG_PTR GetMsgResult() const\n    { return GetLongPtr(DWLP_MSGRESULT); }\n\n  bool GetMargins(int margin, int &x, int &y);\n  int Units_To_Pixels_X(int units);\n  bool GetItemSizes(unsigned id, int &x, int &y);\n  void GetClientRectOfItem(unsigned id, RECT &rect);\n  bool MoveItem(unsigned id, int x, int y, int width, int height, bool repaint = true);\n  bool MoveItem_RECT(unsigned id, const RECT &r, bool repaint = true)\n    { return MoveItem(id, r.left, r.top, RECT_SIZE_X(r), RECT_SIZE_Y(r), repaint); }\n\n  void NormalizeSize(bool fullNormalize = false);\n  void NormalizePosition();\n};\n\nclass CModelessDialog: public CDialog\n{\npublic:\n  bool Create(LPCTSTR templateName, HWND parentWindow);\n  bool Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }\n  #ifndef _UNICODE\n  bool Create(LPCWSTR templateName, HWND parentWindow);\n  #endif\n  virtual void OnOK() Z7_override { Destroy(); }\n  virtual void OnContinue() Z7_override { Destroy(); }\n  virtual void OnCancel() Z7_override { Destroy(); }\n  virtual void OnClose() Z7_override { Destroy(); }\n};\n\nclass CModalDialog: public CDialog\n{\npublic:\n  INT_PTR Create(LPCTSTR templateName, HWND parentWindow);\n  INT_PTR Create(UINT resID, HWND parentWindow) { return Create(MAKEINTRESOURCEW(resID), parentWindow); }\n  #ifndef _UNICODE\n  INT_PTR Create(LPCWSTR templateName, HWND parentWindow);\n  #endif\n\n  bool End(INT_PTR result) { return BOOLToBool(::EndDialog(_window, result)); }\n  virtual void OnOK() Z7_override { End(IDOK); }\n  virtual void OnContinue() Z7_override { End(IDCONTINUE); }\n  virtual void OnCancel() Z7_override { End(IDCANCEL); }\n  virtual void OnClose() Z7_override { End(IDCLOSE); }\n};\n\nclass CDialogChildControl: public NWindows::CWindow\n{\n  // unsigned m_ID;\npublic:\n  void Init(const NWindows::NControl::CDialog &parentDialog, unsigned id)\n  {\n    // m_ID = id;\n    Attach(parentDialog.GetItem(id));\n  }\n};\n\nbool IsDialogSizeOK(int xSize, int ySize, HWND hwnd = NULL);\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/Edit.h",
    "content": "﻿// Windows/Control/Edit.h\n\n#ifndef ZIP7_INC_WINDOWS_CONTROL_EDIT_H\n#define ZIP7_INC_WINDOWS_CONTROL_EDIT_H\n\n// **************** NanaZip Modification Start ****************\n#include <Shlwapi.h>\n// **************** NanaZip Modification End ****************\n\n#include \"../Window.h\"\n\nnamespace NWindows {\nnamespace NControl {\n\nclass CEdit: public CWindow\n{\npublic:\n  // **************** NanaZip Modification Start ****************\n  void Attach(HWND newWindow) override {\n    _window = newWindow;\n    ::SHAutoComplete(\n        _window,\n        SHACF_AUTOAPPEND_FORCE_OFF | SHACF_AUTOSUGGEST_FORCE_OFF);\n  }\n  // **************** NanaZip Modification End ****************\n  void SetPasswordChar(WPARAM c) { SendMsg(EM_SETPASSWORDCHAR, c); }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/ListView.cpp",
    "content": "﻿// Windows/Control/ListView.cpp\n\n#include \"StdAfx.h\"\n\n#include \"ListView.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\nnamespace NControl {\n\nbool CListView::CreateEx(DWORD exStyle, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam)\n{\n  return CWindow::CreateEx(exStyle, WC_LISTVIEW, TEXT(\"\"), style, x, y, width,\n      height, parentWindow, idOrHMenu, instance, createParam);\n}\n\n/* note: LVITEM and LVCOLUMN structures contain optional fields\n   depending from preprocessor macros:\n      #if (_WIN32_IE >= 0x0300)\n      #if (_WIN32_WINNT >= 0x0501)\n      #if (_WIN32_WINNT >= 0x0600)\n*/\n\nbool CListView::GetItemParam(unsigned index, LPARAM &param) const\n{\n  LVITEM item;\n  item.iItem = (int)index;\n  item.iSubItem = 0;\n  item.mask = LVIF_PARAM;\n  const bool res = GetItem(&item);\n  param = item.lParam;\n  return res;\n}\n\nint CListView::InsertColumn(unsigned columnIndex, LPCTSTR text, int width)\n{\n  LVCOLUMN ci;\n  ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;\n  ci.pszText = (LPTSTR)(void *)text;\n  ci.iSubItem = (int)columnIndex;\n  ci.cx = width;\n  return InsertColumn(columnIndex, &ci);\n}\n\nint CListView::InsertItem(unsigned index, LPCTSTR text)\n{\n  LVITEM item;\n  item.mask = LVIF_TEXT | LVIF_PARAM;\n  item.iItem = (int)index;\n  item.lParam = (LPARAM)index;\n  item.pszText = (LPTSTR)(void *)text;\n  item.iSubItem = 0;\n  return InsertItem(&item);\n}\n\nint CListView::SetSubItem(unsigned index, unsigned subIndex, LPCTSTR text)\n{\n  LVITEM item;\n  item.mask = LVIF_TEXT;\n  item.iItem = (int)index;\n  item.pszText = (LPTSTR)(void *)text;\n  item.iSubItem = (int)subIndex;\n  return SetItem(&item);\n}\n\n#ifndef _UNICODE\n\nint CListView::InsertColumn(unsigned columnIndex, LPCWSTR text, int width)\n{\n  LVCOLUMNW ci;\n  ci.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;\n  ci.pszText = (LPWSTR)(void *)text;\n  ci.iSubItem = (int)columnIndex;\n  ci.cx = width;\n  return InsertColumn(columnIndex, &ci);\n}\n\nint CListView::InsertItem(unsigned index, LPCWSTR text)\n{\n  LVITEMW item;\n  item.mask = LVIF_TEXT | LVIF_PARAM;\n  item.iItem = (int)index;\n  item.lParam = (LPARAM)index;\n  item.pszText = (LPWSTR)(void *)text;\n  item.iSubItem = 0;\n  return InsertItem(&item);\n}\n\nint CListView::SetSubItem(unsigned index, unsigned subIndex, LPCWSTR text)\n{\n  LVITEMW item;\n  item.mask = LVIF_TEXT;\n  item.iItem = (int)index;\n  item.pszText = (LPWSTR)(void *)text;\n  item.iSubItem = (int)subIndex;\n  return SetItem(&item);\n}\n\n#endif\n\nstatic LRESULT APIENTRY ListViewSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\n{\n  CWindow window(hwnd);\n  CListView2 *w = (CListView2 *)(window.GetUserDataLongPtr());\n  if (w == NULL)\n    return 0;\n  return w->OnMessage(message, wParam, lParam);\n}\n\nLRESULT CListView2::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\n{\n  #ifndef _UNICODE\n  if (g_IsNT)\n    return CallWindowProcW(_origWindowProc, *this, message, wParam, lParam);\n  else\n  #endif\n    return CallWindowProc(_origWindowProc, *this, message, wParam, lParam);\n}\n\nvoid CListView2::SetWindowProc()\n{\n  SetUserDataLongPtr((LONG_PTR)this);\n  #ifndef _UNICODE\n  if (g_IsNT)\n    _origWindowProc = (WNDPROC)SetLongPtrW(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc);\n  else\n  #endif\n    _origWindowProc = (WNDPROC)SetLongPtr(GWLP_WNDPROC, (LONG_PTR)ListViewSubclassProc);\n}\n\n/*\nLRESULT CListView3::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)\n{\n  LRESULT res = CListView2::OnMessage(message, wParam, lParam);\n  if (message == WM_GETDLGCODE)\n  {\n    // when user presses RETURN, windows sends default (first) button command to parent dialog.\n    // we disable this:\n    MSG *msg = (MSG *)lParam;\n    WPARAM key = wParam;\n    bool change = false;\n    if (msg)\n    {\n      if (msg->message == WM_KEYDOWN && msg->wParam == VK_RETURN)\n        change = true;\n    }\n    else if (wParam == VK_RETURN)\n      change = true;\n    if (change)\n      res |= DLGC_WANTALLKEYS;\n  }\n  return res;\n}\n*/\n  \n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/ListView.h",
    "content": "﻿// Windows/Control/ListView.h\n\n#ifndef ZIP7_INC_WINDOWS_CONTROL_LISTVIEW_H\n#define ZIP7_INC_WINDOWS_CONTROL_LISTVIEW_H\n\n#include \"../../Common/MyWindows.h\"\n\n#include <CommCtrl.h>\n\n#include \"../Window.h\"\n\nnamespace NWindows {\nnamespace NControl {\n\nclass CListView: public NWindows::CWindow\n{\npublic:\n  bool CreateEx(DWORD exStyle, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam);\n\n  void SetUnicodeFormat()\n  {\n    #ifndef UNDER_CE\n    ListView_SetUnicodeFormat(_window, TRUE);\n    #endif\n  }\n \n  bool DeleteAllItems() { return BOOLToBool(ListView_DeleteAllItems(_window)); }\n  bool DeleteColumn(unsigned columnIndex) { return BOOLToBool(ListView_DeleteColumn(_window, columnIndex)); }\n\n  int InsertColumn(unsigned columnIndex, const LVCOLUMN *columnInfo) { return ListView_InsertColumn(_window, columnIndex, columnInfo); }\n  int InsertColumn(unsigned columnIndex, LPCTSTR text, int width);\n  bool SetColumnOrderArray(unsigned count, const int *columns)\n    { return BOOLToBool(ListView_SetColumnOrderArray(_window, count, (int *)(void *)columns)); }\n\n  /*\n  int GetNumColumns()\n  {\n    HWND header = ListView_GetHeader(_window);\n    if (!header)\n      return -1;\n    return Header_GetItemCount(header);\n  }\n  */\n\n  int InsertItem(const LVITEM* item) { return ListView_InsertItem(_window, item); }\n  int InsertItem(unsigned index, LPCTSTR text);\n  bool SetItem(const LVITEM* item) { return BOOLToBool(ListView_SetItem(_window, item)); }\n  int SetSubItem(unsigned index, unsigned subIndex, LPCTSTR text);\n\n  #ifndef _UNICODE\n\n  int InsertColumn(unsigned columnIndex, const LVCOLUMNW *columnInfo) { return (int)SendMsg(LVM_INSERTCOLUMNW, (WPARAM)columnIndex, (LPARAM)columnInfo); }\n  int InsertColumn(unsigned columnIndex, LPCWSTR text, int width);\n  int InsertItem(const LV_ITEMW* item) { return (int)SendMsg(LVM_INSERTITEMW, 0, (LPARAM)item); }\n  int InsertItem(unsigned index, LPCWSTR text);\n  bool SetItem(const LV_ITEMW* item) { return BOOLToBool((BOOL)SendMsg(LVM_SETITEMW, 0, (LPARAM)item)); }\n  int SetSubItem(unsigned index, unsigned subIndex, LPCWSTR text);\n\n  #endif\n\n  bool DeleteItem(unsigned itemIndex) { return BOOLToBool(ListView_DeleteItem(_window, itemIndex)); }\n\n  UINT GetSelectedCount() const { return ListView_GetSelectedCount(_window); }\n  int GetItemCount() const { return ListView_GetItemCount(_window); }\n\n  INT GetSelectionMark() const { return ListView_GetSelectionMark(_window); }\n\n  void SetItemCount(unsigned numItems) { ListView_SetItemCount(_window, numItems); }\n  void SetItemCountEx(unsigned numItems, DWORD flags) {  ListView_SetItemCountEx(_window, numItems, flags); }\n\n  /* startIndex : The index of the item with which to begin the search,\n     or -1 to find the first item that matches the specified flags.\n     The specified item itself is excluded from the search. */\n  int GetNextItem(int startIndex, UINT flags) const { return ListView_GetNextItem(_window, startIndex, flags); }\n  int GetNextSelectedItem(int startIndex) const { return GetNextItem(startIndex, LVNI_SELECTED); }\n  int GetFocusedItem() const { return GetNextItem(-1, LVNI_FOCUSED); }\n  \n  bool GetItem(LVITEM* item) const { return BOOLToBool(ListView_GetItem(_window, item)); }\n  bool GetItemParam(unsigned itemIndex, LPARAM &param) const;\n  /*\n  void GetItemText(unsigned itemIndex, unsigned subItemIndex, LPTSTR text, unsigned textSizeMax) const\n    { ListView_GetItemText(_window, itemIndex, subItemIndex, text, textSizeMax) }\n  */\n  bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam)\n    { return BOOLToBool(ListView_SortItems(_window, compareFunction, dataParam)); }\n\n  // If (index == -1), then the state change is applied to all items.\n  void SetItemState(int index, UINT state, UINT mask) { ListView_SetItemState(_window, index, state, mask) }\n  void SetItemState_Selected(int index, bool select) { SetItemState(index, select ? LVIS_SELECTED : 0, LVIS_SELECTED); }\n  void SetItemState_Selected(int index) { SetItemState(index, LVIS_SELECTED, LVIS_SELECTED); }\n  void SelectAll() { SetItemState_Selected(-1); }\n  void SetItemState_FocusedSelected(int index) { SetItemState(index, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); }\n  UINT GetItemState(int index, UINT mask) const { return ListView_GetItemState(_window, index, mask); }\n  bool IsItemSelected(int index) const { return GetItemState(index, LVIS_SELECTED) == LVIS_SELECTED; }\n\n  bool GetColumn(unsigned columnIndex, LVCOLUMN* columnInfo) const\n    { return BOOLToBool(ListView_GetColumn(_window, columnIndex, columnInfo)); }\n\n  HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType)\n    { return ListView_SetImageList(_window, imageList, imageListType); }\n\n  // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3)\n  DWORD GetExtendedListViewStyle() { return ListView_GetExtendedListViewStyle(_window); }\n  void SetExtendedListViewStyle(DWORD exStyle) { ListView_SetExtendedListViewStyle(_window, exStyle); }\n  void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle) { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); }\n\n  void SetCheckState(UINT index, bool checkState) { ListView_SetCheckState(_window, index, BoolToBOOL(checkState)) }\n  bool GetCheckState(UINT index) { return BOOLToBool(ListView_GetCheckState(_window, index)); }\n\n  bool EnsureVisible(int index, bool partialOK) { return BOOLToBool(ListView_EnsureVisible(_window, index, BoolToBOOL(partialOK))); }\n\n  bool GetItemRect(int index, RECT *rect, int code) { return BOOLToBool(ListView_GetItemRect(_window, index, rect, code)); }\n\n  HWND GetEditControl() { return ListView_GetEditControl(_window) ; }\n  HWND EditLabel(int itemIndex) { return ListView_EditLabel(_window, itemIndex) ; }\n\n  bool RedrawItems(int firstIndex, int lastIndex) { return BOOLToBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); }\n  bool RedrawAllItems()\n  {\n    if (GetItemCount() > 0)\n      return RedrawItems(0, GetItemCount() - 1);\n    return true;\n  }\n  bool RedrawItem(int index) { return RedrawItems(index, index); }\n \n  int HitTest(LPLVHITTESTINFO info) { return ListView_HitTest(_window, info); }\n  COLORREF GetBkColor() { return ListView_GetBkColor(_window); }\n  bool SetColumnWidth(int iCol, int cx) { return BOOLToBool(ListView_SetColumnWidth(_window, iCol, cx)); }\n  bool SetColumnWidthAuto(int iCol) { return SetColumnWidth(iCol, LVSCW_AUTOSIZE); }\n};\n\nclass CListView2: public CListView\n{\n  WNDPROC _origWindowProc;\n  // ~CListView2() ZIP7_eq_delete;\npublic:\n  virtual ~CListView2() {}\n  CListView2() {}\n  void SetWindowProc();\n  virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\n};\n\n/*\nclass CListView3: public CListView2\n{\npublic:\n  virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam);\n};\n*/\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/ProgressBar.h",
    "content": "﻿// Windows/Control/ProgressBar.h\n\n#ifndef ZIP7_INC_WINDOWS_CONTROL_PROGRESSBAR_H\n#define ZIP7_INC_WINDOWS_CONTROL_PROGRESSBAR_H\n\n#include \"../../Common/MyWindows.h\"\n\n#include <CommCtrl.h>\n\n#include \"../Window.h\"\n\nnamespace NWindows {\nnamespace NControl {\n\nclass CProgressBar: public CWindow\n{\npublic:\n  LRESULT SetPos(int pos) { return SendMsg(PBM_SETPOS, (unsigned)pos, 0); }\n  // LRESULT DeltaPos(int increment) { return SendMsg(PBM_DELTAPOS, increment, 0); }\n  // UINT GetPos() { return (UINT)SendMsg(PBM_GETPOS, 0, 0); }\n  // LRESULT SetRange(unsigned short minValue, unsigned short maxValue) { return SendMsg(PBM_SETRANGE, 0, MAKELPARAM(minValue, maxValue)); }\n  DWORD SetRange32(int minValue, int maxValue) { return (DWORD)SendMsg(PBM_SETRANGE32, (unsigned)minValue, (LPARAM)(unsigned)maxValue); }\n  // int SetStep(int step) { return (int)SendMsg(PBM_SETSTEP, step, 0); }\n  // LRESULT StepIt() { return SendMsg(PBM_STEPIT, 0, 0); }\n  // INT GetRange(bool minValue, PPBRANGE range) { return (INT)SendMsg(PBM_GETRANGE, BoolToBOOL(minValue), (LPARAM)range); }\n  \n  #ifndef UNDER_CE\n  COLORREF SetBarColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBARCOLOR, 0, (LPARAM)color); }\n  COLORREF SetBackgroundColor(COLORREF color) { return (COLORREF)SendMsg(PBM_SETBKCOLOR, 0, (LPARAM)color); }\n  #endif\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/Static.h",
    "content": "﻿// Windows/Control/Static.h\n\n#ifndef ZIP7_INC_WINDOWS_CONTROL_STATIC_H\n#define ZIP7_INC_WINDOWS_CONTROL_STATIC_H\n\n#include \"../Window.h\"\n\nnamespace NWindows {\nnamespace NControl {\n\nclass CStatic: public CWindow\n{\npublic:\n  HANDLE SetImage(WPARAM imageType, HANDLE handle) { return (HANDLE)SendMsg(STM_SETIMAGE, imageType, (LPARAM)handle); }\n  HANDLE GetImage(WPARAM imageType) { return (HANDLE)SendMsg(STM_GETIMAGE, imageType, 0); }\n\n  #ifdef UNDER_CE\n  HICON SetIcon(HICON icon) { return (HICON)SetImage(IMAGE_ICON, icon); }\n  HICON GetIcon() { return (HICON)GetImage(IMAGE_ICON); }\n  #else\n  HICON SetIcon(HICON icon) { return (HICON)SendMsg(STM_SETICON, (WPARAM)icon, 0); }\n  HICON GetIcon() { return (HICON)SendMsg(STM_GETICON, 0, 0); }\n  #endif\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Control/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/DLL.cpp",
    "content": "﻿// Windows/DLL.cpp\n\n#include \"StdAfx.h\"\n\n#include \"DLL.h\"\n\n#ifdef _WIN32\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nextern HINSTANCE g_hInstance;\n\nnamespace NWindows {\nnamespace NDLL {\n\nbool CLibrary::Free() throw()\n{\n  if (_module == NULL)\n    return true;\n  if (!::FreeLibrary(_module))\n    return false;\n  _module = NULL;\n  return true;\n}\n\nbool CLibrary::LoadEx(CFSTR path, DWORD flags) throw()\n{\n  if (!Free())\n    return false;\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    _module = ::LoadLibraryEx(fs2fas(path), NULL, flags);\n  }\n  else\n  #endif\n  {\n    _module = ::LoadLibraryExW(fs2us(path), NULL, flags);\n  }\n  return (_module != NULL);\n}\n\nbool CLibrary::Load(CFSTR path) throw()\n{\n  if (!Free())\n    return false;\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    _module = ::LoadLibrary(fs2fas(path));\n  }\n  else\n  #endif\n  {\n    _module = ::LoadLibraryW(fs2us(path));\n  }\n  return (_module != NULL);\n}\n\nbool MyGetModuleFileName(FString &path)\n{\n  const HMODULE hModule = g_hInstance;\n  path.Empty();\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    TCHAR s[MAX_PATH + 2];\n    s[0] = 0;\n    const DWORD size = ::GetModuleFileName(hModule, s, MAX_PATH + 1);\n    if (size <= MAX_PATH && size != 0)\n    {\n      path = fas2fs(s);\n      return true;\n    }\n  }\n  else\n  #endif\n  {\n    WCHAR s[MAX_PATH + 2];\n    s[0] = 0;\n    const DWORD size = ::GetModuleFileNameW(hModule, s, MAX_PATH + 1);\n    if (size <= MAX_PATH && size != 0)\n    {\n      path = us2fs(s);\n      return true;\n    }\n  }\n  return false;\n}\n\n#ifndef Z7_SFX\n\nFString GetModuleDirPrefix()\n{\n  FString s;\n  if (MyGetModuleFileName(s))\n  {\n    const int pos = s.ReverseFind_PathSepar();\n    if (pos >= 0)\n      s.DeleteFrom((unsigned)(pos + 1));\n  }\n  if (s.IsEmpty())\n    s = \".\" STRING_PATH_SEPARATOR;\n  return s;\n}\n\n#endif\n\n}}\n\n#else // _WIN32\n\n#include <dlfcn.h>\n#include <stdlib.h>\n\n// FARPROC\nvoid *GetProcAddress(HMODULE module, LPCSTR procName)\n{\n  void *ptr = NULL;\n  if (module)\n    ptr = dlsym(module, procName);\n  return ptr;\n}\n\nnamespace NWindows {\nnamespace NDLL {\n\nbool CLibrary::Free() throw()\n{\n  if (!_module)\n    return true;\n  const int ret = dlclose(_module);\n  if (ret != 0)\n    return false;\n  _module = NULL;\n  return true;\n}\n\nbool CLibrary::Load(CFSTR path) throw()\n{\n  if (!Free())\n    return false;\n\n  int options = 0;\n\n  #ifdef RTLD_LOCAL\n    options |= RTLD_LOCAL;\n  #endif\n\n  #ifdef RTLD_NOW\n    options |= RTLD_NOW;\n  #endif\n\n  #ifdef RTLD_GROUP\n    #if ! (defined(hpux) || defined(__hpux))\n      options |= RTLD_GROUP; // mainly for solaris but not for HPUX\n    #endif\n  #endif\n  \n  _module = dlopen(path, options);\n  return (_module != NULL);\n}\n\n/*\n// FARPROC\nvoid * CLibrary::GetProc(LPCSTR procName) const\n{\n  // return My_GetProcAddress(_module, procName);\n  return local_GetProcAddress(_module, procName);\n  // return NULL;\n}\n*/\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/DLL.h",
    "content": "﻿// Windows/DLL.h\n\n#ifndef ZIP7_INC_WINDOWS_DLL_H\n#define ZIP7_INC_WINDOWS_DLL_H\n\n#include \"../Common/MyString.h\"\n\n#ifndef _WIN32\ntypedef void * HMODULE;\n// typedef int (*FARPROC)();\n// typedef void *FARPROC;\nvoid *GetProcAddress(HMODULE module, LPCSTR procName);\n#endif\n\nnamespace NWindows {\nnamespace NDLL {\n\n#ifdef _WIN32\n\n/*\n#ifdef UNDER_CE\n#define My_GetProcAddress(module, procName) (void *)::GetProcAddressA(module, procName)\n#else\n#define My_GetProcAddress(module, procName) (void *)::GetProcAddress(module, procName)\n#endif\n*/\n\n/* Win32: Don't call CLibrary::Free() and FreeLibrary() from another\n    FreeLibrary() code: detaching code in DLL entry-point or in\n    destructors of global objects in DLL module. */\n\nclass CLibrary\n{\n  HMODULE _module;\n\n  // Z7_CLASS_NO_COPY(CLibrary);\n  // copy constructor is required here\npublic:\n  CLibrary(): _module(NULL) {}\n  ~CLibrary() { Free(); }\n\n  CLibrary(const CLibrary &c): _module(NULL)\n  {\n    if (c._module)\n    {\n      // we need non const to reference from original item\n      // c._module = NULL;\n      throw 20230102;\n    }\n  }\n\n  HMODULE Get_HMODULE() const { return _module; }\n  // operator HMODULE() const { return _module; }\n  // HMODULE* operator&() { return &_module; }\n  bool IsLoaded() const { return (_module != NULL); }\n\n  void Attach(HMODULE m)\n  {\n    Free();\n    _module = m;\n  }\n  HMODULE Detach()\n  {\n    const HMODULE m = _module;\n    _module = NULL;\n    return m;\n  }\n\n  bool Free() throw();\n  bool LoadEx(CFSTR path, DWORD flags = LOAD_LIBRARY_AS_DATAFILE) throw();\n  bool Load(CFSTR path) throw();\n  // FARPROC\n  // void *GetProc(LPCSTR procName) const { return My_GetProcAddress(_module, procName); }\n};\n\n#else\n\nclass CLibrary\n{\n  HMODULE _module;\n\n  // Z7_CLASS_NO_COPY(CLibrary);\npublic:\n  CLibrary(): _module(NULL) {}\n  ~CLibrary() { Free(); }\n\n  HMODULE Get_HMODULE() const { return _module; }\n\n  bool Free() throw();\n  bool Load(CFSTR path) throw();\n  // FARPROC\n  // void *GetProc(LPCSTR procName) const; // { return My_GetProcAddress(_module, procName); }\n};\n\n#endif\n\nbool MyGetModuleFileName(FString &path);\n\nFString GetModuleDirPrefix();\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Defs.h",
    "content": "﻿// Windows/Defs.h\n\n#ifndef ZIP7_INC_WINDOWS_DEFS_H\n#define ZIP7_INC_WINDOWS_DEFS_H\n\n#include \"../Common/MyWindows.h\"\n\n#ifdef _WIN32\ninline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); }\n#endif\n\ninline bool BOOLToBool(BOOL v) { return (v != FALSE); }\n\ninline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); }\ninline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); }\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/ErrorMsg.cpp",
    "content": "﻿// Windows/ErrorMsg.h\n\n#include \"StdAfx.h\"\n\n#if !defined(_UNICODE) || !defined(_WIN32)\n#include \"../Common/StringConvert.h\"\n#endif\n\n#include \"ErrorMsg.h\"\n\n#ifdef _WIN32\n#if !defined(_UNICODE)\nextern bool g_IsNT;\n#endif\n#endif\n\nnamespace NWindows {\nnamespace NError {\n\nstatic bool MyFormatMessage(DWORD errorCode, UString &message)\n{\n  #ifndef Z7_SFX\n  if ((HRESULT)errorCode == MY_HRES_ERROR_INTERNAL_ERROR)\n  {\n    message = \"Internal Error: The failure in hardware (RAM or CPU), OS or program\";\n    return true;\n  }\n  #endif\n\n  #ifdef _WIN32\n  \n  LPVOID msgBuf;\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |\n        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n        NULL, errorCode, 0, (LPTSTR) &msgBuf, 0, NULL) == 0)\n      return false;\n    message = GetUnicodeString((LPCTSTR)msgBuf);\n  }\n  else\n  #endif\n  {\n    if (::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |\n        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\n        NULL, errorCode, 0, (LPWSTR) &msgBuf, 0, NULL) == 0)\n      return false;\n    message = (LPCWSTR)msgBuf;\n  }\n  ::LocalFree(msgBuf);\n  return true;\n  \n  #else // _WIN32\n\n  AString m;\n\n  const char *s = NULL;\n\n  switch ((Int32)errorCode)\n  {\n    // case ERROR_NO_MORE_FILES   : s = \"No more files\"; break;\n    // case ERROR_DIRECTORY       : s = \"Error Directory\"; break;\n    case E_NOTIMPL             : s = \"E_NOTIMPL : Not implemented\"; break;\n    case E_NOINTERFACE         : s = \"E_NOINTERFACE : No such interface supported\"; break;\n    case E_ABORT               : s = \"E_ABORT : Operation aborted\"; break;\n    case E_FAIL                : s = \"E_FAIL : Unspecified error\"; break;\n    \n    case STG_E_INVALIDFUNCTION : s = \"STG_E_INVALIDFUNCTION\"; break;\n    case CLASS_E_CLASSNOTAVAILABLE : s = \"CLASS_E_CLASSNOTAVAILABLE\"; break;\n    \n    case E_OUTOFMEMORY         : s = \"E_OUTOFMEMORY : Can't allocate required memory\"; break;\n    case E_INVALIDARG          : s = \"E_INVALIDARG : One or more arguments are invalid\"; break;\n    \n    // case MY_E_ERROR_NEGATIVE_SEEK : s = \"MY_E_ERROR_NEGATIVE_SEEK\"; break;\n    default:\n      break;\n  }\n\n  /* strerror() for unknown errors still shows message \"Unknown error -12345678\")\n     So we must transfer error codes before strerror() */\n  if (!s)\n  {\n    if ((errorCode & 0xFFFF0000) == (UInt32)((MY_FACILITY_WRes << 16) | 0x80000000))\n      errorCode &= 0xFFFF;\n    else if ((errorCode & ((UInt32)1 << 31)))\n      return false; // we will show hex error later for that case\n    \n    s = strerror((int)errorCode);\n  \n    // if (!s)\n    {\n      m += \"errno=\";\n      m.Add_UInt32(errorCode);\n      if (s)\n        m += \" : \";\n    }\n  }\n  \n  if (s)\n    m += s;\n\n  MultiByteToUnicodeString2(message, m);\n  return true;\n\n  #endif\n}\n\n\nUString MyFormatMessage(DWORD errorCode)\n{\n  UString m;\n  if (!MyFormatMessage(errorCode, m) || m.IsEmpty())\n  {\n    char s[16];\n    for (int i = 0; i < 8; i++)\n    {\n      unsigned t = errorCode & 0xF;\n      errorCode >>= 4;\n      s[7 - i] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));\n    }\n    s[8] = 0;\n    m += \"Error #\";\n    m += s;\n  }\n  else if (m.Len() >= 2\n      && m[m.Len() - 1] == 0x0A\n      && m[m.Len() - 2] == 0x0D)\n    m.DeleteFrom(m.Len() - 2);\n  return m;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/ErrorMsg.h",
    "content": "﻿// Windows/ErrorMsg.h\n\n#ifndef ZIP7_INC_WINDOWS_ERROR_MSG_H\n#define ZIP7_INC_WINDOWS_ERROR_MSG_H\n\n#include \"../Common/MyString.h\"\n\nnamespace NWindows {\nnamespace NError {\n\nUString MyFormatMessage(DWORD errorCode);\ninline UString MyFormatMessage(HRESULT errorCode) { return MyFormatMessage((DWORD)errorCode); }\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileDir.cpp",
    "content": "﻿// Windows/FileDir.cpp\n\n#include \"StdAfx.h\"\n\n\n#ifndef _WIN32\n#include <stdio.h>\n#include <stdlib.h>\n#include <errno.h>\n#include <limits.h>\n#include <unistd.h>\n#include <time.h>\n#include <utime.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n\n#include \"../Common/C_FileIO.h\"\n#include \"../Common/MyBuffer2.h\"\n#include \"../Common/StringConvert.h\"\n#endif\n\n#include \"FileDir.h\"\n#include \"FileFind.h\"\n#include \"FileName.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NName;\n\n#ifndef _WIN32\n\nstatic bool FiTime_To_timespec(const CFiTime *ft, timespec &ts)\n{\n  if (ft)\n  {\n#if defined(_AIX)\n    ts.tv_sec  = ft->tv_sec;\n    ts.tv_nsec = ft->tv_nsec;\n#else\n    ts = *ft;\n#endif\n    return true;\n  }\n  // else\n  {\n    ts.tv_sec = 0;\n    ts.tv_nsec =\n    #ifdef UTIME_OMIT\n      UTIME_OMIT; // -2 keep old timesptamp\n    #else\n      // UTIME_NOW; -1 // set to the current time\n      0;\n    #endif\n    return false;\n  }\n}\n#endif\n\nnamespace NWindows {\nnamespace NFile {\nnamespace NDir {\n\n#ifdef _WIN32\n\n#ifndef UNDER_CE\n\nbool GetWindowsDir(FString &path)\n{\n  const unsigned kBufSize = MAX_PATH + 16;\n  UINT len;\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    TCHAR s[kBufSize + 1];\n    s[0] = 0;\n    len = ::GetWindowsDirectory(s, kBufSize);\n    path = fas2fs(s);\n  }\n  else\n  #endif\n  {\n    WCHAR s[kBufSize + 1];\n    s[0] = 0;\n    len = ::GetWindowsDirectoryW(s, kBufSize);\n    path = us2fs(s);\n  }\n  return (len != 0 && len < kBufSize);\n}\n\n\n/*\nnew DOCs for GetSystemDirectory:\n  returned path does not end with a backslash unless the\n  system directory is the root directory.\n*/\n\nbool GetSystemDir(FString &path)\n{\n  const unsigned kBufSize = MAX_PATH + 16;\n  UINT len;\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    TCHAR s[kBufSize + 1];\n    s[0] = 0;\n    len = ::GetSystemDirectory(s, kBufSize);\n    path = fas2fs(s);\n  }\n  else\n  #endif\n  {\n    WCHAR s[kBufSize + 1];\n    s[0] = 0;\n    len = ::GetSystemDirectoryW(s, kBufSize);\n    path = us2fs(s);\n  }\n  return (len != 0 && len < kBufSize);\n}\n#endif // UNDER_CE\n\n\nstatic bool SetFileTime_Base(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, DWORD dwFlagsAndAttributes)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\n    return false;\n  }\n  #endif\n  \n  HANDLE hDir = INVALID_HANDLE_VALUE;\n  IF_USE_MAIN_PATH\n    hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,\n        NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);\n  #ifdef Z7_LONG_PATH\n  if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)\n  {\n    UString superPath;\n    if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n      hDir = ::CreateFileW(superPath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,\n          NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);\n  }\n  #endif\n\n  bool res = false;\n  if (hDir != INVALID_HANDLE_VALUE)\n  {\n    res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime));\n    ::CloseHandle(hDir);\n  }\n  return res;\n}\n\nbool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)\n{\n  return SetFileTime_Base(path, cTime, aTime, mTime, FILE_FLAG_BACKUP_SEMANTICS);\n}\n\nbool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)\n{\n  return SetFileTime_Base(path, cTime, aTime, mTime, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT);\n}\n\n\nbool SetFileAttrib(CFSTR path, DWORD attrib)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    if (::SetFileAttributes(fs2fas(path), attrib))\n      return true;\n  }\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH\n      if (::SetFileAttributesW(fs2us(path), attrib))\n        return true;\n    #ifdef Z7_LONG_PATH\n    if (USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        return BOOLToBool(::SetFileAttributesW(superPath, attrib));\n    }\n    #endif\n  }\n  return false;\n}\n\n\nbool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)\n{\n  #ifdef _WIN32\n  if ((attrib & 0xF0000000) != 0)\n    attrib &= 0x3FFF;\n  #endif\n  return SetFileAttrib(path, attrib);\n}\n\n\nbool RemoveDir(CFSTR path)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    if (::RemoveDirectory(fs2fas(path)))\n      return true;\n  }\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH\n      if (::RemoveDirectoryW(fs2us(path)))\n        return true;\n    #ifdef Z7_LONG_PATH\n    if (USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        return BOOLToBool(::RemoveDirectoryW(superPath));\n    }\n    #endif\n  }\n  return false;\n}\n\n\n// When moving a directory, oldFile and newFile must be on the same drive.\n\nbool MyMoveFile(CFSTR oldFile, CFSTR newFile)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    if (::MoveFile(fs2fas(oldFile), fs2fas(newFile)))\n      return true;\n  }\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH_2(oldFile, newFile)\n    {\n      if (::MoveFileW(fs2us(oldFile), fs2us(newFile)))\n        return true;\n    }\n    #ifdef Z7_LONG_PATH\n    if (USE_SUPER_PATH_2)\n    {\n      UString d1, d2;\n      if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))\n        return BOOLToBool(::MoveFileW(d1, d2));\n    }\n    #endif\n  }\n  return false;\n}\n\n#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500\nstatic DWORD WINAPI CopyProgressRoutine_to_ICopyFileProgress(\n  LARGE_INTEGER TotalFileSize,          // file size\n  LARGE_INTEGER TotalBytesTransferred,  // bytes transferred\n  LARGE_INTEGER /* StreamSize */,             // bytes in stream\n  LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream\n  DWORD /* dwStreamNumber */,                 // current stream\n  DWORD /* dwCallbackReason */,               // callback reason\n  HANDLE /* hSourceFile */,                   // handle to source file\n  HANDLE /* hDestinationFile */,              // handle to destination file\n  LPVOID lpData                         // from CopyFileEx\n)\n{\n  return ((ICopyFileProgress *)lpData)->CopyFileProgress(\n      (UInt64)TotalFileSize.QuadPart,\n      (UInt64)TotalBytesTransferred.QuadPart);\n}\n#endif\n\nbool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,\n    ICopyFileProgress *progress)\n{\n#if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500\n#ifndef _UNICODE\n  if (g_IsNT)\n#endif\n  if (progress)\n  {\n    IF_USE_MAIN_PATH_2(oldFile, newFile)\n    {\n      if (::MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile),\n          CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED))\n        return true;\n      if (::GetLastError() == ERROR_REQUEST_ABORTED)\n        return false;\n    }\n    #ifdef Z7_LONG_PATH\n    if (USE_SUPER_PATH_2)\n    {\n      UString d1, d2;\n      if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2))\n        return BOOLToBool(::MoveFileWithProgressW(d1, d2,\n            CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED));\n    }\n    #endif\n    return false;\n  }\n#else\n  UNUSED_VAR(progress)\n#endif\n  return MyMoveFile(oldFile, newFile);\n}\n\n#ifndef UNDER_CE\n#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500  // Win2000\n#define Z7_USE_DYN_CreateHardLink\n#endif\n\n#ifdef Z7_USE_DYN_CreateHardLink\nEXTERN_C_BEGIN\ntypedef BOOL (WINAPI *Func_CreateHardLinkW)(\n    LPCWSTR lpFileName,\n    LPCWSTR lpExistingFileName,\n    LPSECURITY_ATTRIBUTES lpSecurityAttributes\n    );\nEXTERN_C_END\n#endif\n#endif // UNDER_CE\n\nbool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\n    return false;\n    /*\n    if (::CreateHardLink(fs2fas(newFileName), fs2fas(existFileName), NULL))\n      return true;\n    */\n  }\n  else\n  #endif\n  {\n#ifdef Z7_USE_DYN_CreateHardLink\n    const\n    Func_CreateHardLinkW\n      my_CreateHardLinkW = Z7_GET_PROC_ADDRESS(\n    Func_CreateHardLinkW, ::GetModuleHandleW(L\"kernel32.dll\"),\n        \"CreateHardLinkW\");\n    if (!my_CreateHardLinkW)\n      return false;\n    #define MY_CreateHardLinkW  my_CreateHardLinkW\n#else\n    #define MY_CreateHardLinkW  CreateHardLinkW\n#endif\n    IF_USE_MAIN_PATH_2(newFileName, existFileName)\n    {\n      if (MY_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))\n        return true;\n    }\n    #ifdef Z7_LONG_PATH\n    if (USE_SUPER_PATH_2)\n    {\n      UString d1, d2;\n      if (GetSuperPaths(newFileName, existFileName, d1, d2, USE_MAIN_PATH_2))\n        return BOOLToBool(MY_CreateHardLinkW(d1, d2, NULL));\n    }\n    #endif\n  }\n  return false;\n}\n\n\n/*\nWinXP-64 CreateDir():\n  \"\"                  - ERROR_PATH_NOT_FOUND\n  \\                   - ERROR_ACCESS_DENIED\n  C:\\                 - ERROR_ACCESS_DENIED, if there is such drive,\n  \n  D:\\folder             - ERROR_PATH_NOT_FOUND, if there is no such drive,\n  C:\\nonExistent\\folder - ERROR_PATH_NOT_FOUND\n  \n  C:\\existFolder      - ERROR_ALREADY_EXISTS\n  C:\\existFolder\\     - ERROR_ALREADY_EXISTS\n\n  C:\\folder   - OK\n  C:\\folder\\  - OK\n\n  \\\\Server\\nonExistent    - ERROR_BAD_NETPATH\n  \\\\Server\\Share_Readonly - ERROR_ACCESS_DENIED\n  \\\\Server\\Share          - ERROR_ALREADY_EXISTS\n\n  \\\\Server\\Share_NTFS_drive - ERROR_ACCESS_DENIED\n  \\\\Server\\Share_FAT_drive  - ERROR_ALREADY_EXISTS\n*/\n\nbool CreateDir(CFSTR path)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    if (::CreateDirectory(fs2fas(path), NULL))\n      return true;\n  }\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH\n      if (::CreateDirectoryW(fs2us(path), NULL))\n        return true;\n    #ifdef Z7_LONG_PATH\n    if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        return BOOLToBool(::CreateDirectoryW(superPath, NULL));\n    }\n    #endif\n  }\n  return false;\n}\n\n/*\n  CreateDir2 returns true, if directory can contain files after the call (two cases):\n    1) the directory already exists\n    2) the directory was created\n  path must be WITHOUT trailing path separator.\n\n  We need CreateDir2, since fileInfo.Find() for reserved names like \"com8\"\n   returns FILE instead of DIRECTORY. And we need to use SuperPath */\n \nstatic bool CreateDir2(CFSTR path)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    if (::CreateDirectory(fs2fas(path), NULL))\n      return true;\n  }\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH\n      if (::CreateDirectoryW(fs2us(path), NULL))\n        return true;\n    #ifdef Z7_LONG_PATH\n    if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n      {\n        if (::CreateDirectoryW(superPath, NULL))\n          return true;\n        if (::GetLastError() != ERROR_ALREADY_EXISTS)\n          return false;\n        NFind::CFileInfo fi;\n        if (!fi.Find(us2fs(superPath)))\n          return false;\n        return fi.IsDir();\n      }\n    }\n    #endif\n  }\n  if (::GetLastError() != ERROR_ALREADY_EXISTS)\n    return false;\n  NFind::CFileInfo fi;\n  if (!fi.Find(path))\n    return false;\n  return fi.IsDir();\n}\n\n#endif // _WIN32\n\nstatic bool CreateDir2(CFSTR path);\n\nbool CreateComplexDir(CFSTR _path)\n{\n  #ifdef _WIN32\n  \n  {\n    const DWORD attrib = NFind::GetFileAttrib(_path);\n    if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)\n      return true;\n  }\n\n  #ifndef UNDER_CE\n  \n  if (IsDriveRootPath_SuperAllowed(_path))\n    return false;\n  \n  const unsigned prefixSize = GetRootPrefixSize(_path);\n  \n  #endif // UNDER_CE\n\n  #else // _WIN32\n\n  // Posix\n  NFind::CFileInfo fi;\n  if (fi.Find(_path))\n  {\n    if (fi.IsDir())\n      return true;\n  }\n  \n  #endif // _WIN32\n\n  FString path (_path);\n\n  int pos = path.ReverseFind_PathSepar();\n  if (pos >= 0 && (unsigned)pos == path.Len() - 1)\n  {\n    if (path.Len() == 1)\n      return true;\n    path.DeleteBack();\n  }\n\n  const FString path2 (path);\n  pos = (int)path.Len();\n  \n  for (;;)\n  {\n    if (CreateDir2(path))\n      break;\n    if (::GetLastError() == ERROR_ALREADY_EXISTS)\n      return false;\n    pos = path.ReverseFind_PathSepar();\n    if (pos < 0 || pos == 0)\n      return false;\n    \n    #if defined(_WIN32) && !defined(UNDER_CE)\n    if (pos == 1 && IS_PATH_SEPAR(path[0]))\n      return false;\n    if (prefixSize >= (unsigned)pos + 1)\n      return false;\n    #endif\n    \n    path.DeleteFrom((unsigned)pos);\n  }\n  \n  while (pos < (int)path2.Len())\n  {\n    int pos2 = NName::FindSepar(path2.Ptr((unsigned)pos + 1));\n    if (pos2 < 0)\n      pos = (int)path2.Len();\n    else\n      pos += 1 + pos2;\n    path.SetFrom(path2, (unsigned)pos);\n    if (!CreateDir(path))\n      return false;\n  }\n  \n  return true;\n}\n\n\n#ifdef _WIN32\n\nbool DeleteFileAlways(CFSTR path)\n{\n  /* If alt stream, we also need to clear READ-ONLY attribute of main file before delete.\n     SetFileAttrib(\"name:stream\", ) changes attributes of main file. */\n  {\n    DWORD attrib = NFind::GetFileAttrib(path);\n    if (attrib != INVALID_FILE_ATTRIBUTES\n        && (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0\n        && (attrib & FILE_ATTRIBUTE_READONLY) != 0)\n    {\n      if (!SetFileAttrib(path, attrib & ~(DWORD)FILE_ATTRIBUTE_READONLY))\n        return false;\n    }\n  }\n\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    if (::DeleteFile(fs2fas(path)))\n      return true;\n  }\n  else\n  #endif\n  {\n    /* DeleteFile(\"name::$DATA\") deletes all alt streams (same as delete DeleteFile(\"name\")).\n       Maybe it's better to open \"name::$DATA\" and clear data for unnamed stream? */\n    IF_USE_MAIN_PATH\n      if (::DeleteFileW(fs2us(path)))\n        return true;\n    #ifdef Z7_LONG_PATH\n    if (USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        return BOOLToBool(::DeleteFileW(superPath));\n    }\n    #endif\n  }\n  return false;\n}\n\n\n\nbool RemoveDirWithSubItems(const FString &path)\n{\n  bool needRemoveSubItems = true;\n  {\n    NFind::CFileInfo fi;\n    if (!fi.Find(path))\n      return false;\n    if (!fi.IsDir())\n    {\n      ::SetLastError(ERROR_DIRECTORY);\n      return false;\n    }\n    if (fi.HasReparsePoint())\n      needRemoveSubItems = false;\n  }\n\n  if (needRemoveSubItems)\n  {\n    FString s (path);\n    s.Add_PathSepar();\n    const unsigned prefixSize = s.Len();\n    NFind::CEnumerator enumerator;\n    enumerator.SetDirPrefix(s);\n    NFind::CDirEntry fi;\n    bool isError = false;\n    DWORD lastError = 0;\n    while (enumerator.Next(fi))\n    {\n      s.DeleteFrom(prefixSize);\n      s += fi.Name;\n      if (fi.IsDir())\n      {\n        if (!RemoveDirWithSubItems(s))\n        {\n          lastError = GetLastError();\n          isError = true;\n        }\n      }\n      else if (!DeleteFileAlways(s))\n      {\n        lastError = GetLastError();\n        isError = false;\n      }\n    }\n    if (isError)\n    {\n      SetLastError(lastError);\n      return false;\n    }\n  }\n  \n  // we clear read-only attrib to remove read-only dir\n  if (!SetFileAttrib(path, 0))\n    return false;\n  return RemoveDir(path);\n}\n\nbool RemoveDirAlways_if_Empty(const FString &path)\n{\n  const DWORD attrib = NFind::GetFileAttrib(path);\n  if (attrib != INVALID_FILE_ATTRIBUTES\n      && (attrib & FILE_ATTRIBUTE_READONLY))\n  {\n    bool need_ClearAttrib = true;\n    if ((attrib & FILE_ATTRIBUTE_REPARSE_POINT) == 0)\n    {\n      FString s (path);\n      s.Add_PathSepar();\n      NFind::CEnumerator enumerator;\n      enumerator.SetDirPrefix(s);\n      NFind::CDirEntry fi;\n      if (enumerator.Next(fi))\n      {\n        // we don't want to change attributes, if there are files\n        // in directory, because RemoveDir(path) will fail.\n        need_ClearAttrib = false;\n        // SetLastError(ERROR_DIR_NOT_EMPTY);\n        // return false;\n      }\n    }\n    if (need_ClearAttrib)\n      SetFileAttrib(path, 0); // we clear read-only attrib to remove read-only dir\n  }\n  return RemoveDir(path);\n}\n\n#endif // _WIN32\n\n#ifdef UNDER_CE\n\nbool MyGetFullPathName(CFSTR path, FString &resFullPath)\n{\n  resFullPath = path;\n  return true;\n}\n\n#else\n\nbool MyGetFullPathName(CFSTR path, FString &resFullPath)\n{\n  return GetFullPath(path, resFullPath);\n}\n\n#ifdef _WIN32\n\n/* Win10: SetCurrentDirectory() doesn't support long paths and\n    doesn't support super prefix \"\\\\?\\\", if long path behavior is not\n    enabled in registry (LongPathsEnabled) and in manifest (longPathAware). */\n\nbool SetCurrentDir(CFSTR path)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    return BOOLToBool(::SetCurrentDirectory(fs2fas(path)));\n  }\n  else\n  #endif\n  {\n    return BOOLToBool(::SetCurrentDirectoryW(fs2us(path)));\n  }\n}\n\n\n/*\nwe use system function GetCurrentDirectory()\nnew GetCurrentDirectory() DOCs:\n  - If the function fails, the return value is zero.\n  - If the function succeeds, the return value specifies\n      the number of characters that are written to the buffer,\n      not including the terminating null character.\n  - If the buffer is not large enough, the return value specifies\n      the required size of the buffer, in characters,\n      including the null-terminating character.\n  \nGetCurrentDir() calls GetCurrentDirectory().\nGetCurrentDirectory() in win10 in tests:\n  the returned (path) does not end with a backslash, if\n  current directory is not root directory of drive.\n  But that behavior is not guarantied in specification docs.\n*/\n\nbool GetCurrentDir(FString &path)\n{\n  const unsigned kBufSize = MAX_PATH + 16;\n  path.Empty();\n\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    TCHAR s[kBufSize + 1];\n    s[0] = 0;\n    const DWORD len = ::GetCurrentDirectory(kBufSize, s);\n    if (len == 0 || len >= kBufSize)\n      return false;\n    s[kBufSize] = 0;  // optional guard\n    path = fas2fs(s);\n    return true;\n  }\n  else\n  #endif\n  {\n    DWORD len;\n    {\n      WCHAR s[kBufSize + 1];\n      s[0] = 0;\n      len = ::GetCurrentDirectoryW(kBufSize, s);\n      if (len == 0)\n        return false;\n      if (len < kBufSize)\n      {\n        s[kBufSize] = 0;  // optional guard\n        path = us2fs(s);\n        return true;\n      }\n    }\n    UString temp;\n    const DWORD len2 = ::GetCurrentDirectoryW(len, temp.GetBuf(len));\n    if (len2 == 0)\n      return false;\n    temp.ReleaseBuf_CalcLen(len);\n    if (temp.Len() != len2 || len - 1 != len2)\n    {\n      /* it's unexpected case, if current dir of process\n         was changed between two function calls,\n         or some unexpected function implementation */\n      // SetLastError((DWORD)E_FAIL);  // we can set some error code\n      return false;\n    }\n    path = us2fs(temp);\n    return true;\n  }\n}\n\n#endif // _WIN32\n#endif // UNDER_CE\n\n\nbool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName)\n{\n  bool res = MyGetFullPathName(path, resDirPrefix);\n  if (!res)\n    resDirPrefix = path;\n  int pos = resDirPrefix.ReverseFind_PathSepar();\n  pos++;\n  resFileName = resDirPrefix.Ptr((unsigned)pos);\n  resDirPrefix.DeleteFrom((unsigned)pos);\n  return res;\n}\n\nbool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix)\n{\n  FString resFileName;\n  return GetFullPathAndSplit(path, resDirPrefix, resFileName);\n}\n\n\n\nbool MyGetTempPath(FString &path)\n{\n  #ifdef _WIN32\n\n  /*\n  new DOCs for GetTempPathW():\n    - The returned string ends with a backslash.\n    - The maximum possible return value is MAX_PATH+1 (261).\n  */\n\n  const unsigned kBufSize = MAX_PATH + 16;\n  DWORD len;\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    TCHAR s[kBufSize + 1];\n    s[0] = 0;\n    len = ::GetTempPath(kBufSize, s);\n    path = fas2fs(s);\n  }\n  else\n  #endif\n  {\n    WCHAR s[kBufSize + 1];\n    s[0] = 0;\n    len = ::GetTempPathW(kBufSize, s);\n    path = us2fs(s);\n  }\n  /* win10: GetTempPathW() doesn't set backslash at the end of path,\n       if (buffer_size == len_of(path_with_backslash)).\n     So we normalize path here: */\n  NormalizeDirPathPrefix(path);\n  return (len != 0 && len < kBufSize);\n\n  #else  // !_WIN32\n  \n  // FIXME: improve that code\n  path = STRING_PATH_SEPARATOR \"tmp\";\n  const char *s;\n  if (NFind::DoesDirExist_FollowLink(path))\n    s = STRING_PATH_SEPARATOR \"tmp\" STRING_PATH_SEPARATOR;\n  else\n    s = \".\" STRING_PATH_SEPARATOR;\n  path = s;\n  return true;\n  \n  #endif\n}\n\n\nbool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile)\n{\n  UInt32 d =\n    #ifdef _WIN32\n      (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId();\n    #else\n      (UInt32)(time(NULL) << 12) ^  ((UInt32)getppid() << 14) ^ (UInt32)(getpid());\n    #endif\n\n  for (unsigned i = 0; i < 100; i++)\n  {\n    postfix.Empty();\n    if (addRandom)\n    {\n      char s[16];\n      UInt32 val = d;\n      unsigned k;\n      for (k = 0; k < 8; k++)\n      {\n        const unsigned t = (unsigned)val & 0xF;\n        val >>= 4;\n        s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));\n      }\n      s[k] = '\\0';\n      if (outFile)\n        postfix.Add_Dot();\n      postfix += s;\n      UInt32 step = GetTickCount() + 2;\n      if (step == 0)\n        step = 1;\n      d += step;\n    }\n    addRandom = true;\n    if (outFile)\n      postfix += \".tmp\";\n    FString path (prefix);\n    path += postfix;\n    if (NFind::DoesFileOrDirExist(path))\n    {\n      SetLastError(ERROR_ALREADY_EXISTS);\n      continue;\n    }\n    if (outFile)\n    {\n      if (outFile->Create_NEW(path))\n        return true;\n    }\n    else\n    {\n      if (CreateDir(path))\n        return true;\n    }\n    const DWORD error = GetLastError();\n    if (error != ERROR_FILE_EXISTS &&\n        error != ERROR_ALREADY_EXISTS)\n      break;\n  }\n  postfix.Empty();\n  return false;\n}\n\nbool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile)\n{\n  if (!Remove())\n    return false;\n  _path.Empty();\n  AString postfix;\n  if (!CreateTempFile2(prefix, false, postfix, outFile))\n    return false;\n  _path = prefix;\n  _path += postfix;\n  _mustBeDeleted = true;\n  return true;\n}\n\nbool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile)\n{\n  if (!Remove())\n    return false;\n  _path.Empty();\n  FString tempPath;\n  if (!MyGetTempPath(tempPath))\n    return false;\n  AString postfix;\n  tempPath += namePrefix;\n  if (!CreateTempFile2(tempPath, true, postfix, outFile))\n    return false;\n  _path = tempPath;\n  _path += postfix;\n  _mustBeDeleted = true;\n  return true;\n}\n\nbool CTempFile::Remove()\n{\n  if (!_mustBeDeleted)\n    return true;\n  _mustBeDeleted = !DeleteFileAlways(_path);\n  return !_mustBeDeleted;\n}\n\nbool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore,\n    ICopyFileProgress *progress)\n{\n  if (deleteDestBefore)\n  {\n    if (NFind::DoesFileExist_Raw(name))\n    {\n      // attrib = NFind::GetFileAttrib(name);\n      if (!DeleteFileAlways(name))\n        return false;\n    }\n  }\n  DisableDeleting();\n  // if (!progress) return MyMoveFile(_path, name);\n  return MyMoveFile_with_Progress(_path, name, progress);\n  /*\n  if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY))\n  {\n    DWORD attrib2 = NFind::GetFileAttrib(name);\n    if (attrib2 != INVALID_FILE_ATTRIBUTES)\n      SetFileAttrib(name, attrib2 | FILE_ATTRIBUTE_READONLY);\n  }\n  */\n}\n\n#ifdef _WIN32\nbool CTempDir::Create(CFSTR prefix)\n{\n  if (!Remove())\n    return false;\n  _path.Empty();\n  FString tempPath;\n  if (!MyGetTempPath(tempPath))\n    return false;\n  tempPath += prefix;\n  AString postfix;\n  if (!CreateTempFile2(tempPath, true, postfix, NULL))\n    return false;\n  _path = tempPath;\n  _path += postfix;\n  _mustBeDeleted = true;\n  return true;\n}\n\nbool CTempDir::Remove()\n{\n  if (!_mustBeDeleted)\n    return true;\n  _mustBeDeleted = !RemoveDirWithSubItems(_path);\n  return !_mustBeDeleted;\n}\n#endif\n\n\n\n#ifndef _WIN32\n\nbool RemoveDir(CFSTR path)\n{\n  return (rmdir(path) == 0);\n}\n\n\nstatic BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progress)\n{\n  {\n    NIO::COutFile outFile;\n    if (!outFile.Create_NEW(newFile))\n      return FALSE;\n    NIO::CInFile inFile;\n    if (!inFile.Open(oldFile))\n      return FALSE;\n    \n    const size_t k_BufSize = 1 << 16;\n    CAlignedBuffer1 buf(k_BufSize);\n    \n    UInt64 length = 0;\n    if (progress && !inFile.GetLength(length))\n      length = 0;\n    UInt64 prev = 0;\n    UInt64 cur = 0;\n    for (;;)\n    {\n      const ssize_t num = inFile.read_part(buf, k_BufSize);\n      if (num == 0)\n        return TRUE;\n      if (num < 0)\n        break;\n      size_t processed;\n      const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed);\n      if (num2 != num || processed != (size_t)num)\n        break;\n      cur += (size_t)num2;\n      if (progress && cur - prev >= (1u << 20))\n      {\n        prev = cur;\n        if (progress->CopyFileProgress(length, cur) != PROGRESS_CONTINUE)\n        {\n          errno = EINTR; // instead of WIN32::ERROR_REQUEST_ABORTED\n          break;\n        }\n      }\n    }\n  }\n  // There is file IO error or process was interrupted by user.\n  // We close output file and delete it.\n  // DeleteFileAlways doesn't change errno (if successed), but we restore errno.\n  const int errno_save = errno;\n  DeleteFileAlways(newFile);\n  errno = errno_save;\n  return FALSE;\n}\n\n\nbool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,\n    ICopyFileProgress *progress)\n{\n  int res = rename(oldFile, newFile);\n  if (res == 0)\n    return true;\n  if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem)\n    return false;\n\n  if (My_CopyFile(oldFile, newFile, progress) == FALSE)\n    return false;\n    \n  struct stat info_file;\n  res = stat(oldFile, &info_file);\n  if (res != 0)\n    return false;\n\n  /*\n  ret = chmod(dst,info_file.st_mode & g_umask.mask);\n  */\n  return (unlink(oldFile) == 0);\n}\n\nbool MyMoveFile(CFSTR oldFile, CFSTR newFile)\n{\n  return MyMoveFile_with_Progress(oldFile, newFile, NULL);\n}\n\n\nbool CreateDir(CFSTR path)\n{\n  return (mkdir(path, 0777) == 0); // change it\n}\n\nstatic bool CreateDir2(CFSTR path)\n{\n  return (mkdir(path, 0777) == 0); // change it\n}\n\n\nbool DeleteFileAlways(CFSTR path)\n{\n  return (remove(path) == 0);\n}\n\nbool SetCurrentDir(CFSTR path)\n{\n  return (chdir(path) == 0);\n}\n\n\nbool GetCurrentDir(FString &path)\n{\n  path.Empty();\n\n  #define MY_PATH_MAX  PATH_MAX\n  // #define MY_PATH_MAX  1024\n\n  char s[MY_PATH_MAX + 1];\n  char *res = getcwd(s, MY_PATH_MAX);\n  if (res)\n  {\n    path = fas2fs(s);\n    return true;\n  }\n  {\n    // if (errno != ERANGE) return false;\n    #if defined(__GLIBC__) || defined(__APPLE__)\n    /* As an extension to the POSIX.1-2001 standard, glibc's getcwd()\n       allocates the buffer dynamically using malloc(3) if buf is NULL. */\n    res = getcwd(NULL, 0);\n    if (res)\n    {\n      path = fas2fs(res);\n      ::free(res);\n      return true;\n    }\n    #endif\n    return false;\n  }\n}\n\n\n\n// #undef UTIME_OMIT // to debug\n\n#ifndef UTIME_OMIT\n  /* we can define UTIME_OMIT for debian and another systems.\n     Is it OK to define UTIME_OMIT to -2 here, if UTIME_OMIT is not defined? */\n  // #define UTIME_OMIT -2\n#endif\n\n\n\n\n\nstatic bool SetFileTime_Base(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime, const int flags)\n{\n  // need testing\n  /*\n  struct utimbuf buf;\n  struct stat st;\n  UNUSED_VAR(cTime)\n  printf(\"\\nstat = %s\\n\", path);\n  int ret = stat(path, &st);\n  if (ret == 0)\n  {\n    buf.actime  = st.st_atime;\n    buf.modtime = st.st_mtime;\n  }\n  else\n  {\n    time_t cur_time = time(0);\n    buf.actime  = cur_time;\n    buf.modtime = cur_time;\n  }\n  if (aTime)\n  {\n    UInt32 ut;\n    if (NTime::FileTimeToUnixTime(*aTime, ut))\n      buf.actime = ut;\n  }\n  if (mTime)\n  {\n    UInt32 ut;\n    if (NTime::FileTimeToUnixTime(*mTime, ut))\n      buf.modtime = ut;\n  }\n  return utime(path, &buf) == 0;\n  */\n\n  // if (!aTime && !mTime) return true;\n  struct timespec times[2];\n  UNUSED_VAR(cTime)\n  bool needChange;\n  needChange  = FiTime_To_timespec(aTime, times[0]);\n  needChange |= FiTime_To_timespec(mTime, times[1]);\n  // if (mTime) { printf(\"\\n time = %ld.%9ld\\n\", mTime->tv_sec, mTime->tv_nsec);  }\n  if (!needChange)\n    return true;\n  return utimensat(AT_FDCWD, path, times, flags) == 0;\n}\n\nbool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)\n{\n  return SetFileTime_Base(path, cTime, aTime, mTime, 0); // (flags = 0) means follow_link\n}\n\nbool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)\n{\n  return SetFileTime_Base(path, cTime, aTime, mTime, AT_SYMLINK_NOFOLLOW);\n}\n\n\nstruct C_umask\n{\n  mode_t mask;\n\n  C_umask()\n  {\n    /* by security reasons we restrict attributes according\n       with process's file mode creation mask (umask) */\n    const mode_t um = umask(0); // octal :0022 is expected\n    mask = 0777 & (~um);        // octal: 0755 is expected\n    umask(um);  // restore the umask\n    // printf(\"\\n umask = 0%03o mask = 0%03o\\n\", um, mask);\n    \n    // mask = 0777; // debug we can disable the restriction:\n  }\n};\n\nstatic C_umask g_umask;\n\n// #define PRF(x) x;\n#define PRF(x)\n\n#define TRACE_SetFileAttrib(msg) \\\n  PRF(printf(\"\\nSetFileAttrib(%s, %x) : %s\\n\", (const char *)path, attrib, msg);)\n\n#define TRACE_chmod(s, mode) \\\n  PRF(printf(\"\\n chmod(%s, %o)\\n\", (const char *)path, (unsigned)(mode));)\n\nint my_chown(CFSTR path, uid_t owner, gid_t group)\n{\n  return chown(path, owner, group);\n}\n\nbool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)\n{\n  TRACE_SetFileAttrib(\"\")\n\n  struct stat st;\n\n  bool use_lstat = true;\n  if (use_lstat)\n  {\n    if (lstat(path, &st) != 0)\n    {\n      TRACE_SetFileAttrib(\"bad lstat()\")\n      return false;\n    }\n    // TRACE_chmod(\"lstat\", st.st_mode);\n  }\n  else\n  {\n    if (stat(path, &st) != 0)\n    {\n      TRACE_SetFileAttrib(\"bad stat()\")\n      return false;\n    }\n  }\n  \n  if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)\n  {\n    TRACE_SetFileAttrib(\"attrib & FILE_ATTRIBUTE_UNIX_EXTENSION\")\n    st.st_mode = attrib >> 16;\n    if (S_ISDIR(st.st_mode))\n    {\n      // user/7z must be able to create files in this directory\n      st.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR);\n    }\n    else if (!S_ISREG(st.st_mode))\n      return true;\n  }\n  else if (S_ISLNK(st.st_mode))\n  {\n    /* for most systems: permissions for symlinks are fixed to rwxrwxrwx.\n       so we don't need chmod() for symlinks. */\n    return true;\n    // SetLastError(ENOSYS);\n    // return false;\n  }\n  else\n  {\n    TRACE_SetFileAttrib(\"Only Windows Attributes\")\n    // Only Windows Attributes\n    if (S_ISDIR(st.st_mode)\n        || (attrib & FILE_ATTRIBUTE_READONLY) == 0)\n      return true;\n    st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions\n  }\n\n  int res;\n  /*\n  if (S_ISLNK(st.st_mode))\n  {\n    printf(\"\\nfchmodat()\\n\");\n    TRACE_chmod(path, (st.st_mode) & g_umask.mask)\n    // AT_SYMLINK_NOFOLLOW is not implemted still in Linux.\n    res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask,\n        S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0);\n  }\n  else\n  */\n  {\n    TRACE_chmod(path, (st.st_mode) & g_umask.mask)\n    res = chmod(path, (st.st_mode) & g_umask.mask);\n  }\n  // TRACE_SetFileAttrib(\"End\")\n  return (res == 0);\n}\n\n\nbool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)\n{\n  PRF(printf(\"\\nhard link() %s -> %s\\n\", newFileName, existFileName);)\n  return (link(existFileName, newFileName) == 0);\n}\n\n#endif // !_WIN32\n\n// #endif\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileDir.h",
    "content": "﻿// Windows/FileDir.h\n\n#ifndef ZIP7_INC_WINDOWS_FILE_DIR_H\n#define ZIP7_INC_WINDOWS_FILE_DIR_H\n\n#include \"../Common/MyString.h\"\n\n#include \"FileIO.h\"\n\nnamespace NWindows {\nnamespace NFile {\nnamespace NDir {\n\nbool GetWindowsDir(FString &path);\nbool GetSystemDir(FString &path);\n\n/*\nWIN32 API : SetFileTime() doesn't allow to set zero timestamps in file\nbut linux : allows unix time = 0 in filesystem\n*/\n/*\nSetDirTime() can be used to set time for file or for dir.\nIf path is symbolic link, SetDirTime() will follow symbolic link,\nand it will set timestamps of symbolic link's target file or dir.\n*/\nbool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);\n\n/*\nSetLinkFileTime() doesn't follow symbolic link,\nand it sets timestamps for symbolic link file itself.\nIf (path) is not symbolic link, it still can work (at least in some new OS versions).\n*/\nbool SetLinkFileTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);\n\n\n#ifdef _WIN32\n\nbool SetFileAttrib(CFSTR path, DWORD attrib);\n\n/*\n  Some programs store posix attributes in high 16 bits of windows attributes field.\n  Also some programs use additional flag markers: 0x8000 or 0x4000.\n  SetFileAttrib_PosixHighDetect() tries to detect posix field, and it extracts only attribute\n  bits that are related to current system only.\n*/\n#else\n\nint my_chown(CFSTR path, uid_t owner, gid_t group);\n\n#endif\n\nbool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib);\n\n\n#ifndef _WIN32\n#define PROGRESS_CONTINUE   0\n#define PROGRESS_CANCEL     1\n// #define PROGRESS_STOP       2\n// #define PROGRESS_QUIET      3\n#endif\nZ7_PURE_INTERFACES_BEGIN\nDECLARE_INTERFACE(ICopyFileProgress)\n{\n  // in: total, current: include all/processed alt streams.\n  // it returns PROGRESS_CONTINUE or PROGRESS_CANCEL.\n  virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) = 0;\n};\nZ7_PURE_INTERFACES_END\n\nbool MyMoveFile(CFSTR existFileName, CFSTR newFileName);\n// (progress == NULL) is allowed\nbool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile,\n    ICopyFileProgress *progress);\n\n\n#ifndef UNDER_CE\nbool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName);\n#endif\n\nbool RemoveDir(CFSTR path);\nbool CreateDir(CFSTR path);\n\n/* CreateComplexDir returns true, if directory can contain files after the call (two cases):\n    1) the directory already exists (network shares and drive paths are supported)\n    2) the directory was created\n  path can be WITH or WITHOUT trailing path separator. */\n\nbool CreateComplexDir(CFSTR path);\n\nbool DeleteFileAlways(CFSTR name);\nbool RemoveDirWithSubItems(const FString &path);\n#ifdef _WIN32\nbool RemoveDirAlways_if_Empty(const FString &path);\n#else\n#define RemoveDirAlways_if_Empty RemoveDir\n#endif\n\nbool MyGetFullPathName(CFSTR path, FString &resFullPath);\nbool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName);\nbool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix);\n\n#ifndef UNDER_CE\n\nbool SetCurrentDir(CFSTR path);\nbool GetCurrentDir(FString &resultPath);\n\n#endif\n\nbool MyGetTempPath(FString &resultPath);\n\nbool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile);\n\nclass CTempFile  MY_UNCOPYABLE\n{\n  bool _mustBeDeleted;\n  FString _path;\n  void DisableDeleting() { _mustBeDeleted = false; }\npublic:\n  CTempFile(): _mustBeDeleted(false) {}\n  ~CTempFile() { Remove(); }\n  const FString &GetPath() const { return _path; }\n  bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix\n  bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile);\n  bool Remove();\n  // bool MoveTo(CFSTR name, bool deleteDestBefore);\n  bool MoveTo(CFSTR name, bool deleteDestBefore,\n      ICopyFileProgress *progress);\n};\n\n\n#ifdef _WIN32\nclass CTempDir  MY_UNCOPYABLE\n{\n  bool _mustBeDeleted;\n  FString _path;\npublic:\n  CTempDir(): _mustBeDeleted(false) {}\n  ~CTempDir() { Remove();  }\n  const FString &GetPath() const { return _path; }\n  void DisableDeleting() { _mustBeDeleted = false; }\n  bool Create(CFSTR namePrefix) ;\n  bool Remove();\n};\n#endif\n\n\n#if !defined(UNDER_CE)\nclass CCurrentDirRestorer  MY_UNCOPYABLE\n{\n  FString _path;\npublic:\n  bool NeedRestore;\n\n  CCurrentDirRestorer(): NeedRestore(true)\n  {\n    GetCurrentDir(_path);\n  }\n  ~CCurrentDirRestorer()\n  {\n    if (!NeedRestore)\n      return;\n    FString s;\n    if (GetCurrentDir(s))\n      if (s != _path)\n        SetCurrentDir(_path);\n  }\n};\n#endif\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileFind.cpp",
    "content": "﻿// Windows/FileFind.cpp\n\n#include \"StdAfx.h\"\n\n// #include <stdio.h>\n\n#ifndef _WIN32\n#include <fcntl.h>           /* Definition of AT_* constants */\n#include \"TimeUtils.h\"\n// for major\n// #include <sys/sysmacros.h>\n#endif\n\n#include \"FileFind.h\"\n#include \"FileIO.h\"\n#include \"FileName.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NName;\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n\n#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0502  // Win2003\n#define Z7_USE_DYN_FindFirstStream\n#endif\n\n#ifdef Z7_USE_DYN_FindFirstStream\n\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\nEXTERN_C_BEGIN\n\ntypedef enum\n{\n  My_FindStreamInfoStandard,\n  My_FindStreamInfoMaxInfoLevel\n} MY_STREAM_INFO_LEVELS;\n\ntypedef struct\n{\n  LARGE_INTEGER StreamSize;\n  WCHAR cStreamName[MAX_PATH + 36];\n} MY_WIN32_FIND_STREAM_DATA, *MY_PWIN32_FIND_STREAM_DATA;\n\ntypedef HANDLE (WINAPI *Func_FindFirstStreamW)(LPCWSTR fileName, MY_STREAM_INFO_LEVELS infoLevel,\n    LPVOID findStreamData, DWORD flags);\n\ntypedef BOOL (APIENTRY *Func_FindNextStreamW)(HANDLE findStream, LPVOID findStreamData);\n\nEXTERN_C_END\n\n#else\n\n#define MY_WIN32_FIND_STREAM_DATA  WIN32_FIND_STREAM_DATA\n#define My_FindStreamInfoStandard  FindStreamInfoStandard\n\n#endif\n#endif // defined(_WIN32) && !defined(UNDER_CE)\n\n\nnamespace NWindows {\nnamespace NFile {\n\n\n#ifdef _WIN32\n#ifdef Z7_DEVICE_FILE\nnamespace NSystem\n{\nbool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);\n}\n#endif\n#endif\n\nnamespace NFind {\n\n/*\n#ifdef _WIN32\n#define MY_CLEAR_FILETIME(ft) ft.dwLowDateTime = ft.dwHighDateTime = 0;\n#else\n#define MY_CLEAR_FILETIME(ft) ft.tv_sec = 0;  ft.tv_nsec = 0;\n#endif\n*/\n\nvoid CFileInfoBase::ClearBase() throw()\n{\n  Size = 0;\n  FiTime_Clear(CTime);\n  FiTime_Clear(ATime);\n  FiTime_Clear(MTime);\n \n #ifdef _WIN32\n  Attrib = 0;\n  // ReparseTag = 0;\n  IsAltStream = false;\n  IsDevice = false;\n #else\n  dev = 0;\n  ino = 0;\n  mode = 0;\n  nlink = 0;\n  uid = 0;\n  gid = 0;\n  rdev = 0;\n #endif\n}\n\n\nbool CFileInfoBase::SetAs_StdInFile()\n{\n  ClearBase();\n  Size = (UInt64)(Int64)-1;\n  NTime::GetCurUtc_FiTime(MTime);\n  CTime = ATime = MTime;\n\n#ifdef _WIN32\n\n  /* in GUI mode : GetStdHandle(STD_INPUT_HANDLE) returns NULL,\n     and it doesn't set LastError.  */\n#if 1\n  SetLastError(0);\n  const HANDLE h = GetStdHandle(STD_INPUT_HANDLE);\n  if (!h || h == INVALID_HANDLE_VALUE)\n  {\n    if (GetLastError() == 0)\n      SetLastError(ERROR_INVALID_HANDLE);\n    return false;\n  }\n  BY_HANDLE_FILE_INFORMATION info;\n  if (GetFileInformationByHandle(h, &info)\n      && info.dwVolumeSerialNumber)\n  {\n    Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;\n    // FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;\n    // NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;\n    Attrib = info.dwFileAttributes;\n    CTime = info.ftCreationTime;\n    ATime = info.ftLastAccessTime;\n    MTime = info.ftLastWriteTime;\n  }\n#if 0\n  printf(\n    \"\\ndwFileAttributes = %8x\"\n    \"\\nftCreationTime   = %8x\"\n    \"\\nftLastAccessTime = %8x\"\n    \"\\nftLastWriteTime  = %8x\"\n    \"\\ndwVolumeSerialNumber  = %8x\"\n    \"\\nnFileSizeHigh  = %8x\"\n    \"\\nnFileSizeLow   = %8x\"\n    \"\\nnNumberOfLinks  = %8x\"\n    \"\\nnFileIndexHigh  = %8x\"\n    \"\\nnFileIndexLow   = %8x \\n\",\n      (unsigned)info.dwFileAttributes,\n      (unsigned)info.ftCreationTime.dwHighDateTime,\n      (unsigned)info.ftLastAccessTime.dwHighDateTime,\n      (unsigned)info.ftLastWriteTime.dwHighDateTime,\n      (unsigned)info.dwVolumeSerialNumber,\n      (unsigned)info.nFileSizeHigh,\n      (unsigned)info.nFileSizeLow,\n      (unsigned)info.nNumberOfLinks,\n      (unsigned)info.nFileIndexHigh,\n      (unsigned)info.nFileIndexLow);\n#endif\n#endif\n\n#else // non-Wiondow\n\n  mode = S_IFIFO | 0777; // 0755 : 0775 : 0664 : 0644 :\n#if 1\n  struct stat st;\n  if (fstat(0, &st) == 0)\n  {\n    SetFrom_stat(st);\n    if (!S_ISREG(st.st_mode)\n        // S_ISFIFO(st->st_mode)\n        || st.st_size == 0)\n    {\n      Size = (UInt64)(Int64)-1;\n      // mode = S_IFIFO | 0777;\n    }\n  }\n#endif\n#endif\n\n  return true;\n}\n\nbool CFileInfo::IsDots() const throw()\n{\n  if (!IsDir() || Name.IsEmpty())\n    return false;\n  if (Name[0] != '.')\n    return false;\n  return Name.Len() == 1 || (Name.Len() == 2 && Name[1] == '.');\n}\n\n\n#ifdef _WIN32\n\n\n#define WIN_FD_TO_MY_FI(fi, fd) \\\n  fi.Attrib = fd.dwFileAttributes; \\\n  fi.CTime = fd.ftCreationTime; \\\n  fi.ATime = fd.ftLastAccessTime; \\\n  fi.MTime = fd.ftLastWriteTime; \\\n  fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow; \\\n  /* fi.ReparseTag = fd.dwReserved0; */ \\\n  fi.IsAltStream = false; \\\n  fi.IsDevice = false;\n\n  /*\n  #ifdef UNDER_CE\n  fi.ObjectID = fd.dwOID;\n  #else\n  fi.ReparseTag = fd.dwReserved0;\n  #endif\n  */\n\nstatic void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfo &fi)\n{\n  WIN_FD_TO_MY_FI(fi, fd)\n  fi.Name = us2fs(fd.cFileName);\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  // fi.ShortName = us2fs(fd.cAlternateFileName);\n  #endif\n}\n\n#ifndef _UNICODE\nstatic void Convert_WIN32_FIND_DATA_to_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)\n{\n  WIN_FD_TO_MY_FI(fi, fd)\n  fi.Name = fas2fs(fd.cFileName);\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  // fi.ShortName = fas2fs(fd.cAlternateFileName);\n  #endif\n}\n#endif\n  \n////////////////////////////////\n// CFindFile\n\nbool CFindFileBase::Close() throw()\n{\n  if (_handle == INVALID_HANDLE_VALUE)\n    return true;\n  if (!::FindClose(_handle))\n    return false;\n  _handle = INVALID_HANDLE_VALUE;\n  return true;\n}\n\n/*\nWinXP-64 FindFirstFile():\n  \"\"      -  ERROR_PATH_NOT_FOUND\n  folder\\ -  ERROR_FILE_NOT_FOUND\n  \\       -  ERROR_FILE_NOT_FOUND\n  c:\\     -  ERROR_FILE_NOT_FOUND\n  c:      -  ERROR_FILE_NOT_FOUND, if current dir is ROOT     ( c:\\ )\n  c:      -  OK,                   if current dir is NOT ROOT ( c:\\folder )\n  folder  -  OK\n\n  \\\\               - ERROR_INVALID_NAME\n  \\\\Server         - ERROR_INVALID_NAME\n  \\\\Server\\        - ERROR_INVALID_NAME\n      \n  \\\\Server\\Share            - ERROR_BAD_NETPATH\n  \\\\Server\\Share            - ERROR_BAD_NET_NAME (Win7).\n             !!! There is problem : Win7 makes some requests for \"\\\\Server\\Shar\" (look in Procmon),\n                 when we call it for \"\\\\Server\\Share\"\n                      \n  \\\\Server\\Share\\           - ERROR_FILE_NOT_FOUND\n  \n  \\\\?\\UNC\\Server\\Share      - ERROR_INVALID_NAME\n  \\\\?\\UNC\\Server\\Share      - ERROR_BAD_PATHNAME (Win7)\n  \\\\?\\UNC\\Server\\Share\\     - ERROR_FILE_NOT_FOUND\n  \n  \\\\Server\\Share_RootDrive  - ERROR_INVALID_NAME\n  \\\\Server\\Share_RootDrive\\ - ERROR_INVALID_NAME\n  \n  e:\\* - ERROR_FILE_NOT_FOUND, if there are no items in that root folder\n  w:\\* - ERROR_PATH_NOT_FOUND, if there is no such drive w:\n*/\n\nbool CFindFile::FindFirst(CFSTR path, CFileInfo &fi)\n{\n  if (!Close())\n    return false;\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    WIN32_FIND_DATAA fd;\n    _handle = ::FindFirstFileA(fs2fas(path), &fd);\n    if (_handle == INVALID_HANDLE_VALUE)\n      return false;\n    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);\n  }\n  else\n  #endif\n  {\n    WIN32_FIND_DATAW fd;\n\n    IF_USE_MAIN_PATH\n      _handle = ::FindFirstFileW(fs2us(path), &fd);\n    #ifdef Z7_LONG_PATH\n    if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        _handle = ::FindFirstFileW(superPath, &fd);\n    }\n    #endif\n    if (_handle == INVALID_HANDLE_VALUE)\n      return false;\n    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);\n  }\n  return true;\n}\n\nbool CFindFile::FindNext(CFileInfo &fi)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    WIN32_FIND_DATAA fd;\n    if (!::FindNextFileA(_handle, &fd))\n      return false;\n    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);\n  }\n  else\n  #endif\n  {\n    WIN32_FIND_DATAW fd;\n    if (!::FindNextFileW(_handle, &fd))\n      return false;\n    Convert_WIN32_FIND_DATA_to_FileInfo(fd, fi);\n  }\n  return true;\n}\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n\n////////////////////////////////\n// AltStreams\n\n#ifdef Z7_USE_DYN_FindFirstStream\nstatic Func_FindFirstStreamW g_FindFirstStreamW;\nstatic Func_FindNextStreamW  g_FindNextStreamW;\n#define MY_FindFirstStreamW  g_FindFirstStreamW\n#define MY_FindNextStreamW   g_FindNextStreamW\nstatic struct CFindStreamLoader\n{\n  CFindStreamLoader()\n  {\n    const HMODULE hm = ::GetModuleHandleA(\"kernel32.dll\");\n       g_FindFirstStreamW = Z7_GET_PROC_ADDRESS(\n    Func_FindFirstStreamW, hm,\n        \"FindFirstStreamW\");\n       g_FindNextStreamW = Z7_GET_PROC_ADDRESS(\n    Func_FindNextStreamW, hm,\n        \"FindNextStreamW\");\n  }\n} g_FindStreamLoader;\n#else\n#define MY_FindFirstStreamW  FindFirstStreamW\n#define MY_FindNextStreamW   FindNextStreamW\n#endif\n\n\nbool CStreamInfo::IsMainStream() const throw()\n{\n  return StringsAreEqualNoCase_Ascii(Name, \"::$DATA\");\n}\n\nUString CStreamInfo::GetReducedName() const\n{\n  // remove \":$DATA\" postfix, but keep postfix, if Name is \"::$DATA\"\n  UString s (Name);\n  if (s.Len() > 6 + 1 && StringsAreEqualNoCase_Ascii(s.RightPtr(6), \":$DATA\"))\n    s.DeleteFrom(s.Len() - 6);\n  return s;\n}\n\n/*\nUString CStreamInfo::GetReducedName2() const\n{\n  UString s = GetReducedName();\n  if (!s.IsEmpty() && s[0] == ':')\n    s.Delete(0);\n  return s;\n}\n*/\n\nstatic void Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(const MY_WIN32_FIND_STREAM_DATA &sd, CStreamInfo &si)\n{\n  si.Size = (UInt64)sd.StreamSize.QuadPart;\n  si.Name = sd.cStreamName;\n}\n\n/*\n  WinXP-64 FindFirstStream():\n  \"\"      -  ERROR_PATH_NOT_FOUND\n  folder\\ -  OK\n  folder  -  OK\n  \\       -  OK\n  c:\\     -  OK\n  c:      -  OK, if current dir is ROOT     ( c:\\ )\n  c:      -  OK, if current dir is NOT ROOT ( c:\\folder )\n  \\\\Server\\Share   - OK\n  \\\\Server\\Share\\  - OK\n\n  \\\\               - ERROR_INVALID_NAME\n  \\\\Server         - ERROR_INVALID_NAME\n  \\\\Server\\        - ERROR_INVALID_NAME\n*/\n\nbool CFindStream::FindFirst(CFSTR path, CStreamInfo &si)\n{\n  if (!Close())\n    return false;\n#ifdef Z7_USE_DYN_FindFirstStream\n  if (!g_FindFirstStreamW)\n  {\n    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\n    return false;\n  }\n#endif\n  {\n    MY_WIN32_FIND_STREAM_DATA sd;\n    SetLastError(0);\n    IF_USE_MAIN_PATH\n      _handle = MY_FindFirstStreamW(fs2us(path), My_FindStreamInfoStandard, &sd, 0);\n    if (_handle == INVALID_HANDLE_VALUE)\n    {\n      if (::GetLastError() == ERROR_HANDLE_EOF)\n        return false;\n      // long name can be tricky for path like \".\\dirName\".\n      #ifdef Z7_LONG_PATH\n      if (USE_SUPER_PATH)\n      {\n        UString superPath;\n        if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n          _handle = MY_FindFirstStreamW(superPath, My_FindStreamInfoStandard, &sd, 0);\n      }\n      #endif\n    }\n    if (_handle == INVALID_HANDLE_VALUE)\n      return false;\n    Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);\n  }\n  return true;\n}\n\nbool CFindStream::FindNext(CStreamInfo &si)\n{\n#ifdef Z7_USE_DYN_FindFirstStream\n  if (!g_FindNextStreamW)\n  {\n    ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\n    return false;\n  }\n#endif\n  {\n    MY_WIN32_FIND_STREAM_DATA sd;\n    if (!MY_FindNextStreamW(_handle, &sd))\n      return false;\n    Convert_WIN32_FIND_STREAM_DATA_to_StreamInfo(sd, si);\n  }\n  return true;\n}\n\nbool CStreamEnumerator::Next(CStreamInfo &si, bool &found)\n{\n  bool res;\n  if (_find.IsHandleAllocated())\n    res = _find.FindNext(si);\n  else\n    res = _find.FindFirst(_filePath, si);\n  if (res)\n  {\n    found = true;\n    return true;\n  }\n  found = false;\n  return (::GetLastError() == ERROR_HANDLE_EOF);\n}\n\n#endif\n\n\n/*\nWinXP-64 GetFileAttributes():\n  If the function fails, it returns INVALID_FILE_ATTRIBUTES and use GetLastError() to get error code\n\n  \\    - OK\n  C:\\  - OK, if there is such drive,\n  D:\\  - ERROR_PATH_NOT_FOUND, if there is no such drive,\n\n  C:\\folder     - OK\n  C:\\folder\\    - OK\n  C:\\folderBad  - ERROR_FILE_NOT_FOUND\n\n  \\\\Server\\BadShare  - ERROR_BAD_NETPATH\n  \\\\Server\\Share     - WORKS OK, but MSDN says:\n                          GetFileAttributes for a network share, the function fails, and GetLastError\n                          returns ERROR_BAD_NETPATH. You must specify a path to a subfolder on that share.\n*/\n\nDWORD GetFileAttrib(CFSTR path)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n    return ::GetFileAttributes(fs2fas(path));\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH\n    {\n      DWORD dw = ::GetFileAttributesW(fs2us(path));\n      if (dw != INVALID_FILE_ATTRIBUTES)\n        return dw;\n    }\n    #ifdef Z7_LONG_PATH\n    if (USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        return ::GetFileAttributesW(superPath);\n    }\n    #endif\n    return INVALID_FILE_ATTRIBUTES;\n  }\n}\n\n/* if path is \"c:\" or \"c::\" then CFileInfo::Find() returns name of current folder for that disk\n   so instead of absolute path we have relative path in Name. That is not good in some calls */\n\n/* In CFileInfo::Find() we want to support same names for alt streams as in CreateFile(). */\n\n/* CFileInfo::Find()\nWe alow the following paths (as FindFirstFile):\n  C:\\folder\n  c:                      - if current dir is NOT ROOT ( c:\\folder )\n\nalso we support paths that are not supported by FindFirstFile:\n  \\\n  \\\\.\\c:\n  c:\\                     - Name will be without tail slash ( c: )\n  \\\\?\\c:\\                 - Name will be without tail slash ( c: )\n  \\\\Server\\Share\n  \\\\?\\UNC\\Server\\Share\n\n  c:\\folder:stream  - Name = folder:stream\n  c:\\:stream        - Name = :stream\n  c::stream         - Name = c::stream\n*/\n\nbool CFileInfo::Find(CFSTR path, bool followLink)\n{\n  #ifdef Z7_DEVICE_FILE\n  \n  if (IS_PATH_SEPAR(path[0]) &&\n      IS_PATH_SEPAR(path[1]) &&\n      path[2] == '.' &&\n      path[3] == 0)\n  {\n    // 22.00 : it's virtual directory for devices\n    // IsDevice = true;\n    ClearBase();\n    Name = path + 2;\n    Attrib = FILE_ATTRIBUTE_DIRECTORY;\n    return true;\n  }\n  \n  if (IsDevicePath(path))\n  {\n    ClearBase();\n    Name = path + 4;\n    IsDevice = true;\n    \n    if (NName::IsDrivePath2(path + 4) && path[6] == 0)\n    {\n      FChar drive[4] = { path[4], ':', '\\\\', 0 };\n      UInt64 clusterSize, totalSize, freeSize;\n      if (NSystem::MyGetDiskFreeSpace(drive, clusterSize, totalSize, freeSize))\n      {\n        Size = totalSize;\n        return true;\n      }\n    }\n\n    NIO::CInFile inFile;\n    // ::OutputDebugStringW(path);\n    if (!inFile.Open(path))\n      return false;\n    // ::OutputDebugStringW(L\"---\");\n    if (inFile.SizeDefined)\n      Size = inFile.Size;\n    return true;\n  }\n  #endif\n\n  #if defined(_WIN32) && !defined(UNDER_CE)\n\n  const int colonPos = FindAltStreamColon(path);\n  if (colonPos >= 0 && path[(unsigned)colonPos + 1] != 0)\n  {\n    UString streamName = fs2us(path + (unsigned)colonPos);\n    FString filePath (path);\n    filePath.DeleteFrom((unsigned)colonPos);\n    /* we allow both cases:\n      name:stream\n      name:stream:$DATA\n    */\n    const unsigned kPostfixSize = 6;\n    if (streamName.Len() <= kPostfixSize\n        || !StringsAreEqualNoCase_Ascii(streamName.RightPtr(kPostfixSize), \":$DATA\"))\n      streamName += \":$DATA\";\n\n    bool isOk = true;\n    \n    if (IsDrivePath2(filePath) &&\n        (colonPos == 2 || (colonPos == 3 && filePath[2] == '\\\\')))\n    {\n      // FindFirstFile doesn't work for \"c:\\\" and for \"c:\" (if current dir is ROOT)\n      ClearBase();\n      Name.Empty();\n      if (colonPos == 2)\n        Name = filePath;\n    }\n    else\n      isOk = Find(filePath, followLink); // check it (followLink)\n\n    if (isOk)\n    {\n      Attrib &= ~(DWORD)(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);\n      Size = 0;\n      CStreamEnumerator enumerator(filePath);\n      for (;;)\n      {\n        CStreamInfo si;\n        bool found;\n        if (!enumerator.Next(si, found))\n          return false;\n        if (!found)\n        {\n          ::SetLastError(ERROR_FILE_NOT_FOUND);\n          return false;\n        }\n        if (si.Name.IsEqualTo_NoCase(streamName))\n        {\n          // we delete postfix, if alt stream name is not \"::$DATA\"\n          if (si.Name.Len() > kPostfixSize + 1)\n            si.Name.DeleteFrom(si.Name.Len() - kPostfixSize);\n          Name += us2fs(si.Name);\n          Size = si.Size;\n          IsAltStream = true;\n          return true;\n        }\n      }\n    }\n  }\n  \n  #endif\n\n  CFindFile finder;\n\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  {\n    /*\n    DWORD lastError = GetLastError();\n    if (lastError == ERROR_FILE_NOT_FOUND\n        || lastError == ERROR_BAD_NETPATH  // XP64: \"\\\\Server\\Share\"\n        || lastError == ERROR_BAD_NET_NAME // Win7: \"\\\\Server\\Share\"\n        || lastError == ERROR_INVALID_NAME // XP64: \"\\\\?\\UNC\\Server\\Share\"\n        || lastError == ERROR_BAD_PATHNAME // Win7: \"\\\\?\\UNC\\Server\\Share\"\n        )\n    */\n    \n    unsigned rootSize = 0;\n    if (IsSuperPath(path))\n      rootSize = kSuperPathPrefixSize;\n    \n    if (NName::IsDrivePath(path + rootSize) && path[rootSize + 3] == 0)\n    {\n      DWORD attrib = GetFileAttrib(path);\n      if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)\n      {\n        ClearBase();\n        Attrib = attrib;\n        Name = path + rootSize;\n        Name.DeleteFrom(2);\n        if (!Fill_From_ByHandleFileInfo(path))\n        {\n        }\n        return true;\n      }\n    }\n    else if (IS_PATH_SEPAR(path[0]))\n    {\n      if (path[1] == 0)\n      {\n        DWORD attrib = GetFileAttrib(path);\n        if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)\n        {\n          ClearBase();\n          Name.Empty();\n          Attrib = attrib;\n          return true;\n        }\n      }\n      else\n      {\n        const unsigned prefixSize = GetNetworkServerPrefixSize(path);\n        if (prefixSize > 0 && path[prefixSize] != 0)\n        {\n          if (NName::FindSepar(path + prefixSize) < 0)\n          {\n            if (Fill_From_ByHandleFileInfo(path))\n            {\n              Name = path + prefixSize;\n              return true;\n            }\n\n            FString s (path);\n            s.Add_PathSepar();\n            s.Add_Char('*'); // CHAR_ANY_MASK\n            bool isOK = false;\n            if (finder.FindFirst(s, *this))\n            {\n              if (Name.IsEqualTo(\".\"))\n              {\n                Name = path + prefixSize;\n                return true;\n              }\n              isOK = true;\n              /* if \"\\\\server\\share\" maps to root folder \"d:\\\", there is no \".\" item.\n                 But it's possible that there are another items */\n            }\n            {\n              const DWORD attrib = GetFileAttrib(path);\n              if (isOK || (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0))\n              {\n                ClearBase();\n                if (attrib != INVALID_FILE_ATTRIBUTES)\n                  Attrib = attrib;\n                else\n                  SetAsDir();\n                Name = path + prefixSize;\n                return true;\n              }\n            }\n            // ::SetLastError(lastError);\n          }\n        }\n      }\n    }\n  }\n  #endif\n\n  bool res = finder.FindFirst(path, *this);\n  if (!followLink\n      || !res\n      || !HasReparsePoint())\n    return res;\n\n  // return FollowReparse(path, IsDir());\n  return Fill_From_ByHandleFileInfo(path);\n/*\n  // Fill_From_ByHandleFileInfo returns false (with Access Denied error),\n  // if there is reparse link file (not directory reparse item).\n  if (Fill_From_ByHandleFileInfo(path))\n    return true;\n  return HasReparsePoint();\n*/\n}\n\nbool CFileInfoBase::Fill_From_ByHandleFileInfo(CFSTR path)\n{\n  BY_HANDLE_FILE_INFORMATION info;\n  if (!NIO::CFileBase::GetFileInformation(path, &info))\n    return false;\n  {\n    Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;\n    CTime = info.ftCreationTime;\n    ATime = info.ftLastAccessTime;\n    MTime = info.ftLastWriteTime;\n    Attrib = info.dwFileAttributes;\n    return true;\n  }\n}\n\n/*\nbool CFileInfo::FollowReparse(CFSTR path, bool isDir)\n{\n  if (isDir)\n  {\n    FString prefix = path;\n    prefix.Add_PathSepar();\n\n    // \"folder/.\" refers to folder itself. So we can't use that path\n    // we must use enumerator and search \".\" item\n    CEnumerator enumerator;\n    enumerator.SetDirPrefix(prefix);\n    for (;;)\n    {\n      CFileInfo fi;\n      if (!enumerator.NextAny(fi))\n        break;\n      if (fi.Name.IsEqualTo_Ascii_NoCase(\".\"))\n      {\n        // we can copy preperies;\n        CTime = fi.CTime;\n        ATime = fi.ATime;\n        MTime = fi.MTime;\n        Attrib = fi.Attrib;\n        Size = fi.Size;\n        return true;\n      }\n      break;\n    }\n    // LastError(lastError);\n    return false;\n  }\n\n  {\n    NIO::CInFile inFile;\n    if (inFile.Open(path))\n    {\n      BY_HANDLE_FILE_INFORMATION info;\n      if (inFile.GetFileInformation(&info))\n      {\n        ClearBase();\n        Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;\n        CTime = info.ftCreationTime;\n        ATime = info.ftLastAccessTime;\n        MTime = info.ftLastWriteTime;\n        Attrib = info.dwFileAttributes;\n        return true;\n      }\n    }\n    return false;\n  }\n}\n*/\n\nbool DoesFileExist_Raw(CFSTR name)\n{\n  CFileInfo fi;\n  return fi.Find(name) && !fi.IsDir();\n}\n\nbool DoesFileExist_FollowLink(CFSTR name)\n{\n  CFileInfo fi;\n  return fi.Find_FollowLink(name) && !fi.IsDir();\n}\n\nbool DoesDirExist(CFSTR name, bool followLink)\n{\n  CFileInfo fi;\n  return fi.Find(name, followLink) && fi.IsDir();\n}\n\nbool DoesFileOrDirExist(CFSTR name)\n{\n  CFileInfo fi;\n  return fi.Find(name);\n}\n\n\nvoid CEnumerator::SetDirPrefix(const FString &dirPrefix)\n{\n  _wildcard = dirPrefix;\n  _wildcard.Add_Char('*');\n}\n\nbool CEnumerator::NextAny(CFileInfo &fi)\n{\n  if (_findFile.IsHandleAllocated())\n    return _findFile.FindNext(fi);\n  else\n    return _findFile.FindFirst(_wildcard, fi);\n}\n\nbool CEnumerator::Next(CFileInfo &fi)\n{\n  for (;;)\n  {\n    if (!NextAny(fi))\n      return false;\n    if (!fi.IsDots())\n      return true;\n  }\n}\n\nbool CEnumerator::Next(CFileInfo &fi, bool &found)\n{\n  /*\n  for (;;)\n  {\n    if (!NextAny(fi))\n      break;\n    if (!fi.IsDots())\n    {\n      found = true;\n      return true;\n    }\n  }\n  */\n\n  if (Next(fi))\n  {\n    found = true;\n    return true;\n  }\n\n  found = false;\n  DWORD lastError = ::GetLastError();\n  if (_findFile.IsHandleAllocated())\n    return (lastError == ERROR_NO_MORE_FILES);\n  // we support the case for empty root folder: FindFirstFile(\"c:\\\\*\") returns ERROR_FILE_NOT_FOUND\n  if (lastError == ERROR_FILE_NOT_FOUND)\n    return true;\n  if (lastError == ERROR_ACCESS_DENIED)\n  {\n    // here we show inaccessible root system folder as empty folder to eliminate redundant user warnings\n    const char *s = \"System Volume Information\" STRING_PATH_SEPARATOR \"*\";\n    const int len = (int)strlen(s);\n    const int delta = (int)_wildcard.Len() - len;\n    if (delta == 0 || (delta > 0 && IS_PATH_SEPAR(_wildcard[(unsigned)delta - 1])))\n      if (StringsAreEqual_Ascii(_wildcard.Ptr((unsigned)delta), s))\n        return true;\n  }\n  return false;\n}\n\n\n////////////////////////////////\n// CFindChangeNotification\n// FindFirstChangeNotification can return 0. MSDN doesn't tell about it.\n\nbool CFindChangeNotification::Close() throw()\n{\n  if (!IsHandleAllocated())\n    return true;\n  if (!::FindCloseChangeNotification(_handle))\n    return false;\n  _handle = INVALID_HANDLE_VALUE;\n  return true;\n}\n           \nHANDLE CFindChangeNotification::FindFirst(CFSTR path, bool watchSubtree, DWORD notifyFilter)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n    _handle = ::FindFirstChangeNotification(fs2fas(path), BoolToBOOL(watchSubtree), notifyFilter);\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH\n    _handle = ::FindFirstChangeNotificationW(fs2us(path), BoolToBOOL(watchSubtree), notifyFilter);\n    #ifdef Z7_LONG_PATH\n    if (!IsHandleAllocated())\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        _handle = ::FindFirstChangeNotificationW(superPath, BoolToBOOL(watchSubtree), notifyFilter);\n    }\n    #endif\n  }\n  return _handle;\n}\n\n#ifndef UNDER_CE\n\nbool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings)\n{\n  driveStrings.Clear();\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    driveStrings.Clear();\n    UINT32 size = GetLogicalDriveStrings(0, NULL);\n    if (size == 0)\n      return false;\n    CObjArray<char> buf(size);\n    UINT32 newSize = GetLogicalDriveStrings(size, buf);\n    if (newSize == 0 || newSize > size)\n      return false;\n    AString s;\n    UINT32 prev = 0;\n    for (UINT32 i = 0; i < newSize; i++)\n    {\n      if (buf[i] == 0)\n      {\n        s = buf + prev;\n        prev = i + 1;\n        driveStrings.Add(fas2fs(s));\n      }\n    }\n    return prev == newSize;\n  }\n  else\n  #endif\n  {\n    UINT32 size = GetLogicalDriveStringsW(0, NULL);\n    if (size == 0)\n      return false;\n    CObjArray<wchar_t> buf(size);\n    UINT32 newSize = GetLogicalDriveStringsW(size, buf);\n    if (newSize == 0 || newSize > size)\n      return false;\n    UString s;\n    UINT32 prev = 0;\n    for (UINT32 i = 0; i < newSize; i++)\n    {\n      if (buf[i] == 0)\n      {\n        s = buf + prev;\n        prev = i + 1;\n        driveStrings.Add(us2fs(s));\n      }\n    }\n    return prev == newSize;\n  }\n}\n\n#endif // UNDER_CE\n\n\n\n#else // _WIN32\n\n// ---------- POSIX ----------\n\nstatic int MY_lstat(CFSTR path, struct stat *st, bool followLink)\n{\n  memset(st, 0, sizeof(*st));\n  int res;\n  // #ifdef ENV_HAVE_LSTAT\n  if (/* global_use_lstat && */ !followLink)\n  {\n    // printf(\"\\nlstat\\n\");\n    res = lstat(path, st);\n  }\n  else\n  // #endif\n  {\n    // printf(\"\\nstat\\n\");\n    res = stat(path, st);\n  }\n#if 0\n#if defined(__clang__) && __clang_major__ >= 14\n  #pragma GCC diagnostic ignored \"-Wc++98-compat-pedantic\"\n#endif\n\n  printf(\"\\n st_dev = %lld\", (long long)(st->st_dev));\n  printf(\"\\n st_ino = %lld\", (long long)(st->st_ino));\n  printf(\"\\n st_mode = %llx\", (long long)(st->st_mode));\n  printf(\"\\n st_nlink = %lld\", (long long)(st->st_nlink));\n  printf(\"\\n st_uid = %lld\", (long long)(st->st_uid));\n  printf(\"\\n st_gid = %lld\", (long long)(st->st_gid));\n  printf(\"\\n st_size = %lld\", (long long)(st->st_size));\n  printf(\"\\n st_blksize = %lld\", (long long)(st->st_blksize));\n  printf(\"\\n st_blocks = %lld\", (long long)(st->st_blocks));\n  printf(\"\\n st_ctim = %lld\", (long long)(ST_CTIME((*st)).tv_sec));\n  printf(\"\\n st_mtim = %lld\", (long long)(ST_MTIME((*st)).tv_sec));\n  printf(\"\\n st_atim = %lld\", (long long)(ST_ATIME((*st)).tv_sec));\n     printf(S_ISFIFO(st->st_mode) ? \"\\n FIFO\" : \"\\n NO FIFO\");\n  printf(\"\\n\");\n#endif\n\n  return res;\n}\n\n\nstatic const char *Get_Name_from_Path(CFSTR path) throw()\n{\n  size_t len = strlen(path);\n  if (len == 0)\n    return path;\n  const char *p = path + len - 1;\n  {\n    if (p == path)\n      return path;\n    p--;\n  }\n  for (;;)\n  {\n    char c = *p;\n    if (IS_PATH_SEPAR(c))\n      return p + 1;\n    if (p == path)\n      return path;\n    p--;\n  }\n}\n\n\nUInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode)\n{\n  UInt32 attrib = S_ISDIR(mode) ?\n      FILE_ATTRIBUTE_DIRECTORY :\n      FILE_ATTRIBUTE_ARCHIVE;\n  if ((mode & 0222) == 0) // S_IWUSR in p7zip\n    attrib |= FILE_ATTRIBUTE_READONLY;\n  return attrib | FILE_ATTRIBUTE_UNIX_EXTENSION | ((mode & 0xFFFF) << 16);\n}\n\n/*\nUInt32 Get_WinAttrib_From_stat(const struct stat &st)\n{\n  UInt32 attrib = S_ISDIR(st.st_mode) ?\n    FILE_ATTRIBUTE_DIRECTORY :\n    FILE_ATTRIBUTE_ARCHIVE;\n\n  if ((st.st_mode & 0222) == 0) // check it !!!\n    attrib |= FILE_ATTRIBUTE_READONLY;\n\n  attrib |= FILE_ATTRIBUTE_UNIX_EXTENSION + ((st.st_mode & 0xFFFF) << 16);\n  return attrib;\n}\n*/\n\nvoid CFileInfoBase::SetFrom_stat(const struct stat &st)\n{\n  // IsDevice = false;\n\n  if (S_ISDIR(st.st_mode))\n  {\n    Size = 0;\n  }\n  else\n  {\n    Size = (UInt64)st.st_size; // for a symbolic link, size = size of filename\n  }\n\n  // Attrib = Get_WinAttribPosix_From_PosixMode(st.st_mode);\n\n  // NTime::UnixTimeToFileTime(st.st_ctime, CTime);\n  // NTime::UnixTimeToFileTime(st.st_mtime, MTime);\n  // NTime::UnixTimeToFileTime(st.st_atime, ATime);\n  #ifdef __APPLE__\n  // #ifdef _DARWIN_FEATURE_64_BIT_INODE\n  /*\n    here we can use birthtime instead of st_ctimespec.\n    but we use st_ctimespec for compatibility with previous versions and p7zip.\n    st_birthtimespec in OSX\n    st_birthtim : at FreeBSD, NetBSD\n  */\n  // timespec_To_FILETIME(st.st_birthtimespec, CTime);\n  // #else\n  // timespec_To_FILETIME(st.st_ctimespec, CTime);\n  // #endif\n  // timespec_To_FILETIME(st.st_mtimespec, MTime);\n  // timespec_To_FILETIME(st.st_atimespec, ATime);\n  CTime = st.st_ctimespec;\n  MTime = st.st_mtimespec;\n  ATime = st.st_atimespec;\n\n  #elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__)\n  \n  // CTime = ST_CTIME(st);\n  // MTime = ST_MTIME(st);\n  // ATime = ST_ATIME(st);\n  CTime.tv_sec = st.st_ctime;  CTime.tv_nsec = 0;\n  MTime.tv_sec = st.st_mtime;  MTime.tv_nsec = 0;\n  ATime.tv_sec = st.st_atime;  ATime.tv_nsec = 0;\n\n  #else\n  // timespec_To_FILETIME(st.st_ctim, CTime, &CTime_ns100);\n  // timespec_To_FILETIME(st.st_mtim, MTime, &MTime_ns100);\n  // timespec_To_FILETIME(st.st_atim, ATime, &ATime_ns100);\n  CTime = st.st_ctim;\n  MTime = st.st_mtim;\n  ATime = st.st_atim;\n\n  #endif\n\n  dev = st.st_dev;\n  ino = st.st_ino;\n  mode = st.st_mode;\n  nlink = st.st_nlink;\n  uid = st.st_uid;\n  gid = st.st_gid;\n  rdev = st.st_rdev;\n\n  /*\n  printf(\"\\n sizeof timespec = %d\", (int)sizeof(timespec));\n  printf(\"\\n sizeof st_rdev = %d\", (int)sizeof(rdev));\n  printf(\"\\n sizeof st_ino = %d\", (int)sizeof(ino));\n  printf(\"\\n sizeof mode_t = %d\", (int)sizeof(mode_t));\n  printf(\"\\n sizeof nlink_t = %d\", (int)sizeof(nlink_t));\n  printf(\"\\n sizeof uid_t = %d\", (int)sizeof(uid_t));\n  printf(\"\\n\");\n  */\n  /*\n  printf(\"\\n st_rdev = %llx\", (long long)rdev);\n  printf(\"\\n st_dev  = %llx\", (long long)dev);\n  printf(\"\\n dev  : major = %5x minor = %5x\", (unsigned)major(dev), (unsigned)minor(dev));\n  printf(\"\\n st_ino = %lld\", (long long)(ino));\n  printf(\"\\n rdev : major = %5x minor = %5x\", (unsigned)major(rdev), (unsigned)minor(rdev));\n  printf(\"\\n size = %lld \\n\", (long long)(Size));\n  printf(\"\\n\");\n  */\n}\n\n/*\nint Uid_To_Uname(uid_t uid, AString &name)\n{\n  name.Empty();\n  struct passwd *passwd;\n\n  if (uid != 0 && uid == cached_no_such_uid)\n    {\n      *uname = xstrdup (\"\");\n      return;\n    }\n\n  if (!cached_uname || uid != cached_uid)\n    {\n      passwd = getpwuid (uid);\n      if (passwd)\n  {\n    cached_uid = uid;\n    assign_string (&cached_uname, passwd->pw_name);\n  }\n      else\n  {\n    cached_no_such_uid = uid;\n    *uname = xstrdup (\"\");\n    return;\n  }\n    }\n  *uname = xstrdup (cached_uname);\n}\n*/\n\nbool CFileInfo::Find_DontFill_Name(CFSTR path, bool followLink)\n{\n  struct stat st;\n  if (MY_lstat(path, &st, followLink) != 0)\n    return false;\n  // printf(\"\\nFind_DontFill_Name : name=%s\\n\", path);\n  SetFrom_stat(st);\n  return true;\n}\n\n\nbool CFileInfo::Find(CFSTR path, bool followLink)\n{\n  // printf(\"\\nCEnumerator::Find() name = %s\\n\", path);\n  if (!Find_DontFill_Name(path, followLink))\n    return false;\n\n  // printf(\"\\nOK\\n\");\n\n  Name = Get_Name_from_Path(path);\n  if (!Name.IsEmpty())\n  {\n    char c = Name.Back();\n    if (IS_PATH_SEPAR(c))\n      Name.DeleteBack();\n  }\n  return true;\n}\n\n\nbool DoesFileExist_Raw(CFSTR name)\n{\n  // FIXME for symbolic links.\n  struct stat st;\n  if (MY_lstat(name, &st, false) != 0)\n    return false;\n  return !S_ISDIR(st.st_mode);\n}\n\nbool DoesFileExist_FollowLink(CFSTR name)\n{\n  // FIXME for symbolic links.\n  struct stat st;\n  if (MY_lstat(name, &st, true) != 0)\n    return false;\n  return !S_ISDIR(st.st_mode);\n}\n\nbool DoesDirExist(CFSTR name, bool followLink)\n{\n  struct stat st;\n  if (MY_lstat(name, &st, followLink) != 0)\n    return false;\n  return S_ISDIR(st.st_mode);\n}\n\nbool DoesFileOrDirExist(CFSTR name)\n{\n  struct stat st;\n  if (MY_lstat(name, &st, false) != 0)\n    return false;\n  return true;\n}\n\n\nCEnumerator::~CEnumerator()\n{\n  if (_dir)\n    closedir(_dir);\n}\n\nvoid CEnumerator::SetDirPrefix(const FString &dirPrefix)\n{\n  _wildcard = dirPrefix;\n}\n\nbool CDirEntry::IsDots() const throw()\n{\n  /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)\n     we can call fstatat() for that case, but we use only (Name) check here */\n\n#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)\n  if (Type != DT_DIR && Type != DT_UNKNOWN)\n    return false;\n#endif\n\n  return Name.Len() != 0\n      && Name.Len() <= 2\n      && Name[0] == '.'\n      && (Name.Len() == 1 || Name[1] == '.');\n}\n\n\nbool CEnumerator::NextAny(CDirEntry &fi, bool &found)\n{\n  found = false;\n\n  if (!_dir)\n  {\n    const char *w = \"./\";\n    if (!_wildcard.IsEmpty())\n      w = _wildcard.Ptr();\n    _dir = ::opendir((const char *)w);\n    if (_dir == NULL)\n      return false;\n  }\n\n  // To distinguish end of stream from an error, we must set errno to zero before readdir()\n  errno = 0;\n\n  struct dirent *de = readdir(_dir);\n  if (!de)\n  {\n    if (errno == 0)\n      return true; // it's end of stream, and we report it with (found = false)\n    // it's real error\n    return false;\n  }\n\n  fi.iNode = de->d_ino;\n  \n#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)\n  fi.Type = de->d_type;\n  /* some systems (like CentOS 7.x on XFS) have (Type == DT_UNKNOWN)\n     we can set (Type) from fstatat() in that case.\n     But (Type) is not too important. So we don't set it here with slow fstatat() */\n  /*\n  // fi.Type = DT_UNKNOWN; // for debug\n  if (fi.Type == DT_UNKNOWN)\n  {\n    struct stat st;\n    if (fstatat(dirfd(_dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) == 0)\n      if (S_ISDIR(st.st_mode))\n        fi.Type = DT_DIR;\n  }\n  */\n#endif\n  \n  /*\n  if (de->d_type == DT_DIR)\n    fi.Attrib = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(S_IFDIR) << 16);\n  else if (de->d_type < 16)\n    fi.Attrib = FILE_ATTRIBUTE_UNIX_EXTENSION | ((UInt32)(de->d_type) << (16 + 12));\n  */\n  fi.Name = de->d_name;\n\n  /*\n  printf(\"\\nCEnumerator::NextAny; len = %d %s \\n\", (int)fi.Name.Len(), fi.Name.Ptr());\n  for (unsigned i = 0; i < fi.Name.Len(); i++)\n    printf (\" %02x\", (unsigned)(Byte)de->d_name[i]);\n  printf(\"\\n\");\n  */\n\n  found = true;\n  return true;\n}\n\n\nbool CEnumerator::Next(CDirEntry &fi, bool &found)\n{\n  // printf(\"\\nCEnumerator::Next()\\n\");\n  // PrintName(\"Next\", \"\");\n  for (;;)\n  {\n    if (!NextAny(fi, found))\n      return false;\n    if (!found)\n      return true;\n    if (!fi.IsDots())\n    {\n      /*\n      if (!NeedFullStat)\n        return true;\n      // we silently skip error file here - it can be wrong link item\n      if (fi.Find_DontFill_Name(path))\n        return true;\n      */\n      return true;\n    }\n  }\n}\n\n/*\nbool CEnumerator::Next(CDirEntry &fileInfo, bool &found)\n{\n  bool found;\n  if (!Next(fi, found))\n    return false;\n  return found;\n}\n*/\n\nbool CEnumerator::Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const\n{\n  // printf(\"\\nCEnumerator::Fill_FileInfo()\\n\");\n  struct stat st;\n  // probably it's OK to use fstatat() even if it changes file position dirfd(_dir)\n  int res = fstatat(dirfd(_dir), de.Name, &st, followLink ? 0 : AT_SYMLINK_NOFOLLOW);\n  // if fstatat() is not supported, we can use stat() / lstat()\n  \n  /*\n  const FString path = _wildcard + s;\n  int res = MY_lstat(path, &st, followLink);\n  */\n  \n  if (res != 0)\n    return false;\n  // printf(\"\\nname=%s\\n\", de.Name.Ptr());\n  fileInfo.SetFrom_stat(st);\n  fileInfo.Name = de.Name;\n  return true;\n}\n\n#endif // _WIN32\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileFind.h",
    "content": "﻿// Windows/FileFind.h\n\n#ifndef ZIP7_INC_WINDOWS_FILE_FIND_H\n#define ZIP7_INC_WINDOWS_FILE_FIND_H\n\n#ifndef _WIN32\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <dirent.h>\n#endif\n\n#include \"../Common/MyLinux.h\"\n#include \"../Common/MyString.h\"\n#include \"../Common/MyWindows.h\"\n\n#include \"Defs.h\"\n\n#include \"FileIO.h\"\n\nnamespace NWindows {\nnamespace NFile {\nnamespace NFind {\n\n// bool DoesFileExist(CFSTR name, bool followLink);\nbool DoesFileExist_Raw(CFSTR name);\nbool DoesFileExist_FollowLink(CFSTR name);\nbool DoesDirExist(CFSTR name, bool followLink);\n\ninline bool DoesDirExist(CFSTR name)\n  { return DoesDirExist(name, false); }\ninline bool DoesDirExist_FollowLink(CFSTR name)\n  { return DoesDirExist(name, true); }\n\n// it's always _Raw\nbool DoesFileOrDirExist(CFSTR name);\n\nDWORD GetFileAttrib(CFSTR path);\n\n#ifdef _WIN32\n\nnamespace NAttributes\n{\n  inline bool IsReadOnly(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_READONLY) != 0; }\n  inline bool IsHidden(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_HIDDEN) != 0; }\n  inline bool IsSystem(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_SYSTEM) != 0; }\n  inline bool IsDir(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; }\n  inline bool IsArchived(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ARCHIVE) != 0; }\n  inline bool IsCompressed(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_COMPRESSED) != 0; }\n  inline bool IsEncrypted(DWORD attrib) { return (attrib & FILE_ATTRIBUTE_ENCRYPTED) != 0; }\n\n  inline UInt32 Get_PosixMode_From_WinAttrib(DWORD attrib)\n  {\n    UInt32 v = IsDir(attrib) ? MY_LIN_S_IFDIR : MY_LIN_S_IFREG;\n    /* 21.06: as WSL we allow write permissions (0222) for directories even for (FILE_ATTRIBUTE_READONLY).\n    So extracting at Linux will be allowed to write files inside (0777) directories. */\n    v |= ((IsReadOnly(attrib) && !IsDir(attrib)) ? 0555 : 0777);\n    return v;\n  }\n}\n\n#else\n\nUInt32 Get_WinAttribPosix_From_PosixMode(UInt32 mode);\n\n#endif\n\nclass CFileInfoBase\n{\n #ifdef _WIN32\n  bool MatchesMask(UINT32 mask) const { return ((Attrib & mask) != 0); }\n #endif\npublic:\n  UInt64 Size;\n  CFiTime CTime;\n  CFiTime ATime;\n  CFiTime MTime;\n #ifdef _WIN32\n  DWORD Attrib;\n  bool IsAltStream;\n  bool IsDevice;\n\n  /*\n  #ifdef UNDER_CE\n  DWORD ObjectID;\n  #else\n  UINT32 ReparseTag;\n  #endif\n  */\n #else\n  dev_t dev;     /* ID of device containing file */\n  ino_t ino;\n  mode_t mode;\n  nlink_t nlink;\n  uid_t uid;     /* user ID of owner */\n  gid_t gid;     /* group ID of owner */\n  dev_t rdev;    /* device ID (defined, if S_ISCHR(mode) || S_ISBLK(mode)) */\n  // bool Use_lstat;\n #endif\n\n  CFileInfoBase() { ClearBase(); }\n  void ClearBase() throw();\n  bool SetAs_StdInFile();\n\n #ifdef _WIN32\n \n  bool Fill_From_ByHandleFileInfo(CFSTR path);\n  void SetAsDir()  { Attrib = FILE_ATTRIBUTE_DIRECTORY; } // |= (FILE_ATTRIBUTE_UNIX_EXTENSION + (S_IFDIR << 16));\n\n  bool IsArchived() const { return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); }\n  bool IsCompressed() const { return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); }\n  bool IsDir() const { return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); }\n  bool IsEncrypted() const { return MatchesMask(FILE_ATTRIBUTE_ENCRYPTED); }\n  bool IsHidden() const { return MatchesMask(FILE_ATTRIBUTE_HIDDEN); }\n  bool IsNormal() const { return MatchesMask(FILE_ATTRIBUTE_NORMAL); }\n  bool IsOffline() const { return MatchesMask(FILE_ATTRIBUTE_OFFLINE); }\n  bool IsReadOnly() const { return MatchesMask(FILE_ATTRIBUTE_READONLY); }\n  bool HasReparsePoint() const { return MatchesMask(FILE_ATTRIBUTE_REPARSE_POINT); }\n  bool IsSparse() const { return MatchesMask(FILE_ATTRIBUTE_SPARSE_FILE); }\n  bool IsSystem() const { return MatchesMask(FILE_ATTRIBUTE_SYSTEM); }\n  bool IsTemporary() const { return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); }\n\n  UInt32 GetWinAttrib() const { return Attrib; }\n  UInt32 GetPosixAttrib() const\n  {\n    return NAttributes::Get_PosixMode_From_WinAttrib(Attrib);\n  }\n  bool Has_Attrib_ReparsePoint() const { return (Attrib & FILE_ATTRIBUTE_REPARSE_POINT) != 0; }\n \n #else\n  \n  UInt32 GetPosixAttrib() const { return mode; }\n  UInt32 GetWinAttrib() const { return Get_WinAttribPosix_From_PosixMode(mode); }\n\n  bool IsDir() const { return S_ISDIR(mode); }\n  void SetAsDir()  { mode = S_IFDIR | 0777; }\n  void SetFrom_stat(const struct stat &st);\n\n  bool IsReadOnly() const\n  {\n    // does linux support writing to ReadOnly files?\n    if ((mode & 0222) == 0) // S_IWUSR in p7zip\n      return true;\n    return false;\n  }\n \n  bool IsPosixLink() const { return S_ISLNK(mode); }\n\n #endif\n\n  bool IsOsSymLink() const\n  {\n    #ifdef _WIN32\n      return HasReparsePoint();\n    #else\n      return IsPosixLink();\n    #endif\n  }\n};\n\nstruct CFileInfo: public CFileInfoBase\n{\n  FString Name;\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  // FString ShortName;\n  #endif\n\n  bool IsDots() const throw();\n  bool Find(CFSTR path, bool followLink = false);\n  bool Find_FollowLink(CFSTR path) { return Find(path, true); }\n\n  #ifdef _WIN32\n  // bool Fill_From_ByHandleFileInfo(CFSTR path);\n  // bool FollowReparse(CFSTR path, bool isDir);\n  #else\n  bool Find_DontFill_Name(CFSTR path, bool followLink = false);\n  #endif\n};\n\n\n#ifdef _WIN32\n\nclass CFindFileBase  MY_UNCOPYABLE\n{\nprotected:\n  HANDLE _handle;\npublic:\n  bool IsHandleAllocated() const { return _handle != INVALID_HANDLE_VALUE; }\n  CFindFileBase(): _handle(INVALID_HANDLE_VALUE) {}\n  ~CFindFileBase() { Close(); }\n  bool Close() throw();\n};\n\nclass CFindFile: public CFindFileBase\n{\npublic:\n  bool FindFirst(CFSTR wildcard, CFileInfo &fileInfo);\n  bool FindNext(CFileInfo &fileInfo);\n};\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n\nstruct CStreamInfo\n{\n  UString Name;\n  UInt64 Size;\n\n  UString GetReducedName() const; // returns \":Name\"\n  // UString GetReducedName2() const; // returns \"Name\"\n  bool IsMainStream() const throw();\n};\n\nclass CFindStream: public CFindFileBase\n{\npublic:\n  bool FindFirst(CFSTR filePath, CStreamInfo &streamInfo);\n  bool FindNext(CStreamInfo &streamInfo);\n};\n\nclass CStreamEnumerator  MY_UNCOPYABLE\n{\n  CFindStream _find;\n  FString _filePath;\n\n  bool NextAny(CFileInfo &fileInfo, bool &found);\npublic:\n  CStreamEnumerator(const FString &filePath): _filePath(filePath) {}\n  bool Next(CStreamInfo &streamInfo, bool &found);\n};\n\n#endif // defined(_WIN32) && !defined(UNDER_CE)\n\n\nclass CEnumerator  MY_UNCOPYABLE\n{\n  CFindFile _findFile;\n  FString _wildcard;\n\n  bool NextAny(CFileInfo &fileInfo);\npublic:\n  void SetDirPrefix(const FString &dirPrefix);\n  bool Next(CFileInfo &fileInfo);\n  bool Next(CFileInfo &fileInfo, bool &found);\n};\n\n\nclass CFindChangeNotification  MY_UNCOPYABLE\n{\n  HANDLE _handle;\npublic:\n  operator HANDLE () { return _handle; }\n  bool IsHandleAllocated() const\n  {\n    /* at least on win2000/XP (undocumented):\n       if pathName is \"\" or NULL,\n       FindFirstChangeNotification() could return NULL.\n       So we check for INVALID_HANDLE_VALUE and NULL.\n    */\n    return _handle != INVALID_HANDLE_VALUE && _handle != NULL;\n  }\n  CFindChangeNotification(): _handle(INVALID_HANDLE_VALUE) {}\n  ~CFindChangeNotification() { Close(); }\n  bool Close() throw();\n  HANDLE FindFirst(CFSTR pathName, bool watchSubtree, DWORD notifyFilter);\n  bool FindNext() { return BOOLToBool(::FindNextChangeNotification(_handle)); }\n};\n\n#ifndef UNDER_CE\nbool MyGetLogicalDriveStrings(CObjectVector<FString> &driveStrings);\n#endif\n\ntypedef CFileInfo CDirEntry;\n\n\n#else // WIN32\n\n\nstruct CDirEntry\n{\n  ino_t iNode;\n#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)\n  Byte Type;\n#endif\n  FString Name;\n\n  /*\n#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)\n  bool IsDir() const\n  {\n    // (Type == DT_UNKNOWN) on some systems\n    return Type == DT_DIR;\n  }\n#endif\n  */\n\n  bool IsDots() const throw();\n};\n\nclass CEnumerator  MY_UNCOPYABLE\n{\n  DIR *_dir;\n  FString _wildcard;\n\n  bool NextAny(CDirEntry &fileInfo, bool &found);\npublic:\n  CEnumerator(): _dir(NULL) {}\n  ~CEnumerator();\n  void SetDirPrefix(const FString &dirPrefix);\n\n  bool Next(CDirEntry &fileInfo, bool &found);\n  bool Fill_FileInfo(const CDirEntry &de, CFileInfo &fileInfo, bool followLink) const;\n  bool DirEntry_IsDir(const CDirEntry &de, bool followLink) const\n  {\n#if !defined(_AIX) && !defined(__sun) && !defined(__QNXNTO__)\n    if (de.Type == DT_DIR)\n      return true;\n    if (de.Type != DT_UNKNOWN)\n      return false;\n#endif\n    CFileInfo fileInfo;\n    if (Fill_FileInfo(de, fileInfo, followLink))\n    {\n      return fileInfo.IsDir();\n    }\n    return false; // change it\n  }\n};\n\n/*\ninline UInt32 Get_WinAttrib_From_PosixMode(UInt32 mode)\n{\n  UInt32 attrib = S_ISDIR(mode) ?\n    FILE_ATTRIBUTE_DIRECTORY :\n    FILE_ATTRIBUTE_ARCHIVE;\n  if ((st.st_mode & 0222) == 0) // check it !!!\n    attrib |= FILE_ATTRIBUTE_READONLY;\n  return attrib;\n}\n*/\n\n// UInt32 Get_WinAttrib_From_stat(const struct stat &st);\n\n\n#endif // WIN32\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileIO.cpp",
    "content": "﻿// Windows/FileIO.cpp\n\n#include \"StdAfx.h\"\n\n#ifdef Z7_DEVICE_FILE\n#include \"../../C/Alloc.h\"\n#endif\n\n// #include <stdio.h>\n\n/*\n#ifndef _WIN32\n// for ioctl BLKGETSIZE64\n#include <sys/ioctl.h>\n#include <linux/fs.h>\n#endif\n*/\n\n#include \"FileIO.h\"\n#include \"FileName.h\"\n\nHRESULT GetLastError_noZero_HRESULT()\n{\n  const DWORD res = ::GetLastError();\n  if (res == 0)\n    return E_FAIL;\n  return HRESULT_FROM_WIN32(res);\n}\n\n#ifdef _WIN32\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nusing namespace NWindows;\nusing namespace NFile;\nusing namespace NName;\n\nnamespace NWindows {\nnamespace NFile {\n\n#ifdef Z7_DEVICE_FILE\n\nnamespace NSystem\n{\nbool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);\n}\n#endif\n\nnamespace NIO {\n\n/*\nWinXP-64 CreateFile():\n  \"\"             -  ERROR_PATH_NOT_FOUND\n  :stream        -  OK\n  .:stream       -  ERROR_PATH_NOT_FOUND\n  .\\:stream      -  OK\n  \n  folder\\:stream -  ERROR_INVALID_NAME\n  folder:stream  -  OK\n\n  c:\\:stream     -  OK\n\n  c::stream      -  ERROR_INVALID_NAME, if current dir is NOT ROOT ( c:\\dir1 )\n  c::stream      -  OK,                 if current dir is ROOT     ( c:\\ )\n*/\n\nbool CFileBase::Create(CFSTR path, DWORD desiredAccess,\n    DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\n{\n  if (!Close())\n    return false;\n\n  #ifdef Z7_DEVICE_FILE\n  IsDeviceFile = false;\n  #endif\n\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    _handle = ::CreateFile(fs2fas(path), desiredAccess, shareMode,\n        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);\n  }\n  else\n  #endif\n  {\n    IF_USE_MAIN_PATH\n      _handle = ::CreateFileW(fs2us(path), desiredAccess, shareMode,\n        (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);\n    #ifdef Z7_LONG_PATH\n    if (_handle == INVALID_HANDLE_VALUE && USE_SUPER_PATH)\n    {\n      UString superPath;\n      if (GetSuperPath(path, superPath, USE_MAIN_PATH))\n        _handle = ::CreateFileW(superPath, desiredAccess, shareMode,\n            (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, flagsAndAttributes, (HANDLE)NULL);\n    }\n    #endif\n  }\n  \n  /*\n  #ifndef UNDER_CE\n  #ifndef Z7_SFX\n  if (_handle == INVALID_HANDLE_VALUE)\n  {\n    // it's debug hack to open symbolic links in Windows XP and WSL links in Windows 10\n    DWORD lastError = GetLastError();\n    if (lastError == ERROR_CANT_ACCESS_FILE)\n    {\n      CByteBuffer buf;\n      if (NIO::GetReparseData(path, buf, NULL))\n      {\n        CReparseAttr attr;\n        if (attr.Parse(buf, buf.Size()))\n        {\n          FString dirPrefix, fileName;\n          if (NDir::GetFullPathAndSplit(path, dirPrefix, fileName))\n          {\n            FString fullPath;\n            if (GetFullPath(dirPrefix, us2fs(attr.GetPath()), fullPath))\n            {\n              // FIX IT: recursion levels must be restricted\n              return Create(fullPath, desiredAccess,\n                shareMode, creationDisposition, flagsAndAttributes);\n            }\n          }\n        }\n      }\n      SetLastError(lastError);\n    }\n  }\n  #endif\n  #endif\n  */\n\n  return (_handle != INVALID_HANDLE_VALUE);\n}\n\nbool CFileBase::Close() throw()\n{\n  if (_handle == INVALID_HANDLE_VALUE)\n    return true;\n#if 0\n  if (!IsStdStream)\n#endif\n  {\n    if (!::CloseHandle(_handle))\n      return false;\n  }\n#if 0\n  IsStdStream = false;\n  IsStdPipeStream = false;\n#endif\n  _handle = INVALID_HANDLE_VALUE;\n  return true;\n}\n\nbool CFileBase::GetLength(UInt64 &length) const throw()\n{\n  #ifdef Z7_DEVICE_FILE\n  if (IsDeviceFile && SizeDefined)\n  {\n    length = Size;\n    return true;\n  }\n  #endif\n\n  DWORD high = 0;\n  const DWORD low = ::GetFileSize(_handle, &high);\n  if (low == INVALID_FILE_SIZE)\n    if (::GetLastError() != NO_ERROR)\n      return false;\n  length = (((UInt64)high) << 32) + low;\n  return true;\n\n  /*\n  LARGE_INTEGER fileSize;\n  // GetFileSizeEx() is unsupported in 98/ME/NT, and supported in Win2000+\n  if (!GetFileSizeEx(_handle, &fileSize))\n    return false;\n  length = (UInt64)fileSize.QuadPart;\n  return true;\n  */\n}\n\n\n/* Specification for SetFilePointer():\n   \n   If a new file pointer is a negative value,\n   {\n     the function fails,\n     the file pointer is not moved,\n     the code returned by GetLastError() is ERROR_NEGATIVE_SEEK.\n   }\n\n   If the hFile handle is opened with the FILE_FLAG_NO_BUFFERING flag set\n   {\n     an application can move the file pointer only to sector-aligned positions.\n     A sector-aligned position is a position that is a whole number multiple of\n     the volume sector size.\n     An application can obtain a volume sector size by calling the GetDiskFreeSpace.\n   }\n\n   It is not an error to set a file pointer to a position beyond the end of the file.\n   The size of the file does not increase until you call the SetEndOfFile, WriteFile, or WriteFileEx function.\n\n   If the return value is INVALID_SET_FILE_POINTER and if lpDistanceToMoveHigh is non-NULL,\n   an application must call GetLastError to determine whether or not the function has succeeded or failed.\n*/\n\nbool CFileBase::GetPosition(UInt64 &position) const throw()\n{\n  LONG high = 0;\n  const DWORD low = ::SetFilePointer(_handle, 0, &high, FILE_CURRENT);\n  if (low == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)\n  {\n    // for error case we can set (position)  to (-1) or (0) or leave (position) unchanged.\n    // position = (UInt64)(Int64)-1; // for debug\n    position = 0;\n    return false;\n  }\n  position = (((UInt64)(UInt32)high) << 32) + low;\n  return true;\n  // we don't want recursed GetPosition()\n  // return Seek(0, FILE_CURRENT, position);\n}\n\nbool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw()\n{\n  #ifdef Z7_DEVICE_FILE\n  if (IsDeviceFile && SizeDefined && moveMethod == FILE_END)\n  {\n    distanceToMove += Size;\n    moveMethod = FILE_BEGIN;\n  }\n  #endif\n\n  LONG high = (LONG)(distanceToMove >> 32);\n  const DWORD low = ::SetFilePointer(_handle, (LONG)(distanceToMove & 0xFFFFFFFF), &high, moveMethod);\n  if (low == INVALID_SET_FILE_POINTER)\n  {\n    const DWORD lastError = ::GetLastError();\n    if (lastError != NO_ERROR)\n    {\n      // 21.07: we set (newPosition) to real position even after error.\n      GetPosition(newPosition);\n      SetLastError(lastError); // restore LastError\n      return false;\n    }\n  }\n  newPosition = (((UInt64)(UInt32)high) << 32) + low;\n  return true;\n}\n\nbool CFileBase::Seek(UInt64 position, UInt64 &newPosition) const throw()\n{\n  return Seek((Int64)position, FILE_BEGIN, newPosition);\n}\n\nbool CFileBase::SeekToBegin() const throw()\n{\n  UInt64 newPosition = 0;\n  return Seek(0, newPosition) && (newPosition == 0);\n}\n\nbool CFileBase::SeekToEnd(UInt64 &newPosition) const throw()\n{\n  return Seek(0, FILE_END, newPosition);\n}\n\n// ---------- CInFile ---------\n\n#ifdef Z7_DEVICE_FILE\n\nvoid CInFile::CorrectDeviceSize()\n{\n  // maybe we must decrease kClusterSize to 1 << 12, if we want correct size at tail\n  const UInt32 kClusterSize = 1 << 14;\n  UInt64 pos = Size & ~(UInt64)(kClusterSize - 1);\n  UInt64 realNewPosition;\n  if (!Seek(pos, realNewPosition))\n    return;\n  Byte *buf = (Byte *)MidAlloc(kClusterSize);\n\n  bool needbackward = true;\n\n  for (;;)\n  {\n    UInt32 processed = 0;\n    // up test is slow for \"PhysicalDrive\".\n    // processed size for latest block for \"PhysicalDrive0\" is 0.\n    if (!Read1(buf, kClusterSize, processed))\n      break;\n    if (processed == 0)\n      break;\n    needbackward = false;\n    Size = pos + processed;\n    if (processed != kClusterSize)\n      break;\n    pos += kClusterSize;\n  }\n\n  if (needbackward && pos != 0)\n  {\n    pos -= kClusterSize;\n    for (;;)\n    {\n      // break;\n      if (!Seek(pos, realNewPosition))\n        break;\n      if (!buf)\n      {\n        buf = (Byte *)MidAlloc(kClusterSize);\n        if (!buf)\n          break;\n      }\n      UInt32 processed = 0;\n      // that code doesn't work for \"PhysicalDrive0\"\n      if (!Read1(buf, kClusterSize, processed))\n        break;\n      if (processed != 0)\n      {\n        Size = pos + processed;\n        break;\n      }\n      if (pos == 0)\n        break;\n      pos -= kClusterSize;\n    }\n  }\n  MidFree(buf);\n}\n\n\nvoid CInFile::CalcDeviceSize(CFSTR s)\n{\n  SizeDefined = false;\n  Size = 0;\n  if (_handle == INVALID_HANDLE_VALUE || !IsDeviceFile)\n    return;\n  #ifdef UNDER_CE\n\n  SizeDefined = true;\n  Size = 128 << 20;\n  \n  #else\n  \n  PARTITION_INFORMATION partInfo;\n  bool needCorrectSize = true;\n\n  /*\n    WinXP 64-bit:\n\n    HDD \\\\.\\PhysicalDrive0 (MBR):\n      GetPartitionInfo == GeometryEx :  corrrect size? (includes tail)\n      Geometry   :  smaller than GeometryEx (no tail, maybe correct too?)\n      MyGetDiskFreeSpace : FAIL\n      Size correction is slow and block size (kClusterSize) must be small?\n\n    HDD partition \\\\.\\N: (NTFS):\n      MyGetDiskFreeSpace   :  Size of NTFS clusters. Same size can be calculated after correction\n      GetPartitionInfo     :  size of partition data: NTFS clusters + TAIL; TAIL contains extra empty sectors and copy of first sector of NTFS\n      Geometry / CdRomGeometry / GeometryEx :  size of HDD (not that partition)\n\n    CD-ROM drive (ISO):\n      MyGetDiskFreeSpace   :  correct size. Same size can be calculated after correction\n      Geometry == CdRomGeometry  :  smaller than corrrect size\n      GetPartitionInfo == GeometryEx :  larger than corrrect size\n\n    Floppy \\\\.\\a: (FAT):\n      Geometry :  correct size.\n      CdRomGeometry / GeometryEx / GetPartitionInfo / MyGetDiskFreeSpace - FAIL\n      correction works OK for FAT.\n      correction works OK for non-FAT, if kClusterSize = 512.\n  */\n\n  if (GetPartitionInfo(&partInfo))\n  {\n    Size = (UInt64)partInfo.PartitionLength.QuadPart;\n    SizeDefined = true;\n    needCorrectSize = false;\n    if ((s)[0] == '\\\\' && (s)[1] == '\\\\' && (s)[2] == '.' && (s)[3] == '\\\\' && (s)[5] == ':' && (s)[6] == 0)\n    {\n      FChar path[4] = { s[4], ':', '\\\\', 0 };\n      UInt64 clusterSize, totalSize, freeSize;\n      if (NSystem::MyGetDiskFreeSpace(path, clusterSize, totalSize, freeSize))\n        Size = totalSize;\n      else\n        needCorrectSize = true;\n    }\n  }\n  \n  if (!SizeDefined)\n  {\n    my_DISK_GEOMETRY_EX geomEx;\n    SizeDefined = GetGeometryEx(&geomEx);\n    if (SizeDefined)\n      Size = (UInt64)geomEx.DiskSize.QuadPart;\n    else\n    {\n      DISK_GEOMETRY geom;\n      SizeDefined = GetGeometry(&geom);\n      if (!SizeDefined)\n        SizeDefined = GetCdRomGeometry(&geom);\n      if (SizeDefined)\n        Size = (UInt64)geom.Cylinders.QuadPart * geom.TracksPerCylinder * geom.SectorsPerTrack * geom.BytesPerSector;\n    }\n  }\n  \n  if (needCorrectSize && SizeDefined && Size != 0)\n  {\n    CorrectDeviceSize();\n    SeekToBegin();\n  }\n\n  // SeekToBegin();\n  #endif\n}\n\n// ((desiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)) == 0 &&\n\n#define MY_DEVICE_EXTRA_CODE \\\n  IsDeviceFile = IsDevicePath(fileName); \\\n  CalcDeviceSize(fileName);\n#else\n#define MY_DEVICE_EXTRA_CODE\n#endif\n\nbool CInFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\n{\n  DWORD desiredAccess = GENERIC_READ;\n  \n  #ifdef _WIN32\n  if (PreserveATime)\n    desiredAccess |= FILE_WRITE_ATTRIBUTES;\n  #endif\n  \n  bool res = Create(fileName, desiredAccess, shareMode, creationDisposition, flagsAndAttributes);\n\n  #ifdef _WIN32\n  if (res && PreserveATime)\n  {\n    FILETIME ft;\n    ft.dwHighDateTime = ft.dwLowDateTime = 0xFFFFFFFF;\n    ::SetFileTime(_handle, NULL, &ft, NULL);\n  }\n  #endif\n\n  MY_DEVICE_EXTRA_CODE\n  return res;\n}\n\nbool CInFile::OpenShared(CFSTR fileName, bool shareForWrite)\n{ return Open(fileName, FILE_SHARE_READ | (shareForWrite ? FILE_SHARE_WRITE : 0), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); }\n\nbool CInFile::Open(CFSTR fileName)\n  { return OpenShared(fileName, false); }\n\n// ReadFile and WriteFile functions in Windows have BUG:\n// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)\n// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES\n// (Insufficient system resources exist to complete the requested service).\n\n// Probably in some version of Windows there are problems with other sizes:\n// for 32 MB (maybe also for 16 MB).\n// And message can be \"Network connection was lost\"\n\nstatic const UInt32 kChunkSizeMax = 1 << 22;\n\nbool CInFile::Read1(void *data, UInt32 size, UInt32 &processedSize) throw()\n{\n  DWORD processedLoc = 0;\n  const bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL));\n  processedSize = (UInt32)processedLoc;\n  return res;\n}\n\nbool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw()\n{\n#if 0\n  const UInt32 chunkSizeMax = (0 || IsStdStream) ? (1 << 20) : kChunkSizeMax;\n  if (size > chunkSizeMax)\n      size = chunkSizeMax;\n#else\n  if (size > kChunkSizeMax)\n      size = kChunkSizeMax;\n#endif\n  return Read1(data, size, processedSize);\n}\n\nbool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) throw()\n{\n  processedSize = 0;\n  do\n  {\n    UInt32 processedLoc = 0;\n    const bool res = ReadPart(data, size, processedLoc);\n    processedSize += processedLoc;\n    if (!res)\n      return false;\n    if (processedLoc == 0)\n      return true;\n    data = (void *)((Byte *)data + processedLoc);\n    size -= processedLoc;\n  }\n  while (size);\n  return true;\n}\n\nbool CInFile::ReadFull(void *data, size_t size, size_t &processedSize) throw()\n{\n  processedSize = 0;\n  do\n  {\n    UInt32 processedLoc = 0;\n    const UInt32 sizeLoc = (size > kChunkSizeMax ? (UInt32)kChunkSizeMax : (UInt32)size);\n    const bool res = Read1(data, sizeLoc, processedLoc);\n    processedSize += processedLoc;\n    if (!res)\n      return false;\n    if (processedLoc == 0)\n      return true;\n    data = (void *)((Byte *)data + processedLoc);\n    size -= processedLoc;\n  }\n  while (size);\n  return true;\n}\n\n// ---------- COutFile ---------\n\nbool COutFile::Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes)\n  { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); }\n\nbool COutFile::Open_Disposition(CFSTR fileName, DWORD creationDisposition)\n  { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); }\n\nbool COutFile::Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes)\n  { return Open(fileName, FILE_SHARE_READ, CREATE_ALWAYS, flagsAndAttributes); }\n\nbool COutFile::SetTime(const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) throw()\n  { return BOOLToBool(::SetFileTime(_handle, cTime, aTime, mTime)); }\n\nbool COutFile::SetMTime(const FILETIME *mTime) throw() {  return SetTime(NULL, NULL, mTime); }\n\nbool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw()\n{\n  if (size > kChunkSizeMax)\n    size = kChunkSizeMax;\n  DWORD processedLoc = 0;\n  bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL));\n  processedSize = (UInt32)processedLoc;\n  return res;\n}\n\nbool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) throw()\n{\n  processedSize = 0;\n  do\n  {\n    UInt32 processedLoc = 0;\n    const bool res = WritePart(data, size, processedLoc);\n    processedSize += processedLoc;\n    if (!res)\n      return false;\n    if (processedLoc == 0)\n      return true;\n    data = (const void *)((const Byte *)data + processedLoc);\n    size -= processedLoc;\n  }\n  while (size);\n  return true;\n}\n\nbool COutFile::WriteFull(const void *data, size_t size) throw()\n{\n  do\n  {\n    UInt32 processedLoc = 0;\n    const UInt32 sizeCur = (size > kChunkSizeMax ? kChunkSizeMax : (UInt32)size);\n    if (!WritePart(data, sizeCur, processedLoc))\n      return false;\n    if (processedLoc == 0)\n      return (size == 0);\n    data = (const void *)((const Byte *)data + processedLoc);\n    size -= processedLoc;\n  }\n  while (size);\n  return true;\n}\n\nbool COutFile::SetEndOfFile() throw() { return BOOLToBool(::SetEndOfFile(_handle)); }\n\nbool COutFile::SetLength(UInt64 length) throw()\n{\n  UInt64 newPosition;\n  if (!Seek(length, newPosition))\n    return false;\n  if (newPosition != length)\n    return false;\n  return SetEndOfFile();\n}\n\nbool COutFile::SetLength_KeepPosition(UInt64 length) throw()\n{\n  UInt64 currentPos = 0;\n  if (!GetPosition(currentPos))\n    return false;\n  DWORD lastError = 0;\n  const bool result = SetLength(length);\n  if (!result)\n    lastError = GetLastError();\n  UInt64 currentPos2;\n  const bool result2 = Seek(currentPos, currentPos2);\n  if (lastError != 0)\n    SetLastError(lastError);\n  return (result && result2);\n}\n\n}}}\n\n#else // _WIN32\n\n\n// POSIX\n\n#include <fcntl.h>\n#include <unistd.h>\n\nnamespace NWindows {\nnamespace NFile {\n\nnamespace NDir {\nbool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime);\n}\n\nnamespace NIO {\n\nbool CFileBase::OpenBinary(const char *name, int flags, mode_t mode)\n{\n  #ifdef O_BINARY\n  flags |= O_BINARY;\n  #endif\n\n  Close();\n  _handle = ::open(name, flags, mode);\n  return _handle != -1;\n\n  /*\n  if (_handle == -1)\n    return false;\n  if (IsString1PrefixedByString2(name, \"/dev/\"))\n  {\n    // /dev/sda\n    // IsDeviceFile = true; // for debug\n    // SizeDefined = false;\n    // SizeDefined = (GetDeviceSize_InBytes(Size) == 0);\n  }\n  return true;\n  */\n}\n\nbool CFileBase::Close()\n{\n  if (_handle == -1)\n    return true;\n  if (close(_handle) != 0)\n    return false;\n  _handle = -1;\n  /*\n  IsDeviceFile = false;\n  SizeDefined = false;\n  */\n  return true;\n}\n\nbool CFileBase::GetLength(UInt64 &length) const\n{\n  length = 0;\n  // length = (UInt64)(Int64)-1; // for debug\n  const off_t curPos = seekToCur();\n  if (curPos == -1)\n    return false;\n  const off_t lengthTemp = seek(0, SEEK_END);\n  seek(curPos, SEEK_SET);\n  length = (UInt64)lengthTemp;\n\n  /*\n  // 22.00:\n  if (lengthTemp == 1)\n  if (IsDeviceFile && SizeDefined)\n  {\n    length = Size;\n    return true;\n  }\n  */\n\n  return (lengthTemp != -1);\n}\n\noff_t CFileBase::seek(off_t distanceToMove, int moveMethod) const\n{\n  /*\n  if (IsDeviceFile && SizeDefined && moveMethod == SEEK_END)\n  {\n    printf(\"\\n seek : IsDeviceFile moveMethod = %d distanceToMove = %ld\\n\", moveMethod, distanceToMove);\n    distanceToMove += Size;\n    moveMethod = SEEK_SET;\n  }\n  */\n\n  // printf(\"\\nCFileBase::seek() moveMethod = %d, distanceToMove = %lld\", moveMethod, (long long)distanceToMove);\n  // off_t res = ::lseek(_handle, distanceToMove, moveMethod);\n  // printf(\"\\n lseek : moveMethod = %d distanceToMove = %ld\\n\", moveMethod, distanceToMove);\n  return ::lseek(_handle, distanceToMove, moveMethod);\n  // return res;\n}\n\noff_t CFileBase::seekToBegin() const throw()\n{\n  return seek(0, SEEK_SET);\n}\n\noff_t CFileBase::seekToCur() const throw()\n{\n  return seek(0, SEEK_CUR);\n}\n\n/*\nbool CFileBase::SeekToBegin() const throw()\n{\n  return (::seek(0, SEEK_SET) != -1);\n}\n*/\n\n\n/////////////////////////\n// CInFile\n\nbool CInFile::Open(const char *name)\n{\n  return CFileBase::OpenBinary(name, O_RDONLY);\n}\n\nbool CInFile::OpenShared(const char *name, bool)\n{\n  return Open(name);\n}\n\n\n/*\nint CFileBase::my_ioctl_BLKGETSIZE64(unsigned long long *numBlocks)\n{\n  // we can read \"/sys/block/sda/size\" \"/sys/block/sda/sda1/size\" - partition\n  // #include <linux/fs.h>\n  return ioctl(_handle, BLKGETSIZE64, numBlocks);\n  // in block size\n}\n\nint CFileBase::GetDeviceSize_InBytes(UInt64 &size)\n{\n  size = 0;\n  unsigned long long numBlocks;\n  int res = my_ioctl_BLKGETSIZE64(&numBlocks);\n  if (res == 0)\n    size = numBlocks; // another blockSize s possible?\n  printf(\"\\nGetDeviceSize_InBytes res = %d, size = %lld\\n\", res, (long long)size);\n  return res;\n}\n*/\n\n/*\nOn Linux (32-bit and 64-bit):\nread(), write() (and similar system calls) will transfer at most\n0x7ffff000 = (2GiB - 4 KiB) bytes, returning the number of bytes actually transferred.\n*/\n\nstatic const size_t kChunkSizeMax = ((size_t)1 << 22);\n\nssize_t CInFile::read_part(void *data, size_t size) throw()\n{\n  if (size > kChunkSizeMax)\n    size = kChunkSizeMax;\n  return ::read(_handle, data, size);\n}\n\nbool CInFile::ReadFull(void *data, size_t size, size_t &processed) throw()\n{\n  processed = 0;\n  do\n  {\n    const ssize_t res = read_part(data, size);\n    if (res < 0)\n      return false;\n    if (res == 0)\n      break;\n    data = (void *)((Byte *)data + (size_t)res);\n    processed += (size_t)res;\n    size -= (size_t)res;\n  }\n  while (size);\n  return true;\n}\n\n\n/////////////////////////\n// COutFile\n\nbool COutFile::OpenBinary_forWrite_oflag(const char *name, int oflag)\n{\n  Path = name; // change it : set it only if open is success.\n  return OpenBinary(name, oflag, mode_for_Create);\n}\n\n\n/*\n  windows           exist  non-exist  posix\n  CREATE_NEW        Fail   Create     O_CREAT | O_EXCL\n  CREATE_ALWAYS     Trunc  Create     O_CREAT | O_TRUNC\n  OPEN_ALWAYS       Open   Create     O_CREAT\n  OPEN_EXISTING     Open   Fail       0\n  TRUNCATE_EXISTING Trunc  Fail       O_TRUNC ???\n\n  // O_CREAT = If the file exists, this flag has no effect except as noted under O_EXCL below.\n  // If O_CREAT and O_EXCL are set, open() shall fail if the file exists.\n  // O_TRUNC : If the file exists and the file is successfully opened, its length shall be truncated to 0.\n*/\nbool COutFile::Open_EXISTING(const char *name)\n  { return OpenBinary_forWrite_oflag(name, O_WRONLY); }\nbool COutFile::Create_ALWAYS(const char *name)\n  { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_TRUNC); }\nbool COutFile::Create_NEW(const char *name)\n  { return OpenBinary_forWrite_oflag(name, O_WRONLY | O_CREAT | O_EXCL);  }\nbool COutFile::Create_ALWAYS_or_Open_ALWAYS(const char *name, bool createAlways)\n{\n  return OpenBinary_forWrite_oflag(name,\n      createAlways ?\n        O_WRONLY | O_CREAT | O_TRUNC :\n        O_WRONLY | O_CREAT);\n}\n/*\nbool COutFile::Create_ALWAYS_or_NEW(const char *name, bool createAlways)\n{\n  return OpenBinary_forWrite_oflag(name,\n      createAlways ?\n        O_WRONLY | O_CREAT | O_TRUNC :\n        O_WRONLY | O_CREAT | O_EXCL);\n}\nbool COutFile::Open_Disposition(const char *name, DWORD creationDisposition)\n{\n  int flag;\n  switch (creationDisposition)\n  {\n    case CREATE_NEW:        flag = O_WRONLY | O_CREAT | O_EXCL;  break;\n    case CREATE_ALWAYS:     flag = O_WRONLY | O_CREAT | O_TRUNC;  break;\n    case OPEN_ALWAYS:       flag = O_WRONLY | O_CREAT;  break;\n    case OPEN_EXISTING:     flag = O_WRONLY;  break;\n    case TRUNCATE_EXISTING: flag = O_WRONLY | O_TRUNC; break;\n    default:\n      SetLastError(EINVAL);\n      return false;\n  }\n  return OpenBinary_forWrite_oflag(name, flag);\n}\n*/\n\nssize_t COutFile::write_part(const void *data, size_t size) throw()\n{\n  if (size > kChunkSizeMax)\n    size = kChunkSizeMax;\n  return ::write(_handle, data, size);\n}\n\nssize_t COutFile::write_full(const void *data, size_t size, size_t &processed) throw()\n{\n  processed = 0;\n  do\n  {\n    const ssize_t res = write_part(data, size);\n    if (res < 0)\n      return res;\n    if (res == 0)\n      break;\n    data = (const void *)((const Byte *)data + (size_t)res);\n    processed += (size_t)res;\n    size -= (size_t)res;\n  }\n  while (size);\n  return (ssize_t)processed;\n}\n\nbool COutFile::SetLength(UInt64 length) throw()\n{\n  const off_t len2 = (off_t)length;\n  if ((Int64)length != len2)\n  {\n    SetLastError(EFBIG);\n    return false;\n  }\n  // The value of the seek pointer shall not be modified by a call to ftruncate().\n  const int iret = ftruncate(_handle, len2);\n  return (iret == 0);\n}\n\nbool COutFile::Close()\n{\n  const bool res = CFileBase::Close();\n  if (!res)\n    return res;\n  if (CTime_defined || ATime_defined || MTime_defined)\n  {\n    /* bool res2 = */ NWindows::NFile::NDir::SetDirTime(Path,\n        CTime_defined ? &CTime : NULL,\n        ATime_defined ? &ATime : NULL,\n        MTime_defined ? &MTime : NULL);\n  }\n  return res;\n}\n\nbool COutFile::SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw()\n{\n  // On some OS (cygwin, MacOSX ...), you must close the file before updating times\n  // return true;\n\n  if (cTime) { CTime = *cTime; CTime_defined = true; } else CTime_defined = false;\n  if (aTime) { ATime = *aTime; ATime_defined = true; } else ATime_defined = false;\n  if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;\n  return true;\n\n  /*\n  struct timespec times[2];\n  UNUSED_VAR(cTime)\n  if (!aTime && !mTime)\n    return true;\n  bool needChange;\n  needChange  = FiTime_To_timespec(aTime, times[0]);\n  needChange |= FiTime_To_timespec(mTime, times[1]);\n  if (!needChange)\n    return true;\n  return futimens(_handle, times) == 0;\n  */\n}\n\nbool COutFile::SetMTime(const CFiTime *mTime) throw()\n{\n  if (mTime) { MTime = *mTime; MTime_defined = true; } else MTime_defined = false;\n  return true;\n}\n\n}}}\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileIO.h",
    "content": "﻿// Windows/FileIO.h\n\n#ifndef ZIP7_INC_WINDOWS_FILE_IO_H\n#define ZIP7_INC_WINDOWS_FILE_IO_H\n\n#include \"../Common/MyWindows.h\"\n\n#define Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT  (0xA0000003L)\n#define Z7_WIN_IO_REPARSE_TAG_SYMLINK      (0xA000000CL)\n#define Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK   (0xA000001DL)\n\n#define Z7_WIN_SYMLINK_FLAG_RELATIVE 1\n\n#define Z7_WIN_LX_SYMLINK_VERSION_2 2\n\n#ifdef _WIN32\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n#include <winioctl.h>\n#endif\n\n#else\n\n#include <sys/types.h>\n#include <sys/stat.h>\n\n#endif\n\n#include \"../Common/MyString.h\"\n#include \"../Common/MyBuffer.h\"\n\n#include \"../Windows/TimeUtils.h\"\n\n#include \"Defs.h\"\n\nHRESULT GetLastError_noZero_HRESULT();\n\n#define my_FSCTL_SET_REPARSE_POINT     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER\n#define my_FSCTL_GET_REPARSE_POINT     CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)     // REPARSE_DATA_BUFFER\n#define my_FSCTL_DELETE_REPARSE_POINT  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) // REPARSE_DATA_BUFFER\n\nnamespace NWindows {\nnamespace NFile {\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n/*\n  in:  (CByteBuffer &dest) is empty\n  in:  (path) uses Windows path separator (\\).\n  out: (path) uses   Linux path separator (/).\n       if (isAbsPath == true), then \"c:\\\\\" prefix is replaced to \"/mnt/c/\" prefix\n*/\nvoid Convert_WinPath_to_WslLinuxPath(FString &path, bool convertDrivePath);\n// (path) must use Linux path separator (/).\nvoid FillLinkData_WslLink(CByteBuffer &dest, const wchar_t *path);\n\n/*\n  in:  (CByteBuffer &dest) is empty\n  if (isSymLink == false) : MOUNT_POINT : (path) must be absolute.\n  if (isSymLink == true)  : SYMLINK : Windows\n  (path) must use Windows path separator (\\).\n  (path) must be without link \"\\\\??\\\\\" prefix.\n  link \"\\\\??\\\\\" prefix will be added inside FillLinkData(), if path is absolute.\n*/\nvoid FillLinkData_WinLink(CByteBuffer &dest, const wchar_t *path, bool isSymLink);\n// in: (CByteBuffer &dest) is empty\ninline void FillLinkData(CByteBuffer &dest, const wchar_t *path, bool isSymLink, bool isWSL)\n{\n  if (isWSL)\n    FillLinkData_WslLink(dest, path);\n  else\n    FillLinkData_WinLink(dest, path, isSymLink);\n}\n#endif\n\nstruct CReparseShortInfo\n{\n  unsigned Offset;\n  unsigned Size;\n\n  bool Parse(const Byte *p, size_t size);\n};\n\nstruct CReparseAttr\n{\n  UInt32 Tag;\n  UInt32 Flags;\n  UString SubsName;\n  UString PrintName;\n  AString WslName;\n\n  bool HeaderError;\n  bool TagIsUnknown;\n  bool MinorError;\n  DWORD ErrorCode;\n\n  CReparseAttr(): Tag(0), Flags(0) {}\n\n  // returns (true) and (ErrorCode = 0), if (it's correct known link)\n  // returns (false) and (ErrorCode = ERROR_REPARSE_TAG_INVALID), if unknown tag\n  bool Parse(const Byte *p, size_t size);\n\n  bool IsMountPoint()  const { return Tag == Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT; } // it's Junction\n  bool IsSymLink_Win() const { return Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK; }\n  bool IsSymLink_WSL() const { return Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK; }\n\n  // note: \"/dir1/path\" is marked as relative.\n  bool IsRelative_Win() const { return Flags == Z7_WIN_SYMLINK_FLAG_RELATIVE; }\n\n  bool IsRelative_WSL() const\n  {\n    return WslName[0] != '/'; // WSL uses unix path separator\n  }\n\n  bool IsOkNamePair() const;\n  UString GetPath() const;\n};\n\n#ifdef _WIN32\n#define CFiInfo BY_HANDLE_FILE_INFORMATION\n#define ST_MTIME(st) (st).ftLastWriteTime\n#else\n#define CFiInfo stat\n#endif\n\n#ifdef _WIN32\n\nnamespace NIO {\n\nbool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo = NULL);\nbool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);\nbool DeleteReparseData(CFSTR path);\n\nclass CFileBase  MY_UNCOPYABLE\n{\nprotected:\n  HANDLE _handle;\n  \n  bool Create(CFSTR path, DWORD desiredAccess,\n      DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\n\npublic:\n\n  bool DeviceIoControl(DWORD controlCode, LPVOID inBuffer, DWORD inSize,\n      LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned, LPOVERLAPPED overlapped = NULL) const\n  {\n    return BOOLToBool(::DeviceIoControl(_handle, controlCode, inBuffer, inSize,\n        outBuffer, outSize, bytesReturned, overlapped));\n  }\n\n  bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize, LPDWORD bytesReturned) const\n  {\n    return DeviceIoControl(controlCode, NULL, 0, outBuffer, outSize, bytesReturned);\n  }\n\n  bool DeviceIoControlOut(DWORD controlCode, LPVOID outBuffer, DWORD outSize) const\n  {\n    DWORD bytesReturned;\n    return DeviceIoControlOut(controlCode, outBuffer, outSize, &bytesReturned);\n  }\n\npublic:\n  bool PreserveATime;\n#if 0\n  bool IsStdStream;\n  bool IsStdPipeStream;\n#endif\n#ifdef Z7_DEVICE_FILE\n  bool IsDeviceFile;\n  bool SizeDefined;\n  UInt64 Size; // it can be larger than real available size\n#endif\n\n  CFileBase():\n    _handle(INVALID_HANDLE_VALUE),\n    PreserveATime(false)\n#if 0\n    , IsStdStream(false),\n    , IsStdPipeStream(false)\n#endif\n    {}\n  ~CFileBase() { Close(); }\n\n  HANDLE GetHandle() const { return _handle; }\n\n  // void Detach() { _handle = INVALID_HANDLE_VALUE; }\n\n  bool Close() throw();\n\n  bool GetPosition(UInt64 &position) const throw();\n  bool GetLength(UInt64 &length) const throw();\n\n  bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const throw();\n  bool Seek(UInt64 position, UInt64 &newPosition) const throw();\n  bool SeekToBegin() const throw();\n  bool SeekToEnd(UInt64 &newPosition) const throw();\n  \n  bool GetFileInformation(BY_HANDLE_FILE_INFORMATION *info) const\n    { return BOOLToBool(GetFileInformationByHandle(_handle, info)); }\n\n  static bool GetFileInformation(CFSTR path, BY_HANDLE_FILE_INFORMATION *info)\n  {\n    // probably it can work for complex paths: unsupported by another things\n    NIO::CFileBase file;\n    if (!file.Create(path, 0, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS))\n      return false;\n    return file.GetFileInformation(info);\n  }\n};\n\n#ifndef UNDER_CE\n#define IOCTL_CDROM_BASE  FILE_DEVICE_CD_ROM\n#define IOCTL_CDROM_GET_DRIVE_GEOMETRY  CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)\n// #define IOCTL_CDROM_MEDIA_REMOVAL  CTL_CODE(IOCTL_CDROM_BASE, 0x0201, METHOD_BUFFERED, FILE_READ_ACCESS)\n\n// IOCTL_DISK_GET_DRIVE_GEOMETRY_EX works since WinXP\n#define my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX  CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\nstruct my_DISK_GEOMETRY_EX\n{\n  DISK_GEOMETRY Geometry;\n  LARGE_INTEGER DiskSize;\n  BYTE Data[1];\n};\n#endif\n\nclass CInFile: public CFileBase\n{\n  #ifdef Z7_DEVICE_FILE\n\n  #ifndef UNDER_CE\n  \n  bool GetGeometry(DISK_GEOMETRY *res) const\n    { return DeviceIoControlOut(IOCTL_DISK_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }\n\n  bool GetGeometryEx(my_DISK_GEOMETRY_EX *res) const\n    { return DeviceIoControlOut(my_IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, res, sizeof(*res)); }\n\n  bool GetCdRomGeometry(DISK_GEOMETRY *res) const\n    { return DeviceIoControlOut(IOCTL_CDROM_GET_DRIVE_GEOMETRY, res, sizeof(*res)); }\n  \n  bool GetPartitionInfo(PARTITION_INFORMATION *res)\n    { return DeviceIoControlOut(IOCTL_DISK_GET_PARTITION_INFO, LPVOID(res), sizeof(*res)); }\n  \n  #endif\n\n  void CorrectDeviceSize();\n  void CalcDeviceSize(CFSTR name);\n  \n  #endif\n\npublic:\n  bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\n  bool OpenShared(CFSTR fileName, bool shareForWrite);\n  bool Open(CFSTR fileName);\n\n#if 0\n  bool AttachStdIn()\n  {\n    IsDeviceFile = false;\n    const HANDLE h = GetStdHandle(STD_INPUT_HANDLE);\n    if (h == INVALID_HANDLE_VALUE || !h)\n      return false;\n    IsStdStream = true;\n    IsStdPipeStream = true;\n    _handle = h;\n    return true;\n  }\n#endif\n\n  #ifndef UNDER_CE\n\n  bool Open_for_ReadAttributes(CFSTR fileName)\n  {\n    return Create(fileName, FILE_READ_ATTRIBUTES,\n        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,\n        OPEN_EXISTING,\n        FILE_FLAG_BACKUP_SEMANTICS);\n    // we must use (FILE_FLAG_BACKUP_SEMANTICS) to open handle of directory.\n  }\n\n  bool Open_for_FileRenameInformation(CFSTR fileName)\n  {\n    return Create(fileName, DELETE | SYNCHRONIZE | GENERIC_READ,\n        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,\n        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL);\n    // we must use (FILE_FLAG_BACKUP_SEMANTICS) to open handle of directory.\n  }\n\n  bool OpenReparse(CFSTR fileName)\n  {\n    // 17.02 fix: to support Windows XP compatibility junctions:\n    //   we use Create() with (desiredAccess = 0) instead of Open() with GENERIC_READ\n    return\n        Create(fileName, 0,\n        // Open(fileName,\n        FILE_SHARE_READ, OPEN_EXISTING,\n        FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS);\n  }\n  \n  #endif\n\n  bool Read1(void *data, UInt32 size, UInt32 &processedSize) throw();\n  bool ReadPart(void *data, UInt32 size, UInt32 &processedSize) throw();\n  bool Read(void *data, UInt32 size, UInt32 &processedSize) throw();\n  bool ReadFull(void *data, size_t size, size_t &processedSize) throw();\n};\n\nclass COutFile: public CFileBase\n{\n  bool Open_Disposition(CFSTR fileName, DWORD creationDisposition);\npublic:\n  bool Open(CFSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes);\n  bool Open_EXISTING(CFSTR fileName)\n    { return Open_Disposition(fileName, OPEN_EXISTING); }\n  bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways)\n    { return Open_Disposition(fileName, createAlways ? CREATE_ALWAYS : OPEN_ALWAYS); }\n  bool Create_ALWAYS_or_NEW(CFSTR fileName, bool createAlways)\n    { return Open_Disposition(fileName, createAlways ? CREATE_ALWAYS : CREATE_NEW); }\n  bool Create_ALWAYS(CFSTR fileName)\n    { return Open_Disposition(fileName, CREATE_ALWAYS); }\n  bool Create_NEW(CFSTR fileName)\n    { return Open_Disposition(fileName, CREATE_NEW); }\n  \n  bool Create_ALWAYS_with_Attribs(CFSTR fileName, DWORD flagsAndAttributes);\n\n  bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw();\n  bool SetMTime(const CFiTime *mTime) throw();\n  bool WritePart(const void *data, UInt32 size, UInt32 &processedSize) throw();\n  bool Write(const void *data, UInt32 size, UInt32 &processedSize) throw();\n  bool WriteFull(const void *data, size_t size) throw();\n  bool SetEndOfFile() throw();\n  bool SetLength(UInt64 length) throw();\n  bool SetLength_KeepPosition(UInt64 length) throw();\n};\n\n}\n\n\n#else // _WIN32\n\nnamespace NIO {\n\nbool GetReparseData(CFSTR path, CByteBuffer &reparseData);\n// bool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size);\n\n// parameters are in reverse order of symlink() function !!!\nbool SetSymLink(CFSTR from, CFSTR to);\nbool SetSymLink_UString(CFSTR from, const UString &to);\n\n\nclass CFileBase\n{\nprotected:\n  int _handle;\n\n  /*\n  bool IsDeviceFile;\n  bool SizeDefined;\n  UInt64 Size; // it can be larger than real available size\n  */\n\n  bool OpenBinary(const char *name, int flags, mode_t mode = 0666);\npublic:\n  bool PreserveATime;\n#if 0\n  bool IsStdStream;\n#endif\n\n  CFileBase(): _handle(-1), PreserveATime(false)\n#if 0\n    , IsStdStream(false)\n#endif\n  {}\n  ~CFileBase() { Close(); }\n  // void Detach() { _handle = -1; }\n  bool Close();\n  bool GetLength(UInt64 &length) const;\n  off_t seek(off_t distanceToMove, int moveMethod) const;\n  off_t seekToBegin() const throw();\n  off_t seekToCur() const throw();\n  // bool SeekToBegin() throw();\n  int my_fstat(struct stat *st) const  { return fstat(_handle, st); }\n  /*\n  int my_ioctl_BLKGETSIZE64(unsigned long long *val);\n  int GetDeviceSize_InBytes(UInt64 &size);\n  void CalcDeviceSize(CFSTR s);\n  */\n};\n\nclass CInFile: public CFileBase\n{\npublic:\n  bool Open(const char *name);\n  bool OpenShared(const char *name, bool shareForWrite);\n#if 0\n  bool AttachStdIn()\n  {\n    _handle = GetStdHandle(STD_INPUT_HANDLE);\n    if (_handle == INVALID_HANDLE_VALUE || !_handle)\n      return false;\n    IsStdStream = true;\n  }\n#endif\n  ssize_t read_part(void *data, size_t size) throw();\n  // ssize_t read_full(void *data, size_t size, size_t &processed);\n  bool ReadFull(void *data, size_t size, size_t &processedSize) throw();\n};\n\nclass COutFile: public CFileBase\n{\n  bool CTime_defined;\n  bool ATime_defined;\n  bool MTime_defined;\n  CFiTime CTime;\n  CFiTime ATime;\n  CFiTime MTime;\n\n  AString Path;\n  ssize_t write_part(const void *data, size_t size) throw();\n  bool OpenBinary_forWrite_oflag(const char *name, int oflag);\npublic:\n  mode_t mode_for_Create;\n\n  COutFile():\n      CTime_defined(false),\n      ATime_defined(false),\n      MTime_defined(false),\n      mode_for_Create(0666)\n      {}\n\n  bool Close();\n\n  bool Open_EXISTING(CFSTR fileName);\n  bool Create_ALWAYS_or_Open_ALWAYS(CFSTR fileName, bool createAlways);\n  bool Create_ALWAYS(CFSTR fileName);\n  bool Create_NEW(CFSTR fileName);\n  // bool Create_ALWAYS_or_NEW(CFSTR fileName, bool createAlways);\n  // bool Open_Disposition(const char *name, DWORD creationDisposition);\n\n  ssize_t write_full(const void *data, size_t size, size_t &processed) throw();\n\n  bool WriteFull(const void *data, size_t size) throw()\n  {\n    size_t processed;\n    ssize_t res = write_full(data, size, processed);\n    if (res == -1)\n      return false;\n    return processed == size;\n  }\n\n  bool SetLength(UInt64 length) throw();\n  bool SetLength_KeepPosition(UInt64 length) throw()\n  {\n    return SetLength(length);\n  }\n  bool SetTime(const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime) throw();\n  bool SetMTime(const CFiTime *mTime) throw();\n};\n\n}\n\n#endif  // _WIN32\n\n}}\n\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileLink.cpp",
    "content": "﻿// Windows/FileLink.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/CpuArch.h\"\n\n#ifndef _WIN32\n#include <unistd.h>\n#endif\n\n#ifdef Z7_DEVICE_FILE\n#include \"../../C/Alloc.h\"\n#endif\n\n#include \"../Common/UTFConvert.h\"\n#include \"../Common/StringConvert.h\"\n\n#include \"FileDir.h\"\n#include \"FileFind.h\"\n#include \"FileIO.h\"\n#include \"FileName.h\"\n\n#ifdef Z7_OLD_WIN_SDK\n#ifndef ERROR_INVALID_REPARSE_DATA\n#define ERROR_INVALID_REPARSE_DATA       4392L\n#endif\n#ifndef ERROR_REPARSE_TAG_INVALID\n#define ERROR_REPARSE_TAG_INVALID        4393L\n#endif\n#endif\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\nnamespace NFile {\n\nusing namespace NName;\n\n/*\nWin10 Junctions/SymLinks:\n  - (/) slash doesn't work as path separator\n  - Win10 preinstalled junctions don't use tail backslash, but tail backslashes also work.\n  - double backslash works only after drive prefix \"c:\\\\dir1\\dir2\\\",\n    and doesn't work in another places.\n  - absolute path without \\??\\ prefix doesn't work\n  - absolute path \"c:\" doesn't work\n*/\n\n/*\n  Reparse Points (Junctions and Symbolic Links):\n  struct\n  {\n    UInt32 Tag;\n    UInt16 Size;     // not including starting 8 bytes\n    UInt16 Reserved; // = 0, DOCs: // Length, in bytes, of the unparsed portion of\n       // the file name pointed to by the FileName member of the associated file object.\n       // This member is only valid for create operations when the I/O fails with STATUS_REPARSE.\n    \n    UInt16 SubstituteOffset; // offset in bytes from  start of namesChars\n    UInt16 SubstituteLen;    // size in bytes, it doesn't include tailed NUL\n    UInt16 PrintOffset;      // offset in bytes from  start of namesChars\n    UInt16 PrintLen;         // size in bytes, it doesn't include tailed NUL\n    \n    [UInt32] Flags;  // for Symbolic Links only.\n    \n    UInt16 namesChars[]\n  }\n\n  MOUNT_POINT (Junction point):\n    1) there is NUL wchar after path\n    2) Default Order in table:\n         Substitute Path\n         Print Path\n    3) pathnames can not contain dot directory names\n\n  SYMLINK:\n    1) there is no NUL wchar after path\n    2) Default Order in table:\n         Print Path\n         Substitute Path\n\nDOCS:\n  The print name SHOULD be an informative pathname, suitable for display\n  to a user, that also identifies the target of the mount point.\n  Neither of these pathnames can contain dot directory names.\n\nreparse tags, with the exception of IO_REPARSE_TAG_SYMLINK,\nare processed on the server and are not processed by a client\nafter transmission over the wire.\nClients SHOULD treat associated reparse data as opaque data.\n*/\n\n/*\nWin10 WSL2:\nadmin rights + sudo: it creates normal windows symbolic link.\nin another cases   : it creates IO_REPARSE_TAG_LX_SYMLINK repare point.\n*/\n\n/*\nstatic const UInt32 kReparseFlags_Alias       = (1 << 29);\nstatic const UInt32 kReparseFlags_HighLatency = (1 << 30);\nstatic const UInt32 kReparseFlags_Microsoft   = ((UInt32)1 << 31);\n\n#define Z7_WIN_IO_REPARSE_TAG_HSM          (0xC0000004L)\n#define Z7_WIN_IO_REPARSE_TAG_HSM2         (0x80000006L)\n#define Z7_WIN_IO_REPARSE_TAG_SIS          (0x80000007L)\n#define Z7_WIN_IO_REPARSE_TAG_WIM          (0x80000008L)\n#define Z7_WIN_IO_REPARSE_TAG_CSV          (0x80000009L)\n#define Z7_WIN_IO_REPARSE_TAG_DFS          (0x8000000AL)\n#define Z7_WIN_IO_REPARSE_TAG_DFSR         (0x80000012L)\n*/\n\n#define Get16(p) GetUi16(p)\n#define Get32(p) GetUi32(p)\n\nstatic const char * const k_LinkPrefix = \"\\\\??\\\\\";\nstatic const char * const k_LinkPrefix_UNC = \"\\\\??\\\\UNC\\\\\";\nstatic const unsigned k_LinkPrefix_Size = 4;\n\nstatic bool IsLinkPrefix(const wchar_t *s)\n{\n  return IsString1PrefixedByString2(s, k_LinkPrefix);\n}\n\n/*\nstatic const char * const k_VolumePrefix = \"Volume{\";\nstatic const bool IsVolumeName(const wchar_t *s)\n{\n  return IsString1PrefixedByString2(s, k_VolumePrefix);\n}\n*/\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n\n#define Set16(p, v) SetUi16(p, v)\n#define Set32(p, v) SetUi32(p, v)\n\nstatic void WriteString(Byte *dest, const wchar_t *path)\n{\n  for (;;)\n  {\n    const wchar_t c = *path++;\n    if (c == 0)\n      return;\n    Set16(dest, (UInt16)c)\n    dest += 2;\n  }\n}\n\n#ifdef _WIN32\nvoid Convert_WinPath_to_WslLinuxPath(FString &s, bool convertDrivePath)\n{\n  if (convertDrivePath && IsDrivePath(s))\n  {\n    FChar c = s[0];\n    c = MyCharLower_Ascii(c);\n    s.DeleteFrontal(2);\n    s.InsertAtFront(c);\n    s.Insert(0, FTEXT(\"/mnt/\"));\n  }\n  s.Replace(FCHAR_PATH_SEPARATOR, FTEXT('/'));\n}\n#endif\n\n\nstatic const unsigned k_Link_Size_Limit = 1u << 16; // 16-bit field is used for size.\n\nvoid FillLinkData_WslLink(CByteBuffer &dest, const wchar_t *path)\n{\n  // dest.Free(); // it's empty already\n  // WSL probably uses Replacement Character UTF-16 0xFFFD for unsupported characters?\n  AString utf;\n  ConvertUnicodeToUTF8(path, utf);\n  const unsigned size = 4 + utf.Len();\n  if (size >= k_Link_Size_Limit)\n    return;\n  dest.Alloc(8 + size);\n  Byte *p = dest;\n  Set32(p, Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK)\n  // Set32(p + 4, (UInt32)size)\n  Set16(p + 4, (UInt16)size)\n  Set16(p + 6, 0)\n  Set32(p + 8, Z7_WIN_LX_SYMLINK_VERSION_2)\n  memcpy(p + 12, utf.Ptr(), utf.Len());\n}\n\n\nvoid FillLinkData_WinLink(CByteBuffer &dest, const wchar_t *path, bool isSymLink)\n{\n  // dest.Free(); // it's empty already\n  bool isAbs = false;\n  if (IS_PATH_SEPAR(path[0]))\n  {\n    // root paths \"\\dir1\\path\" are marked as relative\n    if (IS_PATH_SEPAR(path[1]))\n      isAbs = true;\n  }\n  else\n    isAbs = IsAbsolutePath(path);\n  if (!isAbs && !isSymLink)\n  {\n    // Win10 allows us to create relative MOUNT_POINT.\n    // But relative MOUNT_POINT will not work when accessing it.\n    // So we prevent useless creation of a relative MOUNT_POINT.\n    return;\n  }\n\n  bool needPrintName = true;\n  UString subs (path);\n  if (isAbs)\n  {\n    const bool isSuperPath = IsSuperPath(path);\n    if (!isSuperPath && NName::IsNetworkPath(us2fs(path)))\n    {\n      subs = k_LinkPrefix_UNC;\n      subs += (path + 2);\n    }\n    else\n    {\n      if (isSuperPath)\n      {\n        // we remove super prefix:\n        path += kSuperPathPrefixSize;\n        // we want to get correct abolute path in PrintName still.\n        if (!IsDrivePath(path))\n          needPrintName = false; // we need \"\\\\server\\path\" for print name.\n      }\n      subs = k_LinkPrefix;\n      subs += path;\n    }\n  }\n  const size_t len1 = subs.Len() * 2;\n  size_t len2 = (size_t)MyStringLen(path) * 2;\n  if (!needPrintName)\n    len2 = 0;\n  size_t totalNamesSize = len1 + len2;\n  /* some WIM imagex software uses old scheme for symbolic links.\n     so we can use old scheme for byte to byte compatibility */\n  const bool newOrderScheme = isSymLink;\n  // newOrderScheme = false;\n  if (!newOrderScheme)\n    totalNamesSize += 2 * 2; // we use NULL terminators in old scheme.\n\n  const size_t size = 8 + 8 + (isSymLink ? 4 : 0) + totalNamesSize;\n  if (size >= k_Link_Size_Limit)\n    return;\n  dest.Alloc(size);\n  memset(dest, 0, size);\n  const UInt32 tag = isSymLink ?\n      Z7_WIN_IO_REPARSE_TAG_SYMLINK :\n      Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT;\n  Byte *p = dest;\n  Set32(p, tag)\n  // Set32(p + 4, (UInt32)(size - 8))\n  Set16(p + 4, (UInt16)(size - 8))\n  Set16(p + 6, 0)\n  p += 8;\n\n  unsigned subOffs = 0;\n  unsigned printOffs = 0;\n  if (newOrderScheme)\n    subOffs = (unsigned)len2;\n  else\n    printOffs = (unsigned)len1 + 2;\n\n  Set16(p + 0, (UInt16)subOffs)\n  Set16(p + 2, (UInt16)len1)\n  Set16(p + 4, (UInt16)printOffs)\n  Set16(p + 6, (UInt16)len2)\n  p += 8;\n  if (isSymLink)\n  {\n    const UInt32 flags = isAbs ? 0 : Z7_WIN_SYMLINK_FLAG_RELATIVE;\n    Set32(p, flags)\n    p += 4;\n  }\n  WriteString(p + subOffs, subs);\n  if (needPrintName)\n    WriteString(p + printOffs, path);\n}\n\n#endif // defined(_WIN32) && !defined(UNDER_CE)\n\n\nstatic void GetString(const Byte *p, unsigned len, UString &res)\n{\n  wchar_t *s = res.GetBuf(len);\n  unsigned i;\n  for (i = 0; i < len; i++)\n  {\n    const wchar_t c = Get16(p + (size_t)i * 2);\n    if (c == 0)\n      break;\n    s[i] = c;\n  }\n  s[i] = 0;\n  res.ReleaseBuf_SetLen(i);\n}\n\n\nbool CReparseAttr::Parse(const Byte *p, size_t size)\n{\n  ErrorCode = (DWORD)ERROR_INVALID_REPARSE_DATA;\n  HeaderError = true;\n  TagIsUnknown = true;\n  MinorError = false;\n\n  if (size < 8)\n    return false;\n  Tag = Get32(p);\n  if (Get16(p + 6) != 0) // padding\n  {\n    // DOCs: Reserved : the field SHOULD be set to 0\n    // and MUST be ignored (by parser).\n    // Win10 ignores it.\n    MinorError = true; // optional\n  }\n  unsigned len = Get16(p + 4);\n  p += 8;\n  size -= 8;\n  if (len != size)\n  // if (len > size)\n    return false;\n  /*\n  if ((type & kReparseFlags_Alias) == 0 ||\n      (type & kReparseFlags_Microsoft) == 0 ||\n      (type & 0xFFFF) != 3)\n  */\n  HeaderError = false;\n\n  if (   Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT\n      && Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK\n      && Tag != Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK)\n  {\n    // for unsupported reparse points\n    ErrorCode = (DWORD)ERROR_REPARSE_TAG_INVALID; // ERROR_REPARSE_TAG_MISMATCH\n    // errorCode = ERROR_REPARSE_TAG_MISMATCH; // ERROR_REPARSE_TAG_INVALID\n    return false;\n  }\n\n  TagIsUnknown = false;\n \n  if (Tag == Z7_WIN_IO_REPARSE_TAG_LX_SYMLINK)\n  {\n    if (len < 4)\n      return false;\n    if (Get32(p) != Z7_WIN_LX_SYMLINK_VERSION_2)\n      return false;\n    len -= 4;\n    p += 4;\n    char *s = WslName.GetBuf(len);\n    unsigned i;\n    for (i = 0; i < len; i++)\n    {\n      const char c = (char)p[i];\n      s[i] = c;\n      if (c == 0)\n        break;\n    }\n    s[i] = 0;\n    WslName.ReleaseBuf_SetLen(i);\n    MinorError = (i != len);\n    ErrorCode = 0;\n    return true;\n  }\n  \n  if (len < 8)\n    return false;\n  const unsigned subOffs = Get16(p);\n  const unsigned subLen = Get16(p + 2);\n  const unsigned printOffs = Get16(p + 4);\n  const unsigned printLen = Get16(p + 6);\n  len -= 8;\n  p += 8;\n\n  Flags = 0;\n  if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK)\n  {\n    if (len < 4)\n      return false;\n    Flags = Get32(p);\n    len -= 4;\n    p += 4;\n  }\n\n  if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)\n    return false;\n  if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)\n    return false;\n  GetString(p + subOffs, subLen >> 1, SubsName);\n  GetString(p + printOffs, printLen >> 1, PrintName);\n\n  ErrorCode = 0;\n  return true;\n}\n\n\nbool CReparseShortInfo::Parse(const Byte *p, size_t size)\n{\n  const Byte * const start = p;\n  Offset = 0;\n  Size = 0;\n  if (size < 8)\n    return false;\n  const UInt32 Tag = Get32(p);\n  UInt32 len = Get16(p + 4);\n  /*\n  if (len + 8 > size)\n    return false;\n  */\n  /*\n  if ((type & kReparseFlags_Alias) == 0 ||\n      (type & kReparseFlags_Microsoft) == 0 ||\n      (type & 0xFFFF) != 3)\n  */\n  if (Tag != Z7_WIN_IO_REPARSE_TAG_MOUNT_POINT &&\n      Tag != Z7_WIN_IO_REPARSE_TAG_SYMLINK)\n    // return true;\n    return false;\n  /*\n  if (Get16(p + 6) != 0) // padding\n    return false;\n  */\n  p += 8;\n  size -= 8;\n  if (len != size) // do we need that check?\n    return false;\n  if (len < 8)\n    return false;\n  unsigned subOffs = Get16(p);\n  unsigned subLen = Get16(p + 2);\n  unsigned printOffs = Get16(p + 4);\n  unsigned printLen = Get16(p + 6);\n  len -= 8;\n  p += 8;\n\n  // UInt32 Flags = 0;\n  if (Tag == Z7_WIN_IO_REPARSE_TAG_SYMLINK)\n  {\n    if (len < 4)\n      return false;\n    // Flags = Get32(p);\n    len -= 4;\n    p += 4;\n  }\n\n  if ((subOffs & 1) != 0 || subOffs > len || len - subOffs < subLen)\n    return false;\n  if ((printOffs & 1) != 0 || printOffs > len || len - printOffs < printLen)\n    return false;\n\n  Offset = (unsigned)(p - start) + subOffs;\n  Size = subLen;\n  return true;\n}\n\nbool CReparseAttr::IsOkNamePair() const\n{\n  if (IsLinkPrefix(SubsName))\n  {\n    if (PrintName == GetPath())\n      return true;\n/*\n    if (!IsDrivePath(SubsName.Ptr(k_LinkPrefix_Size)))\n      return PrintName.IsEmpty();\n    if (wcscmp(SubsName.Ptr(k_LinkPrefix_Size), PrintName) == 0)\n      return true;\n*/\n  }\n  return wcscmp(SubsName, PrintName) == 0;\n}\n\n/*\nbool CReparseAttr::IsVolume() const\n{\n  if (!IsLinkPrefix(SubsName))\n    return false;\n  return IsVolumeName(SubsName.Ptr(k_LinkPrefix_Size));\n}\n*/\n\nUString CReparseAttr::GetPath() const\n{\n  UString s (SubsName);\n  if (IsSymLink_WSL())\n  {\n    // if (CheckUTF8(attr.WslName)\n    if (!ConvertUTF8ToUnicode(WslName, s))\n      MultiByteToUnicodeString2(s, WslName);\n  }\n  else if (IsLinkPrefix(s))\n  {\n    if (IsString1PrefixedByString2_NoCase_Ascii(s.Ptr(), k_LinkPrefix_UNC))\n    {\n      s.DeleteFrontal(6);\n      s.ReplaceOneCharAtPos(0, '\\\\');\n    }\n    else\n    {\n      s.ReplaceOneCharAtPos(1, '\\\\'); // we normalize prefix from \"\\??\\\" to \"\\\\?\\\"\n      if (IsDrivePath(s.Ptr(k_LinkPrefix_Size)))\n        s.DeleteFrontal(k_LinkPrefix_Size);\n    }\n  }\n  return s;\n}\n\n#ifdef Z7_DEVICE_FILE\n\nnamespace NSystem\n{\nbool MyGetDiskFreeSpace(CFSTR rootPath, UInt64 &clusterSize, UInt64 &totalSize, UInt64 &freeSize);\n}\n#endif // Z7_DEVICE_FILE\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n\nnamespace NIO {\n\nbool GetReparseData(CFSTR path, CByteBuffer &reparseData, BY_HANDLE_FILE_INFORMATION *fileInfo)\n{\n  reparseData.Free();\n  CInFile file;\n  if (!file.OpenReparse(path))\n    return false;\n\n  if (fileInfo)\n    file.GetFileInformation(fileInfo);\n\n  const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;\n  CByteArr buf(kBufSize);\n  DWORD returnedSize;\n  if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize))\n    return false;\n  reparseData.CopyFrom(buf, returnedSize);\n  return true;\n}\n\nstatic bool CreatePrefixDirOfFile(CFSTR path)\n{\n  FString path2 (path);\n  const int pos = path2.ReverseFind_PathSepar();\n  if (pos < 0)\n    return true;\n  #ifdef _WIN32\n  if (pos == 2 && path2[1] == L':')\n    return true; // we don't create Disk folder;\n  #endif\n  path2.DeleteFrom((unsigned)pos);\n  return NDir::CreateComplexDir(path2);\n}\n\n\nstatic bool OutIoReparseData(DWORD controlCode, CFSTR path, void *data, DWORD size)\n{\n  COutFile file;\n  if (!file.Open(path,\n      FILE_SHARE_WRITE,\n      OPEN_EXISTING,\n      FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS))\n    return false;\n\n  DWORD returnedSize;\n  return file.DeviceIoControl(controlCode, data, size, NULL, 0, &returnedSize);\n}\n\n\n// MOUNT_POINT (Junction Point) and LX_SYMLINK (WSL) can be written without administrator rights.\n// SYMLINK requires administrator rights.\n// If there is Reparse data already, it still writes new Reparse data\nbool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)\n{\n  NFile::NFind::CFileInfo fi;\n  if (fi.Find(path))\n  {\n    if (fi.IsDir() != isDir)\n    {\n      ::SetLastError(ERROR_DIRECTORY);\n      return false;\n    }\n  }\n  else\n  {\n    if (isDir)\n    {\n      if (!NDir::CreateComplexDir(path))\n        return false;\n    }\n    else\n    {\n      CreatePrefixDirOfFile(path);\n      COutFile file;\n      if (!file.Create_NEW(path))\n        return false;\n    }\n  }\n\n  return OutIoReparseData(my_FSCTL_SET_REPARSE_POINT, path, (void *)(const Byte *)(data), size);\n}\n\n\nbool DeleteReparseData(CFSTR path)\n{\n  CByteBuffer reparseData;\n  if (!GetReparseData(path, reparseData, NULL))\n    return false;\n  /* MSDN: The tag specified in the ReparseTag member of this structure\n     must match the tag of the reparse point to be deleted,\n     and the ReparseDataLength member must be zero */\n  #define my_REPARSE_DATA_BUFFER_HEADER_SIZE 8\n  if (reparseData.Size() < my_REPARSE_DATA_BUFFER_HEADER_SIZE)\n  {\n    SetLastError(ERROR_INVALID_REPARSE_DATA);\n    return false;\n  }\n  // BYTE buf[my_REPARSE_DATA_BUFFER_HEADER_SIZE];\n  // memset(buf, 0, sizeof(buf));\n  // memcpy(buf, reparseData, 4); // tag\n  memset(reparseData + 4, 0, my_REPARSE_DATA_BUFFER_HEADER_SIZE - 4);\n  return OutIoReparseData(my_FSCTL_DELETE_REPARSE_POINT, path, reparseData, my_REPARSE_DATA_BUFFER_HEADER_SIZE);\n}\n\n}\n\n#endif //  defined(_WIN32) && !defined(UNDER_CE)\n\n\n#ifndef _WIN32\n\nnamespace NIO {\n\nbool GetReparseData(CFSTR path, CByteBuffer &reparseData)\n{\n  reparseData.Free();\n\n  #define MAX_PATHNAME_LEN 1024\n  char buf[MAX_PATHNAME_LEN + 2];\n  const size_t request = sizeof(buf) - 1;\n\n  // printf(\"\\nreadlink() path = %s \\n\", path);\n  const ssize_t size = readlink(path, buf, request);\n  // there is no tail zero\n\n  if (size < 0)\n    return false;\n  if ((size_t)size >= request)\n  {\n    SetLastError(EINVAL); // check it: ENAMETOOLONG\n    return false;\n  }\n\n  // printf(\"\\nreadlink() res = %s size = %d \\n\", buf, (int)size);\n  reparseData.CopyFrom((const Byte *)buf, (size_t)size);\n  return true;\n}\n\n\n/*\n// If there is Reparse data already, it still writes new Reparse data\nbool SetReparseData(CFSTR path, bool isDir, const void *data, DWORD size)\n{\n  // AString s;\n  // s.SetFrom_CalcLen(data, size);\n  // return (symlink(s, path) == 0);\n  UNUSED_VAR(path)\n  UNUSED_VAR(isDir)\n  UNUSED_VAR(data)\n  UNUSED_VAR(size)\n  SetLastError(ENOSYS);\n  return false;\n}\n*/\n\nbool SetSymLink(CFSTR from, CFSTR to)\n{\n  // printf(\"\\nsymlink() %s -> %s\\n\", from, to);\n  int ir;\n  // ir = unlink(path);\n  // if (ir == 0)\n  ir = symlink(to, from);\n  return (ir == 0);\n}\n\nbool SetSymLink_UString(CFSTR from, const UString &to)\n{\n  AString utf;\n  ConvertUnicodeToUTF8(to, utf);\n  return SetSymLink(from, utf);\n}\n\n}\n\n#endif // !_WIN32\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileMapping.cpp",
    "content": "﻿// Windows/FileMapping.cpp\n\n#include \"StdAfx.h\"\n\n#include \"FileMapping.h\"\n\nnamespace NWindows {\nnamespace NFile {\nnamespace NMapping {\n\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileMapping.h",
    "content": "﻿// Windows/FileMapping.h\n\n#ifndef ZIP7_INC_WINDOWS_FILE_MAPPING_H\n#define ZIP7_INC_WINDOWS_FILE_MAPPING_H\n\n#include \"../Common/MyTypes.h\"\n\n#include \"Handle.h\"\n\nnamespace NWindows {\n\nclass CFileMapping: public CHandle\n{\npublic:\n  WRes Create(DWORD protect, UInt64 maxSize, LPCTSTR name)\n  {\n    _handle = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, protect, (DWORD)(maxSize >> 32), (DWORD)maxSize, name);\n    return ::GetLastError();\n  }\n\n  WRes Open(DWORD\n      #ifndef UNDER_CE\n      desiredAccess\n      #endif\n      , LPCTSTR name)\n  {\n    #ifdef UNDER_CE\n    WRes res = Create(PAGE_READONLY, 0, name);\n    if (res == ERROR_ALREADY_EXISTS)\n      return 0;\n    Close();\n    if (res == 0)\n      res = ERROR_FILE_NOT_FOUND;\n    return res;\n    #else\n    _handle = ::OpenFileMapping(desiredAccess, FALSE, name);\n    if (_handle != NULL)\n      return 0;\n    return ::GetLastError();\n    #endif\n  }\n\n  LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap)\n  {\n    return ::MapViewOfFile(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap);\n  }\n\n  #ifndef UNDER_CE\n  LPVOID Map(DWORD desiredAccess, UInt64 fileOffset, SIZE_T numberOfBytesToMap, LPVOID baseAddress)\n  {\n    return ::MapViewOfFileEx(_handle, desiredAccess, (DWORD)(fileOffset >> 32), (DWORD)fileOffset, numberOfBytesToMap, baseAddress);\n  }\n  #endif\n};\n\nclass CFileUnmapper\n{\n  const void *_data;\npublic:\n  CFileUnmapper(const void *data) : _data(data) {}\n  ~CFileUnmapper() { ::UnmapViewOfFile(_data); }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileName.cpp",
    "content": "﻿// Windows/FileName.cpp\n\n#include \"StdAfx.h\"\n\n#ifndef _WIN32\n#include <limits.h>\n#include <unistd.h>\n#include \"../Common/StringConvert.h\"\n#endif\n\n#include \"FileDir.h\"\n#include \"FileName.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\nnamespace NFile {\nnamespace NName {\n\n#define IS_SEPAR(c) IS_PATH_SEPAR(c)\n\nint FindSepar(const wchar_t *s) throw()\n{\n  for (const wchar_t *p = s;; p++)\n  {\n    const wchar_t c = *p;\n    if (c == 0)\n      return -1;\n    if (IS_SEPAR(c))\n      return (int)(p - s);\n  }\n}\n\n#ifndef USE_UNICODE_FSTRING\nint FindSepar(const FChar *s) throw()\n{\n  for (const FChar *p = s;; p++)\n  {\n    const FChar c = *p;\n    if (c == 0)\n      return -1;\n    if (IS_SEPAR(c))\n      return (int)(p - s);\n  }\n}\n#endif\n\n#ifndef USE_UNICODE_FSTRING\nvoid NormalizeDirPathPrefix(FString &dirPath)\n{\n  if (dirPath.IsEmpty())\n    return;\n  if (!IsPathSepar(dirPath.Back()))\n    dirPath.Add_PathSepar();\n}\n#endif\n\nvoid NormalizeDirPathPrefix(UString &dirPath)\n{\n  if (dirPath.IsEmpty())\n    return;\n  if (!IsPathSepar(dirPath.Back()))\n    dirPath.Add_PathSepar();\n}\n\n\n#define IS_LETTER_CHAR(c) ((((unsigned)(int)(c) | 0x20) - (unsigned)'a' <= (unsigned)('z' - 'a')))\nbool IsDrivePath (const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }\n// bool IsDriveName2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }\n\n#ifdef _WIN32\n\nbool IsDrivePath2(const wchar_t *s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }\n\n#ifndef USE_UNICODE_FSTRING\n#ifdef Z7_LONG_PATH\nstatic void NormalizeDirSeparators(UString &s)\n{\n  const unsigned len = s.Len();\n  for (unsigned i = 0; i < len; i++)\n    if (s[i] == '/')\n      s.ReplaceOneCharAtPos(i, WCHAR_PATH_SEPARATOR);\n}\n#endif\n#endif\n\nvoid NormalizeDirSeparators(FString &s)\n{\n  const unsigned len = s.Len();\n  for (unsigned i = 0; i < len; i++)\n    if (s[i] == '/')\n      s.ReplaceOneCharAtPos(i, FCHAR_PATH_SEPARATOR);\n}\n\nbool IsAltPathPrefix(CFSTR s) throw()\n{\n  unsigned len = MyStringLen(s);\n  if (len == 0)\n    return false;\n  if (s[len - 1] != ':')\n    return false;\n\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  if (IsDevicePath(s))\n    return false;\n  if (IsSuperPath(s))\n  {\n    s += kSuperPathPrefixSize;\n    len -= kSuperPathPrefixSize;\n  }\n  if (len == 2 && IsDrivePath2(s))\n    return false;\n  #endif\n\n  return true;\n}\n\n#endif // _WIN32\n\n\nconst char * const kSuperPathPrefix =\n    STRING_PATH_SEPARATOR\n    STRING_PATH_SEPARATOR \"?\"\n    STRING_PATH_SEPARATOR;\n#ifdef Z7_LONG_PATH\nstatic const char * const kSuperUncPrefix =\n    STRING_PATH_SEPARATOR\n    STRING_PATH_SEPARATOR \"?\"\n    STRING_PATH_SEPARATOR \"UNC\"\n    STRING_PATH_SEPARATOR;\n#endif\n\n#define IS_DEVICE_PATH(s)          (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '.' && IS_SEPAR((s)[3]))\n#define IS_SUPER_PREFIX(s)         (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && (s)[2] == '?' && IS_SEPAR((s)[3]))\n\n#define IS_UNC_WITH_SLASH(s) ( \\\n     ((s)[0] == 'U' || (s)[0] == 'u') \\\n  && ((s)[1] == 'N' || (s)[1] == 'n') \\\n  && ((s)[2] == 'C' || (s)[2] == 'c') \\\n  && IS_SEPAR((s)[3]))\n\nstatic const unsigned kDrivePrefixSize = 3; /* c:\\ */\n\nbool IsSuperPath(const wchar_t *s) throw();\nbool IsSuperPath(const wchar_t *s) throw() { return IS_SUPER_PREFIX(s); }\n// bool IsSuperUncPath(const wchar_t *s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n\n#define IS_SUPER_OR_DEVICE_PATH(s) (IS_SEPAR((s)[0]) && IS_SEPAR((s)[1]) && ((s)[2] == '?' || (s)[2] == '.') && IS_SEPAR((s)[3]))\nbool IsSuperOrDevicePath(const wchar_t *s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }\nbool IsDevicePath(CFSTR s) throw()\n{\n  #ifdef UNDER_CE\n\n  s = s;\n  return false;\n  /*\n  // actually we don't know the way to open device file in WinCE.\n  unsigned len = MyStringLen(s);\n  if (len < 5 || len > 5 || !IsString1PrefixedByString2(s, \"DSK\"))\n    return false;\n  if (s[4] != ':')\n    return false;\n  // for reading use SG_REQ sg; if (DeviceIoControl(dsk, IOCTL_DISK_READ));\n  */\n  \n  #else\n  \n  if (!IS_DEVICE_PATH(s))\n    return false;\n  const unsigned len = MyStringLen(s);\n  if (len == 6 && s[5] == ':')\n    return true;\n  if (len < 18 || len > 22 || !IsString1PrefixedByString2(s + kDevicePathPrefixSize, \"PhysicalDrive\"))\n    return false;\n  for (unsigned i = 17; i < len; i++)\n    if (s[i] < '0' || s[i] > '9')\n      return false;\n  return true;\n  \n  #endif\n}\n\nbool IsSuperUncPath(CFSTR s) throw() { return (IS_SUPER_PREFIX(s) && IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize)); }\nbool IsNetworkPath(CFSTR s) throw()\n{\n  if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))\n    return false;\n  if (IsSuperUncPath(s))\n    return true;\n  const FChar c = s[2];\n  return (c != '.' && c != '?');\n}\n\nunsigned GetNetworkServerPrefixSize(CFSTR s) throw()\n{\n  if (!IS_SEPAR(s[0]) || !IS_SEPAR(s[1]))\n    return 0;\n  unsigned prefixSize = 2;\n  if (IsSuperUncPath(s))\n    prefixSize = kSuperUncPathPrefixSize;\n  else\n  {\n    const FChar c = s[2];\n    if (c == '.' || c == '?')\n      return 0;\n  }\n  const int pos = FindSepar(s + prefixSize);\n  if (pos < 0)\n    return 0;\n  return prefixSize + (unsigned)(pos + 1);\n}\n\nbool IsNetworkShareRootPath(CFSTR s) throw()\n{\n  const unsigned prefixSize = GetNetworkServerPrefixSize(s);\n  if (prefixSize == 0)\n    return false;\n  s += prefixSize;\n  const int pos = FindSepar(s);\n  if (pos < 0)\n    return true;\n  return s[(unsigned)pos + 1] == 0;\n}\n\nbool IsAltStreamPrefixWithColon(const UString &s) throw()\n{\n  if (s.IsEmpty())\n    return false;\n  if (s.Back() != ':')\n    return false;\n  unsigned pos = 0;\n  if (IsSuperPath(s))\n    pos = kSuperPathPrefixSize;\n  if (s.Len() - pos == 2 && IsDrivePath2(s.Ptr(pos)))\n    return false;\n  return true;\n}\n\nbool If_IsSuperPath_RemoveSuperPrefix(UString &s)\n{\n  if (!IsSuperPath(s))\n    return false;\n  unsigned start = 0;\n  unsigned count = kSuperPathPrefixSize;\n  const wchar_t *s2 = s.Ptr(kSuperPathPrefixSize);\n  if (IS_UNC_WITH_SLASH(s2))\n  {\n    start = 2;\n    count = kSuperUncPathPrefixSize - 2;\n  }\n  s.Delete(start, count);\n  return true;\n}\n\n\n#ifndef USE_UNICODE_FSTRING\nbool IsDrivePath2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':'; }\n// bool IsDriveName2(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && s[2] == 0; }\nbool IsDrivePath(CFSTR s) throw() { return IS_LETTER_CHAR(s[0]) && s[1] == ':' && IS_SEPAR(s[2]); }\nbool IsSuperPath(CFSTR s) throw() { return IS_SUPER_PREFIX(s); }\nbool IsSuperOrDevicePath(CFSTR s) throw() { return IS_SUPER_OR_DEVICE_PATH(s); }\n#endif // USE_UNICODE_FSTRING\n\nbool IsDrivePath_SuperAllowed(CFSTR s) throw()\n{\n  if (IsSuperPath(s))\n    s += kSuperPathPrefixSize;\n  return IsDrivePath(s);\n}\n\nbool IsDriveRootPath_SuperAllowed(CFSTR s) throw()\n{\n  if (IsSuperPath(s))\n    s += kSuperPathPrefixSize;\n  return IsDrivePath(s) && s[kDrivePrefixSize] == 0;\n}\n\nbool IsAbsolutePath(const wchar_t *s) throw()\n{\n  return IS_SEPAR(s[0]) || IsDrivePath2(s);\n}\n\nint FindAltStreamColon(CFSTR path) throw()\n{\n  unsigned i = 0;\n  if (IsSuperPath(path))\n    i = kSuperPathPrefixSize;\n  if (IsDrivePath2(path + i))\n    i += 2;\n  int colonPos = -1;\n  for (;; i++)\n  {\n    const FChar c = path[i];\n    if (c == 0)\n      return colonPos;\n    if (c == ':')\n    {\n      if (colonPos < 0)\n        colonPos = (int)i;\n      continue;\n    }\n    if (IS_SEPAR(c))\n      colonPos = -1;\n  }\n}\n\n#ifndef USE_UNICODE_FSTRING\n\nstatic unsigned GetRootPrefixSize_Of_NetworkPath(CFSTR s)\n{\n  // Network path: we look \"server\\path\\\" as root prefix\n  const int pos = FindSepar(s);\n  if (pos < 0)\n    return 0;\n  const int pos2 = FindSepar(s + (unsigned)pos + 1);\n  if (pos2 < 0)\n    return 0;\n  return (unsigned)pos + (unsigned)pos2 + 2;\n}\n\nstatic unsigned GetRootPrefixSize_Of_SimplePath(CFSTR s)\n{\n  if (IsDrivePath(s))\n    return kDrivePrefixSize;\n  if (!IS_SEPAR(s[0]))\n    return 0;\n  if (s[1] == 0 || !IS_SEPAR(s[1]))\n    return 1;\n  const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);\n  return (size == 0) ? 0 : 2 + size;\n}\n\nstatic unsigned GetRootPrefixSize_Of_SuperPath(CFSTR s)\n{\n  if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))\n  {\n    const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);\n    return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;\n  }\n  // we support \\\\?\\c:\\ paths and volume GUID paths \\\\?\\Volume{GUID}\\\"\n  const int pos = FindSepar(s + kSuperPathPrefixSize);\n  if (pos < 0)\n    return 0;\n  return kSuperPathPrefixSize + (unsigned)pos + 1;\n}\n\nunsigned GetRootPrefixSize(CFSTR s) throw()\n{\n  if (IS_DEVICE_PATH(s))\n    return kDevicePathPrefixSize;\n  if (IsSuperPath(s))\n    return GetRootPrefixSize_Of_SuperPath(s);\n  return GetRootPrefixSize_Of_SimplePath(s);\n}\n\n#endif // USE_UNICODE_FSTRING\n#endif // _WIN32\n\n\nstatic unsigned GetRootPrefixSize_Of_NetworkPath(const wchar_t *s) throw()\n{\n  // Network path: we look \"server\\path\\\" as root prefix\n  const int pos = FindSepar(s);\n  if (pos < 0)\n    return 0;\n  const int pos2 = FindSepar(s + (unsigned)pos + 1);\n  if (pos2 < 0)\n    return 0;\n  return (unsigned)(pos + pos2 + 2);\n}\n\nstatic unsigned GetRootPrefixSize_Of_SimplePath(const wchar_t *s) throw()\n{\n  if (IsDrivePath(s))\n    return kDrivePrefixSize;\n  if (!IS_SEPAR(s[0]))\n    return 0;\n  if (s[1] == 0 || !IS_SEPAR(s[1]))\n    return 1;\n  const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + 2);\n  return (size == 0) ? 0 : 2 + size;\n}\n\nstatic unsigned GetRootPrefixSize_Of_SuperPath(const wchar_t *s) throw()\n{\n  if (IS_UNC_WITH_SLASH(s + kSuperPathPrefixSize))\n  {\n    const unsigned size = GetRootPrefixSize_Of_NetworkPath(s + kSuperUncPathPrefixSize);\n    return (size == 0) ? 0 : kSuperUncPathPrefixSize + size;\n  }\n  // we support \\\\?\\c:\\ paths and volume GUID paths \\\\?\\Volume{GUID}\\\"\n  const int pos = FindSepar(s + kSuperPathPrefixSize);\n  if (pos < 0)\n    return 0;\n  return kSuperPathPrefixSize + (unsigned)(pos + 1);\n}\n\n#ifdef _WIN32\nunsigned GetRootPrefixSize(const wchar_t *s) throw()\n#else\nunsigned GetRootPrefixSize_WINDOWS(const wchar_t *s) throw()\n#endif\n{\n  if (IS_DEVICE_PATH(s))\n    return kDevicePathPrefixSize;\n  if (IsSuperPath(s))\n    return GetRootPrefixSize_Of_SuperPath(s);\n  return GetRootPrefixSize_Of_SimplePath(s);\n}\n\n#ifndef _WIN32\n\nbool IsAbsolutePath(const wchar_t *s) throw() { return IS_SEPAR(s[0]); }\n\n#ifndef USE_UNICODE_FSTRING\nunsigned GetRootPrefixSize(CFSTR s) throw();\nunsigned GetRootPrefixSize(CFSTR s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; }\n#endif\nunsigned GetRootPrefixSize(const wchar_t *s) throw() { return IS_SEPAR(s[0]) ? 1 : 0; }\n\n#endif // _WIN32\n\n\n#ifndef UNDER_CE\n\n\n#ifdef USE_UNICODE_FSTRING\n\n#define GetCurDir NDir::GetCurrentDir\n\n#else\n\nstatic bool GetCurDir(UString &path)\n{\n  path.Empty();\n  FString s;\n  if (!NDir::GetCurrentDir(s))\n    return false;\n  path = fs2us(s);\n  return true;\n}\n\n#endif\n\n\nstatic bool ResolveDotsFolders(UString &s)\n{\n  #ifdef _WIN32\n  // s.Replace(L'/', WCHAR_PATH_SEPARATOR);\n  #endif\n  \n  for (unsigned i = 0;;)\n  {\n    const wchar_t c = s[i];\n    if (c == 0)\n      return true;\n    if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))\n    {\n      const wchar_t c1 = s[i + 1];\n      if (c1 == '.')\n      {\n        const wchar_t c2 = s[i + 2];\n        if (IS_SEPAR(c2) || c2 == 0)\n        {\n          if (i == 0)\n            return false;\n          int k = (int)i - 2;\n          i += 2;\n          \n          for (;; k--)\n          {\n            if (k < 0)\n              return false;\n            if (!IS_SEPAR(s[(unsigned)k]))\n              break;\n          }\n\n          do\n            k--;\n          while (k >= 0 && !IS_SEPAR(s[(unsigned)k]));\n          \n          unsigned num;\n          \n          if (k >= 0)\n          {\n            num = i - (unsigned)k;\n            i = (unsigned)k;\n          }\n          else\n          {\n            num = (c2 == 0 ? i : (i + 1));\n            i = 0;\n          }\n          \n          s.Delete(i, num);\n          continue;\n        }\n      }\n      else if (IS_SEPAR(c1) || c1 == 0)\n      {\n        unsigned num = 2;\n        if (i != 0)\n          i--;\n        else if (c1 == 0)\n          num = 1;\n        s.Delete(i, num);\n        continue;\n      }\n    }\n\n    i++;\n  }\n}\n\n#endif // UNDER_CE\n\n#define LONG_PATH_DOTS_FOLDERS_PARSING\n\n\n/*\nWindows (at least 64-bit XP) can't resolve \".\" or \"..\" in paths that start with SuperPrefix \\\\?\\\nTo solve that problem we check such path:\n   - super path contains        \".\" or \"..\" - we use kSuperPathType_UseOnlySuper\n   - super path doesn't contain \".\" or \"..\" - we use kSuperPathType_UseOnlyMain\n*/\n#ifdef LONG_PATH_DOTS_FOLDERS_PARSING\n#ifndef UNDER_CE\nstatic bool AreThereDotsFolders(CFSTR s)\n{\n  for (unsigned i = 0;; i++)\n  {\n    FChar c = s[i];\n    if (c == 0)\n      return false;\n    if (c == '.' && (i == 0 || IS_SEPAR(s[i - 1])))\n    {\n      FChar c1 = s[i + 1];\n      if (c1 == 0 || IS_SEPAR(c1) ||\n          (c1 == '.' && (s[i + 2] == 0 || IS_SEPAR(s[i + 2]))))\n        return true;\n    }\n  }\n}\n#endif\n#endif // LONG_PATH_DOTS_FOLDERS_PARSING\n\n#ifdef Z7_LONG_PATH\n\n/*\nMost of Windows versions have problems, if some file or dir name\ncontains '.' or ' ' at the end of name (Bad Path).\nTo solve that problem, we always use Super Path (\"\\\\?\\\" prefix and full path)\nin such cases. Note that \".\" and \"..\" are not bad names.\n\nThere are 3 cases:\n  1) If the path is already Super Path, we use that path\n  2) If the path is not Super Path :\n     2.1) Bad Path;  we use only Super Path.\n     2.2) Good Path; we use Main Path. If it fails, we use Super Path.\n\n NeedToUseOriginalPath returns:\n    kSuperPathType_UseOnlyMain    : Super already\n    kSuperPathType_UseOnlySuper    : not Super, Bad Path\n    kSuperPathType_UseMainAndSuper : not Super, Good Path\n*/\n\nint GetUseSuperPathType(CFSTR s) throw()\n{\n  if (IsSuperOrDevicePath(s))\n  {\n    #ifdef LONG_PATH_DOTS_FOLDERS_PARSING\n    if ((s)[2] != '.')\n      if (AreThereDotsFolders(s + kSuperPathPrefixSize))\n        return kSuperPathType_UseOnlySuper;\n    #endif\n    return kSuperPathType_UseOnlyMain;\n  }\n\n  for (unsigned i = 0;; i++)\n  {\n    FChar c = s[i];\n    if (c == 0)\n      return kSuperPathType_UseMainAndSuper;\n    if (c == '.' || c == ' ')\n    {\n      FChar c2 = s[i + 1];\n      if (c2 == 0 || IS_SEPAR(c2))\n      {\n        // if it's \".\" or \"..\", it's not bad name.\n        if (c == '.')\n        {\n          if (i == 0 || IS_SEPAR(s[i - 1]))\n            continue;\n          if (s[i - 1] == '.')\n          {\n            if (i - 1 == 0 || IS_SEPAR(s[i - 2]))\n              continue;\n          }\n        }\n        return kSuperPathType_UseOnlySuper;\n      }\n    }\n  }\n}\n\n\n\n/*\n   returns false in two cases:\n     - if GetCurDir was used, and GetCurDir returned error.\n     - if we can't resolve \"..\" name.\n   if path is \".\", \"..\", res is empty.\n   if it's Super Path already, res is empty.\n   for \\**** , and if GetCurDir is not drive (c:\\), res is empty\n   for absolute paths, returns true, res is Super path.\n*/\n\nstatic bool GetSuperPathBase(CFSTR s, UString &res)\n{\n  res.Empty();\n  \n  FChar c = s[0];\n  if (c == 0)\n    return true;\n  if (c == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))\n    return true;\n  \n  if (IsSuperOrDevicePath(s))\n  {\n    #ifdef LONG_PATH_DOTS_FOLDERS_PARSING\n    \n    if ((s)[2] == '.')\n      return true;\n\n    // we will return true here, so we will try to use these problem paths.\n\n    if (!AreThereDotsFolders(s + kSuperPathPrefixSize))\n      return true;\n    \n    UString temp = fs2us(s);\n    const unsigned fixedSize = GetRootPrefixSize_Of_SuperPath(temp);\n    if (fixedSize == 0)\n      return true;\n\n    UString rem = temp.Ptr(fixedSize);\n    if (!ResolveDotsFolders(rem))\n      return true;\n\n    temp.DeleteFrom(fixedSize);\n    res += temp;\n    res += rem;\n    \n    #endif\n\n    return true;\n  }\n\n  if (IS_SEPAR(c))\n  {\n    if (IS_SEPAR(s[1]))\n    {\n      UString temp = fs2us(s + 2);\n      const unsigned fixedSize = GetRootPrefixSize_Of_NetworkPath(temp);\n      // we ignore that error to allow short network paths server\\share?\n      /*\n      if (fixedSize == 0)\n        return false;\n      */\n      UString rem = temp.Ptr(fixedSize);\n      if (!ResolveDotsFolders(rem))\n        return false;\n      res += kSuperUncPrefix;\n      temp.DeleteFrom(fixedSize);\n      res += temp;\n      res += rem;\n      return true;\n    }\n  }\n  else\n  {\n    if (IsDrivePath2(s))\n    {\n      UString temp = fs2us(s);\n      unsigned prefixSize = 2;\n      if (IsDrivePath(s))\n        prefixSize = kDrivePrefixSize;\n      UString rem = temp.Ptr(prefixSize);\n      if (!ResolveDotsFolders(rem))\n        return true;\n      res += kSuperPathPrefix;\n      temp.DeleteFrom(prefixSize);\n      res += temp;\n      res += rem;\n      return true;\n    }\n  }\n\n  UString curDir;\n  if (!GetCurDir(curDir))\n    return false;\n  NormalizeDirPathPrefix(curDir);\n\n  unsigned fixedSizeStart = 0;\n  unsigned fixedSize = 0;\n  const char *superMarker = NULL;\n  if (IsSuperPath(curDir))\n  {\n    fixedSize = GetRootPrefixSize_Of_SuperPath(curDir);\n    if (fixedSize == 0)\n      return false;\n  }\n  else\n  {\n    if (IsDrivePath(curDir))\n    {\n      superMarker = kSuperPathPrefix;\n      fixedSize = kDrivePrefixSize;\n    }\n    else\n    {\n      if (!IsPathSepar(curDir[0]) || !IsPathSepar(curDir[1]))\n        return false;\n      fixedSizeStart = 2;\n      fixedSize = GetRootPrefixSize_Of_NetworkPath(curDir.Ptr(2));\n      if (fixedSize == 0)\n        return false;\n      superMarker = kSuperUncPrefix;\n    }\n  }\n  \n  UString temp;\n  if (IS_SEPAR(c))\n  {\n    temp = fs2us(s + 1);\n  }\n  else\n  {\n    temp += &curDir[fixedSizeStart + fixedSize];\n    temp += fs2us(s);\n  }\n  if (!ResolveDotsFolders(temp))\n    return false;\n  if (superMarker)\n    res += superMarker;\n  res += curDir.Mid(fixedSizeStart, fixedSize);\n  res += temp;\n  return true;\n}\n\n\n/*\n  In that case if GetSuperPathBase doesn't return new path, we don't need\n  to use same path that was used as main path\n                        \n  GetSuperPathBase  superPath.IsEmpty() onlyIfNew\n     false            *                *          GetCurDir Error\n     true            false             *          use Super path\n     true            true             true        don't use any path, we already used mainPath\n     true            true             false       use main path as Super Path, we don't try mainMath\n                                                  That case is possible now if GetCurDir returns unknown\n                                                  type of path (not drive and not network)\n\n  We can change that code if we want to try mainPath, if GetSuperPathBase returns error,\n  and we didn't try mainPath still.\n  If we want to work that way, we don't need to use GetSuperPathBase return code.\n*/\n\nbool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew)\n{\n  if (GetSuperPathBase(path, superPath))\n  {\n    if (superPath.IsEmpty())\n    {\n      // actually the only possible when onlyIfNew == true and superPath is empty\n      // is case when\n\n      if (onlyIfNew)\n        return false;\n      superPath = fs2us(path);\n    }\n    \n    NormalizeDirSeparators(superPath);\n    return true;\n  }\n  return false;\n}\n\nbool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew)\n{\n  if (!GetSuperPathBase(s1, d1) ||\n      !GetSuperPathBase(s2, d2))\n    return false;\n \n  NormalizeDirSeparators(d1);\n  NormalizeDirSeparators(d2);\n\n  if (d1.IsEmpty() && d2.IsEmpty() && onlyIfNew)\n    return false;\n  if (d1.IsEmpty()) d1 = fs2us(s1);\n  if (d2.IsEmpty()) d2 = fs2us(s2);\n  return true;\n}\n\n\n/*\n// returns true, if we need additional use with New Super path.\nbool GetSuperPath(CFSTR path, UString &superPath)\n{\n  if (GetSuperPathBase(path, superPath))\n    return !superPath.IsEmpty();\n  return false;\n}\n*/\n#endif // Z7_LONG_PATH\n\nbool GetFullPath(CFSTR dirPrefix, CFSTR s, FString &res)\n{\n  res = s;\n\n  #ifdef UNDER_CE\n\n  if (!IS_SEPAR(s[0]))\n  {\n    if (!dirPrefix)\n      return false;\n    res = dirPrefix;\n    res += s;\n  }\n\n  #else\n\n  const unsigned prefixSize = GetRootPrefixSize(s);\n  if (prefixSize != 0)\n#ifdef _WIN32\n  if (prefixSize != 1)\n#endif\n  {\n    if (!AreThereDotsFolders(s + prefixSize))\n      return true;\n    \n    UString rem = fs2us(s + prefixSize);\n    if (!ResolveDotsFolders(rem))\n      return true; // maybe false;\n    res.DeleteFrom(prefixSize);\n    res += us2fs(rem);\n    return true;\n  }\n\n  UString curDir;\n  if (dirPrefix && prefixSize == 0)\n    curDir = fs2us(dirPrefix);  // we use (dirPrefix), only if (s) path is relative\n  else\n  {\n    if (!GetCurDir(curDir))\n      return false;\n  }\n  NormalizeDirPathPrefix(curDir);\n\n  unsigned fixedSize = GetRootPrefixSize(curDir);\n\n  UString temp;\n#ifdef _WIN32\n  if (prefixSize != 0)\n  {\n    /* (s) is absolute path, but only (prefixSize == 1) is possible here.\n       So for full resolving we need root of current folder and\n       relative part of (s). */\n    s += prefixSize;\n    // (s) is relative part now\n    if (fixedSize == 0)\n    {\n      // (curDir) is not absolute.\n      // That case is unexpected, but we support it too.\n      curDir.Empty();\n      curDir.Add_PathSepar();\n      fixedSize = 1;\n      // (curDir) now is just Separ character.\n      // So final (res) path later also will have Separ prefix.\n    }\n  }\n  else\n#endif // _WIN32\n  {\n    // (s) is relative path\n    temp = curDir.Ptr(fixedSize);\n    // (temp) is relative_part_of(curDir)\n  }\n  temp += fs2us(s);\n  if (!ResolveDotsFolders(temp))\n    return false;\n  curDir.DeleteFrom(fixedSize);\n  // (curDir) now contains only absolute prefix part\n  res = us2fs(curDir);\n  res += us2fs(temp);\n  \n  #endif // UNDER_CE\n\n  return true;\n}\n\n\nbool GetFullPath(CFSTR path, FString &fullPath)\n{\n  return GetFullPath(NULL, path, fullPath);\n}\n\n}}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/FileName.h",
    "content": "﻿// Windows/FileName.h\n\n#ifndef ZIP7_INC_WINDOWS_FILE_NAME_H\n#define ZIP7_INC_WINDOWS_FILE_NAME_H\n\n#include \"../Common/MyString.h\"\n\nnamespace NWindows {\nnamespace NFile {\nnamespace NName {\n\nint FindSepar(const wchar_t *s) throw();\n#ifndef USE_UNICODE_FSTRING\nint FindSepar(const FChar *s) throw();\n#endif\n\nvoid NormalizeDirPathPrefix(FString &dirPath); // ensures that it ended with '\\\\', if dirPath is not epmty\nvoid NormalizeDirPathPrefix(UString &dirPath);\n\n#ifdef _WIN32\nvoid NormalizeDirSeparators(FString &s);\n#endif\n\nbool IsDrivePath(const wchar_t *s) throw();  // first 3 chars are drive chars like \"a:\\\\\"\n\nbool IsAltPathPrefix(CFSTR s) throw(); /* name: */\n\nextern const char * const kSuperPathPrefix; /* \\\\?\\ */\nconst unsigned kDevicePathPrefixSize = 4;\nconst unsigned kSuperPathPrefixSize = 4;\nconst unsigned kSuperUncPathPrefixSize = kSuperPathPrefixSize + 4;\n\n#if defined(_WIN32) && !defined(UNDER_CE)\n\nbool IsDevicePath(CFSTR s) throw();   /* \\\\.\\ */\nbool IsSuperUncPath(CFSTR s) throw(); /* \\\\?\\UNC\\ */\nbool IsNetworkPath(CFSTR s) throw();  /* \\\\?\\UNC\\ or \\\\SERVER */\n\n/* GetNetworkServerPrefixSize() returns size of server prefix:\n     \\\\?\\UNC\\SERVER\\\n     \\\\SERVER\\\n  in another cases it returns 0\n*/\n\nunsigned GetNetworkServerPrefixSize(CFSTR s) throw();\n\nbool IsNetworkShareRootPath(CFSTR s) throw();  /* \\\\?\\UNC\\SERVER\\share or \\\\SERVER\\share or with slash */\n\nbool IsDrivePath_SuperAllowed(CFSTR s) throw();  // first chars are drive chars like \"a:\\\" or \"\\\\?\\a:\\\"\nbool IsDriveRootPath_SuperAllowed(CFSTR s) throw();  // exact drive root path \"a:\\\" or \"\\\\?\\a:\\\"\n\nbool IsDrivePath2(const wchar_t *s) throw(); // first 2 chars are drive chars like \"a:\"\n// bool IsDriveName2(const wchar_t *s) throw(); // is drive name like \"a:\"\nbool IsSuperPath(const wchar_t *s) throw();\nbool IsSuperOrDevicePath(const wchar_t *s) throw();\n\nbool IsAltStreamPrefixWithColon(const UString &s) throw();\n// returns true, if super prefix was removed\nbool If_IsSuperPath_RemoveSuperPrefix(UString &s);\n\n#ifndef USE_UNICODE_FSTRING\nbool IsDrivePath2(CFSTR s) throw(); // first 2 chars are drive chars like \"a:\"\n// bool IsDriveName2(CFSTR s) throw(); // is drive name like \"a:\"\nbool IsDrivePath(CFSTR s) throw();\nbool IsSuperPath(CFSTR s) throw();\nbool IsSuperOrDevicePath(CFSTR s) throw();\n\n/* GetRootPrefixSize() returns size of ROOT PREFIX for cases:\n     \\\n     \\\\.\\\n     C:\\\n     \\\\?\\C:\\\n     \\\\?\\UNC\\SERVER\\Shared\\\n     \\\\SERVER\\Shared\\\n  in another cases it returns 0\n*/\n\nunsigned GetRootPrefixSize(CFSTR s) throw();\n\n#endif\n\nint FindAltStreamColon(CFSTR path) throw();\n\n#endif // _WIN32\n\nbool IsAbsolutePath(const wchar_t *s) throw();\nunsigned GetRootPrefixSize(const wchar_t *s) throw();\n\n#ifndef _WIN32\n/* GetRootPrefixSize_WINDOWS() is called in linux, but it parses path by windows rules.\n   It supports only paths system (linux) slash separators (STRING_PATH_SEPARATOR),\n   It doesn't parses paths with backslash (windows) separators.\n   \"c:/dir/file\" is supported.\n*/\nunsigned GetRootPrefixSize_WINDOWS(const wchar_t *s) throw();\n#endif\n\n#ifdef Z7_LONG_PATH\n\nconst int kSuperPathType_UseOnlyMain = 0;\nconst int kSuperPathType_UseOnlySuper = 1;\nconst int kSuperPathType_UseMainAndSuper = 2;\n\nint GetUseSuperPathType(CFSTR s) throw();\nbool GetSuperPath(CFSTR path, UString &superPath, bool onlyIfNew);\nbool GetSuperPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2, bool onlyIfNew);\n\n#define USE_MAIN_PATH (_useSuperPathType != kSuperPathType_UseOnlySuper)\n#define USE_MAIN_PATH_2 (_useSuperPathType1 != kSuperPathType_UseOnlySuper && _useSuperPathType2 != kSuperPathType_UseOnlySuper)\n\n#define USE_SUPER_PATH (_useSuperPathType != kSuperPathType_UseOnlyMain)\n#define USE_SUPER_PATH_2 (_useSuperPathType1 != kSuperPathType_UseOnlyMain || _useSuperPathType2 != kSuperPathType_UseOnlyMain)\n\n#define IF_USE_MAIN_PATH int _useSuperPathType = GetUseSuperPathType(path); if (USE_MAIN_PATH)\n#define IF_USE_MAIN_PATH_2(x1, x2) \\\n    int _useSuperPathType1 = GetUseSuperPathType(x1); \\\n    int _useSuperPathType2 = GetUseSuperPathType(x2); \\\n    if (USE_MAIN_PATH_2)\n\n#else\n\n#define IF_USE_MAIN_PATH\n#define IF_USE_MAIN_PATH_2(x1, x2)\n\n#endif // Z7_LONG_PATH\n\n/*\n  if (dirPrefix != NULL && (path) is relative)\n  {\n    (dirPrefix) will be used\n    result (fullPath) will contain prefix part of (dirPrefix).\n  }\n  Current_Dir path can be used in 2 cases:\n    1) if (path) is relative && dirPrefix == NULL\n    2) for _WIN32: if (path) is absolute starting wuth \"\\\"\n*/\nbool GetFullPath(CFSTR dirPrefix, CFSTR path, FString &fullPath);\nbool GetFullPath(CFSTR path, FString &fullPath);\n\n}}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Handle.h",
    "content": "﻿// Windows/Handle.h\n\n#ifndef ZIP7_INC_WINDOWS_HANDLE_H\n#define ZIP7_INC_WINDOWS_HANDLE_H\n\n#include \"../Common/MyWindows.h\"\n\nnamespace NWindows {\n\nclass CHandle  MY_UNCOPYABLE\n{\nprotected:\n  HANDLE _handle;\npublic:\n  operator HANDLE() { return _handle; }\n  CHandle(): _handle(NULL) {}\n  ~CHandle() { Close(); }\n  bool IsCreated() const { return (_handle != NULL); }\n  bool Close()\n  {\n    if (_handle == NULL)\n      return true;\n    if (!::CloseHandle(_handle))\n      return false;\n    _handle = NULL;\n    return true;\n  }\n  void Attach(HANDLE handle) { _handle = handle; }\n  HANDLE Detach()\n  {\n    const HANDLE handle = _handle;\n    _handle = NULL;\n    return handle;\n  }\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/MemoryGlobal.cpp",
    "content": "﻿// Windows/MemoryGlobal.cpp\n\n#include \"StdAfx.h\"\n\n#include \"MemoryGlobal.h\"\n\nnamespace NWindows {\nnamespace NMemory {\n\nbool CGlobal::Alloc(UINT flags, SIZE_T size) throw()\n{\n  HGLOBAL newBlock = ::GlobalAlloc(flags, size);\n  if (newBlock == NULL)\n    return false;\n  _global = newBlock;\n  return true;\n}\n\nbool CGlobal::Free() throw()\n{\n  if (_global == NULL)\n    return true;\n  _global = ::GlobalFree(_global);\n  return (_global == NULL);\n}\n\nbool CGlobal::ReAlloc(SIZE_T size) throw()\n{\n  HGLOBAL newBlock = ::GlobalReAlloc(_global, size, GMEM_MOVEABLE);\n  if (newBlock == NULL)\n    return false;\n  _global = newBlock;\n  return true;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/MemoryGlobal.h",
    "content": "﻿// Windows/MemoryGlobal.h\n\n#ifndef ZIP7_INC_WINDOWS_MEMORY_GLOBAL_H\n#define ZIP7_INC_WINDOWS_MEMORY_GLOBAL_H\n\n#include \"../Common/MyWindows.h\"\n\nnamespace NWindows {\nnamespace NMemory {\n\nclass CGlobal\n{\n  HGLOBAL _global;\npublic:\n  CGlobal(): _global(NULL) {}\n  ~CGlobal() { Free(); }\n  operator HGLOBAL() const { return _global; }\n  void Attach(HGLOBAL hGlobal)\n  {\n    Free();\n    _global = hGlobal;\n  }\n  HGLOBAL Detach()\n  {\n    const HGLOBAL h = _global;\n    _global = NULL;\n    return h;\n  }\n  bool Alloc(UINT flags, SIZE_T size) throw();\n  bool Free() throw();\n  LPVOID Lock() const { return GlobalLock(_global); }\n  void Unlock() const { GlobalUnlock(_global); }\n  bool ReAlloc(SIZE_T size) throw();\n};\n\nclass CGlobalLock\n{\n  HGLOBAL _global;\n  LPVOID _ptr;\npublic:\n  LPVOID GetPointer() const { return _ptr; }\n  CGlobalLock(HGLOBAL hGlobal): _global(hGlobal)\n  {\n    _ptr = GlobalLock(hGlobal);\n  }\n  ~CGlobalLock()\n  {\n    if (_ptr)\n      GlobalUnlock(_global);\n  }\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/MemoryLock.cpp",
    "content": "﻿// Windows/MemoryLock.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../../C/CpuArch.h\"\n\n#include \"MemoryLock.h\"\n\nnamespace NWindows {\nnamespace NSecurity {\n\n#ifndef UNDER_CE\n\n#ifdef _UNICODE\n#define MY_FUNC_SELECT(f) :: f\n#else\n#define MY_FUNC_SELECT(f) my_ ## f\nextern \"C\" {\ntypedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);\ntypedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid);\ntypedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges,\n    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);\n}\n\n#define GET_PROC_ADDR(fff, name)  \\\n  const Func_ ## fff  my_ ## fff = Z7_GET_PROC_ADDRESS( \\\n        Func_ ## fff, hModule, name);\n#endif\n\nbool EnablePrivilege(LPCTSTR privilegeName, bool enable)\n{\n  bool res = false;\n\n  #ifndef _UNICODE\n\n  const HMODULE hModule = ::LoadLibrary(TEXT(\"advapi32.dll\"));\n  if (!hModule)\n    return false;\n  \nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\n  GET_PROC_ADDR(\n     OpenProcessToken,\n    \"OpenProcessToken\")\n  GET_PROC_ADDR(\n     LookupPrivilegeValue,\n    \"LookupPrivilegeValueA\")\n  GET_PROC_ADDR(\n     AdjustTokenPrivileges,\n    \"AdjustTokenPrivileges\")\n  \n  if (my_OpenProcessToken &&\n      my_AdjustTokenPrivileges &&\n      my_LookupPrivilegeValue)\n  \n  #endif\n\n  {\n    HANDLE token;\n    if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))\n    {\n      TOKEN_PRIVILEGES tp;\n      if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid)))\n      {\n        tp.PrivilegeCount = 1;\n        tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0);\n        if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL))\n          res = (GetLastError() == ERROR_SUCCESS);\n      }\n      ::CloseHandle(token);\n    }\n  }\n    \n  #ifndef _UNICODE\n\n  ::FreeLibrary(hModule);\n  \n  #endif\n\n  return res;\n}\n\n\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\ntypedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);\n\n/*\n  We suppose that Window 10 works incorrectly with \"Large Pages\" at:\n    - Windows 10 1703 (15063) : incorrect allocating after VirtualFree()\n    - Windows 10 1709 (16299) : incorrect allocating after VirtualFree()\n    - Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger,\n                                if CPU doesn't support 1 GB pages.\n  Windows 10 1903 (18362) probably works correctly.\n*/\n\nunsigned Get_LargePages_RiskLevel()\n{\n  OSVERSIONINFOEXW vi;\n  const HMODULE ntdll = ::GetModuleHandleW(L\"ntdll.dll\");\n  if (!ntdll)\n    return 0;\n  const\n  Func_RtlGetVersion func = Z7_GET_PROC_ADDRESS(\n  Func_RtlGetVersion, ntdll,\n      \"RtlGetVersion\");\n  if (!func)\n    return 0;\n  func(&vi);\n  if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)\n    return 0;\n  if (vi.dwMajorVersion + vi.dwMinorVersion != 10)\n    return 0;\n  if (vi.dwBuildNumber <= 16299)\n    return 1;\n\n  #ifdef MY_CPU_X86_OR_AMD64\n  if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB())\n    return 1;\n  #endif\n\n  return 0;\n}\n\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/MemoryLock.h",
    "content": "﻿// Windows/MemoryLock.h\n\n#ifndef ZIP7_INC_WINDOWS_MEMORY_LOCK_H\n#define ZIP7_INC_WINDOWS_MEMORY_LOCK_H\n\n#include \"../Common/MyWindows.h\"\n\nnamespace NWindows {\nnamespace NSecurity {\n\n#ifndef UNDER_CE\n\nbool EnablePrivilege(LPCTSTR privilegeName, bool enable = true);\n\ninline bool EnablePrivilege_LockMemory(bool enable = true)\n{\n  return EnablePrivilege(SE_LOCK_MEMORY_NAME, enable);\n}\n\ninline void EnablePrivilege_SymLink()\n{\n  /* Probably we do not to set any Privilege for junction points.\n     But we need them for Symbolic links */\n  NSecurity::EnablePrivilege(SE_RESTORE_NAME);\n  \n  /* Probably we need only SE_RESTORE_NAME, but there is also\n     SE_CREATE_SYMBOLIC_LINK_NAME. So we set it also. Do we need it? */\n\n  NSecurity::EnablePrivilege(TEXT(\"SeCreateSymbolicLinkPrivilege\")); // SE_CREATE_SYMBOLIC_LINK_NAME\n  \n  // Do we need to set SE_BACKUP_NAME ?\n}\n\nunsigned Get_LargePages_RiskLevel();\n\n#endif\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/NtCheck.h",
    "content": "﻿// Windows/NtCheck.h\n\n#ifndef ZIP7_INC_WINDOWS_NT_CHECK_H\n#define ZIP7_INC_WINDOWS_NT_CHECK_H\n\n#ifdef _WIN32\n\n#include \"../Common/MyWindows.h\"\n\n#if !defined(_WIN64) && !defined(UNDER_CE)\n\n#if defined(_MSC_VER) && _MSC_VER >= 1900\n#pragma warning(push)\n// GetVersionExW was declared deprecated\n#pragma warning(disable : 4996)\n#endif\nstatic inline bool IsItWindowsNT()\n{\n  OSVERSIONINFO vi;\n  vi.dwOSVersionInfoSize = sizeof(vi);\n  return (::GetVersionEx(&vi) && vi.dwPlatformId == VER_PLATFORM_WIN32_NT);\n}\n#if defined(_MSC_VER) && _MSC_VER >= 1900\n#pragma warning(pop)\n#endif\n\n#endif\n\n#ifndef _UNICODE\n    extern\n    bool g_IsNT;\n  #if defined(_WIN64) || defined(UNDER_CE)\n    bool g_IsNT = true;\n    #define SET_IS_NT\n  #else\n    bool g_IsNT = false;\n    #define SET_IS_NT g_IsNT = IsItWindowsNT();\n  #endif\n  #define NT_CHECK_ACTION\n  // #define NT_CHECK_ACTION { NT_CHECK_FAIL_ACTION }\n#else\n  #if !defined(_WIN64) && !defined(UNDER_CE)\n    #define NT_CHECK_ACTION if (!IsItWindowsNT()) { NT_CHECK_FAIL_ACTION }\n  #else\n    #define NT_CHECK_ACTION\n  #endif\n  #define SET_IS_NT\n#endif\n\n#define NT_CHECK  NT_CHECK_ACTION SET_IS_NT\n\n#else\n\n#define NT_CHECK\n\n#endif\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/PropVariant.cpp",
    "content": "﻿// Windows/PropVariant.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/Defs.h\"\n\n#include \"PropVariant.h\"\n\nnamespace NWindows {\nnamespace NCOM {\n\nBSTR AllocBstrFromAscii(const char *s) throw()\n{\n  if (!s)\n    return NULL;\n  UINT len = (UINT)strlen(s);\n  BSTR p = ::SysAllocStringLen(NULL, len);\n  if (p)\n  {\n    for (UINT i = 0; i <= len; i++)\n      p[i] = (Byte)s[i];\n  }\n  return p;\n}\n\nHRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw()\n{\n  p->bstrVal = ::SysAllocStringLen(NULL, numChars);\n  if (!p->bstrVal)\n  {\n    p->vt = VT_ERROR;\n    p->scode = E_OUTOFMEMORY;\n    return E_OUTOFMEMORY;\n  }\n  p->vt = VT_BSTR;\n  return S_OK;\n}\n\nHRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw()\n{\n  p->bstrVal = AllocBstrFromAscii(s);\n  if (p->bstrVal)\n  {\n    p->vt = VT_BSTR;\n    return S_OK;\n  }\n  p->vt = VT_ERROR;\n  p->scode = E_OUTOFMEMORY;\n  return E_OUTOFMEMORY;\n}\n\nCPropVariant::CPropVariant(const PROPVARIANT &varSrc)\n{\n  vt = VT_EMPTY;\n  InternalCopy(&varSrc);\n}\n\nCPropVariant::CPropVariant(const CPropVariant &varSrc)\n{\n  vt = VT_EMPTY;\n  InternalCopy(&varSrc);\n}\n\nCPropVariant::CPropVariant(BSTR bstrSrc)\n{\n  vt = VT_EMPTY;\n  *this = bstrSrc;\n}\n\nCPropVariant::CPropVariant(LPCOLESTR lpszSrc)\n{\n  vt = VT_EMPTY;\n  *this = lpszSrc;\n}\n\nCPropVariant& CPropVariant::operator=(const CPropVariant &varSrc)\n{\n  InternalCopy(&varSrc);\n  return *this;\n}\n\nCPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc)\n{\n  InternalCopy(&varSrc);\n  return *this;\n}\n\nCPropVariant& CPropVariant::operator=(BSTR bstrSrc)\n{\n  *this = (LPCOLESTR)bstrSrc;\n  return *this;\n}\n\nstatic const char * const kMemException = \"out of memory\";\n\nCPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc)\n{\n  InternalClear();\n  vt = VT_BSTR;\n  wReserved1 = 0;\n  bstrVal = ::SysAllocString(lpszSrc);\n  if (!bstrVal && lpszSrc)\n  {\n    throw kMemException;\n    // vt = VT_ERROR;\n    // scode = E_OUTOFMEMORY;\n  }\n  return *this;\n}\n\nCPropVariant& CPropVariant::operator=(const UString &s)\n{\n  InternalClear();\n  vt = VT_BSTR;\n  wReserved1 = 0;\n  bstrVal = ::SysAllocStringLen(s, s.Len());\n  if (!bstrVal)\n    throw kMemException;\n  return *this;\n}\n\nCPropVariant& CPropVariant::operator=(const UString2 &s)\n{\n  /*\n  if (s.IsEmpty())\n    *this = L\"\";\n  else\n  */\n  {\n    InternalClear();\n    vt = VT_BSTR;\n    wReserved1 = 0;\n    bstrVal = ::SysAllocStringLen(s.GetRawPtr(), s.Len());\n    if (!bstrVal)\n      throw kMemException;\n    /* SysAllocStringLen probably appends a null-terminating character for NULL string.\n       But it doesn't specified in MSDN.\n       But we suppose that it works\n\n    if (!s.GetRawPtr())\n    {\n      *bstrVal = 0;\n    }\n    */\n\n    /* MSDN: Windows CE: SysAllocStringLen() : Passing invalid (and under some circumstances NULL)\n                         pointers to this function causes  an unexpected termination of the application.\n       Is it safe? Maybe we must chamnge the code for that case ? */\n  }\n  return *this;\n}\n\nCPropVariant& CPropVariant::operator=(const char *s)\n{\n  InternalClear();\n  vt = VT_BSTR;\n  wReserved1 = 0;\n  bstrVal = AllocBstrFromAscii(s);\n  if (!bstrVal)\n  {\n    throw kMemException;\n    // vt = VT_ERROR;\n    // scode = E_OUTOFMEMORY;\n  }\n  return *this;\n}\n\nCPropVariant& CPropVariant::operator=(bool bSrc) throw()\n{\n  if (vt != VT_BOOL)\n  {\n    InternalClear();\n    vt = VT_BOOL;\n  }\n  boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;\n  return *this;\n}\n\nBSTR CPropVariant::AllocBstr(unsigned numChars)\n{\n  if (vt != VT_EMPTY)\n    InternalClear();\n  vt = VT_BSTR;\n  wReserved1 = 0;\n  bstrVal = ::SysAllocStringLen(NULL, numChars);\n  if (!bstrVal)\n  {\n    throw kMemException;\n    // vt = VT_ERROR;\n    // scode = E_OUTOFMEMORY;\n  }\n  return bstrVal;\n}\n\n#define SET_PROP_id_dest(id, dest) \\\n  if (vt != id) { InternalClear(); vt = id; } dest = value; wReserved1 = 0;\n\nvoid CPropVariant::Set_Int32(Int32 value) throw()\n{\n  SET_PROP_id_dest(VT_I4, lVal)\n}\n\nvoid CPropVariant::Set_Int64(Int64 value) throw()\n{\n  SET_PROP_id_dest(VT_I8, hVal.QuadPart)\n}\n\n#define SET_PROP_FUNC(type, id, dest) \\\n  CPropVariant& CPropVariant::operator=(type value) throw() \\\n  { SET_PROP_id_dest(id, dest)  return *this; }\n\nSET_PROP_FUNC(Byte, VT_UI1, bVal)\n// SET_PROP_FUNC(Int16, VT_I2, iVal)\n// SET_PROP_FUNC(Int32, VT_I4, lVal)\nSET_PROP_FUNC(UInt32, VT_UI4, ulVal)\nSET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart)\n// SET_PROP_FUNC(Int64, VT_I8, hVal.QuadPart)\nSET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime)\n\n#define CASE_SIMPLE_VT_VALUES \\\n    case VT_EMPTY:    \\\n    case VT_BOOL:     \\\n    case VT_FILETIME: \\\n    case VT_UI8:      \\\n    case VT_UI4:      \\\n    case VT_UI2:      \\\n    case VT_UI1:      \\\n    case VT_I8:       \\\n    case VT_I4:       \\\n    case VT_I2:       \\\n    case VT_I1:       \\\n    case VT_UINT:     \\\n    case VT_INT:      \\\n    case VT_NULL:     \\\n    case VT_ERROR:    \\\n    case VT_R4:       \\\n    case VT_R8:       \\\n    case VT_CY:       \\\n    case VT_DATE:     \\\n\n\n/*\n  ::VariantClear() and ::VariantCopy() don't work, if (vt == VT_FILETIME)\n  So we handle VT_FILETIME and another simple types directly\n  we call system functions for VT_BSTR and for unknown typed\n*/\n \nCPropVariant::~CPropVariant() throw()\n{\n  switch ((unsigned)vt)\n  {\n    CASE_SIMPLE_VT_VALUES\n      // vt = VT_EMPTY; // it's optional\n      return;\n    default: break;\n  }\n  ::VariantClear((tagVARIANT *)this);\n}\n\nHRESULT PropVariant_Clear(PROPVARIANT *prop) throw()\n{\n  switch ((unsigned)prop->vt)\n  {\n    CASE_SIMPLE_VT_VALUES\n      prop->vt = VT_EMPTY;\n      break;\n    default:\n    {\n      const HRESULT res = ::VariantClear((VARIANTARG *)prop);\n      if (res != S_OK || prop->vt != VT_EMPTY)\n        return res;\n      break;\n    }\n  }\n  prop->wReserved1 = 0;\n  prop->wReserved2 = 0;\n  prop->wReserved3 = 0;\n  prop->uhVal.QuadPart = 0;\n  return S_OK;\n}\n\nHRESULT CPropVariant::Clear() throw()\n{\n  if (vt == VT_EMPTY)\n  {\n    wReserved1 = 0;\n    return S_OK;\n  }\n  return PropVariant_Clear(this);\n}\n\nHRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) throw()\n{\n  Clear();\n  switch ((unsigned)pSrc->vt)\n  {\n    CASE_SIMPLE_VT_VALUES\n      memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT));\n      return S_OK;\n    default: break;\n  }\n  return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast<PROPVARIANT *>(pSrc));\n}\n\n\nHRESULT CPropVariant::Attach(PROPVARIANT *pSrc) throw()\n{\n  const HRESULT hr = Clear();\n  if (FAILED(hr))\n    return hr;\n  // memcpy((PROPVARIANT *)this, pSrc, sizeof(PROPVARIANT));\n  *(PROPVARIANT *)this = *pSrc;\n  pSrc->vt = VT_EMPTY;\n  pSrc->wReserved1 = 0;\n  return S_OK;\n}\n\nHRESULT CPropVariant::Detach(PROPVARIANT *pDest) throw()\n{\n  if (pDest->vt != VT_EMPTY)\n  {\n    const HRESULT hr = PropVariant_Clear(pDest);\n    if (FAILED(hr))\n      return hr;\n  }\n  // memcpy(pDest, this, sizeof(PROPVARIANT));\n  *pDest = *(PROPVARIANT *)this;\n  vt = VT_EMPTY;\n  wReserved1 = 0;\n  return S_OK;\n}\n\nHRESULT CPropVariant::InternalClear() throw()\n{\n  if (vt == VT_EMPTY)\n  {\n    wReserved1 = 0;\n    return S_OK;\n  }\n  const HRESULT hr = Clear();\n  if (FAILED(hr))\n  {\n    vt = VT_ERROR;\n    scode = hr;\n  }\n  return hr;\n}\n\nvoid CPropVariant::InternalCopy(const PROPVARIANT *pSrc)\n{\n  const HRESULT hr = Copy(pSrc);\n  if (FAILED(hr))\n  {\n    if (hr == E_OUTOFMEMORY)\n      throw kMemException;\n    vt = VT_ERROR;\n    scode = hr;\n  }\n}\n\n\nint CPropVariant::Compare(const CPropVariant &a) throw()\n{\n  if (vt != a.vt)\n    return MyCompare(vt, a.vt);\n  switch ((unsigned)vt)\n  {\n    case VT_EMPTY: return 0;\n    // case VT_I1: return MyCompare(cVal, a.cVal);\n    case VT_UI1: return MyCompare(bVal, a.bVal);\n    case VT_I2: return MyCompare(iVal, a.iVal);\n    case VT_UI2: return MyCompare(uiVal, a.uiVal);\n    case VT_I4: return MyCompare(lVal, a.lVal);\n    case VT_UI4: return MyCompare(ulVal, a.ulVal);\n    // case VT_UINT: return MyCompare(uintVal, a.uintVal);\n    case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart);\n    case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart);\n    case VT_BOOL: return -MyCompare(boolVal, a.boolVal);\n    case VT_FILETIME:\n    {\n      const int res = CompareFileTime(&filetime, &a.filetime);\n      if (res != 0)\n        return res;\n      const unsigned v1 = Get_Ns100();\n      const unsigned v2 = a.Get_Ns100();\n      return MyCompare(v1, v2);\n    }\n    case VT_BSTR: return 0; // Not implemented\n    default: return 0;\n  }\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/PropVariant.h",
    "content": "﻿// Windows/PropVariant.h\n\n#ifndef ZIP7_INC_WINDOWS_PROP_VARIANT_H\n#define ZIP7_INC_WINDOWS_PROP_VARIANT_H\n\n#include \"../Common/MyTypes.h\"\n#include \"../Common/MyWindows.h\"\n#include \"../Common/MyString.h\"\n\nnamespace NWindows {\nnamespace NCOM {\n\nBSTR AllocBstrFromAscii(const char *s) throw();\n\nHRESULT PropVariant_Clear(PROPVARIANT *p) throw();\n\nHRESULT PropVarEm_Alloc_Bstr(PROPVARIANT *p, unsigned numChars) throw();\nHRESULT PropVarEm_Set_Str(PROPVARIANT *p, const char *s) throw();\n\ninline void PropVarEm_Set_UInt32(PROPVARIANT *p, UInt32 v) throw()\n{\n  p->vt = VT_UI4;\n  p->ulVal = v;\n}\n\ninline void PropVarEm_Set_UInt64(PROPVARIANT *p, UInt64 v) throw()\n{\n  p->vt = VT_UI8;\n  p->uhVal.QuadPart = v;\n}\n\ninline void PropVarEm_Set_FileTime64_Prec(PROPVARIANT *p, UInt64 v, unsigned prec) throw()\n{\n  p->vt = VT_FILETIME;\n  p->filetime.dwLowDateTime = (DWORD)v;\n  p->filetime.dwHighDateTime = (DWORD)(v >> 32);\n  p->wReserved1 = (WORD)prec;\n  p->wReserved2 = 0;\n  p->wReserved3 = 0;\n}\n\ninline void PropVarEm_Set_Bool(PROPVARIANT *p, bool b) throw()\n{\n  p->vt = VT_BOOL;\n  p->boolVal = (b ? VARIANT_TRUE : VARIANT_FALSE);\n}\n\n\nclass CPropVariant : public tagPROPVARIANT\n{\n  // ---------- forbidden functions ----------\n  CPropVariant(const char *s);\n  // CPropVariant(const UString &s);\n #ifdef DEBUG_FSTRING_INHERITS_ASTRING\n  CPropVariant(const FString &s);\n  CPropVariant& operator=(const FString &s);\n #endif\n\npublic:\n  CPropVariant()\n  {\n    vt = VT_EMPTY;\n    wReserved1 = 0;\n    // wReserved2 = 0;\n    // wReserved3 = 0;\n    // uhVal.QuadPart = 0;\n    bstrVal = NULL;\n  }\n\n\n  void Set_FtPrec(unsigned prec)\n  {\n    wReserved1 = (WORD)prec;\n    wReserved2 = 0;\n    wReserved3 = 0;\n  }\n\n  void SetAsTimeFrom_FT_Prec(const FILETIME &ft, unsigned prec)\n  {\n    operator=(ft);\n    Set_FtPrec(prec);\n  }\n\n  void SetAsTimeFrom_Ft64_Prec(UInt64 v, unsigned prec)\n  {\n    FILETIME ft;\n    ft.dwLowDateTime = (DWORD)(UInt32)v;\n    ft.dwHighDateTime = (DWORD)(UInt32)(v >> 32);\n    operator=(ft);\n    Set_FtPrec(prec);\n  }\n\n  void SetAsTimeFrom_FT_Prec_Ns100(const FILETIME &ft, unsigned prec, unsigned ns100)\n  {\n    operator=(ft);\n    wReserved1 = (WORD)prec;\n    wReserved2 = (WORD)ns100;\n    wReserved3 = 0;\n  }\n\n  unsigned Get_Ns100() const\n  {\n    const unsigned prec = wReserved1;\n    const unsigned ns100 = wReserved2;\n    if (prec == 0\n        && prec <= k_PropVar_TimePrec_1ns\n        && ns100 < 100\n        && wReserved3 == 0)\n      return ns100;\n    return 0;\n  }\n\n  ~CPropVariant() throw();\n  CPropVariant(const PROPVARIANT &varSrc);\n  CPropVariant(const CPropVariant &varSrc);\n  CPropVariant(BSTR bstrSrc);\n  CPropVariant(LPCOLESTR lpszSrc);\n  CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }\n  CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; }\n\nprivate:\n  CPropVariant(UInt16 value); // { vt = VT_UI2; wReserved1 = 0; uiVal = value; }\n  CPropVariant(Int16 value); // { vt = VT_I2; wReserved1 = 0; iVal = value; }\n  CPropVariant(Int32 value); // { vt = VT_I4; wReserved1 = 0; lVal = value; }\n  CPropVariant(Int64 value); // { vt = VT_I8; wReserved1 = 0; hVal.QuadPart = value; }\n\npublic:\n  CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; }\n  CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; }\n  CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; }\n\n  CPropVariant& operator=(const CPropVariant &varSrc);\n  CPropVariant& operator=(const PROPVARIANT &varSrc);\n  CPropVariant& operator=(BSTR bstrSrc);\n  CPropVariant& operator=(LPCOLESTR lpszSrc);\n  CPropVariant& operator=(const UString &s);\n  CPropVariant& operator=(const UString2 &s);\n  CPropVariant& operator=(const char *s);\n  CPropVariant& operator=(const AString &s)\n    { return (*this)=(const char *)s; }\n  \n  CPropVariant& operator=(bool bSrc) throw();\n  CPropVariant& operator=(Byte value) throw();\n  \nprivate:\n  CPropVariant& operator=(Int16 value) throw();\n  CPropVariant& operator=(UInt16 value) throw();\n  CPropVariant& operator=(Int32 value) throw();\n  CPropVariant& operator=(Int64 value) throw();\n\npublic:\n  CPropVariant& operator=(UInt32 value) throw();\n  CPropVariant& operator=(UInt64 value) throw();\n  CPropVariant& operator=(const FILETIME &value) throw();\n\n  void Set_Int32(Int32 value) throw();\n  void Set_Int64(Int64 value) throw();\n\n  BSTR AllocBstr(unsigned numChars);\n\n  HRESULT Clear() throw();\n  HRESULT Copy(const PROPVARIANT *pSrc) throw();\n  HRESULT Attach(PROPVARIANT *pSrc) throw();\n  HRESULT Detach(PROPVARIANT *pDest) throw();\n\n  HRESULT InternalClear() throw();\n  void InternalCopy(const PROPVARIANT *pSrc);\n  int Compare(const CPropVariant &a) throw();\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/PropVariantConv.cpp",
    "content": "﻿// PropVariantConv.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/IntToString.h\"\n\n#include \"Defs.h\"\n#include \"PropVariantConv.h\"\n\n#define UINT_TO_STR_2(c, val) { s[0] = (c); s[1] = (char)('0' + (val) / 10); s[2] = (char)('0' + (val) % 10); s += 3; }\n\nstatic const unsigned k_TimeStringBufferSize = 64;\n\nbool g_Timestamp_Show_UTC;\n#if 0\nbool g_Timestamp_Show_DisableZ;\nbool g_Timestamp_Show_TDelimeter;\nbool g_Timestamp_Show_ZoneOffset;\n#endif\n\nZ7_NO_INLINE\nbool ConvertUtcFileTimeToString2(const FILETIME &utc, unsigned ns100, char *s, int level, unsigned flags) throw()\n{\n  *s = 0;\n  FILETIME ft;\n\n#if 0\n  Int64 bias64 = 0;\n#endif\n\n  const bool show_utc =\n      (flags & kTimestampPrintFlags_Force_UTC) ? true :\n      (flags & kTimestampPrintFlags_Force_LOCAL) ? false :\n      g_Timestamp_Show_UTC;\n\n  if (show_utc)\n    ft = utc;\n  else\n  {\n    if (!FileTimeToLocalFileTime(&utc, &ft))\n      return false;\n#if 0\n    if (g_Timestamp_Show_ZoneOffset)\n    {\n      const UInt64 utc64 = (((UInt64)utc.dwHighDateTime) << 32) + utc.dwLowDateTime;\n      const UInt64 loc64 = (((UInt64) ft.dwHighDateTime) << 32) +  ft.dwLowDateTime;\n      bias64 = (Int64)utc64 - (Int64)loc64;\n    }\n#endif\n  }\n\n  SYSTEMTIME st;\n  if (!BOOLToBool(FileTimeToSystemTime(&ft, &st)))\n  {\n    // win10 : that function doesn't work, if bit 63 of 64-bit FILETIME is set.\n    return false;\n  }\n\n  {\n    unsigned val = st.wYear;\n    if (val >= 10000)\n    {\n      *s++ = (char)('0' + val / 10000);\n      val %= 10000;\n    }\n    s[3] = (char)('0' + val % 10); val /= 10;\n    s[2] = (char)('0' + val % 10); val /= 10;\n    s[1] = (char)('0' + val % 10);\n    s[0] = (char)('0' + val / 10);\n    s += 4;\n  }\n  UINT_TO_STR_2('-', st.wMonth)\n  UINT_TO_STR_2('-', st.wDay)\n  \n  if (level > kTimestampPrintLevel_DAY)\n  {\n    const char setChar =\n#if 0\n      g_Timestamp_Show_TDelimeter ? 'T' : // ISO 8601\n#endif\n      ' ';\n    UINT_TO_STR_2(setChar, st.wHour)\n    UINT_TO_STR_2(':', st.wMinute)\n    \n    if (level >= kTimestampPrintLevel_SEC)\n    {\n      UINT_TO_STR_2(':', st.wSecond)\n\n      if (level > kTimestampPrintLevel_SEC)\n      {\n        *s++ = '.';\n        /*\n        {\n          unsigned val = st.wMilliseconds;\n          s[2] = (char)('0' + val % 10); val /= 10;\n          s[1] = (char)('0' + val % 10);\n          s[0] = (char)('0' + val / 10);\n          s += 3;\n        }\n        *s++ = ' ';\n        */\n        \n        {\n          unsigned numDigits = 7;\n          UInt32 val = (UInt32)((((UInt64)ft.dwHighDateTime << 32) + ft.dwLowDateTime) % 10000000);\n          for (unsigned i = numDigits; i != 0;)\n          {\n            i--;\n            s[i] = (char)('0' + val % 10); val /= 10;\n          }\n          if (numDigits > (unsigned)level)\n            numDigits = (unsigned)level;\n          s += numDigits;\n        }\n        if (level >= kTimestampPrintLevel_NTFS + 1)\n        {\n          *s++ = (char)('0' + (ns100 / 10));\n          if (level >= kTimestampPrintLevel_NTFS + 2)\n            *s++ = (char)('0' + (ns100 % 10));\n        }\n      }\n    }\n  }\n  \n  if (show_utc)\n  {\n    if ((flags & kTimestampPrintFlags_DisableZ) == 0\n#if 0\n      && !g_Timestamp_Show_DisableZ\n#endif\n      )\n      *s++ = 'Z';\n  }\n#if 0\n  else if (g_Timestamp_Show_ZoneOffset)\n  {\n#if 1\n    {\n      char c;\n      if (bias64 < 0)\n      {\n        bias64 = -bias64;\n        c = '+';\n      }\n      else\n        c = '-';\n      UInt32 bias = (UInt32)((UInt64)bias64 / (10000000 * 60));\n#else\n    TIME_ZONE_INFORMATION zi;\n    const DWORD dw = GetTimeZoneInformation(&zi);\n    if (dw <= TIME_ZONE_ID_DAYLIGHT) // == 2\n    {\n      // UTC = LOCAL + Bias\n      Int32 bias = zi.Bias;\n      char c;\n      if (bias < 0)\n      {\n        bias = -bias;\n        c = '+';\n      }\n      else\n        c = '-';\n#endif\n      const UInt32 hours = (UInt32)bias / 60;\n      const UInt32 mins = (UInt32)bias % 60;\n      UINT_TO_STR_2(c, hours)\n      UINT_TO_STR_2(':', mins)\n    }\n  }\n#endif\n  *s = 0;\n  return true;\n}\n\n\nbool ConvertUtcFileTimeToString(const FILETIME &utc, char *s, int level) throw()\n{\n  return ConvertUtcFileTimeToString2(utc, 0, s, level);\n}\n\nbool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *dest, int level) throw()\n{\n  char s[k_TimeStringBufferSize];\n  const bool res = ConvertUtcFileTimeToString2(ft, ns100, s, level);\n  for (unsigned i = 0;; i++)\n  {\n    const Byte c = (Byte)s[i];\n    dest[i] = c;\n    if (c == 0)\n      break;\n  }\n  return res;\n}\n\nbool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *dest, int level) throw()\n{\n  char s[k_TimeStringBufferSize];\n  const bool res = ConvertUtcFileTimeToString(ft, s, level);\n  for (unsigned i = 0;; i++)\n  {\n    const Byte c = (Byte)s[i];\n    dest[i] = c;\n    if (c == 0)\n      break;\n  }\n  return res;\n}\n\n\nvoid ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw()\n{\n  *dest = 0;\n  switch (prop.vt)\n  {\n    case VT_EMPTY: return;\n    case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;\n    case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;\n    case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;\n    case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;\n    case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;\n    case VT_FILETIME:\n    {\n      // const unsigned prec = prop.wReserved1;\n      int level = 0;\n      /*\n      if (prec == 0)\n        level = 7;\n      else if (prec > 16 && prec <= 16 + 9)\n        level = prec - 16;\n      */\n      ConvertUtcFileTimeToString(prop.filetime, dest, level);\n      return;\n    }\n    // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;\n    case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;\n    case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;\n    case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;\n    case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? '+' : '-'; dest[1] = 0; return;\n    default: dest[0] = '?'; dest[1] = ':'; ConvertUInt64ToString(prop.vt, dest + 2);\n  }\n}\n\nvoid ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw()\n{\n  *dest = 0;\n  switch (prop.vt)\n  {\n    case VT_EMPTY: return;\n    case VT_BSTR: dest[0] = '?'; dest[1] = 0; return;\n    case VT_UI1: ConvertUInt32ToString(prop.bVal, dest); return;\n    case VT_UI2: ConvertUInt32ToString(prop.uiVal, dest); return;\n    case VT_UI4: ConvertUInt32ToString(prop.ulVal, dest); return;\n    case VT_UI8: ConvertUInt64ToString(prop.uhVal.QuadPart, dest); return;\n    case VT_FILETIME:\n    {\n      // const unsigned prec = prop.wReserved1;\n      int level = 0;\n      /*\n      if (prec == 0)\n        level = 7;\n      else if (prec > 16 && prec <= 16 + 9)\n        level = prec - 16;\n      */\n      ConvertUtcFileTimeToString(prop.filetime, dest, level);\n      return;\n    }\n    // case VT_I1: return ConvertInt64ToString(prop.cVal, dest); return;\n    case VT_I2: ConvertInt64ToString(prop.iVal, dest); return;\n    case VT_I4: ConvertInt64ToString(prop.lVal, dest); return;\n    case VT_I8: ConvertInt64ToString(prop.hVal.QuadPart, dest); return;\n    case VT_BOOL: dest[0] = VARIANT_BOOLToBool(prop.boolVal) ? (wchar_t)'+' : (wchar_t)'-'; dest[1] = 0; return;\n    default: dest[0] = '?'; dest[1] = ':'; ConvertUInt32ToString(prop.vt, dest + 2);\n  }\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/PropVariantConv.h",
    "content": "﻿// Windows/PropVariantConv.h\n\n#ifndef ZIP7_INC_PROP_VARIANT_CONV_H\n#define ZIP7_INC_PROP_VARIANT_CONV_H\n\n#include \"../Common/MyTypes.h\"\n\n// provide at least 32 bytes for buffer including zero-end\n\nextern bool g_Timestamp_Show_UTC;\n\n#define kTimestampPrintLevel_DAY -3\n// #define kTimestampPrintLevel_HOUR -2\n#define kTimestampPrintLevel_MIN -1\n#define kTimestampPrintLevel_SEC  0\n#define kTimestampPrintLevel_NTFS 7\n#define kTimestampPrintLevel_NS   9\n\n\n#define kTimestampPrintFlags_Force_UTC   (1 << 0)\n#define kTimestampPrintFlags_Force_LOCAL (1 << 1)\n#define kTimestampPrintFlags_DisableZ    (1 << 4)\n\nbool ConvertUtcFileTimeToString(const FILETIME &ft, char *s, int level = kTimestampPrintLevel_SEC) throw();\nbool ConvertUtcFileTimeToString(const FILETIME &ft, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();\nbool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, char *s, int level = kTimestampPrintLevel_SEC, unsigned flags = 0) throw();\nbool ConvertUtcFileTimeToString2(const FILETIME &ft, unsigned ns100, wchar_t *s, int level = kTimestampPrintLevel_SEC) throw();\n\n// provide at least 32 bytes for buffer including zero-end\n// don't send VT_BSTR to these functions\nvoid ConvertPropVariantToShortString(const PROPVARIANT &prop, char *dest) throw();\nvoid ConvertPropVariantToShortString(const PROPVARIANT &prop, wchar_t *dest) throw();\n\ninline bool ConvertPropVariantToUInt64(const PROPVARIANT &prop, UInt64 &value)\n{\n  switch (prop.vt)\n  {\n    case VT_UI8: value = (UInt64)prop.uhVal.QuadPart; return true;\n    case VT_UI4: value = prop.ulVal; return true;\n    case VT_UI2: value = prop.uiVal; return true;\n    case VT_UI1: value = prop.bVal; return true;\n    case VT_EMPTY: return false;\n    default: throw 151199;\n  }\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/PropVariantUtils.cpp",
    "content": "﻿// PropVariantUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/IntToString.h\"\n\n#include \"PropVariantUtils.h\"\n\nusing namespace NWindows;\n\nstatic void AddHex(AString &s, UInt32 v)\n{\n  char sz[16];\n  sz[0] = '0';\n  sz[1] = 'x';\n  ConvertUInt32ToHex(v, sz + 2);\n  s += sz;\n}\n\n\nAString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value)\n{\n  char sz[16];\n  const char *p = NULL;\n  for (unsigned i = 0; i < num; i++)\n  {\n    const CUInt32PCharPair &pair = pairs[i];\n    if (pair.Value == value)\n      p = pair.Name;\n  }\n  if (!p)\n  {\n    ConvertUInt32ToString(value, sz);\n    p = sz;\n  }\n  return (AString)p;\n}\n\nvoid PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NCOM::CPropVariant &prop)\n{\n  prop = TypePairToString(pairs, num, value);\n}\n\n\nAString TypeToString(const char * const table[], unsigned num, UInt32 value)\n{\n  char sz[16];\n  const char *p = NULL;\n  if (value < num)\n    p = table[value];\n  if (!p)\n  {\n    ConvertUInt32ToString(value, sz);\n    p = sz;\n  }\n  return (AString)p;\n}\n\nvoid TypeToProp(const char * const table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop)\n{\n  char sz[16];\n  const char *p = NULL;\n  if (value < num)\n    p = table[value];\n  if (!p)\n  {\n    ConvertUInt32ToString(value, sz);\n    p = sz;\n  }\n  prop = p;\n}\n\n\nAString FlagsToString(const char * const *names, unsigned num, UInt32 flags)\n{\n  AString s;\n  for (unsigned i = 0; i < num; i++)\n  {\n    UInt32 flag = (UInt32)1 << i;\n    if ((flags & flag) != 0)\n    {\n      const char *name = names[i];\n      if (name && name[0] != 0)\n      {\n        s.Add_OptSpaced(name);\n        flags &= ~flag;\n      }\n    }\n  }\n  if (flags != 0)\n  {\n    s.Add_Space_if_NotEmpty();\n    AddHex(s, flags);\n  }\n  return s;\n}\n\nAString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags)\n{\n  AString s;\n  for (unsigned i = 0; i < num; i++)\n  {\n    const CUInt32PCharPair &p = pairs[i];\n    UInt32 flag = (UInt32)1 << (unsigned)p.Value;\n    if ((flags & flag) != 0)\n    {\n      if (p.Name[0] != 0)\n        s.Add_OptSpaced(p.Name);\n    }\n    flags &= ~flag;\n  }\n  if (flags != 0)\n  {\n    s.Add_Space_if_NotEmpty();\n    AddHex(s, flags);\n  }\n  return s;\n}\n\nvoid FlagsToProp(const char * const *names, unsigned num, UInt32 flags, NCOM::CPropVariant &prop)\n{\n  prop = FlagsToString(names, num, flags);\n}\n\nvoid FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NCOM::CPropVariant &prop)\n{\n  prop = FlagsToString(pairs, num, flags);\n}\n\n\nstatic AString Flags64ToString(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags)\n{\n  AString s;\n  for (unsigned i = 0; i < num; i++)\n  {\n    const CUInt32PCharPair &p = pairs[i];\n    UInt64 flag = (UInt64)1 << (unsigned)p.Value;\n    if ((flags & flag) != 0)\n    {\n      if (p.Name[0] != 0)\n        s.Add_OptSpaced(p.Name);\n    }\n    flags &= ~flag;\n  }\n  if (flags != 0)\n  {\n    {\n      char sz[32];\n      sz[0] = '0';\n      sz[1] = 'x';\n      ConvertUInt64ToHex(flags, sz + 2);\n      s.Add_OptSpaced(sz);\n    }\n  }\n  return s;\n}\n\nvoid Flags64ToProp(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags, NCOM::CPropVariant &prop)\n{\n  prop = Flags64ToString(pairs, num, flags);\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/PropVariantUtils.h",
    "content": "﻿// Windows/PropVariantUtils.h\n\n#ifndef ZIP7_INC_PROP_VARIANT_UTILS_H\n#define ZIP7_INC_PROP_VARIANT_UTILS_H\n\n#include \"../Common/MyString.h\"\n\n#include \"PropVariant.h\"\n\nstruct CUInt32PCharPair\n{\n  UInt32 Value;\n  const char *Name;\n};\n\nAString TypePairToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 value);\nvoid PairToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);\n\nAString FlagsToString(const char * const *names, unsigned num, UInt32 flags);\nAString FlagsToString(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags);\nvoid FlagsToProp(const char * const *names, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop);\nvoid FlagsToProp(const CUInt32PCharPair *pairs, unsigned num, UInt32 flags, NWindows::NCOM::CPropVariant &prop);\n\nAString TypeToString(const char * const table[], unsigned num, UInt32 value);\nvoid TypeToProp(const char * const table[], unsigned num, UInt32 value, NWindows::NCOM::CPropVariant &prop);\n\n#define PAIR_TO_PROP(pairs, value, prop) PairToProp(pairs, Z7_ARRAY_SIZE(pairs), value, prop)\n#define FLAGS_TO_PROP(pairs, value, prop) FlagsToProp(pairs, Z7_ARRAY_SIZE(pairs), value, prop)\n#define TYPE_TO_PROP(table, value, prop) TypeToProp(table, Z7_ARRAY_SIZE(table), value, prop)\n\nvoid Flags64ToProp(const CUInt32PCharPair *pairs, unsigned num, UInt64 flags, NWindows::NCOM::CPropVariant &prop);\n#define FLAGS64_TO_PROP(pairs, value, prop) Flags64ToProp(pairs, Z7_ARRAY_SIZE(pairs), value, prop)\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Registry.cpp",
    "content": "﻿// Windows/Registry.cpp\n\n#include \"StdAfx.h\"\n\n#include <wchar.h>\n// #include <stdio.h>\n\n#ifndef _UNICODE\n#include \"../Common/StringConvert.h\"\n#endif\n#include \"Registry.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\nnamespace NRegistry {\n\n#define MYASSERT(expr) // _ASSERTE(expr)\n#define MY_ASSUME(expr)\n\n/*\nstatic void Error()\n{\n  #ifdef _CONSOLE\n  printf(\"\\nregistry error\\n\");\n  #else\n  MessageBoxW(0, L\"registry error\", L\"\", 0);\n  // exit(1);\n  #endif\n}\n\n#define MY_ASSUME(expr) { if (!(expr)) Error(); }\n*/\n\nLONG CKey::Create(HKEY parentKey, LPCTSTR keyName,\n    LPTSTR keyClass, DWORD options, REGSAM accessMask,\n    LPSECURITY_ATTRIBUTES securityAttributes, LPDWORD disposition) throw()\n{\n  MY_ASSUME(parentKey != NULL);\n  DWORD dispositionReal;\n  HKEY key = NULL;\n  LONG res = RegCreateKeyEx(parentKey, keyName, 0, keyClass,\n      options, accessMask, securityAttributes, &key, &dispositionReal);\n  if (disposition != NULL)\n    *disposition = dispositionReal;\n  if (res == ERROR_SUCCESS)\n  {\n    res = Close();\n    _object = key;\n  }\n  return res;\n}\n\nLONG CKey::Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask) throw()\n{\n  MY_ASSUME(parentKey != NULL);\n  HKEY key = NULL;\n  LONG res = RegOpenKeyEx(parentKey, keyName, 0, accessMask, &key);\n  if (res == ERROR_SUCCESS)\n  {\n    res = Close();\n    MYASSERT(res == ERROR_SUCCESS);\n    _object = key;\n  }\n  return res;\n}\n\nLONG CKey::Close() throw()\n{\n  LONG res = ERROR_SUCCESS;\n  if (_object != NULL)\n  {\n    res = RegCloseKey(_object);\n    _object = NULL;\n  }\n  return res;\n}\n\n// win95, win98: deletes subkey and all its subkeys\n// winNT to be deleted must not have subkeys\nLONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw()\n{\n  MY_ASSUME(_object != NULL);\n  return RegDeleteKey(_object, subKeyName);\n}\n\nLONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw()\n{\n  {\n    CKey key;\n    LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE);\n    if (res != ERROR_SUCCESS)\n      return res;\n    FILETIME fileTime;\n    const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL\n    TCHAR buffer[kBufSize];\n    // we use loop limit here for some unexpected code failure\n    for (unsigned loop_cnt = 0; loop_cnt < (1u << 26); loop_cnt++)\n    {\n      DWORD size = kBufSize;\n      // we always request starting item (index==0) in each iteration,\n      // because we remove starting item (index==0) in each loop iteration.\n      res = RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime);\n      if (res != ERROR_SUCCESS)\n      {\n        // possible return codes:\n        //   ERROR_NO_MORE_ITEMS : are no more subkeys available\n        //   ERROR_MORE_DATA     : name buffer is too small\n        // we can try to remove (subKeyName), even if there is non ERROR_NO_MORE_ITEMS error.\n        // if (res != ERROR_NO_MORE_ITEMS) return res;\n        break;\n      }\n      res = key.RecurseDeleteKey(buffer);\n      if (res != ERROR_SUCCESS)\n        return res;\n    }\n    // key.Close();\n  }\n  return DeleteSubKey(subKeyName);\n}\n\n\n/////////////////////////\n// Value Functions\n\nstatic inline UInt32 BoolToUINT32(bool value) {  return (value ? 1: 0); }\nstatic inline bool UINT32ToBool(UInt32 value) {  return (value != 0); }\n\n\nLONG CKey::DeleteValue(LPCTSTR name) throw()\n{\n  MY_ASSUME(_object != NULL);\n  return ::RegDeleteValue(_object, name);\n}\n\n#ifndef _UNICODE\nLONG CKey::DeleteValue(LPCWSTR name)\n{\n  MY_ASSUME(_object != NULL);\n  if (g_IsNT)\n    return ::RegDeleteValueW(_object, name);\n  return DeleteValue(name == NULL ? NULL : (LPCSTR)GetSystemString(name));\n}\n#endif\n\nLONG CKey::SetValue(LPCTSTR name, UInt32 value) throw()\n{\n  MY_ASSUME(_object != NULL);\n  return RegSetValueEx(_object, name, 0, REG_DWORD,\n      (const BYTE *)&value, sizeof(UInt32));\n}\n\nLONG CKey::SetValue(LPCTSTR name, bool value) throw()\n{\n  return SetValue(name, BoolToUINT32(value));\n}\n\n\n// value must be string that is NULL terminated\nLONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw()\n{\n  MYASSERT(value != NULL);\n  MY_ASSUME(_object != NULL);\n  // note: RegSetValueEx supports (value == NULL), if (cbData == 0)\n  return RegSetValueEx(_object, name, 0, REG_SZ,\n      (const BYTE *)value, (DWORD)(((DWORD)lstrlen(value) + 1) * sizeof(TCHAR)));\n}\n\n/*\nLONG CKey::SetValue(LPCTSTR name, const CSysString &value)\n{\n  MYASSERT(value != NULL);\n  MY_ASSUME(_object != NULL);\n  return RegSetValueEx(_object, name, 0, REG_SZ,\n      (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR));\n}\n*/\n\n#ifndef _UNICODE\n\nLONG CKey::SetValue(LPCWSTR name, LPCWSTR value)\n{\n  MYASSERT(value != NULL);\n  MY_ASSUME(_object != NULL);\n  if (g_IsNT)\n    return RegSetValueExW(_object, name, 0, REG_SZ,\n        (const BYTE *)value, (DWORD)(((DWORD)wcslen(value) + 1) * sizeof(wchar_t)));\n  return SetValue(name == NULL ? NULL :\n        (LPCSTR)GetSystemString(name),\n        (LPCSTR)GetSystemString(value));\n}\n\n#endif\n\n\nLONG CKey::SetValue(LPCTSTR name, const void *value, UInt32 size) throw()\n{\n  MYASSERT(value != NULL);\n  MY_ASSUME(_object != NULL);\n  return RegSetValueEx(_object, name, 0, REG_BINARY,\n      (const BYTE *)value, size);\n}\n\nLONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value)\n{\n  MYASSERT(value != NULL);\n  CKey key;\n  LONG res = key.Create(parentKey, keyName);\n  if (res == ERROR_SUCCESS)\n    res = key.SetValue(valueName, value);\n  return res;\n}\n\nLONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw()\n{\n  MYASSERT(value != NULL);\n  CKey key;\n  LONG res = key.Create(_object, keyName);\n  if (res == ERROR_SUCCESS)\n    res = key.SetValue(valueName, value);\n  return res;\n}\n\n\nLONG CKey::GetValue_UInt32_IfOk(LPCTSTR name, UInt32 &value) throw()\n{\n  DWORD type = 0;\n  DWORD count = sizeof(value);\n  UInt32 value2; // = value;\n  const LONG res = QueryValueEx(name, &type, (LPBYTE)&value2, &count);\n  if (res == ERROR_SUCCESS)\n  {\n    // ERROR_UNSUPPORTED_TYPE\n    if (count != sizeof(value) || type != REG_DWORD)\n      return ERROR_UNSUPPORTED_TYPE; // ERROR_INVALID_DATA;\n    value = value2;\n  }\n  return res;\n}\n\nLONG CKey::GetValue_UInt64_IfOk(LPCTSTR name, UInt64 &value) throw()\n{\n  DWORD type = 0;\n  DWORD count = sizeof(value);\n  UInt64 value2; // = value;\n  const LONG res = QueryValueEx(name, &type, (LPBYTE)&value2, &count);\n  if (res == ERROR_SUCCESS)\n  {\n    if (count != sizeof(value) || type != REG_QWORD)\n      return ERROR_UNSUPPORTED_TYPE;\n    value = value2;\n  }\n  return res;\n}\n\nLONG CKey::GetValue_bool_IfOk(LPCTSTR name, bool &value) throw()\n{\n  UInt32 uintValue;\n  const LONG res = GetValue_UInt32_IfOk(name, uintValue);\n  if (res == ERROR_SUCCESS)\n    value = UINT32ToBool(uintValue);\n  return res;\n}\n\n\n\nLONG CKey::QueryValue(LPCTSTR name, CSysString &value)\n{\n  value.Empty();\n  LONG res = ERROR_SUCCESS;\n  {\n    // if we don't want multiple calls here,\n    // we can use big value (264) here.\n    // 3 is default available length in new string.\n    DWORD size_prev = 3 * sizeof(TCHAR);\n    // at least 2 attempts are required. But we use more attempts for cases,\n    // where string can be changed by anothner process\n    for (unsigned i = 0; i < 2 + 2; i++)\n    {\n      DWORD type = 0;\n      DWORD size = size_prev;\n      {\n        LPBYTE buf = (LPBYTE)value.GetBuf(size / sizeof(TCHAR));\n        res = QueryValueEx(name, &type, size == 0 ? NULL : buf, &size);\n        // if (size_prev == 0), then (res == ERROR_SUCCESS) is expected here, because we requested only size.\n      }\n      if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA)\n      {\n        if (type != REG_SZ && type != REG_EXPAND_SZ)\n        {\n          res = ERROR_UNSUPPORTED_TYPE;\n          size = 0;\n        }\n      }\n      else\n        size = 0;\n      if (size > size_prev)\n      {\n        size_prev = size;\n        size = 0;\n        res = ERROR_MORE_DATA;\n      }\n      value.ReleaseBuf_CalcLen(size / sizeof(TCHAR));\n      if (res != ERROR_MORE_DATA)\n        return res;\n    }\n  }\n  return res;\n}\n\n\n#ifndef _UNICODE\n\nLONG CKey::QueryValue(LPCWSTR name, UString &value)\n{\n  value.Empty();\n  LONG res = ERROR_SUCCESS;\n  if (g_IsNT)\n  {\n    DWORD size_prev = 3 * sizeof(wchar_t);\n    for (unsigned i = 0; i < 2 + 2; i++)\n    {\n      DWORD type = 0;\n      DWORD size = size_prev;\n      {\n        LPBYTE buf = (LPBYTE)value.GetBuf(size / sizeof(wchar_t));\n        res = RegQueryValueExW(_object, name, NULL, &type,\n            size == 0 ? NULL : buf, &size);\n      }\n      if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA)\n      {\n        if (type != REG_SZ && type != REG_EXPAND_SZ)\n        {\n          res = ERROR_UNSUPPORTED_TYPE;\n          size = 0;\n        }\n      }\n      else\n        size = 0;\n      if (size > size_prev)\n      {\n        size_prev = size;\n        size = 0;\n        res = ERROR_MORE_DATA;\n      }\n      value.ReleaseBuf_CalcLen(size / sizeof(wchar_t));\n      if (res != ERROR_MORE_DATA)\n        return res;\n    }\n  }\n  else\n  {\n    AString vTemp;\n    res = QueryValue(name == NULL ? NULL : (LPCSTR)GetSystemString(name), vTemp);\n    value = GetUnicodeString(vTemp);\n  }\n  return res;\n}\n\n#endif\n\n\nLONG CKey::QueryValue_Binary(LPCTSTR name, CByteBuffer &value)\n{\n  // value.Free();\n  DWORD size_prev = 0;\n  LONG res = ERROR_SUCCESS;\n  for (unsigned i = 0; i < 2 + 2; i++)\n  {\n    DWORD type = 0;\n    DWORD size = size_prev;\n    value.Alloc(size_prev);\n    res = QueryValueEx(name, &type, value.NonConstData(), &size);\n    // if (size_prev == 0), then (res == ERROR_SUCCESS) is expected here, because we requested only size.\n    if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA)\n    {\n      if (type != REG_BINARY)\n      {\n        res = ERROR_UNSUPPORTED_TYPE;\n        size = 0;\n      }\n    }\n    else\n      size = 0;\n    if (size > size_prev)\n    {\n      size_prev = size;\n      size = 0;\n      res = ERROR_MORE_DATA;\n    }\n    if (size < value.Size())\n      value.ChangeSize_KeepData(size, size);\n    if (res != ERROR_MORE_DATA)\n      return res;\n  }\n  return res;\n}\n\n\nLONG CKey::EnumKeys(CSysStringVector &keyNames)\n{\n  keyNames.Clear();\n  CSysString keyName;\n  for (DWORD index = 0; ; index++)\n  {\n    const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL\n    FILETIME lastWriteTime;\n    DWORD nameSize = kBufSize;\n    const LONG res = ::RegEnumKeyEx(_object, index,\n        keyName.GetBuf(kBufSize), &nameSize,\n        NULL, NULL, NULL, &lastWriteTime);\n    keyName.ReleaseBuf_CalcLen(kBufSize);\n    if (res == ERROR_NO_MORE_ITEMS)\n      return ERROR_SUCCESS;\n    if (res != ERROR_SUCCESS)\n      return res;\n    keyNames.Add(keyName);\n  }\n}\n\n\nLONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings)\n{\n  size_t numChars = 0;\n  unsigned i;\n  \n  for (i = 0; i < strings.Size(); i++)\n    numChars += strings[i].Len() + 1;\n  \n  CObjArray<wchar_t> buffer(numChars);\n  size_t pos = 0;\n  \n  for (i = 0; i < strings.Size(); i++)\n  {\n    const UString &s = strings[i];\n    const size_t size = s.Len() + 1;\n    wmemcpy(buffer + pos, s, size);\n    pos += size;\n  }\n  // if (pos != numChars) return E_FAIL;\n  return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t));\n}\n\nLONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings)\n{\n  strings.Clear();\n  CByteBuffer buffer;\n  const LONG res = QueryValue_Binary(valueName, buffer);\n  if (res != ERROR_SUCCESS)\n    return res;\n  const size_t dataSize = buffer.Size();\n  if (dataSize % sizeof(wchar_t))\n    return ERROR_INVALID_DATA;\n  const wchar_t *data = (const wchar_t *)(const void *)(const Byte  *)buffer;\n  const size_t numChars = dataSize / sizeof(wchar_t);\n  // we can check that all names are finished\n  // if (numChars != 0 && data[numChars - 1] != 0) return ERROR_INVALID_DATA;\n  size_t prev = 0;\n  UString s;\n  for (size_t i = 0; i < numChars; i++)\n  {\n    if (data[i] == 0)\n    {\n      s = data + prev;\n      strings.Add(s);\n      prev = i + 1;\n    }\n  }\n  return res;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Registry.h",
    "content": "﻿// Windows/Registry.h\n\n#ifndef ZIP7_INC_WINDOWS_REGISTRY_H\n#define ZIP7_INC_WINDOWS_REGISTRY_H\n\n#include \"../Common/MyBuffer.h\"\n#include \"../Common/MyString.h\"\n\nnamespace NWindows {\nnamespace NRegistry {\n\nLONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value);\n\nclass CKey\n{\n  HKEY _object;\n\n  LONG QueryValueEx(LPCTSTR lpValueName, LPDWORD lpType,\n      LPBYTE lpData, LPDWORD lpcbData)\n  {\n    return RegQueryValueEx(_object, lpValueName, NULL, lpType, lpData, lpcbData);\n  }\n\npublic:\n  CKey(): _object(NULL) {}\n  ~CKey() { Close(); }\n\n  operator HKEY() const { return _object; }\n  void Attach(HKEY key) { _object = key; }\n  HKEY Detach()\n  {\n    const HKEY key = _object;\n    _object = NULL;\n    return key;\n  }\n\n  LONG Create(HKEY parentKey, LPCTSTR keyName,\n      LPTSTR keyClass = REG_NONE,\n      DWORD options = REG_OPTION_NON_VOLATILE,\n      REGSAM accessMask = KEY_ALL_ACCESS,\n      LPSECURITY_ATTRIBUTES securityAttributes = NULL,\n      LPDWORD disposition = NULL) throw();\n  LONG Open(HKEY parentKey, LPCTSTR keyName, REGSAM accessMask = KEY_ALL_ACCESS) throw();\n\n  LONG Close() throw();\n\n  LONG DeleteSubKey(LPCTSTR subKeyName) throw();\n  LONG RecurseDeleteKey(LPCTSTR subKeyName) throw();\n\n  LONG DeleteValue(LPCTSTR name) throw();\n#ifndef _UNICODE\n  LONG DeleteValue(LPCWSTR name);\n#endif\n\n  LONG SetValue(LPCTSTR valueName, UInt32 value) throw();\n  LONG SetValue(LPCTSTR valueName, bool value) throw();\n  LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw();\n  // LONG SetValue(LPCTSTR valueName, const CSysString &value);\n#ifndef _UNICODE\n  LONG SetValue(LPCWSTR name, LPCWSTR value);\n  // LONG SetValue(LPCWSTR name, const UString &value);\n#endif\n\n  LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw();\n\n  LONG SetValue_Strings(LPCTSTR valueName, const UStringVector &strings);\n  LONG GetValue_Strings(LPCTSTR valueName, UStringVector &strings);\n\n  LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw();\n\n  // GetValue_[type]_IfOk():\n  //   if (return_result == ERROR_SUCCESS), (value) variable was read from registry\n  //   if (return_result != ERROR_SUCCESS), (value) variable was not changed\n  LONG GetValue_UInt32_IfOk(LPCTSTR name, UInt32 &value) throw();\n  LONG GetValue_UInt64_IfOk(LPCTSTR name, UInt64 &value) throw();\n  LONG GetValue_bool_IfOk(LPCTSTR name, bool &value) throw();\n\n  // QueryValue():\n  //   if (return_result == ERROR_SUCCESS), (value) string was read from registry\n  //   if (return_result != ERROR_SUCCESS), (value) string was cleared\n  LONG QueryValue(LPCTSTR name, CSysString &value);\n  // **************** 7-Zip ZS Modification Start ****************\n  inline LONG QueryValue(LPCTSTR name, bool &value) {\n    return GetValue_bool_IfOk(name, value);\n  }\n  // **************** 7-Zip ZS Modification End ****************\n#ifndef _UNICODE\n  LONG QueryValue(LPCWSTR name, UString &value);\n#endif\n\n  // QueryValue_Binary():\n  //   if (return_result == ERROR_SUCCESS), (value) buffer was read from registry (BINARY data)\n  //   if (return_result != ERROR_SUCCESS), (value) buffer was cleared\n  LONG QueryValue_Binary(LPCTSTR name, CByteBuffer &value);\n\n  LONG EnumKeys(CSysStringVector &keyNames);\n};\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/ResourceString.cpp",
    "content": "﻿// Windows/ResourceString.cpp\n\n#include \"StdAfx.h\"\n\n#ifndef _UNICODE\n#include \"../Common/StringConvert.h\"\n#endif\n\n#include \"ResourceString.h\"\n\nextern HINSTANCE g_hInstance;\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\n\n#ifndef _UNICODE\n\nstatic CSysString MyLoadStringA(HINSTANCE hInstance, UINT resourceID)\n{\n  CSysString s;\n  int size = 128;\n  int len;\n  do\n  {\n    size <<= 1;\n    len = ::LoadString(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size);\n  }\n  while (size - len <= 1);\n  s.ReleaseBuf_CalcLen((unsigned)len);\n  return s;\n}\n\n#endif\n\nstatic const int kStartSize = 256;\n\nstatic void MyLoadString2(HINSTANCE hInstance, UINT resourceID, UString &s)\n{\n  int size = kStartSize;\n  int len;\n  do\n  {\n    size <<= 1;\n    len = ::LoadStringW(hInstance, resourceID, s.GetBuf((unsigned)size - 1), size);\n  }\n  while (size - len <= 1);\n  s.ReleaseBuf_CalcLen((unsigned)len);\n}\n\n// NT4 doesn't support LoadStringW(,,, 0) to get pointer to resource string. So we don't use it.\n\nUString MyLoadString(UINT resourceID)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n    return GetUnicodeString(MyLoadStringA(g_hInstance, resourceID));\n  else\n  #endif\n  {\n    {\n      wchar_t s[kStartSize];\n      s[0] = 0;\n      int len = ::LoadStringW(g_hInstance, resourceID, s, kStartSize);\n      if (kStartSize - len > 1)\n        return s;\n    }\n    UString dest;\n    MyLoadString2(g_hInstance, resourceID, dest);\n    return dest;\n  }\n}\n\nvoid MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest)\n{\n  dest.Empty();\n  #ifndef _UNICODE\n  if (!g_IsNT)\n    MultiByteToUnicodeString2(dest, MyLoadStringA(hInstance, resourceID));\n  else\n  #endif\n  {\n    {\n      wchar_t s[kStartSize];\n      s[0] = 0;\n      int len = ::LoadStringW(hInstance, resourceID, s, kStartSize);\n      if (kStartSize - len > 1)\n      {\n        dest = s;\n        return;\n      }\n    }\n    MyLoadString2(hInstance, resourceID, dest);\n  }\n}\n\nvoid MyLoadString(UINT resourceID, UString &dest)\n{\n  MyLoadString(g_hInstance, resourceID, dest);\n}\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/ResourceString.h",
    "content": "﻿// Windows/ResourceString.h\n\n#ifndef ZIP7_INC_WINDOWS_RESOURCE_STRING_H\n#define ZIP7_INC_WINDOWS_RESOURCE_STRING_H\n\n#include \"../Common/MyString.h\"\n#include \"../Common/MyWindows.h\"\n\nnamespace NWindows {\n\nUString MyLoadString(UINT resourceID);\nvoid MyLoadString(HINSTANCE hInstance, UINT resourceID, UString &dest);\nvoid MyLoadString(UINT resourceID, UString &dest);\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/SecurityUtils.cpp",
    "content": "﻿// Windows/SecurityUtils.cpp\n\n#include \"StdAfx.h\"\n\n#include \"SecurityUtils.h\"\n\nnamespace NWindows {\nnamespace NSecurity {\n\n/*\nbool MyLookupAccountSid(LPCTSTR systemName, PSID sid,\n  CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse)\n{\n  DWORD accountNameSize = 0, domainNameSize = 0;\n\n  if (!::LookupAccountSid(systemName, sid,\n      accountName.GetBuf(0), &accountNameSize,\n      domainName.GetBuf(0), &domainNameSize, sidNameUse))\n  {\n    if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)\n      return false;\n  }\n  DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize;\n  bool result = BOOLToBool(::LookupAccountSid(systemName, sid,\n      accountName.GetBuf(accountNameSize), &accountNameSize2,\n      domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse));\n  accountName.ReleaseBuf_CalcLen(accountNameSize);\n  domainName.ReleaseBuf_CalcLen(domainNameSize);\n  return result;\n}\n*/\n  \nstatic void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest)\n{\n  const size_t len = (size_t)wcslen(src);\n  dest->Length = (USHORT)(len * sizeof(WCHAR));\n  dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR));\n  dest->Buffer = src;\n}\n\n/*\nstatic void MyLookupSids(CPolicy &policy, PSID ps)\n{\n  LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL;\n  LSA_TRANSLATED_NAME *names = NULL;\n  NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names);\n  int res = LsaNtStatusToWinError(nts);\n  LsaFreeMemory(referencedDomains);\n  LsaFreeMemory(names);\n}\n*/\n\nextern \"C\" {\n\n#ifndef _UNICODE\ntypedef BOOL (WINAPI * Func_LookupAccountNameW)(\n    LPCWSTR lpSystemName,\n    LPCWSTR lpAccountName,\n    PSID Sid,\n    LPDWORD cbSid,\n    LPWSTR ReferencedDomainName,\n    LPDWORD cchReferencedDomainName,\n    PSID_NAME_USE peUse\n    );\n#endif\n\n}\n\nstatic PSID GetSid(LPWSTR accountName)\n{\n  #ifndef _UNICODE\n  const HMODULE hModule = GetModuleHandle(TEXT(\"advapi32.dll\"));\n  if (!hModule)\n    return NULL;\n  const\n  Func_LookupAccountNameW lookupAccountNameW = Z7_GET_PROC_ADDRESS(\n  Func_LookupAccountNameW, hModule,\n      \"LookupAccountNameW\");\n  if (!lookupAccountNameW)\n    return NULL;\n  #endif\n\n  DWORD sidLen = 0, domainLen = 0;\n  SID_NAME_USE sidNameUse;\n  if (!\n    #ifdef _UNICODE\n    ::LookupAccountNameW\n    #else\n      lookupAccountNameW\n    #endif\n        (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse))\n  {\n    if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)\n    {\n      const PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen);\n      LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR));\n      const BOOL res =\n        #ifdef _UNICODE\n        ::LookupAccountNameW\n        #else\n          lookupAccountNameW\n        #endif\n            (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse);\n      ::HeapFree(GetProcessHeap(), 0, domainName);\n      if (res)\n        return pSid;\n    }\n  }\n  return NULL;\n}\n\n#define Z7_WIN_SE_LOCK_MEMORY_NAME L\"SeLockMemoryPrivilege\"\n\nbool AddLockMemoryPrivilege()\n{\n  CPolicy policy;\n  LSA_OBJECT_ATTRIBUTES attr;\n  attr.Length = sizeof(attr);\n  attr.RootDirectory = NULL;\n  attr.ObjectName  = NULL;\n  attr.Attributes = 0;\n  attr.SecurityDescriptor = NULL;\n  attr.SecurityQualityOfService  = NULL;\n  if (policy.Open(NULL, &attr,\n      // GENERIC_WRITE)\n      POLICY_ALL_ACCESS)\n      // STANDARD_RIGHTS_REQUIRED,\n      // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES)\n      != 0)\n    return false;\n  LSA_UNICODE_STRING userRights;\n  wchar_t s[128] = Z7_WIN_SE_LOCK_MEMORY_NAME;\n  SetLsaString(s, &userRights);\n  WCHAR userName[256 + 2];\n  DWORD size = 256;\n  if (!GetUserNameW(userName, &size))\n    return false;\n  const PSID psid = GetSid(userName);\n  if (psid == NULL)\n    return false;\n  bool res = false;\n\n  /*\n  PLSA_UNICODE_STRING userRightsArray;\n  ULONG countOfRights;\n  NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights);\n  if (status != 0)\n    return false;\n  bool finded = false;\n  for (ULONG i = 0; i < countOfRights; i++)\n  {\n    LSA_UNICODE_STRING &ur = userRightsArray[i];\n    if (ur.Length != s.Length() * sizeof(WCHAR))\n      continue;\n    if (wcsncmp(ur.Buffer, s, s.Length()) != 0)\n      continue;\n    finded = true;\n    res = true;\n    break;\n  }\n  if (!finded)\n  */\n  {\n    /*\n    LSA_ENUMERATION_INFORMATION *enums;\n    ULONG countReturned;\n    NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned);\n    if (status == 0)\n    {\n      for (ULONG i = 0; i < countReturned; i++)\n        MyLookupSids(policy, enums[i].Sid);\n      if (enums)\n        ::LsaFreeMemory(enums);\n      res = true;\n    }\n    */\n    const NTSTATUS status = policy.AddAccountRights(psid, &userRights);\n    if (status == 0)\n      res = true;\n    // ULONG res = LsaNtStatusToWinError(status);\n  }\n  HeapFree(GetProcessHeap(), 0, psid);\n  return res;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/SecurityUtils.h",
    "content": "﻿// Windows/SecurityUtils.h\n\n#ifndef ZIP7_INC_WINDOWS_SECURITY_UTILS_H\n#define ZIP7_INC_WINDOWS_SECURITY_UTILS_H\n\n#if defined(__MINGW32__) || defined(__MINGW64__)\n#include <ntsecapi.h>\n#else\n#include <NTSecAPI.h>\n#endif\n\n#include \"Defs.h\"\n\n#ifndef _UNICODE\n\nextern \"C\" {\ntypedef NTSTATUS (NTAPI *Func_LsaOpenPolicy)(PLSA_UNICODE_STRING SystemName,\n    PLSA_OBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess, PLSA_HANDLE PolicyHandle);\ntypedef NTSTATUS (NTAPI *Func_LsaClose)(LSA_HANDLE ObjectHandle);\ntypedef NTSTATUS (NTAPI *Func_LsaAddAccountRights)(LSA_HANDLE PolicyHandle,\n    PSID AccountSid, PLSA_UNICODE_STRING UserRights, ULONG CountOfRights );\n#define MY_STATUS_NOT_IMPLEMENTED  ((NTSTATUS)0xC0000002L)\n}\n\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\n#define POLICY_FUNC_CALL(fff, str)  \\\n  if (hModule == NULL) return MY_STATUS_NOT_IMPLEMENTED; \\\n  const Func_ ## fff v = Z7_GET_PROC_ADDRESS(Func_ ## fff, hModule, str); \\\n  if (!v) return MY_STATUS_NOT_IMPLEMENTED; \\\n  const NTSTATUS res = v\n\n#else\n\n#define POLICY_FUNC_CALL(fff, str)  \\\n  const NTSTATUS res = ::fff\n\n#endif\n\n\nnamespace NWindows {\nnamespace NSecurity {\n\nclass CAccessToken\n{\n  HANDLE _handle;\npublic:\n  CAccessToken(): _handle(NULL) {}\n  ~CAccessToken() { Close(); }\n  bool Close()\n  {\n    if (_handle == NULL)\n      return true;\n    bool res = BOOLToBool(::CloseHandle(_handle));\n    if (res)\n      _handle = NULL;\n    return res;\n  }\n\n  bool OpenProcessToken(HANDLE processHandle, DWORD desiredAccess)\n  {\n    Close();\n    return BOOLToBool(::OpenProcessToken(processHandle, desiredAccess, &_handle));\n  }\n\n  /*\n  bool OpenThreadToken(HANDLE threadHandle, DWORD desiredAccess, bool openAsSelf)\n  {\n    Close();\n    return BOOLToBool(::OpenTreadToken(threadHandle, desiredAccess, BoolToBOOL(anOpenAsSelf), &_handle));\n  }\n  */\n\n  bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState,\n      DWORD bufferLength, PTOKEN_PRIVILEGES previousState, PDWORD returnLength)\n    { return BOOLToBool(::AdjustTokenPrivileges(_handle, BoolToBOOL(disableAllPrivileges),\n      newState, bufferLength, previousState, returnLength)); }\n  \n  bool AdjustPrivileges(bool disableAllPrivileges, PTOKEN_PRIVILEGES newState)\n    { return AdjustPrivileges(disableAllPrivileges, newState, 0, NULL, NULL); }\n  \n  bool AdjustPrivileges(PTOKEN_PRIVILEGES newState)\n    { return AdjustPrivileges(false, newState); }\n\n};\n\n\n\n    \nstruct CPolicy\n{\nprotected:\n  LSA_HANDLE _handle;\n  #ifndef _UNICODE\n  HMODULE hModule;\n  #endif\npublic:\n  operator LSA_HANDLE() const { return _handle; }\n  CPolicy(): _handle(NULL)\n  {\n    #ifndef _UNICODE\n    hModule = GetModuleHandle(TEXT(\"advapi32.dll\"));\n    #endif\n  }\n  ~CPolicy() { Close(); }\n\n  NTSTATUS Open(PLSA_UNICODE_STRING systemName, PLSA_OBJECT_ATTRIBUTES objectAttributes,\n      ACCESS_MASK desiredAccess)\n  {\n    Close();\n    POLICY_FUNC_CALL (LsaOpenPolicy, \"LsaOpenPolicy\")\n      (systemName, objectAttributes, desiredAccess, &_handle);\n    return res;\n  }\n  \n  NTSTATUS Close()\n  {\n    if (_handle == NULL)\n      return 0;\n    POLICY_FUNC_CALL (LsaClose, \"LsaClose\")\n      (_handle);\n    _handle = NULL;\n    return res;\n  }\n  \n  NTSTATUS EnumerateAccountsWithUserRight(PLSA_UNICODE_STRING userRights,\n      PLSA_ENUMERATION_INFORMATION *enumerationBuffer, PULONG countReturned)\n    { return LsaEnumerateAccountsWithUserRight(_handle, userRights, (void **)enumerationBuffer, countReturned); }\n\n  NTSTATUS EnumerateAccountRights(PSID sid, PLSA_UNICODE_STRING* userRights, PULONG countOfRights)\n    { return ::LsaEnumerateAccountRights(_handle, sid, userRights, countOfRights); }\n\n  NTSTATUS LookupSids(ULONG count, PSID* sids,\n      PLSA_REFERENCED_DOMAIN_LIST* referencedDomains, PLSA_TRANSLATED_NAME* names)\n    { return LsaLookupSids(_handle, count, sids, referencedDomains, names); }\n\n  NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights, ULONG countOfRights)\n  {\n    POLICY_FUNC_CALL (LsaAddAccountRights, \"LsaAddAccountRights\")\n      (_handle, accountSid, userRights, countOfRights);\n    return res;\n  }\n  NTSTATUS AddAccountRights(PSID accountSid, PLSA_UNICODE_STRING userRights)\n    { return AddAccountRights(accountSid, userRights, 1); }\n\n  NTSTATUS RemoveAccountRights(PSID accountSid, bool allRights, PLSA_UNICODE_STRING userRights, ULONG countOfRights)\n    { return LsaRemoveAccountRights(_handle, accountSid, (BOOLEAN)(allRights ? TRUE : FALSE), userRights, countOfRights); }\n};\n\nbool AddLockMemoryPrivilege();\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Shell.cpp",
    "content": "﻿// Windows/Shell.cpp\n\n#include \"StdAfx.h\"\n\n#include \"../Common/MyCom.h\"\n#include \"../Common/StringConvert.h\"\n\n#include \"COM.h\"\n#include \"FileName.h\"\n#include \"MemoryGlobal.h\"\n#include \"Shell.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\n// MSVC6 and old SDK don't support this function:\n// #define LWSTDAPI  EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE\n// LWSTDAPI StrRetToStrW(STRRET *pstr, LPCITEMIDLIST pidl, LPWSTR *ppsz);\n\n// #define SHOW_DEBUG_SHELL\n\n#ifdef SHOW_DEBUG_SHELL\n\n#include \"../Common/IntToString.h\"\n\nstatic void Print_Number(UInt32 number, const char *s)\n{\n  AString s2;\n  s2.Add_UInt32(number);\n  s2.Add_Space();\n  s2 += s;\n  OutputDebugStringA(s2);\n}\n\n#define ODS(sz) { OutputDebugStringA(sz); }\n#define ODS_U(s) { OutputDebugStringW(s); }\n#define ODS_(op) { op; }\n\n#else\n\n#define ODS(sz)\n#define ODS_U(s)\n#define ODS_(op)\n\n#endif\n\n\nnamespace NWindows {\nnamespace NShell {\n\n#ifndef UNDER_CE\n\n// SHGetMalloc is unsupported in Windows Mobile?\n\nvoid CItemIDList::Free()\n{\n  if (!m_Object)\n    return;\n  /* DOCs:\n      SHGetMalloc was introduced in Windows 95 and Microsoft Windows NT 4.0,\n      but as of Windows 2000 it is no longer necessary.\n      In its place, programs can call the equivalent (and easier to use) CoTaskMemAlloc and CoTaskMemFree.\n     Description from oldnewthings:\n       shell functions could work without COM (if OLE32.DLL is not loaded),\n       but now if OLE32.DLL is loaded, then shell functions and com functions do same things.\n     22.02: so we use OLE32.DLL function to free memory:\n  */\n  /*\n  CMyComPtr<IMalloc> shellMalloc;\n  if (::SHGetMalloc(&shellMalloc) != NOERROR)\n    throw 41099;\n  shellMalloc->Free(m_Object);\n  */\n  CoTaskMemFree(m_Object);\n  m_Object = NULL;\n}\n\n/*\nCItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)\n  {  *this = itemIDList; }\nCItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)\n  {  *this = itemIDList; }\n\nCItemIDList& CItemIDList::operator=(LPCITEMIDLIST object)\n{\n  Free();\n  if (object != 0)\n  {\n    UINT32 size = GetSize(object);\n    m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);\n    if (m_Object != NULL)\n      MoveMemory(m_Object, object, size);\n  }\n  return *this;\n}\n\nCItemIDList& CItemIDList::operator=(const CItemIDList &object)\n{\n  Free();\n  if (object.m_Object != NULL)\n  {\n    UINT32 size = GetSize(object.m_Object);\n    m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);\n    if (m_Object != NULL)\n      MoveMemory(m_Object, object.m_Object, size);\n  }\n  return *this;\n}\n*/\n\n\nstatic HRESULT ReadUnicodeStrings(const wchar_t *p, size_t size, UStringVector &names)\n{\n  names.Clear();\n  const wchar_t *lim = p + size;\n  UString s;\n  /*\n  if (size == 0 || p[size - 1] != 0)\n    return E_INVALIDARG;\n  if (size == 1)\n    return S_OK;\n  if (p[size - 2] != 0)\n    return E_INVALIDARG;\n  */\n  for (;;)\n  {\n    const wchar_t *start = p;\n    for (;;)\n    {\n      if (p == lim) return E_INVALIDARG; // S_FALSE\n      if (*p++ == 0)\n        break;\n    }\n    const size_t num = (size_t)(p - start);\n    if (num == 1)\n    {\n      if (p != lim) return E_INVALIDARG; // S_FALSE\n      return S_OK;\n    }\n    s.SetFrom(start, (unsigned)(num - 1));\n    ODS_U(s)\n    names.Add(s);\n    // names.ReserveOnePosition();\n    // names.AddInReserved_Ptr_of_new(new UString((unsigned)num - 1, start));\n  }\n}\n\n\nstatic HRESULT ReadAnsiStrings(const char *p, size_t size, UStringVector &names)\n{\n  names.Clear();\n  AString name;\n  for (; size != 0; size--)\n  {\n    const char c = *p++;\n    if (c == 0)\n    {\n      if (name.IsEmpty())\n        return S_OK;\n      names.Add(GetUnicodeString(name));\n      name.Empty();\n    }\n    else\n      name.Add_Char(c);\n  }\n  return E_INVALIDARG;\n}\n\n\n#define INIT_FORMATETC_HGLOBAL(type) { (type), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }\n\nstatic HRESULT DataObject_GetData_HGLOBAL(IDataObject *dataObject, CLIPFORMAT cf, NCOM::CStgMedium &medium)\n{\n  FORMATETC etc = INIT_FORMATETC_HGLOBAL(cf);\n  RINOK(dataObject->GetData(&etc, &medium))\n  if (medium.tymed != TYMED_HGLOBAL)\n    return E_INVALIDARG;\n  return S_OK;\n}\n\nstatic HRESULT DataObject_GetData_HDROP_Names(IDataObject *dataObject, UStringVector &names)\n{\n  names.Clear();\n  NCOM::CStgMedium medium;\n  \n  /* Win10 : if (dataObject) is from IContextMenu::Initialize() and\n    if (len_of_path >= MAX_PATH (260) for some file in data object)\n    {\n      GetData() returns HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)\n        \"The data area passed to a system call is too small\",\n      Is there a way to fix this code for long paths?\n    } */\n\n  RINOK(DataObject_GetData_HGLOBAL(dataObject, CF_HDROP, medium))\n  const size_t blockSize = GlobalSize(medium.hGlobal);\n  if (blockSize < sizeof(DROPFILES))\n    return E_INVALIDARG;\n  NMemory::CGlobalLock dropLock(medium.hGlobal);\n  const DROPFILES *dropFiles = (const DROPFILES *)dropLock.GetPointer();\n  if (!dropFiles)\n    return E_INVALIDARG;\n  if (blockSize < dropFiles->pFiles\n      || dropFiles->pFiles < sizeof(DROPFILES)\n      // || dropFiles->pFiles != sizeof(DROPFILES)\n      )\n    return E_INVALIDARG;\n  const size_t size = blockSize - dropFiles->pFiles;\n  const void *namesData = (const Byte *)(const void *)dropFiles + dropFiles->pFiles;\n  HRESULT hres;\n  if (dropFiles->fWide)\n  {\n    if (size % sizeof(wchar_t) != 0)\n      return E_INVALIDARG;\n    hres = ReadUnicodeStrings((const wchar_t *)namesData, size / sizeof(wchar_t), names);\n  }\n  else\n    hres = ReadAnsiStrings((const char *)namesData, size, names);\n\n  ODS_(Print_Number(names.Size(), \"DataObject_GetData_HDROP_Names\"))\n  return hres;\n}\n\n\n\n// CF_IDLIST:\n#define MYWIN_CFSTR_SHELLIDLIST  TEXT(\"Shell IDList Array\")\n\ntypedef struct\n{\n  UINT cidl;\n  UINT aoffset[1];\n} MYWIN_CIDA;\n/*\n  cidl : number of PIDLs that are being transferred, not including the parent folder.\n  aoffset : An array of offsets, relative to the beginning of this structure.\n  aoffset[0] - fully qualified PIDL of a parent folder.\n               If this PIDL is empty, the parent folder is the desktop.\n  aoffset[1] ... aoffset[cidl] : offset to one of the PIDLs to be transferred.\n  All of these PIDLs are relative to the PIDL of the parent folder.\n*/\n\nstatic HRESULT DataObject_GetData_IDLIST(IDataObject *dataObject, UStringVector &names)\n{\n  names.Clear();\n  NCOM::CStgMedium medium;\n  RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT)\n      RegisterClipboardFormat(MYWIN_CFSTR_SHELLIDLIST), medium))\n  const size_t blockSize = GlobalSize(medium.hGlobal);\n  if (blockSize < sizeof(MYWIN_CIDA) || blockSize >= (UInt32)((UInt32)0 - 1))\n    return E_INVALIDARG;\n  NMemory::CGlobalLock dropLock(medium.hGlobal);\n  const MYWIN_CIDA *cida = (const MYWIN_CIDA *)dropLock.GetPointer();\n  if (!cida)\n    return E_INVALIDARG;\n  if (cida->cidl == 0)\n  {\n    // is it posssible to have no selected items?\n    // it's unexpected case.\n    return E_INVALIDARG;\n  }\n  if (cida->cidl >= (blockSize - (UInt32)sizeof(MYWIN_CIDA)) / sizeof(UINT))\n    return E_INVALIDARG;\n  const UInt32 start = cida->cidl * (UInt32)sizeof(UINT) + (UInt32)sizeof(MYWIN_CIDA);\n\n  STRRET strret;\n  CMyComPtr<IShellFolder> parentFolder;\n  {\n    const UINT offset = cida->aoffset[0];\n    if (offset < start || offset >= blockSize\n        // || offset != start\n        )\n      return E_INVALIDARG;\n\n    CMyComPtr<IShellFolder> desktopFolder;\n    RINOK(::SHGetDesktopFolder(&desktopFolder))\n    if (!desktopFolder)\n      return E_FAIL;\n    \n    LPCITEMIDLIST const lpcItem = (LPCITEMIDLIST)(const void *)((const Byte *)cida + offset);\n\n   #ifdef SHOW_DEBUG_SHELL\n    {\n      const HRESULT res = desktopFolder->GetDisplayNameOf(\n          lpcItem, SHGDN_FORPARSING, &strret);\n      if (res == S_OK && strret.uType == STRRET_WSTR)\n      {\n        ODS_U(strret.pOleStr)\n        /* if lpcItem is empty, the path will be\n             \"C:\\Users\\user_name\\Desktop\"\n           if lpcItem is \"My Computer\" folder, the path will be\n             \"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\" */\n        CoTaskMemFree(strret.pOleStr);\n      }\n    }\n   #endif\n    \n    RINOK(desktopFolder->BindToObject(lpcItem,\n        NULL, IID_IShellFolder, (void **)&parentFolder))\n    if (!parentFolder)\n      return E_FAIL;\n  }\n  \n  names.ClearAndReserve(cida->cidl);\n  UString path;\n  \n  // for (int y = 0; y < 1; y++) // for debug\n  for (unsigned i = 1; i <= cida->cidl; i++)\n  {\n    const UINT offset = cida->aoffset[i];\n    if (offset < start || offset >= blockSize)\n      return E_INVALIDARG;\n    const void *p = (const Byte *)(const void *)cida + offset;\n    /* ITEMIDLIST of file can contain more than one SHITEMID item.\n       In win10 only SHGDN_FORPARSING returns path that contains\n       all path parts related to parts of ITEMIDLIST.\n       So we can use only SHGDN_FORPARSING here.\n       Don't use (SHGDN_INFOLDER)\n       Don't use (SHGDN_INFOLDER | SHGDN_FORPARSING)\n    */\n    RINOK(parentFolder->GetDisplayNameOf((LPCITEMIDLIST)p, SHGDN_FORPARSING, &strret))\n\n    /*\n    // MSVC6 and old SDK do not support StrRetToStrW().\n    LPWSTR lpstr;\n    RINOK (StrRetToStrW(&strret, NULL, &lpstr))\n    ODS_U(lpstr)\n    path = lpstr;\n    CoTaskMemFree(lpstr);\n    */\n    if (strret.uType != STRRET_WSTR)\n      return E_INVALIDARG;\n    ODS_U(strret.pOleStr)\n    path = strret.pOleStr;\n    // the path could have super path prefix \"\\\\\\\\?\\\\\"\n    // we can remove super path prefix here, if we don't need that prefix\n  #ifdef Z7_LONG_PATH\n    // we remove super prefix, if we can work without that prefix\n    NFile::NName::If_IsSuperPath_RemoveSuperPrefix(path);\n  #endif\n    names.AddInReserved(path);\n    CoTaskMemFree(strret.pOleStr);\n  }\n\n  ODS_(Print_Number(cida->cidl, \"CFSTR_SHELLIDLIST END\"))\n  return S_OK;\n}\n\n\nHRESULT DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject *dataObject, UStringVector &paths)\n{\n  ODS(\"-- DataObject_GetData_HDROP_or_IDLIST_Names START\")\n  HRESULT hres = NShell::DataObject_GetData_HDROP_Names(dataObject, paths);\n  // if (hres == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))\n  if (hres != S_OK)\n  {\n    ODS(\"-- DataObject_GetData_IDLIST START\")\n    // for (int y = 0; y < 10000; y++) // for debug\n    hres = NShell::DataObject_GetData_IDLIST(dataObject, paths);\n  }\n  ODS(\"-- DataObject_GetData_HDROP_or_IDLIST_Names END\")\n  return hres;\n}\n\n\n\n// #if (NTDDI_VERSION >= NTDDI_VISTA)\ntypedef struct\n{\n  UINT cItems;                    // number of items in rgdwFileAttributes array\n  DWORD dwSumFileAttributes;      // all of the attributes ORed together\n  DWORD dwProductFileAttributes;  // all of the attributes ANDed together\n  DWORD rgdwFileAttributes[1];    // array\n} MYWIN_FILE_ATTRIBUTES_ARRAY;\n\n#define MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY  TEXT(\"File Attributes Array\")\n\nHRESULT DataObject_GetData_FILE_ATTRS(IDataObject *dataObject, CFileAttribs &attribs)\n{\n  attribs.Clear();\n  NCOM::CStgMedium medium;\n  RINOK(DataObject_GetData_HGLOBAL(dataObject, (CLIPFORMAT)\n      RegisterClipboardFormat(MYWIN_CFSTR_FILE_ATTRIBUTES_ARRAY), medium))\n  const size_t blockSize = GlobalSize(medium.hGlobal);\n  if (blockSize < sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY))\n    return E_INVALIDARG;\n  NMemory::CGlobalLock dropLock(medium.hGlobal);\n  const MYWIN_FILE_ATTRIBUTES_ARRAY *faa = (const MYWIN_FILE_ATTRIBUTES_ARRAY *)dropLock.GetPointer();\n  if (!faa)\n    return E_INVALIDARG;\n  const unsigned numFiles = faa->cItems;\n  if (numFiles == 0)\n  {\n    // is it posssible to have empty array here?\n    return E_INVALIDARG;\n  }\n  if ((blockSize - (sizeof(MYWIN_FILE_ATTRIBUTES_ARRAY) - sizeof(DWORD)))\n      / sizeof(DWORD) != numFiles)\n    return E_INVALIDARG;\n  // attribs.Sum = faa->dwSumFileAttributes;\n  // attribs.Product = faa->dwProductFileAttributes;\n  // attribs.Vals.SetFromArray(faa->rgdwFileAttributes, numFiles);\n  // attribs.IsDirVector.ClearAndSetSize(numFiles);\n\n  if ((faa->dwSumFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)\n  {\n    /* in win10: if selected items are volumes (c:\\, d:\\ ..) in  My Compter,\n       all items have FILE_ATTRIBUTE_DIRECTORY attribute\n       ntfs volume also have FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM\n       udf volume: FILE_ATTRIBUTE_READONLY\n       dvd-rom device: (-1) : all bits are set\n    */\n    const DWORD *attr = faa->rgdwFileAttributes;\n    // DWORD product = (UInt32)0 - 1, sum = 0;\n    for (unsigned i = 0; i < numFiles; i++)\n    {\n      if (attr[i] & FILE_ATTRIBUTE_DIRECTORY)\n      {\n        // attribs.ThereAreDirs = true;\n        attribs.FirstDirIndex = (int)i;\n        break;\n      }\n      // attribs.IsDirVector[i] = (attr[i] & FILE_ATTRIBUTE_DIRECTORY) != 0;\n      // product &= v;\n      // sum |= v;\n    }\n    // ODS_(Print_Number(product, \"Product calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names\"))\n    // ODS_(Print_Number(sum, \"Sum calc FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names\"))\n  }\n  // ODS_(Print_Number(attribs.Product, \"Product FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names\"))\n  // ODS_(Print_Number(attribs.Sum, \"Sum FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names\"))\n  ODS_(Print_Number(numFiles, \"FILE_ATTRIBUTES_ARRAY ==== DataObject_GetData_HDROP_Names\"))\n  return S_OK;\n}\n\n\n/////////////////////////////\n// CDrop\n\n/*\n  win10:\n  DragQueryFile() implementation code is not effective because\n  there is no pointer inside DROP internal file list, so\n  DragQueryFile(fileIndex) runs all names in range [0, fileIndex].\n  DragQueryFile(,, buf, bufSize)\n  if (buf == NULL) by spec\n  {\n    returns value is the required size\n    in characters, of the buffer, not including the terminating null character\n    tests show that if (bufSize == 0), then it also returns  required size.\n  }\n  if (bufSize != NULL)\n  {\n    returns: the count of the characters copied, not including null character.\n    win10: null character is also  copied at position buf[ret_count];\n  }\n*/\n\n/*\nvoid CDrop::Attach(HDROP object)\n{\n  Free();\n  m_Object = object;\n  m_Assigned = true;\n}\n\nvoid CDrop::Free()\n{\n  if (m_MustBeFinished && m_Assigned)\n    Finish();\n  m_Assigned = false;\n}\n\nUINT CDrop::QueryCountOfFiles()\n{\n  return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);\n}\n\nvoid CDrop::QueryFileName(UINT fileIndex, UString &fileName)\n{\n  #ifndef _UNICODE\n  if (!g_IsNT)\n  {\n    AString fileNameA;\n    const UINT len = QueryFile(fileIndex, (LPTSTR)NULL, 0);\n    const UINT numCopied = QueryFile(fileIndex, fileNameA.GetBuf(len + 2), len + 2);\n    fileNameA.ReleaseBuf_CalcLen(len);\n    if (numCopied != len)\n      throw 20221223;\n    fileName = GetUnicodeString(fileNameA);\n  }\n  else\n  #endif\n  {\n    // kReserve must be >= 3 for additional buffer size\n    //   safety and for optimal performance\n    const unsigned kReserve = 3;\n    {\n      unsigned len = 0;\n      wchar_t *buf = fileName.GetBuf_GetMaxAvail(len);\n      if (len >= kReserve)\n      {\n        const UINT numCopied = QueryFile(fileIndex, buf, len);\n        if (numCopied < len - 1)\n        {\n          // (numCopied < len - 1) case means that it have copied full string.\n          fileName.ReleaseBuf_CalcLen(numCopied);\n          return;\n        }\n      }\n    }\n    const UINT len = QueryFile(fileIndex, (LPWSTR)NULL, 0);\n    const UINT numCopied = QueryFile(fileIndex,\n        fileName.GetBuf(len + kReserve), len + kReserve);\n    fileName.ReleaseBuf_CalcLen(len);\n    if (numCopied != len)\n      throw 20221223;\n  }\n}\n\n\nvoid CDrop::QueryFileNames(UStringVector &fileNames)\n{\n  UINT numFiles = QueryCountOfFiles();\n  \n  Print_Number(numFiles, \"\\n====== CDrop::QueryFileNames START ===== \\n\");\n\n  fileNames.ClearAndReserve(numFiles);\n  UString s;\n  for (UINT i = 0; i < numFiles; i++)\n  {\n    QueryFileName(i, s);\n    if (!s.IsEmpty())\n      fileNames.AddInReserved(s);\n  }\n  Print_Number(numFiles, \"\\n====== CDrop::QueryFileNames END ===== \\n\");\n}\n*/\n\n\n// #if (NTDDI_VERSION >= NTDDI_VISTA)\n// SHGetPathFromIDListEx returns a win32 file system path for the item in the name space.\ntypedef int Z7_WIN_GPFIDL_FLAGS;\n\nextern \"C\" {\n#ifndef _UNICODE\ntypedef BOOL (WINAPI * Func_SHGetPathFromIDListW)(LPCITEMIDLIST pidl, LPWSTR pszPath); // nt4\n#endif\n\n#if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0600  // Vista\n#define Z7_USE_DYN_SHGetPathFromIDListEx\n#endif\n\n#ifdef Z7_USE_DYN_SHGetPathFromIDListEx\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\ntypedef BOOL (WINAPI * Func_SHGetPathFromIDListEx)(LPCITEMIDLIST pidl, PWSTR pszPath, DWORD cchPath, Z7_WIN_GPFIDL_FLAGS uOpts); // vista\n#endif\n}\n\n#ifndef _UNICODE\n\nbool GetPathFromIDList(LPCITEMIDLIST itemIDList, AString &path)\n{\n  path.Empty();\n  const unsigned len = MAX_PATH + 16;\n  const bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));\n  path.ReleaseBuf_CalcLen(len);\n  return result;\n}\n\n#endif\n\nbool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)\n{\n  path.Empty();\n  unsigned len = MAX_PATH + 16;\n\n#ifdef _UNICODE\n  bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuf(len)));\n#else\n  const\n  Func_SHGetPathFromIDListW\n       shGetPathFromIDListW = Z7_GET_PROC_ADDRESS(\n  Func_SHGetPathFromIDListW, ::GetModuleHandleW(L\"shell32.dll\"),\n      \"SHGetPathFromIDListW\");\n  if (!shGetPathFromIDListW)\n    return false;\n  bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuf(len)));\n#endif\n\n  if (!result)\n  {\n    ODS(\"==== GetPathFromIDList() SHGetPathFromIDList() returned false\")\n    /* for long path we need SHGetPathFromIDListEx().\n      win10: SHGetPathFromIDListEx() for long path returns path with\n             with super path prefix \"\\\\\\\\?\\\\\". */\n#ifdef Z7_USE_DYN_SHGetPathFromIDListEx\n    const\n    Func_SHGetPathFromIDListEx\n    func_SHGetPathFromIDListEx = Z7_GET_PROC_ADDRESS(\n    Func_SHGetPathFromIDListEx, ::GetModuleHandleW(L\"shell32.dll\"),\n        \"SHGetPathFromIDListEx\");\n    if (func_SHGetPathFromIDListEx)\n#endif\n    {\n      ODS(\"==== GetPathFromIDList() (SHGetPathFromIDListEx)\")\n      do\n      {\n        len *= 4;\n        result = BOOLToBool(\n#ifdef Z7_USE_DYN_SHGetPathFromIDListEx\n          func_SHGetPathFromIDListEx\n#else\n          SHGetPathFromIDListEx\n#endif\n          (itemIDList, path.GetBuf(len), len, 0));\n        if (result)\n          break;\n      }\n      while (len <= (1 << 16));\n    }\n  }\n\n  path.ReleaseBuf_CalcLen(len);\n  return result;\n}\n\n#endif\n\n#ifdef UNDER_CE\n\nbool BrowseForFolder(LPBROWSEINFO, CSysString)\n{\n  return false;\n}\n\nbool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)\n{\n  return false;\n}\n\nbool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,\n    LPCTSTR /* initialFolder */, CSysString & /* resultPath */)\n{\n  /*\n  // SHBrowseForFolder doesn't work before CE 6.0 ?\n  if (GetProcAddress(LoadLibrary(L\"ceshell.dll\", L\"SHBrowseForFolder\") == 0)\n    MessageBoxW(0, L\"no\", L\"\", 0);\n  else\n    MessageBoxW(0, L\"yes\", L\"\", 0);\n  */\n  /*\n  UString s = \"all files\";\n  s += \" (*.*)\";\n  return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);\n  */\n  return false;\n}\n\n#else\n\n/* win10: SHBrowseForFolder() doesn't support long paths,\n   even if long path suppport is enabled in registry and in manifest.\n   and SHBrowseForFolder() doesn't support super path prefix \"\\\\\\\\?\\\\\". */\n\nbool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)\n{\n  resultPath.Empty();\n  NWindows::NCOM::CComInitializer comInitializer;\n  LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);\n  if (!itemIDList)\n    return false;\n  CItemIDList itemIDListHolder;\n  itemIDListHolder.Attach(itemIDList);\n  return GetPathFromIDList(itemIDList, resultPath);\n}\n\n\nstatic int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)\n{\n  #ifndef UNDER_CE\n  switch (uMsg)\n  {\n    case BFFM_INITIALIZED:\n    {\n      SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);\n      break;\n    }\n    /*\n    case BFFM_SELCHANGED:\n    {\n      TCHAR dir[MAX_PATH];\n      if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))\n        SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);\n      else\n        SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(\"\"));\n      break;\n    }\n    */\n    default:\n      break;\n  }\n  #endif\n  return 0;\n}\n\n\nstatic bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,\n    LPCTSTR initialFolder, CSysString &resultPath)\n{\n  CSysString displayName;\n  BROWSEINFO browseInfo;\n  browseInfo.hwndOwner = owner;\n  browseInfo.pidlRoot = NULL;\n\n  // there are Unicode/Astring problems in some WinCE SDK ?\n  /*\n  #ifdef UNDER_CE\n  browseInfo.pszDisplayName = (LPSTR)displayName.GetBuf(MAX_PATH);\n  browseInfo.lpszTitle = (LPCSTR)title;\n  #else\n  */\n  browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);\n  browseInfo.lpszTitle = title;\n  // #endif\n  browseInfo.ulFlags = ulFlags;\n  browseInfo.lpfn = initialFolder ? BrowseCallbackProc : NULL;\n  browseInfo.lParam = (LPARAM)initialFolder;\n  return BrowseForFolder(&browseInfo, resultPath);\n}\n\n#ifdef Z7_OLD_WIN_SDK\n// ShlObj.h:\n#ifndef BIF_NEWDIALOGSTYLE\n#define BIF_NEWDIALOGSTYLE     0x0040\n#endif\n#endif\n\nbool BrowseForFolder(HWND owner, LPCTSTR title,\n    LPCTSTR initialFolder, CSysString &resultPath)\n{\n  return BrowseForFolder(owner, title,\n      #ifndef UNDER_CE\n      BIF_NEWDIALOGSTYLE |\n      #endif\n      BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);\n  // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)\n}\n\n#ifndef _UNICODE\n\nextern \"C\" {\ntypedef LPITEMIDLIST (WINAPI * Func_SHBrowseForFolderW)(LPBROWSEINFOW lpbi);\n}\n\nstatic bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)\n{\n  NWindows::NCOM::CComInitializer comInitializer;\n  const\n  Func_SHBrowseForFolderW\n     f_SHBrowseForFolderW = Z7_GET_PROC_ADDRESS(\n  Func_SHBrowseForFolderW, ::GetModuleHandleW(L\"shell32.dll\"),\n      \"SHBrowseForFolderW\");\n  if (!f_SHBrowseForFolderW)\n    return false;\n  LPITEMIDLIST itemIDList = f_SHBrowseForFolderW(browseInfo);\n  if (!itemIDList)\n    return false;\n  CItemIDList itemIDListHolder;\n  itemIDListHolder.Attach(itemIDList);\n  return GetPathFromIDList(itemIDList, resultPath);\n}\n\nstatic\nint CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)\n{\n  switch (uMsg)\n  {\n    case BFFM_INITIALIZED:\n    {\n      SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);\n      break;\n    }\n    /*\n    case BFFM_SELCHANGED:\n    {\n      wchar_t dir[MAX_PATH * 2];\n\n      if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))\n        SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);\n      else\n        SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L\"\");\n      break;\n    }\n    */\n    default:\n      break;\n  }\n  return 0;\n}\n\n\nstatic bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,\n    LPCWSTR initialFolder, UString &resultPath)\n{\n  UString displayName;\n  BROWSEINFOW browseInfo;\n  browseInfo.hwndOwner = owner;\n  browseInfo.pidlRoot = NULL;\n  browseInfo.pszDisplayName = displayName.GetBuf(MAX_PATH);\n  browseInfo.lpszTitle = title;\n  browseInfo.ulFlags = ulFlags;\n  browseInfo.lpfn = initialFolder ? BrowseCallbackProc2 : NULL;\n  browseInfo.lParam = (LPARAM)initialFolder;\n  return BrowseForFolder(&browseInfo, resultPath);\n}\n\nbool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)\n{\n  if (g_IsNT)\n    return BrowseForFolder(owner, title,\n      BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS\n      //  | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.\n      , initialFolder, resultPath);\n  // BIF_STATUSTEXT; BIF_USENEWUI   (Version 5.0)\n  CSysString s;\n  bool res = BrowseForFolder(owner, GetSystemString(title),\n      BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS\n      // | BIF_STATUSTEXT  // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.\n      , GetSystemString(initialFolder), s);\n  resultPath = GetUnicodeString(s);\n  return res;\n}\n\n#endif\n\n#endif\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Shell.h",
    "content": "﻿// Windows/Shell.h\n\n#ifndef ZIP7_WINDOWS_SHELL_H\n#define ZIP7_WINDOWS_SHELL_H\n\n#include \"../Common/MyWindows.h\"\n#if defined(__MINGW32__) || defined(__MINGW64__)\n#include <shlobj.h>\n#else\n#include <ShlObj.h>\n#endif\n\n#include \"../Common/MyString.h\"\n\n#include \"Defs.h\"\n\nnamespace NWindows {\nnamespace NShell {\n\n/////////////////////////\n// CItemIDList\n#ifndef UNDER_CE\n\nclass CItemIDList\n{\n  LPITEMIDLIST m_Object;\n  Z7_CLASS_NO_COPY(CItemIDList)\npublic:\n  CItemIDList(): m_Object(NULL) {}\n  // CItemIDList(LPCITEMIDLIST itemIDList);\n  // CItemIDList(const CItemIDList& itemIDList);\n  ~CItemIDList() { Free(); }\n  void Free();\n  void Attach(LPITEMIDLIST object)\n  {\n    Free();\n    m_Object = object;\n  }\n  LPITEMIDLIST Detach()\n  {\n    LPITEMIDLIST object = m_Object;\n    m_Object = NULL;\n    return object;\n  }\n  operator LPITEMIDLIST() { return m_Object;}\n  operator LPCITEMIDLIST() const { return m_Object;}\n  LPITEMIDLIST* operator&() { return &m_Object; }\n  LPITEMIDLIST operator->() { return m_Object; }\n\n  // CItemIDList& operator=(LPCITEMIDLIST object);\n  // CItemIDList& operator=(const CItemIDList &object);\n};\n\n/////////////////////////////\n// CDrop\n\n/*\nclass CDrop\n{\n  HDROP m_Object;\n  bool m_MustBeFinished;\n  bool m_Assigned;\n  void Free();\npublic:\n  CDrop(bool mustBeFinished) : m_MustBeFinished(mustBeFinished), m_Assigned(false) {}\n  ~CDrop() { Free(); }\n\n  void Attach(HDROP object);\n  operator HDROP() { return m_Object;}\n  bool QueryPoint(LPPOINT point)\n    { return BOOLToBool(::DragQueryPoint(m_Object, point)); }\n  void Finish()\n  {\n    ::DragFinish(m_Object);\n  }\n  UINT QueryFile(UINT fileIndex, LPTSTR fileName, UINT bufSize)\n    { return ::DragQueryFile(m_Object, fileIndex, fileName, bufSize); }\n  #ifndef _UNICODE\n  UINT QueryFile(UINT fileIndex, LPWSTR fileName, UINT bufSize)\n    { return ::DragQueryFileW(m_Object, fileIndex, fileName, bufSize); }\n  #endif\n  UINT QueryCountOfFiles();\n  void QueryFileName(UINT fileIndex, UString &fileName);\n  void QueryFileNames(UStringVector &fileNames);\n};\n*/\n#endif\n\nstruct CFileAttribs\n{\n  int FirstDirIndex;\n  // DWORD Sum;\n  // DWORD Product;\n  // CRecordVector<DWORD> Vals;\n  // CRecordVector<bool> IsDirVector;\n\n  CFileAttribs()\n  {\n    Clear();\n  }\n\n  void Clear()\n  {\n    FirstDirIndex = -1;\n    // Sum = 0;\n    // Product = 0;\n    // IsDirVector.Clear();\n  }\n};\n\n\n/* read pathnames from HDROP or SHELLIDLIST.\n   The parser can return E_INVALIDARG, if there is some unexpected data in dataObject */\nHRESULT DataObject_GetData_HDROP_or_IDLIST_Names(IDataObject *dataObject, UStringVector &names);\n\nHRESULT DataObject_GetData_FILE_ATTRS(IDataObject *dataObject, CFileAttribs &attribs);\n\nbool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path);\nbool BrowseForFolder(LPBROWSEINFO lpbi, CSysString &resultPath);\nbool BrowseForFolder(HWND owner, LPCTSTR title, LPCTSTR initialFolder, CSysString &resultPath);\n\n#ifndef _UNICODE\nbool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path);\nbool BrowseForFolder(LPBROWSEINFO lpbi, UString &resultPath);\nbool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath);\n#endif\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/StdAfx.h",
    "content": "﻿// StdAfx.h\n\n#ifndef ZIP7_INC_STDAFX_H\n#define ZIP7_INC_STDAFX_H\n\n#if defined(_MSC_VER) && _MSC_VER >= 1800\n#pragma warning(disable : 4464) // relative include path contains '..'\n#endif\n#include \"../Common/Common.h\"\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Synchronization.cpp",
    "content": "﻿// Windows/Synchronization.cpp\n\n#include \"StdAfx.h\"\n\n#ifndef _WIN32\n\n#include \"Synchronization.h\"\n\nnamespace NWindows {\nnamespace NSynchronization {\n\n/*\n#define INFINITE  0xFFFFFFFF\n#define MAXIMUM_WAIT_OBJECTS 64\n#define STATUS_ABANDONED_WAIT_0 ((NTSTATUS)0x00000080L)\n#define WAIT_ABANDONED   ((STATUS_ABANDONED_WAIT_0 ) + 0 )\n#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )\n// WINAPI\nDWORD WaitForMultipleObjects(DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout);\n*/\n\n/* clang: we need to place some virtual functions in cpp file to rid off the warning:\n   'CBaseHandle_WFMO' has no out-of-line virtual method definitions;\n   its vtable will be emitted in every translation unit */\nCBaseHandle_WFMO::~CBaseHandle_WFMO()\n{\n}\n\nbool CBaseEvent_WFMO::IsSignaledAndUpdate()\n{\n  if (this->_state == false)\n    return false;\n  if (this->_manual_reset == false)\n    this->_state = false;\n  return true;\n}\n\nbool CSemaphore_WFMO::IsSignaledAndUpdate()\n{\n  if (this->_count == 0)\n    return false;\n  this->_count--;\n  return true;\n}\n\nDWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles)\n{\n  if (count < 1)\n  {\n    // abort();\n    SetLastError(EINVAL);\n    return WAIT_FAILED;\n  }\n\n  CSynchro *synchro = handles[0]->_sync;\n  synchro->Enter();\n  \n  // #ifdef DEBUG_SYNCHRO\n  for (DWORD i = 1; i < count; i++)\n  {\n    if (synchro != handles[i]->_sync)\n    {\n      // abort();\n      synchro->Leave();\n      SetLastError(EINVAL);\n      return WAIT_FAILED;\n    }\n  }\n  // #endif\n\n  for (;;)\n  {\n    for (DWORD i = 0; i < count; i++)\n    {\n      if (handles[i]->IsSignaledAndUpdate())\n      {\n        synchro->Leave();\n        return WAIT_OBJECT_0 + i;\n      }\n    }\n    synchro->WaitCond();\n  }\n}\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Synchronization.h",
    "content": "﻿// Windows/Synchronization.h\n\n#ifndef ZIP7_INC_WINDOWS_SYNCHRONIZATION_H\n#define ZIP7_INC_WINDOWS_SYNCHRONIZATION_H\n\n#include \"../../C/Threads.h\"\n\n#include \"../Common/MyTypes.h\"\n\n#include \"Defs.h\"\n\n#ifdef _WIN32\n#include \"Handle.h\"\n#endif\n\nnamespace NWindows {\nnamespace NSynchronization {\n\nclass CBaseEvent  MY_UNCOPYABLE\n{\nprotected:\n  ::CEvent _object;\npublic:\n  bool IsCreated() { return Event_IsCreated(&_object) != 0; }\n\n  CBaseEvent() { Event_Construct(&_object); }\n  ~CBaseEvent() { Close(); }\n  WRes Close() { return Event_Close(&_object); }\n\n  #ifdef _WIN32\n  operator HANDLE() { return _object; }\n  WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)\n  {\n    _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name);\n    if (name == NULL && _object != NULL)\n      return 0;\n    return ::GetLastError();\n  }\n  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)\n  {\n    _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name);\n    if (_object != NULL)\n      return 0;\n    return ::GetLastError();\n  }\n  #endif\n\n  WRes Set() { return Event_Set(&_object); }\n  // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); }\n  WRes Reset() { return Event_Reset(&_object); }\n  WRes Lock() { return Event_Wait(&_object); }\n};\n\nclass CManualResetEvent: public CBaseEvent\n{\npublic:\n  WRes Create(bool initiallyOwn = false)\n  {\n    return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0);\n  }\n  WRes CreateIfNotCreated_Reset()\n  {\n    if (IsCreated())\n      return Reset();\n    return ManualResetEvent_CreateNotSignaled(&_object);\n  }\n  #ifdef _WIN32\n  WRes CreateWithName(bool initiallyOwn, LPCTSTR name)\n  {\n    return CBaseEvent::Create(true, initiallyOwn, name);\n  }\n  #endif\n};\n\nclass CAutoResetEvent: public CBaseEvent\n{\npublic:\n  WRes Create()\n  {\n    return AutoResetEvent_CreateNotSignaled(&_object);\n  }\n  WRes CreateIfNotCreated_Reset()\n  {\n    if (IsCreated())\n      return Reset();\n    return AutoResetEvent_CreateNotSignaled(&_object);\n  }\n};\n\n\n/*\n#ifdef _WIN32\n\nclass CObject: public CHandle\n{\npublic:\n  WRes Lock(DWORD timeoutInterval = INFINITE)\n    { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }\n};\n\nclass CMutex: public CObject\n{\npublic:\n  WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)\n  {\n    _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name);\n    if (name == NULL && _handle != 0)\n      return 0;\n    return ::GetLastError();\n  }\n  #ifndef UNDER_CE\n  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)\n  {\n    _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name);\n    if (_handle != 0)\n      return 0;\n    return ::GetLastError();\n  }\n  #endif\n  WRes Release()\n  {\n    return ::ReleaseMutex(_handle) ? 0 : ::GetLastError();\n  }\n};\n\nclass CMutexLock  MY_UNCOPYABLE\n{\n  CMutex *_object;\npublic:\n  CMutexLock(CMutex &object): _object(&object) { _object->Lock(); }\n  ~CMutexLock() { _object->Release(); }\n};\n\n#endif // _WIN32\n*/\n\n\nclass CSemaphore  MY_UNCOPYABLE\n{\n  ::CSemaphore _object;\npublic:\n  CSemaphore() { Semaphore_Construct(&_object); }\n  ~CSemaphore() { Close(); }\n  WRes Close() { return Semaphore_Close(&_object); }\n\n  #ifdef _WIN32\n  operator HANDLE() { return _object; }\n  #endif\n\n  // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; }\n\n  WRes Create(UInt32 initCount, UInt32 maxCount)\n  {\n    return Semaphore_Create(&_object, initCount, maxCount);\n  }\n  WRes OptCreateInit(UInt32 initCount, UInt32 maxCount)\n  {\n    return Semaphore_OptCreateInit(&_object, initCount, maxCount);\n  }\n  WRes Release() { return Semaphore_Release1(&_object); }\n  WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); }\n  WRes Lock() { return Semaphore_Wait(&_object); }\n};\n\nclass CCriticalSection  MY_UNCOPYABLE\n{\n  ::CCriticalSection _object;\npublic:\n  CCriticalSection() { CriticalSection_Init(&_object); }\n  ~CCriticalSection() { CriticalSection_Delete(&_object); }\n  void Enter() { CriticalSection_Enter(&_object); }\n  void Leave() { CriticalSection_Leave(&_object); }\n};\n\nclass CCriticalSectionLock  MY_UNCOPYABLE\n{\n  CCriticalSection *_object;\n  void Unlock()  { _object->Leave(); }\npublic:\n  CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); }\n  ~CCriticalSectionLock() { Unlock(); }\n};\n\n\n#ifdef _WIN32\n\ntypedef HANDLE CHandle_WFMO;\ntypedef CSemaphore CSemaphore_WFMO;\ntypedef CAutoResetEvent CAutoResetEvent_WFMO;\ntypedef CManualResetEvent CManualResetEvent_WFMO;\n\ninline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles)\n{\n  return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE);\n}\n\n#define SYNC_OBJ_DECL(obj)\n#define SYNC_WFMO(x)\n#define SYNC_PARAM(x)\n#define SYNC_PARAM_DECL(x)\n\n#else //  _WIN32\n\n// POSIX sync objects for WaitForMultipleObjects\n\n#define SYNC_WFMO(x) x\n#define SYNC_PARAM(x) x,\n#define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x\n#define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x;\n\nclass CSynchro  MY_UNCOPYABLE\n{\n  pthread_mutex_t _mutex;\n  pthread_cond_t _cond;\n  bool _isValid;\n\npublic:\n  CSynchro() { _isValid = false; }\n  ~CSynchro()\n  {\n    if (_isValid)\n    {\n      ::pthread_mutex_destroy(&_mutex);\n      ::pthread_cond_destroy(&_cond);\n    }\n    _isValid = false;\n  }\n  WRes Create()\n  {\n    RINOK(::pthread_mutex_init(&_mutex, NULL))\n    const WRes ret = ::pthread_cond_init(&_cond, NULL);\n    _isValid = 1;\n    return ret;\n  }\n  WRes Enter()\n  {\n#if defined(Z7_LLVM_CLANG_VERSION) && (__clang_major__ == 13) \\\n      && defined(__FreeBSD__)\n  #pragma GCC diagnostic ignored \"-Wthread-safety-negative\"\n  #pragma GCC diagnostic ignored \"-Wthread-safety-analysis\"\n#endif\n    return ::pthread_mutex_lock(&_mutex);\n  }\n  WRes Leave()\n  {\n    return ::pthread_mutex_unlock(&_mutex);\n  }\n  WRes WaitCond()\n  {\n    return ::pthread_cond_wait(&_cond, &_mutex);\n  }\n  WRes LeaveAndSignal()\n  {\n    const WRes res1 = ::pthread_cond_broadcast(&_cond);\n    const WRes res2 = ::pthread_mutex_unlock(&_mutex);\n    return (res2 ? res2 : res1);\n  }\n};\n\n\nstruct CBaseHandle_WFMO;\ntypedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO;\n\n// these constants are from Windows\n#define WAIT_OBJECT_0 0\n#define WAIT_FAILED ((DWORD)0xFFFFFFFF)\n\nDWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles);\n\n\nstruct CBaseHandle_WFMO  MY_UNCOPYABLE\n{\n  CSynchro *_sync;\n\n  CBaseHandle_WFMO(): _sync(NULL) {}\n  virtual ~CBaseHandle_WFMO();\n\n  operator CHandle_WFMO() { return this; }\n  virtual bool IsSignaledAndUpdate() = 0;\n};\n\n\nclass CBaseEvent_WFMO : public CBaseHandle_WFMO\n{\n  bool _manual_reset;\n  bool _state;\n\npublic:\n\n  // bool IsCreated()  { return (this->_sync != NULL); }\n  // CBaseEvent_WFMO()  { ; }\n  // ~CBaseEvent_WFMO() Z7_override { Close(); }\n\n  WRes Close() { this->_sync = NULL; return 0; }\n\n  WRes Create(\n      CSynchro *sync,\n      bool manualReset, bool initiallyOwn)\n  {\n    this->_sync         = sync;\n    this->_manual_reset = manualReset;\n    this->_state        = initiallyOwn;\n    return 0;\n  }\n\n  WRes Set()\n  {\n    RINOK(this->_sync->Enter())\n    this->_state = true;\n    return this->_sync->LeaveAndSignal();\n  }\n\n  WRes Reset()\n  {\n    RINOK(this->_sync->Enter())\n    this->_state = false;\n    return this->_sync->Leave();\n  }\n  \n  virtual bool IsSignaledAndUpdate() Z7_override;\n};\n\n\nclass CManualResetEvent_WFMO Z7_final: public CBaseEvent_WFMO\n{\npublic:\n  WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); }\n};\n\n\nclass CAutoResetEvent_WFMO Z7_final: public CBaseEvent_WFMO\n{\npublic:\n  WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); }\n  WRes CreateIfNotCreated_Reset(CSynchro *sync)\n  {\n    return Create(sync);\n  }\n};\n\n\nclass CSemaphore_WFMO Z7_final: public CBaseHandle_WFMO\n{\n  UInt32 _count;\n  UInt32 _maxCount;\n\npublic:\n  CSemaphore_WFMO() : _count(0), _maxCount(0) {}\n  \n  WRes Close() { this->_sync = NULL; return 0; }\n\n  WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount)\n  {\n    if (initCount > maxCount || maxCount < 1)\n      return EINVAL;\n    this->_sync     = sync;\n    this->_count    = initCount;\n    this->_maxCount = maxCount;\n    return 0;\n  }\n  \n  WRes Release(UInt32 releaseCount = 1)\n  {\n    if (releaseCount < 1)\n      return EINVAL;\n\n    RINOK(this->_sync->Enter())\n    UInt32 newCount = this->_count + releaseCount;\n    if (newCount > this->_maxCount)\n    {\n      RINOK(this->_sync->Leave())\n      return ERROR_TOO_MANY_POSTS; // EINVAL\n    }\n    this->_count = newCount;\n\n    return this->_sync->LeaveAndSignal();\n  }\n\n  virtual bool IsSignaledAndUpdate() Z7_override;\n};\n\n#endif // _WIN32\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/System.cpp",
    "content": "﻿// Windows/System.cpp\n\n#include \"StdAfx.h\"\n\n#ifndef _WIN32\n#include <unistd.h>\n#include <limits.h>\n#if defined(__APPLE__) || defined(__DragonFly__) \\\n    || defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \\\n    || defined(__QNXNTO__)\n#include <sys/sysctl.h>\n#else\n#include <sys/sysinfo.h>\n#endif\n#endif\n\n#include \"../Common/Defs.h\"\n// #include \"../Common/MyWindows.h\"\n\n// #include \"../../C/CpuArch.h\"\n\n#include \"System.h\"\n\nnamespace NWindows {\nnamespace NSystem {\n\n#ifdef _WIN32\n\n/*\nnote: returned value in 32-bit version can be limited by value 32.\n      while 64-bit version returns full value.\nGetMaximumProcessorCount(groupNumber) can return higher value than\nGetActiveProcessorCount(groupNumber) in some cases, because CPUs can be added.\n*/\n// typedef DWORD (WINAPI *Func_GetMaximumProcessorCount)(WORD GroupNumber);\ntypedef DWORD (WINAPI *Func_GetActiveProcessorCount)(WORD GroupNumber);\ntypedef WORD (WINAPI *Func_GetActiveProcessorGroupCount)(VOID);\n/*\n#if 0 && defined(ALL_PROCESSOR_GROUPS)\n#define MY_ALL_PROCESSOR_GROUPS   ALL_PROCESSOR_GROUPS\n#else\n#define MY_ALL_PROCESSOR_GROUPS   0xffff\n#endif\n*/\n\nZ7_DIAGNOSTIC_IGNORE_CAST_FUNCTION\n\nbool CCpuGroups::Load()\n{\n  NumThreadsTotal = 0;\n  GroupSizes.Clear();\n  const HMODULE hmodule = ::GetModuleHandleA(\"kernel32.dll\");\n  // Is_Win11_Groups = GetProcAddress(hmodule, \"SetThreadSelectedCpuSetMasks\") != NULL;\n  const\n      Func_GetActiveProcessorGroupCount\n        fn_GetActiveProcessorGroupCount = Z7_GET_PROC_ADDRESS(\n      Func_GetActiveProcessorGroupCount, hmodule,\n          \"GetActiveProcessorGroupCount\");\n  const\n      Func_GetActiveProcessorCount\n        fn_GetActiveProcessorCount = Z7_GET_PROC_ADDRESS(\n      Func_GetActiveProcessorCount, hmodule,\n          \"GetActiveProcessorCount\");\n  if (!fn_GetActiveProcessorGroupCount ||\n      !fn_GetActiveProcessorCount)\n    return false;\n\n  const unsigned numGroups = fn_GetActiveProcessorGroupCount();\n  if (numGroups == 0)\n    return false;\n  UInt32 sum = 0;\n  for (unsigned i = 0; i < numGroups; i++)\n  {\n    const UInt32 num = fn_GetActiveProcessorCount((WORD)i);\n    /*\n    if (num == 0)\n    {\n      // it means error\n      // but is it possible that some group is empty by some reason?\n      // GroupSizes.Clear();\n      // return false;\n    }\n    */\n    sum += num;\n    GroupSizes.Add(num);\n  }\n  NumThreadsTotal = sum;\n  // NumThreadsTotal = fn_GetActiveProcessorCount(MY_ALL_PROCESSOR_GROUPS);\n  return true;\n}\n\nUInt32 CountAffinity(DWORD_PTR mask)\n{\n  UInt32 num = 0;\n  for (unsigned i = 0; i < sizeof(mask) * 8; i++)\n  {\n    num += (UInt32)(mask & 1);\n    mask >>= 1;\n  }\n  return num;\n}\n\nBOOL CProcessAffinity::Get()\n{\n  IsGroupMode = false;\n  Groups.Load();\n  // SetThreadAffinityMask(GetCurrentThread(), 1);\n  // SetProcessAffinityMask(GetCurrentProcess(), 1);\n  BOOL res = GetProcessAffinityMask(GetCurrentProcess(),\n      &processAffinityMask, &systemAffinityMask);\n  /* DOCs: On a system with more than 64 processors, if the threads\n     of the calling process  are in a single processor group, the\n     function sets the variables pointed to by lpProcessAffinityMask\n     and lpSystemAffinityMask to the process affinity mask and the\n     processor mask of active logical processors for that group.\n     If the calling process contains threads in multiple groups,\n     the function returns zero for both affinity masks\n\n     note: tested in Win10: GetProcessAffinityMask() doesn't return 0\n           in (processAffinityMask) and (systemAffinityMask) masks.\n     We need to test it in Win11: how to get mask==0 from GetProcessAffinityMask()?\n  */\n  if (!res)\n  {\n    processAffinityMask = 0;\n    systemAffinityMask = 0;\n  }\n  if (Groups.GroupSizes.Size() > 1 && Groups.NumThreadsTotal)\n    if (// !res ||\n        processAffinityMask == 0 || // to support case described in DOCs and for (!res) case\n        processAffinityMask == systemAffinityMask) // for default nonchanged affinity\n    {\n      // we set IsGroupMode only if processAffinity is default (not changed).\n      res = TRUE;\n      IsGroupMode = true;\n    }\n  return res;\n}\n\n\nUInt32 CProcessAffinity::Load_and_GetNumberOfThreads()\n{\n  if (Get())\n  {\n    const UInt32 numProcessors = GetNumProcessThreads();\n    if (numProcessors)\n      return numProcessors;\n  }\n  SYSTEM_INFO systemInfo;\n  GetSystemInfo(&systemInfo);\n  // the number of logical processors in the current group\n  return systemInfo.dwNumberOfProcessors;\n}\n\nUInt32 GetNumberOfProcessors()\n{\n  // We need to know how many threads we can use.\n  // By default the process is assigned to one group.\n  CProcessAffinity pa;\n  return pa.Load_and_GetNumberOfThreads();\n}\n\n#else\n\n\nBOOL CProcessAffinity::Get()\n{\n  numSysThreads = GetNumberOfProcessors();\n\n  /*\n  numSysThreads = 8;\n  for (unsigned i = 0; i < numSysThreads; i++)\n    CpuSet_Set(&cpu_set, i);\n  return TRUE;\n  */\n  \n  #ifdef Z7_AFFINITY_SUPPORTED\n  \n  // numSysThreads = sysconf(_SC_NPROCESSORS_ONLN); // The number of processors currently online\n  if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0)\n    return FALSE;\n  return TRUE;\n  \n  #else\n  \n  // cpu_set = ((CCpuSet)1 << (numSysThreads)) - 1;\n  return TRUE;\n  // errno = ENOSYS;\n  // return FALSE;\n  \n  #endif\n}\n\nUInt32 GetNumberOfProcessors()\n{\n  #ifndef Z7_ST\n  long n = sysconf(_SC_NPROCESSORS_CONF);  // The number of processors configured\n  if (n < 1)\n    n = 1;\n  return (UInt32)n;\n  #else\n  return 1;\n  #endif\n}\n\n#endif\n\n\n#ifdef _WIN32\n\n#ifndef UNDER_CE\n\n#if !defined(_WIN64) && \\\n  (defined(__MINGW32_VERSION) || defined(Z7_OLD_WIN_SDK))\n\ntypedef struct {\n  DWORD dwLength;\n  DWORD dwMemoryLoad;\n  DWORDLONG ullTotalPhys;\n  DWORDLONG ullAvailPhys;\n  DWORDLONG ullTotalPageFile;\n  DWORDLONG ullAvailPageFile;\n  DWORDLONG ullTotalVirtual;\n  DWORDLONG ullAvailVirtual;\n  DWORDLONG ullAvailExtendedVirtual;\n} MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX;\n\n#else\n\n#define MY_MEMORYSTATUSEX MEMORYSTATUSEX\n#define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX\n\n#endif\n\ntypedef BOOL (WINAPI *Func_GlobalMemoryStatusEx)(MY_LPMEMORYSTATUSEX lpBuffer);\n\n#endif // !UNDER_CE\n\n  \nbool GetRamSize(size_t &size)\n{\n  size = (size_t)sizeof(size_t) << 29;\n\n  #ifndef UNDER_CE\n    MY_MEMORYSTATUSEX stat;\n    stat.dwLength = sizeof(stat);\n  #endif\n  \n  #ifdef _WIN64\n    \n    if (!::GlobalMemoryStatusEx(&stat))\n      return false;\n    size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);\n    return true;\n\n  #else\n    \n    #ifndef UNDER_CE\n      const\n      Func_GlobalMemoryStatusEx fn = Z7_GET_PROC_ADDRESS(\n      Func_GlobalMemoryStatusEx, ::GetModuleHandleA(\"kernel32.dll\"),\n          \"GlobalMemoryStatusEx\");\n      if (fn && fn(&stat))\n      {\n        // (MY_MEMORYSTATUSEX::ullTotalVirtual) < 4 GiB in 32-bit mode\n        size_t size2 = (size_t)0 - 1;\n        if (size2 > stat.ullTotalPhys)\n            size2 = (size_t)stat.ullTotalPhys;\n        if (size2 > stat.ullTotalVirtual)\n            size2 = (size_t)stat.ullTotalVirtual;\n        size = size2;\n        return true;\n      }\n    #endif\n  \n    // On computers with more than 4 GB of memory:\n    //   new docs  : GlobalMemoryStatus can report (-1) value to indicate an overflow.\n    //   some old docs : GlobalMemoryStatus can report (modulo 4 GiB) value.\n    //                   (for example, if 5 GB total memory, it could report 1 GB).\n    // We don't want to get (modulo 4 GiB) value.\n    // So we use GlobalMemoryStatusEx() instead.\n    {\n      MEMORYSTATUS stat2;\n      stat2.dwLength = sizeof(stat2);\n      ::GlobalMemoryStatus(&stat2);\n      size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys);\n      return true;\n    }\n  #endif\n}\n  \n#else\n\n// POSIX\n// #include <stdio.h>\n\nbool GetRamSize(size_t &size)\n{\n  UInt64 size64;\n  size = (size_t)sizeof(size_t) << 29;\n  size64 = size;\n\n#if defined(__APPLE__) || defined(__DragonFly__) \\\n    || defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \\\n    || defined(__QNXNTO__)\n\n    uint64_t val = 0;\n    int mib[2];\n    mib[0] = CTL_HW;\n\n    #ifdef HW_MEMSIZE\n      mib[1] = HW_MEMSIZE;\n      // printf(\"\\n sysctl HW_MEMSIZE\");\n    #elif defined(HW_PHYSMEM64)\n      mib[1] = HW_PHYSMEM64;\n      // printf(\"\\n sysctl HW_PHYSMEM64\");\n    #else\n      mib[1] = HW_PHYSMEM;\n      // printf(\"\\n sysctl HW_PHYSMEM\");\n    #endif\n\n    size_t size_sys = sizeof(val);\n    int res = sysctl(mib, 2, &val, &size_sys, NULL, 0);\n    // printf(\"\\n sysctl res=%d val=%llx size_sys = %d, %d\\n\", res, (long long int)val, (int)size_sys, errno);\n    // we use strict check (size_sys == sizeof(val)) for returned value\n    // because big-endian encoding is possible:\n    if (res == 0 && size_sys == sizeof(val) && val)\n      size64 = val;\n    else\n    {\n      uint32_t val32 = 0;\n      size_sys = sizeof(val32);\n      res = sysctl(mib, 2, &val32, &size_sys, NULL, 0);\n      // printf(\"\\n sysctl res=%d val=%llx size_sys = %d, %d\\n\", res, (long long int)val32, (int)size_sys, errno);\n      if (res == 0 && size_sys == sizeof(val32) && val32)\n        size64 = val32;\n    }\n\n  #elif defined(_AIX)\n    #if defined(_SC_AIX_REALMEM) // AIX\n      size64 = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024;\n    #endif\n  #elif 0 || defined(__sun)\n    #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)\n    // FreeBSD, Linux, OpenBSD, and Solaris.\n    {\n      const long phys_pages = sysconf(_SC_PHYS_PAGES);\n      const long page_size = sysconf(_SC_PAGESIZE);\n      // #pragma message(\"GetRamSize : sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE)\")\n      // printf(\"\\n_SC_PHYS_PAGES (hex) = %lx\", (unsigned long)phys_pages);\n      // printf(\"\\n_SC_PAGESIZE = %lu\\n\", (unsigned long)page_size);\n      if (phys_pages != -1 && page_size != -1)\n        size64 = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size;\n    }\n    #endif\n  #elif defined(__gnu_hurd__)\n  // fixme\n  #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__)\n  // GNU/kFreeBSD Debian\n  // fixme\n  #else\n\n  struct sysinfo info;\n  if (::sysinfo(&info) != 0)\n    return false;\n  size64 = (UInt64)info.mem_unit * info.totalram;\n  /*\n  printf(\"\\n mem_unit  = %lld\", (UInt64)info.mem_unit);\n  printf(\"\\n totalram  = %lld\", (UInt64)info.totalram);\n  printf(\"\\n freeram   = %lld\", (UInt64)info.freeram);\n  */\n\n  #endif\n\n  size = (size_t)1 << (sizeof(size_t) * 8 - 1);\n  if (size > size64)\n      size = (size_t)size64;\n  return true;\n}\n\n#endif\n\n\nunsigned long Get_File_OPEN_MAX()\n{\n #ifdef _WIN32\n  return (1 << 24) - (1 << 16); // ~16M handles\n #else\n  // some linux versions have default open file limit for user process of 1024 files.\n  long n = sysconf(_SC_OPEN_MAX);\n  // n = -1; // for debug\n  // n = 9; // for debug\n  if (n < 1)\n  {\n    // n = OPEN_MAX;  // ???\n    // n = FOPEN_MAX; // = 16 : <stdio.h>\n   #ifdef _POSIX_OPEN_MAX\n    n = _POSIX_OPEN_MAX; // = 20 : <limits.h>\n   #else\n    n = 30; // our limit\n   #endif\n  }\n  return (unsigned long)n;\n #endif\n}\n\nunsigned Get_File_OPEN_MAX_Reduced_for_3_tasks()\n{\n  unsigned long numFiles_OPEN_MAX = NSystem::Get_File_OPEN_MAX();\n  const unsigned delta = 10; // the reserve for another internal needs of process\n  if (numFiles_OPEN_MAX > delta)\n    numFiles_OPEN_MAX -= delta;\n  else\n    numFiles_OPEN_MAX = 1;\n  numFiles_OPEN_MAX /= 3; // we suppose that we have up to 3 tasks in total for multiple file processing\n  numFiles_OPEN_MAX = MyMax(numFiles_OPEN_MAX, (unsigned long)3);\n  unsigned n = (unsigned)(int)-1;\n  if (n > numFiles_OPEN_MAX)\n    n = (unsigned)numFiles_OPEN_MAX;\n  return n;\n}\n\n}}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/System.h",
    "content": "﻿// Windows/System.h\n\n#ifndef ZIP7_INC_WINDOWS_SYSTEM_H\n#define ZIP7_INC_WINDOWS_SYSTEM_H\n\n#ifndef _WIN32\n// #include <sched.h>\n#include \"../../C/Threads.h\"\n#endif\n\n#include \"../Common/MyTypes.h\"\n#include \"../Common/MyVector.h\"\n#include \"../Common/MyWindows.h\"\n\nnamespace NWindows {\nnamespace NSystem {\n\nUInt32 GetNumberOfProcessors();\n\n#ifdef _WIN32\n\nstruct CCpuGroups\n{\n  CRecordVector<UInt32> GroupSizes;\n  UInt32 NumThreadsTotal; // sum of threads in all groups\n  // bool Is_Win11_Groups; // useless\n  \n  void Get_GroupSize_Min_Max(UInt32 &minSize, UInt32 &maxSize) const\n  {\n    unsigned num = GroupSizes.Size();\n    UInt32 minSize2 = 0, maxSize2 = 0;\n    if (num)\n    {\n      minSize2 = (UInt32)0 - 1;\n      do\n      {\n        const UInt32 v = GroupSizes[--num];\n        if (minSize2 > v) minSize2 = v;\n        if (maxSize2 < v) maxSize2 = v;\n      }\n      while (num);\n    }\n    minSize = minSize2;\n    maxSize = maxSize2;\n  }\n  bool Load();\n  CCpuGroups(): NumThreadsTotal(0) {}\n};\n\nUInt32 CountAffinity(DWORD_PTR mask);\n\nstruct CProcessAffinity\n{\n  // UInt32 numProcessThreads;\n  // UInt32 numSysThreads;\n  DWORD_PTR processAffinityMask;\n  DWORD_PTR systemAffinityMask;\n\n  CCpuGroups Groups;\n  bool IsGroupMode;\n    /*\n      IsGroupMode == true, if\n          Groups.GroupSizes.Size() > 1) && { dafalt affinity was not changed }\n      IsGroupMode == false, if single group or affinity was changed\n    */\n  \n  UInt32 Load_and_GetNumberOfThreads();\n\n  void InitST()\n  {\n    // numProcessThreads = 1;\n    // numSysThreads = 1;\n    processAffinityMask = 1;\n    systemAffinityMask = 1;\n    IsGroupMode = false;\n    // Groups.NumThreadsTotal = 0;\n    // Groups.Is_Win11_Groups = false;\n  }\n\n/*\n  void CpuZero()\n  {\n    processAffinityMask = 0;\n  }\n\n  void CpuSet(unsigned cpuIndex)\n  {\n    processAffinityMask |= ((DWORD_PTR)1 << cpuIndex);\n  }\n*/\n\n  UInt32 GetNumProcessThreads() const\n  {\n    if (IsGroupMode)\n      return Groups.NumThreadsTotal;\n    // IsGroupMode == false\n    // so we don't want to use groups\n    // we return number of threads in default primary group:\n    return CountAffinity(processAffinityMask);\n  }\n  UInt32 GetNumSystemThreads() const\n  {\n    if (Groups.GroupSizes.Size() > 1 && Groups.NumThreadsTotal)\n      return Groups.NumThreadsTotal;\n    return CountAffinity(systemAffinityMask);\n  }\n\n  // it returns normilized number of threads\n  void Get_and_return_NumProcessThreads_and_SysThreads(UInt32 &numProcessThreads, UInt32 &numSysThreads)\n  {\n    UInt32 num1 = 0, num2 = 0;\n    if (Get())\n    {\n      num1 = GetNumProcessThreads();\n      num2 = GetNumSystemThreads();\n    }\n    if (num1 == 0)\n      num1 = NSystem::GetNumberOfProcessors();\n    if (num1 == 0)\n        num1 = 1;\n    if (num2 < num1)\n        num2 = num1;\n    numProcessThreads = num1;\n    numSysThreads = num2;\n  }\n\n  BOOL Get();\n\n  BOOL SetProcAffinity() const\n  {\n    return SetProcessAffinityMask(GetCurrentProcess(), processAffinityMask);\n  }\n};\n\n\n#else // WIN32\n\nstruct CProcessAffinity\n{\n  UInt32 numSysThreads;\n\n  UInt32 GetNumSystemThreads() const { return (UInt32)numSysThreads; }\n  BOOL Get();\n\n  #ifdef Z7_AFFINITY_SUPPORTED\n\n  CCpuSet cpu_set;\n\n  void InitST()\n  {\n    numSysThreads = 1;\n    CpuSet_Zero(&cpu_set);\n    CpuSet_Set(&cpu_set, 0);\n  }\n\n  UInt32 GetNumProcessThreads() const { return (UInt32)CPU_COUNT(&cpu_set); }\n  void CpuZero()              { CpuSet_Zero(&cpu_set); }\n  void CpuSet(unsigned cpuIndex)   { CpuSet_Set(&cpu_set, cpuIndex); }\n  int IsCpuSet(unsigned cpuIndex) const { return CpuSet_IsSet(&cpu_set, cpuIndex); }\n  // void CpuClr(int cpuIndex) { CPU_CLR(cpuIndex, &cpu_set); }\n\n  BOOL SetProcAffinity() const\n  {\n    return sched_setaffinity(0, sizeof(cpu_set), &cpu_set) == 0;\n  }\n\n  #else // Z7_AFFINITY_SUPPORTED\n\n  void InitST()\n  {\n    numSysThreads = 1;\n  }\n  \n  UInt32 GetNumProcessThreads() const\n  {\n    return numSysThreads;\n    /*\n    UInt32 num = 0;\n    for (unsigned i = 0; i < sizeof(cpu_set) * 8; i++)\n      num += (UInt32)((cpu_set >> i) & 1);\n    return num;\n    */\n  }\n  \n  void CpuZero() { }\n  void CpuSet(unsigned /* cpuIndex */) { /* UNUSED_VAR(cpuIndex) */ }\n  int IsCpuSet(unsigned cpuIndex) const { return (cpuIndex < numSysThreads) ? 1 : 0; }\n\n  BOOL SetProcAffinity() const\n  {\n    errno = ENOSYS;\n    return FALSE;\n  }\n  \n  #endif // Z7_AFFINITY_SUPPORTED\n};\n\n#endif // _WIN32\n\n\nbool GetRamSize(size_t &size); // returns false, if unknown ram size\n\nunsigned long Get_File_OPEN_MAX();\nunsigned Get_File_OPEN_MAX_Reduced_for_3_tasks();\n\n}}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Thread.h",
    "content": "﻿// Windows/Thread.h\n\n#ifndef ZIP7_INC_WINDOWS_THREAD_H\n#define ZIP7_INC_WINDOWS_THREAD_H\n\n#include \"../../C/Threads.h\"\n\n#include \"Defs.h\"\n\nnamespace NWindows {\n\nclass CThread  MY_UNCOPYABLE\n{\n  ::CThread thread;\npublic:\n  CThread() { Thread_CONSTRUCT(&thread) }\n  ~CThread() { Close(); }\n  bool IsCreated() { return Thread_WasCreated(&thread) != 0; }\n  WRes Close()  { return Thread_Close(&thread); }\n  // WRes Wait() { return Thread_Wait(&thread); }\n  WRes Wait_Close() { return Thread_Wait_Close(&thread); }\n\n  WRes Create(THREAD_FUNC_TYPE startAddress, LPVOID param)\n    { return Thread_Create(&thread, startAddress, param); }\n  WRes Create_With_Affinity(THREAD_FUNC_TYPE startAddress, LPVOID param, CAffinityMask affinity)\n    { return Thread_Create_With_Affinity(&thread, startAddress, param, affinity); }\n  WRes Create_With_CpuSet(THREAD_FUNC_TYPE startAddress, LPVOID param, const CCpuSet *cpuSet)\n    { return Thread_Create_With_CpuSet(&thread, startAddress, param, cpuSet); }\n \n#ifdef _WIN32\n  WRes Create_With_Group(THREAD_FUNC_TYPE startAddress, LPVOID param, unsigned group, CAffinityMask affinity = 0)\n    { return Thread_Create_With_Group(&thread, startAddress, param, group, affinity); }\n  operator HANDLE() { return thread; }\n  void Attach(HANDLE handle) { thread = handle; }\n  HANDLE Detach() { HANDLE h = thread; thread = NULL; return h; }\n  DWORD Resume() { return ::ResumeThread(thread); }\n  DWORD Suspend() { return ::SuspendThread(thread); }\n  bool Terminate(DWORD exitCode) { return BOOLToBool(::TerminateThread(thread, exitCode)); }\n  int GetPriority() { return ::GetThreadPriority(thread); }\n  bool SetPriority(int priority) { return BOOLToBool(::SetThreadPriority(thread, priority)); }\n#endif\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/TimeUtils.cpp",
    "content": "﻿// Windows/TimeUtils.cpp\n\n#include \"StdAfx.h\"\n\n#ifndef _WIN32\n#include <sys/time.h>\n#include <time.h>\n#endif\n\n#include \"Defs.h\"\n#include \"TimeUtils.h\"\n\nnamespace NWindows {\nnamespace NTime {\n\nstatic const UInt32 kNumTimeQuantumsInSecond = 10000000;\nstatic const unsigned kFileTimeStartYear = 1601;\n#if !defined(_WIN32) || defined(UNDER_CE)\nstatic const unsigned kDosTimeStartYear = 1980;\n#endif\nstatic const unsigned kUnixTimeStartYear = 1970;\nstatic const UInt64 kUnixTimeOffset =\n    (UInt64)60 * 60 * 24 * (89 + 365 * (UInt32)(kUnixTimeStartYear - kFileTimeStartYear));\nstatic const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond;\n\nbool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw()\n{\n  #if defined(_WIN32) && !defined(UNDER_CE)\n  return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft));\n  #else\n  ft.dwLowDateTime = 0;\n  ft.dwHighDateTime = 0;\n  UInt64 res;\n  if (!GetSecondsSince1601(\n      kDosTimeStartYear + (unsigned)(dosTime >> 25),\n      (unsigned)((dosTime >> 21) & 0xF),\n      (unsigned)((dosTime >> 16) & 0x1F),\n      (unsigned)((dosTime >> 11) & 0x1F),\n      (unsigned)((dosTime >>  5) & 0x3F),\n      (unsigned)((dosTime & 0x1F)) * 2,\n      res))\n    return false;\n  res *= kNumTimeQuantumsInSecond;\n  ft.dwLowDateTime = (UInt32)res;\n  ft.dwHighDateTime = (UInt32)(res >> 32);\n  return true;\n  #endif\n}\n\nstatic const UInt32 kHighDosTime = 0xFF9FBF7D;\nstatic const UInt32 kLowDosTime = 0x210000;\n\nbool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw()\n{\n  #if defined(_WIN32) && !defined(UNDER_CE)\n\n  WORD datePart, timePart;\n  if (!::FileTimeToDosDateTime(&ft, &datePart, &timePart))\n  {\n    dosTime = (ft.dwHighDateTime >= 0x01C00000) ? kHighDosTime : kLowDosTime;\n    return false;\n  }\n  dosTime = (((UInt32)datePart) << 16) + timePart;\n\n  #else\n\n#define PERIOD_4 (4 * 365 + 1)\n#define PERIOD_100 (PERIOD_4 * 25 - 1)\n#define PERIOD_400 (PERIOD_100 * 4 + 1)\n\n  unsigned year, mon, day, hour, min, sec;\n  UInt64 v64 = ft.dwLowDateTime | ((UInt64)ft.dwHighDateTime << 32);\n  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n  unsigned temp;\n  UInt32 v;\n  v64 += (kNumTimeQuantumsInSecond * 2 - 1);\n  v64 /= kNumTimeQuantumsInSecond;\n  sec = (unsigned)(v64 % 60);\n  v64 /= 60;\n  min = (unsigned)(v64 % 60);\n  v64 /= 60;\n  hour = (unsigned)(v64 % 24);\n  v64 /= 24;\n\n  v = (UInt32)v64;\n\n  year = kFileTimeStartYear + (unsigned)(v / PERIOD_400 * 400);\n  v %= PERIOD_400;\n\n  temp = (unsigned)(v / PERIOD_100);\n  if (temp == 4)\n    temp = 3;\n  year += temp * 100;\n  v -= temp * PERIOD_100;\n\n  temp = v / PERIOD_4;\n  if (temp == 25)\n    temp = 24;\n  year += temp * 4;\n  v -= temp * PERIOD_4;\n\n  temp = v / 365;\n  if (temp == 4)\n    temp = 3;\n  year += temp;\n  v -= temp * 365;\n\n  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))\n    ms[1] = 29;\n  for (mon = 1; mon <= 12; mon++)\n  {\n    unsigned s = ms[mon - 1];\n    if (v < s)\n      break;\n    v -= s;\n  }\n  day = (unsigned)v + 1;\n\n  dosTime = kLowDosTime;\n  if (year < kDosTimeStartYear)\n    return false;\n  year -= kDosTimeStartYear;\n  dosTime = kHighDosTime;\n  if (year >= 128)\n    return false;\n  dosTime =\n      ((UInt32)year << 25)\n    | ((UInt32)mon  << 21)\n    | ((UInt32)day  << 16)\n    | ((UInt32)hour << 11)\n    | ((UInt32)min  << 5)\n    | ((UInt32)sec  >> 1);\n  #endif\n  return true;\n}\n\n\nbool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw()\n{\n  FILETIME loc = { 0, 0 };\n  const UInt64 u1 = FILETIME_To_UInt64(utc);\n  const UInt64 kDelta = ((UInt64)1 << 41); // it's larger than quantums in 1 sec.\n  if (u1 >= kDelta)\n  {\n    if (!FileTimeToLocalFileTime(&utc, &loc))\n      loc = utc;\n    else\n    {\n      const UInt64 u2 = FILETIME_To_UInt64(loc);\n      const UInt64 delta = u1 < u2 ? (u2 - u1) : (u1 - u2);\n      if (delta > kDelta) // if FileTimeToLocalFileTime() overflow, we use UTC time\n        loc = utc;\n    }\n  }\n  return FileTime_To_DosTime(loc, dosTime);\n}\n\nUInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw()\n{\n  return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond;\n}\n\nvoid UnixTime_To_FileTime(UInt32 unixTime, FILETIME &ft) throw()\n{\n  const UInt64 v = UnixTime_To_FileTime64(unixTime);\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n}\n\nUInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw()\n{\n  return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond;\n}\n\n\nbool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw()\n{\n  if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset))\n  {\n    fileTime = (UInt64)(Int64)-1;\n    return false;\n  }\n  if (unixTime < -(Int64)kUnixTimeOffset)\n  {\n    fileTime = 0;\n    return false;\n  }\n  fileTime = UnixTime64_To_FileTime64(unixTime);\n  return true;\n}\n\n\nbool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &ft) throw()\n{\n  UInt64 v;\n  const bool res = UnixTime64_To_FileTime64(unixTime, v);\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n  return res;\n}\n\n\nInt64 FileTime_To_UnixTime64(const FILETIME &ft) throw()\n{\n  const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;\n  return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;\n}\n\nInt64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw()\n{\n  const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;\n  quantums = (UInt32)(winTime % kNumTimeQuantumsInSecond);\n  return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset;\n}\n\nbool FileTime_To_UnixTime(const FILETIME &ft, UInt32 &unixTime) throw()\n{\n  UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;\n  winTime /= kNumTimeQuantumsInSecond;\n  if (winTime < kUnixTimeOffset)\n  {\n    unixTime = 0;\n    return false;\n  }\n  winTime -= kUnixTimeOffset;\n  if (winTime > (UInt32)0xFFFFFFFF)\n  {\n    unixTime = (UInt32)0xFFFFFFFF;\n    return false;\n  }\n  unixTime = (UInt32)winTime;\n  return true;\n}\n\nbool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,\n  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw()\n{\n  resSeconds = 0;\n  if (year < kFileTimeStartYear || year >= 10000 || month < 1 || month > 12 ||\n      day < 1 || day > 31 || hour > 23 || min > 59 || sec > 59)\n    return false;\n  const unsigned numYears = year - kFileTimeStartYear;\n  UInt32 numDays = (UInt32)((UInt32)numYears * 365 + numYears / 4 - numYears / 100 + numYears / 400);\n  Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\n  if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))\n    ms[1] = 29;\n  month--;\n  for (unsigned i = 0; i < month; i++)\n    numDays += ms[i];\n  numDays += (UInt32)(day - 1);\n  resSeconds = ((UInt64)(numDays * 24 + hour) * 60 + min) * 60 + sec;\n  return true;\n}\n\n\n/* docs: TIME_UTC is not defined on many platforms:\n      glibc 2.15, macOS 10.13\n      FreeBSD 11.0, NetBSD 7.1, OpenBSD 6.0,\n      Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3,\n      Cygwin 2.9, mingw, MSVC 14, Android 9.0.\n  Android NDK defines TIME_UTC but doesn't have the timespec_get().\n*/\n#if defined(TIME_UTC) && !defined(__ANDROID__)\n#define ZIP7_USE_timespec_get\n// #pragma message(\"ZIP7_USE_timespec_get\")\n#elif defined(CLOCK_REALTIME)\n#define ZIP7_USE_clock_gettime\n// #pragma message(\"ZIP7_USE_clock_gettime\")\n#endif\n\nvoid GetCurUtc_FiTime(CFiTime &ft) throw()\n{\n #ifdef _WIN32\n\n  // Both variants provide same low resolution on WinXP: about 15 ms.\n  // But GetSystemTimeAsFileTime is much faster.\n  #ifdef UNDER_CE\n  SYSTEMTIME st;\n  GetSystemTime(&st);\n  SystemTimeToFileTime(&st, &ft);\n  #else\n  GetSystemTimeAsFileTime(&ft);\n  #endif\n\n #else\n  \n  FiTime_Clear(ft);\n#ifdef ZIP7_USE_timespec_get\n  timespec_get(&ft, TIME_UTC);\n#elif defined ZIP7_USE_clock_gettime\n\n#if defined(_AIX)\n  {\n    timespec ts;\n    clock_gettime(CLOCK_REALTIME, &ts);\n    ft.tv_sec = ts.tv_sec;\n    ft.tv_nsec = ts.tv_nsec;\n  }\n#else\n  clock_gettime(CLOCK_REALTIME, &ft);\n#endif\n\n#else\n  struct timeval now;\n  if (gettimeofday(&now, NULL) == 0)\n  {\n    ft.tv_sec = now.tv_sec;\n    // timeval::tv_usec   can be 64-bit signed in some cases\n    // timespec::tv_nsec  can be 32-bit signed in some cases\n    ft.tv_nsec =\n      (Int32) // to eliminate compiler conversion error\n      (now.tv_usec * 1000);\n  }\n#endif\n\n #endif\n}\n\n#ifndef _WIN32\nvoid GetCurUtcFileTime(FILETIME &ft) throw()\n{\n  UInt64 v = 0;\n#if defined(ZIP7_USE_timespec_get) || \\\n    defined(ZIP7_USE_clock_gettime)\n  timespec ts;\n#if defined(ZIP7_USE_timespec_get)\n  if (timespec_get(&ts, TIME_UTC))\n#else\n  if (clock_gettime(CLOCK_REALTIME, &ts) == 0)\n#endif\n  {\n    v = ((UInt64)ts.tv_sec + kUnixTimeOffset) *\n      kNumTimeQuantumsInSecond + (UInt64)ts.tv_nsec / 100;\n  }\n#else\n  struct timeval now;\n  if (gettimeofday(&now, NULL) == 0)\n  {\n    v = ((UInt64)now.tv_sec + kUnixTimeOffset) *\n      kNumTimeQuantumsInSecond + (UInt64)now.tv_usec * 10;\n  }\n#endif\n  ft.dwLowDateTime  = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n}\n#endif\n\n\n}}\n\n\n#ifdef _WIN32\n\n/*\nvoid FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec)\n{\n  if (prec == k_PropVar_TimePrec_0\n      || prec == k_PropVar_TimePrec_HighPrec\n      || prec >= k_PropVar_TimePrec_100ns)\n    return;\n  UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;\n\n  int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;\n  UInt32 d;\n  if (prec == k_PropVar_TimePrec_DOS)\n  {\n    // we round up as windows DosDateTimeToFileTime()\n    v += NWindows::NTime::kNumTimeQuantumsInSecond * 2 - 1;\n    d = NWindows::NTime::kNumTimeQuantumsInSecond * 2;\n  }\n  else\n  {\n    if (prec == k_PropVar_TimePrec_Unix)\n      numDigits = 0;\n    else if (numDigits < 0)\n      return;\n    d = 1;\n    for (unsigned k = numDigits; k < 7; k++)\n      d *= 10;\n  }\n  v /= d;\n  v *= d;\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n}\n*/\n\n#else\n\n/*\nvoid FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec)\n{\n  if (prec >= k_PropVar_TimePrec_1ns\n      || prec == k_PropVar_TimePrec_HighPrec)\n    return;\n\n  int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base;\n  UInt32 d;\n  if (prec == k_PropVar_TimePrec_Unix ||\n      prec == (int)k_PropVar_TimePrec_Base)\n  {\n    ft.tv_nsec = 0;\n    return;\n  }\n  if (prec == k_PropVar_TimePrec_DOS)\n  {\n    // we round up as windows DosDateTimeToFileTime()\n    const unsigned sec1 = (ft.tv_sec & 1);\n    if (ft.tv_nsec == 0 && sec1 == 0)\n      return;\n    ft.tv_nsec = 0;\n    ft.tv_sec += 2 - sec1;\n    return;\n  }\n  {\n    if (prec == k_PropVar_TimePrec_0\n        || numDigits < 0)\n      numDigits = 7;\n    d = 1;\n    for (unsigned k = numDigits; k < 9; k++)\n      d *= 10;\n    ft.tv_nsec /= d;\n    ft.tv_nsec *= d;\n  }\n}\n*/\n\nint Compare_FiTime(const CFiTime *a1, const CFiTime *a2)\n{\n  if (a1->tv_sec < a2->tv_sec) return -1;\n  if (a1->tv_sec > a2->tv_sec) return 1;\n  if (a1->tv_nsec < a2->tv_nsec) return -1;\n  if (a1->tv_nsec > a2->tv_nsec) return 1;\n  return 0;\n}\n\nbool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts)\n{\n  UInt32 quantums;\n  const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums);\n  // time_t is long\n  const time_t sec2 = (time_t)sec;\n  if (sec2 == sec)\n  {\n    ts.tv_sec = sec2;\n    ts.tv_nsec = (Int32)(quantums * 100);\n    return true;\n  }\n  return false;\n}\n\nvoid FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100)\n{\n  const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);\n  ns100 = (unsigned)((UInt64)ts.tv_nsec % 100);\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n}\n\nvoid FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft)\n{\n  const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100);\n  ft.dwLowDateTime = (DWORD)v;\n  ft.dwHighDateTime = (DWORD)(v >> 32);\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/TimeUtils.h",
    "content": "﻿// Windows/TimeUtils.h\n\n#ifndef ZIP7_INC_WINDOWS_TIME_UTILS_H\n#define ZIP7_INC_WINDOWS_TIME_UTILS_H\n\n#include \"../Common/MyTypes.h\"\n#include \"../Common/MyWindows.h\"\n#include \"PropVariant.h\"\n\ninline UInt64 FILETIME_To_UInt64(const FILETIME &ft)\n{\n  return (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;\n}\n\ninline void FILETIME_Clear(FILETIME &ft)\n{\n  ft.dwLowDateTime = 0;\n  ft.dwHighDateTime = 0;\n}\n\ninline bool FILETIME_IsZero(const FILETIME &ft)\n{\n  return (ft.dwHighDateTime == 0 && ft.dwLowDateTime == 0);\n}\n\n\n#ifdef _WIN32\n  #define CFiTime FILETIME\n  #define Compare_FiTime ::CompareFileTime\n  inline void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft)\n  {\n    ft = ts;\n  }\n  /*\n  inline void FILETIME_To_FiTime(const FILETIME &ft, CFiTime &ts)\n  {\n    ts = ft;\n  }\n  */\n  inline void FiTime_Clear(CFiTime &ft)\n  {\n    ft.dwLowDateTime = 0;\n    ft.dwHighDateTime = 0;\n  }\n#else\n\n  #include <sys/stat.h>\n\n #if defined(_AIX)\n   #define CFiTime st_timespec\n #else\n   #define CFiTime timespec\n #endif\n  int Compare_FiTime(const CFiTime *a1, const CFiTime *a2);\n  bool FILETIME_To_timespec(const FILETIME &ft, CFiTime &ts);\n  void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft);\n  void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100);\n  inline void FiTime_Clear(CFiTime &ft)\n  {\n    ft.tv_sec = 0;\n    ft.tv_nsec = 0;\n  }\n\n #ifdef __APPLE__\n  #define ST_MTIME(st) st.st_mtimespec\n  #define ST_ATIME(st) st.st_atimespec\n  #define ST_CTIME(st) st.st_ctimespec\n #elif defined(__QNXNTO__) && defined(__ARM__) && !defined(__aarch64__)\n  // QNX armv7le (32-bit) for \"struct stat\" timestamps uses time_t instead of timespec\n  inline CFiTime ST_MTIME(const struct stat &st)\n    { timespec ts;  ts.tv_sec = st.st_mtime; ts.tv_nsec = 0;  return ts; }\n  inline CFiTime ST_ATIME(const struct stat &st)\n    { timespec ts;  ts.tv_sec = st.st_atime; ts.tv_nsec = 0;  return ts; }\n  inline CFiTime ST_CTIME(const struct stat &st)\n    { timespec ts;  ts.tv_sec = st.st_ctime; ts.tv_nsec = 0;  return ts; }\n #else\n  #define ST_MTIME(st) st.st_mtim\n  #define ST_ATIME(st) st.st_atim\n  #define ST_CTIME(st) st.st_ctim\n #endif\n\n#endif\n\n// void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec);\n\nnamespace NWindows {\nnamespace NTime {\n\nbool DosTime_To_FileTime(UInt32 dosTime, FILETIME &fileTime) throw();\nbool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw();\nbool FileTime_To_DosTime(const FILETIME &fileTime, UInt32 &dosTime) throw();\n\n// UInt32 Unix Time : for dates 1970-2106\nUInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw();\nvoid UnixTime_To_FileTime(UInt32 unixTime, FILETIME &fileTime) throw();\n\n// Int64 Unix Time : negative values for dates before 1970\nUInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw(); // no check\nbool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw();\nbool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &fileTime) throw();\n\nInt64 FileTime64_To_UnixTime64(UInt64 ft64) throw();\nbool FileTime_To_UnixTime(const FILETIME &fileTime, UInt32 &unixTime) throw();\nInt64 FileTime_To_UnixTime64(const FILETIME &ft) throw();\nInt64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw();\n\nbool GetSecondsSince1601(unsigned year, unsigned month, unsigned day,\n  unsigned hour, unsigned min, unsigned sec, UInt64 &resSeconds) throw();\n\nvoid GetCurUtc_FiTime(CFiTime &ft) throw();\n#ifdef _WIN32\n#define GetCurUtcFileTime GetCurUtc_FiTime\n#else\nvoid GetCurUtcFileTime(FILETIME &ft) throw();\n#endif\n\n}}\n\ninline void PropVariant_SetFrom_UnixTime(NWindows::NCOM::CPropVariant &prop, UInt32 unixTime)\n{\n  FILETIME ft;\n  NWindows::NTime::UnixTime_To_FileTime(unixTime, ft);\n  prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_Unix);\n}\n\ninline void PropVariant_SetFrom_NtfsTime(NWindows::NCOM::CPropVariant &prop, const FILETIME &ft)\n{\n  prop.SetAsTimeFrom_FT_Prec(ft, k_PropVar_TimePrec_100ns);\n}\n\ninline void PropVariant_SetFrom_FiTime(NWindows::NCOM::CPropVariant &prop, const CFiTime &fts)\n{\n #ifdef _WIN32\n  PropVariant_SetFrom_NtfsTime(prop, fts);\n #else\n  unsigned ns100;\n  FILETIME ft;\n  FiTime_To_FILETIME_ns100(fts, ft, ns100);\n  prop.SetAsTimeFrom_FT_Prec_Ns100(ft, k_PropVar_TimePrec_1ns, ns100);\n #endif\n}\n\ninline bool PropVariant_SetFrom_DosTime(NWindows::NCOM::CPropVariant &prop, UInt32 dosTime)\n{\n  FILETIME localFileTime, utc;\n  if (!NWindows::NTime::DosTime_To_FileTime(dosTime, localFileTime))\n    return false;\n  if (!LocalFileTimeToFileTime(&localFileTime, &utc))\n    return false;\n  prop.SetAsTimeFrom_FT_Prec(utc, k_PropVar_TimePrec_DOS);\n  return true;\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Window.cpp",
    "content": "﻿// Windows/Window.cpp\n\n#include \"StdAfx.h\"\n\n#ifndef _UNICODE\n#include \"../Common/StringConvert.h\"\n#endif\n#include \"Window.h\"\n\n#ifndef _UNICODE\nextern bool g_IsNT;\n#endif\n\nnamespace NWindows {\n\n#ifndef _UNICODE\nATOM MyRegisterClass(CONST WNDCLASSW *wndClass)\n{\n  if (g_IsNT)\n    return RegisterClassW(wndClass);\n  WNDCLASSA wndClassA;\n  wndClassA.style = wndClass->style;\n  wndClassA.lpfnWndProc = wndClass->lpfnWndProc;\n  wndClassA.cbClsExtra = wndClass->cbClsExtra;\n  wndClassA.cbWndExtra = wndClass->cbWndExtra;\n  wndClassA.hInstance = wndClass->hInstance;\n  wndClassA.hIcon = wndClass->hIcon;\n  wndClassA.hCursor = wndClass->hCursor;\n  wndClassA.hbrBackground = wndClass->hbrBackground;\n  AString menuName;\n  AString className;\n  if (IS_INTRESOURCE(wndClass->lpszMenuName))\n    wndClassA.lpszMenuName = (LPCSTR)wndClass->lpszMenuName;\n  else\n  {\n    menuName = GetSystemString(wndClass->lpszMenuName);\n    wndClassA.lpszMenuName = menuName;\n  }\n  if (IS_INTRESOURCE(wndClass->lpszClassName))\n    wndClassA.lpszClassName = (LPCSTR)wndClass->lpszClassName;\n  else\n  {\n    className = GetSystemString(wndClass->lpszClassName);\n    wndClassA.lpszClassName = className;\n  }\n  return RegisterClassA(&wndClassA);\n}\n\nbool CWindow::Create(LPCWSTR className,\n      LPCWSTR windowName, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam)\n{\n  if (g_IsNT)\n  {\n    _window = ::CreateWindowW(className, windowName,\n        style, x, y, width, height, parentWindow,\n        idOrHMenu, instance, createParam);\n     return (_window != NULL);\n  }\n  return Create(GetSystemString(className), GetSystemString(windowName),\n        style, x, y, width, height, parentWindow,\n        idOrHMenu, instance, createParam);\n}\n\nbool CWindow::CreateEx(DWORD exStyle, LPCWSTR className,\n      LPCWSTR windowName, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam)\n{\n  if (g_IsNT)\n  {\n    _window = ::CreateWindowExW(exStyle, className, windowName,\n      style, x, y, width, height, parentWindow,\n      idOrHMenu, instance, createParam);\n     return (_window != NULL);\n  }\n  AString classNameA;\n  LPCSTR classNameP;\n  if (IS_INTRESOURCE(className))\n    classNameP = (LPCSTR)className;\n  else\n  {\n    classNameA = GetSystemString(className);\n    classNameP = classNameA;\n  }\n  AString windowNameA;\n  LPCSTR windowNameP;\n  if (IS_INTRESOURCE(windowName))\n    windowNameP = (LPCSTR)windowName;\n  else\n  {\n    windowNameA = GetSystemString(windowName);\n    windowNameP = windowNameA;\n  }\n  return CreateEx(exStyle, classNameP, windowNameP,\n      style, x, y, width, height, parentWindow,\n      idOrHMenu, instance, createParam);\n}\n\n#endif\n\n#ifndef _UNICODE\nbool MySetWindowText(HWND wnd, LPCWSTR s)\n{\n  if (g_IsNT)\n    return BOOLToBool(::SetWindowTextW(wnd, s));\n  return BOOLToBool(::SetWindowTextA(wnd, UnicodeStringToMultiByte(s)));\n}\n#endif\n\nbool CWindow::GetText(CSysString &s) const\n{\n  s.Empty();\n  unsigned len = (unsigned)GetTextLength();\n  if (len == 0)\n    return (::GetLastError() == ERROR_SUCCESS);\n  TCHAR *p = s.GetBuf(len);\n  {\n    const unsigned len2 = (unsigned)GetText(p, (int)(len + 1));\n    if (len > len2)\n      len = len2;\n  }\n  s.ReleaseBuf_CalcLen(len);\n  if (len == 0)\n    return (::GetLastError() == ERROR_SUCCESS);\n  return true;\n}\n\n#ifndef _UNICODE\nbool CWindow::GetText(UString &s) const\n{\n  if (g_IsNT)\n  {\n    s.Empty();\n    unsigned len = (unsigned)GetWindowTextLengthW(_window);\n    if (len == 0)\n      return (::GetLastError() == ERROR_SUCCESS);\n    wchar_t *p = s.GetBuf(len);\n    {\n      const unsigned len2 = (unsigned)GetWindowTextW(_window, p, (int)(len + 1));\n      if (len > len2)\n        len = len2;\n    }\n    s.ReleaseBuf_CalcLen(len);\n    if (len == 0)\n      return (::GetLastError() == ERROR_SUCCESS);\n    return true;\n  }\n  CSysString sysString;\n  const bool result = GetText(sysString);\n  MultiByteToUnicodeString2(s, sysString);\n  return result;\n}\n#endif\n\n \n/*\nbool CWindow::ModifyStyleBase(int styleOffset,\n  DWORD remove, DWORD add, UINT flags)\n{\n  DWORD style = GetWindowLong(styleOffset);\n  DWORD newStyle = (style & ~remove) | add;\n  if (style == newStyle)\n    return false; // it is not good\n\n  SetWindowLong(styleOffset, newStyle);\n  if (flags != 0)\n  {\n    ::SetWindowPos(_window, NULL, 0, 0, 0, 0,\n      SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | flags);\n  }\n  return TRUE;\n}\n*/\n\n}\n"
  },
  {
    "path": "NanaZip.Core/SevenZip/CPP/Windows/Window.h",
    "content": "﻿// Windows/Window.h\n\n#ifndef ZIP7_INC_WINDOWS_WINDOW_H\n#define ZIP7_INC_WINDOWS_WINDOW_H\n\n#include \"../Common/MyWindows.h\"\n#include \"../Common/MyString.h\"\n\n#include \"Defs.h\"\n\n#ifndef UNDER_CE\n#ifdef WM_CHANGEUISTATE\n#define Z7_WIN_WM_CHANGEUISTATE  WM_CHANGEUISTATE\n#define Z7_WIN_WM_UPDATEUISTATE  WM_UPDATEUISTATE\n#define Z7_WIN_WM_QUERYUISTATE   WM_QUERYUISTATE\n#else\n// these are defined for (_WIN32_WINNT >= 0x0500):\n#define Z7_WIN_WM_CHANGEUISTATE  0x0127\n#define Z7_WIN_WM_UPDATEUISTATE  0x0128\n#define Z7_WIN_WM_QUERYUISTATE   0x0129\n#endif\n\n#ifdef UIS_SET\n\n#define Z7_WIN_UIS_SET         UIS_SET\n#define Z7_WIN_UIS_CLEAR       UIS_CLEAR\n#define Z7_WIN_UIS_INITIALIZE  UIS_INITIALIZE\n\n#define Z7_WIN_UISF_HIDEFOCUS  UISF_HIDEFOCUS\n#define Z7_WIN_UISF_HIDEACCEL  UISF_HIDEACCEL\n\n#else\n// these are defined for (_WIN32_WINNT >= 0x0500):\n// LOWORD(wParam) values in WM_*UISTATE\n#define Z7_WIN_UIS_SET         1\n#define Z7_WIN_UIS_CLEAR       2\n#define Z7_WIN_UIS_INITIALIZE  3\n\n// HIWORD(wParam) values in WM_*UISTATE\n#define Z7_WIN_UISF_HIDEFOCUS  0x1\n#define Z7_WIN_UISF_HIDEACCEL  0x2\n// defined for for (_WIN32_WINNT >= 0x0501):\n// #define Z7_WIN_UISF_ACTIVE     0x4\n\n#endif\n\n#endif // UNDER_CE\n\n\n#ifdef Z7_OLD_WIN_SDK\n\n// #define VK_OEM_1          0xBA   // ';:' for US\n#define VK_OEM_PLUS       0xBB   // '+' any country\n// #define VK_OEM_COMMA      0xBC   // ',' any country\n#define VK_OEM_MINUS      0xBD   // '-' any country\n// #define VK_OEM_PERIOD     0xBE   // '.' any country\n// #define VK_OEM_2          0xBF   // '/?' for US\n// #define VK_OEM_3          0xC0   // '`~' for US\n\n// #ifndef GWLP_USERDATA\n#define GWLP_WNDPROC        (-4)\n#define GWLP_USERDATA       (-21)\n// #endif\n#define DWLP_MSGRESULT  0\n// #define DWLP_DLGPROC    DWLP_MSGRESULT + sizeof(LRESULT)\n// #define DWLP_USER       DWLP_DLGPROC + sizeof(DLGPROC)\n\n#define BTNS_BUTTON     TBSTYLE_BUTTON      // 0x0000\n\n/*\nvc6 defines INT_PTR via long:\n  typedef long INT_PTR, *PINT_PTR;\n  typedef unsigned long UINT_PTR, *PUINT_PTR;\nbut newer sdk (sdk2003+) defines INT_PTR via int:\n  typedef _W64 int INT_PTR, *PINT_PTR;\n  typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;\n*/\n\n#define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)\n\n#define GetWindowLongPtrA   GetWindowLongA\n#define GetWindowLongPtrW   GetWindowLongW\n#ifdef UNICODE\n#define GetWindowLongPtr  GetWindowLongPtrW\n#else\n#define GetWindowLongPtr  GetWindowLongPtrA\n#endif // !UNICODE\n\n#define SetWindowLongPtrA   SetWindowLongA\n#define SetWindowLongPtrW   SetWindowLongW\n#ifdef UNICODE\n#define SetWindowLongPtr  SetWindowLongPtrW\n#else\n#define SetWindowLongPtr  SetWindowLongPtrA\n#endif // !UNICODE\n\n#define ListView_SetCheckState(hwndLV, i, fCheck) \\\n  ListView_SetItemState(hwndLV, i, INDEXTOSTATEIMAGEMASK((fCheck)?2:1), LVIS_STATEIMAGEMASK)\n\n#endif // Z7_OLD_WIN_SDK\n\ninline bool LRESULTToBool(LRESULT v) { return (v != FALSE); }\n\n#define MY_int_TO_WPARAM(i) ((WPARAM)(INT_PTR)(i))\n\nnamespace NWindows {\n\ninline ATOM MyRegisterClass(CONST WNDCLASS *wndClass)\n  { return ::RegisterClass(wndClass); }\n\n#ifndef _UNICODE\nATOM MyRegisterClass(CONST WNDCLASSW *wndClass);\n#endif\n\n#ifdef _UNICODE\ninline bool MySetWindowText(HWND wnd, LPCWSTR s) { return BOOLToBool(::SetWindowText(wnd, s)); }\n#else\nbool MySetWindowText(HWND wnd, LPCWSTR s);\n#endif\n\n\n#ifdef UNDER_CE\n#define GWLP_USERDATA GWL_USERDATA\n#define GWLP_WNDPROC GWL_WNDPROC\n#define BTNS_BUTTON TBSTYLE_BUTTON\n#define WC_COMBOBOXW L\"ComboBox\"\n#define DWLP_MSGRESULT DWL_MSGRESULT\n#endif\n\nclass CWindow\n{\n  Z7_CLASS_NO_COPY(CWindow)\nprivate:\n  // bool ModifyStyleBase(int styleOffset, DWORD remove, DWORD add, UINT flags);\nprotected:\n  HWND _window;\npublic:\n  CWindow(HWND newWindow = NULL): _window(newWindow) {}\n  CWindow& operator=(HWND newWindow)\n  {\n    _window = newWindow;\n    return *this;\n  }\n  operator HWND() const { return _window; }\n  // **************** NanaZip Modification Start ****************\n  // void Attach(HWND newWindow) { _window = newWindow; }\n  virtual void Attach(HWND newWindow) { _window = newWindow; }\n  // **************** NanaZip Modification End ****************\n  HWND Detach()\n  {\n    HWND window = _window;\n    _window = NULL;\n    return window;\n  }\n\n  bool Foreground() { return BOOLToBool(::SetForegroundWindow(_window)); }\n  \n  HWND GetParent() const { return ::GetParent(_window); }\n  bool GetWindowRect(LPRECT rect) const { return BOOLToBool(::GetWindowRect(_window,rect)); }\n  #ifndef UNDER_CE\n  bool IsZoomed() const { return BOOLToBool(::IsZoomed(_window)); }\n  #endif\n  bool ClientToScreen(LPPOINT point) const { return BOOLToBool(::ClientToScreen(_window, point)); }\n  bool ScreenToClient(LPPOINT point) const { return BOOLToBool(::ScreenToClient(_window, point)); }\n\n  bool CreateEx(DWORD exStyle, LPCTSTR className,\n      LPCTSTR windowName, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam)\n  {\n    _window = ::CreateWindowEx(exStyle, className, windowName,\n      style, x, y, width, height, parentWindow,\n      idOrHMenu, instance, createParam);\n    return (_window != NULL);\n  }\n\n  bool Create(LPCTSTR className,\n      LPCTSTR windowName, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam)\n  {\n    _window = ::CreateWindow(className, windowName,\n      style, x, y, width, height, parentWindow,\n      idOrHMenu, instance, createParam);\n    return (_window != NULL);\n  }\n\n  #ifndef _UNICODE\n  bool Create(LPCWSTR className,\n      LPCWSTR windowName, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam);\n  bool CreateEx(DWORD exStyle, LPCWSTR className,\n      LPCWSTR windowName, DWORD style,\n      int x, int y, int width, int height,\n      HWND parentWindow, HMENU idOrHMenu,\n      HINSTANCE instance, LPVOID createParam);\n  #endif\n\n\n  bool Destroy()\n  {\n    if (_window == NULL)\n      return true;\n    bool result = BOOLToBool(::DestroyWindow(_window));\n    if (result)\n      _window = NULL;\n    return result;\n  }\n  bool IsWindow() {  return BOOLToBool(::IsWindow(_window)); }\n  bool Move(int x, int y, int width, int height, bool repaint = true)\n    { return BOOLToBool(::MoveWindow(_window, x, y, width, height, BoolToBOOL(repaint))); }\n\n  bool ChangeSubWindowSizeX(HWND hwnd, int xSize)\n  {\n    RECT rect;\n    ::GetWindowRect(hwnd, &rect);\n    POINT p1;\n    p1.x = rect.left;\n    p1.y = rect.top;\n    ScreenToClient(&p1);\n    return BOOLToBool(::MoveWindow(hwnd, p1.x, p1.y, xSize, rect.bottom - rect.top, TRUE));\n  }\n\n  void ScreenToClient(RECT *rect)\n  {\n    POINT p1, p2;\n    p1.x = rect->left;\n    p1.y = rect->top;\n    p2.x = rect->right;\n    p2.y = rect->bottom;\n    ScreenToClient(&p1);\n    ScreenToClient(&p2);\n\n    rect->left = p1.x;\n    rect->top = p1.y;\n    rect->right = p2.x;\n    rect->bottom = p2.y;\n  }\n\n  bool GetClientRect(LPRECT rect) { return BOOLToBool(::GetClientRect(_window, rect)); }\n  bool Show(int cmdShow) { return BOOLToBool(::ShowWindow(_window, cmdShow)); }\n  bool Show_Bool(bool show) { return Show(show ? SW_SHOW: SW_HIDE); }\n\n  #ifndef UNDER_CE\n  bool SetPlacement(CONST WINDOWPLACEMENT *placement) { return BOOLToBool(::SetWindowPlacement(_window, placement)); }\n  bool GetPlacement(WINDOWPLACEMENT *placement) { return BOOLToBool(::GetWindowPlacement(_window, placement)); }\n  #endif\n  bool Update() { return BOOLToBool(::UpdateWindow(_window)); }\n  bool InvalidateRect(LPCRECT rect, bool backgroundErase = true)\n    { return BOOLToBool(::InvalidateRect(_window, rect, BoolToBOOL(backgroundErase))); }\n  void SetRedraw(bool redraw = true) { SendMsg(WM_SETREDRAW, (WPARAM)BoolToBOOL(redraw), 0); }\n\n  LONG_PTR SetStyle(LONG_PTR style) { return SetLongPtr(GWL_STYLE, style); }\n  // LONG_PTR SetStyle(DWORD style) { return SetLongPtr(GWL_STYLE, (LONG_PTR)style); }\n  LONG_PTR GetStyle() const { return GetLongPtr(GWL_STYLE); }\n  // bool MyIsMaximized() const { return ((GetStyle() & WS_MAXIMIZE) != 0); }\n\n  LONG_PTR SetLong(int index, LONG newLongPtr) { return ::SetWindowLong(_window, index, newLongPtr); }\n  LONG_PTR GetLong(int index) const { return ::GetWindowLong(_window, index); }\n  LONG_PTR SetUserDataLong(LONG newLongPtr) { return SetLong(GWLP_USERDATA, newLongPtr); }\n  LONG_PTR GetUserDataLong() const { return GetLong(GWLP_USERDATA); }\n\n\n  #ifdef UNDER_CE\n\n  LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr) { return SetLong(index, newLongPtr); }\n  LONG_PTR GetLongPtr(int index) const { return GetLong(index); }\n\n  LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetUserDataLong(newLongPtr); }\n  LONG_PTR GetUserDataLongPtr() const { return GetUserDataLong(); }\n  \n  #else\n  \n  LONG_PTR SetLongPtr(int index, LONG_PTR newLongPtr)\n    { return ::SetWindowLongPtr(_window, index,\n          #ifndef _WIN64\n          (LONG)\n          #endif\n          newLongPtr); }\n  #ifndef _UNICODE\n  LONG_PTR SetLongPtrW(int index, LONG_PTR newLongPtr)\n    { return ::SetWindowLongPtrW(_window, index,\n          #ifndef _WIN64\n          (LONG)\n          #endif\n          newLongPtr); }\n  #endif\n\n  LONG_PTR GetLongPtr(int index) const { return ::GetWindowLongPtr(_window, index); }\n  LONG_PTR SetUserDataLongPtr(LONG_PTR newLongPtr) { return SetLongPtr(GWLP_USERDATA, newLongPtr); }\n  LONG_PTR GetUserDataLongPtr() const { return GetLongPtr(GWLP_USERDATA); }\n  \n  #endif\n  \n  /*\n  bool ModifyStyle(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)\n    {  return ModifyStyleBase(GWL_STYLE, remove, add, flags); }\n  bool ModifyStyleEx(HWND hWnd, DWORD remove, DWORD add, UINT flags = 0)\n    { return ModifyStyleBase(GWL_EXSTYLE, remove, add, flags); }\n  */\n \n  HWND SetFocus() { return ::SetFocus(_window); }\n\n  LRESULT SendMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\n    { return ::SendMessage(_window, message, wParam, lParam); }\n  #ifndef _UNICODE\n  LRESULT SendMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\n    { return ::SendMessageW(_window, message, wParam, lParam); }\n  #endif\n\n  bool PostMsg(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\n    { return BOOLToBool(::PostMessage(_window, message, wParam, lParam)); }\n  #ifndef _UNICODE\n  bool PostMsgW(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)\n    { return BOOLToBool(::PostMessageW(_window, message, wParam, lParam)); }\n  #endif\n\n  bool SetText(LPCTSTR s) { return BOOLToBool(::SetWindowText(_window, s)); }\n  #ifndef _UNICODE\n  bool SetText(LPCWSTR s) { return MySetWindowText(_window, s); }\n  #endif\n\n  int GetTextLength() const\n    { return GetWindowTextLength(_window); }\n  int GetText(LPTSTR string, int maxCount) const\n    { return GetWindowText(_window, string, maxCount); }\n  bool GetText(CSysString &s) const;\n  #ifndef _UNICODE\n  /*\n  UINT GetText(LPWSTR string, int maxCount) const\n    { return GetWindowTextW(_window, string, maxCount); }\n  */\n  bool GetText(UString &s) const;\n  #endif\n\n  bool Enable(bool enable)\n    { return BOOLToBool(::EnableWindow(_window, BoolToBOOL(enable))); }\n  \n  bool IsEnabled() const\n    { return BOOLToBool(::IsWindowEnabled(_window)); }\n  \n  #ifndef UNDER_CE\n  HMENU GetSystemMenu(bool revert)\n    { return ::GetSystemMenu(_window, BoolToBOOL(revert)); }\n  #endif\n\n  UINT_PTR SetTimer(UINT_PTR idEvent, UINT elapse, TIMERPROC timerFunc = NULL)\n    { return ::SetTimer(_window, idEvent, elapse, timerFunc); }\n  bool KillTimer(UINT_PTR idEvent)\n    {return BOOLToBool(::KillTimer(_window, idEvent)); }\n\n  HICON SetIcon(WPARAM sizeType, HICON icon) { return (HICON)SendMsg(WM_SETICON, sizeType, (LPARAM)icon); }\n};\n\n#define RECT_SIZE_X(r) ((r).right - (r).left)\n#define RECT_SIZE_Y(r) ((r).bottom - (r).top)\n\ninline bool IsKeyDown(int virtKey) { return (::GetKeyState(virtKey) & 0x8000) != 0; }\n\n}\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Wrappers/Sha1Wrapper.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       Sha1Wrapper.cpp\n * PURPOSE:    Implementation for SHA-1 wrapper for 7-Zip\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"Sha1Wrapper.h\"\n\n#include <Windows.h>\n\n#include <cstring>\n\nCSha1& CSha1::operator=(\n    CSha1 const& Source)\n{\n    if (this != &Source)\n    {\n        if (this->HashHandle)\n        {\n            ::K7BaseHashDestroy(this->HashHandle);\n            this->HashHandle = nullptr;\n        }\n        if (Source.HashHandle)\n        {\n            ::K7BaseHashDuplicate(Source.HashHandle, &this->HashHandle);\n        }\n    }\n    return *this;\n}\n\nBoolInt Sha1_SetFunction(\n    CSha1* p,\n    unsigned algo)\n{\n    UNREFERENCED_PARAMETER(algo);\n\n    if (p)\n    {\n        // Workaround for using the uninitialized memory.\n        std::memset(p, 0, sizeof(CSha1));\n    }\n\n    // Only return true because it's a wrapper to K7Base.\n    return True;\n}\n\nvoid Sha1_InitState(\n    CSha1* p)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    if (p->HashHandle)\n    {\n        ::K7BaseHashDestroy(p->HashHandle);\n        p->HashHandle = nullptr;\n    }\n\n    ::K7BaseHashCreate(\n        &p->HashHandle,\n        K7_BASE_HASH_ALGORITHM_SHA1,\n        nullptr,\n        0);\n}\n\nvoid Sha1_Init(\n    CSha1* p)\n{\n    if (p)\n    {\n        // Workaround for using the uninitialized memory.\n        std::memset(p, 0, sizeof(CSha1));\n    }\n\n    ::Sha1_InitState(p);\n}\n\nvoid Sha1_Update(\n    CSha1* p,\n    const Byte* data,\n    size_t size)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    ::K7BaseHashUpdate(\n        p->HashHandle,\n        const_cast<LPVOID>(reinterpret_cast<LPCVOID>(data)),\n        static_cast<UINT32>(size));\n}\n\nvoid Sha1_Final(\n    CSha1* p,\n    Byte* digest)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    ::K7BaseHashFinal(\n        p->HashHandle,\n        digest,\n        SHA1_DIGEST_SIZE);\n}\n\nvoid Sha1_PrepareBlock(\n    const CSha1* p,\n    Byte* block,\n    unsigned size)\n{\n    UNREFERENCED_PARAMETER(p);\n    UNREFERENCED_PARAMETER(block);\n    UNREFERENCED_PARAMETER(size);\n\n    // Empty implementation because it's a wrapper to K7Base.\n}\n\nvoid Sha1_GetBlockDigest(\n    const CSha1* p,\n    const Byte* data,\n    Byte* destDigest)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    K7_BASE_HASH_HANDLE CurrentHashHandle = nullptr;\n    if (MO_RESULT_SUCCESS_OK == ::K7BaseHashDuplicate(\n        p->HashHandle,\n        &CurrentHashHandle))\n    {\n        if (MO_RESULT_SUCCESS_OK == ::K7BaseHashUpdate(\n            CurrentHashHandle,\n            const_cast<LPVOID>(reinterpret_cast<LPCVOID>(data)),\n            SHA1_DIGEST_SIZE))\n        {\n            ::K7BaseHashFinal(\n                CurrentHashHandle,\n                destDigest,\n                SHA1_DIGEST_SIZE);\n        }\n        ::K7BaseHashDestroy(CurrentHashHandle);\n    }\n}\n"
  },
  {
    "path": "NanaZip.Core/Wrappers/Sha1Wrapper.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       Sha1Wrapper.h\n * PURPOSE:    Definition for SHA-1 wrapper for 7-Zip\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef ZIP7_INC_SHA1_H\n#define ZIP7_INC_SHA1_H\n\n#include \"../SevenZip/C/7zTypes.h\"\n\n#include <K7Base.h>\n\nEXTERN_C_BEGIN\n\n#define SHA1_NUM_BLOCK_WORDS  16\n#define SHA1_NUM_DIGEST_WORDS  5\n\n#define SHA1_BLOCK_SIZE   (SHA1_NUM_BLOCK_WORDS * 4)\n#define SHA1_DIGEST_SIZE  (SHA1_NUM_DIGEST_WORDS * 4)\n\ntypedef struct CSha1\n{\n    K7_BASE_HASH_HANDLE HashHandle;\n\n#ifdef __cplusplus\n    CSha1& operator=(\n        CSha1 const& Source);\n#endif // __cplusplus\n} CSha1;\n\n#define SHA1_ALGO_DEFAULT 0\n#define SHA1_ALGO_SW      1\n#define SHA1_ALGO_HW      2\n\n/*\nSha1_SetFunction()\nreturn:\n  0 - (algo) value is not supported, and func_UpdateBlocks was not changed\n  1 - func_UpdateBlocks was set according (algo) value.\n*/\nBoolInt Sha1_SetFunction(\n    CSha1* p,\n    unsigned algo);\n\nvoid Sha1_InitState(\n    CSha1* p);\n\nvoid Sha1_Init(\n    CSha1* p);\n\nvoid Sha1_Update(\n    CSha1* p,\n    const Byte* data,\n    size_t size);\n\nvoid Sha1_Final(\n    CSha1* p,\n    Byte* digest);\n\nvoid Sha1_PrepareBlock(\n    const CSha1* p,\n    Byte* block,\n    unsigned size);\n\nvoid Sha1_GetBlockDigest(\n    const CSha1* p,\n    const Byte* data,\n    Byte* destDigest);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Wrappers/Sha256Wrapper.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       Sha256Wrapper.cpp\n * PURPOSE:    Implementation for SHA-256 wrapper for 7-Zip\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"Sha256Wrapper.h\"\n\n#include <Windows.h>\n\n#include <cstring>\n\nCSha256& CSha256::operator=(\n    CSha256 const& Source)\n{\n    if (this != &Source)\n    {\n        if (this->HashHandle)\n        {\n            ::K7BaseHashDestroy(this->HashHandle);\n            this->HashHandle = nullptr;\n        }\n        if (Source.HashHandle)\n        {\n            ::K7BaseHashDuplicate(Source.HashHandle, &this->HashHandle);\n        }\n    }\n    return *this;\n}\n\nBoolInt Sha256_SetFunction(\n    CSha256* p,\n    unsigned algo)\n{\n    UNREFERENCED_PARAMETER(algo);\n\n    if (p)\n    {\n        // Workaround for using the uninitialized memory.\n        std::memset(p, 0, sizeof(CSha256));\n    }\n\n    // Only return true because it's a wrapper to K7Base.\n    return True;\n}\n\nvoid Sha256_InitState(\n    CSha256* p)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    if (p->HashHandle)\n    {\n        ::K7BaseHashDestroy(p->HashHandle);\n        p->HashHandle = nullptr;\n    }\n\n    ::K7BaseHashCreate(\n        &p->HashHandle,\n        K7_BASE_HASH_ALGORITHM_SHA256,\n        nullptr,\n        0);\n}\n\nvoid Sha256_Init(\n    CSha256* p)\n{\n    if (p)\n    {\n        // Workaround for using the uninitialized memory.\n        std::memset(p, 0, sizeof(CSha256));\n    }\n\n    ::Sha256_InitState(p);\n}\n\nvoid Sha256_Update(\n    CSha256* p,\n    const Byte* data,\n    size_t size)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    ::K7BaseHashUpdate(\n        p->HashHandle,\n        const_cast<LPVOID>(reinterpret_cast<LPCVOID>(data)),\n        static_cast<UINT32>(size));\n}\n\nvoid Sha256_Final(\n    CSha256* p,\n    Byte* digest)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    ::K7BaseHashFinal(\n        p->HashHandle,\n        digest,\n        SHA256_DIGEST_SIZE);\n}\n"
  },
  {
    "path": "NanaZip.Core/Wrappers/Sha256Wrapper.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       Sha256Wrapper.h\n * PURPOSE:    Definition for SHA-256 wrapper for 7-Zip\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef ZIP7_INC_SHA256_H\n#define ZIP7_INC_SHA256_H\n\n#include \"../SevenZip/C/7zTypes.h\"\n\n#include <K7Base.h>\n\nEXTERN_C_BEGIN\n\n#define SHA256_NUM_BLOCK_WORDS  16\n#define SHA256_NUM_DIGEST_WORDS  8\n\n#define SHA256_BLOCK_SIZE   (SHA256_NUM_BLOCK_WORDS * 4)\n#define SHA256_DIGEST_SIZE  (SHA256_NUM_DIGEST_WORDS * 4)\n\ntypedef struct CSha256\n{\n    K7_BASE_HASH_HANDLE HashHandle;\n\n#ifdef __cplusplus\n    CSha256& operator=(\n        CSha256 const& Source);\n#endif // __cplusplus\n} CSha256;\n\n#define SHA256_ALGO_DEFAULT 0\n#define SHA256_ALGO_SW 1\n#define SHA256_ALGO_HW 2\n\n/*\nSha256_SetFunction()\nreturn:\n  0 - (algo) value is not supported, and func_UpdateBlocks was not changed\n  1 - func_UpdateBlocks was set according (algo) value.\n*/\nBoolInt Sha256_SetFunction(\n    CSha256* p,\n    unsigned algo);\n\nvoid Sha256_InitState(\n    CSha256* p);\n\nvoid Sha256_Init(\n    CSha256* p);\n\nvoid Sha256_Update(\n    CSha256* p,\n    const Byte* data,\n    size_t size);\n\nvoid Sha256_Final(\n    CSha256* p,\n    Byte* digest);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.Core/Wrappers/Sha512Wrapper.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       Sha512Wrapper.cpp\n * PURPOSE:    Implementation for SHA-384/SHA-512 wrapper for 7-Zip\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"Sha512Wrapper.h\"\n\n#include <Windows.h>\n\n#include <cstring>\n\nCSha512& CSha512::operator=(\n    CSha512 const& Source)\n{\n    if (this != &Source)\n    {\n        if (this->HashHandle)\n        {\n            ::K7BaseHashDestroy(this->HashHandle);\n            this->HashHandle = nullptr;\n        }\n        if (Source.HashHandle)\n        {\n            ::K7BaseHashDuplicate(Source.HashHandle, &this->HashHandle);\n        }\n    }\n    return *this;\n}\n\nBoolInt Sha512_SetFunction(\n    CSha512* p,\n    unsigned algo)\n{\n    UNREFERENCED_PARAMETER(algo);\n\n    if (p)\n    {\n        // Workaround for using the uninitialized memory.\n        std::memset(p, 0, sizeof(CSha512));\n    }\n\n    // Only return true because it's a wrapper to K7Base.\n    return True;\n}\n\nvoid Sha512_InitState(\n    CSha512* p,\n    unsigned digestSize)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    if (p->HashHandle)\n    {\n        ::K7BaseHashDestroy(p->HashHandle);\n        p->HashHandle = nullptr;\n    }\n\n    if (SHA512_DIGEST_SIZE == digestSize)\n    {\n        ::K7BaseHashCreate(\n            &p->HashHandle,\n            K7_BASE_HASH_ALGORITHM_SHA512,\n            nullptr,\n            0);\n    }\n    else if (SHA512_384_DIGEST_SIZE == digestSize)\n    {\n        ::K7BaseHashCreate(\n            &p->HashHandle,\n            K7_BASE_HASH_ALGORITHM_SHA384,\n            nullptr,\n            0);\n    }\n}\n\nvoid Sha512_Init(\n    CSha512* p,\n    unsigned digestSize)\n{\n    if (p)\n    {\n        // Workaround for using the uninitialized memory.\n        std::memset(p, 0, sizeof(CSha512));\n    }\n\n    ::Sha512_InitState(p, digestSize);\n}\n\nvoid Sha512_Update(\n    CSha512* p,\n    const Byte* data,\n    size_t size)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    ::K7BaseHashUpdate(\n        p->HashHandle,\n        const_cast<LPVOID>(reinterpret_cast<LPCVOID>(data)),\n        static_cast<UINT32>(size));\n}\n\nvoid Sha512_Final(\n    CSha512* p,\n    Byte* digest,\n    unsigned digestSize)\n{\n    if (!p)\n    {\n        return;\n    }\n\n    ::K7BaseHashFinal(\n        p->HashHandle,\n        digest,\n        digestSize);\n}\n"
  },
  {
    "path": "NanaZip.Core/Wrappers/Sha512Wrapper.h",
    "content": "﻿/*\n * PROJECT:    NanaZip\n * FILE:       Sha512Wrapper.h\n * PURPOSE:    Definition for SHA-384/SHA-512 wrapper for 7-Zip\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef ZIP7_INC_SHA512_H\n#define ZIP7_INC_SHA512_H\n\n#include \"../SevenZip/C/7zTypes.h\"\n\n#include <K7Base.h>\n\nEXTERN_C_BEGIN\n\n#define SHA512_NUM_DIGEST_WORDS  8\n\n#define SHA512_DIGEST_SIZE  (SHA512_NUM_DIGEST_WORDS * 8)\n#define SHA512_384_DIGEST_SIZE  (384 / 8)\n\ntypedef struct CSha512\n{\n    K7_BASE_HASH_HANDLE HashHandle;\n\n#ifdef __cplusplus\n    CSha512& operator=(\n        CSha512 const& Source);\n#endif // __cplusplus\n} CSha512;\n\n#define SHA512_ALGO_DEFAULT 0\n#define SHA512_ALGO_SW 1\n#define SHA512_ALGO_HW 2\n\n/*\nSha512_SetFunction()\nreturn:\n  0 - (algo) value is not supported, and func_UpdateBlocks was not changed\n  1 - func_UpdateBlocks was set according (algo) value.\n*/\nBoolInt Sha512_SetFunction(\n    CSha512* p,\n    unsigned algo);\n\n// we support only these (digestSize) values: 384/8, 512/8\n\nvoid Sha512_InitState(\n    CSha512* p,\n    unsigned digestSize);\n\nvoid Sha512_Init(\n    CSha512* p,\n    unsigned digestSize);\n\nvoid Sha512_Update(\n    CSha512* p,\n    const Byte* data,\n    size_t size);\n\nvoid Sha512_Final(\n    CSha512* p,\n    Byte* digest,\n    unsigned digestSize);\n\nEXTERN_C_END\n\n#endif\n"
  },
  {
    "path": "NanaZip.ExtensionPackage/NanaZip.ExtensionPackage.Installer.iss",
    "content": "﻿#define AppName \"NanaZip Extension Package\"\n#define AppPublisher \"M2-Team\"\n#define AppCopyright \"© M2-Team and Contributors. All rights reserved.\"\n#define AppURL \"https://github.com/M2Team/NanaZip\"\n\n#ifndef AppVersion\n#define AppVersion \"5.1.0.0\"\n#endif\n\n[Setup]\nAppId={{42795434-AB1A-4197-A724-F13E08953DFC}\nAppName={#AppName}\nAppCopyright={#AppCopyright}\nAppVersion={#AppVersion}\nAppPublisher={#AppPublisher}\nAppPublisherURL={#AppURL}\nAppSupportURL={#AppURL}\nAppUpdatesURL={#AppURL}\nDefaultDirName={autopf}\\{#AppName}\nDisableDirPage=yes\nDefaultGroupName={#AppName}\nDisableProgramGroupPage=yes\nVersionInfoVersion={#AppVersion}\n\nPrivilegesRequired=lowest\nPrivilegesRequiredOverridesAllowed=dialog\nOutputBaseFilename=NanaZip.ExtensionPackage_{#AppVersion}\nSolidCompression=yes\nWizardStyle=modern\n\nArchitecturesAllowed=x64compatible or arm64\nArchitecturesInstallIn64BitMode=x64compatible or arm64\n\n[Languages]\nName: \"english\"; MessagesFile: \"compiler:Default.isl\"\n"
  },
  {
    "path": "NanaZip.ExtensionPackage/NanaZip.ExtensionPackage.Installer.proj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project Sdk=\"Microsoft.Build.NoTargets/3.7.56\" DefaultTargets=\"Restore;Build\">\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <Version>$(MileProjectVersion)</Version>\n    <InstallerOutputPath>$(MSBuildThisFileDirectory)..\\Output</InstallerOutputPath>\n  </PropertyGroup>\n\n  <!-- NOTE: verify Tools.InnoSetup package binaries with official binaries every upgrade -->\n  <ItemGroup>\n    <PackageReference Include=\"Tools.InnoSetup\" Version=\"6.4.2\" />\n  </ItemGroup>\n\n  <Target Name=\"BuildInstaller\" BeforeTargets=\"AfterBuild\">\n    <Exec Command='\"$(InnoSetupCompiler)\" \"$(MSBuildProjectName).iss\" \"/DAppVersion=$(Version)\" \"/O$(InstallerOutputPath)\"' />\n  </Target>\n</Project>\n"
  },
  {
    "path": "NanaZip.MaintainerTools.slnx",
    "content": "<Solution>\n  <Project Path=\"NanaZip.Build.Tasks/NanaZip.Build.Tasks.csproj\" />\n  <Project Path=\"NanaZip.MigrateLegacyStringResources/NanaZip.MigrateLegacyStringResources.csproj\" />\n  <Project Path=\"NanaZip.ProjectAssetsGenerator/NanaZip.ProjectAssetsGenerator.csproj\" />\n  <Project Path=\"NanaZip.RefreshPackageVersion/NanaZip.RefreshPackageVersion.csproj\" />\n</Solution>\n"
  },
  {
    "path": "NanaZip.MigrateLegacyStringResources/NanaZip.MigrateLegacyStringResources.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net10.0</TargetFramework>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <Nullable>enable</Nullable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Build\" Version=\"18.0.2\" />\n    <PackageReference Include=\"Mile.Project.Helpers\" Version=\"1.0.975\" />\n    <PackageReference Include=\"vswhere\" Version=\"3.1.7\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n  <ItemGroup>\n    <Content Include=\"$(VSWhereDir)vswhere.exe\" CopyToOutputDirectory=\"PreserveNewest\" CopyToPublishDirectory=\"PreserveNewest\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "NanaZip.MigrateLegacyStringResources/Program.cs",
    "content": "﻿using Microsoft.Build.Construction;\nusing System.Collections.Immutable;\nusing System.Xml;\n\nnamespace NanaZip.MigrateLegacyStringResources;\n\npublic record ResourceMapping(\n    int ResourceKey,\n    string File,\n    string NewResourcePath,\n    bool RemoveAmpersand = false\n);\n\ninternal class Program\n{\n    const string StringsDir = \"Strings\";\n    const string LegacyDir = $\"NanaZipPackage\\\\{StringsDir}\";\n    const string NewDir = $\"NanaZip.Modern\\\\{StringsDir}\";\n    const string OldFileName = @\"Legacy.resw\";\n\n    static readonly ImmutableArray<ResourceMapping> map =\n        [\n            new(402, \"Common\", \"CancelButton.Content\", true),\n            new(408, \"Common\", \"CloseButton.Content\", true),\n            new(401, \"Common\", \"OKButton.Content\", true),\n            new(3900, \"ProgressPage\", \"ElapsedTimeLabel.Text\"),\n            new(3901, \"ProgressPage\", \"RemainingTimeLabel.Text\"),\n            new(3902, \"ProgressPage\", \"TotalSizeLabel.Text\"),\n            new(3903, \"ProgressPage\", \"SpeedLabel.Text\"),\n            new(3904, \"ProgressPage\", \"ProcessedLabel.Text\"),\n            new(3905, \"ProgressPage\", \"CompressionRatioLabel.Text\"),\n            new(3906, \"ProgressPage\", \"ErrorsLabel.Text\"),\n            new(1032, \"ProgressPage\", \"FilesLabel.Text\"),\n            new(1008, \"ProgressPage\", \"PackedSizeLabel.Text\"),\n            new(444, \"ProgressPage\", \"BackgroundButtonText\", true),\n            new(445, \"ProgressPage\", \"ForegroundButtonText\", true),\n            new(446, \"ProgressPage\", \"PauseButtonText\", true),\n            new(411, \"ProgressPage\", \"ContinueButtonText\", true),\n            new(447, \"ProgressPage\", \"PausedText\"),\n            new(6007, \"CopyLocationPage\", \"SelectDestinationText\"),\n        ];\n\n    static readonly ImmutableArray<IGrouping<string, ResourceMapping>> Mappings\n        = map.GroupBy(x => x.File).ToImmutableArray();\n\n    static int Main(string[] args)\n    {\n        string gitRoot = Mile.Project.Helpers.GitRepository.GetRootPath();\n\n        if (string.IsNullOrEmpty(gitRoot))\n        {\n            Console.WriteLine(\"This tool must be placed in a Git repository.\");\n            return -1;\n        }\n\n        string? vslocation = VSWhereHelper.GetVSPath();\n        if (string.IsNullOrEmpty(vslocation))\n        {\n            Console.WriteLine(\"Visual Studio must be installed.\");\n            return -2;\n        }\n\n        string reswTemplatePath =\n            $\"{vslocation}\\\\Common7\\\\IDE\\\\ItemTemplates\\\\WapProj\\\\\" +\n            $\"1033\\\\Resw\\\\Resources.resw\";\n\n        List<(string Lang, string File)> files = new();\n\n        foreach (\n            DirectoryInfo oldSubDirs\n            in\n            new DirectoryInfo($\"{gitRoot}\\\\{LegacyDir}\")\n            .GetDirectories())\n        {\n            string language = oldSubDirs.Name;\n            string oldFile = $\"{oldSubDirs.FullName}\\\\{OldFileName}\";\n            XmlDocument oldDoc = new XmlDocument();\n            oldDoc.Load(oldFile);\n\n            foreach (var file in Mappings)\n            {\n                string fileName = file.Key;\n                XmlDocument newDoc = new();\n                try\n                {\n                    newDoc.Load($\"{gitRoot}\\\\{NewDir}\\\\{language}\\\\{fileName}.resw\");\n                }\n                catch\n                {\n                    newDoc.Load(reswTemplatePath);\n                }\n\n                foreach (var mapping in file)\n                {\n                    XmlNode? oldNode = oldDoc.SelectSingleNode(\n                        $\"/root/data[@name='Resource{mapping.ResourceKey}']/value\"\n                    );\n\n                    if (oldNode is null)\n                        continue;\n\n                    string newText = oldNode.InnerText ?? string.Empty;\n                    if (mapping.RemoveAmpersand)\n                    {\n                        newText = newText.Replace(\"&\", string.Empty);\n                    }\n\n                    XmlNode? newNode = newDoc.SelectSingleNode(\n                        $\"/root/data[@name='{mapping.NewResourcePath}']/value\"\n                    );\n\n                    if (newNode is not null)\n                    {\n                        newNode.InnerText = newText;\n                        continue;\n                    }\n\n                    XmlElement data = newDoc.CreateElement(\"data\");\n                    data.SetAttribute(\"name\", mapping.NewResourcePath);\n                    data.SetAttribute(\"xml:space\", \"preserve\");\n                    XmlElement dataValue = newDoc.CreateElement(\"value\");\n                    dataValue.InnerText = newText;\n                    data.AppendChild(dataValue);\n                    newDoc.DocumentElement!.AppendChild(data);\n                }\n\n                Directory.CreateDirectory($\"{gitRoot}\\\\{NewDir}\\\\{language}\");\n                files.Add((language, $\"{StringsDir}\\\\{language}\\\\{fileName}.resw\"));\n\n                using FileStream stream = new(\n                    $\"{gitRoot}\\\\{NewDir}\\\\{language}\\\\{fileName}.resw\",\n                    FileMode.OpenOrCreate);\n                stream.SetLength(0);\n                using XmlWriter writer = XmlWriter.Create(\n                    stream,\n                    new XmlWriterSettings() { Indent = true });\n                newDoc.WriteTo(writer);\n            }\n        }\n\n        var project = ProjectRootElement.Open(\n            $\"{gitRoot}\\\\NanaZip.Modern\\\\NanaZip.Modern.vcxproj\"\n        );\n\n        var excludedFiles = files\n            .Select(x => x.File)\n            .Except(\n            project.Items.Where(x => x.ItemType == \"PRIResource\")\n            .Select(x => x.Include));\n        foreach (var file in excludedFiles)\n        {\n            var item = project.AddItem(\"PRIResource\", file);\n        }\n        project.Save();\n\n        var filterProject = ProjectRootElement.Open(\n            $\"{gitRoot}\\\\NanaZip.Modern\\\\NanaZip.Modern.vcxproj.filters\"\n        );\n        foreach (var file in files)\n        {\n            var hasItem = filterProject.Items\n                .Any(x =>\n                x.ItemType == \"PRIResource\" &&\n                x.Include == file.File);\n            if (!hasItem)\n            {\n                var item = filterProject.AddItem(\"PRIResource\", file.File);\n                item.AddMetadata(\"Filter\", $\"{StringsDir}\\\\{file.Lang}\");\n            }\n        }\n\n        foreach (var lang in files.Select(x => x.Lang).Distinct())\n        {\n            var hasItem = filterProject.Items\n                .Any(\n                x =>\n                x.ItemType == \"Filter\" &&\n                x.Include == $\"{StringsDir}\\\\{lang}\");\n            if (!hasItem)\n            {\n                var item = filterProject.AddItem(\n                    \"Filter\",\n                    $\"{StringsDir}\\\\{lang}\");\n                item.AddMetadata(\"UniqueIdentifier\",\n                    Guid.NewGuid().ToString(\"B\"));\n            }\n        }\n        filterProject.Save();\n\n        Console.WriteLine(\"Finished migrating resources.\");\n        return 0;\n    }\n}\n"
  },
  {
    "path": "NanaZip.MigrateLegacyStringResources/VSWhereHelper.cs",
    "content": "﻿using System.Diagnostics;\n\nnamespace NanaZip.MigrateLegacyStringResources;\n\npublic static class VSWhereHelper\n{\n    public static string? GetVSPath()\n    {\n        Process process = new()\n        {\n            StartInfo = new ProcessStartInfo()\n            {\n                UseShellExecute = false,\n                CreateNoWindow = true,\n                RedirectStandardOutput = true,\n                FileName = \"vswhere.exe\",\n                Arguments = \"-prerelease -latest -property resolvedInstallationPath\"\n            }\n        };\n\n        if (!process.Start())\n        {\n            return null;\n        }\n\n        process.WaitForExit();\n\n        if (process.ExitCode != 0)\n        {\n            return null;\n        }\n\n        return process.StandardOutput.ReadLine();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/AboutPage.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"AboutPage.h\"\n#if __has_include(\"AboutPage.g.cpp\")\n#include \"AboutPage.g.cpp\"\n#endif\n\n#include \"NanaZip.Modern.h\"\n\n#include <winrt/Windows.UI.Xaml.Documents.h>\n\n#include <Mile.Project.Version.h>\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    AboutPage::AboutPage(\n        _In_opt_ HWND WindowHandle,\n        _In_opt_ LPCWSTR ExtendedMessage) :\n        m_WindowHandle(WindowHandle),\n        m_ExtendedMessage(ExtendedMessage)\n    {\n\n    }\n\n    void AboutPage::InitializeComponent()\n    {\n        AboutPageT::InitializeComponent();\n\n        winrt::hstring WindowTitle = winrt::hstring(\n            ::K7ModernGetLegacyStringResource(2900));\n        if (WindowTitle.empty())\n        {\n            WindowTitle = L\"About NanaZip\";\n        }\n        ::SetWindowTextW(this->m_WindowHandle, WindowTitle.c_str());\n\n        std::wstring Version = std::wstring(\n            \"NanaZip \" MILE_PROJECT_VERSION_STRING);\n        Version.append(\n            L\" (\" MILE_PROJECT_DOT_VERSION_STRING L\")\");\n#if defined(_M_AMD64)\n        Version.append(L\" (x64)\");\n#elif defined(_M_ARM64)\n        Version.append(L\" (arm64)\");\n#endif\n\n        std::wstring Content = std::wstring(\n            ::K7ModernGetLegacyStringResource(2901));\n        if (Content.empty())\n        {\n            Content = L\"NanaZip is free software\";\n        }\n        if (!this->m_ExtendedMessage.empty())\n        {\n            Content.append(L\"\\r\\n\\r\\n\");\n            Content.append(this->m_ExtendedMessage);\n        }\n\n        this->GridTitleTextBlock().Text(WindowTitle);\n        this->Version().Text(Version);\n        this->Content().Text(Content);\n    }\n\n    void AboutPage::NanaZipWebsiteButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        SHELLEXECUTEINFOW ExecInfo = {};\n        ExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);\n        ExecInfo.lpVerb = L\"open\";\n        ExecInfo.lpFile = L\"https://nanazip.org\";\n        ExecInfo.nShow = SW_SHOWNORMAL;\n        ::ShellExecuteExW(&ExecInfo);\n    }\n\n    void AboutPage::GitHubButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        SHELLEXECUTEINFOW ExecInfo = {};\n        ExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);\n        ExecInfo.lpVerb = L\"open\";\n        ExecInfo.lpFile = L\"https://github.com/M2Team/NanaZip\";\n        ExecInfo.nShow = SW_SHOWNORMAL;\n        ::ShellExecuteExW(&ExecInfo);\n    }\n\n    void AboutPage::CancelButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(this->m_WindowHandle, WM_CLOSE, 0, 0);\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/AboutPage.h",
    "content": "﻿#pragma once\n\n#include \"AboutPage.g.h\"\n\n#include <Windows.h>\n\nnamespace winrt\n{\n    using Windows::Foundation::IInspectable;\n    using Windows::UI::Xaml::RoutedEventArgs;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct AboutPage : AboutPageT<AboutPage>\n    {\n    public:\n\n        AboutPage(\n            _In_opt_ HWND WindowHandle = nullptr,\n            _In_opt_ LPCWSTR ExtendedMessage = nullptr);\n\n        void InitializeComponent();\n\n        void NanaZipWebsiteButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void GitHubButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void CancelButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n    private:\n\n        HWND m_WindowHandle;\n        std::wstring m_ExtendedMessage;\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/AboutPage.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass AboutPage : Windows.UI.Xaml.Controls.Page\n    {\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/AboutPage.xaml",
    "content": "﻿<Page\n  x:Class=\"NanaZip.Modern.AboutPage\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n  xmlns:local=\"using:NanaZip.Modern\"\n  xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n  IsTextScaleFactorEnabled=\"False\"\n  mc:Ignorable=\"d\">\n  <Grid>\n    <Grid.RowDefinitions>\n      <RowDefinition Height=\"*\" />\n      <RowDefinition Height=\"Auto\" />\n    </Grid.RowDefinitions>\n    <StackPanel Grid.Row=\"0\" Padding=\"24,0\">\n      <TextBlock\n        x:Name=\"GridTitleTextBlock\"\n        Margin=\"0,0,0,12\"\n        FontSize=\"24\"\n        FontWeight=\"SemiBold\"\n        Text=\"[About NanaZip]\" />\n      <TextBlock>\n        <Run x:Name=\"Version\" />\n        <LineBreak />\n        <Run Text=\"© M2-Team and Contributors. All rights reserved.\" />\n        <LineBreak />\n        <LineBreak />\n        <Run x:Name=\"Content\" />\n      </TextBlock>\n    </StackPanel>\n    <Grid Grid.Row=\"1\" Padding=\"24\">\n      <Grid.Background>\n        <SolidColorBrush Opacity=\"0.2\" Color=\"{ThemeResource SystemChromeHighColor}\" />\n      </Grid.Background>\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"*\" />\n        <ColumnDefinition Width=\"8\" />\n        <ColumnDefinition Width=\"*\" />\n        <ColumnDefinition Width=\"8\" />\n        <ColumnDefinition Width=\"*\" />\n      </Grid.ColumnDefinitions>\n      <Button\n        Grid.Column=\"0\"\n        HorizontalAlignment=\"Stretch\"\n        Click=\"NanaZipWebsiteButtonClick\"\n        Content=\"NanaZip.org\" />\n      <Button\n        Grid.Column=\"2\"\n        HorizontalAlignment=\"Stretch\"\n        Click=\"GitHubButtonClick\"\n        Content=\"GitHub\" />\n      <Button\n        x:Uid=\"/NanaZip.Modern/Common/CancelButton\"\n        Grid.Column=\"4\"\n        HorizontalAlignment=\"Stretch\"\n        Click=\"CancelButtonClick\"\n        Content=\"[Cancel]\" />\n    </Grid>\n  </Grid>\n</Page>\n"
  },
  {
    "path": "NanaZip.Modern/AddressBar.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"AddressBar.h\"\n#include \"AddressBar.g.cpp\"\n#include \"AddressBarItem.g.cpp\"\n#include \"AddressBarQuerySubmittedEventArgs.g.cpp\"\n\n#include <winrt/Windows.System.h>\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    void AddressBar::OnApplyTemplate()\n    {\n        m_textBoxElement =\n            GetTemplateChild(L\"TextBoxElement\")\n            .as<winrt::TextBox>();\n\n        // Workaround for https://github.com/microsoft/microsoft-ui-xaml/issues/5341\n        winrt::TextCommandBarFlyout textFlyout;\n        textFlyout.Placement(\n            winrt::FlyoutPlacementMode::BottomEdgeAlignedLeft);\n        m_textBoxElement.ContextFlyout(textFlyout);\n        m_textBoxElement.SelectionFlyout(textFlyout);\n\n        m_textBoxElement.GotFocus(\n            []\n            (winrt::IInspectable const& sender, auto&&)\n            {\n                winrt::TextBox textBox =\n                    sender.as<winrt::TextBox>();\n                textBox.SelectAll();\n            });\n\n        m_textBoxElement.PreviewKeyDown({ get_weak(), &AddressBar::OnTextBoxPreviewKeyDown });\n\n        m_popup =\n            GetTemplateChild(L\"SuggestionsPopup\")\n            .as<winrt::Popup>();\n\n        m_popup.Closed(\n            [weak_this{ get_weak() }]\n            (auto&&, auto&&)\n            {\n                if (auto strong_this{ weak_this.get() })\n                {\n                    if (!strong_this->m_textBoxElement)\n                        return;\n                    auto tbCorner = strong_this->m_textBoxElement.CornerRadius();\n                    tbCorner.BottomLeft = tbCorner.TopLeft;\n                    tbCorner.BottomRight = tbCorner.TopRight;\n                    strong_this->m_textBoxElement.CornerRadius(tbCorner);\n                }\n            });\n\n        m_suggestionsList =\n            GetTemplateChild(L\"SuggestionsList\")\n            .as<winrt::ListView>();\n\n        m_suggestionsList.ItemClick(\n            [weak_this{ get_weak() }]\n            (auto&&, winrt::ItemClickEventArgs const& args)\n            {\n                if (auto strong_this{ weak_this.get() })\n                {\n                    strong_this->m_popup.IsOpen(false);\n                    auto submitArgs = winrt::make<AddressBarQuerySubmittedEventArgs>(\n                        L\"\",\n                        args.ClickedItem()\n                    );\n                    strong_this->QuerySubmitted(\n                        *strong_this,\n                        submitArgs\n                    );\n                }\n            }\n        );\n\n        winrt::Button m_dropDownButton =\n            GetTemplateChild(L\"DropDownButton\")\n            .as<winrt::Button>();\n\n        m_dropDownButton.Click(\n            [weak_this{ get_weak() }]\n            (\n                auto&&, auto&&\n                )\n            {\n                if (auto strong_this{ weak_this.get() })\n                {\n                    winrt::IVectorView<winrt::IInspectable> source =\n                        strong_this->ItemsSource()\n                        .as<winrt::IVectorView<winrt::IInspectable>>();\n                    strong_this->OpenSuggestionsPopup(false);\n                }\n            });\n\n        this->m_upButtonElement =\n            GetTemplateChild(L\"UpButton\")\n            .as<winrt::Button>();\n\n        this->m_upButtonElement.Click(\n            [weak_this{ get_weak() }]\n            (\n                auto&&,\n                winrt::RoutedEventArgs const&\n                args\n                )\n            {\n                if (auto strong_this{ weak_this.get() })\n                {\n                    strong_this->UpButtonClicked(*strong_this, args);\n                }\n            });\n\n        __super::OnApplyTemplate();\n    }\n\n    void AddressBar::OnTextBoxPreviewKeyDown(\n        winrt::IInspectable const&,\n        winrt::KeyRoutedEventArgs const& args)\n    {\n        switch (args.Key())\n        {\n        case winrt::VirtualKey::Enter:\n        {\n            if (m_popup &&\n                m_suggestionsList &&\n                m_popup.IsOpen() &&\n                m_suggestionsList.SelectionMode()\n                != winrt::ListViewSelectionMode::None)\n            {\n                auto selectedItem = m_suggestionsList.SelectedItem();\n                auto submitArgs = winrt::make<AddressBarQuerySubmittedEventArgs>(L\"\", selectedItem);\n                // The suggestions dropdown is opened via keyboard.\n                QuerySubmitted(*this, submitArgs);\n            }\n            else\n            {\n                auto submitArgs = winrt::make<AddressBarQuerySubmittedEventArgs>(Text(), nullptr);\n                QuerySubmitted(*this, submitArgs);\n            }\n            args.Handled(true);\n            break;\n        }\n        case winrt::VirtualKey::Down:\n        {\n            if (!m_popup || !m_suggestionsList)\n                break;\n\n            winrt::IVectorView<winrt::IInspectable> source =\n                ItemsSource().as<winrt::IVectorView<winrt::IInspectable>>();\n\n            if (!m_popup.IsOpen())\n            {\n                if (!OpenSuggestionsPopup(true))\n                    break;\n                m_suggestionsList.SelectedIndex(0);\n                args.Handled(true);\n                break;\n            }\n\n            int currentIndex = m_suggestionsList.SelectedIndex();\n            if (currentIndex < (int)source.Size() - 1)\n            {\n                m_suggestionsList.SelectedIndex(currentIndex + 1);\n            }\n\n            args.Handled(true);\n\n            break;\n        }\n        case winrt::VirtualKey::Up:\n        {\n            if (!m_popup || !m_suggestionsList || !m_popup.IsOpen())\n                break;\n\n            int currentIndex = m_suggestionsList.SelectedIndex();\n            if (currentIndex == 0)\n                m_popup.IsOpen(false);\n            else\n                m_suggestionsList.SelectedIndex(currentIndex - 1);\n\n            args.Handled(true);\n            break;\n        }\n        }\n        __super::OnKeyUp(args);\n    }\n\n    DEPENDENCY_PROPERTY_SOURCE_BOX(\n        Text,\n        winrt::hstring,\n        AddressBar,\n        winrt::NanaZip::Modern::AddressBar\n    );\n\n    DEPENDENCY_PROPERTY_SOURCE_NOBOX(\n        IconSource,\n        winrt::ImageSource,\n        AddressBar,\n        winrt::NanaZip::Modern::AddressBar\n    );\n\n    DEPENDENCY_PROPERTY_SOURCE_NOBOX(\n        ItemsSource,\n        winrt::IInspectable,\n        AddressBar,\n        winrt::NanaZip::Modern::AddressBar\n    );\n\n    DEPENDENCY_PROPERTY_SOURCE_BOX_WITHDEFAULT(\n        IsUpButtonEnabled,\n        bool,\n        AddressBar,\n        winrt::NanaZip::Modern::AddressBar,\n        true\n    );\n\n    bool AddressBar::OpenSuggestionsPopup(\n        bool isKeyboard\n    )\n    {\n        if (!m_popup || !m_textBoxElement || !m_suggestionsList)\n            return false;\n\n        DropDownOpened(*this, nullptr);\n\n        winrt::IVectorView<winrt::IInspectable> source =\n            ItemsSource().as<winrt::IVectorView<winrt::IInspectable>>();\n        if (source.Size() == 0)\n            return false;\n\n        if (!isKeyboard)\n        {\n            m_suggestionsList.SelectionMode(\n                winrt::ListViewSelectionMode::None\n            );\n        }\n        else {\n            m_suggestionsList.SelectionMode(\n                winrt::ListViewSelectionMode::Single\n            );\n        }\n\n        m_suggestionsList.Width(m_textBoxElement.ActualWidth());\n        m_popup.VerticalOffset(m_textBoxElement.ActualHeight());\n\n        auto tbCorner = m_textBoxElement.CornerRadius();\n        tbCorner.BottomLeft = tbCorner.BottomRight = 0;\n        m_textBoxElement.CornerRadius(tbCorner);\n\n        auto slCorner = m_suggestionsList.CornerRadius();\n        slCorner.TopLeft = slCorner.TopRight = 0;\n        m_suggestionsList.CornerRadius(slCorner);\n\n        m_popup.IsOpen(true);\n        m_textBoxElement.Focus(winrt::FocusState::Programmatic);\n\n        return true;\n    }\n\n    AddressBarQuerySubmittedEventArgs::\n        AddressBarQuerySubmittedEventArgs(\n            winrt::hstring const& queryText,\n            winrt::IInspectable const& suggestionChosen\n        )\n    {\n        m_queryText = queryText;\n        m_chosenSuggestion = suggestionChosen;\n    }\n\n    winrt::hstring\n        AddressBarQuerySubmittedEventArgs::\n        QueryText()\n    {\n        return m_queryText;\n    }\n\n    winrt::IInspectable\n        AddressBarQuerySubmittedEventArgs::\n        ChosenSuggestion()\n    {\n        return m_chosenSuggestion;\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/AddressBar.h",
    "content": "﻿#pragma once\n\n#include \"AddressBar.g.h\"\n#include \"AddressBarQuerySubmittedEventArgs.g.h\"\n#include \"AddressBarItem.g.h\"\n\n#include <winrt/Windows.UI.Xaml.Media.h>\n#include <winrt/Windows.UI.Xaml.Input.h>\n\n#include <Mile.Helpers.CppWinRT.h>\n#include \"ControlMacros.h\"\n\nnamespace winrt\n{\n    using namespace Windows::Foundation;\n    using namespace Windows::Foundation::Collections;\n    using namespace Windows::UI::Xaml;\n    using namespace Windows::UI::Xaml::Controls;\n    using namespace Windows::UI::Xaml::Controls::Primitives;\n    using namespace Windows::UI::Xaml::Input;\n    using namespace Windows::UI::Xaml::Media;\n    using namespace Windows::System;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct AddressBar : AddressBarT<AddressBar>\n    {\n        AddressBar() = default;\n\n        void OnApplyTemplate();\n        void OnTextBoxPreviewKeyDown(\n            winrt::IInspectable const&,\n            winrt::KeyRoutedEventArgs const&);\n\n        DEPENDENCY_PROPERTY_HEADER(Text, winrt::hstring);\n        DEPENDENCY_PROPERTY_HEADER(\n            IconSource,\n            winrt::ImageSource\n        );\n        DEPENDENCY_PROPERTY_HEADER(\n            ItemsSource,\n            winrt::IInspectable\n        );\n        DEPENDENCY_PROPERTY_HEADER(\n            IsUpButtonEnabled,\n            bool\n        );\n\n        Mile::WinRT::Event<\n            winrt::TypedEventHandler<\n            winrt::NanaZip::Modern::AddressBar,\n            winrt::NanaZip::Modern::AddressBarQuerySubmittedEventArgs>>\n            QuerySubmitted;\n\n        Mile::WinRT::Event<winrt::Windows::UI::Xaml::RoutedEventHandler>\n            UpButtonClicked;\n\n        Mile::WinRT::Event<\n            winrt::TypedEventHandler<\n            winrt::NanaZip::Modern::AddressBar,\n            winrt::IInspectable>>\n            DropDownOpened;\n\n    private:\n        bool OpenSuggestionsPopup(bool isKeyboard);\n\n        winrt::TextBox m_textBoxElement{ nullptr };\n        winrt::Popup\n            m_popup{ nullptr };\n        winrt::Button m_upButtonElement{ nullptr };\n        winrt::ListView m_suggestionsList{ nullptr };\n    };\n\n    struct AddressBarItem : AddressBarItemT<AddressBarItem>\n    {\n        AddressBarItem() = default;\n\n        Mile::WinRT::Property<winrt::hstring> Text;\n        Mile::WinRT::Property<winrt::ImageSource> Icon =\n            Mile::WinRT::Property<winrt::ImageSource>(nullptr);\n        Mile::WinRT::Property<winrt::Thickness> Padding;\n    };\n\n    struct AddressBarQuerySubmittedEventArgs :\n        AddressBarQuerySubmittedEventArgsT<\n        AddressBarQuerySubmittedEventArgs>\n    {\n        AddressBarQuerySubmittedEventArgs(\n            winrt::hstring const&,\n            winrt::Windows::Foundation::IInspectable const&);\n\n        winrt::hstring QueryText();\n        winrt::Windows::Foundation::IInspectable ChosenSuggestion();\n\n    private:\n        winrt::hstring m_queryText;\n        winrt::Windows::Foundation::IInspectable m_chosenSuggestion{ nullptr };\n    };\n}\n\nnamespace winrt::NanaZip::Modern::factory_implementation\n{\n    struct AddressBar : AddressBarT<AddressBar, implementation::AddressBar>\n    { };\n\n    struct AddressBarItem : AddressBarItemT<AddressBarItem, implementation::AddressBarItem>\n    { };\n}\n"
  },
  {
    "path": "NanaZip.Modern/AddressBar.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    runtimeclass AddressBar : Windows.UI.Xaml.Controls.Control\n    {\n        AddressBar();\n\n        Windows.UI.Xaml.Media.ImageSource IconSource;\n        static Windows.UI.Xaml.DependencyProperty IconSourceProperty{ get; };\n\n        String Text;\n        static Windows.UI.Xaml.DependencyProperty TextProperty{ get; };\n\n        Boolean IsUpButtonEnabled;\n        static Windows.UI.Xaml.DependencyProperty IsUpButtonEnabledProperty{ get; };\n\n        Object ItemsSource;\n        static Windows.UI.Xaml.DependencyProperty ItemsSourceProperty{ get; };\n\n        event Windows.Foundation.TypedEventHandler<AddressBar, AddressBarQuerySubmittedEventArgs> QuerySubmitted;\n        event Windows.UI.Xaml.RoutedEventHandler UpButtonClicked;\n        event Windows.Foundation.TypedEventHandler<AddressBar, Object> DropDownOpened;\n    }\n\n    runtimeclass AddressBarQuerySubmittedEventArgs : Windows.UI.Xaml.DependencyObject\n    {\n        Object ChosenSuggestion{ get; };\n        String QueryText{ get; };\n    }\n\n    runtimeclass AddressBarItem\n    {\n        AddressBarItem();\n\n        String Text;\n        Windows.UI.Xaml.Media.ImageSource Icon;\n        Windows.UI.Xaml.Thickness Padding;\n    }\n\n    [default_interface]\n    runtimeclass AddressBarTemplate : Windows.UI.Xaml.ResourceDictionary\n    {\n        AddressBarTemplate();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/AddressBarTemplate.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"AddressBarTemplate.h\"\n#include \"AddressBarTemplate.g.cpp\"\n"
  },
  {
    "path": "NanaZip.Modern/AddressBarTemplate.h",
    "content": "﻿#pragma once\n\n#include \"AddressBarTemplate.g.h\"\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct AddressBarTemplate : AddressBarTemplateT<AddressBarTemplate>\n    {\n        AddressBarTemplate()\n        {\n\n        }\n    };\n}\n\nnamespace winrt::NanaZip::Modern::factory_implementation\n{\n    struct AddressBarTemplate : AddressBarTemplateT<\n        AddressBarTemplate,\n        implementation::AddressBarTemplate>\n    {\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/AddressBarTemplate.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass AddressBarTemplate : Windows.UI.Xaml.ResourceDictionary\n    {\n        AddressBarTemplate();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/AddressBarTemplate.xaml",
    "content": "﻿<ResourceDictionary\n  x:Class=\"NanaZip.Modern.AddressBarTemplate\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:local=\"using:NanaZip.Modern\">\n\n  <Thickness x:Key=\"AddressBarImageIconMargin\">8,2,0,6</Thickness>\n\n  <DataTemplate x:Key=\"DefaultAddressBarItemTemplate\" x:DataType=\"local:AddressBarItem\">\n    <StackPanel\n      Margin=\"{x:Bind Padding}\"\n      Orientation=\"Horizontal\"\n      Spacing=\"4\">\n      <Image\n        Width=\"16\"\n        Height=\"16\"\n        VerticalAlignment=\"Center\"\n        Source=\"{x:Bind Icon}\" />\n      <TextBlock VerticalAlignment=\"Center\" Text=\"{x:Bind Text}\" />\n    </StackPanel>\n  </DataTemplate>\n\n  <Style x:Key=\"DefaultAddressBarTextBoxStyle\" TargetType=\"TextBox\">\n    <Setter Property=\"SelectionHighlightColor\" Value=\"{ThemeResource TextControlSelectionHighlightColor}\" />\n    <Setter Property=\"ContextFlyout\" Value=\"{StaticResource TextControlCommandBarContextFlyout}\" />\n    <Setter Property=\"Foreground\" Value=\"{ThemeResource TextControlForeground}\" />\n    <Setter Property=\"Background\" Value=\"{ThemeResource TextControlBackground}\" />\n    <Setter Property=\"BorderBrush\" Value=\"{ThemeResource ControlStrokeColorDefaultBrush}\" />\n    <Setter Property=\"BorderThickness\" Value=\"{ThemeResource TextControlBorderThemeThickness}\" />\n    <Setter Property=\"FontFamily\" Value=\"{ThemeResource ContentControlThemeFontFamily}\" />\n    <Setter Property=\"FontSize\" Value=\"{ThemeResource ControlContentThemeFontSize}\" />\n    <Setter Property=\"ScrollViewer.HorizontalScrollMode\" Value=\"Auto\" />\n    <Setter Property=\"ScrollViewer.VerticalScrollMode\" Value=\"Auto\" />\n    <Setter Property=\"ScrollViewer.HorizontalScrollBarVisibility\" Value=\"Hidden\" />\n    <Setter Property=\"ScrollViewer.VerticalScrollBarVisibility\" Value=\"Hidden\" />\n    <Setter Property=\"ScrollViewer.IsDeferredScrollingEnabled\" Value=\"False\" />\n    <Setter Property=\"MinHeight\" Value=\"{ThemeResource TextControlThemeMinHeight}\" />\n    <Setter Property=\"MinWidth\" Value=\"{ThemeResource TextControlThemeMinWidth}\" />\n    <Setter Property=\"Padding\" Value=\"{ThemeResource TextControlThemePadding}\" />\n    <Setter Property=\"UseSystemFocusVisuals\" Value=\"{ThemeResource IsApplicationFocusVisualKindReveal}\" />\n    <Setter Property=\"ContextFlyout\" Value=\"{StaticResource TextControlCommandBarContextFlyout}\" />\n    <Setter Property=\"CornerRadius\" Value=\"{ThemeResource ControlCornerRadius}\" />\n    <Setter Property=\"BackgroundSizing\" Value=\"InnerBorderEdge\" />\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"TextBox\">\n          <Grid>\n            <Grid.RowDefinitions>\n              <RowDefinition Height=\"Auto\" />\n              <RowDefinition Height=\"*\" />\n              <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n              <ColumnDefinition Width=\"24\" />\n              <ColumnDefinition Width=\"*\" />\n              <ColumnDefinition Width=\"30\" />\n            </Grid.ColumnDefinitions>\n            <ContentPresenter\n              x:Name=\"HeaderContentPresenter\"\n              Grid.Row=\"0\"\n              Grid.Column=\"0\"\n              Grid.ColumnSpan=\"2\"\n              Margin=\"{ThemeResource TextBoxTopHeaderMargin}\"\n              VerticalAlignment=\"Top\"\n              x:DeferLoadStrategy=\"Lazy\"\n              Content=\"{TemplateBinding Header}\"\n              ContentTemplate=\"{TemplateBinding HeaderTemplate}\"\n              FontWeight=\"Normal\"\n              Foreground=\"{ThemeResource TextControlHeaderForeground}\"\n              TextWrapping=\"Wrap\"\n              Visibility=\"Collapsed\" />\n            <Border\n              x:Name=\"BorderElement\"\n              Grid.Row=\"1\"\n              Grid.RowSpan=\"1\"\n              Grid.Column=\"0\"\n              Grid.ColumnSpan=\"3\"\n              MinWidth=\"{TemplateBinding MinWidth}\"\n              MinHeight=\"{TemplateBinding MinHeight}\"\n              Background=\"{TemplateBinding Background}\"\n              BorderBrush=\"{TemplateBinding BorderBrush}\"\n              BorderThickness=\"{TemplateBinding BorderThickness}\"\n              Control.IsTemplateFocusTarget=\"True\"\n              CornerRadius=\"{TemplateBinding CornerRadius}\" />\n            <ScrollViewer\n              x:Name=\"ContentElement\"\n              Grid.Row=\"1\"\n              Grid.Column=\"1\"\n              Margin=\"{TemplateBinding BorderThickness}\"\n              Padding=\"{TemplateBinding Padding}\"\n              AutomationProperties.AccessibilityView=\"Raw\"\n              Foreground=\"{TemplateBinding Foreground}\"\n              HorizontalScrollBarVisibility=\"{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}\"\n              HorizontalScrollMode=\"{TemplateBinding ScrollViewer.HorizontalScrollMode}\"\n              IsDeferredScrollingEnabled=\"{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}\"\n              IsHorizontalRailEnabled=\"{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}\"\n              IsTabStop=\"False\"\n              IsVerticalRailEnabled=\"{TemplateBinding ScrollViewer.IsVerticalRailEnabled}\"\n              VerticalScrollBarVisibility=\"{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}\"\n              VerticalScrollMode=\"{TemplateBinding ScrollViewer.VerticalScrollMode}\"\n              ZoomMode=\"Disabled\" />\n            <TextBlock\n              x:Name=\"PlaceholderTextContentPresenter\"\n              Grid.Row=\"1\"\n              Grid.Column=\"1\"\n              Grid.ColumnSpan=\"2\"\n              Margin=\"{TemplateBinding BorderThickness}\"\n              Padding=\"{TemplateBinding Padding}\"\n              Foreground=\"{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForeground}}\"\n              IsHitTestVisible=\"False\"\n              Text=\"{TemplateBinding PlaceholderText}\"\n              TextAlignment=\"{TemplateBinding TextAlignment}\"\n              TextWrapping=\"{TemplateBinding TextWrapping}\" />\n            <ContentPresenter\n              x:Name=\"DescriptionPresenter\"\n              Grid.Row=\"2\"\n              Grid.Column=\"0\"\n              Grid.ColumnSpan=\"3\"\n              x:Load=\"False\"\n              AutomationProperties.AccessibilityView=\"Raw\"\n              Content=\"{TemplateBinding Description}\"\n              Foreground=\"{ThemeResource SystemControlDescriptionTextForegroundBrush}\" />\n            <VisualStateManager.VisualStateGroups>\n              <VisualStateGroup x:Name=\"CommonStates\">\n                <VisualState x:Name=\"Normal\" />\n                <VisualState x:Name=\"Disabled\">\n                  <Storyboard>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"HeaderContentPresenter\" Storyboard.TargetProperty=\"Foreground\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlHeaderForegroundDisabled}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"BorderElement\" Storyboard.TargetProperty=\"Background\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlBackgroundDisabled}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"BorderElement\" Storyboard.TargetProperty=\"BorderBrush\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlBorderBrushDisabled}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentElement\" Storyboard.TargetProperty=\"Foreground\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlForegroundDisabled}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"PlaceholderTextContentPresenter\" Storyboard.TargetProperty=\"Foreground\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundDisabled}}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                  </Storyboard>\n                </VisualState>\n                <VisualState x:Name=\"PointerOver\">\n                  <Storyboard>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"BorderElement\" Storyboard.TargetProperty=\"BorderBrush\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource ControlStrokeColorDefaultBrush}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"BorderElement\" Storyboard.TargetProperty=\"Background\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlBackgroundPointerOver}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"PlaceholderTextContentPresenter\" Storyboard.TargetProperty=\"Foreground\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundPointerOver}}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentElement\" Storyboard.TargetProperty=\"Foreground\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlForegroundPointerOver}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                  </Storyboard>\n                </VisualState>\n                <VisualState x:Name=\"Focused\">\n                  <Storyboard>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"PlaceholderTextContentPresenter\" Storyboard.TargetProperty=\"Foreground\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{Binding PlaceholderForeground, RelativeSource={RelativeSource TemplatedParent}, TargetNullValue={ThemeResource TextControlPlaceholderForegroundFocused}}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"BorderElement\" Storyboard.TargetProperty=\"Background\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlBackgroundFocused}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"BorderElement\" Storyboard.TargetProperty=\"BorderBrush\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlBorderBrushFocused}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"BorderElement\" Storyboard.TargetProperty=\"BorderThickness\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlBorderThemeThicknessFocused}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ContentElement\" Storyboard.TargetProperty=\"Foreground\">\n                      <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlForegroundFocused}\" />\n                    </ObjectAnimationUsingKeyFrames>\n                  </Storyboard>\n                </VisualState>\n              </VisualStateGroup>\n            </VisualStateManager.VisualStateGroups>\n          </Grid>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n\n  <Style x:Key=\"DefaultAddressBarStyle\" TargetType=\"local:AddressBar\">\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"local:AddressBar\">\n          <Grid Margin=\"4,0\">\n            <Grid.Resources>\n              <Style x:Name=\"DropDownButtonStyle\" TargetType=\"Button\">\n                <Setter Property=\"Template\">\n                  <Setter.Value>\n                    <ControlTemplate TargetType=\"Button\">\n                      <Grid\n                        x:Name=\"ButtonLayoutGrid\"\n                        Margin=\"2,4,4,8\"\n                        Background=\"{ThemeResource TextControlButtonBackground}\"\n                        BackgroundSizing=\"{TemplateBinding BackgroundSizing}\"\n                        BorderBrush=\"{ThemeResource TextControlButtonBorderBrush}\"\n                        BorderThickness=\"{TemplateBinding BorderThickness}\"\n                        CornerRadius=\"{ThemeResource ControlCornerRadius}\">\n                        <TextBlock\n                          x:Name=\"GlyphElement\"\n                          HorizontalAlignment=\"Center\"\n                          VerticalAlignment=\"Center\"\n                          AutomationProperties.AccessibilityView=\"Raw\"\n                          FontFamily=\"{ThemeResource SymbolThemeFontFamily}\"\n                          FontSize=\"{ThemeResource TextBoxIconFontSize}\"\n                          FontStyle=\"Normal\"\n                          Foreground=\"{ThemeResource TextControlButtonForeground}\"\n                          Text=\"&#xE70D;\" />\n                        <VisualStateManager.VisualStateGroups>\n                          <VisualStateGroup x:Name=\"CommonStates\">\n                            <VisualState x:Name=\"Normal\" />\n                            <VisualState x:Name=\"PointerOver\">\n                              <Storyboard>\n                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ButtonLayoutGrid\" Storyboard.TargetProperty=\"Background\">\n                                  <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlButtonBackgroundPointerOver}\" />\n                                </ObjectAnimationUsingKeyFrames>\n                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ButtonLayoutGrid\" Storyboard.TargetProperty=\"BorderBrush\">\n                                  <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlButtonBorderBrushPointerOver}\" />\n                                </ObjectAnimationUsingKeyFrames>\n                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"GlyphElement\" Storyboard.TargetProperty=\"Foreground\">\n                                  <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlButtonForegroundPointerOver}\" />\n                                </ObjectAnimationUsingKeyFrames>\n                              </Storyboard>\n                            </VisualState>\n                            <VisualState x:Name=\"Pressed\">\n                              <Storyboard>\n                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ButtonLayoutGrid\" Storyboard.TargetProperty=\"Background\">\n                                  <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlButtonBackgroundPressed}\" />\n                                </ObjectAnimationUsingKeyFrames>\n                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"ButtonLayoutGrid\" Storyboard.TargetProperty=\"BorderBrush\">\n                                  <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlButtonBorderBrushPressed}\" />\n                                </ObjectAnimationUsingKeyFrames>\n                                <ObjectAnimationUsingKeyFrames Storyboard.TargetName=\"GlyphElement\" Storyboard.TargetProperty=\"Foreground\">\n                                  <DiscreteObjectKeyFrame KeyTime=\"0\" Value=\"{ThemeResource TextControlButtonForegroundPressed}\" />\n                                </ObjectAnimationUsingKeyFrames>\n                              </Storyboard>\n                            </VisualState>\n                            <VisualState x:Name=\"Disabled\">\n                              <Storyboard>\n                                <DoubleAnimation\n                                  Storyboard.TargetName=\"ButtonLayoutGrid\"\n                                  Storyboard.TargetProperty=\"Opacity\"\n                                  To=\"0\"\n                                  Duration=\"0\" />\n                              </Storyboard>\n                            </VisualState>\n                          </VisualStateGroup>\n                        </VisualStateManager.VisualStateGroups>\n                      </Grid>\n                    </ControlTemplate>\n                  </Setter.Value>\n                </Setter>\n              </Style>\n            </Grid.Resources>\n            <Grid.ColumnDefinitions>\n              <ColumnDefinition Width=\"Auto\" />\n              <ColumnDefinition Width=\"24\" />\n              <ColumnDefinition Width=\"*\" />\n              <ColumnDefinition Width=\"30\" />\n            </Grid.ColumnDefinitions>\n            <Button\n              x:Name=\"UpButton\"\n              Width=\"48\"\n              Height=\"32\"\n              Margin=\"0,0,4,0\"\n              Padding=\"0\"\n              VerticalAlignment=\"Top\"\n              Content=\"&#xE74A;\"\n              FontFamily=\"{StaticResource SymbolThemeFontFamily}\"\n              FontSize=\"12\"\n              IsEnabled=\"{TemplateBinding IsUpButtonEnabled}\" />\n            <RelativePanel Grid.Column=\"1\" Grid.ColumnSpan=\"3\">\n              <TextBox\n                x:Name=\"TextBoxElement\"\n                RelativePanel.AlignLeftWithPanel=\"True\"\n                RelativePanel.AlignRightWithPanel=\"True\"\n                Style=\"{StaticResource DefaultAddressBarTextBoxStyle}\"\n                Text=\"{x:Bind Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\" />\n              <Popup\n                x:Name=\"SuggestionsPopup\"\n                AllowFocusOnInteraction=\"False\"\n                IsLightDismissEnabled=\"True\"\n                ShouldConstrainToRootBounds=\"False\">\n                <Popup.ChildTransitions>\n                  <PopupThemeTransition />\n                </Popup.ChildTransitions>\n\n                <!--\n                  MaxHeight set here to prevent the suggestions\n                  from overflowing the screen. 400 is ~10 elements.\n                -->\n                <ListView\n                  x:Name=\"SuggestionsList\"\n                  MaxHeight=\"400\"\n                  Background=\"{ThemeResource FlyoutPresenterBackground}\"\n                  BorderBrush=\"{ThemeResource FlyoutBorderThemeBrush}\"\n                  BorderThickness=\"{StaticResource FlyoutBorderThemeThickness}\"\n                  CornerRadius=\"{StaticResource OverlayCornerRadius}\"\n                  IsItemClickEnabled=\"True\"\n                  ItemTemplate=\"{StaticResource DefaultAddressBarItemTemplate}\"\n                  ItemsSource=\"{x:Bind ItemsSource, Mode=OneWay}\"\n                  Translation=\"0,0,32\">\n                  <ListView.Shadow>\n                    <ThemeShadow />\n                  </ListView.Shadow>\n                </ListView>\n              </Popup>\n            </RelativePanel>\n            <Image\n              x:Name=\"IconElement\"\n              Grid.Column=\"1\"\n              Width=\"16\"\n              Height=\"16\"\n              Margin=\"{StaticResource AddressBarImageIconMargin}\"\n              Source=\"{x:Bind IconSource, Mode=OneWay}\" />\n            <Button\n              x:Name=\"DropDownButton\"\n              Grid.Column=\"3\"\n              Width=\"30\"\n              Padding=\"{ThemeResource HelperButtonThemePadding}\"\n              VerticalAlignment=\"Stretch\"\n              AutomationProperties.AccessibilityView=\"Raw\"\n              BorderThickness=\"{TemplateBinding BorderThickness}\"\n              CornerRadius=\"{TemplateBinding CornerRadius}\"\n              FontSize=\"{TemplateBinding FontSize}\"\n              IsTabStop=\"False\"\n              Style=\"{StaticResource DropDownButtonStyle}\"\n              Visibility=\"Visible\" />\n          </Grid>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n\n  <Style BasedOn=\"{StaticResource DefaultAddressBarStyle}\" TargetType=\"local:AddressBar\" />\n\n</ResourceDictionary>\n"
  },
  {
    "path": "NanaZip.Modern/App.cpp",
    "content": "﻿#include \"pch.h\"\n\n#include \"App.h\"\n#if __has_include(\"App.g.cpp\")\n#include \"App.g.cpp\"\n#endif\n\n#include <Mile.Xaml.h>\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    App::App()\n    {\n        // Workaround for unhandled exception at twinapi.appcore.dll\n        // Fixes: https://github.com/M2Team/NanaZip/issues/400\n        this->AddRef();\n        winrt::check_hresult(::MileXamlGlobalInitialize());\n    }\n\n    void App::Close()\n    {\n        Exit();\n        ::MileXamlGlobalUninitialize();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/App.h",
    "content": "﻿#pragma once\n\n#include \"App.g.h\"\n\nnamespace winrt\n{\n    using Windows::UI::Xaml::Interop::TypeName;\n    using Windows::UI::Xaml::Markup::IXamlMetadataProvider;\n    using Windows::UI::Xaml::Markup::IXamlType;\n    using Windows::UI::Xaml::Markup::XmlnsDefinition;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    template <typename D, typename ... Interfaces>\n    struct AppT2 : public App_base<D, winrt::IXamlMetadataProvider, Interfaces...>\n    {\n        winrt::IXamlType GetXamlType(\n            winrt::TypeName const& type)\n        {\n            return AppProvider()->GetXamlType(type);\n        }\n\n        winrt::IXamlType GetXamlType(\n            winrt::hstring const& fullName)\n        {\n            return AppProvider()->GetXamlType(fullName);\n        }\n\n        winrt::com_array<winrt::XmlnsDefinition> GetXmlnsDefinitions()\n        {\n            return AppProvider()->GetXmlnsDefinitions();\n        }\n\n    private:\n\n        bool _contentLoaded{ false };\n\n        winrt::com_ptr<XamlMetaDataProvider> _appProvider;\n\n        winrt::com_ptr<XamlMetaDataProvider> AppProvider()\n        {\n            if (!_appProvider)\n            {\n                _appProvider = winrt::make_self<XamlMetaDataProvider>();\n            }\n            return _appProvider;\n        }\n    };\n\n    struct App : AppT2<App>\n    {\n    public:\n        App();\n        void Close();\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/App.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass App :\n        Windows.UI.Xaml.Application,\n        Windows.Foundation.IClosable\n    {\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/App.xaml",
    "content": "﻿<Application\n  x:Class=\"NanaZip.Modern.App\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:local=\"using:NanaZip.Modern\">\n  <Application.Resources>\n    <ResourceDictionary>\n      <ResourceDictionary.MergedDictionaries>\n        <ResourceDictionary Source=\"ms-appx:///Mile.Xaml.Styles.SunValley.xbf\" />\n        <local:AddressBarTemplate />\n        <local:StatusBarTemplate />\n      </ResourceDictionary.MergedDictionaries>\n    </ResourceDictionary>\n  </Application.Resources>\n</Application>\n"
  },
  {
    "path": "NanaZip.Modern/ControlMacros.h",
    "content": "﻿#pragma once\n\n#define DEPENDENCY_PROPERTY_HEADER(name, type) \\\n    type name() const; \\\n    void name(type const&); \\\n    static ::winrt::Windows::UI::Xaml::DependencyProperty \\\n        name##Property();\n\n#define DEPENDENCY_PROPERTY_SOURCE_NOBOX(name, type, implType, projType) \\\n    type implType::name() const \\\n    { \\\n        return GetValue(name##Property()).as<type>(); \\\n    } \\\n    \\\n    void implType::name(type const& name) \\\n    { \\\n        SetValue(name##Property(), name); \\\n    } \\\n    ::winrt::Windows::UI::Xaml::DependencyProperty \\\n        implType::name##Property() \\\n    { \\\n        static ::winrt::Windows::UI::Xaml::DependencyProperty s_##name##Property = \\\n            ::winrt::Windows::UI::Xaml::DependencyProperty::Register( \\\n                L#name, \\\n                ::winrt::xaml_typename<type>(), \\\n                ::winrt::xaml_typename<projType>(), \\\n                nullptr); \\\n        return s_##name##Property; \\\n    }\n\n#define DEPENDENCY_PROPERTY_SOURCE_BOX(name, type, implType, projType) \\\n    type implType::name() const \\\n    { \\\n        return ::winrt::unbox_value<type>(GetValue(name##Property())); \\\n    } \\\n    \\\n    void implType::name(type const& name) \\\n    { \\\n        SetValue(name##Property(), ::winrt::box_value(name)); \\\n    } \\\n    ::winrt::Windows::UI::Xaml::DependencyProperty \\\n        implType::name##Property() \\\n    { \\\n        static ::winrt::Windows::UI::Xaml::DependencyProperty s_##name##Property = \\\n            ::winrt::Windows::UI::Xaml::DependencyProperty::Register( \\\n                L#name, \\\n                ::winrt::xaml_typename<type>(), \\\n                ::winrt::xaml_typename<projType>(), \\\n                nullptr); \\\n        return s_##name##Property; \\\n    }\n\n#define DEPENDENCY_PROPERTY_SOURCE_BOX_WITHDEFAULT(name, type, implType, projType, default) \\\n    type implType::name() const \\\n    { \\\n        return ::winrt::unbox_value<type>(GetValue(name##Property())); \\\n    } \\\n    \\\n    void implType::name(type const& name) \\\n    { \\\n        SetValue(name##Property(), ::winrt::box_value(name)); \\\n    } \\\n    ::winrt::Windows::UI::Xaml::DependencyProperty \\\n        implType::name##Property() \\\n    { \\\n        static ::winrt::Windows::UI::Xaml::DependencyProperty s_##name##Property = \\\n            ::winrt::Windows::UI::Xaml::DependencyProperty::Register( \\\n                L#name, \\\n                ::winrt::xaml_typename<type>(), \\\n                ::winrt::xaml_typename<projType>(), \\\n                ::winrt::Windows::UI::Xaml::PropertyMetadata( \\\n                    ::winrt::box_value((type)default), nullptr \\\n                )); \\\n        return s_##name##Property; \\\n    }\n"
  },
  {
    "path": "NanaZip.Modern/CopyLocationPage.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"CopyLocationPage.h\"\n#include \"CopyLocationPage.g.cpp\"\n\n#include <Mile.Helpers.CppWinRT.h>\n\n#include <shlobj.h>\n\n#include <string>\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    CopyLocationPage::CopyLocationPage(\n        _In_opt_ HWND WindowHandle,\n        _In_opt_ LPCWSTR Title,\n        _In_opt_ LPCWSTR Subtitle,\n        _In_opt_ LPCWSTR AdditionalInformation,\n        _In_opt_ LPCWSTR InitialPath):\n        m_WindowHandle(WindowHandle),\n        m_Title(Title),\n        m_Subtitle(Subtitle),\n        m_AdditionalInformation(AdditionalInformation),\n        m_InitialPath(InitialPath)\n    {\n    }\n\n    void CopyLocationPage::InitializeComponent()\n    {\n        CopyLocationPageT::InitializeComponent();\n\n        this->TitleTextBlock().Text(this->m_Title);\n        this->SubtitleTextBlock().Text(this->m_Subtitle);\n        this->AdditionalInformationTextBlock().Text(\n            this->m_AdditionalInformation);\n        this->PathTextBox().Text(this->m_InitialPath);\n    }\n\n    LPCWSTR CopyLocationPage::GetPath()\n    {\n        return this->PathTextBox().Text().c_str();\n    }\n\n    void CopyLocationPage::OkButtonClick(\n        IInspectable const& sender,\n        RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::SendMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(K7_COPY_LOCATION_DIALOG_RESULT_OK, BN_CLICKED),\n            0);\n\n        ::SendMessageW(\n            this->m_WindowHandle,\n            WM_CLOSE,\n            0,\n            0);\n    }\n\n    void CopyLocationPage::CancelButtonClick(\n        IInspectable const& sender,\n        RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(this->m_WindowHandle, WM_CLOSE, 0, 0);\n    }\n\n    void CopyLocationPage::BrowseButtonClick(\n        IInspectable const& sender,\n        RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        winrt::com_ptr<IFileDialog> FileDialog =\n            winrt::try_create_instance<IFileDialog>(\n                CLSID_FileOpenDialog,\n                CLSCTX_INPROC_SERVER);\n        if (!FileDialog)\n        {\n            return;\n        }\n\n        FILEOPENDIALOGOPTIONS Options;\n        if (FAILED(FileDialog->GetOptions(&Options)))\n        {\n            Options = 0;\n        }\n        if (FAILED(FileDialog->SetOptions(\n            Options | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM)))\n        {\n            return;\n        }\n\n        FileDialog->SetTitle(Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/CopyLocationPage/SelectDestinationText\",\n            L\"Select destination folder.\").c_str());\n\n        {\n            IShellItem* DefaultFolder = nullptr;\n            if (SUCCEEDED(::SHCreateItemFromParsingName(\n                this->PathTextBox().Text().c_str(),\n                nullptr,\n                IID_PPV_ARGS(&DefaultFolder))))\n            {\n                FileDialog->SetFolder(DefaultFolder);\n                DefaultFolder->Release();\n            }\n        }\n\n        if (SUCCEEDED(FileDialog->Show(this->m_WindowHandle)))\n        {\n            IShellItem* Result = nullptr;\n            if (SUCCEEDED(FileDialog->GetResult(&Result)))\n            {\n                std::wstring Path;\n                {\n                    LPWSTR RawPath = nullptr;\n                    if (SUCCEEDED(Result->GetDisplayName(\n                        SIGDN_FILESYSPATH,\n                        &RawPath)))\n                    {\n                        Path = std::wstring(RawPath);\n                        ::CoTaskMemFree(RawPath);\n                    }\n                }\n                if (!Path.empty())\n                {\n                    if (!Path.ends_with(L\"\\\\\"))\n                    {\n                        Path.append(L\"\\\\\");\n                    }\n                    this->PathTextBox().Text(Path);\n                }\n\n                Result->Release();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/CopyLocationPage.h",
    "content": "﻿#pragma once\n\n#include \"CopyLocationPage.g.h\"\n\n#include \"NanaZip.Modern.h\"\n\nnamespace winrt\n{\n    using Windows::Foundation::IInspectable;\n    using Windows::UI::Xaml::RoutedEventArgs;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct CopyLocationPage : CopyLocationPageT<CopyLocationPage>\n    {\n        CopyLocationPage(\n            _In_opt_ HWND WindowHandle = nullptr,\n            _In_opt_ LPCWSTR Title = nullptr,\n            _In_opt_ LPCWSTR Subtitle = nullptr,\n            _In_opt_ LPCWSTR AdditionalInformation = nullptr,\n            _In_opt_ LPCWSTR InitialPath = nullptr\n        );\n\n        void InitializeComponent();\n\n        LPCWSTR GetPath();\n\n        void OkButtonClick(\n            IInspectable const& sender,\n            RoutedEventArgs const& e);\n\n        void CancelButtonClick(\n            IInspectable const& sender,\n            RoutedEventArgs const& e);\n\n        void BrowseButtonClick(\n            IInspectable const& sender,\n            RoutedEventArgs const& e);\n\n    private:\n\n        HWND m_WindowHandle = nullptr;\n        LPCWSTR m_Title = nullptr;\n        LPCWSTR m_Subtitle = nullptr;\n        LPCWSTR m_AdditionalInformation = nullptr;\n        LPCWSTR m_InitialPath = nullptr;\n        std::wstring m_FinalPath;\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/CopyLocationPage.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass CopyLocationPage : Windows.UI.Xaml.Controls.Page\n    {\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/CopyLocationPage.xaml",
    "content": "﻿<Page\n  x:Class=\"NanaZip.Modern.CopyLocationPage\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n  xmlns:local=\"using:NanaZip.Modern\"\n  xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n  mc:Ignorable=\"d\">\n\n  <Grid>\n    <Grid.RowDefinitions>\n      <RowDefinition Height=\"Auto\" />\n      <RowDefinition Height=\"Auto\" />\n      <RowDefinition Height=\"Auto\" />\n      <RowDefinition Height=\"*\" />\n      <RowDefinition Height=\"Auto\" />\n    </Grid.RowDefinitions>\n\n    <Grid.ColumnDefinitions>\n      <ColumnDefinition Width=\"*\" />\n      <ColumnDefinition Width=\"Auto\" />\n    </Grid.ColumnDefinitions>\n\n    <TextBlock\n      x:Name=\"TitleTextBlock\"\n      Grid.ColumnSpan=\"2\"\n      Margin=\"16,0\"\n      d:Text=\"[Copy]\"\n      FontSize=\"24\"\n      Style=\"{ThemeResource BaseTextBlockStyle}\"\n      TextTrimming=\"CharacterEllipsis\"\n      TextWrapping=\"NoWrap\" />\n\n    <TextBlock\n      x:Name=\"SubtitleTextBlock\"\n      Grid.Row=\"1\"\n      Grid.ColumnSpan=\"2\"\n      Margin=\"16,4\"\n      d:Text=\"[Copy to:]\" />\n\n    <TextBox\n      x:Name=\"PathTextBox\"\n      Grid.Row=\"2\"\n      Margin=\"16,0,4,0\" />\n    <Button\n      Grid.Row=\"2\"\n      Grid.Column=\"1\"\n      Margin=\"0,0,16,0\"\n      Click=\"BrowseButtonClick\"\n      Content=\"...\" />\n\n    <TextBlock\n      x:Name=\"AdditionalInformationTextBlock\"\n      Grid.Row=\"3\"\n      Margin=\"16,4,16,0\"\n      d:Text=\"Files: 1\" />\n\n    <Grid\n      Grid.Row=\"4\"\n      Grid.ColumnSpan=\"2\"\n      Background=\"#37C9C9C9\"\n      BorderBrush=\"{ThemeResource CardStrokeColorDefault}\"\n      BorderThickness=\"0,1,0,0\">\n      <StackPanel\n        Grid.Column=\"1\"\n        Padding=\"0,0,12,0\"\n        HorizontalAlignment=\"Right\"\n        Orientation=\"Horizontal\">\n        <Button\n          x:Name=\"PauseButton\"\n          x:Uid=\"/NanaZip.Modern/Common/OKButton\"\n          Width=\"120\"\n          Margin=\"0,16,4,16\"\n          Click=\"OkButtonClick\"\n          Content=\"[OK]\" />\n        <Button\n          x:Uid=\"/NanaZip.Modern/Common/CancelButton\"\n          Width=\"120\"\n          Margin=\"4,16,4,16\"\n          Click=\"CancelButtonClick\"\n          Content=\"[Cancel]\" />\n      </StackPanel>\n    </Grid>\n  </Grid>\n</Page>\n"
  },
  {
    "path": "NanaZip.Modern/InformationPage.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"InformationPage.h\"\n#if __has_include(\"InformationPage.g.cpp\")\n#include \"InformationPage.g.cpp\"\n#endif\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    InformationPage::InformationPage(\n        _In_opt_ HWND WindowHandle,\n        _In_opt_ LPCWSTR Title,\n        _In_opt_ LPCWSTR Content) :\n        m_WindowHandle(WindowHandle),\n        m_Title(Title),\n        m_Content(Content)\n    {\n    }\n\n    void InformationPage::InitializeComponent()\n    {\n        InformationPageT::InitializeComponent();\n\n        ::SetWindowTextW(this->m_WindowHandle, this->m_Title.c_str());\n        \n        this->TitleTextBlock().Text(this->m_Title);\n        this->InformationTextBox().Text(this->m_Content);\n    }\n\n    void InformationPage::CloseButtonClickedHandler(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& args)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(args);\n\n\t\t::PostMessageW(this->m_WindowHandle, WM_CLOSE, 0, 0);\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/InformationPage.h",
    "content": "﻿#pragma once\n\n#include \"InformationPage.g.h\"\n\n#include <Windows.h>\n\nnamespace winrt\n{\n    using Windows::Foundation::IInspectable;\n    using Windows::UI::Xaml::RoutedEventArgs;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct InformationPage : InformationPageT<InformationPage>\n    {\n        InformationPage(\n            _In_opt_ HWND WindowHandle = nullptr,\n            _In_opt_ LPCWSTR Title = nullptr,\n            _In_opt_ LPCWSTR Content = nullptr);\n\n        void InitializeComponent();\n\n        void CloseButtonClickedHandler(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& args);\n\n    private:\n\n        HWND m_WindowHandle = nullptr;\n        winrt::hstring m_Title;\n        winrt::hstring m_Content;\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/InformationPage.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass InformationPage : Windows.UI.Xaml.Controls.Page\n    {\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/InformationPage.xaml",
    "content": "﻿<Page\n  x:Class=\"NanaZip.Modern.InformationPage\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n  xmlns:local=\"using:NanaZip.Modern\"\n  xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n  mc:Ignorable=\"d\">\n\n  <Grid>\n    <Grid.RowDefinitions>\n      <RowDefinition Height=\"Auto\" />\n      <RowDefinition Height=\"*\" />\n      <RowDefinition Height=\"Auto\" />\n    </Grid.RowDefinitions>\n    <TextBlock\n      x:Name=\"TitleTextBlock\"\n      Margin=\"16,0\"\n      d:Text=\"[Information]\"\n      FontSize=\"24\"\n      Style=\"{ThemeResource BaseTextBlockStyle}\" />\n    <TextBox\n      x:Name=\"InformationTextBox\"\n      Grid.Row=\"1\"\n      Margin=\"16,8,16,16\"\n      AcceptsReturn=\"True\"\n      IsReadOnly=\"True\"\n      ScrollViewer.HorizontalScrollBarVisibility=\"Visible\"\n      ScrollViewer.VerticalScrollBarVisibility=\"Visible\">\n      <TextBox.SelectionFlyout>\n        <TextCommandBarFlyout Placement=\"BottomEdgeAlignedLeft\" />\n      </TextBox.SelectionFlyout>\n    </TextBox>\n    <Grid\n      Grid.Row=\"2\"\n      Background=\"#37C9C9C9\"\n      BorderBrush=\"{ThemeResource CardStrokeColorDefault}\"\n      BorderThickness=\"0,1,0,0\">\n      <StackPanel\n        Grid.Column=\"1\"\n        Padding=\"0,0,12,0\"\n        HorizontalAlignment=\"Right\"\n        Orientation=\"Horizontal\">\n        <Button\n          x:Uid=\"/NanaZip.Modern/Common/CloseButton\"\n          Width=\"120\"\n          Margin=\"4,16,4,16\"\n          d:Content=\"[Close]\"\n          Click=\"CloseButtonClickedHandler\" />\n      </StackPanel>\n    </Grid>\n  </Grid>\n</Page>\n"
  },
  {
    "path": "NanaZip.Modern/MainWindowToolBarPage.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"MainWindowToolBarPage.h\"\n#if __has_include(\"MainWindowToolBarPage.g.cpp\")\n#include \"MainWindowToolBarPage.g.cpp\"\n#endif\n\n#include <winrt/Windows.UI.Xaml.Automation.h>\n#include <winrt/Windows.UI.Xaml.Media.h>\n\n#include \"NanaZip.Modern.h\"\n\n#include <Mile.Helpers.CppBase.h>\n#include <Mile.Helpers.CppWinRT.h>\n\nnamespace winrt::Mile\n{\n    using namespace ::Mile;\n}\n\n#include <ShObjIdl_core.h>\n\nnamespace\n{\n    DWORD GetShellProcessId()\n    {\n        HWND ShellWindowHandle = ::GetShellWindow();\n        if (!ShellWindowHandle)\n        {\n            return static_cast<DWORD>(-1);\n        }\n\n        DWORD ShellProcessId = static_cast<DWORD>(-1);\n        if (!::GetWindowThreadProcessId(ShellWindowHandle, &ShellProcessId))\n        {\n            return static_cast<DWORD>(-1);\n        }\n        return ShellProcessId;\n    }\n\n    std::wstring GetCurrentProcessModulePath()\n    {\n        // 32767 is the maximum path length without the terminating null character.\n        std::wstring Path(32767, L'\\0');\n        Path.resize(::GetModuleFileNameW(\n            nullptr, &Path[0], static_cast<DWORD>(Path.size())));\n        return Path;\n    }\n}\n\nnamespace winrt\n{\n    using Windows::Foundation::Point;\n    using Windows::Foundation::IAsyncAction;\n    using Windows::Services::Store::StoreProduct;\n    using Windows::Services::Store::StoreProductQueryResult;\n    using Windows::System::DispatcherQueuePriority;\n    using Windows::UI::Xaml::Automation::AutomationProperties;\n    using Windows::UI::Xaml::Controls::AppBarButton;\n    using Windows::UI::Xaml::Controls::ToolTipService;\n    using Windows::UI::Xaml::Media::GeneralTransform;\n}\n\nnamespace\n{\n    namespace ToolBarCommandID\n    {\n        enum\n        {\n            Add = 1070,\n            Extract = 1071,\n            Test = 1072,\n            Copy = 546,\n            Move = 547,\n            Delete = 548,\n            Info = 551,\n            Options = 900,\n            Benchmark = 901,\n            About = 961\n        };\n    }\n\n    namespace MenuIndex\n    {\n        enum\n        {\n            File = 0,\n            Edit,\n            View,\n            Bookmarks\n        };\n    }\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    MainWindowToolBarPage::MainWindowToolBarPage(\n        _In_ HWND WindowHandle,\n        _In_ HMENU MoreMenu) :\n        m_WindowHandle(WindowHandle),\n        m_MoreMenu(MoreMenu)\n    {\n\n    }\n\n    void MainWindowToolBarPage::InitializeComponent()\n    {\n        MainWindowToolBarPageT::InitializeComponent();\n\n        winrt::AppBarButton ToolBarButtons[10] =\n        {\n            this->AddButton(),\n            this->ExtractButton(),\n            this->TestButton(),\n            this->CopyButton(),\n            this->MoveButton(),\n            this->DeleteButton(),\n            this->InfoButton(),\n            this->OptionsButton(),\n            this->BenchmarkButton(),\n            this->AboutButton()\n        };\n\n        const UINT32 ToolBarLegacyStringResources[10] =\n        {\n            7200, // Add\n            7201, // Extract\n            7202, // Test\n            7203, // Copy\n            7204, // Move\n            7205, // Delete\n            7206, // Info\n            900, // Options\n            901, // Benchmark\n            961 // About\n        };\n\n        const std::size_t ToolBarButtonCount =\n            sizeof(ToolBarButtons) / sizeof(*ToolBarButtons);\n\n        for (size_t i = 0; i < ToolBarButtonCount; ++i)\n        {\n            winrt::hstring Resource = winrt::hstring(::K7ModernGetLegacyStringResource(\n                ToolBarLegacyStringResources[i]));\n            winrt::AutomationProperties::SetName(\n                ToolBarButtons[i],\n                Resource);\n            winrt::ToolTipService::SetToolTip(\n                ToolBarButtons[i],\n                winrt::box_value(Resource));\n        }\n\n        this->m_DispatcherQueue =\n            winrt::DispatcherQueue::GetForCurrentThread();\n\n        std::wstring sponsorButtonLabel = L\"[\";\n        sponsorButtonLabel += Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/MainWindowToolBarPage/SponsorButton/AcquireText\",\n            L\"Sponsor NanaZip\");\n        sponsorButtonLabel += L\"]\";\n\n        this->SponsorButton().Content(winrt::box_value(sponsorButtonLabel));\n    }\n\n    void MainWindowToolBarPage::PageLoaded(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        this->RefreshSponsorButtonContent();\n    }\n\n    void MainWindowToolBarPage::AddButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Add,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::ExtractButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Extract,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::TestButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Test,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::CopyButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Copy,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::MoveButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Move,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::DeleteButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Delete,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::InfoButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Info,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::OptionsButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Options,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::BenchmarkButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::Benchmark,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::AboutButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(\n                ToolBarCommandID::About,\n                BN_CLICKED),\n            0);\n    }\n\n    void MainWindowToolBarPage::MoreButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        winrt::AppBarButton Button = sender.as<winrt::AppBarButton>();\n\n        winrt::GeneralTransform Transform =\n            Button.TransformToVisual(this->Content());\n        winrt::Point LogicalPoint = Transform.TransformPoint(\n            winrt::Point(0.0f, 0.0f));\n\n        UINT DpiValue = ::GetDpiForWindow(this->m_WindowHandle);\n\n        POINT MenuPosition = {};\n        MenuPosition.x = ::MulDiv(\n            static_cast<int>(LogicalPoint.X),\n            DpiValue,\n            USER_DEFAULT_SCREEN_DPI);\n        MenuPosition.y = ::MulDiv(\n            48,\n            DpiValue,\n            USER_DEFAULT_SCREEN_DPI);\n        ::MapWindowPoints(\n            this->m_WindowHandle,\n            HWND_DESKTOP,\n            &MenuPosition,\n            1);\n\n        ::SendMessageW(\n            this->m_WindowHandle,\n            WM_INITMENUPOPUP,\n            reinterpret_cast<WPARAM>(::GetSubMenu(\n                this->m_MoreMenu,\n                MenuIndex::File)),\n            MenuIndex::File);\n        ::SendMessageW(\n            this->m_WindowHandle,\n            WM_INITMENUPOPUP,\n            reinterpret_cast<WPARAM>(::GetSubMenu(\n                this->m_MoreMenu,\n                MenuIndex::Edit)),\n            MenuIndex::Edit);\n        ::SendMessageW(\n            this->m_WindowHandle,\n            WM_INITMENUPOPUP,\n            reinterpret_cast<WPARAM>(::GetSubMenu(\n                this->m_MoreMenu,\n                MenuIndex::View)),\n            MenuIndex::View);\n        ::SendMessageW(\n            this->m_WindowHandle,\n            WM_INITMENUPOPUP,\n            reinterpret_cast<WPARAM>(::GetSubMenu(\n                this->m_MoreMenu,\n                MenuIndex::Bookmarks)),\n            MenuIndex::Bookmarks);\n\n        WPARAM Command = ::TrackPopupMenuEx(\n            this->m_MoreMenu,\n            TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD,\n            MenuPosition.x,\n            MenuPosition.y,\n            this->m_WindowHandle,\n            nullptr);\n        if (Command)\n        {\n            ::PostMessageW(this->m_WindowHandle, WM_COMMAND, Command, 0);\n        }\n    }\n\n    void MainWindowToolBarPage::SponsorButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        winrt::handle(Mile::CreateThread([=]()\n        {\n            DWORD ShellProcessId = ::GetShellProcessId();\n            if (static_cast<DWORD>(-1) == ShellProcessId)\n            {\n                return;\n            }\n\n            HANDLE ShellProcessHandle = nullptr;\n\n            auto Handler = Mile::ScopeExitTaskHandler([&]()\n            {\n                if (ShellProcessHandle)\n                {\n                    ::CloseHandle(ShellProcessHandle);\n                }\n            });\n\n            ShellProcessHandle = ::OpenProcess(\n                PROCESS_CREATE_PROCESS,\n                FALSE,\n                ShellProcessId);\n            if (!ShellProcessHandle)\n            {\n                return;\n            }\n\n            SIZE_T AttributeListSize = 0;\n            ::InitializeProcThreadAttributeList(\n                nullptr,\n                1,\n                0,\n                &AttributeListSize);\n\n            std::vector<std::uint8_t> AttributeListBuffer =\n                std::vector<std::uint8_t>(AttributeListSize);\n\n            PPROC_THREAD_ATTRIBUTE_LIST AttributeList =\n                reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(\n                    &AttributeListBuffer[0]);\n\n            if (!::InitializeProcThreadAttributeList(\n                AttributeList,\n                1,\n                0,\n                &AttributeListSize))\n            {\n                return;\n            }\n\n            if (!::UpdateProcThreadAttribute(\n                AttributeList,\n                0,\n                PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,\n                &ShellProcessHandle,\n                sizeof(ShellProcessHandle),\n                nullptr,\n                nullptr))\n            {\n                return;\n            }\n\n            STARTUPINFOEXW StartupInfoEx = {};\n            PROCESS_INFORMATION ProcessInformation = {};\n            StartupInfoEx.StartupInfo.cb = sizeof(STARTUPINFOEXW);\n            StartupInfoEx.lpAttributeList = AttributeList;\n\n            std::wstring ApplicationName = ::GetCurrentProcessModulePath();\n\n            if (!::CreateProcessW(\n                ApplicationName.c_str(),\n                const_cast<LPWSTR>(L\"NanaZip --AcquireSponsorEdition\"),\n                nullptr,\n                nullptr,\n                TRUE,\n                CREATE_UNICODE_ENVIRONMENT | EXTENDED_STARTUPINFO_PRESENT,\n                nullptr,\n                nullptr,\n                &StartupInfoEx.StartupInfo,\n                &ProcessInformation))\n            {\n                return;\n            }\n\n            ::AllowSetForegroundWindow(\n                ::GetProcessId(ProcessInformation.hProcess));\n\n            ::CloseHandle(ProcessInformation.hThread);\n            ::WaitForSingleObjectEx(ProcessInformation.hProcess, INFINITE, FALSE);\n            ::CloseHandle(ProcessInformation.hProcess);\n\n            ::RegDeleteKeyValueW(\n                HKEY_CURRENT_USER,\n                L\"Software\\\\NanaZip\",\n                L\"SponsorEdition\");\n\n            this->RefreshSponsorButtonContent();\n        }));\n    }\n\n    bool MainWindowToolBarPage::CheckSponsorEditionLicense()\n    {\n        {\n            DWORD Data = 0;\n            DWORD Length = sizeof(DWORD);\n            if (ERROR_SUCCESS == ::RegGetValueW(\n                HKEY_CURRENT_USER,\n                L\"Software\\\\NanaZip\",\n                L\"SponsorEdition\",\n                RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,\n                nullptr,\n                &Data,\n                &Length))\n            {\n                return Data;\n            }\n        }\n\n        if (!this->m_StoreContext)\n        {\n            this->m_StoreContext = winrt::StoreContext::GetDefault();\n        }\n\n        bool Sponsored = false;\n\n        if (this->m_StoreContext)\n        {\n            winrt::StoreProductQueryResult ProductQueryResult =\n                this->m_StoreContext.GetStoreProductsAsync(\n                    { L\"Durable\" },\n                    { L\"9N9DNPT6D6Z9\" }).get();\n            for (auto Item : ProductQueryResult.Products())\n            {\n                winrt::StoreProduct Product = Item.Value();\n                Sponsored = Product.IsInUserCollection();\n            }\n        }\n\n        {\n            DWORD Data = Sponsored;\n            ::RegSetKeyValueW(\n                HKEY_CURRENT_USER,\n                L\"Software\\\\NanaZip\",\n                L\"SponsorEdition\",\n                REG_DWORD,\n                &Data,\n                sizeof(DWORD));\n        }\n\n        return Sponsored;\n    }\n\n    void MainWindowToolBarPage::RefreshSponsorButtonContent()\n    {\n        winrt::handle(Mile::CreateThread([=]()\n        {\n            bool Sponsored = this->CheckSponsorEditionLicense();\n\n            if (!this->m_DispatcherQueue)\n            {\n                return;\n            }\n            this->m_DispatcherQueue.TryEnqueue(\n                winrt::DispatcherQueuePriority::Normal,\n                [=]()\n            {\n                std::wstring ResourcePath = L\"NanaZip.Modern/\";\n                ResourcePath += L\"MainWindowToolBarPage/SponsorButton/\";\n                ResourcePath += Sponsored ? L\"SponsoredText\" : L\"AcquireText\";\n                winrt::hstring ResourceContent =\n                    Mile::WinRT::GetLocalizedString(ResourcePath.c_str());\n                this->SponsorButton().Content(\n                    winrt::box_value(ResourceContent));\n            });\n        }));\n    }\n}\n\nEXTERN_C LPVOID WINAPI K7ModernCreateMainWindowToolBarPage(\n    _In_ HWND ParentWindowHandle,\n    _In_ HMENU MoreMenuHandle)\n{\n    using Interface =\n        winrt::NanaZip::Modern::MainWindowToolBarPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::MainWindowToolBarPage;\n\n    Interface Window = winrt::make<Implementation>(\n        ParentWindowHandle,\n        MoreMenuHandle);\n    return winrt::detach_abi(Window);\n}\n"
  },
  {
    "path": "NanaZip.Modern/MainWindowToolBarPage.h",
    "content": "﻿#pragma once\n\n#include \"MainWindowToolBarPage.g.h\"\n\n#include <Windows.h>\n\n#include <winrt/Windows.System.h>\n#include <winrt/Windows.Services.Store.h>\n\nnamespace winrt\n{\n    using Windows::Foundation::IInspectable;\n    using Windows::Services::Store::StoreContext;\n    using Windows::System::DispatcherQueue;\n    using Windows::UI::Xaml::RoutedEventArgs;\n}\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct MainWindowToolBarPage : MainWindowToolBarPageT<MainWindowToolBarPage>\n    {\n    public:\n\n        MainWindowToolBarPage(\n            _In_ HWND WindowHandle = nullptr,\n            _In_ HMENU MoreMenu = nullptr);\n\n        void InitializeComponent();\n\n        void PageLoaded(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void AddButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void ExtractButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void TestButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void CopyButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void MoveButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void DeleteButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void InfoButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void OptionsButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void BenchmarkButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void AboutButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void MoreButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void SponsorButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n    private:\n\n        HWND m_WindowHandle;\n        HMENU m_MoreMenu;\n        winrt::DispatcherQueue m_DispatcherQueue = nullptr;\n        winrt::StoreContext m_StoreContext = nullptr;\n\n        bool CheckSponsorEditionLicense();\n\n        void RefreshSponsorButtonContent();\n    };\n}\n\nnamespace winrt::NanaZip::Modern::factory_implementation\n{\n    struct MainWindowToolBarPage : MainWindowToolBarPageT<\n        MainWindowToolBarPage, implementation::MainWindowToolBarPage>\n    {\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/MainWindowToolBarPage.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass MainWindowToolBarPage : Windows.UI.Xaml.Controls.Page\n    {\n        MainWindowToolBarPage();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/MainWindowToolBarPage.xaml",
    "content": "﻿<Page\n  x:Class=\"NanaZip.Modern.MainWindowToolBarPage\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n  xmlns:local=\"using:NanaZip.Modern\"\n  xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n  IsTextScaleFactorEnabled=\"False\"\n  Loaded=\"PageLoaded\"\n  mc:Ignorable=\"d\">\n  <Grid>\n    <Grid.RowDefinitions>\n      <RowDefinition Height=\"auto\" />\n      <RowDefinition Height=\"*\" />\n    </Grid.RowDefinitions>\n    <Grid Grid.Row=\"0\">\n      <Grid.ColumnDefinitions>\n        <ColumnDefinition Width=\"auto\" />\n        <ColumnDefinition Width=\"*\" />\n        <ColumnDefinition Width=\"auto\" />\n      </Grid.ColumnDefinitions>\n      <CommandBar\n        Grid.Column=\"0\"\n        HorizontalAlignment=\"Left\"\n        Background=\"Transparent\"\n        DefaultLabelPosition=\"Collapsed\"\n        IsDynamicOverflowEnabled=\"False\"\n        IsOpen=\"False\">\n        <AppBarButton\n          x:Name=\"AddButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Add]\"\n          Click=\"AddButtonClick\"\n          Icon=\"Add\"\n          ToolTipService.ToolTip=\"[Add]\" />\n        <AppBarButton\n          x:Name=\"ExtractButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Extract]\"\n          Click=\"ExtractButtonClick\"\n          Icon=\"MoveToFolder\"\n          ToolTipService.ToolTip=\"[Extract]\" />\n        <AppBarButton\n          x:Name=\"TestButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Test]\"\n          Click=\"TestButtonClick\"\n          Icon=\"Accept\"\n          ToolTipService.ToolTip=\"[Test]\" />\n        <AppBarSeparator />\n        <AppBarButton\n          x:Name=\"CopyButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Copy]\"\n          Click=\"CopyButtonClick\"\n          Icon=\"Copy\"\n          ToolTipService.ToolTip=\"[Copy]\" />\n        <AppBarButton\n          x:Name=\"MoveButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Move]\"\n          Click=\"MoveButtonClick\"\n          ToolTipService.ToolTip=\"[Move]\">\n          <AppBarButton.Content>\n            <TextBlock FontFamily=\"Segoe MDL2 Assets\" Text=\"&#xE8C6;\" />\n          </AppBarButton.Content>\n        </AppBarButton>\n        <AppBarButton\n          x:Name=\"DeleteButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Delete]\"\n          Click=\"DeleteButtonClick\"\n          Icon=\"Delete\"\n          ToolTipService.ToolTip=\"[Delete]\" />\n        <AppBarButton\n          x:Name=\"InfoButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Info]\"\n          Click=\"InfoButtonClick\"\n          ToolTipService.ToolTip=\"[Info]\">\n          <AppBarButton.Content>\n            <TextBlock FontFamily=\"Segoe MDL2 Assets\" Text=\"&#xE946;\" />\n          </AppBarButton.Content>\n        </AppBarButton>\n        <AppBarSeparator />\n        <AppBarButton\n          x:Name=\"OptionsButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Options]\"\n          Click=\"OptionsButtonClick\"\n          Icon=\"Setting\"\n          ToolTipService.ToolTip=\"[Options]\" />\n        <AppBarButton\n          x:Name=\"BenchmarkButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[Benchmark]\"\n          Click=\"BenchmarkButtonClick\"\n          Icon=\"Play\"\n          ToolTipService.ToolTip=\"[Benchmark]\" />\n        <AppBarButton\n          x:Name=\"AboutButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[About]\"\n          Click=\"AboutButtonClick\"\n          Icon=\"Help\"\n          ToolTipService.ToolTip=\"[About]\" />\n        <AppBarSeparator />\n        <AppBarButton\n          x:Uid=\"/NanaZip.Modern/MainWindowToolBarPage/MoreButton\"\n          Width=\"48\"\n          AutomationProperties.Name=\"[More]\"\n          Click=\"MoreButtonClick\"\n          Icon=\"More\"\n          ToolTipService.ToolTip=\"[More]\" />\n      </CommandBar>\n      <Button\n        x:Name=\"SponsorButton\"\n        Grid.Column=\"2\"\n        Margin=\"0,0,6,0\"\n        VerticalAlignment=\"Center\"\n        Background=\"Transparent\"\n        Click=\"SponsorButtonClick\"\n        Content=\"[Sponsor NanaZip]\" />\n    </Grid>\n  </Grid>\n</Page>\n"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.Wrapper.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip.Modern\n * FILE:       NanaZip.Modern.Wrapper.cpp\n * PURPOSE:    Implementation for NanaZip Modern Experience Wrapper\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"NanaZip.Modern.h\"\n\n#include <string>\n\n// Only used in Shell Extension to check whether NanaZip Modern is loaded.\nEXTERN_C HMODULE K7ModernCurrentModule = nullptr;\n\nnamespace\n{\n    std::wstring GetCurrentProcessModulePath()\n    {\n        // 32767 is the maximum path length without the terminating null character.\n        std::wstring Path(32767, L'\\0');\n        Path.resize(::GetModuleFileNameW(\n            ::K7ModernCurrentModule,\n            &Path[0],\n            static_cast<DWORD>(Path.size())));\n        return Path;\n    }\n\n    static HMODULE GetNanaZipModernModuleHandle()\n    {\n        static HMODULE CachedResult = ([]() -> HMODULE\n        {\n            std::wstring ModulePath = ::GetCurrentProcessModulePath();\n            size_t LastBackslashPosition = ModulePath.rfind(L'\\\\');\n            if (std::wstring::npos != LastBackslashPosition)\n            {\n                ModulePath.resize(LastBackslashPosition + 1);\n            }\n            ModulePath.append(L\"NanaZip.Modern.dll\");\n            return ::LoadLibraryExW(\n                ModulePath.c_str(),\n                nullptr,\n                LOAD_WITH_ALTERED_SEARCH_PATH);\n        }());\n\n        return CachedResult;\n    }\n}\n\nEXTERN_C LPCWSTR WINAPI K7ModernGetLegacyStringResource(\n    _In_ UINT32 ResourceId)\n{\n    using ProcType = decltype(::K7ModernGetLegacyStringResource)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernGetLegacyStringResource\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress(ResourceId);\n    }\n\n    return nullptr;\n}\n\nEXTERN_C BOOL WINAPI K7ModernAvailable()\n{\n    using ProcType = decltype(::K7ModernAvailable)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernAvailable\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress();\n    }\n\n    return FALSE;\n}\n\nEXTERN_C HRESULT WINAPI K7ModernInitialize()\n{\n    using ProcType = decltype(::K7ModernInitialize)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernInitialize\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress();\n    }\n\n    return E_NOINTERFACE;\n}\n\nEXTERN_C HRESULT WINAPI K7ModernUninitialize()\n{\n    using ProcType = decltype(::K7ModernUninitialize)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernUninitialize\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress();\n    }\n\n    return E_NOINTERFACE;\n}\n\nEXTERN_C INT WINAPI K7ModernShowSponsorDialog(\n    _In_opt_ HWND ParentWindowHandle)\n{\n    using ProcType = decltype(::K7ModernShowSponsorDialog)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernShowSponsorDialog\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress(ParentWindowHandle);\n    }\n\n    return -1;\n}\n\nEXTERN_C INT WINAPI K7ModernShowAboutDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR ExtendedMessage)\n{\n    using ProcType = decltype(::K7ModernShowAboutDialog)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernShowAboutDialog\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress(ParentWindowHandle, ExtendedMessage);\n    }\n\n    return -1;\n}\n\nEXTERN_C INT WINAPI K7ModernShowInformationDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_opt_ LPCWSTR Content)\n{\n    using ProcType = decltype(::K7ModernShowInformationDialog)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernShowInformationDialog\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress(ParentWindowHandle, Title, Content);\n    }\n\n    return -1;\n}\n\nEXTERN_C VOID WINAPI K7ModernUpdateProgressWindowStatus(\n    _In_ HWND WindowHandle,\n    _In_ PK7_PROGRESS_WINDOW_STATUS Status)\n{\n    using ProcType = decltype(::K7ModernUpdateProgressWindowStatus)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernUpdateProgressWindowStatus\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        ProcAddress(WindowHandle, Status);\n    }\n}\n\nEXTERN_C VOID WINAPI K7ModernSetProgressWindowPausedMode(\n    _In_ HWND WindowHandle,\n    _In_ BOOL Paused)\n{\n    using ProcType = decltype(::K7ModernSetProgressWindowPausedMode)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernSetProgressWindowPausedMode\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        ProcAddress(WindowHandle, Paused);\n    }\n}\n\nEXTERN_C INT WINAPI K7ModernShowProgressWindow(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_ BOOL ShowCompressionInformation,\n    _In_ SUBCLASSPROC WindowSubclassHandler,\n    _In_ LPVOID WindowSubclassContext)\n{\n    using ProcType = decltype(::K7ModernShowProgressWindow)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernShowProgressWindow\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress(\n            ParentWindowHandle,\n            Title,\n            ShowCompressionInformation,\n            WindowSubclassHandler,\n            WindowSubclassContext);\n    }\n    return -1;\n}\n\nEXTERN_C LPVOID WINAPI K7ModernCreateMainWindowToolBarPage(\n    _In_ HWND ParentWindowHandle,\n    _In_ HMENU MoreMenuHandle)\n{\n    using ProcType = decltype(::K7ModernCreateMainWindowToolBarPage)*;\n\n    static ProcType ProcAddress = reinterpret_cast<ProcType>([]() -> FARPROC\n    {\n        HMODULE ModuleHandle = ::GetNanaZipModernModuleHandle();\n        if (ModuleHandle)\n        {\n            return ::GetProcAddress(\n                ModuleHandle,\n                \"K7ModernCreateMainWindowToolBarPage\");\n        }\n        return nullptr;\n    }());\n\n    if (ProcAddress)\n    {\n        return ProcAddress(ParentWindowHandle, MoreMenuHandle);\n    }\n\n    return nullptr;\n}\n"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.cpp",
    "content": "﻿/*\n * PROJECT:    NanaZip.Modern\n * FILE:       NanaZip.Modern.cpp\n * PURPOSE:    Implementation for NanaZip Modern Experience\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#include \"pch.h\"\n\n#include \"NanaZip.Modern.h\"\n\n#include <Mile.Helpers.h>\n#include <Mile.Xaml.h>\n\n#include \"App.h\"\n#include \"SponsorPage.h\"\n#include \"AboutPage.h\"\n#include \"InformationPage.h\"\n#include \"ProgressPage.h\"\n#include \"CopyLocationPage.h\"\n\n#pragma comment(lib, \"comctl32.lib\")\n\n#include <winrt/Windows.ApplicationModel.Resources.Core.h>\n#include <winrt/Windows.UI.Xaml.Hosting.h>\n\n#include <mutex>\n#include <map>\n\nnamespace winrt\n{\n    using Windows::ApplicationModel::Resources::Core::ResourceManager;\n    using Windows::ApplicationModel::Resources::Core::ResourceMap;\n}\n\nnamespace\n{\n    static winrt::ResourceMap GetMainResourceMap()\n    {\n        static winrt::ResourceMap CachedResult = ([]() -> winrt::ResourceMap\n        {\n            try\n            {\n                return winrt::ResourceManager::Current().MainResourceMap();\n            }\n            catch (...)\n            {\n                // Do nothing.\n            }\n            return nullptr;\n        }());\n\n        return CachedResult;\n    }\n\n    static std::mutex g_CachedLanguageStringResourcesMutex;\n    static std::map<UINT32, winrt::hstring> g_CachedLanguageStringResources;\n}\n\nEXTERN_C LPCWSTR WINAPI K7ModernGetLegacyStringResource(\n    _In_ UINT32 ResourceId)\n{\n    {\n        std::lock_guard Lock(g_CachedLanguageStringResourcesMutex);\n        auto Iterator = g_CachedLanguageStringResources.find(ResourceId);\n        if (g_CachedLanguageStringResources.end() != Iterator)\n        {\n            return Iterator->second.c_str();\n        }\n    }\n\n    static winrt::ResourceMap LegacyResourceMap = ([]() -> winrt::ResourceMap\n    {\n        winrt::ResourceMap MainResourceMap = ::GetMainResourceMap();\n        if (MainResourceMap)\n        {\n            return MainResourceMap.GetSubtree(L\"Legacy\");\n        }\n        return nullptr;\n    }());\n    if (!LegacyResourceMap)\n    {\n        return nullptr;\n    }\n\n    winrt::hstring ResourceName = L\"Resource\" + winrt::to_hstring(ResourceId);\n    if (!LegacyResourceMap.HasKey(ResourceName))\n    {\n        return nullptr;\n    }\n\n    winrt::hstring Content = LegacyResourceMap.Lookup(\n        ResourceName).Candidates().GetAt(0).ValueAsString();\n    std::lock_guard Lock(g_CachedLanguageStringResourcesMutex);\n    auto Iterator = g_CachedLanguageStringResources.emplace(\n        ResourceId,\n        std::move(Content));\n    return Iterator.first->second.c_str();\n}\n\nnamespace\n{\n    static winrt::NanaZip::Modern::App g_AppInstance = nullptr;\n}\n\nEXTERN_C BOOL WINAPI K7ModernAvailable()\n{\n    return nullptr != g_AppInstance;\n}\n\nEXTERN_C HRESULT WINAPI K7ModernInitialize()\n{\n    if (g_AppInstance)\n    {\n        return S_OK;\n    }\n    if (!::GetMainResourceMap())\n    {\n        // NanaZip.Modern requires resources.pri to get XAML resources.\n        return E_NOINTERFACE;\n    }\n    try\n    {\n        winrt::init_apartment(winrt::apartment_type::single_threaded);\n        using Implementation = winrt::NanaZip::Modern::implementation::App;\n        g_AppInstance = winrt::make<Implementation>();\n    }\n    catch (...)\n    {\n        return winrt::to_hresult();\n    }\n    return S_OK;\n}\n\nEXTERN_C HRESULT WINAPI K7ModernUninitialize()\n{\n    if (!g_AppInstance)\n    {\n        return S_OK;\n    }\n    try\n    {\n        g_AppInstance.Close();\n        g_AppInstance = nullptr;\n        winrt::uninit_apartment();\n    }\n    catch (...)\n    {\n        return winrt::to_hresult();\n    }\n    return S_OK;\n}\n\nnamespace winrt\n{\n    using Windows::UI::Xaml::Hosting::DesktopWindowXamlSource;\n}\n\nnamespace\n{\n    HWND K7ModernCreateXamlWindow(\n        _In_opt_ HWND ParentWindowHandle,\n        _In_ DWORD ExtendedWindowStyle,\n        _In_ DWORD WindowStyle)\n    {\n        HWND WindowHandle = ::CreateWindowExW(\n            ExtendedWindowStyle,\n            L\"Mile.Xaml.ContentWindow\",\n            nullptr,\n            WindowStyle,\n            CW_USEDEFAULT,\n            0,\n            CW_USEDEFAULT,\n            0,\n            ParentWindowHandle,\n            nullptr,\n            nullptr,\n            nullptr);\n        if (!::SetWindowSubclass(\n            WindowHandle,\n            [](\n                _In_ HWND hWnd,\n                _In_ UINT uMsg,\n                _In_ WPARAM wParam,\n                _In_ LPARAM lParam,\n                _In_ UINT_PTR uIdSubclass,\n                _In_ DWORD_PTR dwRefData) -> LRESULT\n        {\n            UNREFERENCED_PARAMETER(uIdSubclass);\n            UNREFERENCED_PARAMETER(dwRefData);\n\n            switch (uMsg)\n            {\n            case WM_CLOSE:\n            {\n                HWND ParentWindow = ::GetWindow(hWnd, GW_OWNER);\n                if (ParentWindow)\n                {\n                    ::EnableWindow(ParentWindow, TRUE);\n                }\n                break;\n            }\n            default:\n                break;\n            }\n\n            return ::DefSubclassProc(\n                hWnd,\n                uMsg,\n                wParam,\n                lParam);\n        },\n            0,\n            0))\n        {\n            ::DestroyWindow(WindowHandle);\n            return nullptr;\n        }\n        return WindowHandle;\n    }\n\n    HWND K7ModernCreateXamlDialog(\n        _In_opt_ HWND ParentWindowHandle)\n    {\n        return ::K7ModernCreateXamlWindow(\n            ParentWindowHandle,\n            WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,\n            WS_CAPTION | WS_SYSMENU);\n    }\n\n    int K7ModernShowXamlWindow(\n        _In_opt_ HWND WindowHandle,\n        _In_ int Width,\n        _In_ int Height,\n        _In_ HWND ParentWindowHandle)\n    {\n        if (!WindowHandle)\n        {\n            return -1;\n        }\n\n        UINT DpiValue = ::GetDpiForWindow(WindowHandle);\n\n        int ScaledWidth = ::MulDiv(Width, DpiValue, USER_DEFAULT_SCREEN_DPI);\n        int ScaledHeight = ::MulDiv(Height, DpiValue, USER_DEFAULT_SCREEN_DPI);\n\n        RECT ParentRect = {};\n        if (ParentWindowHandle)\n        {\n            ::GetWindowRect(ParentWindowHandle, &ParentRect);\n        }\n        else\n        {\n            HMONITOR MonitorHandle = ::MonitorFromWindow(\n                WindowHandle,\n                MONITOR_DEFAULTTONEAREST);\n            if (MonitorHandle)\n            {\n                MONITORINFO MonitorInfo;\n                MonitorInfo.cbSize = sizeof(MONITORINFO);\n                if (::GetMonitorInfoW(MonitorHandle, &MonitorInfo))\n                {\n                    ParentRect = MonitorInfo.rcWork;\n                }\n            }\n        }\n\n        int ParentWidth = ParentRect.right - ParentRect.left;\n        int ParentHeight = ParentRect.bottom - ParentRect.top;\n\n        ::SetWindowPos(\n            WindowHandle,\n            nullptr,\n            ParentRect.left + ((ParentWidth - ScaledWidth) / 2),\n            ParentRect.top + ((ParentHeight - ScaledHeight) / 2),\n            ScaledWidth,\n            ScaledHeight,\n            SWP_NOZORDER | SWP_NOACTIVATE);\n\n        ::ShowWindow(WindowHandle, SW_SHOW);\n        ::UpdateWindow(WindowHandle);\n\n        return ::MileXamlContentWindowDefaultMessageLoop();\n    }\n\n    int K7ModernShowXamlDialog(\n        _In_opt_ HWND WindowHandle,\n        _In_ int Width,\n        _In_ int Height,\n        _In_ LPVOID Content,\n        _In_ HWND ParentWindowHandle)\n    {\n        if (!WindowHandle)\n        {\n            return -1;\n        }\n\n        ::MileAllowNonClientDefaultDrawingForWindow(WindowHandle, FALSE);\n\n        HMENU MenuHandle = ::GetSystemMenu(WindowHandle, FALSE);\n        if (MenuHandle)\n        {\n            ::RemoveMenu(MenuHandle, 0, MF_SEPARATOR);\n            ::RemoveMenu(MenuHandle, SC_RESTORE, MF_BYCOMMAND);\n            ::RemoveMenu(MenuHandle, SC_SIZE, MF_BYCOMMAND);\n            ::RemoveMenu(MenuHandle, SC_MINIMIZE, MF_BYCOMMAND);\n            ::RemoveMenu(MenuHandle, SC_MAXIMIZE, MF_BYCOMMAND);\n        }\n\n        if (ParentWindowHandle)\n        {\n            ::EnableWindow(ParentWindowHandle, FALSE);\n        }\n\n        if (FAILED(::MileXamlSetXamlContentForContentWindow(\n            WindowHandle,\n            Content)))\n        {\n            ::DestroyWindow(WindowHandle);\n            return -1;\n        }\n\n        int Result = ::K7ModernShowXamlWindow(\n            WindowHandle,\n            Width,\n            Height,\n            ParentWindowHandle);\n\n        return Result;\n    }\n\n    winrt::DesktopWindowXamlSource K7ModernGetDesktopWindowXamlSource(\n        _In_ HWND WindowHandle)\n    {\n        winrt::DesktopWindowXamlSource XamlSource = nullptr;\n        winrt::copy_from_abi(\n            XamlSource,\n            ::GetPropW(WindowHandle, L\"XamlWindowSource\"));\n        return XamlSource;\n    }\n}\n\nEXTERN_C INT WINAPI K7ModernShowSponsorDialog(\n    _In_opt_ HWND ParentWindowHandle)\n{\n    HWND WindowHandle = ::K7ModernCreateXamlDialog(ParentWindowHandle);\n    if (!WindowHandle)\n    {\n        return -1;\n    }\n\n    using Interface =\n        winrt::NanaZip::Modern::SponsorPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::SponsorPage;\n\n    Interface Window = winrt::make<Implementation>(WindowHandle);\n\n    int Result = ::K7ModernShowXamlDialog(\n        WindowHandle,\n        460,\n        320,\n        winrt::get_abi(Window),\n        ParentWindowHandle);\n\n    return Result;\n}\n\nEXTERN_C INT WINAPI K7ModernShowAboutDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR ExtendedMessage)\n{\n    HWND WindowHandle = ::K7ModernCreateXamlDialog(ParentWindowHandle);\n    if (!WindowHandle)\n    {\n        return -1;\n    }\n\n    using Interface =\n        winrt::NanaZip::Modern::AboutPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::AboutPage;\n\n    Interface Window = winrt::make<Implementation>(\n        WindowHandle,\n        ExtendedMessage);\n\n    int Result = ::K7ModernShowXamlDialog(\n        WindowHandle,\n        480,\n        320,\n        winrt::get_abi(Window),\n        ParentWindowHandle);\n\n    return Result;\n}\n\nEXTERN_C INT WINAPI K7ModernShowInformationDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_opt_ LPCWSTR Content)\n{\n    HWND WindowHandle = ::K7ModernCreateXamlDialog(ParentWindowHandle);\n    if (!WindowHandle)\n    {\n        return -1;\n    }\n\n    using Interface =\n        winrt::NanaZip::Modern::InformationPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::InformationPage;\n\n    Interface Window = winrt::make<Implementation>(\n        WindowHandle,\n        Title,\n        Content);\n\n    int Result = ::K7ModernShowXamlDialog(\n        WindowHandle,\n        560,\n        560,\n        winrt::get_abi(Window),\n        ParentWindowHandle);\n\n    return Result;\n}\n\nEXTERN_C VOID WINAPI K7ModernUpdateProgressWindowStatus(\n    _In_ HWND WindowHandle,\n    _In_ PK7_PROGRESS_WINDOW_STATUS Status)\n{\n    if (!WindowHandle || !Status)\n    {\n        return;\n    }\n\n    winrt::DesktopWindowXamlSource XamlSource =\n        ::K7ModernGetDesktopWindowXamlSource(WindowHandle);\n    if (!XamlSource)\n    {\n        return;\n    }\n\n    using Interface =\n        winrt::NanaZip::Modern::ProgressPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::ProgressPage;\n    Interface InstanceObject = XamlSource.Content().as<Interface>();\n    if (!InstanceObject)\n    {\n        return;\n    }\n    winrt::get_self<Implementation>(InstanceObject)->UpdateStatus(Status);\n}\n\nEXTERN_C VOID WINAPI K7ModernSetProgressWindowPausedMode(\n    _In_ HWND WindowHandle,\n    _In_ BOOL Paused)\n{\n    if (!WindowHandle)\n    {\n        return;\n    }\n\n    winrt::DesktopWindowXamlSource XamlSource =\n        ::K7ModernGetDesktopWindowXamlSource(WindowHandle);\n    if (!XamlSource)\n    {\n        return;\n    }\n\n    using Interface =\n        winrt::NanaZip::Modern::ProgressPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::ProgressPage;\n    Interface InstanceObject = XamlSource.Content().as<Interface>();\n    if (!InstanceObject)\n    {\n        return;\n    }\n    winrt::get_self<Implementation>(InstanceObject)->SetPausedMode(Paused);\n}\n\nEXTERN_C INT WINAPI K7ModernShowProgressWindow(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_ BOOL ShowCompressionInformation,\n    _In_ SUBCLASSPROC WindowSubclassHandler,\n    _In_ LPVOID WindowSubclassContext)\n{\n    HWND WindowHandle = ::K7ModernCreateXamlWindow(\n        ParentWindowHandle,\n        WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,\n        WS_OVERLAPPEDWINDOW);\n    if (!WindowHandle)\n    {\n        return -1;\n    }\n\n    ::MileAllowNonClientDefaultDrawingForWindow(WindowHandle, FALSE);\n\n    using Interface =\n        winrt::NanaZip::Modern::ProgressPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::ProgressPage;\n\n    Interface Window = winrt::make<Implementation>(\n        WindowHandle,\n        Title,\n        ShowCompressionInformation);\n\n    if (FAILED(::MileXamlSetXamlContentForContentWindow(\n        WindowHandle,\n        winrt::get_abi(Window))))\n    {\n        ::DestroyWindow(WindowHandle);\n        return -1;\n    }\n\n    if (WindowSubclassHandler)\n    {\n        if (!::SetWindowSubclass(\n            WindowHandle,\n            WindowSubclassHandler,\n            1,\n            reinterpret_cast<DWORD_PTR>(WindowSubclassContext)))\n        {\n            ::DestroyWindow(WindowHandle);\n            return -1;\n        }\n    }\n\n    int Result = ::K7ModernShowXamlWindow(\n        WindowHandle,\n        600,\n        360,\n        ParentWindowHandle);\n\n    return Result;\n}\n\nEXTERN_C INT WINAPI K7ModernShowCopyLocationDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_opt_ LPCWSTR Subtitle,\n    _In_opt_ LPCWSTR AdditionalInformation,\n    _In_opt_ LPCWSTR InitialPath,\n    _In_ SUBCLASSPROC WindowSubclassHandler,\n    _In_ LPVOID WindowSubclassContext)\n{\n    HWND WindowHandle = ::K7ModernCreateXamlDialog(ParentWindowHandle);\n    if (!WindowHandle)\n    {\n        return -1;\n    }\n\n    using Interface =\n        winrt::NanaZip::Modern::CopyLocationPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::CopyLocationPage;\n\n    Interface Window = winrt::make<Implementation>(\n        WindowHandle,\n        Title,\n        Subtitle,\n        AdditionalInformation,\n        InitialPath);\n\n    if (WindowSubclassHandler)\n    {\n        if (!::SetWindowSubclass(\n            WindowHandle,\n            WindowSubclassHandler,\n            1,\n            reinterpret_cast<DWORD_PTR>(WindowSubclassContext)))\n        {\n            ::DestroyWindow(WindowHandle);\n            return -1;\n        }\n    }\n\n    int Result = ::K7ModernShowXamlDialog(\n        WindowHandle,\n        600,\n        400,\n        winrt::get_abi(Window),\n        ParentWindowHandle);\n\n    return Result;\n}\n\nEXTERN_C LPCWSTR WINAPI K7ModernGetCopyLocationDialogPath(\n    _In_ HWND WindowHandle)\n{\n    if (!WindowHandle)\n    {\n        return nullptr;\n    }\n\n    winrt::DesktopWindowXamlSource XamlSource =\n        ::K7ModernGetDesktopWindowXamlSource(WindowHandle);\n    if (!XamlSource)\n    {\n        return nullptr;\n    }\n\n    using Interface =\n        winrt::NanaZip::Modern::CopyLocationPage;\n    using Implementation =\n        winrt::NanaZip::Modern::implementation::CopyLocationPage;\n    Interface InstanceObject = XamlSource.Content().as<Interface>();\n    if (!InstanceObject)\n    {\n        return nullptr;\n    }\n    return winrt::get_self<Implementation>(InstanceObject)->GetPath();\n}\n"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.def",
    "content": "﻿LIBRARY\n\nEXPORTS\n\nK7ModernGetLegacyStringResource\nK7ModernAvailable\nK7ModernInitialize\nK7ModernUninitialize\nK7ModernShowSponsorDialog\nK7ModernShowAboutDialog\nK7ModernShowInformationDialog\nK7ModernUpdateProgressWindowStatus\nK7ModernSetProgressWindowPausedMode\nK7ModernShowProgressWindow\nK7ModernShowCopyLocationDialog\nK7ModernGetCopyLocationDialogPath\nK7ModernCreateMainWindowToolBarPage"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.h",
    "content": "﻿/*\n * PROJECT:    NanaZip.Modern\n * FILE:       NanaZip.Modern.h\n * PURPOSE:    Definition for NanaZip Modern Experience\n *\n * LICENSE:    The MIT License\n *\n * MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n */\n\n#ifndef NANAZIP_MODERN_EXPERIENCE\n#define NANAZIP_MODERN_EXPERIENCE\n\n#include <Windows.h>\n#include <CommCtrl.h>\n\n/**\n * @brief Get legacy string resource from NanaZip Modern Experience resources.\n * @param ResourceId The legacy string resource ID.\n * @return If the legacy string resource is found, it returns the pointer to the\n *         string. Otherwise, it returns nullptr.\n * @remark This function can be used without calling K7ModernInitialize.\n */\nEXTERN_C LPCWSTR WINAPI K7ModernGetLegacyStringResource(\n    _In_ UINT32 ResourceId);\n\n/**\n * @brief Check whether NanaZip Modern Experience is available.\n * @return If NanaZip Modern Experience is available, it returns TRUE.\n *         Otherwise, it returns FALSE.\n */\nEXTERN_C BOOL WINAPI K7ModernAvailable();\n\n/**\n * @brief Initialize NanaZip Modern Experience.\n * @return If the function succeeds, it returns S_OK. Otherwise, it returns an\n *         HRESULT error code.\n */\nEXTERN_C HRESULT WINAPI K7ModernInitialize();\n\n/**\n * @brief Uninitialize NanaZip Modern Experience.\n * @return If the function succeeds, it returns S_OK. Otherwise, it returns an\n *         HRESULT error code.\n */\nEXTERN_C HRESULT WINAPI K7ModernUninitialize();\n\n/**\n * @brief Show the \"Sponsor NanaZip\" dialog.\n * @param ParentWindowHandle A handle to the owner window of the dialog to be\n *                           created. If this parameter is nullptr, the dialog\n *                           has no owner window.\n * @return The message loop exit code of the dialog.\n */\nEXTERN_C INT WINAPI K7ModernShowSponsorDialog(\n    _In_opt_ HWND ParentWindowHandle);\n\n/**\n * @brief Show the \"About NanaZip\" dialog.\n * @param ParentWindowHandle A handle to the owner window of the dialog to be\n *                           created. If this parameter is nullptr, the dialog\n *                           has no owner window.\n * @param ExtendedMessage The extended message to be displayed. If this\n *                        parameter is nullptr, the extended message is empty.\n * @return The message loop exit code of the dialog.\n */\nEXTERN_C INT WINAPI K7ModernShowAboutDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR ExtendedMessage);\n\n/**\n * @brief Show an information dialog with the specified title and content.\n * @param ParentWindowHandle A handle to the owner window of the dialog to be\n *                           created. If this parameter is nullptr, the dialog\n *                           has no owner window.\n * @param Title The title of the information dialog. If this parameter is\n *              nullptr, the title is empty.\n * @param Content The content of the information dialog. If this parameter is\n *                nullptr, the content is empty.\n * @return The message loop exit code of the dialog.\n */\nEXTERN_C INT WINAPI K7ModernShowInformationDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_opt_ LPCWSTR Content);\n\n/**\n * @brief The progress window status structure.\n */\ntypedef struct _K7_PROGRESS_WINDOW_STATUS\n{\n    /**\n     * @brief If true, the progress is shown in bytes. If false, the progress is\n     *        shown in files.\n     */\n    BOOLEAN BytesProgressMode;\n\n    /**\n     * @brief If true, the operation is compression. If false, the operation is\n     *        extraction.\n     */\n    BOOLEAN CompressionMode;\n\n    /**\n     * @brief If true, there is an error. If false, there is no error.\n     */\n    BOOLEAN HaveError;\n\n    /**\n     * @brief The title of the progress window.\n     */\n    LPCWSTR Title;\n\n    /**\n     * @brief The current file path being processed.\n     */\n    LPCWSTR FilePath;\n\n    /**\n     * @brief The total size of the operation in bytes. If unknown, it is set to\n     *        static_cast<UINT64>(-1).\n     */\n    UINT64 TotalSize;\n\n    /**\n     * @brief The processed size of the operation in bytes.\n     */\n    UINT64 ProcessedSize;\n\n    /**\n     * @brief The number of total files. If unknown, it is set to\n     *        static_cast<UINT64>(-1).\n     */\n    UINT64 TotalFiles;\n\n    /**\n     * @brief The number of processed files.\n     */\n    UINT64 ProcessedFiles;\n\n    /**\n     * @brief The input size in bytes. For compression, it is the original size.\n     *        For extraction, it is the compressed size. If unknown, it is set\n     *        to static_cast<UINT64>(-1).\n     */\n    UINT64 InputSize;\n\n    /**\n     * @brief The output size in bytes. For compression, it is the compressed\n     *        size. For extraction, it is the original size. If unknown, it is\n     *        set to static_cast<UINT64>(-1).\n     */\n    UINT64 OutputSize;\n\n    /**\n     * @brief The status message.\n     */\n    LPCWSTR Status;\n} K7_PROGRESS_WINDOW_STATUS, *PK7_PROGRESS_WINDOW_STATUS;\n\n/**\n * @brief Update the progress window status.\n * @param WindowHandle A handle to the progress window which acquired from the\n *                     window subclass procedure.\n * @param Status The progress window status to be updated.\n * @remark You must call this function only in the window subclass procedure of\n *         the progress window.\n */\nEXTERN_C VOID WINAPI K7ModernUpdateProgressWindowStatus(\n    _In_ HWND WindowHandle,\n    _In_ PK7_PROGRESS_WINDOW_STATUS Status);\n\n/**\n * @brief The WM_COMMAND BN_CLICKED ID for the \"Pause\" button will be sent to\n *        the progress window when the \"Pause\" button is clicked.\n */\n#define K7_PROGRESS_WINDOW_COMMAND_PAUSE 446\n\n/**\n * @brief Set the paused mode of the progress window.\n * @param WindowHandle A handle to the progress window which acquired from the\n *                     window subclass procedure.\n * @param Paused If true, the UI of the progress window will be updated to the\n *               paused mode. If false, the UI of the progress window will be\n *               updated to the normal mode.\n * @remark You must call this function only in the window subclass procedure of\n *         the progress window.\n */\nEXTERN_C VOID WINAPI K7ModernSetProgressWindowPausedMode(\n    _In_ HWND WindowHandle,\n    _In_ BOOL Paused);\n\n/**\n * @brief Show the progress window.\n * @param ParentWindowHandle A handle to the owner window of the dialog to be\n *                           created. If this parameter is nullptr, the dialog\n *                           has no owner window.\n * @param Title The title of the progress window. If this parameter is\n *              nullptr, the title is empty.\n * @param ShowCompressionInformation If true, the progress window will show\n *                                   the packed size and compression ratio.\n *                                   Otherwise, the packed size and compression\n *                                   ratio will be hidden.\n * @param WindowSubclassHandler The window subclass procedure for the progress\n *                              window.\n * @param WindowSubclassContext The context pointer for the window subclass\n *                              procedure.\n * @return The message loop exit code of the dialog.\n */\nEXTERN_C INT WINAPI K7ModernShowProgressWindow(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_ BOOL ShowCompressionInformation,\n    _In_ SUBCLASSPROC WindowSubclassHandler,\n    _In_ LPVOID WindowSubclassContext);\n\n/**\n * @brief The WM_COMMAND BN_CLICKED ID for the \"OK\" button will be sent to\n *        the copy location dialog when the \"OK\" button is clicked.\n */\n#define K7_COPY_LOCATION_DIALOG_RESULT_OK 1\n\n/**\n * @brief Show the copy location dialog window.\n * @param ParentWindowHandle A handle to the owner window of the dialog to be\n *                           created. If this parameter is nullptr, the dialog\n *                           has no owner window.\n * @param Title The title of the copy location dialog window.\n                If this parameter is nullptr, the title is empty.\n * @param Subtitle The subtitle of the copy location dialog window.\n                   If this parameter is nullptr, the subtitle is empty.\n * @param AdditionalInformation The additional information text of\n *                              the copy location dialog window.\n *                              If this parameter is nullptr, the additional\n                                information text is empty.\n * @param InitialPath The initial path set on the copy location dialog.\n * @param WindowSubclassHandler The window subclass procedure for the progress\n *                              window.\n * @param WindowSubclassContext The context pointer for the window subclass\n *                              procedure.\n * @return The message loop exit code of the dialog.\n */\nEXTERN_C INT WINAPI K7ModernShowCopyLocationDialog(\n    _In_opt_ HWND ParentWindowHandle,\n    _In_opt_ LPCWSTR Title,\n    _In_opt_ LPCWSTR Subtitle,\n    _In_opt_ LPCWSTR AdditionalInformation,\n    _In_opt_ LPCWSTR InitialPath,\n    _In_ SUBCLASSPROC WindowSubclassHandler,\n    _In_ LPVOID WindowSubclassContext);\n\n/**\n * @brief Get the path of the copy location dialog.\n * @param WindowHandle A handle to the copy location dialog.\n * @return The path currently set.\n */\nEXTERN_C LPCWSTR WINAPI K7ModernGetCopyLocationDialogPath(\n    _In_ HWND WindowHandle);\n\n/**\n * @brief Create the toolbar control for the main window.\n * @param ParentWindowHandle A handle to the owner window of the control to be\n *                           created. This parameter must be valid.\n * @param MoreMenuHandle A menu handle for the \"More\" menu. This parameter must\n *                       be valid.\n * @return The toolbar control instance pointer.\n */\nEXTERN_C LPVOID WINAPI K7ModernCreateMainWindowToolBarPage(\n    _In_ HWND ParentWindowHandle,\n    _In_ HMENU MoreMenuHandle);\n\n#endif // !NANAZIP_MODERN_EXPERIENCE\n"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n\t<dependency>\n\t\t<dependentAssembly>\n\t\t\t<assemblyIdentity\n\t\t\t\ttype=\"win32\"\n\t\t\t\tname=\"Microsoft.Windows.Common-Controls\"\n\t\t\t\tversion=\"6.0.0.0\"\n\t\t\t\tprocessorArchitecture=\"*\"\n\t\t\t\tpublicKeyToken=\"6595b64144ccf1df\"\n\t\t\t\tlanguage=\"*\"/>\n\t\t</dependentAssembly>\n\t</dependency>\n\t<application xmlns=\"urn:schemas-microsoft-com:asm.v3\">\n\t\t<windowsSettings>\n\t\t\t<dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2</dpiAwareness>\n\t\t</windowsSettings>\n\t</application>\n\t<compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n\t\t<application>\n\t\t\t<maxversiontested Id=\"10.0.19041.0\"/>\n\t\t\t<maxversiontested Id=\"10.0.20348.0\"/>\n\t\t\t<maxversiontested Id=\"10.0.22000.0\"/>\n\t\t\t<supportedOS Id=\"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}\"/>\n\t\t</application>\n\t</compatibility>\n</assembly>\n"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.props",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  PROJECT:    NanaZip\n  FILE:       NanaZip.Modern.props\n  PURPOSE:    MSBuild Properties for NanaZip.Modern\n\n  LICENSE:    The MIT License\n\n  MAINTAINER: MouriNaruto (Kenji.Mouri@outlook.com)\n-->\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup>\n    <IncludePath>$(MSBuildThisFileDirectory);$(IncludePath)</IncludePath>\n  </PropertyGroup>\n  <Target Name=\"NanaZipModernBuildSource\" BeforeTargets=\"BeforeClCompile\">\n    <ItemGroup>\n      <ClCompile Include=\"$(MSBuildThisFileDirectory)NanaZip.Modern.Wrapper.cpp\" />\n    </ItemGroup>\n  </Target>\n  <ItemGroup>\n    <ProjectReference Include=\"$(MSBuildThisFileDirectory)NanaZip.Modern.vcxproj\">\n      <Project>{1AB11057-1F48-44D2-A913-C945BFC1AA93}</Project>\n    </ProjectReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{1AB11057-1F48-44D2-A913-C945BFC1AA93}</ProjectGuid>\n    <RootNamespace>NanaZip.Modern</RootNamespace>\n    <MileProjectType>DynamicLibrary</MileProjectType>\n    <MileProjectManifestFile>NanaZip.Modern.manifest</MileProjectManifestFile>\n    <MinimalCoreWin>false</MinimalCoreWin>\n    <DefaultLanguage>en</DefaultLanguage>\n    <AppContainerApplication>false</AppContainerApplication>\n    <ApplicationType>Windows Store</ApplicationType>\n    <ApplicationTypeRevision>10.0</ApplicationTypeRevision>\n    <XamlComponentResourceLocation>nested</XamlComponentResourceLocation>\n    <WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>\n    <MileUniCrtDisableRuntimeDebuggingFeature>true</MileUniCrtDisableRuntimeDebuggingFeature>\n    <MileProjectEnableCppWinRTSupport>true</MileProjectEnableCppWinRTSupport>\n    <MileProjectUseProjectProperties>true</MileProjectUseProjectProperties>\n    <MileProjectCompanyName>M2-Team</MileProjectCompanyName>\n    <MileProjectFileDescription>NanaZip Modern Experience</MileProjectFileDescription>\n    <MileProjectInternalName>NanaZip.Modern</MileProjectInternalName>\n    <MileProjectLegalCopyright>© M2-Team and Contributors. All rights reserved.</MileProjectLegalCopyright>\n    <MileProjectOriginalFilename>NanaZip.Modern.dll</MileProjectOriginalFilename>\n    <MileProjectProductName>NanaZip</MileProjectProductName>\n  </PropertyGroup>\n  <Import Project=\"..\\NanaZip.Project\\NanaZip.Project.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.x64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Platform.ARM64.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.Default.props\" />\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.props\" />\n  <PropertyGroup>\n    <RequiredBundles>Microsoft.VisualStudio.ComponentGroup.MSIX.Packaging</RequiredBundles>\n  </PropertyGroup>\n  <ItemDefinitionGroup>\n    <Link>\n      <ModuleDefinitionFile>NanaZip.Modern.def</ModuleDefinitionFile>\n      <LargeAddressAware>true</LargeAddressAware>\n      <MinimumRequiredVersion>10.0</MinimumRequiredVersion>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Debug'\">MultiThreadedDebug</RuntimeLibrary>\n      <RuntimeLibrary Condition=\"'$(Configuration)' == 'Release'\">MultiThreaded</RuntimeLibrary>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>WINRT_NO_SOURCE_LOCATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>runtimeobject.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Modern.def\" />\n    <None Include=\"NanaZip.Modern.props\" />\n    <None Include=\"NanaZip.Modern.Wrapper.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Modern.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ApplicationDefinition Include=\"App.xaml\">\n      <SubType>Designer</SubType>\n    </ApplicationDefinition>\n    <Page Include=\"AddressBarTemplate.xaml\" />\n    <Page Include=\"CopyLocationPage.xaml\">\n      <SubType>Designer</SubType>\n    </Page>\n    <Page Include=\"InformationPage.xaml\">\n      <SubType>Designer</SubType>\n    </Page>\n    <Page Include=\"ProgressPage.xaml\">\n      <SubType>Designer</SubType>\n    </Page>\n    <Page Include=\"SponsorPage.xaml\">\n      <SubType>Designer</SubType>\n    </Page>\n    <Page Include=\"AboutPage.xaml\">\n      <SubType>Designer</SubType>\n    </Page>\n    <Page Include=\"MainWindowToolBarPage.xaml\">\n      <SubType>Designer</SubType>\n    </Page>\n    <Page Include=\"StatusBarTemplate.xaml\">\n      <SubType>Designer</SubType>\n    </Page>\n  </ItemGroup>\n  <ItemGroup>\n    <Midl Include=\"AddressBar.idl\" />\n    <Midl Include=\"AddressBarTemplate.idl\">\n      <DependentUpon>AddressBarTemplate.xaml</DependentUpon>\n    </Midl>\n    <Midl Include=\"App.idl\">\n      <DependentUpon>App.xaml</DependentUpon>\n    </Midl>\n    <Midl Include=\"CopyLocationPage.idl\">\n      <DependentUpon>CopyLocationPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </Midl>\n    <Midl Include=\"InformationPage.idl\">\n      <DependentUpon>InformationPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </Midl>\n    <Midl Include=\"ProgressPage.idl\">\n      <DependentUpon>ProgressPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </Midl>\n    <Midl Include=\"SponsorPage.idl\">\n      <DependentUpon>SponsorPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </Midl>\n    <Midl Include=\"AboutPage.idl\">\n      <DependentUpon>AboutPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </Midl>\n    <Midl Include=\"MainWindowToolBarPage.idl\">\n      <DependentUpon>MainWindowToolBarPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </Midl>\n    <Midl Include=\"StatusBar.idl\" />\n    <Midl Include=\"StatusBarTemplate.idl\">\n      <DependentUpon>StatusBarTemplate.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </Midl>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"AddressBar.h\">\n      <DependentUpon>AddressBar.idl</DependentUpon>\n    </ClInclude>\n    <ClInclude Include=\"AddressBarTemplate.h\">\n      <DependentUpon>AddressBarTemplate.xaml</DependentUpon>\n    </ClInclude>\n    <ClInclude Include=\"ControlMacros.h\" />\n    <ClInclude Include=\"CopyLocationPage.h\">\n      <DependentUpon>CopyLocationPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n    <ClInclude Include=\"InformationPage.h\">\n      <DependentUpon>InformationPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n    <ClInclude Include=\"NanaZip.Modern.h\" />\n    <ClInclude Include=\"pch.h\" />\n    <ClInclude Include=\"App.h\">\n      <DependentUpon>App.xaml</DependentUpon>\n    </ClInclude>\n    <ClInclude Include=\"ProgressPage.h\">\n      <DependentUpon>ProgressPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n    <ClInclude Include=\"SponsorPage.h\">\n      <DependentUpon>SponsorPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n    <ClInclude Include=\"AboutPage.h\">\n      <DependentUpon>AboutPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n    <ClInclude Include=\"MainWindowToolBarPage.h\">\n      <DependentUpon>MainWindowToolBarPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n    <ClInclude Include=\"StatusBar.h\">\n      <DependentUpon>StatusBar.idl</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n    <ClInclude Include=\"StatusBarTemplate.h\">\n      <DependentUpon>StatusBarTemplate.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"AddressBarTemplate.cpp\">\n      <DependentUpon>AddressBarTemplate.xaml</DependentUpon>\n    </ClCompile>\n    <ClCompile Include=\"CopyLocationPage.cpp\">\n      <DependentUpon>CopyLocationPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n    <ClCompile Include=\"InformationPage.cpp\">\n      <DependentUpon>InformationPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n    <ClCompile Include=\"pch.cpp\" />\n    <ClCompile Include=\"$(GeneratedFilesDir)module.g.cpp\" />\n    <ClCompile Include=\"App.cpp\">\n      <DependentUpon>App.xaml</DependentUpon>\n    </ClCompile>\n    <ClCompile Include=\"ProgressPage.cpp\">\n      <DependentUpon>ProgressPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n    <ClCompile Include=\"SponsorPage.cpp\">\n      <DependentUpon>SponsorPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n    <ClCompile Include=\"AboutPage.cpp\">\n      <DependentUpon>AboutPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n    <ClCompile Include=\"MainWindowToolBarPage.cpp\">\n      <DependentUpon>MainWindowToolBarPage.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n    <ClCompile Include=\"AddressBar.cpp\">\n      <DependentUpon>AddressBar.idl</DependentUpon>\n    </ClCompile>\n    <ClCompile Include=\"NanaZip.Modern.cpp\" />\n    <ClCompile Include=\"StatusBar.cpp\">\n      <DependentUpon>StatusBar.idl</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n    <ClCompile Include=\"StatusBarTemplate.cpp\">\n      <DependentUpon>StatusBarTemplate.xaml</DependentUpon>\n      <SubType>Code</SubType>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <PackageReference Include=\"Mile.Xaml\">\n      <Version>2.5.1616</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.Helpers\">\n      <Version>1.0.1171</Version>\n    </PackageReference>\n    <PackageReference Include=\"Mile.Windows.UniCrt\">\n      <Version>1.2.410</Version>\n    </PackageReference>\n  </ItemGroup>\n  <ItemGroup>\n    <PRIResource Include=\"Strings\\af\\Common.resw\" />\n    <PRIResource Include=\"Strings\\af\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\af\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ar\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ar\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ar\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\az-arab\\Common.resw\" />\n    <PRIResource Include=\"Strings\\az-arab\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\az-arab\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\be\\Common.resw\" />\n    <PRIResource Include=\"Strings\\be\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\be\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\bg\\Common.resw\" />\n    <PRIResource Include=\"Strings\\bg\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\bg\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\bn\\Common.resw\" />\n    <PRIResource Include=\"Strings\\bn\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\bn\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ca-es-valencia\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ca-es-valencia\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ca-es-valencia\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ca\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ca\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ca\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\cs\\Common.resw\" />\n    <PRIResource Include=\"Strings\\cs\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\cs\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\cy\\Common.resw\" />\n    <PRIResource Include=\"Strings\\cy\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\cy\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\da\\Common.resw\" />\n    <PRIResource Include=\"Strings\\da\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\da\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\de\\Common.resw\" />\n    <PRIResource Include=\"Strings\\de\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\de\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\de\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\de\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\el\\Common.resw\" />\n    <PRIResource Include=\"Strings\\el\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\el\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\el\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\el\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\en\\Common.resw\" />\n    <PRIResource Include=\"Strings\\en\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\en\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\en\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\en\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\eo\\Common.resw\" />\n    <PRIResource Include=\"Strings\\eo\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\eo\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\es\\Common.resw\" />\n    <PRIResource Include=\"Strings\\es\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\es\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\et\\Common.resw\" />\n    <PRIResource Include=\"Strings\\et\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\et\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\eu\\Common.resw\" />\n    <PRIResource Include=\"Strings\\eu\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\eu\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\fa\\Common.resw\" />\n    <PRIResource Include=\"Strings\\fa\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\fa\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\fi\\Common.resw\" />\n    <PRIResource Include=\"Strings\\fi\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\fi\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\fr\\Common.resw\" />\n    <PRIResource Include=\"Strings\\fr\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\fr\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\fy\\Common.resw\" />\n    <PRIResource Include=\"Strings\\fy\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\fy\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ga\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ga\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ga\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\gl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\gl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\gl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\gu\\Common.resw\" />\n    <PRIResource Include=\"Strings\\gu\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\gu\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\he\\Common.resw\" />\n    <PRIResource Include=\"Strings\\he\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\he\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\hi\\Common.resw\" />\n    <PRIResource Include=\"Strings\\hi\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\hi\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\hr\\Common.resw\" />\n    <PRIResource Include=\"Strings\\hr\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\hr\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\hu\\Common.resw\" />\n    <PRIResource Include=\"Strings\\hu\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\hu\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\hu\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\hu\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\hy\\Common.resw\" />\n    <PRIResource Include=\"Strings\\hy\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\hy\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\id\\Common.resw\" />\n    <PRIResource Include=\"Strings\\id\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\id\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\is\\Common.resw\" />\n    <PRIResource Include=\"Strings\\is\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\is\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\it\\Common.resw\" />\n    <PRIResource Include=\"Strings\\it\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\it\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ja\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ja\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ja\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ka\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ka\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ka\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\kk\\Common.resw\" />\n    <PRIResource Include=\"Strings\\kk\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\kk\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ko\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ko\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ko\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ku-arab\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ku-arab\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ku-arab\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ky-kg\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ky-kg\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ky-kg\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\lt\\Common.resw\" />\n    <PRIResource Include=\"Strings\\lt\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\lt\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\lv\\Common.resw\" />\n    <PRIResource Include=\"Strings\\lv\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\lv\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\mk\\Common.resw\" />\n    <PRIResource Include=\"Strings\\mk\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\mk\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\mn-cyrl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\mn-cyrl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\mn-cyrl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\mn-mong\\Common.resw\" />\n    <PRIResource Include=\"Strings\\mn-mong\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\mn-mong\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\mr\\Common.resw\" />\n    <PRIResource Include=\"Strings\\mr\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\mr\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ms\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ms\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ms\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\nb\\Common.resw\" />\n    <PRIResource Include=\"Strings\\nb\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\nb\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ne\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ne\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ne\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\nl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\nl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\nl\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\nl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\nl\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\nn\\Common.resw\" />\n    <PRIResource Include=\"Strings\\nn\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\nn\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\pa-in\\Common.resw\" />\n    <PRIResource Include=\"Strings\\pa-in\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\pa-in\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\pl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\pl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\pl\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\pl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\pl\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\ps\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ps\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ps\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\pt-br\\Common.resw\" />\n    <PRIResource Include=\"Strings\\pt-br\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\pt-br\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\pt-br\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\pt-br\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\pt\\Common.resw\" />\n    <PRIResource Include=\"Strings\\pt\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\pt\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ro\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ro\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ro\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ru\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ru\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ru\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\si\\Common.resw\" />\n    <PRIResource Include=\"Strings\\si\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\si\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\sk\\Common.resw\" />\n    <PRIResource Include=\"Strings\\sk\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\sk\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\sl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\sl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\sl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\sq\\Common.resw\" />\n    <PRIResource Include=\"Strings\\sq\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\sq\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\sq\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\sq\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\sr-cyrl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\sr-cyrl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\sr-cyrl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\sr-Latn\\Common.resw\" />\n    <PRIResource Include=\"Strings\\sr-Latn\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\sr-Latn\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\sv\\Common.resw\" />\n    <PRIResource Include=\"Strings\\sv\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\sv\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\sw\\Common.resw\" />\n    <PRIResource Include=\"Strings\\sw\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\sw\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ta\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ta\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ta\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\tg-arab\\Common.resw\" />\n    <PRIResource Include=\"Strings\\tg-arab\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\tg-arab\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\th\\Common.resw\" />\n    <PRIResource Include=\"Strings\\th\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\th\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\tk-cyrl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\tk-cyrl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\tk-cyrl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\tr\\Common.resw\" />\n    <PRIResource Include=\"Strings\\tr\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\tr\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\tt-arab\\Common.resw\" />\n    <PRIResource Include=\"Strings\\tt-arab\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\tt-arab\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\ug-arab\\Common.resw\" />\n    <PRIResource Include=\"Strings\\ug-arab\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\ug-arab\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\uk\\Common.resw\" />\n    <PRIResource Include=\"Strings\\uk\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\uk\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\uz-cyrl\\Common.resw\" />\n    <PRIResource Include=\"Strings\\uz-cyrl\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\uz-cyrl\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\uz-latn\\Common.resw\" />\n    <PRIResource Include=\"Strings\\uz-latn\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\uz-latn\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\vi\\Common.resw\" />\n    <PRIResource Include=\"Strings\\vi\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\vi\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\yo-latn\\Common.resw\" />\n    <PRIResource Include=\"Strings\\yo-latn\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\yo-latn\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hans\\Common.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hans\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hans\\MainWindowToolBarPage.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hans\\ProgressPage.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hans\\SponsorPage.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hant\\Common.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hant\\CopyLocationPage.resw\" />\n    <PRIResource Include=\"Strings\\zh-Hant\\ProgressPage.resw\" />\n  </ItemGroup>\n  <Import Sdk=\"Mile.Project.Configurations\" Version=\"1.0.1917\" Project=\"Mile.Project.Cpp.targets\" />\n  <!--\n  XamlAddCppWinRTMergedWinmd\n\n  This target is overriden to prevent the XAML compiler from enabling\n  hybrid C++/WinRT and C++/CX support, due to a bug in the check.\n  -->\n  <Target Name=\"XamlAddCppWinRTMergedWinmd\" AfterTargets=\"CppWinRTMergeProjectWinMDInputs\" />\n</Project>"
  },
  {
    "path": "NanaZip.Modern/NanaZip.Modern.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Manifest Include=\"NanaZip.Modern.manifest\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ApplicationDefinition Include=\"App.xaml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"NanaZip.Modern.cpp\" />\n    <ClCompile Include=\"pch.cpp\" />\n    <ClCompile Include=\"$(GeneratedFilesDir)module.g.cpp\" />\n    <ClCompile Include=\"AddressBar.cpp\" />\n    <ClCompile Include=\"StatusBar.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"pch.h\" />\n    <ClInclude Include=\"NanaZip.Modern.h\" />\n    <ClInclude Include=\"AddressBar.h\" />\n    <ClInclude Include=\"StatusBar.h\" />\n    <ClInclude Include=\"ControlMacros.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\"NanaZip.Modern.def\" />\n    <None Include=\"NanaZip.Modern.props\" />\n    <None Include=\"NanaZip.Modern.Wrapper.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Page Include=\"SponsorPage.xaml\" />\n    <Page Include=\"AboutPage.xaml\" />\n    <Page Include=\"MainWindowToolBarPage.xaml\" />\n    <Page Include=\"AddressBarTemplate.xaml\" />\n    <Page Include=\"StatusBarTemplate.xaml\" />\n    <Page Include=\"InformationPage.xaml\" />\n    <Page Include=\"ProgressPage.xaml\" />\n    <Page Include=\"CopyLocationPage.xaml\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Filter Include=\"Strings\">\n      <UniqueIdentifier>{aa892a24-e05a-4d90-ac40-9aca1b82e1ad}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\af\">\n      <UniqueIdentifier>{edd99375-7b97-4036-8d96-1401bc0aca45}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ar\">\n      <UniqueIdentifier>{538fba6b-0783-4ea1-849d-9eecdd844758}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\az-arab\">\n      <UniqueIdentifier>{ed531129-80a3-4384-b7b5-1e58f0aa3114}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\be\">\n      <UniqueIdentifier>{5c8da767-cff7-4259-a714-54d84c7741ec}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\bg\">\n      <UniqueIdentifier>{33a892f2-d69d-446d-9327-65eccee678ef}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\bn\">\n      <UniqueIdentifier>{c0821422-eabb-4568-95ef-1f9bfc927e5f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ca\">\n      <UniqueIdentifier>{26bb310a-8365-4afd-a223-3fd5ac3f343e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ca-es-valencia\">\n      <UniqueIdentifier>{120fb161-fdb6-4554-a671-78ffb6c56c0a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\cs\">\n      <UniqueIdentifier>{3ce65f24-cb8c-4755-b65c-3171899c988f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\cy\">\n      <UniqueIdentifier>{34ce5cac-5379-496f-bf86-d5d64de2499f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\da\">\n      <UniqueIdentifier>{f5adb84b-c36b-4406-ad03-27c1ba208b0c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\en\">\n      <UniqueIdentifier>{c42a7c05-d752-456a-9607-27c7580dcfb5}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\eo\">\n      <UniqueIdentifier>{6f3d9948-1a8b-49c4-8eaf-b0c7c42642d5}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\es\">\n      <UniqueIdentifier>{3514bee6-f92e-44db-8b15-a0f1b0dc822d}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\et\">\n      <UniqueIdentifier>{c2d12fb5-147c-4bbe-8380-6ed3f5f95341}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\eu\">\n      <UniqueIdentifier>{c58db774-9666-4c32-be31-9e24e7403c1d}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\fa\">\n      <UniqueIdentifier>{f1630986-5c14-431b-9c93-c26c3c8854a3}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\fi\">\n      <UniqueIdentifier>{f64a0f64-21e4-41b7-84e6-314dfc2edf5b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\fr\">\n      <UniqueIdentifier>{c07fc345-4037-45c3-83cf-f3b815837b05}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\fy\">\n      <UniqueIdentifier>{63ac4b2c-201e-4d32-8b36-83b8e87ee25a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ga\">\n      <UniqueIdentifier>{e13e6131-3ffc-488b-af93-286570dadd19}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\gl\">\n      <UniqueIdentifier>{df739eb7-3c03-4eea-b368-210db03b2fcb}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\gu\">\n      <UniqueIdentifier>{b0d5ec8d-5ea1-4e3e-b598-5e089cc3207d}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\he\">\n      <UniqueIdentifier>{7da8bc8e-f7fc-474c-9073-90b59294556b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\hi\">\n      <UniqueIdentifier>{30d81d0d-c93f-4103-b7f6-8794c70d472f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\hr\">\n      <UniqueIdentifier>{cb8b43fd-52d6-478b-a29c-009f59d59009}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\hy\">\n      <UniqueIdentifier>{806fa69a-c229-49e2-901a-239884c40f12}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\id\">\n      <UniqueIdentifier>{524d1a37-47ae-4d80-b8f4-27cd898d1807}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\is\">\n      <UniqueIdentifier>{be8ff9cc-68e3-414a-b3c7-cd7539ac0c27}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\it\">\n      <UniqueIdentifier>{784dc26d-196e-45f7-8451-086d1d9af6ac}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ja\">\n      <UniqueIdentifier>{9e8b7e45-2a57-4822-bb4e-24697d47c67b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ka\">\n      <UniqueIdentifier>{efc22f64-524b-4717-bb5a-6761beff795a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\kk\">\n      <UniqueIdentifier>{34719ab7-e169-4974-8470-b9db55a4dd23}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ko\">\n      <UniqueIdentifier>{c2134679-e4dd-4b81-8eea-bb72d0b4adc7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ku-arab\">\n      <UniqueIdentifier>{899d3d7e-15f8-471f-b77c-99c0ae5dbca3}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ky-kg\">\n      <UniqueIdentifier>{3884b76c-008d-4964-82fc-368f1e435b9f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\lt\">\n      <UniqueIdentifier>{7e075061-43ac-4314-885b-2978760f34d2}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\lv\">\n      <UniqueIdentifier>{eca75659-53f6-4267-96b6-f8567e315a00}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\mk\">\n      <UniqueIdentifier>{bc56c123-ed11-4513-9bf3-f8f2dbf86611}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\mn-cyrl\">\n      <UniqueIdentifier>{b4125ce8-bc19-446b-8a42-7725735b1e99}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\mn-mong\">\n      <UniqueIdentifier>{d9698af2-909b-4ec3-8eff-e165857ac1dd}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\mr\">\n      <UniqueIdentifier>{f16d6127-8e92-41ef-8644-fdca4b08109c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ms\">\n      <UniqueIdentifier>{9f6be5b0-1b3f-4dd1-8ead-e0e57fcdd4f3}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\nb\">\n      <UniqueIdentifier>{90581af5-adda-4581-8fa9-4f114de60fa5}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ne\">\n      <UniqueIdentifier>{e18a1fa1-ae0b-4b97-9b68-01212677ca51}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\nl\">\n      <UniqueIdentifier>{c1f5466e-3dd5-43e0-8ac3-d7dccc395b94}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\nn\">\n      <UniqueIdentifier>{b679f28c-933f-456c-a112-bc08741904b1}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\pa-in\">\n      <UniqueIdentifier>{1f1e80cf-247e-490b-91ef-4ef6bf37d071}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ps\">\n      <UniqueIdentifier>{7fc93d6d-35ed-4c96-8913-2a913df1dac2}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\pt\">\n      <UniqueIdentifier>{af053cea-1dc3-470d-b3ec-9767d14bd3b7}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ro\">\n      <UniqueIdentifier>{7e085344-923c-4476-a687-e279e326af71}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ru\">\n      <UniqueIdentifier>{9306af3a-e992-45e7-bc88-6f52b77047d8}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\si\">\n      <UniqueIdentifier>{4b45ad91-56ec-487b-8dcf-7bdbba585b8f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\sk\">\n      <UniqueIdentifier>{6f7665e0-608b-4a4b-b879-d05bdb4c910c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\sl\">\n      <UniqueIdentifier>{356bc72f-912a-405d-b2ea-74e05a7179aa}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\sr-cyrl\">\n      <UniqueIdentifier>{3898ad36-e68e-49bf-bb50-51be866ee208}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\sr-Latn\">\n      <UniqueIdentifier>{164f73cf-f1e2-4ca4-bd5b-7b56f7087281}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\sv\">\n      <UniqueIdentifier>{3b7a6379-5c1a-45b4-9306-7f1718e98ed9}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\sw\">\n      <UniqueIdentifier>{9c2af784-0ed4-49a2-aab0-a9c958f83129}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ta\">\n      <UniqueIdentifier>{f6bec5da-ef6f-469a-9d78-4f1cf54407da}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\tg-arab\">\n      <UniqueIdentifier>{11bb1252-75b7-44f1-bdd5-7940fb4376c6}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\th\">\n      <UniqueIdentifier>{22e9d6e2-0af5-439a-b789-df6d176e22d9}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\tk-cyrl\">\n      <UniqueIdentifier>{53ddd2d1-26ef-415f-9b36-6fa4ef013b1e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\tr\">\n      <UniqueIdentifier>{c67ba671-2378-4556-93e0-c052cfc840bd}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\tt-arab\">\n      <UniqueIdentifier>{6ba62c3d-fb53-4b38-a363-d0800be4c925}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\ug-arab\">\n      <UniqueIdentifier>{b6cc2d9d-8c22-474c-b403-9e60acc6a200}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\uk\">\n      <UniqueIdentifier>{64ea4eaa-1b42-4bf4-9041-390b99669490}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\uz-cyrl\">\n      <UniqueIdentifier>{cb01ab9a-dc2f-4439-9d23-887618055a52}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\uz-latn\">\n      <UniqueIdentifier>{5d553e95-a279-4ba4-a8d1-833f6ed2886c}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\vi\">\n      <UniqueIdentifier>{ee56bd69-9df2-470e-8cee-dd5c4f1e2c04}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\yo-latn\">\n      <UniqueIdentifier>{cee0bdd3-75ca-4e33-9c83-280f303ec9ae}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\zh-Hans\">\n      <UniqueIdentifier>{2585c4e7-3460-4b0e-b06b-3e01537ba4e4}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\pl\">\n      <UniqueIdentifier>{7ac42189-d980-4c72-ae5a-edfb08ebd533}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\sq\">\n      <UniqueIdentifier>{3b88d6dd-0db6-4d35-b45e-5056485106c8}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\hu\">\n      <UniqueIdentifier>{0b024271-0fa4-499f-bb60-b9a1a53b7d27}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\el\">\n      <UniqueIdentifier>{f7a348ee-91df-4a79-97e8-516bcd024f29}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\de\">\n      <UniqueIdentifier>{7c1672d6-0ce4-476d-9c5d-156b8afd248e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\zh-Hant\">\n      <UniqueIdentifier>{bb96e5a9-594e-4e81-842c-c0eaaab8febd}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Strings\\pt-br\">\n      <UniqueIdentifier>{b7cfbca0-080d-4a0f-9279-460e584c279d}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <PRIResource Include=\"Strings\\af\\Common.resw\">\n      <Filter>Strings\\af</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\af\\CopyLocationPage.resw\">\n      <Filter>Strings\\af</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ar\\Common.resw\">\n      <Filter>Strings\\ar</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ar\\CopyLocationPage.resw\">\n      <Filter>Strings\\ar</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\az-arab\\Common.resw\">\n      <Filter>Strings\\az-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\az-arab\\CopyLocationPage.resw\">\n      <Filter>Strings\\az-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\be\\Common.resw\">\n      <Filter>Strings\\be</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\be\\CopyLocationPage.resw\">\n      <Filter>Strings\\be</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\bg\\Common.resw\">\n      <Filter>Strings\\bg</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\bg\\CopyLocationPage.resw\">\n      <Filter>Strings\\bg</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\bn\\Common.resw\">\n      <Filter>Strings\\bn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\bn\\CopyLocationPage.resw\">\n      <Filter>Strings\\bn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ca-es-valencia\\Common.resw\">\n      <Filter>Strings\\ca-es-valencia</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ca-es-valencia\\CopyLocationPage.resw\">\n      <Filter>Strings\\ca-es-valencia</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ca\\Common.resw\">\n      <Filter>Strings\\ca</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ca\\CopyLocationPage.resw\">\n      <Filter>Strings\\ca</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\cs\\Common.resw\">\n      <Filter>Strings\\cs</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\cs\\CopyLocationPage.resw\">\n      <Filter>Strings\\cs</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\cy\\Common.resw\">\n      <Filter>Strings\\cy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\cy\\CopyLocationPage.resw\">\n      <Filter>Strings\\cy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\da\\Common.resw\">\n      <Filter>Strings\\da</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\da\\CopyLocationPage.resw\">\n      <Filter>Strings\\da</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\de\\Common.resw\">\n      <Filter>Strings\\de</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\de\\CopyLocationPage.resw\">\n      <Filter>Strings\\de</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\el\\Common.resw\">\n      <Filter>Strings\\el</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\el\\CopyLocationPage.resw\">\n      <Filter>Strings\\el</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\en\\Common.resw\">\n      <Filter>Strings\\en</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\en\\CopyLocationPage.resw\">\n      <Filter>Strings\\en</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\en\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\en</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\en\\SponsorPage.resw\">\n      <Filter>Strings\\en</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\eo\\Common.resw\">\n      <Filter>Strings\\eo</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\eo\\CopyLocationPage.resw\">\n      <Filter>Strings\\eo</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\es\\Common.resw\">\n      <Filter>Strings\\es</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\es\\CopyLocationPage.resw\">\n      <Filter>Strings\\es</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\et\\Common.resw\">\n      <Filter>Strings\\et</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\et\\CopyLocationPage.resw\">\n      <Filter>Strings\\et</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\eu\\Common.resw\">\n      <Filter>Strings\\eu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\eu\\CopyLocationPage.resw\">\n      <Filter>Strings\\eu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fa\\Common.resw\">\n      <Filter>Strings\\fa</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fa\\CopyLocationPage.resw\">\n      <Filter>Strings\\fa</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fi\\Common.resw\">\n      <Filter>Strings\\fi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fi\\CopyLocationPage.resw\">\n      <Filter>Strings\\fi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fr\\Common.resw\">\n      <Filter>Strings\\fr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fr\\CopyLocationPage.resw\">\n      <Filter>Strings\\fr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fy\\Common.resw\">\n      <Filter>Strings\\fy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fy\\CopyLocationPage.resw\">\n      <Filter>Strings\\fy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ga\\Common.resw\">\n      <Filter>Strings\\ga</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ga\\CopyLocationPage.resw\">\n      <Filter>Strings\\ga</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\gl\\Common.resw\">\n      <Filter>Strings\\gl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\gl\\CopyLocationPage.resw\">\n      <Filter>Strings\\gl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\gu\\Common.resw\">\n      <Filter>Strings\\gu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\gu\\CopyLocationPage.resw\">\n      <Filter>Strings\\gu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\he\\Common.resw\">\n      <Filter>Strings\\he</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\he\\CopyLocationPage.resw\">\n      <Filter>Strings\\he</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hi\\Common.resw\">\n      <Filter>Strings\\hi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hi\\CopyLocationPage.resw\">\n      <Filter>Strings\\hi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hr\\Common.resw\">\n      <Filter>Strings\\hr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hr\\CopyLocationPage.resw\">\n      <Filter>Strings\\hr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hu\\Common.resw\">\n      <Filter>Strings\\hu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hu\\CopyLocationPage.resw\">\n      <Filter>Strings\\hu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hy\\Common.resw\">\n      <Filter>Strings\\hy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hy\\CopyLocationPage.resw\">\n      <Filter>Strings\\hy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\id\\Common.resw\">\n      <Filter>Strings\\id</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\id\\CopyLocationPage.resw\">\n      <Filter>Strings\\id</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\is\\Common.resw\">\n      <Filter>Strings\\is</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\is\\CopyLocationPage.resw\">\n      <Filter>Strings\\is</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\it\\Common.resw\">\n      <Filter>Strings\\it</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\it\\CopyLocationPage.resw\">\n      <Filter>Strings\\it</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ja\\Common.resw\">\n      <Filter>Strings\\ja</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ja\\CopyLocationPage.resw\">\n      <Filter>Strings\\ja</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ka\\Common.resw\">\n      <Filter>Strings\\ka</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ka\\CopyLocationPage.resw\">\n      <Filter>Strings\\ka</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\kk\\Common.resw\">\n      <Filter>Strings\\kk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\kk\\CopyLocationPage.resw\">\n      <Filter>Strings\\kk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ko\\Common.resw\">\n      <Filter>Strings\\ko</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ko\\CopyLocationPage.resw\">\n      <Filter>Strings\\ko</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ku-arab\\Common.resw\">\n      <Filter>Strings\\ku-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ku-arab\\CopyLocationPage.resw\">\n      <Filter>Strings\\ku-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ky-kg\\Common.resw\">\n      <Filter>Strings\\ky-kg</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ky-kg\\CopyLocationPage.resw\">\n      <Filter>Strings\\ky-kg</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\lt\\Common.resw\">\n      <Filter>Strings\\lt</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\lt\\CopyLocationPage.resw\">\n      <Filter>Strings\\lt</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\lv\\Common.resw\">\n      <Filter>Strings\\lv</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\lv\\CopyLocationPage.resw\">\n      <Filter>Strings\\lv</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mk\\Common.resw\">\n      <Filter>Strings\\mk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mk\\CopyLocationPage.resw\">\n      <Filter>Strings\\mk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mn-cyrl\\Common.resw\">\n      <Filter>Strings\\mn-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mn-cyrl\\CopyLocationPage.resw\">\n      <Filter>Strings\\mn-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mn-mong\\Common.resw\">\n      <Filter>Strings\\mn-mong</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mn-mong\\CopyLocationPage.resw\">\n      <Filter>Strings\\mn-mong</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mr\\Common.resw\">\n      <Filter>Strings\\mr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mr\\CopyLocationPage.resw\">\n      <Filter>Strings\\mr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ms\\Common.resw\">\n      <Filter>Strings\\ms</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ms\\CopyLocationPage.resw\">\n      <Filter>Strings\\ms</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nb\\Common.resw\">\n      <Filter>Strings\\nb</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nb\\CopyLocationPage.resw\">\n      <Filter>Strings\\nb</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ne\\Common.resw\">\n      <Filter>Strings\\ne</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ne\\CopyLocationPage.resw\">\n      <Filter>Strings\\ne</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nl\\Common.resw\">\n      <Filter>Strings\\nl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nl\\CopyLocationPage.resw\">\n      <Filter>Strings\\nl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nn\\Common.resw\">\n      <Filter>Strings\\nn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nn\\CopyLocationPage.resw\">\n      <Filter>Strings\\nn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pa-in\\Common.resw\">\n      <Filter>Strings\\pa-in</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pa-in\\CopyLocationPage.resw\">\n      <Filter>Strings\\pa-in</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pl\\Common.resw\">\n      <Filter>Strings\\pl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pl\\CopyLocationPage.resw\">\n      <Filter>Strings\\pl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ps\\Common.resw\">\n      <Filter>Strings\\ps</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ps\\CopyLocationPage.resw\">\n      <Filter>Strings\\ps</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt-br\\Common.resw\">\n      <Filter>Strings\\pt-br</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt-br\\CopyLocationPage.resw\">\n      <Filter>Strings\\pt-br</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt\\Common.resw\">\n      <Filter>Strings\\pt</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt\\CopyLocationPage.resw\">\n      <Filter>Strings\\pt</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ro\\Common.resw\">\n      <Filter>Strings\\ro</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ro\\CopyLocationPage.resw\">\n      <Filter>Strings\\ro</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ru\\Common.resw\">\n      <Filter>Strings\\ru</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ru\\CopyLocationPage.resw\">\n      <Filter>Strings\\ru</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\si\\Common.resw\">\n      <Filter>Strings\\si</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\si\\CopyLocationPage.resw\">\n      <Filter>Strings\\si</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sk\\Common.resw\">\n      <Filter>Strings\\sk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sk\\CopyLocationPage.resw\">\n      <Filter>Strings\\sk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sl\\Common.resw\">\n      <Filter>Strings\\sl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sl\\CopyLocationPage.resw\">\n      <Filter>Strings\\sl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sq\\Common.resw\">\n      <Filter>Strings\\sq</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sq\\CopyLocationPage.resw\">\n      <Filter>Strings\\sq</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sr-cyrl\\Common.resw\">\n      <Filter>Strings\\sr-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sr-cyrl\\CopyLocationPage.resw\">\n      <Filter>Strings\\sr-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sr-Latn\\Common.resw\">\n      <Filter>Strings\\sr-Latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sr-Latn\\CopyLocationPage.resw\">\n      <Filter>Strings\\sr-Latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sv\\Common.resw\">\n      <Filter>Strings\\sv</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sv\\CopyLocationPage.resw\">\n      <Filter>Strings\\sv</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sw\\Common.resw\">\n      <Filter>Strings\\sw</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sw\\CopyLocationPage.resw\">\n      <Filter>Strings\\sw</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ta\\Common.resw\">\n      <Filter>Strings\\ta</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ta\\CopyLocationPage.resw\">\n      <Filter>Strings\\ta</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tg-arab\\Common.resw\">\n      <Filter>Strings\\tg-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tg-arab\\CopyLocationPage.resw\">\n      <Filter>Strings\\tg-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\th\\Common.resw\">\n      <Filter>Strings\\th</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\th\\CopyLocationPage.resw\">\n      <Filter>Strings\\th</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tk-cyrl\\Common.resw\">\n      <Filter>Strings\\tk-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tk-cyrl\\CopyLocationPage.resw\">\n      <Filter>Strings\\tk-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tr\\Common.resw\">\n      <Filter>Strings\\tr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tr\\CopyLocationPage.resw\">\n      <Filter>Strings\\tr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tt-arab\\Common.resw\">\n      <Filter>Strings\\tt-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tt-arab\\CopyLocationPage.resw\">\n      <Filter>Strings\\tt-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ug-arab\\Common.resw\">\n      <Filter>Strings\\ug-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ug-arab\\CopyLocationPage.resw\">\n      <Filter>Strings\\ug-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uk\\Common.resw\">\n      <Filter>Strings\\uk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uk\\CopyLocationPage.resw\">\n      <Filter>Strings\\uk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uz-cyrl\\Common.resw\">\n      <Filter>Strings\\uz-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uz-cyrl\\CopyLocationPage.resw\">\n      <Filter>Strings\\uz-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uz-latn\\Common.resw\">\n      <Filter>Strings\\uz-latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uz-latn\\CopyLocationPage.resw\">\n      <Filter>Strings\\uz-latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\vi\\Common.resw\">\n      <Filter>Strings\\vi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\vi\\CopyLocationPage.resw\">\n      <Filter>Strings\\vi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\yo-latn\\Common.resw\">\n      <Filter>Strings\\yo-latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\yo-latn\\CopyLocationPage.resw\">\n      <Filter>Strings\\yo-latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hans\\Common.resw\">\n      <Filter>Strings\\zh-Hans</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hans\\CopyLocationPage.resw\">\n      <Filter>Strings\\zh-Hans</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hans\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\zh-Hans</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hans\\SponsorPage.resw\">\n      <Filter>Strings\\zh-Hans</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pl\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\pl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pl\\SponsorPage.resw\">\n      <Filter>Strings\\pl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt-br\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\pt-br</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt-br\\SponsorPage.resw\">\n      <Filter>Strings\\pt-br</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sq\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\sq</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sq\\SponsorPage.resw\">\n      <Filter>Strings\\sq</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hu\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\hu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hu\\SponsorPage.resw\">\n      <Filter>Strings\\hu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\el\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\el</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\el\\SponsorPage.resw\">\n      <Filter>Strings\\el</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\de\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\de</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\de\\SponsorPage.resw\">\n      <Filter>Strings\\de</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hant\\Common.resw\">\n      <Filter>Strings\\zh-Hant</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\af\\ProgressPage.resw\">\n      <Filter>Strings\\af</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ar\\ProgressPage.resw\">\n      <Filter>Strings\\ar</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\az-arab\\ProgressPage.resw\">\n      <Filter>Strings\\az-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hant\\CopyLocationPage.resw\">\n      <Filter>Strings\\zh-Hant</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hant\\ProgressPage.resw\">\n      <Filter>Strings\\zh-Hant</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\be\\ProgressPage.resw\">\n      <Filter>Strings\\be</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\bg\\ProgressPage.resw\">\n      <Filter>Strings\\bg</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\bn\\ProgressPage.resw\">\n      <Filter>Strings\\bn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ca\\ProgressPage.resw\">\n      <Filter>Strings\\ca</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ca-es-valencia\\ProgressPage.resw\">\n      <Filter>Strings\\ca-es-valencia</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\cs\\ProgressPage.resw\">\n      <Filter>Strings\\cs</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\cy\\ProgressPage.resw\">\n      <Filter>Strings\\cy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\da\\ProgressPage.resw\">\n      <Filter>Strings\\da</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\de\\ProgressPage.resw\">\n      <Filter>Strings\\de</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\el\\ProgressPage.resw\">\n      <Filter>Strings\\el</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\en\\ProgressPage.resw\">\n      <Filter>Strings\\en</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\eo\\ProgressPage.resw\">\n      <Filter>Strings\\eo</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\es\\ProgressPage.resw\">\n      <Filter>Strings\\es</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\et\\ProgressPage.resw\">\n      <Filter>Strings\\et</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\eu\\ProgressPage.resw\">\n      <Filter>Strings\\eu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fa\\ProgressPage.resw\">\n      <Filter>Strings\\fa</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fi\\ProgressPage.resw\">\n      <Filter>Strings\\fi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fr\\ProgressPage.resw\">\n      <Filter>Strings\\fr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\fy\\ProgressPage.resw\">\n      <Filter>Strings\\fy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ga\\ProgressPage.resw\">\n      <Filter>Strings\\ga</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\gl\\ProgressPage.resw\">\n      <Filter>Strings\\gl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\gu\\ProgressPage.resw\">\n      <Filter>Strings\\gu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\he\\ProgressPage.resw\">\n      <Filter>Strings\\he</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hi\\ProgressPage.resw\">\n      <Filter>Strings\\hi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hr\\ProgressPage.resw\">\n      <Filter>Strings\\hr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hu\\ProgressPage.resw\">\n      <Filter>Strings\\hu</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\hy\\ProgressPage.resw\">\n      <Filter>Strings\\hy</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\id\\ProgressPage.resw\">\n      <Filter>Strings\\id</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\is\\ProgressPage.resw\">\n      <Filter>Strings\\is</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\it\\ProgressPage.resw\">\n      <Filter>Strings\\it</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ja\\ProgressPage.resw\">\n      <Filter>Strings\\ja</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ka\\ProgressPage.resw\">\n      <Filter>Strings\\ka</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\kk\\ProgressPage.resw\">\n      <Filter>Strings\\kk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ko\\ProgressPage.resw\">\n      <Filter>Strings\\ko</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ku-arab\\ProgressPage.resw\">\n      <Filter>Strings\\ku-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ky-kg\\ProgressPage.resw\">\n      <Filter>Strings\\ky-kg</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\lt\\ProgressPage.resw\">\n      <Filter>Strings\\lt</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\lv\\ProgressPage.resw\">\n      <Filter>Strings\\lv</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mk\\ProgressPage.resw\">\n      <Filter>Strings\\mk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mn-cyrl\\ProgressPage.resw\">\n      <Filter>Strings\\mn-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mn-mong\\ProgressPage.resw\">\n      <Filter>Strings\\mn-mong</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\mr\\ProgressPage.resw\">\n      <Filter>Strings\\mr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ms\\ProgressPage.resw\">\n      <Filter>Strings\\ms</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nb\\ProgressPage.resw\">\n      <Filter>Strings\\nb</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ne\\ProgressPage.resw\">\n      <Filter>Strings\\ne</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nl\\ProgressPage.resw\">\n      <Filter>Strings\\nl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nn\\ProgressPage.resw\">\n      <Filter>Strings\\nn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pa-in\\ProgressPage.resw\">\n      <Filter>Strings\\pa-in</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pl\\ProgressPage.resw\">\n      <Filter>Strings\\pl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ps\\ProgressPage.resw\">\n      <Filter>Strings\\ps</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt\\ProgressPage.resw\">\n      <Filter>Strings\\pt</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\pt-br\\ProgressPage.resw\">\n      <Filter>Strings\\pt-br</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ro\\ProgressPage.resw\">\n      <Filter>Strings\\ro</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ru\\ProgressPage.resw\">\n      <Filter>Strings\\ru</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\si\\ProgressPage.resw\">\n      <Filter>Strings\\si</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sk\\ProgressPage.resw\">\n      <Filter>Strings\\sk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sl\\ProgressPage.resw\">\n      <Filter>Strings\\sl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sq\\ProgressPage.resw\">\n      <Filter>Strings\\sq</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sr-cyrl\\ProgressPage.resw\">\n      <Filter>Strings\\sr-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sr-Latn\\ProgressPage.resw\">\n      <Filter>Strings\\sr-Latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sv\\ProgressPage.resw\">\n      <Filter>Strings\\sv</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\sw\\ProgressPage.resw\">\n      <Filter>Strings\\sw</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ta\\ProgressPage.resw\">\n      <Filter>Strings\\ta</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tg-arab\\ProgressPage.resw\">\n      <Filter>Strings\\tg-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\th\\ProgressPage.resw\">\n      <Filter>Strings\\th</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tk-cyrl\\ProgressPage.resw\">\n      <Filter>Strings\\tk-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tr\\ProgressPage.resw\">\n      <Filter>Strings\\tr</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\tt-arab\\ProgressPage.resw\">\n      <Filter>Strings\\tt-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\ug-arab\\ProgressPage.resw\">\n      <Filter>Strings\\ug-arab</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uk\\ProgressPage.resw\">\n      <Filter>Strings\\uk</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uz-cyrl\\ProgressPage.resw\">\n      <Filter>Strings\\uz-cyrl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\uz-latn\\ProgressPage.resw\">\n      <Filter>Strings\\uz-latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\vi\\ProgressPage.resw\">\n      <Filter>Strings\\vi</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\yo-latn\\ProgressPage.resw\">\n      <Filter>Strings\\yo-latn</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\zh-Hans\\ProgressPage.resw\">\n      <Filter>Strings\\zh-Hans</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nl\\SponsorPage.resw\">\n      <Filter>Strings\\nl</Filter>\n    </PRIResource>\n    <PRIResource Include=\"Strings\\nl\\MainWindowToolBarPage.resw\">\n      <Filter>Strings\\nl</Filter>\n    </PRIResource>\n  </ItemGroup>\n  <ItemGroup>\n    <Midl Include=\"AddressBar.idl\" />\n    <Midl Include=\"StatusBar.idl\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NanaZip.Modern/ProgressPage.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"ProgressPage.h\"\n#include \"ProgressPage.g.cpp\"\n\n#include <Mile.Helpers.CppBase.h>\n#include <Mile.Helpers.CppWinRT.h>\n\nnamespace winrt::Mile\n{\n    using namespace ::Mile;\n}\n\n// Defined in SevenZip/CPP/7zip/UI/FileManager/resourceGui.h\n#define IDI_ICON 1\n\nnamespace winrt\n{\n    using Windows::System::DispatcherQueuePriority;\n    using Windows::UI::Xaml::Visibility;\n}\n\nnamespace\n{\n    std::wstring ConvertByteSizeToString(\n        std::uint64_t ByteSize)\n    {\n        const wchar_t* Units[] =\n        {\n            L\"Byte\",\n            L\"Bytes\",\n            L\"KiB\",\n            L\"MiB\",\n            L\"GiB\",\n            L\"TiB\",\n            L\"PiB\",\n            L\"EiB\"\n        };\n        const std::size_t UnitsCount = sizeof(Units) / sizeof(*Units);\n\n        // Output Format:\n        // For ByteSize is 0 or 1: x Byte\n        // For ByteSize is from 2 to 1023: x Bytes\n        // For ByteSize is larger than 1023: x.xx {KiB, MiB, GiB, TiB, PiB, EiB}\n\n        std::size_t UnitIndex = 0;\n        double Result = static_cast<double>(ByteSize);\n\n        if (ByteSize > 1)\n        {\n            for (UnitIndex = 1; UnitIndex < UnitsCount; ++UnitIndex)\n            {\n                if (1024.0 > Result)\n                    break;\n\n                Result /= 1024.0;\n            }\n\n            // Keep two digits after the decimal point.\n            Result = static_cast<std::uint64_t>(Result * 100) / 100.0;\n        }\n\n        return Mile::FormatWideString(\n            (UnitIndex > 1) ? L\"%.2f %s\" : L\"%.0f %s\",\n            Result,\n            Units[UnitIndex]);\n    }\n\n    std::wstring ConvertSecondsToTimeString(\n        std::uint64_t Seconds)\n    {\n        if (static_cast<uint64_t>(-1) == Seconds)\n        {\n            return L\"N/A\";\n        }\n\n        int Hour = static_cast<int>(Seconds / 3600);\n        int Minute = static_cast<int>(Seconds / 60 % 60);\n        int Second = static_cast<int>(Seconds % 60);\n\n        return Mile::FormatWideString(\n            L\"%d:%02d:%02d\",\n            Hour,\n            Minute,\n            Second);\n    }\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    ProgressPage::ProgressPage(\n        _In_opt_ HWND WindowHandle,\n        _In_opt_ LPCWSTR Title,\n        _In_ BOOL ShowCompressionInformation) :\n        m_WindowHandle(WindowHandle),\n        m_Title(Title ? std::wstring(Title) : L\"\"),\n        m_ShowCompressionInformation(ShowCompressionInformation)\n    {\n\n    }\n\n    void ProgressPage::UpdateWindowTitle()\n    {\n        std::wstring Title;\n        if (this->m_Paused)\n        {\n            Title.append(std::wstring(\n                this->m_PausedTitleText.c_str(),\n                this->m_PausedTitleText.size()));\n            Title.push_back(L' ');\n        }\n        if (static_cast<std::uint64_t>(-1) != this->m_PercentageProgress)\n        {\n            Title.append(Mile::FormatWideString(\n                L\"%llu%% \",\n                this->m_PercentageProgress));\n        }\n        if (this->m_BackgroundMode)\n        {\n            Title.append(std::wstring(\n                this->m_BackgroundedTitleText.c_str(),\n                this->m_BackgroundedTitleText.size()));\n            Title.push_back(L' ');\n        }\n        Title.append(this->m_Title);\n\n        ::SetWindowTextW(this->m_WindowHandle, Title.c_str());\n        this->TitleTextBlock().Text(Title);\n    }\n\n    void ProgressPage::UpdateTaskbarProgressState()\n    {\n        if (!this->m_TaskbarList || !this->m_WindowHandleForTaskbar)\n        {\n            return;\n        }\n\n        TBPFLAG ProgressState = TBPF_NOPROGRESS;\n        if (this->m_HaveError)\n        {\n            ProgressState = TBPF_ERROR;\n        }\n        else if (this->m_Paused)\n        {\n            ProgressState = TBPF_PAUSED;\n        }\n        else if (static_cast<std::uint64_t>(-1) != this->m_PercentageProgress)\n        {\n            ProgressState = TBPF_NORMAL;\n        }\n        else\n        {\n            ProgressState = TBPF_INDETERMINATE;\n        }\n\n        this->m_TaskbarList->SetProgressState(\n            this->m_WindowHandleForTaskbar,\n            ProgressState);\n    }\n\n    void ProgressPage::InitializeComponent()\n    {\n        ProgressPageT::InitializeComponent();\n\n        HICON ApplicationIconHandle = reinterpret_cast<HICON>(::LoadImageW(\n            ::GetModuleHandleW(nullptr),\n            MAKEINTRESOURCE(IDI_ICON),\n            IMAGE_ICON,\n            256,\n            256,\n            LR_SHARED));\n        if (ApplicationIconHandle)\n        {\n            ::SendMessageW(\n                this->m_WindowHandle,\n                WM_SETICON,\n                TRUE,\n                reinterpret_cast<LPARAM>(ApplicationIconHandle));\n            ::SendMessageW(\n                this->m_WindowHandle,\n                WM_SETICON,\n                FALSE,\n                reinterpret_cast<LPARAM>(ApplicationIconHandle));\n        }\n\n        this->m_TaskbarList = winrt::try_create_instance<ITaskbarList3>(\n            CLSID_TaskbarList,\n            CLSCTX_INPROC_SERVER);\n        if (this->m_TaskbarList)\n        {\n            if (S_OK != this->m_TaskbarList->HrInit())\n            {\n                this->m_TaskbarList = nullptr;\n            }\n        }\n        this->m_WindowHandleForTaskbar = ::GetAncestor(\n            this->m_WindowHandle,\n            GA_ROOT);\n        this->UpdateTaskbarProgressState();\n\n        this->m_BackgroundButtonText = Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/ProgressPage/BackgroundButtonText\");\n        this->m_ForegroundButtonText = Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/ProgressPage/ForegroundButtonText\");\n        this->m_PauseButtonText = Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/ProgressPage/PauseButtonText\");\n        this->m_ContinueButtonText = Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/ProgressPage/ContinueButtonText\");\n\n        this->m_BackgroundedTitleText = this->m_BackgroundButtonText;\n        this->m_PausedTitleText = Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/ProgressPage/PausedText\");\n\n        this->UpdateWindowTitle();\n\n        this->BackgroundButton().Content(winrt::box_value(\n            this->m_BackgroundButtonText));\n        this->PauseButton().Content(winrt::box_value(\n            this->m_PauseButtonText));\n\n        if (!this->m_ShowCompressionInformation)\n        {\n            this->PackedSizeLabel().Visibility(\n                winrt::Visibility::Collapsed);\n            this->PackedSizeTextBlock().Visibility(\n                winrt::Visibility::Collapsed);\n            this->CompressionRatioLabel().Visibility(\n                winrt::Visibility::Collapsed);\n            this->CompressionRatioTextBlock().Visibility(\n                winrt::Visibility::Collapsed);\n        }\n\n        this->m_PreviousTime = ::MileGetTickCount();\n    }\n\n    void ProgressPage::BackgroundButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        this->m_BackgroundMode = !this->m_BackgroundMode;\n        ::SetPriorityClass(\n            ::GetCurrentProcess(),\n            this->m_BackgroundMode\n            ? IDLE_PRIORITY_CLASS\n            : NORMAL_PRIORITY_CLASS);\n        this->BackgroundButton().Content(winrt::box_value(\n            this->m_BackgroundMode\n            ? this->m_ForegroundButtonText\n            : this->m_BackgroundButtonText));\n        this->UpdateWindowTitle();\n    }\n\n    void ProgressPage::PauseButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(K7_PROGRESS_WINDOW_COMMAND_PAUSE, BN_CLICKED),\n            0);\n    }\n\n    void ProgressPage::CancelButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        ::PostMessageW(\n            this->m_WindowHandle,\n            WM_COMMAND,\n            MAKEWPARAM(IDCANCEL, BN_CLICKED),\n            0);\n    }\n\n    void ProgressPage::UpdateStatus(\n        _In_ PK7_PROGRESS_WINDOW_STATUS StatusRequest)\n    {\n        if (!StatusRequest)\n        {\n            return;\n        }\n\n        std::uint64_t CurrentTime = ::MileGetTickCount();\n\n        bool HaveError = StatusRequest->HaveError;\n        std::wstring Title = StatusRequest->Title\n            ? std::wstring(StatusRequest->Title)\n            : L\"\";\n        std::wstring FilePath = StatusRequest->FilePath\n            ? std::wstring(StatusRequest->FilePath)\n            : L\"\";\n        std::uint64_t TotalSize = StatusRequest->TotalSize;\n        std::uint64_t ProcessedSize = StatusRequest->ProcessedSize;\n        std::uint64_t TotalFiles = StatusRequest->TotalFiles;\n        std::uint64_t ProcessedFiles = StatusRequest->ProcessedFiles;\n        std::uint64_t CompressedSize = StatusRequest->CompressionMode\n            ? StatusRequest->OutputSize\n            : StatusRequest->InputSize;\n        std::uint64_t DecompressedSize = StatusRequest->CompressionMode\n            ? StatusRequest->InputSize\n            : StatusRequest->OutputSize;\n        std::wstring Status = StatusRequest->Status\n            ? std::wstring(StatusRequest->Status)\n            : L\"\";\n\n        std::uint64_t TotalProgress = StatusRequest->BytesProgressMode\n            ? TotalSize\n            : TotalFiles;\n        std::uint64_t ProcessedProgress = StatusRequest->BytesProgressMode\n            ? ProcessedSize\n            : ProcessedFiles;\n\n        std::uint64_t PercentageProgress = static_cast<std::uint64_t>(-1);\n        if (static_cast<std::uint64_t>(-1) != ProcessedProgress &&\n            static_cast<std::uint64_t>(-1) != TotalProgress &&\n            0 != TotalProgress)\n        {\n            PercentageProgress = (ProcessedProgress * 100) / TotalProgress;\n        }\n        else\n        {\n            PercentageProgress = 0;\n        }\n\n        if (HaveError != this->m_HaveError)\n        {\n            this->m_HaveError = HaveError;\n            this->UpdateTaskbarProgressState();\n        }\n\n        {\n            bool NeedUpdateTitle = false;\n\n            if (Title != this->m_Title)\n            {\n                this->m_Title = Title;\n                NeedUpdateTitle = true;\n            }\n\n            if (PercentageProgress != this->m_PercentageProgress)\n            {\n                this->m_PercentageProgress = PercentageProgress;\n                NeedUpdateTitle = true;\n            }\n\n            if (NeedUpdateTitle)\n            {\n                this->UpdateWindowTitle();\n            }\n        }\n\n        if (FilePath != this->m_FilePath)\n        {\n            std::wstring String;\n            std::size_t Index = FilePath.rfind(L'\\\\');\n            if (std::wstring::npos == Index)\n            {\n                String = FilePath;\n            }\n            else\n            {\n                String = FilePath.substr(0, Index + 1);\n                String.append(L\"\\r\\n\");\n                String.append(FilePath.substr(Index + 1));\n            }\n            this->FilePathTextBlock().Text(String);\n            this->m_FilePath = FilePath;\n        }\n\n        if (Status != this->m_Status)\n        {\n            this->StatusTextBlock().Text(Status);\n            this->m_Status = Status;\n        }\n\n        if (TotalProgress != this->m_TotalProgress ||\n            ProcessedProgress != this->m_ProcessedProgress)\n        {\n            if (static_cast<std::uint64_t>(-1) != TotalProgress)\n            {\n                this->ProgressBar().Minimum(0.0);\n                this->ProgressBar().Maximum(\n                    static_cast<double>(TotalProgress));\n                this->ProgressBar().Value(\n                    static_cast<double>(ProcessedProgress));\n\n                this->m_TaskbarList->SetProgressValue(\n                    this->m_WindowHandleForTaskbar,\n                    ProcessedProgress,\n                    TotalProgress);\n            }\n            else\n            {\n                this->ProgressBar().Minimum(0.0);\n                this->ProgressBar().Maximum(1.0);\n                this->ProgressBar().Value(0.0);\n            }\n\n            this->m_TotalProgress = TotalProgress;\n            this->m_ProcessedProgress = ProcessedProgress;\n        }\n\n        {\n            std::uint64_t ElapsedTimeAddition =\n                CurrentTime - this->m_PreviousTime;\n            this->m_ElapsedTime += ElapsedTimeAddition;\n            this->m_PreviousTime = CurrentTime;\n            if (ElapsedTimeAddition)\n            {\n                {\n                    std::wstring String = ::ConvertSecondsToTimeString(\n                        this->m_ElapsedTime / 1000);\n                    this->ElapsedTimeTextBlock().Text(String);\n                }\n\n                if (ProcessedProgress)\n                {\n                    if (static_cast<std::uint64_t>(-1) != TotalProgress)\n                    {\n                        std::uint64_t RemainingTime = 0;\n                        if (ProcessedProgress < TotalProgress)\n                        {\n                            RemainingTime = this->m_ElapsedTime;\n                            RemainingTime *= TotalProgress - ProcessedProgress;\n                            RemainingTime /= ProcessedProgress;\n                        }\n                        std::wstring String = ::ConvertSecondsToTimeString(\n                            RemainingTime / 1000);\n                        this->RemainingTimeTextBlock().Text(String);\n                    }\n                    else\n                    {\n                        this->RemainingTimeTextBlock().Text(L\"\");\n                    }\n                }\n\n                {\n                    std::uint64_t Speed = ProcessedProgress * 1000;\n                    // Avoid division by zero by using 1 as the divisor when\n                    // elapsed time is zero.\n                    Speed /= this->m_ElapsedTime ? this->m_ElapsedTime : 1;\n                    std::wstring String = ::ConvertByteSizeToString(Speed);\n                    String.append(L\"/s\");\n                    this->SpeedTextBlock().Text(String);\n                }\n            }\n        }\n\n        if (TotalFiles != this->m_TotalFiles ||\n            ProcessedFiles != this->m_ProcessedFiles)\n        {\n            std::wstring String = Mile::FormatWideString(\n                L\"%llu / %llu\",\n                ((static_cast<std::uint64_t>(-1) != ProcessedFiles)\n                    ? ProcessedFiles\n                    : 0),\n                ((static_cast<std::uint64_t>(-1) != TotalFiles)\n                    ? TotalFiles\n                    : 0));\n            this->FilesTextBlock().Text(String);\n\n            this->m_TotalFiles = TotalFiles;\n            this->m_ProcessedFiles = ProcessedFiles;\n        }\n\n        if (TotalSize != this->m_TotalSize)\n        {\n            std::wstring String = L\"\";\n            if (static_cast<std::uint64_t>(-1) != TotalSize)\n            {\n                String = ::ConvertByteSizeToString(TotalSize);\n                this->TotalSizeTextBlock().Text(String);\n            }\n            this->m_TotalSize = TotalSize;\n        }\n\n        if (CompressedSize != this->m_CompressedSize ||\n            DecompressedSize != this->m_DecompressedSize)\n        {\n            if (DecompressedSize != this->m_DecompressedSize)\n            {\n                std::wstring String = L\"\";\n                if (static_cast<std::uint64_t>(-1) != DecompressedSize)\n                {\n                    String = ::ConvertByteSizeToString(DecompressedSize);\n                    this->ProcessedSizeTextBlock().Text(String);\n                }\n            }\n\n            if (CompressedSize != this->m_CompressedSize)\n            {\n                std::wstring String = L\"\";\n                if (static_cast<std::uint64_t>(-1) != CompressedSize)\n                {\n                    String = ::ConvertByteSizeToString(CompressedSize);\n                    this->PackedSizeTextBlock().Text(String);\n                }\n            }\n\n            if (static_cast<std::uint64_t>(-1) != CompressedSize &&\n                static_cast<std::uint64_t>(-1) != DecompressedSize &&\n                0 != DecompressedSize)\n            {\n                std::wstring String = Mile::FormatWideString(\n                    L\"%llu %%\",\n                    static_cast<std::uint64_t>(\n                        (CompressedSize * 100) / DecompressedSize));\n                this->CompressionRatioTextBlock().Text(String);\n            }\n\n            this->m_CompressedSize = CompressedSize;\n            this->m_DecompressedSize = DecompressedSize;\n        }\n        else\n        {\n            if (ProcessedSize != this->m_ProcessedSize)\n            {\n                if (static_cast<std::uint64_t>(-1) != ProcessedSize)\n                {\n                    std::wstring String = ::ConvertByteSizeToString(\n                        ProcessedSize);\n                    this->ProcessedSizeTextBlock().Text(String);\n                }\n\n                this->m_ProcessedSize = ProcessedSize;\n            }\n        }\n    }\n\n    void ProgressPage::SetPausedMode(\n        _In_ BOOL Paused)\n    {\n        this->m_Paused = Paused;\n        std::uint64_t CurrentTime = ::MileGetTickCount();\n        if (this->m_Paused)\n        {\n            // When pausing, accumulate the elapsed time until now.\n            this->m_ElapsedTime += CurrentTime - this->m_PreviousTime;\n        }\n        // When resuming, just update the previous time to now without\n        // accumulating elapsed time, because the elapsed time during\n        // pause should not be counted.\n        this->m_PreviousTime = CurrentTime;\n        this->ProgressBar().ShowPaused(this->m_Paused);\n        this->PauseButton().Content(winrt::box_value(\n            this->m_Paused\n            ? this->m_ContinueButtonText\n            : this->m_PauseButtonText));\n        this->UpdateWindowTitle();\n        this->UpdateTaskbarProgressState();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/ProgressPage.h",
    "content": "﻿#pragma once\n\n#include \"ProgressPage.g.h\"\n\n#include <Mile.Helpers.CppWinRT.h>\n#include \"ControlMacros.h\"\n\n#include \"NanaZip.Modern.h\"\n\n#include <ShObjIdl_core.h>\n\nnamespace winrt\n{\n    using Windows::Foundation::IInspectable;\n    using Windows::UI::Xaml::RoutedEventArgs;\n    using Windows::UI::Xaml::RoutedEventHandler;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct ProgressPage : ProgressPageT<ProgressPage>\n    {\n    public:\n\n        ProgressPage(\n            _In_opt_ HWND WindowHandle = nullptr,\n            _In_opt_ LPCWSTR Title = nullptr,\n            _In_ BOOL ShowCompressionInformation = TRUE);\n\n        void UpdateWindowTitle();\n\n        void UpdateTaskbarProgressState();\n\n        void InitializeComponent();\n\n        void BackgroundButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void PauseButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void CancelButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void UpdateStatus(\n            _In_ PK7_PROGRESS_WINDOW_STATUS Status);\n\n        void SetPausedMode(\n            _In_ BOOL Paused);\n\n    private:\n\n        HWND m_WindowHandle;\n        BOOL m_ShowCompressionInformation;\n\n        winrt::com_ptr<ITaskbarList3> m_TaskbarList;\n        HWND m_WindowHandleForTaskbar = nullptr;\n\n        winrt::hstring m_BackgroundButtonText;\n        winrt::hstring m_ForegroundButtonText;\n        winrt::hstring m_PauseButtonText;\n        winrt::hstring m_ContinueButtonText;\n\n        winrt::hstring m_BackgroundedTitleText;\n        winrt::hstring m_PausedTitleText;\n\n        bool m_BackgroundMode = false;\n        bool m_Paused = false;\n        bool m_HaveError = false;\n        std::uint64_t m_PreviousTime = 0;\n        std::uint64_t m_ElapsedTime = 0;\n\n        std::wstring m_Title;\n        std::wstring m_FilePath;\n        std::uint64_t m_TotalSize = static_cast<std::uint64_t>(-1);\n        std::uint64_t m_ProcessedSize = static_cast<std::uint64_t>(-1);\n        std::uint64_t m_TotalFiles = static_cast<std::uint64_t>(-1);\n        std::uint64_t m_ProcessedFiles = static_cast<std::uint64_t>(-1);\n        std::uint64_t m_CompressedSize = static_cast<std::uint64_t>(-1);\n        std::uint64_t m_DecompressedSize = static_cast<std::uint64_t>(-1);\n        std::wstring m_Status;\n\n        std::uint64_t m_TotalProgress = static_cast<std::uint64_t>(-1);\n        std::uint64_t m_ProcessedProgress = static_cast<std::uint64_t>(-1);\n        std::uint64_t m_PercentageProgress = static_cast<std::uint64_t>(-1);\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/ProgressPage.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass ProgressPage : Windows.UI.Xaml.Controls.Page\n    {\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/ProgressPage.xaml",
    "content": "﻿<Page\n  x:Class=\"NanaZip.Modern.ProgressPage\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n  xmlns:local=\"using:NanaZip.Modern\"\n  xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n  mc:Ignorable=\"d\">\n\n  <Grid>\n    <Grid.RowDefinitions>\n      <RowDefinition Height=\"Auto\" />\n      <RowDefinition Height=\"*\" />\n      <RowDefinition Height=\"Auto\" />\n    </Grid.RowDefinitions>\n    <TextBlock\n      x:Name=\"TitleTextBlock\"\n      Margin=\"16,0\"\n      d:Text=\"[Adding]\"\n      FontSize=\"24\"\n      Style=\"{ThemeResource BaseTextBlockStyle}\"\n      TextTrimming=\"CharacterEllipsis\"\n      TextWrapping=\"NoWrap\" />\n    <StackPanel\n      Grid.Row=\"1\"\n      Grid.ColumnSpan=\"2\"\n      Padding=\"16,0,16,16\"\n      Orientation=\"Vertical\">\n      <TextBlock\n        x:Name=\"FilePathTextBlock\"\n        Margin=\"0,4,0,0\"\n        d:Text=\"debian-12.0.0-amd64-netinst.iso\"\n        TextTrimming=\"CharacterEllipsis\"\n        TextWrapping=\"NoWrap\" />\n      <TextBlock\n        x:Name=\"StatusTextBlock\"\n        Margin=\"0,4,0,0\"\n        d:Text=\"Compressing\"\n        TextTrimming=\"CharacterEllipsis\"\n        TextWrapping=\"NoWrap\" />\n      <ProgressBar\n        x:Name=\"ProgressBar\"\n        Margin=\"0,4,0,0\"\n        d:Maximum=\"100\"\n        d:Minimum=\"0\"\n        d:Value=\"30\" />\n\n      <Grid Margin=\"0,24,0,0\" ColumnSpacing=\"32\">\n        <Grid.ColumnDefinitions>\n          <ColumnDefinition Width=\"*\" />\n          <ColumnDefinition Width=\"*\" />\n        </Grid.ColumnDefinitions>\n\n        <Grid Grid.Column=\"0\">\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"*\" />\n            <ColumnDefinition Width=\"Auto\" />\n          </Grid.ColumnDefinitions>\n          <StackPanel Grid.Column=\"0\">\n            <TextBlock\n              x:Uid=\"/NanaZip.Modern/ProgressPage/ElapsedTimeLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Elapsed time]\n            </TextBlock>\n            <TextBlock\n              x:Uid=\"/NanaZip.Modern/ProgressPage/RemainingTimeLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Remaining time]\n            </TextBlock>\n            <TextBlock\n              x:Uid=\"/NanaZip.Modern/ProgressPage/FilesLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Files]\n            </TextBlock>\n          </StackPanel>\n\n          <StackPanel Grid.Column=\"1\" HorizontalAlignment=\"Right\">\n            <TextBlock\n              x:Name=\"ElapsedTimeTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"00:00:08\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n            <TextBlock\n              x:Name=\"RemainingTimeTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"00:01:49\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n            <TextBlock\n              x:Name=\"FilesTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"1/6\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n          </StackPanel>\n        </Grid>\n\n        <Grid Grid.Column=\"1\">\n          <Grid.ColumnDefinitions>\n            <ColumnDefinition Width=\"*\" />\n            <ColumnDefinition Width=\"Auto\" />\n          </Grid.ColumnDefinitions>\n          <StackPanel Grid.Column=\"0\">\n            <TextBlock\n              x:Uid=\"/NanaZip.Modern/ProgressPage/SpeedLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Speed]\n            </TextBlock>\n            <TextBlock\n              x:Uid=\"/NanaZip.Modern/ProgressPage/TotalSizeLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Total size]\n            </TextBlock>\n            <TextBlock\n              x:Uid=\"/NanaZip.Modern/ProgressPage/ProcessedLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Processed]\n            </TextBlock>\n            <TextBlock\n              x:Name=\"PackedSizeLabel\"\n              x:Uid=\"/NanaZip.Modern/ProgressPage/PackedSizeLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Packed Size]\n            </TextBlock>\n            <TextBlock\n              x:Name=\"CompressionRatioLabel\"\n              x:Uid=\"/NanaZip.Modern/ProgressPage/CompressionRatioLabel\"\n              Margin=\"0,4,0,0\"\n              Style=\"{ThemeResource BaseTextBlockStyle}\">\n              [Compression ratio]\n            </TextBlock>\n          </StackPanel>\n\n          <StackPanel Grid.Column=\"1\" HorizontalAlignment=\"Right\">\n            <TextBlock\n              x:Name=\"SpeedTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"30 MB/s\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n            <TextBlock\n              x:Name=\"TotalSizeTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"1886 MB\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n            <TextBlock\n              x:Name=\"ProcessedSizeTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"204 MB\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n            <TextBlock\n              x:Name=\"PackedSizeTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"182 MB\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n            <TextBlock\n              x:Name=\"CompressionRatioTextBlock\"\n              Margin=\"0,4,0,0\"\n              d:Text=\"89%\"\n              HorizontalTextAlignment=\"Right\"\n              Typography.NumeralAlignment=\"Tabular\" />\n          </StackPanel>\n        </Grid>\n      </Grid>\n    </StackPanel>\n    <Grid\n      Grid.Row=\"2\"\n      Background=\"#37C9C9C9\"\n      BorderBrush=\"{ThemeResource CardStrokeColorDefault}\"\n      BorderThickness=\"0,1,0,0\">\n      <StackPanel\n        Grid.Column=\"1\"\n        Padding=\"0,0,12,0\"\n        HorizontalAlignment=\"Right\"\n        Orientation=\"Horizontal\">\n        <Button\n          x:Name=\"BackgroundButton\"\n          Width=\"120\"\n          Margin=\"4,16,4,16\"\n          d:Content=\"[Background]\"\n          Click=\"BackgroundButtonClick\" />\n        <Button\n          x:Name=\"PauseButton\"\n          Width=\"120\"\n          Margin=\"4,16,4,16\"\n          d:Content=\"Pause\"\n          Click=\"PauseButtonClick\" />\n        <Button\n          x:Uid=\"/NanaZip.Modern/Common/CancelButton\"\n          Width=\"120\"\n          Margin=\"4,16,4,16\"\n          Click=\"CancelButtonClick\"\n          Content=\"[Cancel]\" />\n      </StackPanel>\n    </Grid>\n  </Grid>\n</Page>\n"
  },
  {
    "path": "NanaZip.Modern/SponsorPage.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"SponsorPage.h\"\n#if __has_include(\"SponsorPage.g.cpp\")\n#include \"SponsorPage.g.cpp\"\n#endif\n\n#include \"NanaZip.Modern.h\"\n\n#include <Mile.Helpers.CppBase.h>\n#include <Mile.Helpers.CppWinRT.h>\n\nnamespace winrt::Mile\n{\n    using namespace ::Mile;\n}\n\n#include <ShObjIdl_core.h>\n\n#include <winrt/Windows.Services.Store.h>\n\n// Defined in SevenZip/CPP/7zip/UI/FileManager/resourceGui.h\n#define IDI_ICON 1\n\nnamespace winrt\n{\n    using Windows::Services::Store::StoreContext;\n    using Windows::Services::Store::StoreProduct;\n    using Windows::Services::Store::StoreProductQueryResult;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    SponsorPage::SponsorPage(\n        _In_opt_ HWND WindowHandle) :\n        m_WindowHandle(WindowHandle)\n    {\n        winrt::hstring WindowTitle = Mile::WinRT::GetLocalizedString(\n            L\"NanaZip.Modern/SponsorPage/GridTitleTextBlock/Text\");\n        ::SetWindowTextW(this->m_WindowHandle, WindowTitle.c_str());\n\n        HICON ApplicationIconHandle = reinterpret_cast<HICON>(::LoadImageW(\n            ::GetModuleHandleW(nullptr),\n            MAKEINTRESOURCE(IDI_ICON),\n            IMAGE_ICON,\n            256,\n            256,\n            LR_SHARED));\n        if (ApplicationIconHandle)\n        {\n            ::SendMessageW(\n                this->m_WindowHandle,\n                WM_SETICON,\n                TRUE,\n                reinterpret_cast<LPARAM>(ApplicationIconHandle));\n            ::SendMessageW(\n                this->m_WindowHandle,\n                WM_SETICON,\n                FALSE,\n                reinterpret_cast<LPARAM>(ApplicationIconHandle));\n        }\n    }\n\n    void SponsorPage::InitializeComponent()\n    {\n        SponsorPageT::InitializeComponent();\n    }\n\n    void SponsorPage::ContributeButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        SHELLEXECUTEINFOW ExecInfo = {};\n        ExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);\n        ExecInfo.lpVerb = L\"open\";\n        ExecInfo.lpFile =\n            L\"https://github.com/M2Team/NanaZip/\"\n            L\"blob/main/CONTRIBUTING.md\";\n        ExecInfo.nShow = SW_SHOWNORMAL;\n        ::ShellExecuteExW(&ExecInfo);\n    }\n\n    winrt::fire_and_forget SponsorPage::BuySponsorEditionButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        winrt::StoreContext Context = winrt::StoreContext::GetDefault();\n        if (Context)\n        {\n            winrt::check_hresult(\n                Context.as<IInitializeWithWindow>()->Initialize(\n                    this->m_WindowHandle));\n\n            winrt::StoreProductQueryResult ProductQueryResult =\n                co_await Context.GetStoreProductsAsync(\n                    { L\"Durable\" },\n                    { L\"9N9DNPT6D6Z9\" });\n            for (auto Item : ProductQueryResult.Products())\n            {\n                winrt::StoreProduct Product = Item.Value();\n\n                co_await Product.RequestPurchaseAsync();\n            }\n        }\n    }\n\n    void SponsorPage::SponsorEditionPolicyButtonClick(\n        winrt::IInspectable const& sender,\n        winrt::RoutedEventArgs const& e)\n    {\n        UNREFERENCED_PARAMETER(sender);\n        UNREFERENCED_PARAMETER(e);\n\n        SHELLEXECUTEINFOW ExecInfo = {};\n        ExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);\n        ExecInfo.lpVerb = L\"open\";\n        ExecInfo.lpFile =\n            L\"https://github.com/M2Team/NanaZip/\"\n            L\"blob/main/Documents/SponsorEdition.md\";\n        ExecInfo.nShow = SW_SHOWNORMAL;\n        ::ShellExecuteExW(&ExecInfo);\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/SponsorPage.h",
    "content": "﻿#pragma once\n\n#include \"SponsorPage.g.h\"\n\n#include <Windows.h>\n\nnamespace winrt\n{\n    using Windows::Foundation::IInspectable;\n    using Windows::UI::Xaml::RoutedEventArgs;\n}\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct SponsorPage : SponsorPageT<SponsorPage>\n    {\n    public:\n\n        SponsorPage(\n            _In_opt_ HWND WindowHandle = nullptr);\n\n        void InitializeComponent();\n\n        void ContributeButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        winrt::fire_and_forget BuySponsorEditionButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n        void SponsorEditionPolicyButtonClick(\n            winrt::IInspectable const& sender,\n            winrt::RoutedEventArgs const& e);\n\n    private:\n\n        HWND m_WindowHandle;\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/SponsorPage.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass SponsorPage : Windows.UI.Xaml.Controls.Page\n    {\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/SponsorPage.xaml",
    "content": "﻿<Page\n  x:Class=\"NanaZip.Modern.SponsorPage\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n  xmlns:local=\"using:NanaZip.Modern\"\n  xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n  IsTextScaleFactorEnabled=\"False\"\n  mc:Ignorable=\"d\">\n  <Grid>\n    <Grid.RowDefinitions>\n      <RowDefinition Height=\"Auto\" />\n      <RowDefinition Height=\"*\" />\n    </Grid.RowDefinitions>\n\n    <TextBlock\n      x:Uid=\"/NanaZip.Modern/SponsorPage/GridTitleTextBlock\"\n      Margin=\"16,0\"\n      HorizontalAlignment=\"Center\"\n      FontSize=\"24\"\n      FontWeight=\"SemiBold\"\n      Text=\"[Sponsor NanaZip]\" />\n\n    <Grid Grid.Row=\"1\" Padding=\"32,16\">\n      <Grid.RowDefinitions>\n        <RowDefinition Height=\"66\" />\n        <RowDefinition Height=\"3\" />\n        <RowDefinition Height=\"66\" />\n        <RowDefinition Height=\"3\" />\n        <RowDefinition Height=\"66\" />\n      </Grid.RowDefinitions>\n      <Button\n        x:Uid=\"/NanaZip.Modern/SponsorPage/ContributeButton\"\n        Grid.Row=\"0\"\n        HorizontalAlignment=\"Stretch\"\n        VerticalAlignment=\"Stretch\"\n        HorizontalContentAlignment=\"Stretch\"\n        AutomationProperties.Name=\"[Become a contributor of NanaZip]\"\n        Click=\"ContributeButtonClick\">\n        <StackPanel Margin=\"16,0\" Orientation=\"Horizontal\">\n          <SymbolIcon Margin=\"0,0,16,0\" Symbol=\"Link\" />\n          <TextBlock x:Uid=\"/NanaZip.Modern/SponsorPage/ContributeButtonTextBlock\" Text=\"[Become a contributor of NanaZip]\" />\n        </StackPanel>\n      </Button>\n      <Button\n        x:Uid=\"/NanaZip.Modern/SponsorPage/BuySponsorEditionButton\"\n        Grid.Row=\"2\"\n        HorizontalAlignment=\"Stretch\"\n        VerticalAlignment=\"Stretch\"\n        HorizontalContentAlignment=\"Stretch\"\n        AutomationProperties.Name=\"[Buy NanaZip Sponsor Edition]\"\n        Click=\"BuySponsorEditionButtonClick\">\n        <StackPanel Margin=\"16,0\" Orientation=\"Horizontal\">\n          <SymbolIcon Margin=\"0,0,16,0\" Symbol=\"Shop\" />\n          <TextBlock x:Uid=\"/NanaZip.Modern/SponsorPage/BuySponsorEditionButtonTextBlock\" Text=\"[Buy NanaZip Sponsor Edition]\" />\n        </StackPanel>\n      </Button>\n      <Button\n        x:Uid=\"/NanaZip.Modern/SponsorPage/SponsorEditionPolicyButton\"\n        Grid.Row=\"4\"\n        HorizontalAlignment=\"Stretch\"\n        VerticalAlignment=\"Stretch\"\n        HorizontalContentAlignment=\"Stretch\"\n        AutomationProperties.Name=\"[Sponsor Edition Policy]\"\n        Click=\"SponsorEditionPolicyButtonClick\">\n        <StackPanel Margin=\"16,0\" Orientation=\"Horizontal\">\n          <SymbolIcon Margin=\"0,0,16,0\" Symbol=\"Help\" />\n          <TextBlock x:Uid=\"/NanaZip.Modern/SponsorPage/SponsorEditionPolicyButtonTextBlock\" Text=\"[Sponsor Edition Policy]\" />\n        </StackPanel>\n      </Button>\n    </Grid>\n  </Grid>\n</Page>\n"
  },
  {
    "path": "NanaZip.Modern/StatusBar.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"StatusBar.h\"\n#include \"StatusBar.g.cpp\"\n\nusing namespace winrt::NanaZip::Modern::implementation;\n\nDEPENDENCY_PROPERTY_SOURCE_BOX(\n    Text1,\n    winrt::hstring,\n    StatusBar,\n    winrt::NanaZip::Modern::StatusBar\n);\n\nDEPENDENCY_PROPERTY_SOURCE_BOX(\n    Text2,\n    winrt::hstring,\n    StatusBar,\n    winrt::NanaZip::Modern::StatusBar\n);\n\nDEPENDENCY_PROPERTY_SOURCE_BOX(\n    Text3,\n    winrt::hstring,\n    StatusBar,\n    winrt::NanaZip::Modern::StatusBar\n);\n\nDEPENDENCY_PROPERTY_SOURCE_BOX(\n    Text4,\n    winrt::hstring,\n    StatusBar,\n    winrt::NanaZip::Modern::StatusBar\n);\n"
  },
  {
    "path": "NanaZip.Modern/StatusBar.h",
    "content": "﻿#pragma once\n\n#include \"StatusBar.g.h\"\n#include \"ControlMacros.h\"\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct StatusBar : StatusBarT<StatusBar>\n    {\n        StatusBar() = default;\n\n        DEPENDENCY_PROPERTY_HEADER(Text1, winrt::hstring);\n        DEPENDENCY_PROPERTY_HEADER(Text2, winrt::hstring);\n        DEPENDENCY_PROPERTY_HEADER(Text3, winrt::hstring);\n        DEPENDENCY_PROPERTY_HEADER(Text4, winrt::hstring);\n    };\n}\n\nnamespace winrt::NanaZip::Modern::factory_implementation\n{\n    struct StatusBar : StatusBarT<StatusBar, implementation::StatusBar>\n    { };\n}\n"
  },
  {
    "path": "NanaZip.Modern/StatusBar.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    runtimeclass StatusBar : Windows.UI.Xaml.Controls.Control\n    {\n        StatusBar();\n\n        String Text1;\n        String Text2;\n        String Text3;\n        String Text4;\n\n        static Windows.UI.Xaml.DependencyProperty Text1Property{ get; };\n        static Windows.UI.Xaml.DependencyProperty Text2Property{ get; };\n        static Windows.UI.Xaml.DependencyProperty Text3Property{ get; };\n        static Windows.UI.Xaml.DependencyProperty Text4Property{ get; };\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/StatusBarTemplate.cpp",
    "content": "﻿#include \"pch.h\"\n#include \"StatusBarTemplate.h\"\n#include \"StatusBarTemplate.g.cpp\"\n"
  },
  {
    "path": "NanaZip.Modern/StatusBarTemplate.h",
    "content": "﻿#pragma once\n\n#include \"StatusBarTemplate.g.h\"\n\nnamespace winrt::NanaZip::Modern::implementation\n{\n    struct StatusBarTemplate : StatusBarTemplateT<StatusBarTemplate>\n    {\n        StatusBarTemplate()\n        {\n            // Xaml objects should not call InitializeComponent during construction.\n            // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent\n        }\n    };\n}\n\nnamespace winrt::NanaZip::Modern::factory_implementation\n{\n    struct StatusBarTemplate : StatusBarTemplateT<\n        StatusBarTemplate,\n        implementation::StatusBarTemplate>\n    {\n    };\n}\n"
  },
  {
    "path": "NanaZip.Modern/StatusBarTemplate.idl",
    "content": "﻿namespace NanaZip.Modern\n{\n    [default_interface]\n    runtimeclass StatusBarTemplate : Windows.UI.Xaml.ResourceDictionary\n    {\n        StatusBarTemplate();\n    }\n}\n"
  },
  {
    "path": "NanaZip.Modern/StatusBarTemplate.xaml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<ResourceDictionary\n  x:Class=\"NanaZip.Modern.StatusBarTemplate\"\n  xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n  xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n  xmlns:local=\"using:NanaZip.Modern\">\n\n  <Style\n    x:Key=\"StatusBarTextBlockStyle\"\n    BasedOn=\"{StaticResource CaptionTextBlockStyle}\"\n    TargetType=\"TextBlock\">\n    <Setter Property=\"Foreground\" Value=\"{ThemeResource TextFillColorSecondaryBrush}\" />\n    <Setter Property=\"TextTrimming\" Value=\"Clip\" />\n  </Style>\n\n  <Style x:Key=\"SeparatorRectangleStyle\" TargetType=\"Rectangle\">\n    <Setter Property=\"Margin\" Value=\"0,0,8,0\" />\n    <Setter Property=\"Width\" Value=\"1\" />\n    <Setter Property=\"Height\" Value=\"16\" />\n    <Setter Property=\"Fill\" Value=\"{ThemeResource DividerStrokeColorDefaultBrush}\" />\n  </Style>\n\n  <Style x:Key=\"DefaultStatusBarStyle\" TargetType=\"local:StatusBar\">\n    <Setter Property=\"Padding\" Value=\"16,0\" />\n    <Setter Property=\"Template\">\n      <Setter.Value>\n        <ControlTemplate TargetType=\"local:StatusBar\">\n          <Grid\n            Margin=\"{TemplateBinding Margin}\"\n            Padding=\"{TemplateBinding Padding}\"\n            Background=\"{TemplateBinding Background}\">\n            <Grid.ColumnDefinitions>\n              <ColumnDefinition Width=\"220\" />\n              <ColumnDefinition Width=\"Auto\" />\n              <ColumnDefinition Width=\"100\" />\n              <ColumnDefinition Width=\"Auto\" />\n              <ColumnDefinition Width=\"100\" />\n              <ColumnDefinition Width=\"Auto\" />\n              <ColumnDefinition Width=\"*\" />\n            </Grid.ColumnDefinitions>\n            <TextBlock\n              Grid.Column=\"0\"\n              VerticalAlignment=\"Center\"\n              Style=\"{StaticResource StatusBarTextBlockStyle}\"\n              Text=\"{x:Bind Text1, Mode=OneWay}\" />\n            <Rectangle Grid.Column=\"1\" Style=\"{StaticResource SeparatorRectangleStyle}\" />\n            <TextBlock\n              Grid.Column=\"2\"\n              VerticalAlignment=\"Center\"\n              Style=\"{StaticResource StatusBarTextBlockStyle}\"\n              Text=\"{x:Bind Text2, Mode=OneWay}\" />\n            <Rectangle Grid.Column=\"3\" Style=\"{StaticResource SeparatorRectangleStyle}\" />\n            <TextBlock\n              Grid.Column=\"4\"\n              VerticalAlignment=\"Center\"\n              Style=\"{StaticResource StatusBarTextBlockStyle}\"\n              Text=\"{x:Bind Text3, Mode=OneWay}\" />\n            <Rectangle Grid.Column=\"5\" Style=\"{StaticResource SeparatorRectangleStyle}\" />\n            <TextBlock\n              Grid.Column=\"6\"\n              VerticalAlignment=\"Center\"\n              Style=\"{StaticResource StatusBarTextBlockStyle}\"\n              Text=\"{x:Bind Text4, Mode=OneWay}\" />\n          </Grid>\n        </ControlTemplate>\n      </Setter.Value>\n    </Setter>\n  </Style>\n\n  <Style BasedOn=\"{StaticResource DefaultStatusBarStyle}\" TargetType=\"local:StatusBar\" />\n\n</ResourceDictionary>\n"
  },
  {
    "path": "NanaZip.Modern/Strings/af/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Kanselleer</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Afsluit</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/af/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/af/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tydsduur sovêr:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Oorblywende tyd:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Grootte:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Spoed:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Foute:</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Ingepakte grootte</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Agtergrond</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Voorgrond</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Wag</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Gaan voort</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Wagtend</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ar/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>إلغاء الأمر</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>إغلاق</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>حسناً</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ar/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>تحديد مجلد الوجهة</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ar/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>الزمن المنقضي:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>الزمن المتبقي:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>الحجم الكلي:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>السرعة:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>المعالج:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>نسبة الضغط:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>الأخطاء:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>الملفات</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>الحجم المضغوط</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>بالخلفية</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>بالمقدمة</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>إيقاف مؤقت</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>استمرار</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>متوقف مؤقتاً</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/az-arab/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>İmtina</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Bağlamaq</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OLDU</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/az-arab/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Qovluğu göstərin.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/az-arab/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Keçdi:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Qalıb:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Cəmi:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Sürət:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Ölçü:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Sıxılma dərəcəsi:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Xəta:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Fayl</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Sıxılmış</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Arxa planda</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Öndə</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Fasilə</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Davam</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Fasilədə</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/be/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Адмена</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Зачыніць</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/be/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Пакажыце папку.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/be/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Мінула:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Засталося:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Усяго:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Хуткасць:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Памер:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Ступень сціску:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Памылак:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Файлаў</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Сціснуты</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Фонам</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>На пярэдні план</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Паўза</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Працягнуць</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>На паўзе</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/bg/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Отказ</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Затваряне</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/bg/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Избор на целева директория.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/bg/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Изминало време:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Оставащо време:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Размер:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Скорост:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Обработени:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Коефициент на компресия:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Грешки:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Файлове</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Компресиран размер</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Фонов режим</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Нормален режим</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Пауза</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Продължаване</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>В пауза</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/bn/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>বাতিল</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>বন্ধ করা</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>ঠিক আছে</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/bn/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>গন্তব্য ফোল্ডার নির্বাচন.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/bn/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>অতিবাহিত সময়ঃ</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>সময় বাকি আছেঃ</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>আকার:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>গতি:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>বিফলতা :</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>সংকুচিত আকার</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>পটভূমি</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value> সামনে</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>বিরতি</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>চালিয়ে যাওয়া</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>বিরতিতে অবস্থানরত</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ca/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Cancel·la</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Tanca</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>D'acord</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ca/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Seleccioneu la carpeta de destinació:</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ca/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Temps transcorregut:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Temps restant:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Mida:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Taxa:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Processat:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Ràtio de compressió:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Errors:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Fitxers</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Mida comprimit</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Rerefons</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Primer pla</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pausa</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Continua</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pausat</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ca-es-valencia/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Cancel·lar</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Tancar</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Acceptar</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ca-es-valencia/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Seleccioneu carpeta de destinació.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ca-es-valencia/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Temps transcorregut:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Temps restant:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Mida:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Velocitat:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Errors:</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Tamany comprimit</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Segon pla</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Primer pla</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pausa</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Continuar</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Parat</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/cs/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Storno</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Zavřít</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/cs/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Vyberte cílovou složku.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/cs/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Uplynulý čas:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Zbývající čas:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Celková velikost:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Rychlost:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Zpracováno:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Komprimační poměr:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Chyb:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Soubory</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Komprimovaná velikost</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Pozadí</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Popředí</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pozastavit</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Pokračovat</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pozastaveno</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/cy/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Canslo</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Cau</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Iawn</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/cy/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/cy/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Wedi treiglo:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Amser a'r ôl:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Maint:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Cyflymder:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Gwallau:</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Maint wedi'i Cywasgu</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Cefndir</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Blaendir</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pwyllo</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Parhau</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pwyllo</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/da/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Annuller</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Luk</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/da/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Vælg destinationsmappen.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/da/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Forløbet tid:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Resterende tid:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Samlet størrelse:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Hastighed:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Behandlet:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Komprimeringsforhold:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Fejl:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Filer</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Pakket størrelse</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Baggrund</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Forgrund</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pause</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Fortsæt</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Sat på pause</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/de/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Abbrechen</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Schließen</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/de/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Zielordner auswählen</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/de/MainWindowToolBarPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"MoreButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Mehr</value>\n    <comment>More</comment>\n  </data>\n  <data name=\"MoreButton.ToolTipService.ToolTip\" xml:space=\"preserve\">\n    <value>Mehr</value>\n    <comment>More</comment>\n  </data>\n  <data name=\"SponsorButton.AcquireText\" xml:space=\"preserve\">\n    <value>NanaZip unterstützen</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n  <data name=\"SponsorButton.SponsoredText\" xml:space=\"preserve\">\n    <value>Danke für Ihre Unterstützung</value>\n    <comment>Appreciate your sponsorship</comment>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/de/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Verstrichene Zeit:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Verbleibende Zeit:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Gesamtdatenmenge:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Geschwindigkeit:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Verarbeitet:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Kompressionsrate:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Fehler:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Dateien</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Gepackte Größe</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Hintergrund</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Vordergrund</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pause</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Fortsetzen</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pause</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/de/SponsorPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BuySponsorEditionButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>NanaZip Sponsor Edition kaufen</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n  <data name=\"BuySponsorEditionButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>NanaZip Sponsor Edition kaufen</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n  <data name=\"ContributeButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>NanaZip-Mitwirkender werden</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n  <data name=\"ContributeButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>NanaZip-Mitwirkender werden</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n  <data name=\"GridTitleTextBlock.Text\" xml:space=\"preserve\">\n    <value>NanaZip unterstützen</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n  <data name=\"SponsorEditionPolicyButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Sponsor Edition Informationen</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n  <data name=\"SponsorEditionPolicyButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Sponsor Edition Informationen</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/el/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Άκυρο</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Κλείσιμο</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/el/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Επιλέξτε φάκελο προορισμού.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/el/MainWindowToolBarPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"MoreButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Περισσότερα</value>\n    <comment>More</comment>\n  </data>\n  <data name=\"MoreButton.ToolTipService.ToolTip\" xml:space=\"preserve\">\n    <value>Περισσότερα</value>\n    <comment>More</comment>\n  </data>\n  <data name=\"SponsorButton.AcquireText\" xml:space=\"preserve\">\n    <value>Δωρεά στο NanaZip</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n  <data name=\"SponsorButton.SponsoredText\" xml:space=\"preserve\">\n    <value>Εκτιμούμε τη χορηγία σας</value>\n    <comment>Appreciate your sponsorship</comment>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/el/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Διανύθηκε:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Απομένει:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Συνολικό μέγεθος:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Ταχύτητα:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Επεξεργάσθηκαν:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Αναλογία συμπίεσης:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Σφάλματα:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Αρχεία</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Συμπιεσμένο μέγεθος</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Στο παρασκήνιο</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Στο προσκήνιο</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Παύση</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Συνέχεια</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Παύθηκε</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/el/SponsorPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BuySponsorEditionButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Αγοράστε την Έκδοση Χορηγού NanaZip</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n  <data name=\"BuySponsorEditionButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Αγοράστε την Έκδοση Χορηγού NanaZip</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n  <data name=\"ContributeButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Γίνετε συνεισφέρων στο NanaZip</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n  <data name=\"ContributeButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Γίνετε συνεισφέρων στο NanaZip</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n  <data name=\"GridTitleTextBlock.Text\" xml:space=\"preserve\">\n    <value>Δωρεά στο NanaZip</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n  <data name=\"SponsorEditionPolicyButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Πολιτική Έκδοσης Χορηγού</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n  <data name=\"SponsorEditionPolicyButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Πολιτική Έκδοσης Χορηγού</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/en/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Cancel</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Close</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/en/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Select destination folder.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/en/MainWindowToolBarPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"MoreButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>More</value>\n    <comment>More</comment>\n  </data>\n  <data name=\"MoreButton.ToolTipService.ToolTip\" xml:space=\"preserve\">\n    <value>More</value>\n    <comment>More</comment>\n  </data>\n  <data name=\"SponsorButton.AcquireText\" xml:space=\"preserve\">\n    <value>Sponsor NanaZip</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n  <data name=\"SponsorButton.SponsoredText\" xml:space=\"preserve\">\n    <value>Appreciate your sponsorship</value>\n    <comment>Appreciate your sponsorship</comment>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/en/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Elapsed time:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Remaining time:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Total size:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Speed:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Processed:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Compression ratio:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Errors:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Files</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Packed Size</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Background</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Foreground</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pause</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Continue</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Paused</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/en/SponsorPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BuySponsorEditionButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Buy NanaZip Sponsor Edition</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n  <data name=\"BuySponsorEditionButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Buy NanaZip Sponsor Edition</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n  <data name=\"ContributeButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Become a contributor of NanaZip</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n  <data name=\"ContributeButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Become a contributor of NanaZip</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n  <data name=\"GridTitleTextBlock.Text\" xml:space=\"preserve\">\n    <value>Sponsor NanaZip</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n  <data name=\"SponsorEditionPolicyButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Sponsor Edition Policy</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n  <data name=\"SponsorEditionPolicyButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Sponsor Edition Policy</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/eo/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Nuligu</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Fermu</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Bone</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/eo/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/eo/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Pasinta tempo:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Restanta tempo:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Grando:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Rapideco:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Eraroj:</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Enarĥiva grando</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Fono</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Malfono</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Paŭzo</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Daŭrigu</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Paŭzita</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/es/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Cancelar</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Cerrar</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Aceptar</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/es/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Selecciona la carpeta de destino</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/es/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tiempo transcurrido:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tiempo pendiente:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Tamaño:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Velocidad:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Procesado:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Razón de compresión:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Errores:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Ficheros</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Tamaño comprimido</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Segundo plano</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Primer plano</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pausa</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Continuar</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pausado</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/et/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Loobu</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Sulge</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/et/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Valige sihtkaust.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/et/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Kulunud aeg:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Järelejäänud aeg:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Kogumaht:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Kiirus:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Töödeldud:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Tihendussuhe:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Vigu:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Faile</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Maht tihendatult</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Taustal</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Esiplaanile</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Paus</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Jätka</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pausiks peatatud</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/eu/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Ezeztatu</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Itxi</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Ongi</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/eu/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Hautatu helmuga agiritegia.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/eu/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Igarotako denbora:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Gelditzen den denbora:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Neurria guztira:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Abiadura:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Prozesatuta:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Konpresio maila:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Akatsak:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Agiriak</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Pakete Neurria</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Barrenean</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Gainean</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pausatu</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Jarraitu</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pausatuta</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fa/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>لغو</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>بستن</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>تایید</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fa/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>پوشه مقصد را انتخاب كنيد</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fa/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>زمان سپری شده:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>زمان باقیمانده:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>مجموع حجم:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>سرعت:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>پردازش شده:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>نسبت فشرده سازی:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>خطاها:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>پرونده‌ها</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>حجم فشرده شده</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>پس زمینه</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>پیش زمینه</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>وقفه</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>ادامه</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>متوقف</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fi/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Peruuta</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Sulje</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fi/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Valitse kohdekansio.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fi/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Aikaa kulunut:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Aikaa jäljellä:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Koko:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Nopeus:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Käsitelty:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Pakkaussuhde:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Virheitä:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Tiedostoja</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Pakattu koko</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Aja taustalla</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Aja edustalla</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Tauko</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Jatka</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Tauolla</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fr/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Annuler</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Fermer</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fr/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Sélectionnez le dossier de destination.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fr/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Temps écoulé :</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Temps restant :</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Taille totale :</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Vitesse :</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Traité :</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Taux de compression :</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Erreurs :</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Fichiers</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Compressé</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Arrière-plan</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Premier plan</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pause</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Continuer</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>En pause</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fy/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Ofbrekke</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Slute</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Okee</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fy/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Bestimmingsmap selektearje.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/fy/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Ferstrutsen tiid:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tiid noch te gean:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Totale grutte:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Fluggens:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Ferwurke:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Kompresje nivo:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Flaters:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Triemmen</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Ynpakte grutte</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Eftergrûn</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Foargrûn</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Skoftsje</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Ferfetsje</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Skoft</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ga/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Cealaigh</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Dún</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Tá go maith</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ga/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Roghnaigh an spriocfhillteán.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ga/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Am caite:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Am fágtha:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Méid iomlán:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Luas:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Déanta:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Luas an chomhbhrúite:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Botúin:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Comhaid</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Comhbhrúite</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Cúlra</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Tulra</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Cuir ar sos</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Lean ar aghaidh</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Ar sos</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/gl/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Cancelar</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Pechar</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>De acordo</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/gl/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Seleccione cartafol destino.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/gl/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tempo transcorrido:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tempo restante:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Tamaño total:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Velocidade:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Procesado:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Proporción de compresión:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Erros:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Ficheiros</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Tamaño comprimido</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Poñer por debaixo</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Traer ao fronte</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pausa</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Continuar</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pausado</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/gu/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>રદ્દ</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>બંદ કરો</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>સારું</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/gu/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>ગન્તવ્ય ફોલ્ડર ચયનિત કરો.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/gu/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>વ્યતીત સમય:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>શેષ બચેલું સમય:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>કુલ આકાર:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>ગતિ:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>પ્રક્રિયા કરેલું:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>દબાવાનું(આકાર છોટા કરવાનું)અનુપાત:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>ત્રુટિયાઁ:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>ફાઇલ્સ</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>કુલ આકાર</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>પૄષ્ઠ્ભૂમિ</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>અગ્રભૂમિ(ડેસ્ક્ટોપ)</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>વિશ્રામ</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>જારી રાખો</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>થોભેલું</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/he/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>בטל</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>סגור</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>אשר</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/he/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>.בחר תיקיית יעד</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/he/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>זמן שחלף:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>זמן שנותר:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>גודל כולל:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>מהירות:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>עובד:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>יחס דחיסה:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>שגיאות:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>קבצים</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>גודל ארוז</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>רקע</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>קידמה</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>השהה</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>המשך</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>מושהה</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hi/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>रद्द</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>बंद करो</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>ठीक है</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hi/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>गन्तव्य फोल्डर चयनित करें.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hi/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>व्यतीत समय:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>बाकी बचा समय:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>कुल आकार:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>गति:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>प्रक्रिया किया हुआ:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>दबाने(आकार छोटा करने) का अनुपात:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>त्रुटियाँ:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>फाइल्स</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>कुल आकार</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>पॄष्ठ्भूमि</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>अग्रभूमि(डेस्क्टोप)</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>विश्राम</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>जारी रखे</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>विश्रामित</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hr/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Odustani</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Zatvori</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>U redu</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hr/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Odabir odredišne mape.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hr/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Utrošeno vrijeme:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Preostalo vrijeme:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Veličina:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Brzina:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Obrađeno:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Omjer kompresije:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Greške:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Datoteke</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Sažeta veličina</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>U pozadini</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>U prvom planu</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pauza</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Nastavi</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pauzirano</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hu/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Mégsem</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Bezárás</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hu/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Válassza ki a cél mappát.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hu/MainWindowToolBarPage.resw",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n\t<!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n\t<xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n\t\t<xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n\t\t<xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n\t\t\t<xsd:complexType>\n\t\t\t\t<xsd:choice maxOccurs=\"unbounded\">\n\t\t\t\t\t<xsd:element name=\"metadata\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:sequence>\n\t\t\t\t\t\t\t\t<xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n\t\t\t\t\t\t\t</xsd:sequence>\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"type\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute ref=\"xml:space\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t\t<xsd:element name=\"assembly\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:attribute name=\"alias\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" type=\"xsd:string\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t\t<xsd:element name=\"data\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:sequence>\n\t\t\t\t\t\t\t\t<xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n\t\t\t\t\t\t\t\t<xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n\t\t\t\t\t\t\t</xsd:sequence>\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n\t\t\t\t\t\t\t<xsd:attribute ref=\"xml:space\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t\t<xsd:element name=\"resheader\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:sequence>\n\t\t\t\t\t\t\t\t<xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n\t\t\t\t\t\t\t</xsd:sequence>\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t</xsd:choice>\n\t\t\t</xsd:complexType>\n\t\t</xsd:element>\n\t</xsd:schema>\n\t<resheader name=\"resmimetype\">\n\t\t<value>text/microsoft-resx</value>\n\t</resheader>\n\t<resheader name=\"version\">\n\t\t<value>2.0</value>\n\t</resheader>\n\t<resheader name=\"reader\">\n\t\t<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n\t</resheader>\n\t<resheader name=\"writer\">\n\t\t<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n\t</resheader>\n\t<data name=\"MoreButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Továbbiak</value>\n    <comment>More</comment>\n  </data>\n\t<data name=\"MoreButton.ToolTipService.ToolTip\" xml:space=\"preserve\">\n    <value>Továbbiak</value>\n    <comment>More</comment>\n  </data>\n\t<data name=\"SponsorButton.AcquireText\" xml:space=\"preserve\">\n    <value>NanaZip támogatása</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n\t<data name=\"SponsorButton.SponsoredText\" xml:space=\"preserve\">\n    <value>Értékeljük szponzorálását</value>\n    <comment>Appreciate your sponsorship</comment>\n  </data>\n</root>\n"
  },
  {
    "path": "NanaZip.Modern/Strings/hu/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Eltelt idő:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Hátralévő idő:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Méret:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Sebesség:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Feldolgozott:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Tömörítési arány:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Hibák:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Fájlok</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Tömörített méret</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Háttérben</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Előtérben</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Szünet</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Folytatás</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Szünet</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hu/SponsorPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n\t<!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n\t<xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n\t\t<xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n\t\t<xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n\t\t\t<xsd:complexType>\n\t\t\t\t<xsd:choice maxOccurs=\"unbounded\">\n\t\t\t\t\t<xsd:element name=\"metadata\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:sequence>\n\t\t\t\t\t\t\t\t<xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n\t\t\t\t\t\t\t</xsd:sequence>\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"type\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute ref=\"xml:space\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t\t<xsd:element name=\"assembly\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:attribute name=\"alias\" type=\"xsd:string\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" type=\"xsd:string\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t\t<xsd:element name=\"data\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:sequence>\n\t\t\t\t\t\t\t\t<xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n\t\t\t\t\t\t\t\t<xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n\t\t\t\t\t\t\t</xsd:sequence>\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n\t\t\t\t\t\t\t<xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n\t\t\t\t\t\t\t<xsd:attribute ref=\"xml:space\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t\t<xsd:element name=\"resheader\">\n\t\t\t\t\t\t<xsd:complexType>\n\t\t\t\t\t\t\t<xsd:sequence>\n\t\t\t\t\t\t\t\t<xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n\t\t\t\t\t\t\t</xsd:sequence>\n\t\t\t\t\t\t\t<xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n\t\t\t\t\t\t</xsd:complexType>\n\t\t\t\t\t</xsd:element>\n\t\t\t\t</xsd:choice>\n\t\t\t</xsd:complexType>\n\t\t</xsd:element>\n\t</xsd:schema>\n\t<resheader name=\"resmimetype\">\n\t\t<value>text/microsoft-resx</value>\n\t</resheader>\n\t<resheader name=\"version\">\n\t\t<value>2.0</value>\n\t</resheader>\n\t<resheader name=\"reader\">\n\t\t<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n\t</resheader>\n\t<resheader name=\"writer\">\n\t\t<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n\t</resheader>\n\t<data name=\"BuySponsorEditionButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Vásároljon NanaZip támogatói kiadást</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n\t<data name=\"BuySponsorEditionButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Vásároljon NanaZip támogatói kiadást</value>\n    <comment>Buy NanaZip Sponsor Edition</comment>\n  </data>\n\t<data name=\"ContributeButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Legyen a NanaZip közreműködője</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n\t<data name=\"ContributeButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Legyen a NanaZip közreműködője</value>\n    <comment>Become a contributor of NanaZip</comment>\n  </data>\n\t<data name=\"GridTitleTextBlock.Text\" xml:space=\"preserve\">\n    <value>NanaZip támogatása</value>\n    <comment>Sponsor NanaZip</comment>\n  </data>\n\t<data name=\"SponsorEditionPolicyButton.AutomationProperties.Name\" xml:space=\"preserve\">\n    <value>Támogatói kiadásra vonatkozó szabályzat</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n\t<data name=\"SponsorEditionPolicyButtonTextBlock.Text\" xml:space=\"preserve\">\n    <value>Támogatói kiadásra vonatkozó szabályzat</value>\n    <comment>Sponsor Edition Policy</comment>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hy/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Չեղարկել</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Փակել</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>ԼԱՎ</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hy/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Ընտրել թղթապանակ</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/hy/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Անցել է.</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Մնացել է.</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Չափ.</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Արագություն.</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Ընթացք.</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Սեղմելու աստիճան</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Սխալներ.</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Ֆայլեր</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Սեղմած</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Խորապատկերում</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Առջևում</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Դադար</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Շարունակել</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Դադարի մեջ է</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/id/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Batal</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Tutup</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Oke</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/id/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Pilih direktori tujuan.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/id/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Waktu terpakai:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Sisa waktu:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Jumlah ukuran:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Kecepatan:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Terproses:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Rasio mampat:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Galat:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Berkas</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Ukuran dipak</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Latar Belakang</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Latar Depan</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Jeda</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Lanjut</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Dijeda</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/is/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Hætta við</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Loka</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Í lagi</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/is/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Veldu móttökumöppu.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/is/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Liðinn tími:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tími eftir:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Heildarstærð:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Hraði:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Meðhöndlað:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Þjöppunarhlutfall:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Villur:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Skrár</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Þjöppuð stærð</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Bakgrunnur</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Forgrunnur</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Gera hlé</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Halda áfram</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Í hléi</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/it/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Annulla</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Chiudi</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/it/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Selezionare la cartella di destinazione.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/it/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tempo trascorso:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Tempo rimanente:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Dimensione totale:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Velocità:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Elaborato:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Rapporto compressione:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Errori:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>File</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Dimensione compressa</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>In background</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>In primo piano</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pausa</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Continua</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>In pausa</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ja/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>キャンセル</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>閉じる(C)</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ja/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>対象のフォルダーを選択してください。</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ja/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>経過時間:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>残り時間:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>合計サイズ:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>速度:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>処理済み:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>圧縮率:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>エラー:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>ファイル数</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>格納サイズ</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>バックグラウンド(B)</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>フォアグラウンド(F)</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>一時停止(P)</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>続行(C)</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>一時停止</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ka/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>გაუქმება</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>დახურვა</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ka/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>აირჩიეთ დანიშნულების საქაღალდე.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ka/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>გასული დრო:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>დარჩენილი დრო:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>ჯამური ზომა:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>სიჩქარე:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>დამუშავებული:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>შეკუმშვის დონე:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>შეცდომა:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>ფაილები</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>შეკუმშულის ზომა</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>ფონურად</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>წინა პლანზე</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>შეჩერება</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>გაგრძელება</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>&amp;შეჩერებული</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/kk/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Болдырмау</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Жабу</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Жарайды</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/kk/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Қалтаны нұсқаңыз</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/kk/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Өтті:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Қалды:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Барлығы:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Жылд.:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Көлем:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Сығу дәрежесі:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Қате:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Файл</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Сығылған</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Фонды</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Алдыңғы жоспарға</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Үізілс</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Жалғастыру</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Үзілісте</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ko/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>경과 시간:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>남은 시간:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>전체 크기:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>속도:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>처리됨:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>압축 효율:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>오류:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>파일</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>압축된 크기</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>낮은 순위로(B)</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>우선 순위로(F)</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>일시정지(P)</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>계속(C)</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>일시정지 됨</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ku-arab/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>پاشگەزبوونەوە</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>داخستن</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>باشە</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ku-arab/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>بوخچەی مەبەست دیاری بکە.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ku-arab/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>ک. دەستپێکردوو:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>کاتی ماوە:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>سەرجەمی قەبارە:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>خێرایی:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>جێبەجێکراوە:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>ڕێژەی پەستاندن:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>هەڵەکان:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>پەڕگەکان</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>قەبارەی پێچراو</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>پاشەبنەما</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>پێشەبنەما</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>ڕاگرتن</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>بەردەوامبوون</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>ڕاگیردرا</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ky-kg/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Айнуу</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Жабуу</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ky-kg/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Баштыкты көрсөтүңүз.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/ky-kg/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Өттү:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Калды:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Баары:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Ылдамдык:</value>\n  </data>\n  <data name=\"ProcessedLabel.Text\" xml:space=\"preserve\">\n    <value>Көлөм:</value>\n  </data>\n  <data name=\"CompressionRatioLabel.Text\" xml:space=\"preserve\">\n    <value>Кысуунун даражасы:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Каталар:</value>\n  </data>\n  <data name=\"FilesLabel.Text\" xml:space=\"preserve\">\n    <value>Файлдар</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Кысылган</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Фоном</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Алдыңкы планга</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Тыныгуу</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Улантуу</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Тыныгууда</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/lt/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"SelectDestinationText\" xml:space=\"preserve\">\n    <value>Pasirinkite paskirties aplanką.</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/lv/Common.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"CancelButton.Content\" xml:space=\"preserve\">\n    <value>Atcelt</value>\n  </data>\n  <data name=\"CloseButton.Content\" xml:space=\"preserve\">\n    <value>Aizvērt</value>\n  </data>\n  <data name=\"OKButton.Content\" xml:space=\"preserve\">\n    <value>Labi</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/lv/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/lv/ProgressPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"ElapsedTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Pagājušais laiks:</value>\n  </data>\n  <data name=\"RemainingTimeLabel.Text\" xml:space=\"preserve\">\n    <value>Atlikušais laiks:</value>\n  </data>\n  <data name=\"TotalSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Lielums:</value>\n  </data>\n  <data name=\"SpeedLabel.Text\" xml:space=\"preserve\">\n    <value>Ātrums:</value>\n  </data>\n  <data name=\"ErrorsLabel.Text\" xml:space=\"preserve\">\n    <value>Kļūdas:</value>\n  </data>\n  <data name=\"PackedSizeLabel.Text\" xml:space=\"preserve\">\n    <value>Saspiests</value>\n  </data>\n  <data name=\"BackgroundButtonText\" xml:space=\"preserve\">\n    <value>Fonā</value>\n  </data>\n  <data name=\"ForegroundButtonText\" xml:space=\"preserve\">\n    <value>Priekšplānā</value>\n  </data>\n  <data name=\"PauseButtonText\" xml:space=\"preserve\">\n    <value>Pauze</value>\n  </data>\n  <data name=\"ContinueButtonText\" xml:space=\"preserve\">\n    <value>Turpināt</value>\n  </data>\n  <data name=\"PausedText\" xml:space=\"preserve\">\n    <value>Pauzēts</value>\n  </data>\n</root>"
  },
  {
    "path": "NanaZip.Modern/Strings/mk/CopyLocationPage.resw",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>1.3</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n</root>"
  }
]